summaryrefslogtreecommitdiff
path: root/gdb
diff options
context:
space:
mode:
Diffstat (limited to 'gdb')
-rw-r--r--gdb/29k-share/README9
-rw-r--r--gdb/29k-share/udi/udi2go32.c607
-rw-r--r--gdb/29k-share/udi/udiids.h48
-rw-r--r--gdb/29k-share/udi/udip2soc.c1250
-rw-r--r--gdb/29k-share/udi/udiphcfg.h44
-rw-r--r--gdb/29k-share/udi/udiphunix.h81
-rw-r--r--gdb/29k-share/udi/udiproc.h308
-rw-r--r--gdb/29k-share/udi/udipt29k.h87
-rw-r--r--gdb/29k-share/udi/udiptcfg.h19
-rw-r--r--gdb/29k-share/udi/udisoc.h184
-rw-r--r--gdb/29k-share/udi/udr.c427
-rw-r--r--gdb/29k-share/udi_soc9
-rw-r--r--gdb/COPYING340
-rw-r--r--gdb/ChangeLog1116
-rw-r--r--gdb/ChangeLog-3.x4838
-rw-r--r--gdb/ChangeLog-90918322
-rw-r--r--gdb/ChangeLog-926285
-rw-r--r--gdb/ChangeLog-937597
-rw-r--r--gdb/ChangeLog-945705
-rw-r--r--gdb/ChangeLog-954915
-rw-r--r--gdb/ChangeLog-965116
-rw-r--r--gdb/ChangeLog-972855
-rw-r--r--gdb/ChangeLog-987122
-rw-r--r--gdb/Makefile.in1619
-rw-r--r--gdb/NEWS1611
-rw-r--r--gdb/README618
-rw-r--r--gdb/TODO471
-rw-r--r--gdb/a29k-tdep.c1040
-rw-r--r--gdb/a68v-nat.c123
-rw-r--r--gdb/abug-rom.c169
-rw-r--r--gdb/acconfig.h95
-rw-r--r--gdb/acinclude.m4861
-rw-r--r--gdb/aclocal.m41307
-rw-r--r--gdb/alpha-nat.c297
-rw-r--r--gdb/alpha-tdep.c1410
-rw-r--r--gdb/altos-xdep.c164
-rw-r--r--gdb/annotate.c577
-rw-r--r--gdb/annotate.h104
-rw-r--r--gdb/arc-tdep.c733
-rw-r--r--gdb/arm-convert.s16
-rw-r--r--gdb/arm-tdep.c1626
-rw-r--r--gdb/arm-xdep.c559
-rw-r--r--gdb/ax-gdb.c1942
-rw-r--r--gdb/ax-gdb.h111
-rw-r--r--gdb/ax-general.c552
-rw-r--r--gdb/ax.h285
-rw-r--r--gdb/bcache.c219
-rw-r--r--gdb/bcache.h72
-rw-r--r--gdb/blockframe.c1301
-rw-r--r--gdb/breakpoint.c6686
-rw-r--r--gdb/breakpoint.h604
-rw-r--r--gdb/buildsym.c1130
-rw-r--r--gdb/buildsym.h297
-rw-r--r--gdb/c-exp.y1740
-rw-r--r--gdb/c-lang.c527
-rw-r--r--gdb/c-lang.h87
-rw-r--r--gdb/c-typeprint.c1089
-rw-r--r--gdb/c-valprint.c535
-rw-r--r--gdb/call-cmds.h28
-rw-r--r--gdb/ch-exp.c2169
-rw-r--r--gdb/ch-lang.c675
-rw-r--r--gdb/ch-lang.h42
-rw-r--r--gdb/ch-typeprint.c346
-rw-r--r--gdb/ch-valprint.c630
-rw-r--r--gdb/coff-solib.c134
-rw-r--r--gdb/coff-solib.h190
-rw-r--r--gdb/coffread.c2255
-rw-r--r--gdb/command.c1564
-rw-r--r--gdb/command.h259
-rw-r--r--gdb/complaints.c166
-rw-r--r--gdb/complaints.h53
-rw-r--r--gdb/config.in325
-rw-r--r--gdb/config/a29k/a29k-kern.mt13
-rw-r--r--gdb/config/a29k/a29k-udi.mt5
-rw-r--r--gdb/config/a29k/a29k.mt5
-rw-r--r--gdb/config/a29k/nm-ultra3.h26
-rw-r--r--gdb/config/a29k/tm-a29k.h707
-rw-r--r--gdb/config/a29k/tm-ultra3.h226
-rw-r--r--gdb/config/a29k/tm-vx29k.h229
-rw-r--r--gdb/config/a29k/ultra3.mh13
-rw-r--r--gdb/config/a29k/ultra3.mt6
-rw-r--r--gdb/config/a29k/vx29k.mt4
-rw-r--r--gdb/config/a29k/xm-ultra3.h52
-rw-r--r--gdb/config/alpha/alpha-linux.mh9
-rw-r--r--gdb/config/alpha/alpha-linux.mt3
-rw-r--r--gdb/config/alpha/alpha-osf1.mh5
-rw-r--r--gdb/config/alpha/alpha-osf1.mt3
-rw-r--r--gdb/config/alpha/alpha-osf2.mh5
-rw-r--r--gdb/config/alpha/alpha-osf3.mh5
-rw-r--r--gdb/config/alpha/nm-linux.h66
-rw-r--r--gdb/config/alpha/nm-osf.h56
-rw-r--r--gdb/config/alpha/nm-osf2.h54
-rw-r--r--gdb/config/alpha/nm-osf3.h26
-rw-r--r--gdb/config/alpha/tm-alpha.h479
-rw-r--r--gdb/config/alpha/tm-alphalinux.h80
-rw-r--r--gdb/config/alpha/xm-alphalinux.h29
-rw-r--r--gdb/config/alpha/xm-alphaosf.h27
-rw-r--r--gdb/config/arc/arc.mt3
-rw-r--r--gdb/config/arc/tm-arc.h347
-rw-r--r--gdb/config/arm/arm.mh5
-rw-r--r--gdb/config/arm/arm.mt6
-rw-r--r--gdb/config/arm/nm-arm.h27
-rw-r--r--gdb/config/arm/tm-arm.h453
-rw-r--r--gdb/config/arm/xm-arm.h76
-rw-r--r--gdb/config/convex/Convex.notes163
-rw-r--r--gdb/config/convex/convex.mh3
-rw-r--r--gdb/config/convex/convex.mt3
-rw-r--r--gdb/config/convex/tm-convex.h511
-rw-r--r--gdb/config/convex/xm-convex.h35
-rw-r--r--gdb/config/d10v/d10v.mt5
-rw-r--r--gdb/config/d10v/tm-d10v.h337
-rw-r--r--gdb/config/d30v/d30v.mt5
-rw-r--r--gdb/config/d30v/tm-d30v.h325
-rw-r--r--gdb/config/fr30/fr30.mt5
-rw-r--r--gdb/config/fr30/tm-fr30.h232
-rw-r--r--gdb/config/gould/np1.mh3
-rw-r--r--gdb/config/gould/np1.mt3
-rw-r--r--gdb/config/gould/pn.mh3
-rw-r--r--gdb/config/gould/pn.mt3
-rw-r--r--gdb/config/gould/tm-np1.h490
-rw-r--r--gdb/config/gould/tm-pn.h409
-rw-r--r--gdb/config/gould/xm-np1.h94
-rw-r--r--gdb/config/gould/xm-pn.h87
-rw-r--r--gdb/config/h8300/h8300.mt6
-rw-r--r--gdb/config/h8300/tm-h8300.h303
-rw-r--r--gdb/config/h8500/h8500.mt6
-rw-r--r--gdb/config/h8500/tm-h8500.h293
-rw-r--r--gdb/config/i386/cygwin.mh6
-rw-r--r--gdb/config/i386/cygwin.mt6
-rw-r--r--gdb/config/i386/fbsd.mh5
-rw-r--r--gdb/config/i386/fbsd.mt3
-rw-r--r--gdb/config/i386/gdbserve.mt3
-rw-r--r--gdb/config/i386/go32.mh8
-rw-r--r--gdb/config/i386/i386aix.mh10
-rw-r--r--gdb/config/i386/i386aix.mt7
-rw-r--r--gdb/config/i386/i386aout.mt3
-rw-r--r--gdb/config/i386/i386bsd.mh7
-rw-r--r--gdb/config/i386/i386bsd.mt3
-rw-r--r--gdb/config/i386/i386dgux.mh9
-rw-r--r--gdb/config/i386/i386gnu.mh31
-rw-r--r--gdb/config/i386/i386gnu.mt3
-rw-r--r--gdb/config/i386/i386lynx.mh11
-rw-r--r--gdb/config/i386/i386lynx.mt3
-rw-r--r--gdb/config/i386/i386m3.mh7
-rw-r--r--gdb/config/i386/i386m3.mt3
-rw-r--r--gdb/config/i386/i386mach.mh10
-rw-r--r--gdb/config/i386/i386mk.mh4
-rw-r--r--gdb/config/i386/i386mk.mt6
-rw-r--r--gdb/config/i386/i386nw.mt3
-rw-r--r--gdb/config/i386/i386os9k.mt3
-rw-r--r--gdb/config/i386/i386sco.mh13
-rw-r--r--gdb/config/i386/i386sco4.mh12
-rw-r--r--gdb/config/i386/i386sco5.mh17
-rw-r--r--gdb/config/i386/i386sco5.mt3
-rw-r--r--gdb/config/i386/i386sol2.mh7
-rw-r--r--gdb/config/i386/i386sol2.mt3
-rw-r--r--gdb/config/i386/i386v.mh8
-rw-r--r--gdb/config/i386/i386v.mt3
-rw-r--r--gdb/config/i386/i386v32.mh9
-rw-r--r--gdb/config/i386/i386v4.mh9
-rw-r--r--gdb/config/i386/i386v4.mt3
-rw-r--r--gdb/config/i386/i386v42mp.mh11
-rw-r--r--gdb/config/i386/i386v42mp.mt3
-rw-r--r--gdb/config/i386/linux.mh7
-rw-r--r--gdb/config/i386/linux.mt5
-rw-r--r--gdb/config/i386/nbsd.mh5
-rw-r--r--gdb/config/i386/nbsd.mt3
-rw-r--r--gdb/config/i386/ncr3000.mh16
-rw-r--r--gdb/config/i386/ncr3000.mt3
-rw-r--r--gdb/config/i386/nm-fbsd.h98
-rw-r--r--gdb/config/i386/nm-gnu.h22
-rw-r--r--gdb/config/i386/nm-i386aix.h42
-rw-r--r--gdb/config/i386/nm-i386bsd.h39
-rw-r--r--gdb/config/i386/nm-i386lynx.h25
-rw-r--r--gdb/config/i386/nm-i386mach.h26
-rw-r--r--gdb/config/i386/nm-i386sco.h41
-rw-r--r--gdb/config/i386/nm-i386sco4.h32
-rw-r--r--gdb/config/i386/nm-i386sco5.h39
-rw-r--r--gdb/config/i386/nm-i386sol2.h35
-rw-r--r--gdb/config/i386/nm-i386v.h36
-rw-r--r--gdb/config/i386/nm-i386v4.h24
-rw-r--r--gdb/config/i386/nm-i386v42mp.h22
-rw-r--r--gdb/config/i386/nm-linux.h73
-rw-r--r--gdb/config/i386/nm-m3.h22
-rw-r--r--gdb/config/i386/nm-nbsd.h34
-rw-r--r--gdb/config/i386/nm-ptx4.h62
-rw-r--r--gdb/config/i386/nm-sun386.h27
-rw-r--r--gdb/config/i386/nm-symmetry.h46
-rw-r--r--gdb/config/i386/ptx.mh7
-rw-r--r--gdb/config/i386/ptx.mt3
-rw-r--r--gdb/config/i386/ptx4.mh7
-rw-r--r--gdb/config/i386/ptx4.mt3
-rw-r--r--gdb/config/i386/sun386.mh5
-rw-r--r--gdb/config/i386/sun386.mt3
-rw-r--r--gdb/config/i386/symmetry.mh5
-rw-r--r--gdb/config/i386/symmetry.mt3
-rw-r--r--gdb/config/i386/tm-cygwin.h127
-rw-r--r--gdb/config/i386/tm-fbsd.h32
-rw-r--r--gdb/config/i386/tm-i386.h307
-rw-r--r--gdb/config/i386/tm-i386aix.h67
-rw-r--r--gdb/config/i386/tm-i386bsd.h43
-rw-r--r--gdb/config/i386/tm-i386gnu.h48
-rw-r--r--gdb/config/i386/tm-i386lynx.h33
-rw-r--r--gdb/config/i386/tm-i386m3.h60
-rw-r--r--gdb/config/i386/tm-i386mk.h25
-rw-r--r--gdb/config/i386/tm-i386nw.h49
-rw-r--r--gdb/config/i386/tm-i386os9k.h63
-rw-r--r--gdb/config/i386/tm-i386sco5.h62
-rw-r--r--gdb/config/i386/tm-i386sol2.h64
-rw-r--r--gdb/config/i386/tm-i386v.h163
-rw-r--r--gdb/config/i386/tm-i386v4.h78
-rw-r--r--gdb/config/i386/tm-i386v42mp.h44
-rw-r--r--gdb/config/i386/tm-linux.h38
-rw-r--r--gdb/config/i386/tm-nbsd.h42
-rw-r--r--gdb/config/i386/tm-ptx.h232
-rw-r--r--gdb/config/i386/tm-ptx4.h24
-rw-r--r--gdb/config/i386/tm-sun386.h205
-rw-r--r--gdb/config/i386/tm-symmetry.h321
-rw-r--r--gdb/config/i386/xm-cygwin.h34
-rw-r--r--gdb/config/i386/xm-go32.h31
-rw-r--r--gdb/config/i386/xm-i386aix.h33
-rw-r--r--gdb/config/i386/xm-i386bsd.h22
-rw-r--r--gdb/config/i386/xm-i386gnu.h23
-rw-r--r--gdb/config/i386/xm-i386lynx.h24
-rw-r--r--gdb/config/i386/xm-i386m3.h33
-rw-r--r--gdb/config/i386/xm-i386mach.h30
-rw-r--r--gdb/config/i386/xm-i386mk.h25
-rw-r--r--gdb/config/i386/xm-i386sco.h42
-rw-r--r--gdb/config/i386/xm-i386v.h45
-rw-r--r--gdb/config/i386/xm-i386v32.h24
-rw-r--r--gdb/config/i386/xm-i386v4.h27
-rw-r--r--gdb/config/i386/xm-linux.h36
-rw-r--r--gdb/config/i386/xm-nbsd.h21
-rw-r--r--gdb/config/i386/xm-ptx.h41
-rw-r--r--gdb/config/i386/xm-ptx4.h25
-rw-r--r--gdb/config/i386/xm-sun386.h20
-rw-r--r--gdb/config/i386/xm-symmetry.h28
-rw-r--r--gdb/config/i386/xm-windows.h35
-rw-r--r--gdb/config/i960/mon960.mt6
-rw-r--r--gdb/config/i960/nindy960.mt3
-rw-r--r--gdb/config/i960/tm-i960.h372
-rw-r--r--gdb/config/i960/tm-mon960.h70
-rw-r--r--gdb/config/i960/tm-nindy960.h106
-rw-r--r--gdb/config/i960/tm-vx960.h53
-rw-r--r--gdb/config/i960/vxworks960.mt6
-rw-r--r--gdb/config/m32r/m32r.mt7
-rw-r--r--gdb/config/m32r/tm-m32r.h234
-rw-r--r--gdb/config/m68k/3b1.mh12
-rw-r--r--gdb/config/m68k/3b1.mt3
-rw-r--r--gdb/config/m68k/altos.mh5
-rw-r--r--gdb/config/m68k/altos.mt3
-rw-r--r--gdb/config/m68k/apollo68b.mh6
-rw-r--r--gdb/config/m68k/apollo68b.mt3
-rw-r--r--gdb/config/m68k/apollo68v.mh11
-rw-r--r--gdb/config/m68k/cisco.mt3
-rw-r--r--gdb/config/m68k/delta68.mh5
-rw-r--r--gdb/config/m68k/delta68.mt3
-rw-r--r--gdb/config/m68k/dpx2.mh7
-rw-r--r--gdb/config/m68k/dpx2.mt3
-rw-r--r--gdb/config/m68k/es1800.mt9
-rw-r--r--gdb/config/m68k/hp300bsd.mh7
-rw-r--r--gdb/config/m68k/hp300bsd.mt3
-rw-r--r--gdb/config/m68k/hp300hpux.mh8
-rw-r--r--gdb/config/m68k/hp300hpux.mt8
-rw-r--r--gdb/config/m68k/isi.mh5
-rw-r--r--gdb/config/m68k/isi.mt3
-rw-r--r--gdb/config/m68k/linux.mh9
-rw-r--r--gdb/config/m68k/linux.mt3
-rw-r--r--gdb/config/m68k/m68klynx.mh11
-rw-r--r--gdb/config/m68k/m68klynx.mt4
-rw-r--r--gdb/config/m68k/m68kv4.mh7
-rw-r--r--gdb/config/m68k/m68kv4.mt3
-rw-r--r--gdb/config/m68k/monitor.mt3
-rw-r--r--gdb/config/m68k/nbsd.mh5
-rw-r--r--gdb/config/m68k/nbsd.mt3
-rw-r--r--gdb/config/m68k/news.mh5
-rw-r--r--gdb/config/m68k/news.mt3
-rw-r--r--gdb/config/m68k/news1000.mh3
-rw-r--r--gdb/config/m68k/nm-apollo68b.h41
-rw-r--r--gdb/config/m68k/nm-apollo68v.h20
-rw-r--r--gdb/config/m68k/nm-delta68.h21
-rw-r--r--gdb/config/m68k/nm-dpx2.h29
-rw-r--r--gdb/config/m68k/nm-hp300bsd.h88
-rw-r--r--gdb/config/m68k/nm-hp300hpux.h53
-rw-r--r--gdb/config/m68k/nm-linux.h47
-rw-r--r--gdb/config/m68k/nm-m68klynx.h25
-rw-r--r--gdb/config/m68k/nm-nbsd.h21
-rw-r--r--gdb/config/m68k/nm-news.h26
-rw-r--r--gdb/config/m68k/nm-sun2.h33
-rw-r--r--gdb/config/m68k/nm-sun3.h31
-rw-r--r--gdb/config/m68k/nm-sysv4.h22
-rw-r--r--gdb/config/m68k/os68k.mt3
-rw-r--r--gdb/config/m68k/st2000.mt3
-rw-r--r--gdb/config/m68k/sun2os3.mh5
-rw-r--r--gdb/config/m68k/sun2os3.mt7
-rw-r--r--gdb/config/m68k/sun2os4.mh5
-rw-r--r--gdb/config/m68k/sun2os4.mt3
-rw-r--r--gdb/config/m68k/sun3os3.mh5
-rw-r--r--gdb/config/m68k/sun3os3.mt8
-rw-r--r--gdb/config/m68k/sun3os4.mh6
-rw-r--r--gdb/config/m68k/sun3os4.mt3
-rw-r--r--gdb/config/m68k/tm-3b1.h32
-rw-r--r--gdb/config/m68k/tm-altos.h57
-rw-r--r--gdb/config/m68k/tm-apollo68b.h59
-rw-r--r--gdb/config/m68k/tm-cisco.h55
-rw-r--r--gdb/config/m68k/tm-delta68.h103
-rw-r--r--gdb/config/m68k/tm-dpx2.h33
-rw-r--r--gdb/config/m68k/tm-es1800.h59
-rw-r--r--gdb/config/m68k/tm-hp300bsd.h62
-rw-r--r--gdb/config/m68k/tm-hp300hpux.h31
-rw-r--r--gdb/config/m68k/tm-isi.h150
-rw-r--r--gdb/config/m68k/tm-linux.h109
-rw-r--r--gdb/config/m68k/tm-m68k.h393
-rw-r--r--gdb/config/m68k/tm-m68klynx.h38
-rw-r--r--gdb/config/m68k/tm-m68kv4.h70
-rw-r--r--gdb/config/m68k/tm-mac.h20
-rw-r--r--gdb/config/m68k/tm-monitor.h44
-rw-r--r--gdb/config/m68k/tm-nbsd.h41
-rw-r--r--gdb/config/m68k/tm-news.h75
-rw-r--r--gdb/config/m68k/tm-os68k.h46
-rw-r--r--gdb/config/m68k/tm-st2000.h20
-rw-r--r--gdb/config/m68k/tm-sun2.h23
-rw-r--r--gdb/config/m68k/tm-sun2os4.h20
-rw-r--r--gdb/config/m68k/tm-sun3.h107
-rw-r--r--gdb/config/m68k/tm-sun3os4.h21
-rw-r--r--gdb/config/m68k/tm-vx68.h91
-rw-r--r--gdb/config/m68k/vxworks68.mt3
-rw-r--r--gdb/config/m68k/xm-3b1.h85
-rw-r--r--gdb/config/m68k/xm-altos.h202
-rw-r--r--gdb/config/m68k/xm-apollo68b.h24
-rw-r--r--gdb/config/m68k/xm-apollo68v.h44
-rw-r--r--gdb/config/m68k/xm-delta68.h36
-rw-r--r--gdb/config/m68k/xm-dpx2.h26
-rw-r--r--gdb/config/m68k/xm-hp300bsd.h85
-rw-r--r--gdb/config/m68k/xm-hp300hpux.h150
-rw-r--r--gdb/config/m68k/xm-isi.h92
-rw-r--r--gdb/config/m68k/xm-linux.h40
-rw-r--r--gdb/config/m68k/xm-m68k.h22
-rw-r--r--gdb/config/m68k/xm-m68klynx.h24
-rw-r--r--gdb/config/m68k/xm-m68kv4.h28
-rw-r--r--gdb/config/m68k/xm-mpw.h24
-rw-r--r--gdb/config/m68k/xm-nbsd.h21
-rw-r--r--gdb/config/m68k/xm-news.h137
-rw-r--r--gdb/config/m68k/xm-news1000.h26
-rw-r--r--gdb/config/m68k/xm-sun2.h78
-rw-r--r--gdb/config/m68k/xm-sun3.h73
-rw-r--r--gdb/config/m68k/xm-sun3os4.h21
-rw-r--r--gdb/config/m88k/cxux.mh7
-rw-r--r--gdb/config/m88k/cxux.mt3
-rw-r--r--gdb/config/m88k/delta88.mh7
-rw-r--r--gdb/config/m88k/delta88.mt3
-rw-r--r--gdb/config/m88k/delta88v4.mh7
-rw-r--r--gdb/config/m88k/delta88v4.mt3
-rw-r--r--gdb/config/m88k/m88k.mh5
-rw-r--r--gdb/config/m88k/m88k.mt3
-rw-r--r--gdb/config/m88k/nm-cxux.h32
-rw-r--r--gdb/config/m88k/nm-delta88v4.h21
-rw-r--r--gdb/config/m88k/nm-m88k.h24
-rw-r--r--gdb/config/m88k/tm-cxux.h59
-rw-r--r--gdb/config/m88k/tm-delta88.h26
-rw-r--r--gdb/config/m88k/tm-delta88v4.h30
-rw-r--r--gdb/config/m88k/tm-m88k.h620
-rw-r--r--gdb/config/m88k/xm-cxux.h66
-rw-r--r--gdb/config/m88k/xm-delta88.h45
-rw-r--r--gdb/config/m88k/xm-delta88v4.h22
-rw-r--r--gdb/config/m88k/xm-dgux.h58
-rw-r--r--gdb/config/m88k/xm-m88k.h20
-rw-r--r--gdb/config/mips/bigmips.mt3
-rw-r--r--gdb/config/mips/bigmips64.mt3
-rw-r--r--gdb/config/mips/decstation.mh5
-rw-r--r--gdb/config/mips/decstation.mt3
-rw-r--r--gdb/config/mips/embed.mt5
-rw-r--r--gdb/config/mips/embed64.mt5
-rw-r--r--gdb/config/mips/embedl.mt5
-rw-r--r--gdb/config/mips/embedl64.mt5
-rw-r--r--gdb/config/mips/irix3.mh6
-rw-r--r--gdb/config/mips/irix3.mt3
-rw-r--r--gdb/config/mips/irix4.mh8
-rw-r--r--gdb/config/mips/irix5.mh6
-rw-r--r--gdb/config/mips/irix5.mt3
-rw-r--r--gdb/config/mips/littlemips.mh3
-rw-r--r--gdb/config/mips/littlemips.mt3
-rw-r--r--gdb/config/mips/mipsm3.mh7
-rw-r--r--gdb/config/mips/mipsm3.mt4
-rw-r--r--gdb/config/mips/mipsv4.mh4
-rw-r--r--gdb/config/mips/mipsv4.mt3
-rw-r--r--gdb/config/mips/news-mips.mh4
-rw-r--r--gdb/config/mips/nm-irix3.h37
-rw-r--r--gdb/config/mips/nm-irix4.h61
-rw-r--r--gdb/config/mips/nm-irix5.h44
-rw-r--r--gdb/config/mips/nm-mips.h32
-rw-r--r--gdb/config/mips/nm-news-mips.h42
-rw-r--r--gdb/config/mips/nm-riscos.h59
-rw-r--r--gdb/config/mips/riscos.mh16
-rw-r--r--gdb/config/mips/tm-bigmips.h21
-rw-r--r--gdb/config/mips/tm-bigmips64.h23
-rw-r--r--gdb/config/mips/tm-embed.h49
-rw-r--r--gdb/config/mips/tm-embed64.h21
-rw-r--r--gdb/config/mips/tm-embedl.h21
-rw-r--r--gdb/config/mips/tm-embedl64.h21
-rw-r--r--gdb/config/mips/tm-irix3.h81
-rw-r--r--gdb/config/mips/tm-irix5.h75
-rw-r--r--gdb/config/mips/tm-mips.h560
-rw-r--r--gdb/config/mips/tm-mips64.h54
-rw-r--r--gdb/config/mips/tm-mipsm3.h66
-rw-r--r--gdb/config/mips/tm-mipsv4.h45
-rw-r--r--gdb/config/mips/tm-tx39.h39
-rw-r--r--gdb/config/mips/tm-tx39l.h39
-rw-r--r--gdb/config/mips/tm-vr4100.h25
-rw-r--r--gdb/config/mips/tm-vr4300.h22
-rw-r--r--gdb/config/mips/tm-vr4300el.h22
-rw-r--r--gdb/config/mips/tm-vr5000.h23
-rw-r--r--gdb/config/mips/tm-vr5000el.h23
-rw-r--r--gdb/config/mips/tm-vxmips.h31
-rw-r--r--gdb/config/mips/tx39.mt5
-rw-r--r--gdb/config/mips/tx39l.mt5
-rw-r--r--gdb/config/mips/vr4100.mt5
-rw-r--r--gdb/config/mips/vr4300.mt5
-rw-r--r--gdb/config/mips/vr4300el.mt5
-rw-r--r--gdb/config/mips/vr5000.mt7
-rw-r--r--gdb/config/mips/vr5000el.mt5
-rw-r--r--gdb/config/mips/vxmips.mt3
-rw-r--r--gdb/config/mips/xm-irix3.h31
-rw-r--r--gdb/config/mips/xm-irix4.h33
-rw-r--r--gdb/config/mips/xm-irix5.h35
-rw-r--r--gdb/config/mips/xm-mips.h61
-rw-r--r--gdb/config/mips/xm-mipsm3.h32
-rw-r--r--gdb/config/mips/xm-mipsv4.h23
-rw-r--r--gdb/config/mips/xm-news-mips.h24
-rw-r--r--gdb/config/mips/xm-riscos.h28
-rw-r--r--gdb/config/mn10200/mn10200.mt6
-rw-r--r--gdb/config/mn10200/tm-mn10200.h212
-rw-r--r--gdb/config/mn10300/mn10300.mt6
-rw-r--r--gdb/config/mn10300/tm-mn10300.h165
-rw-r--r--gdb/config/nm-empty.h2
-rw-r--r--gdb/config/nm-gnu.h45
-rw-r--r--gdb/config/nm-lynx.h83
-rw-r--r--gdb/config/nm-m3.h123
-rw-r--r--gdb/config/nm-nbsd.h86
-rw-r--r--gdb/config/nm-sysv4.h33
-rw-r--r--gdb/config/none/nm-none.h18
-rw-r--r--gdb/config/none/none.mh5
-rw-r--r--gdb/config/none/none.mt4
-rw-r--r--gdb/config/none/tm-none.h23
-rw-r--r--gdb/config/none/xm-none.h18
-rw-r--r--gdb/config/ns32k/merlin.mh16
-rw-r--r--gdb/config/ns32k/merlin.mt3
-rw-r--r--gdb/config/ns32k/nbsd.mh5
-rw-r--r--gdb/config/ns32k/nbsd.mt3
-rw-r--r--gdb/config/ns32k/nm-nbsd.h36
-rw-r--r--gdb/config/ns32k/nm-umax.h54
-rw-r--r--gdb/config/ns32k/ns32km3.mh7
-rw-r--r--gdb/config/ns32k/ns32km3.mt3
-rw-r--r--gdb/config/ns32k/tm-merlin.h313
-rw-r--r--gdb/config/ns32k/tm-nbsd.h79
-rw-r--r--gdb/config/ns32k/tm-ns32km3.h73
-rw-r--r--gdb/config/ns32k/tm-umax.h370
-rw-r--r--gdb/config/ns32k/umax.mh5
-rw-r--r--gdb/config/ns32k/umax.mt3
-rw-r--r--gdb/config/ns32k/xm-merlin.h65
-rw-r--r--gdb/config/ns32k/xm-nbsd.h21
-rw-r--r--gdb/config/ns32k/xm-ns32km3.h23
-rw-r--r--gdb/config/ns32k/xm-umax.h26
-rw-r--r--gdb/config/pa/hppabsd.mh7
-rw-r--r--gdb/config/pa/hppabsd.mt3
-rw-r--r--gdb/config/pa/hppahpux.mh9
-rw-r--r--gdb/config/pa/hppahpux.mt3
-rw-r--r--gdb/config/pa/hppaosf.mh9
-rw-r--r--gdb/config/pa/hppaosf.mt3
-rw-r--r--gdb/config/pa/hppapro.mt3
-rw-r--r--gdb/config/pa/hpux1020.mh11
-rw-r--r--gdb/config/pa/hpux1020.mt3
-rw-r--r--gdb/config/pa/hpux1100.mh11
-rw-r--r--gdb/config/pa/hpux1100.mt3
-rw-r--r--gdb/config/pa/nm-hppab.h135
-rw-r--r--gdb/config/pa/nm-hppah.h281
-rw-r--r--gdb/config/pa/nm-hppah11.h22
-rw-r--r--gdb/config/pa/nm-hppao.h56
-rw-r--r--gdb/config/pa/tm-hppa.h788
-rw-r--r--gdb/config/pa/tm-hppab.h47
-rw-r--r--gdb/config/pa/tm-hppah.h79
-rw-r--r--gdb/config/pa/tm-hppao.h96
-rw-r--r--gdb/config/pa/tm-pro.h14
-rw-r--r--gdb/config/pa/xm-hppab.h27
-rw-r--r--gdb/config/pa/xm-hppah.h49
-rw-r--r--gdb/config/pa/xm-pa.h5
-rw-r--r--gdb/config/powerpc/aix.mh11
-rw-r--r--gdb/config/powerpc/aix.mt3
-rw-r--r--gdb/config/powerpc/cygwin.mh5
-rw-r--r--gdb/config/powerpc/cygwin.mt6
-rw-r--r--gdb/config/powerpc/gdbserve.mt3
-rw-r--r--gdb/config/powerpc/linux.mh10
-rw-r--r--gdb/config/powerpc/macos.mh4
-rw-r--r--gdb/config/powerpc/macos.mt3
-rw-r--r--gdb/config/powerpc/nm-aix.h22
-rw-r--r--gdb/config/powerpc/nm-macos.h20
-rw-r--r--gdb/config/powerpc/nm-solaris.h30
-rw-r--r--gdb/config/powerpc/ppc-eabi.mt3
-rw-r--r--gdb/config/powerpc/ppc-nw.mt3
-rw-r--r--gdb/config/powerpc/ppc-sim.mt6
-rw-r--r--gdb/config/powerpc/ppcle-eabi.mt3
-rw-r--r--gdb/config/powerpc/ppcle-sim.mt6
-rw-r--r--gdb/config/powerpc/solaris.mh18
-rw-r--r--gdb/config/powerpc/solaris.mt3
-rw-r--r--gdb/config/powerpc/tm-cygwin.h21
-rw-r--r--gdb/config/powerpc/tm-macos.h26
-rw-r--r--gdb/config/powerpc/tm-ppc-aix.h28
-rw-r--r--gdb/config/powerpc/tm-ppc-eabi.h84
-rw-r--r--gdb/config/powerpc/tm-ppc-nw.h31
-rw-r--r--gdb/config/powerpc/tm-ppc-sim.h26
-rw-r--r--gdb/config/powerpc/tm-ppcle-eabi.h30
-rw-r--r--gdb/config/powerpc/tm-ppcle-sim.h26
-rw-r--r--gdb/config/powerpc/tm-solaris.h74
-rw-r--r--gdb/config/powerpc/xm-aix.h30
-rw-r--r--gdb/config/powerpc/xm-cygwin.h32
-rw-r--r--gdb/config/powerpc/xm-linux.h21
-rw-r--r--gdb/config/powerpc/xm-mpw.h22
-rw-r--r--gdb/config/powerpc/xm-solaris.h21
-rw-r--r--gdb/config/pyr/pyramid.mh8
-rw-r--r--gdb/config/pyr/pyramid.mt3
-rw-r--r--gdb/config/pyr/tm-pyr.h483
-rw-r--r--gdb/config/pyr/xm-pyr.h92
-rw-r--r--gdb/config/romp/rtbsd.mh8
-rw-r--r--gdb/config/romp/xm-rtbsd.h40
-rw-r--r--gdb/config/rs6000/aix4.mh11
-rw-r--r--gdb/config/rs6000/aix4.mt3
-rw-r--r--gdb/config/rs6000/nm-rs6000.h60
-rw-r--r--gdb/config/rs6000/nm-rs6000ly.h25
-rw-r--r--gdb/config/rs6000/rs6000.mh11
-rw-r--r--gdb/config/rs6000/rs6000.mt3
-rw-r--r--gdb/config/rs6000/rs6000lynx.mh11
-rw-r--r--gdb/config/rs6000/rs6000lynx.mt3
-rw-r--r--gdb/config/rs6000/tm-rs6000-aix4.h26
-rw-r--r--gdb/config/rs6000/tm-rs6000.h564
-rw-r--r--gdb/config/rs6000/tm-rs6000ly.h32
-rw-r--r--gdb/config/rs6000/xm-aix4.h26
-rw-r--r--gdb/config/rs6000/xm-rs6000.h107
-rw-r--r--gdb/config/rs6000/xm-rs6000ly.h29
-rw-r--r--gdb/config/sh/sh.mt6
-rw-r--r--gdb/config/sh/tm-sh.h281
-rw-r--r--gdb/config/sparc/linux.mh7
-rw-r--r--gdb/config/sparc/linux.mt3
-rw-r--r--gdb/config/sparc/nbsd.mh6
-rw-r--r--gdb/config/sparc/nbsd.mt3
-rw-r--r--gdb/config/sparc/nm-linux.h31
-rw-r--r--gdb/config/sparc/nm-nbsd.h57
-rw-r--r--gdb/config/sparc/nm-sparclynx.h25
-rw-r--r--gdb/config/sparc/nm-sun4os4.h35
-rw-r--r--gdb/config/sparc/nm-sun4sol2.h45
-rw-r--r--gdb/config/sparc/sp64.mt9
-rw-r--r--gdb/config/sparc/sp64sim.mt13
-rw-r--r--gdb/config/sparc/sp64sol2.mt3
-rw-r--r--gdb/config/sparc/sparc-em.mt3
-rw-r--r--gdb/config/sparc/sparclet.mt3
-rw-r--r--gdb/config/sparc/sparclite.mt5
-rw-r--r--gdb/config/sparc/sparclynx.mh11
-rw-r--r--gdb/config/sparc/sparclynx.mt3
-rw-r--r--gdb/config/sparc/sun4os4.mh11
-rw-r--r--gdb/config/sparc/sun4os4.mt3
-rw-r--r--gdb/config/sparc/sun4sol2.mh18
-rw-r--r--gdb/config/sparc/sun4sol2.mt3
-rw-r--r--gdb/config/sparc/tm-linux.h29
-rw-r--r--gdb/config/sparc/tm-nbsd.h27
-rw-r--r--gdb/config/sparc/tm-sp64.h378
-rw-r--r--gdb/config/sparc/tm-sp64sim.h50
-rw-r--r--gdb/config/sparc/tm-sparc.h584
-rw-r--r--gdb/config/sparc/tm-sparclet.h132
-rw-r--r--gdb/config/sparc/tm-sparclite.h98
-rw-r--r--gdb/config/sparc/tm-sparclynx.h36
-rw-r--r--gdb/config/sparc/tm-spc-em.h46
-rw-r--r--gdb/config/sparc/tm-sun4os4.h58
-rw-r--r--gdb/config/sparc/tm-sun4sol2.h94
-rw-r--r--gdb/config/sparc/tm-vxsparc.h36
-rw-r--r--gdb/config/sparc/vxsparc.mt3
-rw-r--r--gdb/config/sparc/xm-linux.h48
-rw-r--r--gdb/config/sparc/xm-nbsd.h21
-rw-r--r--gdb/config/sparc/xm-sparc.h22
-rw-r--r--gdb/config/sparc/xm-sparclynx.h24
-rw-r--r--gdb/config/sparc/xm-sun4os4.h34
-rw-r--r--gdb/config/sparc/xm-sun4sol2.h49
-rw-r--r--gdb/config/tahoe/tahoe.mh4
-rw-r--r--gdb/config/tahoe/tahoe.mt3
-rw-r--r--gdb/config/tahoe/tm-tahoe.h289
-rw-r--r--gdb/config/tahoe/xm-tahoe.h136
-rw-r--r--gdb/config/tm-lynx.h34
-rw-r--r--gdb/config/tm-nbsd.h19
-rw-r--r--gdb/config/tm-sunos.h31
-rw-r--r--gdb/config/tm-sysv4.h45
-rw-r--r--gdb/config/v850/tm-v850.h174
-rw-r--r--gdb/config/v850/v850.mt5
-rw-r--r--gdb/config/vax/nm-vax.h28
-rw-r--r--gdb/config/vax/tm-vax.h330
-rw-r--r--gdb/config/vax/vax.mt3
-rw-r--r--gdb/config/vax/vaxbsd.mh13
-rw-r--r--gdb/config/vax/vaxult.mh7
-rw-r--r--gdb/config/vax/vaxult2.mh7
-rw-r--r--gdb/config/vax/xm-vax.h81
-rw-r--r--gdb/config/vax/xm-vaxbsd.h10
-rw-r--r--gdb/config/vax/xm-vaxult.h12
-rw-r--r--gdb/config/vax/xm-vaxult2.h11
-rw-r--r--gdb/config/w65/tm-w65.h213
-rw-r--r--gdb/config/w65/w65.mt8
-rw-r--r--gdb/config/xm-aix4.h99
-rw-r--r--gdb/config/xm-lynx.h20
-rw-r--r--gdb/config/xm-mpw.h81
-rw-r--r--gdb/config/xm-nbsd.h32
-rw-r--r--gdb/config/xm-sysv4.h39
-rw-r--r--gdb/config/z8k/tm-z8k.h287
-rw-r--r--gdb/config/z8k/z8k.mt7
-rwxr-xr-xgdb/configure6279
-rw-r--r--gdb/configure.host162
-rw-r--r--gdb/configure.in606
-rw-r--r--gdb/configure.tgt282
-rw-r--r--gdb/convex-tdep.c1217
-rw-r--r--gdb/convex-xdep.c966
-rw-r--r--gdb/copying.awk77
-rw-r--r--gdb/copying.c327
-rw-r--r--gdb/core-aout.c147
-rw-r--r--gdb/core-regset.c134
-rw-r--r--gdb/core-sol2.c133
-rw-r--r--gdb/corefile.c479
-rw-r--r--gdb/corelow.c511
-rw-r--r--gdb/cp-valprint.c826
-rw-r--r--gdb/cpu32bug-rom.c167
-rw-r--r--gdb/cxux-nat.c523
-rw-r--r--gdb/d10v-tdep.c1028
-rw-r--r--gdb/d30v-tdep.c1396
-rw-r--r--gdb/dbug-rom.c164
-rw-r--r--gdb/dbxread.c2738
-rw-r--r--gdb/dcache.c558
-rw-r--r--gdb/dcache.h50
-rw-r--r--gdb/debugify.c109
-rw-r--r--gdb/debugify.h83
-rw-r--r--gdb/defs.h1139
-rw-r--r--gdb/delta68-nat.c91
-rw-r--r--gdb/demangle.c237
-rw-r--r--gdb/dink32-rom.c198
-rw-r--r--gdb/doc/ChangeLog1473
-rw-r--r--gdb/doc/HPPA-cfg.texi114
-rw-r--r--gdb/doc/LRS197
-rw-r--r--gdb/doc/Makefile.in340
-rw-r--r--gdb/doc/a4rc.sed11
-rw-r--r--gdb/doc/agentexpr.texi839
-rw-r--r--gdb/doc/all-cfg.texi112
-rw-r--r--gdb/doc/annotate.texi717
-rwxr-xr-xgdb/doc/configure862
-rw-r--r--gdb/doc/configure.in4
-rw-r--r--gdb/doc/gdb.texinfo10316
-rw-r--r--gdb/doc/gdbint.texinfo2711
-rw-r--r--gdb/doc/libgdb.texinfo878
-rw-r--r--gdb/doc/lpsrc.sed13
-rw-r--r--gdb/doc/psrc.sed13
-rw-r--r--gdb/doc/refcard.tex645
-rw-r--r--gdb/doc/remote.texi1708
-rw-r--r--gdb/doc/stabs.texinfo4019
-rw-r--r--gdb/dpx2-nat.c83
-rw-r--r--gdb/dsrec.c312
-rw-r--r--gdb/dst.h1659
-rw-r--r--gdb/dstread.c1665
-rw-r--r--gdb/dve3900-rom.c962
-rw-r--r--gdb/dwarf2read.c5865
-rw-r--r--gdb/dwarfread.c3915
-rw-r--r--gdb/elfread.c849
-rw-r--r--gdb/environ.c194
-rw-r--r--gdb/environ.h58
-rw-r--r--gdb/eval.c1989
-rw-r--r--gdb/exc_request.defs51
-rw-r--r--gdb/exec.c762
-rw-r--r--gdb/expprint.c903
-rw-r--r--gdb/expression.h382
-rw-r--r--gdb/f-exp.y1174
-rw-r--r--gdb/f-lang.c973
-rw-r--r--gdb/f-lang.h96
-rw-r--r--gdb/f-typeprint.c458
-rw-r--r--gdb/f-valprint.c767
-rw-r--r--gdb/findvar.c1630
-rw-r--r--gdb/fork-child.c616
-rw-r--r--gdb/fr30-tdep.c552
-rw-r--r--gdb/frame.h264
-rw-r--r--gdb/gdb-stabs.h92
-rw-r--r--gdb/gdb.1375
-rw-r--r--gdb/gdb.gdb35
-rw-r--r--gdb/gdb_stat.h68
-rw-r--r--gdb/gdb_string.h68
-rw-r--r--gdb/gdba.el2607
-rw-r--r--gdb/gdbarch.c360
-rw-r--r--gdb/gdbarch.h118
-rw-r--r--gdb/gdbcmd.h114
-rw-r--r--gdb/gdbcore.h169
-rw-r--r--gdb/gdbinit.in18
-rw-r--r--gdb/gdbserver/Makefile.in241
-rw-r--r--gdb/gdbserver/README127
-rw-r--r--gdb/gdbserver/configure.in100
-rw-r--r--gdb/gdbserver/gdbreplay.c318
-rw-r--r--gdb/gdbserver/gdbserver.1103
-rw-r--r--gdb/gdbserver/low-hppabsd.c379
-rw-r--r--gdb/gdbserver/low-linux.c451
-rw-r--r--gdb/gdbserver/low-lynx.c746
-rw-r--r--gdb/gdbserver/low-sim.c289
-rw-r--r--gdb/gdbserver/low-sparc.c334
-rw-r--r--gdb/gdbserver/low-sun3.c313
-rw-r--r--gdb/gdbserver/remote-utils.c545
-rw-r--r--gdb/gdbserver/server.c258
-rw-r--r--gdb/gdbserver/server.h72
-rw-r--r--gdb/gdbserver/utils.c114
-rw-r--r--gdb/gdbthread.h121
-rw-r--r--gdb/gdbtypes.c2905
-rw-r--r--gdb/gdbtypes.h1135
-rw-r--r--gdb/gnu-nat.c3201
-rw-r--r--gdb/gnu-nat.h93
-rw-r--r--gdb/gnu-regex.c5797
-rw-r--r--gdb/gnu-regex.h576
-rw-r--r--gdb/gould-tdep.c310
-rw-r--r--gdb/gould-xdep.c130
-rw-r--r--gdb/h8300-tdep.c921
-rw-r--r--gdb/h8500-tdep.c653
-rw-r--r--gdb/hp-psymtab-read.c2381
-rw-r--r--gdb/hp-symtab-read.c3988
-rw-r--r--gdb/hp300ux-nat.c221
-rw-r--r--gdb/hppa-tdep.c4445
-rw-r--r--gdb/hppab-nat.c215
-rw-r--r--gdb/hppah-nat.c1059
-rw-r--r--gdb/hppam3-nat.c141
-rw-r--r--gdb/hpread.c2050
-rw-r--r--gdb/hpread.h150
-rw-r--r--gdb/hpux-thread.c641
-rw-r--r--gdb/i386-stub.c927
-rw-r--r--gdb/i386-tdep.c794
-rw-r--r--gdb/i386aix-nat.c362
-rw-r--r--gdb/i386b-nat.c285
-rw-r--r--gdb/i386gnu-nat.c357
-rw-r--r--gdb/i386ly-tdep.c43
-rw-r--r--gdb/i386m3-nat.c421
-rw-r--r--gdb/i386mach-nat.c163
-rw-r--r--gdb/i386v-nat.c392
-rw-r--r--gdb/i386v4-nat.c172
-rw-r--r--gdb/i387-tdep.c111
-rw-r--r--gdb/i960-tdep.c838
-rw-r--r--gdb/infcmd.c1553
-rw-r--r--gdb/inferior.h473
-rw-r--r--gdb/inflow.c751
-rw-r--r--gdb/infptrace.c638
-rw-r--r--gdb/infrun.c3775
-rw-r--r--gdb/inftarg.c968
-rw-r--r--gdb/infttrace.c5674
-rw-r--r--gdb/irix4-nat.c195
-rw-r--r--gdb/irix5-nat.c1349
-rw-r--r--gdb/isi-xdep.c20
-rw-r--r--gdb/jv-exp.y1466
-rw-r--r--gdb/jv-lang.c1088
-rw-r--r--gdb/jv-lang.h67
-rw-r--r--gdb/jv-typeprint.c339
-rw-r--r--gdb/jv-valprint.c526
-rw-r--r--gdb/kdb-start.c35
-rw-r--r--gdb/language.c1451
-rw-r--r--gdb/language.h439
-rw-r--r--gdb/lynx-nat.c837
-rw-r--r--gdb/m2-exp.y1094
-rw-r--r--gdb/m2-lang.c472
-rw-r--r--gdb/m2-lang.h31
-rw-r--r--gdb/m2-typeprint.c49
-rw-r--r--gdb/m2-valprint.c47
-rw-r--r--gdb/m3-nat.c4646
-rw-r--r--gdb/m32r-rom.c650
-rw-r--r--gdb/m32r-stub.c1685
-rw-r--r--gdb/m32r-tdep.c745
-rw-r--r--gdb/m68k-stub.c1014
-rw-r--r--gdb/m68k-tdep.c516
-rw-r--r--gdb/m68klinux-nat.c155
-rw-r--r--gdb/m68knbsd-nat.c86
-rw-r--r--gdb/m88k-nat.c285
-rw-r--r--gdb/m88k-tdep.c629
-rw-r--r--gdb/mac-defs.h34
-rw-r--r--gdb/mac-gdb.r184
-rw-r--r--gdb/mac-nat.c412
-rw-r--r--gdb/mac-xdep.c1087
-rw-r--r--gdb/main.c780
-rw-r--r--gdb/maint.c449
-rw-r--r--gdb/mdebugread.c4544
-rw-r--r--gdb/mem-break.c124
-rw-r--r--gdb/minimon.h562
-rw-r--r--gdb/minsyms.c904
-rw-r--r--gdb/mips-nat.c244
-rw-r--r--gdb/mips-tdep.c3259
-rw-r--r--gdb/mipsm3-nat.c386
-rw-r--r--gdb/mipsread.c446
-rw-r--r--gdb/mipsv4-nat.c159
-rw-r--r--gdb/mn10200-tdep.c919
-rw-r--r--gdb/mn10300-tdep.c791
-rw-r--r--gdb/mon960-rom.c264
-rw-r--r--gdb/monitor.c2296
-rw-r--r--gdb/monitor.h247
-rw-r--r--gdb/mpw-config.in81
-rw-r--r--gdb/mpw-make.sed178
-rw-r--r--gdb/msg.defs1
-rw-r--r--gdb/msg_reply.defs1
-rw-r--r--gdb/news-xdep.c65
-rw-r--r--gdb/nindy-share/Makefile117
-rw-r--r--gdb/nindy-share/Onindy.c743
-rw-r--r--gdb/nindy-share/README3
-rw-r--r--gdb/nindy-share/VERSION1
-rw-r--r--gdb/nindy-share/b.out.h158
-rw-r--r--gdb/nindy-share/block_io.h68
-rw-r--r--gdb/nindy-share/coff.h336
-rw-r--r--gdb/nindy-share/env.h12
-rw-r--r--gdb/nindy-share/nindy.c1154
-rw-r--r--gdb/nindy-share/stop.h86
-rw-r--r--gdb/nindy-share/ttyflush.c53
-rw-r--r--gdb/nindy-tdep.c74
-rw-r--r--gdb/nlm/Makefile.in172
-rwxr-xr-xgdb/nlm/configure1074
-rw-r--r--gdb/nlm/configure.in55
-rw-r--r--gdb/nlm/gdbserve.c1056
-rw-r--r--gdb/nlm/gdbserve.def42
-rw-r--r--gdb/nlm/i386.c108
-rw-r--r--gdb/nlm/i386.h13
-rw-r--r--gdb/nlm/ppc.c257
-rw-r--r--gdb/nlm/ppc.h165
-rw-r--r--gdb/nlm/prelude.c67
-rw-r--r--gdb/nlmread.c261
-rw-r--r--gdb/notify.defs1
-rw-r--r--gdb/ns32k-tdep.c122
-rw-r--r--gdb/ns32km3-nat.c183
-rw-r--r--gdb/ns32knbsd-nat.c353
-rw-r--r--gdb/objfiles.c988
-rw-r--r--gdb/objfiles.h572
-rw-r--r--gdb/ocd.c1444
-rw-r--r--gdb/ocd.h139
-rw-r--r--gdb/op50-rom.c142
-rw-r--r--gdb/os9kread.c1624
-rw-r--r--gdb/osf-share/AT386/cma_thread_io.h457
-rw-r--r--gdb/osf-share/HP800/cma_thread_io.h432
-rw-r--r--gdb/osf-share/README8
-rw-r--r--gdb/osf-share/RIOS/cma_thread_io.h434
-rw-r--r--gdb/osf-share/cma_attr.h341
-rw-r--r--gdb/osf-share/cma_deb_core.h164
-rw-r--r--gdb/osf-share/cma_debug_client.h195
-rw-r--r--gdb/osf-share/cma_errors.h55
-rw-r--r--gdb/osf-share/cma_handle.h182
-rw-r--r--gdb/osf-share/cma_init.h114
-rw-r--r--gdb/osf-share/cma_list.h84
-rw-r--r--gdb/osf-share/cma_mutex.h230
-rw-r--r--gdb/osf-share/cma_sched.h279
-rw-r--r--gdb/osf-share/cma_semaphore_defs.h46
-rw-r--r--gdb/osf-share/cma_sequence.h56
-rw-r--r--gdb/osf-share/cma_stack.h83
-rw-r--r--gdb/osf-share/cma_stack_int.h136
-rw-r--r--gdb/osf-share/cma_tcb_defs.h269
-rw-r--r--gdb/osf-share/cma_util.h125
-rw-r--r--gdb/osfsolib.c980
-rw-r--r--gdb/parse.c1351
-rw-r--r--gdb/parser-defs.h198
-rw-r--r--gdb/partial-stab.h812
-rw-r--r--gdb/ppc-bdm.c387
-rw-r--r--gdb/ppcbug-rom.c230
-rw-r--r--gdb/printcmd.c2575
-rw-r--r--gdb/process_reply.defs1
-rw-r--r--gdb/procfs.c5764
-rw-r--r--gdb/ptx4-nat.c209
-rw-r--r--gdb/pyr-tdep.c452
-rw-r--r--gdb/pyr-xdep.c370
-rw-r--r--gdb/rdi-share/Makefile.am19
-rw-r--r--gdb/rdi-share/Makefile.in293
-rw-r--r--gdb/rdi-share/README.CYGNUS6
-rw-r--r--gdb/rdi-share/aclocal.m4202
-rw-r--r--gdb/rdi-share/adp.h2528
-rw-r--r--gdb/rdi-share/adperr.h74
-rw-r--r--gdb/rdi-share/angel.h177
-rw-r--r--gdb/rdi-share/ardi.c2672
-rw-r--r--gdb/rdi-share/ardi.h85
-rw-r--r--gdb/rdi-share/armdbg.h1452
-rw-r--r--gdb/rdi-share/buffers.h111
-rw-r--r--gdb/rdi-share/bytesex.c57
-rw-r--r--gdb/rdi-share/bytesex.h42
-rw-r--r--gdb/rdi-share/chandefs.h50
-rw-r--r--gdb/rdi-share/channels.h384
-rw-r--r--gdb/rdi-share/chanpriv.h57
-rwxr-xr-xgdb/rdi-share/configure2115
-rw-r--r--gdb/rdi-share/configure.in36
-rw-r--r--gdb/rdi-share/crc.c257
-rw-r--r--gdb/rdi-share/crc.h90
-rw-r--r--gdb/rdi-share/dbg_conf.h54
-rw-r--r--gdb/rdi-share/dbg_cp.h62
-rw-r--r--gdb/rdi-share/dbg_hif.h56
-rw-r--r--gdb/rdi-share/dbg_rdi.h511
-rw-r--r--gdb/rdi-share/devclnt.h260
-rw-r--r--gdb/rdi-share/devices.h104
-rw-r--r--gdb/rdi-share/devsw.c404
-rw-r--r--gdb/rdi-share/devsw.h268
-rw-r--r--gdb/rdi-share/drivers.c34
-rw-r--r--gdb/rdi-share/drivers.h193
-rw-r--r--gdb/rdi-share/endian.h125
-rw-r--r--gdb/rdi-share/etherdrv.c730
-rw-r--r--gdb/rdi-share/ethernet.h99
-rw-r--r--gdb/rdi-share/host.h230
-rw-r--r--gdb/rdi-share/hostchan.c1057
-rw-r--r--gdb/rdi-share/hostchan.h308
-rw-r--r--gdb/rdi-share/hsys.c915
-rw-r--r--gdb/rdi-share/hsys.h101
-rw-r--r--gdb/rdi-share/logging.c369
-rw-r--r--gdb/rdi-share/logging.h121
-rw-r--r--gdb/rdi-share/msgbuild.c282
-rw-r--r--gdb/rdi-share/msgbuild.h75
-rw-r--r--gdb/rdi-share/params.c325
-rw-r--r--gdb/rdi-share/params.h181
-rw-r--r--gdb/rdi-share/rx.c361
-rw-r--r--gdb/rdi-share/rxtx.h263
-rw-r--r--gdb/rdi-share/serdrv.c649
-rw-r--r--gdb/rdi-share/serpardr.c730
-rw-r--r--gdb/rdi-share/sys.h319
-rw-r--r--gdb/rdi-share/tx.c176
-rw-r--r--gdb/rdi-share/unixcomm.c552
-rw-r--r--gdb/rdi-share/unixcomm.h212
-rw-r--r--gdb/remote-adapt.c1443
-rw-r--r--gdb/remote-array.c1497
-rw-r--r--gdb/remote-bug.c1099
-rw-r--r--gdb/remote-d10v.c228
-rw-r--r--gdb/remote-e7000.c2258
-rw-r--r--gdb/remote-eb.c1056
-rw-r--r--gdb/remote-es.c2202
-rw-r--r--gdb/remote-est.c171
-rw-r--r--gdb/remote-hms.c1500
-rw-r--r--gdb/remote-mips.c3655
-rw-r--r--gdb/remote-mm.c1673
-rw-r--r--gdb/remote-nindy.c852
-rw-r--r--gdb/remote-nrom.c360
-rw-r--r--gdb/remote-os9k.c1264
-rw-r--r--gdb/remote-rdi.c973
-rw-r--r--gdb/remote-rdp.c1512
-rw-r--r--gdb/remote-sds.c1206
-rw-r--r--gdb/remote-sim.c1003
-rw-r--r--gdb/remote-st.c879
-rw-r--r--gdb/remote-udi.c1694
-rw-r--r--gdb/remote-utils.c654
-rw-r--r--gdb/remote-utils.h142
-rw-r--r--gdb/remote-vx.c1467
-rw-r--r--gdb/remote-vx29k.c188
-rw-r--r--gdb/remote-vx68.c158
-rw-r--r--gdb/remote-vx960.c163
-rw-r--r--gdb/remote-vxmips.c201
-rw-r--r--gdb/remote-vxsparc.c196
-rw-r--r--gdb/remote.c3473
-rw-r--r--gdb/reply_mig_hack.awk123
-rw-r--r--gdb/rom68k-rom.c169
-rw-r--r--gdb/rs6000-nat.c845
-rw-r--r--gdb/rs6000-tdep.c1800
-rw-r--r--gdb/saber.suppress451
-rw-r--r--gdb/scm-exp.c423
-rw-r--r--gdb/scm-lang.c274
-rw-r--r--gdb/scm-lang.h50
-rw-r--r--gdb/scm-tags.h385
-rw-r--r--gdb/scm-valprint.c422
-rw-r--r--gdb/ser-e7kpc.c470
-rw-r--r--gdb/ser-go32.c958
-rw-r--r--gdb/ser-mac.c362
-rw-r--r--gdb/ser-ocd.c209
-rw-r--r--gdb/ser-tcp.c358
-rw-r--r--gdb/ser-unix.c808
-rw-r--r--gdb/serial.c526
-rw-r--r--gdb/serial.h191
-rw-r--r--gdb/sh-stub.c1549
-rw-r--r--gdb/sh-tdep.c728
-rw-r--r--gdb/sh3-rom.c392
-rw-r--r--gdb/signals.h27
-rw-r--r--gdb/sol-thread.c1673
-rw-r--r--gdb/solib.c1888
-rw-r--r--gdb/solib.h203
-rw-r--r--gdb/somread.c803
-rw-r--r--gdb/somsolib.c1640
-rw-r--r--gdb/somsolib.h177
-rw-r--r--gdb/source.c1724
-rw-r--r--gdb/sparc-nat.c328
-rw-r--r--gdb/sparc-stub.c846
-rw-r--r--gdb/sparc-tdep.c2120
-rw-r--r--gdb/sparcl-stub.c1024
-rw-r--r--gdb/sparcl-tdep.c970
-rw-r--r--gdb/sparclet-rom.c296
-rw-r--r--gdb/sparclet-stub.c1232
-rw-r--r--gdb/srec.h36
-rw-r--r--gdb/stabsread.c5207
-rw-r--r--gdb/stabsread.h249
-rw-r--r--gdb/stack.c2019
-rw-r--r--gdb/standalone.c593
-rw-r--r--gdb/stop-gdb.c110
-rw-r--r--gdb/stuff.c174
-rw-r--r--gdb/sun3-nat.c157
-rw-r--r--gdb/sun386-nat.c258
-rw-r--r--gdb/symfile.c3021
-rw-r--r--gdb/symfile.h300
-rw-r--r--gdb/symm-nat.c846
-rw-r--r--gdb/symm-tdep.c93
-rw-r--r--gdb/symmisc.c1098
-rw-r--r--gdb/symtab.c4518
-rw-r--r--gdb/symtab.h1477
-rw-r--r--gdb/tahoe-tdep.c234
-rw-r--r--gdb/target.c2581
-rw-r--r--gdb/target.h1264
-rw-r--r--gdb/terminal.h92
-rw-r--r--gdb/testsuite/.gdbinit1
-rw-r--r--gdb/testsuite/ChangeLog5930
-rw-r--r--gdb/testsuite/Makefile.in187
-rw-r--r--gdb/testsuite/TODO202
-rw-r--r--gdb/testsuite/aclocal.m4583
-rw-r--r--gdb/testsuite/config/abug.exp20
-rw-r--r--gdb/testsuite/config/arm-ice.exp1
-rw-r--r--gdb/testsuite/config/cpu32bug.exp20
-rw-r--r--gdb/testsuite/config/cygmon.exp1
-rw-r--r--gdb/testsuite/config/d10v.exp20
-rw-r--r--gdb/testsuite/config/dve.exp23
-rw-r--r--gdb/testsuite/config/est.exp20
-rw-r--r--gdb/testsuite/config/gdbserver.exp104
-rw-r--r--gdb/testsuite/config/h8300.exp1
-rw-r--r--gdb/testsuite/config/hmsirom.exp22
-rw-r--r--gdb/testsuite/config/hppro.exp24
-rw-r--r--gdb/testsuite/config/i386-bozo.exp1
-rw-r--r--gdb/testsuite/config/i960.exp20
-rw-r--r--gdb/testsuite/config/m32r-stub.exp1
-rw-r--r--gdb/testsuite/config/m32r.exp23
-rw-r--r--gdb/testsuite/config/m68k-emc.exp17
-rw-r--r--gdb/testsuite/config/mips-idt.exp22
-rw-r--r--gdb/testsuite/config/mips.exp22
-rw-r--r--gdb/testsuite/config/mn10300-eval.exp23
-rw-r--r--gdb/testsuite/config/monitor.exp230
-rw-r--r--gdb/testsuite/config/mt-a29k-udi0
-rw-r--r--gdb/testsuite/config/mt-i386-aout59
-rw-r--r--gdb/testsuite/config/mt-i960-nindy1
-rw-r--r--gdb/testsuite/config/mt-lynx4
-rw-r--r--gdb/testsuite/config/mt-m68k1
-rw-r--r--gdb/testsuite/config/mt-mips-ecoff2
-rw-r--r--gdb/testsuite/config/mt-netware1
-rw-r--r--gdb/testsuite/config/mt-slite8
-rw-r--r--gdb/testsuite/config/mt-sparc-aout0
-rw-r--r--gdb/testsuite/config/mt-unix1
-rw-r--r--gdb/testsuite/config/mt-vxworks2
-rw-r--r--gdb/testsuite/config/netware.exp218
-rw-r--r--gdb/testsuite/config/nind.exp49
-rw-r--r--gdb/testsuite/config/proelf.exp20
-rw-r--r--gdb/testsuite/config/rom68k.exp20
-rw-r--r--gdb/testsuite/config/sh.exp20
-rw-r--r--gdb/testsuite/config/sim.exp85
-rw-r--r--gdb/testsuite/config/slite.exp183
-rw-r--r--gdb/testsuite/config/sparclet.exp391
-rw-r--r--gdb/testsuite/config/udi.exp112
-rw-r--r--gdb/testsuite/config/unix.exp29
-rw-r--r--gdb/testsuite/config/unknown.exp21
-rw-r--r--gdb/testsuite/config/vr4300.exp20
-rw-r--r--gdb/testsuite/config/vr5000.exp20
-rw-r--r--gdb/testsuite/config/vx.exp130
-rw-r--r--gdb/testsuite/config/vxworks.exp20
-rw-r--r--gdb/testsuite/config/vxworks29k.exp27
-rwxr-xr-xgdb/testsuite/configure1058
-rw-r--r--gdb/testsuite/configure.in72
-rw-r--r--gdb/testsuite/gdb.asm/Makefile.in33
-rw-r--r--gdb/testsuite/gdb.asm/asm-source.exp99
-rw-r--r--gdb/testsuite/gdb.asm/asmsrc1.s37
-rw-r--r--gdb/testsuite/gdb.asm/asmsrc2.s16
-rw-r--r--gdb/testsuite/gdb.asm/common.inc18
-rwxr-xr-xgdb/testsuite/gdb.asm/configure950
-rw-r--r--gdb/testsuite/gdb.asm/configure.in22
-rw-r--r--gdb/testsuite/gdb.asm/d10v.inc28
-rw-r--r--gdb/testsuite/gdb.base/Makefile.in46
-rw-r--r--gdb/testsuite/gdb.base/README13
-rw-r--r--gdb/testsuite/gdb.base/a1-selftest.exp426
-rw-r--r--gdb/testsuite/gdb.base/a2-run.exp253
-rw-r--r--gdb/testsuite/gdb.base/all-bin.exp467
-rw-r--r--gdb/testsuite/gdb.base/all-types.c62
-rw-r--r--gdb/testsuite/gdb.base/arithmet.exp375
-rw-r--r--gdb/testsuite/gdb.base/assign.exp446
-rw-r--r--gdb/testsuite/gdb.base/bar.c9
-rw-r--r--gdb/testsuite/gdb.base/baz.c9
-rw-r--r--gdb/testsuite/gdb.base/bitfields.c194
-rw-r--r--gdb/testsuite/gdb.base/bitfields.exp268
-rw-r--r--gdb/testsuite/gdb.base/bitops.exp365
-rw-r--r--gdb/testsuite/gdb.base/branches.c113
-rw-r--r--gdb/testsuite/gdb.base/break.c81
-rw-r--r--gdb/testsuite/gdb.base/break.exp769
-rw-r--r--gdb/testsuite/gdb.base/call-ar-st.c1137
-rw-r--r--gdb/testsuite/gdb.base/call-ar-st.exp451
-rw-r--r--gdb/testsuite/gdb.base/call-rt-st.c530
-rw-r--r--gdb/testsuite/gdb.base/call-rt-st.exp230
-rw-r--r--gdb/testsuite/gdb.base/call-strs.c54
-rw-r--r--gdb/testsuite/gdb.base/call-strs.exp242
-rw-r--r--gdb/testsuite/gdb.base/callfuncs.c280
-rw-r--r--gdb/testsuite/gdb.base/callfuncs.exp269
-rw-r--r--gdb/testsuite/gdb.base/callfuncs2.c267
-rw-r--r--gdb/testsuite/gdb.base/callfuncs2.exp276
-rw-r--r--gdb/testsuite/gdb.base/commands.exp248
-rw-r--r--gdb/testsuite/gdb.base/compiler.c31
-rw-r--r--gdb/testsuite/gdb.base/completion.exp568
-rw-r--r--gdb/testsuite/gdb.base/cond-expr.exp122
-rw-r--r--gdb/testsuite/gdb.base/condbreak.c81
-rw-r--r--gdb/testsuite/gdb.base/condbreak.exp157
-rw-r--r--gdb/testsuite/gdb.base/configure899
-rw-r--r--gdb/testsuite/gdb.base/configure.in15
-rw-r--r--gdb/testsuite/gdb.base/constvars.c183
-rw-r--r--gdb/testsuite/gdb.base/constvars.exp251
-rw-r--r--gdb/testsuite/gdb.base/corefile.exp223
-rw-r--r--gdb/testsuite/gdb.base/coremaker.c120
-rw-r--r--gdb/testsuite/gdb.base/crossload.exp380
-rw-r--r--gdb/testsuite/gdb.base/d10v.ld155
-rw-r--r--gdb/testsuite/gdb.base/d10vovly.c225
-rw-r--r--gdb/testsuite/gdb.base/default.exp793
-rw-r--r--gdb/testsuite/gdb.base/define.exp304
-rw-r--r--gdb/testsuite/gdb.base/display.c52
-rw-r--r--gdb/testsuite/gdb.base/display.exp147
-rw-r--r--gdb/testsuite/gdb.base/dollar.exp128
-rw-r--r--gdb/testsuite/gdb.base/echo.exp44
-rw-r--r--gdb/testsuite/gdb.base/ena-dis-br.exp525
-rw-r--r--gdb/testsuite/gdb.base/ending-run.c27
-rw-r--r--gdb/testsuite/gdb.base/ending-run.exp176
-rw-r--r--gdb/testsuite/gdb.base/environ.exp329
-rw-r--r--gdb/testsuite/gdb.base/eval-skip.exp352
-rw-r--r--gdb/testsuite/gdb.base/exprs.c253
-rw-r--r--gdb/testsuite/gdb.base/exprs.exp222
-rw-r--r--gdb/testsuite/gdb.base/foo.c9
-rw-r--r--gdb/testsuite/gdb.base/funcargs.c582
-rw-r--r--gdb/testsuite/gdb.base/funcargs.exp1017
-rw-r--r--gdb/testsuite/gdb.base/gdbvars.exp117
-rw-r--r--gdb/testsuite/gdb.base/grbx.c10
-rw-r--r--gdb/testsuite/gdb.base/help.exp542
-rw-r--r--gdb/testsuite/gdb.base/i486-elf.u287
-rw-r--r--gdb/testsuite/gdb.base/i860-elf.u314
-rw-r--r--gdb/testsuite/gdb.base/int-type.c25
-rw-r--r--gdb/testsuite/gdb.base/interrupt.c37
-rw-r--r--gdb/testsuite/gdb.base/interrupt.exp175
-rw-r--r--gdb/testsuite/gdb.base/jump.c19
-rw-r--r--gdb/testsuite/gdb.base/jump.exp192
-rw-r--r--gdb/testsuite/gdb.base/langs.exp122
-rw-r--r--gdb/testsuite/gdb.base/langs0.c28
-rw-r--r--gdb/testsuite/gdb.base/langs1.c33
-rw-r--r--gdb/testsuite/gdb.base/langs1.f7
-rw-r--r--gdb/testsuite/gdb.base/langs2.c15
-rw-r--r--gdb/testsuite/gdb.base/langs2.cxx13
-rw-r--r--gdb/testsuite/gdb.base/list.exp521
-rw-r--r--gdb/testsuite/gdb.base/list0.c42
-rw-r--r--gdb/testsuite/gdb.base/list0.h36
-rw-r--r--gdb/testsuite/gdb.base/list1.c33
-rw-r--r--gdb/testsuite/gdb.base/logical.exp575
-rw-r--r--gdb/testsuite/gdb.base/long_long.c55
-rw-r--r--gdb/testsuite/gdb.base/long_long.exp163
-rw-r--r--gdb/testsuite/gdb.base/m32r.ld160
-rw-r--r--gdb/testsuite/gdb.base/m32rovly.c225
-rw-r--r--gdb/testsuite/gdb.base/m68k-aout.u459
-rw-r--r--gdb/testsuite/gdb.base/m68k-aout2.u2208
-rw-r--r--gdb/testsuite/gdb.base/m68k-elf.u298
-rw-r--r--gdb/testsuite/gdb.base/maint.exp578
-rw-r--r--gdb/testsuite/gdb.base/mips-ecoff.u671
-rw-r--r--gdb/testsuite/gdb.base/mips_pro.c35
-rw-r--r--gdb/testsuite/gdb.base/mips_pro.exp62
-rw-r--r--gdb/testsuite/gdb.base/miscexprs.c165
-rw-r--r--gdb/testsuite/gdb.base/miscexprs.exp283
-rw-r--r--gdb/testsuite/gdb.base/nodebug.c58
-rw-r--r--gdb/testsuite/gdb.base/nodebug.exp163
-rw-r--r--gdb/testsuite/gdb.base/opaque.exp244
-rw-r--r--gdb/testsuite/gdb.base/opaque0.c20
-rw-r--r--gdb/testsuite/gdb.base/opaque1.c18
-rw-r--r--gdb/testsuite/gdb.base/overlays.c34
-rw-r--r--gdb/testsuite/gdb.base/overlays.exp246
-rw-r--r--gdb/testsuite/gdb.base/ovlymgr.c225
-rw-r--r--gdb/testsuite/gdb.base/ovlymgr.h17
-rw-r--r--gdb/testsuite/gdb.base/pointers.c176
-rw-r--r--gdb/testsuite/gdb.base/pointers.exp358
-rw-r--r--gdb/testsuite/gdb.base/pointers2.c51
-rw-r--r--gdb/testsuite/gdb.base/pointers2.exp288
-rw-r--r--gdb/testsuite/gdb.base/printcmds.c101
-rw-r--r--gdb/testsuite/gdb.base/printcmds.exp695
-rw-r--r--gdb/testsuite/gdb.base/ptype.c313
-rw-r--r--gdb/testsuite/gdb.base/ptype.exp532
-rw-r--r--gdb/testsuite/gdb.base/radix.exp201
-rw-r--r--gdb/testsuite/gdb.base/recurse.c25
-rw-r--r--gdb/testsuite/gdb.base/recurse.exp145
-rw-r--r--gdb/testsuite/gdb.base/regs.exp86
-rw-r--r--gdb/testsuite/gdb.base/relational.exp481
-rw-r--r--gdb/testsuite/gdb.base/reread.exp117
-rw-r--r--gdb/testsuite/gdb.base/reread1.c26
-rw-r--r--gdb/testsuite/gdb.base/reread2.c21
-rw-r--r--gdb/testsuite/gdb.base/restore.c260
-rw-r--r--gdb/testsuite/gdb.base/restore.exp111
-rw-r--r--gdb/testsuite/gdb.base/return.c35
-rw-r--r--gdb/testsuite/gdb.base/return.exp124
-rw-r--r--gdb/testsuite/gdb.base/run.c67
-rw-r--r--gdb/testsuite/gdb.base/scope.exp610
-rw-r--r--gdb/testsuite/gdb.base/scope0.c176
-rw-r--r--gdb/testsuite/gdb.base/scope1.c45
-rw-r--r--gdb/testsuite/gdb.base/sect-cmd.exp109
-rw-r--r--gdb/testsuite/gdb.base/setshow.c22
-rw-r--r--gdb/testsuite/gdb.base/setshow.exp243
-rw-r--r--gdb/testsuite/gdb.base/setvar.c271
-rw-r--r--gdb/testsuite/gdb.base/setvar.exp420
-rw-r--r--gdb/testsuite/gdb.base/shlib-call.exp258
-rw-r--r--gdb/testsuite/gdb.base/shmain.c47
-rw-r--r--gdb/testsuite/gdb.base/shr1.c47
-rw-r--r--gdb/testsuite/gdb.base/shr2.c11
-rw-r--r--gdb/testsuite/gdb.base/sigall.c1383
-rw-r--r--gdb/testsuite/gdb.base/sigall.exp210
-rw-r--r--gdb/testsuite/gdb.base/signals.c53
-rw-r--r--gdb/testsuite/gdb.base/signals.exp628
-rw-r--r--gdb/testsuite/gdb.base/smoke.c40
-rw-r--r--gdb/testsuite/gdb.base/smoke.cc480
-rw-r--r--gdb/testsuite/gdb.base/smoke.exp181
-rw-r--r--gdb/testsuite/gdb.base/so-impl-ld.c18
-rw-r--r--gdb/testsuite/gdb.base/so-impl-ld.exp167
-rw-r--r--gdb/testsuite/gdb.base/so-indr-cl.c23
-rw-r--r--gdb/testsuite/gdb.base/so-indr-cl.exp146
-rw-r--r--gdb/testsuite/gdb.base/solib.c59
-rw-r--r--gdb/testsuite/gdb.base/solib.exp319
-rw-r--r--gdb/testsuite/gdb.base/solib1.c9
-rw-r--r--gdb/testsuite/gdb.base/solib2.c9
-rw-r--r--gdb/testsuite/gdb.base/sparc-aout.u732
-rw-r--r--gdb/testsuite/gdb.base/sparc-elf.u336
-rw-r--r--gdb/testsuite/gdb.base/ss.h4
-rw-r--r--gdb/testsuite/gdb.base/step-test.c58
-rw-r--r--gdb/testsuite/gdb.base/step-test.exp153
-rw-r--r--gdb/testsuite/gdb.base/structs2.c38
-rw-r--r--gdb/testsuite/gdb.base/structs2.exp79
-rw-r--r--gdb/testsuite/gdb.base/term.exp73
-rw-r--r--gdb/testsuite/gdb.base/twice.c19
-rw-r--r--gdb/testsuite/gdb.base/twice.exp63
-rw-r--r--gdb/testsuite/gdb.base/varargs.c108
-rw-r--r--gdb/testsuite/gdb.base/varargs.exp139
-rw-r--r--gdb/testsuite/gdb.base/volatile.exp243
-rw-r--r--gdb/testsuite/gdb.base/watchpoint.c124
-rw-r--r--gdb/testsuite/gdb.base/watchpoint.exp583
-rw-r--r--gdb/testsuite/gdb.base/whatis-exp.exp217
-rw-r--r--gdb/testsuite/gdb.base/whatis.c269
-rw-r--r--gdb/testsuite/gdb.base/whatis.exp393
-rw-r--r--gdb/testsuite/gdb.c++/Makefile.in20
-rw-r--r--gdb/testsuite/gdb.c++/anon-union.cc54
-rw-r--r--gdb/testsuite/gdb.c++/anon-union.exp337
-rw-r--r--gdb/testsuite/gdb.c++/classes.exp850
-rw-r--r--gdb/testsuite/gdb.c++/compiler.cc34
-rw-r--r--gdb/testsuite/gdb.c++/configure899
-rw-r--r--gdb/testsuite/gdb.c++/configure.in15
-rw-r--r--gdb/testsuite/gdb.c++/cplusfuncs.cc185
-rw-r--r--gdb/testsuite/gdb.c++/cplusfuncs.exp300
-rw-r--r--gdb/testsuite/gdb.c++/demangle.exp1517
-rw-r--r--gdb/testsuite/gdb.c++/derivation.cc240
-rw-r--r--gdb/testsuite/gdb.c++/derivation.exp316
-rw-r--r--gdb/testsuite/gdb.c++/inherit.exp859
-rw-r--r--gdb/testsuite/gdb.c++/local.cc67
-rw-r--r--gdb/testsuite/gdb.c++/local.exp110
-rw-r--r--gdb/testsuite/gdb.c++/member-ptr.cc106
-rw-r--r--gdb/testsuite/gdb.c++/member-ptr.exp510
-rw-r--r--gdb/testsuite/gdb.c++/method.cc80
-rw-r--r--gdb/testsuite/gdb.c++/method.exp233
-rw-r--r--gdb/testsuite/gdb.c++/misc.cc517
-rw-r--r--gdb/testsuite/gdb.c++/misc.exp106
-rw-r--r--gdb/testsuite/gdb.c++/overload.cc151
-rw-r--r--gdb/testsuite/gdb.c++/overload.exp338
-rw-r--r--gdb/testsuite/gdb.c++/ovldbreak.cc177
-rw-r--r--gdb/testsuite/gdb.c++/ovldbreak.exp680
-rw-r--r--gdb/testsuite/gdb.c++/ref-types.cc30
-rw-r--r--gdb/testsuite/gdb.c++/ref-types.exp276
-rw-r--r--gdb/testsuite/gdb.c++/ref-types2.cc47
-rw-r--r--gdb/testsuite/gdb.c++/ref-types2.exp450
-rw-r--r--gdb/testsuite/gdb.c++/templates.cc785
-rw-r--r--gdb/testsuite/gdb.c++/templates.exp202
-rw-r--r--gdb/testsuite/gdb.c++/userdef.cc339
-rw-r--r--gdb/testsuite/gdb.c++/userdef.exp317
-rw-r--r--gdb/testsuite/gdb.c++/virtfunc.cc199
-rw-r--r--gdb/testsuite/gdb.c++/virtfunc.exp751
-rw-r--r--gdb/testsuite/gdb.chill/ChangeLog313
-rw-r--r--gdb/testsuite/gdb.chill/Makefile.in26
-rw-r--r--gdb/testsuite/gdb.chill/builtins.ch83
-rw-r--r--gdb/testsuite/gdb.chill/builtins.exp441
-rw-r--r--gdb/testsuite/gdb.chill/callch.ch50
-rw-r--r--gdb/testsuite/gdb.chill/callch.exp69
-rw-r--r--gdb/testsuite/gdb.chill/chexp.exp450
-rw-r--r--gdb/testsuite/gdb.chill/chillvars.ch204
-rw-r--r--gdb/testsuite/gdb.chill/chillvars.exp316
-rwxr-xr-xgdb/testsuite/gdb.chill/configure899
-rw-r--r--gdb/testsuite/gdb.chill/configure.in11
-rw-r--r--gdb/testsuite/gdb.chill/enum.ch9
-rw-r--r--gdb/testsuite/gdb.chill/enum.exp85
-rw-r--r--gdb/testsuite/gdb.chill/extstruct-grt.ch12
-rw-r--r--gdb/testsuite/gdb.chill/extstruct.ch16
-rw-r--r--gdb/testsuite/gdb.chill/extstruct.exp66
-rw-r--r--gdb/testsuite/gdb.chill/func1.ch9
-rw-r--r--gdb/testsuite/gdb.chill/gch1041.ch17
-rw-r--r--gdb/testsuite/gdb.chill/gch1041.exp76
-rw-r--r--gdb/testsuite/gdb.chill/gch1272.ch21
-rw-r--r--gdb/testsuite/gdb.chill/gch1272.exp86
-rw-r--r--gdb/testsuite/gdb.chill/gch1280.ch13
-rw-r--r--gdb/testsuite/gdb.chill/gch1280.exp76
-rw-r--r--gdb/testsuite/gdb.chill/gch922.ch23
-rw-r--r--gdb/testsuite/gdb.chill/gch922.exp183
-rw-r--r--gdb/testsuite/gdb.chill/gch981.ch60
-rw-r--r--gdb/testsuite/gdb.chill/gch981.exp249
-rw-r--r--gdb/testsuite/gdb.chill/misc.ch12
-rw-r--r--gdb/testsuite/gdb.chill/misc.exp100
-rw-r--r--gdb/testsuite/gdb.chill/powerset.ch33
-rw-r--r--gdb/testsuite/gdb.chill/powerset.exp187
-rw-r--r--gdb/testsuite/gdb.chill/pr-4975-grt.ch13
-rw-r--r--gdb/testsuite/gdb.chill/pr-4975.ch43
-rw-r--r--gdb/testsuite/gdb.chill/pr-4975.exp67
-rw-r--r--gdb/testsuite/gdb.chill/pr-5016.ch24
-rw-r--r--gdb/testsuite/gdb.chill/pr-5016.exp62
-rw-r--r--gdb/testsuite/gdb.chill/pr-5020.ch19
-rw-r--r--gdb/testsuite/gdb.chill/pr-5020.exp85
-rw-r--r--gdb/testsuite/gdb.chill/pr-5022.ch12
-rw-r--r--gdb/testsuite/gdb.chill/pr-5022.exp70
-rw-r--r--gdb/testsuite/gdb.chill/pr-5646-grt.ch5
-rw-r--r--gdb/testsuite/gdb.chill/pr-5646.ch15
-rw-r--r--gdb/testsuite/gdb.chill/pr-5646.exp64
-rw-r--r--gdb/testsuite/gdb.chill/pr-5984.ch8
-rw-r--r--gdb/testsuite/gdb.chill/pr-5984.exp57
-rw-r--r--gdb/testsuite/gdb.chill/pr-6292.ch17
-rw-r--r--gdb/testsuite/gdb.chill/pr-6292.exp58
-rw-r--r--gdb/testsuite/gdb.chill/pr-6632-grt.ch34
-rw-r--r--gdb/testsuite/gdb.chill/pr-6632.ch31
-rw-r--r--gdb/testsuite/gdb.chill/pr-6632.exp66
-rw-r--r--gdb/testsuite/gdb.chill/pr-8134.exp65
-rw-r--r--gdb/testsuite/gdb.chill/pr-8136.ch34
-rw-r--r--gdb/testsuite/gdb.chill/pr-8136.exp63
-rw-r--r--gdb/testsuite/gdb.chill/pr-8405.ch19
-rw-r--r--gdb/testsuite/gdb.chill/pr-8405.exp61
-rw-r--r--gdb/testsuite/gdb.chill/pr-8742.ch32
-rw-r--r--gdb/testsuite/gdb.chill/pr-8742.exp64
-rw-r--r--gdb/testsuite/gdb.chill/pr-8894-grt.ch6
-rw-r--r--gdb/testsuite/gdb.chill/pr-8894.ch12
-rw-r--r--gdb/testsuite/gdb.chill/pr-8894.exp61
-rw-r--r--gdb/testsuite/gdb.chill/pr-9095.ch13
-rw-r--r--gdb/testsuite/gdb.chill/pr-9095.exp62
-rw-r--r--gdb/testsuite/gdb.chill/pr-9946.ch10
-rw-r--r--gdb/testsuite/gdb.chill/pr-9946.exp79
-rw-r--r--gdb/testsuite/gdb.chill/result.ch29
-rw-r--r--gdb/testsuite/gdb.chill/result.exp77
-rw-r--r--gdb/testsuite/gdb.chill/string.ch24
-rw-r--r--gdb/testsuite/gdb.chill/string.exp73
-rw-r--r--gdb/testsuite/gdb.chill/tests1.ch240
-rw-r--r--gdb/testsuite/gdb.chill/tests1.exp822
-rw-r--r--gdb/testsuite/gdb.chill/tests2.ch193
-rw-r--r--gdb/testsuite/gdb.chill/tests2.exp271
-rw-r--r--gdb/testsuite/gdb.chill/tuples.ch86
-rw-r--r--gdb/testsuite/gdb.chill/tuples.exp161
-rw-r--r--gdb/testsuite/gdb.disasm/Makefile.in20
-rw-r--r--gdb/testsuite/gdb.disasm/configure899
-rw-r--r--gdb/testsuite/gdb.disasm/configure.in15
-rw-r--r--gdb/testsuite/gdb.disasm/hppa.exp1403
-rw-r--r--gdb/testsuite/gdb.disasm/hppa.s1738
-rw-r--r--gdb/testsuite/gdb.disasm/mn10200.exp478
-rw-r--r--gdb/testsuite/gdb.disasm/mn10200.s217
-rw-r--r--gdb/testsuite/gdb.disasm/mn10300.exp569
-rw-r--r--gdb/testsuite/gdb.disasm/mn10300.s300
-rw-r--r--gdb/testsuite/gdb.disasm/sh3.exp123
-rw-r--r--gdb/testsuite/gdb.disasm/sh3.s54
-rw-r--r--gdb/testsuite/gdb.fortran/exprs.exp273
-rw-r--r--gdb/testsuite/gdb.fortran/types.exp114
-rw-r--r--gdb/testsuite/gdb.hp/Makefile.in25
-rw-r--r--gdb/testsuite/gdb.hp/ambiguous.cc110
-rw-r--r--gdb/testsuite/gdb.hp/ambiguous.exp216
-rw-r--r--gdb/testsuite/gdb.hp/attach.c19
-rw-r--r--gdb/testsuite/gdb.hp/attach.exp416
-rw-r--r--gdb/testsuite/gdb.hp/attach2.c23
-rw-r--r--gdb/testsuite/gdb.hp/attach2.exp263
-rw-r--r--gdb/testsuite/gdb.hp/average.c39
-rw-r--r--gdb/testsuite/gdb.hp/classes-hp.exp859
-rw-r--r--gdb/testsuite/gdb.hp/compiler.c31
-rw-r--r--gdb/testsuite/gdb.hp/compiler.cc34
-rw-r--r--gdb/testsuite/gdb.hp/ctti-add.cc29
-rw-r--r--gdb/testsuite/gdb.hp/ctti-add1.cc16
-rw-r--r--gdb/testsuite/gdb.hp/ctti-add2.cc22
-rw-r--r--gdb/testsuite/gdb.hp/ctti-add3.cc33
-rw-r--r--gdb/testsuite/gdb.hp/ctti.exp269
-rw-r--r--gdb/testsuite/gdb.hp/dbx.exp222
-rw-r--r--gdb/testsuite/gdb.hp/exception.cc48
-rw-r--r--gdb/testsuite/gdb.hp/exception.exp408
-rw-r--r--gdb/testsuite/gdb.hp/execd-program.c28
-rw-r--r--gdb/testsuite/gdb.hp/foll-exec.c35
-rw-r--r--gdb/testsuite/gdb.hp/foll-exec.exp412
-rw-r--r--gdb/testsuite/gdb.hp/foll-fork.c25
-rw-r--r--gdb/testsuite/gdb.hp/foll-fork.exp385
-rw-r--r--gdb/testsuite/gdb.hp/foll-vfork.c15
-rw-r--r--gdb/testsuite/gdb.hp/foll-vfork.exp381
-rw-r--r--gdb/testsuite/gdb.hp/gen-so-thresh.c229
-rw-r--r--gdb/testsuite/gdb.hp/hwwatchbus.c9
-rw-r--r--gdb/testsuite/gdb.hp/hwwatchbus.exp84
-rw-r--r--gdb/testsuite/gdb.hp/inherit-hp.exp849
-rw-r--r--gdb/testsuite/gdb.hp/misc-hp.cc514
-rw-r--r--gdb/testsuite/gdb.hp/more-steps.c140
-rw-r--r--gdb/testsuite/gdb.hp/more-steps.exp152
-rw-r--r--gdb/testsuite/gdb.hp/namespace.cc103
-rw-r--r--gdb/testsuite/gdb.hp/namespace.exp195
-rw-r--r--gdb/testsuite/gdb.hp/optimize.c76
-rw-r--r--gdb/testsuite/gdb.hp/optimize.exp144
-rw-r--r--gdb/testsuite/gdb.hp/pxdb.c20
-rw-r--r--gdb/testsuite/gdb.hp/pxdb.exp114
-rw-r--r--gdb/testsuite/gdb.hp/quicksort.c284
-rw-r--r--gdb/testsuite/gdb.hp/quicksort.exp809
-rw-r--r--gdb/testsuite/gdb.hp/reg-test.exp190
-rw-r--r--gdb/testsuite/gdb.hp/reg-test.s96
-rw-r--r--gdb/testsuite/gdb.hp/run-hp.c70
-rw-r--r--gdb/testsuite/gdb.hp/sized-enum.c43
-rw-r--r--gdb/testsuite/gdb.hp/sized-enum.exp162
-rw-r--r--gdb/testsuite/gdb.hp/so-thresh.exp362
-rw-r--r--gdb/testsuite/gdb.hp/so-thresh.linkopts5
-rw-r--r--gdb/testsuite/gdb.hp/so-thresh.mk73
-rwxr-xr-xgdb/testsuite/gdb.hp/so-thresh.sh12
-rw-r--r--gdb/testsuite/gdb.hp/start-stop.c161
-rw-r--r--gdb/testsuite/gdb.hp/start-stop.exp360
-rw-r--r--gdb/testsuite/gdb.hp/sum.c15
-rw-r--r--gdb/testsuite/gdb.hp/templ-hp.cc785
-rw-r--r--gdb/testsuite/gdb.hp/templ-hp.exp381
-rw-r--r--gdb/testsuite/gdb.hp/thr-lib.c79
-rw-r--r--gdb/testsuite/gdb.hp/thr-lib.exp234
-rw-r--r--gdb/testsuite/gdb.hp/thr-lib.h7
-rw-r--r--gdb/testsuite/gdb.hp/thr-liblib.c92
-rw-r--r--gdb/testsuite/gdb.hp/thr-stg.exp255
-rw-r--r--gdb/testsuite/gdb.hp/vforked-program.c6
-rw-r--r--gdb/testsuite/gdb.hp/virtfun-hp.cc192
-rw-r--r--gdb/testsuite/gdb.hp/virtfun-hp.exp773
-rw-r--r--gdb/testsuite/gdb.hp/watch-cmd.exp165
-rw-r--r--gdb/testsuite/gdb.hp/watch-hp.c166
-rw-r--r--gdb/testsuite/gdb.hp/watch-hp.exp784
-rw-r--r--gdb/testsuite/gdb.hp/xdb.c20
-rw-r--r--gdb/testsuite/gdb.hp/xdb0.c42
-rw-r--r--gdb/testsuite/gdb.hp/xdb0.h36
-rw-r--r--gdb/testsuite/gdb.hp/xdb1.c33
-rw-r--r--gdb/testsuite/gdb.hp/xdb1.exp77
-rw-r--r--gdb/testsuite/gdb.hp/xdb2.exp104
-rw-r--r--gdb/testsuite/gdb.hp/xdb3.exp307
-rw-r--r--gdb/testsuite/gdb.stabs/Makefile.in16
-rw-r--r--gdb/testsuite/gdb.stabs/aout.sed16
-rwxr-xr-xgdb/testsuite/gdb.stabs/configure899
-rw-r--r--gdb/testsuite/gdb.stabs/configure.in15
-rw-r--r--gdb/testsuite/gdb.stabs/ecoff.sed17
-rw-r--r--gdb/testsuite/gdb.stabs/hppa.sed20
-rw-r--r--gdb/testsuite/gdb.stabs/weird.def939
-rw-r--r--gdb/testsuite/gdb.stabs/weird.exp325
-rw-r--r--gdb/testsuite/gdb.stabs/xcoff.sed17
-rw-r--r--gdb/testsuite/gdb.threads/Makefile.in31
-rw-r--r--gdb/testsuite/gdb.threads/config.in4
-rwxr-xr-xgdb/testsuite/gdb.threads/configure1098
-rw-r--r--gdb/testsuite/gdb.threads/configure.in18
-rw-r--r--gdb/testsuite/gdb.threads/pthreads.c168
-rw-r--r--gdb/testsuite/gdb.threads/pthreads.exp328
-rw-r--r--gdb/testsuite/gdb.threads/step.c221
-rw-r--r--gdb/testsuite/gdb.threads/step.exp200
-rw-r--r--gdb/testsuite/gdb.threads/step2.exp150
-rw-r--r--gdb/testsuite/gdb.trace/Makefile.in21
-rw-r--r--gdb/testsuite/gdb.trace/actions.c134
-rw-r--r--gdb/testsuite/gdb.trace/actions.exp207
-rw-r--r--gdb/testsuite/gdb.trace/backtrace.exp376
-rw-r--r--gdb/testsuite/gdb.trace/circ.c90
-rw-r--r--gdb/testsuite/gdb.trace/circ.exp215
-rw-r--r--gdb/testsuite/gdb.trace/collection.c280
-rw-r--r--gdb/testsuite/gdb.trace/collection.exp623
-rwxr-xr-xgdb/testsuite/gdb.trace/configure899
-rw-r--r--gdb/testsuite/gdb.trace/configure.in15
-rw-r--r--gdb/testsuite/gdb.trace/deltrace.exp269
-rw-r--r--gdb/testsuite/gdb.trace/gdb_c_test.c3792
-rw-r--r--gdb/testsuite/gdb.trace/infotrace.exp99
-rw-r--r--gdb/testsuite/gdb.trace/limits.c51
-rw-r--r--gdb/testsuite/gdb.trace/limits.exp316
-rw-r--r--gdb/testsuite/gdb.trace/packetlen.exp100
-rw-r--r--gdb/testsuite/gdb.trace/passc-dyn.exp181
-rw-r--r--gdb/testsuite/gdb.trace/passcount.exp178
-rw-r--r--gdb/testsuite/gdb.trace/report.exp421
-rw-r--r--gdb/testsuite/gdb.trace/save-trace.exp171
-rw-r--r--gdb/testsuite/gdb.trace/tfind.exp405
-rw-r--r--gdb/testsuite/gdb.trace/tracecmd.exp269
-rw-r--r--gdb/testsuite/gdb.trace/while-dyn.exp124
-rw-r--r--gdb/testsuite/gdb.trace/while-stepping.exp116
-rw-r--r--gdb/testsuite/lib/emc-support.exp223
-rw-r--r--gdb/testsuite/lib/gdb.exp1334
-rw-r--r--gdb/testsuite/lib/trace-support.exp307
-rw-r--r--gdb/thread.c721
-rw-r--r--gdb/top.c3677
-rw-r--r--gdb/top.h67
-rw-r--r--gdb/tracepoint.c2780
-rw-r--r--gdb/tracepoint.h137
-rw-r--r--gdb/tui/ChangeLog121
-rw-r--r--gdb/tui/Makefile.in168
-rw-r--r--gdb/tui/tui.c830
-rw-r--r--gdb/tui/tui.h120
-rw-r--r--gdb/tui/tuiCommand.c215
-rw-r--r--gdb/tui/tuiCommand.h24
-rw-r--r--gdb/tui/tuiData.c1624
-rw-r--r--gdb/tui/tuiData.h302
-rw-r--r--gdb/tui/tuiDataWin.c400
-rw-r--r--gdb/tui/tuiDataWin.h29
-rw-r--r--gdb/tui/tuiDisassem.c343
-rw-r--r--gdb/tui/tuiDisassem.h22
-rw-r--r--gdb/tui/tuiGeneralWin.c469
-rw-r--r--gdb/tui/tuiGeneralWin.h31
-rw-r--r--gdb/tui/tuiIO.c734
-rw-r--r--gdb/tui/tuiIO.h43
-rw-r--r--gdb/tui/tuiLayout.c1410
-rw-r--r--gdb/tui/tuiLayout.h15
-rw-r--r--gdb/tui/tuiRegs.c1210
-rw-r--r--gdb/tui/tuiRegs.h28
-rw-r--r--gdb/tui/tuiSource.c465
-rw-r--r--gdb/tui/tuiSource.h27
-rw-r--r--gdb/tui/tuiSourceWin.c1098
-rw-r--r--gdb/tui/tuiSourceWin.h74
-rw-r--r--gdb/tui/tuiStack.c554
-rw-r--r--gdb/tui/tuiStack.h22
-rw-r--r--gdb/tui/tuiWin.c1650
-rw-r--r--gdb/tui/tuiWin.h28
-rw-r--r--gdb/typeprint.c321
-rw-r--r--gdb/typeprint.h25
-rw-r--r--gdb/ultra3-nat.c329
-rw-r--r--gdb/ultra3-xdep.c128
-rw-r--r--gdb/umax-xdep.c133
-rw-r--r--gdb/utils.c2932
-rw-r--r--gdb/v850-tdep.c884
-rw-r--r--gdb/valarith.c1259
-rw-r--r--gdb/valops.c3461
-rw-r--r--gdb/valprint.c1567
-rw-r--r--gdb/valprint.h54
-rw-r--r--gdb/value.h568
-rw-r--r--gdb/values.c1623
-rw-r--r--gdb/vax-tdep.c263
-rw-r--r--gdb/vx-share/README7
-rw-r--r--gdb/vx-share/dbgRpcLib.h32
-rw-r--r--gdb/vx-share/ptrace.h44
-rw-r--r--gdb/vx-share/regPacket.h160
-rw-r--r--gdb/vx-share/vxTypes.h72
-rw-r--r--gdb/vx-share/vxWorks.h171
-rw-r--r--gdb/vx-share/wait.h46
-rw-r--r--gdb/vx-share/xdr_ld.c84
-rw-r--r--gdb/vx-share/xdr_ld.h45
-rw-r--r--gdb/vx-share/xdr_ptrace.c118
-rw-r--r--gdb/vx-share/xdr_ptrace.h72
-rw-r--r--gdb/vx-share/xdr_rdb.c212
-rw-r--r--gdb/vx-share/xdr_rdb.h137
-rw-r--r--gdb/w65-tdep.c295
-rw-r--r--gdb/w89k-rom.c317
-rw-r--r--gdb/win32-nat.c1122
-rw-r--r--gdb/xcoffread.c2811
-rw-r--r--gdb/xcoffsolib.c220
-rw-r--r--gdb/xcoffsolib.h58
-rw-r--r--gdb/xmodem.c284
-rw-r--r--gdb/xmodem.h29
-rw-r--r--gdb/z8k-tdep.c453
1535 files changed, 572700 insertions, 0 deletions
diff --git a/gdb/29k-share/README b/gdb/29k-share/README
new file mode 100644
index 00000000000..5e19715ffad
--- /dev/null
+++ b/gdb/29k-share/README
@@ -0,0 +1,9 @@
+The files in this directory are shared with other debuggers and
+debug interfaces that use Advanced Micro Devices' UDI (universal debug
+interface) protocol. The protocol provides a common interface among
+debuggers, logic analyzers, emulators, and embedded systems that use
+AMD 29000 family processors.
+
+Do not change these files without coordinating with Advanced Micro
+Devices, Embedded Processor Division, 5204 E. Ben White Blvd, Austin, TX 78741.
+Maybe postmaster@cayman.amd.com can direct you to the current maintainers.
diff --git a/gdb/29k-share/udi/udi2go32.c b/gdb/29k-share/udi/udi2go32.c
new file mode 100644
index 00000000000..63d98ae4017
--- /dev/null
+++ b/gdb/29k-share/udi/udi2go32.c
@@ -0,0 +1,607 @@
+/*
+
+Interface from UDI calls in 32-bit mode to go32 in 16-bit mode.
+Communication is done through a single interrupt vector, which passes
+data through two linear buffers.
+
+Call:
+ AH = 0xfe
+ AL = UDI function number
+ ECX = IN length
+ ESI = pointer to IN buffer
+ EDI = pointer to OUT buffer
+
+Return:
+ EAX = return value of UDI function
+
+Vector:
+ 0x21
+
+*/
+#ifdef __GO32__
+
+#include <stdlib.h>
+#include "udiproc.h"
+#include "udisoc.h"
+
+char dfe_errmsg[500];
+
+static char in_buffer[4096];
+static char out_buffer[4096];
+static char *in_ptr;
+static char *out_ptr;
+
+#define IN_INIT() in_ptr = in_buffer
+#define IN_VAL(t,v) *((t *)in_ptr)++ = v
+#define IN_DATA(ptr, cnt) memcpy(in_ptr, ptr, cnt), in_ptr += cnt
+
+#define OUT_INIT() out_ptr = out_buffer
+#define OUT_VAL(t) (*((t *)out_ptr)++)
+#define OUT_DATA(ptr, cnt) memcpy(ptr, out_ptr, cnt), out_ptr += cnt
+
+static int DO_CALL(int function)
+{
+ asm("pushl %esi");
+ asm("pushl %edi");
+ asm("movb %0, %%al" : : "g" (function));
+ asm("movl _in_ptr, %ecx");
+ asm("movl $_in_buffer, %esi");
+ asm("subl %esi, %ecx");
+ asm("movl $_out_buffer, %edi");
+ asm("movb $0xfe, %ah");
+ asm("int $0x21");
+ asm("popl %edi");
+ asm("popl %esi");
+}
+
+/*----------------------------------------------------------------------*/
+
+#ifdef TEST_UDI
+int main()
+{
+ int r;
+ long p2;
+ short p1;
+ IN_INIT();
+ IN_VAL(long, 11111111);
+ IN_VAL(short, 2222);
+ IN_DATA("Hello, world\n", 17);
+
+ r = DO_CALL(42);
+
+ OUT_INIT();
+ p1 = OUT_VAL(short);
+ p2 = OUT_VAL(long);
+ printf("main: p1=%d p2=%d rv=%d\n", p1, p2, r);
+ return r;
+}
+#endif
+
+/*----------------------------------------------------------------------*/
+
+unsupported(char *s)
+{
+ printf("unsupported UDI host call %s\n", s);
+ abort();
+}
+
+UDIError UDIConnect (
+ char *Configuration, /* In */
+ UDISessionId *Session /* Out */
+ )
+{
+ int r;
+ out_buffer[0] = 0; /* DJ - test */
+ IN_INIT();
+ IN_DATA(Configuration, strlen(Configuration)+1);
+
+ r = DO_CALL(UDIConnect_c);
+
+ OUT_INIT();
+ *Session = OUT_VAL(UDISessionId);
+ return r;
+}
+
+UDIError UDIDisconnect (
+ UDISessionId Session, /* In */
+ UDIBool Terminate /* In */
+ )
+{
+ int r;
+ IN_INIT();
+ IN_VAL(UDISessionId, Session);
+ IN_VAL(UDIBool, Terminate);
+
+ return DO_CALL(UDIDisconnect_c);
+}
+
+UDIError UDISetCurrentConnection (
+ UDISessionId Session /* In */
+ )
+{
+ IN_INIT();
+ IN_VAL(UDISessionId, Session);
+
+ return DO_CALL(UDISetCurrentConnection_c);
+}
+
+UDIError UDICapabilities (
+ UDIUInt32 *TIPId, /* Out */
+ UDIUInt32 *TargetId, /* Out */
+ UDIUInt32 DFEId, /* In */
+ UDIUInt32 DFE, /* In */
+ UDIUInt32 *TIP, /* Out */
+ UDIUInt32 *DFEIPCId, /* Out */
+ UDIUInt32 *TIPIPCId, /* Out */
+ char *TIPString /* Out */
+ )
+{
+ int r;
+ IN_INIT();
+ IN_VAL(UDIUInt32, DFEId);
+ IN_VAL(UDIUInt32, DFE);
+ r = DO_CALL(UDICapabilities_c);
+ OUT_INIT();
+ *TIPId = OUT_VAL(UDIUInt32);
+ *TargetId = OUT_VAL(UDIUInt32);
+ *TIP = OUT_VAL(UDIUInt32);
+ *DFEIPCId = OUT_VAL(UDIUInt32);
+ *TIPIPCId = OUT_VAL(UDIUInt32);
+ strcpy(TIPString, out_ptr);
+ return r;
+}
+
+UDIError UDIEnumerateTIPs (
+ UDIInt (*UDIETCallback) /* In */
+ ( char *Configuration ) /* In to callback() */
+ )
+{
+ UDIETCallback("montip.exe");
+}
+
+UDIError UDIGetErrorMsg (
+ UDIError ErrorCode, /* In */
+ UDISizeT MsgSize, /* In */
+ char *Msg, /* Out */
+ UDISizeT *CountDone /* Out */
+ )
+{
+ int r;
+ if (MsgSize > 4000)
+ MsgSize = 4000;
+ IN_INIT();
+ IN_VAL(UDIError, ErrorCode);
+ IN_VAL(UDISizeT, MsgSize);
+
+ r = DO_CALL(UDIGetErrorMsg_c);
+
+ OUT_INIT();
+ *CountDone = OUT_VAL(UDISizeT);
+ OUT_DATA(Msg, *CountDone);
+ return r;
+}
+
+UDIError UDIGetTargetConfig (
+ UDIMemoryRange KnownMemory[], /* Out */
+ UDIInt *NumberOfRanges, /* In/Out */
+ UDIUInt32 ChipVersions[], /* Out */
+ UDIInt *NumberOfChips /* In/Out */
+ )
+{
+ int r, i;
+ int nr = *NumberOfRanges;
+ int nc = *NumberOfChips;
+ IN_INIT();
+ IN_VAL(UDIInt, *NumberOfRanges);
+ IN_VAL(UDIInt, *NumberOfChips);
+ r = DO_CALL(UDIGetTargetConfig_c);
+ if (r == UDIErrorIncomplete)
+ return r;
+ OUT_INIT();
+ *NumberOfRanges = OUT_VAL(UDIInt);
+ *NumberOfChips = OUT_VAL(UDIInt);
+ for (i=0; i<nr; i++)
+ {
+ KnownMemory[i].Space = OUT_VAL(short);
+ KnownMemory[i].Offset = OUT_VAL(CPUOffset);
+ KnownMemory[i].Size = OUT_VAL(CPUSizeT);
+ }
+ for (i=0; i<nc; i++)
+ {
+ ChipVersions[i] = OUT_VAL(UDIUInt32);
+ }
+ return r;
+}
+
+UDIError UDICreateProcess (
+ UDIPId *PId /* Out */
+ )
+{
+ int r = DO_CALL(UDICreateProcess_c);
+
+ OUT_INIT();
+ *PId = OUT_VAL(UDIPId);
+
+ return r;
+}
+
+UDIError UDISetCurrentProcess (
+ UDIPId PId /* In */
+ )
+{
+ IN_INIT();
+ IN_VAL(UDIPId, PId);
+
+ return DO_CALL(UDISetCurrentProcess_c);
+}
+
+UDIError UDIDestroyProcess (
+ UDIPId PId /* In */
+ )
+{
+ IN_INIT();
+ IN_VAL(UDIPId, PId);
+
+ return DO_CALL(UDIDestroyProcess_c);
+}
+
+UDIError UDIInitializeProcess (
+ UDIMemoryRange ProcessMemory[], /* In */
+ UDIInt NumberOfRanges, /* In */
+ UDIResource EntryPoint, /* In */
+ CPUSizeT StackSizes[], /* In */
+ UDIInt NumberOfStacks, /* In */
+ char *ArgString /* In */
+ )
+{
+ int i, r;
+ IN_INIT();
+ IN_VAL(UDIInt, NumberOfRanges);
+ for (i=0; i<NumberOfRanges; i++)
+ {
+ IN_VAL(short, ProcessMemory[i].Space);
+ IN_VAL(CPUOffset, ProcessMemory[i].Offset);
+ IN_VAL(CPUSizeT, ProcessMemory[i].Size);
+ }
+ IN_VAL(short, EntryPoint.Space);
+ IN_VAL(CPUOffset, EntryPoint.Offset);
+ IN_VAL(UDIInt, NumberOfStacks);
+ for (i=0; i<NumberOfStacks; i++)
+ IN_VAL(CPUSizeT, StackSizes[i]);
+ IN_DATA(ArgString, strlen(ArgString)+1);
+
+ return DO_CALL(UDIInitializeProcess_c);
+}
+
+UDIError UDIRead (
+ UDIResource From, /* In */
+ UDIHostMemPtr To, /* Out */
+ UDICount Count, /* In */
+ UDISizeT Size, /* In */
+ UDICount *CountDone, /* Out */
+ UDIBool HostEndian /* In */
+ )
+{
+ int cleft = Count, cthis, dthis;
+ int cdone = 0, r, bsize=2048/Size;
+
+ while (cleft)
+ {
+ cthis = (cleft<bsize) ? cleft : bsize;
+ IN_INIT();
+ IN_VAL(short, From.Space);
+ IN_VAL(CPUOffset, From.Offset);
+ IN_VAL(UDICount, cthis);
+ IN_VAL(UDISizeT, Size);
+ IN_VAL(UDIBool, HostEndian);
+
+ r = DO_CALL(UDIRead_c);
+
+ OUT_INIT();
+ dthis = OUT_VAL(UDICount);
+ OUT_DATA(To, dthis*Size);
+ cdone += dthis;
+ To += dthis*Size;
+
+ if (r != UDINoError)
+ {
+ *CountDone = cdone;
+ return r;
+ }
+ cleft -= cthis;
+ }
+ *CountDone = cdone;
+ return UDINoError;
+}
+
+UDIError UDIWrite (
+ UDIHostMemPtr From, /* In */
+ UDIResource To, /* In */
+ UDICount Count, /* In */
+ UDISizeT Size, /* In */
+ UDICount *CountDone, /* Out */
+ UDIBool HostEndian /* In */
+ )
+{
+ int cleft = Count, cthis, dthis;
+ int cdone = 0, r, bsize=2048/Size;
+
+ while (cleft)
+ {
+ cthis = (cleft<bsize) ? cleft : bsize;
+ IN_INIT();
+ IN_VAL(short, To.Space);
+ IN_VAL(CPUOffset, To.Offset);
+ IN_VAL(UDICount, cthis);
+ IN_VAL(UDISizeT, Size);
+ IN_VAL(UDIBool, HostEndian);
+ IN_DATA(From, cthis*Size);
+ From += cthis*Size;
+
+ r = DO_CALL(UDIWrite_c);
+
+ OUT_INIT();
+ cdone += OUT_VAL(UDICount);
+
+ if (r != UDINoError)
+ {
+ *CountDone = cdone;
+ return r;
+ }
+ cleft -= cthis;
+ }
+ *CountDone = cdone;
+ return UDINoError;
+}
+
+UDIError UDICopy (
+ UDIResource From, /* In */
+ UDIResource To, /* In */
+ UDICount Count, /* In */
+ UDISizeT Size, /* In */
+ UDICount *CountDone, /* Out */
+ UDIBool Direction /* In */
+ )
+{
+ int r;
+ IN_INIT();
+ IN_VAL(short, From.Space);
+ IN_VAL(CPUOffset, From.Offset);
+ IN_VAL(short, To.Space);
+ IN_VAL(CPUOffset, To.Offset);
+ IN_VAL(UDICount, Count);
+ IN_VAL(UDISizeT, Size);
+ IN_VAL(UDIBool, Direction);
+
+ r = DO_CALL(UDICopy_c);
+
+ OUT_INIT();
+ *CountDone = OUT_VAL(UDICount);
+
+ return r;
+}
+
+UDIError UDIExecute (
+ void
+ )
+{
+ return DO_CALL(UDIExecute_c);
+}
+
+UDIError UDIStep (
+ UDIUInt32 Steps, /* In */
+ UDIStepType StepType, /* In */
+ UDIRange Range /* In */
+ )
+{
+ IN_INIT();
+ IN_VAL(UDIUInt32, Steps);
+ IN_VAL(UDIStepType, StepType);
+ IN_VAL(UDIRange, Range);
+
+ return DO_CALL(UDIStep_c);
+}
+
+UDIVoid UDIStop (
+ void
+ )
+{
+ DO_CALL(UDIStop_c);
+}
+
+UDIError UDIWait (
+ UDIInt32 MaxTime, /* In */
+ UDIPId *PId, /* Out */
+ UDIUInt32 *StopReason /* Out */
+ )
+{
+ int r;
+ IN_INIT();
+ IN_VAL(UDIInt32, MaxTime);
+ r = DO_CALL(UDIWait_c);
+ OUT_INIT();
+ *PId = OUT_VAL(UDIPId);
+ *StopReason = OUT_VAL(UDIUInt32);
+ return r;
+}
+
+UDIError UDISetBreakpoint (
+ UDIResource Addr, /* In */
+ UDIInt32 PassCount, /* In */
+ UDIBreakType Type, /* In */
+ UDIBreakId *BreakId /* Out */
+ )
+{
+ int r;
+ IN_INIT();
+ IN_VAL(short, Addr.Space);
+ IN_VAL(CPUOffset, Addr.Offset);
+ IN_VAL(UDIInt32, PassCount);
+ IN_VAL(UDIBreakType, Type);
+
+ r = DO_CALL(UDISetBreakpoint_c);
+
+ OUT_INIT();
+ *BreakId = OUT_VAL(UDIBreakId);
+ return r;
+}
+
+UDIError UDIQueryBreakpoint (
+ UDIBreakId BreakId, /* In */
+ UDIResource *Addr, /* Out */
+ UDIInt32 *PassCount, /* Out */
+ UDIBreakType *Type, /* Out */
+ UDIInt32 *CurrentCount /* Out */
+ )
+{
+ int r;
+ IN_INIT();
+ IN_VAL(UDIBreakId, BreakId);
+
+ r = DO_CALL(UDIQueryBreakpoint_c);
+
+ OUT_INIT();
+ Addr->Space = OUT_VAL(short);
+ Addr->Offset = OUT_VAL(CPUOffset);
+ *PassCount = OUT_VAL(UDIInt32);
+ *Type = OUT_VAL(UDIBreakType);
+ *CurrentCount = OUT_VAL(UDIInt32);
+
+ return r;
+}
+
+UDIError UDIClearBreakpoint (
+ UDIBreakId BreakId /* In */
+ )
+{
+ IN_INIT();
+ IN_VAL(UDIBreakId, BreakId);
+
+ return DO_CALL(UDIClearBreakpoint_c);
+}
+
+UDIError UDIGetStdout (
+ UDIHostMemPtr Buf, /* Out */
+ UDISizeT BufSize, /* In */
+ UDISizeT *CountDone /* Out */
+ )
+{
+ int r;
+ IN_INIT();
+ if (BufSize > 4000)
+ BufSize = 4000;
+ IN_VAL(UDISizeT,BufSize);
+ r = DO_CALL(UDIGetStdout_c);
+ OUT_INIT();
+ *CountDone = OUT_VAL(UDISizeT);
+ if (*CountDone <= BufSize)
+ OUT_DATA(Buf, *CountDone);
+ return r;
+}
+
+UDIError UDIGetStderr (
+ UDIHostMemPtr Buf, /* Out */
+ UDISizeT BufSize, /* In */
+ UDISizeT *CountDone /* Out */
+ )
+{
+ int r;
+ IN_INIT();
+ if (BufSize > 4000)
+ BufSize = 4000;
+ IN_VAL(UDISizeT,BufSize);
+ r = DO_CALL(UDIGetStderr_c);
+ OUT_INIT();
+ *CountDone = OUT_VAL(UDISizeT);
+ OUT_DATA(Buf, *CountDone);
+ return r;
+}
+
+UDIError UDIPutStdin (
+ UDIHostMemPtr Buf, /* In */
+ UDISizeT Count, /* In */
+ UDISizeT *CountDone /* Out */
+ )
+{
+ int r;
+ IN_INIT();
+ if (Count > 4000)
+ Count = 4000;
+ IN_VAL(UDISizeT,Count);
+ IN_DATA(Buf, Count);
+ r = DO_CALL(UDIPutStdin_c);
+ OUT_INIT();
+ *CountDone = OUT_VAL(UDISizeT);
+ return r;
+}
+
+UDIError UDIStdinMode (
+ UDIMode *Mode /* Out */
+ )
+{
+ int r;
+ IN_INIT();
+ r = DO_CALL(UDIStdinMode_c);
+ OUT_INIT();
+ *Mode = OUT_VAL(UDIMode);
+ return r;
+}
+
+UDIError UDIPutTrans (
+ UDIHostMemPtr Buf, /* In */
+ UDISizeT Count, /* In */
+ UDISizeT *CountDone /* Out */
+ )
+{
+ int r;
+ IN_INIT();
+ if (Count > 4000)
+ Count = 4000;
+ IN_VAL(UDISizeT,Count);
+ IN_DATA(Buf, Count);
+ r = DO_CALL(UDIPutTrans_c);
+ OUT_INIT();
+ *CountDone = OUT_VAL(UDISizeT);
+ return r;
+}
+
+UDIError UDIGetTrans (
+ UDIHostMemPtr Buf, /* Out */
+ UDISizeT BufSize, /* In */
+ UDISizeT *CountDone /* Out */
+ )
+{
+ int r;
+ IN_INIT();
+ if (BufSize > 4000)
+ BufSize = 4000;
+ IN_VAL(UDISizeT,BufSize);
+ r = DO_CALL(UDIGetTrans_c);
+ OUT_INIT();
+ *CountDone = OUT_VAL(UDISizeT);
+ OUT_DATA(Buf, *CountDone);
+ return r;
+}
+
+UDIError UDITransMode (
+ UDIMode *Mode /* Out */
+ )
+{
+ int r;
+ IN_INIT();
+ r = DO_CALL(UDITransMode_c);
+ OUT_INIT();
+ *Mode = OUT_VAL(UDIMode);
+ return r;
+}
+
+#define DFEIPCIdCompany 0x0001 /* Company ID AMD */
+#define DFEIPCIdProduct 0x1 /* Product ID 0 */
+#define DFEIPCIdVersion 0x125 /* 1.2.5 */
+
+unsigned UDIGetDFEIPCId ()
+{
+ return((((UDIUInt32)DFEIPCIdCompany) << 16) |(DFEIPCIdProduct << 12) | DFEIPCIdVersion);
+}
+
+#endif /* __GO32__ */
diff --git a/gdb/29k-share/udi/udiids.h b/gdb/29k-share/udi/udiids.h
new file mode 100644
index 00000000000..5f805e46905
--- /dev/null
+++ b/gdb/29k-share/udi/udiids.h
@@ -0,0 +1,48 @@
+/* This file contains the DFE and TIP IDs to be used by AMD products for
+ the UDICapabilities call.
+
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+ /* Company Codes -- AMD assigns these */
+#define UDICompanyCode_AMD 1
+
+ /* Build a UDIID given a CompanyProdCode and 3 version pieces */
+#define UDIID(CompanyProdCode, v1,v2,v3) ((((CompanyProdCode) & 0xfffff)<<12)+\
+ (((v1)&0xf)<<8) + (((v2)&0xf)<<4) + ((v3)&0xf))
+
+
+ /* Extract a CompanyProdCode or a Version from a UDIID */
+#define UDIID_CompanyProdCode(id) (((id)>>12) & 0xfffff)
+#define UDIID_Version(id) ((id)&0xfff)
+
+
+#define UDIAMDProduct(ProdCode) ((UDICompanyCode_AMD<<4) + (ProdCode&0xf))
+
+ /* AMD DFE Product Codes */
+#define UDIProductCode_Mondfe UDIAMDProduct(0)
+#define UDIProductCode_XRAY UDIAMDProduct(1)
+#define UDIProductCode_TIPTester UDIAMDProduct(2)
+
+ /* AMD TIP Product Codes (need not be distinct from DFE Product Codes) */
+#define UDIProductCode_Montip UDIAMDProduct(0)
+#define UDIProductCode_Isstip UDIAMDProduct(1)
+
+
+#define UDILatestVersion 0x120 /* UDI 1.2.0, can be used in DFE and TIP desired UDI params */
+
diff --git a/gdb/29k-share/udi/udip2soc.c b/gdb/29k-share/udi/udip2soc.c
new file mode 100644
index 00000000000..969e8502eb4
--- /dev/null
+++ b/gdb/29k-share/udi/udip2soc.c
@@ -0,0 +1,1250 @@
+/* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+static char udip2soc_c[]="@(#)udip2soc.c 2.11 Daniel Mann";
+static char udip2soc_c_AMD[]="@(#)udip2soc.c 2.8, AMD";
+/*
+* This module converts UDI Procedural calls into
+* UDI socket messages for UNIX.
+* It is used by DFE client processes
+********************************************************************** HISTORY
+*/
+/* This is all unneeded on DOS machines. */
+#ifndef __GO32__
+
+#include <stdio.h>
+#include <string.h>
+
+/* Before sys/file.h for Unixware. */
+#include <sys/types.h>
+
+#include <sys/file.h>
+
+/* This used to say sys/fcntl.h, but the only systems I know of that
+ require that are old (pre-4.3, at least) BSD systems, which we
+ probably don't need to worry about. */
+#include <fcntl.h>
+
+#include <sys/wait.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <signal.h>
+#include <sys/errno.h>
+#include "udiproc.h"
+#include "udisoc.h"
+
+extern int errno;
+extern int sys_nerr;
+extern int udr_errno;
+extern char* getenv();
+
+/* local type decs. and macro defs. not in a .h file ************* MACRO/TYPE
+*/
+#define version_c 0x121 /* DFE-IPC version id */
+#define TRUE -1
+#define FALSE 0
+#define PORT_NUM 7000
+#define MAX_SESSIONS 5 /* maximum DFE-TIP connections */
+#define SOC_BUF_SIZE 4* 1024 /* size of socket comms buffer */
+#define SBUF_SIZE 500 /* size of string buffer */
+#define ERRMSG_SIZE 500 /* size of error message buffer */
+
+typedef struct connection_str /* record of connect session */
+{
+ int in_use;
+ char connect_id[20]; /* connection identifier */
+ char domain_string[20]; /* dommaing for conection */
+ char tip_string[30]; /* TIP host name for AF_INET */
+ char tip_exe[80]; /* TIP exe name */
+ int dfe_sd; /* associated DFE socket */
+ int tip_pid; /* pid of TIP process */
+ struct sockaddr_in dfe_sockaddr;
+ struct sockaddr_in tip_sockaddr_in;
+ struct sockaddr tip_sockaddr;
+} connection_t;
+
+typedef struct session_str
+{
+ int in_use;
+ connection_t* soc_con_p; /* associated connection */
+ UDISessionId tip_id; /* associated TIP session ID */
+} session_t;
+
+/* global dec/defs. which are not in a .h file ************* EXPORT DEC/DEFS
+*/
+UDIError dfe_errno;
+char dfe_errmsg[ERRMSG_SIZE];/* error string */
+
+/* local dec/defs. which are not in a .h file *************** LOCAL DEC/DEFS
+*/
+LOCAL connection_t soc_con[MAX_SESSIONS];
+LOCAL session_t session[MAX_SESSIONS];
+LOCAL UDR udr;
+LOCAL UDR* udrs = &udr; /* UDR for current session */
+LOCAL int current; /* int-id for current session */
+LOCAL char sbuf[SBUF_SIZE]; /* String handler buffer */
+LOCAL char config_file[80]; /* path/name for config file */
+
+/***************************************************************** UDI_CONNECT
+* Establish a new FDE to TIP conection. The file "./udi_soc" or
+* "/etc/udi_soc" may be examined to obtain the conection information
+* if the "Config" parameter is not a completd "line entry".
+*
+* NOTE: the Session string must not start whith white-space characters.
+* Format of string is:
+* <session> <domain> <soc_name|host_name> <tip_exe|port> <pass to UDIconnect>
+* soc2cayman AF_INET cayman 7000 <not supported>
+* soc2tip AF_UNIX astring tip.exe ...
+*/
+UDIError
+UDIConnect(Config, Session)
+ char *Config; /* in -- identification string */
+ UDISessionId *Session; /* out -- session ID */
+{
+ UDIInt32 service_id = UDIConnect_c;
+ int domain;
+ int cnt=0;
+ int rcnt, pos, params_pos=0;
+ char *tip_main_string;
+ char *env_p;
+ struct hostent *tip_info_p;
+ FILE *fd;
+#if 0
+ FILE *f_p;
+#endif
+ UDIUInt32 TIPIPCId;
+ UDIUInt32 DFEIPCId;
+
+#if 0 /* This is crap. It assumes that udi_soc is executable! */
+ sprintf(sbuf, "which udi_soc");
+ f_p = popen(sbuf, "r");
+ if(f_p)
+ { while( (sbuf[cnt++]=getc(f_p)) != EOF);
+ sbuf[cnt-2]=0;
+ }
+ pclose(f_p);
+#endif
+
+ for (rcnt=0;
+ rcnt < MAX_SESSIONS && session[rcnt].in_use;
+ rcnt++);
+
+ if (rcnt >= MAX_SESSIONS)
+ {
+ sprintf(dfe_errmsg, "DFE-ipc ERROR: Too many sessions already open");
+ return UDIErrorIPCLimitation;
+ }
+
+ /* One connection can be multiplexed between several sessions. */
+
+ for (cnt=0;
+ cnt < MAX_SESSIONS && soc_con[cnt].in_use;
+ cnt++);
+
+ if (cnt >= MAX_SESSIONS)
+ {
+ sprintf(dfe_errmsg,
+ "DFE-ipc ERROR: Too many connections already open");
+ return UDIErrorIPCLimitation;
+ }
+
+ *Session = rcnt;
+ session[rcnt].soc_con_p = &soc_con[cnt];
+
+ if (strchr(Config, ' ')) /* test if file entry given */
+ {
+ soc_con[cnt].in_use = TRUE;
+ sscanf(Config, "%s %s %s %s %n",
+ soc_con[cnt].connect_id,
+ soc_con[cnt].domain_string,
+ soc_con[cnt].tip_string,
+ soc_con[cnt].tip_exe,
+ &params_pos);
+ tip_main_string = Config + params_pos;
+ }
+ else /* here if need to read udi_soc file */
+ {
+ strcpy(config_file, "udi_soc");
+ env_p = getenv("UDICONF");
+ if (env_p)
+ strcpy(config_file, env_p);
+
+ fd = fopen(config_file, "r");
+
+ if (!fd)
+ {
+ sprintf(dfe_errmsg, "UDIConnect, can't open udi_soc file:\n%s ",
+ strerror(errno));
+ dfe_errno = UDIErrorCantOpenConfigFile;
+ goto tip_failure;
+ }
+
+ while (1)
+ {
+ if (fscanf(fd, "%s %s %s %s %[^\n]\n",
+ soc_con[cnt].connect_id,
+ soc_con[cnt].domain_string,
+ soc_con[cnt].tip_string,
+ soc_con[cnt].tip_exe,
+ sbuf) == EOF)
+ break;
+
+ if (strcmp(Config, soc_con[cnt].connect_id) != 0)
+ continue;
+
+ soc_con[cnt].in_use = TRUE; /* here if entry found */
+
+ tip_main_string = sbuf;
+ break;
+ }
+
+ fclose(fd);
+ if (!soc_con[cnt].in_use)
+ {
+ sprintf(dfe_errmsg,
+ "UDIConnect, can't find `%s' entry in udi_soc file",
+ Config);
+ dfe_errno = UDIErrorNoSuchConfiguration;
+ goto tip_failure;
+ }
+ }
+/*----------------------------------------------------------- SELECT DOMAIN */
+ if (strcmp(soc_con[cnt].domain_string, "AF_UNIX") == 0)
+ domain = AF_UNIX;
+ else if (strcmp(soc_con[cnt].domain_string, "AF_INET") == 0)
+ domain = AF_INET;
+ else
+ {
+ sprintf(dfe_errmsg, "DFE-ipc ERROR: socket address family not known");
+ dfe_errno = UDIErrorBadConfigFileEntry;
+ goto tip_failure;
+ }
+
+/*---------------------------------------------------- MULTIPLEXED SOCKET ? */
+/* If the requested session requires communication with
+ a TIP which already has a socket connection established,
+ then we do not create a new socket but multiplex the
+ existing one. A TIP is said to use the same socket if
+ socket-name/host-name and the domain are the same.
+ */
+ for (rcnt=0; rcnt < MAX_SESSIONS; rcnt++)
+ {
+ if (soc_con[rcnt].in_use
+ && rcnt != cnt
+ && strcmp(soc_con[cnt].domain_string,
+ soc_con[rcnt].domain_string) == 0
+ && strcmp(soc_con[cnt].tip_string,
+ soc_con[rcnt].tip_string) == 0)
+ {
+ session[*Session].soc_con_p = &soc_con[rcnt];
+ soc_con[cnt].in_use = FALSE; /* don't need new connect */
+ goto tip_connect;
+ }
+ }
+/*------------------------------------------------------------------ SOCKET */
+ soc_con[cnt].dfe_sd = socket(domain, SOCK_STREAM, 0);
+ if (soc_con[cnt].dfe_sd == -1)
+ {
+ sprintf(dfe_errmsg, "DFE-ipc ERROR, socket() call failed %s ",
+ strerror (errno));
+ dfe_errno = UDIErrorUnknownError;
+ goto tip_failure;
+ }
+
+/*--------------------------------------------------------- AF_UNIX CONNECT */
+ if (domain == AF_UNIX)
+ {
+ if (strcmp(soc_con[cnt].tip_string, "*") == 0)
+ {
+ for (pos = 0; pos < 20; pos++)
+ {
+ int f;
+
+ sprintf(soc_con[cnt].tip_string,"/tmp/U%d", getpid() + pos);
+ f = open(soc_con[cnt].tip_string, O_CREAT);
+ if (f == -1)
+ continue;
+
+ close(f);
+ unlink(soc_con[cnt].tip_string);
+ break;
+ }
+
+ if (pos >= 20)
+ {
+ sprintf(dfe_errmsg,
+ "DFE-ipc ERROR, can't create random socket name");
+ dfe_errno = UDIErrorCantConnect;
+ goto tip_failure;
+ }
+ }
+
+ soc_con[cnt].tip_sockaddr.sa_family = domain;
+ memcpy(soc_con[cnt].tip_sockaddr.sa_data,
+ soc_con[cnt].tip_string,
+ sizeof(soc_con[cnt].tip_sockaddr.sa_data));
+ if (connect(soc_con[cnt].dfe_sd,
+ &soc_con[cnt].tip_sockaddr,
+ sizeof(soc_con[cnt].tip_sockaddr)))
+ { /* if connect() fails assume TIP not yet started */
+/*------------------------------------------------------------ AF_UNIX EXEC */
+ int pid;
+ int statusp;
+ char *arg0;
+
+ arg0 = strrchr(soc_con[cnt].tip_exe,'/');
+
+ if (arg0)
+ arg0++;
+ else
+ arg0 = soc_con[cnt].tip_exe;
+
+ pid = vfork();
+
+ if (pid == 0) /* Child */
+ {
+ execlp(soc_con[cnt].tip_exe,
+ arg0,
+ soc_con[cnt].domain_string,
+ soc_con[cnt].tip_string,
+ NULL);
+ _exit(1);
+ }
+
+ if (waitpid(pid, &statusp, WNOHANG))
+ {
+ sprintf(dfe_errmsg, "DFE-ipc ERROR: can't exec the TIP");
+ dfe_errno = UDIErrorCantStartTIP;
+ goto tip_failure;
+ }
+
+ pos = 3;
+ for (pos = 3; pos > 0; pos--)
+ {
+ if (!connect(soc_con[cnt].dfe_sd,
+ &soc_con[cnt].tip_sockaddr,
+ sizeof(soc_con[cnt].tip_sockaddr)))
+ break;
+ sleep(1);
+ }
+
+ if (pos == 0)
+ {
+ sprintf(dfe_errmsg, "DFE-ipc ERROR, connect() call failed: %s",
+ strerror (errno));
+ dfe_errno = UDIErrorCantConnect;
+ goto tip_failure;
+ }
+ }
+ }
+/*--------------------------------------------------------- AF_INET CONNECT */
+ else if (domain == AF_INET)
+ {
+ fprintf(stderr,
+ "DFE-ipc WARNING, need to have first started remote TIP");
+
+ soc_con[cnt].tip_sockaddr_in.sin_family = domain;
+ soc_con[cnt].tip_sockaddr_in.sin_addr.s_addr =
+ inet_addr(soc_con[cnt].tip_string);
+ if (soc_con[cnt].tip_sockaddr_in.sin_addr.s_addr == -1)
+ {
+ tip_info_p = gethostbyname(soc_con[cnt].tip_string);
+ if (tip_info_p == NULL)
+ {
+ sprintf(dfe_errmsg,"DFE-ipc ERROR, No such host %s",
+ soc_con[cnt].tip_string);
+ dfe_errno = UDIErrorNoSuchConnection;
+ goto tip_failure;
+ }
+ memcpy((char *)&soc_con[cnt].tip_sockaddr_in.sin_addr,
+ tip_info_p->h_addr,
+ tip_info_p->h_length);
+ }
+ soc_con[cnt].tip_sockaddr_in.sin_port
+ = htons(atoi(soc_con[cnt].tip_exe));
+
+ if (connect(soc_con[cnt].dfe_sd,
+ (struct sockaddr *) &soc_con[cnt].tip_sockaddr_in,
+ sizeof(soc_con[cnt].tip_sockaddr_in)))
+ {
+ sprintf(dfe_errmsg, "DFE-ipc ERROR, connect() call failed %s ",
+ strerror (errno));
+ dfe_errno = UDIErrorCantConnect;
+ goto tip_failure;
+ }
+ }
+/*------------------------------------------------------------- TIP CONNECT */
+ if (cnt == 0) udr_create(udrs, soc_con[cnt].dfe_sd, SOC_BUF_SIZE);
+
+tip_connect:
+ current = cnt;
+ session[*Session].in_use = TRUE; /* session id is now in use */
+
+ udr_errno = 0;
+ udrs->udr_op = UDR_ENCODE; /* send all "in" parameters */
+ udr_UDIInt32(udrs, &service_id);
+
+ DFEIPCId = (company_c << 16) + (product_c << 12) + version_c;
+ udr_UDIUInt32(udrs, &DFEIPCId);
+
+ udr_string(udrs, tip_main_string);
+
+ udr_sendnow(udrs);
+
+ udrs->udr_op = UDR_DECODE; /* recv all "out" parameters */
+ udr_UDIUInt32(udrs, &TIPIPCId);
+ if ((TIPIPCId & 0xfff) < version_c)
+ sprintf(dfe_errmsg, "DFE-ipc: Obsolete TIP Specified");
+
+ udr_UDIInt32(udrs, &soc_con[cnt].tip_pid);
+
+ udr_UDISessionId(udrs, &session[*Session].tip_id);
+
+ udr_UDIError(udrs, &dfe_errno);
+ if (dfe_errno > 0) UDIKill(*Session, 0);
+
+ return dfe_errno;
+
+tip_failure:
+
+ soc_con[cnt].in_use = FALSE;
+ session[*Session].in_use = FALSE;
+/* XXX - Should also close dfe_sd, but not sure what to do if muxed */
+ return dfe_errno;
+}
+
+/************************************************************** UDI_Disconnect
+* UDIDisconnect() should be called before exiting the
+* DFE to ensure proper shut down of the TIP.
+*/
+UDIError UDIDisconnect(Session, Terminate)
+UDISessionId Session;
+UDIBool Terminate;
+{
+ int cnt;
+ UDIInt32 service_id = UDIDisconnect_c;
+ if(Session < 0 || Session > MAX_SESSIONS)
+ {
+ sprintf(dfe_errmsg," SessionId not valid (%d)", Session);
+ return UDIErrorNoSuchConfiguration;
+ }
+ udr_errno = 0;
+ udrs->udr_op = UDR_ENCODE; /* send all "in" parameters */
+ udr_UDIInt32(udrs, &service_id);
+ udr_UDISessionId(udrs, &session[Session].tip_id);
+ udr_UDIBool(udrs, &Terminate);
+ udr_sendnow(udrs);
+
+ session[Session].in_use = FALSE; /* session id is now free */
+ for (cnt=0; cnt < MAX_SESSIONS; cnt++)
+ if(session[cnt].in_use
+ && session[cnt].soc_con_p == session[Session].soc_con_p
+ ) break;
+ if(cnt >= MAX_SESSIONS) /* test if socket not multiplexed */
+ if(shutdown(session[Session].soc_con_p->dfe_sd, 2))
+ {
+ sprintf(dfe_errmsg, "DFE-ipc WARNING: socket shutdown failed");
+ return UDIErrorIPCInternal;
+ }
+ else
+ session[Session].soc_con_p->in_use = 0;
+
+ udrs->udr_op = UDR_DECODE; /* receive all "out" parameters */
+ udr_UDIError(udrs, &dfe_errno); /* get any TIP error */
+ return dfe_errno;
+}
+
+/******************************************************************** UDI_KILL
+* UDIKill() is used to send a signal to the TIP.
+* This is a private IPC call.
+*/
+UDIError UDIKill(Session, Signal)
+UDISessionId Session;
+UDIInt32 Signal;
+{
+ int cnt;
+ UDIInt32 service_id = UDIKill_c;
+ if(Session < 0 || Session > MAX_SESSIONS)
+ {
+ sprintf(dfe_errmsg," SessionId not valid (%d)", Session);
+ return UDIErrorNoSuchConfiguration;
+ }
+ udr_errno = 0;
+ udrs->udr_op = UDR_ENCODE; /* send all "in" parameters */
+ udr_UDIInt32(udrs, &service_id);
+ udr_UDISessionId(udrs, &session[Session].tip_id);
+ udr_UDIInt32(udrs, &Signal);
+ udr_sendnow(udrs);
+
+ session[Session].in_use = FALSE; /* session id is now free */
+ for (cnt=0; cnt < MAX_SESSIONS; cnt++)
+ if(session[cnt].in_use
+ && session[cnt].soc_con_p == session[Session].soc_con_p
+ ) break;
+ if(cnt < MAX_SESSIONS) /* test if socket not multiplexed */
+ if(shutdown(session[Session].soc_con_p->dfe_sd, 2))
+ {
+ sprintf(dfe_errmsg, "DFE-ipc WARNING: socket shutdown failed");
+ return UDIErrorIPCInternal;
+ }
+ else
+ session[Session].soc_con_p->in_use = 0;
+
+ udrs->udr_op = UDR_DECODE; /* receive all "out" parameters */
+ udr_UDIError(udrs, &dfe_errno); /* get any TIP error */
+ return dfe_errno;
+}
+
+/************************************************** UDI_Set_Current_Connection
+* If you are connected to multiple TIPs, you can change
+* TIPs using UDISetCurrentConnection().
+*/
+UDIError UDISetCurrentConnection(Session)
+UDISessionId Session;
+{
+ UDIInt32 service_id = UDISetCurrentConnection_c;
+
+ if(Session < 0 || Session > MAX_SESSIONS)
+ return UDIErrorNoSuchConfiguration;
+ if(!session[Session].in_use) /* test if not in use yet */
+ return UDIErrorNoSuchConnection;
+
+ current = Session;
+ /* change socket or multiplex the same socket */
+ udrs->sd = session[Session].soc_con_p->dfe_sd;
+
+ udr_errno = 0;
+ udrs->udr_op = UDR_ENCODE; /* send all "in" parameters */
+ udr_UDIInt32(udrs, &service_id);
+ udr_UDISessionId(udrs, &session[Session].tip_id);
+ udr_sendnow(udrs);
+ if(udr_errno) return udr_errno;
+
+ udrs->udr_op = UDR_DECODE; /* receive all "out" parameters */
+ udr_UDIError(udrs, &dfe_errno); /* get any TIP error */
+ return dfe_errno;
+}
+
+/************************************************************ UDI_Capabilities
+* The DFE uses UDICapabilities() to both inform the TIP
+* of what services the DFE offers and to inquire of the
+* TIP what services the TIP offers.
+*/
+UDIError UDICapabilities(TIPId, TargetId, DFEId, DFE, TIP, DFEIPCId,
+ TIPIPCId, TIPString)
+UDIUInt32 *TIPId; /* out */
+UDIUInt32 *TargetId; /* out */
+UDIUInt32 DFEId; /* in */
+UDIUInt32 DFE; /* in */
+UDIUInt32 *TIP; /* out */
+UDIUInt32 *DFEIPCId; /* out */
+UDIUInt32 *TIPIPCId; /* out */
+char *TIPString; /* out */
+{
+ UDIInt32 service_id = UDICapabilities_c;
+ int size;
+
+ udr_errno = 0;
+ udrs->udr_op = UDR_ENCODE; /* send all "in" parameters */
+ udr_UDIInt32(udrs, &service_id);
+ udr_UDIInt32(udrs, &DFEId);
+ udr_UDIInt32(udrs, &DFE);
+ udr_sendnow(udrs);
+ if(udr_errno) return udr_errno;
+
+ udrs->udr_op = UDR_DECODE; /* receive all "out" paramters */
+ udr_UDIInt32(udrs, TIPId);
+ udr_UDIInt32(udrs, TargetId);
+ udr_UDIInt32(udrs, TIP);
+ udr_UDIInt32(udrs, DFEIPCId);
+ *DFEIPCId = (company_c << 16) + (product_c << 12) + version_c;
+ udr_UDIInt32(udrs, TIPIPCId);
+ udr_string(udrs, sbuf);
+ udr_UDIError(udrs, &dfe_errno); /* get any TIP error */
+ size = strlen(sbuf);
+ if(size +1 > 80) return -1; /* test if sufficient space */
+ strcpy(TIPString, sbuf);
+ return dfe_errno;
+}
+
+/********************************************************** UDI_Enumerate_TIPs
+* Used by the DFE to enquire about available TIP
+* connections.
+*/
+UDIError UDIEnumerateTIPs(UDIETCallback)
+ int (*UDIETCallback)(); /* In -- function to callback */
+{
+ FILE *fp;
+
+ fp = fopen(config_file, "r");
+ if(fp == NULL)
+ return UDIErrorCantOpenConfigFile;
+ while(fgets( sbuf, SBUF_SIZE, fp))
+ if(UDIETCallback( sbuf) == UDITerminateEnumeration)
+ break;
+ fclose( fp);
+ return UDINoError; /* return success */
+}
+
+/*********************************************************** UDI_GET_ERROR_MSG
+* Some errors are target specific. They are indicated
+* by a negative error return value. The DFE uses
+* UDIGetErrorMsg() to get the descriptive text for
+* the error message which can then be displayed to
+* the user.
+*/
+UDIError UDIGetErrorMsg(error_code, msg_len, msg, CountDone)
+UDIError error_code; /* In */
+UDISizeT msg_len; /* In -- allowed message space */
+char* msg; /* Out -- length of message*/
+UDISizeT *CountDone; /* Out -- number of characters */
+{
+ UDIInt32 service_id = UDIGetErrorMsg_c;
+ int size;
+
+ udr_errno = 0;
+ udrs->udr_op = UDR_ENCODE; /* send all "in" parameters */
+ udr_UDIInt32(udrs, &service_id);
+ udr_UDIError(udrs, &error_code);
+ udr_UDISizeT(udrs, &msg_len);
+ udr_sendnow(udrs);
+ if(udr_errno) return udr_errno;
+
+ udrs->udr_op = UDR_DECODE; /* receive all "out" parameters */
+ udr_string(udrs, sbuf);
+ udr_UDISizeT(udrs, CountDone);
+ udr_UDIError(udrs, &dfe_errno); /* get any TIP error */
+ size = strlen(sbuf);
+ if(size +1 > msg_len) return -1; /* test if sufficient space */
+ strcpy(msg, sbuf);
+ return dfe_errno;
+}
+
+/******************************************************* UDI_GET_TARGET_CONFIG
+* UDIGetTargetConfig() gets information about the target.
+*/
+UDIError UDIGetTargetConfig(KnownMemory, NumberOfRanges, ChipVersions,
+ NumberOfChips)
+UDIMemoryRange KnownMemory[]; /* Out */
+UDIInt *NumberOfRanges; /* In and Out */
+UDIUInt32 ChipVersions[]; /* Out */
+UDIInt *NumberOfChips; /* In and Out */
+{
+ UDIInt32 service_id = UDIGetTargetConfig_c;
+ int cnt;
+ int MaxOfRanges = *NumberOfRanges;
+
+ udr_errno = 0;
+ udrs->udr_op = UDR_ENCODE; /* send all "in" parameters */
+ udr_UDIInt32(udrs, &service_id);
+ udr_UDIInt(udrs, NumberOfRanges);
+ udr_UDIInt(udrs, NumberOfChips);
+ udr_sendnow(udrs);
+ if(udr_errno) return udr_errno;
+
+ udrs->udr_op = UDR_DECODE; /* receive all "out" paramters */
+ for(cnt=1; cnt <= MaxOfRanges; cnt++)
+ udr_UDIMemoryRange(udrs, &KnownMemory[cnt-1]);
+ udr_UDIInt(udrs, NumberOfRanges);
+ udr_UDIInt(udrs, NumberOfChips);
+ for(cnt=1; cnt <= *NumberOfChips; cnt++)
+ udr_UDIUInt32(udrs, &ChipVersions[cnt -1]);
+ udr_UDIError(udrs, &dfe_errno); /* get any TIP error */
+ return dfe_errno;
+}
+
+/********************************************************** UDI_CREATE_PRCOESS
+* UDICreateProcess() tells the target OS that a
+* process is to be created and gets a PID back unless
+* there is some error.
+*/
+UDIError UDICreateProcess(pid)
+UDIPId *pid; /* out */
+{
+ UDIInt32 service_id = UDICreateProcess_c;
+
+ udr_errno = 0;
+ udrs->udr_op = UDR_ENCODE; /* send all "in" parameters */
+ udr_UDIInt32(udrs, &service_id);
+ udr_sendnow(udrs);
+ if(udr_errno) return udr_errno;
+
+ udrs->udr_op = UDR_DECODE; /* receive all "out" parameters */
+ udr_UDIPId(udrs, pid);
+ udr_UDIError(udrs, &dfe_errno); /* get any TIP error */
+ return dfe_errno;
+}
+
+/***************************************************** UDI_Set_Current_Process
+* UDISetCurrentProcess uses a pid supplied by
+* UDICreateProcess and sets it as the default for all
+* udi calls until a new one is set. A user of a
+*/
+UDIError UDISetCurrentProcess (pid)
+UDIPId pid; /* In */
+{
+ UDIInt32 service_id = UDISetCurrentProcess_c;
+
+ udr_errno = 0;
+ udrs->udr_op = UDR_ENCODE; /* send all "in" parameters */
+ udr_UDIInt32(udrs, &service_id);
+ udr_UDIPId(udrs, &pid);
+ udr_sendnow(udrs);
+ if(udr_errno) return udr_errno;
+
+ udrs->udr_op = UDR_DECODE; /* receive all "out" parameters */
+ udr_UDIError(udrs, &dfe_errno); /* get any TIP error */
+ return dfe_errno;
+}
+
+/****************************************************** UDI_INITIALISE_PROCESS
+* UDIInitializeProcess() prepare process for
+* execution. (Reset processor if process os processor).
+*/
+UDIError UDIInitializeProcess( ProcessMemory, NumberOfRanges, EntryPoint,
+ StackSizes, NumberOfStacks, ArgString)
+UDIMemoryRange ProcessMemory[]; /* In */
+UDIInt NumberOfRanges; /* In */
+UDIResource EntryPoint; /* In */
+CPUSizeT *StackSizes; /* In */
+UDIInt NumberOfStacks; /* In */
+char *ArgString; /* In */
+{
+ UDIInt32 service_id = UDIInitializeProcess_c;
+ int cnt;
+
+ udr_errno = 0;
+ udrs->udr_op = UDR_ENCODE; /* send all "in" parameters */
+ udr_UDIInt32(udrs, &service_id);
+ udr_UDIInt(udrs, &NumberOfRanges);
+ for(cnt = 0; cnt < NumberOfRanges; cnt++)
+ udr_UDIMemoryRange(udrs, &ProcessMemory[cnt] );
+ udr_UDIResource(udrs, &EntryPoint);
+ udr_UDIInt(udrs, &NumberOfStacks);
+ for(cnt = 0; cnt < NumberOfStacks; cnt++)
+ udr_CPUSizeT(udrs, &StackSizes[cnt]);
+ udr_string(udrs, ArgString);
+ udr_sendnow(udrs);
+ if(udr_errno) return udr_errno;
+
+ udrs->udr_op = UDR_DECODE; /* receive all "out" parameters */
+ udr_UDIError(udrs, &dfe_errno); /* get any TIP error */
+ return dfe_errno;
+}
+
+/********************************************************* UDI_DESTROY_PROCESS
+* UDIDestroyProcess() frees a process resource
+* previously created by UDICreateProcess().
+*/
+UDIError UDIDestroyProcess(pid)
+UDIPId pid; /* in */
+{
+ UDIInt32 service_id = UDIDestroyProcess_c;
+
+ udr_errno = 0;
+ udrs->udr_op = UDR_ENCODE; /* send all "in" parameters */
+ udr_UDIInt32(udrs, &service_id);
+ udr_UDIPId(udrs, &pid);
+ udr_sendnow(udrs);
+ if(udr_errno) return udr_errno;
+
+ udrs->udr_op = UDR_DECODE; /* receive all "out" parameters */
+ udr_UDIError(udrs, &dfe_errno); /* get any TIP error */
+ return dfe_errno;
+}
+
+/****************************************************************** UDI_READ
+* UDIRead() reads a block of objects from a target
+* address space to host space.
+*/
+
+UDIError UDIRead (from, to, count, size, count_done, host_endian)
+UDIResource from; /* in - source address on target */
+UDIHostMemPtr to; /* out - destination address on host */
+UDICount count; /* in -- count of objects to be transferred */
+UDISizeT size; /* in -- size of each object */
+UDICount *count_done; /* out - count actually transferred */
+UDIBool host_endian; /* in -- flag for endian information */
+{
+ UDIInt32 service_id = UDIRead_c;
+ int byte_count;
+
+ udr_errno = 0;
+ udrs->udr_op = UDR_ENCODE; /* send all "in" parameters */
+ udr_UDIInt32(udrs, &service_id);
+ udr_UDIResource(udrs, &from);
+ udr_UDICount(udrs, &count);
+ udr_UDISizeT(udrs, &size);
+ udr_UDIBool(udrs, &host_endian);
+ udr_sendnow(udrs);
+ if(udr_errno) return udr_errno;
+
+ udrs->udr_op = UDR_DECODE; /* receive all "out" paramters */
+ udr_UDICount(udrs, count_done);
+ byte_count = (*count_done) * size;
+ if(*count_done > 0 && *count_done <= count)
+ udr_bytes(udrs, to, byte_count);
+ if(udr_errno) return udr_errno;
+ udr_UDIError(udrs, &dfe_errno); /* get any TIP error */
+ return dfe_errno;
+}
+
+/****************************************************************** UDI_WRITE
+* UDIWrite() writes a block of objects from host
+* space to a target address+space.
+*/
+UDIError UDIWrite( from, to, count, size, count_done, host_endian )
+UDIHostMemPtr from; /* in -- source address on host */
+UDIResource to; /* in -- destination address on target */
+UDICount count; /* in -- count of objects to be transferred */
+UDISizeT size; /* in -- size of each object */
+UDICount *count_done; /* out - count actually transferred */
+UDIBool host_endian; /* in -- flag for endian information */
+{
+ UDIInt32 service_id = UDIWrite_c;
+ int byte_count = count * size;
+
+ udr_errno = 0;
+ udrs->udr_op = UDR_ENCODE; /* send all "in" parameters */
+ udr_UDIInt32(udrs, &service_id);
+ udr_UDIResource(udrs, &to);
+ udr_UDICount(udrs, &count);
+ udr_UDISizeT(udrs, &size);
+ udr_UDIBool(udrs, &host_endian);
+ udr_bytes(udrs, from, byte_count);
+ udr_sendnow(udrs);
+ if(udr_errno) return udr_errno;
+
+ udrs->udr_op = UDR_DECODE; /* receive all "out" paramters */
+ udr_UDICount(udrs, count_done);
+ udr_UDIError(udrs, &dfe_errno); /* get any TIP error */
+ return dfe_errno;
+}
+
+/******************************************************************** UDI_COPY
+* UDICopy() copies a block of objects from one target
+* get address/space to another target address/space.
+*/
+UDIError UDICopy(from, to, count, size, count_done, direction )
+UDIResource from; /* in -- destination address on target */
+UDIResource to; /* in -- source address on target */
+UDICount count; /* in -- count of objects to be transferred */
+UDISizeT size; /* in -- size of each object */
+UDICount *count_done; /* out - count actually transferred */
+UDIBool direction; /* in -- high-to-low or reverse */
+{
+ UDIInt32 service_id = UDICopy_c;
+
+ udr_errno = 0;
+ udrs->udr_op = UDR_ENCODE; /* send all "in" parameters */
+ udr_UDIInt32(udrs, &service_id);
+ udr_UDIResource(udrs, &from);
+ udr_UDIResource(udrs, &to);
+ udr_UDICount(udrs, &count);
+ udr_UDISizeT(udrs, &size);
+ udr_UDIBool(udrs, &direction);
+ udr_sendnow(udrs);
+ if(udr_errno) return udr_errno;
+
+ udrs->udr_op = UDR_DECODE; /* receive all "out" parameters */
+ udr_UDICount(udrs, count_done);
+ udr_UDIError(udrs, &dfe_errno); /* get any TIP error */
+ return dfe_errno;
+}
+
+/***************************************************************** UDI_EXECUTE
+* UDIExecute() continues execution of the default
+* process from the current PC.
+*/
+UDIError UDIExecute()
+{
+ UDIInt32 service_id = UDIExecute_c;
+
+ udr_errno = 0;
+ udrs->udr_op = UDR_ENCODE; /* send all "in" parameters */
+ udr_UDIInt32(udrs, &service_id);
+ udr_sendnow(udrs);
+ if(udr_errno) return udr_errno;
+
+ udrs->udr_op = UDR_DECODE; /* receive all "out" parameters */
+ udr_UDIError(udrs, &dfe_errno); /* get any TIP error */
+ return dfe_errno;
+}
+
+/******************************************************************** UDI_STEP
+* UDIStep() specifies a number of "instruction"
+* steps to make.
+*/
+UDIError UDIStep(steps, steptype, range)
+UDIUInt32 steps; /* in -- number of steps */
+UDIStepType steptype; /* in -- type of stepping to be done */
+UDIRange range; /* in -- range if StepInRange is TRUE */
+{
+ UDIInt32 service_id = UDIStep_c;
+
+ udr_errno = 0;
+ udrs->udr_op = UDR_ENCODE; /* send all "in" parameters */
+ udr_UDIInt32(udrs, &service_id);
+ udr_UDIInt32(udrs, &steps);
+ udr_UDIStepType(udrs, &steptype);
+ udr_UDIRange(udrs, &range);
+ udr_sendnow(udrs);
+ if(udr_errno) return udr_errno;
+
+ udrs->udr_op = UDR_DECODE; /* receive all "out" parameters */
+ udr_UDIError(udrs, &dfe_errno); /* get any TIP error */
+ return dfe_errno;
+}
+
+/******************************************************************** UDI_STOP
+* UDIStop() stops the default process
+*/
+UDIVoid UDIStop()
+{
+ if (strcmp(session[current].soc_con_p->domain_string, "AF_UNIX") == 0)
+ kill(session[current].soc_con_p->tip_pid, SIGINT);
+ else
+ udr_signal(udrs);
+
+/* XXX - should clean up session[] and soc_con[] structs here as well... */
+
+ return;
+}
+
+/******************************************************************** UDI_WAIT
+* UDIWait() returns the state of the target procesor.
+*/
+UDIError UDIWait(maxtime, pid, stop_reason)
+UDIInt32 maxtime; /* in -- maximum time to wait for completion */
+UDIPId *pid; /* out -- pid of process which stopped if any */
+UDIUInt32 *stop_reason; /* out -- PC where process stopped */
+{
+ UDIInt32 service_id = UDIWait_c;
+
+ udr_errno = 0;
+ udrs->udr_op = UDR_ENCODE; /* send all "in" parameters */
+ udr_UDIInt32(udrs, &service_id);
+ udr_UDIInt32(udrs, &maxtime);
+ udr_sendnow(udrs);
+ if(udr_errno) return udr_errno;
+
+ udrs->udr_op = UDR_DECODE; /* receive all "out" parameters */
+ udr_UDIPId(udrs, pid);
+ udr_UDIUInt32(udrs, stop_reason);
+ udr_UDIError(udrs, &dfe_errno); /* get any TIP error */
+ return dfe_errno;
+}
+
+/********************************************************** UDI_SET_BREAKPOINT
+* UDISetBreakpoint() sets a breakpoint at an adress
+* and uses the passcount to state how many
+* times that instruction should be hit before the
+* break occurs.
+*/
+UDIError UDISetBreakpoint (addr, passcount, type, break_id)
+UDIResource addr; /* in -- where breakpoint gets set */
+UDIInt32 passcount; /* in -- passcount for breakpoint */
+UDIBreakType type; /* in -- breakpoint type */
+UDIBreakId *break_id; /* out - assigned break id */
+{
+ UDIInt32 service_id = UDISetBreakpoint_c;
+
+ udr_errno = 0;
+ udrs->udr_op = UDR_ENCODE; /* send all "in" parameters */
+ udr_UDIInt32(udrs, &service_id);
+ udr_UDIResource(udrs, &addr);
+ udr_UDIInt32(udrs, &passcount);
+ udr_UDIBreakType(udrs, &type);
+ udr_sendnow(udrs);
+ if(udr_errno) return udr_errno;
+
+ udrs->udr_op = UDR_DECODE; /* receive all "out" parameters */
+ udr_UDIBreakId(udrs, break_id);
+ udr_UDIError(udrs, &dfe_errno); /* get any TIP error */
+ return dfe_errno;
+}
+
+/******************************************************** UDI_QUERY_BREAKPOINT
+*/
+UDIError UDIQueryBreakpoint (break_id, addr, passcount, type, current_count)
+UDIBreakId break_id; /* in -- assigned break id */
+UDIResource *addr; /* out - where breakpoint was set */
+UDIInt32 *passcount; /* out - trigger passcount for breakpoint */
+UDIBreakType *type; /* out - breakpoint type */
+UDIInt32 *current_count; /* out - current count for breakpoint */
+{
+ UDIInt32 service_id = UDIQueryBreakpoint_c;
+
+ udr_errno = 0;
+ udrs->udr_op = UDR_ENCODE; /* send all "in" parameters */
+ udr_UDIInt32(udrs, &service_id);
+ udr_UDIBreakId(udrs, &break_id);
+ udr_sendnow(udrs);
+ if(udr_errno) return udr_errno;
+
+ udrs->udr_op = UDR_DECODE; /* receive all "out" parameters */
+ udr_UDIResource(udrs, addr);
+ udr_UDIInt32(udrs, passcount);
+ udr_UDIBreakType(udrs, type);
+ udr_UDIInt32(udrs, current_count);
+ udr_UDIError(udrs, &dfe_errno); /* get any TIP error */
+ return dfe_errno;
+}
+
+/******************************************************** UDI_CLEAR_BREAKPOINT
+* UDIClearBreakpoint() is used to clear a breakpoint.
+*/
+UDIError UDIClearBreakpoint (break_id)
+UDIBreakId break_id; /* in -- assigned break id */
+{
+ UDIInt32 service_id = UDIClearBreakpoint_c;
+
+ udr_errno = 0;
+ udrs->udr_op = UDR_ENCODE; /* send all "in" parameters */
+ udr_UDIInt32(udrs, &service_id);
+ udr_UDIBreakId(udrs, &break_id);
+ udr_sendnow(udrs);
+ if(udr_errno) return udr_errno;
+
+ udrs->udr_op = UDR_DECODE; /* receive all "out" parameters */
+ udr_UDIError(udrs, &dfe_errno); /* get any TIP error */
+ return dfe_errno;
+}
+
+/************************************************************** UDI_GET_STDOUT
+* UDIGetStdout() is called when a call to
+* UDIWait() indicates there is STD output data ready.
+*/
+UDIError UDIGetStdout(buf, bufsize, count_done)
+UDIHostMemPtr buf; /* out -- buffer to be filled */
+UDISizeT bufsize; /* in -- buffer size in bytes */
+UDISizeT *count_done; /* out -- number of bytes written to buf */
+{
+ UDIInt32 service_id = UDIGetStdout_c;
+
+ udr_errno = 0;
+ udrs->udr_op = UDR_ENCODE; /* send all "in" parameters */
+ udr_UDIInt32(udrs, &service_id);
+ udr_UDISizeT(udrs, &bufsize);
+ udr_sendnow(udrs);
+ if(udr_errno) return udr_errno;
+
+ udrs->udr_op = UDR_DECODE; /* receive all "out" parameters */
+ udr_UDISizeT(udrs, count_done);
+ udr_bytes(udrs, buf, *count_done);
+ udr_UDIError(udrs, &dfe_errno); /* get any TIP error */
+ return dfe_errno;
+}
+
+/************************************************************** UDI_GET_STDERR
+* UDIGetStderr() is called when a call to
+* UDIWait() indicates there is STDERR output data ready
+*/
+UDIError UDIGetStderr(buf, bufsize, count_done)
+UDIHostMemPtr buf; /* out -- buffer to be filled */
+UDISizeT bufsize; /* in -- buffer size in bytes */
+UDISizeT *count_done; /* out -- number of bytes written to buf */
+{
+ UDIInt32 service_id = UDIGetStderr_c;
+
+ udr_errno = 0;
+ udrs->udr_op = UDR_ENCODE; /* send all "in" parameters */
+ udr_UDIInt32(udrs, &service_id);
+ udr_UDISizeT(udrs, &bufsize);
+ udr_sendnow(udrs);
+ if(udr_errno) return udr_errno;
+
+ udrs->udr_op = UDR_DECODE; /* receive all "out" parameters */
+ udr_UDISizeT(udrs, count_done);
+ udr_bytes(udrs, buf, *count_done);
+ udr_UDIError(udrs, &dfe_errno); /* get any TIP error */
+ return dfe_errno;
+}
+
+/*************************************************************** UDI_PUT_STDIN
+* UDIPutStdin() is called whenever the DFE wants to
+* deliver an input character to the TIP.
+*/
+UDIError UDIPutStdin (buf, count, count_done)
+UDIHostMemPtr buf; /* in -- buffer to be filled */
+UDISizeT count; /* in -- buffer size in bytes */
+UDISizeT *count_done; /* out - number of bytes written to buf */
+{
+ UDIInt32 service_id = UDIPutStdin_c;
+
+ udr_errno = 0;
+ udrs->udr_op = UDR_ENCODE; /* send all "in" parameters */
+ udr_UDIInt32(udrs, &service_id);
+ udr_UDISizeT(udrs, &count);
+ udr_bytes(udrs, buf, count);
+ udr_sendnow(udrs);
+ if(udr_errno) return udr_errno;
+
+ udrs->udr_op = UDR_DECODE; /* receive all "out" parameters */
+ udr_UDISizeT(udrs, count_done);
+ udr_UDIError(udrs, &dfe_errno); /* get any TIP error */
+ return dfe_errno;
+}
+
+/************************************************************** UDI_STDIN_MODE
+* UDIStdinMode() is used to change the mode that chazcters
+* are fetched from the user.
+*/
+UDIError UDIStdinMode(mode)
+UDIMode *mode; /* out - */
+{
+ UDIInt32 service_id = UDIStdinMode_c;
+
+ udr_errno = 0;
+ udrs->udr_op = UDR_ENCODE; /* send all "in" parameters */
+ udr_UDIInt32(udrs, &service_id);
+ udr_sendnow(udrs);
+ if(udr_errno) return udr_errno;
+
+ udrs->udr_op = UDR_DECODE; /* receive all "out" parameters */
+ udr_UDIMode(udrs, mode);
+ udr_UDIError(udrs, &dfe_errno); /* get any TIP error */
+ return dfe_errno;
+}
+
+/*************************************************************** UDI_PUT_TRANS
+* UDIPutTrans() is used to feed input to the passthru mode.
+*/
+UDIError UDIPutTrans (buf, count, count_done)
+UDIHostMemPtr buf; /* in -- buffer address containing input data */
+UDISizeT count; /* in -- number of bytes in buf */
+UDISizeT *count_done; /* out-- number of bytes transfered */
+{
+ UDIInt32 service_id = UDIPutTrans_c;
+
+ udr_errno = 0;
+ udrs->udr_op = UDR_ENCODE; /* send all "in" parameters */
+ udr_UDIInt32(udrs, &service_id);
+ udr_UDISizeT(udrs, &count);
+ udr_bytes(udrs, buf, count);
+ udr_sendnow(udrs);
+ if(udr_errno) return udr_errno;
+
+ udrs->udr_op = UDR_DECODE; /* receive all "out" parameters */
+ udr_UDISizeT(udrs, count_done);
+ udr_UDIError(udrs, &dfe_errno); /* get any TIP error */
+ return dfe_errno;
+}
+
+/*************************************************************** UDI_GET_TRANS
+* UDIGetTrans() is used to get output lines from the
+* passthru mode.
+*/
+UDIError UDIGetTrans (buf, bufsize, count_done)
+UDIHostMemPtr buf; /* out -- buffer to be filled */
+UDISizeT bufsize; /* in -- size of buf */
+UDISizeT *count_done; /* out -- number of bytes in buf */
+{
+ UDIInt32 service_id = UDIGetTrans_c;
+
+ udr_errno = 0;
+ udrs->udr_op = UDR_ENCODE; /* send all "in" parameters */
+ udr_UDIInt32(udrs, &service_id);
+ udr_UDISizeT(udrs, &bufsize);
+ udr_sendnow(udrs);
+ if(udr_errno) return udr_errno;
+
+ udrs->udr_op = UDR_DECODE; /* receive all "out" parameters */
+ udr_UDISizeT(udrs, count_done);
+ udr_bytes(udrs, buf, *count_done);
+ udr_UDIError(udrs, &dfe_errno); /* get any TIP error */
+ return dfe_errno;
+}
+
+/************************************************************** UDI_Trans_Mode
+* UDITransMode() is used to change the mode that the
+* transparent routines operate in.
+*/
+UDIError UDITransMode(mode)
+UDIMode *mode; /* out -- selected mode */
+{
+ UDIInt32 service_id = UDITransMode_c;
+
+ udr_errno = 0;
+ udrs->udr_op = UDR_ENCODE; /* send all "in" parameters */
+ udr_UDIInt32(udrs, &service_id);
+ udr_UDIMode(udrs, mode);
+ udr_sendnow(udrs);
+ if(udr_errno) return udr_errno;
+
+ udrs->udr_op = UDR_DECODE; /* receive all "out" parameters */
+ udr_UDIError(udrs, &dfe_errno);
+ return dfe_errno;
+}
+
+/******************************************************************** UDI_TEST
+*/
+UDIError UDITest( cnt, str_p, array)
+UDISizeT cnt;
+UDIHostMemPtr str_p;
+UDIInt32 array[];
+{
+ UDIInt32 service_id = UDITest_c;
+ UDIInt16 scnt = cnt;
+ UDISizeT r_cnt;
+ char buf[256];
+
+ udr_errno = 0;
+ udrs->udr_op = UDR_ENCODE; /* send all "in" parameters */
+ udr_UDIInt32(udrs, &service_id);
+
+ printf("send cnt=%d scnt=%d\n", cnt, scnt);
+ udr_UDISizeT(udrs, &cnt);
+ udr_UDIInt16(udrs, &scnt);
+ printf(" array[0]=0x%x array[1]=0x%x array[2]=0x%x array[3]=0x%x\n",
+ array[0], array[1], array[2], array[3]);
+ udr_bytes(udrs, (char*)array, 4*sizeof(UDIInt32));
+ printf(" string=%s\n", str_p);
+ udr_string(udrs, str_p);
+ udr_sendnow(udrs);
+ if(udr_errno)
+ { fprintf(stderr, " DFE-ipc Send ERROR\n");
+ return udr_errno;
+ }
+
+ udrs->udr_op = UDR_DECODE; /* receive all "out" parameters */
+ printf("recv ");
+ udr_UDISizeT(udrs, &r_cnt);
+ udr_UDIInt16(udrs, &scnt);
+ printf(" rcnt=%d scnt=%d\n", r_cnt, scnt);
+ udr_bytes(udrs, (char*)array, 4*sizeof(UDIInt32));
+
+ printf(" array[0]=0x%x array[1]=0x%x array[2]=0x%x array[3]=0x%x\n",
+ array[0], array[1], array[2], array[3]);
+ udr_string(udrs, str_p);
+ printf(" string=%s\n", str_p);
+
+ udr_UDIError(udrs, &dfe_errno);
+ return dfe_errno;
+}
+
+
+
+UDIUInt32 UDIGetDFEIPCId()
+{
+ return ((company_c << 16) + (product_c << 12) + version_c);
+}
+#endif /* __GO32__ */
diff --git a/gdb/29k-share/udi/udiphcfg.h b/gdb/29k-share/udi/udiphcfg.h
new file mode 100644
index 00000000000..e9eff0a3c86
--- /dev/null
+++ b/gdb/29k-share/udi/udiphcfg.h
@@ -0,0 +1,44 @@
+/* This file just picks the correct udiphxxx.h depending on the host.
+ The two hosts that are now defined are UNIX and MSDOS.
+
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/*
+ * For the moment, we will default to BSD_IPC; this might change if/when
+ * another type of IPC (Mach? SysV?) is implemented.
+ */
+
+#if 0
+
+/* We don't seem to have a copy of udiphdos.h. Furthermore, all the
+ things in udiphunix.h are pretty much generic 32-bit machine defines
+ which don't have anything to do with IPC. */
+
+#ifdef DOS_IPC
+#include "udiphdos.h"
+#else
+/*#ifdef BSD_IPC */
+#include "udiphunix.h"
+#endif
+
+#else
+
+#include "udiphunix.h"
+
+#endif
diff --git a/gdb/29k-share/udi/udiphunix.h b/gdb/29k-share/udi/udiphunix.h
new file mode 100644
index 00000000000..172fbbfd85b
--- /dev/null
+++ b/gdb/29k-share/udi/udiphunix.h
@@ -0,0 +1,81 @@
+/* Originally called "udiphsun.h", however it was not very
+ Sun-specific; now it is used for generic-unix-with-bsd-ipc.
+
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* This file is to be used to reconfigure the UDI Procedural interface
+ for a given host. This file should be placed so that it will be
+ included from udiproc.h. Everything in here may need to be changed
+ when you change either the host CPU or its compiler. Nothing in
+ here should change to support different targets. There are multiple
+ versions of this file, one for each of the different host/compiler
+ combinations in use.
+*/
+
+#define UDIStruct struct /* _packed not needed on unix */
+/* First, we need some types */
+/* Types with at least the specified number of bits */
+typedef double UDIReal64; /* 64-bit real value */
+typedef float UDIReal32; /* 32-bit real value */
+
+typedef unsigned long UDIUInt32; /* unsigned integers */
+typedef unsigned short UDIUInt16;
+typedef unsigned char UDIUInt8;
+
+typedef long UDIInt32; /* 32-bit integer */
+typedef short UDIInt16; /* 16-bit integer */
+typedef char UDIInt8; /* unreliable signedness */
+
+/* To aid in supporting environments where the DFE and TIP use
+different compilers or hosts (like DOS 386 on one side, 286 on the
+other, or different Unix machines connected by sockets), we define
+two abstract types - UDIInt and UDISizeT.
+UDIInt should be defined to be int except for host/compiler combinations
+that are intended to talk to existing UDI components that have a different
+sized int. Similarly for UDISizeT.
+*/
+typedef int UDIInt;
+typedef unsigned int UDIUInt;
+
+typedef unsigned int UDISizeT;
+
+/* Now two void types. The first is for function return types,
+the other for pointers to no particular type. Since these types
+are used solely for documentational clarity, if your host/compiler
+doesn't support either one, replace them with int and char *
+respectively.
+*/
+typedef void UDIVoid; /* void type */
+typedef void * UDIVoidPtr; /* void pointer type */
+typedef void * UDIHostMemPtr; /* Arbitrary memory pointer */
+
+/* Now we want a type optimized for boolean values. Normally this
+ would be int, but on some machines (Z80s, 8051s, etc) it might
+ be better to map it onto a char
+*/
+typedef int UDIBool;
+
+/* Now indicate whether your compiler support full ANSI style
+ prototypes. If so, use #if 1. If not use #if 0.
+*/
+#if 0
+#define UDIParams(x) x
+#else
+#define UDIParams(x) ()
+#endif
diff --git a/gdb/29k-share/udi/udiproc.h b/gdb/29k-share/udi/udiproc.h
new file mode 100644
index 00000000000..0cc1c2049c1
--- /dev/null
+++ b/gdb/29k-share/udi/udiproc.h
@@ -0,0 +1,308 @@
+/* local type decs. and macro defs.
+
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "udiphcfg.h" /* Get host specific configuration */
+#include "udiptcfg.h" /* Get target specific configuration */
+
+/* Here are all of the CPU Families for which UDI is currently defined */
+#define Am29K 1 /* AMD's Am290xx and Am292xx parts */
+
+typedef UDIInt UDIError;
+typedef UDIInt UDISessionId;
+typedef UDIInt UDIPId;
+typedef UDIInt UDIStepType;
+typedef UDIInt UDIBreakType;
+typedef UDIUInt UDIBreakId;
+typedef UDIUInt UDIMode;
+
+typedef UDIStruct
+{
+ CPUSpace Space;
+ CPUOffset Offset;
+} UDIResource;
+
+typedef UDIStruct
+{
+ CPUOffset Low;
+ CPUOffset High;
+} UDIRange;
+
+typedef UDIStruct
+{
+ CPUSpace Space;
+ CPUOffset Offset;
+ CPUSizeT Size;
+ } UDIMemoryRange;
+
+/* Values for UDIStepType parameters */
+#define UDIStepNatural 0x0000
+#define UDIStepOverTraps 0x0001
+#define UDIStepOverCalls 0x0002
+#define UDIStepInRange 0x0004
+#define UDIStepNatural 0x0000
+
+/* Values for UDIBreakType parameters */
+#define UDIBreakFlagExecute 0x0001
+#define UDIBreakFlagRead 0x0002
+#define UDIBreakFlagWrite 0x0004
+#define UDIBreakFlagFetch 0x0008
+
+/* Special values for UDIWait MaxTime parameter */
+#define UDIWaitForever (UDIInt32) -1 /* Infinite time delay */
+
+/* Special values for PId */
+#define UDIProcessProcessor -1 /* Raw Hardware, if possible */
+
+/* Values for UDIWait StopReason */
+#define UDIGrossState 0xff
+#define UDITrapped 0 /* Fine state - which trap */
+#define UDINotExecuting 1
+#define UDIRunning 2
+#define UDIStopped 3
+#define UDIWarned 4
+#define UDIStepped 5
+#define UDIWaiting 6
+#define UDIHalted 7
+#define UDIStdoutReady 8 /* fine state - size */
+#define UDIStderrReady 9 /* fine state - size */
+#define UDIStdinNeeded 10 /* fine state - size */
+#define UDIStdinModeX 11 /* fine state - mode */
+#define UDIBreak 12 /* Fine state - Breakpoint Id */
+#define UDIExited 13 /* Fine state - exit code */
+
+/* Enumerate the return values from the callback function
+ for UDIEnumerateTIPs.
+*/
+#define UDITerminateEnumeration 0
+#define UDIContinueEnumeration 1
+
+/* Enumerate values for Terminate parameter to UDIDisconnect */
+#define UDITerminateSession 1
+#define UDIContinueSession 0
+
+/* Error codes */
+#define UDINoError 0 /* No error occured */
+#define UDIErrorNoSuchConfiguration 1
+#define UDIErrorCantHappen 2
+#define UDIErrorCantConnect 3
+#define UDIErrorNoSuchConnection 4
+#define UDIErrorNoConnection 5
+#define UDIErrorCantOpenConfigFile 6
+#define UDIErrorCantStartTIP 7
+#define UDIErrorConnectionUnavailable 8
+#define UDIErrorTryAnotherTIP 9
+#define UDIErrorExecutableNotTIP 10
+#define UDIErrorInvalidTIPOption 11
+#define UDIErrorCantDisconnect 12
+#define UDIErrorUnknownError 13
+#define UDIErrorCantCreateProcess 14
+#define UDIErrorNoSuchProcess 15
+#define UDIErrorUnknownResourceSpace 16
+#define UDIErrorInvalidResource 17
+#define UDIErrorUnsupportedStepType 18
+#define UDIErrorCantSetBreakpoint 19
+#define UDIErrorTooManyBreakpoints 20
+#define UDIErrorInvalidBreakId 21
+#define UDIErrorNoMoreBreakIds 22
+#define UDIErrorUnsupportedService 23
+#define UDIErrorTryAgain 24
+#define UDIErrorIPCLimitation 25
+#define UDIErrorIncomplete 26
+#define UDIErrorAborted 27
+#define UDIErrorTransDone 28
+#define UDIErrorCantAccept 29
+#define UDIErrorTransInputNeeded 30
+#define UDIErrorTransModeX 31
+#define UDIErrorInvalidSize 32
+#define UDIErrorBadConfigFileEntry 33
+#define UDIErrorIPCInternal 34
+/* TBD */
+
+/****************************************************************** PROCEDURES
+*/
+
+UDIError UDIConnect UDIParams((
+ char *Configuration, /* In */
+ UDISessionId *Session /* Out */
+ ));
+
+UDIError UDIDisconnect UDIParams((
+ UDISessionId Session, /* In */
+ UDIBool Terminate /* In */
+ ));
+
+UDIError UDISetCurrentConnection UDIParams((
+ UDISessionId Session /* In */
+ ));
+
+UDIError UDICapabilities UDIParams((
+ UDIUInt32 *TIPId, /* Out */
+ UDIUInt32 *TargetId, /* Out */
+ UDIUInt32 DFEId, /* In */
+ UDIUInt32 DFE, /* In */
+ UDIUInt32 *TIP, /* Out */
+ UDIUInt32 *DFEIPCId, /* Out */
+ UDIUInt32 *TIPIPCId, /* Out */
+ char *TIPString /* Out */
+ ));
+
+UDIError UDIEnumerateTIPs UDIParams((
+ UDIInt (*UDIETCallback) /* In */
+ UDIParams(( char *Configuration )) /* In to callback() */
+ ));
+
+UDIError UDIGetErrorMsg UDIParams((
+ UDIError ErrorCode, /* In */
+ UDISizeT MsgSize, /* In */
+ char *Msg, /* Out */
+ UDISizeT *CountDone /* Out */
+ ));
+
+UDIError UDIGetTargetConfig UDIParams((
+ UDIMemoryRange KnownMemory[], /* Out */
+ UDIInt *NumberOfRanges, /* In/Out */
+ UDIUInt32 ChipVersions[], /* Out */
+ UDIInt *NumberOfChips /* In/Out */
+ ));
+
+UDIError UDICreateProcess UDIParams((
+ UDIPId *PId /* Out */
+ ));
+
+UDIError UDISetCurrentProcess UDIParams((
+ UDIPId PId /* In */
+ ));
+
+UDIError UDIDestroyProcess UDIParams((
+ UDIPId PId /* In */
+ ));
+
+UDIError UDIInitializeProcess UDIParams((
+ UDIMemoryRange ProcessMemory[], /* In */
+ UDIInt NumberOfRanges, /* In */
+ UDIResource EntryPoint, /* In */
+ CPUSizeT StackSizes[], /* In */
+ UDIInt NumberOfStacks, /* In */
+ char *ArgString /* In */
+ ));
+
+UDIError UDIRead UDIParams((
+ UDIResource From, /* In */
+ UDIHostMemPtr To, /* Out */
+ UDICount Count, /* In */
+ UDISizeT Size, /* In */
+ UDICount *CountDone, /* Out */
+ UDIBool HostEndian /* In */
+ ));
+
+UDIError UDIWrite UDIParams((
+ UDIHostMemPtr From, /* In */
+ UDIResource To, /* In */
+ UDICount Count, /* In */
+ UDISizeT Size, /* In */
+ UDICount *CountDone, /* Out */
+ UDIBool HostEndian /* In */
+ ));
+
+UDIError UDICopy UDIParams((
+ UDIResource From, /* In */
+ UDIResource To, /* In */
+ UDICount Count, /* In */
+ UDISizeT Size, /* In */
+ UDICount *CountDone, /* Out */
+ UDIBool Direction /* In */
+ ));
+
+UDIError UDIExecute UDIParams((
+ void
+ ));
+
+UDIError UDIStep UDIParams((
+ UDIUInt32 Steps, /* In */
+ UDIStepType StepType, /* In */
+ UDIRange Range /* In */
+ ));
+
+UDIVoid UDIStop UDIParams((
+ void
+ ));
+
+UDIError UDIWait UDIParams((
+ UDIInt32 MaxTime, /* In */
+ UDIPId *PId, /* Out */
+ UDIUInt32 *StopReason /* Out */
+ ));
+
+UDIError UDISetBreakpoint UDIParams((
+ UDIResource Addr, /* In */
+ UDIInt32 PassCount, /* In */
+ UDIBreakType Type, /* In */
+ UDIBreakId *BreakId /* Out */
+ ));
+
+UDIError UDIQueryBreakpoint UDIParams((
+ UDIBreakId BreakId, /* In */
+ UDIResource *Addr, /* Out */
+ UDIInt32 *PassCount, /* Out */
+ UDIBreakType *Type, /* Out */
+ UDIInt32 *CurrentCount /* Out */
+ ));
+
+UDIError UDIClearBreakpoint UDIParams((
+ UDIBreakId BreakId /* In */
+ ));
+
+UDIError UDIGetStdout UDIParams((
+ UDIHostMemPtr Buf, /* Out */
+ UDISizeT BufSize, /* In */
+ UDISizeT *CountDone /* Out */
+ ));
+
+UDIError UDIGetStderr UDIParams((
+ UDIHostMemPtr Buf, /* Out */
+ UDISizeT BufSize, /* In */
+ UDISizeT *CountDone /* Out */
+ ));
+
+UDIError UDIPutStdin UDIParams((
+ UDIHostMemPtr Buf, /* In */
+ UDISizeT Count, /* In */
+ UDISizeT *CountDone /* Out */
+ ));
+
+UDIError UDIStdinMode UDIParams((
+ UDIMode *Mode /* Out */
+ ));
+
+UDIError UDIPutTrans UDIParams((
+ UDIHostMemPtr Buf, /* In */
+ UDISizeT Count, /* In */
+ UDISizeT *CountDone /* Out */
+ ));
+
+UDIError UDIGetTrans UDIParams((
+ UDIHostMemPtr Buf, /* Out */
+ UDISizeT BufSize, /* In */
+ UDISizeT *CountDone /* Out */
+ ));
+
+UDIError UDITransMode UDIParams((
+ UDIMode *Mode /* Out */
+ ));
diff --git a/gdb/29k-share/udi/udipt29k.h b/gdb/29k-share/udi/udipt29k.h
new file mode 100644
index 00000000000..5de2f3ff860
--- /dev/null
+++ b/gdb/29k-share/udi/udipt29k.h
@@ -0,0 +1,87 @@
+/* This file is to be used to reconfigure the UDI Procedural interface
+ for a given target.
+
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* This file should be placed so that it will be
+ included from udiproc.h. Everything in here will probably need to
+ be changed when you change the target processor. Nothing in here
+ should need to change when you change hosts or compilers.
+*/
+
+/* Select a target CPU Family */
+#define TargetCPUFamily Am29K
+
+/* Enumerate the processor specific values for Space in a resource */
+#define UDI29KDRAMSpace 0
+#define UDI29KIOSpace 1
+#define UDI29KCPSpace0 2
+#define UDI29KCPSpace1 3
+#define UDI29KIROMSpace 4
+#define UDI29KIRAMSpace 5
+#define UDI29KLocalRegs 8
+#define UDI29KGlobalRegs 9
+#define UDI29KRealRegs 10
+#define UDI29KSpecialRegs 11
+#define UDI29KTLBRegs 12 /* Not Am29005 */
+#define UDI29KACCRegs 13 /* Am29050 only */
+#define UDI29KICacheSpace 14 /* Am2903x only */
+#define UDI29KAm29027Regs 15 /* When available */
+#define UDI29KPC 16
+#define UDI29KDCacheSpace 17 /* When available */
+
+/* Enumerate the Co-processor registers */
+#define UDI29KCP_F 0
+#define UDI29KCP_Flag 8
+#define UDI29KCP_I 12
+#define UDI29KCP_ITmp 16
+#define UDI29KCP_R 20
+#define UDI29KCP_S 28
+#define UDI29KCP_RTmp 36
+#define UDI29KCP_STmp 44
+#define UDI29KCP_Stat 52
+#define UDI29KCP_Prec 56
+#define UDI29KCP_Reg0 60
+#define UDI29KCP_Reg1 68
+#define UDI29KCP_Reg2 76
+#define UDI29KCP_Reg3 84
+#define UDI29KCP_Reg4 92
+#define UDI29KCP_Reg5 100
+#define UDI29KCP_Reg6 108
+#define UDI29KCP_Reg7 116
+#define UDI29KCP_Mode 124
+
+/* Enumerate the stacks in StackSizes array */
+#define UDI29KMemoryStack 0
+#define UDI29KRegisterStack 1
+
+/* Enumerate the chips for ChipVersions array */
+#define UDI29K29KVersion 0
+#define UDI29K29027Version 1
+
+/* Define special value for elements of ChipVersions array for
+ * chips not present */
+#define UDI29KChipNotPresent -1
+
+typedef UDIInt32 UDICount;
+typedef UDIUInt32 UDISize;
+
+typedef UDIInt CPUSpace;
+typedef UDIUInt32 CPUOffset;
+typedef UDIUInt32 CPUSizeT;
diff --git a/gdb/29k-share/udi/udiptcfg.h b/gdb/29k-share/udi/udiptcfg.h
new file mode 100644
index 00000000000..1641a53bcd4
--- /dev/null
+++ b/gdb/29k-share/udi/udiptcfg.h
@@ -0,0 +1,19 @@
+/* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "udipt29k.h"
diff --git a/gdb/29k-share/udi/udisoc.h b/gdb/29k-share/udi/udisoc.h
new file mode 100644
index 00000000000..bc68b3944ec
--- /dev/null
+++ b/gdb/29k-share/udi/udisoc.h
@@ -0,0 +1,184 @@
+/* This module defines constants used in the UDI IPC modules.
+
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+static char udisoc_h[]="@(#)udisoc.h 2.6 Daniel Mann";
+static char udisoc_h_AMD[]="@(#)udisoc.h 2.4, AMD";
+
+#define LOCAL static
+#define company_c 1 /* AMD Company id */
+#define product_c 1 /* socket IPC id */
+
+/* Enumerate the UDI procedure services
+*/
+#define UDIConnect_c 0
+#define UDIDisconnect_c 1
+#define UDISetCurrentConnection_c 2
+#define UDICapabilities_c 3
+#define UDIEnumerateTIPs_c 4
+#define UDIGetErrorMsg_c 5
+#define UDIGetTargetConfig_c 6
+#define UDICreateProcess_c 7
+#define UDISetCurrentProcess_c 8
+#define UDIDestroyProcess_c 9
+#define UDIInitializeProcess_c 10
+#define UDIRead_c 11
+#define UDIWrite_c 12
+#define UDICopy_c 13
+#define UDIExecute_c 14
+#define UDIStep_c 15
+#define UDIStop_c 16
+#define UDIWait_c 17
+#define UDISetBreakpoint_c 18
+#define UDIQueryBreakpoint_c 19
+#define UDIClearBreakpoint_c 20
+#define UDIGetStdout_c 21
+#define UDIGetStderr_c 22
+#define UDIPutStdin_c 23
+#define UDIStdinMode_c 24
+#define UDIPutTrans_c 25
+#define UDIGetTrans_c 26
+#define UDITransMode_c 27
+#define UDITest_c 28
+#define UDIKill_c 29
+
+#define udr_UDIInt8(udrs, obj) udr_work(udrs, obj, 1)
+#define udr_UDIInt16(udrs, obj) udr_work(udrs, obj, 2)
+#define udr_UDIInt32(udrs, obj) udr_work(udrs, obj, 4)
+#define udr_UDIInt(udrs, obj) udr_work(udrs, obj, 4)
+
+#define udr_UDIUInt8(udrs, obj) udr_work(udrs, obj, 1)
+#define udr_UDIUInt16(udrs, obj) udr_work(udrs, obj, 2)
+#define udr_UDIUInt32(udrs, obj) udr_work(udrs, obj, 4)
+#define udr_UDIUInt(udrs, obj) udr_work(udrs, obj, 4)
+
+#define udr_UDIBool(udrs, obj) udr_UDIInt32(udrs, obj)
+#define udr_UDICount(udrs, obj) udr_UDIInt32(udrs, obj)
+#define udr_UDISize(udrs, obj) udr_UDIUInt32(udrs, obj)
+#define udr_CPUSpace(udrs, obj) udr_UDIInt32(udrs, obj)
+#define udr_CPUOffset(udrs, obj) udr_UDIUInt32(udrs, obj)
+#define udr_CPUSizeT(udrs, obj) udr_UDIUInt32(udrs, obj)
+#define udr_UDIBreakId(udrs,obj) udr_UDIUInt(udrs, obj)
+#define udr_UDISizeT(udrs, obj) udr_UDIUInt(udrs, obj)
+#define udr_UDIMode(udrs, obj) udr_UDIUInt(udrs, obj)
+
+#define udr_UDIHostMemPtr(udrs, obj) udr_UDIUInt32(udrs, obj)
+#define udr_UDIVoidPtr(udrs, obj) udr_UDIUInt32(udrs, obj)
+#define udr_UDIPId(udrs, obj) udr_UDIUInt(udrs, obj)
+#define udr_UDISessionId(udrs, obj) udr_UDIInt32(udrs, obj)
+#define udr_UDIError(udrs, obj) udr_UDIInt32(udrs, obj)
+#define udr_UDIStepType(udrs, obj) udr_UDIInt32(udrs, obj)
+#define udr_UDIBreakType(udrs, obj) udr_UDIInt32(udrs, obj)
+
+
+#define UDR_ENCODE 1
+#define UDR_DECODE 2
+
+typedef struct UDR_str
+{
+ int udr_op; /* UDR operation */
+ int previous_op;
+ int sd;
+ int bufsize;
+ char* buff;
+ char* getbytes;
+ char* putbytes;
+ char* putend;
+ int domain;
+ char* soc_name;
+} UDR;
+
+/******************************************* Declare UDR suport functions */
+int udr_create UDIParams((
+ UDR* udrs,
+ int sd,
+ int size
+ ));
+
+int udr_free UDIParams((
+ UDR* udrs,
+ ));
+
+int udr_signal UDIParams((
+ UDR* udrs,
+ ));
+
+int udr_sendnow UDIParams((
+ UDR* udrs
+ ));
+
+int udr_work UDIParams((
+ UDR* udrs,
+ void* object_p,
+ int size
+ ));
+
+int udr_UDIResource UDIParams((
+ UDR* udrs,
+ UDIResource* object_p
+ ));
+
+int udr_UDIRange UDIParams((
+ UDR* udrs,
+ UDIRange* object_p
+ ));
+
+int udr_UDIMemoryRange UDIParams((
+ UDR* udrs,
+ UDIMemoryRange* object_p
+ ));
+
+int udr_UDIMemoryRange UDIParams((
+ UDR* udrs,
+ UDIMemoryRange* object_p
+ ));
+
+int udr_int UDIParams((
+ UDR* udrs,
+ int* int_p
+ ));
+
+int udr_bytes UDIParams((
+ UDR* udrs,
+ char* ptr,
+ int len
+ ));
+
+char* udr_inline UDIParams((
+ UDR* udrs,
+ int size
+ ));
+
+char* udr_getpos UDIParams((
+ UDR* udrs
+ ));
+int udr_setpos UDIParams((
+ UDR* udrs,
+ char* pos
+ ));
+
+int udr_readnow UDIParams((
+ UDR* udrs,
+ int size
+ ));
+
+int udr_align UDIParams((
+ UDR* udrs,
+ int size,
+ ));
diff --git a/gdb/29k-share/udi/udr.c b/gdb/29k-share/udi/udr.c
new file mode 100644
index 00000000000..10a9f38c6ae
--- /dev/null
+++ b/gdb/29k-share/udi/udr.c
@@ -0,0 +1,427 @@
+/* This module supports sending and receiving data objects over a
+ socket conection.
+
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+static char udr_c[]="@(#)udr.c 2.8 Daniel Mann";
+static char udr_c_AMD[]="@(#)udr.c 2.3, AMD";
+/*
+* All data is serialised into a character stream,
+* and de-serialised back into the approproiate objects.
+********************************************************************** HISTORY
+*/
+/* This is all unneeded on DOS machines. */
+#ifndef __GO32__
+
+#include <stdio.h>
+#include <sys/types.h>
+
+/* This used to say sys/fcntl.h, but the only systems I know of that
+ require that are old (pre-4.3, at least) BSD systems, which we
+ probably don't need to worry about. */
+#include <fcntl.h>
+
+#include <sys/socket.h>
+#include "udiproc.h"
+#include "udisoc.h"
+
+extern int errno;
+extern char* malloc();
+
+/* local type decs. and macro defs. not in a .h file ************* MACRO/TYPE
+*/
+
+/* global dec/defs. which are not in a .h file ************* EXPORT DEC/DEFS
+*/
+int udr_errno; /* error occurs during UDR service */
+
+/* local dec/defs. which are not in a .h file *************** LOCAL DEC/DEFS
+*/
+
+/****************************************************************** UDR_CREATE
+* Build UDR structure for character stream processing.
+*/
+int udr_create(udrs, sd, size)
+UDR* udrs;
+int sd;
+int size;
+{
+ udrs->sd = sd;
+ if(!udrs->buff) udrs->buff = malloc(size);
+ udrs->getbytes = udrs->buff; /* set the buffer to the start */
+ udrs->putbytes = udrs->buff;
+ udrs->putend = udrs->buff;
+ udrs->udr_op = -1; /* don't know the direction */
+ udrs->previous_op = -1; /* don't know the direction */
+ udrs->bufsize = size;
+ return 0;
+}
+
+/******************************************************************** UDR_FREE
+* Free USR structure and close socket.
+*/
+int udr_free(udrs)
+UDR* udrs;
+{
+ close(udrs->sd);
+ free(udrs->buff);
+ return 0;
+}
+
+/****************************************************************** UDR_SIGNAL
+* Send a signal to the process at the other end of the socket,
+* indicating that it should expect to recieve a new message shortly.
+*/
+int udr_signal(udrs)
+UDR* udrs;
+{
+ if(send(udrs->sd, "I", 1, MSG_OOB) == -1)
+ { perror("ERROR, udr_signal(), send(...MSG_OOB)");
+ udr_errno = UDIErrorIPCInternal;
+ return -1; /* return error code */
+ }
+ return 0;
+}
+
+/***************************************************************** UDR_SENDNOW
+* used to flush the current character stream buffer to
+* the associated socket. */
+int udr_sendnow(udrs)
+UDR* udrs;
+{
+ int size = (UDIUInt32)(udrs->putend) - (UDIUInt32)(udrs->buff);
+ if(udrs->previous_op == 0)
+ { udr_errno = UDIErrorIPCInternal;
+ return -1;
+ }
+ udrs->putbytes = udrs->buff;
+ udrs->putend = udrs->buff;
+ if (write(udrs->sd, udrs->buff, size) == -1)
+ { perror("ERROR, udr_sendnow(), write() call: ");
+ udr_errno = UDIErrorIPCInternal;
+ return -1; /* return error code */
+ }
+ return 0;
+}
+
+/******************************************************************** UDR_WORK
+* Function to send or recieve data from the buffers supporting
+* socket communication. The buffer contains serialised objects
+* sent/recieved over a socket connection.
+*/
+int udr_work(udrs, object_p, size)
+UDR* udrs;
+void* object_p;
+int size;
+{
+ int cnt, remain;
+
+ if(udrs->udr_op != udrs->previous_op)
+ { if(udrs->previous_op == 0)
+ { udr_errno = UDIErrorIPCInternal;
+ return -1;
+ }
+ udrs->previous_op= udrs->udr_op;
+ udrs->putbytes = udrs->buff;
+ udrs->getbytes = udrs->buff;
+ }
+
+ if(udrs->udr_op == UDR_ENCODE)
+ { /* write data into character stream buffer */
+ if( (UDIUInt32)(udrs->putbytes) + size >
+ (UDIUInt32)(udrs->buff) + (UDIUInt32)(udrs->bufsize) )
+ { udr_errno = UDIErrorIPCInternal;
+ return -1;
+ }
+ memcpy(udrs->putbytes, (char*)object_p, size);
+ udrs->putbytes += size;
+ if(udrs->putbytes > udrs->putend) udrs->putend = udrs->putbytes;
+ }
+ else if(udrs->udr_op == UDR_DECODE)
+ {
+ if( (UDIUInt32)(udrs->putbytes)-(UDIUInt32)(udrs->getbytes) < size )
+ { /* need more data in character stream buffer */
+ remain = (UDIUInt32)(udrs->bufsize) -
+ ( (UDIUInt32)(udrs->putbytes)-(UDIUInt32)(udrs->buff) );
+ if( ((UDIUInt32)(udrs->bufsize) + (UDIUInt32)(udrs->buff)
+ - (UDIUInt32)(udrs->getbytes)) < size)
+ { udr_errno = UDIErrorIPCInternal;
+ return -1;
+ }
+ cnt = read(udrs->sd, (char*)udrs->putbytes, remain);
+ if(cnt == -1) perror("ERROR udr_work(), read() failure: ");
+ udrs->putbytes += cnt;
+ if( (UDIUInt32)(udrs->putbytes)-(UDIUInt32)(udrs->getbytes) < size )
+ { udr_errno = UDIErrorIPCInternal;
+ return -1; /* return error code */
+ }
+ } /* read data from character stream buffer */
+ memcpy((char*)object_p, udrs->getbytes, size);
+ udrs->getbytes += size;
+ }
+ else
+ { udr_errno = UDIErrorIPCInternal;
+ return -1;
+ }
+ return 0;
+}
+
+/************************************************************* UDR_UDIResource
+*/
+int udr_UDIResource(udrs, object_p)
+UDR* udrs;
+UDIResource* object_p;
+{
+ int retval;
+
+ retval = udr_CPUSpace(udrs, &object_p->Space);
+ retval = retval | udr_CPUOffset(udrs, &object_p->Offset);
+ return retval;
+}
+
+/**************************************************************** UDR_UDIRange
+*/
+int udr_UDIRange(udrs, object_p)
+UDR* udrs;
+UDIRange* object_p;
+{
+ int retval;
+
+ retval = udr_CPUOffset(udrs, &object_p->Low);
+ retval = retval | udr_CPUOffset(udrs, &object_p->High);
+ return retval;
+}
+
+/********************************************************** UDR_UDIMemoryRange
+*/
+int udr_UDIMemoryRange(udrs, object_p)
+UDR* udrs;
+UDIMemoryRange* object_p;
+{
+ int retval;
+
+ retval = udr_CPUSpace(udrs, &object_p->Space);
+ retval = retval | udr_CPUOffset(udrs, &object_p->Offset);
+ retval = retval | udr_CPUSizeT(udrs, &object_p->Size);
+ return retval;
+}
+
+/****************************************************************** UDR_string
+*/
+int udr_string(udrs, sp)
+UDR* udrs;
+char* sp;
+{
+ int len, retval;
+
+ if(udrs->udr_op == UDR_ENCODE)
+ {
+ if(sp)
+ { len = strlen(sp) + 1;
+ retval = udr_UDIInt32(udrs, &len);
+ retval = retval | udr_work(udrs, sp, len);
+ }
+ else /* deal with NULL pointer */
+ { len = 0;
+ retval = udr_UDIInt32(udrs, &len);
+ }
+ }
+ else if(udrs->udr_op == UDR_DECODE)
+ {
+ retval = udr_UDIInt32(udrs, &len);
+ if(len)
+ retval = retval | udr_work(udrs, sp, len);
+ else *sp = '\0'; /* terminate string */
+ }
+ else
+ { udr_errno = UDIErrorIPCInternal;
+ return -1;
+ }
+ return retval;
+}
+
+/******************************************************************* UDR_BYTES
+*/
+int udr_bytes(udrs, ptr, len)
+UDR* udrs;
+char* ptr;
+int len;
+{
+ return udr_work(udrs, ptr, len);
+}
+
+/********************************************************************* UDR_INT
+*/
+int udr_int(udrs, int_p)
+UDR* udrs;
+int* int_p;
+{
+ int ret_val;
+ UDIInt32 udr_obj; /* object of know size */
+
+ if(udrs->udr_op == UDR_ENCODE)
+ {
+ udr_obj = *int_p; /* copy into know object size */
+ return udr_UDIInt32(udrs, &udr_obj);
+ }
+ else if(udrs->udr_op == UDR_DECODE)
+ {
+ ret_val = udr_UDIInt32(udrs, &udr_obj); /* get object of known size */
+ *int_p = udr_obj;
+ return ret_val;
+ }
+ else
+ { udr_errno = UDIErrorIPCInternal;
+ return -1;
+ }
+}
+
+/****************************************************************** UDR_INLINE
+*/
+char* udr_inline(udrs, size)
+UDR* udrs;
+int size;
+{
+ if(udrs->udr_op != udrs->previous_op)
+ { if(udrs->previous_op == 0)
+ { udr_errno = UDIErrorIPCInternal;
+ return 0;
+ }
+ udrs->previous_op= udrs->udr_op;
+ udrs->putbytes = udrs->buff;
+ udrs->getbytes = udrs->buff;
+ }
+ if(udrs->udr_op == UDR_ENCODE)
+ {
+ if(udrs->putbytes + size > udrs->bufsize + udrs->buff)
+ return 0;
+ udrs->putbytes += size;
+ return udrs->putbytes - size;
+ }
+ else if(udrs->udr_op == UDR_DECODE)
+ {
+ if(udrs->getbytes + size > udrs->bufsize + udrs->buff)
+ return 0;
+ udrs->getbytes += size;
+ return udrs->getbytes - size;
+ }
+ else
+ { udr_errno = UDIErrorIPCInternal;
+ return 0;
+ }
+}
+
+/****************************************************************** UDR_GETPOS
+*/
+char* udr_getpos(udrs)
+UDR* udrs;
+{
+ if(udrs->udr_op == UDR_ENCODE)
+ {
+ return udrs->putbytes;
+ }
+ else if(udrs->udr_op == UDR_DECODE)
+ {
+ return udrs->getbytes;
+ }
+ else
+ { udr_errno = UDIErrorIPCInternal;
+ return 0;
+ }
+}
+
+/****************************************************************** UDR_SETPOS
+*/
+int udr_setpos(udrs, pos)
+UDR* udrs;
+char* pos;
+{
+ if( ((UDIUInt32)pos > (UDIUInt32)(udrs->buff) + (UDIUInt32)(udrs->bufsize))
+ || ((UDIUInt32)pos < (UDIUInt32)(udrs->buff) ) )
+ { udr_errno = UDIErrorIPCInternal;
+ return 0;
+ }
+ if(udrs->udr_op == UDR_ENCODE)
+ {
+ udrs->putbytes = pos;
+ return 1;
+ }
+ else if(udrs->udr_op == UDR_DECODE)
+ {
+ udrs->getbytes = pos;
+ return 1;
+ }
+ else
+ { udr_errno = UDIErrorIPCInternal;
+ return 0;
+ }
+}
+
+/***************************************************************** UDR_READNOW
+* Try and ensure "size" bytes are available in the
+* receive buffer character stream.
+*/
+int udr_readnow(udrs, size)
+UDR* udrs;
+int size;
+{
+ int cnt, remain;
+
+ if(udrs->udr_op == UDR_ENCODE)
+ {
+ udr_errno = UDIErrorIPCInternal;
+ return -1;
+ }
+ else if(udrs->udr_op == UDR_DECODE)
+ {
+ if( (UDIUInt32)(udrs->putbytes)-(UDIUInt32)(udrs->getbytes) < size )
+ { /* need more data in character stream buffer */
+ remain = (UDIUInt32)(udrs->bufsize) -
+ ( (UDIUInt32)(udrs->putbytes)-(UDIUInt32)(udrs->buff) );
+ cnt = read(udrs->sd, (char*)udrs->putbytes, remain);
+ if(cnt == -1) perror("ERROR udr_work(), read() failure: ");
+ udrs->putbytes += cnt;
+ if( (UDIUInt32)(udrs->putbytes)-(UDIUInt32)(udrs->getbytes) < size )
+ { fprintf(stderr,"ERROR, udr_readnow() too few bytes in stream\n");
+ return -1; /* return error code */
+ }
+ }
+ }
+ else
+ { udr_errno = UDIErrorIPCInternal;
+ return -1;
+ }
+ return 0;
+}
+
+/******************************************************************* UDR_ALIGN
+*/
+int udr_align(udrs, size)
+UDR* udrs;
+int size;
+{
+ char* align;
+ int offset;
+
+ align = udr_getpos(udrs);
+ offset = size - ((int)align & (size -1));
+ offset = offset & (size -1);
+ if(offset) udr_setpos(udrs, align + offset);
+}
+#endif /* __GO32__ */
diff --git a/gdb/29k-share/udi_soc b/gdb/29k-share/udi_soc
new file mode 100644
index 00000000000..343317f255f
--- /dev/null
+++ b/gdb/29k-share/udi_soc
@@ -0,0 +1,9 @@
+# @(#)udi_soc 2.1 Daniel Mann
+# NOTE: the Session string must not start whith white-space characters.
+# Format of string is:
+# <session> <domain> <soc_name|host_name> <tip_exe> <pass to UDIconnect>
+soc2cayman AF_INET cayman /bin/udi_tip ...
+soc2tip AF_UNIX astring tip.exe ...
+cuba AF_UNIX soc_name ../bin.68020/udi_tip stuff to pass
+cayman AF_INET cayman this_entry_not_matter stuff to pass
+iss AF_UNIX * sun4/isstip -r osboot
diff --git a/gdb/COPYING b/gdb/COPYING
new file mode 100644
index 00000000000..60549be514a
--- /dev/null
+++ b/gdb/COPYING
@@ -0,0 +1,340 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 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
+
+ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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/gdb/ChangeLog b/gdb/ChangeLog
new file mode 100644
index 00000000000..0ae5117e624
--- /dev/null
+++ b/gdb/ChangeLog
@@ -0,0 +1,1116 @@
+1999-04-07 Jim Blandy <jimb@zwingli.cygnus.com>
+
+ * GDB 4.18 released.
+
+1999-04-06 Jim Blandy <jimb@zwingli.cygnus.com>
+
+ * README: Change revision numbers in text to "4.18".
+ * Makefile.in (VERSION): Set to 4.18.
+
+1999-04-06 Stan Shebs <shebs@andros.cygnus.com>
+
+ * solib.c (clear_solib): Don't call disable_breakpoints_in_shlibs,
+ this breaks rerunning on sun4 native.
+
+1999-04-05 Stan Shebs <shebs@andros.cygnus.com>
+
+ * NEWS: Incorporate suggestions from David Taylor and Jason Molenda.
+
+1999-04-02 Jim Blandy <jimb@zwingli.cygnus.com>
+
+ * README: Note that GDB requires an ANSI C compiler, and explain
+ how to get GCC.
+
+ * README: Update.
+ It says we provide HTML documentation, but we don't.
+ The instructions for building the .info files were wrong.
+ It didn't mention that texinfo.tex was provided with GDB.
+ It didn't mention the intl, texinfo, etc, or util directories.
+ (Perhaps util would be best left unmentioned.)
+ It didn't mention the --enable-build-warnings flag, or the --host
+ flag.
+ It didn't mention remote-array.c or remote-d10v.c.
+ It had an old address for reporting bugs. It's now gdb@gnu.org.
+ It mentioned xxgdb, which is obsolete, but didn't mention DDD.
+
+ * config/sparc/nm-linux.h: Don't redefine PT_ATTACH to use the
+ deprecated PTRACE_SUNATTACH compatibility commands. The
+ definitions from <sys/ptrace.h> are fine.
+
+1999-04-01 Stan Shebs <shebs@andros.cygnus.com>
+
+ * NEWS: Add more notes about user-visible changes.
+
+1999-04-01 Jim Blandy <jimb@zwingli.cygnus.com>
+
+ Fix for cross-debugging on an AIX host from Johanna Svenningsson:
+ * ax-gdb.h (enum axs_lvalue_kind): Remove trailing comma from enum.
+ * ax.h (enum agent_op, enum agent_flaws): Same.
+ * tracepoint.h (enum actionline_type): Same.
+ * config/xm-aix4.h: Add declaration for termdef.
+
+1999-03-31 Stan Shebs <shebs@andros.cygnus.com>
+
+ * jv-lang.h (dynamics_objfile): Remove decl, conflicts with static
+ decl in jv-lang.c.
+
+1999-03-31 Jim Blandy <jimb@zwingli.cygnus.com>
+
+ Mon Mar 29 14:40:44 1999 David Taylor <taylor@ryobi.cygnus.com>
+
+ * valops.c (search_struct_field): revert HP merge change
+ to this function -- it causes messages to be printed about
+ member class ambiguity when the compiler is happy.
+ (search_struct_field_aux): delete -- added as part of HP merge
+ change; with aforementioned change it is no longer called.
+
+1999-03-26 Jim Blandy <jimb@zwingli.cygnus.com>
+
+ Merged change from Keith Seitz:
+
+ 1999-03-16 Keith Seitz <keiths@cygnus.com>
+
+ * remote.c (reomte_binary_checked): New file global.
+ (check_binary_download): New function to check if
+ stub supports binary downloading that works with
+ stubs that are not eight bit clean.
+ (remote_write_bytes): Check for binary download capability
+ and use it if available.
+ Remove references to global remote_binary_length. What a hack.
+ (putpkt_binary): New function.
+ (putpkt): Call putpkt_binary.
+ Use xor to escape trouble characters.
+ * m32r-stub.c (bin2mem): Follow escape char convention change.
+
+ Applied patch from Stu Grossman:
+
+ Mon Feb 22 12:32:19 1999 Per Bothner <bothner@cygnus.com>
+
+ * jv-valprint.c (java_val_print): Restore line that somehow got lost.
+
+1999-03-24 Stan Shebs <shebs@andros.cygnus.com>
+
+ * Makefile (VERSION): Bump to 4.17.87.
+
+ Attempt to sort out SCO-related configs.
+ * configure.host (i[3456]86-*-sysv4.2*): Use instead of
+ i[3456]86-*-sysv4.2MP and i[3456]86-*-sysv4.2uw2*.
+ (i[3456]86-*-sysv5*): Recognize.
+ * configure.tgt (i[3456]86-*-sco3.2v5*, i[3456]86-*-sco3.2v4*):
+ Recognize.
+
+Wed Mar 24 01:01:27 1999 Andrew Cagney <cagney@sludge.cygnus.com>
+
+ * rs6000-tdep.c (rs6000_software_single_step): Change SIGNAL to
+ unsigned int.
+
+ From Rodney Brown <rodneybrown@pmsc.com>:
+ * target.h (enum thread_control_capabilities), breakpoint.h (enum
+ bptype), breakpoint.c (enum insertion_state_t): Strict ISO-C
+ doesn't allow trailing comma in enum definition.
+
+1999-03-23 Jason Molenda (jsm@bugshack.cygnus.com)
+
+ * hppa-tdep.c (pa_register_look_aside): Remove CPU_HPPA_RISC_20
+ check, test for presence of struct save_state_t and the ss_wide
+ member directly.
+ * configure.in: Remove CPU_HPPA_RISC_20 test. Add tests for
+ HAVE_STRUCT_SAVE_STATE_T and HAVE_STRUCT_MEMBER_SS_WIDE.
+ * acconfig.h: Add HAVE_STRUCT_SAVE_STATE_T HAVE_STRUCT_MEMBER_SS_WIDE.
+ * configure, config.in: Regenerated.
+
+Tue Mar 23 17:22:57 1999 Philippe De Muyter <phdm@macqel.be>
+
+ * remote.c, parse.c: Include ctype.h.
+
+Mon Mar 22 13:25:13 1999 Michael Snyder <msnyder@cleaver.cygnus.com>
+
+ * infttrace.c (proc_wait): rename to ptrace_wait.
+
+1999-03-17 Jason Molenda (jsm@bugshack.cygnus.com)
+
+ * configure.in (HAVE_MULTIPLE_PROC_FDS): Don't define for Solaris
+ hosts--gdb doesn't support this yet.
+ * configure: Regenerated.
+
+Tue Mar 16 01:11:33 1999 Andrew Cagney <cagney@rhino.cygnus.com>
+
+ * target.h (struct target_ops), target.c (debug_to_query),
+ remote.c (pack_hex_byte, remote_query): Promote char parameters to
+ int. Stops compile problems with pedantic ISO-C compilers.
+
+Tue Mar 16 15:29:04 1999 Stan Shebs <shebs@andros.cygnus.com>
+
+ * jv-lang.c, jv-lang.h (java_primitive_type): Declare argument
+ as int instead of char.
+
+1999-03-15 Jim Blandy <jimb@zwingli.cygnus.com>
+
+ Merged changes for binary downloads from Michael Snyder:
+
+ Fri Mar 12 13:11:48 1999 Michael Snyder <msnyder@cleaver.cygnus.com>
+
+ * remote.c (remote_write_bytes): fix 'X' packet protocol so that it
+ can't overwrite the end of its buffer with escaped characters.
+
+1999-03-12 Jim Blandy <jimb@zwingli.cygnus.com>
+
+ Merged changes for HP/UX 9 from Jason Molenda:
+
+ 1999-03-08 Jason Molenda (jsm@bugshack.cygnus.com)
+
+ * infttrace.c (hppa_get_process_events): Removed. Function only
+ usable on HPUX 10 and above. It is not called by any other part
+ of GDB.
+ * hppah-nat.c (hppa_get_process_events): Ditto.
+ (child_pid_to_exec_file): Only call ptrace with PT_GET_PROCESS_PATHNAME
+ if that symbol has been defined.
+ * config/pa/nm-hppah.h: Don't set up prototypes et al for
+ hppa_get_process_events.
+
+ * config/pa/hppahpux.mh (TERM_LIB): Do not initialize, let autoconf
+ determine best library automatically.
+ * config/pa/hpux1020.mh: Ditto.
+ * config/pa/hpux1100.mh: Ditto.
+ * configure.in (TERM_LIB): Also check for libHcurses.
+ * configure: Regenerated.
+
+ Merged changes to accomodate the Hurd:
+
+ Thu Mar 11 18:05:11 1999 Michael Snyder <msnyder@cleaver.cygnus.com>
+
+ * infptrace.c (proc_wait): Rename to ptrace_wait.
+ * inftarg.c (child_wait): call ptrace_wait instead of proc_wait.
+ * inferior.h: Declare ptrace_wait instead of proc_wait.
+
+1999-03-11 Jim Blandy <jimb@zwingli.cygnus.com>
+
+ * Makefile.in (VERSION): click to 4.17.86, for next snapshot.
+
+1999-03-09 Rodney Brown <RodneyBrown@pmsc.com>
+
+ Get working on UnixWare 2.1.1.
+ * acconfig.h: Update for defines for procfs.c.
+ * configure.in: Identify defines for procfs.c.
+ * configure.host: i386-*-sysv4.2uw2* => i386v42mp
+ * configure.tgt: i386-*-sysv4.2uw2* => i386v42mp
+ * configure, config.in: Regenerate.
+ * procfs.c: Rename HAVE_NO_PRRUN_T to HAVE_PRRUN_T (autoconf
+ standard), wrap UNIXWARE difference in THE_PR_LWP macro for
+ legibility.
+ * config/i386/tm-i386v42mp.h: Remove HAVE_PSTATUS_T,
+ HAVE_NO_PRRUN_T; now set by configure.
+
+1999-03-04 Jim Blandy <jimb@zwingli.cygnus.com>
+
+ Merged changes from Jason Molenda:
+
+ 1999-02-24 Jason Molenda (jsm@bugshack.cygnus.com)
+
+ * configure.in: Set CPU_HPPA_RISC_20 if the host CPU is a PA 2.0
+ processor.
+ * acconfig.h: Add CPU_HPPA_RISC_20
+ * config.in, configure: Regenerated.
+ * hppa-tdep.c (pa_register_look_aside): Only refer to new
+ structure elements if we are on a PA2.0 system.
+ * defs.h: Include limits.h.
+
+ Merged changes from Stu Grossman:
+
+ Wed Feb 17 10:10:27 1999 Stu Grossman <grossman@babylon-5.cygnus.com>
+
+ * gdbtypes.h (get_discrete_bounds): Remove duplicate decl.
+
+ * jv-typeprint.c (java_type_print_base): Change fputs => fputs_filtered.
+
+ Mon Jan 25 18:30:57 1999 Per Bothner <bothner@cygnus.com>
+
+ * jv-lang.h (JAVA_OBJECT_SIZE): Change from hard-wired constant.
+ (java_primitive_type_from_name, get_java_object_header_size): Declare.
+ * jv-lang.c (java_class_from_object): Use get_java_object_type.
+ * jv-lang.c: Update Class field names: dtable->vtable,
+ msize->method_count, nfields->field_count, bfsize->size_in_bytes,
+ nmethods->method_count.
+ (type_from_class): Demangle array type names.
+ (java_link_class_type): Array type names are now demangled.
+ (get_java_object_type): If not defined yet, try looking it up.
+ (get_java_object_header_size): New function.
+ (java_primitive_type_from_name): New function.
+ (java_demangled_signature_length, java_demangled_signature_copy): New.
+ (java_demangle_type_signature): Re-implement using above functions.
+ (evaluate_subexp_java): For UNOP_IND, call evaluate_subexp_java
+ to evaluate subexp (not evaluate_subexp_standard).
+ For BINOP_SUBSCRIPT update for new array type naming scheme.
+ * jv-valprint.c (java_value_print): Use java_class_from_object.
+ Update array printing to new array type naming convention.
+ (java_val_print): Doing check_typedef when printing a pointer is
+ is a waste of effort. Also, handle TYPE_CODE_INT, to make sure
+ Java bytes as not printed as C chars.
+
+ Fri Jan 8 16:58:22 1999 Stu Grossman <grossman@babylon-5.cygnus.com>
+
+ * blockframe.c (find_pc_sect_partial_function): Search full symtabs as
+ a last ditch effort (after the partial & minimal symtabs).
+ * defs.h utils.c: Fixup prototypes for vprintf_filtered,
+ vfprintf_filtered, vfprintf_unfiltered and vprintf_unfiltered to return
+ ints to match their standard equivalents.
+ * defs.h symtab.c top.c: Create skip_prologue_hook to allow Java to
+ control the prologue skipping process.
+ * jv-typeprint.c (java_type_print_base): Remove extern for
+ jv_class_demangle, add new arg for objfile (NULL).
+ * symtab.h: Remove struct sourcevector and struct source. Definately
+ not needed.
+ * values.c (value_virtual_fn_field): Fixes code to handle new vtable
+ debug info format. Patch from marka.
+
+ Wed Dec 16 23:11:25 1998 Stu Grossman <grossman@fencer.cygnus.com>
+
+ * jv-lang.c (java_class_from_object java_class_is_primitive
+ is_object_type): Change dtable to vtable.
+ * (java_primitive_type): Change arg to type char.
+ * (_initialize_java_language): Make java_char_type be unsigned.
+ * jv-lang.h: Fixup prototypes.
+
+ Mon Dec 7 19:02:15 1998 Stu Grossman <grossman@babylon-5.cygnus.com>
+
+ * jv-valprint.c (java_value_print): Fix printing of values where
+ run time type != compile time type.
+
+ Fri Dec 4 15:23:38 1998 Stu Grossman <grossman@fencer.cygnus.com>
+
+ * Makefile.in: Whack out m2-typeprint.c.
+ * c-typeprint.c (c_type_print_varspec_suffix) typeprint.h: Make this
+ global. It's needed by Java.
+ * (c_type_print_base): Whack prefix off of qualified method names
+ (names with name spaces).
+ * gdbtypes.h (struct cplus_struct_type): Add bits for Java attributes.
+ Shrink voffset
+ to 16 bits to compensate for added bits above (hopefully this is still
+ enough).
+ * Add new accessor macros (TYPE_FND_FIELD_PUBLIC, ...) for all new
+ attribute bits.
+ * jv-typeprint.c (java_type_print_base): Fix printing of method
+ attributes. Handle JVM style manglings.
+ * (java_print_type): Enable code type print varspec_suffix to allow
+ array indices to print out.
+ * jv-valprint.c (java_val_print): Minor formatting.
+ * m2-lang.c (m2_language_d): Change m2_print_type to c_print_type.
+ * stabsread.c (read_member_functions): Save public and static attributes.
+
+1999-03-02 Stan Shebs <shebs@andros.cygnus.com>
+
+ From Gary Thomas <gthomas@cygnus.co.uk>:
+ * arm-tdep.c (ARM_LE_BREAKPOINT, ARM_BE_BREAKPOINT,
+ THUMB_LE_BREAKPOINT, THUMB_BE_BREAKPOINT): Use illegal instruction
+ instead of SWI 24.
+ * config/arm/tm-arm.h (CALL_DUMMY): Ditto.
+ (IN_SIGTRAMP): Define.
+
+1999-03-01 Jim Blandy <jimb@zwingli.cygnus.com>
+
+ * configure.in (TERM_LIB): Move the code which sets this to a
+ better place.
+
+1999-02-25 Stan Shebs <shebs@andros.cygnus.com>
+
+ * breakpoint.c (SOLIB_LOADED_LIBRARY_PATHNAME,
+ SOLIB_UNLOADED_LIBRARY_PATHNAME, SOLIB_CREATE_CATCH_LOAD_HOOK,
+ SOLIB_CREATE_CATCH_UNLOAD_HOOK): Supply default definitions.
+ * infrun.c (SOLIB_IN_DYNAMIC_LINKER): Ditto.
+
+1999-02-23 Jim Blandy <jimb@zwingli.cygnus.com>
+
+ Patch from Jason Molenda (jsm@bugshack.cygnus.com)
+ * configure.in (TERM_LIB): Move checking for TERM_LIB, substituting.
+ * configure, aclocal.m4, config.in: Regenerated.
+
+1999-02-22 Jim Blandy <jimb@zwingli.cygnus.com>
+
+ * Makefile.in (VERSION): Bump to 4.17.85, for the release process.
+
+ Patch from Elena Zannoni <ezannoni@kwikemart.cygnus.com>
+ * breakpoint.c (watch_command_1): Reformat comment.
+
+ Patch from Elena Zannoni <ezannoni@kwikemart.cygnus.com>
+ * c-typeprint.c (c_type_print_base): Reformat comments.
+
+ Patch from Edith Epstein <eepstein@sophia.cygnus.com>:
+ * config/pa/nm-hppah.h: Added prototype declarations for
+ hppa_enable_page_protection_events and
+ hppa_disable_page_protection_events.
+
+ Patch from Edith Epstein <eepstein@sophia.cygnus.com>:
+ * infttrace.c (hppa_insert_hw_watchpoint): Make sure that
+ function always returns a value.
+ (hppa_remove_hw_watchpoint): Make sure that function always
+ returns a value.
+
+ Patch from Edith Epstein <eepstein@sophia.cygnus.com>:
+ * inftarg.c (child_wait): Fixed code that checks whether
+ or not the target program has done a fork/vfork.
+ related_pid does not have a value unless the target
+ program has forked/vforked.
+
+1999-02-22 Jim Blandy <jimb@zwingli.cygnus.com>
+
+ * tm-h8500.h, i386lynx-nat.c: Removed. These files are long
+ dead; it seems that they only appeared due to some CVS weirdness.
+ If they appear again, we may need to distribute garlic and holy
+ water.
+
+1999-02-16 Jim Blandy <jimb@zwingli.cygnus.com>
+
+ * Makefile.in (VERSION): Bump to 4.17.2.
+
+Sun Feb 14 18:21:08 1999 Mark Alexander <marka@cygnus.com>
+
+ * config/sh/tm-sh.h (BELIEVE_PCC_PROMOTION): Define, so that
+ coffread.c will correctly handle char or short function parameters.
+
+1999-02-11 Jason Molenda (jsm@bugshack.cygnus.com)
+
+ * configure, aclocal.m4: Regenerate with correct version of aclocal.
+
+1999-02-10 Syd Polk <spolk@cygnus.com>
+
+ * acinclude.m4: Fix for new location of itclConfig.sh and itkConfig.sh.
+ * aclocal.m4: Regnerate.
+ * configure: Regenerate.
+
+1999-02-10 Jason Molenda (jsm@bugshack.cygnus.com)
+
+ * demangle.c: Fix comments to mention "set demangle-style"
+ instead of "set demangle".
+ Run through indent to fix minor indenting problems.
+
+Wed Feb 10 17:53:09 1999 Bob Manson <manson@charmed.cygnus.com>
+
+ * i386-tdep.c (gdb_print_insn_i386): Add missing returns.
+
+Wed Feb 10 13:17:21 1999 Stan Shebs <shebs@andros.cygnus.com>
+
+ Declare Gould configuration obsolete:
+ * configure.host, configure.tgt: Comment out Gould configs.
+ * Makefile.in: Comment out Gould-related actions.
+ * gould-xdep.c, gould-tdep.c, config/gould/*: Comment out.
+ * NEWS: Mention obsolete status.
+
+1999-02-09 DJ Delorie <dj@cygnus.com>
+
+ * sparcl-tdep.c: UDP download works in cygwin
+
+1999-02-08 Jason Molenda (jsm@bugshack.cygnus.com)
+
+ * gnu-regex.c: Check ENABLE_NLS instead of HAVE_LIBINTL_H.
+ * configure.in: Don't check for libintl.h.
+ * configure, config.in: Regenerated.
+
+Mon Feb 8 18:10:50 1999 Stan Shebs <shebs@andros.cygnus.com>
+
+ * NEWS: Mention new X packet and PowerPC variant support.
+
+1999-02-08 Nick Clifton <nickc@cygnus.com>
+
+ * configure.host: Add support for StrongARM host.
+ * configure.tgt: Add support for StrongARM target.
+
+Mon Feb 8 12:05:05 1999 David Taylor <taylor@texas.cygnus.com>
+
+ * dsrec.c (make_srec): Cast targ_addr to int in call to sprintf
+ otherwise on big endian machine with a bfd_vma of 64 bits,
+ *everything* gets loaded at location 0.
+
+Mon Feb 7 10:05:43 1999 Frank Ch. Eigler <fche@cygnus.com>
+
+ * infrun.c (wait_for_inferior): Allow SIGTRAP to be "pass"ed
+ to target program.
+
+Fri Feb 5 16:46:14 1999 Stan Shebs <shebs@andros.cygnus.com>
+
+ * NEWS: Add mentions of various new things.
+
+Thu Feb 4 00:19:14 1999 Christopher Faylor <cgf@cygnus.com>
+
+ * configure.in: Move termcap determination later in the
+ file to catch setting of cygwin flag.
+ * configure: Regenerate.
+
+Wed Feb 3 14:16:38 1999 Christopher Faylor <cgf@cygnus.com>
+
+ * config/i386/cygwin.mh: Move TERMCAP test code to configure.in.
+ * configure.in: Treat libtermcap.a detection as a special case
+ when hosting on cygwin.
+ * configure: Regenerate.
+
+1999-02-03 Keith Seitz <keiths@cygnus.com>
+
+ * remote.c (remote_binary_download, remote_binary_length): New
+ static globals for dealing with binary transmissions.
+ (remote_write_bytes): Add support for binary downloads
+ by shadowing the "M" packet with a new "X" packet. This
+ defaults to ON; if the stub does not understand this, it
+ will fall back to using "M".
+ (putpkt): Add support for binary downloading.
+ * monitor.c (monitor_expect): The mon2000 monitor
+ on the MSA2000 will also emit random DC1/DC3 chars.
+ * m32r-stub.c: Change all char's to unsigned char's
+ to support binary downloading.
+ (handle_exception): Add support for binary downloading
+ via a new "X" packet.
+ (getpacket): Do NOT strip eighth bit of incoming chars.
+ Watch out for escaped characters in the incoming stream.
+ (putpacket): Do NOT strip eighth bit of incoming chars.
+ (bin2mem): New function to write binary data directly to
+ memory.
+ * m32r-rom.c: Add new "mon2000" target.
+
+Tue Feb 2 18:40:29 1999 Elena Zannoni <ezannoni@kwikemart.cygnus.com>
+
+ * hp-psymtab-read.c (hpread_build_psymtabs): Coerce first arg
+ passed to make_cleanup to the correct type.
+ (hpread_quick_traverse): Change fifth arg to call to
+ hpread_end_psymtab to be 0.
+ Compare CURR_MODULE_END to 0 rather than NULL.
+ Get rid of ifdef'ed out code.
+ (scan_procs): Get rid of ifdef'ed out code.
+
+ * somread.c (som_symfile_read): Coerce first argument passed to
+ make_cleanup to the correct type.
+
+Tue Feb 2 17:36:29 1999 Elena Zannoni <ezannoni@kwikemart.cygnus.com>
+
+ * hp-psymtab-read.c (do_pxdb): New function. Check whether the
+ file needs to be processed by pxdb (an HP debug info massaging
+ tool), if so call it.
+ (hpread_build_psymtabs): Initialize scan_start to 0 and
+ simplify flow of control.
+
+ * somread.c (som_symfile_read): Add call to do_pxdb (),
+ in hp-psymtab-read.c.
+
+ * symfile.c (symbol_file_add): Remove ifdef'ed out HPUX specific
+ code.
+ (symfile_bfd_open): Remove HPUXHPPA ifdef'ed code. Code is now
+ in hp-psymtab-read.c.
+
+1999-02-02 Martin Hunt <hunt@cygnus.com>
+
+ * printcmd.c (print_scalar_formatted): Use strcat to concat all
+ the output together before calling fprintf_filtered().
+
+1999-02-01 Jason Molenda (jsm@bugshack.cygnus.com)
+
+ * configure.in: Require autoconf 2.13.
+ (AM_EXEEXT): Replace with new AC_EXEEXT.
+ * acinclude.m4: Move itcl header macros from aclocal.m4 to here.
+ * aclocal.m4: Regenerated.
+ * configure: Regenerated.
+
+1999-02-01 Jim Blandy <jimb@zwingli.cygnus.com>
+
+ Allow PPC users to select which PPC/RS6000 variant they're
+ debugging at run-time. At the moment, the only thing this affects
+ is the set of registers visible.
+ * config/rs6000/tm-rs6000.h (REGISTER_NAME): Define this as a call
+ to the function rs6000_register_name.
+ (rs6000_register_name): Include extern decl.
+ (NUM_REGS): Bump to 183. What's the right way to do this?
+ (FIRST_UISA_SP_REGNUM, LAST_UISA_SP_REGNUM): Renamed from
+ FIRST_SP_REGNUM, LAST_SP_REGNUM.
+ (REGISTER_BYTES): Recompute this.
+ * rs6000-tdep.c: Renamed all uses of FIRST_SP_REGNUM and
+ LAST_SP_REGNUM to FIRST_UISA_SP_REGNUM and LAST_UISA_SP_REGNUM, with
+ some concomitant formatting changes.
+ #include "gdbcmd.h", so we can define commands here.
+ (struct variant): New structure.
+ (COMMON_UISA_REG_NAMES, PPC_UISA_SPR_NAMES, PPC_SEGMENT_REG_NAMES,
+ PPC_32_OEA_SPR_NAMES, num_registers): New macros.
+ (register_names_rs6000, register_names_uisa, register_names_403,
+ register_names_403GC, register_names_505, register_names_860,
+ register_names_601, register_names_602, register_names_603,
+ register_names_604, register_names_750, variants): New variables.
+ (rs6000_register_name, install_variant, find_variant_by_name,
+ install_variant_by_name, list_variants, show_current_variant,
+ set_processor, show_processor): New functions.
+ (_initialize_rs6000_tdep): Define new commands `set processor' and
+ `show processor', and call install_variant_by_name to set the
+ default variant.
+ * rs6000-nat.c: Renamed all uses of FIRST_SP_REGNUM and
+ LAST_SP_REGNUM to FIRST_UISA_SP_REGNUM and LAST_UISA_SP_REGNUM, with
+ some concomitant formatting changes.
+ * configure.in: Accept the `--with-cpu' flag, to specify a default
+ processor variant.
+ * acconfig.h: Provide a blurb for TARGET_CPU_DEFAULT, which is set
+ by configure's `--with-cpu' flag.
+ * config.in, configure: Regenerated.
+
+Sun Jan 31 15:24:24 1999 Stan Shebs <shebs@andros.cygnus.com>
+
+ * buildsym.h, buildsym.c: Convert to ANSI-only.
+
+ * buildsym.h, buildsym.c: Reformat to standard.
+
+ * buildsym.c (merge_symbol_lists): Remove unused variable.
+ (_initialize_buildsym): Remove, does nothing.
+
+1999-01-31 J.T. Conklin <jtc@redbacknetworks.com>
+
+ * i386-stub.c, m32r-stub.c, m68k-stub.c, sh-stub.c, sparc-stub.c,
+ sparcl-stub, sparclet-stub.c: Change declaration of putDebugChar
+ to include explicit void return type as per documentation. Fix up
+ occasions where stubs erroneously checked return type.
+
+Sun Jan 31 13:18:33 1999 Stan Shebs <shebs@andros.cygnus.com>
+
+ From J.T. Conklin <jtc@redbacknetworks.com>:
+ * remote.c (remote_query): Fix tipo.
+
+Fri Jan 29 15:25:09 1999 Stan Shebs <shebs@andros.cygnus.com>
+
+ * configure.tgt (v850): Add wildcard to match.
+
+Fri Jan 29 16:44:01 1999 Edith Epstein <eepstein@sophia.cygnus.com>
+
+ * inferior.h: Ran indent.
+
+ * fork-child.c: Ran indent.
+
+ * infrun.c : Ran indent.
+
+Fri Jan 29 12:57:34 1999 Elena Zannoni <ezannoni@kwikemart.cygnus.com>
+
+ * infrun.c (_initialize_infrun): Do not stop or print anything
+ when a SIGWINCH is received.
+
+ * Makefile.in (m2-exp.tab.c): Use YACC not BISON.
+ (f-exp.tab.c): Ditto.
+ (jv-exp.tab.c): Ditto.
+ (c-exp.tab.c): Ditto.
+ (YACC): Define as @YACC@.
+
+1999-01-29 Martin Hunt <hunt@cygnus.com>
+
+ Changes from Keith Seitz <keiths@cygnus.com>
+ * valops.c (value_assign): Add calls to register_changed_hook and
+ memory_changed_hook to inform UIs that the user has changed
+ the target's registers/memory.
+ * findvar.c (write_register_gen): Remove call to pc_changed_hook.
+ * defs.h: Remove declaration for pc_changed_hook and
+ add declarations for register_changed_hook and
+ memory_changed_hook.
+ * top.c: Ditto.
+
+1999-01-29 Mark Alexander <marka@cygnus.com>
+
+ * procfs.c (wait_fd): Handle deleted threads correctly.
+
+1999-01-28 Jason Molenda (jsm@bugshack.cygnus.com)
+
+ * utils.c (init_page_info): Force window size if running under emacs.
+
+1999-01-27 James Ingham <jingham@cygnus.com>
+
+ * typeprint.c (whatis_exp): Remove static declaration.
+
+Wed Jan 27 16:50:25 1999 Elena Zannoni <ezannoni@kwikemart.cygnus.com>
+
+ * hp-psymtab-read.c: Reformat using indent.
+
+Wed Jan 27 13:20:25 1999 Elena Zannoni <ezannoni@kwikemart.cygnus.com>
+
+ * hp-psymtab-read.c: Reformat comments, update copyright.
+
+Tue Jan 26 16:02:47 1999 Mark Alexander <marka@cygnus.com>
+
+ * v850-tdep.c (v850_generic_reg_names, v850e_reg_names,
+ v850_register_names, v850_processor_type_table): Declare tables
+ and structures for handling differences in register names for
+ v850 and v850e.
+ (struct reg_list): Define new structure for creating tables
+ of register bit masks in v850e instrutions.
+ (handle_prepare, handle_pushm): New helpers for v850_scan_prologue.
+ (v850_scan_prologue): Recognize v850e instructions: callt, prepare,
+ and pushm.
+ (v850_target_architecture_hook): New function to set register
+ names based on current machine.
+ (_initialize_v850_tdep): Set up target_architecture_hook.
+ * config/v850/tm-v850.h (v850_register_names): Declare.
+ (REGISTER_NAME): Define to refer to v850_register_names.
+ (SR0_REGNUM, CTBP_REGNUM): Define.
+ (PS_REGNUM): Redefine in terms of SR0_REGNUM.
+
+Tue Jan 26 18:27:26 1999 Elena Zannoni <ezannoni@kwikemart.cygnus.com>
+
+ * Makefile.in (c-exp.tab.c): Use BISON instead of YACC, to pick
+ the correct value from configure output.
+ (jv-exp.tab.c): Ditto.
+ (f-exp.tab.c): Ditto.
+ (m2-exp.tab.c): Ditto.
+
+1999-01-26 Jason Molenda (jsm@bugshack.cygnus.com)
+
+ * breakpoint.h (ep_is_exception_catchpoint): Add prototype.
+ * frame.h (select_and_print_frame): Add prototype.
+ * stack.c (func_command): Call select_and_print_frame with correct
+ number of arguments. Reformat whitespace.
+
+Tue Jan 26 16:53:54 1999 Fernando Nasser <fnasser@cygnus.com>
+
+ * remote.c (remote_query): fix maximum packet size to account for
+ remote_debug use.
+ (putpkt): add comment to alert about extra byte need.
+
+Mon Jan 25 19:55:30 1999 Mark Alexander <marka@cygnus.com>
+
+ * sh-tdep.c (sh_target_architecture_hook): Return immediately
+ when a matching machine is found.
+
+Fri Jan 22 09:10:35 1999 Mark Alexander <marka@cygnus.com>
+
+ * remote-mips.c (mips_initialize): Fix parameters to clear_breakpoint.
+ (common_breakpoint): Restore support for instruction breakpoints
+ on non-LSI targets.
+
+Thu Jan 21 17:16:19 1999 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * stack.c: Close open comment.
+ * symtab.c (find_pc_sect_line): Ditto.
+
+Thu Jan 21 17:51:51 1999 Stan Shebs <shebs@andros.cygnus.com>
+
+ * procfs.c (init_procfs_ops): New function, fills in procfs_ops,
+ init only nonzero fields, leave to_require_attach and
+ to_require_detach empty, not needed for /proc systems yet.
+ (_initialize_procfs): Call init_procfs_ops.
+
+ From J.T. Conklin <jtc@redbacknetworks.com>:
+ * top.c (init_main): Fix tipo in description of the remotetimeout
+ variable.
+ * breakpoint.c (bpstat_stop_status): Handle systems where
+ DECR_PC_AFTER_BREAK != DECR_PC_AFTER_HW_BREAK.
+
+Thu Jan 21 17:25:46 1999 Mark Alexander <marka@cygnus.com>
+
+ * mon960-rom.c (_initialize_mon960): Call init_mon960_cmds
+ to fill in mon960_cmds structure properly.
+
+Wed Jan 20 17:53:22 1999 Stan Shebs <shebs@andros.cygnus.com>
+
+ * remote-sds.c (sds_ops): Define only once.
+ (init_sds_ops, sds_command, _initialize_remote_sds): Declare.
+ (init_sds_ops): Init only non-zero fields.
+
+Wed Jan 20 15:45:15 1999 Mark Alexander <marka@cygnus.com>
+
+ * h8300-tdep.c (original_register_names, h8300h_register_names,
+ h8300_register_names): Define new variables.
+ (set_register_names): New function to set register names based on
+ current CPU type.
+ (h8300_command, h8300h_command, h8300s_command): Call
+ set_register_names.
+ * config/h8300/tm-h8300.h (h8300_register_names): Declare.
+ (REGISTER_NAME): Define to refer to h8300_register_names.
+
+1999-01-19 Fernando Nasser <fnasser@totem.to.cygnus.com>
+
+ * sol-thread.c abug-rom.c cpu32bug-rom.c dbug-rom.c m32r-rom.c
+ mac-nat.c mon960-rom.c op50-rom.c ppc-bdm.c remote-adapt.c
+ remote-array.c remote-bug.c remote-e7000.c remote-eb.c remote-es.c
+ remote-est.c remote-hms.c remote-mm.c remote-nindy.c remote-nrom.c
+ remote-os9k.c remote-rdp.c remote-sds.c remote-sim.c remote-st.c
+ remote-udi.c rom68k-rom.c sh3-rom.c sparcl-tdep.c sparclet-rom.c
+ v850ice.c win32-nat.c: cosmetic changes to conform to coding
+ standards.
+
+1999-01-19 Jim Blandy <jimb@zwingli.cygnus.com>
+
+ Use aclocal to generate GDB's aclocal.m4 script.
+ * acinclude.m4: New file, containing the hand-written local macro
+ definitions that used to be in aclocal.m4. Don't sinclude
+ ../bfd/aclocal.m4 any more; running aclocal in this directory will
+ get us the definitions we need. HOWEVER: Do sinclude
+ ../bfd/acinclude.m4, because we need the definition of
+ BFD_NEED_DECLARATION.
+ * aclocal.m4: Regenerated by aclocal.
+ * configure: Regenerated by autoconf.
+
+Tue Jan 19 10:27:23 1999 David Taylor <taylor@texas.cygnus.com>
+
+ * breakpoint.c (disable_breakpoints_in_shlibs): new parameter,
+ silent, controls whether to print message about removal of shared
+ library breakpoints.
+ * breakpoint.h (disable_breakpoints_in_shlibs): decl updated.
+ * irix5-nat.c (clear_solib): call disable_breakpoints_in_shlibs.
+ * osfsolib.c (clear_solib): ditto.
+ * solib.c (clear_solib): ditto.
+ * somsolib.c (som_solib_restart): update call to
+ disable_breakpoints_in_shlibs.
+
+ * target.h (child_post_attach): only declare if CHILD_POST_ATTACH
+ is define.
+
+Tue Jan 19 18:07:11 1999 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * corelow.c (solib_add_stub): Ditto.
+ (core_file_to_sym_file): Cast make_cleanup parameter.
+
+ * solib.c (symbol_add_stub, solib_map_sections): Change argument
+ to PTR insted of a char*. Matches catch_errors interface.
+
+Mon Jan 18 14:01:24 1999 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * remote-array.c (array_open): Don't use fprintf_filtered to send
+ data to the log file.
+
+ * remote-array.c (handle_load_dll): Change argument type to PTR so
+ that it is compatible with catch_errors.
+ * ocd.c (ocd_start_remote): Ditto.
+ * remote-sds.c (sds_start_remote): Ditto.
+
+ * win32-nat.c (win32_child_thread_alive): Namespace proof
+ child_thread_alive.
+ (init_child_ops): Update.
+
+Mon Jan 18 12:03:47 1999 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * remote-rdi.c (arm_rdi_open): Set gdb_hostif.hostosarg and
+ gdb_hostif.dbgarg to NULL instead of stdout.
+ (voiddummy, myprint, mywritec): Use gdb_stdout instead of stdout.
+
+Mon Jan 18 16:40:50 1999 Stan Shebs <shebs@andros.cygnus.com>
+
+ * ser-ocd.c (ocd_open): Handle Unix case gracefully.
+
+ * target.c (dummy_target): Don't initialize statically.
+ (init_dummy_target): New function, fills in dummy_target.
+ (initialize_targets): Use it.
+ * hpux-thread.c (hpux_thread_ops): Don't initialize statically.
+ (init_hpux_thread_ops): New function, fills in hpux_thread_ops.
+ (_initialize_hpux_thread): Use it.
+ * m3-nat.c (m3_ops): Don't initialize statically.
+ (init_m3_ops): New function, fills in m3_ops.
+ (_initialize_m3): Use it.
+
+1999-01-18 Fernando Nasser <fnasser@totem.to.cygnus.com>
+
+ * sol-thread.c: delete compile time initialization of target_ops
+ (_initialize_sol_thread): initialize target_ops at run time.
+ * hpux-thread.c: added target_ops entry.
+ * m3-nat.c: ditto.
+
+Mon Jan 18 15:19:13 1999 David Taylor <taylor@texas.cygnus.com>
+
+ * procfs.c (procfs_ops): delete compile time initialization.
+ (_initialize_procfs): initialize procfs_ops at run time.
+
+Mon Jan 18 12:51:44 1999 Christopher Faylor <cgf@cygnus.com>
+
+ * configure.in: Ensure that -luser32 is always linked in
+ for cygwin build.
+ * configure: Regenerated.
+
+Mon Jan 18 08:38:05 1999 Mark Alexander <marka@cygnus.com>
+
+ * values.c (value_virtual_fn_field): Clear the pointed-to
+ offset when casting to the base class.
+
+Mon Jan 18 10:30:51 1999 David Taylor <taylor@texas.cygnus.com>
+
+ * remote-udi.c (init_udi_ops): change non-existant udi_run_ops to
+ udi_ops; delete NULL initializers.
+
+Mon Jan 18 12:03:47 1999 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * serial.c (serial_close): gdb_fclose tages gdb_file** arg, not
+ gdb_file*.
+
+ * f-valprint.c, target.c, gdbarch.c: Pass gdb_stderr not stderr.
+
+Mon Jan 18 10:46:12 1999 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * stack.c (print_frame_info_base): Don't cast call to
+ catch_errors.
+ (print_args_stub): Change char* arg to PTR.
+ * symmisc.c (print_symbol): Ditto.
+ * top.c (quit_cover): Ditto.
+ * remote.c (remote_open_1, remote_start_remote): Ditto.
+ * infrun.c (normal_stop, hook_stop_stub, restore_selected_frame):
+ Ditto.
+
+ * stack.c (backtrace_command): Cast first arg of make_cleanup to
+ make_cleanup_func.
+ * remote.c (remote_kill): Cast putpkt arg to catch_errors_ftype.
+
+Mon Jan 18 08:47:02 1999 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * defs.h (catch_errors_ftype): Define.
+ (catch_errors): Replace char* arg with PTR arg.
+ * top.c (catch_errors): Update
+
+ * breakpoint.c (bpstat_stop_status, bpstat_stop_status,
+ delete_breakpoint, breakpoint_re_set): Delete all casts in call to
+ catch_errors.
+ (breakpoint_cond_eval, watchpoint_check,
+ cover_target_enable_exception_callback, breakpoint_re_set_one):
+ Arg is PTR not char*.
+
+ * breakpoint.c (cover_target_enable_exception_callback): Change
+ type to int. Check for cast values of 0 and -1. Return a result!
+ (insert_breakpoints): Move declaration of SAL and ARGS to where
+ they are used.
+
+1999-01-16 Fernando Nasser <fnasser@totem.to.cygnus.com>
+
+ * remote.c (remote_query): new function - creates proper interface
+ to the remote protocol "q" command.
+
+Fri Jan 15 17:11:48 EST 1999 Zdenek Radouch (radouch@cygnus.com)
+
+ * config/fr30/tm-fr30.h: Changed ABI to match GCC change
+ (always use pointer for structs passed by value).
+
+1999-01-15 Fernando Nasser <fnasser@totem.to.cygnus.com>
+
+ * target.h: added entry for target queries (to_query)
+ target.c: ditto.
+
+Thu Jan 14 18:29:17 1999 David Taylor <taylor@texas.cygnus.com>
+
+ * remote-mm.c (mm_wait): fix stream arg to gdb_flush.
+ * remote-udi.c (udi_wait): fix stream arg to fwrite.
+ * symmisc.c (maintenance_check_symtabs): fix stream argument to
+ print_address_numeric.
+
+Wed Jan 13 19:33:16 1999 David Taylor <taylor@texas.cygnus.com>
+
+ * breakpoint.c (insert_breakpoints): insert cast to eliminate
+ warning.
+
+Wed Jan 13 14:59:02 1999 Michael Snyder <msnyder@cleaver.cygnus.com>
+
+ * infrun.c (set/show scheduler-locking) New command. Set a
+ mode bit that will control how GDB attempts to control thread
+ scheduling for step, continue, etc. (resume): make use of
+ the schedule-locking mode.
+ * target.h (struct target_ops): new field to_has_thread_control.
+ * sol-thread.c: initialize target_ops to_has_thread_control.
+ * procfs.c: ditto.
+ * target.c: ditto.
+ * m3-nat.c: ditto.
+ * remote.c: ditto.
+ * hpux-thread.c: ditto.
+ * thread.c: cull duplicate prototypes. Move prototypes to top.
+ * serial.c: indentation cleanup.
+ * breakpoint.c: add casts to eliminate compiler warnings.
+
+Tue Jan 12 17:00:00 1999 Edith Epstein <eepstein@sophia.cygnus.com>
+
+ * inftarg.c (child_create_inferior): fixed HPUXHPPA specific
+ call to fork_inferior. The shell param is now NULL.
+
+1999-01-12 Jason Molenda (jsm@bugshack.cygnus.com)
+
+ * monitor.c (init_base_monitor_ops): Whitespace cleanup.
+ (_initialize_remote_monitors): Same.
+
+1999-01-12 Jason Molenda (jsm@bugshack.cygnus.com)
+
+ * monitor.c (init_monitor_ops): Initialize the monitor_ops
+ structure if it hasn't already been done.
+
+Tue Jan 12 14:50:10 1999 Stan Shebs <shebs@andros.cygnus.com>
+
+ * inftarg.c (child_ops): Don't initialize statically.
+ (init_child_ops): New function, fills in child_ops.
+ (_initialize_inftarg): Use it.
+ (child_post_attach): Declare extern.
+ (child_wait): Fix ambiguous parens.
+ (child_attach_to_process): Remove unused local wstatus.
+ (child_insert_fork_catchpoint, child_remove_fork_catchpoint,
+ child_insert_vfork_catchpoint, child_remove_vfork_catchpoint,
+ child_has_forked, child_insert_exec_catchpoint,
+ child_remove_exec_catchpoint): Return a value.
+
+Mon Jan 11 16:43:44 1999 Michael Snyder <msnyder@cleaver.cygnus.com>
+
+ * remote.c (remote_wait): Add inferior_pid to thread list only
+ if it is not already there.
+
+1999-01-11 Jason Molenda (jsm@bugshack.cygnus.com)
+
+ * scm-tags.h: Update FSF's address on copyright notice.
+ * ser-e7kpc.c: Same.
+ * gnu-nat.h: Same.
+
+Mon Jan 11 13:45:57 1999 Stu Grossman <grossman@babylon-5.cygnus.com>
+
+ * dwarf2read.c (dump_die): Change stderr to gdb_stderr.
+ * expprint.c (print_subexp): fprintf => fprintf_unfiltered.
+ * jv-typeprint.c (java_type_print_base): fputs => fputs_filtered.
+ * stack.c (struct function_bounds): Remove superfluous `typedef'.
+ * symfile.c (list_overlays_command): stdout => gdb_stdout.
+ * symmisc.c (maintenance_check_symtabs): stdout => gdb_stdout.
+ * utils.c (print_spaces): Make more efficient.
+
+Mon Jan 11 13:55:51 1999 David Taylor <taylor@texas.cygnus.com>
+
+ * utils (print_spaces): fix arg to strcat; fix formatting.
+
+Fri Jan 8 11:57:24 1999 Stan Shebs <shebs@andros.cygnus.com>
+
+ * exec.c (exec_ops): Don't initialize statically.
+ (init_exec_ops): New function, fills in exec_ops.
+ (_initialize_exec): Use it.
+
+Thu Jan 7 17:50:15 EST 1999 Zdenek Radouch (radouch@cygnus.com)
+
+ Beta FR30 port.
+ * fr30-tdep.c
+ * config/fr30/tm-fr30.h
+
+Wed Jan 6 12:28:35 1999 David Taylor <taylor@texas.cygnus.com>
+
+ * configure.in: Add an --enable-tui argument. Construct
+ tui/Makefile from tui/Makefile.in. Use AM_PROG_CC_STDC. If we
+ have the GUI, then we need this to process libgui.h.
+ (ENABLE_CFLAGS): define and export BUILD_TUI.
+ (AC_CHECK_HEADERS): Add check for term.h.
+
+ * configure.host (hppa-*-hpux10.20, hppa-*-hpux11.0*): New configs.
+
+ * config.in, configure : regenerated.
+
+ * Makefile.in: Allow the TUI code to be conditionally enabled.
+ (TUI_LIBRARY): New variable, value are set by the configuration
+ script. Set to the empty string when the TUI isn't enabled.
+ (gdb$(GDBEXT)): Use those, instead of referring to all-tui and
+ tui/libtui.a directly.
+ (BUILD_TUI): build the tui -- only when configured with
+ --enable-tui.
+ (YLWRAP): use ylwrap to avoid problems on systems w/o bison.
+ (gdb$(EXEEXT)): make it dependent on BUILD_TUI.
+ (all-tui): remove dependency from phony target.
+ (c-exp.tab.c): use ylwrap instead of bison.
+ (jv-exp.tab.c): ditto.
+ (f-exp.tab.c): ditto.
+ (m2-exp.tab.c): ditto.
+ (ALLDEPFILES): add somread.c, hp-psymtab-read.c, hp-symtab-read.c.
+ (SFILES): remove the above files
+ (COMMON_OBS): remove somread.o
+ (SFILES): Add the tui files to this, so they get included in etags
+ tables.
+ (gdb$(EXEEXT)): Add all-tui to the list of dependencies, and add
+ tui/libtui.a to the link list.
+ (all-tui): New rule, which does a recursive make in the tui
+ subdir.
+ (tui/libtui.a): When recursing, pass down ${FLAGS_TO_PASS}. And
+ don't echo the make command. This is closer to what the other
+ recursions do.
+ (HFILES_NO_SRCDIR): add hpread.h
+ (COMMON_OBS): add hp-psymtab-read.o, hp-symtab-read.o
+ (SFILES): add hp-psymtab-read.c, hp-symtab-read.c add rules for
+ the new files. Remove hpread.c, hpread.o
+ (gdb$(EXEEXT)): Depend on the actual tui library, not on a
+ fictitious target. Since the fictitious target never existed,
+ make would always relink.
+ (tui/libtui.a): Always recurse to make sure the library is up to
+ date.
+
+Wed Jan 6 12:05:12 1999 Stan Shebs <shebs@andros.cygnus.com>
+
+ * remote.c: Pacify --enable-build-warnings, reformat code
+ to conform to standards, fix spelling errors.
+ (ishex, stubhex, record_currthread, etc): Declare.
+ (ishex, stubhex): Declare char arg as int.
+ (pack_string): Comment out, never used but possibly useful.
+ (threadref_to_int, remote_get_threadinfo, etc): Make static.
+
+Wed Jan 6 11:43:32 1999 David Taylor <taylor@texas.cygnus.com>
+
+ The following changes were made by Elena Zannoni
+ <ezannoni@cygnus.com> and Edith Epstein <eepstein@cygnus.com> as
+ part of a project to merge in changes made by HP.
+
+ * c-exp.y: use external flag hp_som_som_object_present to decide
+ whether code was compiled by HP's compilers. Add two new C++
+ tokens for true and false.
+ (yylex): check for template name is done differently for the
+ HP/aCC compiler case. Change some of the template processing code
+ for handling HP aCC templates. Handle true and false tokens.
+
+Tue Jan 5 11:13:36 1999 Michael Snyder <msnyder@cleaver.cygnus.com>
+
+ * remote.c (record_curthread): Must not modify inferior_pid when
+ called from wait_for_inferior. Instead, if a new thread-id is
+ detected, call add_thread.
+ (MAGIC_NULL_PID): new macro, use instead of the magic number
+ "42000".
+ (remote_find_new_threads): if inferior_pid is unknown, get and use
+ the current thread id.
+ (remote_start_remote): on connecting, attempt to get the current
+ thread id for inferior_pid.
+ (remote_resume): If pid == -1, then resume any-thread (not the
+ current thread specifically). Also some cosmetic fixups.
+
+ * thread.c (info_threads_command): don't initialize current_pid
+ until after call to FIND_NEW_THREADS (which may change inferior_pid).
+ Also some cosmetic fixups.
+ * infrun.c: cosmetic fixups and casts to avoid warnings.
+ * infcmd.c: cosmetic fixups, mainly long lines.
+
+Tue Jan 5 11:55:57 1999 David Taylor <taylor@texas.cygnus.com>
+
+ * target.c (noprocess): terminate sentence with a period.
+ * breakpoint.c (catch_command_1): ditto.
+
+ * c-valprint.c (c_value_print): remove hack^2 from HP; it causes
+ testsuite losses with no real gain.
+
+ * inferior.h (START_INFERIOR_TRAPS_EXPECTED): restore, but only
+ if tm-*.h hasn't overridden default value.
+
+1999-01-04 Jason Molenda (jsm@bugshack.cygnus.com)
+
+ * configure.in: Fix whitespace indentation for --help.
+ * configure: Regenerated.
+
+1999-01-04 Manuel Bouyer <bouyer@antioche.lip6.fr>
+
+ * main.c: Add --write command line option, document -w.
+ * gdb.1: Document --write.
+
+1999-01-04 Jason Molenda (jsm@bugshack.cygnus.com)
+
+ * configure.in: Require autoconf 2.12.1 or higher.
+ * doc/configure.in: Ditto.
+ * nlm/configure.in: Ditto.
+ * rdi-share/configure.in: Ditto.
+ * testsuite/configure.in: Ditto.
+ * doc/Makefile.in: Don't hardcode $(SHELL).
+ * nlm/Makefile.in: Ditto.
+ * rdi-share/Makefile.in: Ditto.
+ * testsuite/Makefile.in: Ditto.
+
+Mon Jan 4 12:53:03 1999 Stan Shebs <shebs@andros.cygnus.com>
+
+ * remote-vx.c (init_vx_ops, init_vx_run_ops): Remove unneeded
+ inits of new fields, including ref to bogus field.
+ (vx_ops, vx_run_ops): Make static.
+
+Mon Jan 4 15:05:29 1999 David Taylor <taylor@texas.cygnus.com>
+
+ * inferior.h (START_INFERIOR_TRAPS_EXPECTED): delete,
+ already defined in tm.h.
+
+ * inftarg.c: change <sys/unistd.h> to <unistd.h> and
+ conditionalize its inclusion.
+ * infttrace.c: ditto.
+
+For older changes see ChangeLog-98
+
+Local Variables:
+mode: change-log
+left-margin: 8
+fill-column: 74
+version-control: never
+End:
diff --git a/gdb/ChangeLog-3.x b/gdb/ChangeLog-3.x
new file mode 100644
index 00000000000..672aa3daa1c
--- /dev/null
+++ b/gdb/ChangeLog-3.x
@@ -0,0 +1,4838 @@
+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 dependency list and cleaned it up somewhat
+ (used macros, didn't make .o files depend on .c files, etc.)
+
+Fri Dec 2 11:44:46 1988 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * value.h, values.c, infcmd.c, valops.c, m-i386.h, m-sparc.h,
+ m-merlin.h, m-npl.h, m-pn.h, m-umax.h, m-vax.h, m-hp9k320.h,
+ m-isi.h, m-news.h, m-sun2.h, m-sun3.h: Cleaned up dealings with
+ functions returning structures. Specifically: Added a function
+ called using_struct_return which indicates whether the function
+ being called is using the structure returning conventions or it is
+ using the value returning conventions on that machine. Added a
+ macro, STORE_STRUCT_RETURN to store the address of the structure
+ to be copied into wherever it's supposed to go, and changed
+ call_function to handle all of this correctly.
+
+ * symseg.h, symtab.h, dbxread.c: Added hooks to recognize an
+ N_TEXT symbol with name "*gcc-compiled*" as being a flag
+ indicating that a file had been compiled with gcc and setting a
+ flag in all blocks produced during processing of that file.
+
+Thu Dec 1 13:54:29 1988 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * m-sparc.h (PUSH_DUMMY_FRAME): Saved 8 less than the current pc,
+ as POP_FRAME and sparc return convention restore the pc to 8 more
+ than the value saved.
+
+ * valops.c, printcmd.c, findvar.c, value.h: Added the routine
+ value_from_register, to access a specific register of a specific
+ frame as containing a specific type, and used it in read_var_value
+ and print_frame_args.
+
+Wed Nov 30 17:39:50 1988 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * dbxread.c (read_number): Will accept either the argument passed
+ as an ending character, or a null byte as an ending character.
+
+ * Makefile, createtags: Added entry to create tags for gdb
+ distribution which will make sure currently configured machine
+ dependent files come first in the list.
+
+Wed Nov 23 13:27:34 1988 Randall Smith (randy at gluteus.ai.mit.edu)
+
+ * stack.c, infcmd.c, sparc-dep.c: Modified record_selected_frame
+ to work off of frame address.
+
+ * blockframe.c (create_new_frame, get_prev_frame_cache_item):
+ Added code to reset pointers within frame cache if it must be
+ realloc'd.
+
+ * dbxread.c (read_dbx_symtab): Added in optimization comparing
+ last couple of characters instead of first couple to avoid
+ strcmp's in read_dbx_symtab (recording extern syms in misc
+ functions or not). 1 call to strlen is balanced out by many fewer
+ calls to strcmp.
+
+Tue Nov 22 16:40:14 1988 Randall Smith (randy at cream-of-wheat.ai.mit.edu)
+
+ * dbxread.c (read_dbx_symtab): Took out optimization for ignoring
+ LSYM's; was disallowing typedefs. Silly me.
+
+ * Checkpointed distribution (mostly for sending to Tiemann).
+
+ * expression.h: Added BINOP_MIN and BINOP_MAX operators for C++.
+ * symseg.h: Included flags for types having destructors and
+ constructors, and flags being defined via public and via
+ virtual paths. Added fields NEXT_VARIANT, N_BASECLASSES,
+ and BASECLASSES to this type (tr: Changed types from
+ having to be derived from a single baseclass to a multiple
+ base class).
+ * symtab.h: Added macros to access new fields defined in symseg.h.
+ Added decl for lookup_basetype_type.
+ * dbxread.c
+ (condense_addl_misc_bunches): Function added to condense the misc
+ function bunches added by reading in a new .o file.
+ (read_addl_syms): Function added to read in symbols
+ from a new .o file (incremental linking).
+ (add_file_command): Command interface function to indicate
+ incrmental linking of a new .o file; this now calls
+ read_addl_syms and condense_addl_misc_bunches.
+ (define_symbol): Modified code to handle types defined from base
+ types which were not known when the derived class was
+ output.
+ (read_struct_type): Modified to better handle description of
+ struct types as derived types. Possibly derived from
+ several different base classes. Also added new code to
+ mark definitions via virtual paths or via public paths.
+ Killed seperate code to handle classes with destructors
+ but without constructors and improved marking of classes
+ as having destructors and constructors.
+ * infcmd.c: Modified call to val_print (one more argument).
+ * symtab.c (lookup_member_type): Modified to deal with new
+ structure in symseg.h.
+ (lookup_basetype_type): Function added to find or construct a type
+ ?derived? from the given type.
+ (decode_line_1): Modified to deal with new type data structures.
+ Modified to deal with new number of args for
+ decode_line_2.
+ (decode_line_2): Changed number of args (?why?).
+ (init_type): Added inits for new C++ fields from
+ symseg.h.
+ *valarith.c
+ (value_x_binop, value_binop): Added cases for BINOP_MIN &
+ BINOP_MAX.
+ * valops.c
+ (value_struct_elt, check_field, value_struct_elt_for_address):
+ Changed to deal with multiple possible baseclasses.
+ (value_of_this): Made SELECTED_FRAME an extern variable.
+ * valprint.c
+ (val_print): Added an argument DEREF_REF to dereference references
+ automatically, instead of printing them like pointers.
+ Changed number of arguments in recursive calls to itself.
+ Changed to deal with varibale numbers of base classes.
+ (value_print): Changed number of arguments to val_print. Print
+ type of value also if value is a reference.
+ (type_print_derivation_info): Added function to print out
+ derivation info a a type.
+ (type_print_base): Modified to use type_print_derivation_info and
+ to handle multiple baseclasses.
+
+Mon Nov 21 10:32:07 1988 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * inflow.c (term_status_command): Add trailing newline to output.
+
+ * sparc-dep.c (do_save_insn, do_restore_insn): Saved
+ "stop_registers" over the call for the sake of normal_stop and
+ run_stack_dummy.
+
+ * m-sparc.h (EXTRACT_RETURN_VALUE): Put in parenthesis to force
+ addition of 8 to the int pointer, not the char pointer.
+
+ * sparc-pinsn.c (print_addr1): Believe that I have gotten the
+ syntax right for loads and stores as adb does it.
+
+ * symtab.c (list_symbols): Turned search for match on rexegp into
+ a single loop.
+
+ * dbxread.c (psymtab_to_symtab): Don't read it in if it's already
+ been read in.
+
+ * dbxread.c (psymtab_to_symtab): Changed error to fatal in
+ psymtab_to_symtab.
+
+ * expread.y (parse_number): Fixed bug which treated 'l' at end of
+ number as '0'.
+
+Fri Nov 18 13:57:33 1988 Randall Smith (randy at gluteus.ai.mit.edu)
+
+ * dbxread.c (read_dbx_symtab, process_symbol_for_psymtab): Was
+ being foolish and using pointers into an array I could realloc.
+ Converted these pointers into integers.
+
+Wed Nov 16 11:43:10 1988 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * m-sparc.h (POP_FRAME): Made the new frame be PC_ADJUST of the
+ old frame.
+
+ * i386-pinsn.c, m-hp9k320.h, m-isi.h, m-merlin.h, m-news.h,
+ m-npl.h, m-pn.h, m-sparc.h, m-sun2.h, m-sun3.h, m-umax.h, m-vax.h:
+ Modified POP_FRAME to use the current frame instead of
+ read_register (FP_REGNUM) and to flush_cached_frames before
+ setting the current frame. Also added a call to set the current
+ frame in those POP_FRAMEs that didn't have it.
+
+ * infrun.c (wait_for_inferior): Moved call to set_current_frame up
+ to guarrantee that the current frame will always be set when a
+ POP_FRAME is done.
+
+ * infrun.c (normal_stop): Added something to reset the pc of the
+ current frame (was incorrect because of DECR_PC_AFTER_BREAK).
+
+ * valprint.c (val_print): Changed to check to see if a string was
+ out of bounds when being printed and to indicate this if so.
+
+ * convex-dep.c (read_inferior_memory): Changed to return the value
+ of errno if the call failed (which will be 0 if the call
+ suceeded).
+
+Tue Nov 15 10:17:15 1988 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * infrun.c (wait_for_inferior): Two changes: 1) Added code to
+ not trigger the step breakpoint on recursive calls to functions
+ without frame info, and 2) Added calls to distinguish recursive
+ calls within a function without a frame (which next/nexti might
+ wish to step over) from jumps to the beginning of a function
+ (which it generally doesn't).
+
+ * m-sparc.h (INIT_EXTRA_FRAME_INFO): Bottom set correctly for leaf
+ parents.
+
+ * blockframe.c (get_prev_frame_cache_item): Put in mod to check
+ for a leaf node (by presence or lack of function prologue). If
+ there is a leaf node, it is assumed that SAVED_PC_AFTER_CALL is
+ valid. Otherwise, FRAME_SAVED_PC or read_pc is used.
+
+ * blockframe.c, frame.h: Did final deletion of unused routines and
+ commented problems with getting a pointer into the frame cache in
+ the frame_info structure comment.
+
+ * blockframe.c, frame.h, stack.c: Killed use of
+ frame_id_from_frame_info; used frame_id_from_addr instead.
+
+ * blockframe.c, frame.h, stack.c, others (oops): Combined stack
+ cache and frame info structures.
+
+ * blockframe.c, sparc-dep.c, stack.c: Created the function
+ create_new_frame and used it in place of bad calls to
+ frame_id_from_addr.
+
+ * blockframe.c, inflow.c, infrun.c, i386-pinsn.c, m-hp9k320.h,
+ m-npl.h, m-pn.h, m-sparc.h, m-sun3.h, m-vax.h, default-dep.c,
+ convex-dep.c, gould-dep.c, hp9k320-dep.c, news-dep.c, sparc-dep.c,
+ sun3-dep.c, umax-dep.c: Killed use of
+ set_current_Frame_by_address. Used set_current_frame
+ (create_new_frame...) instead.
+
+ * frame.h: Killed use of FRAME_FP_ID.
+
+ * infrun.c, blockframe.c: Killed select_frame_by_address. Used
+ select_frame (get_current_frame (), 0) (which was correct in all
+ cases that we need to worry about.
+
+Mon Nov 14 14:19:32 1988 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * frame.h, blockframe.c, stack.c, m-sparc.h, sparc-dep.c: Added
+ mechanisms to deal with possible specification of frames
+ dyadically.
+
+Sun Nov 13 16:03:32 1988 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * ns32k-opcode.h: Add insns acbw, acbd.
+
+Sun Nov 13 15:09:58 1988 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * breakpoint.c: Changed breakpoint structure to use the address of
+ a given frame (constant across inferior runs) as the criteria for
+ stopping instead of the frame ident (which varies across inferior
+ calls).
+
+Fri Nov 11 13:00:22 1988 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * gld-pinsn.c (findframe): Modified to work with the new frame
+ id's. Actually, it looks as if this routine should be called with
+ an address anyway.
+
+ * findvar.c (find_saved_register): Altered bactrace loop to work
+ off of frames and not frame infos.
+
+ * frame.h, blockframe.c, stack.c, sparc-dep.c, m-sparc.h: Changed
+ FRAME from being the address of the frame to being a simple ident
+ which is an index into the frame_cache_item list.
+ * convex-dep.c, default-dep.c, gould-dep.c, hp9k320-dep.c,
+ i386-pinsn.c, inflow.c, infrun.c, news-dep.c, sparc-dep.c,
+ sun3-dep.c, umax-dep.c, m-hp9k320.h, m-npl.h, m-pn.h, m-sparc.h,
+ m-sun3.h, m-vax.h: Changed calls of the form set_current_frame
+ (read_register (FP_REGNUM)) to set_current_frame_by_address (...).
+
+Thu Nov 10 16:57:57 1988 Randall Smith (randy at gluteus.ai.mit.edu)
+
+ * frame.h, blockframe.c, gld-pinsn.c, sparc-dep.c, stack.c,
+ infrun.c, findvar.c, m-sparc.h: Changed the FRAME type to be
+ purely an identifier, using FRAME_FP and FRAME_FP_ID to convert
+ back and forth between the two. The identifier is *currently*
+ still the frame pointer value for that frame.
+
+Wed Nov 9 17:28:14 1988 Chris Hanson (cph at kleph)
+
+ * m-hp9k320.h (FP_REGISTER_ADDR): Redefine this to return
+ difference between address of given FP register, and beginning of
+ `struct user' that it occurs in.
+
+ * hp9k320-dep.c (core_file_command): Fix sign error in size
+ argument to myread. Change buffer argument to pointer; was
+ copying entire structure.
+ (fetch_inferior_registers, store_inferior_registers): Replace
+ occurrences of `FP_REGISTER_ADDR_DIFF' with `FP_REGISTER_ADDR'.
+ Flush former definition.
+
+Wed Nov 9 12:11:37 1988 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * xgdb.c: Killed include of initialize.h.
+
+ * Pulled in xgdb.c from the net.
+
+ * Checkpointed distribution (to provide to 3b2 guy).
+
+ * coffread.c, dbxread.c, symmisc.c, symtab.c, symseg.h: Changed
+ format of table of line number--pc mapping information. Can
+ handle negative pc's now.
+
+ * command.c: Deleted local copy of savestring; code in utils.c is
+ identical.
+
+Tue Nov 8 11:12:16 1988 Randall Smith (randy at plantaris.ai.mit.edu)
+
+ * gdb.texinfo: Added documentation for shell escape.
+
+Mon Nov 7 12:27:16 1988 Randall Smith (randy at sugar-bombs.ai.mit.edu)
+
+ * command.c: Added commands for shell escape.
+
+ * core.c, dbxread.c: Added ROBOTUSSIN mods.
+
+ * Checkpointed distribution.
+
+ * printcmd.c (x_command): Yanked error if there is no memory to
+ examine (could be looking at executable straight).
+
+ * sparc-pinsn.c (print_insn): Amount to leftshift sethi imm by is
+ now 10 (matches adb in output).
+
+ * printcmd.c (x_command): Don't attempt to set $_ & $__ if there
+ is no last_examine_value (can happen if you did an x/0).
+
+Fri Nov 4 13:44:49 1988 Randall Smith (randy at gluteus.ai.mit.edu)
+
+ * printcmd.c (x_command): Error if there is no memory to examine.
+
+ * gdb.texinfo: Added "cont" to the command index.
+
+ * sparc-dep.c (do_save_insn): Fixed typo in shift amount.
+
+ * m68k-opcode.h: Fixed opcodes for 68881.
+
+ * breakpoint.c, infcmd.c, source.c: Changed defaults in several
+ places for decode_line_1 to work off of the default_breakpoint_*
+ values instead of current_source_* values (the current_source_*
+ values are off by 5 or so because of listing defaults).
+
+ * stack.c (frame_info): ifdef'd out FRAME_SPECIFCATION_DYADIC in
+ the stack.c module. If I can't do this right, I don't want to do
+ it at all. Read the comment there for more info.
+
+Mon Oct 31 16:23:06 1988 Randall Smith (randy at gluteus.ai.mit.edu)
+
+ * gdb.texinfo: Added documentation on the "until" command.
+
+Sat Oct 29 17:47:10 1988 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * breakpoint.c, infcmd.c: Added UNTIL_COMMAND and subroutines of
+ it.
+
+ * breakpoint.c, infcmd.c, infrun.c: Added new field to breakpoint
+ structure (silent, indicating a silent breakpoint), and modified
+ breakpoint_stop_status and things that read it's return value to
+ understand it.
+
+Fri Oct 28 17:45:33 1988 Randall Smith (randy at gluteus.ai.mit.edu)
+
+ * dbxread.c, symmisc.c: Assorted speedups for readin, including
+ special casing most common symbols, and doing buffering instead of
+ calling malloc.
+
+Thu Oct 27 11:11:15 1988 Randall Smith (randy at gluteus.ai.mit.edu)
+
+ * stack.c, sparc-dep.c, m-sparc.h: Modified to allow "info frame"
+ to take two arguments on the sparc and do the right thing with
+ them.
+
+ * dbxread.c (read_dbx_symtab, process_symbol_for_psymtab): Put
+ stuff to put only symbols that didn't have debugging info on the
+ misc functions list back in.
+
+Wed Oct 26 10:10:32 1988 Randall Smith (randy at gluteus.ai.mit.edu)
+
+ * valprint.c (type_print_varspec_suffix): Added check for
+ TYPE_LENGTH(TYPE_TARGET_TYPE(type)) > 0 to prevent divide by 0.
+
+ * printcmd.c (print_formatted): Added check for VALUE_REPEATED;
+ value_print needs to be called for that.
+
+ * infrun.c (wait_for_inferior): Added break when you decide to
+ stop on a null function prologue rather than continue stepping.
+
+ * m-sun3.h: Added explanatory comment to REGISTER_RAW_SIZE.
+
+ * expread.y (parse_c_1): Initialized paren_depth for each parse.
+
+Tue Oct 25 14:19:38 1988 Randall Smith (randy at gluteus.ai.mit.edu)
+
+ * valprint.c, coffread.c, dbxread.c: Enum constant values in enum
+ type now accessed through TYPE_FIELD_BITPOS.
+
+ * dbxread.c (process_symbol_for_psymtab): Added code to deal with
+ possible lack of a ":" in a debugging symbol (do nothing).
+
+ * symtab.c (decode_line_1): Added check in case of all numbers for
+ complete lack of symbols.
+
+ * source.c (select_source_symtab): Made sure that this wouldn't
+ bomb on complete lack of symbols.
+
+Mon Oct 24 12:28:29 1988 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * m-sparc.h, findvar.c: Ditched REGISTER_SAVED_UNIQUELY and based
+ code on REGISTER_IN_WINDOW_P and HAVE_REGISTER_WINDOWS. This will
+ break when we find a register window machine which saves the
+ window registers within the context of an inferior frame.
+
+ * sparc-dep.c (frame_saved_pc): Put PC_ADJUST return back in for
+ frame_saved_pc. Seems correct.
+
+ * findvar.c, m-sparc.h: Created the macro REGISTER_SAVED_UNIQUELY
+ to handle register window issues (ie. that find_saved_register
+ wasn't checking the selected frame itself for shit).
+
+ * sparc-dep.c (core_file_command): Offset target of o & g register
+ bcopy by 1 to hit correct registers.
+
+ * m-sparc.h: Changed STACK_END_ADDR.
+
+Sun Oct 23 19:41:51 1988 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * sparc-dep.c (core_file_command): Added in code to get the i & l
+ registers from the stack in the corefile, and blew away some wrong
+ code to get i & l from inferior.
+
+Fri Oct 21 15:09:19 1988 Randall Smith (randy at apple-gunkies.ai.mit.edu)
+
+ * m-sparc.h (PUSH_DUMMY_FRAME): Saved the value of the RP register
+ in the location reserved for i7 (in the created frame); this way
+ the rp value won't get lost. The pc (what we put into the rp in
+ this routine) gets saved seperately, so we loose no information.
+
+ * sparc-dep.c (do_save_insn & do_restore_insn): Added a wrapper to
+ preserve the proceed status state variables around each call to
+ proceed (the current frame was getting munged because this wasn't
+ being done).
+
+ * m-sparc.h (FRAME_FIND_SAVED_REGS): Fix bug: saved registers
+ addresses were being computed using absolute registers number,
+ rather than numbers relative to each group of regs.
+
+ * m-sparc.h (POP_FRAME): Fixed a bug (I hope) in the context
+ within which saved reg numbers were being interpetted. The
+ values to be restored were being gotten in the inferior frame, and
+ the restoring was done in the superior frame. This means that i
+ registers must be restored into o registers.
+
+ * sparc-dep.c (do_restore_insn): Modified to take a pc as an
+ argument, instead of a raw_buffer. This matches (at least it
+ appears to match) usage from POP_FRAME, which is the only place
+ from which do_restore_insn is called.
+
+ * sparc-dep.c (do_save_insn and do_restore_insn): Added comments.
+
+ * m-sparc.h (FRAME_FIND_SAVED_REGS): Modified my code to find the
+ save addresses of out registers to use the in regs off the stack
+ pointer when the current frame is 1 from the innermost.
+
+Thu Oct 20 13:56:15 1988 & Smith (randy at hobbes.ai.mit.edu)
+
+ * blockframe.c, m-sparc.h: Removed code associated with
+ GET_PREV_FRAME_FROM_CACHE_ITEM. This code was not needed for the
+ sparc; you can always find the previous frames fp from the fp of
+ the current frame (which is the sp of the previous). It's getting
+ the information associated with a given frame (ie. saved
+ registers) that's a bitch, because that stuff is saved relative to
+ the stack pointer rather than the frame pointer.
+
+ * m-sparc.h (GET_PREV_FRAME_FROM_CACHE_ITEM): Modified to return
+ the frame pointer of the previous frame instead of the stack
+ pointer of same.
+
+ * blockframe.c (flush_cached_frames): Modified call to
+ obstack_free to free back to frame_cache instead of back to zero.
+ This leaves the obstack control structure in finite state (and
+ still frees the entry allocated at frame_cache).
+
+Sat Oct 15 16:30:47 1988 & Smith (randy at tartarus.uchicago.edu)
+
+ * valops.c (call_function): Suicide material here. Fixed a typo;
+ CALL_DUMMY_STACK_ADJUST was spelled CAll_DUMMY_STACK_ADJUST on
+ line 530 of the file. This cost me three days. I'm giving up
+ typing for lent.
+
+Fri Oct 14 15:10:43 1988 & Smith (randy at tartarus.uchicago.edu)
+
+ * m-sparc.h: Corrected a minor mistake in the dummy frame code
+ that was getting the 5th argument and the first argument from the
+ same place.
+
+Tue Oct 11 11:49:33 1988 & Smith (randy at tartarus.uchicago.edu)
+
+ * infrun.c: Made stop_after_trap and stop_after_attach extern
+ instead of static so that code which used proceed from machine
+ dependent files could fiddle with them.
+
+ * blockframe.c, frame.h, sparc-dep.c, m-sparc.h: Changed sense of
+ ->prev and ->next in struct frame_cache_item to fit usage in rest
+ of gdb (oops).
+
+Mon Oct 10 15:32:42 1988 Randy Smith (randy at gargoyle.uchicago.edu)
+
+ * m-sparc.h, sparc-dep.c, blockframe.c, frame.h: Wrote
+ get_frame_cache_item. Modified FRAME_SAVED_PC and frame_saved_pc
+ to take only one argument and do the correct thing with it. Added
+ the two macros I recently defined in blockframe.c to m-sparc.h.
+ Have yet to compile this thing on a sparc, but I've now merged in
+ everything that I received from tiemann, either exactly, or simply
+ effectively.
+
+ * source.c: Added code to allocated space to sals.sals in the case
+ where no line was specified.
+
+ * blockframe.c, infrun.c: Modified to cache stack frames requested
+ to minimize accesses to subprocess.
+
+Tue Oct 4 15:10:39 1988 Randall Smith (randy at cream-of-wheat.ai.mit.edu)
+
+ * config.gdb: Added sparc.
+
+Mon Oct 3 23:01:22 1988 Randall Smith (randy at cream-of-wheat.ai.mit.edu)
+
+ * Makefile, blockframe.c, command.c, core.c, dbxread.c, defs.h,
+ expread.y, findvar.c, infcmd.c, inflow.c, infrun.c, sparc-pinsn.c,
+ m-sparc.h, sparc-def.c, printcmd.c, stack.c, symmisc.c, symseg.h,
+ valops.c, values.c: Did initial merge of sparc port. This will
+ not compile; have to do stack frame caching and finish port.
+
+ * inflow.c, gdb.texinfo: `tty' now resets the controling terminal.
+
+Fri Sep 30 11:31:16 1988 Randall Smith (randy at gluteus.ai.mit.edu)
+
+ * inferior.h, infcmd.c, infrun.c: Changed the variable
+ stop_random_signal to stopped_by_random signal to fit in better
+ with name conventions (variable is not a direction to the
+ proceed/resume set; it is information from it).
+
+Thu Sep 29 13:30:46 1988 Randall Smith (randy at cream-of-wheat.ai.mit.edu)
+
+ * infcmd.c (finish_command): Value type of return value is now
+ whatever the function returns, not the type of the function (fixed
+ a bug in printing said value).
+
+ * dbxread.c (read_dbx_symtab, process_symbol_for_psymtab):
+ Put *all* global symbols into misc_functions. This is what was
+ happening anyway, and we need it for find_pc_misc_function.
+
+ ** This was eventually taken out, but I didn't mark it in the
+ ChangeLog. Oops.
+
+ * dbxread.c (process_symbol_for_psymtab): Put every debugger
+ symbol which survives the top case except for constants on the
+ symchain. This means that all of these *won't* show up in misc
+ functions (this will be fixed once I make sure it's broken the way
+ it's supposed to be).
+
+ * dbxread.c: Modified placement of debugger globals onto the hash
+ list; now we exclude the stuff after the colon and don't skip the
+ first character (debugger symbols don't have underscores).
+
+ * dbxread.c: Killed debuginfo stuff with ifdef's.
+
+Wed Sep 28 14:31:51 1988 Randall Smith (randy at cream-of-wheat.ai.mit.edu)
+
+ * symtab.h, dbxread.c: Modified to deal with BINCL, EINCL, and
+ EXCL symbols produced by the sun loader by adding a list of
+ pre-requisite partial_symtabs that each partial symtab needs.
+
+ * symtab.h, dbxread.c, symtab.c, symmisc.c: Modified to avoid
+ doing a qsort on the local (static) psymbols for each file to
+ speed startup. This feature is not completely debugged, but it's
+ inclusion has forced the inclusion of another feature (dealing
+ with EINCL's, BINCL's and EXCL's) and so I'm going to go in and
+ deal with them.
+
+ * dbxread.c (process_symbol_for_psymtab): Made sure that the class
+ of the symbol made it into the partial_symbol entry.
+
+Tue Sep 27 15:10:26 1988 Randall Smith (randy at gluteus.ai.mit.edu)
+
+ * dbxread.c: Fixed bug; init_psymbol_list was not being called
+ with the right number of arguments (1).
+
+ * dbxread.c: Put ifdef's around N_MAIN, N_M2C, and N_SCOPE to
+ allow compilation on a microvax.
+
+ * config.gdb: Modified so that "config.gdb vax" would work.
+
+ * dbxread.c, symtab.h, symmisc.h, symtab.c, source.c: Put in many
+ and varied hacks to speed up gdb startup including: A complete
+ rewrite of read_dbx_symtab, a modification of the partial_symtab
+ data type, deletion of select_source_symtab from
+ symbol_file_command, and optimiztion of the call to strcmp in
+ compare_psymbols.
+
+Thu Sep 22 11:08:54 1988 Randall Smith (randy at gluteus.ai.mit.edu)
+
+ * dbxread.c (psymtab_to_symtab): Removed call to
+ init_misc_functions.
+
+ * dbxread.c: Fixed enumeration type clash (used enum instead of
+ integer constant).
+
+ * breakpoint.c: Fixed typo; lack of \ at end of line in middle of
+ string constant.
+
+ * symseg.h: Fixed typo; lack of semicolon after structure
+ definition.
+
+ * command.c, breakpoint.c, printcmd.c: Added cmdlist editing
+ functions to add commands with the abbrev flag set. Changed
+ help_cmd_list to recognize this flag and modified unset,
+ undisplay, and enable, disable, and delete breakpoints to have
+ this flag set.
+
+Wed Sep 21 13:34:19 1988 Randall Smith (randy at plantaris.ai.mit.edu)
+
+ * breakpoint.c, infcmd.c, gdb.texinfo: Created "unset" as an alias
+ for delete, and changed "unset-environment" to be the
+ "environment" subcommand of "delete".
+
+ * gdb.texinfo, valprint.c: Added documentation in the manual for
+ breaking the set-* commands into subcommands of set. Changed "set
+ maximum" to "set array-max".
+
+ * main.c, printcmd.c, breakpoint.c: Moved the declaration of
+ command lists into main and setup a function in main initializing
+ them to guarrantee that they would be initialized before calling
+ any of the individual files initialize routines.
+
+ * command.c (lookup_cmd): A null string subcommand is treated as
+ an unknown subcommand rather than an ambiguous one (eg. "set $x =
+ 1" will now work).
+
+ * infrun.c (wait_for_inferior): Put in ifdef for Sony News in
+ check for trap by INNER_THAN macro.
+
+ * eval.c (evaluate_subexp): Put in catch to keep the user from
+ attempting to call a non function as a function.
+
+Tue Sep 20 10:35:53 1988 Randall Smith (randy at oatmeal.ai.mit.edu)
+
+ * dbxread.c (read_dbx_symtab): Installed code to keep track of
+ which global symbols did not have debugger symbols refering to
+ them, and recording these via record_misc_function.
+
+ * dbxread.c: Killed code to check for extra global symbols in the
+ debugger symbol table.
+
+ * printcmd.c, breakpoint.c: Modified help entries for several
+ commands to make sure that abbreviations were clearly marked and
+ that the right commands showed up in the help listings.
+
+ * main.c, command.c, breakpoint.c, infcmd.c, printcmd.c,
+ valprint.c, defs.h: Modified help system to allow help on a class
+ name to show subcommands as well as commands and help on a command
+ to show *all* subcommands of that command.
+
+Fri Sep 16 16:51:19 1988 Randall Smith (randy at gluteus.ai.mit.edu)
+
+ * breakpoint.c (_initialize_breakpoint): Made "breakpoints"
+ subcommands of enable, disable, and delete use class 0 (ie. they
+ show up when you do a help xxx now).
+
+ * infcmd.c,printcmd,c,main.c,valprint.c: Changed the set-*
+ commands into subcommands of set. Created "set variable" for use
+ with variables whose names might conflict with other subcommands.
+
+ * blockframe.c, dbxread.c, coffread.c, expread.y, source.c:
+ Fixed mostly minor (and one major one in block_for_pc) bugs
+ involving checking the partial_symtab_list when a scan through the
+ symtab_list fails.
+
+Wed Sep 14 12:02:05 1988 Randall Smith (randy at sugar-smacks.ai.mit.edu)
+
+ * breakpoint.c, gdb.texinfo: Added enable breakpoints, disable
+ breakpoints and delete breakpoints as synonyms for enable,
+ disable, and delete. This seemed reasonable because of the
+ immeninent arrival of watchpoints & etc.
+
+ * gdb.texinfo: Added enable display, disable display, and delete
+ display to manual.
+
+Tue Sep 13 16:53:56 1988 Randall Smith (randy at sugar-smacks.ai.mit.edu)
+
+ * inferior.h, infrun.c, infcmd.c: Added variable
+ stop_random_signal to indicate when a proceed had been stopped by
+ an unexpected signal. Used this to determine (in normal_stop)
+ whether the current display point should be deleted.
+
+ * valops.c: Fix to value_ind to check for reference before doing a
+ COERCE_ARRAY.
+
+Sun Jul 31 11:42:36 1988 Richard Stallman (rms at frosted-flakes.ai.mit.edu)
+
+ * breakpoint.c (_initialize_breakpoint): Clean up doc for commands
+ that can now apply also to auto-displays.
+
+ * coffread.c (record_line): Corrected a spazz in editing.
+ Also removed the two lines that assume line-numbers appear
+ only in increasing order.
+
+Tue Jul 26 22:19:06 1988 Peter TerMaat (pete at corn-chex.ai.mit.edu)
+
+ * expression.h, eval.c, expprint.c, printcmd.c, valarith.c,
+ valops.c, valprint.c, values.c, m-*.h: Changes for evaluating and
+ displaying 64-bit `long long' integers. Each machine must define
+ a LONGEST type, and a BUILTIN_TYPE_LONGEST.
+
+ * symmisc.c: (print_symtab) check the status of the fopen and call
+ perror_with_name if needed.
+
+Thu Jul 21 00:56:11 1988 Peter TerMaat (pete at corn-chex.ai.mit.edu)
+
+ * Convex: core.c: changes required by Convex's SOFF format were
+ isolated in convex-dep.c.
+
+Wed Jul 20 21:26:10 1988 Peter TerMaat (pete at corn-chex.ai.mit.edu)
+
+ * coffread.c, core.c, expread.y, i386-pinsn.c, infcmd.c, inflow.c,
+ infrun.c, m-i386.h, main.c, remote.c, source.c, valops.c:
+ Improvements for the handling of the i386 and other machines
+ running USG. (Several of these files just needed extra header files
+ such as types.h.) utils.c: added bcopy, bcmp, bzero, getwd, list
+ of signals, and queue routines for USG systems. Added vfork macro
+ to i386
+
+ * printcmd.c, breakpoint.c: New commands to enable/disable
+ auto-displays. Also `delete display displaynumber' works like
+ `undisplay displaynumber'.
+
+Tue Jul 19 02:17:18 1988 Peter TerMaat (pete at corn-chex.ai.mit.edu)
+
+ * coffread.c: (coff_lookup_type) Wrong portion of type_vector was
+ being bzero'd after type_vector was reallocated.
+
+ * printcmd.c: (delete_display) Check for a display chain before
+ attempting to delete a display.
+
+ * core.c, *-dep.c (*-infdep moved to *-dep): machine-dependent
+ parts of core.c (core_file_command, exec_file_command) moved to
+ *-dep.c.
+
+Mon Jul 18 19:45:51 1988 Peter TerMaat (pete at corn-chex.ai.mit.edu)
+
+ * dbxread.c: typo in read_struct_type (missing '=') was causing a
+ C struct to be parsed as a C++ struct, resulting in a `invalid
+ character' message.
+
+Sun Jul 17 22:27:32 1988 Peter TerMaat (pete at corn-chex.ai.mit.edu)
+
+ * printcmd.c, symtab.c, valops.c, expread.y: When an expression is
+ read, the innermost block required to evaluate the expression is
+ saved in the global variable `innermost_block'. This information
+ is saved in the `block' field of an auto-display so that
+ expressions with inactive variables can be skipped. `info display'
+ tells the user which displays are active and which are not. New
+ fn `contained_in' returns nonzero if one block is contained within
+ another.
+
+Fri Jul 15 01:53:14 1988 Peter TerMaat (pete at corn-chex.ai.mit.edu)
+
+ * infrun.c, m-i386.h: Use macro TRAPS_EXPECTED to set number of
+ traps to skip when sh execs the program. Default is 2, m-i386.h
+ overrides this and sets to 4.
+
+ * coffread.c, infrun.c: minor changes for the i386. May be able
+ to eliminate them with more general code.
+
+ * default-infdep.c: #ifdef SYSTEMV, include header file types.h.
+ Also switched the order of signal.h and user.h, since System 5
+ requires signal.h to come first.
+
+ * core.c main.c, remote,c, source.c, inflow.c: #ifdef SYSTEMV,
+ include various header files. Usually types.h and fcntl.h.
+
+ * utils.c: added queue routines needed by the i386 (and other sys
+ 5 machines).
+
+ * sys5.c, regex.c, regex.h: new files for sys 5 systems. (The
+ regex files are simply links to /gp/gnu/lib.)
+
+Thu Jul 14 01:47:14 1988 Peter TerMaat (pete at corn-chex.ai.mit.edu)
+
+ * config.gdb, README: Provide a list of known machines when user
+ enters an invalid machine. New second arg is operating system,
+ currently only used with `sunos4' or `os4'. Entry for i386 added.
+
+ * news-infdep.c: new file.
+
+ * m-news.h: new version which deals with new bugs in news800's OS.
+
+Tue Jul 12 19:52:16 1988 Peter TerMaat (pete at corn-chex.ai.mit.edu)
+
+ * Makefile, *.c, munch, config.gdb, README: New initialization
+ scheme uses nm to find functions whose names begin with
+ `_initialize_'. Files `initialize.h', `firstfile.c',
+ `lastfile.c', `m-*init.h' no longer needed.
+
+ * eval.c, symtab.c, valarith.c, valops.c, value.h, values.c: Bug
+ fixes from gdb+ 2.5.4. evaluate_subexp takes a new arg, type
+ expected. New fn value_virtual_fn_field.
+
+Mon Jul 11 00:48:49 1988 Peter TerMaat (pete at corn-chex.ai.mit.edu)
+
+ * core.c (read_memory): xfer_core_file was being called with an
+ extra argument (0) by read_memory.
+
+ * core.c (read_memory), *-infdep.c (read_inferior_memory),
+ valops.c (value_at): read_memory and read_inferior_memory now work
+ like write_memory and write_inferior_memory in that errno is
+ checked after each ptrace and returned to the caller. Used in
+ value_at to detect references to addresses which are out of
+ bounds. Also core.c (xfer_core_file): return 1 if invalid
+ address, 0 otherwise.
+
+ * inflow.c, <machine>-infdep.c: removed all calls to ptrace from
+ inflow.c and put them in machine-dependent files *-infdep.c.
+
+Sun Jul 10 19:19:36 1988 Peter TerMaat (pete at corn-chex.ai.mit.edu)
+
+ * symmisc.c: (read_symsegs) Accept only format number 2. Since
+ the size of the type structure changed when C++ support was added,
+ format 1 can no longer be used.
+
+ * core.c, m-sunos4.h: (core_file_command) support for SunOS 4.0.
+ Slight change in the core structure. #ifdef SUNOS4. New file
+ m-sunos4.h. May want to change config.gdb also.
+
+Fri Jul 8 19:59:49 1988 Peter TerMaat (pete at corn-chex.ai.mit.edu)
+
+ * breakpoint.c: (break_command_1) Allow `break if condition'
+ rather than parsing `if' as a function name and returning an
+ error.
+
+Thu Jul 7 22:22:47 1988 Peter TerMaat (pete at corn-chex.ai.mit.edu)
+
+ * C++: valops.c, valprint.c, value.h, values.c: merged code to deal
+ with C++ expressions.
+
+Wed Jul 6 03:28:18 1988 Peter TerMaat (pete at corn-chex.ai.mit.edu)
+
+ * C++: dbxread.c: (read_dbx_symtab, condense_misc_bunches,
+ add_file_command) Merged code to read symbol information from
+ an incrementally linked file. symmisc.c:
+ (init_free_inclink_symtabs, free_inclink_symtabs) Cleanup
+ routines.
+
+Tue Jul 5 02:50:41 1988 Peter TerMaat (pete at corn-chex.ai.mit.edu)
+
+ * C++: symtab.c, breakpoint.c, source.c: Merged code to deal with
+ ambiguous line specifications. In C++ one can have overloaded
+ function names, so that `list classname::overloadedfuncname'
+ refers to several different lines, possibly in different files.
+
+Fri Jul 1 02:44:20 1988 Peter TerMaat (pete at corn-chex.ai.mit.edu)
+
+ * C++: symtab.c: replaced lookup_symtab_1 and lookup_symtab_2 with
+ a modified lookup_symbol which checks for fields of the current
+ implied argument `this'. printcmd.c, source.c, symtab.c,
+ valops.c: Need to change callers once callers are
+ installed.
+
+Wed Jun 29 01:26:56 1988 Peter TerMaat (pete at frosted-flakes.ai.mit.edu)
+
+ * C++: eval.c, expprint.c, expread.y, expression.h, valarith.c,
+ Merged code to deal with evaluation of user-defined operators,
+ member functions, and virtual functions.
+ binop_must_be_user_defined tests for user-defined binops,
+ value_x_binop calls the appropriate operator function.
+
+Tue Jun 28 02:56:42 1988 Peter TerMaat (pete at frosted-flakes.ai.mit.edu)
+
+ * C++: Makefile: changed the echo: expect 101 shift/reduce conflicts
+ and 1 reduce/reduce conflict.
+
+Local Variables:
+mode: indented-text
+left-margin: 8
+fill-column: 74
+version-control: never
+End:
diff --git a/gdb/ChangeLog-9091 b/gdb/ChangeLog-9091
new file mode 100644
index 00000000000..42f8d0b4af8
--- /dev/null
+++ b/gdb/ChangeLog-9091
@@ -0,0 +1,8322 @@
+Mon Dec 30 10:57:02 1991 Per Bothner (bothner at cygnus.com)
+
+ Mainly stuff to improve handling of TYPE_CODE_REF values.
+ * valops.c (value_addr): If taking the addres of a
+ TYPE_CODE_REF, just cast the object to the corresponding
+ TYPE_CODE_PTR. This yields correct C++ semantics, and
+ preserves the location information, which has the nice effect
+ that &(&R) given the location containing R.
+ * values.c (value_copy): Make non-static (used by value_addr).
+ * eval.c (evaluate_subexp_for_address): Use the default
+ scheme (with value_addr) for a variable if it has TYPE_CODE_REF.
+ * valops.c (value_addr), eval.c (evaluate_subexp_for_address,
+ evaluate_subexp_with_coercion): Factor out some common
+ expressions into variables, for easier reading.
+ * findvar.c (locate_var_value): Remove code to handle
+ TYPE_CODE_REF - it should no longer be needed.
+ * valops.c (value_assign): Do a COERCE_REF on the
+ destination operand, for correct C++ semantics.
+ * valarith.c (value_x_binop): Ditto: De-reference C++
+ references in the arguments.
+ * valops.c: ANSI-fy: bcopy->memcpy, bzero->memset.
+
+Sat Dec 28 11:30:26 1991 Per Bothner (bothner at cygnus.com)
+
+ * dwarfread.c, coffread.c: Use INIT_CPLUS_SPECIFIC.
+ * symtab.c (gdb_mangle_name): Recognize and handle
+ constructors specially.
+ * symtab.c (check_stub_method): Test for failure from
+ cplus-demangle by calling error() instead of seg-faulting ...
+
+Fri Dec 27 22:21:30 1991 Fred Fish (fnf at cygnus.com)
+
+ * defs.h: Add definition of null_cleanup()
+
+ * procfs.c: Many small changes to add base support for a new
+ "info proc" command (currently only printing of the address
+ space mapping is implemented) and allow iteration over the
+ address space mapping, calling an arbitrary function for each
+ mapping (used for shared library support).
+
+ * solib.c: Change all ifdefs that checked for "sun" to check
+ for "!SVR4_SHARED_LIBS" instead. Rewrite lookup_base() to
+ handle locating the debug base address even when not currently
+ stopped at the dynamic linker entry point.
+
+ * utils.c: Add null_cleanup() as a known function that does
+ nothing to serve as a base for possibly long cleanup chains
+ with no specific "first cleanup" to serve as an anchor.
+
+ * xm-sysv4.h: Add define of SVR4_SHARED_LIBS
+
+Fri Dec 27 10:11:33 1991 Per Bothner (bothner at cygnus.com)
+
+ * arm-opcode.h, m88k-opcode.h, pn-opcode.h, np1-opcode.h,
+ pyr-opcode.h, tahoe-opcode, vax-opcode.h: Removed -
+ these are all essentially the same as the versions
+ in ../include/opcode. The remaining *-opcode.h here
+ are not quite so obviously the same, and need study.
+ * arm-pinsn.c, gould-pinsn.c, m88k-pinsn.c, pyr-pinsn.c,
+ tahoe-pinsn.c, vax-pinsn.c: Change so these include
+ opcode/FOO.h (actually ../include/opcode/FOO.h)
+ instead of the recenntly departed opcode-FOO.h files.
+ * sparc-pinsn.c: Now that we're using the much tighter
+ opcode table in ../include/opcode/sparc.h, we shouldn't
+ need to sort the opcodes before dis-assembly.
+
+ * symtab.h, symmisc.c: Make cplus_struct_default be const.
+ * symtab.h, buildsym.c: Add and use INIT_CPLUS_SPECIFIC macro.
+ * symmisc.c: Remove unused 'nfields' variable.
+ * buildsym.h: Add extern decl of unknown_symtype_complaint,
+ since it used used by partial-stab.h (included two places).
+ * partial-stab.h: Re-arrange DBXREAD_ONLY #ifdefs so that
+ we should never hit the default case (until new stab codes
+ are added). Hence, we can leave the complaint in the
+ default case in even when DBXREAD_ONLY is off.
+ * partial_stab.h: Recognize a pair of N_SO stabs (one for the
+ directory, one for the filename proper) without peeking ahead.
+ * dbxread.c, mipsread.c: Because of previous change, don't need
+ ugly CHECK_SECOND_N_SO macro.
+ * buildsym.h, dbxread.c, mipsread.c: Make next_symbol_text a
+ macro that invokes a function pointer in next_symbol_text_func.
+ * mipsread.c: Added comments various places to
+ explain what is going on.
+ * mipsread.c (parse_symbol): Support the new (SGI-specific?)
+ symbol types stStruct, stUnion, and stEnum.
+ Also, some fixes in the code for dealing with tags.
+ * mipsread.c: Change handling of startup_file_start and _end
+ - now just use the textlow and texhigh of a psymtab
+ to check if we've found the startup-file.
+ * mipsread.c: Replace s_idx by global cur_sdx in many places.
+ This is so mips_next_symbol_text can get at it.
+
+Thu Dec 26 19:52:01 1991 Fred Fish (fnf at cygnus.com)
+
+ * dbxread.c, symmisc.c: Move add_psymbol_to_plist() from
+ dbxread.c to symmisc and change name to add_psymbol_to_list.
+ Ditto for add_psymbol_addr_to_plist(). Also expand their
+ body to not use ADD_PSYMBOL_VT_TO_LIST.
+
+ * dwarfread.c: Remove add_psymbol_to_list() and convert usages
+ to the ADD_PSYMBOL_TO_LIST macro.
+
+ * ieee-float.c: Change "#ifdef DEBUG" to "#ifdef IEEE_DEBUG"
+ to avoid collision with the DEBUG for ADD_PSYMBOL_VT_TO_LIST.
+
+ * partial-stab.h, symfile.h: Move definitions of the macros
+ ADD_PSYMBOL_TO_LIST and ADD_PSYMBOL_ADDR_TO_LIST from
+ partial-stab.h to symfile.h. They aren't stab specific.
+ Change ADD_PSYMBOL_VT_TO_LIST to use memcpy rather than strncpy.
+
+Tue Dec 24 11:38:08 1991 John Gilmore (gnu at cygnus.com)
+
+ * Makefile.in: Roll VERSION to 4.3.2.
+
+Mon Dec 23 13:54:35 1991 Per Bothner (bothner at cygnus.com)
+
+ * m68k-opcode.h, mips-opcode.h, sparc-opcode.h: Deleted.
+ * m68k-pinsn.c, mips-pinsn.c, sparc-pinsn.c:
+ Include <opcode/FOO.h> instead of <FOO-opcode.h>.
+
+ * symtab.h, symtab.c, coffread.c, dwarfread.c, symmisc.c,
+ dbxread.c: The TYPE_CPLUS_SPECIFIC structure is now only
+ allocated when it is needed. Until it is needed, it points
+ to a shared statically allocated structure.
+
+ * buildsym.h, buildsym.c, dbxread.c: Remove the kludgy code
+ in read_ofile_symtab to recognize two initial N_SO stabs,
+ and let process_on_symbol handle it. This is cleaner, more
+ efficient, and lets mipsread.c share the same code.
+
+ * symfile.h, partial-stab.h: Move ADD_PSYMBOL_VT_TO_LIST
+ and related macros to here ...
+ * dbxread.c: ... from here.
+ * symmisc.c: Move the "overflow" handling from
+ ADD_PSYMBOL_VT_TO_LIST macro into new function extend_psymbol_list.
+ * dwarfread.c: Re-write add_psymbol_to_list to use
+ ADD_PSYMBOL_VT_TO_LIST macro.
+
+ * mipsread.c: Extend mipsread.c to handle stabs-style symbols
+ encapsulated in ecoff symbols. This enable full g++ debugging.
+ * partial-stab.h: Move the code for pre-scanning symbols
+ and building psymtabs to an include file, out from dbxread.c.
+ This way, the same code can also be used by mipsread.c.
+ * dbxread.c, buildsym.h: Various changes to allow some functions
+ to be used by mipsread.c (also some arguable stylistic changes).
+
+ * tm-mips.h: Define BLOCK_ADDRESS_ABSOLUTE, at least for now,
+ since mips-tfile puts relocatable addresses into LBRAC/RBRAC
+ stabs.
+
+ * mipsread.c: Replace code to handle ambiguous tag blocks.
+ Instead of allocating a TYPE_CODE_UNDEF, guess (by looking
+ at types and offsets) if a tag is a struct, union, or enum.
+ Still patch it later if we find out for sure.
+ * mipsread.c: In various ways, replace Forin's
+ ideo-syncratic code by code that fits better with the
+ rest of gdb, for both stabs-based and ecoff-based symtabs.
+ E.g. use end_psymtab; don't do extra passes over FDR table to
+ pre-partition global data; don't use external symbols to
+ create static/global symbols (just put them in the
+ misc_vector); use ADD_PSYMBOL_TO_LIST macro; don't
+ sort psymtabs or symtabs; use obstacks more.
+
+ * symtab.c, mipsread.c, dbxread.c, buildsym.c:
+ ANSIfy: Replace bcopy by memcpy, bzero by memset.
+
+Sun Dec 22 19:31:04 1991 Fred Fish (fnf at cygnus.com)
+
+ * solib.c (locate_base): Fix uninitialized variable that was
+ causing return of random value to callee.
+
+ * config/mh-amix, config/mh-i386v4: Change to find alloca by
+ compiling and linking alloca.c, even when it is not strictly
+ required. Also arrange to link with -ltermlib rather than
+ -ltermcap.
+
+ * Makefile.in: Move TERMCAP definition to prior to inclusion
+ of host makefile fragments so it can be overridden.
+
+Fri Dec 20 16:33:39 1991 John Gilmore (gnu at cygnus.com)
+
+ * xcoffread.c (read_symbol_lineno): Logic error in incrementing
+ symbol table entry number. (From Metin Ozisik.)
+
+Fri Dec 20 11:36:38 1991 Fred Fish (fnf at cygnus.com)
+
+ * config/mh-i386v4: Change XM_CLIBS to "-lc /usr/ucblib/libucb.a"
+ so compiles with native compilers (without builtin alloca) can
+ pick up the version from the bsd emulation library. However, we
+ search the standard C library first so we don't pick up lots of
+ other broken stuff from libucb.a, that we *don't* want.
+
+ * configure.in, tm-amix.h, tm-i386v4.h, xm-amix.h, xm-i386v4.h:
+ Change svr4 references to sysv4.
+
+ * source.c: Move declaration of external function index to
+ front of file so it is in scope for all references.
+
+ * utils.c (error, fatal): Make definitions consistent with
+ defs.h declarations (declared as "volatile void").
+
+Fri Dec 20 10:55:36 1991 John Gilmore (gnu at cygnus.com)
+
+ * rs6k-opcode.h: Bugfix sfe and stbrx. By Al Kossow.
+
+Wed Dec 18 17:09:06 1991 Stu Grossman (grossman at cygnus.com)
+
+ * command.h, defs.h, eval.h, expression.h, remote-sa.sparc.c,
+ sparc-tdep.c, symtab.h, target.h, value.h, vx-share/ptrace.h,
+ vx-share/xdr_ptrace.h, vx-share/xdr_rdb.h: ANSIfy enums.
+
+Mon Dec 16 12:31:46 1991 Fred Fish (fnf at cygnus.com)
+
+ * config/mt-amix, config/mt-i386v4: Add solib.o to TDEPFILES
+ for these SVR4 systems.
+
+ * symfile.c (symbol_file_add): When verbose is set, print
+ the names of files from which symbols are being loaded, as
+ when from_tty is true.
+
+ * solib.c: Completely reorganized (rewritten) to support
+ SVR4 shared libraries in a manner very close to the original
+ SunOS implementation. This support is expected to change and
+ become more general at some future time. The SVR4 version
+ does not yet work for attached processes, for example.
+
+ * dwarfread.c: Arrange in dwarf_build_psymtabs() for the
+ relocation address to be valid whether or not symbols are
+ being read from a shared library or an executable. Use the
+ relocation address recorded in the psymtab when reading
+ full symbol tables (in read_ofile_symtab). Ensure that the
+ relocated address ranges are recorded in partial symtabs.
+
+ * elfread.c: Add new function elf_interpreter() to return the
+ string from the ELF ".interp" section. This is the interpreter
+ that the kernel tries to run and feed the executable to.
+ Expand arguments to record_misc_function to include a type arg.
+ Modify elf_symtab_read() to supply the type arg, and to do symbol
+ relocations for symbols read in from shared libraries.
+
+ * procfs.c: Add new functions proc_base_address() and
+ proc_address_to_fd(), used by shared library support.
+
+ * tm-svr4.h: Add macros to support SVR4 shared libraries.
+ Definitions for SOLIB_ADD, SOLIB_CREATE_INFERIOR_HOOK,
+ CLEAR_SOLIB, and DISABLE_UNSETTABLE_BREAK.
+
+Fri Dec 13 20:11:26 1991 John Gilmore (gnu at cygnus.com)
+
+ * infrun.c, remote-eb.c, remote-nindy.c, remote-vx.c: Remove
+ unused START_INFERIOR_HOOK.
+
+ * remote-eb.c: Change timeout to 24 seconds (*10 fits in byte)
+ to account for slow loading from floppies.
+ (eb_create_inferior): New fn, from eb_start and
+ nindy_create_inferior.
+ (eb_close): Only use log_file if nonzero.
+ (eb_xfer_inferior_memory): If not writing, then read!
+ (eb_read_inferior_memory, eb_write_inferior_memory): Return length.
+ (eb_kill): A new no-op.
+ (eb_mourn_inferior): Remove breakpoints, then generically weep.
+
+Fri Dec 13 16:09:23 1991 Fred Fish (fnf at cygnus.com)
+
+ * breakpoint.c, findvar.c, infrun.c, putenv.c, stack.c: Fix
+ miscellaneous comparisons of integer with NULL that elicit
+ compiler warnings about comparison of integer with pointer, when
+ NULL is ((void *) 0) rather than just a bare 0.
+
+Wed Dec 11 13:02:58 1991 John Gilmore (gnu at cygnus.com)
+
+ * breakpoint.c (breakpoint_re_set_one): Disable each breakpoint
+ while we reset it, in case of problems. Print breakpoint number
+ in error messages.
+
+ * buildsym.c (read_struct_type): Avoid sun3 compiler bug with
+ foo[--n].
+
+ * source.c (find_source_lines): If getting file mod time fails,
+ don't warn.
+
+ * target.c (target_xfer_memory): If errno is set, return it,
+ rather than EIO.
+
+Tue Dec 10 04:07:22 1991 K. Richard Pixley (rich at rtl.cygnus.com)
+
+ * Makefile.in: infodir belongs in datadir.
+
+Sun Dec 8 21:13:33 1991 Michael Tiemann (tiemann at sphagnum.cygnus.com)
+
+ * symtab.h (struct fn_field): Add new fields `is_private',
+ `is_protected', `is_stub', making room by reducing the size of
+ `voffset'.
+ (struct fn_fieldlist): Delete the fields `private_fn_field_bits'
+ and `protected_fn_field_bits'.
+ (TYPE_FN_{PRIVATE,PROTECTED}_BITS): Deleted.
+ (SET_TYPE_FN_{PRIVATE,PROTECTED}): Deleted.
+ (TYPE_FN_{PRIVATE,PROTECTED}): Deleted.
+ (TYPE_FN_FIELD_{STUB,PRIVATE,PROTECTED}): New macros.
+ * valops.c, valprint.c, symtab.c: All callers updated.
+
+ * buildsym.c (read_struct_type): Delete the `visibility' field
+ from `struct next_fnfield', and rework code so that visibility
+ info is stored into the fn_field directly. Also, hacked to set
+ TYPE_FN_FIELD_STUB for both static and normal member functions.
+
+Sat Dec 7 18:13:11 1991 Fred Fish (fnf at cygnus.com)
+
+ * i386-tdep.c: Fix a problem on i386 systems where buffered code
+ stream access was failing to take into account the minimum size
+ granularity of the code section. For now, the buffering is simply
+ disabled. There is a similar problem in the i386 disassember code
+ that has not yet been fixed (FIXME).
+
+ * gmalloc.c: Use macros to hide some of the ugly casting required
+ in the previously applied fix for pointers with high bits set.
+
+Sat Dec 7 16:49:35 1991 John Gilmore (gnu at cygnus.com)
+
+ * Makefile.in: Roll VERSION to 4.3.1.
+
+Sat Dec 7 04:12:35 1991 John Gilmore (gnu at cygnus.com)
+
+ GDB-4.3 release!
+
+ * Makefile.in: Roll VERSION to 4.3
+ * README, TODO, WHATS.NEW, depend: Update.
+
+ * inflow.c (terminal_inferior): Avoid error msg if attached.
+
+ * gmalloc.c: Fix bug that causes malloc & free to
+ fail on systems where pointers have the high bit set (0x800efcf0
+ for example). The problem is that the difference between two
+ pointers is a signed integer, so the computation
+
+ (char *) 0x800efcf0 - (char *) 0
+
+ yields a negative value. The sign of the result of the modulus
+ operator is machine dependent for negative operands, thus it is
+ possible for it to end up negative. From Fred Fish.
+
+Sat Dec 7 00:00:15 1991 K. Richard Pixley (rich at rtl.cygnus.com)
+
+ * Makefile.in: install using INSTALL_PROGRAM and INSTALL_DATA.
+ added clean-info. added some standards.text support and made it
+ look like our other Makefiles.
+
+ * configure.in: mark this directory target dependent. configure
+ now runs entirely in objdir so make existence tests and
+ references against ${srcdir}.
+
+Fri Dec 6 08:30:36 1991 Fred Fish (fnf at cygnus.com)
+
+ * dwarfread.c (enum_type, struct_type): Fixes for opaque and
+ anonymous enumerations, structures, and unions. Now passes all
+ the current gdb test suite tests.
+
+Thu Dec 5 22:46:13 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.
+
+Thu Dec 5 21:53:21 1991 John Gilmore (gnu at cygnus.com)
+
+ * symtab.c (decode_line_1): If SKIP_PROLOGUE leaves us in
+ mid-line, be more careful about possibly advancing to the next line.
+
+Thu Dec 5 18:59:51 1991 Michael Tiemann (tiemann at cygnus.com)
+
+ * cplus-dem.c (cplus_demangle): Call `string_need' when
+ null-terminating a partially-computed string.
+
+Thu Dec 5 18:19:43 1991 Fred Fish (fnf at cygnus.com)
+
+ * dwarfread.c (enum_type): Build a correct TYPE_NAME, add a
+ symbol to the symbol table for each member of the enum.
+
+ * dwarfread.c (struct_type): Build a correct TYPE_NAME.
+
+ * dwarfread.c (add_enum_psymbol): New function to extract enum
+ member names and add them to the partial symbol table while
+ building partial symbol tables.
+
+Thu Dec 5 17:31:05 1991 John Gilmore (gnu at cygnus.com)
+
+ * symtab.c (check_stub_method): Must allocate two extra argument
+ slots (one for `this', one for arglist terminator).
+
+Thu Dec 5 10:51:05 1991 Fred Fish (fnf at cygnus.com)
+
+ * inflow.c (child_terminal_info): Supply missing '"' character.
+
+ * buildsym.c (define_symbol): Supply missing parenthesis.
+
+Thu Dec 5 03:34:21 1991 John Gilmore (gnu at cygnus.com)
+
+ * coredep.c (fetch_core_registers): Fencepost error. Fixed by
+ Jay Lepreau <lepreau@cs.utah.edu>.
+
+ * inflow.c: Remember whether GDB has a terminal. Avoid switching
+ terminals back and forth if we don't have one.
+
+ * c-exp.y (parse_number): Zero is not an unsigned int constant!
+ * dbxread.c (read_dbx_symtab): Enum type numbers can be in (1,2) form.
+
+ Improve type parsing.
+ * buildsym.c (define_symbol, read_range_type): Add
+ long_kludge_name that passes the names of range types being
+ defined, down to where we must choose between 'int' and 'long'
+ variants. This fails on Sun C anyway since the compiler itself is
+ confused between int and long.
+ (read_array_type, cleanup_undefined_types): Correct the size of
+ array type whose element-type size isn't immediately known.
+
+ Early preparation to blow away many builtin types, building them
+ on the fly as needed. Don't compare types to builtin types with
+ ==; examine the relevant fields instead.
+ * coffread.c (process_coff_symbol: C_ARG, C_REGPARM): Avoid ==.
+ * buildsym.c (define_symbol, case 'p'): Avoid ==.
+ * valops.c (value_arg_coerce): Avoid ==. Don't assume host and
+ target types are the same.
+ * valprint.c (val_print): I finally understand arrays, remove FIXME.
+
+ * symmisc.c (printpsyms_command): Reduce redundancy, and put all
+ addresses in GDB itself into parens for easy cleanup and diffing.
+
+Wed Dec 4 21:05:30 1991 Fred Fish (fnf at cygnus.com)
+
+ * dwarfread (enum_type): Arrange for the order of enumeration
+ members to match the source code order; not the order in the
+ Dwarf information, which is explicitly reverse order.
+
+Wed Dec 4 18:24:39 1991 John Gilmore (gnu at cygnus.com)
+
+ * main.c (input_from_terminal_p): Check whether GDB has a
+ terminal at all.
+ (initialize_main): Revise doc for `set editing'.
+
+Wed Dec 4 15:36:39 1991 Fred Fish (fnf at cygnus.com)
+
+ * dwarfread.c (struct_type): Handle structures and unions which
+ contain DIE's other than just member dies.
+
+Wed Dec 4 01:59:05 1991 John Gilmore (gnu at cygnus.com)
+
+ * symfile.c (reread_symbols): Avoid kludging mtime_set, now that
+ BFD is fixed.
+
+Tue Dec 3 17:24:57 1991 John Gilmore (gnu at cygnus.com)
+
+ * Makefile.in: VERSION 4.2.96.
+
+ * main.c (initialize_main): Revise command descriptions.
+ * command.c (show_user): `info user' -> `show user'.
+ * symtab.c (_initialize_symtab): Typo in `info types' desc.
+
+ * coffread.c (coff_symfile_read): Avoid select_source_symtab,
+ since it is not needed and can cause errors when examining ".o"s.
+ (read_coff_symtab, decode_base_type): Use complain, not printf.
+ Print symbol name, not its number.
+ Remove "#if defined(clipper) #define BELIEVE_PCC_PROMOTION", which
+ someday should go in a clipper target config file.
+
+ * symfile.c (compact_misc_function_vector): Handle empty vector.
+ (complain, clear_complaints, syms_from_objfile): Fix complaint
+ formatting.
+ * xcoffexec.c: Change syms_from_objfile caller.
+
+ * sparc-xdep.c: Force tm-file as tm-sparc.h, to make it compile
+ when configured for cross debugging. FIXME, this needs a more
+ general solution.
+
+Mon Dec 2 11:04:05 1991 Per Bothner (bothner at cygnus.com)
+
+ * mips-tdep.c (init_extra_frame_info): Float register
+ 'i' has gdb-internal number 'FP0+i', not '32+i'.
+ * mipsread.c (new_symbol): Translate g++ special
+ symbol "$t" to "this".
+
+Sat Nov 30 21:29:55 1991 Steve Chamberlain (sac at cygnus.com)
+ Changes due to include file renaming:
+
+ * xcoffread.c: internalcoff.h ->coff/internal.c,
+ coff-rs6000.h ->coff/rs6000.h
+ * mipsread.c: coff-mips.h ->coff/mips.h
+ * elfread.c: elf-common.h ->elf/common.h
+ elf-external.h ->elf/external.h,
+ elf-internal.h ->elf/internal.h
+ * dwarfread.c dwarf.h ->elf/dwarf.h
+ * dbxread.c: aout64.h ->aout/aout64.h
+ stab.gnu.h ->aout/stab_gnu.h
+
+ * coffread.c: internalcoff.h ->coff/internal.h
+ * buildsym.c: stab.gnu.h ->aout/stab_gnu.h
+ * depend Updated to take the above into account.
+
+Fri Nov 29 16:59:25 1991 Fred Fish (fnf at cygnus.com)
+
+ * configure.in: Add SVR4 i386 configurations.
+
+ * config/mh-i386v4, config/mt-i386v4, tm-i386v4.h, xm-i386v4.h:
+ New files for i386/SVR4.
+
+ * tm-i386v.h: Allow START_INFERIOR_TRAPS_EXPECTED and
+ DECR_PC_AFTER_BREAK to be predefined by files including
+ tm-i386v.h.
+
+ * i386-tdep.c: Add supply_gregset(), fill_gregset(),
+ supply_fpregset(), and fill_fpregset() functions, which are
+ target dependent support functions for the SVR4 /proc register
+ interface.
+
+ * dwarfread.c (enum_type, struct_type): Expand recognized
+ compiler generated tags to include symbols beginning with '.' as
+ well as '~'.
+
+ * symtab.c (sources_info): Change simple printf of error message
+ to call to error().
+
+Fri Nov 29 16:04:21 1991 Roland H. Pesch (pesch at cygnus.com)
+
+ * doc/gdb.texinfo: remove leading comments that survived M4 but
+ described its role in the doc; add one more font to colophon;
+ strengthen disclaimer about unsupported configs.
+
+Wed Nov 27 01:23:41 1991 John Gilmore (gnu at cygnus.com)
+
+ Fix bugs in C++ debugging.
+
+ * symtab.h: target_type is not used in record types.
+ Eliminate TYPE_MAIN_VARIANT and TYPE_NEXT_VARIANT. Eliminate
+ lookup_method_type. Add TYPE_TYPE_SPECIFIC macro.
+
+ * symtab.c (lookup_member_type): Don't chain them up, just
+ allocate one in symbol_obstack when we need one.
+ (allocate_stub_method): Build stub in symbol_obstack.
+ (check_stub_method): Move here from values.c. Don't deallocate
+ stub; overwrite it.
+ (lookup_method_type): Gone now.
+
+ * buildsym.c: Handle g++ v1 stabs a little bit better.
+ Change some C++ parsing error()s to complain()ts.
+ * buildsym.c, findvar.c, printcmd.c, symtab.c: Make unions and
+ structs have the same representation and work the same as far as
+ C++ is concerned.
+ * buildsym.c, symtab.c, values.c: Remove all references to
+ TYPE_MAIN_VARIANT and TYPE_NEXT_VARIANT.
+
+ * valops.c: Improve comments and indentation. Only call
+ check_stub_method when the stub flag is on.
+ * valprint.c: Fix or mark minor bugs and unportabilities.
+
+ * coffread.c (anonymous unions): Allocate a cplus structure.
+
+ * mipsread.c: Eliminate "template" types. Build new, real
+ types whenever we need them. Allocate cplus structures as needed.
+ Bulletproof the type parsing a bit more. Mark storage leaks.
+ (parse_type): Copy TYPE_TYPE_SPECIFIC when copying a real type
+ on top of a partial type.
+
+Fri Nov 22 16:39:57 1991 John Gilmore (gnu at cygnus.com)
+
+ * inflow.c (terminal_inferior): Check the results of ioctl's, and
+ print a message if any of them fail.
+ (terminal_ours_1): Store result of ioctl's for debugging, but
+ don't print (the terminal isn't ours...).
+
+ * tm-tahoe.h (FRAME_ARGS_ADDRESS): No need to offset from frame
+ pointer.
+
+ * m2-exp.y (MAX, MIN): Rename to MAX_FUNC, MIN_FUNC to avoid
+ conflicts with system header files.
+
+Fri Nov 22 08:27:40 1991 John Gilmore (gnu at cygnus.com)
+
+ * Roll VERSION to 4.2.95.
+
+ * buildsym.c, coredep.c, mem-break.c, xcoffread.c: Put <stdio.h>
+ first, before defs.h.
+ * config/mh-i386sco: Override compiler to gcc, print warning.
+ * configure.in: Handle i386-none-aout rather than i386-aout-none.
+ * infptrace.c, language.h, utils.c: Lint.
+ * m2-exp.y: #undef MAX and MIN in case system includes set them.
+ * xm-tahoe.h: Set HOST_BYTE_ORDER. Include system versions of
+ {BIG,LITTLE}_ENDIAN and the INT_MAX family first, to avoid
+ redefinition warnings.
+ * defs.h: Reorder things so that the xm-file gets first crack
+ at #define's, followed by defs.h and then the tm-file.
+ * Makefile.in: Remove spaces after 'ignore exit code' - flags.
+ Late-model BSD 'make's don't cope with them.
+
+Thu Nov 21 23:48:56 1991 John Gilmore (gnu at cygnus.com)
+
+ * Makefile.in: Roll new files into various lists.
+
+Thu Nov 21 18:26:11 1991 Fred Fish (fnf at cygnus.com)
+
+ * dwarfread.c (struct_type): Must initialize the c++ specific
+ portion of union types as well as struct types, since gdb attempts
+ to reference the c++ specific info for both types.
+
+Thu Nov 21 10:23:52 1991 John Gilmore (gnu at cygnus.com)
+
+ * Makefile.in: Roll VERSION to 4.2.90.
+
+ * defs.h: Incorporate param.h into defs.h. All users changed.
+ * param-no-tm.h: Change users to define TM_FILE_OVERRIDE instead.
+ * param.h, param-no-tm.h: Removed.
+ * Update copyrights in all changed files.
+ * dbxread.c, dwarfread.c, inflow.c, infrun.c, m2-exp.y, putenv.c,
+ solib.c, symtab.h, tm-umax.h, valprint.c: Lint.
+ * tm-convex.h, tm-hp300hpux.h, tm-merlin.h, tm-sparc.h,
+ xm-merlin.h: Avoid host include files in target descriptions.
+ * getpagesize.h: Removed, libiberty copes now.
+ * Makefile.in: Remove getpagesize.h, param.h, param-no-tm.h.
+
+ * exec.c (exec_files_info): If `verbose' is set, show file offset
+ as well.
+
+ * main.c: Use getcwd rather than getwd.
+ * standalone.c: Fake getcwd rather than getwd.
+ * xm-*.h: Remove fake values of MAXPATHLEN.
+
+ * xcoffexec.c: Add /* */ to #if 0'd thing to help ANSI.
+
+Wed Nov 20 18:35:56 1991 John Gilmore (gnu at cygnus.com)
+
+ * Remove gdb/hp-include. Support for HP a.out oddities should be
+ in BFD, not in GDB. Move gdb/hp-include/a.out.h to include/a.out.hp.h.
+
+ * infptrace.c, tm-sun386.h: Cashier <a.out.gnu.h>, remove refs.
+
+ * configure.in, xconfig, tconfig, Makefile.in, doc/gdbint.texinfo:
+ Makefile fragments for various hosts and targets now come from
+ gdb/config/mh-* and gdb/config/mt-*. This is for consistency with
+ other config setups.
+
+ * rs6000-pinsn.c, rs6k-opcode.h: Clean up.
+ * rs6k-opcode.def: Delete.
+
+Wed Nov 20 05:04:40 1991 Fred Fish (fnf at cygnus.com)
+
+ * dwarfread.c: Recognize obsolete form of AT_element_list
+ attribute still used by at least one AT&T compiler, and possibly
+ more.
+
+Tue Nov 19 07:53:55 1991 Fred Fish (fnf at cygnus.com)
+
+ * dwarfread.c (enum_type, struct_type): Ignore names invented by
+ helpful compilers for anonymous structs, unions, and enums.
+
+ * c-exp.y, m2-exp.y: Add defines for yymaxdepth, yy_yys, and
+ yy_yyv, so multiple parsers produced by SVR4 versions of yacc
+ can coexist in the same executable without collision.
+
+ * symtab.h: Add declaration for lookup_template_type() to kill
+ compiler warnings about conversions from int to pointer.
+
+Mon Nov 18 17:45:18 1991 Fred Fish (fnf at cygnus.com)
+
+ * procfs.c: Move inclusion of defs.h to before param.h, as in
+ all the other source files that include both. This is required
+ to supply some typedefs that are used in files included by param.h.
+
+ * m68k-tdep.c (m68k_skip_prologue): Add generic m68k support for
+ skipping function prologues, ala the other cpu families (i386,
+ mips, m88k, etc). Add the ability to skip movm and fmovm
+ instructions in the prologues. Still needs support for profile
+ (-p compiled) prologue sequences (FIXME).
+
+ * tm-68k.h: Change SKIP_PROLOGUE macro to use the new generic
+ m68k prologue skipping function by default.
+
+ * tm-altos.h, tm-isi.h: Continue to use the old definition of
+ SKIP_PROLOGUE.
+
+Mon Nov 18 15:12:45 1991 John Gilmore (gnu at cygnus.com)
+
+ * Makefile.in: Remove tdesc stuff, and extra blanks before colons.
+ * blockframe.c: Remove tdesc-related code. Default
+ FRAME_CHAIN_COMBINE.
+ * infrun.c: Remove tdesc-related code.
+ * m88k-tdep.c (frame_chain_combine, init_frame_pc): Remove copies
+ of defaultable things.
+ * tm-m88k.h: New file, common to all Moto 88k target configs.
+ Derived from tm-delta88.h.
+ * tm-delta88.h: Use it.
+ * xm-m88k.h: Common file for 88K hosts. Remove obsolete stuff.
+ * xm-delta88.h: Use it.
+ * tm-*.h: Remove FRAME_CHAIN_COMBINE macros, since all are
+ default.
+ * coffread.c: Remove tdesc stuff.
+ * tconfig/delta88, tconfig/m88k: Remove tdesc stuff.
+ * xconfig/m88k: Rename tm-88k.h to tm-m88k.h.
+
+Mon Nov 18 13:51:37 1991 Per Bothner (bothner at cygnus.com)
+
+ * source.c (open_source_file): If openp fails, try again
+ using just the base (non-directory) part of the filename.
+ This solves various annoying problems, such as when the
+ source was compiled with an absolute pathname - and the
+ source files have moved. Or if the source was compiled
+ using a relative pathname, it can be more convenient
+ to just specific the source directory to the dir command.
+
+Mon Nov 18 00:04:41 1991 Fred Fish (fnf at cygnus.com)
+
+ * cplus-dem.c (munge_function_name): Add missing third arg to
+ instance of call to do_type().
+
+ * dwarfread.c: Changes to match new dwarf.h. Remove
+ AT_deriv_list, AT_loclist, AT_incomplete, AT_const_data,
+ and AT_is_external.
+
+Sun Nov 17 16:20:53 1991 Michael Tiemann (tiemann at rtl.cygnus.com)
+
+ * symtab.h (struct type): Moved C++-specific fields into new type
+ `struct cplus_struct_type'. Now takes 10% less memory. Many
+ macros changed.
+ * symtab.c (init_type): Don't set fields belonging to
+ TYPE_CPLUS_SPECIFIC unless TYPE is TYPE_CODE_STRUCT.
+ * buildsym.c (read_type): Allocate TYPE_CPLUS_SPECIFIC for
+ TYPE_CODE_STRUCT.
+ (read_struct_type): Ditto. Also, add comments about how we can
+ deduce TYPE_VPTR_FIELDNO from inheritance info and fieldname info.
+ * coffread.c (decode_base_type): Allocate TYPE_CPLUS_SPECIFIC for
+ TYPE_CODE_STRUCT.
+ (read_struct_type): Ditto.
+ * dwarfread.c (struct_type): Ditto.
+
+ * symtab.c (read_range_type): Don't set TYPE_MAIN_VARIANT.
+ (lookup_pointer_type): Don't use or set TYPE_MAIN_VARIANT.
+ (lookup_reference_type): Ditto.
+
+ * cplus-dem.c: Many changes made to handle decoding of
+ ANSI-mangled names.
+ * symtab.c (gdb_mangle_name): Mangle/demangle ANSI-mangled names
+ as well.
+
+Fri Nov 15 17:57:59 1991 Stu Grossman (grossman at cygnus.com)
+
+ * mipsread.c (parse_partial_symbols): patch to keep DEC C
+ compiler from making gdb bomb out. Thanks to Ed Santiago!
+
+Thu Nov 14 19:27:30 1991 Fred Fish (fnf at cygnus.com)
+
+ * symfile.c: Add function compact_misc_function_vector() to
+ remove duplicate misc function vector entries. See comments
+ in source for why this is necessary/desirable.
+
+ * dwarfread.c: Add misc function type parameter to internal
+ record_misc_function(). Remove calls to init_misc_bunches()
+ and condense_misc_bunches(), these are now done in elfread.c.
+
+ * elfread.c: Add support for reading bfd canonical symbol tables
+ and generating misc function vector entries for global and
+ absolute symbols. Do calls to init_misc_bunches() and
+ condense_misc_bunches() where they will enclose all calls to
+ record_misc_function(), including those in dwarfread.c.
+
+Thu Nov 14 17:02:11 1991 Roland H. Pesch (pesch at cygnus.com)
+
+ * doc/Makefile.in: new targets gdb.me, gdb.ms, gdb.mm
+ (roffable documentation).
+ * doc/gdb.texinfo: embedded hints (as comments) for better
+ texi2roff conversion.
+
+Thu Nov 14 13:18:25 1991 John Gilmore (gnu at cygnus.com)
+
+ * m88k-tdep.c (examine_prologue): Deal with OR instructions
+ that shuffle parameters into other regs.
+ * symtab.c (decode_line_1): Fix bug introduced in Per's change
+ of Nov 12th.
+
+Wed Nov 13 19:51:11 1991 Steve Chamberlain (sac at cygnus.com)
+
+ * Makefile.in, xconfig/delta88 made it install a sysV manual page;
+ gdb.z into the right place.
+
+Wed Nov 13 16:45:13 1991 John Gilmore (gnu at cygnus.com)
+
+ Motorola 88000 port without tears, I mean without tdescs.
+
+ * m88k-tdep.c: Blow away all tdesc stuff.
+ Provide functions for all the frame-related macros in
+ tm-delta88.h. Adopt i960-style EXTRA_FRAME_INFO.
+ (examine_prologue, frame_find_saved_regs, skip_prologue): borrow
+ from i960-tdep.c and adapt to the function prologues on the 88k.
+ (read_next_frame_reg): Borrow from mips-tdep.c.
+ FIXME: frame_locals_address should go away.
+
+ * tm-delta88.h: Dump all the tdesc stuff.
+ Macros for all frame-related stuff call fns of same name.
+ Remove duplicated definitions. FP_REGNUM becomes same as
+ SP_REGNUM.
+
+ * xm-88k.h: Eliminate lots of library dependencies, now handled
+ in libiberty. Eliminate KDB nonsupport.
+
+ * doc/gdbint.texinfo: Add rudiments on frames. FIXME, add more.
+
+
+ * stack.c (frame_info): Mark frameless functions.
+ Print locals address (FIXME, remove if same).
+ * blockframe.c: Comment changes, FIXME after.
+ * coffread.c: Even without TDESC, need to zap "@" symbols.
+ Don't register for wierd format names; change the names in BFD.
+
+ * alloca.c, language.c, tdesc.c: Lint.
+ * tdesc.c, tdesc-lib: FIXME: remove these.
+
+Tue Nov 12 19:30:22 1991 John Gilmore (gnu at cygnus.com)
+
+ * Makefile.in: Add tdesc library support. Fixups to lint,
+ copying.c rules.
+
+Tue Nov 12 13:43:26 1991 Per Bothner (bothner at cygnus.com)
+
+ * symtab.c (decode_line_1): Remove spurious call to operator_chars.
+
+ Allow setting breakpoints on C++ destructors.
+ * valops.c (destructor_name_p): Don't check TYPE_HAS_DESTRUCTOR,
+ since it lies. Rely on callers to catch missing destructors.
+ * symtab.c (decode_line_1): For example (see above), here.
+ * buildsym.c, symtab.h: Remove TYPE_FLAGS_HAS{CON,DE}STRUCTOR
+ flags since they are no longer used.
+
+ Fixes to support C++ methods with functional parameters.
+ * c-exp.y (func_mod rule): Allow (and ignore) list of parameter
+ types in a function type.
+ * eval.c (parse_and_eval_type), value.h: New function,
+ parse_and_eval_type, is based on old code from check_stub_method.
+ But don't actually evaluate the cast, since that calls
+ value_cast(), whcih may fail. Just extract the type
+ from the parsed expression.
+ * values.c (check_stub_method): While looping through the
+ arguments, adjust depth *after* parameter has been handled.
+ Replace call and setup of parse_and_eval with new function
+ parse_and_eval_type.
+
+Tue Nov 12 09:40:07 1991 Fred Fish (fnf at cygnus.com)
+
+ * utils.c, rem-multi.shar: Remove fixed arg count version of
+ concat().
+
+ * altos-xdep.c, arm-xdep.c, coffread.c, command.c, convex-xdep.c,
+ core.c, dwarfread.c, gould-xdep.c, infcmd.c, language.c,
+ m88k-xdep.c, main.c, printcmd.c, pyr-xdep.c, source.c,
+ sun386-xdep.c, symm-xdep.c, umax-xdep.c, values.c, xcoffread.c:
+ Change all instances of use of fixed args concat() to variable
+ args concat() now located in libiberty.
+
+Tue Nov 12 07:23:46 1991 John Gilmore (gnu at cygnus.com)
+
+ * Makefile.in: Add xcoffread.c, xcoffexec.c.
+ * xcoffread.c: New file for handling AIX mangled-coff files.
+ * xconfig/rs6000, tconfig/rs6000: New files.
+ * buildsym.c: Add hooks for xcoffread.c.
+ * rs6000-pinsn.c, rs6000-tdep.c, rs6000-xdep.c, tm-rs6000.h,
+ xm-rs6000.h, rs6k-opcode.def, rs6k-opcode.h: New files.
+ * xcoffexec.c: New file for handling AIX shared libraries.
+
+Mon Nov 11 19:14:31 1991 Fred Fish (fnf at cygnus.com)
+
+ * core.c: Minor rewording of message to user containing name of
+ (and possibly arguments to) the program that generated a core
+ file.
+
+ * elfread.c: Remove the register_addr() stub now that it is no
+ longer needed.
+
+ * procfs.c: Move misplaced #endif for ATTACH_DETACH. Add new
+ fetch_core_registers() function for core file support.
+
+Sat Nov 9 13:37:57 1991 Fred Fish (fnf at cygnus.com)
+
+ * dwarfread.c (dwarf_psymtab_to_symtab): Remove leftover call
+ to do_cleanups() which resulted from a previous change.
+
+ * elfread.c: Re-enable compilation of register_addr() stub
+ whenever it is not supplied by coredep.c
+
+Sat Nov 9 00:40:32 1991 John Gilmore (gnu at cygnus.com)
+
+ Add tracking of object files (that contain symbols) to gdb.
+ This includes a "struct objfile" that owns symtabs and psymtabs
+ that were read in from that binary file.
+
+ * symfile.h: Add struct objfile. Add pointer to the objfile
+ into the struct sym_fns.
+ Replace global `symfile' and `symfile_mtime' with
+ `symfile_objfile'. Add global object_files chain.
+
+ * symfile.c: Move param.h above symtab.h.
+ (sort_misc_function_vector): Add.
+ (syms_from_objfile): Was syms_from_bfd.
+ (symfile_open): Now returns objfile.
+ (allocate_objfile): New.
+ (free_objfile): New, replacing free_all_.*symtabs.
+ (symfile_init): Takes objfile arg, puts it in sym_fns result.
+ (reread_symbols): Searches whole chain of objfiles.
+ (allocate_symtab): Takes objfile as new parameter, chains them.
+ Handle INIT_EXTRA_SYMTAB_INFO.
+ (free_all_psymtabs, free_all_symtabs): Move here from symmisc.c.
+
+ * dbxread.c: Make more errors into complaints.
+ (push_subfile, pop_subfile): Move to buildsym.c.
+ (dbx_symfile_read, dbx_symfile_init, fill_symbuf, read_dbx_symtab,
+ start_psymtab, psymtab_to_symtab_1, read_ofile_symtab,
+ dbx_psymtab_to_symtab, ): Use bfd ops, don't use file descriptor.
+ Pass objfile. Change callers.
+ (fill_symbuf, SWAP_SYMBOL): Take bfd as arg.
+ (read_dbx_symtab): Just wipe out new symbols, not all, on error.
+ (end_psymtab): Blow away psymtab if empty.
+ (process_symbol_pair): Swallow into read_ofile_symtab.
+ (process_one_symbol): Use push_context and pop_context.
+ (virtual_context): Delete #if 0'd obsolete stuff.
+
+ * buildsym.c (end_symtab): Pass objfile.
+ (dbx_lookup_type): Handle null typevector.
+ (dbx_alloc_type): Check file number, not sym number, for -1.
+ (find_symbol_in_list): Add for xcoffread.
+ (start_symtab): Default typevector is empty. Keep reusing same
+ context_stack.
+ (end_symtab): Take objfile argument and pass it to
+ allocate_symtab. Don't make a symtab if no blocks or symbols.
+ Handle empty typevector.
+ (push_context): New function for context stack nesting.
+ (read_type): Mark FIXME where we need to reintroduce type smashing.
+
+ * buildsym.h (pop_context): Macro, paired with push_context.
+ (subfile_stack): Move here from dbxread.c.
+
+ * coffread.c (end_symtab, read_coff_symtab): Take and use objfile arg.
+ (read_coff_symtab): Cleanup by freeing objfile, not all symtabs.
+
+ * mipsread.c (read_mips_symtab, parse_partial_symbols, parse_fdr,
+ new_psymtab, new_symtab): Take and use objfile arg.
+
+ * dwarfread.c (scan_compilation_units, start_psymtab,
+ process_dies, end_symtab, dwarf_build_psymtabs,
+ read_lexical_block_scope, read_func_scope, read_file_scope): Take
+ and use objfile argument.
+ (psymtab_to_symtab_1, read_ofile_symtab): Don't take or use file
+ descriptor. Use BFD internal functions instead.
+ (end_symtab): Call global allocate_symtab.
+
+ * elfread.c, target.c: Minor changes to accommodate objfiles.
+ * symtab.h: partial_symbol_table has no symfile_name member now.
+ (fn_fieldlists voffset): avoid non-int bitfield.
+ (struct symtab): Add objfile * and objfile_chain * of symtabs.
+ (struct partial_symtab): Add objfile * and objfile_chain * of
+ psymtabs. Remove symfile_name.
+
+ * symmisc.c: Lose free_all_symtabs, free_all_psymtabs.
+ (printsyms_command): Rename from print_symtabs. Add selective
+ listing if 2nd argument given. Print objfile info.
+ (printpsyms_command): Rename from print_partial_symtabs. Ditto all.
+ (printobjfiles_command): New; prints objfiles lists, and checks
+ for consistency of symtab, psymtab, and objfile lists.
+
+ * symfile.h, symfile.c, symtab.h: Lint
+
+Fri Nov 8 23:38:48 1991 John Gilmore (gnu at cygnus.com)
+
+ * command.c: Include param.h.
+ * defs.h (warning_setup, warning): Declare.
+ * expprint.c (print_subexp, UNOP_MEMVAL case): Lint.
+ * inflow.c (new_tty): Use USE_O_NOCTTY #define.
+ * language.c, printcmd.c (print_scalar_formatted), signame.c,
+ stack.c: lint.
+
+Thu Nov 7 18:26:15 1991 Steve Chamberlain (sac at rtl.cygnus.com)
+
+ * Makefile.in: link with libiberty after libreadline, since
+ readline might want something in libiberty.
+ * m88k-xdep.c: Fixed the register offsets in the ptrace_user
+ struct for BCS 88k machines.
+ * xm-m88k.h: don't define USIZE if already defined.
+ * configure.in: Added delta88 target.
+
+Thu Nov 7 04:51:19 1991 John Gilmore (gnu at cygnus.com)
+
+ * am29k-pinsn.c, am29k-opcode.h: Fix decoding of mtacc, dmac, fmac.
+
+ * tm-*.h: Remove READ_DBX_FORMAT, COFF_FORMAT, and
+ READ_MIPS_FORMAT, which have been unused since BFD. Still
+ remaining is COFF_NO_LONG_FILE_NAMES.
+ * tm-sun3.h, tm-altos.h: Remove detritus accidentally left from
+ function calling code moved to m68k-tdep.c.
+
+Wed Nov 6 17:21:59 1991 John Gilmore (gnu at cygnus.com)
+
+ * coffread.c: Eliminate c_nsyms in favor of c_naux.
+ Complain if no auxents on .bf and .ef FCN symbols, and assume
+ lots of line numbers.
+ (init_linenos, enter_linenos): Use a sentinel at the end of the
+ read-in linenos, to make for a fast, safe loop-end test.
+
+Wed Nov 6 02:54:08 1991 Steve Chamberlain (sac at cygnus.com)
+
+ * coffread.c (read_coff_symtab): coffread used to rely on the
+ x_sym.x_misc.x_lnsz.x_lnno field giving the # of linnos in a
+ function. Two of the formats I'm using (29k and 88k) don't seem to
+ set it. Ths patch to fcn_last_line and (enter_linenos) is an
+ attempt to use the actual size of the linno table in the file to set
+ the number of linenos to process.
+
+Tue Nov 5 22:47:46 1991 Steve Chamberlain (sac at cygnus.com)
+
+ * Makefile.in: put a - infront of the mv y.tab.c c-exp.tab.c and
+ mv y.tab.c m2-exp.tab.c, so that if bison is used, and the files
+ are created in place, so the mv fails, then the make continues.
+
+Tue Nov 5 16:47:47 1991 Per Bothner (bothner at cygnus.com)
+
+ Add C++ as a separate language.
+ * defs.h (enum language): Add language_cplus.
+ * dwarfread.c (end_symtab): Support language_cplus.
+ * c-exp.y: Add new struct language_defn cplus_language_defn.
+ Don't set c to be the default language (see main.c).
+ * c-exp.y (yylex): Only look for field of this if
+ language is C++. (First difference from C!)
+ * language.c: Add case branches for C++ (currently, all
+ the same as C). Also, add c++ to "usage" note for "set lang".
+ * valprint.c (typedef_print). Add case branches for C++.
+ * main.c (main): New way to set initial language: Look at
+ file extension of psymtab containing main(). (Same as we
+ do for symtabs, but avoid loading the symtab yet.)
+ * symtab.c: New routine find_main_psymtab(), used by main()
+ to set initial language.
+ * symfile.c (allocate_symtab): Move code for mapping file
+ extensions-> languages to new deduce_language_from_filename().
+
+ Fix a C++ problem when looking for methods in super-classes.
+ There was confusion between base and derived types.
+ * valops.c (value_fn_field): Change function interface.
+ * values.c: Use new value_fn_field interface.
+
+Mon Nov 4 10:49:33 1991 Per Bothner (bothner at cygnus.com)
+
+ * infrun.c: Fixed typo in comment.
+ * utils.c: All the v*fprintf emulation is now in libiberty,
+ so we can get rid of some junk.
+ * xm-sun3os4.h, xm-sun4os4.h, xconfig/decstation, xconfig/i386sco,
+ xconfig/sun3os4, xconfig/sun4os4: Don`t need HAVE_STRSTR any more.
+ * m68k-pinsn.c (print_insn_arg): Support BB/BW/BL
+ type operands, as used by branch instructions.
+ * gmalloc.c: Fix prototype of memcpy.
+ * elfread.c: Comment out register_addr, since it conflicts
+ with the one in coredep.c.
+ * buildsym.h: Remove extern declarations of two functions
+ that are really static in buildsym.c.
+ * tm-mips.h: Add symbolic names for more registers.
+ * mips-xdep.c (store_inferior_registers): Use new register names.
+ * xm-mips.h: Simplify REGISTER_U_ADDR, since it is now
+ only used for core files, not ptrace. Therefore,
+ the KERNEL_U_ADDR hack is no longer needed.
+ The mapping to ptrace number is now in in mips-xdep.c.
+ * mips-xdep.c: Define REGISTER_PTRACE_ADDR (using the
+ mapping from the old REGISTER_U_ADDR), and use it
+ in {fetch,store}_inferior_registers.
+ * mipsread.c: Rename #include ecoff.h to new name coff-mips.h.
+ * mips-tdep.c (mips_push_dummy_frame, mips_pop_frame):
+ Save/restore FP regs correctly (?).
+ * dbxread.c: Remove duplicate define_symbol and type_synonym_name
+ (these had been previously moved to buildsym.c).
+ Hence, define_symbol becomes extern instead of static.
+ * buildsym.c (read_struct_type): Comment out bogus handling
+ of C++ operator methods. Minor hacking of reading of class
+ contexts. Make define_symbol non-static, so dbxread.c can call it.
+
+Fri Nov 1 11:05:47 1991 John Gilmore (gnu at cygnus.com)
+
+ * mipsread.c (read_mips_symtab, read_the_mips_symtab): Use real
+ filename with error messages.
+ * stack.c (frame_select_command): Rename to select_frame_command
+ to avoid "fr" and "fra" having nonunique completions.
+ * symfile.c (sort_symtab_syms): Ignore sort of zero symtab *.
+ (symfile_init): Print file format name when unable to handle it.
+ (free_named_symtabs): Use BLOCKVECTOR rather than obsolete BLOCKLIST.
+ * symmisc.c (free_symtab): Only free linetable if nonzero.
+ * symtab.h: Remove obsolete BLOCKLIST macros.
+
+Thu Oct 31 18:12:43 1991 Stu Grossman (grossman at cygnus.com)
+
+ * infrun.c (wait_for_inferior): another stepi/nexti fix. Ensure
+ that stop_step is 1 at bottom of main loop. I don't know why this
+ needs to be done, but it helps me sleep better at night.
+
+Sun Oct 27 18:18:39 1991 Stu Grossman (grossman at cygnus.com)
+
+ * main.c (initialize_history): Read history after reading all
+ init files.
+
+Sun Oct 27 14:09:25 1991 John Gilmore (gnu at cygnus.com)
+
+ * buildsym.c: Break out initial malloc sizes.
+ (record_line): Record directly in a subfile. Alloc on demand.
+ (compare_line_numbers): Add from xcoffread.c.
+ (end_symtab): New params say whether to sort pendings and
+ linetable. Patch block stabs if defined. Shrink linetable before
+ allocating the symtab.
+ * buildsym.h: Delete line_vector* and prev_line_number. Add
+ global_stabs and file_stabs for xcoffread.
+ * dbxread.c (start_subfile): Move to buildsym. Change above calls.
+ * symtab.h: LINETABLE(symtab) can now be null. Zap LINELIST.
+ * symmisc.c, symtab.c: Cope with null LINETABLEs.
+
+ * blockframe.c: Pass fromleaf to INIT_EXTRA_FRAME_INFO.
+ * tm-29k.h, tm-88k.h, tm-i960.h, tm-irix3.h, tm-mips.h, tm-pyr.h,
+ tm-sparc.h: Accept fromleaf parameter.
+ * c-exp.y (yyerror): Pass error message if given.
+ * configure.in: Add rs6000 host and target.
+ * inflow.c (new_tty): O_NOCTTY kludge for RS/6000.
+ * symfile.h (entry_point): Add.
+
+Sat Oct 26 00:16:32 1991 John Gilmore (gnu at cygus.com)
+
+ * buildsym.c: New file. Breaks out symbol-table-building routines
+ from dbxread.c, so they can be shared with xcoffread.c.
+ * buildsym.h: New file. Declarations for buildsym.c users.
+ * dbxread.c: Remove large chunks into buildsym.c.
+ * Makefile.in: Add buildsym.c and buildsym.h.
+
+ * symfile.c (syms_from_bfd): New routine.
+ (add_symbol_file): Call it to do the real work.
+ (syms_from_bfd): Initialize entry_point before calling symfile_init.
+ * symtab.h, symfile.c, coffread.c, mipsread.c, dwarfread.c:
+ Avoid declaring or setting entry_point (symfile.h & symfile.c cope).
+
+Fri Oct 25 10:58:16 1991 Mark Eichin (eichin at cygnus.com)
+
+ * cplus-dem.c (cplus-demangle): added support for templates, static
+ data, and the new (correct) mangling for destructors.
+
+ * dwarfread.c: (dwarfwarn): created a varargs version of
+ dwarfwarn, for non __STDC__ compilers.
+
+ * c-exp.y: (yylex): added match for "template" token.
+ (typebase): added TEMPLATE name '<' type '>' clause, for explicit
+ specification of template types.
+
+ * symtab.c: (lookup_template_type): new function for finding
+ templates in symbol table.
+ (type_name_no_tag): changed to explicitly check for s/u/e at the
+ beginning of the symbol - if it is a template, none of these will
+ be there (but the name will still contain spaces.)
+
+Fri Oct 25 18:59:32 1991 Per Bothner (bothner at cygnus.com)
+
+ Various fixes to improve g++ debugging.
+ * symtab.h: Add is_const and is_volatile flags for each method.
+ These are bit fields - take their space from voffset,
+ which shrinks to 30 bits. Since voffset is now a bitfield,
+ make it unsigned for portability. This changes its interpretation
+ slightly: Static methods now have voffset 1 instead of -1,
+ and virtual offsets start at 2, not 1.
+ * symtab.c: Renamed gdb_mangle_typename to gdb_mangle_name,
+ since it now returns an entire magled method name, not just
+ the type part. This avoids some duplication.
+ It also allows us to correctly mangle const and volatile
+ methods (using the new is_const and is_volatile bit fields
+ mentioned above).
+ * valprint.c (type_print_base), values.c (check_stub_method):
+ Simplify by using new gdb_mangle_name.
+ * values.c (value_headof): Fix to correctly handle single
+ inheritance (actually two fixes, either of which suffices).
+ * dbxread.c (read_struct_type): Handle const and volatile
+ method specifiers.
+ * dbxread.c (read_struct_type): Yet one more place where
+ we must handle '\\' continuations.
+ * valprint.c (vtbl_ptr_name): Add final '\0'.
+
+Fri Oct 25 16:06:38 1991 Stu Grossman (grossman at cygnus.com)
+
+ * tm-sparc.h, tm-68k.h (EXTRACT_RETURN_VALUE): fix output of
+ short return values for sparc and 68k. Patch from Paul Eggert.
+
+ * coffread.c, coredep.c, i386-xdep.c: install patches for
+ SysV/386 3.2 from Mauro DePalma.
+
+Fri Oct 25 02:02:13 1991 John Gilmore (gnu at cygnus.com)
+
+ * core.c (core_file_info), exec.c (exec_file_info): Print file
+ type. Use printf_filtered.
+
+ * valops.c (value_fetch_lazy): Avoid 0-length fetches.
+
+Thu Oct 24 23:06:40 1991 Fred Fish (fnf at cygnus.com)
+
+ * dwarfread.c: Add casts to remove compiler warnings.
+
+ * tm-3b1.h, tm-68k.h, tm-altos.h, tm-amix.h, tm-hp300bsd.h,
+ tm-hp300hpux.h, tm-isi.h, tm-news.h, tm-pn.h, tm-sun2.h,
+ tm-sun3.h: Remove locally duplicated code for calling functions
+ in the inferior. The only differences were in the specific trap
+ vectors used and whether or not an fpu was present. These are
+ now handled by appropriate definitions of BPT_VECTOR and
+ HAVE_68881 respectively. Other minor obvious cleanups.
+
+ * valops.c: Correct a minor misspelling.
+
+ * utils.c: Remove local BSD/USG hacks that are now in libiberty.
+
+ * dwarfread.c: Remove prototype for dwarfwarn. Does not work
+ with <varargs.h>.
+
+Thu Oct 24 09:33:44 1991 John Gilmore (gnu at cygnus.com)
+
+ * stack.c (frame_command): Always print. Use new
+ frame_select_command to select a frame without printing.
+
+ * dwarfread.c: Use <varargs.h>, since <stdarg.h> is not portable.
+
+Thu Oct 24 01:32:51 1991 Fred Fish (fnf at cygnus.com)
+
+ * dwarfread.c: New file for DWARF debugging format support.
+
+ * elfread.c: New file for ELF object file format support.
+
+ * procfs.c: New file for SVR4 /proc (process file system) support.
+
+ * tm-amix.h, xm-amix.h, tconfig/amix, xconfig/amix: New files for
+ Amiga UNIX support.
+
+ * xm-svr4.h, tm-svr4.h: New files for SVR4 support.
+
+ * xm-m68k.h: New file for host machines with m68k cpu.
+
+ * Makefile.in: Add elfread.c and dwarfread.c to SFILES_MAINDIR.
+ Add elfread.o and dwarfread.o to OBS.
+
+ * symfile.h: Add "elf" to list of supported formats in comment.
+
+ * c-exp.y, defs.h, symtab.h, valprint.c: Add three new builtin
+ types to gdb, builtin_type_long_double, builtin_type_complex, and
+ builtin_type_double_complex. Add and use new TARGET_SHORT_BIT,
+ TARGET_INT_BIT, TARGET_LONG_BIT, TARGET_FLOAT_BIT,
+ TARGET_DOUBLE_BIT, TARGET_LONG_DOUBLE_BIT, TARGET_COMPLEX_BIT, and
+ TARGET_DOUBLE_COMPLEX_BIT, as the sizes in bits of the indicated
+ types on the target machine (ala the existing TARGET_LONG_LONG_BIT).
+
+ * infrun.c: When using SVR4 /proc interface instead of ptrace(),
+ call proc_set_exec_trap() to setup child to stop at first instruction.
+
+ * inftarg.c: When using SVR4 /proc interface, call proc_wait()
+ rather than wait().
+
+ * m68k-tdep.c: Add new routines supply_gregset(), fill_gregset(),
+ supply_fpregset(), and fill_fpregset(), which are machine
+ dependent support routines for SVR4 /proc interface.
+
+ * utils.c: Add warning_setup() and warning(). Warning() behaves
+ the same as error() except that it returns normally rather than
+ jumping back to command level. Modules that don't want to call
+ warning() for some reason, but want to produce their own warnings,
+ can call warning_setup() to ensure compatibility with the way
+ warning() and error() deal with the terminal.
+
+ * symtab.c: Make internal errors produce more useful messages.
+
+ * tm-68k.h: Move code that is duplicated in almost every single
+ m68k based machine's configuration files to this common file.
+ Duplications in the configuration files still need to be removed
+ (FIXME).
+
+ * infrun.c (child_create_inferior): System V versions must call
+ setpgrp() with no arguments, to comply with prototyping typically
+ in <unistd.h>.
+
+ * munch: Add support for SVR4 style nm output.
+
+ * dbxread.c, mipsread.c symmisc.c, symtab.c: Remove the object
+ file specific fields from the partial symbol table structure and
+ replace them with a pointer to private data for each different
+ flavor of object file reader to initialize appropriately.
+
+Wed Oct 23 09:38:20 1991 John Gilmore (gnu at cygnus.com)
+
+ * xconfig/sun[34]os4: Add note about strstr botch on sunos4.0.3c
+ and previous.
+
+ * mipsread.c (fixup_undef_type): New function. If a struct /
+ union / enum is defined in a header file but nowhere else used,
+ (by typedefing, pointer referencing or declaration) the mipsread code
+ builds the complete tree for the structure but leaves its code as
+ TYPE_CODE_UNDEF as it doesn't know what kind of aggregate it is.
+ Guess its type based on the details of the members.
+
+Tue Oct 22 18:04:32 1991 Stu Grossman (grossman at cygnus.com)
+
+ * infrun.c (wait_for_inferior): Check return value from
+ find_pc_line.
+
+Mon Oct 21 17:47:03 1991 Stu Grossman (grossman at cygnus.com)
+
+ * infrun.c (wait_for_inferior): fix stepi/nexti that was broken
+ by my last edit to this routine.
+
+Mon Oct 21 14:27:43 1991 John Gilmore (gnu at cygnus.com)
+
+ * tm-sun3.h (FIX_CALL_DUMMY): problem with cross debugging.
+ FIX_CALL_DUMMY does unaligned accesses and/or forgets to byte swap
+ the values before putting them into the dummy code. (From Peter
+ Schauer)
+
+Mon Oct 21 10:04:39 1991 Steve Chamberlain (steve at rtl.cygnus.com)
+
+ * configure.in: added ebmon target.
+
+Wed Oct 16 22:49:58 1991 John Gilmore (gnu at cygnus.com)
+
+ GDB-4.2 release!
+
+ * Makefile.in: Roll VERSION to 4.2.
+ * README, TODO, WHATS.NEW: Update.
+
+ * core.c (core_open): Improve error message for bad file.
+ Pass .reg virtual memory address to fetch_core_registers to help
+ it find the registers in the core-file header.
+ * coredep.c (fetch_core_registers): Take new argument, use it,
+ and pass it to register_addr to locate the block of registers.
+ * xm-mips.h: Update KERNEL_U_ADDR for new scheme. Cleanup a bit.
+
+ * dbxread.c (read_dbx_symtab, process_one_symbol): Handle
+ Sequent N_FN_SEQ like everybody else's N_FN.
+
+ * main.c: Circumvent SCO cc bug with #if !!defined(USG).
+ * tm-i386v.h: #endif guck.
+ * xconfig/i386*: Remove -Dgetpagesize()=4096 kludge.
+ * xconfig/i386sco: Add HAVE_STRSTR to avoid ANSI bdeath.
+ * xconfig/tahoe: Add REGEX, which seems to be missing.
+
+ * coredep.c: Add <sys/types.h> for SCOnix.
+ * dbxread.c (read_dbx_symntab): Avoid coredump on malformed file.
+ * printcmd.c (print_formatted): Flush output before disassembly.
+
+Tue Oct 15 20:12:32 1991 Roland H. Pesch (pesch at fowanton.cygnus.com)
+
+ * doc/refcard.tex (sec "Working Files"): consistent metavars and
+ other improvements, due to comments by François Pinard
+ (pinard@iro.umontreal.ca)
+
+ * doc/gdb.texinfo (appendix "Installing GDB"): changes in
+ configure, and improvenets related to Pinard's refcard comments
+
+Tue Oct 15 08:45:12 1991 John Gilmore (gnu at cygnus.com)
+
+ Changes from Fred Fish:
+ * tm-68k.h (FPI_REGNUM): Add.
+ * infrun.c (child_create_inferior): flush stdout and stderr
+ before forking.
+ * configure.in: Handle amigados, amix hosts and targets.
+ * inflow.c: Handle TIOCGLTC_BROKEN for Amiga.
+
+ From Andreas Schwab:
+ * values.c (show_convenience): Use printf_filtered.
+ * main.c (define_command): Check result of lookup_command for
+ exact match.
+ (echo_command): Use printf_filtered, and force output out.
+
+ * dbxread.c (read_enum_type): Avoid Modula-2 kludge that breaks C
+ programs.
+ * i387-tdep.c (double_to_i387): Fix typo for double_to_ieee_extended.
+ * utils.c (_initialize_utils): If !ISATTY, don't paginate.
+ * configure.in, tconfig/decstation, xconfig/decstation: Rename
+ dec3100 to decstation.
+
+Mon Oct 14 13:37:50 1991 Roland H. Pesch (pesch at cygnus.com)
+
+ * doc/gdb.texinfo: Catch up to changes recorded here in ChangeLog
+ (nodes Continuing and Stepping; Memory; Targets) clarifications
+ due to Larry Breed
+
+Fri Oct 11 23:27:06 1991 John Gilmore (gnu at cygnus.com)
+
+ * tm-{irix3,mips,nindy960,pn,symmetry,vx960}.h: Move
+ REGISTER_U_ADDR to corresponding xm- file. Sugg. by Peter Schauer.
+
+ * symmisc.c (print_partial_symtabs): Add printpsyms debug cmd.
+
+ * m68k-tdep.c (m68k_push_dummy_frame, m68k_pop_frame): Add
+ generic routines for calling inferior functions.
+
+ * blockframe.c (inside_main_scope, inside_entry_scope): New.
+
+ * copying.awk: Filter formfeeds out of copying & warrantee.
+ Make them available as `show copying' and `show warrantee' also.
+ * main.c (print_gnu_advertisement): Advt `show' commands.
+
+Thu Oct 10 17:25:47 1991 John Gilmore (gnu at cygnus.com)
+
+ * mach386-xdep.c: Even when cross-compiling, leave in the
+ core-file reading code.
+ * core.c (get_core_registers): Avoid coredump if no .reg section.
+
+Wed Oct 9 17:03:34 1991 John Gilmore (gnu at cygnus.com)
+
+ * mipsread.c, coffread.c: initialise TYPE_VPTR_FIELDNO to -1.
+ This avoids coredumps under `set print object on' in value_headof
+ (called erroneously by value_from_vtable_info) for `p &struct'
+ or `p *struct'. From Peter Schauer.
+
+Mon Oct 7 00:06:52 1991 John Gilmore (gnu at cygnus.com)
+
+ * Makefile.in: Roll version to 4.1.2.
+ * dbxread.c: Use aout64.h, not a.out.gnu.h. Get external symbol entry
+ size from BFD (but, FIXME, we don't yet read external nlists's and
+ convert them to internal nlists's before handling them -- we still
+ assume they have the same size and alignment.) Use SET_NAMESTRING
+ everywhere useful.
+ * exec.c (exec_file_command): Move dead coff-encapsulation code
+ to BFD.
+ * m88k-tdep.c, m88k-xdep.c: Remove encap test and #inc <a.out.h>.
+
+Fri Oct 4 22:30:06 1991 John Gilmore (gnu at cygnus.com)
+
+ * configure.in, tm-i386v.h, xm-i386v.h: Intel 386 Mach host port.
+ * xm-i386mach.h, mach386-xdep.c, xconfig/i386mach: New files.
+
+Fri Oct 4 17:04:31 1991 Per Bothner (bothner at cygnus.com)
+
+ More patches from Peter Schauer <pes@regent.e-technik.tu-muenchen.de>:
+ * mips-xdep.c (store_inferior_registers): Don't try to
+ write the (pseudo) FP.
+ * mipsread.c (parse_partial_symbols): Improved algorithm for
+ setting pst->texthigh.
+
+Fri Oct 4 16:47:32 1991 Roland H. Pesch (pesch at cygnus.com)
+
+ * doc/Makefile: make TEXINPUTS include . everywhere
+
+Fri Oct 4 00:35:56 1991 John Gilmore (gnu at cygnus.com)
+
+ * coffread.c, dbxread.c, symfile.c, symmisc.c, symtab.h: Remove
+ vestiges of typevectors, which were for symsegs and are no longer
+ used. (From a question by Eliot Dresselhaus
+ <dresselh@RFT30.nas.nasa.gov>).
+
+Thu Oct 3 09:33:26 1991 John Gilmore (gnu at cygnus.com)
+
+ * dbxread.c, coffread.c: static-ize functions that were
+ gratuitiously external. (From Fred Fish.)
+
+ * c-exp.y: sym->class to SYMBOL_CLASS (sym).
+
+ * dbxread.c (dbx_lookup_type): Keep doubling size of typevector
+ until it is large enough.
+
+ * dbxread.c (read_type): Handle error case slightly better.
+ Make complaint message not C++-specific.
+
+Wed Oct 2 17:21:07 1991 Stu Grossman (grossman at cygnus.com)
+
+ * infrun.c (wait_for_inferior): Fix step/next so that you only
+ stop at the beginning of a new line. This fixes various problems
+ with for loops, nested if-else's and switch statements.
+
+Tue Oct 1 06:33:55 1991 John Gilmore (gnu at cygnus.com)
+
+ * symtab.c (lookup_symtab_1, lookup_symbol): "fatal" errors
+ between symtabs and psymtabs become ordinary error()s.
+
+ * dbxread.c (read_dbx_symtab): Relocate end_of_text_addr
+ properly, making "end pc" correct in shared lib psymtabs.
+ (From Guy Harris <guy@auspex.com>.)
+
+Mon Sep 30 13:15:31 1991 John Gilmore (gnu at cygnus.com)
+
+ * dbxread.c: Enable, but soften, const_vol_complaint.
+ (read_dbx_symtab): N_STSYM and N_LCSYM define static vars.
+ Ditto Gould N_NBSTS and N_NBLCS. Also, all types in the psymtab
+ should be file-scope, not global.
+ (read_struct_type): Remove ancient multiple-inheritance warning.
+ (read_range_type): Check base type, complain & patch if undefined.
+ * stack.c (frame_info): Demangle the function name in `info stack'.
+ (From Peter Schauer)
+
+Sat Sep 28 10:02:33 1991 John Gilmore (gnu at cygnus.com)
+
+ * eval.c (evaluate_subexp_for_address): Don't use
+ TYPE_POINTER_TYPE directly (it might be zero if this type has
+ never had a pointer created before); use lookup_pointer_type.
+ * symtab.c (lookup_method_type): Arguments were swapped in all
+ callers, so fix it here. I'm amazed this worked at all!
+
+Fri Sep 27 18:09:31 1991 John Gilmore (gnu at cygnus.com)
+
+ * c-exp.y, m2-exp.y: Define more yysymbols that happen to be
+ "bss" rather than "data" symbols, but which still conflict.
+ * m2-exp.y: Lint.
+
+ * coffread.c (coff_symfile_read): Use xmalloc, not malloc.
+ * core.c (core_files_info): Shorten output.
+ * exec.c (exec_files_info): Ditto.
+ (build_section_table): Ignore zero-length sections.
+ * language.c, printcmd.c: Lint.
+ * language.h (get_frame_language): Declare.
+ * saber.suppress: update.
+ * stack.c (find_relative_frame): Remove complex code that was
+ #if 0'd, stick with simple code. Lint.
+ * saber.suppress: Update a bit.
+ * symfile.c (add_symbol_file_command): Add "?" to question.
+ * utils.c (parse_escape): Avoid \a due to bdead compilers.
+ * value.h: Declare typedef_print.
+
+ * valprint.c (val_print, type_print_base): TYPE_CODE_RANGE less
+ kludgey.
+
+ * nindy-tdep.c (nindy_frame_chain_valid): Use lookup_misc_func.
+ (Reported by Mark Peek <mark@imagen.com>.)
+
+ * solib.c (solib_map_sections): Relocate all sections, even
+ though only the text section's size is tracked. Mark ld_text
+ for eventual elimination as we generalize to N sections.
+
+ * infrun.c (wait_for_inferior): Don't check if the PC is in a
+ call_dummy if we were stopped by a random signal that is being
+ passed to the program. This produced wierd results when calling
+ functions in the inferior and signals (e.g. SIGALRM) were in use.
+
+Tue Sep 24 18:05:30 1991 John Gilmore (gnu at cygnus.com)
+
+ * infrun.c (IN_SIGTRAMP): Not parenthesized properly.
+ Bugfix from Paul Eggert <eggert@twinsun.com>.
+ * tm-ultra3.h (IN_SIGTRAMP): Ditto.
+ * valprint.c (print_floating): Print 9 digits for IEEE floats.
+ From Paul Eggert.
+
+Mon Sep 23 15:50:07 1991 John Gilmore (gnu at cygnus.com)
+
+ * Makefile.in: Roll VERSION to 4.1.1.
+ * source.c (line_info): Peter Schauer fixes a bug I introduced in
+ hex conversion.
+
+Fri Sep 20 16:10:52 1991 John Gilmore (gnu at cygnus.com)
+
+ GDB-4.1 release!
+
+ * Makefile.in (VERSION): Set to 4.1.
+ * language.c (set_language_command): Print useful help message,
+ and restore the language string after giving help.
+ * valprint.c (typedef_print): Print typedef in C or M2.
+ * symtab.c (list_symbols): Use it.
+ * main.c (main): Avoid any output before (gdb) prompt when -q.
+ * language.c (set_language_command): Handle errors by restoring
+ the language string to its current state (fix from A. Beers).
+ * doc/gdbint.texinfo: Roll in information from README. Rearrange
+ "how to install" and "how to print the doc" stuff so it drops
+ easier into README.
+ * configure.in: Rename rtpc CPU to romp to match config.sub.
+ * README, WHATS.NEW, TODO: Update for gdb-4.1.
+
+Fri Sep 20 17:39:14 1991 Roland H. Pesch (pesch at cygnus.com)
+
+ * doc/gdb.texinfo: Updates from ChangeLog. set/show write,
+ autoloading shared libs, copyright etc on GDB startup, clean up $_
+ and $__ index refs, set/show listsize and related updates to list
+ cmd. New host/target configs.
+
+Fri Sep 20 15:46:00 1991 Roland H. Pesch (pesch at cygnus.com)
+
+ * doc/Makefile: generate aux version-no file doc/gdbVN.m4
+ from main Makefile.in version definition
+ doc/gdb.texinfo: use version recorded in doc/gdbVN.m4 for current
+ GDB version no refs
+ Makefile.in (setup-to-dist): generate doc/gdbVN.m4
+
+ * doc/gdb.texinfo: merge new language-switching and lang-specific
+ doc by Andrew Beers
+
+Fri Sep 20 15:00:57 1991 Per Bothner (bothner at cygnus.com)
+
+ * mcheck.c: Add __ONEFILE kludge to allow compilation by non-ANSI
+ compilers (which may lack stddef.h).
+
+Fri Sep 20 13:29:42 1991 John Gilmore (gnu at cygnus.com)
+
+ * dbxread.c (read_dbx_symtab, process_one_symbol): N_FN and
+ N_WARNING are the same except for the N_EXT bit, so just use their
+ values alone, rather than OR-ing them with N_EXT.
+
+Fri Sep 20 12:27:55 1991 Stu Grossman (grossman at cygnus.com)
+
+ * mipsread.c (parse_lines): Deal with negative extended line
+ offsets correctly.
+
+ * c-exp.y, m2-exp.y: #define yyerrflag and yynerrs to avoid
+ global symbol conflicts.
+
+Fri Sep 20 02:28:15 1991 John Gilmore (gnu at cygnus.com)
+
+ * .gdbinit: Move 'set complaints' to top, so it runs even in
+ case we aren't debugging GDB.
+ * language.c (_initialize_language): Fix type check and range
+ check documentation strings.
+ * utils.c (!HAVE_VPRINTF): Define vfprintf as a function, so
+ language.c can use it. (Though language.c should really not be
+ handling warnings/errors the way it does, FIXME.)
+ * symtab.c (lookup_primitive_type): const lint.
+
+ Bugfix from Peter Schauer:
+ * source.c (lines_to_list): Make signed, to avoid comparison
+ going unsigned and complaining that -3 is too high for 21 lines.
+ * stack.c (lines_to_list): Ditto.
+
+Thu Sep 19 23:33:41 1991 John Gilmore (gnu at cygnus.com)
+
+ * Makefile.in (HFILES): Add minimon.h.
+ (VERSION): Roll version number to 4.0.95.
+ (gdb.tar.Z, make-proto-gdb.dir, setup-to-dist, gdb-XXX.tar.Z):
+ New rules for building distributions. Normal distribution
+ is built by doing `make -f Makefile.in gdb.tar.Z' in the directory
+ one level up from here; it calls make-proto-gdb.dir to build a
+ directory `proto-gdb' which is an image of the release. The old
+ `gdb.tar.Z' rule still works too.
+ * config.sub, configure: Roll in latest from ..
+
+Thu Sep 19 17:41:24 1991 Roland H. Pesch (pesch at cygnus.com)
+
+ * doc/gdbint.texinfo: Reorder contents; reorganize new-host,
+ new-target, and new-config chapters; fix minor typos; come closer
+ to usual GNU markup conventions for @file @samp @code @var.
+
+Thu Sep 19 17:04:12 1991 Per Bothner (bothner at cygnus.com)
+
+ Patches from Peter Schauer <pes@regent.e-technik.tu-muenchen.de>:
+ * mipsread.c (parse_partial_symbols): Enter the name of all
+ structs/unions... into the psymtab so we can access them if the
+ symtab is not read in.
+ * mips-tdep.c: Remove some unneeded #includes.
+ * xconfig/dec3100: Add HAVE_STRSTR.
+
+Thu Sep 19 15:14:23 1991 John Gilmore (gnu at cygnus.com)
+
+ * Makefile.in: Circumvent Sun Make bug on *-exp.tab.o.
+ * c-exp.y, m2-exp.y: Lint.
+ * m2-exp.y: Avoid using yytname[] which is a Bison-ism.
+ * valprint.c (val_print_fields): Check for stub type.
+ * mipsread.c (_initialize_mipsread): Avoid using
+ builtin_type_void at initialize time.
+ (mipscoff_symfile_read): use it now.
+
+Wed Sep 18 15:55:51 1991 John Gilmore (gnu at cygnus.com)
+
+ Merge multiple-language support, and partial Modula-2 support,
+ from Andrew Beers <beers@cs.buffalo.edu>.
+
+ * i387-tdep.c: New file, consolidates most 80387 support,
+ and eliminates host dependency on double<->extended conversions.
+ * i386-xdep.c, symm-xdep.c: Remove most 387 support.
+ * xconfig/i386{sco,v,v-g,v32,v32-g}: Now need i387-tdep.o.
+
+ * symfile.c (allocate_symtab): New fn, consolidates the work
+ of allocating and initializing a new struct symtab. Set the
+ language of the symtab based on its filename extension.
+ * symfile.h: Declare it.
+ * mipsread.c (new_symtab): Use it. Minor formatting changes.
+ * dbxread.c (end_symtab): Use it.
+
+ * mipsread.c (parse_symbol, case stParam and stProc): Add #if 0'd
+ code for saving types of parameters with each function definition.
+ * dbxread.c (define_symbol, function and parameter cases): Ditto.
+ (read_dbx_symtab, case N_DEFD): Ignore.
+ (read_enum_type): Recognize FALSE/TRUE enum as Modula-2 BOOLEAN.
+ (read_range_type): Rename MAX_OF_TYPE to MAX_OF_C_TYPE, etc.
+ #if 0 out its uses, though, since they set a dead value.
+ * coffread.c (end_symtab): Use allocate_symtab.
+ (process_coff_symbol): #if 0'd for functions and params as above.
+ (read_enum_type): Recognize Modula-2 BOOLEAN.
+ * symtab.c (add_param_to_type): #if 0'd function to add a
+ parameter type to a function type's field list.
+
+ * defs.h (local_hex_format, local_hex_string, *_custom): Add.
+ * i386-xdep.c, pyr-tdep.c, pyr-xdep.c, remote-vx.c, solib.c,
+ source.c, symfile.c, dbxread.c, breakpoint.c, core.c, exec.c,
+ i387-tdep.c, infcmd.c, mips-tdep.c, stack.c, printcmd.c: Output
+ hex with local_hex_string for Modula-2 support.
+
+ * breakpoint.c (breakpoint_cond_eval): Use new value_true to test
+ breakpoint condition language-independently.
+
+ * parse.c: New file with the common code remains of expread.y.
+ * parser-defs.h: New file with common declarations from expread.y.
+ * c-exp.y: New file with the C parser from expread.y, and other
+ language-specific information.
+ * m2-exp.y: New file with the Modula-2 parser and etc.
+ * expread.y, expread.tab.c: Remove.
+ * breakpoint.c, eval.c, printcmd.c, expression.h: Use
+ parse_expression and parse_exp_1 rather than parse_c_expression
+ and parse_c_1.
+
+ * symtab.h (enum languages): Move to defs.h.
+ (enum type_code): Add TYPE_CODE_CHAR and TYPE_CODE_BOOL.
+ Declare Modula-2 builtin types.
+ Add MAX_OF_TYPE and MIN_OF_TYPE macros.
+
+ * symtab.c (_initialize_symtab): Remove builtin type
+ definition and initialization to *-exp.y.
+ (lookup_primitive_typename): Use language-dependent vector.
+ (lookup_typename): Fix bug, make it work if primitive typename.
+ (lookup_unsigned_typename): Call above.
+ (create_array_type): Set up range type for array index.
+ (list_symbols): Call typedef_print to print typedefs.
+
+ * values.c (unpack_long, value_from_longest): Handle
+ TYPE_CODE_BOOL and TYPE_CODE_CHAR.
+
+ * expression.h (enum exp_opcode): Add Modula-2 specific opcodes.
+ * expprint.c: Look up expression opcodes in language-specific
+ table, based on expression's language. Handle some Modula-2
+ specific opcodes.
+
+ * stack.c (frame_info): Print language of stack frame.
+ (select_frame): Also select language, if in auto-mode.
+ (get_frame_language): New subroutine.
+ * main.c (execute_command): Warn as language changes automatically.
+
+ * printcmd.c (ptype_command): Parse types using the language
+ parser, both for language-independence, and so that scopes can
+ be specified.
+
+ * language.h, language.c: New files for language-specific macros,
+ declarations, and definitions.
+
+ Misc fixes:
+
+ * main.c (main): If error() is called during early
+ initialization, print its message and then exit(1) from GDB.
+
+ * valprint.c (type_print_base): Avoid printing garbage for ints
+ of unusual sizes.
+ (_initialize_valprint): Warn about host/target size assumption;
+ improve long long support slightly.
+
+ * convex-tdep.c (comm_registers_info): Avoid parsing decimal and
+ hex -- let parse_and_eval_address do it.
+
+ * doc/gdbint.texinfo (Languages): Doc how to add a language.
+
+ * Makefile.in: Cope with new files and removed files.
+
+Tue Sep 17 08:37:41 1991 John Gilmore (gnu at cygint.cygnus.com)
+
+ Add Andrew Beers' changes for Modula-2 support. His ChangeLog
+ entries are enclosed herein. Not all of these changes
+ have been merged into the master GDB sources -- check the
+ ChangeLog above here for the merge log.
+
+Mon Jun 3 17:05:45 EDT 1991
+
+ m2-exp.y Created. Tested outside of GDB for a few days. Proper
+ operators were added, C specific operators and tokens
+ removed. yylex() revamped to some extent. Still things
+ missing from the grammar, such as sets.
+ Tested for two weeks in GDB v3.5.
+
+Tue Jun 11 17:23:48 EDT 1991
+
+ m2-exp.y Added boolean constants TRUE and FALSE to the grammar
+ so they are built-in. Sort of a hack.
+
+Fri Jun 14 12:53:51 EDT 1991
+
+ m2-exp.y Added range checking for numeric constants. Any numeric
+ constant is assumed to be of builtin type INTEGER unless:
+ (1) it is octal or hexadecimal, in which case it is a
+ CARDINAL; (2) it is too big to fit into an INTEGER, in
+ which case it is a CARDINAL.
+ eval.c Added simple range checking for +, -, and * on integers.
+ Doesn't work very well for *, since 6 * 1,000,000,000 =
+ 1,705,032,704, which fails the simple test of result >=
+ first_operand, no matter in what order the operands are.
+
+Tue Jun 18 14:11:30 EDT 1991
+
+ Broke the parser into parts, one containing the C grammar and the other
+ containing code to be shared by all of the grammars.
+
+ The following files no longer exist:
+
+ expread.y
+ expread.tab.c
+
+ The following files were added:
+
+ c-exp.y (The C grammar)
+ m2-exp.y (The Modula-2 grammar)
+ parser-code.c (Code that is shared by the above grammar)
+ parser-code.h
+ parser-defs.h
+
+ Makefile.dist Changed to reflect the above dependencies. NOTE: It is
+ now necessary to use the Bison compiler compiler, since it
+ will generate function/variable prefixes other than yy.
+
+Tue Jun 18 16:47:49 EDT 1991
+
+ symtab.[ch] Added the external variable working_lang, than holds the
+ value of the current working language.
+ Added the ennumerated type language_mode, with the values
+ language_auto and language_manual, the former meaning that
+ GDB sets working_lang as needed, and the latter meaning
+ that the value of working_lang is totally under user
+ control.
+ symtab.[ch] Added the Modula-2 pervasive types INTEGER, CARDINAL,
+ REAL, BOOLEAN and CHAR. Also added the type codes
+ TYPE_CODE_BOOL and TYPE_CODE_CHAR.
+ utils.c Added set_language_command and show_language_command to
+ implement the GDB support commands "set language" and
+ "show language".
+ expression.h A number of identifiers were added to the type exp_opcode
+ to facilitate Modula-2 builtin functions, integer
+ division, and array indexing.
+
+Wed Jun 19 13:25:58 EDT 1991
+
+ language.h Added the macro STRICT_TYPE, which evaluates to non-zero
+ if the language specified by working_lang requires the use
+ of strict typing of expressions. Eventually, even this
+ will be able to be changed by the user.
+ Added the macro RANGE_CHECK, which evaluates to non-zero
+ if the language specified by working_lang requires the
+ checking of a value against the domain of its type.
+ Eventually, even this will be able to be changed by the
+ user.
+ language.[ch] Predicates involving types (simple_type, ordered_type,
+ same_type, integral_type, numeric_type, character_type,
+ boolean_type, float_type) are added. These predicates are
+ based on the current value of working_lang, and are handy
+ in type-checking.
+
+Wed Jun 19 15:39:34 EDT 1991
+
+ eval.c Added the function type_array_rank which computes the rank
+ of an array type.
+ valarith.c Added the funtion value_bool, which when given a integer
+ value.h value (ie. struct value *) as an argument, it returns a
+ boolean value (ie. struct value *) true if that integer
+ is non-zero, and a boolean value false otherwise.
+ valprint.c Added cases for TYPE_CODE_BOOL, so Modula-2 BOOLEAN values
+ will print out properly.
+
+Wed Jun 19 16:36:34 EDT 1991
+
+ valops.c Added the function value_capitalize, which returns it
+ value.h argument capitalized if its argument is a lowercase
+ letter, or the argument unchanged if its argument is not a
+ letter.
+ valarith.c Added the function range_check_p, which returns non-zero
+ value.h if its value argument is between the integral bounds upper
+ and lower.
+ Added the function range_check_enum_p, which makes sure
+ that its value argument is a valid member of the domain of
+ its type argument.
+ Added the function range_check_range_p, which makes sure
+ its value argument lies between the upper and lower bounds
+ of its type argument, which must be a ranged type.
+ Added the function check_array_index, which range and type
+ checks an index of an array.
+ Added the function value_multi_subscript, which computes
+ array[idx1,idx2...idxN], given a value array and an array
+ of values representing indicies.
+ values.c Changed value_from_long to work with TYPE_CODE_CHAR and
+ unpack_long to work with TYPE_CODE_BOOL and
+ TYPE_CODE_CHAR.
+
+Wed Jun 19 18:04:08 EDT 1991
+
+ symtab.c Stored pervasive types in a structure and make
+ lookup_pervasive_type() a lookup function that was based
+ on working_lang. If lookup_pervasive_type() returned
+ non-zero, then that value was returned (a fix, since
+ before it simply wouldn't return the pervasive type.)
+ language.h Added the macro CAST_IS_CONVERSION, which evaluates to
+ non-zero if the language specified by working_lang means
+ "conversion" when it says "cast".
+ valops.c Added the function value_real_cast(), which performs a
+ value.h *cast*, not a *conversion*, which is what value_cast()
+ does when it can. In particular,
+ value_cast(<float_type>,4) = 4.0, while
+ value_real_cast(<float_type>,4) = some mess.
+ eval.c Modula-2 builtin functions implemented: ABS, CAP, CHR,
+ parser-code.c FLOAT, HIGH, MAX, MIN, ODD, ORD, TRUNC, and VAL.
+ expression.h Added macros MAX_OF_TYPE and MIN_OF_TYPE to work with MAX
+ and MIN on integral types. *NOTE*: These are currently
+ hardcoded to work only if there are 8 bits per storage
+ unit. FIXME.
+ eval.c Made logical functions call value_bool to return a
+ properly typed boolean value, based on working_lang.
+
+Thu Jun 20 11:55:27 EDT 1991
+
+ valprint.c Types now print out in a Modula-2 fashion. This works for
+ the cases when the type is printed out step-by-step, that
+ is, it doesn't work when the name of a structured type
+ (which includes the keyword "struct", etc.) is simply
+ displayed.
+ FIXME: Perhaps this is bad. Parts of it seem to kludgey,
+ since type specifications in C and Modula-2 are very
+ different. The C printing of a type is very recursive,
+ whereas in Modula-2 it is generally very simple. C has
+ type prefixes and suffixes, which have no real analogue in
+ Modula-2. Maybe type_print() should call a language
+ specific type printer. This is also advantageous if we
+ compile GDB to exclude some of the languages. We'll just
+ leave those functions out.
+
+Thu Jun 20 16:57:10 EDT 1991
+
+ dbxread.c When reading the complete symbol table in (via
+ psymtab_to_symtab()), the number and types of function
+ arguments are added to a function type. define_symbol()
+ calls add_param_to_type() to accomplish this.
+ Assumption: when we come across a function definition
+ (N_FUN symbol with an 'f' or 'F' in the name), its
+ arguments will appear before another function definition.
+ When a function is found, a pointer to its type is placed
+ in the global in_function_type. Changes that
+ add_param_to_type() makes are to this global.
+ valprint.c The type of a function now includes (for Modula-2) the
+ types of its parameters.
+ eval.c Type checking and a check for the proper number of
+ arguments is now done for function calls. Not sure of the
+ impact this has on C++ member function yet.
+
+Thu Jun 20 19:58:48 EDT 1991
+
+ valprint.c Rewrote the type printer. Broke it into two language
+ specific parts, adding the functions type_print_m2() and
+ type_print_m2_1().
+ An unfortunate consequence is this: if you debugging a C
+ program in Modula-2 mode (why?), info types does not work
+ well with regular expressions, since the types are printed
+ out in Modula-2 terminology, but stored in C terminology.
+ language.[ch] Added the functions new_type_last(), type_keyword(), and
+ type_sep() to aid in the printing of typedefs.
+ symtab.c Made the printing of typedefs as language independent as
+ possible through calls to new_type_last(), type_keyword(),
+ and type_sep().
+
+Fri Jun 21 11:50:26 EDT 1991
+
+ dbxread.c Check all incoming ennumerated types. If it looks like
+ Modula-2's BOOLEAN type, then change the type_code of the
+ type to TYPE_CODE_BOOL so we can process it as a boolean
+ variable.
+ valprint.c Replaced some of the 0x%x with calls to sprintf and
+ hexformat() in val_print().
+ language.[ch] Added the function hex_to_string(), which converts its
+ integral argument to a hexadecimal number (format is
+ language based) and returns the result as a string.
+
+Mon Jun 24 12:25:07 EDT 1991
+
+ valprint.c Some functions call type_print_1() directly, instead of
+ value.h using type_print(), so they can specify where (column) to
+ print things. Since type_print() takes care of language
+ dependence, that needs to be called first. Added a
+ parameter depth to type_print() (so it is now like
+ type_print_1). Changed type_print to type_print_at, and
+ made type_print a macro that passes a depth argument of
+ zero.
+ symmisc.c Changed all calls to type_print_1 to calls to
+ type_print_at.
+ Makefile.dist Made it possible to build GDB for a specific set of
+ depend languages. Do this by passing a definition for the macro
+ LANGS to make. LANGS should be a string containing a
+ space-separated list of language names (ie. LANGS="c m2").
+ The default is to build all languages. Note that grammar
+ files must follow the naming convention of <lang>-exp.y.
+ gdb.lang This holds the current value of the LANGS macro. It is
+ examined every time make is called, and is updated if
+ necessary.
+ eval.c Added #ifdef _LANG_<lang> to these files.
+ expread.c Still need to add them to dbxread.c and coffread.c.
+ main.c
+ source.c
+ symtab.c
+ utils.c
+ valarith.c
+ valprint.c
+
+Mon Jun 24 16:33:11 EDT 1991
+
+ language.[ch] Added the functions hexformat_pre() and
+ hex_to_string_pre(), which take a prefix argument to
+ include in the format string. Thus, hexformat_pre("08") will
+ return "0x08x" (if the working language is language_c).
+ Made hexformat() and hex_to_string() calls to the above
+ with "" as the prefix argument.
+
+ am29k-pinsn.c, arm-pinsn.c, breakpoint.c, convex-tdep.c, exec.c, core.c,
+ dbxread.c, i386-pinsn.c, i386-stub.c, i386-xdep.c, i960-pinsn.c,
+ infcmd.c, inflow.c, m68k-pinsn.c, m68k-stub.c, m88k-pinsn.c,
+ mips-pinsn.c, mips-tdep.c, ns32k-pinsn.c, printcmd.c, pyr-pinsn.c,
+ pyr-tdep.c, pyr-xdep.c, remote-vx.c, remote.c, solib.c, source.c,
+ stack.c, sun386-xdep.c, symfile.c, symm-xdep.c, symmisc.c, tahoe-pinsn.c,
+ valprint.c, vax-pinsn.c
+
+ Changed all occurences of 0x%[0-9]*l*x in printf format strings to
+ calls to hexformat() and hex_to_string(). Format strings without
+ the leading "0x" were ignored.
+
+ depend Updated to take the above into account.
+
+
+Tue Jun 25 15:27:18 EDT 1991
+
+ symtab.h Added the types range_mode_t, range_check_t, type_mode_t,
+ and type_check_t to keep track of the current state of
+ range and type checking.
+ main.c Added the variables range_mode, range_check, type_mode,
+ and type_check to record the current state of range and
+ type checking. Added initialization code to main().
+ language.h Changed the macros STRICT_TYPE and RANGE_CHECK to examine
+ the above variables.
+
+
+Tue Jun 25 17:57:08 EDT 1991
+
+ dbxread.c process_one_symbol() updates the variable (enum language)
+ source_lang based on the extension of the filename
+ contained in the N_SO sybmol that started this symtab.
+ When end_symtab() is called, the value of source_lang is
+ put into the language field.
+ stack.c select_frame() sets working_lang (and possibly type_check
+ and range_check) to the language field of the symtab
+ associated with the frame that is selected if working_mode
+ is language_auto. If working_mode is language_manual, a
+ warning is printed and working_lang is not set.
+ language.c Added the function set_type_range(), which sets the value of
+ type_check and range_check (if their modes call for
+ automatic setting) based on the current value of
+ working_lang. A non-zero argument will cause the current
+ settings to be output.
+
+
+Wed Jun 26 14:51:40 EDT 1991
+
+ eval.c Added range checks on assignment.
+ m2-exp.y Added the grammar for sets to the language. Currently,
+ these do not do anything except print an error message.
+
+Wed Jun 26 17:01:04 EDT 1991
+
+ m2-exp.y Added the ability for parse_number() to parse negative
+ numbers. A global flag is set upon encountering a unary
+ minus. This was done to make, for example, 1 parse as a
+ CARDINAL, and not as an integer, per Wirth's examples in
+ Programming in Modula-2 ed.4.
+ valprint.c Added support for "set radix 2" by then setting
+ output_format to 't'.
+ eval.c Implemented range checking on subrange types. Added calls
+ to range_check_range_p for BINOP_ASSIGN and BINOP_VAL.
+ Implemented MIN and MAX for ennumerated types. The
+ minimum value of an ennumerated type is defined by Wirth
+ as the first identifier, and the maximum as the last.
+ m2-exp.y Made octal numbers ending with "B" be characters and those
+ ending with "C" be numbers, per Wirth's book. (p. 34)
+
+Thu Jun 27 14:11:52 EDT 1991
+
+ stack.c select_frame() now only sets working_lang, it does not
+ notify the user. If working_mode is language_manual, then
+ a warning is issued once.
+ main.c At the end of each call to execute_command(), working_lang
+ is checked against the local static (enum language)
+ current. If they differ and working_mode is
+ language_auto, the new settings of language, type and
+ range checking are printed out.
+ stack.c Modified frame_info() to include the language of the
+ current frame in the output of "info frame".
+ language.[ch] Added the function language_str() which returns the name
+ of the current language.
+
+Fri Jun 28 15:33:14 EDT 1991
+
+ m2-exp.y Added the built-in procedures INC, INCL, DEC, and DECL to
+ the language. INCL and DECL currently cause an error,
+ since sets are not implemented yet. INC and DEC are
+ implemented as PREINCREMENT/PREDECREMENT with one
+ argument, and as ASSIGN_MODIFY with two arguments.
+ eval.c Added type checking to the above cases.
+ value.h Added not_lval_constant to the lval_type ennumerated type.
+ not_lval_constant means that the value is a constant
+ value; that is 3 or 'a' or TRUE, not as in a constant
+ identifier. This is used to help coerce numbers such as 3
+ to either signed or unsigned numbers.
+ valops.c Added the function value_coerce_constants() which coerces
+ constant integers as following: if one is a constant and
+ the other is not, the constant's type is set to the type
+ of the other argument. If both are constants and one is
+ signed, the other is converted to a signed constant.
+
+Sat Jun 29 17:26:29 EDT 1991
+
+ valarith.c Added a better range checker. It now checks range
+ (successfully) on integral operations [+-] (signed and
+ unsigned) for any C sized type. Still does not work well
+ for multiplication.)
+ int_in_size() returns an integer that is coerced to fit into
+ specified number of bytes.
+
+Mon Jul 1 13:04:14 EDT 1991
+
+ language.[ch] Added the function binop_result_type(), which returns the
+ builtin (struct type *) type that would be the result of a
+ binop on the two values V1 and V2.
+
+Wed Jul 3 19:22:53 EDT 1991
+
+ source.c Extended source_info() to include the source language in
+ the output from "info source".
+
+Fri Jul 5 13:48:52 EDT 1991
+
+ utils.c Moved the support functions for the GDB set/show commands
+ dealing with language into language.c.
+ language.c Added the function language_info(), which displays info
+ about the current working language, type and range check
+ settings. Called via the GDB command "info language".
+ Added an initialization routine _initialize_language(),
+ that sets defaults for the language, type and range
+ variables and sets up the new GDB commands.
+ main.c Language setup moved to language.c.
+ depend Rebuilt.
+
+Mon Jul 8 10:10:22 EDT 1991
+
+ valarith.c Debugged the range checker for arithmetic. Still does not
+ work for multiplication very well.
+
+Mon Jul 8 12:40:37 EDT 1991
+
+ language.[ch] Added the function value_true() which returns non-zero if
+ its argument represents a boolean true value.
+ breakpoint.c Changed breakpoint_cond_eval() to call value_true() to
+ check the truth of an expression.
+
+Thu Jul 11 12:51:34 EDT 1991
+
+ language.[ch] Added the predicate structured_type(), which returns
+ non-zero if the argument is a structured type.
+ Added the predicate pointer_type(), which returns non-zero
+ if the argument is a pointer type.
+ eval.c Added the ability to do addition and substraction on
+ pointers and integers. This case simply bypasses the
+ type checker.
+
+Thu Jul 11 14:41:42 EDT 1991
+
+ include/stab.def
+ Added the symbol N_DEFD (0x4a) which is a definition
+ module dependency that is used by the GNU Modula-2
+ compiler and the linker. It is not important to GDB,
+ except that [dbx|coff|mips]read.c should ignore these
+ symbols.
+
+Fri Jul 12 16:07:00 EDT 1991
+
+ valprint.c Changed the TYPE_LENGTH(type) >= 0 to TYPE_LENGTH(type) >
+ 0 in val_print(). Also added statements to the else part
+ to coerce type (argument to val_print) to a pointer type
+ if it is an "array of unspecified length".
+ valops.c Added the function value_m2_string(), which returns a
+ (value) value which is a constant string, whose type is
+ (ARRAY [0..n] OF CHAR). The length field of the type
+ structure is set to zero, so it will be interpreted as an
+ "array of unspecified length".
+ stack.c Moved the language/frame mismatch check to
+ main.c:execute_command().
+ main.c The working language is recorded each time
+ execute_command() is executed. If working lang has
+ changed during its execution, then the new
+ language/type/range info is printed out for the user. If
+ the working language does not match the language of the
+ frame, a warning is issued.
+
+Sat Jul 13 16:16:39 EDT 1991
+
+ eval.c Moved all the type-checking stuff for operators to
+ language.[ch] language.c. This is so we can keep language-specific
+ stuff (like for what type operators are defined) in
+ language.c.
+ language.[ch] Added the function binop_type_check(), which checks to see
+ if its two (value) arguments are type-compatible with its
+ opcode argument. The opcode should represent an operation
+ involving an operator. Also added the macro function
+ unop_type_check, which calls binop_type_check with a
+ NULL second argument.
+ expprint.c Added Modula-2 operators to the op_print_tab, so info
+ expression.h break works correctly. Also added "op_string", which
+ returns the string corresponding to the (enum exp_opcode)
+ opcode that is its argument.
+
+
+Sat Jul 13 18:26:18 EDT 1991
+
+ coffread.c Added code to record the type of function arguments with
+ each paricular function. Code is very similar to that
+ added to dbxread.c.
+ dbxread.c Moved add_param_to_type() to symtab.c
+ symtab.[ch] Added function add_param_to_type() from dbxread.c
+
+ *** NOTE: The above additions have not been tested.
+
+Mon Jul 15 12:50:47 EDT 1991
+
+ langauge.[ch] Added the functions type_error and range_error, which work
+ like error() except if the type/range mode is set to
+ *_mode_warn, then they do not do a return_to_top_level(),
+ but merely print a warning.
+ Also changed [set|show]_[type|range]_command() to support
+ the new "warn" feature.
+
+Thu Jul 18 17:50:54 EDT 1991
+
+ mipsread.c Added code to record the type of function arguments with
+ each particular function. Code is very similar to that
+ added to dbxread.c.
+
+ *** NOTE: The above additions have not been tested.
+
+Fri Jul 19 11:19:10 EDT 1991
+
+ defs.h Added macros MAX_OF_SIZE, MIN_OF_SIZE, UMAX_OF_SIZE, and
+ UMIN_OF_SIZE, which when given a size of a numeric type,
+ return the maximum and minimum value it can hold. UMAX...
+ and UMIN... return the result for unsigned types.
+ symtab.h Added the macros MAX_OF_TYPE and MIN_OF_TYPE to operate on
+ struct types. They call above macros.
+ dbxread.c Renamed the MAX and MIN_OF_TYPE macros to ..._OF_CTYPE to
+ avoid a name conlict with the above.
+ c-exp.y Added range checking on numeric constants in
+ parse_number() for completeness.
+ valarith.c Made binop_user_defined_p() and unop_user_defined_p()
+ return 0 if working_lang is not language_c.
+
+Thu Aug 8 14:17:22 EDT 1991
+
+ main.c
+ printcmd.c
+ breakpoint.c Documentation strings of some commands changed to
+ eliminate the references to the C language where
+ appropriate.
+
+Tue Aug 13 15:48:03 EDT 1991
+
+ m2-exp.y Added qualified identifiers to the grammar. The semantics
+ are slightly different from those of the GDB operator ::
+ c-exp.y
+ m2-exp.y Added a rule to each grammar of the form: start ::= exp |
+ type_exp, where type_exp is any valid type expression.
+ expression.h
+ eval.c Added the opcode OP_TYPE, and an error case in eval.c.
+ printcmd.c Modified ptype_command() so it actually parses the input
+ (necessary for type expressions with scope qualifiers).
+ Added the function ptype_eval() which expects an
+ expression composed of one OP_TYPE element.
+ *.[ch] Replaced all occurences of parse_c_expression with
+ parse_expression
+ *.[ch] Replaced all occurences of parse_c_1 with parse_exp_1
+
+[End of ChangeLog entries from Andrew Beers for Modula-2 support.]
+
+Mon Sep 16 17:19:46 1991 John Gilmore (gnu at cygnus.com)
+
+ Small fixes from Peter Schauer:
+
+ * infrun.c (child_attach): Lint.
+ * solib.c (find_solib): Handle shared libs version 2.
+
+ Small fixes from David Wood:
+
+ * xm-ultra3.h (SYS_SIGLIST_MISSING): Typo.
+
+ Small fixes:
+
+ * remote-vx.c: Move <stdio.h> to top, for FILE. Fix from
+ John S <basrai%kanga.dnet@c3po.sm-alc.af.mil>.
+
+ * utils.c (wrap_here): Avoid wrap action of fputs_filtered if
+ chars_per_line is at maximum (user typed `set width 0'). Fix
+ from Andreas Schwab <schwab@ls5.informatik.uni-dortmund.de>.
+
+Tue Sep 17 17:31:04 1991 Stu Grossman (grossman at cygnus.com)
+
+ * coredep.c: include ptrace.h where necessary.
+ * mipsread.c(parse_lines): fix unsigned char problem that was
+ messing up line numbers on SGI's and possibly other MIPS based
+ platforms.
+ * infrun.c (child_create_inferior): use better test to check
+ return val from setpgrp().
+ * tm-irix3.h, xm-irix3.h, tconfig/irix3, xconfig/irix3: add these
+ for sgi/irix support.
+
+Wed Sep 18 04:33:31 1991 Per Bothner (bothner at cygnus.com)
+
+ * mipsread.c (parse_symbol): Put non-static procedures
+ in the global block.
+
+Fri Sep 13 00:14:52 1991 John Gilmore (gnu at cygnus.com)
+
+ Patch together `text_start' and `text_end' for 29K port.
+
+ * exec.c (exec_command): If NEED_TEXT_START_END, define the
+ variables and set them based on the exec file.
+ * am29k-tdep.c: declare text_start.
+ * valops.c (call_function_by_hand): declare text_end.
+
+ * inferior.h: Eliminate CANNOT_EXECUTE_STACK in favor of
+ defining CALL_DUMMY_LOCATION as BEFORE_TEXT_END. This is
+ because machines that do this will also have to know to
+ set NEED_TEXT_START_END. Besides, it was a redundant way to
+ say the same thing.
+ * tm-29k.h, tm-convex.h, tm-np1.h: Eliminate
+ CANNOT_EXECUTE_STACK, define CALL_DUMMY_LOCATION and
+ NEED_TEXT_START_END.
+
+Thu Sep 12 00:22:24 1991 John Gilmore (gnu at cygint.cygnus.com)
+
+ AMD 29000 changes from David Wood <wood@david.ultra.nyu.edu>:
+
+ * Makefile.in (CLIBS): Put XM_CLIBS and TM_CLIBS at end.
+ Pass MUNCH_DEFINE to munch whenever we run it.
+ * am29k-pinsn.c (print_insn): Handle NOP specially. Avoid %#x
+ format string; use 0x%x instead.
+ * am29k-tdep.c: Use DUMMY_SAVE_GREGS and RETURN_REGNUM.
+ * ultra-xdep.c, xm-ultra.h: New files for Ultracomputer host system.
+ * xm-rtbsd.h: New host support for RT/PC running BSD Unix.
+ * inflow.c: Handle `short' process group IDs.
+ * infptrace.c (fetch_register): Support CANNOT_FETCH_REGISTER,
+ and check for ptrace errors.
+ * coffread.c (SDB_REG_TO_REGNUM): Define if not already.
+ (coff_symfile_init): Initialize text_bfd_scnum.
+ (read_coff_symtab): Use it to find the text [and absolute?] sections.
+ * ../config.sub: Add vendor nyu and os "sym[1-9]*".
+ * configure.in: Add hosts rtpc-*-* and a29k-*-*.
+ Merge target arm case with other "easy" cases. Add target
+ cases a29k-*-none (rehack of am29k), a29k-*-kern (remote to
+ Ultracomputer kernel), and a29k-*-sym1 (ultracomputer OS's user
+ process).
+ * minimon.h, remote-adapt.c, remote-mm.c: Add.
+ * munch: Cope with RT/PC putting fns in data segment.
+ Restore ability to override `nm' by specifying MUNCH_NM.
+ * xconfig/rtbsd, xconfig/ultra3: New host systems.
+ * tconfig/a29k: Rename from tconfig/am29k. Add remote-mm
+ and remote-adapt. Remove encapsulated coff #define's (the
+ support should go in BFD, and gdb shouldn't know or care).
+ * tconfig/a29k-kern: Same, but for remote kernel debugging.
+ * tconfig/ultra3: For debugging user processes on Ultra3/Sym1.
+ * tm-29k.h: Update BADMAG (though it should go away).
+ Allow the register definitions to be overridden in another
+ tm-file. Fix SR_REGNUM. Add a mess of _REGNUM's. Separate
+ RETURN_REGNUM from GR96_REGNUM and DUMMY_SAVE_GREGS from
+ DUMMY_SAVE_GR96, for handling kernel calling conventions
+ that use GR64+ rather than GR96+.
+ * tm-ultra3.h: New file, for use on Ultra3 Unix as well as for
+ remote debugging of Ultra3 kernel. Includes tm-29k.h and
+ overrides various things.
+
+ * remote-mm.c (mm_attach, mm_wait): Handle attach like
+ child_attach does, making a clean stop in the newly attached
+ program.
+ * remote-eb.c: Lint.
+
+ * coffread.c: Make coffread independent of any particular
+ variant of COFF. Avoid #include-ing any particular one except
+ internalcoff.h. BFD now passes key values for symbol reading
+ as part of its coff_data structure (LINESZ, SYMESZ, AUXESZ,
+ and the symbol masks and shifts); use them.
+ Remove obsolete end_of_text_addr.
+
+ * exec.c: Remove unused include files.
+
+Wed Sep 11 19:38:44 1991 John Gilmore (gnu at cygint.cygnus.com)
+
+ * Makefile.in (documentation targets): Pass $(M4).
+ Bugfix from eggert@twinsun.com (Paul Eggert).
+
+ * stack.c (down_silently_command): Check for stack existence.
+
+Tue Sep 10 23:08:29 1991 John Gilmore (gnu at cygint.cygnus.com)
+
+ * Makefile.in (VERSION): Update to 4.0.3.
+
+Tue Sep 10 09:19:29 1991 John Gilmore (gnu at cygint.cygnus.com)
+
+ * core.c (core_file_command): Print frame at coredump with
+ its level number, by calling print_stack_frame.
+ * frame.h: Add selected_frame_level, print_stack_frame.
+ * frame.h, stack.c: Remove print_sel_frame, print_selected_frame.
+ * convex-tdep.c, convex-xdep.c, infcmd.c, inflow.c, infrun.c:
+ Change print_sel_frame and print_selected_frame callers to
+ print_stack_frame.
+
+ * dbxread.c (read_ofile_symtab): Avoid empty else clause.
+ * symfile.c (free_named_symtabs): Ditto.
+ * main.c (main): wrap_here needs an arg.
+ * solib.c (find_solib): Avoid memory access if _DYNAMIC is zero.
+ (solib_add): Avoid noise.
+ (solib_create_inferior_hook): Lint.
+ (sharedlibrary_command): Move dont_repeat to here.
+ * utils.c (error): Call wrap_here to force buffered output.
+
+ Small patches from Peter Schauer:
+
+ * coffread.c (start_symtab): Free any existing line_vector before
+ malloc-ing new one.
+ (read_coff_symtab): Ditto for type_vector.
+
+ * source.c (lines_to_list): New variable, replacing function.
+ (all uses): Use as variable.
+ (_initialize_source): Add 'set listsize' and 'show listsize'.
+ * utils.c (lines_to_list): Remove function.
+ * stack.c (print_frame_info): Use as variable.
+ * defs.h (lines_to_list): Remove declaration.
+
+Mon Sep 9 13:45:57 1991 John Gilmore (gnu at cygint.cygnus.com)
+
+ * breakpoint.c (insert_breakpoints): Restore warning about
+ the program might be running in another process, but only for
+ systems with this brain death (#ifdef ONE_PROCESS_WRITETEXT).
+ * xm-hp300bsd.h, xm-mips.h, xm-vax.h: Define it.
+
+ * utils.c (error): if error_pre_print is set, print the string
+ first.
+ * main.c (main, print_gnu_advertisement, print_gdb_version):
+ Reformat legalese so it always prints, but acts as an "I'm here"
+ message while symbols are being read. If any errors occur,
+ print a few newlines to set off the message and start it at the
+ left margin. Remove mention of "help" command, and don't yak
+ about symbol reading.
+ (catch_errors): Error string is now printed first in case of
+ error, not last.
+ * command.c (undef_cmd_error, lookup_cmd): On undefined command,
+ suggest the "help" command.
+
+ * Makefile.in (VERSION): Set to 4.0.2.
+
+Thu Sep 5 23:49:48 1991 John Gilmore (gnu at cygint.cygnus.com)
+
+ * .gdbinit: Remove useless "rr" command. Set complaints
+ to 1 for people debugging gdb.
+
+ * breakpoint.c, remote-vx.c: Reword strings printed by
+ catch_errors callers.
+
+Wed Sep 4 11:07:50 1991 John Gilmore (gnu at cygint.cygnus.com)
+
+ * WHATS.NEW: "history write -> history save". Doc "write on/off".
+ (Fix from kenc@viewlogic.com.)
+
+ Fix some infrastructure to be able to cope with host and target
+ machines with different sized basic types (ints, ptrs, etc).
+ (Idea from pierre@la.tce.com (Pierre Willard).)
+
+ * values.c (value_from_longest): Rename from value_from_long.
+ Handle pointer types as well as integers, so that targets with
+ different pointer sizes from the host can be accomodated.
+ * breakpoint.c, convex-tdep.c, eval.c, expprint.c, printcmd.c,
+ valarith.c, valops.c, valprint.c, value.h, values.c: Rename
+ uses of value_from_long to value_from_longest.
+ * eval.c, findvar.c, printcmd.c, valarith.c, valops.c: Pass
+ the correct pointer type to value_from_long{est}.
+
+ * doc/gdb.texinfo ($_, $__): Describe types of these variables.
+
+ * remote-vx.c: Remove obsolete code for calling functions via
+ vxworks kludge interface (it referenced value_from_long).
+
+ * valops.c (value_string): Find malloc with lookup_misc_func, not
+ raw search.
+
+Tue Sep 3 18:37:46 1991 John Gilmore (gnu at cygint.cygnus.com)
+
+ Make writing to files work properly. (Fixes to BFD are also needed.)
+
+ * core.c (core_open): Open file ourselves, read or r/w, depending on
+ write_files. Use bfd_fdopenr.
+ * gdbcore.h (write_files): New variable.
+ * exec.c (write_files): Define variable, add set&show for it.
+ (exec_file_command): Use write_files to open for read or r/write.
+
+ Make shared library reading happen automatically. These changes
+ are mostly from Peter Schauer <pes@regent.e-technik.tu-muenchen.de>.
+
+ * inferior.h (stop_soon_quietly): Add to exported variables.
+ * infrun.c (child_create_inferior): call solib hook, if defined.
+ (child_attach): call solib hook, if defined.
+ * solib.c: Include inferior.h. Add from_tty to so_list as kludge.
+ (find_solib): Use lookup_misc_func rather than hand-rolled.
+ (symbol_add_stub): New stub for catch_errors.
+ (solib_add): Avoid output if !from_tty. Catch errors rather
+ than just calling symbol_file_add and bombing.
+ (solib_create_inferior_hook): Interface with the target process
+ to let it read and alloc shared libs, then figure out what it did.
+
+ * core.c (validate_files): Fix typo, soften warning.
+ (Fix from Hiroto Kagotani <kagotani@cs.titech.ac.jp>.)
+
+ * utils.c (fputs_demangled): Avoid duplicate printing if
+ demangling is off. (Fix from J.T. Conklin <jtc@cayenne.com>.)
+
+ * infrun.c (proceed): Cast -1 to (CORE_ADDR) before comparing.
+ (Fix from pierre@la.tce.com (Pierre Willard).)
+
+ * main.c (catch_errors): Change argument to a char * from an int,
+ since a char * can point to a struct full of glop, but an int
+ is not guaranteed to be able to hold a pointer.
+ * breakpoint.c (breakpoint_cond_eval, bpstat_stop_status,
+ breakpoint_re_set_one, breakpoint_re_set): Adapt.
+ * core.c (core_open, solib_add_stub): Adapt.
+ * remote-vx.c (symbol_stub, add_symbol_stub, callers): Adapt.
+
+Wed Aug 28 18:18:05 1991 John Gilmore (gnu at cygint.cygnus.com)
+
+ * Makefile.in: Update VERSION to 4.0.1. Evade GNU Make bug
+ by adding .NOEXPORT target.
+
+Fri Aug 23 17:14:25 1991 John Gilmore (gnu at cygint.cygnus.com)
+
+ * GDB-4.0 release!
+ * Update README.
+ * Makefile.in (VERSION): Roll to 4.0.
+ (gdb.tar.Z): Make refcard.ps as well, for shipment.
+
+Fri Aug 23 14:07:09 1991 Roland H. Pesch (pesch at cygint.cygnus.com)
+
+ * doc/gdb.texinfo: minor rewordings, crossref to ptype from print,
+ more on printsyms.
+
+ * doc/Makefile, Makefile.in: generate "gdb-all.texi" rather than
+ "gdb-all.texinfo"
+
+ * doc/rdl-apps.texi: renamed from rdl-apps.texinfo
+
+ * Makefile.in, doc/Makefile, doc/gdb.texinfo:
+ reflect above name change
+
+ * WHATS.NEW: correct pointer to refcard.
+
+ * doc/gdb.texinfo: update New Features, Installing
+
+ * doc/gdbint.texinfo: add short description of configure +template
+
+Fri Aug 23 11:46:08 1991 Roland H. Pesch (pesch at cygint.cygnus.com)
+
+ * doc/gdb.texinfo: update, fix bugs in "Installing" appendix
+
+Fri Aug 23 01:02:00 1991 John Gilmore (gnu at cygint.cygnus.com)
+
+ * Makefile.in: Add config.sub, make doc/rdl-apps.texinfo for
+ tar file, add dependencies for referenced doc files.
+
+Thu Aug 22 22:17:06 1991 Stu Grossman (grossman at cygint.cygnus.com)
+
+ * coffread.c, symfile.c, stack.c: saberized.
+
+Thu Aug 22 16:20:27 1991 Roland H. Pesch (pesch at cygint.cygnus.com)
+
+ * doc/refcard.tex: permuted Essential Commands sec
+
+ * doc/gdb.texinfo: new C++ chapter; revised installation appendix;
+ new doc for
+ set/show symbol-reloading
+ default set complaints 0
+ info all-registers
+ RET-repeat disabled after prompted long displays
+ processID (attach) interpretation of 2nd GDB cmdline arg
+
+Thu Aug 22 14:05:47 1991 Stu Grossman (grossman at cygint.cygnus.com)
+
+ * expread.y, coffread.c, dbxread.c, target.c, mem-break.c,
+ cplus-dem.c, values.c, valprint.c, symfile.c, remote.c,
+ breakpoint.c, main.c: lint.
+
+Thu Aug 22 02:02:26 1991 John Gilmore (gnu at cygint.cygnus.com)
+
+ Install new configuration scheme for GDB and friends.
+
+ * config.sub: Translate ordinary names to three-part names.
+ * configure: Use three-part names internally.
+ * configure.in: Translate three-part names to filenames.
+
+ * README, WHATS.NEW: Update for gdb-4.0.
+ * Makefile.in: Roll VERSION to 3.99.
+
+Wed Aug 21 18:21:09 1991 John Gilmore (gnu at cygint.cygnus.com)
+
+ * infptrace.c (KERNEL_U_ADDR_BSD): Include a.out.gnu.h.
+ * i960-tdep.c, m68k-tdep.c, sparc-tdep.c, tm-i960.h,
+ tm-m68k.h, remote-nindy.c: Change ext_format_XXX structs
+ to single structures rather than arrays; when passing
+ their address, use &. This avoids trouble with bdead compilers.
+ * mcheck.c: Don't include <stdlib.h>; just declare "void abort();"
+ instead. This avoids portability headaches.
+ * mips-tdep.c (mips_do_registers_info): Only print FP regs if
+ asked to.
+ * source.c (open_source_file): Avoid ANSI const bdeath by
+ skipping declaration and then casting result value.
+ * tm-hp300bsd.h: Clarify comment.
+ * utils.c (strstr): Result is const char *; ANSI bdeath.
+ * xm-hp300bsd.h: Define HOST_BYTE_ORDER. Redefine INT_MIN,
+ since system include file defines it differently from "defs.h",
+ though the two are equivalent for our purposes.
+ * tconfig/hp300bsd: Add m68k-tdep.o.
+
+Tue Aug 20 16:01:11 1991 John Gilmore (gnu at cygint.cygnus.com)
+
+ * tconfig/sun*4: Remove warnings about system assembler.
+
+Mon Aug 19 13:44:46 1991 John Gilmore (gnu at cygint.cygnus.com)
+
+ * mcheck.c: Avoid warning about undeclared abort fn.
+ * tm-sparc.h (PC_ADJUST): Avoid calling error() from this;
+ it causes recursive calls to error() when used in cleanups.
+ To do so requires that we make it a function, so we do.
+ * sparc-tdep.c (sparc_pc_adjust): New implem of PC_ADJUST.
+ * utils.c (do_cleanups): Remove the current cleanup from the
+ chain *before* calling it, in case error() is called from it.
+ The result won't be pretty, but won't be an infinite loop either.
+
+Mon Aug 19 00:41:04 1991 Michael Tiemann (tiemann at cygint.cygnus.com)
+
+ * dbxread.c (read_struct_type): Grok anon structs for C++.
+ (vb_name, vptr_name): Null terminate these strings.
+
+Fri Aug 16 08:31:03 1991 John Gilmore (gnu at cygint.cygnus.com)
+
+ Minor bug fixes from BSD Net2 gdb:
+
+ * blockframe.c (get_prev_frame_info): If FRAME_CHAIN_COMBINE
+ returns 0, there is no previous frame.
+ * breakpoint.c (commands_command): If !from_tty, don't call
+ input_from_terminal_p().
+ * dbxread.c (record_misc_function): Speed up slightly.
+ (compare_psymbols): Ditto.
+ * infcmd.c (do_registers_info): Take a second argument to
+ determine whether to print float registers. "info registers"
+ does not do so anymore. "info all-registers" does, now.
+ * mips-tdep.c, pyr-tdep.c (xxx_do_registers_info): Take second
+ arg and ignore it.
+ * tm-mips.h, tm-pyr.h (DO_REGISTERS_INFO): Pass second arg.
+ * inflow.c (initialize_inflow): Set tflags_ours correctly.
+
+ Other fixes:
+
+ * breakpoint.c (bpstat_do_actions): Use a cleanup to restore
+ executing_breakpoint_commands if we are interrupted by error.
+ * coffread.c (init_lineno): Avoid problem with zero-sized linetab
+ versus malloc/free. From: john@labtam.labtam.oz.au (John Carey).
+ * core.c (solib_add_stub, core_open): Call SOLIB_ADD inside a
+ catch_errors() so we can setup the frame regardless of whether
+ the shared libs work.
+ * ieee-float.c (double_to_ieee_extended): Get exponent from
+ right place in little-endian systems. From John Carey.
+
+Thu Aug 15 18:43:57 1991 John Gilmore (gnu at cygint.cygnus.com)
+
+ * main.c: Remove unused terminating_signals and catch_termination().
+ (long_options): Terminate with a zero element.
+ [Bugfix from Atsuo Kawaguchi <atsuo@hark86.harl.hitachi.co.jp>.]
+ (gdb_readline): Make call-compatible with readline.
+ (init_signals): Improve comments re vfork vs. signal.
+
+ * utils.c (prompt_for_continue): Use new gdb_readline().
+ If we prompt for continuation, we don't let CR repeat the previous
+ command, once we get back to a prompt. It's too easy to keep
+ hitting CR, expecting "--more--" prompts, and have some long
+ command start repeating on you.
+
+Tue Aug 13 16:17:56 1991 John Gilmore (gnu at cygint.cygnus.com)
+
+ * blockframe.c (frameless_look_for_prologue): Speed up by
+ calling SKIP_PROLOGUE_FRAMELESS_P if it's defined.
+ * tm-sparc.h (SKIP_PROLOGUE, SKIP_PROLOGUE_FRAMELESS_P):
+ Define two variants, one faster.
+ * sparc-tdep.c (sparc_frame_chain): Use target_read_memory
+ and return zero, rather than giving an error.
+ (setup_arbitrary_frame): Initialize the PC in the new frame.
+ (skip_prologue): Add a second arg saying whether we're just
+ checking for a frameless function or not.
+
+ * core.c (core_open, core_close, core_xfer_memory): Move
+ section table pointers and bfd* into the target_ops.
+ (core_open): Allow errors in shared lib reading, etc.
+ (core_files_info): Describe shared library sections.
+
+ * exec.c (exec_open, exec_close, exec_xfer_memory, xfer_memory,
+ exec_files_info, set_section_command): Move section table
+ pointers and bfd* into the target_ops.
+ (add_to_section_table): Add BFD to section table.
+
+ * target.c (target_xfer_memory, target_info): Pass target to
+ xfer_memory and target_info functions.
+ * target.h: ''
+
+ * gdbcore.h: Move struct section_table.
+ * target.h: New home of struct section_table.
+
+ * solib.c (solib_add): New argument is the target_ops whose
+ section list is to be added to, if any. Reallocate the
+ sections in that target to add any that come from shared libs.
+ (throughout) so_sections renamed to sections.
+ (solib_xfer_memory): Deleted.
+ * tm-sunos.h (SOLIB_ADD): Add target argument.
+ (SOLIB_XFER_MEMORY): Delete.
+
+ * core.c, exec.c, inftarg.c, remote-eb.c, remote-nindy.c,
+ remote-vx.c, remote.c, target.c, target.h: Remove add_syms vector
+ from target_ops. It's the same on all targets. Add two section
+ pointers to target_ops.
+
+ * stack.c (find_relative_frame): Dump ancient algorithm for
+ "down", just use handy "next" pointers.
+ (frame_command): Don't error if there is no stack; let user
+ set one.
+
+ * inflow.c (new_tty_prefork, new_tty): New prefork routine
+ modifies static state in the parent process; new_tty itself
+ runs in the child and modifies the child's file descriptors
+ to match the saved static state.
+ * infrun.c (child_create_inferior): Call new_tty_prefork,
+ fork, then new_tty.
+
+ * infptrace.c (child_xfer_memory): Add ignored target arg.
+ * remote-eb.c (eb_xfer_inferior_memory): ''
+ * remote-nindy.c (nindy_xfer_inferior_memory): ''
+ * remote-vx.c (vx_xfer_memory): ''
+ * remote.c (remote_xfer_memory): ''. Rename from
+ remote_xfer_inferior_memory.
+
+ * main.c (main): Only try to attach "corefile" argument if
+ it starts with a digit.
+
+ * symfile.c (symbol_reloading): New "set/show" variable.
+ (symbol_file_add): Shorten message about symbol reading.
+ (add_symbol_file_command): Merge with add_syms_addr_command,
+ since this should work on all targets now.
+ (stop_whining): Default to zero, to shut up complaints
+ about bad symbol tables on many systems.
+ (free_named_symtabs): Just exit unless symbol_reloading.
+
+ * xm-sun3os4.h, xm-sun4os4.h: Define BROKEN_LARGE_ALLOCA,
+ and add comment explaining shared library screw.
+
+ * source.c: #if defined => #ifdef.
+
+Thu Aug 8 12:23:19 1991 John Gilmore (gnu at cygint.cygnus.com)
+
+ * doc/gdbint.texinfo: Improve doc on porting to new OS's.
+
+Tue Aug 6 17:16:15 1991 Roland H. Pesch (pesch at cygint.cygnus.com)
+
+ * doc/rdl-apps.texinfo: provide default readline-appendix finder
+ (doc/Makefile knows how to make one for local config)
+
+ * Makefile.in: use doc/Makefile for doc targets
+
+ * doc/Makefile: GDB documentation now has its own Makefile
+ doc/refcard.tex: renamed from "gdbrc.tex"
+ doc/gdbint.texinfo: add markup in "Cleanups" chapter
+
+
+Fri Aug 2 00:13:06 1991 John Gilmore (gnu at cygint.cygnus.com)
+
+ * values.c (baseclass_addr): When reading target memory, use the
+ length of the basetype, not the upper type. We've only malloc'd
+ enough space for the basetype, leading to errors in free().
+
+ * expprint.c (print_subexp): Print UNOP_MEMVAL of an OP_LONG that
+ ends up as a function specially, since we know the actual type of
+ the pointed-to address. This (somewhat) fixes display of
+ expressions that include misc_function_vector names. Try `cond 1
+ !strcmp("a","b")' then `i b'.
+
+ * infrun.c: Move DO_DEFERRED_STORES from proceed() to resume().
+ The child can be proceeded from inside wait_for_inferior in
+ evaluating breakpoint conditions, and DO_DEFERRED_STORES was
+ getting skipped in that case.
+
+ * expprint.c (print_subexp): Use filtered output, since the
+ subroutines we call use it, otherwise the output is horribly
+ mangled, since output of wrappable stuff comes out late.
+
+ * Makefile.in: Bump VERSION to 3.98.1
+
+ * infrun.c (child_create_process): Use execlp to find the
+ shell to exec our target program. This requires some fiddling
+ with `environ' since there is no execlpe().
+
+Thu Aug 1 15:35:17 1991 Roland H. Pesch (pesch at fowanton.cygnus.com)
+
+ * Makefile.in, doc/gdbrc.tex, doc/rc-* (new files):
+ Minor rearrangement of refcard permits two new make targets--
+ gdbrc.dvi DVI output for refcard, using CM fonts
+ gdbrc.ps PostScript refcard, using PS fonts
+
+Wed Jul 31 16:46:21 1991 John Gilmore (gnu at cygint.cygnus.com)
+
+ * GDB-3.98 release.
+
+ * TODO, Projects, WHATS.NEW, README: Update for gdb-3.98.
+ * Makefile.in (gdb-all.texinfo): Avoid touching file if M4 dies.
+
+Wed Jul 31 16:35:58 1991 Roland H. Pesch (pesch at cygint.cygnus.com)
+
+ * doc/gdb.texinfo: last changes for release.
+ Minor typo and formatting fixes; incorporated most fixes remaining from
+ filed mail commenting on earlier drafts.
+
+ Added warnings: pipes don't work in run command;
+ conditions are converse of assertions;
+ step over fn without debug info goes to next fn;
+ vars may have "wrong" values near fn entrance, exit
+
+ Added example from Kingston on printing repeated nonadjacent values
+
+ Added explicit mention that in Emacs gdb mode C-c and C-z are like
+ shell mode for signals
+
+ Renamed "Stepping and Continuing" to "Continuing and Stepping" so it
+ doesn't sound so much like its parent "Stopping and Continuing"; also
+ moved entries on continue to top of section, so they don't get lost.
+
+ Improved installation directions in appendix, added manual formatting
+ instructions
+
+Tue Jul 30 17:26:39 1991 John Gilmore (gnu at cygint.cygnus.com)
+
+ * configure.in: Remove xm.h and tm.h even if we aren't linking
+ new ones, so "./configure sun4; ./configure none" does the right
+ thing. Assume that alldeps.mak and depend are already built in
+ srcdir, and avoid running "make" (particularly "make depend",
+ which involves "gcc") from inside configure. Build Makefile
+ directly rather than building Makefile.conf first.
+ * configure: Regenerate with above changes.
+ * Makefile.in: Use $(BISON) to find bison. Roll VERSION
+ to 3.98. Revise gdb.tar.Z procedure to produce a file
+ called gdb-$(VERSION).tar.Z but which unpacks into a
+ directory called "gdb". Move non-source files out of
+ $(SFILES_SUBDIR). Pretty up alldeps.mak with comments.
+ (depend): Don't try to do "gcc expread.y".
+ (expread.o): Update dependencies by hand.
+
+Mon Jul 29 15:21:09 1991 Roland H. Pesch (pesch at cygint.cygnus.com)
+
+ * doc/gdb.texinfo:
+ Fixed a variety of small typos that prevented info from formatting
+ cleanly; altered too-long heading for GPL Appendix, as discussed
+ w/RMS; Changed date on cover to July 91.
+
+Fri Jul 26 13:20:02 1991 Roland H. Pesch (pesch at cygint.cygnus.com)
+
+ * doc/gdb.texinfo:
+ (1) Applied some fixes due to comments from Larry Breed (easier ones
+ through chapsec 5.2)
+ (2) Eliminated use of @footnote---had my doubts about it anyways, and
+ it's broken in latest texinfo
+ (3) Introduced *some* use of [] for optional arguments, where
+ explanation is not simpler by listing cmd w arg and cmd w/out arg
+ separately. Still not using @deffn.
+ (4) Dropped in GPL-2. NOTE: one of GPL-2 or texinfo is broken; a
+ couple of headings are too long. Need patches to texinfo or revision
+ to GPL-2.
+
+ * Partial update to README (which still needs work for this
+ release!): (1) use of configure corrected for new script,
+ (2) "make gdb.dvi" and "make gdb.info" mentioned.
+
+Wed Jul 24 06:44:02 1991 John Gilmore (gnu at cygint.cygnus.com)
+
+ * symtab.c (lookup_symbol): Don't complain right off about
+ no debug symbols; use the misc function vector first.
+ (list_symbols): Use misc function vector to find symbols
+ that don't have debug info, and print them.
+ (find_pc_symtab): Temporarily avoid fatal() when psymtab
+ PC range doesn't match symtab PC range, as it does on the
+ MIPS because our symtab reading isn't perfect.
+
+ * dbxread.c (dbx_symfile_read): Make warning about
+ "no debug symbols" slightly nicer.
+
+ * source.c (select_source_symtab): If "main" symbol exists,
+ but decode_line_spec can't find line info, don't just return
+ a zero; try other source symtabs or give an error.
+
+ * mipsread.c (parse_partial_symbols): Sort the psymtabs by
+ their low addresses first, then rip through fixing high addrs.
+
+ * ns32k-opcode.h (sfsr): Bugfix from Rune Nerg}rd,
+ <runene@ifi.uio.no>.
+ (NS32K_SVC_IMMED_OPERANDS): Reverse the #ifndef.
+
+Tue Jul 23 18:52:43 1991 Roland H. Pesch (pesch at cygint.cygnus.com)
+
+ * Minor, mostly mechanical, cleanup of doc subdir for clean
+ makeinfo'ing and TeXing; also ensured gdb-all.texinfo (post-m4)
+ and gdb.info (post- texinfo2 makeinfo) generated for distribution.
+
+Sun Jul 21 03:54:52 1991 John Gilmore (gnu at cygint.cygnus.com)
+
+ Mostly MIPS and general symbol-reading fixups.
+
+ * doc/gdbint.texinfo: Add documentation on symbol-reading
+ interface.
+
+ * mipsread.c: Remove kludges around #include "ecoff.h".
+ Remove redefinitions of a_magic, etc, no longer used.
+ (parse_symbol, ): Convert "Internal:" printfs to complain()ts.
+ Fix global overview comments to match symfile.c protocol.
+ (mipscoff_new_init): Eliminate cur_hdr if we have one.
+ (mipscoff_symfile_read): Eliminate unused code. Avoid
+ sorting all the symtabs, when all we have read here is psymtabs.
+ The symtabs are sorted as they are created anyway. Tell
+ condense_misc_bunches whether we're mainline.
+ (psymtab_to_symtab_1): Pass filename when recursing, to make
+ stack trace more informative.
+ (parse_partial_symbols): Assume cur_hdr as argument.
+ (read_mips_symtab): Don't clobber cur_hdr, so it can be freed.
+ Pass cur_hdr implicitly to parse_partial_symbols. Avoid checking
+ the TYPE_NAME of char *, since that's done in symfile.c.
+ (free_numargs, parse_symbol, add_symbol, add_block,
+ shrink_linetable): Declare these fns void.
+ (upgrade_type): Convert tree of if's to switch. Clean up
+ bogus "off == 0" handling with a complaint. Avoid setting
+ field bitpos and bitsize of array with lower and upper bounds.
+ Check specified bitsize of elements against their actual type's
+ bitsize, and complain if different. Complain about unknown
+ type qualifiers.
+ (parse_fdr): Don't assume sizeof(char *) == sizeof (struct *).
+ (psymtab_to_symtab_1): Print names of subsidiary files that
+ are being read in. FIXME, we read far too many files. This code
+ is not the problem, the problem is in parse_fdr where the psymtabs
+ are set up.
+ (cross_ref): Result should indicate that we used one aux entry
+ normally, or two if we encountered a "next" entry. This used
+ to leave the caller pointing at the wrong aux entry.
+ (add_symbol): If overflowed cur_block, reallocate it larger,
+ chase all pointers to it, and complain(), rather than clobber memory.
+ (shrink_block): Use xrealloc rather than xmalloc-and-copy.
+ (new_field): Only allocate one field initially, not two.
+ Pull ++ out of macro argument. Simplify.
+ (_initialize_mipsread): Avoid initialization of importd
+ global_psymbols and static_psymbols.
+
+ * symfile.c (psymtab_to_symtab): Depend on XXX_psymtab_to_symtab
+ to properly set pst->symtab; avoid searching for it.
+ (symfile_fns): Improve comments, add a FIXME.
+ * dbxread.c: Update comments to reflect symfile protocol.
+ (read_ofile_symtab, end_symtab): Return the symtab.
+ (psymtab_to_symtab_1): Set pst->symtab.
+
+ * coffread.c (coff_symfile_read): tell condense_misc_bunches
+ whether we're mainline.
+
+ * symfile.h (sym_fns): Remove unused sym_discard member.
+ * coffread.c, mipsread.c, dbxread.c: Remove XXX_symfile_discard.
+
+ * mtrace.c (mtrace): Take effect if mallwatch is set, even if
+ the environment variable is not.
+ * infcmd.c (finish_command): Use filtered printfs.
+ * cplus-dem.c: Add struct tags to a few unnamed structs.
+ * valops.c (value_coerce_array): Improve comments.
+ * valprint.c (type_print_varspec_suffix): Print array size only
+ if greater than zero.
+ * m88k-tdep.c: Shift some lines left by one space, that had
+ apparently been trashed at some point.
+ * TODO: More things to do, a few got done.
+
+Thu Jul 18 22:46:05 1991 John Gilmore (gnu at cygint.cygnus.com)
+
+ * symtab.h (LOC_EXTERNAL): Eliminate in favor of LOC_STATIC.
+ (ldsymoff, ldsymlen, globals_offset, statics_offset): Improve
+ comments.
+ * dbxread.c (read_dbx_symtab): LOC_EXTERNAL -> LOC_STATIC.
+ * expread.y, findvar.c, symmisc.c: Ditto.
+ * printcmd.c (address_info): Update printed forms of LOC_
+ symbols. Elim LOC_EXTERNAL.
+ (print_frame_args): Keep track of param stack offsets before
+ re-looking up to find the local register param is kept in.
+
+ * mipsread.c: Use <symconst.h> and <sym.h> rather than <syms.h>.
+ Further integration of mipsread into gdb. Eliminate unused
+ routines, duplicate declarations. Handle static symbols in
+ psymtabs as well as external symbols. When reading symtabs,
+ insert symbols into the correct block (global, static, or a local
+ block).
+ (read_mips_symtab, parse_partial_symbols): Don't pass useless
+ "incremental" arg.
+ (mipscoff_symfile_read): Don't call select_source_symtab.
+ (parse_symbol): Use SYMBOL_VALUE_ADDRESS where appropriate,
+ rather than SYMBOL_VALUE.
+ (parse_external): Comment clobbering of top_stack.
+ (parse_partial_symbols): Update comments. Allocate and parse
+ static symbols as well as external symbols. FIXME, enum values
+ are not handled in this pass, but should be. Inline new_psymbol.
+ Use SYMBOL_VALUE_ADDRESS.
+ (psymtab_to_symtab_1): Read symbols into global static block
+ by default (until enter some function's local block context).
+ (sort_blocks): Clean up STATIC_BLOCK as well as GLOBAL_BLOCK.
+ (destroy_all_symtabs, new_psymbol): Eliminate, unused.
+
+ * source.c (select_source_symtab): Select a source symtab
+ from either the symtabs or, failing that, the psymtabs.
+ (list_command): Update error message.
+ (forward_search_command, reverse_search_command): Use getc, not
+ fgetc, for speed. FIXME, add comment about buffers that die if
+ overrun by long line.
+
+ * values.c (unpack_field_as_long, modify_field): Avoid shifting
+ by an entire word, which is not portable, if we have a 32-bit
+ field. (Code in dbxread.c already turns such bitfields, if
+ aligned, into ordinary ints, but fixing this will help for other
+ symbol formats and for future changes.)
+ * core.c (core_open): Handle ANSI const brain death.
+ * utils.c (vprintf): Fix varargs typo.
+
+Sun Jul 14 00:42:53 1991 John Gilmore (gnu at cygint.cygnus.com)
+
+ * findvar.c (find_var_value): Handle &function better.
+ * TODO: Document work needed on &fn and &array.
+ * printcmd.c (print_address_symbolic): New arg is the prefix
+ to print if a name is printed.
+ (print_address_demangle): Honor "set print address" now.
+ Use new arg above to improve spacing of output.
+ * valprint.c (val_print): When printing function pointers,
+ print symbolic form too.
+ * breakpoint.c (breakpoint_1): Use new print_address_symbolic.
+
+Mon Jul 8 19:02:46 1991 John Gilmore (gnu at cygint.cygnus.com)
+
+ * core.c (memory_error): Reword error msg to mislead less.
+
+ * mips-pinsn.c (print_insn_arg 'd'): Print $ with reg name.
+
+ * mipsread.c (read_mips_symtab, read_the_mips_symtab,
+ parse_partial_symbols): Use newer BFD internals (external_filehdr
+ and external_aouthdr), byte-swap the fields that we care about
+ before using them, and make the file header data local to
+ read_the_mips_symtab rather than global.
+
+Sat Jul 6 01:34:15 1991 John Gilmore (gnu at cygint.cygnus.com)
+
+ * ns32k-opcode.h (movmw, movmd): Fix opcodes. Bug fix
+ from Rune Nerg}rd <runene@ifi.uio.no> on 5 Jul 1991.
+
+ * main.c (command_line_input): Flush stdout and stderr
+ before every call to readline. This reportedly fixes a bug
+ that comes up in Sys V running emacs-gdb and/or xxgdb,
+ when stdin/out are pipes or sockets.
+
+Thu Jul 4 14:47:06 1991 John Gilmore (gnu at cygint.cygnus.com)
+
+ * configure.in, Makefile.in: Avoid rebuilding "depend" as much.
+ Avoid declaring Makefile dependencies, because GNU Make stupidly
+ tries to update it if we do.
+
+ * coffread.c: Revise for minor changes to bfd internal coff
+ indexes.
+
+ * configure: If -template= is given a relative path, make it
+ absolute before recurring in subdirectories.
+
+ * configure, configure.in, Makefile.in: Install "configure" script
+ as replacement for config.gdb.
+ * config.gdb, Makefile.dist, Makefile.sdir: Remove
+ * README: Update for configure, mostly. FIXME.
+
+ * Add dec3100 as equivalent to littlemips. Indicate in all host &
+ target config files that they are for the host. When the lines
+ get copied into the Makefile, this makes it more obvious what's
+ up.
+
+Mon Jun 24 23:49:07 1991 John Gilmore (gnu at cygint.cygnus.com)
+
+ * sparc-opcode.h (trap opcodes): Avoid leading spaces or
+ tabs, which end up in the disassembler output inadvertently.
+
+Wed May 29 23:01:03 1991 John Gilmore (gnu at cygint.cygnus.com)
+
+ Make it compile cleanly in an ANSI GCC2 environment.
+
+ * blockframe.c: <stdio.h>
+ * cplus-dem.c: free takes a void *, ifdef __STDC__
+ * dbxread.c (read_huge_number): avoid gcc2 bug hoisting calc of
+ LONG_MAX/radix.
+ * defs.h (alloca): Avoid doing anything if alloca already def'd.
+ * stddef.h, stdlib.h: Remove these files.
+ * symtab.c: Avoid declaring qsort, close.
+ * symfile.c: Avoid declaring close.
+ * utils.c (vprintf): Declare "ap" arg as proper va_alist.
+ * sparc-tdep.c: Avoid including lots of Sun-host-specific files.
+
+ Assorted other changes.
+ * dbxread.c: include "libaout.h", not "liba.out.h".
+ * printcmd.c (print_frame_args): Set recurse properly for
+ indentation of struct and array parameters.
+ * valops.c (value_cast): Allow cast to void.
+ * infrun.c (resume): If NO_SINGLE_STEP, call machine dependent
+ single_step() in a target-independent fashion.
+ * sparc-tdep.c (single_step): Don't call ptrace ourselves, just
+ set up to be ready to continue. This makes us target independent.
+ * infptrace.c (child_resume): Remove call to single_step; now
+ can single step a SPARC target of any kind.
+
+Wed May 22 18:18:24 1991 Roland H. Pesch (pesch at fowanton.cygnus.com)
+
+ * Makefile.dist, doc/gdb.texinfo, doc/*-m4.texinfo: split up GDB
+ docn into separate sections---basically chapters, plus two loose
+ pieces that can be configured to go in different places. This
+ allows GNU m4 to preprocess the manual without coredumping.
+
+ * Makefile.dist: tell TeX where to find texinfo.
+
+Mon May 20 12:15:04 1991 Roland H. Pesch (pesch at fowanton.cygnus.com)
+
+ * Makefile.dist, doc/gdb.texinfo: respectively create, and use,
+ the new target "rdl-apps.texinfo" which captures the Makefile
+ variable that records where to find the Readline libraries.
+
+Sun May 19 05:36:59 1991 John Gilmore (gnu at cygint.cygnus.com)
+
+ * tahoe-pinsn.c: #include "tahoe-opcode.h", not "opcode.h".
+ * tm-tahoe.h (FIX_CALL_DUMMY): Ignore more parameters.
+ * defs.h (const, volatile): Only define if not already defined.
+ * Makefile.dist (gdb.tar.Z): Create doc subdir w/out CVS/RCS crud.
+
+ * README: Update for release 3.95.
+ * config.gdb: Don't create readline dir in subdir builds.
+ * main.c: Include with "..." form for non-system include files,
+ so "gcc -MM" for "make depend" works.
+ Include readline files with "...h" rather than <readline/...h>.
+ * mipsread.c: Include "ecoff.h" rather than "intel-coff.h".
+
+ * coffread.c: Undo minor damage done by Rich Pixley. Use
+ different internal and external representations of COFF
+ data structures. Use new BFD routines for swapping them in and
+ out.
+ * symfile.c (free_named_symtabs): Avoid freeing file names that
+ are null or empty. Old i960 tools seem to produce files that
+ claim to have empty names, causing each successive file read
+ to blow away the previous one.
+ * sparc-xdep.c (deferred_stores): Repair minor damage by Rich.
+ Move deferred_stores to top of file, but don't separate its
+ #define's from its variable. Add commentary.
+ * Makefile.dist: Fix Rich damage; undo "configure" changes in
+ favor of keeping the (working) config.gdb. Move readline
+ library up a notch.
+
+Fri May 17 12:49:56 1991 Per Bothner (via gnu at cygint.cygnus.com)
+
+ * dbxread.c (read_struct_type): Try to handle g++ version 1 MI
+ debug info.
+ * infptrace.c (fetch_registers): no result, since now void.
+ * tconfig/news: target depends on m68k-tdep too.
+
+Fri May 17 14:40:14 1991 Roland H. Pesch (pesch at fowanton.cygnus.com)
+
+ * Makefile.dist: added readline/inc-*.texinfo to dependencies for
+ gdb.dvi target
+
+ * readline/inc-history.texinfo, readline/inc-readline.texinfo:
+ applied various small fixes due to or inspired by RMS comments
+
+ * doc/gdb.texinfo: finished using all RMS comments, save those for
+ appendices on readline and cmd history (which are in other source
+ files)
+
+Thu May 16 18:06:05 1991 Roland H. Pesch (pesch at fowanton.cygnus.com)
+
+ * doc/gdb.texinfo: (1) Updated w/ref to RMS comments through
+ chapter 9; (2) documented 'break' command's menu mode for
+ overloaded names, in response to hgs problem report C++ p-31
+
+Wed May 15 11:02:48 1991 Roland H. Pesch (pesch at fowanton.cygnus.com)
+
+ * doc/gdb.texinfo: (1) better introductory example; (2) more
+ consistent use of @code, @samp, @file, @kbd throughout; small
+ cleanups to first three nodes; (3) new "Contributors" node;
+ (4) Appendix, Renamed Commands; (5) divert specialized startup
+ instructions to "Targets" chapter for generic manuals, while
+ leaving them up front for manuals specific to specialized
+ environments; (6) apply fixes from RMS comments through chapter 4.
+
+ * pretex.m4: modify explanatory text slightly (and redefine
+ "regexp") to keep GNU m4 from complaining. (It still crashes
+ later, but one step at a time...)
+
+Wed May 15 10:32:12 1991 John Gilmore (gnu at cygint.cygnus.com)
+
+ * readline/readline.c (update_line): Avoid dereferencing a pointer
+ before comparing it to its bounds. Saber caught this.
+ (init_terminal_io): Don't set BC from the "pc=" termcap variable,
+ and only set PC if tgetstr returned non-null. Saber caught this.
+
+Tue May 14 16:29:53 PDT 1991 Roland Pesch (pesch at cygint.cygnus.com)
+
+ * Makefile.dist: put gdb.dvi stuff (updated to use M4 preprocessor
+ stuff for config manual) here where it counts; updated
+ to use new subdir structure (gdb/doc/).
+
+ * Makefile: generated from above via
+ config.gdb none
+ before checkin
+
+ * gdbint.texinfo: added instructions on generating gdb.info* files
+ locally for release. These are ordinary info
+ files, formatted from gdb.texinfo (via gdb-all.texinfo, see
+ Makefile)---but due to use of texinfo 2, can't count on makeinfo
+ to generate these, so we distribute them already formatted.
+
+ * gdb.texinfo: included full Info node and menu crud (as generated
+ by C-u M-x texinfo-master-menu using the texinfo-2 elisp code).
+
+ * Makefile: updated "gdb.dvi" target to use M4 preprocessor;
+ put in comments-for-future gdb.info target (one day makeinfo will
+ work again).
+
+Tue May 14 13:51:36 PDT 1991 Roland Pesch (pesch at cygint.cygnus.com)
+
+ * gdb.texinfo: Updated to include new or old undocumented
+ commands, at least the following (perhaps some others I forgot to
+ record): info f, info float, info path, info program, info s, info
+ set, info source, info terminal, info types, info user, set/show
+ print object.
+ Also covered all recent GDB command renames for v4.
+
+Mon May 13 14:57:46 1991 John Gilmore (gnu at cygint.cygnus.com)
+
+ * mipsread.c: Rather than keeping count of how many symtabs
+ and psymtabs we have, for sorting purposes, count them when
+ we need to sort. This fixes bug in rereading of symbol tables.
+
+Fri May 10 15:43:33 PDT 1991 Roland Pesch (pesch at cygint.cygnus.com)
+
+ * infcmd.c: renamed "info path" to "show paths"
+ * gdbrc.tex: documented above.
+
+Wed May 8 04:51:11 1991 John Gilmore (gnu at cygint.cygnus.com)
+
+ * remote.c: Fix comments.
+ * utils.c (error): Force out any pending wrap output.
+
+Sat May 4 11:11:07 1991 John Gilmore (gnu at cygint.cygnus.com)
+
+ * Makefile.dist: Roll VERSION to 3.95.
+ Fix up "saber_gdb" to work again.
+ * saber.suppress: Update.
+
+ * coffread.c, exec.c, infptrace.c, inftarg.c, remote.c, solib.c,
+ symtab.h, target.c, target.h: Lint.
+ * core.c: setup and select frame after reading shared libs,
+ else reading shared libs will clobber them. Lint.
+ * utils.c (error): Force out any buffered wrap text.
+
+Fri May 3 22:01:56 1991 John Gilmore (gnu at cygint.cygnus.com)
+
+ * remote.c: Remove decls of memory_insert_breakpoint
+ and memory_remove_breakpoint, no longer used. (Suggestion of
+ Jan Norden).
+
+ * Makefile.dist: use ${subdir} in paths of BFD and LIBIBERTY,
+ to make it easier to interface to "configure"'d libraries.
+
+Fri May 3 13:10:01 PDT 1991 Roland Pesch (pesch at fowanton.cygnus.com)
+
+ * valprint.c: introduce "set p", "set pr", "show p" and "show pr" as
+ aliases for set/show print.
+
+Thu May 2 11:22:02 1991 Jim Kingdon (kingdon at cygint.cygnus.com)
+
+ * coffread.c (coff_sym_fns) [TDESC]: Make the type be m88kbcs.
+
+ * m88k-tdep.c (IEEE_isNAN): New function.
+
+ * infrun.c, m88k-tdep.c, m88k-xdep.c: Change
+ initialize_{tdesc,dcontext} to init_{tdesc,dcontext}.
+
+ * infrun.c [TDESC]: Add a bunch of crud.
+
+ * xm-88k.h [__GNUC__]: Don't define memset.
+
+ * m88k-xdep.c: #if 0 out push_breakpoint.
+
+ * tm-88k.h: Define GET_SAVED_REGISTER.
+
+ * tm-88k.h: Define DGUX.
+
+ * m88k-opcode.h (UEXT, SEXT, MAKE): Put parentheses around arguments.
+
+ * m88k-pinsn.c (sprint_address): Declare at top of file.
+
+ * m88k-xdep.c: #if 0 out core_file_command.
+
+ * values.c ({unpack_,value_as_}pointer): Just call
+ {unpack_,value_as_}long (for now anyway).
+
+ * m88k-tdep.c (get_saved_register): Make get_reg a dc_word_t (*)().
+ (psr_register): Change return type to dc_word_t.
+
+ * m88k-tdep.c (tdesc_read_function): Comment out call to ptrace.
+
+ * m88k-tdep.c (get_saved_register): Add lvalp parameter.
+
+ * gdbcore.h (write_memory): Don't prototype it.
+
+ * tm-88k.h, m88k-tdep.c: Make stack_error, stack_jmp global.
+ m88k-xdep.c: Don't mention stack_error.
+
+ * {x,t}config/m88k ({X,T}DEPFILES): Add missing files.
+
+ * mtrace.c: Don't typedef things like size_t, just #define them.
+
+ * coffread.c [TDESC]: #if 0 out references to coffsyn.
+
+ * symtab.h (struct symtab): Include EXTRA_SYMTAB_INFO.
+ tm-88k.h: Define EXTRA_SYMTAB_INFO.
+
+ * coffread.c [TDESC]: Include "tdesc.h" and make tdesc_handle
+ dc_dcontext_t not int.
+
+ * coffread.c [TDESC]: Use system include files not <intel-coff.h>.
+
+ * coffread.c [TDESC]: Move setting of debug_info from
+ coff_symfile_read to find_linenos and make it work with BFD.
+
+ * cplus-dem.c [__STDC__]: Make x{m,re}alloc return void*.
+
+ * signame.c: Cast const char* to char* when assigning to sys_siglist.
+
+ * utils.c (strsave): Make arg const char* not char*.
+
+ * infrun.c (wait_for_inferior) [SHIFT_INSN_REGS]: Use
+ bpstat_explains_signal (stop_bpstat) not stop_breakpoint.
+
+ * tm-88k.h (START_INFERIOR_HOOK): Make tdesc_handle a dc_handle_t.
+
+ * tm-88k.h (EXTRACT_RETURN_VALUE): Use char * not void *.
+
+ * findvar.c (read_var_value, case LOC_CONST_BYTES): Put the address
+ in a char *, not a CORE_ADDR. Use SYMBOL_VALUE_BYTES.
+
+ * tm-88k.h (INIT_EXTRA_FRAME_INFO): Use fci not prev (fci is
+ prev except from create_new_frame). Make next_frame a
+ local variable.
+ Declare get_prev_context.
+ {x,t}m-88k.h: Enclose USG and BCS defines in #if !defined.
+ m88k-{opcode.h,pinsn.c,xdep.c,tdep.c}: New files (same contents as
+ before; they had just been left out of the distribution for a long
+ time).
+
+Thu May 2 17:53:56 1991 John Gilmore (gnu at cygint.cygnus.com)
+
+ Mips bringup and general cleanup
+
+ * cplus-dem.c: Move CPLUS_MARKER define to after defs.h.
+ * infptrace.c (PT_WRITE_D, PT_READ_D): Use correct values.
+ (This still doesn't seem to make MIPS bkpts work.)
+ * mipsread.c: Remove dup "Reading symbol data..." msg.
+ (symbol_file_command, add_file_command): Remove, obsol.
+ * printcmd.c (ptype_command): Say "an enum" rather than "a enum".
+ Wrap output appropriately.
+ * stack.c (locals_info, catch_info, args_info): Check
+ selected_frame rather than target_has_stack or coredumping.
+ * valprint.c (type_print_varspec_suffix): Wrap "ptype" output of
+ enums appropriately.
+
+Wed May 1 14:10:22 1991 Jim Kingdon (kingdon at cygint.cygnus.com)
+
+ * signame.c: Include defs.h and param.h.
+
+ * cplus-dem.c: Include defs.h and param.h.
+ Makefile.dist: Don't hack in the "param.h".
+ param.h: Don't include defs.h.
+
+ * expread.y: Use a union to deal with the fact that type_stack
+ can have both ints and enum type_pieces in it.
+ ({push,pop}_type_int): New functions.
+
+Tue Apr 30 13:18:58 1991 Jim Kingdon (kingdon at cygint.cygnus.com)
+
+ * cplus-dem.c (cplus_mangle_opname): Don't call error.
+ values.c (check_stub_method): Call error if NULL return from
+ cplus_mangle_opname.
+
+ * blockframe.c, breakpoint.c, core.c, command.c, findvar.c,
+ eval.c, expprint.c, infcmd.c, infrun.c, main.c, printcmd.c,
+ remote.c, source.c, stack.c, dbxread.c, coffread.c, symfile.h,
+ symfile.c, utils.c, valarith.c, values.c, valops.c, tm-68k.h,
+ target.c, inftarg.c, ieee-float.c, environ.c, defs.h,
+ command.h, inferior.h, gdbcore.h, symtab.h, expression.h,
+ symtab.c, cplus-dem.c, value.h, expread.y, valprint.c,
+ copying.awk, solib.c, inflow.c, symmisc.c
+ : Lint. Use read_memory not read_memory_integer on CORE_ADDR's.
+ Use {value_as,unpack}_pointer (added to values.c)
+ not {value_as,unpack}_long on CORE_ADDR's.
+ Use longest_to_int (added to defs.h) instead of cast to int.
+ Remove from_tty arg to mod_path.
+ Put symfile_bfd in {coff,dbx}read.c not symfile.h.
+ Use OP_NULL instead of 0 where dummy enum exp_opcode needed.
+
+ * tm-sparc.h: Remove GET_RWINDOW_REG.
+ (FRAME_CHAIN): Call sparc_frame_chain.
+ sparc-tdep.c (sparc_frame_chain): New function.
+ tm-sparc.h (EXTRACT_STRUCT_VALUE_ADDRESS): call
+ sparc_extract_struct_value_address (added to sparc-tdep.c).
+
+ * xm-sun386.h: Don't define SET_STACK_LIMIT_HUGE.
+
+Tue Apr 30 13:13:33 1991 Michael Tiemann (tiemann at cygint.cygnus.com)
+
+ * valprint.c (type_print_base): If the type being printed is a
+ struct containing undefined types, print "<undefine type>"
+ as the type instead of crashing.
+ * values.c (value_headof): Get the vtable pointer taking
+ TYPE_VPTR_BASETYPE into account.
+ * symtab.c, symtab.h, dbxread.c: Fix various whitespace splotches.
+
+Mon Apr 29 13:22:51 1991 Jim Kingdon (kingdon at cygint.cygnus.com)
+
+ * Move BROKEN_LARGE_ALLOCA from tm-sun386.h to xm-sun386.h.
+
+ * sun386-xdep.c [!GDB_TARGET_IS_SUN386]: Just provide empty
+ functions which don't do anything.
+ tm-sun386.h: Define GDB_TARGET_IS_SUN386.
+
+ * Makefile.dist: Add comment about tm-sun3os4.h: tm-sun3.h, etc.
+
+ * sun3-xdep.c, tm-sun3.h, tm-68k.h: Change TARGET_SUN3 to
+ GDB_TARGET_IS_SUN3.
+
+ * infrun.c: Don't include sys/user.h and friends (wrong for
+ cross-debugging and not necessary anymore (see IN_SIGTRAMP in
+ xm-vax.h)).
+ [SET_STACK_LIMIT_HUGE]: Include <sys/{resource,time}.h>.
+ xm-tahoe.h: Don't define _DIRENT_.
+
+ * xm-tahoe.h: Remove USE_OLD_TTY (not needed now that terminal.h
+ includes sgtty.h before sys/ioctl.h).
+
+Sun Apr 28 22:04:47 1991 Jim Kingdon (kingdon at cygint.cygnus.com)
+
+ * param-no-tm.h: Make BITS_BIG_ENDIAN defined to 0/1, not defined
+ or not defined. Don't define it based on TARGET_BYTE_ORDER if
+ it's already defined (in the tm.h file).
+ mips-opcode.h (BIT_FIELDS_*),
+ values.c (modify_field, unpack_field_as_long):
+ Use #if BITS_BIG_ENDIAN not #ifdef BITS_BIG_ENDIAN.
+ {x,t}m-tahoe.h, tahoe-pinsn.c, tahoe-opcode.h: New files.
+
+Fri Apr 26 12:02:06 1991 Jim Kingdon (kingdon at cygint.cygnus.com)
+
+ * tm-sparc.h: Add comments about gcc version 2 and structure passing.
+
+ * xconfig/i386v{,32}{,-g}: Add XM_CFLAGS=-Dgetpagesize()=4096.
+ gmalloc.c: #if 0 out !HAVE_GETPAGESIZE code.
+
+ * expread.y (abs_decl): Accept '&' and '&' abs_decl.
+
+ * symtab.c, symtab.h: Have a builtin_type_{,unsigned_}long_long
+ regardless of LONG_LONG.
+ defs.h (TARGET_LONG_LONG_BIT): New macro.
+ expread.y (typebase): Add {unsigned,} long long {,int}.
+
+Thu Apr 25 12:31:22 1991 Jim Kingdon (kingdon at cygint.cygnus.com)
+
+ * valops.c (typecmp): If t2 == 0, return 1.
+
+Wed Apr 24 09:45:17 1991 Jim Kingdon (kingdon at cygint.cygnus.com)
+ Changes from Tiemann:
+ * cplus-dem.c (optable): Add "nw", "dl", "compound".
+ (cplus_mangle_opname): New function.
+ (do_type): Add case 'Q'.
+ * values.c (check_stub_method): Do lookup_method_type and stuff
+ rather than smash_to_method_type.
+ symtab.c, symtab.h (allocate_stub_method): New function.
+ dbxread.c (read_type): If we get "##", don't lookup_function_type
+ and start clobbering it; allocate_stub_method instead.
+ * printcmd.c (x_command): Dereference references.
+ * valprint.c (type_print_varspec_prefix, case TYPE_CODE_METHOD):
+ Don't print " " type_print_base (...) "::" if !passed_a_ptr.
+ * dbxread.c (read_struct_type): Put "op$" instead of "operator"
+ in the symbol table.
+ * values.c (check_stub_method): Deal with operator names.
+ * valprint.c (cplus_val_print): Check for error in baseclass_addr.
+ * values.c: Move declaration of cplus_demangle to top of file.
+ * values.c (baseclass_addr): If can't read memory, set *ERRP
+ rather than calling error().
+ * value.h: Remove redundant declaration of value_static_field.
+ * values.c (value_static_field): Recursively check all baseclasses.
+ Return NULL if not found.
+ * values.c, value.h: New functions value_{headof,from_vtable_info}.
+ * valprint.c (val_print): Print out first element of vtbl
+ specially.
+ * valprint.c: Move print controls to top and add objectprint.
+ Add command "set print object on/off".
+ * valprint.c (value_print, is_vtbl_member): Put things in local
+ variables rather than continually doing VALUE_TYPE (val), etc.
+ * valops.c (value_struct_elt_for_address): Call check_stub_method.
+ * valops.c (value_struct_elt): Remove found, arg1_as_ptr.
+ * valops.c (search_struct_method): Give error if j > 0 && args == 0.
+ * valops.c (search_struct_field): New argument looking_for_baseclass.
+ Give error if value_static_field or value_primitive_field
+ return NULL.
+ valops.c (various): Call search_struct_field with extra parameter.
+ * symtab.c (decode_line_1): Deal with operators specified as
+ "operator" <optional whitespace> <symbols for operator>.
+ (operator_chars): Help do it.
+ * symtab.c (lookup_struct_elt_type): Call check_stub_type.
+ Take additional argument noerr.
+ Don't dump core if TYPE_FIELD_NAME is NULL.
+ Check the baseclasses recursively.
+ * symfile.c (fill_in_vptr_fieldno): Don't call check_stub_type.
+ Return void not int. (also declarations in symfile.h and value.h).
+ Deal with multiple inheritance.
+ * printcmd.c (print_command_1): Add if (objectprint) code.
+ * expread.y (variable): Allow for destructor with foo::~name.
+ * eval.c (evaluate_subexp, case UNOP_LOGNOT): If following opcode
+ is OP_SCOPE, give an error.
+ * eval.c (evaluate_subexp): Pass third arg to lookup_struct_elt_type.
+ * eval.c (evaluate_subexp), values.c (value_virtual_fn_field):
+ Don't bother to do anything with
+ return value from fill_in_vptr_fieldno.
+ * eval.c (evaluate_subexp): If value_static_field returns NULL,
+ give an error.
+ * dbxread.c (read_struct_type): Set fcontext to 0 for normal member
+ function.
+ * dbxread.c (read_struct_type): Initialize name to 0.
+ * dbxread.c (read_ofile_symtab, N_CATCH): Add offset to bufp->n_value.
+ * dbxread.c (dbx_create_type): Zero TYPE_VPTR_BASETYPE.
+ (read_struct_type): Don't bother to set TYPE_VTPR_{BASETYPE,FIELDNO}
+ if it's just going to be {0,1}.
+
+ * dbxread.c (virtual_context): Use TYPE_BASECLASS starting at 0
+ (yes, it's #if 0, but just in case...).
+
+ * vax-opcode.h, expread.y, expprint.c, cplus-dem.c: Declare some
+ things "const".
+
+ * i386-stub.c: New file.
+
+ * WHATS.NEW: Remove mention of readline and more paging (in 3.5).
+ Try to keep command names up to date with renaming.
+
+ * gmalloc.c [!HAVE_GETPAGESIZE]: Try to figure out the pagesize.
+
+ * infun.c (resume, resume_cleanups): New functions.
+ (wait_for_inferior, proceed, child_create_inferior): Use resume
+ not target_resume.
+
+ * remote.c (getpkt): Don't set immediate_quit.
+
+ * blockframe.c, frame.h (reinit_frame_cache): New function.
+ solib.c (solib_add), symfile.c ({,add_}symbol_file_command):
+ Use it.
+
+Tue Apr 23 10:38:41 1991 Jim Kingdon (kingdon at cygint.cygnus.com)
+
+ * symtab.c (lookup_symbol): Add 3 more of those loops through
+ the symtabs which we all know and love: (1) Look in the
+ STATIC_BLOCK for mangled symbols right after we check the blocks,
+ (2, 3) Look in the STATIC_BLOCK for all the symtabs and psymtabs
+ at the end.
+
+ * main.c (cd_command): Call dont_repeat.
+
+ * dbxread.c (read_struct_type): If const/volatile character is
+ missing, don't complain, just continue.
+
+ * dbxread.c (read_struct_type): Only try to read the fcontext if
+ it is there. Also change "error_type " to "return error_type ".
+ values.c (value_virtual_fn_field): If there is no fcontext,
+ then do things the way GDB 3.x did.
+ valops.c (search_struct_method): Add type to value_virtual_fn_field
+ arguments.
+
+ * dbxread.c (read_struct_type): Fix typo: *pp != '\0' -> **pp != '\0'.
+
+Mon Apr 22 00:02:43 1991 Jim Kingdon (kingdon at cygint.cygnus.com)
+
+ * printcmd.c (print_scalar_formatted): Add 't' for binary.
+
+ * dbxread.c (end_psymtab): Initialize pst->symtab.
+
+ * core.c (core_open): Call ADD_SOLIB.
+
+ * tm-sparc.h: Include <sun4/reg.h> not <machine/reg.h>.
+ sparc-tdep.c: Don't include <machine/reg.h>.
+
+ * sun3-xdep.c [!TARGET_SUN3]: Just provide empty functions which
+ don't do anything.
+
+ * core.c (core_open): Add make_cleanup (unpush_target, &core_ops).
+
+ * Shared library/corefile changes from Peter Schauer:
+ core.c (core_close): Call CLEAR_SOLIB.
+ (core_open): Remove comment about "should deal with shared lib".
+ (core_xfer_memory): If we can't xfer the usual way, try the
+ shared libraries.
+ solib.c (so_list): New fields so_bfd and so_sections{,_end}.
+ (find_solib): Use solib_map_sections to get ld_text.
+ (solib_map_sections, solib_xfer_memory): New functions.
+ (clear_solib): Free so_sections and close so_bfd.
+ tm-sunos.h: Add solib_xfer_memory, solib_add.
+
+ * sparc-tdep.c (skip_prologue): Don't skip anything unless there
+ is a "save" instruction in there somewhere.
+
+ * symfile.c (symbol_file_add): Add comment.
+ solib.c (solib_add): Don't malloc name passed to symbol_file_add.
+
+ * exec.c (build_section_table): If *start isn't NULL, free it.
+
+ * stack.c (parse_frame_specification): Error if NULL selected_frame.
+ infcmd.c (finish_command): Error if NULL selected_frame.
+ inflow.c (kill_command): Deal with NULL selected_frame.
+ stack.c (record_selected_frame): Set *FRAMEP to NULL if there
+ is no selected frame.
+ infrun.c (restore_inferior_status): Add comment.
+ findvar.c (read_var_value): Check for NULL frame where we need
+ a frame.
+ breakpoint.c (get_catch_sals): Check for NULL selected_frame.
+
+ * breakpoint.c (bpstat_print): Try all elements on the bpstat
+ chain before giving up with an internal error.
+
+Sun Apr 21 21:43:10 1991 Jim Kingdon (kingdon at cygint.cygnus.com)
+
+ * value.h, values.c (value_{,free_to_}mark): New functions.
+ breakpoint.c (bpstat_stop_status): Use them.
+
+ * tm-i386v{,-g}.h: Remove N_SET_MAGIC define.
+
+Sat Apr 20 21:42:47 1991 Jim Kingdon (kingdon at cygint.cygnus.com)
+
+ * i386-tdep.c: Remove unnecessary #includes.
+
+ * symtab.c (various): Change error return of find_line_common to -1.
+
+ * coffread.c (find_linenos): Use LINESZ not sizeof (struct lineno).
+
+ * coffread.c (end_symtab): Initialize language, dirname, and
+ fullname fields.
+
+Fri Apr 19 18:18:31 1991 Jim Kingdon (kingdon at cygint.cygnus.com)
+
+ * mips-tdep.c (mips_frame_chain): Don't chain if saved_pc == 0.
+
+ * stddef.h (size_t): Let either _SIZE_T or _SIZE_T_ guard it.
+
+ * mipsread.c (parse_symbol): Set startup_file_{start,end} if
+ entry_point is in current file.
+
+ * findvar.c (read_register_gen): Add "target byte-order" comment.
+
+Wed Apr 17 17:09:48 1991 Jim Kingdon (kingdon at cygint.cygnus.com)
+
+ * i386-tdep.c (i386_get_frame_setup): Use SWAP_TARGET_AND_HOST
+ before returning locals or slocals.
+
+ * i386-tdep.c (i386_follow_jump): Do not add data16 to pos in
+ call to codestream_seek; add one to pos if (and only if)
+ we are dealing with a jump with data16 == 1 (i.e. 0x66, 0xe9).
+
+Mon Apr 15 12:04:32 1991 Jim Kingdon (kingdon at cygint.cygnus.com)
+
+ * valops.c (call_function_by_hand): Put dummy1 in target order
+ before FIX_CALL_DUMMY.
+
+ * tm-i386v.h (FIX_CALL_DUMMY): Don't depend on host byte order.
+
+Sun Apr 14 11:55:19 1991 Jim Kingdon (kingdon at cygint.cygnus.com)
+
+ * valops.c (push_word): Add SWAP_TARGET_AND_HOST.
+
+ * remote.c (remote_open): Send '+' before calling putpkt().
+
+ * tm-i386v.h (REGISTER_VIRTUAL_TYPE): Return pointer to void,
+ not int, for pc, fp, and sp.
+
+ * remote.c (remote_open): Call start_remote after putpkt("?");
+ infrun.c (start_remote): Also call wait_for_inferior & normal_stop.
+
+Sat Apr 13 22:11:42 1991 Jim Kingdon (kingdon at spiff.cygnus.com)
+
+ * exec.c: Include <ctype.h>.
+
+ * sun3-xdep.c (fetch_core_registers): Add #ifdef FP0_REGNUM.
+
+Fri Apr 19 09:36:50 1991 Jim Kingdon (kingdon at cygint.cygnus.com)
+
+ * tm-68k.h (NUM_REGS): Conditionalize on TARGET_SUN3 not sun.
+ tm-sun3.h: Define TARGET_SUN3.
+
+ * utils.c: Use CPLUS_MARKER not '$'.
+
+ * cplus-dem.c: Use CPLUS_MARKER not '$'. If CPLUS_MARKER isn't
+ defined, define it to '$'.
+
+ * arm-opcode.h: New file (same contents as before; it had
+ just been left out of the distribution for a long time).
+
+ * tm-68k.h: Put declaration of ext_format_68881 outside the macros.
+
+ * main.c: New HAVE_SIGSETMASK #ifdefs.
+
+ * coffread.c (read_coff_symtab): Check for "LF%" with all the
+ other L*% things.
+
+ * coffread.c (SDB_TYPE): New macro.
+ various: Use it instead of checking against T_NULL.
+
+ * Makefile.dist (cplus-dem.o): Hack in an #include "param.h"
+ before we compile it.
+ defs.h: Protect against multiple inclusion.
+ param.h: Include defs.h.
+ signame.c: Change #ifdef SYS_SIGLIST_MISSING to #if.
+ param-no-tm.h: Define SYS_SIGLIST_MISSING from USG.
+
+Thu Apr 18 19:49:10 1991 Jim Kingdon (kingdon at cygint.cygnus.com)
+
+ * i386-pinsn.c (OP_E): Change %d to 0x%x for consistency.
+
+ * putenv.c: New file
+ Makefile.dist: Add it to $(OBS).
+
+ * mipsread.c [!CMUCS]: #include <syms.h>.
+
+ * mips-xdep.c (fetch_core_registers): #if 0 out the whole function.
+
+ * Move read_memory_nobpt from mem-break.c to breakpoint.c.
+
+Mon Apr 15 21:45:35 1991 Jim Kingdon (kingdon at cygint.cygnus.com)
+
+ * utils.c (_initialize_utils): Rename "set demangle" to
+ "set print demangle", "set asm-demangle" to "set print
+ asm-demangle" and "set sevenbit-strings" to "set print
+ sevenbit-strings".
+
+ * main.c (initialize_main): Rename "set history write" to
+ "set history save".
+
+ * main.c (initialize_main): Rename "set caution" to
+ "set confirm".
+
+ * values.c (_initialize_values): Remove "info history" alias
+ for (what is now) "show values".
+
+ * infcmd.c, gdbcmd.h: Add unsetlist.
+ infcmd.c: Add unset_command.
+ (_initialize_infcmd): Add "unset" and use it for "unset env".
+
+ * breakpoint.c (_initialize_breakpoint): Remove "unset".
+
+ * valprint.c: Add "set/show print", {set,show}_print.
+ Rename "set addressprint" to "set print address".
+ Rename "set arrayprint" to "set print array".
+ Rename "set array-max" to "set print elements".
+ Rename "set prettyprint" to "set print pretty".
+ Rename "set unionprint" to "set print union".
+ Rename "set vtblprint" to "set print vtbl".
+
+ * main.c: Rename version_info to show_version.
+ (_initialize_main): Rename "info version" to "show version".
+
+ * values.c: Rename value_history_info to show_values.
+ (_initialize_values): Rename "info values" to "show values".
+
+Sun Apr 14 23:08:34 1991 Jim Kingdon (kingdon at cygint.cygnus.com)
+
+ * inftarg.c (child_open), remote-vx{,.68}.c (vx_proc_open):
+ New function to give correct error message.
+
+Thu Apr 11 17:19:41 1991 Jim Kingdon (kingdon at cygint.cygnus.com)
+
+ * target.h: Add to_doc and target_preopen.
+ target.c: Add target_preopen and target_command.
+ Remove target_info.
+ (add_target): Call add_cmd and mess with targetlist->doc.
+ core.c, exec.c, remote-eb.c, remote-nindy.c, remote-vx.c,
+ remote-vx.68.c, inftarg.c, remote.c: Add doc field to target struct.
+ Call target_preopen from open routine.
+
+ * main.c: Rename editing_info to show_commands.
+ (_initialize_main): Rename "info editing" to "show commands".
+
+ * source.c: Rename directories_info to show_directories.
+ (_initialize_values): Rename "info directories" to "show directories".
+
+ * values.c: Rename convenience_info to show_convenience.
+ (_initialize_values): Rename "info convenience" to "show convenience".
+
+ * copying.awk (_initialize_copying): Rename "info copying" to
+ "show copying" and "info warranty" to "show warranty".
+ Rename {copying,warranty}_info to show_{copying,warranty}.
+
+ * symfile.c: Rename add_syms_command to add_symbol_file_command.
+ (_initialize_symfile, add_syms_addr_command):
+ Rename add-syms to add-symbol-file.
+
+Thu Apr 18 18:08:30 1991 John Gilmore (gnu at cygint.cygnus.com)
+
+ * symfile.h (free_named_symtabs): Rename from free_named_symtab.
+ * symfile.c (clear_symtab_users_once, cashier_psymtab,
+ free_named_symtabs): Move these routines from symmisc.c.
+ * symmisc.c (same): same.
+ (free_symtab): Make non-static.
+ * symtab.h (free_symtab): Declare as exported void fn now.
+ * dbxread.c (end_symtab, end_psymtab): Change comments.
+ (initialize_dbxread): Call dbx_new_init() in case the first
+ command is add-symbols.
+ * target.c (dummy_target): Permit add_syms_addr_command.
+
+Sat Apr 13 14:46:07 1991 John Gilmore (gnu at cygint.cygnus.com)
+
+ Permit symbols to be superseded when new symbol files have
+ been read in, particularly for VxWorks.
+
+ * dbxread.c (read_dbx_symtab): Allow N_SOL to cleanly take us back
+ to the main file, as well as to include files. Also, put global
+ functions into the global psymtab, to make "i fun" work.
+ (end_psymtab): Free named symtabs and psymtabs for a file, once a
+ new psymtab for it has been read.
+ * coffread.c (end_psymtab): Free named symtabs and psymtabs for
+ a file, once a new symtab has been read for it.
+ * mipsread.c: FIXME. We need to do the same for MIPS, but it
+ looks harder to determine the top-level block before it's been
+ queued to the psymtab list.
+
+ * symfile.c (symbol_file_add): Use filtered printing and wrap it.
+ If we have wiped out any old symbol tables, clean up at end of
+ symbol reading.
+ (symbol_file_command): Don't reference symfile_fns if it's zero.
+
+ * symtab.h (GLOBAL_BLOCK, STATIC_BLOCK, FIRST_LOCAL_BLOCK): New
+ defines for the blocks of a blockvector that contain global and
+ file-static symbols and the first of the smaller scope contours.
+ * symtab.c (lookup_symbol, find_pc_symtab, find_pc_line,
+ decode_line_1, make_symbol_completion_list): Use the above.
+ * coffread.c (end_symtab, patch_opaque_types): Ditto.
+ * dbxread.c (end_symtab): Ditto.
+ * expread.y (block): Ditto.
+ * mipsread.c (throughout): Ditto.
+ * symmisc.c (free_named_symtabs): Ditto.
+
+ * symtab.c (list_symbols): Process the first symbol of the
+ static psymbols list.
+ (types_info): Restore this function from its untimely #if 0.
+ It's not perfect, but it is better than nothing.
+ (_initialize_symtab): Restore "info types".
+
+Thu Apr 11 05:23:19 1991 John Gilmore (gnu at cygint.cygnus.com)
+
+ * m68k-stub.c: Remote stub for 680x0's, created from
+ rem-m68k.shar (which is removed).
+ * nindy-share/{Makefile,Onindy.c,blout.h,env.h,nindy.c,ttyflush.c}:
+ Remove RCS log stuff now that we use CVS and it blows our diffs.
+
+Wed Apr 10 14:18:06 1991 John Gilmore (gnu at cygint.cygnus.com)
+
+ * symmisc.c (free_named_symtab): Make it work, in its current
+ kludgy fashion. Change result to indicate if we blew away bkpts.
+ * dbxread.c (end_symtab): Accumulate result from
+ free_named_symtab and print warning if we blew user's state.
+ * symfile.h: free_named_symtab now returns an int.
+
+Mon Apr 8 23:57:43 1991 John Gilmore (gnu at cygint.cygnus.com)
+
+ * dbxread.c (dbx_symfile_read): Initialize psymbol list if this
+ is the first symbol read, even if not mainline.
+ (dbx_psymtab_to_symtab): symfile might be zero, cope.
+ * exec.c (exec_ops): Add_syms_addr is valid in our tvec.
+ (set_section_command): New command ("section xxx yyy" -- should
+ be renamed to "set section xxx yyy" FIXME) which sets the
+ base address of a section of the exec file, overriding the
+ virtual address that BFD reports.
+
+Fri Apr 5 17:14:39 1991 John Gilmore (gnu at cygint.cygnus.com)
+
+ * exec.c: Add add_syms_addr_command to exec_ops, so you can
+ load symbols at any address while examining an exec file.
+
+Thu Apr 4 10:09:35 1991 John Gilmore (gnu at cygint.cygnus.com)
+
+ * tm-i386v.h (FLOAT_INFO): Don't define it, since the code
+ for printing the float info is host-dependent, not
+ target-dependent. FIXME.
+ * i386-pinsn.c: Move #includes to top, remove useless ones.
+ * i386-tdep.c: Don't bother including <.../reg.h> since we
+ don't use it (and it doesn't exist on host systems).
+
+ * ieee-float.c (ieee_extended_to_double): Convert NaN to Inf.
+ Convert negative numbers properly.
+ (ieee_test): Make numbers really random; fix format arg.
+
+ * infcmd.c (attach_command, detach_command): Don't repeat on CR.
+ * core.c (core_detach): Unpush core_ops, which might not be on
+ top. We used to just pop the top, which broke things. Don't
+ need dont_repeat() any more.
+ (core_file_command): Psst! Don't repeat it.
+ * remote-nindy.c (nindy_detach): Don't need dont_repeat() now.
+ * expprint.c (print_subexp): Avoid switch fallthru on
+ BINOP_ASSIGN_MODIFY, so we can print += and such.
+ * frame.h: Fix typo.
+ * inflow.c (kill_command): After killing inferior, print our
+ current frame in the core file, if we have one.
+ (generic_mourn_inferior): When inferior dies, either select
+ the current frame (in the new target, e.g. core file), or
+ set both the current and selected frames to NULL.
+
+ Changes from Peter Schauer.
+
+ * infptrace.c: Avoid <sys/ptrace.h> on USG.
+
+ * Make all file names fit in 14 characters (sigh and damn!):
+ mv hp300hpux-xdep.c hp300ux-xdep.c
+ mv symmetry-xdep.c symm-xdep.c
+ mv symmetry-tdep.c symm-tdep.c
+ mv convex-opcode.h convx-opcode.h
+ mv tm-vxworks960.h tm-vx960.h
+ mv tm-vxworks68.h tm-vx68.h
+ mv Makefile.srcdir Makefile.sdir
+ mv gdb-int.texinfo gdbint.texinfo
+ mv remote-sa.m68k.shar rem-m68k.shar
+ mv remote-multi.shar rem-multi.shar
+ * Makefile.dist, README, config.gdb, convex-pinsn.c,
+ tconfig/symmetry, tconfig/vxworks960, tconfig/vxworks68,
+ xconfig/hp300hpux, xconfig/symmetry: Change names to shorter
+ names.
+
+ * command.c (user_info_1, user_info): New command for listing
+ the user-defined commands.
+
+Wed Apr 3 15:00:26 1991 John Gilmore (gnu at cygint.cygnus.com)
+
+ * dbxread.c (really_free_pendings): Clear file_symbols
+ and global_symbols after freeing them; otherwise, running
+ this function twice (if it appears twice on the cleanup
+ chain), we try to free things twice.
+
+ * dbxread.c (read_dbx_symtab): Calculate end_of_text_addr
+ based on text_addr (the address of text in core), not on addr (the
+ offset between text in the .o file and in core). This change
+ is from Peter Schauer.
+
+ * main.c: Define ALL_CLEANUPS as a cast of zero.
+ (return_to_top_level): Use it.
+ (main): Do all cleanups after each command run as part
+ of the gdb startup sequence. Also do all cleanups before
+ entering the command loop, and every time we exit the command
+ loop and reenter. Before, the cleanups from the startup sequence
+ were being left undone until the first error!
+ (command_loop): Rename do_nothing cleanup to command_loop_marker
+ so we can see it easily when examining the cleanup chain.
+ (init_signals): Add another do_nothing for signal handling.
+ (quit_command): Only try to kill target if it has execution.
+ Problems in the target stack got us into a state where
+ inferior_pid was nonzero but none of the targets had execution.
+ In this state you couldn't exit gdb.
+
+ * dbxread.c: Two changes from Peter Schauer.
+ (echo_command): Fflush output after an echo command.
+ (show_history): Pass all args to cmd_show_list.
+
+ * utils.c (init_malloc): Call mtrace to turn on tracing
+ if the environment variable MALLOC_TRACE is set to a file name.
+ * mtrace.c: Add source file which provides a log of every malloc,
+ free, and realloc to a trace file.
+ * mtrace.awk: Add source file which analyzes the trace file.
+ * Makefile.dist (GNU_MALLOC, MALLOCSRC): Add mtrace.{c,o,awk}.
+ (VERSION): Roll to 3.94.3.
+
+ * breakpoint.c (breakpoint_1): Add a space to "i watch" output.
+ (check_duplicates): Don't bother with watchpoints.
+ (set_raw_breakpoint): Comment about danger of this routine.
+ (watch_command): Parse and eval all args before calling
+ set_raw_breakpoint.
+
+ * solib.c (find_solib): Avoid error in referencing memory to
+ see if any more shared libraries have been added. This is
+ particularly useful if the target has terminated. Bug reported
+ by Peter Schauer.
+
+ Changes from Peter Schauer <pesrem@regent.e-technik.tu-muenchen.de>
+ in bringing up 3.94.2 on the Sun-3.
+
+ * Makefile.dist: Include CFLAGS in rule for cplus-dem.o.
+ * breakpoint.c (enable_breakpoint): Check for valid watchpoint
+ expression (in scope) before reenabling watchpoint.
+ * signame.c (init_sigs): Add missing declaration of i, fix
+ sys_siglist declaration.
+ * source.c (list_command): Fixed range computation to use
+ lines_to_list ().
+ * stack.c (backtrace_command): Do not allow command if target has
+ no stack, print informative error message.
+ * target.c (target_command): Do not write into command line
+ because this fails if the target command is used in a user defined
+ command. [This change was enhanced by gnu to support any-
+ unique-prefix matching on target names.]
+ * valops.c (value_struct_elt): Avoid infinite loop on an
+ erroneous attempt to print the member of function (try p main.p).
+
+Mon Apr 1 17:05:45 1991 John Gilmore (gnu at cygint.cygnus.com)
+
+ * expread.y (name_no_typename): Avoid reduce/reduce errors
+ caused by ambiguity in handling NAME_OR_INT and NAME_OR_UINT.
+ Since the GDB parser really doesn't use name_no_typename in a
+ name-only context, the parser can't tell the diff between
+ names and numbers here. Avoid allowing a name_no_typename
+ to be a NAME_OR_*INT to resolve the conflict.
+
+Sun Mar 31 20:12:07 1991 John Gilmore (gnu at cygint.cygnus.com)
+
+ Bugfixes from Mark Fox (markf@wrs.com) (test=testField.c):
+
+ * valprint.c (val_print_fields): bitfield printing didn't handle
+ byte order. Indirect through a few more fns to cope.
+
+ * values.c (modify_field): also cope with byte order.
+
+Sat Mar 23 10:02:21 1991 John Gilmore (gnu at cygint.cygnus.com)
+
+ Cleanup for release 3.94.2:
+
+ * Makefile.dist: Pull REMOTE_OBS. Fix saber includes for BFD
+ include files. Roll version to 3.94.2.
+
+ * coffread.c (init_stringtab): Read length into unsigned char
+ array before swapping; don't assume 32-bit longs.
+
+ * target.c (target_info): Don't bother with get_sym_file, just use
+ the symfile global variable.
+ * symtab.h, symfile.c (get_sym_file): Delete it.
+
+ * dbxread.c (dbx_symfile_init): Don't depend on long == 4 bytes.
+ (define_symbol): Set symbol line number to 0 if not gcc-compiled.
+ (read_type): Replace one more error() with complain().
+
+ * mipsread.c (parse_partial_symbols): Replace printf with complain.
+
+ * i960-tdep.c: Fix copyright attribution.
+
+ * config.gdb: Quote all backquotes in doublequotes. You can
+ quote me on that. BSD 4.4 shell found this one.
+
+ * infptrace.c (throughout): The third argument to ptrace is an
+ int *, not an int.
+
+ * infrun.c (wait_for_inferior): When program has terminated, we
+ have to call target_terminal_ours before we pop that target off
+ the stack (e.g. before a call to target_kill or
+ target_mourn_inferior). This fixes problem where a program
+ terminates, then GDB stops for (tty output) and you have to type
+ "fg" to the shell to resume it. FIXME: This code for what to
+ do after termination really should be in normal_stop instead.
+
+ * gdbcore.h (read_memory_check): Change declaration; it changed
+ names months ago.
+
+ * terminal.h: Include <sgtty.h> before <sys/ioctl.h>, since in BSD
+ 4.4 prereleases, this avoids a bug in their sgtty compatability
+ support.
+ * remote.c: Use terminal.h rather than hand-rolling the same.
+
+ * signame.c, signame.h (psignal): Arg is unsigned, not int.
+ * utils.c (strsave, strstr): Fix arg types.
+ * valprint.c (val_print): lint
+
+ MIPS symbol table support from Per Bothner:
+
+ * symfile.c (symtab_fns): Remove initializer table that needs to
+ be hacked for each new symbol file format supported.
+ (add_symtab_fns): New function, chains symbol table
+ handlers into the global list.
+ (symfile_init): Search this list.
+ * symfile.h: Add next pointer, declare add_symtab_fns.
+ * coffread.c (_initialize_coffread): Call add_symtab_fns.
+ * dbxread.c (_initialize_dbxread): Call add_symtab_fns.
+
+ * mipsread.c (psymtab_to_symtab_1): return void instead of (struct
+ symbol *). Thus, we no longer need the hack to trash
+ pst->filename. Good, since that hack confused code in symfile.c!
+
+ (reorder_symtabs, destroy_all_symtabs): Removed static
+ all_symtabs, which was used to qsort symtabs in reorder_symtabs.
+ Instead, the latter now uses a temporary array (stack-allocated
+ from an obstack, and then freed).
+
+ (parse_symbol): Added a hack to fix up BLOCK_{START,END} if they
+ haven't been set in the outermost stBlock of a procedure. This was
+ a problem with f77 binaries on Ultrix 4.?.
+
+ (new_symtab, new_symbol, new_type): Continue changing code to use
+ obstacks more and otherwise conform to dbxread internal style.
+ Made the free_code of symtabs be free_linetable (as in dbxread)
+ instead of free_contents. This implies memory leaks when reading
+ a new symbol table, until the conversion is finished. Did change
+ (struct symbol) and (struct type) to be allocated on the
+ symbol_obstack. Blocks and blockvectors are among the things
+ still "leaking."
+
+ * mipsread.c (parse_partial_symbols, parse_fdr): It hasn't been
+ tested much, but it solved one problem (reported by Meissner), and
+ cleans up some other things. The problem happened when an
+ included file contains actual code (functions) and not just
+ definitions. The mips coff is a little inconvenient there, since
+ it may cause a procedure to be mapped to the wrong psymtab.
+
+ * mips-tdep.c (heuristic_proc_desc): Minor cleanup.
+ * mips-xdep.c (fetch_core_registers): Minor cleanup. FIXME,
+ this will need work for the new core paradigm.
+
+ Opcode patches from the net:
+
+ * mips-opcode.h: fix incorrect disassembly of the mfc1, cfc1, and
+ ctc1 instructions. Also, the cvt.d.w and cvt.s.w instructions were
+ missing altogether - they are added here. From Bruce Bauman.
+ * mips-opcode.h: The low mask for C0 instructions was too small.
+ From Garrett Lau. I modified the fix to check the entire 32-bit
+ opcode.
+
+ * ns32k-opcode.h: Fix opcodes for deiw and deid. From Bruce
+ Bauman.
+
+Thu Mar 21 12:56:46 1991 John Gilmore (gnu at cygint.cygnus.com)
+
+ Roll in changes from Per Bothner (Tue, 25 Sep 90 11:11:04):
+
+ * dbxread.c (read_type): Pointer subtraction (value_sub in
+ valarith.c) sometimes failed because the types of the
+ pointers being subtracted were not identical.
+ These differed because dbxread.c was allocating pointer types
+ using dbx_alloc_type+smash_to_pointer_type instead of
+ lookup_pointer_type. I failed to find a justification for the
+ former, so I changed it to use the latter. Similarly, I
+ replaced smash_to_function_type by lookup_function_type,
+ and smash_to_reference_type by lookup_reference_type.
+
+ * mipsread.c (parse_symbol, upgrade_type, parse_procedure,
+ _initialize_mipsread): corresponding changes.
+
+ * symtab.c (smash_to_{pointer,reference,function}_type): eliminate.
+
+ * source.c (mod_path): Do tilde_expand on each component of the path,
+ rather than on the (list of) paths as a whole.
+ (print_source_lines): Set first_line_listed in addition to
+ current_source_symtab and current_source_line. If the source was
+ not findable, after a "dir" command to fix the problem,
+ a "list" would get the wrong lines.
+
+ While I was there... (gnu):
+
+ * dbxread.c (read_type): Change error to complaint.
+
+Thu Mar 21 12:56:46 1991 John Gilmore (gnu at cygint.cygnus.com)
+
+ First attempt at detailed understanding of symbol table memory alloc.
+
+ * dbxread.c (dbx_symfile_read): Free our string table if we
+ aren't the mainline. Free the "info" struct since we're done with
+ it.
+ (init_psymbol_list): Free any previously allocated psymbol lists.
+ (): FIXME: Should realloc-down the psymbol lists when done reading
+ the main symbol file?
+
+ * symmisc.c (free_symtab): Free fullname field too.
+
+ * xm-hp300hpux.h (USG): #undef then #define so Makefile can -D.
+ (REGISTER_ADDR): Make result type unsigned int.
+
+ * xconfig/{i386*,hp300hpux,altosgas,altos}: All config files that
+ define REGEX must also define REGEX1 (its dependency).
+
+Tue Mar 19 21:28:57 1991 John Gilmore (gnu at cygint.cygnus.com)
+
+ * tconfig/i960: No longer works, points you at vxworks960 or
+ nindy960.
+
+ * xgdb.c, XGDB-README: Remove file. Users can get the much
+ better xxgdb.
+ * Makefile.dist: Remove all trace of xgdb.
+
+ * breakpoint.c (breakpoint_1): Pass demangle arg to
+ print_address_symbolic.
+ (clear_breakpoints): Remove unused function.
+ (breakpoint_re_set_one): Guts of breakpoint_re_set.
+ (breakpoint_re_set): Use catch_errors to do them all anyway.
+
+ * gdb-int.texinfo (Host versus Target): Add section on what is
+ a "host" feature versus what is a "target" feature.
+
+ * infcmd.c (path_command, path_info): Handle the PATH variable
+ (object search path) as conveniently as the source search path.
+ * environ.c (set_in_environ): Set some vars in GDB's environment,
+ in addition to the child's. PATH, G960BASE, G960BIN for starters.
+ * source.c (mod_path): New function, from guts of
+ directory_command, modifies a path. Used by path_command.
+ (directory_command): Call it.
+ * defs.h (strsave): Declare.
+
+ * utils.c (sevenbit_strings): Add new printing option.
+ (printchar): Use it.
+ (strsave): Provide this handy helper routine.
+ (set_width_command): Rename set_screen_width_command.
+ (_initialize_utils): "set screen-width" => "set width";
+ "set screen-height" => "set height"; add sevenbit-strings.
+
+ * infcmd.c (do_registers_info): Print floating point registers
+ in raw hex as well as float format, regardless of whether it is
+ a "virtual" convertible register.
+ * tm-sparc.h (PRINT_REGISTER_HOOK): Print every pair of float
+ regs as a double, just in case it's being used that way.
+ * values.c (unpack_long): Comment on array/function coercion.
+ (unpack_double): Argument is in target byte order now. For
+ integer arguments, just call unpack_long and float the result.
+ * m68k-tdep.c: include defs.h for "const" handling.
+ * remote-nindy.c: Use ieee-float stuff.
+ (nindy_fetch_registers): Unpack double regs to host double, then
+ to extended.
+ (nindy_store_registers): Pack extendeds to host double, flip
+ around by misusing unpack_double, send as target double.
+
+ * tm-vxworks68.h (FRAME_CHAIN): Handle current frame pointer of
+ zero, as when stopped at the first instruction of a process.
+
+ * blockframe.c: Fix filename in comment (param.h => tm.h).
+ * sparc-tdep.c (skip_prologue): More explicit nudging comments.
+ * tm-68k.h: Fix typos.
+
+Fri Mar 15 01:09:34 1991 John Gilmore (gnu at cygint.cygnus.com)
+
+ Changes from a bringup on the DEC Vax under Ultrix 4.0.
+
+ * coredep.c (fetch_core_registers): Pass end-address of register
+ section to register_addr as expected. Don't call supply_register
+ if we'd just pass it garbage.
+
+ * dbxread.c (read_dbx_symtab): Skip N_NSYMS on Ultrix.
+
+ * exec.c (xfer_memory): Use boolean xfer_fn result, not int.
+
+ * target.c (push_target, target_info): Cast enums to int for < or
+ > comparison.
+
+ * stack.c (print_frame_info): Identify source file & line
+ even if we can't print it.
+
+ * xm-vax.h (MISSING_VPRINTF): No longer missing in Ultrix V4.0.
+
+Sat Mar 9 10:08:20 1991 John Gilmore (gnu at cygint.cygnus.com)
+
+ Clean up IEEE floating point support.
+
+ * ieee-float.h: New file.
+ * ieee-float.c: Write real routines to convert between host
+ doubles and various target IEEE extendeds.
+ * m68k-xdep.c: Eliminate assembler code for extended floats.
+ * xconfig/{3b1,altos,altosgas,hp300bsd,isi,news,news1000,sun2os3,
+ sun2os4,sun3,sun3os3,sun3os4}: Eliminate use of m68k-xdep.o.
+ * tm-i960.h, tm-68k.h (REGISTER_CONVERT_TO_VIRTUAL,
+ REGISTER_CONVERT_TO_RAW): Use ieee_extended_to_double and
+ double_to_ieee_extended.
+ * i960-tdep.c: Define ext_format_i960.
+ * m68k-tdep.c: Define ext_format_68881.
+ * sparc-tdep.c: Define ext_format_sparc, though unused.
+ * Makefile.dist (HFILES): Add ieee-float.h.
+ * inftarg.c: #include "ieee-float.h" for the REGISTER_CONVERT
+ macros.
+
+ Obsolete the "coffstrip" program in favor of using BFD's strip.
+
+ * nindy-share/coffstrip.c: Remove file.
+ * nindy-share/nindy.c (coffstrip): Routine to run bfd_strip.
+ * Makefile.dist: Remove references to nindy-share/coffstrip.c.
+ * tconfig/nindy960: Remove reference to coffstrip.o.
+
+ * Makefile.dist: Roll version number to 3.94.1 (not yet final).
+
+Wed Mar 6 09:56:45 1991 John Gilmore (gnu at cygint.cygnus.com)
+
+ * symfile.h: Add symfile_bfd, common between dbxread and coffread.
+ * dbxread.c: Remove static symfile_bfd.
+ * infcmd.c (do_registers_info): Add PRINT_REGISTER_HOOK, though
+ it is not used yet.
+ * inftarg.c (child_detach): Pop the child_ops vector if the
+ detach is successful.
+ * remote-nindy.c (nindy_create_inferior): Don't push a new
+ nindy_ops since nindy uses the same one for execution and memory
+ examination anyway.
+ * core.c (core_ops): Use child_attach and child_create_inferior
+ rather than default attach and create_inferior functions.
+
+ Handle floating point registers in core files.
+
+ * sparc-xdep.c (fetch_core_registers): Rewrite for float support.
+ * sun3-xdep.c (fetch_core_registers): Rewrite for float support.
+ This version untested since BFD doesn't yet support sun3 core
+ files.
+ * hp300hpux-xdep.c: Rewrite fetch_core_registers to new calling
+ conventions. Fix comments and style. This version has not
+ been compiled yet, since we have no HP inhouse.
+ * core.c (get_core_registers): Look for two sections, ".reg"
+ and ".reg2", and pass both to fetch_core_registers sequentially.
+
+ Revise directory path yet again.
+
+ * source.c (forget_cached_source_info): Not static any more.
+ (init_source_path): New default source path is "$cdir:$cwd".
+ (dir_command): Handle variable arguments ($cdir, $cwd).
+ (source_info): Print "Compilation directory" rather than
+ "Originally compiled in" to remind people of $cdir.
+ (openp): If the path contains $cwd, use current directory.
+ (open_source_file): If compilation directory is known, replace
+ first $cdir in path with the compilation directory.
+ (print_source_lines): Even if we can't print the lines, set the
+ current symtab and line for future commands like "info source" or
+ "breakpoint". Also, error message now contains the file name,
+ line number, and file access error message.
+ (_initialize_source): Fix help text to describe changes.
+ * main.c (cd_command): Forget cached source info when we chdir.
+ * utils.c (strstr): Add simple implementation.
+
+Tue Mar 5 01:41:40 1991 John Gilmore (gnu at fowanton.cygnus.com)
+
+ * coffread.c (read_one_sym, init_linetable, init_stringtab):
+ Byte-swap COFF symbol tables if necessary when reading them in.
+ Use complain() to replace error message in one spot. Needs
+ corresponding change in bfd/coff-code.h to make some symbol
+ swapping routines non-static.
+
+Mon Mar 4 00:53:40 1991 John Gilmore (gnu at cygint.cygnus.com)
+
+ Merge changes from Eirik Fuller, for UTek.
+
+ * defs.h (errno): Add declaration.
+ * altos-xdep.c, arm-xdep.c, convex-xdep.c, gould-xdep.c,
+ hp300hpux-xdep.c, infrun.c, inflow.c, infptrace.c, i386-tdep.c,
+ i386-xdep.c, pyr-xdep.c, mips-xdep.c, remote-eb.c, remote-nindy.c,
+ remote-vx.c, source.c, standalone.c, stuff.c, sun386-xdep.c,
+ symmetry-tdep.c, symmetry-xdep.c, umax-xdep.c, utils.c: Eliminate
+ declarations of errno.
+
+ * remote-eb.c: Define B19200 and B38400 as EXTA and EXTB.
+
+ * remote-vx.c: Include <sys/time.h> for UTek; Sun gets it via
+ <rpc/rpc.h> and <rpc/types.h>.
+
+Sat Mar 2 15:47:55 1991 John Gilmore (gnu at cygint.cygnus.com)
+
+ * i960-tdep.c (examine_prologue): Add new argument limit,
+ which stops the scan at the end of the prologue, or at the PC.
+ This fixes a problem where it walks down into the code for the
+ user's statements if that code looks like function prologues.
+ Mark Fox and I have been bouncing this code back and forth, making
+ small changes to it. Callers changed to match.
+
+Tue Feb 26 01:47:07 1991 Cygnus John Gilmore (cygnus at yuba)
+
+ Cleanup for gdb-3.94 release final:
+
+ * Makefile.dist: Remove remote-vx.c, remote-nindy.c, and all
+ the .c files from vx-share and nindy-share, from the various
+ macros, since they are not found via ALLDEPFILES.
+ (SFILES): Add tm-i960.h.
+ (alldeps.mak rule): Break out ALLDEPFILES_MAINDIR and
+ ALLDEPFILES_SUBDIR. List all the nindy and vxworks subdir files
+ in the SUBDIR list.
+ (TAGFILES_MAINDIR): Change ALLDEPFILES to ALLDEPFILES_MAINDIR.
+ (gdb.tar.Z): Use ALLDEPFILES_SUBDIR as well as SFILES_SUBDIR.
+
+Mon Feb 25 16:02:35 1991 Cygnus John Gilmore (cygnus at oldman)
+
+ * am29k-tdep.c: Add contribution line.
+ (examine_prologue): Cache information about function prologues in
+ the misc-function-vector to avoid lots of references over the
+ serial line while examining instructions.
+
+ * core.c (core_close): New function made from cleanup_core.
+
+ * core.c, exec.c, inftarg.c, remote-eb.c, remote-nindy.c,
+ remote-vx.c, remote.c, target.c, target.h,
+ Update target_ops vector to add attach, close, and load entries.
+ Use add_syms_addr_command, not add_file_addr_command, for
+ add_file. Break out close routine from existing code.
+
+ * dbxread.c (really_free_pendings): Don't free pending_blocks;
+ they are in an obstack.
+ (read_dbx_symtab): Relocate end_of_text_addr in the psymtab.
+ Lint.
+ (define_symbol): Add symbol type parameter; change callers;
+ pass type parameter to DBX_PARM_SYMBOL_CLASS macro to allow
+ it to influence the symbol class on the i960.
+ (define_symbol): Swap LOC_CONST's into target byte order.
+
+ * exec.c (exec_close): New function.
+ (exec_file_command): Call it.
+
+ * findvar.c (read_relative_register_raw_bytes): Doc byte order,
+ Fix byte order of frame pointer.
+ (read_var_value): Result of 0 if var's value can't be found,
+ e.g. missing FRAME_ARGS_ADDRESS. Byte-swap LOC_CONST and
+ LOC_LABEL values to target order. Add LOC_LOCAL_ARG.
+ (locate_var_value): Use read_var_value and use its lazy address
+ as the location of the var's value. Lint.
+
+ * i960-pinsn.c (next_insn): Add routine from vxgdb for scanning
+ instructions.
+
+ * i960-tdep.c (arg_address, i960_frame_find_saved_regs): Remove
+ obsolete Intel versions in favor of vxgdb versions.
+ (check_host, byteswap, byteswap_val, reorder_val): Eliminate
+ code dealing with byte order of values, which Intel did in host byte
+ order rather than gdb-4's target byte order.
+ (i960_frame_chain_valid): Move to nindy-tdep.c.
+ (examine_prologue, skip_prologue, frame_find_saved_regs,
+ frame_args_address, leafproc_return, saved_pc_after_call,
+ pop_frame): Add vxgdb versions from Mark Fox.
+ (examine_prologue, frame_struct_result_address): Add code
+ to deal with the saved value of G13 (struct return address
+ pointer).
+ (frame_args_address): Modify Mark's version to prefer the
+ saved value over the current value in the topmost frame.
+ Cache result in the frame info to avoid performance hair in
+ callers.
+ (print_fault): Add gdb960 code for printing faults.
+ (_initialize_i960): Actually call check_host.
+
+ * ieee-float.c (ieee_extended_to_double, ieee_double_to_extended):
+ add stub routines. FIXME, these currently just return zero!
+
+ * infcmd.c (program_info): Use PRINT_RANDOM_SIGNAL.
+ (attach_command): Call target_attach, not target_open, now.
+
+ * infrun.c (normal_stop): Make global, not static, for vx_attach.
+ (child_attach): Rename from child_open.
+ (wait_for_inferior): Use PRINT_RANDOM_SIGNAL. If stop_pc is zero,
+ don't confuse it with a zero step_resume_break_address.
+
+ * inftarg.c (child_detach): Eliminate inferior_pid test.
+ (child_files_info): Clean up message a bit.
+ (child_ops): Use child_attach, not child_open, to attach.
+
+ * mem-break.c: #ifdef out the whole file if BREAKPOINT is not
+ set (e.g. on VxWorks or NINDY). Move read_memory_nobpt from
+ findvar.c to here, since it depends on the contents of the
+ shadow_contents of breakpoints, but keep if #if 0 since it is
+ never called.
+
+ * nindy-tdep.c: New file, contains nindy_frame_chain_valid, moved
+ from i960-tdep.c.
+
+ * printcmd.c (address_info): Handle LOC_LOCAL_ARG. Lint.
+ (ptype_command, display_command): Eliminate have_inferior_p and
+ have_core_file_p in favor of target_has_stack or
+ target_has_execution.
+ (print_frame_args): Handle LOC_LOCAL_ARG. Eliminate duplicate
+ code for actually finding the values of arguments, though we still
+ keep track of the maximum stack offset for use in printing unnamed
+ arguments. Handle missing FRAME_ARGS_ADDRESS.
+
+ * remote-nindy.c (i960_print_fault): Move to i960-tdep.c.
+ (struct nindy_regs): Define registers passed to/from nindy.
+ (nindy_fetch_registers, nindy_store-registers): Translate between
+ nindy and GDB formats for the registers.
+ (dcache_init): Statically allocate the cache, since it was being
+ allocated by a malloc that was never freed anyway.
+ (nindy_create_inferior): Error, not core dump, if no exec file.
+ (nindy_before_main_loop): Use target_load, not target_add_file.
+
+ * remote-vx.c (net_load): Specify large timeout for load
+ requests. Allow user to break out with INTERRUPT.
+ (net_break): Remove useless code, clean up. Change callers.
+ (parse-args, skip_white_space, find_white_space): Clean up arg
+ parsing to cope with quoted strings.
+ (net_wait, net_quit): Never call error, just return status.
+ (vx_read_register, vx_write_register): Cleanup status checking.
+ #ifdef the code based on which CPU we are using (960 or 68k),
+ FIXME, this should be completely general but it isn't yet.
+ (vx_xfer_memory, vx_resume): Cleanup status checking.
+ (vx_run_files_info): Improve message.
+ (vx_load_command): Renamed from vx_add_file_command. Allow load
+ to be interrupted.
+ (net_ptrace): Remove unused routine.
+ (vx_wait): Adopt code from vxgdb960 to cope with broken
+ connections to target machine and prompt to disconnect. Remove
+ debug printouts. Map some EVENT_'s to SIGnals.
+ (add_symbol_stub, vx_open): Print names of object files we found,
+ and "ok" if we read their symbols OK. Clarify output in general.
+ (vx_attach, vx_detach, vx_kill): Add these commands.
+ (vx_convert_from_virtual, vx_convert_to_virtual): Simplify.
+ (vx_run_ops): Turn off all_mem, to avoid spurious msg in the
+ "info files" output, and create_inferior, since we already have
+ an inferior.
+
+ * stack.c (frame_info): Replace Frame_unknown with 0.
+ (print_frame_arg_vars): Handle LOC_LOCAL_ARG.
+ (return_command): Pop until the PC matches as well as the FP,
+ so it works even if the FP is shared with another function,
+ as in "frameless" or "leaf" procedures.
+
+ * symfile.c (load_command): renamed from add_file_target_command.
+ (add_syms_addr_command): renamed from add_file_addr_command.
+ (add_syms_command): Stub to call target_add_syms.
+ (_initialize_symfile): Change command names and descriptions,
+ add-file => add-syms, and load from alias to its own command.
+
+ * target.c (kill_or_be_killed, maybe_kill_then_attach,
+ maybe_kill_then_create_inferior): Default for attempts to start
+ a process, if one is already running, is to ask about killing
+ it and retry if yes.
+ (upstack_create_inferior): #if-0 it, strata obsolete it.
+ (push_target, unpush_target, pop_target): to_close() a target
+ before unstacking it.
+ (target_info): Renamed from target_files_info.
+ (_initialize_targets): Rename "i files" as "i target", accessible
+ under both names.
+
+ * target.h: Improve comments about the target_ vectored routines.
+
+ * tm-i960.h: Remove NINDY-specific stuff to tm-nindy960.h.
+ Convert commenting style to standard GNU style.
+ (DBX_PARM_SYMBOL_CLASS): allow LOC_LOCAL_ARG's to be recognized.
+ (SKIP_PROLOGUE): No longer a no-op.
+ (SAVED_PC_AFTER_CALL): Now handles leaf procedures.
+ (*_REGNUM): Sort register numbers.
+ (REGISTER_BYTES, REGISTER_BYTE, REGISTER_RAW_SIZE,
+ MAX_REGISTER_RAW_SIZE, REGISTER_CONVERTIBLE,
+ REGISTER_CONVERT_TO_VIRTUAL, REGISTER_CONVERT_TO_RAW): Float regs
+ are now 10 byte extendeds, not 8 byte doubles.
+ (FRAME_CHAIN_VALID): Make this config-dependent, since it differs
+ for nindy versus vxworks targets. FIXME, this should possibly go
+ in the target vector.
+ (EXTRA_FRAME_INFO, INIT_EXTRA_FRAME_INFO): Cache both
+ frame_saved_regs and arg pointer with each frame.
+ (FRAMELESS_FUNCTION_INVOCATION): New leafproc support.
+ (FRAME_ARGS_ADDRESS): Use cached result.
+ (FRAME_ARGS_ADDRESS_CORRECT): New, avoids g14 guessing.
+ (FRAME_FIND_SAVED_REGS): Change arg to subsidiary fn.
+ (PRINT_RAMDON_SIGNAL): Call print_fault.
+ (POP_FRAME): Now works.
+
+ * tm-nindy960.h: Break this off tm-i960.h. NINDY-specific
+ option parsing and startup; STACK_END_ADDR, FRAME_CHAIN_VALID,
+ BREAKPOINT, and DECR_PC_AFTER_BREAK are here.
+ (ADDITIONAL_OPTION_HANDLER): use target_load, not
+ target_add_file.
+
+ * tm-vxworks960.h: Break this off tm-i960.h. VxGDB specific
+ startup; DECR_PC_AFTER_BREAK, and FRAME_CHAIN_VALID are here.
+
+ * valarith.c (value_subscripted_rvalue): Avoid handling
+ floats and doubles specially; it gave alignment errors. Lint.
+
+ * valops.c (value_of_variable, value_of_this): Error if unknown
+ value.
+
+ * valprint.c (print_floating): Bcopy rather than pointer-deref,
+ to avoid alignment problems.
+ (value_print): Handle unknown value address.
+ (cplus_val_print): Two args are ignored; remove them. Change caller.
+ (val_print): Use unpack_long rather than pointer-deref.
+
+ * values.c: Lint.
+ (unpack_long, unpack_double): Use bcopy rather than pointer-deref
+ to avoid alignment problems.
+ (value_being_returned): Error if return value unknown.
+ (set_return_value): Add bogosity warning, FIXME. *
+
+ * TODO: A woman's work is never done.
+
+ * Makefile.dist: Distribute REMOTE_OBS into tconfig files.
+ Separate INCLUDE_CFLAGS for use with lint. Add LINTFILES.
+ Add ieee-float.o to OBS.
+ * tconfig/{nindy960,vxworks68,vxworks960}: Include the desired
+ REMOTE_OBS remote-interface files in the TDEPFILES and TM_FILE.
+ * tconfig/i960: FIXME. Half-merge, produce warning if config'd.
+
+ Changes to generalize the VxWorks RPC protocol slightly, to handle
+ i960 as well as 68000.
+
+ * vx-share/dbgRpcLib.h (VX_SOURCE_STEP): Add.
+ * vx-share/reg.h: Produce i960 regs #ifdef I80960
+ * vx-share/xdr_ptrace.c: Skip FPA registers if 960.
+ * vx-share/xdr_rdb.h: Add SOURCE_STEP struct and xdr decl.
+ * vx-share/xdr_rdb.c: Add xdr_SOURCE_STEP routine.
+ * vx-share/xdr_regs.c: Add xdr_regs, xdr_fp_status, xdr_ext_fp
+ for i960. Change xdr_vectors to xdr_opaques for 68k registers,
+ so they will move in target byte order rather than network
+ byte order (happens to be the same).
+
+Mon Feb 25 03:41:44 1991 John Gilmore (gnu at cygint.cygnus.com)
+
+ * tm-convex.h (END_OF_TEXT_DEFAULT): Remove #if 0'd block.
+
+Sun Feb 24 00:55:53 1991 John Gilmore (gnu at cygint.cygnus.com)
+
+ * am29k-pinsn.c,
+ Add contribution lines to various files, showing where they
+ came from.
+
+ * breakpoint.c (break_insn, check_break_insn_size,
+ read_memory_nobpt): Remove to mem-break.c.
+
+ * xm-*.h, param-no-tm.h, tm-29k.h, valprint.c: Change BYTE_ORDER to
+ HOST_BYTE_ORDER.
+
+ * tm-29k.h (STAB_REG_TO_REGNUM): Warn user if symbol table
+ entry has bad register number. This change is not
+ tested in this release, FIXME.
+
+ * frame.h: Eliminate Frame_unknown in favor of a simple zero.
+ tm-vax.h: Ditto.
+
+ * value.h: Force value's contents field to be aligned to hold
+ at least a double or a long long (if supported). This avoids
+ doing bcopy's in and out of the contents field.
+
+ (step_1): Avoid coredump under obscure circumstances when we
+ have no frame.
+
+ * symtab.h (misc_info): Add field to misc function vector for
+ any kind of cached information the target code desires. AMD
+ 29000 uses this to avoid repeating examine_function_prologue's.
+
+ * coffread.c: Lint. Remove static symfile, read_section_header.
+ core.c (have_core_file_p): Lint: remove.
+ expprint.c (print_subexp): Lint.
+ infptrace.c, valops.c, valprint.c: lint.
+
+ Roll in changes from vxgdb-5.0.1:
+
+ * symtab.h: Comment byte order of each address class. Add
+ LOC_LOCAL_ARG for frame-relative args (960).
+ expread.y: Use LOC_LOCAL_ARG where LOC_ARG is used.
+ symtab.c, symmisc.c: ditto.
+
+ * infrun.c (init_wait_for_inferior): Clear stop_signal.
+
+ * remote.c (remote_resume): Error if resume with a signal.
+
+ * symfile.c (prim_record_misc_function): Clear misc_info.
+ (fill_in_vptr_fieldno): Check stub type of arg.
+
+ * valops.c (value_cast): Avoid looking up names of types whose
+ name we don't know, to prevent coredump. Sun CC produces typedef
+ rtx and the name of *rtx is zero...
+
+Mon Feb 18 21:16:25 1991 John Gilmore (gnu at cygint.cygnus.com)
+
+ Roll in changes from final AMD 29000 port (Tiemann).
+
+ tconfig/am29k: Add COFF_ENCAPSULATE and TARGET=TARGET_AM29K
+ for ../include/a.out.encap.h. This might not work now that BFD
+ is separately compiled. Instead, BFD support for encap will have
+ to translate machine type 29k into the right COFF_MAGIC.
+
+ * infcmd.c: Remove references to inferior_pid that aren't used
+ in actual ptrace calls; use target_has_execution, etc.
+ (have_inferior_p): Remove function.
+ (program_info): Print target info rather than "process number";
+ avoid gratuitous messages unless from_tty.
+ (run_stack_dummy, finish_command): Set proceed_to_finish.
+ infrun.c: Remove inferior_pid refs. Decl & init proceed_to_finish.
+ main.c: Lint. Lose have_inferior_p().
+ inferior.h (have_inferior_p): Remove, lint.
+ (proceed_to_finish): Add flag to ask that all regs be saved
+ by normal_stop, for the few commands that need it, speeding up
+ serial I/O. Add comments to stop_registers.
+
+ * remote-eb.c: Remove newline from breakpoint message we grep
+ for. Never time out when running the user program.
+
+
+
+Wed Feb 13 15:34:40 1991 John Gilmore (gnu at cygint.cygnus.com)
+
+ Roll in changes from vxgdb-5.0.1:
+
+ * dbxread.c (read_dbx_symtab): If we encounter a "FORTRAN COMMON"
+ symbol in its raw form, we are processing an unlinked ".o" file.
+ See if the target environment has assigned it an address, using
+ target_lookup_symbol (VxWorks does), and enter it into the symtab
+ that way.
+
+ * tm-vxworks.h (FRAME_CHAIN, FRAME_CHAIN_VALID): Override usual
+ 68k versions for a simpler version that assumes zero FP at bottom.
+ Fixes bug of truncated stack reports.
+
+ * target.h (target_lookup_symbol): Define this routine's args
+ and result, finally.
+
+ * target.c (nosymbol): Default routine for target_lookup_symbol.
+ (target_default): Default lookup_symbol and call_function too.
+ (files_info): Only print has_all_memory warning if a non-dummy
+ target follows.
+
+ * remote-vx.c (vx_read_register, vx_convert_to_virtual,
+ vx_convert_from_virtual): If target does not have floating point,
+ zero register "values", and avoid doing cross-net conversions.
+ (vx_lookup_symbol): Rename net_lookup_symbol, add to vectors.
+ (vx_open): Rearrange code that attaches to target and reads
+ symbols for all loaded modules, to work if some of the modules
+ are not accessible. Add symbol_stub() and add_symbol_stub()
+ as callbacks from catch_errors(). Allow connect attempt to be
+ interrupted painlessly with ^C (FIXME, there are still some bugs
+ if the interrupt happens during symbol reading.). Print
+ final message with puts_filtered, since symbol messages are
+ now filtered too.
+
+ Misc cleanup:
+
+ * main.c (catch_errors): Only print errstring if non-null.
+ (command_loop): Avoid an ioctl per command to test ISATTY.
+
+ * remote-vx.c (net_load): make static; avoid sophomoric msg.
+ (vx_xfer_memory): Return correct result!
+ (vx_files_info): Indicate whether target has float or not.
+ (vx_lookup_symbol): Complain, not error, if target gone.
+ (vx_open): Print "Connected" msg before disabling immediate-quit.
+ [FIXME: lookup_symbol and vx_open changes need testing.]
+
+ target.c, remote-eb.c, inftarg.c, am29k-opcode.h, target.h,
+ tm-29k.h, tmm-vxworks68.h, symfile.c, gdb-int.texinfo: Add
+ contributor lines and update copyrights to 1991.
+
+ Changes from an attempted H-PUX host port:
+
+ * infptrace.c (PT_ATTACH, PT_DETACH): Handle HP/UX, which
+ defines PT_ATTACH and PT_DETACH but not PT_KILL.
+ * remote-eb.c (eb_open): Misplaced endif kills sysv H/PUX.
+ * remote-vx.c: include <sys/time.h> for HPUX.
+ * hp300hpux-xdep.c (fetch_core_registers): Rewrite old
+ "core_file_command" routine to BFD regime. May not work yet.
+
+ Attempted port of "gdb-3.4 Van Jacobson xgdb" to modern gdb.
+
+ * xgdb.c: Replace X10 version with some VJ version.
+ (FIXME: Its copyright assignment is not on record.)
+ * xgdb.c: Update include files to X11R4 (Xaw crud).
+ (xgdb_display_source, create_text_widget): fix call to
+ get_filename_and_charpos. Rewack source window stuff for X11R4
+ (gleaned from include files, and "nm's" of binary libraries, since
+ I had no doc available).
+ (append_selection, append_selection_word): Disable with FIXME
+ since R4 changed interface here.
+ (create_buttons): Add back the old set of buttons.
+ (xgdb_create_window): Fix call to XtInitialize (&argc not argc).
+
+ * Makefile.dist (xgdb, xgdb-init.c): Update for X11R4 on Suns.
+ Roll VERSION to 3.94 (not yet final though).
+
+Sat Feb 9 09:46:25 1991 John Gilmore (gnu at cygint.cygnus.com)
+
+ * obstack.h (obstack_ptr_grow, obstack_ptr_grow_fast,
+ obstack_int_grow, obstack_int_grow_fast): Eliminate
+ cast on left of assignment, which gives MIPS cc fits and is
+ not Standard C.
+
+ * sparc-pinsn.c (print_insn): Eliminate 'set' test, subsumed by
+ F_ALIAS. Use printf, not fprintf, when not passing a file
+ pointer...
+ (compare_opcodes): Check that identical instructions have
+ identical opcodes, complain otherwise.
+
+ * sparc-opcode.h (st %fsr): Fix opcode "lose" mask. This
+ was reported by Roland McGrath.
+ (unimp): Only match if exactly zero instruction. (Roland)
+ (branches and traps): Generate all variations of these
+ instructions with macros, based on a single call that defines
+ each condition name and its binary representation.
+ (set): Turn on alias bit, to avoid test in sparc-pinsn.c.
+
+ * valprint.c (val_print_fields): Take, and use, format parameter.
+ This means that "p/x struct" again prints the elements in the
+ desired format. Changed callers.
+
+ * stack.c (frame_info): Use filtered output, and indicate wrap
+ points. Remove kludgy formatting designed to avoid line wrap.
+
+ * utils.c (wrap_here): If the line is already full (because
+ we had printed a long indent or long wrapped string), do an
+ immediate newline-and-indent.
+
+ * m68k-pinsn.c (print_insn_arg): Bugfix from
+ ntmtv!thompson@ames.arc.nasa.gov (Mike Thompson): 'bkpt #0'
+ instruction is incorrectly disassembled as bkpt #8.
+
+ * dbxread.c (end_psymtab): Bugfix from Peter Schauer
+ <pesrem@regent.e-technik.tu-muenchen.de>: If you want to set a
+ breakpoint in a *.y file gdb will say Reading in symbols for *.y...
+ and then will dump core (sometimes). I traced it back to an
+ uninitialized symfile_name in psymtab_to_symtab.
+ (const_vol_complaint): Add quotes to message.
+ (define_symbol): Only believe line number if gcc_compiled.
+ Avoid allocating symbol if we will not return it.
+
+ Add target strata support so that newly established targets go
+ into their right place in the target stack (e.g. a new exec file
+ doesn't wipe out the ability to access the running process).
+
+ * target.h, core.c, exec.c, inftarg.c, remote-eb.c,
+ remote-nindy.c, remote-vx.c, remote.c, target.c: Add to_stratum
+ and initialize it properly in all the targets.
+
+ * target.h: Document strata. Change return type of push_target.
+
+ * target.c (nomemory): new function for dummy memory access.
+ (tcomplain): Rename complain, now also used in symfile.c.
+ (push_target): Push targets within strata. New return value shows
+ whether new target is on top of stack or not. Always keep dummy
+ target on stack.
+ (target_files_info): Ignore dummy target.
+
+ * core.c (core_open): Warn user, and skip accessing file, if the
+ core target is not the topmost target in the stack.
+ * remote-nindy.c (nindy_create_inferior): Avoid unpush_target, now
+ already handled.
+
+ * remote-vx.c: Remove vx_prepare_to_store from vxworks memory
+ target_ops, it doesn't belong there since we have no regs there.
+ Change name of target from machine => memory to clarify.
+
+Thu Feb 7 16:32:09 1991 John Gilmore (gnu at spiff.cygnus.com)
+
+ * Freeze version 3.93 for release.
+
+ * Makefile.dist: Handle vx-share and nindy-share subdirs
+ properly when building gdb.tar.Z.
+
+ * symtab.c: lint; add no_symtab_msg to consolidate the messages
+ printed in various places, so I could change just one copy.
+
+ * dbxread.c, coffread.c: Change references to bfd->iostream
+ to cast to FILE *, now that BFD avoids needing types defined
+ in other header files.
+
+Tue Feb 5 21:39:35 1991 John Gilmore (gnu at cygint.cygnus.com)
+
+ * command.c, dbxread.c, expprint.c, infcmd.c, infptrace.c,
+ infrun.c, printcmd.c, remote-nindy.c, source.c, sparc-tdep.c,
+ sparc-xdep.c, symfile.h, symmisc.c, utils.c, valprint.c: Lint
+ (actually gcc -Wall).
+
+ * dbxread.c: Remove first_global_sym, last_global_sym, since
+ they are never referenced.
+
+ * defs.h (baud_rate): Declare.
+ main.c: Define it, and add the -b option to set it.
+
+ * gdb-int.texinfo: Add text on how to define a new host or target
+ architecture, prompted by Per Bothner's questions about MIPS
+ support.
+
+ * gdb.texinfo: Document "complaints". Change doc of -q since
+ gdb no longer prints the copyright and blurb if you specify a file
+ name to be debugged (just like Emacs). Add doc for Nindy-specific
+ command line flags for specifying target serial port and such.
+ Update copyright to 1991.
+
+ * gdbcore.h: Remove a large mass of now-useless crud, since BFD
+ has taken over for us the job of ripping up executable files. The
+ crud caused Per Bothner's port to not compile.
+
+ * infrun.c (normal_stop): Avoid printing "Program exited
+ normally" if we are in batch mode. This allows a GDB which
+ executes a program on a target system, to behave like a Unix
+ command (input from stdin, output to stdout, no extraneous
+ output).
+
+ * main.c (main): Allow additional machine-dependent command line
+ options to be specified with the ADDITIONAL_OPTIONS,
+ ADDITIONAL_OPTION_CASES, ADDITIONAL_OPTION_HELP, and
+ ADDITIONAL_OPTION_HANDLER macros. Also allow machine-dependent
+ processing to occur just before the main loop with
+ BEFORE_MAIN_LOOP_HOOK.
+ (main): If a "core file" argument is specified, and it is not a
+ core file, try it as a process ID to attach.
+ (symbol_completion_function): Attempt to cope with
+ "show screen-" TAB, not very successfully. This needs more work,
+ FIXME.
+ (batch_file): New function, returns whether we are reading
+ commands from an interactive tty on stdin, or from somewhere else.
+ Called by normal_stop since it doesn't get from_tty passed down
+ to it like many commands do.
+
+ * remote-nindy.c: Handle command line options for nindy
+ connection.
+ (nindy_before_main_loop): Prompt user for tty name if they
+ don't specify it before getting to the interactive command loop.
+
+ * tm-i960.c: Add ADDITIONAL_OPTIONS, etc, to handle -O, -brk,
+ and -r command line options. Also add hook before main loop
+ to make it easy to specify a tty.
+
+ * TODO: More things to do, one done.
+
+Mon Feb 4 23:57:39 1991 John Gilmore and Mike Tiemann (at cygint.cygnus.com)
+
+ * dbxread.c: Make complaint() calls pass pointer, not struct.
+ Add complaints about badly formatted C++ type information
+ (const/volatile indicator, and parse errors resulting in
+ error_type). Fix C++ virtual member fn comment.
+ (read_struct_type): Avoid bumping pointer if we got a parse
+ error; this prevents our walking beyond the end of a string.
+ Terminate loop on null char as well as semicolon.
+ (process_one_symbol): Fix the LBRAC fix so that it uses the
+ last previous SLINE, FUN, or SO record's PC address. C++ debug
+ symbols did not have SLINE records in a useful order compared
+ to the LBRAC records.
+ (define_symbol): Handle "catch" records.
+
+ * symtab.c (check_stub_type): Added new complain
+ `stub_noname_complain' and added a consistency check to
+ keep the debugger from crashing when finishing from an
+ exception frame. A real fix will be needed later.
+
+Sat Feb 2 10:43:05 1991 John Gilmore (gnu at cygint.cygnus.com)
+
+ * infcmd.c (attach_command): Make global.
+
+ * Makefile.dist (REMOTE_OBS): Make these compile by default,
+ but make them easy to comment out. Perhaps later they should
+ be enabled by what CPU you configure for? FIXME.
+ (VERSION): Roll to 3.93.
+ (pinsn.o): Remove rule for obsolete file.
+ (dbxread.o,coffread.o,mipsread.o): Use ${srcdir} explicitly.
+
+ Run down a problem that manifested by printing the wrong function
+ name in stack traces of read_ofile_symtab. Turned out that the
+ problem was the SunOS 4.1.1 (and previous) C compiler outputs
+ the LBRAC symbol with an address in the *data* segment, which
+ blew our binary search through the blocks.
+
+ * dbxread.c: Use the complain() facility consistently to bitch
+ about problems in the symbol file we are reading.
+ (finish_block): Add code to check the nesting of the blocks;
+ complain and Procrust them to fit if wrong.
+ (make_blockvector): Check the order of the blocks, complain
+ [but don't cope] if wrong.
+ (process_one_symbol): ifndef SUN_FIXED_LBRAC_BUG, check LBRAC
+ symbols to be sure their PC value is greater than the last SLINE
+ (line number) symbol we've seen, complaining and adopting the
+ SLINE PC value if wrong.
+
+ * symfile.h (struct complaint, complaint_root, complain,
+ clear_complaints): Add.
+ * symfile.c (complain, complaint_root, clear_complaints): Add
+ facility to deal with non-fatal complaints and to regularize their
+ suppression.
+ (symbol_file_add): Clear complaint counters to allow new complaints.
+ (initialize_symfile): Add 'set complaints' and 'show complaints'.
+
+ * dbxread.c (dbx_symfile_read): Remember the address and size
+ of the string table for the main symbol file, so we won't read it
+ more than once.
+ (dbx_psymtab_to_symtab): Fix the check for main symbol file,
+ to avoid reading the string table yet again. Lint.
+ (throughout): Improve filtered output, including word wrap.
+ (read_range_type): Improve Bothner's fix to handle other types too.
+
+ * utils.c: Improve line wrap implementation. Handle unlimited
+ width by making chars_per_line unsigned.
+ (puts_filtered): New, easy, function.
+
+ * defs.h (puts_filtered): add.
+
+ * mipsread.c (compare_symbols, sort_symtab): Remove these fns,
+ call the identical sort_symtab_syms() in symfile.c instead.
+
+ * expread.y: Suggest the `file' command rather than `symbol-file'.
+
+ * command.h (enum var_types): Add zinteger for seroable
+ unsigned integer.
+ * command.c (do_setshow_command): Handle var_zinteger. Restructure
+ nested if's into a switch.
+
+ * breakpoint.c (bpstat_print): If bpstat "print" flag is not set,
+ we did not stop because of a breakpoint (it must have been for
+ some other reason, like a "stepi"), so don't print anything.
+
+ * symtab.c: Include <sys/types.h> all the time. Now that BFD
+ doesn't include <sys/types.h>, old SunOS's require it for
+ <sys/stat.h>.
+
+Sat Feb 2 10:39:15 1991 Per Bothner (bothner@cs.wisc.edu)
+
+ A test port of gdb-3.92.6 to the Sony NEWS.
+
+ * Makefile.dist
+ Don't normally link in remote- or vx stuff.
+ Some of it doesn't compile, and it wastes space for 99% of the users.
+ Remove reference to no-longer-used HAVE_VPRINTF.
+ Fixed BFD_DEP typo to BFD_DIR.
+ * dbxread.c
+ Fix cast in arg to bfd_h_getlong.
+ Make char *prefix be const.
+ Fix how certain range types are mapped into builtin unsigned int types.
+ * infrun.c
+ Remove 2 #includes. They cause errors (on Sony, at least),
+ and aren't needed (they wern't in earlier versions).
+ * printcmd.c
+ print_address_symbolic should never demangle labels
+ (since it prints *assembler-level* labels).
+
+ [This was superseded by the change to printcmd below.]
+
+ * utils.c
+ Add some "volatile" return types to avoid warnings.
+ If MISSING_VPRINTF add vprintf function and not just macro
+ (since vprintf is used in printcmd.c).
+ * valprint.c
+ Unless __GNUC__, use obstack_grow instead of obstack_ptr_grow.
+ (The latter isn't grokked by some PCC-based compilers.)
+
+ [This change is in abeyance, we prefer to fix obstack_ptr_grow.]
+
+ Make chunk size of dont_print_obstack 32*4 instead of default 4096.
+ * nindy-share/coffstrip.c
+ Added some forward declarations (otherwise, gcc complains
+ about implicit extern redefined as static).
+
+Sun Jan 20 02:38:19 1991 John Gilmore (gnu at cygint.cygnus.com)
+
+ Changes inspired by Per Bothner:
+ * printcmd.c (print_address_symbolic): Take additional parameter
+ specifying whether to demangle.
+ (print_address): Pass in asm_demangle to control demangling.
+ (print_address_demangle): New fn, takes explicit arg to control
+ demangling.
+ * utils.c: Add new vars demangle and asm_demangle, and let them
+ be set and shown.
+ (fputs_demangled): If !demangle, just print the argument.
+ (fprint_symbol): If !demangle, just print raw symbol.
+ * valprint.c (val_print): Call print_address_demangle rather than
+ print_address, to cause demangling to depend on the global
+ rather than assembler-level demangling setting.
+ * WHATS.NEW, gdb.texinfo: Document.
+
+ * main.c (show_command): Show all settings if no arg.
+ (initialize_main): Make "info set" the same as naked "show".
+ * command.c (cmd_show_list): Handle prefix commands in the
+ list, and print the name of the setting as well as its English
+ description and value.
+
+ Allow gdb functions to specify where a line should wrap if it
+ exceeds the size of a terminal line. Use it to make the output
+ prettier.
+ * utils.c (set_screen_width_command): New fn, mallocs a buffer
+ of the right size when screen width changes.
+ (set_screensize_command, screensize_info): Remove #if 0'd fns.
+ (wrap_here): New fn, indicates a point in the output where we
+ should wrap the line rather than just letting it overflow at a
+ random place.
+ (fputs_filtered): Implement wrapping.
+ (n_spaces): New fn, returns a pointer to N spaces.
+ (print_spaces_filtered): Use n_spaces.
+ * defs.h (n_spaces): Declare.
+ * stack.c (print_frame_info): Wrap with 4-space indent after
+ fn name and before filename and line number.
+ * printcmd.c (print_frame_args): Wrap with 4-space indent
+ before each argument name is printed.
+ * valprint.c (value_print): Wrap with no indentation before
+ each repetition.
+ (val_print_fields): Wrap with indentation relative to nesting
+ level before each field name.
+ (val_print): Wrap with nesting indentation before array elements.
+ * command.c (do_setshow_command): Avoid extra newlines,
+ wrap with 4-space indent around values printed, end with period.
+ * WHATS.NEW, gdb.texinfo, gdb-int.texinfo: Document.
+
+ * breakpoint.c (breakpoint_1): Implement addressprint for
+ "info breakpoints" display. Change file name and line number
+ format to " at file:nnn" rather than " (file line nnn)".
+ * gdb.texinfo: Document.
+
+
+Fri Jan 18 07:21:25 1991 John Gilmore (gnu at cygint.cygnus.com)
+
+ Frozen for gdb-3.92.6 release.
+
+ README, WHATS.NEW: Update for 3.92.6 release.
+
+ tconfig/{altos, i386v, i386v32, m88k, umax}: Eliminate
+ coffread.o from configs since it is now built by default.
+ tconfig/{3b1, altosgas, arm, convex, hp300bsd, hp300hpux,
+ i386v-g, i386v32-g, isi, merlin, news, news1000, np1, pn,
+ pyramid, symmetry, vax, vxworks68}: Eliminate dbxread.o
+ from configs since it is now built by default.
+
+ Makefile.dist: Update for release 3.92.6. Handle files that
+ have been moved to ../include, ../getopt, or ../bfd. Add
+ saber.suppress and tests directory. Add config.status to
+ the release (it will say "none").
+
+ coredep.c: Minor formatting fixes.
+
+ These changes were made in early December but only checked in now:
+ * nindy-share/Onindy.c, nindy-share/coffstrip.c,
+ nindy-share/nindy.c: lint
+ * nindy-share/nindy.c (ninStopWhy): Don't byteswap the
+ register values coming back from the target; we store values
+ in target byte order everywhere.
+
+Wed Jan 16 19:01:37 1991 John Gilmore (gnu at cygint.cygnus.com)
+
+ * am29k-opcode.h, am29k-pinsn.c: Add 29050 opcodes.
+
+ * valprint.c (cplus_val_print, val_print_fields): New functions,
+ which print C++ objects. They conspire to avoid printing a
+ virtual base class more than once, following all the twists and
+ turns of C++ virtual base rules.
+ (val_print): Call the above rather than do it by hand.
+
+ * symfile.c (symbol_file_add): Only reset symfile_mtime for main
+ symbol file, not for added files like shared libs. This really
+ needs to be generalized to a timestamp per file.
+
+ * core.c (cleanup_core): Avoid coredump if no core file.
+
+ * config.gdb: Accept -host or -target in place of +host or
+ +target.
+
+ * coffread.c (find_linenos): Avoid desupported BFD interface
+ to line numbers. We still read them manually rather than using
+ BFD's "generic" features.
+
+ * gdbrc.tex, threecol.tex: Add GDB reference card and its
+ formatting code.
+ Makefile.dist: Add refcard to OTHERS list for creating tar files.
+
+ * Makefile.dist: Eliminate use of $< in explicit targets.
+
+ * readline/Makefile: Use $< rather than $*.c, which does not
+ include the VPATH in GNU Make.
+
+ * tconfig/i960-bout, tconfig/i960-coff: These are identical
+ copies of tconfig/i960, added for global configuration
+ compatability. All i960 versions can read both coff and b.out.
+
+ * tm-88k.h: Fix multiline macro that lacked \'s. Remove
+ COFF_FORMAT and COFF_CHECK_X_ZEROES since these are now handled
+ automaticaly.
+
+ * TODO: Think of more things to do.
+
+Wed Jan 2 19:09:29 1991 John Gilmore (gnu at spiff.cygnus.com)
+
+ tconfig/{am29k,i960,sun2*,sun3*,sun4*}: Eliminate config
+ of sdb versus dbx debug symbols. Add kludge for 68881 80-bit to
+ 64-bit float conversion.
+
+ tconfig/sun4, tconfig/sun3, xconfig/sun4, xconfig/sun3: Make
+ equivalent to sun?os4 so global config works.
+
+Wed Jan 2 18:20:51 1991 John Gilmore (gnu at spiff.cygnus.com)
+
+ Fix from Eberhard Mattes <mattes@azu.informatik.uni-stuttgart.de>
+
+ * main.c: Only declare linesize once; declare pagesize not at
+ all, since it is never used.
+ (main): Clear newly allocated line before it is used.
+
+Fri Dec 28 00:13:42 1990 John Gilmore (gnu at cygint)
+
+ Further stabilization for the Intel 960.
+
+ * Makefile.dist: Parameterize the location of the "include"
+ and "bfd" directories, as well as "getopt". Add symfile.c.
+ Link in both dbxread and coffread. Fix up "make depend" to
+ rewack the locations of include, bfd, and getopt in its output.
+
+ * README: Document moving include files, improve some of
+ the other doc.
+
+ * coffread.c: Move common code out to symfile.c. Change
+ symbol_file_command style interface to use new *_symfile_init
+ and *_symfile_read interface under BFD. Use BFD internal
+ info to locate line table, symbols, etc.
+
+ * core.c (core_fetch_registers): Rename to get_core_registers
+ to avoid confusion with fetch_core_registers.
+ (register_addr): Move to coredep.c, which is already machine
+ dependent. This leaves core.c pretty clean of dependencies.
+
+ * coredep.c (register_addr): Accept this routine from core.c.
+
+ * dbxread.c: Move common code (with coffread.c, etc) into new
+ symfile.c. Each psymtab now contains a pointer to the
+ format-dependent function that knows how to read it in. Make
+ some things static.
+ (dbx_psymtab_to_symtab): Renamed from psymtab_to_symtab_2.
+ (process_one_symbol): Add code to complain about a "compiler bug
+ we muzzle here", if we actually see it.
+
+ * eval.c (evaluate_subexp): Insert missing "break" statements
+ in code that determines whether a variable is an lvalue in
+ memory, register, or whatever. I detected this via a compiler
+ bug in which it *almost* mashed out the whole switch statement.
+
+ * gdb-int.texinfo: Add minor sections on configuring gdb for
+ release, and about the README file.
+
+ * infcmd.c (registers_info): Fix formatting somewhat. Still
+ not as pretty as before, but it handles byte swapping.
+
+ * remote-nindy.c: If data cache routines are interrupted while
+ waiting for the remote end, be sure that any uninitialized cache
+ blocks are on the free list, not on the valid list!
+
+ * symfile.h: Flesh out this header file with all the various
+ routines and variables that have been merged in from dbxread.c
+ coffread.c, and symtab.c to symfile.c.
+
+ * symfile.c: New file, containing code common to dbxread.c,
+ coffread.c, and some code from symtab.c. All generic code for
+ reading symbol files should be in here now.
+ (unrecord_misc_function): Remove unused function.
+
+ * symtab.h: Remove file-reading things to symfile.h.
+
+ * symtab.c: Remove file-reading things to symfile.c.
+
+ * tm-i960.h: Fix FRAME_CHAIN types; define PRINT_RANDOM_SIGNAL
+ to decode i960 fault types.
+
+ * target.h, remote.c, remote-eb.c, remote-vx.c, remote-nindy.c,
+ target.c: Change type of the "resume" function from int to void,
+ since its result was never used.
+
+Sat Dec 22 02:51:40 1990 John Gilmore (gnu at cygint)
+
+ * main.c: Replace "stupid" with "caution"; you now "set caution
+ on or off".
+
+ * printcmd.c (print_scalar_formatted): Fix typo in 'g' format
+
+ * infcmd.c (do_registers_info): Call val_print to deal with the
+ byte order of the registers being printed. FIXME, this makes
+ the formatting of the output uglier.
+
+ * infcmd.c (wait_for_inferior): If PRINT_RANDOM_SIGNAL is
+ defined, call it for signals the debugger doesn't itself use.
+ The i960 uses this for more detailed fault information.
+
+ * remote.c (remote_open): If arg is null, print help rather than
+ dumping core.
+
+ * sparc-xdep.c (register_valid): Avoid declaring size, since
+ various modules will think of various sizes depending on the
+ architecture of their tm-file. FIXME, we need protection against
+ actually entering one of those modules, which would clobber
+ storage if not for the target architecture compiled into gdb.
+
+ * stack.c (up_command, down_command): Always print the frame
+ you arrive at.
+ (up_silently_command, down_silently_command): New commands
+ for use in scripts.
+
+ * i960-pinsn.c (reg), i960-tdep.c: Lint.
+
+ * i960-tdep.c (i960_frame_chain_valid): Lookup_symbol now takes
+ more parameters than it used to.
+
+ * findvar.c (registers): Increase slop to 256 bytes, which should
+ protect us against even most RISC machines with large register
+ sets.
+ (locate_var_value): Move declaration inside related ifdef.
+
+ * remote-nindy.c (): Use TIOCSETN rather than TIOCSETP
+ throughout, to avoid throwing away buffered input from the board.
+ (nindy_wait): Supply_register takes addr_of_value, not value.
+ (i960_print_fault): Renamed from i80960_fault.
+ (nindy_fetch_registers): Avoid have_regs stuff, just get them.
+ (nindy_store_registers): Avoid regs_changed stuff, just stuff
+ them.
+ (nindy_create_inferior): Don't bother to write PC_REGNUM since
+ we can set the PC in the call to proceed(). Unpush nindy_ops
+ before pushing it on top, to avoid message to user. Eliminate
+ commentary from Unix machines that just misleads here.
+ (reset_command): Fix error message to suggest target command.
+
+Wed Dec 19 11:03:56 1990 John Gilmore (gnu at cygint)
+
+ Release 3.92.5 as frozen.
+
+ Stabilize the merged release...with help from lint, Saber C,
+ gcc -W, etc.
+
+ Everywhere: Add include files needed to declare return types
+ of functions called.
+
+ * gdb.texinfo: Roland Pesch is documenting gdb, glory be!
+
+ * breakpoint.h: Add undeclared breakpoint functions, and some
+ functions for display handling since I couldn't think of a better
+ .h to put them in.
+
+ * breakpoint.c (insert_breakpoints): Make code for disabling
+ shared library bkpts more likely to work. It's used when we
+ rerun a program and stop before the shared library has been
+ mapped in.
+ (breakpoint_cond_eval, bpstat_stop_status): Pass arg as int,
+ cast from pointer, so it squeezes through catch_errors.
+ (bpstat_stop_status): Fix logic broken some time ago. We now
+ always create a bpstat if the stop address matches a breakpoint,
+ even if we don't stop there -- just like the old code used to do
+ before I got my fingers into it (sigh).
+ (breakpoint_1): Print "ignore count" after "stop only if"
+ condition, since that's how it actually works.
+ (mention): Handle watchpoints as well as breakpoints.
+ (watch_command): use set_raw_breakpoint and mention to do most
+ of the work (and initialize all the fields!). Only pass one
+ arg to parse_c_expression, since that's all it takes.
+
+ * command.c (not_just_help_class_command): Rename arg to args
+ since we ignore "unused argument" warnings on vars named "args".
+ inflow.c (child_terminal_info): ditto.
+ infptrace.c (kill_inferior): ditto
+ main.c (catch_errors, version_info, quit_command, pwd_command,
+ source_command, dump_me_command, editing_info,
+ set_history_size_command, set_history, show_history,
+ set_verbose): ditto
+ stack.c (locals_info): ditto
+ target.c (target_files_info): ditto
+ valprint.c (set_input_radix, set_output_radix): ditto
+
+ * core.c: Remove old variables for handling core and exec file
+ sections (data_start, data_end, stack_start, stack_end,
+ reg_stack_start, reg_stack_end, reg_stack_offset, text_start,
+ text_end, exec_data_start, exec_data_end, text_offset,
+ exec_data_offset, data_offset, stack_offset). They're
+ superseded the more general build_section_table and
+ xfer_memory.
+ (get_exec_file): Mention the `file' command.
+ (read_memory_check): Rename to memory_error, and only call it
+ in the case of an actual error.
+ (read_memory, write_memory): call memory_error.
+ (core_fetch_registers): Register section name is ".reg".
+
+ coredep.c: Remove a bunch of crud now that all this file does
+ is pull the registers out of a core file.
+ (fetch_core_registers): Rewrite to actually work, I hope.
+
+ dbxread.c: Use a.out.gnu.h, not system a.out, now.
+ Replace index() with strchr(). Remove all the pre-BFD macro
+ definitions for accessing the symbol file.
+ (struct dbx_symfile_info): Encapsulate the information that
+ dbx_symfile_init needs to pass to dbx_symfile_read in this
+ struct.
+
+ (dbx_new_init, dbx_symfile_init, dbx_symfile_read,
+ dbx_symfile_discard): Rearrange symbol file reading to divide
+ the format-specific part from the format-independent part,
+ leaving the format-independent part such as file name expansion
+ and opening in symtab.c. This replaces
+ partial_symbol_file_open and partial_symbol_file_read.
+ Symbol_file_read, add_file, add_file_target_command,
+ add_file_addr_command move to symtab.c. Pass an explicit
+ "mainline" flag for when reading the main symbol table, rather
+ than relying on the offset address to be zero or nonzero.
+
+ (dbx_symfile_read): Don't allow void *'s to be printed as
+ typedefs.
+ (SWAP_SYMBOL): Use bfd routines to byte-swap the symbols.
+ (ADD_PSYMBOL_TO_LIST): Make the "function call rather than
+ macro" debug version really work.
+ (read_dbx_symtab): Remove unref'd parameter inclink.
+ Avoid swapping N_SLINE symbols, for speed.
+ Merge N_TEXT!N_EXT case with the other external symbol
+ definitions' case. Add comments.
+ (start_psymtab): Allocate the symfile name in the psymtab on
+ the psymbol_obstack, rather than using the caller's storage.
+ (end_psymtab): Only allocate a dependencies list if there are
+ more than zero.
+ (psymtab_to_symtab_2): Use BFD when reopening file to read
+ its symbols for real.
+ (read_struct_type): Add FIXME comments where it needs work
+ for C++ bogosity.
+ (read_huge_number): Add FIXME about overflows.
+ (read_range_type): Add FIXME about comparing a long to 1<<32.
+
+ * coffread.c: Minor changes to move things closer to the new
+ regime with symtab.c and dbxread.c Major work is still needed
+ here.
+
+ * exec.c (exec_file_command): Remove old variables (see core.c
+ above).
+ (xfer_memory): If memory transfer is right at the end of a
+ section, don't lose.
+
+ * findvar.c (get_saved_register): If value is in a real
+ register, LVAL is lval_register, not lval_memory.
+
+ frame.h: Declare print_sel_frame and record_selected_frame.
+
+ gdb-int.texinfo: New file, for GDB internals documentation.
+ Very simple, unformatted doc of cleanups is there for now.
+
+ gdbcore.h: Remove obsolete variables that described a.out
+ section addresses and offsets. (See core.c above.)
+ Declare fetch_core_registers and registers_fetched.
+
+ getopt.c: Declare char *alloca(); even on SPARC.
+
+ infcmd.c (run_command): Call target_kill rather than
+ kill_inferior.
+ (step_command, next_command, stepi_command, nexti_command):
+ Declare from_tty parameter even though we don't use it.
+ (run_stack_dummy): argument BUFFER is a char array, not
+ a pointer to REGISTER_TYPE.
+ (finish_command): using_struct_return needed a value *,
+ not a struct symbol *.
+
+ * infptrace.c (child_xfer_memory): To avoid dependency on
+ where sections are in memory, try PT_WRITE_D and if that fails,
+ try PT_WRITE_I. Most Unixes don't care which you use.
+
+ * infrun.c (step_resume_break_shadow): Change to array to
+ match other breakpoint shadow storage.
+ (clear_proceed_status): Pass address of bpstat to
+ bpstat_clear, not the bpstat itself.
+ (child_create_inferior): FIXME comment about if the child
+ exits.
+ (start_inferior): Remove old function.
+ (child_open): Use target_kill rather than kill_inferior.
+ (wait_for_inferior): Ditto.
+ (insert_step_breakpoint, remote_step_breakpoint): Use
+ new step_resume_break_shadow.
+
+ * inftarg.c (child_wait): If all child processes die,
+ pretend that the one being waited for exited with signal 42.
+
+ * main.c (command_line_input): When scanning for comments,
+ don't coredump on unclosed quotes.
+ (quit_command): Use target_kill rther than kill_inferior.
+ (_initialize_main): Rename class_user from "user" to
+ "user-defined".
+
+ * printcmd.c (print_command_1): Initialize "fmt" if no format
+ is specified by the user.
+ (print_frame_args): Only add to args_printed if we are
+ actually fetching args from the stack (avoiding undefined
+ arg_size).
+ (_initialize_printcmd): Remove bogus \{ from string.
+
+ * remote-eb.c (eb_open): Avoid coredump on no argument.
+
+ * remote-nindy.c: Bring out of Intel environment into new
+ target environment. Remove all conditional compilation on
+ I80960. Massive hacking throughout.
+ (nindy_xfer_inferior_memory): New routine stolen from
+ infptrace.c.
+ (nindy_create_inferior): New routine pieced together, probably
+ not quite working yet.
+ (nindy_ops): New target_ops struct for nindy.
+
+ * remote-vx.c: Use write_memory rather than target_write_memory
+ to get error checking.
+ (vx_add_file_command, vx_open): Use symbol_file_add rather than
+ add_file.
+ (vx_create_inferior): Use target_terminal_ours...
+
+ * signame.c (_initialize_signame): Always initialize, since
+ we need the table for things other than psignal.
+
+ * solib.c (solib_add): Use symbol_file_add, not add_file.
+ (solib_address): Return boolean result rather than struct
+ pointer which nobody else knows the type of.
+
+ * sparc-tdep.c, valops.c: Use write_memory rather than
+ target_write_memory, to get error checking.
+
+ * stack.c (locals_info, catch_info, args_info,
+ get_selected_block, frame_command, up_command): Use
+ target_has_stack, rather than have_inferior_p or
+ have_core_file_p.
+
+ * sun3-xdep.c (fetch_core_registers): Rewrite for new BFD regime.
+
+ * symfile.h: New file, defining the interface between the
+ generic and object-file-specific symbol reading code.
+
+ * symtab.c: Move generic symbol-reading interface to symtab.c,
+ from dbxread.c, coffread.c, mipsread.c, etc. Add symtab_fns
+ table to map BFD targets to symbol-reading modules in GDB.
+ Change index to strchr.
+ (lookup_struct_elt_type): Use error() rather than hand-made
+ simulations thereof.
+ (lookup_partial_symbol): Speedup slightly when length == 0.
+ (symbol_file_add): New function.
+ (symbol_file_command): Call it.
+ (symfile_open, symfile_init): New function.
+ (add_file_target_command, add_file_addr_command): moved from
+ dbxread.c.
+
+ * target.c (target_command): use target_kill.
+
+ * target.h (target_files_info): Don't declare, never called
+ from outside.
+
+ * tm-sun2.h, tm-sun3.h (STACK_END_ADDR): Use system include
+ files to determine stack end address.
+
+ * valarith.c (value_x_binop, value_x_unop): Change error message
+ to be more useful. Pass proper argument to value_struct_elt.
+
+ * valops.c (value_assign): FIXME comment that long long
+ bitfields will break here.
+
+ * Makefile.dist: Add symfile.h, remote-nindy.c, remote-eb.c.
+ Update `make saber_gdb' to work better.
+
+ * TODO: A woman's work is never done.
+
+ * cplus-dem.c, environ.c, inferior.h, infrun.c, inftarg.c,
+ main.c, obstack.c, printcmd.c, remote-eb.c, remote-nindy.c,
+ remote-vx.c, remote.c, solib.c, source.c, sparc-pinsn.c,
+ sparc-tdep.c, sparc-xdep.c, symmisc.c, symtab.c, symtab.h
+ target.c, terminal.h, tm-sparc.h, tm-sunos.h, utils.c,
+ valops.c, valprint.c, exec.c: Lint.
+
+
+Wed Dec 12 23:44:15 1990 John Gilmore (gnu at cygnus.com)
+
+ Continuing Intel 960 port merge of GDB.
+
+ * Makefile.dist: Merge i960 "nindy-share" files. Rename
+ malloc.h to gmalloc.h to avoid name conflicts in /usr/include.
+ Don't ship gdb.dvi in tar file. Link gdb with init.o, not init.c.
+ Wack over "make depend" so it handles files in subdirectories
+ vx-share, nindy-share, bfd, and in the current directory.
+
+ * blockframe.c (get_prev_frame_info): Remove fatal error
+ if stack not defined.
+
+ * core.c (core_open, core_detach): New functions that handle
+ the old "core-file" command as "target core" and "detach" instead.
+ (core_file_command): Call them.
+ (core_xfer_memory): Use common routine xfer_memory.
+
+ * dbxread.c: Include a.out.gnu.h, not system a.out.h.
+ dbxread now uses bfd for everything but symbol reading itself.
+ BFD internals are used to drag out the relevant file offsets.
+ (partial_symbol_file_open): Change args all around for BFD.
+
+ * symtab.c: Rename "value" to "val" everywhere, so we can
+ #include "value.h".
+ (symbol_file_command): New command, moved from dbxread.c
+ and coffread.c. It uses BFD to read the file, then vectors
+ based on its type, to dbx or coff symbol readers.
+ * symtab.h: Extern a few vars for symbol_file_command.
+
+ * target.h: Breakpoint takes a char * save area, not a char **.
+
+ * valprint.c (val_print): When unpacking bitfields, offset
+ the address in gdb of the value, if it is declared with a shorter
+ type. Remove the last "runtime kludge test" of host byte order.
+
+ * utils.c: Remove old my_bfd_read routine.
+
+ * stack.c (frame_info): Use target_has_stack. Print program counter
+ register's actual name rather than "pc", since it's called the
+ "ip" (instruction pointer) on the i960 (sigh).
+
+ * target.c (target_command): Add command for selecting a target
+ type and calling its open routine. This is used for initiating
+ communication with a particular target, in a generic way.
+
+ * tm-i960.h: Update for modern gdb. Remove semicolons from
+ various macros. Handle reading struct return convention, and
+ error-out attempts to return structs with the "return" command.
+ Be sure gdb doesn't think we know how to call functions in the
+ inferior.
+
+ * i960-tdep.c: Rename FRAME_CHAIN_VALID and FRAME_FIND_SAVED_REGS
+ to i960_xxx in lower case.
+ (arg_address): Circumvent errors due to LOC_ARG_BLOCK
+ not being defined yet.
+
+ * remote.c (remote_open): Call start_remote to initialize
+ wait_for_inferior during open.
+ (remote_xfer_inferior_memory): Return length written rather
+ than errno value.
+
+ * remote-vx.c (target_command -> vx_open): Use new generic
+ target command.
+ * remote-eb.c, inftarg.c, exec.c: ditto.
+
+ * infrun.c: Fix comments.
+ (attach_program -> child_open): Use new generic target command.
+ (wait_for_inferior): Clear saved register values before target_wait,
+ so target_wait can set some of them if convenient.
+
+ * infptrace.c (fetch_inferior_registers, store_inferior_registers):
+ Return success indicator, not void.
+ (child_xfer_memory): Avoid fetching initial word if we'll
+ overwrite it anyway.
+
+ * infcmd.c (attach_command): Use new generic target open routine.
+ (_initialize_infcmd): Update doc on attach and detach commands.
+ (do_registers_info): Merge in a byte-order problem as a FIXME
+ comment.
+
+ * findvar.c (find_saved_register): Avoid problem in current frame.
+ (read_relative_register): Ditto.
+ (write_register): Convert byte order on the way out.
+
+ * exec.c (file_command): Add.
+ (add_to_section_table, exec_command): Use new bfd_map_over_sections.
+ (xfer_memory): Common function between core_xfer_memory and
+ exec_xfer_memory.
+ (exec_xfer_memory): Use it.
+
+ * pn-opcode.h: Document that a "PN" is a Gould PowerNode.
+
+ * breakpoint.c, breakpoint.h, symtab.h, value.h, frame.h, utils.c,
+ valops.c, stack.c, target.c, sparc-xdep.c, source.c, printcmd.c,
+ infcmd.c, i960-pinsn.c, eval.c, defs.h: lint and gcc -Wall.
+
+Sun Dec 2 16:45:06 1990 John Gilmore (gnu at cygnus.com)
+
+ Merge Intel 960 port of gdb, continuing...
+
+ * dbxread.c (partial_symbol_file_open, partial_symbol_file_read,
+ symbol_file_command): Pass from_tty arg to hush 'em up.
+
+ * coffread.c (symbol_file_command): Avoid output if from_tty != 1.
+ Add magic numbers for 960 COFF format.
+
+Fri Nov 30 09:18:20 1990 John Gilmore (gnu at cygnus.com)
+
+ Merge Intel 960 port of gdb, from Intel "1.2" release.
+
+ CHANGE_LOG entries from their port, which was based on
+ gdb+-2.8.0:
+
+ Thu Sep 6 11:02:22 PDT 1990
+ Remove temp file if download is interrupted.
+
+ Wed Aug 1 09:08:33 PDT 1990
+ Now uses binary protocol to talk to NINDY.
+ Old hex protocol (NINDY 2.13 and older) supported with -O switch.
+ Times out after 5 seconds when trying to talk to NINDY.
+
+ Tue May 29 12:54:49 PDT 1990
+ Added variable baud rate (-b switch).
+ Source code reorganization.
+
+ Thu Apr 26 11:09:55 PDT 1990
+ More cleanup of batch mode; specifically, execute "-s", "-e", and
+ "-se" switches as soon as they are encountered on the invocation line.
+
+ Fri Apr 20 13:47:15 PDT 1990
+ Add -brk switch.
+
+ Thu Apr 19 09:54:28 PDT 1990
+ Add 'reset' command.
+
+ Wed Apr 18 09:48:07 PDT 1990
+ After opening remote tty, wait for 1 second to go by without input
+ from it before trying to talk to NINDY (fixes problems with the
+ Heurikon HK80/V960E).
+
+ Mon Apr 4 16:33:05 PDT 1990
+ Some output was not being suppressed in 'batch' mode.
+
+ Thu Mar 22 15:31:11 PST 1990
+ Ask user if old symbol table should be deleted when new file is
+ downloaded.
+
+ Allow user to run a program downloaded before gdb960 was brought up.
+
+ Correct "exec-file" help message for i80960 context.
+
+ Correct bug in calculating user space address: could occasionally
+ corrupt user program.
+
+ Make sure to zero low-order bits in rip's because of bug in 960CA
+ A-step part: could cause operation faults when "next"ing across
+ a function call.
+
+ Correct bug that made it impossible to get source line numbers for
+ code loaded at addresses higher than 0x7fffffff.
+
+ Wed Jan 10 12:43:22 PST 1990
+ Open remote tty for exclusive use.
+
+ Fri Jan 5 12:14:42 PST 1990
+ Correct disassembly (CA manual was right after all):
+ opcode for sysctl is 0x659
+
+ Mon Oct 23 12:03:04 PDT 1989
+ Use G960BASE and G960BIN environment variables to find 'sx' utility.
+
+ Mon Oct 16 14:15:09 PDT 1989
+ "sfr0"-"sfr31" should have been named "sf0"-"sf31"
+
+ Mon Oct 2 15:56:31 PDT 1989
+
+ Added 960CA disassembly support.
+
+ To simplify maintenance:
+ - eliminated use of symblic links on pinsn.c: use i960-pinsn.c
+ directly instead.
+ - eliminated opcode.h: incorporates tables into i960-pinsn.c
+ - moved 960-specific routines from i960-pinsn.c to i960-md.c
+ - made disassembly interface identical to that in gdmp960.
+
+
+
+Wed Nov 28 21:32:48 1990 John Gilmore (gnu at cygint)
+
+ * target.h: Allow targets to stack. Add target_has_memory,
+ _registers, etc. Restructure memory access and "info files"
+ to walk the target stack.
+ * exec.c, core.c, inftarg.c, remote.c, remote-vx.c, remote-eb.c,
+ target.c: Change tables to match target.h.
+ * inflow.c (child_mourn_inferior): pop child_ops.
+ (generic_mourn_inferior): Use new has_stack flag.
+ * infptrace.c (child_xfer_memory): New memory regime.
+ * inftarg.c (child_files_info): New "info files" regime.
+ * remote-eb.c: New memory regime, new info files.
+ * remote-vx.c: New memory regime, new info files. Now use
+ separate targets for VxWorks attachment to machine, and
+ actually running a process under VxWorks, since one has
+ stack & execution & regs and the other doesn't.
+ * remote.c: New memory regime, new info files.
+ * sparc-xdep.c (fetch_core-registers): New memory regime.
+ * target.c: New routines and support for stacked targets,
+ new memory regime, new info files regime.
+
+
+ Generalize section handling for an arbitrary number of sections,
+ including use of the new BFD (binary file) library.
+ * gdbcore.h: Add struct section_table.
+ * exec.c (build_section_table): Iterate all sections and
+ record what gdb needs to know about them.
+ (exec_command): Use it.
+ (exec_xfer_memory): Use the table.
+ (exec_files_info): Print the table.
+ * core.c (core_file_command, core_xfer_memory, core_files_info):
+ Likewise.
+ * source.c (find_source_lines): Use bfd_get_mtime.
+ * dbxread.c: Quick changes to make it compile with new BFD.
+ * utils.c (error): Avoid using bfd_error in generic routines.
+
+ * core.c (core_fetch_registers): Get from the ".regs" section of
+ the BFD core file.
+ * sparc-xdep.c (fetch_core_registers): Use the .regs info.
+
+ * inferior.h (attach_flag): Export.
+ * infcmd.c (run_command): use new target_create_inferior.
+ * infrun.c (child_create_inferior): Don't return result.
+ * Makefile.dist (VERSION): 3.91.4.
+
+Fri Nov 23 28:15:38 1990 John Gilmore (gnu at cygint)
+
+ * breakpoint.c (bpstat_num): Handle breakpoints which have
+ since been deleted, such as temporary breakpoints.
+ infcmd.c (program_info): ditto.
+
+ * core.c (core_file_command): Display the frame where the core
+ dump occurred.
+
+ * main.c: lint.
+
+ * remote-vx.c (target_command): Merge in target command from
+ targ-vx.c. A few other cleanups.
+
+ * TODO, Projects: Lots more stuff to do...
+
+Fri Nov 23 18:15:38 1990 John Gilmore (gnu at cygint)
+
+ Massive changes to wall off the remote-debugging interface
+ behind a function vector. The port to handle VxWorks targets
+ is also part of this.
+
+ All files: Replace references to renamed functions,
+ remove references to remote_debugging, remove references to
+ have_include_file, have_core_file in favor of target_has_stack,
+ target_has_memory, etc.
+
+ * Modularize the breakpoint interface.
+ breakpoint.h (BREAKPOINT_MAX): New define sets max length of
+ a breakpoint instruction.
+ breakpoint.c: struct breakpoint's shadow_contents now sized as
+ BREAKPOINT_MAX.
+ (insert_breakpoints): Vector to target to install breakpoints.
+ (remove_breakpoints): Vector to target here too.
+ Remove REMOTE_SA_SPARC kludges and other remote_debugging.
+ sparc-tdep.c (single_step): Use new breakpoint interface for
+ the single-step breakpoints.
+ mem-break.c (memory_insert_breakpoint, memory_remove_breakpoint):
+ New file, contains routines to insert and remove breakpoints by
+ reading out the old contents and later replacing them. This is
+ how ptrace breakpoints work, and many remote systems as well.
+
+ * tm-vxworks68.h: New config file, overrides a few things for
+ Wind River's preferences.
+
+ * target.h: New file, for transfer vector used to talk to the
+ inferior (child, attached, core, exec, remote, etc). All accesses
+ to the thing being debugged should come through these vectors.
+ target.c: New file, routines to handle transfer vector.
+ (various files): Add transfer vectors XXX_ops for the various
+ targets and pseudo-targets (core files, etc) we support.
+
+ * breakpoint.c (bpstat_stop_status): Further explorations of
+ watchpoints and why things don't work all the time.
+ (bpstat_alloc): New fn to allocate a bpstat and chain it.
+
+ * config.gdb: Only add "source ${srcdir}/.gdbinit" to
+ the local gdbinit if it doesn't already have it.
+
+ * core.c (core_ops): add and install.
+ Allow core debugging without exec file.
+
+ * dbxread.c (free_and_init_header_files): Merge two fns.
+ (end_symtab): Free named symbol table when a new version comes in.
+ (read_dbx_symtab): Relocate all kinds of symbols with base
+ address. First step toward handling different text, data, bss
+ reloc.
+ (add_file_addr_command): Renamed add_file_command.
+ (add_file_command): Vector to remote handler.
+ Add "load" as an alias for "add-file" command.
+
+ * defs.h: Allow "volatile" to be used in non-ANSI; use it for
+ non-returning functions.
+
+ * exec.c: Add exec_ops, and push it as a target when an exec
+ file is specified.
+
+ * infcmd.c (run_command): Pass executable file name and arg list
+ separately when starting an inferior. Permit "run" when no exec
+ file is specified, for VxWorks.
+ (detach_command): Move to child_detach in inftarg.c.
+
+ * inftarg.c: New file. Unix-child-specific routines, and the
+ child_ops structure.
+
+ * inferior.h (registers): Export "registers" as the way for
+ target dependent register handlers to find gdb's local copy of
+ the registers. Rename "stop_after_attach" to "stop_soon_quietly"
+ since it is now used by places that want wait_for_inferior to
+ handle the grunge but want to see every trap from the inferior.
+
+ * inflow.c (create_inferior): Pull out, and merge into infrun.c.
+ Eliminate remote_debugging hooks in terminal handling.
+
+ * infrun.c: Replace start_inferior with child_create_inferior.
+ Move all the hair of Unix shells and ptrace idiosyncracies into
+ child_create_inferior, so remote handlers don't have to deal.
+ Remove running_in_shell. Rename stop_after_attach to
+ stop_soon_quietly, and use it in a few other places where we want
+ to just call wait_for_inferior and get control back on the first
+ trap. trap_expected now never takes a value > 1.
+ (init_wait_for_inferior): Initialize static vars when a new
+ process is created.
+
+ main.c (gdbinit): Add new hook for .gdbinit file name, let
+ it be overridden by config files as GDBINIT_FILENAME.
+ (DEFAULT_PROMPT): Add new hook for overriding (gdb) prompt.
+ Both of these are used for VxWorks gdb.
+
+ mcheck.c: rename include file "gmalloc.c" to avoid problems
+ with system include file "malloc.c".
+
+ param-no-tm.h: New include file, same as param.h but does not
+ include the default "tm.h" file. This is used in files where
+ the target is known, e.g. remote-eb.c or sparc-xdep.c.
+
+ param.h: Now just a shell that includes tm.h and param-no-tm.h.
+
+ remote-vx.c: New file, VxWorks remote debugging support. Uses
+ RPC routines that are shared with the target system, in directory
+ ${srcdir}/vx-share.
+
+ remote.c: Vectorize remote interface.
+
+ source.c: Globalize source_path, and make an alias "l" for "list"
+ since we now have the "load" command.
+
+ sparc-xdep.c: Use new param-no-tm.h.
+
+ symmisc.c (free_named_symtab): Add new function from Wind River.
+ However, ifdef it out for now while we think about what it should
+ really be doing.
+
+ tm-sun3.h, xm-sparc.h, xm-sun3.h, xm-symmetry.h: Move
+ PREPARE_TO_STORE to
+ the xm- file, and change its name to CHILD_PREPARE_TO_STORE, since
+ non-Unix-children handle this with their own code in the target
+ transfer vector.
+
+ Makefile.dist: Roll version to 3.92.3. Add vx-share stuff to
+ source and target lists. Add vx-share to default list of include
+ directories. Add new files to src and target lists: mem-break,
+ target, inftarg, remote-eb, remote-vx, targ-vx. Be sure the
+ ${srcdir} versions of munch and createtags are used.
+
+ * valops.c (find_function_addr): Split out of call_function.
+ (call_function_by_hand): Rename call_function; this function
+ calls functions in the target by laboriously patching the target
+ word-by-word with the right stack, args, regs, etc.
+
+
+Mon Nov 5 17:29:10 1990 John Gilmore (gnu at cygint)
+
+ Handle AMD 29000 a bit better.
+
+ * remote-eb.c (readchar): Mask received char log to make it readable.
+ (remote_start): Pass arguments down to executing program.
+ Make startaddr unsigned.
+ infrun.c (start_inferior): Accept args, pass them to
+ remote_start.
+ infcmd.c (run_command): Pass args down to start_inferior.
+
+ * tconfig/am29k-aout, tconfig/am29k-coff: New files specifying
+ the target object file format.
+ tm-29k.h: Pay heed to COFF_ENCAPSULATE.
+
+ * am29k-pinsn.c (print_insn): Print 0x on hex numbers in disassembly.
+ am29k-tdep.c (examine_prologue): Better checking of function prefixes.
+
+Sun Oct 7 18:20:45 1990 John Gilmore (gnu at cygint)
+
+ * Makefile.dist (VERSION): Roll version to 3.91.9 and freeze.
+ * TODO: We did a few things, we have more to do though.
+
+ * xm-sparc.h (CLEAR_DEFERRED_STORES): Define.
+ * inflow.c (inferior_died): Clear deferred stores.
+
+ * Debug problems with dummy frames and calls to the inferior.
+ * tm-sparc.h (PUSH_DUMMY_FRAME, POP_FRAME): Move to sparc-tdep.c.
+ * sparc-tdep.c (do_restore_insn): Simplify.
+ (sparc_frame_find_saved_regs): Simplify and fix what we find.
+ (sparc_push_dummy_frame): Simplify and fix what we push.
+ (sparc_pop_frame): Slightly more hair here, deciding whether
+ we are restoring a saved PC or returning to a return address in %i7.
+ * sparc-xdep.c (read_inferior_registers): Debug if valid reg is read.
+
+ * utils.c (xmalloc, xrealloc): Return type depends on __STDC__.
+ * symtab.h (xmalloc): ditto, for obstack_chunk_alloc.
+ * obstack.h (chunkfun): ditto.
+ * defs.h (xmalloc, xrealloc): ditto
+
+ * utils.c (quit): Grab the terminal from the child if necessary.
+
+ * inflow.c (term_status_command): Rename to term_info, change
+ to "info terminal".
+
+ * sparc-pinsn.c (print_insn): Disassembly prefers real instructions.
+ (is_delayed_branch): Speed up.
+ * sparc-opcode.h: Add ALIAS bit to aliases. Fix up opcode tables.
+ Still missing some float ops, and needs testing.
+
+ * Support for input and output radixes other than base 10
+ * defs.h (input_radix, output_radix): Declare.
+ * expread.y (yyparse, parse_number): Handle changes of input
+ radix, and ambiguous names-or-numbers in radixes >10.
+ * printcmd.c (print_scalar_formatted): Print formatted hex
+ numbers in varying column widths.
+ * valprint.c (val_print): Use output_format to print scalar ints.
+ (set_input_radix, set_output_radix, set_radix): Create.
+ (set_output_radix): Set output_format from output_radix.
+ (_initialize_valprint): add `set radix' but leave the others off.
+
+ * main.c (execute_command): Let stupid questions be turned off.
+ (_initialize_main): Handle "set stupidity", etc.
+
+ * main.c, inflow.c, inferior.h, frame.h, command.c, defs.h,
+ sparc-pinsn.c, sparc-xdep.c, value.h, valops.c, values.c: Lint.
+
+Tue Oct 2 11:20:02 1990 John Gilmore (gnu at cygint)
+
+ * TODO, Makefile.dist, ChangeLog: Freeze for 3.91.8 release.
+ bfd stuff is still screwed up, but with some manual work, it
+ compiles.
+
+ * breakpoint.c (bpstat_do_actions): Start over if a command
+ proceeds the inferior, since the inferior will have stopped and
+ will need to have its new stop-actions taken care of.
+
+ * dbxread.c (read_struct_type): Expression gives Sun3 4.0.3
+ compiler fits, simplify it.
+
+ * gdb.texinfo (directory command): Doc new dir command.
+ source.c (directory_command): "dir" now puts things on the front
+ of the path, moves dups up front, and handles multiple names
+ on the command line, inserting each one in order. It also
+ blows away cached line and full_filename info.
+
+ * stack.c (backtrace_command): Skip "more stack frames follow"
+ unless interactive.
+
+ * Change #ifndef HAVE_VPRINTF to #define MISSING_VPRINTF in
+ xm-convex.h, xm-hp300bsd.h, xm-isi.h, xm-merlin.h, xm-news.h,
+ xm-np1.h, xm-pn.h, xm-pyr.h, xm-symmetry.h, xm-umax.h, xm-vax.h.
+ The only odd one was Gould NP1, which had defined vprintf to
+ "printf"!!!
+
+ * Merge Ted Goldstein <tedg@Eng.sun.com>'s changes for epoch.
+ printcmd.c (print_command_1): Pass 'inspect' flag down as a global
+ variable, inspect_it.
+ valprint.c (print_string, val_print): Use the global inspect_it
+ to indicate whether to print in Epoch style or normal style.
+
+Mon Oct 1 23:55:26 1990 John Gilmore (gnu at cygint)
+
+ * printcmd.c (call_command): add an alias for the "print" command
+ which runs expressions and doesn't print the result if void.
+ (print_command_1): implement it.
+
+ * command.c: Remove #if 0'd code. Initialize all the fields
+ in add_cmd (). Rename do_nothing_command to
+ not_just_help_class_command, and make it externally visible.
+ command.h: add user_commands to struct.
+ * main.c (define_command): Don't overload c->function with a char
+ string as well as a function pointer.
+
+ * eval.c (evaluate_subexp): Reinstall tiemann changes to
+ calling convention of value_struct_elt () that got dropped in
+ merge.
+
+ * tm-sparc.h (FRAME_FIND_SAVED_REGS): move to sparc-xdep.c.
+ sparc-tdep.c (sparc_frame_find_saved_regs): ditto.
+
+ * tm-sparc.h (POP_FRAME): replace some constants with defines.
+
+ * sparc-xdep.c (store_inferior_registers): defer stores to regs
+ until a good time (e.g. when we are about to run the child),
+ saving ptrace calls.
+ * infrun.c (proceed): handle DO_DEFERRED_STORES.
+ * tm-sparc.h: define DO_DEFERRED_STORES.
+
+ * sparc-xdep.c (store_inferior_registers): when storing float
+ registers, don't store stack regs too. When storing the SP,
+ however, DO store the stack regs too. This fixes a bug in which
+ the dummy frame is not recognized when a call_function finishes,
+ because its frame pointer (in the stack regs) was never
+ initialized.
+ (read_inferior_registers): Mark WIM and TBR and FPS and CPS valid
+ even though we don't know how to read them from an inferior.
+ valops.c (call_function): Comment about storing SP.
+
+ * infrun.c (save_inferior_status): Save away the original bpstat
+ chain so it can be restored later. Install the copied version for
+ use by whoever saved the status. It will be blow away by
+ restore_inferior_status, and the original chain restored. This is
+ important for people who have pointers into the original.
+
+ * breakpoint.c, command.h, copying.awk, dbxread.c, defs.h,
+ findvar.c, frame.h, obstack.h, obstack.c, inflow.c, value.h,
+ main.c, printcmd.c, sparc-tdep.c, symtab.c, valprint.c: lint
+
+
+Fri Sep 28 20:32:46 1990 John Gilmore (gnu at cygnus.com)
+
+ * Makefile.dist: Roll version to 3.91.8. Add bfd.h and bfdconfig.h
+ temporarily to the makefile. Add am29k-opcode.h and WHATS.NEW.
+ Add stuff.c and kdb-start.c to the OTHERS list for tar files.
+
+Fri Sep 28 19:12:12 1990 John Gilmore (gnu at cygint)
+
+ * Merge Mike Tiemann's multiple inheritance changes from Sun.
+ Store the baseclasses in a type struct starting from array element
+ 0 rather than from the unusual array element 1.
+
+ dbxread.c: the above.
+ (virtual_context): Add
+ Read new debug information about which virtual function table
+ a virtual function is from, and store it in fn_field.fcontext.
+
+ symtab.h: Add fcontextt. Fix baseclass indices. Typo in
+ TYPE_FN_FIELD_STATIC_P.
+
+ symtab.c: the above.
+ valops.c: the above. Handle pointer casts of object *'s.
+ (search_struct_method): Add.
+ (value_struct_elt): First arg is now a pointer to a value, and is
+ modified on return.
+
+ valprint.c: the above.
+ values.c (value_virtual_fn_field): Add type arg. Handle
+ offsetting to the proper object when calling virtual fns.
+ The above.
+ (baseclass_addr): Add valuep arg.
+
+ * README: Document the current state of BFD config (missing).
+ * TODO, ChangeLog, Makefile.dist: Roll version.
+ * WHATS.NEW: Add summary of changes since 3.5.
+
+Thu Sep 27 16:23:12 1990 John Gilmore (gnu at cygint)
+
+ * dbxread.c (read_struct_type): Clear bit vectors whenever
+ we allocate one.
+ symtab.c (B_CLRALL): define.
+
+ * tm-sparc.h (STORE_RETURN_VALUE): Avoid clobbering types by
+ using == rather than =. Huh... This fixes the dreaded problem
+ wherein builtin_type_int becomes TYPE_CODE_FLT.
+
+ * core.c (info_files): Show the inferior pid.
+
+ * config.gdb: Avoid putting "dir" command into .gdbinit. GDB
+ already knows how to look in the source directory.
+
+ * Remove psymtab hair from many places. Remove duplicated code
+ for searching symbol tables. Hide psymtabs from most places.
+ Make it fast to get from a psymtab to its symtab.
+
+ blockframe.c (blockvector_for_pc): Remove psymtab hair.
+ coffread.c (psymtab_to_symtab): Rename to psymtab_to_symtab2.
+ mipsread.c (psymtab_to_symtab): Rename to psymtab_to_symtab2.
+ dbxread.c: export psymtab_to_symtab, make it work if called N times.
+ (psymtab_to_symtab): Rename to psymtab_to_symtab2. Initialize
+ new symtab completely. New psymtabs get symtab pointer
+ initialized to zero. Remove MI warning printf.
+ symtab.h: Comments. Add psymtab to symtab pointer.
+ (PSYMTAB_TO_SYMTAB): New macro.
+ symtab.c: use PSYMTAB_TO_SYMTAB. Add psymtab_to_symtab and export it.
+ source.c: use PSYMTAB_TO_SYMTAB. Remove symtab version and
+ compilation fields.
+ stack.c (backtrace_command): Avoid pre-pass to read symbols, if
+ verbose is not set.
+ (print_frame_info): Avoid special-casing symbols that have not yet
+ been read in.
+
+ * source.c (open_source_file): Quick path if we have already
+ located the source file by its full name.
+
+ * symtab.c (lookup_symbol): Use find_pc_symtab rather than
+ find_pc_psymtab. When a name is found in the misc function
+ vector, search the symbol table for its mangled name, not the
+ name that the user typed.
+
+ * bfd.h: Fix missing comment terminators, make #endifs match.
+
+ * valarith.c (value_less): Handle unsigned int comparisons.
+ Add FIXME about pointer compares, which assume host and target
+ pointers are the same.
+
+ * command.c (do_nothing_command): lint
+ dbxread.c: lint. Remove sort_syms. Document C++ visibility info,
+ fix comments on debug symbol format for visibility. Actually set
+ visibility of symbols.
+ main.c (echo_command): lint; use <readline/history.h>.
+ tm-sparc.h (FRAME_FIND_SAVED_REGS): lint
+ obstack.h (_obstack_blank): Rearrange pointer math to avoid
+ pointing past end of allocated memory; saber complains.
+ obstack.h: Declare the external functions that we use.
+ valarith.h: use <string.h>
+ solib.c (solib_add): lint.
+
+Fri Sep 21 17:05:19 1990 John Gilmore (gnu at cygint)
+
+ * main.c (initialize_main): Default info_verbose to off, now that
+ symbol reading is fast.
+ (quit_command): Avoid clobbering exec_bfd while quitting.
+
+ * Initial BFD (binary file diddling library) merger:
+ coffread.c: Change AOUTHDR to struct exe_hdr.
+ dbxread.c: ditto.
+ core.c: initialize initialized data at compile time.
+ (core_file_command): Move from coredep.c, convert to bfd.
+ (xfer_core_file): Convert to bfd.
+ exec.c (exec_file_command): use bfd routines.
+ gdbcore.h: BFD.
+ mips-tdep.c: Remove exec_file_command and friends.
+ source.c: bfd.
+
+ * coredep.c: (fetch_core_registers) Convert core_file_command to
+ fetch_core_registers.
+ mips-xdep.c, sparc-xdep.c, sun3-xdep.c: ditto.
+
+ * utils.c: (error): Bogus crap, FIXME, to print bfd errors.
+ (my_bfd_read): More bogosity, which I don't think we call.
+ (program_name): Remove this atrocity asap!
+
+Wed Sep 19 13:36:41 1990 John Gilmore (gnu at cygint)
+
+ * From Per Bothner:
+ values.c: allocate_repeat_value was not clearing the
+ optimized_out field.
+ (value_static_field): minor stylistic fix (wrong macro was used).
+ valops.c (value_struct_elt_for_address): didn't work for C++
+ static fields.
+
+ * signame.c (_initialize_signame): Initialize signal names once.
+
+ * breakpoint.h, command.c, copying.awk, defs.h, environ.c,
+ exec.c, frame.h, infcmd.c, inferior.h, main.c, munch, sun3-xdep.c,
+ symtab.h, tm-29k.h, valprint.c, value.h, values.c: Lint.
+
+ * remote-eb.c: Support user-settable baud rates on the serial port.
+
+ * tm-sun3.h (PREPARE_TO_STORE): fix typo.
+
+Fri Sep 14 13:28:29 1990 John Gilmore (gnu at cygint)
+
+ * tconfig/sun3os4: Remove warning about native assembler,
+ since it also occurs in the xconfig file.
+
+ * findvar.c (registers): Allocate some slop after `registers'
+ to prevent stray accesses from trashing the next variable.
+
+ * tm-68k.h (REGISTER_BYTES): Allocate the right number of bytes
+ on the sun-3, by changing the #ifdef from `sun3' (which is not
+ defined by cc) to `sun'. Symptom was trashed builtin_type_XXX
+ vars, which happened to follow `registers' in the executable.
+
+ * readline/history.c (history_search): Heed gcc-2's advice
+ and parenthesize && inside ||).
+
+ * am29k-opcode.h, am29k-pinsn.c, am29k-tdep.c, remote-eb.c,
+ tm-29k.c: Insert FSF copyright headers.
+
+ * remote-eb.c: Better comments.
+
+ * Makefile.dist: Update to 3.91.6.
+ * TODO: note PREPARE_TO_STORE problem.
+
+Thu Sep 13 09:52:33 1990 Jim Kingdon (kingdon at cygint)
+
+ * stack.c (frame_info): Only use FRAME_FIND_SAVED_REGS if defined.
+
+ * remote.c: Wrap the whole file in #if !defined (SPECIAL_REMOTE).
+
+ * infrun.c (wait_for_inferior, at end): Don't set up
+ prev_* if the inferior no longer exists.
+
+ * inferior.h (CALL_DUMMY_LOCATION): New macro, to replace
+ CANNOT_EXECUTE_STACK.
+ valops.c (call_function): Use it.
+
+ * tm-convex.h: Add CALL_DUMMY_LENGTH for use by PC_IN_CALL_DUMMY.
+
+ * inferior.h (PC_IN_CALL_DUMMY): New macro.
+ infrun.c (wait_for_inferior, 2 places): Use it.
+
+ * values.c (value_being_returned): Only use
+ EXTRACT_STRUCT_VALUE_ADDRESS if defined.
+
+ * Move PREPARE_TO_STORE from xm-sun3.h to tm-sun3.h to do the
+ right thing for remote-eb.c.
+
+ * sun3-xdep.c: Remove extraneous call to remote_store_registers.
+ * sun386-xdep.c, hp300hpux-xdep.c, sparc-xdep.c: Ditto.
+
+ * blockframe.c: Put get_frame_saved_regs inside #if !defined
+ (FRAME_FIND_SAVED_REGS).
+
+ * findvar.c ({fetch,store}_registers): Check for
+ REMOTE_{FETCH_STORE}_REGISTER macro.
+
+ * findvar.c (get_saved_register): Add argument lval and
+ change meaning of argument addr.
+ findvar.c: Change calls to get_saved_register to reflect
+ new calling convention.
+ valops.c (value_assign): Use get_saved_register instead of
+ find_saved_register.
+
+Sun Sep 2 12:40:20 1990 Jim Kingdon (kingdon at cygint.cygnus.com)
+
+ * coffread.c (read_one_sym): Make temp_aux an AUXENT, not
+ an (uninitialized) pointer to one. Use "&" when passing it
+ to fread.
+
+Fri Aug 31 22:57:54 1990 Jim Kingdon (kingdon at cygint.cygnus.com)
+
+ * coffread.c (getfilename): Use DGUX x_offset and x_name if
+ defined.
+
+ * coffread.c (symbol_file_command): Put semicolon after
+ "int from_tty".
+ Put safe_to_init_tdesc_context in #if defined (TDESC).
+ Put #ifdef TDESCs in 1st column for non-ANSI cpp's.
+ coffread.c: #include <sys/stat.h>.
+ (read_coff_symtab): Typo: in_source_files -> in_source_file.
+ Add missing ')' in check for "lc%" and friends. Remove
+ extraneous '}'.
+ Declare read_one_sym() at top of file.
+ (read_file_hdr): Put in extra #ifdefs so MC68MAGIC and
+ MC68WRMAGIC can have the same value without causing a duplicate
+ case.
+
+Thu Sep 13 15:55:36 1990 John Gilmore (gnu at cygint)
+
+ * Allow a Makefile to be built without building the
+ tm and xm file links that screw up builds in subdirectories.
+ This is done with `config.gdb none', then you can do things
+ like `make gdb.tar.Z'.
+ * tconfig/none: Config file for no target system
+ * xconfig/none: Config file for no host system
+ * config.gdb: If no TM or XM files are called out by the
+ host or target file, don't make links for them.
+
+ * cplus-dem.c: Add documentation.
+
+ * dbxread.c (read_ofile_symtab): Turn a fatal error into a
+ simple error, so the user's gdb doesn't crash due to some object
+ file problem (e.g. somebody is rebuilding the file out from under
+ gdb).
+
+ * printcmd.c (print_address_symbolic): demangle the symbol.
+
+ * Makefile.dist (OTHERS): Remove tdesc-lib because it has
+ Motorola copyrights in it. Make "make gdb.tar.Z" work.
+ (alldeps.mak): sort and uniq all results from this; duplicates
+ hose gdb.tar.Z link building. Remove RCS files from
+ tconfig and xconfig. Add config files for sun386. Add
+ a few odd files to OTHERS and HFILES.
+
+Mon Sep 10 21:20:24 1990 John Gilmore (gnu at cygint)
+
+ * Makefile.dist: Pull solib.c to tconfig/sun?os4.
+ Roll version number to 3.91.5. Make lint work in bindir.
+
+ * README: Document cross-debugging and new file structure.
+
+ * blockframe.c: Lint. Include "value.h" to declare read_register.
+ (find_pc_partial_function): remove duplicate line.
+
+ * command.h: Lint. Declare error_no_arg and dont_repeat.
+
+ * tm-news.h: Remove inadvertently duplicated stuff.
+
+ * mipsread.c: Remove cache_pc_function stuff, now done cleanly.
+ Clean up usage of misc_function_type. Declare some CORE_ADDRs.
+
+ * config.gdb: Allow `config.gdb host target' form. Clean
+ up previous change that printed bogus messages when you just said
+ `config.gdb'.
+
+ * core.c: #include "command.h" for lint.
+ * dbxread.c: lint
+ * eval.c: lint
+ * main.c: Remove some casts of enums. Lint.
+ * source.c: lint
+ * symtab.c: lint
+ * symtab.h: lint
+ * expread.y: lint
+ * valarith.c: lint
+
+ * printcmd.c (initialize_printcmd): Fix thinko in inspect cmd.
+
+ * sparc-tdep.c (isannulled): Take instruction as parameter, don't
+ read it from memory. This will allow us to save ptrace calls
+ eventually. Changed caller single_step too.
+
+ * sparc-xdep.c (fetch_inferior_registers): Avoid reading regs
+ that we aren't going to use, saving many ptrace calls, especially
+ when watchpointing or single stepping. Use some #define's for
+ constants.
+ (store_inferior_registers): Ditto.
+ (core_file_command): Use some #define's for constants.
+
+ * tm-sparc.h: Add #define's for some register numbers, so we
+ can eliminate the use of random constants in sparc-xdep.c.
+
+ * stack.c (frame_command, print_frame_info, up_command,
+ down_command) Remove frame_changed, since it
+ causes a bug and doesn't seem to do anything useful. In some
+ places it was used as a flag, in others as a stack level (?).
+
+ * utils.c: Use MISSING_VPRINTF rather than HAVE_VPRINTF, so the
+ default is to use the portable (vprintf) version rather than the
+ kludge version.
+ * xm-news.h (MISSING_VPRINTF): Add.
+
+ * valprint.c (val_print): Demangle fancy vtbl printouts. Lint.
+
+Sat Sep 8 00:24:12 1990 John Gilmore (gnu at cygint)
+
+ * Remove stuff that forces -Bstatic linking of gdb, and warnings
+ about linking debugged programs -Bstatic in the sun?os4 config
+ files in tconfig and xconfig subdirectories.
+
+ * main.c (main): Remove unreached exit(0) now that we exit
+ via quit_command().
+
+ * Create TODO file for online bug list. There are too many
+ "little" bugs to keep track of on paper.
+
+ * Change Projects file to refer to bug-gdb@cygnus.com
+ rather than kingdon@ai.
+
+Fri Sep 7 23:35:15 1990 John Gilmore (gnu at cygint)
+
+ * Makefile.dist (VERSION): 3.91.4 now.
+
+ * symtab.c (init_misc_bunches): Rename from init_misc_functions.
+ (condense_misc_bunches): Add sanity check that misc_count is
+ the same as the number of symbols in the bunch.
+
+ * coffread.c: rename init_misc_bunches. Pass an argument
+ to condense_misc_bunches (a zero).
+
+ * dbxread.c (partial_symbol_file_read): Call init_misc_bunches
+ every time we are called; don't rely on our caller to do it.
+ (add_file): Remove call to init_misc_bunches.
+
+ * mipsread.c: Only warn, don't error, if unknown symbol types.
+ This keeps an old gdb from falling on its face if it sees newly
+ extended symbol info. Rename init_misc_bunches.
+
+Fri Sep 7 22:58:15 1990 John Gilmore (gnu at cygint)
+
+ * Merge in changes from Per Bothner for DECstations and other
+ MIPS stuff. The rest is Bothner speaking:
+
+ The next message is a merger of Alessando Forin's mips port with
+ mine. I've tried to use my good if biased judgment to get
+ the best of both. It *does* need testing.
+
+ Some of the changes are general, *not* mips-specific.
+
+ param.h:
+ Didn't believe in little-endian bit order.
+ There are still inconsistencies about whether flags
+ like BITS_BIG_ENDIAN are integer (#if ...) or
+ boolean (#ifdef ...). I tried to paper over them.
+
+ dbxread.c,coffread.c,mipsread.c,symtab.c,symtab.h:
+ Moved some misc_function code that was common to
+ {dbx,coff,mips}read.c to symtab.c.
+ In the process, I think I cleaned things up a bit.
+ At the same time, moved obsavestring and obconcat to symtab.c.
+
+ dbxread.c:
+ Removed obsolete condense_addl_misc_bunches (use
+ condense_misc_bunches(1) instead).
+
+ exec.c:
+ Needed to include <sys/dir>, at least on DECstations.
+
+ valops.c, mips-tdep.c, tm-mips.h:
+ Added PUSH_ARGUMENTS macro to support funny argument-pushing
+ conventions (when STACK_ALIGN is insufficient).
+ Needed on mips, where doubles need 8-byte alignment,
+ but ints only need 4.
+
+ mips-opcode.h:
+ Removed cruft that was not being used.
+ Merged in many fixes (most from Frank Yellin, fy@lucid.com).
+
+ mips-pinsn.c:
+ Print $ before register-names (I think that makes things a little
+ more consistent).
+ Never print two instructions, even if one delays.
+ Removed hex-disassemble set_cmd. (This is not mips-specific,
+ so I think the argument is whether it is generally worthwhile or not.
+ I'm inclined to think not, given how easy it is to
+ convert between radixes in gdb.)
+
+ mipsread.c:
+ This is basically Alessando's code.
+ It doesn't use obstacks; I changed it to use obstacks
+ in a few minor places where using malloc causes a
+ memory leak. (Probably, more places could/should be changed.)
+ I added record_misc_function where it was missing.
+ In symbol_file_command and add_file_command, I tried
+ to make the code consistent with more recent versions.
+ Minor sylistic changes in parse_procedure.
+ Make a .gdbinfo. psuedo-symbol point back to the real
+ procedure symbol (using the isym field).
+
+ mips-tdep.c:
+ This is basically from my port, but with a lot of details
+ and a number of routines merged in from Alessando's version.
+ I basically used my code "raw" backtrace (use heuristics
+ from the actual code, rather than symbol table info) - though
+ the idea is Alessandro's. I feel my code is a little cleaner
+ here, particularly in being a little more flexible, such as being
+ able to handle gcc-produced code (which it now can).
+ It also doesn't do frame caching (which is not useful
+ more recent gdb versions).
+ I also used my code for push_/pop_dummy, more or less.
+ I tried to incorporate AF's code for testing sigtramp
+ while backtracing; I probably got it wrong.
+ Added mips_print_register, which tries to scrunch as much
+ information as possible on a screen...
+ Removed the skip-prologue set_cmd. As with hex-disassemble (see
+ under mips-pinsn.c), I don't see anything mips-specific here,
+ and I don't see it being all that useful anyway.
+
+ tm-mips.h:
+ Added a $fp psuedo-reg distinct from $fp (nice for gcc).
+ Use more register names (rather than hard-cases numbers).
+
+Thu Sep 6 18:33:15 1990 John Gilmore (gnu at cygint)
+
+ * Hack up 3.90.11 changes:
+
+ * Makefile.dist (depend): parameterize $(GCC).
+ Add solib.c and solib.o.
+ (readline): Fix vpath for both absolute or relative SRCDIR.
+
+ * blockframe.c: Fix from Schaefer@asc.slb.com for shared libs.
+ Also, let the part I didn't understand at least compile so
+ I can test the rest. FIXME.
+
+ * dbxread.c: Fix thinko using strcmp.
+ (init_psymbol_list): declare static.
+ (partial_symbol_file_open): Comment cleanups better, avoid
+ cleaning up the string table since the caller will do that.
+ Move the stat for mod time into symbol_file_command, temporarily.
+ (There should be a mod time for each symbol file, eventually,
+ to control its rereading. FIXME.)
+
+ * infptrace.c (PT_WRITE_D): use same value as PT_WRITE_I for
+ SunOS, which gives error for shared libs otherwise. (From
+ Schaefer, probably FIXME needs work for portability.)
+
+ * solib.c: Move #include "param.h" to work.
+ Lowercase all the Uppercase Letters In the Messages.
+ (find_solib): Clean up inferior_so_name for debug printouts.
+ Allow no argument, to mean all shared libraries.
+
+ * symmisc.c: include param.h to get CLEAR_SOLIB.
+
+Wed Sep 5 18:00:08 1990 John Gilmore (gnu at cygint)
+
+ * Merge in Kingdon's changes from FSF: the diffs from 3.90.9
+ to 3.90.11. ChangeLog entries below are from this.
+
+Wed Jun 13 09:17:39 1990 Jim Kingdon (kingdon at mole.ai.mit.edu)
+
+ * Version 3.90.11.
+
+ * Makefile.dist (HFILES): Add tm-sunos.h.
+
+Tue Jun 12 16:15:26 1990 Jim Kingdon (kingdon at pogo.ai.mit.edu)
+
+ * Version 3.90.10.
+
+ * Makefile.dist (gdb.tar.Z): Change linking of config so it works.
+
+Thu Jun 7 16:22:27 EDT 1990 Jay Fenlason (hack@ai.mit.edu)
+
+ * sparc-opcode.h Added single-operand version of rett.
+
+Mon Jun 4 18:12:31 1990 Jim Kingdon (kingdon at pogo.ai.mit.edu)
+
+ * m-sparc.h (REG_STRUCT_HAS_ADDR, STRUCT_ARG_SYM_GARBAGE):
+ Put parens around gcc_p in expansion.
+
+Thu May 24 15:44:51 1990 Jim Kingdon (kingdon at mole.ai.mit.edu)
+
+ * utils.c (lines_to_list): Return 10 if lines_per_page == 0.
+
+Wed May 23 16:36:04 1990 Jim Kingdon (kingdon at pogo.ai.mit.edu)
+
+ * Changes for Sun shared libraries:
+ blockframe.c (find_pc_partial_function): If a non-text symbol
+ is found, set *address = pc - FUNCTION_START_OFFSET.
+ breakpoint.c (insert_breakpoints) [DISABLE_UNSETTABLE_BREAK]:
+ Disable breakpoints instead of giving an error.
+ source.c (select_source_symtab): Initialize cs_pst.
+ symmisc.c: Call CLEAR_SOLIB if defined.
+ symtab.h: Make text{low,high} CORE_ADDR not int.
+ (psymtab): New field addr.
+ solib.c: New file.
+ dbxread.c: Move DECLARE_FILE_HEADERS outside functions.
+ (record_misc_function): Give correct type for N_DATA symbols.
+ (condense_misc_bunches): do "misc_function_count = j" regardless
+ of inclink.
+ Take code which is shared between symbol_file_command and
+ add_file_command and put it into partial_symbol_file_{open,read}.
+ Split add_file_command into add_file_command and add_file.
+ Make psymtab_to_symtab read in the string table if the file
+ is not symfile.
+ Two new parameters to read_dbx_symtab and start_psymtab.
+ tm-sunos.h: New file.
+
+Tue May 22 17:43:03 1990 Jim Kingdon (kingdon at pogo.ai.mit.edu)
+
+ * infcmd.c: Change cont_command to continue_command and "cont"
+ to "continue".
+
+Mon May 21 14:41:41 1990 Jim Kingdon (kingdon at pogo.ai.mit.edu)
+
+ * breakpoint.c (enable_breakpoint): Get value of watchpoint.
+
+ * defs.h [sparc]: Use <alloca.h> regardless of __GNUC__.
+
+ * values.c (USE_STRUCT_CONVENTION): Check for structures of
+ size 1,2,4,8 rather than size < 8.
+
+ * dbxread.c (dbx_lookup_type): Do f->length *= 2 as many times
+ as necessary, not just once.
+
+ * sparc-opcode.h: Add a bunch of new opcodes which Sun as supports.
+
+Thu May 17 15:04:09 1990 Jim Kingdon (kingdon at pogo.ai.mit.edu)
+
+ * {t,x}m-sun386.h, sun386-xdep.c, {x,t}config/sun386
+
+ * tm-news.h: Add CALL_DUMMY_*.
+
+ * tm-68k.h: Remove duplicate comment at FRAME_FIND_SAVED_REGS.
+
+ * config.gdb: In list_host, list_target, use ${i}, not $i.
+
+Tue May 15 21:27:12 1990 Jim Kingdon (kingdon at pogo.ai.mit.edu)
+
+ * source.c (find_source_lines) [BROKEN_LARGE_ALLOCA]: Use xmalloc.
+
+ * sparc-opcode.h: Change all store floating-point state register
+ instructions to have the right match & lose fields.
+
+Sat May 5 12:39:18 1990 Jim Kingdon (kingdon at pogo.ai.mit.edu)
+
+ * Makefile.dist: Move -I${srcdir} to GLOBAL_CFLAGS and pass
+ VPATH to readline.
+ config.gdb: If srcdir != ., create readline directory and
+ copy a makefile into it.
+
+ * wait.h, infrun.c: Change WRETCODE to WEXITSTATUS for
+ consistency with POSIX.
+
+ * breakpoint.c (bpstat_stop_status): Disable watchpoint
+ when we exit its exp_valid_block.
+
+Tue Sep 4 11:46:46 1990 John Gilmore (gnu at cygint)
+
+ * Makefile.dist: Bump version to 3.91.3.
+
+ * Clean up handling of breakpoint commands (somewhat).
+ Prompted by Tiemann bug report "cont 10" doesn't work any more.
+
+ inferior.h: Add breakpoint_proceeded to inferior status struct
+ and globals; save it and restore it.
+ (clear_breakpoint_commands): Cleanup, remove old #define.
+
+ infrun.c (clear_proceed_status): Set breakpoint_proceeded.
+ (save_inferior_status, restore_inferior_status): handle it also.
+ (proceed): Remove earlier code that set breakpoint_proceeded.
+ It is now set only in clear_proceed_status.
+ (clear_proceed_status): Cleanup, use bpstat_clear rather
+ than clear_breakpoint_commands. No callers need the stop_bpstat
+ between clear_proceed_status and proceed.
+
+ infcmd.c: Add breakpoint_proceeded definition and comment.
+ (cont_command, jump_command, signal_command): Move call to
+ clear_proceed_status right next to call to proceed.
+
+ breakpoint.c (bpstat_do_actions): Avoid clobbering our
+ caller's argument while running down the chain of breakpoints.
+ Use new variable "breakpoint_proceeded" to determine when
+ a command that it executes moves the inferior past the
+ breakpoint.
+ (bpstat_clear): Handle NULL argument.
+ (bpstat_clear_actions): Avoid useless call to
+ breakpoint_auto_delete.
+ (delete_breakpoint): Clean up bpstat's that are pointing to
+ the deleted breakpoint from the stop_bpstat chain.
+ (breakpoint_auto_delete): Simplify.
+
+ * Clean up handling of EOF, error on stdin, etc. This was
+ prompted by a network problem that caused gdb to go into an
+ infinite loop filling up its malloc'd memory.
+
+ main.c (return_to_top_level): Cleanup: call bpstat_clear_actions,
+ not clear_breakpoints_commands, which is now gone.
+ (main): If command_loop returns (e.g. from EOF on stdin), do
+ a quit_command (looping back to command_loop if quit_command
+ doesn't really quit).
+ (command_loop): check result from command_line_input and
+ exit if it returns NULL, rather than passing the NULL to
+ execute_command.
+ (gdb_readline): Free malloc'd result space before returning
+ NULL for EOF.
+
+ * utils.c (query): Handle C-d to mean "yes", just as if the
+ input was not a terminal. Also avoid infinite loop if EOF
+ occurs in mid-input-line before newline. This allows
+ query to be used at EOF on stdin with reasonable results.
+
+ * infrun.c (proceed): Set breakpoint_proceeded.
+
+ * values.c (value_as_long): Avoid infinite recursion for enums.
+ (_initialize_values): Fix typo in help msg (kingdon).
+
+ * Makefile.dist (RL_LIB): Use RL_LIB_DEP for dependencies,
+ RL_LIB for linking. This allows -lreadline for linking
+ and nothing for dependencies, once readline is a real library.
+
+ * config.gdb: Jim Kingdon: give useful error message if the
+ host or target type is not recognized.
+
+ * defs.h (alloca): SPARC <alloca.h> does not declare alloca,
+ it just defines it. Dumb, but deal with it.
+
+ * Jim Kingdon suggests:
+ in xconfig/sun3os4, CFLAGS should be XM_CFLAGS.
+
+Wed Aug 29 18:03:27 1990 John Gilmore (gnu at cygint)
+
+ * Makefile.dist (VERSION): Bump version # to 3.91.2.
+
+ * Clean up Bothner's changes.
+
+ * blockframe.c (clear_pc_function_cache): New function.
+ * blockframe.c: remake cache_pc_function_* static.
+ * dbxread.c (symbol_file_command): remove references to
+ cache_pc_function_* variables.
+ * dbxread.c (read_struct_type): Use VOFFSET_STATIC.
+ * printcmd.c: Avoid kludging a global variable (addressprint)
+ to avoid printing the address of a string twice. Instead,
+ pass the format letter 's' down low enough that it can be seen
+ to avoid this problem.
+ (print_formatted): Pass format arg to value_print.
+ (restore_addressprint): Remove function.
+ (do_examine): Avoid hacking addressprint, cleanups and such.
+ (print_frame_args): Add a comment to a Bothner change.
+ * symtab.h: define VOFFSET_STATIC and use it instead of "-1".
+ * symmisc.c (free_all_symtabs): Call clear_pc_function_cache
+ to wipe out the values cached in blockframe.c.
+ * symtab.c (find_method): Add comment saying how big you must
+ allocate to be "big enough". Per being terse again.
+ * valprint.c (val_print): Handle format letter "s" to print
+ strings without addresses. Add comment to vtbl printing code
+ which casts with wild abandon. Rearrange reference-printing
+ code so it prints:
+ @0xaddr: value (print w/addressprint)
+ value (print w/~addressprint)
+ @0xaddr (parameter lists w/addressprint)
+ or nothing (parameter lists w/o addressprint)
+
+Tue Aug 28 10:47:18 1990 John Gilmore (gnu at cygint)
+
+ * Merge more changes from Per Bothner:
+
+Gdb's handling of TYPE_CODE_REF was so counter-C++ (and otherwise
+annoying) that I tried to improve it. Here are my suggestions.
+
+ These patches all attempt to handle TYPE_CODE_REF (as in C++) better.
+
+ findvar.c:
+ Do automatic de-reference when taking the address of a reference.
+ printcmd.c:
+ Don't deref_ref when printing parameter lists.
+ valops.c:
+ More attempts at treating refernences properly.
+ valprint.c:
+ In val_print, if deref_ref==0, don't print dangling " = ".
+ value.h:
+ Add COERCE_REF macro, which de-references an REF.
+
+ * Merge changes from Per Bothner:
+
+* Fixed (Sony news)-specific configuration problems.
+* Fixed other problems with using vanilla pcc and libc (enum problems;
+assumption that vsprintf exists).
+* Some major speed-ups (finc_pc_partial_function now caches a match;
+parsing avoids duplicate symbol_lookup calls).
+* Changed handling of baseclasses (no longer use baseclasses field
+of struct type, use the first n_baseclasses fields instead).
+* Various minor changes/fixes, most C++-related.
+
+blockframe.c:
+Cache the most previous match from find_pc_partial_function.
+(Save both low and high ends of matching function's pc range.)
+This speeds up the loop of infrun.c:wait_for_inferior quite
+a bit, and makes step/next commands much zippier.
+command.c:
+Added an enum->int cast (otherwise, some compilers barf).
+dbxread.c:
+No longer set baseclass offset to 0, since multiple
+inheritance now mostly works.
+Added a number of casts, to shut up compiler warnings
+(after stabs where made enums, not ints).
+When discarding a symbol table (in symbol_file_command),
+must clear the cache introduced in blockframe.c.
+Don't convert $vtbl_ptr_type to vtbl any more.
+Get rid of TYPE_BASECLASEES and baseclass_vec (see also symtab.h).
+Mask off sign bit emitted by g++ for virtual table offset.
+Set voffset to -1 (not 1) for static member functions.
+expread.y:
+Changed parsing/lexing of names to avoid doing symbol lookup twice
+(once when lexing to determine symbol class, once for real).
+Now only call symbol_lookup once. Fields of 'this' win especially big.
+printcmd.c:
+Subpress printing addr twice in the case of 'x/s addr'.
+symtab.c:
+lookup_basetype_type is no longer used.
+Add find_methods as recursive helper function to decode_line_1.
+This allows multiple inheritance to work.
+Also, once one or more matches has been found, do not look in
+base-classes. (Baseclass methods would be overridden, anyway.)
+symtab.h:
+Removed baseclasses array in struct type.
+Instead of using baseclasses[i], use fields[i-1].
+Added virtual_field_bits[i] to indicate if the i'th baseclass is virtual.
+Changed sign convention of voffset (previous was inconsistent).
+tm-news.h:
+Some macros (CALL_DUMMY and relatives) were missing. Put them back.
+utils.c:
+Used to assume existence of vsprintf. Re-written to not need it
+if HAVE_VPRINTF is undefined.
+valops.c:
+typecmp was too pessimistic. Made it less so.
+valprint.c:
+Don't print space after address.
+If vtable points to a misc symbol (with 0 offset), print it,
+since that indicates the actual class of the object.
+Changed ype_print_derivation_info to use new inheritance
+scheme (without baseclasses vector).
+values.c:
+In value_primitive_field, fixed some bugs left over from previous set of fixes.
+Also, changes needed because TYPE_BASECLASSES were removed.
+xm-news.h:
+REGISTER_U_ADDR didn't work for PC. Rewrote to use an array.
+
+Tue Aug 21 20:08:54 1990 John Gilmore (gnu at cygint)
+
+ * source.c:
+ If there is no path set, and the symbols don't indicate what directory
+ a file was compiled in, look in the current directory. But either
+ a path or a known compilation directory will prevent this.
+
+ * dbxread.c:
+ Three independent bug fixes:
+ * Remove the #if 0 block that breaks some stuff.
+ * SunOS 4.1 fixed the promoted-parameter-wrong-addr bug in Sun C;
+ adapt gdb to either SunOS 4.0.* or 4.1.
+ * MAX_OF_TYPE and MIN_OF_TYPE thinko. By tedg@sun, I think.
+
+ * symtab.c:
+ Instantiate the class T when looking for methods in it. (Tiemann@sun)
+
+ * valprint.c:
+ (type_print) Demangle the name being printed.
+ (type_print_base) Handle botched demangling without coredump (tiemann).
+
+ * values.c:
+ (check_stub_method): Document routine.
+ (tiemann) fix bug for no-arg functions
+ Avoid clobbering beyond end of malloc'd storage.
+ Terminate the argument list properly.
+
+Sat Aug 18 01:29:59 1990 Per Bothner (bothner@cs.wisc.edu)
+
+ * Changes merged by John Gilmore:
+
+breakpoint.c:
+ In breakpoint_1, use new print_address_symbolic instead
+ of find_pc_partial_function. (This forces use of assembler-level
+ addresses, and avoids misleading non-mangled source-level names.)
+cplus-dem.c:
+ Generalize ansi argument such that -1 means skip arglist totally.
+ Removed global variable print_ansi_qualifiers (which made
+ code non-reentrant), in favor of extra explicit arguments
+ to internal routines.
+printcmd.c:
+ Add new helper function print_address_symbolic.
+ Use find_pc_misc_function instead of find_pc_partial_function
+ (since we want assembler-level symbols here).
+stack.c:
+ Print unknown function as just "f (...)", not "f (...) (...)".
+ Use new fputs_demangled explicitly.
+symtab.c:
+ Fixed a typing violation (problem: value.h cannot be imported
+ without renaming many variable in this file).
+ lookup_symbol: If no matching misc_func, look for a C++-mangled name.
+ decode_line_1: Moved forward some never-reached code.
+ Made decode_line_2 skip function prologues correctly.
+utils.c:
+ fputs_filtered should not demangle by default.
+ Add new fputs_demangled to demangle on demand..
+valops.c:
+ Change value_struct_elt to use value_primitive_field (using recursive
+ utility function search_struct_field). This allows foo.bar to work
+ for multiple inheritance (so far only for data fields).
+ Change check_field in the same way (recursive helper function
+ to support multiple inheritance).
+ (Note: there are more of these problems that I haven't fixed.
+ Any code that says TYPE_BASECLASS (t, 1) is probably wrong.)
+ value_of_this: 'this' symbol name is now just "this", note "$this".
+valprint.c:
+ Don't print static members.
+ Avoid printing "members of <type>" if there are none.
+ Simplified type_print_derivation_info by merging duplicate code.
+ Remove useless blank lines in type_print_base (ptype command).
+value.h:
+ Added declaration of new routine value_primitive_field.
+values.c:
+ Added value_primitive_field which is generalized version of
+ value_field that can handle multiple inheritance (non-zero offsets etc).
+ Re-implemented value_field to call value_primitive_field.
+
+Fri Aug 17 23:33:44 1990 John Gilmore (gnu at cygint)
+
+ * infcmd.c -- insert else to avoid 'delete env' coredump when you
+ delete the whole environment. Karl Berry reported the bug.
+ * source.c - fix openp to avoid //'s in filenames, which
+ trigger an Emacs bug causing it to not be able to find files
+ when running gdb in a window.
+ * dbxread.c - zap the #if 0 that botches the add-file code.
+ It seems to work a lot better without all the code commented out.
+
+Fri Jul 20 16:58:46 1990 John Gilmore (gnu at cygnus.com)
+
+ * Merge Tiemann's and Ted Goldstein's changes, detailed below,
+ into gdb-3.90.9.
+
+Tue Jul 17 19:34:33 1990 Ted Goldstein (tedg at golem)
+
+ * Makefile - added a ${CFLAGS} to a couple of entries,
+ added remote-sa.sparc.c
+ * added remote.sa-sparc.c, a modification of remote.c
+ which conducts a dialog directly with the SparcStation prom.
+ * breakpoint.c, infrun.c, sparcdep.c added
+ remote_insert_breakpoint(), and remote_remove_breakpoint()
+ to breakpoint.c instead of directly writing breakpoint instructions.
+ * sparcdep.c on remote_debugging,there is no need
+ to remove signle step breakpoint instructions.
+ * main.c added "-epoch" flag and "int epoch_interface" to main.c
+ global variable
+ * printcmd.c - epoch interface sends lisp expressions to open up
+ epoch windows on inspection.
+ * valprint.c - added arrayprint, and addressprint and made adding
+ format controls easier
+ * wait.h added a couple of undef's because we were getting
+ complaints about WSTOPSIG and WTERMSIG begin redefined.
+
+
+Wed Jul 4 05:27:51 1990 Michael Tiemann (tiemann at masham)
+
+ * symtab.c (decode_line_1): Add support for handling method stubs
+ in the type information.
+
+Tue Jul 3 09:39:18 1990 Michael Tiemann (tiemann at masham)
+
+ * values.c (baseclass_addr): Run loop from INDEX+1 to
+ N_BASECLASSES; otherwise, we can still get into a loop.
+ @@ This should be restructured to use a cleaner search strategy.
+
+Sun Jul 1 12:28:51 1990 Michael Tiemann (tiemann at masham)
+
+ * dbxread.c (define_symbol,read_type): Grok GNU C++'s new
+ abbreviation "Tt" for tags which have the same name as their
+ typedecls.
+
+Fri Jun 29 01:03:46 1990 Michael Tiemann (tiemann at masham)
+
+ * symtab.c (list_symbols): add ability to set breakpoints on all
+ the functions which match a particular regular expression.
+
+Tue Jun 26 04:26:29 1990 Michael Tiemann (tiemann at masham)
+
+ * cplus-dem.c (cplus_demangle): New parameter ANSI says whether we
+ should print ANSI qualifiers (such as `const' and `volatile').
+ All callers changed to call with ANSI == 1, except from
+ `check_method_stub', which uses old-style syntax.
+
+ * symseg.h (struct fn_field): Remove unneccessary `args' field.
+ * symtab.h (TYPE_FN_FIELD_ARGS): Redefined.
+
+ * values.c (check_stub_method): New function.
+
+ * cplus-dem.c (do_type): Handle "long long" (encoded as 'x').
+
+ * dbxread.c (read_type): Handle new GNU C++ method type stubs.
+ * valprint (type_print_base): Ditto.
+
+ * symtab.c (gdb_mangle_typename): New function.
+
+Tue Jun 5 00:18:43 1990 Michael Tiemann (tiemann at gzilla)
+
+ * breakpoint.c (catch_command): New function. Provides a
+ mechanism to set breakpoints based on catch clauses.
+ (disable_catch): Similar, but disables breakpoints on catch
+ clauses.
+ (delete_catch): Similar, but deleted breakpoints on catch clauses.
+
+Sun Jun 3 22:54:08 1990 Michael Tiemann (tiemann at gzilla)
+
+ * blockframe.c (blockvector_for_pc): New function.
+ * blockframe.c (block_for_pc): Changed to call
+ `blockvector_for_pc' and get the block itself.
+
+ * stack.c (catch_info): New function. Prints info about
+ exceptions which can be caught in the current frame.
+ * stack.c (print_frame_label_vars): New function. Similar to
+ `print_frame_local_vars'.
+ * stack.c (print_block_frame_labels): Prints out labels that are
+ defined in this frame. These labels are exceptions that can be
+ caught.
+
+ * dbxread.c: Updated to handle N_CATCH symtab types.
+
+Thu May 3 22:10:00 1990 Michael Tiemann (tiemann at teacake)
+
+ * valprint.c (everywhere): TYPE_NAME (TYPE) no longer comes in the
+ form "struct ..." for GNU C++. Don't flush any part of TYPE_NAME
+ when printing the type.
+
+Wed May 2 22:43:04 1990 Michael Tiemann (tiemann at teacake)
+
+ * valprint.c (val_print): Use `baseclass_addr' to access the
+ baseclasses pointed to via the derived class object at VALADDR.
+
+ * values.c (baseclass_addr): New function. Casts derived pointers
+ to baseclass pointers taking virtual baseclasses and multiple
+ inheritance into account.
+
+Sat May 5 12:39:18 1990 Jim Kingdon (kingdon at pogo.ai.mit.edu)
+
+ * Version 3.90.9.
+
+Fri May 4 12:12:55 1990 Jim Kingdon (kingdon at pogo.ai.mit.edu)
+
+ * breakpoint.c (watch_command, bpstat_stop_status): Deal with
+ exp_valid_block field correctly.
+
+ * infrun.c (wait_for_inferior): When checking "don't even think
+ about breakpoints" if stop_signal == SIGTRAP && trap_expected,
+ also check step_resume_breakpoint.
+ Insert breakpoints and continue (not step) if
+ step_resume_break_address != NULL, even if another_trap.
+ If trap_expected and we enter sigtramp, then set up a
+ step_resume_break.
+ If trap_expected is set when we hit the step_resume_break,
+ set another_trap.
+ When calling resume and trap_expected says tell resume to step
+ (2 places), also check step_resume_break_address.
+
+ * infrun.c (wait_for_inferior): Don't set
+ prev_{pc,sp,func_{start,name}} before calling wait ().
+ Do set them after exiting loop.
+ Move their declarations outside functions.
+ (start_inferior): Initialize them.
+
+Thu May 3 00:15:11 1990 Jim Kingdon (kingdon at pogo.ai.mit.edu)
+
+ * infrun.c (wait_for_inferior, after check for trap_expected > 1):
+ Restore old code which distinguishes between trap_expected and
+ running_in_shell, just make the latter take any non-TRAP signal,
+ not just SEGV.
+
+ * values.c (allocate_value): Zero VALUE_OPTIMIZED_OUT flag.
+
+ * Makefile.dist (pinsn.o): Use PINSN_CC to compile.
+ xconfig/3b1 (CC,PINSN_CC): Define.
+
+ * xconfig/altos, altos-dep.c: Rename altos-dep.c to altos-xdep.c.
+
+ * Version 3.90.8
+
+ * breakpoint.c (bpstat_stop_status),
+ infrun.c (wait_for_inferior) [SHIFT_INST_REGS]: New code.
+
+ * param.h, tm-88k.h: Define ADDR_BITS_*.
+ infcmd.c (jump_command, read_pc), infrun.c (wait_for_inferior),
+ printcmd.c (do_one_display): Use them.
+
+ * utils.c: Split #ifdef USG into a USG_UTILS and a QUEUE_MISSING.
+ xm-88k.h: Define USG_UTILS.
+
+Wed May 2 00:05:33 1990 Jim Kingdon (kingdon at pogo.ai.mit.edu)
+
+ * printcmd.c (printf_command) [__INT_VARARGS_H]: New code.
+ (printf_command): Add from_tty parameter.
+
+ * valprint.c (value_print): Check VALUE_OPTIMIZED_OUT flag.
+
+ * value.h: Add optimized_out field and change lazy field to
+ char. Add macro VALUE_OPTIMIZED_OUT.
+
+ * i386-pinsn.c: Change from Eirik Fuller to write to stream directly
+ instead of stuffing things in buffers (oappend, etc).
+
+ * breakpoint.c (bpstat_do_actions): If *BSP is set to NULL by
+ execute_command, exit both loops.
+
+ * Makefile.dist: Don't set TARGET_ARCH. Add .c.o rule.
+
+Tue May 1 17:07:23 1990 Jim Kingdon (kingdon at pogo.ai.mit.edu)
+
+ * Makefile.dist (RAPP_OBS, rapp),
+ rgdb.c, rserial.c, rudp.c, serial.c, udp.c, xdep.h,
+ remote.h: Added.
+ m68k-xdep.c, coredep.c: Wrap in #if !defined (RDB).
+
+ * valops.c (value_struct_elt), values.c (value_static_field):
+ Change error messages to remove references to `info methods'.
+
+Tue Apr 24 10:25:10 1990 Jim Kingdon (kingdon at pogo.ai.mit.edu)
+
+ * More 88k changes:
+ infrun.c (start_inferior): Add START_INFERIOR_HOOK.
+ infcmd.c [SHIFT_INST_REGS]: New code.
+ findvar.c (read_relative_register_raw_bytes): Return a value.
+ infcmd.c (do_registers_info): Check value from
+ read_relative_register_raw_bytes.
+
+ * command.c (delete_cmd): Free the struct cmd_list_element(s)
+ we are removing.
+
+Mon Apr 23 10:42:21 1990 Jim Kingdon (kingdon at pogo.ai.mit.edu)
+
+ * More 88k changes:
+ findvar.c (get_saved_register): New function.
+ findvar.c: Rewrite code which called find_saved_register to
+ call get_saved_register instead.
+
+Sun Apr 22 14:47:51 1990 Jim Kingdon (kingdon at pogo.ai.mit.edu)
+
+ * valprint.c (val_print): Change error message printed when
+ the type has TYPE_FLAG_STUB set.
+
+ * valprint.c (val_print): Check for TYPE_CODE_UNDEF.
+
+ * findvar.c (write_register): Set register_valid (regno).
+
+ * valops.c (call_function): Check for NULL return from block_for_pc.
+
+Fri Apr 20 11:31:23 1990 Jim Kingdon (kingdon at pogo.ai.mit.edu)
+
+ * findvar.c (write_register): Add PREPARE_TO_STORE.
+ {sun3,sparc,symmetry}-xdep.c (PREPARE_TO_STORE): Add.
+ infptrace.c, {mips,pyr,symmetry,sun3,arm,hp300hpux}-xdep.c
+ (store_inferior_registers): Don't call read_register_bytes.
+ symmetry-xdep.c (store_inferior_registers):
+ #if 0 out code to fetch registers.
+
+ * values.c (value_as_long): Call COERCE_ARRAY.
+
+ * tm-sun3.h: Include tm-68k.h not m-68k.h
+
+ * sparc-tdep.c (single_step): Set next_pc, npc4 within
+ if (!one_stepped), not outside it.
+
+ * Changes from Data General for 88k:
+ * coffread.c (read_file_hdr): Add *88*MAGIC.
+ * coffread.c (have_symbol_file_p): New function.
+ * coffread.c [COFF_CHECK_X_ZEROES] [TDESC]: New code.
+ * coffread.c (read_one_sym): If there is more than one
+ aux entry, don't give an error message, just ignore the
+ extra ones.
+ * coffread.c (process_coff_symbol): Replace clipper with
+ BELIEVE_PCC_PROMOTION in #ifdef's.
+ * coffread.c: Define L_LNNO32 if not defined.
+ (enter_linenos): Use it.
+ * blockframe.c: Add INIT_FRAME_PC hook and use it in
+ get_prev_frame_info.
+ m-m88k.h: Use INIT_{FRAME_PC,EXTRA_FRAME_INFO} to do tdesc stuff.
+ Use dummy versions of FRAME_CHAIN_*.
+ * Makefile.dist, xconfig/i386*: Rename M_CLIBS to XM_CLIBS and add
+ TM_CLIBS and CDEPS.
+ tdesc/libdc.o: New target.
+ tdesc.{c,h}, tdesc/*, {t,x}config/m88k: New files.
+
+Thu Apr 12 15:47:00 1990 Jim Kingdon (kingdon at pogo.ai.mit.edu)
+
+ * m68k-opcode.h (bras, bsrs): Use "Bw" not "Bg".
+
+Tue Apr 10 20:50:25 1990 Jim Kingdon (kingdon at pogo.ai.mit.edu)
+
+ * Version 3.90.7.
+
+ * xm-mips.h (BYTE_ORDER): If not defined, make it LITTLE_ENDIAN.
+
+ * mips-xdep.c ({fetch,store}_inferior_registers): Remove variable
+ offset and just use register_addr (regno, 1).
+ (core_file_command): Remove variable reg_offset and just use
+ register_addr (regno, 0).
+
+ * gdbcore.h [COFF_FORMAT]: #undef a_magic before redefining it.
+
+ * infrun.c ("if (trap_expected && stop_signal != SIGTRAP)", near end
+ of wait_for_inferior): Always pass 0 as first arg to resume.
+ #if 0 out "SIGSEGV in shell" test right above it (now redundant).
+
+ * i386-pinsn.c (oappend_address): New function.
+ (oappend): Make it "static void" and declare at top of file.
+ (OP_J, OP_DIR): Use oappend_address.
+
+Mon Apr 9 15:22:09 1990 Jim Kingdon (kingdon at pogo.ai.mit.edu)
+
+ * mips-xdep.c: Include <mips/inst.h> not "mips/inst.h".
+
+ * wait.h [HAVE_WAIT_STRUCT]: Put #defines in #if !defined so that
+ it's OK if they are defined in <sys/wait.h>.
+
+ * findvar.c (fetch_registers): Pass "registers", not "&registers",
+ to remote_fetch_registers.
+
+ * mips-tdep.c (_initialize_mipsdep): Remove hex_disassembler
+ and re-write skip_prologue to use add_set_cmd.
+
+ * Makefile.dist (alldeps.mak): Don't put \ after the last
+ filename in each list.
+
+Sun Apr 8 01:59:19 1990 Jim Kingdon (kingdon at pogo.ai.mit.edu)
+
+ * Version 3.90.6.
+
+ * Makefile.dist (alldeps.mak): "XM_FILE" -> "XM_FILE=".
+
+ * valarith.c (value_x_{un,bin}op): use "operator" not "operator "
+ to match dbxread.c change of 16 Mar 90.
+
+ * valarith.c (value_x_unop): Pass &static_memfuncp,
+ not static_memfuncp.
+
+ * breakpoint.c: Add watchpoint stuff.
+ breakpoint.h: Add bpstat_should_step.
+ infrun.c (proceed, wait_for_inferior): Use it.
+ breakpoint.h: Add bpstat_print (and rename old bpstat_print
+ to bpstat_should_print).
+ infrun.c (normal_stop): Use it.
+
+ * value.h: Add value_free. Declare a few functions.
+
+Sat Apr 7 21:43:43 1990 Jim Kingdon (kingdon at pogo.ai.mit.edu)
+
+ * dbxread.c (read_dbx_symtab): Remove PROFILE_TYPES code and
+ insert comment suggesting easy shell script equivalents.
+
+ * values.c (unpack_long): Give better error messages for
+ unrecognized sizes of ints and floats.
+
+Fri Apr 6 00:32:21 1990 Jim Kingdon (kingdon at pogo.ai.mit.edu)
+
+ * dbxread.c, gdbcore.h (IS_OBJECT_FILE): Check for a_drsize
+ nonzero as well as a_trsize.
+
+ * More places: Use SWAP_TARGET_AND_HOST.
+
+ * valops.c (destructor_name_p): Only skip "struct " if present.
+
+ * main.c (gdb_readline): Return NULL on end of file.
+
+ * sparc-opcode.h: Add jmp 1+2, jmp 1+i, jmp i+1.
+
+ * Makefile.dist: Make expread.tab.c unambiguously be in srcdir.
+
+ * main.c: Split source_command into source_command and
+ read_command_file.
+ (main): Accept "-" as arg to +command for stdin.
+
+ * dbxread.c (psymtab_to_symtab): Don't read string table.
+ (symbol_file_command): Save string table size.
+
+ * Version 3.90.5
+
+ * symtab.c: Remove declaration of lookup_misc_func.
+
+ * mips-pinsn.c: Add use_hex_p stuff (re-worked from Forin stuff).
+
+ * mips-opcode.h: Add bdelay field.
+ mips-pinsn.c: Various changes from Forin, I think to make it look
+ like the MIPS assembler format.
+ mips-tdep.c, mips-xdep.c, mipsread.c: Various changes from Forin.
+
+ * gdbcore.h: Declare register_addr.
+
+ * gdbcore.h: Include <a.out.h>, before trying to redefine N_TXTADDR
+ and friends.
+ various: Don't include both a.out.h and gdbcore.h.
+
+ * Makefile.dist (HFILES): Add param.h
+
+ * utils.c (init_malloc): Moved here from mcheck.c and modified
+ to use the standard mcheck.c
+ Makefile.dist: Modify to reflect new mcheck.
+
+Thu Apr 5 16:38:28 1990 Jim Kingdon (kingdon at pogo.ai.mit.edu)
+
+ * valprint.c (val_print, print_hex_chars): Print integers
+ larger than LONGEST.
+
+ * valarith.c (value_sub): Give error message if attempt to
+ subtract something of the wrong type from a pointer.
+
+ * breakpoint.c (bpstat_stop_status): Initialize retval to NULL.
+
+ * i386-tdep.c (i386_pop_frame): Change addr to adr.
+
+Wed Apr 4 05:21:50 1990 Jim Kingdon (kingdon at teenage-mutant)
+
+ * main.c (command_line_input): return NULL on end of file.
+ (execute_command): If p is NULL, return almost right away.
+ (read_command_lines): Treat end of file like "end".
+
+ * printcmd.c (print_frame_args): Change it so num is number
+ of ints of args, not number of args.
+
+ * xm-*.h: Make sure BYTE_ORDER is defined.
+ Also fix various #includes of old names of things.
+
+ * main.c (command_line_input): Fix comment code of 2 Apr.
+
+ * values.c (value_from_long, unpack_long): SWAP_TARGET_AND_HOST.
+ various: Replace {BYTES,WORDS}_BIG_ENDIAN with TARGET_BYTE_ORDER.
+ valarith.c various: SWAP_TARGET_AND_HOST.
+ dbxread.c (READ_FILE_HEADERS): SWAP_TARGET_AND_HOST.
+ (SWAP_SYMBOL): New macro. Use it wherever symbuf_idx is incremented.
+ exec.c (exec_file_command): SWAP_TARGET_AND_HOST.
+
+ * valarith.c (value_subscripted_rvalue): Just bcopy() the
+ appropriate bytes rather than playing strange games with
+ value_from_long.
+
+ * param.h (SWAP_TARGET_AND_HOST): New macro.
+
+ * tm-np1.h (V7_REGNUM): Change from 27 to 26.
+ (REGISTER_VIRTUAL_TYPE): Return correct result for vector regs.
+ gould-tdep.c: New file.
+
+ * Move reading of register before store from
+ findvar.c (write_register) to
+ infptrace.c, *-xdep.c (store_inferior_register).
+
+ * findvar.c (fetch_registers, store_registers): New functions.
+ write_register{,_bytes}: Use store_registers regardless of
+ have_inferior_p.
+ registers_valid: New variable.
+ (supply_register, read_register, etc.): Use it.
+ (read_register_gen): New variable.
+ various: Use read_register_gen rather than read_register_bytes
+ where appropriate.
+ *-xdep.c (fetch_inferior_registers): Remove remote_debugging check.
+ infrun.c (wait_for_inferior, start_inferior): Call registers_changed
+ not fetch_inferior_registers.
+ *-xdep.c (fetch_inferior_registers): Call registers_fetched if
+ not setting registers via supply_register, and if fetching
+ all registers.
+ infptrace.c, *-xdep.c (fetch_inferior_registers): Add param,
+ # of register to fetch (-1 for all).
+ infptrace.c, hp300hpux-xdep.c (fetch_inferior_registers):
+ Actually fetch only those registers needed.
+ value.h: Declare all the extern register functions from findvar.c.
+
+ * coffread.c (read_coff_symtab): Test for specific kinds of GCC
+ labels (LI%.*, LPB%.*, etc), not just ??%.*.
+
+ * coffread.c (record_misc_function): Use mf_text not mf_unknown.
+
+ * utils.c,defs.h (lines_to_list): New function.
+ source.c (select_source_symtab, list_command, forward_search_command,
+ reverse_search_command), stack.c (print_frame_info):
+ Use it instead of 10.
+
+ * munch: If MUNCH_NM variable exists, use it.
+
+ * main.c (initialize_main): Set rl_readline_name.
+ main.c: #include readline.h and #undef savestring.
+ Remove declarations of things declared in readline.h.
+
+ * main.c (gdb_readline): If instream == 0, read from stdin.
+
+ * main.c (main): Only call clearerr if ISATTY. Exit loop if
+ feof (instream).
+
+ * infcmd.c (detach_command): Set inferior_pid to 0 after
+ calling remote_close.
+
+ * main.c (main): If exec and sym files are the same, and there
+ is an error reading execfile, don't try to read sym file.
+
+ * infcmd.c (detach_command) [ATTACH_DETACH]: Don't try to detach
+ from inferior when remote debugging.
+
+ * source.c (reverse_search_command): Change while test from 1 to
+ line > 1.
+
+Tue Apr 3 18:14:14 1990 Jim Kingdon (kingdon at pogo.ai.mit.edu)
+
+ * Version 3.90.4.
+
+ * Makefile.dist (gdb.tar.Z): Use -z option to tar rather than
+ creating gdb.tar and calling compress separately.
+
+ * breakpoint.c (read_memory_nobpt): Do not treat bcopy as if it
+ returned an "errno" value.
+
+ * various: Make sure gdbcore.h is not included before a.out.h.
+
+ * Makefile.dist (OPCODES): Add mips-opcode.h.
+
+ * config.gdb: Print lists of {hosts,targets} after finding srcdir.
+ When parsing +{host,target}=, strip off +{host,target}=, not +{x,t}m=.
+
+ * Makefile.dist (gdb.tar): Do {t,x}config not just config.
+
+Mon Apr 2 02:42:23 1990 Jim Kingdon (kingdon at pogo.ai.mit.edu)
+
+ * sparc-opcode.h (inc): Fix incorrect lose field.
+
+ * valarith.c (value_subscripted_rvalue): Use TARGET_BYTE_ORDER,
+ rather than checking endianness at runtime.
+
+ * main.c (comand_line_input): Accept comments anywhere, not
+ just at starts of lines.
+
+Sat Mar 31 21:59:35 1990 Jim Kingdon (kingdon at pogo.ai.mit.edu)
+
+ * symtab.c (check_stub_type): Call lookup_symbol with 5 args.
+
+Fri Mar 30 15:23:52 1990 Jim Kingdon (kingdon at pogo.ai.mit.edu)
+
+ * frame.h: #include param.h.
+ param.h: Protect against multiple inclusion.
+
+ * i386-tdep.c (i386_get_frame_setup): Fix comment about what
+ opcode 0x55 is.
+ If 0x81 or 0x83 is followed by something besides 0xec,
+ put codestream back where it was and return 0.
+ [USE_MACHINE_REG_H]: Include <machine/reg.h> not <sys/reg.h>
+ Move include of a.out.h above <sys/user.h>.
+ (i386_frame_find_saved_regs): Make locals signed.
+ (i386_frame_find_saved_regs, i386_push_dummy_frame, i386_pop_frame):
+ Use REGISTER_BYTES, REGISTER_RAW_SIZE, etc. to deal with floating
+ point registers.
+
+Wed Mar 28 18:33:40 1990 Jim Kingdon (kingdon at mole.ai.mit.edu)
+
+ * Makefile.dist (OTHERS): Add gdb.dvi.
+ (gdb.dvi): New rule.
+
+ * breakpoint.c (_initialize_breakpoint): Clean up docstrings so
+ as not to mention subcommands (e.g. auto-display).
+ Call add_cmd not add_abbrev_cmd for "disable breakpoint" and
+ put it in class_alias.
+
+ * breakpoint.c (set_breakpoint_count): New function.
+ (set_breakpoint, break_command_1): Use it.
+
+ * breakpoint.c (get_number): New function.
+ (*_command, map_breakpoint_numbers): Use it.
+
+ * infptrace.c (write_inferior_memory): Remove remote_debugging
+ stuff (is handled in core.c).
+ (read_inferior_memory): Remove #if 0'd out remote_debugging code.
+
+Tue Mar 27 16:51:27 1990 Jim Kingdon (kingdon at mole.ai.mit.edu)
+
+ * inferior.h: Include frame.h.
+
+ * findvar.c (write_register): Replace sun4 #ifdef with
+ check of CANNOT_STORE_REGISTER.
+ xm-sparc.h: Define CANNOT_STORE_REGISTER.
+
+ * sparc-tdep.c: Remove superfluous declaration of
+ get_breakpoint_commands.
+
+ * breakpoint.{c,h}: Add bpstat stuff.
+ bpstat_do_action: Re-work do_breakpoint_commands into this.
+ main.c (command_loop): Call bpstat_do_action not
+ do_breakpoint_commands.
+ inferior.h, infrun.c, breakpoint.c, infcmd.c:
+ Rework breakpoint_commands and stop_breakpoint
+ stuff to use bpstat instead.
+
+ * infcmd.c (program_info): "info reg"->"info registers".
+
+ * np1-opcode.h: Renamed from npl-opcode.h.
+ gould-pinsn.c: Include np1-opcode.h.
+ Makefile.dist (OPCODES): Change npl-opcode.h to np1-opcode.h
+
+ * coffread.c (read_enum_type): Stop reading when we hit .eos.
+
+Mon Mar 26 15:52:35 1990 Jim Kingdon (kingdon at pogo.ai.mit.edu)
+
+ * Version 3.90.3.
+
+ * breakpoint.c (read_memory_nobpt): New function.
+ gdbcore.h: Declare read_memory_{nobpt,check}.
+ mips-tdep.c: Use read_memory_nobpt not breakpoint_shadow_val.
+
+Fri Mar 23 14:26:38 1990 Jim Kingdon (kingdon at mole.ai.mit.edu)
+
+ * inflow.c (terminal_inferior): Reenable commented out
+ inferior_thisrun_terminal check.
+ (terminal_ours_1): If inferior_thisrun_terminal is nonzero,
+ return immediately.
+
+ * Makefile.dist: Rewrite DEPFILES, M_FILE, etc. stuff to deal
+ with host & target separation.
+
+ * config/*: Split into xconfig/* and tconfig/*.
+ *-dep.c: Split into *-xdep.c and *-tdep.c.
+
+ * main.c (main): Always pass two args to xrealloc.
+
+Thu Mar 22 20:29:25 1990 Jim Kingdon (kingdon at mole.ai.mit.edu)
+
+ * Makefile.dist ({,dist}clean): rm {x,t}m.h not param.h
+ xgdb.o: Remove obsolete dependency (now in depend).
+
+ * arm-pinsn.c: Include arm-opcode.h not opcode.h.
+
+ * mips-pinsn.c, mips-opcode.h: New files from Bothner (from
+ release of 24 Jan 90 with mips-opcode.h patch from 1 Feb 90).
+
+ * utils.c (xmalloc): Return NULL on request for 0 bytes.
+
+Wed Mar 21 13:30:08 1990 Jim Kingdon (kingdon at mole.ai.mit.edu)
+
+ * config.gdb: Re-write machine stuff to deal with host & target.
+
+ * xm-altos.h: Don't define HAVE_WAIT_STRUCT.
+
+ * m-*.h: Split into xm-*.h and tm-*.h.
+
+ * infrun.c (wait_for_inferior): Put #ifdef sony_news code
+ in regardless of machine.
+
+ * symtab.c (decode_line_1): Add quotes and capitalize error
+ message "no class, struct, or union named".
+
+ * Makefile.dist (cplus-dem.o): Compile with -Dnounderscore.
+
+ * stack.c (print_frame_info): Use print_symbol to print function name.
+
+ * symtab.c (output_source_filename): Don't print a comma if
+ we are skipping a filename already printed.
+
+Tue Mar 20 10:48:54 1990 Jim Kingdon (kingdon at mole.ai.mit.edu)
+
+ * symtab.c (output_source_filename): Don't print a filename
+ more than once.
+
+ * utils.c (fprint_symbol): New function.
+ defs.h: Decalare it.
+ various: Use fprint_symbol to print symbol names.
+ Makefile.dist (SFILES, OBS): Add cplus-dem.{c,o}.
+
+Mon Mar 19 17:11:03 1990 Jim Kingdon (kingdon at mole.ai.mit.edu)
+
+ * coffread.c (read_file_hdr): Add MC68K??MAGIC.
+
+ * coffread.c (read_coff_symtab): Ignore swbeg and string label
+ symbols.
+
+ * coffread.c (read_coff_symtab): Increment num_object_files
+ in case C_STAT not C_FILE.
+ New variable in_source_file. Set it in case C_FILE.
+ Check it in case C_STAT.
+
+ * coffread.c [FUNCTION_EPILOGUE_SIZE]: New code.
+ m-umax.h (FUNCTION_EPILOGUE_SIZE): Define.
+
+ * config/3b1: New file.
+
+ * config/sun*: Print message warning people to use GAS with GCC.
+
+Sun Mar 18 02:56:40 1990 Jim Kingdon (kingdon at mole.ai.mit.edu)
+
+ * infcmd.c (run_stack_dummy): Change error message.
+
+ * m-68k.h (REGISTER_VIRTUAL_TYPE): Make pc, fp, sp char *.
+
+ * m-mips.h (LONGEST, BUILTIN_TYPE_LONGEST): Remove.
+
+Sat Mar 17 21:27:49 1990 Jim Kingdon (kingdon at mole.ai.mit.edu)
+
+ * mips-dep.c: Remove infptrace.c stuff.
+
+ * m-bigmips.h: New file.
+ m-mips.h [MIPSEB]: Remove *_BIG_ENDIAN stuff.
+
+ * m-sparc.h (FIX_CALL_DUMMY): Do not insert unimp instruction
+ if function was compiled with gcc.
+
+ * m-mips.h: Remove FIX_CALL_DUMMY_ALIGNED and make FIX_CALL_DUMMY
+ use new args.
+
+ * valops.c (call_function): New args to FIX_CALL_DUMMY.
+ m-*.h (FIX_CALL_DUMMY): Take new args.
+
+ * values.c (using_struct_return): New parameter gcc_p.
+ valops.c (call_function): New variable using_gcc.
+ valops.c (call_function) [REG_STRUCT_HAS_ADDR]: New code.
+
+ * m-mips.h, mips-dep.c: New files from Forin.
+ m-mips.h: Replace RETURN_STRUCT_BY_REF with USE_STRUCT_CONVENTION.
+
+Fri Mar 16 13:17:19 1990 Jim Kingdon (kingdon at pogo.ai.mit.edu)
+
+ * Makefile.dist: Add some dependencies of m-*.h files.
+ (HFILES): Add m-68k.h.
+
+ * dbxread.c (read_struct_type): Put "operator+" not "operator +"
+ in symtab.
+
+ * core.c: Split read_memory into read_memory_check and read_memory.
+ breakpoint.c (insert_breakpoints): If can't read memory,
+ tell user that error was due to seting breakpoints.
+
+Thu Mar 15 11:47:19 1990 Jim Kingdon (kingdon at pogo.ai.mit.edu)
+
+ * infrun.c [COFF_ENCAPSULATE]: Include a.out.encap.h.
+
+ * blockframe.c (FRAMELESS_LOOK_FOR_PROLOGUE): Make it a function.
+ various m-*.h: Call function not macro.
+ frame.h: Declare the function.
+
+Wed Mar 14 02:44:51 1990 Jim Kingdon (kingdon at pogo.ai.mit.edu)
+
+ * sparc-dep.c: Include signame.h.
+
+ * sparc-pinsn.c (print_insn): When looking for sethi before
+ delayed branch, call read_memory_noerr not read_memory.
+
+ * m-isi.h, m-sun3.h, m-news.h, m-hp300bsd.h, m-altos.h,
+ m-hp300hpux.h, m-sun2.h: Merge machine stuff except inferior
+ function call stuff into new file m-68k.h. Create m-3b1.h.
+
+Tue Mar 13 21:34:33 1990 Jim Kingdon (kingdon at pogo.ai.mit.edu)
+
+ * inflow.c (new_tty): If can't open tty, print error message
+ before exiting.
+
+ * blockframe.c: Remove declaration of psymtab_to_symtab.
+ symtab.h: Declare psymtab_to_symtab.
+ blockframe.c: Remove declarations of block_for_pc and
+ find_pc_function_start.
+ frame.h: Add declarations of block_for_pc and find_pc_function_start.
+ Remove declaration of nonexistent function find_pc_function.
+ values.c: include frame.h instead of declaring block_for_pc.
+
+ * Version 3.90.2.
+
+Mon Mar 12 14:20:06 1990 Jim Kingdon (kingdon at pogo.ai.mit.edu)
+
+ * main.c (main): Delete superfluous "e" from long_options.
+
+Sat Mar 10 15:47:23 1990 Jim Kingdon (kingdon at pogo.ai.mit.edu)
+
+ * valprint.c (val_print): Print <%d bit integer> not just
+ <large integer>.
+
+ * dbxread.c (error_type): Fix loop that finds '\0' so that on
+ exit, *pp points to the '\0', not the character after.
+ (read_type): Make sure that places which call read_type and then
+ try to read more input stop immediately with another error
+ upon encountering '\0'.
+
+ * dbxread.c (read_range_type): Fix check for large signed
+ integral type to match comment and reality. Set TYPE_LENGTH based
+ on n2bits for signed, n3bits for unsigned.
+
+ * infcmd.c (cont_command): Print warning message if we
+ decide to ignore the argument.
+
+ * gdb.texinfo (attach): @xref{Attach} -> @xref{Remote}.
+
+Fri Mar 9 16:26:47 1990 Jim Kingdon (kingdon at pogo.ai.mit.edu)
+
+ * symtab.h (address_class): Reinstate LOC_EXTERNAL with rewritten
+ comment.
+
+ * expread.y (yyerror, parse_c_1): Make yyerror take a char * arg.
+
+ * main.c (symbol_completion_function): Don't call error() on
+ "info jkldskf".
+
+ * m-npl.h (USE_STRUCT_CONVENTION): Change >= to >.
+
+Thu Mar 8 00:19:01 1990 Jim Kingdon (kingdon at pogo.ai.mit.edu)
+
+ * symseg.h: Nuke more symseg references including LOC_EXTERNAL.
+ Put contents of symseg.h into symtab.h and remove symseg.h.
+
+Wed Mar 7 18:02:15 1990 Jim Kingdon (kingdon at pogo.ai.mit.edu)
+
+ * symtab.h (SYMBOL_LINE): New macro.
+ symtab.c (decode_line_1): Accept variable as well as function.
+ Lookup variable/function in selected block if no file specified.
+ printcmd.c: #if 0 out whereis_command.
+
+ * command.c (do_setshow_command): Call function with additional
+ argument C.
+ main.c (set_history_size_command): Take argument C.
+ (set_verbose): New function to set docstring.
+ (initialize_main): Put set_verbose in command list.
+ command.c (lookup_cmd_1): Accept result_list NULL.
+
+ * valprint.c (_initialize_valprint): Change docstring for
+ "set unionprint" to normal set/show form.
+
+ * command.c (add_show_from_set): Check that docstring starts with
+ "Set " before assuming it does.
+
+ * main.c (show_history): Call cmd_show_list.
+ command.{c,h} (cmd_show_list): New function.
+ command.h: Declare do_setshow_command.
+
+ * command.h (cmd_list_element): New field completer.
+ main.c (symbol_completion_function): Use it.
+ symtab.h: Declare make_symbol_completion_list.
+ command.c (add_cmd): Set completer.
+ main.c, gdbcmd.h (noop_completer): New function.
+ infcmd.c: Set completer for environment functions.
+
+ * symtab.c (types_info, _initialize_symtab): #if 0 out.
+ various: Use fputs_filtered, not fprintf_filtered(%s).
+
+ * valprint.c (type_print_base): Check for integers larger than
+ LONGEST.
+
+ * sun3-dep.c: Include "signame.h" instead of directly declaring
+ sys_siglist.
+
+Tue Mar 6 14:59:34 1990 Jim Kingdon (kingdon at pogo.ai.mit.edu)
+
+ * infrun.c (signals_info): Allow argument to be a signal name
+ as well as an expression.
+ (handle_command): Check for error from sig_number.
+
+ * main.c (float_handler): Change error message.
+
+ * inflow.c (create_inferior): If getenv ("SHELL") exists, use it
+ instead of /bin/sh.
+
+ * dbxread.c (read_dbx_symtab, case N_SO): New variable first_symnum.
+ Pass it to {start,end}_psymtab.
+
+ * dbxread.c (read_ofile_symtab): Increment symbuf_idx and symnum
+ when calling process_symbol_pair.
+
+ * symtab.c (sources_info, output_source_filename):
+ Re-write so output_source_filename takes a first parameter
+ instead of a next one.
+
+ * dbxread.c (read_dbx_symtab, case N_SO): When incrementing
+ symbuf_idx, increment symnum also.
+
+ * values.c (set_internalvar_component): Use VALUE_CONTENTS,
+ not VALUE_CONTENTS_RAW.
+
+ * symmisc.c (free_symtab): Don't free filename (now in symbol_obstack).
+
+ * environ.c (init_environ): Copy entire string, including
+ terminating '\0'.
+
+ * value.h, values.c: Rename value_lazy to value_fetch_lazy.
+ values.c (value_of_internalvar): Call value_fetch_lazy.
+
+ * dbxread.c (read_huge_number): Return an error on encountering
+ a large decimal number.
+
+ * dbxread.c (read_huge_number): Reverse sense of overflow test.
+
+ * valprint.c (val_print, case TYPE_CODE_INT): Check for integers
+ larger than LONGEST.
+
+ * dbxread.c (read_ofile_symtab): When calling process_one_symbol,
+ call it with desc and value rather than with bufp->n_{desc,value}.
+
+ * defs.h (LONG_MAX): Define.
+
+ * sun3-dep.c: Declare sys_siglist.
+
+ * infptrace.c: Move include of gdbcore.h after a.out.h
+
+ * Makefile.dist (expread.o, mcheck.o): Remove leading "./" not
+ leading ".".
+
+ * m-hp300hpux.h [!HPUX_VERSION_5]: Define KERNEL_U_ADDR_HPUX.
+ infptrace.c [KERNEL_U_ADDR_HPUX] [KERNEL_U_ADDR_BSD]:
+ Set kernel_u_addr using nlist().
+ m-hp300bsd.h: Define KERNEL_U_ADDR_BSD.
+
+Mon Mar 5 16:52:41 1990 Jim Kingdon (kingdon at pogo.ai.mit.edu)
+
+ * dbxread.c (read_dbx_symtab): If value of .o symbol is crazy,
+ don't end psymtab.
+
+ * dbxread.c (read_dbx_symtab): Ignore first of a pair of N_SO
+ when both appear.
+ (start_subfile, start_symtab): Extra parameter dirname.
+ (start_subfile): Use obsavestring, not savestring, for name.
+ various: Call start_{subfile,symtab} with extra argument.
+ (end_symtab): Set dirname field in symtab.
+ (read_ofile_symtab): Call process_symbol_pair on pair of N_SO.
+ (process_symbol_pair): New function.
+ symtab.h (symtab): New field dirname.
+ source.c (open_source_file): New function.
+ source.c: Use open_source_file instead of openp where appropriate.
+
+ * defs.h (TARGET_CHAR_BIT): Define.
+
+Sun Mar 4 13:11:48 1990 Jim Kingdon (kingdon at pogo.ai.mit.edu)
+
+ * dbxread.c (fill_symbuf): Print error messages nicely.
+
+ * Makefile.dist (SFILES): Put standalone.c at end.
+
+ * Makefile.dist (alldeps.mak): Put out backslash after arm-convert.s.
+
+ * symtab.{c,h} (builtin_type_error): New type.
+ symseg.h (type_code): Add TYPE_CODE_ERROR.
+ valprint.c (val_print, type_print_base),
+ values.c (using_struct_return, set_return_value):
+ Check for and deal with TYPE_CODE_ERROR.
+ dbxread.c (error_type): New function
+ (read_type and subroutines): Call error_type instead of error.
+
+ * dbxread.c (read_huge_number): New function.
+ (read_range_type): Use read_huge_number and check results
+ to see if it is a large integral type.
+
+ * symmisc.c: Remove symseg stuff.
+
+ * Gould NP1 changes from (or inspired by) chpmjd@gdr.bath.ac.uk
+ dbxread.c (read_dbx_symtab) [N_NBSTS]:
+ Treat this and N_NBLCS like N_LCSYM, etc.
+ (process_one_symbol) [BLOCK_ADDRESS_ABSOLUTE]: New code.
+ m-npl.h (USE_STRUCT_CONVENTION): Add.
+ (IGNORE_SYMBOL): Add 0xa4.
+ (END_OF_TEXT_DEFAULT): Remove.
+ (STRING_TABLE_OFFSET): don't add sizeof(int).
+ [!HAVE_VPRINTF]: Define vprintf to be doprnt, not printf.
+ (BLOCK_ADDRESS_ABSOLUTE): Define.
+ (BREAKPOINT): Pad to size of machine word.
+ (SAVED_PC_AFTER_CALL): Remove ` at start of line (!).
+ (R2_REGNUM): Define.
+ (SP_REGNUM, FP_REGNUM): Switch definitions.
+ (REGISTER_U_ADDR): Use FP_REGNUM in place of SP_REGNUM.
+ (STORE_STRUCT_RETURN, EXTACT_RETURN_VALUE, STORE_RETURN_VALUE,
+ call function stuff):
+ Replace bogus definitions with correct ones for NP1.
+ (CANNOT_EXECUTE_STACK): Define.
+ (FRAME_LOCALS_ADDRESS): Don't add 80.
+ (FRAME_FIND_SAVED_REGS): Also get SP.
+ gould-pinsn.c (findframe): Move framechain declaration outside #if 0.
+ infptrace.c (write_inferior_memory): Check addr against text_end
+ and use PT_WRITE_I or PT_WRITE_D as appropriate.
+ (store_inferior_registers): Don't try to write registers in
+ CANNOT_STORE_REGISTER.
+ m-npl.h (CANNOT_STORE_REGISTER): Define.
+ npl-opcode.h (lil): 0xf8080000 -> 0xf80b0000.
+
+ * munch: Distinguish between BSD and System V nm by actually
+ seeing what output from nm looks like.
+
+Fri Mar 2 13:43:36 1990 Jim Kingdon (kingdon at pogo.ai.mit.edu)
+
+ * printcmd.c (print_frame_args): Change highest_offset to point
+ to next unprinted arg.
+
+ * main.c (main): Print "type help for list of commands" along
+ with the version. Follow it with a blank line.
+
+Thu Mar 1 14:49:26 1990 Jim Kingdon (kingdon at pogo.ai.mit.edu)
+
+ * valprint.c: Move print_address for function from value_print
+ to val_print.
+
+Wed Feb 28 15:06:12 1990 Jim Kingdon (kingdon at pogo.ai.mit.edu)
+
+ * Makefile.dist (m-sun4os4.h): Depend on m-sparc.h
+
+ * Makefile.dist (version.c): Depend on Makefile.dist, not Makefile.
+
+ * Makefile.dist: Change MAKEFILES to Makefiles.
+
+ * symtab.h: Declare get_sym_file.
+ core.c: Include symtab.h.
+
+ * Move signal name stuff from utils.c to signame.c
+ Move signal name stuff from defs.h to signame.h.
+ Makefile.dist (SFILES, HFILES, OBS): Add signame.{c,h,o}.
+
+Mon Feb 26 12:03:12 1990 Jim Kingdon (kingdon at pogo.ai.mit.edu)
+
+ * command.c (add_cmd): Don't call savestring on name.
+
+Sun Feb 25 15:52:18 1990 Jim Kingdon (kingdon at pogo.ai.mit.edu)
+
+ * printcmd.c (print_frame_args): Make highest_offset an int.
+ New variable args_printed.
+ (print_frame_nameless_args): Remove parameter end and add num
+ and first.
+ (print_frame_args): Change call to print_frame_nameless_args.
+
+Fri Feb 23 21:40:15 1990 Jim Kingdon (kingdon at pogo.ai.mit.edu)
+
+ * stack.c (up_command, down_command):
+ Only print stack frame if from_tty.
+
+Thu Feb 22 12:01:36 1990 Jim Kingdon (kingdon at pogo.ai.mit.edu)
+
+ * expread.y: Inlcude value.h and don't cast return value from
+ lookup_internalvar.
+
+ * infrun.c: Remove code in #ifdef UMAX_PTRACE.
+
+ * values.c (convenience_info): Print in form "$foo = 5".
+ Don't print "Debugger convenience variables:" before first one.
+
+ * Makefile.dist: Remove ADD_FILES from CLIBS.
+ (gdb, kdb, xgdb): Put in ADD_FILES as well as CLIBS.
+
+ * m-pyr.h: #if 0 out call dummy stuff.
+ Put in POP_FRAME which just calls error().
+ valops.c: If CALL_DUMMY is not defined, put in dummy call_function
+ which just prints an error message.
+
+Tue Feb 20 22:11:40 1990 Jim Kingdon (kingdon at pogo.ai.mit.edu)
+
+ * breakpoint.c (commands_command): Add arg from_tty.
+
+ * main.c (main): Put if (!setjmp (to_top_level)) around calls
+ to *_command made in response to command line arguments.
+
+Mon Feb 19 13:58:28 1990 Jim Kingdon (kingdon at pogo.ai.mit.edu)
+
+ * main.c (main): Use getopt_long_only. Move one-character options
+ to long_options. Remove entries which are just unambiguous
+ abbreviations of other options.
+
+ * command.h: Add types cmd_types and var_types.
+ Add fields type, var_type, and var to struct cmd_list_element.
+ command.c (add_set_cmd, add_set_from_show): New functions.
+ (add_cmd): Set c->var_type.
+ (add_abbrev_cmd): Call add_cmd instead of duplicating code.
+ main.c: Add showlist.
+ Move parse_binary_operation from main.c to command.c.
+ command.c (do_setshow_command): New function.
+ gdbcmd.h: New file.
+ Makefile.dist: Add gdbcmd.h.
+ many files: Include gdbcmd.h, use add_set_cmd and add_show_from_set.
+ Replace info * with show * where appropriate.
+ utils.c (fputs_filtered): Use UINT_MAX in lines_per_page to mean
+ no paging.
+ defs.h: Define UINT_MAX.
+ infcmd.c (run_command): Use execute_command, not set_args_command.
+ main.c (execute_command): Call do_setshow_command if necessary.
+ main.c (show_command, show_history): New functions.
+ main.c (initialize_main): Call add_prefix_cmd
+ for show and show history.
+
+ * coffread.c (enter_linenos): Print error if
+ file_offset < linetab_offset.
+
+Sun Feb 18 15:37:05 1990 Jim Kingdon (kingdon at pogo.ai.mit.edu)
+
+ * convex-dep.c (comm_registers_info): Fix typo. ("argc"->"arg").
+
+Wed Feb 14 20:45:14 1990 Jim Kingdon (kingdon at pogo.ai.mit.edu)
+
+ * config.gdb: Create Makefile with make.
+
+ * Makefile.dist, config.gdb: Move "srcdir=" line from Makefile.dist
+ to new file Makefile.srcdir.
+
+ * valprint.c: Include <errno.h>.
+
+ * value.h: Declare value_coerce_function.
+
+ * findvar.c: Add missing " after #include "gdbcore.h
+
+ * main.c (main): Re-write command parsing to use getopt.
+ On "gdb +help" print options with '+' not '-'.
+ Makefile.dist: Add getopt.
+
+Tue Feb 13 00:08:27 1990 Jim Kingdon (kingdon at pogo.ai.mit.edu)
+
+ * Makefile.dist: Add "srcdir=."
+ config.gdb: Edit srcdir= rather than adding it to the beginning.
+
+ * pyr-dep.c: Make global_reg_offset, last_frame_offset not static.
+ Move definition of reg_stack_offset to core.c [REG_STACK_SEGMENT].
+
+ * config/pyramid: Print message about alloca.
+
+ * breakpoint.c (clear_command): When printing "no breakpoint"
+ error, only use arg if non-NULL.
+
+ * core.c (read_memory): Rename to read_memory_noerr.
+ (read_memory): New function which calls read_memory and checks for err.
+ gdbcore.h: Declare all extern core.c functions.
+ move myread from core.c to utils.c.
+ declare it in defs.h.
+ (read_memory_integer): move from infcmd.c to core.c.
+ gdbcore.h: Declare it.
+ Many places: Remove error checking on read_memory, or call
+ read_memory_noerr instead. Include "gdbcore.h" if calling either.
+
+ * value.h (COERCE_ARRAY): Coerce functions to function pointers.
+ valops.c (value_coerce_function): New function.
+
+ * core.c, convex-dep.c, arm-dep.c (xfer_core_file): Return EIO
+ if address out of bounds.
+
+ * m-arm.h, arm-dep.c arm-pinsn.c arm-opcode.h: New files.
+ dbxread.c, m-convex.h (VARIABLES_INSIDE_BLOCK): Add gcc_p parameter.
+ Makefile.dist (alldeps.mak): Special case for arm-convert.s.
+ dbxread.c (define_symbol): Check for local based on it not
+ being any one of the known deftypes.
+ values.c (using_struct_return): Use new macro USE_STRUCT_CONVENTION.
+
+ * Makefile.dist, config.gdb: Put in srcdir stuff.
+
+Mon Feb 12 22:46:16 1990 Jim Kingdon (kingdon at pogo.ai.mit.edu)
+
+ * breakpoint.c: Add addr_string and cond_string fields to
+ struct breakpoint.
+ (break_command_1): Set them. Use mention ().
+ (mention): Create with code from break_command_1.
+ (breakpoint_re_set): New function.
+ (breakpoint_clear): Remove.
+ (condition_command): Set cond_string.
+ (breakpoint_delete): Free cond_string and addr_string.
+ Declare parse_c_1's type and remove casts to struct expression *.
+ symmisc.c (free_all_symtabs): Don't call breakpoint_clear.
+ dbxread.c, coffread.c (reread_symbols): Call breakpoint_re_set,
+ Include breakpoint.h.
+ breakpoint.h: New file.
+ dbxread.c: Move declaration of symmisc.c functions to symtab.h.
+
+Sun Feb 11 17:29:23 1990 Jim Kingdon (kingdon at pogo.ai.mit.edu)
+
+ * symtab.c: Make lookup_block_symtab extern.
+ symtab.h: Declare it.
+ valops.c (value_of_this): Use it.
+
+Fri Feb 9 08:59:37 1990 Jim Kingdon (kingdon at pogo.ai.mit.edu)
+
+ * config/hp300hpux: Print message telling people to use gcc.
+
+ * value.h: Declare print_floating.
+ printcmd.c (print_scalar_formatted, case 'f'): Use print_floating.
+ valprint.c (val_print, case TYPE_CODE_FLT): Use print_floating.
+ valprint.c (print_floating): Make this function out of is_nan
+ and the code which was in val_print.
+ Put parentheses around high & 0xfffff.
+ Print sign and fraction for NaN's.
+ Print 17 digits not 16 for doubles.
+ (is_nan): Remove.
+ m-news.h, m-sun3.h: Define IEEE_FLOAT.
+
+ * Rename gld-pinsn.c to gould-pinsn.c.
+ config/{pn,npl}: Change name of gld-pinsn.c
+
+Tue Feb 6 00:25:36 1990 Jim Kingdon (kingdon at pogo.ai.mit.edu)
+
+ * infptrace.c: Define PT_ATTACH if not defined.
+ m-hp300hpux.h: Define ATTACH_DETACH.
+
+ * main.c (initialize_main): Change alias class to aliases.
+
+ * dbxread.c: Search and destroy references to symsegs.
+ Also remove some #if 0'd code.
+
+ * core.c: Remove reread_exec.
+ dbxread.c (reread_symbols): New function.
+ dbxread.c (symbol_file_command): Set symfile_mtime.
+ coffread.c: Same.
+ infcmd.c (run_command): Call reread_symbols not reread_exec.
+
+ * valprint.c (val_print): When printing string after char *, print
+ it for "" just like any other string.
+
+ * core.c (reread_exec): New procedure.
+ infcmd.c (run_command): Call reread_exec.
+
+ * coffread.c (symbol_file_command): Add from_tty.
+
+ * dbxread.c (symbol_file_command): Only ask about loading new
+ symbol table if from_tty.
+
+Mon Feb 5 02:25:25 1990 Jim Kingdon (kingdon at pogo.ai.mit.edu)
+
+ * inflow.c (inferior_died): Call breakpoint_clear_ignore_counts.
+
+ * Makefile.dist (OBS): Remove dbxread.o and coffread.o.
+
+ * config.gdb: Ignore files ending in '#' in config.
+
+ * stack.c (backtrace_command): Add QUIT to get_prev_frame loops.
+
+Sat Feb 3 22:25:09 1990 Jim Kingdon (kingdon at pogo.ai.mit.edu)
+
+ * Makefile.dist (YACC): Don't use -v.
+
+Fri Feb 2 19:26:50 1990 Jim Kingdon (kingdon at mole.ai.mit.edu)
+
+ * createtags: Only change .o to .c at end of name.
+
+ * Makefile.dist (alldeps.mak): new target.
+ (Makefile): add alldeps.mak.
+ (SOURCES): remove PINSNS.
+ (TAGFILES: use ALLPARAM.
+ (gdb.tar): add config/.
+
+ * config.gdb: Check for M_FILE= not #param.h
+ config/*: Make sure M_FILE= exists with space after M_FILE=.
+ Makefile.dist (TAGS): Pass M_FILE and DEPFILES.
+ createtags: Change .o to .c. Remove special tests for dep.c etc.
+
+ * dbxread.c, coffread.c: Don't check COFF_FORMAT and READ_DBX_FORMAT.
+ Makefile.dist: Move {dbx,coff}read.c from SFILES to ALLDEPFILES.
+ config/*: add dbxread.o or coffread.o to depfiles.
+
+ * Makefile.dist (depend): Depend on $(SOURCES), not force.
+
+Thu Feb 1 17:43:54 1990 Jim Kingdon (kingdon at pogo.ai.mit.edu)
+
+ * symmisc.c (print_symbol): Print newline after label.
+
+Wed Jan 31 22:35:38 1990 Jim Kingdon (kingdon at pogo.ai.mit.edu)
+
+ * dbxread.c (read_addl_syms): Remove code that checks for
+ _etext.
+ Move end_of_text_addr into read_dbx_symtab.
+ (read_dbx_symtab): #if 0 out code which checks for _etext.
+
+Tue Jan 30 15:40:19 1990 Jim Kingdon (kingdon at albert.ai.mit.edu)
+
+ * Makefile.dist (gdb.tar): Use readline's "make readline.tar"
+ instead of having a list of readline files.
+
+ * infrun.c (normal_stop): #if 0 out "you have found a bug in sh".
+
+ * munch (-DSYSV): Check for .text at end of name.
+ Optionally allow extra underscore before initialize.
+ Remove space between #! and /bin/sh.
+
+ * m-merlin.h: Put in clarifying comments about SHELL_FILE.
+ Makefile.dist (install): Execute M_INSTALL.
+ config/merlin: Define M_INSTALL.
+
+Mon Jan 29 04:32:09 1990 Jim Kingdon (kingdon at pogo.ai.mit.edu)
+
+ * inflow.c: Change all references to signal handlers from
+ int (*)() to void (*)().
+
+ * main.c: Declare init_signals before use & make it void.
+ Declare initialize_all_files.
+
+ * Makefile.dist (config.status): New target.
+
+Sat Jan 27 00:19:50 1990 Jim Kingdon (kingdon at pogo.ai.mit.edu)
+
+ * defs.h (enum command_class): Remove comma after last element.
+
+ * Makefile.dist (gdb.tar.Z): Use compress <foo >bar rather
+ than deleting gdb.tar.Z before starting.
+
+ * dbxread.c (process_one_symbol): Compare context_stack_depth
+ with !VARIABLES_INSIDE_BLOCK, not VARIABLES_INSIDE_BLOCK.
+
+ * mcheck.c: Put whole file in #if defined MALLOC_RANGE_CHECK.
+
+ * mcheck.c (checkhdr): Call fatal_dump_core not abort.
+
+ * mcheck.c: Copy from malloc distribution.
+
+ * main.c (main): Call init_malloc ().
+
+ * main.c (initialize_signals): Rename to init_signals.
+
+Fri Jan 26 00:53:23 1990 Jim Kingdon (kingdon at mole.ai.mit.edu)
+
+ * *dep.c: Make core_file_command return void.
+
+ * gdbcore.h [!KERNEL_U_ADDR]: Declare kernel_u_addr.
+ infptrace.c [!KERNEL_U_ADDR]: Make it extern.
+
+ * altos-dep.c (NBPG, UPAGES): Wrap #define in #if !defined.
+
+ * m-pn.h (GOULD_PN): Define.
+ *-pinsn.c: Include actual opcode table not just opcode.h
+
+ * main.c [ALIGN_STACK_ON_STARTUP]: New code.
+ m-i386.h: Define ALIGN_STACK_ON_STARTUP.
+
+ * m-merlin.h (NO_SIGINTERRUPT, SHELL_FILE): Define.
+
+ * Move code from infptrace [USE_PTRACE_GETREGS] to sun3-dep.c.
+ m-sun{2,3}.h, m-sparc.h: Define FETCH_INFERIOR_REGISTERS.
+
+ * Makefile.dist, config.gdb, config/*:
+ Re-write to use machine-dependent makefiles instead of cpp.
+
+ * m-hp300hpux.h: Define FETCH_INFERIOR_REGISTERS.
+ infptrace.c: Put {fetch,store}_inferior_registers inside
+ #if !defined FETCH_INFERIOR_REGISTERS.
+
+ * Split execcore.c into exec.c and coredep.c.
+ Move a bunch of stuff from coredep.c and *dep.c to gdbcore.h.
+
+ * infptrace.c ({fetch,store}_inferior_registers):
+ Use U_REGS_OFFSET to set offset.
+ m-umax.h: Define U_REGS_OFFSET.
+
+ * m-umax.h: Define PTRACE_{ATTACH,DETACH}.
+
+ * m-i386.h (N_SET_MAGIC): Define.
+ m-i386gas.h: add #undef N_SET_MAGIC.
+
+Thu Jan 25 18:39:45 1990 Jim Kingdon (kingdon at mole.ai.mit.edu)
+
+ * m-hp300bsd.h: Remove KERNEL_U_ADDR.
+
+ * infptrace.c [!KERNEL_U_ADDR]: Get address of kernel u area
+ at runtime.
+
+ * infptrace.c: Replace numbers with PT_KILL, etc.
+ (store_inferior_registers): Loop for as many words are in the register.
+
+ * infptrace.c [NO_SINGLE_STEP]: Call single_step().
+
+ * kill_inferior{,_fast}: Declare as returning void.
+
+ * m-sun3.h (USE_PTRACE_GETREGS): Define.
+
+ * execcore.c: Add IS_OBJECT_FILE & related stuff.
+
+ * infptrace.c: Include <sys/ptrace.h>.
+ [ATTACH_DETACH] [USE_PTRACE_GETREGS]: New code.
+
+ * Split default-dep.c into infptrace.c and execcore.c.
+
+ * valprint.c [IEEE_FLOAT]: Change void * to char *.
+
+ * breakpoint.c: Change printf_filtered(%s) to fputs_filtered.
+
+Wed Jan 24 00:35:52 1990 Jim Kingdon (kingdon at pogo.ai.mit.edu)
+
+ * dbxread.c (symbol_file_command): When freeing everything, free
+ the string table too.
+
+ * Makefile.dist (gdb1): add "rm -f gdb1".
+
+ * printcmd.c (print_scalar_formatted): If size is 0, use 'b'
+ 'h', 'w', or 'g' depending on the type.
+
+ * stack.c (backtrace_command): Read in symbols for frames we'll
+ print before printing them.
+
+ * valops.c (value_at): Don't print "I/O error" on EIO from
+ ptrace. Don't print "out of bounds" for any ptrace error
+ except EIO.
+
+ * valprint.c (type_print_base, case TYPE_CODE_ENUM):
+ Print "FOO = 5" not "FOO : 5".
+
+ * symtab.{c,h}: Make lookup_misc_func extern.
+
+ * Makefile.dist: Define VERSION in makefile, and generate
+ version.c automatically.
+ (gdb.tar): Use gdb-$(VERSION), not dist-gdb.
+
+ * expread.y (yylex): Use lookup_primitive_typename to
+ cut down on calls to lookup_symbol.
+ symtab.{c,h} (lookup_primitive_typename): New function.
+ (lookup_typename): Use it.
+
+ * symtab.{c,h} (check_stub_type): New function.
+ valprint.c (type_print_base, val_print, type_print_derivation_info),
+ values.c (allocate_value): Call it.
+
+ * printcmd.c (whereis_command): New function.
+ symtab.c (lookup_symbol): Add symtab parameter.
+ various: Pass additional argument to lookup_symbol.
+ symseg.h (struct symbol): Add line field.
+ dbxread.c (define_symbol): Set sym->line.
+
+ * dbxread.c (symbol_file_command): Read string table into
+ malloc'd memory (symfile_string_table) and leave it there.
+ (psymtab_to_symtab): Use symfile_string_table.
+
+ * utils.c (sig_abbrev): Return NULL if not found.
+ infrun.c (sig_print_{header,info}): Consolidate duplicated
+ code from handle_command, signals_info.
+ (sig_print_info): Just print number if no name from sig_abbrev.
+
+ * Makefile.dist (OTHERS): Add ChangeLog-3.x
+
+ * infrun.c (restore_inferior_status): #if 0 out
+ "Unable to restore previously selected frame" error message.
+
+ * infrun.c (signals_info, handle_command): Print signal
+ abbrevs along with numbers.
+
+ * infrun.c (handle_command): Accept symbol signal names.
+
+ * utils.c (sig_{number,abbrev}, init_sig): New functions.
+ _initialize_utils: Call init_sig for each signal.
+ defs.h: Declare them.
+
+ * default-dep.c (read_inferior_memory): Check quit_flag in
+ fetch loop.
+
+ * Changes for lazy fetching (speeds things up for big objects):
+ value.h (struct value): New field lazy.
+ VALUE_CONTENTS_RAW, VALUE_LAZY, value_at_lazy: New.
+ findvar.c (read_var_value): Set lazy instead of fetching.
+ various: Copy into VALUE_CONTENTS_RAW, not VALUE_CONTENTS.
+ valops.c: Add value_at_lazy, value_lazy.
+ various: Call value_at_lazy instead of value_at.
+
+ * symtab.h (LONGEST): Define.
+
+ * m-*.h (LONGEST, BUILTIN_TYPE_LONGEST): Delete (in symtab.h).
+
+ * infrun.c (wait_for_inferior): #if 0 out stop if ABOUT_TO_RETURN
+
+ * version.c: Change version number to 4.0development
+
+For older changes see ChangeLog-3.x
+
+Local Variables:
+mode: indented-text
+left-margin: 8
+fill-column: 74
+version-control: never
+End:
diff --git a/gdb/ChangeLog-92 b/gdb/ChangeLog-92
new file mode 100644
index 00000000000..635c912e89e
--- /dev/null
+++ b/gdb/ChangeLog-92
@@ -0,0 +1,6285 @@
+Thu Dec 31 11:06:38 1992 Fred Fish (fnf@cygnus.com)
+
+ * Makefile.in (BISON): Add comment that when bison is used, it
+ must include the "-y" option.
+ * c-exp.y, m2-exp.y (yyrule, yyname, yyss, yyssp, yyvs, yyvsp):
+ Remove defines to remap non-yacc symbols, thus backing out of
+ previous recent changes. Standard policy is that non-yacc parser
+ generators get fixed, rather than adding bug workarounds in gdb
+ for each new one that pops up. Expand comment to note this.
+ * c-exp.y, m2-exp.y (YYDEBUG): Revert back to disabled by default.
+
+Thu Dec 31 09:03:02 1992 Stu Grossman (grossman at cygnus.com)
+
+ * partial-stab.h (near N_BINCL): Remove redundant code in N_BINCL
+ case. Use code in N_SOL.
+
+ * paread.c: New file that contains all HPPA/HPUX symbol reading
+ code.
+ * dbxread.c: Remove almost all HPPA/HPUX symbol reading code.
+ * (dbx_symfile_init): Use sizeof(long) instead of 4.
+ * (dbx_symfile_offsets): Make static.
+ * (pastab_build_psymtabs): New interface routine for paread to
+ send stabs into dbxread.
+ * gdb-stabs.h: Remove gobs of HPPA cruft.
+
+Wed Dec 30 19:47:13 1992 Fred Fish (fnf@cygnus.com)
+
+ * c-exp.y, m2-exp.y (yyrule, yyname): Remap like other yy* names
+ for byacc.
+ * ch-exp.y (yyrule, yyname): Remap like other yy* names for byacc.
+
+ * c-exp.y, m2-exp.y (yyreds, yytoks): Remap like other yy* names.
+ * c-exp.y, m2-exp.y (YYDEBUG): Define if MAINTENANCE_CMDS is defined
+ and YYDEBUG is not already defined.
+ * c-exp.y (strncmp): Replace throughout with STREQN, missed
+ them during the previous replacements.
+ * printcmd.c (_initialize_printcmd): Update internal documentation
+ for "set" command to note that the assignment syntax is language
+ dependent.
+ * ch-exp.y (yyreds, yytoks): Remap like other yy* names.
+ * ch-exp.y (YYDEBUG): Define if MAINTENANCE_CMDS is defined
+ and YYDEBUG is not already defined.
+ * ch-exp.y (GDB_REGNAME, GDB_LAST, GDB_VARIABLE, GDB_ASSIGNMENT,
+ single_assignment_action): New terminals and nonterminal for gdb
+ extensions to chill expression grammer.
+ * ch-exp.y (match_dollar_tokens): Lexer routine to match all
+ tokens that start with '$' (register names, convenience vars, etc).
+ * ch-exp.y (tokentab2): Add GDB_ASSIGNMENT.
+ * ch-exp.y (yylex): Call match_dollar_tokens.
+
+Mon Dec 28 15:00:01 1992 Stu Grossman (grossman at cygnus.com)
+
+ * hppah-tdep.c (skip_trampoline_code): Use new macros for
+ accessing minimal symbol data.
+ * infcmd.c (read_pc): Use #ifdef, not #if.
+ * symfile.c (syms_from_objfile): Add CONST to decl for targets.
+ * tm-hppa.h (FIX_CALL_DUMMY): Use new macros for accessing
+ minimal symbol data.
+
+ * hppah-tdep.c (frame_saved_pc): Use better test for outermost
+ frame. Use find_return_regnum to find the caller.
+ * (find_unwind_entry): New routine to locate stack frame info
+ associated with a procedure. This looks in the $UNWIND_START$
+ section in the SOM file.
+ * (find_return_regnum): New routine. Uses find_unwind_entry() to
+ figure out where the caller's return address is stored.
+ * (find_proc_framesize): New routine. Uses find_unwind_entry()
+ to figure out the frame size for a procedure.
+ * (saved_pc_after_call): New routine, moved from tm-hppa.h.
+ * (init_extra_frame_info): New routine. Corrects PC and FP for
+ outermost frame if necessary.
+ * (frame_chain): New routine, moved from tm-hppa.h.
+ * (skip_trampoline_code): Handle computed function calls (ie:
+ calls from $$dyncall).
+ * (unwind_command): Temporary support function to allow user
+ to control/observe aspects of the unwind (stack frame) info.
+ * infcmd.c (read_pc): (Temporary), put a hack in to see if the PC
+ was in a system call, if so, then read the PC from r31.
+ * tm-hppah.h (SKIP_TRAMPOLINE_CODE, IN_SOLIB_TRAMPOLINE): Deal
+ with extra arg for skip_trampoline_code().
+ * (INIT_EXTRA_FRAME_INFO): Define to point at subr (see above).
+ * (FRAME_CHAIN, FRAME_CHAIN_VALID): Turn into real subroutines.
+ * tm-hppa.h (SAVED_PC_AFTER_CALL): Turn into real subroutine.
+
+Sun Dec 27 17:34:15 1992 Fred Fish (fnf@cygnus.com)
+
+ * dbxread.c (dbx_symfile_init, elfstab_build_psymtabs):
+ Call new bfd_get_size() and verify that string table is no larger
+ than the file that is supposed to contain it.
+ * symfile.c (syms_from_objfile): Only complain about configured
+ NAMES_HAVE_UNDERSCORE differences between gdb and bfd if the
+ current target is the default BFD target.
+
+Sat Dec 26 20:51:41 1992 Fred Fish (fnf@cygnus.com)
+
+ * solib.c (BKPT_AT_MAIN): Change to BKPT_AT_SYMBOL.
+ * solib.c (bkpt_names): New array of symbol names to try to
+ use for the "mapping complete" breakpoint. Configurable
+ define SOLIB_BKPT_NAME is first one to try.
+ * solib.c (find_solib): Test debug_base for nonzero rather
+ than just greater than zero.
+ * solib.c (enable_break): Use bkpt_names to look up address
+ at which to set "mapping complete" breakpoint.
+
+Tue Dec 22 20:33:38 1992 Fred Fish (fnf@cygnus.com)
+
+ * defs.h (STRCMP, STREQ, STREQN): New macros.
+ * defs.h (demangle_and_match): Remove prototype.
+ * dwarfread.c (STREQ, STREQN): Remove macros, replaced with STREQ
+ and STREQN defined in defs.h.
+ * dwarfread.c (set_cu_language): For completely unknown languages,
+ try to deduce the language from the filename. Retain behavior
+ that for known languages we don't know how to handle, we use
+ language_unknown.
+ * dwarfread.c (enum_type, symthesize_typedef): Initialize language
+ and demangled name fields in symbol.
+ * dwarfread.c, mipsread.c, partial-stab.h: For all usages of
+ ADD_PSYMBOL_TO_LIST, add language and objfile parameters.
+ * dwarfread.c (new_symbol): Attempt to demangle C++ symbol names
+ and cache the results in SYMBOL_DEMANGLED_NAME for the symbol.
+ * elfread.c (STREQ): Remove macro, use STREQ defined in defs.h.
+ Replace usages throughout.
+ * elfread.c (demangle.h): Include.
+ * elfread.c (record_minimal_symbol): Remove prototype and function.
+ * gdbtypes.h, symtab.h (B_SET, B_CLR, B_TST, B_TYPE, B_BYTES,
+ B_CLRALL): Moved from symtab.h to gdbtypes.h.
+ * infcmd.c (jump_command): Remove code to demangle name and add
+ it to a cleanup list. Now just use SYMBOL_DEMANGLED_NAME.
+ * minsyms.c (demangle.h): Include.
+ * minsyms.c (lookup_minimal_symbol): Indent comment to match code.
+ * minsyms.c (install_minimal_symbols): Attempt to demangle symbol
+ names as C++ names, and cache them in SYMBOL_DEMANGLED_NAME.
+ * mipsread.c (psymtab_language): Add static variable.
+ * stabsread.c (demangle.h): Include.
+ * stabsread.c (define_symbol): Attempt to demangle C++ symbol
+ names and cache them in the SYMBOL_DEMANGLED_NAME field.
+ * stack.c (return_command): Remove explicit demangling of name
+ and use of cleanups. Just use SYMBOL_DEMANGLED_NAME.
+ * symfile.c (demangle.h): Include.
+ * symfile.c (add_psymbol_to_list, add_psymbol_addr_to_list): Fix
+ to match macros in symfile.h and allow them to be compiled
+ if INLINE_ADD_PSYMBOL is not true.
+ * symfile.h (INLINE_ADD_PSYMBOL): Default to true if not set.
+ * symfile.h (ADD_PSYMBOL_*): Add language and objfile parameters.
+ Add code to demangle and cache C++ symbol names. Use macro form
+ if INLINE_ADD_PSYMBOL is true, otherwise use C function form.
+ * symmisc.c (add_psymbol_to_list, add_psymbol_addr_to_list):
+ Remove, also defined in symfile.c, which we already fixed.
+ * symtab.c (expensive_mangler): Remove prototype and function.
+ * symtab.c (find_methods): Remove physnames parameter and fix
+ prototype to match.
+ * symtab.c (completion_list_add_symbol): Name changed to
+ completion_list_add_name.
+ * symtab.c (COMPLETION_LIST_ADD_SYMBOL): New macro, adds both
+ the normal symbol name and the cached C++ demangled name.
+ * symtab.c (lookup_demangled_partial_symbol,
+ lookup_demangled_block_symbol): Remove prototypes and functions.
+ * symtab.c (lookup_symbol): Remove use of expensive_mangler,
+ use lookup_block_symbol instead of lookup_demangled_block_symbol.
+ Remove code to try demangling names and matching them.
+ * symtab.c (lookup_partial_symbol, lookup_block_symbol):
+ Fix to try matching the cached demangled name if no match is
+ found using the regular symbol name.
+ * symtab.c (find_methods): Remove unused physnames array.
+ * symtab.c (name_match, NAME_MATCH): Remove function and macro,
+ replaced with SYMBOL_MATCHES_REGEXP from symtab.h.
+ * symtab.c (completion_list_add_symbol): Rewrite to use cached
+ C++ demangled symbol names.
+ * symtab.h: Much reformatting of structures and such to add
+ whitespace to make them more readable, and make them more
+ consistent with other gdb structure definitions.
+ * symtab.h (general_symbol_info): New struct containing fields
+ common to all symbols.
+ * symtab.h (SYMBOL_LANGUAGE, SYMBOL_DEMANGLED_NAME,
+ SYMBOL_SOURCE_NAME, SYMBOL_LINKAGE_NAME, SYMBOL_MATCHES_NAME,
+ SYMBOL_MATCHES_REGEXP, MSYMBOL_INFO, MSYMBOL_TYPE): New macros.
+ * symtab. (struct minimal_symbol, struct partial_symbol, struct
+ symbol): Use general_symbol_info struct.
+ * utils.c (demangle_and_match): Remove, no longer used.
+ * valops.c (demangle.h): Include.
+ * xcoffexec.c (eq): Remove macro, replace usages with STREQ.
+ * blockframe.c, breakpoint.c, c-exp.y, c-valprint.c, dbxread.c,
+ infcmd.c, m2-exp.y, minsyms.c, objfiles.h, solib.c, stack.c,
+ symmisc.c, symtab.c, valops.c: Replace references to minimal
+ symbol fields with appropriate macros.
+ * breakpoint.c, buildsym.c, c-exp.y, c-typeprint.c, c-valprint.c,
+ coffread.c, command.c, convex-tdep.c, cp-valprint.c, dbxread.c,
+ demangle.c, elfread.c, energize.c, environ.c, exec.c,
+ gdbtypes.c, i960-tdep.c, infrun.c, infrun-hacked.c, language.c,
+ main.c, minsyms.c, mipsread.c, partial-stab.h, remote-es1800.c,
+ remote-nindy.c, remote-udi.c, rs6000-tdep.c, solib.c, source.c,
+ sparc-pinsn.c, stabsread.c, standalone.c, state.c, stuff.c,
+ symfile.c, symmisc.c, symtab.c, symtab.h, tm-sysv4.h,
+ tm-ultra3.h, values.c, xcoffexec.c, xcoffread.c: Replace strcmp
+ and strncmp usages with STREQ, STREQN, or STRCMP as appropriate.
+ * breakpoint.c, buildsym.c, c-typeprint.c, expprint.c, findvar.c,
+ mipsread.c, printcmd.c, source.c, stabsread.c, stack.c,
+ symmisc.c, tm-29k.h, valops.c, values.c: Replace SYMBOL_NAME
+ references with SYMBOL_SOURCE_NAME or SYMBOL_LINKAGE_NAME as
+ appropriate.
+ * buildsym.c (start_subfile, patch_subfile_names): Default the
+ source language to what can be deduced from the filename.
+ * buildsym.c (end_symtab): Update the source language in the
+ allocated symtab to match what we have been using.
+ * buildsym.h (struct subfile): Add a language field.
+ * c-typeprint.c (c_print_type): Remove code to do explicit
+ demangling.
+ * dbxread.c (psymtab_language): Add static variable.
+ * dbxread.c (start_psymtab): Initialize psymtab_language using
+ deduce_language_from_filename.
+
+Mon Dec 21 22:24:33 1992 Fred Fish (fnf@cygnus.com)
+
+ * valprint.c (val_print): Reorganize comment and add note
+ about dependency on target byte ordering.
+ * ch-exp.y (value_array_slice): Fix typo.
+ * ch-valprint.c (chill_val_print): Remove C'ism that arrays of
+ byte sized ints are assumed to be char strings and printed with
+ string syntax. In chill, arrays of chars and arrays of
+ bytes/ubytes are distinquishable, and printed appropriately.
+
+Mon Dec 21 18:02:35 1992 Stu Grossman (grossman at cygnus.com)
+
+ * tm-hppah.h: #define NEED_TEXT_START_END for target memory
+ read/write routines for HPUX.
+
+ * hppa-pinsn.c (print_insn): Improve handling of be and ble
+ branch targets to compute target address using const from previous
+ instruction if necessary.
+ * Add `Q' operator to print out bit position field various
+ instructions.
+ * hppah-nat.c: #include sys/param.h, and sys/user.h. General
+ cleanups, use new code from Utah.
+ * (store_inferior_registers): Update to new code from Utah.
+ * (initialize_kernel_u_addr): Re-enable decl of struct user u.
+ * (fetch_register): Clear out priv level when reading PCs.
+ * hppah-tdep.c: Get rid of gobs of KERNELDEBUG stuff.
+ * Remove decl of errno, #include wait.h and target.h.
+ * (frame_saved_pc): Check `flags' pseudo-register to see if we
+ were inside of a kernel call. If so, then PC is in a different
+ register. Also, mask out bottom two bits of all PCs so as not to
+ confuse higher level code.
+ * (push_dummy_frame): Create from #define in tm-hppa.h.
+ * (find_dummy_frame_regs): Update from Utah.
+ * (hp_pop_frame): Create from #define in tm-hppa.h.
+ * (hp_restore_pc_queue): New, from Utah.
+ * (hp_push_arguments): Big fixes from Utah.
+ * (pa_do_registers_info, pa_print_registers): Only print out fp
+ regs upon request.
+ * (skip_trampoline_code): New routine to deal with stubs that
+ live in nowhereland between callers and callees.
+ * i860-tdep.c: Remove decl of attach_flag.
+ * infrun.c (wait_for_inferior): Add new macro
+ INSTRUCTION_NULLIFIED, which can tell if the instruction pointed
+ at by PC will be nullified. If so, then step the target once more
+ so as to avoid confusing the user.
+ * (just before step_over_function:): Use stop_func_start, not
+ stop_pc when checking for the existance of line number info.
+ stop_func_start will reflect the proper address of the target
+ routine, not of the stub that we may be traversing to get there.
+ * tm-hppa.h: define SKIP_TRAMPOLINE_CODE and IN_SOLIB_TRAMPOLINE
+ to deal with the stubs that PA compilers sometimes stick between
+ callers and callees. Also, define FLAGS_REGNUM for access to the
+ `flags' pseudo-reg.
+ * (REGISTER_CONVERT_TO_VIRTUAL, REGISTER_CONVERT_TO_RAW): Use
+ memcpy, not bcopy.
+ * (CANNOT_STORE_REGISTER): New from Utah. Says that we can't
+ write gr0, PC regs, and PSW!
+ * (FRAME_FIND_SAVED_REGS): Bug fixes from Utah.
+ * (PUSH_DUMMY_FRAME, POP_FRAME): Make into real routines in
+ hppah-nat.c.
+ * (CALL_DUMMY, FIX_CALL_DUMMY): Fixes from Utah.
+ * Define struct unwind_table_entry.
+ * valops.c (call_function_by_hand): Add another arg to
+ FIX_CALL_DUMMY (under #ifdef GDB_TARGET_IS_HPPA). Why is this
+ necessary?
+
+Mon Dec 21 02:17:57 1992 david d `zoo' zuhn (zoo at cirdan.cygnus.com)
+
+ * remote-vx.c: remove include of "symfile.h", replace it with "complaints.h"
+
+Fri Dec 18 10:32:25 1992 Fred Fish (fnf@cygnus.com)
+
+ * Makefile.in (VERSION): Bump to 4.7.4.
+ * Makefile.in (SFILES_MAINDIR): Add typeprint.c, c-typeprint.c,
+ m2-typeprint.c, c-valprint.c cp-valprint.c m2-valprint.c.
+ * Makefile.in (HFILES): Add valprint.h.
+ * Makefile.in (OBS): Add typeprint.o, c-typeprint.o,
+ m2-typeprint.o, c-valprint.o, cp-valprint.o m2-valprint.o.
+ * typeprint.c, typeprint.h: New files for language independent
+ type printing functions.
+ * c-typeprint.c, m2-typeprint.c: New files for language dependent
+ type printing functions and definitions.
+ * valprint.h: New include file for language independent value
+ printing definitions.
+ * c-valprint.c, cp-valprint.c, m2-valprint.c: New files for language
+ dependent value printing functions.
+ * c-exp.y (production ptype): Add range_type variable and use new
+ create_range_type function.
+ * c-exp.y (tokentab2, tokentab3), c-lang.c (c_op_print_tab),
+ infcmd.c (path_var_name), language.c (unk_op_print_tab),
+ m2-lang.c (m2_op_print_tab): Change from ANSI-obsolescent
+ "const static" to ANSI-conformant "static const".
+ * c-exp.y (c_create_fundamental_type): Remove unused nbytes.
+ * c-exp.y (c_language_defn, cplus_language_defn): Add c_print_type,
+ and c_val_print.
+ * c-lang.h (c_print_type, c_val_print): Add prototypes.
+ * coffread.c (decode_type): Add range_type variable and call to
+ new create_range_type function.
+ * complaints.c (complain): Remove unused val variable.
+ * complaints.c (_initialize_complaints): Make it void.
+ * convex-tdep.c (value_of_trapped_internalvar): Add range_type
+ variable and call new create_range_type function.
+ * defs.h (enum val_prettyprint): Move enum from value.h to here
+ so we can avoid having to include value.h just for prototypes that
+ need the enum (thanks ANSI).
+ * dwarfread.c (struct_type): Local anonymous_size variable is
+ only used if !BITS_BIG_ENDIAN.
+ * dwarfread.c (decode_subscript_data_item): Add rangetype
+ variable and call new create_range_type function.
+ * elfread.c (elf_symfile_read): Remove unused dbx and text_sect
+ variables.
+ * eval.c (evaluate_subexp): Remove unused local variable name
+ and the statement with no side effects that initializes it.
+ * expprint.c (print_subexp): Change local_printstr to
+ LA_PRINT_STRING.
+ * gdbtypes.c (create_range_type): New function that creates
+ a range type using code fragments from object file readers as
+ an example of what has to be initialized.
+ * gdbtypes.c (create_array_type): Removed index_type, low_bound,
+ and high_bound parameters, replaced with a single range_type
+ parameter. Change function body to use passed in range_type
+ rather than handcrafting one.
+ * gdbtypes.h (create_range_type): Add prototype.
+ * gdbtypes.h (create_array_type): Change prototype parameters.
+ * infrun.c (normal_stop): Remove unused local variables tem and c.
+ * infrun.c (hook_stop_stub): Return 0 rather than random value.
+ * language.c (unk_lang_print_type, unk_lang_val_print): Add
+ stub functions that call error if called.
+ * language.c (unknown_language_defn, auto_language_defn,
+ local_language_defn): Add initializers unk_lang_print_type and
+ unk_lang_val_print.
+ * language.h (struct language_defn): Reformat for larger
+ comments, add la_print_type and la_val_print members. Add
+ LA_PRINT_TYPE and LA_VAL_PRINT macros. Change local_printchar
+ to LA_PRINT_CHAR and local_printstr to LA_PRINT_STRING.
+ * m2-lang.c (m2_create_fundamental_type): Remove unused local
+ variable nbytes.
+ * m2-lang.c (m2_language_defn): Add initializers m2_print_type
+ and m2_val_print.
+ * m2-lang.h (m2_print_type, m2_val_print): Add prototypes.
+ * main.c (execute_command): Remove unused local variable cmdlines.
+ * main.c (echo_command), stabsread.c (read_type), printcmd.c
+ (clear_displays), symmisc.c (block_depth), values.c
+ (clear_value_history):
+ Make testing of truth value of assignment result explicit.
+ * mipsread.c (upgrade_type): Update FIXME to include future use
+ of create_range_type.
+ * printcmd.c (ptype_command, ptype_eval, whatis_command,
+ whatis_exp, maintenance_print_type): Move prototypes and functions
+ to new typeprint.c.
+ * printcmd.c (_initialize_printcmd): Move add_com calls for
+ ptype_command and whatis_command to new typeprint.c.
+ * ser-bsd.c (serial_open): Remove unused variable sgttyb.
+ * source.c (find_source_lines): Local variable c only used
+ when LSEEK_NOT_LINEAR is defined.
+ * stabsread.c (read_array_type): Use new create_range_type
+ function.
+ * stabsread.c (read_range_type): Add new index_type variable and
+ call new create_range_type function rather than handcrafting
+ range types.
+ * symmisc.c (type_print_1): Change usages to LA_PRINT_TYPE.
+ * symtab.c (typedef_print usages): Use c_typedef_print, renamed.
+ * symtab.c (type_print_base usages): Use c_type_print_base.
+ * symtab.c (type_print_varspec_prefix usages): Use
+ c_type_print_varspec_prefix.
+ * symtab.c (type_print_method_args usages): Use
+ cp_type_print_method_args.
+ * valprint.c: Completely ripped apart and the fragments used
+ to create c-valprint.c, cp-valprint.c, m2-valprint.c, and
+ valprint.h. Remaining stuff is language independent.
+ * value.h (struct fn_field): Forward declare for prototypes.
+ * value.h (type_print_1): Remove prototype.
+ * value.h (enum val_prettyprint): Moved to defs.h.
+ * value.h (typedef_print): Prototype renamed to c_typedef_print.
+ * value.h (baseclass_offset): Add prototype.
+ * Makefile.in (SFILES_MAINDIR): Add ch-typeprint.c, ch-valprint.c.
+ * Makefile.in (OBS): Add ch-typeprint.o, ch-valprint.o.
+ * ch-typeprint.c: New file for language dependent type printing.
+ * ch-valprint.c: New file for language dependent value printing.
+ * ch-exp.y (parse_number): Remove prototype and stub function.
+ * ch-exp.y (decode_integer_literal): Removed unused digits and
+ temp variables.
+ * ch-exp.y (convert_float): Completely ifdef out for now.
+ * ch-exp.y (tokentab2, tokentab3, tokentab4, tokentab5),
+ ch-lang.c (chill_op_print_tab):
+ Change from ANSI-obsolescent "const static" to ANSI-conformant
+ "static const".
+ * ch-exp.y (yylex): Add unhandled storage class enumeration
+ literals to switch statement for completeness.
+ * ch-lang.c (chill_create_fundamental_types): Remove unused
+ nbytes variable. Change dummy type to 2 bytes to match int.
+ Handle FT_VOID types gratuituously added to chill DWARF by
+ compiler. Change FT_CHAR case to generate an TYPE_CODE_CHAR
+ type rather than a one byte TYPE_CODE_INT type.
+ * ch-lang.c (chill_language_defn): Add chill_print_type and
+ chill_val_print.
+ * ch-lang.h (chill_print_type, chill_val_print): Add prototypes.
+
+Thu Dec 17 00:44:57 1992 John Gilmore (gnu@cygnus.com)
+
+ Eliminate uses of NAMES_HAVE_UNDERSCORE, using
+ bfd_get_symbol_leading_char instead.
+
+ * coffread.c (EXTERNAL_NAME): New macro for removing possible
+ leading character from names.
+ (read_coff_symtab): Use BFD's FILE *, don't open a second one.
+ (process_coff_symbol, coff_read_struct_type, coff_read_enum_type):
+ Replace NAMES_HAVE_UNDERSCORE with EXTERNAL_NAME.
+
+ * kdb-start.c (main): Remove NAMES_HAVE_UNDERSCORE.
+ * minsyms.c (install_minimal_symbols): Replace NAMES_HAVE_UNDERSCORE.
+ Remove SOME_NAMES_HAVE_DOT support (apparently unused).
+ * partial-stab.h: Replace NAMES_HAVE_UNDERSCORE.
+ * solib.c: Replace NAMES_HAVE_UNDERSCORE.
+ * stabsread.h: Remove NAMES_HAVE_UNDERSCORE and HASH_OFFSET.
+ * symfile.c (syms_from_objfile): Insert debugging check to test
+ NAMES_HAVE_UNDERSCORE setting against the BFD support.
+
+ * doc/gdbint.texinfo (Host Conditionals): Remove
+ NAMES_HAVE_UNDERSCORE, SOME_NAMES_HAVE_DOT, document
+ MEM_FNS_DECLARED.
+ (Target Conditionals): Remove all of the above.
+
+ * xm-rs6000.h (MEM_FNS_DECLARED): Update comments.
+
+ * coffread.c (read_coff_symtab, C_BLOCK): Use complain() rather
+ than error() for .bb/.eb. Bug found by Eddie Fung, <efung@cs.uq.oz.au>.
+
+Tue Dec 15 10:05:56 1992 Ian Lance Taylor (ian@cygnus.com)
+
+ * coffread.c (decode_type): catch negative tagndx fields generated
+ by SCO 3.2v4 cc.
+ * exec.c: comment out string following #endif.
+ * configure.in (i[34]86-*-sco3.2v4*): use host i386sco4.
+ * xm-i386sco.h: include <sys/types.h> and <sys/dir.h>, required by
+ <sys/user.h>.
+ * config/i386sco4.mh: new file; like i386sco.mh, but don't require
+ gcc, and define const to empty to avoid SCO 3.2v4 cc bug.
+
+Tue Dec 15 04:14:24 1992 Fred Fish (fnf@cygnus.com)
+
+ * complaints.c: New file, code moved from utils.c.
+ * complaints.c (complain): Made into a varargs function.
+ * complaints.h: New file, code moved from symfile.h.
+ * Makefile.in (SFILES_MAINDIR): Add complaints.c.
+ * Makefile.in (HFILES): Add complaints.h.
+ * Makefile.in (OBS): Add complaints.o.
+ * symfile.c (complaint_root, stop_whining, complaint_series,
+ complain, clear_complaints, add_show_from_set for stop_whining):
+ Moved to complaints.c.
+ * symfile.h (struct complaint, complaint_root decl, complain
+ prototype, clear_complaints prototype): Moved to complaints.h.
+ * buildsym.c, coffread.c, dbxread.c, dwarfread.c, elfread.c,
+ gdbtypes.c, mipsread.c, stbsread.c, symfile.c: Include
+ complaints.h. Remove casts from arguments to complain(),
+ which is now a varargs function, and remove unnecessary
+ placeholder zero args.
+ * defs.h (begin_line): Add prototype.
+ * defs.h (vprintf_filtered): Add prototype.
+ * dwarfread.c (varargs.h): Remove, no longer needed.
+ * dwarfread.c (dwarfwarn): Remove prototype and function.
+ * dwarfread.c (complaints): Define a bunch of complaints.
+ * dwarfread.c (SQUAWK): Remove macro defs, convert all
+ usages to standard complain() calls.
+ * utils.c (begin_line): New function that ensures that
+ whatever gets filter-printed next starts on its own line.
+ * utils.c (vprintf_filtered): New func, like vfprintf_filtered,
+ but to stdout (calls vfprintf_filtered internally).
+
+Tue Dec 15 02:01:00 1992 John Gilmore (gnu@cygnus.com)
+
+ * remote.c: Avoid printf_filtered line limit. Suggested by
+ Robert R. Henry, <rrh@tera.com>.
+ * infcmd.c (environment_info): Ditto, for Don Allen <allen@think.com>.
+
+ * main.c (main): Accept --silent as well as --quiet. Change +help
+ to --help. Suggested by Karl Berry, <karl@cs.umb.edu>.
+
+ * doc/gdbint.texinfo: SWAP_HOST_AND_TARGET => SWAP_TARGET_AND_HOST.
+ Noticed by Andy Jackson, <arj@cam-orl.co.uk>.
+
+Mon Dec 14 23:28:15 1992 John Gilmore (gnu@cygnus.com)
+
+ * tm-nindy960.h, remote-nindy.c: Lint.
+
+Mon Dec 14 18:48:52 1992 Fred Fish (fnf@cygnus.com)
+
+ * gdbtypes.c (create_array_type): Complete rewrite. Now requires
+ a optional type to decorate as an array type, the type of the
+ index, and the bounds of the array. Records this additional info
+ in the array type for use with languages with nonzero array
+ bounds.
+ * gdbtypes.h (enum type_code): Update comment for TYPE_CODE_ARRAY
+ to note that arrays may have bounds.
+ * gdbtypes.h (create_array_type): Update prototype.
+ * c-exp.y (ptype production): Adjust for new create_array_type
+ calling conventions.
+ * coffread.c (decode_type): Call create_array_type rather than
+ handcrafting array types.
+ * convex-tdep.c (value_type): Remove, now use create_array_type.
+ * convex-tdep.c (value_of_trapped_internalvar): Convert calls to
+ vector_type into calls to create_array_type.
+ * dwarfread.c (decode_subscr_data): Name changed to
+ decode_subscript_data_item throughout.
+ * dwarfread.c (decode_subscript_data_item): Rewrite to use
+ create_array_type. Now records index type and range as well.
+ * dwarfread.c (dwarf_read_array_type): Rewrite as part of
+ change to use create_array_type.
+ * dwarfread.c (read_subroutine_type): Test existing user defined
+ types before decorating them, to ensure they are blank, and
+ complain about it if they are not.
+ * dwarfread.c (decode_fund_type): For unrecognized types, always
+ return some valid type (type integer). If the unrecognized type
+ cannot be an implementation defined type, complain as well.
+ * m88k-tdep.c (pushed_size): Update comment for TYPE_CODE_ARRAY.
+ * m88k-tdep.c (store_param): Update comment for TYPE_CODE_ARRAY.
+ * mipsread.c (upgrade_type): Add FIXME comment that code to
+ handcraft arrays should be replaced with call to create_array_type.
+ * stabsread.c (read_array_type): Replace code to handcraft
+ array types with call to create_array_type.
+ * valprint.c (type_print_varspec_prefix): Minor formatting
+ change, join lines that don't need to be split.
+
+Mon Dec 14 17:18:42 1992 Stu Grossman (grossman at cygnus.com)
+
+ * convex-xdep.c, hppab-nat.c, infptrace.c: Remove
+ decl for attach_flag, it now lives in inferior.h.
+ * hppa-pinsn.c: Reformat opcode tables. Add function prototypes.
+ Make most functions static.
+ * hppah-nat.c: General cleanups, remove BSD specific code (since
+ that all lives in hppab-nat.c).
+ * hppah-tdep.c (frame_chain_valid), tm-hppa.h (FRAME_CHAIN):
+ Change sense of test against inside_entry_file(). This fix is
+ from U. of Utah.
+ * tm-hppa.h (PUSH_DUMMY_FRAME, POP_FRAME): Use char * for 2nd arg
+ to read/write_register_bytes().
+ * gdbtypes.h: Remove const from decl for cplus_struct_default to
+ work around PA-GAS assembler bug. Also, add trailing */ to some
+ comments.
+ * gdbtypes.c: Remove const from decl for cplus_struct_default.
+ Same reason as above.
+
+Wed Dec 9 19:53:25 1992 John Gilmore (gnu@cygnus.com)
+
+ * mipsread.c (parse_symbol): When checking whether a structured
+ type is an enum, check qualifiers of its first member, as well as
+ the base type of the member. Bug found and fixed by John M.
+ Farrell, <farrell@fjord.reo.dec.com>.
+
+ * vx-share/{reg.h,xdr_regs.h,xdr_regs.c}: Remove, unused.
+ * remote-vx.c: Don't include vx-share/reg.h.
+ * vx-share/ptrace.h: Reproduce from scratch.
+ * config/{vxworks68,vxworks960}: Don't include xdr_regs.o.
+ * Makefile.in: Remove references to removed files, and to removed
+ 29k-share directories.
+
+Tue Dec 8 13:30:58 1992 Fred Fish (fnf@cygnus.com)
+
+ * c-lang.c (_initialize_c_language): Name changed from
+ _initialize_c_exp.
+ * m2-lang.c (_initialize_m2_language): Name changed from
+ _initialize_m2_exp.
+ * m2-lang.c (_initialize_m2_language): Change malloc to xmalloc since
+ it is no longer inside m2-exp.y, where it was remapped by Makefile.
+ * c-exp.y, m2-exp.y: Migrate code that has nothing to do with
+ expression parsing into c-lang.c and m2-lang.c respectively.
+ * c-lang.c, m2-lang.c: New files, code migrated from c-exp.y and
+ m2-exp.y respectively.
+ * c-lang.h, m2-lang.h: New files, internal interfaces between c-*
+ and m2-* files respectively.
+ * Makefile.in (SFILES_MAINDIR): Add c-lang.c, m2-lang.c.
+ * Makefile.in (HFILES): Add c-lang.h, m2-lang.h.
+ * Makefile.in (OBS): Add c-lang.o, m2-lang.o.
+ * expression.h (struct block): Forward declaration for prototypes.
+ * language.h (struct objfile): Forward declaration for prototypes.
+ * Makefile.in (SFILES_MAINDIR): Add ch-lang.c.
+ * Makefile.in (HFILES): Add ch-lang.h.
+ * Makefile.in (OBS): Add ch-lang.o.
+ * ch-exp.y: Migrate code that has nothing to do with expression
+ parsing into ch-lang.c.
+ * ch-lang.c: New file, code migrated from c-exp.y.
+ * ch-lang.h: New file, internal interface between ch-* files.
+ * ch-lang.c (_initialize_chill_language): Name changed from
+ _initialize_chill_exp.
+
+ Changes for Amiga Unix from rhealey@ub.d.umn.edu.
+ * config/amix.mh (NAT_FILE): Add, set to nm-sysv4.h.
+ * config/amix.mh (NATDEPFILES): Add.
+ * config/amix.mh (XDEPFILES): Move procfs.o and fork-child.o
+ to NATDEPFILES.
+
+ * dwarfread.c (decode_subscr_data): Remove spurious test that
+ accepted only integer subscript types. We don't do anything
+ with the type at the moment anyway.
+
+Fri Dec 4 06:56:56 1992 Fred Fish (fnf@cygnus.com)
+
+ * ch-exp.y (match_character_literal): Fix case where no
+ match at all is found.
+ * ch-exp.y (chill_create_fundamental_type): Chill uses fixed
+ width types. For example, "INT" is always 2 bytes regardless
+ of the values of any TARGET_*_BIT macros. So use explicit
+ numeric sizes for the types.
+
+Thu Dec 3 12:00:06 1992 Fred Fish (fnf@cygnus.com)
+
+ * c-exp.y (c_create_fundamental_type): New function to create
+ language specific fundamental types for C.
+ * m2-exp.y (m2_create_fundamental_type): New function to create
+ language specific fundamental types for Modula 2.
+ * c-exp.y (c_language_defn, cplus_language_defn): Add
+ c_create_fundamental_type to language struct initializers.
+ * m2-exp.y (m2_language_defn): Add m2_create_fundamental_type
+ to language struct initializers.
+ * dwarfread.c (expression.h, language.h): Include.
+ * dwarfread.c (ftypes): New array to hold fundamental types
+ for current compilation unit.
+ * dwarfread.c (cu_language_defn): New pointer to language
+ struct for language of current compilation unit.
+ * dwarfread.c (dwarf_fundamental_type): New function to
+ create/lookup fundamental types.
+ * dwarfread.c (set_cu_language): Initialize cu_language_defn.
+ * dwarfread.c (throughout): Replace lookup_fundamental_type
+ with dwarf_fundamental_type.
+ * dwarfread.c (read_file_scope): Zero out ftypes for each new
+ compilation unit (may be different language or different objfile).
+ * gdbtypes.c (lookup_fundamental_type): Move actual type
+ creations into language specific fundamental type creation
+ functions and call via create_fundamental_type. Add comment
+ about this function being obsolescent.
+ * gdbtypes.h (FT_BYTE, FT_UNSIGNED_BYTE): New types, true byte
+ sized signed and unsigned integers.
+ * gdbtypes.h (FT_NUM_MEMBERS): Increment, new types added.
+ * language.c (language_def): New function to lookup a language
+ struct given it's enumeration.
+ * language.h (struct language_defn): Add la_fund_type, a pointer
+ to a function that creates fundamental types for this language.
+ * language.h (create_fundamental_type): New macro to create
+ fundamental types based on the current language.
+ * language.h (language_def): Add prototype.
+ * language.c (unk_lang_create_fundamental_type): New function
+ for initializing language structs, calls error if called.
+ * language.c (unk_language_defn, auto_language_defn,
+ local_language_defn): Use unk_lang_create_fundamental_type.
+ ch-exp.y (chill_create_fundamental_type): New function.
+ ch-exp.y (chill_language_defn): Add chill_create_fundamental_type.
+ ch-exp.y (_initialize_chill_exp): BOOL types are only one byte.
+
+Tue Dec 1 17:07:31 1992 Fred Fish (fnf@cygnus.com)
+
+ * dwarfread.c (CHILL_PRODUCER): Add producer string for
+ GNU chill.
+ * dwarfread.c (handle_producer): Test CHILL_PRODUCER as well
+ as GCC_PRODUCER and GPLUS_PRODUCER.
+
+Mon Nov 30 18:46:58 1992 Stu Grossman (grossman at cygnus.com)
+
+ * remote-udi.c (udi_wait): Don't stop if TIP says that remote is
+ still running.
+
+Mon Nov 30 12:00:25 1992 Fred Fish (fnf@cygnus.com)
+
+ * tm-sun4sol2.h: Add CPLUS_MARKER. Solaris 2.0 requires '.'
+ rather than '$'. This particular piece of braindamage is
+ spreading like ooze. It's now infected libiberty, deja-gnu,
+ gdb, and gcc.
+ * values.c (baseclass_addr): Use CPLUS_MARKER rather than
+ hardwired '$' character.
+
+Sun Nov 29 15:22:42 1992 Fred Fish (fnf@cygnus.com)
+
+ (Changes to break incredibly ugly, unmaintainable 750 line
+ read_struct_type function up into managable pieces.)
+ * Makefile.in (VERSION): Bump to 4.7.3.
+ * stabsread.c (struct field_info): Local struct definition.
+ * stabsread.c (read_member_functions, read_struct_fields,
+ read_baseclasses, read_tilde_fields, attach_fn_fields_to_type,
+ attach_fields_to_type, read_cpp_abbrev): Prototypes and new
+ functions from fragmented read_struct_type.
+ * stabsread.c (stabs_general_complaint): Catchall complaint.
+ * stabsread.c (STABS_CONTINUE): Macro'ize cretinous stabs
+ symbol name continuation code. Use macro throughout.
+ * stabsread.c (various places): Replace add-one-to-pointer
+ with pointer increment.
+ * stabsread.c (read_type): Retain function local copy of type
+ descriptor. Rearrange code calling read_struct_type() to match
+ new conventions.
+ * stabsread.c (define_symbol): For the sake of dbx, gcc emits
+ a single blank as the name of nameless enumerations. Recognize
+ this special case and set nameless flag.
+ * ch-exp.y (GENERAL_PROCEDURE_NAME, LOCATION_NAME): New
+ terminal tokens.
+ * ch-exp.y (access_name): New non-terminal token and
+ production.
+ * ch-exp.y (general_procedure_name): Now a terminal token.
+ * ch-exp.y (location): Expand production.
+ * ch-exp.y (match_simple_name_string): New function.
+ * ch-exp.y (yylex): Call match_simple_name_string and return
+ GENERAL_PROCEDURE_NAME or LOCATION_NAME as appropriate.
+
+Wed Nov 25 07:17:13 1992 Fred Fish (fnf@cygnus.com)
+
+ * munch: Backslash escape vertical bar characters inside
+ grep patterns since they have special meaning for some greps.
+ * parse.c (write_exp_string): Complete rewrite to store string
+ contants as a leading explicit length, followed by the string data,
+ followed by a trailing explicit length.
+ * eval.c (evaluate_subexp), expprint.c (print_subexp),
+ parse.c (length_of_subexp), parse.c (prefixify_subexp):
+ Use recorded explicit length of strings in expression elements,
+ rather than strlen. Adjust code to skip over strings stored in
+ expression elements, and code to access strings, to account for
+ new leading explicit size expression element.
+ * parse.c (length_of_subexp): Test for minimum endpos of 1, not
+ 0, to avoid negative expression element indices.
+ * valops.c (search_struct_method): Minor whitespace change.
+
+Mon Nov 23 11:14:15 1992 Fred Fish (fnf@cygnus.com)
+
+ * c-exp.y (yylex): Add tempbuf, tempbufindex, and tempbufsize,
+ which together maintain a dynamically expandable static buffer
+ for the lexer to use when translating C strings to their internal
+ form (other future uses possible). Fix parsing of C style strings
+ to do the normal C style input conversions of escaped character
+ sequences.
+ * valops.c (value_string): Remove translation of escaped
+ character sequences, now done in C expression parser.
+ * language.h (PRINT_LITERAL_FORM): New macro that takes character
+ and decides if it should be printed in literal form or some other
+ form, based on it's ASCII value and setting of sevenbit_strings.
+ * {c-exp.y, m2-exp.y} (emit_char): Use new PRINT_LITERAL_FORM
+ macro, change indentation style.
+ * ch-exp.y (chill_printchar): Use new PRINT_LITERAL_FORM macro.
+ * ch-exp.y (chill_printstr): First cut at real function instead
+ of error stub.
+
+Sun Nov 22 16:21:41 1992 david d `zoo' zuhn (zoo at cirdan.cygnus.com)
+
+ * nindy-share/stop.h: fixed bogus comment-end in copyright message
+
+ * i960-pinsn.c: fixed two calls of fputs_filtered that had 3 arguments
+
+Fri Nov 20 21:35:57 1992 Fred Fish (fnf@cygnus.com)
+
+ * defs.h (sevenbit_strings): Add declaration.
+ * defs.h (printchar): Replace with gdb_printchar.
+ * language.h (language_defn): Add new function pointers
+ la_printchar and la_printstr, to do language dependent
+ printing of characters and strings.
+ * language.h (local_printchar, local_printstr): New macros
+ to call language dependent functions pointed to by la_printchar
+ and la_printstr respectively.
+ * c-exp.y (emit_char, c_printchar, c_printstr): New language
+ dependent functions for printing characters and strings.
+ * c-exp.y (c_language_defn, cplus_language_defn): Add
+ c_printchar and c_printstr.
+ * command.c (do_setshow_command): Rename printchar use to
+ gdb_printchar.
+ * expprint.c (print_subexp): Replace C style string output
+ with call to local_printstr.
+ * language.c (unk_lang_printchar, unk_lang_printstr):
+ New stubs, currently errors.
+ * language.c (unknown_language_defn, auto_language_defn,
+ local_language_defn): Add unk_lang_printchar and
+ unk_lang_printstr.
+ * m2-exp.y (emit_char, m2_printchar, m2_printstr): New
+ language dependent functions to print characters and strings.
+ * m2-exp.y (m2_language_defn): Add m2_printchar and m2_printstr.
+ * utils.c (printchar): Renamed to gdb_printchar.
+ * valprint.c (print_string): Remove prototype, function moved
+ to c-exp.y, where it becomes c_printstr.
+ * valprint.c (print_max): Made global for reference from the
+ language dependent printing routines in *-exp.y.
+ * valprint.c (repeat_count_threshold): New variable with function
+ of old REPEAT_COUNT_THREHOLD define, but now settable by user.
+ Change all references to old macro to references to new variable.
+ * valprint.c (value_print, val_print): Replace calls to
+ print_string with calls to local_printstr.
+ * valprint.c (val_print): Replace C style character printing
+ with call to local_printchar.
+ * valprint.c (val_print): Add case for TYPE_CODE_CHAR.
+ * valprint.c (_initialize_valprint): Add add_show_from_set
+ call for setting up repeat_count_threshold as print variable.
+ * ch-exp.y (decode_integer_value): New function.
+ * ch-exp.y (decode_integer_literal): Use decode_integer_value.
+ * ch-exp.y (chill_printchar, chill_printstr): New language
+ dependent functions for printing characters and strings.
+ * ch-exp.y (chill_language_defn): Add chill_printchar and
+ chill_printstr.
+
+Thu Nov 19 21:22:21 1992 John Gilmore (gnu@cygnus.com)
+
+ * main.c (main): Print GDB version number in gdb -help; doc pid arg.
+ Suggested by Marty Leisner, <leisner@eso.mc.xerox.com>.
+ (print_gdb_version): New arg is stdout or stderr. Callers changed.
+
+Wed Nov 18 15:05:45 1992 Ian Lance Taylor (ian@cygnus.com)
+
+ * remote-vx.c (vx_kill): just warn if we can't contact the board,
+ and assume the process has been killed.
+
+Wed Nov 18 14:39:57 1992 Stu Grossman (grossman at cygnus.com)
+
+ * remote-udi.c (udi_open): Reset vars so that user can re-run
+ programs without leaving GDB.
+ * (many routines): Slightly improve error handling.
+ * (download): Zero out BSS by longs instead of bytes to avoid
+ timeouts in real hardware.
+ * 29k-share/udi/udip2soc.c (UDIDisconnect, UDIKill): Indicate
+ that connection is no longer in use after shutdown() of socket.
+ This keeps GDB from dying of a SIGPIPE when you issue multiple
+ `target udi' commands.
+
+Wed Nov 18 14:27:47 1992 Fred Fish (fnf@cygnus.com)
+
+ * language.h (language_format_info): New structure to bundle
+ local formatting information.
+ * language.h (language_defn): Replace individual format info
+ with language_format_info structs.
+ * language.h (local_*_format, local_*_format_prefix,
+ local_*_format_specifier, local_*_format_suffix): New macros
+ for binary/octal/decimal/hex formats to access info elements.
+ * c-exp.y (c_language_defn): Update for new format handling.
+ * m2-exp.y (m2_language_defn): Update for new format handling.
+ * dbxread.c (language.h): Include for partial-stab.h use.
+ * mipsread.c (expression.h, language.h): Include for
+ partial-stab.h use.
+ * defs.h (local_hex_format, local_hex_format_custom,
+ local_hex_string, local_hex_string_custom): Move to language.h.
+ * language.c (local_hex_format_custom, local_hex_string,
+ local_hex_string_custom, local_octal_format_custom): Use new
+ format handling.
+ * language.c (unknown_language_defn, auto_language_defn,
+ local_language_defn): Update for new format handling.
+ * printcmd.c (print_scalar_formatted): Use new macros
+ to access decimal and binary format info for printing.
+ * c-exp.y (chill_language_defn): Update for new format handling.
+ * ch-exp.y (CHARACTER_LITERAL): Add support to yylex.
+ * ch-exp.y (decode_integer_literal): Add function
+ * ch-exp.y (match_integer_literal): Use decode_integer_literal.
+ * ch-exp.y (builtin_type_chill_char): Add definition.
+ * gdbtypes.h (builtin_type_chill_char): Add declaration.
+
+Tue Nov 17 11:17:06 1992 Ian Lance Taylor (ian@cygnus.com)
+
+ * tm-rs6000.h (BELIEVE_PCC_PROMOTION): Define, since AIX cc gets
+ it right.
+ (aix_framedata): added nosavedpc field.
+ (SAVED_PC_AFTER_CALL): Don't try to optimize; just call
+ read_register.
+ (FRAMELESS_FUNCTION_INVOCATION): Pass second argument of 0.
+ (FRAME_SAVED_PC): If PC not saved, use SAVED_PC_AFTER_CALL.
+ * rs6000-tdep.c (skip_prologue): Handle gcc generated stfd
+ instructions as function_frame_info does. Expand special case of
+ st r31,-4(r1) to be st r31,NUM(r1), since gcc can generate offsets
+ other than -4.
+ (pop_frame): Add 4 rather than sizeof (int) to avoid host
+ dependence.
+ (function_frame_info): Set frameless if the function has no frame,
+ and set nosavedpc if the PC was not saved. Handle gcc generated
+ stfd 31,-4(31); st 31, -12(31) correctly.
+ (frameless_function_invocation): New second argument pcsaved; if 0
+ return whether the function has a frame, if 1 return whether the
+ function saved PC.
+ (frame_initial_stack_address): Correct typo: cache registers for
+ callee_fi, not for fi, (avoids reading garbage memory locations).
+
+Mon Nov 16 15:58:07 1992 Stu Grossman (grossman at cygnus.com)
+
+ * infrun.c (wait_for_inferior (just before step_over_function
+ label)): Change test for stepping into subroutine to check for the
+ presence of line number info. This makes stuff compiled with -g1
+ cause GDB to not lose control when stepping.
+
+ * symtab.c (find_pc_line): Improve code per gnu's suggestions.
+ Improve comments as well.
+
+Sun Nov 15 09:22:09 1992 Fred Fish (fnf@cygnus.com)
+
+ * Makefile.in (VERSION): Bump to 4.7.2
+ * symtab.c (find_pc_symtab): Fix return of random value
+ to caller.
+ * Makefile.in (c-exp.tab.c, m2-exp.tab.c): Add dependency on
+ Makefile since it contains sed patterns used in generation.
+ Add sed pattern to also delete #include of any malloc.h.
+ * c-exp.y, expr.c, expression.h, language.c, m2-exp.y,
+ parser-defs.h, valarith.c, valops.c, value.h: Remap macros and
+ function names to conform to K&R terminology with respect to
+ logical and bitwise operators:
+ UNOP_ZEROP => UNOP_LOGICAL_NOT
+ UNOP_LOGNOT => UNOP_COMPLEMENT
+ BINOP_LOGAND => BINOP_BITWISE_AND
+ BINOP_LOGXOR => BINOP_BITWISE_XOR
+ BINOP_LOGIOR => BINOP_BITWISE_IOR
+ BINOP_AND => BINOP_LOGICAL_AND
+ BINOP_OR => BINOP_LOGICAL_OR
+ PREC_OR => PREC_LOGICAL_OR
+ PREC_AND => PREC_LOGICAL_AND
+ PREC_LOGIOR => PREC_BITWISE_IOR
+ PREC_LOGXOR => PREC_BITWISE_XOR
+ PREC_LOGAND => PREC_BITWISE_AND
+ value_zerop() => value_logical_not()
+ value_lognot() => value_complement()
+ * c-exp.y (c_op_print_tab): Add explicit empty terminator.
+ * m2-exp.y (m2_op_print_tab): Add explicit empty terminator.
+ * i387-tdep.c (sys/dir.h): Remove, appears to be unnecessary
+ and is nonexistant in some SVR4 based systems.
+ * language.c (DEFAULT_ALLOCSIZE): Change from 3 => 4.
+ * m2-exp.y (number_sign, modblock): Make static, #ifdef out
+ unused modblock.
+ * m2-exp.y (ANDAND): Rename to LOGICAL_AND.
+ * source.c (source_info): Fix minor nits, print "1 line" rather
+ than "1 lines", and "language is <lang>".
+ * valarith.c (value_binop): Handle TYPE_CODE_BOOL as well
+ as TYPE_CODE_INT and TYPE_CODE_FLOAT.
+ * valprint.c (val_print): Print TYPE_CODE_BOOL type values as
+ "TRUE" or "FALSE".
+ * values.c (value_from_longest): Handle TYPE_CODE_BOOL.
+ * ch-exp.y: New expression parser, for GNU-Chill.
+ * defs.h (enum language): Add language_chill.
+ * dwarfread.c (set_cu_language): Add LANG_CHILL case and make
+ LANG_MODULA2 a recognized language.
+ * gdbtypes.h (enum_typecode): Note TYPE_CODE_BOOL used for
+ Chill as well as Modula-2.
+ * gdbtypes.y (builtin_type_chill_bool, builtin_type_chill_long,
+ builtin_type_chill_ulong, builtin_type_chill_real): Add.
+ * language.c (set_language_command): Add chill.
+ * language.c (binop_result_type, integral_type, character_type,
+ boolean_type, structured_type, value_true, binop_type_check):
+ Add language_chill cases.
+ * language.h (_LANG_chill): Define.
+ * symfile.c (deduce_language_from_filename): Recognize the
+ filename extensions ".chill", ".c186", and ".c286" for Chill.
+ * valprint.c (typedef_print): Add case for language_chill.
+ * Makefile.in (SFILES_MAINDIR): Add ch-exp.y.
+ * Makefile.in (YYFILES): Add ch-exp.tab.c.
+ * Makefile.in (YYOBJ): Add ch-exp.tab.o.
+ * Makefile.in (saber_gdb): Add unload of ch-exp.y and load
+ of ch-exp.tab.c.
+ * Makefile.in (distclean): Add target ch-exp.tab.c.
+ * Makefile.in (realclean): Add rm of ch-exp.tab.c.
+ * Makefile.in (ch-exp.tab.o, ch-exp.tab.c): New targets.
+ * eval.c (evaluate_subexp): Add OP_BOOL case.
+ * expprint.c (print_subexp): Add OP_BOOL case.
+
+Fri Nov 13 20:36:28 1992 John Gilmore (gnu@cygnus.com)
+
+ * infcmd.c (set_environment_command): Avoid skipping first
+ char of env value if an '=' appears in it. Bug report and fix
+ by Mark Jungerman, <maj@lucid.com>.
+
+Fri Nov 13 20:24:10 1992 Stu Grossman (grossman at cygnus.com)
+
+ * infcmd.c (step_over_calls): Improve comments.
+ * symtab.c (find_pc_psymtab): Clean up a bit.
+ * (find_pc_symtab): Fix comments, clean up code.
+ * (find_pc_line): General cleanups, efficiency improvements.
+ Also, don't return garbage when some line info exists, but there
+ was no good match.
+
+Thu Nov 5 23:04:38 1992 Rob Ryan (rr2b@andrew.cmu.edu)
+
+ * xcoffexec.c (vmap_symtab): fixed a bug where if a object has no
+ member, and the stat pointer passed to vmap_symtab was NULL, the
+ wrong vmap entries would be modified. Fixes behavior where
+ attempting to load symbols for a module with no member would mess
+ up already read in symbols.
+
+Wed Nov 11 17:09:17 1992 Stu Grossman (grossman at cygnus.com)
+
+ * Makefile.in: Remove dependancies for 29k-share/dfe/yank.o and
+ 29k-share/dfe/mini2udi.o.
+ * config/a29k-udi.mt: Remove yank.o and mini2udi.o.
+ * alldeps.mak, depend: Update to deal with removal of
+ aforementioned files.
+ * remote-udi.c: Major cleanups. Clean up udi_open and drop
+ requirement for useless 'program' argument. Clean up
+ udi_create_inferior, and udi_load to call common download()
+ routine. Create download routine to load remote hosts directly
+ (with the help of BFD) so that we don't need yank.c and
+ mini2udi.c.
+ Fix udi_detach to call UDIDisconnect with
+ the right arguments. Clean up udi_resume, don't assign tip_error
+ twice. Clean up udi_wait, straighten out status codes. Make
+ udi_kill really work.
+
+Fri Nov 6 10:26:01 1992 Steve Chamberlain (sac@thepub.cygnus.com)
+
+ * c-exp.y: separated host/target idea of integer type size,
+ removed redundant parse rules. (YYSTYPE): added typed_val, removed
+ UINT and CHAR rules. (parse_number): work out the targetwise type
+ of a number based upon it's size and qualifiers. (yylex): chars
+ are now treated the same way as ints.
+
+ * source.c (indentify_source_line): don't core dump if wanted
+ line is larger than number of lines in source. (can happen when
+ coff gets confused about #included source).
+
+Fri Nov 6 03:00:39 1992 John Gilmore (gnu@cygnus.com)
+
+ Fix problems noticed by Allan Steel, <allan@maths.su.oz.au>,
+ when debugging a program with 100 shared libraries.
+
+ * solib.c (solib_map_sections): Always close the BFD we open.
+ Free all malloc'd storage we allocate, too, including error cases.
+ (struct so_list): Remove unused so_bfd member.
+ (clear_solib): Don't bother closing so_bfd.
+
+ * symfile.c (symfile_bfd_open): Mark newly opened BFD as
+ cacheable. `So many symbol files, so little file descriptors.'
+
+Fri Nov 6 00:14:38 1992 John Gilmore (gnu@cygnus.com)
+
+ * m68k-stub.c: Remove ansidecl.h and the few uses of it.
+ Stubs should stand alone as much as possible.
+
+ * source.c (show_directories): Avoid printf_filtered length prob
+ pointed out by Jonathan Stone.
+
+ * i960-pinsn.c (MEM_MAX, MEM_SIZ): Set upper limit properly to
+ avoid accesses beyond end of table. Fix by Lee W. Cooprider,
+ <Lee_Cooprider@vos.stratus.com>.
+
+Thu Nov 5 17:33:08 1992 Fred Fish (fnf@cygnus.com)
+
+ * {ser-bsd.c, ser-termios.c} (serial_close): Pass address of
+ struct, not struct itself.
+ * serial.h (serial_restore): Fix prototype, takes pointer not
+ struct.
+
+Thu Nov 5 17:12:42 1992 Stu Grossman (grossman at cygnus.com)
+
+ * Makefile.in (depend): Add nm.h to the list of things to fixup.
+ * depend: Redo, to fixup nm.h problems with *-tab.c files.
+
+Thu Nov 5 00:19:51 1992 John Gilmore (gnu@cygnus.com)
+
+ * i386-stub.c: Remove ansidecl.h and the few uses of it.
+ Stubs should stand alone as much as possible.
+
+ * README: Add remote-es1800.c and remote-st2000.c to table.
+ * go32-nat.c: Remove, there is no native go32 support.
+ * go32-xdep.c: Remove unused fork, fvork, wait, execlp, kill_inferior.
+
+Wed Nov 4 15:27:31 1992 Stu Grossman (grossman at cygnus.com)
+
+ * inflow.c (pass_signal, set_sigint_trap, clear_sigint_trap): Add
+ new routines to deal with sending SIGINTs to attached processes
+ when the user interrupts the controlling GDB.
+ * inftarg.c (child_wait), procfs.c (procfs_wait): Add calls to
+ the aforementioned routines when waiting for the attached process.
+
+ * elfread.c, mipsread.c: Include <string.h>.
+ * i386-stub.c: Include "ansidecl.h" to deal with prototypes.
+ * serial.h: Add prototype for serial_restore().
+
+Wed Nov 4 11:13:25 1992 Ian Lance Taylor (ian@cygnus.com)
+
+ * minsyms.c (lookup_minimal_symbol_by_pc): subtract 1, not 2, from
+ minimal_symbol_count, because the NULL symbol is not included in
+ the count. This prevented this function from finding the last
+ symbol in the table.
+
+Tue Nov 3 11:29:17 1992 Ian Lance Taylor (ian@cygnus.com)
+
+ * dbxread.c (process_one_symbol): if not defined
+ (BLOCK_ADDRESS_FUNCTION_RELATIVE), set function_start_offset at
+ the start of the function, not just after N_FUN.
+
+Fri Oct 30 16:33:02 1992 Fred Fish (fnf@cygnus.com)
+
+ * Makefile.in (c-exp.tab.c, m2-exp.tab.c): Add sed patterns to
+ remap all malloc's to xmalloc's and all realloc's to xrealloc's.
+ * c-exp.y, m2-exp.y: Add comment about how malloc/realloc are
+ remapped to xmalloc/xrealloc, use only malloc/realloc in grammer
+ file. Remove preprocessor defines that previously did remapping.
+
+Fri Oct 30 00:58:18 1992 John Gilmore (gnu@cygnus.com)
+
+ * infcmd.c (run_command): Avoid long calls to printf_filtered.
+ Bug fix courtesy of Alexander Klaiber.
+
+Tue Oct 27 17:08:45 1992 K. Richard Pixley (rich@cygnus.com)
+
+ hp300 native support (hp300hpux untested).
+
+ * hp300ux-xdep.c: removed.
+ * xm-hp300bsd.h (REGISTER_U_ADDR): removed.
+ * xm-hp300hpux.h: updated copyright.
+ (ATTACH_DETACH, FETCH_INFERIOR_REGISTERS): removed.
+ * nm-hp300bsd.h, nm-hp300hpux.h, hp300ux-nat.c: new files.
+ * Makefile.in (HFILES): added nm-hp300bsd.h and nm-hp300hpux.h.
+ * config/hp300bsd.mh (XDEPFILES): removed infptrace.o inftarg.o
+ fork-child.o coredep.o corelow.o.
+ (NAT_FILE, NATDEPFILES): new macros.
+ * config/hp300bsd.mt (TDEPFILES): removed exec.o.
+ * config/hp300hpux.mh (XDEPFILES): removed infptrace.o inftarg.o
+ fork-child.o.
+ (NAT_FILE, NATDEPFILES): new macros.
+ * config/hp300hpux.mt (TDEPFILES): removed exec.o.
+
+ Vax ultrix native support.
+
+ * nm-vax.h: new file.
+ * Makefile.in (HFILES): added nm-vax.h.
+ * config/vaxult.mh (XDEPFILES): infptrace.o inftarg.o fork-child.o
+ coredep.o corelow.o removed.
+ (NAT_FILE, NATDEPFILES): new macros.
+ * xm-vax.h: updated copyright.
+ (REGISTER_U_ADDR): removed.
+
+ Apollo native support (untested).
+
+ * Makefile.in (HFILES): added nm-apollo68[bv].h.
+ * a68v-nat.c, nm-apollo68[bv].h: new files.
+ * xm-apollo68[bv].h (FETCH_INFERIOR_REGISTERS): removed.
+ * xm-apollo68b.h (PTRACE_IN_WRONG_PLACE): removed.
+ * a68v-xdep.c: removed.
+ * config/apollo68[bv].mh (XDEPFILES): removed infptrace.o
+ inftarg.o fork-child.o a68v-xdep.o.
+ (NAT_FILE, NATDEPFILES): new macros.
+
+ * defs.h: include nm.h.
+ * coredep.c, infptrace.c, procfs.c, rs6000-nat.c, sparc-nat.c,
+ sparc-tdep.c, : do not include nm.h.
+ * doc/gdbint.texinfo: nm.h now included in defs.h.
+
+Fri Oct 23 04:47:17 1992 Stu Grossman (grossman at cygnus.com)
+
+ * Makefile.in (VERSION): 4.7.1 post release!
+
+ * config/hppahpux.mh (NATDEPFILES): Add hppah-nat.o.
+
+Fri Oct 23 00:48:08 1992 John Gilmore (gnu@cygnus.com)
+
+ * Makefile.in (VERSION): gdb-4.7 release.
+ * README: Update for gdb-4.7.
+
+Thu Oct 22 11:24:18 1992 Stu Grossman (grossman at cygnus.com)
+
+ * sparc-tdep.c: include nm.h (for now) so that we get USE_PROC_FS
+ when necessary.
+
+ * alldeps.mak, depend: Update.
+
+Thu Oct 22 03:14:36 1992 John Gilmore (gnu@cygnus.com)
+
+ * partial-stab.h ('f', 'F'): Don't reference pst->textlow if pst
+ is null.
+ * tm-sun4sol2.h (PROLOGUE_FIRSTLINE_OVERLAP): Remove -- it
+ causes problems in setting breakpoint in the right place in
+ functions with `float' args which are passed as doubles.
+ * xm-vaxbsd.h (MEM_FNS_DECLARED): Avoid erroneous redecl's.
+ * config/rs6000.mh (NATDEPFILES): Add corelow.o.
+
+Thu Oct 22 01:01:24 1992 Stu Grossman (grossman at cygnus.com)
+
+ * Makefile.in (HFILES): Add nm-i386sco.h.
+ * dwarfread.c: include <sys/types.h> for SCO.
+ * infptrace.c: Don't include ptrace.h under SCO.
+ * config/i386sco.mh: Use -D_POSIX_SOURCE instead of -posix for
+ gcc.
+ * config/i386v.mt: Add exec.o to TDEPFILES.
+
+Wed Oct 21 19:08:20 1992 Stu Grossman (grossman at cygnus.com)
+
+ * i386v-nat.c: Remove space from front of #endif.
+ * irix4-nat.c: Remove externs of registers[], include inferior.h
+ instead.
+ * mips-nat.c: Explicitly initialize zerobuf to 0!
+ * mips-tdep.c (init_extra_frame_info): Undo John's last change.
+ Always setup fci->frame, even if it's non-zero. Too many places
+ depend upon this behavior (and I have to get a release out the
+ door)!
+ * mipsread.c (parse_partial_symbols, psymtab_to_symtab_1): Set
+ processing_gcc_compilation if we find the embedded stabs marker.
+ This fixes several bugs with finding the location of short or char
+ function parameters passed on the stack.
+
+Wed Oct 21 17:46:07 1992 K. Richard Pixley (rich@sendai.cygnus.com)
+
+ Native support for sun4sol2.
+
+ * xm-sysv4.h (USE_PROC_FS, ATTACH_DETACH): removed to nm-sysv4.h.
+ * nm-sysv4.h: new file.
+ * Makefile.in (HFILES): added nm-sysv4.h.
+ * config/sun4sol2.mh (XDEPFILES): removed procfs.o fork-child.o.
+ (NAT_FILE, NATDEPFILES): new macros.
+ * config/sun4sol2.mt (TDEPFILES): removed exec.o and solib.o.
+
+Wed Oct 21 03:51:01 1992 John Gilmore (gnu@cygnus.com)
+
+ * coredep.c: Include "nm.h" to get REGISTER_U_ADDR.
+ * doc/gdbint.texinfo: Improve REGISTER_U_ADDR and USE_PROC_FS doc.
+
+ * Makefile.in (VERSION): Tick to 4.6.9.
+
+Tue Oct 20 23:27:56 1992 John Gilmore (gnu@cygnus.com)
+
+ * mipsread.c (UNSAFE_DATA_ADDR): Remove MIPS-host-specific
+ definition, replace with portable one.
+ * remote-nindy.c: Lint.
+ (nindy_wait): Return type is int, result is inferior_pid.
+ * symmisc.c (dump_psymtab): Only print section_offsets if set.
+ (initialize_symmisc): Remove empty function.
+ * tm-spc-noun.h, tm-sun4os4.h, tm-sun4sol2.h (STACK_END_ADDRESS):
+ Remove obsolete, misspelled macro.
+ * doc/gdbint.texinfo: Document obsolete STACK_END_ADDR.
+ (all @node commands): Use new form to avoid nitpicking errors.
+ * doc/gdbint.texinfo: Document host/native/target split.
+
+Wed Oct 21 00:14:34 1992 Stu Grossman (grossman at cygnus.com)
+
+ * mips-nat.c (zerobuf): Get rid of const to avoid gcc warnings.
+
+ * xm-mips.h (offsetof): Don't define this if __STDC__.
+
+Tue Oct 20 21:32:18 1992 K. Richard Pixley (rich@sendai.cygnus.com)
+
+ umax native support (untested).
+
+ * config/umax.mh (XDEPFILES): removed infptrace.o inftarg.o
+ fork-child.o.
+ (NAT_FILE, NATDEPFILES): new macros.
+ * config/umax.mt (TDEPFILES): removed exec.o.
+ * xm-umax.h (U_REGS_OFFSET, ATTACH_DETACH, REGISTER_U_ADDR):
+ removed to nm-umax.h.
+ * nm-umax.h: new file.
+ * Makefile.in (HFILES): added nm-umax.h.
+
+ hppa native support (untested).
+
+ * config/hppahpux.mh, config/hppabsd.mh (XDEPFILES): now empty.
+ (NAT_FILE, NATDEPFILES): new macros.
+ * config/hppabsd.mt (TDEPFILES): removed exec.o and hppab-core.o.
+ * config/hppahpux.mt (TDEPFILES): removed exec.o.
+ * xm-hppa[bh].h (REGISTER_U_ADDR, U_REGS_OFFSET): removed.
+ * nm-hppa[bh].h, hppa[bh]-nat.c: new files.
+ * hppa[bh]-xdep.c: removed.
+ * hppa[bh]h-tdep.c: do not include ptrace.h.
+ * Makefile.in (HFILES): added nm-hppa[bh].h.
+
+ * doc/gdbint.texinfo: add PUSH_DUMMY_FRAME, POP_FRAME.
+
+Tue Oct 20 00:01:46 1992 Stu Grossman (grossman at cygnus.com)
+
+ * mips-nat.c: Straighten out include files. Work around
+ conflicting defs of JB_xxx syms in <setjmp.h> and <machine/pcb.h>
+ for Ultrix-4.2.
+
+Mon Oct 19 15:09:57 1992 Stu Grossman (grossman at cygnus.com)
+
+ * mips-nat.c (fetch_core_registers, register_addr): Copy from
+ coredep.c, but zero out FP_REGNUM & ZERO_REGNUM so that stack
+ backtraces from core files work.
+ * config/decstation.mh, config/irix3.mh: Remove coredep.o.
+ Functions are now defined in mips-nat.c.
+
+ * tm-irix3.h: Put MIPS_EFI_SYMBOL_NAME in here too.
+
+ * remote-hms.c: Disable all uses of serial_nextbaudrate and
+ serial_default_name().
+
+ * remote-hms.c, ser-go32.c, serial.h: Change from
+ serial_timedreadchar() to new serial_readchar().
+
+ * Makefile.in (HFILES): Fixup list of nm-*.h files. Add missing ones.
+
+Mon Oct 19 12:45:23 1992 Per Bothner (bothner@cygnus.com)
+
+ * c-exp.y: Moved handling of 'const' and 'volatile' from
+ <type> to <typebase>. This removes 2 conflicts.
+
+Sun Oct 18 00:36:30 1992 Fred Fish (fnf@cygnus.com)
+
+ * breakpoint.c (breakpoint_re_set_one): Don't delete watchpoints
+ from breakpoint table when reseting breakpoints.
+
+Sat Oct 17 00:59:23 1992 Fred Fish (fnf@cygnus.com)
+
+ Native support cleanup and corefile fixes for i386 SVR4 systems.
+
+ * i386-tdep.c (supply_gregset, fill_gregset, supply_fpregset,
+ fill_fpregset): Moved to i386v4-nat.c
+ * i386v4-nat.c, nm-i386v4.h, : New files.
+ * i386sol2.mh, i386v4.mh, ncr3000.mh (NAT_FILE): Use nm-i386v4.h.
+ * i386sol2.mh, i386v4.mh, ncr3000.mh (NATDEPFILES): Add corelow.o,
+ change i386v-nat.o to i386v4-nat.o.
+
+Fri Oct 16 13:06:08 1992 K. Richard Pixley (rich@sendai.cygnus.com)
+
+ Miscellaneous 386 configs updated.
+
+ * config/i386aout.mt (TDEPFILES): removed exec.o.
+ * config/i386sol2.mh, config/ncr3000.mh, config/i386v4.mh
+ (XDEPFILES): removed procfs.o fork-child.o i386-xdep.o.
+ (NAT_FILE, NATDEPFILES): new macros.
+ * config/i386aout.mt, config/i386sol2.mt, config/ncr3000.mt,
+ config/i386v4.mt (TDEPFILES): removed exec.o.
+ * config/i386v32.mh (XDEPFILES): removed infptrace.o inftarg.o
+ fork-child.o coredep.o corelow.o i386-xdep.o i387-tdep.o.
+ (NAT_FILE, NATDEPFILES): new macros.
+ * config/i386sco.mh (XDEPFILES): removed infptrace.o inftarg.o
+ fork-child.o coredep.o corelow.o i386-xdep.o.
+ (NAT_FILE, NATDEPFILES): new macros.
+
+ Native support cleanup for i386bsd (untested).
+
+ * config/i386bsd.mt (NATDEPFILES): exec.o removed.
+ * config/i386bsd.mh (NATDEPFILES): added exec.o
+ * tm-i386bsd.h (FLOAT_INFO): removed.
+ * nm-i386bsd.h (FLOAT_INFO): added.
+
+ Native support for i386v (untested).
+
+ * config/i386v.mh (XDEPFILES): removed infptrace.o inftarg.o
+ fork-child.o coredep.o corelow.o i386-xdep.o i387-tdep.o.
+ (NAT_FILE, NATDEPFILES): new macros.
+ * config/i386v.mt (TDEPFILES): removed exec.o, added i387-tdep.o.
+ * i386-xdep.c: removed.
+ * Makefile.in (HFILES): added nm-i386v.h
+ * i386v-nat.c, nm-i386v.h: new file.
+ * xm-i386v.h: (REGISTER_U_ADDR, i386_register_u_addr): removed to
+ nm-i386v.h.
+ * tm-i386v.h (FLOAT_INFO): removed.
+
+ Native support for linux (untested).
+
+ * config/linux.mh (XDEPFILES): removed infptrace.o inftarg.o
+ fork-child.o coredep.o corelow.o i387-tdep.o i386-xdep.o.
+ (NAT_FILE, NATDEPFILES): new macros.
+ * config/linux.mt (TDEPFILES): removed exec.o, added i387-tdep.o.
+ * Makefile.in (HFILES): added nm-linux.h.
+ * nm-linux.h: new file.
+ * xm-linux.h: updated copyright. cleaned up formatting.
+ (ATTACH_DETACH, U_REGS_OFFSET): removed to nm-linux.h.
+
+ Native support for sun386 (untested).
+
+ * config/sun386.mh (XDEPFILES): removed infptrace.o inftarg.o
+ fork-child.o sun386-xdep.o.
+ (NAT_FILE, NATDEPFILES): new macros.
+ * config/sun386.mt (TDEPFILES): removed exec.o.
+ * Makefile.in (HFILES): added nm-sun386.h.
+ * sun386-nat.c, nm-sun386.h: new file.
+ * sun386-xdep.c: removed.
+ * xm-sun386.h: updated comment and copyright.
+ (ATTACH_DETACH, FETCH_INFERIOR_REGISTERS): removed to
+ nm-sun386.h.
+
+ Native support for i386mach (untested).
+
+ * config/i386mach.mh (XDEPFILES): removed infptrace.o inftarg.o
+ fork-child.o mach386-xdep.o.
+ (NAT_FILE, NATDEPFILES): new macros.
+ * Makefile.in (HFILES): added nm-i386mach.h.
+ * nm-i386mach.h, i386mach-nat.c: new files.
+ * mach386-xdep.c: removed.
+ * xm-i386mach.h: updated copyright.
+ (ATTACH_DETACH, FETCH_INFERIOR_REGISTERS): removed to
+ nm-i386mach.h.
+
+ Native separation for go32 (untested).
+
+ * config/go32.mh (NAT_FILE, NATDEPFILES): new macros.
+ * go32-nat.c: new file.
+ * go32-xdep.c (call_ptrace, child_resume,
+ fetch_inferior_registers, store_inferior_registers,
+ child_xfer_memory, fetch_core_registers): removed to go32-nat.c.
+
+ Native support for m88k (untested).
+
+ * Makefile.in (HFILES): added nm-m88k.h
+ * xm-delta88.h, xm-m88k.h (REGISTER_U_ADDR,
+ FETCH_INFERIOR_REGISTERS): removed.
+ * config/m88k.mh, config/delta88.mh (XDEPFILES): infptrace.o
+ inftarg.o fork-child.o m88k-xdep.o removed to NATDEPFILES.
+ (NAT_FILE, NATDEPFILES): new macros.
+ * config/m88k.mt, config/delta88.mt (TDEPFILES): removed exec.o.
+ * m88k-nat.c, nm-m88k.h, nm-delta88.h: new files.o.
+ * m88k-xdep.c: removed.
+
+Fri Oct 16 04:16:30 1992 John Gilmore (gnu@cygnus.com)
+
+ * i386b-nat.c: Comment changes.
+ * nm-i386bsd.h, xm-i386bsd.h: Split native dependent pieces out
+ into new nm-file.
+ * config/i386bsd.mh (NAT_FILE): Point to new nm-file.
+
+Fri Oct 16 03:34:01 1992 John Gilmore (gnu@cygnus.com)
+
+ Avoid longjmp()-catching compilation errors in cross-ports.
+
+ * doc/gdbint.texinfo: Update GET_LONGJMP_TARGET, L_SET doc.
+ * irix4-nat.c, mips-nat.c (JB_ELEMENT_SIZE, get_longjmp_target):
+ Move from mips-tdep.c and tm-{irix3,mips}.h.
+ * mips-nat.c: Remove a bunch of code that was ifdef'd out of
+ native MIPS ports.
+ * nm-irix3.h, nm-mips.h (GET_LONGJMP_TARGET): Move from tm-irix3.h
+ and tm-mips.h.
+
+ * ultra3-nat.c (register_addr): Move from ultra3-xdep.c.
+ (fetch_core_registers): Fix bfd_seek arguments.
+
+Fri Oct 16 03:02:28 1992 John Gilmore (gnu@cygnus.com)
+
+ Make core files work again (add back the `core' target).
+
+ * config/decstation.mh, news.mh, sun2os3.mh, sun2os4.mh
+ (NATDEPFILES): Add corelow.o.
+ * config/delta88.mt, m88k.mt (TDEPFILES): Remove coredep.o, it's
+ native dependent.
+
+ * config/3b1.mh, bigmips.mh, hp300bsd.mh, hppabsd.mh, hppahpux.mh,
+ i386sco.mh, i386v.mh, i386v32.mh, irix3.mh, isi.mh, linux.mh,
+ littlemips.mh, merlin.mh, news1000.mh, pn.mh, rtbsd.mh, tahoe.mh,
+ vaxbsd.mh, vaxult.mh (XDEPFILES): Add corelow.o whenever coredep.o
+ appears. FIXME, these should be moved to NATDEPFILES for native
+ use only.
+
+Thu Oct 15 21:53:53 1992 K. Richard Pixley (rich@sendai.cygnus.com)
+
+ Ultra3 host/target/native split. (untested).
+
+ * ultra3-xdep.c: updated copyright. Do not include sys/ptrace.h.
+ (fetch_register, fetch_inferior_registers,
+ store_inferior_registers, fetch_core_registers): removed to
+ ultra3-nat.c.
+ * xm-ultra3.h (FETCH_INFERIOR_REGISTERS, U_REGS_OFFSET): removed
+ to nm-ultra3.h.
+ * Makefile.in (HFILES): added nm-ultra3.h.
+ * nm-ultra3.h, ultra3-nat.c: new files for native support.
+ * config/ultra3.mh (XDEPFILES): removed infptrace.o inftarg.o
+ fork-child.o.
+ (NAT_FILE, NATDEPFILES): new macros for native support.
+ * config/ultra3.mt (TDEPFILES): exec.o removed.
+
+ * xm-vaxult.h: add MEM_FNS_DECLARED.
+
+Thu Oct 15 02:59:30 1992 John Gilmore (gnu@cygnus.com)
+
+ * Makefile.in (VERSION): Roll to 4.6.8.
+ (OBS): Put version.o first, so Makefile rebuild happens early.
+
+ * command.h: Publicize prototype for not_just_help_class_command.
+ * command.c: Remove proto.
+ * maint.c: Mark "mt" as an abbrev, to avoid duplicated help
+ output. Move "maint info" from class info to class maintenance,
+ and improve text.
+ * infrun.c: Move "stop" to class_obscure, and give it a
+ function so it will not be seen as a global help topic. FIXME,
+ it should be possible to set these attributes independently.
+
+ * core.c (core_command): Make nicer error message for no core support.
+
+ Lint around file_ptr's (bfd's off_t's) and bfd_seek.
+
+ * dbxread.c (read_dbx_symtab): Use L_SET as bfd_seek arg.
+ (elfstab_build_psymtabs): staboffset and stabstroffset args are
+ file_ptr's.
+ * dwarfread.c (struct dwfinfo): Convert dbfoff, lnfoff to file_ptr.
+ (scan_compilation_units): Punt unused filename arg. dbfoff,
+ lnoffset, and curlnoffset are file_ptr's now.
+ (dwarf_build_psymtabs): Drop desc and filename args; use
+ objfile. dbfoff and lnoffset are file_ptr's now.
+ (read_ofile_symtab): foffset is now file_ptr. Use L_SET in bfd_seek.
+ * elfread.c (struct elfinfo): dboffset and lnoffset are file_ptr's.
+ (elf_symfile_read): Skip desc and filename args to
+ dwarf_build_psymtabs. Pass file_ptr's to elfstab_build_psymtabs.
+ * gdb-stabs.h: Use file_ptr rather than off_t.
+ * mipsread.c (fixup_symtab): f_ptr is a file_ptr. Re-enable
+ compile-time debug check that someone turned off as "unused".
+ (read_the_mips_symtab): st_filptr is a file_ptr. Fix bfd_seek call.
+ * symfile.h: Update dwarf_build_psymtabs and
+ elfstab_build_psymtabs prototypes.
+ * xcoffread.c (init_stringtab, init_lineno, xcoff_symfile_read):
+ Use file_ptr offsets. bfd_seeks use L_SET.
+
+Thu Oct 15 01:27:32 1992 Stu Grossman (grossman at cygnus.com)
+
+ * mips-tdep.c, mipsread.c, tm-mips.h: Get rid of ".gdbinfo."
+ symbol. #define MIPS_EFI_SYMBOL_NAME instead. Use different
+ value so that demangler won't be invoked. This greatly speeds up
+ stepping.
+ * mips-tdep.c (mips_pop_frame): Rewrite handling of
+ linked_proc_info so that it properly deallocates the appropriate
+ item after it is done with it instead of before.
+ * Don't pass bogus frame pointer to create_new_frame(). Just
+ leave it as zero so that lower level code will figure out the
+ correct value.
+
+Wed Oct 14 18:56:28 1992 K. Richard Pixley (rich@sendai.cygnus.com)
+
+ Sony News native support.
+
+ * Makefile.in (HFILES): added nm-news.h.
+ * nm-news.h: new file.
+ * config/news.mh (XDEPFILES): removed infptrace.o inftarg.o
+ fork-child.o coredep.o to NATDEPFILES.
+ (NAT_FILE, NATDEPFILES): new macros for native support.
+ * config/news.mt (TDEPFILES): removed exec.o.
+
+ * remote-vx.c: remove redundant include of sys/time.h.
+
+ * infrun.c: include ctype.h. Otherwise some machines result in
+ undefined for isdigit.
+
+Tue Oct 13 01:27:14 1992 John Gilmore (gnu@cygnus.com)
+
+ * configure.in: Convert m68k entries to m68* entries to handle
+ all the various m68xxx hosts and targets.
+ * config/news1000.mt: No longer needed, same as news.mt.
+
+Fri Oct 9 18:54:37 1992 K. Richard Pixley (rich@sendai.cygnus.com)
+
+ * config/sun3os[34].mh (NATDEPFILES): remove duplicate inftarg.o.
+
+Fri Oct 9 14:20:08 1992 Stu Grossman (grossman at cygnus.com)
+
+ * Makefile.in (HFILES): Add all nm-irix3.h, nm-irix4.h,
+ nm-sun2.h, nm-mips.h.
+
+ * config/irix3.mh (NATDEPFILES): nat-mips.o => mips-nat.o.
+
+ * Makefile.in (alldeps.mak): Add = sign after NATDEPFILES.
+
+ * config/bigmips.mh config/littlemips.mh: Remove mips-xdep.o.
+
+Fri Oct 9 08:41:11 1992 Ian Lance Taylor (ian@cygnus.com)
+
+ * xm-hppah.h: if __STDC__ is not defined, define
+ HPPA_COMPILER_BUG.
+ symtab.c (decode_line_1): avoid a bug in the HP9000/700 native
+ compiler; see the comment in the file.
+
+Fri Oct 9 04:43:43 1992 John Gilmore (gnu@cygnus.com)
+
+ First cut at support for all BSD variants on 386.
+
+ * tm-i386bsd.h, xm-i386bsd.h: New config files.
+ * i386b-nat.c: New native support file.
+ * configure.in: Add host and target for i[34]86-*-bsd*.
+ * config/i386bsd.mh, config/i386bsd.mt: New config files.
+
+Fri Oct 9 00:31:33 1992 K. Richard Pixley (rich@sendai.cygnus.com)
+
+ Sun2 native support (untested).
+
+ * xm-sun2.h (ATTACH_DETACH, FETCH_INFERIOR_REGISTERS,
+ REGISTER_U_ADDR): removed to nm-sun2.h.
+ * nm-sun2.h: new file.
+ * config/sun2os[34].mh (XDEPFILES): infptrace.o inftarg.o
+ fork-child.o sun3-xdep.o removed.
+ (NAT_FILE, NATDEPFILES): new macros.
+
+ Mips native support. Decstation and iris4 have been tested.
+ Iris3 has not.
+
+ * mips-tdep.c (supply_gregset, fill_gregset, supply_fpregset,
+ fill_fpregset): removed to irix4-nat.c
+ * mips-xdep.c: removed.
+ * irix4-nat.c, mips-nat.c, nm-irix3.h, nm-irix4.h, nm-mips.h: new
+ files.
+ * procfs.c: include nm.h.
+ * xm-irix3.h (U_REGS_OFFSET, FETCH_INFERIOR_REGISTERS): removed.
+ * xm-irix4.h: bump copyright.
+ (U_REGS_OFFSET, FETCH_INFERIOR_REGISTERS, USE_PROC_FS,
+ PROC_NAME_FMT): removed.
+ * xm-mips.h (FETCH_INFERIOR_REGISTERS): removed.
+ * config/irix4.mh (XDEPFILES): removed procfs.o fork-child.o.
+ (NAT_FILE, NATDEPFILES): new macros for native support.
+ (CC): supply default compiler switches.
+ * config/irix3.mh (XDEPFILES): removed infptrace.o inftarg.o
+ fork-child.o coredep.o.
+ (NAT_FILE, NATDEPFILES): new macros for native support. Note that
+ irix3 is untested.
+ * config/decstation.mh (XDEPFILES): removed infptrace.o inftarg.o
+ fork-child.o mips-xdep.o coredep.o.
+ (NAT_FILE, NATDEPFILES): new macros for native support.
+
+Thu Oct 8 23:50:51 1992 K. Richard Pixley (rich@sendai.cygnus.com)
+
+ * config/rs6000.mh (XDEPFILES): removed fork-child.o.
+ (NATDEPFILES): added fork-child.o
+ * config/sun3os3.mh (XDEPFILES): removed fork-child.o.
+ (NATDEPFILES): added fork-child.o
+ * config/sun3os4.mh (XDEPFILES): removed fork-child.o.
+ (NATDEPFILES): added fork-child.o
+
+Thu Oct 8 23:19:25 1992 John Gilmore (gnu@cygnus.com)
+
+ * infcmd.c (path_info): Avoid 250-char limit on printf_filtered,
+ by using puts_filtered instead.
+
+Fri Oct 9 00:28:25 1992 Ken Raeburn (raeburn@cambridge.cygnus.com)
+
+ * remote-nindy.c (nindy_load): Replacement version from Steve
+ Chamberlain, doesn't require forking to run "strip" or "sx".
+
+Thu Oct 8 18:27:35 1992 Stu Grossman (grossman at cygnus.com)
+
+ * Makefile.in (HFILES): Add nm-*.h files.
+
+Thu Oct 8 16:27:45 1992 K. Richard Pixley (rich@sendai.cygnus.com)
+
+ * config/sun4os4.mh (XDEPFILES): fork-child.o removed.
+ (NATDEPFILES): added fork-child.o.
+
+ * doc/gdbint.texinfo: document a few more macros, create new
+ section for native macros.
+
+Thu Oct 8 13:52:46 1992 Stu Grossman (grossman at cygnus.com)
+
+ * Makefile.in alldeps.mak depend: Rip out 29k/udi pending
+ resolution of copyright issues.
+
+Wed Oct 7 20:08:53 1992 Stu Grossman (grossman at cygnus.com)
+
+ * Makefile.in (setup-to-dist): Remove -norecursion so that doc
+ subdir gets configured.
+
+Wed Oct 7 12:24:01 1992 Ken Raeburn (raeburn@cygnus.com)
+
+ * Makefile.in (nindy.o): Define "STRIP" as pathname of strip
+ program.
+ * nindy-share/nindy.c (coffstrip): Use that pathname, instead of
+ searching for a "bfd_strip" program. Also, fixed up arguments
+ passed to that program.
+
+ * tm-nindy960.h (ADDITIONAL_OPTIONS): Use "-ser" rather than "-r",
+ which is now used for something else. Rewrite description of
+ associated parameters to match how gdb does it now.
+ (ADDITIONAL_OPTION_HELP): Fix message accordingly.
+
+ * m68k-pinsn.c (print_insn_arg): Handle new "`" operand type.
+
+Tue Oct 6 14:47:11 1992 K. Richard Pixley (rich@sendai.cygnus.com)
+
+ NOTICE_SIGNAL_HANDLING_CHANGE macro added to the target vector as
+ to_notice_signals.
+
+ * inferior.h (proc_signal_handling_change): prototype removed.
+ * infrun.c (NOTICE_SIGNAL_HANDLING_CHANGE): default removed.
+ (handle_command): now calls target_notice_signals.
+ * procfs.c (proc_signal_handling_change): renamed to
+ procfs_notice_signals. Now static. Add prototype. All callers
+ changed.
+ * target.h (struct target_ops): new field, to_notice_signals.
+ (target_notice_signals): new macro to cover new field.
+ * target.c (cleanup_target): default to_notice_signals to ignore.
+ * corelow.c (core_ops),
+ exec.c (exec_ops),
+ inftarg.c (child_ops),
+ procfs.c (procfs_ops),
+ remote-adapt.c (adapt-ops),
+ remote-eb.c (eb_ops),
+ remote-es1800.c (es1800_ops, es1800_child_ops),
+ remote-hms.c (hms_ops),
+ remote-mm.c (mm_ops),
+ remote-nindy.c (nindy_ops),
+ remote-st2000.c (st2000_ops),
+ remote-udi.c (udi_ops),
+ remote-vx.c (vx_ops, vx_run_ops),
+ remote.c (remote_ops),
+ target.c (dummy_target),
+ xcoffexec.c (exec_ops): added static initializer for
+ to_notice_signals.
+ * xm-irix4.h, xm-sysv4.h (NOTICE_SIGNAL_HANDLING_CHANGE): removed.
+
+Tue Oct 6 12:13:08 1992 John Gilmore (gnu@cygnus.com)
+
+ * main.c (define_command): Add forgotten initializer.
+
+Tue Oct 6 02:23:17 1992 John Gilmore (gnu@cygnus.com)
+
+ * language.c, language.h: Move saved_language out to global
+ expected_language. Set expected_language when user expectation
+ changes.
+ * language.c (language_info): Don't print type/range checking gub.
+ * main.c (main): Set expected language.
+ (execute_command): Check against expected language.
+ * symfile.c (set_initial_language): Set expected language.
+
+ * configure.in, config/i386sol2.{mh,mt}: Preliminary Solaris-x86 conf.
+
+Fri Sep 4 00:34:30 1992 Per Bothner (bothner@rtl.cygnus.com)
+
+ A bunch of changes mostly to improve debugging of C++ programs.
+ Specifically, the calling of inferiors methods is improved.
+
+ * value.h: New macros METHOD_PTR_IS_VIRTUAL,
+ METHOD_PTR_FROM_VOFFSET, METHOD_PTR_TO_VOFFSET to partially
+ hide the implementation details of pointer-to-method objects.
+ How to tell if the pointer points to a virtual method is
+ still very dependent on the particular compiler, but this
+ should make it easier to find the places to change.
+ * eval.c (evaluate_subexp [case OP_FUNCALL]), valprint.c
+ (val_print [case TYPE_CODE_PTR]): Use the new METHOD_PTR_*
+ macros, instead of a hard-wired-in code that incorrectly
+ assumed a no-longerused representation of pointer-to-method
+ values. And otherwise fix the relevant bit-rotted code.
+
+ * valprint.c (type_print_base [case TYPE_CODE_STRUCT]):
+ If there are both fields and methods, put a space between.
+
+ * stabsread.c (read_struct_type): Fix bug in handling of
+ GNU C++ anonymous type (indicated by CPLUS_MARKER followed
+ by '_'). (It used to prematurely exit the loop reading in
+ the fields, so it would think it should start reading
+ methods while still in the fields. This could crash gdb
+ given a gcc that can emit nested type information.)
+
+ * valops.c (search_struct_method): Pass 'this' value by
+ reference instead of by value. This provides a more
+ consistent interface through a recursive search where the
+ "bottom" functions may need to adjust offsets (due to multiple
+ inheritance).
+ * valops.c, value.h, values.c: Pass extra parameters to
+ value_fn_field and value_virtual_fn_field so we can
+ correctly adjust offset for multiple inheritance.
+ * eval.c (evaluate_subexp [case OP_FUNCALL]): Simplify
+ virtual function calls by using value_virtual_fn_field().
+ * values.c: New function baseclass_offset, derived from
+ baseclass_addr (which perhaps can be made obsolete?).
+ It returns an offset rather than an address. This is a
+ cleaner interface since it doesn't mess around allocating
+ new values.
+ * valops.c (search_struct_method): Use baseclass_offset
+ rather than baseclass_addr.
+
+Mon Oct 5 16:02:04 1992 Stu Grossman (grossman at cygnus.com)
+
+ * Makefile.in: Re-install 29K/UDI stuff.
+ * remote-udi.c (udi_resume): Clean up.
+ * (udi_wait): Rewrite, leave out bugs.
+ * Add debugging code to print out all register fetches and stores.
+ * Straighten out target_ops.
+ * tm-29k.h (DUMMY_FRAME_RSIZE): Pad out to doubleword.
+
+Mon Oct 5 09:46:44 1992 Ian Lance Taylor (ian@cygnus.com)
+
+ * remote-udi.c (udi_create_inferior): run with no arguments should
+ not pass the program name as an argument, since the UDI code
+ already handles that.
+ (udi_load): get the symbols from prog_name, not arg_string (the
+ load command should really use arg_string as the program name, not
+ prog_name, but at least the run command works now).
+
+ * munch: HP9000/300 nm puts an extra space between T and symbol
+ name.
+
+ * config/irix4.mh: added -lsun to XM_CLIBS to get RPC functions
+ needed for vxworks targets.
+
+Fri Oct 2 22:04:42 1992 John Gilmore (gnu@cygnus.com)
+
+ * am29k-tdep.c (_initialize_29k): Make it possible for the
+ user to set and query the address where function calls into the
+ inferior write a small scratch routine. `set call_scratch_address'
+ * inferior.h (PC_IN_CALL_DUMMY): Fix fencepost error.
+ * remote.c (remote_prepare_to_store): Only fetch regs if they are
+ not already cached validly.
+
+Thu Oct 1 14:36:42 1992 K. Richard Pixley (rich@sendai.cygnus.com)
+
+ Rs6000 native support.
+
+ * infptrace.c: remove #ifdef USG from around include ptrace.h.
+ machines without this header should not be compiling this file.
+ * nm-rs6000.h, rs6000-nat.c: new files for native support.
+ * rs6000-tdep.c: do not include sys/ptrace.h or sys/reg.h.
+ * rs6000-xdep.c: removed. all code now in rs6000-nat.c.
+ * xm-rs6000.h: do not include ptrace.h.
+ (ATTACH_DETACH, FETCH_INFERIOR_REGISTERS): moved to nm-rs6000.h.
+ * config/rs6000.mh (XDEPFILES): removed rs6000-xdep.o.
+ infptrace.o and inftarg.o move to NATDEPFIES.
+ (NAT_FILE, NATDEPFILES): new macro for native support.
+
+ Sun3 native support.
+
+ * config/sun3os3.mh, config/sun3os4.mh (NAT_FILE, NATDEPFILES):
+ new macros for native support.
+ (XDEPFILES): moved infptrace.o and inftarg.o to NATDEPFILES,
+ removed sun3-xdep.o.
+ * xm-sun3.h (ATTACH_DETACH, FETCH_INFERIOR_REGISTERS): moved to
+ nm-sun3.h.
+ * sun3-xdep.c: removed. All code is now in sun3-nat.c.
+ * sun3-nat.c, nm-sun3.h: new files for native support.
+
+Thu Oct 1 10:30:54 1992 Fred Fish (fnf@cygnus.com)
+
+ * dwarfread.c (dbsize): New variable to hold size of dwarf info.
+ * dwarfread.c (dwarf_build_psymtabs): Rename dbsize parameter to
+ dbfsize and use it to initialize new local file scope dbsize.
+ * dwarfread.c (read_ofile_symtab): Initialize dbsize and use it.
+ * dwarfread.c (basicdieinfo): Use dbsize to check for oversize
+ DIEs as well as the current check for undersize DIEs. This helps
+ to gracefully detect and reject corrupted DIE information.
+
+Thu Oct 1 01:57:56 1992 John Gilmore (gnu@cygnus.com)
+
+ Add `command hooks' and a hook for inferior program stopping.
+
+ * command.h (struct cmd_list_element): Remove unused `aux'
+ field. Add new `hook', `hookee', and `cmd_pointer' fields.
+ * command.c (add_cmd): Initialize new fields, elim old.
+ (add_alias_cmd): Clone new fields.
+ (delete_cmd): Un-hook hookee if we're deleting hook.
+ (help_cmd): Tell user the command is hooked, if it is.
+ (lookup_cmd_1): Abbreviations return the original command
+ instead of themselves, so that hooks on the original cmd will be
+ run.
+ * defs.h (enum command_class): Add class_pseudo and comments.
+ * gdbcmd.h (execute_user_command): Add prototype.
+ * infrun.c (normal_stop): If the stop command is hooked,
+ run the hook whenever we stop.
+ (hook_stop_stub): Stub for catch_errors.
+ (_initialize_infrun): Set up pseudo "stop" command.
+ * main.c (execute_user_command): Code extracted from execute_command.
+ (execute_command): If hooked, run the hook before the command.
+ (define_command): If defining a new hook, check the command it
+ is hooking, and warn if none. Install the hook.
+ * source.c (_initialize_source): "l" is an abbrev for "list".
+ * doc/gdb.texinfo: Document command hooks.
+
+ * Makefile.in (VERSION): Roll to 4.6.7.
+ * config/sun4os4.mh: Remove dup inftarg.o from NATDEPFILES.
+ * infrun.c (breakpoints_inserted): Make it static again.
+ * tm-symmetry.h (FLOAT_INFO): #if 0 it for cross-ptrace abuse.
+
+Wed Sep 30 15:33:22 1992 K. Richard Pixley (rich@sendai.cygnus.com)
+
+ Native file renaming.
+
+ * nat-sparc.c -> sparc-nat.c
+ * nat-sun4os4.h -> nm-sun4os4.h
+ * nat-trash.h -> nm-trash.h
+ * config/sun4os4.mh: track file renaming.
+ * configure.in: link to nm.h rather than nat.h.
+ * infptrace.c: include nm.h rather than nat.h.
+
+Tue Sep 29 14:35:00 1992 K. Richard Pixley (rich@sendai.cygnus.com)
+
+ Host/target/native split for sun4.
+
+ * Makefile.in (TSOBS): removed corelow.o.
+ * infptrace.c: included nat.h.
+ * nat-trash.h: temporary header file. This should be removed once
+ all hosts have the native/host/target split.
+ * configure.in: add a symlink from nat-trash.h to nat.h if no
+ other nat file exists for this configuration.
+ * sparc-tdep.c: no longer include sys/ptrace.h.
+ * sparc-xdep.c: removed. contents have been moved to nat-sparc.c.
+ * xm-sparc.h (ATTACH_DETACH, FETCH_INFERIOR_REGISTERS): moved to
+ nat-sun4os4.h.
+ * nat-sparc.c, nat-sun4os4.h: new files for sun4 native support.
+ * config/sun4os4.mh (XDEPFILES): moved infptrace.o and inftarg.o
+ to NATDEPFILES. removed sparc-xdep.o.
+ (NATDEPFILES, NAT_FILE): new macros for native support.
+
+ Break the direct connection from core_file_command to any
+ particular type of core file support.
+
+ * target.h (find_core_target): new prototype.
+ * target.c (find_core_target): new function. Walks the target
+ list looking for the core target.
+ * core.c (core_file_command): replace calls to core_detach and
+ core_open with find_core_target and direct calls.
+
+Tue Sep 29 10:19:00 1992 Ian Lance Taylor (ian@cygnus.com)
+
+ * xm-hp300hpux.h: define MEM_FNS_DECLARED; include <sys/ptrace.h>
+ for infptrace.c.
+ config/hp300hpux.mh: ALLOCA1 was not defined.
+
+Mon Sep 28 22:03:41 1992 Stu Grossman (grossman at cygnus.com)
+
+ * breakpoint.c, exec.c, language.c, main.c, printcmd.c, symfile.c,
+ target.c, valprint.c: Use unfiltered forms of f/printf, et. al.
+ until we can figure out a better way to do paging.
+
+Sat Sep 26 02:07:31 1992 John Gilmore (gnu@cygnus.com)
+
+ * findvar.c (supply_register): Add CLEAN_UP_REGISTER_VALUE hook.
+ * tm-hppa.h (CLEAN_UP_REGISTER_VALUE): Use it.
+ * hppa-coredep.c: Remove, now that we use the hook.
+ * config/hppab.mh, config/hppah.mh: Use standard coredep.o.
+ * hppab-xdep.c, hppah-xdep.c: Remove custom code, use hook.
+
+ * dbxread.c, partial-stab.h: Replace all #ifdef hp9000s800's with
+ GDB_TARGET_IS_HPPA's. This is a SERIOUS KLUDGE. The code needs to all
+ be ripped out and reimplemented right (see elfread.c).
+ * tm-hppa.h (GDB_TARGET_IS_HPPA): Define.
+
+ Rename all HPPA files to fit into unique DOS filenames:
+ * *hppabsd* => *hppab*
+ * *hppahpux* => *hppah*
+
+Sat Sep 26 00:25:15 1992 John Gilmore (gnu@cygnus.com)
+
+ Make the /proc support a target-struct in its own right.
+
+ * Makefile.in: Remove inftarg.[co], since it is now included via
+ config/*.mh files.
+ * config/*.mh: Add inftarg.o and fork-child.o to all *.mh that
+ reference infptrace.o. Add fork-child.o to all *.mh that
+ reference procfs.o.
+
+ * inferior.h (proc_wait, inferior_proc_init, proc_set_exec_trap):
+ No longer global functions.
+ (fork_inferior): New global function from fork-child.c.
+ * inftarg.c (child_wait): Remove USE_PROC_FS conditional.
+ (ptrace_me, ptrace_him): New stub functions for fork_inferior().
+ (child_create_inferior): Moved to fork-child.c as fork_inferior.
+ (child_create_inferior): New tiny function that calls fork_inferior.
+ * fork-child.c: New file, containing fork_inferior, which is
+ built from slight mods to inftarg.c's child_create_inferior.
+
+ * procfs.c (procfs_ops): Add target vector.
+ (attach): Rename as static do_attach.
+ (procfs_create_inferior): New tiny function that calls fork_inferior.
+ (child_xfer_memory): Rename to static procfs_xfer_memory.
+ (store_inferior_registers): Rename to static procfs_store_registers.
+ (inferior_proc_init): Rename to static procfs_init_inferior.
+ (procfs_attach, procfs_detach, procfs_prepare_to_store,
+ procfs_files_info, procfs_open, procfs_mourn_inferior,
+ procfs_can_run): Slightly mangled copies of the corresponding
+ child_XXX routines from inftarg.c.
+ (proc_wait): Renamed to static procfs_wait.
+ (child_resume): Rename to static procfs_resume.
+ (fetch_inferior_registers): Rename to static procfs_fetch_registers.
+ (initialize_proc_fs): Rename to initialize_procfs. Set up
+ procfs_ops, too.
+
+ * putenv.c: index -> strchr.
+ * regex.c: Always rename bcopy to memcpy, etc.
+ FIXME: Eventually do the renames rather than use #define's.
+ * sparc-tdep.c (deferred_stores): Moved from sparc-xdep.c.
+ Fix bcopy->memcpy.
+ * sparc-xdep.c: Move deferred_stores to target dependent.
+ * xm-irix4.h, xm-sysv4.h (CREATE_INFERIOR_HOOK): No longer needed.
+
+Fri Sep 25 21:59:27 1992 John Gilmore (gnu@cygnus.com)
+
+ Split non-target-dependent code out of target_attach routines.
+
+ * target.h: Comments on target_attach args and results.
+ * infcmd.c (attach_command): Check for existing execution, call
+ target_attach, set up terminal status and wait_for_inferior, wait
+ for the attach status, and do normal_stop.
+ * inftarg.c (child_attach): Remove target independent stuff.
+ * remote-adapt.c (adapt_attach): Ditto.
+ * remote-mm.c (mm_attach): Ditto.
+ * remote-udi.c (udi_attach): Ditto.
+ * remote-vx.c (vx_attach): Ditto.
+
+ Cleanup.
+
+ * remote-hms.c (hms_attach): Remove completely, it was useless.
+ * remote-mm.c, remote-hms.c, remote-udi.c, remote-adapt.c: Remove
+ commented-out start_remote calls.
+ * remote-hms.c, remote-adapt.c, remote-mm.c, remote-udi.c: Remove
+ DENTER and DEXIT macros and their calls. Use a real debugger --
+ like gdb -- to see what functions are being called when.
+ * utils.c (strcmp_iw): Make nonstatic, for lint.
+
+Fri Sep 25 18:48:20 1992 John Gilmore (gnu@cygnus.com)
+
+ * infrun.c, inftarg.c, inferior.h: Comment and lint cleanups.
+
+Fri Sep 25 15:13:44 1992 Stu Grossman (grossman at cygnus.com)
+
+ * tm-sparc.h, dbxread.c (read_ofile_symtab): Install Jim Wilson's
+ fix to differentiate between gcc1 & gcc2 compiled files so that we
+ can debug calls that pass structs as args correctly.
+ * symmisc.c (dump_symtab): If block was compiled with gcc, say
+ so, and what version.
+
+ * remote.c (remote_wait): Make regs be char to avoid picayune
+ ANSI compiler warnings.
+
+ * energize.h: Move all external struct decls to inside of
+ __STDC__, add prototype for energize_shell_wait().
+ * energize.c (getpty): Clean up, make us really get a controlling
+ terminal.
+ * (energize_initialize): Disable SIGIO prior to setting up for
+ I/O interrupts. Move setsid(), et. al. to getpty().
+ * (energize_shell_wait): New routine to wait for things started
+ via the shell command, uses wait() instead of /dev/proc.
+ * Also, add prototype for execute_command_1().
+
+Fri Sep 25 12:09:33 1992 K. Richard Pixley (rich@sendai.cygnus.com)
+
+ * inftarg.c (child_create_inferior, child_attach,
+ child_mourn_inferior): collect unix child process stratum
+ functions which live below the target vector into this file to
+ facilitate host/target/native split. Also, make them static.
+ * inflow.c (child_mourn_inferior): removed.
+ * infrun.c (child_create_inferior, child_attach): removed.
+ (resume): becomes global so that functions below the
+ target vector can find it.
+ * inferior.h (resume): add prototype.
+ (child_mourn_inferior, child_create_inferior, child_attach):
+ remove prototypes.
+
+ * xcoffexec.c (exec_ops): child_attach and child_create_inferior
+ replaced with find_default_attach and
+ find_default_create_inferior.
+
+Fri Sep 25 10:21:04 1992 Ken Raeburn (raeburn@rtl.cygnus.com)
+
+ * i960-pinsn.c: Use _filtered routines for printing, so symbolic
+ addresses don't get displayed in the wrong positions.
+
+Fri Sep 25 09:52:47 1992 K. Richard Pixley (rich@sendai.cygnus.com)
+
+ Separate core functions along target vector in preparation for
+ native support. Functions above vector now live in core.c. Those
+ below in corelow.c.
+
+ * core.c (solib_add_stub, core_close, core_open, core_detach,
+ get_core_registers, core_files_info, core_ops): moved to corelow.c
+ (_initialize_core): removed addition of core_ops target.
+ * corelow.c: new file.
+ (solib_add_stub, core_close, core_open, core_detach,
+ get_core_registers, core_files_info, core_ops): moved from core.c
+ (_initialize_corelow): new function.
+ * gdbcore.h (core_open, core_detach): added prototypes.
+ (core_ops): add forward declaration.
+ * Makefile.in (SFILES_MAINDIR): add core.c
+ (OBS): add core.o
+ (TSOBS): change core.o to corelow.o
+
+Wed Sep 23 11:14:53 1992 Stu Grossman (grossman at cygnus.com)
+
+ * m68k-tdep.c (m68k_saved_pc_after_call): Use 'GDB_TARGET_IS_SUN3'
+ instead of 'sun' predefined symbol so that trap analysis code is
+ enabled only when the TARGET is a sun3.
+
+Tue Sep 22 17:13:19 1992 Ken Raeburn (raeburn@cambridge.cygnus.com)
+
+ * tm-i960.h (ext_format_i960): Add top-level declaration.
+ (REGISTER_CONVERT_TO_{VIRTUAL,RAW}): Don't declare it in nested
+ blocks, else Sun4 compiler complains.
+
+Tue Sep 22 00:43:51 1992 John Gilmore (gnu@cygnus.com)
+
+ * mips-pinsn.c (print_insn_arg, case 'B'): Disassemble `break'
+ instruction's argument. Patch from jonathan@cs.stanford.edu
+ (Jonathan Stone).
+
+Mon Sep 21 18:16:30 1992 K. Richard Pixley (rich@sendai.cygnus.com)
+
+ Break the thread of control that implies that a unix child
+ process will be the default target.
+
+ * target.c (find_default_run_target, find_default_attach,
+ find_default_create_inferior, return_zero): new functions.
+ (cleanup_target): Make return_zero the default for to_can_run.
+
+ * exec.c (exec_ops), core.c (core_ops): Replace child_attach and
+ child_create_inferior references with find_default_XXX instead.
+
+ * target.h (struct target_ops): new field, to_can_run.
+ (find_default_attach, find_default_create_inferior): new prototypes.
+ (target_can_run): new macro.
+
+ * Also added a zero (default) to_can_run element to all static
+ struct target_ops initializations throughout GDB, except:
+ * inftarg.c (child_ops): Use new child_can_run() to enable child runs.
+
+ * infrun.c (child_create_inferior): Clean up error handling when
+ no exec file is specified.
+ (child_attach): Don't require exec file.
+
+Mon Sep 21 19:43:13 1992 John Gilmore and K. Richard Pixley (gnu@cygnus.com)
+
+ Remove kill_inferior_fast, in favor of target_kill, which goes
+ through the target vector.
+
+ * inferior.h (kill_inferior_fast): remove declaration.
+
+ * main.c (disconnect): call quit_cover using catch_errors rather
+ than calling kill_inferior_fast directly. New way goes through
+ the target vector, handles attached processes, and writes
+ command history if appropriate.
+ (quit_cover): new function, wrapper for quit_command.
+
+ * convex-xdep.c, go32-xdep.c, hppabsd-xdep.c, hppahpux-xdep.c,
+ infptrace.c, procfs.c: Removed all instances of kill_inferior_fast,
+ inlining them into the local kill_inferior when needed.
+
+Mon Sep 21 19:23:05 1992 John Gilmore (gnu@cygnus.com)
+
+ * infrun.c (_initialize_infrun): Alias `i handle' == `i signals'.
+ * stabsread.c (read_struct_type): Simplify complicated expression
+ for dumb DECstation compiler.
+
+Mon Sep 21 14:54:35 1992 Ian Lance Taylor (ian@cygnus.com)
+
+ * m68k-pinsn (print_insn_arg, fetch_arg): added support for
+ operands to memory management instructions, from WRS.
+
+Sep 20 08:42:12 1992 Fred Fish (fnf@cygnus.com)
+
+ * main.c (main): Back out previous language setting changes.
+ Replace with simple default to C before processing any init
+ files. There MUST be a language set, even in the absence of
+ init files or executables, or expression parsing fails.
+
+Sat Sep 19 09:52:26 1992 Fred Fish (fnf@cygnus.com)
+
+ * main.c (main): Move code that sets initial language to
+ symfile.c. Fixup places where command files are processed to
+ be consistent in setting a default language if none has been
+ previously set.
+ * symfile.c (set_initial_language): Add code moved from
+ main() that sets an initial default language when a new
+ symbol file is read.
+ * symfile.c (symbol_file_command): Call set_initial_language.
+ * symtab.c (find_main_psymtab): Add FIXME comment.
+
+Wed Sep 16 22:31:55 1992 K. Richard Pixley (rich@sendai.cygnus.com)
+
+ * breakpoint.c, sparc-tdep.c: comment changes.
+ * configure.in: removed target_dependent line.
+
+ * remote-mm.c (mm_attach): change printf to error to prevent
+ fallthrough bug.
+ * remote-udi.c (udi_attach): change printf to error to prevent
+ fallthrough bug.
+
+ * rs6000-tdep.c (push_dummy_frame, pop_dummy_frame): replace
+ calls to {fetch|store}_inferior_registers with calls to
+ target_{fetch|store}_registers, for remote-target independence.
+
+Sat Sep 19 04:23:54 1992 John Gilmore (gnu@cygnus.com)
+
+ * Makefile.in: Fix bug I introduced in merging Rich's change.
+ * infrun.c (child_create_inferior): Use proceed() rather than
+ doing all the same stuff by hand.
+
+Thu Sep 17 17:35:37 1992 K. Richard Pixley (rich@sendai.cygnus.com)
+
+ * Makefile.in, configure.in: add support for files used only when
+ configured native, that is, when host = target.
+
+Wed Sep 16 23:03:23 1992 K. Richard Pixley (rich@sendai.cygnus.com)
+
+ * tm-sparc.h, xm-sparc.h: externs and macros relating to deferred
+ stores are target dependent and were moved from xm to tm.
+
+Sat Sep 19 03:14:37 1992 John Gilmore (gnu@cygnus.com)
+
+ * Makefile.in (gdb-all.texi): Build in objdir, not $srcdir.
+
+ * config/decstation.mh: Add MMALLOC_LIB and MMALLOC_DISABLE
+ overrides, to avoid problem in xdr_bytes with malloc(0) => 0.
+
+Wed Sep 16 20:04:54 1992 K. Richard Pixley (rich@sendai.cygnus.com)
+
+ * target.h (struct target_ops): removed to_convert_to_virtual and
+ to_convert_from_virtual elements. Initializations removed from
+ all static initializations.
+ (target_convert_to_virtual, target_convert_from_virtual):
+ removed.
+ (host_convert_to_virtual, host_convert_from_virtual): Removed
+ forward declarations.
+ * target.c (cleanup_target): removed default assignments for
+ to_convert_to_virtual and to_convert_from_virtual.
+ * inftarg.c (host_convert_to_virtual, host_convert_from_virtual):
+ removed.
+ * findvar.c (value_of_register, value_from_register):
+ target_convert_to_virtual inlined.
+ * infcmd.c (do_registers_info): target_convert_to_virtual inlined.
+ * valops.c (value_assign): target_convert_from_virtual inlined.
+
+Fri Sep 18 02:07:39 1992 John Gilmore (gnu@cygnus.com)
+
+ * main.c (gdb_readline): Avoid printf_filtered, which sets char
+ position wrong if used for the prompt.
+ * utils.c (puts_filtered): Comment: NOT a puts() replacement!
+
+ Support for accessing arbitrary MIPS stack frames in memory.
+
+ * blockframe.c (get_prev_frame_info): If INIT_FRAME_PC_FIRST is
+ set, run it before INIT_EXTRA_FRAME_INFO.
+ * stack.c (frame_info): If PRINT_EXTRA_FRAME_INFO defined, call it.
+
+ * mips-tdep.c (init_extra_frame_info): Only clobber the `frame'
+ (FP) value in the frame_info struct if it is zero (as from top of
+ execution stack).
+ (setup_arbitrary_frame): Implement FRAME_SPECIFICATION_DYADIC.
+
+ * mips-xdep.c (fetch_inferior_registers): ZERO_REGNUM always
+ comes back as zero. So does FP_REGNUM, as a trigger for
+ init_extra_frame_info.
+
+ * tm-mips.h (INIT_FRAME_PC_FIRST): Kludge, FIXME, defined to get
+ the program counter set before INIT_EXTRA_FRAME_INFO is run.
+ (INIT_FRAME_PC): Defined to null.
+ (PRINT_EXTRA_FRAME_INFO): print frame pointer location via symtab.
+ (FRAME_SPECIFICATION_DYADIC): Ask for two args in frame command.
+ Briefly explain MIPS stacks in GDB.
+
+Thu Sep 17 03:49:59 1992 John Gilmore (gnu@cygnus.com)
+
+ * copying.awk, copying.c (show_copying_command,
+ show_warranty_command): Rename from copying_info, warranty_info,
+ to match command function conventions.
+
+ * utils.c (prompt_for_continue): Reinitialize more-counts
+ before printing anything, and again afterward. Fix comments.
+ (vfprintf_filtered): Eliminate static buffer; use auto buffer,
+ or alloca() if needed.
+
+ * rs6000-xdep.c: Use correct conditional (IBM6000_TARGET) to
+ detect native versus cross-host.
+
+Wed Sep 16 21:57:14 1992 Stu Grossman (grossman at cygnus.com)
+
+ * m68k-tdep.c (sun3_saved_pc_after_call): Only do trap check for
+ Suns. Rename to m68k_saved_pc_after_call.
+ * tm-68k-noun.h, tm-sun3.h (SAVED_PC_AFTER_CALL): Use
+ m68k_saved... instead of sun3_saved...
+
+Wed Sep 16 17:00:07 1992 John Gilmore (gnu@cygnus.com)
+
+ * Makefile.in (update-depend, update-alldeps): Split out of
+ setup-to-dist, for convenience in rebuilding the depend and
+ alldeps.mak files.
+ (assorted): Update to catch straggler files when building gdb.tar.Z.
+
+Tue Sep 15 01:18:50 1992 John Gilmore (gnu@cygnus.com)
+
+ Preliminary cleanup for splitting host/native/target.
+
+ * infptrace.c (child_resume): Don't deal with NO_SINGLE_STEP
+ here; it is dealt with at a gdb-target-independent level.
+ * rs6000-tdep.c (single_step): Don't call ptrace, we are a
+ high toned routine. Fix return type to void.
+ * tm-rs6000.h (AIX_BUGGY_PTRACE_CALL): Zap, we think we fixed it.
+ Rich and I believe the "real problem" was that both single_step
+ and target_resume were issuing PT_CONTINUE calls. This would
+ cause the second PT_CONTINUE to sometimes fail because the process
+ was already running.
+ * infptrace.c (child_resume): Remove AIX_BUGGY_PTRACE_CALL kludge.
+
+Mon Sep 14 19:20:43 1992 Stu Grossman (grossman at cygnus.com)
+
+ * energize.c (pty_to_kernel): Must check for EAGAIN as
+ termination condition.
+ (full_filename): Don't prepend dirname if filename begins with /.
+ (breakpoint_notify, kernel_dispatch): Deal with DynamicLoad
+ messages properly!!
+ (getpty (NCR)): Lotsa bug fixes...
+ (kernel_dispatch (case StopRType)): Use kill() instead of
+ killpg() so we can deal with losing systems...
+ (wait_for_events): Work around NCR select() lossage. It doesn't
+ zero out readfds when select() returns zero.
+ (energize_initialize): Use I_SETSIG to get SIGIO interrupts. Use
+ getcwd() instead of getwd() (NCR getwd() seg faults).
+ (energize_wait): Use sigaction() for NCR. Their version of signal()
+ is unreliable by default.
+
+ * procfs.c (proc_wait): Call print_sys_errmsg() if we get an
+ error from PIOCSWSTOP.
+
+ * breakpoint.c, core.c, exec.c, language.c, main.c, printcmd.c,
+ symfile.c, target.c, valprint.c: Use _filtered form of *printf.
+ defs.h, utils.c: Make vfprintf_filtered global.
+
+ * energize.c (send_location): New routine to consolidate all
+ places where we must notify kernel of where the given pc is.
+ (cplus_demangle): Put single-quotes around demangled names.
+ (energize_call_command): Call send_location() after doing up,
+ down, and frame commands.
+
+Fri Sep 11 18:28:28 1992 Roland H. Pesch (pesch@fowanton.cygnus.com)
+
+ * doc/gdb.texinfo, doc/gdbinv-m.m4.in, doc/gdbinv-s.m4.in: first
+ pass at doc for two new remote targets---29K using UDI, and Tandem
+ ST2000 using STDBUG.
+
+ * doc/all.m4, doc/none.m4: new m4 switch, _ST2000__
+
+ * doc/all.m4: turn on H8/300 stuff for generic manual
+
+ * doc/gdbinv-s.m4.in: remove text on special procedures to continue
+ after explicit call to breakpoint() in serial stubs.
+
+Fri Sep 11 01:34:25 1992 John Gilmore (gnu@sphagnum.cygnus.com)
+
+ * mipsread.c: Clean up some white space.
+ (parse_symbol): Handle stEnd of stFile.
+ (parse_partial_symbols): Remove old #if 0'd code. Handle stLocal.
+
+ * mips-xdep.c (REGISTER_PTRACE_ADDR, fetch_inferior_registers,
+ store_inferior_registers): Replace unexplained numbers
+ with manifest constants from a DECstation header file.
+ * xm-mips.h (KERNEL_U_ADDR): Get from <machine/param.h>.
+ (REGISTER_U_ADDR): Fix up for Ultrix 4.2.
+
+ * tm-tahoe.h, xm-tahoe.h (KERNEL_U_ADDR): Move macro to xm-tahoe.h.
+
+ * stack.c (_initialize_stack): "dow" should be a valid abbreviation
+ for "down". Suggested by Richard Stallman.
+
+Thu Sep 10 15:26:07 1992 Ken Raeburn (raeburn@cambridge.cygnus.com)
+
+ * remote-vx.c: Rename realloc for inclusion of rpc/rpc.h, to avoid
+ redeclaration bug on SunOS 4.
+
+Wed Sep 9 17:36:53 1992 John Gilmore (gnu@cygnus.com)
+
+ * i386-stub.c, sparc-stub.c (getpacket): Actually check checksums.
+ * m68k-stub.c: Remove a few extraneous ANSI-isms.
+ * remote-nindy.c (nindy_prepare_to_store): Only fetch regs if
+ they aren't already there.
+ * remote-vx.c (vx_prepare_to_store): Ditto.
+ * xcoffread.c: Surround forward struct defns with #ifdef __STDC__.
+
+Wed Sep 9 16:50:22 1992 John Gilmore (gnu@cygnus.com)
+
+ Removed a large number of changes inserted by Per Bothner
+ for C++ support. These will go back in when they've been
+ examined.
+
+Tue Sep 8 21:05:18 1992 Stu Grossman (grossman at cygnus.com)
+
+ * serial.h: Fix prototye for serial_raw().
+ * ser-bsd.c, ser-termios.c: Fix args for serial_open() &
+ serial_write() to match prototypes.
+ * remote-st2000.c (get_reg_name): Make *p be const.
+
+Tue Sep 8 17:24:52 1992 Ken Raeburn (raeburn@cambridge.cygnus.com)
+
+ * remote-nindy.c (nindy_fetch_registers): Make return type void,
+ to agree with target structure field type.
+ (nindy_store_registers): Ditto.
+
+ * Makefile (OPCODES): New var, pointing to opcodes library.
+ (CLIBS, CDEPS): Include it.
+ (saber_gdb): Load opcodes library.
+
+Tue Sep 8 15:22:06 1992 Stu Grossman (grossman at cygnus.com)
+
+ * a68v-xdep.c (store_inferior_registers): declare as void.
+ * infptrace.c: HP/Apollos have ptrace.h in the wrong place.
+ * remote-st2000.c: Massive changes to use new serial package.
+ Also added 'connect' command to transparantly connect to serial
+ port.
+ * ser-termios.c: Big cleanup, use nicer coding conventions.
+ * ser-bsd.c: New module, serial stuff for BSD systems.
+ * serial.h: Define struct ttystate properly using HAVE_TERMIO.
+ * xm-apollo68b.h: #define PTRACE_IN_WRONG_PLACE...
+
+Fri Sep 4 18:53:57 1992 Roland H. Pesch (pesch@fowanton.cygnus.com)
+
+ * doc/gdb.texinfo: fix shameful error of agreement reported by
+ jimb@occs.cs.oberlin.edu (Jim Blandy)
+ * doc/gdb.texinfo: remove old partial discussion of remote serial
+ protocol (via serial debug stubs)
+ * doc/gdbinv-m.m4.in, doc/gdbinv-s.m4.in: new section discussing
+ use of serial debug stubs
+
+Fri Sep 4 00:34:30 1992 Per Bothner (bothner@rtl.cygnus.com)
+
+ * symfile.h: Declaration of set_demangling_style() moved
+ here from demangle.h (which is now in ../include).
+ * i386-xdep.c: Update comment.
+
+Thu Sep 3 13:44:46 1992 K. Richard Pixley (rich@sendai.cygnus.com)
+
+ * symtab.c (completion_list_add_symbol): restructured to optimize
+ for time. First clip names that cannot match. Then clip any
+ names we've already considered. Drop a redundant strncpy. Drop
+ a redundant malloc and associated free for demangled names.
+
+Thu Sep 3 09:17:05 1992 Stu Grossman (grossman at cygnus.com)
+
+ * a68v-xdep.c (store_inferior_registers): Define as type void.
+ * configure.in: Add host m68k-apollo*-bsd*.
+ * demangle.c (struct demanglers): Use enum instead of constant
+ value to keep braindamaged HP/Apollo compiler happy.
+
+Wed Sep 2 20:45:31 1992 Per Bothner (bothner@rtl.cygnus.com)
+
+ * utils.c (strcmp_iw): Add a hack to allow "FOO(ARGS)" to
+ match "FOO". This allows 'break Foo' to work when Foo is
+ a mangled C++ function. (See comment before function.)
+
+Wed Sep 2 13:45:27 1992 John Gilmore (gnu@cygnus.com)
+
+ * config/rs6000.mh (MH_CFLAGS): Circumvent IBM <rpc/rpc.h> bug,
+ for files in vx-share/*.c.
+ * xm-rs6000.h (fd_set): Circumvent the rs6000.mh circumvention,
+ for normal GDB source files.
+
+ * Makefile.in (VERSION): Roll to 4.6.6.
+
+ * tm-vx68.h, tm-es1800.h: Use tm-68k.h rather than tm-sun3.h.
+ * tm-sun3.h: Remove STACK_END_ADDR, no longer used.
+ * tm-sun3os4.h: Update comments.
+ * xm-delta88.h: Remove STACK_END_ADDR.
+
+Wed Sep 2 01:18:31 1992 John Gilmore (gnu@cygnus.com)
+
+ * Makefile.in (VERSION): Roll to 4.6.5.
+
+ * infrun.c: Lint for recent `handle' changes.
+
+ * ser-termios.c, ser-go32.c: Remove DEFUN crap, clean up.
+ * serial.h (EXFUN): Remove all uses, convert to PARAMS.
+ * config/sun4os4.mh: Include ser-termios.o. FIXME, all .mh files
+ should include a ser-XXX.o module.
+
+ * dbxread.c (elfstab_build_psymtabs): Remove DEFUN crap.
+ * defs.h, i960-pinsn.c, remote-hms.c: Replace CONST with simple const.
+
+ * configure.in: Map unrecognized sun 68k's, sun sparcs, into
+ known suns in configure.in, rather than mapping them to unique
+ config files that happen to duplicate other config files.
+ * config/sun3.{mh,mt}: Remove (use identical sun3os4.*).
+ * config/sun4.{mh,mt}: Remove (use identical sun4os4.*).
+
+Wed Sep 2 00:10:43 1992 John Gilmore (gnu@cygnus.com)
+
+ * configure.in (*-*-sunos*): Use trailing * to match all
+ sub-variants of SunOS, e.g. sunos4* to match sunos4.1.1.
+ (sparc-*-sunos3): Remove host & target. Sunos3 never shipped
+ in production on Sun-4.
+ ({a29k,i[34]86,i960}-*-elf): Add targets, equivalent to coff.
+ (m68k-*-{aout,coff,elf}): Add targets, w/new config and tm files.
+ (sparc-*-{aout,coff,elf}): Add targets, w/new config and tm files.
+
+ * config/m68k-un.mt, config/m68k-noun.mt, config/sparc-un.mt,
+ config/sparc-noun.mt: New target configs for embedded.
+ * config/sun4os3.{mh,mt}: Remove, never existed in production.
+
+ * tm-68k-un.h, tm-68k-noun.h, tm-spc-un.h, tm-spc-noun.h: New
+ target definitions for embedded with and without underlines on
+ identifiers.
+
+ * tm-sparc.h, tm-sun2.h, tm-sun3.h: Delete NAMES_HAVE_UNDERSCORE:
+ not a parameter of the CPU, but of the development environment.
+ * tm-es1800.h, tm-sunos.h, tm-vx68.h: Add NAMES_HAVE_UNDERSCORE.
+
+Tue Sep 1 17:31:45 1992 John Gilmore (gnu@cygnus.com)
+
+ * breakpoint.c (breakpoint_re_set): Avoid setting source symtab
+ (which involves reading in main's symtab) if we have no breakpoints.
+
+Mon Aug 31 13:47:45 1992 Fred Fish (fnf@cygnus.com)
+
+ * dwarfread.c (cu_language): New local variable to record
+ language for current compilation unit being processed.
+ * dwarfread.c (set_cu_language): New local function to decode
+ and record language for current compilation unit being processed.
+ * dwarfread.c (synthesize_typedef): Add local function to
+ synthesize a typedef for C++ classes, structs, unions, and
+ enumerations.
+ * dwarfread.c (read_structure_scope): Synthesize typedefs
+ for C++ classes, structs and unions.
+ * dwarfread.c (read_enumeration): Synthesize typedefs for
+ C++ enumerations.
+ * dwarfread.c (read_file_scope): Call set_cu_language to
+ record language for current compilation unit. After symtab
+ is built, save this recorded language.
+ * dwarfread.c (process_dies, add_partial_symbol, struct_type,
+ scan_partial_symbols, new_symbol): Recognize TAG_class_type.
+ * dwarfread.c (add_partial_symbol): Synthesize partial symbol
+ typedefs for C++ classes, structs, unions, and enumerations.
+ * dwarfread.c (scan_compilation_units): Call set_cu_language
+ to record language for current compilation unit.
+ * dwarfread.c (scan_partial_symbols): Call add_enum_psymbol here
+ for TAG_enumeration_types, rather than in add_partial_symbol.
+ * dwarfread.c (add_partial_symbol): Combine TAG_enumeration_type
+ case with class, struct, and union type cases, now that they are
+ the same. Remove tests for non-NULL name attributes, now done
+ by callers.
+ * gdbtypes.h (TYPE_CODE_CLASS): Add type for C++ classes, but
+ treat as alias for TYPE_CODE_STRUCT for now.
+
+Sun Aug 30 21:32:17 1992 Ian Lance Taylor (ian@cygnus.com)
+
+ * Makefile.in: map "gdb" through program_transform_name when
+ installing.
+
+Sun Aug 30 21:18:51 1992 Fred Fish (fnf@cygnus.com)
+
+ * {i386-tdep.c, m68k-tdep.c, mips-tdep.c, sparc-tdep.c}
+ (supply_gregset, fill_gregset, supply_fpregset, fill_fpregset):
+ Use "regi" for local indexing through register numbers, reserving
+ "regno" for the name of a specific register passed as an input
+ parameter. Fix bug propagated through all versions that sometimes
+ used regno as an index when it should have been regi, thus using
+ -1 as an index in some cases.
+
+Sun Aug 30 18:15:17 1992 Per Bothner (bothner@rtl.cygnus.com)
+
+ * cplus-dem.c, demangle.h: Moved to ../libiberty and ../include,
+ respectively, so same demangler can be used by other programs.
+ * Makefile.in: Remove demangler stuff.
+ * Makefile.in (depend): Pass -I../readline (needed for main.c).
+ * demangle.c (_initialize_demangler): Tell demangler which
+ CPLUS_MARKER to assume.
+
+Fri Aug 28 13:13:33 1992 John Gilmore (gnu@cygnus.com)
+
+ RS/6000 portability changes (for hosting cross-debuggers).
+
+ * breakpoint.c (fixup_breakpoints): Re-kludge to IBM6000_TARGET.
+ * buildsym.c, rs6000-xdep.c, rs6000-tdep.c, tm-rs6000.h,
+ xcoffexec.c, xcoffread.c: Rename aixcoff to xcoff everywhere.
+ * printcmd.c (print_frame_args): Remove an RS/6000 dependency.
+ * stabsread.c (define_symbol): Remove RS/6000 dependencies.
+ * tm-rs6000.h (ATTACH_DETACH): Remove: host-dependent.
+ (PTRACE_ATTACH, PTRACE_DETACH): Remove: host-dep.
+ (NO_SINGLE_STEP): Add, target-dependent.
+ (loadinfotextindex): Lowercase, remove "aix_".
+ * xm-rs6000.h: Add <sys/ptrace.h> for infptrace.c.
+ (NO_SINGLE_STEP): Remove, target-dependent.
+ * xcoffexec.c (vmap_symtab): Cleanup #if 0'd code.
+ * xcoffread.c: Only build file if RS/6000 native GDB.
+ (build_function_symbol): Remove #if 0'd code.
+ * rs6000-tdep.c: Cleanup. Add static fn protos.
+ Use CORE_ADDR for addresses throughout. Make void fns void.
+ (pop_dummy_frame): Add FIXME about bogosity of design here.
+ (rs6000_struct_return_address): Ditto.
+ (frameless_function_invocation, frame_get_cache_fsr,
+ frame_initial_stack_address, xcoff_relocate_symtab,
+ xcoff_init_loadinfo, free_loadinfo, xcoff_add_toc_to_loadinfo,
+ add_text_to_loadinfo, find_toc_address): Move from xdep file.
+ Use CORE_ADDRs. Change identifiers to lowercase.
+
+ * rs6000-xdep.c: Make whole file conditional on native RS/6000,
+ supplying dummy routines if non-native. Add prototype for
+ static exec_one_dummy_insn. Move a mess of functions to
+ rs6000-tdep.c (as above). Remove #if 0'd code.
+
+ * config/rs6000.mh (XDEPFILES): Move xcoffexec.o to target side.
+ (XM_CLIBS): Add -lm to circumvent AIX 3.2 libc ldexp bug.
+ * config/rs6000.mt (TDEPFILES): Adopt xcoffexec.o.
+
+ * gdbtypes.h (TYPE_ALLOC): Parenthesize result to avoid problems
+ for callers.
+
+ * vx-share/README, nindy-share/README: New files describing
+ how these directories' code is shared, and with whom.
+
+Thu Aug 27 20:04:56 1992 John Gilmore (gnu@cygnus.com)
+
+ * configure.in (target configurations): Reformat into table.
+ Remove unsupp. Amigados host and target. Ditto Mach 386 target.
+
+ * tm-altosgas.h, tm-i386v-g.h: Remove ancient coff encap configs.
+ * config/{altosgas.mt, i386v-g.mt, i386v32-g.mt}: Ditto.
+ * config/{i386sco.mt,i386v32.mt}: Remove; identical to i386v.mt.
+ * config/{go32.mt,i960.mt}: Remove; they only printed error msgs.
+ * config/nindy960.mt: Remove useless MT_CFLAGS setting.
+ * config/i386aout.mt: Use tm-i386v.h, not tm-i386v-g.h.
+
+ * Makefile.in (config-check): Add command to check whether
+ configure.in is consistent with config/*.
+
+Wed Aug 26 21:10:52 1992 John Gilmore (gnu@cygnus.com)
+
+ * configure.in (host configurations): Reformat nested cases into
+ easy-to-maintain table.
+ (m68k-altos-*, i386v*): We don't care whether coff encap is used.
+ config/{altosgas.mh, i386v-g.mh, i386v32-g.mh}: Remove.
+
+Wed Aug 26 16:02:01 1992 Fred Fish (fnf@cygnus.com)
+
+ * cplus-dem.c: Reorder args to most local functions to make them
+ follow the consistent pattern of struct work_stuff pointer first,
+ followed by pointer into string being demangled, followed by
+ pointer to the string where the result is being stored, followed
+ by other args. Also generally replace most variables of name
+ "type" with "mangled" for consistency. They all pointed to the
+ same string but half were one name and half the other.
+ * cplus-dem.c (LONGERNAMES): Remove #ifndef's.
+ * cplus-dem.c (demangle_qualified): Rewrite to clean up and allow
+ use whenever a qualified name is being demangled.
+ * cplus-dem.c (do_type): Qualified names are treated similarly
+ to fundamental types, not as modifiers of fundamental types.
+
+Mon Aug 24 20:44:38 1992 Stu Grossman (grossman at cygnus.com)
+
+ * configure.in: Add sparclite as a target.
+
+ * sparc-stub.c (handle_exception): Flush instruction cache just
+ before returning to the user. (hexToInt): Fix overzealous cleanup.
+
+Mon Aug 24 11:57:13 1992 Fred Fish (fnf@cygnus.com)
+
+ * infrun.c (handle_command): Rewrite to allow multiple signal
+ numbers, signal number ranges, and to recognize "all" to mean all
+ signals except those used by the debugger.
+ * infrun.c (SET_SIGS, UNSET_SIGS): Macros used in handle_command
+ to set or reset actions for specific signals.
+
+Sun Aug 23 17:10:07 1992 Fred Fish (fnf@cygnus.com)
+
+ * coffread.c (decode_type): Call alloc_type to alloc new
+ types.
+ * stabsread.c (read_array_type, read_range_type, define_symbol):
+ Call alloc_type to alloc new types.
+ * stabsread.c (define_symbol): Move dbl_valu symbol field data
+ from type_obstack to symbol_obstack.
+ * stabsread.c (define_symbol): Move typedef_sym from type_obstack
+ to symbol_obstack.
+ * gdbtypes.h (TYPE_ALLOC): New macro to allocate space for data
+ associated with a type, using the same mechanism as was used to
+ allocate space for the type structure itself.
+ * coffread.c (patch_type, coff_read_struct_type,
+ coff_read_enum_type): Use TYPE_ALLOC.
+ * dwarfread.c (struct_type): Use TYPE_ALLOC.
+ * gdbtypes.c (create_array_type, check_stub_method,
+ allocate_cplus_struct_type): Use TYPE_ALLOC.
+ * mipsread.c (parse_symbol, parse_type): Use TYPE_ALLOC.
+ * stabsread.c (read_struct_type, read_array_type, read_enum_type,
+ read_range_type): Use TYPE_ALLOC.
+
+Sun Aug 23 11:04:08 1992 Fred Fish (fnf@cygnus.com)
+
+ * breakpoint.c (breakpoint_re_set): Select a default source
+ symtab if one is not currently selected.
+ * utils.c (query): Call wrap_here before building the output
+ query string, to turn off wrapping and flush any buffered output.
+ Otherwise our query may end up in the wrap buffer and never be
+ seen by the user.
+ * eval.c (evaluate_subexp): Report error when attempting to
+ evaluate subscript for types without a target type, rather
+ than dumping core by using the NULL pointer.
+ * symfile.c (symbol_file_command): Forget current_source_symtab
+ and current_source_line when discarding symbol table.
+
+Sat Aug 22 22:33:20 1992 John Gilmore (gnu@cygnus.com)
+
+ Bug fixes from Andrew Heybey <ath@lcs.mit.edu>.
+
+ * tm-mips.h (REGISTER_VIRTUAL_TYPE): Float regs are float type.
+ * mips-tdep.c (mips_print_register): Alloc enough space for two regs.
+
+Fri Aug 21 15:17:03 1992 Stu Grossman (grossman at cygnus.com)
+
+ * remote.c (remote_open): Fix baud rate setting to make -b flag
+ work. (remote_wait): Change 'T' message parser to deal with new
+ improved format which allows stub to send an arbitrary bunch of
+ registers.
+ * sparc-stub.c: General cleanups. (trap_low, handle_exception):
+ make all this re-entrant by storing all state on the stack. Clean
+ up memory error trapping. (computeSignal, set_debug_traps):
+ make it all table driven. Make a start at a baud rate setting command.
+
+Wed Aug 19 10:23:27 1992 Ian Lance Taylor (ian@cygnus.com)
+
+ * m68k-pinsn.c: handle new operand type 'r', introduced for cas2.
+
+ * remote-vx.c: redefine malloc to avoid buggy declaration on
+ RS/6000 <rpc/types.h>.
+ xm-rs6000.h: include <sys/select.h> to define fd_set for
+ <rpc/svc.h> on RS/6000.
+
+Tue Aug 18 14:48:24 1992 Ian Lance Taylor (ian@cygnus.com)
+
+ * Makefile.in: added FLAGS_TO_PASS variable, and passed it to
+ recursive invocations of make. Always create installation
+ directories.
+
+Mon Aug 17 18:29:58 1992 Per Bothner (bothner@rtl.cygnus.com)
+
+ * m68k-pinsn.c: Minor fix in style of output (don't use
+ range to indicate floating point control registers).
+
+Sat Aug 15 02:58:03 1992 John Gilmore (gnu@cygnus.com)
+
+ * m68k-pinsn.c: Surround extended support with #ifdef HAVE_68881.
+
+ * infcmd.c (registers_info): Handle multiple register names.
+ Changes inspired by Roland McGrath.
+
+Sat Aug 15 02:28:52 1992 Stu Grossman (grossman at cygnus.com)
+
+ * sparc-stub.c: New file. Mix it with your SPARClite
+ application, and it will speak GDB remote protocol!
+ * remote.c (remote_wait): Change 'T' (expedited reply) message to
+ deal with arbitrary registers. Needed for sparc-stub.
+
+Fri Aug 14 12:11:25 1992 Fred Fish (fnf@cygnus.com)
+
+ * cplus-dem.c (cplus_markers): Add table for gnu style and
+ use throughout, in place of compile time constant CPLUS_MARKER.
+ * cplus-dem.c (ARM_VTABLE_STRING, ARM_VTABLE_STRLEN): Add.
+ * cplus-dem.c (cfront_special): New function, as suggested
+ by pfieland@stratus.com.
+ * cplus-dem.c (forget_types): New function.
+ * cplus-dem.c (cplus_demangle): Call gnu_special, moved from
+ demangle_prefix().
+ * cplus-dem.c (mop_up): Call forget_types().
+ * cplus-dem.c (AUTO_DEMANGLING, GNU_DEMANGLING, LUCID_DEMANGLING):
+ Use throughout, instead of checking current_demangling_style.
+ * cplus-dem.c (demangle_signature): When finding an explicit
+ start of function args, forget all remembered types for
+ lucid/cfront style demangling.
+ * cplus-dem.c (demangle_prefix): In a sequence of two or more
+ underbar characters, use last pair as the delimiter. Hoist
+ gnu_special() call up to cplus_demangle(). Call cfront_special()
+ when appropriate.
+ * cplus-dem.c (cplus_special): Fix virtual table name demangling
+ for inherited classes.
+ * cplus-dem.c (demangle_args): Document quirks of numbered
+ references to previously seen types.
+ * dbxread.c (read_ofile_symtab, process_one_symbol):
+ Use AUTO_DEMANGLING rather than explicitly checking
+ current_demangling_style.
+ * demangle.h: Add some comments.
+ * demangle.h (AUTO_DEMANGLING, GNU_DEMANGLING, LUCID_DEMANGLING,
+ CFRONT_DEMANGLING): New macros.
+ * dwarfread.c (LCC_PRODUCER): Remove trailing space, which is
+ not found in the actual producer string produced by lcc.
+ * dwarfread.c (handle_producer): Use AUTO_DEMANGLING rather
+ than explicitly checking current_demangling_style.
+
+Thu Aug 13 11:54:46 1992 John Gilmore (gnu at cygnus.com)
+
+ * breakpoint.c (enable_longjmp_breakpoint,
+ disable_longjmp_breakpoint, set_longjmp_resume_breakpoint):
+ Check for duplicate breakpoints at the same address. Bug report
+ and preliminary fix from Dave Morrison, <drmorris@us.oracle.com>.
+
+Wed Aug 12 11:14:58 1992 Fred Fish (fnf@cygnus.com)
+
+ * buildsym.c (end_symtab): Document that end_symtab can return
+ NULL under non-error conditions.
+ * dwarfread.c (read_file_scope): Guard against dereferencing NULL
+ returned from end_symtab for empty compilation units.
+
+Tue Aug 11 02:49:39 1992 John Gilmore (gnu at cygnus.com)
+
+ * am29k-tdep.c: Lint from DECstation compiler.
+ * mem-break.c: Restore test of BREAKPOINT size that Fred removed.
+ As the man page says, "Sometimes you just can't get lint to shut
+ up". That doesn't mean you should blow away the code it won't
+ shut up about.
+ * mips-xdep.c: Revise stubbing-out of code until Rich cleans
+ it up over the next few weeks. Make mips x 29k build.
+ * tm-29k.h (CALL_DUMMY): Make it work on cross-endian hosts.
+ (FIX_CALL_DUMMY): Comment in the patching of the breakpoint,
+ but leave it as a comment because the breakpoint instruction
+ is not easily accessible at this moment (it's static, and if
+ we define one here, it goes into every file compiled).
+
+Mon Aug 10 22:27:19 1992 Fred Fish (fnf@cygnus.com)
+
+ * Makefile.in (VERSION): Bump to 4.6.3.
+ * dwarfread.c (scan_partial_symbols): Skip over DIE's within
+ function scopes when building partial symbol tables.
+ * objfiles.c (open_existing_mapped_file): Make it clear in
+ warning message that out of date mapped files are ignored.
+ * symtab.c (lookup_symtab_1, lookup_symbol): Print compilation
+ unit source file name in error message.
+
+Sat Aug 8 23:12:22 1992 Fred Fish (fnf@cygnus.com)
+
+ * dwarfread.c (struct dieinfo): Add has_at_byte_size.
+ * dwarfread.c (struct_type): In absence of AT_byte_size for
+ bitfield, use size of object of member's type for the size of
+ the anonymous object containing the bit field.
+ * dwarfread.c (completedieinfo): Set has_at_byte_size when
+ an AT_byte_size attribute is seen.
+ * mipsread.c (psymtab_to_symtab_1): Fix misspelled cast to
+ union aux_ext (was aux_ent).
+ * i386-pinsn.c (print_insn): Cast 2'nd arg to read_memory from
+ unsigned char* to char*, for Lucid compiler.
+ * i386-tdep.c (codestream_fill): Fix cast of 2'nd arg to read_memory
+ to be correct type (from unsigned char* to char*).
+ * valprint.c (type_print_derivation_info): Minor tweak to placement
+ of commas in derived class printing.
+ * xcoffread.c (builtin_type): Fix misspelling in fatal message.
+
+Fri Aug 7 11:18:23 1992 Steve Chamberlain (sac@thepub.cygnus.com)
+
+ * xm-go32.h: Define LSEEK_NOT_LINEAR
+ * source.c (find_source_lines): if LSEEK_NOT_LINEAR is defined
+ then work out the lseek positions of newlines by running through
+ the file and `tell'ing. This makes source file listing work on
+ OS's where the relationship between physical position in file and
+ canonical position is indeterminate, eg VMS and DOS.
+
+Thu Aug 6 10:56:01 1992 Fred Fish (fnf@cygnus.com)
+
+ * stabsread.c: Ensure that all members of all allocated structures
+ are initialized to known state to avoid hard to find bugs with gdb
+ using fields containing random data.
+ * buildsym.c (start_subfile): Compact dirname initialization.
+ * buildsym.c (patch_subfile_names): New function.
+ * buildsym.c (end_symtab): Make copy of dirname on symbol obstack.
+ * buildsym.c (end_symtab): Free all malloc'd subfile fields.
+ * buildsym.h (patch_subfile_names): Add prototype.
+ * dbxread.c (process_one_symbol): Call patch_subfile_names.
+
+Wed Aug 5 01:42:40 1992 John Gilmore (gnu at cygnus.com)
+
+ * remote-udi.c: Update comments.
+
+ * remote.c (getpkt): Only force retransmission ten times;
+ after that, assume bug in target code, and handle pkt anyway.
+
+Mon Aug 3 17:06:20 1992 Stu Grossman (grossman at cygnus.com)
+
+ * configure.in: Add support for apollo 68k under BSD environment.
+ * xm-apollo68b.h: New file to support above.
+
+Mon Aug 3 00:25:56 1992 Fred Fish (fnf@cygnus.com)
+
+ * configure.in: Recognize i486 host cpu.
+ * valprint.c (type_print_derivation_info): Print derivation info
+ in same form as class declarations in source.
+ * valprint.c (type_print_varspec_suffix): Split arg printing
+ code out to type_print_args function.
+
+Sat Aug 1 13:32:58 1992 Fred Fish (fnf@cygnus.com)
+
+ * dwarfread.c (struct dieinfo): Remove obsolete at_visibility,
+ at_import, at_frame_base.
+ * dwarfread.c (completedieinfo): Remove cases for obsolete
+ AT_visibility, AT_import, and AT_frame_base attributes.
+ * breakpoint.h (BREAKPOINT_MAX): Increase from 10 to 16 for
+ i860, which can keep up to 4 shadow breakpoints.
+ * tm-stratus.h (USG): Define.
+ * tm-stratus.h (TARGET_BYTE_ORDER): Define to BIG_ENDIAN.
+ * xm-stratus.h (HOST_BYTE_ORDER): Define to BIG_ENDIAN.
+ * xm-stratus.h (xm-sysv4.h): Include, name changed from xm-svr4.h.
+ * xm-stratus.h (NO_JOB_CONTROL): Remove define.
+ * config/stratus.mt (TDEPFILES): Include files available from
+ stratus that are not yet in release pending receipt of paperwork
+ at FSF.
+ * buildsym.c (finish_block): Minor code format change.
+ * gdbtypes.h (struct field): Add to comments.
+ * gdbtypes.h (virtual_field_bits): Add to comments.
+ * objfiles.c (allocate_objfile): Change obstack interface to
+ match FSF merging efforts.
+
+Mon Jul 27 21:14:44 1992 Fred Fish (fnf@cygnus.com)
+
+ * Makefile.in (VERSION): Bump to 4.6.2.
+ * Makefile.in (SFILES_MAINDIR): Add stabsread.c
+ * Makefile.in (OBS): Add stabsread.o
+ * Makefile.in (stabsread.o): Add build rule.
+ * stabsread.c, stabsread.h: New files.
+ * buildsym.c: Split out stabs specific support to stabsread.c.
+ * buildsym.h: Split out stabs specific support to stabsread.h.
+ * dbxread.c (stabsread.h): Include
+ * dbxread.c (dbx_new_init): Call stabsread_new_init.
+ * dbxread.c (dbx_psymtab_to_symtab_1): Call stabsread_init.
+ * dbxread.c (read_ofile_symtab): Call end_stabs.
+ * dbxread.c (process_one_symbol): Call end_stabs and start_stabs.
+ * dbxread.c (elfstab_build_psymtabs): Call stabsread_new_init.
+ * dwarfread.c (psymtab_to_symtab_1): Call buildsym_init, add
+ really_free_pendings to cleanups.
+ * elfread.c (elf_new_init): Call stabsread_new_init.
+ * gdbtypes.c: Small changes to maintenance commands.
+ * mipsread.c (stabsread.h): Include.
+ * mipsread.c (psymtab_to_symtab_1): Call end_stabs.
+ * xcoffread.c (stabsread.h): Include.
+ * xcoffread.c (global_stabs): Remove redundant def.
+ * xcoffread.c (read_xcoff_symtab): Call start_stabs and end_stabs.
+
+Wed Jul 22 21:39:33 1992 Fred Fish (fnf@cygnus.com)
+
+ * lmode_inferior_valid, lmode_ours_valid: New static vars.
+ * inflow.c (terminal_init_inferior, terminal_inferior,
+ terminal_ours_1, initialize_inflow): Record and use state
+ of lmode_inferior_valid and lmode_ours_valid.
+
+Wed Jul 22 04:23:03 1992 D. V. Henkel-Wallace (gumby@cygnus.com)
+
+ * es1800.c: use FREAD|FWRITE rather than _FREAD|_FWRITE.
+ include <sgtty.h> on USG. (from sef).
+
+ * depend: es1800 dependency needed here.
+
+Mon Jul 20 21:09:53 1992 Fred Fish (fnf@cygnus.com)
+
+ * buildsym.c (read_struct_type): Initialize structs allocated
+ with alloca, to avoid using random values from stack later on.
+ * defs.h (fprintf_filtered): Add prototype.
+ * gdbtypes.c (check_stub_method): Fix misleading comments.
+ * gdbtypes.c (print_arg_types, dump_fn_fieldlists): New maint
+ support functions.
+ * gdbtypes.c (print_cplus_stuff, recursive_dump_type): Many
+ small changes to maint support functions.
+ * gdbtypes.h (cplus_struct_type): Reorganize member ordering
+ for some fields and expand comments.
+ * objfiles.c (allocate_objfile): Use new obstack_alloc_arg
+ macro and track change to obstack_full_begin macro.
+ * utils.c (fprintfi_filtered): New function.
+ * valprint.c (type_print_base): Fixup field printing to not
+ print extraneous lines and not print bogus "no data fields"
+ messages for C++ classes with no data members. Also use new
+ fprintfi_filtered function.
+
+Mon Jul 20 11:25:18 1992 D. V. Henkel-Wallace (gumby@cygnus.com)
+
+ * configure.in: es1800 ok for 68000 too.
+
+Sat Jul 18 15:48:58 1992 david d `zoo' zuhn (zoo at cirdan.cygnus.com)
+
+ * configure.in: echo error messages to stderr, not stdout
+
+Fri Jul 17 17:07:24 1992 david d `zoo' zuhn (zoo at cirdan.cygnus.com)
+
+ * configure.in: recognize hppa* instead of hppa
+
+Fri Jul 17 16:52:04 1992 Stu Grossman (grossman at cygnus.com)
+
+ * energize.c: Second cut at DynamicLoad message handling.
+
+ * energize.c: Relativize pathnames in #include statements.
+ * (kernel_dispatch): Better error messages for unknown protocol
+ messages.
+ * (kernel_dispatch): First cut at DynamicLoad message handling.
+
+ * Makefile.in: Remove -I../readline from all compilations,
+ include a special case for main.o instead.
+
+Fri Jul 17 10:14:56 1992 Fred Fish (fnf@cygnus.com)
+
+ * eval.c (evaluate_subexp): Ask lookup_struct_elt_type to call
+ error if it fails to find a member type, rather than return NULL
+ and trigger a coredump.
+ * symtab.c (lookup_symbol, lookup_demangled_block_symbol,
+ lookup_demangled_partial_symbol,): Ask demangle_and_match to
+ match on complete demanglings, including argument lists for member
+ functions, rather than just accepting the first demangling that
+ matches the class and function name.
+ * dwarfread.c (read_file_scope): Pass contents of AT_comp_dir
+ to start_symtab as the directory name.
+ * dwarfread.c (completedieinfo): Strip off any leading hostname
+ portion of the AT_comp_dir attribute string. Gdb doesn't know
+ what to do with them (FIXME).
+
+Thu Jul 16 13:37:09 1992 Stu Grossman (grossman at cygnus.com)
+
+ * breakpoint.c (commands_command): Simplify code a bit, remove
+ unnecessary fflush().
+
+ * Makefile.in (OTHERS): Add gcc.patch.
+ * partial-stab.h (N_SO): Fix handling of redundant SOs (again...)
+
+Thu Jul 16 12:07:40 1992 Fred Fish (fnf@cygnus.com)
+
+ * dwarfread.c (LCC_PRODUCER): Change to match current NCR
+ lcc producer string.
+
+Thu Jul 16 11:40:55 1992 Stu Grossman (grossman at cygnus.com)
+
+ * WHATS.NEW renamed to NEWS.
+
+Wed Jul 15 11:37:31 1992 Fred Fish (fnf@cygnus.com)
+
+ * dbxread.c, dwarfread.c: Re-enable experimental code to
+ automatically select demangling style.
+ * demangle.c (DEFAULT_DEMANGLING_STYLE): Rename from simply
+ DEMANGLING_STYLE, to make more descriptive. Revert back to
+ "auto" as default. Comment use.
+ * Makefile.in (DEMANGLING_STYLE, DEMANGLE_OPTS): Remove.
+ * Makefile.in (${DEMANGLER}.o) Remove target and special
+ compilation rule.
+
+Tue Jul 14 23:05:14 1992 Fred Fish (fnf@cygnus.com)
+
+ * Makefile.in (VERSION): Bump to 4.6.1 (post-release versions).
+
+Tue Jul 14 19:26:54 1992 Stu Grossman (grossman at cygnus.com)
+
+ * Makefile.in, demangle.c: Change default demangling style to
+ gnu.
+ * Makefile.in: Update version to 4.6 !!!
+ * README, WHATS.NEW: Update for 4.6.
+
+Tue Jul 14 16:59:46 1992 Ken Raeburn (raeburn@cygnus.com)
+
+ * i960-tdep.c (frame_args_address): If arg pointer can't be found,
+ use frame address.
+
+ * buildsym.c (read_struct_type): Don't die on TYPE_CODE_UNDEF
+ nodes as base classes.
+
+Tue Jul 14 00:12:30 1992 Stu Grossman (grossman at cygnus.com)
+
+ * alldeps.mak, depend: Update.
+
+ * xcoffread.c: Add decl for section_offset to keep prototype happy.
+
+ * Makefile.in (VERSION): 4.5.9.
+
+ * xm-hp300bsd.h: Add decl for strdup().
+ * mips-tdep.c (heuristic_proc_desc): Fill in proc start addr in
+ PDR. Cleanup a few things, fix compilation warnings.
+
+Mon Jul 13 19:06:54 1992 Fred Fish (fnf@cygnus.com)
+
+ * Makefile.in (DEMANGLING_STYLE): New define to set default
+ demangling style for C++. Defaults to "auto".
+ * Makefile.in (DEMANGLE_OPTS): Use DEMANGLING_STYLE.
+ * Makefile.in (SFILES_MAINDIR): Add demangle.c
+ * Makefile.in (OBS): Add demangle.o
+ * cplus-dem.c (GNU_DEMANGLING, ARM_DEMANGLING, LUCID_DEMANGLING):
+ Remove compile time decisions about demangling style and replace
+ with runtime decisions using current_demangling_style.
+ * cplus-dem.c (main): Expand code included during building of
+ standalone demangler to recognize demangling style options.
+ * dbxread.c (demangle.h): Include.
+ * dbxread.c (read_ofile_symtab, process_one_symbol): Set GNU C++
+ demangling style if processing g++ code and current demangling style
+ is auto (Note: this feature currently disabled.)
+ * demangle.c: New file, generic demangling control.
+ * demangle.h (demangling_styles): New enumeration to select one
+ of several demangling styles. Also define string names for each
+ style.
+ * demangle.h (set_demangling_style): Add prototype.
+ * dwarfread.c (demangle.h): Include.
+ * dwarfread.c (GPLUS_PRODUCER, LCC_PRODUCER, CFRONT_PRODUCER):
+ New producer string prefixes to recognize.
+ * dwarfread.c (handle_producer): Consolidate actions for specific
+ producers. Set demangling style based on producer string if
+ current style is auto. (Note: this feature currently disabled.)
+ * config/ncr3000.mt (DEMANGLE_OPTS): Remove.
+
+Sat Jul 11 18:23:58 1992 John Gilmore (gnu at cygnus.com)
+
+ * config/sun4sol2.mh: Remove -xs flag, default INSTALL to cp.
+
+Fri Jul 10 13:58:34 1992 Per Bothner (bothner@rtl.cygnus.com)
+
+ * gdbtypes.c, gdbtypes.h: New function lookup_signed_typename.
+ * c-exp.y: Call lookup_signed_typename() after seeing
+ "signed". This handles "signed char" correctly.
+ * c-exp.y: Recognize (but ignore) 'const' and 'volatile'
+ keywords before a type specifier.
+
+Fri Jul 10 10:19:52 1992 Fred Fish (fnf@cygnus.com)
+
+ * command.c (lookup_cmd_1): Clarify descriptive comments.
+ * gdbcmd.h (maintenanceprintlist): Add declaration.
+ * main.c (maintenanceprintlist): Add definition.
+ * main.c (gdb_completer_command_word_break_characters): Add.
+ * main.c (symbol_completion_function): Switch completer word
+ break character sets dynamically, based on whether completion is
+ being done on commands or on something else.
+ * main.c (initialize_cmd_lists): Init maintenanceprintlist.
+ * maint.c: Include demangle.h.
+ * maint.c (maintenance_demangle): New function.
+ * maint.c (maintenance_print_command): New function.
+ * maint.c (_initialize_maint_cmds): Reorganize some commands
+ under new maintenance print subcommand.
+
+Thu Jul 9 19:05:27 1992 Per Bothner (bothner@rtl.cygnus.com)
+
+ * gdbtypes.c (lookup_struct_elt_type): If the input type is
+ TYPE_CODE_PTR or TYPE_CODE_REF, dereference it to get the
+ target type. Otherwise, 'whatis this.field' wouldn't work,
+ which would be inconsistent, since 'print this.field' works.
+ * buildsym.c (read_struct_type, read_enum_type): Clear
+ TYPE_FLAG_STUB flag.
+ * buildsym.c (cleanup_undefined_types): Don't rely on a
+ flawed "Reasonable test to see if" a type has been defined
+ since it was referred to; now we can just see if the
+ TYPE_FLAG_STUB flag has been cleared.
+ * valprint.c (print_type_base): Emit public/protected/private
+ labels for methods as well as fields. Also, indent these labels
+ 2 spaces instead of 4, for a more conventional "look".
+ * symtab.c (gdb_mangle_name): Undo Fred's change, unless
+ GCC_MANGLE_BUG is defined. Also, handle destructors specially.
+ * gcc.patch: New file. Contains patch for gcc (so people
+ with gdb-2.2.x won't have to wait for a new gcc release).
+
+Thu Jul 9 18:44:26 1992 Ken Raeburn (raeburn@cygnus.com)
+
+ * i960-pinsn.c (mem): Variables reg[123] should point to CONST.
+ (print_addr): Call print_address to show symbolic version as well.
+
+ * remote-vx.c (vx_kill): Don't look for arguments; they aren't
+ being passed.
+ (vx_read_register): Declare inferior_fp_regs. Delete code for
+ copying "inferior_registers" around; the values are already in var
+ "registers". Use correct size for register set.
+
+ * remote-vx.c (vx_write_register): Don't try writing FP regs; the
+ target doesn't support it.
+ (vx_read_register): Don't try reading them either.
+
+ * tm-i960.h (IP_REGNUM): Move to end of non-FP list, since the
+ VxWorks back end reads them in one contiguous set except for this
+ one.
+ (register_names): Change "pc" to "pcw" to avoid confusion printing
+ "$pc".
+ * tm-vx960.h (PC_REGNUM): Use RIP_REGNUM, since that's where we
+ find the PC under VxWorks.
+
+Wed Jul 8 21:34:30 1992 Fred Fish (fnf@cygnus.com)
+
+ * dwarfread.c (alloc_utype, decode_subscr_data): Call alloc_type
+ to create new blank types, instead of handcrafting them.
+ * defs.h (printfi_filtered): Add prototype.
+ * utils.c (printfi_filtered): New function.
+ * gdbtypes.c (recursive_dump_type): Use printfi_filtered to
+ to simplify the code. Other cleanups.
+ * gdbtypes.c (check_stub_method): Demangle using DMGL_ANSI.
+ * gdbtypes.h (struct cplus_struct_type): Add comments describing
+ use of various fields.
+ * gdbtypes.c (print_bit_vector, print_cplus_stuff): New functions.
+ * c-exp.y (%token): Add CLASS as a token for C++, add grammar
+ production that currently treats it exactly the same as STRUCT.
+ * c-exp.y (yylex): Recognize "class" as token CLASS.
+ * symtab.c (gdb_mangle_name): Rewrite to match current g++ stabs.
+ * symtab.c (decode_line_1): Fix to pass quoted args on down to
+ general symbol handling code. Call cplus_mangle_opname with
+ DMGL_ANSI.
+ * symtab.c (decode_line_2): Print demangled function names in
+ breakpoint menus, instead of just file and line number.
+ * symtab.c (name_match): Call cplus_demangle with DMGL_ANSI.
+ * valprint.c (type_print_base): Print "class" for C++ classes,
+ rather than "struct". Print section labels for public, protected
+ and private members of C++ classes.
+ * values.c: Include demangle.h.
+ * values.c (value_headof): Call cplus_demangle with DMGL_ANSI.
+
+Wed Jul 8 17:23:07 1992 Stu Grossman (grossman at cygnus.com)
+
+ * Makefile.in (VERSION): Update to 4.5.8.
+
+ Wed Jul 8 00:11:02 1992 Stu Grossman (grossman at cygnus.com)
+
+ * dbxread.c (dbx_symfile_init): Init stab_section_info to NULL to
+ prevent crashes when examining cross-targets.
+ * dbxread.c (process_one_symbol): Include directory name when
+ calling start_subfile for SOL & BINCL symbols. This allows gdb to
+ find include files, and yacc/lex sources when the cwd doesn't match
+ that in which the object was compiled.
+ * objfiles.h (ALL_MSYMBOLS): Don't seg fault when there are no
+ msymbols.
+ * symtab.c (lookup_symtab_1): Rewrite. It now handles include
+ files.
+
+Tue Jul 7 09:00:42 1992 Fred Fish (fnf@cygnus.com)
+
+ * maint.c (maintenance_command, maintenance_info_command):
+ Install with allow_unknown as 0 and call help_list to show
+ list of possibilities when no subcommand is specified.
+
+Tue Jul 7 00:20:29 1992 Fred Fish (fnf@cygnus.com)
+
+ * configure.in: Add m68k-ericsson-*.
+ * remote-es1800.c, tm-es1800.h, config/es1800.mt: New files.
+
+Sun Jul 5 17:17:16 1992 Fred Fish (fnf@cygnus.com)
+
+ * maint.c: New file.
+ * Makefile.in (SFILES_MAINDIR): Add new file maint.c.
+ * Makefile.in (OBS): Add new file maint.o.
+ * defs.h (command_class): Add class_maintenance.
+ * defs.h (MAINTENANCE_CMDS): Default to including maintenance
+ commands. Allow for them (and other nonessential parts of gdb)
+ to be selectively left out under special circumstances.
+ * gdbtypes.c (recursive_dump_type): New function; supports
+ maintenance print-type command.
+ * gdbtypes.h (recursive_dump_type, maintenance_print_type):
+ Add prototypes.
+ * main.c (maintenancelist, maintenanceinfolist): Add maintenance
+ command lists.
+ * main.c (initialize_cmd_lists): Eliminate unnecessary casts on
+ initializers. Add initializations for setprintlist, showprintlist,
+ setchecklist, showchecklist, maintenancelist, and maintenanceinfolist.
+ * printcmd.c (maintenance_print_type): New maintenance cmd.
+ * valprint.c (setprintlist, showprintlist): Move to main.c, as
+ implied by comment that all cmd lists are owned by main.c.
+ * infcmd.c (unsetlist): Move to main.c, as implied by comment
+ that all cmd lists are owned by main.c.
+ * language.c (setchecklist, showchecklist): Move to main.c, as
+ implied by comment that all cmd lists are owned by main.c
+ * breakpoint.c (enablelist, enablebreaklist, disablelist, cmdlist,
+ deletelist): Remove redundant declarations (also in gdbcmd.h).
+ * symmisc.c (printsyms_command): Now maintenance_print_symbols.
+ * symmisc.c (printmsyms_command): Now maintenance_print_msymbols.
+ * symmisc.c (printpsyms_command): Now maintenance_print_psymbols.
+ * symmisc.c (printobjfiles_command): Now maintenance_print_objfiles.
+ * symtab.h (maintenance_print_symbols, maintenance_print_psymbols,
+ maintenance_print_msymbols, maintenance_print_objfiles):
+ Add prototypes.
+ * symmisc.c (printsyms_command, printpsyms_command,
+ printmsyms_command, printobjfiles_command): Removed from
+ _initialize_symmisc.
+ * main.c (dump_me_command): Moved to maint.c and renamed to
+ maintenance_dump_me.
+ * breakpoint.c (all_breakpoints_info): Rename to
+ maintenance_info_breakpoints.
+ * breakpoint.c (_initialize_breakpoint): Convert add_info of
+ all_breakpoints_info to add maintenance_info_breakpoints to the
+ maintenanceinfolist instead.
+ main.c (initialize_main): Set up maintenance class commands.
+
+Sun Jul 5 11:03:53 1992 Stu Grossman (grossman at cygnus.com)
+
+ * energize-patches: Fix minor problems with building energize lib.
+
+ * energize-patches: Change names of all cadillac procedure calls
+ to be energize procedure calls. Simplify many hooks by moving
+ tests energize.c. Configure energize, and build it automatically now.
+
+Sun Jul 5 09:43:28 1992 Fred Fish (fnf@cygnus.com)
+
+ * Makefile.in (VERSION): Bump to 4.5.7.
+ * cplus-dem.c (demangle_args): Validate index for previously
+ seen type to guard against bogus values from malformed manglings.
+ * valops.c (value_struct_elt_for_reference): Guard against
+ blindly using NULL return value from lookup_symbol.
+
+Sun Jul 5 09:46:43 1992 Stu Grossman (grossman at cygnus.com)
+
+ * cadillac.c, cadillac-patches: Rename to energize.c and
+ energize-patches. Change all routines and variables named
+ 'cadillac*' to 'energize*'. Create new file called energize.h to
+ hold all interface declarations.
+
+ * deblib/connection/*: Move all of this stuff into energize/, but
+ delete unneeded files.
+
+Sun Jul 5 03:06:39 1992 John Gilmore (gnu at cygnus.com)
+
+ * tm-sysv4.h (NAMES_HAVE_UNDERSCORE): SVR4 systems don't.
+
+ * buildsym.c (finish_block): Fix thinko `inner block' complaints.
+ * dbxread.c (process_one_symbol): Parse N_OPT "gcc2_compiled.".
+ * procfs.c (proc_set_exec_trap): Set run-on-last-close flag on
+ child processes, to avoid dead ones "hanging around" after GDB exits.
+ (attach): Always stop the process if it needs it. Set RLC flag
+ when attaching running processes, so it will continue if we detach
+ it, quit, or are killed.
+ (detach): Clear faults and set RLC flag to make process run
+ when we close it.
+ (open_proc_file): New `mode' argument for O_RDONLY or O_RDWR.
+ Callers changed.
+ (info_proc): Open process O_RDONLY, so we can see any process,
+ even those controlled by debuggers.
+ * tm-sun4sol2.h (SUN_FIXED_LBRAC_BUG): They did (in Sol 2).
+
+Sat Jul 4 03:43:38 1992 John Gilmore (gnu at cygnus.com)
+
+ Relocate symbols using an array of section_offsets, rather than a
+ single `addr' or `offset'. This makes Solaris-2 support work, and
+ permits better VxWorks (and maybe xcoff) support later.
+
+ * symtab.h (struct section_offsets): New structure for keeping
+ a set of offsets, rather than a single one.
+ (struct objfile): Replace addr with section_offsets member.
+ * symfile.h: Add sym_offsets to struct sym_fns. Conforming changes.
+ * gdb-stabs.h: New include file with `symbol type specific'
+ parameters for psymtabs and objfiles.
+ * Makefile.in (HFILES): Add gdb-stabs.h.
+ * buildsym.h (start_psymtab, process_one_symbol): Fix prototypes.
+ * coffread.c: Conforming changes. Fake offset array always 0.
+ * dbxread.c: Conforming changes.
+ (struct dbx_symfile_info): Move to gdb-stabs.h.
+ (start_psymtab): Call elfstab_offset_sections to calculate good
+ offsets for this source file, based on the ELF symbol table info.
+ (read_ofile_symtab): Yank N_CATCH, which is dead.
+ (process_one_symbol, N_CATCH): Yank.
+ (", N_FUN, N_FNAME, N_FN, N_FN_SEQ, N_SO, N_SOL, N_ENTRY):
+ Relocate with SECT_OFF_TEXT.
+ (", N_STSYM, N_LCSYM, N_ROSYM): Grope around in the stab string
+ to distinguish relocatable from absolute symbols. Then, if not
+ absolute, do:
+ (", N_STSYM, N_DSLINE): SECT_OFF_DATA.
+ (", N_LCSYM, N_BSLINE): SECT_OFF_BSS.
+ (", N_ROSYM): SECT_OFF_RODATA.
+ (elfstab_build_psymtabs): Caller has allocated dbx_symfile_info.
+ (dbx_symfile_offsets): Add to translate addr to offset.
+ * dwarfread.c: Conforming changes. Single offset currently used.
+ * elfread.c: Add various complaints about elf/stab stuff.
+ #include gdb-stabs.h. Conforming changes, using a single offset.
+ (elf_symtab_read): Record info from BSF_FILE symbols, and local
+ variables called "Bbss.bss", "Ddata.data", and "Drodata.rodata",
+ for later use in building psymtabs.
+ (elf_symfile_read): Allocate dbx_symfile_info here, to keep
+ the info collected in elf_symtab_read. Cleanup calls free_elfinfo.
+ (free_elfinfo): New fn, frees all chained stab_section_infos
+ in an objfile, and zaps the start-of-chain pointer.
+ (elfstab_offset_sections): New fn, looks in stab_section_info
+ chain to determine section bases to relocate a psymtab's worth
+ of symbols, as they are being read.
+ * mipsread.c: Conforming changes. Stabs-reading will relocate
+ using one offset. MIPS-reading will not relocate at all.
+ * partial-stab.h: Relocate different symbol types using different
+ offsets from section_offsets.
+ * symfile.c: Conforming changes.
+ (find_lowest_section): Unused function to use later
+ to free us from the Tyranny of the Text Section.
+ (syms_from_objfile): Translate absolute arg ADDR to offsets used
+ in all lower layers of symbol reading. Call format-specific
+ sym_offsets function to initialize offsets for high speed symbol
+ reading.
+ (symbol_file_add): Call reinit_frame_cache so callers don't have to.
+ (symbol_file_command, add_symbol_file_command): Callers changed.
+ * symmisc.c (dump_psymtab): Print new relocation parameters.
+ * xcoffread.c: Corresponding changes.
+
+ * buildsym.c: Tidy innerblock_complaint and blockvector_complaint.
+ * main.c (main): Read the $HOME/.gdbinit file before processing
+ the argv arguments (e.g. reading symbol files or core
+ files). This allows global parameters to be set, which will apply
+ during the symbol reading. The ./.gdbinit is still read after
+ argv processing.
+ * symtab.c (list_symbols): `i variables' shouldn't show enum values.
+ * xcoffexec.c: Clean up quote inside comment.
+
+Fri Jul 3 20:18:26 1992 Fred Fish (fnf@cygnus.com)
+
+ * breakpoint.c, buildsym.c, c-exp.y, coffread.c, command.c,
+ core.c, cplus-dem.c, dbxread.c, dwarfread.c, elfread.c, environ.c,
+ eval.c, findvar.c, gdbtypes.c, hppabsd-tdep.c, hppahpux-tdep.c,
+ i386-tdep.c, ieee-float.c, infcmd.c, inflow.c, infptrace.c,
+ infrun.c, m2-exp.y, mipsread.c, objfiles.c, parse.c, procfs.c,
+ putenv.c, remote-mm.c, remote-vx.c, solib.c, sparc-tdep.c,
+ sparc-xdep.c, stack.c, symfile.c, symtab.c, symtab.h, target.c,
+ tm-i386v.h, tm-sparc.h, utils.c, valarith.c, valops.c, valprint.c,
+ values.c, xcoffread.c:
+ Remove "(void)" casts from function calls where the return value
+ is ignored, in accordance with GNU coding standards.
+
+Fri Jul 3 00:00:49 1992 John Gilmore (gnu at cygnus.com)
+
+ * dbxread.c (process_one_symbol): Ignore N_MAIN, N_ENDM for Solaris.
+ * partial-stab.h: Ignore N_ENDM.
+ * elfread.c (elf_symtab_read): Ignore symbols that don't have a
+ CODE or DATA section attachment. This eliminates a lot of random
+ values from shared libraries, which screw up the ordinary symbols
+ in the address ranges they happen to overlap.
+ * buildsym.c (define_symbol): Eliminate special tests
+ for function types; move into "function" cases in switch statement.
+ (define_symbol: 'f', 'F', 'P'): Process all parameter types
+ in case they define new type numbers. But ignore them (FIXME).
+ ('k', 'B'): Ignore const and volatile if we see them (FIXME).
+ (read_sun_builtin_type): Add commentary.
+
+Wed Jul 1 00:47:02 1992 david d `zoo' zuhn (zoo at cirdan.cygnus.com)
+
+ * xm-rs6000.h: define MEM_FNS_DECLARED
+
+Tue Jun 30 02:25:10 1992 John Gilmore (gnu at cygnus.com)
+
+ * tm-mips.h (GDB_TARGET_IS_MIPS): Define for mips-xdep.c.
+ (READ_MIPS_FORMAT, COFF_FORMAT): Remove, unused now.
+ * mips-xdep.c: Remove most include files (unused, caused errs).
+ (fetch_core_registers): Use right parameters in dummy fn.
+
+Mon Jun 29 18:30:57 1992 John Gilmore (gnu at cygnus.com)
+
+ * buildsym.c (scan_file_globals): Beware the null file.
+ Fix from Jim Williams.
+
+ * stack.c (return_command): Evaluate expression *before* popping
+ off the stack frames! Fix inspired by Jim Williams.
+ (up_silently_command, down_silently_command): No sel frame is error.
+
+ * defs.h (memcpy, memset): Conditionalize decls on
+ #ifndef MEM_FNS_DECLARED, since DECstation differs.
+ (alloca): Break out the STDC and non-STDC alloca cases, to make
+ it work on old preprocessors as well as "picky ANSI" ones.
+ * xm-mips.h (memcpy, memset): Declare, and set MEM_FNS_DECLARED.
+
+ * mips-tdep.c (heuristic_proc_start): Zero arg produces zero.
+ * utils.c (fputs_demangled): Rename SLOP since DECstation system
+ header files define it!
+
+ * tm-29k.h (BREAKPOINT): Allow it to be overridden with -D.
+
+Mon Jun 29 16:30:25 1992 Fred Fish (fnf@cygnus.com)
+
+ * dbxread.c, i386-pinsn.c, i386-tdep.c, regex.c, solib.c, symmisc.c,
+ symtab.h, tm-i386v4.h, valprint.c, values.c: Lint.
+ * breakpoint.c, c-exp.y, coffread.c, command.c, environ.c, eval.c,
+ findvar.c, infcmd.c, infptrace.c, infrun.c, m2-exp.y, parse.c,
+ putenv.c, solib.c, sparc-xdep.c, symtab.c, tm-i386v.h, tm-sparc.h,
+ utils.c, valarith.c, valops.c, valprint.c, values.c:
+ Replace bcopy() use with memcpy(), which is more standard and can
+ take advantage of gcc's builtin functions for increased performance.
+ * breakpoint.c, buildsym.c, coffread.c, dbxread.c, i386-tdep.c,
+ ieee-float.c, infcmd.c, sparc-tdep.c, stack.c, symtab.c, symtab.h,
+ target.c, values.c:
+ Replace bzero() use with memset(), which is more standard and can
+ take advantage of gcc's builtin functions for increased performance.
+ * i386-tdep.c, main.c, valprint.c:
+ Replace bcmp() use with memcmp(), which is more standard and can
+ take advantage of gcc's builtin functions for increased performance.
+
+Sun Jun 28 13:30:22 1992 Fred Fish (fnf@cygnus.com)
+
+ * remote.c (remote_wait): Fix cast on signal() call.
+ * defs.h (alloca): More diddling with alloca. Have to ensure
+ that it has a prototype, so that if alloca is defined as a macro
+ that takes an arg, the definition is seen as a use of a macro
+ that takes an arg, to satisfy picky ANSI preprocessors.
+
+Sat Jun 27 12:12:20 1992 Fred Fish (fnf@cygnus.com)
+
+ * sparc-pinsn.c: Use <string.h> rather than "string.h", for
+ consistency with all other gdb files.
+ * cadillac.c: Use <string.h> rather than <strings.h>.
+ * cadillac.c (kernel_dispatch): Convert rindex usage to strrchr.
+ * Makefile.in (MAKE): Remove definition for consistency with
+ other Makefile.in files and to fix problem with recursive makes.
+
+Fri Jun 26 19:03:23 1992 John Gilmore (gnu at cygnus.com)
+
+ * hppahpux-xdep.c (child_xfer_memory): Avoid PT_WDUSER because it
+ crashes H-PUX.
+
+Fri Jun 26 11:09:10 1992 Steve Chamberlain (sac@thepub.cygnus.com)
+
+ * source.c (print_source_lines): for DOS interoperability; don't
+ print CR (013) as ^M.
+
+Thu Jun 25 15:18:42 1992 Stu Grossman (grossman at cygnus.com)
+
+ * dbxread.c (dbx_symfile_init): Move more code under hp9000s800
+ conditional.
+ * hppabsd-core.c: Don't include "param.h", include <sys/param.h>
+ instead.
+ * remote.c (remote_wait): Cast signal to void * to avoid warning
+ from busted HP compiler.
+
+ * partial-stab.h (N_SO): Rearrange code a little so that all SO
+ stabs cause end_psymtab to be called.
+
+ * buildsym.c (read_sun_builtin_type): Handle new FCS Sun CC
+ compiler feature of putting 'c' into basic type descriptors for
+ all forms of char.
+
+ * procfs.c (child_resume): Work around Solaris (on Sparc) lossage
+ where there is no place for nPC in prrun struct.
+
+Thu Jun 25 12:06:00 1992 Fred Fish (fnf@cygnus.com)
+
+ * mipsread.c: Pass NULL name pointer to init_type, not 0.
+ * gdbtypes.c (init_type): Use copy of typename on type_obstack.
+ * dwarfread.c (enum_type): Save enum names on type_obstack.
+ * dwarfread.c (struct_type): Save member name on type_obstack.
+ * symtab.c (_initialize_symtab): Fix misspelling.
+ * regex.c (store_jump, insert_jump): Return void.
+
+Thu Jun 25 04:00:10 1992 John Gilmore (gnu at cygnus.com)
+
+ * defs.h (PARAMS): Move to ../include/ansidecl.h.
+ (alloca): Declare return type on SPARC, since Sun doesn't.
+ (*_BYTE_ORDER): Improve comment: *must* be defined.
+
+ * tm-hppa.h: New file, architectural definition of HP PA.
+ * tm-hppabsd.h, tm-hppahpux.h: Shrink to deltas from tm-hppa.h.
+
+ * am29k-pinsn.c, am29k-tdep.c, copying.awk, copying.c,
+ hppa-coredep.c, hppa-pinsn.c, hppabsd-core.c, hppabsd-tdep.c,
+ hppabsd-xdep.c, hppahpux-tdep.c, hppahpux-xdep.c, remote-udi.c,
+ ser-go32.c, xcoffsolib.c: Remove <stdio.h> which is already in
+ "defs.h".
+
+ * hppa-coredep.c, hppa-pinsn.c, hppabsd-core.c, hppabsd-tdep.c,
+ hppabsd-xdep.c, hppahpux-tdep.c, hppahpux-xdep.c, xcoffsolib.c,
+ xcoffsolib.h, xm-go32.h, xm-hppabsd.h, xm-hppahpux.h: Copyrights.
+
+Wed Jun 24 12:53:20 1992 John Gilmore (gnu at cygnus.com)
+
+ * printcmd.c (output_command): Thinko.
+ (x_command): Only set remembered size/format if cmd succeeds.
+
+ * dbxread.c (read_ofile_symtab): Remove N_CATCH special case,
+ since it is no longer used and burns time for every symbol read.
+ (process_one_symbol): Treat N_CATCH like default (complain).
+
+Wed Jun 24 00:26:56 1992 Stu Grossman (grossman at cygnus.com)
+
+ * partial-stab.h (case N_TEXT): Fix fencepost error when
+ detecting start of new symbol info after reading symtab for a
+ module with a zero length TEXT segment.
+
+Tue Jun 23 21:46:26 1992 Fred Fish (fnf@cygnus.com)
+
+ * Makefile.in (VERSION): Bump to 4.5.6.
+ * coffread.c (coff_end_symtab): Cast 2nd arg of complain() to
+ correct type.
+ * defs.h (NORETURN): Define away for Lucid compiler.
+ * remote.c (remote_timer, remote_interrupt): Signal handlers
+ take one int arg.
+ * ser-termios.c (serial_write, serial_close): Return whatever
+ value the write/close call returns, rather than falling off end.
+ * inferior.h (PTRACE_ARG3_TYPE): Third arg to ptrace is int on
+ more systems than it is "char *". Define PTRACE_ARG3_TYPE to
+ default to int.
+ * infptrace.c, hppabsd-xdep.c, hppahpux-xdep.c, i386-xdep.c,
+ inferior.h (call_ptrace): Use PTRACE_ARG3_TYPE to declare type
+ of third arg.
+ * a68v-xdep.c, arm-xdep.c, convex-xdep.c, hp300ux-xdep.c, infrun.c,
+ m88k-xdep.c, mach386-xdep.c, mips-xdep.c, os68k-xdep.c, pyr-tdep.c,
+ pyr-xdep.c, rs6000-xdep.c, sparc-xdep.c, sun3-xdep.c, sun386-xdep.c,
+ symm-xdep.c, ultra3-xdep.c: Use PTRACE_ARG3_TYPE to cast ptrace
+ argument 3.
+ * sparc-xdep.c, a68v-xdep.c (fetch_inferior_registers,
+ store_inferior_registers): Supply missing fourth argument to
+ ptrace().
+ * cadillac.c (kernel_dispatch): Make return type void.
+ * cadillac.c (iosig): Signal handlers take one int arg.
+ * valprint.c (val_print_fields): Call fprint_symbol to get
+ automatic C++ demangling for mangled field names.
+
+Mon Jun 22 20:18:06 1992 Fred Fish (fnf@cygnus.com)
+
+ * command.c (add_abbrev_prefix_cmd): Fix misspelling in comment.
+ * dwarfread.c (enum_type): Fix misspelling in comment.
+ * valprint.c (val_print_fields, cplus_val_print): Minor
+ adjustment to printing of C++ class structures to more closely
+ match format for printing C structures, with and without setting
+ pretty print.
+
+Mon Jun 22 17:19:02 1992 Per Bothner (bothner@cygnus.com)
+
+ * infrun.c (wait_for_inferior): Don't test for SIGEMT
+ (which is not a Posix signal) if it isn't defined.
+ * tm-linux.h, xm-linux.h, config/linux.m[ht], configure.in:
+ New port to Linux (a free Unix clone for 386 machines).
+
+Sat Jun 20 19:19:52 1992 John Gilmore (gnu at cygnus.com)
+
+ COFF changes for dealing better with EPI 29K C compiler output.
+
+ * coffread.c (record_minimal_symbol): Pass the minsym type to it.
+ Callers changed.
+ (coff_end_symtab): Sort blocks if needed. Complain if misordered.
+ (read_coff_symtab): Move patch_opaque_types call from
+ coff_symfile_read. Restrict it to symtabs from this objfile.
+ (process_coff_symbol: C_TPDEF): Don't put ordinary foward
+ references on opaque type chain; just let coff_lookup_type handle 'em.
+ (decode_type): Complain about tagndx values on
+ non-struct/union/enum types, which the EPI compiler tends to produce.
+
+ * symtab.c (list_symbols): Make minimal symbol variable-finding work.
+
+ * tm-68k.h (FIX_CALL_DUMMY): Avoid alignment and byte order
+ dependency.
+
+ * elfread.c (elf_symfile_read): Update bfd_elf_find_section
+ usage to match new prototype. Include libbfd.h to get prototype.
+
+ * source.c (find_source_lines): Handle large st_size fields.
+
+Sat Jun 20 16:28:39 1992 Fred Fish (fnf@cygnus.com)
+
+ * infcmd.c (jump_command): Use cleanups to avoid memory leaks.
+ * stack.c (return_command): Use cleanups to avoid memory leaks.
+
+Fri Jun 19 19:06:41 1992 John Gilmore (gnu at cygnus.com)
+
+ * remote-adapt.c, remote-eb.c, remote-mm.c: Lint. Fix
+ INT_REGNUM to INTE_REGNUM.
+
+ * tm-29k.h (SDB_REG_TO_REGNUM): Add for EPI 29K C compiler.
+
+Fri Jun 19 15:30:15 1992 Stu Grossman (grossman at cygnus.com)
+
+ * configure.in, dbxread.c, hppa-coredep.c, hppa-pinsn.c,
+ hppabsd-core.c, hppabsd-tdep.c, hppabsd-xdep.c, hppahpux-tdep.c,
+ hppahpux-xdep.c, munch, partial-stab.h, tm-hppabsd.h,
+ tm-hppahpux.h, xm-hppabsd.h, xm-hppahpux.h: HPPA merge.
+
+ * Makefile.in (c-exp.tab.c, m2-exp.tab.c): Filter out bogus extern
+ declarations of malloc/realloc/free that are inserted by some
+ versions of yacc.
+ * m2-exp.y: Prevent conflicts with TRUE and FALSE tokens by
+ #undeffing them.
+ * xm-rs6000.h: Declare malloc/realloc/free appropriately. Yet
+ another decl of strdup (this really ought to come from libiberty.h!).
+
+Fri Jun 19 10:28:05 1992 John Gilmore (gnu at cygnus.com)
+
+ * remote.c (getpkt): Error if input exceeds buffer size.
+ (_initialize_remote): `set remotedebug' enables packet trace.
+
+ * dbxread.c (process_one_symbol:N_FUN): GCC now produces relative
+ N_SLINE's, etc, just like Sun cc on Solaris2.
+
+ * am29k-tdep.c (read_register_stack, write_register_stack):
+ Change RSTACK_HIGH_ADDR to rstack_high_address, a user-settable
+ variable. Add `set' and `show' commands for it.
+ * doc/gdb.texinfo: Document it.
+
+Thu Jun 18 19:35:22 1992 Fred Fish (fnf@cygnus.com)
+
+ * valprint.c (type_print_1): Plug memory leak. Print all
+ C++ syms as demangled, not just functions.
+ * buildsym.c (read_range_type): When we find a signed char
+ type, do a lookup of signed char, not plain char. Plain char's
+ still get looked up as plain char's elsewhere.
+
+Thu Jun 18 18:59:04 1992 John Gilmore (gnu at cygnus.com)
+
+ * eval.c: Avoid residue-by-zero when evaluating without side effects.
+ (Bug and fix found by Pierre Willard.)
+
+Wed Jun 17 13:08:33 1992 Stu Grossman (grossman at cygnus.com)
+
+ * xm-rs6000.h: Fix decls for malloc, realloc, and free.
+
+ * xm-rs6000.h: Add decl for strdup().
+
+ * tm-rs6000.h: Remove #include of inferior.h. Fixes many
+ compilation errors.
+
+ * breakpoint.c (enable_command, disable_command): Without args,
+ should only affect normal breakpoints and watchpoints.
+
+ * m68k-pinsn.c (print_insn_arg): Make register be const.
+ * xcoffexec.c: Remove ' from comment.
+ * xm-sun3os4.h: Define MALLOC_INCOMPATIBLE to avoid conflicts
+ with decls of malloc in c-exp.tab.c (as produced by yacc).
+ There's got to be a better way to do this...
+
+Wed Jun 17 11:10:40 1992 Fred Fish (fnf@cygnus.com)
+
+ * partial-stab.h: Convert single rindex use to strrchr.
+ * mipsread.c, dbxread.c: Remove troublesome inclusion of non-
+ standard <strings.h> file, now that the only single use of
+ rindex in the gdb source files is gone.
+
+Tue Jun 16 22:17:49 1992 Fred Fish (fnf@cygnus.com)
+
+ * mipsread.c: Undo ill effects from including <strings.h>,
+ which #defines index to be strchr. Unfortunately, index is
+ a member of a symbol table structure that can't be changed.
+ * mipsread.c: tm-mips.h includes coff/symconst.h and coff/sym.h,
+ remove redundant #include's.
+
+Tue Jun 16 14:15:51 1992 Stu Grossman (grossman at cygnus.com)
+
+ * mipsread.c: #include <strings.h> for rindex().
+
+Tue Jun 16 09:01:49 1992 Fred Fish (fnf@cygnus.com)
+
+ * xcoffexec.c (map_vmap): Turn comment into a real C comment.
+
+Mon Jun 15 18:41:23 1992 Stu Grossman (grossman at cygnus.com)
+
+ * dbxread.c (process_one_symbol), partial-stab.h: Ignore
+ extraneous SO stabs from busted C++ compilers.
+
+Mon Jun 15 12:21:45 1992 Fred Fish (fnf@cygnus.com)
+
+ * Makefile.in (VERSION): Bump to 4.5.5.
+ * symtab.c (decode_line_1): Until C++ support stabilizes, when
+ C++ lookups fail, print possibly helpful hint about completion.
+ * cplus-dem.c (demangle_signature): Fix ARM style demangling
+ for static data members.
+ * dbxread.c (dbx_psymtab_to_symtab_1): Fix prototype.
+ * config/ncr3000.mh (INSTALL): Don't use /usr/ucb/install,
+ it's broken on ncr3000's.
+
+Mon Jun 15 07:21:00 1992 Fred Fish (fnf@cygnus.com)
+
+ * dwarfread.c (decode_modified_type): Change type of first arg.
+ Change 'modifier' to char from unsigned char. Cast single use
+ that needs to be unsigned char.
+ * symtab.h (SYMBOL_BASEREG_VALID): Explain disabling.
+ * utils.c (strdup_demangled): Add function.
+ * defs.h (strdup_demangled): Add prototype.
+ * stack.c (return_command): Demangle C++ function names for query.
+ * infcmd.c (jump_command): Demangle C++ function names for query.
+ * cplus-dem.c (consume_count): New function and prototype.
+ * cplus-dem.c (demangle_class, gnu_special, demangle_func_type,
+ do_type): Replace conversion code with consume_count().
+ * cplus-dem.c (gnu_special): Fix demangled of static members.
+ * source.c (list_command): Print demangled function names
+ when appropriate. Fix supplied by Peter Schauer.
+
+Mon Jun 15 01:45:48 1992 John Gilmore (gnu at cygnus.com)
+
+ * sparc-tdep.c: Clean up slightly for Solaris2.
+
+ * buildsym.c (define_symbol): Nameless types are now on several
+ platforms; generalize them and un-ifdef them to make Solaris 2
+ work.
+
+Sun Jun 14 10:55:51 1992 John Gilmore (gnu at cygnus.com)
+
+ * infcmd.c: Fix typo (reported by Rob Savoye).
+ * xm-sun4sol2.h (gregset_t): Thinko in register set definition.
+ * symtab.h: Disable SYMBOL_BASEREG_VALID until it works.
+ * dbxread.c (dbx_psymtab_to_symtab_1): Renamed from
+ psymtab_to_symtab_1. Use current psymtab's sym_offset and symbol_size,
+ rather than the one for the first file in the dependency chain.
+
+ * dbxread.c (end_psymtab): Only reset texthigh if it's not already
+ set. Don't reset our own texthigh, or dependency-only pst's, in
+ scanning all the rest of the psymtabs.
+ (process_one_symbol): Fix comments around N_OBJ, N_OPT, N_UNDF.
+
+ * buildsym.h (N_UNDF): Improve comments.
+ (N_LSYM, etc): Skip types without names (":T(0,3)=sfoob...").
+
+Sat Jun 13 11:16:45 1992 Fred Fish (fnf at cygnus.com)
+
+ * symtab.h (struct symbol): Add aux_value union for preserving
+ an additional per-symbol value.
+ * symtab.h (SYMBOL_BASEREG, SYMBOL_BASEREG_VALID): Add defines.
+ * frame.h (FRAME_GET_BASEREG_VALUE): Provide default definition.
+ * findvar.c (read_var_value): Use SYMBOL_BASEREG if valid.
+ * printcmd.c (address_info): Use SYMBOL_BASEREG if valid.
+ * symmisc.c (print_symbol): Use SYMBOL_BASEREG if valid.
+
+Sat Jun 13 09:18:46 1992 Michael Tiemann (tiemann@rtl.cygnus.com)
+
+ * symfile.c (clear_symtab_users_once): Now non-static (for
+ objfiles.c).
+
+Fri Jun 12 18:54:40 1992 John Gilmore (gnu at cygnus.com)
+
+ * arm-pinsn.c, i960-pinsn.c, m68k-pinsn.c, mips-pinsn.c,
+ ns32k-pinsn.c, pyr-pinsn.c, sparc-pinsn.c, tahoe-pinsn.c,
+ vax-pinsn.c: Remove reg_names decl (now in defs.h).
+
+ Solaris-2 support on SPARC:
+
+ * dbxread.c: Add symbol_size to struct dbx_symfile_info.
+ Add symbol_size and file offsets to struct symloc.
+ Add static symbol_table_offset, string_table_offset,
+ file_string_table_offset, next_file_string_table_offset,
+ last_function_name.
+ (add_old_header_file): Convert error() to complain()t.
+ (dbx_symfile_read): Get symbol size via the objfile.
+ Also get symbol_table_offset.
+ (dbx_symfile_init): Record symbol size and count via the objfile.
+ (dbx_next_symbol_text): Always add file_string_table_offset when
+ accessing string table.
+ (read_dbx_symtab): Initialize file_string_table_offset to 0.
+ (SET_NAMESTRING): Use the offset.
+ (end_psymtab): Large kludge to determine addresses where source
+ files start and end (for the psymtab header).
+ (psymtab_to_symtab_1): Set file_string_table_offset before reading.
+ Get this, symbol size, and symbol offset, from psymtab.
+ (read_ofile_symtab): Don't back up one symbol for Solaris2.
+ Patch up last_source_start_addr if zero in N_SO.
+ (process_one_symbol): Add variable function_start_offset.
+ ( "", N_FUN, N_LBRAC, N_RBRAC, N_SLINE): Add ifdef for
+ BLOCK_ADDRESS_FUNCTION_RELATIVE.
+ ( "", N_OBJ, N_OPT): Ignore.
+ (elfstab_build_psymtabs): New function to read stabs out of
+ an ELF file.
+
+ * Makefile.in: Accept $(BISON) even though we really want $(YACC).
+ (gdb): use GLOBAL_CFLAGS when linking, too.
+ * partial-stab.h (N_UNDF): Deal with Sol2 relative stringtab offsets.
+ (N_OBJ, N_OPT): Ignore.
+ ('f', 'F'): Save last function name.
+
+ * elfread.c (record_minimal_symbol_and_info): Kludged to put
+ extra info in the minimal symbol.
+ (elf_symtab_read): The extra info is the size of an ELF object,
+ which was kludged to us in the `udata' field of the BFD symbol.
+ Gag me with a crowbar...
+ (elf_symfile_read): Keep track of both the absolute load address,
+ and the offset between load addr and symbols. Handle STABS as
+ well as DWARF sections, passing the absolute load address to
+ elfstab_build_psymtabs.
+
+ * symfile.h: Prototype elfstab_build_psymtabs.
+ * symfile.c: Add almost-OK debug versions of add_psymbol_*to_list.
+
+ * xm-sysv4.h: Add <limits.h> to avoid conflicting defns in defs.h.
+
+ * buildsym.h: Add processing_acc_compilation flag.
+ * buildsym.c (read_sun_builtin_type, read_sun_floating_type): New.
+ (define_symbol): Skip arg types in function entries. Resolve
+ overloaded 'P' which acc uses for prototypes of functions called
+ by this file.
+ (read_type: 'b', 'r'): Handle Solaris2 builtin types.
+
+ * minsyms.c (prim_record_minimal_symbol_and_info): Hack to
+ save size of ELF symbols. FIXME.
+ * tm-sun4os5.h: Rename to tm-sun4sol2.h. Update defines for Sol2.
+ * xm-sun4os5.h: Rename to xm-sun4sol2.h. Hack more defines.
+
+ * configure.in: Solaris config is sparc-sun-solaris2.
+ * config/sun4os5.m[ht]: Rename to config/sun4sol2.m[ht]; new xm, tm.
+
+ * objfiles.c (free_objfile): Eliminate storage leaks. Contributed
+ by <Peter.Schauer@regent.e-technik.tu-muenchen.dbp.de>.
+ * symfile.c (symfile_bfd_open): Comment where name is freed.
+ * symmisc.c (extend_psymbol_list): Comment where list is freed.
+
+Fri Jun 12 08:24:36 1992 Fred Fish (fnf at cygnus.com)
+
+ * expprint.c (print_subexp): Add missing ']'.
+ * defs.h (reg_names): Fix declaration to match that in infcmd.c
+ * stack.c (reg_names): Delete redundant (and inconsistent) decl.
+ * WHATS.NEW: Point out improved C++ function name handling.
+ * gdbtypes.c (lookup_fundamental_type): For now, use the same
+ type names for both implicitly and explicitly signed integral
+ types. See comment in the source code.
+
+Thu Jun 11 12:31:50 1992 John Gilmore (gnu at cygnus.com)
+
+ Two `long long' fixes from Robert R. Henry (rrh@dino.tera.com):
+ * defs.h (longest_to_int): Avoid void arm of ?: in error case.
+ * expprint.c (print_subexp): Fix printing of register names.
+
+Thu Jun 11 01:33:40 1992 John Gilmore (gnu at cygnus.com)
+
+ * inferior.h (register_valid): Declare.
+ * remote-udi.c, rs6000-xdep.c, sparc-xdep.c, tm-rs6000.h: Remove decl.
+ * objfiles.h (ALL_OBJFILE_{SYMTABS,PSYMTABS,MSYMBOLS}): Add
+ macros for traversing the data structures in a single objfile.
+ * tm-m88k.h, tm-sparc.h (REGISTER_NAMES): Remove extra semicolon.
+ * tm-i960.h (REGISTER_NAMES): Cosmetic change.
+ * infcmd.c: Lint.
+
+Tue Jun 9 17:19:45 1992 Fred Fish (fnf at cygnus.com)
+
+ * c-exp.y, m2-exp.y: Move remapping defines for malloc and
+ realloc. Add remapping defines for {yyss, yyssp, yyvs, yyvsp}.
+ * config/{amix.mh, i386v4.mh, ncr3000.mh, stratus.mh,
+ sun4os5.mh}: Add definition for INSTALL using /usr/ucb/install.
+
+Tue Jun 9 16:29:19 1992 Stu Grossman (grossman at cygnus.com)
+
+ * depend: rebuild to account for remote-st2000.c.
+ * remote-st2000.c: Almost works now.
+ * tm-st2000.h: Need to turn on HAVE_68881, else things won't compile.
+
+Mon Jun 8 23:05:51 1992 Fred Fish (fnf@cygnus.com)
+
+ * c-exp.y (yylex): Recognize single-quoted strings that specify
+ tokens with embedded whitespace, such as C++ demangled names.
+ * defs.h (demangle_and_match, strcmp_iw, skip_quoted): Prototypes.
+ * main.c (gdb_completer_quote_characters): Add global variable.
+ * main.c (symbol_completion_function): Total rewrite for C++
+ demangled name handling.
+ * main.c (skip_quoted): New function.
+ * main.c (main): Set rl_completer_quote_characters.
+ * symmisc.c (dump_symtab): Print source language for symtab.
+ * symtab.c (expensive_mangler): Add prototype and function.
+ * symtab.c (completion_list_add_symbol): Total rewrite for new
+ C++ demangled name handling.
+ * symtab.c (lookup_symbol): Check for demangled C++ symbol first,
+ other changes for demangled C++ symbol handling.
+ * symtab.c (lookup_demangled_block_symbol): Use demangle_and_match.
+ * symtab.c (lookup_demangled_partial_symbol): Use demangle_and_match.
+ * symtab.c (decode_line_1): Recognize C++ demangled names on input.
+ * symtab.c (completion_list_add_symbol): Total rewrite for new
+ C++ demangled name handling.
+ * symtab.c (expensive_mangler): New function.
+ * utils.c (strcmp_iw, demangle_and_match): New functions.
+ * xcoffread.c (aixcoff_symfile_read): Fix prototype.
+
+Mon Jun 8 21:59:08 1992 John Gilmore (gnu at cygnus.com)
+
+ * Makefile.in: Roll VERSION to 4.5.4.
+ * Makefile.in, config/*.mh, config/*.mt: Rename TM_CFLAGS
+ to MT_CFLAGS, XM_CFLAGS to MH_CFLAGS to match file names.
+ * config/sun4os5.mh: Add MH_CFLAGS=-xs to save debug info.
+
+Mon Jun 8 14:17:42 1992 Stu Grossman (grossman at cygnus.com)
+
+ * alldeps.mak: Rebuild to account for new files.
+ * config/st2000.mt: Use tm-st2000.h, not tm-68k.h.
+ * tm-st2000.h: New file.
+ * configure.in: Tandem debug monitor (st2000) support.
+ * remote-st2000.c, config/st2000.mt: ditto.
+
+Fri Jun 5 11:51:01 1992 John Gilmore (gnu at cygnus.com)
+
+ * blockframe.c (inside_entry_file, inside_main_func,
+ inside_entry_func): Return 0 if no symbols; avoid crashing.
+
+Wed Jun 3 17:48:04 1992 John Gilmore (gnu@cygnus.com)
+
+ * xcoffread.c (read_xcoff_symtab): Set c_sclass from n_sclass
+ without masking, since it is signed and will later be compared
+ against signed quantities. The right fix is probably to make
+ it all unsigned, but this is a small, safe fix for this release.
+ FIXME -- make the real change sometime soon.
+
+Mon Jun 1 16:16:12 1992 Michael Tiemann (tiemann@cygnus.com)
+
+ * remote-vx.c (vx_load_command,add_symbol_stub): Default READNOW
+ parameter in call to `symbol_file_add' to 0.
+
+ * xm-sun4os4.h (MALLOC_INCOMPATIBLE): Define it.
+
+Sun May 31 06:38:27 1992 Michael Tiemann (tiemann@cygnus.com)
+
+ * configure.in: Handle -m680[01234]0-wrs.
+
+Fri May 29 22:16:02 1992 Michael Tiemann (tiemann@rtl.cygnus.com)
+
+ * m68k-pinsn.c (print_insn_arg): Pass &EXT_FORMAT_68881 to
+ `ieee_extended_to_double'.
+
+Wed May 27 09:27:57 1992 John Gilmore (gnu at cygnus.com)
+
+ * valops.c (value_assign): Lint, by Pierre Willard.
+
+Tue May 19 19:38:10 1992 John Gilmore (gnu at cygnus.com)
+
+ * coredep.c (fetch_core_registers): Remove premature warning,
+ which triggers on DECstation even though all regs are accessible.
+
+ * m68k-pinsn.c (print_insn_arg): Use new macros to get
+ sign-extension of instruction fields even on unsigned-char hosts.
+ Bug found by Fred J Roeber, fjr@sgfb.ssd.ray.com.
+
+ 88K changes inspired by Ted Lemon (uunet!lupine!mellon):
+ * tm-m88k.h, tm-umax.h: Avoid sizeof() in REGISTER_xxx macros,
+ since they define the target, not the host.
+ * m88k-pinsn.c: Fix typo.
+
+Thu May 14 01:16:48 1992 John Gilmore (gnu at cygnus.com)
+
+ * valarith.c (value_zerop): -0.0 is still zero.
+ * eval.c (evaluate_subexp): Avoid NaN anomalies in float compares.
+ Patches by Paul Eggert <eggert@twinsun.com>.
+
+Mon May 18 13:53:51 1992 Stu Grossman (grossman at cygnus.com)
+
+ * alldeps.mak, depend: re-make to account for ser-*.c.
+
+Sun May 17 16:51:20 1992 Fred Fish (fnf@cygnus.com)
+
+ * inflow.c (new_tty): Temporarily ignore SIGTTOU when
+ disconnecting from controlling terminal, to avoid gdb hanging
+ on SVR4. Fixes bug reported by Oliver Okrongli.
+ * procfs.c (PROC_NAME_FMT): Change format to match default used
+ by system, as suggested by Oliver Okrongli.
+ * tm-68k.h (FRAME_FIND_SAVED_REGS): Apply missing parentheses
+ bug fix from Brent Townshend (bst%tt@cam.ORG).
+ * c-exp.y (nonempty_typelist): Fix memory overrun bug reported
+ by turlais@rechser.total.fr.
+ * dwarfread.c (decode_subscr_data): Fix bug in calculation of
+ length of non-zero lowerbound arrays. Bug fix from Peggy Fieland.
+ * objfiles.h (unlink_objfile): Add prototype.
+ * objfiles.c (unlink_objfile): Add function.
+ * objfiles.c (free_objfile): Call unlink_objfile.
+ * objfiles.c (allocate_objfile): Call unlink_objfile on newly
+ remapped objfiles. Bug reported by hahn@sunshine.labs.tek.com.
+ Also, discard old possibly bogus sf struct.
+ * symfile.c (symbol_file_add): Call init_entry_point_info() and
+ find_sym_fns() for remapped symbol files, in case of any changes
+ since the last mapping.
+
+Wed May 13 18:28:20 1992 Steve Chamberlain (sac@thepub.cygnus.com)
+
+ * findvar.c (read_relative_register_raw_bytes): use the raw size
+ of a register to bcopy, rather than the host's sizeof(CORE_ADDR).
+
+Tue May 12 17:44:39 1992 Steve Chamberlain (sac@thepub.cygnus.com)
+
+ Changes to support GDB running on DOS using GO32 and H8 support
+
+ * defs.h: if xm.h doesn't define FOPEN_RB, include "fopen-same.h",
+ allowing hosts with different text and binary file formats to
+ work.
+ * coffread.c (read_coff_symtab): changed calling convention and
+ operation - now it opens its own file with FOPEN_RB rather than
+ duping and fdopening the provided handle.
+ * dbxread.c, cplus-dem.c: #include mangling.
+ * exec.c: If O_BINARY isn't defined, set it to 0, call openp for
+ binary files oring in the right bit.
+ * utils.c, terminal.h, inflow.c: hackery because dos doesn't have terminals.
+ * remote-hms.c: cleanup to use the new remote serial stuff
+ * serial.h, ser-termios.c, ser-go32.c: newfiles to provide host
+ independent remote terminal I/O.
+ * remote.c: if DONT_USE_REMOTE not defined, then don't use it.
+ * source.c (openp): fix off by one problem removing / - can now
+ open a source file in the root directory with DOS.
+ * values.c (value_as_pointer): remove bogus address bits from
+ long. (unpack_long): unpack into unsigned long/short if pointer.
+
+Tue May 12 14:15:48 1992 Stu Grossman (grossman at cygnus.com)
+
+ * infrun.c (child_attach): Don't allow gdb to attach to itself.
+ It gets permanently stuck in many OSes.
+ * breakpoint.c, infcmd.c, infrun.c, utils.c: Change many printfs
+ to printf_filtered.
+ * breakpoint.c: Improve help text for info breakpoints.
+
+Mon May 11 14:17:18 1992 John Gilmore (gnu at cygnus.com)
+
+ * README: Add pointer to internals doc, and describe reading
+ info files.
+ * utils.c (print_sys_errmsg): Use stderr. Reported by Pierre Willard.
+ * symtab.c (output_source_filename): Remove old glop for wrapping
+ lines, use wrap_here. Reported by Pierre Willard (pierre@la.tce.com).
+
+Thu May 7 11:45:03 1992 John Gilmore (gnu at cygnus.com)
+
+ * Makefile.in: version.c should depend on Makefile, not Makefile.in.
+ * munch: Add sort -u to avoid duplications.
+ * symtab.c (lookup_symbol): Improve Stu's fix of 22 April.
+ Improved fix by hahn@sunshine.labs.tek.com (Doug Hahn).
+
+Mon May 11 13:27:46 1992 Fred Fish (fnf@cygnus.com)
+
+ * cplus-dem.c (demangle_signature): Recognize misplaced '_' to
+ avoid infinite loops while demangling bogus mangled names.
+ * valprint.c (type_print_base): Minor fix for GNU style guide
+ conformance.
+
+Sat May 9 18:02:17 1992 Fred Fish (fnf at fishpond)
+
+ * Makefile.in (VERSION): Bump to 4.5.3
+ * Makefile.in (DEMANGLE_OPTS): Remove obsolete -Dnounderscore
+ * Makefile.in (demangle): New target to create standalone
+ demangler with same code and options as internal demangler.
+ * cplus-dem.c: Massive restructuring, rewriting, cleanups, etc
+ to support ARM style and Lucid style demangling, improve
+ maintainability, fix several demangling bugs. More changes
+ to follow.
+ * defs.h (strstr): Add ANSI compatible prototype.
+ * valprint.c (type_print_1): Demangle using ansi option.
+ * config/ncr3000.mt (DEMANGLE_OPTS): Remove -Dnounderscore.
+
+Sat May 9 14:47:28 1992 Stu Grossman (grossman at cygnus.com)
+
+ * xcoffexec.c (vmap_exec): Don't assume .text and .data are the
+ first two sections.
+
+Fri May 8 11:42:15 1992 Per Bothner (bothner@rtl.cygnus.com)
+
+ * mipsread.c (parse_procedure): Return rather than using
+ uninitialized variable 'b'.
+
+Fri May 8 07:48:27 1992 Stu Grossman (grossman at cygnus.com)
+
+ * Makefile.in, remote-udi.c, remote-vx.c, 29k-share/dfe/mini2udi.c,
+ 29k-share/dfe/yank.c, vx-share/xdr_ptrace.c, vx-share/xdr_regs.c:
+ Remove -I29k-share, -Ivx-share from Makefile.in. Make #includes
+ relative to each source file.
+
+Fri May 8 07:48:27 1992 K. Richard Pixley (rich@cygnus.com)
+
+ * Makefile.in: propogate INSTALL, INSTALL_DATA, INSTALL_PROGRAM on
+ recursions.
+
+Thu May 7 10:00:52 1992 Stu Grossman (grossman at cygnus.com)
+
+ * am29k-pinsn.c: Use new opcode table in "opcode/a29k.h".
+ * am29k-tdep.c: Update to latest code from AMD.
+ (get_saved_register) don't crap out if no frame.
+ * remote-udi.c: Set/clear inferior_pid as appropriate.
+ (udi_open) call target_preopen, don't close fd 0!!!, clean up
+ error handling. Fixup end-of-debugging messages.
+ (udi_fetch_registers) clean up big time, mainly don't multiply
+ register_valid indices by 4, and use proper Offset when reading
+ gr96-gr127. (udi_store_registers) general cleanup.
+ (fetch_register) cleanup, simplify. (regnum_to_srnum)
+ INT_REGNUM->INTE_REGNUM.
+ * tm-29k.h: Upgrade to latest code from AMD.
+ * 29k-share/udi/udip2soc.c: Get rid of useless errmsg_m macro.
+ (UDIConnect) Clean up error processing (like, don't do exit() if
+ execlp fails), make code restartable, make more attractive.
+ (UDIStop) Use SIGINT instead of SIGUSR1, as isstip won't stop
+ otherwise.
+
+Wed May 6 14:34:18 1992 Per Bothner (bothner@rtl.cygnus.com)
+
+ * tm-irix3.h: Re-define CPLUS_MARKER to '.'.
+ * xm-rs6000.h, tm-rs6000.h: Move re-definition of CPLUS_MARKER
+ from former to latter.
+
+Wed May 6 14:12:35 1992 Fred Fish (fnf@cygnus.com)
+
+ * cplus-dem.c (do_args): Handle void args the same as others.
+ * objfiles.c (free_objfile): Only try to unmap files when
+ reusable objfiles are supported.
+ * valprint.c (type_print_varspec_suffix): Add parameter that
+ specifies if C++ demangling included function arguments. Use
+ it to suppress printing extra pair of ()'s.
+ * valprint.c (type_print_1): Fix problem with printing demangled
+ C++ function types where demangled type includes the function
+ args.
+
+Tue May 5 11:10:27 1992 Fred Fish (fnf@cygnus.com)
+
+ * Makefile.in (DEMANGLER): Define and default to cplus-dem.
+ Allows selection of C++ demangler to be a configuration option
+ until multiple demanglers are supported.
+ * demangle.h: New include file for extended demangler support.
+ * breakpoint.c, gdbtypes.c, printcmd.c, stack.c, symtab.c,
+ utils.c, valprint.c: Include "demangle.h" and change all calls
+ to cplus_demangle() or fputs_demangled() to use individual
+ demangling options.
+ * valprint.c (type_print_1): Change options to cplus_demangle
+ to print demangled function args. Still broken, but now less so.
+ * cplus-dem.c: Include demangle.h, reorganize and update some
+ comments to reflect reality.
+ * cplus-dem.c (cplus_demangle, cplus_mangle_opname): Change
+ second arg from fixed integer to bit based multiple options.
+ * cplus-dem.c (optable): Reformat and replace ansi members with
+ bit based options.
+ * cplus-dem.c (do_type): Fix bug with parsing missing return type.
+
+Mon May 4 22:26:59 1992 John Gilmore (gnu at cygnus.com)
+
+ * values.c (set_internalvar): Force evaluation of lazy values.
+ Bug reported by RMS.
+
+Sun May 3 15:47:45 1992 Fred Fish (fnf@cygnus.com)
+
+ * Makefile.in (VERSION): Bump to 4.5.2.
+ * Makefile.in (DEMANGLE_OPTS): Add, default to -Dnounderscore.
+ * configure.in: Simplify ncr3000 gdb_host logic, add gdb_target.
+ * dwarfread.c (struct_type): Apply fix from Peggy Fieland for
+ proper handling of bit fields.
+ * gdbtypes.h (struct type): Clarify use of field.bitpos.
+ * symtab.h: Fix couple of misspellings in comments.
+ * value.h (struct value): Clarify use of bitpos.
+ * value.h (unpack_field_as_long): Change prototype, returns
+ LONGEST.
+ * values.c (unpack_field_as_long): Change return type to LONGEST,
+ sign extend unpacked fields that are signed, other rewriting.
+ * config/ncr3000.mt: New target config file.
+
+Fri May 1 01:53:26 1992 John Gilmore (gnu at cygnus.com)
+
+ * utils.c (printchar): Print 0x7F and 0x80-0x9F in \nnn notation
+ even when printing 8-bit characters.
+
+ * gdbtypes.c (make_{reference,pointer,function}_type): New
+ functions which handle overwriting of forward-referenced types
+ for stabs file reading.
+ (lookup_{reference,pointer,function}_type): These just call
+ the make_*_type functions with a null storage alloc parameter.
+ * gdbtypes.h (make_{reference,pointer,function}_type): Declare.
+ * xcoffread.c (smash_to_pointer_type): Remove, no longer used.
+
+ * buildsym.c (dbx_lookup_type): Zero result for (-1,-1) arg.
+ (dbx_alloc_type): Make it easier to understand. No funct change.
+ (define_symbol: 't'): Don't put the typedef name into the name of
+ the struct, union, or enum. Bugfix.
+ (read_type: '*', '&', 'f'): Add comments. Use make_XXX_type
+ routines to properly handle overwriting preallocated types so that
+ forward references will work.
+ (read_enum_type): Force enum values to file scope, due to bug in
+ Sun compiler output. FIXME, fix later.
+
+ Remove unused header_file_prev_index mechanism. It was already
+ obsolete in gdb-3.5. These comments appeared in 3.5:
+ /* 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. */
+ * dbxread.c (add_new_header_file): Remove header_file_prev_index.
+ * buildsym.h: Remove it and prev_index that saves it.
+ * buildsym.c (push_subfile, pop_subfile, start_symtab): Remove it.
+
+ * solib.c (special_symbol_handling): When called from core files,
+ must set up debug_addr. Don't print error messages, just return.
+ * symmisc.c (print_symbol): Less ascii diarrhea for enums, please.
+
+Wed Apr 29 15:26:51 1992 Per Bothner (bothner@rtl.cygnus.com)
+
+ * cplus-dem.c: Allow nested class names (as in
+ Foo::Bar::method()).
+ Allow the cleaner cfront style of nested class names
+ (Q2_3Foo3Bar as well as Q23Foo3Bar).
+ Make cplus_demangle re-entrant by removing use of global
+ variables. Instead, place all shared variables in a
+ stack-allocated structure, and pass around its address.
+
+Fri Apr 24 07:41:19 1992 Stu Grossman (grossman at cygnus.com)
+
+ * Makefile.in (make-proto-gdb-1): 1st cut at packaging
+ 29k-share/* subdirs...
+
+ * remote-udi.c (udi_insert/remove_breakpoint): Completely
+ rewrite, only leave out the bugs.
+
+ * Makefile.in: Add 29k/UDI support. Improve depend.
+ * alldeps.mak, configure.in, depend: Add 29k/UDI support.
+
+ * am29k-tdep.c: Update to use new calling conventions, and misc
+ symbol elements.
+
+ * m68k-pinsn.c (print_insn_arg): Make branch offsets be signed.
+
+Thu Apr 23 18:43:17 1992 Fred Fish (fnf@cygnus.com)
+
+ * tm-29k.h: Set DECR_PC_AFTER_BREAK to 0, as 29ks have nice
+ breakpoint instructions that leave PC pointing at the right place.
+
+ * core.c (core_open): Call warning() to print warnings.
+
+Wed Apr 22 09:55:42 1992 Stu Grossman (grossman at cygnus.com)
+
+ * symtab.c (lookup_symbol): Need to check if msymbol->name is
+ NULL, as ALL_MSYMBOLS will never return a NULL msymbol pointer.
+ This prevents a crash when trying to lookup the value of a
+ non-existent symbol.
+
+Wed Apr 22 09:42:15 1992 Fred Fish (fnf@cygnus.com)
+
+ * signame.c, signame.h: Remove, replaced by strsignal.c in
+ libiberty.
+ * i960-tdep.c, infrun.c, mach386-xdep.c, procfs.c, sparc-tdep.c,
+ sun386-xdep.c: Remove include of signame.h
+ * Makefile.in (SFILES_MAINDIR): Remove signame.c
+ * Makefile.in (HFILES): Remove signame.h
+ * Makefile.in (OBS): Remove signame.o
+ * defs.h (safe_strerror, safe_strsignal, strerrno, strsigno,
+ errno_max, signo_max, strtoerrno, strtosigno, strsignal,
+ psignal, perror): Add prototypes.
+ * defs.h, xm-apollo68v.h, xm-ultra3.h (SYS_SIGLIST_MISSING):
+ Remove define.
+ * depend: Manually remove signame.[cho] references.
+ * convex-tdep.c (subsig_name): Replace use of sys_siglist with
+ strsignal.
+ * convex-xdep.c (core_file_command): Replace use of sys_siglist
+ with safe_strsignal.
+ * core.c (core_open): Replace use of sys_siglist with
+ safe_strsignal.
+ * core.c (memory_error): Replace use of sys_errlist with
+ safe_strerror.
+ * i960-tdep.c (print_fault): Replace use of sys_siglist with
+ safe_strsignal.
+ * infcmd.c (program_info): Replace use of sys_siglist with
+ safe_strsignal.
+ * infrun.c (signal_stop, signal_print, signal_program):
+ Allocate dynamically based on dynamic determination of number
+ of signals to support.
+ * infrun.c (child_create_inferior): Replace use of sys_errlist
+ with safe_strerror.
+ * infrun.c (wait_for_inferior): Replace use of sys_siglist with
+ safe_strsignal.
+ * infrun.c (sig_print_info): Replace use of sig_abbrev with
+ strsigno and sys_siglist with safe_strsignal.
+ * infrun.c (handle_command): Call signo_max to find number of
+ signals. Replace sig_number with strtosigno and sig_abbrev with
+ strsigno.
+ * infrun.c (signals_info): Replace sig_number with strtosigno.
+ * infrun.c (_initialize_infrun): Call signo_max to find number of
+ signals. Dynamically allocate signal_{stop,print,program}.
+ * procfs.c (errno_table): Remove, now in libiberty/strerror.c.
+ * procfs.c (errnoname): Add function and prototype.
+ * procfs.c (info_proc_siginfo): Call errnoname, replace use
+ of sys_siglist with safe_strsignal.
+ * procfs.c (info_proc_stop, info_proc_signals): Replace use of
+ sys_siglist with safe_strsignal.
+ * procfs.c (info_proc_stop): Call errnoname.
+ * procfs.c (signalname): Replace sig_abbrev with strsigno.
+ * stuff.c (main, get_offset): Replace use of sys_errlist with
+ strerror.
+ * sun386-xdep.c (core_file_command): Replace use of sys_siglist
+ with safe_strsignal.
+ * umax-xdep.c (core_file_command): Replace use of sys_siglist
+ with safe_strsignal.
+ * utils.c (safe_strerror, safe_strsignal): Add functions that
+ call strerror and strsignal respectively, and deal with NULL
+ returns.
+ * utils.c (perror_with_name, print_sys_errmsg): Replace use of
+ sys_errlist with safe_strerror.
+ * valprint.c (val_print): Replace use of sys_errlist with
+ safe_strerror.
+
+Tue Apr 21 12:00:47 1992 K. Richard Pixley (rich@cygnus.com)
+
+ * Makefile.in: rework CFLAGS so that they can be set from the
+ command line to make. CFLAGS -> INTERNAL_CFLAGS.
+ USER_CFLAGS -> CFLAGS. Remove MINUS_G. Default CFLAGS to -g.
+ Pass CFLAGS on recusions.
+
+Fri Apr 17 19:25:57 1992 Fred Fish (fnf@cygnus.com)
+
+ * gdbtypes.h, c-exp.y, m2-exp.y, mipsread.c, gdbtypes.c: Back
+ out of change on 4/14/92 and remove TYPE_FLAG_FUND_TYPE. It was
+ overkill for the problem it solved.
+ * valprint.c (type_print_base): Remove TYPE_FLAG_FUND_TYPE test
+ and default to simply printing type names as appropriate.
+ * main.c (main): Remove one of the leading newlines from
+ warning_pre_print initialization.
+ * objfiles.c (open_existing_mapped_file): Add function and
+ prototype.
+ * objfiles.c (open_mapped_file): Rewrite to use new function
+ open_existing_mapped_file.
+
+Thu Apr 16 23:50:12 1992 John Gilmore (gnu at cygnus.com)
+
+ * sun3-xdep.c (fetch_core_registers): Lint.
+ * tm-sun3.h: Prototype lint.
+ * value.h: Typo.
+
+Thu Apr 16 19:56:50 1992 Fred Fish (fnf@cygnus.com)
+
+ * dwarfread.c (TARGET_FT_POINTER_SIZE, TARGET_FT_LONG_SIZE):
+ Define using TARGET_PTR_BIT and TARGET_LONG_BIT for now.
+ * objfiles.c: Cast calls to close() with unused returns to void.
+ * objfiles.c (allocate_objfile): Initialize objfile's mmfd, free
+ old objfile's name before updating it.
+ * objfiles.c (free_objfile): Major rewrite for mapped objfiles.
+ * objfiles.h (objfile struct): Add mmfd member.
+ * symfile.c (syms_from_objfile): Move some code to
+ new_symfile_objfile.
+ * symfile.c (new_symfile_objfile): Add new function, common code
+ from syms_from_objfile.
+ * symfile.c (symbol_file_add): Call new_symfile_objfile for both
+ mapped and unmapped symbol files.
+ * symfile.c (symbol_file_command): Print "No symbol file now"
+ message, ala exec_file_command for the exec file.
+ * symfile.h (new_symfile_objfile): Add prototype.
+ * xcoffexec.c (map_vmap): Add call to new_symfile_objfile.
+ * xcoffsolib.c (solib_add): Add call to new_symfile_objfile.
+
+Thu Apr 16 18:26:34 1992 Per Bothner (bothner@cygnus.com)
+
+ * rs6000-pinsn.c: New version from IBM (Metin).
+ * m2-exp.y: Re-write string initializers ("<>" => {'<', '>'})
+ to avoid warnings from some compilers.
+
+Tue Apr 14 22:33:55 1992 Fred Fish (fnf@cygnus.com)
+
+ * gdbtypes.h (FT_FIXED_DECIMAL, FT_FLOAT_DECIMAL): Add defines.
+ * gdbtypes.h (TYPE_FLAG_FUND_TYPE): Add define for bit in a
+ type's flag word that marks it as a fundamental type.
+ * c-exp.y (_initialize_c_exp): Add TYPE_FLAG_FUND_TYPE bit to
+ flags argument for all calls to init_type().
+ * m2-exp.y (_initialize_m2_exp): Add TYPE_FLAG_FUND_TYPE bit to
+ flags argument for all calls to init_type(). Also remove
+ dependency on host sizes for ints, floats, etc.
+ * mipsread.c (_initialize_mipsread): Add TYPE_FLAG_FUND_TYPE bit to
+ flags argument for all calls to init_type(). Also remove
+ dependency on host sizes for ints, floats, etc.
+ * gdbtypes.c (lookup_fundamental_type): Add TYPE_FLAG_FUND_TYPE
+ bit to flags argument for all calls to init_type(). Add types
+ FT_FIXED_DECIMAL and FT_FLOAT_DECIMAL.
+ * valprint.c (unsigned_type_table, signed_type_table,
+ float_type_table): Remove.
+ * valprint.c (type_print_base): Test new TYPE_FLAG_FUND_TYPE
+ bit when printing fundamental types, and print the actual name
+ for such types, rather than inventing one. Remove code that
+ invented fundamental type names.
+ * valprint.c (_initialize_valprint): Remove initializations
+ for now removed unsigned_type_table, signed_type_table, and
+ float_type_table.
+
+Tue Apr 14 14:30:46 1992 Stu Grossman (grossman at cygnus.com)
+
+ * remote-vx.c, vx-share/xdr_ptrace.c, vx-share/xdr_ptrace.h,
+ vx-share/xdr_rdb.h: Update for new remote protocol under VxWorks
+ 5.0.2.
+
+Mon Apr 13 20:59:21 1992 Fred Fish (fnf@cygnus.com)
+
+ * dwarfread.c (target_to_host): New function similar to previous
+ swapin function.
+ * dwarfread.c (SWAPIN, swapin): Remove macro and support function.
+ Extensive changes to convert all previous usages to use new
+ target_to_host() function.
+ * dwarfread.c (struct dieinfo): Change types of most integral
+ members to be unsigned.
+
+Mon Apr 13 15:59:10 1992 John Gilmore (gnu at cygnus.com)
+
+ * WHATS.NEW: Revise -mapped doc.
+
+Sat Apr 11 23:14:36 1992 John Gilmore (gnu at cygnus.com)
+
+ * mipsread.c (parse_partial_symbols): Complain when sh->index is
+ too high or when skipping `forwards' moves us backwards.
+ (parse_type): Print mis-guessed tag name in complaint.
+ (parse_external): Eliminate cur_stab and obscure top_stack clobbers.
+ (parse_procedure): Do not attempt to create symbols; just fill in
+ the SYMBOL_VALUE field of a .gdbinfo. symbol if we can find one.
+ (psymtab_to_symtab_1): Split up `stabs' from `native ecoff' code
+ for clarity. Set top_stack before calling parse_external. In
+ stabs, sort symbols before calling parse_procedure.
+ * mipsread.c: Lint.
+ * symmisc.c (std_in, std_out, std_err): Add vars to access std
+ FILE *'s when debugging GDB (e.g. as args to dump_symtab).
+ * Makefile.in: Remove stage* targets. Avoid echo on recursive
+ makes. Eliminate doc/Makefile from tar.Z file if doc/Makefile.in
+ exists.
+
+Fri Apr 10 23:47:37 1992 John Gilmore (gnu at cygnus.com)
+
+ * Makefile.in (VERSION): Set to 4.5.1.
+ * xcoffread.c (NO_TYPEDEFS): Fix typo in commented-out #define.
+ * sparc-tdep.c (supply_gregset, fill_gregset, supply_fpregset,
+ fill_gregset): New functions for SVR4 /proc support.
+ * mipsread.c: Cleanup. Add more complaints for unhandled cases.
+ Remove new symbol types and such to ../include/coff/symconst.h.
+ (parse_symbol): Simplify code for parsing struct/enum/unions.
+ (parse_type): Handle `long long' types.
+ (upgrade_type): Handle `const' qualifier.
+ (parse_partial_symbols): fix indentation, clean a bit.
+
+Fri Apr 10 22:41:03 1992 Fred Fish (fnf@cygnus.com)
+
+ * dwarfread.c (SWAPIN,swapin): New macro and function to call to
+ copy in data from raw read buffers, calling bfd byteswapping
+ routines as appropriate. Use to replace most existing memcpy
+ calls.
+ * dwarfread.c (basicdieinfo, completedieinfo): Add objfile arg.
+ * configure.in: Recognize new ncr3000 config.
+ * config/ncr3000.mh: New config file.
+
+Fri Apr 10 08:30:58 1992 Stu Grossman (grossman at cygnus.com)
+
+ GDB-4.5 release!
+
+ * README: Update for release.
+ * Makefile.in: Update version to 4.5.
+ * WHATS.NEW: The obvious.
+
+ * depend: Generate new depend file for this release.
+
+ * Makefile.in (depend): Fix dependancy generation so that it does
+ not include gcc 'fixincluded' files, which are usually in a system
+ specific location.
+
+Thu Apr 9 13:35:00 1992 Per Bothner (bothner@rtl.cygnus.com)
+
+ Changes from metin@ibmpa.awdpa.ibm.com (Metin G. Ozisik).
+ * buildsym.c (#ifdef RS6000_TARGET): Don't create unnecessary
+ symbols for nameless types. And, handle `R' (register parameter
+ type) for AIX. (an extension to existing stabstring grammar).
+ * rs6000-xdep.c: Fix typo (= should have been ==).
+
+Thu Apr 9 12:10:06 1992 Stu Grossman (grossman at cygnus.com)
+
+ * Makefile.in: version=4.4.88, add xm-vax.h to HFILES.
+
+Thu Apr 9 02:29:03 1992 John Gilmore (gnu at cygnus.com)
+
+ * xm-sun4os5.h (DO_DEFERRED_STORES, CLEAR_DEFERRED_STORES): Zap.
+ * signame.c (SIGWAITING, SIGLWP): Add.
+
+Tue Apr 7 16:34:07 1992 Per Bothner (bothner@cygnus.com)
+
+ * xm-i386mach.h: add decls for errno and strdup().
+
+ * breakpoint.c (breakpoint_1): Add (int) casts for enums
+ used in array index context (otherwise, some compilers barf).
+
+Tue Apr 7 08:45:46 1992 Stu Grossman (grossman at cygnus.com)
+
+ * m68k-tdep.c, tm-sun3.h: #ifdef around get_longjmp_target().
+ Change def of SAVED_PC_AFTER_CALL to call routine to see if we are
+ in a system call, and provide better backtrace if so.
+
+ * Makefile.in (HFILES): Add xcoffsolib.h.
+ * rs6k-opcode.h: Move to ../include/opcode/rs6k.h.
+ * rs6000-pinsn.c: #include "opcode/rs6k.h"
+
+ * mipsread.c (read_mips_symtab, read_the_mips_symtab,
+ mipscoff_symfile_read): Convert to BFD to do file I/O.
+
+ * symfile.c: #include <ctype.h> to get proper def if isspace().
+
+ * i386-tdep.c (get_longjmp_target): #ifdef GET_LONGJMP_TARGET.
+
+Mon Apr 6 17:25:45 1992 Per Bothner (bothner@cygnus.com)
+
+ * mipsread.c: Create a .gdbinfo pseudo-symbol for each
+ function also when parsing embedded stabs.
+
+Mon Apr 6 15:25:03 1992 Stu Grossman (grossman at cygnus.com)
+
+ * mipsread.c: Fix more declarations.
+
+ * mipsread.c: Fix many invocations of complain. Use enum
+ type_code where appropriate.
+
+ * xm-vaxult.h: Add decl for strdup().
+
+ * Makefile.in: Add dependancies for xm-vaxbsd.h and xm-vaxult.h
+ for xm-vax.h.
+
+Fri Apr 3 17:41:29 1992 Stu Grossman (grossman at cygnus.com)
+
+ * buildsym.h, dbxread.c, mipsread.c: Add objfile arg to
+ process_one_symbol.
+
+Fri Apr 3 12:17:14 1992 Per Bothner (bothner@cygnus.com)
+
+ * munch: Must pre-pend "_" to "initialize" for SYSV style nm.
+ * tm-rs6000.h, xcoffexec.c, xcoffread.c, xm-rs6000.h:
+ Merge in more patches for rs6000 from Metin Ozisik.
+ * utils.c: Fix typo in comment.
+
+Fri Apr 3 11:23:03 1992 Fred Fish (fnf@cygnus.com)
+
+ * procfs.c (procinfo struct): Add nopass_next_sigstop member.
+ * procfs.c (attach): Set nopass_next_sigstop if attached
+ process is forcibly stopped.
+ * procfs.c (child_resume): Use nopass_next_sigstop to suppress
+ resending SIGSTOP to attached process on first resume.
+
+Fri Apr 3 01:37:26 1992 Stu Grossman (grossman at cygnus.com)
+
+ * Makefile.in (SFILES_MAINDIR): add mipsread.c
+
+Thu Apr 2 20:20:54 1992 John Gilmore (gnu at cygnus.com)
+
+ * Makefile.in (OBS): Compile mipsread.c for all targets now.
+ (VERSION): Bump to 4.4.85.
+ * mipsread.c: Update for new include files. Lint.
+ * tm-irix3.h, tm-mips.h: Use new include files for ECOFF symtab.
+ * config/{bigmips.mt, littlemips.mt, irix3.mt, decstation.mt}:
+ Don't need to bring in mipsread.o specially any more.
+
+Thu Apr 2 19:38:31 1992 Stu Grossman (grossman at cygnus.com)
+
+ * mipsread.c (fixup_sigtramp): Also look for _sigtramp as a real
+ routine (for Irix-4.x). Make many funcs static and void.
+ * mips-tdep.c (mips-frame-chain): Clean up, simplify.
+ * (init_extra_frame_info): Don't trash cached value of frame
+ pointer register. This fixes backtracing through routines that use
+ alloca(). Generally clean up declarations of functions, and use
+ typedefs and macros to reference data structures as appropriate.
+ * tm-irix3.h, tm-mips.h (EXTRA_FRAME_INFO): use proper type for
+ proc_desc element.
+
+Thu Apr 2 09:47:11 1992 Fred Fish (fnf@cygnus.com)
+
+ * values.c (unpack_long): Fix unpacking error for signed chars
+ on hosts where the default character type is unsigned.
+ * procfs.c (pr_flag_table, pr_why_table): Add some entries
+ for newer SVR4 variants.
+ * procfs.c (proc_set_exec_trap): Reorder tests for ioctl's that
+ turn off trace inherit-on-fork flag to favor latest SVR4 method.
+ * procfs.c (mappingflags): Add support for MA_PHYS
+
+Thu Apr 2 00:55:56 1992 John Gilmore (gnu at cygnus.com)
+
+ * buildsym.c (read_struct_type): Avoid coredump when C++
+ abbreviated type name is messed up. Reported by Joe Buck.
+ FIXME, we need to determine whether GDB or GCC needs to be
+ smarter to correctly locate this type name.
+
+ * c-exp.y, coffread.c, command.c, command.h, copying.awk,
+ dbxread.c, gdbtypes.c, infcmd.c, inferior.h, infrun.c,
+ m2-exp.y, printcmd.c, remote.c, solib.c, source.c, stack.c,
+ symtab.c, tm-sun4os4.h, tm-sun4os5.h, values.c: Lint.
+ * symfile.c (add_symbol_file_command): Initialize mapped/readnow.
+
+Wed Apr 1 11:39:52 1992 Fred Fish (fnf@cygnus.com)
+
+ * breakpoint.h (bpdisp, bptype): Remove trailing comma.
+ * symtab.h (current_source_symtab): Make extern
+ * symtab.h (current_source_line): Make extern
+ * inferior.h: Move all procfs.c prototypes to one place, add
+ prototype for proc_signal_handling_change. Add prototypes for
+ signal_stop_state, signal_print_state, and signal_pass_state.
+ * inferior.h (stop_soon_quietly): Make extern
+ * inferior.h (attach_flag): Make extern
+ * infrun.c (NOTICE_SIGNAL_HANDLING_CHANGE): Default is null.
+ * infrun.c (signal_stop_state, signal_print_state,
+ signal_pass_state): New functions to query specific signal
+ handling flags.
+ * infrun.c (handle_command): Minor error message change, add
+ NOTICE_SIGNAL_HANDLING_CHANGE.
+ * procfs.c (open_proc_file): Remove iris specific reset of
+ inherit-on-fork flag, moved to proc_set_exec_trap().
+ * procfs.c (proc_set_exec_trap): Add SVR4 and iris code
+ to reset inherit-on-fork flag, bash comment to GNU form.
+ * procfs.c (proc_base_address, set_proc_siginfo,
+ fetch_core_registers): Conform to code style.
+ * procfs.c (signame.h): Include.
+ * procfs.c (MAX_SYSCALLS, syscall_table[], init_syscalltable(),
+ syscallname(), info_proc_syscalls()): New macros, tables, and
+ functions to organize and report system call information.
+ * procfs.c (saved_fltset, saved_trace, saved_sighold,
+ saved_exitset, saved_entryset): Add to procinfo struct.
+ * procfs.c (struct trans): Add.
+ * procfs.c (pr_flag_table, pr_why_table, faults_table,
+ siginfo_table, errno_table): Tables to translate numeric values
+ to symbolic names and short descriptions.
+ * procfs.c (signalname, info_proc_signals): Add function and
+ prototype.
+ * procfs.c (proc_info): Now info_proc.
+ * procfs.c (proc_info_address_map): Now info_proc_mappings.
+ * procfs.c (info_proc_flags, info_proc_stop, info_proc_siginfo,
+ info_proc_faults, lookupname, lookupdesc, sigcodename,
+ sigcodedesc): New functions.
+ * procfs.c (proc_signal_handling_change): New function to set
+ the trace flags based on the state of gdb's signal handling flags.
+ * procfs.c (inferior_proc_init): Call proc_signal_handling_change
+ and remove code to do PIOCSTRACE ioctl.
+ * procfs.c (attach, detach): Preserve and restore process flags
+ using saved_* fields in procinfo struct.
+ * procfs.c (attach): Call proc_signal_handling_change.
+ * procfs.c (info_proc): Major rework to expand "info proc" cmd.
+ * procfs.c (proc_desc): Update for latest changes.
+ * xm-irix4.h (CREATE_INFERIOR_HOOK): Protect by USE_PROC_FS.
+ * xm-irix4.h (NOTICE_SIGNAL_HANDLING_CHANGE): Add definition.
+ * xm-sysv4.h (NOTICE_SIGNAL_HANDLING_CHANGE): Add definition.
+
+Tue Mar 31 18:38:28 1992 Fred Fish (fnf@cygnus.com)
+
+ * procfs.c (set_proc_siginfo): Add prototype and new function.
+ * procfs.c (detach, child_resume): Call set_proc_siginfo to set
+ up inferior siginfo struct.
+ * elfread.c (elf_symfile_read): Compute the relocation amount
+ by subtracting off the address of the ".text" section.
+ * solib.c: Add pointer to ".text" section to so_list struct.
+ * solib.c (solib_map_sections): Initialize pointer to ".text"
+ section in so_list struct.
+ * solib.c (symbol_add_stub): Pass base address of ".text"
+ section to symbol_file_add, rather than the load address of
+ the shared library. On SunOS they are the same. On SVR4 they
+ are not.
+
+Tue Mar 31 17:48:15 1992 Stu Grossman (grossman at cygnus.com)
+
+ * mipsread.c (parse_procedure): PDR.isym should get pointer to
+ function name, not .gdbinfo. symbol.
+
+Tue Mar 31 17:05:04 1992 John Gilmore (gnu at cygnus.com)
+
+ * breakpoint.c (breakpoint_1): Fix prototype, this time for sure!
+
+Tue Mar 31 11:01:06 1992 Stu Grossman (grossman at cygnus.com)
+
+ * Makefile.in (VERSION): 4.4.8
+
+ * procfs.c (open_proc_file): Disable inherit-on-fork flag so that
+ commands in .cshrc/.profile won't get traced.
+
+Tue Mar 31 08:11:58 1992 John Gilmore (gnu at cygnus.com)
+
+ * elfread.c (elf_symtab_read): Use xmalloc, not bfd_xmalloc.
+ * exec.c (build_section_table): Don't abort if no sections.
+ * sparc-tdep.c (single_step): Lint.
+ * utils.c (mrealloc): Handle realloc (0, size) case here.
+
+Mon Mar 30 16:50:43 1992 Stu Grossman (grossman at cygnus.com)
+
+ * Makefile.in (alldeps.mak): Config files are now *.m[ht] as
+ opposed to m[ht]-*!
+
+ * config/irix4.mh: Don't use coredep.o. It doesn't work with procfs.
+
+ * mipsread.c (parse_symbol, parse_procedure): Re-do the way that
+ .gdbinfo. symbols are created. Move creation from parse_procedure
+ to parse_symbol, where it is fairly easy to grow the symtab. This
+ also fixes a symtab trashing bug on all mips-based systems.
+ * (got_numargs, lookup_numargs, free_numargs): Delete. Not
+ needed anymore.
+ * tm-mips.h, tm-iris3.h, mips-tdep.c, mipsread.c: Re-do struct
+ mips_extra_func_info, and all the PROC_xxx macros that look at it.
+
+Mon Mar 30 14:17:53 1992 Per Bothner (bothner@cygnus.com)
+
+ * c-exp.y: Add missing return type to yyparse() prototype.
+
+Sat Mar 28 22:22:06 1992 John Gilmore (gnu at cygnus.com)
+
+ Create and use macros for iterating on symtabs, psymtabs, msymbols.
+
+ * minsyms.c (iterate_over_msymbols): Remove; clunky and slow.
+ * symfile.h, symtab.h (iterate_over_msymbols): Remove prototype
+ * coffread.c (coff_symfile_read): iterate_over_symtabs => ALL_SYMTABS.
+ (patch_opaque_types): Avoid dummy args and result.
+ * objfiles.c (have_partial_symbols, have_full_symbols,
+ have_minimal_symbols): explicit iteration => ALL_OBJFILES; simplify.
+ (iterate_over_objfiles, iterate_over_symtabs,
+ iterate_over_psymtabs): Remove, clunky and slow.
+ * objfiles.h: Replace iterate_over_* prototypes with ALL_SYMTABS,
+ ALL_PSYMTABS, and ALL_MSYMBOLS macros.
+ * symmisc.c (dump_symtab, dump_psymtab, dump_msymbols,
+ dump_objfile): Remove dummy args and results. Move filename
+ comparisons to callers.
+ (printsyms_command, printpsyms_command, printmsyms_command,
+ printobjfiles_command): iterate_over_* => ALL_*. Compare filenames.
+ * symtab.c (lookup_symtab_1, lookup_symtab, lookup_partial_symtab,
+ lookup_symbol, find_main_psymtab, find_pc_symtab, sources_info,
+ list_symbols, make_symbol_completion_list): Replace explicit
+ iteration with ALL_SYMTABS, ALL_PSYMTABS, or ALL_MSYMBOLS.
+ Eliminate Dijkstra flag crap, break out of loops with gotos.
+ (lookup_symtab_1): Protect '/' tests from short filenames.
+ (cplus_mangled_symbol): Move inline into lookup_symbol.
+ * xcoffexec.c (relocate_objfile_msymbols): Remove poor hack.
+ (relocate_minimal_symbol): Move inline to vmap_symtab.
+ (vmap_symtab): Replace iteration with ALL_OBJFILES,
+ iterate_over_msymbols with ALL_MSYMBOLS.
+
+ Misc cleanup prior to release.
+
+ * Makefile.in (VERSION): Roll to 4.4.7.
+ (HFILES): Add call-cmds.h.
+ * call-cmds.h: New header for command fns called by other files.
+ * breakpoint.c (watchpoints_info): Remove, same as breakpoints_info.
+ (breakpoint_1): Remove unused type arg. Change callers.
+
+ * dwarfread.c (dwarf_build_psymtabs): Remove mainline test.
+ * mipsread.c (compare_symtabs, compare_psymtabs): Remove, unused.
+ * mipsread.c: Add prototypes for all static functions.
+
+ * symmisc.c (dump_symtab_lines, dump_symtabs, dump_last_symtab,
+ dump_blockvector, dump_block, dump_addrchass, dump_namespace,
+ dump_symbol, dump_type, dump_linetable, dump_strtbl): Remove, unused.
+ * xcoffread.c (dump_symtab_lines, dump_symtabs, dump_last_symtab,
+ dump_blockvector, dump_block, dump_addrchass, dump_namespace,
+ dump_symbol, dump_type, dump_linetable, dump_strtbl): Remove 2nd
+ unused copy!
+
+ * buildsym.c (define_symbol): Handle global register variables
+ (from Pierre Willard). Complain if register numbers are too large.
+ * target.c (nomemory): Now that higher levels examine errno, give EIO.
+ * tm-sparc.h: Don't #include <sun4/reg.h>.
+ * sparc-tdep.c (sparc_frame_chain, frame_saved_pc): Remove
+ dependency on <sun4/reg.h>. Start to handle cross-byte-order.
+
+ * language.h: Avoid forward enum declaration.
+ * configure.in, tm-sun4os5.h, xm-sun4os5.h, config/sun4os5.mh,
+ config/sun4os5.mt: New host and target.
+ * defs.h (errno): #include <errno.h> rather than assuming int.
+ From Pierre Willard.
+
+ * breakpoint.c, breakpoint.h, buildsym.c, coffread.c, cplus-dem.c,
+ dbxread.c, dwarfread.c, elfread.c, infcmd.c, infrun.c, inftarg.c,
+ language.c, main.c, mem-break.c, mips-tdep.c, mipsread.c,
+ partial-stab.h, remote.c, saber.suppress, symfile.c, symtab.c,
+ valops.c, valprint.c, xcoffread.c, c-exp.y, m2-exp.y, blockframe.c,
+ command.c, core.c, exec.c, gdbtypes.h, parse.c, printcmd.c, solib.c,
+ sparc-xdep.c, utils.c, value.h, values.c: Lint.
+
+Sat Mar 28 02:43:26 1992 John Gilmore (gnu at cygnus.com)
+
+ * buildsym.c (read_range_type): Avoid int overflow by using unsigned.
+ * dbxread.c (dbx_symfile_init): Remove bogus `lvalue cast'.
+ * language.h (enum exp_opcode): Avoid forward enum def.
+ * main.c (define_command, user_defined_command): Lint.
+ * mem-break.c, xcoffread.c: Lint.
+ * solib.c: Only #include <a.out.h> on SunOS, not SVR4.
+
+Sun Mar 29 14:16:22 1992 Per Bothner (bothner@cygnus.com)
+
+ * Merged in latest RS6000 diffs from Metin G. Ozisik.
+ * xcoffsolib.c, xcoffsolib.h: New files, from Metin.
+ * Various files: Changed #ifdef IBM6000 to IBM6000_HOST
+ or IBM6000_TARGET as (approximately) appropriate.
+
+Sat Mar 28 13:00:10 1992 Fred Fish (fnf@cygnus.com)
+
+ * objfiles.h (OBJF_SYMS): Define flag bit for objfile flags.
+ * symfile.c (symbol_file_add): Use OBJF_SYMS to decide whether
+ or not to try reading symbols from a mapped objfile. Plugs memory
+ leak due to shared libraries generating no psymtabs or symtabs.
+
+Fri Mar 27 15:44:55 1992 John Gilmore (gnu at cygnus.com)
+
+ * buildsym.c (MAX_OF_C_TYPE, MIN_OF_C_TYPE): Unused, remove.
+ * copying.awk: Lint. Make stronger warning at top of copying.c.
+ * elfread.c (elf_symtab_read): Eliminate check of mainline.
+ * gdbtypes.c (smash_to_*): Remove FIXME comments.
+ (lookup_pointer_type): Add FIXME comment.
+ * main.c (set_history_size_command): Disallow negative size.
+ * partial-stab.h: Update copyright.
+ * rs6000-tdep.c (skip_trampoline_code): Better comments.
+
+Wed Mar 25 10:45:38 1992 John Gilmore (gnu at cygnus.com)
+
+ * main.c (set_history_size_command): Negative size is error.
+ (Reported by Peggy Fieland.)
+
+Thu Mar 26 17:01:18 1992 Fred Fish (fnf@cygnus.com)
+
+ * coffread.c (coff_symfile_init): Update comment.
+ * dbxread.c (DBX_SYMFILE_INFO, DBX_TEXT_SECT, DBX_SYMCOUNT,
+ DBX_STRINGTAB, DBX_STRINGTAB_SIZE, DBX_SYMTAB_OFFSET): Define
+ macros to access the dbx specific objfile information.
+ * dbxread.c (symfile_string_table, symfile_string_table_size):
+ Remove these local variables.
+ * dbxread.c (read_ofile_symtab, psymtab_to_symtab_1,
+ read_dbx_symtab): Remove the stringtab and stringtab_size params
+ from the function prototypes, the function definition, and the
+ function calls. These are now available via DBX_STRINGTAB and
+ DBX_STRINGTAB_SIZE using the objfile pointer.
+ * dbxread.c (dbx_symfile_read): Relocate addr before using as
+ an arg to read_dbx_symtab.
+ * dbxread.c (dbx_symfile_read): Remove code that free'd the
+ stringtab and the dbx specific per-objfile private info.
+ * dbxread.c (init_psymbol_list): Remove symbol count from passed
+ args in prototype, function definition, and function calls. It is
+ now available via the DBX_SYMCOUNT macro using the objfile
+ pointer.
+ * dbxread.c (dbx_symfile_read, dbx_symfile_init): Remove the
+ local instance of struct dbx_symfile_info and replace with DBX_*
+ macros.
+ * dbxread.c (dbx_symfile_read): Remove init's of now deleted
+ symfile_string_table and symfile_string_table_size.
+ * dbxread.c (dbx_symfile_finish): Remove now obsolete free of
+ symfile_string_table.
+ * dbxread.c (init_psymbol_list): Use DBX_SYMCOUNT.
+ * dbxread.c (dbx_psymtab_to_symtab): Remove local stringtab and
+ stringtab size variables. Remove all code that used to reread
+ the stringtab.
+ * objfiles.c (allocate_objfile): Move calls to init_malloc()
+ to prior to any calls to mmalloc for the objfile specific heap.
+ * utils.c (init_malloc): Document the requirement that for each
+ heap for which corruption checking is desired, that init_mmalloc
+ must be called prior to any mmalloc calls on the heap.
+
+Thu Mar 26 13:20:06 1992 Per Bothner (bothner@cygnus.com)
+
+ * rs6000-pinsn.c: Make dis-assembly output more like
+ other targets: Don't print instruction in hex before
+ the assembly; use print_address to print out jump
+ destinations.
+
+Wed Mar 25 16:52:35 1992 Per Bothner (bothner@cygnus.com)
+
+ * c-exp.y, gdbtypes.h: Add builtin_type_signed_char.
+ * cplus-dem.c: Support "Sc" meaning "signed char".
+
+Wed Mar 25 15:21:44 1992 Stu Grossman (grossman at cygnus.com)
+
+ * configure.in: fix iris/iris3.
+
+Wed Mar 25 14:55:48 1992 Per Bothner (bothner@cygnus.com)
+
+ * command.c, main.c (various places): Use ctype.h macros
+ (such as isupper(x)), instead of hard-wiring in ASCII-isms
+ (such as (x >= 'A' && x <= 'Z')).
+ (There are still more of these in other files.)
+ * main.c (defined_command): Lower-case the user's
+ new command before entering it. Needed because
+ command lookup is case-insensitive (and also lower-cases).
+ (Based on Metin's earlier patch.)
+
+Tue Mar 24 23:27:01 1992 K. Richard Pixley (rich@cygnus.com)
+
+ * config/irix4.mh: new file.
+
+Tue Mar 24 14:17:48 1992 Stu Grossman (grossman@cygnus.com)
+
+ * infcmd.c (step_1): Call disable_longjmp_breakpoint at the right
+ time.
+
+ * xm-mips.h: Declare strdup for ultrix.
+
+ * mipsread.c (fixup_sigtramp): Make sure that current_objfile is setup
+ when calling new_symbol.
+ * mips-tdep.c (mips_frame_chain): Use symfile_objfile instead of
+ current_objfile.
+
+Tue Mar 24 13:26:25 1992 Per Bothner (bothner@rtl.cygnus.com)
+
+ * config/rs6000.mh: Update (for Fred's new mmalloc)
+ flags to disable use of GNU malloc/mmalloc.
+ * munch: Change SYSV rule to allow .text before the label,
+ as well as after, to work for AIX.
+ * gdbtypes.h: Minor clarifiction.
+
+Tue Mar 24 07:26:19 1992 Michael Tiemann (tiemann@cygnus.com)
+
+ * buildsym.c (read_struct_type): Handle cretinous dbx symbol name
+ continuation in yet another place (between method declarations).
+
+Mon Mar 23 23:01:41 1992 Stu Grossman (grossman at cygnus.com)
+
+ * mips-tdep.c: include symfile.h and objfiles.h to fix
+ compilation errors.
+
+Mon Mar 23 15:49:14 1992 Per Bothner (bothner@cygnus.com)
+
+ * valops.c (value_struct_elt_for_reference): Added 'offset'
+ parameter to handle multiple inheritance.
+ * eval.c, value.h: Update accordingly.
+
+Fri Mar 20 17:43:27 1992 Fred Fish (fnf@cygnus.com)
+
+ * objfiles.h: New file
+ * Makefile.in (HFILES): Add objfiles.h
+ * blockframe.c: Remove entry_scope_lowpc, entry_scope_highpc,
+ main_scope_lowpc, main_scope_highpc.
+ * blockframe.c, buildsym.c, coffread.c, dbxread.c, dwarfread.c,
+ elfread.c, gdbtypes.h, minsyms.c, mipsread.c, objfiles.c, solib.c,
+ source.c, symfile.c, symmisc.c, symtab.c, target.c, xcoffexec.c,
+ xcoffread.c, : Include objfiles.h.
+ * tm-29k.h, tm-i386v.h, tm-merlin.h, tm-rs6000.h, tm-sun386.h,
+ tm-symmetry.h, tm-tahoe.h, tm-umax.h, tm-vax.h, m88k-tdep.c,
+ mips-tdep.c (FRAME_CHAIN): Renamed outside_startup_file to
+ inside_entry_file() and logic changed appropriately.
+ * blockframe.c (outside_startup_file): Renamed to
+ inside_entry_file() and logic changed appropriately.
+ * blockframe.c (inside_main_scope): Renamed to inside_main_func()
+ and logic changed to use per-objfile specific fields.
+ * blockframe.c (inside_entry_scope): Renamed to
+ inside_entry_func() and logic changed to use per-objfile specific
+ fields.
+ * blockframe.c, buildsym.h, coffread.c, dwarfread.c, mipsread.c,
+ symfile.c, mips-tdep.c (startup_file_start, startup_file_end):
+ Remove extern decls.
+ * symfile.c, symfile.h (entry_point): Remove extern decl.
+ * coffread.c (coff_symfile_init): Common entry point init code
+ moved to symfiles.c, call init_entry_point_info().
+ * coffread.c (complete_symtab): Use new per-objfile entry info.
+ * mip-tdep.c (mips_frame_chain): Use new per-objfile entry info.
+ * mipsread.c (parse_partial_symbols): Use new per-objfile entry
+ info.
+ * dbxread.c (read_dbx_symtab): Use new per-objfile entry info.
+ * defs.h (inside_entry_scope, outside_startup_file,
+ inside_main_scope): Prototypes changed for renames to
+ inside_entry_func, inside_entry_file, inside_main_func,
+ respectively.
+ * symfile.c (syms_from_objfile): Common entry point init code
+ moved to init_entry_point_info() and call init_entry_point_info().
+ * symfile.h (init_entry_point_info): Include prototype.
+ * xcoffread.c (aixcoff_symfile_init): Common entry point init code
+ moved to symfiles.c and call init_entry_point_info().
+ * dwarfread.c (entry_scope_lowpc, entry_scope_highpc,
+ main_scope_lowpc, main_scope_highpc): Remove extern decls.
+ * dwarfread.c (read_func_scope, read_file_scope): Use new per-
+ objfile entry info.
+ * frame.h (FRAME_CHAIN_VALID): Provide default definition that
+ works for the majority of targets.
+ * tm-68k.h, tm-convex.h, tm-h8300.h, tm-i386v.h, tm-irix3.h,
+ tm-merlin.h, tm-mips.h, tm-pyr.h, tm-rs6000.h, tm-sparc.h,
+ tm-sun386.h, tm-tahoe.h, tm-umax.h, tm-vax.h (FRAME_CHAIN_VALID):
+ Use default definition in frame.h.
+ * frame.h (selected_frame_level): Make decl extern.
+ * objfiles.c, symfile.c (current_objfile): Moved to objfiles.c
+ * objfiles.c, symfile.c (symfile_objfile): Moved to objfiles.c
+ * partial-stab.h: Use new per-objfile entry info.
+ * symfile.h (struct objfile): Removed, moved to objfiles.h.
+ * symfile.h, objfiles.h (allocate_objfile, free_objfile,
+ free_all_objfiles, iterate_over_objfiles, iterate_over_symtabs,
+ iterate_over_psymtabs, have_partial_symbols, have_full_symbols,
+ have_minimal_symbols): Prototypes moved to objfiles.h.
+ * symfile.h, objfiles.h (ALL_OBJFILES, ALL_OBJFILES_SAFE):
+ Macros moved to objfiles.h.
+ * tm-h8300.h, tm-i386v4.h (FRAME_CHAIN_VALID_ALTERNATE): Define.
+
+Thu Mar 19 18:49:45 1992 Per Bothner (bothner@cygnus.com)
+
+ More C++ improvements (pointers to members, qualified names).
+ * c-exp.y: Support exp.type::name and exp->type::name
+ syntaxes. (Unfortunately, doesn't work for static members.)
+ * c-exp.y, eval.c: Make type::~type work better.
+ * eval.c (evaluate_subexp: OP_SCOPE): Replace use of
+ value_static_field by value_struct_elt_for_reference.
+ * eval.c (evaluate_subexp): Merge code for STRUCTOP_MEMBER
+ and STRUCTOP_MPTR; cast arg1 to domain-type of arg2.
+ * eval.c (evaluate_subexp): Remove special case for UNOP_ADDR
+ for OP_SCOPE operand; no point in it now that we use lazy
+ reading of values, and use "reference to member" objects.
+ * gdbtypes.h: Clarify comment.
+ * valops.c: Change value_struct_elt_for_address to return
+ a reference (or variable), rather than a pointer. Change
+ the name to value_struct_elt_for_reference to reflect this.
+ Returning a reference instead of a address provides a
+ generalization, since we can use the routine for both
+ class::name as well as &class::name.
+ Also, recurse to handle multiple inheritance properly.
+ * valprint.c: Moved code to print pointer-to-members
+ to new function point_class_member. This allows a
+ "reference-to-member" to be printed using the same code.
+ * valprint.c (type_print_varspec_prefix): Avoid printing
+ "struct " for domains of class-member types.
+ * valops.c (search_struct_field): Inline code for simplified
+ version of value_static_field (which can then be deleted).
+ * value.h: Rename value_struct_elt_for_address to
+ value_struct_elt_for_reference. Delete value_static_field.
+ * values.c: Remove no longer used function value_static_field.
+
+Thu Mar 19 13:54:11 1992 Fred Fish (fnf@cygnus.com)
+
+ * coffread.c, mipsread.c, xcoffread.c, coffread.c, dbxread.c,
+ elfread.c (coff_symfile_finish): Add function, prototype, and
+ add to the xxxx_sym_fns struct for each file type. Also reformat
+ the xxxx_sym_fns vector to a standard format and add comments.
+ * coffread.c, mipsread.c, xcoffread.c, coffread.c, dbxread.c,
+ elfread.c (xxx_symfile_new_init, xxx_symfile_init, xxx_symfile_read):
+ Pass pointer to struct objfile rather than pointer to sym_fns.
+ Change references inside each function accordingly. Allocate any
+ symbol file specific info in the per-objfile memory region.
+ * dbxread.c (free_and_init_header_files): Break function into
+ free_header_files(), called from dbx_symfile_finish(), and
+ init_header_files(), called from dbx_new_init().
+ * dbxread.c (dbx_new_init): Move deallocation things to new
+ dbx_symfile_finish function.
+ * elfread.c (elf_new_init): Call buildsym_new_init().
+ * objfiles.c (free_objfile): Call the appropriate symfile_finish()
+ routine for the objfile before deallocating other stuff.
+ * sparc-tdep.c (get_longjmp_target): Cast target_read_memory arg.
+ * symfile.h: Move struct sym_fns to before struct objfile def.
+ Add sym_finish function pointer and change prototypes of other
+ function pointers to reflect passing struct objfile pointer rather
+ than struct sym_fns pointer.
+ * symfile.c: Remove now obsolete symtab_fns pointer.
+ * symfile.c (symfile_init): Renamed to find_sym_fns, and now only
+ locates the correct sym_fns struct for the given objfile.
+ * symfile.c (syms_from_objfile, symbol_file_add): Restructured
+ for better support of mapped symbol tables.
+ * symfile.c (symbol_file_command): Remove obsolete code using
+ symfile_fns.
+ * symfile.h: Remove duplicate declarations for symfile_objfile,
+ entry_point, and object_files.
+ * target.c (target_info): Compare symfile_objfile to NULL.
+ * xcoffread.c (aixcoff_new_init): Move deallocation stuff to
+ aixcoff_symfile_finish().
+
+Wed Mar 18 18:22:46 1992 Fred Fish (fnf@cygnus.com)
+
+ * infrun.c (IN_SOLIB_TRAMPOLINE): Add default definition.
+ * infrun.c (wait_for_inferior): Use IN_SOLIB_TRAMPOLINE.
+ * tm-sysv4.h (IN_SOLIB_TRAMPOLINE): Add SVR4 definition.
+
+Wed Mar 18 15:51:15 1992 Per Bothner (bothner@cygnus.com)
+
+ Some improvements to g++ debugging.
+ * symtab.c (list_symbols): demangle before pattern matching.
+ * symtab.c: Other fixes to improve handing of operators.
+ * valprint.c (type_print_base): Fix test for constructor.
+ * values.c (value_static_field): Allow evaluation of
+ CLASS::METHOD, returning a function pointer.
+
+Wed Mar 18 08:39:52 1992 Fred Fish (fnf@cygnus.com)
+
+ * Makefile.in (VERSION): Roll 4.4.6.
+ * exec.c (exec_file_command): Add code to ignore optional args
+ passed in by file_command() for use in symbol_file_command().
+ * main.c (main): Document -mapped and -readnow in help summary.
+ * objfiles.c (open_mapped_file): Cosmetic change, arg renamed.
+ * objfiles.c (allocate_objfile): Filename arg removed. Changes
+ to get filename from bfd with bfd_get_filename(). Test mapto
+ against 0, not NULL. Use mstrsave() to make copy of filename.
+ * remote-mm.c (mm_load): Symbol_file_add() takes an additional
+ arg.
+ * remote-vx.c (vx_load_command, add_symbol_stub):
+ Symbol_file_add() takes an additional arg.
+ * solib.c (symbol_add_stub): Symbol_file_add() takes an
+ additional arg.
+ * symfile.c (symfile_open): Renamed to symfile_bfd_open and
+ changed to return a bfd not an objfile pointer.
+ * symfile.c (syms_from_objfile): Eliminate local copy of bfd.
+ * symfile.c (symbol_file_add): Takes an additional arg (readnow).
+ Change to eliminate local bfd and use symfile_bfd_open() plus
+ allocate_objfile(). Add code to implement readnow option.
+ * symfile.c (symbol_file_command): Changes to option handling,
+ readnow functionality moved to symbol_file_add().
+ * symfile.c (symfile_init): Eliminate local copy of bfd.
+ * symfile.c (add_symbol_file_command): Changes to parse mapped
+ and readnow options.
+ * symfile.h (allocate_objfile): Arg removed from prototype.
+ * symtab.h (symbol_file_add): Arg added to prototype.
+ * xcoffexec.c (map_vmap): Allocate_objfile() takes an additional
+ arg.
+
+Sat Mar 14 16:38:47 1992 Fred Fish (fnf@cygnus.com)
+
+ * gmalloc.c, gmalloc.h mcheck.c mmap-alloc.c mmap-sbrk.c mtrace.c,
+ mtrace.awk, state.c, state.h: Removed.
+ * .gdbinit: Add ../malloc, ../libiberty, and ../bfd to list of
+ directories searched for source files.
+ * Makefile.in (GNU_MALLOC, MALLOC_CFLAGS, MALLOCSRC): Removed
+ * Makefile.in (MMALLOC_DIR, MMALLOC_DEP, MMALLOC_LIB,
+ MMALLOC_DISABLE, MMALLOC_CHECK, MMALLOC_CFLAGS): Add
+ * Makefile.in (CFLAGS): Replace MALLOC_CFLAGS with MMALLOC_CFLAGS.
+ * Makefile.in (CLIBS, CDEPS): Add MMALLOC_LIB
+ * Makefile.in (ADD_FILES, ADD_DEPS): Remove GNU_MALLOC.
+ * Makefile.in (SFILES_MAINDIR): Remove stat.c mmap-alloc.c, mmap-
+ sbrk.c
+ * Makefile.in (HFILES): Remove state.h
+ * Makefile.in (POSSLIBS_MAINDIR): Remove MALLOCSRC.
+ * Makefile.in (OBS): Remove state.o mmap-alloc.o mmap-sbrk.o
+ * Makefile.in (saber_gdb): Remove mcheck, mtrace. Add MMALLOC_DIR.
+ * Makefile.in (clean): Remove all object files.
+ * c-exp.y: Define malloc to xmalloc and realloc to xrealloc.
+ * cplus-dem.c: Remove prototypes definitions that are now done in
+ def.h.
+ * dbxread.c (throughout): Change from using per-objfile
+ xmalloc/xrealloc/free functions to xmmalloc/xmrealloc/mfree.
+ * defs.h: Remove prototypes for mmap_* functions. Add prototypes
+ for xmmalloc, xmrealloc, mfree, mmcheck, mmtrace, mmalloc_attach,
+ mmalloc_detach, mmalloc_setkey, msavestring, and mstrsave, nomem.
+ * depend: Remove dependencies for state.o, state.h.
+ * dwarfread.c: Add declaration for warning_pre_print.
+ * dwarfread.c (dwarfwarn): Use warning_pre_print.
+ * dwarfread.c (throughout): Change from using per-objfile
+ xmalloc/xrealloc/free functions to xmmalloc/xmrealloc/mfree.
+ * gdbtypes.c (lookup_fundamental_type): Fix init_type calls to
+ use supplied objfile.
+ * i386-xdep.c (print_387_status): Change to use warning() rather
+ than printfs.
+ * i387-tdep.c (print_387_control_word): Change to use warning()
+ rather than printfs.
+ * infrun.c (wait_for_inferior): Remove unreachable abort() call
+ that some compilers grumble about.
+ * language.c (throughout): Add declaration for warning_pre_print
+ and using warning() instead of printfs.
+ * m2-exp.y: Define malloc to xmalloc and realloc to xrealloc.
+ * main.c (main): Add declaration for warning_pre_print and set it
+ similarly to error_pre_print. Add declarations for
+ mapped_symbol_files and readnow_symbol_files. Add appropriate
+ definitions to long_options[].
+ * minsyms.c: Trivial fix to comment.
+ * objfiles.c (allocate_objfile): Substantially rewritten for
+ using mapped symbol files.
+ * objfiles.c (throughout): Change from using per-objfile
+ xmalloc/xrealloc/free functions to xmmalloc/xmrealloc/mfree.
+ * objfiles.c (open_mapped_file, mapped_to_address): Add functions.
+ * source.c (throughout): Change from using per-objfile
+ xmalloc/xrealloc/free functions to xmmalloc/xmrealloc/mfree.
+ * source.c (open_source_file): Use mstrsave to save file name in
+ mapped symbol region for objfile.
+ * symfile.c: Remove include for state.h.
+ include to local form.
+ * symfile.c (symbol_file_add_digested): Remove.
+ * symfile.c (symbol_file_add): Substantially rewritten for mapped
+ symbol files.
+ * symfile.h: Remove malloc/xrealloc/xmalloc/xrealloc/free members
+ from objfile structure. Add malloc descriptor pointer (md).
+ * symfile.h (OBJF_DUMPABLE): Changed name to OBJF_MAPPED.
+ * symm-xdep.c (print_fpu_status): Use warning() rather than
+ printfs.
+ * symmisc.c (free_symtab_block): Now takes and uses current
+ objfile pointer.
+ * symmisc.c (throughout): Change from using per-objfile
+ xmalloc/xrealloc/free functions to xmmalloc/xmrealloc/mfree.
+ * symtab.c (cplus_mangled_symbol): Cast return value to avoid
+ Sun compiler grumblings when PTR is char *.
+ * symtab.c (lookup_symbol): Cast return value of iterate_over_
+ msymbols() to correct pointer type.
+ * utils.c (warning_pre_print): Initialize to "\nwarning: ".
+ * utils.c (fatal, fatal_dump_core): Ensure that the fatal
+ error always starts on a line of it's own.
+ * utils.c (init_malloc, malloc_botch, xmalloc, xrealloc):
+ Rewrite for new mapped malloc package use.
+ * utils.c (mmalloc, mrealloc, mfree): Stubs for configurations
+ that don't want to use the mapped malloc package; pass arguments
+ on to traditional malloc package functions.
+ * utils.c (nomem): Add for fatal virtual memory exhausted aborts.
+ * utils.c (xmmalloc, xmrealloc, xmalloc, xrealloc): Like mmalloc,
+ mrealloc, malloc, and realloc but get fatal error if runs out
+ of memory.
+ * utils.c (msavestring, mstrsave): Save a string in a specific
+ mapped malloc region.
+ * utils.c (print_spaces): Use xmalloc to get the buffer.
+ * xm-amix.h, xm-i386v4.h, xm-sun3os4.h, xm-sun4os4.h: Add defines
+ for MMAP_BASE_ADDRESS and MMAP_INCREMENT.
+ * config/i386v4.mh: Insignificant reorganization.
+
+Sat Mar 14 11:44:47 1992 Fred Fish (fnf@cygnus.com)
+
+ * xcoffread.c: Only enable compilation of debugging functions
+ if IBM6000 is defined. Fails to compile otherwise.
+
+Fri Mar 13 15:51:11 1992 K. Richard Pixley (rich@cygnus.com)
+
+ * Makefile.in: pass MAKEINFO down on info.
+
+Fri Mar 13 12:56:36 1992 John Gilmore (gnu at cygnus.com)
+
+ * mipsread.c (mipscoff_symfile_read): Eliminate a lot of
+ useless code, including an lseek to an uninitialized variable.
+ Reported by Jim Williams <jimbo@wrs.com>.
+
+Thu Mar 12 11:56:46 1992 Per Bothner (bothner@cygnus.com)
+
+ Merged in patches from metin@ibmpa.awdpa.ibm.com (Metin G.
+ Ozisik) (dated Fri, 6 Mar 92 17:51) for the rs6000.
+ * minsyms.c, symfile.c: Changes that may be generally
+ applicable, but are #ifdef IBM6000 for now.
+ * rs6000-xdep.c: Fixed typo in comment.
+ * rs6000-tdep.c: Non-substatial changes.
+ * xoffread.c: The main change here is addition of some
+ debugging functions.
+ * xoffexec.c: More changes.
+
+ * xcoffread.c: Fixed two too-few-parameters bugs.
+
+ * solib.h, infrun.c, tm-rs6000.h: Add a PID parameter
+ to SOLIB_CREATE_INFERIOR_HOOK macro.
+
+Sun Mar 8 21:17:48 1992 Fred Fish (fnf@cygnus.com)
+
+ * symfile.h: Add prototype for iterate_over_msymbols().
+ * symtab.c (cplus_mangled_symbol): Add function.
+ * symtab.c (lookup_symbol): Call cplus_mangled_symbol via
+ iterate_over_msymbols to find demangled C++ symbol.
+ * xcoffexec.c (relocate_minimal_symbol): Return meaningful
+ value to iterate_over_msymbols().
+ * xcoffexec.c (vmap_symtab): Ignore return from iterate_over_
+ msymbols().
+
+Fri Mar 6 21:59:34 1992 K. Richard Pixley (rich@cygnus.com)
+
+ * Makefile.in: added check target.
+
+Thu Mar 5 23:56:01 1992 John Gilmore (gnu at cygnus.com)
+
+ * ecoff.c: Move to ../bfd/coff-msym.c.
+ * config/mt-*mips: Remove ecoff.o from the configuration.
+ * remote.c (): Add newline to initial +.
+ (remote_resume): Mention how to cope with signals.
+ (remote_interrupt): Add debug msg.
+ (remote-wait): Implement new 'T' reply, which includes
+ status, PC, and FP all in a single short message.
+ (putpkt): Add further debugging of packet acks.
+ * mipsread.c (fixup_symtab): Also swap RFD's.
+ (parse_partial_symbols): Avoid bug on unknown symbol types.
+ * Makefile.in (VERSION): Roll to 4.4.5.
+ * mips-tdep.c (heuristic_proc_start): Avoid long delays
+ for remote MIPS by limiting heuristic to 200 byte search.
+ (heuristic_proc_desc): Byte-swapping.
+ (mips_print_register): Cope with failure of
+ read_relative_register_raw_bytes. Byte-swap integers for
+ printing.
+ * mips-pinsn.c (print_insn): Byte-swap instruction.
+
+Thu Mar 5 12:32:09 1992 Stu Grossman (grossman at cygnus.com)
+
+ * config.sub configure.in config/mh-irix4
+ gdb/configure.in gdb/mips-tdep.c gdb/mipsread.c
+ gdb/procfs.c gdb/signame.h gdb/tm-irix3.h gdb/tm-mips.h
+ gdb/xm-irix4.h gdb/config/mt-irix3
+ gdb/config/mh-irix4 texinfo/configure.in: Port to SGI Irix-4.x.
+
+Wed Mar 4 11:56:42 1992 Fred Fish (fnf@cygnus.com)
+
+ * defs.h, utils.c: xrealloc takes PTR as first arg.
+ * defs.h: Reword confusing comment about ANSI prototypes.
+ * defs.h: Some minor whitespace changes.
+ * infrun.c (wait_for_inferior): Compare int tmp to int 0,
+ not NULL, which can be (void *).
+ * tm-amix.h, tm-i386v4.h: Add defines for setjmp/longjmp handling.
+ * tm-i386v.h (SP_ARG0): Define
+ * xm-sysv4.h: Back out of change for missing prototypes.
+ * i386-tdep.c (get_longjmp_target): Add function.
+
+Wed Mar 4 05:46:11 1992 K. Richard Pixley (rich@rtl.cygnus.com)
+
+ * Makefile.in: install man page too.
+
+Tue Mar 3 15:11:52 1992 Michael Tiemann (tiemann@cygnus.com)
+
+ * All GDB files that #include defs.h: Removed stdio.h.
+ (defs.h): #include stdio.h.
+
+Mon Mar 2 23:00:12 1992 Steve Chamberlain (sac@thepub.cygnus.com)
+
+ * gdbtypes.c (lookup_pointer_type): initialize the TYPE_LENGTH of
+ a ptype to reflect the setting of TARGET_PTR_BIT. Set the
+ TYPE_FLAGS of a ptype to TYPE_FLAG_UNSIGNED.
+ * tm-h8300.h, h8300-tdep.c, remote-hms.c: personal checkpoint
+ * printcmd.c (print_address): if ADDR_BITS_REMOVE is defined, use
+ it before printing out the hex shape of an address.
+
+Sun Mar 1 17:41:09 1992 Per Bothner (bothner@cygnus.com)
+
+ * rs6000-xdep.c (frame_initial_stack_address): Move
+ code to set frame->cache_fsr into new separate function
+ frame_get_cacahe_fsr. This allows fixing a fatal error.
+ * xcoffexec.c: Turn previously suppressed error
+ message back on, after cleaning up BFD.
+
+ * breakpoint.c (breakpoint_re_set): Removed (at least for now)
+ printing of blank line, since it cases printing of an
+ extra blank line. Is this intended? It does mess up
+ gdb test suite.
+ * defs.h: Put back declarations of malloc and realloc,
+ but protected by #ifndef MALLOC_INCOMPATIBLE.
+ * objfiles.c: Undo previous change: Use malloc/realloc
+ for objfile malloc/realloc fields (but add a cast).
+ * xcoffexec.c: Suppress an error message (for now).
+
+Sat Feb 29 14:43:02 1992 Per Bothner (bothner@cygnus.com)
+
+ Changes from metin@ibmpa.awdpa.ibm.com (Metin G. Ozisik)
+ [Mail dated Fri, 21 Feb 92 13:14:54 -0800]
+ * buildsym.c: Use smash_to_pointer_type() to handle forward type
+ references.
+ * xcoffread.c: Modifications to C_DECL storage class handling, and
+ introduction of an old smash_to_pointer_type() routine.
+
+ Changes from metin@ibmpa.awdpa.ibm.com (Metin G. Ozisik)
+ [Mail dated Thu, 20 Feb 92 13:57:16 -0800]
+ * rs6000-xdep.c, rs6000-tdep.c, tm-rs6000.h: function_frame_info()
+ parameters have been modified.
+
+ Changes from metin@ibmpa.awdpa.ibm.com (Metin G. Ozisik)
+ [Mail dated Thu, 20 Feb 92 10:10:05 -0800]
+ * rs6000-tdep.c: Before Feb 5 92, register_valid[] array was not used,
+ and fetch_inferior_registers() always fetched all the registers
+ resulting valid register values at hand all the time. Pushing a dummy
+ frame did not require validating all register values first. After
+ putting the above mechanism into action, we didn't have valid registers
+ values always ready. Thus, all registers need to be fetched before
+ pushing a dummy frame now.
+
+ Changes from metin@ibmpa.awdpa.ibm.com (Metin G. Ozisik)
+ [Mail dated Thu, 13 Feb 92 16:22:44 -0800]
+ * rs6000-xdep.c: frame_initial_stack_address() function to calculate
+ the starting address (actual frame address) of a frame.
+ * rs6000-tdep.c: modifications to function_frame_info() to see if
+ function reserves a frame pointer register (alloca register)
+ * tm-rs6000.h: EXTRA_FRAME_INFO, FRAME_ARGS_ADDRESS and
+ FRAME_LOCALS_ADDRESS has been updated to support debugging of
+ functions with alloca() calls.
+
+Sun Mar 1 13:13:39 1992 Fred Fish (fnf@cygnus.com)
+
+ * xm-sysv4.h: Provide definitions/prototypes for host environment
+ functions for which no definitions or prototypes are provided in
+ any currently included gdb or host environment header files.
+ For SVR4, this currently includes malloc and realloc, which cannot
+ be portably prototyped in any gdb include file.
+
+Sat Feb 29 14:43:02 1992 Per Bothner (bothner@cygnus.com)
+
+ * buildsym.h: Remove obsolete variable file_stabs.
+
+ * Makefile.in: Move place where configure merges in host-
+ and target-dependent fragments later, so the latter
+ can override (say) GNU_MALLOC.
+ * config/mh-rs6000: Use system malloc. Otherwise, I
+ ended up with *two* incompatible versions of malloc
+ (functions in libc would call the malloc in libc).
+ I assume this is a shared library problem.
+
+ * remote.c: Fix (presumed) typo.
+ * objfiles.c: Use xmalloc/xrealloc instead of
+ malloc/realloc (since the latter are no longer declared).
+
+ Changes from metin@ibmpa.awdpa.ibm.com (Metin G. Ozisik)
+ [Mail dated Thu, 6 Feb 1992 10:22:02 -0800]
+ * rs6000-xdep.c: Improvements to fetch_inferior_registers() to
+ handle individual registers.
+ * tm-rs6000.h: Fix SAVED_PC_AFTER_CALL macro to handle pc value
+ correctly in case it wasn't cached yet. (A problem showed up
+ after fetching individual registers.)
+ * buildsym.c: Disable type_synonym_name's type name overwriting
+ in cases it is unnecesary. rs6000 portation doesn't use
+ type_synonym_name, and it used to nullify type names
+ * xcoffread.c: to handle g++'s typename abbreviation, fill in a
+ type's name as soon as space for that type is allocated.
+ * xcoffread.c: ignore a section's lineno information if it is
+ not `.text'. (In rs6000 bfd portation integration, skipping over
+ `.pad' sections are ignored since it was in machine independent
+ part of the code. Thus, a problem of fake sections with invalid
+ lineno information arised.)
+
+ Changes from metin@ibmpa.awdpa.ibm.com (Metin G. Ozisik)
+ [Mail dated Thu, 6 Feb 1992 13:26:22 -0800]
+ * rs6000-tdep.c: make function_frame_info() work whether or not
+ reading from a core file.
+ * tm-rs6000.h: Implementation of FRAME_FIND_SAVED_REGS macro.
+
+ * infrun.c. main.c, printcmd.c. symtab.c:
+ More changes from IBM for rs6000.
+
+
+Thu Feb 27 22:57:19 1992 Per Bothner (bothner@cygnus.com)
+
+ * rs6k-opcode.h, tm-rs6000.h, xm-rs6000.h, rs6000-tdep.c,
+ rs6000-xdep.c, xcoffexec.c, xcoffread.c:
+ Merge in changes (mostly from IBM) for RS6000.
+ * breakpoint.c, buildsym.c, infptrace.c, stack.c, symtab.c:
+ More changes from IBM for RS6000. These are in machine-
+ independent code, and probably could do with some cleaning
+ up. The most questionable of these are #ifdef IBM6000.
+ * infrun.c, sparc-tdep.c: Pass a parameter (signal number)
+ to single_step() (for consistency with rs6000 and i860).
+ * utils.c: Allow the 1st arg to xrealloc to be NULL
+ (in which case do malloc). This removes the need for
+ some tests in xcoff code (and perhaps other places?).
+ * coffread.c: Removed variables last_source_file,
+ type_vector, and type_vector_length as these are now
+ defined by buildsym.[ch].
+ * defs.h: Remove prototypes for malloc and realloc, since
+ these should only be used to implement xmalloc and xrealloc,
+ and they conflict with <stdlib.h> in AIX - where they
+ return void* even when __STDC__ isn't defined. Sigh.
+ * munch: Recognize *initialize* in data as well as text
+ (AIX uses data). Also, incorporate a patch from Garrett
+ Wollman <wollman@uvm-gen.uvm.edu> to make the sed script
+ much more sensible, by only trying to match the name of
+ the initialize_foo function, and not the junk before it.
+
+Thu Feb 27 20:07:43 1992 Stu Grossman (grossman at cygnus.com)
+
+ * breakpoint.c (breakpoint_re_set_one): Don't reset breakpoint
+ unless symbol table indicates that something has changed.
+
+Thu Feb 27 11:48:47 1992 John Gilmore (gnu at cygnus.com)
+
+ * remote.c: Make it work for embedded MIPS. Increase buffer
+ size, and use throughout. Round buffer size up if too many regs.
+ Support baud rate setting and try for an 8-bit path. If
+ interrupted while waiting for target, send a ^C down the wire.
+ Avoid single-byte reads.
+ * tm-mips.h: Add more embedded-system registers to REGISTER_NAMES
+ and NUM_REGS.
+ * mips-xdep.h: Avoid the embedded regs when on Unix.
+
+ * mipsread.c: Byte-swap the symbol table structures, using
+ routines from ecoff.c, to read a symbol table written in any
+ of the four possible byte orders.
+ * configure.in (mips-big-* target): Same as Sony News.
+ * config/mt-bigmips, config/mt-littlemips: Add ecoff.o.
+ * ecoff.c: New file for symbol swapping routines.
+
+Thu Feb 27 09:26:38 1992 Stu Grossman (grossman at cygnus.com)
+
+ * breakpoint.c (all_breakpoints_info, breakpoint_1): Add 'info
+ all-breakpoints' command.
+ * (get_number): Allow users to enter negative breakpoint numbers.
+ * (breakpoint_1): Reformat display of 'info break' to show new
+ fields.
+ * (create_longjmp_breakpoint, breakpoint_re_set,
+ breakpoint_re_set_one, enable/disable_longjmp_breakpoint),
+ symfile.c (syms_from_objfile): Re-do
+ insertion of longjmp breakpoints. Move all code into
+ breakpoint_re_set, and call that instead of
+ create_longjmp_breakpoint in symfile.c.
+
+Thu Feb 27 06:11:05 1992 John Gilmore (gnu at cygnus.com)
+
+ * breakpoint.h (ALL_BREAKPOINTS_SAFE): Add.
+ * breakpoint.c (breakpoint_re_set): Use ALL_BREAKPOINTS_SAFE.
+ * symtab.c (find_pc_symtab): Handle having no objfiles.
+ * infcmd.c: Fix comment.
+ * objfiles.c (free_all_objfiles): Add.
+ * symfile.h (ALL_OBJFILES, ALL_OBJFILES_SAFE): Add.
+ * symfile.c (symbol_file_command): free all objfiles when
+ specifying a new symbol file.
+ (reread_symbols): Stat the file name, don't fstat the descriptor.
+
+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.
+
+Tue Feb 25 19:31:19 1992 Stu Grossman (grossman at cygnus.com)
+
+ * dbxread.c (end_psymtab): Delete empty psymtabs.
+ * symfile.c (allocate_psymtab): Recycle empty psymtabs.
+ * symfile.h (struct objfile): Add free_psymtabs.
+
+Sat Feb 22 02:00:32 1992 John Gilmore (gnu at cygnus.com)
+
+ * Makefile.in (VERSION): Roll to gdb-4.4.4.
+
+ * symfile.c (symbol_file_command): strcmp => !strcmp.
+ * breakpoint.h: Move prototypes to follow enum definition they need.
+ * breakpoint.c, infrun.c: Lint.
+ * printcmd.c: Use `enum enable' rather than `enum
+ display_status'.
+ * mipsread.c: First pass at making it compile with the new
+ objfile changes. Probably seriously broken still, but it
+ compiles. FIXME.
+
+Sat Feb 22 00:56:39 1992 Stu Grossman (grossman at cygnus.com)
+
+ * infrun.c, infcmd.c, breakpoint.c, main.c, symfile.c,
+ breakpoint.h, tm-sun4os4.h, tm-sparc.h, sparc-tdep.c, tm-mips.h,
+ mips-tdep.h, tm-sun3.h, tm-68k.h, m68k-tdep.h: Add support for
+ stepping (and nexting) through longjmp(). Also, cleanup
+ breakpoint handling quite a bit by creating explicit breakpoint
+ types instead of using magic breakpoint numbers.
+ Makefile.in: Update version to 4.4.3
+
+Sat Feb 22 00:08:50 1992 John Gilmore (gnu at cygnus.com)
+
+ * buildsym.c, dwarfread.c, gdbtypes.c, inflow.c, main.c,
+ minsyms.c, printcmd.c, remote.c, saber.suppress: Saberlint.
+ * symmisc.c, xcoffread.c: Move debug functions to symmisc.c.
+
+ * xm-sun3os4.h, xm-sun4os4.h: Enable HAVE_MMAP.
+
+ * minsyms.c (install_minimal_symbols): Add bunches to any
+ existing minsyms in the objfile. Avoid extra mallocation
+ by working directly in the obstack. Remove ignored `mainline' parm.
+ * coffread.c, dbxread.c, elfread.c, mipsread.c, solib.c, symtab.h,
+ xcoffread.c: Change all callers.
+ * FIXME: We should be able to eliminate MAINLINE from all the
+ symbol readers now, with a small bit of work.
+
+ * valops.c, value.h: Lint.
+ * remote-vx.c: Add missing break; statement. Bugfix by
+ Michael Sclafani, <sclafani@src.dec.com>.
+
+Fri Feb 21 17:29:54 1992 Fred Fish (fnf at cygnus.com)
+
+ * Makefile.in (VERSION): Update version to 4.4.2
+ * Makefile.in (SFILES_MAINDIR): Add gdbtypes.c, state.c, objfiles.c,
+ minsyms.c, mmap-alloc.c, mmap-sbrk.c
+ * Makefile.in (HFILES): Add gdbtypes.h, state.h, solib.h
+ * Makefile.in (OBS): Add gdbtypes.o, state.o, objfiles.o, minsyms.o,
+ mmap-alloc.o, mmap-sbrk.o
+
+ * altos-xdep.c: Minor whitespace change.
+ * am29k-tdep.c (examine_prologue): Convert from misc function vector
+ use to new minimal symbol table use.
+ * arm-xdep.c (fetch_inferior_registers): Document unused argument.
+ * arm-xdep.c (store_inferior_registers): Returns void.
+ * blockframe.c (get_pc_function_start, find_pc_partial_function):
+ Convert from misc function vector use to new minimal symbol table use.
+ Remove find_pc_misc_function(). Ifdef out block_innermost_frame().
+ * breakpoint.c: Add prototypes for local functions.
+ * breakpoint.c (catch_command_1): Change to static and remove unused
+ local "pc".
+ * breakpoint.c (map_breakpoint_numbers): Prototype arg "function".
+ * breakpoint.h: Change function decls to prototype form.
+ * buildsym.c: Add prototypes for local functions.
+ * buildsym.c: Moved hashname() function here from dbxread.c.
+ * buildsym.c (dbx_lookup_type): Cast args to xrealloc().
+ * buildsym.c: Remove dbx_create_type(), uses changed to alloc_type().
+ * buildsym.c (dbx_alloc_type): Change to static.
+ * buildsym.c (finish_block): Add objfile parameter.
+ * buildsym.c (misc): Change symbol_obstack to objfile version.
+ * buildsym.c (make_blockvector): Change to static.
+ * buildsym.c (start_subfile): Use strdup instead of obsavestring.
+ * buildsym.c (compare_line_numbers): Change to static, args are const,
+ cast args when used.
+ * buildsym.c (start_symtab): Inline new_object_header_files() call.
+ * buildsym.c (patch_block_stabs): Moved to this file from xcoffread
+ and made static. Add objfile parameter.
+ * buildsym.c (end_symtab): Simplify code using line table size.
+ Realloc the linetable on the objfile symbol_obstack and copy there.
+ * buildsym.c (scan_file_globals): Convert from misc function vector
+ use to new minimal symbol use.
+ * buildsym.c (define_symbol): Add objfile parameter. Make sure
+ strings get allocated in objfile's symbol_obstack. Convert references
+ to builtin types to lookup_fundamental_type().
+ * buildsym.c (read_type): Make static, add objfile parameter, convert
+ references to buildin types to lookup_fundamental_type().
+ * buildsym.c (read_struct_type): Add objfile parameter.
+ * buildsym.c (read_array_type): Make static, add objfile parameter.
+ * buildsym.c (read_enum_type): Make static, add objfile parameter.
+ * buildsym.c (read_huge_number): Make static.
+ * buildsym.c (read_range_type): Make static, add objfile parameter,
+ convert references to buildin types to lookup_fundamental_type ().
+ * buildsym.c (read_args): Make static, add objfile parameter.
+ * buildsym.h: Convert function decl's to prototype form.
+ * c-exp.y: Add prototypes for local functions, convert uses of misc
+ function vector to minimal symbol table. Reformat all builtin type
+ initializations and pass a NULL objfile to init_type() for them.
+ * coffread.c: Change context_stack ref's to coff_context_stack,
+ add local function prototypes. Cast uses of xrealloc arg 1.
+ * coffread.c (coff_alloc_type): Call alloc_type instead of hand-
+ crafting a new type.
+ * coffread.c (add_symbol_to_list): Change to coff_add_symbol_to_list.
+ * coffread.c (finish_block): Change name to coff_finish_block.
+ * coffread.c (make_blockvector): Add and use objfile parameter.
+ * coffread.c (record_line): Change name to coff_record_line.
+ * coffread.c (start_symtab): Change name to coff_start_symtab.
+ * coffread.c (end_symtab): Change name to coff_end_symtab.
+ * coffread.c (record_misc_function): Change name to record_minimal_
+ symbol and change to minimal symbol table use from misc func tbl.
+ * coffread.c (coff_symfile_read): Convert from misc function vector
+ use to minimal symbol table use.
+ * coffread.c (hashname): Remove; use common version in buildsym.c.
+ * coffread.c (decode_base_type): Change references to builtin types
+ to calls to lookup_fundamental_type().
+ * coffread.c (read_struct_type): Change name to coff_read_struct_type.
+ * coffread.c (read_enum_type): Change name to coff_read_enum_type.
+ * command.c: Add prototypes for local functions.
+ * command.c (add_cmd): Prototype the 'fun' parameter and use the
+ appropriate member of the function union for that type.
+ * command.c (add_abbrev_cmd): Prototype the 'fun' parameter and
+ ifdef out the function since it isn't currently used.
+ * command.c (add_alias_cmd): Pass correct function type to add_cmd.
+ * command.c (add_prefix_cmd): Prototype the 'fun' parameter.
+ * command.c (add_abbrev_prefix_cmd): Prototype the 'fun' parameter.
+ * command.c (help_cmd): Compare function pointer to NULL.
+ * command.c (help_cmd_list): Compare function pointer to NULL.
+ * command.c (lookup_cmd_1): Use correct member of function union.
+ * command.c (undef_cmd_error): Make static.
+ * command.c (complete_on_cmdlist): Use correct member of func union.
+ * command.c (do_setshow_command): Use correct member of func union.
+ * command.c (shell_escape): Convert rindex use to strrchr.
+ * command.h (COMMAND_H): Define if already included.
+ * command.h (cmd_list_element struct): Change 'function' to a union
+ and prototype args. Prototype completer function.
+ * command.h: Convert decl's to prototype form.
+ * convex-xdep.c (store_inferior_registers): Returns void.
+ * copying.c: Prototype local functions.
+ * coredep.c: Minor whitespace change.
+ * cplus-dem.c: Remove hack to use BSD equivalents of mem* and str*.
+ * cplus-dem.c: Prototype local functions.
+ * dbxread.c (hashname): Remove; moved to buildsym.c.
+ * dbxread.c (free_and_init_header_files): Make static.
+ * dbxread.c: Add prototypes for local functions.
+ * dbxread.c (new_object_header_files): Remove; inlined usages.
+ * dbxread.c (xrealloc usages): Cast args.
+ * dbxread.c (record_misc_function): Change to record_minimal_symbol
+ and change usages accordingly.
+ * dbxread.c (static_psymbols usages): Change to use per-objfile copy.
+ * dbxread.c (xmalloc usages): Use per-objfile copy when appropriate.
+ * dbxread.c (dbx_next_symbol_text): Make static.
+ * dbxread.c (init_psymbol_list): Convert to use per-objfile data.
+ * dbxread.c (init_bincl_list): Add and use objfile parameter.
+ * dbxread.c (free_bincl_list): Add and use objfile parameter.
+ * dbxread.c (compare_psymbols): Remove; use common symfile.c version.
+ * dbxread.c (end_psymtab): Convert to use per-objfile data.
+ * dwarfread.c (DEFUN/EXFUN): Remove all usages. Use PARAMS for
+ prototypes.
+ * dwarfread.c (record_misc_function): Change name to record_minimal_
+ symbol and use minimal symbol table throughout.
+ * dwarfread.c (compare_psymbols): Remove; use common symtab.c version.
+ * dwarfread.c: Convert all references to builtin types to use the new
+ lookup_fundamental_type function.
+ * dwarfread.c (read_enumeration): Add and use objfile parameter.
+ * elfread.c (DEFUN/EXFUN): Remove all usages. Use PARAMS for proto-
+ types.
+ * elfread.c (record_misc_function): Convert to use record_minimal_
+ symbol.
+ * elfread.c (elf_symtab_read): Add objfile parameter.
+ * eval.c: Add prototypes for local functions and move some decls
+ around to accomodate prototypes.
+ * expprint.c: Add prototypes for local functions. Change references
+ to misc function vector to minimal symbol table.
+ * findvar.c (read_memory usages): Cast args.
+ * gdbtypes.h: New file, type info from symfile.h and symtab.h.
+ * gmalloc.c: Use NOARGS where prototypes used hardwired void.
+ * gmalloc.c (BLOCKSIZE): Constant to be shifted is unsigned.
+ * gmalloc.h: Use NOARGS where prototypes used hardwired void.
+ * gould-xdep.c: Minor whitespace change.
+ * hp300ux-xdep.c (fetch_inferior_registers): Remove unused regno var.
+ * hp300ux-xdep.c (store_inferior_registers): Returns void.
+ * hp300ux-xdep.c (fetch_core_registers): Takes unused arg reg_addr.
+ * i386-stub.c: Add prototypes, change "volatile" to NORETURN.
+ * i386-tdep.c: Add prototypes for local functions.
+ * i386-tdep.c (codestream_fill, codestream_seek, codestream_read,
+ i386_get_frame_setup, i386_skip_prologue): Explicitly declare params
+ that defaulted to int.
+ * i386-tdep.c (i386_follow_jump, i386_frame_find_saved_regs,
+ i386_push_dummy_frame): Returns void.
+ * i386-xdep.c (i386_register_u_addr): Declare params that default to
+ int and explicitly declare return type as int.
+ * i387-tdep.c: Minor formatting changes.
+ * i960-tdep.c (leafproc_return): Convert from misc function vector
+ use to minimal symbol table use.
+ * infcmd.c: Add prototypes for local functions.
+ * infcmd.c (continue_command, until_next_command, until_command,
+ path_info, path_command): Make static.
+ * infcmd.c (step_1, until_next_command): Convert from misc func
+ vector to minimal symbol table use.
+ * inflow.c: Add prototypes for local functions.
+ * infptrace.c (store_inferior_registers): Returns void, not int.
+ * language.c (_initialize_language): Use proper member of function
+ union.
+ * m2-exp.y: Add prototypes for local functions, convert misc function
+ vector uses to minimal symbol table uses.
+ * m2-exp.y (make_qualname, yyerror): Make static.
+ * m2-exp.y (_initialize_m2_exp): Call init_types with NULL objfile.
+ * m68k-pinsn.c: Add prototypes for local functions.
+ * m68k-pinsn.c (print_insn): Cast args to read_memory.
+ * m68k-pinsn.c (fetch_arg): Make parameter 'code' and int.
+ * m68k-stub.c: Add prototypes.
+ * m88k-pinsn.c (sprint_address): Convert from misc function vector
+ use to minimal symbol table use.
+ * m88k-xdep.c (fetch_inferior_registers): Takes an unused parameter.
+ * m88k-xdep.c (store_inferior_registers): Returns void.
+ * mach386-xdep.c (fetch_inferior_registers): Takes an unused param.
+ * mach386-xdep.c (store_inferior_registers): Returns void.
+ * mach386-xdep.c (fetch_core_registers): Takes an unused parameter.
+ * main.c: Add prototypes for local functions.
+ * main.c (return_to_top_level): Is type NORETURN (volatile). Cast
+ longjmp() result to (NORETURN void).
+ * main.c (catch_errors): Prototype the 'func' parameter.
+ * main.c (disconnect, stop_sig, do_nothin, float_handler):
+ Takes an unused arg.
+ * main.c (execute_command): Call the right member of the func union.
+ * main.c (command_loop_marker, symbol_completion_function,
+ command_loop): Make static.
+ * main.c (command_line_input): Make linelength unsigned, cast arg
+ to command_line_input().
+ * main.c (add_info, add_com): Prototype the 'fun' parameter.
+ * main.c (initialize_main): Call right member of function union.
+ * mcheck.c (NOARGS): Change hardwired void in prototypes to NOARGS.
+ * mem-break.c: Include symtab.h
+ * mips-xdep.c (fetch_inferior_registers): Takes unused param.
+ * mips-xdep.c (store_inferior_registers): Returns void.
+ * mipsread.c (mipscoff_symfile_read): Change from misc function vector
+ use to minimal symbol table use.
+ * mipsread.c (symbol_obstack usages): Convert all to use per-objfile
+ version.
+ * mipsread.c (make_type): Remove, convert usages to init_type.
+ * mipsread.c (_initialize_mipsread): Call init_type with NULL objfile.
+ * nindy-tdep.c (nindy_frame_chain_valid): Convert from misc function
+ vector use to minimal symbol table use.
+ * parse.c: Add prototypes for local functions.
+ * parse.c (xrealloc usages): Cast args.
+ * parse.c (prefixify_expression, length_of_subexp): Make static.
+ * parser-defs.h (PARSER_DEFS_H): Define when first included.
+ * parser-defs.h: Convert function decls to prototype form.
+ * partial-stab.h: Convert from misc function vector use to new minimal
+ symbol table use.
+ * partial-stab.h (global_psymbols, static_psymbols usages): Reference
+ the per-objfile copies.
+ * printcmd.c: Add prototypes for local functions. Move some struct
+ definitions around to accomodate prototypes.
+ * printcmd.c (decode_format): Make static, change args oformat and
+ osize to int from char.
+ * printcmd.c (print_formatted): Change 'format' and 'size' to int.
+ * printcmd.c (print_scalar_formatted): Change arg 'format' to int.
+ * printcmd.c (print_address_symbolic): Convert from misc function
+ vector use to minimal symbol table use.
+ * printcmd.c (address_info): Convert from misc function vector use
+ to minimal symbol table use.
+ * printcmd.c (delete_display, enable_display, disable_display_command):
+ Make static.
+ * procfs.c (EXFUN/DEFUN): Remove all usages, convert to PARAMS.
+ * procfs.c (fetch_core_registers): Add unused param reg_addr.
+ * pyr-xdep.c (fetch_inferior_registers): Add unused param regno.
+ * pyr-xdep.c (store_inferior_registers): Returns void.
+ * remote-mm.c (mm_load): symbol_file_add return value unused.
+ * remote-nindy.c: Minor format change.
+ * remote-vx.c (vx_load_command): symbol_file_add result unused.
+ * rs6000-xdep.c (fetch_inferior_registers): Add unused param regno.
+ * rs6000-xdep.c (store_inferior_registers): Returns void.
+ * rs6000-xdep.c (fetch_core_registers): add unused param reg_addr
+ * rs6000-xdep.c (aixcoff_relocate_symtab): Convert from misc function
+ vector use to minimal symbol table use.
+ * solib.c: Add prototypes for local functions.
+ * solib.c (solib_add_common_symbols, locate_base): Convert from misc
+ function vector use to minimal symbol table use.
+ * solib.c (EXFUN/DEFUN): Remove all usages, convert to PARAMS.
+ * solib.c (find_solib, shared_library_command): Make static
+ * solib.c (read_memory, write_memory usages): Cast args.
+ * solib.c (special_symbol_handling): Add function
+ * source.c: Add prototypes for local functions.
+ * source.c (select_source_symtab): Convert to scan objfiles.
+ * source.c (open_source_file): Make static.
+ * source.c (xrealloc usages): Cast args.
+ * source.c (source_line_charpos): ifdef out, unused.
+ * source.c (get_filename_and_charpos): Make static.
+ * stack.c: Add prototypes for local functions.
+ * stack.c (print_frame_info, frame_info): Convert from misc function
+ vector use to minimal symbol table use.
+ * symfile.c: Add prototypes for local functions.
+ * symfile.c (compare_symbols): Make args const PTR's.
+ * symfile.c (compare_psymbols, sort_pst_symbols) add.
+ * symfile.c (sort_all_symtab_syms): Scan objfile list.
+ * symfile.c (obsavestring): Add objfile parameter.
+ * symfile.c (init_misc_bunches, prim_record_misc_function,
+ compare_misc_functions, discard_misc_bunches, condense_misc_bunches,
+ sort_misc_function_vector, compact_misc_function_vector): Remove
+ * symfile.c (symbol_file_add_digested): Add function.
+ * symfile.c (symbol_file_add): Returns struct objfile *.
+ * symfile.c (symbol_file_command): Modify for state file use.
+ * symfile.c (symfile_open): Add parameter "dumpable".
+ * symfile.c (allocate_objfile, free_objfile): Moved to objfiles.c
+ * symfile.c (load_command, add_symbol_file_command): Make static.
+ * symfile.c (fill_in_vptr_fieldno): Moved to gdbtypes.c
+ * symfile.c (rindex usages): Converted to strrchr.
+ * symfile.c (allocate_psymtab): New
+ * symfile.c (free_named_symtabs): Ifdef out code that needs to be
+ converted to minimal symbol table usage, but no obvious conversion.
+ * symfile.c (free_all_symtabs): Remove.
+ * symfile.c (_initialize_symfile): Use per-objfile info.
+ * symfile.h: Rework the objfile structure to add per-objfile data
+ objects (psymbol_obstack, symbol_obstack, type_obstack,
+ global_psymbols, static_psymbols, msymbols, minimal_symbol_count,
+ fundamental_types, malloc, realloc, free, xmalloc, xrealloc, etc).
+ Add prototypes to function declarations.
+ * symm-tdep.c (symmetry_extract_return_value): Convert from misc
+ function vector usage to minimal symbol table usage.
+ * symmisc.c (DEV_TTY): Define if not defined.
+ * symmisc.c: Add local function prototypes.
+ * symmisc.c (dump_objfile, dump_msymbols, dump-symtab, print_syms,
+ printpsyms_command, print_objfiles, print_objfiles_command):
+ Rework to use iterate_over_*
+ * symtab.c: Add prototypes for local functions.
+ * symtab.c (lookup_symtab_1): Convert to look through objfiles.
+ * symtab.c (lookup_partial_symtab): Scan through objfiles.
+ * symtab.c (lookup_primitive_typename, lookup_typename, lookup_
+ unsigned_typename, lookup_struct, lookup_union, lookup_enum,
+ lookup_template_type, lookup_struct_elt_type, lookup_pointer_type,
+ lookup_reference_type, lookup_member_type, allocate_stub_method,
+ check_stub_method, create_array_type, smash_to_member_type,):
+ Moved to gdbtypes.c
+ * symtab.c (lookup_symbol): Some args are const.
+ * symtab.h: All type related defs and structs moved to gdbtypes.h
+ * symtab.h: Convert decls to prototypes.
+ * target.c (noprocess): Make static.
+ * target.h: Change decl's to prototypes.
+ * tm-sunos.h: (CLEAR_SOLIB, SOLIB_ADD, SOLIB_CREATE_INFERIOR_HOOK,
+ DISABLE_UNSETTABLE_BREAK) Moved to solib.h.
+ * utils.c (_initialize_utils): Use correct member of function union.
+ * valarith.c: include gdbtypes.h
+ * valops.c: include gdbtypes.h, add prototypes for local functions.
+ * valops.c (value_push, value_arg_push, find_function_addr):
+ Make static.
+ * valops.c (value_string): Convert from misc function vector use
+ to minimal symbol table use.
+ * valops.c (check_field_in): Make arg const.
+ * valprint.c: Add prototypes for local functions.
+ * valprint.c (print_string): Make static
+ * valprint.c (value_print, val_print_fields, val_print): Make arg int.
+ * values.c: Add prototypes for local functions.
+ * values.c (value_headof): Convert from misc function vector to
+ minimal symbol table.
+ * xcoffexec.c: Add prototypes for local functions.
+ * xcoffexec.c (exec_close, file_command, add_to_section_table):
+ Make static.
+ * xcoffexec.c (relocate_minimal_symbol): Add.
+ * xcoffread.c (patch_block_stabs): Moved to buildsyms.c.
+ * xcoffread.c: Add prototypes for local functions.
+ * xcoffread.c (sort_syms): Convert to scan objfiles.
+ * xcoffread.c (read_xcoff_symtab): Make static.
+ * xcoffread.c (various): Replace references to builtin types with
+ calls to lookup_fundamental_type. Replace references to symbol_obstack
+ and psymbol_obstack with pointers to the per-objfile copies.
+ * xcoffread.c (dump_linetable, dump_type, dump_symbol, dump_namespace,
+ dump_block, dump_blockvector, dump_last_symtab, dump_symtabs):
+ Make static.
+ * xcoffread.c (init_stringtab): Add objfile parameter.
+ * gdbtypes.c: New file
+ * minsyms.c: New file
+ * mmap-alloc.c: New file
+ * mmap-sbrk.c: New file
+ * objfiles.c: New file
+ * state.c: New file
+ * state.h: New file
+
+Fri Feb 21 17:29:54 1992 John Gilmore (gnu at cygnus.com)
+
+ * Check in Fred Fish's changes in these modules. Fred
+ will make ChangeLog entries for all of them. Update VERSION
+ to 4.4.2.
+
+Thu Feb 20 18:10:17 1992 Fred Fish (fnf at cygnus.com)
+
+ * tm-sparc.h, tm-sysv4.h, solib.h: Move shared lib definitions
+ into solib.h.
+ * sparc-pinsn.c, sparc-tdep.c, standalone.c, sun3-xdep.c,
+ sun386-xdep.c, symm-xdep.c, target.c, ultra3-xdep.c, utils.c,
+ value.h: Prototypes for static functions; lint.
+ * gdbtypes.h: Empty file to ease transition.
+
+Thu Feb 20 16:43:13 1992 Fred Fish (fnf at cygnus.com)
+
+ * environ.h, expression.h, frame.h, gdbcmd.h, gdbcore.h,
+ inferior.h, language.h, signame.h, target.h, terminal.h,
+ tm-68k.h, tm-i386v.h, tm-sparc.h, tm-sun386.h, tm-symmetry.h,
+ xm-i386v.h, xm-sparc.h: Prototypes for all external functions.
+ Lint.
+ * core.c, exec.c, infrun.c, inftarg.c, language.c, remote.c,
+ signame.c, sparc-xdep.c: Prototypes for all static functions.
+ Lint.
+ * core.c, eval.c, exec.c, inftarg.c, remote-adapt.c, remote-eb.c,
+ remote-hms.c, remote-mm.c, remote-nindy.c, remote-vx.c, remote.c,
+ target.c, target.h, valarith.c, valops.c, value.h, xcoffexec.c:
+ Remove to_call_function and target_call_function, since it
+ always calls the same thing (call_function_by_hand).
+ * core.c, exec.c, solib.c: Rename target_ops sections =>
+ to_sections, etc.
+ * infcmd.c, inflow.c, infptrace.c, infrun.c, main.c, target.c,
+ target.h: target_kill takes no args.
+ * language.c (language_info): Scaffolding to allow briefer
+ messages when the current language changes. FIXME.
+ * xm-amix.h, xm-i386v4.h, xm-stratus.h: Define NORETURN to avoid
+ complaints about volatile functions.
+ * xm-sysv4.h (HAVE_MMAP): Define.
+
+Thu Feb 20 09:04:18 1992 Fred Fish (fnf at cygnus.com)
+
+ * defs.h: Include ansidecl.h and PARAMS macro. Use PARAMS
+ to make prototypes for all functions declared here.
+ * cplus-dem.c: Avoid declaring xmalloc and xrealloc.
+ * c-exp.y: Rename SIGNED, OR, and AND to avoid conflict.
+ * environ.c: Include <stdio.h> before defs.h. Minor cleanup.
+ * ieee-float.h: Use PARAMS for prototypes; make some params const.
+ * ieee-float.c, valarith.c: Include <stdio.h>. Lint. b*=>mem*.
+ * m2-exp.y: Remove unused CONST; Rename OR and AND.
+ * utils.c: Avoid declaring malloc and realloc. Lint.
+ (request_quit): Accept signal-number parameter.
+
+Mon Feb 17 07:13:27 1992 Fred Fish (fnf at cygnus.com)
+
+ * dwarfread.c (process_dies): Add case to handle TAG_pointer_type
+ DIE's. Add new function read_tag_pointer_type() to read them.
+
+ * dwarfread.c (dwarf_read_array_type, read_subroutine_type):
+ When creating a new user defined type, check to see if a partial
+ type already exists, and if so, bash it to fit.
+
+Fri Feb 14 19:00:17 1992 John Gilmore (gnu at cygnus.com)
+
+ * coffread.c (decode_base_type): Pass long, not union.
+ Fix by Eric Valette, ev@chorus.fr.
+
+Thu Feb 13 17:14:28 1992 Fred Fish (fnf at cygnus.com)
+
+ * elfread.c (elf_symtab_read): Fix code to correctly track
+ changes in bfd for absolute symbols.
+
+Thu Feb 13 12:43:29 1992 Stu Grossman (grossman at cygnus.com)
+
+ * xm-vaxbsd.h: Close off comment.
+
+Thu Feb 13 07:45:19 1992 Fred Fish (fnf at cygnus.com)
+
+ * xm-sysv4.h: Define NEED_POSIX_SETPGID.
+
+Fri Feb 7 11:51:12 1992 Per Bothner (bothner at cygnus.com)
+
+ * mips-tdep.c (mips_print_registers): Print correct register
+ number for double pseudo-registers.
+
+Fri Feb 7 07:56:05 1992 John Gilmore (gnu at cygnus.com)
+
+ * buildsym.c (read_struct_type): Avoid double-bump of parse ptr
+ in the op$::OPERATOR. case. From Steven McCanne,
+ <mccanne@horse.ee.lbl.gov>.
+
+ * exec.c (set_section_name): Pass arg to exec_files_info;
+ only call it if interactive. From Francis Kauth <fk@tv.tv.tek.com>.
+
+Thu Feb 6 17:41:32 1992 John Gilmore (gnu at cygnus.com)
+
+ * main.c (print_gdb_version): Copyright msg: only this year.
+ (cd_command): Avoid changing current_directory on error.
+
+Thu Feb 6 15:14:01 1992 Per Bothner (bothner at cygnus.com)
+
+ * mipsread.c (parse_partial_symbols): Handle dependencies
+ between partial symbol tables (when not doing stabs-in-ecoff).
+ (This used to be handled by parse_fdr, but parse_fdr was
+ incompatible with handling stabs-in-ecoff, so the code
+ was re-written to not use parse_fdr. Unfortunately,
+ the logic to handle dependencies was overlooked.)
+
+Thu Feb 6 11:51:39 1992 Steve Chamberlain (sac at rtl.cygnus.com)
+
+ * coffread.c (read_enum_type): Use the size of a target int when
+ describing enum.
+ * defs.h: added new #define for TARGET_PTR_BIT, defaults to size
+ of target int.
+ * h8300-tdep.c, remote-hms.c, tm-h8300.h: too many changes to count
+ * symtab.c (lookup_reference_type, lookup_ptr_type): use
+ TARGET_PTR_BIT to determine size of a pointer
+ * values.c (unpack_long): when unpacking a REF or a PTR don't
+ assume the size of the type.
+
+Wed Feb 5 22:29:59 1992 John Gilmore (gnu at cygnus.com)
+
+ * mipsread.c (parse_symbol): Avoid clobbering enum pointer when
+ looking at its members. Improve guess between struct and union,
+ only assuming union if multiple members have offsets of zero.
+
+Tue Feb 4 18:05:44 1992 Per Bothner (bothner at cygnus.com)
+
+ * mipsread.c: Use (FP0_REGNUM-32) instead of magic number 6.
+ (This is just for clarity - and one day permitting us to
+ change FP0_REGNUM from 38 to 32, which would make more sense.)
+ * tm-mips.h: Added STAB_REG_TO_REGNUM macro, so that
+ register numbers in stabs-in-ecoff get handled correctly.
+
+Sat Feb 1 04:45:10 1992 Stu Grossman (grossman at cygnus.com)
+
+ * xm-vax.h, xm-vaxult.h, xm-vaxbsd.h, config/mh-vaxult,
+ config/mh-vaxbsd, configure.in: Split up config stuff for Vaxen
+ into BSD and Ultrix.
+
+Sat Feb 1 04:39:41 1992 John Gilmore (gnu at cygnus.com)
+
+ * dbxread.c (dbx_symfile_init): Call malloc, not xmalloc.
+
+Sat Feb 1 04:15:41 1992 Stu Grossman (grossman at cygnus.com)
+
+ * Makefile.in: Increment version to 4.4.1.
+ * main.c (print_gdb_version): Update copyright notice.
+
+Sat Feb 1 01:43:11 1992 Per Bothner (bothner at cygnus.com)
+
+ * mipsread.c: Prepend "struct " to the names of structure
+ types, and similarly for enums and unions. (This used
+ to be done, but got lost in the re-write to "guess" the
+ difference between enum/struct/union.)
+ Also, guess that a tag is an enum if the first member
+ has type btNil.
+
+Fri Jan 31 21:45:51 1992 Stu Grossman (grossman at cygnus.com)
+
+ * xm-vax.h: #ifndef ultrix around #include of endian.h and
+ limits.h (sigh).
+
+Fri Jan 31 00:05:01 1992 John Gilmore (gnu at cygnus.com)
+
+ * Projects: Patching executables is done.
+ * Makefile.in (VERSION): Roll to gdb-4.4.
+ * README, WHATS.NEW: Update for gdb-4.4.
+
+ * symfile.c (reread_symbols): Whenever we reread one object
+ file's symbols, we must restart the scan, because the object_files
+ chain has been permuted.
+
+ * exec.c (exec_files_info): Split out into print_section_info.
+ Print BFD filename of each section if it's not the default one.
+ * core.c (core_files_info): Call print_section_info.
+
+ * xm-vax.h: Include a few system header files whose definitions
+ must precede defs.h.
+ * language.c, language.h: Make some things const.
+ * expression.h, main.c: const spreads like ooze.
+
+ * mem-break.c (break_insn, break_insn_size): Use unsigned chars,
+ since BREAKPOINT values can be >0x80.
+
+Thu Jan 30 17:21:14 1992 Stu Grossman (grossman at cygnus.com)
+
+ * infrun.c, xm-i386sco.h: SCO needs to use setpgid().
+
+Thu Jan 30 01:04:23 1992 John Gilmore (gnu at cygnus.com)
+
+ * sparc-pinsn.c: Remove kludge for preferring architectures.
+ Remove #ifdef's for SORT_NEEDED. We need to sort the table, now
+ and forever. Add `add' instruction to the set that get checked
+ for a preceding `sethi' in order to print an absolute address.
+ Corresponding changes in ../include/opcode/sparc.h needed
+ to eliminate garbage instructions.
+
+Wed Jan 29 19:24:34 1992 Per Bothner (bothner at cygnus.com)
+
+ * mipsread.c (parse_partial_symbols): Make sure partial
+ symbols are created for external symbols (as used to be
+ the case). This is a bit of a pain with the mips-coff.
+ It uses a table which points to all of the external
+ symbols belonging to a particular FDR or psymtab.
+ Once we've generated this table, we might as well save
+ it, and then use it in psymtab_to_symtab_1 to find
+ the symbols to pass to parse_external().
+ * symfile.c, symfile.c: New function start_psymtab_common
+ to share the common parts of allocating a new psymtab
+ for dbxread, mipsread (and later dwarfread). Its code
+ was pulled out from start_psymtab in dbxread.c.
+ * dbxread.c (start_psymtab): Use start_psymtab_common().
+
+ * valprint.c (val_print): If there is an error when trying
+ to print a string, check to see if there really is a problem
+ by reading just one character. If that works, assume
+ things are ok.
+
+Wed Jan 29 18:58:43 1992 Stu Grossman (grossman at cygnus.com)
+
+ * sparc-pinsn.c (compare_opcodes): Make it prefer v6, v7,
+ cypress, v8 mnemonics in that order.
+
+Tue Jan 28 17:32:13 1992 Per Bothner (bothner at cygnus.com)
+
+ * sparc-pinsn.c: Put the qsort() back in.
+
+Mon Jan 27 18:51:03 1992 John Gilmore (gnu at cygnus.com)
+
+ * findvar.c (read_register, write_register): Handle machines
+ where REGISTER_TYPE is not the same size as "int".
+
+ Handle debug symbols in dynamically loaded (relocated) code:
+
+ * dbxread.c (read_ofile_symtab): Fix up N_CATCH better. Pass
+ offset to process_one_symbol.
+ (process_one_symbol): Take new offset parameter. Add it into
+ appropriate symbol types to relocate symbols to loaded addresses.
+ Handle all possible symbol types, and complain() about types that
+ we don't expect to see.
+ * mipsread.c (psymtab_to_symtab_1): Pass offset of zero to
+ process_one_symbol (FIXME, should pass real offset).
+
+ Misc bugfixes:
+
+ * breakpoint.c (resolve_sal_pc): Split out code to resolve a
+ sal's PC value.
+ (set_breakpoint, break_command_1, until_break_command,
+ catch_command_1, breakpoint_re_set_one): Use it.
+ * symtab.h (resolve_sal_pc): Declare.
+ * infcmd.c (jump_command): Use resolve_sal_pc.
+
+ * source.c (list_command): Shorten "FILE, line N" to "FILE:N".
+
+ * putenv.c (putenv): Avoid unportably casting pointers to unsigneds.
+
+ * c-exp.y (yylex): `this' and `template' are only tokens in C++.
+
+ * xm-convex.h, xm-hp300bsd.h, xm-isi.h, xm-merlin.h, xm-news.h,
+ xm-np1.h, xm-pn.h, xm-pyr.h, xm-rtbsd.h, xm-symmetry.h, xm-umax.h:
+ Remove MISSING_VPRINTF declaration, and superfluous "kgdb" defines.
+
+Mon Jan 27 15:46:21 1992 Stu Grossman (grossman at cygnus.com)
+
+ * dbxread.c (process_one_symbol): Make a first cut at handling
+ symbol tables generated by Sun's acc. (#ifdef'd out, FIXME.)
+
+ * symtab.c (find_pc_line): Fix stepping into and out of #included
+ files.
+
+Mon Jan 27 13:00:55 1992 Stu Grossman (grossman at cygnus.com)
+
+ * Makefile.in (OPCODES): Remove OPCODES defs and refs. There is
+ no longer any need to copy ../include/opcode/* into gdb.
+
+Mon Jan 27 12:30:38 1992 John Gilmore (gnu at cygnus.com)
+
+ * ChangeLog, ChangeLog-9091: Split ChangeLog at 1992.
+
+Sun Jan 26 19:05:40 1992 Per Bothner (bothner at cygnus.com)
+
+ * valprint.c (type_print_base, type_print_method_args):
+ Print C++ constructor methods without bogus "return type."
+
+Sat Jan 25 15:57:59 1992 Fred Fish (fnf at cygnus.com)
+
+ * infptrace.c (child_xfer_memory): Parameter "target" should
+ be a pointer to a structure, not the entire structure.
+
+Fri Jan 24 01:30:27 1992 Fred Fish (fnf at cygnus.com)
+
+ * depend: Convert the couple of references to ansidecl.h that
+ used the local gdb version to use the ../include version.
+
+Thu Jan 23 22:24:43 1992 Fred Fish (fnf at cygnus.com)
+
+ * procfs.c
+ (child_xfer_memory): Takes pointer to a struct, not entire struct.
+ (inferior_proc_init): Fix non-ANSI version of args.
+ (attach): Call print_sys_errmsg with correct number of args.
+ (mappingflags): Make static, does not need to be global.
+
+ * i386-tdep.c (i386_frame_num_args): Takes a pointer to a struct
+ not the entire struct itself.
+
+ * valops.c (value_assign): Cast some args to modify_field() and
+ {read,write}_register_bytes() correctly.
+
+ * ansidecl.h: Removed, is duplicate of ../include/ansidecl.h
+
+ * Makefile.in (MALLOCSRC): Removed reference to removed local
+ copy of ansidecl.h.
+
+ * dwarfread.c (list_in_scope): Needs an initial value, use file
+ scope.
+
+Mon Jan 20 19:06:28 1992 Stu Grossman (grossman at cygnus.com)
+
+ * main.c (main): Make option_index local to keep new getopt happy.
+ main.c, solib.c, Makefile.in: Update copyright notices.
+
+Mon Jan 20 08:54:00 1992 Michael Tiemann (tiemann at cygnus.com)
+
+ * cplus-dem.c (cplus_demangle): Correctly demangle destructors.
+
+Sat Jan 18 17:17:45 1992 Stu Grossman (grossman at cygnus.com)
+
+ * Makefile.in (HFILES): Add partial-stab.h.
+
+Sat Jan 18 16:45:01 1992 Fred Fish (fnf at cygnus.com)
+
+ * config/mh-stratus, config/mt-stratus, tm-stratus.h, xm-stratus.h:
+ New files for stratus. Not complete enough to actually build
+ on the Stratus machine; that awaits copyright assignment for
+ i860 changes.
+
+ * Makefile.in (USER_CFLAGS): Add macro specifically reserved
+ for getting custom flags into CFLAGS when doing makes.
+
+ * configure.in: Add config information for stratus.
+
+Thu Jan 16 00:51:46 1992 Fred Fish (fnf at cygnus.com)
+
+ * dbxread.c (process_one_symbol): Pass address of structure
+ to complain(), rather than the whole structure.
+
+Wed Jan 15 09:56:16 1992 Fred Fish (fnf at cygnus.com)
+
+ * solib.c (solib_add_common_symbols): Only compile in when not
+ using SVR4 style shared libraries.
+
+Tue Jan 14 22:34:00 1992 Fred Fish (fnf at cygnus.com)
+
+ * dwarfread.c (locval): Add offreg flag to indicate location
+ values that are computed off a base register.
+
+ * dwarfread.c (new_symbol): Rework TAG_global_variable and
+ TAG_local_variable cases to account for static variables
+ within function scopes.
+
+Tue Jan 14 12:28:52 1992 Stu Grossman (grossman at cygnus.com)
+
+ * inflow.c: remove #include <sys/dir.h>. Not necessary, and
+ doesn't exist on some systems.
+
+ * infrun.c (wait_for_inferior!!!!): Prevent gdb from hanging when
+ nexting over recursive function calls.
+
+ * target.c (target_read_string): Create this routine to read null
+ terminated strings from the target. It deals with running off the
+ end of memory elegantly as well. solib.c (find_solib): Use
+ target_read_string() to avoid problems with running off the end of
+ memory.
+
+ * inflow.c (child_terminal_info): #ifdef TIOCPGRP around lines
+ that reference pgrp_inferior.
+
+Mon Jan 13 14:57:11 1992 Per Bothner (bothner at cygnus.com)
+
+ * tm-mips.h: Removed BLOCK_ADDRESS_ABSOLUTE, now that
+ mips-tfile has been hacked to act more "traditionally."
+ * dbxread.c: Fixed typo in comment.
+
+Sun Jan 12 13:08:36 1992 Per Bothner (bothner at cygnus.com)
+
+ * mips-tdep.c (mips_skip_prologue): Add some number of
+ 'sw' instructions before 'addiu' adjusts the stack.
+
+Fri Jan 10 13:47:06 1992 Fred Fish (fnf at cygnus.com)
+
+ * dwarfread.c (start_symtab, end_symtab, scopecount, openscope,
+ freescope, buildblock closescope, record_line, add_symbol_to_list,
+ gatherblocks, make_blockvector): Extensive changes to switch
+ to generic symbol table building code in buildsym.c. Remove
+ scope tree structures and functions, symbol table building
+ functions, and lots of other small changes.
+
+ * dwarfread.c: Add new macros GCC_PRODUCER and STREQN. Remove
+ GCC_COMPILED_FLAG_SYMBOL and GCC2_COMPILED_FLAG_SYMBOL.
+
+Tue Jan 7 13:09:57 1992 Stu Grossman (grossman at cygnus.com)
+
+ * buildsym.c (cleanup_undefined_types): Add support for enums.
+ This fixes the 'GDB internal error. cleanup_undefined_types with
+ bad type' problem.
+
+Sun Jan 5 09:47:50 1992 Stu Grossman (grossman at cygnus.com)
+
+ * dbxread.c: detect gcc2 compilations.
+
+Thu Jan 2 15:07:41 1992 John Gilmore (gnu at cygnus.com)
+
+ * sparc-pinsn.c: Rename bitfields that overlap with macro names
+ in ../include/opcode/sparc.h.
+
+Wed Jan 1 04:29:00 1992 Fred Fish (fnf at cygnus.com)
+
+ * Makefile.in: Change tm-svr4.h to tm-sysv4.h. Change xm-svr4.h
+ to xm-sysv4.h. Split OPCODE_DIR into OPCODE_DIR1 and OPCODE_DIR2
+ to reflect actual locations of opcode files, so TAGS target will
+ be buildable.
+
+ * i386-tdep.c: Change an erroneous 'm68k' reference to 'i386'.
+
+ * i386-tdep.c (supply_fpregset, fill_fpregset): Remove m68k
+ code.
+
+ * m68k-tdep.c (supply_fpregset, fill_fpregset): Fix array
+ dereferencing to access the correct elements.
+
+ * valops.c (value_addr): Declare return type of external func
+ value_copy().
+
+ * xcoffread.c: Undefine next_symbol_text before redefining it.
+
+For older changes see ChangeLog-9091
+
+Local Variables:
+mode: indented-text
+left-margin: 8
+fill-column: 74
+version-control: never
+End:
diff --git a/gdb/ChangeLog-93 b/gdb/ChangeLog-93
new file mode 100644
index 00000000000..463154d9ce8
--- /dev/null
+++ b/gdb/ChangeLog-93
@@ -0,0 +1,7597 @@
+Fri Dec 31 14:33:49 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * nindy-share/nindy.c: Fix order of arguments to store_unsigned_integer
+ (second and third arguments were reversed).
+ (say): Use varargs.
+
+Fri Dec 31 12:13:47 1993 Jim Kingdon (kingdon@deneb.cygnus.com)
+
+ * remote-mips.c: Add timeout parameter to mips_request and
+ mips_receive_packet.
+ (callers): pass in mips_receive_wait except mips_initialize (where
+ we use it to clean up the kludge where we had been changing
+ mips_receive_wait temporarily) and mips_wait (where we pass in
+ -1 for no timeout).
+
+Fri Dec 31 14:33:49 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stack.c (print_block_frame_locals): Also print LOC_BASEREG variables.
+
+Fri Dec 31 06:55:38 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * symtab.c (find_methods): Call fprintf_symbol_filtered with DMGL_ANSI.
+
+Thu Dec 30 10:16:54 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * values.c (unpack_long): Fix garbled error message.
+
+ * remote-mips.c (mips_error): New function.
+ * remote-mips.c: Use it instead of error() most places.
+ * remote-mips.c (mips_receive_packet): New arg throw_error.
+ (mips_initialize): Use it not catch_errors.
+ * defs.h: Declare error_pre_print and warning_pre_print here...
+ * main.c: ...not here.
+
+ * breakpoint.c (breakpoint_chain): Make static.
+ * breakpoint.c, breakpoint.h (frame_in_dummy): New function.
+ * stack.c (print_frame_info): Use it.
+
+Thu Dec 30 07:41:36 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * exec.c (add_to_section_table): Check for SEC_ALLOC instead of
+ SEC_LOAD to handle .bss segments properly.
+
+Thu Dec 30 10:16:54 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * infrun.c (wait_for_inferior): Enable code which assumes that if
+ we jump into the prologue from another function, then it was a
+ subroutine call. #if 0 AT_FUNCTION_START; the above code should
+ take care of this case.
+
+Wed Dec 29 12:32:08 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * valprint.c (val_print_string): Change chunksize from 200
+ to 8.
+
+ * symfile.c (generic_load): If no arguments, get file name
+ from get_exec_file.
+
+ * c-exp.y: Revert Kung's change. "..." is not a type, and the
+ change caused "p (...)0" to dump core.
+ * gdbtypes.c (check_stub_method): Don't pass "..." to
+ parse_and_eval_type. This should fix the bug which Kung was
+ trying to fix.
+
+ * stabsread.c (define_symbol): If we choose not to combine
+ two symbols, don't just ignore the second (LOC_REGISTER) one.
+ * printcmd.c (print_frame_args): If we have a LOC_ARG and a
+ LOC_REGISTER, use the LOC_ARG not the LOC_REGISTER.
+
+Tue Dec 28 15:08:00 1993 Fred Fish (fnf@deneb.cygnus.com)
+
+ * solib.c (DEBUG_BASE): Remove macro and all references.
+ * solib.c (debug_base_symbols): Add array of symbols to lookup.
+ * solib.c (IGNORE_FIRST_LINK_MAP_ENTRY): Add macro.
+ * solib.c (look_for_base, locate_base): Use debug_base_symbols.
+ * solib.c (find_solib): Use IGNORE_FIRST_LINK_MAP_ENTRY.
+
+Tue Dec 28 12:06:57 1993 Kung Hsu (kung@cirdan.cygnus.com)
+
+ * c-exp.y : fix grammar to parse ellipsis (...)
+
+Mon Dec 27 18:42:14 1993 Kung Hsu (kung@cirdan.cygnus.com)
+
+ * stabsread.c (read_type): fix problem when reading static member
+ of a class. caused by change to allow :: inside template
+ instantiated name.
+
+Mon Dec 27 11:07:05 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdbtypes.h: Expand on comments for TYPE_CODE_BITSTRING and
+ TYPE_CODE_STRING a bit.
+
+ * m68k-tdep.c (m68k_skip_prologue, m68k_find_saved_regs):
+ Allow pea %fp; move.l %sp, %fp instead of link instruction to
+ set up the new frame.
+
+ * main.c (init_main): Change "set remotedebug" back to var_zinteger
+ from var_boolean.
+
+ * c-exp.y (yylex): Don't try to deal with nested types.
+
+ * cp-valprint.c (cplus_print_value): Call check_stub_type on
+ TYPE_BASECLASS (type, i) before we look at its name.
+
+ * dbxread.c: Move default definition of GCC_COMPILED_FLAG_SYMBOL
+ from here . . .
+ * symtab.h: . . . to here.
+ * dbxread.c (record_minimal_symbol): Move check for gcc{,2}_compiled.
+ and __gnu_compiled* from here . . .
+ * minsyms.c (prim_record_minimal_symbol_and_info): . . . to here.
+ * minsyms.c (prim_record_minimal_symbol): Call
+ prim_record_minimal_symbol_and_info rather than duplicating code.
+ * minsyms.c, symtab.h (prim_record_minimal_symbol{,_and_info}),
+ coffread.c (record_minimal_symbol),
+ xcoffread.c (RECORD_MINIMAL_SYMBOL), callers: Add objfile parameter.
+
+Sun Dec 26 20:44:02 1993 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * dbxread.c (process_one_symbol): Handle stabs-in-som just like
+ stabs-in-elf.
+ (pastab_build_psymtabs): Likewise.
+
+ * hppa-tdep.c: Change all comments to reference %r3 or frame
+ pointer rather than %r4.
+ (frame_chain, skip_prologue, dig_rp_from_stack): Handle %r3 as the
+ frame pointer.
+
+ * config/pa/tm-hppa.h (FP_REGNUM): Define as %r3.
+ (FIND_FRAME_SAVED_REGS): Handle %r3 as frame pointer.
+ (CALL_DUMMY): Likewise.
+
+Sun Dec 26 16:59:39 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * exec.c (exec_file_command): If error occurs after we have opened
+ exec_bfd but before we call push_target, make sure to close exec_bfd.
+
+ * infrun.c (wait_for_inferior): Remove confusing and inaccurate
+ stuff about subroutine calls, return, etc., from comment which
+ says "We've wandered out of the step range.".
+
+Sun Dec 26 09:18:10 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * infrun.c (wait_for_inferior): When checking whether the line has
+ changed, check the symtab as well.
+
+Sun Dec 26 09:18:10 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdbtypes.c (force_to_range_type): Use switch statement.
+ complain() not warning() if the TYPE_CODE isn't one we know how to
+ deal with gracefully. Use builtin_type_int not
+ lookup_fundamental_type (the objfile we passed to
+ lookup_fundamental_type was sometimes NULL).
+
+ * valops.c (call_function_by_hand, push_word), defs.h (push_word),
+ convex-xdep.c, m88k-nat.c, i386m3-nat.c, mips-tdep.c, mipsm3-nat.c,
+ ns32km3-nat.c, remote-bug.c, m88k-tdep.c, remote-hms.c, remote-mips.c,
+ config/gould/tm-np1.h, hppa-tdep.c (hppa_fix_call_dummy), remote-vx.c:
+ Use REGISTER_SIZE, unsigned LONGEST, and
+ {store,extract}_unsigned_integer, instead of sizeof
+ (REGISTER_TYPE) and REGISTER_TYPE.
+ * All tm.h files: Change REGISTER_TYPE to REGISTER_SIZE.
+ * hppa-tdep.c (pa_print_fp_reg): Remove unused variable val.
+
+ * Makefile.in (ALLDEPFILES): Remove i386ly-nat.c and m68kly-nat.c.
+ Add lynx-nat.c.
+
+Sat Dec 25 20:05:41 1993 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * hppa-tdep.c (init_extra_frame_info): Correctly adjust the base
+ of the current frame when "fromleaf" is true. Do not adjust the
+ frame base of the innermost frame if it is a leaf function.
+
+Sat Dec 25 13:39:21 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabsread.c (define_symbol): Only combine a p/r pair into a
+ LOC_REGPARM if REG_STRUCT_HAS_ADDR.
+
+Sat Dec 25 09:50:29 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * valops.c (value_struct_elt): Check for (value)-1 return from
+ search_struct_method.
+
+Sat Dec 25 09:50:29 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * defs.h: Move definitions of TARGET_*_BIT after include of tm.h.
+ The old way (using #undef in tm.h) was ugly and asking for
+ trouble, because it makes it possible for some file to use the
+ wrong definition. Move definition of HOST_CHAR_BIT after definition
+ of TARGET_CHAR_BIT.
+ * config/alpha/tm-alpha.h, config/h8300/tm-h8300.h,
+ config/h8500/tm-h8500.h, config/z8k/tm-z8k.h: Don't undef TARGET_*_BIT
+ before defining them.
+
+ * mdebugread.c: Change the builtin_type_* in this file to
+ mdebug_type_* and make them static. Use TYPE_CODE_ERROR for
+ complex and float decimal.
+
+ * printcmd.c (disassemble_command): Call wrap_here between printing
+ address and printing instruction.
+
+Fri Dec 24 14:23:57 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabsread.c (read_type): Don't fall through 'S' case (the case it
+ was falling though happened to do the right thing ("break;") but that
+ is hardly a good thing to assume).
+
+Tue Dec 21 13:32:02 1993 Per Bothner (bothner@kalessin.cygnus.com)
+
+ * ch-exp.y (match_dollar_tokens): Fix off-by-one bug.
+ * ch-lang.c (chill_is_varying_struct), ch-lang.h: New function.
+ * ch-lang.c (chill_printstr): Use double quotes, not single quotes.
+ * ch-typeprint.c (chill_type_print_base): Handle TYPE_CODE_BITSTRING.
+ Improve printing of TYPE_CODE_STRING, TYPE_CODE_SET, and
+ TYPE_CODE_STRUCT (including checking chill_is_varying_struct).
+ Print TYPE_DUMMY_RANGE by printing its TYPE_TARGET_TYPE.
+ Handle TYPE_CODE_ENUM.
+ * ch-valprint.c (chill_val_print): Handle TYPE_CODE_BITSTRING.
+ For TYPE_CODE_STRING, never print address. Handle VARYING strings.
+ * gdbtypes.c (force_to_range_type): New.
+ * gdbtypes.c (create_set_type): Make work, following Chill layout.
+ * gdbtypes.h (TYPE_LOW_BOUND, TYPE_HIGH_BOUND, TYPE_DUMMY_RANGE): New.
+ * stabsread.c (read_type): Distinguish string and bitstring from
+ char-array and set.
+ * valarith.c (value_subscript), valops.c (value_coerce_array):
+ Handle STRINGs as well as ARRAYs.
+ * valarith.c (value_bit_index): Fix think. Use new macros.
+
+
+Fri Dec 17 10:45:32 1993 Kung Hsu (kung@cirdan.cygnus.com)
+
+ * symtab (decode_line_1): fix a bug when position char is not
+ set correctly.
+ * c-valprint (c_val_print): handle vtbl printing when vtbl is not
+ set up yet.
+
+Thu Dec 16 16:46:01 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * mips-tdep.c (read_next_frame_reg): If SIGFRAME_REG_SIZE is not
+ defined, define it as 4.
+
+Thu Dec 16 13:08:01 1993 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * config/m68k/nm-hp300bsd.h: Correctly identify 4.3BSD vs 4.4BSD.
+
+ * config/m68k/tm-hp300bsd.h (REMOTE_BPT_VECTOR): Define.
+
+ * config/m68k/tm-m68k.h (REMOTE_BPT_VECTOR): Allow targets to
+ override.
+ (REMOTE_BREAKPOINT): Likewise.
+
+Thu Dec 16 09:14:58 1993 Jeff Law (law@snake.cs.utah.edu)
+
+ * hpread.c (read_hp_function_type): Correctly handle
+ pass-by-value structures > 64bits in size.
+ (process_one_debug_symbol): Likewise.
+
+Mon Dec 13 20:17:39 1993 Per Bothner (bothner@kalessin.cygnus.com)
+
+ Implement support for Chill POWERSETs.
+ * ch-exp.y (operand_2): Implement 'Element IN PowerSet'.
+ * ch-typeprint.c (chill_type_print_base): Handle POWERSETs.
+ * ch-valprint.c (chill_val_print): Handle TYPE_CODE_SET.
+ * eval.c (evaluate_subexp): Implement BINOP_IN.
+ * expression.h (enum exp_opcode): Added BINOP_IN.
+ * gdbtypes.c (create_set_type), gdbtypes.h: New function.
+ * stabsread.c (read_type): If 'S', create a set type.
+ * valarith.c (value_bit_index, value_in), value.h: New functions,
+ for indexing in SETs.
+
+Mon Dec 13 06:42:37 1993 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * paread.c (pa_symfile_init): Check for the existance of stabs
+ after DBX_TEXT_SECT has been initialized.
+
+Tue Nov 23 17:29:28 1993 Steve Chamberlain (sac@jonny.cygnus.com)
+
+ * config/h8300/tm-h8300.h (BREAKPOINT): Insn changed to sleep.
+ (DECP_PC_AFTER_BREAK): Now is 0.
+ * config/h8500/tm-h8500.h (REGISTER_BYTES, REGISTER_BYTE,
+ REGISTER_NAMES): update to new view. (INIT_EXTRA_FRAME_INFO): No
+ extra frame info now.
+ * config/sh/sh.h (NOP): Define NOP insn.
+ * config/z8k/tm-z8k.h (BIG): is now sim_z8001_mode.
+ * config/z8k/z8ksim.mt (TDEPFILES): Add remote-sim.o to list.
+ * ser-go32.c: Lint. (strncasecmp): Removed, now in libiberty.
+ (go32_readchar): Special handling for faster polling. (async
+ structure): Volatile.
+ * h8300-tdep.c (print_register_hook): Allocate and use the right
+ number bytes for the raw register.
+ * h8500-tdep.c (regoff, frame_find_saved_reg, examine_prologue):
+ deleted. (h8500_register_size, h8500_register_virtual_type, ):
+ Use new way of counting registers.
+ * remote-e7000.c (echo_index): deleted. (expect): Better handling
+ of user interrupts. (expect_prompt): Remove never used log file
+ support. (want, want_nopc): Add support for H8/300H.
+ (fetch_regs_from_dump): Treat \r and \n as whitespace.
+ (e7000_drain): Send an "end" command before waiting for output to
+ stop. (e7000_wait): Cope with H8/300H, better handling of user
+ interrupts. (why_stop, expect_n, sub2_from_pc): New function.
+ * remote-utils.c (gr_load_image): call fflush and QUIT more regularly.
+ * utils.c (notice_quit): New function for polling for user interrupts.
+
+Fri Dec 10 15:53:56 1993 Per Bothner (bothner@kalessin.cygnus.com)
+
+ * stabsread.c (read_array_type): Allow negative array bounds,
+ without interpreting that to mean "adjustable."
+ * ch-valprint.c (chill_val_print): Handle RANGE types.
+ * ch-typeprint.c (chill_type_print_base): Handle BOOL.
+ Handle variant records. Handle RANGE types.
+
+Tue Dec 7 15:41:32 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * config/mips/idt.mt: Use tm-idt.h instead of tm-bigmips.h.
+ * config/mips/idtl.mt: Use tm-idtl.h instead of tm-mips.h.
+ * config/mips/tm-idt.h, config/mips/tm-idtl.h: New files; use
+ different BREAKPOINT value for IDT.
+
+ * mipsread.c: Include bfd.h and coff/sym.h.
+
+Mon Dec 6 16:34:10 1993 K. Richard Pixley (rich@cygnus.com)
+
+ * ser-unix.c (set_tty_state): set the rest of the terminal state
+ pieces.
+
+Mon Dec 6 12:01:37 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * configure.in: Recognize mips* for all mips targets.
+ (mips*el-*-elf*, mips*-*-elf*): New targets; use idt and idtl.
+
+ Added Irix 5 support.
+ * configure.in (mips-sgi-irix5*): New host and target. Use irix5
+ for both.
+ * config/mips/irix5.mh, config/mips/irix5.mt,
+ config/mips/xm-irix5.h, config/mips/nm-irix5.h,
+ config/mips/tm-irix5.h, irix5-nat.c: New files for Irix 5 support.
+ * mdebugread.c: New file, split out of mipsread.c. Added
+ elfmdebug_build_psymtabs routine. Added some checks on external
+ symbols. Changed code to keep ecoff_debug_info and
+ ecoff_debug_swap structs in the psymtab and in global pointers
+ rather than retrieving them from the bfd. Also changed to keep
+ the pending list with the psymtab rather than the objfile (each
+ psymtab for a single objfile points to the same pending list).
+ * mipsread.c: Bulk of file moved into mdebugread.c, leaving just
+ the sym_fns.
+ * Makefile.in (SFILES): Added mdebugread.c.
+ (OBS): Added mdebugread.o.
+ (mdebugread.o): New target.
+ * symfile.h: Declare mdebug_build_psymtabs and
+ elfmdebug_build_psymtabs.
+ * elfread.c (struct elfinfo): Added mdebugsect field.
+ (elf_locate_sections): Remember location of .mdebug section.
+ (elf_symfile_read): Call elfmdebug_build_psymtabs on .mdebug
+ section.
+ * infrun.c (AT_FUNCTION_START): Set to 0 if not already defined.
+ (wait_for_inferior): Use AT_FUNCTION_START if it is defined to see
+ if PC is at the start of a function.
+ * mips-tdep.c (read_next_frame_reg): Use SIGFRAME_REG_SIZE, and
+ give it a default definition.
+ (mips_skip_prologue): Skip instructions which initialize $gp
+ register.
+ (in_sigtramp): New procedure, moved in from mipsread.c.
+ * config/mips/tm-mips.h: Declare in_sigtramp.
+
+ * serial.h (serial_fdopen): Make parameter const to match
+ function definition.
+
+Fri Dec 3 14:20:43 1993 Stu Grossman (grossman at cygnus.com)
+
+ * config/mips/irix4.mh: Enable ser-tcp.o.
+
+Tue Nov 30 15:24:24 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * Makefile.in (check): Do not use subdir_do, so that
+ TARGET_FLAGS_TO_PASS is used correctly.
+
+Mon Nov 29 16:10:38 1993 Stu Grossman (grossman at cygnus.com)
+
+ * i386-nlmstub.c: Undo I/O redirection changes by Tom Lord.
+ These definitely won't work under Netware.
+
+Mon Nov 29 15:34:58 1993 Kung Hsu (kung@cirdan.cygnus.com)
+
+ * stabsread.c(read_struct_field): Fix the check when getting to
+ member functions.
+
+Mon Nov 29 16:48:16 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ gcc -Wall -O lint:
+ * mips-tdep.c (heuristic_proc_desc): Initialize reg30 to avoid
+ warning. Unnest comment.
+ (init_extra_frame_info): Remove unused variable mask.
+ (MASK): Fully parenthesize.
+ (mips_push_dummy_frame): Remove unused variable val.
+ (mips_skip_prologue): Remove unused variables f and b.
+
+Mon Nov 29 12:23:25 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * mipsread.c (parse_symbol, parse_partial_symbols): Do not create
+ (partial) symbols for opaque struct definitions.
+
+Mon Nov 29 11:36:57 1993 Stu Grossman (grossman at cygnus.com)
+
+ * i386ly-tdep.c (i386lynx_saved_pc_after_call): Change call_inst
+ to unsigned char to avoid domain warning for some values.
+
+Mon Nov 22 23:42:59 1993 Steve Chamberlain (sac@jonny.cygnus.com)
+
+ * remote-e7000.c (e7000_wait): Cope with H8/300 register dump.
+ * config/h8300/h8300hms.mt: Add remote-e7000.
+
+Mon Nov 22 11:03:45 1993 Fred Fish (fnf@cygnus.com)
+
+ Merged changes from kev@spuds.geg.mot.com (Kevin A. Buettner):
+ * gdb/config/m88k/delta88.mh (NATDEPFILES): Added corelow.o and
+ coredep.o to this list.
+ * gdb/m88k-nat.c (m88k_register_u_addr): Avoid error when passed
+ the number for an M88110 extended register by just returning the
+ address of r0.
+
+Sat Nov 20 09:20:51 1993 Fred Fish (fnf@rtl.cygnus.com)
+
+ * go32-xdep.c (re_comp, re_exec): Remove stubs now that gdb
+ always uses it's own version of regex.
+
+Fri Nov 19 18:23:19 1993 Kung Hsu (kung@cirdan.cygnus.com)
+
+ * valops.c(value_struct_elt_for_reference): enhance search operator in
+ c++.
+ * symtab.c(decode_line_1): same as above.
+
+Fri Nov 19 15:08:47 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * symtab.c (decode_line_1): Add comment about use of
+ return_to_top_level directly instead of error. Add comment saying
+ that the '' should not be needed--that the completer should be fixed.
+
+Fri Nov 19 11:00:33 1993 Kung Hsu (kung@cirdan.cygnus.com)
+
+ * symtab.c(decode_line_1): fix the inconsistency of setting
+ breakpoint with '' or without them. The '' is needed when you
+ want name completion.
+
+Thu Nov 18 08:25:50 1993 Fred Fish (fnf@cygnus.com)
+
+ * valprint.c (val_print_string): When looking for a null
+ terminator compare current bufsize to fetchlimit to determine
+ when to stop, instead of computing buffer+fetchlimit which
+ may overflow for very large limits (like "unlimited").
+
+Wed Nov 17 18:23:09 1993 Kung Hsu (kung@cirdan.cygnus.com)
+
+ * eval.c(evaluate_subexp): to use unified search so type conversion
+ operator works in calling method.
+ * valarith.c(value_x_binop, value_x_unop): same as above.
+ * valops.c(search_struct_method): same as above.
+
+Wed Nov 17 18:47:34 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * mipsread.c: Change use of ECOFF information to correspond to
+ changes in bfd/libecoff.h.
+ (mipscoff_symfile_offsets): Made static.
+
+Wed Nov 17 09:43:31 1993 Kung Hsu (kung@cirdan.cygnus.com)
+
+ * valops.c (typecmp): improve prototype matching when calling
+ a method. Make 'p (*(ostream *) &cout) << "lll" ' to work.
+ * eval.c(evalute_subexp): fix operator search problem when call
+ like p x.'operator+'(i).
+
+Tue Nov 16 17:15:03 1993 Stu Grossman (grossman at cygnus.com)
+
+ * i386ly-nat.c, i386lynx-nat.c, m68kly-nat.c: Remove. Move
+ common code into lynx-nat.c.
+ * lynx-nat.c: New module. Contains portable code for Lynx native
+ stuff (mostly ptrace related).
+ * config/i386/i386lynx.mh (NATDEPFILES): i386ly-nat.o -> lynx-nat.o
+ * config/m68k/m68klynx.mh (NATDEPFILES): i386ly-nat.o -> lynx-nat.o
+
+ * config/nm-lynx.h, config/tm-lynx.h: New files to contain
+ non-architecture specific native and target defs.
+ * config/i386/nm-i386lynx.h, config/i386/tm-i386lynx.h,
+ config/m68k/nm-m68klynx.h, config/m68k/tm-m68klynx.h: Move all
+ (arch) portable stuff into ../{tm nm}-lynx.h.
+
+Tue Nov 16 13:33:47 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * symtab.c (gdb_mangle_name): Only assume that the physname is
+ the entire mangled name if it looks like the mangled name of a
+ constructor. Needed for testsuite to work with GCC 2.4.5.
+
+ * a68v-nat.c: Replace with new version from Troy Rollo. The
+ version I am replacing appears to be an old copy of sun3-nat.c.
+ * dstread.c (dst_symfile_read): Replace sort_all_symtab_syms call
+ with loop.
+
+ * Makefile.in (TAGS): Depend on TAGFILES_{NO,WITH}_SRCDIR.
+
+ * Makefile.in: (HFILES,TAGFILES): Split into _WITH_SRCDIR and
+ _NO_SRCDIR versions.
+ (TAGS): Only add srcdir to TAGFILES_NO_SRCDIR.
+ (This is part of a long saga involving me putting srcdir on
+ everything (perhaps for now-obsolete reasons, I forget), Rich
+ removing the srcdir from everything, Stu putting it back some
+ places for Sun make, and me just now getting around to fixing
+ `make TAGS' again).
+
+Mon Nov 15 12:29:10 1993 Kung Hsu (kung@cirdan.cygnus.com)
+
+ * stack.c(print_frame_info): print demangled function name
+ ansi style.
+
+Mon Nov 15 14:32:29 1993 Steve Chamberlain (sac@jonny.cygnus.com)
+
+ * remote-e7000.c: New file to cope with the Hitachi E7000 ICE.
+ * remote-utils.c, remote-utils.h (gr_load_image): New function to
+ download to target.
+ * h8300-tdep.c, h8500-tdep.c, remote-z8k.c, sh-tdep.c z8k-tdep.c
+ (sim_load): delete.
+ * remote-sim.c (gdbsim_load): Use gr_load_image, rather than
+ sim_load.
+ * config/sh/sh.mt: Add remote-e7000
+
+Mon Nov 15 11:38:25 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * config/i386/linux.mh: Remove XM_CLIBS, TERMLIB, SYSV_DEFINE, and
+ REGEX.
+ * config/i386/xm-linux.h: Don't include xm-i386v.h. Define
+ HOST_BYTE_ORDER ourselves. Define HAVE_TERMIOS not HAVE_TERMIO.
+ Define NEED_POSIX_SETPGID. Include unistd.h.
+
+Mon Nov 15 12:29:10 1993 Kung Hsu (kung@cirdan.cygnus.com)
+
+ * symtab.c(gdb_mangle_name): fix the problem with constructor
+ name mangling.
+
+Mon Nov 15 11:38:25 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdbtypes.h: Add TYPE_FLAG_TARGET_STUB.
+ * gdbtypes.c (check_stub_type): On TYPE_FLAG_TARGET_STUB, do
+ what cleanup_undefined_types does for arrays, except we clear
+ TYPE_FLAG_TARGET_STUB if we fix up the type.
+ * stabsread.c (cleanup_undefined_types): Add comments about how
+ doing arrays here is no longer the clean way to do it.
+ (read_array_type): Set TYPE_FLAG_TARGET_STUB as well as calling
+ add_undefined_type.
+ * c-typeprint.c, ch-typeprint.c: Move call to check_stub_type
+ outside switch so it happens for all type codes.
+ * cp-valprint.c (cp_print_value_fields): Recurse to val_print,
+ instead of c_val_print, so that check_stub_type gets called.
+
+ * gdbtypes.h, gdbtypes.c, m2-lang.c, ch-lang.c, c-lang.c: Remove
+ TYPE_FLAG_SIGNED. It was inconsistently set, never checked
+ (except in recursive_dump_type), and is pointless.
+
+Mon Nov 15 00:40:38 1993 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * paread.c (pa_symfile_init): Look for the $TEXT$ section rather
+ than the .text section.
+
+Sun Nov 14 00:28:13 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabsread.c: Remove #if 0'd dbx_class_complaint. We now handle
+ this (more or less) gracefully, and complain() was never a good
+ way of dealing with this.
+
+ * stabsread.c (read_type): Skip the colon when reading a
+ cross-reference. Only complain, not error_type, on unrecognized
+ cross-reference types. error_type, not dump core, if the colon is
+ missing.
+
+Fri Nov 12 16:23:08 1993 Stu Grossman (grossman at cygnus.com)
+
+ * config/m68k/tm-sun3.h: Disable use of alternate breakpoint insn
+ when doing remote stuff.
+
+Fri Nov 12 16:22:39 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * c-exp.y (yylex): Call lookup_symtab not lookup_partial_symtab.
+
+ * partial-stab.h: Ignore ':' symbol descriptors. Same case as
+ Kung's stabsread.c change.
+
+Fri Nov 12 11:18:02 1993 Kung Hsu (kung@cirdan.cygnus.com)
+
+ * stabsread.c (patch_block_stabs, define_symbol, read_type): in
+ g++ template instantiation, nested class can be part of the
+ params, and '::' can gets into symbol or type names. This is
+ to fix the problem.
+
+ * gdbtypes.c (lookup_struct_elt_type): Handle type ref or pointer
+ to struct/union case.
+
+Fri Nov 12 10:39:31 1993 Stu Grossman (grossman at cygnus.com)
+
+ * coff-solib.c (coff_solib_add): Cast result of alloca().
+ * m68k-tdep.c (m68k_saved_pc_after_call): Get rid of
+ GDB_TARGET_IS_SUN3. Use more general SYSCALL_TRAP macro.
+ * config/m68k/m68klynx.mh (NATDEPFILES): Remove exec.o (it's
+ already in TDEPFILES).
+ * config/m68k/tm-m68k.h (SAVED_PC_AFTER_CALL): Use
+ m68k_saved_pc_after_call.
+ * Remove all Sun3 specific stuff.
+ * (FIX_CALL_DUMMY): Cast arg to bfd_putb32 to unsigned char *.
+ * config/m68k/tm-m68klynx.h: Define SYSCALL_TRAP as trap #10.
+ Disable REMOTE_BREAKPOINT mechanism.
+ * config/m68k/tm-sun3.h: Get rid of GDB_TARGET_IS_SUN3.
+ * Protect from multiple includion.
+ * Move Sun3 specific stuff from tm-m68k.h to here.
+ * Define SYSCALL_TRAP as trap #0.
+ * Remove def of SAVED_PC_AFTER_CALL (now in tm-m68k.h).
+ * gdbserver/low-lynx.c: Redo all register store/fetch stuff to
+ make it portable for 386 and 68k.
+
+Fri Nov 12 09:53:26 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * mips-tdep.c (init_extra_frame_info): Check to see whether the
+ registers mentioned in the proc_desc have been saved. This
+ generalizes mips_in_lenient_prologue in the sense that we keep
+ searching until we've found saves for all the registers, not just
+ look for a "lenient prologue" pattern.
+ * mips-tdep.c: #if 0 lenient prologue code.
+
+ * mips-tdep.c (heuristic_proc_desc): Don't assume a host short
+ is 16 bits.
+
+Thu Nov 11 19:58:05 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * config/i386/i386sol2.mh: Comment out corelow.o.
+
+ * printcmd.c (address_info): Use filtered, not unfiltered functions.
+ We should be able to deal with a QUIT here.
+
+Thu Nov 11 15:22:20 1993 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * printcmd.c (address_info): Use fprintf_symbol_filtered
+ to print the symbol name.
+
+ * stabsread.c (define_symbol): Handle cfront lossage for
+ struct/union/enums and typedefs.
+
+ * partial-stab.h (case N_BINCL): Update psymtab_language
+ as appropriate when changing subfiles.
+ (case N_SOL): Update psymtab_language as appropriate when
+ changing subfiles. Add typedef for structs, unions, and enums
+ when processing C++ files.
+
+Thu Nov 11 13:18:47 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * README: Remove information on languages and just cite the (newly
+ updated) information in doc/gdb.texinfo instead.
+
+ * delta68-nat.c: Fix typos (add missing ");" and stuct -> struct).
+
+Wed Nov 10 09:31:10 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * dbxread.c (process_one_symbol, N_RBRAC): Don't clear
+ within_function just because local_symbols is NULL. It appears
+ that this bug has existed since the 10 Apr 89 change which started
+ clearing within_function here.
+
+ * config/m68k/tm-m68k.h: Clean up CALL_DUMMY comment.
+ * config/m68k/{tm-hp300bsd.h,tm-hp300hpux.h,tm-m68k-em.h,
+ tm-monitor.h,tm-sun3.h,tm-vx68.h}, config/sparc/tm-sparc.h:
+ Define BELIEVE_PCC_PROMOTION.
+ * dbxread.c: Remove BELIEVE_PCC_PROMOTION define. The code which
+ used this was moved to stabsread.c a long time ago.
+
+ * dstread.c (dst_sym_fns): Update for flavours.
+ * symfile.c (find_sym_fns): Add kludge for apollo like for rs/6000.
+ * dstread.c (dst_symfile_offsets): Set objfile->num_sections.
+
+ gcc -Wall lint:
+ * thread.c: Include "gdbcmd.h" and <ctype.h>.
+ * Makefile.in: Update dependency.
+ * thread.c (thread_command): Remove unused variable p.
+ * values.c (unpack_double): Use len instead of TYPE_LENGTH (type).
+ * valprint.c (print_floating): Correctly check sign bit now that
+ we are using unsigned arithmetic.
+ * symtab.c (find_pc_line_range): Remove unused variables exact_match,
+ ind, and l.
+
+Tue Nov 9 17:42:25 1993 Kung Hsu (kung@cirdan.cygnus.com)
+
+ * valarith.c (value_x_binop): fix search operator in class bug
+ * valarith.c (value_x_unop): fix search operator in class bug
+
+Tue Nov 9 19:20:17 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * Makefile.in (init.c): Add udi2go32.o to list of files that we
+ should not try to search for _initialize_* functions.
+
+ * remote-udi.c (udi_wait): Change UDIGdb_StdoutReady back to
+ UDIStdoutReady. It accidentally got changed on 24 Oct 93 when
+ stdout was changed to gdb_stdout. Likewise for UDIGetStdout,
+ UDIStderrReady, and UDIGetStderr.
+
+Tue Nov 9 12:48:06 1993 Tom Lord (lord@cygnus.com)
+
+ * remote-hms.c (hms_wait): fixed too many arguments to putc_unfiltered.
+
+Tue Nov 9 12:20:46 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * utils.c (quit): Also call gdb_flush on standard output and error.
+
+ * .gdbinit: Remove "source /.gdbinit". It causes a spurious error
+ if /.gdbinit doesn't exist (and I know of no convention of putting
+ something in /.gdbinit).
+
+Mon Nov 8 18:17:11 1993 Kung Hsu (kung@cirdan.cygnus.com)
+
+ * cp-valprint.c (cp_print_value_fields): change output from <no
+ value> to <optimized out or zero length>
+
+Mon Nov 08 17:05:30 1993 Jeffrey Wheat (cassidy@cygnus.com)
+
+ * Makefile.in: Change RUNTEST_FLAGS back to RUNTESTFLAGS
+ Change RUNTEST = runtest to test for existance of
+ a runtest in the source tree first.
+
+Mon Nov 8 10:42:03 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * Makefile.in: Remove unused variable GCC. Remove "#CC=cc" line
+ which doesn't really relate to anything.
+
+ * Makefile.in (CC_FOR_TARGET): Test for existence of gcc/xgcc, not
+ for existence of gcc/Makefile.
+
+ * inflow.c (terminal_init_inferior), infptrace.c (child_resume):
+ Add comments about use of Lynx PIDGET and how we will want to
+ clean it up.
+
+ * stabsread.c: Remove long_kludge_name code (it was already #if 0).
+ * stabsread.c (read_one_struct_field): Clean up comments to reflect
+ Kung's change of 5 Nov 93.
+ * stabsread.c (read_one_struct_field): Don't give up on unknown
+ visibility character, just shove it in fip->list->visibility.
+ (read_baseclasses): Don't give up on unknown virtual or visibility
+ characters, just assume a reasonable default, complain, and keep
+ going.
+ (attach_fields_to_type): Complain on unrecognized visibility.
+ One result of all this is that '9' (VISIBILITY_IGNORE) can be used
+ in a stab as well as being something which GDB uses internally.
+
+Mon Nov 8 07:57:30 1993 Doug Evans (dje@canuck.cygnus.com)
+
+ * configure.in: Remove h8300h, we have multilib now.
+
+Mon Nov 8 06:11:24 1993 D. V. Henkel-Wallace (gumby@cirdan.cygnus.com)
+
+ * configure.in: Add unixware as a configuration alias for x86
+ sysv4
+
+ * config/i386/i386nw.mt: add i387-tdep.o, exec.o to TDEPFILES
+
+Sun Nov 7 23:49:21 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * symtab.c (decode_line_1, decode_line_2): Do not adjust pc by
+ FUNCTION_START_OFFSET if funfirstline is not set.
+
+Fri Nov 5 17:19:30 1993 Kung Hsu (kung@cirdan.cygnus.com)
+
+ * gdbtypes.h : add a field 'ignore_field_bits in cplus_specific,
+ and macros to handle the bits.
+ * stabsread.c (read_one_struct_field): add VISIBILITY_IGNORE, and
+ for field of length 0, set this bit on.
+ * cp-valprint.c (cp_print_value_fields): for VISIBILITY_IGNORE
+ field, print <no value>.
+
+Fri Nov 5 14:43:46 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * Version 4.11.2.
+
+Fri Nov 5 09:49:22 1993 Stu Grossman (grossman at cygnus.com)
+
+ * inflow.c (terminal_init_inferior): Temporarily use Lynx PIDGET
+ macro to set process groups.
+ * infptrace.c (child_resume): Temporarily use Lynx PIDGET to
+ specify resumption of all threads.
+ * infrun.c (wait_for_inferior): Fix handling of thread-specific
+ breakpoints for systems where DECR_PC_AFTER_BREAK > 0 (ie: backup
+ PC by the right amount when continuing the thread).
+ * thread.c (thread_apply_command): Add the `thread apply'
+ command to apply a given GDB command to a list of threads.
+
+Fri Nov 5 05:58:03 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * Makefile.in (init.c): Don't call sed if filename is empty.
+
+Thu Nov 4 08:27:24 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * dbxread.c (unknown_symchar_complaint): Make message refer to
+ "symbol descriptor" not "symbol type character" for consistency
+ with stabs.texinfo terminology.
+
+ * stabsread.c (read_struct_fields): Accept either '$' or '.' as
+ the character which introduces a cpp_abbrev or anonymous type.
+
+ * c-lang.c (c_printstr): Print "" to stream (like all the other
+ output from this function), not gdb_stdout.
+
+ * dbxread.c (process_one_symbol): Do relocate 'S' symbols by
+ the text offset (revert 12 Oct 93 change).
+
+ * configure.in: Make hppa*-*-hiux* use hppahpux,
+ not non-existent hppahiux.
+
+Wed Nov 3 16:24:09 1993 Kung Hsu (kung@cirdan.cygnus.com)
+
+ * values.c (value_fn_field): when physical name not found, do not
+ error, but return null.
+ * valops.c (value_struct_elt): when name and args match does not
+ mean it is the one, some times a typedef class can have the same
+ member method and args. This probably will not happen with new
+ version of g++, but it does happen in old g++ and cause gdb error.
+
+Wed Nov 3 09:20:18 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ Merge changes for dos x udi:
+ * Makefile.in (udi2go32.o): add rule to build this file
+ * 29k-share/udi/udi2go32.c: new file
+ * config/a29k/a29k-udi.mt: add udi2go32.o
+ * 29k-share/udi/{udr.c, udip2soc.c}: #ifdef out the entire file
+ if __GO32__ is defined. What a hack.
+
+Wed Nov 3 09:20:18 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * remote.c (putpkt, getpkt): Don't call interrupt_query.
+
+ * findvar.c (value_of_register): Rename val to reg_val to avoid
+ name conflict with some (e.g. tm-m68k.h) REGISTER_CONVERT_TO_VIRTUAL.
+
+ * main.c: Add variables source_line_number, source_file_name,
+ source_error, source_error_allocated, and source_pre_error.
+ (command_line_input): If source_file_name set, increment
+ source_line_number and set error_pre_print with them.
+ (source_command): Set source_* and make a cleanup so they get
+ set back.
+
+Tue Nov 2 16:28:34 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stack.c (down_silently_command): Add comment about PR 1913.
+
+ * breakpoint.c (insert_breakpoints, delete_breakpoint): Call
+ target_terminal_ours_for_output before attempting output.
+
+ * fork-child.c (fork_inferior): Fix comment so that it suggests
+ "set shell" rather than having "set env SHELL" affect GDB's
+ operation.
+
+Tue Nov 2 15:03:08 1993 Tom Lord (lord@rtl.cygnus.com)
+
+ * utils.c (vfprintf_unfiltered): don't use maybe_filtered
+ since it involves a fixed size buffer.
+
+Tue Nov 2 13:42:30 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * findvar.c (value_of_register, value_from_register),
+ hppa-tdep.c (pa_print_fp_reg), infcmd.c (do_registers_info),
+ valops.c (value_assign): Use REGISTER_CONVERT_TO_* only if
+ REGISTER_CONVERTIBLE is defined, otherwise just copy the content.
+ Pass desired type to REGISTER_CONVERT_TO_*.
+
+ * config/m68k/tm-m68k.h, config/i960/tm-i960.h (REGISTER_CONVERT_*):
+ Pass length of desired type to store/extract_floating.
+ * config/i386/tm-arm.h, config/i386/tm-i386aix.h,
+ config/i386/tm-sun386.h, config/i386/tm-symmetry.h,
+ config/m88k/tm-m88k.h config/rs6000/tm-rs6000.h (REGISTER_CONVERT_*):
+ Use extract_floating and store_floating with length of desired type.
+ * config/m68k/tm-news.h (STORE,EXTRACT_RETURN_VALUE): Add type
+ parameter to REGISTER_CONVERT_*.
+
+ * config/a29k/tm-a29k.h, config/convex/tm-convex.h,
+ config/gould/tm-np1.h, config/gould/tm-pn.h, config/h8300/tm-h8300.h,
+ config/h8500/tm-h8500.h, config/i386/tm-i386v.h,
+ config/mips/tm-mips.h, config/ns32k/tm-merlin.h,
+ config/ns32k/tm-umax.h, config/pa/tm-hppa.h, config/pyr/tm-pyr.h,
+ config/sh/tm-sh.h, config/sparc/tm-sparc.h, config/tahoe/tm-tahoe.h,
+ config/vax/tm-vax.h, config/z8k/tm-z8k.h (REGISTER_CONVERTIBLE,
+ REGISTER_CONVERT_TO_RAW, REGISTER_CONVERT_TO_VIRTUAL): Remove
+ versions for which REGISTER_CONVERTIBLE is always false.
+ * z8k-tdep.c (register_convert_to_virtual, register_convert_to_raw):
+ Remove, no longer used.
+
+ * alpha-tdep.c (alpha_register_convert_to_raw,
+ alpha_register_convert_to_virtual): New routines to handle
+ the different raw formats in alpha floating point registers.
+ * config/alpha/tm-alpha.h (REGISTER_CONVERTIBLE,
+ REGISTER_CONVERT_TO_VIRTUAL, REGISTER_CONVERT_TO_RAW): Use them.
+
+Tue Nov 2 12:45:23 1993 Stan Shebs (shebs@rtl.cygnus.com)
+
+ * gdbserver/configure.in: Recognize *-*-lynxos* instead of
+ *-*-lynx*, recognize sparc-*-lynxos*.
+ * gdbserver/Makefile.in (install, install_only): Add.
+ * gdbserver/gdbserver.1: New file, man page for gdbserver.
+
+Tue Nov 2 03:01:01 1993 Jeff Law (law@snake.cs.utah.edu)
+
+ * hpread.c: Include <time.h> and <sys/types.h>. Change include
+ of "libhppa.h" to "som.h".
+ (BYTES_IN_WORD): Define.
+ (hppa_sym_fns): "hppa" is 4 characters, not 5.
+
+Mon Nov 1 09:40:21 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * symtab.c, symtab.h, source.c: Change find_line_pc_range to take
+ a struct symtab_and_line argument, rather than a symtab and a line.
+ Re-write it to be based on the address rather than bogusly adding
+ one to the line number and hoping that has something to do with the
+ end of the line.
+
+ * config/m88k/m88k.mh (NATDEPFILES): Remove exec.o.
+
+ * paread.c (pa_symtab_read): Change comments to say ignoring
+ labels really should be handled by the assembler/compiler.
+
+ * Makefile.in: Add -O to CXXFLAGS.
+
+ * TODO: Expand comments on fast watchpoints.
+
+Sun Oct 31 19:45:06 1993 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * paread.c (pa_symtab_read): Also filter out local symbols
+ starting with "L$".
+
+Sun Oct 31 09:28:46 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * symfile.h (sym_fns), symfile.c (find_sym_fns), xcoffread.c,
+ coffread.c, dbxread.c, elfread.c, mipsread.c, nlmread.c, paread.c:
+ Change from using bfd target name to using the flavour.
+
+ * objfiles.h, infcmd.c, symfile.c: Add comments about how various
+ objfiles get created and when we should blow them away.
+
+Sat Oct 30 08:32:53 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * symfile.c (reread_symbols): When re-reading symbols, do all the
+ right operations ourself, rather than calling symbol_file_command.
+ If we re-read something, call clear_symtab_users not just
+ breakpoint_re_set.
+ * objfiles.h, objfiles.c (build_objfile_section_table): No longer
+ static.
+ * symfile.c (clear_symtab_users): Call clear_pc_function_cache.
+ * coffread.c, dbxread.c, elfread.c, mipsread.c, nlmread.c, paread.c
+ (*_symfile_offsets): Set objfile->num_sections.
+ * remote.c (remote_wait), symfile.c (syms_from_objfile):
+ Don't muck with objfile->num_sections now that all the symbol
+ readers set it.
+ * elfread.c: Clean up obsolete comment about handling only DWARF.
+ * paread.c: Remove comment about how we should use an "ordinary"
+ file format with an hppa suffix. There is nothing ordinary about SOM.
+
+ * config/i386/{i386m3.mh,i386mk.mh}, config/mips/mipsm3.mh,
+ config/ns32k/ns32km3.mh: Change MMALLOC_LIB to MMALLOC.
+ * TODO: Update Mach stuff.
+
+Fri Oct 29 16:30:36 1993 Stan Shebs (shebs@rtl.cygnus.com)
+
+ LynxOS support:
+ * configure.in: Change *-*-lynx* to *-*-lynxos*, add
+ sparc-*-lynxos*.
+ * Makefile.in (ALLDEPFILES): Add m68kly-nat.c, sparcly-nat.c.
+ Rename i386lynx-nat.[co] to i386ly-nat.[co].
+ (ALLCONFIG): Add config/{m68k,sparc}/{m68k,sparc}lynx.m[ht].
+ (m68kly-nat.o, sparcly-nat.o): Add rules.
+ * i386ly-tdep.c: Cosmetics.
+ * i386lynx-nat.c: Removed.
+ * i386ly-nat.c: New file, was i386lynx-nat.c.
+ * m68kly-nat.c: New file.
+ * sparcly-nat.c: New file.
+ * config/xm-lynx.h: New file, cpu-independent host info.
+ * config/i386/i386lynx.mh: Changes for consistency.
+ * config/i386/i386lynx.mt: Ditto.
+ * config/i386/tm-i386lynx.h: Ditto.
+ * config/i386/nm-i386lynx.h: Ditto.
+ * config/i386/xm-i386lynx.h: Include config/xm-lynx.h.
+ * config/m68k/m68klynx.mh, config/m68k/m68klynx.mt,
+ config/m68k/tm-m68klynx.h, config/m68k/nm-m68klynx.h,
+ config/m68k/xm-m68klynx.h: New files, M68K LynxOS support.
+ * config/sparc/sparclynx.mh, config/sparc/sparclynx.mt,
+ config/sparc/tm-sparclynx.h, config/sparc/nm-sparclynx.h,
+ config/sparc/xm-sparclynx.h: New files, Sparc LynxOS support.
+
+Fri Oct 29 08:11:29 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * defs.h, findvar.c (extract_floating, store_floating): New functions.
+ * Move SWAP_TARGET_AND_HOST from defs.h to findvar.c because it is
+ now used only by extract_floating and store_floating.
+ * valprint.c (print_floating): Use unsigned arithmetic. Use
+ extract_unsigned_integer instead of SWAP_TARGET_AND_HOST.
+ Change sizeof (float) to 4 and sizeof (double) to 8 (those are always
+ the relevant sizes for this code, which is in #ifdef IEEE_FLOAT).
+ * values.c (unpack_long, unpack_double, value_from_double),
+ valarith.c (value_binop), stabsread.c (define_symbol):
+ Use extract_floating and store_floating instead of
+ SWAP_TARGET_AND_HOST.
+ * config/m68k/tm-m68k.h, config/i960/tm-i960.h (REGISTER_CONVERT_*):
+ Use extract_floating and store_floating.
+ * config/m88k/tm-m88k.h: Add comments (it should be doing the same).
+ * i386-tdep.c (i386_extract_return_value),
+ * remote-nindy.c (nindy_store_registers): Use store_floating.
+
+Fri Oct 29 09:31:38 1993 Steve Chamberlain (sac@rtl.cygnus.com)
+
+ * remote-sim.c (gdbsim_store_register): Change var name so
+ it compiles with non-ANSI compilers.
+
+Fri Oct 29 08:11:29 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * TODO: Add idea for "disassemble" with source.
+
+Fri Oct 29 00:41:01 1993 Fred Fish (fnf@cygnus.com)
+
+ * Makefile.in (VERSION): Bump to 4.11.1 after release and cvs
+ tagging.
+
+Thu Oct 28 09:14:42 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * TODO: Add section on Mach. Stop calling it a "bug list".
+ Remove John's name and email address. Remove item on "always"
+ ("hook-stop" takes care of this). Remove item on executables with
+ no symbols (this works on some machines, at least). Remove item
+ about calling error() during symbol reading (I think all the important
+ ones have been cleaned up). Revise items about signals and remote
+ systems. Remove section on ^Z requiring several continues to make
+ it go (this now works. Perhaps the item is based on confusion over
+ programs (like GDB itself) which catch SIGTSTP and then re-send
+ themselves the signal. PR 2575 might contain relevant info).
+
+Thu Oct 28 16:55:34 1993 Fred Fish (fnf@cygnus.com)
+
+ * NEWS: Note improvements in C++ support, preliminary thread
+ implementation, and LynxOS native and target support for 386.
+
+Thu Oct 28 16:55:34 1993 Fred Fish (fnf@cygnus.com)
+
+ * README: Add note from Peter Schauer about OSF/1 shared
+ libraries. Add note from Pace Willisson about configuring on BSDI
+ BSD/386 release 1.0. Update gdb references to gdb 4.11.
+
+Thu Oct 28 09:14:42 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * NEWS: Add notes about Alpha and "set remotedebug" for UDI.
+
+ * valops.c (value_assign): Change bitfield code to use a buffer of
+ the correct size, rather than an int.
+
+Wed Oct 27 13:43:07 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * config/i386/{i386m3.mt,i386m3.mh},
+ config/mips/{mipsm3.mt,mipsm3.mh},
+ config/ns32k/{ns32km3.mt,ns32km3.mh}: Use correct names for TM_FILE
+ and XM_FILE. Replace host files *mach3-xdep.o with native
+ files *m3-nat.o. Replace host file os-mach3.o with native
+ file m3-nat.o.
+
+ * remote-udi.c: Remove LOG_FILE stuff; superceded by "set remotedebug".
+ * remote-mon.c: Remove commented out "set remotedebug" command.
+ * remote-nindy.c: Clean up comment about wanting alternative to
+ options specified on the GDB command line.
+
+ * fork-child.c (fork_inferior): Set inferior_pid before calling
+ init_trace_fun. Move the code which gets us through the shell
+ to new function startup_inferior.
+ * inferior.h: Declare startup_inferior.
+ * procfs.c (procfs_init_inferior), inftarg.c (ptrace_him):
+ Call startup_inferior.
+ * m3-nat.c (m3_trace_him): Call intercept_exec_calls.
+ * config/nm-m3.h: Don't define STARTUP_INFERIOR.
+ * config/i386/tm-i386m3.h, config/ns32k/tm-ns32k.h,
+ config/mips/tm-mipsm3.h: Don't define START_INFERIOR_TRAPS_EXPECTED.
+
+ * m68k-stub.c: Change vector 13 from SIGFPE to SIGBUS.
+
+Tue Oct 26 22:05:03 1993 Jim Kingdon (kingdon@deneb.cygnus.com)
+
+ * mips-tdep.c (mips_pop_frame): If proc_desc is NULL, don't dump core.
+
+Tue Oct 26 15:07:29 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ gcc -Wall lint:
+ * nlmread.c: Include stabsread.h.
+ * Makefile.in: Update dependencies.
+
+ * remote.c: Change PBUFSIZ back to 400. John's 28 Feb 1992 change
+ to increase it broke the ability to write large chunks of memory
+ with m68k-stub and i386-stub. Now we only use more than 400 on
+ machines where we need that much to write the registers.
+ * remote.c (remote_write_bytes): Eliminate possible abort(). The
+ check for when to abort was off by a few bytes and besides which,
+ it is handled by MAXBUFBYTES, which the caller uses.
+ * m68k-stub.c: Add comments about trap #1 and trap #8 instructions.
+
+Tue Oct 26 08:36:07 1993 Doug Evans (dje@canuck.cygnus.com)
+
+ * remote-sim.h (SIM_ADDR): New type (same as CORE_ADDR).
+ (sim_set_pc): Update prototype.
+ (sim_read, sim_write): Ditto, and use unsigned char *buf.
+ (sim_fetch_register, sim_store_register): Use unsigned char *buf.
+ (sim_info): Pass printf function as argument, add verbose argument.
+ (sim_stop_reason): Renamed from sim_stop_signal, fix prototype.
+ * remote-sim.c (gdbsim_wait): Update call to sim_stop_reason.
+ (gdbsim_files_info): Update call to sim_info.
+
+Tue Oct 26 10:41:29 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * valops.c (value_assign): Call reinit_frame_cache when assigning
+ to a register.
+
+Mon Oct 25 11:08:59 1993 Stu Grossman (grossman at cygnus.com)
+
+ * infrun.c (wait_for_inferior): Fix PC out of objfile bounds
+ check to just use stop_func_name == 0.
+ * remote-udi.c (store_register): Invalidate NPC/PC_REGNUM after
+ changing PC.
+
+Mon Oct 25 14:57:45 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdbserver/{low-lynx.c,low-sparc.c,low-sun3.c}, standalone.c,
+ m3-nat.c, i386m3-nat.c, mipsm3-nat.c, ns32km3-nat.c: bcopy -> memcpy.
+
+ gcc -Wall lint:
+ * breakpoint.c: Include thread.h.
+ * coffread.c: Include stabsread.h.
+ * Makefile.in: Update dependencies.
+ * breakpoint.c (mention): Add bp_call_dummy to switch.
+ * symmisc.c (dump_symtab): Use %d not %ld for line number.
+
+Sun Oct 24 18:29:32 1993 Tom Lord (lord@rtl.cygnus.com)
+
+ * every non-obsolete file except utils.c:
+ Change the stream argument to _filtered to GDB_FILE *.
+ Change all references to stdout/stderr to gdb_stdout/gdb_stderr.
+ Replace all calls to stdio output functions with
+ calls to corresponding _unfiltered functions.
+ Replaced calls to fopen for output to gdb_fopen.
+ Added sufficient goo to utils.c and defs.h to make the above
+ work.
+
+ The net effect is that stdio output functions are only directly
+ used in utils.c. Elsewhere, the _unfiltered and _filtered
+ functions and GDB_FILE type are used.
+
+ In the near future, GDB_FILE will stop being equivalant to
+ FILE.
+
+ The semantics of some commands has changed in a very subtle way:
+ called in the right context, they may cause new occurences of
+ prompt_for_continue() behavior.
+
+ Please respect this change by not reintroducing stdio output
+ dependencies in the main body of gdb code. All output from
+ commands should go to a GDB_FILE.
+
+Sun Oct 24 20:16:38 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * parse.c, parser-defs.h (write_exp_msymbol): New function to write
+ the appropriate expression for a minimal symbol. Taken from c-exp.y
+ and m2-exp.y but handles mst_file_*.
+ * c-exp.y, m2-exp.y: Use it.
+
+Sun Oct 24 09:31:05 1993 Fred Fish (fnf@lisa.cygnus.com)
+
+ * elfread.c (elf_symtab_read): Use bfd convention that both
+ initialized and uninitialized data sections have the SEC_ALLOC
+ flag bit set, but only initialized sections have SEC_LOAD set.
+ SEC_DATA is ignored since it only gets set for initialized
+ data.
+
+Sat Oct 23 14:48:18 1993 Doug Evans (dje@canuck.cygnus.com)
+
+ * remote-sim.h (sim_stop): New enum.
+ (sim_stop_signal): Change prototype, result is enum sim_stop.
+ * remote-sim.c (gdbsim_wait): Update call to sim_stop_signal.
+
+Fri Oct 22 07:49:54 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabsread.c (define_symbol): Skip the whole thing about "pcc
+ promotion" on little-endian machines.
+
+ * remote-vx.c (vx_wait): Rename pid parameter to pid_to_wait_for.
+ Some compilers (legitimately) don't like variables in the
+ function's outermost block whose name is the the same as the name of
+ a parameter.
+
+ Merge Apollo patches from Troy Rollo (troy@cbme.unsw.edu.au):
+ * dst.h, dstread.c, config/m68k/{apollo68b.mt,tm-apollo68b.h}:
+ New files.
+ * config/m68k/nm-apollo68b.h: Add more defines.
+ * configure.in: Recognize apollo target, not just host.
+
+ * configure.in: Add * to end of all OS names.
+
+Fri Oct 22 06:14:01 1993 Fred Fish (fnf@cygnus.com)
+
+ * Makefile.in (ALLPARAM): Add config/m88k/xm-delta88v4.h
+
+Thu Oct 21 12:23:12 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * Makefile.in (init.c): Generate using the source, not munch. This
+ cleans up all kinds of hassles (which nm to use in munch, etc). The
+ new formatting conventions (mostly already followed) are that
+ the name of the _initialize_* routines must start in column zero,
+ and must not be inside #if.
+ * munch: Removed.
+ * Makefile.in: Remove references to munch.
+ * serial.c, remote.c, infptrace.c, maint.c, convex-tdep.c,
+ alpha-tdep.c, hp300ux-nat.c, hppab-nat.c, osfsolib.c, remote-es.c,
+ procfs.c, remote-udi.c, ser-go32.c, ultra3-xdep.c, sh-tdep.c,
+ i960-tdep.c, hppa-tdep.c, h8500-tdep.c, dpx2-nat.c, delta68-nat.c,
+ z8k-tdep.c: Make sure the above conventions are followed. Make
+ sure they are all declared as returning void. Clean up
+ miscellaneous comments and such.
+
+ * sh-tdep.c (sim_load): Add function.
+
+Thu Oct 21 15:58:48 1993 david d `zoo' zuhn (zoo@rtl.cygnus.com)
+
+ * remote-mips.c (mips_wait): add pid argument.
+
+Thu Oct 21 12:23:12 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * Makefile.in (c-exp.tab.o): Remove notice about shift/reduce conflicts
+ which no longer occur.
+
+ gcc -Wall lint:
+ * findvar.c (symbol_read_needs_frame), corelow.c (ignore),
+ inflow.c (gdb_has_a_terminal): Make sure to return a value.
+ * regex.h: Declare re_set_syntax.
+ * printcmd.c: Include valprint.h.
+ * infcmd.c, exec.c, maint.c, core.c: Include language.h.
+ * maint.c: Include expression.h.
+ * infrun.c, fork-child.c, corelow.c, inflow.c: Include thread.h.
+ * inftarg.c: Include command.h.
+ * coredep.c: Include value.h.
+ * c-exp.y, m2-exp.y, ch-exp.y: Include bfd.h, symfile.h and objfiles.h.
+ * ch-typeprint.c: Include typeprint.h.
+ * ch-valprint.c: Include c-lang.h.
+ * nlmread.c: Include buildsym.h.
+ * environ.c: Include gdbcore.h. Only include defs.h once.
+ (set_in_environ): Cast const char * to char * when passing to
+ set_gnutarget.
+ * Makefile.in: Update dependencies to reflect all these new includes.
+ Remove unused variables:
+ * printcmd.c (printf_command): args_to_vprintf.
+ * coffread.c (coff_symfile_init): strsection.
+ Move variables to within the #ifdefs where they are used:
+ * symtab.c (gdb_mangle_name): opname.
+ * inftarg.c (child_attach): pid and exec_file.
+ * inftarg.c (child_detach): siggnal.
+ * objfiles.c (allocate_objfile): mapto, md, and fd.
+ * objfiles.c (free_objfile): mmfd.
+ * infrun.c (wait_for_inferior): Include BPSTAT_WHAT_LAST in switch.
+ * infrun.c (wait_for_inferior): Remove unused same_pid label.
+ * inferior.h: Declare set_sigint_trap and clear_sigint_trap.
+ * parser-defs.h: Declare write_exp_elt_block.
+ * stabsread.h: Declare elfstab_offset_sections and
+ coffstab_build_psymtabs.
+
+Thu Oct 21 12:05:08 1993 Ken Raeburn (raeburn@cygnus.com)
+
+ Patch from Jeff Law:
+ * paread.c: Fix references to "hppa" that should now be "som".
+
+Thu Oct 21 12:23:12 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * symtab.c (decode_line_1): Don't use SYMBOL_LINE for functions.
+
+Thu Oct 21 02:59:07 1993 Stu Grossman (grossman at cygnus.com)
+
+ * remote-udi.c (udi_store_registers, store_register): Use
+ UDI29KPC address space when modifying PC. It seems that you can't
+ modify the PC directly (at least in the isstip simulator).
+
+Wed Oct 20 11:35:43 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * target.h: Put remote_debug declaration back here. Add baud_rate.
+ * remote.c, remote-udi.c, remote-utils.h: Let target.h take care of
+ declaring these. Those random externs all over are error prone.
+ * Move "set remotebaud" from remote-utils.c to main.c to it applies
+ to remote.c as well.
+
+ * xcoffread.c (xcoff_symfile_read), coffread.c (coff_symfile_read):
+ Sort symtabs for this objfile only, not for all objfiles.
+ * symfile.c, symfile.h (sort_all_symtab_syms): Remove; no longer used.
+
+ * mipsread.c (parse_symbol): In third-eye, a function has a block
+ within it which represents the whole function. Create only one
+ GDB block for both.
+
+Wed Oct 20 17:47:42 1993 Stu Grossman (grossman at cygnus.com)
+
+ * main.c: Make baud_rate and remote_debug be global variables,
+ remove #include "remote-utils.h". This makes it possible to build
+ GDB without remote-utils.c. Also, move setting of remote_debug
+ into main, so that all remote*.c files can use it (not just the
+ serial line ones). And, make baud_rate be an int.
+ * remote-udi.c: Change kiodebug to remote_debug.
+ * remote-utils.c: Move setting of baud rate and debug into main.c.
+ * remote-utils.h: Redefine sr_{get set}_debug and sr_{get set}_baud
+ to use baud_rate and remote_debug globals for compatibility.
+ * remote.c: Use remote_debug and baud_rate globals directly,
+ instead of sr_ functions, so that we don't need to load
+ remote-utils.c.
+ * config/a29k/a29k-udi.mt: Define REMOTE_O as null so that we don't
+ get the default remote* modules.
+
+Wed Oct 20 11:35:43 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabsread.c (define_symbol): When combining a LOC_ARG and a
+ LOC_REGISTER, use the type from the LOC_REGISTER, not from the
+ LOC_ARG.
+
+Wed Oct 20 14:34:38 1993 K. Richard Pixley (rich@sendai.cygnus.com)
+
+ * config/i386/xm-go32.h: define some signals if they aren't
+ already defined.
+
+Wed Oct 20 11:35:43 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * Makefile.in (INTERNAL_LDFLAGS): New macro. The new part is
+ that we use CFLAGS and PROFILE_CFLAGS to link.
+ (gdb, rapp, kdb): Use INTERNAL_LDFLAGS instead of
+ LDFLAGS and/or GLOBAL_CFLAGS.
+
+Wed Oct 20 09:29:55 1993 Stu Grossman (grossman at cygnus.com)
+
+ * Makefile.in: Add $(srcdir) to all refs to 29k-share
+ directories.
+
+Tue Oct 19 17:23:34 1993 Fred Fish (fnf@deneb.cygnus.com)
+
+ * Makefile.in (ALLCONFIG): Add config/i386/{i386m3.mh, i386m3.mt,
+ i386/i386mk.mh i386/i386mk.mt}, config/mips/{mipsm3.mh,
+ mipsm3.mt}, config/ns32k/{ns32km3.mh, ns32m3.mt}
+ * Makefile.in (remote_utils_h): Add remote-sim.h
+ * Makefile.in (NONSRC): Add i386-nlmstub.c
+ * Makefile.in (HFILES): Add coff-solib.h
+
+Tue Oct 19 14:15:40 1993 Kung Hsu (kung@cirdan.cygnus.com)
+
+ * values.c (value_virtual_fn_field): Fix the offset calculation
+ when calling virtual functions. (gdb.t22/virtfunc.exp).
+ * eval.c (evaluate_subexp): same as above.
+
+Tue Oct 19 10:43:16 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * config/rs6000/rs6000.mh (TERMCAP): Define to -lcurses.
+
+ * Makefile.in: Define CXXFLAGS.
+
+Tue Oct 19 09:28:52 1993 Stu Grossman (grossman@cygnus.com)
+
+ * sparclite/Makefile.in: Fixup so that this works with Sun make
+ and VPATH.
+
+Tue Oct 19 10:43:16 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * breakpoint.h (struct bpstat_what): Don't use bitfields.
+
+ * typeprint.c: Add "class CLASS-NAME" to docstring for ptype.
+
+Tue Oct 19 06:17:10 1993 Fred Fish (fnf@cirdan.cygnus.com)
+
+ * Makefile.in (ALLPARAM): Add config/m88k/{nm-delta88v4.h,
+ tm-delta88v4.h, xm-dgux.h}.
+ * Makefile.in (ALLCONFIG): Add config/m88k/{delta88v4.mh,
+ delta88v4.mt}.
+
+ * README: Remove comment about SunOS 5.x programs leaving
+ coredumps. Info from Sun is that this was not in customer
+ releases.
+
+Mon Oct 18 10:28:08 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * hppa-tdep.c (restore_pc_queue): Call target_terminal_ours after
+ done stepping the inferior.
+
+ * c-exp.y: Remove never-used (because of shift/reduce conflicts)
+ rules for pointers to members.
+ * Makefile.in: Remove notice about expected shift/reduce conflicts.
+
+ * buildsym.c (finish_block): If we pop the context stack and it is
+ not empty, complain () instead of abort ().
+
+Sun Oct 17 19:42:31 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * parse.c, parser-defs.h (follow_types): New function.
+ * c-exp.y (ptype : typebase abs_decl): Use it.
+ * c-exp.y (ptype): Add support for type qualifiers after the
+ typebase. The typebase rule already has support for them before
+ the typebase.
+ * Makefile.in: Change the expected number of shift/reduce
+ conflicts to 6. This is OK--the 2 new conflicts are basically the
+ same as one of the old ones.
+
+Sun Oct 17 13:04:49 1993 Fred Fish (fnf@cygnus.com)
+
+ * Makefile.in (VERSION): Bump to 4.10.3.
+
+Sun Oct 17 09:18:57 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * infrun.c (wait_for_inferior): Clean up comments which were at
+ the top of the file, making them more concise and moving them with
+ the code (Sorry, Randy, but these stream-of-consciousness comments
+ really have to go). Switch the order of the "&&", which makes
+ things clearer and turns out to be an improvement with respect to
+ side effects and speed.
+
+Sun Oct 17 02:06:01 1993 Stu Grossman (grossman at cygnus.com)
+
+ * procfs.c: Handle process exits more elegantly by trapping on
+ entry to _exit. Also, cleanup procinfo list when process dies of
+ it's own accord (as opposed to being killed).
+
+Sat Oct 16 20:47:30 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * config/m88k/xm-dgux.h: Define NO_PTRACE_H.
+
+ * corelow.c (add_to_thread_list): Need a cast to go from PTR to
+ asection *.
+
+ * infrun.c: Add comment about signals.
+
+ * fork-child.c (fork_inferior): Remove CREATE_INFERIOR_HOOK again.
+ Stu reinstated it (accidently I assume).
+
+Sat Oct 16 15:27:10 1993 Stu Grossman (grossman at cygnus.com)
+
+ * procfs.c (procfs_wait): Losing Unixware can't do poll on /proc
+ files. Use PIOCWSTOP instead.
+ * corelow.c (add_to_thread_list): Fix arg to match prototype.
+
+ * procfs.c (procfs_set_sproc_trap): Don't use this if sproc
+ isn't available.
+ * (procfs_notice_signals): Fix prototype.
+
+Fri Oct 15 22:46:07 1993 Stu Grossman (grossman at cygnus.com)
+
+ * breakpoint.c (breakpoint_thread_match break_command_1):
+ Thread-specific breakpoint support.
+ * breakpoint.h (struct breakpoint): Add thread id field.
+ * fork-child.c (fork_inferior): Move call to init_thread_list()
+ back a bit so that init_trace_fun can do thread functions.
+ * hppa-tdep.c (restore_pc_queue): Add pid to call to target_wait.
+ * hppab-nat.c (child_resume): Handle default pid.
+ * hppah-nat.c (child_resume): Handle default pid.
+ * i386lynx-nat.c (child_wait): New arg pid.
+ * inflow.c (kill_command): Reset thread list.
+ * infptrace.c (child_resume): Handle default pid.
+ * infrun.c: Thread-specific breakpoint support.
+ * inftarg.c (child_wait): Add pid arg.
+ * osfsolib.c (solib_create_inferior_hook): Add pid to call to
+ target_resume.
+ * procfs.c: Multi-thread support.
+ * remote-bug.c (bug_wait): Add pid arg.
+ * remote-hms.c (hms_wait): Add pid arg.
+ * remote-mips.c (mips_wait): Add pid arg.
+ * remote-mon.c (monitor_wait): Add pid arg.
+ * remote-nindy.c (nindy_wait): Add pid arg.
+ * remote-sim.c (gdbsim_wait): Add pid arg.
+ * remote-udi.c (udi_wait): Add pid arg.
+ * remote-vx.c (vx_wait): Add pid arg.
+ * remote-z8k.c (sim_wait): Add pid arg.
+ * remote.c (remote_wait): Add pid arg.
+ * solib.c (solib_create_inferior_hook): Add pid to call to
+ target_resume.
+ * target.h (struct target_ops): Add pid arg to to_wait and
+ to_notice_signals.
+ * thread.c (valid_thread_id): New func to validate thread #s.
+ * (pid_to_thread_id): New func to do the obvious.
+ * thread.h: Prototypes for above.
+
+ * coff-solib.c (coff_solib_add): Use nameoffset field to locate
+ filename.
+
+Fri Oct 15 21:29:40 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * h8300-tdep.c, h8500-tdep.c: Define sim_load only, but not
+ sim_kill, sim_open, or sim_set_args.
+
+ * stack.c (print_stack_frame): Put catch_errors around
+ print_frame_info so (for example) error printing source doesn't
+ cause auto-displays to get skipped in normal_stop.
+
+ * findvar.c (value_from_register): When preparing to cast a value
+ from REGISTER_VIRTUAL_TYPE to type, copy the REGISTER_VIRTUAL_SIZE;
+ the old code didn't copy the whole thing.
+ * valops.c (value_assign): Add comment.
+
+Fri Oct 15 12:57:30 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * mipsread.c (upgrade_type): Replace bitsize sanity checks and
+ complaint by a comment explaining why they were useless.
+
+Fri Oct 15 14:30:30 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * Move comments on bypassing call dummy breakpoint from stack.c
+ to breakpoint.h.
+
+Fri Oct 15 11:52:56 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * symtab.c (lookup_partial_symtab): If filename is not found and
+ contains no slashes, try again and compare without leading path
+ components.
+ * symtab.c (lookup_symtab_1): Replace open coded version of
+ lookup_partial_symtab with a function call.
+
+Thu Oct 14 20:34:15 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * fork-child.c (fork_inferior), remote-eb.c (eb_create_inferior),
+ remote-mon.c (monitor_create_inferior), remote-nindy.c
+ (nindy_create_inferior), remote-st.c (st2000_create_inferior),
+ remote-vx.c (vx_create_inferior): Remove CREATE_INFERIOR_HOOK; it
+ is replaced by init_trace_fun.
+ * config/convex/xm-convex.h, convex-xdep.c: Add comments explaining
+ how to do without CREATE_INFERIOR_HOOK for whoever fixes the Convex
+ port.
+
+ * Makefile.in: Add Mach files to ALLDEPFILES, etc.
+ * m3-nat.c: Clean up more hair--message(), cprocs.
+ * configure.in: Recognize Mach targets and hosts.
+ * config/ns32k/tm-umax.h: Add some #ifndef's so tm-ns32km3.h can
+ include this file.
+ * Mach headers in config/*/tm-*.h: Fix includes to match correct
+ locations of files.
+
+Thu Oct 14 21:35:55 1993 Rob Savoye (rob@darkstar.cygnus.com)
+
+ * remote-mon.c (general_open): Set dev_name. Minor tweaking to get
+ it working again.
+ * config/m68k/tm-monitor.h: Remove floating point register names
+ as there aren't any on any of the monitors that use this code.
+
+Wed Oct 13 11:47:23 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * inflow.c: Pass pointer to process group, not process group itself,
+ to TIOCSPGRP ioctl.
+
+ * inflow.c (terminal_ours_1): Don't print warning on failure to
+ set process group.
+
+ * printcmd.c (printf_command): Instead of using makeva* and
+ calling vprintf, just make the appropriate calls to printf.
+ * printcmd.c, config/pa/xm-pa.h, config/mips/xm-makeva.h,
+ config/alpha/xm-alpha.h, config/m88k/xm-m88k.h: Remove all
+ traces of makeva*. My apologies to everyone (including me!)
+ who spent so much time getting it to work on various machines,
+ but look at the bright side, at least you won't have to do it
+ again in the future.
+
+ * printcmd.c (printf_command): Make a cleanup for val_args (fixes
+ a memory leak).
+
+Tue Oct 12 22:54:41 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * config/mips/xm-mips.h: Remove comment about HAVE_SGTTY vs. usleep.
+
+Tue Oct 12 12:01:29 1993 david d `zoo' zuhn (zoo@rtl.cygnus.com)
+
+ * configure.in: only configure gdbserver for native environments
+
+Tue Oct 12 08:59:15 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabsread.c (read_type): Treat a negative type number at the start
+ of a type as a type reference, not as a definition of a type with
+ "50=" omitted. This makes things work on the RS/6000 again (the
+ 14 Sep 1993 change broke it).
+
+ * inflow.c: Use 0 (standard input) not scb->fd.
+ (terminal_ours_1): If printing warning, don't claim it happened in
+ terminal_inferior.
+
+ * blockframe.c (get_prev_frame_info): Don't error() if there are no
+ frames; just return NULL.
+
+ * xcoffsolib.h, xcoffexec.c: Undo the part of Fred's bfd->abfd
+ change which involved structure elements. It was unnecessary and
+ was not consistently done.
+
+ * stabsread.h, stabsread.c, dbxread.c (common_block*, copy_pending):
+ Move common block handling from dbxread.c to stabsread.c.
+ Use the name from the BCOMM instead of the ECOMM.
+ Allocate things on the symbol_obstack.
+ * xcoffread.c (process_xcoff_symbol): Process C_BCOMM, C_ECOMM,
+ and C_ECOML. On unrecognized storage classes, go ahead and call
+ define_symbol (after the complaint).
+
+ * dbxread.c (process_one_symbol): Don't relocate 'S' symbols by
+ the text offset.
+
+Tue Oct 12 12:33:09 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * osfsolib.c (solib_create_inferior_hook): Reset stop_soon_quietly
+ after shared library symbol reading to get rid of warning from
+ heuristic_proc_start.
+
+Tue Oct 12 12:01:29 1993 david d `zoo' zuhn (zoo@rtl.cygnus.com)
+
+ * remote-sim.c: fix unterminated character string
+
+Tue Oct 12 08:59:15 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabsread.c: Fix comment about gcc 2.3.3 stab for long long int.
+
+Mon Oct 11 14:27:25 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * m3-nat.c, config/nm-m3.h: Add a target_ops struct and other
+ various things to try to get this to work.
+
+ * symtab.h: Fix comments re headers, sharing blockvectors, etc.
+
+Mon Oct 11 11:46:06 1993 david d `zoo' zuhn (zoo@rtl.cygnus.com)
+
+ * config/i960/vxworks960.mt (REMOTE_O): add dcache.o and remote-utils.o
+
+Mon Oct 11 02:48:57 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * mipsread.c (parse_partial_symbols): Do not add undefined
+ symbols to the partial symbol table.
+ * alpha-tdep.c (init_extra_frame_info): Remove kludge for gcc,
+ gcc has to be compatible with the native tools.
+ * alpha-tdep.c (alpha_push_arguments): Rename NUM_ARG_REGS to
+ ALPHA_NUM_ARG_REGS and move its definition to tm-alpha.h.
+ * config/alpha/tm-alpha.h (FRAME_ARGS_ADDRESS): Change it to the
+ way the native tools define it, update comment.
+
+Fri Oct 8 15:54:06 1993 Fred Fish (fnf@deneb.cygnus.com)
+
+ * osfsolib.c, remote-sim.c, remote.c, solib.c, xcoffexec.c,
+ xcoffsolib.h: Use 'abfd' for bfd variables instead of 'bfd'.
+ Sun cc doesn't like variable names that match their typedef'd type.
+
+Fri Oct 8 14:56:21 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * inflow.c: Remove unused includes of sys/param.h and sys/types.h.
+
+ * inflow.c, ser-unix.c, ser-go32.c, ser-tcp.c, serial.h,
+ terminal.h, fork-child.c, main.c, utils.c: Move all the process
+ group stuff back to inflow.c and terminal.h; that's a better place
+ for it and fixes problems with trying to get/set the process group
+ of a tty we're doing remote debugging on.
+ * terminal.h: Skip the redefines and includes if HAVE_TERMIOS.
+
+ * findvar.c, value.h (symbol_read_needs_frame): New function.
+ * c-exp.y, m2-exp.y: Call it instead of having our own switch on
+ the symbol's class.
+ * valops.c (value_of_variable): Use symbol_read_needs_frame to
+ decide whether we care about finding a frame.
+
+Fri Oct 8 02:34:21 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * blockframe.c (get_frame_block): Do not adjust pc if the frame
+ function was interrupted by a signal.
+
+Thu Oct 7 19:20:11 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * config/h8300/tm-h8300.h: Don't define sr_get_debug.
+ * remote-sim.c: Include remote-utils.h.
+ * target.h: Add comment about target_has_execution.
+
+Thu Oct 7 16:14:19 1993 Steve Chamberlain (sac@phydeaux.cygnus.com)
+
+ * h8300-tdep.c (sim_load, sim_kill, sim_open, sim_set_args):
+ New functions.
+ * infrun.c (normal_stop): Don't try and set the pc in the current
+ frame coredump if there isn't one.
+ * remote-sim.c (gdbsim_store_register): Don't
+ SWAP_TARGET_AND_HOST, sim_store_register takes bytes in raw order.
+ (gdbsim_wait): Set status with WSETSTOP.
+ * config/h8300/tm-h8300.h (sr_get_debug): Define
+
+Thu Oct 7 12:56:57 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ New Mach stuff:
+ * config/i386/i386mach.c: Explain this is for the old (probably
+ non-functional and/or obsolete) Mach stuff.
+ * m3-nat.c, config/nm-m3.h,
+ i386m3-nat.c, mipsm3-nat.c, ns32km3-nat.c,
+ config/i386/{i386m3.mh,i386m3.mt,tm-i386m3.h,xm-i386m3.h},
+ config/i386/{i386mk.mh,i386mk.mt,tm-i386mk.h,xm-i386mk.h},
+ config/mips/{mipsm3.mh,mipsm3.mt,tm-mipsm3.h,xm-mipsm3.h},
+ config/ns32k/{ns32km3.mh,ns32km3.mt,tm-ns32km3.h,xm-ns32km3.h}:
+ New files.
+
+ * blockframe.c (find_pc_partial_function): If we call
+ PSYMTAB_TO_SYMTAB, call target_terminal_ours_for_output first.
+ This is needed now that wait_for_inferior passes in endaddr.
+ * infrun.c: Move call to target_terminal_inferior from proceed
+ to resume.
+
+Thu Oct 7 09:22:04 1993 Stu Grossman (grossman at cygnus.com)
+
+ * blockframe.c (find_pc_partial_function): Fix handling for PCs
+ beyond the end of the last function in an objfile.
+ * coff-solib.c (coff_solib_add): Use BFD to get fields from .lib
+ section.
+ * infrun.c (wait_for_inferior): Modify test for subroutine entry
+ to include pc out of bounds of the previous function.
+ * remote.c (remote_wait): Use strtoul for parsing 'N' message.
+ Add code to relocate symfile_objfile->sections.
+
+Thu Oct 7 06:22:43 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * config/sparc/sun4os4.mh: Add comment saying why we don't use
+ -lresolv.
+
+Thu Oct 7 09:29:11 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * breakpoint.c, breakpoint.h (breakpoint_init_inferior): New function
+ that clears the `inserted' flag for all breakpoints and deletes
+ any breakpoints which should go away between runs of programs.
+ * inflow.c (generic_mourn_inferior), infrun.c (init_wait_for_inferior),
+ remote-es.c (es1800_load), comments in exec.c and corelow.c:
+ Use it instead of mark_breakpoints_out.
+ * breakpoint.c (mark_breakpoints_out): Update comment, tm-rs6000.h
+ uses it in a completely different context.
+ * breakpoint.c (breakpoint_re_set_one): Add bp_call_dummy case.
+
+Thu Oct 7 09:29:11 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * Makefile.in (REGEX, REGEX1): Always use our own version of
+ regex.c to be consistent across hosts.
+ * source.c (_initialize_source): Initialize regex to use grep
+ style syntax as an approximation to POSIX basic regex syntax.
+
+Wed Oct 6 12:43:47 1993 Jeffrey A Law (law@snake.cs.utah.edu)
+ Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * hppa-tdep.c (frame_chain): Rework so that it correctly
+ handles boundaries where code with a frame pointer calls code
+ without a frame pointer.
+ (dig_fp_from_stack): New function.
+
+Wed Oct 6 12:43:47 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * breakpoint.c (delete_breakpoint): Don't insert a disabled breakpoint.
+
+ * README: Add Alpha notes from Schauer.
+
+Tue Oct 5 15:26:04 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * Makefile.in (install, uninstall): Remove $$n.1 stuff; I don't
+ understand what it is trying to do, but I suspect it's not doing
+ it.
+
+ * config/ns32k/merlin.mh: Add comment about M_INSTALL.
+ * config/m88k/{delta88.mh,delta88v4.mh}: Remove M_INSTALL and
+ M_UNINSTALL; it tries to install a non-existent file gdb.z.
+ * Makefile.in: Remove M_INSTALL stuff; the above were the only uses.
+
+ * stabsread.c (read_range_type): Remove comment which recommends
+ distinguishing float from complex by the name.
+
+Tue Oct 5 12:17:40 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+ Jim Kingdon (kingdon@cygnus.com)
+ Stu Grossman (grossman@cygnus.com)
+
+ Changes to support alpha OSF/1 in native mode.
+ * alpha-nat.c, alpha-tdep.c, config/alpha/alpha-osf1.mt,
+ config/alpha/nm-alpha.h, config/alpha/tm-alpha.h, osfsolib.c:
+ New files.
+ * Makefile.in: Add new files and dependencies.
+ * configure.in: Add alpha target.
+ * config/alpha/alpha-osf1.mh (NATDEPFILES): Add osfsolib.o
+ * config/alpha/alpha-osf1.mh (MH_CFLAGS): Remove, we can handle
+ shared libraries now.
+ * config/alpha/xm-alpha.h: Cleanup, get MAKEVA_* defines right.
+
+ * defs.h (CORE_ADDR): Make its type overridable via CORE_ADDR_TYPE,
+ provide `unsigned int' default.
+ * breakpoint.c (breakpoint_auto_delete): Delete only if we really
+ stopped for the breakpoint.
+ * stabsread.c, stabsread.h (define_symbol): Change valu parameter
+ to a CORE_ADDR.
+ * stabsread.c (read_range_type): Handle the case where the lower
+ bound overflows and the upper doesn't and the range is legal.
+ * infrun.c (resume): Do not step a breakpoint instruction if
+ CANNOT_STEP_BREAKPOINT is defined.
+
+ * inferior.h (CALL_DUMMY_LOCATION): New variant AT_ENTRY_POINT.
+ Now that we have the bp_call_dummy breakpoint the call dummy code
+ is no longer needed. PUSH_DUMMY_FRAME, PUSH_ARGUMENTS and
+ FIX_CALL_DUMMY can be used to set up everything for the dummy.
+ The breakpoint for the dummy is set at the entry point and thats it.
+ * blockframe.c (inside_entry_file, inside_entry_func): Do not stop
+ backtraces if pc is in the call dummy at the entry point.
+ * infcmd.c (run_stack_dummy): Handle AT_ENTRY_POINT case. Use
+ the expected breakpoint pc when setting up the frame for
+ set_momentary_breakpoint.
+ * symfile.c (entry_point_address): New function for AT_ENTRY_POINT
+ support.
+ * valops.c (call_function_by_hand): Handle AT_ENTRY_POINT case.
+
+Tue Oct 5 11:37:02 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * configure.in: Recognize hppa*-*-hiux* (currently synonym for hpux).
+ Change other hppa host entries to use -*- not -hp-.
+
+Mon Oct 4 19:16:14 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * i386-nlmstub.c: New file; debugging stub for i386 NetWare. Must
+ be compiled with NetWare header files and turned into an NLM with
+ nlmconv.
+
+Mon Oct 4 11:02:11 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * minsyms.c (lookup_minimal_symbol_by_pc): Don't use mst_abs symbols.
+
+ * dbxread.c (process_one_symbol): Make n_opt_found static.
+
+ * Rename i386lynx-tdep.c to i386ly-tdep.c for 14 character file names.
+ * Makefile.in, config/i386/i386lynx.mt: Change accordingly.
+
+ * values.c (record_latest_value): Fetch lazy values and set VALUE_LVAL
+ to not_lval.
+
+Sun Oct 3 15:54:51 1993 Stan Shebs (shebs@rtl.cygnus.com)
+
+ * objfiles.h (objfile): New slot sym_stab_info, use by most
+ stab-reading formats.
+ * gdb-stabs.h (DBX_SYMFILE_INFO): Access sym_stab_info instead of
+ sym_private.
+ * coffread.c (coff_symfile_init): Alloc struct for sym_stab_info.
+ * dbxread.c, elfread.c, paread.c: Change sym_private references to
+ sym_stab_info references.
+
+Sat Oct 2 19:28:35 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * mipsread.c, objfiles.c, utils.c: Use PTR not void *. RISC/OS
+ 4.02 lacks void *.
+ * elfread.c: Use void * not PTR inside PARAMS.
+
+ * config/mips/news-mips.mh: Remove coredep.o; mips-nat.o does it.
+ * config/mips/news-mips.mh: Define NAT_FILE not NM_FILE.
+ * config/mips/nm-news-mips.h: Include mips/nm-mips.h not nm-mips.h.
+
+Sat Oct 2 16:05:22 1993 Stu Grossman (grossman at cygnus.com)
+
+ * Makefile.in, coff-solib.c, coff-solib.h, i386lynx.mt,
+ tm-i386lynx.h: Add support for SVR3 COFF shared libraries.
+
+Sat Oct 2 15:50:41 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * m88k-nat.c (store_inferior_registers): When writing all registers,
+ don't try to write EXIP_REGNUM or ENIP_REGNUM (not needed for this
+ case, and they cause trouble).
+
+ * TODO: Don't suggest doing fast watchpoints by stepping a line
+ at a time. That would be really hairy and still not fast enough.
+ Do suggest debug registers and page table diddling.
+
+Fri Oct 1 14:54:46 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * printcmd.c (do_examine): Make meaning of 'h', 'w', and 'g' not
+ depend on builtin_type_*. Instead, it is always 2, 4, and 8 bytes
+ like the documentation says.
+ * printcmd.c (decode_format) [CC_HAS_LONG_LONG]: Remove 'l' as
+ synonym for 'g'. This was never documented, it shouldn't depend on
+ CC_HAS_LONG_LONG, and I don't see what's wrong with 'g'.
+
+Fri Oct 1 10:06:35 1993 Kung Hsu (kung@cirdan.cygnus.com)
+
+ * symtab.c: fix a bug in testsuite (virtfunc.exp)
+
+Thu Sep 30 11:30:56 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * m88k-nat.c (fill_gregset): Fix typo (R_SFIP -> R_FIP).
+
+ * c-typeprint.c (c_type_print_base, TYPE_FN_FIELD_STUB code):
+ If demangled name lacks a colon, don't dump core.
+
+ * blockframe.c (find_pc_partial_function): If pst->readin is
+ set, don't try to get symbols from pst.
+
+ * inflow.c (generic_mourn_inferior): Call reinit_frame_cache
+ instead of doing it ourself.
+ * blockframe.c (reinit_frame_cache): Use code which was in
+ generic_mourn_inferior so we can use this function even when
+ we have switched targets.
+ * corelow.c (core_detach): Call reinit_frame_cache.
+ * target.c (target_detach): Don't call generic_mourn_inferior
+ (revert yesterday's change, now handled by core_detach).
+ * objfiles.c (free_objfile): Detach any core file if we call
+ SOLIB_CLEAR. #include target.h.
+
+ * fork-child.c (fork_inferior): Don't call target_terminal_init
+ and target_terminal_inferior until we are sure that the inferior
+ has called gdb_setpgid. This fixes PR 2900 (Schauer tracked it
+ down and was able to reliably reproduce it by putting a sleep()
+ before the gdb_setpgid()).
+
+Thu Sep 30 12:00:49 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * c-exp.y, m2-exp.y: Change type of address for msymbol to
+ builtin_type_long.
+ * infptrace.c (fetch_register, store_inferior_register,
+ child_xfer_memory): Use PTRACE_XFER_TYPE for the type of ptrace
+ transfers. Provide an `int' default for PTRACE_XFER_TYPE.
+
+Thu Sep 30 11:30:56 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * defs.h (TARGET_*_BIT): Don't use host information (sizeof) in
+ picking defaults.
+
+ * cp-valprint.c (cp_is_vtbl_ptr_type): Continue to accept old form.
+
+Thu Sep 30 11:25:55 1993 Kung Hsu (kung@cygnus.com)
+
+ * cp-valprint.c (cp_is_vtbl_ptr_type):
+ change vtable field name to __vtbl (pr2695).
+
+ * symtab.c (gdb_mangle_name): fix a bug, to get mangled name right.
+
+Wed Sep 29 18:34:22 1993 Stu Grossman (grossman at cygnus.com)
+
+ * Makefile.in: Add deps for i386lynx-nat.o and i386lynx-tdep.o to
+ keep non-gnu makes happy.
+
+Wed Sep 29 17:20:54 1993 Jeff Law (law@snake.cs.utah.edu)
+
+ * hpread.c (read_hpux_symtab): When a K_END is found for a
+ K_MODULE, clear the have_module and have_name flags.
+
+Wed Sep 29 10:52:19 1993 Kung Hsu (kung@cygnus.com)
+
+ * c-valprint.c: to fix virtual table print bug (pr2695).
+
+Wed Sep 29 10:52:19 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * target.c (target_detach): Call generic_mourn_inferior.
+ * inflow.c (generic_mourn_inferior): Call flush_cached_frames.
+
+Tue Sep 28 23:08:59 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * dbxread.c, coffread.c, elfread.c: A few changes to comments.
+
+Tue Sep 28 18:39:37 1993 Stan Shebs (shebs@rtl.cygnus.com)
+
+ * configure.in: Rename ...-lynx* to ...-lynxos*.
+ Add m68*-*-lynxos* configuration.
+ * dbxread.c (coffstab_build_psymtabs): New function,
+ interfaces coffread.c to dbxread functions.
+ * coffread.c (coff_symfile_info): Expand to include
+ dbx_symfile_info slots.
+ (coff_symfile_init): Init coff_symfile_info struct.
+ (coff_locate_sections): New functions, finds the stab and stabstr
+ sections.
+ (coff_symfile_read): Call coffstab_build_psymtabs if a stab
+ section is present.
+ (coff_section_offsets): Replace fake version with real offsets.
+
+Tue Sep 28 18:00:50 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * infcmd.c (run_stack_dummy): Set the frame in the bp_call_dummy
+ breakpoint.
+
+Tue Sep 28 17:53:26 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * config/nm-sysv4.h: Include solib.h. Define SVR4_SHARED_LIBS.
+ * config/tm-sysv4.h: Don't include solib.h.
+ * config/xm-sysv4.h: Don't define SVR4_SHARED_LIBS.
+ * config/i386/i386v4.mt (TDEPFILES): Move solib.o from here...
+ * config/i386/i386v4.mh (NATDEPFILES): ...to here.
+ * config/i386/nm-i386v4.h: Include nm-sysv4.h.
+ * config/m68k/amix.mt (TDEPFILES): Move solib.o from here...
+ * config/m68k/amix.mh (NATDEPFILES): ...to here.
+
+Tue Sep 28 09:45:38 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * symmisc.c (print_symbol): Use %02x not %2x for LOC_CONST_BYTES.
+
+ Clean up problems with targets and hosts that have 64 bit longs
+ and pointers and 32 bit ints.
+ * breakpoint.c, buildsym.c, c-lang.c, c-valprint.c, ch-lang.c,
+ ch-valprint.c, core.c, cp-valprint.c, dbxread.c, exec.c,
+ expprint.c, gdbtypes.c, infcmd.c, language.c, language.h,
+ m2-lang.c, maint.c, mips-tdep.c, mipsread.c, partial-stab.h,
+ printcmd.c, remote-vx.c, solib.c, source.c, stack.c, symfile.c,
+ symmisc.c, symtab.c, valops.c, valprint.c, xcoffexec.c:
+ Change all printf formats from %x to %lx if outputting an address.
+ Change la_*_format to use long format.
+ local_hex_string, local_hex_string_custom now take an unsigned long
+ argument, change all callers.
+ * coffread.c (read_coff_symtab): Remove superfluous cast for
+ complaint output.
+ * dbxread.c (end_psymtab): Cast MSYMBOL_INFO to long, not int.
+ * findvar.c, value.h (write_register): Change val to LONGEST.
+ * gdbtypes.h (struct type): Change `bitsize' to long as
+ TYPE_FIELD_STATIC_PHYSNAME uses this field as a pointer.
+ * inferior.h (struct inferior_status): Change type of stop_pc to
+ CORE_ADDR.
+ * language.h (local_octal_string, local_octal_string_custom):
+ Remove prototype, the functions are neither defined nor used.
+ * mipsread.c (parse_symbol): Use temporary variable for bitsize as
+ f->bitsize is a long now.
+ * objfiles.c (add_to_objfile_sections, build_objfile_section_table):
+ Use unsigned long casts instead of int for abusing sections_end
+ pointer as integer.
+ * stack.c (parse_frame_specification): Change type of `args' to
+ CORE_ADDR for SETUP_ARBITRARY_FRAME.
+
+ * printcmd.c (make_vasize): Allow redefinition via MAKEVA_SIZE.
+ * mipsread.c (parse_type): Alpha cc now supports the t->continued
+ bit, update algorithm to match the way the compiler uses it.
+
+Tue Sep 28 12:05:11 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * utils.c (fprintfi_filtered): Fix comments.
+
+Mon Sep 27 18:10:08 1993 Stu Grossman (grossman at cygnus.com)
+
+ * coffread.c (read_coff_symtab): Don't call getfilename if there
+ are no auxents.
+
+Mon Sep 27 10:22:37 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * symtab.c (find_pc_line): Fix comments.
+
+ * remote-udi.c (udi_mourn): Don't pop target.
+
+Fri Sep 24 17:25:41 1993 Stu Grossman (grossman at cygnus.com)
+
+ * corelow.c: Add multi thread/process support for core files with
+ .reg/XXX pseudo-sections.
+ * i386lynx-nat.c thread.h thread.c: Remove unnecessary core file
+ support.
+
+Thu Sep 23 10:49:37 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * remote-udi.c (download): Skip zero length sections.
+
+ * valops.c (search_struct_method, value_struct_elt):
+ Use (value)-1, not -1, for error.
+
+ * infcmd.c (step_1), infrun.c (wait_for_inferior): Add comments
+ about SHIFT_INST_REGS.
+
+ * exec.c (exec_file_command): Set text_end based on all code readonly
+ sections, not just ".text".
+
+ * defs.h, infcmd.c, config/z8k/tm-z8k.h, config/m88k/tm-m88k.h,
+ config/sh/tm-sh.h, config/h8300/tm-h8300.h, config/h8500/tm-h8500.h,
+ z8k-tdep.c: Remove all references to ADDR_BITS_SET.
+ * config/m88k/tm-m88k.h: Define TARGET_WRITE_PC.
+
+ * config/m88k/tm-m88k.h, m88k-tdep.c: Add call function stuff.
+
+Thu Sep 23 00:13:06 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * config/mips/tm-mips.h (STORE_STRUCT_RETURN): Define as noop as
+ the pushing of the struct return address is already handled in
+ mips_push_arguments.
+ * mips-tdep.c (reinit_frame_cache_sfunc): Fix typo in prototype
+ declaration.
+ * mipsread.c (parse_symbol, parse_type, upgrade_type): Add more
+ sanity checks for corrupt symbol entries to avoid core dumps
+ reported by benson@odi.com. Obviously Ultrix 4.3A cc now has
+ the same problems as the OSF/1 alpha cc.
+ * mipsread.c (parse_lines): Iterate over the range of the compressed
+ line number entries, the old iteration sometimes failed to stop
+ and wrote past the end of the LINETABLE. Add sanity check to avoid
+ the same problem in case the line number info is corrupt.
+ * mipsread.c (parse_procedure): Adjust pdr for alpha __sigtramp.
+ * mipsread.c (parse_external, parse_partial_symbols): Ignore stNil
+ symbols that are produced for statics in .o files and stLocal symbols
+ that are produced for every section in OSF/1 dynamically linked
+ executables.
+ * mipsread.c (psymtab_to_symtab_1): Put out `undefined symbols'
+ warning only under `verbose on' as there are many undefined symbols
+ in a dynamically linked executable.
+
+Wed Sep 22 10:28:06 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * config/i960/nindy960.mt: Don't define REMOTE_O; REMOTE_O was
+ intended only for VxWorks. Remove dcache.o from TDEPFILES now
+ that we pick it up from the default REMOTE_O.
+
+ * breakpoint.c (bpstat_what): Initialize retval.call_dummy and
+ retval.step_resume.
+
+ * mips-tdep.c (mips_frame_chain): If frame size zero, return zero.
+ * rs6000-tdep.c: Add comment about framelessness.
+
+ * remote-nindy.c: Declare ninMemGet and ninMemPut.
+
+Wed Sep 22 08:02:57 1993 Stu Grossman (grossman at cygnus.com)
+
+ * Makefile.in: Add i386lynx-tdep to the right places.
+ (TARDIRS): Add gdbserver.
+
+ * exec.c (print_section_info): Print entry point.
+ * i386lynx-nat.c (i386lynx_saved_pc_after_call): Move into
+ i386lynx-tdep.c. Add core file support.
+ * i386lynx-tdep.c: New module for Lynx/386 target dependant code.
+ * maint.c: Add `maint info sections' command to print info about all
+ sections that BFD knows about for exec and core files.
+ * sparc-tdep.c (sparc_push_dummy_frame): Update stack pointer
+ before putting frame on the stack. Consolidate writes to reduce
+ traffic for remote debugging.
+ * config/i386/i386lynx.mh (NATDEPFILES): Remove exec.o.
+ * config/i386/i386lynx.mt (TDEPFILES): Add exec.o, i386lynx-tdep.o.
+ * config/i386/nm-i386lynx.h: Add target_pid_to_str().
+ * config/i386/tm-i386lynx.h: Remove target_pid_to_str().
+ * sparclite/Makefile.in: Add deps to keep Sun make happy.
+
+Tue Sep 21 17:48:14 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * breakpoint.h, breakpoint.c (bpstat_stop_status): Add new argument
+ not_a_breakpoint.
+ * infrun.c (wait_for_inferior): Pass it. Also consolidate the
+ test of whether we are stepping into a CURRENTLY_STEPPING macro.
+
+Tue Sep 21 17:22:34 1993 K. Richard Pixley (rich@sendai.cygnus.com)
+
+ * breakpoint.c (bpstat_stop_status),
+ infcmd.c (step_1),
+ infrun.c (wait_for_inferior): collapse SHIFT_INST_REGS ifdef
+ and insert macro.
+
+ * m88k-tdep.c: include ieee-float.h. new global target_is_m88110.
+ new const struct ext_format_m88110 for float format.
+ (pic_prologue_code): add braces.
+ (next_insn): remove unused variable buf.
+ (frame_find_saved_regs): remove unused variables next_addr,
+ saved_regs, regnum.
+ (frame_locals_address): remove unused variables frame, ap.
+ (frame_args_address): remove unused variables frame, ap.
+ (push_parameters): add some breaks and a default case.
+
+ * remote-bug.c: remove redundant includes of value.h, target.h,
+ serial.h.
+ (bug_open): corrected typo, sr_multi_scan -> gr_multi_scan.
+ (bug_fetch_register): special case sfip register for m88110.
+ remove flag bit masking of pc registers. This should be handled
+ by the ADDR_BITS_* macros.
+ (bug_store_register): special case sfip register for m88110.
+ Corrected sprint format for extended registers.
+
+ * config/m88k/tm-m88k.h: white space and comment changes. include
+ ieee-float.h. expanded to cope with m88110 extended registers.
+ (R0_REGNUM, XFP_REGNUM, X0_REGNUM): new macros.
+ (SHIFT_INST_REGS): becomes a real macro.
+
+Tue Sep 21 17:48:14 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * breakpoint.c (breakpoint_1): Support bp_call_dummy.
+
+Tue Sep 21 17:06:19 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * elfread.c (record_minimal_symbol_and_info): Guess the section to
+ use from the type.
+ * objfiles.c: Include gdb-stabs.h for SECT_* macros.
+ (objfile_relocate): Relocate textlow and texthigh in psymtabs.
+ Relocate partial symbols. Check that minimal SYMBOL_SECTION is
+ nonnegative before using it.
+ * symtab.h: Adjust section field comment.
+
+ * remote.c (interrupt_query): New function.
+ (remote_interrupt_twice): Call interrupt_query.
+ (putpkt, getpkt): If quit_flag is set, call interrupt_query.
+ (remote_wait): Don't bother with objfile_relocate if the addresses
+ haven't changed.
+ (remote_fetch_registers): If we see a packet that doesn't start
+ with a hex character, fetch a new one.
+
+Tue Sep 21 11:44:00 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * remote.c, remote-utils.c: Use SERIAL_FLUSH_INPUT after opening it.
+
+ * printcmd.c (print_scalar_formatted): When truncating value we are
+ going to print as unsigned, handle it generally for any length
+ less than sizeof (LONGEST), rather than special-casing sizeof (char),
+ sizeof (short), and sizeof (long). Clarify comment on what this
+ is for.
+
+ * symfile.c (deduce_language_from_filename): Accept .cxx for C++.
+ * buildsym.c (start_subfile): Use deduce_language_from_filename
+ rather than checking for .C or .cc ourself.
+
+Mon Sep 20 14:53:11 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * defs.h: Declare argument of re_comp as const char *.
+
+ * remote.c, remote-mips.c: Use sr_get_debug not remote_debug.
+
+ * README: Say using bfd from another release doesn't generally work.
+
+Sat Sep 18 10:13:18 1993 Jim Kingdon (kingdon@poseidon.cygnus.com)
+
+ * mipsread.c (parse_type): Don't complain() if we guessed struct
+ and it was a union, or vice versa.
+
+ * defs.h (make_cleanup): Change PTR to void * when inside PARAMS.
+
+ Some of the following is in #ifdef CALL_DUMMY_BREAKPOINT_OFFSET.
+ * breakpoint.h (enum bptype): Add bp_call_dummy.
+ (struct bpstat_what): Add call_dummy field.
+ * infrun.c (wait_for_inferior): Deal with it.
+ * breakpoint.c (bpstat_what): Deal with call dummy breakpoint.
+ * infcmd.c (run_stack_dummy): Set the call dummy breakpoint.
+ * config/sparc/tm-sparc.h: Define CALL_DUMMY_BREAKPOINT_OFFSET.
+
+ * remote-sim.h: New file.
+ * remote-sim.c: Add remote debug feature. Rename stuff to distinguish
+ interface to simulator from gdb-specific stuff. Other changes.
+ * remote-sp64sim.c: Renamed to remote-sim.c.
+ Use sr_get_debug instead of our own sim_verbose/simif_snoop.
+ Use gnutarget in call to bfd_openr.
+ Rename simif_* to gdbsim_*.
+ * config/sparc/sp64sim.mt: Change remote-sp64sim.c to remote-sim.c.
+
+Fri Sep 17 04:41:17 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * findvar.c (extract_signed_integer): Cast *p to LONGEST before doing
+ the xor and subtract. Otherwise it will not sign extend if the type
+ of LONGEST is larger than int.
+ * cp-valprint.c (cp_print_class_method): Inhibit core dump if
+ domain is an undefined cross reference.
+ * valops.c (call_function_by_hand): Set real_pc to correct
+ value if CALL_DUMMY_LOCATION != ON_STACK.
+
+Thu Sep 16 20:37:06 1993 Jim Kingdon (kingdon@cirdan.cygnus.com)
+
+ * config/a29k/tm-a29k.h (FRAME_CHAIN): If rsize is zero, return zero.
+
+Thu Sep 16 13:16:22 1993 Stu Grossman (grossman at cygnus.com)
+
+ * infrun.c (wait_for_inferior): Allow user to single step within
+ a stack dummy.
+
+Thu Sep 16 12:34:01 1993 Jim Kingdon (kingdon@cirdan.cygnus.com)
+
+ * dbxread.c (copy_pending): Deal with END NULL.
+ (process_one_symbol): Add comments about what common_block NULL means.
+
+Wed Sep 15 14:50:26 1993 Jim Kingdon (kingdon@cirdan.cygnus.com)
+
+ * remote-udi.c, remote-adapt.c, remote-mm.c: Move processor_type
+ to tm-a29k.h and a29k-tdep.c and make it an enum.
+ * a29k-tdep.c (a29k_get_processor_type): New function. Fix many
+ aspects of how we detected the processor type.
+ * remote-udi.c, remote-adapt.c, remote-mm.c (*_open): Call it
+ rather than figuring out the type ourselves.
+
+Thu Sep 16 12:12:59 1993 Stu Grossman (grossman at cygnus.com)
+
+ * sparc-stub.c (_trap_low): Do restore/save sequence after
+ setting sp to ensure that we load the previous window from the
+ right place on the stack.
+
+Thu Sep 16 00:36:32 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * mipsread.c: Many changes for alpha ecoff format:
+ Correct sizeof(int) == sizeof(long) assumptions.
+ Replace stParsed hack by putting the parsed types on the pending chain.
+ Replace mips specific ecoff mapping by ECOFF_REG_TO_REGNUM macro,
+ provide default for cross debugging.
+ Swapping the symbol back is no longer needed as the symbol is not
+ modified anymore.
+ Add new alpha basic types, handle btTypedef, handle stStaticProc
+ external symbols .
+ Update and clean up cross_ref for alpha cc cross ref variations.
+ Allocate types on the type_obstack to inhibit storage leaks.
+ * config/mips/tm-mips.h (ECOFF_REG_TO_REGNUM): Define.
+ * gdbtypes.c (recursive_dump_type): Dump TYPE_TAG_NAME if it is set.
+
+Tue Sep 14 09:12:17 1993 Jim Kingdon (kingdon@cirdan.cygnus.com)
+
+ * stabsread.c (read_type): Process "s" (size) type attribute.
+ If type is defined to another type, copy the type.
+
+Tue Sep 14 18:37:17 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * config/i386/i386v4.mh (NATDEPFILES): Move exec.o from here...
+ * config/i386/i386v4.mt (TDEPFILES): ...to here.
+
+Tue Sep 14 12:21:49 1993 K. Richard Pixley (rich@sendai.cygnus.com)
+
+ * Makefile.in (remote_utils_h): add serial.h and target.h.
+ (main.o, remote-es.o, remote-nindy.o, remote.o): remove target.h
+ (already in remote_utils_h).
+ (remote-utils.o): new rule.
+
+ * remote-utils.h: include serial.h.
+
+ * serial.h: ifdef protect from multiple inclusion.
+
+ * remote.c, remote-nindy.c, remote-mon.c, remote-es.c: include
+ remote-utils.h.
+
+ * remote.c (remote_open), remote-nindy.c (nindy_open,
+ nindy_files_info), remote-mon.c (general_open), remote-es.c
+ (es1800_open): use remote-utils facilities for baud rate.
+
+Tue Sep 14 09:12:17 1993 Jim Kingdon (kingdon@cirdan.cygnus.com)
+
+ * paread.c, coffread.c, elfread.c, dwarfread.c:
+ Include <time.h> and <sys/types.h> before libbfd.h.
+
+ * paread.c: Define BYTES_IN_WORD before including aout/aout64.h.
+
+ * Makefile.in (a29k-tdep.o): Depend on $(defs_h).
+ * config/a29k/tm-a29k.h (SAVED_PC_AFTER_CALL): Use gr122 not lr0
+ if this is a transparent procedure.
+
+Mon Sep 13 16:06:43 1993 Jim Kingdon (kingdon@cirdan.cygnus.com)
+
+ * remote.c: Define remote_debug to 0 and #if 0 baud_rate. Temporary
+ hack so this file compiles again.
+
+ * remote-utils.c (gr_multi_scan): Cast return value from alloca.
+ (gr_multi_scan): #if 0 never-reached return(-1).
+
+ * remote-udi.c (udi_wait): Return inferior_pid not 0.
+
+Mon Sep 13 14:14:35 1993 K. Richard Pixley (rich@sendai.cygnus.com)
+
+ Collect some remote things into remote-utils.
+ * remote-utils.[ch]: new files of functions collected from several
+ different remote targets.
+ * Makefile.in (REMOTE_O): add remote-utils.o.
+ (dcache_h, remote_utils_h): new macros.
+ (HFILES): add $(remote_utils_h).
+ (ALLDEPFILES): add $(remote_utils_h).
+ (dcache.o): new rule.
+ (main.o, remote-bug.o): also depend on $(remote_utils_h).
+ * target.h (remote_debug): extern moved to remote-utils.h.
+ * target.c (find_default_run_target, find_core_target): initialize
+ runable.
+ (remote_debug): moved to remote-utils.c.
+ (_initialize_targets): move declaration of user variable
+ remotedebug to remote-utils.c.
+ * remote-bug.c: include remote-utils.h rather than dcache.h.
+ (bug_close, bug_write, bug_write_cr, desc, bug_dcache, timeout,
+ dev_name, check_open, is_open, readchar, readchar_nofail,
+ pollchar, expect, expect_prompt, get_hex_digit, get_hex_byte,
+ get_hex_word, bug_kill, bug_detach, bug_create_inferior,
+ multi-scan, bug_prepare_to_store, bug_fetch_word,
+ bug_store_word, bug_files_info, bug_mourn, bug_com, bug_device,
+ bug_speed): removed and replaced with facilities from
+ remote-utils.[ch].
+ (bug_read_inferior_memory): renamed to bug_read_memory.
+ (bug_write_inferior_memory): renamed to bug_write_memory.
+ (bug_xfer_inferior_memory): renamed to bug_xfer_memory.
+ (get_word): comment out this unused function for now.
+ (bug_settings, cpu_check_strings): new statics.
+ (bug_open): rewritten to use gr_open.
+ (_initialize_remote_bug): remove declarations of commands bug,
+ device, speed.
+ * main.c: include remote-utils.h.
+ (baud_rate): removed to remote-utils.c.
+ (main): handle baud rate settings using new facilities from
+ remote-utils.
+ * defs.h (baud_rate): removed extern.
+
+ m88110 support via bug-197 monitor.
+ * remote-bug.c (get_reg_name, bug_fetch_register,
+ bug_store_register): added m88110 extended register support.
+ (wait_strings): added bug-197 prompt.
+ (bug_wait): cope with bug-197 prompt.
+ (start_load): cope with either bug-197 or bug-187 prompt.
+
+Mon Sep 13 12:53:09 1993 Jim Kingdon (kingdon@cirdan.cygnus.com)
+
+ * inferior.h, infrun.c, thread.c, infcmd.c: Remove all uses of
+ pc_changed. If it was ever set to a non-zero value, it was before
+ GDB 2.8. It doesn't seem to have any useful function.
+
+ * defs.h: Don't define NORETURN (see comment).
+
+Sat Sep 11 10:46:09 1993 Jim Kingdon (kingdon@poseidon.cygnus.com)
+
+ * m88k-nat.c (fill_gregset): Set r31 and sfip.
+
+Thu Sep 9 10:18:29 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * remote-udi.c (udi_wait, case UDIStdinNeeded): Use a loop calling
+ getchar() (terminated only on '\n') instead of scanf. Send the
+ '\n' which terminates it to the remote system.
+
+ More gcc lint:
+ * exec.c (ignore): Return 0.
+ * stack.c (return_command): Fetch lazy value directly, not via
+ VALUE_CONTENTS, to avoid "value computed is not used".
+ * inflow.c (new_tty): Move osigttou inside #if.
+
+ * remote.c (remote_fetch_registers): If remote reply is short, just
+ note that fact and keep going (reading extra registers as all bits 0).
+ (remote_store_registers): Send number of registers that were found
+ by remote_fetch_registers.
+ * m68k-tdep.c, config/m68k/tm-m68k.h, config/m68k/tm-*.h: Remove
+ HAVE_68881. Define CANNOT_STORE_REGISTER if ptrace() can't write
+ floating registers.
+ * config/m68k/{tm-m68k-nofp.h,m68k-nofp.mt,tm-m68k-fp.h,m68k-fp.mt}:
+ Remove, replaced by {tm-m68k-em.h,m68k-em.mt}.
+ * Makefile.in, configure.in: Change accordingly.
+
+Thu Sep 9 04:59:03 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * mipsread.c (cross_ref): Allow SGI extended symbol types as cross
+ reference targets.
+ * symmisc.c (print_symbol): Use TYPE_TAG_NAME not TYPE_NAME to avoid
+ printing of identities.
+
+Wed Sep 8 19:18:27 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * breakpoint.c (breakpoint_1): Deal with step resume breakpoint.
+
+Wed Sep 8 13:01:10 1993 K. Richard Pixley (rich@cygnus.com)
+
+ Gcc lint.
+ * config/m88k/tm-m88k.h (frame_find_saved_regs): prototype.
+ * config/h8300/tm-h8300.h (NUM_REGS): rewrite to avoid nested comment.
+ * blockframe.c (get_prev_frame_info): initialize address.
+ * breakpoint.c (bpstat_copy): initialize retval.
+ (bpstat_stop_status): initialize value_is_zero.
+ (bpstat_what): initialize bs_class.
+ (breakpoint_1, mention): add do-nothing case for bp_step_resume.
+ (break_command_1): initialize cond_end, addr_end, &
+ canonical_strings_chain.
+ (enable_breakpoint): initialize save_selected_frame.
+ * buildsym.c (end_symtab): initialize symtab & linetablesize.
+ * c-exp.y (parse_number): initialize i.
+ * c-typeprint.c (c_type_print_varspec_prefix): include
+ TYPE_CODE_BITSTRING in switch statements and do nothing.
+ * c-valprint.c (c_val_print): removed unused variable c.
+ * ch-valprint.c (chill_val_print): removed unused variable eltlen.
+ * cp-valprint.c (cp_print_class_method): initialize f & j.
+ * eval.c (evaluate_subexp): initialize pc2, arg1, arg2.
+ * expprint.c (print_subexp): initialize myprec, assoc, & tempstr.
+ * findvar.c (value_from_register): initialize first_addr.
+ * gdbtypes.c (lookup_struct_elt_type): localize use of temporary
+ variable typename.
+ * infcmd.c (run_stack_dummy): return zero rather than simple
+ return.
+ * infrun.c (wait_for_inferior): initialize stop_sp, prologue_pc.
+ remove symtab, appears unused.
+ (restore_selected_frame): return 1.
+ * mipsread.c (psymtab_to_symtab_1): initialize first_off.
+ (fixup_sigtramp): initialize b0.
+ * printcmd.c (do_examine): initialize val_type.
+ (print_frame_args): initialize b.
+ * ser-tcp.c (tcp_restore): comment out declaration. Appears
+ unused.
+ * ser-unix.c (hardwire_restore): comment out declaration. Appears
+ unused.
+ (hardwire_send_break): moved variable status into ifdef
+ HAVE_SGTTY.
+ (wait_for): moved variable numfds into ifdef HAVE_SGTTY.
+ * serial.h: comment change only.
+ * stabsread.c (rs6000_builtin_type): initialize rettype.
+ (read_range_type): initialize nbits.
+ * stack.c (print_frame_info): remove unused variable numargs.
+ (parse_frame_specification): remove unused variables arg1, arg2,
+ arg3.
+ (return_command): initialize return_value.
+ * symfile.c (cashier_psymtab): initialize pprev.
+ * symtab.c (find_pc_psymbol): initialize best.
+ (lookup_symbol): initialize s.
+ (make_symbol_completion_list): initialize quote_pos.
+ * thread.c: include command.h.
+ (thread_info): static declaration removed; unused.
+ (info_threads_command): fix == vs = typo.
+ * typeprint.c (whatis_exp): initialize old_chain.
+ * valprint.c (val_print_string): remove unused variable
+ first_addr_err. Initialize old_chain.
+ (_initialize_valprint): white space comment change.
+ * values.c (show_values): rewrite if statement to avoid empty
+ body.
+ (vb_match): remove unused variable fieldtype_target_type.
+
+Wed Sep 8 10:21:33 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * Makefile.in (mipsread.o): Depend on $(bfd_h).
+
+Tue Sep 7 13:06:44 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdbserver/Makefile.in (TAGS): config files are in
+ $(srcdir)/../config, not $(srcdir)/config.
+
+ * config/pa/tm-hppa.h: Declare target_read_pc and target_write_pc.
+ (STORE_RETURN_VALUE): Pass the correct offset of the return
+ register to write_register_bytes.
+ * hppa-tdep.c: Use target_write_pc if PCOQ_TAIL_REGNUM was not saved.
+
+Tue Sep 7 14:30:34 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * remote.c (remote_wait): Don't call error. Instead, call warning
+ inside a loop. User can ^C to get out.
+
+ * config/m68k/tm-m68k.h (FIX_CALL_DUMMY): Changed name of swapping
+ routine to match BFD name change.
+ * config/z8k/tm-z8k.h (FIX_CALL_DUMMY): Likewise.
+
+Mon Sep 6 15:01:57 1993 Jeffrey Wheat (cassidy@cygnus.com)
+
+ * elfread.c: change elf32_symbol_type to elf_symbol_type
+
+Mon Sep 6 15:43:25 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * remote.c (remote_wait): Added 'W' and 'N' responses.
+
+Fri Sep 3 08:57:10 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * main.c, utils.c: Add comments about immediate_quit.
+
+ * elfread.c (elf_symtab_read): Don't add symbols starting with ".L"
+ to minimal symbols.
+
+ * target.c (pop_target): Don't try to deal with the stack becoming
+ empty. Shouldn't happen and the code that tried was broken.
+
+ * dcache.c: Cast return value from xmalloc.
+
+ * remote.c: Move setting of immediate_quit from remote_open to
+ remote_start_dummy and set it back to zero when done.
+
+Thu Sep 2 00:07:36 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * m88k-tdep.c: Remove a bunch of unused #includes.
+
+ * language.h: Add comment about current_language.
+
+ * mips-tdep.c (_initialize_mips_tdep): Change heuristic-fence-post
+ from var_uinteger to var_zinteger.
+
+ * configure.in: Fix typo (delta88r4 -> delta88v4).
+
+ * config/m88k/xm-delta88.h: Don't include sys/siginfo.h. It was
+ to make this work on SVR4 before SVR4 had its own configuration,
+ and it breaks SVR3.
+
+ * config/m88k/tm-delta88v4.h: Define FRAME_CHAIN_VALID_ALTERNATE.
+
+ * config/m88k/delta88v4.h (NATDEPFILES): Remove infptrace.o inftarg.o.
+
+ * config/m88k/xm-dgux.h: Renamed from config/m88k/xm-m88k.h.
+ * config/m88k/m88k.mh: Use xm-dgux.h.
+ * config/m88k/xm-m88k.h: New file, with HOST_BYTE_ORDER,
+ MAKEVA_END and MAKEVA_ARG.
+ * config/m88k/xm-*.h: Include m88k/xm-m88k.h.
+ * printcmd.c: Remove __INT_VARARGS_H code; now in xm-m88k.h.
+
+Wed Sep 1 19:31:28 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * remote-udi.c (udi_wait): Call `warning' not `error'.
+
+ * symtab.c (COMPLETION_LIST_ADD_SYMBOL): If the symbol has a
+ demangling, don't put the mangled form in the completion list.
+
+ * symtab.c, symfile.c, c-exp.y, ch-exp.y, m2-exp.y, buildsym.c,
+ symfile.h, stabsread.c, minsyms.c, solib.c, nlmread.c, dwarfread.c
+ partial-stab.h, symmisc.c, gdbtypes.c: Lint. Remove (or put
+ inside #if) unused variables and labels. Fix unclosed comment.
+ Deal with enumeration values unhandled in switch statements. Make
+ sure non-void functions return values. Include appropriate
+ headers.
+ * dbxread.c (elfstab_build_psymtabs): Don't check for unsigned
+ value < 0.
+
+Wed Sep 1 14:36:00 1993 K. Richard Pixley (rich@sendai.cygnus.com)
+
+ * i960-tdep.c, ns32k-pinsn.c, remote-adapt.c, xcoffread.c:
+ index -> strchr.
+
+Wed Sep 1 11:35:49 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * remote.c: Add comment explaining why dcache is disabled.
+ (remote_fetch_word, remote_store_word): Make static and #if 0.
+ They are not called from anywhere.
+
+Wed Sep 1 14:41:28 1993 K. Richard Pixley (rich@sendai.cygnus.com)
+
+ * arm-tdep.c, convex-tdep.c, convex-xdep.c, dbxread.c,
+ h8300-tdep.c, h8500-tdep.c, i960-pinsn.c, i960-tdep.c,
+ infptrace.c, m88k-tdep.c, mips-tdep.c, regex.c, remote-vx.c,
+ rs6000-tdep.c, xcoffexec.c, xcoffread.c, z8k-tdep.c,
+ config/arm/tm-arm.h, config/convex/tm-convex.h,
+ config/gould/tm-np1.h, config/gould/tm-pn.h,
+ config/m68k/tm-isi.h, config/ns32k/tm-umax.h,
+ config/pa/tm-hppa.h, config/pyr/tm-pyr.h,
+ config/rs6000/tm-rs6000.h, config/tahoe/tm-tahoe.h,
+ config/vax/tm-vax.h: bzero -> memset.
+
+ * regex.c: bcmp -> memcmp.
+
+Wed Sep 1 11:35:49 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * symtab.c (find_pc_line, find_line_common),
+ symtab.h (struct linetable), xcoffread.c (arrange_linetable):
+ Revise comments re linetable sorting.
+ * buildsym.c (compare_line_numbers): Sort by pc, not by line.
+ * coffread.c: Tell end_symtab to sort the line table.
+
+ * coffread.c: Re-work a lot of the coff-specific stuff to use stuff
+ in buildsym.c. This includes coff_finish_block, coff_context_stack,
+ coff_local_symbols, coff_file_symbols, coff_global_symbols,
+ coff_end_symtab and coff_add_symbol_to_list.
+ (read_enum_type): Deal with it now that we have a "struct pending"
+ not a "struct coff_pending".
+
+ * buildsym.c (end_symtab): Don't realloc subfile->linetable.
+
+Wed Sep 1 13:12:43 1993 K. Richard Pixley (rich@sendai.cygnus.com)
+
+ * a68v-nat.c, altos-xdep.c, convex-tdep.c, convex-xdep.c,
+ findvar.c, hppab-nat.c, hppah-nat.c, i386mach-nat.c,
+ irix4-nat.c, m68k-tdep.c, m88k-tdep.c, mipsread.c, regex.c,
+ remote-bug.c, remote-hms.c, rs6000-nat.c, rs6000-tdep.c,
+ sparc-nat.c, stabsread.c, sun3-nat.c, sun386-nat.c, symfile.c,
+ umax-xdep.c, xcoffread.c, 29k-share/udi/udip2soc.c,
+ 29k-share/udi/udr.c, config/a29k/tm-a29k.h, config/arm/tm-arm.h,
+ config/convex/tm-convex.h, config/gould/tm-np1.h,
+ config/gould/tm-pn.h, config/h8300/tm-h8300.h,
+ config/h8500/tm-h8500.h, config/i386/tm-i386aix.h,
+ config/i386/tm-sun386.h, config/i386/tm-symmetry.h,
+ config/i960/tm-i960.h, config/m68k/tm-news.h,
+ config/m88k/tm-m88k.h, config/mips/tm-mips.h,
+ config/ns32k/tm-merlin.h, config/ns32k/tm-umax.h,
+ config/pa/tm-hppa.h, config/pyr/tm-pyr.h,
+ config/rs6000/tm-rs6000.h, config/sh/tm-sh.h,
+ config/tahoe/tm-tahoe.h, config/vax/tm-vax.h,
+ config/z8k/tm-z8k.h, nindy-share/nindy.c: bcopy -> memcpy.
+
+Wed Sep 1 05:05:53 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * mipsread.c (parse_partial_symbols): Use language from FDR if it
+ is unambigous. Patch from ptf@delcam.co.uk (Paul Flinders).
+ * mipsread.c (ecoff_symfile_info): New struct to hold the global
+ pending_list.
+ * mipsread.c (mipscoff_symfile_init, parse_partial_symbols):
+ Allocate the global pending list and link it to the objfile.
+ * mipsread.c (is_pending_symbol, add_pending): Use global pending
+ list from objfile. Allocate pending list entries from the
+ psymbol_obstack.
+ * mipsread.c (free_pending): Remove. The pending list is now
+ freed when the psymbol_obstack is freed.
+ * mipsread.c (psymtab_to_symtab1): Remove pending list allocation,
+ the global pending list is used now.
+ * mipsread.c (parse_partial_symbols): Skip only the first
+ file indirect entry when building the dependency list.
+
+Tue Aug 31 15:01:27 1993 K. Richard Pixley (rich@sendai.cygnus.com)
+
+ Break dcache code out of remote.c.
+ * dcache.h: white space changes only.
+ * dcache.c: add user settable variable to set whether data caching
+ is in use.
+ * remote.c: include dcache.h. removed data caching code which is
+ now in dcache.c. Compile in data caching again. (data caching
+ is currently off by default.)
+ (remote_read_bytes, remote_write_bytes): change second arg to
+ unsigned char.
+ (remote_dcache): new static variable.
+ * Makefile.in (REMOTE_O): add dcache.o.
+ * config/m88k/m88k.mt (TDEPFILES): removed dcache.o.
+
+ Break dcache code out of remote-nindy.c.
+ * remote-nindy.c: removed dcache code. Changed callers to use new
+ conventions. include dcache.h.
+ (nindy_dcache): new static variable.
+ * config/i960/nindy960.mt (TDEPFILES): added dcache.o.
+
+ Break dcache code out of remote-bug.c into dcache.[hc].
+ * Makefile.in (dcache_h): new macro.
+ (HFILES): added $(dcache_h).
+ (ALLDEPFILES): added dcache.c.
+ (dcache.o): new rule.
+ (remote-bug.o): now depends on $(dcache_h).
+ * remote-bug.c: include dcache.h. remove externs for insque and
+ remque, add extern for bcopy. Prototype bug_close,
+ bug_clear_breakpoints, bug_write_cr. dcache code moved to
+ dcache.[hc]. Changed dcache calling convention to include an
+ initial DCACHE argument.
+ (bug_dcache): new static variable.
+ (bug_read_inferior_memory): change second arg to
+ unsigned char.
+ * dcache.[ch]: new files.
+ * config/m88k/m88k.mt (TDEPFILES): add dcache.o.
+
+Tue Aug 31 10:33:13 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * c-typeprint.c (c_print_type_base): Treat show = 0 just like
+ show < 0. The only case where we had been distinguishing is that
+ show = 0 used to print "struct " or "enum " instead of
+ "struct {...}" or "enum {...}" which seems clearly wrong.
+
+Mon Aug 30 17:51:32 1993 K. Richard Pixley (rich@sendai.cygnus.com)
+
+ * configure.in: recognize m88110 as an m88k.
+
+Mon Aug 30 16:07:59 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * valops.c (call_function_by_hand): If we discard cleanups, call
+ bpstat_clear (&inf_status.stop_bpstat).
+
+Mon Aug 30 12:47:46 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * stabsread.h, dbxread.c (end_psymtab): Return NULL if the psymtab
+ was empty and thrown away.
+ * mipsread.c (parse_partial_symbols): Do not add empty psymtabs to
+ dependency list, skip self dependencies.
+ * mipsread.c (parse_fdr): Removed, obsolete.
+ * mipsread.c (parse_lines): Check for cbLine being zero, not
+ cbLineOffset.
+ * mipsread.c (struct symloc): Add pst_language.
+ * mipsread.c (parse_partial_symbols): Set up proper language for
+ header files, save it in pst_language for psymtab_to_symtab_1.
+ * mipsread.c (psymtab_to_symtab_1): Use pst_language.
+
+Mon Aug 30 10:48:06 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * configure.in: Fix typo m88*-motorola-svr4* -> sysv4*.
+
+Fri Aug 27 17:09:19 1993 Ken Raeburn (raeburn@cambridge.cygnus.com)
+
+ * paread.c: Include som.h instead of libhppa.h. (From Utah.)
+
+Fri Aug 27 09:30:40 1993 Jim Kingdon (kingdon@deneb.cygnus.com)
+
+ * symmisc.c (dump_symtab): Use catch_errors around print_symbol.
+ Change calling sequence of print_symbol to fit catch_errors.
+
+ * mips-tdep.c: Call reinit_frame_cache every time the user does
+ "set heuristic-fence-post".
+
+ * gdbserver/low-sun3.c: New file.
+ * gdbserver/Makefile.in, config/m68k/sun3.mh: Change accordingly.
+
+ * Rename files for 14-character limits:
+ gdbserver/remote-gutils.c -> gdbserver/utils.c
+ gdbserver/remote-inflow.c -> gdbserver/low-lynx.c
+ gdbserver/remote-inflow-sparc.c -> gdbserver/low-sparc.c
+ gdbserver/remote-server.c -> gdbserver/server.c
+ remote-monitor.c -> remote-mon.c
+ * Makefile.in, gdbserver/Makefile.in, gdbserver/configure.in,
+ config/m68k/monitor.mt, config/i386/i386lynx.mh,
+ config/sparc/sun4os4.mh: Change accordingly.
+ * gdbserver/Makefile.in: Remove more junk inherited from gdb Makefile.
+
+Thu Aug 26 14:32:51 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * infcmd.c, inferior.h (run_stack_dummy): If we stop somewhere
+ besides the dummy, return 1 rather than calling error().
+ Let caller print the error message. Remove name argument.
+ * valops.c (call_function_by_hand): Deal with changes to calling
+ sequence of run_stack_dummy. Discard restore_inferior_status cleanup
+ if run_stack_dummy returns 1.
+
+ * Version 4.10.2.
+
+ * config/mips/tm-mips.h (EXTRACT_STRUCT_VALUE_ADDRESS):
+ Get struct return address from v0, not a0.
+
+ * infrun.c (restore_inferior_status): Use catch_errors when
+ restoring selected frame.
+
+Wed Aug 25 21:52:25 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * infrun.c (save_inferior_status, restore_inferior_status):
+ Save and restore the registers too.
+ * inferior.h (struct inferior_status): Add "registers".
+
+Tue Aug 24 00:36:17 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * dbxread.c (end_psymtab): Clean up comment.
+
+ * frame.h, symtab.h, findvar.c (read_var_value): Change basereg
+ support to use LOC_BASEREG rather than SYMBOL_BASEREG_VALID.
+ * dwarfread.c: Use LOC_BASEREG where appropriate.
+ * Various: Support LOC_BASEREG and LOC_BASEREG_ARG.
+
+ * coffread.c (init_lineno, init_stringtab): Don't check whether
+ xmalloc returned NULL.
+
+ * config/vax/xm-vaxult.h: Define NO_PTRACE_H.
+
+ * target.c, target.h: Add "set remotedebug" command.
+ * remote-bug.c, remote.c, remote-mips.c: Remove "set remotedebug" and
+ "set m88ksnoop" options and use generic "set remotedebug" instead.
+ * NEWS: Describe this change.
+
+Mon Aug 23 20:26:22 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * buildsym.h: Remove declaration of dbxread.c functions.
+ * stabsread.h: Group together dbxread.c functions.
+ Move elfstab_build_psymtabs here from symfile.h.
+ Declare pastab_build_psymtabs.
+ * elfread.c, paread.c: Include stabsread.h (for stabsread_new_init
+ declaration, etc).
+
+Mon Aug 23 17:16:23 1993 K. Richard Pixley (rich@sendai.cygnus.com)
+
+ * remote-bug.c: rename quiet to bug88k_snoop.
+ (double_scan, multi_scan): generalize double_scan into a scan
+ for multiple patterns. Rename to multi_scan.
+ (bug_wait, bug_write_inferior_memory): adapt to use the new
+ multi_scan in order to catch and represent target bus errors.
+ (bug_scan): currently unused, so comment out.
+ (bug_quiet): removed. Replaced with a standard user settable boolean.
+
+ * m88k-tdep.c: remove include of sys/dir.h. Appears unnecessary
+ and isn't available on solaris.
+
+Mon Aug 23 14:56:42 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * config/m88k/{delta88v4.mt,delta88v4.mh}: New files
+ * config/m88k/delta88.mh: Fix comment.
+ * config/m88k/tm-delta88.h: Remove unused BCS define.
+ * config/m88k/{tm-delta88v4.h,xm-delta88v4.h,nm-delta88v4.h}:
+ New files.
+ * configure.in: Recognize m88*-motorola-sysv4*.
+ * m88k-nat.c: Always include sys/types.h; don't depend on USG.
+
+Mon Aug 23 12:57:42 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * mipsread.c (parse_symbol, parse_type, cross_ref): Pass name of
+ symbol as an argument and use it in complaints.
+ * symmisc.c (dump_psymtab): Dump filenames of dependencies.
+
+Mon Aug 23 1993 Sean Fagan (sef@cygnus.com)
+ and Jim Kingdon (kingdon@cygnus.com)
+
+ Add NetBSD support:
+ * configure.in: Recognize netbsd.
+
+Sun Aug 22 22:50:32 1993 Jeff Law (law@snake.cs.utah.edu)
+
+ * hpread.c (get_textlow): Don't go past a K_END when looking for a
+ K_FUNCTION. Avoids losing on source files with no functions.
+
+Fri Aug 20 14:01:39 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * remote-nindy.c: Remove unused include of sys/ioctl.h.
+
+ * frame.h, symtab.h: Revise comments regarding baseregs.
+
+Fri Aug 20 15:07:05 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * mipsread.c (parse_partial_symbols, psymtab_to_symtab_1):
+ Set language for psymtab and symtab.
+ * mipsread.c (new_symbol): Set language and initialize demangled
+ name for symbol.
+ * symmisc.c (print_symbol): Use SYMBOL_SOURCE_NAME when printing
+ the symbol type.
+ * symtab.c (decode_line_1): Inhibit coredumps with cfront executables.
+
+Fri Aug 20 14:01:39 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * Move KERNEL_U_ADDR from xm-hp300bsd.h to nm-hp300bsd.h and make
+ it conditionalized on 4.3 vs. 4.4.
+ * config/m68k/nm-hp300bsd.h: Move REGISTER_U_ADDR out of 4.3 and
+ 4.4 sections; it was identical and now works for 4.4.
+
+ * mips-tdep.c (is_delayed): Use INSN*BRANCH* not ANY_DELAY.
+
+ * printcmd.c (MAKEVA_END): Update this version to use "aligner".
+
+Thu Aug 19 22:08:09 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * config/vax/tm-vax.h (BELIEVE_PCC_PROMOTION): Define.
+ * mipsread.c (parse_symbol, parse_type, cross_ref): Handle corrupt
+ file indirect entries with complaints instead of core dumps. Remove
+ complaint for stTypedef within aggregates.
+
+Thu Aug 19 17:58:39 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * coffread.c (process_coff_symbol): Ignore tagnames like .0fake.
+
+ * coffread.c (coff_read_enum_type): #if 0 out code which changes
+ enum {FALSE, TRUE} into boolean.
+
+ * config/m68k/delta68.m{t,h}: Use nm-delta68.h, etc. not
+ non-existent files nm-delta.h, etc.
+ * config/m68k/tm-delta68.h: Define CANNOT_STORE_REGISTER.
+ * delta68-nat.c: Add "[0]" in offsetof argument.
+ * delta68-nat.c (_initialize_kernel_u_addr): Don't try to set up
+ nl with initializer, just assign to it. Check n_scnum field on
+ return.
+
+Wed Aug 18 21:42:52 1993 Jeff Law (law@snake.cs.utah.edu)
+
+ * hpread.c (read_hpux_symtab): Call SET_NAMESTRING for K_MODULE
+ debug symbols.
+
+Wed Aug 18 12:03:00 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * printcmd.c (print_address), values.c (value_as_pointer): Don't
+ use ADDR_BITS_REMOVE.
+ * defs.h: Try to clarify comment about ADDR_BITS_REMOVE.
+
+ * blockframe.c (block_innermost_frame): Uncomment.
+ Return NULL if passed NULL.
+ * frame.h: Declare it.
+ * expression.h (union exp_element): Add field block.
+ * parse.c (write_exp_elt_block): New function.
+ * expression.h (OP_VAR_VALUE): Now takes additional struct block *.
+ * *-exp.y: Write block for OP_VAR_VALUE.
+ * eval.c, expprint.c, parse.c: Deal with block for OP_VAR_VALUE.
+ * valops.c, value.h (value_of_variable), callers:
+ Add second argument, for block.
+
+ * main.c (gdb_readline): If we read some characters followed by EOF,
+ return them rather than returning NULL.
+
+Tue Aug 17 11:14:25 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * mips-tdep.c: Remove unused #ifndef NUMERIC_REG_NAMES and add comment.
+
+Tue Aug 17 15:10:04 1993 K. Richard Pixley (rich@sendai.cygnus.com)
+
+ * config/m88k/tm-m88k.h: Fix typo in comment.
+ (FP_REGNUM): define in terms of SP_REGNUM
+ rather than by absolute number. Also clearly comment that this
+ is a convenient lie in order to decrease future confusion.
+ (ACTUAL_FP_REGNUM): new macro for FP.
+ (FRAME_CHAIN_VALID): removed. Standard default works fine.
+ * m88k-tdep.c (frame_chain_valid): redundant, so removed.
+ (NEXT_PROLOGUE_INSN): removed unused fourth arg, fixed all
+ callers.
+ (read_next_frame_reg): declare static.
+ (examine_prologue): removed unused variabel insn2, rename insn1
+ to insn, rewrote comment about finding fp, sp, etc. set frame_fp
+ based on ACTUAL_FP_REGNUM rather than FP_REGNUM which is
+ actually a scammed alias for SP_REGNUM on m88k.
+
+ * frame.h: fixed typo in comment.
+
+Tue Aug 17 11:14:25 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * 29k-share/udi/udiphcfg.h: Always include udiphunix.h not udiphdos.h.
+
+ * complaints.c (complain): fflush (stdout) after output.
+
+Tue Aug 17 01:43:55 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * blockframe.c, frame.h (sigtramp_saved_pc): New routine to fetch
+ the saved pc from sigcontext on the stack for BSD signal handling.
+ * config/i386/tm-i386bsd.h (SIGTRAMP_START, SIGTRAMP_END, FRAME_CHAIN,
+ FRAMELESS_FUNCTION_INVOCATION, FRAME_SAVED_PC, SIGCONTEXT_PC_OFFSET):
+ Define to make backtracing through sigtramp work.
+ * config/vax/tm-vax.h (SIGTRAMP_START, SIGTRAMP_END, TARGET_UPAGES,
+ FRAME_SAVED_PC, SIGCONTEXT_PC_OFFSET): Ditto.
+
+Mon Aug 16 13:52:14 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * main.c (cd_command): If current_directory on entry is "/", then
+ don't append an extra slash.
+ Don't assume that /../.. means /.
+
+ * target.c (target_xfer_memory): Clear errno before calling
+ to_xfer_memory.
+
+ * stack.c (frame_info, print_frame_info): Add comment about using
+ the starting source line number on a line boundary if backtracing
+ through sigtramp.
+
+Mon Aug 16 09:52:33 1993 Jeff Law (law@snake.cs.utah.edu)
+
+ * hpread.c: Add U Utah contribution notice. Add TODO list.
+ (hp_type_lookup): Use TYPE_NAME and TYPE_TAG_NAME.
+ (process_one_debug_symbol): Likewise.
+
+Mon Aug 16 02:56:01 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * blockframe.c (create_new_frame, get_prev_frame_info):
+ Use the function name when calling IN_SIGTRAMP.
+ * config/m68k/tm-m68k.h (SIG_PC_FP_OFFSET, SIG_SP_FP_OFFSET):
+ Define for correct handling of bachtraces through _sigtramp.
+ * m68k-tdep.c (m68k_find_saved_regs): Adjust saved sp for fake
+ sigtramp frames.
+ * mipsread.c (parse_type): Handle corrupt TIR info with complaint
+ instead of core dump.
+ * mipsread.c (parse_partial_symbols): Put static symbols into the
+ mimimal symbol table, use proper mst_types for all minimal symbols.
+ * stack.c (frame_info, print_frame_info): Use the starting source
+ line number on a line boundary if backtracing through sigtramp.
+
+Fri Aug 13 14:37:05 1993 K. Richard Pixley (rich@sendai.cygnus.com)
+
+ * remote-bug.c: include gdbcmd.h.
+ (sleep, remque, insque): forward decls added.
+ (bug_fetch_registers, bug_store_registers): forward decls
+ removed.
+ (bug_read_inferior_memory, bug_write_inferior_memory): forward
+ decls added.
+ (srec_frame, srec_max_retries, srec_bytes, srec_echo_pace,
+ srec_sleep, srec_noise): new static variables for user settable
+ options. Mostly these are for debugging and tuning. I don't
+ expect them to stay user settable options for long.
+ (timeout): change default to 4 seconds.
+ (check_open): declare funtion static, force return value.
+ (readchar_nofail): if timeout, then say so if not being quiet.
+ (pollchar, double_scan, bug_scan, bug_srec_write_cr,
+ start_load): new functions.
+ (bug_wait): rewritten to use double scan.
+ (expect): while (1) -> for (;;)
+ (get_hex_digit): rewrite if condition to avoid gcc complaints.
+ (bug_load, bug_create_inferior, bug_open, bug_store_register):
+ removed unused variables.
+ (bug_load): replaced DELTA macro with user settable srec_frame
+ variable. Other minor lint.
+ (find_end_of_word, is_baudrate_right, set_rate, not_bug_wait,
+ gethex, timed_read, translate_addr, bug_before_main_loop):
+ unsused and removed.
+ (bug_resume): add missing first arg, pid.
+ (get_reg_name): use ip rather than cr04.
+ (bug_write, bug_write_cr, but_clear_breakpoints, bug_quiet):
+ declare type, args, and explicitly return.
+ (bug_store_register): straighten out the ip vs cr04 confusion.
+ (bug_write_inferior_memory): rewrite to cope with errors while
+ downloading s-records.
+ (bug_read_inferior_memory): declare static.
+ (bug_clear_breakpoints): expect nobr before prompt.
+ (_initialize_remote_bug): add initializations for srec-bytes,
+ srec-max-retries, srec-frame, srec-noise, srec-sleep,
+ srec-echo-pace.
+
+ * Makefile.in (remote-bug.o): new rule.
+ (ALLDEPFILES): added remote-bug.c
+
+ * remote-hms.c (hms_wait): use -1 for timeout's which means block
+ forever rather than 99999.
+
+ * ser-unix.c (get_tty_state): if a descriptor is not a tty, then
+ simply save encode this fact as the process group and return
+ success rather than an error.
+ (set_tty_state): if process group is -1, do not reset the
+ process group.
+ (hardwire_reachar): comment change.
+
+ * serial.h: comment change.
+
+ * config/m88k/tm-m88k.h: comment change to remove embedded
+ comment.
+ (SKIP_PROLOGUE): skip_prologue returns a value which is expected
+ to reset the pc argument. So reset it.
+
+Fri Aug 13 10:15:24 1993 Fred Fish (fnf@deneb.cygnus.com)
+
+ * Makefile.in (VERSION): Bump to 4.10.1 after release and cvs
+ tagging.
+
+Thu Aug 12 20:40:14 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdbserver/Makefile.in: Use GDBSERVER_LIBS and
+ GDBSERVER_DEPFILES. Also remove much (but not all that could be
+ removed) crud inherited from gdb Makefile.in.
+ * config/i386/i386lynx.mh, config/sparc/sun4os4.mh: Define GDBSERVER_*.
+ * gdbserver/README: Say it works on Sun and change configuration
+ instructions slightly.
+
+Wed Aug 11 18:56:59 1993 david d `zoo' zuhn (zoo@rtl.cygnus.com)
+
+ * config/i386/i386v4.mh: use -lsocket and -lnsl, for remote
+ targets that use BSD style network connections
+
+Wed Aug 11 17:54:24 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * remote-{monitor,bug}.c: Make bug_ops not static (forward declaration
+ of statics doesn't work with SunOS4 /bin/cc).
+ Rename the occurrence in remote-monitor.c to monitor_bug_ops.
+
+Tue Aug 10 13:07:14 1993 Jim Kingdon (kingdon@deneb.cygnus.com)
+
+ * blockframe.c (find_pc_partial_function),
+ mips-tdep.c (find_proc_desc): Deal with "pathological" case.
+
+Tue Aug 10 14:50:30 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * utils.c (wrap_here): Allow indent to be NULL.
+ (fputs_filtered): Don't check for null wrap_indent (wrap_here now
+ guarantees that it isn't, and anyway we were only checking one out
+ of the two places we dereferenced it).
+
+ * objfiles.h (struct objfile): Clean up comments for
+ {obj,sym}_private to clarify what they are private to.
+
+Mon Aug 9 16:45:00 1993 Stan Shebs (shebs@rtl.cygnus.com)
+
+ * stabsread.c, buildsym.c (hashname): Moved function to
+ buildsym.c, as suggested in the sources.
+
+Mon Aug 9 09:53:45 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * remote-udi.c: Make udi_ops extern rather than trying forward
+ declaration of a static variable.
+
+ * hppab-nat.c: Define ptrace to call_ptrace and pass the 5th arg
+ there, rather than using an ANSI C specific macro.
+
+ * 29k-share/udi/udr.c: Include fcntl.h not sys/fcntl.h. Also put
+ sys/types.h near the top (just on general principles).
+
+ * environ.c (set_in_environ): Remove G960BASE and G960BIN; they are
+ no longer used.
+
+ * gdbcore.h: New variable gnutarget.
+ * core.c: Add commands to set and show it.
+ * Callers to bfd_*open*: Pass gnutarget instead of NULL as target.
+ * environ.c (set_in_environ): For GNUTARGET, use set_gnutarget not
+ putenv.
+
+ * symtab.c (decode_line_1): Give error on unmatched single quote.
+
+Sun Aug 8 13:59:49 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * ser-unix.c (hardwire_send_break) [HAVE_SGTTY]: Use select not usleep.
+
+ * remote.c: Add comments about 'd', 'r', and unrecognized requests.
+
+ * inflow.c (terminal_init_inferior): Don't muck with tty state if
+ gdb_has_a_terminal() is false.
+
+Sun Aug 8 10:07:47 1993 Fred Fish (fnf@cygnus.com)
+
+ * dwarfread.c (record_minimal_symbol): Remove prototype and
+ function.
+ * dwarfread.c (add_partial_symbol): Remove code to add minimal
+ symbols and remove comment about limitations. Experiments show
+ that now that gdb handles the ELF symtab better for creating
+ minimal symbols, that no additional information is added by
+ examining the DWARF information, and in fact, given the
+ limitations, the DWARF code was actually making things worse.
+
+Sat Aug 7 10:59:03 1993 Fred Fish (fnf@deneb.cygnus.com)
+
+ * elfread.c (elf_symtab_read): Properly sort out the bss symbols
+ from the data symbols and give them the correct minimal_symbol_type.
+ Add file static symbols to the minimal symbol table, not just
+ global symbols. Add absolute symbols as well (like _edata, _end).
+ Redo stabs-in-elf special symbol handling now that file static
+ symbols are entered into the into the minimal symbol table.
+ * dwarfread.c (add_partial_symbol): Add comment about limitations
+ of DWARF symbols for distinquishing data from bss when adding
+ minimal symbols. Add file local symbols to minimal symbols.
+
+Thu Aug 5 08:58:58 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * ser-go32.c: Define job_control variable.
+
+Thu Aug 5 15:56:13 1993 david d `zoo' zuhn (zoo@rtl.cygnus.com)
+
+ * configure.in: z8k-coff is the same as z8k-sim
+
+Thu Aug 5 08:58:58 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * 29k-share/udi/udip2soc.c: Include sys/types.h before sys/file.h.
+
+ * config/i386/tm-i386bsd.h (NUM_REGS): There are only 10, not 11.
+
+ * inflow.c: Put all uses of F_GETFL and F_SETFL in #ifdef F_GETFL.
+
+ * 29k-share/udi/udip2soc.c: Include fcntl.h not sys/fcntl.h.
+
+Wed Aug 4 18:32:12 1993 Fred Fish (fnf@cygnus.com)
+
+ * inflow.c (pass_signal): Signal handlers take one int arg;
+ supply an unused one to make it type compatible as an arg to
+ signal().
+
+Tue Aug 3 18:34:14 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * config/mips/tm-mips.h: Include bfd.h before coff/sym.h.
+
+Tue Aug 3 15:34:57 1993 Fred Fish (fnf@cygnus.com)
+
+ * Makefile.in (ALLCONFIG): Add config/i386/i386nw.mt,
+ config/m68k/delta68.mh, config/m68k/delta68.mt,
+ config/m68k/dpx2.mh, config/m68k/dpx2.mt, config/mips/riscos.mh,
+ config/mips/news-mips.mh.
+ * Makefile.in (ALLPARAM): Add config/i386/nm-symmetry.h,
+ config/i386/tm-i386nw.h, config/m68k/nm-delta68.h,
+ config/m68k/tm-delta68.h, config/m68k/xm-delta68.h,
+ config/m68k/nm-dpx2.h, config/m68k/tm-dpx2.h,
+ config/m68k/xm-dpx2.h, config/mips/xm-makeva.h.
+ * Makefile.in (ALLDEPFILES): Add dpx2-nat.c.
+
+Tue Aug 3 12:02:09 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * mipsread.c: Updated for BFD ECOFF changes. Now gets the
+ swapping routines and external structure sizes via the
+ ecoff_backend information. No longer includes coff/mips.h.
+
+Tue Aug 3 10:58:04 1993 Fred Fish (fnf@cygnus.com)
+
+ * Makefile.in (SFILES): Add thread.c
+
+Tue Aug 3 10:21:58 1993 Doug Evans (dje@canuck.cygnus.com)
+
+ * remote-sp64sim.c (simif_create_inferior): Add FIXME regarding
+ sim_set_args return code.
+
+Mon Aug 2 16:35:31 1993 K. Richard Pixley (rich@sendai.cygnus.com)
+
+ * Makefile.in (VERSION): bumped to 4.9.4.
+
+ * remote-monitor.c: updated copyright.
+ (bug_ops, monitor_desc): now static.
+ (monitor_desc): in several places, check and/or set to NULL.
+
+ * remote-hms.c (hms_files_info): Add the appropriate items where
+ missing in the printf call.
+
+ * remote-bug.c: new file for m88k bug support.
+
+ * config/m88k/m88k.mt (TDEPFILES): added remote-bug.o.
+
+Mon Aug 2 14:22:09 1993 Steve Chamberlain (sac@phydeaux.cygnus.com)
+
+ * h8300-tdep.c: Use new variable h8300hmode.
+
+Mon Aug 2 12:06:00 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * valops.c (typecmp): If we are passing a non-reference to a function
+ which takes a reference, pass the address.
+ (value_arg_coerce): Don't use COERCE_ENUM; we don't want to dereference
+ references here.
+
+ * thread.c (thread_switch): Define as static.
+ (add_thread): Cast return value from xmalloc.
+
+ * gdbtypes.c (fill_in_vptr_fieldno): Call check_stub_type.
+ * gdbtypes.{c,h}: Improve comments on vptr_fieldno.
+
+Mon Aug 2 11:58:52 1993 Fred Fish (fnf@deneb.cygnus.com)
+
+ * README: Elaborate on gdb C++ support and cfront support.
+
+Mon Aug 2 11:30:57 1993 Stu Grossman (grossman at cygnus.com)
+
+ * i386lynx-nat.c, thread.c, thread.h: Update copyrights.
+
+Mon Aug 2 12:06:00 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * Makefile.in (ALLDEPFILES): Add i386lynx-nat.c.
+
+Mon Aug 2 08:42:50 1993 Stu Grossman (grossman at cygnus.com)
+
+ * gdbserver/remote-inflow.c (create_inferior): Fix comments, and
+ error msg. Setup seperate process group for child.
+ * (write_inferior_memory): Sleep for 1 second and retry on ptrace
+ failure.
+
+Sun Aug 1 22:58:18 1993 Stu Grossman (grossman at cygnus.com)
+
+ * config/i386/i386lynx.mh (NATDEPFILES): Drop coredep (for now).
+ * config/i386/nm-i386bsd.h: Protect from multiple inclusion.
+ * config/i386/nm-i386lynx.h: Lotsa new host porting stuff.
+ * config/i386/tm-i386lynx.h: Define SAVED_PC_AFTER_CALL and
+ target_pid_to_str.
+
+ * Makefile.in (CLIBS): Reorder to make Lynx ld happy.
+ * (HFILES): New file thread.h.
+ * (OBS): New file thread.c.
+ * configure.in: Host config for Lynx/386.
+ * fork-child.c (fork_inferior): Call init_thread_list().
+ * infrun.c (resume): Add pid to invocation of target_resume().
+ * (wait_for_inferior): Pay attention to pid from target_wait().
+ Multi-threading code now uses this to determine what to do.
+ * inftarg.c (child_wait): Conditionalize based on CHILD_WAIT macro.
+ Use target_pid_to_str() macro throughout when printing pid.
+ * inferior.h (child_resume): Add pid to prototype.
+ * hppab-nat.c hppah-nat.c infptrace.c (child_resume): Pass in pid as
+ argument, instead of using inferior_pid.
+ * procfs.c (procfs_resume): Pass in pid as argument. Ignored for
+ now. Use target_pid_to_str() macro throughout for printing process id.
+ * remote-adapt.c (adapt_resume): Pass in pid as argument.
+ * remote-eb.c (eb_resume): Pass in pid as argument.
+ * remote-es.c (es1800_resume): Pass in pid as argument.
+ * remote-hms.c (hms_resume): Pass in pid as argument.
+ * remote-mips.c (mips_resume): Pass in pid as argument.
+ * remote-mm.c (mm_resume): Pass in pid as argument.
+ * remote-monitor.c (monitor_resume): Pass in pid as argument.
+ * remote-nindy.c (nindy_resume): Pass in pid as argument.
+ * remote-sa.sparc.c (remote_resume): Pass in pid as argument.
+ * remote-sim.c (rem_resume): Pass in pid as argument.
+ * remote-sp64sim.c (simif_resume): Pass in pid as argument.
+ * remote-st.c (st2000_resume): Pass in pid as argument.
+ * remote-udi.c (udi_resume): Pass in pid as argument.
+ * remote-vx.c (vx_resume): Pass in pid as argument.
+ * remote-z8k.c (rem_resume): Pass in pid as argument.
+ * remote.c (remote_resume): Pass in pid as argument.
+ * solib.c (solid_create_inferior_hook): Pass inferior_pid to
+ target_resume().
+ * target.c (normal_pid_to_str): New routine to print out process
+ ID normally.
+ * target.h (struct target_ops): Add pid to prototype at
+ to_resume(). (target_resume): Add pid argument.
+ * (target_pid_to_str): Default definition for normal type pids.
+ * thread.h, thread.c: New modules for multi thread/process control.
+
+Sun Aug 1 13:02:42 1993 John Gilmore (gnu@cygnus.com)
+
+ * README: Say that bug-gdb is also the place to send requests
+ for help with GDB.
+
+Sun Aug 1 09:42:13 1993 Fred Fish (fnf@cygnus.com)
+
+ * Makefile.in (make-proto-gdb-1): Use -f opt on rm of Makefile.
+ * h8500-tdep.c: Add parens around a few macro args.
+
+Fri Jul 30 15:43:49 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * TODO: Remove items about unix-to-unix/rapp debugging (now we
+ have gdbserver), moving xm files to subdirectory, ptype yylval,
+ and file-local symbols.
+
+ * gdbtypes.h: Improve comments about C++ methods.
+
+Fri Jul 30 14:16:32 1993 Fred Fish (fnf@deneb.cygnus.com)
+
+ * c-exp.y: Add missing 5th arg for one call to lookup_symbol, cast
+ NULL in all other calls to correct pointer types.
+
+Fri Jul 30 15:43:49 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ From Jeffrey Law:
+ * tm-hppa.h (TARGET_WRITE_PC): Define.
+ * hppa-tdep.c (hppa_fix_call_dummy): If in a syscall,
+ then return the address of the dummy itself rather than
+ the address of $$dyncall.
+ (target_write_pc): New function to store a new PC.
+
+Fri Jul 30 12:51:27 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+ and Jim Kingdon (kingdon@cygnus.com)
+
+ * breakpoint.c (breakpoint_re_set_one): Always reparse breakpoint
+ conditions, they might contain symbol table references.
+
+Fri Jul 30 12:51:27 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * mipsread.c (parse_symbol): Handle opaque struct definitions and
+ type naming for stTypedef symbols.
+
+Fri Jul 30 14:44:21 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * c-exp.y (yylex): Detect C++ nested types.
+
+Fri Jul 30 11:07:37 1993 Doug Evans (dje@canuck.cygnus.com)
+
+ * sp64-tdep.c (sparc64_frame_chain, sparc64_frame_saved_pc): Deleted.
+ (dump_ccreg, sparc_print_register_hook): New fns.
+ * remote-sim.h: New file.
+ * remote-sp64sim.h (sim_*): External fns. (simif_*): Internal fns.
+
+ * config/sparc/sp64.mt: New file.
+ * config/sparc/tm-sp64.h (FRAME_CHAIN, FRAME_SAVED_PC): Deleted.
+ (PRINT_REGISTER_HOOK): Call new fn sparc_print_register_hook.
+
+Fri Jul 30 10:15:01 1993 Fred Fish (fnf@deneb.cygnus.com)
+
+ * Makefile.in (ALLCONFIG): Add config/i386/ptx.mh
+
+Fri Jul 30 08:58:01 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ From J. Law:
+ * infcmd.c (read_pc): Remove PA specific code.
+ * tm-hppa.h (TARGET_READ_PC): Define.
+ * hppa-tdep.c (target_read_pc): New function.
+
+ * symtab.c (gdb_mangle_name): Deal with it if type lacks a name.
+
+Fri Jul 30 07:36:53 1993 Fred Fish (fnf@deneb.cygnus.com)
+
+ * NEWS: Add note that DEC alpha support is host only, not native.
+ * README: Emphasize that C++ support works best with GNU C++ and
+ stabs debugging format.
+ * delta68-nat.c: Add missing FSF copyright.
+
+Fri Jul 30 08:58:01 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * paread.c (pa_symtab_read): Put file-local symbols in minimal symbols.
+ * hppa-tdep.c (frame_chain_valid): Check that our function has the
+ same address as _start, not that it must be the same symbol.
+
+Fri Jul 30 00:18:40 1993 Fred Fish (fnf@deneb.cygnus.com)
+
+ * Makefile.in (ALLDEPFILES): Add delta68-nat.c
+ * Makefile.in (delta68-nat.o): Add dependency.
+
+Thu Jul 29 12:09:46 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * value.h (COERCE_ENUM): Use COERCE_REF to coerce refs; value_ind
+ was adequate in gdb 3.5 but not now.
+
+ * valops.c (typecmp): An array in t2 matches a pointer in t1.
+
+ * valops.c (typecmp): When comparing type1& to type2, compare
+ type1 and type2 as leniently as if we were comparing type1 to
+ type2.
+
+ * cp-valprint.c (cplus_print_value): Don't dump core if the
+ baseclass doesn't have a name.
+ * values.c (vb_match): New function, which finds the virtual
+ base class pointer even if the types are nameless.
+ (baseclass_{addr,offset}): Use it.
+
+ * hppa-tdep.c: Make "maintenance print unwind" command from old
+ "unwind" command.
+
+ * remote-udi.c: Remove udi_timer, call to siginterrupt, and associated
+ obsolete junk which apparently had been copied from the
+ pre-serial.h remote.c, but which is no longer used.
+
+Thu Jul 29 12:36:20 1993 Fred Fish (fnf@deneb.cygnus.com)
+
+ * Makefile.in (NONSRC): Need 29k-share/README, not
+ 29k-share/udi/README.
+
+Thu Jul 29 12:09:46 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * paread.c (pa_symfile_init): If error reading string table, don't
+ use errno in cases where it hasn't been set.
+
+ * ser-unix.c (gdb_setpgid): Pass our pid, not 0, to setpgid.
+
+ * remote-monitor.c (_initialize_monitor): Comment out use of
+ connect_command, since connect_command itself is commented out.
+
+ * remote-monitor.c (generic_open): Parse arguments the same way
+ as remote.c.
+
+ * hppa-tdep.c (pc_in_linker_stub): Fix unclosed comments.
+
+Wed Jul 28 13:19:34 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * config/mips/xm-mips.h: Define HAVE_TERMIOS.
+
+ * dbxread.c (record_minimal_symbol): Don't put gcc_compiled or
+ __gnu_compiled* symbols into the minimal symbols.
+
+Wed Jul 28 08:26:58 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * remote-mips.c (_initialize_remote_mips): Added "timeout" and
+ "retransmit-timeout" variables to set mips_receive_wait and
+ mips_retransmit_wait, respectively.
+
+Wed Jul 28 03:58:58 1993 (pes@regent.e-technik.tu-muenchen.de)
+
+ * symmisc.c (dump_msymbols): Handle new mst_file_* types.
+
+Tue Jul 27 12:07:38 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * remote-udi.c: Remove old comment about download not implemented.
+
+ * serial.h, ser-{unix,go32,tcp}.c: Add flush_input and send_break.
+ * nindy-share/*, remote-nindy.c: Extensive hacking to make it
+ conform to GDB conventions like using memcpy not bcopy, serial.h,
+ etc. This is to make it host on Solaris, AIX, etc.
+ * Makefile.in: Reflect removed nindy-share files.
+ * config/i960/nindy960.mt (TDEPFILES): Remove ttybreak.o.
+
+ * stack.c (print_frame_info): Revise comment about `pathological'
+ case (there was a wrong FIXME about text labels; also asm() can
+ trigger this as well as versions of ar which truncate .o names).
+
+ * buildsym.c (start_subfile): If a .c file includes a .C file, set
+ the language of both of them to C++.
+
+ * config/sparc/xm-sun4os4.h: Define MEM_FNS_DECLARED and include
+ <memory.h>.
+ Include <malloc.h> rather than declaring malloc functions ourself.
+
+ * ser-unix.c (set_tty_state): Don't ignore errors setting process
+ group.
+ * inflow.c (terminal_inferior): If attach_flag set, ignore errors
+ from set_tty_state.
+
+ * fork-child.c (fork_inferior): Only quote exec file if needed.
+
+ * mipsread.c (parse_symbol): Remove 21 Jul 93 change with
+ stTypedef inside an stBlock.
+
+Tue Jul 27 12:36:49 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * breakpoint.c (breakpoint_1): Walk the breakpoint chain to decide if
+ we have breakpoints or watchpoints as we might have to ignore internal
+ breakpoints.
+
+ Fix gdb core dumps after `file newfile' commands.
+ * symtab.h, symfile.c (clear_symtab_users): New routine which
+ unconditionally clears symtab users. clear_symtab_users_once
+ commented out as it was a noop anyway.
+ * objfiles.c (free_objfile): Don't call clear_symtab_users_once.
+ * objfiles.c (free_all_objfiles), symfile.c (new_symfile_objfile),
+ xcoffexec.c (exec_close): Call clear_symtab_users if necessary.
+ * symfile.c (syms_from_objfile): Install cleanups for errors during
+ symbol reading.
+ * coffread.c, dbxread.c, mipsread.c, xcoffread.c (*_symfile_read):
+ Lint cleanup code, call do_cleanups explicitly.
+ * symfile.c (symbol_file_add): Call new_symfile_objfile and
+ reinit_frame_cache _after_ the new symbols are read in.
+
+Tue Jul 27 01:57:01 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * mipsread.c (parse_type): Do not set tag name for compiler
+ generated fake tag names.
+
+Mon Jul 26 17:31:49 1993 K. Richard Pixley (rich@rtl.cygnus.com)
+
+ * config/m88k/m88k.mt (TDEPFILES): add exec.o.
+
+Mon Jul 26 13:17:36 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * hppa-tdep.c: Remove all uses of use_unwind and `set use_unwind'
+ command. Now we use unwind info by default if we can find it.
+
+ * config/sparc: Move VARIABLES_INSIDE_BLOCK and SUN_FIXED_LBRAC_BUG
+ to tm-sparc.h so they are shared between Solaris and SunOS4.
+ * dbxread.c (process_one_symbol): Deal with SunOS4 acc N_STSYM and
+ N_GSYM functions.
+
+ * config/pa/tm-hppa.h (REGISTER_NAMES): Use "fr" rather than "fp"
+ for floating point registers.
+
+ * mipsread.c (parse_symbol): Put stStaticProc symbols in minimal
+ symbols as mst_file_text.
+
+ * hppa-tdep.c (pc_in_linker_stub): Return 0 if can't read memory.
+
+ * stabsread.c (rs6000_builtin_type): Make logical types be
+ TYPE_CODE_BOOL.
+
+Sun Jul 25 23:41:48 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * breakpoint.{c,h} (struct breakpoint): Replace symtab field with
+ source_file field.
+
+Fri Jul 23 09:57:25 1993 Jim Kingdon (kingdon@deneb.cygnus.com)
+
+ * remote.c: Don't error() on errors xferring memory.
+ * target.h: Clean up comments about *xfer_memory.
+
+ * exec.c, corelow.c (target_ops struct): Don't allow
+ {insert,remove}_breakpoints to be defaulted to
+ memory_{insert_remove}_breakpoint.
+
+ * demangle.c: Make it so `help set dem' tells you how to get the
+ list of demangling styles.
+
+Thu Jul 22 15:41:09 1993 Jim Kingdon (kingdon@deneb.cygnus.com)
+
+ * Makefile.in: Use REMOTE_O macro not remote.o.
+ * config/i960/{nindy960,vxworks960}: Don't use remote.o.
+
+Thu Jul 22 12:43:25 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * coredep.c: If NEED_SYS_CORE_H defined, include <sys/core.h>
+ (can't include it in nm-*.h file because it causes conflicts with
+ a.out symbol definitions).
+ * hp300ux-nat.c (fetch_core_registers): Commented out; obsolete.
+ * config/m68k/hp300hpux.mh (NATDEPFILES): Added coredep.o and
+ corelow.o.
+ * config/m68k/nm-hp300hpux.h (NEED_SYS_CORE_H): Defined.
+ (REGISTER_U_ADDR): Defined.
+ * config/m68k/xm-hp300hpux.h (HAVE_TERMIOS): Define instead of
+ HAVE_TERMIO.
+ * config/pa/xm-hppah.h: Likewise.
+
+Wed Jul 21 11:37:30 1993 Jim Kingdon (kingdon@deneb.cygnus.com)
+
+ * mipsread.c (parse_symbol): when stTypedef and friends occur within
+ an stBlock, skip over the fields of the inner one.
+
+ * mips-tdep.c (init_extra_frame_info): If in lenient prologue, call
+ heuristic_proc_desc rather than just assuming registers not saved.
+
+ * Makefile.in (regex.o): Add dependency.
+
+ * hppa{b,h}-nat.c: Warning, not error, if can't access registers.
+
+ * config/pa/hppa{b,h}.h: Define ATTACH_DETACH.
+
+Wed Jul 21 03:07:30 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * config/mips/xm-makeva.h: New file implements va_list alignment
+ restrictions for mips hosts.
+ * config/mips/{xm-irix3.h, xm-mips.h, xm-news-mips.h, xm-riscos.h}:
+ Use it.
+
+Wed Jul 21 00:11:05 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * mips-tdep.c (init_extra_frame_info): Do not check for
+ mips_in_lenient_prologue if it is a dummy frame.
+ * mipsread.c (fixup_sigtramp): Initialize pdr.adr, it is used by
+ mips_in_lenient_prologue.
+
+Tue Jul 20 14:14:59 1993 Jeff Law (law@snake.cs.utah.edu)
+
+ * hpread.c (read_hp_array_type): Handle "char foo[]".
+
+Tue Jul 20 12:53:47 1993 Jim Kingdon (kingdon@deneb.cygnus.com)
+
+ * mips-tdep.c (heuristic_proc_start): First time we print the
+ warning, elaborate.
+ (_initialize_mips_tdep): Improve docstring for `set heur'.
+
+ * config/rs6000/tm-rs6000.h: Remove call to insert_step_breakpoint.
+
+ * symtab.c (find_line_symtab): New function, to deal with multiple
+ symtabs with the same name.
+ (find_line_pc{,_range}): Use it.
+ (find_pc_symtab): Add comment about overlapping symtabs.
+
+Mon Jul 19 21:29:14 1993 Fred Fish (fnf@deneb.cygnus.com)
+
+ * Makefile.in (SFILES): Add nlmread.c.
+ * Makefile.in (OBS): Add nlmread.o.
+ * Makefile.in (nlmread.o): Add new target.
+ * configure.in (i[34]86-*-netware): New configuration.
+ * nlmread.c, config/i386/{i386nw.mt, tm-i386nw.h}: New files
+ for NLM/NetWare support.
+
+Mon Jul 19 11:48:57 1993 Jim Kingdon (kingdon@deneb.cygnus.com)
+
+ * symtab.h (enum minimal_symbol_type): Add mst_file_*.
+ * partial-stab.h [DBXREAD_ONLY]: Record statics in miminal symbols.
+ * dbxread.c (record_minimal_symbol): Deal with statics.
+ * minsyms.c (lookup_minimal_symbol): Prefer externals to statics.
+
+ * config/i386/xm-i386sco.h: Define HAVE_TERMIOS.
+
+ * printcmd.c, config/pa/xm-pa.h, config/alpha/xm-alpha.h: Make it so
+ arg_bytes field of makeva_list is always aligned.
+ * config/pa/xm-pa.h: Make arglist_address a char *.
+
+ * ser-unix.c: Don't try to use job control with termio.
+
+Sun Jul 18 23:11:28 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+ and Jim Kingdon (kingdon@cygnus.com)
+
+ Make breakpoint_re_set_one work with overloaded member functions,
+ `b 123' and `b foo' if foo is a static function.
+ * symtab.c (decode_line_1, decode_line_2): New argument `canonical'
+ to return canonical line specs if requested by the caller.
+ * breakpoint.c, source.c, symtab.c, symtab.h: Change prototypes and
+ callers accordingly.
+ * symtab.c (build_canonical_line_spec): New helper function which
+ constructs the canonical line spec.
+ * breakpoint.c (break_command_1): Use canonical line spec instead
+ of command string as addr_string if necessary.
+ * source.c (line_info): Fix storage leak.
+
+Sun Jul 18 15:22:45 1993 Jim Kingdon (kingdon@rtl.cygnus.com)
+
+ * infptrace.c: Split out define of PT_KILL; Sequent defines PT_KILL
+ but not the others.
+ * symm-tdep.c: Remove exec_file_command.
+ [_SEQUENT_] (ptx_coff_regno_to_gdb, register_addr): New functions.
+ A few miscellaneous cleanups.
+ * symm-nat.c: Renamed from symm-xdep.c.
+ * All symmetry dependent files: Many changes.
+
+ * mips-tdep.c (mips_skip_prologue): New argument lenient.
+ Use read_memory_nobpt.
+ (is_delayed, mips_in_lenient_prologue): New functions.
+ (init_extra_frame_info): If in the prologue, don't use saved registers.
+ * config/mips/tm-mips.h: Declare mips_skip_prologue.
+
+ * partial-stab.h (N_SO): Add the text offset to valu before, not after,
+ passing it to END_PSYMTAB.
+
+Fri Jul 16 18:48:52 1993 Jim Kingdon (kingdon@rtl.cygnus.com)
+
+ * symtab.c (find_pc_symtab): Call warning, not printf directly.
+
+ * solib.c (solib_add): Use x{re,m}alloc, not {re,m}alloc.
+
+Fri Jul 16 09:56:42 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * mipsread.c: No longer need to undefine ZMAGIC.
+
+Thu Jul 15 18:03:37 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * m88k-pinsn.c: Moved code into opcodes/m88k-dis.c.
+ (print_insn): Now just calls print_insn_m88k.
+
+Thu Jul 15 14:54:05 1993 Doug Evans (dje@canuck.cygnus.com)
+
+ * h8300-tdep.c (examine_prologue): Make prototype match definition.
+
+Thu Jul 15 08:34:49 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * NEWS: Mention that remote.c now has a `load' operation.
+
+ * hppa-tdep.c (pc_in_linker_stub): New function.
+ (find_proc_framesize): Return 0 for linker stubs.
+ (rp_saved): Tell the caller where rp is saved.
+ (frame_chain_valid): Return 1 for linker stubs.
+ (frame_saved_pc): Use return value from rp_saved.
+
+ * stack.c (print_frame_info): When checking PC_IN_CALL_DUMMY,
+ pass the sp relative to the frame in question, not the sp in the
+ innermost frame.
+
+Wed Jul 14 17:37:03 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * mipsread.c (parse_procedure): Take as argument the symtab to look
+ the name up in. Look it up with mylookup_symbol, not lookup_symbol.
+ (psymtab_to_symtab_1): For stabs, pass the symtab to parse_procedure.
+
+ * mipsread.c (mylookup_symbol): Use strcmp, not STREQ, as we have
+ already checked the first characters.
+
+ Changes from Jeffrey Law:
+ * printcmd.c (makeva_list): Use MAKEVA_EXTRA_INFO to define
+ machine dependent fields in the makeva_list structure.
+ (makeva_size): Allocate extra space to handle gaps made by
+ alignment restrictions.
+ * config/pa/xm-pa.h (MAKEVA_EXTRA_INFO): Define.
+ (MAKEVA_START): Initialize arglist_address field.
+ (MAKEVA_ARG): Always store arguments on natural alignment
+ boundaries. Set arglist_address to the address right after
+ the args.
+ (MAKEVA_END): Simply return the value stored in arglist_address.
+
+Wed Jul 14 13:51:54 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * ch-valprint.c (chill_val_print, case TYPE_CODE_STRING): Print
+ address, not addr.
+
+ * hppah-nat.c (store_inferior_registers): Don't print i in cases
+ where we aren't using it.
+
+ * a29k-tdep.c (get_saved_register): Fix typo.
+
+Wed Jul 14 09:45:52 1993 Doug Evans (dje@canuck.cygnus.com)
+
+ * configure.in: Recognize h8300h (variant of h8300).
+
+Wed Jul 14 09:45:52 1993 Doug Evans (dje@canuck.cygnus.com)
+
+ * configure.in: Recognize sparc64-*-*.
+
+Tue Jul 13 14:03:48 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabsread.c (define_symbol): Make the caddr_t hack apply to `function
+ returning foo' as well as `pointer to foo'.
+
+ * remote.c [REMOTE_BREAKPOINT]: Use for breakpoint insn if defined.
+ * config/m68k/tm-m68k.h: Define it.
+ * mem-break.c, breakpoint.c: Improve comments.
+
+Tue Jul 13 13:35:31 1993 Frederic Pierresteguy (F.Pierresteguy@frcl.bull.fr)
+
+ * config/m68k/tm-dpx2.h: Replace "tm-68k.h" with "m68k/tm-m68k.h".
+ * config/m68k/xm-dpx2.h: Define HAVE_TERMIOS not HAVE_TERMIO.
+
+Tue Jul 13 11:50:38 1993 Doug Evans (dje@canuck.cygnus.com)
+
+ * gdbcore.h (read_memory_integer, read_memory_unsigned_integer):
+ Make prototype match definition.
+
+Tue Jul 13 11:15:15 1993 Fred Fish (fnf@cygnus.com)
+
+ * elfread.c: Remove notice about file still being under
+ construction.
+ * Makefile.in (ultra3-xdep.o, umax-xdep.o): Add missing ')'.
+
+Mon Jul 12 17:46:35 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * a29k-tdep.c (read_register_stack): Make val static.
+
+Mon Jul 12 14:10:48 1993 Doug Evans (dje@canuck.cygnus.com)
+
+ * config/h8300/tm-h8300.h (REGISTER_CONVERTIBLE): Change value to 0.
+ (REGISTER_CONVERT_TO_VIRTUAL, REGISTER_CONVERT_TO_RAW): Move def'n to
+ usual spot.
+
+Mon Jul 12 11:29:44 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * c-valprint.c (c_val_print): Fix thinko with unspecified length
+ arrays.
+
+ * hppa-tdep.c (find_proc_framesize): If there is a frame pointer,
+ use it.
+
+Sun Jul 11 19:35:05 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * symtab.c (decode_line_1): Use end of block to figure out whether
+ val.end is in the same function, not minimal symbols.
+
+ * source.c (line_info): Add a few more wrap_here's.
+
+ * i386-tdep.c (i386_follow_jump): Do byteswapping where needed and
+ don't make assumptions about sizes of host data types.
+
+ * blockframe.c, symtab.h (find_pc_partial_function): New arg endaddr.
+ * infrun.c, breakpoint.c, printcmd.c: Change callers.
+ * printcmd.c (containing_function_bounds): Remove.
+ * printcmd.c (disassemble_command): Use find_pc_partial_function,
+ not containing_function_bounds.
+ * infcmd.c (step_1): Use find_pc_partial_function rather than
+ trying to roll our own. Move check for a pc between SIGTRAMP_START and
+ SIGTRAMP_END in find_pc_partial_function, not step_1.
+
+ * sparc-tdep.c (sparc_frame_chain, frame_saved_pc):
+ Keep unswapped value in array of char, not REGISTER_TYPE.
+ Use REGISTER_RAW_SIZE not sizeof (REGISTER_TYPE).
+ (sparc_extract_struct_value_address): Use TARGET_PTR_BIT not
+ sizeof (CORE_ADDR).
+
+Thu Jul 1 15:50:05 1993 Frederic Pierresteguy (F.Pierresteguy@frcl.bull.fr)
+
+ * configure.in (m68*-bull-sysv*): added support for Bull dpx2.
+ * config/m68k/{t,x,n}m-dpx2.h, dpx2-nat.c: New files.
+ * config/m68k/dpx2.m{h,t}: New files.
+
+Thu Jul 1 15:46:10 1993 Jeff Law (law@snake.cs.utah.edu)
+
+ * hpread.c: Run through gnu-indent.
+
+Sun Jul 11 12:32:08 1993 Doug Evans (dje@canuck.cygnus.com)
+
+ * config/sparc/tm-sparc.h (PRINT_REGISTER_HOOK): Fix typo, add
+ more parens around macro arg.
+
+Sat Jul 10 09:54:17 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * infrun.c: Remove step_resume_{duplicate,shadow}. Replace
+ step_resume_break_address with step_resume_breakpoint (now local
+ to wait_for_inferior).
+ ({insert,remove}_step_breakpoint): Remove.
+ (wait_for_inferior): Set step resume break with
+ set_momentary_breakpoint. Test hitting it with bpstat_stop_status
+ and bpstat_what (stop_step_resume_break removed).
+ * breakpoint.{h,c}, infrun.c: Return value from bpstat_what now struct
+ which includes previous return value as main_action, and a step_resume
+ bit.
+ * breakpoint.c (delete_breakpoint): If breakpoint was inserted, and
+ there is another breakpoint there, insert it.
+ * infrun.c (wait_for_inferior): Rearrange the spaghetti a bit. Use
+ a few more gotos.
+ Various: Clean up and add comments.
+
+ * infrun.c [TDESC]: Remove remaining tdesc code (see ChangeLog
+ for Wed Nov 13 16:45:13 1991).
+
+Fri Jul 9 12:36:46 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * values.c, value.h (modify_field), callers: Make fieldval a LONGEST.
+
+ * h8300-tdep.c (NEXT_PROLOGUE_INSN): Make pword1 an INSN_WORD *
+ not short *.
+
+ * findvar.c, defs.h
+ ({extract,store}_{signed_integer,unsigned_integer,address}):
+ New routines to replace SWAP_TARGET_AND_HOST.
+ All over: All uses of SWAP_TARGET_AND_HOST on integers replaced.
+
+ * config/sparc/tm-sparc.h: Add comment suggesting that removing
+ ins and locals from the registers array might clean things up.
+
+ * utils.c: Clean up comments about wrap buffer and wrap_here.
+ * printcmd.c (printf_command): Call wrap_here before vprintf.
+
+ * mipsread.c (cross_ref): Set the name to unknown for "struct *" case.
+ Patch from ptf@delcam.co.uk (Paul Flinders).
+
+ * a29k-tdep.c, findvar.c (get_saved_register): Fix byteswapping sins.
+
+Fri Jul 9 09:47:02 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * defs.h, remote-eb.c (TM_FILE_OVERRIDE): Remove it.
+ * mips-tdep.c (init_extra_frame_info): Set proper fci->frame if pc
+ is at the start of the dummy code.
+
+Thu Jul 8 14:48:54 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * sparc-tdep.c (sparc_push_dummy_frame): Skip all the do_save_insn
+ stuff, just write the sp and fp.
+ (sparc_pop_frame): Skip the do_restore_insn; we already restore
+ the sp with the other out registers.
+
+ * hppa-tdep.c (hppa_push_arguments): Allocate enough space for
+ arguments.
+
+ * hppa-tdep.c: Change _initialize_hppab_tdep to _initialize_hppa_tdep.
+
+Thu Jul 8 14:47:00 1993 Doug Evans (dje@canuck.cygnus.com)
+
+ * sparc-tdep.c (sparc_frame_chain): Handle sizeof (CORE_ADDR)
+ != sizeof (REGISTER_TYPE).
+ (frame_saved_pc): Ditto.
+
+Thu Jul 8 08:22:05 1993 Doug Evans (dje@canuck.cygnus.com)
+
+ * config/h8300/tm-h8300.h: (REGISTER_TYPES): Adjust for h8/300h.
+ (REGISTER_RAW_SIZE): Ditto.
+ (REGISTER_VIRTUAL_TYPE): Use builtin_type_unsigned_long for regs
+ on the h8/300h (ints may still be 16 bits).
+ (EXTRACT_RETURN_VALUE, STORE_RETURN_VALUE,
+ EXTRACT_STRUCT_VALUE_ADDRESS): Add FIXME's for h8/300h. Some
+ thought needed here.
+
+ * h8300-tdep.c (print_insn): Call print_insn_h8300h if h8/300h.
+ (examine_prologue): reg_save_depth is 4 if h8/300h.
+
+ * findvar.c (read_register): Provide some support for 64 bit regs.
+ (write_register): Ditto.
+
+Wed Jul 7 14:30:00 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * config/mips/nm-riscos.h: machine/machparam.h is always the right
+ place to look for BSD43_NBPG, not machine/vmparam.h
+
+ * infcmd.c (run_stack_dummy): New argument name.
+ Change error message in (another) attempt to make it comprehensible.
+ * valops.c (call_function_by_hand): Pass name to run_stack_dummy.
+ * symtab.h: Declare demangle and asm_demangle since macros use them.
+
+ * eval.c (evaluate_subexp): Add comment about calling a member
+ function of a variable in a register.
+
+ * expression.h: Clean up comment about string in STRUCT_STRUCT etc.
+
+ * config/{rs6000/tm-rs6000.h,sparc/tm-sparc.h,pyr/tm-pyr.h},
+ inferior.h (PC_IN_CALL_DUMMY) [ON_STACK]: Add comments about stack
+ frame tops and bottoms.
+
+ * frame.h, blockframe.c, stack.c, a29k-tdep.c,
+ config/gould/tmp-{pn,np1}.h,
+ config/{sparc/tm-sparc.h,pyr/tm-pyr.h,vax/tm-vax.h}: Remove field
+ next_frame from struct frame_info. It has no purpose beyond
+ ->next->frame and is an artifact from GDB 2.8.
+
+Tue Jul 6 11:51:18 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * Makefile.in: Remove gdb before creating a new one.
+ Update init.c atomically.
+
+ * Makefile.in (ALLPARAM): Add config/{alpha/xm-alpha.h,pa/xm-pa.h}.
+ (ALLCONFIG): Add config/alpha/alpha-osf1.mh.
+
+ * infcmd.c (_initialize_infcmd): In docstring for "continue",
+ describe argument as setting ignore count.
+
+Sun Jul 4 15:04:47 1993 Doug Evans (dje@cygnus.com)
+
+ * h8300-tdep.c (examine_prologue): Fix call to
+ read_memory_unsigned_integer.
+
+Fri Jul 2 18:22:54 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * config/mips/{x,n}m-irix{3,4}.h: Make some definitions here
+ rather than including xm-bigmips.h.
+
+ * eval.c (evaluate_subexp): Improve error messages for OP_TYPE and
+ default cases.
+
+ * Makefile.in (distclean): Remove y.tab.h.
+
+Fri Jul 2 14:55:48 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * exec.c (exec_file_command): Remove Mar 28 hack as BFD handles
+ file updates properly now.
+ * mipsread.c (mips_coff_new_init): Force reevaluation of sigtramp
+ addresses if switching to a new symbol file.
+ * dbxread.c (process_one_symbol): Avoid dereferencing NULL
+ symbols that might be returned from define_symbol.
+
+Fri Jul 2 13:33:12 1993 Steve Chamberlain (sac@phydeaux.cygnus.com)
+
+ New target macros for getting at the pc, sp and fp.
+ * infcmd.c (read_pc, write_pc): Modify to use new macros.
+ (read_sp, write_sp, read_fp, write_fp): New functions.
+ * blockframe.c (reinit_frame_cache, get_prev_frame_info):
+ Use new functions.
+ * breakpoint.c (bpstat_alloc): ditto.
+ * infrun.c (wait_for_inferior): ditto.
+ * stack.c (print_frame_info): ditto.
+ * valops (call_function_by_hand): ditto.
+ * corelow.c (core_open): ditto.
+ * h8500-tdep.c: (target_read_sp, target_write_sp, target_read_pc,
+ target_write_pc, target_read_fp, target_write_fp): New functions.
+ * inferior.h (read_sp, write_sp, read_fp, write_fp): Prototypes.
+
+ * config/alpha/xm-alpha.h: Add MAKEVA_END.
+ * config/h8500/tm-h8500.h: Define new macros.
+
+Fri Jul 2 13:51:04 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * configure.in (mipos-*-riscos*): New host and target; use riscos.
+ * config/mips/nm-riscos.h: If BSD43_NBPG is not defined by
+ vmparam.h, include machparam.h.
+ (KERNEL_U_ADDR): Define to be BSD43_UADDR.
+
+Fri Jul 2 13:39:48 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * c-exp.y (yylex): Give error if unmatched single quote.
+
+ * configure.in, config/m68k/*delta68*, delta68-nat.c: New port.
+
+ * Remove unused STACK_END_ADDR in the following files (in other
+ files it is used for something): tm-mips.h, tm-sun2.h, tm-news.h,
+ tm-a29k, tm-i386v.h, tm-hppa.h, tm-nindy960.h, tm-amix.h,
+ tm-hp300hpux.h, tm-isi.h.
+
+Thu Jul 1 09:51:27 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * config/mips/nm-riscos.h: Define NBPG and UPAGES.
+ config/mips/xm-riscos.h: Include <sys/types.h>.
+
+ * ser-unix.c (hardwire_noflush_set_tty_state): Use an assignment,
+ not an initializer, to copy the structure.
+
+ * gdbtypes.h (struct type): Add field tag_name.
+ * gdbtypes.c (type_name_no_tag), c-typeprint.c (c_type_print_base):
+ Use it.
+ * {coff,dwarf,mips,stabs}read.c: Set it.
+
+ * xm-sysv4.h: Undefine HAVE_TERMIO.
+
+ * config/mips/nm-riscos.h: Remove unmatched #endif.
+ Define FETCH_INFERIOR_REGISTERS.
+ * config/mips/riscos.mh: Don't include coredep.o; mips-nat.o is enough.
+ Fix misspelling of NAT_FILE.
+ * mips-nat.c (fetch_core_registers): If KERNEL_U_ADDR is not defined,
+ we can still process "modern" core files.
+
+ * ser-unix.c (hardwire_print_tty_state) [HAVE_TERMIOS]: Don't
+ print c_line.
+ (_initialize_ser_hardwire): Just check whether _POSIX_JOB_CONTROL
+ is defined; don't care what it is defined to.
+
+Wed Jun 30 20:06:46 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * config/vax/xm-vaxult2.h: Define FD_SET and FD_ZERO.
+
+Tue Jun 29 11:02:58 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * inftarg.c: Remove unused include of terminal.h.
+ * signals.h: Don't undefine signals anymore.
+ * main.c: Use job_control from serial.h.
+ * fork-child.c (fork_inferior): Use gdb_setpgid.
+ * serial.h, ser-unix.c, ser-go32.c: Provide gdb_setpgid.
+ * utils.c (quit): Use current_target->to_terminal_ours to figure
+ out whether we care about lack of job control, rather than __GO32__.
+ * utils.c: Include serial.h not terminal.h
+ (quit): Use job_control not TIOCGPGRP.
+ * terminal.h: Don't undefine TIOCGPGRP.
+ * serial.h, ser-unix.c, ser-go32.c, ser-tcp.c: Add SERIAL_FLUSH_OUTPUT.
+ * utils.c (quit): Use it.
+ * serial.h: Add SERIAL_UN_FDOPEN.
+ * utils.c (quit): Use it.
+ * ser-unix.c: Add process group to ttystate.
+ [HAVE_SGTTY]: Add tchars, ltchars, and lmode to ttystate.
+ * inflow.c: Include serial.h not terminal.h.
+ Use serial.h stuff to replace most of the maze of #ifdef's.
+ * inflow.c, main.c, inferior.h: make gdb_has_a_terminal a function.
+ * serial.h: Document SERIAL_SET_TTY_STATE as being immediate.
+ * ser-unix.c: Use TIOCSETN not TIOCSETP so it is true.
+ * serial.h, ser-unix.c, ser-go32.c, ser-tcp.c:
+ Add SERIAL_PRINT_TTY_STATE, SERIAL_NOFLUSH_SET_TTY_STATE, and
+ SERIAL_SET_PROCESS_GROUP.
+ * inflow.c: Use them.
+ * config/xm-svr4.h, config/rs6000/xm-rs6000.h, config/sparc/sun4os4.h:
+ Define HAVE_TERMIOS.
+ * Various: Remove all use of TIOC*_BROKEN.
+
+Wed Jun 30 12:20:51 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * config/m68k/tm-sun3.h (BELIEVE_PCC_PROMOTION_TYPE): Define.
+
+Tue Jun 29 13:44:41 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * target.h (target_detach): Turn macro into function.
+ * target.c (target_detach): Define it, do deferred register stores
+ before calling the real target function.
+
+Tue Jun 29 13:15:42 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+ and Jim Kingdon (kingdon@cygnus.com)
+
+ * symtab.h (BLOCK_SHOULD_SORT): Do not sort blocks corresponding to
+ a function to avoid printing of function arguments in wrong order
+ due to sorting.
+ * symfile.c (compare_symbols): Remove code for sorting arguments
+ as blocks containing arguments are no longer sorted.
+ * symtab.c (lookup_block_symbol): Update comment accordingly.
+
+Tue Jun 29 11:02:58 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * config/pa/tm-hppa.h: Remove unused ARGS_GROW_DOC.
+ (REG_STRUCT_HAS_ADDR): Add comment.
+
+ * infrun.c (wait_for_inferior): Use find_pc_line not find_pc_symtab
+ to check whether there is line number information.
+
+Tue Jun 29 08:29:17 1993 david d `zoo' zuhn (zoo at cirdan.cygnus.com)
+
+ * remote-udi.c: Fix docstring so that it compiles.
+
+ * remote-mips.c, remote-nindy.c: move bfd.h before symfile.h
+ (for file_ptr).
+
+Tue Jun 29 09:11:27 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * dbxread.c (process_one_symbol): If we find a LOC_BLOCK where we
+ don't expect it, change it to LOC_STATIC so at least we don't coredump.
+
+ * c-typeprint.c (c_type_print_base): Don't error() on invalid type.
+
+ * symtab.h: Add comments about line numbers.
+ * source.c (identify_source_line): Fix off by one bug with line.
+
+Mon Jun 28 19:00:21 1993 Jeff Law (law@snake.cs.utah.edu)
+
+ * hpread.c: Do not include libhppax. Instead include libhppa.h
+ and hpux-symtab.h. Misc indention fixes.
+ (find_unwind_entry): Add PARAM prototype.
+ (read_hpux_symtab): More fixes for names and sizes of structs,
+ unions, enums, typedefs, and tagdefs.
+ (read_hp_enum_type, read_hp_struct_type): Likewise.
+ (read_hp_set_type, read_hp_subrange_type): Likewise.
+ (hp_type_lookup, process_one_debug_symbol): Likewise.
+ (process_one_debug_symbol): Search forward from the K_FUNCTION for
+ the first K_BEGIN when setting the line number associated with a
+ function. Avoid unnecessary calls to savestring.
+ (hp_alloc_type): Initialize TYPE_CPLUS_SPECIFIC here. Remove
+ most cases where we set it elsewhere.
+ (hppa_sym_fns): Use "hppa" instead of hppax since hpread.c and
+ paread.c use the same BFD backend now. All references changed.
+ (hpux_symfile_init): Allocate space to hold the debugging section
+ contents on the symbol obstack.
+
+Mon Jun 28 10:09:08 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * printcmd.c (makeva*): New interface, for making a va_list.
+ (printf_command): Use it.
+ * config/m88k/xm-delta88.h: Remove VPRINTF define, not needed.
+ * config/pa/xm-pa.h: New file.
+ * config/pa/xm-hppa{b,h}.h: Include it.
+
+ * xcoffread.c: Remove obsolete NO_TYPEDEFS comment.
+
+Sun Jun 27 08:54:55 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * valprint.c (val_print_type_code_int): Fix off by one error with
+ eliminating leading zeroes for large little endian integers.
+
+Sun Jun 27 08:58:56 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * config/mips/riscos.mh (CC): Use -systype sysv.
+
+ * ser-unix.c: Move #include of <sys/time.h> to HAVE_SGTTY section.
+
+ * Makefile.in (ALLPARAM): Add config/mips/{x,n}-{news-mips,riscos}.h.
+
+Fri Jun 25 11:22:28 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * config/m68k/tm-m68k.h: Remove obsolete comment about duplicating
+ CALL_DUMMY between different 68k machines.
+
+Fri Jun 25 17:02:45 1993 Stu Grossman (grossman at cygnus.com)
+
+ * gdbserver/Makefile.in: Add dependancies on server.h.
+ * gdbserver/remote-gutils.c: Remove lots of unused functions and
+ variables.
+ * gdbserver/remote-inflow.c: Remove lots of unused variables and
+ #includes. Also, use PTRACE_* symbols instead of constants.
+ (mywait): Surround calls to wait() with enable/disable_async_io()
+ so that we can be interrupted from GDB while waiting for the
+ child. Also, handle child exit more gracefully.
+ * gdbserver/remote-server.c: Remove lots of unused variables.
+ Move all extern defs into server.h. Redo main loop so that
+ failure from getpkt() causes communications to be re-established.
+ Fix 'k' command so that it restarts the child.
+ * gdbserver/remote-utils.c: Remove lots of unloved vars and
+ subrs. Move many extern decls into server.h. (remote_open): For
+ tcp, seperate usage of proto fd from connected fd. Close proto
+ fd after getting connection. (putpkt/getpkt): Pay attention to
+ errors when reading/writing. Report these to the caller. New
+ routines input_interrupt/enable_async_io/disable_async_io to make
+ it possible to get an I/O interrupt when data arrives from the
+ comm link.
+ * serial.h: New file to contain common defs for all remote files.
+
+Fri Jun 25 17:02:45 1993 Stu Grossman (grossman at cygnus.com)
+
+ * remote.c: Add arg names to prototypes, in a modest effort at
+ clarification. Also add prototypes for some new functions.
+ * (remote_wait): Better error reporting for 'T' responses.
+ * ser-go32.c (strncasecmp): Make str1 & str2 be const.
+ * (dos_async_init): Make usage message reflect requested port #.
+ * ser-tcp.c (tcp_open): Terminate hostname properly to prevent
+ random hostname lookup failures. Add nicer message for unknown
+ host error. (wait_for): Wake up in case of exceptions. Also,
+ restart select() if we got EINTR.
+ * ser-unix.c (wait_for): Restart select() if we got EINTR.
+ * serial.c: (serial_close): Clean up code.
+
+Fri Jun 25 11:22:28 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * config/m68k/tm-m68k.h: Remove obsolete comment about duplicating
+ CALL_DUMMY between different 68k machines.
+
+Fri Jun 25 11:22:28 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * Makefile.in (*.tab.c): Use ./c-exp.tab.c not just c-exp.tab.c.
+ Make comment explaining this comprehensible.
+ (TAGFILES): Include ALLDEPFILES.
+ (ALLDEPFILES): udi2soc.c and udr.c are in 29k-share/udi, not
+ 29k-share/udi/udi.
+ (update-alldeps): Remove; obsolete.
+
+ * remote.c: Move comments regarding packets to top of file with the
+ rest of the protocol comments.
+ Fix incorrect description of 'T' response.
+
+ * README (Reporting Bugs): Refer people to the GDB manual.
+
+ * c-valprint.c (c_val_print): Handle TYPE_CODE_BOOLEAN.
+ * stabsread.c: Type -16 is 4 bytes.
+
+ * remote-udi.c: Improve docstring.
+
+Fri Jun 25 11:16:31 1993 Fred Fish (fnf@cygnus.com)
+
+ * elfread.c (elf_symfile_read): Call bfd_elf_find_section, not
+ bfd_elf32_find_section, to track bfd changes.
+
+Fri Jun 25 11:22:28 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * config/mips/riscos.mh (REGEX{,1}, MUNCH_DEFINE, MH_CFLAGS): Define.
+ * config/mips/xm-riscos.h: Define USG.
+
+Thu Jun 24 14:52:45 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * main.c (filename_completer): Don't complete to files ending in ~.
+
+ * NEWS: Mention filename completion and "info line" enhancements.
+
+ * main.c (symbol_completion_function): On "info t foo", return NULL,
+ don't error().
+
+ * main.c (symbol_completion_function): Don't use readline word
+ breaking. Use new calling convention for c->completer and
+ complete_on_cmdlist.
+ * command.h (struct command): Change arguments; now the text passed
+ to completer does not have any word breaking done. New arg word.
+ * symtab.{c,h} (make_symbol_completion_list): Do word breaking. Take
+ word argument.
+ * {main.c,gdbcmd.h} ({filename,noop}_completer): Take word argument.
+ * command.{c,h} (complete_on_cmdlist): Take word argument.
+
+ * command.c (lookup_cmd_1): Doc fix.
+
+Thu Jun 24 13:26:04 1993 K. Richard Pixley (rich@sendai.cygnus.com)
+
+ * Makefile.in (OP_INCLUDE): define.
+ (OPCODE_CFLAGS): use OP_INCLUDE.
+
+ * config/i386/ncr3000.mh, config/i386/i386v4.mh,
+ config/i386/i386sol2.mh, config/m68k/hp300hpux.mh,
+ config/m68k/amix.mh, config/mips/irix[34].mh,
+ config/m88k/delta88.mh, config/sparc/sun4sol2.mh (ALLOCA,
+ ALLOCA1): macros removed.
+
+ * config/mips/decstation.mh, config/rs6000/rs6000.mh
+ (MMALLOC_LIB): renamed to MMALLOC.
+
+Wed Jun 23 00:25:58 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * partial-stab.h: Consolidate case statements for N_LSYM and N_FUN.
+ * dbxread.c: Change comment regarding acc.
+
+Wed Jun 23 16:33:36 1993 Jeff Law (law@snake.cs.utah.edu)
+
+ * hpread.c: Document a few functions, misc cleanups. Update
+ copyright to reflect the first "release" of this file.
+ (struct hpux_symfile_info): Delete unneeded fields. Keep pointers
+ to the contents of the debug sections rather than offsets within
+ the file itself. Corresponding changes to the accessor macros.
+ (sl_symbol_size, slt_symbuf): Delete unneeded global variables.
+ (slt_symbuf_start, slt_symbuf_end, lntt_symbuf): Likewise.
+ (lntt_symbuf_start, lntt_symbuf_end, gntt_symbuf): Likewise.
+ (gntt_symbuf_start, gntt_symbuf_end): Likewise.
+ (fill_slt_symbuf, fill_lntt_symbuf): Delete unneeded functions.
+ (fill_gntt_symbuf): Likewise.
+ (get_lntt, get_gntt, get_slt): Simplify.
+ (hpux_symfile_init): Read and store the contents of the debugging
+ sections. Do error checking on memory allocation and BFD calls.
+ (read_hpux_symtab): Delete KERNELDEBUG crud. Ignore debug symbols
+ which are not needed for building partial symbol tables. Handle
+ K_CONST, K_TYPEDEF, and K_TAGDEF just like K_SVAR and K_DVAR.
+ (read_ofile_symtab): Delete useless processing_gcc_compilation stuff.
+ (read_hp_struct_type): Initialize TYPE_CPLUS_SPECIFIC.
+ (read_hp_set_type, read_hp_array_type): Likewise.
+ (read_hp_subrange_type, hp_type_lookup): Likewise.
+
+Wed Jun 23 15:04:54 1993 K. Richard Pixley (rich@sendai.cygnus.com)
+
+ Makefile overhaul dropping autodepend features.
+ * Makefile.in: many comment changes. forced consistent use of $()
+ for makefile variables references. dropped leading ./ in file
+ references. Drop $(srcdir)/ prefix on all dependencies.
+ Inserted contents of alldeps.mak and depend.
+ (INCLUDE_CFLAGS): defined as new macro for getting libiberty's
+ include directory into the compilation line.
+ (GDB_CFLAGS): new macro to take up the semantic previously held
+ by INCLUDE_CFLAGS.
+ (LIBIBERTY): dropped ancient subdir macro. I last removed this
+ macro in feb of '92. How does it keep coming back?
+ (MMALLOC_LIB): renamed to MMALLOC.
+ (BFD_SRC_DIR): renamed to BFD_SRC.
+ (BFD_OBJ_DIR): renamed to BFD_DIR.
+ (BFD_LIB): renamed to BFD.
+ (BFD_INCLUDES): renamed to BFD_CFLAGS.
+ (READLINE_DIR): now represents object directory.
+ (RL_LIB): renamed to READLINE.
+ (READLINE_SRC, READLINE_CFLAGS, OPCODES, OPCODES_CFLAGS): new
+ macros.
+ (INTERNAL_CFLAGS): added GDB_CFLAGS, OPCODES_CFLAGS,
+ READLINE_CFLAGS, BFD_CFLAGS. Dropped USER_CFLAGS.
+ (LDFLAGS): removed default assignment.
+ (TEXIDIR, INCLUDE_DEP, MMALLOC_DIR, MMALLOC_DEP, BFD_DEP,
+ READLINE_DEP, LIBIBERTY_DIR, TESTS, depend, STAGESTUFF): unused, so removed.
+ (ALLOCA1, ALLOCA): removed all references. alloca is now in
+ libiberty.
+ (VERSION): unilaterally and arbitrarily bumped to 4.9.3.
+ (SFILES, NONSRC, HFILES, ALLDEPFILES, ALLPARAM, ALLCONFIG):
+ removed all $(srcdir) prefixes.
+ (getopt_h, ieee-float_h, bfd_h, wait_h, dis-asm_h): new macros
+ for potential dependencies. commented out by default.
+ (readline_headers, udiheaders): convenient abbreviations.
+ (gdbcore_h, frame_h, symtab_h, gdbtypes_h, expression_h,
+ value_h, breakpoint_h, command_h, gdbcmd_h, defs_h, inferior_h):
+ new macros used for header file dependencies.
+ (install-info, clean-info): collapse into the info rule.
+ (install): now depends on all.
+ (install-only): new target for installing without depending on
+ all.
+ (uninstall): new target.
+ (config-check, config-check-hosts, config-check-targets): added
+ fixme comments.
+ (ch-exp.tab.c, m2-exp.tab.c): added artificial dependencies in
+ order to force parallel makes into keeping these rules separate.
+ * configure.in: omit cat'ing depend file onto generated Makefile.
+ * alldeps.mak, depend: removed.
+
+ * inferior.h: remove redundant include of symtab.h which is
+ included in value.h via breakpoint.h.
+
+ * alloca.c: removed. alloca is now in libiberty.
+
+ * config/m88k/delta88.mh, config/ns32k/merlin.mh (M_UNINSTALL):
+ new macro to undo what M_INSTALL does.
+
+Wed Jun 23 00:25:58 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * config/ns32k/{merlin.mh,xm-merlin.h}: Be consistent about name
+ of gdb-sh.
+
+ * dbxread.c (copy_pending): Change name and function of begi argument
+ to endi, since that is what the caller needs.
+
+ * Makefile.in (TAGFILES): Don't include YYFILES.
+
+ * Makefile.in (HFILES): Include monitor.h.
+
+ * Makefile.in: Include text that used to be in alldeps.mak.
+ Remove config/mips/{bigmips.mh,xm-bigmips} from it.
+ * Makefile.in, configure.in: Remove all traces of alldeps.mak.
+
+ * main.c (main): Print help message on stdout not stderr
+ per standards.texi.
+ New option --version per standards.texi.
+ In help message, show long options with "--" not "-".
+ Don't try to print help message or version until after we have
+ called initialize_all_files.
+
+Tue Jun 22 11:03:13 1993 Jeff Law (law@snake.cs.utah.edu)
+
+ * hpread.c: Delete useless #if 1 statements.
+ (hp_type_translate): Use T_LONG, T_UNS_LONG, and T_DOUBLE instead
+ of magic integers. Fix handling for T_UNS_INT. Abort if the type
+ passed in is not an "immediate" type.
+ (read_hp_enum_type): Properly compute the size of the type.
+ (read_hp_array_type): Likewise.
+ (hp_type_lookup): Prefix the names of structs, unions and enums
+ with "struct", "union", and "enum" as appropriate.
+
+Tue Jun 22 03:15:38 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * solib.c (solib_add_common_symbols): Don't call lookup_minimal_symbol.
+ (solib_add): Call special_symbol_handling once, not once per library.
+
+ * procfs.c (procfs_resume): Don't pass a SIGTSTP whose action
+ is SIG_DFL.
+
+ * procfs.c (procfs_resume): Skip the unnecessary PRSVADDR on all
+ systems, not just Solaris.
+
+ * stabsread.c: Include <ctype.h>.
+
+Mon Jun 21 16:09:46 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * fork-child.c (fork_inferior): Quote exec_file so it can contain
+ funky characters.
+
+Mon Jun 21 16:56:47 1993 Fred Fish (fnf@cygnus.com)
+
+ * Makefile.in (INCLUDE_CFLAGS): Add BFD_INCLUDES for now, since
+ bfd.h is included by target.h, which most of gdb includes.
+ * depend: Hand remove BFD_INCLUDES from ${CC} lines, now that
+ it's in INCLUDE_CFLAGS.
+
+Mon Jun 21 16:09:46 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * config/i386/*aix*, i386aix-nat.c: New files.
+ * configure.in: Use them.
+ * alldeps.mak: List them.
+ * coffread.c (decode_base_type): Deal with anonymous enum type.
+ * i387-tdep.c (print_387_status_word): Add comment re "top".
+ * i386-tdep.c [I386_AIX_TARGET] (i386_extract_return_value): New func.
+ * dbxread.c: Use SEEK_SET and SEEK_CUR, not L_*. Define them if and
+ only if not defined by a header file.
+ * mipsread.c: Don't define L_SET or L_INCR.
+
+Mon Jun 21 15:10:07 1993 Fred Fish (fnf@cygnus.com)
+
+ * Makefile.in (BFD_INCLUDES): Bfd.h is now back in bfd build dir.
+ * depend: Hand updated to match.
+
+Mon Jun 21 10:13:42 1993 Jeff Law (law@snake.cs.utah.edu)
+
+ * hpread.c: Include "demangle.h".
+ (process_one_debug_symbol): Set the SYMBOL_LANGUAGE and
+ SYMBOL_INIT_DEMANGLED_NAME for the current symbol. Adjust
+ SYMBOL_VALUE for local variables in the stack by the size of the
+ current function's stack (found in unwind descriptor). Keep
+ better track of the current unwind descriptor.
+
+Sun Jun 20 13:11:11 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * stabsread.c (read_struct_fields): Don't call read_cpp_abbrev on $_.
+ (read_cpp_abbrev): Don't complain specially for $_. Also return 0 if
+ we don't recognize the abbrev.
+
+Sun Jun 20 00:24:41 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * solib.c (solib_add_common_symbols): Add comment about performance.
+
+Fri Jun 18 12:37:36 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * config/mips/{{x,n}m-riscos.h,riscos.mh}: New files.
+ * configure.in (mips-*-sysv*): Use riscos for host, bigmips for target.
+
+ * config/mips/{{x,n}m-news-mips.h,news-mips.mh}: New files.
+ * config/mips/{bigmips.mh,xm-bigmips.h}: Remove.
+ * configure.in (mips-sony-*): Use news-mips for host.
+
+ * buildsym.h: Doc fix for processing_acc_compilation.
+
+Thu Jun 17 19:57:08 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * printcmd.c (print_formatted): Don't use tab in wrap_here arg.
+
+Thu Jun 17 17:29:30 1993 Jim Kingdon (kingdon@lisa.cygnus.com)
+
+ * Makefile.in (INTERNAL_CFLAGS): Include ../include as well as
+ ${srcdir}/../include.
+
+ * config/m88k/xm-delta88.h: Comment out unused defines which conflict
+ with system headers.
+ * printcmd.c (printf_command): Cast second arg to vprintf to PTR.
+ Use VPRINTF macro if defined.
+ * config/m88k/xm-delta88.h: Define VPRINTF. Include <sys/siginfo.h>.
+ Define TIOC{GETC,GLTC}_BROKEN.
+ * m88k-nat.c: Uncomment include of <sys/ptrace.h>.
+ * main.c: Rename initialize_{main,cmd_lists,history} to init_* to
+ make things easier on munch (apparently this matters on
+ the delta88 with svr3).
+
+Thu Jun 17 16:53:56 1993 david d `zoo' zuhn (zoo@cygnus.com)
+
+ * Makefile.in: canonicalize install.sh; for use within
+ this directory (and subdirs)
+
+Tue Jun 15 17:01:23 1993 david d `zoo' zuhn (zoo at cirdan.cygnus.com)
+
+ * Makefile.in: remove parentdir support; use INSTALL_XFORM
+
+Thu Jun 17 15:08:35 1993 Steve Chamberlain (sac@phydeaux.cygnus.com)
+
+ * configure.in (alpha-*-osf*), config/alpha/alpha-osf.mh: New
+ host.
+ * sh-tdep.c (frame_find_saved_regs): Use NUM_REGS rather than hard
+ wired (and wrong) constant.
+ * values.c (unpack_long): Add case to unpack when target object is
+ sizeof(int).
+ * config/sh/tm-sh.h (REGISTER_NAMES): Know about the news ones the
+ simulator defines.
+
+Wed Jun 16 16:08:18 1993 K. Richard Pixley (rich@sendai.cygnus.com)
+
+ * NEWS: tracking user visible changes starting with
+ vxworks-timeout.
+
+ * remote-vx.c (_initialize_vx): rename user settable option from
+ rpcTimeout to vxworks-timeout.
+
+Wed Jun 16 14:34:10 1993 Jeff Law (law@snake.cs.utah.edu)
+
+ * hpread.c (hp_type_translate): Fix promotion bugs from
+ char to short and short to int.
+
+Wed Jun 16 12:21:49 1993 Fred Fish (fnf@cygnus.com)
+
+ * Makefile.in (depend): More makefile diddling.
+ * alldeps.mak, depend: Update to latest automatically built
+ versions.
+
+ * Makefile.in (depend): Bfd.h keeps moving, keep up with it.
+ * alldeps.mak, depend: Update to latest automatically built
+ versions.
+
+Tue Jun 15 12:26:05 1993 K. Richard Pixley (rich@sendai.cygnus.com)
+
+ * remote-vx.c: include gdbcmd.h for setlist.
+ (_initialize_vx): make rpcTimeout user settable.
+
+Mon Jun 14 09:23:51 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * main.c, gdbcmd.h: Add function filename_completer.
+ * main.c, symfile.c, source.c, exec.c, core.c: Use it for
+ "directory", "source", "cd", "symbol-file" "add-symbol-file",
+ "load", "file", "exec-file", "core-file" commands.
+ (But '/' is a word break, limiting usefulness; see comments).
+
+ * source.c (mod_path): Warning not error if can't find directory.
+
+ * isi-xdep.c: New file.
+ * config/m68k/isi.mh (XDEPFILES): Add isi-xdep.o
+
+Sun Jun 13 09:17:48 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * config/m68k/xm-news.h: Include <sys/param.h>.
+
+ * m88k-tdep.c (IEEE_isNAN): Remove.
+ config/m88k/tm-m88k.h (INVALID_FLOAT): Return 0. This was the same
+ broken isNAN as on the mips.
+
+ * valprint.c (_initialize_valprint): Use c->function.sfunc not just
+ c->function.
+
+ * dbxread.c (process_one_symbol): If SUN_FIXED_LBRAC_BUG is not
+ defined, don't worry about Sun's silly LBRAC bug.
+ * config/m68k/tm-sun3.h: Define SUN_FIXED_LBRAC_BUG to 0.
+
+ * dbxread.c (process_one_symbol): If there's a symbol before an
+ N_SO, don't error().
+ (case N_BCOMM): complain () not error ().
+
+ * defs.h, main.c (catch_errors): Add return_mask arg.
+ stack.c (print_frame_info): Pass RETURN_MASK_ERROR.
+ other callers: Pass RETURN_MASK_ALL.
+ (return_to_top_level), callers: Add return_reason arg.
+ * utils.c (quit):
+ Use return_to_top_level (RETURN_QUIT) instead of error ().
+ * main.c (main), tm-nindy960.h (ADDITIONAL_OPTION_HANDLER):
+ Use SET_TOP_LEVEL not setjmp (to_top_level).
+ * remote-nindy.c: Use catch_errors not setjmp (to_top_level).
+
+Sat Jun 12 14:40:54 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * solib.c (solib_create_inferior_hook) [SVR4_SHARED_LIBS]:
+ Don't try to get the debug base yet.
+
+ * dbxread.c (process_one_symbol): Set n_opt_found based on whether
+ a non-gcc N_OPT symbol is found. Make SUN_FIXED_LBRAC_BUG a macro
+ which returns 0 or 1 to say whether to do it.
+ * config/sparc/sun4{sol2,os4}.h
+ (SUN_FIXED_LBRAC_BUG,VARIABLES_INSIDE_BLOCK): Use n_opt_found so
+ the right thing happens for both acc and SunOS4 /bin/cc.
+
+ * valprint.c (print_hex_chars): Use local_hex_format_{pre,suf}fix.
+ * printcmd.c (print_scalar_formatted): Use val_print_type_code_int.
+
+ * mips-tdep.c: Remove isa_NAN; it assumed sizeof(host int) == 4 and
+ probably contained byte-order sins too.
+ config/mips/tm-mips.h (INVALID_FLOAT): Define to 0 like most machines.
+ The IEEE_FLOAT code in print_floating takes care of it.
+
+Sat Jun 12 14:47:04 1993 Fred Fish (fnf@cygnus.com)
+
+ * Makefile.in (VERSION): Bump to 4.9.2.
+ * c-valprint.c (c_val_print): For array of chars printed with
+ string syntax, don't print the address of the array. From
+ bothner@cygnus.com.
+ * c-exp.y (yylex): Recognize '.' as indicating a floating point
+ number regardless of the radix. From wilson@cygnus.com.
+ * valprint.c (set_input_radix_1, set_output_radix_1): New
+ prototypes and functions that do the actual radix setting work.
+ * valprint.c (set_radix, set_output_radix, set_input_radix):
+ Rewrite to use set_input_radix_1 and set_output_radix_1.
+ * valprint.c (initialize_valprint): Enable commands to
+ independently set and show input and output radices.
+ * valprint.c (show_radix): New prototype and function that
+ handles separate input and output radices.
+
+Fri Jun 11 18:39:38 1993 Ken Raeburn (raeburn@cygnus.com)
+
+ Patches from Jeff Law, law@cs.utah.edu:
+ * hppa-pinsn.c: Now uses disassembler from opcode library,
+ this contains only the stub function print_insn.
+
+Fri Jun 11 15:19:59 1993 K. Richard Pixley (rich@cygnus.com)
+
+ * main.c (main): back to two periods for elipse.
+ (print_gdb_version): revised format for configuration info.
+
+Fri Jun 11 10:24:35 1993 Fred Fish (fnf@cygnus.com)
+
+ * defs.h (INT_MAX): Cast unsigned shift result to int.
+
+Fri Jun 11 10:17:41 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * dbxread.c (process_one_symbol): Rather than having
+ BLOCK_ADDRESS_FUNCTION_RELATIVE a macro, make it a variable which
+ is true if we are doing stabs-in-elf, false otherwise.
+ config/sparc/tm-sun4sol2.h: Don't define it.
+
+Fri Jun 11 13:33:40 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * remote-mips.c (mips_send_packet): Don't print garbage character
+ in debugging info.
+ (mips_request): Don't check that remote pid is 0, because
+ sometimes it isn't.
+ (mips_fetch_registers): Pass a pointer to SWAP_TARGET_AND_HOST,
+ not an integer.
+
+Fri Jun 11 10:17:41 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * stack.c (print_frame_info): Use catch_errors around print_frame_args.
+
+ * Makefile.in (install): Don't depend on gdb.
+
+ * Rename remote-es1800.c to remote-es.c
+ and remote-st2000.c to remote-st.c for 14-char filenames.
+ config/m68k/{es1800,st2000}: Use the new names.
+
+ * mips-tdep.c (isa_NAN): Don't return true on -0.
+
+Fri Jun 11 10:24:35 1993 Fred Fish (fnf@cygnus.com)
+
+ * defs.h (INT_MAX): Cast unsigned shift result to int.
+
+Thu Jun 10 13:26:41 1993 Fred Fish (fnf@cygnus.com)
+
+ * elfread.c (elf_symtab_read): Add bfd section address to bfd
+ symbols, now that they are section relative.
+ * solib.c (bfd_lookup_symbol): Ditto.
+
+Thu Jun 10 11:27:34 1993 Jeff Law (law@snake.cs.utah.edu)
+
+ * hpread.c (read_hp_function_type): Adjust SYMBOL_VALUE for
+ arguments in the stack by the size of the current function's stack
+ (found in the unwind descriptor).
+ (process_one_debug_symbol): Likewise. Keep track of the current
+ function's unwind descriptor.
+
+Thu Jun 10 10:56:56 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * Makefile.in (depend): Add bfd -I's for paread.c and xcoffexec.c
+ depend: Updated accordingly.
+
+Wed Jun 9 16:08:44 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * Makefile.in (*.tab.c): Use mv for atomic update.
+
+ * Makefile.in ({dist,real}clean): Also remove nm.h.
+ (realclean): Also remove ${TESTS}, y.output, yacc.{acts,tmp}.
+ (distclean): Don't rebuild *.tab.c or TAGS.
+
+Wed Jun 9 12:56:58 1993 K. Richard Pixley (rich@cygnus.com)
+
+ * Makefile.in (version.c): add host and target names to version.c.
+ * main.c (main): print three periods for the elipse.
+ (print_gdb_version): also print configuration.
+
+ * udi/udiids.h, udi/udip2soc.c, udi/udiphcfg.h, udi/udiphunix.h,
+ udi/udiproc.h, udi/udipt29k.h, udi/udiptcfg.h, udi/udisoc.h,
+ udi/udr.c: Change AMD copyrights to FSF copyleft '93.
+
+ * remote-eb.c (get_hex_regs, eb_fetch_registers), remote-adapt.c
+ (get_hex_regs, adapt_fetch_registers): cast args to
+ supply_register to avoid gcc warning.
+
+ * config/a29k/a29k.mt (TDEPFILES): drop minimon support. It
+ doesn't compile on solaris and is now obsolete.
+
+ * config/sparc/sun4os4.mh (XM_CLIBS): remove -lresolv. This
+ breaks stock sunos installations.
+
+Wed Jun 9 06:14:33 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * m68k-stub.c: Add comment about frame cache.
+
+ * target.h (target_store_registers): Doc fix re error handling.
+
+ * findvar.c (write_register): Call SWAP_TARGET_AND_HOST regardless
+ of register_valid[regno].
+
+Tue Jun 8 14:42:10 1993 Jim Kingdon (kingdon@rtl.cygnus.com)
+
+ * symtab.h, dwarfread.c: Doc fix re dependencies.
+
+Tue Jun 8 17:54:09 1993 Rob Savoye (rob@rtl.cygnus.com)
+
+ * serial.c (serial_close): If scb is NULL, don't try to close
+ it.
+ * configure.in: Add support for rom68k and bug boot monitors.
+
+Tue Jun 8 17:39:12 1993 Steve Chamberlain (sac@phydeaux.cygnus.com)
+
+ * coffread.c (init_stringtab): Fix bug where sizeof(long) != 4.
+ * gdbcore.h, core.c (read_memory_unsigned_integer): New function.
+ * findvar.c (read_register, write_register): Fix thinko where
+ sizeof(host long) != sizeof(target int).
+ * h8300-tdep.c: Use new read_memory_unsigned_integer call.
+ * sh-tdep.c (_initialize_sh_tdep): Add memory_size command.
+
+Tue Jun 8 14:42:10 1993 Jim Kingdon (kingdon@rtl.cygnus.com)
+
+ * Move config/m68k/tm-m68k.h (FRAME_FIND_SAVED_REGS) to
+ m68k-tdep.c (m68k_find_saved_regs). Don't duplicate code between
+ 68881 and non-68881 cases. Check for a pair of movel instructions.
+
+Tue Jun 8 14:52:55 1993 K. Richard Pixley (rich@sendai.cygnus.com)
+
+ First cut at sparc-vxworks targetting.
+ * config/sparc/tm-vxsparc.h, config/sparc/vxsparc.mt: new files.
+ * configure.in: sparc-vxworks gdb_target now vxsparc.
+
+ * remote-eb.c, remote.c: symfile.h requires bfd.h so include it.
+
+Tue Jun 8 14:42:10 1993 Jim Kingdon (kingdon@rtl.cygnus.com)
+
+ * config/m68k/xm-news.h: add "extern int errno".
+
+Tue Jun 8 13:45:07 1993 K. Richard Pixley (rich@sendai.cygnus.com)
+
+ * remove-vx.c (vx_read_register, vx_write_register): collapse
+ ifdef I80960 else (assumes) m68k into parameterizable macros
+ VX_NUM_REGS and VX_SIZE_FPREGS.
+ * config/m68k/tm-vx68.h, config/i960/tm-vx960.h (VX_NUM_REGS,
+ VX_SIZE_FPREGS): new definitions.
+
+Tue Jun 8 11:08:29 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * symfile.{c,h} (generic_load): New function.
+ remote{,-nindy,-eb,-mips}.c: Use it.
+
+Mon Jun 7 20:07:30 1993 Stu Grossman (grossman@cygnus.com)
+
+ * Makefile.in (depend): More sed gubbish to deal with
+ ../bfd/bfd.h being generated during the build.
+ * depend: Re-done with corrected makefile.
+
+Mon Jun 7 16:32:05 1993 Fred Fish (fnf@cygnus.com)
+
+ * Makefile.in (BFD_SRC_DIR): Renamed def and usages from BFD_DIR.
+ * Makefile.in (BFD_OBJ_DIR): New definition for the bfd build
+ directory to find automatically generated header files and library.
+ * Makefile.in (BFD_LIB): Use BFD_OBJ_DIR.
+ * Makefile.in (LINTFLAGS): Include BFD_OBJ_DIR.
+ * Makefile.in (saber_gdb): Include BFD_OBJ_DIR.
+ * Makefile.in (depend): Include BFD_OBJ_DIR in gcc args.
+ * Makefile.in (paread.o, xcoffexec.o): Remove, now in depend.
+ * depend, alldeps.mak: Rebuild after Makefile.in changes.
+
+Fri Jun 4 10:18:51 1993 david d `zoo' zuhn (zoo at cirdan.cygnus.com)
+
+ * configure.in: change lynx support to CPU-*-lynxos*
+
+ * Makefile.in (subdir_do): change test from existence of directory
+ to existence of Makefile (the directory may exist but not be configured)
+
+Thu Jun 3 01:18:51 1993 david d `zoo' zuhn (zoo at cirdan.cygnus.com)
+
+ * config/sparc/xm-sun4sol2.h: define MEM_FNS_DECLARED
+
+Fri Jun 4 10:43:33 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * configure.in (mips-idt-ecoffl*): New target; use idtl.
+ (mips-idt-ecoff*): Added trailing '*'.
+ * config/mips/idtl.mt: New file; like idt.mt, but little endian.
+
+Thu Jun 3 17:36:56 1993 Stu Grossman (grossman@cygnus.com)
+
+ * ser-go32.c: Clean up lots of compilation nits.
+
+Thu Jun 3 14:44:57 1993 Stu Grossman (grossman@cygnus.com)
+
+ * Patches from Jeffrey Law <law@cs.utah.edu>.
+ * hppab-nat.c: Eliminate unnecessary ifdefs for
+ FETCH_INFERIOR_REGISTERS, CANNOT_FETCH_REGISTER, and
+ CANNOT_STORE_REGISTER.
+ (fetch_register): Delete code to handle CANNOT_FETCH_REGISTER.
+ * hppa-pinsn.c: Support 'I', 'J', and 'K' in output
+ templates for 1.1 FP computational instructions.
+
+Thu Jun 3 03:34:49 1993 Stu Grossman (grossman@cygnus.com)
+
+ * Makefile.in: Remove ser-tcp.[co]. (Use XDEPFILES instead.)
+ * alldeps.mak, depend: Rebuild to account for ser-tcp.
+ * config/sparc/sun4os4.mh: Add ser-tcp to XDEPFILES.
+ * gdbserver/Makefile.in (gdbserver): Use -lbsd.
+ * gdbserver/remote-inflow{-sparc}.c (create_inferior): Don't use a
+ shell when running the child, as args have been expanded by the
+ time we get here. Simplify calling convention.
+ * gdbserver/remote-server.c (main): Use new calling convention
+ for create_inferior, remove defunct code for coalescing argv.
+ Remove extra calls to mywait(), as we no longer have to wade
+ through a shell.
+
+ * target.c (target_read_memory_partial): Don't deref errnoptr
+ when checking for null pointer.
+
+Wed Jun 2 19:58:46 1993 John Gilmore (gnu@cygnus.com)
+
+ * remote-es1800.c: Fix typo.
+
+Tue Jun 1 21:22:39 1993 Fred Fish (fnf@cygnus.com)
+
+ * target.c (target_read_memory_partial): Like target_read_memory,
+ but does partial reads, such as reads that bump into the end of
+ the address space.
+ * target.h (target_read_memory_partial): Add prototype.
+ * valprint.c (PRINT_MAX_DEFAULT): New define, initial value 200.
+ * valprint.c (val_print_string): Complete rewrite to fix bug with
+ bumping into end of memory, avoiding unnecessarily long reads, and
+ fixing bug when print_max is set to 0 (unlimited print length).
+ * valprint.c (_initialize_valprint): Use PRINT_MAX_DEFAULT to
+ initialize print_max.
+
+Tue Jun 1 18:11:35 1993 Rob Savoye (rob at darkstar.cygnus.com)
+
+ * configure.in: Add support for rom68k and bug boot monitors.
+
+Mon May 31 10:37:04 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * printcmd.c (print_scalar_formatted): Print integers bigger than
+ LONGEST in hex no matter how big, and no matter what the format
+ and size.
+
+ * stabsread.c (read_type): Skip type attributes if present.
+
+ * stabsread.c (read_huge_number): Don't accept '0' + radix as part
+ of number, just through '0' + radix - 1.
+
+Sun May 30 15:35:21 1993 Fred Fish (fnf@cygnus.com)
+
+ * Makefile.in (SER_HARDWIRE): Temporarily comment out ser-tcp.o.
+
+ * {dbxread.c, dwarfread.c} (read_ofile_symtab): Rewrite to take
+ single parameter, the pointer to the partial symtab, rather than
+ a bunch of args that are derived from the partial symtab. Change
+ prototypes and callers to match.
+
+ * dbxread.c (read_ofile_symtab): Remove "#if 1" around code to
+ set demangling style automatically.
+ * defs.h (CPLUS_MARKER): Clarify comment that this is only for
+ GNU C++, not C++ in general.
+ * symtab.h (general_symbol_info): Simplify by eliminating one
+ structure level for the language dependent info.
+
+Sat May 29 15:59:29 1993 Fred Fish (fnf@cygnus.com)
+
+ * c-typeprint.c (c_type_print_base): Avoid dereferencing NULL
+ names for TYPE_CODE_STRUCT and TYPE_CODE_UNION types.
+ TYPE_CODE_ENUM was already testing for this.
+
+Fri May 28 17:18:05 1993 Stu Grossman (grossman@cygnus.com)
+
+ * Makefile.in: Add new file ser-tcp.c.
+ * defs.h (memcmp): Add decl for memcmp to #ifndef MEM_FNS_DECLARED.
+ * findvar.c (write_register): See if we are writing back the same
+ value that's already in the register. If so, don't bother.
+ * remote.c (putpkt, getpkt): Improve handling of communication
+ problems.
+ * ser-go32.c: Prototype it to death. Update serial_ops and add
+ dummy routines where appropriate.
+ * ser-tcp.c: New module to implement serial I/O via TCP
+ connections.
+ * ser-unix.c: Clean up getting/setting of tty state. Get rid of
+ SERIAL_RESTORE, add SERIAL_{GET|SET}_TTY_STATE interfaces.
+ * serial.c: Add start of support for connect command.
+ (serial_open): Distinguish between tcp and local devices.
+ * serial.h (struct serial_ops): Get rid of restore, add
+ get_tty_state and set_tty_state. Define protoypes and macros for
+ this mess.
+ * gdbserver/remote-utils.c: Add tcp support. (readchar): Do
+ some real buffering. Handle error conditions gracefully.
+ * gdbserver/remote-inflow-sparc.c: Update to remote-inflow.c
+ (Lynx), remove lots of cruft.
+
+Fri May 28 17:24:51 1993 david d `zoo' zuhn (zoo at cirdan.cygnus.com)
+
+ * printcmd.c (print_address_symbolic): turn this into an assigment
+ instead of an initialization (many compilers don't accept
+ structure initialization).
+
+Thu May 27 16:56:25 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * xcoffread.c (read_xcoff_symtab): If several program csects in one
+ source file, give them all the name of the source file, rather than
+ the 2nd and subsequent ones having NULL names.
+
+Thu May 27 06:16:56 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * printcmd.c (print_address_symbolic): Append source filename and
+ linenumber of the symbol if print symbol-filename is on.
+ (initialize_printcmd): `set print symbol-filename'.
+
+Wed May 26 13:46:16 1993 Stu Grossman (grossman@cygnus.com)
+
+ * configure.in: Add config for Lynx target. Configure gdbserver
+ only for Lynx. Re-do selective configuration of sparclite.
+
+ * gdbserver/{remote-gutils.c remote-server.c Makefile.in
+ configure.in remote-inflow.c remote-utils.c}: New files to
+ support GDB remote server. Currently only works for Lynx.
+
+Wed May 26 10:28:14 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabsread.c (define_symbol, case 't'): Only set the name if it
+ is not a pointer type.
+
+ * stabsread.c (define_symbol): Clean up logic; move the read_type
+ calls to inside the switch statement (this improves the error
+ handling).
+
+ * mipsread.c (parse_symbol, parse_partial_symbols): Deal with Fortran
+ common blocks.
+
+Tue May 25 20:44:24 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * printcmd.c (print_formatted, case 'i'): Pass a tab to wrap_here.
+
+ * source.c (line_info): Change "pc" to "address" in messages and
+ use print_address for addresses.
+
+ * source.c (line_info): If we don't find a symtab, print more useful
+ output, including the symbolic address.
+
+ * source.c (line_info): If --fullname, display the source.
+ (identify_source_line), callers: Take pc as argument, rather than
+ assuming innermost frame (emacs doesn't use this, so no one ever
+ noticed).
+ * symtab.h: Declare frame_file_full_name.
+ * main.c: Don't.
+
+Tue May 25 15:30:43 1993 Brendan Kehoe (brendan@lisa.cygnus.com)
+
+ * breakpoint.c (catch_command_1): Fix typo in error msg.
+
+Tue May 25 16:05:55 1993 Ken Raeburn (raeburn@cambridge.cygnus.com)
+
+ * elfread.c (elf_symfile_read): Update ELF structure and routine
+ names to specify 32-bit versions.
+ (elf_symtab_read): Retrieve size field directly from symbol,
+ instead of using old kludge.
+
+ * mips-pinsn.c (print_insn): Cast address to bfd_vma before
+ calling opcodes library.
+ * z8k-tdep.c (print_insn): Likewise.
+
+Tue May 25 13:06:28 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabsread.c: Remove all uses of error(). Make error_type and
+ read_type_number static.
+ (define_symbol): Don't try to deal with a missing symbol
+ descriptor which isn't followed by digit, '(', or '-'.
+ * stabsread.h: Don't declare read_type_number here.
+ * gdbtypes.h: Don't declare error_type here.
+ * xcoffread.c: Remove NO_TYPEDEFS code.
+
+Tue May 25 09:33:16 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * mips-tdep.c: Removed #include of many header files, and #define
+ of MIPSMAGIC; no longer used.
+
+Tue May 25 09:36:13 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * Many places: replace "the inferior" in messages with "the program"
+ or "the program being debugged".
+ * inflow.c (try_writing_regs): Remove; it's been #if 0'd forever
+ and I'm getting sick of maintaining it.
+
+ * config/i386/linux.mh: Don't use \ newline; the awk scripts don't
+ support it.
+
+ * config/i386/go32.mh: Define SER_HARDWIRE.
+ * Makefile.in: Define SER_HARDWIRE.
+ (DEPFILES): Use it.
+ (alldeps.mak): Add SER_HARDWIRE.
+ Remove all references to ser-hardwire.{c,o}.
+ * configure.in: Remove all ser_hardwire and gdb_serial_driver stuff.
+
+Mon May 24 23:50:05 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * sparc-nat.c (store_inferior_registers): Fill in all members of
+ inferior_fp_registers by reading them from the inferior before
+ modifying and writing them back.
+ Fixes unexplainable inferior FP exceptions after calls to the inferior
+ or setting of floating point registers.
+ * mips-tdep.c (mips_skip_prologue): Skip move of argument register
+ to register which is generated by gcc-2.4.
+
+Tue May 25 00:42:39 1993 Ken Raeburn (raeburn@cygnus.com)
+
+ * hppa-pinsn.c: Define OLD_TABLE before including opcode/hppa.h.
+
+Mon May 24 13:55:14 1993 Stu Grossman (grossman@cygnus.com)
+
+ * config/i386/{i386lynx.mh i386lynx.mt nm-i386lynx.h tm-i386lynx.h
+ xm-i386lynx.h}: New configuration for Lynx.
+
+Mon May 24 10:01:10 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * mipsread.c (parse_symbol): Deal with scVar and scVarRegister.
+ * symtab.h: Comment that LOC_REGPARM_ADDR can be call by reference.
+
+ * c-typeprint.c (c_type_print_base): Don't print typedef'd names
+ as struct, union, or enum tags.
+
+Mon May 24 01:10:01 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * symmisc.c (dump_msymbols): Avoid gdb coredump with stripped
+ executable.
+
+Sat May 22 10:03:09 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * infrun.c (wait_for_inferior),
+ infcmd.c (program_info, signal_command): Use symbolic signal names.
+
+ * inftarg.c (child_wait): Deal with EINTR and include message from
+ strerror if printing an error message.
+
+ * main.c (command_line_input): Use STOP_SIGNAL not SIGTSTP.
+
+ * stabsread.c: Remove most uses of lookup_fundamental_type.
+ (define_symbol): Use read_type for type of enum constant,
+ not just read_type_number. Also don't call error().
+ (define_symbol): For unrecognized constant type, one complaint (the
+ one from error_type) is enough. Don't make our own in addition.
+ (define_symbol): Don't treat an N_FUN 'R' as a prototype.
+ * gdbtypes.h: Doc fixes.
+
+Sat May 22 03:33:07 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ Fix stack unwinding through _sigtramp on Irix. These patches are from
+ Paul Flinders <ptf@delcam.co.uk>.
+ * mipsread.c (fixup_sigtramp): Find _sigtramp on Irix even when the
+ executable uses sigvec.
+ * mips-tdep.c (read_next_frame_reg): Allow tm-file to override
+ sigcontext offsets.
+ * config/mips/tm-irix3.h: Add sigcontext offsets for Irix.
+
+Sat May 22 00:39:01 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * infrun.c (wait_for_inferior): Clear stop_signal if it should not
+ be passed to the inferior to make "handle <signal> nopass nostop" work.
+
+Sat May 22 00:21:41 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * config/mips/tm-irix3.h: Clean up, use tm-bigmips.h and redefine
+ the necessary bits.
+ * findvar.c (value_from_register): Fix uninitialized first_addr
+ which caused problems with assignment of doubles to register variables
+ on some targets.
+ * mipsread.c: Remove TM_FILE_OVERRIDE, include tm.h and provide the
+ missing mips definitions if necessary.
+
+ Fix handling of double register variables for mips targets and big
+ endian hosts. These patches are from Paul Flinders <ptf@delcam.co.uk>.
+ * config/mips/tm-mips.h: Increase MAX_REGISTER_{RAW,VIRTUAL}_SIZE to
+ 8 bytes for doubles.
+ * config/mips/tm-mips.h (REGISTER_CONVERT_TO_TYPE): New macro for
+ conversion of type held in multiple registers to host format.
+ * config/mips/tm-mips.h (REGISTER_CONVERT_FROM_TYPE): New macro,
+ companion to REGISTER_CONVERT_TO_TYPE.
+ * config/mips/tm-mips.h (EXTRACT_RETURN_VALUE, STORE_RETURN_VALUE):
+ Convert to function calls.
+ * config/mips/tm-mips.h (FIX_CALL_DUMMY): New code for big endian
+ mips targets.
+ * mips-tdep.c (mips_print_register): Raw buffer now needs just
+ MAX_REGISTER_RAW_SIZE bytes.
+ * mips-tdep.c (mips_print_register): Use REGISTER_CONVERT_TO_TYPE
+ (if defined) for doubles.
+ * mips-tdep.c: (mips_extract_return_value, mips_store_return_value):
+ New functions, take care of REGISTER_CONVERT_TO/FROM_TYPE.
+ * valops.c (value_assign): Use REGISTER_CONVERT_TO_TYPE if
+ defined.
+ * findvar.c (value_from_register): Use REGISTER_CONVERT_TO_TYPE if
+ defined.
+
+Fri May 21 09:04:25 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * configure.in: Add i[34]86-*-isc*.
+
+ * stabsread.c: Make sure all complain() pass the address of the struct.
+
+ * xcoffread.c: Make sure all struct complaints are static not auto.
+
+ * Makefile.in: Add rule for xcoffexec.o like that for paread.o.
+
+ * xcoffread.c (process_xcoff_symbol, case C_LSYM): Use define_symbol.
+
+Wed May 19 12:33:59 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * config/i386/linux.mh: Re-enable coredumps now that they should work.
+
+Wed May 19 15:44:20 1993 K. Richard Pixley (rich@cygnus.com)
+
+ * config/m68k/tm-m68k.h (FRAME_CHAIN): add missing close paren.
+
+Wed May 19 15:33:57 1993 Stu Grossman (grossman@cygnus.com)
+
+ * config/pa/nm-hppab.h: Comment PTRACE_ARG3_TYPE.
+
+Wed May 19 12:33:59 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * Makefile.in (INSTALLED_LIBS): New variable.
+
+Tue May 18 14:08:50 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * main.c (quit_command): In the "quit anyway?" message, tell the user
+ whether we are planning to detach or kill the program.
+
+ * config/vax/vaxbsd.mh: Add "NAT_FILE= nm-vax.h".
+ * config/vax/xm-vaxbsd.h: Use <sys/param.h> not <machine/limits.h>
+
+ * infcmd.c (read_pc): Doc fix.
+
+ * printcmd.c (print_address_symbolic): Use %u not %d for offset.
+
+ * blockframe.c (get_prev_frame_info): If pc in sigtramp, set
+ signal_handler_caller.
+ * tm-68k.h (FRAME_{CHAIN,SAVED_PC}): Deal with sigtramp.
+ * tm-hp300bsd.h: Define SIGTRAMP_{START,END} not IN_SIGTRAMP.
+ * inferior.h (IN_SIGTRAMP): Definition moved from infrun.c.
+ Use SIGTRAMP_START if defined.
+ * infcmd.c (step_1): Use SIGTRAMP_{START,END} if needed.
+ * infrun.c (wait_for_inferior): Check IN_SIGTRAMP before SKIP_PROLOGUE.
+
+ * infptrace.c: Remove unused KERNEL_U_ADDR_HPUX code.
+
+ * infcmd.c (step_1): Fix poorly worded error message.
+
+ * config/{i386/linux.mh,m68k/isi.mh} (NATDEPFILES):
+ Comment out corelow.c because core dumps are broken on these machines.
+
+ * Makefile.in (depend): Put "${srcdir}" in generated dependencies
+ if srcdir is not ".".
+ Also put in -I${BFD_DIR} or -I${READLINE_DIR} for files which need it.
+ (INCLUDE_CFLAGS): Remove BFD_DIR and READLINE_DIR.
+ * depend: Update to latest automatically built version.
+
+Tue May 18 08:10:45 1993 Fred Fish (fnf@cygnus.com)
+
+ * ChangeLog, ChangeLog-92: Split ChangeLog at 1993.
+ * Makefile.in (NONSRC): Add ChangeLog-92
+
+Tue May 18 08:03:37 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * findvar.c ({read,write}_register): Use REGISTER_RAW_SIZE
+ not typo RAW_REGISTER_SIZE.
+
+ * frame.h, inferior.h: Doc fixes.
+
+Mon May 17 15:43:03 1993 Stu Grossman (grossman@cygnus.com)
+
+ * findvar.c (write_register): Add sanity check for register size.
+ (read_register): Fixup sanity check for register size to be
+ consistent with write_register().
+
+Mon May 17 07:36:20 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * sparclite/Makefile.in: Add dummy info, install and install-info
+ targets.
+
+Thu May 13 07:30:22 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * remote-nindy.c: Removed declaration of coffstrip.
+ * nindy-share/nindy.c: #if 0 coffstrip routine; no longer used.
+
+Wed May 12 00:35:19 1993 Fred Fish (fnf@cygnus.com)
+
+ * Makefile.in (VERSION): Bump to 4.9.1 after release and cvs
+ tagging.
+
+ * Makefile.in (VERSION): GDB 4.9 release.
+
+Tue May 11 08:04:41 1993 Fred Fish (fnf@cygnus.com)
+
+ * README: Update known bugs to include the Solaris bug that
+ leaves core dumps in the current directory when restarting the
+ inferior with "run". Expand on the testsuite information.
+
+ * Makefile.in (VERSION): Bump to 4.8.96 for what should hopefully
+ be the last 4.9 prerelease test archive.
+
+Mon May 10 22:13:23 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * config/m68k/xm-hp300bsd.h: Include <sys/param.h> to avoid INT_MAX
+ redefined warnings.
+
+Mon May 10 20:00:43 1993 Fred Fish (fnf@cygnus.com)
+
+ * README, NEWS: Update for gdb 4.9 release.
+
+Mon May 10 19:38:34 1993 John Gilmore (gnu@cygnus.com)
+
+ * ch-exp.y (MAX, MIN): Rename to MAX_TOKEN, MIN_TOKEN.
+ * target.c (MIN): #undef before defining.
+
+Mon May 10 16:03:03 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ Patch from Jeffrey Law:
+ * gdb/config/pa/nm-hppab.h (PTRACE_ARG3_TYPE): Define as caddr_t.
+
+Mon May 10 15:28:27 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * hppa-tdep.c (hppa_push_arguments): Allocate correct amount of
+ memory.
+
+Mon May 10 13:14:46 1993 Fred Fish (fnf@cygnus.com)
+
+ * ch-exp.y (start): Apply work-around to avoid bison warning.
+
+Sun May 9 07:25:02 1993 Fred Fish (fnf@cygnus.com)
+
+ * Makefile.in (BISON): Remove double quotes around BISON
+ definition when bison is used.
+
+ * configure.in (hppa*-hp-bsd): Change to hppa*-hp-bsd*
+ * configure.in (hppa*-hp-hpux): Change to hppa*-hp-hpux*
+ * configure.in (m68*-hp-bsd): Change to m68*-hp-bsd*
+ * configure.in (m68*-hp-hpux): Change to m68*-hp-hpux*
+ * configure.in (hppa*-*-bsd): Change to hppa*-*-bsd*
+ * configure.in (hppa*-*-hpux): Change to hppa*-*-hpux*
+ * configure.in (m68*-hp-bsd): Change to m68*-hp-bsd*
+ * configure.in (m68*-hp-hpux): Change to m68*-hp-hpux*
+
+ * Makefile.in (VERSION): Bump to 4.8.6.
+
+Sat May 8 12:36:03 1993 Fred Fish (fnf@cygnus.com)
+
+ * config/pa/xm-hppah.h (MALLOC_INCOMPATIBLE): Define it, and
+ include declarations for malloc/realloc/free. Both malloc and
+ realloc return 'void *' for non-ANSI compilations.
+
+Sat May 8 01:39:30 1993 (pes@regent.e-technik.tu-muenchen.de)
+
+ * coffread.c (read_coff_symtab): Don't fclose stream as it is no
+ longer opened twice.
+
+Thu May 6 21:08:55 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * solib.c (clear_solib): Don't close bfd if it is NULL.
+
+Thu May 6 20:55:35 1993 Fred Fish (fnf@cygnus.com)
+
+ * core.c (dis_asm_read_memory): Cast second arg of
+ target_read_memory to "char *".
+ * breakpoint.c (watchpoint_check): Change arg type from PTR to
+ "char *", to match other functions called by catch_errors().
+
+Thu May 6 15:47:45 1993 Stu Grossman (grossman@cygnus.com)
+
+ * More patches from Jeffrey Law (law@cs.utah.edu).
+ * gdb/config/nm-hppab.h (PTRACE_ARG3_TYPE): Define as caddr_t.
+ * gdb/config/pa/tm-hppah.h (millicode_start, millicode_end):
+ Delete unnecessary declarations.
+
+Thu May 6 15:15:46 1993 Stu Grossman (grossman@cygnus.com)
+
+ * ser-unix.c (wait_for): Use VTIME to do timeouts instead of
+ poll() for termio{s}.
+
+Thu May 6 10:03:41 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * i386-tdep.c (i386_frame_num_args): Always return -1.
+
+Wed May 5 15:16:33 1993 Stu Grossman (grossman@cygnus.com)
+
+ * Patches from Jeffrey Law <law@cs.utah.edu>.
+ * gdb/hppa-tdep.c: Declare frame_saved_pc.
+ (frameless_function_invocation): New function.
+ (frame_saved_pc, init_extra_frame_info): Use
+ frameless_function_invocation.
+ * gdb/config/pa/tm-hppa.h (SAVED_PC_AFTER_CALL): Use saved_pc_after
+ call instead of just grabbing the value currently in %r2.
+ (FRAMELESS_FUNCTION_INVOCATION): Use frameless_function_invocation.
+ * gdb/config/pa/tm-hppah.h (SAVED_PC_AFTER_CALL): Delete private
+ definition and use the common one in tm-hppa.h.
+ * gdb/hppa-tdep.c (frame_chain_valid): If "use_unwind" is true, then
+ use unwind descriptors to determine if the frame chain is valid.
+ * gdb/hppa-tdep.c (find_dummy_frame_regs): Rework so that
+ it does not assume %r4 is the frame pointer.
+ * gdb/hppa-pinsn.c (print_insn): Handle 'r' and 'R' for break, rsm,
+ and ssm instructions.
+ * gdb/hppa-tdep.c (extract_5r_store, extract_5R_store): New
+ helper functions for print_insn.
+ * gdb/hppa-tdep.c (gcc_p, hpux_cc_p): Delete unused functions.
+ * gdb/config/pa/tm-hppa.h (ABOUT_TO_RETURN): Handle a return
+ which nullifies the following instruction.
+
+Tue May 4 12:11:38 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * infptrace.c [FIVE_ARG_PTRACE]: Define ptrace to call_ptrace and
+ pass the 5th arg there, rather than using an ANSI C-specific macro.
+
+ * Makefile.in (depend): Don't include ${CC} command for *.tab.c.
+
+Tue May 4 19:33:12 1993 Fred Fish (fnf@cygnus.com)
+
+ * Makefile.in (VERSION): Bump to 4.8.5
+ * Makefile.in (INCLUDE_CFLAGS): Add BFD_DIR and READLINE_DIR
+ directories to include search path.
+ * Makefile.in (CLIBS, CDEPS, ADD_FILES, ADD_DEPS): Clean up
+ whitespace.
+ * Makefile.in (depend): For gcc -MM line, use INTERNAL_CFLAGS
+ * Makefile.in (main.o, dbxread.o, coffread.o, mipsread.o,
+ elfread.o, dwarfread.o, stabsread.o, xcoffread.o, xcoffexec.o,
+ xdr_ld.o, xdr_rdb.o, nindy.o, Onindy.o, ttybreak.o, ttyflush.o,
+ udr.o, udip2soc.o): Remove explicit rules, use the ones that
+ are automatically generated in "depend".
+ * Makefile.in (paread.o): Document why a dependency doesn't get
+ automatically generated in "depend" and leave this explicit rule
+ in for now (FIXME).
+ * depend: Update to latest automatically generated version.
+
+Tue May 4 12:11:38 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * xcoffread.c: Doc fix.
+
+ * Makefile.in (depend): Include $(CC) command in generated output.
+
+Mon May 3 22:51:05 1993 Fred Fish (fnf@cygnus.com)
+
+ * Makefile.in (NONSRC): Remove ${srcdir}/putenv.c.
+ * Makefile.in (SFILES): Add ${srcdir}/putenv.c.
+ * depend: Update to latest automatically built version.
+
+Mon May 3 19:20:20 1993 Stu Grossman (grossman@cygnus.com)
+
+ * sparclite/Makefile.in: Create default target that does nothing
+ in order to force user to build by hand.
+
+ * sparclite/Makefile: Remove. It's not necessary anymore.
+
+ * ser-unix.c (wait_for): New routine to handle read timeouts,
+ etc. Uses poll() if HAVE_TERMIO[S] is defined, select() otherwise.
+
+Mon May 3 13:52:08 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * mips-pinsn.c (print_insn): Return value.
+
+Sun May 2 11:43:57 1993 Fred Fish (fnf@cygnus.com)
+
+ * Makefile.in (SFILES): Remove ser-hardwire.c; it is a link made
+ at configuration time and doesn't belong in the distribution archive.
+
+ * Makefile.in (NONSRC): Add 29k-share/README.
+ * Makefile.in (HFILES): Add 29k-share/udi/udiids.h.
+
+ * defs.h (UINT_MAX, LONG_MAX, INT_MAX, INT_MIN): Replace hex
+ constants with slightly more portable definitions (still depends
+ on 2's complement arithmetic though).
+ * config/i386/nm-linux.h: Define NO_SYS_REG_H for no <sys/reg.h>.
+ * i386v-nat.c (sys/reg.h): Conditionalize include on
+ NO_SYS_REG_H. Linux doesn't have <sys/reg.h>.
+ * ser-unix.c (termio.h): Include <termio.h> like other files that
+ include termio.h, not <sys/termio.h> which may not exist (on
+ linux for example).
+
+Sat May 1 16:05:24 1993 Fred Fish (fnf@cygnus.com)
+
+ * valprint.c (print_longest): Change format parameter from a
+ 'char' to an 'int'. We can't have 'char' parameters with the
+ current coding style, where we mix prototypes with pre-ANSI
+ style declarations.
+ * value.h (print_longest): Change format parameter in prototype
+ from a 'char' to an 'int'.
+
+Sat May 1 02:47:20 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * config/mips/tm-mips.h (STAB_REG_TO_REGNUM): Match it with the gcc
+ definition.
+ * config/mips/tm-irix3.h (STAB_REG_TO_REGNUM): Add.
+ * irix4-nat.c (fill_fpregset): Fix bug with indexing into fpregsetp.
+
+Fri Apr 30 17:45:32 1993 Stu Grossman (grossman@cygnus.com)
+
+ * The following patches are from Jeffrey Law <law@cs.utah.edu>.
+ * config/pa/hppabsd.mh: Add more files to NATDEPFILES.
+ * config/pa/xm-hppa[bh].h: Define FIVE_ARG_PTRACE.
+ * hppab-nat.c: Delete WANT_NATIVE_TARGET ifdefs.
+ ptrace needs 5 arguments, #define ptrace to always
+ pass zero as the 5th argument.
+
+Fri Apr 30 15:54:13 1993 Steve Chamberlain (sac@thepub.cygnus.com)
+
+ * configure.in: Match z8k-*-sim for z8000.
+ * config/h8500/tm-h8500.h, h8500-tdep.c: Lint.
+ * remote-hms.c: Update to use new serial protocol.
+
+Fri Apr 30 16:50:38 1993 K. Richard Pixley (rich@rtl.cygnus.com)
+
+ * mips-tdep.c: remove include of sys/dir.h. Doesn't seem
+ necessary and Solaris doesn't have it.
+
+ * Makefile.in (clean-info, install, install-info, info, dvi,
+ check, all): do not echo recursion lines.
+
+ * 29k-share/udip2soc.c (UDIConnect): replace union wait with int.
+
+ * config/sparc/sun4sol2.mh (XM_CLIBS): add -lsocket which is
+ required target ports which use sockets (like a29k-udi).
+
+ * remote-udi.c (udi_wait): Use SIGURG, as Solaris doesn't have SIGLOST.
+
+Fri Apr 30 11:05:42 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * ser-unix.c [USE_{TERMIO,ALARM}_TIMEOUT]: New code to deal with
+ systems lacking select().
+
+ * Makefile.in (TAGS): Doc fix. Deal with empty DEPFILES.
+
+Fri Apr 30 10:06:46 1993 Fred Fish (fnf@cygnus.com)
+
+ * alldeps.mak, depend: Update with latest automatically built
+ versions.
+
+Thu Apr 29 12:03:23 1993 Fred Fish (fnf@cygnus.com)
+
+ * Makefile.in (SFILES): Add ser-unix.c and ser-go32.c.
+
+ * Makefile.in (make-proto-testsuite.dir): New target to make
+ prototype testsuite tree.
+
+ * Makefile.in (VERSION): Bump to 4.8.4.
+
+Thu Apr 29 08:46:22 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * stabsread.c (define_symbol): If unrecognized constant type,
+ complain() not error().
+
+Thu Apr 29 00:03:59 1993 Fred Fish (fnf@cygnus.com)
+
+ * infptrace.c: Add missing close paren to test for
+ FIVE_ARG_PTRACE defined.
+
+ * defs.h (CC_HAS_LONG_LONG): Set up to define CC_HAS_LONG_LONG
+ when compiling with gcc, but disable it for now. See comment.
+ * defs.h (LONGEST): Define as either "long" or "long long"
+ based on CC_HAS_LONG_LONG.
+ * defs.h (longest_to_int): Use CC_HAS_LONG_LONG to control
+ how longest_to_int is defined.
+ * c-valprint.c (c_val_print): Call print_longest.
+ * expprint.c (dump_expression): Use PRINTF_HAS_LONG_LONG
+ instead of LONG_LONG.
+ * {printcmd.c, gdbtypes.h} (LONG_LONG): Replace usages with
+ CC_HAS_LONG_LONG.
+ * printcmd.c (print_scalar_formatted): Call print_longest
+ and let it figure out what to do for PRINTF_HAS_LONG_LONG.
+ * typeprint.c (print_type_scalar): Call print_longest and let
+ it figure out what to do for PRINTF_HAS_LONG_LONG.
+ * valprint.c (val_print_type_code_int): Call print_longest
+ and let it figure out what to do for PRINTF_HAS_LONG_LONG.
+ * stabsread.c (LONG_LONG): Replace usages with CC_HAS_LONG_LONG.
+ * value.h (struct value): Replace usage of LONG_LONG with
+ CC_HAS_LONG_LONG.
+ * value.h (print_longest): Add prototype.
+ * values.c (LONG_LONG): Replace usages with CC_HAS_LONG_LONG.
+ * values.c (unpack_double): Collapse code that was unnecessarily
+ dependent on CC_HAS_LONG_LONG. Use LONGEST instead of direct types.
+ * values.c (value_from_longest): Remove dependency on
+ CC_HAS_LONG_LONG and just use LONGEST.
+ * solib.c (solib_map_sections): Use bfd_get_filename
+ to access filename field.
+ * solib.c (clear_solib): Save filename and free it later, after
+ bfd_close, since bfd_close may reference it. Use bfd_get_filename
+ to access the field.
+ * config/convex/xm-convex.h (LONG_LONG): Replace with
+ CC_HAS_LONG_LONG. Add define for PRINTF_HAS_LONG_LONG.
+ * doc/gdbint.texinfo (LONG_LONG): Replace with CC_HAS_LONG_LONG.
+ Add PRINTF_HAS_LONG_LONG references.
+
+Wed Apr 28 06:11:38 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * inflow.c (kill_command), infcmd.c (attach_command),
+ remote.c (remote_interrupt_twice): In messages for the user, call it
+ "the program" or "the program being debugged" not "the inferior".
+
+ * hp300ux-nat.c: Cast second arg to supply_register calls.
+ (_initialize_kernel_u_addr, getpagesize): New functions.
+ (store_inferior_register_1): Change arg name from value to val.
+ (fetch_core_registers): Make arg core_reg_size unsigned.
+ Pass 5 args to ptrace.
+ * config/m68k/xm-hp300hpux.h: Define FIVE_ARG_PTRACE.
+ Remove KERNEL_U_ADDR stuff.
+ * infptrace.c [FIVE_ARG_PTRACE]: Pass 5th arg to ptrace.
+ * config/m68k/hp300hpux.m{t,h}:
+ Move exec.o from NATDEPFILES to TDEPFILES
+ * config/m68k/hp300hpux.mt: Mention GAS requirement. Remove
+ hp-include stuff. Add m68k-tdep.o to TDEPFILES.
+
+Wed Apr 28 13:27:54 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * ch-exp.y (yylex): Don't STREQ with simplename if it is NULL.
+
+Wed Apr 28 06:11:38 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * config/sparc/xm-sun4os4.h [__STDC__]: Don't use MALLOC_INCOMPATIBLE.
+
+Wed Apr 28 11:39:18 1993 Roland H. Pesch (pesch@fowanton.cygnus.com)
+
+ * doc/gdb.texinfo: make node "Shell Commands" unconditional;
+ describe `set demangle-style arm' (not cfront);
+ mention can type `q' to discard output, when gdb pages
+
+Wed Apr 28 11:32:39 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * valops.c (search_struct_field): Fix gdb core dump with incomplete
+ stabs info.
+
+Wed Apr 28 06:11:38 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * remote.c: Change timeout to 2.
+ (remote_open): Use unpush_target not remote_close.
+ (remote_resume): If siggnal != 0, give warning not error().
+ (remote_wait, remote_interrupt, remote_interrupt_twice):
+ If we get two interrupts, let the user get out if they want.
+ (remote_{kill,mourn}): New functions.
+ i386-stub.c (handle_exception, case 'k'): Don't BREAKPOINT.
+
+Wed Apr 28 09:20:55 1993 Ian Lance Taylor (ian@rtl.cygnus.com)
+
+ * config/sparc/sun4sol2.mh (XM_CLIBS): Define to be -lnsl.
+
+Wed Apr 28 06:11:38 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * Remote targets (mourn): Call unpush_target.
+
+ * config/sparc/xm-sun4os4.h: Declare free() to return int.
+ Remove twisted use of PARAMS.
+
+ * config/rs6000/xm-rs6000.h: Don't define MALLOC_INCOMPATIBLE now
+ that ansidecl.h assumes ANSI on AIX.
+
+Tue Apr 27 10:01:33 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * README: Move most stuff about hacking GDB to doc/gdbint.texinfo.
+ (Known bugs): Remove AIX bugs, revise SPARC struct bug description.
+
+Tue Apr 27 13:44:19 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * expprint.c (print_subexp): Fix bug with OP_SCOPE operator output.
+
+Tue Apr 27 10:01:33 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * remote-vx.c (net_connect): Allow numeric IP address for host.
+
+Mon Apr 26 17:59:38 1993 Steve Chamberlain (sac@thepub.cygnus.com)
+
+ * config/sh/sh.mt, config/sh/tm-sh.h, sh-tdep.c: New files.
+
+Mon Apr 26 07:13:32 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * rs6000-tdep.c (branch_dest): Deal with stepping through system call.
+
+ * symtab.h, xcoffread.c: Revise linetable sorting comments.
+
+Sun Apr 25 02:32:16 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * valops.c (value_cast): A cast might also change the object
+ representation in C++.
+ * dbxread.c (end_psymtab): Copy subpst read_symtab function from pst
+ to get the proper read_symtab function when called from mipsread.c.
+ * mipsread.c (mipscoff_psymtab_to_symtab, psymtab_to_symtab_1):
+ Set cur_bfd in psymtab_to_symtab_1 as CURBFD(pst) is invalid
+ for dummy psymtabs, inhibit processing of dummy psymtabs.
+
+Sat Apr 24 19:59:54 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * Changes from (or inspired by) AMD:
+ * remote-udi.c (udi_attach): Assignments to Space and Offset were
+ switched, fix it.
+ (udi_wait): Make error message (UDIGetStdout) match error.
+ (udi_wait): Handle UDIStdinNeeded.
+ * command.c [CANT_FORK]: Use system().
+ * utils.c (prompt_for_continue): Allow quit with 'q'.
+
+ * solib.c (solib_add): Don't call special_symbol_handling if there
+ were errors in symbol_add_stub. Also set so->from_tty before
+ calling symbol_add_stub.
+
+Fri Apr 23 16:17:00 1993 Stu Grossman (grossman@cygnus.com)
+
+ * Merge in HPPA/BSD patches from Utah:
+ * defs.h: Add const to 2nd arg of psignal prototype.
+ * hppah-tdep.c: Renamed to hppa-tdep.c 'cuz it's common code with
+ BSD now.
+ * hppab-core.c: Deleted. No longer useful.
+ * hppab-nat.c: #include more files. Use PT_WUREGS, not
+ PT_WRITE_U.
+ * hppab-tdep.c: Deleted. Supplanted by hppa-tdep.c.
+ * config/pa/hppabsd.mh (NATDEPFILES): Remove hppab-core.o.
+ * config/pa/hppabsd.mt (TDEPFILES): hppab-tdep.o => hppa-tdep.o
+ * config/pa/hppahpux.mt (TDEPFILES): hppab-tdep.o => hppa-tdep.o
+ * config/pa/xm-hppab.h: #define SET_STACK_LIMIT_HUGE.
+
+Fri Apr 23 10:34:02 1993 Stu Grossman (grossman@cygnus.com)
+
+ * Fix two bugs found by deja-gnu. One is the incorrect reporting
+ of the PC being in a stack dummy when looking at a core file
+ without symbols. The other is the incorrect passing of char
+ arguments during expression evaluation (ie: p foo('a','b') would
+ mess up the passing of it's args because it wasn't coercing the
+ char's to ints).
+ * hppah-tdep.c: Rename global functions to have consistent hppa_
+ prefix. Make more functions static. Drop hp_ prefix from static
+ functions. (hppa_push_arguments): Call value_arg_coerce to cast
+ char to int args if necessary. (hppa_fix_call_dummy): Create
+ this routine from FIX_CALL_DUMMY macro in tm-hppa.h.
+ * inferior.h (PC_IN_CALL_DUMMY): Check for frame_address being
+ valid (ie: != 0) before doing comparison against PC.
+ * valops.c (call_function_by_hand): Adjust call to FIX_CALL_DUMMY
+ to reflect new arguments.
+ * config/pa/tm-hppa.h (POP_FRAME, PUSH_ARGUMENTS): Use new hppa_
+ prefix for func name. (FIX_CALL_DUMMY): Move code into
+ hppah-tdep.c.
+
+ * testsuite/gdb.t16/gdbme.c, testsuite/gdb.t17/gdbme.c: Add calls
+ to malloc() so that we can test GDB eval of dynamically created
+ arrays (like char strings in `print "foo"').
+
+Fri Apr 23 01:28:14 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * printcmd.c (print_address_symbolic): Search symtabs as well as the
+ minimal symbols for a nearby symbol.
+
+Thu Apr 22 19:44:21 1993 John Gilmore (gnu@cacophony.cygnus.com)
+
+ * coffread.c: Comment changes around minimal symbol recording.
+
+Thu Apr 22 16:24:36 1993 K. Richard Pixley (rich@rtl.cygnus.com)
+
+ * command.c: comment changes only.
+
+ * mips-tdep.c (heuristic_fence_post): new static variable.
+ (heuristic_proc_start): use heuristic_fence_post, print better
+ warnings, but only if not stop_soon_quietly.
+ (_initialize_mips_tdep): add_set_cmd for heuristic-fence-post.
+
+Thu Apr 22 14:50:05 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * symtab.h: Fix LOC_REF_ARG comment.
+
+Wed Apr 22 20:21:30 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+ and Jim Kingdon (kingdon@cygnus.com)
+
+ * stabsread.c (define_symbol): Combine a 'p', 'r' arg pair to a
+ LOC_REGPARM symbol.
+ * config/sparc/tm-sparc.h (REG_STRUCT_HAS_ADDR): Revise comments.
+ symfile.c (compare_symbols): Don't check first character; STRCMP
+ does that.
+
+ * stabsread.c (define_symbol): Generate a LOC_REGPARM_ADDR for
+ structures that are passed by address in a register.
+ * symtab.h (enum address_class): Add LOC_REGPARM_ADDR.
+ * findvar.c (read_var_value),
+ printcmd.c (address_info, print_frame_args),
+ stack.c (print_frame_arg_vars), symmisc.c (print_{,partial_}symbol),
+ * symtab.c (lookup_block_symbol): Deal with it.
+
+Thu Apr 22 09:07:24 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * objfiles.h (obj_section), objfiles.c (build_objfile_section_table):
+ Add objfile field.
+ * objfiles.c (find_pc_section): Return a struct obj_section *.
+ * sparc-tdep.c (in_solib_trampoline): Deal with find_pc_section return.
+ * symfile.c (syms_from_objfile) [IBM6000_TARGET]:
+ Don't use obj_section hack.
+ * xcoffexec (vmap_symtab): Relocate obj_sections.
+ * printcmd.c (containing_function_bounds): Use find_pc_section.
+
+ * symtab.h: Clean up SYMBOL_VALUE comments.
+
+Wed Apr 21 14:29:57 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * stack.c (print_frame_arg_vars), printcmd.c (print_frame_args):
+ Expand comments about LOC_ARG/LOC_LOCAL pairs.
+
+ * coffread.c (read_coff_symtab): Use rewind before fseek.
+
+Wed Apr 21 14:24:19 1993 Per Bothner (bothner@cygnus.com)
+
+ * ch-exp.y: Removed unused structure_primitive_value and FIXME_23.
+ * Makefile.in: Add $(YFLAGS) when using $(YACC).
+ * Makefile.in: Remove message to expect conflicts and unused
+ rules in ch-exp.y, since there no longer are any such.
+
+Wed Apr 21 13:27:50 1993 david d `zoo' zuhn (zoo at cirdan.cygnus.com)
+
+ * stabs.texinfo: fixed bad xrefs (un-initialized statics)
+
+Tue Apr 20 08:55:11 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * xcoffexec.c (xcoff_relocate_core): If no exec file, error()
+ rather than dumping core.
+
+ * Makefile.in: Add ${srcdir}/ to all source files.
+ (alldeps.mak): Add "${srcdir}/" to files when generating alldeps.mak.
+ (TAGS): Deal with srcdir and new config directory scheme.
+ createtags: Remove.
+ Makefile.in (NONSRC): Remove createtags.
+ alldeps.mak: Updated.
+
+ * rs6000-tdep.c: Delete unused function print_frame.
+
+ * frame.h (struct frame_info): Doc fix for next_frame.
+ New field signal_handler_caller.
+ blockframe.c (create_new_frame, get_prev_frame_info),
+ config/rs6000/tm-rs6000.h (INIT_EXTRA_FRAME_INFO): Set it (needs
+ INIT_FRAME_PC_FIRST).
+ stack.c (print_frame_info), rs6000-tdep.c (rs6000_frame_chain):
+ Check it.
+
+Mon Apr 19 22:52:33 1993 Stu Grossman (grossman@cygnus.com)
+
+ * irix4-nat.c (fetch_core_registers): Special version of this for
+ Irix 4.x, which stores regs a bit differently from other /proc
+ based systems.
+ * procfs.c, core-svr4.c: Move fetch_core_registers from procfs.c
+ to new file core-svr4.c.
+ * config/i386/i386sol2.mh, config/i386/i386v4.mh, config/m68k/amix.mh,
+ config/i386/ncr3000.mh, config/sparc/sun4sol2.mh: Add core-svr4.o
+ to NATDEPFILES.
+ * config/mips/irix4.mh: Add corelow.o to NATDEPFILES.
+
+Mon Apr 19 11:13:34 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * i387-tdep.c: Remove unused #includes.
+
+ * configure.in: Match i[34]86-*-sysv3.2 not i[34]86-*-sysv32.
+
+ * config/i386/nm-i386v.h: Define NO_PTRACE_H.
+
+Sun Apr 18 10:39:35 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * xcoffread.c: Nuke NO_DEFINE_SYMBOL code. There is no going back.
+
+ * stabsread.c (define_symbol): 'R' is synonym for 'P', not 'r'.
+ xcoffread.c (process_xcoff_symbol, case C_RPSYM):
+ Don't muck with SYMBOL_CLASS.
+
+Fri Apr 16 17:38:33 1993 Stu Grossman (grossman@cygnus.com)
+
+ * munch: Don't use head command. It doesn't exist everywhere.
+
+Fri Apr 16 15:07:57 1993 Fred Fish (fnf@cygnus.com)
+
+ * inflow.c (new_tty): Remove spurious 'o' character at end
+ of #endif line.
+
+Fri Apr 16 12:27:11 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * mips-tdep.c (mips_skip_prologue): Always skip the typical prologue
+ instructions and nothing more.
+ * mipsread.c (add_line): Add comment why we have to combine line number
+ entries for the same line number.
+
+Fri Apr 16 09:42:03 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * symtab.{c,h}: Doc fixes (remove symseg references, last relevant
+ in gdb 2.8!).
+
+Thu Apr 15 21:16:58 1993 Fred Fish (fnf@cygnus.com)
+
+ * depend, alldeps.mak: Update, now that gcc -MM bug is fixed.
+
+Thu Apr 15 12:38:39 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * source.c (select_source_symtab): Clean up comment. Also, if
+ we have a current_source_symtab, and s is NULL, return without
+ doing anything.
+ xcoffread.c (xcoff_symfile_read): Don't call select_source_symtab.
+ breakpoint.c (breakpoint_re_set): Don't call select_source_symtab.
+
+Thu Apr 15 02:37:48 1993 John Gilmore (gnu@cacophony.cygnus.com)
+
+ * dbxread.c (unknown_symchar_complaint): Add new complaint.
+ * stabsread.h: Declare it.
+ * partial-stab.h: Use it.
+
+ * utils.c (malloc_botch): Don't forward-declare if NO_MMALLOC.
+
+Wed Apr 14 17:12:51 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * stack.c (print_frame_info): Print specially if dummy frame.
+
+ * breakpoint.c: Add comments regarding within_scope future direction.
+
+ * Version 4.8.3.
+
+ * xcoffread.c (record_include_{begin,end}): Change fatal to complain.
+
+Wed Apr 14 14:03:18 1993 Per Bothner (bothner@cygnus.com)
+
+ * ch-exp.y: Fix thinko that broke parsing of FALSE.
+
+Wed Apr 14 12:49:29 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * stabsread.c (read_member_functions): Initialize domain for stubbed
+ member functions to avoid gdb core dumps when printing pointers
+ to member functions.
+ * cp-valprint.c (cp_print_class_method): Check for stubbed member
+ functions.
+
+Tue Apr 13 08:28:26 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * expprint.c (print_subexp): If opcode not found in op_print_tab,
+ stop with an error().
+ eval.c (evaluate_subexp): Change error message.
+
+ * objfiles.c (build_objfile_section_table): Cast return value
+ from obstack_finish.
+
+Mon Apr 12 10:53:50 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * config/rs6000/tm-rs6000.h, rs6000-tdep.c: Move FRAME_CHAIN
+ to rs6000_frame_chain and deal with it if we're in a signal handler.
+ (FRAME_SAVED_PC): Use rs6000_frame_chain.
+
+ * breakpoint.c (within_scope): New function.
+ (enable_breakpoint, watchpoint_check): Use it.
+
+ * source.c (openp): Handle "exec-file ./ls" correctly.
+
+ * breakpoint.c (breakpoint_1): Use wrap_here before "at".
+
+Sat Apr 10 01:32:43 1993 Per Bothner (bothner@rtl.cygnus.com)
+
+ * ch-exp.y: Clean up lexing of identifiers and
+ reserved words. (E.g. don't recognize FALSEXXX as the
+ keyword FALSE followed by the identifier XXX.)
+ Also, convert identifiers to lower case.
+
+Fri Apr 9 15:53:19 1993 Stu Grossman (grossman@cygnus.com)
+
+ * remote-mips.c, remote-monitor.c, remote-st2000.c: Convert to
+ new serial interface.
+
+Fri Apr 9 15:01:12 1993 Stu Grossman (grossman@cygnus.com)
+
+ * remote.c (remote_open): Use SERIAL_OPEN instead of serial_open.
+ (putpkt, getpkt): Use new return codes for SERIAL_READCHAR.
+ * ser-go32.c: Return -1 on most failures, 0 on most successes,
+ and use new return codes for go32_readchar().
+ * ser-unix.c: Ditto. Also, move error handling up to caller for
+ SERIAL_SETBAUDRATE().
+ * serial.c (serial_open): Internal call, not SERIAL_OPEN to get
+ to specific routine.
+ (serial_close): New routine to wrap around device close routine.
+ serial.h: Clean & document return values more clearly.
+
+Fri Apr 9 10:20:55 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * rs6000-pinsn.c (print_operand): Deal with no operand instructions.
+
+ * rs6000-pinsn.c (print_operand, case LI): Print condition register
+ operand in decimal rather than wrong textual versions.
+
+ * printcmd.c (_initialize_printcmd): Clean up docstring for "x"
+ (mention 't', remove false thing about 'g' only good with 'f').
+
+ * breakpoint.h: move "struct breakpoint" and friends to top of
+ file so that bpstat_find_breakpoint prototype works.
+
+ * solib.c (struct so_list): Add bfd field.
+ (solib_map_sections): Leave bfd open and scratch_pathname allocated.
+ Put the bfd in bfd field of the so_list.
+ (clear_solib): Free bfd name and close_bfd on the bfd.
+
+Fri Apr 9 00:45:41 1993 Per Bothner (bothner@rtl.cygnus.com)
+
+ * valarith.c (value_subscript): Add COERCE_REF.
+ * ch-exp.y (operand_5): We can generalize the 2nd operand
+ of a string repetition ot 'literal' without ambiguity.
+
+Thu Apr 8 10:15:10 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * breakpoint.h (struct bpstat): Remove momentary field.
+ Remove bpstat_momentary_breakpoint. This was always kludgy
+ and is no longer used.
+
+ * breakpoint.h: Add enum bpstat_what.
+ breakpoint.h (struct bpstat), breakpoint.c (bpstat_stop_status):
+ stop and print fields of bpstat now per-breakpoint, not just
+ one for the whole chain.
+ breakpoint.{c,h} (bpstat_what): New function.
+ breakpoint.h: Remove bpstat_stop and bpstat_should_print.
+ infrun.c: Replace switch (stop_bpstat->breakpoint_at->type)
+ with call to bpstat_what.
+ README: Remove watchpoint/breakpoint bug from known bugs.
+
+ * breakpoint.h: Prototype bpstat_find_breakpoint.
+
+Thu Apr 8 16:01:21 1993 Fred Fish (fnf@cygnus.com)
+
+ * symtab.c (find_methods, gdb_mangle_name): Note that functions
+ are g++ specific.
+ * symtab.h (VTBL_FNADDR_OFFSET, OPNAME_PREFIX_P, VTBL_PREFIX_P,
+ DESTRUCTOR_PREFIX_P): Note that macros are g++ specific.
+
+Thu Apr 8 12:45:32 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * i960-pinsn.c (tabent): Copied struct definition from
+ opcodes/i960-dis.c.
+
+Thu Apr 8 10:34:37 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * symtab.h (DESTRUCTOR_PREFIX_P): New macro to check if physname
+ is a C++ destructor.
+ * symtab.c (gdb_mangle_name): Use it.
+ * symtab.c (find_methods): Do not add destructors to choice list
+ for constructors.
+ * symtab.c (decode_line_1): Make breakpoints on destructors work
+ for gcc-2.x again.
+
+Wed Apr 7 18:43:09 1993 Stu Grossman (grossman@cygnus.com)
+
+ * ser-go32.c: Make it use serial port name.
+ * go32-xdep.c: Put in def for strlwr, needed by dir.o in go32 libc.
+
+ * infcmd.c (read_pc): Make sure that we read PC_REGNUM when not
+ in a system call!
+
+Wed Apr 7 15:52:11 1993 Stu Grossman (grossman@cygnus.com)
+
+ * configure.in: Only configure sparclite subdir when target_cpu
+ is sparclite.
+
+Wed Apr 7 10:11:22 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * xcoffread.c (struct coff_symbol): Change c_sclass to unsigned char.
+ Remove FIXME comment regarding this.
+
+ * symfile.h: Change NULL->'\0' in comment (that wasn't a typo).
+
+ * xcoffread.c (read_xcoff_symtab): Use E_SYMNMLEN.
+
+Tue Apr 6 22:30:58 1993 K. Richard Pixley (rich@cygnus.com)
+
+ Add section table to objfile struct. Use it for find_pc_section.
+ * objfiles.c (add_to_objfile_sections,
+ build_objfile_section_table, find_pc_section): new functions.
+ (allocate_objfile): build section table.
+ * objfiles.h (struct obj_section): new structure.
+ (struct objfile): add section table.
+ (find_pc_section): new prototype.
+ * solib.[ch] (find_pc_section_from_so_list): removed.
+ * sparc-tdep.c: include objfiles.h for find_pc_section. include
+ symfile.h for objfiles.h.
+ (in_solib_trampoline): adjusted for new find_pc_section
+ prototype. Removed BAD_RICH_HACK ifdefs.
+ * symfile.c (syms_from_objfile): offset objfile sections.
+ (find_pc_section): removed. Also removed BAD_RICH_HACK ifdefs.
+ * symfile.h (find_pc_section): prototype removed. Also fixed
+ comment typo NUL -> NULL.
+ * target.[ch] (find_pc_section_from_targets): removed.
+ * config/sparc/tm-sun4sol2.h (BAD_RICHH_HACK): removed.
+
+Tue Apr 6 21:41:13 1993 Stu Grossman (grossman@cygnus.com)
+
+ * ser-go32.c: Format. (go32_open): Use proper return value.
+
+ * configure.in: Undo conditional configdirs hack for sparclite.
+
+Tue Apr 6 17:07:37 1993 Jim Wilson (wilson@sphagnum.cygnus.com)
+
+ * symtab.c (list_symbols): When call break_command, pass both
+ filename and function name not just function name.
+
+Tue Apr 6 15:00:09 1993 Fred Fish (fnf@cygnus.com)
+
+ (Changes and new files to make "none" a full fledged configuration)
+ * config/none/{nm-none.h, tm-none.h, xm-none.h}: New files.
+ Currently only tm-none.h has any meaningful contents.
+ * config/none/none.mh (NAT_FILE): Use nm-none.h
+ * config/none/none.mh (XM_FILE): Use xm-none.h
+ * config/none/none.mt (TM_FILE): Use tm-none.h
+ * Makefile.in (depend): Remove comment about parse errors in
+ valops.c, it now parses correctly and generates a correct depend
+ line. Remove line that touches xm.h, tm.h, and nm.h; they are
+ now linked to config/none/{xm-none.h, tm-none.h, nm-none.h}.
+
+Tue Apr 6 09:54:29 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * values.c (USE_STRUCT_RETURN): Only use gcc wierdness for gcc1.
+
+ * xcoffread.c (read_xcoff_symtab): Deal correctly with symbols of
+ exactly 8 characters.
+
+Tue Apr 6 10:31:26 1993 Stu Grossman (grossman@cygnus.com)
+
+ * configure.in: Sparclite uses sparc config dir. Also has it's
+ own tm- & .mt files now. Also add sparclite to configdirs.
+ * go32-xdep.c: Dummy routines for sigsetmask & strlwr.
+ * config/i386/go32.mh: Nullify def of TERMCAP.
+ * config/i386/xm-go32.h: Get rid of redef of EIO.
+ * config/sparc/{sparclite.mh tm-sparclite.h}: New sparclite
+ specific configs. Very similar to sun4os4, but without solib.
+ * sparclite/{Makefile.in configure.in}: First cut at making this
+ dir configgable.
+
+Tue Apr 6 03:10:44 1993 Stu Grossman (grossman@cygnus.com)
+
+ * ser-go32.c: First cut at adapting to new serial interface.
+
+Mon Apr 5 22:29:43 1993 Stu Grossman (grossman@cygnus.com)
+
+ * Makefile.in (SFILES OBS): Add serial.[co] & ser-hardwire.[co].
+ These implement a new serial line interface for talking to remote
+ targets.
+ * configure.in: Link ser-hardwire.c to ser-unix.c for all hosts,
+ EXCEPT go32, which gets ser-go32.c.
+ * remote.c: Use new serial interface. More remote-xxx's to be
+ converted later.
+ * ser-bsd.c, ser-termios.c: Removed.
+ * serial.c: New. Implements common operations for all serial
+ types.
+ * ser-unix.c: New. Unix specific serial operations for various
+ flavors of Unix (Posix, SysV, BSD).
+ * serial.h: Generic serial interface defs.
+ * config/i386/go32.mh, config/i386/i386bsd.h,
+ config/m68k/apollo68b.mh, config/sparc/sun4os4.mh: Remove
+ ser-bsd.o from XDEPFILES. All the magic is now handled in
+ configure.in.
+
+Mon Apr 5 20:48:54 1993 Stu Grossman (grossman@cygnus.com)
+
+ * config/h8500/tm-h8500.h: Clean up brain damage found by GCC.
+
+Fri Apr 2 08:23:14 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * xcoffread.c (xcoff_symfile_offsets): Use 0 not addr for offsets.
+
+ * rs6000-tdep.c (frameless_function_invocation): Don't even think
+ about framelessness except on the innermost frame.
+
+ * xcoffexec.c: Call fatal() not abort().
+
+ * stabsread.c (patch_block_stabs): If stab & no symbol, make
+ a LOC_OPTIMIZED_OUT symbol.
+ symtab.h (enum address_class): Add LOC_OPTIMIZED_OUT.
+ findvar.c (read_var_value), printcmd.c (address_info),
+ symmisc.c (print_{,partial_}symbol), c-exp.y (variable),
+ m2-exp.y (yylex): Deal with it.
+ ch-exp.y (yylex): Deal with it.
+
+Thu Apr 1 18:43:02 1993 Stu Grossman (grossman@cygnus.com)
+
+ * findvar.c (value_from_register): H8500 specific, check to see
+ if we are looking at short pointer. If so, skip crock.
+ * h8500-tdep.c (h8500_frame_chain): Mask down value from
+ read_memory_integer() to avoid getting messed up by sign extension.
+
+Thu Apr 1 16:44:41 1993 K. Richard Pixley (rich@rtl.cygnus.com)
+
+ * sparc-tdep.c (in_solib_trampoline), symfile.c (find_pc_section):
+ ifdef protect using BAD_RICH_HACK. This should be removed soon.
+ * config/sparc/tm-sun4sol2.h (BAD_RICH_HACK): define.
+
+Thu Apr 1 09:01:38 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * i960-pinsn.c, a29k-pinsn.c: Much abridged, just use libopcodes.a.
+
+ * core.c (dis_asm_print_address): New function.
+
+ * core.c (dis_asm_read_memory): Reinstate 4th arg. The prototype
+ has been fixed.
+
+Thu Apr 1 09:34:43 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * breakpoint.c (bpstat_print, bpstat_stop_status): Change to walk the
+ entire breakpoint chain and print only the first entry that needs to
+ be printed and needs to be stopped for. Fixes problems with printing
+ of multiple breakpoints with different conditions.
+ * breakpoint.c (print_it_done): Renamed from print_it_noop as it
+ effectively stops printing of the breakpoint chain.
+ * breakpoint.c (print_it_noop): New routine to print nothing
+ for this breakpoint entry and dont stop printing.
+ * breakpoint.c (breakpoint_re_set_one): mention the reevaluated
+ watchpoint only if it is enabled.
+ * mipsread.c (parse_procedure): Correct incorrect setjmp procedure
+ descriptor from the library to make backtraces through setjmp work.
+ * mipsread.c (fixup_sigtramp): Correct pcreg and fregoffset for
+ sigtramp.
+ * mips-tdep.c (read_next_frame_reg): Provide correct values for
+ all registers saved within sigtramp, cleanup.
+
+Wed Mar 31 12:52:12 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * sparc-pinsn.c: Much abridged, just calls version in libopcodes.a.
+
+Wed Mar 31 21:23:41 1993 K. Richard Pixley (rich@rtl.cygnus.com)
+
+ * core.c (dis_asm_read_memory): drop fourth arg which conflicts
+ with prototype in ../include/dis-asm.h.
+
+Wed Mar 31 12:52:12 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * core.c (dis_asm_{read_memory,memory_error}): New functions.
+ m68k-pinsn.c, h8500-tdep.c, i386-pinsn.c, mips-pinsn.c, z8k-tdep.c:
+ Use read_memory_func interface to disassembler.
+
+Tue Mar 30 15:46:14 1993 K. Richard Pixley (rich@rtl.cygnus.com)
+
+ Teach sparc solaris to next over shared library functions.
+ * solib.[hc] (find_pc_section_from_so_list): new function and
+ prototype.
+ * sparc-tdep.c (in_solib_trampoline): new function.
+ * symfile.[hc] (find_pc_section): new function and prototypes.
+ * target.[hc] (find_pc_section_from_targets): new function and
+ prototypes.
+ * config/sparc/tm-sun4sol2.h (IN_SOLIB_TRAMPOLINE): redefine to
+ in_solib_trampoline.
+
+Tue Mar 30 08:06:24 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * infrun.c (wait_for_inferior): Revise comment.
+
+ * command.c (do_setshow_command): Use %u with var_{u,z}integer.
+
+ * command.{c,h}: New var_type var_integer.
+ main.c: Use it for history_size.
+
+ * rs6000-tdep.c, xcoffexec.c, config/rs6000/xm-rs6000.h, breakpoint.c:
+ Lint and byte-order fixups.
+
+ * breakpoint.c (print_it_normal): Return 0 after hitting watchpoint.
+
+ * breakpoint.h (bpstat): New field print_it.
+ breakpoint.c (bpstat_print): Use it.
+ (print_it_normal): New function (from old bpstat_print code).
+ (bpstat_{alloc,stop_status}): Set print_it field.
+
+ * breakpoint.c (bpstat_stop_status): Use catch_errors when
+ evaluating watchpoint condition, via new function watchpoint_check.
+ Also stop if watchpoint disabled due to leaving its block.
+
+ * findvar.c [REG_STRUCT_HAS_ADDR]: Add comment.
+
+Tue Mar 30 00:14:38 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * mips-pinsn.c: Add missing include of dis-asm.h.
+
+Mon Mar 29 15:03:25 1993 Fred Fish (fnf@cygnus.com)
+
+ * Makefile.in (clean, distclean, realclean): Recursively apply
+ to subdirs first, rather than last. This avoids, for example,
+ Makefile being removed in a parent directory before the recursive
+ make is run.
+
+ * alldeps.mak, depend: Update for below changes.
+
+ * config/m68k/tm-m68k.h: Renamed from config/m68k/tm-68k.h.
+ * m68k/{tm-3b1.h, tm-altos.h, tm-amix.h, tm-es1800.h,
+ tm-hp300bsd.h, tm-hp300hpux.h, tm-isi.h, tm-news.h, tm-os68k.h,
+ tm-st2000.h, tm-sun2.h, tm-sun3.h, tm-vx68.h}: Include tm-m68k.h
+ instead of tm-68k.h.
+ * Makefile.in (HFILES): tm-68k.h renamed to tm-m68k.h.
+ * README, a29k-pinsn.c, m68k-pinsn.c, m68k-stub.c, remote-vx.c,
+ m68k/{altos.mh, altos.mt, apollo68b.mh, nm-apollo68b.h,
+ nm-hp300bsd.h, config/m68k/xm-apollo68b.h}: Map '68k' to 'm68k'.
+ * a29k/tm-a29k.h, doc/gdbint.texinfo: Account for renaming of
+ tm-68k.h to tm-m68k.h.
+ * m68k/m68k-fp.mt (TM_FILE): tm-68k-fp.h renamed to tm-m68k-fp.h.
+ * m68k/m68k-nofp.mt (TM_FILE): tm-68k-nofp.h renamed to
+ tm-m68k-nofp.h.
+
+ * config/a29k/tm-a29k.h: Renamed from config/a29k/tm-29k.h.
+ * a29k-pinsn.c: Renamed from am29k-pinsn.c.
+ * a29k-tdep.c: Renamed from am29k-tdep.c.
+ * remote-eb.c, config/a29k/tm-ultra3.h: Include renamed tm-a29k.h.
+ * remote-monitor.c, remote-st2000.c, config/a29k/{nm-ultra3.h,
+ tm-a29k.h, xm-ultra3.h}, config/romp/rtbsd.mh, doc/gdbinv-s.texi,
+ testsuite/gdb.t15/funcargs.exp, testsuite/gdb.t17/callfuncs.exp:
+ Map '29k' to 'a29k'.
+ * config/a29k/{a29k-kern.mt, a29k-udi.mt, a29k.mt, ultra3.mt}
+ (TDEPFILES): Use renamed a29k-pinsn.o and a29k-tdep.o.
+ * config/a29k/{a29k-udi.mt, a29k.mt} (TM_FILE): Use renamed
+ tm-a29k.h.
+ * config/a29k/a29k-udi.mt (MT_CFLAGS): Remove TARGET_AM29K
+ define that does not appear anywhere else in the gdb source tree.
+ * doc/gdbinit.texinfo: Document renaming of tm-29k.h to tm-a29k.h.
+
+Mon Mar 29 13:55:29 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * breakpoint.c: Add comments regarding breakpoint_re_set.
+
+ * xcoffread.c (sort_syms, compare_symbols): Remove.
+ (xcoff_symfile_read): Use sort_all_symtab_syms from symfile.c
+ not our own sort_syms (it is identical).
+
+ * xcoffread.c: Nuke NAMES_HAVE_DOT define (not used).
+
+Sun Mar 28 11:24:37 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * breakpoint.c (breakpoint_re_set_one): Fix storage leak.
+ * breakpoint.c (enable_breakpoint): Don't enable watchpoint if it
+ went out of scope.
+ * exec.c (exec_close): Fix storage leak.
+ * exec.c (exec_file_command): Make sure that bfd doesn't realign the
+ output sections when patching an executable.
+ * mips-nat.c (store_inferior_registers): Use REGISTER_PTRACE_ADDR
+ when writing all registers.
+ * mips-tdep.c (mips_push_dummy_frame): Save floating point registers
+ at the right offset in the dummy frame.
+ * mipsread.c (psymtab_to_symtab_1): Do not complain for stProc,
+ stStaticProc and stEnd symbols as they are generated by gcc-2.x.
+ * mipsread.c (mipscoff_new_init): Initialize stabsread and buildsym.
+
+Fri Mar 26 15:25:05 1993 John Gilmore (gnu@cygnus.com)
+
+ * Makefile.in (TARFILES): Avoid trailing backslash.
+
+Fri Mar 26 11:29:30 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * breakpoint.{c,h}: Add exp_string to struct breakpoint and use
+ it in breakpoint_re_set.
+ * breakpoint.c (watch_command, enable_breakpoint): Fetch lazy values.
+
+ * rs6000-tdep.c (single_step): Misc cleanups (CORE_ADDR not int,
+ don't use sizeof(int) for target stuff, etc).
+
+Thu Mar 25 15:03:53 1993 Fred Fish (fnf@cygnus.com)
+
+ * alldeps.mak, configure.in, i860-break.h, i860-opcode.h,
+ i860-pinsn.c, i860-tdep.c, config/i860/*: Remove incomplete i860
+ support that can't be integrated anyway due to lack of clear
+ authorship.
+
+Thu Mar 25 12:26:50 1993 Stu Grossman (grossman@cygnus.com)
+
+ * findvar.c (read_register, write_register): Make these capable
+ of reading/writing registers that are shorter than REGISTER_TYPE.
+ * (value_from_register): Install H8500 specific code to return
+ proper value when register is being used as a pointer.
+ * h8500-tdep.c: Remove extra defines of NUM_REGS.
+ (h8500_skip_prologue): Use correct lengths for LINK instructions.
+ (FRAME_CHAIN): Change name to h8500_frame_chain. Rewrite code to
+ chain frames properly by combining frame pointer with T reg.
+ (init_extra_frame_info): Delete. It's now a macro.
+ (frame_args_address): Don't add PTR_SIZE. Stack args are already
+ offset by the correct amount off of the frame pointer.
+ (register_byte): Delete. It's now a macro.
+ (register_raw_size, register_virtual_size): Delete. Replaced by
+ common routine h8500_register_size, cuz there's no difference
+ between the raw & virtual sizes on this machine.
+ (register_convert_to_raw, register_convert_to_virtual): Delete,
+ cuz there's no difference between the raw & virtual forms.
+ Replaced by memcpy in tm file.
+ (register_virtual_type): Rename to h8500_register_virtual_type.
+ Get rid of pointer pseudo-regs, use _REGNUM with all reg names.
+ (_initialize_h8500_tdep): Get rid of crock to ensure that GDB &
+ emulator have same reg offsets. This is all handled in the
+ simulator code now.
+ (h8500_trapped_internalvar): New routine to detect references to
+ convenience vars acting as pointer pseudo-regs.
+ (h8500_value_trapped_internalvar): Conjure up value of pointer
+ pseudo-regs.
+ (h8500_set_trapped_internalvar): Convert set value in real
+ register references.
+ infcmd.c (read_pc, write_pc): Add h8500 specific code to handle
+ code segment register.
+ infrun.c (proceed): Simplify. Call write_pc instead of doing it
+ by hand.
+ (wait_for_inferior): Add h8500 specific code to add stack segment
+ when reading SP register.
+ remote-sim.c (fetch_register): Spacing.
+ tm-h8500.h: #define GDB_TARGET_IS_H8500 to make it easier to
+ detect cruft. Redo all register manipulation stuff. Get rid of
+ pointer pseudo-regs. (INIT_EXTRA_FRAME_INFO): Adds stack segment
+ to frame pointer. (IS_TRAPPED_INTERNALVAL,
+ VALUE_OF_TRAPPED_INTERNALVAR, SET_TRAPPED_INTERNALVAR): Use these
+ to create internal vars for pointer pseudo-regs.
+
+Thu Mar 25 10:10:28 1993 Fred Fish (fnf@cygnus.com)
+
+ * Makefile.in: Numerous small changes to macro definitions
+ and rules for building gdb distribution tree. Many macros
+ eliminated or merged, and rules simplified.
+ * alldeps.mak: Update.
+ * depend: Update.
+
+Wed Mar 24 13:52:29 1993 david d `zoo' zuhn (zoo at poseidon.cygnus.com)
+
+ * Makefile.in: recurse through SUBDIRS for dvi target too
+
+Wed Mar 24 08:48:30 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * Clean up xcoff relocation.
+ objfiles.h (struct objfiles): Add section_offsets, num_sections.
+ symfile.c (syms_from_objfile), xcoffread.c (xcoff_symfile_offsets):
+ Set them.
+ symtab.h (struct general_symbol_info): Add section field.
+ minsyms.c (prim_record_minimal_symbol{,_and_info}): Set it.
+ xcoffread.c: Set section for symbols and msymbols.
+ (struct symtab): Add block_line_section field.
+ buildsym.c (end_symtab): Set it.
+ (end_symtab and callers): Add section parameter.
+ objfiles.c (objfile_relocate): New funciton.
+ xcoffexec.c (vmap_symtab): Use it.
+ xcoffsolib.h (struct vmap): Remove unused fields.
+ config/rs6000/tm-rs6000.h, stack.c, xcoffexec.c: Remove
+ CORE_NEEDS_RELOCATION, symtab_relocated.
+ config/rs6000/tm-rs6000.h: Remove use of loadinfotext.
+ rs6000-tdep.c: Make loadinfotext static.
+ breakpoint.c (fixup_breakpoints): Doc fix.
+ symtab.h (struct symtab), config/rs6000/tm-rs6000.h, buildsym.c
+ (end_symtab): primary field replaces nonreloc.
+
+Tue Mar 23 00:10:53 1993 John Gilmore (gnu@cygnus.com)
+
+ * symtab.h (struct linetable_entry): Remove confusing comment.
+
+Tue Mar 23 00:01:23 1993 david d `zoo' zuhn (zoo at cirdan.cygnus.com)
+
+ * Makefile.in: add installcheck target
+
+Mon Mar 22 16:17:58 1993 Fred Fish (fnf@cygnus.com)
+
+ * config/{a29k, arm, convex, gould, h8300, i386, i860, i960, m68k,
+ m88k, mips, none, ns32k, pa, pyr, romp, rs6000, sparc, tahoe, vax,
+ z8k}: New directories to hold cpu specific configuration files.
+ Naming follows gcc convention.
+ * config/{*.mt, *.mh}: All target and host makefile fragment
+ config files moved to an appropriate config/<cpu> subdirectory.
+ * nm-*, xm-*, tm-*: All native, host, and target files, which
+ get linked to nm.h, xm.h, and tm.h respectively by configure,
+ moved to appropriate config/<cpu> subdirectory.
+ * nm-sysv4.h, xm-sysv4.h, tm-sysv4.h, tm-sunos.h, nm-trash.h:
+ Native, host, and target files that are common across more than
+ one cpu architecture and included by one of the configured
+ native, host, or target files, get moved to config directory.
+ * Makefile.in (INCLUDE_CFLAGS): Add -I${srcdir}/config to
+ pick up native, host, or target include files moved to one of
+ the config subdirectories, and that are included by other files.
+ * Makefile.in (alldeps.mak): Modify to account for new config
+ directory structure.
+ * alldeps.mak, depend: Update for new config directory structure.
+ * config/*/[ntx]m-*.h: Modify all files that include other
+ [ntx]m-*.h files to use path relative to gdb/config. I.E.
+ "a29k/tm-ultra3.h" includes "a29k/tm-29k.h" rather than just
+ "tm-29k.h".
+ * remote-eb.c (tm-29k.h): Include a29k/tm-29k.h.
+ * mipsread.c (tm-mips.h): Include mips/tm-mips.h.
+ * i860-pinsn.c (tm-i860.h): Include i860/tm-i860.h.
+ * configure.in: Default gdb_host_cpu to host_cpu, and remap
+ the ones where the default is not unique or different than the
+ config subdirectory name. Similarly, handle gdb_target_cpu.
+ Modify configure.in as appropriate to make use of gdb_host_cpu
+ and gdb_target_cpu to find makefile fragments and make links.
+
+Mon Mar 22 12:36:24 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * mipsread.c (compare_blocks): Sort blocks with the same start
+ address by decreasing ending address.
+
+Mon Mar 22 20:36:04 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * mipsread.c (parse_procedure): Save cur_fdr accross call to
+ lookup_symbol as it might get clobbered by the call.
+
+ * mipsread.c (parse_partial_symbols): Use ADD_PSYMBOL_ADDR_TO_LIST.
+ The previous code did not initialize the language field for the psymtab
+ entry.
+
+Sat Mar 20 00:33:39 1993 John Gilmore (gnu@cygnus.com)
+
+ * c-exp.y (parse_number): Avoid shift warning.
+ * serial.h (struct ttystate): Declare empty one on DOS.
+
+Fri Mar 19 12:59:50 1993 Stu Grossman (grossman@cygnus.com)
+
+ * xm-sun4os4.h: Return type of free() should be void, not int.
+
+ * vx-share/vxWorks.h: Remove #def of NULL.
+
+Fri Mar 19 11:28:18 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * tm-rs6000.h: Nuke no-op STAB_REG_TO_REGNUM.
+
+Fri Mar 19 07:40:09 1993 Steve Chamberlain (sac@cygnus.com)
+
+ * z8k-tdep.c (print_insn): Include the new dis-asm header file.
+
+Thu Mar 18 14:26:57 1993 Per Bothner (bothner@rtl.cygnus.com)
+
+ * ieee-float.c: Moved to ../libiberty.
+ * ieee-float.h: Moved to ../include.
+ * Makefile.in: Update accordingly.
+ * i386-pinsn.c (print_insn), m68k-pinsn.c (print_insn):
+ Convert to stubs that call disassemblers in ../opcodes/*-dis.c.
+ * m68k-tdep.c: Removed definition of ext_format ext_format_68881;
+ it is now in ../opcodes/m68881-ext.c.
+ * mips-tdep.c (mips_skip_prologue): Try to skip more of the
+ prologue (some callers _do_ care).
+ * mips-pinsn.c (print_insn), z8k-tdep.c (print_insn): Convert to
+ new interface of ../opcodes/*-dis.c.
+ * ch-exp.y: Add #include <ctype.h>.
+
+Thu Mar 18 11:57:49 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * xcoffexec.c (exec_close): Don't close exec_bfd twice.
+
+ * xcoffread.c (enter_line_range): endaddr is exclusive, not inclusive.
+
+Wed Mar 17 09:46:31 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * xcoffread.c (arrange_linetable): Use x{m,re}alloc not {m,re}alloc.
+
+Wed Mar 17 11:28:11 1993 Steve Chamberlain (sac@thepub.cygnus.com)
+
+ * z8k-tdep.c (extract_return_value, write_return_value,
+ store_struct_return): New functions from macros in tm-z8k.h.
+
+Wed Mar 17 11:23:06 1993 Fred Fish (fnf@cygnus.com)
+
+ * valops.c (value_arg_coerce): Apply temporary patch to
+ fix problem with coercion of array and function types when
+ passed as arguments to C functions, pending a more complete
+ review of when and how coercion should be done, depending
+ upon context and language.
+
+Wed Mar 17 09:46:31 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * xcoffread.c (MIN_TBTABSIZ): Change to 12.
+
+ * xcoffread.c (xcoff_symfile_read): Only read stringtab and
+ debugsec if there are a non-zero number of symbols.
+
+Tue Mar 16 18:08:45 1993 John Gilmore (gnu@cygnus.com)
+
+ * command.c (show_user): Avoid fprintf_filtered botch (AGAIN!).
+
+Tue Mar 16 15:18:17 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * xcoffexec.c (add_vmap): Wrap symbol read in catch_errors.
+
+ * xcoffread.c (read_symbol_lineno): Look to end of symbols for .bf,
+ not just 50 symbols.
+ (symtbl_num_syms): New variable.
+ (read_xcoff_symtab): Set it.
+ (read_symbol_nvalue): Check for bad symno.
+ (read_symbol_{lineno,nvalue}, callers): Don't pass symtable; it's
+ always symtbl.
+
+Tue Mar 16 10:09:05 1993 Stu Grossman (grossman@cygnus.com)
+
+ * config/rs6000.mh: Get rid of -Dfd_set=int crock.
+ This is defined in defs.h if necessary.
+ * vx-share/vxWorks.h: Remove #defs of min and max.
+ * vx-share/xdr_ld.c, vx-share/xdr_ptrace.c,
+ vx-share/xdr_rdb.c: include defs.h.
+
+Fri Mar 12 09:33:23 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * xcoffread.c (retrieve_tracebackinfo): Move assignment out
+ of while condition.
+
+ * xcoffread.c (enter_line_range): complain() on bad endoffset.
+ xcoffread.c: Doc fixes.
+
+Tue Mar 9 09:56:12 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * tm-rs6000.h (CORE_NEEDS_RELOCATION): Just call xcoff_relocate_core.
+ xcoffexec.c (xcoff_relocate_core): New function.
+ (text_adjustment): Removed.
+ (add_vmap): Return the vmap.
+ rs6000-tdep.c (add_text_to_loadinfo): No longer static.
+
+Fri Mar 5 05:22:46 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * xcoffsolib.h: Add objfile member to struct vmap.
+ xcoff{exec,solib}.c: Use it, not lookup_objfile_bfd.
+ xcoffexec.c (add_vmap): Allocate objfiles here.
+
+Sun Mar 14 02:54:15 1993 John Gilmore (gnu@cygnus.com)
+
+ Support 68000 series without floating point.
+
+ * configure.in (m68000-*-{aout,elf,coff}): New configs.
+ * tm-68k-nofp.h: New file, lacks 68881 support.
+ * config/m68k-nofp.mt: New file.
+
+Sun Mar 14 02:30:08 1993 John Gilmore (gnu@cygnus.com)
+
+ Remove a few remaining underscore/no-underscore remnants from
+ config files.
+
+ * config/{m68k-un.mt, sparc-un.mt}: Remove.
+ * config/m68k-noun.mt: Rename to m68k-fp.mt.
+ * config/sparc-noun.mt: Rename to sparc-em.mt.
+ * tm-68k-noun.h, tm-spc-noun.h: Remove.
+ * tm-68k-un.h: Rename to tm-68k-fp.h.
+ * tm-spc-un.h: Rename to tm-spc-em.h.
+ * tm-sun4sol2.h: Cleanup.
+ * configure.in (m68k-*, sparc-* targets): Corresponding changes.
+
+Sat Mar 13 14:58:22 1993 John Gilmore (gnu@cygnus.com)
+
+ * symmisc.c (std_in, std_out, std_err): Move initializations
+ to runtime code, in case they aren't constant.
+
+Fri Mar 12 16:23:54 1993 K. Richard Pixley (rich@cygnus.com)
+
+ * symtab.c (find_pc_symtab): some object file formats, notably
+ mips, have holes in the address ranges of symtabs. Change
+ this algorithm from first hit to tightest fit.
+
+ * mips-tdep.c (heuristic_proc_start): if we walk the pc into the
+ fence post without finding the enclosing function, then print a
+ warning.
+
+Thu Mar 11 09:33:01 1993 Fred Fish (fnf@cygnus.com)
+
+ * utils.c (fputs_demangled, fprint_symbol): Remove.
+ * utils.c (fprintf_symbol_filtered): New function which combines
+ the functionality of fputs_demangled and fprint_symbol. Uses a
+ caller provided language parameter to select the appropriate
+ demangler, and caller provided args to pass to the demangler.
+ * defs.h (enum language): Move further up in file so enum can
+ be used in prototypes.
+ * defs.h (fputs_demangled, fprint_symbol): Remove prototypes.
+ * defs.h (fprintf_symbol_filtered): Add prototype.
+ * c-typeprint.c (cp_type_print_method_args): Replace calls to
+ fputs_demangled with call to fprintf_symbol_filtered.
+ * cp-valprint.c (demangle.h): Include
+ * cp-valprint.c (cp_print_value_fields): Replace calls to
+ fprint_symbol with calls to fprintf_symbol_filtered.
+ * printcmd.c (print_frame_args): Replace call to fprint_symbol
+ with call to fprintf_symbol_filtered.
+ * stack.c (print_frame_info): Remove obsolete code so we don't
+ have to update fputs_demangled usage in it.
+ * stack.c (print_frame_info, frame_info): Add language variable
+ to pass to fprintf_symbol_demangled and initialize it from the
+ symbol's language. Replace calls to fputs_demangled with calls
+ to fprintf_symbol_filtered.
+ * symtab.c (find_methods): Replace call to fputs_demangled with
+ call to fprintf_symbol_filtered.
+ * ch-valprint.c (demangle.h): Include.
+ * ch-valprint.c (chill_print_value_fields): Replace call to
+ fprint_symbol with call to new fprintf_symbol_filtered.
+
+Wed Mar 10 17:37:11 1993 Fred Fish (fnf@cygnus.com)
+
+ * Makefile.in (VERSION): Bump version to 4.8.2.
+
+ * main.c (source_command): Require an explicit pathname of file
+ to source, since previous behavior of defaulting to gdb init file
+ was troublesome and undocumented.
+ * printcmd.c (disassemble_command): Add missing '{}' pair to
+ else with two statements. Bug reported by Stephane Tsacas
+ <slt@isoft.fr>.
+ * symtab.c (find_pc_line): Don't complain about zero length or
+ negative length line numbers for the moment, since we may not own
+ the terminal when called, such as when single stepping. (FIXME)
+ * language.h (CAST_IS_CONVERSION): True if current language is
+ C++ as well as C. Fix from Peter Schauer.
+ * environ.c (get_in_environ, set_in_environ, unset_in_environ):
+ Use STREQN macro rather than bare '!strncmp()'.
+ * environ.c (unset_in_environ): Avoid use of memcpy on
+ overlapping memory regions, as suggested by Paul Eggert
+ <eggert@twinsun.com>.
+ * c-exp.y (%union struct): Remove unused ulval as suggested
+ by Paul Eggert <eggert@twinsun.com>.
+
+Mon Mar 8 19:03:06 1993 Fred Fish (fnf@cygnus.com)
+
+ * main.c (gdbinit): Make static.
+ * main.c (inhibit_gdbinit): Move to file scope.
+ * main.c (main): Remove local inhibit_gdbinit.
+ * main.c (source_command): Don't source '.gdbinit' file by
+ default if gdb has been told to ignore it.
+
+Sun Mar 7 21:58:53 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * Makefile.in (MAKEOVERRIDES): Define to be empty for GNU Make
+ 3.63.
+
+Fri Mar 5 17:39:45 1993 John Gilmore (gnu@cacophony.cygnus.com)
+
+ * printcmd.c (print_address_symbolic): Only print if offset
+ is shorter than max_symbolic_offset.
+ (initialize_printcmd): `set print max-symbolic-offset'.
+
+ * am29k-tdep.c (TAGWORD_ZERO_MASK): New #define.
+ (examine_tag): Use it.
+ (read_register_stack): Only look in the local registers for a
+ memory address if it's between rfb and rsp; go to memory otherwise.
+ (initialize_29k): Fix call_scratch_address doc. Remove reginv_com.
+ (reginv_com): Remove ancient kludge command.
+
+Fri Mar 5 17:16:26 1993 K. Richard Pixley (rich@rtl.cygnus.com)
+
+ * tm-irix3.h (ZERO_REGNUM): copy this macro from tm-mips.h so that
+ irix4 will again compile.
+
+ * tm-mips.h (GDB_TARGET_IS_MIPS): no longer used, now removed.
+
+ * configure.in: accept mips-sgi-irix4* for irix4.
+
+Fri Mar 5 07:49:48 1993 Steve Chamberlain (sac@lisa.cygnus.com)
+
+ * z8k-tdep.c (print_register_hook): Lint.
+
+Thu Mar 4 17:42:03 1993 John Gilmore (gnu@cygnus.com)
+
+ Lint fixes from Paul Eggert (eggert@twinsun.com):
+
+ * command.c (do_setshow_command): var_uintegers are unsigned.
+ * sparc-tdep.c (save_insn_opcodes, restore_insn_opcodes):
+ unsigned, since they use hex values with the high bit set.
+
+Thu Mar 4 08:22:55 1993 Fred Fish (fnf@cygnus.com)
+
+ Fixes submitted by Karl Berry (karl@nermal.hq.ileaf.com):
+ * m88k-pinsn.c (sprint_address): Use SYMBOL_NAME macro to
+ access symbol name.
+ * m88k-nat-c (SXIP_OFFSET, SNIP_OFFSET, SFIP_OFFSET): Enclose
+ macro definitions in parenthesis.
+
+ * dbxread.c (dbx_symfile_init): Catch the case where there is
+ no string table, but the only way we find out is by reading zero
+ bytes from EOF.
+
+Wed Mar 3 15:51:28 1993 Fred Fish (fnf@cygnus.com)
+
+ * dbxread.c (dbx_symfile_init): Make size of the string table
+ size field a define (DBX_STRINGTAB_SIZE_SIZE). Ensure that the
+ offset to the string table is nonzero and handle the nonexistant
+ string table case, should it occur. Ensure that the string table
+ size read from the file is reasonable, with a minimum lower bound
+ of DBX_STRINGTAB_SIZE_SIZE instead of zero.
+
+Wed Mar 3 07:23:03 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * Makefile.in: Changes to build testsuite correctly.
+ (FLAGS_TO_PASS): Added CXX and CXXFLAGS.
+ (CC_FOR_TARGET, CXX, CXX_FOR_TARGET): New variables.
+ (TARGET_FLAGS_TO_PASS): New variable.
+ (SUBDIRS): Added testsuite.
+ (all): Build testsuite using TARGET_FLAGS_TO_PASS, so that
+ testsuite is compiled with CC_FOR_TARGET rather than CC.
+
+Tue Mar 2 17:57:56 1993 Fred Fish (fnf@cygnus.com)
+
+ * dbxread.c (dbx_symfile_init): Fix for nonexistant string table,
+ reported by mycroft@gnu.ai.mit.edu.
+
+ (Ultrix 2.2 support from Michael Rendell <michael@mercury.cs.mun.ca>)
+ * configure.in (vax-*-ultrix2*): New triplet.
+ * config/vaxult2.mh: New file.
+ * xm-vaxult2.h: New file.
+
+ * c-exp.y (parse_number): Change high_bit to unsigned.
+ * demangle.c: Change all references to cfront to ARM, since the
+ actual algorithm is the one specified in the Annotated Reference
+ Manual. This was confusing users into thinking that full cfront
+ support was implemented.
+ * dwarfread.c (CFRONT_PRODUCER): Remove, was never really used.
+ * eval.c (evaluate_subexp): For STRUCTOP_PTR pass the arg type
+ directly to lookup_struct_elt_type, which will do the
+ dereferencing itself.
+ * gdbtypes.c (lookup_struct_elt_type): Expand comments. Fix
+ NULL dereferencing bug for unnamed structs, comment out
+ questionable code.
+
+Mon Mar 1 17:54:41 1993 John Gilmore (gnu@cygnus.com)
+
+ * coffread.c (process_coff_symbol): Change PCC argument correction
+ so that it only happens on big-endian targets; so that it only
+ happens if the short or char argument is aligned on an int
+ boundary; and so that it changes the location, rather than the
+ type, of the argument. These changes tend to parallel similar
+ (old) changes in stabsread.c.
+
+ * coffread.c (coff_read_enum_type): Use the specified size for
+ enums, don't assume that they are int-sized.
+
+ * c-valprint.c (c_val_print): Don't assume enums are the same as
+ ints.
+
+ * coredep.c: Handle NO_PTRACE_H in coredep.c. Fix by Michael
+ Rendell, <michael@mercury.cs.mun.ca>.
+
+Mon Mar 1 09:25:57 1993 Fred Fish (fnf@cygnus.com)
+
+ * language.h (local_decimal_format_custom): Add prototype.
+ * language.c (local_decimal_format_custom): Add function, bug
+ reported by Robert R. Henry (rrh@tera.com).
+
+Fri Feb 26 18:33:18 1993 John Gilmore (gnu@cacophony.cygnus.com)
+
+ * xcoffexec.c (vmap_ldinfo): Fix "/" for '/' typo, reported
+ by Josef Leherbauer, joe@takeFive.co.at.
+
+Wed Feb 24 19:17:11 1993 John Gilmore (gnu@cacophony.cygnus.com)
+
+ * symfile.c (syms_from_objfile), tm-29k.h, tm-3b1.h, tm-68k-un.h,
+ tm-altos.h, tm-arm.h, tm-convex.h, tm-es1800.h, tm-h8300.h,
+ tm-hp300bsd.h, tm-hp300hpux.h, tm-hppa.h, tm-i386bsd.h,
+ tm-i386v.h, tm-i960.h, tm-irix3.h, tm-isi.h, tm-linux.h,
+ tm-m88k.h, tm-merlin.h, tm-mips.h, tm-news.h, tm-np1.h, tm-pn.h,
+ tm-pyr.h, tm-rs6000.h, tm-spc-un.h, tm-sun386.h, tm-sunos.h,
+ tm-symmetry.h, tm-sysv4.h, tm-tahoe.h, tm-umax.h, tm-vax.h,
+ tm-vx68.h, tm-z8k.h: Remove remnants of NAMES_HAVE_UNDERSCORE.
+
+Wed Feb 24 07:41:15 1993 Fred Fish (fnf@cygnus.com)
+
+ * symtab.h (SYMBOL_INIT_DEMANGLED_NAME): Initialize contents
+ of demangled name fields to NULL if no demangling exists for
+ a symbol. SYMBOL_INIT_LANGUAGE_SPECIFIC does this for new
+ symbols if their language is known at the time they are created,
+ but sometimes the language is not known until later.
+
+ * ch-typeprint.c (chill_print_type_base): Name changed to
+ chill_type_print_base to match pattern for C and C++ names.
+ * ch-typeprint.c (chill_print_type): Change "char" to "CHAR"
+ to be consistent with other usages.
+ * ch-typeprint.c (chill_type_print_base): Add support for
+ printing Chill STRUCT types.
+ * ch-valprint.c: Include values.h.
+ * ch-valprint.c (chill_print_value_fields): New function and
+ prototype for printing Chill STRUCT values.
+ * ch-valprint.c (chill_val_print): Fix call to val_print_string
+ that was being called with two args instead of three.
+ * ch-valprint.c (chill_val_print): Call chill_print_value_fields
+ to print Chill STRUCT values.
+
+Tue Feb 23 18:58:11 1993 Mike Werner (mtw@poseidon.cygnus.com)
+
+ * configure.in: added testsuite to configdirs.
+
+Tue Feb 23 11:46:11 1993 Mike Stump (mrs@cygnus.com)
+
+ * doc/stabs.texi: The `this' pointer is now known by the name
+ `this' instead of `$t'.
+
+Tue Feb 23 11:21:33 1993 Fred Fish (fnf@cygnus.com)
+
+ * dwarfread.c (read_tag_string_type): Rewrite to allow forward
+ references of TAG_string_type DIEs in user defined types.
+ * ch-lang.c (chill_create_fundamental_type): Track compiler
+ change that now emits debugging info with the type long for Chill
+ longs.
+
+Mon Feb 22 15:21:54 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * remote-mips.c: New file; implements MIPS remote debugging
+ protocol.
+ * config/idt.mt: New file; uses remote-mips.c
+ * configure.in (mips-idt-ecoff): New target; uses idt.mt.
+
+ * mips-tdep.c (mips_fpu): New variable; controls use of MIPS
+ floating point coprocessor.
+ (mips_push_dummy_frame): If not mips_fpu, don't save floating
+ point registers.
+ (mips_pop_frame): If not mips_fpu, don't restore floating point
+ registers.
+ (_initialize_mips_tdep): New function; let the user reset mips_fpu
+ variable.
+ * tm-mips.h (EXTRACT_RETURN_VALUE, STORE_RETURN_VALUE): If not
+ mips_fpu, don't use fp0 as floating point return register.
+ (FIX_CALL_DUMMY): If not mips_fpu, don't save floating point
+ registers.
+
+Mon Feb 22 07:54:03 1993 Mike Werner (mtw@poseidon.cygnus.com)
+
+ * gdb/testsuite: made modifications to testcases, etc., to allow
+ them to work properly given the reorganization of deja-gnu and the
+ relocation of the testcases from deja-gnu to a "tool" subdirectory.
+
+Sun Feb 21 10:55:55 1993 Mike Werner (mtw@poseidon.cygnus.com)
+
+ * gdb/testsuite: Initial creation of gdb/testsuite.
+ Migrated dejagnu testcases and support files for testing nm to
+ gdb/testsuite from deja-gnu. These files were moved "as is"
+ with no modifications. This migration is part of a major overhaul
+ of dejagnu. The modifications to these testcases, etc., which
+ will allow them to work with the new version of dejagnu will be
+ made in a future update.
+
+Fri Feb 19 18:36:55 1993 John Gilmore (gnu@cygnus.com)
+
+ * NEWS: Add reminders for next release.
+
+Fri Feb 19 10:01:39 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * mipsread.c (parse_lines): Correct check for files compiled with
+ -g1.
+
+Fri Feb 19 05:56:15 1993 John Gilmore (gnu@cygnus.com)
+
+ * Makefile.in (VERSION): 4.8.1 to distinguish local versions.
+
+Fri Feb 19 01:32:58 1993 John Gilmore (gnu@cygnus.com)
+
+ * Makefile.in (VERSION): GDB-4.8 release!
+ * README, NEWS: Update for release.
+
+Thu Feb 18 22:44:40 1993 Stu Grossman (grossman@cygnus.com)
+
+ * am29k-pinsn.c (print_insn): Minor nits with const.
+ * am29k-tdep.c: More minor nits with arg types for
+ supply_register, NULL vs. 0, read_register_gen, & reginv_com.
+
+Thu Feb 18 22:38:03 1993 John Gilmore (gnu@cygnus.com)
+
+ * gcc.patch: Update for a different GCC (G++) bug.
+ * main.c (print_gdb_version): Update copyright year to 1993.
+ * nm-hp300bsd.h: Decide whether this is BSD 4.3 or 4.4,
+ conditionalize this file on it. FIXME, right way is to split
+ these into two config files.
+ (ATTACH_DETACH): Define for BSD 4.4
+ (PTRACE_ARG_TYPE): caddr_t for BSD 4.4, unset for 4.3.
+ (U_REGS_OFFSET): Revise for 4.4.
+ (REGISTER_U_ADDR): Separate for 4.4, but it doesn't work yet.
+ * xm-hp300bsd.h: Move definitions of UINT_MAX, INT_MAX, INT_MIN,
+ LONG_MAX into this file to avoid cpp "redefinition" warnings.
+
+Thu Feb 18 16:13:28 1993 K. Richard Pixley (rich@rtl.cygnus.com)
+
+ * nm-hp300bsd.h (PTRACE_ARG3_TYPE): FSF's hp300's have int* not
+ caddr_t.
+
+Thu Feb 18 04:10:06 1993 John Gilmore (gnu@cygnus.com)
+
+ * c-lang.c (c_printstr): Bugfix for length==0 case.
+
+ * c-lang.c (c_printstr): If a C string ends in a null, don't
+ print the null.
+
+Thu Feb 18 02:39:21 1993 Stu Grossman (grossman at cygnus.com)
+
+ * defs.h (STRCMP): Make it work for unsigned chars.
+
+Thu Feb 18 01:56:06 1993 John Gilmore (gnu@cygnus.com)
+
+ * nm-hp300bsd.h (ATTACH_DETACH, PTRACE_ATTACH, PTRACE_DETACH): define.
+ * config/hp300bsd.mh (REGEX, REGEX1): Define.
+ * m68k-pinsn.c (BREAK_UP_BIG_DECL, AND_OTHER_PART): #if __GNUC__,
+ define to kludge the large opcode table into two smaller tables,
+ since GCC take exponential space to build the table. Lint.
+ (NOPCODES): Remove, use "numopcodes" from opcode/m68k.h instead.
+
+Wed Feb 17 19:24:40 1993 John Gilmore (gnu@cygnus.com)
+
+ * Makefile.in (VERSION): Roll to 4.7.9.
+ * xm-hp300bsd.h: Define PSIGNAL_IN_SIGNAL_H and put a compatible
+ definition here, to handle both BSD 4.3 and 4.4 systems.
+ * mipsread.c (ZMAGIC): #undef to avoid duplicate define.
+ * remote.c (alarm): Move declaration to global level, before
+ first reference to it.
+ * tm-i386bsd.h (NUM_REGS): There are only eleven, not twelve.
+ * dbxread.c (process_one_symbol): Cast to unsigned char, not int.
+
+Wed Feb 17 13:40:29 1993 K. Richard Pixley (rich@cygnus.com)
+
+ * remote.c (readchar): forward declare alarm which otherwise looks
+ like an undeclared variable to gcc.
+
+ * dbxread.c (process_one_symbol): cast enum value N_SO into int
+ when comparing against an int. Avoids superfluous warning from
+ vax ultrix 4.2 cc.
+
+ * inflow.c (set_sigint_trap): add cast to assignment from signal.
+ Avoids superfluous warnings from some systems and/or compilers
+ (like vax ultrix 4.2.)
+
+ * language.c (struct op_print unk_op_print_tab): use the enum
+ values rather naked zeros as initializers. Avoids warnings from
+ ultrix type compilers.
+
+Tue Feb 16 00:53:20 1993 John Gilmore (gnu@cygnus.com)
+
+ * Makefile.in (VERSION): Roll to 4.7.6.
+ (SFILES_SUBDIR): Add 29k-share/udi_soc.
+ (SFILES_SUBSUBDIR): Move 29k-share/udi files to this macro.
+ (alldeps.mak): Make ALLDEPFILES_SUBSUBDIR for files in sub sub dirs.
+ (ALLDEPFILES_SUBSUBDIR): Depend on this for deeper dep files.
+ (HFILES): Remove all nm-* except nm-trash.h. Add ns32k-opcode.h.
+ (depend): Fix bug where nm-files in config files weren't noticed.
+ (make-proto-gdb-1): Avoid changing directories while building new
+ prototype. Build SFILES_SUBSUBDIR with longer symlinks.
+
+Mon Feb 15 20:48:09 1993 John Gilmore (gnu@cygnus.com)
+
+ * remote.c: Improve error recovery. Allow user to break out
+ of initial connection attempt with INTERRUPT. Treat a timeout
+ while waiting for remote packet like a retry, unless the remote
+ side is actively running user code. Fix a few long printf_filtered's.
+
+ * xcoffread.c (read_xcoff_symtab): Don't use null symbol name for
+ trampoline symbols.
+
+ * buildsym.c (start_subfile): Allow null file name.
+
+Fri Feb 12 15:46:49 1993 K. Richard Pixley (rich@cygnus.com)
+
+ * xcoffread.c (process_xcoff_symbol, read_symbol_lineno): complain
+ expects a pointer to complaint rather than a complaint
+ structure.
+ (process_linenos): free the previously allocated subfile name,
+ then allocate the new one from the heap.
+
+Fri Feb 12 08:06:05 1993 Steve Chamberlain (sac@thepub.cygnus.com)
+
+ * h8300-tdep.c, tm-h8300.h: turn off some experimental features
+
+Thu Feb 11 00:59:07 1993 John Gilmore (gnu@cygnus.com)
+
+ * stabsread.c (dbx_lookup_type): Handle negative type numbers.
+ Previously, would bogusly index off the bottom of type_vector.
+ (rs6000_builtin_type): Accept type number as argument.
+ (read_type, case '-'): Handle negatives like any other type number.
+
+ * symfile.c (deduce_language_from_filename): Handle null name.
+
+ * mips-tdep.c (isa_NAN): Fix byte order dependency.
+ Reported by Nobuyuki Hikichi <hikichi@sra.co.jp>,
+ fixed by sato@sm.sony.co.jp.
+
+ * xcoffread.c (parmsym): Don't use an initializer to set up
+ this struct symbol. Set it up in initialize_xcoffread.
+ (read_xcoff_symtab, xcoff_symfile_read): Surround code that only
+ works on real rs/6000 target with #ifndef FAKING_RS6000.
+
+Wed Feb 10 23:42:37 1993 John Gilmore (gnu@cygnus.com)
+
+ * stabsread.c (rs6000_builtin_type): Move function from
+ xcoffread.c:builtin_type.
+ * xcoffread.c (builtin_type): Move to stabsread. Remove
+ IBM6000_HOST dependency. Move misplaced comments.
+ (various): Change printf's to complaints.
+ (patch_block_stabs, process_xcoff_symbol case C_DECL): Add
+ objfile argument to read_type calls under #if 0.
+ (process_xcoff_symbol case C_RSYM): Fix typo in #ifdef.
+ * xcoffexec.c (map_vmap): Don't allocate an objfile for the exec_file.
+ * Makefile.in: xcoffread.o is not built by default.
+ * xm-rs6000.h (IBM6000_HOST): Remove.
+ * config/rs6000.mh (NATDEPFILES): xcoffread.o is native only.
+ * doc/gdbint.texinfo: Eliminate IBM6000_HOST, document
+ IBM6000_TARGET.
+
+Wed Feb 10 18:31:20 1993 Stu Grossman (grossman at cygnus.com)
+
+ * findvar.c (read_var_value): If REG_STRUCT_HAS_ADDR, then set
+ VALUE_LVAL to be lval_memory so that we don't try to modify wild
+ register numbers when user tries to modify elements in structs
+ passed as arguments.
+ * inflow.c (child_terminal_info): Move banner outside of system
+ specific #ifdefs.
+ * tm-hppa.h (REG_STRUCT_HAS_ADDR): Define this for HPPA, which
+ passes struct/union arguments by address.
+
+Wed Feb 10 15:34:46 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * Based on patch from Kean Johnston <maw@netcom.com>:
+ * nm-i386sco4.h: New file. Like nm-i386sco.h, but define
+ ATTACH_DETACH, PTRACE_ATTACH and PTRACE_DETACH.
+ * config/i386sco4.mh (NAT_FILE): Use nm-i386sco4.h.
+
+Tue Feb 9 20:07:18 1993 John Gilmore (gnu@cygnus.com)
+
+ * remote-udi.c (FREEZE_MODE): Fix && for & typo. Found and
+ fixed by Lynn D. Shumaker, shumaker@saifr00.cfsat.honeywell.com.
+
+Tue Feb 9 08:18:07 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * config/i386sco4.mh (MUNCH_DEFINE): Pass -p to nm to avoid bug in
+ cc debugging output.
+
+Tue Feb 9 00:19:28 1993 John Gilmore (gnu@cygnus.com)
+
+ * stabsread.c (define_symbol): Complain about unrecognized names
+ that begin with CPLUS_MARKER (often '$'), but don't die. Fix
+ suggested by gb@cs.purdue.edu (Gerald Baumgartner).
+ (read_cpp_abbrev): Don't use the class name as part of the
+ vtable pointer member name (_vptr$) in $vf abbrevs or unrecognized
+ abbrevs. Inspired by Mike Tiemann.
+ (read_tilde_fields): Comment. Remove ancient dead code.
+ Remove erroneous but non-dead code. Simplify. Add complaints.
+ (in general): Remove extraneous (parentheses) in return
+ statements.
+
+Fri Feb 5 14:01:22 1993 John Gilmore (gnu@cygnus.com)
+
+ * coffread.c (coff_lookup_type): Fix fencepost error reported
+ by Art Berggreen, <arg@opal.acc.com>.
+
+ Fix long file name bug reported on SCO Open Desktop 2.0 by Ulf Lunde
+ <Ulf.Lunde@kvatro.no> and Dag H. Wanvik <Dag.H.Wanvik@kvatro.no>:
+
+ * coffread.c (getfilename): Eliminate COFF_NO_LONG_FILE_NAMES
+ test, which is apparently left over from when we used native
+ include files and couldn't depend on the member names being there.
+ * tm-3b1.h, tm-altos.h, tm-i386v.h: Don't set it.
+
+Thu Feb 4 12:23:15 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * mipsread.c: Major overhaul to use new BFD symbol table reading
+ routines. Now swaps information as it is needed, rather than
+ swapping everything when the file is read.
+
+Thu Feb 4 01:52:36 1993 John Gilmore (gnu@cygnus.com)
+
+ * Makefile.in (TARDIRS): Add sparclite demo dir.
+ (*.tab.c): Change dependency on Makefile to depend on
+ Makefile.in, otherwise it always rebuilds after configuring.
+ Force output *.tab.c file into current directory even in "make"
+ versions that rewrite dependent file names used in command lines.
+
+ * TODO: Remove some things we did.
+ * am29k-opcode.h, convx-opcode: Remove; now in ../include/opcode.
+ * os68k-xdep.c: Remove; useless file (os68k is a target only).
+ * convex-pinsn.c: Use ../include/opcode/convex.h. Add CONST.
+ * symtab.h: Eliminate unnamed unions and structs.
+
+Wed Feb 3 14:48:08 1993 John Gilmore (gnu@cygnus.com)
+
+ * Makefile.in (VERSION): Roll to 4.7.5.
+
+Tue Feb 2 20:47:42 1993 John Gilmore (gnu@cygnus.com)
+
+ * breakpoint.c (breakpoint_re_set_one): Handle watchpoints when
+ re-evaluating symbol pointers.
+
+Tue Feb 2 16:10:31 1993 Fred Fish (fnf@cygnus.com)
+
+ * c-exp.y (lcurly, rcurly): New nonterminals.
+ * c-exp.y (exp): Use lcurly and rcurly for arrays and UNOP_MEMVAL
+ constructs.
+ * parse.c (free_funcalls): Moved prototype from parser-defs.h,
+ made function static.
+ * parse.c (struct funcall): Moved struct def from parser-defs.h.
+ * parse.c (funcall_chain): Moved from parser-defs.h, made static.
+ * parse.c (start_arglist):
+ * parser-defs.h (free_funcalls): Moved prototype to parse.c.
+ * parser-defs.h (struct funcall): Moved struct def to parse.c.
+ * parser-defs.h (funcall_chain): Moved to parse.c.
+ * printcmd.c (print_frame_nameless_args): Fix prototype.
+ * tm-mips.h (setup_arbitrary_frame): Fix prototype.
+ * tm-sparc.h (setup_arbitrary_frame): Fix prototype.
+ * valops.c (typecmp): Moved prototype from values.h.
+ * value.h (typecmp): Moved prototype to valops.c, made static.
+ * ch-exp.y (yylex): Change way control sequences are disabled.
+
+Tue Feb 2 16:11:43 1993 John Gilmore (gnu@cygnus.com)
+
+ * tm-mips.h, tm-sparc.h: Fix thinko in SETUP_ARBITRARY_FRAME.
+
+Tue Feb 2 15:30:33 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * mipsread.c (upgrade_type): Build array types correctly, using
+ create_range_type and create_array_type.
+
+Tue Feb 2 00:19:08 1993 John Gilmore (gnu@cygnus.com)
+
+ * remote-nindy.c: Cleanup.
+
+ * infrun.c (wait_for_inferior): When rolling back the PC after
+ a breakpoint, call write_pc so that NPC gets rolled back as well
+ (for the 29K).
+
+ * blockframe.c (inside_entry_file, inside_main_func,
+ inside_entry_func): PC of zero is always "bottom of stack".
+
+ * printcmd.c (print_frame_args, print_frame_nameless_args):
+ Let print_frame_nameless_args decide whether there are any,
+ laying groundwork for possibly later printing 29K args for
+ functions where we have tag words but no symbols.
+
+Mon Feb 1 18:09:58 1993 Roland H. Pesch (pesch@fowanton.cygnus.com)
+
+ * Makefile.in: fix GDB doc targets for new doc subdir structure
+
+Mon Feb 1 17:56:47 1993 John Gilmore (gnu@cygnus.com)
+
+ * stack.c (parse_frame_specification): Parse as many arguments
+ as there are (up to MAXARGS). Pass all of them in argc, argv
+ format to SETUP_ARBITRARY_FRAME. Put the burden of checking how
+ many there were, onto SETUP_ARBITRARY_FRAME.
+ * tm-mips.h, tm-sparc.h: Corresponding changes.
+ * mips-tdep.c, sparc-tdep.c: Ditto.
+
+Mon Feb 1 17:19:37 1993 John Gilmore (gnu@cygnus.com)
+
+ * hp300ux-nat.c: Update copyrights.
+ * mipsread.c (parse_partial_symbols): Complain about block
+ indexes that go backwards. Fix from Peter Schauer.
+ * symfile.c (syms_from_objfile, symbol_file_add): Allow a
+ symbol-file that has no linkage symbols to be read.
+ * tm-rs6000.h, xm-rs6000.h: (SIGWINCH_HANDLER and friends): Move
+ from tm- file to xm-file, since they're host dependent.
+ * valarith.c (value_binop): Typo.
+
+Mon Feb 1 16:16:59 1993 Stu Grossman (grossman at cygnus.com)
+
+ * sparclite/aload.c: Add copyleft.
+ * sparclite/crt0.s: Add comment at beginning.
+
+Mon Feb 1 14:36:11 1993 Steve Chamberlain (sac@thepub.cygnus.com)
+
+ * remote-z8k.c, z8k-tdep.c: support for the Z8001 and Z8002.
+ * parse.c (std_regs): Only declare if NO_STD_REGS is defined.
+
+Sun Jan 31 04:32:48 1993 Michael Tiemann (tiemann@rtl.cygnus.com)
+
+ * values.c (value_headof): Fix typo in which VTBL and ARG were
+ being confused for one another.
+
+ * valops.c (typecmp): Now static.
+
+ * gdbtypes.c (fill_in_vptr_fieldno): Don't ignore the first
+ baseclass--we don't always inherit its virtual function table
+ pointer.
+
+ * eval.c (evaluate_subexp): In OP_FUNCALL case, adjust `this'
+ pointer correctly in case value_struct_elt moves it around.
+
+ * valops.c (typecmp): Now static. Also, now groks references
+ better.
+
+ * gdbtypes.c (lookup_struct_elt_type): Pass NOERR instead of
+ zero on recursive call. If NAME is the name of TYPE, return TYPE.
+
+Sat Jan 30 19:55:52 1993 John Gilmore (gnu@cygnus.com)
+
+ * hppah-nat.c: Eliminate <sys/user.h> and other unnecessary stuff,
+ to avoid "too much defining" error from native C compiler (!).
+
+ * Makefile.in (HFILES): Add typeprint.h.
+ * typeprint.[ch]: Update copyrights.
+
+Thu Jan 28 19:09:02 1993 John Gilmore (gnu@cygnus.com)
+
+ * Makefile.in: Update to match doc/ subdir changes.
+
+ * config/hp300hpux.mh: No cross-host file needed, just native.
+ * config/go32.mh: Remove nonexistent "native" support.
+
+ M88K fixes reported by Carl Greco, <cgreco@Creighton.Edu>:
+ * tm-m88k.h (REGISTER_CONVERT_TO_RAW): Fix typo.
+ * m88k-tdep.c (next_insn): Lint, cleanup.
+ (store_parm_word): Lint.
+
+ * README: Fix typo (reported by karl@hq.ileaf.com).
+
+Wed Jan 27 21:34:21 1993 Fred Fish (fnf@cygnus.com)
+
+ * expression.h (BINOP_CONCAT): Document use for self concatenation
+ an integral number of times.
+ * language.c (binop_type_check): Extend BINOP_CONCAT for self
+ concatenation case.
+ * valarith.c (value_concat): Rewrite to support self
+ concatenation an integral number of times.
+ * Makefile.in (ch-exp.tab.c): Change "expect" message.
+ * ch-exp.y (FIXME's): Make all FIXME tokens distinct, to
+ eliminate hundreds of spurious shift/reduce and reduce/reduce
+ conflicts that mask the 5 real ones.
+ * ch-exp.y (STRING, CONSTANT, SC): Remove unused tokens.
+ * ch-exp.y (integer_literal_expression): Remove production,
+ no longer used.
+
+Thu Jan 21 09:58:36 1993 Fred Fish (fnf@cygnus.com)
+
+ * eval.c (evaluate_subexp): Fix OP_ARRAY, remove code that
+ implied that "no side effects" was nonfunctional.
+ * eval.c (evaluate_subexp): Add BINOP_CONCAT case to deal with
+ character string and bitstring concatenation.
+ * expprint.c (dump_expression): Add case for BINOP_CONCAT.
+ * expression.h (exp_opcode): Add BINOP_CONCAT.
+ * gdbtypes.h (type_code): Add TYPE_CODE_BITSTRING.
+ * language.c (string_type): Add function to determine if a type
+ is a string type.
+ * language.c (binop_type_check): Add case for BINOP_CONCAT.
+ * valarith.c (value_concat): New function to concatenate two
+ values, such as character strings or bitstrings.
+ * valops.c (value_string): Remove error stub and implement
+ function body.
+ * value.h (value_concat): Add prototype.
+ * ch-exp.y (operand_3): Add actions for SLASH_SLASH (//).
+ * ch-exp.y (yylex): Recognize SLASH_SLASH.
+ * ch-lang.c (chill_op_print_tab): Add SLASH_SLASH (//) as
+ BINOP_CONCAT.
+
+Tue Jan 19 14:26:15 1993 Fred Fish (fnf@cygnus.com)
+
+ * c-exp.y (exp): Add production to support direct creation
+ of array constants using the obvious syntax.
+ * c-valprint.c (c_val_print): Set printed string length.
+ * dwarfread.c (read_tag_string_type): New prototype and
+ function that handles TAG_string_type DIEs.
+ * dwarfread.c (process_dies): Add case for TAG_string_type
+ that calls new read_tag_string_type function.
+ * expprint.c (print_subexp): Add support for OP_ARRAY.
+ * gdbtypes.c (create_range_type, create_array_type): Inherit
+ objfile from the index type.
+ * ch-typeprint.c (chill_print_type): Add case for
+ TYPE_CODE_STRING.
+ * ch-valprint.c (chill_val_print): Fix case for
+ TYPE_CODE_STRING.
+
+Mon Jan 18 11:58:45 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * mipsread.c (CODE_MASK, MIPS_IS_STAB, MIPS_MARK_STAB,
+ MIPS_UNMARK_STAB, STABS_SYMBOLS): Removed; now in
+ include/coff/mips.h.
+
+Fri Jan 15 20:26:50 1993 Fred Fish (fnf@cygnus.com)
+
+ * c-exp.y (exp:STRING): Convert C strings into array-of-char
+ constants with an explicit null byte terminator. OP_STRING is
+ now used for real string types.
+ * c-lang.c (builtin_type_*): Move declarations to lang.c since
+ they are used by all languages.
+ * c-lang.c (_initialize_c_language): Move initializations of
+ builtin_type_* to lang.c.
+ * c-typeprint.c (c_type_print_varspec_prefix,
+ c_type_print_varspec_suffix): TYPE_CODE_PASCAL_ARRAY renamed
+ to TYPE_CODE_STRING.
+ * c-valprint.c (c_val_print): Change the way character arrays
+ are printed as strings to be consistent with the way strings
+ are printed when pointer-to-char types are dereferenced.
+ Remove test of print_max before calling val_print_string, which
+ now does it's own test.
+ * eval.c (evaluate_subexp): Add case for OP_ARRAY.
+ * expprint.c (print_subexp, dump_expression): Add case for OP_ARRAY.
+ * expression.h (enum exp_opcode): Add OP_ARRAY and document.
+ * gdbtypes.c (builtin_type_*): Add declarations moved from
+ c-lang.c.
+ * gdbtypes.c (create_string_type): New function to create real
+ string types.
+ * gdbtypes.c (recursive_dump_type): TYPE_CODE_PASCAL_ARRAY
+ renamed to TYPE_CODE_STRING.
+ * gdbtypes.c (_initialize_gdbtypes): Add initializations of
+ builtin_type_* types moved from c-lang.c.
+ * gdbtypes.h (enum type_code): TYPE_CODE_PASCAL_ARRAY renamed
+ to TYPE_CODE_STRING.
+ * gdbtypes.h (builtin_type_string): Add extern declaration.
+ * gdbtypes.h (create_string_type): Add prototype.
+ * m2-lang.c (m2_create_fundamental_type): TYPE_CODE_PASCAL_ARRAY
+ renamed to TYPE_CODE_STRING.
+ * m88k-tdep.c (pushed_size): TYPE_CODE_PASCAL_ARRAY renamed to
+ TYPE_CODE_STRING.
+ * mipsread.c (_initialize_mipsread): TYPE_CODE_PASCAL_ARRAY
+ renamed to TYPE_CODE_STRING.
+ * parse.c (length_of_subexp, prefixify_subexp): Add case for
+ OP_ARRAY.
+ * printcmd.c (print_formatted): Recognize TYPE_CODE_STRING.
+ * typeprint.c (print_type_scalar): TYPE_CODE_PASCAL_ARRAY renamed
+ to TYPE_CODE_STRING.
+ * valops.c (allocate_space_in_inferior): New function and
+ prototype, using code ripped out of value_string.
+ * valops.c (value_string): Rewritten to use new function
+ allocate_space_in_inferior, but temporarily disabled until some
+ other support is in place.
+ * valops.c (value_array): New function to create array constants.
+ * valprint.c (val_print_string): Add comment to document use,
+ complete rewrite to fix several small buglets.
+ * value.h (value_array): Add prototype.
+ * value.h (val_print_string): Change prototype to match rewrite.
+ * ch-valprint.c (chill_val_print): Add case for TYPE_CODE_STRING.
+ * ch-exp.y (match_character_literal): Disable recognition of
+ control sequence form of character literals and document why.
+
+Thu Jan 14 15:48:12 1993 Stu Grossman (grossman at cygnus.com)
+
+ * nindy-share/nindy.c: Add comments to #endif's to clarify
+ grouping.
+
+ * hppa-pinsn.c (print_insn): Use read_memory_integer, instead of
+ read_memory to get byte order right.
+ * hppah-tdep.c (find_unwind_info): Don't read in unwind info
+ anymore. This is done in paread.c now. We expect unwind info
+ to hang off of objfiles, and search all of the objfiles when until
+ we find a match.
+ * (skip_trampoline_code): Cast arg to target_read_memory.
+ * objfiles.h (struct objfile): Add new field obj_private to hold
+ per object file private data (unwind info in this case).
+ * paread.c (read_unwind_info): New routine to read unwind info
+ for the objfile. This data is hung off of obj_private.
+ * tm-hppa.h: Define struct obj_unwind_info, to hold pointers to
+ the unwind info for this objfile. Also define OBJ_UNWIND_INFO to
+ make this easier to access.
+
+Wed Jan 13 20:49:59 1993 Fred Fish (fnf@cygnus.com)
+
+ * c-valprint.c (cp_print_class_member): Add extern decl.
+ * c-valprint.c (c_val_print): Extract code for printing methods
+ and move it to cp_print_class_method in cp-valprint.c.
+ * c-valprint.c (c_val_print): Extract code to print strings and
+ move it to val_print_string in valprint.c.
+ * cp-valprint.c (cp_print_class_method): New function using
+ code extracted from c_val_print.
+ * valprint.c (val_print_string): New function using code
+ extracted from c_val_print.
+ * value.h (val_print_string): Add prototype.
+ * ch-exp.y (CHARACTER_STRING_LITERAL): Set correct token type.
+ * ch-exp.y (literal): Add action for CHARACTER_STRING_LITERAL.
+ * ch-exp.y (tempbuf, tempbufsize, tempbufindex, GROWBY_MIN_SIZE,
+ CHECKBUF, growbuf_by_size): New variables, macros, and support
+ functions for implementing a dynamically expandable temp buffer.
+ * ch-exp.y (match_string_literal): New lexer function.
+ * ch-exp.y (match_bitstring_literal): Dynamic buffer code
+ removed and replaced with new CHECKBUF macro.
+ * ch-exp.y (yylex): Call match_string_literal when appropriate.
+ * ch-valprint.c (ch_val_print): Add code for TYPE_CODE_PTR.
+
+Sat Jan 9 19:59:33 1993 Stu Grossman (grossman at cygnus.com)
+
+ * Makefile.in: Add info for paread.o.
+ * config/hppahpux.mh: Add paread.o to NATDEPFILES.
+
+ * blockframe.c (frameless_look_for_prologue): Correct the
+ comment.
+ * gdbtypes.h, gdbtypes.c: Use const in decl of
+ cplus_struct_default, now that pa-gas assembler has been fixed.
+ * hppah-nat.c: Formatting.
+ * hppah-tdep.c: Remove lots of useless externs for variables we
+ don't use.
+ * (find_unwind_entry): Speed up by using binary search, and a one
+ entry cache.
+ * (rp_saved): New routine to see what unwind info says about RP
+ being saved on the stack frame.
+ * (frame_saved_pc): Look for prologue to see if we need to
+ examine the stack for the saved RP or not.
+ * (init_extra_frame_info): Check for prologue, instead of
+ framesize to determine if we are frameless or not.
+ * (frame_chain_valid): Stop backtraces when we run into _start.
+ * (push_dummy_frame): Reformat to make more readable.
+ * (find_dummy_frame_regs): ditto.
+ * (hp_pop_frame): ditto.
+ * (hp_restore_pc_queue): small cleanup.
+ * (hp_push_arguments): ditto.
+ * (pa_do_registers_info): ditto.
+ * (skip_prologue): New routine created from SKIP_PROLOGUE macro.
+ * tm-hppa.h: Move contents of SKIP_PROLOGUE into hppah-tdep.c.
+ * Define FRAME_CHAIN_VALID.
+ * Turn on BELIEVE_PCC_PROMOTION so that we can access char args
+ passed to functions.
+
+ * paread.c (pa_symtab_read): Use new bfd conventions for
+ accessing linker symbol table.
+ * (pa_symfile_init): Access embedded STAB info via BFD section
+ mechanism and related macros.
+
+
+Sat Jan 9 19:31:43 1993 Stu Grossman (grossman at cygnus.com)
+
+ * sparc-stub.c: Use a seperate stack for our traps.
+ * Handle recursive traps.
+ * Remove all trap init code. This needs to be done by the
+ environment.
+ * (set_mem_fault_trap): Call exceptionHandler() to setup this
+ trap.
+ * (handle_exception): See if we are at breakinst, if so, then
+ advance PC sp that users can just step out of breakpoint().
+ * (case 'G'): Don't let GDB hack CWP. Also, copy saved regs to
+ new place if SP has changed.
+ * (case 's'): Get rid of this, we can't do it yet.
+ * (case 't'): New command to test any old random feature.
+ * (case 'r'): New command to reset the system.
+ * (breakpoint): Add label to breakpoint trap instruction so that
+ handle_exception() can detect where we are and get past the
+ breakpoint trivially.
+
+Thu Jan 7 13:33:06 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * mips-pinsn.c: Actual work now done by opcodes/mips-dis.c.
+
+Thu Jan 7 09:21:51 1993 david d `zoo' zuhn (zoo at cirdan.cygnus.com)
+
+ * configure.in: recognise all sparclite variants
+
+Wed Jan 6 10:14:51 1993 Steve Chamberlain (sac@thepub.cygnus.com)
+
+ * symfile.c: If O_BINARY isn't defined, set it to 0, call openp for
+ binary files oring in the right bit.
+
+ * main.c, source.c, state.c, symmisc.c: use macros defined in
+ fopen-{bin|both} when fopening files.
+
+Wed Jan 6 08:19:11 1993 Fred Fish (fnf@cygnus.com)
+
+ * defs.h (HOST_CHAR_BIT): New macro, defaults to either CHAR_BIT
+ from a configuration file (typically including <limits.h>), or to
+ TARGET_CHAR_BIT if CHAR_BIT is not defined.
+ * eval.c (evaluate_subexp): Use new BYTES_TO_EXP_ELEM macro.
+ * eval.c (evaluate_subexp): Add case for OP_BITSTRING.
+ * expprint.c (print_subexp): Use new BYTES_TO_EXP_ELEM macro.
+ * exppritn.c (print_subexp, dump_expression): Add case for
+ OP_BITSTRING.
+ * expression.h (OP_BITSTRING): New expression element type for
+ packed bitstrings.
+ * expression.h (EXP_ELEM_TO_BYTES, BYTES_TO_EXP_ELEM): New
+ macros to convert between number of expression elements and bytes
+ to store that many elements.
+ * i960-tdep.c (leafproc_return): Use new macros to access
+ minimal symbol name and address fields.
+ * m88k-pinsn.c (sprint_address): Use new macros to access
+ minimal symbol name and address fields.
+ * nindy-tdep.c (nindy_frame_chain_valid): Use new macro to access
+ minimal symbol address field.
+ * parse.c (write_exp_elt, write_exp_string, prefixify_expression,
+ parse_exp_1): Use new EXP_ELEM_TO_BYTES macro.
+ * parse.c (write_exp_string, length_of_subexp, prefixify_expression):
+ Use new BYTES_TO_EXP_ELEM macro.
+ * parse.c (write_exp_bitstring): New function to write packed
+ bitstrings into the expression element vector.
+ * parse.c (length_of_subexp, prefixify_subexp): Add case for
+ OP_BITSTRING.
+ * parser-defs.h (struct stoken): Document that it is used for
+ OP_BITSTRING as well as OP_STRING.
+ * parser-defs.h (write_exp_bitstring): Add prototype.
+ * ch-exp.y (BIT_STRING_LITERAL): Change token type to sval.
+ * ch-exp.y (NUM, PRED, SUCC, ABS, CARD, MAX, MIN, SIZE, UPPER,
+ LOWER, LENGTH): New tokens for keywords.
+ * ch-exp.y (chill_value_built_in_routine_call, mode_argument,
+ upper_lower_argument, length_argument, array_mode_name,
+ string_mode_name, variant_structure_mode_name): New non-terminals
+ and productions.
+ * ch-exp.y (literal): Useful production for BIT_STRING_LITERAL.
+ * ch-exp.y (match_bitstring_literal): New lexer support function
+ to recognize bitstring literals.
+ * ch-exp.y (tokentab6): New token table for 6 character keywords.
+ * ch-exp.y (tokentab5): Add LOWER, UPPER.
+ * ch-exp.y (tokentab4): Add PRED, SUCC, CARD, SIZE.
+ * ch-exp.y (tokentab3): Add NUM, ABS, MIN, MAX.
+ * ch-exp.y (yylex): Check tokentab6.
+ * ch-exp.y (yylex): Call match_bitstring_literal.
+
+Mon Jan 4 16:54:18 1993 Fred Fish (fnf@cygnus.com)
+
+ * xcoffexec.c (vmap_symtab): Use new macros to access minimal
+ symbol name and value fields.
+
+ * c-exp.y (yylex): Make static, to match prototype and other
+ <lang>-exp.y files.
+
+ * expression.h (exp_opcode): Add BINOP_MOD.
+ * eval.c (evaluate_subexp): Handle new BINOP_MOD.
+ * expprint.c (dump_expression): Handle new BINOP_MOD.
+ * language.c (binop_type_check): Handle new BINOP_MOD.
+ * main.c (float_handler): Re-enable float handler when hit.
+ * valarith.c (language.h): Include, need current_language.
+ * valarith.c (TRUNCATION_TOWARDS_ZERO): Define default macro
+ for integer divide truncates towards zero for negative results.
+ * valarith.c (value_x_binop): Handle BINOP_MOD if seen.
+ * valarith.c (value_binop): Allow arithmetic operations on
+ TYPE_CODE_CHAR variables. Add case to handle new BINOP_MOD.
+ * ch-exp.y (operand_4): Add useful actions for MOD and REM.
+ * ch-exp.y (tokentab3): Add MOD and REM.
+ * ch-exp.y (yylex): Set innermost_block for symbols found
+ in local scopes. Return LOCATION_NAME for local symbols.
+ * ch-lang.c (chill_op_print_tab): Fix MOD entry to use
+ BINOP_MOD instead of BINOP_REM. Add REM entry, using BINOP_REM.
+
+Mon Jan 4 07:35:31 1993 Steve Chamberlain (sac@wahini.cygnus.com)
+
+ * command.c (shell_escape, make_command, _initialize_command):
+ don't create or use fork if CANT_FORK is defined.
+ * serial.h, ser-go32.c: now compiles, but "the obvious problems of
+ code written for the IBM PC" remain.
+ * xm-go32.h: define CANT_FORK
+
+Sun Jan 3 14:24:56 1993 Steve Chamberlain (sac@thepub.cygnus.com)
+
+ * remote-sim.c: first attempt at general simulator interface
+ * remote-hms.c: whitespace
+ * h8300-tdep.c: (h8300_skip_prologue, examine_prologue):
+ understand new stack layout. (print_register_hook): print ccr
+ register in a fancy way.
+
+Sun Jan 3 14:16:10 1993 Fred Fish (fnf@cygnus.com)
+
+ * eval.c (language.h): Include.
+ * eval.c (evaluate_subexp_with_coercion): Only coerce arrays
+ to pointer types when the current language is C. It loses for
+ other languages when the lower index bound is nonzero.
+ * valarith.c (value_subscript): Take array lower bounds into
+ account when performing subscripting operations.
+ * valops.c (value_coerce_array): Add comment describing why
+ arrays with nonzero lower bounds are dealt with in value_subscript,
+ rather than in value_coerce_array.
+
+Sat Jan 2 12:16:41 1993 Fred Fish (fnf@cygnus.com)
+
+ * ch-exp.y (FLOAT_LITERAL): Add token.
+ * ch-exp.y (literal): Add FLOAT_LITERAL.
+ * ch-exp.y (match_float_literal): New lexer routine.
+ * ch-exp.y (convert_float): Remove.
+ * ch-exp.y (yylex): Call match_float_literal.
+ * ch-exp.y (yylex): Match single '.' after trying
+ to match floating point literals.
+
+ * eval.c (evaluate_subexp): Add case MULTI_SUBSCRIPT.
+ * expprint.c (print_subexp): Rename BINOP_MULTI_SUBSCRIPT to
+ MULTI_SUBSCRIPT.
+ * expprint.c (dump_expression): New function for dumping
+ expression vectors during gdb debugging.
+ * expression.h (BINOP_MULTI_SUBSCRIPT): Name changed to
+ MULTI_SUBSCRIPT and moved out of BINOP range.
+ * expression.h (DUMP_EXPRESSION): New macro that calls
+ dump_expression if DEBUG_EXPRESSIONS is defined.
+ * m2-exp.y (BINOP_MULTI_SUBSCRIPT): Changed to MULTI_SUBSCRIPT.
+ * parse.c (length_of_subexp, prefixify_subexp): Change
+ BINOP_MULTI_SUBSCRIPT to MULTI_SUBSCRIPT.
+ * parse.c (parse_exp_1): Call DUMP_EXPRESSION before and after
+ prefixify'ing the expression.
+ * printcmd.c (print_command_1): Add comment.
+ * ch-exp.y (expression_list): Add useful actions.
+ * ch-exp.y (value_array_element): Add useful actions.
+ * ch-exp.y (array_primitive_value): Add production.
+ * ch-exp.y (yylex): Recognize ',' as a token.
+
+Fri Jan 1 18:22:02 1993 david d `zoo' zuhn (zoo at cirdan.cygnus.com)
+
+ * Makefile.in: pass prefix and exec_prefix via FLAGS_TO_PASS,
+ POSIXize the recursive makes (make [variable assignments] target{s})
+
+Fri Jan 1 11:56:23 1993 Fred Fish (fnf@cygnus.com)
+
+ * tm-sun4sol2.h (CPLUS_MARKER): Remove, now set in tm-sysv4.h.
+ * tm-sysv4.h (CPLUS_MARKER): By default, g++ uses '.' as the
+ CPLUS_MARKER for all SVR4 systems, so follow suit.
+ * defs.h (strdup_demangled): Remove prototype.
+ * dwarfread.c (enum_type, synthesize_typedef): Use new macro
+ SYMBOL_INIT_LANGUAGE_SPECIFIC.
+ * dwarfread.c (new_symbol): Use SYMBOL_INIT_DEMANGLED_NAME.
+ * minsyms.c (install_minimal_symbols, prim_record_minimal_symbol,
+ prim_record_minimal_symbol_and_info): Use new macro
+ SYMBOL_INIT_LANGUAGE_SPECIFIC.
+ * minsyms.c (install_minimal_symbols): Use new macro
+ SYMBOL_INIT_DEMANGLED_NAME.
+ * stabsread.c (define_symbol): Use new macro
+ SYMBOL_INIT_DEMANGLED_NAME.
+ * symfile.c (add_psymbol_to_list, add_psymbol_addr_to_list):
+ Use new macro SYMBOL_INIT_DEMANGLED_NAME.
+ * symfile.h (ADD_PSYMBOL_VT_TO_LIST): Use new macro
+ SYMBOL_INIT_DEMANGLED_NAME.
+ * symmisc.c (dump_msymbols, dump_symtab, print_partial_symbol):
+ SYMBOL_DEMANGLED_NAME now tests language itself.
+ * symtab.c (COMPLETION_LIST_ADD_SYMBOL): SYMBOL_DEMANGLED_NAME
+ now tests language itself.
+ * symtab.h (SYMBOL_CPLUS_DEMANGLED_NAME): New macro that does
+ what SYMBOL_DEMANGLED_NAME used to do, directly access the C++
+ mangled name member in the language dependent portion of a symbol.
+ * symtab.h (SYMBOL_DEMANGLED_NAME): New macro that returns the
+ mangled name member appropriate for a symbol's language.
+ * symtab.h (SYMBOL_SOURCE_NAME, SYMBOL_LINKAGE_NAME,
+ SYMBOL_MATCHES_NAME, SYMBOL_MATCHES_REGEXP):
+ SYMBOL_DEMANGLED_NAME now tests language itself.
+ * symtab.h (SYMBOL_INIT_LANGUAGE_SPECIFIC): New macro that
+ initializes language dependent portion of symbol.
+ * symtab.h (SYMBOL_INIT_DEMANGLED_NAME): New macro that
+ demangles and caches the demangled form of symbol names.
+ * utils.c (fputs_demangled, fprint_symbol): Use current language
+ to select an appropriate demangling algorithm.
+ * utils.c (strdup_demangled): Remove, no longer used.
+ * symtab.h (SYMBOL_CHILL_DEMANGLED_NAME): New macro that directly
+ access the Chill mangled name member in the language dependent
+ portion of a symbol.
+ * ch-lang.c (chill_demangle): New function, simple demangler.
+ * defs.h (chill_demangle): Add prototype.
+ * symtab.h (language_dependent_info): Add struct for Chill.
+
+For older changes see ChangeLog-92
+
+Local Variables:
+mode: indented-text
+left-margin: 8
+fill-column: 74
+version-control: never
+End:
diff --git a/gdb/ChangeLog-94 b/gdb/ChangeLog-94
new file mode 100644
index 00000000000..a691ace1003
--- /dev/null
+++ b/gdb/ChangeLog-94
@@ -0,0 +1,5705 @@
+Fri Dec 30 17:58:55 1994 Steve Chamberlain (sac@jonny.cygnus.com)
+
+ * config/m68k/tm-est.h: Remove cruft.
+
+
+Thu Dec 29 22:40:00 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * Allow up to 10 whitespace separated arguments to user defined
+ commands.
+ * top.c (struct user_args): Structure for holding arguments to
+ user defined commands.
+ (print_command_line): Delete unused "tmp_chain" variable. Clean
+ up flow control by having cases exit in the same manner.
+ Before executing a command or evaluating an expression, substitute
+ the current $arg0..$arg9 values if the command/expression uses them.
+ (arg_cleanup): New function.
+ (setup_user_args, locate_arg, insert_args): Likewise.
+ (execute_user_command): Allow arguments to user defined commands.
+
+ * Allow if/while commands to be used within a breakpoint command
+ list.
+ * breakpoint.c (bpstat_do_actions): Call execute_control_command
+ rather than execute_command (passes entire command structure rather
+ than just the command line text).
+ (breakpoint_1): Use "print_command_line" to print a breakpoint
+ command line (including control structures).
+ * gdbcmd.h (execute_control_command): Provide extern decl.
+ (print_command_line): Likewise.
+ * top.c (execute_control_command): No longer static.
+ (print_command_line): New function to recursively print a command
+ line, including control structures.
+
+Thu Dec 29 18:18:31 1994 Rob Savoye <rob@darkstar.cygnus.com>
+
+ * hppa-tdep.c (pa_print_registers): Extract register values stored
+ in big endian format on big and little endian hosts.
+
+ * array-rom.c: Support for Array Tech LSI33k based RAID disk
+ controller board.
+ * configure.in: Recognize "mips*-*-ecoff*" rather than
+ "mips*-idt-ecoff*" so it'll work for the LSI33k.
+
+ * monitor.[ch], op50-rom.c, rom68k-rom.c, w89k-rom.c: Add support
+ to monitor config structure for supported baud rates for a target
+ and variable stop bits.
+ * monitor.c (monitor_fetch_register): Store register values in big
+ endian format on any host.
+
+Wed Dec 28 19:27:22 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * hppa-tdep.c (hppa_fix_call_dummy): Prefer import stubs over
+ export stubs and actual shared library functions so that lazy
+ binding works correctly. Try both __d_plt_call and __gcc_plt_call
+ trampolines for calling import stubs.
+
+Wed Dec 28 15:29:02 1994 Stan Shebs <shebs@andros.cygnus.com>
+
+ * a29k-tdep.c (pop_frame): Fix a variable name.
+
+Wed Dec 28 12:21:39 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * hppa-tdep.c (push_dummy_frame): Refine code to determine what
+ space ID to place in the stack & inf_status structure.
+ (hppa_pop_frame): Don't walk through trampoline code if popping a
+ call dummy frame.
+ (hppa_fix_call_dummy): Call the stack dummy directly if the
+ current PC is in a shared library.
+
+ * hppa-tdep.c (push_dummy_frame): Return type is void. Clear
+ in_syscall bit in flags. Don't depend on the PC queue registers
+ when in_syscall is set, they're not valid.
+ * config/pa/tm-hppa.h (PUSH_DUMMY_FRAME): Pass inf_status down to
+ push_dummy_frame.
+ (SR4_REGNUM): Define.
+
+ * hppa-tdep.c: Misc. lint changes.
+
+Tue Dec 27 12:32:43 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * breakpoint.c (watchpoint_check): Don't bother restoring the
+ "selected" frame anymore, it's not necessary. Initialize the
+ frame cache before trying to find the current frame in the frame
+ chain.
+
+ * somsolib.c (som_solib_add): Return without loading any shared
+ libraries if symfile_objfile is NULL.
+ (som_solib_create_inferior_hook): Likewise.
+
+Fri Dec 23 17:03:13 1994 Steve Chamberlain (sac@jonny.cygnus.com)
+
+ * remote-est.c: New file supports EST-300 CPU32 background
+ mode ICE.
+ * remote-utils.c (sr_com): Call registers_changed.
+ * configure.in (m68*-*-est*): New configuration.
+ * config/m68k/tm-est.h: New file.
+
+Fri Dec 23 16:18:50 1994 Stu Grossman (grossman@cygnus.com)
+
+ * Makefile.in (CLIBS): Put LIBIBERTY last.
+
+Thu Dec 22 09:27:16 1994 Jim Kingdon <kingdon@deneb.cygnus.com>
+
+ * ser-tcp.c (tcp_open): Cast to struct sockaddr when passing to
+ function which expects that.
+
+Thu Dec 22 13:25:33 1994 J.T. Conklin (jtc@rtl.cygnus.com)
+
+ * nlm/gdbserve.c, nlm/ppc.c, nlm/ppc.h: Don't try to use
+ ALTERNATE_MEM_FUNCS.
+
+Wed Dec 21 14:00:26 1994 Rob Savoye <rob@darkstar.cygnus.com>
+
+ * monitor.c: Now supports xmodem as a remoteloadprotocol.
+
+Tue Dec 20 23:01:17 1994 Stu Grossman (grossman@cygnus.com)
+
+ * config/mips/xm-irix4.h, config/mips/xm-irix5.h: #define
+ _BSD_COMPAT to get reliable signal handling.
+
+Tue Dec 20 11:44:28 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * sparc-tdep.c, a29k-tdep.c, findvar.c (get_saved_register):
+ if !target_has_registers, call error().
+
+ * value.h: Remove obsolete comments about FRAME vs struct
+ frame_info *.
+
+
+Sun Dec 18 11:52:58 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * sparc-tdep.c (sparc_pop_frame): Remove erroneous extra argument
+ to write_register.
+
+Sat Dec 17 13:23:21 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * tm-sparc.c (EXTRA_FRAME_INFO): New field sp_offset.
+ * sparc-tdep.c (sparc_init_extra_frame_info): Set it.
+ (examine_prologue, sparc_init_extra_frame_info): Use ->frame plus
+ ->sp_offset to compute the address something is saved at, not
+ ->bottom.
+
+ * sparc-tdep.c (get_saved_register): New function.
+ * tm-sparc.h: Define GET_SAVED_REGISTER; don't define
+ FRAME_FIND_SAVED_REGS, HAVE_REGISTER_WINDOWS or REGISTER_IN_WINDOW_P.
+ * stack.c (frame_info): Add comment about what to do if
+ FRAME_FIND_SAVED_REGS is not defined.
+
+ * sparc-tdep.c (sparc_init_extra_frame_info): Set ->frame field
+ here. Get it right for flat frames.
+ * sparc-tdep.c (sparc_frame_chain): Instead of returning
+ meaningful value for ->frame field, just return dummy value.
+ This change is needed because the old code didn't deal with mixed
+ flat and non-flat frames.
+
+ * sparc-tdep.c (sparc_pop_frame): Write SP_REGNUM from
+ frame->frame, don't go through saved regs for this.
+
+ * sparc-tdep.c: Move guts of skip_prologue to new function
+ examine_prologue. Check for flat prologue and set is_flat.
+ Provide the caller with the information about what is saved where
+ if desired.
+ (skip_prologue, sparc_frame_find_saved_regs): Call examine_prologue.
+
+ * sparc-tdep.c: Replace union sparc_insn_layout and anonymous
+ union in isannulled, which won't work on a little-endian host,
+ with X_* macros.
+
+ * sparc-tdep.c (sparc_frame_saved_pc): If addr == 0, the saved PC
+ is still in %o7.
+
+ * config/sparc/tm-sparc.h: Define INIT_FRAME_PC and
+ INIT_FRAME_PC_FIRST.
+ * blockframe.c (get_prev_frame_info): Modify comments regarding
+ INIT_FRAME_PC_FIRST and the sparc.
+
+ * sparc-tdep.c (single_step): Use 4 not sizeof (long) for size of
+ instruction.
+
+Sat Dec 17 02:33:37 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * c-typeprint.c (c_type_print_base): Use `show' of -1 to print
+ the return type of methods to avoid infinite loops with anonymous
+ types.
+ * valops.c (search_struct_field): Handle anonymous unions.
+
+ * sparc-tdep.c (sunos4_skip_trampoline_code): New function
+ to correctly handle steps into -g compiled PIC objects in the
+ main executable.
+ * config/sparc/tm-sun4os4.h (SKIP_TRAMPOLINE_CODE):
+ Redefine to use sunos4_skip_trampoline_code.
+
+ * dwarfread.c (DWARF_REG_TO_REGNUM): Provide a default mapping
+ from DWARF to GDB register numbering.
+ * dwarfread.c (locval): Use DWARF_REG_TO_REGNUM to map the
+ register value.
+ * config/mips/tm-mipsv4.h (DWARF_REG_TO_REGNUM): Define.
+
+Fri Dec 16 10:56:29 1994 J.T. Conklin <jtc@rtl.cygnus.com>
+
+ * Makefile.in (uninstall): transform file names.
+
+Thu Dec 15 16:55:35 1994 Stan Shebs <shebs@andros.cygnus.com>
+
+ * defs.h: Include progress.h.
+ (QUIT): Call PROGRESS.
+ * main.c (main): Call START_PROGRESS and END_PROGRESS, break
+ usage message into shorter strings.
+ * source.c: Change long command help strings into concats of
+ shorter ones, for picky ANSI compilers.
+
+ * top.c (command_loop): For space usage display, show both
+ absolute size and the change from before command execution.
+
+Thu Dec 15 16:40:10 1994 Stu Grossman (grossman@cygnus.com)
+
+ * defs.h, main.c (gdb_fputs), top.c: Add stream arg to
+ fputs_unfiltered_hook.
+ * defs.h, top.c, utils.c (error): Add error_hook.
+
+Tue Dec 13 15:15:33 1994 Stan Shebs <shebs@andros.cygnus.com>
+
+ * breakpoint.c, infrun.c, printcmd.c: Change long command help
+ strings into concats of shorter ones, for picky ANSI compilers.
+
+Mon Dec 12 17:08:02 1994 Stan Shebs <shebs@andros.cygnus.com>
+
+ Sparc flat register window support.
+ * sparc-tdep.c (sparc_insn_layout): New union, defines layout of
+ instructions symbolically (used to be local to skip_prologue).
+ (sparc_init_extra_frame_info): New function.
+ (sparc_frame_chain): Add flat cases throughout.
+ (skip_prologue): Add recognition of flat prologues.
+ (sparc_frame_find_saved_regs): Add flat cases.
+ (sparc_pop_frame): Ditto.
+ * config/sparc/tm-sparc.h (EXTRA_FRAME_INFO): New slots.
+ (INIT_EXTRA_FRAME_INFO): Call sparc_init_extra_frame_info.
+ (PRINT_EXTRA_FRAME_INFO): Define.
+
+
+Mon Dec 12 13:06:59 1994 Jim Kingdon <kingdon@deneb.cygnus.com>
+
+ * f-lang.c: Remove duplicate declaration of
+ builtin_type_f_integer, and only include it in the f_builtin_types
+ once.
+
+ * somread.c (som_symfile_read): Just assign to objfile->obj_private,
+ not OBJ_UNWIND_INFO. Assigning to a cast is a GCC-ism which
+ the HP compiler doesn't like.
+
+
+Fri Dec 9 15:50:05 1994 Stan Shebs <shebs@andros.cygnus.com>
+
+ * remote.c (remote_wait): Pass string instead of char to strcpy.
+
+Fri Dec 9 04:43:17 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdbserver/low-lynx.c (mywait): Remove debugging printf.
+
+Thu Dec 8 15:07:29 1994 Jim Kingdon <kingdon@deneb.cygnus.com>
+
+ * frame.h: Restore pre-Nov 3 comments about FRAME_FP with minor
+ changes. They are correct, unlike the post-Nov 3 comment
+ (FRAME_FP doesn't have any machine-independent relationship with
+ FP_REGNUM or any other such notion of a "frame pointer").
+
+Wed Dec 7 14:50:54 1994 Jim Kingdon <kingdon@deneb.cygnus.com>
+
+ * gdbserver/remote-utils.c (write_ok): Write "OK", not "Ok", to
+ match stubs and protocol spec.
+ * gdbserver/remote-utils.c (remote_open): Cast to struct sockaddr
+ when passing to function which expects that.
+
+ The following changes aren't quite enough to make things work with
+ LynxOS (apprently kernel problems).
+ * infrun.c (wait_for_inferior): When resuming new thread, pass pid
+ not -1 for remote case.
+ * thread.c (info_threads_command): Give error if !target_has_stack.
+ * infrun.c (start_remote): Call init_thread_list.
+ * thread.c (info_threads_command): Don't call kill for remote
+ debugging target.
+ * target.c (normal_pid_to_str): Print "thread" not "process" for
+ remote.
+ * remote.c, gdbserver/*: Add 'H', 'S', and 'C' requests, 'X'
+ response, and `thread' part of 'T' response.
+ * gdbserver/*: If program exits, send packet to GDB before
+ exiting. Handle termination with a signal the same as exiting
+ with an exitstatus.
+ * remote.c: Don't try to kill program after getting an 'X'
+ response.
+ * infrun.c (wait_for_inferior): Add comment about kill versus mourn.
+
+Thu Dec 8 12:37:38 1994 Rob Savoye <rob@darkstar.cygnus.com>
+
+ * config/pa/tm-pro.h tm-hppap.h, hppapro.mt: Rename tm-hppap.h to
+ tm-pro.h.
+
+Wed Dec 7 18:22:59 1994 Stan Shebs <shebs@andros.cygnus.com>
+
+ * source.c: Various cosmetic changes.
+ (forward_search_command): Handle very long source lines correctly.
+
+Wed Dec 7 13:21:47 1994 Rob Savoye <rob@darkstar.cygnus.com>
+
+ * hppa-tdep.c: Use GDB_TARGET_IS_PA_ELF so SOM target support will
+ stop being linked in.
+
+ * config/pa/tm-hppap.h: New file. Set GDB_TARGET_IS_PA_ELF,
+ otherwise it looks like BSD-ELF.
+
+Mon Dec 5 21:43:52 1994 Stu Grossman (grossman@cygnus.com)
+
+ * inftarg.c: include <sys/types.h> to get def of pid_t.
+
+Fri Dec 2 15:03:07 1994 Stan Shebs <shebs@andros.cygnus.com>
+
+ * solib.c (auto_solib_add_at_startup): New global.
+ (solib_create_inferior_hook): Call solib_add only if
+ auto_solib_add_at_startup is nonzero.
+ (_initialize_solib): New command "set auto-solib-add".
+
+Fri Dec 2 12:52:04 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * parse.c (msymbol_addr_type): Replaced by
+ lookup_pointer_type (builtin_type_void).
+
+ * printcmd.c (_initialize_printcmd): Give examine_*_type
+ a name for `ptype $_'.
+
+Fri Dec 2 12:52:04 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * printcmd.c (print_formatted): Call val_print_string directly,
+ rather than via value_print.
+
+Wed Nov 30 22:27:27 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * somsolib.c (som_solib_get_got_by_pc): New function.
+ * somsolib.h (som_solib_get_got_by_pc): Add extern decl.
+ * hppa-tdep.c (hppa_fix_call_dummy): Handle case where FUN is the
+ function's export stub or real address in a shared library.
+
+Tue Nov 29 13:40:25 1994 J.T. Conklin (jtc@rtl.cygnus.com)
+
+ * config/i386/nbsd.mh (REGEX, REGEX1): No longer define.
+
+ * configure.in (i[345]86-*-freebsd*): New configuration.
+ * config/i386/{fbsd.mh,fbsd.mt,nm-fbsd.h}: New files.
+
+Tue Nov 29 12:23:25 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * top.c (read_next_line): Pass annotation suffix "commands"
+ instead of "command", matches documentation.
+
+Mon Nov 28 14:53:21 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * config/a29k/tm-a29k.h (setup_arbitrary_frame): Replace
+ FRAME_ADDR with CORE_ADDR in prototype.
+
+ * top.c (command_line_input): If annotation suffix is NULL,
+ replace it with an empty string.
+ (read_next_line): Pass "command" as annotation suffix to
+ command_line_input.
+
+Mon Nov 28 11:03:14 1994 J.T. Conklin (jtc@rtl.cygnus.com)
+
+ * config/rs6000/tm-rs6000.h (setpgrp): move defn from here...
+ * config/rs6000/xm-rs6000.h: ...to here.
+
+
+Fri Nov 25 21:26:02 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * tm-hppa.h (skip_trampoline_code): Add extern decl.
+ * hppa-tdep.c (hppa_pop_frame): Silently restart the inferior and
+ allow it to execute any return path trampoline code. Stop the
+ inferior and give the user control when the trampoline has
+ finished executing.
+ (in_solib_call_trampoline): Handle export stubs which also perform
+ parameter relocations.
+ (in_solib_return_trampoline): Likewise.
+
+Fri Nov 25 13:37:10 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * coffread.c, symfile.h (coff_getfilename): Make it static again.
+ * xcoffread.c (coff_getfilename): Use a static copy from
+ coffread.c, modified for accessing the static xcoff strtbl.
+
+Fri Nov 25 00:51:05 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * hppa-tdep.c (in_solib_call_trampoline): Recognize calls through
+ _sr4export and $$dyncall as trampolines. Likewise for long-call
+ stubs and parameter relocation stubs.
+ (in_solib_return_trampoline): Recognize a return trampoline for
+ return value relocation stubs.
+
+ * hpread.c: Include hp-symtab.h instead of hpux-symtab.h.
+ Various name changes to match those used by hp-symtab.h.
+
+Thu Nov 24 00:39:27 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * blockframe.c (find_pc_partial_function): Inhibit mst_trampoline
+ symbol special handling when INHIBIT_SUNSOLIB_TRANSFER_TABLE_HACK
+ is defined.
+ * infrun.c (IN_SOLIB_CALL_TRAMPOLINE): Renamed from
+ IN_SOLIB_TRAMPOLINE. All callers changed.
+ (IN_SOLIB_RETURN_TRAMPOLINE): Provide default definition.
+ (wait_for_inferior): Handle single stepping through trampolines on
+ return paths from shared libraries.
+ * config/pa/tm-hppa.h (IN_SOLIB_CALL_TRAMPOLINE): Use
+ in_solib_call_trampoline.
+ (IN_SOLIB_RETURN_TRAMPOLINE): Use in_solib_return_trampoline.
+ (INHIBIT_SUNSOLIB_TRANSFER_TABLE_HACK): Define.
+ * hppa-tdep.c (in_solib_call_trampoline): New function.
+ (in_solib_return_trampoline): New function.
+
+Wed Nov 23 21:43:03 1994 Steve Chamberlain (sac@jonny.cygnus.com)
+
+ * tm-h8300.h (REMOTE_BREAKPOINT): Define.
+ * h8300-tdep.c (h8300_pop_frame): Remove redundant call.
+
+ * remote-e7000.c (HARD_BREAKPOINTS): Reenable.
+ (BC_BREAKPOINTS): Disable.
+ * sh-tdep.c (print_insn): Cope with big and little endian machines.
+ * sh/sh.mt: Use libsim.a
+ * sh/tm-sh.h (TARGET_BYTE_ORDER_SELECTABLE): New
+ (BREAKPOINT): Changed to be byteorder independent.
+
+Tue Nov 22 19:13:39 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ Maintenance commands to report time and space usage.
+ * main.c (display_time, display_space): New globals.
+ (main): Add argument --statistics to enable reporting, display
+ time and space after startup is done.
+ * maint.c (maintenance_time_display, maintenance_space_display):
+ New commands.
+ * top.c (command_loop): Display time and space after command
+ execution.
+
+ * top.c (pre_init_ui_hook): New global.
+ (gdb_init): If pre_init_ui_hook set, call before all other init.
+
+Tue Nov 22 10:25:59 1994 Kung Hsu (kung@mexican.cygnus.com)
+
+ * a29k-tdep.c (examine_tag): Fix a bug in stack frame size.
+
+Sat Nov 19 03:10:51 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * config/i386/i386sol2.mh: Reenable core file support.
+
+ * symfile.c (deduce_language_from_filename): Treat .c++ as a
+ C++ extension.
+
+ * valops.c (destructor_name_p): Do not compare the template
+ part for template classes.
+
+Fri Nov 18 14:55:59 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * defs.h, infcmd.c (reg_names): Don't declare as constant.
+ * remote-mips.c (mips_open): Read and set the processor type.
+ * mips-tdep.c (mips_set_processor_type): Always return an int.
+
+Fri Nov 18 10:38:12 1994 J.T. Conklin <jtc@rtl.cygnus.com>
+
+ * nlm/alpha.c (strtol): Remove, it is provided by NetWare C library.
+ * nlm/gdbserve.def (strtol): Add to import list.
+ * nlm/fake_aio.c: Remove file, no longer used.
+
+ * Makefile.in (LD_FOR_TARGET, NLMCONV_FOR_TARGET): Remove.
+ * nlm/Makefile.in (gdbserve.O): Link with ${CC_FOR_TARGET}.
+ (LD_FOR_TARGET): Remove.
+
+Thu Nov 17 22:09:50 1994 Rob Savoye <rob@darkstar.cygnus.com>
+
+ * monitor.h, monitor.c, w89k-rom.c, op50n-rom.c, idp-rom.c: Add
+ support for two variables used to control the load protocol and
+ conversion type.
+
+Thu Nov 17 17:51:12 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ Support for different MIPS IDT processor models.
+ * mips-tdep.c (mips_processor_type, tmp_mips_processor_type,
+ mips_generic_reg_names, mips_r3041_reg_names,
+ mips_r3051_reg_names, mips_r3081_reg_names,
+ mips_processor_type_table): New globals.
+ (mips_do_registers_info): Don't display register if name is empty.
+ (mips_set_processor_type_command): New command.
+ (mips_show_processor_type_command): New command.
+ (mips_set_processor_type): New function.
+ (mips_read_processor_type): New function.
+ * config/mips/tm-idt.h (DEFAULT_MIPS_TYPE): New macro.
+ * config/mips/tm-mips.h (DEFAULT_MIPS_TYPE): New macro.
+ (NUM_REGS): Increase to account for all CP0 registers.
+ (REGISTER_NAMES): Add empty names for CP0 registers.
+ (FIRST_EMBED_REGNUM, LAST_EMBED_REGNUM): Adjust.
+ (PRID_REGNUM): New macro.
+
+Wed Nov 16 16:41:52 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * README: Add warning about termcap in Ultrix and OSF/1.
+
+Wed Nov 16 15:28:29 1994 Rob Savoye (rob@cygnus.com)
+
+
+ * hppa-tdep.c: Remove including sys/dir.h from a target file.
+
+Wed Nov 16 10:31:27 1994 J.T. Conklin (jtc@cygnus.com)
+
+ * config/powerpc/gdbserve.mt (TDEPFILES): Remove fake_aio.o.
+
+ * nlm/gdbserve.c: Include <nwtypes.h> before other NetWare headers.
+ * nlm/ppc.c: Likewise.
+
+ * nlm/ppc.c (strtol): Remove, it is provided by NetWare C Library.
+ (StopBell): New function (stubbed out).
+
+Wed Nov 16 00:12:21 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * hppa-tdep.c (skip_trampoline_code): Handle shared library import
+ trampolines.
+
+Tue Nov 15 16:18:52 1994 Kung Hsu (kung@mexican.cygnus.com)
+
+ * c-exp.y (yylex): Fix a bug in template scanning.
+
+Tue Nov 15 14:25:47 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * i386-stub.c, m68k-stub.c, sparc-stub.c, sparcl-stub.c: Mask out
+ the top bit returned by getDebugChar.
+
+Tue Nov 15 01:03:56 1994 Rob Savoye (rob@slipknot.cygnus.com)
+
+ * op50-rom.c, w89k-rom.c, monitor.c: Modify to usr two variables
+ to set remote load type and protocol.
+ * rom68k-rom.c: Add to_stop in target_ops.
+
+
+Sat Nov 12 21:55:47 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * somsolib.c: Add TODO list.
+ (som_solib_add): Immediately return if $SHLIB_INFO$ sections does
+ not exist or has size zero. Slightly simplify error handling.
+ Keep an internal list of all the loaded shared libraries and
+ various tidbits of information about the loaded shared libraries.
+ Build section tables for each loaded shared library and add those
+ tables to the core target if necessary.
+ (som_solib_create_inferior_hook): Force re-reading of shared
+ libraries at exec time.
+ (som_sharedlibrary_info_command): New function for dumping
+ information about the currently loaded shared libraries.
+ (_initialize_som_solib): New function.
+
+Sat Nov 12 02:26:50 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * Makefile.in (copying.o, f-exp.tab.o, dpx2-nat.o, dstread.o,
+ i386aix-nat.o, i386m3-nat.o, irix5-nat.o, lynx-nat.o, m3-nat.o,
+ mipsm3-nat.o, ns32km3-nat.o, remote-e7000.o, remote-os9k.o):
+ Add dependencies.
+ (copying.o, os9kread.o, remote.o): Update dependencies.
+
+ * valarith.c (value_sub): When subtracting pointers, only
+ check for a match of the pointed to element lengths.
+ Cast element length to LONGEST to obtain a signed result for
+ pointer subtractions.
+
+Fri Nov 11 10:51:07 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * ch-exp.y (yylex): Fix off-by-one error when converting string to
+ lowercase. Null terminate new string.
+
+ * hppa-tdep.c (rp_saved): Handle IMPORT stubs too.
+
+ * somsolib.c (som_solib_add): Check the value of __dld_flags, if
+ it indicates __dld_list is not valid return an error. If it
+ indicates that libraries were not mapped privately, issue a
+ warning.
+
+Thu Nov 10 23:17:45 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * symfile.c (syms_from_objfile): Only call find_lowest_section if
+ no ".text" section exists.
+
+Thu Nov 10 15:16:21 1994 Rob Savoye <rob@rtl.cygnus.com>
+
+ * rom68k-rom.c: New file. Replaces the old remote-mon.c and uses
+ the new generic ROM interface in monitor.c.
+ * config/m68k/monitor.mt: Use new ROM support.
+ * monitor.c: Add support for xmodem download protocol.
+
+Wed Nov 9 18:46:24 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * findvar.c (find_saved_register): Fix a frame variable name.
+ * infcmd.c (finish_command): Ditto.
+
+Tue Nov 8 13:20:14 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * TODO: Remove "Watchpoints seem not entirely reliable, though
+ they haven't failed me recently." item--this old (4.6 at least)
+ item is too vague to be useful (some watchpoint bugs have been
+ fixed since then).
+ * TODO: Add explanation of "RPC interface" item.
+
+Mon Nov 7 22:25:21 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * hppa-tdep.c (read_unwind_info): Use "text_offset" for linker
+ stub unwind descriptors too.
+
+ * Enable backtracing from inside a SOM shared library back into
+ user code.
+ * hppa-tdep.c (internalize_unwinds): Accept and use new
+ "text_offset" argument for dynamic relocation of
+ region_{start,end} fields in the unwind descriptor.
+ (read_unwind_info): Pass text_offset to internalize unwinds.
+
+Mon Nov 7 14:34:42 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * m3-nat.c: Remove comments about arbitrary limit in
+ printf_filtered; that limit is gone.
+
+Mon Nov 7 00:27:16 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * Beginnings of SOM shared library support. Breakpoints and
+ single frame backtracing within the library only. Only works when
+ using the HPUX 9 dynamic linker. More functionality to be added
+ soon.
+
+ * somsolib.c, somsolib.h: New files.
+ * Makefile.in (HFILES_NO_SRCDIR): Add somsolib.h
+ (ALLDEPFILES): Add somsolib.c.
+ (somsolib.o): Add some dependencies.
+ * somread.c (som_symtab_read): Accept multiple section offsets.
+ All callers changed. Adjust all text symbols with the first
+ section offset.
+ * symfile.c (find_lowest_section): Enable this function. Add some
+ tie-breaking logic when sections have the same vma.
+ (syms_from_objfile): Use find_lowest_section rather than looking
+ for ".text" by name. Relax warning to only warn if the lowest
+ section is not a code section.
+ * config/pa/{hppabsd.mh, hppahpux.mh} (NATDEPFILES): Add somsolib.o
+ * config/pa/{nm-hppab.h, nm-hppah.h}: Include somsolib.h.
+
+Sun Nov 6 12:54:54 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * partial-stab.h (N_TEXT): Put back GDB_TARGET_IS_HPPA kludge,
+ it is still needed for GCC-2.6 compiled code.
+ * TODO (GDB_TARGET_IS_HPPA): Note this kludge can be nuked
+ sometime after GCC-2.7 has been released.
+
+ * hppa-tdep.c (frame_saved_pc): Mask off low two bits when
+ retrieving the PC from a signal handler caller. Fix thinko
+ in Stan's last change ("frame", should have been "frame->next").
+ If the next frame is a signal handler caller and it's a system
+ call which has entered the kernel ((PSW & 0x2) != 0), then the
+ saved pc is in %r2 instead of %r31.
+
+Fri Nov 4 23:47:07 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * hppa-tdep.c (hppa_frame_find_saved_regs): Change "frame" to
+ "frame_info" throughout.
+
+Fri Nov 4 16:26:59 1994 Kung Hsu (kung@mexican.cygnus.com)
+
+ * sparcl-stub.c: get rid of defs.h.
+
+Fri Nov 4 13:11:54 1994 Jim Kingdon <kingdon@deneb.cygnus.com>
+
+ * gdbserver/Makefile.in (MMALLOC_CFLAGS): Add -I${MMALLOC_DIR}.
+ Correct definition of MMALLOC_DIR to reflect fact this is
+ gdb/gdbserver/Makefile.in, not gdb/Makefile.in.
+
+ * gdbserver/server.c (main): After we kill the inferior in
+ response to a 'k' request, exit.
+
+ * remote.c (remote_kill): Use catch_errors when calling putpkt.
+ (putpkt): Return int, not void, to match catch_errors calling
+ convention.
+
+Fri Nov 4 10:52:38 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * rs6000-tdep.c (pop_frame): Correct a variable name.
+
+Fri Nov 4 05:43:35 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * TODO: Re-write item about SIGINT handling to reflect the fact
+ that target_stop now exists.
+
+Thu Nov 3 15:19:17 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ Replace useless FRAME, FRAME_ADDR types with struct frame_info *
+ and CORE_ADDR, respectively.
+ * frame.h (FRAME, FRAME_INFO_ID, FRAME_ADDR): Remove.
+ * blockframe.c (get_frame_info): Remove.
+ * a29k-tdep.c, alpha-tdep.c, blockframe.c, breakpoint.c,
+ breakpoint.h, energize.c, findvar.c, gould-pinsn.c,
+ h8300-tdep.c, h8500-tdep.c, hppa-tdep.c, i386-tdep.c, i960-tdep.c,
+ infcmd.c, inferior.h, infrun.c, m68k-tdep.c, m88k-tdep.c,
+ mips-tdep.c, nindy-tdep.c, printcmd.c, pyr-tdep.c, rs6000-tdep.c,
+ sh-tdep.c, sparc-tdep.c, stack.c, valops.c, z8k-tdep.c,
+ config/a29k/tm-a29k.h, config/alpha/tm-alpha.h,
+ config/gould/tm-pn.h, config/h8300/tm-h8300.h,
+ config/h8500/tm-h8500.h, config/mips/tm-mips.h,
+ config/ns32k/tm-merlin.h, config/ns32k/tm-umax.h,
+ config/pyr/tm-pyr.h, config/sparc/tm-sparc.h): Replace FRAME with
+ struct frame_info * everywhere, replace FRAME_ADDR with CORE_ADDR,
+ rename variables consistently (using `frame' or `fi'), remove
+ calls to get_frame_info and FRAME_INFO_ID, remove comments about
+ FRAME and FRAME_ADDR cruftiness.
+
+Thu Nov 3 14:25:24 1994 Stu Grossman (grossman@cygnus.com)
+
+ * corelow.c, exec.c, inftarg.c, m3-nat.c, op50-rom.c, procfs.c,
+ remote-adapt.c, remote-e7000.c, remote-eb.c, remote-es.c,
+ remote-hms.c, remote-mips.c, remote-mm.c, remote-mon.c,
+ remote-nindy.c, remote-os9k.c, remote-pa.c, remote-sim.c,
+ remote-st.c, remote-udi.c, remote-vx.c, remote-z8k.c, remote.c,
+ w89k-rom.c, target.c, target.h: Add support for target_stop().
+
+Thu Nov 3 01:23:45 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * osfsolib.c (solib_map_sections, first_link_map_member,
+ next_link_map_member, xfer_link_map_member): Retrieve and use
+ shared library relocation offset from runtime loader structures.
+ Use libxproc.a routines to get a working version if
+ USE_LDR_ROUTINES is defined.
+ * README: Remove item about shared library relocation for
+ Alpha OSF/1.
+
+Wed Nov 2 15:05:39 1994 Kung Hsu (kung@mexican.cygnus.com)
+
+ * c-exp.y (yylex): scan template names, and scan nested class
+ names.
+
+Wed Nov 2 11:01:55 1994 J.T. Conklin (jtc@phishhead.cygnus.com)
+
+ * nlm/Makefile.in: install gdbserve.nlm.
+
+
+Tue Nov 1 13:00:46 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * c-valprint.c (c_value_print): Check for plain literal `char'
+ target type when suppressing `(char *)' output for strings.
+
+Mon Oct 31 19:19:51 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * coffread.c (coff_symfile_init): Remove unused local abfd.
+ * utils.c [NO_MMALLOC] (mmalloc, mrealloc): Define and use size_t
+ instead of long, for compatibility with mmalloc.h.
+
+Sat Oct 29 02:40:40 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * top.c (line_completion_function): Renamed from
+ symbol_completion_function, takes the line buffer and the
+ point in the line buffer as additional arguments.
+ (readline_line_completion_function): New function, interface
+ between readline and line_completion_function.
+ (init_main): Use it.
+ (complete_command): Use line_completion_function instead of
+ abusing rl_line_buffer. Free completion strings after printing
+ them.
+ * symtab.c (completion_list_add_name): Recheck for duplicates
+ if we intend to add a modified symbol.
+
+ * gdbtypes.h (cplus_struct_type): nfn_fields_total no longer
+ includes the number of methods from the baseclasses.
+ * stabsread.c (attach_fn_fields_to_type): No longer add the
+ number of methods from the baseclasses to TYPE_NFN_FIELDS_TOTAL,
+ the baseclass type might not have been completely filled in yet.
+ * symtab.c (total_number_of_methods): New function to compute
+ the total number of methods for a type, including the methods
+ from baseclasses.
+ (decode_line_1): Use it instead of TYPE_NFN_FIELDS_TOTAL to
+ allocate the symbol array for find_methods.
+
+ * stabsread.c (scan_file_globals): Add default case to minimal
+ symbol type switch, to avoid gcc -Wall warnings.
+
+ * config/rs6000/tm-rs6000.h (INIT_EXTRA_FRAME_INFO):
+ Don't test for zero backchain pointer to recognize a signal
+ handler frame, if read() gets interrupted by a signal, the
+ backchain will be non zero.
+ (SIG_FRAME_FP_OFFSET): Move to here from rs6000-tdep.c,
+ improve comment.
+ (SIG_FRAME_PC_OFFSET): New definition.
+ (FRAME_SAVED_PC): Return saved pc from sigcontext if this
+ is a signal handler frame.
+ * rs6000-tdep.c (function_frame_info): Do not error out
+ if we can't access the instructions.
+
+ * config/rs6000/tm-rs6000.h (CONVERT_FROM_FUNC_PTR_ADDR):
+ New definition to get the function address from a function pointer.
+ * valops.c (find_function_addr): Use it when calling a user
+ function through a function pointer.
+
+Fri Oct 28 16:16:52 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * Makefile.in (MMALLOC_DIR): New definition.
+ (MMALLOC): Use MMALLOC_DIR.
+ (MMALLOC_CFLAGS): Look in MMALLOC_DIR for mmalloc.h.
+ (OPCODES): Remove gratuitous "./".
+ * defs.h (mmalloc.h): Include.
+ (mmalloc, mrealloc, etc): Remove decls.
+ (cplus_demangle, cplus_demangle_opname): Remove decls.
+
+Wed Oct 26 15:41:07 1994 Stu Grossman (grossman@cygnus.com)
+
+ * defs.h, main.c, top.c: Change sense and name of
+ no_windows variable. Now called use_windows, and defaults to off
+ (for compatibility).
+
+Wed Oct 26 12:20:53 1994 Jim Kingdon <kingdon@cygnus.com>
+
+ * coffread.c (coff_symtab_read): If we get the address from
+ target_lookup_symbol, set the section to -2 not SECT_OFF_BSS.
+ (coff_symtab_read): Set value and section of symbol that
+ process_coff_symbol returns.
+
+Tue Oct 25 09:53:04 1994 J.T. Conklin (jtc@phishhead.cygnus.com)
+
+ * config/i386/tm-nbsd.h: Enable longjmp support.
+
+Sat Oct 22 03:41:13 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * valarith.c (value_binop): Take care of ANSI `value preserving'
+ rule, which was not addressed by the previous change.
+
+ * rs6000-tdep.c (skip_prologue): Handle `mr r31,r1', which is
+ generated by gcc-2.6, as a synonym for `oril r31,r1,0'.
+
+ * TODO: Remove item about RS/6000 shared libraries.
+
+Thu Oct 20 17:35:45 1994 Stu Grossman (grossman@cygnus.com)
+
+ * defs.h, infrun.c (wait_for_inferior), top.c: Call
+ target_wait_hook to allow GUI to handle blocking for inferior. Call
+ call_command_hook in execute_command to provide means for wrapping
+ commands with GUI state change updates.
+
+ * infrun.c (wait_for_inferior): Make sure
+ through_sigtramp_breakpoint is non-null before deleting.
+
+Thu Oct 20 10:26:43 1994 J.T. Conklin (jtc@phishhead.cygnus.com)
+
+ * config/powerpc/ppc-nw.mt (TDEPFILES): Removed exec.o.
+
+Thu Oct 20 06:56:07 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * Makefile.in (coffread.o): Depend on target.h.
+ (remote-vx.o): Depend on gdb-stabs.h objfiles.h symfile.h $(bfd_h).
+
+Wed Oct 19 22:49:31 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * TODO: Fix typo.
+
+Wed Oct 19 11:32:15 1994 Jim Kingdon <kingdon@cygnus.com>
+
+ * objfiles.c (objfile_relocate): When relocating ->sections, use
+ objfile not symfile_objfile.
+
+ * symtab.h, minsyms.c (minsyms_sort): New function.
+ * objfiles.c (objfile_relocate): Call it.
+
+ * remote-vx.c (vx_add_symbols): Call breakpoint_re_set.
+
+ * objfiles.c, objfiles.h (objfile_to_front): New function.
+ * remote-vx.c (vx_add_symbols): Call it.
+
+ * coffread.c (coff_symtab_read): Handle common symbols the same
+ way that partial-stab.h does.
+
+Wed Oct 19 21:06:12 1994 Rob Savoye (rob@cirdan.cygnus.com)
+
+ * hppa-tdep.c: Remove include files a.out.h, ioctl.h, and
+ machine/psl.h. These are host files.
+
+Wed Oct 19 15:13:51 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * objfiles.h (struct objfile): Fix comment--minimal_symbol_count
+ does *not* include the terminating NULL msymbol.
+
+Tue Oct 18 20:53:29 1994 Rob Savoye <rob@darkstar.cygnus.com>
+
+ * monitor.c (monitor_load_srec,monitor_make_srec): Add an asrecord
+ loader that reads files using BFD and converts it on the fly.
+
+Mon Oct 17 18:52:06 1994 Rob Savoye <rob@darkstar.cygnus.com>
+
+ * monitor.c (set_loadtype_command): Fixed so it doesn't core dump.
+ * monitor.c (monitor_load): check the load type and load the file
+ accordingly. Default to gr_load_image().
+ * monitor.c (monitor_load_ascii_srec): Load an ascii file in
+ srecord format by downloading to the monitor.
+ * w89k-rom.c, op50n-rom.c: set supported load types.
+
+Mon Oct 17 10:29:08 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * Makefile.in (ALLDEPFILES): Remove xcoffexec.c.
+ * Makefile.in: Remove xcoffexec.o rule.
+
+ * exec.c (exec_file_command): Add comment.
+
+ Fix data and bss relocation for VxWorks 5.1:
+ * remote-vx.c (vx_add_symbols): New function.
+ (vx_load_command, add_symbol_stub): Call it instead of
+ symbol_file_add.
+ (vx_wait): Remove comment which was wrong to useless.
+ * remote-vx.c: Reindent much of file.
+ * coffread.c (cs_to_section, find_targ_sec): New functions.
+ (process_coff_symbol): Set SYMBOL_SECTION to result
+ from cs_to_section.
+ (coff_symtab_read): Call cs_to_section and deal with result
+ rather than assuming sections are in a certain order. Deal with
+ BSS.
+ * coffread.c: Remove text_bfd_scnum variable.
+
+Sat Oct 15 16:55:48 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * corelow.c: Format to standard.
+ (core_close): Use name instead of bfd_filename.
+
+Fri Oct 14 10:29:08 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * exec.c (map_vmap): Cast return from xmalloc to its proper type,
+ not to PTR.
+
+ * symfile.c (reread_symbols): Include bfd_errmsg string in error
+ message if bfd_close fails.
+ * exec.c (exec_close), solib.c (clear_solib), corelow.c
+ (core_close), objfiles.c (free_objfile), irix5-nat.c
+ (clear_solib), osfsolib.c (clear_solib), remote-utils.c
+ (gr_load_image): Check for errors from bfd_close.
+ * solib.c (look_for_base), remote-utils.c (gr_load_image),
+ remote-udi.c (download), corelow.c (core_open), symfile.c
+ (symfile_bfd_open), symfile.c (generic_load): Add comment
+ regarding error from bfd_close.
+ * remote-udi.c (download), remote-utils.c (gr_load_image): Add
+ comment about bogus handling of errors from bfd_openr.
+ * exec.c (exec_close): Add comment regarding memory leak and
+ dangling reference to vp->name.
+
+Sat Oct 15 03:43:00 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * eval.c (evaluate_subexp): Make fnptr a LONGEST instead
+ of using longest_to_int.
+
+ * infcmd.c (run_stack_dummy): Reinstate set_current_frame call,
+ mips and alpha targets need the real breakpoint pc for
+ creating the breakpoint frame.
+
+ * stack.c (return_command): Cast return value to the return
+ type of the function from which we return.
+ * values.c (set_return_value): Pass VALUE_CONTENTS unmodified
+ to STORE_RETURN_VALUE.
+
+ * symtab.c (lookup_symbol): Remove search for `static mangled
+ symbols', the search for `static symbols' already looks for
+ mangled and demangled symbols via lookup_block_symbol.
+
+ * valarith.c (value_binop): Use ANSI C arithmetic conversions
+ when performing integral evaluations, implement BINOP_EQUAL and
+ BINOP_LESS.
+ (value_equal, value_less): Use value_binop to perform the
+ comparison if both operands have TYPE_CODE_INT.
+
+ * rs6000-tdep.c (pop_frame): Make sure all registers are valid,
+ as they are written back later. Handle sp restore for frameless
+ functions. Use fdata.nosavedpc instead of fdata.frameless to
+ determine if the pc has been saved.
+ (function_frame_info): Handle `mr r31,r1', which is generated by
+ gcc-2.6, as a synonym for `oril r31,r1,0'.
+ (skip_trampoline_code): Handle shared library trampolines.
+ * xcoffread.c (read_xcoff_symtabs): Record XMC_GL symbols with
+ their real name. Enables setting of breakpoints in shared libraries
+ before the executable is run.
+
+Fri Oct 14 19:39:47 1994 Rob Savoye <rob@darkstar.cygnus.com>
+
+ * monitor.h, remote-mon.c: Hack up to so the old ROM monitor
+ interface code still works with the new ROM monitor
+ structures. Fake out a couple of fields.
+
+Fri Oct 14 14:54:37 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * h8500-tdep.c (target_read_sp, target_write_sp, target_read_pc,
+ target_write_pc, target_read_fp, target_write_fp): Rename to
+ h8500_read_sp, etc.
+ (h8500_read_pc, h8500_write_pc): Add pid argument.
+ * config/h8500/tm-h8500.h (TARGET_READ_SP, TARGET_WRITE_SP,
+ TARGET_READ_PC, TARGET_WRITE_PC, TARGET_READ_FP, TARGET_WRITE_FP):
+ Change to match functions above.
+
+Thu Oct 13 13:24:29 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * NEWS: Add item about if and while.
+
+ * .gdbinit: Restore `end'; it was not excess. Reindent
+ list-objfiles to make this clear. Comment out all of
+ list-objfiles because old gdb's choke on it.
+
+Wed Oct 12 23:19:08 1994 Ian Lance Taylor <ian@sanguine.cygnus.com>
+
+ * config/mips/tm-bigmips64.h: Just define TARGET_BYTE_ORDER and
+ include tm-mips64.h.
+
+Wed Oct 12 18:02:17 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * Makefile.in (ANNOTATE_OBS): New definition.
+ (COMMON_OBS): Add exec.o.
+ (annotate.o): Remove extra compile rule.
+ * config/*/*.mh, config/*/*.mt: Remove exec.o from *DEPFILES lists
+ everywhere.
+
+ * .gdbinit: Remove excess `end'.
+
+ * exec.c: Merge in RS6000 support from xcoffexec.c.
+ (symfile.h, objfiles.h, xcoffsolib.h): Include.
+ (vmap): New global variable.
+ (exec_close): Close and free objects in vmap chain.
+ (exec_file_command) [IBM6000_TARGET]: Set up initial vmap.
+ (bfdsec_to_vmap, map_vmap): Moved here from xcoffexec.c.
+ (exec_files_info): Print vmap information.
+ * xcoffexec.c: Remove.
+ * config/rs6000/rs6000.mt, config/rs6000/rs6000lynx.mt
+ (TDEPFILES): Use exec.o instead of xcoffexec.o.
+ * TODO: Remove pertinent items.
+
+Wed Oct 12 10:08:19 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * partial-stab.h (N_TEXT): Delete GDB_TARGET_IS_HPPA kludge; they
+ are no longer needed as of gcc-2.6.0.
+
+Tue Oct 11 15:51:01 1994 Ian Lance Taylor <ian@sanguine.cygnus.com>
+
+ * lynx-nat.c (child_wait): Correct handling of byte reversed SPARC
+ Lynx wait status.
+ (fetch_core_registers): Don't try to fetch a register if
+ regmap maps it to -1.
+ * sparc-tdep.c (sparc_frame_find_saved_regs): Use FRAME_SAVED_I0
+ and FRAME_SAVED_L0 when setting saved_regs_addr. SPARC Lynx
+ stores the registers in a weird order.
+
+Sat Oct 8 20:59:13 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * blockframe.c (reinit_frame_cache): Reinstate select_frame call
+ if inferior_pid is nonzero.
+
+Sat Oct 8 04:27:21 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ Speed up GDB startup time by not demangling partial symbols.
+ * symfile.h (ADD_PSYMBOL_VT_TO_LIST),
+ symfile.c (add_psymbol_to_list, add_psymbol_addr_to_list):
+ No longer demangle partial symbols.
+ * symtab.c (lookup_symbol, list_symbols): Handle mangled
+ variables, e.g. C++ static members, via the minimal symbols.
+
+ Handle reordered functions in an objfile, for Irix 5.2 shared
+ libraries.
+ * objfiles.h (OBJF_REORDERED): New bit in the objfile flags,
+ set if the functions in an objfile are reordered.
+ * mdebugread.c (parse_partial_symbols): Detect reordered
+ functions in an objfile.
+ * symtab.c (find_pc_psymtab, find_pc_symtab): Use expensive
+ lookup algorithm if the functions in the objfile are reordered.
+
+ * xcoffexec.c (exec_close): If the current target has a copy
+ of the exec_ops sections, reflect the freeing of the sections
+ in current_target.
+
+ * valops.c (call_function_by_hand): Use `sizeof dummy1', not
+ `sizeof dummy', for constructing the call dummy code.
+
+ * config/sparc/tm-sparc.h: Add PARAMS declarations to all
+ function declarations.
+ * sparc-tdep.c (sparc_pop_frame): Cast result of
+ read_memory_integer to CORE_ADDR when passing it to PC_ADJUST.
+
+ * irix5-nat.c (enable_break): Set breakpoint at the entry point
+ of the executable, to handle the case where main resides in a
+ shared library.
+ * irix5-nat.c (solib_create_inferior_hook): Reset stop_soon_quietly
+ after shared library symbol reading, to get rid of a warning from
+ heuristic_proc_start if the startup code has no symbolic debug info.
+
+ * breakpoint.h (struct breakpoint): Add new fields language
+ and input_radix, to enable breakpoint resetting with the
+ proper language and radix.
+ * breakpoint.c (set_raw_breakpoint): Initialize them.
+ (breakpoint_re_set_one): Use them when resetting the breakpoint.
+ (breakpoint_re_set): Preserve current language and input_radix
+ across breakpoint_re_set_one calls.
+
+ * symtab.c (decode_line_1): Do not build a canonical line
+ specification for `*expr' line specifications.
+
+ * breakpoint.h (bpstat_stop_status): Fix prototype declaration.
+
+Fri Oct 7 08:48:18 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ The point of these changes is to avoid reading the frame pointer
+ and stack pointer during stepping, to speed things up.
+ A. Changes to not select a frame until we need a selected frame:
+ * blockframe.c (flush_cached_frames): Call select_frame (NULL, -1).
+ * infrun.c (wait_for_inferior): Move call to select_frame back to
+ normal_stop. This reverts a change of 13 Apr 94 (it says Jeff
+ Law, but the change was my idea); the only reason for that change
+ was so we could save and restore the selected frame in
+ wait_for_inferior, and now that flush_cached frames clears the
+ selected frame, that should work OK now.
+ B. Changes to not create a current_frame until we need one:
+ * blockframe.c (get_current_frame): If current_frame is NULL, try
+ to create an innermost frame.
+ * sparc-tdep.c (sparc_pop_frame), infcmd.c (run-stack_dummy),
+ infrun.c (wait_for_inferior), thread.c (thread_switch),
+ convex-tdep.c (set_thread_command), a29k-tdep.c (pop_frame),
+ alpha-tdep.c (alpha_pop_frame), convex-xdep.c (core_file_command),
+ h8300-tdep.c (h8300_pop_frame), h8500-tdep.c (h8300_pop_frame),
+ hppa-tdep.c (hppa_pop_frame), i386-tdep.c (i386_pop_frame),
+ i960-tdep.c (pop_frame), m68k-tdep.c
+ (m68k_pop_frame), mips-tdep.c (mips_pop_frame), rs6000-tdep.c
+ (push_dummy_frame, pop_dummy_frame, pop_frame), sh-tdep.c
+ (pop_frame), config/arm/tm-arm.h (POP_FRAME),
+ config/convex/tm-convex.h (POP_FRAME), config/gould/tm-pn.h
+ (POP_FRAME), config/ns32k/tm-merlin.h (POP_FRAME),
+ config/ns32k/tm-umax.h (POP_FRAME), config/tahoe/tm-tahoe.h
+ (POP_FRAME), config/vax/tm-vax.h (POP_FRAME): Don't
+ call create_new_frame.
+ * corelow.c (core_open), altos-xdep.c (core_file_command),
+ arm-xdep.c (core_file_command), gould-xdep.c (core_file_command),
+ m3-nat.c (select_thread), sun386-nat.c (core_file_command),
+ umax-xdep.c (core_file_command): Don't call create_new_frame; do
+ call flush_cached_frames.
+ * blockframe.c (reinit_frame_cache): Don't call create_new_frame
+ or select_frame.
+ C. Changes to get rid of stop_frame_address and instead only
+ fetch the frame pointer when we need it.
+ * breakpoint.c (bpstat_stop_status): Remove argument
+ frame_address; use FRAME_FP (get_current_frame ()).
+ * infrun.c (wait_for_inferior): Don't pass frame pointer to
+ bpstat_stop_status.
+ * infrun.c (wait_for_inferior): Use FRAME_FP (get_current_frame
+ ()) instead of stop_frame_address.
+ * infrun.c (save_inferior_status, restore_inferior_status),
+ inferior.h (struct inferior_status): Don't save and restore
+ stop_frame_address.
+ * inferior.h, infcmd.c, thread.c (thread_switch), m3-nat.c
+ (select_thread): Remove stop_frame_address and uses thereof.
+ D. Same thing for the stack pointer.
+ * infrun.c (wait_for_inferior): Remove stop_sp and replace
+ uses thereof with read_sp ().
+ E. Change to eliminate one nasty little spot where we were
+ wanting to know the frame pointer from before the current step
+ (idea from GDB 3.5, which saved my ass, because my other ideas of
+ how to fix it were very baroque).
+ * infrun.c: Remove prev_frame_address.
+ * infrun.c (wait_for_inferior, step_over_function): Use
+ step_frame_address instead of prev_frame_address.
+ F. Same basic idea for the stack pointer.
+ * inferior.h, infcmd.c: New variable step_sp.
+ * infcmd.c (step_1, until_next_command): Set it.
+ * infrun.c: Remove prev_sp and replace uses by step_sp.
+ * infrun.c (wait_for_inferior): If we get out of the step
+ range, then set step_sp to the current stack pointer before we
+ start going again.
+
+Fri Oct 7 12:17:17 1994 Ian Lance Taylor <ian@sanguine.cygnus.com>
+
+ * top.c (target_byte_order_auto): New static variable.
+ (set_endian): Mention that ``auto'' is permitted.
+ (set_endian_auto): New static function.
+ (show_endian): Change message based on target_byte_order_auto.
+ (set_endian_from_file): New function.
+ (init_main): Add command ``auto'' to endianlist.
+ * exec.c (exec_file_command): Call set_endian_from_file.
+ * defs.h (set_endian_from_file): Declare.
+
+Thu Oct 6 18:10:41 1994 J.T. Conklin (jtc@phishhead.cygnus.com)
+
+ * nlm/i386.c (flush_i_cache): New function, does nothing.
+ (frame_to_registers, registers_to_frame, set_step_traps,
+ clear_step_traps, do_status): Make non-static.
+
+Thu Oct 6 12:26:42 1994 Ian Lance Taylor <ian@sanguine.cygnus.com>
+
+ * config/mips/tm-mips.h (GDB_TARGET_IS_MIPS64): If not already
+ defined, define as 0.
+ (FIX_CALL_DUMMY): Rewrite to remove presumption that host and
+ target are similar.
+ * config/mips/tm-idt.h (TARGET_BYTE_ORDER_SELECTABLE): Define.
+ * config/mips/tm-idtl.h (TARGET_BYTE_ORDER_SELECTABLE): Define.
+ * config/mips/tm-idt64.h (TARGET_BYTE_ORDER_SELECTABLE): Define.
+ (BREAKPOINT): Remove definition.
+ * config/mips/tm-idtl64.h (TARGET_BYTE_ORDER_SELECTABLE): Define.
+ (BREAKPOINT): Remove definition.
+ * config/mips/tm-mips64.h (GDB_TARGET_IS_MIPS64): Define with a
+ value of 1, rather than without a value.
+ * config/mips/tm-bigmips64.h (GDB_TARGET_IS_MIPS64): Likewise.
+ * mips-tdep.c: Rewrite uses of GDB_TARGET_IS_MIPS64 to switch at
+ run time rather than at compile time.
+
+ * remote-mips.c (break_insn): Remove.
+ (BREAK_INSN, BREAK_INSN_SIZE): Define.
+ (mips_insert_breakpoint): Use BREAK_INSN, not break_insn.
+ (mips_remove_breakpoint): Likewise.
+
+ * defs.h: If TARGET_BYTE_ORDER_SELECTABLE is defined by tm.h,
+ define TARGET_BYTE_ORDER as target_byte_order, and declare
+ target_byte_order as an extern int, and define BITS_BIG_ENDIAN as
+ a test of TARGET_BYTE_ORDER.
+ * top.c: Several additions if TARGET_BYTE_ORDER_SELECTABLE is
+ defined:
+ (endianlist, target_byte_order): New variables.
+ (set_endian, set_endian_big, set_endian_little): New functions.
+ (show_endian): New function.
+ (init_cmd_lists): Initialize endianlist.
+ (init_main): Add commands ``set endian big'', ``set endian
+ little'', and ``show endian''.
+ * a29k-pinsn.c: Rewrite uses of TARGET_BYTE_ORDER and
+ BITS_BIG_ENDIAN to switch at run time rather than at compile time.
+ * coffread.c, dwarfread.c, findvar.c, mips-tdep.c: Likewise.
+ * remote-os9k.c, stabsread.c, valarith.c, valprint.c: Likewise.
+ * values.c: Likewise.
+
+Wed Oct 5 11:41:24 1994 J.T. Conklin (jtc@phishhead.cygnus.com)
+
+ * nlm/configure.in: ${gdb_host_cpu} defaults to ${host_cpu}.
+
+ * nlm/Makefile.in: Get rid of NWINCLUDES.
+ * config/{alpha,powerpc}/gdbserve.mt: Remove NWINCLUDES.
+ User should now configure with --with-headers.
+
+Mon Oct 3 07:48:34 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdbserver/server.c (main): Silently accept all unrecognized
+ requests and send back a zero length acknowledge. That is what
+ *-stub.c do and is what remote.c expects.
+
+Mon Oct 3 05:11:47 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * corelow.c (core_open): Copy the modified to_sections_end
+ vector from current_target to core_ops too.
+
+ * gdbserver/server.c (main): Silently accept query requests
+ and send back a zero length acknowledge.
+
+Fri Sep 30 17:17:21 1994 J.T. Conklin (jtc@phishhead.cygnus.com)
+
+ * nlm/Makefile.in: Don't define NWINCLUDES.
+ * config/{alpha,powerpc}/gdbserve.mt: define NWINCLUDES.
+
+Fri Sep 30 15:59:55 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdbserver/low-lynx.c (create_inferior): Pass all 4 args to ptrace.
+
+Fri Sep 30 06:42:42 1994 Ian Lance Taylor (ian@cygnus.com)
+
+ * lynx-nat.c (child_wait): Use status.w_status, not status, in
+ arithmetic. status is a `union wait'.
+
+ * config/nm-lynx.h (PTRACE_ARG3_TYPE): Define to int, not char *.
+
+ * lynx-nat.c (child_wait): Pass fourth argument to ptrace.
+
+Thu Sep 29 08:22:27 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * xcoffread.c (read_xcoff_symtab): Fix comment for yesterday's change.
+
+Wed Sep 28 17:48:18 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * coffread.c (complete_symtab): If last_source_file is set upon
+ entry, free it.
+
+Wed Sep 28 08:59:14 1994 Jim Kingdon (kingdon@cygnus.com)
+
+ * xcoffread.c (read_xcoff_symtab, case C_FILE):
+ Set main_aux before using it.
+
+ * xcoffexec.c (exec_close): If quitting, don't call clear_symtab_users.
+
+ * xcoffread.c (read_xcoff_symtab): Process XTY_LD symbols we were
+ ignoring before. But continue to ignore XMC_DS.
+
+Wed Sep 28 00:35:23 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * hpread.c (hpread_read_array_type): Do not change the type code
+ to TYPE_CODE_PTR for "char foo[]". Just make it a zero length
+ array type.
+
+ * hpread.c (hpread_type_translate): Handle T_UNS_LONG types with
+ lengths other than 32bits (HP C 9.69 represents an "unsigned char"
+ as an T_UNS_LONG with length 8).
+
+ * hpread.c (struct hpread_symfile_info): Delete have_module field
+ and accessor macro. Minor indentation fix.
+ (hpread_build_psymtabs, case K_MODULE): Only start a new psymtab
+ and reset state variables have_name & texthigh if pst is NULL.
+ (hpread_build_psymtabs, case K_SRCFILE): Only reset the name of a
+ partial symbol table if pst is non-NULL. If pst is NULL, then
+ start a new psymtab.
+ (hpread_process_one_debug_symbol, case K_MODULE): Now empty.
+ (hpread_process_one_debug_symbol, case K_SRCFILE): Simplify and
+ correct handling of subfiles.
+
+Mon Sep 26 02:59:00 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * defs.h (misc_command_type): Remove trailing comma from
+ enumerator list.
+
+Sun Sep 25 23:19:58 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * hppa-tdep.c (frame_saved_pc): Fix thinko in code to dig saved pc
+ out of an interrupt frame.
+
+Sun Sep 25 12:50:17 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * infcmd.c (do_registers_info) [INVALID_FLOAT]: Only use if
+ defined.
+ * values.c (unpack_double) [INVALID_FLOAT]: Ditto.
+ * mips-tdep.c (mips_print_register): Don't test float validity.
+ * config/a29k/tm-a29k.h, config/alpha/tm-alpha.h,
+ config/arm/tm-arm.h, config/convex/tm-convex.h,
+ config/h8300/tm-h8300.h, config/h8500/tm-h8500.h,
+ config/i386/tm-i386v.h, config/i386/tm-sun386.h,
+ config/i960/tm-i960.h, config/m68k/tm-m68k.h,
+ config/m88k/tm-m88k.h, config/mips/tm-mips.h,
+ config/ns32k/tm-merlin.h, config/ns32k/tm-nbsd.h,
+ config/ns32k/tm-ns32km3.h, config/ns32k/tm-umax.h,
+ config/pa/tm-hppa.h, config/pyr/tm-pyr.h,
+ config/rs6000/tm-rs6000.h, config/sh/tm-sh.h,
+ config/sparc/tm-sparc.h, config/z8k/tm-z8k.h (INVALID_FLOAT):
+ Remove definition.
+
+Sun Sep 25 06:07:37 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * TODO: Remove item about adding general multi-threaded stuff;
+ this is done.
+ Remove item about specifying arbitrary locations of stack frames
+ (this works on some machines).
+ Remove item about debugging functions without a frame pointer
+ (this works on some machines).
+ Remove item about re-writing macros which handle frame chaining and
+ frameless functions. They have been re-written at least once
+ since that item was written.
+ Remove item about gdb catching SIGINT when attached; this is done.
+ Remove item about having list_command not read symbols--why bother?
+
+Sat Sep 24 17:40:10 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * TODO: Append contents of Projects file.
+ * Projects: Remove.
+
+Sat Sep 24 01:47:25 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * corelow.c (add_solib_stub): Remove copying of to_sections,
+ pass current_target to SOLIB_ADD. The Sep 10 change failed
+ if SOLIB_ADD errored out, or if SOLIB_ADD was trying to access
+ target memory.
+ * corelow.c (core_open): After reading the shared libraries,
+ copy the modified to_sections vector from current_target to
+ core_ops, so that core_close can free it later.
+ * config/rs6000/nm-rs6000.h, rs6000-nat.c (xcoff_relocate_core):
+ Pass down target parameter from SOLIB_ADD and use it instead of
+ directly accessing core_ops.
+
+Fri Sep 23 14:58:49 1994 J.T. Conklin (jtc@rtl.cygnus.com)
+
+ * solib.c: *BSD systems need <a.out.h> to be included before
+ <link.h>.
+
+ * i386b-nat.c: Add i386_float_info(), etc.
+ * config/i386/nm-nbsd.h: #define FLOAT_INFO.
+
+ * config/nm-nbsd.h: New file, for generic NetBSD native support.
+ * config/i386/nm-nbsd.h: Use it.
+ * config/sparc/nm-nbsd.h: Use it.
+ * config/ns32k/nm-nbsd.h: Use it.
+
+ * configure.in (i386-*-netbsd): Use config/i386/nbsd.m[ht].
+ (ns32k-*-netbsd): Use config/ns32k/nbsd.m[ht].
+ * config/i386/{nbsd.mh,nbsd.mt,nm-nbsd.h,tm-nbsd.h,xm-nbsd.h}:
+ New files, support for NetBSD/i386.
+ * config/ns32k/{nbsd.mh,nbsd.mh,nm-nbsd.h,tm-nbsd.h,xm-nbsd.h}:
+ New files, support for NetBSD/ns32k.
+
+Tue Sep 20 11:34:27 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * .gdbinit: Add list-objfiles command.
+
+ * TODO: Reword item regarding NO_STD_REGS.
+
+ * coffread.c (record_minimal_symbol, coff_read_enum_type,
+ coff_read_struct_type): Allocate on symbol_obstack, not directly
+ via malloc/savestring.
+
+Tue Sep 20 15:42:02 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * TODO: Add more items.
+ * tests: Remove the directory and all of its (obsolete) contents.
+
+Tue Sep 20 11:34:27 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * coffread.c (init_stringtab): When copying length to stringtab,
+ use target format, not host format, since that is what the rest of
+ the code assumes.
+
+Mon Sep 19 15:48:10 1994 J.T. Conklin (jtc@phishhead.cygnus.com)
+
+ * Makefile.in: Removed prelude.o, i386-nlmstub.o, nlmstub.o,
+ nlmstub.nlm, and nlmstub targets. Removed NWSOURCE and
+ NWINCLUDES definitions.
+ * i386-nlmstub.c: Removed.
+
+Mon Sep 19 07:48:36 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * dbxread.c (read_dbx_dynamic_symtab): Cast bfd_asymbol_name to
+ char * (from const char *) before assigning. Don't save string we
+ pass to record_minimal_symbol (it already saves it).
+
+
+Sat Sep 17 02:26:58 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * cp-valprint.c (static_field_print): New variable, controls
+ printing of static members.
+ (_initialize_cp_valprint): New print set subcommand
+ "static-members". Turn on printing of static members by default.
+ (cp_print_value_fields): Print static members if necessary.
+
+ * solib.c: Remove inclusion of libelf.h and elf/mips.h.
+ (elf_locate_base): Use only standard BFD functions to collect
+ information about the .dynamic section. Check for DT_MIPS_RLD_MAP
+ tag only if it got defined via the inclusion of <link.h>.
+
+ * f-exp.y: Write block for OP_VAR_VALUE.
+ * f-valprint.c (info_common_command): Handle `info common'
+ without an argument correctly.
+
+ * c-typeprint.c (c_type_print_base): Handle template constructors.
+ * symtab.c (gdb_mangle_name): Handle template method mangling,
+ get rid of GCC_MANGLE_BUG code, which only applied to gcc-2.2.2.
+
+Fri Sep 16 16:06:08 1994 Per Bothner (bothner@kalessin.cygnus.com)
+
+ * gdbtypes.h (TYPE_INDEX_TYPE): New macro.
+ * ch-typeprint.c, ch-valprint.c: Use TYPE_INDEX_TYPE.
+ * ch-valprint.c (chill_val_print): Pass index type directly
+ (instead of its TYPE_TARGET_TYPE) to print_type_scalar.
+ * stabsread.c (read_type): Don't set TYPE_FLAG_TARGET_STUB
+ if the index type is a stub.
+
+Fri Sep 16 17:18:44 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * config/i386/{i386aix.mh, i386bsd.mh, i386lynx.mh, i386sco.mh,
+ i386sco4.mh, i386sol2.mh, i386v.mh, i386v32.mh, i386v4.mh,
+ ncr3000.mh, ptx.mh, ptx4.mh}, config/m68k/{altos.mh, apollo68v.mh,
+ delta68.mh, dpx2.mh, hp300bsd.mh, hp300hpux.mh, m68klynx.mh,
+ m68kv4.mh}, config/m88k/{delta88.mh, delta88v4.mh},
+ config/mips/riscos.mh, config/pa/hppahpux.mh,
+ config/rs6000/rs6000lynx.mh, config/sparc/{sparclynx.mh,
+ sun4sol2.mh}, config/tahoe/tahoe.mh, config/vax/{vaxbsd.mh,
+ vaxult.mh, vaxult2.mh} (REGEX, REGEX1, SYSV_DEFINE): No longer
+ define.
+ * config/i386/i386sco4.mh (MUNCH_DEFINE): No longer define.
+
+Fri Sep 16 15:40:34 1994 Stu Grossman (grossman@cygnus.com)
+
+ * defs.h (QUIT): Call interactive_hook to allow GUI to interrupt.
+ Also, add decl for symtab_to_filename.
+ * source.c (symtab_to_filename): New. Returns the file
+ associated with a symtab.
+ * top.c: Define interactive_hook. Called during QUIT to animate
+ the GUI.
+
+Fri Sep 16 00:14:40 1994 Per Bothner (bothner@kalessin.cygnus.com)
+
+ * stabsread.c (read_type): Handle stub types for bitstrings.
+ * stabsread.c (read_array_type): Check for stub domain type
+ using TYPE_FLAG_STUB, not its length.
+ * gdbtypes.c (create_set_type): Handle a stub domain type.
+
+ * ch-exp.y: Get rid of some extra non-terminals, and move
+ their rules into primitive_value.
+ * parser-defs.h: Add comment about unary postfix operators.
+ * ch-lang.c (chill_op_print_tab): Add '->', postfix and prefix.
+ * expprint.c (print_subexp): Recognize unary postfix operator.
+
+Wed Sep 14 18:27:42 1994 Jason Molenda (crash@phydeaux.cygnus.com)
+
+ * remote-hms.c: use remote_debug instead of hms_silent toggle.
+ Add warnings about depreciation of `snoop' cmd.
+
+Wed Sep 14 18:18:58 1994 Steve Chamberlain (sac@jonny.cygnus.com)
+
+ * remote-hms.c (hms_read_inferior_memory): Cope when
+ target sends both \r and \n.
+
+Wed Sep 14 17:14:57 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * remote-mips.c (mips_error): Place NORETURN macro correctly.
+ * TODO: Add item about START_INFERIOR_TRAPS_EXPECTED.
+
+Wed Sep 14 14:26:21 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * xcoffread.c (read_xcoff_symtab): Fix obsolete comment about
+ mst_solib_trampoline.
+
+ * f-valprint.c (f_val_print): Change cast of valaddr from
+ CORE_ADDR * to char **, since that is how it is used.
+
+ * dbxread.c (read_dbx_dynamic_symtab): Save copy of symbol names
+ using obsavestring, and pass that to prim_record_minimal_symbol.
+ Having the objfile point to bfd_asymbol_name directly doesn't work
+ if we save and restore a mapped symbol file.
+
+
+Tue Sep 13 18:23:26 1994 Rob Savoye (rob@darkstar.cygnus.com)
+
+ * w89k-rom.c, op50-rom.c, monitor.c, config/pa/hppapro.mt: New files
+ to add a generic ROM monitor interface, and support file for the
+ WinBond W89K and the Oki OP50N PA based target boards.
+
+
+Sun Sep 11 22:34:57 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * config/pa/tm-hppa.h (REGISTER_NAMES): Use r26-r23 for arg0-arg3.
+
+Sun Sep 11 04:36:47 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * irix5-nat.c, osfsolib.c, solib.c (solib_add): Simplify last
+ change by replacing `symbols_added' with `so_last'.
+ * mdebugread.c (parse_external, parse_partial_symbols): Ignore
+ global common symbols, they will be resolved by the runtime loader.
+ * mdebugread.c (parse_symbol, parse_partial_symbols, cross_ref):
+ Handle scSCommon like scCommon symbols.
+
+Sat Sep 10 01:43:28 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * corelow.c (add_solib_stub): Copy to_sections changes from
+ core_ops to current_target after adding the shared libraries.
+ * partial-stab.h (N_EXCL), dbxread.c (add_old_header_file,
+ find_corresponding_bincl_psymtab): Change `repeated header not seen'
+ error to a complaint, simplify complaint.
+ * procfs.c (signalname, errnoname): Make `name' const.
+ * symfile.c (reread_symbols): Use filename from old BFD to
+ reopen the objfile.
+ * values.c (record_latest_value): Don't record value in the
+ history chain until we are sure there won't be an error.
+
+Fri Sep 9 15:52:09 1994 J.T. Conklin (jtc@phishhead.cygnus.com)
+
+ * nlm/Makefile.in: remove MMALLOC, READLINE, TERMCAP, and other
+ cruft.
+
+ * config/i386/gdbserve.mt: New file, defs for i386 nlm stub.
+
+Thu Sep 8 17:14:43 1994 Steve Chamberlain (sac@jonny.cygnus.com)
+
+ * remote.c (fromhex): Make error more explicit.
+ (read_frame): Don't print bad checksum information unless
+ remote_debugging. Don't use repeat count unless it's > 0.
+ * remote-e7000.c (expect): When echoing, ignore multiple newlines.
+ (e7000_insert_breakpoint, e7000_remove_breakpoint, target_ops):
+ Optionally cope with BC style breakpoints.
+ (e7000_command): After command send directly to the E7000 mark
+ registers as changed.
+ (why_stop, e7000_wait: Understand BC style stop condition.
+ * sh-tdep.c (sh_skip_prologue): Understand more complicated
+ sequences. (frame_find_saved_regs): Likewise.
+ * config/h8500/tm-h8500.h (target_write_pc, TARGET_WRITE_PC):
+ Handle extra arg.
+ * config/i386/xm-go32.h (GDBINIT_FILENAME): Set to gdb.ini.
+ (more work here to come)
+ * config/sh/tm-sh.h (EXTRA_FRAME_INFO): Add f_offset and leaf_function
+ fields.
+
+Thu Sep 8 16:15:34 1994 J.T. Conklin (jtc@rtl.cygnus.com)
+
+ * sparclite/Makefile.in: Assorted stuff needed for eload.
+
+ * sparclite/eload.c: Merge in command line argument parsing and
+ error message handling improvements orignally made to aload.c.
+
+Wed Sep 7 23:24:50 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * defs.h (enum misc_command_type, command_control_type): Enums
+ for describing the command and control types.
+ (struct command_line): Add new fields to keep track of the command
+ type and body associated with the command.
+ * top.c: Include value.h. Delete whitespace at the end of lines.
+ (build_command_line, get_command_line): New functions.
+ (execute_control_command, while_command, if_command): Likewise.
+ (realloc_body_list, read_next_line): Likewise.
+ (recurse_read_control_structure): Likewise.
+ (execute_user_command): Call execute_control_command.
+ (read_command_lines): Simplify by calling read_next_line, call
+ read_control_structure for "if" and "while" commands.
+ (free_command_lines): Free new fields in the command structure.
+ (define_command): Reset control_level to zero.
+ (init_main): Install command handlers for "if" and "while" commands.
+
+Tue Sep 6 16:24:07 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * c-typeprint.c (c_type_print_varspec_prefix,
+ c_type_print_varspec_suffix): Add cases for Fortran type codes.
+ * eval.c (evaluate_subexp): For OP_ARRAY expressions in Fortran,
+ call f77_value_literal_string instead.
+ * f_exp.y: Include <string.h>, move include of parser-defs.h.
+ (parse_number): Translate 'd' floats to 'e' so atof() works.
+ (yylex): Remove unused variables.
+ * f-lang.c: Include <string.h>.
+ (get_bf_for_fcn): Remove unused variable.
+ * f-typeprint.c (f_type_print_varspec_prefix,
+ f_type_print_varspec_suffix): Remove unused
+ variables, add cases to switch statements.
+ (f_type_print_base): Remove unused variables.
+ * f-valprint.c (gdbcore.h, command.h): Include.
+ (f77_get_dynamic_lowerbound, f77_get_dynamic_upperbound):
+ Call read_memory_integer with correct number of arguments.
+ (f77_get_dynamic_upperbound): Call f77_get_dynamic_lowerbound
+ with correct argument type.
+ (f77_print_array): Removed unused array array_size_array.
+ (f_val_print): Don't use a CORE_ADDR as a char *.
+ * valops.c (value_cast): Handle COMPLEX and BOOL types.
+ (value_assign): Handle Fortran literal string and complex values.
+ (f77_cast_into_complex, f77_assign_from_literal_string,
+ f77_assign_from_literal_complex): New functions.
+
+Mon Sep 5 14:46:41 1994 Per Bothner (bothner@kalessin.cygnus.com)
+
+ * ch-typeprint.c (chill_type_print_base): Make TYPE_CODE_RANGE
+ case more robust.
+
+Sun Sep 4 16:06:34 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * i960-tdep.c (signal.h): Don't include.
+
+ * cxux-nat.c (target_is_m88110): Remove definition.
+
+ * configure.in (config/nm-empty.h): If cross only, use instead
+ of config/nm-trash.h.
+ * config/nm-trash.h: Remove.
+ * config/nm-empty.h: New file.
+ * config/i386/nm-m3.h: New file, includes config/nm-m3.h.
+ * config/mips/nm-m3.h: New file, includes config/nm-m3.h.
+ * config/m68k/nm-sysv4.h: New file, includes config/nm-sysv4.h.
+ * config/mips/nm-sysv4.h: New file, includes config/nm-sysv4.h.
+ * config/sparc/nm-sysv4.h: New file, includes config/nm-sysv4.h.
+
+
+Fri Sep 2 17:35:55 1994 J.T. Conklin (jtc@phishhead.cygnus.com)
+
+ * configure.in: No longer look for nm, tm, and xm headers in
+ config/<header>; they are always in config/<cpu>/<header>.
+
+Fri Sep 2 16:40:03 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * objfiles.c (allocate_objfile): Add the newly-created objfile to
+ the end of the list of objfiles, instead of at the beginning.
+
+ * xcoffread.c (allocate_include_entry): New function, abstracted
+ from code in record_include_begin.
+ (record_include_begin, record_include_end): Call it.
+
+ * blockframe.c (reinit_frame_cache): Test inferior_pid instead of
+ target_has_stack to decide whether to create a real stack frame
+ for the cache.
+
+ * coffread.c (process_coff_symbol) [CXUX_TARGET]: Ignore vendor
+ section.
+ * config/m88k/tm-cxux.h (CXUX_TARGET): Define.
+
+ * h8300-tdep.c: Include "dis-asm.h" instead of <dis-asm.h>.
+
+Fri Sep 2 09:51:46 1994 J.T. Conklin (jtc@cygnus.com)
+
+ * config/sparc/tm-nbsd.h: Add #defines to map NetBSD struct and
+ field names into what is expected by sparc-nat.c.
+
+Thu Sep 1 17:32:54 1994 Per Bothner (bothner@kalessin.cygnus.com)
+
+ * c-typeprint.c (c_typedef_print): Add missing Chill support.
+
+Thu Sep 1 15:41:21 1994 Stu Grossman (grossman@cygnus.com)
+
+ * rs6000-pinsn.c (print_insn): Use powerpc disassembler when
+ doing Power PC.
+ * config/powerpc/tm-ppc-nw.h: Define GDB_TARGET_POWERPC.
+
+ * config/i386/i386lynx.mh, config/m68k/m68klynx.mh,
+ config/rs6000/rs6000lynx.mh, config/sparc/sparclynx.mh: Enable
+ ser-tcp.
+
+ * nlm/Makefile.in: Get rid of NWSOURCE.
+ * nlm/alpha-io.S (inVti, outVti): Remove extraneous ldha's.
+ * nlm/gdbserve.o: Add dummy __main routine.
+ * nlm/gdbserve.def: Turn on debug.
+
+Thu Sep 1 12:36:39 1994 Jim Kingdon (kingdon@cygnus.com)
+
+ * config/xm-nbsd.h: Don't define SET_STACK_LIMIT_HUGE; it is obsolete.
+
+Thu Sep 1 11:01:40 1994 J.T. Conklin (jtc@rtl.cygnus.com)
+
+ * config/tm-nbsd.h: New file, support for all NetBSD targets.
+ * config/xm-nbsd.h: fix typo.
+ * config/sparc/{nm,tm,xm}-nbsd.h: New files, renamed from
+ {nm,tm,xm}-sparcnbsd.h to conform to prefered file naming
+ conventions.
+ * configure.in: (sparc-*-netbsd): use config/sparc/nbsd.m[ht].
+
+Wed Aug 31 14:40:33 1994 Jason Molenda (crash@phydeaux.cygnus.com)
+
+ * remote-udi.c (udi_read_inferior_memory,udi_write_inferior_memory):
+ change typeo in error msg (`inferrior' -> `inferior').
+
+Wed Aug 31 09:17:02 1994 Jim Kingdon (kingdon@cygnus.com)
+
+ * inflow.c (set_sigint_trap, clear_sigint_trap): Check for
+ attach_flag (this check was performed by the callers). Also check
+ inferior_thisrun_terminal.
+ * inftarg.c (child_wait), lynx-nat.c (child_wait),
+ procfs.c (wait_fd), symm-nat.c (child_wait): Don't check
+ attach_flag in deciding whether to call set_sigint_trap and
+ clear_sigint_trap.
+
+ * value.h (struct value): Change literal_data from PTR to char *,
+ since that is the way it is used.
+
+Tue Aug 30 21:56:54 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * somread.c (som_symfile_read): Force unwinds to be re-read after
+ reading in a new partial symbol table.
+
+Tue Aug 30 13:14:16 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * config/h8500/tm-8500.h (DONT_USE_REMOTE): Remove definition,
+ an obsolete conditional.
+ * config/pa/tm-hppa.h (BREAKPOINT) [KERNELDEBUG]: Remove use,
+ an obsolete conditional.
+ * config/rs6000/rs6000.mh, config/rs6000/rs6000.mt: Clean up
+ comments.
+
+Mon Aug 29 14:39:42 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * Makefile.in (ns32k-opcode.h): Remove reference.
+ (ns32k-pinsn.o): Update dependencies.
+ * ns32k-opcode.h: Remove file.
+ * ns32k-pinsn.c (print_insn): Call version in libopcodes, remove
+ all other code in this file.
+
+Mon Aug 29 12:04:07 1994 Stu Grossman (grossman@cygnus.com)
+
+ * nlm/configure.in: Stop using cpu.c. Put it in TDEPFILES instead.
+ * config/alpha/gdbserve.mt (TDEPFILES): Remove alpha-patch.o.
+
+ * nlm/Makefile.in: Add rule for .S.o.
+ * nlm/aio.h: Protect from multiple inclusions.
+ * nlm/alpha-io.S: Remove everything we don't need.
+ * nlm/{alpha-patch.c, alpha-patch.h, alpha-uart.c, alpha-uart.h}:
+ Remove, no longer needed.
+ * nlm/alpha.c: Merge in lots of stuff from previous files.
+ * nlm/alpha.h: Don't #include alpha-patch.h. Make
+ breakpoint_insn extern.
+ * Move stuff from alpha-patch.h into here.
+
+ * config/alpha/gdbserve.mt (TDEPFILES): Get rid of alpha-uart.o.
+
+Mon Aug 29 11:34:34 1994 Jim Kingdon (kingdon@cygnus.com)
+
+ * annotate.c (annotate_starting): Flush output.
+
+Sat Aug 27 23:32:43 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * symfile.c (symbol_file_add): Move reinit_frame_cache call to
+ the callers of symbol_file_add. Gets rid of heuristic fence-post
+ warnings on mips and alpha targets when the PC resides in a shared
+ library which is not yet read in.
+ * coff-solib.c (coff_solib_add), cxux-nat.c (add_shared_symbol_files),
+ irix5-nat.c (solib_add), osfsolib.c (solib_add),
+ remote-vx.c (vx_open), solib.c (solib_add):
+ Add call to reinit_frame_cache after all shared libraries are read in.
+ * remote-udi.c (udi_load), remote-vx.c (vx_load_command),
+ symfile.c (symbol_file_command, add_symbol_file_command):
+ Add call to reinit_frame_cache after symbol_file_add.
+
+Wed Aug 24 17:45:14 1994 J.T. Conklin (jtc@cygnus.com)
+
+ * config/xm-nbsd.h: New file, support for all NetBSD ports.
+ * config/sparc/{nm-sparcnbsd.h,tm-sparcnbsd.h,xm-sparcnbsd.h,
+ sparcnbsd.mh,sparcnbsd.mt}: New files, support for NetBSD/sparc.
+ * configure.in: Add sparc-*-netbsd target.
+
+Wed Aug 24 13:17:34 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * remote-vx.c (vx_attach): Interpret the command argument as an
+ unsigned long.
+
+Wed Aug 24 13:08:08 1994 Ian Lance Taylor (ian@sanguine.cygnus.com)
+
+ * configure.in: Change i[34]86 to i[345]86.
+ * nlm/configure.in: Likewise.
+ * gdbserver/configure.in: Likewise.
+
+Wed Aug 24 09:41:09 1994 J.T. Conklin (jtc@cygnus.com)
+
+ * configure.in (i386-*-netware): Automatically configure nlm
+ subdir.
+
+Tue Aug 23 17:51:13 1994 J.T. Conklin (jtc@cygnus.com)
+
+ * nlm/gdbserve.c: conditionalize header file inclusion for either
+ NetWare 4.0 or PIN targets.
+ * nlm/i386.c: include appropriate header files.
+ * nlm/prelude.c: define TERMINATE_BY_UNLOAD for NetWare 4.0
+ targets.
+
+Tue Aug 23 16:54:16 1994 Stu Grossman (grossman@cygnus.com)
+
+ * nlm/ppc.c (set_step_traps clear_step_traps): Cleanups.
+ * nlm/gdbserve.def: Autoload clib.
+
+Tue Aug 23 12:05:19 1994 Jim Kingdon (kingdon@cygnus.com)
+
+ * breakpoint.c (condition_command): Call breakpoints_changed.
+
+ * gdbtypes.h: Declare f77_create_literal_string_type and
+ f77_create_literal_complex_type.
+ * valops.c (f77_value_literal_string, f77_value_substring,
+ f77_value_literal_complex): Use xmalloc not malloc.
+ * valops.c (f77_value_literal_string, f77_value_substring):
+ Make addr char * not CORE_ADDR.
+ * value.h (struct value): Add new field literal_data of aligner union.
+ (VALUE_LITERAL_DATA): Use it.
+ * f-lang.h: Declare find_common_for_function.
+ * value.h, valops.c: Split VALUE_SUBSTRING_START into memaddr and
+ myaddr fields of a union. Don't overload it with the frame field
+ (not sure this is necessary; I'm not sure what lval_* codes
+ VALUE_SUBSTRING_* can be used with).
+
+Mon Aug 22 11:45:01 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * config/a29k/{a29k-kern.mt,a29k-udi.mt,a29k.mt,ultra3.mh,
+ ultra3.mt}: Clean up comments, remove no-longer-used definitions.
+
+ * rs6000-nat.c: Include libbfd.h again, needed until reference
+ to bfd_cache_lookup is cleaned out.
+
+ * config/i386/linux.mh (XM_CLIBS): Add -lm.
+
+Mon Aug 22 10:42:15 1994 Steve Chamberlain (sac@jonny.cygnus.com)
+
+ Work to reduce the interrupts-off duration when running in DOS.
+ * ser-go32.c: (dos_async_ready): See if anything is in the buffer.
+ (dos_async_rx): rewrite to unpack as many characters from the
+ asynctsr as possible into a local buffer.
+
+Fri Aug 19 14:55:45 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ Initial Fortran language support, adapted from work by Farooq Butt
+ (fmbutt@engage.sps.mot.com).
+ * Makefile.in: Add Fortran-related files and dependencies.
+ * defs.h (language_fortran): New language enum.
+ * language.h (_LANG_fortran): Define.
+ (MAX_FORTRAN_DIMS): Define.
+ * expression.h: Reformat to standard.
+ (MULTI_F77_SUBSCRIPT, OP_F77_UNDETERMINED_ARGLIST,
+ OP_F77_LITERAL_COMPLEX, OP_F77_SUBSTR): New expression opcodes.
+ * gdbtypes.h (TYPE_CODE_COMPLEX, TYPE_CODE_LITERAL_COMPLEX,
+ TYPE_CODE_LITERAL_STRING): New type codes.
+ (type): New fields upper_bound_type and lower_bound_type.
+ (TYPE_ARRAY_UPPER_BOUND_TYPE, TYPE_ARRAY_LOWER_BOUND_TYPE,
+ TYPE_ARRAY_UPPER_BOUND_VALUE, TYPE_ARRAY_LOWER_BOUND_VALUE): New
+ macros.
+ (builtin_type_f_character, etc): Declare.
+ * value.h (VALUE_LITERAL_DATA, VALUE_SUBSTRING_START): Define.
+ * f-exp.y: New file, Fortran expression grammar.
+ * f-lang.c: New file, Fortran language support functions.
+ * f-lang.h: New file, Fortran language support declarations.
+ * f-typeprint.c: New file, Fortran type printing.
+ * f-valprint.c: New file, Fortran value printing.
+ * eval.c (evaluate_subexp): Add code for new expression opcodes,
+ fix wording of error message.
+ * gdbtypes.c (f77_create_literal_complex_type,
+ f77_create_literal_string_type): New functions.
+ * language.c (set_language_command): Add Fortran info.
+ (calc_f77_array_dims): New function.
+ * parse.c (length_of_subexp, prefixify_subexp): Add cases for new
+ expression opcodes.
+ * symfile.c (deduce_language_from_filename): Recognize .f and .F
+ as Fortran source files.
+ * valops.c (f77_value_literal_string, f77_value_substring,
+ f77_value_literal_complex): New functions.
+
+Fri Aug 19 13:35:01 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * c-typeprint.c (c_print_type): Assume demangled arguments
+ if a '(' is found in varstring, looking for ')' at the end of
+ varstring did fail with demangled const member functions, which
+ have a trailing `const'.
+ * remote.c (get_offsets, putpkt): Change to `char' buffers,
+ to avoid errors when compiling with DEC c89.
+ (remote_wait): Cast to `char *' before passing buffer to
+ fputs_filtered, to avoid errors when compiling with DEC c89.
+ (remote_wait): Do not return inferior_pid by default, this
+ statement is never reached, which causes warnings from some
+ compilers.
+ * stabsread.c (scan_file_globals): Ignore static minimal symbols.
+ * symfile.c (load_command): If called with no argument, try
+ to get the filename from the executable file.
+ (generic_load): Remove check for NULL filename, it is done
+ in load_command now.
+
+Fri Aug 19 10:36:15 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * Makefile.in (ALLDEPFILES): Add hpread.c.
+ (hpread.o): Add dependencies.
+
+ * somread.c: Do not include "aout/aout64.h". SOM has nothing to
+ do with a.out.
+ (BYTES_IN_WORD): Delete.
+ (som_symfile_read): Call hpread_build_psymtabs to build any
+ minimal symbols based on the HP C native debug symbols.
+ (som_symfile_finish): Call hpread_symfile_finish.
+ (som_symfile_init): Call hpread_symfile_init.
+ * config/pa/tm-hppa.h (HPREAD_ADJUST_STACK_ADDRESS): Define.
+ * hppa-tdep.c (hpread_adjust_stack_address): New function.
+
+ * config/pa/hppabsd.mh (NATDEPFILES): Add hpread.o
+ * config/pa/hppahpux.mh (NATDEPFILES): Likewise.
+ * hpread.c: New file.
+
+Fri Aug 19 00:40:55 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * hppa-tdep.c (skip_trampoline_code): Revert incorrect change
+ from June 2, 1994 (what was I thinking?!?). Fix it right this
+ time.
+
+Thu Aug 18 17:01:35 1994 J.T. Conklin (jtc@rtl.cygnus.com)
+
+ * nlm/i386.c, nlm/i386.h: New files that contain i386 specific code.
+
+Thu Aug 18 14:39:46 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * README: Grammar improvements, clarifications, updates.
+
+Wed Aug 17 23:08:53 1994 Stu Grossman (grossman@cygnus.com)
+
+ * Makefile.in (TARGET_FLAGS_TO_PASS): Pass down LD_FOR_TARGET and
+ NLMCONV_FOR_TARGET. (SUBDIRS): Add nlm target.
+ * configure.in (powerpc-*-netware*): Automatically configure nlm
+ subdir.
+ * nlm/Makefile.in: Add {CC NLMCONV LD}_FOR_TARGET. Remove alpha
+ specific stuff. Make things more configurable.
+ * nlm/configure.in: Add powerpc-*-netware* target. Use
+ gdbserve.mt/cpu.c/cpu.h for target stuff. Get rid of tm/xm/nm.h
+ files.
+ * nlm/gdbserve.c: Move Alpha specific stuff into other files.
+ Remove lots of architecture-specific stuff.
+ * nlm/gdbserve.def: Add new imports.
+ * nlm/ppc.c, nlm/ppc.h: New files that contain PowerPC specific code.
+ * nlm/prelude.c: Don't include libhooks.h, get rid of call to
+ register library.
+ * nlm/prelude.o: What was this doing here?
+ * config/alpha/gdbserve.mt: Defs for alpha nlm stub.
+ * config/powerpc/gdbserve.mt: Defs for PowerPC nlm stub.
+ * config/powerpc/ppc-nw.mt: Defs for PowerPC target for GDB.
+ * config/powerpc/tm-ppc-nw.h: Ditto.
+
+ * nlmstub.def: New file, contains imports for 386 nlm stub.
+
+Wed Aug 17 23:17:33 1994 Rob Savoye (rob@darkstar.cygnus.com)
+
+ * remote-pa.c: New file for HPPA embedded support. Currently it's
+ a copy of remote.c.
+ * config/pa/hppabsd.mt,hppahpux.mt,hppaosf.mt: User remote-pa.c.
+
+Wed Aug 17 13:19:52 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * config/m68k/tm-delta68.h (EXTRACT_RETURN_VALUE,
+ STORE_RETURN_VALUE): Define to use %a0 for pointers.
+
+Wed Aug 17 07:43:06 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * remote-mips.c: Remove unused declaration of mips_load.
+
+Tue Aug 16 16:45:34 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * coffread.c: General cleanup, and support for section offsets.
+ (time.h, sys/types.h, libbfd.h): Don't include.
+ (cur_src_start_addr, cur_src_end_addr): Rename to
+ current_source_start_addr, current_source_end_addr.
+ (nlist_stream_global): Remove.
+ (nlist_bfd_global): New global variable.
+ (coff_symfile_read): Remove code that gets and uses fileno()
+ directly.
+ (read_coff_symtab, enter_linenos, process_coff_symbol): Add
+ section_offsets parameter, add text/data section offset to
+ appropriate symbols' values.
+ (read_one_sym): Use bfd_read instead of fread.
+ (init_stringtab, init_lineno): Change first parameter to a bfd,
+ use bfd routines instead of raw I/O.
+
+Tue Aug 16 15:24:03 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * symtab.c (decode_line_1): If funfirstline and we get a
+ non-LOC_BLOCK symbol (e.g. variable or type), then error().
+
+ * Makefile.in (TARFILES, NONSRC, SFILES_STAND, SFILES_KGDB):
+ Remove; unused.
+ (TAGFILES_NO_SRCDIR): Remove ALLPARAM.
+ (HFILES_NO_SRCDIR): Remove all files in config sub-directory.
+ (TAGS): Also pass result of find on config sub-directory to etags.
+ (ALLPARAM): Remove; now unused.
+
+Sun Aug 14 13:05:26 1994 Fred Fish (fnf@cygnus.com)
+
+ * Makefile.in (VERSION): Bump to 4.13.1
+ * NEWS, README: Update to match gdb 4.13 release version.
+
+Sat Aug 13 08:22:50 1994 Fred Fish (fnf@cygnus.com)
+
+ Harris CX/UX support, from Bob Rusk (rrusk@mail.csd.harris.com).
+ * cxux-nat.c: Remove dangling #else block.
+ (m88k_harris_core_register_addr): New function.
+
+ * environ.c (init_environ): If no environment, do nothing.
+
+Fri Aug 12 19:30:53 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * hpread.c: Delete rest of TODO list. Do not include "libbfd.h",
+ <time.h>, <sys/types.h>, "demangle.h", <sys/file.h>,
+ "expression.h", "language.h", "gdbtypes.h", "demangleh".
+ Move all global variables into the private symbol table structure
+ and add accessor macros. Update some comments.
+ (hpread_build_psymtabs): Delete dbsubc_addr, we don't need it.
+ (hpread_end_psymtab): New function to end a partial symbol table,
+ all callers changed (no more bogus sharing with dbxread.c).
+
+Fri Aug 12 15:52:37 1994 Stu Grossman (grossman@cygnus.com)
+
+ * remote.c (remote_wait): Return inferior_pid instead of 0 for
+ `W` message.
+
+Fri Aug 12 11:47:10 1994 J.T. Conklin (jtc@phishhead.cygnus.com)
+
+ * sparclite/aload.c (sys_error, error): Use vfprintf for variable
+ argument lists.
+
+Thu Aug 11 04:06:42 1994 Doug Evans (dje@canuck.cygnus.com)
+
+ * defs.h (concat, basename, buildargv, freeargv, strerrno, strsigno,
+ errno_max, signo_max, strtoerrno, strtosigno): Delete.
+ Include "libiberty.h" instead.
+
+Wed Aug 10 13:23:47 1994 Rick Sladkey (jrs@world.std.com)
+
+ * i386v-nat.c (i386_insert_nonaligned_watchpoint):
+ add additional argument specifying raw address to permit
+ proper release of debug registers.
+ (i386_insert_watchpoint, i386_insert_aligned_watchpoint):
+ change all callers.
+
+Wed Aug 10 16:13:45 1994 Stu Grossman (grossman@cygnus.com)
+
+ * defs.h, top.c: Use `extern' in declarations of GUI hooks, and
+ define them in top.c. Add comments to the hooks.
+
+Wed Aug 10 15:57:43 1994 Doug Evans (dje@canuck.cygnus.com)
+
+ * remote-sim.c (gdbsim_ops): Set `to_insert_breakpoint' and
+ `to_remove_breakpoint' fields.
+
+Wed Aug 10 15:46:03 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * infcmd.c (run_command): Remove comment suggesting using
+ target_has_execution instead of inferior_pid.
+
+Wed Aug 10 10:33:20 1994 Kung Hsu (kung@mexican.cygnus.com)
+
+ * remote-mips.c (mips_open): add code to handle baud rate.
+
+Tue Aug 9 09:44:42 1994 Stu Grossman (grossman@cygnus.com)
+
+ * infrun.c (wait_for_inferior): Call target_resume() upon
+ detection of new processes.
+
+ * procfs.c (create_procinfo): Return pointer to new procinfo
+ structure.
+ * (do_detach): Spacing & formatting cleanup.
+ * (procfs_wait): Move wait_again label to ensure that we really
+ wait again. On exit from fork, release new child from gdbs'
+ clutches.
+ * (procfs_set_sproc_trap): Enable trapping of fork and vfork.
+
+Mon Aug 08 15:34:13 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * hpread.c (hpread_process_one_debug_symbol): Fix block scoping
+ problem (losing localvars on the close-brace instead of after
+ the close brace).
+
+Mon Aug 8 15:09:32 1994 J.T. Conklin (jtc@phishhead.cygnus.com)
+
+ * i386-nlmstub.c (handle_exception): Wait until the thread has
+ been started before killing the NLM by pointing the PC at
+ _exit().
+
+Sat Aug 6 22:27:30 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * config/mips/tm-irix5.h (IN_SIGTRAMP): Redefine for Irix 5,
+ Irix 5 has a standard _sigtramp signal handler.
+ * irix5-nat.c (solib_add): Get rid of sigtramp_address handling,
+ it is not needed for a standard _sigtramp signal handler.
+ Add shared library sections to the section table of the target
+ before adding the symbols.
+ * mips-tdep.c (mips_skip_prologue): Do not skip load immediate
+ instructions that do not prepare a stack adjustment.
+ * regex.c (SIGN_EXTEND_CHAR): Update to emacs-19.25 definition,
+ which does the right thing on machines where `char' is unsigned.
+
+Fri Aug 5 17:50:59 1994 Stu Grossman (grossman@cygnus.com)
+
+ * remote.c (remote_open): Move setting of inferior_pid prior to
+ call to remote_start_remote. Also use unique value for pid to
+ avoid confusion with read_register_pid & friends.
+ * (remote_wait): Return inferior_pid instead of 0 in all cases.
+
+Fri Aug 5 12:23:02 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * dwarfread.c (bfd.h): Don't include.
+
+Fri Aug 5 09:08:34 1994 J.T. Conklin (jtc@phishhead.cygnus.com)
+
+ * i386-nlmstub.c (handle_exception): Point the PC at _exit() to
+ kill the program being debugged. KillMe(), the undocumented
+ call intended for this purpose, causes the server to hang.
+
+Thu Aug 4 16:26:06 1994 Steve Chamberlain (sac@jonny.cygnus.com)
+
+ * remote.c (read_frame): Calculate run length encoded checksum
+ correctly.
+ * config/sh/stub.c: New file.
+
+Thu Aug 4 14:34:12 1994 Stu Grossman (grossman@cygnus.com)
+
+ * target.c (find_default_run_target): Make sure to_can_run is set
+ before calling it.
+
+Thu Aug 4 11:46:27 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * TODO: Remove note about fast watchpoints and remove obsolete
+ Mach stuff.
+
+Thu Aug 4 11:08:03 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * config/i386/xm-i386v4.h, config/m68k/xm-m68kv4.h,
+ config/sparc/xm-sun4sol2.h (NORETURN): Don't define.
+ * config/m88k/tm-cxux.h (ARCH_NUM_REGS): Undefine before defining.
+
+Thu Aug 4 10:26:36 1994 Stu Grossman (grossman@rtl.cygnus.com)
+
+ * target.c (add_target): Don't call clean_target on target
+ vectors anymore.
+ * (unpush_target): Test for to_close being set before calling.
+ * (target_xfer_memory, target_info): Check for to_has_memory
+ before playing with memory.
+
+ * remote.c (remote_open): Set inferior_pid to make kill command
+ happy.
+ * inflow.c (kill_command): Revert change of Aug 2. Use
+ inferior_pid to determine whether to print out "The program is not
+ being run." message.
+
+Thu Aug 4 07:55:04 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * config/i386/i386m3.mh (NAT_CLIBS): Add -lmachid and -lnetname.
+ * m3-nat.c, config/nm-m3.h: #if 0 REQUEST_QUIT stuff.
+ * m3-nat.c: Pass argument to return_to_top_level.
+ Declare m3_kill_inferior before use.
+ (port_chain_insert): In "can't happen" case, abort rather than
+ setting `mid' to large decimal constant (which gcc warns about).
+ (get_thread_name): Use cast to convert const char * to char *.
+ (add_mach_specific_commands): #if 0 "thread break" command.
+ (m3_trace_him): Call push_target.
+ (mach_really_wait): New argument pid; remove unused
+ variable pid.
+ (intercept_exec_calls): Call target_terminal_init and
+ target_terminal_inferior once the child execs.
+ * infrun.c (proceed): Pass argument to PREPARE_TO_PROCEED.
+
+Wed Aug 3 22:41:13 1994 Tom Lord (lord@x1.cygnus.com)
+
+ * procfs.c (procfs_mourn_inferior): don't dereference the
+ procinfo pointer after it has been freed.
+
+Wed Aug 3 12:05:13 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * breakpoint.c (breakpoint_1): Improve pluralization in display
+ of breakpoint hit counts.
+
+ * language.h (struct language_defn): Remove unused field
+ la_longest_float.
+ (longest_float): Remove, no longer used.
+ * language.c (unknown_language_defn, auto_language_defn,
+ local_language_defn): Remove init of la_longest_float field.
+ * c-lang.c (c_language_defn, cplus_language_defn,
+ asm_language_defn): Ditto.
+ * ch-lang.c (chill_language_defn): Ditto.
+ * m2-lang.c (m2_language_defn): Ditto.
+
+Tue Aug 2 10:58:34 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * defs.h (bfd_read, bfd_seek): Remove declarations.
+ * os9kread.c, rs6000-nat.c (libbfd.h): Don't include.
+
+Tue Aug 2 09:50:50 1994 J.T. Conklin (jtc@phishhead.cygnus.com)
+
+ * inflow.c (kill_command): Fix a bug which prevented target
+ programs to be killed.
+
+Mon Aug 1 18:48:47 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * defs.h: Change two-line declarations to one-line form.
+ (NORETURN): Define as "volatile" only for older GCCs.
+ (ATTR_NORETURN): Define for newer GCCs.
+ * procfs.c (proc_init_failed): Add ATTR_NORETURN to declaration.
+
+Mon Aug 1 16:43:24 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * breakpoint.c (mention), main.c (fputs_unfiltered): Add comments.
+ * breakpoint.c (delete_breakpoint, enable_breakpoint,
+ disable_breakpoint): Don't call breakpoints_changed; it is now
+ called via the *_breakpoint_hook functions.
+ * annotate.c (_initialize_annotate, breakpoint_changed): New functions.
+
+Mon Aug 1 13:38:04 1994 Kung Hsu (kung@mexican.cygnus.com)
+
+ * stabsread.c (read_type): Fix a bug in enum size calculation.
+
+Mon Aug 1 01:36:13 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * hppa-tdep.c (compare_unwind_entries): Add "const" to both
+ argument types to shut up GCC.
+
+ * hppa-tdep.c (saved_pc_after_call): If the saved PC is in a
+ linker stub, then return the address the stub will return to.
+ (frame_saved_pc): Correctly restart the search for the saved
+ pc when a linker stub is encountered.
+
+ * hppa-tdep.c (inst_saves_gr): Handle 16 and 8 bit instruction
+ register stores emitted by the version 9 HP compilers.
+ (inst_saves_fr): Relax test for a specific base register (%r1);
+ this avoids losing with the version 9 HP compilers.
+ (skip_prologue): Try to skip argument stores emitted by the HP
+ compilers. It's not perfect, but it's better than before.
+
+Fri Jul 29 23:20:30 1994 Stu Grossman (grossman@cygnus.com)
+
+ * findvar.c (write_pc write_pc_pid): Remove casts to long when
+ calling write_register_pid.
+ * (write_register_pid): Add prototype.
+
+Fri Jul 29 21:56:23 1994 Steve Chamberlain (sac@jonny.cygnus.com)
+
+ * remote.c (read_frame): Split readchar/checksum calculation into
+ two parts since evaluation order is undefined.
+
+Fri Jul 29 13:46:08 1994 Fred Fish (fnf@cygnus.com)
+
+ From Kevin A. Buettner (kev@cujo.geg.mot.com).
+ * Makefile.in (coredep.o): Add inferior.h as dependency.
+ * inflow.c: Add F_SETOWN to list of defines to check
+ around code that uses F_SETOWN.
+
+Fri Jul 29 09:59:05 1994 J.T. Conklin (jtc@phishhead.cygnus.com)
+
+ * Makefile.in (CC_FOR_TARGET, CXX_FOR_TARGET): If using newlib,
+ set the -L and -B directory prefixes so we can link with it.
+
+Thu Jul 28 14:37:36 1994 Stu Grossman (grossman@cygnus.com)
+
+ * Makefile.in (INSTALLED_LIBS, CLIBS, DEPFILES): Add support for
+ --enable-xxx configure option by adding ENABLE_{CLIBS DEPFILES}
+ where appropriate.
+
+ * General hackery to support alternate user-interface.
+ * breakpoint.c (mention, delete_breakpoint, enable_breakpoint,
+ disable_breakpoint): Call hooks for alternate user-interface.
+ * defs.h: Add declarations for alternate user-interface hooks.
+ * main.c (main): Add --nw (and --nowindows) options to disable
+ the GUI.
+ * (near call to command_loop): Call command_loop_hook if set.
+ * (fputs_unfiltered): Call fputs_unfiltered_hook if set.
+ * stack.c: Call print_frame_info_listing_hook if set.
+ * top.c (gdb_init): Initialize targets.c and utils.c prior to
+ other files to make sure that calls to error and warning will
+ work. Call init_ui_hook after everything else.
+ * utils.c (query): Call query_hook if set.
+ * (gdb_flush): Call flush_hook if set.
+ * Change _initialize_utils to initialize_utils cuz we don't use
+ automatic initialization of utils.c anymore.
+
+
+ * remote.c: Get rid of #ifdef DONT_USE_REMOTE. It's no longer
+ necessary.
+
+Thu Jul 28 14:52:01 1994 J.T. Conklin (jtc@phishhead.cygnus.com)
+
+ * Makefile.in (CC_FOR_TARGET, CXX_FOR_TARGET): Use newlib if it is
+ there and we are using the gcc from the tree.
+ (LD_FOR_TARGET): Look for ld in ../ld/ld.new.
+
+Thu Jul 28 10:43:36 1994 Fred Fish (fnf@cygnus.com)
+
+ * Makefile.in (annotate.o): Add dependencies.
+
+Wed Jul 27 14:34:42 1994 J.T. Conklin (jtc@phishhead.cygnus.com)
+
+ * sparclite/aload.c: Added new -q (quiet) option.
+ return 0 exit status if file was successfully downloaded.
+
+ * nlm/gdbserve.c: merge in command line argument parsing changes
+ and bug fixes made to i386-nlmstub.c.
+
+ * i386-nlmstub.c: The returnLength field must be initialized
+ before portConfig is passed to AIOGetPortConfiguration.
+ Compare command line arguments with strnicmp(); args are
+ case insensitive on netware.
+
+Wed Jul 27 09:24:19 1994 Fred Fish (fnf@cygnus.com)
+
+ * Makefile.in (DISTSTUFF): Add definition.
+ (diststuff): Add for new distribution support.
+ (gdb.tar.Z, make-proto-gdb.dir, setup-to-dist,
+ gdb-$(VERSION).tar.Z, make-proto-gdb-1, make-proto-testsuite.dir):
+ Remove old distribution building rules, now uses standard
+ distribution support in parent directory Makefile.in.
+
+Tue Jul 26 14:15:53 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * target.c (push_target): Cast result from xmalloc.
+
+Tue Jul 26 18:20:46 1994 Paul Flinders (ptf@smee)
+
+ * elfread.c (elf_symtab_read): Discard compiler labels generated
+ by the Solaris 2.1/Intel SunPro compiler.
+
+Mon Jul 25 18:19:24 1994 Stu Grossman (grossman@cygnus.com)
+
+ * target.c (nomemory): Fix prototype and routine to take correct
+ args.
+
+Mon Jul 25 15:38:23 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * Makefile.in (clean): Remove libgdb-files.
+
+Mon Jul 25 11:50:57 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * coredep.c: Include inferior.h.
+
+Mon Jul 25 11:36:02 1994 J.T. Conklin (jtc@phishhead.cygnus.com)
+
+ * i386-nlmstub.c: Add support for NODE, PORT and BAUD command
+ line arguments.
+
+Sat Jul 23 14:36:09 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * symfile.c (deduce_language_from_filename): Recognize .S as asm,
+ .cp as C++, alphabetize better.
+
+ * breakpoint.c (ignore, condition): Move usage note into body of
+ help text, so first line can be one-line summary.
+
+Sat Jul 23 00:58:15 1994 Stu Grossman (grossman@cygnus.com)
+
+ * target.c (unpush_target): Fix handling of removal of top target.
+
+Fri Jul 22 17:30:39 1994 Stu Grossman (grossman@cygnus.com)
+
+ * Makefile.in: Add stuff to build nlmstub.
+ * Add rule for annotate.o to keep Sun make happy.
+ * configure.in: Add config for powerpc/Netware.
+
+ * partial-stab.h (near N_SO): Don't call START_PSYMTAB with null
+ filename. This speeds up handling of trailing N_SO stabs (they
+ mark the end of a .o file).
+
+ * target.c, target.h: Change the way pushing and popping of
+ targets work to support target overlays and inheritance.
+ * corelow.c, hppa-tdep.c, inflow.c, remote-nindy.c, utils.c:
+ Fixup references to current_target, due to previous changes.
+
+ * config/i386/tm-i386nw.h: Enable longjmp support. More work is
+ needed to get the address of longjmp out of the target.
+
+Tue Jul 19 13:25:06 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * main.c: Include <ctype.h>.
+
+Mon Jul 18 15:32:17 1994 Kung Hsu (kung@mexican.cygnus.com)
+
+ * remote-mips.c (mips_readchar): Fix a bug in checking <IDT>
+ prompt.
+
+Mon Jul 18 14:26:35 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * solib.c (look_for_base): Don't deref exec_bfd if NULL.
+
+Sun Jul 17 15:38:36 1994 Fred Fish (fnf@cygnus.com)
+
+ * Makefile.in (VERSION): Bump to 4.12.4.
+
+Sun Jul 17 12:20:35 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ Harris CX/UX support, from Bob Rusk (rrusk@mail.csd.harris.com).
+ * configure.in (m88*-harris-cxux*): New configuration.
+ * cxux-nat.c, config/m88k/cxux.mh, config/m88k/cxux.mt,
+ config/m88k/xm-cxux.h, config/m88k/tm-cxux.h, config/m88k/nm-cxux.h:
+ New files.
+ * config/m88k/tm-m88k.h: Add comment about Harris OS.
+ (TARGET_WRITE_PC): Pass pid through to register writers.
+
+ * configure.in (m68*): Put vendor-only-specified host configs
+ after vendor-and-os-specified configs.
+ (m68*-atari-sysv4*, m68*-cbm-sysv4*): Replace with m68*-*-sysv4.
+
+ * config/m88k/delta88.mh (MUNCH_DEFINE): Remove.
+ * config/m88k/delta88.mt, config/m88k/delta88v4.mh: Format
+ consistently.
+
+Sat Jul 16 23:39:17 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * elfread.c (elf_symtab_read): Handle error return from
+ bfd_get_dynamic_symtab_upper_bound gracefully.
+
+Sat Jul 16 14:43:17 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * inferior.h (ARCH_NUM_REGS): New macro, actual number of
+ registers in use by the inferior.
+ * coredep.c (fetch_core_registers, register_addr): Use it.
+ * findvar.c (registers_changed, registers_fetched,
+ read_register_bytes): Ditto.
+ * infcmd.c (do_registers_info, registers_info): Ditto.
+ * infptrace.c (fetch_inferior_registers,
+ store_inferior_registers): Ditto.
+ * stack.c (frame_info): Ditto.
+
+ * coredep.c (CORE_REGISTER_ADDR): New macro.
+ (fetch_core_registers): Use it.
+
+ * breakpoint.c (ignore, condition): Add usage notes to help strings.
+ * symfile.c (add-symbol-file): Add usage note to help string.
+ (add_shared_symbol_files_command): New command.
+
+ gcc -Wall lint.
+ * inferior.h (read_pc_pid): Declare.
+ * breakpoint.c (watchpoint_check): Cache breakpoint in local
+ variable b, remove unused variable other_type_used.
+ * main.c (inferior.h, call-cmds.h): Include.
+ (gdb_init): Declare.
+ * remote.c (remote_wait): Return 0 by default.
+
+Fri Jul 15 16:43:33 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ Stop printing at null char option, from Oliver Meyer
+ (omeyer@i3.informatik.rwth-aachen.de).
+ * valprint.h, valprint.c (stop_print_at_null): New global.
+ * valprint.c (_initialize_valprint): New print set subcommand
+ "null-stop".
+ * c-valprint.c (c_val_print): If stop_print_at_null is on, and
+ printing a char array, adjust the number of chars to print.
+
+Fri Jul 15 14:33:40 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ From Kevin A. Buettner (kev@cujo.geg.mot.com).
+ * m88k-tdep.c (examine_prologue): Modified to handle prologues for
+ pic code in addition to prologues where an instruction from the
+ prologue gets moved into the delay slot of a branch instruction
+ immediately following the prologue. A table of potential prologue
+ instructions (prologue_insn_tbl) is now used for picking apart a
+ function prologue.
+ (frame_find_saved_regs): Changed the way in which limit gets set
+ so that the delay slot of branch instructions immediately
+ following the prologue gets examined.
+ (pushed_size, store_parm_word, store_parm, push_parameters,
+ collect_returned_value): Deleted.
+
+Fri Jul 15 01:06:00 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * infrun.c (wait_for_inferior): Handle stepping into leaf
+ functions whose prologue consists of gp loading code only.
+
+Thu Jul 14 14:22:12 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * dbxread.c: Don't include libbfd.h.
+ * dwarfread.c, elfread.c somread.c: Don't include libbfd.h,
+ <time.h>, or <sys/types.h>.
+ * elfread.c (elf_symfile_read): Use only standard BFD functions to
+ collect information about the stab and stab string sections.
+
+Thu Jul 14 13:17:39 1994 Kung Hsu (kung@x1.cygnus.com)
+
+ * stabsread.c (read_huge_number): handle large unsigned number
+ for stabs generated by os9k C compiler.
+
+Wed Jul 13 18:58:15 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ Breakpoint hit counts, from Bob Rusk (rrusk@mail.csd.harris.com).
+ * breakpoint.h (hit_count): New breakpoint field.
+ * breakpoint.c (show_breakpoint_hit_counts): New variable.
+ (clear_breakpoint_hit_counts): New function.
+ (bpstat_stop_status): Increment the hit count.
+ (breakpoint_1): Display the hit count.
+ * infcmd.c (run_command): Reset breakpoint hit counts.
+ * target.c (generic_mourn_inferior): Don't clear ignore counts if
+ displaying hit counts.
+
+Tue Jul 12 12:23:15 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * elfread.c (elf_symfile_read): Unconditionally add dynamic
+ symbols for all symbol files. Makes skipping over the
+ trampoline code work when stepping from a function in a shared
+ library into a function in a different shared library for Irix 5.
+ Other ELF targets do not have enough information in their
+ dynamic symbol tables to make this work.
+ (elf_symtab_read): Relocate mst_solib_trampoline address.
+
+Mon Jul 11 16:38:49 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ Atari support, from Uwe Seimet (seimet@chemie.uni-kl.de).
+ * configure.in (m68*-atari-sysv4*): New configuration.
+ (m68*-cbm-sysv4*): Use m68kv4 instead of amix.
+ * m68k-tdep.c (R_PS): Define as R_SR if necessary.
+ * config/m68k/m68kv4.mh, config/m68k/m68kv4.mt,
+ config/m68k/tm-m68kv4.h, config/m68k/xm-m68kv4.h: New files.
+ * config/m68k/amix.mh, config/m68k/amix.mt,
+ config/m68k/tm-amix.h, config/m68k/xm-amix.h: Removed, superseded
+ by m68kv4 files.
+
+Sat Jul 9 16:28:43 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * symtab.c (find_function_start_sal): New function to find
+ the start of a function from a function symbol.
+ (decode_line_1, decode_line_2): Use it instead of open coded
+ partial copies of the code.
+ (list_symbols): Quote symbol name before passing it to
+ break_command to enable proper handling of mangled symbols.
+
+Wed Jul 6 20:22:07 1994 Per Bothner (bothner@kalessin.cygnus.com)
+
+ * ch-exp.y (match_simple_name_string): Don't lower-case here.
+ * ch-exp.y (yylex): First try name lookup using exact name
+ typed by user; if that fails, try lower-cased name.
+
+Wed Jul 06 12:39:07 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * hpread.c: More cleanups. Delete lots of trailing whitespace.
+ Remove some items from the TODO list and notes throughout code
+ for things which need fixing. Add more comments.
+ Document bogus struct symloc sharing with dbxread.c. Delete more
+ useless variables. Add more PARAM prototypes. Fixup more
+ indention problems that have crept in.
+ (SET_NAMESTRING): Accept new namep and objfile arguments so that
+ it doesn't depend on the variable names on the procedures it's
+ used from.
+ (hpread_symfile_init): Delete incorrect checks for bogus sizes of
+ the debug sections.
+
+Wed Jul 6 00:48:57 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * dbxread.c, elfread.c, mipsread.c, nlmread.c, os9kread.c:
+ Move "no debugging symbols found" test to symfile.c.
+ * symfile.c (syms_from_objfile, reread_symbols): Add
+ "no debugging symbols found" test.
+ * coffread.c (init_stringtab): Handle stripped files with a
+ stringtab offset of zero gracefully.
+ * osfsolib.c (solib_create_inferior_hook): Use DYNAMIC flag from
+ BFD instead of stop_pc heuristic to determine if it is a dynamically
+ linked object file.
+ * procfs.c (wait_fd): Handle ENOENT error return from PIOCWSTOP
+ ioctl, it indicates that the process has exited.
+
+Mon Jul 04 19:48:03 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * hpread.c (hpread_symfile_init): Make sure to initialize all the
+ private data to zero. Not having any HP C debug symbols is not an
+ error. Just return.
+
+Mon Jul 4 19:28:56 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * hppa-tdep.c (read_unwind_info): ELF unwind information is in the
+ .PARISC.unwind section now.
+
+Mon Jul 4 17:06:26 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * breakpoint.c (mention): Always show breakpoint address if no
+ source file.
+
+Sat Jul 2 01:51:33 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * solib.c (bfd_lookup_symbol, look_for_base): Reinstate to reenable
+ handling of shared libraries for non-ELF executables, but only if
+ HANDLE_SVR4_EXEC_EMULATORS is defined.
+ (locate_base): Try to find debug_base in the dynamic linker
+ for non-ELF executables if HANDLE_SVR4_EXEC_EMULATORS is defined.
+ * config/sparc/tm-sun4sol2.h (HANDLE_SVR4_EXEC_EMULATORS):
+ Define to enable handling of shared libraries for a.out executables,
+ run under Solaris BCP.
+
+Fri Jul 01 19:50:21 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * hpread.c: Change contribution notice to the Cygnus/Utah agreed
+ upon notice. Delete some stuff from the TODO list. Rework
+ many comments to be clearer. Major cleanups. Consistently
+ use "hpread_" prefix. Delete unnecessary macros, structures
+ variables, fiels, functions and #if 0 code. Mark code which
+ still needs to be cleaned up. PARAMize and make most functions
+ static. Fix error checking when reading in the debug section
+ contents. No more minimal symbol table handling in this code!
+
+Thu Jun 30 13:59:23 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * infrun.c (wait_for_inferior): Print "Program exited normally"
+ regardless of batch_mode.
+ * defs.h, top.c (batch_mode): Removed.
+
+Wed Jun 29 18:53:36 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * Makefile.in (dcache_h): Remove redundant definition.
+ (init.c): Add a comment.
+ (top.c): Remove explicit compile action.
+ * breakpoint.c (mention): Share code indicating location of
+ break/watchpoints, don't print address if addressprint is off.
+ * breakpoint.c, c-typeprint.c, c-valprint.c, energize.c, symtab.h
+ (demangle): Remove redundant declarations.
+ * eval.c: Remove redundant function declarations.
+ * objfiles.h: Cosmetic and grammatical improvements.
+ * TODO: Various updates.
+
+ * remote-mips.c: Replace all \r chars with \015.
+ (mips_receive_header): Display control characters readably.
+ (mips_xfer_memory): Add a simple progress display.
+
+Wed Jun 29 13:11:45 1994 Steve Chamberlain (sac@cirdan.cygnus.com)
+
+ * remote-e7000.c (e7000_open): Don't try a tcp open if we're
+ using go32.
+ * remote-hms.c (flush): New function.
+ (expect): Get edge case right.
+ (hms_read_inferior_memory): Be more tolerant of line noise.
+
+Tue Jun 28 14:17:03 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * configure.in: Use i386m3.mh and i386m3.mt as names of host and
+ target files, not non-existent mach3.mh and mach3.mt.
+
+Wed Jun 29 00:26:17 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * dbxread.c (dbx_symfile_read): Unconditionally add dynamic
+ symbols for all symbol files. Makes skipping over the
+ trampoline code work when stepping from a function in a shared
+ library into a function in a different shared library.
+ (read_dbx_dynamic_symtab): Relocate mst_solib_trampoline address.
+
+Tue Jun 28 15:28:01 1994 Stu Grossman (grossman@cygnus.com)
+
+ * dbxread.c, partial-stab.h (near N_SO): SO stabs with blank
+ names mean end of .o file.
+ * infrun.c (wait_for_inferior): Clean up multi-thread logic near
+ top of routine. Handle new thread notification cleanly.
+ * lynx-nat.c (child_wait): General cleanups, handle new LynxOS
+ thread notification scheme.
+ * (child_resume): General cleanups, handle resumption of all
+ threads properly.
+
+Mon Jun 27 09:57:23 1994 Steve Chamberlain (sac@cirdan.cygnus.com)
+
+ * ser-go32.c: Rewrite to run under windows.
+ * ser-e7kpc.c: New file to support the E7000 with the PC ISA
+ bus interface.
+ * serial.c (serial_open): Notice device "pc".
+ * remote-e7000.c: Fix copyright date.
+ (expect): Compare \n and \r the same.
+ (e7000_open): Allow pc as a serial port
+ * sh/sh.mt: Add ser-e7kpc.
+ * h8300/h8300hms.mt: Add ser-e7kpc.
+ * main.c (proc_wait): Don't wait if using go32.
+
+Mon Jun 27 00:35:51 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * somread.c: Simplify by using stabsect_build_psymtabs.
+ * dbxread.c (stabsect_build_psymtabs): New argument "text_name"
+ corresponding to the name of the text section. All references
+ changed.
+ (somstab_build_psymtabs): Delete function, no longer needed.
+
+Sun Jun 26 23:54:08 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * somread.c: Renamed from paread.c. Changed function names and
+ comments to reflect that this file deals with SOM (an object file
+ format), rather than the PA (a cpu).
+ (Makefile.in): Chaned appropriately.
+ (config/pa/hppabsd.mh, config/pa/hppahpux.mh): Likewise.
+ * dbxread.c (somstab_build_psymtabs): Renamed from
+ pastab_build_psymtabs.
+
+Fri Jun 24 08:15:42 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * core-sol2.c: New file to handle ELF and BCP core file flavours.
+ * config/sparc/sun4sol2.mh (NATDEPFILES): Use it instead of
+ core-svr4.
+ * Makefile.in: Updated for core-sol2.c.
+ * README: Add notes about SPARCworks cc under Solaris 2.x,
+ from Casper H.S. Dik (casper@fwi.uva.nl).
+ * config/mips/xm-makeva.h: Removed, no longer necessary.
+ * Makefile.in, config/mips/xm-irix3.h, config/mips/xm-irix5.h,
+ config/mips/xm-mips.h, config/mips/xm-news-mips.h,
+ config/mips/xm-riscos.h: Remove references to xm-makeva.h
+
+Wed Jun 22 17:48:21 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdba.el: Put program input and output in a separate buffer.
+
+Wed Jun 22 16:54:15 1994 Fred Fish (fnf@cygnus.com)
+
+ * energize-patches, main.c (main), top.c (gdb_init, pwd_command),
+ top.h: Change all occurances of dirbuf to gdb_dirbuf. Collides
+ with global variable of same name in libnsl.so on UnixWare.
+
+Wed Jun 22 14:40:52 1994 Kung Hsu (kung@mexican.cygnus.com)
+
+ * symtab.c (decode_line_1): fix a bug in dealing with '<>'
+ embedded in template name.
+
+Tue Jun 21 14:06:46 1994 Kung Hsu (kung@mexican.cygnus.com)
+
+ * config/i386/nm-linux.h: change calling convention of
+ TARGET_CAN_USE_HARDWARE_WATCHPOINT() and
+ target_insert_watchpoint() and
+ target_remove_watchpoint().
+
+ * config/mips/tm-mips64.h: define FORCE_LONG_LONG to force LONGEST
+ to be long long in gdb.
+ * config/mips/tm-bigmips.h: ditto.
+
+Mon Jun 20 23:54:37 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * c-lang.c (asm_language_defn): New definitions for language_asm,
+ mostly copied from c_language_defn, to avoid warnings when
+ switching between c and asm stack frames.
+
+Mon Jun 20 13:51:55 1994 Ian Lance Taylor (ian@sanguine.cygnus.com)
+
+ * mdebugread.c (parse_symbol): Don't call ecoff_swap_tir_in or
+ ecoff_swap_rndx_in directly; use the debug_swap pointer instead.
+ (upgrade_type, handle_psymbol_enumerators): Likewise.
+ (has_opaque_xref, cross_ref): Likewise.
+ (elfmdebug_build_psymtabs): Call swap->read_debug_info to read
+ debugging information, rather than doing it here.
+ * mipsread.c (mipscoff_symfile_read): Call read_debug_info entry
+ point in ecoff_debug_swap backend structure, rather than calling
+ ecoff_slurp_symbolic_info directly.
+
+Fri Jun 17 20:58:58 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * breakpoint.c: Include annotate.h. Call annotate_field rather
+ than printing annotation directly.
+
+ * main.c: Include string.h.
+
+Thu Jun 16 14:41:37 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * fork-child.c (startup_inferior) [STARTUP_INFERIOR]: If defined,
+ call it instead of doing normal loop.
+ * infcmd.c (attach_command): Don't call wait_for_inferior if
+ running Mach 3.
+ * infrun.c (proceed) [PREPARE_TO_PROCEED]: If defined, call
+ hook that can decide whether to step over the next breakpoint.
+ * utils.c (wrap_here): Abort if wrap_buffer not allocated.
+ (request_quit) [REQUEST_QUIT]: If defined, call it instead of
+ doing normal quit.
+
+ * configure.in: Improve sorting/formatting of hosts and targets.
+ (i[34]86-*-mach3*, i[34]86-*-osf1mk*, mips-*-mach3*,
+ m88*-*-mach3*, ns32k-*-mach3*): Recognize.
+ * Makefile.in (stop-gdb): New target.
+ * stop-gdb.c: New file, utility to get attention of waiting GDBs
+ in Mach 3.
+
+Wed Jun 15 00:41:03 1994 Tom Lord (lord@rtl.cygnus.com)
+
+ * top.c (gdb_init): Init current_directory in gdb_init. Probably
+ the identical initialization can be deleted from main.c, but i
+ haven't done so just in case.
+
+Tue Jun 14 17:24:41 1994 Tom Lord (lord@x1.cygnus.com)
+
+ * gdba.el: Added menu windows and slightly improved window
+ handling to gdba.el. Fixed numerous minor bugs that were causing
+ emacs and gdb to fall out of sync.
+
+Tue Jun 14 16:18:44 1994 Kung Hsu (kung@mexican.cygnus.com)
+
+ * breakpoint.c: annotate changes lost at merge, put back in.
+
+Mon Jun 13 17:28:50 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * config/i386/i386sco.mh, i386sco4.mh (XDEPFILES): Remove
+ i387-tdep.o.
+
+Sun Jun 12 03:51:52 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * config/m68k/dpx2.mh (NATDEPFILES): Remove duplicate inclusion
+ of inftarg.o.
+ * config/m68k/tm-dpx2.h (CANNOT_STORE_REGISTER): Define to inhibit
+ writing of floating registers, the dpx2 kernel disallows it.
+ * irix5-nat.c (LM_ADDR): The loaded address of the shared library
+ is contained in o_praw.
+ * irix5-nat.c (solib_map_sections): Adjust sections by the
+ difference between the loaded address and the prelinked address.
+ * irix5-nat.c (solib_address): Use LM_ADDR for the loaded start
+ address.
+ * mdebugread.c (parse_symbol): Do not relocate stEnd/scText
+ symbols, their value is absolute.
+ * mdebugread.c (parse_partial_symbols): Handle Irix 5.2 shared
+ libraries fh->adr fields of zero. Relocate minimal symbol values
+ upon readin. Relocate non-stabs symbols upon readin.
+ * mdebugread.c (psymtab_to_symtab_1): Use pst->textlow for the
+ start address of the outermost block.
+ * mdebugread.c (parse_lines, parse_procedure): Pass in pst
+ instead of section_offsets and use relocated pst->textlow for
+ line number and procedure address relocations.
+
+ From gmo@MicroUnity.com (Guillermo A. Loyola):
+ * mdebugread.c (parse_symbol, parse_partial_symbols, cross_ref):
+ Handle SGI Irix5 stIndirect symbol type.
+
+Fri Jun 10 14:52:56 1994 Kung Hsu (kung@mexican.cygnus.com)
+
+ * breakpoint.c: fix a syntax error native cc does not like.
+
+ * Makefile.in: change sparclite-tdep.c to sparcl-tdep.c.
+ * sparclite/Makefile.in: ditto.
+ * sparcl-tdpe.c: change file name because first 8 chars has to be
+ unique.
+ * sparcl-stub.c: ditto.
+
+ * sparclite/Makefile.in: fix INCLUDE_CFLAGS to have {srcdir}/../config.
+
+Fri Jun 10 10:38:15 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * hppa-tdep.c (target_read_pc, target_write_pc): Accept (and
+ ignore) a PID argument.
+ (hppa_pop_frame): Pass a PID to target_write_pc.
+ * config/pa/tm-hppa.h (TARGET_READ_PC, TARGET_WRITE_PC): Accept
+ and pass through a PID argument.
+ (target_read_pc, target_write_pc): Update prototypes.
+
+Thu Jun 9 18:10:44 1994 Kung Hsu (kung@mexican.cygnus.com)
+
+ * Makefile.in: add new file sparclite-tdep.c.
+ * sparclite/Makefile.in: add new file sparclite-stub.c.
+ * sparclite/hw_breakpoint.note: note for SPARClite hardware breapoint
+ support.
+ * config/sparc/sparclite.mt: add sparclite-tdep.o.
+ * config/sparc/tm-sparclite.h: add hardware breakpoints support
+ defiines and code.
+ * sparclite-tdep.c: new file, contains hardware breakpoint support
+ code.
+ * sparclite-stub.c: new file, stub code that add support hardware
+ breakpoint support.
+ * breakpoint.c: add hardware breakpoint support.
+ * breakpoint.h: add new breakpoint type to support hardware
+ breakpoint.
+ * config/mips/nm-irix4.h: change interface for target dependent
+ code supporting watch point.
+ * config/pa/nm-hppab.h: change interface for target dependent
+ code supporting watch point.
+
+Thu Jun 9 14:59:58 1994 Kung Hsu (kung@mexican.cygnus.com)
+
+ * remote-os9k.c (rombuf_command): fix a bug accepting rombug
+ output.
+ * stabsread.c (read_struct_fields): os9k nested structure does not
+ have terminating ';', instead it just get to ',' and bit position
+ and length.
+
+Wed Jun 8 23:20:45 1994 Stu Grossman (grossman@cygnus.com)
+
+ * nlmread.c (nlm_symtab_read): Clean up a bit.
+ * (nlm_symfile_read): Record bounds of main() so that backtrace
+ command will know where to stop.
+ * objfiles.c (objfile_relocate): Relocate entry point/func info
+ for backtrace as well.
+ * objfiles.h: Define values for invalid PCs for entry point info.
+ * symfile.c (init_entry_point_info): Initialize invalid values
+ with aforementioned macros.
+ * config/alpha/tm-alphanw.h: Turn on FRAME_CHAIN_VALID_ALTERNATE
+ to cause backtrace to stop when it gets back to main().
+ * config/i386/tm-i386nw.h: Ditto.
+
+Sat Jun 4 18:17:03 1994 Per Bothner (bothner@kalessin.cygnus.com)
+
+ Fix value_print, which used to be ostensibly language-independent,
+ but would print pointers and arrays in C syntax. Instead, call
+ a language-specific function.
+ * language.h (struct language_defn): New functional field
+ la_value_print.
+ (LA_VALUE_PRINT): New macro.
+ * language.c (unk_lang_value_print): New stub/dummy function.
+ (unknown_language_defn, auto_language_defn, local_language_defn):
+ Use it.
+ * c-valprint.c (c_value_print): New function, with code moved from:
+ * valprint.c (value_print): ... here. Now just invoke
+ LA_VALUE_PRINT to do language-specific stuff.
+ * valprint.c (value_print_array_elements): Make non-static.
+ * c-lang.c (c_language_defn, cplus_language_defn): Add
+ c_value_print in the la_value_print field.
+ * m2-lang.c (m2_language_defn): Likewise.
+ * ch-lang.c (chill_language_defn): But here use chill_value_print.
+ * ch-valprint.c (chill_val_print): Print null pointer as NULL.
+ * ch-valprint.c (chill_value_print): New function, based on
+ c_value_print, but use Chill "look and feel."
+ * c-lang.h (c_value_print): New prototype.
+ * ch-lang.h (chill_value_print): New prototype.
+ * value.h (value_print_array_elements): New prototype.
+
+ * ch-valprint.c (chill_val_print, case TYPE_CODE_BITSTRING
+ and case TYPE_CODE_SET): Check that the element type isn't a stub.
+
+Fri Jun 3 09:15:00 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * main.c: Move entire file except for #ifndef MAIN_OVERRIDE code
+ to new file top.c. Make things extern instead of static and
+ similar rearrangements to deal with this.
+ * top.h: New file.
+ * utils.c: Move fputs_unfiltered to main.c. Remove
+ FPUTS_UNFILTERED_OVERRIDE ifndef.
+ * Makefile.in: Change so that gdb uses main.c, utils.c, and top.c,
+ and libgdb uses utils.c and top.c.
+
+Thu Jun 2 23:19:10 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * hppa-tdep.c (skip_trampoline_code): Fix typo.
+
+Thu Jun 2 18:09:59 1994 Per Bothner (bothner@kalessin.cygnus.com)
+
+ * ch-valprint.c (chill_val_print_array_elements): New function.
+ A Chill version of val_print_array_elements, it prints the
+ array index labels, in additions ot the array element values.
+ (chill_val_print): Use the new function.
+
+Thu Jun 2 08:50:00 1994 Stu Grossman (grossman@cygnus.com)
+
+ * configure.in: Add nlm subdir to configdirs for alpha-*-netware
+ target.
+ * defs.h (enum language): Add language_asm.
+ * findvar.c (read_register_bytes read_register_gen
+ write_register_bytes read_register read_register_pid
+ write_register write_register_pid supply_register): Move multi-
+ thread handling down into these routines. Create XXX_pid routines
+ that allow register references to specify the pid.
+ * findvar.c infcmd.c (read_pc read_pc_pid write_pc write_pc_pid
+ read_sp write_sp read_fp write_fp): Move these routines from
+ infcmd to findvar to centralize the whole mess.
+ * i386-nlmstub.c: Portability fixes.
+ * infptrace.c (child_resume): Conditionalize to allow other natives
+ to override it. Remove PIDGET gubbish, it's no longer necessary.
+ * infrun.c (wait_for_inferior): Put registers_changed() before
+ target_wait() to speed up remote debugging.
+ * Replace code that reads registers from other threads with much
+ nicer looking new function calls (see changes to findvar.c).
+ * Don't skip prologues if debugging assembly source.
+ * lynx-nat.c (child_resume): Lynx now needs it's own version of
+ child_resume to handle multi-thread debugging properly.
+ * remote.c: Add O response to get console output from target.
+ * (readchar): Add timeout parameter. Handle SERIAL_EOF and
+ SERIAL_ERROR here to simplify callers.
+ * Change static var timeout to remote_timeout.
+ * (fromhex): Remove unnecessary return -1 at end of routine.
+ * (remote_wait): Turn this into a big switch statement. Add
+ support for O response.
+ * (putpkt): Remove unnecessary handling of SERIAL_EOF/ERROR.
+ * (getpkt): Split getpkt into two parts. read_frame deals with
+ all formatting issues, run-length encoding, and framing. getpkt
+ now handles error recovery, and frame detection.
+ * ser-tcp.c (tcp_readchar): Handle EINTR from read().
+ * ser-unix.c (hardwire_raw): Set CLOCAL so that we ignore modem
+ control. (hardwire_readchar): Handle EINTR from read().
+ * symfile.c (deduce_language_from_filename): Add support for .s
+ files.
+ * config/nm-lynx.h: Define CHILD_WAIT so that lynx-nat.c can
+ override infptrace's child_wait.
+ * config/rs6000/rs6000lynx.mh: Use xm-rs6000ly.h & nm-rs6000ly.h
+ instead of XXXlynx.h.
+ * config/rs6000/rs6000lynx.mt: Use tm-rs6000ly.h instead of
+ tm-rs6000lynx.h.
+ * nlm/gdbserve.c: Portability fixes.
+
+Tue May 31 20:35:44 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * inftarg.c (child_wait): Call proc_wait, not wait.
+ (child_mourn_inferior): Call proc_remove_foreign.
+ * main.c (gdb_init): Call init_proc.
+ * main.c: Provide dummy versions of init_proc, proc_wait, and
+ proc_remove_foreign for the gdb case (the libgdb case provides its
+ own versions of these functions).
+ * Makefile.in (libgdb-files): Add libproc.a.
+
+Wed Jun 1 11:08:52 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ Hardware watchpoints for Linux, from Rick Sladkey
+ (jrs@world.std.com).
+ * infrun.c (wait_for_inferior) [HAVE_CONTINUABLE_WATCHPOINT]: Add
+ new hardware breakpoint recovery method.
+ * i386v-nat.c (i386_insert_watchpoint,
+ i386_insert_nonaligned_watchpoint, i386_remove_watchpoint,
+ i386_stopped_by_watchpoint) [TARGET_CAN_USE_HARWARE_WATCHPOINT]:
+ New functions to support the 386 hardware debugging registers.
+ * config/i386/nm-linux.h (TARGET_CAN_USE_HARDWARE_WATCHPOINT,
+ HAVE_CONTINUABLE_WATCHPOINT, STOPPED_BY_WATCHPOINT,
+ target_insert_watchpoint, target_remove_watchpoint): Define these
+ macros to use the hardware debugging functions in i386v-nat.c.
+
+Wed May 25 17:06:15 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * Makefile.in: Replace libgdb.a with libgdb-files. Make "all"
+ build it.
+
+Thu May 19 09:56:20 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * target.c, target.h: New variables target_activity_function and
+ target_activity_fd.
+ * inflow.c, inferior.h: New functions set_sigio_trap and
+ clear_sigio_trap.
+ * inftarg.c (child_wait), procfs.c (wait_fd): Call them.
+
+Wed May 18 13:01:55 1994 Doug Evans (dje@canuck.cygnus.com)
+
+ * remote-sim.h (sim_verbose): Delete.
+ Document callbacks needed.
+ (sim_*): Change result to void where there isn't one.
+ (sim_open): Clarify argument and error response.
+ (sim_close): Declare.
+ (sim_load): Change bfd_handle argument to file name. Clarify result.
+ (sim_create_inferior): Renamed from sim_set_args.
+ (sim_set_pc): Delete.
+ (sim_info): Delete printf_fn argument.
+ * remote-sim.c (gdbsim_kill): Add comment describing purpose.
+ (gdbsim_load): Try sim_load first.
+ (gdbsim_create_inferior): Call sim_create_inferior.
+ (gdbsim_open): Handle args == NULL. Update call to sim_open.
+ (gdbsim_close): Call sim_close.
+ (gdbsim_files_info): Update call to sim_info.
+ (gdbsim_ops): Realign comments.
+
+ * printcmd.c (decode_format): Allow TARGET_PTR_BIT to be non-constant.
+
+Tue May 17 16:45:20 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * xcoffread.c (read_xcoff_symtab): For C_FILE symbols, only use
+ the auxent if the symbol's name is ".file". From David Edelsohn
+ <c1dje@watson.ibm.com>.
+
+Tue May 17 11:08:22 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * breakpoint.c (breakpoint_1): Fix typo.
+
+ * annotate.c (annotate_field_end): Fix typo.
+
+ * Makefile.in: Move annotate.o from COMMON_OBS to OBS.
+
+ * Makefile.in (TSSTART): Remove; no longer used.
+
+ * utils.c (vfprintf_maybe_filtered, vfprintf_unfiltered): Call
+ fputs_unfiltered and exit directly, rather than fatal. The latter
+ calls vfprintf_unfiltered!
+
+ * gdbtypes.h, gdbtypes.c (can_dereference): New function.
+ * value.h, printcmd.c (print_value_flags): Move from here...
+ * annotate.c: ...to here, and make it use can_dereference.
+
+Sat May 14 15:13:52 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * inflow.c (job_control, attach_flag, generic_mourn_inferior):
+ Remove, needed for both native and cross.
+ * target.c (attach_flag, generic_mourn_inferior): Put here.
+ * utils.c (job_control): Put here.
+ (terminal.h): Don't include anymore.
+
+Sat May 14 09:11:44 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * source.c (find_source_lines): Always use code that was #ifdef
+ BROKEN_LARGE_ALLOCA. Do the cleanup before returning, rather than
+ leaving it on the chain. Reindent much of this function.
+ * config/sparc/{xm-sun4sol2.h,xm-sun4os4.h},
+ config/i386/{xm-sun386.h,xm-i386m3.h,xm-i386mach.h},
+ config/m68k/{sun3os4.h,xm-news.h,xm-hp300hpux.h},
+ config/ns32k/xm-ns32km3.h: Remove all references to
+ BROKEN_LARGE_ALLOCA; with the above change it is no longer needed.
+ * main.c, fork-child.c, many config files: Remove all
+ SET_STACK_LIMIT_HUGE code; with the above changes it should no
+ longer be needed.
+
+ * symtab.c (lookup_partial_symbol): Use if and abort, not assert.
+ This avoids __eprintf troubles.
+
+Fri May 13 08:10:21 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * main.c (main): Surround in #ifndef MAIN_OVERRIDE. Move
+ initialization code which needs to be called even if we bypass the
+ command line stuff into gdb_init.
+ * utils.c (fputs_unfiltered): Surround in #ifndef
+ FPUTS_UNFILTERED_OVERRIDE.
+ * Makefile.in (libgdb.a): New target.
+
+ * utils.c: Rearrange I/O stuff a bit so that all output goes
+ through fputs_unfiltered. Use vasprintf; removes arbitrary limit
+ which made %s not work with arbitrarily large strings.
+ * printcmd.c (printf_command): Use printf_filtered, not
+ printf_unfiltered and printf, now that arbitrary limit is gone.
+
+ gcc -Wall lint:
+ * breakpoint.c (watchpoint_check): Remove unused variable b.
+ * stack.c (print_frame_info): Move sp and buf inside #if.
+ * eval.c (evaluate_subexp): Remove unused variables pp,
+ mangle_ptr, ptr, and mangle_tstr.
+ * valarith.c (value_x_binop): Remove unused variables mangle_tstr
+ and mangle_ptr.
+ * symtab.c (lookup_symtab): Put variable copy inside #if.
+ (decode_line_1): Put variable q1 inside #if 0.
+ * target.h: Declare target_link.
+ * infrun.c (wait_for_inferior): Remove unused variables signame.
+ * remote.c (remote_resume): Remove unused variable name.
+ * c-exp.y (parse_number): Parenthesize operand of shift.
+ * dbxread.c (record_minimal_symbol): Parenthesize operand of &&
+ (this is a semantic change, the warning seems to have detected a bug).
+ * dbxread.c (end_psymtab): Move variable p1 inside #if.
+ * coffread.c: Move variable temptype inside #if.
+ * ch-typeprint.c (chill_type_print_base): Remove unused variable
+ name.
+ * ch-valprint.c: #include typeprint.h and ch-lang.h.
+ (chill_val_print): Remove unused variable in_range.
+ (chill_val_print): Remove statement "length > TYPE_LENGTH (type);".
+ (chill_val_print): Add default case for switch.
+ * stabsread.h: Declare stabsect_build_psymtabs.
+ * os9kread.c (read_minimal_symbols): Make this return void.
+ (os9k_symfile_read): Remove unused variables stb_exist and val.
+ (os9k_symfile_init): Remove unused variable val.
+ (fill_sym): Remove unused variable id.
+ (read_os9k_psymtab): Put variable back_to inside #if 0. Remove
+ unused variable nsl.
+ Remove unused variable symfile_bfd.
+ #if 0 unused variables lbrac_unmatched_complaint and
+ lbrac_mismatch_complaint.
+ Remove declaration for non-existent function os9k_next_symbol_text.
+
+ * annotate.c, annotate.h: New files, containing a function for
+ each annotation which outputs it.
+ * Move breakpoints_changed from breakpoint.c to annotate.c.
+ * breakpoint.c, blockframe.c, infrun.c, cp-valprint.c, main.c,
+ printcmd.c, source.c, stack.c, utils.c, valprint.c:
+ Use annotate.c functions to output annotations.
+ * Makefile.in (OBS): Add annotate.o.
+
+Thu May 12 10:46:27 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * hppa-tdep.c (read_unwind_info): Make sure elf_unwind_size and
+ elf_unwind_entries are always initialized.
+
+ * hppa-tdep.c (skip_trampoline_code): Handle argument relocation
+ stubs which return directly to the caller rather than to the stub
+ itself.
+
+Wed May 11 20:11:51 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * c-exp.y (yyerror): Display a more informative error message.
+ * ch-exp.y (yyerror): Ditto, don't use global yychar.
+ * m2-exp.y (yyerror): Ditto.
+
+Tue May 10 11:57:53 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * inflow.c (job_control): Move definition to front of file.
+
+Tue May 10 14:42:37 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * maint.c (print_section_table): Rename SEC_SHARED_LIBRARY to
+ SEC_COFF_SHARED_LIBRARY to match corresponding change in bfd.
+
+Fri May 6 13:30:22 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * Makefile.in (kdb): Remove old init.c creation commands.
+ * configure.in (sparclite): Match on sparclite*.
+ * sparclite/aload.c (main): Only change section addresses for
+ a.out format object files.
+
+Fri May 6 13:24:04 1994 Steve Chamberlain (sac@cygnus.com)
+
+ * config/i386/go32.mh: Define CC.
+
+Fri May 6 11:56:54 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * gdbserver/Makefile.in: Remove irrelevant definitions and
+ comments inherited from the gdb Makefile.
+ (BFD_DIR, BFD, BFD_SRC, BFD_CFLAGS): Add from gdb Makefile.
+ (VERSION): Update to 4.12.3.
+ (gdbserver): Remove any existing executable first.
+ (distclean, realclean): Remove nm.h.
+ * gdbserver/low-lynx.c: Add Sparc Lynx support.
+ * gdbserver/low-sparc.c, gdbserver/low-sun3.c (sys/wait.h):
+ Don't use absolute pathname.
+
+Thu May 5 12:00:22 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * rs6000-nat.c (vmap_ldinfo): Don't fail if fstat returns an
+ error.
+
+Wed May 4 06:56:03 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * infrun.c (proceed, normal_stop, wait_for_inferior), breakpoint.c
+ (print_it_normal): Add annotations for the inferior starting and
+ stopping, and for all the various messages related to how it
+ stopped.
+
+ * printcmd.c (do_one_display): Annotate.
+ * stack.c (print_frame_info): Annotate printing of stack frames.
+
+Wed May 4 18:15:51 1994 Stu Grossman (grossman@cygnus.com)
+
+ * remote.c (get_offsets): Handle case where stub doesn't support
+ qOffsets message.
+
+Wed May 4 15:30:39 1994 Per Bothner (bothner@kalessin.cygnus.com)
+
+ Add partial support for g++ code compiled with -fvtable-thunks.
+ * c-valprint.c (c_val_print): Add vtblprint support
+ when using thunks.
+ * cp-valprint.c (cp_is_vtbl_member): A vtable can be an array of
+ pointers (if using thunks) as well as array of structs (otherwise).
+ * cp-valprint.c (vtbl_ptr_name_old, vtbl_ptr_name): Move to global
+ level, and make the latter non-static (so define_symbol can use it).
+ * stabsread.c (define_symbol): If the type being defined is a
+ pointer type named "__vtbl_ptr_type", set the TYPE_NAME to that name.
+ * symtab.h (VTBL_PREFIX_P): Allow "_VT" as well as "_vt".
+ * values.c (value_virtual_fn_field): Handle thunks.
+ * values.c (value_headof): Minor efficiency hack.
+ * values.c (value_headof): Incomplete thunk support. FIXME.
+
+Wed May 4 06:56:03 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * valprint.c (print_longest): Clarify comment about use_local.
+ * printcmd.c, defs.h (print_address_numeric), callers in
+ symmisc.c, symfile.c, stack.c, source.c, remote.c, infcmd.c,
+ cp-valprint.c, core.c, ch-valprint.c, c-valprint.c, breakpoint.c,
+ exec.c: New argument use_local.
+ * source.c (identify_source_line): Use filtered output. Use
+ print_address_numeric.
+
+ * core.c (memory_error), symtab.c (cplusplus_hint, decode_line_1),
+ language.c (type_error, range_error): Use filtered output.
+ * utils.c (error_begin): Update comment to tell people to use
+ filtered output.
+
+ * Makefile.in (HFILES_WITH_SRCDIR): List bfd.h.
+ (HFILES_NO_SRCDIR): List gdbcore.h not gdbcore_h, so as not to get
+ bfd.h.
+
+Tue May 3 07:41:33 1994 Jim Kingdon (kingdon@cygnus.com)
+
+ * procfs.c (procfs_wait): Reinstate code which deduces the signal
+ from the fault, #ifndef FAULTED_USE_SIGINFO.
+ * config/sparc/tm-sun4sol2.h: Define FAULTED_USE_SIGINFO.
+
+Fri Apr 29 18:15:04 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * breakpoint.c (breakpoint_1): Annotate each field of the headers.
+ Explicitly annotate each record.
+
+Fri Apr 29 15:56:18 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * xcoffexec.c: Reformat to standards and lint.
+ (language.h): Include.
+ (exec_close): Declare arg "quitting".
+ (file_command): Declare arg "from_tty".
+ (map_vmap): Cast xmalloc result to PTR.
+ * rs6000-nat.c: Reformat to standards and lint.
+ (exec_one_dummy_insn): Use char array for saved instruction.
+ (fixup_breakpoints): Declare.
+ (vmap_ldinfo): Be more informative in fatal error messages.
+ (xcoff_relocate_symtab): Define to return void.
+ * xcoffsolib.h: Reformat to standards, improve comments.
+ * config/rs6000/nm-rs6000.h (xcoff_relocate_symtab): Declare.
+
+Thu Apr 28 08:40:56 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * utils.c, defs.h (error_begin): New function.
+ (quit): Print annotation before printing the error message.
+ * main.c (return_to_top_level): Print annotation before doing the
+ longjmp.
+ * symtab.c (decode_line_1): Call error not warning and then
+ return_to_top_level. Call error_begin and printf_unfiltered
+ rather calling warning (before calls to return_to_top_level).
+ * core.c (memory_error): Use error_begin, printf_unfiltered,
+ print_address_numeric and return_to_top_level instead of error.
+ Cleans up a FIXME-32x64.
+ * language.c (type_error, range_error): Call error_begin
+ not just target_terminal_ours.
+
+ * dbxread.c (stabsect_build_psymtabs): Assign to sym_stab_info
+ directly, rather than via DBX_SYMFILE_INFO. A cast on the left
+ side of an assignment is non-portable.
+
+ * utils.c (query): Change syntax of query annotations to be
+ consistent with other input annotations.
+ (prompt_for_continue): Likewise for prompt-for-continue annotation.
+
+Thu Apr 28 01:20:39 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * mdebugread.c (psymtab_to_symtab_1): Do not call sort_blocks
+ for stabs symtabs.
+ * mips-tdep.c (mips_skip_prologue): Handle prologues for functions
+ that have a stack frame size of 32k or larger (from Paul Flinders).
+ Remove #if 0'd code.
+
+Wed Apr 27 16:33:51 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * lynx-nat.c (CANNOT_STORE_REGISTER): Add a fallback definition
+ for Lynx platforms that need it.
+ * config/nm-lynx.h (__LYNXOS): Define if not already defined.
+
+Wed Apr 27 16:01:37 1994 Jim Kingdon (kingdon@cygnus.com)
+
+ * procfs.c (procfs_wait): Use the signal from the pr_info rather
+ than trying to deduce it from the fault.
+
+Wed Apr 27 12:22:46 1994 Steve Chamberlain (sac@cygnus.com)
+
+ * printcmd.c (print_address_symbolic): Initialize name to empty
+ string to avoid core dump if lookup fails.
+ * remote-e7000.c (printf_e7000debug): Error if target not open.
+
+Tue Apr 26 22:45:24 1994 Stu Grossman (grossman at cygnus.com)
+
+ * i386-nlmstub.c: Update to be more in line with PIN stub.
+ * nlm/gdbserve.c (putDebugChar): Install bug fix from i386-nlmstub.
+ * (hex2mem): Init ptr.
+ * General cleanups to use ConsolePrintf, standard prologues, etc...
+
+Tue Apr 26 10:23:04 1994 Stu Grossman (grossman at cygnus.com)
+
+ * i386-nlmstub.c: More changes to be compatible with remote.c.
+
+ * dbxread.c: Move a bunch of strncmps out of process_one_symbol
+ into (the far less frequently called) dbx_symfile_read.
+
+ * i386-nlmstub.c: An interim version till we get PIN for the x86.
+
+Tue Apr 26 09:50:45 1994 Stu Grossman (grossman at cygnus.com)
+
+ * dbxread.c (record_minimal_symbol): Record the section
+ associated with the symbol to make dynmaic relocation work.
+ * (dbx_symfile_read, process_one_symbol): Fixes to work around
+ Solaris brain-damage which don't apply to relocatable object
+ files.
+ * (stabsect_build_psymtabs): New routine to read stabs out of an
+ arbitrarily named section.
+ * nlmread.c (nlm_symtab_read): Read ALL syms from the NLM, not just
+ globals.
+ * (nlm_symfile_read): Call stabsect_build_psymtabs to read the
+ stabs out of the nlm.
+ * partial-stabs.h (cases 'f' & 'F'): Fixes to work around Solaris
+ brain-damage which don't apply to relocatable object files.
+ * remote.c (putpkt): Improve error reporting and error handling.
+ * (get_offsets): Temporary kludge to force data & bss sections to
+ have the same relocation.
+ * stabsread.c (define_symbol, scan_file_globals): Record section
+ info in sym.
+
+Sat Apr 23 19:05:52 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * breakpoint.c (breakpoint_1): Annotate each field of output. Add
+ FIXME-32x64 comment.
+
+Fri Apr 22 16:43:54 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * infrun.c (wait_for_inferior): Move call to flush_cached_frames
+ to after call to target_wait. This means that flush_cached_frames
+ can call target_terminal_ours if it wants to.
+ * infrun.c (wait_for_inferior) [HAVE_NONSTEPPABLE_WATCHPOINT]: Add
+ comment about why the code is dubious.
+
+ * stabsread.c (read_type): Call read_type, not nonexistent
+ os9k_read_type.
+
+Fri Apr 22 14:25:36 1994 Kung Hsu (kung@mexican.cygnus.com)
+
+ * remote-os9k.c (rombug_fetch_registers): set trace mode
+ correctly.
+ * remote-os9k.c (rombug_read_inferior_memory): cache data in
+ buffer.
+ * os9kread,c (read_os9k_psymtab): process file symbol to truncate
+ extra info.
+ * os9kread.c (os9k_read_ofile_symtab): proper casting of args
+ passed to process_one_symbol.
+ * stabsread.c (read_type): process os9k functio prototype.
+
+Fri Apr 22 11:27:39 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * solib.c (symbol_add_stub): If so->textsection is NULL, don't
+ dump core.
+
+Thu Apr 21 07:45:49 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * utils.c (prompt_for_continue): Annotate prompt.
+ (query): Annotate query.
+ * printcmd.c (print_frame_args): Change syntax of argument
+ annotation to make name and value part of a single group of
+ annotations, not two separate groups.
+ * cp-valprint.c (cp_print_value_fields): Likewise for fields.
+ * valprint.c (val_print_array_elements): Change syntax of
+ annotation to be more concise.
+ * main.c, defs.h (command_line_input): New argument tells what
+ string to include in the annotations.
+ * symtab.c (decode_line_2), main.c (read_command_lines,
+ command_loop): Change callers.
+
+ * breakpoint.c (watch_command): Use (CORE_ADDR)0, not NULL, for
+ target null pointer.
+ * blockframe.c (find_frame_addr_in_frame_chain): Likewise.
+
+ * printcmd.c (output_command): Annotate things we print here too.
+ * printcmd.c (print_command_1): Add "value-history-value" annotation.
+ * Move declaration of print_value_flags from defs.h to value.h.
+ * main.c (command_line_input): Call wrap_here as well as gdb_flush.
+
+Thu Apr 21 09:29:37 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * dbxread.c (read_dbx_dynamic_symtab): Reinstall support for sun3,
+ BFD handles sun3 dynamic relocations now.
+ * elfread.c (elf_symtab_read, elf_symfile_read): Handle dynamic
+ symbol table.
+
+Wed Apr 20 19:41:21 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * printcmd.c (print_command_1): Annotate the top-level expressions
+ that we print.
+ (print_frame_args): Annotate each argument.
+ * printcmd.c, defs.h (print_value_flags): New function.
+ * cp-valprint.c (cp_print_value_fields): Annotate each field.
+ * valprint.c (val_print_array_elements): Annotate each array element.
+
+Wed Apr 20 13:18:41 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * findvar.c (read_var_value): Handle LOC_REPARM_ADDR case correctly,
+ the register contains a pointer to the type, not the type itself.
+
+Mon Apr 11 10:44:35 1994 Jim Kingdon (kingdon@deneb.cygnus.com)
+
+ * main.c (main): Accept --annotate=N option and make --fullname
+ the same as --annotate=1.
+ (command_line_input): Print annotatation before and after prompt.
+ * blockframe.c (flush_cached_frames): Print annotation.
+ * Rename frame_file_full_name to annotation_level and move it from
+ symtab.h to defs.h.
+ * source.c (identify_source_line): If annotation_level > 1,
+ change output format.
+ * breakpoint.c: Print annotation whenever a breakpoint changes.
+ * main.c: New variable server_command.
+ (command_line_input): Parse "server " and set server_command.
+ (dont_repeat): Check server_command.
+
+Wed Apr 20 08:37:16 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * xcoffread.c (xcoff_next_symbol_text): Don't return before
+ updating raw_symbol and symnum. Return a value in the case where
+ we complained.
+
+ * dstread.c, coffread.c: Don't define pending_blocks; buildsym.c
+ takes care of it.
+ * parse.c: Don't define block_found; it is defined in symtab.c.
+ * parser-defs.h: Add comment regarding block_found.
+
+Tue Apr 19 09:46:05 1994 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * hppa-tdep.c (internalize_unwind_info): Delete unused indexp
+ argument.
+
+Mon Apr 18 13:18:56 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * dbxread.c (read_dbx_dynamic_symtab): Relocate BFD symbols by
+ section vma. Do not read dynamic relocs for sun3 executables to
+ avoid BFD assertion message.
+
+Mon Apr 18 10:08:07 1994 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * nm-hppab.h (KERNEL_U_ADDR): Define.
+ (FIVE_ARG_PTRACE): Likewise.
+ (CANNOT_STORE_REGISTER): Likewise.
+ * nm-hppah.h (KERNEL_U_ADDR): Define.
+ (FIVE_ARG_PTRACE): Likewise.
+ (CANNOT_STORE_REGISTER): Likewise.
+ (NEED_TEXT_START_END): Likewise.
+
+ * tm-hppah.h (NEED_TEXT_START_END): Delete definition.
+ * xm-hppah.h (KERNEL_U_ADDR): Delete definition.
+ (FIVE_ARG_PTRACE): Likewise.
+ * xm-hppab.h (KERNEL_U_ADDR): Delete definition.
+ (FIVE_ARG_PTRACE): Likewise.
+
+ * hppa-tdep.c (read_unwind_info): Make static.
+ (restore_pc_queue): Indirect through the target vector to
+ reload the register state.
+
+Sat Apr 16 22:20:51 1994 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * paread.c (compare_unwind_entries): Delete function. It's been
+ moved into hppa-tdep.c.
+ (read_unwind_info): Likewise.
+ (pa_symfile_read): No longer call read_unwind_info. The unwind
+ tables will be read in as they are needed.
+
+ * hppa-tdep.c (compare_unwind_entries): New function.
+ (read_unwind_info, internalize_unwinds): Likewise.
+ (find_unwind_entry): Read in unwind information on demand.
+
+Fri Apr 15 11:53:46 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * source.c (DIRNAME_SEPARATOR): New macro, replaces all references
+ to : in search path processing.
+ * defs.h (qsort): Rename argument in prototype.
+ * symtab.h (SAYMBOL_VALUE): Rename value field, avoids bugs in
+ some compilers.
+ * breakpoint.c, exec.c, mdebugread.c, mipsread.c, xcoffexec.c
+ (false): Eliminate usages.
+
+Fri Apr 15 11:35:19 1994 Steve Chamberlain (sac@cygnus.com)
+
+ * h8500-tdep.c (initialize_h8500_tdep, large_command):
+ All references to value changed to value_ptrlage_command is now
+ called big_command.
+ All references to value changed to value_ptr.
+ * remote-e7000.c (e7000_wait): Use target_waitstatus and SETSTOP
+ * remote-hms.c (hms_wait): Timeout after five seconds.
+ * ser-go32.c (dosasync_read): Poll if timeout < 0.
+ * config/tm/tm-h8500.h (BEFORE_MAIN_LOOP_HOOK): Deleted.
+ * config/sh/tm-sh.h (BREAKPOINT): Is now sleep opcode.
+
+Thu Apr 14 07:01:56 1994 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * procfs.c (procfs_wait): Protect watchpoint code with appropriate
+ #ifdefs.
+ (procfs_set_watchpoint, procfs_stopped_by_watchpoint): Likewise.
+
+Wed Apr 13 14:52:46 1994 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * breakpoint.h (enum bptype): Add bp_hardware_watchpoint and
+ bp_watchpoint_scope breakpoints.
+ (struct breakpoint): Add val_chain and related_breakpoint fields
+ for use by watchpoints.
+
+ * breakpoint.c (within_scope): Delete. No longer used.
+ (TARGET_CAN_USE_HARDWARE_WATCHPOINT): Provide default definition.
+ (target_{remove,insert}_watchpoint): Likewise.
+ (can_use_hardware_watchpoint): New function.
+ (remove_breakpoint): New function to remove a single breakpoint
+ or hardware watchpoint.
+ (insert_breakpoints): Handle insertion of hardware watchpoints.
+ Store a copy of the value chain derived from the watchpoint
+ expression.
+ (remove_breakpoints): Simplify by using remove_breakpoint.
+ (delete_breakpoint): Likewise.
+ (watchpoint_check): Delete the watchpoint and watchpoint scope
+ breakpoints when the watchpoint goes out of scope. Save & restore
+ the current frame after checking watchpoints.
+ (breakpoint_init_inferior): Likewise (restarting the program
+ makes all local watchpoints go out of scope).
+ (bpstat_stop_status): Handle hardware watchpoints much like normal
+ watchpoints. Delete the watchpoint and watchpoint scope breakpoint
+ when the watchpoint goes out of scope. Remove and reinsert all
+ breakpoints before returning if we stopped when a hardware watchpoint
+ fired.
+ (watch_command): Use a hardware watchpoint when possible. If
+ watching a local expression, build a scope breakpoint too.
+ (map_breakpoint_numbers): Also call given function for any
+ related breakpoints.
+ (disable_breakpoint): Never disable a scope breakpoint.
+ (enable_breakpoint): Handle hardware breakpoints much like normal
+ breakpoints, but recompute the watchpoint_scope breakpoint's
+ frame and address (if we have an associated scope breakpoint).
+ (read_memory_nobpt): Handle hardware watchpoints like normal
+ watchpoints. When necessary handle watchpoint_scope breakpoints.
+ (print_it_normal, bpstat_what, breakpoint_1, mention): Likewise.
+ (clear_command, breakpoint_re_set_one, enable_command): Likewise.
+ (disable_command): Likewise.
+
+ * blockframe.c (find_frame_addr_in_frame_chain): New function.
+ Extern prototype added to frame.h
+
+ * infrun.c (wait_for_inferior): Set current_frame and select
+ a frame before checking if we stopped due to a hardare watchpoint
+ firing. Handle stepping over hardware watchpoints.
+ (normal_stop): Remove unnecessary call to select_frame.
+
+ * value.h (value_release_to_mark): Declare.
+ * values.c (value_release_to_mark): New function.
+
+ * procfs.c (procfs_wait): Add cases for hardware watchpoints.
+ (procfs_set_watchpoint, procfs_stopped_by_watchpoint): New functions.
+
+ * hppab-nat.c (hppa_set_watchpoint): New function.
+
+ * config/pa/nm-hppab.h (STOPPED_BY_WATCHPOINT): Define.
+ (HAVE_STEPPABLE_WATCHPOINT): Define.
+ (TARGET_CAN_USE_HARDWARE_WATCHPOINT): Define.
+ (target_{insert,delete}_watchpoint): Define.
+
+ * config/mips/nm-irix4.h (TARGET_CAN_USE_HARDWARE_WATCHPOINT): Define.
+ (STOPPED_BY_WATCHPOINT, HAVE_NONSTEPPABLE_WATCHPOINT): Likewise.
+ (target_{insert,remove}_watchpoint): Likewise.
+
+Mon Apr 11 19:21:27 1994 Stu Grossman (grossman at cygnus.com)
+
+ * xcoffread.c (read_xcoff_symtab): Ignore symbols of class C_EXT,
+ smtyp XTY_LD, sclass XMC_DS (external data segment label). They
+ often have the same names as debug symbols for functions, and
+ confuse lookup_symbol().
+
+Mon Apr 11 10:44:35 1994 Jim Kingdon (kingdon@deneb.cygnus.com)
+
+ * remote.c: Around redefinition of PBUFSIZE, adjust whitespace.
+ * config/pa/tm-hppa.h (REGISTER_BYTES): Use 4 rather than
+ REGISTER_RAW_SIZE (1).
+ Together these changes work around a bug in HP's compiler. Both
+ seem to be necessary.
+
+Mon Apr 11 09:18:24 1994 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * paread.c (pa_symtab_read): Handle ST_STUB symbols and symbols
+ with scope SS_EXTERNAL. ST_ENTRY symbols in dynamic executables
+ are type mst_solib_trampoline.
+
+Fri Apr 8 17:14:37 1994 Jim Kingdon (kingdon@deneb.cygnus.com)
+
+ * config/m68k/es1800.mt: Change comments.
+
+Fri Apr 8 17:14:37 1994 Rob Savoye (rob@darkstar.cygnus.com)
+
+ * config/m68k/monitor.mt (TDEPFILES): Don't include remote-es.o.
+
+Fri Apr 8 15:35:30 1994 Stu Grossman (grossman at cygnus.com)
+
+ * lynx-nat.c: Restore regmap structure for SPARC. It's needed
+ for core files.
+
+Fri Apr 8 14:53:35 1994 Jim Kingdon (kingdon@deneb.cygnus.com)
+
+ * values.c (unpack_long): Remove obsolete comment about using a
+ switch statement.
+
+ * symfile.c (symbol_file_command): Add comments about command syntax.
+
+Thu Apr 7 17:25:21 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+ Jim Kingdon (kingdon@cygnus.com)
+
+ * infrun.c (IN_SOLIB_TRAMPOLINE): Correct comment, trampolines
+ are in the .plt section.
+ * minsyms.c (lookup_solib_trampoline_symbol_by_pc,
+ find_solib_trampoline_target): New functions for handling
+ stepping into -g compiled shared libraries.
+ * symtab.h (lookup_solib_trampoline_symbol_by_pc,
+ find_solib_trampoline_target): Add prototypes.
+ * config/tm-sunos.h (IN_SOLIB_TRAMPOLINE, SKIP_TRAMPOLINE_CODE):
+ Define to handle stepping into -g compiled shared libraries.
+ * config/tm-sysv4.h (SKIP_TRAMPOLINE_CODE): Define to handle
+ stepping into -g compiled shared libraries.
+
+Thu Apr 7 17:22:54 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * configure.in: Add mips-*-sysv4* support.
+ * config/mips/mipsv4.mh, config/mips/mipsv4.mt,
+ config/mips/tm-mipsv4.h, config/mips/xm-mipsv4.h, mipsv4-nat.c:
+ New files for MIPS SVR4 support.
+ * Makefile.in: Update for new mipsv4 files.
+ * alpha-tdep.c (heuristic_proc_desc, find_proc_desc): Use
+ read_next_frame_reg to obtain the frame relative stack pointer.
+ * mips-tdep.c (heuristic_proc_desc): Use read_next_frame_reg to
+ obtain the frame relative stack pointer.
+ * mdebugread.c (parse_partial_symbols, psymtab_to_symtab1):
+ Handle stStatic and stStaticProc symbols in stabs-in-ecoff output
+ by entering them into the minimal symbol table.
+ * printcmd.c (print_scalar_formatted): Do not try to unpack to
+ a long for float formats.
+ * solib.c: Include "elf/mips.h" only if DT_MIPS_RLD_MAP does not
+ get defined in <link.h>.
+ * solib.c (solib_add): Add shared library sections to the section
+ table of the target before adding the symbols.
+ * partial-stab.h: Relocate static and global functions.
+ * dbxread.c (read_dbx_symtab): Remove unused variable
+ end_of_text_address. Relocate text_addr when passing it
+ to end_psymtab.
+
+ For Alpha OSF/1 targets, enable gdb to set breakpoints in shared
+ library functions before the executable is run. Retrieve dynamic
+ symbols from stripped executables.
+ * mipsread.c (read_alphacoff_dynamic_symtab): New function.
+ * mipsread.c (mipscoff_symfile_read): Use it. Issue warning message
+ if no debugging symbols were found.
+ * alpha-tdep.c (alpha_skip_prologue): Silently return the unaltered
+ pc if memory at the pc is not accessible and GDB_TARGET_HAS_SHARED_LIBS
+ is defined.
+ * config/alpha/nm-alpha.h (GDB_TARGET_HAS_SHARED_LIBS): Define,
+ OSF/1 has shared libraries.
+
+Thu Apr 7 15:11:11 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * dbxread.c (read_dbx_dynamic_symtab): Adjust for recent changes
+ to BFD handling of dynamic symbols.
+
+Tue Apr 5 15:29:25 1994 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * hppa-tdep.c (hppa_fix_call_dummy): If FUN is a procedure label,
+ then gets its real address into FUN and its GOT/DP value into %r19.
+
+ * tm-hppa.h (CALL_DUMMY): Use %r20, not %r19 as a temporary.
+
+ * hppa-tdep.c (frameless_function_invocation): If no unwind
+ descriptor was found, then assume this was not a frameless
+ function invocation.
+ (frame_saved_pc): If the saved PC is in a linker stub, then
+ return the return address which the linker stub will return to.
+
+ * xm-hppab.h: Never define USG.
+ * xm-hppah.h: Always define USG.
+
+Tue Apr 5 12:58:47 1994 Per Bothner (bothner@kalessin.cygnus.com)
+
+ * values.c (unpack_long, value_from_longest),
+ valarith.c (value_binop): Allow TYPE_CODE_RANGE.
+
+Fri Apr 1 14:04:34 1994 Jason Merrill (jason@deneb.cygnus.com)
+
+ * symfile.c (deduce_language_from_filename): .cpp is a C++ extension.
+
+Fri Apr 1 00:44:00 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ For SVR4 targets, enable gdb to set breakpoints in shared
+ library functions before the executable is run.
+ * elfread.c (elf_symtab_read): Handle symbols for shared library
+ functions.
+ * sparc-tdep.c (in_solib_trampoline): Renamed to in_plt_section
+ and moved to objfiles.c.
+ * objfiles.c (in_plt_section): Moved to here from sparc-tdep.
+ * config/tm-sysv4.h (IN_SOLIB_TRAMPOLINE): Use new in_plt_section.
+ * config/sparc/tm-sun4sol2.h (IN_SOLIB_TRAMPOLINE): Removed,
+ the new generic definition from tm-sysv4.h works for Solaris.
+
+Wed Mar 30 16:14:27 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * elfread.c (elf_symtab_read): Change storage_needed,
+ number_of_symbols and i to long. Rename get_symtab_upper_bound to
+ bfd_get_symtab_upper_bound. Check for errors from
+ bfd_get_symtab_upper_bound and bfd_canonicalize_symtab.
+ * nlmread.c (nlm_symtab_read): Same changes.
+
+Wed Mar 30 11:43:29 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * xcoffread.c (xcoff_next_symbol_text): New function.
+ (read_xcoff_symtab): Set next_symbol_text_func to it.
+ Move raw_symbol outside of read_xcoff_symtab.
+
+ * remote.c (getpkt): Remove unused "out" label.
+
+Wed Mar 30 09:15:42 1994 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * breakpoint.c (print_it_normal): Allow GDB to notify the user
+ about more than one watchpoint being triggered.
+
+Wed Mar 30 08:24:18 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * config/m68k/tm-dpx2.h: Include tm-m68k.h not nonexistent tm-68k.h.
+
+Wed Mar 30 00:31:49 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * blockframe.c (find_pc_partial_function): mst_file_text
+ symbols do not live in the shared library transfer table.
+ * ch-exp.y (decode_integer_value, match_character_literal,
+ match_bitstring_literal): Guard tolower calls with isupper,
+ tolower on old BSD systems blindly subtracts a constant.
+ * dbxread.c (read_ofile_symtab): Check for __gnu_compiled_* as
+ well when determining the producer of the object file.
+ * mdebugread.c (has_opaque_xref): New function to check for
+ cross reference to an opaque aggregate.
+ * mdebugread.c (parse_symbol, parse_partial_symbols): Do not
+ enter typedefs to opaque aggregates into the symbol tables.
+ * mdebugread.c (parse_external): Remove skip_procedures argument,
+ it has always been 1. Remove code that handled stProc symbols,
+ it was never executed and was wrong, as the index of a
+ stProc symbol points to the local symbol table and not to the
+ auxiliary symbol info. Update caller.
+ * mdebugread.c (parse_partial_symbols): Do not enter external
+ stProc symbols into the partial symbol table, they are already
+ entered into the minimal symbol table.
+ * config/i386/tm-symmetry.h: Clean up, it is now only used for Dynix.
+ Remove all conditionals and definitions for ptx.
+ I386_REGNO_TO_SYMMETRY moved to here from symm-tdep.c.
+ Fix addresses of floating point registers in REGISTER_U_ADDR.
+ STORE_STRUCT_RETURN now handles cc and gcc conventions.
+ FRAME_CHAIN, FRAMELESS_FUNCTION_INVOCATION, FRAME_SAVED_PC,
+ IN_SIGTRAMP, SIGCONTEXT_PC_OFFSET defined to make backtracing through
+ signal trampoline code work.
+ * config/i386/xm-symmetry.h: Clean up, it is now only used for Dynix.
+ Remove all conditionals and definitions for ptx.
+ Remove KDB definitions.
+ * symm-nat.c (store_inferior_registers): Fetch registers before
+ storing them to obtain valid floating point control registers.
+ Store fpu registers.
+ * symm-nat.c (print_1167_control_word): Dynix 3.1.1 defines
+ FPA_PCR_CC_C0 and FPA_PCR_CC_C1, avoid duplicate case value.
+ * symm-nat.c (fetch_inferior_registers, child_xfer_memory):
+ Fix typos.
+ * symm-nat.c (child_resume): Update type of `signal' parameter.
+ * symm-tdep.c (I386_REGNO_TO_SYMMETRY): Moved to tm-symmetry.h.
+
+Tue Mar 29 23:01:33 1994 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * hppa-tdep.c (hppa_fix_call_dummy): Use an alternate method for
+ calling import stubs for functions in shared libraries.
+
+Tue Mar 29 21:14:04 1994 Per Bothner (bothner@kalessin.cygnus.com)
+
+ * ch-exp.y: Implement SIZE(mode_name) and SIZE(expression).
+
+ * ch-lang.c (chill_is_varying_struct): Magic string is
+ was "<var_length>" is now "__var_length" (more portable).
+
+Tue Mar 29 19:41:34 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * remote.c (getpkt): If we get a timeout, actually retry rather
+ than just giving up the first time it happens.
+ * remote.c: Document sequence numbers.
+ (remote_store_registers): Change syntax of 'P' request so that it
+ never looks like a sequence number.
+
+Tue Mar 29 16:06:01 1994 Kung Hsu (kung@mexican.cygnus.com)
+
+ * os9kread.c (record_minimal_symbol): add section_offset to
+ relocate minimal symbol table.
+ * os9kread.c (read_minimal_symbols): ditto.
+ * os9kread.c (os9k_symfile_init): increase size of dbg and stb
+ file names.
+ * os9kread.c (read_os9k_psymtab): if there's no dbg file, just
+ return. Also if file addr is 0 leave it 0, not to relocate.
+ * remote-os9k.c (_initialize_remote_os9k): add 'set remotexon',
+ 'set remotexoff' and 'set remotelog' commands.
+
+Tue Mar 29 12:38:45 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * remote.c (remote_store_registers): Add 'P' request to set an
+ individual register.
+ (remote_write_bytes, remote_read_bytes): Use %lx, not %x, to print
+ a target address.
+
+Sat Mar 26 07:05:18 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * config/sparc/tm-sparc.h: Define USE_REGISTER_NOT_ARG.
+ * stabsread (define_symbol): If USE_REGISTER_NOT_ARG, go back to
+ combining all 'p' and 'r' pairs into a LOC_REGPARM.
+
+ * command.c (do_setshow_command, case var_string): Never add a
+ space to the end of the string.
+ * NEWS: Document this change.
+ * .gdbinit: Add a space to the "set prompt" command.
+
+Fri Mar 25 12:40:41 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * m3-nat.c, i386m3-nat.c, config/i386/i386m3.mh: Many minor
+ changes to make it compile (it doesn't link yet).
+
+ * buildsym.c (start_subfile, patch_subfile_names), demangle.c
+ (set_demangling_style, set_demangling_command): Use savestring not
+ strdup. We were not dealing properly with a NULL return from
+ strdup, and were not declaring strdup (the system header may or
+ may not have it).
+
+ * valprint.c (val_print): Remove inaccurate comment about what
+ types can be stub types.
+
+ * config/i386/ptx.mh (XDEPFILES): Add coredep.o. Delete infptrace.o.
+ * symm-nat.c (child_wait, _initialize_symm_nat, kill_inferior):
+ Supply alternate version if ATTACH_DETACH is not defined.
+ * ptx4-nat.c, config/i386/{nm-ptx4.h, ptx4.mh, ptx.mt, ptx4.mt,
+ tm-ptx.h, tm-ptx4.h, xm-ptx.h, xm-ptx4.h}: New files.
+ * configure.in: Recognize i[34]86-sequent-sysv4* host.
+
+Fri Mar 25 10:14:03 1994 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * hppa-tdep.c (skip_prologue): Do nothing if not at the beginning
+ of a function.
+ (skip_trampoline_code): Rewrite and add support for argument
+ relocation stubs stubs, import/export stubs, calls through
+ "_sr4export" and cascaded trampolines.
+
+ * hppa-tdep.c (skip_prologue): Return "pc" not zero
+ if no unwind descriptor is found.
+
+ * tm-hppa.h (NUM_REGS): Bump to 128 registers.
+ (REGISTER_NAMES): Add entries for "right-half" of FP registers.
+ (REGISTER_RAW_SIZE, MAX_REGISTER_RAW_SIZE): Do not treat FP regs
+ differently. All registers are four bytes.
+ (REGISTER_BYTES, REGISTER_BYTE): Simplify now that all registers are
+ the same size.
+ (REGISTER_VIRTUAL_TYPE): Use builtin_type_float for all FP regs.
+
+ * hppa-tdep.c (pa_print_fp_reg): Update to print even numbered FP
+ registers as both single and double values (fetching 2nd 32bit half
+ as necessary). Annotate each register printed with its precision.
+
+ * paread.c (read_unwind_info): Fix off-by-one error.
+
+Fri Mar 25 08:33:28 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * main.c (complete_command): Deal with it if arg is NULL.
+
+Thu Mar 24 07:12:09 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * config/mips/tm-mips.h (SETUP_ARBITRARY_FRAME): Revise comment
+ regarding using the PC--using the PC is necessary and all the
+ FIXME comments in the world won't make it go away.
+
+ * valops.c (value_at, value_at_lazy): Give error if we dereference
+ a pointer to void.
+ * gdbtypes.h: Fix comments regarding TYPE_CODE_VOID.
+ * stabsread.c: Use 1, not 0, for TYPE_LENGTH of void types.
+
+ * stabsread.c (patch_block_stabs): Add comment about what happens
+ if the definition is in another compilation unit from the stab.
+
+ * dbxread.c (end_psymtab): Add comment about empty psymtabs.
+
+Wed Mar 23 07:50:33 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * main.c (complete_command): New command, from Rick Sladkey
+ <jrs@world.std.com>.
+ (symbol_completion_function): Don't declare rl_point and
+ rl_line_buffer; they are now declared in readline.h.
+ (show_commands): Don't declare history_base; it is declared in
+ history.h.
+ * command.c (lookup_cmd): Don't delete trailing whitespace.
+ Reverts change of 14 May 1989.
+
+Wed Mar 23 16:14:52 1994 Stu Grossman (grossman at cygnus.com)
+
+ * minsyms.c (prim_record_minimal_symbol): Move section deduction
+ code from prim_record_minimal_symbol_and_info() to here. Callers
+ of the latter can legitimately supply a section number of -1.
+
+Wed Mar 23 07:50:33 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdbtypes.h, gdbtypes.c: Add comments regarding whether static
+ member functions have an element in args for a (nonexistent) this
+ pointer.
+
+Tue Mar 22 20:12:53 1994 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * config/pa/tm-hppao.h (NO_PC_SPACE_QUEUE_RESTORE): Define.
+
+ * hppa-tdep.c (hppa_pop_frame): Do not restore the PC space
+ queue if NO_PC_SPACE_QUEUE_RESTORE is defined.
+
+ * stabsread.c (REG_STRUCT_HAS_ADDR): Accept additional argument
+ for the structure's type. All callers changed.
+
+ * valops.c (call_function_by_hand): Check REG_STRUCT_HAS_ADDR
+ for each structure argument rather than assuming it's either
+ true or false for all structure arguments.
+
+ * config/pa/tm-hppa.h (REG_STRUCT_HAS_ADDR): Depend only
+ on the length structure passed, not the compiler used.
+
+ * config/sparc/tm-sparc.h (REG_STRUCT_HAS_ADDR): Accept additional
+ argument for the structure's type.
+
+Tue Mar 22 15:28:33 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * values.c (set_internalvar): Don't set var->value until we are
+ sure there won't be an error().
+
+ * remote.c (get_offsets): Reinstate comment which was in
+ remote_wait about use of SECT_OFF_TEXT and so on.
+
+Mon Mar 21 13:11:30 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * symmisc.c (maintenance_check_symtabs): New function to check
+ consistency of psymtabs and symtabs.
+ * symtab.h (maintenance_check_symtabs): Add prototype.
+ * maint.c: Add new `maint check-symtabs' command.
+ * config/i386/tm-i386aix.h, config/i386/tm-sun386.h,
+ config/i386/tm-symmetry.h (REGISTER_CONVERT_TO_RAW): Fix typo.
+ * config/i386/tm-symmetry.h: Make comment inside #if 0 a real
+ comment.
+ * config/i386/tm-symmetry.h (STORE_STRUCT_RETURN): Cast argument
+ to write_memory to avoid warnings from gcc.
+ * config/i386/xm-symmetry.h: Add missing #endif.
+ * config/i386/nm-symmetry.h (NO_PTRACE_H): Add for Dynix.
+ * config/i386/symmetry.mt (TDEPFILES): Add i386-tdep.o.
+ * config/i386/symmetry.mh (NAT_FILE, NATDEPFILES): Add.
+
+Mon Mar 21 11:50:28 1994 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * hppa-tdep.c (hppa_fix_call_dummy): Use value_ptr.
+ (hppa_push_arguments): Likewise.
+
+Mon Mar 21 11:02:51 1994 Stu Grossman (grossman at cygnus.com)
+
+ * alpha-tdep.c: Gobs of changes (many imported from mips-tdep) to
+ improve remote debugging efficiency. Also fixed problems with
+ doing function calls for programs with no entry points.
+ * infcmd.c (run_stack_dummy): Use CALL_DUMMY_ADDRESS instead of
+ entry_point_address.
+ * inferior.h (PC_IN_CALL_DUMMY): ditto.
+ * mdebugread.c (parse_symbol, parse_procedure, parse_external,
+ parse_lines): Pass section_offsets info to these routines so that
+ we can relocate symbol table entries upon readin.
+ * (psymtab_to_symtab_1): Set symtab->primary to tell
+ objfile_relocate to do relocations for our symbols.
+ * (ecoff_relocate_efi): New routine to relocate adr field of PDRs
+ (which hang off of the symbol table).
+ * Use prim_record_minimal_symbols_and_info instead of
+ prim_record_minimal_symbols to supply section info to make minimal
+ symbol relocations work.
+ * minsyms.c (prim_record_minimal_symbols_and_info): If section is
+ -1, try to deduce it from ms_type.
+ * objfiles.c (objfile_relocate): Use ALL_OBJFILE_SYMTABS where
+ appropriate. Handle relocation of MIPS_EFI symbols special. Also,
+ add code to relocate objfile->sections data structure.
+ * remote.c (get_offsets): Use new protocol message to acquire
+ section offsets from the target.
+ * (remote_wait): Get rid of relocation stuff. That's all handled
+ by objfile_relocate now.
+ * config/alpha/alpha-nw.mt (TM_FILE): Use tm-alphanw.h.
+ * config/alpha/tm-alpha.h: Define CALL_DUMMY_ADDRESS, and
+ VM_MIN_ADDRESS.
+ * config/alpha/tm-alphanw.h: DECR_PC_AFTER_BREAK=0, VM_MIN_ADDRESS=0.
+
+Mon Mar 21 10:09:06 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * hpread.c (_initialize_hpuxread): Don't call add_symtab_fns if
+ HPREAD is not defined.
+
+Sun Mar 20 15:21:57 1994 Doug Evans (dje@cygnus.com)
+
+ * sparc-tdep.c (sparc_frame_find_save_regs): Use REGISTER_RAW_SIZE
+ instead of 4.
+ * sp64-tdep.c (target_ptr_bit, set_target_ptr_bit): Deleted,
+ can no longer set this at run time.
+ * config/sparc/sp64.mt (SIMFILES): Use remote-sim.o now.
+ (TM_CLIBS): Define to -lm, the simulator uses the sqrt() function.
+ * config/sparc/tm-sp64.h (FPS_REGNUM, CPS_REGNUM): Define (so
+ sparc-tdep.c compiles).
+ (TARGET_PTR_BIT): Must be a constant now, fix at 64.
+
+Sat Mar 19 08:51:12 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * config/m68k/{cisco.mt,tm-cisco.h}: New files.
+ * Makefile.in (ALLPARAM, ALLCONFIG): Add them.
+ * configure.in: Recognize m68*-cisco*-*.
+
+ * Makefile.in (TAGS): Use variables directly, rather than using
+ find, to locate TM_FILE, XM_FILE, and NAT_FILE. This is faster
+ and means that these filenames no longer need be unique across all
+ the config/* directories.
+ * configure.in: Put the config/*/ into TM_FILE, etc.
+
+ * m68k-stub.c (computeSignal): Return SIGFPE, not SIGURG, for chk
+ and trapv exceptions.
+
+ * target.h (struct section_table), objfiles.h (struct obj_section):
+ Change name of field sec_ptr to the_bfd_section. More mnemonic
+ and avoids the (sort of, for the ptx compiler) name clash with
+ the name of the typedef.
+ * exec.c, xcoffexec.c, sparc-tdep.c, rs6000-nat.c, osfsolib.c,
+ solib.c, irix5-nat.c, objfiles.c, remote.c: Change users.
+
+ * utils.c: Include readline.h.
+ * Makefile.in (utils.o): Add dependency.
+
+ * remote.c (getpkt): Add support for run-length encoding.
+
+Fri Mar 18 19:11:15 1994 Steve Chamberlain (sac@jonny.cygnus.com)
+
+ * utils.c (prompt_for_continue): Call readline, not gdb_readline.
+
+Fri Mar 18 10:25:55 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * dstread.c (record_minimal_symbol): New arg objfile. Pass it to
+ prim_record_minimal_symbol.
+ Callers: Pass it.
+
+ * regex.c (EXTEND_BUFFER): Adjust pointers within buffer by
+ computing their offset from the start of the old buffer and adding
+ to the new buffer, rather than by assuming we can add the
+ difference between the old buffer and the new buffer (it might not
+ fit in an int). Merge in cosmetic differences from emacs regex.c
+ version of this macro.
+
+Wed Mar 16 15:28:54 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * Makefile.in (install-only): Fix use of program_transform_name.
+
+Wed Mar 16 07:18:43 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * printcmd.c: Remove "set print fast-symbolic-addr off" command.
+ The bug which it worked around was fixed on 25 Feb 94 in coffread.c,
+ so I'm nuking the command.
+ * symtab.c (find_addr_symbol): Comment out, no longer used.
+
+ * main.c (main): Don't init_source_path for the -cd argument. Now
+ that source_path doesn't contain the current_directory from when
+ GDB started up, init_source_path is no longer useful (and is
+ harmful because it clobbers a source_path set in $HOME/.gdbinit).
+
+ * TODO: Remove item about line numbers being off. It is useless
+ and confusing without a reproducible test case (it mentions
+ proceed(), but I was able to step through proceed without trouble).
+
+Tue Mar 15 13:39:23 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ For Sunos 4.x targets, enable gdb to set breakpoints in shared
+ library functions before the executable is run. Retrieve dynamic
+ symbols from stripped executables.
+ * symtab.h (minimal_symbol_type): Add mst_solib_trampoline type.
+ * parse.c (write_exp_msymbol), symmisc.c (dump_msymbols),
+ symtab.c (list_symbols): Handle mst_solib_trampoline.
+ * minsyms.c (lookup_minimal_symbol): Handle mst_solib_trampoline
+ for all targets, remove IBM6000_TARGET dependencies.
+ * dbxread.c (read_dbx_dynamic_symtab): New function.
+ * dbxread.c (dbx_symfile_read): Use it.
+ * dbxread.c (SET_NAMESTRING): Set namestring to
+ "<bad string table index>" instead of "foo" if the string index is
+ corrupt.
+ * xcoffread.c (read_xcoff_symtab): Use mst_solib_trampoline instead
+ of mst_unknown.
+ * symtab.c (list_symbols): Take from_tty as parameter and pass it
+ to break_command. Handle mst_file_* minimal symbol types.
+ * config/i386/tm-i386bsd.h: Give just macro name, not args, to #undef.
+
+Tue Mar 15 11:40:43 1994 Kung Hsu (kung@mexican.cygnus.com)
+
+ * c-exp.y(yylex): fix potential memory overflow.
+
+Tue Mar 15 10:33:28 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * environ.c (set_in_environ): Eliminate special handling of PATH and
+ GNUTARGET.
+ * putenv.c: Removed, conflicts with system declaration of
+ putenv on RS/6000 running AIX 3.2.5, and above change makes it
+ unnecessary.
+ * Makefile.in: Change accordingly.
+ * procfs.c (procfs_create_inferior): Change comment accordingly.
+
+Tue Mar 15 10:05:27 1994 Jim Kingdon (kingdon@cygnus.com)
+
+ * rs6000-tdep.c: Change value to value_ptr.
+
+Sun Mar 13 17:19:03 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * hpread.c (read_hpux_symtab: Correctly determine the namespace
+ and address class of SVAR, DVAR, TYPEDEF, TAGDEF, CONST, and
+ MEMENUM symbols. Do not include function-scoped variables in
+ the partial symbol table.
+
+Sun Mar 13 09:45:51 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * i386m3-nat.c: Include floatformat.h.
+ (get_i387_state): Use memset not bzero.
+
+ * Version 4.12.3.
+
+ * Makefile.in: Enable commented out getopt_h, bfd_h, etc. Change
+ ieee-float.h to floatformat.h.
+
+ * valprint.c (val_print_string): Ignore error if the error
+ happened after a terminating '\0'.
+
+ * c-valprint.c (c_val_print): Never add 1 to return value from
+ val_print_string; just return what it returns.
+
+ * target.h (enum target_signal): Add TARGET_SIGNAL_FIRST, for
+ looping through all of the enums.
+ * infrun.c (signals_info): Use it.
+
+Fri Mar 11 08:08:50 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * main.c (main): When printing warning about bad baud rate, don't
+ use warning(); it relies on current_target which isn't set up yet.
+
+ * breakpoint.c (_initialize_breakpoint): Update docstring for
+ tbreak to match what the code actually does. Don't mention tbreak
+ in docstrings for "enable once" or "enable breakpoints once".
+
+Thu Mar 10 08:52:38 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * symfile.h (ADD_PSYMBOL_VT_TO_LIST): Don't put a semicolon after
+ while (0). That defeats the whole purpose of using do . . . while (0).
+ * mdebugread.c (parse_partial_symbols): Don't use ?: expression as
+ list for ADD_PSYMBOL_TO_LIST; the macro takes its address and
+ using a ?: expression as an lvalue is not portable.
+
+ * stabsread.c (define_symbol): If REG_STRUCT_HAS_ADDR, also
+ convert a LOC_ARG to a LOC_REF_ARG. Update code which combines
+ 'p' and 'r' symbol descriptors into a single symbol to look for a
+ LOC_REF_ARG.
+ * README, config/sparc/tm-sparc.h: Update comments.
+
+Wed Mar 9 21:43:24 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * mdebugread.c (parse_type): Do not complain for types with
+ an `indexNil' aux index, these are simply undefined types.
+ Remove indexNil check from caller of parse_type.
+ * mdebugread.c (parse_partial_symbols): Do not enter
+ stGlobal, scCommon symbols into the minimal symbol table, their
+ value is the size of the common, not its address.
+ Handle scInit, scFini, scPData and scXData sections.
+ Use minimal symbol type mst_file_* for stLabel symbols, instead of
+ mst_*.
+ Enter stProc symbols into the global_psymbols list once, not into
+ the static_psymbols_list.
+ Get rid of dummy psymtab if it is empty, to allow proper detection
+ of stripped executables.
+ * mdebugread.c (cross_ref): Allow cross references to Fortran
+ common blocks.
+
+Wed Mar 9 15:23:19 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabsread.c (common_block_end, fix_common_block): Stash the
+ struct pending * in the SYMBOL_TYPE, not the SYMBOL_NAMESPACE, so
+ as to not assume that a pointer fits in an enum.
+
+Wed Mar 9 18:56:36 1994 Kung Hsu (kung@mexican.cygnus.com)
+
+ * os9kread.c (fill_sym): check compiler verion number for pre-
+ UltraC compiler.
+ * os9kread.c (os9k_process_one_symbol): address of symbol is
+ relative to section not module.
+ * stabsread.c (define_symbol): add symbol type 's' as local
+ symbol for os9k.
+ * remote-os9k.c: add command 'set monitor_log' to turn on or off
+ monitor logging.
+ * remote-os9k.c: fix bug in delete breakpoint, single step trace.
+ * remote-os9k.c: fix bug in 'set remotebaud' function.
+ * remote-os9k.c (rombug_link): minimize checking so to improve
+ speed.
+ * symfile.c (symbol_file_command): check if failed to link, also make
+ the command be able to accept more than one filenames.
+ * target.c (target_link): check if failed to link with rombug.
+ * config/i386/tm-i386os9k.h : add #define DECR_PC_AFTER_BREAK 0.
+
+Wed Mar 9 15:23:19 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * remote-es.c (es1800_child_ops): Don't declare it static.
+
+Tue Mar 8 11:42:39 1994 Jim Kingdon (kingdon@cygnus.com)
+
+ * config/i386/tm-i386v4.h: Give just macro name, not args, to #undef.
+
+Tue Mar 8 06:56:13 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * dbxread.c: New variable lowest_text_address.
+ (record_minimal_symbol, read_dbx_symtab): Set it.
+ (read_dbx_symtab): Use lowest_text_address + text_size instead of
+ end_of_text_address.
+ * config/gould/tm-pn.h: Add comment regarding END_OF_TEXT_DEFAULT.
+
+ * dbxread.c (end_psymtab): Remove old and commented out
+ capping_global and capping_static. Fix comments regarding
+ N_SO_ADDRESS_MAYBE_MISSING to match the real name of the macro.
+
+ * parser-defs.h: Add "extern" to start of variable declarations so
+ we don't end up with commons.
+ * parse.c: Define these variables.
+
+ * irix5-nat.c (find_solib): Cast o_path to CORE_ADDR when using it
+ as one.
+
+Mon Mar 7 13:00:50 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * alpha-tdep.c: Change value to value_ptr.
+
+Sun Mar 6 17:36:53 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * solib.c (elf_locate_base): New function to locate the address
+ of the dynamic linker's runtime structure in the dynamic info section.
+ * solib.c (locate_base): Use it instead of iterating over the list
+ of mapped address segments.
+ * solib.c (look_for_base, bfd_lookup_symbol): Removed, no longer
+ necessary.
+
+Fri Mar 4 09:50:47 1994 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * hppa-tdep.c (pc_in_linker_stub): Move decl to beginning of file.
+ (pc_in_interrupt_handler): New function. Also add PARAM decl.
+ (find_proc_framesize): Deal with HPUX setting SAVE_SP bit for
+ signal trampoline and interrupt routines.
+ (frame_saved_pc): Handle signal trampolines and interrupt routines.
+ (frame_chain, frame_chain_valid): Likewise.
+ (hppa_frame_find_saved_regs): Likewise. Also deal with special
+ saved regs convention for SP.
+
+ * tm-hppa[bho].h: FRAME_FIND_SAVED_PC_IN_SIGTRAMP): Define.
+ (FRAME_BASE_BEFORE_SIGTRAMP): Define.
+ (FRAME_FIND_SAVED_REGS_IN_SIGTRAMP): Define.
+
+ * tm-hppah.h (IN_SIGTRAMP): Define.
+
+Thu Mar 3 12:41:16 1994 Jim Kingdon (kingdon@deneb.cygnus.com)
+
+ * ch-exp.y (match_simple_name_string): Accept '_' as well as an
+ alphabetic character as the start of a name.
+
+ * sparclite/Makefile.in (all install): Build and install aload.
+
+ * configure.in: Accept i[34]86-*-*sysv32 because that is what
+ config.guess and config.sub produce.
+
+ * mips-tdep.c: Change value to value_ptr.
+
+Wed Mar 2 09:17:55 1994 Jim Kingdon (kingdon@deneb.cygnus.com)
+
+ * breakpoint.c, breakpoint.h, c-valprint.c, ch-valprint.c,
+ cp-valprint.c, eval.c, expprint.c, findvar.c, language.c,
+ objfiles.h, infcmd.c, printcmd.c, stack.c, typeprint.c,
+ valarith.c, valops.c, valprint.c, value.h, values.c: Replace
+ value with value_ptr. This is for the ptx compiler.
+ * objfiles.h, target.h: Don't declare a "sec_ptr" field using a
+ "sec_ptr" typedef.
+ * symm-nat.c: Add a bunch of stuff for symmetry's ptrace stuff.
+ #if 0 i386_float_info.
+ * symm-tdep.c (round): Remove. Also remove sgttyb.
+ * symm-tdep.c: Remove lots of stuff which duplicates stuff from
+ i386-tdep.c. Remove register_addr and ptx_coff_regno_to_gdb.
+ * i386-tdep.c (i386_frame_find_saved_regs): Put in
+ I386_REGNO_TO_SYMMETRY check in case it is needed for Dynix
+ someday.
+ * config/i386/nm-symmetry.h: Change KERNEL_U_ADDR. Move
+ stuff from PTRACE_READ_REGS, PTRACE_WRITE_REGS macros to
+ symm-nat.c. Define CHILD_WAIT and declare child_wait().
+ * config/i386/tm-symmetry.h: Remove call function stuff; stuff in
+ tm-i386v.h is apparently OK.
+ * config/i386/xm-symmetry.h [_SEQUENT_]: Define HAVE_TERMIOS not
+ HAVE_TERMIO. Define MEM_FNS_DECLARED, NEED_POSIX_SETPGID, and
+ USE_O_NOCTTY.
+
+Wed Mar 2 11:31:08 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * osfsolib.c (xfer_link_map_member): Update to use new
+ target_read_string interface.
+
+Wed Mar 2 09:17:55 1994 Jim Kingdon (kingdon@deneb.cygnus.com)
+
+ * infrun.c (wait_for_inferior): In checking
+ remove_breakpoints_on_following_step, check
+ through_sigtramp_breakpoint as well as step_resume_breakpoint.
+
+Tue Mar 1 16:22:56 1994 Jim Kingdon (kingdon@deneb.cygnus.com)
+
+ * os9kread.c (os9k_process_one_symbol): Rename
+ VARIABLES_INSIDE_BLOCK to OS9K_VARIABLES_INSIDE_BLOCK.
+ * symfile.c (symbol_file_command): Check for (CORE_ADDR)-1, not
+ (CORE_ADDR)0, from target_link, since that is what it uses.
+ Process name at end, not during parsing (like we did before Kung's
+ change), so that -readnow and -mapped can appear anywhere.
+ Make text_relocation a local variable.
+ * config/i386/i386os9k.mt: Fix comment.
+ * Makefile.in (ALLDEPFILES): Add remote-os9k.c.
+ * os9kread.c: Put "comments" after #endif inside /* */.
+ * stabsread.h: Add os9k_stabs variable.
+ * stabsread.c (start_stabs), os9kread.c (os9k_process_one_symbol):
+ Set it.
+ * stabsread.c (define_symbol): If os9k_stabs, put a 'V' symbol
+ descriptor in global_symbols not local_symbols.
+ (read_type): If os9k_stabs, accept 'c', 'i', and 'b' type
+ descriptors.
+ (read_type): If os9k_stabs, accept function parameters after 'f'
+ type descriptor.
+ (read_array_type): If os9k_stabs, don't expect index type and
+ expect lower and upper to be separated by ',' not ';'.
+ (read_enum_type): If os9k_stabs, read a number before the first
+ enumeration constant.
+ (os9k_init_type_vector): New function.
+ (dbx_lookup_type): Call it when starting new type vector.
+ * config/i386/tm-i386os9k.h: Define BELIEVE_PCC_PROMOTION.
+ * (os9k_process_one_symbol): Call define_symbol not os9k_define_symbol.
+ * os9kstab.c: Removed.
+ * Makefile.in: Update accordingly.
+ * objfiles.c (objfile_relocate_data): Removed.
+ * remote-os9k.c (rombug_wait): Call objfile_relocate
+ not objfile_relocate_data.
+ * objfiles.h, objfiles.c: Remove find_pc_objfile.
+ * remote-os9k.c (rombug_wait): Call find_pc_section not
+ find_pc_objfile.
+ * main.c (quit_command): Check inferior_pid; revert Kung change.
+ * remote-os9k.c (rombug_create_inferior): Set inferior_pid.
+
+Tue Mar 1 14:56:14 1994 Kung Hsu (kung@mexican.cygnus.com)
+
+ * os9kread.c: New file to read os9000 style symbo table.
+ * os9kstab.c: new file to read os9000 style stabs.
+ * remote-os9k.c: remote protocol talking to os9000 rombug monitor.
+ * objfiles.c (find_pc_objfile): new function to search objfile
+ from pc.
+ * objfiles.c (objfile_relocate_data): new function to relocate
+ data symbols in symbol table.
+ * objfiles.h: Add two aux fields in struct objfile to handle
+ multiple symbol table files situation like in os9000.
+ * symfile.c: Change so 'symbol-file' command can handle multiple
+ files. Also call target_link() to get relocation infos.
+ * target.c (target_link): new function to get relocation info when
+ a symbol file is requested to load.
+ * main.c (quit_command): take out 'inferior_pid != 0' condition,
+ because in cross mode there's no inferior pid, bit they need to
+ be detached.
+ Makefile.in: add os9kread.c os9kstab.c and .o's.
+ configure.in: add i386os9k target.
+ config/i386/i386os9k.mt: new add.
+ config/i386/tm-i386os9k.h: new add.
+
+Tue Mar 1 13:16:10 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * config/sparc/tm-sun4sol2.h (IN_SIGTRAMP): Handle ucbsigvechandler.
+ * sparc-tdep.c (sparc_frame_saved_pc): Handle ucbsigvechandler.
+
+Tue Mar 1 11:54:11 1994 Jim Kingdon (kingdon@deneb.cygnus.com)
+
+ * target.c, target.h (target_read_string): Provide error detection to
+ caller. Put string in malloc'd space, so caller need not impose
+ arbitrary limits.
+ * solib.c (find_solib): Update to use new interface.
+ * irix5-nat.c (find_solib): Read o_path from inferior
+ (clear_solib): Free storage for o_path.
+ * valprint.c (val_print_string): Add comments.
+
+Mon Feb 28 23:54:39 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * symtab.c (decode_line_1): Handle the case when skip_quoted does not
+ advance `p'.
+
+Mon Feb 28 12:40:46 1994 Jim Kingdon (kingdon@deneb.cygnus.com)
+
+ * value.h (struct value): Add modifiable field.
+ * values.c (allocate_value, record_latest_value, value_copy): Set it.
+ (record_latest_value): Don't mess with VALUE_LVAL of value.
+ * valops.c (value_assign): Check it. Reword existing error
+ message on not_lval.
+
+ * mips-tdep.c (mips_step_skips_delay), config/mips/tm-mips.h
+ (STEP_SKIPS_DELAY): Added.
+ * infrun.c (proceed) [STEP_SKIPS_DELAY]: Check for a breakpoint in
+ the delay slot.
+
+ * valprint.c (val_print_string): If errcode is set, always print
+ an error, regardless of force_ellipsis. In the non-EIO case,
+ just print the error message rather than calling error(). Don't
+ access *(bufptr-1) if bufptr points to the start of the buffer.
+ When looking for '\0', don't increment bufptr and addr if bufptr
+ started out already at limit. If an error happens on fetching the
+ first character, don't print the string.
+
+Sun Feb 27 21:05:06 1994 Jim Kingdon (kingdon@deneb.cygnus.com)
+
+ * config/m68k/tm-apollo68b.h: Remove HAVE_68881 define; it is
+ obsolete.
+
+ * i387-tdep.c, i386-tdep.c i386v-nat.c, i386aix-nat.c,
+ i386m3-nat.c, config/m68k/tm-m68k.h, i960-tdep.c
+ config/i960/tm-i960.h, remote-nindy.c, config/m88k/tm-m88k.h,
+ m88k-tdep.c: Use floatformat.h instead of ieee-float.h.
+ * sparc-tdep.c: Remove now-obsolete ieee-float.h stuff
+ * findvar.c: Update comment regarding ieee-float.h.
+
+Sun Feb 27 21:39:48 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * config/i386/tm-i386v4.h (I386V4_SIGTRAMP_SAVED_PC, IN_SIGTRAMP,
+ FRAME_CHAIN, FRAMELESS_FUNCTION_INVOCATION, FRAME_SAVED_PC):
+ Define to make backtracing through the various sigtramp handlers
+ work.
+ * i386-tdep.c (i386v4_sigtramp_saved_pc): New routine to fetch
+ the saved pc from ucontext on the stack for SVR4 signal handling.
+
+Fri Feb 25 09:41:11 1994 Jim Kingdon (kingdon@deneb.cygnus.com)
+
+ * remote.c, remote-mon.c, remote-utils.c, remote-utils.h,
+ target.h, remote-es.c, remote-nindy.c: Don't set baud rate if
+ baud_rate is -1. Remove sr_get_baud_rate and sr_set_baud_rate;
+ just use the global variable itself. When printing baud rate,
+ don't print a baud rate if baud_rate is -1.
+
+ * coffread.c (read_coff_symtab): Pass mst_file_* to
+ record_minimal_symbol for C_STAT symbols. Put C_EXT and C_STAT
+ symbols in the minimal symbols regardless of SDB_TYPE.
+
+Thu Feb 24 08:30:33 1994 Jim Kingdon (kingdon@deneb.cygnus.com)
+
+ * breakpoint.h (enum bptype): New type bp_through_sigtramp.
+ (bpstat_what_main_action): New code BPSTAT_WHAT_THROUGH_SIGTRAMP.
+ * breakpoint.c (bpstat_what): Return BPSTAT_WHAT_THROUGH_SIGTRAMP
+ if we hit a bp_through_sigtramp breakpoint. Remove kludge which
+ ignored bs->stop for a bp_step_resume breakpoint.
+ * infrun.c (wait_for_inferior): Make a through_sigtramp_breakpoint
+ which performs one (the check_sigtramp2 one) of the functions
+ which had been handled by the step_resume_breakpoint. For each
+ use of the step_resume_breakpoint, make it still use the
+ step_resume_breakpoint, use the through_sigtramp_breakpoint, or
+ operate on both.
+ Deal with BPSTAT_WHAT_THROUGH_SIGTRAMP return from bpstat_what.
+ When setting the frame address of the step resume breakpoint, set
+ it to the address for frame *before* the call instruction is
+ executed, not after.
+
+ * mips-tdep.c (mips_print_register): Print integers using
+ print_scalar_formatted rather than duplicating all the
+ CC_HAS_LONG_LONG and so on.
+ (mips_push_dummy_frame): Use read_register_gen rather than using
+ read_register and then putting it back in target format with
+ store_unsigned_integer. If registers are more than 4 bytes, give
+ an error rather than have some registers overwrite other
+ registers.
+ #if 0 unused include of opcode/mips.h.
+
+ * symfile.h: Don't declare arguments for coff_getfilename.
+
+ * defs.h: Revert Kung change regarding FORCE_LONG_LONG.
+
+Thu Feb 24 08:06:52 1994 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * configure.in (hppa*-*-osf*): New configuration.
+ * config/pa/hppaosf.mt: New target makefile fragment.
+ * config/pa/tm-hppao.h: New target include file.
+
+Thu Feb 24 04:29:19 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * exec.c (print_section_info): Print entry point for exec_bfd only.
+ * ser-unix.c (wait_for): Fix typo in HAVE_TERMIO case.
+ * dwarfread.c: Remove second inclusion of <sys/types.h>, which
+ causes problems if <sys/types.h> has no multiple inclusion protection.
+
+Wed Feb 23 16:28:55 1994 Jeffrey A. Law (law@cygnus.com)
+
+ * tm-hppa.h (CALL_DUMMY): Add two NOP instructions to the end of
+ the call dummy to avoid kernel bugs in HPUX, BSD, and OSF1.
+ (CALL_DUMMY_LENGTH): Changed accordingly.
+
+Wed Feb 23 16:21:25 1994 Stu Grossman (grossman at cygnus.com)
+
+ * sparc-stub.c (trap_low): Make trap handler work for arbitrary
+ numbers of register windows.
+
+ * sparclite/hello.c: Add factorial function for testing.
+ * salib.c: Use macros instead of constants for I/O addresses to
+ make 931 support easier.
+ * sparclite.h: Change constraint for LOC to "rJ" to force use of
+ register in sta/lda instructions.
+
+Wed Feb 23 10:39:18 1994 Jim Kingdon (kingdon@rtl.cygnus.com)
+
+ * dbxread.c (process_one_symbol): Set
+ block_address_function_relative for COFF like we do for ELF and SOM.
+
+Sat Feb 19 03:17:32 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * mdebugread.c (new_psymtab): Pass in section_offsets and set
+ them in the pst.
+ * mdebugread.c (handle_psymbol_enumerators): New function to enter
+ the enumerators of an ecoff enum into the partial symbol table.
+ * mdebugread.c (parse_partial_symbols): Call it.
+ * symfile.c (reread_symbols): Initialize objfile->*_psymbols.next.
+ * symmisc.c (dump_psymtab): Fix typo, clean up output of section
+ offsets. Cast psymtab->read_symtab to PTR before passing it to
+ gdb_print_address.
+ * i386-tdep.c (i386_skip_prologue): Skip over instructions that
+ set up the global offset table pointer in pic compiled code.
+ * config/mips/tm-mips.h (FIX_CALL_DUMMY): For big endian targets,
+ error() on TYPE_CODE_FLT arguments whose size is greater than 8,
+ swap all other TYPE_CODE_FLT arguments as mips_push_arguments
+ ensures that floats are promoted to doubles before they are pushed
+ on the stack.
+
+Fri Feb 18 23:12:59 1994 Stu Grossman (grossman at cygnus.com)
+
+ * sparclite/Makefile.in, sparclite/salib.c, sparclite/sparclite.h:
+ Fixup cache_on and flush_i_cache so that they work for both the
+ 930 and 932 processors. Rewrite most low level funcs (uart
+ access & cache stuff) to use new ASI access macros in sparclite.h.
+ Also make it easy to access second serial port.
+
+Fri Feb 18 22:17:33 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * hp300ux-nat.c: Don't incloude <sys/dir.h>, <sys/ioctl.h>, or
+ <sys/stat.h>; not needed.
+
+Fri Feb 18 08:26:29 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stack.c (print_frame_info): In "pathological" case, don't
+ distrust the line number information.
+
+Fri Feb 18 16:51:14 1994 Kung Hsu (kung@mexican.cygnus.com)
+
+ * mips-tdep.c (mips_print_register): handle 64 bits register.
+ * valprint.c (print_longest): fix a bug in printing 64 bits value.
+
+Fri Feb 18 08:26:29 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * Version 4.12.2.
+
+ * Makefile.in (install): Do the sed for program_transform_name
+ ourselves instead of worrying about INSTALL_XFORM. This enables
+ users to override INSTALL_PROGRAM in the standard way.
+
+ * Makefile.in (c-exp.tab.o, ch-exp.tab.o, m2-exp.tab.o): Don't
+ depend on Makefile.in.
+
+ * defs.h, valprint.c: Make longest_to_int a function not a macro.
+ Only test against INT_MIN if a LONGEST is bigger than an int.
+
+ * README: Change GhostScript to Ghostscript.
+
+Fri Feb 18 07:30:55 1994 Jim Kingdon (kingdon@cygnus.com)
+
+ * config/rs6000/{tm-rs6000lynx.h,nm-rs6000lynx.h,xm-rs6000lynx.h}:
+ Rename to tm-rs6000ly.h, nm-rs6000ly.h, xm-rs6000ly.h for 14
+ character file names.
+ * Makefile.in (ALLPARAM): Add these files.
+
+ * config/mips/littlemips64.mt: Rename to mipsel64.mt for 14
+ character file names.
+ * Makefile.in: Add Kung's new mips64 files.
+
+Thu Feb 17 17:25:47 1994 Kung Hsu (kung@mexican.cygnus.com)
+
+ * configure.in: add mips64-*-elf, mips64-*-ecoff, mips64el-*-elf,
+ mips64el-*-ecoff and mips64-big-*.
+ * defs.h: get rid of FORCE_LONG_LONG.
+ * mips-tdep.c (mips_find_saved_regs): add sd and sdc1 instruction
+ parsing. Change register size to be MIPS_REGSIZE.
+
+Thu Feb 17 09:30:22 1994 David J. Mackenzie (djm@thepub.cygnus.com)
+
+ * corelow.c, exec.c, irix5-nat.c, mipsread.c, objfiles.c,
+ osfsolib.c, rs6000-nat.c, solib.c, symfile.c, utils.c,
+ xcoffexec.c: Use bfd_get_error and bfd_set_error and new error names.
+
+Fri Feb 11 21:47:24 1994 Steve Chamberlain (sac@sphagnum.cygnus.com)
+
+ * remote-hms.c (readchar, hms_open, hms_fetch_register): Made more robust.
+ (remove_commands, add_commands): Add/remove hms-drain when target
+ is connected.
+
+Fri Feb 11 16:11:38 1994 Stu Grossman (grossman at cygnus.com)
+
+ * configure.in: Add Lynx/rs6000 support.
+ * lynx-nat.c: Clean up some Sparc stuff. Clean up ptrace error
+ messages. Add rs6000 support. Don't try to modify unwritable
+ registers.
+ * rs6000-nat.c: Move lots of native dependent stuff (like core
+ file support) from rs6000-tdep.c & xcoffexec.c to here.
+ * rs6000-tdep.c: Move native dependent stuff to nat.c.
+ * xcoffexec.c: Move native dependent stuff to nat.c.
+ * config/rs6000/nm-rs6000.h: Move defs of SOLIB_* macros to here
+ from tm file.
+ * config/rs6000/tm-rs6000.h: Remove defs of SOLIB_* funcs, cuz they're
+ really native.
+ * config/rs6000/tm-rs6000lynx.h, config/rs6000/xm-rs6000lynx.h:
+ New files to support Lynx/rs6000.
+
+Tue Feb 8 00:32:28 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * README: Remove note about gcc warnings on alpha, these should be
+ gone now.
+ * c-exp.y, ch-exp.y, core.c, corelow.c, eval.c, fork-child.c,
+ m2-exp.y, minsyms.c, nlmread.c, parse.c, putenv.c, regex.c
+ remote-utils.c, stabsread.c: Include <string.h>.
+ * regex.c: Include "defs.h", change re_comp argument to const char *.
+ * infptrace.c (fetch_register, store_inferior_registers): Change
+ regaddr to type CORE_ADDR.
+ * config/alpha/alpha-nw.mt, config/alpha/alpha-osf1.mt (MT_CFLAGS):
+ Remove, no longer necessary now that we use bfd_vma for a CORE_ADDR.
+
+Mon Feb 7 09:21:17 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * symtab.h: Always define BYTE_BITFIELD to nothing.
+
+Mon Feb 7 08:44:17 1994 Jim Kingdon (kingdon@deneb.cygnus.com)
+
+ * config/m68k/{m68k-em.mt,tm-m68k-em.h}: Remove; no longer used.
+ * configure.in: Remove comment about m68k-em.mt.
+ * Makefile.in: Remove references.
+
+Mon Feb 7 08:22:42 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * defs.h [BFD64]: Use BFD_HOST_64_BIT, not nonexistent
+ BFD_HOST_64_TYPE.
+
+Sun Feb 6 15:56:09 1994 Jeff Law (law@wild.cs.utah.edu)
+
+ * hpread.c (hpux_symfile_init): Use obj_som_* rather than obj_* to
+ access BFD private data. Search for the "$TEXT$" space rather
+ than ".text".
+ (hppa_sym_fns): Add bfd target flavour to initializer.
+
+Sun Feb 6 06:55:15 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * target.c (target_preopen): If target_kill doesn't remove the
+ target from the stack, use pop_target to do it.
+
+ * coffread.c (process_coff_symbol, case C_TPDEF): Don't set name
+ of TYPE_CODE_PTR or TYPE_CODE_FUNC types. This parallels similar
+ changes to stabsread.c from summer 1993.
+
+ * remote-udi.c (udi_files_info): If prog_name is NULL, just skip
+ printing the program, rather than passing NULL to printf.
+ (udi_detach): Set udi_session_id to -1 so that udi_close doesn't
+ try to call UDIDisconnect again. Print better message.
+ (udi_kill): Just call UDIDisconnect ourselves, rather than doing
+ it via udi_close.
+ (udi_create_inferior): If udi_session_id is negative, open a new
+ TIP rather than giving an error.
+
+ * config/mips/mipsm3.mh, config/i386/i386m3.mh,
+ config/ns32k/ns32km3.mh: Define NAT_FILE.
+ * config/nm-m3.h: Change guard from _OS_MACH3_H_ and _OS_MACH3_H
+ (it was inconsistent and namespace-wrong) to NM_M3_H.
+ * m3-nat.c (mach_really_wait): Change parameter name to ourstatus.
+ (m3_open): New function.
+ (m3_ops): Use it.
+ * TODO: Update Mach section.
+
+ * Makefile.in: Remove "rapp" stuff; it is superseded by gdbserver.
+
+Sun Feb 6 13:26:21 1994 Per Bothner (bothner@kalessin.cygnus.com)
+
+ * printcmd.c (printf_command): Add missing single-letter
+ backslash-escape sequences, and improve error message.
+
+Sun Feb 6 06:55:15 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * corelow.c (solib_add_stub, core_open): Pass address of from_tty
+ rather than trying to shove an int into a pointer and back out
+ again. This avoids compiler warnings.
+
+ * defs.h (alloca): Declare as void *, not char *, on hpux.
+ Don't prototype it, just declare the return type.
+
+Sun Feb 6 03:25:41 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * config/i386/tm-sun386.h, config/i386/tm-symmetry.h
+ (REGISTER_CONVERT_TO_RAW): Add missing backslash.
+
+Sat Feb 5 08:03:41 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * remote-mips.c (mips_fetch_registers): If regno is FP_REGNUM or
+ ZERO_REGNUM, just read it as zero without talking to the board.
+
+ * config/i386/tm-i386aix.h (REGISTER_CONVERT_TO_RAW): Add missing
+ backslash.
+ * i386-tdep.c (i386_extract_return_value): Pass TYPE_LENGTH (type)
+ to store_floating, not nonexistent variable len.
+
+ * remote-mips.c (mips_insert_breakpoint, mips_remove_breakpoint):
+ New functions.
+ (mips_store_word): Change calling convention to return errors, and
+ to provide old contents if the caller wants it.
+ (mips_xfer_memory): Deal with errors from mips_store_word.
+ * config/mips/tm-idt.h, config/mips/tm-idtl.h: Remove BREAKPOINT
+ define now that remote-mips.c doesn't use BREAKPOINT.
+
+ * remote-mips.c (mips_create_inferior): Call warning if arguments
+ specified, and then execute "set args" command. Call error, not
+ mips_error, if executable file not specified.
+
+ * remote-e7000.c: Replace "snoop" command (e7000_noecho) with
+ remote_debug.
+
+ * config/rs6000/tm-rs6000.h (STORE_STRUCT_RETURN): Don't cast
+ to unsigned int.
+
+Sat Feb 5 05:27:05 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * value.h (print_longest): Rename "value" to "val" in prototype
+ declaration because some compilers don't like arguments whose
+ names are the same as types.
+ * remote.c (remote_xfer_memory): Cast "myaddr" to unsigned char *
+ before passing it to remote_*_bytes.
+
+Fri Feb 4 15:53:18 1994 Steve Chamberlain (sac@cygnus.com)
+
+ * h8500-tdep.c (saved_pc_after_call): The size of the
+ pc is memory model dependent. (segmented_command,
+ unsegmented_command, _initialize_h8500_tdep): New commands to
+ change memory model.
+ * remote-e7000.c (_initialize_remote_e7000): Change name of snoop
+ command.
+ * remote-hms.c (hms_load): Remove breakpoints when loaded.
+ (hms_wait): Use new status structure
+ (hms_open): Push the target here. (hms_before_main_loop): Not
+ here. (supply_val, hms_fetch_register, hms_store_register): Cope
+ with H8/500 names too. (hms_fetch_register): Take out REGISTER_TYPE.
+ * sh-tdep.c (show_regs, initialize_sh_tdep): New command to print
+ all registers in a compact way.
+
+Fri Feb 4 07:41:13 1994 Jim Kingdon (kingdon@deneb.cygnus.com)
+
+ * config/rs6000/tm-rs6000.h: Declare rs6000_struct_return_address
+ as CORE_ADDR to match definition in rs6000-tdep.c.
+
+Fri Feb 4 01:14:20 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * dwarfread.c (process_dies): Skip nested TAG_compile_unit DIEs.
+ * dwarfread.c (add_partial_symbol): Do not enter opaque aggregate
+ definitions into the psymtab.
+
+Thu Feb 3 12:38:58 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * m68k-stub.c: Treat mc68332 like mc68020 most places. Provide
+ a special exceptionSize for the 68332.
+
+ * remote-udi.c (udi_attach): If no arguments, print error.
+
+Thu Feb 3 17:34:05 1994 Fred Fish (fnf@cygnus.com)
+
+ * Makefile.in (VERSION): Bump to 4.12.1
+ * NEWS, README: Update to match 4.12 release.
+
+Thu Feb 3 12:38:58 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * command.c (empty_sfunc): New function.
+ (add_set_cmd): Use it instead of not_just_help_class_command.
+ (not_just_help_class_command): Change calling convention back to
+ what it was before yesterday's change.
+
+ * stabsread.c (read_sun_builtin_type): Skip the semicolon at the end
+ of the type if present.
+
+Wed Feb 2 11:16:45 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * printcmd.c (decode_format): Don't blithely set the size for
+ an address to 'w'. Make it 'g' or 'h', depending on TARGET_PTR_BIT.
+
+ * defs.h: Just typedef CORE_ADDR to bfd_vma. Include bfd.h.
+ If BFD64, make a LONGEST a BFD_HOST_64_BIT.
+ * defs.h (longest_to_int): Don't depend on CC_HAS_LONG_LONG; instead
+ always just check against INT_MIN and INT_MAX (this also fixes things
+ if sizeof (long) > sizeof (int), e.g. Alpha).
+ * config/pa/tm-hppa.h, config/i386/sun386.h, config/rs6000/tm-rs6000.h:
+ Don't define LONGEST or BUILTIN_TYPE_LONGEST.
+ * gdbtypes.h: Remove BUILTIN_TYPE_LONGEST and
+ BUILTIN_TYPE_UNSIGNED_LONGEST.
+ * language.h, c-lang.c, ch-lang.c, m2-lang.c, language.c: Remove
+ longest_int and longest_unsigned_int.
+ * value.h (struct value): Just align to LONGEST, rather than worrying
+ about CC_HAS_LONG_LONG.
+ * valarith.c (value_binop): Figure out type ourself based on
+ sizeof (LONGEST) rather than relying on BUILTIN_TYPE_LONGEST. The
+ point is that we don't depend on CC_HAS_LONG_LONG anymore.
+ * valprint.c (val_print_type_code_int): Just call
+ extract_unsigned_integer directly, rather than going through
+ unpack_long.
+ * printcmd.c (decode_format): Remove code which would sometimes
+ change 'g' size to 'w' for integers. print_scalar_formatted handles
+ printing huge integers well enough, thank you.
+
+ * command.c (add_set_cmd, not_just_help_class_command): Change
+ to make this the sfunc, not cfunc, since that is how we call it.
+ * command.h: Comment difference between sfunc and cfunc.
+ * demangle.c (set_demangling_command): Add third arg since that
+ is how it is called.
+ (_initialize_demangler): Use sfunc, not cfunc, for
+ set_demangling_command, since that is how it is called.
+ Remove show_demangling_command; it has no effect.
+
+ * command.c (shell_escape): Report errors correctly (with error
+ message from strerror).
+
+Wed Feb 2 14:35:41 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * xcoffread.c (read_xcoff_symtab): Change CSECT_LEN to use
+ x_scnlen.l rather than x_scnlen to match corresponding change in
+ coff/internal.h.
+
+Wed Feb 2 11:16:45 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdbtypes.h, ch-typeprint.c, ch-valprint.c:
+ Change comments regarding TYPE_CODE_BOOL.
+ * language.c (boolean_type): Always return 1 for TYPE_CODE_BOOL,
+ regardless of the language.
+ (value_true): Just call value_logical_not regardless of language.
+ * coffread.c (coff_read_enum_type), stabsread.c (read_enum_type):
+ Remove #if 0'd code which makes some enums TYPE_CODE_BOOL.
+ * language.h: Improve comment for la_builtin_type_vector.
+ * m2-lang.c (_initialize_m2_language): Don't add any fields to
+ builtin_type_m2_bool.
+
+Tue Feb 1 17:13:32 1994 Kevin Buettner (kev@cujo.geg.mot.com)
+
+ * config/m88k/{tm-delta88.h,tm-delta88v4.h}, m88k-tdep.c:
+ Define IN_SIGTRAMP and backtrace correctly through signal handlers.
+
+Tue Feb 1 22:13:25 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * procfs.c (wait_fd): Handle EINTR error return from PIOCWSTOP ioctl
+ by restarting the ioctl.
+
+Tue Feb 1 16:16:25 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * target.h (target_wait): Add comment about calling
+ return_to_top_level.
+
+Tue Feb 1 12:21:00 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * coffread.c (read_one_sym): bfd_coff_swap_aux_in now takes
+ additional arguments.
+ * xcoffread.c (read_xcoff_symtab, read_symbol_lineno): Likewise.
+
+Mon Jan 31 16:10:41 1994 Stu Grossman (grossman at cygnus.com)
+
+ * sparc-stub.c: Remove unnecessary #include of memory.h.
+
+Mon Jan 31 12:12:34 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * mips-tdep.c: Remove code which sets saved_regs from
+ init_extra_frame_info and put it in new function mips_find_saved_regs.
+ (READ_FRAME_REG): Remove macro and replace uses with the expansion.
+ * mips-tdep.c, config/mips/tm-mips.h: When examining ->saved_regs,
+ check if it is NULL and call mips_find_saved_regs if so.
+
+ * remote-mips.c: Use unfiltered, not filtered, output most places.
+
+ * blockframe.c (get_prev_frame_info): Detect and stop an infinite
+ backtrace. Revise comments.
+
+Mon Jan 31 09:40:33 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * mdebugread.c (parse_procedure): Remove _sigtramp kludges for
+ alpha and irix. The _sigtramp case has to be handled properly
+ in the tdep files if we have no ecoff debugging info.
+ * alpha-tdep.c (alpha_frame_saved_pc, alpha_frame_chain),
+ mips-tdep.c (mips_frame_saved_pc): Handle signal handler frames
+ without PC_REGNUM kludge.
+ * mdebugread.c (fixup_sigtramp), mips-tdep.c (read_next_frame_reg):
+ Clean up handling of mips sigtramp frames, improve comments.
+
+Sat Jan 29 23:25:57 1994 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * paread.c (read_unwind_info): Fix typo.
+
+ * paread.c (pa_symtab_read): Update the "check_strange_names"
+ filter to match GCC's current output. Filter out section symbols
+ (which the HP linker sometimes puts in the wrong place).
+
+Sat Jan 29 07:44:59 1994 Jim Kingdon (kingdon@deneb.cygnus.com)
+
+ * serial.h (SERIAL_SET_TTY_STATE): Comment return value.
+
+ * Makefile.in (TAGS): Just echo one line, rather than the whole thing.
+
+ * Makefile.in: Remove all references to sparcly-nat.c.
+
+ * Makefile.in (HFILES_NO_SRCDIR): Include dcache.h remote-utils.h
+ remote-sim.h directly, rather than via $(remote_utils_h). This avoids
+ duplicating serial.h and target.h.
+
+ * Makefile.in: Don't set M_INSTALL and M_UNINSTALL. These variables
+ are not used anywhere (a 5 Oct 1993 change removed the uses).
+
+ * config/m68k/monitor.mt (TDEPFILE): Add remote-es.o.
+ * config/m68k/es1800.mt: Add comment.
+ * remote-es.c: Extensive changes to update to current conventions.
+
+ * ser-unix.c (wait_for, hardwire_readchar) [HAVE_TERMIO, HAVE_TERMIOS]:
+ If the timeout is too big to fit in c_cc[VTIME], then do multiple reads
+ to achieve the desired timeout.
+ * serial.h (serial_t): Add field timeout_remaining.
+
+Fri Jan 28 08:45:02 1994 Jim Kingdon (kingdon@deneb.cygnus.com)
+
+ * c-exp.y (yylex): Reenable nested type code.
+
+Fri Jan 28 15:40:33 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * a29k-tdep.c (examine_tag): Add comment regarding argcount.
+
+ * remote-mips.c (mips_ops): Fix docstring.
+
+ * remote-bug.c (bug_ops): Remove spurious newline from docstring.
+
+ * config/m68k/tm-monitor.h: Changes to bring this into accordance
+ with the old tm-m68k-em.h:
+ (GDBINIT_FILENAME, DEFAULT_PROMPT): Remove.
+ (HAVE_68881): Don't undefine; HAVE_68881 is obsolete.
+ (REGISTER_NAMES): Don't muck with it; what tm-m68k.h has is fine.
+ Add FIXME regarding GET_LONGJMP_TARGET.
+
+ * remote-udi.c (udi_close, udi_detach, udi_kill): Add comments.
+ * infptrace.c (kill_inferior): Add comments.
+ * main.c (quit_command): Call target_close after we kill or
+ detach.
+ * remote-udi.c (udi_close): Don't error() if QUITTING.
+
+Fri Jan 28 11:55:52 1994 Rob Savoye (rob@darkstar.cygnus.com)
+
+ * configure.in: Make m68k-coff and aout add monitor support in
+ addition to the standard serial support.
+
+Fri Jan 28 08:45:02 1994 Jim Kingdon (kingdon@deneb.cygnus.com)
+
+ * mdebugread.c (psymtab_to_symtab_1): Don't complain on stLabel with
+ index indexNil.
+
+Fri Jan 28 10:40:34 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * config/pa/tm-hppa.h: Define macro SMASH_TEXT_ADDRESS.
+ * elfread.c (record_minimal_symbol_and_info),
+ dwarfread.c (process_dies), paread.c (pa_symtab_read): Use it.
+
+Thu Jan 27 15:12:23 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * i386-stub.c: Add ".text" right before "mem_fault:".
+
+ * main.c (baud_rate): Add FIXME comment about printing -1 value.
+
+ * remote-utils.c (usage): Fix message to be accurate and conform
+ more closely to normal conventions.
+
+ * remote-utils.c (gr_files_info): Have the exec_bfd test control
+ whether to show information about exec_bfd, and not control whether
+ to show information about device and speed.
+
+ * remote-utils.c (gr_open): If sr_get_device returns NULL, give
+ usage message, don't dump core.
+
+ * remote-bug.c (bug_write_memory): Use alloca, not GCC extension
+ for variable size array.
+ (bug_fetch_register, bug_store_register): Rename "value" to
+ "fpreg_buf" because some compilers don't like variables whose
+ names are the same as types.
+ (bug_store_register): Use a cast when converting char * to
+ unsigned char *.
+
+ * symmisc.c (maintenance_print_symbols): Don't refer to the name
+ of the command in error message (the text was referring to the old
+ name of the command).
+
+ * symmisc.c (dump_symtab): Fix args to fprintf_filtered.
+
+ * c-typeprint.c (c_type_print_base): Have SHOW == 0 mean to print
+ full details on structure elements without names. This partially
+ reverts the changes of 1 Jul 1993 and 31 Aug 1993; I think this aspect
+ of those changes was accidental.
+
+ * stack.c (parse_frame_specification): If SETUP_ARBITRARY_FRAME is
+ defined, make it an error to specify a single argument which is not
+ a frame number.
+
+ * Makefile.in (version.c), main.c (print_gdb_version): Use
+ host_alias and target_alias, not host_canonical and
+ target_canonical, to print configuration.
+
+Wed Jan 26 10:57:21 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * parse.c (write_exp_msymbol): Use new type msymbol_addr_type instead
+ of builtin_type_long. It is necessary to get a type which is
+ TARGET_PTR_BIT bits in size; builtin_type_long might not be big enough.
+
+ Fix many sins which will come up in 32 bit x 64 bit GDB, and
+ various miscellaneous things discovered in the process:
+ * printcmd.c, defs.h (print_address_numeric): New function.
+ * c-valprint.c (c_val_print), ch-valprint.c (chill_val_print)
+ breakpoint.c (describe_other_breakpoints, breakpoint_1, mention),
+ cp-valprint.c (cplus_print_value), infcmd.c (jump_command),
+ printcmd.c, stack.c, symfile.c, symmisc.c, valprint.c:
+ Use it.
+ * utils.c, defs.h (gdb_print_address): New function.
+ * expprint (dump_expression), gdbtypes.h: Use it.
+ * breakpoint.c (describe_other_breakpoints),
+ symmisc.c (dump_symtab, print_symbol):
+ Use filtered not unfiltered I/O.
+ (remove_breakpoints): Remove BREAKPOINT_DEBUG code. Might as well
+ just run gdb under a debugger for this (and it had problems with
+ printing addresses, how to print b->shadow, etc.).
+ * buildsym.c (make_blockvector), core.c (memory_error),
+ exec.c (print_section_info), maint.c (print_section_table),
+ mdebugread.c (parse_procedure), solib.c, source.c, symfile.c,
+ symmisc.c, symtab.c, valops.c, valprint.c, xcoffexec.c:
+ Add comments saying code is broken. Marked with "FIXME-32x64".
+ * dbxread.c (process_one_symbol), partial-stab.h (default),
+ remote-vx.c (vx_run_files_info):
+ Don't cast int being passed to local_hex_string.
+ * symmisc.c (print_symbol): Don't cast long being passed to %lx.
+ * symtab.h (general_symbol_info): Add comment about SYMBOL_VALUE
+ only being a long.
+ * symmisc.c (print_symbol): Print "offset" in message for LOC_ARG
+ and LOC_LOCAL.
+ * printcmd.c (print_address): Remove #if 0 code with ADDR_BITS_REMOVE.
+ * source.c: Include <sys/types.h> regardless of USG.
+
+Tue Jan 25 12:58:26 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * valops.c (value_assign): Set `type' after coercing toval.
+ * c-valprint.c (c_val_print), ch-valprint.c (chill_val_print):
+ Use extract_unsigned_integer to get the address of a reference.
+
+Tue Jan 25 11:31:53 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabsread.c (STABS_CONTINUE, error_type), partial-stab.h:
+ AIX can use ? instead of \ for continuation. Deal with it.
+
+ * paread.c (read_unwind_info): Just assign to objfile->obj_private,
+ not OBJ_UNWIND_INFO. Assigning to a cast is a GCC-ism which
+ the HP compiler in ANSI mode doesn't like.
+
+ * main.c: When defaulting HAVE_SIGSETMASK based on USG, just do it
+ based on USG, rather than defining HAVE_SIGSETMASK to an
+ expression containing defined. Having a macro used in #if expand
+ to an expression containing "defined" is undefined according to
+ ANSI, and the HP compiler in ANSI mode doesn't do what we wanted
+ it to.
+
+Mon Jan 24 20:51:29 1994 John Gilmore (gnu@cygnus.com)
+
+ * sparc-nat.c (fetch_inferior_registers, store_inferior_registers):
+ Clean up the changes of 11 Jan, as recommended by Peter Schauer.
+
+Fri Jan 21 19:10:44 1994 Per Bothner (bothner@kalessin.cygnus.com)
+
+ * ch-exp.y (match_string_literal): Allow a zero-length string.
+ * ch-lang.c (chill_printstr): Don't print zero-length string funny.
+
+Sat Jan 22 17:08:48 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * i386aix-nat.c (i386_float_info): Reverse order of registers before
+ passing them to print_387_status.
+ (print_387_status): Don't subtract top from 7 before using it.
+ * i387-tdep.c: Remove comment about AIX wanting "top" subtracted
+ from 7; the above explains it.
+
+Sat Jan 22 20:25:11 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * mips-tdep.c (init_extra_frame_info): Use frame relative stack
+ pointer value when fixing up the frame at the start of a function.
+
+Sat Jan 22 12:29:13 1994 Stu Grossman (grossman at cygnus.com)
+
+ * lynx-nat.c (fetch_core_registers): Load the I & L regs for the
+ Sparc from the stack.
+
+Sat Jan 22 08:30:42 1994 Jim Kingdon (kingdon@deneb.cygnus.com)
+
+ * remote-mips.c (mips_initialize): Clear mips_initializing via
+ cleanup chain, not directly.
+
+ * ser-unix.c (wait_for) [HAVE_TERMIO, HAVE_TERMIOS]: Make a timeout
+ of -1 mean forever, like in the HAVE_SGTTY case. Warn if we are
+ munging the timeout due to the limited range of c_cc[VTIME].
+
+ * fork-child.c, inferior.h (fork_inferior): New argument shell_file.
+ * procfs.c (procfs_create_inferior), inftarg.c (child_create_inferior),
+ m3-nat.c (m3_create_inferior): Pass it.
+ * procfs.c: Remove ptrace function. It was declared in a way which
+ conflicted with the prototype in unistd.h on Solaris.
+
+Sat Jan 22 01:37:40 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * sparc-tdep.c (frame_saved_pc): Get the pc from the saved pc
+ in the sigcontext if it is a signal trampoline frame.
+ * config/sparc/tm-sun4sol2.h (IN_SIGTRAMP, SIGCONTEXT_PC_OFFSET):
+ Define for Solaris2.
+
+Sat Jan 22 00:34:47 1994 Stu Grossman (grossman at cygnus.com)
+
+ * sparc-tdep.c, lynx-nat.c, config/sparc/tm-sparc.h,
+ config/sparc/tm-sparclynx.h: Move defs of FRAME_SAVED_I0/L0 to
+ tm-sparc.h so they can be overridden if necessary.
+
+Fri Jan 21 17:49:28 1994 Stu Grossman (grossman at cygnus.com)
+
+ * lynx-nat.c: Add Sparc support.
+ * sparcly-nat.c: Remove. It's useless.
+ * config/sparc/nm-sparclynx.h: Rewrite.
+ * config/sparc/sparclynx.mh (NATDEPFILES): Replace sparcly-nat.o
+ with lynx-nat.o
+ * config/sparc/tm-sparclynx.h: Rewrite.
+
+Fri Jan 21 19:08:48 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * rs6000-pinsn.c: Use the new disassembler in the opcodes
+ directory. Old code was discarded, since the new opcode table has
+ a different format.
+
+Fri Jan 21 14:28:30 1994 Fred Fish (fnf@cygnus.com)
+
+ * Makefile.in (realclean): Remove info files per make-stds.texi.
+
+Fri Jan 21 12:47:53 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * dbxread.c (end_psymtab): Only patch psymtab textlow and texthigh
+ if N_SO_ADDRESS_MAYBE_MISSING is defined.
+ * config/sparc/tm-sun4sol2.h: Define it.
+
+Thu Jan 20 15:04:24 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * printcmd.c (print_address_symbolic): Unconditionally use msymbol
+ if we did not find a symbol.
+
+Fri Jan 21 08:20:18 1994 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * infptrace.c (child_xfer_memory): Only use if CHILD_XFER_MEMORY
+ is not defined.
+
+ * hppab-nat.c (call_ptrace): Delete redundant function.
+ (kill_inferior, attach, detach, child_resume): Likewise.
+ (child_xfer_memory): Likewise.
+
+ * hppah-nat.c (call_ptrace): Delete redundant function.
+ (kill_inferior, attach, detach, child_resume): Likewise.
+
+ * config/pa/hppabsd.mh (NATDEPFILES): Add infptrace.o.
+
+ * config/pa/hppahpux.mh (NATDEPFILES): Add infptrace.o.
+
+ * config/pa/nm-hppab.h (FETCH_INFERIOR_REGISTERS): Define.
+
+ * config/pa/nm-hppah.h (FETCH_INFERIOR_REGISTERS): define.
+ (CHILD_XFER_MEMORY): Define.
+ (PT_*): Define so that generic infptrace.c code can be used.
+
+Fri Jan 21 09:23:33 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * xcoffread.c (xcoff_symfile_read): Make second parameter a
+ struct section_offsets *, not a (nonexistent) struct section_offset *.
+
+ * xcoffread.c (read_xcoff_symtab): Make main_aux just a union
+ internal_xcoff_symtab, not an array of one of them. Change lots of
+ "main_aux" to "&main_aux" and so on.
+
+ * coffread.c, xcoffread.c: Include <coff/internal.h>
+ before "symfile.h".
+
+Thu Jan 20 17:30:55 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * coffread.c (coff_getfilename): Make it not static.
+
+ * xcoffread.c (read_xcoff_symtab): complain() not abort().
+
+ * xcoffread.c (struct coff_symbol): Rename c_nsyms to c_naux (removes
+ a completely gratuitous difference between xcoffread.c and coffread.c).
+
+Wed Jan 19 15:09:44 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * infrun.c (wait_for_inferior): Don't set frame for
+ step_resume_breakpoint for IN_SIGTRAMP cases.
+
+ * infrun.c (wait_for_inferior), breakpoint.h (struct bpstat_what),
+ breakpoint.c (bpstat_what): Move step_resume from its own field of
+ the struct bpstat_what into the main_action. Make it override
+ other breakpoints. This is a conservative change in the sense
+ that before the step resume breakpoint was a breakpoint.c
+ breakpoint, hitting the step resume breakpoint overrode even
+ calling bpstat_stop_status.
+
+Wed Jan 19 12:40:25 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * infrun.c (normal_stop): Set stop_pc after popping the dummy frame
+ in case execution was stopped in the called function.
+ * stack.c (print_frame_info, frame_info): If backtracing through
+ a call dummy, handle the starting source line number on a line
+ boundary like backtracing through sigtramp.
+ * sparc-tdep.c (sparc_frame_find_saved_regs): Get frame address
+ for call dummy frame right. Remove old test for dummy frame,
+ it has been unused at least since gdb-3.5.
+ * sparc-tdep.c (sparc_push_dummy_frame): Set return address register
+ of the dummy frame.
+
+Tue Jan 18 16:16:35 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * infcmd.c (signal_command): Accept 0 as legitimate signal number.
+
+Tue Jan 18 14:09:25 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * infrun.c (signals_info), target.c (target_signal_from_name):
+ Use ugly casts to avoid enumvar < enumvar or enumvar++.
+
+Mon Jan 17 22:00:15 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * ser-unix.c (hardwire_noflush_set_tty_state): Don't muck with ICANON.
+ * inflow.c (terminal_ours_1): When discussing how to deal with the
+ tty state, make note of query() as well as readline.
+
+ * infrun.c (_initialize_infrun): Add TARGET_SIGNAL_POLL to list of
+ signals for which stop and print are cleared by default.
+
+Mon Jan 17 20:00:51 1994 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * config/pa/tm-hppa.h (unwind_table_entry): Use one of the
+ reserved fields to hold a stub unwind entry type. Fix typo.
+ (stub_unwind_entry): New structure for raw stub unwind entries.
+ (stub_unwind_types): The types of stubs we may encounter.
+ (UNWIND_ENTRY_SIZE, STUB_UNWIND_ENTRY_SIZE): New defines.
+ * hppa-tdep.c (rp_saved): Use additional information provided
+ by linker stub unwind descriptors.
+ (frameless_function_invocation): Likewise.
+ (frame_chain_valid): Likewise.
+ * paread.c (compare_unwind_entries): New function for sorting
+ unwind table entries.
+ (read_unwind_info): Rewrite to remove dependency on host endianness.
+ Read in data from the $UNWIND_END$ subspace which contains linker
+ stub unwind descriptors. Merge that data into the basic unwind
+ table.
+
+ * hppab-nat.c (_initialize_kernel_u_addr): Delete unwanted functions.
+
+Mon Jan 17 22:00:15 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * xcoffread.c (read_xcoff_symtab, case C_FILE): Accept the name
+ from either the symbol name or the auxent.
+ * coffread.c, symfile.h (coff_getfilename): Renamed from getfilename,
+ no longer static.
+
+Mon Jan 17 13:35:01 1994 Fred Fish (fnf@cygnus.com)
+
+ * Makefile.in (ALLPARAM): Change irix5.h to nm-irix5.h.
+
+Mon Jan 17 12:35:42 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * README: Update notes for alpha port.
+
+Mon Jan 17 11:15:57 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * i960-tdep.c (i960_fault_to_signal): Return TARGET_SIGNAL_ILL
+ for operation fault, constraint fault, and type fault.
+
+Sun Jan 16 12:46:01 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * Makefile.in (init.c): Add comment explaining formatting conventions.
+
+ * c-exp.y (parse_number): Assign to temporary between the right
+ shifts, to work around a bug in the SCO compiler.
+
+ * Makefile.in (ALLCONFIG, ALLPARAM, ALLDEPFILES, HFILES_NO_SRCDIR):
+ Add various files which were added to GDB recently.
+
+ * xcoffread.c (process_xcoff_symbol): Only change 'V' to 'S' if not
+ within_function.
+
+ * Makefile.in: Add mostlyclean target.
+
+Sat Jan 15 10:20:13 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * Version 4.11.4.
+
+Sat Jan 15 18:27:34 1994 Per Bothner (bothner@kalessin.cygnus.com)
+
+ * main.c (show_commands): Make return type of extern
+ history_get be HIST_ENTRY, rather than struct _hist_entry.
+ (The latter loses with the upcoming merged readline.)
+
+Sat Jan 15 10:20:13 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * minsyms.c (prim_record_minimal_symbol_and_info): Make tempstring
+ const char *, not char *.
+
+ * symtab.h (struct symbol): Make section short, not unsigned short.
+
+ * symtab.c (lookup_symbol): Add comment about QUIT here.
+
+ * utils.c (fputs_unfiltered): Call fputs, not fputs_maybe_filtered.
+
+ * c-exp.y (parse_number): Check for overflow regardless of range
+ checking. Fix overflow check to use unsigned LONGEST, not
+ unsigned int.
+
+ * c-exp.y (parse_number): Make it so that integer constants are
+ builtin_type_long_long if builtin_type_long isn't big enough or if
+ an "LL" suffix is used. Properly handle "UL" or "LU" suffixes.
+
+ * c-typeprint.c (c_type_print_varspec_suffix, case TYPE_CODE_FUNC):
+ Print our "()" first, then recurse for the target type.
+
+Fri Jan 14 21:55:39 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * remote-udi.c (udi_create_inferior): Quote empty execfile argument.
+
+ * gdbserver/low-lynx.c: Include <sys/wait.h> not "/usr/include/wait.h".
+
+Fri Jan 14 14:17:06 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * utils.c (request_quit): Re-establish signal handler regardless
+ of USG.
+
+ * config/mips/xm-irix4.h: Define HAVE_TERMIOS.
+
+Fri Jan 14 21:55:39 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * i960-tdep.c: Include target.h.
+
+Fri Jan 14 17:12:28 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * lynx-nat.c (sys/wait.h): Don't use absolute pathname.
+
+Fri Jan 14 11:06:10 1994 Jim Kingdon (kingdon@deneb.cygnus.com)
+
+ * lynx-nat.c (child_wait): Fix thinkos in struct target_waitstatus
+ changes (status -> ourstatus; declare status, etc.).
+ * config/nm-lynx.h: Fix child_wait prototype and include target.h.
+
+Fri Jan 14 14:17:06 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * Makefile.in (ALLPARAM): Add config/nm-lynx.h.
+
+Fri Jan 14 11:49:44 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * remote-mips.c (mips_request, mips_wait): Correct prototypes.
+
+Fri Jan 14 11:37:17 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * config/i386/xm-linux.h: Define HAVE_TERMIOS.
+
+Fri Jan 14 01:04:36 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * config/alpha/tm-alpha.h (CALL_DUMMY): Improve comment.
+
+Thu Jan 13 10:32:38 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * remote-vx.c (vx_wait): Only call i960_fault_to_signal if I80960
+ is defined. Otherwise just report TARGET_SIGNAL_UNKNOWN.
+
+ * mips-tdep.c (mips_push_arguments): Byteswap struct_addr before
+ writing it.
+
+ Add search to target vector (#if 0'd until after 4.12):
+ * target.h (to_search, target_search): Add.
+ * gdbcore.h, core.c (generic_search): Add.
+ * remote.c (remote_search): Add.
+ * a29k-tdep.c (init_frame_info): Use target_search to find traceback
+ tag.
+
+ * printcmd.c (print_address_symbolic): If set print fast-symbolic-addr
+ is on, call find_pc_function rather than relying just on the minimal
+ symbols (probably only matters for symbol readers which don't put
+ statics in the minimal symbols, but changing this strikes me as
+ not conservative enough).
+ Initialize name_location in all cases.
+ If no symbol and no msymbol, don't print anything symbolic.
+
+ * a29k-tdep.c (push_dummy_frame): Add comment about saving lr0.
+
+Wed Jan 12 20:53:16 1994 John Gilmore (gnu@cygnus.com)
+
+ * printcmd.c (print_address_symbolic): Make it search the
+ symtabs for variables as well as functions. Add `set print
+ fast-symbolic-addr' and default it to fast (the old way).
+ Print line numbers for data items as well as functions.
+
+ * symtab.c (find_addr_symbol): Return the symtab and the symbol
+ address, if a symbol is found (take two more args pointing to
+ where to store these results).
+
+ * symtab.h (find_addr_symbol): Add prototype.
+
+Wed Jan 12 19:32:11 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * objfiles.h: Fix comments to reflect the fact that the phrase
+ "top of stack" always refers to where the pushing and popping takes
+ place, regardless of whether it is at the highest or lowest address.
+
+Wed Jan 12 13:23:37 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * mdebugread.c (parse_symbol): Do not set TYPE_TAG_NAME for
+ compiler generated tag names.
+ * mdebugread.c (parse_type): Handle cross references to qualified
+ aggregate types.
+ * valops.c (value_struct_elt): Improve error message if the
+ address of a method is requested from an object instance.
+ * valops.c (search_struct_method): Make name_matched non-static
+ to get it initialized correctly.
+ * config/i386/nm-i386sco.h (CANNOT_STORE_REGISTER): Define to
+ exclude segment register which are not writable on newer SCO versions.
+
+Wed Jan 12 14:44:45 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * go32-xdep.c: Remove unused function uerror.
+ (sigsetmask): Declare return type. Declare argument (to match the
+ way it is called). Explicitly return 0.
+
+Wed Jan 12 01:44:25 1994 John Gilmore (gnu@cygnus.com)
+
+ * symtab.h (struct symbol, general_symbol_info, minimal_symbol,
+ partial_symbol): Shrink the storage sizes of symbols, by making
+ enums into 1-byte bitfields when compiled __GNUC__, moving all the
+ enums and small ints to the end of each struct to improve
+ alignment, and switching the section number from int to unsigned
+ short.
+
+Wed Jan 12 00:16:26 1994 John Gilmore (gnu@cygnus.com)
+
+ * symtab.c (find_addr_symbol): New routine that will find the nearest
+ symbol associated with an address. It does so by exhaustive
+ search of the symtabs, so it's slow but complete.
+
+Tue Jan 11 23:57:30 1994 John Gilmore (gnu@cygnus.com)
+
+ * coffread.c (read_coff_symtab): Set PC bounds of _globals_ symtab
+ to [0,0] rather than [0, end of first source file]. This avoids
+ problems with other parts of GDB looking for linetables in the
+ _globals_ symtab. Eliminate variables num_object_files and
+ first_object_file_end.
+
+Tue Jan 11 00:53:46 1994 John Gilmore (gnu@cygnus.com)
+
+ * a29k-tdep.c (init_frame_info): Cast null arg to examine_tag.
+ (pop_frame): Restore PC2 and LR0 from dummy frames.
+ (push_dummy_frame): Save PC2 and LR0 into dummy frames.
+ (setup_arbitrary_frame): Handle 3 args and set up real frames.
+ * config/a29k/tm-a29k.h (FRAME_NUM_ARGS): Update comments.
+ (DUMMY_FRAME_RSIZE): Add 2 longwords for PC2 and LR0.
+ (SETUP_ARBITRARY_FRAME): Define.
+
+Tue Jan 11 06:59:10 1994 Jim Kingdon (kingdon@deneb.cygnus.com)
+
+ * infrun.c, config/mips/tm-irix5.h: Remove #if 0'd AT_FUNCTION_START.
+
+Tue Jan 11 14:27:03 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * remote-udi.c (udi_resume): Correct prototype.
+
+Tue Jan 11 11:10:30 1994 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * config/pa/tm-hppa.h (FRAME_FIND_SAVED_REGS): Call
+ hppa_frame_find_saved_regs.
+ * hppa-tdep.c (dig_fp_from_stack): Delete function.
+ (prologue_inst_adjust_sp): New function.
+ (is_branch, inst_saves_gr, inst_saves_fr): New functions.
+ (skip_prologue): Completely rewrite to use unwind information.
+ (hppa_frame_find_saved_regs): Likewise.
+
+Tue Jan 11 06:59:10 1994 Jim Kingdon (kingdon@deneb.cygnus.com)
+
+ * remote-mips.c (mips_wait): Use new function mips_signal_from_protocol
+ to convert a signal number with appropriate bounds checking.
+
+ * remote-mips.c (mips_wait): Fix typos (0x177 -> 0177, 0x377 -> 0377).
+
+Tue Jan 11 00:53:46 1994 John Gilmore (gnu@cygnus.com)
+
+ * stack.c (frame_info): If FRAME_FIND_SAVED_REGS isn't defined,
+ print a newline to end the display anyway.
+
+ * sparc-tdep.c (sparc_pop_frame): Pop the fsr and csr (float and
+ coprocessor status regs) when popping a frame. This fixes
+ float exceptions that occur after calling inferior functions.
+
+ * sparc-nat.c (fetch_inferior_registers, store_inferior_registers):
+ Read and write the fsr (float status register) to/from the child
+ process along with the float regs. Remove Peter Schauer's change
+ of May 24 '93, which has higher overhead and doesn't solve the
+ real problem (which was that FSR wasn't being set).
+
+Mon Jan 10 23:16:42 1994 John Gilmore (gnu@cygnus.com)
+
+ * a29k-tdep.c (examine_prologue): Don't worry if the ASGEQ
+ stack overflow check isn't right after the register stack
+ adjustment instruction. Metaware R2.3u compiler moves other
+ things in front of it. This fix isn't perfect but is what's
+ running.
+
+Mon Jan 10 20:08:23 1994 Jim Kingdon (kingdon@deneb.cygnus.com)
+
+ * c-valprint.c (c_val_print): Treat TYPE_CODE_RANGE like TYPE_CODE_INT.
+
+ * config/alpha/alpha-netware.mt: Rename to alpha-nw.mt for 14
+ character filenames.
+ * configure.in: Change accordingly.
+
+Mon Jan 10 15:48:36 1994 Tom Lord (lord@rtl.cygnus.com)
+
+ * m68k-stub.c, sparc-stub.c: removed spurious introduction of
+ _filtered io routines from these two files.
+
+Fri Jan 7 12:42:45 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * config/i386/tm-i386v.h, config/m68k/tm-m68k.h, config/mips/tm-mips.h,
+ config/vax/tm-vax.h (CALL_DUMMY_BREAKPOINT_OFFSET): Define.
+ * mdebugread.c (parse_symbol): Handle enum sh.type produced by
+ DEC c89.
+ * mdebugread.c (add_line): Handle zero linenos produced by DEC c89.
+
+Fri Jan 7 12:55:25 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * utils.c (print_sys_errmsg): Call gdb_flush (gdb_stdout) before
+ printing to gdb_stderr.
+
+ * remote-udi.c (udi_kill): Don't close the connection, just set
+ inferior_pid to zero.
+ (udi_mourn): Call remove_breakpoints.
+
+ * remote-udi.c: Remove obsolete need_artificial_traps comment.
+
+ * i386b-nat.c (sregmap): If sEAX, etc., not defined, use tEAX, etc.
+
+Thu Jan 6 07:17:53 1994 Jim Kingdon (kingdon@deneb.cygnus.com)
+
+ * symtab.c (lookup_symbol): Don't try adding .c to the name.
+
+ * remote-bug.c: At the start of each section, reset srec_frame
+ back to 160.
+
+ * target.h: Add TARGET_WAITKIND_LOADED and TARGET_WAITKIND_SPURIOUS.
+ * target.c (store_waitstatus): Add CHILD_SPECIAL_WAITSTATUS hook.
+ * infrun.c (wait_for_inferior): Replace SIGTRAP_STOP_AFTER_LOAD with
+ code which looks for those two waitkinds. Use switch statement.
+ * config/rs6000/tm-rs6000.h: Replace SIGTRAP_STOP_AFTER_LOAD with
+ CHILD_SPECIAL_WAITSTATUS.
+
+ * procfs.c (procfs_wait): Fix argument name to match 4 Jan changes.
+ * Move target_signal_from_host, target_signal_to_host, and
+ store_waitstatus from inftarg.c to target.c. procfs needs them.
+ * target.c: Include "wait.h" and <signal.h>.
+ * target.h, infrun.c (proceed), proceed callers: Pass new code
+ TARGET_SIGNAL_DEFAULT instead of -1. This avoids problems with
+ enums being treated as unsigned and is cleaner.
+ * infrun.c (signals_info): Don't print TARGET_SIGNAL_DEFAULT or
+ TARGET_SIGNAL_0.
+ * infcmd.c (signal_command), infrun.c (signals_info):
+ Don't allow user to specify numeric equivalent of
+ TARGET_SIGNAL_DEFAULT.
+
+Tue Jan 4 15:34:36 1994 Stu Grossman (grossman@cygnus.com)
+
+ * config/alpha/alpha-netware.mt: New target support for Alpha
+ running Netware.
+ * configure.in: Add alpha-*-netware* target.
+
+Tue Jan 4 14:51:35 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * remote-mips.c (mips_wait): Fix ref to TARGET_WAITKIND_STOPPED.
+
+Tue Jan 4 09:47:14 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * target.h: Add enum target_waitkind, enum target_signal, and
+ struct target_waitstatus. Change status argument to target_wait to
+ be struct target_waitstatus * instead of int *.
+ * target.h, infrun.c, all targets: Change type of signal arguments
+ to resume(), proceed(), and target_resume() from int to enum
+ target_signal.
+ * All targets (*_wait, *_resume): Change accordingly.
+ * infcmd.c (program_info, signal_command), throughout infrun.c,
+ * fork-child.c, solib.c, hppa-tdep.c, osfsolib.c: Use this stuff.
+ * convex-xdep.c, convex-tdep.c: Add FIXME's (getting the Convex
+ signal code stuff right with the new signals would be non-trivial).
+ * inferior.h (stop_signal): Make it enum target_signal not int.
+ * target.c, target.h (target_signal_to_string, target_signal_to_name,
+ target_signal_from_name): New functions.
+ * inftarg.c, target.h (target_signal_to_host, target_signal_from_host,
+ store_waitstatus): New functions.
+ * procfs.c (procfs_notice_signals): Use them.
+ * i960-tdep.c (i960_fault_to_signal): New function, to replace
+ print_fault.
+ * config/i960/tm-i960.h: Don't define PRINT_RANDOM_SIGNAL.
+
+ * objfiles.c (build_objfile_section_table): Don't abort() if
+ objfile->sections is already set.
+
+ * objfiles.c (add_to_objfile_sections): Check SEC_ALLOC not SEC_LOAD
+ to match recent change to exec.c.
+
+ * Version 4.11.3.
+
+ * main.c (print_gdb_version): Change year to 1994.
+
+ * ChangeLog, ChangeLog-93: Split ChangeLog at 1994.
+ * Makefile.in (NONSRC): Add ChangeLog-93.
+
+Mon Jan 3 11:57:29 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabsread.c (read_type): Allow defining several type numbers
+ at once (e.g. "(1,2)=(3,4)="...).
+
+ * stabsread.c (read_enum_type): Use TARGET_INT_BIT not sizeof (int).
+
+ * breakpoint.c (frame_in_dummy): Check PC as well as frame.
+
+Mon Jan 3 02:47:03 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * mdebugread.c (psymtab_to_symtab_1): Only pass N_STAB symbols
+ to process_one_symbol.
+ * symtab.c (find_pc_psymbol): Search global_psymbols as well to
+ avoid caching a bad endaddr in find_pc_partial_function.
+
+Sun Jan 2 21:41:17 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * config/m68k/tm-sun3.h: Don't define BELIEVE_PCC_PROMOTION.
+
+Sat Jan 1 04:35:23 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * infrun.c (wait_for_inferior): Do not step or step resume past
+ the end of a one-line function we just stepped into.
+
+For older changes see ChangeLog-93
+
+Local Variables:
+mode: indented-text
+left-margin: 8
+fill-column: 74
+version-control: never
+End:
diff --git a/gdb/ChangeLog-95 b/gdb/ChangeLog-95
new file mode 100644
index 00000000000..2265be880ad
--- /dev/null
+++ b/gdb/ChangeLog-95
@@ -0,0 +1,4915 @@
+Fri Dec 29 16:30:58 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ * symfile.c (find_sym_fns): Add PowerMac to xcoff file recognition
+ kludge.
+
+Fri Dec 22 11:05:59 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * configure.in (gdb_host): Add support for DG/UX running on x86 as
+ a host.
+ (all x86 targets and hosts): Add support for pentium-pro machines.
+
+ * configure: Rebuild.
+
+ * config/i386/i386dgux.mh: New file for DG/UX running on x86 host.
+
+Thu Dec 21 19:09:20 1995 Rob Savoye <rob@chinadoll.cygnus.com>
+
+ * remote-array.c (array_wait): Poll the keyboard along with the
+ serial port so users can tpye at the target while their
+ application is running.
+
+Thu Dec 21 11:58:52 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * Makefile.in (ppcbug-rom.o, srec.o): Add dependencies.
+
+ * monitor.c (monitor_debug): Take prefix, and suffix arguments.
+ Print trailing newline after the suffix.
+ (monitor_printf{,_noecho}): Change monitor_debug calls.
+ (monitor_printf): Call monitor_expect instead of trying to do the
+ expect processing locally so that if there is extra junk, it
+ doesn't hang things up.
+ (readchar): If MO_HANDLE_NL is set, handle \r\n pairs and convert
+ them to a single \r. Use monitor_debug to print out byte read.
+
+ * monitor.h (MO_HANDLE_NL): Add new flag.
+
+ * ppcbug-rom.c (ppcbug_ops{1,2}): Split into two ops, one that
+ uses lo 0 to load, and the other that uses lo 1. Set flag
+ MO_HANDLE_NL.
+ (ppcbug_open{0,1}): Clone and split to handle ppcbug_ops{1,2}.
+ (_initialize_ppcbug_rom): Set up both ppcbug_open{0,1}.
+
+Wed Dec 20 10:54:41 1995 Fred Fish <fnf@cygnus.com>
+
+ * defs.h: Delete extraneous whitespace at end of file.
+ * symfile.h: Move #include of demangle.h outside conditional.
+ * objfiles.h (struct objstats, OBJSTAT, OBJSTATS): New struct and
+ macros to hold per-objfile statistics for internal
+ instrumentation.
+ (struct objfile): Add OBJSTATS member, which is optional.
+ * buildsym.h (next_symbol_text_func): Now takes objfile argument.
+ Also update copyright to 1995.
+ * dbxread.c (dbx_next_symbol_text): Now takes objfile argument.
+ (dbx_symfile_init, coffstab_build_psymtabs, elfstab_build_psymtabs,
+ stabsect_build_psymtabs): Accumulate string table size.
+ (dbx_next_symbol_text, read_dbx_symtab, read_ofile_symtab):
+ Accumulate number of stabs symbols read.
+ * dwarfread.c (new_symbol, symthesize_typedef):
+ Accumulate number of full symbols created.
+ * gdbtypes.c (alloc_type): Accumulate number of types.
+ * maint.c (maintenance_print_statistics): New function.
+ * mdebugread.c (mdebug_next_symbol_text): Now takes objfile
+ argument.
+ * minsyms.c (prim_record_minimal_symbol_and_info): Accumulate
+ number of minimal symbols read.
+ * os9kread.c (read_os9k_psymtab): next_symbol_text takes objfile
+ arg.
+ * partial-stab.h: next_symbol_text takes objfile arg.
+ * stabsread.c (error_type, STABS_CONTINUE): Now takes objfile arg
+ and uses it to call next_symbol_text.
+ * symfile.c (add_psymbol_to_list, add_psymbol_addr_to_list):
+ Accumulate number of partial symbols created.
+ * symfile.h (ADD_PSYMBOL_VT_TO_LIST): Accumulate number of partial
+ symbols created.
+ * symmisc.c (print_objfile_statistics): Print the per-objfile
+ internal instrumentation statistics gathered.
+ * xcoffread.c (xcoff_next_symbol_text): Now takes objfile argument.
+
+Fri Dec 15 16:15:55 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * top.c (set_endian_from_file): Use new bfd_big_endian macro.
+
+Fri Dec 15 12:21:10 1995 Raymond Jou <rjou@mexican.cygnus.com>
+
+ * mpw-make.sed: Add quotes to RIncludes reference.
+
+Fri Dec 15 13:18:55 1995 Rob Savoye <rob@darkstar.cygnus.com>
+
+ * remote-array.c: Remove bogus setting of baudrate to 4800. Their
+ hardware has real UARTS now.
+
+Mon Dec 11 18:19:16 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ * configure.in (powerpc-*-macos*): New target configuration.
+ * configure: Update.
+ * config/powerpc/macos.mh, config/powerpc/macos.mt,
+ config/powerpc/nm-macos.h, config/powerpc/tm-macos.h, mac-nat.c:
+ New files, native PowerMac debugging support.
+ * Makefile.in (mac-nat.o): Add build rule.
+ * mpw-config.in (enable_cflags): Add support.
+ (m68k-apple-macos, powerpc-apple-macos): Fix natdepfiles to
+ list object file instead of source file.
+ * mpw-make.sed (@ENABLE_CFLAGS@): Don't edit out, replace with
+ value of variable.
+ (install, install-only): Edit MPW-specific installation into
+ place of Unix shell code.
+ * mac-gdb.r: Fix version resources to use symbolic version strings.
+ (cfrg): New resource, code fragment for PowerMac.
+
+Mon Dec 11 14:13:03 1995 Fred Fish <fnf@amigalib.com>
+
+ * dbxread.c (process_one_symbol): When looking at the next
+ minimal symbol, check for end of the minimal symbol array
+ (symbol with NULL pointer for name) before dereferencing it.
+
+Mon Dec 11 15:56:55 1995 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * eval.c (evaluate_struct_tuple): Fix thinko.
+
+Mon Dec 11 06:52:02 1995 Wilfried Moser <moser@rtl.cygnus.com>
+
+ * ch-typeprint.c (chill_type_print_base): Slightly change of printing
+ of variant structures.
+
+Mon Dec 11 00:36:01 1995 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * valops.c (value_cast): Handle casts to and from TYPE_CODE_CHAR.
+ * ch-exp.c (match_integer_literal): Fix long long support.
+ * gdbtypes.c (get_discrete_bounds): Make TYPE_LENGTH (type) ==
+ sizeof (LONGEST) case work OK.
+
+Fri Dec 8 21:02:24 1995 Fred Fish <fnf@cygnus.com>
+
+ * coffread.c, dbxread.c, dstread.c, objfiles.c, os9kread.c,
+ symfile.c, symtab.c: Use "obstack.h" rather than <obstack.h>.
+
+Wed Dec 6 16:16:18 1995 Stu Grossman (grossman@cirdan.cygnus.com)
+
+ * remote-mips.c (mips_receive_header): Allow mips_syn_garbage to be
+ user-settable (via set syn-garbage-limit). Setting it to -1 makes
+ it unlimited.
+
+Tue Dec 5 18:33:43 1995 Brendan Kehoe <brendan@lisa.cygnus.com>
+
+ * gdbtypes.c (check_stub_method): Make sure we get back a function
+ string in the demangled name before we try to use it.
+
+Tue Dec 5 18:08:29 1995 Stu Grossman (grossman@cygnus.com)
+
+ * monitor.c (monitor_expect_regexp): Make static, add prototype.
+ * (monitor_read_memory_single): Call monitor_expect_regexp with
+ pointer to getmem_resp_delim_pattern, not entire struct.
+
+Tue Dec 5 15:51:25 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ * c-lang.h (c_op_print_tab): Don't declare, some compilers
+ consider illegal if structure not defined, and only used
+ in c-lang.c anyway.
+
+Sun Dec 3 12:31:03 1995 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * eval.c (evaluate_subexp_standard case): Fix typo.
+
+Sun Dec 3 11:59:21 1995 Jeffrey A. Law <law@cygnus.com>
+
+ * ch-exp.c (parse_named_record_element): Avoid aggregrate
+ initializations for automatic variables.
+
+ * hppa-tdep.c (hppa_alignof): Fix typo in last change.
+
+Sat Dec 2 19:32:57 1995 Fred Fish <fnf@cygnus.com>
+
+ * symfile.c (global_psymbols, static_psymbols): Remove, unused.
+
+Sat Dec 2 03:02:21 1995 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * alpha-tdep.c (heuristic_proc_desc): Add heuristic to
+ determine the return address register, needed for OSF/1-3.2C.
+ * config/alpha/tm-alpha.h (T7_REGNUM, T9_REGNUM): Define.
+
+Fri Dec 1 07:23:57 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * ppcbug-rom.c (ppcbug_cmds): Turn on MO_GETMEM_READ_SINGLE
+ because PPCbug displays the memory as characters as well as hex.
+ Fix getmem/setmem commands.
+
+ * srec.c (load_srec): Fix off by one typo in last submission.
+
+ * rs6000-tdep.c (push_arguments): Fix typo.
+
+Thu Nov 30 23:54:17 1995 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * language.c (lang_bool_type), language.h: New function.
+ * language.h (LA_BOOL_TYPE): New macro.
+ * eval.c (evaluate_subexp_standard) Use LA_BOOL_TYPE instead
+ of builtin_type_int where appropriate,
+ * valarith.c (value_subscript): Likewise.
+
+ * valops.c (value_slice): Implement (value) bitstring slices.
+ * valprint.c (val_print): If TYPE_LENGTH is zero, don't automatically
+ print "<incomplete type>" - Chill has zero-length (string) types.
+
+ * gdbtypes.c (check_stub_type): Removed; no longes needed.
+ * ch-exp.c (expect, parse_call): Tweak error messages.
+
+Wed Nov 29 13:35:18 1995 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * scm-valprint.c (scm_isymnames): Remove "#@" prefix.
+ (scm_scmval_print): Do not print "#@" prefix.
+
+ * gdbtypes.h (enum type_code): Added TYPE_CODE_TYPEDEF.
+ (check_typedef): New prototype.
+ (CHECK_TYPEDEF): New macro.
+ (TYPE_DUMMY_RANGE): Removed.
+ * gdbtypes.c (get_discrete_bounds): Fix paren error; make more robust.
+ (create_array_type): Don't force_to_range_type; users of the
+ array are responsible for handling non-range index types.
+ (create_set_type): Likewise.
+ (force_to_range_type): Removed.
+ (check_typedef): New function handles stub types and typedefs.
+ (check_stub_type): Just call check_typedef. (To be removed.)
+ (recursive_dump_type): Handle TYPE_CODE_TYPEDEF.
+ * ch-lang.c (type_lower_upper): Use get_discrete_bounds.
+ (evaluate_subexp_chill): Handle string repetition.
+ Re-arrange to handle EVAL_AVOID_SIDE_EFFECTS better.
+ * ch-typeprint.c (chill_type_print_base): Handle TYPE_CODE_TYPEDEF.
+ Pass show=0 in recursive calls various places.
+ (case TYPE_CODE_ARRAY): Don't require index type to have
+ TYPE_CODE_RANGE.
+ (case TYPE_CODE_RANGE): Don't need to support TYPE_DUMMY_RANGE.
+ * gdbtypes.c, ch-lang.c, ch-typeprint.c (numerous places):
+ Add check_typedef/CHECK_TYPEDEF as needed.
+
+ * ch-exp.y: Replaced by ...
+ * ch-exp.c: New file. Use recursive-descent.
+ Recognize labelled array tuples and powerset ranges.
+ * Makefile.in: Update for no longer using yacc for ch-exp.
+
+ * c-lang.c: Make various functions non-static.
+ * c-lang.h: Add bunches of prototypes.
+ * cp-valprint.c (cp_print_value_fields): Also take address.
+ (cp_print_value): Likewise. Use baselcass_offset.
+ * stabsread.c (current_symbol): New static variable.
+ (type_synonym_name): Remove.
+ (read_type): If copying, make copy be a TYPE_CODE_TYPEDEF.
+ (read_array_type): Don't need to handle undefined element type here.
+ (cleanup_undefined_types): Ditto.
+ (read_range_type): Look for Chill ranges.
+ * valops.c (value_assign): Fix case lval_internalvar - don't try
+ to assign into old value (which might be too small!).
+ (value_coerce_array): No longer need special VALUE_REPEATED handling.
+ (value_arg_coerce): Cleaner array->pointer decay mechanism.
+ (search_struct_field): Use baseclass_offset rather than
+ baseclass_addr.
+ (value_slice): Use get_discrete_bounds.
+ * value.h (COERCE_VARYING_ARRAY): Take type argumnt as well.
+ * values.c (baseclass_offset): Change parameter interface.
+ (baseclass_addr): Removed.
+ * c-typeprint.c, c-valprint.c, ch-valprint.c, values.c, valops.c:
+ Add check_typedef/CHECK_TYPEDEF as needed.
+
+ * alpha-tdep.c, c-exp.y, h8500-tdep.c, f-exp.y, f-valprint.c,
+ findvar.c, hppa-tdep.c, infcmd.c, language.c, printcmd.c,
+ rs6000-tdep.c, symmisc.c, symtab.c, mdebugread.c:
+ Add check_typedef/CHECK_TYPEDEF as needed.
+
+ * f-typeprint.c, valarith.c, valprint.c, typeprint.c, eval.c:
+ Add check_typedef/CHECK_TYPEDEF as needed.
+ * f-typeprint.c: Various cleaning up.
+ * valarith.c (value_subscript): Also subscript bitstrings (for Chill).
+ * typeprint.c (print_type_scalar): Also support TYPE_CODE_RANGE.
+ * eval.c (evaluate_subexp_standard case OP_ARRAY): Implement
+ support for labelled array tuples and ranges in powerset tuples.
+ (init_array_element): New function.
+
+ * top.c (command_line_input): Only strip out an initial #-comment.
+ Looking for internal comments is language-specific (breaks Scheme).
+
+ * expression.h (enum exp_opcode): Add BINOP_RANGE.
+ * expprint.c (dump_expression): Support BINOP_RANGE.
+ * eval.c (evaluate_subexp_standard): Handle BINOP_RANGE (as error).
+ (case MULTI_SUBSCRIPT): Fix broken f77 value->int ad hoc conversion.
+ * ch-lang.c (chill_op_print_tab): Support BINOP_RANGE.
+ (evaluate_subexp_chill): Error on BINOP_COMMA.
+
+ * Makefile.in: Clean up so doc stuff stays in doc sub-dir.
+
+Wed Nov 29 16:39:50 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * monitor.c (monitor_debug): New function to print monitor debug
+ output in printable fashion.
+ (monitor_printf{,_noecho}): Call monitor_debug instead of
+ fputs_unfiltered.
+
+ * srec.c (load_srec): When printing srec debug information, do not
+ print the carriage return directly, instead print \\r followed by
+ a newline.
+
+Tue Nov 28 15:25:28 1995 Doug Evans <dje@canuck.cygnus.com>
+
+ * Makefile.in (target_subdir): Define.
+ (CC_FOR_TARGET, CXX_FOR_TARGET): Use it to find target libraries.
+ * configure.in (X_CFLAGS): Fix typo.
+ (target_subdir): Set to "${target_alias}/" if cross.
+ * configure: Regenerated.
+
+ * dbxread.c (dbx_symfile_read): Set block_address_function_relative
+ for `pe' format files.
+
+Tue Nov 28 11:17:47 1995 Fred Fish <fnf@cygnus.com>
+
+ * magic.h: Renamed to gmagic.h to avoid <magic.h> conflict.
+ * magic.c: Renamed to gmagic.c in sympathy.
+ * eval.c, gmagic.c, config/tm-magic.h:
+ Include "gmagic.h" rather than "magic.h".
+
+Sat Nov 25 02:56:38 1995 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * mdebugread.c (handle_psymbol_enumerators, parse_symbol):
+ Recognize enums from alpha cc -migrate.
+ (upgrade_type): Pass correct fd to parse_symbol when parsing
+ the index type of an array.
+ (parse_procedure, parse_lines, psymtab_to_symtab_1): Handle
+ unsorted procedure descriptors from Irix 5.x and Alpha OSF/1-3.x
+ shared libraries. Use CORE_ADDR instead of `unsigned long' in
+ procedure descriptor address computations.
+
+ * symtab.c (decode_line_1): Prevent accidental strchr match
+ of a null character with the terminating null character of
+ gdb_completer_quote_characters.
+ (cplusplus_hint): Make sure that only a single quote is printed
+ in the hint message.
+
+Fri Nov 24 16:17:01 1995 Jeffrey A Law (law@cygnus.com)
+
+ * top.c (recurse_read_control_structure): Don't make cleanups
+ here. Callers handle that correctly.
+
+Tue Nov 21 15:16:34 1995 Fred Fish <fnf@rtl.cygnus.com>
+
+ * config/m68k/xm-hp300hpux.h: Define MMAP_BASE_ADDRESS and MMAP_INCREMENT.
+ Also force HAVE_MMAP to be defined since autoconf is currently broken
+ for detecting a working mmap under hpux.
+ * config/pa/xm-hppah.h (MMAP_BASE_ADDRESS): Tweak MMAP_BASE_ADDRESS
+ to a better value suggested by Jeffrey A Law (law@cygnus.com).
+
+Tue Nov 21 08:48:58 1995 Fred Fish <fnf@cygnus.com>
+
+ * config/pa/xm-hppah.h: Define MMAP_BASE_ADDRESS and MMAP_INCREMENT.
+ Also force HAVE_MMAP to be defined since autoconf is currently broken
+ for detecting a working mmap under hpux.
+ * objfiles.c (map_to_address): Have gdb print a warning when it
+ is compiled with HAVE_MMAP but without both MMAP_BASE_ADDRESS and
+ MMAP_INCREMENT defined (thus making it appear mmap doesn't work).
+
+Mon Nov 20 14:13:53 1995 Stu Grossman (grossman@cygnus.com)
+
+ * infrun.c (wait_for_inferior): Add support for dynamic function
+ trampolines. These are pieces of code between the caller and the
+ callee that figure out the address of the callee's code at run
+ time. Upon entry, we can't figure out the callee's address, so we
+ set a breakpoint within the trampoline where the address will be
+ known, and continue the target. Once we hit the breakpoint, we
+ break at the callee's address and proceed as usual.
+
+Mon Nov 20 11:12:34 1995 Fred Fish <fnf@cygnus.com>
+
+ * objfiles.c (allocate_objfile): Change warning message about mapped
+ symbol tables so that it is obvious that they are not supported on
+ this particular machine rather than implying they are not supported
+ at all in this version of gdb.
+
+Sun Nov 19 05:20:53 1995 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * irix5-nat.c, osfsolib.c (solib_address): Return the name of the
+ containing solib.
+ * stack.c (print_frame_info): Use minimal symbol only if
+ fi->pc is in a known section.
+
+Sat Nov 18 11:19:35 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu>
+
+ * solib.c (solib_address): Return the name of the containing solib.
+ * solib.h (PC_SOLIB): New macro; define using solib_address.
+ * stack.c (print_frame_info) [PC_SOLIB]: If no function name, try
+ PC_SOLIB on the PC value.
+
+Sat Nov 18 04:09:31 1995 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * annotate.c (annotate_source, annotate_frame_begin): Issue
+ `0x' prefix for the pc value, to remain consistent with previous
+ GDB versions.
+
+ * blockframe.c (find_pc_partial_function), config/pa/tm-hppa.h:
+ Remove Sun shared library transfer hack and
+ INHIBIT_SUNSOLIB_TRANSFER_TABLE_HACK, it is obsoleted by the
+ mst_solib_trampoline minimal symbols.
+
+ * blockframe.c (inside_main_func): Check main_func_*pc against
+ INVALID_ENTRY_*PC, not zero.
+ * symfile.c (init_entry_point_info): Initialize ei.*pc with
+ INVALID_ENTRY_*PC.
+ * mipsread.c (mipscoff_symfile_read): If the entry_file bounds
+ are still unknown after processing the partial symbols, then try
+ to set them from the minimal symbols.
+
+ * infcmd.c (registers_info): Error out if selected_frame is NULL.
+ * stack.c (return_command): Select new current frame silently if
+ not interactive.
+
+ * mipsread.c (read_alphacoff_dynamic_symtab): Ignore additional
+ DT_MIPS_LOCAL_GOTNO and DT_MIPS_GOTSYM entries.
+
+ * irix5-nat.c (solib_create_inferior_hook): Call solib_add only
+ if auto_solib_add_at_startup is nonzero.
+ (_initialize_solib): Add "set auto-solib-add" command.
+ * osfsolib.c (solib_create_inferior_hook): Call solib_add only
+ if auto_solib_add_at_startup is nonzero.
+ (_initialize_solib): Add "set auto-solib-add" command.
+
+Wed Nov 15 17:12:04 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ * utils.c: Don't include sys/ioctl.h etc if MPW is host.
+
+Tue Nov 14 17:16:46 1995 Doug Evans <dje@canuck.cygnus.com>
+
+ * config/arm/tm-arm.h (ADDITIONAL_REGISTER_NAMES): Fix r5.
+ (FRAME_SAVED_PC): Minor clean up.
+
+Tue Nov 14 14:51:05 1995 Stu Grossman (grossman@cygnus.com)
+
+ * monitor.c (monitor_load_srec monitor_make_srec): Move all
+ S-record download code into srec.c.
+ * srec.c srec.h: New files. Contain S-record loading routines
+ formerly in monitor.c.
+ * serial.c serial.h: New routine just like fprintf, but uses
+ serial_t instead of FILE *.
+ * sh-tdep.c (frame_find_saved_regs init_extra_frame_info):
+ Don't add four to saved pc (makes things match manual). Also, fix
+ bug where we didn't get pc from stack frame correctly.
+ * config/sh/tm-sh.h (SAVED_PC_AFTER_CALL): Don't add four to
+ saved pc. Real hardware does this for you.
+ * sh3-rom.c (sh3_load): New routine. Sets up for download then
+ calls generic S-record loader.
+ * config/h8300/h8300.mt, config/h8500/h8500.mt,
+ config/m68k/monitor.mt, config/pa/hppapro.mt, config/sh/sh.mt:
+ Add srec.o to TDEPFILES.
+
+Tue Nov 14 15:57:36 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * ppcbug-rom.c: New file to support the Motorola PPCBUG monitor
+ for PowerPC's.
+
+ * config/powerpc/ppc{,le}-{eabi,sim}.mt (TDEPFILES): Include
+ ppcbug-rom.o, monitor.o, and srec.o
+
+ * config/i386/linux.mt (XDEPFILES): Include ser-tcp.o.
+
+Mon Nov 13 13:12:46 1995 Jeffrey A Law (law@cygnus.com)
+
+ * partial-stab.h: Remove GDB_TARGET_IS_HPPA kludge.
+
+Fri Nov 10 13:08:54 1995 Jeff Law (law@kahlua.cs.utah.edu)
+
+ * terminal.h (HAVE_SGTTY): Fix typo.
+
+Thu Nov 9 17:34:01 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * configure.in (gdb_target): Build in the simulator for all
+ PowerPC eabi targets, not just eabisim, providing
+ --enable-sim-powerpc is used, or the host compiler is GCC.
+
+Thu Nov 9 14:04:05 1995 Raymond Jou (rjou@mexican.cygnus.com)
+
+ * mpw-config.in: Add variable with names of SIOW libraries.
+ * mpw-make.sed: Add an action to build SIOWgdb.
+
+Wed Nov 8 19:25:22 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ * mpw-make.sed: Edit @ENABLE_CFLAGS@ out, mpw-configure can
+ add back in if necessary.
+
+Wed Nov 8 15:59:52 1995 James G. Smith <jsmith@pasanda.cygnus.co.uk>
+
+ * config/mips/vr4300.mt: Added simulator to default VR4300 build.
+
+Tue Nov 7 16:02:25 1995 Stu Grossman (grossman@cygnus.com)
+
+ * remote-mips.c (mips_initialize): Fix brain damage found by
+ Jamie. Basically had case statement in the wrong place...
+ * (mips_load): Remove unnecessary `db tty0' command. It's all
+ handled by mips_initialize now.
+
+Tue Nov 7 12:59:14 1995 Raymond Jou <rjou@mexican.cygnus.com>
+
+ * mac-gdb.r: Added #ifdef Macgdb.
+
+Tue Nov 7 14:59:51 1995 James G. Smith <jsmith@pasanda.cygnus.co.uk>
+
+ * remote-mips.c (mips_initialize): Updated to talk to VR4300 RISQ
+ monitor board.
+
+Mon Nov 6 11:44:11 1995 James G. Smith <jsmith@pasanda.cygnus.co.uk>
+
+ * config/mips/{tm-vr4300.h tm-vr4300el.h} (TARGET_MONITOR_PROMPT):
+ Change into real strings.
+
+ * remote-sim.c (gdbsim_open): Moved sim_open() call to after
+ callback initialisation.
+
+Sun Nov 5 00:07:52 1995 Jason Molenda (crash@phydeaux.cygnus.com)
+
+ * configure.in (AC_CHECK_HEADERS): add stddef.h.
+
+Fri Nov 3 12:30:43 1995 Fred Fish <fnf@cygnus.com>
+
+ * Makefile.in (COMMON_OBS): Use corefile.o rather than core.o
+ * core.c: Rename to corefile.c.
+ * config/pyr/tm-pyr.h, umax-xdep.c, sun386-nat.c, pyr-xdep.c,
+ Makefile.in (SFILES), gould-xdep.c, coredep.c, armtdep.c,
+ arm-xdep.c, altos-xdep.c: Change core.c references to corefile.c.
+
+ From Graham Stoney <greyham@research.canon.oz.au>.
+ * Makefile.in (remote-array.o): Add rule to build.
+ (ALLDEPFILES): Add remote-array.c
+ * remote-array.c (baud_rate): Remove unnecessary declaration.
+ (baudrate): Remove.
+ (array_files_info): Print global baud_rate not baudrate.
+
+Sat Nov 4 10:21:58 1995 Stu Grossman (grossman@cygnus.com)
+
+ * Makefile.in (INTERNAL_CFLAGS): Add ENABLE_CFLAGS.
+ * fork-child.c (fork_inferior): Add call to
+ TARGET_CREATE_INFERIOR_HOOK to allow target specific code to get
+ control just before the new process executes it's first instruction.
+ * remote-mips.c (mips_initialize): Cleanup a bit. Don't try to
+ receive a packet at first. This speeds up initialization a lot.
+ Use TARGET_MONITOR_PROMPT instead of "<IDT>".
+ (common_breakpoint): Use rresponse instead of rerrflg to inspect
+ error code.
+ * symfile.c (syms_from_objfile reread_symbols): Call
+ TARGET_SYMFILE_POSTREAD to allow target specific code to get
+ control after reading new symbols.
+ * target.h: New macros TARGET_SYMFILE_POSTREAD, and
+ TARGET_CREATE_INFERIOR_HOOK. See above for descriptions.
+ * config/mips/{irix5.mh nm-irix5.h}: Delete nm-irix5.h. Make
+ NAT_FILE point directly at ../nm-sysv4.h.
+ * config/mips/{mipsm3.mh nm-m3.h}: Delete nm-m3.h. Make
+ NAT_FILE point directly at ../nm-m3.h.
+ * config/mips/{mipsv4.mh nm-sysv4.h}: Delete nm-sysv4.h. Make
+ NAT_FILE point directly at ../nm-sysv4.h.
+ * config/mips/nm-mips.h: Improve comment at top of file.
+ * config/mips/tm-mips.h (TARGET_MONITOR_PROMPT): Change
+ definition into a proper string.
+
+Wed Nov 1 20:18:08 1995 Fred Fish <fnf@cygnus.com>
+
+ * config/i386/tm-i386.h: New file containing generic i*86 target
+ definitions.
+ (TARGET_BYTE_ORDER): Moved here from tm-i386v.h.
+ (IEEE_FLOAT): Moved here from tm-i386v.h.
+ (START_INFERIOR_TRAPS_EXPECTED): Define default as 2.
+ (FUNCTION_START_OFFSET): Moved here from tm-i386v.h.
+ (SKIP_PROLOGUE): Moved here from tm-i386v.h.
+ (SAVED_PC_AFTER_CALL): Moved here from tm-i386v.h.
+ (INNER_THAN): Moved here from tm-i386v.h.
+ (BREAKPOINT): Moved here from tm-i386v.h.
+ (DECR_PC_AFTER_BREAK): Moved here from tm-i386v.h.
+ (ABOUT_TO_RETURN): Moved here from tm-i386v.h.
+ (REGISTER_SIZE): Moved here from tm-i386v.h.
+ (NUM_REGS): Moved here from tm-i386v.h.
+ (REGISTER_NAMES): Moved here from tm-i386v.h.
+ (EXTRACT_STRUCT_VALUE_ADDRESS): Moved here from tm-i386v.h.
+ (FP_REGNUM): Moved here from tm-i386v.h.
+ (SP_REGNUM): Moved here from tm-i386v.h.
+ (PC_REGNUM): Moved here from tm-i386v.h.
+ (PS_REGNUM): Moved here from tm-i386v.h.
+ (FP0_REGNUM): Moved here from tm-i386aix.h.
+ (FPC_REGNUM): Moved here from tm-sun386.h.
+ (REGISTER_BYTES): Moved here from tm-i386aix.h.
+ (REGISTER_BYTE): Moved here from tm-i386aix.h.
+ (REGISTER_RAW_SIZE): Moved here from tm-i386aix.h.
+ (MAX_REGISTER_RAW_SIZE): Moved here from tm-i386aix.h.
+ (REGISTER_VIRTUAL_SIZE): Moved here from tm-i386aix.h.
+ (MAX_REGISTER_VIRTUAL_SIZE): Moved here from tm-i386aix.h.
+ (EXTRACT_RETURN_VALUE): Moved here from tm-i386aix.h.
+ (STORE_RETURN_VALUE): Moved here from tm-i386aix.h.
+ (REGISTER_VIRTUAL_TYPE): Moved here from tm-i386v.h.
+ (STORE_STRUCT_RETURN): Moved here from tm-i386v.h.
+ (FRAME_CHAIN): Moved here from tm-i386v4.h.
+ (FRAMELESS_FUNCTION_INVOCATION): Moved here from tm-i386v4.h.
+ (FRAME_SAVED_PC): Moved here from tm-i386os9k.h
+ (FRAME_ARGS_ADDRESS): Moved here from tm-i386v.h.
+ (FRAME_LOCALS_ADDRESS): Moved here from tm-i386v.h.
+ (FRAME_NUM_ARGS): Moved here from tm-i386sun.h.
+ (FRAME_ARGS_SKIP): Moved here from tm-i386v.h.
+ (FRAME_FIND_SAVED_REGS): Moved here from tm-i386v.h.
+ (PUSH_DUMMY_FRAME): Moved here from tm-i386v.h.
+ (POP_FRAME): Moved here from tm-i386v.h.
+ (CALL_DUMMY, CALL_DUMMY_LENGTH, CALL_DUMMY_START_OFFSET,
+ CALL_DUMMY_BREAKPOINT_OFFSET, FIX_CALL_DUMMY): Moved here from
+ tm-i386v.h
+ (print_387_control_word, print_387_status_word): Declare prototypes.
+ (struct frame_info, struct frame_saved_regs): Forward decls for
+ prototypes.
+ (SP_ARG0): Moved here from tm-i386v.h.
+
+ * config/i386/tm-i386v.h:
+ (i386/tm-i386.h): Include.
+ (TARGET_BYTE_ORDER): Remove.
+ (IEEE_FLOAT): Remove.
+ (START_INFERIOR_TRAPS_EXPECTED): Undef before redefine to 4.
+ (FUNCTION_START_OFFSET): Remove.
+ (SKIP_PROLOGUE): Remove.
+ (i386_skip_prologue): Remove prototype.
+ (SAVED_PC_AFTER_CALL): Remove.
+ (INNER_THAN): Remove.
+ (BREAKPOINT): Remove.
+ (DECR_PC_AFTER_BREAK): Remove.
+ (ABOUT_TO_RETURN): Remove.
+ (REGISTER_SIZE): Remove.
+ (NUM_REGS): Undef before redefine to 16 (no FP support).
+ (REGISTER_NAMES): Undef before redefine.
+ (FP_REGNUM, SP_REGNUM, PC_REGNUM, PS_REGNUM): Remove.
+ (REGISTER_BYTES): Undef before redefine.
+ (REGISTER_BYTE): Undef before redefine.
+ (REGISTER_RAW_SIZE): Undef before redefine.
+ (REGISTER_VIRTUAL_SIZE): Undef before redefine.
+ (MAX_REGISTER_RAW_SIZE): Undef before redefine.
+ (MAX_REGISTER_VIRTUAL_SIZE): Undef before redefine.
+ (REGISTER_VIRTUAL_TYPE): Undef before redefine.
+ (STORE_STRUCT_RETURN): Undef before redefine.
+ (EXTRACT_RETURN_VALUE): Undef before redefine.
+ (STORE_RETURN_VALUE): Undef before redefine.
+ (EXTRACT_STRUCT_VALUE_ADDRESS): Remove.
+ (FRAME_CHAIN): Undef before redefine.
+ (FRAMELESS_FUNCTION_INVOCATION): Undef before redefine.
+ (FRAME_SAVED_PC): Undef before redefine.
+ (FRAME_ARGS_ADDRESS): Remove.
+ (FRAME_LOCALS_ADDRESS): Remove.
+ (FRAME_NUM_ARGS): Undef before redefine.
+ (FRAME_ARGS_SKIP): Remove.
+ (FRAME_FIND_SAVED_REGS): Remove.
+ (PUSH_DUMMY_FRAME): Remove.
+ (POP_FRAME): Remove.
+ (CALL_DUMMY): Remove.
+ (CALL_DUMMY_LENGTH): Remove.
+ (CALL_DUMMY_START_OFFSET): Remove.
+ (CALL_DUMMY_BREAKPOINT_OFFSET): Remove
+ (FIX_CALL_DUMMY): Remove.
+ (print_387_control_word): Remove.
+ (print_387_status_word): Remove.
+ (SP_ARG0): Remove.
+
+ * config/i386/tm-symmetry.h:
+ (TM_SYMMETRY_H): Enclose file in test for define & define if needed.
+ (START_INFERIOR_TRAPS_EXPECTED): Move to after inclusion of
+ tm-i386v4.h or tm-i386v.h, #undef, and #define back to 2.
+ (DECR_PC_AFTER_BREAK): Move to after inclusion of tm-i386v4.h
+ or tm-i386v.h, #undef, and #define to 0.
+ (MAX_REGISTER_RAW_SIZE): Remove.
+ (FRAME_CHAIN): Remove.
+ (FRAMELESS_FUNCTION_INVOCATION): Remove.
+ (FRAME_SAVED_PC): Remove.
+ (print_387_control_word, print_387_status_word): Remove prototypes.
+
+ * config/i386/tm-ptx.h:
+ (TM_PTX_H): Enclose file in test for define & define if needed.
+ (START_INFERIOR_TRAPS_EXPECTED): Move to after inclusion of
+ tm-i386v4.h or tm-i386v.h, #undef, and #define back to 2.
+ (DECR_PC_AFTER_BREAK): Move to after inclusion of tm-i386v4.h
+ or tm-i386v.h, #undef, and #define to 0.
+ (SDB_REG_TO_REGNUM): Remove obsolete commented out define.
+ (print_387_control_word, print_387_status_word): Remove prototypes.
+
+ * config/i386/tm-linux.h:
+ (TM_LINUX_H): Enclose file in test for define & define if needed.
+ (i386/tm-i386.h): Include instead of tm-i386v.h.
+ (START_INFERIOR_TRAPS_EXPECTED): Remove.
+
+ * config/i386/tm-i386v4.h:
+ (TM_I386V4_H): Enclose file in test for define & define if needed.
+ (i386/tm-i386.h): Include instead of tm-i386v.h.
+ (START_INFERIOR_TRAPS_EXPECTED): Remove.
+ (FRAME_CHAIN): Moved to tm-i386.h.
+ (FRAMELESS_FUNCTION_INVOCATION): Moved to tm-i386.h.
+ (FRAME_SAVED_PC): Remove.
+ (sigtramp_saved_pc): Define as i386v4_sigtramp_saved_pc.
+ (FRAME_NUM_ARGS): Remove.
+
+ * config/i386/tm-i386os9k.h:
+ (TM_I386OS9K_H): Enclose file in test for define & define if needed.
+ (i386/tm-i386.h): Include instead of tm-i386v.h.
+ (START_INFERIOR_TRAPS_EXPECTED): Remove.
+ (NUM_REGS): Undefine before redefining.
+ (FRAME_CHAIN): Remove.
+ (FRAMELESS_FUNCTION_INVOCATION): Remove.
+ (FRAME_SAVED_PC): Move to tm-i386.h.
+
+ * config/i386/tm-i386nw.h:
+ (TM_I386NW_H): Enclose file in test for define & define if needed.
+ (i386/tm-i386.h): Include instead of tm-i386v.h.
+ (START_INFERIOR_TRAPS_EXPECTED): Remove.
+
+ * config/i386/tm-i386bsd.h:
+ (TM_I386BSD_H): Enclose file in test for define & define if needed.
+ (i386/tm-i386.h): Include instead of tm-i386v.h.
+ (START_INFERIOR_TRAPS_EXPECTED): Remove.
+ (FRAMELESS_FUNCTION_INVOCATION): Remove.
+ (FRAME_SAVED_PC): Remove.
+
+ * config/i386/tm-i386aix.h:
+ (i386/tm-i386.h): Include instead of tm-i386v.h.
+ (START_INFERIOR_TRAPS_EXPECTED): Remove.
+ (FP_REGNUM): Remove.
+ (SP_REGNUM): Remove.
+ (PC_REGNUM): Remove.
+ (PS_REGNUM): Remove.
+ (FP0_REGNUM): Moved to tm-i386.h.
+ (NUM_REGS): Remove.
+ (REGISTER_NAMES): Remove.
+ (REGISTER_BYTES): Moved to tm-i386.h.
+ (REGISTER_BYTE): Moved to tm-i386.h.
+ (REGISTER_RAW_SIZE): Moved to tm-i386.h.
+ (MAX_REGISTER_RAW_SIZE): Moved to tm-i386.h.
+ (REGISTER_VIRTUAL_SIZE): Moved to tm-i386.h.
+ (REGISTER_VIRTUAL_TYPE): Removed.
+ (EXTRACT_RETURN_VALUE): Moved to tm-i386.h.
+ (STORE_RETURN_VALUE): Moved to tm-i386.h.
+
+ * config/i386/tm-sun386.h:
+ (TM_SUN386_H): Enclose file in test for define & define if needed.
+ (i386/tm-i386.h): Include.
+ (TARGET_BYTE_ORDER): Remove.
+ (FUNCTION_START_OFFSET): Remove.
+ (SKIP_PROLOGUE): Remove.
+ (SAVED_PC_AFTER_CALL): Remove.
+ (INNER_THAN): Remove.
+ (BREAKPOINT): Remove.
+ (DECR_PC_AFTER_BREAK): Remove.
+ (ABOUT_TO_RETURN): Remove.
+ (REGISTER_SIZE): Remove.
+ (NUM_REGS): Undefine before defining.
+ (REGISTER_NAMES): Undefine before redefining.
+ (REGISTER_BYTES): Undefine before redefining.
+ (REGISTER_BYTE): Undefine before defining.
+ (FP_REGNUM): Undefine before defining.
+ (PC_REGNUM): Undefine before defining.
+ (FPC_REGNUM): Undefine before defining.
+ (REGISTER_RAW_SIZE): Undefine before defining.
+ (FRAME_CHAIN): Undefine before defining.
+ (FRAMELESS_FUNCTION_INVOCATION): Undefine before defining.
+ (FRAME_SAVED_PC): Undefine before defining.
+ (FRAME_NUM_ARGS): Moved to tm-i386.h.
+ (MAX_REGISTER_RAW_SIZE): Remove.
+ (MAX_REGISTER_VIRTUAL_SIZE): Remove.
+ (STORE_STRUCT_RETURN): Remove.
+ (EXTRACT_STRUCT_VALUE_ADDRESS): Remove.
+ (FRAME_ARGS_ADDRESS): Remove.
+ (FRAME_LOCALS_ADDRESS): Remove.
+ (FRAME_NUM_ARGS): Undefine before defining.
+ (FRAME_ARGS_SKIP): Remove.
+ (FRAME_FIND_SAVED_REGS): Remove.
+ (PUSH_DUMMY_FRAME): Remove.
+ (POP_FRAME): Remove.
+ (CALL_DUMMY, CALL_DUMMY_LENGTH, CALL_DUMMY_START_OFFSET): Remove.
+ (struct frame_info, struct frame_saved_regs): Remove forward decls
+ for prototypes.
+
+ * config/i386/tm-i386lynx.h (i386/tm-i386.h): Include instead of
+ tm-i386v.h.
+ * config/i386/tm-i386m3.h (i386/tm-i386.h): Include instead of
+ tm-i386v.h.
+
+ * i386-tdep.c (i386_extract_return_value): Make function visible
+ for all i386 targets, but only assume floating point values returned
+ in floating point registers for I386_AIX_TARGET.
+
+ * i386v-nat.c (i386_register_u_addr): Enable code to locate
+ floating point regs in user struct.
+
+Wed Nov 1 15:32:57 1995 Fred Fish <fnf@cygnus.com>
+
+ * breakpoint.c (breakpoint_re_set): Fix typo in comment.
+ * symtab.c (in_prologue): Document func_start and when it is zero
+ don't call SKIP_PROLOGUE (which typically leads unconditionally to
+ an error when we try to access a prologue at address 0).
+
+Tue Oct 31 13:01:15 1995 Fred Fish <fnf@cygnus.com>
+
+ * elfread.c: Include elf-bfd.h rather than libelf.h.
+
+Tue Oct 31 10:42:42 1995 steve chamberlain <sac@slash.cygnus.com>
+
+ * win32-nat.c (xlate_exception): Treat a stack overflow like a SEGV.
+
+Sun Oct 29 11:22:05 1995 Fred Fish <fnf@cygnus.com>
+
+ * monitor.c: Include gnu-regex.h rather than system regex.h.
+
+Sat Oct 28 23:51:48 1995 steve chamberlain <sac@slash.cygnus.com>
+
+ * defs.h: Test on name __WIN32__ rather than WIN32.
+ * inflow.c (new_tty): Likewise
+ * terminal.h: Likewise.
+ * utils.c (initialize_utils): Likewise.
+ * win32-nat.c (child_create_inferiror): Print error code when failing.
+ * config/i386/win32.mh (XM_CLIBS): Need -lkernel32.
+
+Sat Oct 28 04:52:36 1995 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * symtab.h (enum address_class): Add LOC_UNRESOLVED for
+ a location whose address has to be resolved via the minimal
+ symbol table.
+ * buildsym.c (finish_block), findvar.c (symbol_read_needs_frame,
+ read_var_value), printcmd.c (address_info),
+ symmisc.c (print_symbol, print_partial_symbol): Handle
+ LOC_UNRESOLVED.
+ * stabsread.c (scan_file_globals): Change unresolved LOC_STATIC
+ symbols to LOC_UNRESOLVED. Remove rt_common_objfile lookup
+ kludge, global common symbols are now handled by LOC_UNRESOLVED.
+ (scan_file_globals_1): Move code back to scan_file_globals,
+ delete.
+
+Fri Oct 27 09:54:07 1995 Stu Grossman (grossman@cygnus.com)
+
+ * breakpoint.c (breakpoint_re_set): #ifdef GET_LONGJMP_TARGET
+ around calls to create_longjmp_breakpoint. Why install the
+ breakpoints if we can't find the longjmp target?
+ * infrun.c (wait_for_inferior): Cleanup comments near call test.
+ * remote-mips.c: Fixed a bunch of prototypes to avoid char/int
+ complaint from picky compilers. Add comment to mips_expect.
+ Replace all instances of sr_get_debug with remote_debug.
+ * (mips_readchar): Don't jam init string to monitor.
+ mips_initialize() handles that.
+ * (mips_receive_header): Print better message when we get too
+ much garbage.
+ * (mips_request): Allow caller to pass in buff to allow them to
+ analyze the returned message.
+ * (mips_initialize): Re-do initialization to try sending a BREAK,
+ a ^C, and then a download escape sequence. Cleanup protocol
+ startup. Eliminate sleeps. Clear breakpoints (if using monitor
+ breakpoints). Re-init frame.
+ * (mips_detach): Close down target.
+ * (mips_wait): Handle return status with registers, or breakpoint
+ * stuff.
+ * (mips_kill): Add ^C handling.
+ * (mips_insert_breakpoint mips_remove_breakpoint): Call new
+ breakpoint stuff if enabled.
+ * (calculate_mask remote_mips_set_watchpoint
+ remote_mips_remove_watchpoint remote_mips_stopped_by_watchpoint):
+ Hardware watchpoint/breakpoint stuff.
+ * (common_breakpoint): Common code for new monitor breakpoint commands.
+ * (mips_load): Don't use `prompt'. It's a global variable.
+ * top.c (dont_repeat_command): New command for use in
+ user-defined commands to suppress auto-repeat (by hittin return key).
+ * valops.c: Add start of auto function-call abandonment capability.
+
+Thu Oct 26 22:02:27 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ * mpw-config.in: Add support for PowerMac host, add beginnings
+ of native support.
+ * mpw-make.sed: Disable subdir recursion, edit out useless rule.
+ * mac-xdep.c (Values.h): Don't include.
+ (GestaltEqu.h): Include Gestalt.h instead.
+ (do_mouse_down): Comment out control tracking, needs to be
+ updated to use UPP before will work on PowerMac.
+ * config/xm-mpw.h: New file, all-Mac host support.
+ * config/m68k/xm-mpw.h: Move most definitions into generic Mac
+ support.
+ * config/powerpc/xm-mpw.h: New file, PowerMac host support.
+
+Thu Oct 26 15:21:32 1995 Brendan Kehoe <brendan@lisa.cygnus.com>
+
+ * regex.h: Renamed to gnu-regex.h.
+ * regex.c: Renamed to gnu-regex.c.
+ * Makefile.in (POSSLIBS): Refer to gnu-regex.h and gnu-regex.c.
+ (REGEX, REGEX1): Change to gnu-regex.o instead of regex.o.
+ (regex.o): Renamed to gnu-regex.o; refer to gnu-regex.c.
+ (irix5-nat.o, osfsolib.o, gnu-regex.o, solib.o, source.o, symtab.o):
+ Likewise.
+ * irix5-nat.c, osfsolib.c, gnu-regex.c, solib.c, source.c, symtab.c):
+ Include "gnu-regex.h" instead of "regex.h".
+ * alpha-tdep.c (in_prologue): Rename to alpha_in_prologue, to
+ avoid conflicts with symtab.h.
+
+Tue Oct 24 18:30:18 1995 Jason Molenda (crash@phydeaux.cygnus.com)
+
+ * config/pa/hppahpux.mh: Remove hardcoding of X locations.
+ * Makefile.in: Use X11_CFLAGS, X11_LDFLAGS and X11_LIBS.
+ * configure.in: Link X statically on Solaris, SunOS and HPUX.
+
+Tue Oct 24 12:26:14 1995 Stu Grossman (grossman@cygnus.com)
+
+ * monitor.c (monitor_expect_regexp): Same as monitor_expect, but
+ with the obvious extension.
+ (monitor_read_memory_single): Use regexp for getmem.resp_delim
+ because of parsing ambiguities caused by certain monitors.
+ (monitor_read_memory): Use new regexp stuff to parse
+ getmem.resp_delim.
+ * monitor.h (struct memrw_cmd->resp_delim): Document this as a
+ regexp.
+ * sh3-rom.c: Finish off table. Use new regexp capability for
+ getmem commands.
+
+ * infrun.c (wait_for_inferior): Disable questionable code near
+ the step range test. Replace call detection test with much
+ simpler (and more efficient) test that doesn't require prologue
+ examination (as often).
+ * symtab.c symtab.h (in_prologue): New function that indicates
+ whether or not we are in a function prologue. This uses the
+ symbol table, and then falls back to prologue examination if that
+ fails. It's much more efficient for remote debugging because it
+ avoids examining memory, which is very slow. This is used in
+ wait_for_inferior to determine if we've made a function call that
+ needs to be skipped over (for next/nexti).
+ * mips-tdep.c (after_prologue): New function, returns the PC
+ after the prologue. Uses PDRs and the symbol table.
+ (mips_find_saved_regs): Use in_prologue() to avoid costly
+ prologue examination if possible.
+ (mips_skip_prologue): Use after_prologue() if possible to avoid
+ costly prologue examination.
+
+Mon Oct 23 16:03:33 1995 James G. Smith <jsmith@pasanda.cygnus.co.uk>
+
+ * configure.in (configdirs): Added support for the VR4300 default
+ builds (mips64*vr4300*el-*-elf*, mips64*vr4300*-*-elf*).
+
+ * configure: Regenerated.
+
+ * remote-mips.c (mips_load): Updated the prompt spotting code to
+ make use of the TARGET_MONITOR_PROMPT manifest.
+
+Sat Oct 21 06:11:49 1995 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * alpha-tdep.c, mips-tdep.c (init_extra_frame_info):
+ Do not set saved registers from heuristics for a sigtramp frame.
+
+ * dwarfread.c (enum_type): Determine signedness of enum type
+ from enumerators.
+
+ * mips-tdep.c: Include gdb_string.h, gcc -Wall lint.
+
+ * rs6000-nat.c (xcoff_relocate_core): Fix typo.
+
+ * valops.c (value_repeat): Fix length of memory transfer to
+ match recent allocate_repeat_value change.
+
+Thu Oct 19 19:04:35 1995 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * gdbtypes.c (get_discrete_bounds): Fix typo.
+
+Thu Oct 19 12:15:37 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ * defs.h (SEEK_SET, SEEK_CUR): Add default definitions.
+ * dbxread.c, mdebugread.c, os9kread.c (SEEK_SET, SEEK_CUR):
+ Remove default definitions.
+
+ * Makefile.in (CC-LD): Rename to CC_LD, so MPW xform works.
+ (MMALLOC_SRC): Define.
+ (MMALLOC_CFLAGS): Use.
+ (ser-mac.o): Add rule.
+ * dwarfread.c, somread.c, ultra3-nat.c, xcoffread.c: Replace L_SET
+ with SEEK_SET in all calls to bfd_seek.
+ * scm-tags.h (scm_tags): Remove excess comma.
+
+ * mpw-config.in: Adapt to work with autoconf'ed configury;
+ build config.h, add empty definitions to mk.tmp.
+ (powerpc-apple-macos): Make it work.
+ * mpw-make.sed: New file, sed commands to translate Unix makefile
+ into MPW syntax.
+ * mpw-make.in: Remove.
+ * mac-gdb.r: New file, was macgdb.r, renamed for consistency
+ with other tools, now includes cfrg resource.
+ * macgdb.r: Remove.
+ * config/m68k/xm-mpw.h: Remove most of contents, replace with
+ include of include/mpw/mpw.h.
+
+Tue Oct 17 10:38:53 1995 Jeffrey A Law (law@cygnus.com)
+
+ * hppa-tdep.c (frame_chain): Fix more obscure problems caused
+ by system calls that core dump processes without saving all
+ the register state.
+
+ * config/pa/hppahpux.mt (XDEPFILES): Remove bogus definition.
+ * config/pa/hppapro.mt (XDEPFILES): Likewise.
+
+Tue Oct 17 08:04:26 1995 Fred Fish <fnf@rtl.cygnus.com>
+
+ * NEWS: Fix typo.
+
+Mon Oct 16 18:24:03 1995 Jim Wilson <wilson@chestnut.cygnus.com>
+
+ * config/sh/tm-sh.h (REGISTER_VIRTUAL_TYPE): Return builtin_type_float
+ for FP registers.
+ (REGISTER_NAMES): Add FP register names. Remove ticks, stalls, cycles,
+ insts, plr, and tlr.
+ (NUM_REGS, NUM_REALREGS): Increase from 23 to 41.
+ (FPUL_REGNUM, FP0_REGNUM): New macros.
+
+Mon Oct 16 11:27:06 1995 Stu Grossman (grossman@cygnus.com)
+
+ * remote-mips.c: Add support for speedy (about 10x faster)
+ downloads.
+
+ * remote-array.c: Move baud_rate initialization from
+ _initialize_array to array_open. It was forcing the baud rate of
+ all targets to be 4800 baud! Seems like I've fixed this before...
+ * config/mips/idt.mt (TDEPFILES): Remove remote-array.o. This
+ has *nothing* to do with IDT!!!
+
+
+ * Makefile.in sh3-rom.c config/sh/sh.mt config/sh/tm-sh.h: Add
+ sh3 monitor support.
+ * monitor.c: Cleanup regexp compilation stuff to make it easier
+ to use several regexps.
+ * monitor.h: Get rid of struct rom_cmd_data. It's no longer used.
+ * config/m68k/tm-monitor.h: Don't redefine NUM_REGS here. It just
+ causes GDB to crash.
+
+ * sparcl-tdep.c: Cleanup serial error handling.
+
+Sun Oct 15 16:19:27 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ * rs6000-tdep.c: Don't include a.out.h, improve some formatting.
+
+Fri Oct 13 15:27:49 1995 Stu Grossman (grossman@cygnus.com)
+
+ * dcache.c: Change default value of remotecache to off. It just
+ screws up too many targets.
+ * sparcl-stub.c: Add prototypes to many forward decls.
+ * Create private copies of strlen, strcpy, and memcpy to prevent
+ chaos when user steps into them.
+ * (trap_low handle_exception): Clean up DSU support code
+ (hardware breakpoints). Move lots of stuff from asm-land to
+ C-land (make it much easier to #ifdef if necessary). Also, use
+ trap 255 to get into break mode instead of doing a DSU register
+ write, which may trash the register.
+ * (putpacket): Don't check return value of putDebugChar. It
+ returns void...
+
+Fri Oct 13 14:16:17 1995 steve chamberlain <sac@slash.cygnus.com>
+
+ * remote-sim.h: Always include callback.h.
+ (sim_set_callbacks): New declaration.
+
+Fri Oct 13 10:57:40 1995 Jeffrey A Law (law@cygnus.com)
+
+ * somsolib.c (som_solib_add): Just give a warning if a file
+ mentioned in the dld_list can't be found.
+ * config/pa/tm-hppah.h (FRAME_SAVED_PC_IN_SIGTRAMP): Dig out
+ the PC from the PC queues rather than %r31.
+
+Thu Oct 12 13:36:15 1995 Jeffrey A Law (law@cygnus.com)
+
+ * corelow.c (core_open): Don't update the to_sections and
+ to_sections_end fields in core_ops here. It's too late.
+ * irix5-nat.c (solib_add): Update the to_sections and
+ to_sections_end fields in core_ops here if needed.
+ * osfsolib.c (solib_add): Likewise.
+ * rs6000-nat.c (xcoff_relocate_core): Likewise.
+ * solib.c (solib_add): Likewise.
+ * somsolib.c (solib_add): Likewise.
+
+Wed Oct 11 17:25:59 1995 Fred Fish <fnf@rtl.cygnus.com>
+
+ * Makefile.in (VERSION): Bump version to 4.15.1
+
+Tue Oct 10 15:26:39 1995 Fred Fish <fnf@cygnus.com>
+
+ * Makefile.in (VERSION): Version 4.15 released.
+ * README: Updated for version 4.15.
+ * NEWS: Updated for 4.15 release.
+
+Tue Oct 10 13:18:50 1995 Fred Fish <fnf@cygnus.com>
+
+ * configure.in: Add AC_PROG_YACC
+ * configure: Regenerate
+ * Makefile.in (BISON): Remove macro definition.
+ (YACC): Set from autoconfig.
+ (FLAGS_TO_PASS): Remove BISON.
+ (TARGET_FLAGS_TO_PASS): Remove BISON.
+
+Tue Oct 10 12:25:11 1995 steve chamberlain <sac@slash.cygnus.com>
+
+ * win32-nat.c (child_create_inferior): Pass argv correctly.
+ * Makefile.in (win32-nat.o): Add dependencies.
+
+Mon Oct 9 14:36:29 1995 steve chamberlain <sac@slash.cygnus.com>
+
+ * NEWS: Add information about win32 and arm code.
+ * win32-nat.c: Renamed from win32.c.
+ * config/i386/win32.mh: Renamed from config/i386/i386win32.mh.
+ * config/i386/win32.mt: Renamed from config/i386/i386win32.mt.
+ * config/i386/tm-win32.h: Renamed from config/i386/tm-i386win32.h.
+ * config/i386/xm-win32.h: Renamed from config/i386/xm-i386win32.h.
+ * configure.in (i[345]86-*-win32): Updated to cope with filename
+ changes.
+ * configure: Regenerated.
+
+Sun Oct 8 18:01:04 1995 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * ch-exp.y (yylex): Also look for '$' following '$'.
+
+Sat Oct 7 22:52:42 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * ch-exp.y (yylex): Fix typo.
+
+Fri Oct 6 11:56:49 1995 Jim Wilson <wilson@chestnut.cygnus.com>
+
+ * remote-sim.c (gdbsim_open): Put callback initializations here.
+ (_initalize_remote_sim): Not here.
+
+Fri Oct 6 17:08:49 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ * top.c (execute_control_command): Use 0/1 instead of BFD's
+ true/false.
+
+Fri Oct 6 14:43:19 1995 Stu Grossman (grossman@cygnus.com)
+
+ * sparcl-stub.c: Include sparclite.h to get access to register
+ fondling macros.
+ * (trap_low): Save and restore FP regs if necessary. Also, clean
+ up save and restore of debug unit regs.
+ * (hard_trap_info): Add more architecturally defined traps.
+ * (set_debug_traps): Only set FP disabled trap if FP is disabled.
+ * (get_in_break_mode): Clean up. Get rid of calls to
+ set_hw_breakpoint_trap(). Also, use write_asi macro.
+ * (handle_exception): Clean up `g' and `G' commands. Add `P'
+ command.
+ * (hw_breakpoint): Why was this here!? It's gone now...
+
+Fri Oct 6 11:56:49 1995 Jim Wilson <wilson@chestnut.cygnus.com>
+
+ * callback.c (fdbad): Fix typo in comment.
+ (os_close, os_isatty, os_lseek, os_read, os_write): Use if
+ statements rather than || to get correct return value.
+ (os_write_stdout): Pass missing first argument to os_write.
+ * remote-sim.c: Include callback.h.
+ (_initialize_remote_sim): Call sim_set_callbacks and then
+ initialize the callbacks.
+
+Thu Oct 5 17:28:09 1995 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * values.c (allocate_repeat_value): Allocate an array type, and
+ a value of that type; use that instead of setting VALUE_REPEATED.
+ * value.h (struct value): Remove fields repetitions and repeated.
+ (VALUE_REPEATED, VALUE_REPETITIONS): Removed, no longer used.
+ * c-valprint.c, ch-valprint.c, eval.c, printcmd.c, valops.c,
+ value.h, values.c: Simplify, since now VALUE_REPEATED is never
+ used.
+ * valprint.c (value_print_array_elemen): Removed never-used
+ function.
+
+Thu Oct 5 15:14:36 1995 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * parse.c (write_dollar_variable): New function.
+
+ * c-exp.y (yylex): Replace code for recognizing '$'
+ pseudo-variables with a call to write_dollar_variable.
+ Simplify grammar correspondingly.
+ * f-exp.y: Likewise.
+ * m2-exp.y: Likewise.
+ * ch-exp.y: Likewise. (Remove function match_dollar_tokens.)
+ * scm-exp.c (scm_lreadr): Call write_dollar_variable to handle '$'.
+
+Thu Oct 5 13:27:30 1995 steve chamberlain <sac@slash.cygnus.com>
+
+ * win32.c: New file; support for debugging on windows NT.
+ * configure.in: (i[345]86-*-win32): New target.
+ * configure: Regnerated.
+ * eval.c (evaluate_subexp_standard): Remove unused name.
+ * serial.c (gdb_string.h): Include.
+ * source.c (value.h): Include.
+ * config/i386/i386win32.mh (XDEPFILES): Add win32.o
+ * config/i386/i386win32.mt: New.
+ * config/i386/tm-i386win32.h: New.
+
+Wed Oct 4 18:41:34 1995 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * expression.h (enum exp_code): Added OP_NAME.
+ * expprint.c (print_subexp): Add OP_NAME support.
+ * parse.c (length_of_subexp, prefixify_subexp): Likewise.
+ * scm-lang.c (scm_unpack, in_eval_c, scm_lookup_name): new function.
+ * scm-lang.h: Declare builtin_type_scm; other minor tweaks.
+ * values.c (unpack_long): If type is SCM, call scm_unpack.
+ * scm-valprint.c (scm_val_print): Use extract_signed_integer,
+ instead unpack_long
+ * scm-lang.c: More Scheme expression parsing from here ...
+ * scm-exp.c: ... to here. New file.
+ Also, provide for gdb to evaluate simple constants and names..
+ * Makefile.in: Note new scm-exp.{c,o}.
+
+Wed Oct 4 17:23:03 1995 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * gdbtypes.c (get_discrete_bounds): New function.
+ (force_to_range_type): Use get_discrete_bounds.
+ * gdbtypes.h (get_discrete_bounds): Add declaration.
+ * valarith.c (value_bit_index): Generalize to use get_discrete_bounds.
+ * ch-valprint.c (chill_val_print): Make (power)sets and bitstring
+ support use get_discrete_bounds and generally be more robust.
+
+Tue Oct 3 16:54:56 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ * remote-nrom.c (nrom_ops): Add value for to_thread_alive,
+ add comments naming slots.
+
+Mon Oct 2 21:45:44 1995 Jeff Law (law@hurl)
+
+ * top.c (build_command_line): Demand arguments for if/while
+ commands.
+
+Mon Oct 2 13:08:01 1995 Jason Molenda (crash@phydeaux.cygnus.com)
+
+ * Makefile.in (X11_CFLAGS): Set only to @X_INCDIR@.
+
+Sat Sep 30 16:13:36 1995 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * scm-lang.c: Moved Scheme value printing code to ...
+ * scm-valprint.c: ... this new file.
+ Also major improvements in support for printing SCM values.
+ * scm-lang.h: New file.
+ * scm-tags.h: New file.
+ * Makefile.in: Note new scm-valprint.{c,o}.
+
+Sat Sep 30 09:35:02 1995 Jason Molenda (crash@phydeaux.cygnus.com)
+
+ * configure.in: X_INCDIR and X_LIBDIR added.
+ * Makefile.in: @X_INCDIR@ and @X_LIBDIR@ added.
+ * configure: Regnerated.
+
+Fri Sep 29 02:10:05 1995 steve chamberlain <sac@slash.cygnus.com>
+
+ * config/arm/tm-arm.h (FRAME_CHAIN, FRAME_CHAIN_VALID):
+ Any pc > LOWESTPC is ok.
+
+ * remote-rdp.c (rdp_init): Take out variable baud rate stuff.
+ (remote_rdp_detatch): Delete.
+ * breakpoint.c (ctype.h): Don't include twice.
+
+ * Makefile.in (remote-rdp.o): Doesn't need remote-rdp.h
+ * callback.c (os_printf_filtered): fix protos.
+ * defs.h (puts_filtered, puts_unfiltered
+ [v|f|]printf_[un]filtered): Make format arg const.
+ * remote-rdp.c (rdp_init): Attept to sync at different
+ baudrates.
+ * utils.c (puts_filtered, puts_unfiltered
+ [v|f|]printf_[un]filtered): Define prototypes with
+ const in the right place.
+
+Thu Sep 28 17:43:39 1995 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * defs.h (enum language): Add language_scm.
+ * expression.h (enum exp_code): Added OP_EXPRSTRING.
+ * scm-lang.c: Preliminary support for Guile /SCM dialect of Scheme.
+ * expprint.c (print_subexp): Add OP_EXPRSTRING support.
+ * parse.c (length_of_subexp, prefixify_subexp): Likewise.
+ * valops.c (find_function_in_inferior): New function.
+ (value_allocate_space_in_inferior): New function.
+ (allocate_space_in_inferior): Redefine using previous function.
+ * Makefile.in (SFILES): Add scm-lang.c.
+ (COMMON_OBS): Add scm-lang.o
+
+Thu Sep 28 14:32:11 1995 steve chamberlain <sac@slash.cygnus.com>
+
+ * callback.[ch]: New files.
+ * remote-rdp.c: Support for the ARM RDP monitor.
+ * Makefile: Update.
+ * arm-tdep.c (arm_othernames): New.
+ (_initialize_arm_tdep): install 'othernames' command.
+ (arm_nullified_insn, shifted_reg_val, arm_get_next_pc): New.
+ * configure.in: Check for termios.h, termio.h and sgtty.h.
+ (i[345]86-*-win32*): New host.
+ * configure: Regenerated.
+ * inflow.c: Clean up inclusions.
+ * main.c (main): Check for WINGDB, not WIN32.
+ * printcmd.c (do_examine): Put QUIT test in loop.
+ * remote-hms.c (e7000_load): Delete.
+ (hms_ops): Point to generic_load instead.
+ * remote-hms.c (hms_ops): Point to generic_load.
+ * remote-sim.c (sim_callback_write_stdout): Becomes
+ gdbsim_write_stdout.
+ (gdbsim_load): Call generic_load.
+ * remote-utils.c (gr_load_image): Delete.
+ * ser-unix.c (terminal.h): Include instead of havig
+ own #if tree.
+ (hardwire_flush_input): Reset input buffer too.
+ * source.c (openp): If WIN32 then open file in binary mode.
+ * terminal.h: Configure IO mechanism using autoconf defines if
+ available and not overriden.
+ * utils.c (quit, pollquit, notice_quit): WIN32 check becomes
+ WINGDB check.
+
+ * config/arm/arm.mt (TDEPFILES): Add remote-rdp.o.
+ * config/arm/tm-arm.h (TARGET_BYTE_ORDER): becomes
+ TARGET_BYTE_ORDER_SELECTABLE.
+ (ADDR_BITS_REMOVE): New.
+ (ORIGINAL_REGISTER_NAMES, ADDITIONAL_REGISTER_NAMES): New.
+ (INST_xx): New.
+ (FRAME_FIND_SAVED_REGS): Pass the right argument.
+ (arm_get_next_pc): Declare.
+
+Wed Sep 27 10:14:36 1995 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * valops.c (search_struct_field): Also allow "else" as a variant
+ name.
+ * eval.c (evaluate_struct_tuple): New function. Used to evaluate
+ structure tuples. Now also handles Chill variant records.
+ (get_label): New function, used by evaluate_struct_tuple.
+ (evaluate_subexp_standard case OP_ARRAY): Use evaluate_struct_tuple.
+ (evaluate_labeled_field_init): Removed.
+
+ * valops.c (search_struct_field): Generalize to work with Chill
+ variant records.
+
+Sat Sep 23 01:22:23 1995 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * mdebugread.c (parse_partial_symbols): Reset includes_used
+ and dependencies_used after finishing the partial symbol table.
+
+ * rs6000-tdep.c (push_dummy_frame): Handle lr_offset of zero
+ correctly.
+
+ * rs6000-nat.c (xcoff_relocate_core): Don't relocate data
+ addresses for the main objfile if DONT_RELOCATE_SYMFILE_OBJFILE
+ is defined.
+ * xcoffread.c: gcc -Wall lint. Remove traceback table reading
+ code. The existing code tried to add parameter information for
+ functions compiled without -g, which cannot be done properly
+ for optimized code and produced misleading parameter displays.
+ (ef_complaint, eb_complaint): Make a local static copy to avoid
+ dependency on coffread.c.
+ (read_xcoff_symtab, process_xcoff_symbol, scan_xcoff_symtab):
+ Enter C_EXT/C_HIDEXT symbols into the minimal symbol table only.
+ (read_xcoff_symtab): Ignore C_STAT section auxiliary entry
+ symbols. Complain about unmatched .ef and .eb symbols instead of
+ segfaulting.
+ (process_xcoff_symbol): Determine value of C_GSYM symbols via
+ the global_sym_chain mechanism in stabsread.c.
+ (xcoff_new_init): Call stabsread_new_init and buildsym_new_init.
+ (init_string_tab): Initialize length field bytes in the strtbl.
+ (scan_xcoff_symtab): Skip symbols that start with `$' or `.$'.
+ Set first_fun_line_offset for symbols with two auxents only.
+
+Wed Sep 20 21:06:35 1995 Jeff Law (law@snake.cs.utah.edu)
+
+ * op50-rom.c (op50n_cmds): Send ".\r" after the interrupt
+ character.
+
+Wed Sep 20 13:12:56 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * Makefile.in (maintainer-clean): New target, synonym for
+ realclean. Add GNU standard maintainer-clean echos.
+ * gdbserver/Makefile.in (maintainer-clean): New target, synonym
+ for realclean.
+ * nlm/Makefile.in (maintainer-clean): Likewise.
+
+Wed Sep 20 08:16:03 1995 steve chamberlain <sac@slash.cygnus.com>
+
+ * defs.h (xmalloc, xrealloc): Delete, they're declared in libiberty.h.
+ (GETENV_PROVIDED, FCLOSE_PROVIDED): New.
+ * doc/gdbint.texinfo (GETENV_PROVIDED, FCLOSE_PROVIDED): Document.
+ * remote-sim.[ch] (sim_callback_write_stdout): New.
+
+Tue Sep 19 15:28:58 1995 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * gdbtypes.c (create_set_type): Set TYPE_LENGTH in bytes, not bits.
+ * valops.c (value_bitstring): TYPE_LENGTH is bytes, not bits.
+
+ * gdbtypes.c (force_to_range_type): Calculate upper limit of
+ TYPE_CODE_CHAR depending on TYPE_LENGTH (instead of just using 255).
+
+Mon Sep 18 01:43:42 1995 Jeff Law (law@snake.cs.utah.edu)
+
+ * somsolib.c (auto_solib_add_at_startup): Delete definition. No
+ longer needed.
+
+Sat Sep 16 13:23:36 1995 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * config/mips/tm-mips.h (UNUSED_REGNUM): Define.
+ * mipsv4-nat.c (supply_gregset): Fill UNUSED_REGNUM register
+ with zero.
+
+Thu Sep 14 17:35:24 1995 Stu Grossman (grossman@cygnus.com)
+
+ * remote-sim.c (gdbsim_create_inferior): Back out change that
+ broke all simulator configurations except the rs6000.
+
+Thu Sep 14 14:44:59 1995 Jeffrey A. Law <law@rtl.cygnus.com>
+
+ * monitor.c (monitor_expect): Discard NULL characters.
+
+Thu Sep 14 14:12:30 1995 Kung Hsu <kung@mexican.cygnus.com>
+
+ * infcmd.c: Add extern declaration for auto_solib_add_at_startup.
+
+Wed Sep 13 13:33:58 1995 Kung Hsu <kung@mexican.cygnus.com>
+
+ * symfile.c: Move global variable auto_solib_add_at_startup from
+ solib.c to symfile.c.
+ * solib.c: ditto.
+ * symfile.h: Add extern declaration of the above mentioned variable.
+ * infcmd.c: Take out extern declaration, since it's in symfile.h.
+
+Thu Sep 14 12:39:35 1995 Stu Grossman (grossman@cygnus.com)
+
+ * coffread.c (coff_symtab_read): Complain about unmatched .ef and
+ .eb symbols instead of segfaulting.
+
+Wed Sep 13 13:33:58 1995 Kung Hsu <kung@mexican.cygnus.com>
+
+ * stabsread.c (read_one_struct_field): Use subfile language instead of
+ global language. Improve efficiency.
+
+Wed Sep 13 08:45:02 1995 Jeff Law (law@fast.cs.utah.edu)
+
+ * somsolib.c (auto_solib_add_at_startup): Define new global variable.
+ (som_solib_create_inferior_hook): Don't add libraries if
+ auto_solib_add_at_startup is zero.
+ (_initialize_som_solib): Add command to toggle
+ auto_solib_add_at_startup.
+
+Tue Sep 12 19:37:24 1995 Jeff Law (law@snake.cs.utah.edu)
+
+ * monitor.c (monitor_make_srec): Fix thinkos in computation
+ of addr_size.
+
+Tue Sep 12 15:46:18 1995 Kung Hsu <kung@mexican.cygnus.com>
+
+ * stabsread.c (read_one_struct_field): Add a patch to handle cfront
+ generated stabs that each field is in full mangled name.
+
+ * stabsread.c: To include language.h and expression.h for the reason
+ above.
+
+ * infcmd.c (attach_command): Add solibs only when
+ auto_solib_add_at_startup is set.
+
+Mon Sep 11 17:22:35 1995 Fred Fish <fnf@cygnus.com>
+
+ * NEWS: Add information about remote target caching.
+
+Sun Sep 10 15:36:21 1995 Fred Fish <fnf@cygnus.com>
+
+ * defs.h: Only include mmalloc.h if NO_MMALLOC is not
+ defined.
+
+Sun Sep 10 10:24:48 1995 Michael Tiemann <tiemann@axon.cygnus.com>
+
+ * tm-ppc-eabi.h (PC_IN_CALL_DUMMY): Redefine this to work with the
+ simulator. FIXME.
+
+ * rs6000-tdep.c (push_dummy_frame): Calculate the correct link
+ register offset from the current frame (don't assume it is always 8).
+ (push_dummy_frame): Add comment about having only 4096 bytes of
+ stack space in the simulator (by default).
+
+ * remote-sim.c (gdbsim_create_inferior): Call
+ `add_text_to_loadinfo' so that gdb can find TOC entries when
+ calling functions in the inferior.
+
+Sun Sep 10 09:00:28 1995 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * sparc-tdep.c (fill_fpregset): Fix incorrect FP_MAX_REGNUM
+ substitution.
+ (supply_fpregset): Use FP_MAX_REGNUM.
+
+Sat Sep 9 08:21:52 1995 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * stabsread.c (read_enum_type): Exit loop for putting pending
+ enum symbols into the enum type correctly if we had no pending
+ symbols on entry to read_enum_type.
+
+Fri Sep 8 12:57:41 1995 Kung Hsu <kung@mexican.cygnus.com>
+
+ * inferior.h: Add extern declaration of inferior_environ.
+ * solib.c (solib_map_sections): To get inferior's env instead of
+ gdb's for LD_LIBRARY_PATH, same for PATH.
+
+ * solib.c (solib_map_sections): Copy full path name into so_list
+ structure so that symbol_file_add can find it.
+
+Tue Sep 5 17:47:53 1995 Doug Evans <dje@canuck.cygnus.com>
+
+ * config/sparc/tm-sp64.h (REGISTER_RAW_SIZE): Lower 32 fp regs
+ have size 4.
+ (REGISTER_VIRTUAL_SIZE): Likewise.
+ (REGISTER_VIRTUAL_TYPE): Lower 32 fp regs have type float.
+ Upper 32 fp regs have type double.
+ * sparc-tdep.c (NUM_SPARC_FPREGS): Replace with
+ (FP_REGISTER_BYTES): this, and update all uses.
+ (FP_MAX_REGNUM): Define if not already.
+ (get_saved_register): Handle new sparc64 fp regs.
+ (sparc_frame_find_saved_regs): Likewise.
+ (sparc_print_register_hook): Only print fp regs < 32 as doubles.
+ Add code to handle long doubles when gdb does.
+ (_initialize_sparc_tdep): Use print_insn_sparc64 if sparc64.
+
+Sat Sep 2 06:41:26 1995 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * configure.in: Explicitly `exit 0' for broken shells.
+ * configure: Rebuilt.
+
+ * symtab.c (list_symbols): Add missing blank after
+ `<function, no debug info>' output.
+
+ * valops.c (value_assign): Handle truncation when assigning
+ to bitfields. Use value_copy to construct the return value
+ from toval.
+ * values.c (value_copy): Copy VALUE_FRAME and VALUE_OPTIMIZED_OUT.
+
+Fri Sep 1 08:25:50 1995 James G. Smith <jsmith@beauty.cygnus.com>
+
+ * configure (mips64*vr4300*-*-elf): Support added.
+ * remote-mips.c (mips_readchar): Change to allow build-time prompt
+ string.
+ * config/mips/tm-mips.h: Added TARGET_MONITOR_PROMPT.
+ * config/mips/{vr4300.mt, vr4300el.mt, tm-vr4300.h,
+ tm-vr4300el.h}: Added.
+
+Thu Aug 31 12:48:04 1995 Jim Wilson <wilson@chestnut.cygnus.com>
+
+ * config/sh/sh.mt (SIM): Add -lm.
+
+Wed Aug 30 18:10:57 1995 Kung Hsu <kung@mexican.cygnus.com>
+
+ * rmote-nindy.c (non_dle, nidy_resume, nindy_wait): Changes to
+ conform to GNU coding standards.
+
+ * solib.c (match_main): Modify to follow GNU coding conventions.
+
+Mon Aug 28 17:07:26 1995 Kung Hsu <kung@lisa.cygnus.com>
+
+ * remote.c (remote_wait): Revert 19 July my change which should be
+ customer specific.
+
+Sat Aug 26 00:26:11 1995 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * mdebugread.c (parse_symbol): Handle sh.value of zero for enums.
+ Determine signedness of enum type from enumerators.
+ (parse_type): Handle btIndirect types, handle fBitfield for
+ some non-member types.
+ (upgrade_type): Use TYPE_FLAG_TARGET_STUB for arrays with
+ unknown length.
+ (cross_ref): Handle stIndirect forward reference to btTypedef.
+
+ * stabsread.c (read_enum_type): Determine signedness of enum
+ type from enumerators.
+
+ * top.c (execute_command): Remove trailing whitespace from
+ command arguments, except for `set' and `complete' commands.
+ (validate_comname): Allow underscores in user defined command
+ names.
+
+ * values.c (modify_field): Change `Value does not fit in %d bits'
+ error to a warning. Exclude sign extension bits of negative field
+ values from fit check.
+
+Fri Aug 25 11:31:29 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * configure.in (powerpc*-*-eabisim*): Only link in the simulator
+ if the target is powerpc{,le}-*-eabisim*, since the simulator
+ needs GCC to build.
+ * config/powerpc/ppc{,le}-sim.mt: Cloned from ppc{,le}-eabi.mt.
+ * config/powerpc/ppc{,le}-eabi.mt: Remove simulator support.
+ * config/powerpc/tm-ppc{,le}-sim.mt: Include tm-ppc{,le}-sim.h.
+
+Wed Aug 23 16:55:35 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * config/powerpc/ppc{,le}-eabi.mt (SIM_OBJS, SIM): Link in the
+ PowerPC simulator.
+
+Tue Aug 22 02:00:47 1995 Jeff Law (law@snake.cs.utah.edu)
+
+ * tm-hppa.h (EXTRACT_RETURN_VALUE): Fix for FP values.
+
+ * tm-hppa.h (STORE_RETURN_VALUE): Fix to work with -msoft-float
+ calling conventions too. Use the TYPE of the return value, not
+ its length to determine if it should also be copied into the
+ floating point registers.
+
+ * tm-hppa.h (PROLOGUE_FIRSTLINE_OVERLAP): Delete. Causes more
+ problems than it fixes.
+ * hppa-tdep.c (skip_prologue): If we exit the main loop without
+ finding all the register saves, retry again without looking for
+ the registers we could not find the first time.
+
+Mon Aug 21 23:39:56 1995 Jeff Law (law@snake.cs.utah.edu)
+
+ * hppa-tdep.c (frame_chain_valid): Handle systems where "$START$"
+ calls "main" directly.
+ (skip_prologue): Always assume arguments were saved into the stack
+ since GCC will do so without setting the magic Args_Saved bit in
+ the unwind descriptor.
+
+Mon Aug 21 11:49:17 1995 Kung Hsu <kung@mexican.cygnus.com>
+
+ * remote-udi.c (udi_wait): Mask off high bits of stop reason.
+ * remote-udi.c (fetch_register): For unfetchable regs, pretend it's
+ done. Fix a bug.
+
+Mon Aug 21 00:45:17 1995 Jeff Law (law@snake.cs.utah.edu)
+
+ * Makefile.in (install): Remove "brokensed" hack, unnecessary now
+ that we're using autoconf.
+ (uninstall): Likewise.
+
+
+Sat Aug 19 01:19:34 1995 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * gdbtypes.c (recursive_dump_type): Add dont_print_type_obstack
+ to inhibit infinite recursion when printing aggregate types.
+
+Fri Aug 18 17:48:55 1995 steve chamberlain <sac@slash.cygnus.com>
+
+ * dcache.c (dcache_write_line): Write dirty lines right.
+
+Fri Aug 18 06:26:56 1995 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * sparc-tdep.c (isbranch): Fix typo which caused wrong
+ target addresses for annulled branches.
+
+Wed Aug 16 21:54:39 1995 Jeff Law (law@snake.cs.utah.edu)
+
+ * config/pa/tm-hppa.h (PROLOGUE_FIRSTLINE_OVERLAP): Define.
+
+Tue Aug 15 07:51:21 1995 steve chamberlain <sac@slash.cygnus.com>
+
+ * remote.c (remote_write_bytes): Chop up large transfers.
+
+Mon Aug 14 17:56:36 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ * gcc.patch: Remove, relevant only to long-ago versions of GCC.
+
+Mon Aug 14 13:43:01 1995 Kung Hsu <kung@mexican.cygnus.com>
+
+ * config/sparc/tm-sparclite.h: Define FRAME_CHAIN_VALID_ALTERNATE.
+ * blockframe.c (inside_main_func): If main func addr range not set,
+ try to set it now.
+
+Sat Aug 12 15:34:54 1995 Jeffrey A. Law <law@rtl.cygnus.com>
+
+ * config/powerpc/xm-aix.h (FIVE_ARG_PTRACE): Define.
+ * config/rs6000/xm-rs6000.h (FIVE_ARG_PTRACE): Likewise.
+
+ * configure.in: Recognize aix4 specially as some aspects
+ of aix4 need different handling than aix3.
+ * configure: Updated.
+ * config/powerpc/{aix4.mh,aix4.mt,tm-ppc-aix4.h}: New files
+ specific to aix4 support on the power pc.
+ * config/powerpc/tm-ppc-aix.h (DONT_RELOCATE_SYMFILE_OBJFILE): Do
+ not defined. The aix4 specific target files will do that.
+ * config/rs6000/{aix4,mh,aix4,mt,tm-rs6000-aix4.h}: New files
+ specific to aix4 support on the rs6000.
+
+ * config/rs6000/tm-rs6000.h (CONVERT_FROM_FUNC_PTR_ADDR): Don't
+ do the conversion if the pointer is not a magic aix function
+ pointer.
+ * rs6000-tdep.c: Include objfiles.h and symtab.h.
+ (is_magic_function_pointer): New function.
+
+ * rs6000-tdep.c (skip_prologue): Refine check for frameless
+ functions. Handle b .+4 emitted by aix4 compilers. Only
+ allow one load of a minimal toc pointer. Handle aix4 compiler's
+ code for alloca.
+
+ * rs6000-tdep.c (find_toc_address): Report an error if no toc was
+ found rather than possibly core dumping.
+
+ * partial-stab.h: Handle extra field generated by the aix4 compiler
+ for enumerations.
+ * stabsread.c (read_enum_type): Likewise.
+
+Sat Aug 12 03:18:04 1995 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * rs6000-tdep.c (extract_return_value): Fix returning of values
+ whose length is less than the register size for big endian targets.
+
+Fri Aug 11 13:04:32 1995 Kung Hsu <kung@mexican.cygnus.com>
+
+ * symtab.c (list_symbols): if break command set breakpoint on
+ matched symbol.
+
+Wed Aug 9 18:59:05 1995 Fred Fish <fnf@cygnus.com>
+
+ * defs.h (strchr, strrchr, strstr, strtok, strerror): Enclose in
+ #ifndefs to protect against previous definitions as macros.
+
+Wed Aug 9 14:51:36 1995 Kung Hsu <kung@mexican.cygnus.com>
+
+ * xcoffread.c (xcoff_symfile_offset): Revert an unwanted change
+ that got in accidentally with Aug 1 change.
+
+Sat Aug 5 09:07:28 1995 steve chamberlain <sac@slash.cygnus.com>
+
+ * remote-hms.c (hms_cmds): Get reg term right.
+ * monitor.c (monitor_fetch_register): If we see
+ a non-hex digit, just stop reading.
+ * remote.c (remote_wait): Change way $O is handled.
+
+Wed Aug 9 11:42:36 1995 Jeffrey A. Law <law@rtl.cygnus.com>
+
+ * configure.in (powerpc-*-aix*): Recognize as a new gdb host
+ and target.
+ (powerpc-*-eabi*): Don't set configdirs.
+ (powerpcle-*-eabi*): Likewise.
+ * configure: Updated.
+ * rs6000-nat.c (vmap_ldinfo): Don't relocate data addresses
+ for the main objfile if DONT_RELOCATE_SYMFILE_OBJFILE is
+ defined.
+ * config/powerpc/{aix.mh,aix.mh}: Host and target makefile fragments
+ for powerpc running aix4.
+ * config/powerpc/{nm-aix.h, tm-ppc-aix.h, xm-aix.h}: Native, target
+ and host include files for powerpc running aix4.
+
+Wed Aug 9 08:11:45 1995 Stan Shebs <shebs@cygnus.com>
+
+ * top.c (target_output_hook): Really make it match defs.h (char *
+ is not the same as unsigned char *).
+
+Tue Aug 8 15:13:05 1995 J.T. Conklin <jtc@rtl.cygnus.com>
+
+ * Makefile.in (CXX_FOR_TARGET): Don't use ${rootme}/../gcc/xgcc
+ unless it is present.
+
+Tue Aug 8 10:50:15 1995 Jeffrey A. Law <law@rtl.cygnus.com>
+
+ * top.c (target_output_hook): Make declaration match the one
+ in defs.h.
+
+ * symfile.c (add_psymbol_to_list): Initialize SYMBOL_SECTION.
+ (add_psymbol_addr_to_list): Likewise.
+ * symfile.h (ADD_PSYMBOL_VT_TO_LIST): Likewise.
+
+Mon Aug 7 15:34:29 1995 steve chamberlain <sac@slash.cygnus.com>
+
+ * top.c (target_output_hook): New definition.
+ * stack.c (gdb_string.h): Include after defs.h
+ * defs.h (target_output_hook): New declaration.
+ * source.c (mod_path): Fix Win32 \ handling.
+
+Sun Aug 6 22:14:25 1995 Jeff Law (law@snake.cs.utah.edu)
+
+ * hppa-tdep.c (frame_saved_pc): Don't try to dig a return pointer
+ out of a long branch stub.
+
+Fri Aug 4 13:37:31 1995 Jeffrey A. Law <law@rtl.cygnus.com>
+
+ * xcoffread.c (process_linenos): Fix typo in last change.
+
+Thu Aug 3 22:01:26 1995 Fred Fish <fnf@rtl.cygnus.com>
+
+ * ch-exp.y (write_lower_upper_value): Add prototype so bison
+ generated parser will insert prototype before first func usage.
+ Bison and byacc order the output sections differently. Also
+ make function static.
+
+Thu Aug 3 10:45:37 1995 Fred Fish <fnf@cygnus.com>
+
+ * Update all FSF addresses except those in COPYING* files.
+
+Thu Aug 3 01:38:45 1995 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * config/alpha/tm-alpha.h (EXTRA_FRAME_INFO): Add pc_reg field.
+ (SKIP_TRAMPOLINE_CODE): Define.
+ * alpha-tdep.c (alpha_frame_saved_pc): Use pc_reg field from
+ frame to find the saved pc register.
+ (alpha_saved_pc_after_call): Skip over shared library trampoline
+ before trying to find the saved pc register.
+ (find_proc_desc): Copy PROC_PC_REG from found proc_desc
+ to heuristic proc_desc.
+ (init_extra_frame_info): Initialize pc_reg field in frame.
+
+Wed Aug 2 18:00:36 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ * configure.in (m68*-est-*): Use monitor target config.
+ * configure: Update.
+ * config/m68k/est.mt, config/m68k/tm-est.h: Delete.
+ * config/m68k/monitor.mt, config/m68k/tm-monitor.h: Fix comments.
+
+Tue Aug 1 22:52:53 1995 Fred Fish <fnf@cygnus.com>
+
+ * Makefile.in (VERSION): Bump to 4.14.2
+
+Tue Aug 1 16:04:36 1995 Kung Hsu <kung@mexican.cygnus.com>
+
+ * xcoffread.c (process_linenos): The value in include file symbol
+ should point to line number table. Currently this value is not
+ set correctly by AIX ld. A fix to get around this bug.
+
+Tue Aug 1 11:44:53 1995 J.T. Conklin <jtc@rtl.cygnus.com>
+
+ * configure.in: Check for working mmap, ansi headers, string.h,
+ strings.h, and memory.h.
+ * configure: Regenerated.
+
+ * gdb_stat.h: New file, "portable" <sys/stat.h>.
+ * gdb_string.h: New file, "portable" <string.h>.
+
+ * altos-xdep.c, arm-tdep.c, arm-xdep.c, convex-tdep.c,
+ convex-xdep.c, coredep.c, cxux-nat.c, dbxread.c, exec.c,
+ gould-xdep.c, hppa-tdep.c, i386aix-nat.c, i386b-nat.c,
+ i386mach-nat.c, i386v-nat.c, infptrace.c, m88k-nat.c, main.c,
+ mdebugread.c, objfiles.c, os9kread.c, procfs.c, pyr-xdep.c,
+ rs6000-nat.c, source.c, standalone.c, stuff.c, sun386-nat.c,
+ symfile.c, symm-nat.c, symm-tdep.c, symtab.c, top.c, ultra3-nat.c,
+ ultra3-xdep.c, umax-xdep.c, xcoffread.c: Include "gdb_stat.h"
+ instead of <sys/stat.h>.
+
+ * alpha-tdep.c, breakpoint.c, buildsym.c, c-typeprint.c,
+ ch-typeprint.c, coffread.c, command.c, core-sol2.c, core-svr4.c,
+ core.c, corelow.c, cp-valprint.c, dbxread.c, dcache.c, demangle.c,
+ dpx2-nat.c, dstread.c, dwarfread.c, elfread.c, environ.c, eval.c,
+ exec.c, f-lang.c, f-typeprint.c, f-valprint.c, findvar.c,
+ fork-child.c, gdbtypes.c, hpread.c, i386-tdep.c, infcmd.c,
+ inflow.c, infptrace.c, infrun.c, irix5-nat.c, language.c,
+ m2-typeprint.c, main.c, mdebugread.c, minsyms.c, mipsread.c,
+ monitor.c, nlmread.c, objfiles.c, os9kread.c, osfsolib.c, parse.c,
+ printcmd.c, procfs.c, regex.c, remote-adapt.c,
+ remote-array.c, remote-bug.c, remote-e7000.c, remote-eb.c,
+ remote-es.c, remote-hms.c, remote-mm.c, remote-os9k.c,
+ remote-pa.c, remote-sim.c, remote-st.c, remote-udi.c,
+ remote-utils.c, remote-vx.c, remote-vx29k.c, remote-vx68.c,
+ remote-vx960.c, remote-vxmips.c, remote-vxsparc.c, remote.c,
+ solib.c, somread.c, source.c, stabsread.c, stack.c, symfile.c,
+ symmisc.c, symtab.c, target.c, top.c, typeprint.c, utils.c,
+ valarith.c, valops.c, valprint.c, values.c, xcoffread.c: Include
+ "gdb_string.h" instead of <string.h>.
+
+ * config/xm-sysv4.h, i386/xm-ptx.h, m68k/xm-sun3os4.h,
+ sparc/xm-sun4os4.h (HAVE_MMAP): Removed.
+
+ * config/xm-lynx.h, config/i386/xm-ptx.h,
+ config/m68k/nm-apollo68b.h, config/m68k/xm-hp300hpux.h,
+ config/mips/xm-irix3.h, config/mips/xm-mips.h,
+ config/mips/xm-news-mips.h, config/mips/xm-riscos.h,
+ config/pa/hppah.h, config/rs6000/xm-rs6000.h,
+ config/sparc/xm-sun4os4.h, config/sparc/xm-sun4sol2.h,
+ config/vax/xm-vaxbsd.h, config/vax/xm-vaxult.h,
+ config/vax/xm-vaxult2.h (MEM_FNS_DECLARED): Removed.
+ * config/mips/xm-irix3.h, config/mips/xm-mips.h,
+ config/pa/xm-hppah.h (memcpy, memset): Removed declarations.
+
+Tue Aug 1 02:08:30 1995 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * mips-tdep.c (mips_extract_return_value): Fix returning of
+ values whose length is less than the register size for big endian
+ targets.
+ * alpha-tdep.c (alpha_extract_return_value,
+ alpha_store_return_value): Use alpha_convert_register_to_*
+ to handle functions returning "float" correctly.
+
+Mon Jul 31 19:12:48 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ * h8500-tdep.c: General linting and cleanup.
+ (opcodes/h8500-opc.h): Don't include.
+ (code_size, data_size): Make static.
+ (frame_locals_address, frame_args_address): Remove.
+ (h8300_pop_frame): Rename to h8500_pop_frame.
+ (big_command, medium_command, compact_command, small_command):
+ Define as regular functions rather than with macro trickery.
+ (tm_print_insn): Set to correct disassembler function.
+ * config/h8500/tm-h8500.h: Minor cleanup, add prototypes.
+ (ABOUT_TO_RETURN): #if 0 out.
+ (FRAME_ARGS_ADDRESS, FRAME_LOCALS_ADDRESS): Use usual define.
+ (GDB_TARGET_IS_H8500): Remove duplicate definition.
+ (regoff): Remove, never used.
+ * config/h8500/h8500.mt (TDEPFILES): Add monitor.o.
+
+Mon Jul 31 14:32:30 1995 J.T. Conklin <jtc@rtl.cygnus.com>
+
+ * configure.in: Check for unistd.h.
+ * configure: Regenerated.
+
+ * command.c, cp-valprint.c, fork-child.c, i386-tdep.c,
+ i386b-nat.c, inflow.c, main.c, maint.c, objfiles.c, solib.c,
+ source.c, stack.c, symfile.c, top.c, utils.c: Include strings.h
+ and/or unistd.h to bring prototypes into scope.
+
+Sun Jul 30 01:40:11 1995 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * rs6000-tdep.c (frame_saved_pc): Check for signal handler caller
+ before trying to determine the start of the function.
+ (skip_prologue): Skip subroutine call which might save the
+ floating point registers only if it is within the first three
+ instructions.
+ Reinstate setting of alloca_reg if setup of a gcc frame pointer
+ is found.
+ (frame_get_cache_fsr): Use new fields in rs6000_framedata.
+
+Sat Jul 29 14:43:35 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ * sparclite: Removed subdirectory. aload and eload are now in
+ utils/sparclite, low-level library is in libgloss.
+ * configure.in (sparclite*): Don't configure sparclite subdir.
+ * configure: Update.
+ * Makefile.in (TARDIRS): Remove, no longer used.
+
+Sat Jul 29 01:45:56 1995 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * procfs.c (unconditionally_kill_inferior): Clear current signal
+ if PROCFS_NEED_CLEAR_CURSIG_FOR_KILL is defined.
+ * config/alpha/nm-osf3.h (PROCFS_NEED_CLEAR_CURSIG_FOR_KILL): Define.
+
+ * alpha-tdep.c: Move sigtramp handling of saved registers from
+ read_next_frame_reg to alpha_find_saved_regs, handle saved
+ floating point registers.
+ * mips-tdep.c: Move sigtramp handling of saved registers from
+ read_next_frame_reg to mips_find_saved_regs, handle saved
+ floating point registers.
+ * config/mips/tm-irix3.h, config/mips/tm-irix5.h,
+ config/mips/tm-mipsv4.h (SIGFRAME_FPREGSAVE_OFF): Define.
+
+ * sparc-tdep.c (sparc_pc_adjust): Fix check for `unimp'
+ instruction to handle functions returning structures with
+ large sizes properly.
+
+Fri Jul 28 11:50:17 1995 steve chamberlain <sac@slash.cygnus.com>
+
+ * configure, configure.in (z8k-*-sim): deleted.
+
+Thu Jul 27 12:49:28 1995 Jeffrey A. Law <law@rtl.cygnus.com>
+
+ * lynx-nat.c (child_wait): Handle threads exiting.
+
+Thu Jul 27 07:47:50 1995 Michael Meissner <meissner@cygnus.com>
+
+ * rs6000-tdep.c (skip_prologue): Don't assume the update stack
+ instruction is the last in the prologue, since xlc stores the lr
+ after the stack update. Make sure offset is correct sign for
+ large frames.
+ (frame_saved_pc): Move test for signal before frameless.
+
+ * config/rs6000/tm-rs6000.h (DEFAULT_LR_SAVE): Define.
+ * config/powerpc/tm-ppc-eabi.h (DEFAULT_LR_SAVE): Redefine.
+
+Thu Jul 27 01:22:08 1995 Jeffrey A. Law <law@rtl.cygnus.com>
+
+ * hppa-tdep.c (hppa_fix_call_dummy): Rewrite code for calling
+ into shared libraries.
+
+Wed Jul 26 23:33:34 1995 Michael Meissner <meissner@cygnus.com>
+
+ * config/rs6000/tm-rs6000.h (rs6000_framedata): Add offsets the
+ gprs, fprs, lr, and cr is stored at.
+ (FRAME_FIND_SAVED_REGS): Use new fields in rs6000_framedata.
+ (function_frame_info): Delete declaration.
+ (SKIP_PROLOGUE): Skip_prologue is now passed a rs6000_framedata
+ structure to fill in.
+ (FRAMELESS_FUNCTION_INVOCATION): Function now longer takes a
+ second argument.
+ (FRAME_SAVED_PC): Call frame_saved_pc.
+
+ * rs6000-tdep.c (skip_prologue): Recognize V.4 prologues as well
+ as AIX style. Fill in rs6000_framedata structure. Remember where
+ the gprs, fprs, cr, and lr are saved.
+ (pop_frame): Use skip_prologue, not function_frame_info, and use
+ new rs6000_framedata fields.
+ (function_frame_info): Function deleted.
+ (frameless_function_invocation): Separate frame_saved_pc support
+ to new function. Recognize V.4 frames.
+ (frame_saved_pc): New function.
+ (frame_get_cache_fsr): Use skip_prologue, not function_frame_info.
+ (frame_initial_stack_address): Ditto.
+
+Wed Jul 26 01:00:37 1995 Jeff Law (law@snake.cs.utah.edu)
+
+ * remote.c: Add documentation for extended protocol operations
+ and for thread_alive change from a couple weeks ago.
+ (extended_remote_ops): Declare and define a new target vector
+ for the extended remote protocol.
+ (extended_remote_restart): New function to restart the remote
+ server & process.
+ (remote_open): Just a stub routine.
+ (extended_remote_open): New function to start a remote session
+ using the extended gdb remote protocol.
+ (remote_open_1): New function containing code common to both
+ remote_open and extended_remote_open.
+ (remote_mourn, extended_remote_mourn, remote_mourn_1): Similarly.
+ (extended_remote_create_inferior): New function for the extended
+ remote target.
+ (initialize_remote): Add the extended_remote_ops target vector.
+ * gdbserver/server.c (main, case '!'): Set extended_protocol.
+ (main, case 'k'): If the extended protocol is in use, kill the
+ inferior then start a new one.
+ (main, case 'R'): New command to restart the remote server and
+ inferior process. Only supported when using the extended
+ protocol.
+ (main, server loop): If the inferior terminates while using the
+ extended protocol then start a new one. If getpkt fails when
+ using the extended protocol then exit.
+
+Tue Jul 25 11:43:44 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ * mdebugread.c (psymtab_to_symtab_1): Relocate encoded stab
+ line numbers using the psymtab's section offsets.
+
+Tue Jul 25 10:43:27 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * config/rs6000/tm-rs6000.h (rs6000_framedata): Rename from
+ aix_framedata. Change all uses.
+ * rs6000-tdep.c: Change all aix_framedata -> rs6000_framedata.
+
+Sat Jul 22 23:44:18 1995 Jeff Law (law@snake.cs.utah.edu)
+
+ * defs.h (ATTR_FORMAT): Disable if ANSI_PROTOTYPES is not defined.
+
+Fri Jul 21 16:50:28 1995 Jeffrey A. Law <law@rtl.cygnus.com>
+
+ * lynx-nat.c (child_thread_alive): New function. Somehow I
+ forgot to check this in with all the other thread_alive changes.
+
+Thu Jul 20 22:22:34 1995 Jeff Law (law@snake.cs.utah.edu)
+
+ * somread.c (som_symtab_read): Add unsatisfied common symbols to
+ the minimal symbol table. All common symbols are "unsatisfied"
+ when -E is passed to the linker.
+
+Thu Jul 20 15:04:57 1995 Fred Fish <fnf@cygnus.com>
+
+ * top.c (show_endian): Cast first arg of printf_unfiltered to
+ correct type of "char *".
+
+Thu Jul 20 14:18:51 1995 Jeffrey A. Law <law@rtl.cygnus.com>
+
+ * lynx-nat.c (child_wait): A thread_id of zero from wait apparently
+ means the process is single threaded, so there's no need to add
+ it to the thread list. Handle case where multi-threaded process
+ reverts back to a single-threaded process.
+
+ * gdbserver/low-hppabsd.c: Remove error declaration.
+ * gdbserver/low-sparc.c: Likewise.
+ * gdbserver/low-sun3.c: Likewise.
+ * gdbserver/server.h: Remove error and fatal declaration.
+ * gdbserver/utils.c (error): Update to be compatable with recent
+ changes in defs.h.
+ (fatal): Likewise.
+
+Wed Jul 19 22:42:43 1995 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * config/m68k/tm-m68kv4.h (DWARF_REG_TO_REGNUM): Define to
+ correctly map floating point registers numbers.
+
+ * dwarfread.c (locval, new_symbol): Handle variables that are
+ optimized out.
+
+ * mdebugread.c: Replace all uses of builtin_type_* with
+ mdebug_type_*. Define and initialize mdebug_type_*.
+
+ * serial.h (serial_close): Add additional argument `really_close'.
+ (SERIAL_CLOSE): Update serial_close call accordingly.
+ (SERIAL_UN_FDOPEN): Use serial_close to handle refcnt properly.
+ * serial.c (serial_close): Handle `really_close'.
+ * serial.h (scb_base): Moved to serial.c, made static.
+
+ * valops.c (value_addr): Don't coerce arrays.
+ (typecmp): Coerce arrays instead of calling value_addr if necessary.
+
+Wed Jul 19 18:19:28 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ From Richard Earnshaw (rearnsha@armltd.co.uk):
+ * infrun.c (wait_for_inferior): Set the convenience variable
+ $_exitcode to the termination code of the inferior.
+ * top.c (quit_command): Accept optional expression to use
+ as parameter to exit().
+
+Wed Jul 19 13:15:32 1995 Kung Hsu <kung@mexican.cygnus.com>
+
+ * remote.c (remote_wait): When getting registers, check endianess and
+ do conversion if necessary.
+
+Tue Jul 18 00:41:31 1995 Jeff Law (law@snake.cs.utah.edu)
+
+ * gdbserver/low-hppabsd.c: New file.
+ * gdbserver/Makefile.in (SFILES): Add low-hppabsd.c.
+ * config/pa/hppabsd.mh (XDEPFILES): Add ser-tcp.o.
+ (GDBSERVER_DEPFILES): Add low-hppabsd.o.
+ * config/pa/hppaosf.mh: Likewise.
+
+Mon Jul 17 21:35:18 1995 Fred Fish <fnf@cygnus.com>
+
+ * dache.c (struct dcache_block): Change data member from unsigned
+ char to char, since everything passed in and out of dcache is char
+ or casted to appropriate type anyway.
+ (dcache_alloc): Move assignment of db out of test and combine
+ separate tests into if-else.
+ (dcache_peek_byte): Change ptr from unsigned char* to char*.
+ (dcache_peek_byte): Remove now unnecessary cast in read_memory call.
+ (dcache_peek): Change cast of incoming data arg.
+ (dcache_poke): Change cast of addr of incoming data arg.
+ (dcache_info): Mask data passed to printf_filtered to lsbyte only.
+ (dcache_info): Change printf_filtered arg from "% 2x" to " %2x".
+ * target.c (debug_to_thread_alive): Change return type to int and
+ return zero, for type compatibility with other *_thread_alive
+ funcs.
+ (cleanup_target): Change cast of ignore function to match type of the
+ to_thread_alive member.
+ * defs.h (error_hook): Add ATTR_NORETURN.
+ * defs.h (NORETURN, ATTR_NORETURN): Switch from volatile to
+ __attribute__ method with gcc 2.7, to avoid gcc 2.6.3 bug.
+ * remote.c (remote_wait): Cast first arg to strtol, strchr, and
+ strncmp to "const char *" from "unsigned char *".
+ (remote_wait): Cast arg to putpkt and strcpy from "unsigned char *"
+ to "char *".
+ (remote_wait): Change printf format for long arg from "%d" to "%ld".
+ (getpkt): Remove unused variable "bp".
+ (remote_fetch_word, remote_store_word): Ifdef out apparently unused
+ functions.
+ * breakpoint.c (watchpoint_check): Removed unused variables
+ "saved_level" and "saved_frame".
+ * valops.c (value_arg_coerce): Add other enum TYPE_CODE_* and
+ default cases to switch for completeness.
+ * infrun.c (wait_for_inferior): Enclose "have_waited" label
+ in #ifdef that matches the one in which it is referenced.
+ * ser-unix.c (hardwire_noflush_set_tty_state): Enclose otherwise
+ unused variable "state" in #ifdef that matches one in which it is
+ referenced.
+ * eval.c (evaluate_subexp_standard): Remove unused variable "var".
+ * eval.c (evaluate_subexp_standard): Remove unused variable
+ "tmp_symbol".
+ * valarith.c (value_subscript): Remove unused variable
+ "lowerbound", which is redeclared in a nested scope prior to use.
+ * printcmd.c (print_frame_nameless_args): Use "%ld" to print long
+ arg, not "%d".
+ * {mem-break.c, remote-pa.c, remote.c, saber.suppress}:
+ Remove unused static var "check_break_insn_size".
+ * buildsym.c (finish_block): Add other enum LOC_* and default
+ cases to switch for completeness.
+ ch-lang.c (type_lower_upper): Removed unused label "retry".
+ Add other enum TYPE_* and default cases to switch for completeness.
+ * f-typeprint.c (f_type_print_args): Ifdef out unused function
+ that may be used someday when Fortran support is complete.
+ * ch-valprint.c (chill_print_type_scalar): Add other enum
+ TYPE_* and default cases to switch for completeness.
+ (chill_val_print): Remove unused local var "high_bound" that
+ is redeclared in a nested scope prior to use.
+ (chill_var_print): Use "%ld" to print long arg, not "%d".
+ * regex.c (re_compile_fastmap, re_match_2): Add remaining enum
+ types and default to switches for completeness.
+ * minsyms.c (lookup_minimal_symbol_text): Delete unused variable
+ "trampoline_symbol".
+ (prim_record_minimal_symbol_and_info): Return NULL rather than
+ trash.
+ * elfread.c (elf_symtab_read): Don't dereference NULL returns from
+ record_minimal_symbol_and_info.
+ * f-lang.c (saved_function_list_end): Ifdef out unused variable
+ that may be used someday.
+ * f-valprint.c (f_val_print): Remove unused local "straddr".
+
+Mon Jul 17 13:08:00 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * stabsread.h (struct stab_section_list): Define.
+ (coffstab_build_psymtabs): Remove staboff and stabsize parameters.
+ Add textaddr, textsize, and stabs parameters.
+ * gdb-stabs.h (struct dbx_symfile_info): Remove text_sect field.
+ Add text_addr and text_size fields.
+ (DBX_TEXT_SECT): Don't define.
+ (DBX_TEXT_ADDR, DBX_TEXT_SIZE): Define.
+ * coffread.c: Include <ctype.h>.
+ (struct coff_symfile_info): Remove stabsect and stabindexsect
+ fields. Add textaddr, textsize, and stabsects fields.
+ (coff_locate_sections): Record the address of the .text section,
+ and total the sizes of all sections with names beginning with
+ ".text". Don't bother to record a .stab.index section (COFF
+ doesn't use them). Make a linked list of all sections with names
+ beginning with ".stab".
+ (coff_symfile_read): Adjust call to coffstab_build_psymtabs for
+ new parameters.
+ * dbxread.c (dbx_symfile_read): Use DBX_TEXT_ADDR and
+ DBX_TEXT_SIZE, rather than getting both from DBX_TEXT_SECT.
+ (dbx_symfile_init): Set DBX_TEXT_ADDR and DBX_TEXT_SIZE, not
+ DBX_TEXT_SECT.
+ (elfstab_build_psymtabs): Likewise.
+ (stabsect_build_psymtabs): Likewise.
+ (symbuf_sections, symbuf_left, symbuf_read): New static variables.
+ (fill_symbuf): If symbuf_sections is not NULL, read symbols from
+ multiple sections.
+ (coffstab_build_psymtabs): Remove staboffset and stabsize
+ parameters. Add textaddr, textsize, and stabsects parameters.
+ Set DBX_TEXT_ADDR and DBX_TEXT_SIZE, not DBX_TEXT_SECT. Handle
+ multiple stabs sections.
+ * os9kread.c (os9k_symfile_read): Use DBX_TEXT_ADDR and
+ DBX_TEXT_SIZE, rather than getting both from DBX_TEXT_SECT.
+ (os9k_symfile_init): Set DBX_TEXT_ADDR and DBX_TEXT_SIZE, not
+ DBX_TEXT_SECT.
+
+ * remote-vx.c (vx_ops, vx_run_ops): Initialize new to_thread_alive
+ field.
+
+Sat Jul 15 01:02:53 1995 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * config/alpha/alpha-osf3.mh, config/alpha/nm-osf3.h: New files
+ for OSF/1-3.x procfs support.
+ * configure.in (alpha-dec-osf): Use them when configuring
+ for OSF/1-3.x.
+ * configure: Updated.
+ * target.c: Include <string.h>.
+
+Fri Jul 14 16:16:56 1995 J.T. Conklin <jtc@rtl.cygnus.com>
+
+ * Makefile.in, configure.in: Use one variable, frags, to hold
+ pathnames of makefile fragments.
+ * configure: regenerated.
+
+Fri Jul 14 09:49:47 1995 Jeff Law (law@snake.cs.utah.edu)
+
+ * procfs.c (procfs_ops): Fix typo in last change.
+
+Thu Jul 13 13:42:38 1995 Jeffrey A. Law <law@rtl.cygnus.com>
+
+ * inftarg.c (child_thread_alive): New function to see if a
+ particular thread is still running.
+ (child_ops): Add child_thread_alive entry.
+ * remote.c (remote_thread_alive): New function to see if a
+ particular thread is still alive.
+ (remote_ops): Add remote_thread_alive.
+ * target.c (dummy_target): Add dummy entry for thread_alive.
+ (cleanup_target): de_fault thread_alive too.
+ (update_current_target): INHERIT thread_alive too.
+ (debug_to_thread_alive): New function.
+ (setup_target_debug): Add debug_to_thread_alive.
+ * target.h (struct target_ops): Add to_thread_alive.
+ (target_thread_alive): Define.
+ * thread.c (info_threads_command): Don't call kill; use
+ target_thread_alive instead.
+ * config/nm-lynx.h (CHILD_THREAD_ALIVE): Define.
+ * gdbserver/low-lynx.c (mythread_alive): New function.
+ (mywait): Don't restart any threads after a new thread notification,
+ let the generic code handle it.
+ * gdbserver/low-sparc.c (mythread_alive): Dummy version.
+ * gdbserver/low-sun3.c (mythread_alive): Likewise.
+ * gdbserver/server.c (main): Handle thread_alive requests.
+ * gdbserver/server.h (mythread_alive): Declare.
+ * corelow.c (core_ops): Add dummy entry for thread_alive.
+ * exec.c (exec_ops): Likewise.
+ * m3-nat.c (m3_ops): Likewise.
+ * monitor.c (monitor_ops): Likewise.
+ * procfs.c (procfs_ops): Likewise.
+ * remote-array.c (array_ops): Likewise.
+ * remote-e7000.c (e7000_ops): Likewise.
+ * remote-es.c (es1800_ops, es1800_child_ops): Likewise.
+ * remote-mips.c (mips_ops): Likewise.
+ * remote-pa.c (remote_hppro_ops): Likewise.
+ * remote-sim.c (gdbsim_ops): Likewise.
+ * sparcl-tdep.c (sparclite_ops): Likewise.
+
+Tue Jul 11 11:15:55 1995 Kung Hsu <kung@rtl.cygnus.com>
+
+ * solib.c: Add _DYNAMIC__MGC base symbol for Mentor Graphics Inc.
+ * solib.c (match_main): New function for checking name of main.
+ * solib.c (solib_add): Not to add if solib match main.
+
+Fri Jul 7 14:41:56 1995 Kung Hsu <kung@rtl.cygnus.com>
+
+ * elfread.c (elf_symtab_read): Fix a bug ignoring compiler
+ generated internal labels ($LM...).
+
+Wed Jul 5 11:38:36 1995 Kung Hsu <kung@rtl.cygnus.com>
+
+ * defs.h: if __GO32__ or WIN32 the directory separating symbol should
+ be '\' not '/'.
+
+ * remote-nindy (nindy_wait): Use infinite timeout reading after
+ esacpe character.
+
+Tue Jul 4 10:30:22 1995 Jeffrey A. Law <law@rtl.cygnus.com>
+
+ * infrun.c (wait_for_inferior): When switching from one thread to
+ another, save infrun's state for the old thread and load infrun's
+ previous state for the new thread.
+ * thread.c (struct thread_info): Add new fields for thread specific
+ state saved/restored in infrun.c.
+ (add_thread): Initialize new fields.
+ (load_infrun_state): New function.
+ (save_infrun_state): New function.
+ * thread.h (load_infrun_state): Provide external decl.
+ (save_infrun_state): Likewise.
+
+ * infrun.c (wait_for_inferior): When we hit a breakpoint for the
+ wrong thread, make sure to write the fixed PC value into the thread
+ that stopped. Restart all threads after single stepping over a
+ breakpoint for a different thread.
+ * breakpoint.c (set_momentary_breakpoint): Make momentary
+ breakpoints thread specific in a multi-threaded program.
+ * lynx-nat.c (child_resume): Add some comments. Correctly
+ choose between the single and multi-threaded step and continue
+ ptrace calls.
+
+Fri Jun 30 16:15:36 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ * config/h8300/h8300.mt: Renamed from h8300hms.mt.
+ * config/h8500/h8500.mt: Renamed from h8500hms.mt.
+ * config/z8k/z8k.mt: Renamed from z8ksim.mt.
+ * configure, configure.in: Update to reflect renamings.
+
+ * remote-sim.c (sim): New command, passes commands to simulator.
+ (simulator_command): New function.
+ (gdbsim_ops): Clean up.
+ * remote-sim.h (sim_do_command): Declare.
+ * sh-tdep.c (memory_size): Remove command.
+
+ * Makefile.in (SIM, SIM_OBS): New variables.
+ (CLIBS, CDEPS): Add value of SIM.
+ (DEPFILES): Add value of SIM_OBS
+
+ * config/arm/arm.mt, config/h8300/h8300.mt, config/h8500/h8500.mt,
+ config/sh/sh.mt, config/sparc/sp64sim.mt, config/w65/w65.mt,
+ config/z8k/z8k.mt: Remove simulator files from TDEPFILES,
+ define in SIM_OBS and SIM.
+ config/sparc/sp64sim.mt (SIMFILES): Remove.
+
+ * remote-z8k.c: Remove, was superseded by remote-sim.c
+ * Makefile.in, mpw-make.in: Remove references to remote-z8k.c.
+
+Sun Jun 25 15:30:43 1995 Stan Shebs <shebs@cygnus.com>
+
+ * remote.c (remote_read_bytes, remote_write_bytes): Second arg
+ should be char *, not unsigned char *.
+ * dcache.h (memxferfunc): Ditto.
+ * monitor.c (monitor_write_memory, monitor_read_memory_single):
+ Ditto.
+ (monitor_make_srec): Let compiler figure size of hextab.
+
+Sat Jun 24 19:27:37 1995 Jeffrey A. Law <law@rtl.cygnus.com>
+
+ * lynx-nat.c (child_wait): Don't restart new threads and loop
+ to the top of child_wait; let the machine independent code in
+ wait_for_inferior deal with new thread notifications.
+
+Fri Jun 23 11:51:58 1995 Kung Hsu <kung@mexican.cygnus.com>
+
+ * remote-nindy (nindy_load): Put in target specific load, it's
+ 20 times faster.
+
+Thu Jun 22 20:21:59 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ * utils.c (error): Move local `args' outside conditional,
+ move local `string1' inside, declare function as void if
+ non-ANSI compiler, dereference error_hook when calling.
+
+ * mac-xdep.c (stdarg.h): Don't include.
+
+Thu Jun 22 13:12:33 1995 Kung Hsu <kung@mexican.cygnus.com>
+
+ * remote-nindy.c (nindy_wait): Change timeout in SERIAL_READCHAR.
+
+Wed Jun 21 13:24:41 1995 Jeff Law (law@snake.cs.utah.edu)
+
+ * hppam3-nat.c: Change HP800_THREAD_STATE to TRACE_FLAVOR and
+ HP800_THREAD_STATE_COUNT to TRACE_FLAVOR_SIZE.
+
+Wed Jun 21 05:57:56 1995 Steve Chamberlain <sac@slash.cygnus.com>
+
+ * monitor.c: Turn on caching.
+ (monitor_printf): If a ^C was sent, don't expect to see its
+ echo.
+ (monitor_open): Enable caching.
+ (monitor_resume, monitor_load): Flush cache.
+ (monitor_xfer_memory): Call cache routine.
+ (monitor_dump_regs): New.
+ (monitor_fetch_registers): If monitor_dump_regs available
+ then use it.
+ (monitor_load): Don't ref exec_bfd if it's NULL.
+ (monitor_load_srec): Use new monitor_make_srec calling convention.
+ (monitor_make_srec): Rewrite to cope with two, three and four byte
+ addresses.
+ * remote-hms.c (hms_cmds): Initialze end-of-command delim.
+ * dcache.h, dcache.h: Rewritten.
+ * remote.c: Reenable caching.
+ (getpkt): Reduce MAX_TRIES to 3.
+ (remote_xfer_memory): Use dcache_xfer_memory.
+ * defs.h (error_hook): New.
+ * top.c (error_hook): New definition.
+ * utils.c (error): Use error_hook if initialized.
+ * sparcl-tdep.c (HAVE_SOCKETS): Don't define if GO32 or WIN32. Use
+ HAVE_SOCKETS in place of #ifndef GO32.
+
+Tue Jun 20 22:17:44 1995 Jeff Law (law@snake.cs.utah.edu)
+
+ * config/pa/tm-hppa.h (PSW_*): Define processor status word masks.
+ (INSTRUCTION_NULLIFIED): Allow specific targets to override.
+ * config/pa/tm-hppao.h (INSTRUCTION_NULLIFIED): Define to work
+ around losing mach kernel behavior.
+
+Tue Jun 20 12:03:36 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ * monitor.c (monitor_wait): Don't use the watchdog timeout
+ if its value is 0.
+ * w89k-rom.c (w89k_open): Define to be static.
+
+
+Sat Jun 17 10:17:16 1995 Jeff Law (law@snake.cs.utah.edu)
+
+ * somsolib.c (som_solib_add): Validate regexp argument.
+ Don't assume the first entry on dld's library list is the main
+ program. Don't load the same library more than once and don't
+ consider the main program a shared library.
+ (som_solib_sharedlibrary_command): New function
+ (_initialize_som_solib): Add "sharedlibrary" command.
+
+Thu Jun 15 14:54:58 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ * array-rom.c: Remove, no longer used.
+
+ * remote-hms.c (hms_open): Make static.
+
+ * mpw-config.in (MacSerial.h): Copy from version in {CIncludes},
+ not {MPW}Interfaces:CIncludes.
+ * ser-mac.c (mac_baud_rate_table): Fix value for 38400 baud.
+
+Wed Jun 14 14:27:07 1995 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * ch-exp.y: Remove lots of unsupported productions and names.
+ Add support for IF-expressions, ORIF, ANDIF, NUM, and ADDR.
+
+Tue Jun 13 21:40:11 1995 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * parser-defs.h (enum precedence): Added PREC_BUILTIN_FUNCTION.
+ * expression.h (enum exp_opcode): Added UNOP_LOWER, UNOP_UPPER,
+ UNUP_LENGTH.
+ * expprint.c (dump_expression): Handle the new exp_opcodes.
+ (print_subexp): Handle PREC_BUILTIN_FUNCTION.
+ (print_simple_m2_func): Removed.
+ (print_subexp): Remove support for Modula2 builtin functions.
+ * m2-lang.c (m2_op_print_tab): Add support for builtin functions.
+ * ch-exp.y: Parse LOWER, UPPER, and LENGTH builtins.
+ (write_lower_upper_value): Convenience function for LOWER and UPPER.
+ (upper_lower_argument, length_argument): Removed non-terminals.
+ * ch-lang.c (chill_op_print_tab): Entries for UPPER, LOWER, LENGTH.
+ (type_lower_upper): New function. Calculate LOWER/UPPER of type.
+ (value_chill_length): New function. Calcalate LENGTH of ARRAY/STRING.
+ (evaluate_subexp_chill): Handle UNOP_LOWER, UNOP_UPPER, UNOP_LENGTH.
+
+Mon Jun 12 12:48:13 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ Windows support bits from Steve Chamberlain <sac@slash.cygnus.com>.
+ * defs.h: Don't declare strchr and friends if WIN32.
+ (DIRNAME_SEPARATOR): Move here from source.c.
+ (SLASH_P, SLASH_CHAR, SLASH_STRING, ROOTED_P): New macros,
+ symbolic definitions for filename bits.
+ * top.c (cd_command): Use these.
+ * source.c (mod_path, openp): Ditto.
+ * terminal.h: Disable termio/sgtty definitions if WIN32.
+ * findvar.c (registers_changed): Call registers_changed_hook
+ if it is defined.
+
+Mon Jun 12 12:22:05 1995 J.T. Conklin <jtc@rtl.cygnus.com>
+
+ * Makefile.in (distclean, realclean): Remove config.cache and
+ config.log.
+
+Mon Jun 12 00:21:59 1995 Jeff Law (law@snake.cs.utah.edu)
+
+ * somsolib.c: Include gdb-stabs.h.
+ (som_solib_section_offsets): Use SECT_OFF_XXX rather than 0, 1,
+ etc. Initialize offsets for RODATA & BSS too.
+
+Sat Jun 10 17:59:11 1995 Jeff Law (law@snake.cs.utah.edu)
+
+ * hppa-tdep.c (frame_chain): Try to compensate for incomplete
+ register information in core files when backtracing.
+
+Fri Jun 9 14:51:38 1995 Stu Grossman (grossman@cygnus.com)
+
+ * remote-nrom.c: Remove everything but download code. More
+ cleanups.
+
+Thu Jun 8 15:06:00 1995 Stu Grossman (grossman@cygnus.com)
+
+ * defs.h maint.c monitor.c remote-mips.c remote.c: Add support
+ for `watchdog' variable. This allows the user to put an upper
+ limit on the amount of time that GDB will wait for the target to
+ return from a step or continue operation. This will primarily be
+ used for the testsuite, where it is difficult to come up with a
+ reasonable timeout for things like function calls, which can take
+ as long as three minutes under some circumstances. If the
+ watchdog timer expires, GDB will generate an error that looks like
+ `Watchdog has expired.', and will detach from the target.
+
+ * remote-mips.c (mips_open): Setup initial frame from target.
+ Print it out so that user is told where the program is stopped
+ when they attach.
+
+ * remote-nrom.c: Loads of cleanups. Use serial code to open
+ network connections. Use expect() to wait for response to
+ download command.
+
+ * ser-tcp.c (tcp_open): Retry connection if we get ECONNREFUSED.
+
+ * serial.c serial.h (serial_open serial_fdopen serial_close):
+ Allow users to open the same device multiple times. They all get
+ to share the same serial_t. This is about the only way to have
+ multiple active targets use the same device (for download and
+ debug).
+
+ * sparcl-tdep.c: Keep #include <unistd.h> away from GO32.
+
+ * target.c: Add `targetdebug' variable. If this is non-zero,
+ then a special target is put at the top of the target stack which
+ will cause all calls through the target vector to have their args
+ and results printed out.
+
+Wed Jun 7 17:40:37 1995 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * ch-exp.y: Handle <primitive_value> "->" <modename>.
+
+Wed Jun 7 17:46:33 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * mem-break.c (LITTLE_BREAKPOINT): If BREAKPOINT and
+ {LITTLE,BIG}_BREAKPOINT are all defined, don't redefine.
+ (BIG_BREAKPOINT): Ditto.
+
+ * config/rs6000/tm-rs6000.h (BREAKPOINT): Define as either
+ BIG_BREAKPOINT or LITTLE_BREAKPOINT depending on the target byte
+ order.
+
+Wed Jun 7 12:41:42 1995 Jeff Law (law@snake.cs.utah.edu)
+
+ * somsolib.c (som_solib_section_offsets): Handle relative pathnames.
+
+ * hppa-tdep.c (frame_saved_pc): Handle backtracing through signal
+ handler in dynamically linked executables.
+
+Tue Jun 6 10:44:25 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ From Andrew Cagney <cagney@highland.com.au>
+ * rs6000-tdep.c (single_step): Handle both little and big endian
+ breakpoints.
+ (gdb_print_insn_powerpc): Deal with disassembling both little and
+ big endian PowerPC systems.
+ (_initialize_rs6000_tdep): Use gdb_print_insn_powerpc to handle
+ disassembly, rather that assuming big endian order.
+
+ * config/rs6000/tm-rs6000.h (BREAKPOINT): Delete.
+ (BIG_BREAKPOINT): Define, big endian breakpoint instruction.
+ (LITTLE_BREAKPOINT): Define, little endian breakpoint instruction.
+
+Sat Jun 3 01:54:56 1995 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * README: Add note about Unixware 2.x.
+
+ * dbxread.c (process_one_symbol): Check for exact symbol name
+ match when fixing up N_GSYM and N_STSYM symbols from Sun acc.
+
+ * valprint.c (value_print_array_elements): Use
+ fprintf_filtered to put out `<repeats %u times>',
+ from schwab@issan.informatik.uni-dortmund.de (Andreas Schwab).
+
+ * value.h (struct value): Change `repetitions' field from
+ `short' to `int' type.
+
+Fri Jun 2 11:17:23 1995 Doug Evans <dje@canuck.cygnus.com>
+
+ * arc-tdep.c (arc_bfd_mach_type): New static global.
+ (codestream_fill): Handle byte order differences.
+ (setup_prologue_scan): Don't read stdarg function's "sub sp,sp,N".
+ (arc_get_frame_setup): Read it here.
+ (arc_frame_saved_pc): And here.
+ (arc_print_insn): New function.
+ (arc_set_cpu_type): Set arc_bfd_mach_type. Don't set tm_print_insn.
+ (_initialize_arc_tdep): Set tm_print_insn to arc_print_insn.
+
+Wed May 31 12:04:01 1995 J.T. Conklin <jtc@rtl.cygnus.com>
+
+ * nlm/{configure.in, Makefile.in}: Converted to use autoconf.
+ * nlm/configure: New file, generated with autoconf 2.3.
+
+ * nlm/configure.in: Use sed instead of awk to get the value of
+ cpufile. Awk is not a utility required by the GNU coding
+ standards. This change also fixes the rigid whitespace
+ requirements that were required for awk.
+
+ * sparclite/aload.c: Use a file descriptor instead of a stdio
+ stream for i/o with target board.
+ Use #error if HAVE_TERMIOS is not defined.
+
+ * sparclite/{Makefile.in, configure.in}: Converted to use
+ autoconf.
+ * sparclite/configure: New file, generated with autoconf 2.3.
+
+Sun May 28 23:10:07 1995 Jeff Law (law@snake.cs.utah.edu)
+
+ * defs.h: Include either varargs.h or stdarg.h (for va_list).
+ Fix stupid thinko in last change ("..." -> "va_list").
+
+ * defs.h (vprintf_filtered declaration): Add PARAMS prototype;
+ gcc-2.5 chokes on format attributes for unprototyped functions.
+ (vfprintf_filtered declaration): Likewise.
+ (vprintf_unfiltered declaration): Likewise.
+ (vfprintf_unfiltered). Likewise.
+
+Sat May 27 23:54:17 1995 J.T. Conklin <jtc@rtl.cygnus.com>
+
+ * configure.in: Use sed instead of awk to get the values of
+ hostfile, targetfile and nativefile. Awk is not a utility
+ required by the GNU coding standards. This change also
+ fixes the rigid whitespace requirements that were required
+ for awk.
+ * configure: regenerated.
+
+Sat May 27 16:24:04 1995 Angela Marie Thomas <angela@cirdan.cygnus.com>
+
+ * sparclite/{Makefile,configure}.in: Add hooks for building with
+ -lsocket & -lnsl for solaris2. Don't build aload/eload for DOS.
+
+Thu May 25 12:46:37 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdbserver/remote-utils.c (prepare_resume_reply): Add FIXME
+ comment regarding signal numbering.
+
+Wed May 24 15:49:47 1995 Steve Chamberlain <sac@slash.cygnus.com>
+
+ * arm-tdep.c (_initialize_arm_tdep): Use print_insn_little_arm
+ now.
+
+ * arm-tdep.c (convert_from_extended, convert_to_extended):
+ New.
+ * coffread.c (enter_linenos): Return if linetab 0.
+ * config/arm/arm.mt (TDEPFILES): Add simulator support.
+ * config/arm/tm-arm.h (FRAME_FIND_SAVED_REGS): Fix prototypes.
+
+Mon May 22 19:37:21 1995 Rob Savoye <rob@darkstar.cygnus.com>
+
+ * config/idt.mt: replace monitor and array-rom with the new
+ remote-array.
+
+Mon May 22 15:38:25 1995 Stu Grossman (grossman@cygnus.com)
+
+ * remote-nindy.c: Install Kung patch for PR 6820. I have no idea
+ what this does...
+
+ * breakpoint.c: Move defaults of watchpoint related macros into
+ target.h.
+ * target.h: Macros from breakpoint.c. Conditionalize based on
+ TARGET_HAS_HARDWARE_WATCHPOINTS.
+ * i386v-nat.c procfs.c: Use TARGET_HAS_HARDWARE_WATCHPOINTS
+ instead of TARGET_CAN_USE_HARDWARE_WATCHPOINT to enable watchpoint
+ code.
+ * config/i386/nm-linux.h, config/mips/nm-irix4.h,
+ config/pa/nm-hppab.h, config/sparc/tm-sparclite.h: #define
+ TARGET_HAS_HARDWARE_WATCHPOINTS to enable watchpoint code.
+
+Mon May 22 06:47:30 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * breakpoint.c, target.h: Move defaults of watchpoint related
+ macros back to breakpoint.c. Required to get GDB compiling
+ on Solaris again.
+
+Fri May 19 14:49:37 1995 J.T. Conklin <jtc@rtl.cygnus.com>
+
+ * defs.h (ATTR_FORMAT): New macro, expands to gcc's format
+ attribute when compiled by gcc.
+ * defs.h, language.h, monitor.h: Changed many function
+ declarations to use ATTR_FORMAT.
+
+ * breakpoint.c (delete_command); source.c (directory_command);
+ top.c (define_command): Changed call to query() that had too
+ many arguments.
+ * printcmd.c (address_info): Changed call to printf_filtered()
+ that had too many arguments.
+
+Fri May 19 09:52:07 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * infrun.c (wait_for_inferior): Move assignments to stop_signal
+ and stop_pc, and STOPPED_BY_WATCHPOINT code, back where they
+ were--after the switch statement on w.kind. You can't read the
+ registers of an inferior which has exited. Use a goto in the
+ STOPPED_BY_WATCHPOINT code.
+ * infrun.c (wait_for_inferior): Reinstate
+ HAVE_STEPPABLE_WATCHPOINT and HAVE_CONTINUABLE_WATCHPOINT code.
+
+Fri May 19 06:15:40 1995 Jim Kingdon <kingdon@deneb.cygnus.com>
+
+ * utils.c, complaints.c, language.c, monitor.c, remote-array.c,
+ remote-mips.c, remote-os9k.c, remote-st.c: Conditionalize use of
+ stdarg rather than varargs on ANSI_PROTOTYPES not __STDC__; it
+ must match the definition of PARAMS.
+
+Thu May 18 15:58:46 1995 J.T. Conklin <jtc@rtl.cygnus.com>
+
+ * utils.c (fprintf_filtered, fprintf_unfiltered, fprintfi_filtered,
+ printf_filtered, printf_unfiltered, printfi_filtered, query, warning,
+ error, fatal, fatal_dump_core): Use stdarg.h macros when compiling
+ with an ANSI compiler.
+ * complaints.c (complain): Likewise.
+ * language.c (type_error, range_error): Likewise.
+ * monitor.c (monitor_printf, monitor_printf_noecho): Likewise.
+ * remote-array.c (printf_monitor, debuglogs): Likewise.
+ * remote-mips.c (mips_error): Likewise.
+ * remote-os9k.c (printf_monitor): Likewise.
+ * remote-st.c (printf_stdebug): Likewise.
+
+ * defs.h, complaints.h, language.h, monitor.h: Add prototypes to
+ match above changes.
+
+ * printcmd.c: Remove uneeded #include <varargs.h>.
+ * remote-e7000.c: Likewise.
+
+ * f-typeprint.c (f_type_print_base): Fix typo found by above
+ changes.
+
+Wed May 17 11:21:32 1995 Jim Kingdon <kingdon@deneb.cygnus.com>
+
+ * Makefile.in (xcoffread.o): Depend on partial-stab.h.
+
+ * xcoffsolib.c (sharedlibrary_command): New command.
+ * xcoffsolib.c (solib_info): Call xcoff_relocate_symtab.
+ * xcoffsolib.c: Miscellaneous cleanups.
+
+ * partial-stab.h: Ignore symbol descriptor '-' (for local
+ variables with negative type numbers) without complaint.
+
+ * rs6000-nat.c (vmap_ldinfo): Use bfd_stat rather than our own
+ local emulation thereof. Remove unused variable ostart.
+
+Wed May 17 15:55:53 1995 J.T. Conklin <jtc@rtl.cygnus.com>
+
+ * Makefile.in (config.status): changed target so that
+ config.status --recheck is executed if configure script changes.
+
+ * monitor.c (monitor_printf): Changed format specification in
+ error message to work with pre-ansi compilers.
+ (monitor_load_srec): reduced length of s-records from 128 to 32
+ bytes so download is more reliable with the rom68k monitor.
+
+ * rom68k-rom.c: Added trailing space to prompt string.
+
+ * config/i386/xm-i386sco.h (HAVE_STRSTR): Removed.
+ * config/i386/xm-go32.h, mswin/xm.h (SYS_SIGLIST_MISSING):
+ Removed.
+ * defs.h, config/{xm-lynx.h, xm-nbsd.h},
+ config/i386/{xm-i386bsd.h, xm-linux.h},
+ config/m68k/xm-hp300bsd.h, config/mips/xm-irix4.h,
+ config/ns32k/xm-ns32km3.h, doc/gdbint.texinfo
+ (PSIGNAL_IN_SIGNAL_H): Removed.
+
+Tue May 16 13:16:06 1995 J.T. Conklin <jtc@rtl.cygnus.com>
+
+ * Makefile.in (Makefile): Added config.status to dependency list.
+
+ * configure.in: Added INIT-CMDS argument to AC_OUTPUT which sets
+ gdb_host_cpu, gdb_target_cpu and nativefile.
+ * configure: regenerated.
+
+Mon May 15 23:50:51 1995 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * mdebugread.c (parse_symbol): Do not relocate stBlock/scText
+ symbols, their value is the displacement from the procedure address.
+ * top.c (init_main): Add missing newlines to help strings for
+ `if' and `while' commands, fix help string for `show commands'.
+
+Mon May 15 18:37:56 1995 Stu Grossman (grossman@cygnus.com)
+
+ * breakpoint.c: Move defaults of watchpoint related macros into
+ target.h. Use BP_TEMPFLAG and BP_HARDWAREFLAG instead of
+ constants.
+ * infrun.c (wait_for_inferior): Enhance comment near
+ STOPPED_BY_WATCHPOINT.
+ * target.h: Macros from breakpoint.c.
+
+Mon May 15 17:11:38 1995 J.T. Conklin <jtc@rtl.cygnus.com>
+
+ * config/i386/{i386sol2.mh, i386v4.mh, ncr3000.mh},
+ config/m68k/m68kv4.mh, config/mips/{irix4.mh, irix5.mh,
+ mipsv4.mh}, config/sparc/sun4so2.mh (INSTALL): Removed, figured
+ out by autoconf.
+ * config/apollo68v.mh (RANLIB): Removed, figured out by autoconf.
+
+ * Makefile.in, configure.in: Converted to use autoconf
+ * aclocal.m4: New file, local autoconf macro definitions.
+ * configure: New file, generated with autoconf 2.3.
+
+Mon May 15 14:46:41 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ * remote.c (remote_kill): Add prototype.
+ * cpu32bug-rom.c (cpu32bug_open): Properly define as static.
+ * config/h8300/h8300hms.mt (TDEPFILES): Add monitor.o.
+
+Mon May 15 12:12:34 1995 Stu Grossman (grossman@cygnus.com)
+
+ * sparclite/salib.c (win_ovf win_unf): Make window size constant
+ into a variable (__WINSIZE) so that it can be controlled via the
+ .h file.
+ * sparclite/sparclite.h: Add SL933 #ifdef to set __WINSIZE to 6
+ for the 933 board.
+
+ * infrun.c: Add #ifdef HP_OS_BUG to all references to
+ trap_expected_after_continue.
+ * (wait_for_inferior): Fix for remote watchpoints. Don't try to
+ insert breakpoints while target is running (this only works on
+ *some* native targets). This may also speed up native watchpoints
+ considerably.
+
+Sat May 13 13:55:04 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * dwarfread.c (struct dwfinfo), dbxread.c (struct symloc),
+ mdebugread.c (struct symloc), hpread.c (struct symloc),
+ xcoffread.c (struct symloc): Fix inaccurate comment introduced
+ 20 Apr 1995.
+
+Sat May 13 13:34:18 1995 Jim Kingdon <kingdon@deneb.cygnus.com>
+
+ * rs6000-tdep.c (find_toc_address): Revise comment.
+ * symfile.c, symfile.h (init_psymbol_list): New function;
+ consolidate duplicated copies from os9kread.c, dbxread.c
+ and dwarfread.c.
+ * defs.h: Declare info_verbose.
+ * xcoffread.c: Extensive changes to support psymtabs.
+
+Fri May 12 13:48:41 1995 Stu Grossman (grossman@andros.cygnus.com)
+
+ * cpu32bug-rom.c remote-est.c rom68k-rom.c: Update line_term element.
+
+Fri May 12 06:39:30 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * partial-stab.h: Expand comments.
+
+Thu May 11 19:01:37 1995 Jeff Law (law@snake.cs.utah.edu)
+
+ * Support debugging using native MACH primitives on hppa*-*-osf*.
+ * configure.in: hppa*-*-osf* != hppa*-*-bsd* anymore.
+ * config/pa/hppaosf.mh: New file.
+ * config/pa/nm-hppao.h: Likewise.
+ * hppam3-nat.c: Likewise.
+ * config/pa/tm-hppao.h (PSW_SS): Define for single-stepping.
+ (MACHINE_CPROC_*_OFFSET): Define.
+ (TRACE_*): Define.
+ (START_INFERIOR_TRAPS_EXPECTED): Delete definition.
+
+Wed May 10 18:59:26 1995 Stu Grossman (grossman@andros.cygnus.com)
+
+ * hppa-tdep.c (read_unwind_info): Cosmetic cleanup.
+ * (unwind_command): Clean it up and make it print things out
+ nicer.
+ * monitor.c: Add ^C handling capability (mostly ripped off from
+ remote.c).
+ * (monitor_printf): Make it check the command echo.
+ * (monitor_printf_noecho): Similar to above, but doesn't check
+ for echo.
+ * (monitor_stop): No longer waits for prompt. That is the job of
+ the caller. This makes things work much better for monitor_wait,
+ which waits for the prompt itself.
+ * (monitor_open): Deal with new monitor_stop semantics. Also,
+ flush input after sending init strings to get rid of junk that may
+ be output. Also, don't always send \r to remote. Use
+ monitor_ops->line_term cuz proper character isn't always \r.
+ * (monitor_fetch_register): Switch to completely different
+ algorithm to deal with lame-ass monitors which put spaces in the
+ middle of numbers, and prompt with a space!!!!!
+ * (monitor_read_memory_single): New routine to be used with
+ monitors that can only return one byte/short/long at a time. This
+ is selected via MO_GETMEM_READ_SINGLE.
+ * (monitor_load_srec): Use monitor_printf_noecho for sending S
+ records. Most targets don't echo them.
+ * (monitor.h): Get rid of cmd_delim. Add line_delim.
+ * op50n-rom.c (op50n_cmds): Fill it up. Make it work.
+ * w89k-rom.c: Change all eols from \r to \n. Change load_resp to
+ ^Q to prevent error message.
+ * config/pa/tm-hppa.h (CALL_DUMMY (for hppro)): Add special
+ instruction sequence at end to make restore_pc_queue happy.
+
+Wed May 10 15:59:00 1995 Torbjorn Granlund <tege@adder.cygnus.com>
+
+ * remote-est.c (est_open): Make static to match prototype.
+
+Tue May 9 16:58:50 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * configure.in: Add little endian PowerPC support.
+ * config/powerpc/ppcle-eabi.mt: New file for little endian PowerPC
+ support.
+ * config/powerpc/tm-ppcle-eabi.h: ditto.
+
+Mon May 8 12:11:38 1995 J.T. Conklin <jtc@rtl.cygnus.com>
+
+ * nlm/configure.in (gdb_host, gdb_host_cpu, gdb_target): Removed.
+ These variables not used.
+
+ * config/m68k/monitor.mt (TDEPFILES): Added cpu32bug-rom.o.
+
+Wed May 3 17:54:47 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ * monitor.c (monitor_command): Don't use PROMPT until monitor
+ target is known to be open.
+ (monitor_make_srec): Don't define size of hextab.
+
+Tue May 2 18:32:24 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ * configure.in (--enable-netrom): New configuration option.
+ * Makefile.in (REMOTE_OBS): Rename from REMOTE_O, append
+ value of NETROM_OBS.
+ (NETROM_OBS): New variable.
+ * remote-nrom.c: New file, NetROM target support.
+ * config/a29k/a29k-udi.mt, config/i960/vxworks960.mt: Use
+ REMOTE_OBS instead of REMOTE_O.
+ * config/arc/arc.mt: Ditto.
+
+Fri Apr 28 23:30:00 1995 Stu Grossman (grossman@cygnus.com)
+
+ * array-rom.c (_initialize_array array_open): Move baud_rate
+ initialization from _initxxx to array_open to fix bug with
+ overriding -b command line option.
+
+Thu Apr 27 20:29:34 1995 Doug Evans <dje@canuck.cygnus.com>
+
+ * Makefile.in (RUNTEST): Fix reference of `srcdir'.
+
+Wed Apr 26 19:01:08 1995 Steve Chamberlain <sac@slash.cygnus.com>
+
+ * remote-hms.c: Rewrite to use new monitor conventions.
+
+Tue Apr 25 11:27:14 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * dbxread.c: Add comment explaining lowest_text_address.
+ Add comment regarding stringtab_global and psymtabs.
+
+Sat Apr 22 01:26:29 1995 Jeff Law (law@snake.cs.utah.edu)
+
+ * config/pa/tm-hppa.h (EXTRACT_STRUCT_VALUE_ADDRESS): Fix.
+
+ * config/pa/tm-hppa.h (EXTRACT_RETURN_VALUE): Rewrite to correctly
+ handle "short", "int" and small structures returned in registers.
+
+Fri Apr 21 12:57:53 1995 Kung Hsu <kung@mexican.cygnus.com>
+
+ * minsyms.c: add new function lookup_minimal_symbol_text, to look
+ for text symbol only.
+ * breakpoint.c (create_longjmp_breakpoint): call
+ lookup_minimal_symbol_text instead of lookup_minimal_symbol.
+ * symtab.h: add lookup_minimal_symbol_text prototype.
+
+Fri Apr 21 12:03:44 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ * sh-tdep.c (sh-opc.h): Don't include.
+ (gdbcore.h): Include.
+ (frame_find_saved_regs): Remove unused local.
+
+Thu Apr 20 10:12:21 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * dwarfread.c (struct dwfinfo), dbxread.c (struct symloc),
+ mdebugread.c (struct symloc), hpread.c (struct symloc): Clean
+ up comments.
+
+Wed Apr 19 16:58:11 1995 Stu Grossman (grossman@andros.cygnus.com)
+
+ * hppa-tdep.c (deposit_17): New routine to deposit 17 bit
+ constants into PA instructions.
+ * Put #ifdefs around all signal handling code. Not generally
+ needed for embedded boards.
+ * (hppa_fix_call_dummy): Parameterize offsets into call dummy to
+ allow different dummys to be used by this code. Use
+ INSTRUCTION_SIZE instead of REGISTER_SIZE for things.
+ Conditionalize setup of _sr4export fixup. Improve comments.
+ * config/pa/tm-hppa.h: Define INSTRUCTION_SIZE. Use a different
+ call dummy if PA_LEVEL_0 is defined. Better comments for call
+ dummys. Define offsets for LDIL/LDO instructions which load
+ function addresses.
+ * config/pa/tm-pro.h: Get rid of signal handling stuff. Define
+ PA_LEVEL_0 to disable mucking with space regs and such.
+
+Mon Apr 17 15:37:08 1995 Stu Grossman (grossman@andros.cygnus.com)
+
+ * cpu32bug-rom.c monitor.h op50-rom.c remote-est.c rom68k-rom.c
+ w89k-rom.c: Remove loadtypes, loadprotos and baudrates.
+ * op50-rom.c: Fix copyrights and add load routine to op50n_cmds.
+ * rom68k-rom.c (_initialize_rom68k): Don't set baud rate.
+ * w89k-rom.c: Fix copyrights.
+
+Sun Apr 16 14:00:55 1995 Stu Grossman (grossman@andros.cygnus.com)
+
+ * monitor.c: Move all xmodem stuff into xmodem.[ch]. Remove
+ unnecessary remoteloadprotocol and remoteloadtype support.
+ * (expect expect_prompt): Change names to monitor_expect and
+ monitor_expect_prompt. Make them global.
+ * (printf_monitor): Change name to monitor_printf. Make global.
+ * (monitor_read_memory): Flush command echo to avoid parsing
+ ambiguity with CPU32Bug monitor.
+ * (monitor_load): Remove remoteloadprotocol and remoteloadtype
+ support. Call target_ops->load_routine, default to
+ monitor_load_srec.
+ * (monitor_load_srec): Remove everything but S-record support.
+ * monitor.h (monitor_ops): Add load_routine to provide monitor
+ specific download capability.
+ * remote-est.c: Clean up copyrights and comments.
+ * w89k-rom.c: Use new xmodem support.
+ * xmodem.c xmodem.h: New files to support xmodem downloads.
+ * rom68k-rom.c remote-est.c: Fix copyrights, add load_routine
+ entry to monitor_ops.
+ * cpu32bug-rom.c: New file to support Moto BCC debuggers.
+ * config/m68k/est.mt (TDEPFILES): Add cpu32bug.o.
+ * config/pa/hppapro.mt (TDEPFILES): Add xmodem.o.
+
+Sat Apr 15 18:00:15 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * rem-multi.shar: Removed; superceded by gdbserver.
+
+Fri Apr 14 12:10:24 1995 Jim Kingdon <kingdon@deneb.cygnus.com>
+
+ * xcoffread.c (xcoff_sym_fns): Revise comment about merging this
+ with coffread.c.
+
+ * breakpoint.c (fixup_breakpoints): Removed.
+ * rs6000-nat.c (vmap_symtab): Don't call fixup_breakpoints.
+ (vmap_ldinfo, xcoff_relocate_core): Call breakpoint_re_set.
+
+ * coffread.c (coff_symfile_offsets): Allocate SECT_OFF_MAX
+ sections, not just SECT_OFF_MAX-1.
+
+ * rs6000-nat.c (vmap_symtab), xcoffread.c: Re-do section offsets
+ to be indexed by SECT_OFF_* instead of xcoff section numbers.
+ * objfiles.c, remote.c: Remove comments regarding SECT_OFF_*.
+ * symtab.h: Revise comment about block_line_section.
+ * rs6000-nat.c (vmap_symtab): Don't relocate objfile->sections.
+
+Sat Apr 15 14:15:14 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ * mpw-make.in (init.c): Don't try to do symbolic {o} in sed
+ command, not allowed by some version of MPW Make.
+ * ser-mac.c (mac-setbaudrate): Make it actually set baud rates.
+
+Sat Apr 15 14:05:09 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * alpha-tdep.c (alpha_push_arguments): Fix typo (TYPE_VALUE ->
+ VALUE_TYPE). Do the cast for TYPE_CODE_BOOL, TYPE_CODE_CHAR,
+ TYPE_CODE_ENUM, and TYPE_CODE_RANGE as well as TYPE_CODE_INT.
+
+Sat Apr 15 14:04:32 1995 Per Bothner <bothner@cygnus.com>
+
+ * alpha-tdep.c (alpha_push_arguments): Only cast to long for
+ TYPE_CODE_INT.
+
+
+Thu Apr 13 16:17:04 1995 Rob Savoye <rob@darkstar.cygnus.com>
+
+ * remote-array.c: New file for Array Tech LSI33k based controller
+ board.
+
+Thu Apr 13 12:23:31 1995 Kung Hsu <kung@rtl.cygnus.com>
+
+ * a29k-tdep.c (get_longjmp_target): Replace SWAP_TARGET_AND_HOST with
+ extract_address.
+ * remote-vxsparc.c: New file, preliminary check in, this configuration
+ not supported yet.
+ * remote-vxmips.c: ditto.
+
+Thu Apr 13 12:10:14 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * rs6000-tdep.c (xcoff_add_toc_to_loadinfo): Don't use a prototype
+ to declare the function.
+
+Wed Apr 12 16:40:20 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ * monitor.h (init_monitor_ops): Declare.
+ * rom68k-rom.c: Clarify some comments.
+ (rom68k_open): Define as static, to match decl.
+
+Wed Apr 12 16:36:44 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.gdb: New file.
+ * .gdbinit: Move list-objfiles to gdb.gdb.
+
+ * values.c (set_internalvar): Set modifiable flag of newval.
+
+Wed Apr 12 14:34:31 1995 Jim Kingdon <kingdon@deneb.cygnus.com>
+
+ * xcoffread.c: Call complain() rather than error() or printing a
+ warning.
+
+Wed Apr 12 08:15:27 1995 Doug Evans <dje@canuck.cygnus.com>
+
+ * arc-tdep.c: #include "gdbcmd.h".
+ (codestream_seek): Pass CORE_ADDR.
+ (arc_cpu_type, tmp_arc_cpu_type, arc_cpu_type_table): New globals.
+ (debug_pipeline_p): Likewise.
+ (X_...): Instruction field access macros.
+ (BUILD_INSN): Define.
+ (codestream_tell): Allow for stream elements > 1 byte.
+ (codestream_fill): Likewise.
+ (setup_prologue_scan): New function.
+ (arc_get_frame_setup): Call it. Update to current spec
+ regarding prologues. Use BUILD_INSN.
+ (skip_prologue): New argument `frameless_p'. Use BUILD_INSN.
+ (arc_frame_saved_pc): New function.
+ (frame_find_saved_regs): Use BUILD_INSN.
+ (get_insn_type, single_step): New functions.
+ (one_stepped): New global.
+ (arc_set_cpu_type_command, arc_show_cpu_type_command): New functions.
+ (arc_set_cpu_type): New function.
+ (_initialize_arc_tdep): Define new `set' commands `cpu',
+ `displaypipeline', and `debugpipeline'.
+ * arc/tm-arc.h (TARGET_BYTE_ORDER): Delete.
+ (TARGET_BYTE_ORDER_SELECTABLE): Define.
+ (DEFAULT_ARC_CPU_TYPE): Define.
+ (SKIP_PROLOGUE_FRAMELESS_P): Define.
+ (BREAKPOINT): Delete.
+ (BIG_BREAKPOINT, LITTLE_BREAKPOINT): Define.
+ (DECR_PC_AFTER_BREAK): Change to 8.
+ (NO_SINGLE_STEP): Define.
+ (ARC_PC_TO_REAL_ADDRESS): Define.
+ (SAVED_PC_AFTER_CALL): Use it.
+ (NUM_REGS, REGISTER_BYTES): Fix.
+ (FRAME_SAVED_PC): Call arc_frame_saved_pc.
+ (FRAME_LOCALS_ADDRESS): Fix.
+
+Tue Apr 11 16:42:37 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * top.c, utils.c, defs.h: Remove error_hook. It is currently
+ unused and would need to hook into error_begin()/return_to_top_level(),
+ instead of error(), if it were to be used.
+
+Tue Apr 11 13:46:25 1995 Jim Kingdon <kingdon@deneb.cygnus.com>
+
+ * utils.c, defs.h (warning_begin): Renamed from warning_setup, for
+ consistency with error_begin. Also print warning_pre_print.
+ Document it better.
+ * utils.c (warning): Use it.
+ * utils.c (error_begin): Doc fix.
+ * rs6000-nat.c (vmap_ldinfo): If we don't find ldinfo for the
+ symfile_objfile, nuke it.
+
+Tue Apr 11 09:35:20 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * printcmd.c (print_address_numeric): Pass use_local to
+ print_longest, rather than always passing 1.
+
+ * nlm/Makefile.in: Remove comments discussing munch.
+
+
+Mon Apr 10 18:31:57 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ Merge in support for Mac MPW as a host.
+ (Old change descriptions retained for informational value.)
+
+ * mpw-config.in (i386-unknown-go32): Change from aout.
+ (sh-hitachi-hms): New target.
+ * mpw-make.in (BISON): Use byacc instead of bison.
+ (VERSION): Bump to 4.14.1.
+ (*-pinsn.*): Remove mentions everywhere.
+ (all): Don't build MacGDB.
+ (gdb, SiowGDB): Depend on Version.r.
+ (Version.r): Generate from version info.
+ * main.c (main): Pass program name to START_PROGRESS, END_PROGRESS.
+ (main) [MPW]: Remove debugging hook.
+ * mac-xdep.c (debug_openp): New flag.
+ (mac_init): Set flag if env variable defined.
+ * ser-mac.c (mac_open): Clarify error message.
+ (mac_readchar): Call PROGRESS while looping.
+ (mac_write): Call sleep instead of sec_sleep.
+ (sec_sleep): Remove.
+ * source.c (openp) [MPW]: Only print debugging info if debugging.
+ * utils.c (query) [MPW]: Clarify that behavior is a bug.
+
+ * mpw-make.in (init.c): Use open-brace instead of mpw-open-brace.
+
+ * main.c, source.c: Remove hacks that replace long strings
+ with shorter ones, now solved portably.
+
+ * config/m68k/xm-mpw.h (spin.h): Include.
+ (ALMOST_STDC): Only define if MPW_C.
+ * config/m68k/tm-mac.h: New file, Mac target definitions.
+
+ * mpw-config.in (m68k-apple-macos, ppc-apple-macos,
+ i386-unknown-aout): New targets.
+ (mk.tmp): Add *DEPFILES definitions.
+ * mpw-make.in: Remove gC rules, clean up definitions for other
+ include files, bump version, fix bogus \ that should be \Option-d.
+ (init.c): Build correctly.
+
+ * mpw-make.in (HFILES_NO_SRCDIR): Add somsolib.h
+ (ALLDEPFILES): Add somsolib.c.
+ (somsolib.o): Add some dependencies.
+
+ * mpw-config.in: Use nm-empty.h if host is not target.
+ (xdepfiles): Add mac-xdep.c.o.
+ (xm_file): Remove.
+ * mpw-make.in: Add Fortran files.
+ (XDEPFILES): Remove.
+
+ * mpw-config.in (MacSerial.h): Duplicate from standard Serial.h.
+ * ser-mac.c (MacSerial.h): Include instead of Serial.h.
+
+ * mpw-make.in: Use {s} instead of {srcdir} everywhere.
+ (bindir, libdir): Remove extra colon.
+ (source.c): Compile with C instead of gC.
+ (c-exp.tab.c, ch-exp.tab.c, m2-exp.tab.c): Add {o}.
+ (install-only): Don't install MacGDB.
+ * source.c (openp) [MPW]: Add a debugging display.
+ (open_source_file) [MPW]: Use MPW basename finders.
+ [MPW_C]: Briefer versions of help for line and list commands.
+
+ * mpw-make.in: Change references from paread.c to somread.c
+
+ * mpw-make.in (VERSION): Update to 4.12.3.
+ (SiowGDB): New target, GDB using SIOW library.
+ (init-new.c): New target, attempt to generate init.c from sources.
+ (main.c.o, top.c.o): Put each in its own segment.
+ * main.c (main) [MPW]: Always call mac_init.
+ * utils.c (query) [MPW]: Always return "yes" if in MacGDB, output
+ an extra newline otherwise.
+ * mac-xdep.c: More comments in various places, remove junk.
+ (mac_init): Add tests for MPW and SIOW.
+ (use_wne, has_color_qd): Renamed.
+ (use_color_qd): New variable.
+ (grow_window): Only do console resizing to console window,
+ call resize_console_window.
+ (zoom_window): Call resize_console_window.
+ (resize_console_window, scroll_text): New functions.
+ (adjust_console_sizes): Always align viewrect to even multiples of
+ text lines.
+ (adjust_console_text): Always scroll by whole lines.
+ (hacked_vfprintf, hacked_puts, hacked_fputc, hacked_putc): Force a
+ recalculation of scroll positions if a newline was output.
+ (hacked_fflush): Similarly, for flushing.
+ (hacked_fgetc): New function, aborts if called in MacGDB.
+ * ser-mac.c (mac_readchar): Rename starttime to start_time,
+ remove debugging printf.
+ (mac_write): Sleep on first 4 writes.
+ (sec_sleep): New function, works like standard sleep.
+ * macgdb.r: Adjust positioning and contents of About box.
+ Set minimum size to 2000K, preferred size to 5000K.
+ * config/m68k/xm-mpw.h (fgetc): Define as a macro.
+
+ * mpw-make.in (.c.o, .gc.o): Prefix segment names with gdb_.
+ (top.c.o, annotate.c.o): Add build rules.
+ * macgdb.r (SysTypes.r): Include.
+ ('vers'): New resource, version info.
+ (mFile, mEdit, mDebug): Enable all menu items.
+ (mDebug): Add key equivalents for continue, step, next.
+ (wConsole): Add zoom and close boxes to window.
+ * mac-xdep.c (new_console_window): New function, code taken from
+ mac_init.
+ (mac_command_loop): Use GetCaretTime for wait interval, call
+ do_idle on null events.
+ (do_idle): New function.
+ (zoom_window): Implement zooming.
+ (v_scroll_proc): New function, handles vertical scrolling.
+ (activate_window): Do activation of console window.
+ (do_menu_command): Implement items of file, edit, and debug menus.
+ (do_keyboard_command): Fix command extraction.
+ (adjust_console_sizes, adjust_console_text): New functions.
+ (hacked_fprintf, hacked_vfprintf, hacked_fputs, hacked_fputc,
+ hacked_putc): Don't call draw_console.
+ * ser-mac.c (mac_open): Add an error message for invalid ports.
+ (first_mac_write): New global.
+ (mac_write): Use first_mac_write to sleep on first several writes.
+
+ * mpw-make.in (INCLUDE_CFLAGS): Add readline source dir.
+ (READLINE_CFLAGS, READLINE_SRC, READLINE_DIR): Uncomment.
+ (TSOBS): Don't compile inflow.c.
+ (all, install): Add MacGDB.
+ * main.c (main): Do Mac-specific init and command loop if a
+ standalone app, skip full option help message if compiling
+ with MPW C.
+ (gdb_readline): If MPW, add a newline after the (gdb) prompt.
+ * utils.c (_initialize_utils): If MPW, don't try to use termcap to
+ compute the window size.
+ * config/m68k/xm-mpw.h (printf, fprintf, fputs, fputc, putc,
+ fflush): Define as macros that expand into hacked_... versions.
+ (StandAlone, mac_app): Declare.
+ * macgdb.r (SIZE): Set the default partition to 4000K.
+ * mac-xdep.c (readline.h, history.h): Include.
+ (terminal.h): Don't include.
+ (mac_app): Define.
+ (gdb_has_a_terminal): Define Mac-specific version.
+ (do_keyboard_command): Simplify search for command string.
+ (readline): Define as gdb_readline.
+ Add other history/readline stubs to make main gdb link.
+ (hacked_fprintf, hacked_printf, hacked_vfprintf, hacked_fputs,
+ hacked_fputc, hacked_fflush): New functions, intercept output to
+ stdout and stderr, send to console window.
+
+ * mpw-make.in (MacGDB): New target, standalone Mac-hosted gdb.
+ (XDEPFILES): Define.
+ (main.c.o): Compile with gC instead of C.
+ * mac-defs.h: New file, menu etc definitions shared between
+ C and Rez files.
+ * macgdb.r: New file, Rez (resource compiler) resource
+ definitions.
+ * mac-xdep.c: New file, Mac host interface code.
+ * config/m68k/xm-mpw.h (PATHNAME_SEPARATOR): Rename to
+ DIRNAME_SEPARATOR.
+ (PATHNAME_SEPARATOR_STRING): Remove.
+ (SIGQUIT, SIGHUP): Define.
+ (fileno, R_OK): Define.
+
+ * mpw-config.in: New file, MPW configuration fragment.
+ * mpw-make.in: New file, MPW makefile fragment.
+ * config/m68k/xm-mpw.h: New file, MPW host definitions.
+ * ser-mac.c: New file, Mac serial interface.
+
+Mon Apr 10 16:47:57 1995 Kung Hsu <kung@mexican.cygnus.com>
+
+ * valprint.c (print_longest): Fix a syntax error in #ifdef
+ PRINTF_HAS_LONG_LONG.
+
+ * config/mips/xm-irix5.h: turn on CC_HAS_LONG_LONG and
+ PRINTF_HAS_LONG_LONG.
+ * config/mips/tm-irix5.h: turn on FORCE_LONG_LONG.
+
+Sat Apr 8 02:47:45 1995 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * mdebugread.c (parse_symbol): Use new variable
+ nodebug_var_symbol_type as type of variables which don't have any
+ ecoff debug info associated with them.
+ (parse_symbol, parse_procedure): Use heuristics to determine if
+ functions were compiled without debugging info and change their
+ type to nodebug_function_symbol_type.
+ (_initialize_mdebugread): Initialize nodebug_*_symbol_type.
+
+ * source.c (line_info): Clear sal.pc for `info line' without
+ arguments.
+
+Fri Apr 7 17:43:01 1995 Stu Grossman (grossman@andros.cygnus.com)
+
+ * monitor.c: make_xmodem_packet and print_xmodem_packet go away.
+ send_xmodem_packet shows up to do the obvious. Lots of fixes to
+ xmodem downloads including resetting of block number at start of
+ new transfers, fix for buffer overrun problem, addition of CRC
+ generation code.
+ * (monitor_open): loadtype_str and loadproto_str now default to
+ first entry in monitor_ops->loadtypes.
+ * (monitor_wait): Lengthen register dump buf, because of verbose
+ Winbond monitor.
+ * (monitor_fetch_register): Report unimplemented registers as 0.
+ * (monitor_read_memory): Only do 16 byte aligned transfers
+ because of formatting weirdness with the Winbond monitor. Also,
+ ignore non-hex, non-whitespace formatting between bytes (same
+ monitor).
+ * (monitor_load): Clean up logic.
+ * (monitor_load_srec): Re-do xmodem support. Move lots of it
+ into send_xmodem_packet.
+ * (getacknak): Get rid of polls and timeouts. Handle CRC
+ requests from receiver.
+ * (monitor_make_srec): Efficiency improvements. Don't call
+ sprintf to output two digit hex numbers.
+ * (crcinit, docrc): New, CRC-16 support routines.
+ * (send_xmodem_packet): New routine to generate either CRC-16 or
+ checksummed xmodem packets.
+
+ * remote-est.c (est_loadtypes), rom68k-rom.c (rom68k_loadtypes):
+ Reduce tables down to only the load types supported by each
+ monitor.
+
+ * w89k-rom.c (w89k_supply_register): Parses output of Winbond
+ register dumps.
+ * (w89k_loadtypes, w89k_loadprotos): Reduce to just srec/xmodem.
+ * (w89k_cmds): Add clear all breakpoints, memory fill, and dump
+ registers commands.
+
+ * config/pa/tm-hppa.h: Define lots register offsets needed by
+ w89k-rom.c.
+
+
+Thu Apr 6 17:00:46 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * Makefile.in (X11_INCLUDES): Define as empty.
+ (X11_CFLAGS): Define as including $(X11_INCLUDES).
+ (X11_LIB_SWITCHES): Define as empty.
+ (X11_LIBS): Define as -lX11.
+
+
+Wed Apr 5 19:57:38 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * mips-tdep.c (mips_print_register): Remove unused variable
+ our_type and call to init_type. Fixes memory leak. Reindent function.
+
+ * mips-tdep.c (mips_print_register), findvar.c
+ (write_register_bytes): Make buffer char[] instead of unsigned
+ char[].
+
+Mon Apr 3 19:28:14 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * top.c, utils.c, main.c, defs.h: Replace error_pre_print with two
+ variables: error_pre_print (for RETURN_ERROR) and quit_pre_print
+ (for RETURN_QUIT). Fixes a bug whereby typing ^C (e.g. in "maint
+ print sym") could output extraneous stuff.
+ * objfiles.c: Don't declare error_pre_print; defs.h does it.
+
+Mon Apr 3 13:48:28 1995 Stu Grossman (grossman@andros.cygnus.com)
+
+ * monitor.h: Add MO_GETMEM_NEEDS_RANGE flag.
+ * monitor.c (monitor_read_memory): Use previously mentioned flag
+ to send proper format memory examine commands to the w89k monitor.
+ Also, try to handle bizarre format of memory dump...
+
+ * op50-rom.c w89k-rom.c: Update to new monitor.[ch] conventions.
+
+Sat Apr 1 03:22:20 1995 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * dbxread.c (process_one_symbol) [SOFUN_ADDRESS_MAYBE_MISSING]:
+ Handle relocated symbol address.
+ * partial-stab.h, case N_SO, SOFUN_ADDRESS_MAYBE_MISSING:
+ Do not relocate a zero address.
+
+Thu Mar 30 19:46:36 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * config/a29k/tm-a29k.h: Nuke obsolete define CONTROL_END_ADDR; it
+ is nowhere used.
+
+ * stabsread.c (read_range_type): Remove FIXME comment about
+ type-id (I presume this meant a number followed by = followed by a
+ type) versus type number; Per fixed it.
+
+Wed Mar 29 09:56:04 1995 Jason Molenda (crash@phydeaux.cygnus.com)
+
+ * configure.in: sparc-*-sunos5* is same as sparc-*-solaris2*.
+
+Wed Mar 29 18:30:03 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ * remote-e7000.c (why_stop): Add new kinds of strings to expect
+ from the emulator.
+ (e7000_wait): Add interpretations for more stop reasons,
+ including warnings for write protect and cycle address errors.
+
+Wed Mar 29 17:09:29 1995 Stu Grossman (grossman@cygnus.com)
+
+ * monitor.c monitor.h remote-est.c rom68k-rom.c: Add start of
+ support for interrupting target.
+ * monitor.c (monitor_open): Send stop command before doing
+ anything else.
+ * (monitor_load_srec): Fix record size calculation to prevent end
+ of segment from getting trashed.
+ * rom68k-rom.c: Update to latest version of struct monitor_ops.
+ * config/sparc/tm-sparc.h (FIX_CALL_DUMMY): Fix byte-order
+ problems. Makes DOS hosted function calling work.
+ * sparclite/crt0.s: Define _start to make COFF happy.
+
+Wed Mar 29 09:11:51 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * defs.h (atof): Don't provide an external declaration if atof is
+ a macro.
+
+Wed Mar 29 00:01:07 1995 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * rs6000-tdep.c (skip_prologue): Skip saving of LR and CR in
+ the stack frame, fix typos in `st rx,NUM(r1)' and `stu r1,NUM(r1)'
+ tests.
+
+Tue Mar 28 17:04:04 1995 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * gdbtypes.c (create_range_type): If indextype has TYPE_FLAG_STUB
+ set, set TYPE_FLAG_TARGET_STUB.
+ (check_stub_type): Recalculate TYPE_LENGTH for range type.
+ * stabsread.c (read_range_type): If index type number is followed
+ by '=', back up, call read_type. and assume we have a true range.
+ * gdbtypes.h (TYPE_FLAG_TARGET_STUB): Update comment.
+
+Mon Mar 27 22:51:54 1995 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * alpha-nat.c, irix4-nat.c, irix5-nat.c, mipsv4-nat.c,
+ sparc-tdep.c (supply_gregset, supply_fpregset): Fill inaccessible
+ registers with zero to handle recent read_register_bytes change.
+ * irix4-nat.c, irix5-nat.c, mipsv4-nat.c (supply_gregset,
+ fill_gregset): Fix handling of CAUSE_REGNUM.
+ * mips-nat.c (store_inferior_registers): Handle unwritable
+ registers when storing a single register.
+ * config/mips/tm-irix3.h (CAUSE_REGNUM, BADVADDR_REGNUM):
+ Fix definitions.
+
+ * mdebugread.c (parse_symbol, psymtab_to_symtab_1): Clear
+ allocated mips_extra_func_info, if the debug info is corrupt,
+ the PDR to fill it in might be missing.
+
+Mon Mar 27 14:43:00 1995 Kung Hsu <kung@mexican.cygnus.com>
+
+ * vx-share/regPacket.h: a new file interfacing with vxworks.
+
+Sun Mar 26 13:22:47 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * breakpoint.c (bpstat_do_actions): Once we've executed the
+ commands, set bs->commands to NULL.
+
+Sat Mar 25 01:16:10 1995 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * buildsym.c (patch_subfile_name): Update last_source_file
+ with the real source file name.
+ * dbxread.c (end_psymtab): Handle static functions in the
+ SOFUN_ADDRESS_MAYBE_MISSING case by passing pst->filename
+ to lookup_minimal_symbol.
+ (process_one_symbol): Ignore extra outermost context from
+ SunPRO cc and acc.
+ * stabsread.c (define_symbol): Do not complain for SunPRO
+ static variable encoding if STATIC_TRANSFORM_NAME is defined.
+ * sparc-tdep.c, config/sparc/tm-sun4sol2.h
+ (sunpro_static_transform_name): Renamed from
+ solaris_static_transform_name.
+ * config/sparc/tm-sun4os4.h (STATIC_TRANSFORM_NAME):
+ Define to sunpro_static_transform_name for acc 3.0 compiled
+ executables.
+ * procfs.c, config/alpha/nm-osf2.h (PROCFS_DONT_TRACE_FAULTS):
+ Renamed from PROCFS_DONT_TRACE_IFAULT, don't trace any faults
+ if defined.
+ * procfs.c (info_proc_siginfo): Cast sip->si_addr to
+ `unsigned long' and use `lx' format for printing it.
+
+Fri Mar 24 15:45:42 1995 Stu Grossman (grossman@cygnus.com)
+
+ * configure.in: Move test for m68*-est-* before m68*-*-coff*.
+ * findvar.c: Move default def of CANNOT_STORE_REGISTER closer to
+ the beginning of the code.
+ * (write_register_gen): New routine. Analogous to
+ read_register_gen.
+ * (write_register_bytes): Another rewrite! Make it smarter about
+ not updating regs with the same value.
+ * monitor.c (printf_monitor readchar): Use stderr instead of
+ stdout to output debug info. Also cleanup readchar a little.
+ * (expect): Make sure that excessive responses are null
+ terminated.
+ * (monitor_open): Check for magic number in monitor_ops struct.
+ Allow multiple commands as init strings. Also, clear all
+ breakpoints.
+ * (monitor_resume monitor_wait): Send a command to dump all the
+ regs for those targets which don't do so when waking up after a
+ continue command.
+ * (monitor_wait): Handle excessive response output better.
+ * (monitor_write_memory): Use block fill, word, and long word
+ commands (if they exist) to write memory more efficiently.
+ * General cleanups to use flag bits instead of individual flag
+ words in monitor_ops struct.
+ * (monitor_command): Return output from command.
+ * (monitor_load_srec): Allocate buffer only once. Use alloca.
+ Wait for load response string instead of using a timeout to start
+ sending S-records. Fix bug where value of srec_frame shrinks. If
+ hashmark is set, print `-' for retransmissions. General cleanups.
+ * (monitor_make_srec): Get rid of S-record default type kludge.
+ * monitor.h: Use seperate struct for memory and register
+ read/write commands. Memory commands can come in byte, word,
+ long, and longlong forms.
+ * (monitor_ops): Change lots of fields. Generalize some stuff.
+ Put all flags into flags word. Allow init to be a list of commands.
+ Add command for clearing all breakpoints, block fill, dumping all
+ registers.
+ * remote-est.c: Rewrite to use new monitor conventions.
+ * config/m68k/est.mt (TDEPFILES): Add monitor.o.
+ * config/m68k/tm-est.h: Set NUM_REGS to 18.
+ * testsuite/gdb.base/break.exp: Lots of cleanups. Use gdb_test
+ more thoroughly.
+
+Thu Mar 23 23:20:00 1995 Jeff Law (law@snake.cs.utah.edu)
+
+ * somsolib.c (som_solib_add): Handle case where a shared library
+ referenced by a core file has sections without the SEC_ALLOC bit
+ set (eg stabs sections).
+
+Thu Mar 23 15:07:08 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * breakpoint.c (bpstat_do_actions): For each element in the bpstat
+ chain, do all the commands regardless of whether they run the
+ inferior.
+
+Wed Mar 22 19:17:06 1995 Doug Evans <dje@cygnus.com>
+
+ * mem-break.c (LITTLE_BREAKPOINT, BIG_BREAKPOINT): Define as
+ BREAKPOINT if mono-endian.
+ (break_insn): Deleted.
+ (big_break_insn, little_break_insn): Define.
+ (memory_insert_breakpoint): Handle bi-endian cpus.
+ (BREAKPOINT_LEN): Define.
+ (memory_remove_breakpoint): Use it.
+ (memory_breakpoint_size): Likewise.
+
+Tue Mar 21 17:03:17 1995 Kung Hsu <kung@mexican.cygnus.com>
+
+ * sparc-stub.c: add nop after 'bg good_wim'.
+ * sparcl-stub.c: ditto.
+
+Tue Mar 21 13:34:12 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * infrun.c (handle_command): Don't print TARGET_SIGNAL_0,
+ TARGET_SIGNAL_UNKNOWN, or TARGET_SIGNAL_DEFAULT.
+
+Mon Mar 20 10:09:59 1995 Jeff Law (law@snake.cs.utah.edu)
+
+ * hppab-nat.c (store_inferior_registers): Sync with HPUX version.
+
+Mon Mar 20 07:34:48 1995 Stu Grossman (grossman@cygnus.com)
+
+ * hppah-nat.c (store_inferior_registers): Move check for
+ CANNOT_STORE_REGISTER to a better place. Fixes ptrace I/O errors
+ found by test suite during function calls, which attempts to write
+ unwritable registers.
+
+Sat Mar 18 02:02:24 1995 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * mdebugread.c (parse_symbol): If finishing a function without
+ known parameter type info, set that from parameter symbols.
+ Remove commented-out add_param_to_type support.
+
+Thu Mar 16 16:38:03 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * xcoffread.c (process_linenos): Make sure filename we pass to
+ start_subfile will cause deduce_language_from_filename to return
+ the correct thing. Reindent function to GNU standards.
+
+Thu Mar 16 15:54:00 1995 J.T. Conklin <jtc@rtl.cygnus.com>
+
+ * nlm/gdbserve.c (handle_exception): #if out call to StopBell,
+ as it is not available on NetWare 3 or PIN.
+ * nlm/ppc.c (StopBell): Removed.
+
+Thu Mar 16 12:14:41 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * xcoffread.c (read_xcoff_symtab): When creating a dummy parameter
+ inferred from the traceback tags, give its type the name
+ "<non-float parameter>".
+
+ * stabsread.c (rs6000_builtin_type): Recognize types -31 to -34.
+
+Wed Mar 15 15:09:29 1995 Stu Grossman (grossman@cygnus.com)
+
+ * findvar.c (read_register_bytes write_register_bytes): Make
+ these routines much smarter about updating registers from the
+ target, only doing so when absolutely necessary. This really
+ speeds up register modification on some remote targets.
+
+ * monitor.c: More cleanups. Get rid of monitor_load_ascii_srec.
+ BFD makes this unnecessary. Lots of debugging speedups.
+ * (expect): NULL terminate return string.
+ * (monitor_open monitor_supply_register parse_register_dump
+ monitor_wait monitor_fetch_register): Switch to using GNU regexp
+ library to parse multi-register displays.
+ * (monitor_read_memory): Read multiple bytes (up to 16) at once.
+ * (monitor_create_inferior): Call clear_proceed_status to make run
+ command notice first breakpoint.
+ * (monitor_load): Clean up. Reset inferior_pid, set pc to start
+ address and reset symbol table stuff to make loads put things into
+ a fresh state.
+ * (monitor_load_srec): Lower sleep time to 1 second.
+
+ * monitor.h (struct monitor_ops): Add register_pattern and
+ supply_register to monitor_ops.
+
+ * rom68k-rom.c: Add new support for handling register dumps.
+ * config/m68k/tm-m68k.h: Define D0_REGNUM and A0_REGNUM for register
+ dump handling.
+
+Wed Mar 15 15:18:27 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * utils.c, defs.h (putchar_unfiltered, fputc_unfiltered): Make
+ argument be an int, not a char. Using a prototype followed by an
+ old-style function definition in a case where an argument is
+ widened is a GCC-ism not supported by the native AIX compiler.
+
+Wed Mar 15 12:22:35 1995 J.T. Conklin <jtc@rtl.cygnus.com>
+
+ * nlmstub.def: Removed, this was moved to nlm/gdbserve.def
+ long ago.
+
+ * configure.in (alpha-*-netware*): Removed configuration.
+ * config/alpha/{alpha-nw.mt, gdbserve.mt, tm-alphanw.h}: Removed.
+ * nlm/{README-ALPHA-NETWARE, aio.h, alpha-io.S, alpha-regdef.h,
+ alpha.c, alpha.h, altdebug.h}: Removed.
+
+ * nlm/gdbserve.c (main): Add support for processing BOARD=
+ argument, deprecate NODE=.
+
+Wed Mar 15 10:58:26 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * c-exp.y (yylex): Make an empty character constant an error.
+
+Tue Mar 14 15:00:54 1995 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * valops.c (value_arg_coerce): Do possible value_coerce_array
+ before determining type argument to value_cast.
+
+Tue Mar 14 10:41:41 1995 Kung Hsu <kung@mexican.cygnus.com>
+
+ * remote-es.c: Replace ignore with 0.
+
+Tue Mar 14 05:52:36 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * valops.c (value_repeat), eval.c (evaluate_subexp_standard):
+ If VALUE_REPEATED is already set, just error out.
+
+ * valops.c (value_cast, value_slice), parse.c (follow_types): Add
+ FIXME-type-allocation comments.
+
+ * gdbtypes.h (struct type): Fix comment about what units the
+ TYPE_LENGTH is in.
+
+Mon Mar 13 18:27:25 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ * ch-valprint.c (annotate.h): Include.
+ * eval.c (evaluate_subexp_standard): Remove unused variable.
+ (calc_f77_array_dims): Add parens to expression.
+ * f-exp.y (yylex): Add parens to expression, remove unused label.
+ * f-lang.h (calc_f77_array_dims): Declare.
+ * f-valprint.c (f_val_print): Remove unused variables.
+
+Mon Mar 13 15:25:47 1995 Jim Kingdon <kingdon@deneb.cygnus.com>
+
+ * alpha-tdep.c (find_proc_desc): If pdr.framereg field is -1, don't
+ use the PDR, just examine prologues instead.
+
+Fri Mar 10 16:13:18 1995 Kung Hsu <kung@mexican.cygnus.com>
+
+ * config/arc/tm-arc.h: Change arc register names.
+
+Fri Mar 10 02:49:40 1995 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ Fix problems with infinite recursion when printing a class
+ that contains a static instance of the class.
+ * cp-valprint.c (dont_print_vb_obstack): Renamed from
+ dont_print_obstack, made static.
+ (dont_print_statmem_obstack): New obstack, controls printing
+ of static member classes.
+ (_initialize_cp_valprint): Initialize it.
+ (cp_print_static_field): New function, handles printing of
+ static members.
+ (cp_print_value_fields): New parameter dont_print_statmem to
+ handle recursive printing of static member classes, use
+ cp_print_static_field to handle printing of static members.
+ * c-valprint.c (cp_print_value_fields): Update prototype and
+ call to include additional dont_print_statmem parameter.
+ * c-valprint.c, f-valprint.c (dont_print_obstack): Remove unused
+ extern declaration.
+
+ * alpha-tdep.c, findvar.c, infptrace.c: Include <string.h>.
+
+ * config/alpha/tm-alpha.h (FRAME_FIND_SAVED_REGS): Call
+ alpha_find_saved_regs if fi->saved_regs is still NULL.
+
+ * elfread.c (elf_symtab_read): Ensure that the filename field
+ of a minsym is nonempty. Ignore solib trampoline symbols from
+ the main symbol table, they might have a bogus value.
+
+ * procfs.c (set_proc_siginfo), config/alpha/alpha-osf2.mh:
+ Fix typos in comments.
+
+Thu Mar 9 17:19:47 1995 Jim Kingdon <kingdon@deneb.cygnus.com>
+
+ * mdebugread.c (parse_symbol, psymtab_to_symtab_1): Initialize
+ pdr.framereg field of MIPS_EFI_SYMBOL_NAME symbol to -1. That way
+ we know whether the PDR ever got set.
+ * mips-tdep.c (find_proc_desc): If pdr.framereg field is -1, don't
+ use the PDR, just examine prologues instead.
+
+Wed Mar 8 23:35:10 1995 Jeff Law (law@snake.cs.utah.edu)
+
+ * somsolib.c (som_solib_section_offsets): Get offset of text
+ section right.
+
+Wed Mar 8 16:12:21 1995 Stu Grossman (grossman@cygnus.com)
+
+
+ * source.c (forward_search_command reverse_search_command): Set
+ convenience variable $_ to be the line # of the match.
+ * symtab.c (decode_line_1): Allow convenience variables to be
+ used in line specs (for breakpoints and such).
+
+Wed Mar 8 12:51:00 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ * Makefile.in (VERSION): Bump to 4.14.1.
+ * NEWS, README: Update for 4.14.
+ * i386v-nat.c (i386_insert_aligned_watchpoint): Fix declaration.
+ (i386_insert_nonaligned_watchpoint): Call aligned instead of
+ generic watchpoint insertion.
+
+Tue Mar 7 19:26:10 1995 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * valops.c (value_slice): Do COERCE_VARYING_ARRAY.
+
+Tue Mar 7 00:23:47 1995 Stu Grossman (grossman@cygnus.com)
+
+ * monitor.c, array-rom.c, monitor.h, rom68k-rom.c: Move target_ops
+ into monitor.c.
+ * monitor.c (monitor_create_inferior): Allow run command to start
+ program.
+
+ * monitor.c (monitor_load): Set PC to start address when done
+ loading.
+
+ * array-rom.c, monitor.h, rom68k-rom.c: Clean up target_ops.
+ Remove ref to monitor_create_inferior.
+
+ * monitor.c: More general cleanups. Add prototypes, remove
+ unused routines. Fix bug with wrong number of args to error().
+
+ * main.c (main): Don't start up GUI when running under gdb mode
+ in emacs.
+
+ * Makefile.in: Add rules for monitor.o and rom68k-rom.o to make
+ Sun make (with VPATH) work...
+
+ * monitor.c, monitor.h, rom68k-rom.c: Serious cleanup to make IDP
+ (rom68k) target work right.
+ * array-rom.c, op50-rom.c, w89k-rom.c: Partial updates to new
+ monitor.c interface. More work needs to be done here.
+ * config/m68k/tm-monitor.h: Change DECR_PC_AFTER_BREAK to 0 to
+ match the IDP monitor. Also, set NUM_REGS to 18 cuz there's no
+ floating-point for this card.
+
+ * serial.h, ser-go32.c, ser-mac.c, ser-tcp.c, ser-unix.c: Add
+ SERIAL_SETSTOPBITS to set the number of stopbits (needed for IDP
+ board?!?!?).
+
+ * defs.h, utils.c, remote-hms.c, remote-pa.c, remote.c: Fix defs
+ and usage of fputc_unfiltered and putchar_unfiltered. Eliminate
+ putc_unfiltered (it's superfluous).
+
+ * command.h, command.c, top.c: Add var_enum command type. It's
+ like var_string but allows only only one of the specified strings.
+
+Mon Mar 6 15:03:59 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * valops.c (value_cast): Don't use backslash newline--pre-ANSI
+ compilers (such as SunOS4 /bin/cc) don't generally support it
+ except in some contexts.
+
+Fri Mar 3 17:42:48 1995 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * valops.c (value_cast): Check for cast to array type *before*
+ we coerce array to pointer (in case arg2 is already array).
+
+ * valops.c (call_function_by_hand): Set using_gcc to 2 if using
+ gcc2. Needed for REG_STRUCT_HAS_ADDR to work on sparc.
+ Also check REG_STRUCT_HAS_ADDR for union, array and string types.
+
+ * valops.c (call_function_by_hand): Re-arrange code for pushing
+ paramaters on the stack so we can do better STACK_ALIGN.
+
+ * valops.c (call_function_by_hand): Call error if the number
+ of arguments is fewer than parameter types in function type.
+
+Fri Mar 3 17:13:05 1995 Doug Evans <dje@canuck.cygnus.com>
+
+ * sparc-tdep.c (sparc_extract_struct_value_address): Move
+ sparc64 support to here.
+ (sparc64_extract_struct_value_address): Deleted.
+ (dump_ccreg): Add a prototype so long long arg -> int.
+ * sparc/tm-sp64.h (USE_STRUCT_CONVENTION): Define.
+ (EXTRACT_STRUCT_VALUE_ADDRESS): Delete.
+
+Fri Mar 3 15:12:12 1995 Jeff Law (law@snake.cs.utah.edu)
+
+ * hpread.c (hpread_record_lines): New argument "offset". All
+ callers changed. Use it to handle dynamic address relocation.
+ (hpread_build_psymtabs): Adjust texthigh as we read each function
+ debug symbol. Fix computation of texthigh.
+ (hpread_read_subrange_type): Work around macro bugs in HP's
+ compilers.
+ (hpread_process_one_debug_symbol): Correctly map source lines.
+
+ * somread.c (check_strange_names): Filter names emitted by the HP
+ compiler when generating PIC code.
+
+ * valops.c (value_struct_elt_for_reference): Work around macro
+ bugs in HP's compilers.
+ * c-exp.y (block): Likewise.
+
+Fri Mar 3 12:27:28 1995 Jim Kingdon <kingdon@deneb.cygnus.com>
+
+ * rs6000-tdep.c (push_dummy_frame): Fix order of arguments to
+ store_address.
+
+ * utils.c [_AIX]: Include stddef.h instead of #defining size_t.
+
+Fri Mar 3 12:33:24 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * rs6000-tdep.c (skip_prologue): Skip multiple stores of the saved
+ registers that GCC emits on the PowerPC by default in addition to
+ the store multiple instruction used on the Power series.
+
+Fri Mar 3 00:54:58 1995 Doug Evans <dje@canuck.cygnus.com>
+
+ * sparc-tdep.c (decode_asi): New function.
+ (sparc_print_register_hook): Pretty print more v9 registers.
+ * sparc/tm-sp64.h (REGISTER_NAMES): Fix some typos.
+
+Thu Mar 2 22:20:22 1995 Doug Evans <dje@canuck.cygnus.com>
+
+ * dwarfread.c (struct dieinfo): Use CORE_ADDR for at_{low,high}_pc.
+ (target_to_host): Change result type to CORE_ADDR.
+
+Thu Mar 2 15:13:04 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * rs6000-tdep.c: Fix byte-swapping sins.
+
+Thu Mar 2 16:48:45 1995 Michael Meissner <meissner@cygnus.com>
+
+ * rs6000-tdep.c (branch_dest): Minor code cleanup, don't share
+ code between branch unconditional and branch conditional cases.
+
+Wed Mar 1 09:41:26 1995 Doug Evans <dje@canuck.cygnus.com>
+
+ Various changes for sparc64.
+ * sparc-tdep.c (NUM_SPARC_FPREGS): Define.
+ (SPARC_INTREG_SIZE): Define.
+ (*): Use SPARC_INTREG_SIZE instead of REGISTER_RAW_SIZE (intreg)
+ where appropriate.
+ (enum branch_type): New value `done_retry'.
+ (isbranch): Renamed from isannulled. All callers changed.
+ Support new sparc64 branch insns.
+ (single_step): Handle done_retry.
+ (sparc_extract_struct_value_address): Don't assume 4 byte regs.
+ (get_saved_register): Likewise.
+ (sparc_push_dummy_frame): Likewise.
+ (sparc_frame_find_saved_regs): Likewise.
+ (sparc_pop_frame): Likewise. Don't refer to FPS_REGNUM, CPS_REGNUM,
+ or PS_REGNUM if not sparc64. sparc64 has 64 fp regs.
+ (sparc64_extract_struct_value_address): New function.
+ (dump_ccreg, sparc_print_register_hook): Likewise.
+ * sp64-tdep.c: Deleted.
+ * sparc/tm-sp64.h (GDB_TARGET_IS_SPARC64): Define.
+ (NUM_REGS): Reduce by 2, cle/tle are in the pstate reg.
+ (CC_HAS_LONG_LONG): Define.
+ (REGISTER_NAMES): Delete cle/tle and reorganize.
+ (PS_REGNUM, FPS_REGNUM, CPS_REGNUM): Delete, they're ifdef'd out of
+ sparc-tdep.c now.
+ (REGISTER_BYTES): Update.
+ (REGISTER_CONVERT_TO_VIRTUAL, REGISTER_CONVERT_TO_RAW): Delete.
+ (EXTRACT_RETURN_VALUE): Delete. Use definition in tm-sparc.h.
+ (NO_SINGLE_STEP): Likewise.
+ * sparc/tm-sparc.h (EXTRACT_VALUE_RETURN): Don't assume 4 byte regs.
+ * sparc/sp64.mt: Move simulator support ...
+ * sparc/sp64sim.mt: ... to here.
+
+Wed Mar 1 13:14:42 1995 Kung Hsu <kung@mexican.cygnus.com>
+
+ * remote-vx960.c: new file for target specific register packaging.
+ * remote-vx68.c: ditto.
+ * config/i960/vxworks960.mt: add remote-vx960.o.
+ * config/m68k/vxworks68.mt: add remote-vx68.o.
+
+Wed Mar 1 13:42:49 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * remote.c (remote_wait): Make calls to strtol be type correct by
+ passing the address of a char * pointer instead of an unsigned
+ char *.
+
+ * rs6000-tdep.c (push_dummy_frame): Cast sp to char * when calling
+ write_memory to make things type correct.
+
+Wed Mar 1 12:17:31 1995 Michael Meissner <meissner@cygnus.com>
+
+ * ch-exp.y, c-exp.y, f-exp.y, m2-exp.y (yy defines): Support the
+ standard Linux yacc by adding more names to be redefined with a
+ prefix.
+
+Tue Feb 28 22:55:47 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * hppa-tdep.c (pa_print_registers), monitor.c: Use
+ extract_unsigned_integer and friends, not SWAP_TARGET_AND_HOST.
+ * defs.h, findvar.c: Move SWAP_TARGET_AND_HOST back to findvar.c.
+ Rename it to SWAP_FLOATING to make it clear it is no longer for
+ integers.
+
+Tue Feb 28 14:38:39 1995 Kung Hsu <kung@mexican.cygnus.com>
+
+ * defs.h (SWAP_TARGET_AND_HOST): check endianess at runtime not
+ compile time.
+ * arc-tdep.c (_initialize_arc_tdep): set tm_print_insn according to
+ processor.
+
+ * vx-share/ptrace.h: merge in WRS new ptrace requests.
+
+ * defs.h: fix a syntax error.
+
+ * a29k-tdep.c (get_longjmp_target): add this function, from WRS.
+ * remote-vx.c: move read_register and write_register out to
+ target specific files.
+ * remote-vx29k.c (get_fp_contnets): add this function, from WRS.
+
+ * defs.h: define SWAP_TARGET_AND_HOST macro.
+ * findvar.c, monitor.c, hppa-tdep.c: remove definition of
+ SWAP_TARGET_AND_HOST.
+
+Tue Feb 28 08:31:40 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * alpha-tdep.c (find_proc_desc): Only attempt to set
+ PROC_LOCALOFF (found_heuristic) if found_heuristic is non-NULL.
+
+Mon Feb 27 11:56:32 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ * monitor.c: General gcc -Wall lint cleanup and reformat.
+ (monitor_command): If no args, send an empty command.
+
+Thu Feb 23 21:07:25 1995 Stu Grossman (grossman@cygnus.com)
+
+ * monitor.c (monitor_load_ascii_srec): Add a one second sleep
+ after send LOAD_CMD to prevent loss of first S-record.
+
+Tue Feb 21 20:48:42 1995 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * valops.c (call_function_by_hand): Set using_gcc to 2 if gcc-2.
+ Call error if too few arguments.
+ If REG_STRUCT_HAS_ADDR (structs passed by invisible reference),
+ copy and convert to reference *before* we calculate alignment.
+ Also, make sure structs allocated for return values and invisible
+ reference don't violate STACK_ALIGN.
+
+Tue Feb 21 23:29:59 1995 Per Bothner <bothner@rtl.cygnus.com>
+
+ * ch-exp.y (expression_conversion): Recognize 'ARRAY () TYPE (EXPR)'
+ (same as C's '(TYPE[])EXPR')
+
+Tue Feb 21 11:47:26 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ * top.c (print_gdb_version): Update the year.
+
+Sun Feb 19 14:31:57 1995 Jim Kingdon <kingdon@rtl.cygnus.com>
+
+ * Makefile.in (CC_FOR_TARGET, CXX_FOR_TARGET): Look for newlib in
+ `..' not in `../..'.
+
+Sun Feb 19 11:05:28 1995 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * procfs.c (unconditionally_kill_inferior): Don't issue a PIOCKILL
+ in addition to a PIOCSSIG to kill the inferior.
+
+Thu Feb 16 15:06:12 1995 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * parse.c (follow_types): Given (TYPE[]) (i.e. with no length),
+ create a 0-length array type, and set BOUND_CANNOT_BE_DETERMINED.
+ * valops.c (value_cast): If a cast like (TYPE[])VALUE (i.e. array
+ of unknown length) use sizeof(VALUE)/sizeof(TYPE) as the length.
+ * c-typeprint.c (c_type_print_varspec_suffix): If array length
+ is 0, print it, but not if upper_bound is BOUND_CANNOT_BE_DETERMINED.
+
+Thu Feb 16 16:06:50 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * dcache.c (insque, remque): Rewrite Linux support.
+
+Wed Feb 15 12:33:20 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * config/powerpc/tm-ppc-eabi.h (TEXT_SEGMENT_BASE): Define as 1.
+
+ * dcache.c (insque, remque): If compiling in standard C on Linux,
+ protect insque and remque with macros to cast the pointer
+ arguments to the proper type.
+
+Tue Feb 14 17:16:41 1995 Stu Grossman (grossman@cygnus.com)
+
+ * annotate.c, breakpoint.c, defs.h, top.c: Replace
+ enable/disable_breakpoint_hook with modify_breakpoint_hook.
+
+Tue Feb 14 16:58:07 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * expression.h: Move declaration of evaluate_subexp_with_coercion
+ from here...
+ * value.h: ...to here.
+ * expression.h: Don't include value.h
+
+Tue Feb 14 11:46:07 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * expression.h: Move include of value.h until after declaration of
+ enum exp_opcode.
+
+Sun Feb 12 13:47:30 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ * remote-e7000.c: Comprehensive cleanup; removal of dead code,
+ simplify code, declare things, format to standards.
+ (inferior.h, value.h, command.h, remote-utils.h): Include.
+ (e7000_login): Rename to e7000_login_command.
+ (e7000_ftp): Rename to e7000_ftp_command.
+ (e7000_drain): Rename to e7000_drain_command.
+
+ * irix5-nat.c (string.h): Include near beginning of file.
+
+Sun Feb 12 12:36:38 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * valops.c (value_arg_coerce): Use VALUE_TYPE not SYMBOL_TYPE on
+ arg, it is a value not a symbol.
+
+ gcc -Wall lint:
+ * eval.c: Move declaration of evaluate_subexp_with_coercion from here..
+ * expression.h: ..to here.
+ * expression.h: Include value.h.
+ * ch-lang.c (evaluate_subexp_chill): Add default case in switch.
+
+Sun Feb 12 11:03:47 1995 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * language.h (struct language_defn): New field evaluate_exp.
+ * c-lang.c (c_language_defn, cplus_language_defn, asm_langauge_defn),
+ f-lang.c (f_language_defn), language.c (unknown_language_defn,
+ auto_language_defn, local_language_defn), m2-lang.c (m2_language_defn):
+ Set evaluate_exp to evaluate_subexp_standard.
+ * ch-lang.c (evaluate_subexp_chill): New function. Chill-specific
+ support for MULTI_SUBSCRIPT.
+ (chill_language_defn): Set evaluate_exp to evaluate_subexp_chill.
+ * eval.c (enum noside): Move from here ....
+ * expression.h (enum noside): ... to here.
+ (evaluate_subexp_standard): New prototype.
+ * eval.c (evaluate_subexp): Renamed to evaluate_subexp_standard.
+ Removed lo-longer-needed test for chill_varying_type.
+ (evaluate_subexp): New. Calls exp->language_defn->evaluate_exp.
+
+ * ch-exp.y (maybe_expression_list): New non-terminal.
+ (primitive_value): Allow empty parameter list.
+
+Sun Feb 12 10:02:16 1995 Per Bothner <bothner@cygnus.com>
+
+ * buildsym.c (finish_block): If finishing a function without known
+ parameter type info, set that from parameter symbols.
+ * c-typeprint.c (c_type_print_varspec_suffix): For TYPE_CODE_FUNC,
+ print parameter types, if available.
+ * ch-typeprint.c (chill_type_print_base): Likewise.
+
+ * gdbtypes.h (struct type): Remove function type field.
+ (TYPE_FUNCTION_TYPE): Remove macro. We can't as simply re-use
+ function types now that we're also storing parameter types.
+ And the payoff is much less.
+ * gdbtypes.c (make_function_type): Don't use/set TYPE_FUNCTION_TYPE.
+ (recursive_dump_type): Don't print TYPE_FUNCTION_TYPE.
+ * dwarfread.c (read_subroutine_type): Don't set TYPE_FUNCTION_TYPE.
+
+ * valops.c (value_arg_coerce): Now takes param_type argument.
+ (call_function_by_hand): Convert arguments with value_arg_coerce
+ early, and overwrite original args with converted args.
+ No longer need multiple calls to value_arg_coerce.
+ (value_arg_push): Removed.
+ * hppa-tdep.c (hppa_push_arguments): No longer call value_arg_coerce.
+ * mips-tdep.c (mips_push_arguments): Likewise.
+ * alpha-tdep.c (alpha_push_arguments): Likewise.
+ * rs6000-tdep.c (push_arguments, ran_out_of_registers_for_arguments):
+ Likewise.
+ * value.h (value_arg_coerce): Remove declaration. (It's now static.)
+
+ * valops.c (value_cast): Do COERCE_VARYING_ARRAY after COERCE_REF.
+
+ * symtab.c (add_param_to_type): Remove (commented-out) function,
+ since that functionality has been re-written.
+ * coffread.c: Remove commented-out add_param_to_type support.
+ * mdebugread.c (parse_symbol): Likewise.
+ * stabsread.c (define_symbol): Likewise.
+
+Sun Feb 12 09:03:47 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * buildsym.c (start_subfile): Set language for f2c like for cfront.
+
+Thu Feb 9 20:20:11 1995 Rob Savoye <rob@darkstar.cygnus.com>
+
+ * op50n-rom.c: Add the control registers.
+
+Thu Feb 9 15:46:39 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ * Makefile.in (CLIBS): Add $(LIBIBERTY) before, in addition to
+ after, any host/target/native libraries.
+ * dcache.c (insque, remque): Remove declarations.
+ * gdbtypes.h (type_code): Remove trailing comma.
+
+ From Peter Schauer:
+ * xcoffread.c (read_xcoff_symtab) [C_HIDEXT]: Move #ifdef
+ STATIC_NODEBUG_VARS inside case.
+
+Thu Feb 9 07:43:41 1995 Jim Kingdon <kingdon@deneb.cygnus.com>
+
+ * config/sparc/tm-sun4sol2.h: Define STATIC_TRANSFORM_NAME.
+ * partial-stab.h: Call it.
+ * stabsread.c (define_symbol) [STATIC_TRANSFORM_NAME]: Call
+ STATIC_TRANSFORM_NAME to get the name and use minimal symbols to
+ get the address.
+ * sparc-tdep.c (solaris_static_transform_name): New function.
+
+Thu Feb 9 12:09:09 1995 Jeff Law (law@snake.cs.utah.edu)
+
+ * somread.c (som_symtab_read): Handle dynamic relocation for both
+ text and data symbols.
+ (som_symfile_offsets): If objfile is a shared library, then get
+ text and data offsets from the shared library structures.
+ * somsolib.c (som_solib_add): Copy the bfd pointer from the
+ objfile rather than reopening the file again.
+ (som_solib_section_offsets): New function.
+ * somsolib.h (som_solib_section_offsets): Declare.
+
+Wed Feb 8 20:32:18 1995 Jim Kingdon <kingdon@deneb.cygnus.com>
+
+ * config/sparc/tm-sun4sol2.h, dbxread.c: Rename
+ N_SO_ADDRESS_MAYBE_MISSING to SOFUN_ADDRESS_MAYBE_MISSING.
+ * symtab.h (minimal_symbol) [SOFUN_ADDRESS_MAYBE_MISSING]: Add
+ filename field.
+ * elfread.c (record_minimal_symbol_and_info),
+ minsyms.c, symtab.h (prim_record_minimal_symbol_and_info): Return
+ newly created symbol.
+ * elfread.c (elf_symtab_read) [SOFUN_ADDRESS_MAYBE_MISSING]:
+ Set filename field of minimal symbol.
+ * symmisc.c (dump_msymbols) [SOFUN_ADDRESS_MAYBE_MISSING]:
+ Print filename field.
+ * minsyms.c, symtab.h (lookup_minimal_symbol): New arg sfile.
+ * symm-tdep.c, somsolib.c, hppa-tdep.c, c-exp.y, f-exp.y,
+ m2-exp.y, nindy-tdep.c, m3-nat.c, irix5-nat.c, hpread.c,
+ os9kread.c, breakpoint.c, alpha-tdep.c, valops.c, symtab.c,
+ printcmd.c, dbxread.c: Change callers to pass NULL for sfile.
+ * dbxread.c (process_one_symbol) [SOFUN_ADDRESS_MAYBE_MISSING]:
+ Find address of function from minimal symbols.
+ * partial-stab.h, case 'f', 'F': Call find_stab_function_addr
+ instead of getting pst->textlow from the stab.
+ * minsyms.c (find_stab_function_addr): New function.
+
+Wed Feb 8 19:19:56 1995 Rob Savoye <rob@darkstar.cygnus.com>
+
+ * monitor.c: Fix so all the output shows up in the GUI command
+ window.
+
+Mon Feb 6 18:50:59 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ * i386-tdep.c (_initialize_i386_tdep): Put void decl on separate
+ line, so init.c generation works correctly.
+ * arc-tdep.c (_initialize_arc_tdep): Ditto.
+
+Mon Feb 6 14:44:36 1995 Rob Savoye <rob@darkstar.cygnus.com>
+
+ * config/mips/idt.mt: Add support for the lsi33k target.
+ * config/sparc/sun4sol2.mh: Add support for ser-tcp.
+ * array-rom.c: Finish the rest of the support commands needed by
+ GDB.
+ * mips-tdep.c: Add LSI33k register names and processor type.
+
+Sat Feb 4 13:29:52 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ * config/m68k/est.mt (TDEPFILES): Remove m68k-pinsn.o.
+
+Fri Feb 3 11:19:20 1995 Stu Grossman (grossman@cygnus.com)
+
+ * core.c (dis_asm_read_memory), defs.h, top.c: Get rid of
+ dis_asm_read_memory_hook. We can now call the disassemblers
+ directly and have no need for this hook anymore.
+ * defs.h, printcmd.c: Make print_insn be static.
+
+ * ser-go32.c (dos_comisr): Make this 8 bit clean.
+ * (dos_open dos_close): Allow multiple opens to the same device.
+ Use a ref count to prevent unwanted deallocations.
+ * sparcl-tdep.c: Put #ifdefs around all socket stuff to make GO32
+ happy.
+ * (sparclite_ops): Switch to download_stratum.
+ * target.h (enum strata): Move download_stratum before
+ process_stratum so that executable targets get pushed on top of
+ download targets.
+
+Thu Feb 2 19:02:45 1995 Rob Savoye <rob@darkstar.cygnus.com>
+
+ * array-rom.c: Remove the non GDB remote protocol config stuff.
+
+ * monitor.c: All reading/writing functions for memory and
+ registers work.
+
+Thu Feb 2 16:11:04 1995 Kung Hsu <kung@mexican.cygnus.com>
+
+ * config/arc/arc.mt: new target makefile for arc processor.
+ * config/arc/tm-arc.h: new target header for arc processor.
+ * config/arc/go32.mh: new go32 host makefile for arc processor.
+ * config/arc/xm-go32.h: new go32 host header for arc processor.
+ * arc-tdep.c: new target dependent codes for arc processor.
+
+Thu Feb 2 13:58:40 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ * Makefile.in (VERSION): Bump to 4.13.2.
+
+Thu Feb 2 07:27:56 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ Fix compiler warnings:
+ * remote-e7000.c (printf_e7000debug): Rename to puts_e7000debug
+ and have the caller do the sprintf. Saves us from varargs hell.
+ (normal): Define before use.
+ * remote-e7000.c: Reindent a few things.
+
+Wed Feb 1 21:16:42 1995 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * f-typeprint.c (f_type_print_varspec_suffix): Print array index
+ ranges in reverse order.
+ * f-valprint.c (f77_create_arrayprint_offset_tbl): Fix calculation.
+
+ * eval.c (evaluate_subscript): Don't call value_subscript, since
+ it adjusts for lower bound and enforces ranges.
+
+ * expression.h (exp_code): Remove MULTI_F77_SUBSCRIPT, OP_F77_SUBSTR.
+ * eval.c, parse.c: Removed uses of removed opcodes.
+ * eval.c (evaluate_subexp): Clean up handling of
+ OP_UNDETERMINED_ARGLIST (no backtracking, more general).
+
+ * f-valprint.c (f_val_print): Print TYPE_CODE_STRING using
+ LA_PRINT_STRING, and not val_print_string (which reads from inferior).
+
+ * ch-lang.c (chill_is_varying_struct), ch-lang.h: Remve function
+ duplicate function made redundant by chill_varying_type.
+
+ Re-write of f77 string and complex number support:
+
+ * language.h (struct language_defn): New fields string_lower_bound
+ and string_char_type.
+ * c-lang.c (c_language_defn, cplus_language_defn, asm_language_defn),
+ language.c (unknown_language_defn, auto_language_defn,
+ local_language_defn), m2-lang.c (m2_language_defn), f-lang.c
+ (f_language_defn), ch-lang.c (chill_language_defn): Set new fields.
+ * gdbtypes.c (create_string_type): Use new string_char_type field.
+ * valops.c (value_string): Use new string_lower_bound field.
+
+ * defs.h (TARGET_COMPLEX_BIT, TARGET_DOUBLE_COMPLEX_BIT): Removed.
+ * f-lang.c (f_create_fundamental_type, _initialize_f_language),
+ m2-lang.c (m2_create_fundamental_type),
+ gdbtypes.c (_initialize_gdbtypes): Set TYPE_TARGET_TYPE of complex
+ types. Set their TYPE_CODEs to TYPE_CODE_COMPLEX.
+ * mdebugread.c (mdebug_type_complex, mdebug_type_double_complex):
+ Removed. Use builtin_type_complex and builtin_type_double_complex.
+
+ * gdbtypes.h (enum type_code): Removed TYPE_CODE_LITERAL_STRING
+ and TYPE_CODE_LITERAL_COMPLEX.
+ * c-typeprint.c, f-typeprint.c, f-valprint.c, eval.c: Removed uses of
+ TYPE_CODE_LITERAL_STRING and TYPE_CODE_LITERAL_COMPLEX.
+ * gdbtypes.c, gdbtypes.h (f77_create_literal_complex_type,
+ f77_create_literal_string_type): Removed.
+ * value.h (VALUE_LITERAL_DATA, VALUE_SUBSTRING_MEMADDR,
+ VALUE_SUBSTRING_MYADDR): Removed.
+
+ * expression.h (enum exp_opcode): Rename OP_F77_LITERAL_COMPLEX to
+ OP_COMPLEX.
+ * parse.c: Update accordingly.
+
+ * f-valprint.c (f77_print_cmplx): Removed.
+ (f_val_print case TYPE_CODE_COMPLEX): Re-write to use print_floating.
+
+ * f-exp.y (STRING_LITERAL): Use OP_STRING instead of OP_ARRAY.
+ * eval.c (evaluate_subexp): For case OP_ARRAY, don't call
+ f77_value_literal_string.
+ * valops.c, value.h (f77_value_literal_string, f77_value_substring,
+ f77_assign_from_literal_string, f77_assign_from_literal_complex):
+ Removed.
+ (value_assign): No longer need to handle literal types.
+ * valops.c (f77_value_literal_complex), value.h: Re-written and
+ renamed to value_literal_complex. Last arg is now a (complex) type.
+ * valops.c (f77_cast_into_complex): Re-written and renamed to
+ cast_into_complex.
+ * eval.c (evaluate_subexp): Update accordingly.
+
+ * ch-valprint.c (chill_val_print): On TYPE_CODE_STRING, don't
+ print address for non-'s'-formats.
+ * ch-typeprint.c, ch-valprint.c: Use chill_varying_type instead
+ of chill_is_varying_struct.
+
+Wed Feb 1 13:27:33 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ gcc -Wall lint.
+ * alpha-tdep.c (alpha_in_lenient_prologue): Comment out.
+ (after_prologue): Remove unused local b.
+ * procfs.c (thread.h): Include.
+ (pr_flag_table, pr_why_table, faults_table, siginfo_table): Use
+ nested braces in initializer.
+ * top.c (initialize_targets, initialize_utils): Declare.
+ (locate_arg, insert_args): Add parens around tested assignments.
+ * remote-utils.c (sr_scan_args): Remove decl of strtol.
+ * remote.c (thread.h): Include.
+ (remote_wait): Remove unused local p2.
+ * sparc-tdep.c (fill_gregset, fill_fpregset): Remove decls of
+ registers array.
+
+ defs.h (stdlib.h): Include.
+ (exit, perror, atoi, qsort, memcpy, memcmp): Don't declare.
+ (fclose, atof, malloc, realloc, free, strchr, strrchr, strstr,
+ strtok, strerror): Don't specify parameter types in declaration.
+
+Wed Feb 1 12:23:57 1995 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * ch-exp.y (value_string_element, string_primitive_value,
+ start_element, left_element, right_element, slice_size,
+ lower_element, upper_element, first_element): Removed.
+ (value_string_slice, value_array_slice): Replaced by ...
+ (slice): New non-terminal, with working slice support.
+ (primitive_value_lparen, rparen): New non-terminals.
+ (maybe_tuple_elements): New non-terminal, to allow empty tuples.
+ (idtokentab): Added "up".
+
+ * value.h (COERCE_VARYING_ARRAY): New macro.
+ * valarith.c (value_subscript): Use it.
+ * valops.c (value_cast): Likewise. Also, do nothing if already
+ correct type, and allow converting from/to range to/from scalar.
+
+ * valops.c, value.h (varying_to_slice, value_slice): New functions.
+ * eval.c (OP_ARRAY): Add cast for array element.
+ * expression.h (TERNOP_SLICE, TERNOP_SLICE_COUNT): New exp_opcodes.
+ * valops.c (chill_varying_type): Moved function frp, here ...
+ * gdbtypes.c (chill_varying_type), gdbtypes.h: ... to here.
+ * parse.c (length_of_subexp, prefixify_subexp): Add support
+ for TERNOP_SLICE, TERNOP_SLICE_COUNT.
+ * expprint.c (print_subexp, dump_expression): Likewise.
+ * eval.c (evaluate_subexp): Likewise.
+
+ * eval.c (evaluate_subexp case MULTI_SUBSCRIPT): Don't call
+ value_x_binop on a Chill varying string.
+
+Tue Jan 31 13:51:53 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * config/m68k/monitor.mt,
+ config/pa/{hppabsd.mt,hppahpux.mt,hppaosf.mt,hppapro.mt}: Put
+ depfiles in TDEPFILES not REMOTE_O.
+
+Tue Jan 31 11:14:44 1995 Steve Chamberlain <sac@splat>
+
+ From nigel@algor.co.uk.
+ * ser-go32.c (dos_close): Don't crash if scb null.
+ (dos_sendbreak): New function.
+ (dos_ops): Point to dos_sendbreak.
+ (dos_info): Calculate COM number correctly.
+
+Tue Jan 31 09:40:11 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * xcoffread.c (process_xcoff_symbol): Use new variables
+ func_symbol_type and var_symbol_type as type of functions and
+ variables which don't have any stabs associated with them.
+ Reindent most of function.
+ (_initialize_xcoffread): Initialize *_symbol_type.
+
+ * xcoffread.c (read_xcoff_symtab): Reindent most of function.
+ Put C_HIDEXT symbols in the minimal symbols, rather than ignoring
+ them (this part commented out as I didn't quite get it to work).
+ (cs_to_section, find_targ_sec): New functions, to support above code.
+ * xcoffread.c (RECORD_MINIMAL_SYMBOL): Only skip '.' if it is
+ actually present.
+
+Mon Jan 30 17:34:24 1995 Stu Grossman (grossman@cygnus.com)
+ * sparcl-tdep.c: Add `sparclite' target for doing serial and udp
+ downloads to SPARClite demo boards.
+
+Sun Jan 29 09:43:22 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * remote.c, remote-pa.c: Remove #if 0'd icache code. It has had
+ no hope of working as is for a long time (in particular, shebs' 27
+ Jan 95 change confuses the issue further--target_read_memory and
+ xfer_core_file do *not* do the same thing in this context).
+ Revise comment.
+
+Sat Jan 28 13:40:46 1995 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * elfread.c (elf_symtab_read): Do not test BSF_GLOBAL for
+ procedure linkage table symbols, it is no longer set due to the
+ Jan 6 BFD change in bfd/elfcode.h.
+
+Fri Jan 27 17:08:06 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ * top.c (use_windows): Clarify comments.
+
+ * convex-tdep.c (xfer_core_file): Comment out.
+ * config/convex/tm-convex.h (XFER_CORE_FILE): Remove.
+ * remote.c, remote-pa.c (remote_fetch_word): Change xfer_core_file
+ references to target_read_memory.
+ * gdbcore.h (xfer_core_file, core_open, core_detach): Remove
+ declarations.
+ * corelow.c (core_open, core_detach): Make static.
+
+ * arm-tdep.c: Make it compile.
+ (exec_file_command, xfer_core_file): Comment out.
+ (arm_print_insn): Remove, now in libopcodes.
+ (skip_prologue): Comment out most of body.
+ (arm_frame_find_saved_regs): Move here from tm-arm.h.
+ (_initialize_arm_tdep): Set tm_print_insn.
+ * config/arm/tm-arm.h: Remove old refs to first_object_file_end.
+ (XFER_CORE_FILE): Remove.
+ (FRAME_FIND_SAVED_REGS): Call arm_frame_find_saved_regs.
+
+Fri Jan 27 08:48:28 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * Makefile.in (CHILL_LIB): Define as in testsuite/Makefile.in.
+
+Thu Jan 26 18:24:41 1995 Jim Kingdon <kingdon@deneb.cygnus.com>
+
+ * symtab.c (find_pc_line): When subtracting one to get a line
+ number, make sure not to end up with zero.
+
+ * remote-vx.c: Revert all of Kung's changes of 16 Jan. The
+ problems with those changes were (a) the file didn't compile, (b)
+ they changed memset to bzero--memset is correct, (c) they took out
+ code to deal with boards lacking floating point, (d) who knows
+ what I didn't discover in a quick read.
+
+Thu Jan 26 17:32:54 1995 Stu Grossman (grossman@cygnus.com)
+
+ * sparcl-tdep.c: Clean up formatting and indentation.
+
+Thu Jan 26 10:49:59 1995 Steve Chamberlain <sac@splat>
+
+ * remote-hms.c (hms_ops): Change ref of hr_load_image
+ to gr_load_image.
+ (dcache_flush, dcache_hit, dcache_value, dcache_fetch,
+ dcache_poke, dcache_init): Deleted.
+ (hms_open, hms_resume, hms_fetch_word, hms_store_word):
+ Use dcache routines provided by remote-util.h
+
+Thu Jan 26 12:08:31 1995 Michael Meissner <meissner@cygnus.com>
+
+ * configure.in: Add support for powerpc-*-eabi.
+
+ * powerpc/tm-ppc-eabi.h, powerpc/pcc-eabi.mt: New files for
+ PowerPC support.
+
+Wed Jan 25 18:13:14 1995 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * language.h (struct language_defn): New field c_style_arrays.
+ * language.c (unknown_language_defn, auto_language_defn,
+ local_language_defn), c-lang.c (c_language_defn, cplus_language_defn,
+ asm_language_defn): Set c_style_arrays to true.
+ * m2-lang.c (m2_language_defn), ch-lang.c (chill_language_defn),
+ f-lang.c (f_language_defn): Set c_style_arrays to false.
+ * valops.c (value_string): If c_style_array is not set,
+ allocate string in gdb (not inferior) using allocate_value.
+
+ * value.h (COERCE_ARRAY), valops.c (value_addr, value_arg_coerce):
+ Only call value_coerce_array if current_language->c_style_arrays.
+ * values.c: Add #include "language.h". (Needed for COERCE_ARRAY.)
+
+ * valops.c (chill_varying_type): New predicate.
+ * valops.c (value_cast): Support assigning a fixed string or array
+ to a variable string/array structure.
+
+ * valarith.c (value_subscripted_rvalue): Extra parameter lowerbound.
+ Check index>=lowerbound, and then add lowerbound to index here,
+ instead of in caller. Generalize to arbitrary lval_types.
+ (value_subscript): Use enhanced value_subscripted_rvalue if
+ c_style_arrays is false (and index is in range).
+
+
+Wed Jan 25 18:13:14 1995 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * eval.c (evaluate_subexp case OP_ARRAY): Fix calls to memset:
+ TYPE_LENGTH is length in bytes, not bits.
+
+Wed Jan 25 08:19:35 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * infrun.c (proceed): Flush stdout before resuming inferior.
+ * infcmd.c (step_1), annotate.c (annotate_starting):
+ Don't bother to flush here.
+
+Wed Jan 25 01:11:21 1995 Jeff Law (law@snake.cs.utah.edu)
+
+ * hpread.c (hpread_process_one_debug_symbol): Fix lines garbled
+ by an ill-advised global search and replace.
+
+Mon Jan 23 13:11:46 1995 Per Bothner <bothner@kalessin.cygnus.com>
+
+ Add support for Chill bitstring literals (e.h. H'FF00').
+ * ch-exp.y (match_bitstring_literal): Fix for proper endianness.
+ * expprint.c (print_subexp): Don't call error on OP_BITSTRING,
+ just print B'<unimlemented>'.
+ * gdbtypes.c (create_set_type): Fix bug in length calculation.
+ * valops.c, value.h (value_bitstring): New function.
+ * eval.c (evaluate_subexp): Implement support for OP_BITSTRING.
+
+ * ch-typeprint.c (chill_type_print_base): For TYPE_CODE_FUNC,
+ check that return type is non-void, and print in proper Chill syntax.
+
+Mon Jan 23 12:20:34 1995 Rob Savoye <rob@darkstar.cygnus.com>
+
+ * Makefile.in: Remove references to remote-mon.c.
+ * remote-mon.c: remove. Replaced by rom68k-rom.c.
+ * rom68k-rom.c: Support for Rom68k monitor.
+
+Mon Jan 23 10:50:57 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * Makefile.in (CHILL_FOR_TARGET): Update -L argument to point to
+ gcc/ch/runtime not chillrt, since that is where the chill runtime
+ lives now.
+
+Mon Jan 23 00:06:57 1995 Steve Chamberlain <sac@splat>
+
+ * remote-hms.c (hms_load): Delete.
+ (target_ops): Use hr_load_image.
+
+ * remote-e7000.c, remote-z8k.c, remote-nindy.c (target_ops):
+ Define memory_insert/remove_breakpoint.
+ * xm-go32.h: Remove redundant SIGs.
+
+Thu Jan 19 20:26:58 1995 Steve Chamberlain <sac@splat>
+
+ * ser-go32.c: Rewritten by nigel@algor.co.uk.
+
+Fri Jan 20 15:23:55 1995 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * expression.h (OP_LABELED): New operator, for Chill
+ labeled structre tuples.
+ * ch-exp.y (tuple_element, named_record_element, tuple_elements):
+ New non-terminals, to handle labeled structure tuples.
+ (tuple): Re-define using tuple_elements.
+ * eval.c (evaluate_labeled_field_init): New function, to handle
+ initialization of structure fields, possibly using OP_LABELED.
+ (evaluate_subexp): Use it.
+ * expprint.c (print_subexp case): For OP_ARRAY, use Chill syntax
+ for Chill. Handled OP_LABELED.
+ * parse.c (length_of_subexp, prefixify_subexp): Handle OP_LABELED.
+
+ * eval.c (evaluate_subexp): Handle Chill Powerset tuples.
+ * valarith.c (value_bit_index): Just treat bitstring as represented
+ by an array of bytes. Alignment is handled by compiler.
+
+Wed Jan 18 19:00:29 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ * h8300-tdep.c (gdb_print_insn_h8300): Fix typo (&info -> info).
+ * sh-tdep.c (gdb_print_insn_sh): Ditto.
+
+Wed Jan 18 11:25:43 1995 Kung Hsu <kung@mexican.cygnus.com>
+
+ * remote-os9k.c (rombug_open): Fix a bug in exception handling
+ command.
+ * remote-os9k.c (rombug_write_inferior_memory): reset buffer after
+ write.
+
+Tue Jan 17 09:48:38 1995 Jim Kingdon <kingdon@lioth.cygnus.com>
+
+ * parse.c (_initialize_parse): Improve wording of names of
+ msym_*_symbol_type.
+
+Tue Jan 17 14:00:58 1995 Ian Lance Taylor <ian@sanguine.cygnus.com>
+
+ * config/mips/tm-mips.h (enum mips_fpu_type): New enum.
+ (mips_fpu): Change type to enum mips_fpu_type.
+ (FIX_CALL_DUMMY): Handle mips_fpu == MIPS_FPU_SINGLE.
+ * mips-tdep.c (mips_fpu): Change type to enum mips_fpu_type.
+ Don't initialize.
+ (mips_fpu_string): New static variable.
+ (mips_push_dummy_frame): Handle mips_fpu == MIPS_FPU_SINGLE.
+ (mips_pop_frame): Likewise.
+ (mips_extract_return_value): Likewise.
+ (mips_store_return_value): Likewise.
+ (mips_set_fpu_command): New static function.
+ (mips_show_fpu_command): New static function.
+ (_initialize_mips_tdep): Change handling of set/show mipsfpu.
+
+Tue Jan 17 09:48:38 1995 Jim Kingdon <kingdon@lioth.cygnus.com>
+
+ * a29k-tdep.c (gdb_print_insn_a29k): Fix typo (&info -> info).
+
+ * parse.c (write_exp_msymbol): Use new variables
+ msym_*_symbol_type as type of msymbol expression.
+ (_initialize_parse): Initialize them.
+
+Mon Jan 16 18:11:03 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ General cleanup and simplication of disassembler interface.
+ * a29k-pinsn.c, arm-pinsn.c, convex-pinsn.c, gould-pinsn.c,
+ hppa-pinsn.c, i386-pinsn.c, i960-pinsn.c, m68k-pinsn.c,
+ m88k-pinsn.c, mips-pinsn.c, ns32k-pinsn.c, pyr-pinsn.c,
+ rs6000-pinsn.c, sparc-pinsn.c, tahoe-pinsn.c, vax-pinsn.c: Remove.
+ * gould-tdep.c, ns32k-tdep.c, tahoe-tdep.c, vax-tdep.c: New files,
+ had been -pinsn.c files.
+ * Makefile.in (ALLDEPFILES): Remove removed files.
+ (a29k-pinsn.o, arm-pinsn.o, convex-pinsn.o, gould-pinsn.o,
+ hppa-pinsn.o, i386-pinsn.o, i960-pinsn.o, m68k-pinsn.o,
+ m88k-pinsn.o, mips-pinsn.o, ns32k-pinsn.o, pyr-pinsn.o,
+ rs6000-pinsn.o, sparc-pinsn.o, tahoe-pinsn.o, vax-pinsn.o):
+ Remove compile actions.
+ * arm-tdep.o, gould-tdep.o, ns32k-tdep.o, tahoe-tdep.o,
+ vax-tdep.o: Add compile actions.
+ * defs.h (tm_print_insn): New global.
+ * a29k-tdep.c (gdb_print_insn_a29k): New function.
+ (_initialize_a29k_tdep): Rename from _initialize_29k,
+ set tm_print_insn.
+ * alpha-tdep.c (print_insn): Remove.
+ (_initialize_alpha_tdep): Set tm_print_insn.
+ * arm-tdep.c (arm_print_insn): New function, was print_insn
+ in arm-pinsn.c.
+ * convex-tdep.c (convex_print_insn): New function, was print_insn
+ in convex-pinsn.c.
+ * h8300-tdep.c (print_insn): Remove.
+ (gdb_print_insn_h8300): New function.
+ (_initialize_h8300_tdep): New function.
+ * h8500-tdep.c (print_insn): Remove.
+ (_initialize_h8500_tdep): New function.
+ * hppa-tdep.c (_initialize_hppa_tdep): Set tm_print_insn.
+ * i386-tdep.c (_initialize_i386_tdep): New function.
+ * i960-tdep.c (mem, next_insn): New functions, were in
+ i960-pinsn.c.
+ (_initialize_i960_tdep): Set tm_print_insn.
+ * m68k-tdep.c (_initialize_m68k_tdep): New function.
+ * m88k-tdep.c (_initialize_m88k_tdep): New function.
+ * mips-tdep.c (gdb_print_insn_mips): New function.
+ (_initialize_mips_tdep): Set tm_print_insn.
+ * pyr-tdep.c (pyr_print_insn): New function, was print_insn
+ in pyr-pinsn.c.
+ * rs6000-tdep.c (_initialize_rs6000_tdep): New function.
+ * sh-tdep.c (print_insn): Remove.
+ (gdb_print_insn_sh): New function.
+ (_initialize_sh_tdep): Set tm_print_insn.
+ * sparc-tdep.c (_initialize_sparc_tdep): New function.
+ * w65-tdep.c (print_insn): Remove.
+ (_initialize_w65_tdep): New function.
+ * z8k-tdep.c (print_insn): Remove.
+ (gdb_print_insn_z8k): New function.
+ (_initialize_z8k_tdep): Set tm_print_insn.
+ * printcmd.c (print_insn): New function, generic disassembler.
+ * config/*/*.mt (TDEPFILES): Remove refs to *-pinsn.o.
+
+Mon Jan 16 15:43:29 1995 Kung Hsu <kung@mexican.cygnus.com>
+
+ * Makefile.in: add new files remote-vx29k.c, config/a29k/tm-vx29k.h,
+ and config/a29k/vx29k.mt.
+ * configure.in: add new configuration a29k-*-vxworks.
+ * remote-vx29k.c: new file merged from WRS.
+ * remote-vx.c: merge changes from WRS.
+ * config/a29k/vx29k.mt: new file for new configuration.
+ * config/a29k/tm-vx29k.h: new header file for newconfiguration.
+
+Sun Jan 15 14:36:19 1995 Steve Chamberlain <sac@splat>
+
+ * breakpoint.h (disable_breakpoint, enable_breakpoint):
+ New declarations.
+ (enum bpdisp): Change name of 'delete' member to 'del'.
+ (struct bpstat): Changed name to 'bpstats'.
+ * breakpoint.c (disable_breakpoint, enable_breakpoint,
+ breakpoint_chain): Made globally visible.
+ (bpstat_stop_status): Use new name for bpstat.
+ (break_command_1, watch_command_1, catch_command_1,
+ breakpoint_auto_delete, denable_delete_breakpoint): Use 'del'
+ instead of 'delete'.
+ (set_breakpoint_sal): New function.
+ * defs.h (registers_changed_hook): New declaration.
+ * infcmd.c (run_stack_dummy): 'delete' is now 'del'.
+ * inflow.c (new_tty): Treat WIN32 in same way as __GO32__
+ * main.c (main): Don't scan options when in WIN32 and exit
+ without entering main loop.
+ * m2-exp.y (m2_elx): Member 'class' is now 'aclass'.
+ * symtab.h (struct symbol, struct partial_symbol): Changed name of
+ member 'class' to 'aclass'.
+ (SYMBOL_CLASS, PSYMBOL_CLASS): Reflect change.
+ * top.c (registers_changed_hook): New definition.
+ * utils.c (quit, notice_quit, initialize_utils): Treate WIN32
+ in same way as __GO32__.
+ * value.h (c_typedef_print): Rename 'new' argument.
+
+ * w65-tdep.c, config/tm-w65.h, config/w65.mt: New files.
+ * configure.in: Suppprt for w65,
+
+
+Sat Jan 14 11:18:11 1995 Jim Kingdon <kingdon@lioth.cygnus.com>
+
+ * infcmd.c (signal_command): For "signal 0", pass (CORE_ADDR)-1,
+ not stop_pc, to proceed.
+
+ * eval.c (evaluate_subexp): Clear expect_type except for C++ and CHILL.
+
+Fri Jan 13 17:52:57 1995 Jim Kingdon <kingdon@lioth.cygnus.com>
+
+ * infcmd.c (signal_command): Accept "signal 0"; the change to not
+ accept it was accidental. "handle 0" and "info signal 0" remain
+ illegal, though.
+
+Fri Jan 13 15:19:01 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ * Makefile.in (all): Don't make libgdb-files.
+ (libgdb): New action, makes libgdb-files.
+
+Thu Jan 12 21:23:25 1995 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * stabsread.c (read_enum_type): When pending enum symbols are
+ put into the enum type, they must be inserted in "backwards
+ order, in case we've overflowed a struct pending buffer.
+
+
+Thu Jan 12 09:33:24 1995 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * README: Add note about SPARCworks cc release 3.0 and higher.
+
+ Add procfs support for Alpha OSF/1-2.x.
+ * config/alpha/nm-osf.h: Renamed from nm-alpha.h, generic
+ OSF/1 native support.
+ * config/alpha/alpha-osf1.mh (NAT_FILE): Changed accordingly.
+ (MUNCH_DEFINE): Removed.
+ * config/alpha/alpha-osf2.mh, config/alpha/nm-osf2.h: New files
+ for procfs support.
+ * configure.in (alpha-dec-osf*): Use alpha-osf2.mh for OSF/1
+ release 2.x and higher, else alpha-osf1.mh, as the procfs support
+ in release 1.x is incomplete.
+ * Makefile.in (ALLCONFIG): Add config/alpha/alpha-osf2.mh.
+ * alpha-nat.c (supply_gregset, fill_gregset, supply_fpgregset,
+ fill_fpgregset): New routines for procfs support.
+ * inftarg.c (_initialize_inftarg): Don't add ptrace support
+ if we have an optional procfs and /proc is accessible.
+ * procfs.c: Include sys/fault.h and sys/syscall.h before
+ including sys/procfs.h.
+ (unconditionally_kill_inferior): If PROCFS_NEED_PIOCSSIG_FOR_KILL
+ is defined, additionally perform a PIOCSSIG to really terminate
+ the inferior.
+ (create_procinfo): Always return a result.
+ (create_procinfo, do_attach): Don't trace T_IFAULT faults if
+ PROCFS_DONT_TRACE_IFAULT is defined.
+ (procfs_init_inferior): Use START_INFERIOR_TRAPS_EXPECTED as
+ argument to startup_inferior if it is defined.
+ (proc_set_exec_trap): If PIOCSSPCACT is defined, use it instead
+ of tracing exits from exec system calls. Needed for the user level
+ loader under Alpha OSF/1.
+ (do_detach): Clear any pending signal if we want to detach from
+ a process without a signal.
+ (set_proc_siginfo): If PROCFS_DONT_PIOCSSIG_CURSIG is defined,
+ don't issue a PIOCSSIG if pr_cursig already contains the signal we
+ intend to set.
+ (info_proc_signals): If PROCFS_SIGPEND_OFFSET is defined, the
+ pending signals are numbered from 1 instead of 0.
+ (info_proc_mappings): Increase size of output format for addresses
+ if BFD_HOST_64_BIT is defined.
+ (procfs_stop): Renamed from child_stop.
+ (_initialize_procfs): Don't add procfs support if we have an
+ optional procfs and /proc is not accessible.
+
+
+Wed Jan 11 17:53:26 1995 Rob Savoye <rob@darkstar.cygnus.com>
+
+ * array-rom.c: Add support for most commands.
+
+ * monitor.c: Add GDB remote protocol for the hybrid environment on
+ the Array board.
+
+Wed Jan 11 00:44:01 1995 Jeff Law (law@snake.cs.utah.edu)
+
+ * command.c (show_user_1): Use print_command_line to show a user
+ defined command (including control structures).
+
+ * top.c (init_main): Change documentation for user defined
+ commands to indicate they may accept up to ten arguments.
+
+Tue Jan 10 16:22:41 1995 Jim Kingdon <kingdon@lioth.cygnus.com>
+
+ * mips-tdep.c (mips_skip_prologue): Accept or as well as addu for
+ `move $s8, $sp' instruction.
+
+Sun Jan 8 12:45:34 1995 Jim Kingdon <kingdon@deneb.cygnus.com>
+
+ * target.c, target.h (target_signal_from_command): New function.
+ * infrun.c (handle_command, signals_info), infcmd.c
+ (signal_command): Use it.
+ * infrun.c, infcmd.c: Update docstrings for these commands.
+
+ * target.h (enum target_signal), target.c (signals), target.c
+ (target_signal_from_host, target_signal_to_host): Add
+ TARGET_SIGNAL_REALTIME_* and TARGET_SIGNAL_PRIO for lynx.
+ * config/tm-lynx.h: Define signal numbers for realtime events.
+
+Sat Jan 7 07:23:53 1995 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * dbxread.c (process_one_symbol): Handle N_FUN symbols
+ for Sun acc 3.0 under SunOS4.
+
+ Changes to improve handling of runtime common symbols
+ under SunOS4.
+ * minsyms.c (get_symbol_leading_char): New routine to determine
+ the leading symbol character for an objfile.
+ (prim_record_minimal_symbol_and_info, install_minimal_symbols):
+ Use it.
+ * objfiles.h (rt_common_objfile): New global, points to objfile
+ containing the runtime common minimal symbols.
+ * objfiles.c (free_objfile): Mark rt_common_objfile as
+ unallocated before freeing it.
+ * solib.c (allocate_rt_common_objfile): New routine to allocate
+ an objfile for the runtime common minimal symbols.
+ (solib_add_common_symbols): Allocate an objfile for the runtime
+ common symbols if necessary and put common symbols into it.
+ Clean up code and comments.
+ (solib_add, special_symbol_handling): Cleanup comments regarding
+ runtime common symbols.
+ * stabsread.c (scan_file_globals_1): New routine, contains
+ old scan_file_globals code. Checks if there are any unresolved
+ global symbols before starting the expensive minimal symbol table
+ search.
+ (scan_file_globals): Now calls scan_file_globals_1 for the passed
+ objfile and eventually for the runtime common objfile. Complains
+ about any unresolved global symbols and removes them from the
+ global symbol chain to avoid dangling pointers into the symbol
+ table if the symbol table is reread.
+
+Thu Jan 5 17:38:29 1995 Stu Grossman (grossman@cygnus.com)
+
+ * Makefile.in (install_only uninstall): Indent for clarity.
+
+ * core.c (dis_asm_read_memory): Add call to
+ dis_asm_read_memory_hook to provide alternate way for disassembler
+ to read memory.
+
+ * defs.h: Protect from multiple inclusion. Add decl for
+ dis_asm_read_memory_hook.
+
+ * top.c: Make window startup be the default.
+ * Add dis_asm_read_memory_hook.
+
+
+Thu Jan 5 01:16:40 1995 Jeff Law (law@snake.cs.utah.edu)
+
+ * stabsread.c (define_symbol): Handle `a' symbol type used for
+ reference parameter passed in a register.
+
+
+Wed Jan 4 12:27:29 1995 Kung Hsu <kung@mexican.cygnus.com>
+
+ * defs.h: move include tm.h up, so that the type LONGEST can
+ also based on the target requirement to determine. In this case
+ target mips64.
+
+ * remote-os9k.c (rombug_open): catch exception e in rombug.
+ * remote-os9k.c (rombug_wait): print message before register display
+ from rombug.
+
+Wed Jan 4 09:18:27 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * top.c (locate_arg): Call strchr not index.
+
+Tue Jan 3 16:52:03 1995 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * ch-exp.y (literal): Recognize NULL.
+ (tuple): Parse simple unlabelled tuples.
+ * eval.c (evaluate_subexp case OP_ARRAY): Use expect_type to
+ evaluate brace-initializer-expressions depending on context.
+ (evaluate_subexp case UNOP_CAST): Pass the target type as
+ expected type when evaluating the expression.
+
+ * ch-typeprint.c (chill_type_print_base): Get names of PTR and
+ BOOL from TYPE_NAME.
+ * ch-valprint.c (chill_print_type_scalar): New function, to handle
+ TYPE_CODE_RANGE better than print_type_scalar does.
+ (chill_val_print_array_elements): Use above new function.
+
+Mon Jan 2 15:02:51 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ * remote-udi.c (udi_load): Tell symbol_file_add that the
+ program being loaded is the main program.
+
+For older changes see ChangeLog-94
+
+Local Variables:
+mode: indented-text
+left-margin: 8
+fill-column: 74
+version-control: never
+End:
diff --git a/gdb/ChangeLog-96 b/gdb/ChangeLog-96
new file mode 100644
index 00000000000..760b425f759
--- /dev/null
+++ b/gdb/ChangeLog-96
@@ -0,0 +1,5116 @@
+Tue Dec 31 15:19:32 1996 Geoffrey Noer <noer@cygnus.com>
+
+ * config/mn10300/tm-mn10300.h: more small register fixes
+
+Tue Dec 31 06:51:43 1996 Mark Alexander <marka@cygnus.com>
+
+ * config/i386/xm-windows.h: Undo previous change to SIGTRAP
+ and SIGQUIT values; it messed up non-MIPS targets.
+ * config/mips/tm-mips.h: Undefine BREAKPOINT, replace
+ with separate LITTLE_BREAKPOINT and BIG_BREAKPOINT definitions;
+ this fixes problem with setting breakpoints in little-endian
+ programs in the simulator.
+
+Mon Dec 30 00:14:06 1996 Doug Evans <dje@seba.cygnus.com>
+
+ * remote-sim.c (gdbsim_open_p): New static local.
+ (gdbsim_open): Call unpush_target if sim open. Set gdbsim_open_p.
+ (gdbsim_close): Only call sim_close if sim open. Reset gdbsim_open_p.
+
+Sun Dec 29 09:15:03 1996 Mark Alexander <marka@cygnus.com>
+
+ * config/i386/xm-windows.h: Make SIGTRAP and SIGQUIT consistent
+ with sim/mips/support.h.
+
+Fri Dec 27 14:53:40 1996 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * v850-tdep.c (struct pifsr): Add cur_frameoffset field.
+ (v850_scan_prologue): Add debug code #ifdef'ed DEBUG. Support new
+ compiler prologues using register save functions and short store
+ instructions. Add support for functions with large stack frames.
+
+ * config/v850/tm-vm850.h ({R0,R1,R12,EP}_REGNUMS): New register
+ number defintiions for r0, r1, r12, ep.
+ (SAVE{1,2,3}_{START,END}_REGNUM): Register number definitions for
+ the 3 sets of saved registers.
+
+Thu Dec 26 19:56:55 1996 Mark Alexander <marka@cygnus.com>
+
+ * valprint.c (print_longest): Don't lose upper bits
+ of 64-bit values on Windows.
+ * config/i386/xm-windows.h: Leave CC_HAS_LONG_LONG defined,
+ undefine PRINTF_HAS_LONG_LONG, so that 64-bit values will
+ be printed without loss of upper bits.
+
+Thu Dec 26 15:15:21 1996 Michael Snyder <msnyder@cleaver.cygnus.com>
+
+ * config/sparc/tm-sparclet.h: make registers ASR15, ASR19 invisible
+ (they're not useful, you can't change, write or even read them)
+
+Thu Dec 26 15:20:48 1996 Fred Fish <fnf@cygnus.com>
+
+ * config/pa/hppahpux.mh (TERMCAP): Always link to libc before
+ libcurses, to avoid picking up broken select() from libcurses
+ on some versions of HPUX.
+
+Thu Dec 26 15:14:41 1996 Michael Snyder <msnyder@cleaver.cygnus.com>
+
+ * sparclet-rom.c: Remove includes of Unix system files.
+ Add function "sparclet_supply_register" so that parse_register_dump
+ will not seg-fault by calling a null function pointer.
+ Remove XMODEM support (unfinished work?).
+ Remove flag "MO_HANDLE_NL", so monitor's output can be read by humans.
+ Add fill command.
+ Remove colon from getreg.resp_delim so PSR register will work.
+ Remove pointer to sparclet_load (downloading SREC's doesn't work).
+ Null out local register names for %g0, all %cc and all %asr regs,
+ since the monitor can't report them. Will return zero instead.
+ * sparclet-stub.c: New -- remote protocol support for sparclet CPU.
+ * config/sparc/tm-sparclet.h: Re-arrange REGISTER_NAMES:
+ Add back %g0 and %psr, add %cc coprocessor regs, add %asr regs.
+ Adjust NUM_REGS and REGISTER_BYTES accordingly
+
+Tue Dec 24 10:27:37 1996 Jeffrey A Law (law@cygnus.com)
+
+ * remote-e7000.c (want_h8300h, want_nopc_h8300h): Renamed
+ from want and want_nopc.
+ (want_h8300s, want_nopc_h8300s): New variables for H8/S register
+ lists.
+ (e7000_fetch_registers): Use H8/300H or H8/S register list string
+ as needed.
+ (e7000_wait): Likewise.
+
+Mon Dec 23 02:25:58 1996 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * mips-tdep.c (mips_find_saved_regs): If a frame has been
+ interrupted by a signal, figure out whether the registers that
+ the proc_desc claims are saved have been saved yet.
+ (mips_push_dummy_frame): Write dummy frame register after all
+ registers have been saved in the dummy frame. Update comments
+ to reflect the fact that we are now using an AT_ENTRY_POINT
+ call dummy.
+
+Sun Dec 22 15:52:25 1996 Martin M. Hunt <hunt@pizza.cygnus.com>
+
+ * d10v-tdep.c (d10v_skip_prologue): PR11287. Fix problem where
+ some breakpoints weren't being set.
+
+Sat Dec 21 12:57:59 1996 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * config/mips/tm-mips.h (PC_IN_CALL_DUMMY): Removed, the default
+ definition in inferior.h is sufficient.
+ * mips-tdep.c (mips_pc_in_call_dummy): Ditto.
+ (mips_push_arguments): Make sure that the stack is aligned to a
+ multiple of 8 after the arguments are pushed.
+ Structures are always passed by value in the old ABI.
+ Adjust argument register value on big endian targets when passing
+ a value whose length is less than the register size.
+ Write stack arguments with a single write_memory call.
+ (mips_pop_frame): Use frame_saved_regs instead of proc_desc to
+ decide which registers have to be restored.
+
+ * irix5-nat.c (fill_gregset): Sign extend registers before
+ filling in the gregset structure.
+
+Fri Dec 20 11:06:03 1996 Stu Grossman (grossman@critters.cygnus.com)
+
+ * mswin/genmakes: Don't define _DEBUG. This breaks wingdb.
+
+Thu Dec 19 19:42:44 1996 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * v850-tdep.c (v850_scan_prologue): Deal with -mep shorting
+ register saves by using the ep register.
+
+Thu Dec 19 15:57:16 1996 Doug Evans <dje@canuck.cygnus.com>
+
+ * m32r-tdep.c (m32r_frame_find_saved_regs): Fix thinko in arg def.
+
+Thu Dec 19 09:38:56 1996 Mark Alexander <marka@cygnus.com>
+
+ * values.c (unpack_double): Make it compile with MSVC++ 2.x.
+ * remote-mips.c (S_IROTH): Define if not defined by stat.h, e.g.
+ when using MSVC++.
+ (common_open): Fix help string.
+
+Wed Dec 18 23:01:32 1996 Stan Shebs <shebs@andros.cygnus.com>
+
+ * mpw-make.sed: Use NewFolderRecursive for installation.
+
+Sat Dec 14 20:50:01 1996 Mark Alexander <marka@cygnus.com>
+
+ * mips-tdep.c (mips_push_arguments): Handle floating point args.
+ * config/mips/tm-mips.h (FIX_CALL_DUMMY): Define to set up $25
+ correctly for PIC on Irix 5.
+
+Sat Dec 14 09:52:30 1996 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * i386-tdep.c (i386_frame_find_saved_regs): Handle zero return
+ from get_pc_function_start gracefully.
+
+Sat Dec 14 00:43:57 1996 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * c-exp.y (qualified_name): Replace explicit check for valid
+ destructor name with call to destructor_name_p.
+
+ * c-lang.h, c-typeprint.c (cp_type_print_method_args): Removed,
+ no longer needed.
+
+ * c-typeprint.c (c_type_print_varspec_prefix, c_type_print_base):
+ Replace remaining fprintf_unfiltered calls with their filtered variant.
+ (c_type_print_base): Do not print return type for destructors from
+ template classes.
+ Replace cp_type_print_method_args with cplus_demangle call to get
+ consistent type output for stubbed and unstubbed methods.
+
+ * cp-valprint.c (cp_print_class_method): Replace
+ cp_type_print_method_args with cplus_demangle call to get consistent
+ type output for stubbed and unstubbed methods.
+
+ * gdbtypes.c, gdbtypes.h (get_destructor_fn_field): New function
+ to find the destructor field indices for a type.
+
+ * gdbtypes.h (struct type): Clarify comments for vptr_basetype
+ and arg_types fields.
+ (struct fn_field): Remove args field, no longer used.
+
+ * symtab.c (decode_line_1), valops.c (value_struct_elt,
+ check_field_in): Use get_destructor_fn_field to find the destructor
+ field indices instead of assuming that the compiler passes the member
+ function fields in a specific order.
+
+ * symtab.c (find_methods): Pass NULL instead of SYMBOL_BLOCK_VALUE
+ to lookup_symbol.
+ (list_symbol): Replace cp_type_print_method_args with cplus_demangle
+ call in zapped out code and explain why this code is zapped out.
+
+Thu Dec 12 13:29:14 1996 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * config/powerpc/ppc{,le}-sim.mt (SIM): Add the simulator common
+ library ../sim/common/libcommon.a.
+
+Wed Dec 11 11:15:08 1996 Doug Evans <dje@canuck.cygnus.com>
+
+ * monitor.c (monitor_load): Add support for load address argument.
+ * dsrec.c: #include <time.h>.
+ (load_srec): New argument load_offset. Print download stats.
+ * srec.h (load_srec): Update prototype.
+ * sh3-rom.c (sh3_load): Update call to load_srec.
+
+Mon Dec 9 17:34:05 1996 Geoffrey Noer <noer@cygnus.com>
+
+ * config/mn10300/tm-mn10300.h: more small register fixes
+ * mn10300-tdep.c: filled in from another target
+
+Mon Dec 9 17:12:19 1996 Doug Evans <dje@canuck.cygnus.com>
+
+ * monitor.c (monitor_insert_breakpoint): Handle bi-endian machines.
+
+Mon Dec 9 15:58:51 1996 Mark Alexander <marka@cygnus.com>
+
+ * config/mips/tm-mips.h: Get rid of call-dummy code.
+ Minor changes to make pre-ANSI compilers happy.
+ * mips-tdep.c: Minor changes to make pre-ANSI compilers happy.
+ (mips_push_arguments): Rewrite to partially support EABI.
+ (mips_pc_in_call_dummy): New function.
+ * infcmd.c: Include symfile.h to get prototype of entry_point_address,
+ which fixes 64-bit sign extension bug on MIPS.
+
+Mon Dec 9 00:14:49 1996 Geoffrey Noer <noer@cygnus.com>
+
+ * config/mn10300/tm-mn10300.h: fix register names
+ * mn10300-tdep.c: new skeleton tdep for mn10300
+
+Sun Dec 8 18:02:57 1996 Doug Evans <dje@canuck.cygnus.com>
+
+ * remote-sim.h: Update some comments.
+ * remote-sim.c (gdb_os_error): New function.
+ (init_callbacks): Fix initializing of gdb_callback. Add gdb_os_error.
+ (gdb_os_printf_filtered): Use gdb_stdout, not stdout.
+
+Sun Dec 8 00:36:31 1996 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * irix5-nat.c (supply_gregset, fill_gregset): Handle gregsets
+ from O32 and N32 ABI.
+ (xfer_link_map_member): Work around problem with alignments
+ in struct obj when compiling GDB under N32 ABI.
+
+Thu Dec 5 23:30:44 1996 Stan Shebs <shebs@andros.cygnus.com>
+
+ * d10v-tdep.c: Add support for examination and interpretation
+ of instruction trace buffer.
+ (trace, untrace, info trace, tdisassemble): New commands.
+
+Thu Dec 5 14:06:23 1996 Doug Evans <dje@canuck.cygnus.com>
+
+ * config/sparc/tm-sparclet.h (TARGET_BYTE_ORDER): Undef.
+ (TARGET_BYTE_ORDER_SELECTABLE): Define.
+ (BREAKPOINT): Undef.
+ ({BIG,LITTLE}_BREAKPOINT): Define.
+ (TM_PRINT_INSN_MACH): Redefine for sparclet.
+
+Wed Dec 4 16:34:05 1996 Geoffrey Noer <noer@cygnus.com>
+
+ * config/mn10300/mn10300.mt, config/mn10300/tm-mn10300.h: New.
+
+Tue Dec 3 13:02:08 1996 Fred Fish <fnf@ninemoons.com>
+
+ * infptrace.c (store_inferior_registers): Move some common code out
+ to store_register, like fetch_inferior_registers & fetch_register.
+ (store_register): New function, from store_inferior_registers.
+ (fetch_inferior_registers, fetch_register): Minor code tweaks to
+ make {fetch,store}_inferior_registers and {fetch,store}_register
+ routines as similar in structure as possible.
+ (fetch_inferior_registers, store_inferior_registers): Eliminate
+ local variable numregs and just use ARCH_NUM_REGS directly.
+
+Tue Dec 3 11:38:14 1996 Michael Snyder <msnyder@cleaver.cygnus.com>
+
+ * blockframe.c: add macro USE_GENERIC_DUMMY_FRAMES to enable/disable
+ code for generic call_dummy frames.
+ * config/h8300/tm-h8300.h: turn on USE_GENERIC_DUMMY_FRAMES
+ * config/m32r/tm-m32r.h: Ditto.
+ * config/sh/tm-sh.h: Ditto.
+ * config/v850/tm-v850.h: Ditto.
+
+Sun Dec 1 00:41:47 1996 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * vax-tdep.c (vax_print_insn, print_insn_arg): Use info functions
+ for printing. From Valeriy Ushakov <uwe@ptc.spbu.ru>.
+
+Sun Dec 1 00:40:46 1996 Geoffrey Noer <noer@cygnus.com>
+
+ * configure.tgt: Add new mn10300 entry.
+
+Sun Dec 1 00:18:59 1996 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ Add support for Irix 6.2 native O32 and N32 ABI.
+
+ * config.in, configure.in, configure: Check for <objlist.h>.
+ * configure.tgt: Handle mips*-sgi-irix6* like irix5 for now.
+
+ * cp-valprint.c (cp_print_value_fields): Use SYMBOL_VALUE_ADDRESS
+ instead of SYMBOL_BLOCK_VALUE to get the address of a static member.
+
+ * dwarf2read.c: Turn warnings and recoverable errors into complaints,
+ add new complaints where appropriate.
+ gcc -Wall cleanup.
+ (struct line_head): Change line_base from char to int to avoid
+ problems with compilers whose plain char is represented by an
+ unsigned char.
+ (struct partial_die_info): Add is_declaration field.
+ (dwarf2_tmp_obstack): New obstack for allocating temporary storage
+ used during symbol reading.
+ (cu_header_offset): New variable for resolving relative reference
+ dies.
+ (optimized_out, basereg, islocal, frame_base_reg, frame_base_offset):
+ New interface variables for decode_locdesc.
+ (struct dwarf2_pinfo): New structure for communication between
+ psymtab and symtab reading, passed via pst->read_symtab_private.
+ (dwarf2_has_info, dwarf2_build_psymtabs): Accept objects files
+ without line number sections.
+ (dwarf2_build_psymtabs_hard): Initialize temporary obstack
+ for symbol reading.
+ Allocate and initialize pst->read_symtab_private.
+ Relocate pst->textlow and pst->texthigh with baseaddr.
+ (scan_partial_symbols): Do not add DW_AT_declaration symbols
+ to the partial symbol table.
+ Add file scope enumerator symbols to the partial symbol table.
+ Fix typo in highpc computation.
+ If we didn't find a lowpc, set it to highpc to avoid complaints
+ from `maint check.
+ (add_partial_symbol): Relocate symbol values with baseaddr.
+ Add static DW_TAG_subprogram and DW_TAG_variable symbols to the
+ minimal symbol table.
+ Obtain symbol values for DW_TAG_variable symbols from the location
+ descriptor, skip symbols with missing location desciptors.
+ Skip symbols for aggregate types without children.
+ Handle enumerator symbols.
+ (dwarf2_psymtab_to_symtab): Issue symbol reading message if verbose.
+ (psymtab_to_symtab_1): Set local variables from
+ pst->read_symtab_private, set cu_header_offset and baseaddr.
+ Initialize temporary obstack for symbol reading, initialize
+ buildsym and add a cleanup to really_free_pendings.
+ Relocate highpc with baseaddr when calling end_symtab.
+ If the compilation is from a C file generated by language
+ preprocessors, do not set the symtab language if it was already
+ deduced by start_subfile.
+ Removed verbose sorting symbol table message.
+ (process_die): Handle DW_TAG_ptr_to_member_type and
+ DW_TAG_reference_type.
+ Use read_subroutine_type to get the function type for
+ DW_TAG_subprogram before calling read_func_scope.
+ (read_file_scope): Initialize file name to <unknown>, start_subfile
+ expects a non-NULL name.
+ If we didn't find a lowpc, set it to highpc to avoid complaints
+ from finish_symbol.
+ Relocate lowpc and highpc with baseaddr.
+ Get rid of Irix6.2 native cc compile machine prefix in comp_dir.
+ Zero out ftypes for each new compilation unit (may be different
+ language or different objfile).
+ Accept compilation units without line number information, pass
+ comp_dir to decode_lines.
+ (read_func_scope): Initialize function name to <unknown> to avoid
+ core dumps when DW_AT_name is missing.
+ Relocate lowpc and highpc with baseaddr.
+ Handle DW_AT_frame_base, keep result for DW_OP_fbreg operations.
+ Pass function type to new_symbol.
+ (read_lexical_block_scope): Relocate lowpc and highpc with baseaddr.
+ (read_structure_scope): Set TYPE_TAG_NAME, not TYPE_NAME.
+ Handle DW_TAG_class_type.
+ Copy fields to type_obstack, release temporary storage for fields.
+ Don't add symbol if die is a stub die and has no children.
+ Handle C++ static member fields.
+ (read_enumeration): Set TYPE_TAG_NAME, not TYPE_NAME.
+ Copy fields to type_obstack, release temporary storage for fields.
+ Let new_symbol handle the symbol creation for enumerators
+ instead of handcrafting a symbol.
+ Determine signedness of enum type from enumerators.
+ (dwarf_read_array_type): Handle variable length arrays.
+ Use lookup_pointer_type instead of handcrafting a type.
+ Create array type only if a DW_TAG_subrange_type was found.
+ (read_tag_pointer_type, read_tag_reference_type):
+ Use lookup_pointer_type and lookup_reference_type instead
+ of handcrafting a type.
+ (read_tag_ptr_to_member_type): New function to handle
+ DW_TAG_ptr_to_member_type.
+ (read_subroutine_type): Handle parameter dies.
+ Use lookup_function_type instead of handcrafting a type.
+ (read_typedef): Allocate a TYPE_CODE_TYPEDEF type for the typedef.
+ (read_base_type): If the type has a name, use init_type to create
+ a new type instead of second guessing a fundamental type.
+ (read_comp_unit): Reset die reference table before building
+ a new one.
+ (dwarf2_read_section): Read section contents into psymbol_obstack.
+ (dwarf2_read_abbrevs): Handle unterminated abbreviations
+ for a compile unit gracefully.
+ (read_partial_die): Zero partial die before reading its info.
+ Handle DW_AT_declaration.
+ Fix typo in handling of DW_FORM_block4.
+ (read_full_die): Fix typo in handling of DW_FORM_block4.
+ (read_1_signed_byte, read_2_signed_bytes, read_4_signed_bytes):
+ New routines to get signed values from a buffer.
+ (read_n_bytes, read_string): Allocate storage from the temporary
+ obstack. If the host char size permits it, return pointer
+ to buffer instead of allocating storage.
+ (set_cu_language): Handle DW_LANG_Mips_Assembler.
+ (dwarf_attr): Return NULL if reference die for DW_AT_specification
+ or DW_AT_abstract_origin die is not found.
+ (record_minimal_symbol): Removed, replaced with a direct call to
+ prim_record_minimal_symbol, it now handles saving the string itself.
+ (convert_locdesc): Removed, partial symtab reading now uses
+ decode_locdesc.
+ (dwarf_attr): Use dwarf2_get_ref_die_offset to get the absolute
+ offset for the die reference.
+ (dwarf_decode_lines): Complain if the line section info is missing.
+ Use read_1_signed_byte to extract lh.line_base to avoid
+ problems with compilers whose plain char is represented by an
+ unsigned char.
+ Add cleanups for allocated temporary storage.
+ Start a subfile for the first file in the state machine.
+ Fix off by one problem with dirs.dirs access.
+ Use comp_dir when directory index is 0.
+ Support multiple sequences (from Jason Merrill <jason@cygnus.com>).
+ (dwarf2_start_subfile): Try to keep line numbers from identical
+ absolute and relative file names in a common subfile.
+ (new_symbol): Allocate symbol and symbol name on the symbol_obstack.
+ Set SYMBOL_LINE from DW_AT_decl_line if present.
+ Set SYMBOL_TYPE from passed type if not NULL.
+ Change DW_TAG_variable symbol types with missing type entries
+ to a sensible type.
+ Handle optimized_out, offreg and islocal storage classes.
+ Add external symbols with type information whose address isn't
+ known as LOC_UNRESOLVED symbols.
+ Synthesize typedefs for C++ classes, structs, unions and enumerations.
+ Handle DW_TAG_enumerator symbols, complain for unrecognized
+ symbol tags.
+ (die_type): A missing DW_AT_type represents a void type.
+ Use dwarf2_get_ref_die_offset to get the absolute offset for
+ the die reference.
+ (die_containing_type): New function to build type from
+ DW_AT_containing_type attribut.
+ (read_type_die): Handle DW_TAG_ptr_to_member_type.
+ Treat DW_TAG_subprogram like DW_TAG_subroutine_type.
+ (dwarf_base_type): Fix typo with creation of FT_UNSIGNED_SHORT
+ fundamental type.
+ (create_name): Removed, symbol name allocation is now done
+ in new_symbol.
+ (dump_die): Use print_address_numeric to print a CORE_ADDR.
+ (dwarf2_empty_die_ref_table): New function to clear the die
+ reference table.
+ (dwarf2_get_ref_die_offset): New function to get the absolute
+ die offset from a die reference attribute.
+ (decode_locdesc): Complete rewrite using a stack, code mostly
+ borrowed from dwarfread.c:locval.
+ (dwarf_alloc_type): Removed, replaced by direct calls to alloc_type.
+ (dwarf_alloc_block): Allocate block on temporary obstack.
+
+ * elfread.c (elf_symtab_read): When handling Irix dynamic symbols,
+ skip section name symbols and relocate all others.
+ (elf_symfile_read): Build dwarf2 psymtab even if offset is non-zero.
+
+ * irix5-nat.c (fetch_core_registers): Handle core_reg_sect
+ from N32 executables. Call registers_fetched after extracting
+ the registers.
+ (obj_list_variant, struct link_map, LM_OFFSET, LM_ADDR): New
+ definitions to enable support of O32 and N32 format objlists.
+ (struct so_list): New members offset, so_name and lmstart to
+ eliminate dependencies from the objlist format used.
+ (solib_map_sections, symbol_add_stub, solib_add,
+ info_sharedlibrary_command, solib_address, clear_solib): Use
+ so_name and LM_OFFSET.
+ (first_link_map_member): Rewrite to enable support of O32 and N32
+ format objlists.
+ (next_link_map_member, xfer_link_map_member): New functions to
+ support O32 and N32 format objlists.
+ (find_solib): Use first_link_map_member, next_link_map_member and
+ xfer_link_map_member.
+ (solib_create_inferior_hook): Use TARGET_SIGNAL_* instead of
+ host signal numbers.
+
+ * mdebugread.c (parse_partial_symbols, handle_psymbol_enumerators):
+ Pass CORE_ADDR variant to add_psymbol_to_list.
+
+ * mips-tdep.c (heuristic_proc_desc): Stop examining the prologue
+ if we encounter a positive stack adjustment. Handle `move $30,$sp'.
+ Handle `sd reg,offset($sp)' for 32 bit ABIs.
+
+ * symmisc.c (dump_msymbols, print_partial_symbols): Use
+ print_address_numeric to print a SYMBOL_VALUE_ADDRESS.
+ (dump_symtab): Print compilation directory if it is not NULL.
+
+ * valops.c (search_struct_field, value_struct_elt_for_reference):
+ Use SYMBOL_VALUE_ADDRESS instead of SYMBOL_BLOCK_VALUE to get the
+ address of a static member.
+
+Thu Nov 28 00:46:24 1996 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * vax-tdep.c (vax_print_insn): Made static, modified to take
+ disassemble_info as parameter.
+ (_initialize_vax_tdep): New function to initialize tm_print_insn
+ to vax_print_insn.
+
+Wed Nov 27 11:29:06 1996 Michael Snyder <msnyder@cleaver.cygnus.com>
+
+ * blockframe.c: Remove old-style CALL_DUMMY code.
+ * h8300-tdep.c, config/h8300/tm-h8300.h: Ditto.
+ * m32r-tdep.c, config/m32r/tm-m32r.h: Ditto.
+ * sh-tdep.c, config/sh/tm-sh.h: Ditto.
+ * v850-tdep.c, config/v850/tm-v850.h: Ditto.
+
+Wed Nov 27 10:32:14 1996 Michael Snyder <msnyder@cleaver.cygnus.com>
+
+ * breakpoint.c: DELETE command will not delete CALL_DUMMY breakpoint.
+ * blockframe.c: Add target-independant support for managing
+ CALL_DUMMY frames on the host side.
+ * frame.h: Declarations for generic CALL_DUMMY frame support.
+ * h8300-tdep.c: Add target function calls using generic frame support.
+ * config/h8300/tm-h8300.h: config for generic target function calls.
+ * m32r-tdep.c: Add target function calls using generic frame support.
+ * config/m32r/tm-m32r.h: config for generic target function calls.
+ * sh-tdep.c: Add target function calls using generic frame support.
+ * config/sh/tm-sh.h: config for generic target function calls.
+ * v850-tdep.c: Add target function calls using generic frame support.
+ * config/v850/tm-v850.h: config for generic target function calls.
+ * valops.c: ADD PUSH_RETURN_ADDRESS so that it doesn't have to be
+ done by PUSH_ARGUMENTS when there's no CALL_DUMMY.
+
+Tue Nov 26 19:21:35 1996 Mark Alexander <marka@cygnus.com>
+
+ * config/mips/tm-mips.h (ADDR_BITS_REMOVE, TARGET_READ_SP): Define.
+ (mips_addr_bits_remove): Declare.
+ * mips-tdep.c (mips_push_dummy_frame): Fix heuristic-fence-post
+ errors when hitting breakpoints during inferior function calls
+ in 64-bit programs.
+ (fix_sign_extension): Make public, rename to mips_addr_bits_remove.
+ * utils.c (paddr_nz, preg_nz): New functions, similar to
+ paddr and preg but don't print leading zeroes.
+ * defs.h (paddr_nz, preg_nz): Declare.
+ * remote-mips.c: Use paddr_nz instead of paddr throughout
+ to reduce packet size.
+ (pmon_end_download): Improve timeout error handling.
+
+Tue Nov 26 17:21:37 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * configure: Rebuild with autoconf 2.12.
+
+Mon Nov 25 13:17:16 1996 Fred Fish <fnf@ninemoons.com>
+
+ From: Paul Eggert <eggert@twinsun.com>
+ * remote-bug.c (wait_strings): Avoid creating a trigraph.
+
+Fri Nov 22 15:55:22 1996 Martin M. Hunt <hunt@pizza.cygnus.com>
+
+ * valops.c (value_at, value_fetch_lazy): Put in D10V call
+ to fix up address pointers.
+ * values.c (value_from_longest): Removed previous d10v changes.
+ * config/d10v/tm-d10v.h (TARGET_PTR_BIT): Change to 4 bytes.
+
+Fri Nov 22 10:06:19 1996 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * config/i386/nm-i386v4.h (LOSING_POLL): Define, needed for
+ Unixware 1.1.2.
+
+Thu Nov 21 19:13:58 1996 Mark Alexander <marka@cygnus.com>
+
+ * mips-tdep.c: Replace hard-coded constants with MIPS_INSTLEN.
+ (common_breakpoint): Use paddr instead of %x to print 64-bit values.
+ (heuristic_proc_desc): Add tests for 64-bit instructions.
+ (init_extra_frame_info, mips_push_arguments): Recognize additional
+ registers for EABI.
+ * remote-mips.c: Extend DDB target to allow TFTP downloads.
+ * config/mips/tm-mips.h (MIPS_LAST_ARG_REGNUM, MIPS_NUM_ARG_REGS):
+ Define.
+
+Wed Nov 20 19:09:16 1996 Martin M. Hunt <hunt@pizza.cygnus.com>
+
+ * infcmd.c (do_registers_info): Call val_print with the
+ virtual buf instead of the raw buf. Needed for REGISTER_CONVERT
+ to work with non-floating point regs.
+
+ * d10v-tdep.c (d10v_skip_prologue): If we have line debugging
+ information, then the end of the prologue should the first
+ assembly instruction of the first source line.
+
+ * values.c (value_from_longest): Put in D10V call to
+ fix up address pointers.
+
+ * config/d10v/tm-d10v.h (REGISTER_VIRTUAL_SIZE): Modified.
+ (REGISTER_VIRTUAL_TYPE): Modified for PC_REGNUM and SP_REGNUM.
+ (REGISTER_CONVERTIBLE): Make PC and SP convertible.
+ (REGISTER_CONVERT_TO_VIRTUAL): Define.
+ (REGISTER_CONVERT_TO_RAW): Define.
+ (D10V_MAKE_DADDR): Define.
+ (D10V_MAKE_IADDR): Define.
+
+Wed Nov 20 16:15:15 1996 Geoffrey Noer <noer@cygnus.com>
+
+ * config/i386/cygwin32.mh: add MMALLOC_CFLAGS = -I$(MMALLOC_SRC)
+ -DMMCHECK_FORCE=1 so memory checks are loaded for cygwin32 gdb
+
+Wed Nov 20 00:43:09 1996 Doug Evans <dje@canuck.cygnus.com>
+
+ * callback.h: Delete, moved to ../include.
+ * callback.c: Delete, moved to ../sim/common.
+ * Makefile.in (SFILES,COMMON_OBJS): Delete callback.[co].
+ (callback.o): Delete rule.
+ * remote-sim.h: No longer include callback.h.
+ (sim_callback_write_stdout): Delete prototype.
+ * remote-sim.c (init_callbacks,end_callbacks): New functions.
+ (gdb_os_write_stdout, gdb_os_printf_filtered): New functions.
+ (gdb_callback, callbacks_initialized): New static globals.
+ (gdbsim_open): Call init_callbacks.
+ (gdbsim_close): Call end_callbacks.
+ (simulator_command): Call init_callbacks.
+
+ * config/h8300/h8300.mt (SIM): Change to ../sim/h8300/libsim.a.
+ * config/h8500/h8500.mt (SIM): Change to ../sim/h8500/libsim.a.
+
+Mon Nov 18 15:58:05 1996 Jim Wilson <wilson@cygnus.com>
+
+ * config/mips/tm-mips.h (FIX_CALL_DUMMY): Change unsigned LONGEST
+ to ULONGEST.
+
+Fri Nov 15 15:34:18 1996 Fred Fish <fnf@cygnus.com>
+
+ From Peter Schauer <Peter.Schauer@Regent.E-Technik.TU-Muenchen.DE>
+ * procfs.c (wait_fd): Handle EINTR error return from poll
+ by restarting the poll.
+ * defs.h (PIDGET): Define a default version that just
+ returns its argument unchanged.
+ * inflow.c (terminal_init_inferior): Eliminate #ifdef
+ of PIDGET and fold both alternatives into common code.
+ (pass_signal): Use PIDGET for pid passed to kill().
+
+Thu Nov 14 15:54:20 1996 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * utils.c (paddr,preg): Use a static variable initialized to 32
+ instead of doing addr>>32 to eliminate a warning produced by GCC
+ on 32-bit systems.
+
+ * config/d10v/tm-d10v.h (ULONGEST): Define.
+
+Tue Nov 12 12:25:27 1996 Jim Wilson <wilson@cygnus.com>
+
+ * c-typeprint.c (cp_type_print_method_args): Pass -1 for show in
+ recursive call to type_print.
+
+Tue Nov 12 12:18:29 1996 Jim Wilson <wilson@cygnus.com>
+
+ * defs.h (ULONGEST): New macro.
+ * alpha-tdep.c, breakpoint.c, c-exp.y, ch-exp.c, convex-xdep.c,
+ corefile.c, defs.h, f-exp.y, findvar.c, gdbcore.h, m2-exp.y,
+ m88k-tdep.c, printcmd.c, remote-hms.c, remote-mips.c, sparc-tdep.c,
+ valarith.c, valops.c, values.c, config/gould/tm-np1.h,
+ config/mips/tm-mips.h, mswin/prebuilt/gdb/cexptab.c,
+ mswin/prebuilt/gdb/fexptab.c, mswin/prebuilt/gdb/m2exptab.c:
+ Change all occurances of unsigned LONGEST to ULONGEST.
+
+ * configure.host (mips-sgi-irix6): Add.
+
+Tue Nov 12 12:16:40 1996 Michael Snyder <msnyder@cleaver.cygnus.com>
+
+ * sh-tdep.c: Add functionality for target function calls.
+ * config/sh/tm-sh.h: Add support for target function calls.
+
+Tue Nov 12 12:06:58 1996 Michael Snyder <msnyder@cleaver.cygnus.com>
+
+ * m32r-tdep.c: Add functionality for target function calls.
+ * valops.c: Small change to support target function calls.
+ * config/m32r/tm-m32r.h: Add support for target function calls.
+
+Mon Nov 11 17:15:59 1996 Geoffrey Noer <noer@cygnus.com>
+
+ * defs.h: Modify Nov 11 12:59:00 change so _MSC_VER is checked
+ instead of _WIN32.
+ * win32-nat.c: Fix Nov 11 12:59:00 change (windows.h should
+ be included instead of windefs.h for compilers other than
+ VC++).
+ * mswin/windefs.h: Remove ^Ms and change C++ style comments
+ to C style comments.
+
+Mon Nov 11 14:32:38 1996 Mark Alexander <marka@cygnus.com>
+
+ * utils.c (get_cell): Fix off-by-one bug.
+ * mips-tdep.c (get_frame_pointer, fix_sign_extension):
+ New functions to consolidate common code.
+ (mips_frame_chain, init_extra_frame_info): Use new functions
+ to fix problems with backtrace and finish commands on ddb board.
+
+Mon Nov 11 12:59:00 1996 Dawn Perchik <dawn@critters.cygnus.com>
+
+ * mips-tdep.c, remote-mips.c, values.c, mdebugread.c,
+ config/mips/tm-mips.h: Add/fix bugs for 64-bit mips support.
+ * defs.h: Cleanup; add prototypes.
+ * corefile.c: Change FIXME #ifdef
+ * win32-nat.c: Include windefs instead of windows.h.
+ * utils.c: Add routines for printing addresses and registers
+ based on type size.
+
+Sat Nov 9 01:05:10 1996 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * alpha-tdep.c (heuristic_proc_desc): Stop examining the prologue
+ if we encounter a positive stack adjustment.
+ (find_proc_desc): If heuristic_fence_post is non-zero, use
+ heuristic_proc_start to determine the start of a function before
+ calling heuristic_proc_desc.
+
+ * coffread.c (coff_symtab_read): Change minimal symbol types
+ for C_LABEL symbols from mst_* to mst_file_*.
+
+ * config/m68k/sun3os4.mh (MMALLOC_CFLAGS): Define MMCHECK_FORCE to 1.
+
+ * configure.in: Handle error message from sun3 native ld when
+ configuring HLDFLAGS.
+ * configure: Regenerated with autoconf.
+
+ * c-valprint.c (c_value_print): Adjust value address by VALUE_OFFSET.
+ * cp-valprint.c (cp_print_value): Prevent gdb crashes by making sure
+ that the virtual base pointer from an user object still points to
+ accessible memory.
+
+ * dbxread.c (dbx_symfile_init): Initialize sym_stab_info to
+ clear the recently added header_files fields.
+ (dbx_symfile_finish): Free hfiles[i].vector to avoid storage leak.
+
+Fri Nov 8 14:30:23 1996 Michael Snyder <msnyder@cleaver.cygnus.com>
+
+ * config/tm-sh.h: Added a missing comma in middle of
+ REGISTER_NAMES list.
+
+Fri Nov 8 12:29:51 1996 Stan Shebs <shebs@andros.cygnus.com>
+
+ * monitor.c: Fix some formatting and comments.
+
+ * remote-sim.c (simulator_command): Set up callbacks before
+ entering the simulator.
+
+Thu Nov 7 15:19:08 1996 Martin M. Hunt <hunt@pizza.cygnus.com>
+
+ * d10v-tdep.c: Fix some problems with inferior function calls.
+ * config/d10v/tm-d10v.h (EXTRA_FRAME_INFO): Change dummy to be
+ a pointer to the dummy's stack instead of just a flag.
+
+Tue Nov 5 10:21:02 1996 Michael Snyder <msnyder@cleaver.cygnus.com>
+
+ * m32r-tdep.c: Improved frame_chain and fn prologue analysis.
+ * config/tm-m32r.h: Add framesize and register to extra_frame_info.
+
+Tue Nov 5 10:08:07 1996 Stu Grossman (grossman@critters.cygnus.com)
+
+ * mswin/gdbwin.h: Remove bogus definition of CORE_ADDR.
+ * mswin/srcwin.cpp (CSrcScroll1::CSrcScroll1): Initialize depth
+ to fix divide-by-zero problem with clicking on source window.
+
+Mon Nov 4 00:48:37 1996 Stu Grossman (grossman@critters.cygnus.com)
+
+ * mswin/recordit: Fix problem with absolute paths.
+ * mswin/recordit: Fix problem with relative paths.
+
+Sun Nov 3 18:06:42 1996 Stu Grossman (grossman@critters.cygnus.com)
+
+ * mswin/{Makefile.in configure configure.in}: New files for
+ configuring wingdb under Unix.
+
+Sat Nov 2 03:54:13 1996 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * irix5-nat.c, osfsolib.c, solib.c (symbol_add_stub): Handle
+ missing or zero-sized .text sections properly.
+ * mdebugread.c: Handle scRConst and scSUndefined storage classes.
+ * stabsread.c (scan_file_globals): Try to resolve symbols
+ for shared libraries from the minimal symbol table of the main
+ executable first.
+
+Fri Nov 1 13:59:28 1996 Martin M. Hunt <hunt@pizza.cygnus.com>
+
+ * d10v-tdep.c, config/d10v/tm-d10v.h: Major fixes to support
+ inferior function calls and proper stack backtracing on D10V-EVA
+ board.
+
+Fri Nov 1 10:50:51 1996 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * config/powerpc/linux.mh (NATDEPFILES): Fix up things so that it
+ links.
+ (GDBSERVER_DEPFILES,TERMCAP): Ditto.
+
+ * monitor.c (dev_name,targ_ops): Move static variables before
+ first use, to avoid compiler warnings.
+
+Thu Oct 31 16:37:17 1996 Michael Snyder <msnyder@cleaver.cygnus.com>
+
+ * m32r-tdep.c: Improved frame_chain and fn prologue analysis.
+ * configure.tgt: Add entry for m32r target.
+ * monitor.h: Add a flag to tell monitor_store_register to use
+ (val, regno) instead of (regno, val).
+ * monitor.c: Make monitor_store_register honor the above flag.
+ Make monitor_exp ignore DC1/DC3 for m32r.
+ Increase buf size in monitor_dump_regs.
+
+Wed Oct 30 18:14:14 1996 Michael Snyder <msnyder@cleaver.cygnus.com>
+
+ * m32r-tdep.c, m32r-rom.c: New files.
+ * config/m32r/m32r.mt: New file.
+ * config/m32r/tm-m32r.h: New file.
+
+Tue Oct 29 16:56:01 1996 Geoffrey Noer <noer@cygnus.com>
+
+ * config/i386/xm-cygwin32.h:
+ * config/powerpc/xm-cygwin32.h:
+ add #define LSEEK_NOT_LINEAR so source lines aren't unexpectedly
+ truncated.
+
+Tue Oct 29 18:36:43 1996 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * config/powerpc/tm-ppc-eabi.h (TARGET_BYTE_ORDER_SELECTABLE):
+ Define.
+
+Tue Oct 29 14:59:20 1996 Stan Shebs <shebs@andros.cygnus.com>
+
+ * TODO: Add item suggesting an "info bfd" command.
+
+Tue Oct 29 12:48:04 1996 Martin M. Hunt <hunt@pizza.cygnus.com>
+
+ * d10v-tdep.c: Snapshot that supports D10V-EVA board.
+
+ * config/d10v/tm-d10v.h (REGISTER_NAMES): Add imap0,imap1,dmap.
+ (TARGET_READ_FP,TARGET_WRITE_FP): Define.
+
+Mon Oct 28 17:34:24 1996 Stu Grossman (grossman@critters.cygnus.com)
+
+ * mswin/genmakes mswin/recordit: New scripts to generate make
+ files for MSVC.
+
+Sun Oct 27 20:18:04 1996 Mark Alexander <marka@cygnus.com>
+
+ * config/mips/{tm-vr5000.h,tm-vr5000el.h,vr5000.mt,vr5000el.mt}:
+ New files.
+ * configure.tgt: Modify cases for vr5000 to use new files.
+
+Sat Oct 26 07:15:14 1996 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * config/alpha/alpha-osf3.mh (XM_CLIBS): Add -lm for OSF/1-4.0.
+
+ * procfs.c (proc_set_exec_trap): Under Alpha OSF/1-4.0, tracing
+ the entry to the exit system call to detect termination of the
+ inferior stopped working. Trace termination of the inferior via
+ PRFS_STOPTERM instead.
+ (procfs_init_inferior): Do not trace entry to exit system call
+ if PIOCSSPCACT is defined.
+ (procfs_wait): Handle PR_DEAD event, which signals the termination
+ of the inferior if PRFS_STOPTERM is set.
+
+ * mdebugread.c (parse_partial_symbols): Ignore stNil section
+ start address symbols.
+
+ * sparc-tdep.c (get_saved_register): Get saved PC from the
+ frame info if not in innermost frame.
+
+Thu Oct 24 10:51:45 1996 Mark Alexander <marka@cygnus.com>
+
+ * dbxread.c (process_one_symbol): Interpret end-of-function
+ markers correctly; this fixes problem on Vr5000 where all
+ functions in a module had the same address.
+ * configure.in, configure.tgt, configure.host, gdbserver/configure.in:
+ Correct for pc-linux-gnu problem in config.guess.
+ * configure: Regenerate.
+
+Thu Oct 24 10:06:58 1996 Stu Grossman (grossman@critters.cygnus.com)
+
+ * dbxread.c: Don't swap symbols in place, since internal and
+ external forms may have different sizes. Don't assume that an
+ internal_nlist has the same layout as an external_nlist. Create
+ symbol for n_strx element so to hide specifics of nlist from
+ partial-stab.h.
+ * partial-stab.h: Don't reference dbxread symbols directly. Use
+ CUR_SYMBOL_STRX instead.
+ * config/i386/xm-windows.h: Define SIGQUIT and SIGTRAP.
+
+ * config/v850/tm-v850.h: Define PS_REGNUM and TARGET_V850 for
+ MSVC builds.
+ * mswin/gdbwin.c (reg_order): Define register order for V850.
+ * mswin/gui.cpp (CGuiApp::InitInstance): Define target name for
+ V850.
+ * mswin/regdoc.h: Define MAXREGS for V850.
+
+Tue Oct 22 16:28:20 1996 Stu Grossman (grossman@critters.cygnus.com)
+
+ * v850-tdep.c (scan_prologue): Changes to deal with scheduled
+ prologues correctly. First, prologue end is now defined by
+ presence of a branch, jump or call insn. Second, can no longer
+ fix frame offsets because we may not know the offset until after a
+ register has been saved.
+ * (v850_init_extra_frame_info): Fixup frame offsets here because
+ we have all the info at this time.
+ * (v850_frame_chain): Use new calling convention for scan_prologue.
+
+Tue Oct 22 10:25:29 1996 Martin M. Hunt <hunt@pizza.cygnus.com>
+
+ * d10v-tdep.c, config/d10v/tm-d10v.h: Changes to allow stack
+ backtraces and inferior function calls.
+
+Tue Oct 22 10:32:46 1996 Stan Shebs <shebs@andros.cygnus.com>
+
+ * mpw-make.sed: Update init.c editing to work with Oct 8 change.
+ (@HLDFLAGS@): Always edit out.
+
+Mon Oct 21 18:17:08 1996 Mark Alexander <marka@cygnus.com>
+
+ * mdebugread.c (parse_partial_symbols): Fix 64-bit
+ sign-extension problems in calculating psymtab addresses.
+ * buildsym.c (end_symtab): Use macro to pop context.
+
+Mon Oct 21 14:40:50 1996 Stu Grossman (grossman@critters.cygnus.com)
+
+ * v850-tdep.c: Cleanup lots of things. Add many comments.
+
+ * v850-tdep.c (v850_init_extra_frame_info v850_frame_chain): Fix
+ sign bugs with scanning prologues. Get a little smarter about
+ calculating the length of uninteresting instructions.
+
+Mon Oct 21 14:01:38 1996 Michael Snyder <msnyder@cleaver.cygnus.com>
+
+ * top.c: Add new commands "set annotate" and "show annotate".
+
+Sun Oct 20 04:38:39 1996 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * corelow.c (core_close): Clear inferior_pid only if there is
+ an open core_bfd.
+
+ * cp-valprint.c (cp_print_value_fields): Pass correct address
+ to val_print, not 0.
+
+ From Andreas Schwab (schwab@issan.informatik.uni-dortmund.de):
+ * eval.c (evaluate_subexp_standard) [case BINOP_REPEAT]: Chase
+ typedefs before checking for integral type of right operand.
+
+Fri Oct 18 17:26:22 1996 Mark Alexander <marka@cygnus.com>
+
+ * mdebugread.c (parse_symbol): Fix crash when malloc has
+ no type info and void type has no associated pointer type.
+
+Thu Oct 17 18:18:20 1996 Stan Shebs <shebs@andros.cygnus.com>
+
+ * configure.host: New file, host configuration mapping.
+ * configure.tgt: New file, target configuration mapping.
+ * configure.in: Remove host and target mapping.
+ * configure: Rebuild.
+
+Wed Oct 16 17:46:03 1996 Stan Shebs <shebs@andros.cygnus.com>
+
+ * breakpoint.c (must_shift_inst_regs): New global.
+ (bpstat_stop_status): Change #if uses of DECR_PC_AFTER_BREAK into
+ equivalent expression uses.
+ * infrun.c (wait_for_inferior): Ditto.
+
+Wed Oct 16 01:53:43 1996 Stu Grossman (grossman@critters.cygnus.com)
+
+ * v850-tdep.c (v850_push_arguments): Use symbolic names for arg
+ registers.
+ * config/v850/tm-v850.h: Change FP to 29. Define arg regs.
+
+Tue Oct 15 16:30:07 1996 Stu Grossman (grossman@critters.cygnus.com)
+
+ * Makefile.in (init.c): Don't use -s option with grep. It means
+ something different under Digital Unix.
+
+ * buildsym.c (finish_block): Treat LOC_BASEREG_ARG and
+ LOC_LOCAL_ARG as arguments so that GDB will know about function
+ args declared this way. Mostly affects dwarf.
+ * dwarfread.c (decode_die_type): Change default type from int to
+ void. This allows GDB to recognize void functions.
+ * (new_symbol): If AT_PROTOTYPED is present, set a flag in the
+ type structure.
+ * findvar.c (extract_floating store_floating): Clean up comments
+ to reflect reality.
+ * gdbtypes.h: Add TYPE_FLAG_PROTOTYPED so that we can tell if a
+ function has a prototype. Currently, only dwarf supports this.
+ * utils.c (floatformat_from_doublest): Fix logic error with
+ converting from double to float. (It wasn't shifting mant_long if
+ it had a hidden bit.)
+ * v850-tdep.c: Add support for function calling. Fix some
+ problems with debugging code w/o debug symbols.
+ * config/v850/tm-v850.h: Ditto.
+
+Tue Oct 15 18:19:42 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * utils.c: Always ensure that size_t is defined. Check
+ HAVE_STDDEF_H rather than __STDC__
+ (xmalloc, xrealloc): Use size_t rather than long.
+
+Tue Oct 15 14:24:19 1996 Martin M. Hunt <hunt@pizza.cygnus.com>
+
+ * config/powerpc/tm-ppc-eabi.h: Undefine NO_SINGLE_STEP so targets
+ can use single-step commands.
+
+Sun Oct 13 11:38:25 1996 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * stabsread.c (define_symbol): If REG_STRUCT_HAS_ADDR is non-zero,
+ follow typedefs before checking TYPE_CODE for structures and unions.
+
+Fri Oct 11 15:43:54 1996 Stu Grossman (grossman@critters.cygnus.com)
+
+ * frame.h: Move definition of struct frame_saved_regs to before
+ struct frame to make it possible to use frame_saved_regs in
+ EXTRA_FRAME_INFO macro.
+
+ * v850-tdep.c config/v850/tm-v850.h: Lotsa new functions and
+ macros to make frame operations (such as backtrace) work.
+
+Fri Oct 11 14:23:50 1996 Fred Fish <fnf@cygnus.com>
+
+ * dbxread.c (process_one_symbol): Check for null string directly
+ rather than using strcmp against "".
+ * partial-stab.h: Ditto.
+
+Fri Oct 11 12:18:32 1996 Mark Alexander <marka@cygnus.com>
+
+ * gdbserver/{gdbreplay.c,low-linux.c,remote-utils.c,utils.c}:
+ Make it compile on Linux and eliminate some warnings.
+
+Thu Oct 10 16:32:08 1996 Stu Grossman (grossman@critters.cygnus.com)
+
+ * Makefile.in (init.c): Fixup final sed script to work around
+ Linux bug with `p' operator.
+
+Wed Oct 9 18:02:48 1996 Stan Shebs <shebs@andros.cygnus.com>
+
+ * remote-mips.c: Use the correct name everywhere (DDB) for NEC's
+ VR4300 target.
+ (ddb_ops, pmon_ops): Fix the documentation strings.
+
+Wed Oct 9 07:42:44 1996 Stu Grossman (grossman@critters.cygnus.com)
+
+ * Makefile.in (init.c): Retro HPUX grep lacks -h option. Strip
+ filenames with sed instead.
+
+Tue Oct 8 15:59:44 1996 Stu Grossman (grossman@critters.cygnus.com)
+
+ * defs.h: Remove decls of xmalloc and xrealloc. There is a
+ conflicting definition in libiberty.h.
+
+Tue Oct 8 11:47:13 1996 Fred Fish <fnf@cygnus.com>
+
+ * dbxread.c (dbx_symfile_read): Call free_pending_blocks rather
+ than poking global variable (which is now static).
+ * hpread.c (hpread_build_psymtabs): Ditto.
+ * os9kread.c (os9k_symfile_read): Ditto.
+ * xcoffread.c (xcoff_initial_scan): Ditto.
+
+ * buildsym.h (free_pending_blocks): Declare here.
+ (pending_blocks): Remove declaration of global symbol.
+ (free_pendings): Remove declaration of global symbol.
+ (make_blockvector): Declare here.
+ (record_pending_block): Declare here.
+
+ * dstread.c (make_blockvector): Remove static copy that was old
+ clone of version in buildsym.c.
+ (process_dst_block): Call record_pending_block rather than doing
+ it by hand.
+ (read_dst_symtab): Ditto.
+
+ * buildsym.c (make_blockvector): Make global rather than static,
+ (record_pending_block): New function, code moved from finish_block.
+ (finish_block): Use record_pending_block.
+ (free_pending_blocks): New function.
+ (really_free_pendings): Call free_pending_blocks.
+ (pending_blocks): Make static instead of global.
+ (free_pendings): Make static instead of global.
+
+Tue Oct 8 09:03:22 1996 Stu Grossman (grossman@critters.cygnus.com)
+
+ * config/i386/windows.mh config/i386/xm-windows.h:: New config
+ files to support building Wingdb (built under Microsoft build
+ environment).
+
+ * Makefile.in: Add rule for hpux-thread.o (needs special header
+ files).
+ * (SUBDIRS): Remove mswin.
+ * Change procedure for creating init.c. Speeds things up quite a
+ bit.
+ * config.in configure configure.in: Check for select, poll.
+ * Check for OSF header files before including hpux-thread.o.
+ * Don't configure doc or testsuite when building under MSVC.
+ * findvar.c value.h (read_register_pid write_register_pid): Make
+ global. Needed for hppa-tdep.c.
+ * (supply_register): Don't set pid to inferior_pid when supplying
+ registers.
+ * hppa-tdep.c (saved_pc_after_call): frame_saved_pc ->
+ FRAME_SAVED_PC.
+ * (frame_saved_pc): Change name to hppa_frame_saved_pc.
+ * (hppa_pop_frame): Don't use a pid of 0 with target_write_pc.
+ Use write_pc instead, which uses the correct pid.
+ * (target_read_pc target_write_pc): Use read/write_register_pid
+ instead of read/write_register to preserve the pid passed in.
+ * inftarg.c (child_can_run): Add flag child_suppress_run to allow
+ hpux-threads.c to override this as a runnable target.
+ * config/pa/nm-hppah.h: Define target_new_objfile and
+ target_pid_to_str.
+ * config/pa/tm-hppa.h (FRAME_SAVED_PC): Use hppa_frame_saved_pc
+ instead of frame_saved_pc.
+ * config/m68k/tm-m68k.h: Define TARGET_M68K for Wingdb.
+ * config/m68k/tm-monitor.h: Use FRAME_CHAIN_VALID_ALTERNATE, since
+ we can't easily determine the start file bounds with ELF.
+ * config/mips/tm-mips.h: Define TARGET_MIPS for Wingdb.
+ * hpux-thread.c: New file for HPUX/OSF thread support.
+ * osf-share/{README AT386/cma_thread_io.h HP800/cma_thread_io.h
+ RIOS/cma_thread_io.h cma_attr.h cma_deb_core.h cma_debug_client.h
+ cma_errors.h cma_handle.h cma_init.h cma_list.h cma_mutex.h
+ cma_sched.h cma_semaphore_defs.h cma_sequence.h cma_stack.h
+ cma_stack_int.h cma_tcb_defs.h cma_util.h}: New files for OSF
+ thread support.
+
+Sun Oct 6 15:48:09 1996 Fred Fish <fnf@cygnus.com>
+
+ * buildsym.c (finish_block): Change innerblock_anon_complaint to
+ print the addresses as part of the complaint. Add a complaint for
+ cases where the block end address is smaller than the block start
+ address, in case any such conditions slip through our fixup mechanism.
+ * symmisc.c (dump_symtab): Only print blockvector for primary
+ symtabs, to avoid massive duplication of output due to secondary
+ symtabs that point to same blockvector. Also do some minor
+ formatting tweaks.
+
+Mon Oct 7 10:42:32 1996 Per Bothner <bothner@deneb.cygnus.com>
+
+ Replace header_files global by per-objfile field.
+ * gdb-stabs.h (struct dbx_symfile_info): Add fields header_files,
+ n_header_files, n_allocated_header_files.
+ * stabsread.h (header_files, n_header_files, n_allocated_header_files):
+ Replace externs by macros HEADER_FILES, N_HEADER_FILES, and
+ N_ALLOCATED_HEADER_FILES.
+ * dbxread.c (dbx_symfile_finish): Free HEADER_FILES.
+ (free_header_files, init_header-files): Don't free/init headerfiles.
+ (various functions): Use macros instead of header_files globals.
+ * stabsread.c (various functions): Likewise.
+
+Sun Oct 6 22:43:06 1996 Jason Merrill <jason@yorick.cygnus.com>
+
+ * dwarf2read.c (read_tag_reference_type): New fn.
+ (read_type_die): Call it.
+ (dwarf_attr): Also look in the DIEs referred to by specification
+ or abstract_origin attributes.
+
+Wed Oct 2 22:07:16 1996 Fred Fish <fnf@cygnus.com>
+
+ * inferior.h (IN_SIGTRAMP): Pass pc to SIGTRAMP_START and
+ SIGTRAMP_END.
+ * config/i386/tm-i386os9k.h (SIGTRAMP_START, SIGTRAMP_END):
+ Define with dummy pc arg.
+ * config/m68k/tm-nbsd.h: Ditto.
+ * doc/gdbint.texinfo: Document that SIGTRAMP_START and
+ SIGTRAMP_END are macros that take an single argument.
+
+Mon Sep 30 20:02:45 1996 Fred Fish <fnf@cygnus.com>
+
+ * defs.h: Remove define of PRIVATE_XMALLOC.
+
+Mon Sep 30 15:39:28 1996 Stu Grossman (grossman@critters.cygnus.com)
+
+ * config/v850/tm-v850.h: Use distinct register for PC, not EIPC.
+
+Mon Sep 30 11:16:34 1996 Jeffrey A Law (law@cygnus.com)
+
+ * top.c (execute_control_command): Free values from while_control
+ and if_control conditions after evaluation to avoid storage leaks.
+ From Peter Schauer.
+
+Fri Sep 27 17:43:06 1996 Stu Grossman (grossman@critters.cygnus.com)
+
+ * configure configure.in: Recognize v850 target.
+ * v850-tdep.c: New file, NEC V850 target support.
+ * config/v850/{v850.mt tm-v850.h}: New files for NEC V850 support.
+
+Fri Sep 27 14:48:15 1996 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * infrun.c (wait_for_inferior): Update current_line and
+ current_symtab when stepping continues in the middle of a new line.
+
+Fri Sep 27 10:25:30 1996 Fred Fish <fnf@cygnus.com>
+
+ * top.c (print_gdb_version): Rewrote to comply with new GNU coding
+ standards for the --version option.
+ (print_gnu_advertisement): Remove, now part of print_gdb_version.
+ (show_version): Remove call to print_gnu_advertisement.
+ * top.h (print_gnu_advertisement): Remove prototype.
+ * main.c (print_gdb_help): Move help to static function and
+ add prototype.
+ (main): Call print_gdb_help rather than inlining it.
+ (main): Remove call to print_gnu_advertisement.
+
+Fri Sep 27 13:32:53 1996 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * config/d10v/tm-d10v.h (TARGET_{INT,PTR}_BIT): Define.
+ (TARGET_{,LONG_}DOUBLE_BIT): Ditto.
+
+Thu Sep 26 23:10:26 1996 Mark Alexander <marka@cygnus.com>
+
+ * configure.in, config/i386/tm-linux.h: Fix configure
+ problem on older Linux systems that prevented core files
+ from being recognized.
+
+Wed Sep 25 18:31:33 1996 Stan Shebs <shebs@andros.cygnus.com>
+
+ * dbug-rom.c: New file, support for Motorola's dBUG monitor.
+ * config/m68k/monitor.mt (TDEPFILES): Add it.
+ * NEWS: Mention it.
+
+Mon Sep 23 16:13:50 1996 Martin M. Hunt <hunt@pizza.cygnus.com>
+
+ * config/d10v/tm-d10v.h (SAVED_PC_AFTER_CALL): Fixed.
+ Now single-steps correctly.
+ * d10v-tdep.c (d10v_pop_frame): Fixed.
+
+Fri Sep 20 16:10:58 1996 Stan Shebs <shebs@andros.cygnus.com>
+
+ * config/sh/tm-sh.h (REGISTER_NAMES): Move fp registers to
+ be consistent with GCC.
+ (FPUL_REGNUM, etc): Renumber to match list changes.
+ (ADDR_BITS_REMOVE): Delete.
+ * sh-tdep.c (sh_reg_names, sh3_reg_names, sh3e_reg_names):
+ Rearrange to match REGISTER_NAMES.
+ * sh3-rom.c (sh3_regnames, sh3e_regnames): Ditto.
+
+Thu Sep 19 16:19:01 1996 Martin M. Hunt <hunt@pizza.cygnus.com>
+
+ * d10v-tdep.c: Stack chain should work now.
+
+Tue Sep 17 18:46:57 1996 Martin M. Hunt <hunt@pizza.cygnus.com>
+
+ * d10v-tdep.c, config/d10v/tm-d10v.h: Snapshot.
+
+Tue Sep 17 12:20:50 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * configure.in: Add cases for MIPS 5000 like MIPS 4300.
+ * configure: Rebuild.
+
+Tue Sep 17 12:09:00 1996 Dawn Perchik <dawn@critters.cygnus.com>
+
+ * ser-e7kpc.c: Added wingdb support for target e7000pc.
+
+Tue Sep 17 10:56:52 1996 James G. Smith <jsmith@cygnus.co.uk>
+
+ * remote-mips.c (pmon_wait): DDB PMON does not require forced
+ re-entry back into debug mode.
+
+Mon Sep 16 14:32:58 1996 James G. Smith <jsmith@cygnus.co.uk>
+
+ * remote-mips.c (mips_load): Ensure that the PC is explicitly
+ loaded after a load to a DDB PMON system.
+
+Fri Sep 13 12:02:39 1996 Fred Fish <fnf@cygnus.com>
+
+ * Makefile.in (INTERNAL_LDFLAGS): Add @HLDFLAGS@ to list.
+ (HLDENV): Set to @HLDENV@.
+ (gdb): Prefix link command line with $(HLDENV).
+ * configure.in: Add support to test for --enable-shared and
+ generate appropriate values for HLDFLAGS and HLDENV.
+ * configure: Regenerated with autoconf.
+
+Sun Sep 8 15:26:27 1996 Fred Fish <fnf@cygnus.com>
+
+ * alpha-nat.c (fetch_core_registers): Match Sep 4 gdbcore.h prototype
+ change for core_read_registers in struct core_fns.
+ * core-regset.c (fetch_core_registers): Ditto & add prototype.
+ * core-sol2.c (fetch_core_registers): Ditto & add prototype.
+ * i386aix-nat.c (fetch_core_registers): Ditto & add prototype.
+ * i386b-nat.c (fetch_core_registers): Ditto.
+ * i386mach-nat.c (fetch_core_registers): Ditto & add prototype.
+ * irix4-nat.c (fetch_core_registers): Ditto.
+ * irix5-nat.c (fetch_core_registers): Ditto.
+ * lynx-nat.c (fetch_core_registers): Ditto & add prototype.
+ * m68knbsd-nat.c (fetch_core_registers): Ditto.
+ * mips-nat.c (fetch_core_registers): Ditto & add prototype.
+ * rs6000-nat.c (fetch_core_registers): Ditto.
+ * sparc-nat.c (fetch_core_registers): Ditto.
+ * sun3-nat.c (fetch_core_registers): Ditto & add prototype.
+ * ultra3-nat.c (fetch_core_registers): Ditto & add prototype.
+
+ * alpha-nat.c (register_addr): Match Sep 4 gdbcore.h prototype change.
+ * delta68-nat.c (register_addr): Ditto.
+ * gdbserver/low-linux.c (register_addr): Ditto.
+ * gdbserver/low-hppabsd.c (register_addr): Ditto.
+ * i386m3-nat.c (register_addr): Ditto.
+ * mips-nat.c (register_addr): Ditto.
+ * ultra3-nat.c (register_addr): Ditto.
+
+Sun Sep 8 15:14:00 1996 Stu Grossman (grossman@critters.cygnus.com)
+
+ * blockframe.c (inside_main_func): Cleanup slightly. Move
+ mainsym def into the block it's used in.
+ * configure.in configure: Allow NATDEPFILES to be recognized in
+ .mh files regardless of whitespace.
+
+ * cpu32bug-rom.c (cpu32bug_cmds): Change load_response string to
+ keep downloads from hanging.
+
+ * remote-wiggler.c: Add support for flash upgrades.
+ * (wiggler_error): Fix message format. Add new error code.
+ * (wiggler_write_byets): Error code is hex. Report errors with
+ proper routine name.
+ * (wiggler_read_byets): Report errors with proper routine name.
+ * (get_packet): Add support for new flash commands.
+ * (wiggler_load): Call clear_symtab_users() to reset things
+ properly after download.
+ * (flash_xfer_memory bdm_update_flash_command): New funxtions to
+ support flash upgrades for Wiggler.
+ * (_initialize_remote_wiggler): Add `bdm update-flash' command.
+
+Fri Sep 6 13:14:13 1996 Geoffrey Noer <noer@cygnus.com>
+
+ * ser-tcp.c: don't include netinet/tcp.h if __CYGWIN32__
+
+Thu Sep 5 17:05:13 1996 Geoffrey Noer <noer@cygnus.com>
+
+ * config/i386/cygwin32.mh:
+ * config/powerpc/cygwin32.mh: build ser-tcp.o for both hosts
+
+Thu Sep 5 12:09:13 1996 Per Bothner <bothner@deneb.cygnus.com>
+
+ * value.h (COERCE_REF): Fix previous change.
+ (COERCE_ENUM): Add a check_typedef (this is the real fix).
+
+Thu Sep 5 03:28:30 1996 Wilfried Moser <moser@rtl.cygnus.com>
+
+ * eval.c (evaluate_subexp_standard): In case of OP_ARRAY: make a
+ better check of array boundaries.
+
+Thu Sep 5 01:29:42 1996 Stu Grossman (grossman@critters.cygnus.com)
+
+ * configure: Update aclocal.m4 and re-run autoconf to get correct
+ defs for BFD stuff.
+ * remote-wiggler.c (wiggler_error): Error codes are hex. Also,
+ fix default message generation.
+
+Wed Sep 4 17:28:40 1996 Stu Grossman (grossman@critters.cygnus.com)
+
+ * Makefile.in: Add mswin to SUBDIRS. Add rules for
+ mswin/libwingdb.a and remote-wiggler.o.
+ * breakpoint.c (breakpoint_here_p): Clean up bp enabled test.
+ * (breakpoint_inserted_here_p): New func, just like
+ breakpoint_here_p, except it's honest. Honestly.
+ * breakpoint.h: Proto for above.
+ * configure configure.in: Add mswin to configdirs if host is
+ i[3456]86-*-windows.
+ * core-aout.c (fetch_core_registers register_addr) gdbcore.h:
+ Change all vars that can contain addresses to type CORE_ADDR.
+ * findvar.c (supply_register): Allow val to be NULL. This means
+ that regno is unsupported.
+ * (read_pc read_pc_pid write_pc write_pc_pid): Make non-pid forms
+ just call pid forms with inferior_pid so that there's only once
+ place to hack PC's and such.
+ * infrun.c (proceed): Don't skip breakpoints if user changed PC.
+ * remote-wiggler.c: New file. Support for BDM interface from
+ Macraigor Systems.
+ * serial.c: Enhance serial logging capability. Add hex and octal
+ output modes (set remotelogbase {hex|octal|ascii}. Also log
+ breaks, timeouts, errors, and eofs.
+ * serial.h: Redefine SERIAL_SEND_BREAK to go through a wrapper
+ function so that we can log breaks. Don't export serial_logfile
+ or serial_logfp.
+ * top.c (execute_command): Don't test for serial_logfp here.
+ Just call serial_log_comand, and let serial.c sort it out.
+ * valops.c (value_of_variable): Don't attempt to establish frames
+ for static and global variables. This makes things work a bit
+ better if the stack or frame pointer is trashed.
+ * config/m68k/monitor.mt (TDEPFILES): Add remote-wiggler.o.
+ * config/m68k/tm-m68k.h: Define STACK_ALIGN. CPU32 can't hack
+ misaligned stacks during function calls.
+
+Wed Sep 4 13:06:26 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * terminal.h: Don't use #elif.
+
+Wed Sep 4 06:49:35 1996 Wilfried Moser <moser@rtl.cygnus.com>
+
+ * ch-exp.c (parse_tuple_element): Allow (*): for array tuples
+ if we have a type.
+
+ * eval.c (evaluate_subexp_standard): In case of OP_ARRAY:
+ check number of args against bounds of array to avoid
+ memory corruption.
+
+ * value.h (COERCE_REF): Do a CHECK_TYPEDEF in case we get
+ a TYPE_CODE_TYPEDEF.
+
+Fri Aug 30 15:07:14 1996 James G. Smith <jsmith@cygnus.co.uk>
+
+ * remote-mips.c: Provide support for DDBVR4300 target board.
+ (ddb_open, ddb_ops): Added.
+ (mips_monitor_type): MON_DDB Added.
+ (mips_enter_debug, mips_exit_debug, mips_initialize,
+ mips_fetch_registers, common_breakpoint, mips_load,
+ _initialize_remote_mips): Updated.
+
+Thu Aug 29 17:00:18 1996 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * nlm/configure.in (i[345]86-*-*): Recognize i686 for pentium pro.
+ * nlm/configure: Regenerate.
+
+ * gdbserver/configure.in (i[345]86-*-*): Recognize i686 for
+ pentium pro.
+
+Wed Aug 28 13:11:15 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * configure.in: If CY_AC_PATH_TCLCONFIG can't find TCL, don't run
+ CY_AC_LOAD_TCLCONFIG.
+ * configure: Rebuild.
+
+Tue Aug 27 12:40:40 1996 Fred Fish <fnf@cygnus.com>
+
+ * infrun.c (wait_for_inferior): Initialize stop_func_end before calling
+ find_pc_partial_function.
+
+Tue Aug 27 10:17:34 1996 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * configure: Regenerate again.
+
+Tue Aug 27 04:25:08 1996 Geoffrey Noer <noer@cygnus.com>
+
+ * configure.in: work around host_alias configure bug.
+ AC_CANONICAL_HOST is called twice (first by AC_CHECK_TOOL
+ and second by AC_CANONICAL_SYSTEM). The second clobbers the
+ previous setting. Circumventing by moving the second check
+ to before the first.
+ * configure: regenerated
+
+Mon Aug 26 18:36:54 1996 Martin M. Hunt <hunt@pizza.cygnus.com>
+
+ * config/d10v/d10v.mt: New file.
+ * config/d10v/tm-d10v.h: New file.
+ * configure.in: New target D10V.
+ * d10v-tdep.c: New file.
+
+Sun Aug 25 00:09:47 1996 Fred Fish <fnf@rtl.cygnus.com>
+
+ * rs6000-tdep.c: Fix typo in comment.
+ * valops.c (call_function_by_hand): Set using_gcc to 2
+ for code compiled without -g, per comment in code.
+ * config/a29k/tm-a29k.h (STACK_ALIGN): Add comment.
+ * config/sparc/tm-sparc.h (STACK_ALIGN): Add comment.
+ * config/sparc/tm-sp64.h (STACK_ALIGN): Add comment.
+ * config/pyr/tm-pyr.h (STACK_ALIGN): Add comment.
+ * config/m88k/tm-m88k.h (STACK_ALIGN): Add comment.
+ * config/pa/tm-hppa.h (PUSH_ARGUMENTS): Enclose args in ()'s.
+ (STACK_ALIGN): Add comment, move to be with other associated
+ macros, and document.
+ * config/mips/tm-mips.h (PUSH_ARGUMENTS): Enclose args in ()'s.
+ (STACK_ALIGN): Remove completely, handled by PUSH_ARGUMENTS.
+ * config/alpha/tm-alpha.h (PUSH_ARGUMENTS): Enclose args in ()'s.
+ * config/rs6000/tm-rs6000.h (STACK_ALIGN): Remove completely,
+ handled by PUSH_ARGUMENTS.
+ (PUSH_ARGUMENTS): Enclose args in ()'s.
+
+Fri Aug 23 13:55:05 1996 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * infrun.c (wait_for_inferior): Try to reenable shared library
+ breakpoints even if auto_solib_load is not set.
+
+Wed Aug 21 16:31:27 1996 Fred Fish <fnf@cygnus.com>
+
+ * valprint.c (print_longest): Test for CC_HAS_LONG_LONG as well as
+ PRINTF_HAS_LONG_LONG.
+ * expprint.c (dump_expression): Ditto.
+ * configure.in: Fix check for long long support in compiler to
+ use a function body, not a nested function.
+ * configure: Rebuild with autoconf.
+
+Tue Aug 20 17:59:42 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * aclocal.m4: Include ../bfd/aclocal.m4.
+ * configure.in: Add stdlib.h to AC_CHECK_HEADERS. Call
+ BFD_NEED_DECLARATION on malloc, realloc, and free.
+ * acconfig.h: Add NEED_DECLARATION_MALLOC,
+ NEED_DECLARATION_REALLOC, and NEED_DECLARATION_FREE.
+ * configure, config.in: Rebuild.
+ * defs.h: Include <stddef.h> and <stdlib.h> based on HAVE_*_H
+ rather than __STDC__. Only declare malloc, realloc, and free if
+ NEED_DECLARATION_* is defined.
+
+Tue Aug 20 15:37:03 1996 Fred Fish <fnf@cygnus.com>
+
+ * solib.c (_initialize_solib): Add missing '\' chars at ends of
+ strings that continue on next line.
+ (enable_break): Replace "return 0" with setting success to zero
+ and letting normal return handle the return.
+
+Sat Aug 17 14:16:23 1996 Fred Fish <fnf@cygnus.com>
+
+ * mips-tdep.c (mips_push_arguments): Make sure sp and struct_addr
+ are properly aligned.
+
+Fri Aug 16 17:54:26 1996 Stan Shebs <shebs@andros.cygnus.com>
+
+ * rs6000-tdep.c (rs6000_fix_call_dummy): Add full set of arguments.
+ * config/rs6000/tm-rs6000.h (FIX_CALL_DUMMY): Pass all arguments
+ to function, declare function correctly.
+
+Fri Aug 16 17:24:35 1996 Dawn Perchik <dawn@critters.cygnus.com>
+
+ * symtab.h: changed namespace to _namespace for compiling under
+ MFC v4.0.
+
+Fri Aug 16 13:52:21 1996 Stan Shebs <shebs@andros.cygnus.com>
+
+ * mpw-make.sed: Update for various recent changes, add some
+ comments.
+
+Fri Aug 16 15:47:36 1996 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * config/rs6000/tm-rs6000.h (FIX_CALL_DUMMY): Cast args to be an
+ integer for type correctness.
+
+Fri Aug 16 15:15:37 1996 James G. Smith <jsmith@cygnus.co.uk>
+
+ * config/mips/{vr4300.mt, vr4300el.mt} (SIM): Add -lm when
+ simulator is included.
+
+Thu Aug 15 13:44:13 1996 Fred Fish <fnf@cygnus.com>
+
+ * findvar.c (write_register_pid): Only needed when TARGET_WRITE_PC
+ is not defined.
+ (read_register_pid): Only needed when TARGET_READ_PC is not
+ defined.
+ * hppa-tdep.c (frame_saved_pc): Remove prototype.
+ * infptrace.c (udot_info): Prototype when CHILD_XFER_MEMORY is
+ not defined.
+ * config/xm-aix4.h (aix_resizewindow): Convert old style decl
+ to prototype.
+ * xcoffsolib.c (command.h): Include for needed prototypes.
+
+Wed Aug 14 17:54:19 1996 Stu Grossman (grossman@critters.cygnus.com)
+
+ * config/i386/cygwin32.mh: Set NAT_FILE to nm-empty.h to make
+ native work.
+
+Wed Aug 14 02:03:42 1996 Fred Fish <fnf@cygnus.com>
+
+ From Blair MacIntyre <bm@cs.columbia.edu>:
+ * hppa-tdep.c (hppa_fix_call_dummy): Use MSYMBOL_TYPE rather
+ than SYMBOL_TYPE on msymbols.
+ * somsolib.c (som_solib_create_inferior_hook): Ditto.
+
+ * Makefile.in (init.c): Generate with prototypes.
+
+ * config/pa/tm-hppa.h (frame_saved_pc): Add prototype.
+ * config/rs6000/xm-rs6000.h (aix_resizewindow): Ditto.
+ * config/rs6000/tm-rs6000.h (frame_initial_stack_address): Ditto.
+ (pc_load_segment_name): Ditto.
+ (pop_frame): Ditto.
+ (extract_return_value): Ditto.
+ (is_magic_function_pointer): Ditto.
+ (push_dummy_frame): Ditto.
+ (fix_call_dummy): Ditto.
+ (push_arguments): Ditto.
+ (skip_trampoline_code): Ditto.
+ (aix_process_linenos): Ditto.
+
+ * config/m68k/tm-cisco.h (get_longjmp_target): Add prototype.
+ * config/m68k/tm-es1800.h: Ditto.
+ * config/m68k/tm-vx68.h: Ditto.
+ * config/m68k/tm-sun3.h: Ditto.
+ * config/m68k/tm-m68kv4.h: Ditto.
+
+Tue Aug 13 23:04:36 1996 Fred Fish <fnf@cygnus.com>
+
+ * config/mips/nm-mips.h (get_longjmp_target): Add prototype.
+ * config/mips/nm-irix3.h (get_longjmp_target): Add prototype.
+ * remote-mips.c (mips_read_processor_type): Remove prototype.
+ * mips-tdep.c (gdb_print_insn_mips): Add prototype and make static.
+ * irix5-nat.c (fetch_core_registers): Add prototype.
+
+Mon Aug 12 21:23:44 1996 Fred Fish <fnf@cygnus.com>
+
+ * remote-pa.c (boot_board): Add dummy params to make type compatible
+ for passing to add_com.
+ * scm-exp.c (scm_lreadr): Ensure svalue is not used uninitialized.
+ * buildsym.c (compare_line_numbers): Change function to match
+ prototype and also what qsort expects.
+
+Mon Aug 12 19:19:00 1996 Mark Alexander <marka@cygnus.com>
+
+ * remote.c: Make remote_write_size public.
+ * sh-tdep.c (_initialize_sh_tdep): Set remote_write_size to 300
+ to prevent packet errors with some versions of CMON.
+
+Mon Aug 12 16:20:58 1996 Stu Grossman (grossman@critters.cygnus.com)
+
+ * defs.h: Define CONST_PTR as blank if compiling with Microsoft
+ C, else it's `const'.
+ * c-lang.c c-lang.h ch-lang.c f-lang.c language.c m2-lang.c
+ scm-lang.c: Microsoft C can't hack const pointers. Use CONST_PTR
+ macro instead.
+ * configure configure.in defs.h: Use AC_C_CONST to figure out if
+ the compiler supports const. Gets rid of some cruft in defs.h.
+ * dwarf2read.c: <string.h> -> "gdb_string.h"
+ * remote-sim.c: Add prototypes. Fix call to gdbsim_kill.
+ * sparcl-tdep.c (download): Add prototypes to write_routine and
+ start_routine args.
+
+ * mswin/gdbwin.c: Don't include both varargs.h AND stdarg.h. Get
+ rid of varargs.h Include string.h.
+ * (gdbwin_update gdbwin_fputs regs_changed_f bpt_changed_f
+ update): Fix prototypes, fix calls.
+ * (update): Return value for catch_errors.
+ * (run_execute_command togdb_command_from_tty togdb_command):
+ Cleanup catching of errors from calls to execute_command. Also,
+ dup command string to avoid modifying const strings.
+ * (togdb_breakinfo_i_init togdb_breakinfo_i_next): Use 0 instead
+ of NULL when see if b->address isn't set.
+ * (bi_disable_bpt bi_enable_bpt bi_delete_all
+ bi_delete_breakpoint): Add arg to calls to update.
+ * (gui_command): Add prototype.
+ * (mswin_query): Fix prototype.
+ * (_initialize_gdbwin): Dup string to avoid modifying const.
+ * (info_path togdb_get_info_path): Remove const from decls cuz
+ this can't be const (it points at malloc'ed memory).
+ * (togdb_searchpath): Remove const from path. Dup string to
+ avoid modifying const strings.
+ * rindex -> strrchr.
+ * (gdbwin_list_symbols): Regexp param is const.
+ * Fix lots of refs to psymtabs to deref correct pointers.
+ * (togdb_set_breakpoint_sal): Call set_breakpoint_sal with sal,
+ not &sal.
+ * mswin/gdbwin.h (togdb_searchpath togdb_get_info_path
+ toget_set_info_path): Fix prototypes to match reality.
+ * mswin/gui.cpp: Define _beginthreadex and _endthreadex routines
+ with proper prototypes.
+ * mswin/iface.cpp (gdbwin_fputs): Define with correct number of args.
+ * mswin/ser-win32s.c: Fix defs of min and max.
+ * mswin/serdll32.c (OpenComm16): Make cbInQueue and cbOutQueue be
+ USHORT.
+ * (WriteComm16): Change lpBug from LPVOID to LPCSTR.
+ * mswin/serdll32.h: Fix prototypes for OpenComm16 and WriteComm16.
+
+Sun Aug 11 20:54:16 1996 Stu Grossman (grossman@critters.cygnus.com)
+
+ * main.c (main): Make sure command loop is used with cygwin32.
+ * terminal.h: Allow cygwin32 to use termios.h.
+
+Fri Aug 9 12:42:49 1996 Jeffrey A Law (law@cygnus.com)
+
+ * somread.c (som_symtab_read): Handle secondary definition
+ symbols (aka weak symbols).
+
+ * config/tm-hppa.h (EXTRACT_RETURN_VALUE): Fix thinko in
+ last change.
+
+Thu Aug 8 10:12:36 1996 Stu Grossman (grossman@critters.cygnus.com)
+
+ * symfile.c (symfile_bfd_open): Change ifdef from __WIN32__ to
+ _WIN32.
+
+ * somread.c: Rearrange order of includes to fix warnings under
+ hpux-10.10. Also don't include sys/file.h.
+
+Wed Aug 7 21:45:52 1996 Stu Grossman (grossman@critters.cygnus.com)
+
+ * dbxread.c: Don't include param.h or sys/file.h.
+ * (dbx_symfile_read): Determine symfile_relocatable from bfd
+ flags instead of file extension. Also clean up a little bit.
+
+Wed Aug 7 17:18:37 1996 Stu Grossman (grossman@critters.cygnus.com)
+
+ * dwarf2read.c dwarfread.c exec.c infcmd.c infrun.c main.c
+ mdebugread.c os9kread.c source.c top.c utils.c: Don't
+ include param.h or sys/file.h (or unistd.h in some cases).
+ * defs.h exec.c inflow.c remote-array.c remote-e7000.c
+ sparcl-tdep.c terminal.h utils.c: Replace all occurances of
+ __WIN32__, WINGDB, WIN32, etc... with _WIN32.
+ * main.c: Remove #ifndef WINGDB around option processing. Fix
+ bug with passing argc==0 and argv==NULL to getopt.
+ * (main) Remove calls to access() before source_command. Let
+ soure_command handle access errors.
+ * maint.c (maintenance_dump_me): #ifdef out for _WIN32.
+ * symtab.c (operator_chars): Make this global for wingdb.
+ * top.c (disconnect): #ifdef out for _WIN32.
+ * (source_command): If got an error and from_tty, then call print
+ error, else just return quietly.
+ * utils.c (fatal_dump_core): Can't kill ourselves under windows.
+ Just exit.
+ * (pollquit notice_quit): #ifdef out stuff that doesn't exist
+ under windows.
+
+Wed Aug 7 09:59:19 1996 Jeffrey A Law (law@cygnus.com)
+
+ * config/pa/tm-hppa.h (EXTRACT_RETURN_VALUE): Tweak for
+ structures > 4 bytes in size.
+
+ * valops.c (call_function_by_hand): Handle aligning stacks that
+ grow up correctly.
+ * config/pa/tm-hppa.h (USE_STRUCT_CONVENTION): Define.
+ (STACK_ALIGN): Define.
+ * hppa-tdep.c (hppa_alignof): Don't demand a minumim two byte
+ alignment on structs/unions.
+
+Sun Aug 4 16:22:42 1996 Fred Fish <fnf@cygnus.com>
+
+ * config/powerpc/nm-aix.h (PTRACE_ARG3_TYPE): Define to "int *",
+ which is the documented type under at least AIX 3 and AIX 4.
+
+Sat Aug 3 04:02:46 1996 Fred Fish <fnf@cygnus.com>
+
+ * config/alpha/alpha-osf3.mh (XM_FILE): Change from xm-alpha.h to
+ xm-alphaosf.h.
+ (MMALLOC_CFLAGS): Define NO_MMCHECK to not install consistency
+ checks.
+
+Thu Aug 1 10:11:34 1996 Fred Fish <fnf@cygnus.com>
+
+ * config/mips/tm-mips.h (TM_MIPS_H): Enclose file contents in
+ this, define when contents are included.
+ (mips_read_processor_type): Add prototype.
+ * config/mips/xm-mips.h: Remove strdup decl, now in gdb_string.h
+ * mdebugread.c (ecoff_relocate_efi): Add prototype.
+ (fixup_sigtramp): Only needed when TM_MIPS_H is defined.
+
+Wed Jul 31 20:21:24 1996 Fred Fish <fnf@cygnus.com>
+
+ * rs6000-nat.c (add_vmap): Return 0 to caller rather than random value.
+ (vmap_ldinfo): Ensure got_exec_file is not used uninitialized.
+ (fetch_core_registers): Add prototype.
+ (vmap_symtab): Ditto.
+ (objfile_symbol_add): Ditto.
+ (add_vmap): Ditto.
+ (vmap_ldinfo): Ditto.
+ (vmap_exec): Ditto.
+
+Tue Jul 30 17:57:46 1996 Stan Shebs <shebs@andros.cygnus.com>
+
+ * stabsread.c (get_substring): Declare second arg as int.
+
+ * remote-es.c: Include gdb_string.h after defs.h.
+
+Mon Jul 29 21:13:20 1996 Fred Fish <fnf@cygnus.com>
+
+ * rs6000-tdep.c (push_arguments): Remove unused variable "pc".
+ (branch_dest): Remove unused variable "offset".
+ (pop_dummy_frame): Add prototype and make static.
+ (push_arguments): Guard against using len uninitialized.
+ (push_arguments): Guard against using arg uninitialized.
+ (frame_saved_pc): Remove unused variable "frameless".
+ (free_loadinfo): Ifdef out unused function.
+
+ * xcoffread.c (compare_lte): Change prototype and function to
+ be correct type for passing to qsort.
+ (add_stab_to_list): Ifdef out unused function and prototype.
+ (compare_lte): Add prototype
+ (arrange_linetable): Ditto.
+ (record_include_begin): Ditto.
+ (record_include_end): Ditto.
+ (process_linenos): Ditto.
+ (xcoff_next_symbol_text): Ditto.
+ (scan_xcoff_symtab): Ditto.
+ (xcoff_initial_scan): Ditto.
+
+ * mips-tdep.c (mips_read_processor_type): Add parens around
+ bitwise-and operands in comparison; previous expression always
+ evaluated to 0 because of equality comparison of two constants.
+
+ * rs6000-tdep.c (skip_prologue): Add missing parens around
+ operands of logical-or so that first operand does not bind
+ to previous logical-and.
+
+ * configure.in: Expand "long long" test to include code that triggers
+ known problem on HPUX with native compiler.
+ (configure): Regenerated.
+
+Mon Jul 29 18:12:27 1996 Jeffrey A Law (law@cygnus.com)
+
+ * somsolib.c (som_solib_create_inferior_hook): Don't
+ warn if __d_pid can't be found.
+
+Sun Jul 28 10:46:39 1996 Fred Fish <fnf@cygnus.com>
+
+ * config/mips/tm-mips.h (struct frame_info): Forward decl.
+ (struct type): Ditto.
+ (struct value): Ditto.
+
+ * config/mips/tm-mips.h (sigtramp_address): Move extern decl
+ from mips-tdep.c to here.
+ (sigtramp_end): Ditto.
+ (fixup_sigtramp): Ditto.
+
+ * config/mips/tm-mips.h (init_extra_frame_info): Add prototype.
+ (mips_frame_chain): Ditto.
+ (mips_step_skips_delay): Ditto.
+ (mips_frame_saved_pc): Ditto.
+ (mips_find_saved_regs): Ditto.
+ (mips_frame_num_args): Ditto.
+ (mips_pop_frame): Ditto.
+ (mips_extract_return_value): Ditto.
+ (mips_store_return_value): Ditto.
+ (mips_push_dummy_frame): Ditto.
+ (mips_push_arguments): Ditto.
+ (mips_do_registers_info): Ditto.
+ (ecoff_relocate_efi): Ditto.
+ (ecoff_relocate_efi): Ditto.
+ * irix4-nat.c (fetch_core_registers): Add prototype.
+ * mips-tdep.c (read_next_frame_reg): Add prototype
+ (heuristic_proc_start): Ditto.
+ (heuristic_proc_desc): Ditto.
+ (mips_print_register): Ditto.
+ * config/mips/nm-irix5.h (procfs_set_watchpoint): Add prototype.
+ (procfs_stopped_by_watchpoint): Ditto.
+ * config/mips/nm-irix4.h (procfs_set_watchpoint): Add prototype.
+ (procfs_stopped_by_watchpoint): Ditto.
+ * config/alpha/tm-alpha.h (ecoff_relocate_efi): Add prototype.
+ (struct symbol): Add forward decl for prototype.
+
+ * breakpoint.c (internal_breakpoint_number): Only needed if
+ GET_LONGJMP_TARGET or SOLIB_ADD is defined.
+
+ * objfiles.c (ecoff_relocate_efi): Remove prototype.
+
+Sat Jul 27 17:47:35 1996 Fred Fish <fnf@cygnus.com>
+
+ * configure.in: Add test for "long long" support.
+ * configure: Regenerate with autoconf.
+ * acconfig.h: Add CC_HAS_LONG_LONG
+ * config.in: Regenerate with autoheader.
+ * config/mips/tm-mips64.h (FORCE_LONG_LONG): Remove
+ * config/sparc/tm-sp64.h (CC_HAS_LONG_LONG): Remove.
+ * config/mips/tm-vr4300el.h (CC_HAS_LONG_LONG): Remove.
+ * config/mips/tm-vr4300.h (CC_HAS_LONG_LONG): Remove.
+ * config/mips/xm-irix5.h (CC_HAS_LONG_LONG): Remove
+ (PRINTF_HAS_LONG_LONG): Remove.
+ (FORCE_LONG_LONG): Remove.
+ * config/powerpc/xm-aix.h (UINT_MAX): Undef and use gdb's version.
+ * config/convex/xm-convex.h (CC_HAS_LONG_LONG): Remove
+ (PRINTF_HAS_LONG_LONG): Remove.
+ * config/xm-nbsd.h (CC_HAS_LONG_LONG): Remove.
+ (PRINTF_HAS_LONG_LONG): Remove.
+ * config/pa/tm-hppa.h (GET_FIELD): Put parens around
+ subtraction inside shift. Put parens around subtraction
+ in operand of bitwise and.
+ (struct frame_info): Forward declare
+ if __STDC__ defined.
+ (frame_saved_regs): Ditto.
+ (struct value): Ditto.
+ (struct type): Ditto.
+ (struct inferior_status): Ditto.
+ (init_extra_frame_info): Add prototype.
+ (skip_prologue): Ditto.
+ (frameless_function_invocation): Ditto.
+ (frame_chain): Ditto.
+ (frame_chain_valid): Ditto.
+ (saved_pc_after_call): Ditto.
+ (hppa_fix_call_dummy): Ditto.
+ (hppa_push_arguments): Ditto.
+ (pa_do_registers_info): Ditto.
+ (in_solib_call_trampoline): Ditto.
+ (in_solib_return_trampoline): Ditto.
+ (push_dummy_frame): Ditto.
+ * convex-tdep.c (decout): Use print_longest rather than
+ fprintf_filtered.
+ * defs.h: Remove use of FORCE_LONG_LONG and __GNUC__ to set
+ CC_HAS_LONG_LONG.
+ (INT_MIN): Fix so it works correctly when assigned to a long long.
+ * valprint.c (longest_to_int): Rewrite to remove dependence
+ on INT_MIN and INT_MAX.
+ (print_longest): Rewrite the code that falls back to synthesized
+ hex output when LONGEST value is not representable as in a long and
+ printf doesn't support printing long longs.
+ * ch-valprint.c (chill_val_print): Cast 2nd arg of
+ chill_print_type_scalar to LONGEST.
+ chill_print_type_scalar): Make static and add prototype.
+ * hppa-tdep.c (get_field): Ifdef out unused function.
+ (set_field): Ditto.
+ (extract_3): Ditto.
+ (extract_5_store): Ditto.
+ (extract_11): Ditto.
+ (extract_12): Ditto.
+ (deposit_17): Ditto.
+ (extract_14): Convert to static and add prototype.
+ (deposit_14): Ditto.
+ (extract_21): Ditto.
+ (deposit_21): Ditto.
+ (extract_17): Ditto.
+ (extract_5r_store): Ditto.
+ (extract_5R_store): Ditto.
+ (extract_5_load): Ditto.
+ (find_proc_framesize): Ditto.
+ (find_dummy_frame_regs): Ditto.
+ (sign_extend): Ditto.
+ (find_unwind_entry): Add prototype.
+ (find_return_regnum): Ditto.
+ (unwind_command): Ditto.
+ (find_dummy_frame_regs): Add parens around subtraction in operand
+ of bitwise-and.
+ (skip_prologue): Add parens around operands of logical-and inside
+ operand of logical-or.
+ (sign_extend): Add parens around operands of subtraction inside
+ operand of shift.
+ (low_sign_extend): Ditto.
+ * top.c (filename_completer): Convert old style decl of
+ filename_completion_function into prototype.
+ * f-lang.c (patch_common_entries): Ifdef out unused function.
+ * stabsread.c (read_cfront_baseclasses): Remove unused local
+ variable "msg_noterm".
+ (resolve_cfront_continuation): Remove unused local variable "fip".
+ (read_type): Remove unused variable xtypenums.
+ (read_cfront_static_fields): Remove unused variable "i".
+ (read_cfront_static_fields): Remove unused variable "nfields".
+ (read_cfront_member_functions): Add missing comment terminator.
+ (read_cfront_static_fields): Return 1 rather than random value.
+ (read_cfront_baseclasses): Ditto.
+ (read_cfront_baseclasses): Ditto.
+ (read_cfront_baseclasses): Ditto.
+ * somsolib.c (som_solib_create_inferior_hook): Remove unused
+ variable "u".
+ (som_solib_create_inferior_hook): Remove unused variable
+ shadow_contents.
+ (language.h): Add for needed prototypes.
+ (som_solib_sharedlibrary_command): Add prototype.
+ * hpread.c: (hpread_read_array_type): Add prototype.
+ * somread.c (hpread_build_pysmtabs): Add prototype.
+ (hpread_symfile_finish): Ditto.
+ (hpread_symfile_init): Ditto.
+ * hppah-nat.c (fetch_register): Convert old style decl
+ to prototype.
+ (gdbcore.h): Include for needed prototypes.
+ (fetch_register): Remove unused variable "mess".
+ * remote-pa.c (get_offsets): Ifdef out unused function.
+ (remote_start_remote): Remove unused variable "timeout".
+ (boot_board): Add prototype.
+ (reaad_frame): Add prototype.
+ (getpkt): Remove unused variable "bp".
+ (remote_kill): Add prototype.
+ (remote_mourn): Add prototype.
+ (remote_insert_breakpoint): Add prototype.
+ (remote_remove_breakpoint): Add prototype.
+ * valops.c (value_push): Only use if PUSH_ARGUMENTS is not defined.
+ * infcmd.c (do_registers_info): Only need prototype if
+ DO_REGISTERS_INFO is not defined.
+ (breakpoint_auto_delete_contents): Only need if
+ CALL_DUMMY_BREAKPOINT_OFFSET is defined.
+
+Sat Jul 27 08:49:49 1996 Fred Fish <fnf@cygnus.com>
+
+ * xcoffread.c (xcoff_end_psymtab): Add textlow_not_set parameter.
+ (END_PSYMTAB): Ditto.
+ (scan_xcoff_symtab): Call xcoff_end_psymtab with textlow_not_set.
+
+Fri Jul 26 14:07:37 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * printcmd.c (_initialize_printcmd): Initialize
+ tm_print_insn_info.flavour.
+
+Thu Jul 25 19:41:31 1996 Fred Fish <fnf@cygnus.com>
+
+ * Makefile.in (scm-valprint.o): Depends upon gdbcore_h.
+ (arm-tdep.o): Ditto.
+ (dcache.o): Ditto.
+ (i386ly-tdep.o): Ditto.
+ (i960-tdep.o): Ditto.
+ (m68k-tdep.o): Ditto.
+ (nindy-tdep.o): Ditto.
+ (scm-lang.o): Ditto.
+ (w65-tdep.o): Ditto.
+ (z8k-tdep.o): Ditto.
+ (m68k-tdep.o): Depends upon value_h and gdb_string.h
+ (m2-valprint.o): Depends upon m2-lang.h.
+ (sparc-tdep.o): Depends upon gdb_string.h
+ (valprint.o): Depends upon valprint.h
+
+ * remote-e7000.c (notice_quit): Remove prototype.
+ * top.c (initialize_targets): Remove prototype, now in target.h.
+ * stabsread.c (resolve_cfront_continuation): Remove prototype.
+ * dbxread.c (resolve_cfront_continuation): Remove prototype.
+ * symfile.h (set_demangling_style): Remove prototype.
+ * config/tm-sysv4.h (in_plt_section): Remove prototype, in objfiles.h.
+ * config/sparc/tm-sparc.h (single_step): Remove extern decl, now in
+ target.h.
+ * config/arc/tm-arc.h (one_stepped, single_step): Remove extern decls,
+ now in target.h.
+ * ser-unix.c (hardwire_restore): Remove obsolete prototype.
+ * sparc-tdep.c (single_step): Remove forward decl of isbranch.
+ * scm-lang.c (find_function_in_inferior): Remove prototype.
+ (value_allocate_space_in_inferior): Ditto.
+ * infrun.c (write_pc_pid): Remove prototype, now in inferior.h.
+ * defs.h (strchr): Remove declarations, they are declared in
+ gdb_string.h also.
+ (strrchr): Ditto.
+ (strstr): Ditto.
+ (strtok): Ditto.
+ (strerror): Ditto.
+ * f-valprint.c (f77_print_array_1): Remove extra arg that was being
+ passed to f77_print_array_1.
+ * gdbtypes.c (add_name): Remove unused variables lenstrlen and lenstr.
+ * scm-exp.c (scm_istr2int): Remove unused variable "j".
+ (scm_parse): Remove unused variable "str".
+ * hp300ux-nat.c (store_inferior_register): Remove unused variable
+ "buf".
+ (store_inferior_registers): Remove unnecessary decl "registers".
+ * m68k-tdep.c (m68k_pop_frame): Remove unused variable "fi".
+ * scm-lang.c (scm_get_field): Remove unused variable "val".
+ (scm_lookup_name): Remove unused variable "symval".
+ * objfiles.c (map_to_file): Remove unused local variable "tempfd".
+ * procfs.c (do_attach, do_detach): Remove unused variable "result".
+ (last_resume_pid): Remove unused static variable.
+ * alpha-tdep.c (alpha_linux_sigtramp_offset): Remove unused variable
+ "res".
+ * objfiles.c (map_to_address): Remove unused function.
+ * f-valprint.c (print_max): Remove extraneous extern decl,
+ in valprint.h.
+ (calc_f77_array_dims): Remove extraneous prototype, in f-lang.h.
+ * ch-exp.c (write_lower_upper_value): Remove prototype for
+ type_lower_upper.
+
+ * gdbtypes.c (cfront_mangle_name): #ifdef out unused function.
+ * ch-exp.c (parse_mode_call): Ditto.
+ * f-valprint.c (there_is_a_visible_common_named): Ditto.
+ * f-lang.c (clear_function_list): Ditto.
+ (get_bf_for_fcn): Ditto.
+ (clear_bf_list): Ditto.
+ (add_common_block): Ditto.
+ (patch_all_commons_by_name): Ditto.
+ (find_first_common_named): Ditto.
+ (add_common_entry): Ditto.
+ (allocate_saved_function_node): Ditto.
+ (allocate_saved_bf_node): Ditto.
+ (allocate_common_entry_node): Ditto.
+ (allocate_saved_f77_common_node): Ditto.
+
+ * arm-tdep.c (gdbcore.h): Include for necessary prototypes.
+ * dcache.c (gdbcore.h): Ditto.
+ * i386ly-tdep.c (gdbcore.h): Ditto.
+ * i960-tdep.c (gdbcore.h): Ditto.
+ * m2-valprint.c (m2-lang.h): Ditto.
+ * m68k-tdep.c (gdbcore.h): Ditto.
+ (value.h): Ditto.
+ (gdb_string.h): Ditto.
+ * nindy-tdep.c (gdbcore.h): Ditto.
+ * scm-lang.c (gdbcore.h): Ditto.
+ * scm-valprint.c (gdbcore.h): Ditto.
+ * w65-tdep.c (gdbcore.h): Ditto.
+ * z8k-tdep.c (gdbcore.h): Ditto.
+ * sparc-tdep.c (gdb_string.h): Include.
+ * valprint.c (valprint.h): Include.
+
+ * config/xm-lynx.h: Remove part of comment about INT_MIN
+ redefined warnings from defs.h, since INT_MIN define in
+ defs.h is now protected by #ifndef INT_MIN.
+ * config/i386/xm-i386bsd.h: Ditto.
+ * config/m68k/xm-hp300bsd.h: Ditto.
+ * config/m68k/xm-news.h: Ditto.
+
+ * config/pa/xm-hppah.h (INT_MIN): Remove bogus INT_MIN
+ definition as 0x80000000. The macro in defs.h is better.
+ * config/i386/xm-i386m3.h (INT_MIN): Ditto.
+ * config/i386/xm-i386mach.h (INT_MIN): Ditto.
+ * config/ns32k/xm-ns32km3.h (INT_MIN): Ditto.
+ * config/pa/xm-hppab.h: Ditto.
+
+ * core-aout.c (fetch_core_registers): Add prototype.
+ * hp300ux-nat.c (fetch_inferior_register): Ditto.
+ (store_inferior_register_1): Ditto.
+ (store_inferior_register): Ditto.
+ * config/m68k/tm-m68k.h (find_saved_regs): Ditto.
+ *scm-valprint.c (c_val_print): Ditto.
+ * procfs.c (add_fd): Ditto.
+ (remove_fd): Ditto.
+ (wait_fd): Ditto.
+ (sigcodename): Ditto.
+ (sigcodedesc): Ditto.
+ (procfs_kill_inferior): Ditto.
+ (procfs_xfer_memory): Ditto.
+ (procfs_store_registers): Ditto.
+ (create_procinfo): Ditto.
+ (procfs_init_inferior): Ditto.
+ (proc_set_exec_trap): Ditto.
+ (procfs_attach): Ditto.
+ (procfs_detach): Ditto.
+ (procfs_prepare_to_store): Ditto.
+ (procfs_files_info): Ditto.
+ (procfs_open): Ditto.
+ (procfs_wait): Ditto.
+ (procfs_fetch_registers): Ditto.
+ (procfs_mourn_inferior): Ditto.
+ (procfs_can_run): Ditto.
+ (procfs_thread_alive): Ditto.
+ (procfs_stop): Ditto.
+ * alpha-nat.c (fetch_core_registers): Ditto.
+ * config/alpha/tm-alpha.h (alpha_osf_skip_sigtramp_frame): Ditto.
+ * objfiles.c (ecoff_relocate_efi): Ditto.
+ * inflow.c (pass_signal): Ditto.
+ (handle_sigio): Ditto.
+ * annotate.c (breakpoint_changed): Ditto.
+ * callback.c (wrap): Ditto.
+ (fdbad): Ditto.
+ (fdmap): Ditto.
+ * utils.c (malloc_botch): Ditto.
+ (fputs_maybe_filtered): Ditto.
+ (vfprintf_maybe_filtered): Ditto.
+ * defs.h (notice_quit): Ditto.
+ * defs.h (xmalloc, xrealloc): Ditto.
+ * top.c (stop_sig): Ditto.
+ (init_signals): Ditto.
+ (user_defined_command): Ditto.
+ (source_cleanup_lines): Ditto.
+ (dont_repeat_command): Ditto.
+ (serial_log_command): Ditto.
+ (disconnect): Ditto.
+ * target.h (initialize_targets): Ditto.
+ * os9kread.c (read_minimal_symbols): Ditto.
+ * mdebugread.c (mdebug_psymtab_to_symtab): Ditto.
+ (fdr_name): Ditto.
+ (push_parse_stack): Ditto.
+ (pop_parse_stack): Ditto.
+ (is_pending_symbol): Ditto.
+ (add_pending): Ditto.
+ * serial.c (serial_logchar): Ditto.
+ (serial_interface_lookup): Ditto.
+ * serial.h (serial_log_command): Ditto.
+ * f-valprint.c (info_common_command): Ditto.
+ * gdbtypes.h (print_type_scalar): Ditto.
+ * scm-valprint.c (scm_scmlist_print): Ditto.
+ (scm_ipruk): Ditto.
+ * scm-lang.c (scm_printstr): Ditto.
+ (in_eval_c): Ditto.
+ (evaluate_subexp_scm): Ditto.
+ * scm-exp.c (scm_read_token): Ditto.
+ (scm_skip_ws): Ditto.
+ (scm_lreadparen): Ditto.
+ * m2-lang.c (emit_char): Ditto.
+ (m2_printchar): Ditto.
+ (m2_printstr): Ditto.
+ (m2_create_fundamental_type): Ditto.
+ * f-lang.c (emit_char): Ditto.
+ (f_printchar): Ditto.
+ (f_printstr): Ditto.
+ (f_create_fundamental_type): Ditto.
+ * ch-lang.c (chill_printchar): Ditto.
+ (chill_printstr): Ditto.
+ (chill_create_fundamental_type): Ditto.
+ (value_chill_length): Ditto.
+ (value_chill_card): Ditto.
+ (value_chill_max_min): Ditto.
+ (evaluate_subexp_chill): Ditto.
+ * ch-exp.c (PEEK_TOKEN): Ditto.
+ (peek_token_): Ditto.
+ (forward_token_): Ditto.
+ (parse_case_label): Ditto.
+ (parse_opt_untyped_expr): Ditto.
+ (parse_unary_call): Ditto.
+ (parse_call): Ditto.
+ (parse_named_record_element): Ditto.
+ (parse_tuple_element): Ditto.
+ (parse_opt_element_list): Ditto.
+ (parse_tuple): Ditto.
+ (parse_primval): Ditto.
+ (parse_operand6): Ditto.
+ (parse_operand5): Ditto.
+ (parse_operand4): Ditto.
+ (parse_operand3): Ditto.
+ (parse_operand2): Ditto.
+ (parse_operand1): Ditto.
+ (parse_operand0): Ditto.
+ (parse_expr): Ditto.
+ (parse_then_alternative): Ditto.
+ (parse_else_alternative): Ditto.
+ (parse_if_expression): Ditto.
+ (parse_untyped_expr): Ditto.
+ (growbuf_by_size): Ditto.
+ (match_simple_name_string): Ditto.
+ (decode_integer_value): Ditto.
+ (decode_integer_literal): Ditto.
+ (match_float_literal): Ditto.
+ (match_float_literal): Ditto.
+ (match_string_literal): Ditto.
+ (match_character_literal): Ditto.
+ (match_integer_literal): Ditto.
+ (match_bitstring_literal): Ditto.
+ (write_lower_upper_value): Ditto.
+ * ch-lang.h (type_lower_upper): Ditto.
+ * c-lang.c (emit_char): Ditto.
+ * dwarfread.c (free_utypes): Ditto.
+ * stabsread.h (resolve_cfront_continuation): Ditto.
+ * stabsread.c (get_substring): Ditto.
+ (read_one_struct_field): Ditto.
+ * stabsread.h (process_later): Ditto.
+ * demangle.c (set_demangling_command): Ditto.
+ * defs.h (set_demangling_style): Ditto.
+ * maint.c (maintenance_info_command): Ditto.
+ (print_section_table): Ditto.
+ (maintenance_info_sections): Ditto.
+ (maintenance_print_command): Ditto.
+ * symtab.h (maintenance_print_statistics): Ditto.
+ * objfiles.h (in_plt_section): Ditto.
+ * objfiles.c (add_to_objfile_sections): Ditto.
+ * bcache.c (hash): Ditto.
+ (lookup_cache): Ditto.
+ * exec.c (bfdsec_to_vmap): Ditto.
+ (ignore): Ditto.
+ * f-exp.y (growbuf_by_size, match_string_literal): Ditto.
+ * language.c (unk_lang_printchar): Ditto.
+ (unk_lang_printstr): Ditto.
+ (unk_lang_create_fundamental_type): Ditto.
+ (unk_lang_print_type): Ditto.
+ (unk_lang_val_print): Ditto.
+ (unk_lang_value_print): Ditto.
+ * target.c (update_current_target): Ditto.
+ (debug_to_open): Ditto.
+ (debug_to_close): Ditto.
+ (debug_to_attach): Ditto.
+ (debug_to_detach): Ditto.
+ (debug_to_resume): Ditto.
+ (debug_to_wait): Ditto.
+ (debug_to_fetch_registers): Ditto.
+ (debug_to_store_registers): Ditto.
+ (debug_to_prepare_to_store): Ditto.
+ (debug_to_xfer_memory): Ditto.
+ (debug_to_files_info): Ditto.
+ (debug_to_insert_breakpoint): Ditto.
+ (debug_to_remove_breakpoint): Ditto.
+ (debug_to_terminal_init): Ditto.
+ (debug_to_terminal_inferior): Ditto.
+ (debug_to_terminal_ours_for_output): Ditto.
+ (debug_to_terminal_ours): Ditto.
+ (debug_to_terminal_info): Ditto.
+ (debug_to_kill): Ditto.
+ (debug_to_load): Ditto.
+ (debug_to_lookup_symbol): Ditto.
+ (debug_to_create_inferior): Ditto.
+ (debug_to_mourn_inferior): Ditto.
+ (debug_to_can_run): Ditto.
+ (debug_to_notice_signals): Ditto.
+ (debug_to_thread_alive): Ditto.
+ (debug_to_stop): Ditto.
+ * breakpoint.h (set_breakpoint_sal): Ditto.
+ * remote-utils.c (usage): Ditto.
+ * remote.c (set_thread): Ditto.
+ (remote_thread_alive): Ditto.
+ (get_offsets): Ditto.
+ (read_frame): Ditto.
+ (remote_insert_breakpoint): Ditto.
+ (remote_remove_breakpoint): Ditto.
+ * sparc-nat.c (fetch_core_registers): Ditto.
+ * corelow.c (add_to_thread_list): Ditto.
+ (ignore): Ditto.
+ * inftarg.c (proc_wait): Ditto.
+ * infptrace.c (udot_info): Ditto.
+ (fetch_register): Ditto.
+ * ser-unix.c (hardwire_noflush_set_tty_state): Ditto.
+ (hardwire_print_tty_state): Ditto.
+ (hardwire_flush_output): Ditto.
+ (hardwire_flush_input): Ditto.
+ (hardwire_send_break): Ditto.
+ (hardwire_setstopbits): Ditto.
+ * ser-tcp.c (tcp_return_0): Ditto.
+ (tcp_noflush_set_tty_state): Ditto.
+ (tcp_print_tty_state): Ditto.
+ * solib.c (match_main): Ditto.
+ * gdbtypes.c (print_bit_vector): Ditto.
+ (print_arg_types): Ditto.
+ (dump_fn_fieldlists): Ditto.
+ (print_cplus_stuff): Ditto.
+ * symfile.h (entry_point_address): Ditto.
+ * symfile.c (decrement_reading_symtab): Ditto.
+ * valops.c (value_arg_coerce): Ditto.
+ * value.h (find_function_in_inferior): Ditto.
+ (value_allocate_space_in_inferior): Ditto.
+ * values.c (vb_match): Ditto.
+ * thread.c (info_thread_command): Ditto.
+ (restore_current_thread): Ditto.
+ (thread_apply_all_command): Ditto.
+ (thread_apply_command): Ditto.
+ * inferior.h (write_pc_pid): Ditto.
+ * infrun.c (delete_breakpoint_current_contents): Ditto.
+ * breakpoint.c (print_it_normal): Ditto.
+ (watchpoint_check): Ditto.
+ (print_it_done): Ditto.
+ (print_it_noop): Ditto.
+ (maintenance_info_breakpoints): Ditto.
+ (create_longjmp_breakpoint): Ditto.
+ (hbreak_command): Ditto.
+ (thbreak_command): Ditto.
+ (watch_commnd_1): Ditto.
+ (rwatch_command): Ditto.
+ (awatch_command): Ditto.
+ (do_enable_breakpoint): Ditto.
+ * ch-valprint.c (chill_val_print_array_elements): Ditto.
+ * eval.c (evaluate_subexp): Ditto.
+ (get_label): Ditto.
+ (evaluate_struct_tuple): Ditto.
+ * eval.c (init_array_element): Ditto.
+
+ * alpha-tdep.c (push_sigtramp_desc): Add prototype and make static.
+ * breakpoint.c (hw_breakpoint_used_count): Ditto.
+ (hw_watchpoint_used_count): Ditto.
+ * findvar.c (write_register_gen): Ditto.
+ (read_register_pid): Ditto.
+ * symtab.c (cplusplus_hint): Ditto.
+ * infcmd.c (breakpoint_auto_delete_contents): Ditto.
+ * ch-valprint.c (chill_print_type_scalar): Ditto.
+ * gdbtypes.c (add_name): Ditto.
+ (add_mangled_type): Ditto.
+ (cfront_mangle_name): Ditto.
+ * sparc-tdep.c (isbranch): Ditto.
+ * inftarg.c (child_stop): Ditto.
+ * win32-nat.c (child_stop): Ditto.
+ * mac-nat.c (child_stop): Ditto.
+ * remote-utils.c (sr_com): Ditto.
+ * dbxread.c (process_now): Ditto.
+ * ch-exp.c (require): Ditto.
+ (check_token): Ditto.
+ (expect): Ditto.
+ (parse_mode_call): Ditto.
+ (parse_mode_or_normal_call): Ditto.
+ * scm-lang.c (scm_lookup_name): Ditto
+ * f-lang.c (allocate_saved_bf_node): Ditto.
+ (allocate_saved_function_node): Ditto.
+ (allocate_saved_f77_common_node): Ditto.
+ (allocate_common_entry_node): Ditto.
+ (add_common_block): Ditto.
+ (add_common_entry): Ditto.
+ (find_first_common_named): Ditto.
+ (patch_common_entries): Ditto.
+ (patch_all_commons_by_name): Ditto.
+ (clear_bf_list): Ditto.
+ (get_bf_for_fcn): Ditto.
+ (clear_function_list): Ditto.
+ * scm-exp.c (scm_istr2int): Ditto.
+ (scm_istring2number): Ditto.
+ * scm-valprint.c (scm_inferior_print): Ditto.
+ * f-typeprint.c (print_equivalent_f77_float_type): Ditto.
+ * f-valprint.c (f77_get_dynamic_length_of_aggregate): Ditto.
+ (f77_create_arrayprint_offset_tbl): Ditto.
+ (f77_print_array_1): Ditto.
+ (f77_print_array): Ditto.
+ (list_all_visible_commons): Ditto.
+ (there_is_a_visible_common_named): Ditto.
+ * mdebugread.c (ecoff_relocate_efi): Ditto.
+ * callback.c (os_close): Ditto.
+ (os_get_errno): Ditto.
+ (os_isatty): Ditto.
+ (os_lseek): Ditto.
+ (os_open): Ditto.
+ (os_read): Ditto.
+ (os_read_stdin): Ditto.
+ (os_write): Ditto.
+ (os_write_stdout): Ditto.
+ (os_rename): Ditto.
+ (os_system): Ditto.
+ (os_time): Ditto.
+ (os_unlink): Ditto.
+ (os_shutdown): Ditto.
+ (os_init): Ditto.
+ (os_printf_filtered): Ditto.
+
+ * scm-lang.h (scm_parse): Change old style decl to prototype.
+ * config/alpha/tm-alphalinux.h (alpha_linux_sigtramp_offset): Ditto.
+ * top.c (init_proc): Ditto.
+ (query_hook): Ditto.
+ (error_hook): Ditto.
+ * f-lang.c (c_value_print): Ditto.
+ * ch-exp.c (parse_expression): Ditto.
+ (parse_primval): Ditto.
+ (parse_untyped_expr): Ditto.
+ (parse_opt_untyped_expr): Ditto.
+ (ch_lex): Ditto.
+ * config/sparc/tm-sparc.h (sparc_init_extra_frame_info): Ditto.
+ (sparc_frame_saved_pc): Ditto.
+ (sparc_push_dummy_frame): Ditto.
+ (sparc_pop_frame): Ditto.
+ * defs.h (fclose): Ditto.
+ (atof): Ditto.
+ (error_hook): Ditto.
+
+ * arc-tdep.c (single_step): Change arg to type "enum target_signal".
+ * rs6000-tdep.c (single_step): Ditto.
+ * sparc-tdep.c (single_step): Ditto.
+
+ * breakpoint.c (cleanup_executing_breakpoints): Change unused arg type
+ to PTR which is what make_cleanup expects.
+ * utils.c (null_cleanup): Change arg type to PTR.
+ * defs.h (null_cleanup): Change prototype to match actual function.
+ * config/sparc/tm-sparc.h (struct frame_info): Move forward decl.
+ * ch-valprint.c (chill_val_print): Cast 2nd arg of
+ chill_print_type_scalar to LONGEST.
+ * infrun.c (wait_for_inferior): Have empty switch case for
+ BPSTAT_WHAT_CHECK_SHLIBS when SOLIB_ADD is not defined.
+ (stop_on_solib_events): Only needed if SOLIB_ADD is defined.
+ * infcmd.c (attach_command): Only need auto_solib_add if SOLIB_ADD
+ is defined.
+ * symfile.c (generic_load): Scan long int using a long int spec,
+ not an int spec.
+ * infptrace.c (udot_info): Only need local variables if KERNEL_U_SIZE
+ is defined.
+ (fetch_register): Only need function if FETCH_INFERIOR_REGISTERS is
+ not defined.
+ * inflow.c (handle_sigio): Only need prototype when the actual
+ function is compiled in.
+ * valprint.c (longest_to_int): Expand error message to be
+ separate messages for args larger than largest signed int
+ and args smaller than smallest signed int.
+ * valprint.c (print_longest): Fix problems with support for case
+ where compiler supports type "long long" but the runtime doesn't
+ support printing them with "%ll".
+ * scm-valprint.c (scm_scmlist_print, scm_scmval_print): Change
+ return types to void since we don't actually return anything
+ meaningful and callees ignore the values anyway.
+ * procfs.c (modify_inherit_on_fork_flag): Enclose pr_flags in PIOCSET
+ ifdef.
+ (modify_run_on_last_close_flag): Ditto.
+ (wait_fd): Enclose local variables "num_fds" and "i" LOSING_POLL
+ ifdef
+ * alpha-tdep.c (push_sigtramp_desc): Return proc_desc rather than
+ random value.
+ * infrun.c (wait_for_inferior): Ensure random_signal is not used
+ uninitialized.
+ * valops.c (call_function_by_hand): Ensure struct_addr is not used
+ uninitialized.
+ * breakpoint.c (watch_command_1): Ensure prev_frame is not used
+ uninitialized.
+ * utils.c (vfprintf_maybe_filtered): Change second arg from "char *"
+ to "const char *".
+ * infptrace.c (udot_info): Add two dummy args so that the type is
+ correct for passing to add_info.
+ * f-lang.c (saved_fcn): Move decl to head of file so it can be used
+ in prototypes.
+ (saved_bf_symnum): Ditto.
+ (SAVED_FUNCTION): Ditto.
+ (SAVED_FUNCTION_PTR): Ditto.
+ (SAVED_BF): Ditto.
+ (SAVED_BF_PTR): Ditto.
+ * ch-exp.c (parse_named_record_element): Build error message in
+ temporary buffer before passing it to expect, rather than passing
+ wrong number of args to expect.
+ * demangle.c (set_demangling_style): Call set_demangling_command with
+ correct number of arguments.
+ * inferior.h (terminal_init_inferior_with_pgrp): Change arg type to
+ int to match actual function.
+ (os_isatty): Call fdmap with right number of arguments, was missing
+ the host_callback* arg.
+ * target.c (cleanup_target): Prototype all functions casts.
+ * target.h (one_stepped, single_step): Declare here and convert
+ single_step to prototype.
+ * infrun.c (one_stepped, single_step): Don't declare externs
+ here, they have moved to target.h.
+ * eval.c (init_array_element): Declare previously undeclared
+ last two args as LONGEST.
+ * dcache.c (dcache_xfer_memory): Change xfunc decls to prototype form.
+
+Thu Jul 25 16:11:54 1996 Doug Evans <dje@canuck.cygnus.com>
+
+ * dsrec.c (load_srec): Protect ANSI style function parms with PARAMS.
+
+Mon Jul 22 18:13:27 1996 Stu Grossman (grossman@critters.cygnus.com)
+
+ * Makefile.in (os9kread.o): Remove dependency on partial-stab.h.
+ * dbxread.c (read_dbx_symtab end_psymtab), partial-stab.h: Don't
+ use partial_symtab->textlow==0 as a flag, as 0 is a legitimate
+ text address. Use a seperate flag (textlow_not_set) instead.
+ This makes stabs in ELF .o files work a lot better.
+ * mdebugread.c xcoffread.c: Define textlow_not_set for
+ partial-stab.h.
+ * stabsread.h (end_psymtab): Add textlow_not_set arg to prototype.
+
+Sat Jul 20 10:41:06 1996 Fred Fish <fnf@cygnus.com>
+
+ * dwarf2read.c (struct filenames): Change internal "struct file"
+ to "struct fileinfo" to avoid conflict with "struct file" in
+ <sys/file.h> on HPUX and Solaris.
+
+Fri Jul 19 14:05:57 1996 Stan Shebs <shebs@andros.cygnus.com>
+
+ * dwarf2read.c: New file, DWARF 2 reader originally contributed by
+ Brent Benson, with additions by Gary Funck and Jerry Kreuscher.
+ * Makefile.in (COMMON_OBS): Add dwarf2read.o.
+ (SFILES): Add dwarf2read.c.
+ (dwarf2read.o): Add build rule.
+ * symfile.h (dwarf2_has_info, dwarf2_build_psymtabs): Declare
+ exported functions.
+ * elfread.c (elf_symfile_read): Call them.
+ (elf_symtab_read) [HARRIS_TARGET]: Skip some special symbols.
+
+Thu Jul 18 01:22:01 1996 Geoffrey Noer <noer@cygnus.com>
+
+ * symfile.c (symfile_bfd_open):
+ * exec.c (exec_file_command): for __GO32__ and __WIN32__ systems,
+ free the user from having to type the .exe extension.
+
+Wed Jul 17 06:54:50 1996 Mark Alexander <marka@cygnus.com>
+
+ * mon960-rom.c: Shorten the mon960_inits string to a single
+ carriage return; this prevents a hang on connecting immediately
+ after powerup, when MON960 is attempting autobaud detection.
+
+Tue Jul 16 23:47:04 1996 Mark Alexander <marka@cygnus.com>
+
+ * a29k-tdep.c (get_saved_register): Allow PC to be modified
+ when innermost frame is selected, but not in outer frames.
+
+Tue Jul 16 23:37:25 1996 Stu Grossman (grossman@critters.cygnus.com)
+
+ * command.c (do_setshow_command): Don't segfault when showing
+ var_string and var_string_noescape vars that are NULL.
+
+Mon Jul 15 16:55:48 1996 Doug Evans <dje@canuck.cygnus.com>
+
+ * win32-nat.c (handle_load_dll): dos_path_to_unix_path renamed to
+ cygwin32_conv_to_posix_path.
+ (child_create_inferior): unix_path_to_dos_path renamed to
+ cygwin32_conv_to_win32_path. Rewrite code to translate PATH.
+
+Mon Jul 15 16:44:05 1996 Stu Grossman (grossman@critters.cygnus.com)
+
+ * defs.h printcmd.c: Create global disassemble_info structure
+ tm_print_insn_info.
+ * i386-tdep.c (set_assembly_language_command): set
+ tm_print_insn_info.mach to the appropriate value for 386 or 8086
+ disassembly.
+ * printcmd.c (print_insn): Move init of disassembler_info to
+ _initialize_printcmd. Set endian for disassembler here.
+ * sparc-tdep.c: Set tm_print_insn_info.mach as appropriate to
+ select sparc/sparclite.
+ * config/sparc/{tm-sparc.h tm-sparclite.h}: Get rid of
+ TM_PRINT_INSN. Set TM_PRINT_INSN_MACH to
+ bfd_mach_sparc/bfd_mach_sparc_sparclite.
+
+Fri Jul 12 19:04:32 1996 Fred Fish <fnf@cygnus.com>
+
+ * hpread.c (hpread_lookup_type): Use xmmalloc/xmrealloc rather
+ than xmalloc/xrealloc.
+
+Fri Jul 12 17:59:47 1996 Fred Fish <fnf@cygnus.com>
+
+ * objfiles.c (map_to_file): Error return from mmalloc_findbase is
+ a NULL pointer, not a -1.
+
+Fri Jul 12 10:16:24 1996 Stu Grossman (grossman@critters.cygnus.com)
+
+ * i386-tdep.c (set_assembly_language_command): New routine to
+ select between i386 and i8086 instruction sets for disassembly.
+ New command `set assembly-language {i386 i8086}'.
+
+Thu Jul 11 21:13:21 1996 Mark Alexander <marka@cygnus.com>
+
+ * monitor.c (monitor_write_memory, monitor_read_memory_single):
+ Disable use of "long long" memory read/write commands; can't
+ use them because we hold the values to read/write in an int
+ variable, and because strtoul fails on values that exceed the
+ size of a long. This fixes breakpoint problems on MON960.
+
+Thu Jul 11 11:39:31 1996 Fred Fish <fnf@cygnus.com>
+
+ * config/m68k/xm-hp300hpux.h (HAVE_MMAP): Remove definition.
+ * config/pa/xm-hppah.h (HAVE_MMAP): Ditto.
+
+Wed Jul 10 16:54:41 1996 Fred Fish <fnf@cygnus.com>
+
+ * Makefile.in (MMALLOC_CFLAGS): Eliminate intermediate MMALLOC_DISABLE
+ and MMALLOC_CHECK macros, and add comment indicating how host dependent
+ makefile fragment should modify MMALLOC_CFLAGS to not use mmalloc, or
+ to use it but to not do heap corruption checking.
+ * gdbserver/Makefile.in: Ditto.
+ * utils.c (init_malloc): Replace warning() use with direct call of
+ fprintf_unfiltered, since current_target has not yet been set and thus
+ we cannot use warning(). If we try to use mmcheck and it fails,
+ suggest that this configuration needs NO_MMCHECK or MMCHECK_FORCE
+ defined. Other small mmalloc related cleanups.
+ * config/sparc/sun4os4.mh (MMALLOC_CFLAGS): Define MMCHECK_FORCE to 1.
+ * config/alpha/alpha-osf2.mh (MMALLOC_CFLAGS): Set to -DNO_MMCHECK.
+
+ * config/sparc/xm-sun4os4.h (MMAP_BASE_ADDRESS, MMAP_INCREMENT):
+ * config/i386/xm-i386v4.h (MMAP_BASE_ADDRESS, MMAP_INCREMENT):
+ * config/i386/xm-linux.h (MMAP_BASE_ADDRESS, MMAP_INCREMENT):
+ * config/m68k/xm-hp300hpux.h (MMAP_BASE_ADDRESS, MMAP_INCREMENT):
+ * config/m68k/xm-m68kv4.h (MMAP_BASE_ADDRESS, MMAP_INCREMENT);
+ * config/m68k/xm-sun3os4.h (MMAP_BASE_ADDRESS, MMAP_INCREMENT):
+ * config/pa/xm-hppah.h (MMAP_BASE_ADDRESS, MMAP_INCREMENT):
+ * config/sparc/xm-sun4sol2.h (MMAP_BASE_ADDRESS, MMAP_INCREMENT):
+ Remove obsolete defines.
+
+ * config/alpha/alpha-linux.mh (MMALLOC_DISABLE):
+ * config/alpha/alpha-osf1.mh (MMALLOC_DISABLE):
+ * config/rs6000/rs6000.mh (MMALLOC_DISABLE):
+ * config/rs6000/aix4.mh (MMALLOC_DISABLE):
+ * config/powerpc/aix4.mh (MMALLOC_DISABLE):
+ * config/powerpc/aix.mh (MMALLOC_DISABLE):
+ * config/ns32k/ns32km3.mh (MMALLOC_DISABLE):
+ * config/mips/mipsm3.mh (MMALLOC_DISABLE):
+ * config/mips/decstation.mh (MMALLOC_DISABLE):
+ * config/m88k/cxux.mh (MMALLOC_DISABLE):
+ * config/i386/i386mk.mh (MMALLOC_DISABLE):
+ * config/i386/i386m3.mh (MMALLOC_DISABLE):
+ * config/i386/i386gnu.mh (MMALLOC_DISABLE):
+ Use MMALLOC_CFLAGS instead.
+
+Tue Jul 9 22:41:12 1996 Jeffrey A Law (law@cygnus.com)
+
+ * h8300-tdep.c: Remove some outdated comments.
+ (h8300_skip_prologue): Rework to be more correct for the H8/300H.
+ Handle stm.l insns for the H8/S.
+ (examine_prologue): Likewise.
+
+Tue Jul 9 16:48:55 1996 Raymond Jou <rjou@mexican.cygnus.com>
+
+ * ser-mac.c (mac_close): Change a typo SetSetBuf to SerSetBuf.
+
+Mon Jul 08 08:50:39 1996 Mark Alexander <marka@cygnus.com>
+
+ * mon960-rom.c (mon960_open): Add floating point detection to
+ prevent hang on non-FPU processors (PR 9775).
+ (mon960_cmds): Swap setmem.cmdw and setmem.cmdl to fix problem
+ setting breakpoints and improve loading speed.
+
+Sun Jul 7 14:57:34 1996 Fred Fish <fnf@cygnus.com>
+
+ * coffread.c (record_minimal_symbol): Don't presave name string
+ on symbol_obstack before passing to prim_record_minimal_symbol.
+ It now handles saving the string itself.
+ * dbxread.c (read_dbx_dynamic_symtab): Ditto.
+ * mipsread.c (read_alphacoff_dynamic_symtab): Ditto.
+ * os9kread.c (record_minimal_symbol): Ditto.
+ * solib.c (solib_add_common_symbols): Ditto.
+
+ * coffread.c (coff_symtab_read): Don't presave name string on
+ symbol_obstack before passing to prim_record_minimal_symbol_and_info.
+ It now handles saving the string itself.
+ * dbxread.c (record_minimal_symbol): Ditto.
+ * elfread.c (record_minimal_symbol_and_info): Ditto.
+
+ * dstread.c (record_minimal_symbol): Remove static function that just
+ called prim_record_minimal_symbol with the same args (after change to
+ prim_record_minimal_symbol to do it's own name string saves).
+ * nlmread.c (record_minimal_symbol): Ditto.
+ * somread.c (record_minimal_symbol): Ditto.
+
+ * hpread.c (hpread_read_enum_type): Save symbol name on symbol obstack.
+ (hpread_read_function_type): Ditto.
+ (hpread_process_one_debug_symbol): Ditto.
+ * mdebugread.c (parse_symbol): Ditto.
+ (new_symbol): Ditto.
+ * minsyms.c (prim_record_minimal_symbol_and_info): Ditto.
+
+ * coffread.c (process_coff_symbol): Use obsavestring to save
+ SYMBOL_NAME, rather than obstack_copy0.
+ * dstread.c (create_new_symbol): Ditto
+ * symfile.c (obconcat): Ditto.
+ * stabsread.c (patch_block_stabs): Ditto.
+ * xcoffread.c (SYMNAME_ALLOC): Ditto.
+
+ * symfile.c (obsavestring): Update comments
+ * solib.c (solib_add_common_symbols): Remove local var origname.
+
+Wed Jul 3 15:56:08 1996 Stu Grossman (grossman@critters.cygnus.com)
+
+ * configure: Re-build with autoconf-2.10.
+
+ * sparcl-tdep.c (_initialize_sparc_tdep) config/sparc/tm-sparc.h,
+ config/sparc/tm-sparclite.h: Initialize tm_print_insn from
+ TM_PRINT_INSN, which comes from the tm file.
+
+Tue Jul 02 21:41:20 1996 Mark Alexander <marka@cygnus.com>
+
+ * coffread.c, dbxread.c, elfread.c, mipsread.c, nlmread.c,
+ os9kread.c: Replace identical sym_offsets functions with
+ default_symfile_offsets.
+ * somread.c (som_symfile_offsets): Use new SIZEOF_SECTION_OFFSETS
+ macro to allocate section_offsets.
+ * symfile.c (default_symfile_offsets): New function.
+ * symfile.h: Declare default_symfile_offsets.
+ * symtab.h: Define SIZEOF_SECTION_OFFSETS macro to
+ simplify allocation of section_offsets.
+
+Tue Jun 11 12:02:55 1996 Stu Grossman (grossman@critters.cygnus.com)
+
+ * Makefile.in (INTERNAL_LDFLAGS): Add in flags from configure.
+ * configure configure.in: Only make sol-thread.o for native.
+ Also, switch to dlopened libthread_db.so.1.
+ * sol-thread.c: Switch to using dlopen to get the thread_db
+ library.
+
+Thu Jun 13 16:53:25 1996 Stu Grossman (grossman@critters.cygnus.com)
+
+ * configure, configure.in: Change test for libthread_db to only
+ work for configs where build/host/target are the same.
+
+Tue Jul 2 15:04:20 1996 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * config/powerpc/{linux.mh,xm-linux.h}: New files, for Linux on
+ PowerPC.
+
+ * configure.in (powerpc-*-linux): Add Linux, System V, and ELF
+ support.
+ * configure: Regenerate.
+
+Mon Jul 1 13:00:43 1996 Stan Shebs <shebs@andros.cygnus.com>
+
+ From Raymond Jou <rjou@mexican.cygnus.com>:
+ * mpw-make.sed: Add lines to whack out autoconf hook
+ @CONFIG_LDFLAGS@.
+
+Mon Jul 01 11:07:15 1996 Mark Alexander <marka@cygnus.com>
+
+ * remote-e7000.c (e7000_stop): New function.
+
+Fri Jun 28 06:34:19 1996 Dawn Perchik <dawn@cygnus.com>
+
+ * configure, configure.in: Add target sparclet.
+ * monitor.h, monitor.c: Added monitor flags MO_NO_ECHO_ON_SETMEM
+ (don't expect echo on setmem command), MO_RUN_FIRST_TIME (if
+ command to start process running on target is different from one
+ to continue execution), MO_HEX_PREFIX (if addresses from monitor
+ have a "0x" prefix).
+ * monitor.c, parse.c, sparc-tdep.c: Don't require strings in the
+ registers array. This is to allow NULLs to be place holders in
+ the tm-*.h file so that only minor changes are needed when a new
+ processor is introduced (eg, one without floating point).
+ * sparc-tdep.c: Conditionally remove dependancies on floating
+ point.
+ * sparclet-rom.c, config/sparc/sparclet.mt,
+ config/sparc/tm-sparclet.h: New files for target sparclet.
+ * symfile.c (load_command): Add option for 2nd parameter; a load
+ offset added to the vma of each section.
+
+Fri Jun 28 05:39:19 1996 Dawn Perchik <dawn@cygnus.com>
+
+ * main.c (main): Add option "l" for setting remote_timeout.
+
+Fri Jun 28 05:25:18 1996 Dawn Perchik <dawn@cygnus.com>
+
+ * remote-e7000.c, remote.c, target.h, top.c: Add set option
+ "remote_timeout" for setting remote_timeout. Add set option
+ "use_hard_breakpoints" for setting hardware .vs. memory
+ breakpoints.
+
+Fri Jun 28 04:32:18 1996 Dawn Perchik <dawn@cygnus.com>
+
+ * remote-e7000.c (e7000_parse_device): New function.
+ Add option "tcp_remote" to target command if using
+ tcp to connect to a remote host which is then connected
+ via serial port to the e7000 (for exampole, a port master).
+ (e7000_open): Change to call e7000_parse_device.
+
+Fri Jun 28 03:47:17 1996 Dawn Perchik <dawn@cygnus.com>
+
+ * monitor.c (monitor_debug): Fix remotedebug buffering.
+
+Thu Jun 27 18:24:17 1996 Stan Shebs <shebs@andros.cygnus.com>
+
+ * config/i386/cygwin32.mh, config/powerpc/cygwin32.mh
+ (NATDEPFILES): Add a space.
+
+Wed Jun 26 06:05:39 1996 Wilfried Moser <moser@rtl.cygnus.com>
+
+ * gdbtypes.c (create_array_type): If TYPE_LENGTH (result_type)
+ is zero, set TYPE_FLAG_TARGET_STUB to force reevaluation of the type.
+
+ * ch-exp.c (calculate_array_length): Function removed.
+
+Tue Jun 25 17:41:06 1996 Martin M. Hunt <hunt@pizza.cygnus.com>
+
+ * remote-e7000.c (e7000_read_inferior_memory_large): New function.
+ (e7000_xfer_inferior_memory): Call it.
+
+Tue Jun 25 23:14:07 1996 Jason Molenda (crash@godzilla.cygnus.co.jp)
+
+ * gdb/gdbserver/Makefile.in (docdir): Removed.
+
+Tue Jun 25 22:05:38 1996 Jason Molenda (crash@godzilla.cygnus.co.jp)
+
+ * Makefile.in (bindir, libdir, datadir, mandir, infodir, includedir):
+ Use autoconf set values.
+ (docdir): Removed.
+ * configure.in (AC_PREREQ): autoconf 2.5 or higher.
+ * nlm/Makefile.in (bindir, libdir, datadir, mandir, infodir,
+ includedir): Use autoconf set values.
+ (docdir): Removed.
+ * nlm/configure.in (AC_PREREQ): autoconf 2.5 or higher.
+ * nlm/configure: Rebuilt.
+ * gdb/gdbserver/Makefile.in (datadir): Set to $(prefix)/share.
+
+Mon Jun 24 09:56:14 1996 Angela Marie Thomas (angela@cygnus.com)
+
+ * stabsread.c (read_cfront_member_functions): add type
+
+Sun Jun 23 23:40:48 1996 Doug Evans <dje@canuck.cygnus.com>
+
+ * win32-nat.c: #include <unistd.h>.
+ (unix_paths_to_dos_paths, dos_paths_to_unix_paths): Delete.
+ (child_create_inferior): Convert only env var PATH to win32 style.
+ (set_pathstyle_dos): Delete.
+ (_initialize_inftarg): Delete dos-path-style command.
+
+Thu Jun 20 13:42:23 1996 Doug Evans <dje@canuck.cygnus.com>
+
+ * configure.in: Revise sol-thread.o test.
+ * configure: Regenerated.
+
+ * source.c (find_source_lines): Reassign size to result of read.
+
+Tue Jun 18 16:25:54 1996 Jeffrey A. Law <law@rtl.cygnus.com>
+
+ * h8300-dep.c (gdb_print_insn_h8300): Handle the H8/S.
+ (h8300_command): Likewise.
+ (set_machine): Likewise.
+ (set_machine_hook): Likewise.
+ (_initialize_h8300m): Likewise.
+
+ * config/h8300/tm-h8300.h (h8300smode): Declare.
+
+Sun Jun 16 15:21:51 1996 Jeffrey A. Law <law@rtl.cygnus.com>
+
+ * somsolib.c (som_solib_create_inferior_hook): Handle tracking
+ of shl_load calls for hpux10.
+
+Thu Jun 13 11:16:10 1996 Tom Tromey <tromey@thepub.cygnus.com>
+
+ * config.in: Regenerated.
+ * acconfig.h (HAVE_THREAD_DB_LIB): Added entry.
+
+ * configure: Regenerated.
+ * aclocal.m4 (CY_AC_PATH_TCLH, CY_AC_PATH_TKH): Use odd names to
+ avoid name clashes with SunOS headers.
+
+Tue Jun 11 19:52:50 1996 Fred Fish <fnf@cygnus.com>
+
+ From Michael Snyder <Michael_Snyder@next.com>:
+ * bcache.c (print_bcache_statistics): Avoid divide-by-zero
+ exception if one or more objfile has no symbols, such as when
+ a dynamic library has been stripped.
+
+Tue Jun 11 12:02:55 1996 Stu Grossman (grossman@critters.cygnus.com)
+
+ * Makefile.in (INTERNAL_LDFLAGS): Add in flags from configure.
+ * configure configure.in: Only make sol-thread.o for native.
+ Also, switch to dlopened libthread_db.so.1.
+ * sol-thread.c: Switch to using dlopen to get the thread_db
+ library.
+
+Mon Jun 10 14:17:19 1996 Fred Fish <fnf@cygnus.com>
+
+ * config/sparc/{xm-sun4sol2.h,xm-sun4os4.h} (MMAP_BASE_ADDRESS):
+ Change from 0xE0000000 to 0xC0000000.
+
+Thu Jun 6 17:10:32 1996 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * config/powerpc/xm-solaris.h: Initial version of support for
+ Solaris on PowerPC.
+
+Wed Jun 5 01:52:57 1996 James G. Smith <jsmith@cygnus.co.uk>
+
+ * configure.in (configdirs): Force 4100 builds to use 4300 GDB
+ target.
+ * configure: Rebuild.
+
+ * config/mips/vr4300el.mt (SIM_OBS): Include simulator in
+ little-endian builds.
+
+Mon Jun 3 11:48:29 1996 Jeffrey A Law (law@cygnus.com)
+
+ * inftarg.c (child_thread_alive): Protect declaration with
+ #ifndef CHILD_THREAD_ALIVE.
+
+ * source.c (find_source_lines): Check the time on the symtab's bfd if
+ it exists, else check the time on the exec_bfd.
+
+Thu May 30 09:43:17 1996 Mark Alexander <marka@cygnus.com>
+
+ * dsrec.c (make_srec): Fix calculation of address size
+ to allow addresses less than 0x100.
+
+Thu May 30 04:24:09 1996 Wilfried Moser <moser@rtl.cygnus.com>
+
+ * ch-exp.c (ch_lex): In case of LOC_TYPEDEF call calculate_array_length.
+
+Tue May 28 16:15:47 1996 Geoffrey Noer <noer@cygnus.com>
+
+ * remote-mips.c: cannot use EINVAL for breakpoint test since
+ its value varies for different hosts (e.g. go32's is 19, while
+ sunos is 22). Changed to hardcoded 22 since that is what the
+ mips boards return.
+
+Tue May 28 11:14:58 1996 Tom Tromey <tromey@creche.cygnus.com>
+
+ * configure: Regenerated.
+ * aclocal.m4 (CY_AC_PATH_TCLH): Don't use AC_TRY_RUN.
+ (CY_AC_PATH_TKH): Don't use AC_TRY_RUN.
+
+Sun May 26 16:56:35 1996 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * solib.c (solib_absolute_prefix, solib_search_path): New variables.
+ (_initialize_solib): Add set/show commands for those variables.
+ (solib_map_sections): Implement searching using them.
+
+Sun May 26 14:14:49 1996 Fred Fish <fnf@cygnus.com>
+
+ Changes from: David Mosberger-Tang <davidm@azstarnet.com>
+
+ * NEWS: Add Alpha Linux as a new native configuration.
+
+ * mdebugread.c (parse_symbol): When we find a malloc() symbol with
+ return type VOID, assume no debugging info is available for that
+ object file and patch the return value into VOID *. Otherwise,
+ operations requiring an implicit call to malloc() will fail.
+
+ * infrun.c (wait_for_inferior): The criterion to detect entering a
+ sigtramp handler is now: (a) the current pc is inside a sigtramp
+ handler, (b) the previous pc is not in a sigtramp handler, and (c)
+ the current stack pointer is "inner" than the old one. Condition
+ (c) is new to avoid mistaking a return from a signal handler into
+ sigtramp as a new sigtramp invocation.
+
+ * dcache.c (struct dcache_block): Declare addr as CORE_ADDR. An
+ int may not be big enough to hold an address.
+ (dcache_hit): Ditto.
+ (dcache_peek_byte): Fix indentation.
+
+ * configure.in (alpha-*-linux*): Add target.
+ * configure: Rebuild
+
+ * config/alpha/tm-alpha.h (PROC_DESC_IS_DYN_SIGTRAMP): New macro.
+ (SET_PROC_DESC_IS_DYN_SIGTRAMP): Ditto.
+ (DYNAMIC_SIGTRAMP_OFFSET): Ditto.
+ (SIGCONTEXT_ADDR): Ditto.
+ (FRAME_PAST_SIGTRAMP_FRAME): Ditto.
+
+ * config/alpha/alpha-linux.mh: New file.
+ * config/alpha/alpha-linux.mt: Ditto.
+ * config/alpha/nm-linux.h: Ditto.
+ * config/alpha/tm-alphalinux.h: Ditto.
+ * config/alpha/xm-alphalinux.h: Ditto.
+ * config/alpha/xm-alphaosf.h: Renamed from xm-alpha.h.
+ * config/alpha/alpha-osf1.mh (XM_FILE): Change from xm-alpha.h to
+ xm-alphaosf.h.
+ * config/alpha/alpha-osf2.mh: Ditto.
+
+ * blockframe.c (find_pc_partial_function): Pass PC to
+ SIGTRAMP_START and SIGTRAMP_END macros for the benefit of systems
+ that detect sigtramp code via designated code sequences (as is the
+ case for Linux/Alpha, for example).
+
+ * config/i386/tm-i386bsd.h: Change SIGTRAMP_START and SIGTRAMP_END
+ to ignore new PC argument.
+ * config/m68k/tm-hp300bsd.h: Ditto.
+ * config/vax/tm-vax.h: Ditto.
+
+ * alpha-tdep.c (alpha_linux_sigtramp_offset): New function.
+ (alpha_osf_skip_sigtramp_frame): Ditto.
+ (push_sigtramp_desc): Ditto.
+ (alpha_find_saved_regs): Use SIGCONTEXT_ADDR macro to extract
+ sigcontext address from frame.
+ (alpha_saved_pc_after_call): When in sigtramp, use
+ alpha_frame_saved_pc() instead of read-register().
+ (after_prologue): When inside a dynamically generated sigtramp
+ function, there is no prologue, so return address of first
+ instruction.
+ (alpha_in_prologue): Fix typo in comment.
+ (find_proc_desc): Use macro DYNAMIC_SIGTRAMP_OFFSET to determine
+ whether we're inside a dynamicaly generated sigtramp function. If
+ so, create and push and appropriate procedure descriptor.
+ (alpha_frame_chain): Use macro FRAME_PAST_SIGTRAMP_FRAME to obtain
+ the frame past a sigtramp frame (if the current frame is indeed a
+ sigtramp function).
+ (init_extra_frame_info): Don't read next frame register off of
+ stack-pointer when inside a dynamiccaly generated sigtramp.
+ (alpha_pop_frame): Also unlink and destroy procedure descriptors
+ created for dynamically generated sigtramp functions.
+
+ * alpha-nat.c: When compiling under Linux, include <asm/reg.h> and
+ <alpha/ptrace.h> instead of <machine/reg.h>
+
+Tue Jul 2 13:58:10 1996 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * gnu-nat.c (inf_validate_task_sc):
+ Give terminal to gdb while asking question.
+ (inf_resume): Don't validate the task suspend-count while execing.
+
+Thu Jun 13 11:04:52 1996 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * gnu-nat.c (inf_validate_task_sc): Query user before clearing any
+ additional suspend count.
+ (S_proc_wait_reply, gnu_attach): Don't call inf_validate_task_sc.
+ (inf_resume): Call inf_validate_task_sc here.
+ (gnu_resume): Call inf_update_procs to ensure noticing new threads.
+
+Fri Jun 7 17:00:43 1996 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * gnu-nat.c (gnu_create_inferior: attach_to_child): Return PID.
+
+Thu May 23 15:13:56 1996 Jeffrey A Law (law@cygnus.com)
+
+ * h8300-tdep.c (IS_PUSH): Refine.
+ (IS_MOVE_FP, IS_MOV_SP_FP): Accept H8/300H varaints.
+ (IS_SUB4_SP, IS_SUBL_SP): New macros.
+ (h8300_skip_prologue): Handle H8/300H prologue code sequences.
+ (examine_prologue): Handle addresses from 0x010000 to 0xffffff
+ when in H8/300H mode. Get the return pointer's address correctly
+ for the H8/300H. Handle H8/300H prolouge code sequences.
+
+ * symfile.c (generic_load): Print the starting address
+ of the file just loaded.
+
+Thu May 23 12:09:52 1996 Stan Shebs <shebs@andros.cygnus.com>
+
+ * mpw-make.sed: Edit @THREAD_DB_OBS@ out of makefile.
+
+Tue May 21 11:53:56 1996 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * breakpoint.c (bpstat_do_actions): Avoid endless recursion
+ if a `source' command is contained in bs->commands.
+
+ * infrun.c (wait_for_inferior): Update step_frame_address when
+ stepping into a new line.
+
+ From schwab@issan.informatik.uni-dortmund.de (Andreas Schwab):
+ * breakpoint.c (breakpoint_1): Add shlib_disabled case to
+ bpenables array.
+
+Mon May 20 22:52:00 1996 Mark Alexander <marka@cygnus.com>
+
+ * dsrec.c (load_srec): Add WAITACK parameter, for machines
+ like EST visionICE that send back an ACK after each S-record.
+ * monitor.c (monitor_wait_srec_ack): New function.
+ (monitor_load): Pass monitor_wait_srec_ack to load_srec
+ if the monitor's MO_SREC_ACK flag is set.
+ * monitor.h: Define MO_SREC_ACK flag.
+ * remote-est.c (est_cmds): Add MO_SREC_ACK flag.
+ * sh3-rom.c (sh3_load): Accomodate change in load_srec prototype.
+ * srec.h: Add WAITACK parameter to load_srec prototype.
+
+Sun May 19 21:22:00 1996 Rob Savoye <rob@chinadoll>
+
+ * config/sparc/sparclite.mt: Add the sparc simulator.
+
+Sun May 19 16:49:37 1996 Fred Fish <fnf@cygnus.com>
+
+ * defs.h (read_command_lines, query_hook): Update prototypes.
+ (readline_begin_hook, readline_hook, readline_end_hook): Declare.
+ * breakpoint.c (commands_command): Build message in temporary buffer
+ and pass that, as well as tty control flag, to read_command_lines.
+ * top.c (readline_begin_hook, readline_hook, readline_end_hook):
+ Define here.
+ (command_loop): Check for non-NULL instream before looping.
+ (command_line_input): Use readline_hook when appropriate, to get
+ user input from a GUI window.
+ (read_next_line): Also build prompt if getting user input from a GUI.
+ (recurse_read_control_structure): Fix typo in comment.
+ (read_command_lines): Use passed in prompt and tty flag to decide how
+ to build message. Use readline_begin_hook when appropriate, to set
+ up a GUI interaction window. Just return head, whether NULL or not,
+ after using readline_end_hook to complete GUI interaction.
+ (define_command, document_command): Build message in a temporary
+ buffer and pass it to read_command_lines, along with tty flag.
+
+
+Sat May 18 02:43:58 1996 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * blockframe.c (frameless_look_for_prologue):
+ Add FUNCTION_START_OFFSET only if func_start is non-zero.
+ * minsyms.c (lookup_minimal_symbol_by_pc): Return NULL if
+ pc is not in a known section.
+ * stack.c (print_frame_info): Remove check for fi->pc in known
+ section, now handled by lookup_minimal_symbol_by_pc.
+
+
+Fri May 17 13:31:04 1996 Stan Shebs <shebs@andros.cygnus.com>
+
+ * sh-stub.c: New file, was config/sh/stub.c.
+
+
+Wed May 15 08:25:12 1996 Jeffrey A Law (law@cygnus.com)
+
+ * top.c (read_next_line): Fix thinkos. From Donn Seeley.
+
+ * coffread.c (coff_symtab_read): Handle C_LABEL symbols like
+ C_STAT symbols.
+ * h8300-tdep.c (h8300_pop_frame): Reset $sp and $pc correctly.
+ Flush cached frames just before exiting.
+ * remote-sim.c (gdbsim_resume): Complain if the program isn't
+ being run.
+ * config/h8300/tm-h8300.h (BELIEVE_PCC_PROMOTION): Define.
+
+Tue May 14 18:05:16 1996 Stu Grossman (grossman@critters.cygnus.com)
+
+ * procfs.c (procfs_thread_alive procfs_stop): Make static.
+ (procfs_pid_to_str): New routine to print out thread id's in an
+ intelligible manner.
+ * sol-thread.c (sol_thread_fetch_registers): Re-order manner in
+ which supply_register is called to fix bug with writing
+ individual regs.
+ * config/sparc/tm-sun4sol2.h: Define default for
+ target_pid_to_str in case host lacks libthread_db.
+
+Mon May 13 23:53:30 1996 Stu Grossman (grossman@critters.cygnus.com)
+
+ * Makefile.in config.in configure configure.in
+ config/sparc/nm-sun4sol2.h config/sparc/sun4sol2.mh
+ config/sparc/tm-sun4sol2.h: Use autoconf to config Solaris thread
+ and pthread support, since pre-2.5 systems don't come with
+ libthread_db.so.1.
+
+ * procfs.c (info_proc): Use int instead of id_t. Old versions of
+ Irix don't seem to define this.
+
+Mon May 13 17:40:58 1996 Jeffrey A Law (law@cygnus.com)
+
+ * top.c (execute_control_command, case while_control): Allow
+ a while command to be interrupted.
+
+Mon May 13 16:17:36 1996 Stu Grossman (grossman@critters.cygnus.com)
+
+ * sol-thread.c: More cleanup, add comments.
+ (sol_thread_resume): Prevent people from trying to step
+ inactive threads.
+ (sol_thread_wait sol_thread_fetch_registers
+ sol_thread_store_registers): Remove unnecessary check for
+ sol_thread_active. These routines won't get called unless threads
+ are active.
+
+Mon May 13 11:29:37 1996 Stan Shebs <shebs@andros.cygnus.com>
+
+ SH3-E support from Allan Tajii <atajii@hmsi.com>:
+ * sh-tdep.c (sh_reg_names, sh3_reg_names): Add empty names for
+ float registers.
+ (sh3e_reg_names): New register name array.
+ (sh_processor_type_table): Add sh3e processor type.
+ * config/sh/tm-sh.h (REGISTER_VIRTUAL_TYPE): Fix test.
+ (REGISTER_NAMES, NUM_REGS, NUM_REALREGS, etc): Adjust for
+ full set of registers.
+ * remote-e7000.c (want_sh3, want_sh3_nopc): New globals.
+ (e7000_fetch_registers, e7000_wait): Use them.
+ * sh3-rom.c (sh3_regnames): Add float registers.
+ (sh3e_cmds, sh3e_ops): New globals.
+ (sh3e_open): New function.
+ (_initialize_sh3_rom): Rename from _initialize_sh3, set up
+ sh3e target vector.
+
+Fri May 10 15:53:38 1996 Stu Grossman (grossman@lisa.cygnus.com)
+
+ * sol-thread.c: Cleanup. gcc -Wall fixes. Add prototypes.
+ Print out messages instead of codes for thread_db errors. Make
+ access macros for thread and lwp manipulation. Make cleanups to
+ fixup inferior_pid in case of errors.
+
+Thu May 9 19:06:02 1996 Fred Fish <fnf@cygnus.com>
+
+ * aclocal.m4: Remove unused definition of AC_C_CROSS.
+ * configure.in: Add powerpcle-*-solaris* host and target config
+ so April 30th change does not get lost next time configure is
+ rebuilt.
+
+Thu May 9 14:13:08 1996 Stu Grossman (grossman@critters.cygnus.com)
+
+ * Makefile.in, breakpoint.c, corelow.c, fork-child.c, inflow.c,
+ infrun.c, mac-nat.c, procfs.c, remote.c, sol-thread.c, thread.c,
+ win32-nat.c, config/nm-lynx.h: Rename thread.h to gdbthread.h to
+ avoid conflict with Solaris /usr/include/thread.h.
+
+Thu May 9 12:33:32 1996 Rob Savoye <rob@chinadoll.cygnus.com>
+
+ * abug-rom.c: Config file for the older style ABug monitor that
+ runs on the mvme13x boards.
+ * config/m68k/monitor.mt: Add abug support for m68k cross
+ debugging.
+
+Wed May 8 20:33:24 1996 Fred Fish <fnf@cygnus.com>
+
+ * infcmd.c (do_registers_info): Always print the raw floating
+ point value's bytes in big endian order, so the the leftmost bit
+ is the most significant.
+ * breakpoint.c (clear_momentary_breakpoints): Remove dead code
+ that is referenced nowhere else.
+ (set_breakpoint): Ditto.
+ (do_enable_breakpoint): Created from enable_once_breakpoint
+ with a couple of changes.
+ (enable_breakpoint): Call do_enable_breakpoint with an appropriate
+ bpdisp enum value to set disposition of breakpoint.
+ (enable_once_breakpoint): Ditto.
+ (enable_delete_breakpoint): Ditto.
+ * breakpoint.h (clear_momentary_breakpoints): Remove prototype.
+ * symtab.c (find_pc_line): Improve comments.
+ * xcoffread.c: Ditto.
+
+Tue May 7 18:37:06 1996 Stan Shebs <shebs@andros.cygnus.com>
+
+ * target.c (debug_to_xfer_memory): Insert line breaks when
+ dumping the memory block.
+
+Mon May 6 13:52:52 1996 Stu Grossman (grossman@critters.cygnus.com)
+
+ * fork-child.c (fork_inferior), inferior.h: init_trace_fun now
+ returns a possibly modified pid.
+ * inftarg.c (ptrace_him): Now returns pid;
+ * m3-nat.c (m3_trace_him): Now returns pid;
+ * infcmd.c (run_command): Minor cleanup.
+ * infrun.c (wait_for_inferior): Add another check for one_stepped
+ near where we read the pc to avoid erroneously setting
+ random_signal for multi-threaded support.
+ * procfs.c: Add support for Solaris LWPs. Remove def of
+ LOSING_POLL. Many cleanups... Several workarounds for Solaris
+ lossage. System call entry and exit are now handled by
+ dynamically registered handlers.
+ * (syscallname): Don't barf when handed an unknown syscall
+ number.
+ * (info_proc_syscalls): Ditto.
+ * sol-thread.c: New file. Implements Solaris thread support.
+ * symfile.c (symbol_file_add): Add call to target_new_objfile to
+ notify target-dependent code about new symbol tables.
+ * (clear_symtab_users): Call target_new_objfile to notify it of
+ the removal of all symbol tables.
+ * target.c (push_target): Make sure that to_close is non-zero
+ before calling it.
+ * target.h (target_new_objfile): Provide default.
+ * config/alpha/nm-osf2.h: Define LOSING_POLL because this version
+ of OSF can't hack using poll with /proc.
+ * config/sparc/nm-sun4sol2.h (target_new_objfile): Define to be
+ sol-thread-new-objfile.
+ * config/sparc/sun4sol2.mh: Add sol-thread.o to NATDEFFILES, and
+ add libthread_db.so.1 to NAT_CLIBS.
+ * config/sparc/tm-sun4sol2.h: Define PIDGET, TIDGET, and
+ target_pid_to_str.
+
+Sat May 4 02:13:34 1996 N Srin Kumar <nsrin@wipinfo.soft.net>
+
+ * procfs.c (remove_fd): Fix copy of fds to fill hole left after
+ removal of the requested fd.
+
+Mon May 6 07:52:48 1996 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * rs6000-tdep.c (_initialize_rs6000_tdep): Don't do XCOFF specific
+ hooks under ELF.
+
+ * config/powerpc/tm-ppc-eabi.h: Define ELF_OBJECT_FORMAT.
+
+Thu May 2 12:46:14 1996 Jeffrey A Law (law@cygnus.com)
+
+ From Peter Schauer:
+ * breakpoint.h (enum bpdisp): Add del_at_next_stop.
+ * breakpoint.c (insert_breakpoints, watchpoint_check,
+ bpstat_stop_status): Avoid bad references to memory freed via
+ delete_breakpoint on watchpoints going out of scope.
+ Do not delete these watchpoints, disable them and change their
+ disposition to del_at_next_stop instead.
+ (breakpoint_auto_delete): Delete all breakpoints whose disposition
+ is del_at_next_stop.
+ (breakpoint_init_inferior): Use switch to avoid reference to
+ already deleted breakpoint.
+
+Wed May 1 17:29:18 1996 Fred Fish <fnf@cygnus.com>
+
+ * Makefile.in (rs6000-nat.o): Depend on xcoffsolib.h.
+ * config/rs6000/rs6000.mh (NATDEPFILES): Move xcoffread.o ...
+ * config/rs6000/rs6000.mt (TDEPFILES): ... to here.
+ * xcoffsolib.c (xcoff_relocate_symtab_hook): Define and initialize.
+ (solib_info): Call xcoff_relocate_symtab via the hook.
+ (sharedlibrary_command): Ditto.
+ * xcoffread.c: Remove all FAKING_RS6000 comments and defines.
+ (xcoff_add_toc_to_loadinfo_hook): Define and initialize here.
+ (xcoff_init_loadinfo_hook): Define and initialize here.
+ (scan_xcoff_symtab): Call xcoff_add_toc_to_loadinfo via the hook.
+ (xcoff_initial_scan): Call xcoff_init_loadinfo via the hook.
+ * xcoffsolib.h (xcoff_relocate_symtab_hook): Declare extern func.
+ * rs6000-tdep.c (_initialize_rs6000_tdep): Add initializations
+ of xcoff_add_toc_to_loadinfo_hook and xcoff_init_loadinfo_hook.
+ * rs6000-nat.c (_initialize_core_rs6000): Add initialization
+ of xcoff_relocate_symtab_hook.
+
+Tue Apr 30 13:22:02 1996 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * configure (powerpcle-*-solaris*): Add Solaris support.
+
+ * config/powerpc/{solaris.m[ht],tm-solaris.h}: New files for
+ Solaris support.
+
+Mon Apr 29 16:17:31 1996 Dawn Perchik <dawn@cygnus.com>
+
+ * c-valprint.c (c_val_print): Fix printing for arrays defined
+ with 0 length.
+
+Sun Apr 28 15:08:05 1996 Stan Shebs <shebs@andros.cygnus.com>
+
+ Support for bi-endian remote breakpoints.
+ * remote.c (big_break_insn, little_break_insn): New globals.
+ (break_insn): Remove.
+ (remote_insert_breakpoint, remote_remove_breakpoint): Use own
+ code if REMOTE_BREAKPOINT defined, otherwise call memory
+ breakpoint functions.
+ * config/sh/tm-sh.h (REMOTE_BREAKPOINT): Remove.
+ (BIG_REMOTE_BREAKPOINT, LITTLE_REMOTE_BREAKPOINT): Define.
+
+ * mon960-rom.c (mon960_cmds): Remove forward decl.
+ (mon960_load): Use current_monitor instead of mon960_cmds.
+ (mon960_regnames): Remove backslashes from line ends.
+ (_initialize_mon960): Fix documentation string.
+
+Sun Apr 28 12:10:35 1996 Fred Fish <fnf@cygnus.com>
+
+ * symfile.h (psymbol_allocation_list): Expand comments which
+ describe the psymbol allocation list and how each field is
+ used.
+
+Sun Apr 28 03:44:30 1996 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * breakpoint.c (delete_breakpoint): Fix bpt->val, bpt->exp
+ storage leaks.
+ (breakpoint_re_set_one): Fix b->exp, b->val, b->cond storage leaks.
+
+ * infcmd.c (run_command), solib.c (locate_base): Check for
+ target_has_execution in addition to inferior_pid, a core file
+ from a threaded program is yielding a non-zero inferior_pid.
+
+ * sparc-tdep.c (get_saved_register): Handle window registers
+ in a dummy frame correctly.
+
+Sat Apr 27 20:38:32 1996 Fred Fish <fnf@cygnus.com>
+
+ * Makefile.in (CLIBS): Move $(MMALLOC) past all other libs,
+ so that anything that wants an allocation function not yet pulled
+ in, will get it from mmalloc rather than a system library.
+ * Makefile.in (INSTALLED_LIBS): Reorder to match order of CLIBS,
+ to avoid surprising results when used.
+
+Sat Apr 27 00:12:05 1996 Dawn Perchik (dawn@cygnus.com)
+
+ * stabsread.c: Changes and bug fixes for cfront support.
+ Fix bug for class data members.
+ Fix parsing bug when no base classes exist.
+ Fix memory bug - allocate space for cplusplus specific info.
+ Add support for static data.
+ Add prototypes for static functions.
+ Enhance comments to show what each function expects to parse.
+ Cleanup code.
+ * stabsread.c(resolve_cont),dbxread.c(resolve_cont): Rename
+ function to resolve_cfront_continuation.
+
+Fri Apr 26 23:58:26 1996 Jeffrey A Law (law@cygnus.com)
+
+ * infrun.c (wait_for_inferior): Call registers_changed when
+ restarting the inferior to get over a nullified instruction.
+
+Tue Apr 24 12:12:55 1996 Dawn Perchik (dawn@cygnus.com)
+
+ * dbxread.c,stabsread.c,gdbtypes.c,partial-stab.h,valops.c:
+ Add new support for parsing cfront stabs.
+
+Wed Apr 24 00:32:55 1996 Jeffrey A Law (law@cygnus.com)
+
+ * infrun.c (wait_for_inferior): Move "have_waited" label
+ outside of #ifdef conditionals. Don't trash the wait status
+ if we get a signal and the current instruction is nullified.
+
+Mon Apr 22 20:17:01 1996 Fred Fish <fnf@cygnus.com>
+
+ * Makefile.in (VERSION): Bump version number to 4.16.1.
+ * NEWS: Update for 4.16 release.
+
+Mon Apr 22 16:32:29 1996 Stan Shebs <shebs@andros.cygnus.com>
+
+ * monitor.h: Clean up comment formatting.
+ (current_monitor): Remove decl.
+ (LOADTYPES, LOADPROTOS, INIT_CMD, etc): Remove definitions.
+ (push_monitor, SREC_SIZE): Remove.
+ * monitor.c: Expand old macro into current_monitor derefs
+ everywhere.
+ * remote-os9k.c (current_monitor): Remove definition.
+
+Mon Apr 22 14:54:45 1996 Mark Alexander <marka@superball.cygnus.com>
+
+ * corefile.c (specify_exec_file_hook): Allow arbitrary number of
+ hooks.
+ (call_extra_exec_file_hooks): New function.
+ * h8300-tdep.c: Lint; add .h files to provide missing declarations,
+ remove unused variables.
+ (set_machine_hook): New function.
+ (_initialize_h8300m): Initialize it.
+
+Fri Apr 19 15:03:49 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * remote-mips.c (encoding): Don't specify size, to avoid bug in
+ SunOS native compiler.
+
+Thu Apr 18 18:46:57 1996 Stan Shebs <shebs@andros.cygnus.com>
+
+ * monitor.c: Use int rather than LONGEST for values, since
+ the formatting strings are not prepared to accept long longs.
+
+Wed Apr 17 20:17:27 1996 Doug Evans <dje@canuck.cygnus.com>
+
+ * arm-tdep.c (initialize_arm_tdep): Make apcs32 a `zinteger'.
+
+Tue Apr 16 17:38:23 1996 Stu Grossman (grossman@critters.cygnus.com)
+
+ * corelow.c (add_to_thread_list): Make sure reg_sect is non-null
+ before de-referencing it. Prevents deref of NULL pointer if core
+ file lacks .reg section.
+ * defs.h: Rename floatformat_{to from}_long_double to
+ floatformat_{to from}_doublest. Get rid of FLOATFORMAT_{TO
+ FROM}... macros.
+ * findvar.c (extract_floating store_floating): Change all refs to
+ FLOATFORMAT_{FROM TO}... to floatformat_{from to}_doublest.
+ * utils.c: Change floatformat_{to from}_long_double to
+ floatformat_{to from}_doublest cuz the new routines will use
+ whatever size (double or long double) is appropriate.
+ * config/i960/tm-i960.h (REGISTER_CONVERT_TO_VIRTUAL
+ REGISTER_CONVERT_TO_RAW): Change FLOATFORMAT... macros to
+ floatformat... routine calls.
+
+Mon Apr 15 16:34:11 1996 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * stabsread.c (read_type): Move handling of '@' from type
+ number handling to handling of types proper (as emitted by gcc!).
+ For typedefs, allocate the typedef type before reading its
+ definition, to properly handling recursive types.
+
+Mon Apr 15 11:19:26 1996 Jeffrey A Law (law@cygnus.com)
+
+ * ch-exp.c (calculate_array_length): Fix prototype.
+
+Sat Apr 13 14:21:16 1996 Stu Grossman (grossman@critters.cygnus.com)
+
+ * remote-nindy.c (nindy_open): Acquire more target state so that
+ user can attach to a previously running program.
+ * (nindy_fetch_registers nindy_store_registers): Get rid of fp
+ conversion code. That's all handled in {extract store}_floating
+ now.
+ * utils.c (floatformat_to_double): Don't bias exponent when
+ handling zero's, denorms or NaNs.
+ * config/i960/tm-i960.h (REGISTER_CONVERT_TO_VIRTUAL
+ REGISTER_CONVERT_TO_RAW): Change to using DOUBLST and
+ FLOATFORMAT_TO/FROM_DOUBLEST macros.
+ * config/i960/tm-nindy960.h: Undefine
+ REGISTER_CONVERT_TO_VIRTUAL, REGISTER_CONVERT_TO_RAW, and
+ REGISTER_CONVERTIBLE. These are no longer necessary now that all
+ the magic happens in extract/store_floating.
+
+Sat Apr 13 02:58:02 1996 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * eval.c (evaluate_subexp_standard): Report error when attempting to
+ evaluate subscripts for types which cannot be subscripted.
+
+ * valarith.c (value_x_binop, value_x_unop): Add noside parameter.
+ Return a zero value with the return type of the member function
+ if noside is EVAL_AVOID_SIDE_EFFECTS instead of calling the member
+ function.
+ * values.h (value_x_binop, value_x_unop): Update prototypes
+ accordingly.
+ * eval.c (evaluate_subexp_standard): Update all callers of
+ value_x_binop, value_x_unop accordingly.
+
+ * valarith.c (value_neg, value_complement): Perform ANSI C/C++
+ integral promotion on operands.
+
+Fri Apr 12 13:19:27 1996 Fred Fish <fnf@cygnus.com>
+
+ * README: Update for 4.16 release.
+ * configure.in (AC_CHECK_FUNCS): Also check for sbrk.
+ * configure: Regenerate with autoconf.
+ * config.in: Regenerate with autoheader.
+ * main.c (main): Only use sbrk() when HAVE_SBRK is defined.
+ * top.c (command_loop): Ditto.
+
+Fri Apr 12 09:45:29 1996 Stu Grossman (grossman@critters.cygnus.com)
+
+ * defs.h: Define TARGET_{FLOAT DOUBLE LONG_DOUBLE}_FORMAT
+ defaults for bi-endian targets. Replace function pointers for
+ floatformat routines with macros. No need for these to be runtime
+ selectable.
+ * findvar.c: Get rid of floatformat function pointers. Use
+ macros in extract_floating and store_floating.
+ * remote-nindy.c (nindy_fetch_registers nindy_store_registers):
+ Use floatformat macros.
+
+Thu Apr 11 21:28:02 1996 Fred Fish <fnf@cygnus.com>
+
+ From: Miles Bader <miles@gnu.ai.mit.edu>
+ * configure.in (AC_CHECK_HEADERS): check for endian.h.
+ Use AC_CHECK_TOOL to find AR & RANLIB. Add AC_PROG_AWK.
+ Add host & target cases for i[345]86-*-gnu*.
+ * config.in: Regenerate with autoheader.
+ * configure: Regenerate with autoconf.
+ * Makefile.in (AR, AWK): Set from corresponding autoconf substs.
+ (init.c): Don't scan mig-generated files.
+ * defs.h (endian.h): Include if HAVE_ENDIAN_H defined.
+ * config/nm-m3.h (ATTACH_NO_WAIT): Define.
+ * infcmd.c (attach_command): Use "#ifndef ATTACH_NO_WAIT"
+ rather than "#ifndef MACH".
+
+Thu Apr 11 18:49:42 1996 Stan Shebs <shebs@andros.cygnus.com>
+
+ * remote.c (remotewritesize): New GDB variable, controls size
+ of memory packets sent to the target.
+
+Thu Apr 11 13:47:52 1996 Stu Grossman (grossman@critters.cygnus.com)
+
+ * dcache.c: Add prototypes. Make many functions static.
+ * (dcache_peek dcache_fetch dcache_poke): Make dcache_fetch and
+ dcache_poke call dcache_xfer_memory directly in order to fix
+ problems with turning off dcache. dcache_peek is now unnecessary,
+ so it goes away.
+
+ * defs.h: Define new macros HOST_{FLOAT DOUBLE LONG_DOUBLE}_FORMAT
+ and TARGET_{FLOAT DOUBLE LONG_DOUBLE}_FORMAT to specify a pointer
+ to a struct floatformat. This allows for better handling of
+ targets whose floating point formats differ from the host by more
+ than just byte order.
+ * (floatformat_to_long_double floatformat_from_long_double):
+ Prototypes for new functions in utils.c.
+ * (floatformat_to_doublest floatformat_from_doublest): Prototypes
+ for pointers to floating point conversion functions. The actual
+ function uses either double or long double if the host supports it.
+ * findvar.c (floatformat_to_doublest floatformat_from_doublest):
+ Initialize to point at correct function depending on HAVE_LONG_DOUBLE.
+ * (extract_floating store_floating): Rewrite. Now, if host fp
+ format is the same as the target, we just do a copy. Otherwise,
+ we call floatformat_{to from}_doublest.
+ * remote-nindy.c (nindy_xfer_inferior_memory): Change param
+ `write' to `should_write'.
+ * utils.c (floatformat_to_long_double
+ floatformat_from_long_double): New routines that implement long
+ double versions of functions in libiberty/floatformat.c.
+ * config/i960/tm-i960.h (TARGET_LONG_DOUBLE_FORMAT): Define this for
+ i960 extended real (80 bit) numbers.
+ * nindy-share/nindy.c (ninMemGet ninMemPut): Return number of bytes
+ actually read or written.
+
+Wed Apr 10 02:56:06 1996 Wilfried Moser <moser@rtl.cygnus.com>
+
+ * ch-valprint.c (chill_val_print): Remove call to calculate_array_length.
+ (calculate_array_length): Move function from here ...
+
+ * ch-exp.c (calculate_array_length): ... to here.
+ (parse_primval): If we have a symbol with an array type
+ and the length is 0, call calculate_array_length.
+
+Tue Apr 9 01:23:05 1996 Wilfried Moser <moser@rtl.cygnus.com>
+
+ * eval.c (evaluate_subexp_standard): In case of TYPE_CODE_SET:
+ Add some checks for powerset compatibility.
+
+ * valops.c (value_slice): Use lowbound instead of lowerbound for
+ call to slice_range_type to get correct bounds.
+
+Mon Apr 8 12:53:56 1996 Fred Fish <fnf@cygnus.com>
+
+ * Makefile.in (scm-exp.o, scm-lang.o, scm-valprint.o): Add targets and
+ dependencies.
+ * scm-lang.c (gdb_string.h): Include.
+ * objfiles.c (add_to_objfile_sections): Cast second arg of obstack_grow
+ call to correct type (char *).
+ * cp-valprint.c (cp_print_static_field): Ditto.
+ * somsolib.c (som_solib_create_inferior_hook): Add a declaration
+ for external find_unwind_entry function (from hppa-tdep.c).
+ * remote-pa.c (remote_write_bytes, remote_read_bytes): Change
+ type of second arg to "char *" to be type compatible with
+ dcache.
+ (remote_wait): Cast second arg to strtol to correct type.
+ * hppa-tdep.c (compare_unwind_entries): Change argument types to
+ "const void *" to be type compatible with qsort, and then
+ assign to local args prior to use.
+
+Mon Apr 8 15:35:52 1996 Jeffrey A Law (law@cygnus.com)
+
+ * infptrace.c (kill_inferior): Remove call to "kill"; update
+ comments.
+
+Mon Apr 8 14:05:07 1996 Geoffrey Noer <noer@cygnus.com>
+
+ * remote-e7000.c: don't append :23 to target port if __WIN32__
+ is defined (it's WinGDB).
+
+Sun Apr 7 22:34:29 1996 Fred Fish <fnf@cygnus.com>
+
+ From: Miles Bader <miles@gnu.ai.mit.edu>
+ * gnu-nat.c, gnu-nat.h, msg.defs, exc_request.defs, i386gnu-nat.c,
+ msg_reply.defs, notify.defs, process_reply.defs, reply_mig_hack.awk,
+ config/nm-gnu.h, config/i386/{i386gnu.mh, i386gnu.mt, nm-gnu.h,
+ m-i386gnu.h, xm-i386gnu.h}: New files for GNU hurd.
+
+Sun Apr 7 13:32:41 1996 Fred Fish <fnf@cygnus.com>
+
+ * configure.in (case host): Add i386sco5 host.
+ * configure: Regenerate.
+
+ From: Robert Lipe <robertl@dgii.com>
+ Add support for SCO OpenServer 5 (a.k.a. 3.2v5*) This
+ target is an SVR3.2 with COFF, ELF, and shared libes, but
+ no /proc.
+ * config/i386/i386sco5.mh: New file.
+ * config/i386/nm-i386sco5.h: New file.
+
+Sat Apr 6 08:55:22 1996 Fred Fish <fnf@cygnus.com>
+
+ * bcache.c (bcache): When size of chunk to cache is exactly equal to
+ BCACHE_MAXLENGTH, stash chunk as unique copy.
+
+Sat Apr 6 00:46:26 1996 Fred Fish <fnf@cygnus.com>
+
+ * symfile.c (INLINE_ADD_PSYMBOL): Remove ifdef.
+ (add_psymbol_to_list): Add an arg for passing CORE_ADDR values and
+ use it, rather than calling add_psymbol_addr_to_list.
+ (add_psymbol_addr_to_list): Delete.
+ (add_psymbol_to_list): Make psymbol static to avoid random data in
+ gaps due to alignment of structure members.
+ * symfile.h (INLINE_ADD_PSYMBOL, ADD_PSYMBOL_TO_LIST,
+ ADD_PSYMBOL_ADDR_TO_LIST): Remove. Real world tests show no
+ performance improvements by inlining via complicated macros and
+ they just make gdb larger and harder to maintain.
+ * dwarfread.c (add_enum_psymbol): Replace ADD_PSYMBOL_TO_LIST
+ and/or ADD_PSYMBOL_ADDR_TO_LIST macro(s) with call to
+ add_psymbol_to_list with appropriate long or CORE_ADDR args.
+ (add_partial_symbol): Ditto.
+ * partial-stab.h: Ditto.
+ * os9kread.c (read_os9k_psymtab): Ditto
+ * mdebugread.c (parse_partial_symbols): Ditto.
+ (handle_psymbol_enumerators): Ditto.
+ (demangle.h): Include.
+ * hpread.c (hpread_build_psymtabs): Ditto.
+ (hpread_build_psymtabs): Ditto.
+ (demangle.h): Include
+
+Thu Apr 4 20:16:55 1996 Fred Fish <fnf@cygnus.com>
+
+ * configure.in: Check for setpgid function.
+ * config.in: Regenerate with autoheader.
+ * configure: Regenerate with autoconf.
+ * inflow.c (_initialize_inflow): Only try to use _SC_JOB_CONTROL
+ if it is actually defined.
+ (gdb_setpgid): Use HAVE_SETPGID.
+ * ch-exp.c: Change include of <string.h> to "gdb_string.h".
+ * c-exp.y, f-exp.y, m2-exp.y: Ditto.
+ * c-exp.y, serial.c: Include <ctype.h>.
+ * config/m68k/nm-news.h: Add typedef for pid_t which is
+ apparently missing from <sys/types.h>. Enclose entire
+ file in NM_NEWS_H ifndef and define when included.
+ * config/mips/nm-news-mips.h: Ditto.
+ * config/m68k/tm-m68k.h (REGISTER_CONVERT_TO_VIRTUAL,
+ REGISTER_CONVERT_TO_RAW): Change name of temporary variable.
+
+Thu Apr 4 19:04:18 1996 Stan Shebs <shebs@andros.cygnus.com>
+
+ * arm-xdep.c: Move native-specific code to here from arm-tdep.c.
+ * arm-tdep.c (arm_apcs_32): New global.
+ (arm_addr_bits_remove, arm_saved_pc_after_call,
+ arm_push_dummy_frame, arm_pop_frame): New functions.
+ (arm_skip_prologue): Updated version from Richard Earnshaw.
+ (_initialize_arm_tdep): Add set/show "apcs32".
+ * config/arm/tm-arm.h (ADDR_BITS_REMOVE): Call
+ arm_addr_bits_remove.
+ (SAVED_PC_AFTER_CALL): Call arm_saved_pc_after_call.
+ (frame_find_saved_regs): Declare properly.
+ (PUSH_DUMMY_FRAME): Call arm_push_dummy_frame.
+ (POP_FRAME): Call arm_pop_frame, use ADDR_BITS_REMOVE instead of
+ explicit mask.
+ * config/arm/nm-arm.h: New file.
+ * config/arm/xm-arm.h (KERNEL_U_ADDR, FETCH_INFERIOR_REGISTERS):
+ Move definitions to nm-arm.h.
+ * config/arm/arm.mh (NAT_FILE): Define.
+
+ * symfile.c (generic_load): Initialize data_count properly.
+
+Thu Apr 4 17:17:53 1996 Fred Fish <fnf@cygnus.com>
+
+ * symmisc.c (print_objfile_statistics): Print memory used by
+ psymbol cache obstack.
+
+Thu Apr 4 15:43:07 1996 Stan Shebs <shebs@andros.cygnus.com>
+
+ * symfile.c (report_transfer_performance): New function.
+ (generic_load): Call it to report transfer rate.
+ * remote-e7000.c (e7000_load): Ditto.
+
+Mon Apr 1 16:31:00 1996 Stan Shebs <shebs@andros.cygnus.com>
+
+ * mpw-make.sed: Change references to config.h to be in objdir,
+ edit out rules to rebuild config.h.
+
+Mon Apr 1 08:32:23 1996 Fred Fish <fnf@cygnus.com>
+
+ * hppa-tdep.c (hppa_pop_frame): Call clear_proceed_status before
+ proceeding.
+
+Sun Mar 31 16:15:43 1996 Fred Fish <fnf@cygnus.com>
+
+ * hppah-nat.c (store_inferior_registers, store_inferior_registers,
+ fetch_register, child_xfer_memory): Use call_ptrace function supplied
+ by infptrace.c rather than calling ptrace directly.
+
+Sun Mar 31 15:39:00 1996 Stan Shebs <shebs@andros.cygnus.com>
+
+ * mon960-rom.c: Cleanups and elimination of unused code,
+ clarify documentation string.
+ (mon960_serial, mon960_ttyname): Remove.
+ * config/i960/tm-mon960.h (ADDITIONAL_OPTIONS,
+ ADDITIONAL_OPTION_CASES, ADDITIONAL_OPTION_HELP): Remove.
+
+Sat Mar 30 11:00:22 1996 Fred Fish <fnf@cygnus.com>
+
+ * configure.in: Check whether printf family supports printing
+ long doubles or not and define PRINTF_HAS_LONG_DOUBLE if so.
+ * acconfig.h: Provide default undef for PRINTF_HAS_LONG_DOUBLE.
+ * configure: Regenerate.
+ * valprint.c (print_floating): Use PRINTF_HAS_LONG_DOUBLE.
+ * c-exp.y (parse_number): Use PRINTF_HAS_LONG_DOUBLE.
+ * configure.in: Fix have_gregset and have_fpregset autoconf
+ variable names so that they match the pattern required to
+ cache them.
+
+Fri Mar 29 21:39:56 1996 Fred Fish <fnf@cygnus.com>
+
+ * core-aout.c (fetch_core_registers): Cast core_reg_size to int
+ before testing against reg_ptr.
+ * eval.c (evaluate_subexp_standard): Cast type of
+ TYPE_FN_FIELD_VOFFSET to int.
+ * findvar.c (extract_signed_integer, extract_unsigned_integer,
+ extract_long_unsigned_integer): Cast type of sizeof to int.
+ * values.c (unpack_field_as_long, modify_field): Ditto.
+ * valops.c (value_assign, call_function_by_hand): Ditto.
+ * infcmd.c (do_registers_info): Ditto.
+ * ser-tcp.c (tcp_open): Ditto.
+ * remote.c (putpkt): Ditto.
+ * dcache.c (dcache_peek): Ditto.
+ * dcache.c (dcache_poke): Ditto.
+ * m2-exp.y (yylex): Ditto.
+ * gnu-regex.c (re_match_2): Ditto.
+ * f-lang.c (ADD_BF_SYMNUM, saved_bf_list_end, tmp_bf_ptr): Ifdef
+ out unused macro definition and variables.
+ * inftarg.c (proc_wait): Move from main.c to here, and make static.
+ * valprint.c (val_print_string): Change bufsize from int to unsigned.
+ * main.c (wait.h): Include.
+ * top.c (command_line_input): Remove unused variable "c".
+ * f-typeprint.c (f_type_print_varspec_prefix): Add missing enum
+ value TYPE_CODE_TYPEDEF to switch statement.
+ (f_type_print_varspec_suffix): Add missing enum value
+ TYPE_CODE_TYPEDEF to switch statement.
+ * ch-exp.c (parse_primval): Add remaining enumeration values to
+ switch statement, with no specific action.
+ (ch_lex): Add LOC_UNRESOLVED in switch statement.
+ (pushback_token): Ifdef out, since code using it is ifdef'd out.
+ * stabsread.c (cleanup_undefined_types): Remove unused label
+ "badtype".
+ * objfiles.h (print_symbol_bcache_statistics): Add prototype.
+ * maint.c (objfiles.h): Include.
+ (maintenance_print_statistics): Remove unused variable "temp".
+ * minsyms.c (lookup_minimal_symbol_solib_trampoline): Remove
+ unused variable "found_file_symbol".
+ * m2-exp.y (yylex): Add LOC_UNRESOLVED case to switch.
+ * language.c (lang_bool_type): Use existing function local type
+ variable rather than create block local variables.
+ * solib.c (disable_break): Enclose in ifndef SVR4_SHARED_LIBS.
+ * infptrace.c (wait.h, command.h): Include.
+ * ser-tcp.c (gdb_string.h): Include
+ * i386-tdep.c (codestream_seek): Change "place" to CORE_ADDR.
+ (i386_get_frame_setup): Change "pc" from int to CORE_ADDR.
+ * command.c (complete_on_enum): Make assignment used as truth value
+ explictly check against NULL.
+ (wait.h): Include.
+ * infrun.c (wait_for_inferior): Ifdef out prologue_pc since code
+ that uses it is ifdef'd out.
+ * parser-defs.h: Add prototype for write_dollar_variable.
+ * infrun.c: Add prototype for write_pc_pid.
+ * breakpoint.h: Add prototype for re_enable_breakpoints_in_shlibs.
+ * symmisc.c (bcache.h): Include.
+ * bcache.h: Add prototype for print_bcache_statistics.
+ * symfile.c: Include <time.h>.
+ * printcmd.c (print_scalar_formatted): Change len to unsigned int.
+ * valarith.c (value_equal): Cast result of TYPE_LENGTH to int.
+ * valarith.c (value_binop): Change result_len, promoted_len1,
+ and promoted_len2 to unsigned int.
+ * valarith.c (value_subscripted_rvalue): Change elt_offs and
+ elt_size to unsigned int.
+ * valops.c (value_array): Change typelength to unsigned int.
+ (destructor_name_p): Change len to unsigned int.
+ * scm-lang.h (scm_parse): Add prototype for scm_unpack.
+ * symfile.c (decrement_reading_symtab): Change return type to void.
+ * valarith.c (value_subscript): Remove unused variable "word".
+ (value_subscript): Remove unused variable "tint".
+ * valops.c (auto_abandon): Ifdef out, since code using it is also
+ ifdef'd out.
+ * eval.c (init_array_element): Remove unused variable "val".
+ * Makefile.in (values.o): Depends on scm-lang.h.
+ (command.o): Depends upon wait_h.
+ (ser-tcp.o): Depends upon gdb_string.h.
+ (infptrace.o): Depends upon wait_h and command_h.
+ (maint.o): Depends on objfiles.h and symfile.h.
+ * values.c (allocate_repeat_value): Remove unused variable
+ "element_type".
+ (scm-lang.h): Include.
+ * breakpoint.c (create_longjmp_breakpoint): Enclose in
+ GET_LONGJMP_TARGET define, unused otherwise.
+ * config/i386/nm-linux.h: Add prototypes for i386_insert_watchpoint,
+ i386_remove_watchpoint and i386_stopped_by_watchpoint.
+
+Thu Mar 28 12:53:19 1996 Doug Evans <dje@canuck.cygnus.com>
+
+ * configure.in (sparc64-*-solaris2*): Delete.
+ Stick with sparc-*-solaris2*.
+ * configure: Regenerated.
+
+Thu Mar 28 06:51:26 1996 Fred Fish <fnf@cygnus.com>
+
+ * valops.c (value_assign): Make copy of internal variable value
+ before returning it as a new value, since it is owned by the
+ internal variable and will be freed along with it.
+
+Wed Mar 27 08:36:17 1996 Jeffrey A Law (law@cygnus.com)
+
+ * From Peter Schauer.
+ * breakpoint.c (breakpoint_re_set_one): Keep temporary
+ breakpoints bp_until, bp_finish, bp_watchpoint_cope, bp_call_dummy
+ and bp_step_resume in case breakpoint_re_set_one is called due
+ to a step over a dlopen call.
+ * infrun.c (wait_for_inferior): Always remove breakpoints from
+ inferior in BPSTAT_WHAT_CHECK_SHLIBS case.
+
+Tue Mar 26 13:15:32 1996 Fred Fish <fnf@cygnus.com>
+
+ * config/mips/tm-mips.h (COERCE_FLOAT_TO_DOUBLE): Only prefer
+ non-prototyped case over prototyped case for C.
+ * config/pa/tm-hppa.h (COERCE_FLOAT_TO_DOUBLE): Ditto.
+
+Sat Mar 23 17:24:28 1996 Fred Fish <fnf@cygnus.com>
+
+ * os9kread.c (os9k_process_one_symbol): Note nonportable
+ assumption that an int can hold a char *.
+
+ * bcache.h (struct hashlink): Wrap data[] inside union with
+ double to force longest alignment.
+ (BCACHE_DATA): New macro to access data[].
+ (BCACHE_ALIGNMENT): New macro to get offset to data[].
+ * bcache.c (lookup_cache, bcache): Use BCACHE_DATA to get
+ address of cached data. Use BCACHE_ALIGNMENT to compute
+ amount of space to allocate for each hashlink struct.
+
+Sat Mar 23 12:14:02 1996 Fred Fish <fnf@cygnus.com>
+
+ * ch-lang.c (evaluate_subexp_chill): Fix typo.
+
+Thu Mar 21 08:27:19 1996 Fred Fish <fnf@cygnus.com>
+
+ * Makefile.in (VERSION): Bump version to 4.15.3
+
+Thu Mar 21 10:56:41 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * config.in: Rename from config.h.in.
+ * configure.in: Call AC_CONFIG_HEADER with config.h:config.in.
+ Change CONFIG_HEADERS test in AC_OUTPUT accordingly.
+ * configure: Rebuild.
+ * Makefile.in (stamp-h): Depend upon config.in, not config.h.in.
+ Set CONFIG_HEADERS to config.h:config.in.
+
+Tue Mar 19 12:47:51 1996 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * partial-stab.h (case N_ENDM): Finish current partial symbol
+ table for Solaris 2 cc.
+
+Tue Mar 19 10:39:15 1996 Jeffrey A Law (law@cygnus.com)
+
+ * rs6000-nat.c (exec_one_dummy_insn): Don't clobber the
+ PC in the registers array. From Peter Schauer.
+
+Mon Mar 18 13:47:09 1996 Fred Fish <fnf@cygnus.com>
+
+ * symfile.c (reread_symbols): Reinitialize bcache struct
+ members to zero using memset. Also use memset to reinit
+ global_psymbols and static_psymbols, rather than explicitly
+ resetting each structure member.
+
+Sat Mar 16 19:47:36 1996 Fred Fish <fnf@cygnus.com>
+
+ * configure.in: Add fragment to create stamp-h.
+
+ From Peter Schauer <Peter.Schauer@Regent.E-Technik.TU-Muenchen.DE>
+ * configure.in (AC_CHECK_HEADERS): Check for link.h.
+ * configure: Regenerate with autoconf.
+ * config.h.in: Regenerate with autoheader.
+ * config/i386/nm-linux.h: Include solib.h only if HAVE_LINK_H
+ is defined.
+ * solib.c: Exclude most of the code if HAVE_LINK_H is not defined.
+ * config/i386/linux.mh: Reinstate XM_CLIBS, it is needed for
+ older a.out based systems.
+
+Sat Mar 16 16:45:43 1996 Fred Fish <fnf@cygnus.com>
+
+ * config.h.in: New file.
+ * acconfig.h: New file, for autoheader.
+ * configure.in (AC_CONFIG_HEADER): Add, generate config.h.
+ * configure: Regenerate.
+ * Makefile.in (defs_h): Add config.h
+ (distclean): Remove config.h and stamp-h during distclean.
+ (config.h, stamp-h): New targets to remake config.h when necessary.
+ * defs.h (config.h): Include before any other includes or defines.
+ * i386-tdep.c (gdb_string.h): Move include after include of defs.h.
+ * i386v4-nat.c (defs.h): Include before testing HAVE_SYS_PROCFS_H.
+
+Sat Mar 16 14:55:27 1996 Fred Fish <fnf@cygnus.com>
+
+ From Peter Schauer <Peter.Schauer@Regent.E-Technik.TU-Muenchen.DE>
+ * Makefile.in (INSTALLED_LIBS): Make sure that @LIBS@ will not
+ result in an empty line, to work around a bug in native Ultrix 4.4
+ and OSF/1-3.2C make.
+
+Sat Mar 16 13:33:17 1996 Fred Fish <fnf@cygnus.com>
+
+ * configure.in: Add gdbserver to configdirs under linux.
+ * configure: Regenerate.
+
+Fri Mar 15 12:06:58 1996 J.T. Conklin <jtc@rtl.cygnus.com>
+
+ * config/i386/nm-nbsd.h (FLOAT_INFO): Comment out.
+ * config/i386/tm-nbsd.h (NUM_REGS): Define.
+
+Thu Mar 14 10:31:18 1996 Jeffrey A Law (law@cygnus.com)
+
+ * solib.c (solib_break_names): Add _r_debug_state for
+ vanilla SVR4 implementations. From Peter Schauer.
+
+Mon Mar 11 14:24:57 1996 Dawn Perchik <dawn@critters.cygnus.com>
+
+ * mon960-rom.c: New file; support mon960 rom monitor on i960.
+ * monitor.c (monitor_debug): Change remotedebug to buffer strings.
+ * monitor.c (monitor_open): Add test for flag MO_NO_ECHO_ON_OPEN before
+ epecting prompt and echo during open.
+ * monitor.c (monitor_stop): Add test for flag MO_SEND_BREAK_ON_OPEN to
+ determine if break should be sent as stop command.
+ * monitor.h: Add flags MO_NO_ECHO_ON_OPEN and MO_SEND_BREAK_ON_OPEN.
+ * i960-tdep.c (mon960_frame_chain_valid): New function for getting
+ stack frame on mon960.
+ * Makefile.in: Add mon960 files.
+ * configure.in: Changed i960-*-coff* and i960-*-elf* to target mon960;
+ added i960-nindy-coff* and i960-nindy-elf* for target nindy.
+ * configure: Regenerated.
+ * config/i960/mon960.mt, config/i960/tm-mon960.h: New files;
+ support mon960 rom monitor on i960.
+
+Mon Mar 11 11:02:47 1996 Steve Chamberlain <sac@slash.cygnus.com>
+
+ With Michael Snyder:
+ * i386-tdep.c (skip_trampoline_code): Fix strncmp length.
+ * win32-nat.c (CHECK, DEBUG*, debug_*): New.
+ (handle_load_dll): Don't reload symbols.
+ (handle_exception): Use the DEBUG_* names.
+ (child_wait): Add DEBUG_* code.
+ (_initialize_inftarg): Add new commands to set debug_ names.
+
+Mon Mar 11 09:19:58 1996 Jeffrey A Law (law@cygnus.com)
+
+ * From Peter Schauer:
+ * breakpoint.c (insert_breakpoints): Use ALL_BREAKPOINTS_SAFE.
+ (bpstat_stop_status): Likewise.
+ (remove_solib_event_breakpoints): Likewise.
+ (clear_momentary_breakpoints): Likewise.
+ (re_enable_breakpoints_in_shlibs): Don't reenable a breakpoint
+ if we still can't read the memory for that breakpoint.
+ (mention): Add bp_shlib_event case to keep gcc quiet.
+
+Fri Mar 8 12:08:12 1996 Jeffrey A Law (law@cygnus.com)
+
+ * breakpoint.h (enum enable): New enum shlib_disabled for
+ shared library breakpoints that have been temporarily disabled.
+ * breakpoint.c: Handle temporarily disabled shared library
+ breakpoints like disabled breakpoints in most places.
+ (insert_breakpoints): Use shlib_disabled to indicate
+ that an unsettable breakpoint is only temporarily disabled.
+ (re_enable_breakpoints_in_shlibs): New function.
+ * corelow.c (solib_add_stub): After adding shared libraries,
+ try to reenable any temporarily disabled breakpoints.
+ * infcmd.c (attach_command): Likewise.
+ * infrun.c (wait_for_inferior): Likewise.
+
+Fri Mar 8 11:41:25 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * defs.h (extract_long_unsigned_integer): Declare.
+ * findvar.c (extract_long_unsigned_integer): New function.
+ * printcmd.c (print_scalar_formatted): Use it.
+ * valprint.c (val_print_type_code_int): Likewise.
+
+Thu Mar 7 17:40:50 1996 Stan Shebs <shebs@andros.cygnus.com>
+
+ * infcmd.c (do_registers_info): Ignore anonymous registers.
+ * sh-tdep.c (set processor): New command to set specific
+ processor type.
+ (sh_reg_names, sh3_reg_names): Arrays of register names for
+ SH and SH3 processors.
+ (sh_set_processor_type): New function.
+ * sh3-rom.c (sh3_open): Call it.
+ (sh3_regname): Add names of all the bank registers.
+ (sh3_supply_register): Clean up formatting.
+ * config/sh/tm-sh.h (NUM_REGS, NUM_REALREGS): Increase to include
+ bank registers.
+ (REGISTER_NAMES): Add names of bank registers.
+ (FP15_REGNUM): Define.
+ (REGISTER_VIRTUAL_TYPE): Use it.
+ * monitor.c: Clean up some comments.
+
+Thu Mar 7 12:09:51 1996 J.T. Conklin <jtc@rtl.cygnus.com>
+
+ * i386b-nat.c: Revert part of Mar 5 change. FreeBSD collapsed the
+ s* and t* symbols too.
+
+Thu Mar 7 15:18:51 1996 James G. Smith <jsmith@cygnus.co.uk>
+
+ * symfile.c (generic_load): Avoid division by zero.
+
+Wed Mar 6 17:57:59 1996 Jeffrey A Law (law@cygnus.com)
+
+ * breakpoint.c (bfd_lookup_symbol): Provide for all SVR4 systems,
+ not just those with HANDLE_SVR4_EXEC_EMULATORS.
+
+ From Peter Schauer:
+ * breakpoint.c (internal_breakpoint_number): Move to file scope.
+ (create_solib_event_breakpoint): Use an internal breakpoint number.
+
+Wed Mar 6 00:32:44 1996 Wilfried Moser <moser@rtl.cygnus.com>
+
+ * valarith.c (value_in): Change builtin_type_chill_bool to
+ LA_BOOL_TYPE.
+
+Tue Mar 5 23:48:36 1996 Wilfried Moser <moser@rtl.cygnus.com>
+
+ * ch-exp.c (parse_primval): Handle CARD, MAX, MIN.
+ (match_string_literal): Handle control sequence.
+ (match_character_literal): Deto.
+
+ * ch-lang.c (chill_printchar): Change formating of nonprintable
+ characters from C'xx' to ^(num).
+ (chill_printstr): Deto.
+ (value_chill_card, value_chill_max_min): New functions to process
+ Chill's CARD, MAX, MIN.
+ (evaluate_subexp_chill): Process UNOP_CARD, UNOP_CHMAX, UNOP_CHMIN.
+
+ * expression.h (exp_opcode): Add UNOP_CARD, UNOP_CHMAX, UNOP_CHMIN
+ for Chill's CARD, MAX, MIN.
+
+ * valarith.c (value_in): Add processing of TYPE_CODE_RANGE
+ and change return type from builtin_type_int to
+ builtin_type_chill_bool.
+
+Tue Mar 5 18:54:04 1996 Stan Shebs <shebs@andros.cygnus.com>
+
+ * config/nm-nbsd.h (link_object, lo_name, etc): Move to here
+ from config/nm-nbsd.h.
+ * config/sparc/nm-nbsd.h (regs, fp_status, etc): Move to here
+ from config/sparc/tm-nbsd.h.
+
+ * config/m68k/nm-hp300hpux.h (FIVE_ARG_PTRACE): Define here
+ instead of in config/m68k/xm-hp300hpux.h.
+
+Tue Mar 5 12:05:35 1996 J.T. Conklin <jtc@rtl.cygnus.com>
+
+ * i386b-nat.c, m68knbsd-nat.c (fetch_core_registers): Provide
+ implementation for NetBSD systems.
+
+Mon Mar 4 23:44:16 1996 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * valarith.c (binop_user_defined_p): Return 0 for BINOP_CONCAT.
+ (value_concat): Handle varying strings (add COERCE_VARYING_ARRAY).
+
+ * ch-lang.c (evaluate_subexp_chill case MULTI_SUBSCRIPT): Error
+ if "function" is pointer to non-function.
+
+Mon Mar 4 17:47:03 1996 Stan Shebs <shebs@andros.cygnus.com>
+
+ * top.c (print_gdb_version): Update copyright year.
+
+Mon Mar 4 14:44:54 1996 Jeffrey A Law (law@cygnus.com)
+
+ From Peter Schauer:
+ * infrun.c (wait_for_inferior): Remove breakpoints and
+ switch terminal settings before calling SOLIB_ADD.
+ * solib.c (enable_break, SVR4 variant): Don't map in symbols
+ for the dynamic linker, the namespace pollution causes real
+ problems.
+
+Sun Mar 3 17:18:57 1996 James G. Smith <jsmith@cygnus.co.uk>
+
+ * remote-mips.c (common_breakpoint): Explicitly terminate the
+ returned buffer.
+
+Wed Feb 28 22:32:18 1996 Stan Shebs <shebs@andros.cygnus.com>
+
+ From Wilfried Moser <wilfried.moser@aut.alcatel.at>:
+ * remote.c (remote_detach): Send a command 'D' to the target
+ when detaching, update the function's comments.
+
+Thu Jun 6 16:11:38 1996 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * gnu-nat.c (thread_cmd_list): New declaration.
+ (parse_int_arg): New function.
+
+Wed Jun 5 17:28:04 1996 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * gnu-nat.h (struct proc): Add DETACH_SC field.
+ * gnu-nat.c (make_proc): Set DETACH_SC.
+ (struct inf): Add DETACH_SC & DEFAULT_THREAD_DETACH_SC fields.
+ (make_inf): Set DETACH_SC & DEFAULT_THREAD_DETACH_SC fields.
+ (add_thread_commands): Add set/show for detach-suspend-count.
+ Add takeover-suspend-count cmd.
+ (inf_detach): Set suspend counts to the detach SC, not 0.
+ (set_thread_detach_sc_cmd, show_thread_detach_sc_cmd,
+ set_task_detach_sc_cmd, show_task_detach_sc_cmd,
+ set_thread_default_thread_detach_sc_cmd,
+ show_thread_default_thread_detach_sc_cmd): New functions.
+ (show_task_cmd): Also show detach-suspend-count values.
+ (thread_takeover_sc_cmd): New function.
+
+Fri May 31 16:49:24 1996 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * gnu-nat.c (show_thread_run_cmd): Actually print state.
+
+Thu May 30 10:47:56 1996 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * gnu-nat.c (inf_signal): Make unforwardable exceptions an error.
+
+Tue May 28 17:06:36 1996 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * gnu-nat.c (inf_validate_stopped): proc_getprocinfo takes a
+ pointer to the flags now, not the flags themselves.
+
+Mon May 27 13:31:17 1996 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * gnu-nat.c (gnu_wait): Print debugging msgs for pending execs.
+ (gnu_create_inferior): Check return from ptrace.
+
+Sun May 26 16:56:35 1996 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * gnu-nat.h (struct proc): Add DEAD field.
+ * gnu-nat.c (make_proc): Initialize DEAD.
+ (inf_set_traced, inf_validate_task_sc, inf_validate_procs: Frob it.
+ (gnu_wait): Only abort for 0 threads if the task isn't dead.
+
+Sat May 25 17:06:05 1996 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * gnu-nat.c (inf_signal): Pass SIGCODE when posting a signal.
+
+Wed May 22 18:44:28 1996 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * gnu-nat.c (S_proc_wait_reply): Add SIGCODE argument.
+ (inf_set_traced): Only give no-signal-thread error message if
+ turning *on* tracing.
+
+Wed May 15 13:03:16 1996 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * gnu-nat.c (inf_validate_procs): If INF has no threads, always
+ set inf->threads_up_to_date to 0.
+ (inf_signal): Pass in new SIGCODE argument to msg_sig_post_untraced.
+ (gnu_wait): Pass in new TIMEOUT arg to interrupt_operation.
+ (proc_update_sc): Cast thread state arg to thread_set_state.
+ (proc_get_state): Cast thread state arg to thread_get_state.
+ (inf_validate_task_sc): Cast task_basic_info arg to task_info.
+ * i386gnu-nat.c (gnu_fetch_registers, gnu_store_registers): Call
+ inf_update_procs before we lookup the thread.
+ * config/i386/i386gnu.mh (MH_CFLAGS): New variable.
+
+Tue May 7 17:52:33 1996 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * gnu-nat.c (gnu_kill_inferior): Use inf_set_task to clear the task.
+
+Mon May 6 19:06:49 1996 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * gnu-nat.c (inf_set_traced): Use msg_set_init_int with
+ INIT_TRACEMASK instead of setting the exec flags.
+
+Fri May 3 19:10:57 1996 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * gnu-nat.c (inf_validate_procs): Don't clear INF->task if we find
+ the task's died, so others have a chance at it.
+ (gnu_resume): When single-stepping a single thread, given an error
+ if there is no such thread. When single-stepping one but running
+ the others, just given a warning and still run all the threads.
+ (gnu_wait): If there seem to be no threads, look harder, and
+ signal an error if there really aren't any.
+ (gnu_attach): Reset thread numbering to 0.
+
+ * i386gnu-nat.c (gnu_fetch_registers, gnu_store_registers): Give
+ thread name in warning messages.
+
+ * gnu-nat.c (active_inf): New function.
+ (show_sig_thread_cmd, show_stopped_cmd): Use it.
+ (info_port_rights, info_send_rights_cmd, info_port_sets_cmd,
+ info_recv_rights_cmd, info_port_rights_cmd, info_port_rights_cmd):
+ New functions.
+ (add_task_commands): Add new port-right info commands.
+
+Fri Apr 26 20:42:16 1996 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * gnu-nat.c (gnu_wait): Instead of _hurd_intr_rpc_mach_msg, just
+ use mach_msg with MACH_RCV_INTERRUPT.
+ (set_noninvasive_cmd): New function.
+ (add_task_commands): Add command entry for `set noninvasive'.
+
+Mon Mar 4 14:12:02 1996 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * gnu-nat.c (gnu_read_inferior): Use hurd_safe_memmove, not safe_bcopy.
+ (safe_bcopy): Function removed.
+
+Mon Dec 4 14:18:26 1995 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * gnu-nat.c (proc_update_sc): Assert only threads can have state.
+ (make_proc): Initialize state_valid & state_changed fields.
+
+Tue Nov 28 17:51:21 1995 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * reply_mig_hack.awk: New file.
+
+Tue Nov 14 14:31:03 1995 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * breakpoint.c (breakpoint_1): Print breakpoint thread field.
+
+ * lynx-nat.c (child_wait): Return TARGET_WAITKIND_SPURIOUS for new
+ threads.
+
+Mon Nov 13 18:30:53 1995 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * target.c (debug_to_check_threads): New function.
+
+ * inflow.c (terminal_init_inferior_with_pgrp): New function.
+ (terminal_init_inferior): Call terminal_init_inferior_with_pgrp.
+ * inferior.h (terminal_init_inferior_with_pgrp): New declaration,
+ but only if PROCESS_GROUP_TYPE is defined.
+
+Mon Nov 6 16:42:09 1995 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * target.c (debug_to_thread_alive): Pass through the return value.
+
+Thu Nov 2 18:05:00 1995 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * target.c (signals, target_signal_from_host, target_signal_to_host):
+ Add mach exceptions.
+ * target.h (enum target_signal): Add mach exceptions.
+
+Mon Oct 30 16:41:04 1995 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * gnu-nat.c: New file: gnu native backend.
+ * i386gnu-nat.c: New file: i386-specific part of gnu native backend.
+ * gnu-nat.h: New file.
+ * config/nm-gnu.h: New file.
+ * config/tm-i386gnu.h: New file.
+ * config/xm-i386gnu.h: New file.
+ * config/i386/i386gnu.mh: New file.
+ * config/i386/i386gnu.mt: New file.
+
+Wed Feb 28 15:50:12 1996 Fred Fish <fnf@cygnus.com>
+
+ * Makefile.in (VERSION): Bump version to 4.15.2 to establish
+ baseline for gdb 4.16 rerelease testing.
+
+Wed Feb 28 13:32:05 1996 Jeffrey A Law (law@cygnus.com)
+
+ * somsolib.c (som_solib_create_inferior_hook): Before returning
+ call clear_symtab_users.
+
+Tue Feb 27 00:04:46 1996 Stu Grossman (grossman@critters.cygnus.com)
+
+ * remote-e7000.c (e7000_open): Delete all breakpoints when
+ connecting to e7000. Change connect message to allow use of
+ monitor.exp in test suite.
+ * (e7000_load): Print transfer rate of download.
+ * symfile.c (generic_load): Print transfer rate of download.
+
+Sun Feb 25 13:58:33 1996 Stan Shebs <shebs@andros.cygnus.com>
+
+ * configure.in (mips*-*-vxworks*): New config.
+ * configure: Regenerated.
+
+ * config/mips/vxmips.mt, config/mips/tm-vxmips.h: New files.
+ * remote-vxmips.c (vx_convert_to_virtual, vx_convert_from_virtual):
+ Remove, never used.
+
+Sat Feb 24 12:30:28 1996 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * partial-stab.h (case N_FUN): Function symbols generated
+ by SPARCworks cc have a meaningless zero value, do not update
+ pst->textlow if the function symbol value is zero.
+
+ * stabsread.c (define_symbol): Initialize SYMBOL_TYPE field
+ for function prototype declaration symbols.
+
+Fri Feb 23 22:33:04 1996 Stu Grossman (grossman@critters.cygnus.com)
+
+ * remote-e7000.c (e7000_load): New routine to download via the
+ network.
+ * (e7000_wait): Don't backup PC when we hit a breakpoint.
+ Apparantly new sh2 pods get this right...
+ * (e7000_ops): Add call to e7000_load.
+
+Thu Feb 22 00:52:42 1996 J.T. Conklin <jtc@rtl.cygnus.com>
+
+ * config/m68k/{nbsd.mh,nbsd.mt,nm-nbsd.h,tm-nbsd.h,xm-nbsd.h},
+ m68knbsd-nat.c: New files, support for NetBSD/m68k.
+
+ * configure.in (m68k-*-netbsd*): New config.
+ * configure: Regenerated.
+
+Wed Feb 21 19:00:21 1996 Fred Fish <fnf@cygnus.com>
+
+ * standalone.c (open, _initialize_standalone): Fix obvious typos
+ reported by Martin Pool <martin@citr.uq.oz.au>.
+
+Wed Feb 21 14:24:04 1996 Jeffrey A Law (law@cygnus.com)
+
+ * solib.c (solib_create_inferior_hook): Fix thinko.
+
+Tue Feb 20 23:59:19 1996 Jeffrey A Law (law@cygnus.com)
+
+ * solib.c (solib_break_names): Define for Solaris and Linux.
+ (enable_break): For SVR4 systems, first try to use the debugger
+ interfaces in the dynamic linker to track shared library events
+ as they happen, then fall back to BKPT_AT_SYMBOL code. Convert
+ BKPT_AT_SYMBOL code to use shared library event breakpoints.
+ (solib_create_inferior_hook): Simplify BKPT_AT_SYMBOL code,
+ it no longer needs to restart/wait on the inferior.
+ * symfile.c (find_lowest_section): No longer static.
+ * symfile.h (find_lowest_section): Corresponding changes.
+
+Tue Feb 20 18:54:08 1996 Fred Fish <fnf@cygnus.com>
+
+ * valops.c (COERCE_FLOAT_TO_DOUBLE): Define default value.
+ (value_arg_coerce): Use COERCE_FLOAT_TO_DOUBLE.
+ * config/alpha/tm-alpha.h (COERCE_FLOAT_TO_DOUBLE): Define to 1.
+ * config/mips/tm-mips.h: Ditto.
+ * config/pa/tm-hppa.h: Ditto.
+ * config/rs6000/tm-rs6000.h: Ditto.
+ * config/sparc/tm-sparc.h: Ditto.
+
+Tue Feb 20 17:32:05 1996 J.T. Conklin <jtc@rtl.cygnus.com>
+
+ * config/{i386,ns32k}/nbsd.mh (NATDEPFILES): Remove core-aout.o.
+
+ * config/nm-nbsd.h (FETCH_INFERIOR_REGISTERS): Defined.
+ * config/xm-nbsd.h (CC_HAS_LONG_LONG, PRINTF_HAS_LONG_LONG):
+ #ifdef'd out definitions --- Causes serious gdb failures on
+ the i386. Need to investigate further before enabling.
+
+ * i386b-nat.c (fetch_inferior_registers, store_inferior_registers,
+ fetch_core_registers): New functions. These functions are defined
+ if FETCH_INFERIOR_REGISTERS is set. Registers are fetched/stored
+ with ptrace PT_GETREGS/PT_SETREGS.
+
+Tue Feb 20 16:55:06 1996 Stu Grossman (grossman@critters.cygnus.com)
+
+ * findvar.c (extract_floating store_floating): Replace `long
+ double' with `DOUBLEST'.
+
+Mon Feb 19 15:25:51 1996 J.T. Conklin <jtc@rtl.cygnus.com>
+
+ * config/xm-nbsd.h (CC_HAS_LONG_LONG, PRINTF_HAS_LONG_LONG):
+ Define.
+
+Mon Feb 19 10:32:05 1996 Jeffrey A Law (law@cygnus.com)
+
+ * symtab.h (looup_minimal_symbol_solib_trampoline): Declare.
+
+ * breakpoint.h (remove_solib_event_breakpoints): Declare.
+ * breakpoint.c (remove_solib_event_breakpoints): New function.
+ * somsolib.c (solib_create_inferior_hook): Remove all solib event
+ breakpoints before inserting any new ones. Use a solib event
+ breakpoint for the breakpoint at "_start".
+ Remove extraneous "\n" from calls to warning.
+
+ * breakpoint.c (breakpoint_1): Add missing "sigtramp" to bptypes
+ name array.
+
+Mon Feb 19 01:09:32 1996 Doug Evans <dje@cygnus.com>
+
+ * dwarfread.c (add_partial_symbol): Use ADD_PSYMBOL_ADDR_TO_LIST
+ for CORE_ADDR values.
+ (new_symbol): Use SYMBOL_VALUE_ADDRESS for CORE_ADDR values.
+ * symfile.h (add_psymbol_{,addr}to_list): Add prototypes.
+
+Sun Feb 18 14:37:13 1996 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * mipsread.c (mipscoff_symfile_read): Unconditionally add
+ alpha coff dynamic symbols for all symbol files. Makes skipping
+ over the trampoline code work when stepping from a function in a
+ shared library into a function in a different shared library.
+
+Sun Feb 18 09:27:10 1996 Stu Grossman (grossman@cygnus.com)
+
+ * config/sparc/tm-sparc.h: Define PS_FLAG_CARRY. Define
+ RETURN_VALUE_ON_STACK to return long doubles on the stack.
+
+Sat Feb 17 16:33:11 1996 Fred Fish <fnf@cygnus.com>
+
+ * Makefile.in (ch-exp.o): Add dependencies.
+ (various): Add gdb_string.h to dependencies that need it.
+
+Sat Feb 17 08:57:50 1996 Fred Fish <fnf@cygnus.com>
+
+ * symmisc.c (print_symbol_bcache_statistics): Update description for
+ printing byte cache statistics.
+
+Thu Feb 16 16:02:03 1996 Stu Grossman (grossman@cygnus.com)
+
+ * Add native support for long double data type.
+ * c-exp.y (%union): Change dval to typed_val_float. Use DOUBLEST
+ to store actual data. Change types of INT and FLOAT tokens to
+ typed_val_int and typed_val_float respectively. Create new token
+ DOUBLE_KEYWORD to specify the string `double'. Make production
+ for FLOAT use type determined by parse_number. Add production for
+ "long double" data type.
+ * (parse_number): Use sscanf to parse numbers as float, double or
+ long double depending upon the type of typed_val_float.dval. Also
+ allow user to specify `f' or `l' suffix to explicitly specify
+ float or long double constants. Change typed_val to
+ typed_val_int.
+ * (yylex): Change typed_val to typed_val_int. Also, scan for
+ "double" keyword.
+ * coffread.c (decode_base_type): Add support for T_LNGDBL basic
+ type.
+ * configure, configure.in: Add check for long double support in
+ the host compiler.
+ * defs.h: Define DOUBLEST appropriatly depending on whether
+ HAVE_LONG_DOUBLE (from autoconf) is defined. Also, fix prototypes
+ for functions that handle this type.
+ * expression.h (union exp_element): doubleconst is now type
+ DOUBLEST.
+ * m2-exp.y f-exp.y (%union): dval becomes type DOUBLEST.
+ * findvar.c (extract_floating): Make return value be DOUBLEST.
+ Also, add support for numbers with size of long double.
+ * (store_floating): Arg `val' is now type DOUBLEST. Handle all
+ floating types.
+ * parser-defs.h parse.c (write_exp_elt_dblcst): Arg expelt is now
+ DOUBLEST.
+ * valarith.c (value_binop): Change temp variables v1, v2 and v to
+ type DOUBLEST. Coerce type of result to long double if either op
+ was of that type.
+ * valops.c (value_arg_coerce): If argument type is bigger than
+ double, coerce to long double.
+ * (call_function_by_hand): If REG_STRUCT_HAS_ADDR is defined, and
+ arg type is float and > 8 bytes, then use pointer-to-object
+ calling conventions.
+ * valprint.c (print_floating): Arg doub is now type DOUBLEST.
+ Use appropriate format and precision to print out floating point
+ values.
+ * value.h: Fixup prototypes for value_as_double,
+ value_from_double, and unpack_double to use DOUBLEST.
+ * values.c (record_latest_value): Remove check for invalid
+ floats. Allow history to store them so that people may examine
+ them in hex if they want.
+ * (value_as_double unpack_double): Change return value to DOUBLEST.
+ * (value_from_double): Arg `num' is now DOUBLEST.
+ * (using_struct_return): Use RETURN_VALUE_ON_STACK macro (target
+ specific) to expect certain types to always be returned on the stack.
+
+Fri Feb 16 14:00:54 1996 Fred Fish <fnf@cygnus.com>
+
+ * bcache.c, bcache.h: New files to implement a byte cache.
+ * Makefile.in (SFILES): Add bcache.c.
+ (symtab_h): Add bcache.h.
+ (HFILES_NO_SRCDIR): add bcache.h
+ (COMMON_OBJS): Add bcache.o
+ (bcache.o): New target.
+ * dbxread.c (start_psymtab): Make global_syms & static_syms
+ type "partial_symbol **".
+ * hpread.c (hpread_start_symtab): Ditto.
+ * os9kread.c (os9k_start_psymtab): Ditto.
+ * stabsread.h (start_psymtab): Ditto.
+ * {symfile.c, symfile.h} (start_psymtab_common): Ditto.
+ * maint.c (maintenance_print_statistics): Call
+ print_symbol_bcache_statistics.
+ * objfiles.c (allocate_objfile): Initialize psymbol bcache malloc
+ and free pointers.
+ * solib.c (allocate_rt_common_objfile): Ditto.
+ * symfile.c (reread_symbols): Ditto.
+ (free_objfile): Free psymbol bcache when objfile is freed.
+ (objfile_relocate): Use new indirect psymbol pointers.
+ * objfiles.h (struct objfile): Add psymbol cache.
+ * symfile.c (compare_psymbols): Now passed pointers to pointers to
+ psymbols.
+ (reread_symbols): Free psymbol bcache when freeing other objfile
+ resources.
+ (add_psymbol_to_list, add_psymbol_addr_to_list): Initialize new
+ psymbol using the psymbol bcache.
+ (init_psymbol_list): Psymbol lists now contain pointers rather than
+ the actual psymbols.
+ * symfile.h (psymbol_allocation_list): Psymbol lists now dynamically
+ grown arrays of pointers.
+ (ADD_PSYMBOL_VT_TO_LIST): Initialize new symbol using the psymbol
+ bcache.
+ * symmisc.c (print_partial_symbols): Now takes pointer to pointer
+ to partial symbol.
+ (print_symbol_bcache_statistics): New function to print per objfile
+ bcache statistics.
+ (print_partial_symbol, print_partial_symbols,
+ maintenance_check_symtabs, extend_psymbol_list):
+ Account for change to pointer to pointer to partial symbol.
+ * symtab.c (find_pc_psymbol, lookup_partial_symbol, decode_line_2,
+ make_symbol_completion_list):
+ Account for change to pointer to pointer to partial symbol.
+ * symtab.h (bcache.h): Include.
+ * xcoffread.c (xcoff_start_psymtab): Make global_syms & static_syms
+ type "partial_symbol **".
+
+Fri Feb 16 10:02:34 1996 Fred Fish <fnf@cygnus.com>
+
+ * dwarfread.c (free_utypes): New function.
+ (read_file_scope): Call free_utypes as cleanup, rather than just
+ freeing the utypes pointer.
+
+Thu Feb 15 21:40:52 1996 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * demangle.c (is_cplus_marker): New function, checks if a
+ character is one of the commonly used C++ marker characters.
+ * defs.h (is_cplus_marker): Add prototype.
+ * c-typeprint.c (c_type_print_base), ch-lang.c (chill_demangle),
+ cp-valprint.c (cp_print_class_method), mdebugread.c (parse_symbol),
+ stabsread.c (define_symbol, read_member_functions, read_struct_fields),
+ symtab.h (OPNAME_PREFIX_P, VTBL_PREFIX_P, DESTRUCTOR_PREFIX_P),
+ values.c (vb_match): Use is_cplus_marker instead of comparison
+ with CPLUS_MARKER.
+
+Thu Feb 15 18:08:13 1996 Fred Fish <fnf@cygnus.com>
+
+ * symfile.h (INLINE_ADD_PSYMBOL): Default this to 0 and possibly
+ delete entirely someday.
+
+Thu Feb 15 15:25:34 1996 Stan Shebs <shebs@andros.cygnus.com>
+
+ * mpw-make.sed: Edit out makefile rebuild rule.
+ (host_alias, target_alias): Comment out instead of deleting.
+ (@LIBS@): Edit out references.
+
+Tue Feb 13 22:56:46 1996 Fred Fish <fnf@cygnus.com>
+
+ * symfile.c (add_psymbol_to_list, add_psymbol_addr_to_list):
+ Use n_psyms in OBJSTAT, not psyms.
+
+Mon Feb 12 15:59:31 1996 Doug Evans <dje@charmed.cygnus.com>
+
+ * configure.in (sparclet-*-aout*): New config.
+ * configure: Regenerated.
+
+Mon Feb 12 14:17:52 1996 Fred Fish <fnf@cygnus.com>
+
+ * somsolib.c (som_solib_add): Use xmalloc rather than bare
+ unchecked call to malloc.
+ * remote-mips.c (pmon_load_fast): ditto.
+ * remote-mm.c (mm_open): ditto.
+ * hpread.c (hpread_lookup_type): ditto.
+ * remote-adapt.c (adapt_open): ditto.
+
+Mon Feb 12 13:11:32 1996 Fred Fish <fnf@cygnus.com>
+
+ * f-lang.c (allocate_saved_bf_node, allocate_saved_function_node,
+ allocate_saved_f77_common_node, allocate_common_entry_node,
+ add_common_block): Use xmalloc rather than malloc, some of which
+ were unchecked.
+ * gnu-regex.c: At same point as other gdb specific changes
+ #undef malloc and then #define it to xmalloc.
+ * ch-exp.c (growbuf_by_size): Use xmalloc/xrealloc rather than
+ bare unchecked calls to malloc/realloc.
+ * stabsread.c (dbx_lookup_type): Use xmalloc rather than bare
+ unchecked call to malloc.
+
+Wed Feb 7 11:31:26 1996 Stu Grossman (grossman@cygnus.com)
+
+ * symtab.c (gdb_mangle_name): Change opname var to be const to
+ match return val of cplus_mangle_name.
+ * i960-tdep.c: Change arg types of next_insn to match callers.
+
+Wed Feb 7 07:34:24 1996 Fred Fish <fnf@cygnus.com>
+
+ * config/i386/linux.mh (XM_CLIBS, GDBSERVER_LIBS): Remove. These
+ apparently aren't needed in any reasonably recent version of
+ linux.
+
+Tue Feb 6 21:37:03 1996 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * stabsread.c (read_range_type): If !self-subrange and language
+ is Chill, assume a true range. If a true_range is a sub_subrange,
+ use builtin_type_int for index_type.
+
+Tue Feb 6 18:38:51 1996 J.T. Conklin <jtc@slave.cygnus.com>
+
+ * nindy-share/nindy.c (say): Use stdarg.h macros when compiling
+ with an ANSI compiler.
+
+Mon Feb 5 18:24:28 1996 Steve Chamberlain <sac@slash.cygnus.com>
+
+ From Michael_Snyder@NeXT.COM (Michael Snyder):
+ * valops.c (value_arg_coerce): Coerce float to double, unless the
+ function prototype specifies float.
+
+Mon Feb 5 09:51:55 1996 Tom Tromey <tromey@creche.cygnus.com>
+
+ * language.c (set_language_command): Use languages table when
+ printing available languages.
+
+Sat Feb 3 12:22:05 1996 Fred Fish <fnf@cygnus.com>
+
+ Fix problems reported by Hans Verkuil (hans@wyst.hobby.nl):
+ * command.c (add_cmd): Add missing initialization for enums member.
+ Reorder members to match structure declaration to make it easier to
+ tell when one is missing.
+ * exec.c (exec_file_command): Fix problem where filename in malloc'd
+ memory is referenced after being freed.
+
+Sat Feb 3 03:26:21 1996 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * dwarfread.c (read_func_scope): Avoid GDB core dumps if
+ AT_name tag is missing.
+
+ * procfs.c (procfs_stopped_by_watchpoint): Fix logic when
+ FLTWATCH and FLTKWATCH are defined.
+
+ * remote.c (remote_read_bytes): Advance memaddr for transfers,
+ return number of bytes transferred for partial reads.
+
+ * top.c (init_signals): Reset SIGTRAP to SIG_DFL.
+
+Fri Feb 2 13:40:50 1996 Steve Chamberlain <sac@slash.cygnus.com>
+
+ * win32-nat.c (mappings): Add ppc registers.
+ (child_resume): Turn off step for ppc.
+
+Thu Feb 1 10:29:31 1996 Steve Chamberlain <sac@slash.cygnus.com>
+
+ * config/powerpc/(cygwin32.mh, cygwin32.mt, tm-cygwin32.h,
+ xm-cygwin32.h): New.
+ * config/i386/(*win32*): Becomes *cygwin32*.
+ * configure.in (i[3456]86-*-win32*): Becomes i[3456]86-*-cygwin32.
+ (powerpcle-*-cygwin32): New.
+ * configure: Regenerate.
+ * win32-nat.c (child_create_inferior): Call CreateProcess
+ with the right program arg.
+
+Thu Feb 1 11:01:10 1996 Jeffrey A Law (law@cygnus.com)
+
+ * config/pa/tm-hppa.h (SOFT_FLOAT): Provide a default definition.
+
+Wed Jan 31 19:01:28 1996 Fred Fish <fnf@cygnus.com>
+
+ * serial.c: Change fputc/fputs/fprintf to _unfiltered forms.
+
+Wed Jan 31 18:36:27 1996 Stan Shebs <shebs@andros.cygnus.com>
+
+ * config/sparc/xm-sun4os4.h (HAVE_TERMIOS): Remove.
+
+ * config/sparc/xm-sparc.h (HAVE_WAIT_STRUCT): Remove, never used.
+
+ * config/i386/nm-i386mach.h (CHILD_PREPARE_TO_STORE): Move to
+ here from config/i386/xm-i386mach.h, fix name.
+ * config/i386/nm-sun386.h: Ditto, from config/i386/xm-sun386.h.
+ * config/i386/nm-ptx4.h (CHILD_PREPARE_TO_STORE): Move to
+ here from config/i386/xm-ptx4.h.
+ * config/i386/nm-ptx4.h: Ditto, from config/i386/xm-ptx.h.
+ * config/i386/nm-symmetry.h: Ditto, from config/i386/xm-symmetry.h.
+ * config/m68k/nm-sun3.h: Ditto, from config/m68k/xm-sun3.h.
+ * config/sparc/nm-nbsd.h: Ditto, from config/sparc/xm-nbsd.h.
+ * config/sparc/nm-sun4os4: Ditto, from config/sparc/xm-sparc.h.
+
+ * config/sparc/nm-sun4sol2.h: New file, renamed from nm-sysv4.h.
+ (PRSVADDR_BROKEN): Move here from xm-sun4sol2.h.
+ * config/sparc/sun4sol2.mh (NAT_FILE): Update.
+
+Wed Jan 31 17:20:26 1996 Jeffrey A Law (law@cygnus.com)
+
+ * config/pa/tm-hppa.h (EXTRACT_RETURN_VALUE): Handle software
+ floating point correctly.
+ (STORE_RETURN_VALUE): Likewise.
+ * config/pa/tm-pro.h (SOFT_FLOAT): define.
+
+Wed Jan 31 13:34:52 1996 Fred Fish <fnf@cygnus.com>
+
+ * config/i386/xm-linux.h (MMAP_BASE_ADDRESS, MMAP_INCREMENT):
+ Define to what should be reasonable values. However, apparently
+ a bug in linux mmap prevents mapped symbol tables from working.
+
+Tue Jan 30 18:26:19 1996 Fred Fish <fnf@cygnus.com>
+
+ * defs.h (errno.h>: Move #include closer to head of file to solve
+ obscure problem with systems that declare perror with const arg, in
+ both errno.h and stdio.h, and const is defined away by intervening
+ local include.
+
+Tue Jan 30 15:41:10 1996 Fred Fish <fnf@cygnus.com>
+
+ From Jon Reeves <reeves@zk3.dec.com>:
+ * i386-stub.c (getpacket): Change fprintf stream from "gdb" to stderr.
+ (mem_fault_routine): Fix misplaced volatile type qualifier in decl.
+
+Mon Jan 29 19:05:58 1996 Fred Fish <fnf@cygnus.com>
+
+ * Makefile.in (diststuff): Make all-doc; diststuff target does not
+ exist in doc/Makefile.in.
+
+Mon Jan 29 18:44:57 1996 Stan Shebs <shebs@andros.cygnus.com>
+
+ * config/m88k/xm-cxux.h (BP_HIT_COUNT): Remove, never used.
+
+Mon Jan 29 00:10:35 1996 Wilfried Moser <moser@rtl.cygnus.com>
+
+ * ch-valprint.c (calculate_array_length): New function to
+ determine the length of an array type.
+ (chill_val_print (case TYPE_CODE_ARRAY)): If the length of an
+ array type is zero, call calculate_array_length.
+
+ * gdbtypes.c (get_discrete_bounds (case TYPE_CODE_ENUM)): The
+ values may not be sorted. Scan all entries and set the real lower
+ and upper bound.
+
+Sun Jan 28 15:50:42 1996 Fred Fish <fnf@cygnus.com>
+
+ * config/xm-linux.h: Move include of solib.h and #define of
+ SVR4_SHARED_LIBS from here ...
+ * config/nm-linux.h: ...to here.
+
+Sat Jan 27 10:34:05 1996 Fred Fish <fnf@cygnus.com>
+
+ * configure.in (AC_CHECK_HEADERS): Check for sys/procfs.h.
+ Also check for gregset_t and fpregset_t types.
+ * configure: Regenerate.
+ * core-regset.c (sys/procfs.h): Only include if HAVE_SYS_PROCFS_H
+ is defined.
+ (fetch_core_registers): Turn into stub unless both HAVE_GREGSET_T
+ and HAVE_FPREGSET_T are defined. These changes allow systems
+ like linux that are migrating to /proc support to use a single
+ configuration for both new and old versions.
+
+ * config/i386/linux.mt: Note that this is now for both a.out and
+ ELF systems.
+ * config/i386/linux.mh (NATDEPFILES): Add solib.o, core-regset.o,
+ i386v4-nat.o
+ * config/i386/tm-linux.h (tm-sysv4.h): Include.
+ * config/i386/xm-linux.h (solib.h): Include
+ (SVR4_SHARED_LIBS): Define.
+ * i386v4-nat.c: Only compile if HAVE_SYS_PROCFS_H is defined.
+ (supply_gregset, fill_gregset): Compile if HAVE_GREGSET_T defined.
+ (supply_fpregset, fill_fpregset): Compile if HAVE_FPREGSET_T
+ defined.
+
+Fri Jan 26 13:48:14 1996 Stan Shebs <shebs@andros.cygnus.com>
+
+ * config/sparc/xm-sparc.h (NEW_SUN_CORE): Remove, never used.
+ * config/i386/xm-sun386.h: Ditto.
+ * config/m68k/xm-sun2.h, config/m68k/xm-sun3.h: Ditto.
+
+Thu Jan 25 16:05:53 1996 Tom Tromey <tromey@creche.cygnus.com>
+
+ * Makefile.in (INSTALLED_LIBS, CLIBS): Include @LIBS@.
+
+Thu Jan 25 09:22:15 1996 Steve Chamberlain <sac@slash.cygnus.com>
+
+ From Greg McGary <gkm@gnu.ai.mit.edu>:
+ * dcache.c (dcache_peek, dcache_poke): Advance addr for
+ multi-byte I/O.
+
+Thu Jan 25 13:08:51 1996 Doug Evans (dje@cygnus.com)
+
+ * infrun.c (normal_stop): Fix test for shared library event.
+
+Thu Jan 25 03:26:38 1996 Doug Evans <dje@charmed.cygnus.com>
+
+ * configure.in (sparc64-*-*): Add default host configuration.
+ (sparc64-*-solaris2*): Add target configuration.
+ (sparc64-*-solaris2* host): Link statically if GCC used.
+ * configure: Regenerated.
+ * sparc/sp64sol2.mt: New file.
+
+Wed Jan 24 22:31:37 1996 Doug Evans <dje@charmed.cygnus.com>
+
+ * Makefile.in (RUNTEST): srcdir renamed to rootsrc.
+
+Wed Jan 24 15:42:24 1996 Tom Tromey <tromey@creche.cygnus.com>
+
+ * Makefile.in (lint): Close backquotes.
+
+Wed Jan 24 13:19:10 1996 Fred Fish <fnf@cygnus.com>
+
+ * NEWS: Make note of new record and replay feature for
+ remote debug sessions.
+ * serial.c (gdbcmd.h): Include.
+ (serial_logfile, serial_logfp, serial_reading, serial_writing):
+ Define here, for remote debug session logging.
+ (serial_log_command, serial_logchar, serial_write, serial_readchar):
+ New functions for remote debug session logging.
+ (serial_open): Open remote debug session log file when needed.
+ (serial_close): Close remote debug session log file when needed.
+ (_initialize_serial): Add set/show commands for name of remote
+ debug session log file.
+ * serial.h (serial_readchar): Declare
+ (SERIAL_READCHAR): Call serial_readchar().
+ (SERIAL_WRITE): Call serial_write().
+ (serial_close): Declare as extern.
+ (serial_logfile, serial_logfp): Declare.
+ * top.c (execute_command): Declare serial_logfp. Log user command
+ in remote debug session log if log file is open.
+ * remote-array.c (array_wait): #ifdef out echo to gdb_stdout.
+ (array_read_inferior_memory): Rewrite to fix memory overwrite bug.
+ * remote-array.c (SREC_SIZE): Remove, duplicates define in
+ monitor.h.
+ * remote-array.c (hexchars, hex2mem): Remove, unused.
+ * gdbserver/low-linux.c (store_inferior_registers): Remove
+ unnecessary extern declaration of registers[].
+ * gdbserver/Makefile.in (all): Add gdbreplay.
+ * gdbserver/gdbreplay.c: New file.
+ * gdbserver/README: Give example of recording a remote
+ debug session with gdb and then replaying it with gdbreplay.
+
+Tue Jan 23 18:02:35 1996 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * stabsread.c (rs6000_builtin_type): Make bool type unsigned.
+ (read_one_struct_field): Support boolean bitfields.
+ * c-valprint.c (c_val_print): Print booleans properly.
+
+Tue Jan 23 18:54:09 1996 Stan Shebs <shebs@andros.cygnus.com>
+
+ * remote-vxsparc.c (vx_convert_to_virtual, vx_convert_from_virtual):
+ Remove, never used.
+ * config/sparc/vxsparc.mt (TDEPFILES): Add remote-vxsparc.o.
+
+Tue Jan 23 14:36:05 1996 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * ch-exp.c (parse_tuple): Error if invalid mode.
+
+ * value.h (COERCE_ARRAY): Don't coerce enums.
+ (COERCE_ENUM): Don't COERCE_REF.
+ (COERCE_NUMBER): New macro (same as COERCE_ARRAY then COERCE_ENUM).
+ * valops.c (value_assign): Only do COERCE_ARRAY if internalvar (let
+ value_cast handle it otherwise); do *not* COERCE_ENUM either way.
+ * valarith.c: Use COERCE_NUMBER instead od COEREC_ARRAY.
+ Add COERCE_REF before COERCE_ENUM.
+ * values.c (value_as_long): Simplify.
+
+ * valops.c (value_array): Create internalvar if !c_style_arrays.
+
+ * language.c (lang_bool_type): Add Fortran support.
+ * eval.c (OP_BOOL): Use LA_BOOL_TYPE.
+
+Tue Jan 23 13:08:26 1996 Jeffrey A Law (law@cygnus.com)
+
+ * symfile.c (auto_solib_add): Renamed from auto_solib_add_at_startup.
+ All references changed.
+ * breakpoint.c (bpstat_what): Add shlib_event to the class types.
+ Update state table. Reformat so that it's still readable.
+ When we hit the shlib_event breakpoint, set the calss of shlib_event.
+ (breakpoint_1): Add "shlib events" as a breakpoint type.
+ Print the shlib_event breakpoint like other breakpoints.
+ (create_solib_event_breakpoint): New function.
+ (breakpoint_re_set_one): Handle solib_event breakpoints.
+ * breakpoint.h (enum bytype): Add bp_shlib_event breakpoint type.
+ (enum bpstat_what_main_action): Add BPSTAT_WHAT_CHECK_SHLIBS
+ action.
+ (create_solib_event_breakpoint): Declare.
+ * infrun.c (wait_for_inferior): Handle CHECK_SHLIBS bpstat.
+ (normal_stop): Inform the user when the inferior stoped due
+ to a shared library event.
+ (_initialize_infrun): Add new set/show variable "stop-on-solib-events"
+ to control whether or not gdb continues the inferior or stops it when
+ a shared library event occurs.
+ * minsyms.c (lookup_minimal_symbol_solib_trampoline): New function.
+ * somsolib.c (TODO list): Update.
+ (som_solib_create_inferior_hook): Arrange for gdb to be notified
+ when significant shared library events occur.
+ * hppa-tdep.c (find_unwind_entry): No longer static.
+
+Tue Jan 23 09:00:48 1996 Doug Evans <dje@charmed.cygnus.com>
+
+ * printcmd.c (print_insn): Pass fprintf_unfiltered to
+ INIT_DISASSEMBLE_INFO.
+
+Mon Jan 22 16:59:40 1996 Stan Shebs <shebs@andros.cygnus.com>
+
+ * remote.c (remotebreak): New GDB variable.
+ (remote_break): New global.
+ (remote_interrupt): Send a break instead of ^C if remote_break.
+ * NEWS: Describe the new variable.
+
+Mon Jan 22 16:24:11 1996 Doug Evans <dje@charmed.cygnus.com>
+
+ * sparc-tdep.c (_initialize_sparc_tdep): Always use print_insn_sparc.
+
+Fri Jan 19 07:19:38 1996 Fred Fish <fnf@cygnus.com>
+
+ * hp300ux-nat.c (getpagesize): Remove unused function
+ fetch_core_registers.
+ (hp300ux_core_fns): Remove, is unused.
+ (_initialize_core_hp300ux): Remove, is unused.
+ (gdbcore.h): Remove #include, no longer needed.
+
+Fri Jan 19 00:59:53 1996 Jeffrey A Law (law@cygnus.com)
+
+ * rs6000-nat.c (exec_one_dummy_insn): Rework to avoid
+ ptrace bug in aix4.1.3 on the rs6000.
+
+Wed Jan 17 13:22:27 1996 Stan Shebs <shebs@andros.cygnus.com>
+
+ * remote-hms.c (hms_ops): Add value for to_thread_alive.
+ * remote-nindy.c (nindy_ops): Ditto.
+ * remote-udi.c (udi_ops): Ditto.
+
+Tue Jan 16 18:00:35 1996 James G. Smith <jsmith@cygnus.co.uk>
+
+ * remote-mips.c (pmon_opn, pmon_wait, pmon_makeb64, pmon_zeroset,
+ pmon_checkset, pmon_make_fastrec, pmon_check_ack,
+ pmon_load_fast): New functions. Support for the PMON monitor world.
+ (common_open): New function to merge support for different monitors.
+ (mips_open): Use common_open().
+ (mips_send_command): New function.
+ (mips_send_packet): Scan out-of-sequence packets.
+ (mips_enter_debug, mips_exit_debug): New functions.
+ (pmon_ops): New target definition structure.
+
+Tue Jan 16 11:22:58 1996 Stu Grossman (grossman@cygnus.com)
+
+ * Makefile.in (CLIBS): Add LIBS to allow libraries to be
+ specified on the make command line (via make LIBS=xxx).
+
+
+Fri Jan 12 21:41:58 1996 Jeffrey A Law (law@cygnus.com)
+
+ * symtab.c (find_pc_symtab): Don't lose if OBJF_REORDERED
+ is set but there are no psymtabs.
+
+Fri Jan 12 15:56:12 1996 Steve Chamberlain <sac@slash.cygnus.com>
+
+ * dsrec.c (load_srec): Remove unused variable.
+ * monitor.c (monitor_expect): Don't expect a ^C to echo.
+ * serial.c (serial_open): Add parallel interface.
+ * sh3-rom.c (parallel, parallel_in_use): New.
+ (sh3_load): If parallel_in_use, download though the
+ parallel port.
+ (sh3_open): Open parallel port if specified.
+ (sh3_close): New function.
+ (_inititalize_sh3): Add sh3_close hook and documentation.
+ * monitor.c (monitor_close): Export.
+ * monitor.h (monitor_close): Add prototype.
+
+Fri Jan 12 13:11:42 1996 Stan Shebs <shebs@andros.cygnus.com>
+
+ From Wilfried Moser <wilfried.moser@aut.alcatel.at>:
+ * remote.c (remotetimeout): New GDB variable, use to set the
+ remote timeout for reading.
+
+Fri Jan 12 07:14:27 1996 Fred Fish <fnf@cygnus.com>
+
+ * lynx-nat.c, irix4-nat.c, sparc-nat.c: Include gdbcore.h
+ to get "struct core_fns" defined.
+ * Makefile.in (lynx-nat.o, irix4-nat.o, sparc-nat.o):
+ Are dependent upon gdbcore_h.
+
+Thu Jan 11 23:13:24 1996 Per Bothner <bothner@cygnus.com>
+
+ * symfile.c (decrement_reading_symtab): New function.
+ * symfile.c, symtab.h (currently_reading_symtab): New variable.
+ * symfile.c (psymtab_to_symtab): Adjust currently_reading_symtab.
+ * gdbtypes.c (check_typedef): Don't call lookup_symbol if
+ currently_reading_symtab (since that could infinitely recurse).
+
+Thu Jan 11 17:21:25 1996 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * stabsread.c (read_struct_type): Trivial simplification.
+
+ * stabsread.c (define-symbol): Use invisible references
+ for TYPE_CODE_SET and TYPE_CODE_BITSTRING too.
+ * valops.c (call_function_by_hand): Likewise.
+ * eval.c (evaluate_subexp_standard): When known, use the formal
+ parameter type as the expected type when evaluating arg expressions.
+ * ch-lang.c (evaluate_subexp_chill): Likewise (for MULTI_SUBSCRIPT).
+
+Thu Jan 11 10:08:14 1996 Tom Tromey <tromey@creche.cygnus.com>
+
+ * main.c (main): Disable window interface if --help or --version
+ specified.
+
+Wed Jan 10 16:08:49 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
+
+ * configure.in, configure: Recognize rs6000-*-aix4*.
+ * config/powerpc/xm-aix.h: Reduce to include "xm-aix4.h".
+ * config/rs6000/aix4.mh (XM_FILE): Point to xm-aix4.h.
+ * config/rs6000/xm-aix4.h: New file.
+ * config/xm-aix4.h: New file.
+
+Wed Jan 10 11:25:37 1996 Fred Fish <fnf@cygnus.com>
+
+ From Wilfried Moser <wilfried.moser@aut.alcatel.at>:
+ * gdbserver/low-linux.c: New file.
+ * remote.c (remote_read_bytes): Fix aborts on larger packets.
+
+ * config/i386/linux.mh (GDBSERVER_DEPFILES, GDBSERVER_LIBS):
+ Define.
+ * stabsread.c (define_symbol): If register value is too large,
+ tell what it is and what max is.
+
+Tue Jan 9 09:33:53 1996 Jeffrey A Law (law@cygnus.com)
+
+ * hpread.c (hpread_build_psymtabs): Finish Jan 4th
+ enum namespace -> enum_namespace change.
+
+Tue Jan 9 04:44:47 1996 Wilfried Moser <moser@rtl.cygnus.com>
+
+ * ch-exp.c (parse_primval): In case ARRAY, add missing
+ FORWARD_TOKEN ().
+
+Mon Jan 8 13:29:34 1996 Stan Shebs <shebs@andros.cygnus.com>
+
+ * remote-mips.c (mips_receive_header): Recognize \012 instead
+ of \n, but write \n when program sends a \012.
+ * ser-mac.c (mac_input_buffer): Increase size of buffer.
+
+Mon Jan 8 12:00:40 1996 Jeffrey A Law (law@cygnus.com)
+
+ * infptrace.c (initialize_infptrace): Move function out of
+ #ifdef conditional; put code within the function inside an
+ #ifdef conditional.
+
+ * buildsym.c (end_symtab): Remove sort_pending and sort_linevec
+ arguments. Sorting is now dependent on OBJF_REORDERED. All
+ callers/references changed.
+ * dbxread.c (read_ofile_symtab): Correctly determine value for
+ last_source_start_addr for reordered executables.
+ (process_one_symbol): Handle N_FUN with no name as an end of
+ function marker.
+ * partial-stab.h (case N_FN, N_TEXT): Don't assume CUR_SYMBOL_VALUE
+ is the high text address for a psymtab.
+ (case N_SO): Likewise.
+ (case N_FUN): Handle N_FUN with no name as an end of function
+ marker.
+ * minsyms.c (lookup_minimal_symbol_by_pc): Examine all symbols
+ at the same address rather than a random subset of them.
+ * coffread.c (coff_symfile_init): Set OBJF_REORDERED.
+ * elfread.c (elf_symfile_init): Similarly.
+ * somread.c (som_symfile_init): Similarly.
+ * xcoffread.c (xcoff_symfile_init): Similarly.
+
+Fri Jan 5 17:46:01 1996 Stu Grossman (grossman@cygnus.com)
+
+ * stack.c (print_stack_frame print_frame_info) symmisc.c
+ (dump_symtab): Change RETURN_MASK_ERROR to RETURN_MASK_ALL so
+ that catch_errors doesn't get blindsided by QUIT and lose the
+ cleanup chain. This fixes a problem where ^C while in a
+ user-defined command sometimes leaves instream NULL and causes a
+ segfault in command_loop.
+
+Fri Jan 5 13:59:16 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
+
+ * configure.in, configure: Add `-ldl -lw' for Solaris linking.
+
+Fri Jan 5 12:02:00 1996 Steve Chamberlain <sac@slash.cygnus.com>
+
+ * config/sh/sh.mt, config/powerpc/*.mt, config/pa/hppapro.mt,
+ config/m68k/monitor.mt, config/h8500/h8500.mt, config/h8300/h8300.mt:
+ srec.o renamed to dsrec.o.
+
+Thu Jan 4 16:04:54 1996 Stu Grossman (grossman@cygnus.com)
+
+ * breakpoint.c (remove_breakpoint): Change error to warning so
+ that hardware watchpoint removal problems won't leave breakpoint
+ traps in the target.
+ * remote-e7000.c (e7000_insert_breakpoint,
+ e7000_remove_breakpoint): Use e7000 based breakpoints, not memory
+ breakpoints.
+ * (e7000_wait): Adjust PC back by two when we see a breakpoint to
+ compensate for e7000 maladjustment.
+ * sparcl-tdep.c (sparclite_check_watch_resources): Fix logic bug
+ which prevented hardware watchpoints from working.
+
+Thu Jan 4 10:44:17 1996 Fred Fish <fnf@cygnus.com>
+
+ * infptrace.c (udot_info): New function.
+ (PT_*): Define each individually if that one is not defined.
+ * rs6000-nat.c (kernel_u_size): New function
+ Include <sys/user.h> for "struct user"
+ * alpha-nat.c (kernel_u_size): New function.
+ Include <sys/user.h> for "struct user"
+ * sparc-nat.c (kernel_u_size): New function.
+ Include <sys/user.h> for "struct user"
+ * i386b-nat.c (kernel_u_size): New function.
+ * i386v-nat.c (kernel_u_size): New function.
+ * config/i386/nm-fbsd.h (KERNEL_U_SIZE): Define.
+ (kernel_u_size): Declare.
+ * config/i386/nm-linux.h (KERNEL_U_SIZE): Define.
+ (kernel_u_size): Declare.
+ * config/sparc/nm-sun4os4.h (KERNEL_U_SIZE): Define.
+ (kernel_u_size): Declare.
+ * config/alpha/nm-osf2.h (KERNEL_U_SIZE): Define.
+ (kernel_u_size): Declare.
+ * config/rs6000/nm-rs6000.h (KERNEL_U_SIZE): Define.
+ (kernel_u_size): Declare.
+
+Thu Jan 4 11:00:01 1996 steve chamberlain <sac@slash.cygnus.com>
+
+ * mdebugread.c (mylookup_symbol): enum namespace becomes
+ enum_namespace type.
+ * symfile.c (add_psymbol_to_list)
+ (add_psymbol_addr_to_list): Ditto.
+ * symtab.c (lookup_partial_symbol): Ditto.
+ (lookup_symbol): Ditto.
+ (lookup_block_symbol): Ditto.
+ * win32-nat.c (handle_load_dll): Use incoming dll base.
+ (child_wait): Catch DLL load errors.
+ (create_child_inferior): Translated between paths correctly.
+
+Wed Jan 3 23:13:53 1996 Fred Fish <fnf@cygnus.com>
+
+ * i386v4-nat.c (supply_gregset, fill_gregset): Subtract NUM_FREGS
+ from NUM_REGS to get number of general registers that we care about.
+ * config/i386/tm-i386.h (REGISTER_BYTES): Define in terms
+ of number of general regs and number of floating point regs.
+
+Wed Jan 3 19:49:54 1996 steve chamberlain <sac@slash.cygnus.com>
+
+ * config/i386/tm-win32.h (IN_SOLIB_CALL_TRAMPOLINE): New.
+ (SKIP_TRAMPOLINE_CODE): New.
+ * config/i386/xm-win32.h (CANT_FORK): Deleted.
+ (SLASH*) Changed to use unix style slash.
+ * symtab.h (namespace enum): becomes typedef to avoid namespace
+ collision in C++.
+ * infcmd.c (path_command): Use empty string if PATH name not set.
+ * i386-tdep.c (skip_trampoline_code): New function.
+ * srec.c: Renamed dsrec.c to avoid filename collision.
+ * Makefile.in: Cope with renaming.
+
+Wed Jan 3 13:09:04 1996 Fred Fish <fnf@cygnus.com>
+
+ * symmisc.c (print_objfile_statistics): Print memory use statistics
+ for objfile psymbol, symbol, and type obstacks.
+
+Tue Jan 2 13:41:14 1996 Stan Shebs <shebs@andros.cygnus.com>
+
+ * config/mips/nm-irix5.h: Restore.
+ (TARGET_HAS_HARDWARE_WATCHPOINTS, etc): Define as for Irix 4;
+ from Lee Iverson <leei@ai.sri.com>.
+ * config/mips/irix5.mh (NAT_FILE): Use nm-irix5.h.
+ * config/mips/irix[345].mh (MUNCH_DEFINE): Remove.
+
+For older changes see ChangeLog-95
+
+Local Variables:
+mode: change-log
+left-margin: 8
+fill-column: 74
+version-control: never
+End:
diff --git a/gdb/ChangeLog-97 b/gdb/ChangeLog-97
new file mode 100644
index 00000000000..4f9a949c048
--- /dev/null
+++ b/gdb/ChangeLog-97
@@ -0,0 +1,2855 @@
+Wed Dec 31 11:43:53 1997 Mark Alexander <marka@cygnus.com>
+
+ * dsrec.c (load_srec): Check remotedebug flag when printing
+ debug info.
+
+Wed Dec 31 10:33:15 1997 David Taylor <taylor@texas.cygnus.com>
+
+ * breakpoint.c (breakpoint_re_set): add _siglongjmp to list of
+ longjmp breakpoints.
+
+Mon Dec 29 21:25:34 1997 Mark Alexander <marka@cygnus.com>
+
+ * dve3900-rom.c: New file to support Densan DVE-R3900/20 board.
+ * monitor.c (monitor_debug): Move to utils.c, rename to puts_debug.
+ (monitor_write_memory, monitor_read_memory, monitor_insert_breakpoint,
+ monitor_remove_breakpoint): Remove useless address bits if current
+ monitor has MO_ADDR_BITS_REMOVE flag.
+ * monitor.h (MO_ADDR_BITS_REMOVE): Define.
+ * utils.c (puts_debug): Formerly monitor_debug from monitor.c;
+ move here and make public. Add better support for carriage returns.
+ * defs.h (puts_debug): Declare.
+ * dsrec.c (load_srec): Use puts_debug to print remotedebug information.
+ Output header record correctly.
+ (make_srec): Output a header record instead of a termination record
+ if sect is non-NULL (value is ignored), but abfd is NULL.
+ * config/mips/tm-tx39.h (DEFAULT_MIPS_TYPE): Remove definition.
+ (REGISTER_NAMES): Define to add R3900-specific registers.
+ * config/mips/tm-tx39l.h: Ditto.
+ * config/mips/tx39.mt (TDEPFILES): Add dve3900-rom.o and support files.
+ * config/mips/tx39l.mt: Ditto.
+
+Wed Dec 24 12:48:48 1997 Stan Shebs <shebs@andros.cygnus.com>
+
+ * dsrec.c: Cosmetic improvements.
+ (make-srec): Change indexing of format and code tables to
+ remove confusing empty entries.
+
+Mon Dec 22 21:51:53 1997 Mark Alexander <marka@cygnus.com>
+
+ * remote-mips.c (_initialize_remote_mips): Fix DDB doc string.
+
+Sun Dec 21 17:00:06 1997 David Taylor <taylor@texas.cygnus.com>
+
+ * d30v-tdep.c (d30v_frame_find_saved_regs): split most of
+ function off into d30v_frame_find_saved_regs_offsets;
+ (d30v_frame_find_saved_regs_offsets): new function. Got
+ backtrace working when calling from framefull (unoptimized)
+ routines (.e.g, main) into frameless (optimized) routines
+ (e.g., printf).
+
+Fri Dec 19 09:49:49 1997 David Taylor <taylor@texas.cygnus.com>
+
+ * d30v-tdep.c (d30v_frame_chain): test end_of_stack
+ (d30v_frame_find_saved_regs): set it.
+ * config/d30v/tm-d30v.h: improved FRAME_CHAIN_VALID
+
+Thu Dec 18 12:34:28 1997 Andrew Cagney <cagney@b1.cygnus.com>
+
+ From Gavin Koch <gavin@cygnus.com>: mips-tdep.c
+ * (mips_push_arguments): For big-endian shorts and char's store at
+ * the correct location.
+
+Thu Dec 18 00:26:46 1997 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * mdebugread.c (parse_partial_symbols): Delete check that symbols
+ for file not already loaded. Did not work when an include file
+ was involved.
+
+Wed Dec 17 10:43:04 1997 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * elfread.c (elf_symfile_read): Since the partial symbol table is
+ searched last in first, insert mdebug or XCOFF info into the
+ partial symbol table before any DWARF2 info.
+
+Thu Dec 18 00:00:48 1997 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * symfile.c (init_psymbol_list): Handle init with zero elements.
+
+ * elfread.c (elf_symfile_read): If `mainline', clear psymbol table
+ using init_psymbol_list 0. For build_psymtabs functions, pass
+ mainline==0 so that psymbol_list isn't re-initialized.
+
+ * symfile.c (discard_psymtab): New function, correctly unlink an
+ empty psymtab from an object file.
+ * dbxread.c (end_psymtab): Call discard_psymtab.
+ * xcoffread.c (xcoff_end_psymtab): Ditto.
+ * hpread.c (hpread_end_psymtab): Ditto.
+ * os9kread.c (os9k_end_psymtab): Ditto.
+
+Wed Dec 17 10:47:05 1997 Michael Snyder (msnyder@cleaver.cygnus.com)
+
+ * tracepoint.c (set_raw_tracepoint): initialize addr_string
+ to NULL; (trace_actions_command): call readline_begin_hook only
+ if from_tty is true.
+
+Tue Dec 16 20:05:48 1997 Mark Alexander <marka@cygnus.com>
+
+ * configure.tgt: Change little-endian tx39 target name to tx39l.
+
+Tue Dec 16 11:24:30 1997 Jeffrey A Law (law@cygnus.com)
+
+ * remote-sim.c (gdbsim_open): Use "--architecture" instead of
+ ambigious short form.
+
+Tue Dec 16 10:29:16 1997 David Taylor <taylor@texas.cygnus.com>
+
+ * d30v-tdep.c (d30v_frame_chain): don't or in DMEM_START to
+ FP_REGNUM value before return; (prologue_find_regs): two sets
+ of offsets -- frame pointer and stack pointer, not just one that
+ tries to do double duty; (d30v_frame_find_saved_regs): stop once
+ we hit pc (in case we're stopped in the middle of the prologue)
+ and improve handling of frameless prologues; (d30v_push_arguments):
+ *ALL* arguments go on the stack until we run out of args registers,
+ force sp to be 8 byte aligned.
+
+ * config/tm-d30v.h (EXTRACT_STRUCT_VALUE_ADDRESS): fix, it's r2,
+ not r0; (FRAME_CHAIN_VALID): handle use of external memory;
+ (STACK_ALIGN): define.
+
+Mon Dec 15 15:13:57 1997 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * remote-sim.c (gdbsim_wait): When HAVE_SIGACTION and SA_RESTART
+ intall cntrl-c handler with SA_RESTART clear. On BSD systems this
+ stops read syscalls's being restarted.
+
+ * configure.in (configdirs): Check for sigaction.
+ * configure: Re-generate.
+
+Mon Dec 15 11:38:52 1997 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * dwarf2read.c: From change proposed by Gavin Koch.
+ (address_significant_size): New static variable.
+ (dwarf2_build_psymtabs_hard): Check consistency between
+ `address_size' and `address_significant_size'.
+ (read_address): MASK out all but the significant bits, as
+ determined by `address_significant_size', of any addresses.
+ (elf-bfd.h): Include.
+ (dwarf2_build_psymtabs_hard): Set `address_significant_size'
+ according to the arch_size of the elf object file.
+
+Thu Dec 11 13:40:46 1997 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * dwarf2read.c (dwarf_decode_lines): Change type of address to
+ CORE_ADDR.
+
+Thu Dec 11 14:28:01 1997 Michael Snyder (msnyder@cleaver.cygnus.com)
+
+ * tracepoint.c (trace_find_command): don't error if going
+ backwards thru the trace buffer in a loop.
+ * (struct tracepoint): delete unused field.
+
+Wed Dec 10 17:57:00 1997 David Taylor <taylor@texas.cygnus.com>
+
+ * d30v-tdep.c : don't bury lots of magic numbers in the code
+ instead use defines for the opcodes and opcode masks; update
+ to use actual d30v patterns; fix register sizes to be 4 bytes
+ not 2 bytes; improve prologue testing now that we have a C
+ compiler; fix stack frame handling enough to get backtraces
+ working; initial changes to push and pop frames (so that gdb
+ can call functions in the inferior).
+
+ * config/d30v/tm-d30v.h: update DMEM_START, IMEM_START, and
+ STACK_START; change FR_REGNUM to 61 (was 11). Reformat comment
+ about DUMMY FRAMES so that it is readable. Fix SAVED_PC_AFTER_FRAME
+ macro.
+
+Wed Dec 10 17:41:07 1997 Jim Blandy <jimb@zwingli.cygnus.com>
+
+ * ch-valprint.c (chill_val_print): To avoid segfaults, don't print
+ a string whose dynamic length is longer than its static length.
+
+Wed Dec 10 15:54:00 1997 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * dwarf2read.c (dwarf2_build_psymtabs_hard): Check
+ cu_header.length is within dwarf_info_buffer not
+ dwarf_abbrev_buffer.
+
+Mon Dec 8 14:28:49 1997 Michael Snyder (msnyder@cleaver.cygnus.com)
+
+ * tracepoint.c (memrange_sortmerge): allow for memranges
+ that overlap. (collect_pseudocommand etc.) cleanup decls.
+
+Fri Dec 5 09:22:35 1997 Nick Clifton <nickc@cygnus.com>
+
+ * config/v850/tm-v850.h (BREAKPOINT): Reverted back to old value...
+
+Thu Dec 4 09:30:22 1997 Nick Clifton <nickc@cygnus.com>
+
+ * config/v850/tm-v850.h (BREAKPOINT): Changed to match new value.
+
+Wed Dec 3 12:44:15 1997 Keith Seitz <keiths@onions.cygnus.com>
+
+ * tracepoint.c: Add declaration for x_command.
+
+ * printcmd.c (x_command): Remove static declaration.
+
+Wed Dec 3 12:00:42 1997 Michael Snyder (msnyder@cleaver.cygnus.com)
+
+ * tracepoint.c (finish_tfind_command): call do_display so that
+ auto-displays are updated by tfind. Also, keep track of frame
+ and current-function so that tfind behaves like stepping (only
+ show the stack frame if we step into a new function or return).
+
+Wed Dec 3 14:14:58 1997 David Taylor <taylor@texas.cygnus.com>
+
+ * sol-thread.c: additional support for debugging threaded core
+ files on solaris; previously only kernel threads were found --
+ user threads generated errors.
+ * corelow.c: don't register core_ops as a target if
+ coreops_suppress_target is true (set by sol-thread.c).
+
+Tue Dec 2 14:53:09 1997 Michael Snyder (msnyder@cleaver.cygnus.com)
+
+ * tracepoint.c: make "tdump" command handle literal memranges.
+
+Tue Dec 2 11:34:48 1997 Michael Snyder (msnyder@cleaver.cygnus.com)
+
+ * tracepoint.c: use "lookup_cmd" to parse actions commands
+ (thus allowing unambiguous prefixes and aliases).
+
+Tue Dec 2 10:15:57 1997 Nick Clifton <nickc@cygnus.com>
+
+ * configure.tgt: Add support for Thumb target.
+
+Tue Dec 2 10:14:15 1997 Michael Snyder (msnyder@cleaver.cygnus.com)
+
+ * tracepoint.c: move prototype of validate_actionline(), and
+ make it consistent with the function declaration.
+
+Thu Nov 27 09:07:18 1997 Michael Meissner <meissner@cygnus.com>
+
+ * Makefile.in (tracepoint_h): New macro for tracepoint.h
+ includes.
+ (tracepoint.o): Add rule to build.
+
+Wed Nov 26 22:59:04 1997 Jeffrey A Law (law@cygnus.com)
+
+ * remote-sim.c (gdbsim_cntrl_c): Lose ANSI prototype.
+
+ * tracepoint.c (set_raw_tracepoint): fix typo
+
+Wed Nov 26 11:33:09 1997 Keith Seitz <keiths@onions.cygnus.com>
+
+ * tracepoint.c (set_raw_tracepoint): Make sure there's a trailing
+ slash on the directory name.
+
+ * top.c (get_prompt): New function.
+ * top.h: Declare it.
+
+Wed Nov 26 09:59:47 1997 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * dwarf2read.c (struct comp_unit_head): Change length and
+ abbrev_offset fields to unsigned int.
+ (dwarf2_build_psymtabs_hard): Verify length and offset read from
+ .debug_info section.
+
+Mon Nov 24 19:36:34 1997 Michael Snyder (msnyder@cleaver.cygnus.com)
+
+ * tracepoint.c, tracepoint.h: new module, implements tracing,
+ which is a new functionality somewhat like breakpoints except
+ that a tracepoint stops the inferior only long enough to collect
+ and cache selected buffers and memory locations, then allows
+ the inferior to continue; the cached trace data can then be
+ examined later.
+
+Mon Nov 24 14:17:02 1997 Michael Snyder (msnyder@cleaver.cygnus.com)
+
+ * infcmd.c: export registers_info, for use by other modules.
+ * printcmd.c: export output_command, for use by other modules.
+ * stack.c: export locals_info and args_info, for use by other modules.
+ * remote.c: export getpkt, putpkt, and fromhex for external use.
+ Make fromhex case-insensative. New function "remote_console_output"
+ abstracts the acceptance of "O" packets from target.
+ Make all "remotedebug" output go to stdout, not stderr.
+
+Mon Nov 24 08:59:28 1997 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * valprint.c (print_longest): When CC has long long but printf
+ doesn't, print decimal value as three parts.
+
+ * config/i386/tm-fbsd.h: New file.
+ * config/i386/fbsd.mt (TM_FILE): Change to tm-fbsd.h.
+
+ * config/i386/nm-fbsd.h (FLOAT_INFO): Move definition from here.
+ * config/i386/tm-fbsd.h (FLOAT_INFO): To here.
+
+ * configure.in (PRINTF_HAS_LONG_LONG): Check full functionality of
+ %ll format specifier.
+ (SCANF_HAS_LONG_DOUBLE): Check the scanf family for support of
+ long double using %Lg.
+ * acconfig.h: Provide default undef for SCANF_HAS_LONG_DOUBLE.
+ * configure: Re-generate.
+
+ * c-exp.y (parse_number): Use sscanf %Lg when host has
+ SCANF_HAS_LONG_DOUBLE not PRINTF_HAS_LONG_DOUBLE
+
+Sun Nov 23 17:12:58 1997 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * printcmd.c (print_insn): Set the machine type if known.
+
+ * i386-tdep.c (_initialize_i386_tdep): Delete "set
+ assembly-language" command. Replaced by generic "set
+ architecture". Set initial machine using bfd_lookup_arch.
+
+Fri Nov 21 19:43:23 1997 Jim Blandy <jimb@zwingli.cygnus.com>
+
+ * valops.c (call_function_by_hand): If the function has a
+ prototype, convert its arguments as if by assignment. Otherwise,
+ do the usual promotions.
+ * stabsread.c (define_symbol): Set the TYPE_FLAG_PROTOTYPED flag
+ on functions' types when we can; all C++ functions should get it,
+ and if the Sun-style prototype notation is in the stabs, we can
+ notice that.
+
+Fri Nov 21 12:20:16 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * aclocal.m4 (AM_CYGWIN32, AM_EXEEXT): Remove. They are already
+ defined by the inclusion of ../bfd/aclocal.m4.
+ * configure: Rebuild.
+
+Fri Nov 21 10:52:39 1997 Michael Meissner <meissner@cygnus.com>
+
+ * Makefile.in (SHELL): Really do the change.
+
+Fri Nov 21 02:19:57 1997 Geoffrey Noer <noer@cygnus.com>
+
+ * Makefile.in: also revert SHELL change until configury
+ changes work
+
+Thu Nov 20 16:35:13 1997 Doug Evans <devans@canuck.cygnus.com>
+
+ * sparc-tdep.c (sparc_pc_adjust): Don't assume sizeof (long) == 4.
+
+Thu Nov 20 04:11:27 1997 Geoffrey Noer <noer@cygnus.com>
+
+ * aclocal.m4: add EXEEXT setting rule
+ * configure.in: call it
+ * configure: regenerate
+ * Makefile.in: pepper with EXEEXTs in appropriate places,
+ set SHELL = @SHELL@ for those lame hosts that don't have a /bin/sh
+ For some reason, EXEEXT isn't getting substututed in correctly
+ so for now, set EXEEXT to empty string
+
+Mon Nov 17 15:35:06 1997 Doug Evans <devans@canuck.cygnus.com>
+
+ * Makefile.in (remote-sim.o): Depend on $(INCLUDE_DIR)/callback.h.
+
+Fri Nov 14 13:04:34 1997 Jeffrey A Law (law@cygnus.com)
+
+ * jv-exp.y (copy_exp, insert_exp): Avoid ANSI prototypes.
+
+Thu Nov 13 09:47:35 1997 Michael Meissner <meissner@cygnus.com>
+
+ * d30v-tdep.c (d30v_print_flags): Function to print the d30v flags
+ in a human readable format.
+ (print_flags_command): Command wrapper to call d30v_print_flags.
+ (d30v_do_registers_info): When printing out all of the registers,
+ print out the flag values in a human readable fashion.
+ (_initialize_d30v_tdep): Add info flags command to print the
+ flags.
+
+ * config/d30v/tm-d30v.h (PSW_*): Add macros for each of the PSW
+ bits that are defined.
+
+Wed Nov 12 14:58:39 1997 Jeff Holcomb <jeffh@cygnus.com>
+
+ * symfile.c (generic_load): Handle cancel from the
+ ui_load_progress_hook routine.
+ * dsrec.c (load_srec): Handle cancel from the
+ ui_load_progress_hook routine.
+
+Mon Nov 10 15:13:13 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * valprint.c (print_longest): The b, h, w, and g format specifiers
+ print unsigned values.
+
+Mon Nov 10 02:02:49 1997 Martin M. Hunt <hunt@cygnus.com>
+
+ * top.c (quit_confirm): Change exit message.
+
+Tue Nov 4 16:52:50 1997 Geoffrey Noer <noer@cygnus.com>
+
+ * config/i386/cygwin32.mh: because cygwin.dll calls malloc/realloc
+ to allocate memory for environ space, gdb cannot use memory
+ checks -- set -DNO_MMCHECK
+
+Tue Nov 4 13:50:59 1997 Jim Blandy <jimb@sendai.cygnus.com>
+
+ * jv-exp.y (ArrayAccess): Implement Name [ Expression ]; check the
+ code to see why this is not trivial.
+ (copy_exp, insert_exp): New functions.
+
+Fri Oct 24 17:24:00 1997 Dawn Perchik <dawn@cygnus.com>
+
+ * dwarf2read.c (dwarf2_build_psymtabs_hard): Handle the case
+ where a compilation unit die has no children (DW_TAG_compile_unit
+ has DW_children_no).
+ (scan_partial_symbols): Add comment for nesting_level.
+
+Wed Oct 29 15:53:24 1997 David Taylor <taylor@texas.cygnus.com>
+
+ * solib.c (solib_break_names): add entry for Solaris 2.6 run
+ time linker. From Casper Dik via Peter Schauer.
+
+Tue Oct 28 17:31:47 1997 Martin M. Hunt <hunt@cygnus.com>
+
+ * configure.in (configdir): Add -lcomdlg32 and -ladvapi32
+ to WIN32LIBS.
+
+ * configure: Rebuild
+
+Fri Oct 24 16:48:21 1997 David Taylor <taylor@texas.cygnus.com>
+
+ * sol-thread.c (sol_find_new_threads_callback,
+ sol_find_new_threads): New functions.
+ * config/sparc/nm-sun4sol2.h (FIND_NEW_THREADS): New macro, invoke
+ sol_find_new_threads.
+ * thread.c (info_threads_command): invoke FIND_NEW_THREADS if it
+ is defined.
+
+Thu Oct 23 16:16:04 1997 Jeff Law (law@fast.cs.utah.edu)
+
+ * dbxread.c (process_one_symbol): Put back initialization
+ of a variable lost during last change. Don't perform
+ assignment inside conditionals.
+ * stabsread.c (symbol_reference_defined): Return -1 for error/not
+ found. All callers changed appropriately.
+ (define_symbol): Don't perform assignment inside conditionals.
+
+Wed Oct 22 13:04:52 1997 Jeffrey A Law (law@cygnus.com)
+
+ * mdebugread.c (psymtab_to_symtab_1): Handle new live range stabs
+ entries.
+
+ * dbxread.c: More comment cleanups.
+ * stabsread.c: Fix various violations of the GNU coding and
+ formatting standards. Update/add comments to make code clearer.
+ (resolve_reference): Delete unused function.
+ (ref_search_val): Remove function. It didn't belong in stabsread.c
+ (resolve_live_range): No longer returns a value. Do not add it
+ to the live range list until the entire range stab has been parsed.
+ (get_substring): Remove duplicate declaration.
+ (resolve_symbol_reference): Now static. Remove unnecessary code
+ to deal with cleanups.
+ (ref_add): Use xrealloc instea of realloc.
+ (process_reference): Reorganize slightly to make clearer.
+ * stabsread.h (resolve_symbol_reference): Remove declaration.
+ (resolve_reference): Likewise.
+ * symtab.c (find_active_alias): New function.
+ (lookup_block_symbol): Use find_active_alias.
+ * symtab.h (struct range_list): Fix dangling struct live_range
+ reference.
+ (ref_search_val): Remove decl.
+
+ * symtab.h (struct range_list): Renamed from struct live_range.
+ (struct symbol): Remove struct live_range_info substruct.
+ Bring the alias list and range list fields up to the toplevel
+ as "aliases" and "ranges".
+ (SYMBOL_ALIASES, SYMBOL_RANGES): Corresponding changes.
+ (SYMBOL_RANGE_START, SYMBOL_RANGE_END, SYMBOL_RANGE_NEXT): Delete.
+ * stabsread.c: Corresponding changes.
+
+ * dbxread.c: Fix various violations of the GNU coding and
+ formatting standards. Update/add comments to make code
+ clearer.
+ (process_later): Use xrealloc instead of realloc.
+
+ * symtab.c: Include inferior.h.
+
+Tue Oct 21 14:15:26 1997 Per Bothner <bothner@cygnus.com>
+
+ * ch-exp.c: Rename FIELD_NAME to DOT_FIELD_NAME (to avoid conflict).
+
+Fri Oct 17 13:22:02 1997 Stan Shebs <shebs@andros.cygnus.com>
+
+ * infcmd.c: Improve grammar of "set args" help.
+
+Thu Oct 16 15:03:58 1997 Michael Meissner <meissner@cygnus.com>
+
+ * remote-sds.c (sds_load): Properly declare as static.
+
+Wed Oct 15 10:27:14 1997 Doug Evans <dje@canuck.cygnus.com>
+
+ * config/sparc/tm-sparc.h (FIX_CALL_DUMMY): Mask off displacement
+ to 30 bits in call insn to handle --enable-64-bit-bfd.
+ (STORE_STRUCT_RETURN): Change to handle --enable-64-bit-bfd.
+
+Tue Oct 14 22:13:27 1997 Dawn Perchik <dawn@cygnus.com>
+
+ * stabsread.c: Make ref_map entries dynamically allocated.
+
+Thu Oct 9 12:37:57 1997 Frank Ch. Eigler <fche@cygnus.com>
+
+ * printcmd.c (print_address_symbolic, address_info): Mask
+ target-specific flag bits from PC, for more aesthetic disassembly.
+ * config/mips/tm-mips.h: Added PC masking for MIPS family
+ (especially the MIPS16).
+
+Sat Oct 4 18:45:44 1997 Mark Alexander <marka@cygnus.com>
+
+ * remote-mips.c (mips-initialize): Work around flakiness in
+ some versions of PMON after loading a program.
+
+Fri Oct 3 15:49:18 1997 Per Bothner <bothner@cygnus.com>
+
+ * c-lang.h, cp-valprint.c (static_field_print): Make non-static.
+ * parse.c, parser-defs.h (length_of_subexp): Make non-static.
+ * jv-exp.y (FieldAccess): Handle dollar-VARIABLE as primary.
+ (ArrayAccess): Likewise. Also remove warnings.
+ (CastExpression): Implement (typename) UnaryExpression.
+ (push_qualified_expression_name): Fix small bug.
+ * jv-lang.c: Use TYPE_TAG_NAME, not TYPE_NAME for class names.
+ (_initialize_jave_language): Fix typo (jave -> java).
+ (java_language): Java does *not* have C-style arrays.
+ (java_class_from_object): Make more general (and complicated).
+ (java_link_class_type): Fix typo "super" -> "class". Handle arrays.
+ (java_emit_char, java_printchar): New function.
+ (evaluate_subexp_java case BINOP_SUBSCRIPT): Handle Java arrays.
+ * jv-valprint.c (java_value_print): Implement printing of Java arrays.
+ (java_print_value_fields): New function.
+ (java_val_print): Better printing of TYPE_CODE_CHAR, TYPE_CODE_STRUCT.
+
+Fri Oct 3 09:52:26 1997 Mark Alexander <marka@cygnus.com>
+
+ * config/mips/tm-mips.h (MAKE_MSYMBOL_SPECIAL): Force MIPS16
+ addresses to be odd.
+ (MIPS_FPU_SINGLE_REGSIZE, MIPS_FPU_DOUBLE_REGSIZE): Define.
+ * mips-tdep.c (mips_extract_return_value): Doubles aren't
+ returned in FP0 if FP registers are single-precision only.
+
+Mon Sep 29 23:03:03 1997 Mark Alexander <marka@cygnus.com>
+
+ * mips-tdep.c (set_reg_offset): New function.
+ (mips16_heuristic_proc_desc): Calculate offsets of registers
+ saved by entry pseudo-op after rest of prologue has been read.
+ Use set_reg_offset to ignore all but the first save of a given
+ register.
+ (mips32_heuristic_proc_desc): Initialize frame adjustment value.
+ * remote-sim.c (gdbsim_store_register): Don't update registers
+ that have a null or empty name.
+ * findvar.c (read_register_bytes): Don't fetch registers
+ that have a null or empty name.
+
+Tue Sep 30 13:35:54 1997 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * config/mips/tm-mips.h (NUM_REGS): Define conditionally.
+ (REGISTER_NAMES): Ditto.
+
+Fri Sep 26 21:08:22 1997 Keith Seitz <keiths@pizza.cygnus.com>
+
+ * dsrec.c (load_srec): add ui_load_progress_hook to
+ display some feedback to user
+
+ * symfile.c (generic_load): add ui_load_progress_hook to
+ display some feedback to user
+
+Fri Sep 26 17:32:22 1997 Jason Molenda (crash@pern.cygnus.com)
+
+ * command.c (add_cmd, add_show_from_set): Insert new commands in
+ alphabetical order.
+
+Fri Sep 26 12:22:00 1997 Mark Alexander <marka@cygnus.com>
+
+ * config/mips-tm-mips.h (mips_extra_func_info): New frame_adjust
+ member for storing offset of MIPS16 frame pointer from SP.
+ * mips-tdep.c: Use RA_REGNUM instead of hardcoded 31 throughout.
+ (PROC_FRAME_ADJUST): Define.
+ (mips16_heuristic_proc_desc): Store frame pointer adjustment value.
+ (get_frame_pointer): Use frame pointer adjustment value when
+ calculating frame address.
+ * remote-sim.c (gdbsim_fetch_register): Don't fetch registers
+ that have a null or empty name.
+
+Fri Sep 26 12:40:51 1997 Jeffrey A Law (law@cygnus.com)
+
+ * mips-tdep.c (_initialize_mips_tdep): Allow target files to
+ override default FPU type.
+
+Fri Sep 26 10:33:54 1997 Felix Lee <flee@cygnus.com>
+
+ * configure.tgt (v850-*-*): necmsg.lib instead of v850.lib.
+
+Wed Sep 24 14:02:09 1997 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * config/v850/tm-v850.h (BREAKPOINT): Use 1 word DIVH insn with
+ RRRRR=0 for simulator breakpoint. Previous breakpoint insn was two
+ words.
+
+Thu Sep 18 15:07:46 1997 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * ser-e7kpc.c (get_ds_base): Only use under Windows.
+ (windows.h): Include when any _WIN32 host.
+
+Wed Sep 24 18:12:47 1997 Stu Grossman <grossman@babylon-5.cygnus.com>
+
+ * The following block of changes add support for debugging assembly
+ source files.
+ * breakpoint.c (resolve_sal_pc): Prevent crash when pc isn't
+ associated with a function.
+ * buildsym.c (record_line start_symtab end_symtab): Don't delete
+ symtabs which only have line numbers (but no other debug symbols).
+ * dbxread.c (read_dbx_symtab end_psymtab): Ditto.
+
+ * remote-sim.c: New functions gdbsim_insert/remove_breakpoint. Use
+ intrinsic simulator breakpoints if available, otherwise do it the
+ hard way.
+
+ * configure.tgt: Add d30v.
+ * d30v-tdep.c: New file.
+ * config/d30v/d30v.mt, config/d30v/tm-d30v.h: New files.
+
+Tue Sep 23 11:24:13 1997 Stan Shebs <shebs@andros.cygnus.com>
+
+ * Makefile.in (ALLCONFIG): Remove, inaccurate and never used.
+
+Tue Sep 23 00:08:18 1997 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * mips-tdep.c (mips_push_arguments): Tweak alignment of register
+ value if the remaining length of a non-integral argument is smaller
+ than the register size for big-endian non-EABI mode.
+
+ * rs6000-tdep.c (branch_dest): Handle return from signal
+ handler function via sigreturn kernel call.
+
+Mon Sep 22 15:32:06 1997 Dawn Perchik <dawn@cygnus.com>
+
+ * stabsread.h, symtab.h, dbxread.c, symtab.c, stabsread.c:
+ Fix prototypes. Remove function scoped function declarations.
+
+Fri Sep 19 18:51:26 1997 Felix Lee <flee@cygnus.com>
+
+ * config/i386/windows.mh (XDEPFILES): need to list some files
+ explicitly, for odd reasons.
+
+Tue Sep 16 20:00:05 1997 Per Bothner <bothner@cygnus.com>
+
+ * jv-exp.y (push_fieldnames): New, to handle EXP.FIELD1....FIELDN.
+ (push_expression_name): New, to handle expression names.
+ (push_qualified_expression_name): New, for qualified expression names.
+ (parse_number): Fix bugs in parsing of non-decimal integers.
+ * jv-lang.h, jv-lang.c (java_demangle_type_signature): New.
+ * jv-lang.c (type_from_class): Just use name with java_lookup_class.
+ (java_link_class_type): Add dummy "class" field.
+ (java_lookup_type): New.
+ (evaluate_subexp_java case STRUCTOP_STRUCT): Force to address.
+ * jv-typeprint.c (java_type_print_base): Don't print "class" field.
+ Use java_demangle_type_signature to print array class types.
+ * jv-valprint.c (java_value_print): Preliminary array support.
+ Print pointer as TYPE@HEXADDR, instead of (TYPE)0xHEXADDR.
+ (java_val_print): Move check for object type to java_value_print.
+ Check for null. Print pointer as @HEXADDR, not 0xHEXADDR.
+
+ * valops.c (search_struct_field): Search basesclasses in
+ ascending, not descending order. Hack to avoid virtual baseclass
+ botch for Java interfaces.
+
+Tue Sep 16 19:56:23 1997 Per Bothner <bothner@cygnus.com>
+
+ * util.c (run_cleanup_chain, make_run_cleanup, do_run_cleanups):
+ New cleanup clean for cleanups to be run when at each 'run' command.
+ * infcmd.c (run_command): Call do_run_cleanups.
+
+ * solib.c (find_solib): Register cleanup to call clear_solib
+ on a new 'run' command.
+ (symbol_add_stub): First look for existing objfile with same name.
+
+Tue Sep 16 16:00:01 1997 Stan Shebs <shebs@andros.cygnus.com>
+
+ * remote-sds.c (sds_load): New function.
+ (sds_ops): Use it.
+ (sds_open): Don't set inferior_pid yet.
+ (sds_kill): Remove contents.
+ (sds_create_inferior): Rewrite to work more like monitor
+ interfaces.
+ (sds_restart): Remove, no longer used.
+
+ * monitor.h (MO_SREC_ACK_PLUS, MO_SREC_ACK_ROTATE): New flags.
+ * monitor.c (monitor_wait_srec_ack): Add DINK32-specific ack code.
+ * dsrec.c (load_srec): Always write a header S-record.
+ * dink32-rom.c (dink32_regnames): Fix the names of float registers.
+ (dink32_cmds): Set to use S-record downloading with acks.
+ * remote-est.c (est_cmds): Add MO_SREC_ACK_PLUS flag.
+
+Tue Sep 16 10:08:27 1997 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * config/v850/tm-v850.h (BREAKPOINT): Set to a truely illegal
+ instruction.
+
+ * exec.c (exec_file_command): Call set_architecture_from_file.
+
+Mon Sep 15 13:01:22 1997 Mark Alexander <marka@cygnus.com>
+
+ * dbxread.c (MSYMBOL_SIZE): New macro.
+ (end_psymtab): Use MSYMBOL_SIZE to extract size from minimal symbol.
+ * elfread.c (elf_symtab_read): If ELF symbol is "special",
+ such as a MIPS16 function, mark minimal symbol as special too.
+ * mips-tdep.c (pc_is_mips16): New function to check whether
+ a function is MIPS16 by looking at the minimal symbol. Use
+ pc_is_mips16 throughout instead of IS_MIPS16_ADDR macro.
+ * config/mips/tm-mips.h (SYMBOL_IS_SPECIAL, MAKE_MSYMBOL_SPECIAL,
+ MSYMBOL_IS_SPECIAL, MSYMBOL_SIZE): New functions for setting/testing
+ "special" MIPS16 bit in ELF and minimal symbols.
+ * mdebugread.c (parse_partial_symbols): Don't construct a partial
+ symbol table for a file that already has one.
+
+Sat Sep 13 08:32:13 1997 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * mdebugread.c (parse_symbol, handle_psymbol_enumerators): Handle
+ yet another variant of enumerator debugging info, used by DU 4.0
+ native cc.
+
+Tue Sep 9 20:47:23 1997 Felix Lee <flee@cygnus.com>
+
+ * config/i386/windows.mh (XDEPFILES): reduce to libwingdb.a.
+ otherwise link command line is too long.
+
+Tue Sep 9 17:41:41 1997 Jeffrey A Law (law@cygnus.com)
+
+ * symtab.c, dbxread.c, stabsread.c: Fix up ANSI-C isms. Fix
+ some formatting problems.
+
+Mon Sep 8 16:45:51 1997 Stu Grossman <grossman@cygnus.com>
+
+ * ser-e7kpc.c: Don't include w32sut.h. We no longer use the UT
+ mechanism. Remove prototypes for dos_async_* functions. They don't
+ exist anymore.
+
+Mon Sep 8 12:48:50 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * top.c (quit_confirm, quit_force): New functions, broken out of
+ quit_command.
+ (quit_command): Just call quit_confirm and quit_force.
+ * top.h (quit_confirm, quit_force): Declare.
+
+Sun Sep 7 17:26:30 1997 Dawn Perchik <dawn@cygnus.com>
+
+ * dbxread.c, buildsym.c, symtab.c, stabsread.c: Add support for
+ reading stabs extensions for live range information.
+ * stabsread.h, partial-stab.h: Add prototypes for new functions.
+ * symtab.h: Add structure for storing live range information.
+
+Wed Sep 3 16:39:39 1997 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * top.c (set_arch): New function, update target_architecture.
+
+ * defs.h, top.c (set_architecture_from_arch_mach): Replace
+ set_architecture, takes the arch and machine as arguments.
+
+ * sh3-rom.c (sh3e_open): Update.
+ (sh3_open): Ditto.
+
+Tue Sep 2 12:00:46 1997 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * remote-e7000.c (e7000_fetch_registers): Fix typo, stray paren.
+ (e7000_wait): Ditto.
+
+Mon Sep 1 11:21:03 1997 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * top.c (init_main): Add ``set processor'' as an alias for ``set
+ architecture''.
+
+Sat Aug 30 13:44:48 1997 Bob Manson <manson@charmed.cygnus.com>
+
+ * config/sparc/sparclite.mt: Removed simulator references (erc32
+ has been disabled).
+
+Thu Aug 28 10:20:04 1997 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * remote-e7000.c (e7000_fetch_registers): Check
+ target_architecture instead of sh_processor_type.
+ (e7000_wait): Ditto.
+
+ * config/sh/tm-sh.h (sh_set_processor_type): Delete prototype.
+
+ * sh3-rom.c (sh3_open): Call set_architecture not
+ sh_set_processor_type.
+ (sh3e_open): Ditto.
+
+ * sh-tdep.c (sh_show_processor_type_command): Delete.
+ (sh_set_processor_type_command): Delete.
+ (sh_target_architecture_hook): Rename from sh_set_processor_type,
+ use AP to determine architecture.
+ (sh_show_regs): Use bfd_mach_sh* types.
+
+ * remote-sim.c (gdbsim_open): Pass --arch=XXX to simulator when
+ architecture was specified explicitly.
+
+ * defs.h (target_architecture, target_architecture_auto,
+ set_architecture, set_architecture_from_file): Declare.
+ (target_architecture_hook): Allow targets to be notified of set
+ arch commands.
+
+ * top.c (init_main): Add set/show/info architecture commands.
+ (set_architecture, show_architecture, info_architecture): New
+ functions, parse same.
+ (set_architecture_from_file): New function, determine arch from
+ BFD.
+
+Tue Aug 26 17:13:43 1997 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * remote-sim.c (gdbsim_open): Only pass endianness to sim_open
+ when set explicitly. Prepend endianness arg so that it can be
+ overridden.
+
+ * defs.h, top.c (target_byte_order_auto): Make global when
+ byteorder is selectable.
+
+Tue Aug 26 15:19:56 1997 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * remote-sim.c (gdbsim_create_inferior): Pass exec_bfd into
+ sim_create_inferior.
+ (gdbsim_create_inferior): Pass -1 to proceed, sim_create_inferior
+ has already set the PC.
+ (gdbsim_create_inferior): Allow exec_file to be NULL, make "No
+ exec file" a warning. Ditto for "No program loaded".
+
+Mon Aug 25 17:08:01 1997 Geoffrey Noer <noer@cygnus.com>
+
+ * ocd.c: revert Sun change -- enable log file handling
+
+Mon Aug 25 12:21:46 1997 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * remote-sim.c (gdbsim_open): Pass exec_bfd to sim_open call.
+
+Sun Aug 24 21:16:59 1997 Geoffrey Noer <noer@cygnus.com>
+
+ * ocd.c: comment out sections that create and flush wigglers.log
+ log file when using the wiggler.
+
+Thu Aug 21 16:18:08 1997 Geoffrey Noer <noer@cygnus.com>
+
+ * config/powerpc/ppc-eabi.mt:
+ * config/powerpc/ppc-sim.mt:
+ * config/powerpc/ppcle-eabi.mt:
+ * config/powerpc/ppcle-sim.mt: ser-ocd.c needs to be before
+ other ocd-related files in TDEPFILES
+
+Thu Aug 21 14:56:04 1997 Geoffrey Noer <noer@cygnus.com>
+
+ * ppc-bdm.c (bdm_ppc_wait): stop printfing ecr, der
+ * ocd.c: initialize remote_timeout
+ (ocd_wait): while looping, call ocd_do_command with OCD_AYT
+ (ocd_get_packet): remove find_packet goto. If there isn't
+ an 0x55 at the start, something is quite wrong so error out
+ instead of advancing in the packet and trying again. If checksum
+ is invalid, print error message instead of trying again.
+ * ser-ocd.c (ocd_readchar): error if we attempt to read past
+ the end of the from_wiggler_buffer.
+
+
+Wed Aug 20 14:08:39 1997 Stan Shebs <shebs@andros.cygnus.com>
+
+ * dink32-rom.c: Don't use "mf" command to fill, is too picky
+ about alignment.
+
+
+Tue Aug 19 08:41:36 1997 Fred Fish <fnf@cygnus.com>
+
+ * objfiles.c (objfile_relocate): Add call to breakpoint_re_set
+ after relocations are complete.
+ * remote-vx.c (vx_add_symbols): Remove call to breakpoint_re_set,
+ this is now done in objfile_relocate.
+
+Mon Aug 18 17:29:54 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * win32-nat.c (handle_exception): Return a value indicating
+ whether the exception was handled. Don't handle random exceptions
+ the first time around, so that structured exception handling
+ works.
+ (child_wait): Check the return value of handle_exception. Set the
+ continue_status argument to ContinueDebugEvent accordingly.
+
+Mon Aug 18 11:14:15 1997 Nick Clifton <nickc@cygnus.com>
+
+ * configure.tgt: Add support for v850ea target.
+
+Sun Aug 17 20:31:57 1997 Michael Snyder (msnyder@cleaver.cygnus.com)
+
+ * m32r-stub.c: fix typo
+
+Sun Aug 17 17:33:34 1997 Stan Shebs <shebs@andros.cygnus.com>
+
+ * remote-sds.c: Remove unused remnants of remote.c.
+ (tob64): Return the result length.
+ (sds_interrupt): Send a stop message.
+ (sds_wait): Add debug output for signal interpretation, flag
+ that signal was due to a trap.
+ (sds_fetch_registers): Fill the registers array correctly for
+ PowerPC.
+ (sds_store_registers): Get the right values from registers array.
+ (putmessage): Tweak length handling so checksum comes out right.
+ (sds_insert_breakpoint, sds_remove_breakpoint): Do correctly.
+
+Fri Aug 15 20:53:13 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * Makefile.in (init.c): Don't use xargs.
+
+Fri Aug 15 13:59:37 1997 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * infrun.c (wait_for_inferior): Add the symbols for any
+ newly loaded objects upon a TARGET_WAITKIND_LOADED event.
+
+ Rewrite code which determines the TOC address for calling functions
+ in the inferior under AIX.
+ * rs6000-nat.c (find_toc_address): New function to determine
+ the required TOC address from a function address.
+ (_initialize_core_rs6000): Set up find_toc_address_hook to point
+ to find_toc_address.
+ (xcoff_relocate_symtab, xcoff_relocate_core): Remove
+ add_text_to_loadinfo calls.
+ (exec_one_dummy_insn): Change pid and status to int to get rid of
+ compiler warnings.
+ (xcoff_relocate_symtab): Cast ldi to `int *' when passing it to
+ ptrace to get rid of compiler warnings.
+ * rs6000-tdep.c: Add definition for find_toc_address_hook.
+ (rs6000_fix_call_dummy): If find_toc_address_hook is non zero,
+ patch TOC address load code in the call dummy with the value
+ returned from find_toc_address_hook.
+ (struct loadinfo, loadinfo, loadinfolen,
+ loadinfotextindex, xcoff_init_loadinfo, free_loadinfo,
+ xcoff_add_toc_to_loadinfo, add_text_to_loadinfo, find_toc_address):
+ Remove.
+ (_initialize_rs6000_tdep): Remove initialization of
+ coff_add_toc_to_loadinfo_hook and xcoff_init_loadinfo_hook.
+ * xcoffread.c (coff_add_toc_to_loadinfo_hook,
+ xcoff_init_loadinfo_hook): Remove.
+ (struct coff_symfile_info): Add toc_offset field.
+ (scan_xcoff_symtab): Record toc_offset value in toc_offset field
+ instead of calling xcoff_add_toc_to_loadinfo_hook.
+ (get_toc_offset): New function to return the value of the
+ toc_offset field for an object file.
+ (xcoff_initial_scan): Remove call of xcoff_init_loadinfo_hook.
+ * xcoffsolib.h (add_text_to_loadinfo): Remove declaration.
+ * config/rs6000/tm-rs6000.h: Add declarations for
+ find_toc_address_hook and get_toc_offset.
+
+Wed Aug 13 19:31:28 1997 Stan Shebs <shebs@andros.cygnus.com>
+
+ * remote-sds.c: New file, interface to SDS-compatible monitors.
+ * Makefile.in (remote-sds.o): Add build rule.
+ * config/powerpc/ppc-eabi.mt, config/powerpc/ppc-sim.mt
+ (TDEPFILES): Add remote-sds.o.
+
+Tue Aug 12 14:37:18 1997 Geoffrey Noer <noer@cygnus.com>
+
+ * ocd.c (ocd_wait): loop until we're in BDM mode instead of
+ assuming control has returned to GDB.
+
+Mon Aug 11 19:16:04 1997 Stan Shebs <shebs@andros.cygnus.com>
+
+ * dink32-rom.c: New file, support for DINK32 monitor.
+ * Makefile.in (dink32-rom.o): Add build rule.
+ * config/powerpc/ppc-eabi.mt, config/powerpc/ppc-sim.mt
+ (TDEPFILES): Add dink32-rom.o.
+ * monitor.h (MO_32_REGS_PAIRED, MO_SETREG_INTERACTIVE,
+ MO_SETMEM_INTERACTIVE, MO_GETMEM_16_BOUNDARY,
+ MO_CLR_BREAK_1_BASED): New monitor interface flags.
+ * monitor.c: Use them.
+ (monitor_store_register): Use setreg.term if defined.
+ (monitor_insert_breakpoint, monitor_remove_breakpoint): Notice
+ if set_break and clr_break fields are empty.
+
+Mon Aug 11 16:22:36 1997 Geoffrey Noer <noer@cygnus.com>
+
+ * ocd.c (ocd_insert_breakpoint, ocd_remove_breakpoint): Macro
+ BDM_BREAKPOINT already has braces around it, remove erroneous ones.
+ * ser-ocd.c (ocd_write): Conditionalize on _WIN32 instead of
+ __CYGWIN32__.
+ * config/powerpc/tm-ppc-eabi.h: Remove BDM_NUM_REGS, BDM_REGMAP
+ * ppc-bdm.c: move BDM_NUM_REGS, BDM_REGMAP here from tm.h file,
+ fill in doc fields of bdm_ppc_ops.
+ (bdm_ppc_fetch_registers): Don't ask for invalid registers such
+ as the MQ or floating point regs not present on ppc 8xx boards.
+ (bdm_ppc_store_registers): Don't write those same invalid registers.
+ * config/i386/cygwin32.mh: Stop including ocd.o ser-ocd.o.
+ * config/powerpc/ppc-eabi.mt:
+ * config/powerpc/ppcle-eabi.mt:
+ * config/powerpc/ppc-sim.mt:
+ * config/powerpc/ppcle-sim.mt: Include ser-ocd.o.
+
+Mon Aug 11 16:08:52 1997 Fred Fish <fnf@cygnus.com>
+
+ * frame.h (enum lval_type): Conditionalize on __GNUC__
+ instead of __STDC__.
+
+Sun Aug 10 19:08:26 1997 Jeffrey A Law (law@cygnus.com)
+
+ * utils.c (error): Fix return type for !ANSI_PROTOTYPES.
+
+Sun Aug 10 16:49:09 1997 Geoffrey Noer <noer@cygnus.com>
+
+ * ocd.c: move ocd_write_bytes proto to ocd.h since it is used
+ by ppc-bdm.c, use OCD_LOG_FILE to help debugging, define
+ BDM_BREAKPOINT if not defined in tm.h
+ (ocd_error): add new error cases
+ (ocd_start_remote): send the OCD_INIT command before
+ OCD_AYT and OCD_GET_VERSION calls, 80 was correct speed after all
+ (ocd_write_bytes): no longer static
+ (ocd_insert_breakpoint): no longer static
+ (ocd_remove_breakpoint): new
+ * ocd.h: add protos for ocd_write_bytes, ocd_insert_breakpoint,
+ and ocd_remove_breakpoint
+ * ppc-bdm.c: change bdm_ppc_ops so we call ocd_insert_breakpoint
+ and ocd_remove_breakpoint instead of memory_insert_breakpoint
+ and memory_remove_breakpoint.
+ (bdm_ppc_open): after calling ocd_open, modify DER
+ register so interrupts will drop us into debugging mode, finally
+ disable the watchdog timer on the board so we don't leave BDM
+ mode unexpectedly.
+
+Sat Aug 9 01:50:14 1997 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * values.c (value_primitive_field): Account for offset when
+ extracting the value of a bitfield.
+ From Paul Hilfinger <hilfingr@CS.Berkeley.EDU>.
+
+Fri Aug 8 21:35:44 1997 Mark Alexander <marka@cygnus.com>
+
+ * gdbserver/utils.c (error): Change prototype to match defs.h.
+ * gdbserver/low-sim.c: Change simulator calls to use new interface.
+ * remote.c (remote_write_bytes): Include '$' at start of packet
+ and checksum at end of packet in overhead calculation.
+
+Fri Aug 8 15:59:24 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * ser-ocd.c: If _WIN32, include <windows.h>.
+ (dll_do_command): New static variable if _WIN32.
+ (ocd_open): Set dll_do_command if _WIN32.
+ (ocd_write): Use dll_do_command rather than do_command.
+ * config/i386/cygwin32.mh (XDEPFILES): Remove libwigglers.a.
+ (BDM_DLLNAME, BDM_LIBNAME, BDM_DEFFILE): Don't define.
+ ($(BDM_LIBNAME)): Remove target.
+ * wigglers.def: Remove.
+
+ * config/i386/cygwin32.mh ($(BDM_LIBNAME)): Rename target from
+ libwigglers.def.
+ (libwigglers.a): Remove target.
+
+Fri Aug 8 13:11:01 1997 Mike Meissner <meissner@cygnus.com>
+
+ * config/powerpc/ppc{,le}-{eabi,sim}.mt (TDEPFILES): Make sure
+ ppc-bdm.o and ocd.o are used for all powerpc-eabi targets.
+
+Thu Aug 7 19:40:52 1997 Geoffrey Noer <noer@cygnus.com>
+
+ Changes to OCD support to support wiggler box as well as
+ target boxes:
+ * ocd.c: change speed in init command to 0 from 80,
+ add (temporary) logging commands to help debugging,
+ (ocd_open): if "target ocd wiggler lpt" then use special
+ ser-ocd.c serial interface which communicates with Wigglers.dll,
+ otherwise ("target ocd <foo>") do as we did before
+ (ocd_get_packet): add OCD_LOG_FILE and OCD_SET_CONNECTION to
+ switch of known commands of len 0
+ * ocd.h: add OCD_LOG_FILE
+ * serial.c (serial_open): do serial_interface_lookup on ocd
+ in the case of ocd
+ * ser-ocd.c: add buffer to contain responses from sending a
+ command to the Wigglers.dll.
+ (ocd_readchar): return curr char from buffer and increment ptr
+ (ocd_write): send buffer to Wigglers.dll, storing response in
+ return buffer and initializing curr location ptr to start of
+ buffer.
+
+Thu Aug 7 13:39:31 1997 Geoffrey Noer <noer@cygnus.com>
+
+ * ocd.h: add OCD_SET_CONNECTION
+ * ocd.c: rename "do_command" to "ocd_do_command"
+
+Thu Aug 7 13:09:17 1997 Geoffrey Noer <noer@cygnus.com>
+
+ Nomenclature change. BDM is a specific type of OCD
+ (On Chip Debugging). Wiggler is the parallel port box controlled
+ by Wigglers.dll. The faster target box from Macraigor Systems
+ is not a wiggler.
+ * ocd.c:
+ * ocd.h:
+ * ppc-bdm.c:
+ * ser-ocd.c:
+ Replace all instances of "wiggler_" with "ocd_" and change most other
+ instances of "wiggler" to "ocd" or "ocd device" depending on context.
+ * config/m68k/monitor.mt: remove remote-wiggler.o from TDEPFILES
+ until OCD with that target is supported again.
+
+Wed Aug 6 16:15:31 1997 Geoffrey Noer <noer@cygnus.com>
+
+ * Makefile.in: add DLLTOOL = @DLLTOOL@, pass on DLLTOOL to
+ sub makes, change clean rule to also remove *.a to remove
+ libwigglers.a, in dependencies: add ppc-bdm.o ocd.o ser-ocd.o and
+ remove remote-wiggler.o
+ * configure.in: add DLLTOOL support
+ * configure: regenerate
+ * wigglers.def: new file for imports for wigglers.dll
+ * ser-ocd.c: new file which is layer between ocd.c and either the
+ wigglers.dll or the target box, only stub so far
+ * config/powerpc/ppc-eabi.mt: add ppc-bdm.o to TDEPFILES
+ * config/powerpc/ppc-sim.mt: add ppc-bdm.o to TDEPFILES
+ * config/i386/cygwin32.mh: add ocd.o ser-ocd.o libwigglers.a
+ to XDEPFILES, add rules to build libwigglers.a
+
+ checking in changes of Stu Grossman <grossman@cygnus.com>:
+ * remote-wiggler.c: delete
+ * ocd.c: new, was remote-wiggler.c
+ always include sys/types.h, include ocd.h, move WIGGLER
+ commands and many wiggler prototypes to ocd.h, make wiggler_desc
+ static, stop making local wiggler functions static,
+ define write_mem_command for wiggler_write_bytes
+ (wiggler_start_remote): stop hardcoding the target type,
+ instead set and use a target_type variable.
+ (wiggler_open): add new target_type and ops args
+ (wiggler_wait): now no longer takes pid and target_status as args,
+ stop trying to set target_status struct, remove BGND insn
+ checks
+ (read_bdm_registers): renamed to wiggler_read_bdm_registers
+ (wiggler_read_bdm_registers): numregs arg changed to reglen arg,
+ remove pktlen check, set reglen instead of numregs
+ (dump_all_bdm_regs): delete
+ (wiggler_fetch_registers): delete
+ (wiggler_prepare_to_store): now just an empty function
+ (wiggler_store_registers): delete
+ (wiggler_read_bdm_register): new
+ (wiggler_write_bdm_registers): new
+ (wiggler_write_bdm_register): new
+ (wiggler_write_bytes): use write_mem_command variable instead of
+ WIGGLER_WRITE_MEM
+ (get_packet): renamed to wiggler_get_packet, change refs throughout
+ (put_packet): renamed to wiggler_put_packet, change refs throughout
+ (wiggler_get_packet): add break to default case of switch,
+ change length of WIGGLER_GET_VERSION len to 10 from 4 to match
+ specs
+ (wiggler_mourn): unpush_target with current_ops, not &wiggler_ops
+ (flash_xfer_memory): delete
+ (noop_store_registers): new placeholder replacement for
+ target_store_registers() which prevents generic_load from trying to
+ set up the PC.
+ (bdm_update_flash_command): add store_registers_tmp variable,
+ make handling of wiggler_ops more generic -- define wiggler_ops
+ in a target-specific file instead (such as ppc-bdm.c in the case
+ of the ppc), use current_target to deal with registers again
+ making this file less target-specific.
+ (bdm_read_register_command): new
+ (_initialize_remote_wiggler): stop doing add_target (&wiggler_ops),
+ comment out add_cmd ("read-register", ...)
+ * ocd.h: new, contains common wiggler prototypes, command definitions
+ * ppc-bdm.c: file for ppc-specific OCD code, including target_ops
+ structure for ppc bdm
+ (bdm_ppc_open): new
+ (bdm_ppc_wait): new
+ (bdm_ppc_fetch_registers): new
+ (bdm_ppc_store_registers_: new
+ (_initialize_bdm_ppc): new
+ * config/powerpc/tm-ppc-eabi.h: add necessary CPU32 BDM defines
+
+Wed Aug 6 00:24:08 1997 Jeffrey A Law (law@cygnus.com)
+
+ * hpread.c (hpread_read_struct_type): Use accessor macros rather
+ than directly mucking around with data structures.
+
+Tue Aug 5 13:37:14 1997 Per Bothner <bothner@cygnus.com>
+
+ * gdbtypes.h: Re-interpret struct field. Suppport address of static.
+ Add a bunch of macros.
+ * coffread.c, dwarf2read.c, dwarfread.c, mdebugread.c, stabsread.c:
+ Update to use new macros.
+ * coffread.c, hpread.c, stabsread.c: Remove bugus TYPE_FIELD_VALUE.
+ * value.h, values.c (value_static_field): New function.
+ * cp-valprint.c, valops.c: Modify to use value_static_field.
+
+ * jv-lang.c (get_java_utf8_name): Re-write so it works with
+ implied (missing) data field, as defined by cc1java.
+ (java_link_class_type): Type length and field offset (in interior)
+ now includes object header. Get static fields working.
+ * jv-lang.h (JAVA_OBJECT_SIZE): Update for change in Kaffe.
+ * jv-typeprint.c (java_type_print_derivation_info,
+ java_type_print_base): New functions, for better Java output.
+ * jv-valprint.c: Start to support Java-specific output.
+
+Sun Aug 3 08:18:09 1997 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * c-valprint.c (c_val_print): Use extract_address to retrieve
+ the address of the virtual function.
+ From Peter Bloecher (Peter.Bloecher@eedn.ericsson.se).
+
+ * eval.c (evaluate_subexp_standard), valarith.c (value_x_unop):
+ Handle C++ operator *.
+
+Fri Aug 1 15:21:44 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * configure.in: Check for cygwin32 environment. Define and
+ substitute WIN32LIBS and WIN32LDAPP. Always set configdir to
+ unix; setting it to win was for an old Tcl/Tk configuration
+ scheme.
+ * Makefile.in (TK_CFLAGS): Add @TK_BUILD_INCLUDES@.
+ (WIN32LDAPP, WIN32LIBS): Define.
+ (CLIBS): Add $(WIN32LIBS).
+ (gdb): Use $(WIN32LDAPP).
+ * configure: Rebuild.
+
+Thu Jul 31 15:40:19 1997 Per Bothner <bothner@cygnus.com>
+
+ * symtab.h (SYMBOL_INIT_LANGUAGE_SPECIFIC, SYMBOL_INIT_DEMANGLED_NAME,
+ SYMBOL_DEMANGLED_NAME): Add demangling support for Java.
+ * utils.c (fprintf_symbol_filtered): Handle language_java.
+
+ * symtab.c (decode_line_1): Handle Java-style package.class.method.
+
+Wed Jul 30 14:04:18 1997 Per Bothner <bothner@cygnus.com>
+
+ * java-*: Renamed to jv-*, to make fit within 14 characters.
+ * jv-lang.h (java_type_print): Added declaration.
+ * jv-typeprint.c: New file. Provides java_print_type.
+ * jv-lang.c (java_link_class_type): New function.
+ (java_language_defn): Replace c_print_type by java_print_type.
+ * Makefile.in: Update accordingly.
+
+Tue Jul 29 10:12:44 1997 Felix Lee <flee@cygnus.com>
+
+ * Makefile.in (init.c): except some mswin files do need to be
+ scanned. oh well.
+
+Mon Jul 28 14:04:39 1997 Felix Lee <flee@cygnus.com>
+
+ * Makefile.in (init.c): don't try to scan mswin for _initialize
+ funcs. (generates misleading error message because files have
+ .cpp suffix, not .c suffix)
+
+Mon Jul 28 13:27:21 1997 Felix Lee <flee@cygnus.com>
+
+ * ser-e7kpc.c: <w32sut.h> -> "mswin/w32sut.h"
+
+Mon Jul 28 02:54:31 1997 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * xcoffread.c (coff_getfilename): Do not strip directory component
+ of filename.
+
+Fri Jul 25 15:16:15 1997 Felix Lee <flee@cygnus.com>
+
+ * mon960-rom.c: removed unused #includes; no ioctl.h in Windows.
+ * nindy-share/ttyflush.c: find sleep() for _MSC_VER.
+ * remote-array.c: #include <ctype.h> for isascii().
+ * utils.c (notice_quit,pollquit): cleanup. _WIN32 -> _MSC_VER.
+
+Fri Jul 25 16:48:18 1997 Jeffrey A Law (law@cygnus.com)
+
+ * top.c (execute_command): Force cleanup of alloca areas.
+ * findvar.c (registers_changed): Likewise.
+
+Fri Jul 25 15:37:15 1997 Stu Grossman <grossman@cygnus.com>
+
+ * v850ice.c: Include <windows.h>. Support new v850 DLL interface.
+ * Add defs for target status.
+
+Tue Jul 22 12:11:48 1997 Michael Snyder (msnyder@cleaver.cygnus.com)
+
+ * config/mips/tm-mips64.h: longs, long longs, and pointers
+ are all 64 bits on EABI mips targets.
+
+Thu Jul 17 11:38:46 1997 Michael Snyder (msnyder@cleaver.cygnus.com)
+
+ * partial-stab.h (case N_BINCL): detect missing partial symtab.
+ * dbxread.c: Add a complaint for N_BINCL without a corresponding
+ partial symtab. Remove earlier change of 5/27/97.
+
+Wed Jul 16 10:38:03 1997 Michael Snyder (msnyder@cleaver.cygnus.com)
+
+ * sol-thread.c (sol_thread_[store, fetch]_registers): if
+ inferior_pid is an LWP rather than a Solaris thread, let
+ procfs handle the request.
+ (rw_common, sol_thread_xfer_memory): procfs_xfer_memory will
+ only work if inferior_pid points to an LWP (rather than a
+ Solaris thread). Use procfs_first_available to find a good LWP.
+ (info_solthreads): added a maintenance command to list all
+ known Solaris threads and their attributes.
+ * mips-tdep.c (mips_do_registers_info): Completely changed the
+ output format to be neat and columnar. Added the helper funcs
+ do_fp_register_row and do_gp_register_row. Also small mods to
+ mips_print_register, which is still used to print a single reg.
+
+Mon Jul 14 18:02:53 1997 Michael Snyder (msnyder@cleaver.cygnus.com)
+
+ * procfs.c (wait_fd): Handle an fd that has "hung up" or
+ otherwise terminated (Solaris threads).
+
+Thu Jul 10 00:02:41 1997 Martin M. Hunt <hunt@cygnus.com>
+
+ * defs.h (init_ui_hook): Change prototype to accept one arg.
+ * main.c (gdb_init): Change prototype to accept one arg.
+ * top.c (gdb_init): Accepts one argument which it uses to
+ call (*init_ui_hook).
+
+Fri Jul 4 14:49:33 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * source.c (OPEN_MODE, FDOPEN_MODE): Define; value depends upon
+ whether CRLF_SOURCE_FILES is defined.
+ (open_source_file): Use OPEN_MODE with open and openp.
+ (print_source_lines): Use FDOPEN_MODE with fdopen. If
+ CRLF_SOURCE_FILES is defined, ignore \r characters.
+ (forward_search_command): Use FDOPEN_MODE with fdopen.
+ (reverse_search_command): Likewise.
+ * config/i386/xm-cygwin32.h (CRLF_SOURCE_FILES): Define.
+ (LSEEK_NOT_LINEAR): Don't define.
+
+Thu Jul 3 17:41:46 1997 Michael Snyder (msnyder@cleaver.cygnus.com)
+
+ * mips-tdep.c (mips_extract_return_value): align 4-byte float
+ return values within the 8-byte FP register.
+
+Thu Jul 3 13:48:11 1997 Michael Snyder (msnyder@cleaver.cygnus.com)
+
+ * mips-tdep.c (mips_push_arguments): don't left-adjust 32-bit
+ integers in 64-bit register parameters before function calls.
+
+Mon Jun 30 17:54:51 1997 Michael Snyder (msnyder@cleaver.cygnus.com)
+
+ * mips-tdep.c (mips_push_arguments): special-case handling for
+ odd-sized struct parameters passed in registers / on stack.
+
+Mon Jun 30 15:30:38 1997 Michael Snyder (msnyder@cleaver.cygnus.com)
+
+ * mips-tdep.c (mips_push_arguments): tweak alignment of small
+ structs passed in registers for little-endian non-EABI mode.
+
+Mon Jun 30 13:05:39 1997 Michael Snyder (msnyder@cleaver.cygnus.com)
+
+ * breakpoint.c (frame_in_dummy): use generic dummy if available.
+ (check_duplicates, clear_command): compare sections only if
+ doing overlay debugging.
+
+Fri Jun 27 23:03:53 1997 Fred Fish <fnf@ninemoons.com>
+
+ * buildsym.h (struct subfile): Add debugformat member.
+ (record_debugformat): Declare global function.
+ * buildsym.c (start_subfile): Initialize debugformat member
+ to NULL.
+ (record_debugformat): New function to record the format.
+ (end_symtab): Copy format into symtab debugformat member.
+ (end_symtab): Free subfile debugformat member.
+ * symmisc.c (free_symtab): Free debugformat when freeing
+ symtab.
+ * symfile.c (allocate_symtab): Initialize the new debugformat
+ member for new symtabs.
+ * symtab.h (struct symtab): Add debugformat member.
+ * source.c (source_info): Print the debug format.
+
+ * os9kread.c (os9k_process_one_symbol): Call record_debugformat
+ with "OS9".
+ * hpread.c (hpread_expand_symtab): Call record_debugformat
+ with "HP".
+ (hpread_process_one_debug_symbol): Ditto.
+ * dbxread.c (process_one_symbol): Call record_debugformat
+ with "stabs".
+ * coffread.c (coff_start_symtab): Call record_debugformat
+ with "COFF".
+ * xcoffread.c (read_xcoff_symtab): Call record_debugformat
+ with "XCOFF".
+ * dwarfread.c (read_file_scope): Call record_debugformat
+ with "DWARF 1".
+ * dwarf2read.c (read_file_scope): Call record_debugformat
+ with "DWARF 2".
+ * dstread.c (dst_end_symtab): Set debugformat to be
+ "Apollo DST".
+ * mdebugread.c (new_symtab): Set debugformat to be "ECOFF".
+
+Fri Jun 27 21:05:45 1997 Michael Snyder (msnyder@cleaver.cygnus.com)
+
+ * mips-tdep.c (mips_push_arguments): handle alignment of
+ integer and struct args on stack for mips64 big-endian.
+
+Fri Jun 27 19:19:12 1997 Michael Snyder (msnyder@cleaver.cygnus.com)
+
+ * config/mips/tm-mips.h (USE_STRUCT_CONVENTION): MIPS_EABI returns
+ structs in a register wherever possible.
+ * mips-tdep.c (mips_extract_return_value): handle structs.
+ (mips_store_return_value): handle values smaller than MIPS_REGSIZE
+ (including structs, if gdb ever allows it).
+
+Fri Jun 20 17:58:34 1997 Fred Fish <fnf@cygnus.com>
+
+ * sh-tdep.c (sh_skip_prologue): Also recognize fmov insns.
+ (sh_frame_find_saved_regs): Recognize fmov insns and adjust
+ stack push count accordingly.
+ * sh-tdep.c (IS_FMOV, FPSCR_SZ): New defines
+
+Thu Jun 19 08:18:48 1997 Mark Alexander <marka@cygnus.com>
+
+ * utils.c (floatformat_from_doublest): Improve test for infinity.
+
+Wed Jun 18 13:47:52 1997 Fred Fish <fnf@cygnus.com>
+
+ * dwarfread.c (isreg, optimized_out, offreg, basereg): Move
+ global variables into the struct dieinfo structure.
+ (locval): Pass pointer to a dieinfo struct rather than a
+ pointer to the raw location information. Change prototype.
+ Set isreg, optimized_out, offreg and basereg as appropriate.
+ (struct_type): Call locval with dieinfo struct pointer.
+ (new_symbol): Ditto.
+ (new_symbol): Call locval and save location before testing
+ the values of the new dieinfo struct flags, set by locval.
+
+Tue Jun 17 13:30:12 1997 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * procfs.c (proc_set_exec_trap, procfs_init_inferior, procfs_wait,
+ unconditionally_kill_inferior): Undo Oct 26 1996 and Apr 26 1997
+ changes to trace PRFS_STOPTERM and handle PR_DEAD.
+ These changes tried to work around a problem with an early DU 4.0
+ release, but they trigger subtle timing dependent kernel bugs
+ in older OSF/1 releases.
+
+Tue Jun 17 06:52:47 1997 Fred Fish <fnf@cygnus.com>
+
+ * dwarfread.c (new_symbol): Use SYMBOL_VALUE_ADDRESS, instead of
+ SYMBOL_VALUE, to set the value of LOC_STATIC symbols.
+
+Mon Jun 16 18:38:28 1997 Mark Alexander <marka@cygnus.com>
+
+ * infrun.c (wait_for_inferior): Mark registers as invalid when
+ stepping over an instruction that triggered a watchpoint.
+ * remote-mips.c: Numerous changes to support hardware breakpoints
+ and watchpoints on LSI MiniRISC and TinyRISC boards.
+ * mips-tdep.c: Move MIPS16-related macros to config/mips/tm-mips.h.
+ (mips_breakpoint_from_pc): Account for different breakpoint
+ instructions used by PMON and IDT monitor.
+ * config/mips/tm-embed.h: Enable hardware breakpoints on embedded
+ MIPS targets.
+ * config/mips/tm-mips.h: Define breakpoint instructions for
+ PMON and IDT monitor. Move MIPS16-related macros here from
+ mips-tdep.c.
+
+Fri Jun 13 13:44:47 1997 Michael Snyder (msnyder@cleaver.cygnus.com)
+
+ * config/mips/tm-tx39[l].h, tx39[l].mt: change r3900 target to tx39.
+
+Fri Jun 13 14:14:10 1997 Jeffrey A Law (law@cygnus.com)
+
+ * mn10300-tdep.c (mn10300_analyze_prologue): Fix some comments.
+ Add missing return statements after finding an "add imm{16,32},sp"
+ instruction.
+ (mn10300_frame_chain): Add in size of our register save area to find
+ our caller's frame if our caller does not have a frame pointer.
+
+Fri Jun 13 12:55:49 1997 Doug Evans <dje@canuck.cygnus.com>
+
+ * symfile.c (generic_load): Check return code of target_write_memory.
+
+Fri Jun 13 10:28:09 1997 Fred Fish <fnf@cygnus.com>
+
+ * config/i386/nm-linux.h: Enable prototypes that were #ifdef out.
+ * config/tm-sysv4.h (in_plt_section): Add prototype.
+
+ * maint.c (maintenance_translate_address): Avoid assignment
+ inside if, per GNU coding standards.
+ * symfile.c (simple_read_overlay_table): Avoid assignments inside if,
+ per GNU coding standards.
+
+ * monitor.c (parse_register_dump): Is really a void function.
+ Add prototype.
+ (monitor_read_memory): Remove unused variable "name".
+ (monitor_read_memory): Remove unused variable "regbuf".
+ (monitor_open): Remove unused variable "i".
+ (get_hex_word): Apparently unused, #if away for now.
+ (from_hex): Ditto.
+
+ * i386v4-nat.c (supply_fpregset): Remove unused variable "regi".
+ (fill_fpregset): Remove unused variables "regi", "to", "from" and
+ "registers".
+
+ * remote-e7000.c (ctype.h): Include.
+ (e7000_insert_breakpoint): #if away unused arg used by unused expr.
+ * frame.h (generic_get_saved_register): Add prototype.
+ (enum lval_type): Add partial forward decl.
+ * dsrec.c (make_srec): Remove unused variable "type_code".
+ * remote-sim.c (gdbsim_wait): Handle sim_running and sim_polling
+ cases by just ignoring them.
+ (command.h): Include.
+
+ * java-exp.y (parse_number): Remove unused variable "unsigned_p".
+ * java-lang.c (gdbcore.h): Include for prototypes.
+ (type_from_class): Remove unused variable "ftype".
+ (type_from_class): Remove unused variable "name_length".
+ (evaluate_subexp_java): Add default case to handle remaining
+ enumerations.
+ * java-valprint.c (c-lang.h): Include for prototypes.
+
+ * symfile.c (simple_read_overlay_region_table): #if away
+ unused function.
+ (simple_free_overlay_region_table): Ditto.
+ (overlay_is_mapped): Add default case to switch.
+ (simple_read_overlay_region_table): Ditto.
+ (simple_read_overlay_region_table): Add prototype.
+
+ * symtab.c (fixup_symbol_section): Remove unused msym variable.
+ (fixup_psymbol_section): Ditto.
+ (find_pc_sect_symtab): Make distance a CORE_ADDR.
+
+ * utils.c: Add comment about t_addr being either unsigned long or
+ unsigned long long.
+ (paddr): Change formats to match actual types args are cast to.
+ (preg): Ditto.
+ (paddr_nz): Ditto.
+ (preg_nz): Ditto.
+
+ * defs.h (perror_with_name): Is a NORETURN function.
+ * utils.c (perror_with_name): Is a NORETURN function.
+ (error): Is NORETURN independently of ANSI_PROTOTYPES.
+
+ * symtab.c (fixup_symbol_section): Remove prototype.
+ * symtab.h: (fixup_symbol_section): Add prototype.
+ * m32r-rom.c (report_transfer_performance): Add prototype.
+ * sparclet-rom.c: Ditto.
+ * dsrec.c: Ditto.
+
+ * c-exp.y (parse_number): Cast args to float* or double* as
+ appropriate for conversion format.
+ * java-exp.y (parse_number): Ditto.
+
+ * Makefile.in (c-exp.tab.c): Remove #line lines that refer
+ to nonexistant y.tab.c file.
+ (java-exp.tab.c): Ditto.
+ (f-exp.tab.c): Ditto.
+ (m2-exp.tab.c): Ditto.
+
+ * sh-tdep.c (symfile.h): Include.
+ (gdb_string.h): Include.
+ (sh_fix_call_dummy): Ifdef away, currently unused.
+ * config/sh/tm-sh.h (pop_frame): Add prototype.
+ * config/sh/tm-sh.h (sh_set_processor_type): Add prototype.
+
+Sat Jun 7 02:34:19 1997 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * eval.c (evaluate_subexp_for_sizeof): Handle dereferencing
+ of non-pointer values.
+
+ * symtab.c (gdb_mangle_name): Improve mangling of nested types,
+ their physical names already include the class name.
+
+ * valops.c (value_cast): Handle upcast of a class pointer.
+
+ From Andreas Schwab (schwab@issan.informatik.uni-dortmund.de):
+ * corelow.c (get_core_registers): Make secname big enough.
+
+Fri Jun 6 14:43:23 1997 Keith Seitz <keiths@pizza.cygnus.com>
+
+ * config/sh/tm-sh.h: add define for FPSCR_REGNUM
+ * sh-tdep.c (sh_show_regs): print out all registers for
+ the current processor
+
+Fri Jun 6 13:01:55 1997 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * remote-sim.c (gdbsim_kill): Remove call to depreciated function
+ sim_kill.
+
+Thu Jun 5 11:39:03 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ Fixes for recent correction to PE format:
+ * coffread.c (pe_file): New static variable.
+ (struct find_targ_sec_arg): Change resultp from pointer to int to
+ pointer to pointer to asection.
+ (find_targ_sec): Just store the section in args->resultp, not the
+ section offset value.
+ (cs_to_section): Compute the section offset value from the
+ section.
+ (cs_section_address): New static function.
+ (coff_symfile_read): Set pe_file.
+ (read_one_sym): When reading a PE file, adjust the symbol value to
+ include the section address if the symbol has an appropriate
+ storage class.
+
+Tue Jun 3 16:24:46 1997 Michael Snyder (msnyder@cleaver.cygnus.com)
+
+ * configure.tgt: add mipsr3900-elf target
+ * config/mips/r3900.mt r3900l.mt tm-r3900.h tm-r3900l.h: ditto
+
+Tue May 27 10:34:11 1997 Michael Snyder <msnyder@cleaver.cygnus.com>
+
+ * dbxread.c: Check malloc's return for null, prevent segv.
+
+Fri May 23 14:45:02 1997 Bob Manson <manson@charmed.cygnus.com>
+
+ * infcmd.c (jump_command): Don't try to dereference sfn if it's
+ NULL.
+
+Fri May 23 13:51:57 1997 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * top.c (init_cmd_lists): Always initialize endianlist.
+ (init_main): Always define endian commands.
+ (set_endian_big): Issue warning if endian not selectable.
+ (set_endian_little): Ditto.
+ (set_endian_auto): Ditto.
+
+Thu May 22 11:53:21 1997 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * remote-sim.c (simulator_command): Restrict access to the
+ simulator to periods when the simulator is open.
+
+Wed May 21 16:03:25 1997 Michael Snyder <msnyder@cleaver.cygnus.com>
+
+ * procfs.c (init_procinfo): new function, abstracts some code
+ shared by create_procinfo and do_attach;
+ (procfs_set_inferior_syscall_traps): new function, abstracts
+ some code needed by procfs_init_inferior, do_attach, and
+ procfs_lwp_creation_handler; (procfs_first_available): new
+ function, find any LWP that's runnable; (procfs_thread_alive):
+ replace stub function with real implementation;
+ (procfs_lwp_creation_handler): fix bug starting new child
+ threads; (info_proc): bug fixes and enhancements for the
+ "INFO PROCESSES" command; (close_procinfo_file): call new
+ function "delete_thread" to cleanup GDB's thread database;
+ (proc_init_failed): add new argument "kill", to control whether
+ process is killed (so this function can be shared by
+ create_procinfo and do_attach); (procfs_exit_handler): handle
+ exit from an attached process, and cleanup procinfo handles
+ when the process exits; (procfs_resume, procfs_wait): cleanup
+ after a thread when it exits; (do_attach, do_detach): handle
+ attached processes with multiple threads; plus some general
+ improvements in the diagnostic output.
+ * sol-thread.c (sol_thread_alive): replace stub with real
+ implementation; (thread_to_lwp, lwp_to_thread): enhance to
+ handle threads that may have exited; (sol_thread_attach): add
+ startup setup stuff; (sol_thread_detach): add unpush_target
+ call; (sol_thread_mourn_inferior): add unpush_target call;
+ (sol_thread_wait, sol_thread_resume): enhance to deal with
+ thread exit cleanly; (sol_thread_new_objfile,
+ sol_thread_pid_to_str): detect unsuccessful startup and
+ don't crash; plus some general cleanup.
+ * thread.c (delete_thread): new function, allows targets to
+ notify gdb when a thread is no longer valid.
+ * infrun.c (wait_for_inferior): don't try to detect a new
+ thread on receiving a TARGET_EXITED event.
+
+Tue May 20 09:32:02 1997 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * remote-sim.c (gdbsim_open): Pass callback struct.
+ (init_callbacks): Remove call to sim_set_callbacks.
+
+Thu May 15 07:56:50 1997 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * config/rs6000/tm-rs6000.h (SIG_FRAME_LR_OFFSET): Define.
+ * rs6000-tdep.c (frameless_function_invocation): Mark frames
+ with a zero PC as frameless to improve backtraces from core dumps
+ caused by dereferencing a NULL function pointer.
+ (frameless_function_invocation, frame_saved_pc, rs6000_frame_chain):
+ Handle frameless functions interrupted by a signal.
+
+ * sparc-tdep.c (sparc_init_extra_frame_info, sparc_frame_saved_pc):
+ Handle frameless functions interrupted by a signal.
+
+Wed May 14 08:58:55 1997 Jeffrey A Law (law@cygnus.com)
+
+ * mn10200-tdep.c (mn10200_analyze_prologue): Update prologue comments
+ to reflect current reality. Gross attempt at handling out of
+ line prologues.
+
+ * mn10200-tdep.c (mn10200_skip_prologue): Don't look at the debug
+ symbols to find the end of the prologue.
+ * mn10300-tdep.c (mn10300_skip_prologue): Likewise.
+
+Thu May 8 08:42:47 1997 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * configure.in (AC_TYPE_SIGNAL): Add
+ * configure: Re-generate.
+ * remote-sim.c: Signal returns RETSIGTYPE.
+
+Wed May 7 20:05:07 1997 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * target.h (target_stop): Drop argument so it can be tested for
+ NULL.
+
+Sat May 3 20:51:48 1997 Mark Alexander <marka@cygnus.com>
+
+ * utils.c (floatformat_from_doublest): Handle infinity properly.
+
+Thu May 1 11:44:46 1997 Michael Snyder <msnyder@cleaver.cygnus.com>
+
+ * Finalize merge from Hurd folk.
+ Mon Oct 30 16:41:04 1995 Miles Bader <miles@gnu.ai.mit.edu>
+ * thread.c (thread_apply_command, thread_apply_all_command,
+ thread_command): Make sure TP is alive.
+ (thread_alive): New function.
+ Tue Nov 14 14:31:03 1995 Miles Bader <miles@gnu.ai.mit.edu>
+ * infrun.c (sig_print_info): Deal better with long signal names.
+ Wed Nov 22 15:23:35 1995 Miles Bader <miles@gnu.ai.mit.edu>
+ * thread.c (thread_id_to_pid): New function.
+ Fri Dec 1 13:25:25 1995 Miles Bader <miles@gnu.ai.mit.edu>
+ * gnu-nat.c: (set_thread_cmd_list, show_thread_cmd_list,
+ set_thread_default_cmd_list, show_thread_default_cmd_list):
+ New variables. (set_thread_cmd, show_thread_cmd,
+ set_thread_default_cmd, show_thread_default_cmd): New functions.
+ Fri Apr 18 15:20:16 1997 Miles Bader <miles@gnu.ai.mit.edu>
+ * gnu-nat.c (inf_startup): remove TASK parameter.
+ (inf_set_task): replace with new function (inf_set_pid).
+ * gdbthread.h: Add extern decl for thread_cmd_list.
+
+Thu May 1 02:28:21 1997 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * printcmd.c (disassemble_command): Adjust low function bound
+ by FUNCTION_START_OFFSET.
+
+Mon Apr 28 21:25:32 1997 Michael Snyder <msnyder@cleaver.cygnus.com>
+
+ * Makefile.in: Add rule for gnu-nat.o and i386gnu-nat.o (Gnu Hurd)
+ * config/i386/i386gnu.mh: remove rules for [i386]gnu-nat.o, now
+ in Makefile.in (as for other targets); add NATDEPFILE corelow.o to
+ satisfy symbol dependancy in solib.c (core_ops).
+ * target.[ch] conditionalize Mach-specific signals so that they
+ won't show up in non-Mach gdb's!
+ * thread.c: change name of static function "thread_switch" to
+ "switch_to_thread", to avoid conflict with Mach global symbol;
+ move thread_cmd_list to global scope so targets can add their
+ own thread commands.
+ * infrun.c: sig_print_info: allow for long signal names.
+ * gnu-nat.[ch]: tidying up comments.
+ * gnu-nat.c: remove calls to prune_threads and renumber_threads;
+ gnu_wait must not return -1 when inferior exits;
+ attach_to_child will modify inferior_pid in a way that allows
+ fork_inferior to remain unchanged; remove extra arg from
+ startup_inferior; move Mach thread commands here from thread.c.
+
+Mon Apr 28 18:21:20 1997 Michael Snyder <msnyder@cleaver.cygnus.com>
+
+ * symtab.c: decode_line_1, replace the assignment to
+ values.sals[0].pc which I accidentally left out on 4/3/97.
+
+Mon Apr 28 17:27:40 1997 Michael Snyder <msnyder@cleaver.cygnus.com>
+
+ * c-exp.y: make parse_number reject "123DEADBEEF".
+ (fix by Bob Manson).
+ * java-exp.y: Ditto.
+ * top.c: change "to enable to enable" to "to enable" in a couple
+ of help strings.
+
+Mon Apr 28 09:01:59 1997 Mark Alexander <marka@cygnus.com>
+
+ * breakpoint.c (remove_breakpoint): Pass correct type to
+ target_remove_watchpoint.
+ * target.h: Improve comment for target_{remove,insert}_breakpoint.
+
+Sat Apr 26 03:38:02 1997 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * alpha-tdep.c (heuristic_proc_desc): Increase search limit
+ for return address register, handle `ret' instruction.
+
+ * corelow.c (get_core_registers): Initialize cf.
+
+ * procfs.c: Minor changes to make pre-ANSI compilers happy.
+ (procfs_notice_signals): Copy traced signal set back to
+ pi->prrun.pr_trace.
+ (unconditionally_kill_inferior): If PR_DEAD is defined,
+ rerun inferior after killing it.
+
+Fri Apr 25 00:10:18 1997 Jeffrey A Law (law@cygnus.com)
+
+ * config/mn10300/tm-mn10300.h (EXTRACT_STRUCT_VALUE_ADDRESS): The
+ structure value address is found in $a0 now.
+ * config/mn10200/tm-mn10200.h (EXTRACT_STRUCT_VALUE_ADDRESS): Likewise.
+
+Thu Apr 24 13:31:10 1997 Jeffrey A Law (law@cygnus.com)
+
+ * config/mn10300/tm-mn10300.h (STORE_RETURN_VALUE): Pointers are
+ returned in $a0.
+ (EXTRACT_RETURN_VALUE): Likewise.
+
+ * mn10300-tdep.c (mn10300_analyze_prologue): Check for a return
+ insn at "pc", not "fi->pc".
+
+Wed Apr 23 11:18:45 1997 Jeffrey A Law (law@cygnus.com)
+
+ * config/mn10200/tm-mn10200.h (STORE_RETURN_VALUE): Pointers are
+ returned in $a0.
+ (EXTRACT_RETURN_VALUE): Likewise.
+
+Tue Apr 22 11:58:15 1997 Fred Fish <fnf@cygnus.com>
+
+ * config/arm/tm-arm.h (TARGET_DOUBLE_FORMAT): Define to use
+ floatformat_ieee_double_littlebyte_bigword for little endian
+ target byte order.
+ * utils.c (floatformat_to_doublest): Create local preswapped
+ copy of input for floatformat_littlebyte_bigword formats.
+ (get_field, put_field): Treat floatformat_littlebyte_bigword
+ the same as floatformat_little.
+ (floatformat_from_doublest): Postswap output words for
+ the floatformat_littlebyte_bigwords format.
+
+Tue Apr 22 09:02:10 1997 Stu Grossman (grossman@critters.cygnus.com)
+
+ * config/alpha/alpha-osf3.mh config/i386/{i386gnu linux}.mh
+ config/mips/{embed embed64 embedl embedl64 vr4300 vr4300el vr5000
+ vr5000el}.mt config/powerpc/{aix aix4}.mh config/rs6000/{aix
+ aix4}.mh config/sh/sh.mt config/sparc/sp64sim.mt:
+ config/v850/v850.mt:
+ Remove -lm. That's now handled by configure.
+
+ * Makefile.in (maintainer-clean): Add distclean to dependencies.
+ Remove duplicate rm's of files.
+
+Mon Apr 21 09:49:25 1997 Stu Grossman (grossman@critters.cygnus.com)
+
+ * remote-pa.c: Remove. It's broken and no longer necessary.
+
+ Sat Apr 19 11:56:10 1997 Per Bothner <bothner@deneb.cygnus.com>
+
+ * java-exp.y: Combine TRUE and FALSE into BOOLEAN_LITERAL.
+ (Avoids name clash with broken AIX header files.)
+
+Sat Apr 19 01:49:37 1997 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * serial.c (serial_log_command): Fix fputs_unfiltered calls.
+
+ * config/powerpc/tm-ppc-aix4.h, config/rs6000/tm-rs6000-aix4.h
+ (DONT_RELOCATE_SYMFILE_OBJFILE): Removed.
+ * xcoffsolib.h (struct vmap): Add new members tvma, toffs and dvma,
+ remove tadj.
+ * exec.c (bfdsec_to_vmap): Initialize new vmap members, initialize
+ tstart and dstart with section VMA.
+ * rs6000-nat.c (vmap_symtab): Relocate relative to the VMA in the
+ object file.
+ (vmap_ldinfo, xcoff_relocate_core): Adjust tstart by section offset
+ of the text section, remove DONT_RELOCATE_SYMFILE_OBJFILE hack.
+ (vmap_exec): Relocate relative to the VMA in the object file,
+ relocate .bss section as well.
+ (xcoff_relocate_core): No longer adjust section addresses by VMA.
+ * rs6000-tdep.c (find_toc_address): Change type of tocbase
+ to CORE_ADDR.
+ * xcoffread.c (secnum_to_bfd_section): New routine to get
+ BFD section from CS section number.
+ (scan_xcoff_symtab): Make toc_offset section relative.
+
+ * symtab.c (total_number_of_methods): Avoid core dump if
+ baseclass type is still undefined.
+
+Fri Apr 18 17:25:10 1997 Stu Grossman (grossman@critters.cygnus.com)
+
+ * Makefile.in (SUBDIRS): Add mswin so that make cleanup cleans up
+ that directory.
+ * defs.h utils.c (error warning): Make message be const.
+ * main.c (fputs_unfiltered): Only send gdb_stdout and gdb_stderr
+ to hook. Otherwise send it to fputs.
+ * monitor.c monitor.h (monitor_get_dev_name): New function. Does
+ the obvious.
+ * remote-e7000.c: Remove debugify stuff. Change printf, fprintf
+ to _filtered forms to make output appear in GUIs. Replace all
+ uses of SERIAL_READCHAR with readchar, which has better error
+ checking.
+ * (e7000_parse_device): Add prototype.
+ (readchar): Improve doc. Handle random serial errors.
+ (expect): Disable notice_quit code. It's busted. Remove
+ serial error handling (it's now handled in readchar). Remove
+ remote_debug echoing. That's handled in readchar as well.
+ (e7000_parse_device): Remove serial_flag arg. It's not
+ necessary.
+ (e7000_open): Split into two pieces. Second part is
+ e7000_start_remote, and is error protected. Now, when we connect
+ to the target, we setup the initial frame and registers so that
+ the user gets an immediate indication of where the target is.
+ (gch): Remove debug output. That's handled by readchar.
+ (e7000_read_inferior_memory): Handle errors better.
+ (_initialize_remote_e7000): Get rid of `<xxx>' things from
+ command names. They show up when doing completion and confuse
+ things horribly.
+ * ser-e7kpc.c: Get rid of the DLL's since we can access the device
+ directly from Win32s and Win95. Get rid of debugify crud.
+ * serial.c: Remove debugify cruft.
+ * (serial_logchar serial_log_command serial_write serial_readchar
+ serial_send_break serial_close): Merge common functionality into
+ serial_logchar. Clean up rest of routines.
+ * sparclet-rom.c: Disembowel. Leave only download routine.
+ Download routine now switches to remote target automatically.
+ * top.c (disconnect): Only define if SIGHUP is defined. Cleans
+ up MSVC/Win32 problem.
+ * utils.c (gdb_flush): Don't call hook unless it's for gdb_stdout
+ or gdb_stderr.
+ * config/sh/tm-sh.h: Define TARGET_SH for WinGDB.
+ * config/sparc/tm-sparclet.h: Remove override for prompt.
+
+Fri Apr 18 13:38:19 1997 Doug Evans <dje@canuck.cygnus.com>
+
+ * remote-sim.c (gdbsim_open): Only pass -E to sim_open if
+ TARGET_BYTE ORDER_SELECTABLE.
+
+Fri Apr 18 16:52:41 1997 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * remote-sim.c (init_callbacks): Initialize poll_quit and magic
+ fields of gdb_callback.
+ (gdbsim_stop): Add gdbsim_stop to list of supported client
+ operations.
+ (gdbsim_wait, gdbsim_resume): Move call to sim_resume into
+ sim_wait where gdb is in a position to handle a long running
+ function.
+ (gdbsim_cntrl_c): New function. Wrap the sim_resume call in a
+ SIGINT handler.
+ (gdb_os_poll_quit): New function. Check for a quit pending on the
+ console.
+
+Thu Apr 17 14:30:04 1997 Per Bothner <bothner@deneb.cygnus.com>
+
+ * objfiles.c (allocate_objfile): Allow NULL bfd argument.
+ * defs.h (enum language): Add language_java.
+ * java-exp.y, java-lang.c, java-lang.h, java-valprint.c: New files.
+ * Makefile.in: Update for new files.
+ * symfile.c (deduce_language_from_filename): Recognize .java.
+
+Thu Apr 17 02:20:23 1997 Doug Evans <dje@canuck.cygnus.com>
+
+ * m32r-stub.c (stash_registers): Rewrite.
+ (restore_registers): Renamed to restore_and_return.
+ (cleanup_stash): New function.
+ (process_exception): New function.
+ (_catchException*): Rewrite.
+
+ * remote-sim.c (gdbsim_load): Update call to sim_load.
+ (gdbsim_create_inferior): No longer pass start_address to
+ sim_create_inferior.
+ (gdbsim_open): Pass endian indicator as arg.
+
+Tue Apr 15 15:31:09 1997 Stan Shebs <shebs@andros.cygnus.com>
+
+ * remote.c (get_offsets): Don't use scanf for interpreting
+ response to qOffsets.
+
+Tue Apr 15 14:51:04 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * gdbserver/Makefile.in (INSTALL_XFORM): Remove.
+ (INSTALL_XFORM1): Remove.
+ (install-only): Use $(program_transform_name) directly, rather
+ than using $(INSTALL_XFORM) and $(INSTALL_XFORM1).
+ (uninstall): Transform name.
+
+Mon Apr 14 17:06:27 1997 Mark Alexander <marka@cygnus.com>
+
+ * remote-mips.c (mips_load): Ensure that PC gets updated
+ after a load on LSI target.
+
+Mon Apr 14 15:54:51 1997 Geoffrey Noer <noer@pizza.cygnus.com>
+
+ * procfs.c (notice_signals): fix typo
+
+Mon Apr 14 16:25:10 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * gdbserver/Makefile.in (INSTALL): Change install.sh to
+ install-sh.
+
+Mon Apr 14 11:55:27 1997 Geoffrey Noer <noer@pizza.cygnus.com>
+
+ * config/i386/cygwin32.mh: remove -lkernel32 from XM_CLIBS
+ since gcc automatically includes it
+
+Thu Apr 10 13:20:53 1997 Geoffrey Noer <noer@cygnus.com>
+
+ * procfs.c: Substantial (but incomplete) changes to support
+ sysv4.2mp procfs as implemented in UnixWare 2.1. The procinfo
+ struct now has substructs like struct flt_ctl instead of
+ just a fltset_t and has a ctl_fd, status_fd, as_fd, and
+ map_fd instead of a single fd. Non-sysv4.2mp procfs models
+ still have the structs and multiple fds, but don't use the
+ entire struct and the four fds all point to the same thing.
+ We use PROCFS_USE_READ_WRITE to decide whether to talk to
+ procfs with reads/writes or use ioctl instead. We use
+ HAVE_MULTIPLE_PROC_FDS to determine whether procfs really has
+ multiple fds or not. PROC_NAME_FMT is split out into
+ CTL_PROC_NAME_FMT, AS_PROC_NAME_FMT, MAP_PROC_NAME_FMT,
+ STATUS_PROC_NAME_FMT.
+
+ (procfs_notice_signals): now a necessary wrapper around
+ (notice_signals): which are the new guts for noticing signals
+ (open_proc_file): gets a new flag arg used in sysv4.2mp to
+ determine whether or not to attempt to open the ctl_fd.
+ (procfs_read_status): new local function, reads procfs status
+ (procfs_write_pcwstop): new local function, writes a PCWSTOP
+ (procfs_write_pckill): new local function, writes a PCKILL
+ (unconditionally_kill_inferior): remove signo since we now
+ just call procfs_write_pckill().
+ (procfs_xfer_memory): call lseek with SEEK_SET rather than 0
+ (proc_iterate_over_mappings): the whole function is ifdefed
+ on UNIXWARE to keep things readable.
+
+ Expanded the syscall_table to include new potential sysv4.2mp
+ members. Note that all ifdefs of UNIXWARE should be eliminated
+ if possible or renamed to describe what's being selected for a
+ bit better. Sysv4.2mp and IRIX both have SYS_sproc so the
+ IRIX specific code now also checks it's not UNIXWARE.
+
+ * config/i386/tm-i386v42mp.h: also define HAVE_PSTATUS_T,
+ HAVE_NO_PRRUN_T, PROCFS_USE_READ_WRITE, and UNIXWARE
+ * config/mips/nm-irix4.h: set CTL_PROC_NAME_FMT et al to
+ "/debug/%d" as PROC_NAME_FMT used to be
+
+Wed Apr 9 11:36:14 1997 Jeffrey A Law (law@cygnus.com)
+
+ * mn10300-tdep.c: Almost completely rewritten based on mn10200
+ port.
+ * config/mn10300/tm-mn10300.h: Likewise.
+
+Tue Apr 8 10:45:24 1997 Stu Grossman (grossman@critters.cygnus.com)
+
+ * config/pa/{hppabsd.mt hppahpux.mt hppaosf.mt}: Remove
+ remote-pa.o from TDEPFILES. Nobody uses it, and besides, it's a
+ lousy out-of-date clone of remote.c.
+
+Fri Apr 4 08:21:21 1997 Stu Grossman (grossman@critters.cygnus.com)
+
+ * remote.c: Fix problems realized while showering.
+ * (hexnumlen): Add prototype. Use max, not min.
+ * (remote_write_bytes remote_read_bytes): Fix max packet size
+ calculations to properly account for packet overhead. Also handle
+ (probably rare) case where remote_register_buf_size isn't set.
+
+ * remote.c: Fix doc for `C' and `S' commands to indicate full
+ address.
+ * (remote_ops extended_remote_ops remote_desc remote_write_size):
+ Make static.
+ * (remote_fetch_registers remote_write_bytes remote_read_bytes):
+ Record size of response to fetch registers command, use this to
+ limit size of memory read and write commands.
+ * (push_remote_target): New function to make it possible to have
+ another target switch to the remote target.
+ * target.h: Add prototype for push_remote_target.
+ * sh-tdep.c (sh_frame_find_saved_regs): Fix sign extension bugs
+ for hosts which default to unsigned chars (such as SGI's).
+ * (_initialize_sh_tdep): Don't set remote_write_size. It's now
+ handled automatically in remote.c.
+
+Thu Apr 3 15:10:30 1997 Michael Snyder <msnyder@cleaver.cygnus.com>
+
+ * blockframe.c: blockvector_for_pc_sect(), block_for_pc_sect(),
+ find_pc_sect_function(), find_pc_sect_partial_function(): new
+ functions for debugging overlays; pc without section is ambiguous.
+ * breakpoint.[ch]: add section pointer to breakpoint struct;
+ add section argument to check_duplicates(); check section as well
+ as pc in [breakpoint_here_p(), breakpoint_inserted_here_p(),
+ breakpoint_thread_match(), bpstat_stop_status()];
+ add section argument to describe_other_breakpoints();
+ use INIT_SAL() macro to zero-out new sal structures;
+ make resolve_sal_pc() fix up the sal's section as well as its pc;
+ match on section + pc in clear_command() and delete_breakpoint();
+ account for overlay sections in insert_breakpoints(),
+ remove_breakpoint() and breakpoint_re_set_one();
+ all this to support overlays where a PC is not unique.
+ * exec.c: change xfer_memory() to handle overlay sections.
+ * findvar.c: change read_var_value() to handle overlay sections.
+ * frame.h: declaration for block_for_pc_sect() [blockframe.c].
+ * infcmd.c: jump_command() warns against jumping into an overlay
+ that's not in memory. Also use INIT_SAL() to initialize sals.
+ * infrun.c: wait_for_inferior() sets a flag to invalidate cached
+ overlay state information; Also use INIT_SAL() to init sals.
+ * m32r-rom.c: modify load routines to use LMA instead of VMA.
+ * m32r-stub.c: mask exit value down to 8 bits; screen out any
+ memory read/writes in the range 600000 to a00000, and ff680000
+ to ff800000 (hangs because nothing is mapped there); fix strcpy().
+ * maint.c: maintenance command "translate-address" supports overlays.
+ * minsyms.c: lookup_minimal_symbol_by_pc_sect() supports overlays.
+ * objfiles.[ch]: add ovly_mapped field to the obj_section struct;
+ this constitutes gdb's internal overlay mapping table. Add macro
+ ALL_OBJSECTIONS() to loop thru the obj_structs and look at overlays.
+ Add function find_pc_sect_section().
+ * printcmd.c: modify print_address_symbolic() with overlay smarts;
+ modify address_info() with overlay smarts; add function sym_info()
+ to support the INFO SYMBOL command (translate address to symbol(s));
+ modify disassemble_command() to work on unmapped overlays.
+ * source.c: use INIT_SAL() to initialize sals.
+ * symfile.[ch]: change generic_load() to use section's LMA address
+ instead of VMA address, for overlay sections.
+ Add numerous functions for finding a PC's section / overlay,
+ translating between VMA and LMA address ranges, determining if an
+ overlay section is mapped, etc. Add several user commands for
+ overlay debugging. Add support for a "generic" form of automatically
+ reading overlay mapping info from the inferior (based on the default
+ (simple) overlay manager which Cygnus provides as an example).
+ * symtab.[ch]: add functions find_pc_sect_symtab(),
+ find_pc_sect_psymtab(), find_pc_sect_psymbol(), find_pc_sect_line()
+ for lookup; modify lookup_symbol and decode_line_1() to use them;
+ modify find_function_start_sal() to account for overlay sections;
+ add macro INIT_SAL() for initializing struct symtab_and_line.
+ * target.c: fix a comment in the declaration of target_ops.
+
+Thu Apr 3 10:31:12 1997 Mark Alexander <marka@cygnus.com>
+
+ * mips-tdep.c (mips_in_call_stub, mips_in_return_stub,
+ mips_skip_stub, mips_ignore_helper): New functions for dealing
+ with MIPS16 call/return thunks.
+ (mips_init_frame_pc_first): New function to implement
+ INIT_FRAME_PC_FIRST macro; includes code from old macro plus
+ new code to skip over MIPS16 thunks.
+ (mips_frame_chain): Skip over MIPS16 thunks.
+ * config/mips/tm-mips.h (mips_in_call_stub, mips_in_return_stub,
+ mips_skip_stub, mips_ignore_helper): Declare.
+ (IN_SOLIB_CALL_TRAMPOLINE, IN_SOLIB_RETURN_TRAMPOLINE,
+ SKIP_TRAMPOLINE_CODE, IGNORE_HELPER_CALL): New macros that invoke
+ the above functions.
+ (INIT_FRAME_PC_FIRST): Change to invoke mips_init_frame_pc.
+ (mips_init_frame_pc): Declare.
+ * infrun.c (wait_for_inferior): Use new IGNORE_HELPER_CALL macro
+ to decide if certain library function calls should be ignored.
+
+Wed Apr 2 14:16:51 1997 Doug Evans <dje@canuck.cygnus.com>
+
+ * remote-sim.c (gdbsim_open): Check return code from sim_open.
+ Update call to sim_open (new arg SIM_OPEN_DEBUG).
+
+Mon Mar 31 14:55:53 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * gdbinit.in: New file.
+ * .gdbinit: Remove.
+ * configure.in: Generate .gdbinit from gdbinit.in.
+ * configure: Rebuild.
+
+Sat Mar 29 13:57:20 1997 Fred Fish <fnf@cygnus.com>
+
+ * COPYING: Install new version of file from FSF.
+ * copying.c (show_copying_command): Update FSF address.
+
+Fri Mar 28 18:33:41 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * Makefile.in (distclean): Remove .gdbinit.
+
+Fri Mar 28 15:38:04 1997 Mike Meissner <meissner@cygnus.com>
+
+ * remote-sim.c (gdb_os_{,e}vprintf_filtered): Change stdarg type
+ to va_list from void *, since va_list might not be a pointer
+ type.
+
+Thu Mar 27 14:21:46 1997 Mark Alexander <marka@cygnus.com>
+
+ * remote-mips.c: Clean up comment and extraneous semicolon
+ for mips_monitor_prompt variable.
+
+Thu Mar 27 12:46:58 1997 Mark Alexander <marka@cygnus.com>
+
+ * remote-mips.c: Add `set monitor-prompt' command.
+
+Wed Mar 26 06:47:44 1997 Mark Alexander <marka@cygnus.com>
+
+ Fix from Peter Schauer:
+ * mdebugread.c (parse_procedure): Set address of procedure to
+ block start; this fixes problems with shared libraries introduced
+ by change of Mar 21.
+
+Mon Mar 24 19:43:16 1997 Geoffrey Noer <noer@cygnus.com>
+
+ * symtab.c (find_pc_symtab): change to support the case
+ where the objfile is reordered and contains both coff and
+ stabs debugging info (continue on if a psymtab isn't found).
+
+Sun Mar 23 16:19:20 1997 Mark Alexander <marka@cygnus.com>
+
+ Fixes from Peter Schauer:
+ * config/mips/tm-mips.h (REGISTER_CONVERT_TO_TYPE,
+ REGISTER_CONVERT_FROM_TYPE): Swap words if target, not host,
+ is big-endian and if registers are 32 bits.
+ * mips-tdep.c (mips_print_register, mips_extract_return_value,
+ mips_store_return_value): Fix floating-point word-order problems on
+ little-endian targets introduced by changes of Mar 21.
+
+Sun Mar 23 15:43:27 1997 Stan Shebs <shebs@andros.cygnus.com>
+
+ * remote.c (target_resume_hook, target_wait_loop_hook): New
+ globals.
+ (remote_resume, remote_wait): Use them.
+ * d10v-tdep.c: Set the above hooks.
+ (tracesource): New GDB variable, controls source display in
+ traces.
+ (display_trace): Find and display source line if requested.
+ (trace_info): Mention empty trace buffer if appropriate.
+ (tdisassemble_command): Robustify argument handling.
+
+ * configure.host: Remove extra bogus Linux case.
+
+Sat Mar 22 16:41:35 1997 Fred Fish <fnf@cygnus.com>
+
+ * remote-sim.c (simulator_command): Add comment about dealing with
+ NULL or empty args.
+
+Sat Mar 22 02:48:11 1997 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * c-exp.y (yylex): Handle nested template parameter lists.
+ * symtab.c (decode_line_2): Fix test for valid choice number.
+
+Fri Mar 21 19:10:05 1997 Mark Alexander <marka@cygnus.com>
+
+ * mips-tdep.c (mips_push_arguments): On non-EABI architectures,
+ copy first two floating point arguments to general registers, so that
+ MIPS16 functions will receive the arguments correctly.
+ (mips_print_register): Print double registers correctly on
+ little-endian hosts.
+ (mips_extract_return_value): Return double values correctly
+ on little-endian hosts.
+
+ * mdebugread.c (parse_procedure): Adjust address of procedure relative
+ to address in file descriptor record; this accounts for constant
+ strings that may precede functions in the text section. Remove
+ now-useless lowest_pdr_addr from argument list and all calls.
+
+Fri Mar 21 15:36:25 1997 Michael Meissner <meissner@cygnus.com>
+
+ * configure.tgt (powerpc*-{eabi,linux,sysv,elf}*): Determine
+ whether the simulator will be built by whether the Makefile in the
+ simulator directory was built.
+
+ * configure.in (--enable-sim-powerpc): Delete switch.
+ * configure: Regenerate.
+
+Thu Mar 20 20:52:04 1997 Jeffrey A Law (law@cygnus.com)
+
+ * mn10200-tdep.c (mn10200_analyze_prologue): Look for save of "a1"
+ in the prologue too.
+
+ * remote-sim.c (gdb_os_vprintf_filtered): Fix to work with non-ANSI
+ compilers.
+ (gdb_os_evprintf_filtered): Similarly.
+
+Wed Mar 19 16:13:22 1997 Geoffrey Noer <noer@pizza.cygnus.com>
+
+ New UnixWare 2.1 configuration
+ * config/i386/i386v42mp.mt: new
+ * config/i386/i386v42mp.mh: new
+ * config/i386/tm-i386v42mp.h: new
+ * config/i386/nm-i386v42mp.h: new
+ * configure.tgt: added new entries
+ * configure.host: added new entries
+
+Mon Mar 17 17:52:00 1997 J.T. Conklin <jtc@cygnus.com>
+
+ * dsrec.c (load_srec): Print leading zeroes when printing section
+ addresses.
+
+Mon Mar 17 15:00:16 1997 Andrew Cagney <cagney@kremvax.cygnus.com>
+
+ * remote-sim.h: Delete - moved to ../include/remote-sim.h.
+
+ * Makefile.in (remote_utils_h): Update path to remote-sim.h.
+
+Fri Mar 7 20:55:28 1997 Andrew Cagney <cagney@kremvax.cygnus.com>
+
+ * remote-sim.c (flush_stdout, write_stderr, flush_stderr,
+ vprintf_filtered, evprintf_filtered): Callbacks that accept
+ varargs.
+
+Sat Mar 15 00:50:46 1997 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * breakpoint.c (insert_breakpoints, watchpoint_check,
+ bpstat_stop_status): Do not disable watchpoints going out of scope.
+ (insert_breakpoints): Make sure that the current frame is valid
+ before calling find_frame_addr_in_frame_chain.
+
+ * top.c (setup_user_args): Handle quotes and backslashes.
+ (print_gdb_version): Update copyright year.
+
+Fri Mar 14 15:44:03 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * Makefile.in (elfread.o): Depend upon elf-bfd.h and elf/mips.h.
+
+Thu Mar 13 22:51:00 1997 Dawn Perchik <dawn@cygnus.com>
+
+ * utils.c (pollquit, notice_quit): If _WIN32, limit test for
+ cntl-C to wingdb.
+ (initialize_utils): If _WIN32, don't call ScreenRows and ScreenCols
+ except under wingdb. (Contributed by Martin Hunt).
+
+Thu Mar 13 12:40:49 1997 Tom Tromey <tromey@cygnus.com>
+
+ * configure: Regenerated.
+ * configure.in: Run AC_CONFIG_AUX_DIR before AC_CANONICAL_SYSTEM.
+
+Thu Mar 13 11:00:22 1997 Doug Evans <dje@canuck.cygnus.com>
+
+ * remote-sim.h (sim_state, SIM_DESC): New types.
+ (sim_open): Return a `descriptor' as result.
+ (*): New argument of descriptor result from sim_open.
+ * remote-sim.c (gdbsim_desc): Renamed from gdbsim_open_p.
+ (gdbsim_open): Record result of sim_open in gdbsim_desc.
+ Pass argv list to sim_open, argv[0] = pseudo program name.
+ (*): Pass gdbsim_desc to sim_foo fns.
+
+Wed Mar 12 14:40:06 1997 Tom Tromey <tromey@cygnus.com>
+
+ * config.in: Regenerated.
+
+ * acconfig.h (START_INFERIOR_TRAPS_EXPECTED, sys_quotactl,
+ HAVE_HPUX_THREAD_SUPPORT): Define.
+
+Tue Mar 11 07:25:27 1997 Mark Alexander <marka@cygnus.com>
+
+ First cut at supporting simulators in gdbserver:
+
+ * configure, configure.in: Allow gdbserver to be configured
+ for cross-target environments.
+ * gdbserver/Makefile.in: Add simulator support.
+ * gdbserver/configure.in: Eliminate assumption that host == target.
+ Simplify using gdb/configure.tgt and gdb/configure.host.
+ Fix other minor configuration errors.
+ * gdbserver/low-sparc.c: Fix compile error.
+ * gdbserver/remote-utils.c: Eliminate assumption that registers
+ and addresses are four bytes. Fix minor compile errors and warnings.
+ * gdbserver/server.c: Rewrite numerous instances of identical code
+ for starting inferior processes to call new function start_inferior.
+ Eliminate assumption that registers and addresses are four bytes.
+ * gdbserver/server.h: Add missing prototypes to eliminate compiler
+ warnings.
+ * gdbserver/low-sim.c: New file to mate gdbserver with simulators.
+ * config/mips/vr5000.mt: Add Vr5000 simulator support to gdbserver.
+ * config/i386/linux.mh: Eliminate gdbserver support as a first step
+ in moving such support from host to target makefile fragments.
+ * config/i386/linux.mt: Move gdbserver support here from linux.mh.
+
+Mon Mar 10 12:27:47 1997 Michael Snyder <msnyder@cleaver.cygnus.com>
+
+ * symtab.h (INIT_SAL): New macro to initialize symtab_and_line,
+ to insure consistant initialization of unused fields to zero.
+ * symtab.c: replace initializations of sals with new macro INIT_SAL.
+ * breakpoint.c: ditto.
+ * infrun.c: ditto.
+ * infcmd.c: ditto.
+ * source.c: add call to INIT_SAL macro.
+
+Sat Mar 8 00:16:37 1997 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * sparc-tdep.c (isbranch): Always handle v9 branch instructions,
+ they might get used on 32 bit targets as well.
+
+Wed Mar 5 19:34:09 1997 Bob Manson <manson@charmed.cygnus.com>
+
+ * remote-mips.c (mips_exit_debug): Some IDT boards don't
+ send the full exit string.
+
+Wed Mar 5 12:59:27 1997 Jeffrey A Law (law@cygnus.com)
+
+ * mn10200-tdep.c (mn10200_push_arguments): Handle new calling
+ conventions.
+ (mn10200_store_struct_return): Likewise.
+
+Tue Mar 4 10:31:02 1997 Mark Alexander <marka@cygnus.com>
+
+ * mips-tdep.c (mips_fetch_instruction): New function; replace
+ common code throughout with calls to it.
+ (mips_find_saved_regs): Examine MIPS16 entry instruction to determine
+ correct saved addresses of $s0 and $s1.
+ (mips_find_saved_regs, mips16_heuristic_proc_desc): Use MIPS_REGSIZE
+ instead of hardcoded 4.
+ (mips16_skip_prologue): Handle extended instructions correctly.
+
+Mon Mar 3 12:29:20 1997 Doug Evans <dje@canuck.cygnus.com>
+
+ * defs.h (LONGEST): Move #ifndef LONGEST to outside.
+ Try BFD_HOST_64_BIT if ! CC_HAS_LONG_LONG.
+
+Thu Feb 27 18:54:11 1997 Mark Alexander <marka@cygnus.com>
+
+ * mips-tdep.c (IS_MIPS16_ADDR, MAKE_MIPS16_ADDR, UNMAKE_MIPS16_ADDR):
+ New macros for testing, setting, and clearing bit 0 of addresses.
+ Change numerous bits of code where bit 0 was being manipulated
+ to use these macros.
+
+Thu Feb 27 14:12:41 1997 Mark Alexander <marka@cygnus.com>
+
+ * remote-mips.c: Put back the form feeds.
+
+Thu Feb 27 12:04:24 1997 Mark Alexander <marka@cygnus.com>
+
+ * remote-mips.c: Remove form feeds (^L) from source.
+ (mips_initialize): LSI PMON doesn't support 'set regsize' command.
+ (pmon_wait): Don't need to exit and re-enter debug mode on LSI
+ PMON after a continue; it causes target program misbehavior.
+ (mips_fetch_register): Don't fetch unsupported registers; this
+ cuts down on wasted serial traffic.
+
+Thu Feb 27 09:38:16 1997 Stu Grossman (grossman@critters.cygnus.com)
+
+ * configure.in configure (HPUX/OSF thread support): Enable this
+ only when running GCC, since HP's thread header files use ANSI C
+ which is not supported by their default compiler.
+
+ * configure.host (i[3456]86-*-windows): Disable long long
+ support for WinGDB. Add mswin to configdirs.
+ * configure.in configure: Move calls to configure.host and
+ configure.tgt to the top of configure.in to allow them to set
+ config variables before they are referenced.
+
+Tue Feb 25 20:21:52 1997 Stan Shebs <shebs@andros.cygnus.com>
+
+ * configure.tgt (mips*-*-lnews*): New target.
+
+Mon Feb 24 16:35:00 1997 Jeffrey A Law (law@cygnus.com)
+
+ * mn10200-tdep.c (mn10200_analyze_prologue): Don't fix fi->frame
+ if we're not the innermost frame. Fix minor typos.
+
+Sat Feb 22 03:39:50 1997 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * stabsread.c (read_type): Fix handling of template names
+ with template parameters containing `::'.
+
+ * valops.c (search_struct_field, search_struct_method):
+ Pass correct valaddr parameter to baseclass_offset.
+ Prevent gdb crashes by making sure that the virtual base pointer
+ from an user object still points to accessible memory.
+
+Tue Feb 18 13:36:34 1997 Mark Alexander <marka@cygnus.com>
+
+ * maint.c: Eliminate -Wall warnings by including some header files.
+
+Tue Feb 18 13:06:30 1997 Mark Alexander <marka@cygnus.com>
+
+ * remote-sim.c (init_callbacks): Undo previous change.
+
+Tue Feb 18 11:13:00 1997 Dawn Perchik <dawn@cygnus.com>
+
+ * maint.c: Fix dereference of pointer.
+ * remote-sim.c: Fix reference of structure member "last_error".
+ * debugify.c: Include config.h to get ANSI definitions.
+
+Sat Feb 15 17:43:46 1997 Stu Grossman (grossman@critters.cygnus.com)
+
+ * remote-vx.c (vx_attach): Remove code added by kung. It made no
+ sense.
+
+Fri Feb 14 13:00:07 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * main.c (print_gdb_help): Make static to match declaration.
+
+Thu Feb 13 18:18:18 1997 Dawn Perchik <dawn@cygnus.com>
+
+ * remote-e7000.c, ser-e7kpc.c, serial.c: Remove // comments.
+
+Wed Feb 12 15:58:00 1997 Dawn Perchik <dawn@cygnus.com>
+
+ * debugify.c, debugify.h: Make safe for non-ansi compilers.
+
+Wed Feb 12 15:30:00 1997 Dawn Perchik <dawn@cygnus.com>
+
+ * defs.h: Fix prototypes for new cleanup functions.
+
+Wed Feb 12 15:08:47 1997 Dawn Perchik <dawn@cygnus.com>
+
+ * debugify.c, debugify.h: Fix for general gnu use. Remove C++
+ comment, add PARAMS, add license info and fix indentation.
+
+Wed Feb 12 14:42:47 1997 Dawn Perchik <dawn@cygnus.com>
+
+ * debugify.c, debugify.h: New files. Provide common macros
+ for writing debug info to a log file or stdio.
+
+Wed Feb 12 02:44:39 1997 Dawn Perchik <dawn@cygnus.com>
+
+ * c-valprint.c (c_val_print): Fix printing for arrays defined
+ with 0 length.
+
+Tue Feb 11 22:24:39 1997 Dawn Perchik <dawn@cygnus.com>
+
+ * defs.h: Fix cntl-C to read from the Windows message queue.
+ Add prototypes for make_final_cleanup (and the other cleanup
+ routines.
+ * remote-e7000.c: Fix sync code to timeout if unable to sync.
+ Change sync code to report status while trying to sync-up
+ with hardware. Add debugging output and document.
+ * ser-e7kpc.c: Swap order of len & offset to match implementation.
+ Add debugging output and document.
+ * serial.c: Add debugging output.
+ * top.c: Add call to do_final_cleanups.
+ Remove conditionals preventing Win32 from getting SIGQUIT.
+ * utils.c: (*_cleanup): Modify cleanup routines to accept a cleanup
+ chain as a parameter. Extract this generic code from the cleanup
+ routines into separate funtions (*_my_cleanup). Keep old
+ functionality by passing "cleanup_chain" to the new funtions.
+ Define the cleanup chain "final_cleanup_chain" to be a cleanup
+ chain which will be executed only when gdb exits. Add functions
+ (*_final_cleanup) to match the original (*_cleanup) functions.
+ (pollquit, quit, notice_quit): Fix to read cntl-C from the
+ Windows message queue.
+
+Tue Feb 11 15:36:31 1997 Doug Evans <dje@canuck.cygnus.com>
+
+ * m32r-rom.c: #include <sys/types.h>.
+ #ifdef out new load support if wingdb.
+ * m32r/tm-m32r.h (TARGET_M32R): Define, for wingdb.
+
+Tue Feb 11 12:28:09 1997 Jeffrey A Law (law@cygnus.com)
+
+
+ * config/mn10200/tm-mn10200.h (STORE_STRUCT_RETURN): Fix.
+ * mn10200-tdep.c (mn10200_store_struct_return): New function.
+
+ * config/mn10200/tm-mn10200.h (EXTRACT_RETURN_VALUE): Fix case when
+ extracting a return value from a register pair.
+
+ * mn10200-tdep.c (mn10200_push_arguments): Stack only needs to
+ be two byte aligned. Round argument sizes up to two byte boundary.
+ Write out args in two byte hunks.
+ (mn10200_push_return_address): Implement.
+ * config/mn10200/tm-mn10200.h (EXTRACT_RETURN_VALUE): Abort for
+ structures > 8 bytes (temporary).
+ (STORE_RETURN_VALUE): Likewise.
+ (CALL_DUMMY): No longer undefine.
+ (USE_STRUCT_CONVENTION): Use for args > 8 bytes.
+ (REG_STRUCT_HAS_ADDR): Define.
+
+Mon Feb 10 18:35:55 1997 Mark Alexander <marka@cygnus.com>
+
+ * mips-tdep.c (non_heuristic_proc_desc): New function.
+ (find_proc_desc): Move non-heuristic proc search code into separate
+ function.
+ (gdb_print_insn_mips): Use non-heuristic method to find procedure
+ descriptor, to avoid prologue examination when disassembling.
+ * remote-mips.c: Add support for new "lsi" target (LSI MiniRISC
+ aka MicroMeteor board).
+ (mips_exit_debug): Prevent protocol reinitialization if an error
+ occurs while exiting debug mode.
+
+Mon Feb 10 16:11:57 1997 Jeffrey A Law (law@cygnus.com)
+
+ * mn10200-tdep.c: Remove lots of debugging printfs, update/improve
+ comments, formatting, etc. Plus other minor fixes for problems
+ I found during my first pass over the mn10200 port.
+ (mn10200_analyze_prologue): New function.
+ (mn10200_frame_chain, mn10200_init_extra_frame_info): Use it.
+ * config/mn10200/tm-mn10200.h: Lots of updates/improvements to
+ comments, formatting, etc. Minor fixes for problems I found during
+ my first pass over the mn10200 port.
+ (TARGET_*_BIT): Define appropriately for ints, long longs, doubles and
+ pointers.
+ (REGISTER_VIRTUAL_TYPE): Define as a long.
+ (EXTRACT_RETURN_VALUE): Rework to deal with long ints living
+ in register pairs.
+ (STORE_RETURN_VALUE): Similarly.
+
+ * blockframe.c (generic_get_saved_regs): Remove unused variable
+ "addr".
+ * breakpoint.c (frame_in_dummy): Move struct breakpoint *b decl
+ inside #ifdef CALL_DUMMY.
+ (watch_command_1): Initialize target_resources_ok.
+ * command.c (do_setshow_command): Provide dummy initialization
+ for "match".
+ * valops.c (find_function_addr): Move function & prototype inside
+ #ifdef CALL_DUMMY.
+ (value_arg_coerce): Similarly.
+ (value_of_variable): Provide dummy initialization of "frame".
+
+Mon Feb 10 07:54:26 1997 Fred Fish <fnf@cygnus.com>
+
+ * xcoffread.c (RECORD_MINIMAL_SYMBOL): Add NULL asection* parameter
+ to prim_record_minimal_symbol_and_info call that was missed in Jan 3
+ change.
+ (scan_xcoff_symtab): Ditto.
+
+Sun Feb 09 09:23:26 1997 Mark Alexander <marka@cygnus.com>
+
+ * remote-mips.c (common_breakpoint): Prevent 64-bit addresses
+ from being sent to 32-bit targets by masking off upper bits.
+ * mips-tdep.c (heuristic_proc_start): Mask off upper 32 bits
+ of PC on 32-bit targets.
+ (mips16_heuristic_proc_desc): Recognize 'addiu s1,sp,n' as a
+ frame setup instruction.
+ (mips32_heuristic_proc_desc): Fix warning found by gcc -Wall.
+ (mips16_skip_prologue): Recognize 'addiu s1,sp,n' as a valid
+ prologue instruction. Fix warnings and bugs found by gcc -Wall.
+ * buildsym.c (finish_block): Improve handling of overlapping blocks;
+ fixes problem on MIPS16 printing function arguments.
+
+Sat Feb 8 01:14:43 1997 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * dwarf2read.c (dwarf2_linkage_name): New function to get
+ the linkage name of a die from DW_AT_MIPS_linkage_name or
+ DW_AT_name.
+ (read_func_scope, dwarf2_add_field, dwarf2_add_member_fn,
+ new_symbol): Use it instead of accessing DW_AT_name.
+ (read_partial_die): Use DW_AT_MIPS_linkage name as name of the
+ partial die if present.
+ (dwarf2_add_member_fn): Make a copy of physname on the type obstack.
+
+Fri Feb 7 10:06:22 1997 Jeffrey A Law (law@cygnus.com)
+
+ * blockframe.c (generic_frame_chain_valid): If the new frame
+ is not INNER_THAN the old frame, then it's not valid.
+
+Tue Feb 04 09:04:37 1997 Mark Alexander <marka@cygnus.com>
+
+ * mips-tdep.c (mips16_get_imm): Fix calculation of extended immediate.
+ (mips16_heuristic_proc_desc): Recognize jal(x) instruction.
+
+Mon Feb 03 17:57:58 1997 Mark Alexander <marka@cygnus.com>
+
+ * mips-tdep.c (mips16_decode_reg_save): Distinguish between
+ sd and sw instructions correctly.
+ (heuristic_proc_start): Add support for MIPS16.
+ (mips16_get_imm, mips16_heuristic_proc_desc,
+ mips32_heuristic_proc_desc): New helper functions for
+ heuristic_proc_desc.
+ (heuristic_proc_desc): Rewrite and reorganize to support MIPS16.
+ (mips_push_arguments): Don't align small arguments in EABI.
+ (mips32_skip_prologue): Attempt to shrink code size a little.
+
+Mon Feb 3 11:06:05 1997 Michael Snyder <msnyder@cleaver.cygnus.com>
+
+ * m32r-stub.c: New -- remote protocol support for M32R cpu.
+ * m32r-rom.c: Several experiments with improved download time.
+
+Fri Jan 31 08:26:39 1997 Mark Alexander <marka@cygnus.com>
+
+ * mips-tdep.c (MIPS16_INSTLEN): Define.
+ (mips_find_saved_regs): Replace hardcoded 2's with MIPS16_INSTLEN.
+ (heuristic_proc_start): Recognize 'entry' pseudo-op as a start
+ of function on MIPS16.
+ (mips32_skip_prologue, mips16_skip_prologue): New helper functions
+ for mips_skip_prologue.
+ (mips_skip_prologue): Recognize both 16- and 32-bit prologues.
+
+Wed Jan 29 12:45:54 1997 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * config/powerpc/ppc{,le}-sim.mt (SIM): Remove the library
+ ../sim/common/libcommon.a.
+
+Tue Jan 28 15:54:13 1997 Michael Snyder <msnyder@cleaver.cygnus.com>
+
+ * blockframe.c: fix a null pointer ref in generic_get_saved_register
+
+Tue Jan 28 15:39:50 1997 Geoffrey Noer <noer@cygnus.com>
+
+ * mn10200-tdep.c (mn10200_frame_chain): Get basic backtracing
+ working.
+
+Mon Jan 27 14:31:52 1997 Mark Alexander <marka@cygnus.com>
+
+First set of changes for mips16:
+ * config/mips/tm-mips.h (MIPS16_BIG_BREAKPOINT,
+ MIPS16_LITTLE_BREAKPOINT, BREAKPOINT_FROM_PC): Define.
+ (ABOUT_TO_RETURN): Call new function mips_about_to_return.
+ (mips_breakpoint_from_pc, mips_about_to_return): Declare.
+ * mem-break.c (memory_breakpoint_from_pc): New function.
+ (memory_insert_breakpoint, memory_remove_breakpoint): Use
+ memory_breakpoint_from_pc to determine breakpoint contents and size.
+ * target.h (memory_breakpoint_from_pc): Declare.
+ * monitor.c (monitor_insert_breakpoint): Use memory_breakpoint_from_pc
+ to determine size of breakpoint instruction.
+ * mips-tdep.c (mips32_decode_reg_save, mips16_decode_reg_save):
+ New helper functions for mips_find_saved_regs.
+ (mips_find_saved_regs): Recognize mips16 prologues.
+ (mips_addr_bits_remove): Strip off upper 32 bits of address
+ when target CPU is 32 bits but CORE_ADDR is 64 bits.
+ (mips_step_skips_delay): No branch delay slot on mips16.
+ (gdb_print_insn_mips): Disassemble mips16 code.
+ (mips_breakpoint_from_pc, mips_about_to_return): New functions.
+
+Mon Jan 27 10:34:03 1997 Jeffrey A Law (law@cygnus.com)
+
+ * tm-mn10200.h (NUM_REGS): Decrease to 12.
+ (REGISTER_NAMES): Elimination registers not found on the mn10200.
+ (PC_REGNUM, MDR_REGNUM, PSW_REGNUM): Corresponding changes.
+ (LIR_REGNUM, LAR_REGNUM): Delete. They don't exist on the mn10200.
+
+Sat Jan 25 00:07:59 1997 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * dwarf2read.c: Replace integral tag, name and form fields in
+ internal structure definitions with the corresponding enumeration
+ types from dwarf2.h. Add default cases to switches on enumerations
+ where appropriate.
+ Make quoting of string arguments in complaint messages consistent.
+ Check for NULL returns from DW_STRING.
+ (struct partial_die_info): Add sibling and has_type fields, remove
+ unused value field.
+ (DW_*): Move access macro definitions near the definition of the
+ attribute structure.
+ (struct field_info): New structure to pass information about fields
+ and member functions between die processing routines.
+ (dwarf2_build_psymtabs_hard): Set cu_header_offset.
+ (scan_partial_symbols): Do not enter DW_TAG_subprogram dies into
+ the partial symbol table if the DW_AT_*_pc attributes are missing.
+ Add file scope base type definitions to the partial symbol table.
+ Skip over child dies if the die has a sibling attribute.
+ (add_partial_symbol): Enter global variables with type attributes
+ and without location descriptors into the partial symbol table.
+ Store value of DW_TAG_variable dies in the partial symbol table.
+ Do not enter global variables into the minimal symbol table.
+ Add base type definitions to the partial symbol table.
+ (psymtab_to_symtab_1): Use dwarf2_get_pc_bounds to determine highpc.
+ (process_die): Move check for DW_AT_low_pc to read_func_scope.
+ Add a typedef symbol for base type definitions to the symbol table.
+ Ignore DW_TAG_inlined_subroutine tags for now.
+ (read_file_scope): Use dwarf2_get_pc_bounds to determine pc bounds.
+ (read_func_scope, read_lexical_block_scope): Use dwarf2_get_pc_bounds
+ to determine pc bounds, ignore dies with invalid bounds.
+ (dwarf2_get_pc_bounds): New routine to extract and validate the
+ DW_AT_*_pc attributes of a die.
+ (dwarf2_add_field, dwarf2_attach_fields_to_type, skip_member_fn_name,
+ dwarf2_add_member_fn, dwarf2_attach_fn_fields_to_type):
+ New functions to handle fields and member functions.
+ (read_structure_scope): Rewritten to use them.
+ (read_array_type): Renamed from dwarf_read_array_type.
+ Default upper array bound to describe an array with unspecified
+ length.
+ Create array types in backwards order, as dwarf2 puts out the array
+ dimensions from left to right.
+ (read_subroutine_type): Handle DW_TAG_unspecified_parameters,
+ DW_AT_artificial and DW_AT_prototyped.
+ (read_base_type): Make an unsigned type for DW_ATE_boolean.
+ Pass objfile to dwarf_base_type.
+ (read_partial_die): Use read_attribute to read in the attributes.
+ Handle DW_AT_sibling and DW_AT_type.
+ Follow references when determining DW_AT_name and DW_AT_external
+ attributes of the die.
+ Validate DW_AT_*_pc attributes.
+ (read_full_die): Use read_attribute to read in the attributes.
+ (read_attribute): New function to read an attribute described
+ by an abbreviated attribute.
+ (new_symbol): Relocate symbol value for DW_TAG_label with baseaddr.
+ Do not set SYMBOL_VALUE_ADDRESS for DW_TAG_subprogram,
+ SYMBOL_BLOCK_VALUE for the symbol will be set later by finish_block.
+ Change symbol class for global variables with a zero valued location
+ descriptor to LOC_UNRESOLVED.
+ Handle DW_AT_const_value attributes for DW_TAG_variable,
+ DW_TAG_formal_parameter and DW_TAG_enumerator.
+ Build a typedef symbol for DW_TAG_base_type.
+ (dwarf2_const_value): New routine to copy a constant value from an
+ attribute to a symbol.
+ (dwarf_base_type): Use passed in objfile, not current_objfile
+ when calling dwarf2_fundamental_type.
+ (dump_die): Use DW_* accessor macros to access values of attributes.
+ (decode_locdesc): Handle DW_OP_plus_uconst.
+
+Wed Jan 22 01:31:16 1997 Geoffrey Noer <noer@cygnus.com>
+
+ * mn10200-tdep.c: New file.
+ * config/mn10200/tm-mn10200.h: New, REGISTER_SIZE is 24 bits not 32,
+ SP_REGNUM and FP_REGNUM are different, also no lar or lir.
+ * config/mn10200/mn10200.mt: New file.
+ * configure.tgt: add mn10200 entry.
+
+Tue Jan 21 18:32:23 1997 Stu Grossman (grossman@lisa.cygnus.com)
+
+ * configure.in configure: Check if host has libdl if doing
+ Solaris threads.
+
+Tue Jan 21 17:03:26 1997 Geoffrey Noer <noer@cygnus.com>
+
+ * mn10300-tdep.c: Wrote/fixed implementations of
+ mn10300_frame_chain, mn10300_init_extra_frame_info,
+ mn10300_frame_saved_pc
+ * config/mn10300/tm-mn10300.h: Redefine INIT_EXTRA_FRAME_INFO
+ and INIT_FRAME_PC macros.
+
+Tue Jan 21 17:01:20 1997 Stu Grossman (grossman@lisa.cygnus.com)
+
+ * configure.in configure: Check if host has libm. Make sure we
+ are using gcc when using the -export-dynamic option. Fixes a
+ problem with building under Solaris/SunPro cc.
+
+Mon Jan 20 13:52:13 1997 Mark Alexander <marka@cygnus.com>
+
+ * config/mips/{embed,embed64,embedl,embedl64}.mt:
+ Link in simulator on MIPS embedded targets.
+
+Sat Jan 18 02:31:29 1997 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * blockframe.c (frameless_look_for_prologue): Mark frames
+ with a zero PC as frameless to improve backtraces from core dumps
+ caused by dereferencing a NULL function pointer.
+
+Thu Jan 16 14:10:41 1997 Geoffrey Noer <noer@cygnus.com>
+
+ * config/mn10300/tm-mn10300.h: fix BREAKPOINT definition.
+
+Tue Jan 14 16:01:06 1997 Geoffrey Noer <noer@cygnus.com>
+
+ * mn10300-tdep.c: made a lot more generic, ripping out code
+ from copied target (no more mn10300_scan_prologue,
+ init_extra_frame_info, and mn10300_fix_call_dummy calls)
+ * config/mn10300/tm-mn10300.h: undefine INIT_EXTRA_FRAME_INFO
+ and INIT_FRAME_PC macros
+
+Thu Jan 9 11:44:40 1997 Michael Snyder <msnyder@cleaver.cygnus.com>
+
+ * sparc-tdep.c (sparc_frame_find_saved_regs): Don't use
+ FP_REGISTER_BYTES to compute offsets into the saved frame,
+ since it fails for SPARC targets configured without any
+ FP regs. Instead, use DUMMY_STACK_REG_BUF_SIZE.
+
+Mon Jan 6 11:15:14 1997 Stu Grossman (grossman@critters.cygnus.com)
+
+ * symtab.c (fixup_symbol_section): Handle NULL symbols without
+ crashing.
+
+Fri Jan 3 12:08:16 1997 Stu Grossman (grossman@critters.cygnus.com)
+
+ * Makefile.in configure configure.in: Remove ENABLE_CLIBS,
+ ENABLE_OBS, and THREAD_DB_OBS. These are consolidated into LIBS
+ and CONFIG_OBS.
+ * configure configure.in: Clean up test cases around thread support.
+ * configure.tgt (v850-*-*): Include v850ice.o and v850.lib if
+ host is Windows.
+ * c-valprint.c ch-valprint.c cp-valprint.c eval.c expprint.c
+ printcmd.c valops.c value.h values.c: Add bfd_section arg to
+ value_at and value_at_lazy.
+ * coffread.c dbxread.c elfread.c mdebugread.c minsyms.c symtab.h:
+ Add bfd_section arg to prim_record_minimal_symbol_and_info.
+ * corefile.c gdbcore.h printcmd.c valops.c: Use read_memory_section
+ instead of read_memory. It takes a bfd_section arg.
+ * coffread.c dbxread.c elfread.c gdb-stabs.h objfiles.h: Remove
+ unnecessary cast for assignment of struct dbx_symfile_info.
+ Struct objfile now uses a real pointer instead of PTR for this
+ element.
+ * dbxread.c (dbx_symfile_init): Stash bfd section pointers for
+ text, data and bss into dbx_symfile_info.
+ * exec.c (xfer_memory): Handle transfers for user-specified
+ sections.
+ * findvar.c (read_var_value locate_var_value): Copy bfd section
+ from the symbol to the value.
+ * gdb-stabs.h: Add section pointers for text, data and bss
+ sections.
+ * maint.c (translate address command): Add test code for overlay
+ address translation.
+ * printcmd.c (do_examine do_one_display): Now takes a bfd section
+ arg.
+ * (print_formatted x_command): Record current section along with
+ current address for repeated commands.
+ * sparc-nat.c (fetch_inferior_registers): Change
+ target_xfer_memory to target_{read write}_memory to allow changes
+ to target_xfer_memory interface for section info.
+ * symmisc.c (dump_msymbols print_symbol): Print section
+ assocaited with symbol.
+ * symtab.c (fixup_symbol_section): New routine to
+ add section info to symbols returned by lookup_symbol.
+ * symtab.h (struct general_symbol_info): Add bfd section to
+ symbols.
+ * target.c target.h (target_xfer_memory): Add bfd section to
+ args.
+ * (target_read_memory_section): New routine to read data from a
+ specific section.
+ * (target_memory_bfd_section): New global variable to pass bfd
+ section in to targets.
+ * valarith.c (value_add value_addr value_array): Preserve bfd
+ section when computing new value.
+ * value.h (struct value): Add bfd section to values.
+ * values.c (allocate_value value_copy): Initialize/preserve bfd
+ section.
+ * (unpack_double): Clean up _MSC_VER conditionals to remove
+ duplicate code.
+ * v850ice.c: New module to support communication with NEC's
+ PC-based ICE.
+ * config/v850/tm-v850.h (REGISTER_NAMES): Replace sp, gp, fp, and
+ ep names with rxx names. sp and fp are renamed via a different
+ mechanism.
+
+Fri Jan 3 14:20:05 1997 Geoffrey Noer <noer@cygnus.com>
+
+ * mn10300-tdep.c (mn10300_push_arguments): rewrote,
+ also removed code elsewhere that made use of RP_REGNUM.
+ * config/mn10300/tm-mn10300.h: ripped out RP_REGNUM, V0_REGNUM,
+ ARG0_REGNUM, ARGLAST_REGNUM (all not appropriate for mn10300
+ arch.), redefined SAVED_PC_AFTER_CALL, EXTRACT_RETURN_VALUE,
+ EXTRACT_STRUCT_VALUE_ADDRESS, STORE_RETURN_VALUE.
+
+For older changes see ChangeLog-96
+
+Local Variables:
+mode: indented-text
+left-margin: 8
+fill-column: 74
+version-control: never
+End:
diff --git a/gdb/ChangeLog-98 b/gdb/ChangeLog-98
new file mode 100644
index 00000000000..bd19b49066a
--- /dev/null
+++ b/gdb/ChangeLog-98
@@ -0,0 +1,7122 @@
+Thu Dec 31 15:26:13 1998 Stan Shebs <shebs@andros.cygnus.com>
+
+ * corelow.c (core_ops): Don't initialize statically.
+ (init_core_ops): New function, fills in core_ops.
+ (_initialize_corelow): Use it.
+
+Thu Dec 31 16:54:30 1998 David Taylor <taylor@texas.cygnus.com>
+
+ The following changes were made by
+ Elena Zannoni <ezannoni@kwikemart.cygnus.com>
+ Edith Epstein <eepstein@sophia.cygnus.com>
+ David Taylor <taylor@texas.cygnus.com>
+
+ * config/pa/tm-hppa.h (INSTRUCTION_NULLIFIED): Change to read
+ nullify instruction bit from IPSW only when we are not in a system
+ call.
+ (STRCAT_REGISTER, pa_do_strcat_registers_info): Additional
+ parameter -- precision.
+
+ * Makefile.in (BUILD_TUI): To build the tui, only when configured
+ with --enable-tui.
+ (YLWRAP): Use ylwrap to avoid problems on systems w/o bison.
+ (gdb$(EXEEXT)): Make it dependent on BUILD_TUI.
+ (all-tui): Remove dependency from phony target.
+ (c-exp.tab.c): Use ylwrap instead of bison.
+ (jv-exp.tab.c): Ditto.
+ (f-exp.tab.c): Ditto.
+ (m2-exp.tab.c): Ditto.
+
+ * configure.in (ENABLE_CFLAGS): Define and export BUILD_TUI.
+
+ * configure: Regenerated.
+
+ * c-typeprint.c (c_type_print_base): Get to the method name by
+ skipping over all the namespaces, classes and '::'.
+
+ * infcmd.c (run_command): Only call SOLIB_RESTART if it's
+ defined.
+ (detach_command): Ditto.
+
+ * infptrace.c (call_ptrace): Add some debugging code.
+
+ * infrun.c (follow_inferior_fork): Only define on HP.
+ (wait_for_inferior): Only call SOLIB_IN_DYNAMIC_LINKER if we have
+ shared libraries; restore test of IN_SOLIB_DYNSYM_RESOLVE_CODE
+ removed by HP.
+
+ * Makefile.in (ALLDEPFILES): Add somread.c, hp-psymtab-read.c,
+ hp-symtab-read.c.
+ (SFILES): Remove the above files
+ (COMMON_OBS): Remove somread.o
+ (SFILES): Add the tui files to this, so they get
+ included in etags tables.
+ (all-tui): New rule, which does a recursive make in the tui
+ subdir.
+ (gdb$(EXEEXT)): Add tui-all to the list of
+ dependencies, and add tui/libtui.a to the link list.
+ (tui/libtui.a): When recursing, pass down
+ ${FLAGS_TO_PASS}. And don't echo the make command. This is
+ closer to what the other recursions do.
+ (HFILES_NO_SRCDIR) add hpread.h.
+ (COMMON_OBS): Add hp-psymtab-read.o, hp-symtab-read.o
+ Allow the TUI code to be conditionally enabled.
+ (TUI_TARGET, TUI_LIBRARY): New variables, whose values are set by
+ the configuration script. They're set to the empty string when
+ the TUI isn't enabled.
+ (gdb$(GDBEXT)): Use those, instead of referring to tui-all and
+ tui/libtui.a directly.
+
+ * Makefile.in: Avoid spurious relinking.
+ (gdb$(EXEEXT)): Depend on the actual tui library, not on a
+ fictitious target. Since the fictitious target never existed, make
+ would always relink.
+ (tui/libtui.a): Renamed from all-tui. Always recurse to make sure
+ the library is up to date.
+ (TUI_TARGET): Variable removed; there's no need for it any more.
+
+ * Makefile.in: Look for tui include files in the tui source dir.
+
+ * Use automake's `aclocal' program to generate aclocal.m4, to allow
+ us to use automake macros in configure.in with impunity.
+
+ * acconfig.h: Add an entry for the `TUI' symbol.
+
+ * acinclude.m4: New file, containing the code from the old
+ aclocal.m4. Incorporate (by reference) ../bfd/acinclude.m4, not
+ ../bfd/aclocal.m4, since we only want bfd's local macros.
+
+ * aclocal.m4: Now automagically generated. Just run aclocal!
+
+ * annotate.c (annotate_catchpoint): New function.
+
+ * annotate.h: Taking the new includes (symtab.h and gdbtypes.h).
+ not taking the ansic C build fix.
+ (annotate_catchpoint): Declare.
+
+ * blockframe.c (blockvector_for_pc_sect): Check that the end of
+ the block is >= to the pc, not just >.
+
+ * breakpoint.c (create_temp_exception_breakpoint): #If it out --
+ nothing calls it.
+ (bpstat_stop_status): Don't call SOLIB_HAVE_LOAD_EVENT if it's not
+ defined; don't call SOLIB_HAVE_UNLOAD_EVENT if it's not defined.
+ (bpstat_get_triggered_catchpoints): If we don't have shared
+ library support, then don't call SOLIB_LOADED_LIBRARY_PATHNAME nor
+ SOLIB_UNLOADED_LIBRARY_PATHNAME.
+ (watch_command_1): Don't require a run before a watch command
+ unless we're on HP [it's an HP OS bug, not a generic limitation]
+ (catch_load_command_1): Don't define if no shared libraries.
+ (catch_command_1): Don't claim to support fork catchpoints unless
+ CHILD_INSERT_FORK_CATCHPOINT is defined, don't claim to support
+ vfork catchpoints unless CHILD_INSERT_VFORK_CATCHPOINT is defined,
+ don't clain to support shared library load catchpoints if shared
+ libraries aren't supported, and don't claim to support exec
+ catchpoints unless CHILD_INSERT_EXEC_CATCHPOINT is defined
+
+ (bpstat_do_actions): If we just set cmd to NULL, don't then try to
+ set it to cmd->next as we'll SEGV.
+ (bpstat_do_actions): Simplify significantly. It's
+ now almost as simple as before the merge and it no longer has the
+ HP bug that breakpoint commands are executed repeatedly.
+
+ (break_at_finish_command_1): Rewrite and make sure
+ selected_frame points to a frame before using it. Fix string
+ termination error.
+ (break_at_finish_at_depth_command_1): Ditto.
+
+ (can_use_hw_watchpoints): New static variable.
+ (read_memory_nobpt): Test for breakpoint type bp_none.
+ (insert_breakpoints): Test for breakpoint type bp_catch_exec;
+ insure have a current frame before getting the frame address.
+ (remove_breakpoints): Check for breakpoints of types bp_none,
+ bp_catch_fork, bp_catch_vfork, and bp_catch_exec.
+ (bpstat_stop_status): Fix updates of b->hit_count.
+ (bpstat_have_active_hw_watchpoints): New function.
+ (create_exec_event_watchpoint): New function.
+ (watch_command_1): Use can_use_hw_watchpoints.
+ (catch_fork_command_1): Change name of function to call from
+ target_create_catch_(v)fork_hook to create_(v)fork_even_catchpoint.
+ (delete_breakpoint): Test for already deleted breakpoints; add
+ support for bp_catch_fork, bp_catch_vfork, and bp_catch_exec
+ breakpoints.
+ (_initialize_breakpoint): Add can-use-hw-watchpoints to list of
+ user settable debugger variables.
+
+ (clear_command): When there is no argument
+ to the clear command, delete all breakpoints that are hit at
+ default line. This will include a breakpoint whose line number
+ does not correspond to the default line, but has been set at
+ the default address.
+
+ (delete_breakpoint): Don't call bpstat_clear_actions, instead
+ clear things explicitly; if clearing breakpoint_at, then also
+ clear any associated actions so that bpstat_do_actions won't try
+ to execute them.
+ (_initialize_breakpoint): Fix function name for bx command.
+
+ (tbreak_command): Remove static from declaration.
+ (maintenance_info_breakpoints): Ditto.
+
+ (reattach_breakpoints): New funct definition, used with with
+ hardware watchpoints
+ (breakpoint_1): Change format and add entries to bptypes[]
+ (maintenance_info_breakpoints): Function is no longer static
+
+ (_initialize_breakpoint): Removed a comment.
+ (exception_catchpoints_are_fragile,
+ exception_support_initialized): Define.
+ (breakpoint_here_p): Fixed syntax error in conditional
+ (disable_watchpoints_before_interactive_call_start): Fixed call to
+ check_duplicates. Need a section parameter.
+ (enable_watchpoints_after_interactive_call_stop): Fixed call to
+ check_duplicates. Need a section parameter.
+ (breakpoint_re_set_one): Fixed call to check_duplicates. Need a
+ section parameter.
+ (delete_command): Fixed syntax error in conditional
+ (breakpoint_re_set): Fixed some typos.
+
+ (args_for_catchpoint_enable): New type for handling exceptions.
+ (current_exception_event): New variable for handling exceptions.
+ (insert_breakpoints): Check for additional breakpoint types --
+ bp_catch_throw, bp_catch_catch, call_disabled. Also, do some
+ additional work to handle an exception catchpoint.
+ (remove_breakpoint): There are additional breakpoint types to
+ check for: Bp_catch_throw, bp_catch_catch, call_disabled. Also do
+ some additional work to remove the exception catchpoints
+ (breakpoint_init_inferior): New input parameter. If there are
+ exception catchpoints delete them.
+ (breakpoint_here_p): There are additional breakpoint enable
+ settings to check for: Shlib_disabled, call_disabled
+ (breakpoint_thread_match): There are additional breakpoint enable
+ settings to check for: Call_disabled
+ (ep_is_catchpoint): There are additional breakpoint types to check
+ for: Bp_catch_throw, bp_catch_catch
+ (ep_is_exception_catchpoint): New function
+ (bpstat_find_step_resume_breakpoint): New function
+ (bpstat_do_actions): Introduce a local copy of the bpstat
+ structure.
+ (print_it_normal): There are additional breakpoint types to check
+ for: Bp_catch_throw, bp_catch_catch Changeing the control
+ structure a bit (adding else ifs) Add code to print out info about
+ exceptions.
+ (bpstat_stop_status): There are additional breakpoint enable
+ settings to check for: Call_disabled. there are additional
+ breakpoint types to chack for: Bp_catch_catch and bp_catch_throw.
+ Check to see if stopped due to an exception. Minor fixes to the
+ catch_errors calls. Make sure to count all encountered
+ breakpoints. There was something funky going on previously with
+ the counting.
+ (bpstat_what): Add cases for new breakpoint types:
+ bp_catch_catch, bp_catch_throw.
+ (bpstat_get_triggered_catchpoints): Check for new breakpoint types
+ : Bp_catch_catch, bp _catch_throw.
+ (breakpoint_1): Account for new breakpoint types.
+ (describe_other_breakpoints): Account for new breakpoint enable
+ setting (call_disabled)
+ (check_duplicates): Account for new breakpoint enable setting
+ (call_disabled)
+ (disable_breakpoints_in_shlibs): New function
+ (disable_watchpoints_before_interactive_call_start): New function
+ (mention): Account for new breakpoint types.
+ (break_command_1): Some additional checking for a valid PC.
+ (watch_command_1): Some dditional checking to prevent a watch
+ before a run command.
+ (ep_parse_optional_filename): Simplified for loop.
+ (create_exception_catchpoint): New function
+ (cover_target_enable_exception_callback): New function
+ (handle_gnu_4_16_catch_command): This used to be thcatch_command_1
+ function.e
+ (create_temp_exception_breakpoint): New function
+ (catch_command_1): Differs from gdb 4.16 and gdb 4.17. Is now
+ calling catch_exception_command_1 using the EX_EVENT_CATCH and
+ EX_EVENT_THROW values as parameters.
+ (clear_command): Additional comments
+ (delete_breakpoint): Handle exceptions. Check for additional
+ breakpoint enable settings: Shlib_disabled, call_disabled.
+ (delete_command): Hp folks are claiming that we should not delete
+ shlib_event breakpoints
+ (breakpoint_re_set_one): Moved call to check_duplicates. Add new
+ breakpoint types to switch statement.
+ (breakpoint_re_set_thread): New function
+ (enable_command): Account for new breakpoint types.
+
+ (insertion_state_t): New enumerated type.
+ (remove_breakpoint): New param in funct prototype.
+ (insert_breakpoints): Check for bp_catch_fork and bp_catch_vfork.
+ (remove_breakpoints): Changed call to remove_breakpoint.
+ (detach_breakpoints): New function.
+ (remove_breakpoint): New parameter, is. Also changed the
+ way b->inserted is set.
+ (ep_is_catchpoint): New function.
+ (ep_is_shlib_catchpoint): New function.
+ (print_it_normal): Check for bp_catch_load, bp_catch_unload,
+ bp_catch_fork, bp_catch_vfork, bp_catch_exec. Also new code
+ to print out catchpoints properly.
+ (bpstat_stop_status): Check for bp_catch_fork, bp_catch_vfork,
+ and bp_catch_exec. Also, some code to check for catching a
+ shared library load/unload.
+ (bpstat_what): Added catch_shlib_event to class enumeration.
+ Defined new macro, shlr. Expanded the bpstat_what_main_action
+ table. Add cases for bp_catch_load, bp_catch_unload,
+ bp_catch_fork, bp_catch_vfork, and bp_catch_exec.
+ (bpstat_get_triggered_catchpoints): New function.
+ (breakpoint_1): Changes to bptypes definition. Also check for
+ bp_catch_load, bp_catch_unload, bp_catch_fork, bp_catch_vfork,
+ bp_catch_exec. Similar changes to the switch statement.
+ (set_raw_breakpoint): Initialize new breakpoint structure fields.
+ dll_pathname, triggered_dll_pathname, forked_inferior_pid,
+ exec_pathname.
+ (create_solib_load_unload_event_breakpoint): New function.
+ (create_solib_load_event_breakpoint): New function.
+ (create_solib_unload_event_breakpoint): New function.
+ (create_fork_vfork_event_catchpoint): New function.
+ (create_fork_event_catchpoint): New function.
+ (create_vfork_event_catchpoint): New function.
+ (mention): New cases for bp_catch_load, bp_catch_unload,
+ bp_catch_fork, bp_catch_vfork, bp_catch_exec.
+ (ep_skip_leading_whitespace): New function.
+ (ep_find_event_name_end): New function.
+ (ep_parse_optional_if_clause): New function.
+ (ep_parse_optional_filename): New function.
+ (catch_fork_kind): New enumerated type.
+ (catch_fork_command_1): New function.
+ (catch_exec_command_1): New function.
+ (catch_load_command_1): New function.
+ (catch_unload_command_1): New function.
+ (catch_throw_command_1): New function.
+ (catch_command_1): Now calls catch_throw_command_1.
+ (tcatch_command): New function.
+ (delete_breakpoint): Changed call to remove_breakpoint.
+ Also free the new fields in the breakpoint structure.
+ (breakpoint_re_set_one): Handle bp_catch_load, bp_catch_unload,
+ bp_catch_fork, bp_catch_vfork, bp_catch_exec.
+ (disable_command): Handle bp_catch_load, bp_catch_unload,
+ bp_catch_fork, bp_catch_vfork, bp_catch_exec.
+ (enable_command): Handle bp_catch_load, bp_catch_unload,
+ bp_catch_fork, bp_catch_vfork, bp_catch_exec.
+ (_initialize_breakpoint): Alter add_com call for catchpoints,
+ add add_com call for watchpoints.
+
+ * breakpoint.h (enum bptype): New entries bp_catch_catch,
+ bp_catch_throw, and bp_none, bp_catch_load, bp_catch_unload,
+ bp_catch_fork, bp_catch_vfork,bp_catch_exec. Add declarations for
+ new functions bpstat_have_active_hw_watchpoints and
+ create_exec_event_catchpoint.
+ (tbreak_command): Add prototype.
+ (update_breakpoints_after_exec): Add prototype; update comments.
+ (reattach_breakpoints): New funct prototype declaration.
+ (enable): New enumerated value call_disabled.
+ (bpstat_find_step_resume_breakpoint): New funct decl.
+ (inf_context): New enumerated type.
+ (breakpoint_re_set_thread): New funct decl.
+ (breakpoint_init_inferior): New parameter.
+ (disable_watchpoints_before_interactive_call_start): New funct decl.
+ (enable_watchpoints_after_interactive_call_stop): New funct decl.
+ (disable_breakpoints_in_shlibs): New funct decl.
+ (struct breakpoint): New fields, dll_pathname,triggered_dll_pathname,
+ forked_inferior_pid,exec_pathname BPSTAT_WHAT_CHECK_SHLIBS_RESUME_FROM_HOOK.
+ (bpstat_get_triggered_catchpoints): New function.
+ (detach_breakpoints): New function.
+ (create_solib_load_event_breakpoint): New function.
+ (create_solib_unload_event_breakpoint) New function.
+ (create_fork_event_catchpoint): New function.
+ (create_vfork_event_catchpoint): New function.
+ (ep_is_catchpoint): New function.
+ (ep_is_shlib_catchpoint) New function.
+ (enum bpstat_what_main_action): New entry.
+
+ * buildsym.c (finish_block): Get rid of processing_hp_compilation;
+ handle LOC_INDIRECT case. Set the BLOCK_GCC_COMPILED to the right
+ compiler.
+ (push_context): Add symbols for parameters to the context_stack.
+ (merge_symbol_lists): New function. Merges two symbol lists.
+ (struct context_stack): Add new field param.
+
+ (processing_hp_compilation): New external var.
+
+ * c-exp.y: Use external flag hp_som_som_object_present to decide
+ whether code was compiled by HP's compilers. Add two new C++
+ tokens for true and false.
+ (yylex): Check for template name is done differently for the
+ HP/aCC compiler case; change some of the template processing code
+ for handling HP aCC templates.
+
+ * c-lang.c (c_create_fundamental_type): Added case to handle
+ template args. Handle FT_BOOLEAN type. Set no sign flag for
+ FT_CHAR.
+ (cplus_builtin_types): New structure for c++ builtin types.
+ (cplus_language_defn): Use cplus_builtin_types instead of
+ c_builtin_types.
+
+ * c-typeprint.c (c_type_print_base): Don't print 'privete' label
+ for a class if all members are private, similarly don't print
+ 'public' for a struct. Add support for sized enums (HP/aCC). get
+ rid of the 'static' keyword printed by the demangler for member
+ function, when printing the type of a class. 'static' will be
+ added by this function. If the demangled name is null, and the
+ method is not stubbed, get the signature by looking at the
+ information stored in the symbol structure. Remove printing of
+ 'const' and 'volatile' keywords for methods. This is now taken
+ care as part of the demangled member names.
+ (cp_type_print_method_args): New function. To print a C++ method
+ arguments and name to the output stream.
+
+ (c_type_print_cv_qualifier): New function. Print out "const" and
+ "volatile" attributes.
+ (c_type_print_varspec_prefix): Print const or volatile qualifiers.
+ (c_type_print_args): Print 'void' for c++.
+ (c_type_print_varspec_suffix): Print 'void' for a no argument
+ function.
+ (c_type_print_base): Print const or volatile qualifiers. Do not
+ print 'unnamed union' if HP aCC compiler used. Distinguish
+ between struct and class based on the DECLARED_TYPE. Handle
+ HP/aCC compiler case for not printing vtable. Add Template
+ support.
+
+ (cp_type_print_derivation_info): Print out 'protected' when
+ appropriate. This applies only to HP's compilers, not gcc.
+
+ (c_val_print): Added parameter embedded_offset. Add
+ embedded_offset to valaddr in function calls; fix calls to
+ val_print and cp_print_value_fields. process TYPE_CODE_METHOD as
+ well. moved call to check_typedef out of conditional. added
+ embedded offset param to val_print call.
+
+ (c_value_print): Add new parameter to call to val_print.
+ handle pointer to class case. Attempt to
+ determine the real type of the object to be printed.
+ ensure that const char *, const unsigned char *
+ come out without the type but the volatile variants
+ and the signed variants don't.
+
+ * coff-solib.c (coff_solib_add): Add parameters to call
+ to symbol_file_add.
+
+ * coff-solib.h: (Solib_REMOVE_INFERIOR_HOOK): New macro. defined
+ to 0. functionality not implemented for coff.
+ (SOLIB_CREATE_CATCH_LOAD_HOOK): New macro, generate error message
+ for coff.
+ (SOLIB_CREATE_CATCH_UNLOAD_HOOK): Ditto.
+ (SOLIB_HAVE_LOAD_EVENT): Ditto.
+ (SOLIB_LOADED_LIBRARY_PATHNAME): Ditto.
+ (SOLIB_HAVE_UNLOAD_EVENT): Ditto.
+ (SOLIB_UNLOADED_LIBRARY_PATHNAME): Ditto.
+ (SOLIB_IN_DYNAMIC_LINKER): Ditto.
+ (SOLIB_RESTART): Ditto.
+
+ * command.c (find_cmd): New function. (lookup_cmd_1): Call it,
+ change parsing if tui_version or xdb_commands is set.
+ (_initialize_command): Install new alias if xdb_commands is set.
+
+ * complaints.h: Add ifdef...endif pair at beginning and end of file.
+
+ * config.in, configure: Regenerated.
+
+ * config/pa/hppabsd.mh (NATDEPFILES): Added new files
+ hp-psymtab-read.o and hp-symtab-read.o.
+ * config/pa/hppahpux.mh (NATDEPFILES): Ditto.
+
+ * config/pa/hppahpux.mh (TERMCAP): Use -lHcurses.
+ * config/pa/hppaosf.mh (NATDEPFILES): Ditto.
+
+ * config/pa/hpux1020.mh (TERMCAP): Use -lHcurses.
+ (MH_CFLAGS): New flag, -D__HP_CURSES, this define
+ is used by HP's linker to find the correct curses library.
+
+ * config/pa/hpux1020.mh: New file.
+
+ * config/pa/hpux1020.mt: New file.
+
+ * config/pa/hpux1100.mh (TERMCAP): Link against -lcurses, not
+ -lHcurses. The latter does not contain mvwaddstr, wscrl, or
+ wstbwlmkfzz.
+
+ * config/pa/hpux1100.mh (TERMCAP): Use -lHcurses.
+ (MH_CFLAGS): New flag, -D__HP_CURSES, this define
+ is used by HP's linker to find the correct curses library.
+
+ * config/pa/hpux1100.mh (TERMCAP): When hosting on hpux 11.00, use
+ -lHcurses rather than -lcurses.
+
+ * config/pa/hpux1100.mh: New file.
+
+ * config/pa/hpux1100.mt: New file.
+
+ * config/pa/nm-hppah.h (CHILD_HAS_SYSCALL_EVENT): New macro
+ (CHILD_THREAD_ALIVE): New macro
+ (STOPPED_BY_WATCHPOINT): Add a condition to the macro,
+ ! stepped_after_stopped_by_watchpoint
+ (TARGET_ENABLE_HW_WATCHPOINTS): New macro
+ (hppa_enable_hw_watchpoints): New funct decl
+ (TARGET_DISABLE_HW_WATCHPOINTS): New macro
+ ( hppa_disable_hw_watchpoints): New funct decl
+ these are for HP's implementation of fast
+ watchpoints (via page protection).
+ (target_pid_to_str): New macro, calls hppa_pid_to_str
+ (target_tid_to_str): New macro, calls hppa_tid_to_str
+
+ * config/pa/nm-hppah.h (CHILD_POST_WAIT): Delete;
+ (CHILD_CREATE_CATCH_FORK_HOOK): Replace with
+ CHILD_INSERT_FORK_CATCHPOINT and CHILD_REMOVE_FORK_CATCHPOINT.
+ (CHILD_CREATE_CATCH_VFORK_HOOK): Replace with
+ CHILD_INSERT_VFORK_CATCHPOINT and CHILD_REMOVE_VFORK_CATCHPOINT.
+ (CHILD_CAN_FOLLOW_VFORK_PRIOR_TO_EXEC,
+ CHILD_INSERT_EXEC_CATCHPOINT, CHILD_REMOVE_EXEC_CATCHPOINT,
+ CHILD_HAS_EXECD, CHILD_REPORTED_EXEC_EVENTS_PER_EXEC_CALL,
+ CHILD_POST_ATTACH, TARGET_HAS_HARDWARE_WATCHPOINTS,
+ TARGET_CAN_USE_HARDWARE_WATCHPOINT,
+ TARGET_REGION_SIZE_OK_FOR_HW_WATCHPOINT,
+ TARGET_RANGE_PROFITABLE_FOR_HW_WATCHPOINT, STOPPED_BY_WATCHPOINT,
+ HAVE_NONSTEPPABLE_WATCHPOINT, target_insert_watchpoint,
+ target_remote_watchpoint): New macros.
+
+ * config/pa/nm-hppah.h (CHILD_XFER_MEMORY): Reinsert accidentally
+ deleted define.
+
+ * config/pa/nm-hppah.h:
+ (PREPARE_TO_PROCEED): Defined macro to use
+ hppa_prepare_to_proceed.
+ (hppa_pid_to_str): Extern decl.
+ (hppa_tid_to_str): Extern decl.
+ (target_pid_or_tid_to_str): New macro definition.
+ (hppa_pid_or_tid_to_str): Extern decl.
+ (ENSURE_VFORKING_PARENT_REMAINS_STOPPED): New macro - for
+ handling events caused by a call to vfork.
+ (hppa_ensure_vforking_parent_remains_stopped): Extern decl.
+ (RESUME_EXECD_VFORKING_CHILD_TO_GET_PARENT_VFORK): New macro -
+ for handling events caused by a call to vfork.
+ (hppa_resume_execd_vforking_child_to_get_parent_vfork): Extern decl.
+
+ * config/pa/nm-hppah.h: Fix PREPARE_TO_PROCEED macro.
+
+ * config/pa/nm-hppah.h: Fix for gcc compile on HPUX, change
+ PT_RDUAREA to PT_RUAREA.
+
+ * config/pa/nm-hppah.h: Introduced an HPUXHPPA define.
+ A bit of a hack so that I can ifdef some code that
+ only works for the HP wildebeest debugger.
+
+ * config/pa/nm-hppah.h: Lots of new CHILD_ defines;
+ process_event_kind enum.
+
+ * config/pa/tm-hppa.h (BREAKPOINT32): New define.
+ (CALL_DUMMY_HAS_COMPLETED): New define.
+
+ * config/pa/tm-hppa.h (STACK_ALIGN): New macro.
+ (NO_EXTRA_ALIGNMENT_NEEDED): New macro.
+ (PC_REQUIRES_RUN_BEFORE_USE): New macro.
+ (REGISTER_NAMES): Formatting in file changed.
+ (CR27_REGNUM): Base register for thread local storage.
+ (USE_STRUCT_CONVENTION): New macro used to decide whether
+ a function returning a value of type type will
+ put it on the stack or into registers (based on the
+ PA risc calling conventions).
+ (EXTRACT_RETURN_VALUE): Fixed calculation for extracting return value.
+ (VALUE_RETURNED_FROM_STACK): New macro.
+ (TARGET_READ_PC): Declared the function used in the definition.
+ (SKIP_TRAMPOLINE_CODE): Declared the function used in the definition.
+ (TARGET_WRITE_PC): Declared the function used in the definition.
+ (TARGET_READ_FP): Declared the function used in the definition.
+
+ * config/pa/tm-hppa.h (STRCAT_REGISTER): Define macro for
+ future use.
+ (pa_do_strcat_registers_info): Moved function decl from
+ defs.h to this HPUX specific .h file.
+
+ * config/pa/tm-hppa.h (USE_STRUCT_CONVENTION): Type_LENGTH returns
+ bytes, not bits; fix off by 8 error.
+
+ * config/pa/tm-hppa.h:
+ New comment for obj_unwind_info definition
+ New typedef, obj_private_struct
+
+ * config/pa/tm-hppa.h: Delete most target_ macros -- use default
+ versions instead; remove extraneous comma from proc_wait macro.
+
+ * config/pa/tm-hppa.h: Get rid of macro HP_COMPILED_TARGET.
+
+ * config/pa/tm-hppa.h: Removed redefinitions of
+ USE_STRUCT_CONVENTION and STACK_ALIGN macros.
+
+ * config/pa/tm-hppa.h: Some new definitions
+ New macros: Arg0_REGNUM, ARG1_REGNUM, ARG2_REGNUM, ARG3_REGNUM.
+ target_pid_to_exec_file, target_acknowledge_forked_child,
+ target_create_catch_fork_hook, target_create_catch_vfork_hook,
+ target_has_forked, target_has_vforked, require_attach,
+ require_detach, proc_wait
+ New funct decls: Hppa_pid_to_exec_file,
+ hppa_acknowledge_forked_child, hppa_create_catch_fork_hook,
+ hppa_create_catch_vfork_hook, hppa_target_has_forked,
+ hppa_target_has_vforked, hppa_require_attach,
+ hppa_require_detach, process_wait
+ (unwind_table_entry): Added comments to describe struct fields.
+
+ * config/pa/tm-hppah.h (somsolib.h): Include it.
+
+ * config/pa/tm-hppah.h:
+ (CHILD_ENABLE_EXCEPTION_CALLBACK): New define
+ (CHILD_GET_CURRENT_EXCEPTION_EVENT): New define
+
+ * configure.host (hppa-*-hpux10.20, hppa-*-hpux11.0*): New configs.
+
+ * configure.in (AC_CHECK_HEADERS): Add check for term.h.
+
+ * configure.in: Add an --enable-tui argument.
+
+ * configure.in: Construct tui/Makefile from tui/Makefile.in.
+
+ * configure.in: Use AM_PROG_CC_STDC. If we have the GUI, then we
+ need this to process libgui.h.
+
+ * convex-tdep.c (decout): Change FILE to GDB_FILE.
+
+ * corefile.c: Include objfiles.h, symfile.h.
+ (core_file_command): Attempt to determine the name of the symbol
+ file from the core file.
+ (read_memory_string): New function.
+
+ * corefile.c (core_file_command): Temporary hack to make non-hpux
+ work. For, non-hpux, t->to_core_file_to_sym_file does not have a
+ reasonable value. No target_ops vector on the stack gives it a
+ non-zero value. fix later.
+
+ * corelow.c (core_file_to_sym_file): Added new local variable,
+ failing command, and do some explicit type castings.
+ (core_ops): Add three new fields: to_has_syscall_event,
+ to_enable_exception_callback, to_get_current_exception_event.
+ Necessary since we still have oldstyle initialization in
+ this file
+
+ * corelow.c: Include unistd.h
+ (core_file_to_sym_file): New function
+ (core_file_thread_alive): New function
+ (core_ops): Added new target ops vector fields. see below. And
+ yes we definitiely need to initialize them here, as long as
+ we're using static initialization.
+
+ * cxux-nat.c (add_shared_symbol_files): Additonal params for calls
+ to symbol_file_add.
+
+ * defs.h (gdb_file_isatty): New function decl.
+
+ * defs.h (GDB_FILE): If TUI is defined, define a structure rather
+ than making this an alias for FILE.
+ (gdb_stdout, gdb_stderr): If TUI is defined, then define these
+ as pointers to variables of type GDB_FILE rather than making them
+ be aliases for stdout and stderr.
+
+ * defs.h (TUIDO): Add definition conditionalized on definition
+ (or lack thereof) of TUI.
+
+ * defs.h (command_class): Add two additional values.
+ (precision_type): New enum.
+
+ * defs.h (gdb_fclose): Add declaration.
+
+ * defs.h (store_address): Change prototype to match function.
+
+ * defs.h (tui_version, xdb_commands, dbx_commands): Add decl's.
+
+ * defs.h (gdb_file_deallocate): New function declaration
+
+ * defs.h:
+ (streamtype): New enumerated type to distinguish between
+ output to a FILE and output to a buffer.
+ (tui_stream): New struct type, named GDB_FILE. Contains,
+ streamtype, FILE, buffer, and bufferlength fields.
+ (gdb_stdout): Of type GDB_FILE, will pass this around gdb
+ rather than stdout.
+ (gdb_stderr): Of type GDB_FILE, will pass this around gdb
+ rather than stderr.
+ (fputs_unfiltered_hook): Change stream parameter from FILE to
+ GDB_FILE
+ (flush_hook): Change stream parameter from FILE to GDB_FILE
+ (gdb_fclose): Fix declaration for gdb_fclose; parameter is now of
+ type GDB_FILE **
+ (gdb_file_adjust_strbuf): New function declaration. function lives in
+ utils.c.
+ (gdb_file_init_astring): New function declaration. function lives
+ in utils.c
+ (gdb_file_get_strbuf): New function declaration. function lives
+ in utils.c
+
+ * defs.h: Additional include files included when TUI is defined.
+
+ * defs.h: Funct decl source_full_path_of.
+
+ * demangle.c: Add HP_DEMANGLING_STYLE_STRING.
+
+ * demangle.c: Added new demangling style, EDG_DEMANGLING_STYLE_STRING,
+ to the demanglers structure. This is for support of
+ Kuck & Assoc.'s changes for demangling.
+
+ * eval.c (evaluate_subexp_standard): C++ member function changes.
+
+ * eval.c (evaluate_subexp_standard): Verify TYPE_TARGET_TYPE is
+ non NULL before dereferencing it.
+
+ * eval.c (evaluate_subexp_standard): With HP/aCC compiler it is not possible
+ to perform inferior calls via function pointers.
+ Resolve calls to overloaded functions using find_overload_match.
+ We cannot handle HP/aCC pointers to member functions.
+ Deal with HP/aCC pointers to members in various kind of expressions.
+
+ * f-lang.c (f_printchar): Change FILE to GDB_FILE.
+ (f_printstr): Ditto.
+ (emit_char): Ditto.
+
+ * f-lang.c (f_printstr): Change stdout to gdb_stdout.
+
+ * f-typeprint.c (f_print_type): Change FILE to GDB_FILE.
+ (f_type_print_varspec_prefix): Ditto.
+ (f_type_print_args): Ditto.
+ (f_type_print_varspec_suffix): Ditto.
+ (print_equivalent_f77_float_type): Ditto.
+ (f_type_print_base): Ditto.
+
+ * findvar.c (): Hp snapshot 3 changes. (extract_address): Coerce
+ return value from extract_unsigned_integer to CORE_ADDR.
+ (store_address): Change val from CORE_ADDR to LONGEST; changes to
+ support machines where CORE_ADDR and LONGEST are different sizes.
+ (get_saved_register): Coerce arg to store_address to LONGEST.
+ (read_relative_register_raw_bytes): Cast last arg to
+ store_address to LONGEST. (read_register): Cast return from
+ extract_address to a CORE_ADDR. (write_register_pid): Change val
+ from LONGEST to CORE_ADDR. (read_pc_pid): Save and restore
+ inferior_pid if necessary. (write_pc_pid): Ditto.
+ (read_var_value): Cast arg to store_address.
+
+ * findvar.c (read_relative_register_raw_bytes_for_frame): New
+ function.
+ (read_relative_register_raw_bytes): Call it.
+
+ * findvar.c (symbol_read_needs_frame): Handle LOC_THREAD_LOCAL_STATIC and
+ LOC_INDIRECT.
+
+ * fork-child.c (fork_inferior): Chenge fifth parameter to be a
+ function returning void.
+
+ * fork-child.c (fork_inferior): Delete unused variable f.
+
+ * fork-child.c:
+ (Startup_WITH_SHELL): New macro -- interim fix for a bug
+ (breakup_args): New function -- breaks up an argument string into
+ an argument suitable for passing into execvp().
+ (fork_inferior): Handling problems with starting up gdb with a shell.
+ -- again, this appears to be an interim fix.
+
+ * fork-child.c:
+ (fork_inferior): Added a comment
+ (clone_and_follow_inferior): New function.
+ (startup_inferior): Minor formatting changes.
+
+ * fork-child.c:
+ (fork_inferior): Hp change is problematic. The -f option has
+ different meanings for different shells. It is particularly
+ inappropriate for bourne shells.
+
+ * fork-child.c:
+ (fork_inferior): Added new parameter, pre_trace_fun.
+ pre_trace_fun is a function pointer. For some targets,
+ like HPUX, this function gets called to prepare for forking
+ a child.
+
+ * fork-child.c:
+ (fork_inferior): Fixed call to init_trace_fun
+
+ * fork-child.c:
+ Moved definition of STARTUP_WITH_SHELL to inferior.h
+ Added a DEBUGGING macro. Currently set to 0. May remove
+ later.
+ breakup_args: Add DEBUGGING ifdefs. more sophisticated
+ parsing to break up args.
+ (fork_inferior): Rename kshell variable to shell. new local
+ variable, tryname. Make use of STARTUP_WITH_SHELL macro.
+ More error processing if starting up with a shell.
+ (startup_inferior): Distinguish between starting up with a shell
+ and not doing so.
+
+ * gdbthread.h:
+ Declarations for load_infrun_state and save_infrun_state take
+ an additional parameter.
+
+ * gdbthread.h: Note that sometime between gdb 4.16 and 4.17,
+ thread.h was renamed gdbthread.h
+ (load_infrun_state): Additional parameters
+ (store_infrun_state): Additional parameters
+
+ * gdbthread.h: Include breakpoint.h
+
+ * hp-psymtab-read.c (QUICK_LOOK_UP): Redefine to be 0.
+ (hpread_build_psymtabs): Deal with enums.
+ (hpread_start_psymtab): Include section offset.
+ (hpread_end_psymtab): Take care of offset.
+
+ * hp-psymtab-read.c (TRUE): Define.
+ (FALSE): Define.
+ (file_exists): New function. Checks for existance of file.
+ (hpread_pxdb_needed): Rewrite.
+ (hpread_quick_traverse): Use correct demangling style.
+ Handle F77 case.
+ (hpread_get_header): Rewrite.
+ (hpread_get_textlow): Add support for DOC_FUNCTION.
+ (hpread_build_psymtabs): Make sure we do the right thing
+ for pxdb and F77.
+
+ * hp-psymtab-read.c (hpread_pxdb_check): Change parenthesis positions.
+
+ * hp-psymtab-read.c (hpread_quick_traverse): Compare CORE_ADDR
+ variable end_addr to 0 instaed of NULL to get rif of gcc warning.
+
+ * hp-psymtab-read.c:
+ (Hpread_get_textlow): Added param to function
+ Defined convennience macros and some datatypes and variables for
+ processing the quick lookup-tables. Looks like the code existed
+ before, but has been munged.
+ (hpread_pxdb_needed): Major rearrangements of code. Additional local
+ variables. Also, more extensive checking for various scenarios:
+ debug info for optimized code vs. unoptimized code, pxdb has been
+ run vs. pxdb has not been run.
+ (VALID_FILE): New macro
+ (VALID_MODULE): New macro
+ (VALID_PROC): New macro
+ (VALID_CLASS): New macro
+ (FILE_START): New macro
+ (MODULE_START): New macro
+ (PROC_START): New macro
+ (FILE_END): New macro
+ (MODULE_END): New macro
+ (PROC_END): New macro
+ (FILE_ISYM): New macro
+ (MODULE_ISYM): New macro
+ (PROC_ISYM): New macro
+ (VALID_CURR_FILE): New macro
+ (VALID_CURR_MODULE): New macro
+ (VALID_CURR_PROC): New macro
+ (VALID_CURR_CLASS): New macro
+ (CURR_FILE_START): New macro
+ (CURR_MODULE_START): New macro
+ (CURR_PROC_END): New macro
+ (CURR_FILE_ISYM): New macro
+ (CURR_MODULE_ISYM): New macro
+ (CURR_PROC_ISYM): New macro
+ (TELL_OBJFILE): New macro
+ (pst_syms_struct): New typedef to keep track of the start/end symbol
+ table (LNTT) indices of psymtabs created so far.
+ (pst_syms_count): New variable
+ (pst_syms_size): New variable
+ (told_objfile): New variable
+ (init_pst_syms): New function. sets up psymtab symbol index stuff.
+ (clear_pst_syms): New function. clean up psymtab symbol index stuff.
+ (record_pst_syms): New function. add info about newest psymtab to symbol
+ index table.
+ (find_next_pst_start): New function. Find a suitable symbol table index.
+ (find_next_file_isym): New function
+ (find_next_proc_isym): New function
+ (find_next_module_isym): New function
+ (scan_procs): New function. Scan and record partial symbols for all
+ functions starting from specified index and in a specified code range.
+ (hpread_quick_traverse: Major rearrangement of code. The function
+ now uses all the nifty macros. There are some new local variables.
+ Check for EDG_DEMANGLING style. ifdef out some code for handling F77.
+ Previously, the function looped over all the modules in the table.
+ Now, the function loops over all the files, modules, and procedures.
+ With HP aCC and CTTI, it is possible for a compiled object to have a
+ file and no module.
+ (hpread_build_psymtabs): Added a section of code ifdefed by
+ QUICK_LOOK_UP. It check to see whether or not there are any globals
+ in the executable. Fix number of params to hpread_start_psymtab call.
+ Some changes to the way DNTT_TYPE_MODULE is handled.
+ (hpread_get_textlow): Change in signature, minor code changes. The
+ function finds the low address associated with a specified symbol.
+ In looking for the address for the symbol avoid going of the end of
+ the LNTT file.
+
+ * hp-psymtab-read.c: Change TRUE to 1 and FALSE to 0. Do some
+ reformatting.
+
+ * hp-psymtab-read.c: Include demangle.h
+ (trans_lang): New function to let gdb know the correct language.
+ (hpread_quick_traverse): Use ARM style demangling.
+ Demangle procedures names.
+ Use gdb language names instead of hp language names.
+ Add symbol to list using its demangled name.
+
+ * hp-psymtab-read.c: New file.
+ (hpread_call_pxdb): New function. Call PXDB to process our file.
+ (hpread_pxdb_check): New function. Return TRUE if the file needs
+ pre-processing by PXDB and we have thus called PXDB to do this
+ processing and the file needs to be re-loaded.
+ (hpread_quick_traverse): New function. Traverse the quick look-up
+ tables, building a set of psymtabs.
+ (hpread_get_header): New function. Get appropriate header from obj
+ file, based on pxdb type
+ (hpread_symfile_init): No change from hpread.c
+ (hpread_build_psymtabs): If there are quick lookup tables, read those,
+ then scan the global section LNTT. Otherwise, just scan the whole LNTT.
+ Changed: Add a global function entry to the global partial symbol list.
+ Handle end of symbols, for QLT case.
+ In case of TAGDEF, if it is a class or a template, add the name to the
+ var_namespace, so that it is known as a type by gdb.
+ In case of CONSTANT, and it is global, add it to the globals.
+ (hpread_symfile_finish): No change from hpread.c
+ (hpread_get_lntt): Make it not static
+ (hpread_get_gntt): No change from hpread.c
+ (hpread_get_slt): Make it not static
+ (hpread_get_textlow): No change from hpread.c
+ (hpread_start_psymtab): No change from hpread.c
+ (hpread_end_psymtab): No change from hpread.c
+
+ * hp-symtab-read.c (hpread_get_scope_start): Renamed. It was
+ hpread_get_depth.
+ (hpread_type_translate): Distinguish between signed and unsigned char
+ types.
+ (hpread_psymtab_to_symtab): Set flag for hp compilation.
+ (hpread_read_function_type): Append symbols for parameters to local
+ list as well as to the global list. Get the parameters types from the
+ local list instead of the global list.
+ (hpread_read_struct_type): Add new field num_fn_fields to next_fn_field
+ structure. Rewrite handling of templates
+ (hpread_type_lookup): Change handling of dntt_type_modifier.
+ (hpread_process_one_debug_symbol): Call hpread_get_scope_start instea
+ of hpread_get_depth. Handle enum as well.
+ (hpread_get_scope_depth): New function. Get nesting depth for a
+ DNTT entry.
+
+ * hp-symtab-read.c (hpread_psymtab_to_symtab): Set
+ processing_gcc_compilation to 0.
+
+ * hp-symtab-read.c (hpread_psymtab_to_symtab_1): Change stdout to
+ gdb_stdout; change fflush to gdb_flush.
+ (hpread_psymtab_to_symtab): Change fflush to gdb_flush.
+
+ * hp-symtab-read.c (hpread_read_enum_type): Declare variable.
+ (hpread_read_struct_type): Eliminate references
+ to 'args' member of fn_field.
+
+ * hp-symtab-read.c (hpread_read_struct_type): A static member
+ is now indicated by the bitsize field, not the bitpos.
+ Initialize physname to empty.
+ (fix_static_member_physnames): Use new macros to deal with
+ physnames.
+
+ * hp-symtab-read.c (hpread_read_struct_type): Change references
+ to bitpos member of struct field to use the FIELD_BITPOS macro.
+
+ * hp-symtab-read.c (hpread_read_struct_type): Comment out reference to
+ obsolete field fn_field.args.
+ Add struct complaint definitions for complaints.
+ (hpread_read_struct_type): Change call to complain.
+ (hpread_read_array_type): Change call to complain.
+ (hpread_type_lookup): Change call to complain.
+ (hpread_process_one_debug_symbol): Change calls to complain.
+ (hpread_type_translate): Change calls to complain.
+
+ * hp-symtab-read.c (hpread_read_struct_type): Make sure bitvector
+ has been allocated before calling has_vtable.
+
+ * hp-symtab-read.c (hpread_read_struct_type): Revert change,
+ just check for vtable without checking for bitvectors too.
+
+ * hp-symtab-read.c:
+ (Hpread_expand_symtab): Change name of local variable from
+ at_end_of_module to at_module_boundary.
+ Also, if demangling style is already EDG, do not reset it
+ to the HP demangling style.
+ Change at_end_of_module param to hpread_process_one_debug_symbol
+ call to at_module_boundary.
+ No longer break out of loop when reach end of module. With CTTI,
+ the compiler can generate function symbols which are not in
+ any module. Typically they show up after the end of one
+ module and before the start of the next module.
+ (hpread_read_struct_type): Check that the debug info for
+ a TEMPLATE_ARG is correct.
+ (hpread_process_one_debug_symbol): Change name of at_end_of_module_p
+ param to at_module_boundary_p.
+ Also set *at_module_boundary_p = -1 if missing a module end and set
+ it to 1 when finished expanding the debug info.
+ Handle TLS variable.
+
+ * hp-symtab-read.c: Include defs.h, symtab.h, gdbtypes.h, complaints.h.
+ (fixup_class): New static variable.
+ (fixup_method): New static variable.
+ (hpread_get_location): Rewrite.
+ (hpread_has_name): Add cases for DNTT_TYPE_DOC_FUNCTION and
+ DNTT_TYPE_DOC_MEMFUNC
+ (hpread_expand_symtab): Use HP demangling style.
+ Set hp_som_som_object_present to 1.
+ (hpread_type_translate): Error out if not immediate. Issue warning
+ if there is an unhandled type code.
+ (error_in_hpread_type_translate_complaint): Remove this structure.
+ (hpread_read_enum_type): Don't assume size of enum is always 4 bytes.
+ (hpread_read_function_type): Add new parameter to indicate a new block.
+ Do not add the parameters to the symbol list.
+ If the type was read in earlier, do not modify the type structure.
+ If we are creating a new block, set the local symbol list to be the
+ param list.
+ Need to mark this type as preprocessed.
+ (hpread_read_doc_function_type): New function. Read and internalize
+ a native DOC function debug symbol.
+ (hpread_read_struct_type): A method can be of type doc_function and
+ doc_memfunc too.
+ Handle case in which a method is read before its class. Deal with
+ incomplete method types.
+ Handle cases in which HP/aCC compiler creates operator names w/o
+ the 'operator' keyword. Rewrite the loop over the fileds.
+ (fix_static_member_physnames): New function. Adjust the physnames for
+ each static member.
+ (fixup_class_method_type): New function. Fix-up the type structure for a
+ class.
+ (hpread_read_array_type): Change complaint to warning.
+ (hpread_type_lookup): Add case for DNTT_TYPE_DOC_FUNCTION.
+ For structures/classes set static member to point to strings with full
+ names.
+ Change calls to hpread_read_function_type to pass extra parameter.
+ (hpread_record_lines): Handle case for SLT_NORMAL_OFFSET.
+ (class_of): New function. Given a function "f" which is a member of a class,
+ find the classname that it is a member of.
+ (hpread_process_one_debug_symbol): Deal with possible alias field from the
+ som record for the Function or Entry type.
+ Do the demangling ourselves if the gdb demangler failed.
+ Add support for DOC functions.
+ For function types, add parameters to local list.
+ (hpread_get_scope_depth): Make this function a no-op.
+ (hpread_adjust_bitoffsets): New function. Adjust the bitoffsets for all
+ fields of an anonymous union.
+ (hpread_get_next_skip_over_anon_unions): New function. Skip over anonymous
+ unions.
+
+ * hp-symtab-read.c: Include demangle.h
+ (hpread_expand_symtab): Ensure we are using ARM-style demangling.
+ (hpread_process_one_debug_symbol): Set the mangled and demangled
+ names for functions.
+ Record the class name to generate the demangled names of member
+ functions.
+
+ * hp-symtab-read.c: New file.
+ (hpread_get_depth): No change from hpread.c
+ (hpread_get_line): No change from hpread.c
+ (hpread_get_location): No change from hpread.c
+ (hpread_has_name): Make it not static. Return 1 for DNTT_TYPE_BLOCKDATA
+ and DNTT_TYPE_MEMFUNC. Return 0 for CLASS_SCOPE, REFERENCE,PTRMEM,
+ PTRMEMFUNC, CLASS, GENFIELD, VFUNC, MEMACCESS, INHERITANCE,
+ FRIEND_CLASS, FRIEND_FUNC, MODIFIER, OBJECT_ID, TEMPLATE, TEMPLATE_ARG,
+ FUNC_TEMPLATE, LINK.
+ (hpread_psymtab_to_symtab_1): No changes from hpread.c
+ (hpread_psymtab_to_symtab): Make it a static function
+ (hpread_expand_symtab): Modified
+ (hpread_type_translate): If not typep.dntti.immediate do not abort,
+ but complain and return. Same for default action. Handle more HP_TYPEs.
+ (hpread_lookup_type): Initially allocate a correct-size type-vector.
+ (hpread_alloc_type): Reset type_addr only if a type was allocated.
+ (hpread_read_enum_type): If this has already a type associated, return.
+ (hpread_read_function_type): Do different things depending on whether
+ function is a MEMFUNC, a TEMPLATE, a FUNCTION som record.
+ Do not use the LOC_REGPARM_ADDR symbol class.
+ (hpread_read_struct_type): Handle classes and templates too. Major
+ rewrite.
+ (hpread_get_nth_template_arg): New function.
+ (hpread_read_templ_arg_type): New function.
+ (hpread_read_set_type): No change from hpread.c
+ (hpread_read_array_type): Modified
+ (hpread_read_subrange_type): Add handling of more DNTT entries.
+ added support for templates, classes, references, virtual functions.
+ (hpread_type_lookup): Handle DNNT_TYPE_MODULE.
+ (hpread_record_lines): No changes from hpread.c
+ (hpread_process_one_debug_symbol): Handle WITH, COMMON,
+ CLASS_SCOPE. Expand TAGDEF case to handle classes and templates.
+
+ * hppa-tdep.c (pa_do_strcat_registers_info): Has a new parameter,
+ precision, which is passed into the call to pa_strcat_fp_reg to
+ indicate whether to display the floating point registers using
+ single or double preceision.
+ (pa_strcat_registers): Introduce local variable, precision, and
+ pass it into call to pa_strcat_fp_reg.
+ (pa_strcat_fp_reg): Modified function. New parameter, precision,
+ used by function to decide whether to use single or double
+ precision. Also added the code to put a double precision value
+ into a buffer.
+
+ * hppa-tdep.c: Add'l includes <machine/save_state.h>,
+ <unistd.h>, declare pa_register_look_aside, define is_pa_2.
+ (rp_saved): Check for where to read the return pointer from.
+ (pa_do_registers_info): Handle is_pa_2. (pa_register_look_aside):
+ new function. (pa_print_registers): Handle is_pa_2.
+ (in_solib_call_trampoline): Handle a compiler/linker error.
+ (skip_trampoline_code): Changes to some masks used in examining
+ instructions. (inst_saves_fr): Test for FSTWS instruction.
+ (skip_prologue): Renamed to skip_prologue_hard_way.
+ (after_prologue): New function. (skip_prologue): New function.
+
+ * hppa-tdep.c (after_prologue): If f is NULL, don't dereference
+ it.
+
+ * hppa-tdep.c (after_prologue): If no debug info, return zero
+ telling caller that we need to find the end of the prologue via
+ the hard way (instruction examination).
+
+ * hppa-tdep.c (find_unwind_entry): Avoid dereferencing a null
+ pointer.
+
+ * hppa-tdep.c (hppa_pid_to_exec_file): Deleted -- no longer used.
+
+ * hppa-tdep.c (hppa_prepare_to_proceeed): Add prototype.
+ (read_unwind_info): Purecov comments, bug fixes.
+ (find_unwind_entry): Purecov comments, bug fixes.
+ (find_stub_with_shl_get): Purecov comments.
+ (frame_chain): Additional parens.
+ (hppa_push_arguments): Changes to commented out version of routine.
+ (hppa_fix_call_dummy): Purecov comments, fix location of end.o.
+ (in_solib_call_trampoline): Purecov comments.
+ (in_solib_return_trampoline): Purecov comments.
+ (setup_d_pid_in_inferior): Fix location of end.o.
+ (initialize_hp_cxx_exception_support): Fix location of end.o.
+ (child_enable_exception_callback): Purecov comments.
+
+ * hppa-tdep.c:
+ (Pa_do_strcat_registers_info): New routine. called by
+ tui/tuiRegs.c:_tuiRegisterFormat to place a register name
+ and value into a string buffer. Interface may change in
+ future. Checking this in so that we have something
+ functional for HP.
+ (pa_strcat_registers): New routine, called by
+ pa_do_strcat_registers_info. Does same thing as
+ pa_print_registers except it takes a stream parameter.
+ This routine should disappear in future. Checking in
+ so that we have something functional to give HP
+ (pa_strcat_fp_reg): New routine, called by
+ pa_do_strcat_registers_info and pa_strvat_registers
+ to place a floating point register name and value into
+ a buffer. This interface may change in future.
+ Checking in so that we have something functional to give HP.
+
+ * hppa-tdep.c: (Pa_print_fp_reg): Change prototype to match def'n.
+ (pa_register_look_aside): Fix comment immediately before function.
+
+ * hppa-tdep.c: Changes to better support stack unwinding,
+ reading and writing registers for HPUX. The HP folks had
+ an advantage ... access to a runtime architecture spec ;-}.
+ New includes: Ptrace.h
+ (internalize_unwinds): Initialize new fields in table.
+ (read_unwind_info): Entries in the table are now more complex
+ structures. References of the form ...->table[index].stub_type
+ are now ...->table[index].stub_unwind.stub_type.
+ (find_proc_framesize): Added a check for pc == 0.
+ (rp_saved): Entries in the table are now more complex
+ structures. References of the form ...->table[index].stub_type
+ are now ...->table[index].stub_unwind.stub_type.
+ (frameless_function_invocation): Stub_type becomes
+ stub_unwind.stub_type
+ (saved_pc_after_call): Stub_type becomes stub_unwind.stub_type
+ (hppa_frame_saved_pc): Stub_type becomes stub_unwind.stub_type
+ (frame_chain_valid): Stub_type becomes stub_unwind.stub_type
+ (hppa_call_dummy): Stub_type becomes stub_unwind.stub_type
+ (pa_print_fp_reg): Additional params to call val_print
+ (in_solib_call_trampoline): Stub_type becomes stub_unwind.stub_type
+ (in_solib_return_trampoline): Stub_type becomes stub_unwind.stub_typ
+ (skip_trampoline_code): Additional code to handle external
+ dyncalls. Also stub_type becomes stub_unwind.stub_type
+ (hppa_pid_to_exec_file): New funct. FOr HPUX 10.0 and beyond there
+ is an explicit ptrace request for getting the pathname associated
+ with a process id (pid).
+
+ * hppa-tdep.c: Fix for gcc compile on HPUX
+ (hppa_pid_to_exec_file): Remove unwanted param from
+ call to call_ptrace. Note, hppa_pid_to_exec_file goes
+ away in subsequent hp snapshots.
+
+ * hppa-tdep.c: Include bfd.h.
+ include dl.h
+ (args_for_find_stub): New structure.
+ (find_unwind_entry): Deal with null input pc value.
+ (rp_saved): Ditto.
+ For the import stub, return -24 always.
+ (hppa_frame_saved_pc): Save old pc value, to detect we are in a loop.
+ (init_extra_frame_info): Use TARGET_READ_FP.
+ (frame_chain): Include thread support.
+ If the caller's pc is zero, we loose and return, just like stack bottom.
+ Disable warning about being unable to find unwind info.
+ (hppa_push_arguments): Rewrite.
+ (hppa_value_returned_from_stack): New function. Handles returning a value
+ larger that 64 bits, stored on the stack.
+ (find_stub_with_shl_get): New function. To look up symbols in shlibs.
+ (cover_find_stub_with_shl_get): New function. Cover routine for
+ find_stub_with_shl_get to pass to catch_errors.
+ (hppa_fix_call_dummy): Comment out old stub mechanism. Rewrite using dyncall.
+ (target_read_fp): New function.
+ (pa_do_registers_info): Floating point registers start at FP4.
+ (pa_print_registers): Use FP4_REGNUM instead of 72.
+ (skip_trampoline_code): Do machine instruction matching for PA2.0.
+ (setup_d_pid_in_inferior): New function. Exception handling support.
+ (initialize_hp_cxx_exception_support): Ditto.
+ (child_enable_exception_callback): Ditto.
+ (child_get_current_exception_event): Ditto.
+
+ * hppah-nat.c (child_post_wait, child_post_follow_vfork,
+ child_post_follow_inferior_by_clone): New functions.
+
+ * hppah-nat.c (child_xfer_memory): Make sure the call to ptrace really
+ fails before we give up.
+ (hppa_pid_to_str): New function. Format a process id.
+ (hppa_tid_to_str): New function. Format a thread id.
+
+ * hppah-nat.c (child_xfer_memory): Use xmalloc, not alloca.
+ (child_post_wait): Delete.
+ (child_post_follow_vfork): Delete decl of child_ops; delete
+ large chunks of function -- let it be handled by the normal
+ mechanism that notices and handles exec events, in resume().
+
+ * hppah-nat.c (require_notification_of_exec_events): New function;
+ just notify of exec events, not all events, and just the specified
+ pid, don't include it's children (10.20 version).
+ (child_acknowledge_created_inferior): Call new function
+ require_notification_of_exec_events instead of
+ require_notification_of_events.
+
+ * hppah-nat.c [!GDB_NATIVE_HPUX_11]: Move HPUX 10.x-specific
+ support code here from infptrace.c.
+
+ * hppah-nat.c: Removed #define ptrace call_ptrace
+ replaced all calls to ptrace with calls to call_ptrace
+ (parent_attach_all): Removed call to ptrace
+
+ * hpread.c (hpread_psymtab_to_symtab_1): Change fflush to
+ gdb_flush; change stdout to gdb_stdout.
+ (hpread_psymtab_to_symtab): Change fflush to gdb_flush.
+
+ * hpread.h: New file. Includes all includes, struct defs, defines
+ from hpread.c.
+
+ * infcmd.c
+ (attach_command): New local variable, exec_file, added code to
+ determine exec_file from pid if exec_file is not already known,
+ call new target operation, target_post_attach -- a no-op unless
+ on HPUXHPPA
+ (detach_command): After detaching, do a SOLIB_RESTART
+
+ * infcmd.c (objfiles.h): Fix typo on include line.
+
+ * infcmd.c (run_command): Only call SOLIB_RESTART if it's
+ defined.
+ (detach_command): Ditto.
+
+ * infcmd.c:
+ (run_stack_dummy): Add calls to
+ disable_watchpoints_before_interactive_call_start and
+ enable_watchpoints_after_interactive_call_stops
+ (finish_command): Alter code handling the evaluation and printing
+ of the target function's return value.
+ (attach_command): When given a pid, but no exec file, try to determine
+ the exec file from the process. If the process does not record a
+ full path name, try to qualify the filename against the source path.
+ (_initialize_infcmd): Add some verbiage about how to use the attach command
+
+ * infcmd.c:
+ Include objfiles.h
+ (run_command): If program has already been started, and decide
+ to restart it, then kill the target, flush the caches,
+ call init_wait_for_inferior. Also purge old solib objfiles.
+
+ * infcmd.c: Changed calls to val_print, using a new macro,
+ SOLIB_RESTART
+ (run_command): Calls SOLIB_RESTART
+ (do_registers_info): Changed calls to val_print
+
+ * infcmd.c: Made the symfile.h include preceed the
+ objfiles.h include. The other ordering caused a
+ compile problem (incompletely defined types).
+
+ * inferior.h (REQUIRE_DETACH): Fix default definition.
+ * inftarg.c (child_post_attach): Fix declaration, make static.
+ (proc_wait): Make globally visible.
+ (child_insert_fork_catchpoint, etc): Fix return type.
+
+ * inferior.h (STARTUP_WITH_SHELL): New define.
+ (START_INFERIOR_TRAPS_EXPECTED): New define
+
+ * inferior.h (fork_inferior): Change fifth parameter to be a function
+ returning void.
+
+ * inferior.h (proc_wait): Declare.
+
+ * inferior.h:
+ (Require_ATTACH): New macro
+ (REQUIRE_DETACH): New macro
+ (detach): Definition is now an extern
+ (clone_and_follow_inferior): New definition, it's also an extern
+
+ * inferior.h:
+ (Require_attach): Default definition for require_attach funct
+ (require_detach): Default definition for require_detach funct
+ (pre_fork_inferior): New funct decl for function defined in
+ infptrace.c
+ (fork_inferior): New parameter in funct decl.
+
+ * inferior.h:
+ New variable decls: Inferior_ignoring_startup_exec_events,
+ inferior_ignoring_leading_exec_events -- these variables
+ are used when processing an exec call.
+ (CALL_DUMMY_HAS_COMPLETED): New default macro -- for targets
+ where PC in call dummy implies that call dummy has
+ completed. Note, that on HPUX this inference does not hold.
+
+ * infptrace.c
+ (require_notification_of_events): New function
+ (child_acknowledge_created_inferior): Previously named
+ hppa_acknowledge_forked_child. Also calling
+ require_notification_of_events and clearing some semaphore
+ variables
+ (child_post_startup_inferior): New function
+ (child_create_catch_fork_hook): Previously named
+ hppa_create_catch_fork_hook
+ (child_create_catch_vfork_hook): Previously named
+ hppa_create_catch_vfork_hook
+ (child_has_forked): Previously named hppa_target_has_forked
+ (child_has_vforked): Previously named hppa_target_has_vforked
+ (process_wait): Changed to call target_post_wait
+ (attach): Add call to require_notification_of_events
+ (child_pid_to_exec_file): New function
+ (hppa_require_attach): New local variable, pt_status
+ (hppa_get_process_events): New function
+
+ * infptrace.c (call_ptrace): Simplify control flow.
+ (proc_wait): Move here from inftarg.c, add target_post_wait call.
+
+ * infptrace.c (call_ptrace): Add some debugging code.
+
+ * infptrace.c (child_pid_to_exec_file): Declare variable.
+
+ * infptrace.c (kill_inferior): Clean up call to proc_wait.
+
+ * infptrace.c:
+ (Call_ptrace): When the ptrace request is PT_SETTRC,
+ call ptrace and then call parent_attach_all.
+
+ * infptrace.c:
+ (Child_has_syscall_event): New function. only applicable
+ (for now) on HPUX 10.30 and beyond via the ttrace call.
+ In infptrace.c there is a default operation.
+ With ttrace, it is possible to tell the kernel to
+ notify the debugger that the target program is about to make
+ or return from a syscall.
+ (child_thread_alive): New function. a default function.
+ ptrace doesn't support kernel threads.
+ (hppa_enable_page_protection_events): Defualt function
+ (hppa_disable_page_protection_events): Default function
+
+ * infptrace.c (child_pid_to_exec_file): Fix number of params to
+ cal_ptrace call.
+
+ * infptrace.c (hppa_pid_or_tid_to_str): New function.
+ (hppa_switched_threads): New function.
+ (hppa_ensure_vforking_parent_remains_stopped): New function.
+ (hppa_resume_execd_vforking_child_to_get_parent_vfork): New function.
+
+ * infptrace.c: Most of the changes found in infptrace.c should
+ be moved to hppah-nat.c
+ (PT_VERSION): A new define
+ (startup_semaphore_t): A new struct type. it is used to
+ coordinate the parent and child processes after a fork and
+ before an exec on HPUX.
+ (call_ptrace): Changes to determine whether the ptrace
+ request is for starting the tracing of the target process.
+ (parent_attach_all): New funct. used on HPUX for coordinating
+ the parent and child processes after a fork and before and exec.
+ (hppa_acknowledge_forked_child): New funct. prabably belongs
+ in hppah-nat.c
+ (hppa_enable_catch_fork): New funct. probably belongs in
+ hppah-nat.c
+ (hppa_disable_catch_fork): New funct. probably belongs in
+ hppah-nat.c
+ (hppa_create_catch_fork_hook): New funct. probably belongs in
+ hppah-nat.c
+ (hppa_enable_catch_vfork): New funct. probably belongs in
+ hppah-nat.c
+ (hppa_disable_catch_vfork): New funct. probably belongs in
+ hppah-nat.c
+ (hppa_create_catch_vfork_hook): New funct. probably belongs to
+ hppah-nat.c
+ (hppa_target_has_forked): New funct. probably belongs in
+ hppah-nat.c
+ (hppa_target_has_vforked): New funct. probably belongs in
+ hppah-nat.c
+ (process_wait): New funct. also ifdefed for proc_wait.
+ (kill_inferior): Call proc_wait rather than wait. this is
+ pretty hacky.
+ (pre_fork_inferior): New function. used only by HPUX.
+ probably should be defined elsewhere.
+
+ * infrun.c (follow_inferior_fork): Only define on HP.
+ (wait_for_inferior): Only call SOLIB_IN_DYNAMIC_LINKER if we have
+ shared libraries; restore test of IN_SOLIB_DYNSYM_RESOLVE_CODE
+ removed by HP.
+
+ * infrun.c (normal_stop): Add a call to the TUIDO
+ macro just before the annotate_stopped label. This
+ updates the windows after each program stop.
+
+ * infrun.c (normal_stop): Verify stop_command is non-zero before
+ dereferencing it (it won't be set if dbx_commands is set).
+
+ * infrun.c (resume): Add #ifdef HPPAHPUX around HPUX-specific
+ code.
+
+ * infrun.c (resume): Add missing semicolon.
+
+ * infrun.c (wait_for_inferior): Fix syntax error.
+
+ * infrun.c (follow_fork_mode_kind_names): Removed "both" option.
+ (follow_fork): Added parameters. additional code for handling
+ following of parent, following of child
+ (resume): Added code for deciding how to resume in presence of
+ fork. Additional params to follow_fork call.
+
+ * infrun.c (follow_exec): Ifdef for HPUXHPPA for the moment, the
+ code in here assumes the existance of the child_ops target
+ vector. This is incorrect for Solaris.
+
+ * infrun.c (resume): Fixed ifdefs, HPPAHPUX -> HPUXHPPA.
+
+ * infrun.c (wait_for_inferior): Fixed a matching parens problem --
+ matching curly brace inside ifdefed code which is not being
+ compiled. Change local validFlag to be an 'int' rather than a
+ 'bool' and fixed the corresponding assignment statements.
+
+ * infrun.c:
+ Two new global variables: Inferior_ignoring_startup_exec_events and
+ inferior_ignoring_leading_exec_events.
+ New static variables: Parent_of_vfork_trap_expected_and_ignorable,
+ step_resume_breakpoint, through_sigtramp_breakpoint, pending_follow,
+ follow_vfork_when_exec
+ (follow_inferior_fork): Does what follow_fork did!
+ (follow_fork): Is now a wrapper function for follow_inferior_fork
+ (follow_vfork): Is now a wrapper function for follow_inferior_fork
+ (follow_exec): New function, handles an exec event.
+ (resume): Remove 3 local variables: Child_pid, has_forked, has_vforked.
+ move and expand code that tries to follow a fork (i.e. also check
+ for vfork and exec
+ (init_wait_for_inferior): Initialize the new structure, pending_follow
+ (delete_breakpoint_current_contents): When deleting all the breakpoints also
+ set the breakpoint struct pointer to NULL.
+ (wait_for_inferior): A number of changes.
+ The step_resume_breakpoint and through_sigtramp_breakpoint local
+ variables are now visible in entire module.
+ Changed name of variable from child_inferior_pid to saved_inferior_pid.
+ Added several cases to the event processing switch statement:
+ Target_WAITKIND_FORKED, TARGET_WAITKIND_VFORKED, TARGET_WAITKIND_EXECD.
+ Also, for TARGET_WAITKIND_STOPPED, check to see if expecting a trap
+ from the parent of a vfork (ignorable) otherwise break as usual.
+ When determining the value of 'random_signal' (0 or 1), no longer check for
+ catchpoints.
+ When determining how to handle unexpected signals, must now take into
+ account fork, vfork, and exec.
+ Change call to PC_IN_CALL_DUMMY to a call to CALL_DUMMY_HAS_COMPLETED
+ At stop_stepping label, check to see if stopped for fork or
+ vfork event.
+
+ * infrun.c: New code is related to threads and fork/vfork/exec.
+ New static variable: Thread_step_needed
+ Deleted static variable: Parent_of_vfork_trap_expected_and_ignorable
+ Altered the pending_follow and fork_event structs
+ (follow_inferior_fork): Before detaching from child and removing
+ all breakpoints form it -- but only if forking or following
+ vforks as soon as they happen. Also reset the solib inferior hook.
+ The same kind of logic applies to hitting step_resume_breakpoints
+ (calling breakpoint_re_set_thread) and to resetting and inserting
+ breakpoints.
+ (follow_exec): Forward decl
+ (follow_vfork): Check to see if gdb followed the child. If
+ the child exec'd before gdb saw the parent's vfork event
+ then call follow_exec.
+ (follow_exec): If the exec occured after a vfork, then follow
+ the vfork as well. Do it before following the exec.
+ Make sure to update breakpoints after and exec
+ (resume): New local variable, should_resume.
+ Change parameters in calls to follow_fork, follow_vfork, and
+ follow_exec. Some changes to the way various pending_follow.kind
+ situations are handled (there's TARGET_WAITKIND_FORKED,
+ TARGET_WAITKIND_VFORKED, ARGET_WAITKIND_EXECD. Some additional
+ conditions to check before deciding to resume the target (i.e.
+ should_resume=1, stepping?, thread_step_needed?i, regular
+ resume?)
+ (proceed): When proceeded at location that does not have a breakpoint
+ set thread_step_needed=0 to indicate that it is not necessary to
+ single step thread over breakpoint. SOme additional checks to see
+ if it is necessary to step thread over breakpoint.
+ (start_remote): Remove call to clear_proceed_status.
+ (init_wait_for_inferior): Initialize new fields in fork_event
+ structure and add a call to clear_proceed_status.
+ (wait_for_inferior): New local variable: New_thread_event.
+ Initialize thread_step_needed = 0.
+ Minor massaging of conditions for adding a new thread to the thread list.
+ No longer resuming execution after adding a new thread. Let user play with thread first.
+ Some changes in the way TARGET_WAITKIND_FORKED, ARGET_WAITKIND_VFORKED,
+ TARGET_WAITKIND_EXECD are handled -- this is all HPUX related.
+ Simplified TARGET_WAITKIND_STOPPED -- HP previously had some
+ more complicated code in here.
+ Moved the code to resume threads to after the large case statement that processes the events.
+ Additional processing for stop_signal=TARGET_SIGNAL_TRAP.
+ Cleanup code at process_event_stop_test label.
+ Set thread_step_needed when processing a BPSTAT_WHAT_SINGLE.
+ Minor massaging of fork/vfork/exec part of stop_stepping code.
+ (normal_stop): Minor changes. calling show_and_print_stack_frame.
+ (xdb_handle_command): New function
+ (_initialize_infrun): Handle xdb_commands. also handle dbx commands
+
+ * infrun.c: Changes to support following forks, and handling
+ catchpoints.
+ (follow_fork_mode_kind_names): New array
+ (follow_fork): New function. implements the follow parent,
+ or child functionality.
+ (resume): Additions to check whether the target process
+ just forked and decide which process to follow.
+ (wait_for_inferior): Additional variables (child_inferior_pid,
+ stepping_through_solib_after_catch,
+ - stepping_through_solib_catchpoints.
+ - Altered CURRENTLY_STEPPING macro to check for stepping through
+ a shared library after hitting a catchpoint.
+ - Add parameters to save_infrun_state call
+ - Check for fork and vfork when deciding if event is a random
+ signal
+ - When considering stops due to breakpoints, check for
+ BPSTAT_WHAT_CHECK_SHLIBS_RESUME_FROM_HOOK
+ - Check for stop due to an explicit catchpoint
+ - When checking for single stepping event, also check for
+ stepping to get out of dynamic linker's hook after catching
+ a shlib event
+ (is_internal_shlib_eventpoint): New funct. check to see if
+ event type is bp_shlib_event.
+ (stopped_for_internal_shlib_event): New funct. check for shlib
+ events
+ (stopped_for_shlib_catchpoint): New funct. check for catchpoints.
+ (normal_stop): Additions to check for shlib event
+ (set_follow_fork_mode_command): New funct. handles the new follow
+ fork command.
+ (_initialize_infrun): Additions for follow-fork-mode command.
+
+ * infrun.c: Ifdefing references to
+ switched_from_inferior_pid for HPUXHPPA. They don't seem
+ useful for Solaris (i.e. non-HPUX)
+
+ * infrun.c: Included tuiData.h and tuiDataWin.h, ifdefed for TUI.
+ Included top.h. New static variables: Switched_from_inferior_pid,
+ number_of_threads_in_syscalls.
+ (follow_inferior_fork): If there is a step_resume breakpoint
+ explicitly reset the thread number.
+ (resume): For TARGET_WAITKIND_VFORKED, removed a check for getting
+ the vfork event to soon.
+ (init_wait_for_inferior): Added parameter to call to
+ breakpoint_init_inferior. Initialize number_of_threads_in_syscalls.
+ (wait_for_inferior): New local variables: Prev_sal,
+ enable_hw_watchpoints_after_wait, stepping_through_sigtramp,
+ stepped_after_stopped_by_watchpoint. Enable watchpoints after a wait.
+ Added cases for TARGET_WAITKIND_SYSCALL_ENTRY and
+ TARGET_WAITKIND_SYSCALL_RETURN.
+ Do additional processing if stop due to breakpoint, but breakpoint is
+ only valid for a thread other than the one currently running. Additional
+ parameters to save_infrun_state and load_infrun_state. Some additional
+ processing for BPSTAT_WHAT_STEP_RESUME. Some additional processing to
+ handle stepping over a function.
+ (normal_stop): Added notification of switching threads. ifdefing some
+ TUI changes and leaving out non-essential TUI changes.
+ (restore_selected_frame): Ifdefing some TUI changes
+ (restore_inferior_status): Ifdefing some TUI changes
+
+ * infrun.c: Removed the TUI ifdefs and TUI code. Also removed
+ include for top.h. HP introduced this. I'm taking it out.
+
+ * inftarg.c (child_detach_from_process): Declare.
+ (child_attach_to_process): Declare.
+ (child_stop): Make static to match declaration.
+
+ * inftarg.c (ptrace_him): Change prototype back to return int.
+
+ * inftarg.c (ptrace_me): Remove debug output, pass NULL to
+ fork_inferior if not HPUX.
+
+ * inftarg.c:
+ (child_require_attach): New funct prototype and definition
+ (child_require_detach): New funct prototype and definition
+ (proc_wait): Funct prototype and definition are enclosed by
+ proc_wait ifndef
+ (child_attach_to_process): New function, does most of the
+ work that child_attach used to do and some additional
+ work to determine whether gdb is already attached to the
+ target how to react.
+ (child_attach): Altered. It's now a wrapper for
+ child_attach_to_process.
+ (child_require_attach): New function, called if should attach
+ even when gdb is already attached to target.
+ (child_detach_from_process): New function, does most of the
+ work that child_detach used to do and some additional work
+ to determine whether gdb is currently attached to the target.
+ (child_detach): Altered. It's now a wrapper for
+ child_detach_from_process.
+ (child_require_detach): New function, called if should try to
+ detach even when gdb is not attached to target.
+ (ptrace_him): Calls a new function, target_acknowledge_forked_child.
+ Currently, target_acknowledge_forked_child, is only defined to
+ do something for HPUX.
+ (child_create_inferior): Changed call to fork_inferior.
+ (child_ops): Added to_require_attach and to_require_detach fields
+ to the child_ops target ops vector.
+
+ * inftarg.c:
+ Some hacks for ttrace work
+ (child_wait): Additional local variables, additional code in
+ while loop to check for: Process exited, process forked,
+ process vforked, process execd
+ (child_thread_alive): John B. seems to think that the kill
+ call is inapproapriate for HPUX.
+ (child_attach_to_process): Using strtol rather than atoi.
+ no longer check for case where there is no known exec file.
+ (child_post_attach): New function, a default, a no-op
+ (child_insert_fork_catchpoint): New function, a default, a no-op
+ (child_remove_fork_catchpoint): New function, a default, a no-op
+ (child_create_catch_fork_hook): Deleted
+ (child_create_catch_vfork_hook): Deleted
+ (child_insert_vfork_catchpoint): New function, a default, a no-op
+ (child_remove_vfork_catchpoint): New function, a default, a no-op
+ (child_can_follow_vfork_prior_to_exec ):new function, a default,
+ a no-op
+ (child_insert_exec_catchpoint): New function, a default, a no-op
+ (child_remove_exec_catchpoint): New function, a default, a no-op
+ (child_has_execd): New function, a default, returns 0
+ (child_reported_exec_events_per_exec_call): New function, a
+ default, returns 1
+ (child_has_exited): New function, a default.
+ (child_core_file_to_sym_file): New function, a default, returns NULL.
+ (child_ops): Initialize new target_ops vector fields to the
+ child* functions.
+ * infptrace.c:
+ (Call_ptrace): For HPUX, handle additional requests: Pt_CONTIN1,
+ PT_STEP1.
+ (require_notification_of_events): Add several signals to the
+ set of events requiring notification: Ptrace_SIGNAL,
+ PTRACE_EXEC, PTRACE_FORK, PTRACE_VFORK
+ (child_acknowledge_created_inferior): This function is only
+ defined if CHILD_ACKNOWLEDGE_CREATED_INFERIOR is defined.
+ (child_post_startup_inferior): Function is only defined if
+ CHILD_POST_STARTUP_INFERIOR is defiend. Also, now call
+ require_notification_of_events.
+ (child_create_catch_fork_hook): Deleted
+ (child_create_catch_vfork_hook): Deleted
+ (child_insert_fork_catchpoint): New function
+ (child_remove_fork_catchpoint): New function
+ (child_insert_vfork_catchpoint): New function
+ (child_remove_vfork_catchpoint): New function
+ (child_has_forked): Now enclosed by a CHILD_HAS_FORKED ifdef
+ (child_has_vforked): Now enclosed by CHILD_HAS_VFORKED ifdef
+ (child_can_follow_vfork_prior_to_exec): New function
+ (child_insert_exec_catchpoint): New function
+ (attach): Removed call to require_notification_of_events
+ (child_post_attach): New function, call to
+ require_notification_of_events moved here.
+ (child_pid_to_exec_file): New enclosed by CHILD_PID_TO_EXEC_FILE ifdef
+ introduced the concept of a saved_inferior_pid
+ (hppa_require_attach): Add some code to decide if gdb is already
+ attached to process. Can not figure this out via a ptrace call.
+ (hppa_insert_hw_watchpoint): New function
+ (hppa_remove_hw_watchpoint): New function
+
+ * inftarg.c:
+ (child_attach_to_process): Change position in file
+ (child_detach_from_process): Change position in file
+
+ * inftarg.c:
+ (child_attach_to_process): Changed parameter to child_wait call
+
+ * inftarg.c:
+ (child_post_wait): New function declaration and definition
+ (ptrace_him):
+ - change return value to a void.
+ - change target_acknowledge_forked_child call to
+ target_acknowledge_created_inferior
+ - call target_post_startup_inferior rather than returning pid.
+ (child_attach_to_process): Change param name, fail_if_already_attached
+ -> after_fork.
+ Invert a couple of if-then-else statments.
+ Use REQUIRE_ATTACH macro
+ (child_attach): Change params in child_attach_to_process call
+ (child_require_attach): Change params in child_attach_to_process call
+ (child_detach_to_process): Change param name,
+ fail_if_already_attached -> after_fork.
+ Invert a couple of if-then-else statments.
+ Use REQUIRE_DETACH macro
+ (child_detach): Change params in child_detach_from_process call
+ (child_require_detach): Change params in child_detach_from_process
+ call
+ (child_post_startup_inferior): New function
+ (child_acknowledge_created_inferior): New function
+ (child_clone_and_follow_inferior): New function
+ (child_post_follow_inferior_by_clone): New function
+ (child_create_catch_fork_hook): New function
+ (child_create_catch_vfork_hook): New function
+ (child_has_forked): New function
+ (child_has_vforked): New function
+ (child_post_follow_vfork): New function
+ (child_stop): No longer a static function
+ (child_pid_to_exec_file): New function
+
+ * inftarg.c:
+ (child_wait): Child_pid becomes related pid. return pid
+ rather than inferior_pid. Changes are in code handling fork
+ and vfork
+
+ * inftarg.c:
+ Include gdb_stat.h and sys/unistd.h
+ (child_wait): New local variables. Check for live threads.
+ Check for syscall events
+ (child_thread_alive): No longer a static funct.
+ (ptrace_him): Remove some code inserted in snap3
+ (child_create_inferior): Added a bunch of code to handle a
+ bad interaction between start-up-with-shell and the HP
+ catch-fork/catch-exec logic. I am ifdefing this for
+ HPUXHPPA for now.
+ (child_has_syscall_event): New default target_ops function
+ (child_enable_exception_callback): New default target_ops function
+ (child_get_current_exception_event): New default target_ops function
+ (child_ops): 3 new fields
+
+ * inftarg.c: Remove HPUX_SNAP1 and HPUX_SNAP2 ifdefs
+
+ * inftarg.c: Reverted previous change.
+
+ * infttrace.c (hppa_remove_hw_watchpoint): Fix check for write
+ access hardware watchpoint.
+
+ * infttrace.c (proc_wait): Rename from proc_wait.
+
+ * infttrace.c (require_notification_of_exec_events): New function;
+ just notify of exec events, not all events, and just the specified
+ pid, don't include it's children.
+ (child_acknowledge_created_inferior): Call new function
+ require_notification_of_exec_events instead of
+ require_notification_of_events.
+ (child_post_startup_inferior): Call require_notification_of_events
+
+ * infttrace.c: Changed all references to boolean to int.
+ Changed all references to TRUE and FALSE to 1 and 0.
+
+ * irix5-nat.c (symbol_add_stub): Add params to call to
+ symbol_file_add.
+
+ * jv-lang.c (get_dynamics_objfile): Add 2 more parameters to call
+ to allocate_objfile.
+
+ * main.c (fputs_unfiltered): Changes to prevent cursor form
+ jumping around in the TUI. Altered where tuiTermUnsetup and
+ tuiTermSetup are called
+
+ * main.c (fputs_unfiltered): Changed function so that it
+ checks to see if output is to a string buffer or to a
+ FILE stream and does the correct action (i.e. strcat or
+ fputs). Fixed params for fputs call.
+
+ * main.c (fputs_unfiltered): Don't try to call the TUI's
+ CommandCharCount functions when the TUI isn't enabled.
+
+ * main.c (fputs_unfiltered): Change FILE to GDB_FILE.
+
+ * main.c (main): If the user gives the --version or --help flags,
+ disable the TUI.
+
+ * main.c (tui_version, xdb_commands, dbx_commands): New variables.
+ (main): New command line arguments --tui, --xdb, --dbx; add call
+ to tyiCleanUp via tuiDo to main loop.
+ (fputs_unfiltered): Tui related changes.
+
+ * main.c: Define 2 new global variables, gdb_stdout and gdb_stderr
+ of type GDB_FILE.
+ (main): Allocate space for and initialize gdb_stdout and gdb_stdin.
+
+ * objfiles.c (find_pc_sect_section): Make end condition be less
+ than s->endaddr, not less than or equal to s->endaddr.
+
+ * objfiles.c:
+ (allocate_objfile): 2 new parameters: User_loaded and is_solib.
+ When appropriate, record in the object file that it is user loaded.
+ The run command can use this information to purge object file
+ entries associated with the old inferior and keep user loaded
+ object files loaded via the add-symbol-file command.
+ (objfile_purge_solibs): New function. deletes all objectfile entries
+ that are not explicitly loaded by the user.
+
+ * objfiles.c:
+ (objfile_relocate): Check for LOC_INDIRECT
+ (find_pc_sect_section): Change condition from
+ pc < s->endaddr to pc <= s->endaddr
+
+ * objfiles.h:
+ New variables: User_loaded and is_solib
+ (OBJF_SHARED): New macro. used to distinguish objfile for
+ shared library from "vanilla" objfile.
+ (allocate_objfile): Add new parameters to function decl.
+ (objfile_purge_solibs): New function decl.
+
+ * objfiles.h: Add some typedefs: Importentry, ExportEntry.
+ Add some new variables: Import_list, import_list_size,
+ export_list, export_list_size
+
+ * osfsolib.c:
+ (symbol_add_stub): Added params to call to symbol_file_add
+
+ * pa/hpux1020.mh (NATDEPFILES): Add corelow.o, symbol table and
+ solib files.
+
+ * pa/hpux1100.mh (NAT_FILE): Use nm-hppah11.h.
+ (NATDEPFILES): Add symbol table and solib files.
+
+ * pa/nm-hppah11.h: New file, HPUX11-only definitions.
+
+ * pa/tm-hppa.h (proc_wait): Remove decl and macro.
+
+ * parse.c (write_dollar_variable): Handle cases in which variables
+ besides the debugger ones start with $ and $$.
+ (parse_nested_classes_for_hpacc): New function. Parse a string that
+ is possibly a namespace / nested class specification.
+ (find_template_name_end): New function.
+
+ * procfs.c:
+ (procfs_init_inferior): Return value is now a void.
+
+ * procfs.c (procfs_ops): Initializing new target ops vector fields. see list below.
+
+ * procfs.c:
+ (procfs_ops): Adding new target_ops vector fields and
+ removing a few. see list below
+
+ * procfs.c: Added new fields to procfs_ops.
+ Necessary since we still have oldstyle initialization in
+ this file
+
+ * pyr-tdep.c (pyr_do_registers_info): Change stdout to gdb_stdout.
+ (frame_locals_address): Change stderr to gdb_stderr.
+ (frame_args_addr): Ditto.
+
+ * pyr-xdep.c (fetch_inferior_registers): Change stderr to
+ gdb_stderr.
+
+ * serial.c (serial_close): Call gdb_fclose, not fclose on a
+ GDB_FILE.
+
+ * serial.c (serial_logchar): Change chtype to ch_type. sigh.
+
+ * solib.c (look_for_base): The parameter to file must be
+ of type FILE *. So cast exec_bfd -> iostream in the call
+ to fileno as a FILE *, not a GDB_FILE *. This will work because
+ exec_bfd -> iostream is declared and given a value in bdf and
+ bfd will continue to use FILE rather than GDB_FILE.
+
+ * solib.c:
+ (solib_add): Remove references to exec_ops.
+
+ * solib.c:
+ (solib_add): Update exec_ops.to_sections
+
+ * solib.c:
+ (symbol_add_stub): Added params to call to symbol_file_add
+
+ * solib.h:
+ (SOLIB_REMOVE_INFERIOR_HOOK): New macro. defined to 0.
+ functionality not implemented for this target.
+
+ * solib.h: Added macro definitions. These macros generate
+ error messages for solaris??
+ (SOLIB_CREATE_CATCH_LOAD_HOOK)
+ (SOLIB_CREATE_CATCH_UNLOAD_HOOK)
+ (SOLIB_HAVE_LOAD_EVENT)
+ (SOLIB_LOADED_LIBRARY_PATHNAME)
+ (SOLIB_HAVE_UNLOAD_EVENT)
+ (SOLIB_UNLOADED_LIBRARY_PATHNAME)
+ (SOLIB_IN_DYNAMIC_LINKER)
+ (SOLIB_RESTART)
+
+ * somread.c (is_in_import_list): Ditto.
+
+ * somread.c (som_symfile_read): Added some comments
+
+ * somread.c (som_symfile_read): Read in import and export lists.
+ (som_symtab_read): Change test for dynamic executable.
+ (is_in_import_list): New function. Check if a given symbol name
+ is in the import list.
+ (init_import_symbols): New function. Read in and initialize the
+ som import list.
+ (init_export_symbols): New function. Read in and initialize the
+ som export list.
+
+ * somread.c:
+ (som_symfile_read): Fix missing comment delimiters
+
+ * somsolib.c (DLD_FLAGS_MAPPRIVATE): New macro.
+ Define bit of __dld_flags in HP-UX a.out files.
+ (DLD_FLAGS_HOOKVALID): Ditto.
+ (DLD_FLAGS_LISTVALID): Ditto.
+ (DLD_FLAGS_BOR_ENABLE): Ditto.
+ (som_solib_total_st_size): Cumulative size in bytes of the
+ symbol tables of all shared objects on the so_list_head list.
+ (som_solib_st_size_threshhold_exceeded): Threshold for adding symbols
+ for shlibs.
+ (som_solib_sizeof_symbol_table): New function. Computes size of
+ symbol table for a shlib.
+ (som_solib_load_symbols): New function. Load symbols from shlib.
+ (som_solib_add): Detect if __dld_list is not valid.
+ Record main program's symbol table size.
+ Load symbols if called from command line.
+ Keep threshold into account when loading shlib symbols.
+ (som_solib_create_inferior_hook): Use dld_flags macros.
+ (som_sharedlibrary_info_command): Let user know if symbols were
+ not loaded.
+ (som_solib_restart): Discard all the shlibs descriptors.
+ (_initialize_som_solib): Chenge help message for auto-solib-add
+ command.
+ Set threshold for symbol table to 50 megabytes.
+
+ * somsolib.c (_initialize_som_solib): Added call to som_solib_restart.
+ (som_solib_restart): New function
+ (som_solib_in_dynamic_linker): New function
+ (som_solib_desire_dynamic_linker_symbols): New function
+ (som_solib_unloaded_library_pathname): New function
+ (som_solib_loaded_library_pathname): New function
+ (som_solib_library_pathname): New function
+ (som_solib_have_unload_event): New function
+ (som_solib_have_load_event): New function
+ (som_solib_create_catch_unload_hook): New function
+ (som_solib_create_catch_load_hook): New function
+ (som_solib_create_inferior_hook): Rewritten
+ dld_cache: New struct
+ addr_and_unwind_t: New struct
+ (find_unwind_entry) added prototype
+
+ * somsolib.c (som_solib_create_inferior_hook): Introduce new local
+ msymbol2 and change some msymbol's to msymbol2's -- was clobbering
+ msymbol, passing a NULL to lookup_minimal_symbol_solib_trampoline,
+ and ultimately core dumping with a SEGV.
+
+ * somsolib.c:
+ Include assert.h
+ (som_solib_mapped_entry): Additional comments for text_addr,
+ text_link_addr, text_end, and tsd_start_addr fields. Commenting
+ out 2 tsd fields, __data_start and __data_end.
+ (som_solib_add_solib_objfile): Add params to calls to symbol_file_add.
+ Add some code for distinguishing between a shared library and other
+ objfiles. This appears to be a prelude to thread local storage.
+ (som_solib_load_symbols): Changes to printf statement
+ enclosed by SOLIB_DEBUG ifdef.
+ (som_solib_add): Change comment to correctly specify path
+ to end.o -- /opt/langtools/lib/end.o. changes to printf statement
+ enclosed by SOLIB_DEBUG ifdef.
+ Removed several SOLIB_DEBUG ifdefs and the associated printfs.
+ Add code to find the start address for the object file's thread
+ local storage
+ (som_solib_create_inferior_hook): Fix warning messages use correct
+ path to end.o -- /opt/langtools/lib/end.o. Change control flow.
+ No longer user early returns from function is cases of error.
+ (reset_inferior_pid): New function
+ (som_solib_remove_inferior_hook): New function
+ (so_lib_thread_start_addr): New function. used for tsd.
+
+ * somsolib.c: Removed references to ASSERT macro.
+
+ * somsolib.c: Add debugging macro.
+ (struct som_solib_mapped_entry): Add new field tsd_start_addr.
+ (struct so_list): Added new field solib_addr.
+ (som_solib_add_solib_objfile): New function.
+ (som_solib_load_symbols): Rewritten.
+ (som_solib_add): Make sure we don't load the symbols in if the
+ threshold was exceeded.
+ (som_solib_get_solib_by_pc): New function. Return the address of
+ handle of the shared library.
+ (som_solib_restart): Disable breakpoints at restart.
+ (_initialize_som_solib): Set threshold to 100 megabytes.
+
+ * somsolib.c: Add include of fcntl.h so that O_RDONLY is defined.
+
+ * somsolib.h (DISABLE_UNSETTABLE_BREAK): New macro.
+ (PC_SOLIB): New macro.
+
+ * somsolib.h:
+ (SOLIB_CREATE_CATCH_LOAD_HOOK): Define
+ (SOLIB_CREATE_CATCH_UNLOAD_HOOK): Define
+ (SOLIB_HAVE_LOAD_EVENT): Define
+ (SOLIB_LOADED_LIBRARY_PATHNAME): Define
+ (SOLIB_HAVE_UNLOAD_EVENT): Define
+ (SOLIB_UNLOADED_LIBRARY_PATHNAME): Define
+ (SOLIB_IN_DYNAMIC_LINKER): Define
+ (SOLIB_RESTART): Define
+
+ * somsolib.h:
+ (SOLIB_REMOVE_INFERIOR_HOOK): New macro. defined to use
+ som_solib_remove_inferior_hook.
+
+ * somsolib.h:
+ (som_solib_create_catch_load_hook)
+ (som_solib_create_catch_unload_hook)
+ (som_solib_have_load_event)
+ (som_solib_loaded_library_pathname)
+ (som_solib_have_unload_event)
+ (som_solib_unloaded_library_pathname)
+ (som_solib_in_dynamic_linker)
+ Fix prototypes to use type names, not parameter names.
+
+ * source.c (find_source_lines): Make non static.
+ (open_source_file): Ditto.
+ (source_full_path_of): New function.
+ (print_source_lines): Rename to print_source_lines_base and make
+ static; formatting.
+ (print_source_lines): New function.
+ (forward_search_command): Tui changes.
+ (reverse_search_command): Tui changes.
+ (_initialize_source): Add xdb and dbx compatibility commands.
+
+ * source.c (list_command): Handle case of odd number of source
+ lines to display.
+
+ * source.c:
+ (source_full_path_of): New function. file was overlooked
+ in merge ;-/.
+
+ * stack.c (func_command): Make high bound be <, not <=.
+
+ * stack.c (_initialize_stack): For the backtrace command, delete
+ the help line about usage, since this has to be a valid help
+ message for the 'where' command too.
+
+ * stack.c (current_frame_command): Add a check for the
+ existance of a stack. If there is no stack produce an
+ error message and exit.
+
+ * stack.c (down_silently_base, up_silently_base,
+ args_plus_locals_info, print_frame_info_base,
+ print_stack_frame_base, print_stack_frame_base_stub): Declare.
+ (print_frame_local_vars): Add'l parameter.
+ (print_stack_frame_stub): New version created, old version renamed
+ to show_and_print_stack_frame_base_stub.
+ (print_stack_frame_base_stub, print_only_stack_frame_stub,
+ show_and_print_stack_frame, print_only_stack_frame,
+ stack_publish_stopped_with_no_frame, print_frame_info,
+ show_stack_frame, backtrace_full_command, args_plus_locals_info,
+ select_and_print_frame, select_and_maybe_print_frame,
+ current_frame_command, func_command): New functions.
+ (backtrace_command): New function, old renamed to
+ backtrace_command_1.
+ (print_block_frame_locals, print_frame_local_vars): Additional
+ parameter, number of tabs.
+ (up_silently_command): New function, old renamed to
+ up_silently_command_base.
+ (down_silently_command): New function, old renamed to
+ down_silently_base.
+ (_initialize_stack): Register new commands based on values of
+ xdb_commands and dbx_commands variables.
+
+ * stack.c (func_command): Make high bound be <, not <=.
+
+ * stack.c (parse_frame_specification): Fix prototype to match
+ function definition.
+ (show_and_print_stack_frame_stub): Fix name.
+ (select_and_print_frame): Change uncaught tuiDO call.
+
+ * stack.c (up_silent_base): Rename from up_silently_command_base.
+
+ * symfile.c (symbol_file_command): Only call SOLIB_RESTART if it's
+ defined.
+
+ * symfile.c (add_psymbol_with_dem_name_to_list): New function.
+ Adds a symbol with a long value to a psymtab. Differs from
+ add_psymbol_to_list in taking both a mangled and a demangled name.
+
+ * symfile.c (compare_psymbols): Call strcmp directly, instead of
+ using macro.
+
+ * symfile.c (symbol_file_add): Reindent portions.
+ (symbol_file_command): Add call to tuiDo.
+
+ * symfile.c (symbol_file_command): Only call SOLIB_RESTART if it's
+ defined.
+
+ * symfile.c (symfile_bfd_open): Add code to call PXDB on hpux, if
+ the file has not already been processed by pxdb.
+ Added define USE_PXDB.
+
+ * symfile.c (symfile_bfd_open): Change parenthesis positioning
+ around call to hpread_pxdb_check.
+
+ * symfile.c (symfile_bfd_open): Make not static.
+ (RESET_HP_UX_GLOBALS): New macro. Resets globals when new symbol
+ file loaded.
+ (USE_PXDB): Not needed. Removed.
+ (symbol_file_add): Add HP specific code to deal with pxdb.
+ (symbol_file_command): Reset HP specific globals if new symbol file
+ loaded.
+ (symfile_bfd_open): Comment out checking for pxdb.
+ (reread_symbols): Reset HP specific globals.
+
+ * symfile.c (symfile_bfd_open): Uncomment hpus specific code.
+
+ * symfile.c:
+ (symbol_file_add): Add user_loaded and is_solib parameters.
+ fixed number of parameters in call to allocate_objfile
+ (symbol_file_command): Added call to SOLIB_RESTART macro.
+ fixed number of parameters in calls to symbol_file_add.
+ (add_symbol_file_command): Fixed number of parameters in calls to
+ symbol_file_add.
+
+ * symfile.c: Added prototype for hpread_pxdb_check.
+
+ * symfile.c: Changed HPUX_SNAP1 ifdef to HPUXHPPA. enclosed calls to
+ RESET_HP_UX_GLOBALS with an HPUXHPPA ifdef
+
+ * symfile.h (symfile_bfd_open): Add protptype.
+
+ * symfile.h: Add prototype for add_psymbol_with_dem_name_to_list.
+
+ * symfile.h: Clarify purpose of auto_solib_add.
+
+ * symmisc.c (maintenance_print_symbols): Call gdb_fclose, not
+ fclose on a GDB_FILE* during cleanup.
+ (maintenance_print_psymbols): Call gdb_fclose, not fclose on a
+ GDB_FILE* during cleanup.
+ (maintenance_print_msymbols): Call gdb_fclose, not fclose on a
+ GDB_FILE* during cleanup.
+
+ * symmisc.c (maintenance_print_symbols): Gdb_fclose now takes a
+ GDB_FILE ** parameter. Fix the local GDB_FILE variables and the
+ call to make_cleanup.
+ (maintenance_print_psymbols): Ditto
+ (maintenance_print_msymbols): Ditto
+
+ * symmisc.c (print_objfile_statistics): Close quotes in
+ output strings.
+
+ * symmisc.c:
+ (Print_symbol): Add LOC_INDIRECT to switch statement
+ (print_partial_symbols): Add LOC_INDIRECT to switch statement
+
+ * symtab.c (find_pc_sect_psymtab): High bounds should be <, not <=.
+ (find_pc_sect_symtab): Ditto.
+
+ * symtab.c (hp_som_som_object_present): New flag to indicate HP
+ compiled code.
+ (find_pc_sect_psymtab): Change tests to make sure we are checking
+ the texthigh adress as well.
+ (lookup_transparent_type): New function. Look up a type name
+ in the struct_namespace. The type returned must not be opaque.
+ (find_pc_sect_symtab): Make sure we check the address 'pc' itself,
+ too.
+ (find_addr_symbol): Prepare to handle LOC_INDIRECT address class, but
+ leave it commented out.
+ (find_pc_sect_line): Return correct information if pc is in import
+ or export stub (trampoline).
+ (decode_line_1): Skip two chars, if they are '$$'. Like for HP's
+ $$dyncall. Handle cases in which varaible and function names can start
+ with $.
+ (overload_list_add_symbol): If cannot demangle name, use it as is.
+ Free string after use.
+ (make_symbol_overload_list): Initialize oload_name to NULL and
+ oload_name_len to 0. If demangle not successful, use name as it is.
+ Free string after use.
+
+ * symtab.c (lookup_symbol): Changed call to find_pc_sect_symtab,
+ to the original find_pc_symtab, in HP added fragment.
+
+ * symtab.c (lookup_symbol): Change HPUX_SNAP1 ifdef to a HPUXHPPA ifdef
+
+ * symtab.c (lookup_symbol): Ifdef the searching of symbol in the
+ minimal symbol tables, for hpux we move this check at the end
+ of the function.
+ Before we error out if symbol is not found in the symtab, look
+ in the statics.
+ Before erroring out if static symbol not found look in the globals.
+
+ * symtab.c (lookup_symbol): Return symbol as soon as found.
+ (decode_line_1): Check whether we have a conditional break. Temporarily
+ remove it from the line, to not confure perenthesis checking.
+ Handle namespaces.
+ (overload_list_add_symbol): New function. Overload
+ resolution support.
+ (make_symbol_overload_list): Ditto.
+
+ * symtab.c:
+ (find_template_name_end): New prototype decl.
+ (lookup_symbol): When a global or static symbol shows up in the
+ psymtab table, but not the symtab table, tell the user that
+ the symbol may be an inlined function or a template function and
+ provide some guidance to the user about how to more fully
+ specify the symbol.
+ (lookup_transparent_type): When a global or static symbol shows up
+ in the psymtab table, but not the symtab table, tell the user that
+ the symbol may be an inlined function or a template function and
+ provide some guidance to the user about how to more fully
+ specify the symbol.
+ (decode_line_1): Handle template function specification when decoding a
+ line. May need to be ifdefed for HP's aCC?
+ (_initialize_symtab): Handle dbx commands.
+
+ * symtab.h (address_class): Add new address calss for
+ LOC_THREAD_LOCAL_STATIC and LOC_INDIRECT.
+ (lookup_transparent_type): Add prototype.
+ (exception_event_kind): New enum for exception catchpoints.
+ (exception_event_record): New structure for exception catchpoints.
+ (CURRENT_EXCEPTION_KIND): New macro.
+ (CURRENT_EXCEPTION_CATCH_SAL): New macro.
+ (CURRENT_EXCEPTION_CATCH_LINE): New macro.
+ (CURRENT_EXCEPTION_CATCH_FILE): New macro.
+ (CURRENT_EXCEPTION_CATCH_PC): New macro.
+ (CURRENT_EXCEPTION_THROW_SAL): New macro.
+ (CURRENT_EXCEPTION_THROW_LINE): New macro.
+ (CURRENT_EXCEPTION_THROW_FILE) new macro.:
+ (Current_EXCEPTION_THROW_PC): New macro.
+
+ * symtab.h(make_symbol_overload_list): Add prototype.
+
+ * symtab.h:
+ (symbol_file_add): Add new params to function decl.
+
+ * target.c (cleanup_target): Changed casting of default functions for
+ to_has_forked, to_has_vforked, to_pid_to_exec_file to get rid of
+ warnings.
+
+ * target.c (cleanup_target): Changed the default functions for
+ to_pid_to_exec_file and to_core_file_to_sym_file
+
+ * target.c (cleanup_target): Fixed PARAMS for to_has_syscall_event
+
+ * target.c (cleanup_target): Syntax error, mismatched paranthesis.
+
+ * target.c:
+ (Default_clone_and_follow_inferior): New funct prototype declaration
+ and function definition
+ (dummy_target): More target_ops vector changes for HPUX
+ new fields. ifdefed for HPUX_SNAP2. New fields are
+ to_post_wait, to_post_startup_inferior
+ to_acknowledge_created_inferior, to_clone_and_follow_inferior,
+ to_post_follow_inferior_by_clone, to_create_catch_fork_hook,
+ to_create_catch_vfork_hook, to_has_forked, to_has_vforked,
+ to_post_follow_vfork, to_pid_to_exec_file
+ (de_fault): Add new HPUX specific target_ops operations to
+ the de_fault macro
+ (INHERIT): Add new HPUX specific target_ops operations to the
+ INHERIT macro
+ (find_default_clone_and_follow_inferior): New funct definition
+ (debug_to_post_wait): New funct
+ (debug_to_post_startup_inferior): New funct
+ (debug_to_acknowledge_created_inferior): New funct
+ (debug_to_clone_and_follow_inferior): New funct
+ (debug_to_post_follow_inferior_by_clone): New funct
+ (debug_to_create_catch_fork_hook): New funct
+ (debug_to_create_catch_vfork_hook): New funct
+ (debug_to_has_forked): New funct
+ (debug_to_has_vforked): New funct
+ (debug_to_post_follow_vfork): New funct
+ (setup_target_debug): Initialize new target_ops vector fields.
+
+ * target.c:
+ (Cleanup_target): Fixed the return type on a few of the
+ default function values.
+
+ * target.c:
+ (Dummy_target): Add 3 new fields
+ (nosupport_runtime): New function, used in cleanup_target
+ (cleanup_target): Changes in the de_fault macro, both to
+ accomodate the new target_ops vector fields and to use
+ more accurate default functions.
+ (update_current_target): Add new target_ops vector fields to the
+ INHERIT macro
+ (generic_mourn_inferior): The call to breakpoint_init_inferior now takes a
+ parameter
+ (normal_pid_to_str): Adding a \0 to the end of buf.
+ (debug_to_has_syscall_event): New func
+ (debug_to_enable_exception_callback): New func
+ (debug_to_get_current_exception_event): New func
+ (setup_target_debug): Initialize the 3 new target_ops vector fields
+
+ * target.c:
+ (Struct signals): Fix message associated with SIGRETRACT.
+
+ * target.c:
+ (Dummy_target): Fix syntax error
+ (cleanup_target): Changed the default values for the new
+ target_ops vector fields. HP folks inappropriately set
+ most of them to noprocess(). They should be a mixture
+ of ignore() and return_zero().
+
+ * target.c:
+ (Dummy_target): Add new target_ops vector fields and their initializations
+ (cleanup_target): Added new new target_ops vector fields to the de_fault
+ macro definition.
+ (update_current_target): Added new new target_ops vector fields to the INHERIT
+ macro definition
+ (return_one): New function, used by the de_fault macro
+ (debug_to_post_attach): New function
+ (debug_to_wait): Added new cases: Target_WAITKIND_FORKED, TARGET_WAITKIND_VFORKED,
+ TARGET_WAITKIND_EXECD
+ (debug_to_insert_fork_catchpoint): New function
+ (debug_to_remove_fork_catchpoint): New function
+ (debug_to_insert_vfork_catchpoint): New function
+ (debug_to_remove_vfork_catchpoint): New function
+ (debug_to_can_follow_vfork_prior_to_exec): New function
+ (debug_to_insert_exec_catchpoint): New function
+ (debug_to_remove_exec_catchpoint): New function
+ (debug_to_core_file_to_sym_file): New function
+ (setup_target_debug): Give new fields in current_target target_ops vector values.
+
+ * target.c: Hp merge, 4/15/98 snapshot
+ There are new target_ops fields that pertain only
+ to HPUX. All the changes relate to this. First,
+ new fields are added to the dummy_target target_ops
+ vector: To_require_attach, to_require_detach.
+
+ * target.c: Remove HPUX_SNAP1 and HPUX_SNAP2 ifdefs
+
+ * thread.c (info_threads_command): Call print_only_stack_frame
+ instead of print_stack_frame.
+ (_initialize_thread): Make t an alias for thread only if
+ xdb_commands is not set.
+
+ * thread.c (thread_command): If no arguments, don't generate an
+ error, instead tell the user which thread is current.
+ (info_threads_commands): Don't lose the users position within the
+ current thread -- remember it and then restore it.
+
+ * thread.c:
+ (struct thread_info): Add stepping_through_sigtramp field
+ (add_thread): Initialize stepping_through_sigtramp field
+ (load_infrun_state): Add stepping_through_sigtramp param and
+ make sure it gets assigned a value.
+ (save_infrun_state): Add stepping_through_sigtramp param and
+ make sure that the value gets saved.
+ (info_threads_command): Ifdefing some local variables and
+ code for HPUXHPPA. HP folks want print the tid rather than pid?
+ Also, looks like the HP folks solved the same thread switching
+ problem that 4.17 solves. Taking 4.17.
+ (restore_current_thread): Print out the current frame after
+ switching threads.
+ (thread_apply_all_command): Ifdefing a print statement for
+ HPUXHPPA. The HP folks want to print out a tid rather than pid?
+ (thread_apply_command): Ifdefing a print statement for
+ HPUXHPPA. The HP folks want to print out a tid rather than pid?
+ (thread_command): Decided not to take HP change.
+
+ * thread.c: Fixing gdb core dump problem causing many testsuite
+ failures.
+ (add_thread): Remove call to bpstat_clear, initialize
+ tp->stepping_through_solib_catchpoints = NULL;
+
+ * thread.c: Changes for catchpoints, shared libaries,
+ (thread_info): Additional fields in the thread_info struct
+ for stepping_through_solib_after_catch and
+ stepping_through_solib_catchpoints.
+ (add_thread): Initialize the new thread_info fields.
+ (load_infrun_state): Additional parameters for handling
+ catchpoints and shared libraries.
+ (save_infrun_state): Additional parameters for handling
+ catchpoints and shared libraries.
+
+ * top.c (command_loop): Initialize space_at_cmd_start to 0.
+ (set_prompt): New function.
+ (togglelist, stoplist): New command lists.
+ (command_loop): Tui changes -- paranoia to make sure
+ insert mode is off when not editing.
+ (quit_force): Clean up tui on exit.
+ (init_main): Make definition of info status command dependent upon
+ dbx mode not being set.
+ (fputs_unfiltered_hook): Changed stream parameter from FILE
+ to GDB_FILE
+ (flush_hook): Changed stream parameter from FILE to GDB_FILE
+
+ * top.h (set_prompt): Declare.
+
+ * typeprint.c (whatis_exp): Decide real runtime type. For the vtable
+ case.
+
+ * utils.c (query): Changes to prevent cursor from jumping around in the
+ TUI. Call tuiBufferGetc explicitly, rather than passing it
+ into tuiDo. The tuiDo function does some additional work
+ that is inappropriate when handling queries.
+ (GDB_FILE_ISATTY): New macro that takes a GDB_FILE param and
+ determines whether or not it's using a tty.
+ (gdb_file_isatty); called by the GDB_FILE_ISATTY macro. Does
+ the actual work
+ (init_page_info): Call GDB_FILE_ISATTY rather than ISATTY
+ (print_spaces): Fix parameter to fputc. fix call to
+ gdb_file_adjust_strbuf.
+ (gdb_file_init_astring): Fix parameter to xmalloc
+ (gdb_file_deallocate): New function to deallocate
+ a GDB_FILE object and possibly a string buffer
+ (gdb_file_init_astring): Initialize buffer as the empty
+ string. Indent GNU style.
+ (gdb_fopen): Gdb_fopen is called if the GDB_FILE object is
+ actually afile rather than astring. The routine now allocates space
+ for a GDB_FILE object and initializes its fields in addition to
+ performing an fopen.
+ (gdb_flush): Fix the parameter passed into fflush. It's now
+ stream->ts_filestream.
+ (gdb_fclose): Pass in an object of type GDB_FILE **. Fix parameter
+ to fclose. It's now tmpstream->ts_filestream. Make sure to free
+ the GDB_FILE object and set the GDB_FILE * object to NULL.
+ (gdb_adjust_strbuf): New function. Determine if the current
+ ts_strbuf field contains sufficient space to concatenate a string
+ of length n on the end. If not, then reallocate the ts_strbuf.
+ (print_spaces): Check to see if the GDB_FILE is afile or
+ astring. If it is astring, then adjust the size of the ts_strbuf
+ field and concatenate the correct number of spaces onto the end of
+ the buffer. Otherwise continue to use fputc.
+ (gdb_file_get_strbuf): New function. return a ptr to the ts_strbuf
+ field in a GDB_FILE object.
+ (gdb_file_init_astring): New function to allocate space for and
+ initialize a GDB_FILE object when it is an astring.
+ (set_width): Declare it.
+ (pagination_enabled): Define it.
+ (query): Tui changes.
+ (init_page_info, set_width): New functions.
+ (set_width_command): Call set_width.
+ (_initialize_utils): Replace termcap stuff with call to
+ init_page_info; if xdb_commands set, define am and sm commands;
+ define pagination as a set/show command.
+ (vfprintf_maybe_filtered): Change FILE to GDB_FILE.
+ (fputs_maybe_filtered): Ditto.
+ (print_spaces): Ditto.
+ (gdb_printchar): Ditto.
+ (gdb_flush): Ditto.
+ (fputs_filtered): Ditto.
+ (vfprintf_filtered): Ditto.
+ (vfprintf_unfiltered): Ditto.
+ (fprintf_filtered): Ditto.
+ (fprintf_unfiltered): Ditto.
+ (fprintfi_filtered): Ditto.
+ (print_spaces_filtered): Ditto.
+ (fprintf_symbol_filtered): Ditto.
+ (gdb_fclose): New function.
+
+ * valops.c (call_function_by_hand): Assign to param_type only
+ if function has parameters.
+
+ * valops.c (call_function_by_hand): Ifdef the
+ HP_COMPILED_TARGET stuff.
+ (value_arg_coerce): Ditto.
+
+ * valops.c (call_function_by_hand): Make sure param_type is
+ initialized to NULL.
+
+ * valops.c (find_rt_vbase_offset): Add parameter to value_at.
+ (value_rtti_type): Ditto.
+ (value_full_object): Ditto.
+
+ * valops.c (search_struct_field_aux): Fixed mismatching parenths
+
+ * valops.c (search_struct_field_aux): Make sure TYPE_TAG_NAME
+ is not null before copying it.
+
+
+ * valops.c (search_struct_field_aux): Set found_class_name to null
+ if class has no name (anon unions case). Adjust base_addr
+ computation.
+
+ * valops.c (value_arg_coerce): Change final arg to int.
+
+ * valops.c (value_arg_coerce): Remove the conditional on HP
+ compiled target, for doing coercion of float to double. Removed
+ third parameter, using_gcc.
+ (call_function_by_hand): Do not use HP_COMPILED_TARGET, just
+ use the gcc_compiled variable.
+
+ * valops.c (value_cast): Take case of the enclosing_type and
+ pointer_to_offset fields.
+ (value_at): Use VALUE_CONTENTS_ALL_RAW
+ (value_fetch_lazy): Ditto
+ (value_assign): Handle enclosing_type, embedded_offset and
+ pointed_to_offset fields.
+ (value_repeat): Use VALUE_CONTENTS_ALL_RAW and VALUE_ENCLOSING_TYPE.
+ (value_ind): Set enclosing_type and embedded_offset correctly,
+ for a pointer value being dereferenced. Target memory bytes
+ corresponding to the size of the enclosing type are retreived.
+ (value_addr): Handle enclosing_type and pointed_to_offset.
+ (value_push): Use VALUE_CONTENTS_ALL and VALUE_ENCLOSING_TYPE.
+ (value_arg_coerce): Coerce floats to doubles only if gcc was not
+ used to compile the target.
+ (call_function_by_hand): Handle pointers to functions as paramters.
+ (value_array): Use VALUE_CONTENTS_ALL and VALUE_ENCLOSING_TYPE.
+ (search_struct_method): Produce more informative error message.
+ (find_rt_vbase_offset): Deal with negative offsets.
+ (value_find_oload_method_list): New function. Return the list of
+ overloaded methods of a specified name.
+ (find_method_list): New function. Search through the methods of an
+ object (and its bases) to find a specified method.
+ (value_full_object): New function. Given a value, check its real
+ run-time type.
+ (value_rtti_target_type): New function. Given a pointer value V, find
+ the real (RTTI) type of the object it points to.
+ (value_rtti_type): New function. Find the real run-time type of a
+ value using RTTI.
+
+ * valops.c: Include gdbcmd.h
+ Set global overload_resolution to 0.
+ (find_function_in_inferior): Modify error message.
+ (value_allocate_space_in_inferior): Modify error message.
+ (value_cast): Deal with HP/aCC peculiarities.
+ (value_of_variable): Use SYMBOL_SOURCE_NAME instead of SYMBOL_NAME.
+ (value_addr): Modify address value by adding the embedded offset.
+ (value_ind): Modify the address of the object by the pointed_to_offset.
+ (call_function_by_hand): Do not do any extra alignment if not needed.
+ Fetch the return value from the stack rather then from the register,
+ for the hppa architecture.
+ (search_struct_field): Rewritten. Now this function uses
+ search_struct_field_aux to do all the work.
+ (search_struct_field_aux): New function. This is the old
+ search_struct_field rewritten.
+ (find_rt_vbase_offset): Give error if virtual table pointer is not good.
+ (find_overload_match): New function. Find the best function that
+ matches on the argument types according to the overload resolution
+ rules.
+ (_initialize_valops): Add new set/show command for overload-resolution.
+
+ * value.h (VALUE_POINTED_TO_OFFSET): New macro.
+ Add field pointed_to_offset to value structure.
+ Add prototypes for new functions in valops.c.
+
+ * value.h (write_register_pid): Change prototype to match
+ function.
+
+ * value.h: Hp merge, 4/15/98 snapshot
+ Added parameter to val_print func decl.
+ Added new macro, VALUE_EMBEDDED_OFFSET, and
+ new func decl, find_rt_vbase_offset, for C++
+ support.
+
+ * values.c (allocate_value): Allocate also for value_embedded_offset
+ and value_enclosing_type.
+ (value_copy): Copy value_embedded_offset and value_enclosing_type too.
+ Use all_raw in copying the value itself.
+ (value_primitive_field): Add handling of base subobjects.
+
+ * values.c (value_copy): Copy the pointed_to_offset as well.
+ (allocate_value): Allocate the pointed_to_offset as well.
+ (value_virtual_fn_field): Rewrite.
+
+ * values.c (value_primitive_field): Adjust embedded offset and
+ offset calculation.
+
+ * values.c (value_static_field): Take into consideration that static
+ data members can be minimal symbols too.
+
+ * values.c (value_virtual_fn_field): Fix call to value_at.
+
+ * win32-nat.c (handle_load_dll): Added params to call to symbol_file_add.
+
+ Other changes have to do with XDB compatability. Leave oout
+ for now.
+
+ defs.h (vfprintf_filtered): Change FILE to GDB_FILE in decl.
+ (fprintf_filtered): Ditto.
+ (fprintfi_filtered): Ditto.
+ (vfprintf_unfiltered): Ditto.
+ (fprintf_unfiltered): Ditto.
+
+ infcmd.c (_initialize_infcmd): If xdb_commands is set, make S an
+ alias for next and define R, lr, g. Define go.
+
+ pyr-tdep.c (pyr_print_insn): Change FILE to GDB_FILE.
+
+
+ * breakpoint.c (create_temp_exception_breakpoint): #If it out --
+ nothing calls it.
+ (bpstat_stop_status): Don't call SOLIB_HAVE_LOAD_EVENT if it's not
+ defined; don't call SOLIB_HAVE_UNLOAD_EVENT if it's not defined.
+ (bpstat_get_triggered_catchpoints): If we don't have shared
+ library support, then don't call SOLIB_LOADED_LIBRARY_PATHNAME nor
+ SOLIB_UNLOADED_LIBRARY_PATHNAME.
+ (watch_command_1): Don't require a run before a watch command
+ unless we're on HP [it's an HP OS bug, not a generic limitation]
+ (catch_load_command_1): Don't define if no shared libraries.
+ (catch_command_1): Don't claim to support fork catchpoints unless
+ CHILD_INSERT_FORK_CATCHPOINT is defined, don't claim to support
+ vfork catchpoints unless CHILD_INSERT_VFORK_CATCHPOINT is defined,
+ don't clain to support shared library load catchpoints if shared
+ libraries aren't supported, and don't claim to support exec
+ catchpoints unless CHILD_INSERT_EXEC_CATCHPOINT is defined
+
+ There are new target_ops vector fields that pertain
+ only to HPUX. Added the to_require_attach and
+ to_require_detach fields to exec_ops. These new
+ fields are ifdef'ed for HPUX_SNAP1.
+
+ * breakpoint.h:
+ Fix compile error in enum bptype.
+
+ * coff-solib.h:
+ Fixed a number of macro definitions. SOLIB_LOADED_LIBRARY_PATHNAME,
+ SOLIB_HAVE_LOAD_EVENT, SOLIB_HAVE_UNLOAD_EVENT,
+ SOLIB_UNLOADED_LIBRARY_PATHNAME, SOLIB_IN_DYNAMIC_LINKER. These
+ macros are only meaningful (for now) for SOM. So, all
+ the macros were defined as error(...), but were used in
+ conditions. This caused the compile to crap out. I redefined
+ these (for now) to be 0.
+
+ * procfs.c:
+ (procfs_create_inferior): Fix call to fork_inferior -- need another
+ parameter.
+
+ * solib.h:
+ Fixed a number of macro definitions. SOLIB_LOADED_LIBRARY_PATHNAME,
+ SOLIB_HAVE_LOAD_EVENT, SOLIB_HAVE_UNLOAD_EVENT,
+ SOLIB_UNLOADED_LIBRARY_PATHNAME, SOLIB_IN_DYNAMIC_LINKER. These
+ macros are only meaningful (for now) for SOM. So, all
+ the macros were defined as error(...), but were used in
+ conditions. This caused the compile to crap out. I redefined
+ these (for now) to be 0.
+
+ * valops.c:
+ (search_struct_field): Undeclared local variable, "assigned".
+ (find_rt_vbase_offset): Fixed call to value_at
+
+ * value.h: Fix signature for find_rt_vbase_offset funct decl
+ (missing a param)
+
+Wed Dec 30 17:48:12 1998 Stan Shebs <shebs@andros.cygnus.com>
+
+ From J.T. Conklin <jtc@redbacknetworks.com>:
+ * i386-stub.c: Fix error string in last change.
+
+1998-12-30 Jason Molenda (jsm@bugshack.cygnus.com)
+
+ * utils.c: <Readline/readline.h> instead of "readline/readline.h".
+
+ * configure.in (TERM_LIB): Search for the appropriate term library
+ on the host system.
+ * configure: Regenerated.
+ * Makefile.in (TERMCAP): Set based on autoconf check.
+ * config/*/*.mh: Don't override TERMCAP setting.
+
+Wed Dec 30 17:23:14 1998 Mark Alexander <marka@cygnus.com>
+
+ * value.c (value_virtual_fn_field): Handle the situation where
+ vtbl is a pointer to a structure instead of a pointer to an array.
+
+Mon Dec 28 17:43:36 1998 David Taylor <taylor@texas.cygnus.com>
+
+ The following changes were made by Jim Blandy <jimb@cygnus.com>,
+ Edith Epstein <eepstein@cygnus.com>, Elena Zannoni
+ <ezannoni@cygnus.com> Stan Shebs <shebs@cygnus.com>, and David
+ Taylor <taylor@cygnus.com>, as part of the project to merge in
+ changes originally made by HP; HP did not create ChangeLog
+ entries.
+
+ * c-lang.h (cp_print_value_fields): Update prototype; fixed
+ prototype decl for c_val_print function -- it needed an
+ embedded_offset param; fixed prototype of cp_print_value_fields.
+ Include value.h.
+ (C_LANG_H): Define.
+
+ * c-valprint.c (c_val_print): Add new parameter embedded_offset.
+ Add embedded_offset to valaddr in function calls. fix calls to
+ val_print, and cp_print_value_fields. Attempt to determine the
+ real type of the object to be printed. fixed call to
+ cp_print_value_fields. process TYPE_CODE_METHOD as well. moved
+ call to check_typedef out of conditional. add embedded offset
+ param to val_print call.
+
+ (c_value_print): Add new parameter to call to val_print. Handle
+ pointer to class case. Ensure that const char *, const unsigned
+ char * come out without the type but the volatile variants and the
+ signed variants don't.
+
+ * ch-lang.h (chill_val_print): Add parameter to decl.
+
+ * ch-valprint.c: The various print routines have an additional
+ parameter. Currently, the new parameter is only used when printing
+ C++ expressions. So, in ch-valprint.c, the new parameter is always
+ 0. Changes in calls to val_print, chill_val_print, c_val_print
+ Affected functions are chill_val_print_array_elements,
+ chill_val_print, chill_print_value_fields, chill_value_print.
+
+ * cp-valprint.c add vtable pointers names for aCC (HP) compiler.
+ (cp_print_class_method): Print message for HP/aCC case.
+ (cp_print_class_member): Add comments.
+ (cp_print_value): Adjust address computations for virtual base
+ classes. add new parameter 'offset'. Find correct offset for
+ base class in HP/aCC case. Change call to cp_print_value_fields
+ to have extra par.
+ (cp_print_value_fields): Do not print also if the only field is
+ the vtable pointer. Print out vtable ptr, for HP/aCC compiled
+ case. do not print leading '=' in case of anonymous union, or
+ struct. add new parameter 'offset'. Do not print the vtable
+ pointer as a member, in the HP aCC case. Changed calls to
+ val_print to have extra parameter.
+ (cp_print_hpacc_virtual_table_entries): New function. Print vtable
+ entries, in HP/aCC compiled case.
+ (cp_print_static_field): Change call to cp_print_value_fields, and
+ val_print.
+
+ * d30v-tdep.c (d30v_print_register): Add embedded_offset param
+ to val_print call.
+
+ * defs.h: Additional include files included when TUI is defined.
+ (gdb_file_isatty): New function decl.
+ (GDB_FILE): If TUI is defined, define a structure rather
+ than making this an alias for FILE.
+ (gdb_stdout, gdb_stderr): If TUI is defined, then define these
+ as pointers to variables of type GDB_FILE rather than making them
+ be aliases for stdout and stderr.
+ (TUIDO): Add definition conditionalized on definition
+ (or lack thereof) of TUI.
+ (command_class): Add two additional values.
+ (precision_type): New enum.
+ (gdb_fclose): Add decl.
+ (store_address): Change prototype to match function.
+ (tui_version, xdb_commands, dbx_commands): Add decls.
+ (gdb_file_deallocate): New function decl
+ (pa_do_strcat_registers_info): New function decl.
+ (streamtype): New enumerated type to distinguish between output to
+ a FILE and output to a buffer.
+ (tui_stream): New struct type, named GDB_FILE.
+ (gdb_stdout): Of type GDB_FILE, will pass this around gdb rather
+ than stdout.
+ (gdb_stderr): Of type GDB_FILE, will pass this around gdb rather
+ than stderr.
+ (fputs_unfiltered_hook): Change stream parameter from FILE to
+ GDB_FILE.
+ (flush_hook): Change stream parameter from FILE to GDB_FILE.
+ (gdb_fclose): Fix decl for gdb_fclose; parameter is now of
+ type GDB_FILE **.
+ (gdb_file_adjust_strbuf): New function decl. function lives
+ in utils.c.
+ (gdb_file_init_astring): New function decl. function lives
+ in utils.c.
+ (gdb_file_get_strbuf): New function decl. function lives in
+ utils.c.
+ (source_full_path_of): Declare.
+
+ * exec.c (_initialize_exec): Make definition of file command be
+ dependent upon dbx_commands not being set.
+ (exec_file_attach): New function.
+ (exec_file_command): Call it.
+ (exec_ops): Add new target vector fields.
+
+ * f-lang.h (f_print_type): Change FILE to GDB_FILE in decl.
+ (f_val_print): Ditto.
+ (f_val_print): Add parameter to the function decl.
+
+ * f-valprint.c (_initialize_f_valprint): If xdb_commands is set,
+ define lc command.
+ (f77_create_arrayprint_offset_tbl): Change FILE to GDB_FILE.
+ (f77_print_array): Ditto.
+ (f77_print_array_1): Ditto.
+ (f_val_print): Ditto.
+ (f_val_print): Add a parameter; this new parameter is currently
+ only non-zero when handling C++ expressions. In this file its
+ value is always 0. changed fflush to gdb_flush.
+
+ * gnu-nat.c: (init_gnu_ops): Add new target vector fields.
+ (gnu_create_inferior): Add param to fork_inferior call.
+
+ * hppa-tdep.c (after_prologue): If f is NULL, don't dereference
+ it. if no debug info, return zero telling caller that we need to
+ find the end of the prologue via the hard way (instruction
+ examination).
+ (find_unwind_entry): Avoid dereferencing a null
+ pointer.
+ (hppa_pid_to_exec_file): Deleted -- no longer used.
+ (hppa_prepare_to_proceeed): Add prototype.
+ (read_unwind_info): Purecov comments, bug fixes.
+ (find_unwind_entry): Purecov comments, bug fixes.
+ (find_stub_with_shl_get): Purecov comments.
+ (frame_chain): Additional parens.
+ (hppa_push_arguments): Changes to commented out version of routine.
+ (hppa_fix_call_dummy): Purecov comments, fix location of end.o.
+ (in_solib_call_trampoline): Purecov comments.
+ (in_solib_return_trampoline): Purecov comments.
+ (setup_d_pid_in_inferior): Fix location of end.o.
+ (initialize_hp_cxx_exception_support): Fix location of end.o.
+ (child_enable_exception_callback): Purecov comments.
+ (pa_do_strcat_registers_info): Has a new parameter, precision,
+ which is passed into the call to pa_strcat_fp_reg to indicate
+ whether to display the floating point registers using
+ single or double preceision.
+ (pa_strcat_registers): Introduce local variable, precision, and
+ pass it into call to pa_strcat_fp_reg.
+ (pa_strcat_fp_reg): Modified function. New parameter, precision,
+ used by function to decide whether to use single or double
+ precision. Also add the code to put a double precision value
+ into a buffer.
+ (pa_do_strcat_registers_info): New routine. called by
+ tui/tuiRegs.c:_tuiRegisterFormat to place a register name
+ and value into a string buffer. Interface may change in
+ future. Checking this in so that we have something
+ functional for HP.
+ (pa_strcat_registers): New routine, called by
+ pa_do_strcat_registers_info. Does same thing as
+ pa_print_registers except it takes a stream parameter.
+ This routine should disappear in future. Checking in
+ so that we have something functional to give HP
+ (pa_strcat_fp_reg): New routine, called by
+ pa_do_strcat_registers_info and pa_strvat_registers
+ to place a floating point register name and value into
+ a buffer. This interface may change in future.
+ Checking in so that we have something functional to give HP.
+ (pa_print_fp_reg): Change prototype to match def'n.
+ (pa_register_look_aside): Fix comment immediately before function.
+ Changes to better support stack unwinding, reading and writing
+ registers for HPUX. New includes ptrace.h, bfd.h, dl.h.
+ (internalize_unwinds): Initialize new fields in table.
+ (read_unwind_info): Entries in the table are now more complex
+ structures. References of the form ...->table[index].stub_type are
+ now ...->table[index].stub_unwind.stub_type.
+ (find_proc_framesize): Add a check for pc == 0.
+ (rp_saved): Entries in the table are now more complex
+ structures. References of the form ...->table[index].stub_type are
+ now ...->table[index].stub_unwind.stub_type.
+ (frameless_function_invocation): Stub_type becomes
+ stub_unwind.stub_type
+ (saved_pc_after_call): Stub_type becomes stub_unwind.stub_type
+ (hppa_frame_saved_pc): Stub_type becomes stub_unwind.stub_type
+ (frame_chain_valid): Stub_type becomes stub_unwind.stub_type
+ (hppa_call_dummy): Stub_type becomes stub_unwind.stub_type
+ (pa_print_fp_reg): Additional params to call val_print
+ (in_solib_call_trampoline): Stub_type becomes
+ stub_unwind.stub_type
+ (in_solib_return_trampoline): Stub_type becomes
+ stub_unwind.stub_typ
+ (skip_trampoline_code): Additional code to handle external
+ dyncalls. Also stub_type becomes stub_unwind.stub_type
+ (hppa_pid_to_exec_file): New funct. FOr HPUX 10.0 and beyond there
+ is an explicit ptrace request for getting the pathname associated
+ with a process id (pid).
+ (hppa_pid_to_exec_file): Remove unwanted param from call to
+ call_ptrace.
+ (args_for_find_stub): New structure.
+ (find_unwind_entry): Deal with null input pc value.
+ (rp_saved): Ditto.
+ For the import stub, return -24 always.
+ (hppa_frame_saved_pc): Save old pc value, to detect we are in a loop.
+ (init_extra_frame_info): Use TARGET_READ_FP.
+ (frame_chain): Include thread support.
+ If the caller's pc is zero, we lose and return, just like stack
+ bottom.
+ Disable warning about being unable to find unwind info.
+ (hppa_push_arguments): Rewrite.
+ (hppa_value_returned_from_stack): New function. Handles returning
+ a value larger than 64 bits, stored on the stack.
+ (find_stub_with_shl_get): New function. To look up symbols in shlibs.
+ (cover_find_stub_with_shl_get): New function. Cover routine for
+ find_stub_with_shl_get to pass to catch_errors.
+ (hppa_fix_call_dummy): Comment out old stub mechanism.
+ Rewrite using dyncall.
+ (target_read_fp): New function.
+ (pa_do_registers_info): Floating point registers start at FP4.
+ (pa_print_registers): Use FP4_REGNUM instead of 72.
+ (skip_trampoline_code): Do machine instruction matching for PA2.0.
+ (setup_d_pid_in_inferior): New function. Exception handling support.
+ (initialize_hp_cxx_exception_support): Ditto.
+ (child_enable_exception_callback): Ditto.
+ (child_get_current_exception_event): Ditto.
+
+ * hpux-thread.c (hpux_thread_ops): Add new target vector fields.
+
+ * infcmd.c: Include objfiles.h.
+ (attach_command): New local variable, exec_file, add code to
+ determine exec_file from pid if exec_file is not already known,
+ call new target operation, target_post_attach -- a no-op unless
+ on HPUXHPPA.
+ (detach_command): After detaching, do a SOLIB_RESTART.
+ (objfiles.h): Fix typo on include line.
+ (run_command): Only call SOLIB_RESTART if it's defined.
+ (detach_command): Ditto.
+ (run_command): If program has already been started, and decide
+ to restart it, the kill the target, flush the caches,
+ call init_wait_for_inferior. Also purge old solib objfiles.
+ (run_stack_dummy): Add calls to
+ disable_watchpoints_before_interactive_call_start and
+ enable_watchpoints_after_interactive_call_stops.
+ (finish_command): Alter code handling the evaluation and printing
+ of the target function's return value.
+ (attach_command): When given a pid, but no exec file, try to
+ determine the exec file from the process. If the process does not
+ record a full path name, try to qualify the filename against the
+ source path.
+ (_initialize_infcmd): Add some verbiage about how to use the
+ attach command.
+ (do_registers_info): Changed calls to val_print
+ made the symfile.h include preceed the
+ objfiles.h include. The other ordering caused a
+ compile problem (incompletely defined types).
+
+ * inftarg.c (child_post_attach): Fix decl, make static.
+ (proc_wait): Make globally visible.
+ (child_insert_fork_catchpoint, etc): Fix return type.
+ (child_detach_from_process): Declare.
+ (child_attach_to_process): Declare.
+ (child_stop): Make static to match decl.
+ (ptrace_him): Change prototype back to return int.
+ (ptrace_me): Remove debug output, pass NULL to fork_inferior if
+ not HPUX.
+ (proc_wait): function prototype and definition are enclosed by
+ proc_wait ifndef
+ (child_attach_to_process): New function, does most of the work
+ that child_attach used to do and some additional work to determine
+ whether gdb is already attached to the target how to react.
+ (child_attach): Altered. It's now a wrapper for
+ child_attach_to_process.
+ (child_require_attach): New function, called if should attach even
+ when gdb is already attached to target.
+ (child_detach_from_process): New function, does most of the work
+ that child_detach used to do and some additional work to determine
+ whether gdb is currently attached to the target.
+ (child_detach): Altered. It's now a wrapper for
+ child_detach_from_process.
+ (child_require_detach): New function, called if should try to
+ detach even when gdb is not attached to target.
+ (ptrace_him): Calls a new function,
+ target_acknowledge_forked_child. Currently,
+ target_acknowledge_forked_child, is only defined to do something
+ for HPUX.
+ (child_create_inferior): Changed call to fork_inferior.
+ (child_ops): Add to_require_attach and to_require_detach fields
+ to the child_ops target ops vector.
+ Some hacks for ttrace work:
+ (child_wait): Additional local variables, additional code in
+ while loop to check for process exited, process forked,
+ process vforked, process execd.
+ (child_thread_alive): John B. seems to think that the kill
+ call is inapproapriate for HPUX.
+ (child_attach_to_process): Using strtol rather than atoi.
+ no longer check for case where there is no known exec file.
+ (child_post_attach): New function, a default, a no-op.
+ (child_insert_fork_catchpoint): New function, a default, a no-op.
+ (child_remove_fork_catchpoint): New function, a default, a no-op.
+ (child_insert_vfork_catchpoint): New function, a default, a no-op.
+ (child_remove_vfork_catchpoint): New function, a default, a no-op.
+ (child_can_follow_vfork_prior_to_exec ):new function, a default,
+ a no-op.
+ (child_insert_exec_catchpoint): New function, a default, a no-op.
+ (child_remove_exec_catchpoint): New function, a default, a no-op.
+ (child_has_execd): New function, a default, returns 0.
+ (child_reported_exec_events_per_exec_call): New function, a
+ default, returns 1.
+ (child_has_exited): New function, a default.
+ (child_core_file_to_sym_file): New function, a default, returns NULL.
+ (child_ops): Initialize new target vector fields.
+
+ * jv-lang.h: (Java_val_print): Add embedded_offset param to func
+ decl.
+
+ * jv-valprint.c: Changing calls to val_print to accomodate new param.
+ (java_value_print): Add embedded_offset param to val_print call
+ (java_print_value_fields): Add embedded_offset param to val_print
+ call.
+ (java_val_print): Add embedded_offset param. alter call to
+ c_val_print to accomodate embedded_offset param.
+
+ * language.c (lang_bool_type): Return builtin_type_bool in c++
+ case.
+ (unk_lang_val_print): Add embedded_offset param to
+ prototype decl and definition.
+
+ * language.h (LA_VAL_PRINT macro, la_val_print function decl):
+ altered to accomodate the new parameter to the various print
+ functions.
+
+ * m2-lang.h (m2_val_print): Add a parameter to the function decl.
+
+ * m2-valprint.c (m2_val_print): Add a parameter.
+ This parameter is currently only used when evaluating C++
+ expressions. So, it is always 0 in this file.
+
+ * m3-nat.c (m3_create_inferior): Add param to fork_inferior call
+ (m3_pid_to_exec_file): New function
+ (m3_ops): Add new target vector fields.
+
+ * mac-nat.c (init_child_ops): Add new target vector fields.
+
+ * mips-tdep.c: Chnages to accomodate additional parameter
+ to val_print.
+ (mips_print_register): Alter calls to val_print
+
+ * monitor.c (monitor_write): Change stderr to gdb_stderr.
+ (monitor_remove_breakpoint): Ditto.
+ (init_base_monitor_ops): Add new target vector fields.
+
+ * ppc-bdm.c (init_bdm_ppc_ops): Add new target vector fields.
+
+ * printcmd.c (do_examine): When saving a value_ptr, remove it from
+ the list of value_ptr's to be freed automatically; when discarding
+ a previously saved value_ptr, free it.
+ (print_formatted): Update comments; add new comments.
+ (printf_command, print_insn): Purecov comments.
+ (_initialize_printcmd): Add assign as a command if dbx_commands is
+ set; create va as an alias for disassemble if xdb_commands is set.
+ (address_info): New cases LOC_INDIRECT and
+ LOC_THREAD_LOCAL_STATIC.
+ (display_command): If tui_version and exp starts with a '$', then
+ don't display it unless tui_vSetLayoutTo fails.
+ (disassemble_command): Add tuiDo calls.
+ (print_scalar_formatted): For integers that are long long, check
+ the print format and print out in binary octal, decimal, or
+ hex. Call the new print_*_chars functions in valprint.c
+ (print_frame_args): Altered calls to val_print, to reflect
+ additional parameter to val_print (case LOC_BASEREG_ARG).
+
+ * procfs.c: (Procfs_init_inferior): Return value is now a void.
+ (procfs_ops): Add new target vector fields.
+ (procfs_create_inferior): Fix call to fork_inferior -- need another
+ parameter.
+
+ * remote-adapt.c (adapt_open): Change stderr to gdb_stderr.
+ (adpat_insert_breakpoint): Ditto.
+ (init_adapt_ops): Add new target vector fields.
+
+ * remote-array.c (array_wait): Change fflush to gdb_flush and
+ stdout to gdb_stdout.
+ (init_array_ops): Add new target vector fields.
+
+ * remote-bug.c (bug_load): Change fflush to gdb_flush; stdout to
+ gdb_stdout.
+ (bug_wait): Change stderr to gdb_stderr.
+ (bug_insert_breakpoint): Ditto.
+ (init_bug_ops): Add new target vector fields.
+
+ * remote-e7000.c
+ (init_e7000_ops): Add new target vector fields.
+ * remote-eb.c (init_eb_ops): Ditto.
+ * remote-es.c (init_es1800_ops): Ditto.
+ (init_es1800_child_ops): Ditto.
+ * remote-es.c (init_es1800_ops): Ditto.
+ (init_es1800_child_ops): Ditto.
+ * remote-hms.c (init_hms_ops): Ditto.
+ * remote-hms.c (init_hms_ops): Ditto.
+ * remote-nindy.c (init_nindy_ops): Ditto.
+ * remote-nrom.c (init_nrom_ops): Ditto.
+ * remote-os9k.c (init_rombug_ops): Ditto.
+ * remote-rdp.c (init_remote_rdp_ops): Ditto.
+ * remote-sds.c (init_sds_ops): Ditto.
+ * remote-sim.c (init_gdbsim_ops): Ditto.
+ * remote-st.c (init_st2000_ops): Ditto.
+ * remote-udi.c (init_udi_ops): Ditto.
+ * remote-vx.c (init_vx_ops): Ditto.
+ (init_vx_run_ops): Ditto.
+ * remote-vx.c: (Init_vx_ops): Ditto.
+ (init_vx_run_ops): Ditto.
+
+ * remote-mips.c (mips_getstring): Change stderr to gdb_stderr.
+ (pmon_insert_breakpoint): Ditto.
+ (pmon_remove_breakpoint): Ditto.
+ (check_lsi_error): Ditto.
+ (common_breakpoint): Ditto.
+ (pmon_makeb64): Ditto.
+
+ * remote-mips.c (mips_xfer_memory): Change fflush to gdb_flush;
+ change stdout to gdb_stdout.
+
+ * remote-mm.c (mm_open): Change stderr to gdb_stderr.
+ (init_mm_ops): Add new target vector fields.
+ (mm_load): Fixed params in commented out call to symbol_file_add.
+
+ * remote-nindy.c (instream): Change decl to FILE.
+
+ * remote-udi.c (udi_load): Fixed params in call to symbol_file_add.
+
+ * remote-vx.c (vx_add_symbols): Fixed params in call to
+ symbol_file_add.
+
+ * remote.c (init_remote_ops): Cosmetic change to match expected
+ test output.
+
+ * rs6000-nat.c (add_vmap): Add params to call to allocate_objfile.
+
+ * scm-lang.h: Add parameter to scm_val_print function decl.
+
+ * scm-valprint.c (scm_scmval_print): Cast svalue to (int); new
+ parameter. This parameter is currently only used when evaluating
+ C++ expressions. So, it is always 0 in this file.
+ (c_val_print): Fixed prototype decl; it needed an embedded_offset
+ param.
+
+ * sol-thread.c (sol_core_ops): Add new target vector fields.
+ (sol_thread_ops): Ditto.
+
+ * somsolib.c (DLD_FLAGS_MAPPRIVATE): New macro.
+ Define bit of __dld_flags in HP-UX a.out files.
+ (DLD_FLAGS_HOOKVALID): Ditto.
+ (DLD_FLAGS_LISTVALID): Ditto.
+ (DLD_FLAGS_BOR_ENABLE): Ditto.
+ (som_solib_total_st_size): Cumulative size in bytes of the
+ symbol tables of all shared objects on the so_list_head list.
+ (som_solib_st_size_threshhold_exceeded): Threshold for adding symbols
+ for shlibs.
+ (som_solib_sizeof_symbol_table): New function. Computes size of
+ symbol table for a shlib.
+ (som_solib_load_symbols): New function. Load symbols from shlib.
+ (som_solib_add): Detect if __dld_list is not valid.
+ Record main program's symbol table size.
+ Load symbols if called from command line.
+ Keep threshold into account when loading shlib symbols.
+ (som_solib_create_inferior_hook): Use dld_flags macros.
+ (som_sharedlibrary_info_command): Let user know if symbols were
+ not loaded.
+ (som_solib_restart): Discard all the shlibs descriptors.
+ (_initialize_som_solib): Chenge help message for auto-solib-add
+ command.
+ Set threshold for symbol table to 50 megabytes.
+ (_initialize_som_solib): Add call to som_solib_restart.
+ (som_solib_restart): New function
+ (som_solib_in_dynamic_linker): New function
+ (som_solib_desire_dynamic_linker_symbols): New function
+ (som_solib_unloaded_library_pathname): New function
+ (som_solib_loaded_library_pathname): New function
+ (som_solib_library_pathname): New function
+ (som_solib_have_unload_event): New function
+ (som_solib_have_load_event): New function
+ (som_solib_create_catch_unload_hook): New function
+ (som_solib_create_catch_load_hook): New function
+ (som_solib_create_inferior_hook): Rewritten
+ dld_cache: New struct
+ addr_and_unwind_t: New struct
+ (find_unwind_entry) add prototype
+ Include assert.h, remove references to ASSERT macro,
+ add include of fcntl.h so that O_RDONLY is defined.
+ (som_solib_create_inferior_hook): Introduce new local
+ msymbol2 and change some msymbol's to msymbol2's -- was clobbering
+ msymbol, passing a NULL to lookup_minimal_symbol_solib_trampoline,
+ and ultimately core dumping with a SEGV.
+ (som_solib_mapped_entry): Additional comments for text_addr,
+ text_link_addr, text_end, and tsd_start_addr fields. Commenting
+ out 2 tsd fields, __data_start and __data_end.
+ (som_solib_add_solib_objfile): Add params to calls to symbol_file_add.
+ Add some code for distinguishing between a shared library and other
+ objfiles. This appears to be a prelude to thread local storage.
+ (som_solib_load_symbols): Changes to printf statement
+ enclosed by SOLIB_DEBUG ifdef.
+ (som_solib_add): Change comment to correctly specify path
+ to end.o -- /opt/langtools/lib/end.o. changes to printf statement
+ enclosed by SOLIB_DEBUG ifdef.
+ Removed several SOLIB_DEBUG ifdefs and the associated printfs.
+ Add code to find the start address for the object file's thread
+ local storage
+ (som_solib_create_inferior_hook): Fix warning messages use correct
+ path to end.o -- /opt/langtools/lib/end.o. Change control flow.
+ No longer user early returns from function is cases of error.
+ (reset_inferior_pid): New function
+ (som_solib_remove_inferior_hook): New function
+ (so_lib_thread_start_addr): New function. used for tsd.
+ (struct som_solib_mapped_entry): Add new field tsd_start_addr.
+ (struct so_list): Add new field solib_addr.
+ (som_solib_add_solib_objfile): New function.
+ (som_solib_load_symbols): Rewritten.
+ (som_solib_add): Make sure we don't load the symbols in if the
+ threshold was exceeded.
+ (som_solib_get_solib_by_pc): New function. Return the address of
+ handle of the shared library.
+ (som_solib_restart): Disable breakpoints at restart.
+
+ * sparcl-tdep.c (init_sparclite_ops): Add new target vector fields.
+
+ * target.c (cleanup_target): Changed casting of default functions
+ for to_has_forked, to_has_vforked, to_pid_to_exec_file to get rid
+ of warnings. Fixed PARAMS for to_has_syscall_event. Fixed the
+ return type on a few of the default function values.
+ (cleanup_target): Changes in the de_fault macro, both to
+ accomodate the new target_ops vector fields and to use
+ more accurate default functions.
+ (debug_to_open): Change stderr to gdb_stderr.
+ (debug_to_close): Ditto.
+ (debug_to_attach): Ditto.
+ (debug_to_post_attach): Ditto.
+ (debug_to_require_attach): Ditto.
+ (debug_to_detach): Ditto.
+ (debug_to_require_detach): Ditto.
+ (debug_to_resume): Ditto.
+ (debug_to_wait): Ditto.
+ (debug_to_post_wait): Ditto.
+ (debug_to_fetch_registers): Ditto.
+ (debug_to_store_registers): Ditto.
+ (debug_to_prepare_to_store): Ditto.
+ (debug_to_xfer_memory): Ditto.
+ (debug_to_files_info): Ditto.
+ (debug_to_insert_breakpoint): Ditto.
+ (debug_to_remove_breakpoint): Ditto.
+ (debug_to_terminal_init): Ditto.
+ (debug_to_terminal_inferior): Ditto.
+ (debug_to_terminal_ours_for_output): Ditto.
+ (debug_to_terminal_ours): Ditto.
+ (debug_to_terminal_info): Ditto.
+ (debug_to_kill): Ditto.
+ (debug_to_load): Ditto.
+ (debug_to_lookup_symbol): Ditto.
+ (debug_to_create_inferior): Ditto.
+ (debug_to_post_startup_inferior): Ditto.
+ (debug_to_acknowledge_created_inferior): Ditto.
+ (debug_to_clone_and_follow_inferior): Ditto.
+ (debug_to_post_follow_inferior_by_clone): Ditto.
+ (debug_to_insert_fork_catchpoint): Ditto.
+ (debug_to_remove_fork_catchpoint): Ditto.
+ (debug_to_insert_vfork_catchpoint): Ditto.
+ (debug_to_remove_vfork_catchpoint): Ditto.
+ (debug_to_has_forked): Ditto.
+ (debug_to_has_vforked): Ditto.
+ (debug_to_can_follow_vfork_prior_to_exec): Ditto.
+ (debug_to_post_follow_vfork): Ditto.
+ (debug_to_insert_exec_catchpoint): Ditto.
+ (debug_to_remove_exec_catchpoint): Ditto.
+ (debug_to_has_execd): Ditto.
+ (debug_to_reported_exec_events_per_exec_call): Ditto.
+ (debug_to_has_syscall_event): Ditto.
+ (debug_to_has_exited): Ditto.
+ (debug_to_mourn_inferior): Ditto.
+ (debug_to_can_run): Ditto.
+ (debug_to_notice_signals): Ditto.
+ (debug_to_thread_alive): Ditto.
+ (debug_to_stop): Ditto.
+ (debug_to_enable_exception_callback): Ditto.
+ (debug_to_get_current_exception_event): Ditto.
+ (debug_to_pid_to_exec_file): Ditto.
+ (debug_to_core_file_to_sym_file): Ditto.
+ (default_clone_and_follow_inferior): New function prototype
+ decl and function definition.
+ (dummy_target): Add new target_ops vector fields and their
+ initializations. More target_ops vector changes for HPUX new
+ fields.
+ (de_fault): Add new HPUX specific target_ops operations to the
+ de_fault macro
+ (INHERIT): Add new HPUX specific target_ops operations.
+ (debug_to_post_wait): New function.
+ (debug_to_post_startup_inferior): Ditto.
+ (debug_to_acknowledge_created_inferior): Ditto.
+ (debug_to_clone_and_follow_inferior): Ditto.
+ (debug_to_post_follow_inferior_by_clone): Ditto.
+ (debug_to_create_catch_fork_hook): Ditto.
+ (debug_to_create_catch_vfork_hook): Ditto.
+ (debug_to_has_forked): Ditto.
+ (debug_to_has_vforked): Ditto.
+ (debug_to_post_follow_vfork): Ditto.
+ (setup_target_debug): Initialize new target_ops vector fields.
+ (nosupport_runtime): New function, used in cleanup_target
+ (update_current_target): Add new new target_ops vector fields to
+ the INHERIT macro definition.
+ (generic_mourn_inferior): The call to breakpoint_init_inferior now
+ takes a parameter.
+ (normal_pid_to_str): Add a \0 to the end of buf.
+ (debug_to_has_syscall_event): New function.
+ (debug_to_enable_exception_callback): New function.
+ (debug_to_get_current_exception_event): New function.
+ (setup_target_debug): Initialize the 3 new target_ops vector fields
+ (struct signals): Fix message associated with SIGRETRACT.
+ (return_one): New function, used by the de_fault macro
+ (debug_to_post_attach): New function.
+ (debug_to_wait): Add new cases TARGET_WAITKIND_FORKED,
+ TARGET_WAITKIND_VFORKED, TARGET_WAITKIND_EXECD.
+ (debug_to_insert_fork_catchpoint): New function.
+ (debug_to_remove_fork_catchpoint): Ditto.
+ (debug_to_insert_vfork_catchpoint): Ditto.
+ (debug_to_remove_vfork_catchpoint): Ditto.
+ (debug_to_can_follow_vfork_prior_to_exec): Ditto.
+ (debug_to_insert_exec_catchpoint): Ditto.
+ (debug_to_remove_exec_catchpoint): Ditto.
+ (debug_to_core_file_to_sym_file): Ditto.
+ (setup_target_debug): Give new fields in current_target target_ops
+ vector values.
+
+ * target.h: Include symtab.h.
+ (target_waitkind): New enumerated values
+ TARGET_WAITKIND_SYSCALL_ENTRY, TARGET_WAITKIND_SYSCALL_RETURN,
+ TARGET_WAITKIND_FORKED, TARGET_WAITKIND_VFORKED,
+ TARGET_WAITKIND_EXECD.
+ (target_waitstatus): Add a syscall_id field to structure.
+ (child_has_syscall_event): New decl.
+ (child_thread_alive): New decl.
+ (target_ops): Add 3 new fields: To_has_syscall_event,
+ to_enable_exception_callback, to_get_current_exception_event
+ (target_enable_exception_callback): New macro.
+ (target_has_syscall_event): New macro.
+ (target_get_current_exception_event): New macro.
+ (TARGET_DISABLE_HW_WATCHPOINTS): New macro.
+ (TARGET_ENABLE_HW_WATCHPOINTS): New macro.
+ (PC_REQUIRES_RUN_BEFORE_USE): New macro.
+ (target_tid_to_str): New macro.
+ (target_waitstatus): Additional fields in struct to keep track
+ of child pid and pathname to execd file.
+ (target_ops): Add in the new target_ops function pointer fields.
+ New macros to go along with new target_ops fields.
+ In target_waitstatus.value, change name of child_pid field to
+ related_pid.
+ (target_pid_or_tid_to_str): Define default macro.
+ Add missing #endif after PC_REQUIRES_RUN_BEFORE_USE definition
+ (ENSURE_VFORKING_PARENT_REMAINS_STOPPED): Define default macro.
+ (RESUME_EXECD_VFORKING_CHILD_TO_GET_PARENT_VFORK): Define default
+ macro.
+ There are new function decls for to_require_attach
+ and to_require_detach. There are also new macros,
+ target_require_attach and target_require_detach. There are
+ also new function decls for find_default_require_detach
+ and find_default_require_attach.
+ (target_ops): New fields to_post_wait, to_post_startup_inferior
+ to_acknowledge_created_inferior, to_clone_and_follow_inferior,
+ to_post_follow_inferior_by_clone, to_create_catch_fork_hook,
+ to_create_catch_vfork_hook, to_has_forked, to_has_vforked,
+ to_post_follow_vfork, to_pid_to_exec_file.
+ New function definitions child_pid_to_exec_file, child_post_wait,
+ child_post_startup_inferior, child_acknowledge_created_inferior,
+ child_clone_and_follow_inferior,
+ child_post_follow_inferior_by_clone, child_create_catch_fork_hook,
+ child_create_catch_vfork_hook, child_has_forked,
+ child_has_vforked, child_acknowledge_created_inferior,
+ child_post_follow_vfork.
+ New macros target_post_startup_inferior,
+ target_acknowledge_created_inferior,
+ target_clone_and_follow_inferior,
+ target_post_follow_inferior_by_clone,
+ target_create_catch_fork_hook, target_create_catch_vfork_hook,
+ target_pid_to_exec_file.
+ (find_default_clone_and_follow_inferior): New function prototype.
+
+
+ * v850ice.c (init_850ice_ops): Init new target vector fields.
+
+ * valprint.c (print_binary_chars): Print out long long as
+ a binary number.
+ (print_octal_chars): Print out long long as an octal number
+ (print_decimal_chars): Print out long long as a decimal number
+ (strcat_longest): Define it.
+ * valprint.c: Hp merge, 4/15/98 snapshot
+ Add parameter to val_print. This is used for
+ evaluating C++ expressions.
+
+ * value.h (VALUE_POINTED_TO_OFFSET): New macro.
+ Add field pointed_to_offset to value structure.
+ Add prototypes for new functions in valops.c.
+ (write_register_pid): Change prototype to match
+ function.
+ (val_print function decl): Additional parameter.
+ (VALUE_EMBEDDED_OFFSET): New macro.
+ (find_rt_vbase_offset): New function decl -- for C++ support.
+
+Wed Dec 23 15:03:42 1998 Per Bothner <bothner@cygnus.com>
+
+ * Makefile.in (READLINE_CFLAGS): Search $(READLINE_SRC)/.. rather
+ than $(READLINE_SRC) so #include <readline/readline.h> will work.
+ * top.c: #include <readline/history.h> instead of "history.h".
+ * tracepoint.c: Likewise.
+ * mac-xdep.c: Likewise.
+
+Wed Dec 23 12:32:00 1998 Andrew Cagney <cagney@chook.cygnus.com>
+
+ * defs.h (TARGET_FLOAT_FORMAT, TARGET_DOUBLE_FORMAT): Define using
+ TARGET_BYTE_ORDER and not target_byte_order.
+
+Tue Dec 22 10:51:33 1998 Elena Zannoni <ezannoni@kwikemart.cygnus.com>
+
+ * config/i386/cygwin.mh (TERMCAP): define.
+ (from Chris Faylor, cgf@cygnus.com)
+
+ * top.c: specify directory name for including readline.h
+
+ * tracepoint.c: ditto.
+
+ * utils.c: ditto.
+
+Mon Dec 21 13:30:34 1998 Mark Alexander <marka@cygnus.com>
+
+ * value.c (value_virtual_fn_field): Handle the situation where
+ vtbl is a pointer to a structure instead of a pointer to an array.
+
+Mon Dec 21 10:38:11 1998 Andrew Cagney <cagney@chook>
+
+ * mips-tdep.c: (MIPS_DEFAULT_FPU_TYPE): Default to
+ MIPS_FPU_DOUBLE.
+
+1998-12-17 J.T. Conklin <jtc@redbacknetworks.com>
+
+ * blockframe.c (get_frame_saved_regs): If the saved_regs_addr ptr
+ is null, ensure that saved registers are copied from the local
+ variable that was used to obtain them.
+
+Sat Dec 19 09:55:09 1998 Stu Grossman <grossman@babylon-5.cygnus.com>
+
+ * mips-tdep.c (mips32_heuristic_proc_desc): Clear temp_saved_regs
+ on restart. Fixes problem with backtracing through functions that
+ use virtual frame pointers.
+
+Fri Dec 18 14:23:34 1998 Andrew Cagney <cagney@chook>
+
+ * mips-tdep.c (mips_push_arguments): Don't left-shift small
+ structs being passed in a register when an O64 target.
+
+ * config/mips/tm-mips.h (enum mips_fpu_type, mips_fpu): Move to
+ mips-tdep.c.
+
+ * mips-tdep.c (mips_fpu_string): Delete variable.
+ (mips_fpu_type_auto): New variable.
+ (mips_fpu_type): Rename mips_fpu.
+ (_initialize_mips_tdep): Delete initialization of mips_fpu et.al.
+ Rewrite ``set mipsfpu'' command set.
+ (set_mipsfpu_command, show_mipsfpu_command,
+ set_mipsfpu_single_command, set_mipsfpu_double_command,
+ set_mipsfpu_none_command, set_mipsfpu_auto_command): New
+ functions, handle commands.
+ (mips_push_arguments, mips_push_dummy_frame, mips_pop_frame,
+ mips_extract_return_value): Update.
+
+Thu Dec 17 02:15:40 1998 Andrew Cagney <cagney@chook.cygnus.com>
+
+ * configure.tgt (gdb_target): Identify mips64*vr4100*-*-elf* as
+ vr4100.
+
+Thu Dec 17 01:34:36 1998 Andrew Cagney <cagney@chook>
+
+ * gdbtypes.c (build_gdbtypes): New function.
+ (_initialize_gdbtypes): Call.
+
+Wed Dec 16 11:47:00 1998 Andrew Cagney <cagney@chook>
+
+ * gdbarch.c (show_architecture): Use TARGET_ARCHITECTURE.
+ * gdbarch.h, gdbarch.c: Fix typo's. Use struct's in preference to
+ types.
+ * gdbarch.h, gdbarch.c (gdbarch_debug): Add ``set archdebug'' to
+ command set.
+
+Tue Dec 15 23:46:40 1998 Andrew Cagney <cagney@chook>
+
+ * config/mips/tm-*.h: (TARGET_BYTE_ORDER_DEFAULT,
+ TARGET_BYTE_ORDER_SELECTABLE_P): Replace TARGET_BYTE_ORDER and
+ TARGET_BYTE_ORDER_SELECTABLE.
+
+1998-12-14 Anthony Thompson (athompso@cambridge.arm.com)
+
+ * remote-rdp.c (rdp_init): Don't discard first character on reset.
+ (translate_open_mode): Define table.
+ (exec_swi): Handle SWI_Clock. SWI_Open now handles stdin/stdout.
+ SWI_Write returns number of bytes not written. SWI_Read does the
+ same. SWI_Seek should return success/failure flag. Fix SWI_Flen.
+
+1998-12-14 J.T. Conklin <jtc@redbacknetworks.com>
+
+ * config/i386/nbsd.mh, config/m68k/nbsd.mh, config/ns32k/nbsd.mh
+ (XDEPFILES): Add ser-tcp.o.
+
+Mon Dec 14 14:46:13 1998 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * monitor.c (monitor_expect, monitor_printf_noecho,
+ monitor_printf): Always compile EXTRA_RDEBUG code.
+ (RDEBUG): Ditto.
+
+ From Michael Meissner <meissner@cygnus.com>:
+ * ppcbug-rom.c (init_ppc_cmds): Cleanup formatting.
+
+1998-12-08 Michael Meissner <meissner@cygnus.com>
+
+ * monitor.c (monitor_printable_string): New function to convert a
+ string into a printable representation.
+ (monitor_error): Call error after converting string into printable
+ format.
+ (monitor_printf{,_noecho}): If EXTRA_RDEBUG is defined, convert
+ string into printable form before printing.
+ (monitor_expect): Ditto.
+ (monitor_read_memory{,_single}): Call monitor_error, not error.
+ (monitor_read_memory): Return immediately if length is 0.
+
+ * ppcbug-rom.c (init_ppc_cmds): Fill in dump_registers field,
+ which is now required.
+
+Mon Dec 14 11:01:39 1998 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * gdbarch.h, gdbarch.c: Consolidate the semi-dynamic target system
+ dependant GDB parameters.
+ (set_gdbarch_from_file): Combine set_architecture_from_file and
+ set_byte_order_from_file.
+ * top.c, defs.h, printcmd.c: Delete them from here.
+ * Makefile.in: Add gdbarch.[ch].
+ * exec.c (exec_file_command): Call set_gdbarch_from_file.
+
+Sun Dec 13 09:52:51 1998 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * defs.h (TARGET_PRINT_INSN_INFO, TARGET_PRINT_INSN): Define.
+ (TARGET_ARCHITECTURE, TARGET_ARCHITECTURE_AUTO): Define.
+ (TARGET_BYTE_ORDER_AUTO): Define.
+ (TARGET_BYTE_ORDER_SELECTABLE_P): Provide default. Replaces
+ TARGET_BYTE_ORDER_SELECTABLE. Handle compat issues.
+ (BITS_BIG_ENDIAN): Simplify.
+ (TARGET_FLOAT_FORMAT): Ditto.
+ (TARGET_DOUBLE_FORMAT):
+
+ * remote-e7000.c, sh-tdep.c, printcmd.c, remote-sim.c,
+ remote-rdi.c, sparc-tdep.c: Update.
+
+ * config/powerpc/tm-ppcle-eabi.h, config/rs6000/tm-rs6000.h,
+ config/powerpc/tm-ppc-eabi.h, config/mn10300/tm-mn10300.h:
+ Convert.
+
+Sat Dec 12 09:28:13 1998 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * frame.h (struct frame_info): Add CORE_ADDR *saved_regs and
+ struct frame_extra_info *extra_info.
+ (frame_obstack_alloc, frame_saved_regs_zalloc): Prototype.
+ (SIZEOF_FRAME_SAVED_REGS): Provide default.
+ (FRAME_INIT_SAVED_REGS): Provide default.
+ (struct frame_saved_regs): Deprecate.
+ (EXTRA_FRAME_INFO): Deprecate.
+
+ * blockframe.c (frame_obstack_alloc, frame_saved_regs_zalloc): New
+ function.
+ (generic_get_saved_register): Use FRAME_INIT_SAVED_REGS and
+ frame->saved_regs.
+ (frame_cache_obstack): Make static.
+ (get_frame_saved_regs): Deprecate. Copy the saved regs into the
+ frame buffer.
+
+ * stack.c (frame_info): Rewrite using frame->saved_regs and
+ FRAME_INIT_SAVED_REGS.
+ * findvar.c (find_saved_register): Ditto.
+
+ * config/mn10300/tm-mn10300.h (EXTRA_FRAME_INFO): Delete.
+ (FRAME_FIND_SAVED_REGS): Replace with FRAME_INIT_SAVED_REGS. No-op.
+ * mn10300-tdep.c: Update.
+ (analyze_dummy_frame): New function.
+ (struct frame_extra_info): Define.
+ (mn10300_init_extra_frame_info): Update.
+
+ * config/rs6000/tm-rs6000.h: (EXTRA_FRAME_INFO): Delete.
+ (FRAME_FIND_SAVED_REGS): Replace with FRAME_INIT_SAVED_REGS.
+ (FRAME_ARGS_ADDRESS): Replace with function.
+
+ * rs6000-tdep.c (frame_get_saved_regs): Rename from
+ frame_get_cache_fsr.
+ (rs6000_init_extra_frame_info): New function.
+ (rs6000_frame_init_saved_regs): Call frame_get_saved_regs.
+ (FUNCTION_START_OFFSET): Delete references, was ZERO.
+ (rs6000_frame_args_address): New function.
+ (frame_initial_stack_address): Update
+
+ * config/mips/tm-mips.h (EXTRA_FRAME_INFO): Remove saved_regs.
+ (FRAME_INIT_SAVED_REGS): Rename FRAME_FIND_SAVED_REGS, update.
+ * mips-tdep.c (mips_find_saved_regs, read_next_frame_reg,
+ init_extra_frame_info, mips_pop_frame): Update.
+ * config/alpha/tm-alpha.h (FRAME_INIT_SAVED_REGS,
+ EXTRA_FRAME_INFO), alpha-tdep.c (alpha_find_saved_regs,
+ alpha_pop_frame, init_extra_frame_info): Ditto.
+
+ * i960-tdep.c, m88k-tdep.c, h8300-tdep.c: Update.
+ * config/sparc/tm-sparc.h, config/a29k/tm-a29k.h: Define
+ FRAME_INIT_SAVED_REGS as no-op.
+
+ * z8k-tdep.c (z8k_init_frame_saved_regs): Rename
+ get_frame_saved_regs.
+ (examine_frame, z8k_skip_prologue): Update.
+ * config/z8k/tm-z8k.h (FRAME_INIT_SAVED_REGS): Define.
+
+1998-12-11 Fernando Nasser <fnasser@totem.to.cygnus.com>
+
+ From J.T. Conklin <jtc@redbacknetworks.com>:
+ * i386-stub.c (handle_exception): Add support for 'P' command.
+ (NUMREGS): New macro.
+
+Fri Dec 11 09:07:05 1998 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * i386b-nat.c: Include "expression.h".
+
+ * symtab.h: Don't include "gnu-regex.h".
+
+ * solib.c (solib_add_common_symbols): Cast parameters passed to
+ make_cleanup to use the new make_cleanup_func typedef.
+
+ * inftarg.c: Include "wait.h" after, rather than before, <wait.h>.
+ "wait.h" was defining all WIF* macro's instead of filling in those
+ that <wait.h> missed.
+
+Fri Dec 11 09:52:04 1998 Andrew Cagney <cagney@chook>
+
+ * mipsm3-nat.c, hppah-nat.c, infptrace.c, i386gnu-nat.c,
+ hppab-nat.c, core-aout.c, arm-xdep.c, alpha-nat.c, altos-xdep.c,
+ pyr-xdep.c, remote-st.c, remote-os9k.c, tahoe-tdep.c, pyr-tdep.c,
+ vax-tdep.c: Replace reg_name with REGISTER_NAME.
+
+Thu Dec 10 15:19:40 1998 David Taylor <taylor@texas.cygnus.com>
+
+ The following changes were made by Jim Blandy <jimb@cygnus.com>,
+ Edith Epstein <eepstein@cygnus.com>, Elena Zannoni
+ <ezannoni@cygnus.com> Stan Shebs <shebs@cygnus.com>, and David
+ Taylor <taylor@cygnus.com>, as part of the project to merge in
+ changes originally made by HP; HP did not create ChangeLog
+ entries.
+
+ * annotate.c (annotate_catchpoint): New function.
+
+ * annotate.h (annotate_catchpoint): declare it; add new includes
+ (symtab.h and gdbtypes.h).
+
+ * buildsym.h: add external var processing_hp_compilation.
+
+ * coff-solib.h:
+ (SOLIB_REMOVE_INFERIOR_HOOK): new macro. defined to 0.
+ functionality not implemented for coff.
+ (SOLIB_CREATE_CATCH_LOAD_HOOK): New macro; generate error msg for coff.
+ (SOLIB_CREATE_CATCH_UNLOAD_HOOK): ditto.
+ (SOLIB_HAVE_LOAD_EVENT): ditto.
+ (SOLIB_LOADED_LIBRARY_PATHNAME): ditto.
+ (SOLIB_HAVE_UNLOAD_EVENT): ditto.
+ (SOLIB_UNLOADED_LIBRARY_PATHNAME): ditto.
+ (SOLIB_IN_DYNAMIC_LINKER): ditto.
+ (SOLIB_RESTART): ditto.
+
+ * complaints.h: add ifdef...endif pair at beginning and end of file.
+
+ * dstread.c (dst_symfile_read): the parameter to fileno
+ must be of type FILE *. So cast abfd->iostream in the
+ call to fileno must be cast as a FILE *, not a GDB_FILE *.
+ This will work because abfd->iostream is declared and
+ given a value in bdf and bfd will continue to use FILE
+ rather than GDB_FILE.
+
+ * dwarf2read.c (dwarf_bool_name): change parameter from bool
+ to mybool. sigh.
+
+ * expression.h: include symtab.h
+
+ * frame.h (print_only_stack_frame, show_stack_frame,
+ show_frame_info): add prototypes.
+
+ * gdbcmd.h (togglelist, stoplist): declare.
+
+ * gdbcore.h (read_memory_string): declare it.
+ (exec_file_attach): add prototype.
+
+ * inflow.c (terminal_is_ours): make non static.
+
+ * minsyms.c: minor spacing change.
+
+ * parser-defs.h (parse_nested_classes_for_hpacc): add prototype.
+ (find_template_name_end): add prototype.
+
+ * scm-lang.c (scm_unpack): cast svalue to (int).
+
+ * top.h: declare it.
+
+ * valprint.h (print_binary_chars): new prototype definition.
+ (print_octal_chars): new prototype definition.
+ (print_decimal_chars): new prototype definition.
+
+Thu Dec 10 07:14:56 1998 Andrew Cagney <cagney@chook>
+
+ * config/arm/tm-arm.h, arm-tdep.c: Replace REGISTER_NAMES with
+ REGISTER_NAME.
+ * mn10300-tdep.c, config/mn10300/tm-mn10300.h: Ditto.
+ * sh-tdep.c, config/sh/tm-sh.h: Ditto.
+
+ * defs.h (REGISTER_NAME): Provide default for old targets.
+ * defs.h, infcmd.c: Rename reg_names to gdb_register_names.
+
+ * tracepoint.c, target.c, parse.c, infcmd.c, remote-udi.c,
+ expprint.c, infcmd.c, printcmd.c, eval.c, stack.c, findvar.c,
+ remote-udi.c, config/alpha/tm-alpha.h, remote-sim.c, d30v-tdep.c,
+ config/mips/tm-mips.h, hppa-tdep.c: Use REGISTER_NAME.
+
+1998-12-08 James E Wilson <wilson@wilson-pc.cygnus.com>
+
+ * config/i960/mon960.mt (SIM_OBJS, SIM): Define.
+
+Tue Dec 8 16:49:24 1998 Stan Shebs <shebs@andros.cygnus.com>
+
+ * NEWS: Add mentions of newly-added configurations.
+
+1998-12-08 Philippe De Muyter <phdm@macqel.be>
+
+ * config/xm-aix4.h (SIGWINCH_HANDLER): Function `aix_resize_window'
+ must accept a signal number as parameter.
+ * config/rs6000/xm-rs6000.h (SIGWINCH_HANDLER): Ditto.
+ * utils.c (initialize_utils): Give a parameter to `SIGWINCH_HANDLER'.
+
+ * inferior.h (register_valid): Variable's type is `SIGNED char', not
+ `char'.
+ * findvar.c (register_valid): Ditto.
+
+ * defs.h (make_cleanup_func): Protect parameter list by `PARAMS'.
+ * gdbthread.h (unbind_target_thread_vector): Likewise.
+
+Tue Dec 8 15:09:44 1998 Edith Epstein <eepstein@sophia.cygnus.com>
+
+ Merged in m68k-linux patch from Andreas Schwab
+
+ 1998-12-01 Andreas Schwab <schwab@issan.cs.uni-dortmund.de>
+
+ * Makefile.in, configure.host, configure.tgt: Add support for
+ m68k-linux.
+ * config/m68k/linux.mh: New file.
+ * config/m68k/linux.mt: New file.
+ * config/m68k/nm-linux.h: New file.
+ * config/m68k/tm-linux.h: New file.
+ * config/m68k/xm-linux.h: New file.
+ * gdb/m68klinux-nat.c: New file.
+ * gdbserver/low-linux.c: Add support for m68k-linux.
+ * gdb/config/m68k/tm-m68k.h (NUM_FREGS): New macro.
+
+1998-12-07 Jason Molenda (jsm@bugshack.cygnus.com)
+
+ * config/i386/xm-cygwin.h: Remove REQUEST_QUIT definition.
+ * config/powerpc/xm-cygwin.h: Ditto.
+
+1998-12-07 Jim Blandy <jimb@zwingli.cygnus.com>
+
+ * rs6000-tdep.c (pop_frame): Correctly find the registers saved in
+ the stack frame. Their offset from the previous stack frame is in
+ fdata.gpr_offset and fdata.fpr_offset, not fdata.offset.
+ (gdb.base/return.exp)
+ * config/rs6000/tm-rs6000.h: Doc fixes.
+
+1998-12-03 Jason Molenda (jsm@bugshack.cygnus.com)
+
+ * monitor.c (monitor_read_memory): Zero out pattern buffers
+ before calling re_search.
+ (parse_register_dump): Ditto.
+
+Thu Dec 3 10:37:22 EST 1998 Zdenek Radouch (radouch@cygnus.com)
+
+ FR30 updates - still very preliminary.
+ * configure.tgt
+ * fr30-tdep.c
+ * config/fr30/tm-fr30.h
+
+Thu Dec 3 16:30:35 1998 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * ax-gdb.c: Include target.h.
+
+Tue Dec 3 10:59:00 1998 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * ax-gdb.c (_initialize_ax_gdb), i960-tdep.c (pop_frame),
+ monitor.c (flush_monitor_dcache, longlongendswap), remote-array.c
+ (hexword2ascii), w89k-rom.c (init_w89k_cmds), z8k-tdep.c
+ (init_frame_pc, extract_return_value): Make return type void.
+ * monitor.c (monitor_write_even_block): Make return type explicit.
+ (monotor_read_memory_block): Delete function.
+ * monitor.h: Update.
+ * remote.c (remote_get_threadlist, remote_update_threads),
+ remote-array.c (array_get_packet), remote-rdi.c (Fail): Always
+ return a value.
+ * m32r-tdep.c (m32r_fix_call_dummy): From Michael Snyder, void
+ function.
+ * jv-valprint.c (java_val_print): From Stu Grossman. Return 0 by
+ default.
+
+Wed Dec 2 15:11:38 1998 Michael Snyder <msnyder@cleaver.cygnus.com>
+
+ * tracepoint.c: Move default definition of
+ TARGET_VIRTUAL_FRAME_POINTER from here to target.h.
+ * target.h: Add default definition of TARGET_VIRTUAL_FRAME_POINTER.
+ * ax-gdb.c (gen_frame_args_address, gen_frame_locals_address):
+ use TARGET_VIRTUAL_FRAME_POINTER to determine frame pointer.
+ (gen_trace_for_expr): new argument, address of tracepoint,
+ gets passed to new_agent_expr and added to struct agent_expr.
+ (is_nontrivial_conversion): call to new_agent_expr now requires
+ a dummy argument. (agent_command): use get_current_frame() to
+ get current PC scope; pass it to gen_trace_for_expr.
+ * ax-general.c (new_agent_expr): new argument, address of
+ tracepoint; store it in new field of struct agent_expr.
+ * ax.h (struct agent_expr): add new field for tracepoint address.
+ * ax-gdb.h: change prototypes to match above changes.
+
+ * m32r-tdep.c (decode_prologue): If no branch or push fp is found,
+ but there's a stack adjust, then use that as the end of prologue.
+ (m32r_skip_prologue): don't skip past the first line if there is
+ line info. (m32r_virtual_frame_pointer): new function.
+ (m32r_fix_call_dummy): no return value needed.
+
+Tue Dec 1 10:59:00 1998 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * ocd.c (remote_timeout), (BDM_BREAKPOINT), monitor.c (readchar),
+ remote.c: Cleanup closing of open comments.
+
+Mon Nov 30 16:04:03 1998 Doug Evans <devans@canuck.cygnus.com>
+
+ * config/fr30/tm-fr30.h (INNER_THAN): Add parameters.
+
+Mon Nov 30 11:18:48 1998 Andrew Cagney <cagney@chook>
+
+ * frame.h (FRAME_CHAIN_VALID): Default to
+ default_frame_chain_valid.
+ * blockframe.c (default_frame_chain_valid): New function.
+
+ * frame.h (FRAME_CHAIN_VALID_ALTERNATIVE): Delete references
+ * blockframe.c (alternate_frame_chain_valid): New function.
+ * config/mips/tm-mipsv4.h, config/m88k/tm-delta88v4.h,
+ config/m68k/tm-monitor.h, config/m68k/tm-m68kv4.h,
+ config/i386/tm-i386v4.h, config/i386/tm-i386nw.h,
+ config/h8300/tm-h8300.h: Update.
+
+ * blockframe.c (nonnull_frame_chain_valid): New function.
+ * config/m68k/tm-os68k.h, config/m68k/tm-vx68.h,
+ config/m68k/tm-apollo68b.h, config/i960/tm-vx960.h,
+ config/arc/tm-arc.h: Update FRAME_CHAIN_VALID.
+
+ * hppa-tdep.c (frame_chain_valid, hppa_frame_chain_valid),
+ remote-vx29k.c (get_fp_contents, vx29k_frame_chain_valid),
+ arm-tdep.c (frame_chain_valid, arm_frame_chain_valid): Rename
+ functions so that they are name space clean.
+ * config/pa/tm-hppa.h, config/a29k/tm-vx29k.h,
+ config/arm/tm-arm.h: Update FRAME_CHAIN_VALID.
+
+ * gould-tdep.c (gould_frame_chain_valid), d30v-tdep.c
+ (d30v_frame_chain_valid), d10v-tdep.c (d10v_frame_chain_valid):
+ New functions.
+ * config/gould/tm-np1.h, config/gould/tm-pn.h,
+ config/d30v/tm-d30v.h, config/d10v/tm-d10v.h: Update
+ FRAME_CHAIN_VALID.
+
+Sun Nov 29 11:18:37 1998 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * z8k-tdep.c (z8k_addr_bits_remove), w65-tdep.c
+ (w65_addr_bits_remove), h8500-tdep.c (h8500_addr_bits_remove),
+ m88k-tdep.c (m88k_addr_bits_remove): Function to clean up an
+ address.
+ * config/z8k/tm-z8k.h, config/w65/tm-w65.h, config/m88k/tm-m88k.h,
+ config/h8500/tm-h8500.h: Define ADDR_BITS_REMOVE to call targets
+ corresponding function.
+ * z8k-tdep.c (saved_pc_after_call): Update.
+
+Sat Nov 28 12:24:31 1998 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * config/z8k/tm-z8k.h, config/w65/tm-w65.h, config/vax/tm-vax.h,
+ config/v850/tm-v850.h, config/tahoe/tm-tahoe.h,
+ config/sparc/tm-sparc.h, config/sh/tm-sh.h,
+ config/rs6000/tm-rs6000.h, config/pyr/tm-pyr.h,
+ config/pa/tm-hppa.h, config/ns32k/tm-umax.h,
+ config/ns32k/tm-merlin.h, config/none/tm-none.h,
+ config/mn10300/tm-mn10300.h, config/mn10200/tm-mn10200.h,
+ config/mips/tm-mips.h, config/m88k/tm-m88k.h,
+ config/m68k/tm-m68k.h, config/m32r/tm-m32r.h,
+ config/i960/tm-i960.h, config/i386/tm-i386.h,
+ config/h8500/tm-h8500.h, config/h8300/tm-h8300.h,
+ config/gould/tm-pn.h, config/gould/tm-np1.h, config/arm/tm-arm.h,
+ config/convex/tm-convex.h, config/d10v/tm-d10v.h,
+ config/alpha/tm-alpha.h, config/a29k/tm-a29k.h: Add parameters to
+ macro INNER_THAN.
+
+ * valops.c (push_word, value_push, call_function_by_hand),
+ breakpoint.c (bpstat_stop_status), blockframe.c
+ (generic_push_dummy_frame, generic_frame_chain_valid), inferior.h
+ (PC_IN_CALL_DUMMY), infrun.c (wait_for_inferior): Update use of
+ INNER_THAN.
+
+Fri Nov 27 11:00:25 1998 Andrew Cagney <cagney@chook>
+
+ * target.h (one_stepped): Move global from here.
+ * infrun.c (singlestep_breakpoints_inserted_p): To here. Rename.
+ Make static.
+ (wait_for_inferior): Update.
+ (resume): Update. Set variable after call to SOFTWARE_SINGLE_STEP.
+
+ * target.h (NO_SINGLE_STEP): Replace with SOFTWARE_SINGLE_STEP_P
+ and SOFTWARE_SINGLE_STEP.
+ * config/sparc/tm-sparc.h, config/rs6000/tm-rs6000.h,
+ config/arc/tm-arc.h: Update.
+ * rs6000-tdep.c (rs6000_software_single_step), sparc-tdep.c
+ (sparc_software_single_step), arc-tdep.c (arc_single_step): New
+ functions. Replace function single_step.
+
+ * config/mips/tm-mips.h (STEP_SKIPS_DELAY_P): Define.
+ * infrun.c (proceed): Cleanup.
+
+Thu Nov 26 11:19:15 1998 Andrew Cagney <cagney@amy.cygnus.com>
+
+ * config/alpha/tm-alpha.h (ABOUT_TO_RETURN): Replace macro.
+ * alpha-tdep.c (alpha_about_to_return): With new function.
+ (heuristic_proc_start): Update.
+ * config/mips/tm-mips.h (ABOUT_TO_RETURN), mips-tdep.c
+ (heuristic_proc_start, mips_about_to_return): Ditto.
+ * config/ns32k/tm-merlin.h (ABOUT_TO_RETURN),
+ config/ns32k/tm-umax.h (ABOUT_TO_RETURN), ns32k-tdep.c
+ (ns32k_about_to_return, ns32k_get_enter_addr): Ditto.
+
+ * config/z8k/tm-z8k.h, config/w65/tm-w65.h, config/vax/tm-vax.h,
+ config/tahoe/tm-tahoe.h, config/sparc/tm-sparc.h,
+ config/sh/tm-sh.h, config/rs6000/tm-rs6000.h, config/pyr/tm-pyr.h,
+ config/pa/tm-hppa.h, config/m88k/tm-m88k.h, config/m68k/tm-m68k.h,
+ config/i960/tm-i960.h, config/i386/tm-i386.h,
+ config/h8500/tm-h8500.h, config/h8300/tm-h8300.h,
+ config/gould/tm-pn.h, config/gould/tm-np1.h,
+ config/convex/tm-convex.h, config/arm/tm-arm.h,
+ config/arc/tm-arc.h, config/a29k/tm-a29k.h: Delete macro
+ ABOUT_TO_RETURN.
+ * config/w65/tm-w65.h (RTL, RTS): Delete macros.
+ * h8500-tdep.c (about_to_return): Delete function.
+
+Thu Nov 26 11:19:15 1998 Andrew Cagney <cagney@chook.cygnus.com>
+
+ * rs6000-tdep.c (rs6000_breakpoint_from_pc): Change big_breakpoint
+ and little_breakpoint to char[] from char*.
+ * remote-array.c (array_insert_breakpoint): Change bp_addr to
+ CORE_ADDR type.
+
+Wed Nov 25 00:13:06 1998 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * vx-share/xdr_ld.c (xdr_ldtabl): Cast second arg to char**
+ instead of char*.
+
+ * configure.tgt (v850): Only build v850ice when cygwin and gui.
+ * configure.in: Add parameter to --enable-build-warnings.
+ * configure: Re-build.
+
+ * c-exp.y (parse_number): Rewrite shift to pacify GCC.
+
+ * config/i960/tm-i960.h (BREAKPOINT): Delete definition - simply
+ wrong.
+
+ * monitor.c (compile_pattern): Make val const char*.
+ (monitor_wait_cleanup): Make old_timeout void*, pointing at
+ old_timeout.
+ (monitor_wait): Update.
+
+ * remote-udi.c, remote-sim.c, remote-e7000.c, hppa-tdep.c,
+ remote-mips.c, sparcl-tdep.c, xcoffread.c: Cast parameters passed
+ to make_cleanup to use the new make_cleanup_func typedef.
+
+ * alpha-tdep.c (MASK): Use LONGEST to avoid arithmetic overflow.
+
+ * config/a29k/tm-a29k.h (TRANSPARENT): Rename macro to
+ TRANSPARENT_FRAME. Avoid name-space clash.
+ * a29k-tdep.c (init_frame_info): Update.
+
+Wed Nov 25 20:37:00 1998 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * rs6000-tdep.c (rs6000_breakpoint_from_pc): Change big_breakpoint
+ and little_breakpoint to char[] from char*.
+ * mem-break.c (memory_insert_breakpoint,
+ memory_remove_breakpoint): Pass address of bplen.
+ * remote-array.c (array_insert_breakpoint): Change bp_addr to
+ CORE_ADDR type.
+
+Tue Nov 24 15:46:33 1998 Michael Snyder <msnyder@cleaver.cygnus.com>
+
+ * config/mn10300/tm-mn10300.h (TARGET_VIRTUAL_FRAME_POINTER):
+ new target macro.
+ * mn10300-tdep.c (mn10300_virtual_frame_pointer): new function.
+ * tracepoint.c (encode_actions): Use the new target macro to
+ determine the virtual frame pointer, for collecting locals/args.
+ (add_local_symbols, collect_symbol): add a register/offset pair of
+ arguments so that the virtual frame pointer can be passed in.
+
+1998-11-24 Felix Lee <flee@cygnus.com>
+
+ * procfs.c (procfs_wait): handle syscall events first.
+
+ * procfs.c (GDB_GREGSET_TYPE, GDB_FPREGSET_TYPE): new macros.
+ * config/sparc/xm-sun4sol2.h: use them.
+ * core-sol2.c: don't #undef gregset_t and fpregset_t.
+ * sol-thread.c: ditto.
+ * sparc-tdep.c: ditto.
+
+Tue Nov 24 14:13:10 1998 Andrew Cagney <cagney@chook>
+
+ * breakpoint.c (memory_breakpoint_size): Delete global.
+ (read_memory_nobpt): Determine real breakpoint address and size
+ using BREAKPOINT_FROM_PC.
+
+ * defs.h (breakpoint_from_pc_fn): BREAKPOINT_FROM_PC function
+ template.
+ * target.h, mem-break.c (memory_breakpoint_from_pc):
+ Rewrite. Always define. Return NULL when memory breakpoints are
+ not supported.
+ (memory_insert_breakpoint, memory_remove_breakpoint): Call
+ BREAKPOINT_FROM_PC.
+ * target.h (BREAKPOINT_FROM_PC): Provide default.
+ * gdbint.texinfo (BREAKPOINT_FROM_PC): Document.
+
+ * config/rs6000/tm-rs6000.h (BREAKPOINT): Delete macro.
+ (BREAKPOINT_FROM_PC): Define.
+ ({BIG,LITTLE}_BREAKPOINT): Move macros from here.
+ * rs6000-tdep.c: To here.
+ (rs6000_breakpoint_from_pc): New function.
+
+ * config/mn10300/tm-mn10300.h (BREAKPOINT): Delete macro.
+ (BREAKPOINT_FROM_PC): Define, call.
+ * mn10300-tdep.c (mn10300_breakpoint_from_pc): New function.
+
+ * config/mips/tm-mips.h ({BIG,LITTLE}_BREAKPOINT,
+ IDT_{BIG,LITTLE}_BREAKPOINT, PMON_{BIG,LITTLE}_BREAKPOINT,
+ MIPS16_{BIG,LITTLE}_BREAKPOINT): Move macros from here.
+ * mips-tdep.c: To here.
+
+ * config/arm/tm-arm.h ({BIG,LITTLE}_BREAKPOINT): Delete macros.
+ ({ARM,THUMB}_{BE,LE}_BREAKPOINT): Move macros from here.
+ * arm-tdep.c: To here.
+
+ * remote-array.c (memory_breakpoint_size): Delete variable.
+ (array_insert_breakpoint): Obtain breakpoint size using
+ BREAKPOINT_FROM_PC.
+ * remote-st.c (memory_breakpoint_size, st2000_insert_breakpoint):
+ Ditto.
+ * remote-os9k.c (memory_breakpoint_size,
+ rombug_insert_breakpoint): Ditto.
+ * remote-e7000.c (memory_breakpoint_size): Ditto.
+
+Mon Nov 23 11:38:40 1998 Michael Snyder <msnyder@cleaver.cygnus.com>
+
+ * symfile.c (deduce_language_from_filename): rewrite so as to
+ work from a table of filename extensions, modifiable by the user.
+ (filename_language_table): new data structure.
+ (set_ext_lang_command): new function for new command, "set
+ extension-language". (info_extension_language_command): new
+ function for new command "info extension-languages".
+ (add_filename_language, init_filename_language_table): new
+ support functions for the above.
+ * language.c (language_enum): new function. Support for above.
+
+Mon Nov 23 10:47:54 1998 Andrew Cagney <cagney@chook.cygnus.com>
+
+ * config/sh/tm-sh.h, config/mn10200/tm-mn10200.h,
+ config/m32r/tm-m32r.h, config/arm/tm-arm.h, config/i960/tm-i960.h,
+ config/gould/tm-np1.h, config/d10v/tm-d10v.h,
+ config/v850/tm-v850.h, config/pa/tm-hppa.h, config/a29k/tm-a29k.h,
+ config/mn10300/tm-mn10300.h, config/mips/tm-mips.h
+ (USE_STRUCT_CONVENTION): Cleanup, define macro as function.
+
+ * sh-tdep.c (sh_use_struct_convention), mn10200-tdep.c
+ (mn10200_use_struct_convention), i960-tdep.c
+ (i960_use_struct_convention), gould-tdep.c
+ (gould_use_struct_convention), d10v-tdep.c
+ (d10v_use_struct_convention), v850-tdep.c
+ (v850_use_struct_convention), hppa-tdep.c
+ (hpha_use_struct_convention), m32r-tdep.c
+ (m32r_use_struct_convention), arm-tdep.c
+ (arm_use_struct_convention), mn10300-tdep.c
+ (mn10300_use_struct_convention), a29k-tdep.c
+ (a29k_use_struct_convention), mips-tdep.c
+ (mips_use_struct_convention): New functions
+
+ * value.h, values.c (generic_use_struct_convention): New function,
+ replace macro.
+ * values.c (USE_STRUCT_CONVENTION): Macro defaults to function
+ generic_use_struct_convention.
+
+Sat Nov 21 17:15:40 1998 Philippe De Muyter <phdm@macqel.be>
+
+ * breakpoint.c (bpstat_stop_status): Do not increment hit_count
+ of breakpoint if condition is not true.
+
+ * coffread.c (coff_symtab_read): Discard C_LABEL's that are not
+ function entry points, to avoid getting them in the stack dump
+ instead of the actual function.
+
+ * config/m68k/delta68.mh (NAT_FILE): Undo 1998-08-18 change;
+ without NAT_FILE definition, configure will assume that GDB cannot
+ run native.
+ * config/m68k/nm-delta68.h (KERNEL_U_SIZE): New macro.
+ * delta68-nat.c (kernel_u_size): New function.
+
+Fri Nov 20 10:13:03 1998 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * buildsym.c (end_symtab): Cleanup PROCESS_LINENUMBER_HOOK.
+
+Thu Nov 19 15:21:04 1998 Geoffrey Noer <noer@cygnus.com>
+
+ * rdi-share/host.h: if compiling under Cygwin, make sure new
+ preprocessor define is defined. Define it if not.
+ * rdi-share/hostchan.h: ditto
+ * rdi-share/aclocal.m4: regenerate
+ * rdi-share/configure: regenerate
+
+Thu Nov 19 14:43:44 1998 Geoffrey Noer <noer@cygnus.com>
+
+ * configure.in: switch back to checking __CYGWIN32__
+ * configure: regenerate
+
+Thu Nov 19 09:53:00 1998 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * exec.c (exec_file_command): Cleanup. Replace #if
+ NEED_TEXT_START_END with if().
+ * config/pa/nm-hppah.h (NEED_TEXT_START_END): Redefine to be 1.
+ * config/convex/tm-convex.h (NEED_TEXT_START_END): Ditto.
+ * config/gould/tm-np1.h (NEED_TEXT_START_END): Ditto.
+ * config/a29k/tm-a29k.h (NEED_TEXT_START_END): Ditto.
+
+Thu Nov 19 13:06:22 1998 Geoffrey Noer <noer@cygnus.com>
+
+ * main.c: Wait until more time has passed before calling
+ new cygwin_ funcs, revert back to the cygwin32_ ones for now.
+ * win32-nat.c: Ditto.
+
+Wed Nov 18 15:03:17 1998 Andrew Cagney <cagney@chook.cygnus.com>
+
+ * 29k-share/udi/udip2soc.c (UDIConnect): Replace sys_errlist with
+ strerror.
+
+Mon Nov 16 14:17:05 1998 Geoffrey Noer <noer@cygnus.com>
+
+ * defs.h: if compiling under Cygwin, define __CYGWIN__ if
+ __CYGWIN32__ is defined and __CYGWIN__ isn't for backwards
+ compatibility.
+
+Fri Nov 13 00:15:08 1998 Geoffrey Noer <noer@cygnus.com>
+
+ Changes to account for name change from cygwin32 to cygwin and
+ clean up Win32-related ifdefs.
+
+ * configure.tgt: check for cygwin* instead of cygwin32.
+ New cygwin gdb_target variable loses the "32".
+ * configure.host: check for cygwin* instead of cygwin32.
+ New cygwin gdb_host variable loses the "32".
+ * configure.in: test __CYGWIN__ instead of __CYGWIN32__,
+ rename gdb_cv_os_cygwin32 variable to drop the "32". Call
+ AM_EXEEXT instead of AC_EXEEXT since that isn't in a released
+ autoconf yet.
+ * configure: regenerate.
+
+ * main.c: drop "32" from cygwin_ funcs, include sys/cygwin.h where
+ cygwin path conv protos live, instead of adding a proto here for
+ them here.
+ * {main.c, ser-tcp.c, ser-unix.c, top.c}: check __CYGWIN__
+ instead of __CYGWIN32__.
+ * source.c: thoughout, check _WIN32 instead of WIN32.
+
+ * config/i386/cygwin32.mh: delete.
+ * config/i386/cygwin.mh: new file, was cygwin32.mh.
+ * config/i386/cygwin32.mt: delete.
+ * config/i386/cygwin.mt: new file, was cygwin32.mt.
+ * config/i386/tm-cygwin32.h: delete.
+ * config/i386/tm-cygwin.h: new file, was tm-cygwin32.h.
+ * config/i386/xm-cygwin32.h: delete.
+ * config/i386/xm-cygwin.h: new file, was xm-cygwin32.h.
+ * config/i386/xm-windows.h: #include xm-cygwin.h now.
+ * config/powerpc/cygwin32.mh: delete.
+ * config/powerpc/cygwin.mh: new file, was cygwin32.mh.
+ * config/powerpc/cygwin32.mt: delete.
+ * config/powerpc/cygwin.mt: new file, was cygwin32.mt.
+ * config/powerpc/tm-cygwin32.h: delete.
+ * config/powerpc/tm-cygwin.h: new file, was tm-cygwin32.h.
+ * config/powerpc/xm-cygwin32.h: delete.
+ * config/powerpc/xm-cygwin.h: new file, was xm-cygwin32.h.
+
+ * rdi-share/aclocal.m4: regenerate with aclocal.
+ * rdi-share/configure: regenerate with autoconf.
+ * rdi-share/{host.h, hostchan.c, hostchan.h, serdrv.c, serpardr.c,
+ unixcomm.c}: check __CYGWIN__ instead of __CYGWIN32__.
+
+Thu Nov 12 17:19:43 1998 John Metzler <jmetzler@cygnus.com>
+
+ * remote.c (remote_get_threadinfo): Support for remote
+ multithread debugging.
+ (remote_get_threadlist): get a partial list of threads
+ (remote_threadlist_iterator): Step through all the threads
+ (init_remote_threadtests): Optional builtin unit test commands.
+
+ * thread.c (bind_target_thread_vector): Implementa a more dynamic
+ way of accessing target specific thread info functions than
+ FIND_NEW_THREADS.
+ (target_thread_info): Function to get extended thread information.
+
+ * gdbthread.h: Export internal data structures corresponding to
+ external detailed thread info response. This is more like a 'ps'
+ command than what might be expected of host based threads. This
+ is for embedded systems.
+
+Wed Nov 11 15:47:00 1998 Michael Snyder <msnyder@cleaver.cygnus.com>
+
+ * procfs.c (proc_set_exec_trap): don't set PR_ASYNC or PR_FORK
+ in the child process for UnixWare (causes processes forked by
+ the debuggee to hang).
+
+Mon Nov 9 12:00:36 1998 Dave Brolley <brolley@cygnus.com>
+
+ * config/fr30/fr30.mt: New file.
+ * config/fr30/tm-fr30.h: New file.
+
+1998-11-05 Jim Wilson <wilson@cygnus.com>
+
+ * remote-vx.c (net_read_registers, net_write_registers,
+ vx_xver_memory, vx_resume, vx_attach, vx_detach, vx_kill):
+ Change errno to errno_num.
+ * vx-share/xdr_ptrace.c (xdr_ptrace_return): Likewise.
+ * vx-share/xdr_ptrace.h (struct ptrace_return): Likewise.
+
+Thu Nov 5 08:41:33 1998 Christopher Faylor <cgf@cygnus.com>
+
+ * top.c (gdb_readline): Allow CRLF line termination on systems
+ which define CRLF_SOURCE_FILES.
+ * win32-nat.c: 1) Add thread support, 2) fix ability to attach to
+ a running process, and 3) implement limited support for cygwin
+ signals.
+ (thread_rec): New function.
+ (child_add_thread): Ditto.
+ (child_init_thread_list): Ditto.
+ (child_delete_thread): Ditto.
+ (do_child_fetch_inferior_registers): Ditto.
+ (do_child_store_inferior_registers): Ditto.
+ (handle_output_debug_string): Ditto.
+ (child_fetch_inferior_registers): Use do_* function to perform
+ operation.
+ (child_store_inferior_registers): Ditto.
+ (child_continue): Ditto.
+ (child_thread_alive): Ditto.
+ (cygwin_pid_to_str): Ditto.
+ (handle_load_dll): Reorganize, add first attempt at reading
+ dll names from attached processes. Change info messages to provide
+ more information when dll is already loaded.
+ (handle_exception): Changes mandated by new thread-aware structures.
+ (child_wait): Track thread creation/destruction. Handle cygwin
+ signals.
+ (child_create_inferior): Ditto.
+ (child_resume): Ditto.
+ (child_kill_inferior): Ditto. Close child process handle to avoid a
+ handle leak.
+ (child_ops): Fill out child_ops fields that deal with threads.
+ * config/i386/tm-cygwin32.h: Declare function and macro needed
+ for converting a cygwin "pid" to a string.
+ * config/i386/xm-cygwin32.h: define HAVE_SIGSETMASK as 0 since
+ sigsetmask is not defined in cygwin.
+
+Thu Nov 5 08:38:18 1998 Christopher Faylor <cgf@cygnus.com>
+
+ * win32-nat.c: Remove obsolete PPC conditionals.
+
+Wed Nov 4 18:44:31 1998 Dave Brolley <brolley@cygnus.com>
+
+ * configure.tgt: Add fr30-*-elf*.
+
+1998-11-03 Jim Wilson <wilson@cygnus.com>
+
+ * c-exp.y (parse_number): Check TARGET_LONG_LONG_BIT when setting
+ high_bit to avoid undefined negative shift.
+
+Mon Nov 2 15:26:33 1998 Geoffrey Noer <noer@cygnus.com>
+
+ * configure.in: Check cygwin* instead of cygwin32*.
+ * configure: regenerate
+
+Thu Oct 29 10:04:20 1998 Michael Snyder <msnyder@cleaver.cygnus.com>
+
+ [Support for trace debugging: registers that were not collected.]
+ * remote.c (remote_fetch_registers): accept 'xxxx' in the register
+ packet, with the meaning "register value is not available".
+ Set register_valid to -1, which will connote "no value available".
+ * findvar.c (read_relative_register_raw_bytes): return failure if
+ register_valid == -1. (value_of_register): return failure if
+ register_valid == -1. (read_var_value): return error if
+ value_of_register fails for a register variable.
+ (value_from_register): return failure if register_valid == -1.
+ * eval.c (evaluate_subexp_standard): return error if
+ value_of_register fails for a register used in an expression.
+ * infcmd.c (do_registers_info): display "value not available"
+ for registers for which register_valid == -1.
+
+ * tracepoint.c (set_raw_tracepoint): just save the filename as is
+ from the symbol table, rather than trying to prepend the dir name.
+ Also save the bfd section. (tracepoints_info): use the section
+ when looking up the function name.
+ * tracepoint.h: add section field to tracepoint struct.
+
+Wed Oct 28 08:01:38 1998 Mark Alexander <marka@cygnus.com>
+
+ * sparcl-tdep.c (send_resp, sparclite_serial_start,
+ sparclite_serial_write): Use remote_timeout instead of hardcoded
+ two second timeout.
+ (download): Fix adjustment of a.out load addresses.
+
+Wed Oct 28 12:32:58 1998 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * configure.in (--enable-build-warnings): Finish rename from
+ --enable-warnings.
+ (enable-build-warnings): Add -Wpointer-arth, allow =* for
+ sim/common compatibility.
+ * configure: Re-generate.
+
+Wed Oct 21 08:44:30 1998 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * 29k-share/udi/udip2soc.c: Replace sys_errlist with strerror().
+
+Thu Oct 22 09:56:55 1998 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * config/rs6000/aix4.mh (NATDEPFILES): Move xcoffread.o from here.
+ * config/rs6000/aix4.mt (TDEPFILES): To here.
+
+Wed Oct 21 10:02:31 1998 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * rdi-share/unixcomm.c: Provide definitions of SERPORT and PARPORT
+ on BSD hosts.
+
+1998-10-19 Jason Molenda (jsm@bugshack.cygnus.com)
+
+ * configure.in (AM_EXEEXT): Use AC_EXEEXT instead.
+ * configure: Regenerated.
+
+Sat Oct 17 17:39:23 1998 Felix Lee <flee@cygnus.com>
+
+ * core-sol2.c: #include <sys/types.h>, for sol2.7 weirdness.
+
+Fri Oct 16 15:31:38 1998 Michael Snyder <msnyder@cleaver.cygnus.com>
+
+ * m32r-tdep.c (decode_prologue): Return failure if we reach
+ the end of the function without finding the end of the prologue.
+
+1998-10-16 Jason Molenda (jsm@bugshack.cygnus.com)
+
+ * command.c copying.c copying.awk core-aout.c core-regset.c
+ corelow.c dcache.c i386-tdep.c i386v4-nat.c i387-tdep.c
+ infcmd.c infptrace.c infrun.c remote.c solib.c symfile.c
+ symmisc.c valarith.c: Add prototypes.
+
+ * defs.h: Add prototype for utils.c::do_run_cleanups.
+
+ * gdbtypes.c: Add prototypes.
+ (make_pointer_type): Add braces to remove nested if-else ambiguity.
+ (make_reference_type): Ditto.
+
+ * printcmd.c (printf_command): Initialize 'f' and 'string' at
+ function startup to suppress possibly-used-before-initialized warning.
+
+ * remote-utils.c: Add prototypes.
+ (sr_pollchar): Add braces to remove nested if-else ambiguity.
+
+ * ser-tcp.c: Add prototypes.
+ (wait_for): Add braces to remove nested if-else ambiguity.
+ (tcp_readchar): Ditto.
+
+ * ser-unix.c: Add prototypes.
+ (get_tty_state): Don't define errno here.
+ (hardwire_readchar): Only define 't' if we are compiling in a Cygwin
+ environment.
+
+ * symtab.c: Add prototypes.
+ (find_methods): Add braces to remove nested if-else ambiguity.
+ (search_symbols): Set 'i' to an initial value to suppress a
+ possibly-used-before-initialized warning.
+
+ * valops.c: Add prototypes.
+ (value_cast): Set 'eltype2' to an initial value to suppress a
+ possibly-used-before-initialized warning.
+ (value_of_variable): Add braces to remove nested if-else ambiguity.
+ (value_of_this): Ditto.
+
+ * valprint.c: Add prototypes.
+ (print_floating): Add braces to remove nested if-else ambiguity.
+
+Thu Oct 15 19:50:48 1998 Stan Shebs <shebs@andros.cygnus.com>
+
+ * tm-sp64.h (SETUP_ARBITRARY_FRAME, FRAME_SPECIFICATION_DYADIC):
+ Remove, nevermore used.
+
+Thu Oct 15 16:55:00 1998 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * command.c: Include "wait.h" after, rather than before, <wait.h>.
+ "wait.h" was defining all WIF* macro's instead of filling in those
+ that <wait.h> missed.
+
+1998-10-14 Jason Molenda (jsm@bugshack.cygnus.com)
+
+ * defs.h: Move _initialize_printcmd, _initialize_stack,
+ _initialize_blockframe out of here and in to their respective .c
+ files.
+ * blockframe.c: Move _initialize_blockframe prototype to here.
+ * printcmd.c: Move _initialize_printcmd prototype to here.
+ * stack.c: Move _initialize_stack prototype to here.
+
+ * source.c, symtab.h: Move _initialize_source prototype to the .c
+ file.
+ * values.c, value.h: Move _initialize_values prototype to the .c file.
+ * gdbthread.h, thread.c: Move _initialize_thread prototype to the .c
+ file.
+ * breakpoint.c, breakpoint.h: Move _initialize_breakpoint prototype
+ to the .c file.
+
+ * abug-rom.c alpha-nat.c alpha-tdep.c annotate.c ax-gdb.c bcache.c:
+ Standardize comments for the prototype section of these files.
+
+ * configure.in: Look in libc for wctype before looking for it in libc.
+
+Tue Oct 13 18:56:51 1998 Felix Lee <flee@cygnus.com>
+
+ * sol-thread.c (ps_pstop, etc): simple test for proc_service.h
+ version didn't work for sol2.6; pushed it to autoconf.
+ * configure.in (gdb_cv_proc_service_is_old): new test.
+ * acconfig.h (PROC_SERVICE_IS_OLD): new define.
+ * configure, config.in: regenerate.
+
+1998-10-13 Jason Molenda (jsm@bugshack.cygnus.com)
+
+ * blockframe.c (find_pc_sect_partial_function): Add braces to avoid
+ possible nested-if confusion.
+ * breakpoint.c (breakpoint_here_p): Ditto.
+ (breakpoint_inserted_here_p): Ditto.
+ (breakpoint_thread_match): Ditto.
+
+ * gnu-regex.c: Define _REGEX_RE_COMP only if it isn't already defined.
+ * gnu-regex.h: Define _REGEX_RE_COMP to pick up old compatability
+ prototypes.
+
+ * symtab.h: Add prototype for _initialize_source.
+ * value.h: Add prototype for _initialize_value.
+
+ * defs.h: Include sys/types.h or stddef.h to get size_t.
+ (make_cleanup): Add make_cleanup_func typedef and switch to using
+ a prototype for this function.
+ (mfree): Add prototypes for mmalloc, mrealloc, mfree if we aren't
+ using mmalloc.
+
+ * ax-gdb.c breakpoint.c coffread.c corelow.c dbxread.c
+ dwarf2read.c dwarfread.c elfread.c eval.c exec.c infcmd.c infrun.c
+ mipsread.c nlmread.c os9kread.c parse.c printcmd.c symfile.c
+ symmisc.c symtab.c thread.c top.c tracepoint.c typeprint.c
+ valops.c: Cast parameters passed to make_cleanup to use the new
+ make_cleanup_func typedef.
+
+Tue Oct 13 00:51:48 1998 Felix Lee <flee@cygnus.com>
+
+ * sol-thread.c (ps_pstop, etc): different solaris versions have
+ slightly different prototypes in proc_service.h; compensate.
+
+1998-10-12 Jason Molenda (jsm@bugshack.cygnus.com)
+
+ * Makefile.in (AWK): Unused; remove.
+ * configure.in: Remove unused autoconf checks for MINIX, memcpy,
+ poll, select, strings.h.
+ * config.in: Regenerated.
+ * configure: Regenerated.
+
+1998-10-12 Jason Molenda (jsm@bugshack.cygnus.com)
+
+ * configure.in: Check for sys/debugreg.h, asm/debugreg.h.
+ * i386v-nat.c: Include asm/debugreg.h, sys/debugreg.h if it is not
+ present.
+
+Sun Oct 11 12:08:07 1998 Peter Schauer <pes@regent.e-technik.tu-muenchen.de>
+
+ * dwarf2read.c (dwarf2_build_psymtabs_hard): Do not adjust the
+ address range of a compilation unit without children.
+
+ * mdebugread.c (parse_partial_symbols): Fix handling of stabs
+ continuations, use xmalloc and xrealloc.
+
+Fri Oct 9 18:14:43 1998 Mark Alexander <marka@cygnus.com>
+
+ * rs6000-tdep.c: Don't include tm.h twice.
+
+1998-10-08 Keith Seitz <keiths@cygnus.com>
+
+ * main.c (main): Remove calls to {pre,post}_add_symbol_hooks.
+ There should be sufficient information/hooks now to eliminate
+ this hack.
+
+ * exec.c (file_command): Add a new hook here to inform ui's
+ when the exec file has changed. Adding it here allows the
+ ui to be informed after symbol reading.
+
+ * gdbcore.h: Add declaration of file_changed_hook.
+
+Thu Oct 8 08:40:42 1998 Mark Alexander <marka@cygnus.com>
+
+ * rs6000-tdep.c (get_saved_register): Define only if
+ USE_GENERIC_DUMMY_FRAMES is defined.
+
+1998-10-06 Jason Molenda (jsm@bugshack.cygnus.com)
+
+ Eliminate a few warnings from the compiler.
+ * breakpoint.h: Add prototype.
+ * breakpoint.c (do_enable_breakpoint): cast mem_cnt, i to (void).
+ * configure.in: Check if strdup declaration is necessary.
+ * configure: Regenerated.
+ * defs.h: Add prototypes.
+ * gdb_string.h: Only define strdup if necessary.
+ * gdbthread.h: Add prototypes.
+ * printcmd.c: Add prototyptes.
+ (disassemble_command): Remove unused variable 'section'.
+ * symtab.c: Add prototypes.
+ * symtab.h: Include gnu-regex.h, add prototype.
+ * thread.c: Add prototype.
+
+Mon Oct 5 19:44:39 1998 Stan Shebs <shebs@andros.cygnus.com>
+
+ From David Purves <purves@apogee.com>:
+ * stabsread.c (rs6000_builtin_type): Create a complex float instead
+ of an error.
+ (read_sun_floating_type): Similarly.
+ (read_range_type): Create a complex float if self_subrange is
+ true.
+
+Fri Oct 2 19:42:31 1998 Stu Grossman <grossman@babylon-5.cygnus.com>
+
+ * c-lang.c (emit_char c_printchar c_printstr), c-lang.h (c_printstr)
+ ch-lang.c (chill_printstr chill_printchar) c-valprint.c (c_val_print)
+ ch-valprint.c (chill_val_print) expprint.c (print_subexp) f-lang.c
+ (f_printstr f_printchar emit_char) f-valprint.c (f_val_print)
+ jv-lang.c (java_printchar java_emit_char) jv-valprint.c
+ (java_value_print java_val_print) language.c (unk_lang_printchar
+ unk_lang_printstr unk_lang_emit_char) language.h (struct
+ language_defn LA_PRINT_STRING LA_EMIT_CHAR) m2-lang.c (m2_printstr
+ m2_printchar emit_char) printcmd.c (print_formatted) scm-lang.c
+ (scm_printstr) valprint.c (val_print_string) value.h
+ (val_print_string): Add emit_char routines to language_desc struct
+ to allow finer control over language specific character output issues.
+ Add character width arg to printstr routines to allow handling of
+ wchar_t/Unicode strings. Fix c_printstr to handle wide characters.
+ Supply width argument to LA_PRINT_STRING and val_print_string.
+
+ * jv-lang.c (java_object_type dynamics_objfile java_link_class_type
+ get_dynamics_objfile get_java_object_type) jv-lang.h
+ (get_java_object_type): Make lots of things static.
+
+ * expprint.c (dump_prefix_expression dump_subexp): Move opcode name
+ printing to common routine (op_name).
+ * (dump_subexp): Add support for OP_SCOPE.
+
+Fri Oct 2 16:25:54 1998 Stan Shebs <shebs@andros.cygnus.com>
+
+ * configure.host (i[3456]86-*-windows): Remove, no longer used.
+ * mswin: Remove directory, no longer used.
+
+Fri Oct 2 18:52:20 1998 Fernando Nasser <fnasser@cygnus.com>
+
+ * sol-thread.c: Fixed prototypes and calls to supply_fpregset and
+ fill_fpregset
+
+1998-10-02 Keith Seitz <keiths@cygnus.com>
+
+ * remote.c (remote_interrupt): Rewrite to use remote_stop.
+ (remote_interrupt_twice): Remove. remote_stop now handles it.
+ (remote_stop): New function which handles interrupting the
+ remote target so that CLUI and GUI use the same core functions
+ to achieve the same goal.
+ (remote_wait): Change to handle remote_stop properly.
+ [interrupted_already]: New static global to help remote_stop.
+ [remote_ops, extended_remote_ops]: Add remote_stop for to_stop member.
+
+ * target.c: Rename static function "ignore" to "target_ignore" and
+ export it so that gdb can determin if some target vector member is
+ actually not defined. Replace all occurances of ignore.
+
+ * target.h: Export target_ignore.
+
+Fri Oct 2 03:51:48 1998 Peter Schauer <pes@regent.e-technik.tu-muenchen.de>
+
+ * target.c (target_xfer_memory): Handle requests with zero
+ transfer length right away.
+
+ * values.c (unpack_double): Set up code, length and signedness of
+ type _after_ checking for typedef.
+
+Thu Oct 1 15:39:27 EDT 1998 Frank Ch. Eigler <fche@cygnus.com>
+
+ * breakpoint.c (bpstat_stop_status): Do not consider an
+ untripped watchpoint as a "hit".
+
+Thu Oct 1 20:52:39 1998 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * exec.c (exec_file_command), convex-tdep.c (exec_file_command),
+ arm-xdep.c (exec_file_command), remote-rdp.c
+ (remote_rdp_create_inferior), remote-os9k.c
+ (rombug_create_inferior), remote-mm.c (mm_create_inferior),
+ remote-eb.c (eb_create_inferior), remote-es.c
+ (es1800_create_inferior), remote-rdi.c (arm_rdi_create_inferior),
+ remote-sim.c (gdbsim_create_inferior), remote-utils.c
+ (gr_create_inferior), remote-st.c (st2000_create_inferior),
+ remote-nindy.c (nindy_create_inferior), remote-hms.c
+ (hms_create_inferior), remote-e7000.c (e7000_create_inferior),
+ remote-array.c (array_create_inferior), remote-adapt.c
+ (adapt_create_inferior): Replace "exec" with "executable" in
+ messages.
+
+1998-09-25 Keith Seitz <keiths@cygnus.com>
+
+ * rdi-share/unixcomm.c: If using cygwin32, also use the SERPORT and
+ PARPORT defines for win32.
+ (Unix_MatchValidSerialDevice): For cygwin32, valid serial port names
+ start with "com", not "/dev/tty".
+ (Unix_OpenSerial): Do not use O_NONBLOCK on cygwin32.
+
+ * rdi-share/devsw.c (DevSW_Close): Free the device's state
+ (SwitcherState) so that the device may be reopened.
+
+ * remote-rdi.c (mywritec): Send all output through gdb's *_unfiltered
+ functions, ignoring non-ASCII chars, so that non-tty UI's can snarf
+ the output from fputs_hook.
+ (mywrite): Ditto.
+ (arm_rdi_open): Set inferior_pid.
+ (arm_rdi_detach): Pop the target off the target stack so that
+ users can attach and detach multiple times.
+ (arm_rdi_close): Close the opened device and reset inferior_pid, too.
+
+1998-09-24 Jason Molenda (jsm@bugshack.cygnus.com)
+
+ * configure.in: Change --enable-warnings to --enable-build-warnings.
+ * configure: Updated.
+
+1998-09-24 Jason Molenda (jsm@bugshack.cygnus.com)
+
+ * configure.in (WARN_CFLAGS): Add -Wmissing-prototypes.
+ * configure: Regenerated.
+
+1998-09-24 Jason Molenda (jsm@bugshack.cygnus.com)
+
+ * configure.in: Add --enable-warnings.
+ Adjust whitespace of other --with and --enable options so that
+ configure --help lines up correctly.
+ * aclocal.m4: Ditto.
+ * Makefile.in (WARN_CFLAGS): Add. Set by configure.
+ * configure: Regenerated.
+
+Thu Sep 24 15:44:34 1998 Stan Shebs <shebs@andros.cygnus.com>
+
+ * remote-rdi.c: Fix formatting, remove some commented-out code.
+ (init_rdi_ops): Omit needless initializations.
+
+Wed Sep 23 18:21:03 1998 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * remote.c (remote_address_masked): New function - mask address
+ according to REMOTE_ADDRESS_SIZE.
+ (remote_address_size): New global.
+ (hexnumstr): New function - convert arbitrary unsigned to hex.
+ (remote_write_bytes, remote_read_bytes): Use hexnumstr to
+ construct packet address. Mask address when necessary.
+ (_initialize_remote): Add "set remoteaddresssize" command, set
+ REMOTE_ADDRESS_SIZE variable.
+
+ * NEWS: Update.
+
+Wed Sep 23 18:08:52 1998 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * remote.c (_initialize_remote, packet_command, print_packet):
+ Pretty print code.
+
+Wed Sep 23 12:32:54 1998 <cagney@amy.cygnus.com>
+
+ * remote.c (packet_command): Test REMOTE_DESC to determine if
+ remote connection is open.
+
+Tue Sep 22 22:27:24 1998 Mark Alexander <marka@cygnus.com>
+
+ Patch from Dawn Perchik <dawn@cygnus.com>:
+ * rs6000-tdep.c (pop_frame): Handle generic dummy frames.
+ (push_arguments): Likewise.
+ (frame_saved_pc): Likewise.
+ (rs6000_frame_chain): Likewise.
+ (ppc_push_return_address): New function.
+ (get_saved_register): New function.
+ * config/powerpc/tm-ppc-eabi.h: Add generic dummy frame macros.
+
+Mon Sep 21 19:29:32 1998 Stu Grossman <grossman@babylon-5.cygnus.com>
+
+ * defs.h utils.c (fputc_filtered): New function. Does the obvious...
+ * jv-lang.c (java_printchar): Fix output of chars > 0xff. Fold
+ java_emit_char into java_printchar.
+ * language.h (PRINT_LITERAL_FORM): Reformat for readability.
+
+Mon Sep 21 14:38:03 1998 Catherine Moore <clm@cygnus.com>
+
+ * config/arm/tm-arm.h (*_BREAKPOINT): Define both little endian
+ and big endian breakpoint patterns.
+
+ * arm-tdep.c (arm_break_point_from_pc): Insert either big endian
+ or little endian breakpoints depending upon target byte order.
+
+Fri Sep 18 07:53:08 1998 Peter Schauer <pes@regent.e-technik.tu-muenchen.de>
+
+ * sol-thread.c (sol_thread_notice_signals): Use PIDGET when
+ passing pid down to procfs_notice_signals.
+
+Wed Sep 16 14:57:14 1998 Stu Grossman <grossman@babylon-5.cygnus.com>
+
+ * stabsread.c (resolve_symbol_reference): Return 1 on success, 0 on
+ failure.
+ * (define_symbol): Check return value from resolve_symbol_reference,
+ and drop symbol if it fails.
+
+Tue Sep 15 15:24:16 1998 Stu Grossman <grossman@fencer.cygnus.com>
+
+ * stabsread.c: Make all complaints static.
+ * Fix formatting of live range splitting code.
+ * (resolve_symbol_reference define_symbol resolve_live_range): Change
+ errors to complaints so that bad live range symbols won't abort the
+ entire symbol table. Handle errors by aborting just the current
+ symbol.
+ * (ref_init): Goes away. Folded into ref_add().
+ * (REF_MAP_SIZE): Put parens around parameter so that args like
+ `1 + 2' get handled correctly (yes, this was a real bug).
+ * (ref_add): Remove check for allocation failures. Not necessary
+ when using xrealloc(). Fix pointer arithmetic problem when clearing
+ memory. This and the previous patch prevent random SEGV's when there
+ are lots of live range symbols.
+
+Tue Sep 15 14:02:01 1998 Nick Clifton <nickc@cygnus.com>
+
+ * remote-rdi.c: Prevent multiple attempts to close the remote
+ connection.
+
+Tue Sep 15 10:24:17 1998 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * printcmd.c (examine_i_type): New static - type for instructions.
+ (do_examine): For "i" format, specify examine_i_type.
+ (do_examine): Call value_at_lazy instead of value_at so that
+ examine data is only fetched if it is used.
+ (x_command): If examine data was not fetched, set convenience
+ variable "__" to void.
+ (_initialize_printcmd): Initialize examine_i_type.
+
+Sun Sep 13 01:34:59 1998 Michael Snyder <msnyder@cleaver.cygnus.com>
+
+ * blockframe.c (find_pc_sect_partial_function): use bfd section
+ of msymbol for end of section comparison.
+
+Fri Sep 11 14:02:49 1998 Michael Snyder <msnyder@cleaver.cygnus.com>
+
+ * tracepoint.c: clean up several unused variables and such.
+
+Fri Sep 11 12:38:34 EDT 1998 Zdenek Radouch (radouch@cygnus.com)
+
+ * arm-tdep.c (arm_push_arguments): fixed frame construction
+
+Thu Sep 10 20:51:23 1998 Michael Snyder <msnyder@cleaver.cygnus.com>
+
+ * mn10300-tdep.c (mn10300_analyze_prologue): guard against NULL.
+
+Wed Sep 9 19:37:36 1998 Stan Shebs <shebs@andros.cygnus.com>
+
+ * dbxread.c (IGNORE_SYMBOL): Remove definition, is never used.
+ * os9kread.c: Remove comment mentioning IGNORE_SYMBOL.
+
+Wed Sep 9 11:39:05 1998 Ron Unrau <runrau@cygnus.com>
+
+ * blockframe.c(find_pc_sect_partial_function): look for min syms in
+ the same section when trying to guess the end of a function.
+ * symfile.c(list_overlays_command): use print_address_numeric
+ * remote-sim.c: export simulator_command
+
+1998-09-08 Jason Molenda (jsm@bugshack.cygnus.com)
+
+ * breakpoint.c (bpstat_stop_status): Declare a bp match if the
+ current fp matches the bp->fp OR if the current fp is less than
+ the bp->fp if we're looking at a bp_step_resume breakpoint.
+
+Tue Sep 8 19:42:58 1998 Stan Shebs <shebs@andros.cygnus.com>
+
+ * symtab.h (struct symtab): Remove EXTRA_SYMTAB_INFO hook,
+ not currently used.
+ * symfile.c (allocate_symtab): Deprecate use of
+ INIT_EXTRA_SYMTAB_INFO here.
+
+Fri Sep 4 15:33:25 1998 Stan Shebs <shebs@andros.cygnus.com>
+
+ * README: Update remote debugging and testsuite info.
+
+Thu Sep 3 13:50:20 1998 Mark Alexander <marka@cygnus.com>
+
+ * config/mn10300/tm-mn10300.h (FP_REGNUM): Redefine to be a
+ pseudo-register, not the same as a3.
+ (D2_REGNUM, D3_REGNUM, A2_REGNUM, A3_REGNUM): Define.
+ * mn10300-tdep.c (fix_frame_pointer): New function.
+ (set_movm_offsets): Use register number macros instead of
+ hard-coded constants.
+ (mn10300_analyze_prologue): Fix to handle redefinition of FP_REGNUM.
+ (mn10300_frame_chain): Fix to handle redefinition of FP_REGNUM;
+ use register number macros instead of hard-coded constants;
+ add missing parameter to call of mn10300_analyze_prologue.
+ (mn10300_frame_saved_pc): Use register number macros instead of
+ hard-coded constants.
+
+Tue Sep 1 12:04:57 EDT 1998 Zdenek Radouch (radouch@cygnus.com)
+
+ Changes to support/fix ARM/ELF port. Use MAKE_MSYMBOL_SPECIAL for
+ both ELF and COFF;
+ * elfread.c (elf_symtab_read): use ELF specific macro
+ * coffread.c (coff_symtab_read): use COFF_MAKE_MSYMBOL_SPECIAL()
+ * arm-tdep.c: separate COFF and ELF thumb processing
+ disable --mapcs-float processing
+ * dwarf2read.c: Disabled building of minimal symbols
+ * config/arm/tm-arm.h: new macros for distinguishing arm/thumb
+ * config/mips/tm-mips.h: use ELF specific macro
+
+Mon Aug 31 15:42:10 1998 Tom Tromey <tromey@cygnus.com>
+
+ * top.c (context_hook): Define.
+
+Tue Aug 25 13:21:58 1998 Michael Snyder <msnyder@cleaver.cygnus.com>
+
+ * ax-gdb.c (gen_var_ref): Allow for typedef types.
+ (gen_cast, gen_bitfield_ref, gen_expr, gen_deref): ditto.
+
+Mon Aug 24 18:29:03 1998 Michael Snyder <msnyder@cleaver.cygnus.com>
+
+ * tracepoint.c (collect_symbol): Handle register doubles that
+ are stored in two registers.
+
+Mon Aug 24 14:39:08 1998 Mark Alexander <marka@cygnus.com>
+
+ * sh-stub.c (undoSStep): Improve comment.
+ * sparc-tdep.c (sparc_extract_struct_value_address): Simplify to use
+ same method on both 32-bit and 64-bit machines.
+ * sparcl-tdep.c (sparclite_check_watch_resources): Simulator doesn't
+ support hardware breakpoints.
+ * config/sparc/tm-sparc.h (CALL_DUMMY): Improve comments.
+
+1998-08-20 Jason Molenda (jsm@bugshack.cygnus.com)
+
+ * rdi-share/Makefile.am (INCLUDES): Fix typeo.
+ * rdi-share/Makefile.in: Regenerated.
+
+1998-08-19 Jason Molenda (jsm@bugshack.cygnus.com)
+
+ * rdi-share/Makefile.am: Use just `INCLUDES' not `libname_INCLUDES'.
+ * rdi-share/Makefile.in: Regenerated.
+
+1998-08-19 Keith Seitz <keiths@cygnus.com>
+
+ * v850ice.c (v850ice_stop): New function to stop the ICE.
+ (v850ice_load) Pass filename to ICE DLL.
+ (ice_stepi, ice_nexti, ice_cont): Do not directly call the gdb
+ commands -- let the GUI do it so that it can retain control
+ of the display.
+
+Wed Aug 19 15:53:52 1998 Anthony Green <green@hoser.cygnus.com>
+
+ * i386v4-nat.c: Include sys/reg.h if present.
+
+Wed Aug 19 03:07:53 1998 Richard Henderson <rth@cygnus.com>
+
+ * config/alpha/alpha-linux (XDEPFILES): Build ser-tcp.
+
+1998-08-18 Fernando Nasser <fnasser@totem.to.cygnus.com>
+
+ * symtab.c (decode_line_1): For minimal symbol, SKIP_PROLOG to
+ make sure we stop after the frame pointer is locaded and backtrace
+ prints an accurate stack. Complements changes made on Mon Jul 27
+ 10:45:56 1998
+ (decode_line_2): Replaced the whitespace after ">" in a prompt
+ which has been taken away by changes made on Sun Jul 19 02:11:45
+ 1998
+
+1998-08-18 Keith Seitz <keiths@cygnus.com>
+
+ * stack.c: Define new hook, selected_frame_level_changed_hook, which
+ will be called whenever the selected stack level changes.
+ (select_frame): Call the selected_frame_level_changed_hook.
+
+Tue Aug 18 18:03:42 1998 Stan Shebs <shebs@andros.cygnus.com>
+
+ * remote-rdi.c (arm_rdi_open): Pass serial device name to
+ Adp_OpenDevice, and include it in error reports.
+
+1998-08-18 Jason Molenda (jsm@bugshack.cygnus.com)
+
+ * configure.in: Add more header files to AC_CHECK_HEADERS.
+ * configure: Regenerated.
+
+ * command.c: Include wait.h or sys/wait.h if present.
+ * inftarg.c: Ditto.
+ * core-aout.c: Include ptrace.h or sys/ptrace.h if present, based
+ on autoconf test.
+ * infptrace.c: Ditto.
+
+ * expprint.c: Include ctype.h for isprint prototype.
+ * i386aix-nat.c: Include sys/reg.h if autoconf says it is present.
+ * i386v-nat.c: Include ptrace.h, sys/ptrace.h, and sys/reg.h if
+ present, based on autoconf test.
+
+ * utils.c: Include curses.h and term.h if present.
+ (puts_debug): Change 'carriage_return' local variable to return_p
+ to avoid name clash.
+
+ * config/m68k/nm-apollo68b.h: Don't define PTRACE_IN_WRONG_PLACE,
+ determine it with autoconf.
+ * config/i386/nm-linux.h: Don't define NO_SYS_REG_H, determine it
+ with autoconf.
+ * config/i386/nm-i386sco.h: Don't define NO_PTRACE_H, determine it
+ with autoconf.
+ * config/i386/nm-i386v.h: Ditto.
+ * config/i386/nm-symmetry.h: Ditto.
+ * config/m88k/xm-cxux.h: Ditto.
+ * config/m88k/xm-dgux.h: Ditto.
+
+ * config/m68k/delta68.mh (NAT_FILE): nm-delta68.h no longer necessary.
+ * config/m68k/nm-delta68.h: Removed.
+
+Fri Aug 14 11:14:03 1998 Jeffrey A Law (law@cygnus.com)
+
+ * mn10300-tdep.c (set_movm_offsets): Change second argument to
+ be the actual args to movm itself. All callers changed. Only set
+ fi->fsr.regs[x] if reg X is saved by the movm instruction.
+
+Fri Aug 14 04:18:23 1998 Peter Schauer <pes@regent.e-technik.tu-muenchen.de>
+
+ * sol-thread.c (lwp_to_thread): Fix error message for failing
+ td_ta_map_lwp2thr call.
+ (ps_lgetLDT): Mask off upper bits in GS register when comparing
+ with selector.
+
+Wed Aug 12 16:30:01 1998 Frank Ch. Eigler <fche@cygnus.com>
+
+ * remote-sim.c (simulator_command): Reset register cache after
+ simulator command.
+
+Wed Aug 12 09:00:26 1998 Stu Grossman <grossman@babylon-5.cygnus.com>
+
+ * expprint.c (dump_prefix/postfix_expression): Don't try to print
+ type expressions.
+
+Tue Aug 11 11:33:25 1998 Stu Grossman <grossman@babylon-5.cygnus.com>
+
+ * c-typeprint.c (c_print_type): Don't crash if varstring is null.
+ * expprint.c expression.h (dump_expression): Rename to
+ dump_prefix_expression.
+ * Print out the expression in normal form. Call print_longest
+ instead of trying to do it ourselves.
+ * (dump_postfix_expression): New function, prints out the expression
+ with indentation and better formatting and interpretation.
+ * parse.c (parse_exp_1): Put calls to dump expressions under ifdef
+ MAINTENANCE_CMDS and expressiondebug variable.
+
+Thu Aug 6 13:20:02 1998 Ron Unrau <runrau@cygnus.com>
+
+ * infrun.c (wait_for_inferior): use stop_func_name instead of
+ stop_func_start to decide that no debug info exists.
+
+Thu Jul 30 13:53:50 1998 Mark Alexander <marka@cygnus.com>
+
+ * mips-tdep.c (mask_address_p): New variable.
+ (mips_addr_bits_remove): Test mask_address_p to decide whether
+ to mask off the upper 32 bits of addresses.
+ (_initialize_mips_tdep): Add command to set mask_address_p.
+ (mips_call_dummy_address): New function.
+ * config/mips/tm-mips.h (CALL_DUMMY_ADDRESS): Redefine to
+ call mips_call_dummy_address.
+
+1998-07-29 Fernando Nasser <fnasser@totem.to.cygnus.com>
+
+ * symfile.c (add_symbol_file_command): Test for the from_tty
+ parameter and avoid query when not interactive.
+
+Mon Jul 27 16:11:42 1998 Michael Snyder <msnyder@cleaver.cygnus.com>
+
+ * tracepoint.c (remote_set_transparent_ranges): new function.
+ Send the start and end addresses of all loadable read-only
+ sections down to the trace target, so that it can treat them
+ as "transparent" (ie. don't care if they were collected or not).
+
+Mon Jul 27 15:38:07 1998 Mark Alexander <marka@cygnus.com>
+
+ * mn10300-tdep.c (mn10300_analyze_prologue): Undo previous fix
+ for setting frame address in optimized code; made unnecessary
+ by compiler fixes.
+
+Mon Jul 27 10:45:56 1998 Martin M. Hunt <hunt@cygnus.com>
+
+ * symtab.c (decode_line_1): For minimal symbol, call
+ find_pc_sect_line() to make sure the line number gets set
+ properly.
+ (print_symbol_info): Redeclare function void.
+
+1998-07-27 Jason Molenda (jsm@bugshack.cygnus.com)
+
+ * config/d10v/tm-d10v.h (REGISTER_NAMES): sp -> r15. The
+ stack pointer et al are synthesized from the SP_REGNUM (etc)
+ defines and should not be mentioned in REGISTER_NAMES.
+
+Fri Jul 24 14:41:19 1998 Michael Snyder <msnyder@cleaver.cygnus.com>
+
+ * tracepoint.c (encode_actions): Treat register names and simple
+ variable names as special cases and don't convert them to byte-
+ codes: these things can be collected far more efficiently
+ without invoking the bytecode interpreter.
+
+Fri Jul 24 13:32:46 1998 Mark Alexander <marka@cygnus.com>
+
+ * config/i386/tm-i386.h (STORE_STRUCT_RETURN): Make it
+ work on hosts of any endianness.
+ * config/i386/tm-i386v.h: Ditto.
+
+Fri Jul 24 07:41:12 1998 Mark Alexander <marka@cygnus.com>
+
+ * mn10300-tdep.c (set_movm_offsets): New helper function
+ for mn10300_analyze_prologue.
+ (mn10300_analyze_prologue): Simplify by factoring out common code.
+ Fix bugs in setting frame address for optimized code.
+ Use read_memory_nobpt instead of target_read_memory.
+
+Thu Jul 23 17:01:17 1998 Michael Snyder <msnyder@cleaver.cygnus.com>
+
+ * tracepoint.c (collect_symbol): handle LOC_ARG case.
+
+Thu Jul 23 15:07:40 1998 Dawn Perchik <dawn@cygnus.com>
+
+ * sparc-tdep.c (sparc_init_extra_frame_info): Recognize when we're
+ in a function prologue before the SAVE instruction.
+ (sparc_frame_saved_pc): Ditto.
+ * config/sparc/tm-sparc.h (EXTRA_FRAME_INFO): Add in_prologue flag.
+
+Thu Jul 23 14:58:09 1998 Dawn Perchik <dawn@cygnus.com>
+
+ * i386-tdep.c (i386_get_frame_setup): Recognize function
+ prologues in code compiled with -fcheck-stack.
+
+Thu Jul 23 14:49:27 1998 Dawn Perchik <dawn@cygnus.com>
+
+ * remote-mips.c (remote_mips_insert_hw_breakpoint,
+ remote_mips_remove_hw_breakpoint): New functions for hardware
+ breakpoints on LSI targets.
+ * config/mips/tm-embed.h (target_remove_hw_breakpoint,
+ target_insert_hw_breakpoint): Define to call
+ remote_mips_insert_hw_breakpoint and remote_mips_remove_hw_breakpoint,
+ respectively.
+
+1998-07-21 Fernando Nasser <fnasser@totem.to.cygnus.com>
+
+ * source.c (print_source_lines): Print "No such file or directory"
+ just once.
+ (directory_command): same as above; resets if user issues dir.
+
+Sun Jul 19 02:11:45 1998 Martin M. Hunt <hunt@cygnus.com>
+
+ * symtab.c (decode_line_2): Instead of printing a prompt
+ and calling command_line_input() without a prompt, just
+ call it with the proper args. This makes the GUI work too.
+
+Fri Jul 17 9:26:50 1998 Ron Unrau <runrau@cygnus.com>
+
+ * blockframe.c (find_pc_sect_partial_function): allow for the possi-
+ bility of multiple symbols at the same address when finding high.
+ * breakpoint.c (resolve_sal_pc): if the function based section lookup
+ fails, try getting the section from the minimal symbol table.
+ * parse.c (write_exp_msymbol): use symbol_overlayed_address to get
+ the LMA of a minimal symbol if unmapped.
+ * symtab.c (find_line_symtab): change interface to return symtab
+ containing the best linetable found.
+ (decode_line_1): use find_line_symtab to set val.symtab. This should
+ improve support for source files with multiple symtabs.
+
+Wed Jul 15 11:51:33 1998 Keith Seitz <keiths@cygnus.com>
+
+ * main.c (main): Fix violations of GNU coding standard.
+
+ * breakpoint.c: Export delete_command.
+
+ * infcmd.c: Export continue_command, stepi_command, and nexti_command.
+
+ * Makefile.in: Add target for v850ice.o.
+
+ * configure.tgt: Add cygwin32 dependencies for v850 ice.
+
+Wed Jul 15 10:58:29 1998 Nick Clifton <nickc@cygnus.com>
+
+ * tracepoint.c (set_raw_tracepoint): Cope with symbols that do not
+ have an associated directory.
+
+Mon Jul 13 15:21:04 1998 Mark Alexander <marka@cygnus.com>
+
+ * utils.c (puts_debug): Display non-printable characters in hex
+ instead of octal.
+
+Thu Jul 9 16:16:47 1998 Jeffrey A Law (law@cygnus.com)
+
+ * mn10300-tdep.c (mn10300_generic_register_names): New variable.
+ (set_machine_hook): New function. Copy the appropriate register
+ names into reg_names.
+ (_initialize_mn10300_tdep): Set up to call set_machine_hook.
+ * tm-mn10300 (NUM_REGS): Bump to 32.
+ (REGISTER_NAMES): Updated accordingly.
+
+
+Tue Jul 7 7:40:13 1998 Ron Unrau <runrau@cygnus.com>
+
+ * symtab.c (find_pc_sect_psymbol): allow case where textlow is 0
+
+Thu Jul 2 15:57:58 1998 Frank Ch. Eigler <fche@cygnus.com>
+
+ * breakpoint.c (resolve_sal_pc): Accept absence of innermost
+ Lexical block for breakpoint resolution.
+
+Thu Jul 2 10:22:00 1998 Dawn Perchik <dawn@cygnus.com>
+
+ * mdebugread.c (parse_partial_symbols): Go ahead and read the .mdebug
+ section, but just don't add a 2nd minimal symbol if this is an .mdebug
+ section in an ELF file.
+
+1998-07-01 Jim Blandy <jimb@zwingli.cygnus.com>
+
+ * Makefile.in (ax-general.o): Depend on $(defs_h) too.
+ (ax_h): Bother to define this.
+
+Mon Jun 29 19:01:18 1998 Jim Wilson <wilson@cygnus.com>
+
+ * gnu-regex.c (re_comp): Add cast to char * before gettext calls.
+
+Sun Jun 28 11:35:48 1998 Peter Schauer <pes@regent.e-technik.tu-muenchen.de>
+
+ Improve support for SunPro F77.
+ * dbxread.c (end_psymtab, process_one_symbol): Handle minimal
+ symbols with trailing underscore names.
+ * minsyms.c (find_stab_function_addr): Ditto.
+ * dbxread.c (process_one_symbol): Ignore N_ALIAS for now.
+ * partial-stab.h (case N_ALIAS): Ditto.
+ * stabsread.c (read_sun_builtin_type): Handle boolean types.
+
+Fri Jun 26 14:03:01 1998 Keith Seitz <keiths@cygnus.com>
+
+ * symtab.h (enum namespace): Add new namespaces FUNCTIONS_NAMESPACE,
+ TYPES_NAMESPACE, METHODS_NAMESPACE, and VARIABLES_NAMESPACE used by
+ new search_symbols.
+ Add prototype for search_symbols and free_search_symbols.
+
+ * symtab.c (list_symbols): Rewrite to use new search_symbols.
+ (file_matches): New helper function for search_symbols.
+ (free_search_symbols): New function which frees data returned from
+ search_symbols.
+ (print_symbol_info): New helper function which prints info about a
+ matched symbol to stdout. Extracted from old list_symbols.
+ (print_msymbol_info): New helper function which prints info about
+ a matched msymbol to stdout. Extracted from old list_symbols.
+ (symtab_symbol_info): Extracted from old list_symbols.
+ (variables_info): Use symtab_symbol_info.
+ (functions_info): Use symtab_symbol_info.
+ (types_info): Use symtab_symbol_info.
+ (rbreak_command): Rewrite to use new search_symbols.
+
+Thu Jun 25 22:38:32 1998 Frank Ch. Eigler <fche@cygnus.com>
+
+ * mips-tdep.c (mips_push_arguments): Use 128-bit stack frame
+ alignment for inferior calls.
+
+Wed Jun 24 23:17:12 1998 Mark Alexander <marka@cygnus.com>
+
+ * mn10200-tdep.c (mn10200_analyze_prologue): Fix calculation
+ of jsr target address.
+
+Tue Jun 23 19:37:46 1998 Mark Alexander <marka@cygnus.com>
+
+ * config/mn10200/tm-mn10200.h (SAVED_PC_AFTER_CALL): Don't
+ zero upper byte of address.
+
+Tue Jun 23 17:32:26 1998 Michael Snyder <msnyder@cleaver.cygnus.com>
+
+ * rs6000-tdep.c (pop_dummy_frame): use memcpy.
+ (push_arguments): use memset.
+ (various other places): fix up indentation and long lines.
+
+Tue Jun 23 11:58:35 1998 Jason Molenda (crash@bugshack.cygnus.com)
+
+ * configure.in: s/lXext/-lXext/ for Jillian's change.
+
+Tue Jun 23 11:14:04 1998 Michael Snyder <msnyder@cleaver.cygnus.com>
+
+ * source.c (find_source_lines): fix indentation.
+
+ * config/mips/tm-irix5.h: Modify to work better on irix 6, by
+ making FP registers 8 bytes instead of 4.
+ REGISTER_BYTES: redefine. REGISTER_BYTE(): redefine.
+ REGISTER_VIRTUAL_TYPE: redefine. MIPS_LAST_ARG_REGNUM: redefine.
+ * irix5-nat.c (fetch_core_registers): read 8 bytes per FP register.
+ * mips-tdep.c (FP_REGISTER_DOUBLE): new macro to distinguish
+ targets with 8-byte FP registers (don't use TARGET_MIPS64).
+ (STACK_ARGSIZE): new macro, how much space is taken up on the
+ stack for each function argument (don't use TARGET_MIPS64).
+ (mips_push_arguments): modify logic to work better on Irix 6
+ (n32 ABI).
+
+Tue Jun 23 12:29:53 1998 Jillian Ye <jillian@cygnus.com>
+
+ * configure.in: Add -lXext to mips_extra_libs
+ * configure: Regenerated.
+
+Sun Jun 21 09:31:12 1998 Ron Unrau (runrau@cygnus.com)
+
+ * symtab.c (find_line_pc): assumed that a PC of 0 is illegal.
+ Changed to pass PC as arg and return 1 if valid (0 otherwise).
+ * symtab.h: Change prototype to match.
+ * symtab.c (find_line_pc_range): Use new interface.
+ * breakpoint.c (resolve_sal_pc): Ditto.
+
+Wed Jun 17 15:50:00 1998 Ron Unrau (runrau@cygnus.com)
+
+ * parse.c (target_map_name_to_register): Check target specific
+ aliases *first* so that it can over-ride architectural names
+
+Wed Jun 17 17:13:38 1998 Said Ziouani (saidz@park-street.cygnus.com)
+
+ * remote-sds.c (sds_start_remote): Fix printf call.
+
+Tue Jun 16 16:32:08 1998 Mark Alexander <marka@cygnus.com>
+
+ * mn10200-tdep.c (mn10200_analyze_prologue): Fix null pointer
+ crash when in "start".
+
+Tue Jun 16 14:38:40 1998 Ron Unrau (runrau@cygnus.com)
+
+ * dbxread.c: reset function_start_offset after a finishing N_FUN
+ is seen.
+ * remote-sim.c: allow TARGET_REDEFINE_DEFAULT_OPS to override
+ target vectors as needed.
+
+Sun Jun 14 08:46:25 1998 Ron Unrau (runrau@cygnus.com)
+
+ * partial-stab.h: 'F' and 'f' type N_FUN psymbols should pass
+ CUR_SYMBOL_VALUE as CORE_ADDR instead of long
+ * buildsym.[ch]: export pending_blocks list
+
+Sat Jun 13 13:02:32 1998 Dawn Perchik (dawn@cygnus.com)
+
+ * remote.c: Fix remote help string to match that of help.exp.
+
+Fri Jun 12 14:22:55 1998 Jason Molenda (crash@bugshack.cygnus.com)
+
+ * configure.in (LIBS): Add -lw to the list of libraries if needed.
+
+Thu Jun 11 15:05:10 1998 Jason Molenda (crash@bugshack.cygnus.com)
+
+ * btowc.c: Removed.
+ * configure.in: Don't see if we need to replace btowc().
+ * Makefile.in: Don't include LIBOBJS.
+ * configure: Regenerated.
+ * gnu-regex.c (regex_compile): Only support i18n [:foo:] if
+ we have btowc().
+
+Wed Jun 10 15:39:14 1998 Stu Grossman <grossman@babylon-5.cygnus.com>
+
+ * c-exp.y: Fix problems with parsing "'foo.bar'::func".
+ Some languages allow symbols with dots.
+
+ * gdbtypes.c (check_stub_method): Cosmetic. Use more descriptive
+ names for parameters.
+
+ * jv-exp.y: Parser now accepts primitive types.
+ * (parse_number): Use correct ifdef for scanf long double support.
+ * jv-lang.c (java_array_type): Initial cut at array support.
+
+ * language.c language.h (set_language): Now returns previous language.
+
+ * symtab.c (find_methods): Make static. Cosmetic changes, including
+ indentation, and adding descriptive comments. Move local variable
+ defs into the block they are used in.
+ * Don't call check_stub_method any more. Use gdb_mangle_name to
+ generate the full method name. find_method doesn't need all the other
+ goobldegook that check_stub_method does.
+ * (gdb_mangle_name): Use more descriptive names for parameters. Fix
+ comment.
+ * (lookup_partial_symbol lookup_block_symbol): Check for java to
+ ensure we can find mangled names.
+ * (decode_line_1): Move local variable defs into the block they are
+ used in. (Improves code readability.)
+
+Wed Jun 10 18:04:35 1998 Frank Ch. Eigler <fche@cygnus.com>
+
+ * gdbtypes.c (get_discrete_bounds): Assign unsigned type flag for
+ all-positive enum.
+ (create_set_type): Ditto for all-positive set values.
+ * values.c (unpack_field_as_long): Check for typedef in struct
+ field unpacking.
+
+Wed Jun 10 14:06:05 1998 Jason Molenda (crash@bugshack.cygnus.com)
+
+ * configure.in: Add some tests for gnu-regex.c's benefit.
+ See if btowc() function is provided in C library.
+ * configure, config.in: Regenerated.
+ * Makefile.in (CLIBS, CDEPS): Add @LIBOBJS@ to build btowc.c
+ if necessary.
+ * btowc.c: New file.
+
+ * gnu-regex.c: Reorder wchar.h and wctype.h includes for Solaris'
+ benefit.
+ Drop namespace preserving defines for now.
+
+Wed Jun 10 11:53:42 1998 Jason Molenda (crash@bugshack.cygnus.com)
+
+ * gnu-regex.c: Include "gnu-regex.h", not "regex.h".
+
+Wed Jun 10 11:34:07 1998 Jason Molenda (crash@bugshack.cygnus.com)
+
+ * gnu-regex.c, gnu-regex.h: Change LGPL license to GPL license
+ to stay consistent with the rest of GDB.
+
+Wed Jun 10 11:27:39 1998 Jason Molenda (crash@bugshack.cygnus.com)
+
+ * gnu-regex.c, gnu-regex.h: Update to current FSF (glibc) versions.
+
+Wed Jun 10 10:58:18 1998 Michael Snyder <msnyder@cleaver.cygnus.com>
+
+ * printcmd.c (disassemble_command): move overlay mapping code
+ "up" into find_pc_partial_function.
+ * blockframe.c (find_pc_partial_function): adjust start address
+ and end address for overlays (mapped vs. unmapped addresses),
+ so that all callers of this function may benefit.
+ * m32r-tdep.c (m32r_skip_prologue): adjust indentation.
+
+Mon Jun 8 16:08:10 1998 Ron Unrau <runrau@cygnus.com>
+
+ * objfiles.c (add_to_objfile_sections): All targets to define
+ TARGET_KEEP_SECTION to permit them to retain bfd sections that
+ GDB would otherwise have discarded.
+
+Fri Jun 5 13:56:19 1998 Doug Evans <devans@canuck.cygnus.com>
+
+ * dbxread.c (read_dbx_symtab): Don't lower texthigh for last psymtab.
+
+Thu Jun 4 18:35:04 1998 Stan Shebs <shebs@andros.cygnus.com>
+
+ * remote.c (init_extended_remote_ops): Make extended_remote_ops
+ by copying from remote_ops, move it and init_remote_ops to
+ usual place at end of file, remove "void" from arg lists.
+
+Thu Jun 4 17:51:06 1998 Mark Alexander <marka@cygnus.com>
+
+ * sparc-tdep.c (sparc_fix_call_dummy): Byte-swap the call dummy
+ on bi-endian machines.
+ (sparc_extract_return_value): Handle values smaller than int on
+ machines with little-endian data.
+ (sparc_target_architecture_hook): Set bi_endian flag.
+
+Thu Jun 4 12:14:48 1998 Michael Snyder <msnyder@cleaver.cygnus.com>
+
+ * printcmd.c (disassemble_command): Fix off-by-one error for
+ disassembling functions in unmapped overlay sections.
+
+Thu Jun 4 10:15:03 1998 Elena Zannoni <ezannoni@kwikemart.cygnus.com>
+
+ * remote.c: merged.
+
+ - Jim Blandy <jimb@zwingli.cygnus.com>
+ (print_packet, remote_packet_command): New functions.
+ (_initialize_remote): Register the remote-packet command.
+ - David Taylor <taylor@texas.cygnus.com>
+ (_initialize_remote): remote-compare is now
+ compare-sections.
+ - Elena Zannoni <ezannoni@kwikemart.cygnus.com>
+ (remote_compare_command): added warning, issued in case
+ of mismatch only.
+
+Thu Jun 4 08:25:38 1998 Michael Snyder <msnyder@cleaver.cygnus.com>
+
+ * remote.c (remote_compare_command): New function, new command.
+ Compare object file binary image with corresponding memory on
+ remote target. Report differences.
+
+Tue Jun 2 19:05:04 1998 Mark Alexander <marka@cygnus.com>
+
+ * sparc-tdep.c (sparc_target_architecture_hook): Set target
+ byte order only when it's selectable.
+
+Tue Jun 2 02:01:56 1998 Mark Alexander <marka@cygnus.com>
+
+ * sparc-tdep.c (sparc_target_architecture_hook): New function to
+ set endianness based on machine type.
+ (_initialize_sparc_tdep): Initialize target_architecture_hook.
+ (sparc_print_register_hook): Print PSR and FPSR in fancy format
+ on 32-bit machines.
+ * config/sparc/tm-sparc.h (PRINT_REGISTER_HOOK): Redefine to
+ call sparc_print_register_hook instead of using inline code.
+ * config/sparc/tm-sp64.h (PRINT_REGISTER_HOOK): Remove.
+
+Thu May 28 17:19:14 1998 Keith Seitz <keiths@cygnus.com>
+
+ * main.c (main): Check for NULL from getenv on CYGWIN32.
+
+Thu May 28 09:41:44 1998 Nick Clifton <nickc@cygnus.com>
+
+ * monitor.c (monitor_vsprintf): Handle %%. Patch courtesy of
+ Felix Lee (flee@cygnus.com)
+
+Thu May 28 00:27:35 1998 Peter Schauer <pes@regent.e-technik.tu-muenchen.de>
+
+ * mips-tdep.c (mips_push_dummy_frame): Fix calculation of
+ PROC_REG_OFFSET and PROC_FREG_OFFSET.
+
+Mon Apr 27 14:37:49 1998 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * config/v850/tm-v850.h (REGISTER_BYTE): FP_REGNUM and
+ FP_RAW_REGNUM use the same register location.
+
+ * v850-tdep.c (v850_scan_prologue): Use FP_RAW_REGNUM instead of
+ FP_REGNUM.
+ (v850_frame_chain): Ditto.
+
+ * config/v850/tm-v850.h (REGISTER_NAMES): Add "fp".
+ (NUM_REGS): Update.
+ (FP_REGNUM): Update.
+ (FP_RAW_REGNUM): Define.
+
+Wed May 27 14:22:31 1998 Keith Seitz <keiths@cygnus.com>
+
+ * main.c (main): Convert the path returned from getenv to a posix
+ path on cygwin32 hosts.
+
+Mon May 25 13:31:27 1998 Keith Seitz <keiths@cygnus.com>
+
+ * remote.c (remote_open_1): If an error occurs starting the remote,
+ pop the target AND return.
+
+Sat May 23 02:23:09 1998 Peter Schauer <pes@regent.e-technik.tu-muenchen.de>
+
+ * dwarf2read.c (read_subroutine_type): Set TYPE_FLAG_PROTOTYPED
+ on C++ functions.
+ * valops.c (value_arg_coerce): Add new argument to indicate whether
+ the function has a prototype, handle integer and float promotions
+ accordingly.
+ (call_function_by_hand): Always call value_arg_coerce, pass down
+ prototype information.
+
+Fri May 22 10:56:36 1998 John Metzler <jmetzler@cygnus.com>
+
+ * remote.c (_initialize_remote): Typo extended__remote
+
+Thu May 21 13:14:25 1998 John Metzler <jmetzler@cygnus.com>
+
+ * gnu-nat.c (init_gnu_ops): Initialization of target ops by assignment.
+ (_initialize_gnu_nat): Call new init
+ * mac-nat.c (init_child_ops): Ditto.
+ (_initialize_mac_nat): Ditto.
+ * monitor.c (init_base_monitor_ops): Ditto.
+ (_initialize_remote_monitors): Ditto.
+ * ppc-bdm.c (init_bdm_ppc_ops): Ditto.
+ (_initialize_bdm_ppc): Ditto.
+ * remote-adapt.c (init_adapt_ops): Ditto.
+ (_initialize_remote_adapt): Ditto.
+ * remote-array.c (init_array_ops): Ditto.
+ (_initialize_array): Ditto.
+ * remote-bug (init_bug_ops): Ditto.
+ (_initialize_remote_bug): Ditto.
+ * remote-e7000.c (init_e7000_ops): Ditto.
+ (_initialize_remote_e7000): Ditto.
+ * remote-eb.c (init_eb_ops): Ditto.
+ (_initialize_remote_eb): Ditto.
+ * remote-es.c (init_es1800_ops): Ditto.
+ (init_es1800_child_ops): Ditto.
+ (_initialize_es1800): Ditto.
+ * remote-hms.c (init_hms_ops): Ditto.
+ (_initialize_remote_hms): Ditto.
+ * remote-mm.c (init_mm_ops): Ditto.
+ (_initialize_remote_mm): Ditto.
+ * remote-nindy.c (init_nindy_ops): Ditto.
+ (_initialize_nindy): Ditto.
+ * remote_nrom.c (init_nrom_ops): Ditto.
+ (_initialize_remote_nrom): Ditto.
+ * remote-os9k (init_rombug_ops): Ditto.
+ (_initialize_remote_os9k): Ditto.
+ * remote-rdi.c (init_rdi_ops): Ditto.
+ (_initialize_remote_rdi): Ditto.
+ * remote-rdp.c (init_remote_rdp_ops): Ditto.
+ (_initialize_remote_rdp): Ditto.
+ * remote-sds.c (init_sds_ops): Ditto.
+ (_initialize_remote_sds): Ditto.
+ * remote-sim.c (init_gdbsim_ops): Ditto.
+ (_initialize_remote_sim): Ditto.
+ * remote-st.c (init_st2000_ops): Ditto.
+ (_initialize_remote_st2000): Ditto.
+ * remote-udi.c (init_udi_ops): Ditto.
+ (_initialize_remote_udi): Ditto.
+ * remote-vx.c (init_vx_ops): Ditto.
+ (init_vx_run_ops): Ditto.
+ (_initialize_vx): Ditto.
+ * remote.c (init_remote_ops): Ditto.
+ (init_extended_remote_ops): Ditto.
+ (_initialize_remote): Ditto.
+ * sparcl-tdep.c (init_sparclite_ops): Ditto.
+ (_initialize_sparcl_tdep): Ditto.
+ * v850ice.c (init_850ice_ops): Ditto.
+ (_initialize_v850ice): Ditto.
+ * win32-nat.c (init_child_ops): Ditto.
+ (_initialize_inftarg): Ditto.
+
+1998-05-21 Jim Blandy <jimb@zwingli.cygnus.com>
+
+ * ax-gdb.c (const_var_ref): Don't handle function names. I don't
+ want to implement all the "usual unary conversion" rules for
+ constants.
+ (gen_usual_unary): Turn "function" values into "pointer to
+ function" values, in accordance with ANSI.
+ (gen_deref): Don't do the usual unary conversions here. Let the
+ caller do it. Note that dereferencing a function pointer yields
+ a function designator, which we call an rvalue, not an lvalue.
+ (gen_address_of): Handle functions specially.
+ (gen_struct_ref): Perform the usual unary conversions before
+ calling gen_deref.
+ (gen_expr): In case for the prefix '*' operator, call
+ gen_usual_unary manually.
+
+Wed May 20 15:29:41 1998 Gavin Koch <gavin@cygnus.com>
+
+ * mips/tm-tx39.h (MIPS_DEFAULT_FPU_TYPE): Defined as MIPS_FPU_NONE.
+ * mips/tm-tx39l.h: Same.
+
+Wed May 20 10:12:11 1998 John Metzler <jmetzler@cygnus.com>
+
+ * m32r-tdep.c (decode_prologue): Handle frames compiled with -Os.
+ Split out as separate function called by skip prologue and scan
+ prologue. new formula handles optimization in which the prologue
+ is interleaved with the body of the function. Also recognizes new
+ variations of prologue encoding. Use of frame pointer is
+ essential to debugging, -fno-omit-frame-pointer
+ (m32r_skip_prologue): Call decode prologue, ignore line info
+ (m32r_scan_prologue): Call decode prologue, ignore line info.
+
+Tue May 19 17:23:54 1998 John Metzler <jmetzler@cygnus.com>
+
+ * w89k-rom.c (_initialize_w89k): Call new init function
+ (init_w89k_cmds): Convert to dynamic initialization of monitor_ops
+ data structure for forward compatability with additions to the
+ data structure.
+ * dbug-rom.c (_initialize_dbug_rom): ditto
+ (init_dbug_cmds): ditto
+ * m32r-rom.c (_initialize_m32r_rom): ditto
+ (init_m32r_cmds): ditto
+
+Tue May 19 14:54:11 1998 Michael Snyder <msnyder@cleaver.cygnus.com>
+
+ * tracepoint.c (memrange_cmp): use const void * args to avoid
+ ANSI compiler warnings.
+
+1998-05-19 Jim Blandy <jimb@zwingli.cygnus.com>
+
+ * ax-gdb.c (gen_fetch, gen_var_ref, gen_deref, find_field,
+ gen_bitfield_ref, gen_expr): Call error, not abort.
+ * ax-general.c (read_const, generic_ext, ax_trace_quick,
+ ax_label, ax_const_d, ax_reg, ax_print): Same.
+
+ * tracepoint.c: Remove the $(...) syntax for memranges.
+ (validate_actionline, encode_actions, trace_dump_command): Remove
+ clauses for the $(...) syntax.
+ (parse_and_eval_memrange): Function deleted.
+ (_initialize_tracepoint): Update function description.
+
+ * ax-gdb.c (_initialize_ax_gdb): Make the "agent" command a
+ subcommand of "maintenance", as it should have been from the
+ beginning. #include "gdbcmd.h", to get the declaration for
+ maintenancelist.
+ * Makefile.in: Document that dependency.
+
+Tue May 19 12:00:58 1998 Elena Zannoni <ezannoni@kwikemart.cygnus.com>
+
+ * tracepoint.c (get_tracepoint_by_number): new function, to access
+ traceframe_number for use of the GUI.
+
+ * tracepoint.h: added prototype for get_traceframe_number.
+
+Mon May 18 13:34:27 1998 Keith Seitz <keiths@cygnus.com>
+
+ * dbxread.c (process_one_symbol): If block addresses are relative to
+ function start addresses, reset function_start_address whenever a new
+ source file is seen.
+
+Mon May 18 13:04:27 1998 Michael Snyder <msnyder@cleaver.cygnus.com>
+
+ * tracepoint.c (get_tracepoint_by_number): make sure to advance
+ arg pointer even if we fail to parse a useful number. Otherwise,
+ since this function is called in a loop, it may loop forever!
+ Also change strtol call to allow arbitrary radix.
+ (map_args_over_tracepoints (and other places)): add QUIT; call
+ to loop, to allow breakout using control-C. Not all loops were
+ analyzed to make sure they could terminate cleanly, but even
+ terminating with a messed-up tracepoint list would be better
+ than not terminating at all!
+ (tdump_command): check to see if we're connected to a trace-
+ capable target (currently only "remote") before doing anything
+ else.
+
+Sat May 16 22:21:48 1998 Frank Ch. Eigler <fche@cygnus.com>
+
+ * config/d30v/tm-d30v.h (INIT_FRAME_PC_FIRST): Fill in PC into
+ frame struct before extracting saved register offsets.
+
+Fri May 15 22:47:45 1998 Michael Snyder <msnyder@cleaver.cygnus.com>
+
+ * tracepoint.c (encode_actions): fix typo in printf format string.
+
+1998-05-15 Jim Blandy <jimb@zwingli.cygnus.com>
+
+ Implement a few more tracing operators: ^ | & ~ !
+ * ax-gdb.c (gen_integral_promotions, gen_logical_not,
+ gen_complement): New functions.
+ (gen_binop): New argument MAY_CARRY, indicating whether we need to
+ correct the upper bits of the value after performing the
+ operation. Callers changed.
+ (gen_expr): Handle BINOP_BITWISE_AND, BINOP_BITWISE_IOR, and
+ BINOP_BITWISE_XOR here as well, by calling gen_binop. Handle
+ UNOP_LOGICAL_NOT, UNOP_COMPLEMENT.
+
+ * ax-gdb.c (gen_conversion): Reworked to avoid some unnecessary
+ sign extension.
+
+ * ax-gdb.c (gen_usual_arithmetic): Renamed from gen_usual_binary,
+ to match the ANSI C standard better. Callers changed.
+
+ * ax-gdb.c (gen_traced_pop): Add prototyped declaration.
+
+Fri May 15 18:18:38 1998 David Taylor <taylor@texas.cygnus.com>
+
+ * tracepoint.c (stringify_collections_list): return a collection
+ of strings rather than a single string.
+ (free_actions_list): new function.
+ (encode_actions): process collection of strings returned by
+ stringify_collections_list.
+
+1998-05-15 Jim Blandy <jimb@zwingli.cygnus.com>
+
+ * ax-gdb.c (gen_traced_pop): New function.
+ (gen_expr): Call it for comma operator.
+ (gen_trace_for_expr): Call it, instead of writing it out.
+
+ Add facilities for sending arbitrary packets to the remote agent.
+ There are a bunch of improvements to make (make it generic; handle
+ 'O' replies properly), but I just want to get this onto the branch.
+ * remote.c (print_packet, remote_packet_command): New functions.
+ (_initialize_remote): Register the remote-packet command.
+
+Thu May 14 17:52:31 1998 Elena Zannoni <ezannoni@kwikemart.cygnus.com>
+
+ * tracepoint.c: move actionline_type definition to tracepoint.h.
+ (validate_actionline): make non static.
+
+ * tracepoint.h: move actioline_type definition from tracepoint.c.
+ (validate_actionline) moved prototype from tracepoint.c.
+
+Thu May 14 11:49:18 1998 David Taylor <taylor@texas.cygnus.com>
+
+ * tracepoint.c (validate_actionline): add additional error
+ checking, remove some dead code.
+ (encode_actions): additional cleanups.
+ (trace_find_command): remove some dead code.
+ (trace_find_pc_command): ditto.
+ (trace_find_tracepoint_command): ditto.
+ (trace_find_line_command): ditto.
+ (trace_find_range_command): ditto.
+ (trace_find_outside_command): ditto.
+
+Thu May 14 5:51:00 1998 Ron Unrau <runrau@cygnus.com>
+
+ * symtab.c (decode_line_1): set section for "break *<addr>"
+
+Wed May 13 20:58:02 1998 Mark Alexander <marka@cygnus.com>
+
+ * corefile.c (reopen_exec_file): Reopen the exec file if
+ it has changed.
+
+Wed May 13 15:22:02 1998 Mark Alexander <marka@cygnus.com>
+
+ * sparc-tdep.c (fetch_instruction): New function.
+ (single_step, sparc_init_extra_frame_info, examine_prologue):
+ Use fetch_instruction instead of read_memory_integer
+ to ensure that instructions are always read as big-endian.
+
+Wed May 13 14:42:21 1998 Ian Lance Taylor <ian@cygnus.com>
+
+ * configure.in: Add AC_FUNC_ALLOCA.
+ * defs.h: Check HAVE_ALLOCA_H rather than sparc. Add _AIX pragma
+ alloca.
+ * configure: Rebuild.
+ * Makefile.in (jv-lang.o, jv-typeprint.o, jv-valprint.o): New
+ targets.
+
+Wed May 13 11:19:08 1998 Michael Snyder <msnyder@cleaver.cygnus.com>
+
+ * tracepoint.c (trace_command): Remove old diagnostic code that was
+ preventing tracepoints from being defined with a full-path filename.
+
+Tue May 12 13:17:35 1998 Frank Ch. Eigler <fche@cygnus.com>
+
+ * stabsread.c (read_one_struct_field): Check for typedef in type
+ tree before clearing bitfield information.
+
+1998-05-11 Jim Blandy <jimb@zwingli.cygnus.com>
+
+ * ax-gdb.c (gen_binop): New function, based on gen_mul, to replace
+ gen_mul and gen_div, and handle `%' op as well. Correctly tests
+ type of arguments.
+ (gen_expr): Factor out common code in binary arithmetic operators.
+ Add support for `%'.
+ (gen_mul, gen_div): Removed.
+
+Thu May 7 14:49:38 1998 Bob Manson <manson@charmed.cygnus.com>
+
+ * config/sparc/tm-sp64.h (CALL_DUMMY): Store and retrieve
+ %o0-%o5 as 64-bit values; compensate for stack bias.
+ (USE_STRUCT_CONVENTION): We only pass pointers to structs
+ if they're larger than 32 bytes.
+ (REG_STRUCT_HAS_ADDR): Ditto.
+
+ * sparc-tdep.c (sparc_init_extra_frame_info): Use read_sp()
+ instead of read_register. If the target is a sparc64 and the frame
+ pointer is odd, compensate for the stack bias.
+ (get_saved_register): Use read_sp().
+ (DUMMY_STACK_REG_BUF_SIZE): Use FP_REGISTER_BYTES.
+ (sparc_push_dummy_frame): Use read_sp()/write_sp(). On sparc64,
+ save the PC, NPC, CCR, FSR, FPRS, Y and ASI registers.
+ (sparc_frame_find_saved_regs): Use read_sp(). Read the PC, NPC,
+ CCR, FSR, FPRS, Y and ASI registers from the frame, if it's a
+ dummy frame.
+ (sparc_pop_frame): Use write_sp(). If the target is a sparc64 and
+ the FP is odd, compensate for stack bias.
+ (sparc_store_return_value): Right-justify the return value before
+ writing it to %o0.
+ (sparc_fix_call_dummy): Don't NOP out part of the call dummy on
+ sparc64.
+ (sparc64_read_sp, sparc64_read_fp, sparc64_write_sp,
+ sparc64_write_fp, sp64_push_arguments,
+ sparc64_extract_return_value): New functions to support the
+ sparc64 ABI.
+
+ * dwarfread.c (handle_producer): Set processing_gcc_compilation to
+ the right version number.
+
+ * dwarf2read.c (read_file_scope): Assume we're processing
+ GCC2 output.
+
+Wed May 6 16:34:03 1998 Jeffrey A Law (law@cygnus.com)
+
+ * somsolib.c: Include gdb_stat.h.
+
+Mon May 4 18:34:01 1998 David Taylor <taylor@texas.cygnus.com>
+
+ * ax-gdb.c (gen_mul): new function; (gen_div): new function;
+ (gen_expr): add support for * and / operators, call gen_mul and
+ gen_div as appropriate.
+
+Mon May 4 16:24:22 1998 Mark Alexander <marka@cygnus.com>
+
+ * defs.h (make_run_cleanup): Declare.
+ * solib.c (find_solib): Pass correct number of arguments to
+ make_run_cleanup.
+
+Mon May 4 07:08:25 1998 Michael Snyder <msnyder@cleaver.cygnus.com>
+
+ * tracepoint.c (trace_actions_command): actions command must set
+ step_count to zero (in case previous actions have set it but the
+ new set does not).
+
+Sat May 2 09:35:07 1998 Stu Grossman <grossman@babylon-5.cygnus.com>
+
+ * ocd.h: Add new flags, function codes, and processor types to
+ support new Wiggler capabilities.
+ * (ocd_write_bytes_size): New function to allow atomic writes of
+ memory in sizes larger than a byte.
+
+ * ser-unix.c (baudtab): Add 57600, 115200, 230400, and 460800 baud.
+
+Fri May 1 19:51:32 1998 Frank Ch. Eigler <fche@cygnus.com>
+
+ * stabsread.c (read_one_struct_field): Do not override supplied
+ bitfield size for a range type value.
+
+ * gdbtypes.c (create_range_type): For a range with positive
+ lower limit, declare range type as unsigned.
+
+Fri May 1 10:58:34 1998 John Metzler <jmetzler@cygnus.com>
+
+ * monitor.c: Turn off debug
+
+Fri May 1 09:29:56 1998 Peter Schauer <pes@regent.e-technik.tu-muenchen.de>
+
+ * breakpoint.c (delete_command): Skip internal breakpoints when
+ all breakpoints are requested.
+
+ * stabsread.c (define_symbol): Record parameter types from Sunpro
+ function stabs in the TYPE_FIELDS of the function type.
+
+Thu Apr 30 15:59:54 1998 Jason Molenda (crash@bugshack.cygnus.com)
+
+ * Makefile.in (config-check-targets, config-check-hosts): Removed.
+
+1998-04-30 Paul Eggert <eggert@twinsun.com>
+
+ * Makefile.in (maintainer-clean):
+ Don't get ahead of yourself and delete Makefile
+ before running `make'.
+ (local-maintainer-clean, do-maintainer-clean): New rules.
+
+Wed Apr 29 14:02:59 1998 David Taylor <taylor@texas.cygnus.com>
+
+ * ax-gdb.c (gen_add): when adding a pointer and an int, use
+ the size of the pointer, not the int (typo) to decide how
+ to extend the result.
+
+Wed Apr 29 10:20:40 1998 John Metzler <jmetzler@cygnus.com>
+
+ * monitor.h: Defined additional hooks for dmpregs, configure_hooks
+ and wait_filter. These additions require that all ROM monitor
+ interfaces be recoded to initialize monitor ops using assignments
+ rather than static structure initialization. Added new bits to
+ flags MO_EXACT_DUMPADDR, MO_HAS_BLOCKWRITES.
+
+ * monitor.c (RDEBUG): Conditional tracing throughout the file.
+ (fromhex): Now recognized upper cse hex digits
+ (monitor_printf_noecho):
+ (monitor_readchar): Tracing interferes with input timing.
+ (monitor_open): Register different memory write functions with
+ dcache_init if MO_HAS_BLOCKWRITES.
+ (flush_monior_dcache): Added as an additional utilty.
+ (monitor-resume): Call continue hook if one has been supplied.
+ (monitor_wait_filter): New function Factored out of monitor wait
+ and used if alternate wait-filter has not been provided.
+ (monitor_wait): call alternate wait filter if provided. Call
+ monitor_dump_regs, a new function factored out from inline code.
+ (monitor_dump_block): A new function used as a utility when
+ monitors must dump several blocks of registers using different
+ commands.
+ (monitor_dump_regs): Call alternate function if provided. Uses new
+ hook in monitor.h.
+ (monitor_write_memory): Engage previouly added hook
+ MO_FILL_USES_ADDR.
+ (monitor_write_even_block): new function supports writing long
+ blocks of 4byte words.
+ (longlongendswap): new internal function
+ (monitor_write_memory_longlongs): new function writes large blocks
+ using command to enter a long long.
+ (monitor_write-memory_block): new Function figures out which block
+ mod to use.
+ (monitor_read_memory): Can now handle dump formats in which the bytes
+ preceeding the requested data is not printed.
+
+Tue Apr 28 19:41:33 1998 Tom Tromey <tromey@cygnus.com>
+
+ * tracepoint.c (memrange_cmp): Another typo fix; `memrbnge' ->
+ `memrange'.
+
+ * tracepoint.c (memrange_cmp): Fixed typo in function intro.
+
+Tue Apr 28 17:41:20 1998 Philippe De Muyter <phdm@macqel.be>
+
+ * symfile.c (overlay_auto_command): Add forgotten parameter
+ definitions.
+ (overlay_manual_command, overlay_off_command): Likewise.
+ (overlay_load_command): Likewise.
+ * tracepoint.c (memrange_cmp): Parameters have type void *, not
+ struct memrange *.
+
+Tue Apr 28 11:08:25 1998 John Metzler <jmetzler@cygnus.com>
+
+ * rom68k-rom.c (_initialize_rom68k): Fix unresolved init_rom_68kcmds.
+
+Mon Apr 27 14:32:21 1998 Mark Alexander <marka@cygnus.com>
+
+ * config/sparc/tm-sparc.h (CALL_DUMMY): Shorten it drastically,
+ make it work on the simulator.
+ (FIX_CALL_DUMMY): Convert to function call instead of inline code.
+ (sparc_fix_call_dummy): Declare.
+ * sparc-tdep.c (sparc_fix_call_dummy): New function, taken from
+ old FIX_CALL_DUMMY macro, with additional fixes for simulator.
+ (sparc_push_dummy_frame): Set registers differently on simulator
+ to prevent corrupted register window save areas.
+
+Mon Apr 27 13:46:40 1998 John Metzler <jmetzler@cygnus.com>
+
+ * rom68k-rom.c (_initialize_rom68k, init_rom68k_cmds):
+ Convert all static initializations of monitor ops structures to
+ executable initializations in order that additions to the data
+ structure definition can me made without repeating this editing
+ exercise.
+ * abug-rom.c (_initialize_abug_rom, init_abug-cmds): Ditto.
+ * cpu32bug-rom.c (_initialize_cpu32bug_rom, init_cpu32bug_cmds): Ditto.
+ * mon960-rom.c (initialize_mon960, init_mon960_cmds): Ditto.
+ * op50-rom.c (initialize_op50n, init_op50n_cmds): Ditto.
+ * ppcbug-rom.c (_initialize_ppcbug_rom, init_ppc_cmds): Ditto.
+ * sh3-rom.c (_initialize_sh3_rom, init_sh3_cmds): Ditto.
+ * sparclet-rom.c (_initialize_sparclet, init_sparclet_cmds): Ditto.
+ * remote-est.c (_initialize_est, init_est_cmds): Ditto.
+ * remote-hms.c ( _initialize_remote_hms, init_hms_cmds): Ditto.
+
+Mon Apr 27 10:43:04 1998 Jason Molenda (crash@bugshack.cygnus.com)
+
+ * gdb_string.h (strdup): Don't specify arguments in prototype.
+
+Sun Apr 26 07:57:21 1998 Peter Schauer <pes@regent.e-technik.tu-muenchen.de>
+
+ * rs6000-nat.c (vmap_ldinfo): Issue warning instead of error if
+ fstat on ldinfo_fd fails. Use objfile->obfd instead of vp->bfd
+ to check for reference to the same file.
+
+ * target.c (target_read_string): Handle string transfers at the
+ end of a memory section gracefully.
+
+Fri Apr 24 17:18:56 1998 Geoffrey Noer <noer@cygnus.com>
+
+ * Makefile.in: enable EXEEXT setting
+
+Fri Apr 24 11:53:49 1998 David Taylor <taylor@texas.cygnus.com>
+
+ * tracepoint.c (add_local_symbols): change type of type from
+ char to int so that type shows up as 'A' or 'L' not 0.
+
+Thu Apr 23 16:37:20 1998 Jason Molenda (crash@bugshack.cygnus.com)
+
+ * README: Minor changes for 4.17 release.
+
+Thu Apr 23 15:44:39 1998 Per Bothner <bothner@cygnus.com>
+
+ * symfile.c (deduce_language_from_filename): .class implies java.
+
+Thu Apr 23 12:52:21 1998 Philippe De Muyter <phdm@macqel.be>
+
+ * configure.in (strerror): Check if function must be declared.
+ * acconfig.h (NEED_DECLARATION_STRERROR): New define slot.
+ * gdb_string.h (strerror): Function declaration issued if
+ NEED_DECLARATION_STRERROR.
+ * configure, config.in: Files regenerated.
+
+Thu Apr 23 12:27:43 1998 Philippe De Muyter <phdm@macqel.be>
+
+ * symfile.c (simple_overlay_update_1): Do not prefix array address
+ by `&'.
+ * bcache.h (BCACHE_DATA_ALIGNMENT): Ditto.
+ * tracepoint.c (encode_actions): Ditto.
+ * language.c, complaints.c, utils.c (varargs.h): Do not include that
+ file here, it is already included indirectly by defs.h.
+ * dbxread.c (dbx_symfile_init, process_one_symbol): Cast xmalloc return
+ value to the appropriate pointer type.
+ * utils.c (floatformat_from_doublest): Ditto.
+ * tracepoint.c (read_actions, _initialize_tracepoint): Ditto.
+ (add_memrange): Likewise with xrealloc return value.
+ * stabsread.c (ref_add): Ditto.
+ * coffread.c (coff_symfile_init): Likewise for xmmalloc return value.
+ * elfread.c (elf_symfile_read): Ditto.
+ * os9kread.c (os9k_symfile_init): Ditto.
+
+Thu Apr 23 00:32:08 1998 Tom Tromey <tromey@cygnus.com>
+
+ * config.in: Rebuilt.
+ * acconfig.h (ENABLE_NLS, HAVE_CATGETS, HAVE_STPCPY, HAVE_GETTEXT,
+ HAVE_LC_MESSAGES): Define.
+
+Wed Apr 22 15:38:56 1998 Tom Tromey <tromey@cygnus.com>
+
+ * configure: Rebuilt.
+ * configure.in: Call CY_GNU_GETTEXT.
+ * Makefile.in (top_builddir): New macro.
+ (INTL): Define to @INTLLIBS@.
+ (INTL_DEPS): New macro.
+ (CDEPS): Reference INTL_DEPS, not INTL.
+
+Wed Apr 22 12:58:23 1998 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ Handle missing shared libraries during the examination of a core
+ dump gracefully.
+ * solib.c (find_solib): Use catch_errors around call to
+ solib_map_sections. Use warning instead of error if reading of
+ the shared library name fails.
+ (solib_map_sections): Change return and argument types to make
+ it callable from catch_errors.
+ (symbol_add_stub): Avoid GDB core dump if solib->abfd is NULL.
+ * irix5-nat.c, osfsolib.c (xfer_link_map_member, solib_map_sections,
+ symbol_add_stub): Ditto.
+
+Wed Apr 22 14:34:49 1998 Michael Meissner <meissner@cygnus.com>
+
+ * Makefile.in (INTL*): Add support to link in the intl library,
+ and to add -I options to its source and object directories.
+ (INTERNAL_CFLAGS): Ditto.
+ (C{LIBS,DEPS}): Ditto.
+
+Tue Apr 21 11:20:54 1998 Frank Ch. Eigler <fche@cygnus.com>
+
+ * mips-tdep.c (gdb_print_insn_mips): Disassemble MIPS instructions
+ with subtarget-specific `mach', rather than fixed default.
+ * config/mips/tm-mips.h (TM_PRINT_INSN_MACH): New macro, default
+ disassembly `mach'.
+
+Mon Apr 20 15:35:03 1998 Philippe De Muyter <phdm@macqel.be>
+
+ * coffread.c (decode_base_type): Treat a long field with size greater
+ than TARGET_LONG_BIT as long long.
+ * values.c (value_from_longest): Print code value in error message.
+
+Mon Apr 20 15:32:21 1998 Mark Kettenis <kettenis@phys.uva.nl>
+
+ * gdb/gdb_string.h (strdup): Declare only if not defined as a
+ macro.
+
+Mon Apr 20 14:18:45 1998 J. Kean Johnston <jkj@sco.com>
+
+ * procfs.c: Added replacement macros for LWP stuff. Fixed support
+ for UnixWare / SVR4.2MP targets and any targets which use
+ multi-file /proc entries. Fixed support for hardware watchpoints.
+ * solib.c: SCO needs some of the same code as SunOS. Change
+ preprocessor conditionals.
+
+ * config/i386/i386sco5.mt: New file.
+ * config/i386/tm-i386sco5.h: New file.
+ * config/i386/i386sco5.mh (NATDEPFILES): add i386v-nat.o.
+ * config/i386/nm-i386v42mp.h
+ (TARGET_HAS_HARDWARE_WATCHPOINTS): define.
+ Add other macros for hardware assisted watchpoints.
+ * config/i386/nm-i386sco5.h: Correct attributions.
+ (TARGET_HAS_HARDWARE_WATCHPOINTS): define.
+ * config/i386/nm-linux.h (target_remote_watchpoint): Pass
+ 'type' through to i386_insert_watchpoint.
+
+Mon Apr 20 14:12:30 1998 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * infrun.c (wait_for_inferior): Don't add signalled processes
+ as new threads.
+ * procfs.c (wait_fd): Note if LWP has exited.
+ (procfs_wait): use GETPID to get process ID.
+
+Sat Apr 18 15:21:04 1998 Stan Cox <scox@cygnus.com>
+
+ * configure.tgt: Added sparc86x support.
+
+Thu Apr 16 13:13:24 1998 Jason Molenda (crash@bugshack.cygnus.com)
+
+ * rdi-share/etherdrv.c (EthernetWrite): Use strerror to get
+ error string if in an ANSI C-ish environment.
+
+Wed Apr 15 18:59:48 1998 Mark Alexander <marka@cygnus.com>
+
+ * sparc-tdep.c (SPARC_HAS_FPU): Define.
+ (sparc_extract_return_value): New function, required to handle
+ machines without floating point.
+ (sparc_store_return_value): Ditto.
+ * config/sparc/tm-sparc.h (EXTRACT_RETURN_VALUE): Call
+ sparc_extract_return_value instead of using inline code.
+ (sparc_extract_return_value): Declare.
+ (STORE_RETURN_VALUE): Call sparc_store_return_value instead
+ of using inline code.
+ (sparc_store_return_value): Declare.
+
+Wed Apr 15 12:19:42 1998 Martin M. Hunt <hunt@cygnus.com>
+
+ * solib.c (enable_break): Only call warning once
+ instead of three times.
+
+Tue Apr 14 16:52:59 1998 Mark Alexander <marka@cygnus.com>
+
+ * sparc-tdep.c (sparc_extract_struct_value_address): Make it
+ work correctly on little-endian hosts.
+ (sparc_push_arguments): New function.
+ (gdb_print_insn_sparc): New function.
+ (_initialize_sparc_tdep): Make gdb_print_insn_sparc the default
+ disassembler, so that SPARClite-specific instructions will
+ be recognized.
+ * sparcl-tdep.c (readchar): Print debugging information.
+ (debug_serial_write): New function, a replacement for SERIAL_WRITE
+ that prints debugging information.
+ * config/sparc/tm-sparc.h (PUSH_ARGUMENTS): Define.
+ (sparc_push_arguments): Declare.
+
+Tue Apr 14 15:43:49 1998 John Metzler <jmetzler@cygnus.com>
+
+ * gdbcfgxref (xref_menu): Call new regex and wild card searches
+ Now you can type in a specific triple like mips64-vr4300-elf or
+ somthing like mips*.h
+ (triple_search, wildcardsearch): The new functions
+
+Mon Apr 13 16:28:07 1998 Elena Zannoni <ezannoni@kwikemart.cygnus.com>
+
+ * utils.c (warning): added call to warning_hook
+
+ * source.c (find_source_lines): modified to call warning in case
+ of source vs. executable time stamp mismatch. Simplified object
+ file check. Initialized mtime to 0.
+
+ * defs.h: added warning_hook prototype
+
+ * top.c: added warning_hook prototype.
+
+Mon Apr 13 09:54:08 1998 Keith Seitz <keiths@andros.cygnus.com>
+
+ * config/sparc/tm-sun4os4.h (IS_STATIC_TRANSFORM_NAME): Add missing
+ definition.
+
+Fri Apr 10 22:36:28 1998 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ Update support for x86 Solaris 2.
+ * config/i386/tm-i386sol2.h, nm-i386sol2.h: New configuration
+ files for x86 Solaris 2.
+ * config/i386/i386sol2.mt, i386sol2.mh: Use them.
+ * config/sparc/tm-sun4sol2.h (PROCFS_GET_CARRY): New macro, extract
+ carry flag from a given regset.
+ (IS_STATIC_TRANSFORM_NAME): New macro, check if a symbol name
+ is a SunPro transformed name.
+ * i386-tdep.c (sunpro_static_transform_name): New function to
+ extract the source name from a SunPro transformed name.
+ * inferior.h (procfs_first_available, procfs_get_pid_fd):
+ Add prototypes.
+ * infrun.c (wait_for_inferior): Handle breakpoint hit in
+ signal handler without intervening stop in sigtramp.
+ * procfs.c (procfs_lwp_creation_handler): Use PROCFS_GET_CARRY
+ instead of direct access to the status register.
+ (procfs_get_pid_fd): New function, returns procfs fd for a given pid.
+ * sol-thread.c (ps_lgetLDT): New function, returns LDT for a given
+ lwpid.
+ (sol_find_new_threads): Handle failed libthread_db initialization
+ gracefully.
+ * stabsread.c (define_symbol): Use IS_STATIC_TRANSFORM_NAME
+ to check for a SunPro transformed symbol name.
+
+Fri Apr 10 10:35:35 1998 John Metzler <jmetzler@cygnus.com>
+
+ * utils.c (fmthex): A formatting function for hexdumps
+
+ * mips-tdep.c (unpack_mips16): Fixed instruction decoding, lots of
+ bit pattern interpretations. mips_fetch_instruction does not work
+ for 16 bit instructions. Some confusion remains about sign
+ extension in backward branches.
+ (mips32_relative_offset): Sign extension
+ (mips32_next_pc): Major debugging, bit pattern interpretation
+ (print_unpack): debugging printf
+ (fetch_mips_16): new funtion, key on PC low bit, not symbol table
+ (mips16_next_16): Initial major debugging of this function. Lots
+ of bit pattern mistakes.
+ (mips_next_pc): key on low bit of PC, not symbol table.
+ * symfile.c (generic_load): Added a download verification which
+ reads back the loaded code. Download chunk size is now a defined
+ macro. Fixed a bug in which downloading slips into loading one
+ byte at a time. Lower level functions in monitor.c can load long
+ sequences of bytes and make use of these fixups. Referencing
+ bfd-start_address directly was incorrectly getting zero for start.
+
+Thu Apr 9 19:20:32 1998 Ian Lance Taylor <ian@cygnus.com>
+
+ * mips-tdep.c (do_fp_register_row): Use alloca rather than arrays
+ with dynamic size.
+
+Wed Apr 8 19:21:42 1998 Jason Molenda (crash@bugshack.cygnus.com)
+
+ * top.c (print_gdb_version): Print 1998 now.
+
+Wed Apr 8 16:57:22 1998 Philippe De Muyter <phdm@macqel.be>
+
+ * source.c: Remove obsolete decl of strstr().
+
+Wed Apr 8 16:47:33 1998 Jason Molenda (crash@bugshack.cygnus.com)
+
+ * solib.c (solib_create_inferior_hook): Remove Ulrich Drepper's
+ patch of March 23 1998.
+ * breakpoint.c (breakpoint_re_set_one): Remove Ulrich Drepper's
+ patch of March 23 1998.
+
+Sat Apr 4 10:05:00 1998 Dawn Perchik <dawn@cygnus.com>
+
+ * mdebugread.c (parse_partial_symbols): If this is an .mdebug
+ section in an ELF file, override a symbol's ECOFF section with its
+ ELF section. Also, fix stabs continuation where a stabs string
+ continues for more than one continuation.
+
+Mon Apr 6 09:17:48 1998 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * mips-tdep.c (mips_push_arguments): Specify dimention of valbuf
+ using MAX_REGISTER_RAW_SIZE.
+
+Sat Apr 4 10:05:00 1998 Dawn Perchik <dawn@cygnus.com>
+
+ * infrun.c: Fix prototype of signals_info to match static funtion.
+
+Thu Apr 2 12:47:41 1998 Frank Ch. Eigler <fche@cygnus.com>
+
+ * sol-thread.c (sol_thread_store_registers): Save & restore new
+ value of single updated register to prevent accidental clobbering.
+
+Wed Apr 1 22:01:09 1998 Mark Alexander <marka@cygnus.com>
+
+ * config/sparc/tm-sparclite.h (TARGET_BYTE_ORDER_SELECTABLE): Define.
+ * config/sparc/sparclite.mt: Link in the erc32 simulator.
+
+Wed Apr 1 16:30:49 1998 Ian Dall <Ian.Dall@dsto.defence.gov.au>
+
+ * ns32k-tdep.c (flip_bytes, ns32k_localcount,
+ ns32k_get_enter_addr, sign_extend): Restore functions mysteriously
+ deleted.
+
+ * ns32knbsd-nat.c: New (?) file to support fetching and storing
+ registers on NetBSD hosts.
+
+ * nbsd.mh (NATDEPFILES): put ns32knbsd-nat.o instead of
+ ns32k-nat.o
+
+ * ns32km3-nat.c (reg_offset): Get order of floating point
+ registers correct. Add extra 32382 register offsets.
+ (REG_ADDRESS): define to point at correct part of thread
+ state. Use calls to "warning" instead of "message".
+
+ * tm-nbsd.h, tm-ns32km3.h (REGISTER_NAMES, NUM_REGS,
+ REGISTER_BYTES, REGISTER_BYTE): redefine allowing for 32382
+ fpu registers.
+
+Wed Apr 1 13:43:07 1998 Philippe De Muyter <phdm@macqel.be>
+
+ * NEWS: m68k-motorola-sysv host support added.
+ * coffread.c (coff_start_symtab): Accept the filename as an argument,
+ set it here. Callers updated.
+
+Wed Apr 1 23:13:23 1998 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * config/mips/tm-mips.h (REGISTER_VIRTUAL_TYPE): Handle 32 bit SR,
+ FSR and FIR registers.
+ (REGISTER_VIRTUAL_SIZE): Compute using REGISTER_VIRTUAL_TYPE.
+ (REGISTER_RAW_SIZE): Define using REGISTER_VIRTUAL_SIZE.
+
+ * config/mips/tm-mips64.h: Ditto.
+
+Tue Mar 31 21:30:39 1998 Nick Clifton <nickc@cygnus.com>
+
+ * arm-tdep.c (gdb_print_insn_arm): Attach a fake Thumb symbol
+ vector to the info structure when disassembling thumb
+ instructions.
+
+ * coffread.c (coff_symtab_read, read_one_sym,
+ process_coff_symbol): Support Thumb symbol types.
+
+ * dbxread.c (process_one_symbol): Call SMASH_TEXT_ADDRESS (if it
+ is defined) for function symbols.
+
+Tue Mar 31 16:39:28 1998 Michael Snyder <msnyder@cleaver.cygnus.com>
+
+ * tracepoint.c (get_tracepoint_by_number): change warning to note.
+ (delete_trace_command): suppress y/n query if no tracepoints, or
+ if not from_tty. (trace_pass_command): reject junk at end of args.
+ (read_actions): an action list consisting only of "end" is discarded.
+ (validate_actionline (for collect command)): an argument beginning
+ with a dollar_sign but not recognized as a special argument is
+ parsed like any other expression -- if it isn't a register name,
+ it's rejected. Also reject an empty argument to while-stepping.
+ (trace_find_command): reject a negative frame number argument.
+ (_initialize_tracepoint): set $traceframe initially to -1.
+
+Mon Mar 30 16:42:12 1998 Jason Molenda (crash@bugshack.cygnus.com)
+
+ * rdi-share/Makefile.am, rdi-share/aclocal.m4,
+ rdi-share/configure: New files.
+ * rdi-share/configure.in: Rewritten to be an autoconf input file.
+ * rdi-share/Makefile.in, rdi-share/configure: Generated by
+ automake/autoconf.
+ * rdi-share/dbg_hif.h, etherdrv.c, hostchan.c: Use autoconf tests
+ to check environment.
+
+Sun Mar 29 15:17:16 1998 Keith Seitz <keiths@onions.cygnus.com>
+
+ * tracepoint.c (trace_start_command): Set trace_running_p.
+ (trace_stop_command): Clear trace_running_p.
+
+Sat Mar 28 15:19:48 1998 Stan Shebs <shebs@andros.cygnus.com>
+
+ * NEWS: Update for 4.17 release.
+
+Fri Mar 27 10:15:50 1998 David Taylor <taylor@tito.cygnus.com>
+
+ * tracepoint.c (parse_and_eval_memrange): Fix memory leaks.
+ (encode_actions): Use the new gen_trace_for_expr function
+ instead of expr_to_address_and_size; collect registers when
+ using expressions. (clear_collection_list): Fix memory leak.
+
+1998-03-26 Jim Blandy <jimb@zwingli.cygnus.com>
+
+ * ax-gdb.h (gen_trace_for_expr): Add prototype.
+
+Thu Mar 26 17:24:23 1998 David Taylor <taylor@texas.cygnus.com>
+
+ * tracepoint.c (validate_actionline): Fix memory leak.
+ (encode_actions): Fix memory leak.
+
+Thu Mar 26 16:16:55 1998 David Taylor <taylor@tito.cygnus.com>
+
+ * tracepoint.c (trace_mention): New function.
+ (trace_command): Call it.
+
+1998-03-26 Jim Blandy <jimb@zwingli.cygnus.com>
+
+ * ax-general.c (ax_reqs): New function.
+ * ax.h (enum agent_flaws, struct agent_reqs): New types.
+ (agent_reqs): New extern prototype. Well, actually, this was
+ there before, due to a premature checkin.
+ (struct aop_map): Add new `data_size' member.
+ * ax-general.c (aop_map): Supply its value.
+ * ax-gdb.c (agent_command): Call ax_reqs, for testing.
+
+ * ax-general.c (ax_print): If we encounter an invalid or
+ incomplete opcode, don't abort; just print an error message.
+
+ * ax-gdb.c: Generate trace bytecodes, as appropriate.
+ (trace_kludge): New variable.
+ (gen_fetch, gen_bitfield_ref): Emit trace bytecodes, if asked
+ nicely.
+ (expr_to_agent): Ask for no trace bytecodes.
+ (gen_trace_for_expr): New function.
+ (agent_command): Call it, and display the result appropriately ---
+ no struct axs_value, so no type or kind information.
+
+ * ax-gdb.c: Use TARGET_CHAR_BIT throughout, not HOST_CHAR_BIT.
+
+Thu Mar 26 22:29:28 1998 Elena Zannoni <ezannoni@kwikemart.cygnus.com>
+
+ * tracepoint.c (trace_status_command): Recognize a boolean return
+ value from the stub to indicate whether trace experiment is
+ running. Export this value as a global state variable.
+ (trace_running_p) for use by the GUI. (from Michael Snyder)
+ (trace_pass_command) added call to modify_tracepoint_hook.
+
+ * tracepoint.h export trace_running_p.
+
+Thu Mar 26 13:08:01 1998 David Taylor <taylor@texas.cygnus.com>
+
+ * tracepoint.c (validate_actionline): do not error out if
+ exp->elts[0].opcode is not on short line -- let
+ expr_to_address_and_size handle it.
+
+1998-03-26 Jim Blandy <jimb@zwingli.cygnus.com>
+
+ * tracepoint.c: Include "ax.h", not "agentexpr.h".
+
+ * tracepoint.c (encode_actions): Call expr_to_address_and_size,
+ not simply expr_to_agent.
+
+ * ax-general.c: Comment out code in progress, so everyone else can
+ at least compile.
+
+ * gdbtypes.c: Doc fix.
+
+ * ax.h, ax-gdb.h, ax-general.c, ax-gdb.c: New files.
+ * Makefile.in (REMOTE_OBJS): Add ax-general.o and ax-gdb.o.
+ (SFILES): Add ax-general.c, ax-gdb.c.
+ (ax_h): New variable.
+ (ax-general.o, ax-gdb.o): New rules.
+
+
+Tue Mar 24 16:22:40 1998 Stu Grossman <grossman@bhuna.cygnus.co.uk>
+
+ * Makefile.in: Derive SHELL from configure.
+ * config/d10v/d10v.mt config/m32r/m32r.mt
+ config/mn10200/mn10200.mt config/mn10300/mn10300.mt
+ config/d30v/d30v.mt: Remove -lm from SIM. This prevents
+ dependency checking of -lm (under NT native builds). (It is
+ automatically added by configure if it exists.)
+ * doc/configure mswin/configure nlm/configure
+ testsuite/gdb.base/configure testsuite/gdb.c++/configure
+ testsuite/gdb.chill/configure testsuite/gdb.disasm/configure
+ testsuite/gdb.stabs/configure testsuite/gdb.threads/configure:
+ Regenerate with autoconf 2.12.1 to fix shell issues for NT native
+ builds.
+
+Mon Mar 23 18:10:57 1998 Ulrich Drepper (drepper@cygnus.com)
+
+ * solib.c (solib_create_inferior_hook): Rewrite previous
+ change to check the type of file via BFD.
+
+Mon Mar 23 13:52:28 1998 Ulrich Drepper (drepper@cygnus.com)
+
+ * breakpoint.c (breakpoint_re_set_one): Treat bp_shlib_events
+ like bp_breakpoints.
+ * solib.c (solib_create_inferior_hook): Relocate section addresses
+ if the alleged start address doesn't agree with the PC.
+
+Sat Mar 21 19:34:49 1998 Elena Zannoni <ezannoni@kwikemart.cygnus.com>
+
+ merged changes from Foundry (list follows by file/author):
+
+ - Tom Tromey <tromey@cygnus.com>
+ * Makefile.in (gdbres.o): New target.
+ (WINDRES): New define.
+ * configure: Rebuilt.
+ * configure.in (WINDRES): Define.
+ (CONFIG_OBS): Include gdbres.o on Windows.
+ * gdbtool.ico: New file.
+ * gdb.rc: New file.
+
+ * ser-unix.c
+ - Keith Seitz <keiths@onions.cygnus.com>
+ (wait_for): Don't reset the timeout_remaining for CYGWIN32,
+ since we now effectively poll the serial port.
+ Don't reset the current_timeout, either, since this member is used
+ by hardwire_readchar to track the timeout and call the ui_loop_hook.
+ (hardwire_readchar): Poll the serial port for Cygwin32. We timeout
+ every second, update the UI, and loop around doing this until we
+ have hit the real timeout or we get data or an error. This will
+ allow the UI to stay active while gdb is "blocked" talking to the
+ target.
+ - Martin M. Hunt <hunt@cygnus.com>
+ (wait_for): Do reset current_timeout because it is only used to
+ keep track of what the current timeout for the scb is.
+
+ * top.c
+ - Martin M. Hunt <hunt@cygnus.com>
+ (quit_confirm): Change exit message again
+ for GUI.
+ (pc_changed_hook): Add prototype.
+ - Tom Tromey <tromey@cygnus.com>
+ (quit_confirm): Added missing `else'.
+ (quit_confirm): Special-case message if init_ui_hook is
+ set.
+
+ * symtab.c
+ - Martin M. Hunt <hunt@cygnus.com>
+ (find_pc_sect_line): If no symbol information
+ is found, return correct pc anyway.
+ (find_methods): Comment out an apparently
+ bogus error message because it messes up Foundry.
+
+ * serial.c
+ - Martin M. Hunt <hunt@cygnus.com>
+ (_initialize_serial): Add a description of
+ "set remotelogbase".
+
+ * findvar.c
+ - Martin M. Hunt <hunt@cygnus.com>
+ (write_register_gen): Add call to
+ pc_changed_hook if the PC is being changed.
+
+ * defs.h
+ - Martin M. Hunt <hunt@cygnus.com>
+ (pc_changed_hook): Define.
+
+ * command.c
+ - Martin M. Hunt <hunt@cygnus.com>
+ (do_setshow_command): If no arguments are supplied,
+ don't dump core, instead print out an error message.
+
+ * breakpoint.c
+ - Martin M. Hunt <hunt@cygnus.com>
+ Make set_raw_breakpoint, set_breakpoint_count,
+ and breakpoint_count non-static so they are accessible from
+ elsewhere.
+ (enable_breakpoint): Enable breakpoint
+ with same disposition instead of changing all breakpoints
+ to donttouch.
+
+ * annotate.h
+ - Keith Seitz <keiths@onions.cygnus.com>
+ Add declarations for annotation hooks.
+
+ * annotate.c
+ - Keith Seitz <keiths@onions.cygnus.com>
+ Add hooks: annotate_starting_hook, annotate_stopped_hook,
+ annotate_signalled_hook, annotate_exited_hook.
+ (annotate_starting): If hook exists, call it instead.
+ (annotate_stopped): If hook exists, call it instead.
+ (annotate_exited): If hook exists, call it instead.
+ (annotate_signalled): If hook exists, call it instead.
+
+Fri Mar 20 14:45:36 1998 Michael Snyder <msnyder@cleaver.cygnus.com>
+
+ * gdbserver/Makefile.in: add dependency on XM_CLIBS.
+ * gdbserver/low-sim.c (registers) force into alignment.
+ (create_inferior): Fix typo on new_argv; add abfd arg to
+ sim_open, sim_create_inferior. Add reg_size arg to
+ sim_fetch_register, sim_store_register. Make simulator
+ take a single-step to get into a known running state.
+ * gdbserver/gdbreplay.c: include fcntl.h for def'n of F_SETFL.
+ * gdbserver/server.c: Add remote_debug variable to control
+ debug output.
+ * gdbserver/server.h: Add prototypes for enable/disable_async_io.
+ * gdbserver/remote-utils.c: add verbose debugging output controlled
+ by "remote_debug" variable. Add call to "disable_async_io()"
+ to avoid being killed by async SIGIO signals.
+ * config/m32r/m32r.mt: define GDBSERVER_(LIBS and DEPFILES),
+ so that gdbserver can be built with the m32r simulator.
+
+Fri Mar 20 09:04:06 1998 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * gdbtypes.h (builtin_type_{,u}int{8,16,32,64}): New gdb builtin
+ types.
+
+ * gdbtypes.c (_initialize_gdbtypes): Initialize new types.
+
+ * mips-tdep.c (do_gp_register_row): Pad register value when GP
+ register is smaller than MIPS_REGSIZE.
+
+ * findvar.c (value_of_register): When raw and virtual register
+ values identical, check that sizes are consistent.
+
+Thu Mar 19 11:32:15 1998 Michael Snyder (msnyder@cleaver.cygnus.com)
+
+ * minsyms.c (compare_minimal_symbols): If addresses are identical,
+ then compare on names. Sorted list should have symbols with
+ identical addresses AND names adjacent, so dups can be discarded.
+
+Wed Mar 18 12:50:17 1998 Jeff Law (law@cygnus.com)
+
+ * stabsread.c (define_symbol): Don't look for ',' as a LRS
+ indicator.
+
+Wed Mar 18 10:34:51 1998 Nick Clifton <nickc@cygnus.com>
+
+ * rdi-share/etherdrv.c: Set sys_errlist[] as char * not const char *.
+
+Fri Mar 13 15:43:53 1998 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * config/mips/xm-mips.h (CC_HAS_LONG_LONG): Undefine for Ultrix
+ when compiling with native cc, the compiler has broken long long
+ support.
+
+Fri Mar 13 15:37:02 1998 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * config/m68k/xm-sun3os4.h: Remove malloc declarations, they
+ are handled via autoconf now.
+ * remote.c (remote_ops, extended_remote_ops): Replace static
+ forward declaration by moving the static definition to the top of
+ the file, for old K&R compilers.
+ * tracepoint.c (collect_symbol, trace_start_command):
+ Replace ANSI string concatenation with K&R compatible simple string.
+
+1998-03-11 Fred Fish <fnf@ninemoons.com>
+
+ * source.c (select_source_symtab): Don't reach error if we have
+ a current_source_symtab from reading in partial symbol table.
+
+Fri Mar 6 13:10:27 1998 Fred Fish <fnf@cygnus.com>
+
+ * utils.c (quit): Call SERIAL_DRAIN_OUTPUT rather than
+ SERIAL_FLUSH_OUTPUT.
+ * serial.h (struct serial_ops): Add drain_output, pointer to
+ function that waits for output to drain.
+ (SERIAL_DRAIN_OUTPUT): Macro to wait for output to drain.
+ * ser-unix.c (hardwire_drain_output): New function and prototype.
+
+ * ser-unix.c (hardwire_ops): Add entry for drain_output function.
+ * ser-tcp.c (tcp_ops): Ditto.
+ * ser-ocd.c (ocd_ops): Ditto.
+ * ser-mac.c (mac_ops): Ditto.
+ * ser-go32.c (dos_ops): Ditto.
+ * ser-e7kpc.c (e7000pc_ops): Ditto.
+
+Thu Mar 5 16:07:41 1998 Michael Snyder (msnyder@cleaver.cygnus.com)
+
+ * sparcl-tdep.c: fix #endif comments
+
+Thu Mar 5 15:10:35 1998 Jason Molenda (crash@bugshack.cygnus.com)
+
+ * Makefile.in (BISON): Configure substitutes in @YACC@, not @BISON@.
+
+Thu Mar 5 14:42:41 1998 Keith Seitz <keiths@onions.cygnus.com>
+
+ * ocd.c (ocd_open): If we fail ocd_start_remote, make sure we
+ error () so that we abort out of bdm_ppc_open.
+
+Wed Mar 4 16:53:52 1998 Martin M. Hunt <hunt@cygnus.com>
+
+ * serial.c (_initialize_serial): Add a description of
+ "set remotelogbase".
+
+ * command.c (do_setshow_command): If no arguments are supplied,
+ don't dump core, instead print out an error message.
+
+Wed Mar 4 01:39:08 1998 Ron Unrau <runrau@cygnus.com>
+
+ * elfread.c (elf_symtab_read): merge SYMBOL_IS_SPECIAL into
+ MAKE_MSYMBOL_SPECIAL
+ * config/mips/tm-mips.h: ditto
+
+Tue Mar 3 17:19:08 1998 John Metzler <jmetzler@cygnus.com>
+
+ * dwarfread.c (read_tag_pointer_type): Pointer sizes now come from
+ TARGET_PTR_BIT rather from sizeof(char *) on host.
+
+Tue Mar 3 14:37:02 1998 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * alpha-nat.c (fetch_osf_core_registers): Renamed from
+ fetch_aout_core_registers.
+ (alpha_osf_core_fns): Renamed from alpha_aout_core_fns, change
+ flavour to bfd_target_unknown_flavour for OSF core files.
+
+Mon Mar 2 17:44:13 1998 Michael Snyder (msnyder@cleaver.cygnus.com)
+
+ * breakpoint.c (_initialize_breakpoint): Make "en" an alias
+ for "enable" (so that it doesn't conflict with "end").
+
+Mon Mar 2 17:04:25 1998 Jason Molenda (crash@bugshack.cygnus.com)
+
+ * Makefile (VERSION): Bump to 4.17.1.
+
+Mon Mar 2 16:59:15 1998 Jason Molenda (crash@bugshack.cygnus.com)
+
+ * rdi-share/etherdrv.c (sys_errlist): Add correct decl for Linux.
+
+Mon Mar 2 16:51:44 1998 Jason Molenda (crash@bugshack.cygnus.com)
+
+ * Makefile.in (YYFILES): Remove in maintainer-clean, not distclean.
+
+Mon Mar 2 16:47:11 1998 Philippe De Muyter <phdm@macqel.be>
+
+ * Makefile.in (distclean): Add `rm $(YYFILES)'.
+
+Mon Mar 2 16:45:48 1998 Philippe De Muyter <phdm@macqel.be>
+
+ * coffread.c (coff_read_enum_type): Set TYPE_FLAG_UNSIGNED if enum
+ is unsigned.
+
+Sun Mar 2 15:16:13 1998 Richard Henderson <rth@cygnus.com>
+
+ * configure.host, configure.tgt: Add sparc-linux.
+ * sparc-nat.c: Include <asm/reg.h> not <machine/reg.h> for Linux.
+ * config/sparc/*linux*: New files.
+
+Mon Mar 2 12:12:41 1998 Anthony Thompson (athompso@cambridge.arm.com)
+
+ * arm-tdep.c (gdb_print_insn_arm): Call print_insn_big_arm
+ if we're big endian; else call print_insn_little_arm.
+
+Mon Feb 24 11:24:57 1998 Richard Henderson <rth@cygnus.com>
+
+ * Makefile.in (BISON): Don't even pretend to use yacc.
+ (c-exp.tab.o): Use bison -o to use a unique intermediate file.
+ (f-exp.tab.o, m2-exp.tab.o): Likewise.
+ (jv-exp.tab.o): Likewise.
+
+Tue Feb 24 03:32:59 1998 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * remote-sim.c (gdbsim_fetch_register): Don't abort when the
+ register size is wrong.
+
+Thu Feb 19 16:49:48 1998 John Metzler <jmetzler@cygnus.com>
+
+ * target.c (debug_to_fetch_registers,debug_to_store_registers,
+ debug-to_insert_breakpoint,debug_to_remove_breakpoint): tracing
+ 64 bit targets crashed long long printfs.
+
+Tue Feb 17 16:36:22 1998 Michael Snyder (msnyder@cleaver.cygnus.com)
+
+ * symfile.c (read_target_int_array): rename read_target_long_array
+ and force the sizeof an ovly_table element to sizeof(long),
+ instead of sizeof(int).
+
+Tue Feb 17 18:05:05 1998 Frank Ch. Eigler <fche@cygnus.com>
+
+ * remote-mips.c (mips_request): Use unsigned long during parsing
+ returned value from monitor, to prevent accidental sign extension.
+
+Tue Feb 17 14:28:33 1998 Peter Schauer <pes@regent.e-technik.tu-muenchen.de>
+
+ * acconfig.h: FORCE_MMCHECK changed to MMCHECK_FORCE.
+ * configure.in: Ditto.
+ * configure: Regenerated.
+
+Tue Feb 17 14:07:34 1998 Peter Schauer <pes@regent.e-technik.tu-muenchen.de>
+
+ * gdbtypes.c (check_typedef): Do not try to resolve the length of
+ a type which has TYPE_FLAG_TARGET_STUB set, if the target type has
+ set TYPE_FLAG_TARGET_STUB as well.
+
+Tue Feb 17 14:32:18 1998 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * remote-sim.c (gdbsim_fetch_register, gdbsim_store_register):
+ Pass register size to sim_{fetch,store}_register. Check nr of
+ register bytes transfered is correct.
+
+Mon Feb 16 14:05:54 1998 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * remote-d10v.c (remote_d10v_open): Call push_remote_target
+ instead of open_remote_target.
+
+ * remote.c (remote_xfer_memory): Use REMOTE_TRANSLATE_XFER_ADDRESS
+ to translate addr/size when defined.
+ (open_remote_target): Delete.
+
+ * target.h (open_remote_target): Delete.
+
+ * config/d10v/tm-d10v.h (REMOTE_TRANSLATE_XFER_ADDRESS): Define.
+
+Mon Feb 16 14:05:54 1998 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * d10v-tdep.c (d10v_extract_return_value): Wierd. GCC wants to
+ return odd sized register quantities with only half of the first
+ register used!
+
+ * config/d10v/tm-d10v.h (USE_STRUCT_CONVENTION): Use stack when
+ size > 8.
+
+Mon Feb 16 14:05:54 1998 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * config/d10v/tm-d10v.h (USE_STRUCT_CONVENTION): Define. True when
+ sizeof type > 1.
+
+Sun Feb 15 16:10:50 1998 Ron Unrau <runrau@cygnus.com>
+
+ * parse.c (write_dollar_variable): call new function
+ target_map_name_to_register to allow targets to define their own
+ register name aliases.
+ * infcmd.c (registers_info): use target_map_name_to_register so that
+ "print $reg" and "info reg $reg" use the same register name aliases.
+
+Fri Feb 13 16:40:30 1998 Stan Shebs <shebs@andros.cygnus.com>
+
+ * config/i386/i386mk.mt (OBJFORMATS): Delete, no longer used.
+ * config/i386/xm-i386mk.h: Fix an include.
+ * config/pyr/tm-pyr.h (PC_INNER_THAN): Remove, never used.
+
+Thu Feb 12 16:12:07 1998 Frank Ch. Eigler <fche@cygnus.com>
+
+ * remote-mips.c (mips_enter_debug): Sleep before sending CR to
+ monitor.
+ (mips_exit_debug): Accept any whitespace / verbiage before monitor
+ prompt reappears.
+
+Thu Feb 12 18:25:42 1998 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * d10v-tdep.c (show_regs): Avoid use of %llx when printing 8 byte
+ accumulators.
+
+Thu Feb 12 17:10:22 1998 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * valops.c (value_at): For d10v, make read pointers with
+ read_target_unsigned_integer, keep addresses unsigned.
+ (value_fetch_lazy): Ditto.
+
+Thu Feb 12 12:14:02 1998 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * remote-d10v.c: New file. Layer the d10v GDB->remote memory map
+ on top of the remote serial memory transfer functions.
+
+ * config/d10v/d10v.mt (TDEPFILES): Add remote-d10v.o
+
+ * Makefile.in (remote-d10v.o): Add dependencies.
+
+ * remote.c (remote_open_1): Add arg extended_p, engage extended
+ protocol when extended_p.
+ (remote_open, extended_remote_open): Pass !extended_p /
+ extended_p to remote_open_1.
+
+ * remote.c (open_remote_target), target.h: New function.
+
+Wed Feb 11 08:41:15 1998 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * config/i386/fbsd.mh (XDEPFILES): Add ser-tcp.o.
+
+Tue Feb 10 17:50:37 1998 Keith Seitz <keiths@onions.cygnus.com>
+
+ * tracepoint.c (tracepoint_operation): Call the modify_tracepoint_hook
+ if it exists.
+ Remove static declaration of free_actions.
+
+ * tracepoint.h: Add declaration of free_actions.
+
+Tue Feb 10 12:17:13 1998 Fred Fish <fnf@cygnus.com>
+
+ * symtab.c (decode_line_1): Revert change that mistakenly
+ removed assignment of sals[0].pc field.
+
+Mon Feb 10 12:37:47 1998 Philippe De Muyter <phdm@macqel.be>
+
+ * m68k/tm-delta68.h (EXTRACT_RETURN_VALUE): Type argument for
+ `REGISTER_CONVERT_TO_VIRTUAL is `TYPE', not
+ `REGISTER_VIRTUAL_TYPE (FP0_REGNUM)';
+ (STORE_RETURN_VALUE): Ditto, and offset for `write_register_bytes'
+ is `REGISTER_BYTE (FP0_REGNUM)', not `FP0_REGNUM'.
+ (FRAME_NUM_ARGS): New macro.
+ * m68k/tm-news.h (EXTRACT_RETURN_VALUE, STORE_RETURN_VALUE): Ditto.
+ * delta68-nat.c (clear_insn_cache): New function, forgotten in previous
+ patch.
+
+Mon Feb 9 11:10:06 1998 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * d10v-tdep.c: Replace references to IMEM_ADDR and DMEM_ADDR with
+ D10V_MAKE_[DI]ADDR and D10V_CONVERT_[ID]ADDR_TO_RAW macros.
+
+ * config/d10v/tm-d10v.h (IMEM_START): Move to 0x01......
+ (DMEM_START): Move to 0x00......
+ (STACK_START): Move to 0x00..7ffe.
+ (D10V_MAKE_IADDR, D10V_MAKE_DADDR): Translate unconditionally.
+
+ * d10v-tdep.c (d10v_xlate_addr): Delete function.
+
+Mon Feb 9 15:10:21 1998 Fred Fish <fnf@cygnus.com>
+
+ * symtab.c (fixup_psymbol_section): Move forward declaration to
+ top of file with other such decls. Make it a static function.
+ * symtab.h: Minor formatting tweaks.
+
+Mon Feb 9 13:14:12 1998 Stan Shebs <shebs@andros.cygnus.com>
+
+ * config/a29k-udi.mt, config/i960/vxworks960.mt (REMOTE_OBS):
+ Remove redefinition.
+ * config/i960/tm-i960.h (BREAKPOINT): Define.
+
+Mon Feb 9 15:35:38 1998 Ian Lance Taylor <ian@cygnus.com>
+
+ * Makefile.in (init.c): Ignore errors when making init.c. Seems
+ necessary to work around bug in Solaris make.
+
+Sun Feb 6 02:44:28 1998 Philippe De Muyter <phdm@macqel.be>
+
+ * m68k/tm-delta68.h (CPLUS_MARKER): Macro deleted.
+ (EXTRACT_STRUCT_VALUE_ADDRESS): Macro defined.
+ (EXTRACT_RETURN_VALUE, STORE_RETURN_VALUE): Macros modified
+ because floating-point values return via %fp0.
+ (CLEAR_INSN_CACHE): New macro.
+ * m68k/tm-m68k.h (REGISTER_CONVERT_TO_VIRTUAL): Macro fixed
+ to use DOUBLEST.
+ (REGISTER_CONVERT_TO_RAW): Ditto.
+ * infptrace.c (child_xfer_memory): If CLEAR_INSN_CACHE is defined,
+ call it after having written in child process's memory.
+ * inflow.c (PROCESS_GROUP_TYPE): Macro defined if HAVE_TERMIO.
+ (gdb_has_a_terminal, terminal_ours_1): Functions fixed for HAVE_TERMIO.
+
+Fri Feb 6 16:17:30 1998 Jeffrey A Law (law@cygnus.com)
+
+ * config/mips/tm-mips64.h (TARGET_LONG_BIT): Allow final target to
+ override.
+ (TARGET_LONG_LONG_BIT): Likewise.
+ (TARGET_PTR_BIT): Likewise.
+
+Fri Feb 6 17:42:22 1998 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * config/d10v/tm-d10v.h (D10V_CONVERT_IADDR_TO_RAW,
+ D10V_CONVERT_DADDR_TO_RAW): Define.
+
+ * d10v-tdep.c (d10v_push_arguments): Re-write. Pass arguments in
+ registers, regardless of their size, when they fit.
+
+Thu Feb 5 13:16:36 1998 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * d10v-tdep.c (d10v_extract_return_value): For function pointers
+ translate address to IMAP area.
+
+ * config/d10v/tm-d10v.h (EXTRA_FRAME_INFO): Delete dummy from
+ struct.
+ (POP_FRAME): Point at generic_pop_current_frame.
+
+ * d10v-tdep.c (d10v_pop_frame): Delete code handling dummy frames,
+ handled earlier.
+ (d10v_push_return_address): New function.
+ (d10v_pop_dummy_frame): Delete.
+ (d10v_fix_call_dummy): Delete.
+ (d10v_call_dummy_address): Delete.
+
+ * d10v-tdep.c (d10v_init_extra_frame_info): Clear dummy and
+ frameless.
+
+ * d10v-tdep.c (d10v_push_arguments): Keep stack word aligned.
+
+ * config/d10v/tm-d10v.h (EXTRACT_STRUCT_VALUE_ADDRESS): Extract
+ address of structure from first ARG1_REGNUM.
+
+ * d10v-tdep.c (d10v_push_arguments): Force 4 byte args into
+ even-odd register pair. Store 1 and 2 byte args in registers.
+
+ * valops.c (value_fetch_lazy): Ensure that a D10V function pointer
+ is fetched in the correct byte order.
+ (value_at): Ditto. Also ensure data pointers are mapped to data
+ segment.
+
+ * config/d10v/tm-d10v.h (D10V_DADDR_P, D10V_IADDR_P):
+
+ * d10v-tdep.c: Replace 2 with REGISTER_RAW_SIZE.
+ (d10v_pop_frame): Replace R13 with LR_REGNUM.
+ (d10v_push_arguments): Replace R2 with ARG1_REGNUM.
+ (d10v_push_arguments): Replace 6 with ARGN_REGNUM.
+ (d10v_extract_return_value): Access return value with RET1_REGNUM.
+
+ * config/d10v/tm-d10v.h (ARG1_REGNUM, ARGN_REGNUM, RET1_REGNUM):
+ Define.
+ (STORE_RETURN_VALUE): Specify return register using RET1_REGNUM.
+ (STORE_STRUCT_RETURN): Specify ARG1_REGNUM as the struct ptr
+ location.
+
+Thu Feb 5 13:16:36 1998 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * blockframe.c (generic_pop_dummy_frame): Flush the frame, no
+ longer valid.
+
+ * blockframe.c (generic_pop_current_frame), frames.h: New
+ function.
+
+Thu Feb 5 17:18:16 1998 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * remote-sim.c (gdbsim_create_inferior): clear_proceed_status
+ before /re/starting the simulator.
+
+Thu Feb 5 15:55:31 1998 C. M. Heard (heard@vvnet.com)
+
+ * top.c (do_nothing): Remove signal handler after signal is caught.
+
+Thu Feb 5 11:57:06 1998 Michael Snyder (msnyder@cleaver.cygnus.com)
+
+ * tracepoint.c (tracepoint_operation): call free_actions instead
+ of free. (free_actions): eliminate some memory leaks for actions.
+ (validate_actionline): pass string arg by reference, so we can
+ change the pointer. Change all memrange collection arguments to
+ canonical form (literal address and size), to enforce early
+ evaluation. Accept UNOP_MEMVAL (assembly variables) for
+ trace collection. (parse_and_eval_memrange): accept expressions
+ for the address and size fields of a memrange (and evaluate
+ them immediately). (several places): use -1 instead of zero
+ to distinguish an absolute memrange from a register-relative one.
+ (encode_actions): add handling for UNOP_MEMVAL (assembly variable).
+
+Wed Feb 4 17:40:21 1998 Jason Molenda (crash@bugshack.cygnus.com)
+
+ * Makefile.in (SFILES): add tracepoint.c.
+ (LINTFILES): add @CONFIG_SRCS@.
+ (SOURCES): Ditto.
+ * configure.in (CONFIG_SRCS): Mirror use of CONFIG_OBS.
+ * configure: Regenerated.
+
+Tue Feb 3 16:12:32 1998 Gordon W. Ross (gwr@mc.com)
+
+ * infptrace.c (child_resume): Don't try to step if
+ NO_SINGLE_STEP is defined.
+
+Mon Feb 2 19:06:13 1998 Jason Molenda (crash@bugshack.cygnus.com)
+
+ * Makefile.in (VERSION): Bump to 4.16.2.
+
+Mon Feb 2 17:18:25 1998 Richard Henderson <rth@cygnus.com>
+
+ * alpha-nat.c (fetch_aout_core_registers): Rename from
+ fetch_core_registers.
+ (fetch_elf_core_registers): New function.
+ (supply_gregset): Use ALPHA_REGSET_BASE.
+ (supply_fpregset): Likewise.
+ (fill_fpregset): Likewise.
+ (alpha_aout_core_fns): Rename from alpha_core_fns.
+ (alpha_elf_core_fns): New.
+ * config/alpha/alpha-linux.mh (NATDEPFILES): solib.o not osfsolib.o.
+ Disable MMALLOC.
+ * config/alpha/nm-linux.h (SVR4_SHARED_LIBS): Define if ELF.
+ (TARGET_ELF64): Likewise.
+ (ALPHA_REGSET_BASE): New.
+ * config/alpha/nm-osf.h (ALPHA_REGSET_BASE): New.
+ * config/alpha/tm-alphalinux.h: Include tm-sysv4.h.
+
+ * solib.c (elf_locate_base): Add TARGET_ELF64 support.
+ (info_sharedlibary_command): Likewise.
+
+ * configure.host: Match alpha*.
+ * configure.tgt: Likewise.
+
+Fri Jan 30 15:11:38 1998 David Taylor <taylor@texas.cygnus.com>
+
+ Changes by <Peter.Schauer@Regent.E-Technik.TU-Muenchen.DE>
+ * infrun.c (IN_SOLIB_DYNSYM_RESOLVE_CODE): new macro for detecting
+ whether we are in the dynamic symbol resolution code
+ (wait_for_inferior): invoke it.
+ * solib.c (in_svr4_dynsym_resolve_code): new function
+ (enable_break): record start and end of the dynamic linker
+ text and plt sections for use in in_svr4_dynsym_resolve_code.
+ * solib.h (IN_SOLIB_DYNSYM_RESOLVE_CODE): add svr4 definition;
+ (in_svr4_dynsym_resolve_code): declare it.
+ * config/nm-gnu.h (solib.h): move inclusion to after definition
+ of SVR4_SHARED_LIBS.
+ * config/nm-sysv4.h (solib.h): ditto.
+ * config/i386/nm-i386sco5.h (solib.h): ditto.
+ * config/i386/nm-linux.h (solib.h): ditto.
+ * config/mips/nm-irix5.h (IN_SOLIB_DYNSYM_RESOLVE_CODE): undefine.
+
+Thu Jan 29 19:39:31 1998 Stan Shebs <shebs@andros.cygnus.com>
+
+ * coffread.c (coff_symtab_read) [SEM]: Remove code, macro can
+ never be defined.
+ * dbxread.c (process_one_symbol) [BLOCK_ADDRESS_ABSOLUTE]:
+ Remove, no longer needed.
+ * hppa-tdep.c (N_SET_MAGIC): Remove, no longer used.
+ * config/pa/xm-hppab.h (SEEK_SET, SEEK_CUR, SEEK_END): Ditto.
+ * config/mips/tm-mipsm3.h (NUMERIC_REG_NAMES): Ditto.
+ * config/mips/mipsm3.mt (TDEPFILES): Remove mipsread.o.
+
+Wed Jan 28 14:46:52 1998 Stan Shebs <shebs@andros.cygnus.com>
+
+ Suggested by Chris Walter <walter@budoe.bu.edu>:
+ * dwarfread.c (set_cu_language): Recognize Fortran.
+ * dwarf2read.c (set_cu_language): Ditto.
+ (read_array_type): Fix language test.
+
+Wed Jan 28 12:51:08 1998 Michael Snyder (msnyder@cleaver.cygnus.com)
+
+ * blockframe.c (generic_frame_chain_valid): A frame pointer may
+ be valid if it is equal to the frame pointer of its caller (ie.
+ not necessarily strictly INNER_THAN). Allows frameless functions.
+
+Wed Jan 28 11:23:25 1998 Mark Alexander <marka@cygnus.com>
+
+ * monitor.c (monitor_vsprintf): New function to handle
+ printing of large addresses using %A format specifier.
+ (monitor_printf_noecho, monitor_printf): Use monitor_vsprintf
+ instead of vsprintf.
+ * dve3900-rom.c (_initialize_r3900_rom): Use %A instead of %Lx
+ to print addresses.
+
+Tue Jan 27 16:14:23 1998 Jason Molenda (crash@bugshack.cygnus.com)
+
+ * configure.in (CONFIG_LDFLAGS): Only add -export-dynamic
+ when using GNU ld.
+
+Mon Jan 26 19:07:46 1998 Jason Molenda (crash@bugshack.cygnus.com)
+
+ * config/alpha/tm-alphalinux.h (alpha_linux_sigtramp_offset):
+ Add closing parenthesis. From HJ Lu.
+
+Mon Jan 26 17:54:45 1998 Mark Alexander <marka@cygnus.com>
+
+ * dve3900-rom.c: Improve performance by using memory commands
+ that print less fluff. Minor cosmetic changes.
+ Eliminate compiler warnings.
+
+Sat Jan 24 23:44:43 1998 Martin M. Hunt <hunt@cygnus.com>
+
+ * breakpoint.c (enable_breakpoint): Preserve breakpoint
+ disposition when enabling a breakpoint.
+
+ * symtab.c (find_pc_sect_line): If no symbol information
+ is found, return correct pc anyway.
+
+Fri Jan 23 17:26:22 1998 Stan Shebs <shebs@andros.cygnus.com>
+
+ * configure.host (i[3456]86-*-osf1mk*, mips-*-mach3*,
+ ns32k-*-mach3*): Fix file names.
+ (i[3456]86-*-os9k, m88*-*-mach3*, w65-*-*): Remove config
+ recognition, no source files for these.
+ * configure.tgt (powerpc-*-aix4*): Remove config, now identical
+ to powerpc-*-aix*.
+ * config/powerpc/{aix4.mh,aix4.mt,tm-ppc-aix4.h}: Remove files,
+ no longer needed.
+
+Fri Jan 23 16:49:41 1998 Mark Alexander <marka@cygnus.com>
+
+ * monitor.c (monitor_write, monitor_readchar): New functions.
+ * monitor.h (monitor_write, monitor_readchar): Declare.
+ * dve3900-rom.c: Add support for fast loading on ethernet connections.
+
+Fri Jan 23 07:47:06 1998 Fred Fish <fnf@cygnus.com>
+
+ * config/d10v/tm-d10v.h (CALL_DUMMY): Define as "{ 0 }".
+ (TARGET_READ_FP): Define to d10v_read_fp rather than d10v_read_sp.
+ (TARGET_WRITE_FP): Define to d10v_write_fp rather than d10v_write_sp.
+ (d10v_write_fp, d10v_read_fp): Add prototypes.
+ * symtab.c (decode_line_1): Remove assignment of sals[0].pc field.
+ * symfile.c (simple_overlay_update, simple_overlay_update_1):
+ Ignore the size of overlay sections. This check is redundant anyway.
+ * printcmd.c (print_frame_args): Ditto.
+ * valops.c (value_fetch_lazy): Ditto.
+ * values.c (unpack_long): Ditto.
+ * d10v-tdep.c (d10v_frame_chain, d10v_frame_find_saved_regs,
+ d10v_init_extra_frame_info): Fix some minor bugs so the finish command
+ works properly.
+ (show_regs): Change num1 and num2 types from "long long" to "LONGEST".
+ (d10v_read_fp, d10v_write_fp): New functions.
+ (d10v_push_arguments): Remove unneeded assigns to "val" and "contents".
+ (d10v_push_arguments): Fix for pointers and structs.
+ (d10v_extract_return_value): Fix for pointers and chars.
+
+Tue Jan 20 18:53:18 1998 Stan Shebs <shebs@andros.cygnus.com>
+
+ * configure.tgt (i386-*-mach*, m88*-*-mach3*): Remove config
+ recognition, no source files for these (note that the i386 Mach
+ config is for pre-Mach 3).
+ (mips*-*-mach3*, ns32k-*-mach3*): Fix file names.
+ * config/mips/mipsel64.mt: Remove, never referenced.
+
+Mon Jan 19 14:01:28 1998 Stan Shebs <shebs@andros.cygnus.com>
+
+ * top.c (print_gdb_version): Restore to original message.
+
+Mon Jan 19 13:34:40 1998 Ian Lance Taylor <ian@cygnus.com>
+
+ From cgf@bbc.com (Chris Faylor):
+ * win32-nat.c (child_mourn_inferior): Call ContinueDebugEvent to
+ let the child exit.
+ (child_kill_inferior): Respond to all debug events as the child is
+ terminating.
+
+ * Makefile.in (all): Change gdb dependency to gdb$(EXEEXT).
+ (uninstall): Add $(EXEEXT) to file name to remove.
+ (gdb$(EXEEXT)): Rename target from plain gdb.
+ (gdb1$(EXEEXT)): Rename target from plain gdb1.
+ (clean, mostlyclean): Add $(EXEEXT) to binary names to remove.
+
+1998-01-16 Felix Lee <flee@cygnus.com>
+
+ * top.c (print_gdb_version): delete stutter.
+
+Thu Jan 15 12:29:13 1998 Nick Clifton <nickc@cygnus.com>
+
+ * remote-rdi.c (arm_rdi_open): Patch from Tony.Thompson@arm.com
+ to prevent spurous error messages on non-ICE targets.
+
+Wed Jan 14 19:27:02 1998 Stan Shebs <shebs@andros.cygnus.com>
+
+ * config/mips/{r3900.mt,r3900l.mt,tm-r3900.h,tm-r3900l.h}:
+ Remove, no longer used.
+
+Wed Jan 14 18:11:26 1998 Michael Meissner <meissner@cygnus.com>
+
+ Patch from Jim Wilson.
+ * d30v-tdep.c (d30v_frame_find_saved_regs_offsets): Properly
+ declare void function before use.
+
+ * config/d30v/tm-d30v.h (CALL_DUMMY): Initialize as { 0 }, not {}.
+
+Tue Jan 13 16:38:48 1998 Fred Fish <fnf@cygnus.com>
+
+ * configure.in (--with-mmalloc): Add new configure arg to use the
+ mmalloc package. Default is to not use it.
+ (START_INFERIOR_TRAPS_EXPECTED): Define to the integer 2, not
+ the string "2".
+ * acconfig.h (USE_MMALLOC, FORCE_MMCHECK): Add #undef.
+ * configure: Regenerated.
+ * config.in: Regenerated.
+ * Makefile.in (MMALLOC_DIR, MMALLOC_SRC): Remove.
+ (MMALLOC): Set using configure.
+ (MMALLOC_CFLAGS): Set using configure.
+
+ * config/i386/tm-linux.h (sys_quotactl): Define to 1 rather
+ than just defining it.
+ * mpw-make.sed: Undefine USE_MMALLOC rather than defining NO_MMALLOC.
+ * utils.c (NO_MMALLOC): Use USE_MMALLOC instead.
+ * objfiles.c: ditto.
+ * defs.h: ditto.
+
+ * config/sparc/sun4os4.mh (MMALLOC_CFLAGS): Remove.
+ * config/m68k/sun3os4.mh (MMALLOC_CFLAGS): Remove.
+ * config/i386/cygwin32.mh (MMALLOC_CFLAGS): Remove.
+ * config/alpha/alpha-osf3.mh (MMALLOC_CFLAGS): Remove.
+ * config/alpha/alpha-osf2.mh (MMALLOC_CFLAGS): Remove.
+ * gdbserver/Makefile.in (MMALLOC_*): Remove.
+ * config/rs6000/rs6000.mh (MMALLOC, MMALLOC_CFLAGS): Remove.
+ * config/rs6000/aix4.mh (MMALLOC, MMALLOC_CFLAGS): Remove.
+ * config/powerpc/aix4.mh (MMALLOC, MMALLOC_CFLAGS): Remove.
+ * config/powerpc/aix.mh (MMALLOC, MMALLOC_CFLAGS): Remove.
+ * config/ns32k/ns32km3.mh (MMALLOC, MMALLOC_CFLAGS): Remove.
+ * config/mips/mipsm3.mh (MMALLOC, MMALLOC_CFLAGS): Remove.
+ * config/mips/decstation.mh (MMALLOC, MMALLOC_CFLAGS): Remove.
+ * config/m88k/cxux.mh (MMALLOC, MMALLOC_CFLAGS): Remove.
+ * config/i386/xm-windows.h (NO_MMALLOC, NO_MMCHECK): Remove.
+ * config/i386/i386mk.mh (MMALLOC, MMALLOC_CFLAGS): Remove.
+ * config/i386/i386m3.mh (MMALLOC, MMALLOC_CFLAGS): Remove.
+ * config/i386/i386gnu.mh (MMALLOC, MMALLOC_CFLAGS): Remove.
+ * config/alpha/alpha-osf1.mh (MMALLOC, MMALLOC_CFLAGS): Remove.
+ * config/alpha/alpha-linux.mh (MMALLOC, MMALLOC_CFLAGS): Remove.
+
+Mon Jan 12 11:46:51 1998 Michael Snyder (msnyder@cleaver.cygnus.com)
+
+ * config/m68k/tm-m68k.h (REGISTER_VIRTUAL_TYPE): make A0 thru A7
+ default to void pointer type (so that their default radix is hex).
+
+ * symtab.c: move rbreak_command from no_class to class_breakpoint
+ so it will be listed under "help breakpoints".
+
+Sat Jan 10 14:58:04 1998 Stan Shebs <shebs@andros.cygnus.com>
+
+ * rdi-share/hostchan.c: Remove gettimeofday declaration.
+
+Thu Jan 8 11:03:59 1998 Nick Clifton <nickc@cygnus.com>
+
+ * remote-rdp.c: Applied patches submitted by Tony.Thompson@arm.com
+ to implement the Angel remote debugging interface.
+
+ * Makefile.in: Add build rules for remote-rdi.c and
+ rdi-share/libangsd.a.
+
+ * configure.tgt: Updated from source on branch.
+ * config/arm/tm-arm.h: Updated from source on branch.
+ * arm-tdep.c: Updated from source on branch.
+
+ * rdi-share: New directory, RDI library contributed by ARM.
+
+Mon Jan 5 20:21:59 1998 Mark Alexander <marka@cygnus.com>
+
+ * monitor.h (MO_PRINT_PROGRAM_OUTPUT): Define.
+ * monitor.c (monitor_wait): Echo program output.
+ * dve3900-rom.c (_initialize_r3900_rom): Remove MO_HANDLE_NL flag,
+ add MO_PRINT_PROGRAM_OUTPUT flag.
+
+Mon Jan 5 18:21:11 1998 David Taylor <taylor@texas.cygnus.com>
+
+ * top.h (HAVE_SIGSETJMP): define SIGJMP_BUF, SIGSETJMP, and
+ SIGLONGJMP appropriately based on whether HAVE_SIGSETJMP is
+ defined.
+ * top.c (return_to_top_level, catch_errors): use the new macros
+ * main.c (SET_TOP_LEVEL): ditto.
+ * config/xm-sysv4.h (HAVE_SIGSETJMP): Define.
+
+Fri Jan 2 18:48:58 1998 Mark Alexander <marka@cygnus.com>
+
+ * configure.in: Double up brackets in shell case pattern.
+
+Fri Jan 2 17:06:05 1998 Michael Snyder (msnyder@cleaver.cygnus.com)
+
+ * tracepoint.c (finish_tfind_command): improved algorithm for
+ deciding when we've "stepped" into a new stack frame.
+ (map_args_over_tracepoints): loop over tracepoint list "safely",
+ since list elements may be deleted during loop.
+ (read_actions): add actions to history list.
+
+For older changes see ChangeLog-97
+
+Local Variables:
+mode: change-log
+left-margin: 8
+fill-column: 74
+version-control: never
+End:
diff --git a/gdb/Makefile.in b/gdb/Makefile.in
new file mode 100644
index 00000000000..2c6dfb5cdeb
--- /dev/null
+++ b/gdb/Makefile.in
@@ -0,0 +1,1619 @@
+# Copyright 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998
+# 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+host_alias = @host_alias@
+target_alias = @target_alias@
+program_transform_name = @program_transform_name@
+bindir = @bindir@
+libdir = @libdir@
+tooldir = $(libdir)/$(target_alias)
+
+datadir = @datadir@
+mandir = @mandir@
+man1dir = $(mandir)/man1
+man2dir = $(mandir)/man2
+man3dir = $(mandir)/man3
+man4dir = $(mandir)/man4
+man5dir = $(mandir)/man5
+man6dir = $(mandir)/man6
+man7dir = $(mandir)/man7
+man8dir = $(mandir)/man8
+man9dir = $(mandir)/man9
+infodir = @infodir@
+includedir = @includedir@
+
+# This can be referenced by `INTLDEPS' as computed by CY_GNU_GETTEXT.
+top_builddir = .
+
+SHELL = @SHELL@
+EXEEXT = @EXEEXT@
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA = @INSTALL_DATA@
+
+AR = @AR@
+AR_FLAGS = qv
+RANLIB = @RANLIB@
+DLLTOOL = @DLLTOOL@
+WINDRES = @WINDRES@
+
+# If the user configured GDB to include the TUI, the name of the tui
+# library goes here.
+TUI_LIBRARY = @TUI_LIBRARY@
+
+# If the user configured GDB to include the TUI, the all-tui
+# target goes here.
+BUILD_TUI = @BUILD_TUI@
+
+# Flags that describe where you can find the termcap library.
+# This can be overridden in the host Makefile fragment file.
+TERMCAP = @TERM_LIB@
+
+# If you are compiling with GCC, make sure that either 1) You have the
+# fixed include files where GCC can reach them, or 2) You use the
+# -traditional flag. Otherwise the ioctl calls in inflow.c
+# will be incorrectly compiled. The "fixincludes" script in the gcc
+# distribution will fix your include files up.
+CC=@CC@
+
+# Directory containing source files.
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+YACC=@YACC@
+
+YLWRAP = $(srcdir)/../ylwrap
+
+# where to find makeinfo, preferably one designed for texinfo-2
+MAKEINFO=makeinfo
+
+# Set this up with gcc if you have gnu ld and the loader will print out
+# line numbers for undefined references.
+#CC_LD=gcc -static
+CC_LD=$(CC)
+
+# Where is our "include" directory? Typically $(srcdir)/../include.
+# This is essentially the header file directory for the library
+# routines in libiberty.
+INCLUDE_DIR = $(srcdir)/../include
+INCLUDE_CFLAGS = -I$(INCLUDE_DIR)
+
+# Where is the "-liberty" library? Typically in ../libiberty.
+LIBIBERTY = ../libiberty/libiberty.a
+
+# Configured by the --with-mmalloc option to configure.
+MMALLOC = @MMALLOC@
+MMALLOC_CFLAGS = @MMALLOC_CFLAGS@
+
+# Where is the BFD library? Typically in ../bfd.
+BFD_DIR = ../bfd
+BFD = $(BFD_DIR)/libbfd.a
+BFD_SRC = $(srcdir)/$(BFD_DIR)
+BFD_CFLAGS = -I$(BFD_DIR) -I$(BFD_SRC)
+
+# Where is the READLINE library? Typically in ../readline.
+READLINE_DIR = ../readline
+READLINE = $(READLINE_DIR)/libreadline.a
+READLINE_SRC = $(srcdir)/$(READLINE_DIR)
+READLINE_CFLAGS = -I$(READLINE_SRC)/..
+
+WARN_CFLAGS = @WARN_CFLAGS@
+
+# Where is the INTL library? Typically in ../intl.
+INTL_DIR = ../intl
+INTL = @INTLLIBS@
+INTL_DEPS = @INTLDEPS@
+INTL_SRC = $(srcdir)/$(INTL_DIR)
+INTL_CFLAGS = -I$(INTL_DIR) -I$(INTL_SRC)
+
+# Where is the TUI library? Typically in tui/.
+TUI_DIR=tui
+TUI_SRC = $(srcdir)/$(TUI_DIR)
+TUI_CFLAGS= -I$(TUI_SRC)
+
+# Opcodes currently live in one of two places. Either they are in the
+# opcode library, typically ../opcodes, or they are in a header file
+# in INCLUDE_DIR.
+# Where is the "-lopcodes" library, with (some of) the opcode tables and
+# disassemblers?
+OPCODES = ../opcodes/libopcodes.a
+# Where are the other opcode tables which only have header file
+# versions?
+OP_INCLUDE = $(INCLUDE_DIR)/opcode
+OPCODES_CFLAGS = -I$(OP_INCLUDE)
+
+# The simulator is usually nonexistent; targets that include one
+# should set this to list all the .o or .a files to be linked in.
+SIM =
+
+
+ENABLE_CFLAGS= @ENABLE_CFLAGS@
+
+# -I. for config files.
+# -I$(srcdir) for gdb internal headers and possibly for gnu-regex.h also.
+# -I$(srcdir)/config for more generic config files.
+
+# It is also possible that you will need to add -I/usr/include/sys if
+# your system doesn't have fcntl.h in /usr/include (which is where it
+# should be according to Posix).
+DEFS = @DEFS@
+GDB_CFLAGS = -I. -I$(srcdir) -I$(srcdir)/config $(DEFS)
+
+# M{H,T}_CFLAGS, if defined, have host- and target-dependent CFLAGS
+# from the config directory.
+GLOBAL_CFLAGS = $(MT_CFLAGS) $(MH_CFLAGS)
+#PROFILE_CFLAGS = -pg
+
+# CFLAGS is specifically reserved for setting from the command line
+# when running make. I.E. "make CFLAGS=-Wmissing-prototypes".
+CFLAGS = -g
+
+# Need to pass this to testsuite for "make check". Probably should be
+# consistent with top-level Makefile.in and gdb/testsuite/Makefile.in
+# so "make check" has the same result no matter where it is run.
+CXXFLAGS = -g -O
+
+# INTERNAL_CFLAGS is the aggregate of all other *CFLAGS macros.
+INTERNAL_CFLAGS = $(CFLAGS) $(GLOBAL_CFLAGS) $(PROFILE_CFLAGS) \
+ $(GDB_CFLAGS) $(OPCODES_CFLAGS) $(READLINE_CFLAGS) \
+ $(BFD_CFLAGS) $(MMALLOC_CFLAGS) $(INCLUDE_CFLAGS) \
+ $(INTL_CFLAGS) $(TUI_CFLAGS) $(ENABLE_CFLAGS) $(WARN_CFLAGS)
+
+# LDFLAGS is specifically reserved for setting from the command line
+# when running make.
+
+# Profiling options need to go here to work.
+# I think it's perfectly reasonable for a user to set -pg in CFLAGS
+# and have it work; that's why CFLAGS is here.
+INTERNAL_LDFLAGS = $(CFLAGS) $(GLOBAL_CFLAGS) $(PROFILE_CFLAGS) $(LDFLAGS) @CONFIG_LDFLAGS@ @HLDFLAGS@
+HLDENV = @HLDENV@
+
+# We are using our own version of REGEX now to be consistent across
+# machines.
+REGEX = gnu-regex.o
+REGEX1 = gnu-regex.o
+
+# If your system is missing alloca(), or, more likely, it's there but
+# it doesn't work, then refer to libiberty.
+
+# Libraries and corresponding dependencies for compiling gdb.
+# {X,T}M_CLIBS, defined in *config files, have host- and target-dependent libs.
+# TERMCAP comes after readline, since readline depends on it.
+# MMALLOC comes after anything else that might want an allocation function.
+# LIBIBERTY appears twice on purpose.
+# If you have the Cygnus libraries installed,
+# you can use 'CLIBS=$(INSTALLED_LIBS)' 'CDEPS='
+INSTALLED_LIBS=-lbfd -lreadline -lopcodes -liberty \
+ $(TERMCAP) $(XM_CLIBS) $(TM_CLIBS) $(NAT_CLIBS) $(GDBTKLIBS) @LIBS@ \
+ -lmmalloc -lintl -liberty
+CLIBS = $(SIM) $(BFD) $(READLINE) $(OPCODES) $(INTL) $(LIBIBERTY) \
+ $(TERMCAP) $(XM_CLIBS) $(TM_CLIBS) $(NAT_CLIBS) $(GDBTKLIBS) @LIBS@ \
+ $(MMALLOC) $(LIBIBERTY) $(WIN32LIBS)
+CDEPS = $(XM_CDEPS) $(TM_CDEPS) $(NAT_CDEPS) $(SIM) $(BFD) $(READLINE) \
+ $(OPCODES) $(MMALLOC) $(INTL_DEPS) $(LIBIBERTY) @CONFIG_DEPS@
+
+ADD_FILES = $(REGEX) $(XM_ADD_FILES) $(TM_ADD_FILES) $(NAT_ADD_FILES)
+ADD_DEPS = $(REGEX1) $(XM_ADD_FILES) $(TM_ADD_FILES) $(NAT_ADD_FILES)
+
+VERSION=4.18
+DIST=gdb
+
+LINT=/usr/5bin/lint
+LINTFLAGS= $(BFD_CFLAGS)
+
+RUNTEST = `if [ -f $${rootsrc}/../dejagnu/runtest ] ; then \
+ echo $${rootsrc}/../dejagnu/runtest ; else echo runtest; \
+ fi`
+
+RUNTESTFLAGS=
+
+# This is ser-unix.o for any system which supports a v7/BSD/SYSV/POSIX
+# interface to the serial port. Hopefully if get ported to OS/2, VMS,
+# etc., then there will be (as part of the C library or perhaps as
+# part of libiberty) a POSIX interface. But at least for now the
+# host-dependent makefile fragment might need to use something else
+# besides ser-unix.o
+SER_HARDWIRE = ser-unix.o
+
+# The `remote' debugging target is supported for most architectures,
+# but not all (e.g. 960)
+REMOTE_OBS = remote.o dcache.o remote-utils.o tracepoint.o ax-general.o ax-gdb.o
+
+# This is remote-sim.o if a simulator is to be linked in.
+SIM_OBS =
+
+ANNOTATE_OBS = annotate.o
+
+# Host and target-dependent makefile fragments come in here.
+@host_makefile_frag@
+@target_makefile_frag@
+# End of host and target-dependent makefile fragments
+
+FLAGS_TO_PASS = \
+ "prefix=$(prefix)" \
+ "exec_prefix=$(exec_prefix)" \
+ "against=$(against)" \
+ "AR=$(AR)" \
+ "AR_FLAGS=$(AR_FLAGS)" \
+ "CC=$(CC)" \
+ "CFLAGS=$(CFLAGS)" \
+ "CHILLFLAGS=$(CHILLFLAGS)" \
+ "CHILL=$(CHILL)" \
+ "CHILL_LIB=$(CHILL_LIB)" \
+ "CXX=$(CXX)" \
+ "CXXFLAGS=$(CXXFLAGS)" \
+ "DLLTOOL=$(DLLTOOL)" \
+ "RANLIB=$(RANLIB)" \
+ "MAKEINFO=$(MAKEINFO)" \
+ "INSTALL=$(INSTALL)" \
+ "INSTALL_PROGRAM=$(INSTALL_PROGRAM)" \
+ "INSTALL_DATA=$(INSTALL_DATA)" \
+ "RUNTEST=$(RUNTEST)" \
+ "RUNTESTFLAGS=$(RUNTESTFLAGS)"
+
+# Flags that we pass when building the testsuite.
+
+# empty for native, $(target_alias)/ for cross
+target_subdir = @target_subdir@
+
+CC_FOR_TARGET = ` \
+ if [ -f $${rootme}/../gcc/xgcc ] ; then \
+ if [ -f $${rootme}/../$(target_subdir)newlib/Makefile ] ; then \
+ echo $${rootme}/../gcc/xgcc -B$${rootme}/../gcc/ -idirafter $${rootme}/$(target_subdir)newlib/targ-include -idirafter $${rootsrc}/../$(target_subdir)newlib/libc/include -nostdinc -B$${rootme}/../$(target_subdir)newlib/; \
+ else \
+ echo $${rootme}/../gcc/xgcc -B$${rootme}/../gcc/; \
+ fi; \
+ else \
+ if [ "$(host_canonical)" = "$(target_canonical)" ] ; then \
+ echo $(CC); \
+ else \
+ t='$(program_transform_name)'; echo gcc | sed -e '' $$t; \
+ fi; \
+ fi`
+
+CXX = gcc
+CXX_FOR_TARGET = ` \
+ if [ -f $${rootme}/../gcc/xgcc ] ; then \
+ if [ -f $${rootme}/../$(target_subdir)newlib/Makefile ] ; then \
+ echo $${rootme}/../gcc/xgcc -B$${rootme}/../gcc/ -idirafter $${rootme}/$(target_subdir)newlib/targ-include -idirafter $${rootsrc}/../$(target_subdir)newlib/libc/include -nostdinc -B$${rootme}/../$(target_subdir)newlib/; \
+ else \
+ echo $${rootme}/../gcc/xgcc -B$${rootme}/../gcc/; \
+ fi; \
+ else \
+ if [ "$(host_canonical)" = "$(target_canonical)" ] ; then \
+ echo $(CXX); \
+ else \
+ t='$(program_transform_name)'; echo gcc | sed -e '' $$t; \
+ fi; \
+ fi`
+
+CHILLFLAGS = $(CFLAGS)
+CHILL = gcc
+CHILL_FOR_TARGET = ` \
+ if [ -f $${rootme}/../gcc/Makefile ] ; then \
+ echo $${rootme}/../gcc/xgcc -B$${rootme}/../gcc/ -L$${rootme}/../gcc/ch/runtime/; \
+ else \
+ if [ "$(host_canonical)" = "$(target_canonical)" ] ; then \
+ echo $(CC); \
+ else \
+ t='$(program_transform_name)'; echo gcc | sed -e '' $$t; \
+ fi; \
+ fi`
+CHILL_LIB = ` \
+ if [ -f $${rootme}/../gcc/ch/runtime/libchill.a ] ; then \
+ echo $${rootme}/../gcc/ch/runtime/chillrt0.o \
+ $${rootme}/../gcc/ch/runtime/libchill.a; \
+ else \
+ echo -lchill; \
+ fi`
+
+# The use of $$(x_FOR_TARGET) reduces the command line length by not
+# duplicating the lengthy definition.
+TARGET_FLAGS_TO_PASS = \
+ "prefix=$(prefix)" \
+ "exec_prefix=$(exec_prefix)" \
+ "against=$(against)" \
+ 'CC=$$(CC_FOR_TARGET)' \
+ "CC_FOR_TARGET=$(CC_FOR_TARGET)" \
+ "CFLAGS=$(CFLAGS)" \
+ "CHILLFLAGS=$(CHILLFLAGS)" \
+ 'CHILL=$$(CHILL_FOR_TARGET)' \
+ "CHILL_FOR_TARGET=$(CHILL_FOR_TARGET)" \
+ "CHILL_LIB=$(CHILL_LIB)" \
+ 'CXX=$$(CXX_FOR_TARGET)' \
+ "CXX_FOR_TARGET=$(CXX_FOR_TARGET)" \
+ "CXXFLAGS=$(CXXFLAGS)" \
+ "INSTALL=$(INSTALL)" \
+ "INSTALL_PROGRAM=$(INSTALL_PROGRAM)" \
+ "INSTALL_DATA=$(INSTALL_DATA)" \
+ "MAKEINFO=$(MAKEINFO)" \
+ "RUNTEST=$(RUNTEST)" \
+ "RUNTESTFLAGS=$(RUNTESTFLAGS)"
+
+# All source files that go into linking GDB.
+# Links made at configuration time should not be specified here, since
+# SFILES is used in building the distribution archive.
+
+SFILES = ax-general.c ax-gdb.c bcache.c blockframe.c breakpoint.c \
+ buildsym.c c-exp.y c-lang.c c-typeprint.c c-valprint.c \
+ ch-exp.c ch-lang.c ch-typeprint.c ch-valprint.c coffread.c \
+ command.c complaints.c corefile.c cp-valprint.c dbxread.c \
+ demangle.c dwarfread.c dwarf2read.c elfread.c environ.c eval.c \
+ expprint.c f-exp.y f-lang.c f-typeprint.c f-valprint.c \
+ findvar.c gdbarch.c gdbtypes.c infcmd.c inflow.c infrun.c language.c \
+ jv-exp.y jv-lang.c jv-valprint.c jv-typeprint.c \
+ m2-exp.y m2-lang.c m2-typeprint.c m2-valprint.c main.c maint.c \
+ mem-break.c minsyms.c mipsread.c nlmread.c objfiles.c parse.c \
+ printcmd.c remote.c remote-nrom.c scm-exp.c scm-lang.c \
+ scm-valprint.c source.c stabsread.c stack.c symfile.c \
+ symmisc.c symtab.c target.c thread.c top.c tracepoint.c \
+ typeprint.c utils.c valarith.c valops.c valprint.c values.c \
+ serial.c ser-unix.c mdebugread.c os9kread.c \
+ tui/tui.c tui/tui.h tui/tuiCommand.c tui/tuiCommand.h \
+ tui/tuiData.c tui/tuiData.h tui/tuiDataWin.c tui/tuiDataWin.h \
+ tui/tuiDisassem.c tui/tuiDisassem.h tui/tuiGeneralWin.c \
+ tui/tuiGeneralWin.h tui/tuiIO.c tui/tuiIO.h tui/tuiLayout.c \
+ tui/tuiLayout.h tui/tuiRegs.c tui/tuiRegs.h tui/tuiSource.c \
+ tui/tuiSource.h tui/tuiSourceWin.c tui/tuiSourceWin.h \
+ tui/tuiStack.c tui/tuiStack.h tui/tuiWin.c tui/tuiWin.h
+
+LINTFILES = $(SFILES) $(YYFILES) @CONFIG_SRCS@ init.c
+
+# "system" headers. Using these in dependencies is a rather personal
+# choice. (-rich, summer 1993)
+# (Why would we not want to depend on them? If one of these changes in a
+# non-binary-compatible way, it is a real pain to remake the right stuff
+# without these dependencies -kingdon, 13 Mar 1994)
+getopt_h = $(INCLUDE_DIR)/getopt.h
+floatformat_h = $(INCLUDE_DIR)/floatformat.h
+bfd_h = $(BFD_DIR)/bfd.h
+wait_h = $(INCLUDE_DIR)/wait.h
+dis-asm_h = $(INCLUDE_DIR)/dis-asm.h
+remote-sim_h = $(INCLUDE_DIR)/remote-sim.h
+
+dcache_h = dcache.h
+remote_utils_h = $(dcache_h) serial.h target.h remote-utils.h $(remote-sim_h)
+
+
+readline_headers = \
+ $(READLINE_SRC)/chardefs.h \
+ $(READLINE_SRC)/history.h \
+ $(READLINE_SRC)/keymaps.h \
+ $(READLINE_SRC)/readline.h
+
+udiheaders = \
+ $(srcdir)/29k-share/udi/udiproc.h \
+ $(srcdir)/29k-share/udi/udiphcfg.h \
+ $(srcdir)/29k-share/udi/udiphunix.h \
+ $(srcdir)/29k-share/udi/udiptcfg.h \
+ $(srcdir)/29k-share/udi/udipt29k.h \
+ $(srcdir)/29k-share/udi/udisoc.h
+
+gdbcore_h = gdbcore.h $(bfd_h)
+
+frame_h = frame.h
+symtab_h = symtab.h bcache.h
+gdbtypes_h = gdbtypes.h
+expression_h = expression.h
+value_h = value.h $(symtab_h) $(gdbtypes_h) $(expression_h)
+
+breakpoint_h = breakpoint.h $(frame_h) $(value_h)
+
+command_h = command.h
+gdbcmd_h = gdbcmd.h $(command_h)
+
+defs_h = defs.h xm.h tm.h nm.h config.status config.h gdbarch.h
+
+inferior_h = inferior.h $(breakpoint_h)
+tracepoint_h = tracepoint.h
+ax_h = ax.h
+
+# Header files that need to have srcdir added. Note that in the cases
+# where we use a macro like $(gdbcmd_h), things are carefully arranged
+# so that each .h file is listed exactly once (M-x tags-search works
+# wrong if TAGS has files twice). Because this is tricky to get
+# right, it is probably easiest just to list .h files here directly.
+
+HFILES_NO_SRCDIR = bcache.h buildsym.h call-cmds.h coff-solib.h defs.h \
+ dst.h environ.h $(gdbcmd_h) gdbcore.h \
+ gdb-stabs.h hpread.h $(inferior_h) language.h minimon.h monitor.h \
+ objfiles.h parser-defs.h partial-stab.h serial.h signals.h solib.h \
+ symfile.h stabsread.h target.h terminal.h typeprint.h xcoffsolib.h \
+ c-lang.h ch-lang.h f-lang.h \
+ jv-lang.h \
+ m2-lang.h \
+ complaints.h valprint.h \
+ 29k-share/udi/udiids.h 29k-share/udi_soc nindy-share/b.out.h \
+ nindy-share/block_io.h nindy-share/coff.h \
+ nindy-share/env.h nindy-share/stop.h \
+ vx-share/dbgRpcLib.h vx-share/ptrace.h vx-share/vxTypes.h \
+ vx-share/vxWorks.h vx-share/wait.h vx-share/xdr_ld.h \
+ vx-share/xdr_ptrace.h vx-share/xdr_rdb.h gdbthread.h \
+ dcache.h remote-utils.h top.h somsolib.h
+
+# Header files that already have srcdir in them, or which are in objdir.
+
+HFILES_WITH_SRCDIR = $(udiheaders) ../bfd/bfd.h
+
+
+# GDB "info" files, which should be included in their entirety
+INFOFILES = gdb.info*
+
+REMOTE_EXAMPLES = m68k-stub.c i386-stub.c sparc-stub.c rem-multi.shar
+
+POSSLIBS = gnu-regex.c gnu-regex.h
+
+# {X,T,NAT}DEPFILES are something of a pain in that it's hard to
+# default their values the way we do for SER_HARDWIRE; in the future
+# maybe much of the stuff now in {X,T,NAT}DEPFILES will go into other
+# variables analogous to SER_HARDWIRE which get defaulted in this
+# Makefile.in
+
+DEPFILES = $(TDEPFILES) $(XDEPFILES) $(SER_HARDWIRE) $(NATDEPFILES) \
+ $(REMOTE_OBS) $(SIM_OBS) @CONFIG_OBS@
+
+SOURCES = $(SFILES) $(ALLDEPFILES) $(YYFILES) @CONFIG_SRCS@
+# Don't include YYFILES (*.tab.c) because we already include *.y in SFILES,
+# and it's more useful to see it in the .y file.
+TAGFILES_NO_SRCDIR = $(SFILES) $(HFILES_NO_SRCDIR) $(ALLDEPFILES) \
+ $(POSSLIBS)
+TAGFILES_WITH_SRCDIR = $(HFILES_WITH_SRCDIR)
+
+COMMON_OBS = version.o blockframe.o breakpoint.o findvar.o stack.o thread.o \
+ source.o values.o eval.o valops.o valarith.o valprint.o printcmd.o \
+ symtab.o symfile.o symmisc.o infcmd.o infrun.o command.o \
+ expprint.o environ.o gdbarch.o gdbtypes.o copying.o $(DEPFILES) \
+ mem-break.o target.o parse.o language.o $(YYOBJ) buildsym.o \
+ exec.o bcache.o objfiles.o minsyms.o maint.o demangle.o \
+ dbxread.o coffread.o elfread.o \
+ dwarfread.o dwarf2read.o mipsread.o stabsread.o corefile.o \
+ c-lang.o ch-exp.o ch-lang.o f-lang.o \
+ jv-lang.o jv-valprint.o jv-typeprint.o \
+ m2-lang.o \
+ scm-exp.o scm-lang.o scm-valprint.o complaints.o typeprint.o \
+ c-typeprint.o ch-typeprint.o f-typeprint.o m2-typeprint.o \
+ c-valprint.o cp-valprint.o ch-valprint.o f-valprint.o m2-valprint.o \
+ nlmread.o serial.o mdebugread.o os9kread.o top.o utils.o
+
+OBS = $(COMMON_OBS) $(ANNOTATE_OBS) main.o
+
+LIBGDB_OBS =
+
+TSOBS = inflow.o
+
+NTSOBS = standalone.o
+
+NTSSTART = kdb-start.o
+
+SUBDIRS = doc \
+ testsuite \
+ nlm
+
+# For now, shortcut the "configure GDB for fewer languages" stuff.
+YYFILES = c-exp.tab.c \
+ jv-exp.tab.c \
+ f-exp.tab.c m2-exp.tab.c
+YYOBJ = c-exp.tab.o \
+ jv-exp.tab.o \
+ f-exp.tab.o m2-exp.tab.o
+
+# Things which need to be built when making a distribution.
+
+DISTSTUFF = $(YYFILES)
+
+# Prevent Sun make from putting in the machine type. Setting
+# TARGET_ARCH to nothing works for SunOS 3, 4.0, but not for 4.1.
+.c.o:
+ $(CC) -c $(INTERNAL_CFLAGS) $<
+
+all: gdb$(EXEEXT)
+ @$(MAKE) $(FLAGS_TO_PASS) DO=all "DODIRS=`echo $(SUBDIRS) | sed 's/testsuite//'`" subdir_do
+
+installcheck:
+
+# The check target can not use subdir_do, because subdir_do does not
+# use TARGET_FLAGS_TO_PASS.
+check: force
+ @if [ -f testsuite/Makefile ]; then \
+ rootme=`pwd`; export rootme; \
+ rootsrc=`cd $(srcdir); pwd`; export rootsrc; \
+ cd testsuite; \
+ $(MAKE) $(TARGET_FLAGS_TO_PASS) check; \
+ else true; fi
+
+info dvi install-info clean-info: force
+ @$(MAKE) $(FLAGS_TO_PASS) DO=$@ "DODIRS=$(SUBDIRS)" subdir_do
+
+gdb.z:gdb.1
+ nroff -man $(srcdir)/gdb.1 | col -b > gdb.t
+ pack gdb.t ; rm -f gdb.t
+ mv gdb.t.z gdb.z
+
+# Traditionally "install" depends on "all". But it may be useful
+# not to; for example, if the user has made some trivial change to a
+# source file and doesn't care about rebuilding or just wants to save the
+# time it takes for make to check that all is up to date.
+# install-only is intended to address that need.
+install: all install-only
+install-only:
+ transformed_name=`t='$(program_transform_name)'; \
+ echo gdb | sed -e $$t` ; \
+ if test "x$$transformed_name" = x; then \
+ transformed_name=gdb ; \
+ else \
+ true ; \
+ fi ; \
+ $(INSTALL_PROGRAM) gdb$(EXEEXT) $(bindir)/$$transformed_name$(EXEEXT) ; \
+ $(INSTALL_DATA) $(srcdir)/gdb.1 $(man1dir)/$$transformed_name.1
+ @$(MAKE) DO=install "DODIRS=$(SUBDIRS)" $(FLAGS_TO_PASS) subdir_do
+
+uninstall: force
+ transformed_name=`t='$(program_transform_name)'; \
+ echo gdb | sed -e $$t` ; \
+ if test "x$$transformed_name" = x; then \
+ transformed_name=gdb ; \
+ else \
+ true ; \
+ fi ; \
+ rm -f $(bindir)/$$transformed_name$(EXEEXT) $(man1dir)/$$transformed_name.1
+ @$(MAKE) DO=uninstall "DODIRS=$(SUBDIRS)" $(FLAGS_TO_PASS) subdir_do
+
+# We do this by grepping through sources. If that turns out to be too slow,
+# maybe we could just require every .o file to have an initialization routine
+# of a given name (remote-udi.o -> _initialize_remote_udi, etc.).
+#
+# Formatting conventions: The name of the _initialize_* routines must start
+# in column zero, and must not be inside #if.
+#
+# Note that the set of files with init functions might change, or the names
+# of the functions might change, so this files needs to depend on all the
+# object files that will be linked into gdb.
+
+init.c: $(OBS) $(TSOBS)
+ @echo Making init.c
+ @rm -f init.c-tmp
+ @echo '/* Do not modify this file. */' >init.c-tmp
+ @echo '/* It is created automatically by the Makefile. */'>>init.c-tmp
+ @echo '#include "ansidecl.h"' >>init.c-tmp
+ @echo 'extern void initialize_all_files PARAMS ((void));' >>init.c-tmp
+ @echo 'void initialize_all_files PARAMS ((void)) {' >>init.c-tmp
+ @-echo $(OBS) $(TSOBS) | \
+ tr ' ' '\012' | \
+ sed -e '/^Onindy.o/d' \
+ -e '/^nindy.o/d' \
+ -e '/ttyflush.o/d' \
+ -e '/xdr_ld.o/d' \
+ -e '/xdr_ptrace.o/d' \
+ -e '/xdr_rdb.o/d' \
+ -e '/udr.o/d' \
+ -e '/udip2soc.o/d' \
+ -e '/udi2go32.o/d' \
+ -e '/version.o/d' \
+ -e '/^[a-z0-9A-Z_]*_[SU].o/d' \
+ -e '/[a-z0-9A-Z_]*-exp.tab.o/d' \
+ -e 's/\.o/.c/' \
+ -e 's|\([^ ][^ ]*\)|$(srcdir)/\1|g' | \
+ while read f; do grep '^_initialize_[a-z_0-9A-Z]* *(' $$f 2>/dev/null; done | \
+ sed -e 's/^.*://' -e 's/^\([a-z_0-9A-Z]*\).*/ {extern void \1 PARAMS ((void)); \1 ();}/' >>init.c-tmp
+ @echo '}' >>init.c-tmp
+ @mv init.c-tmp init.c
+
+.PRECIOUS: init.c
+
+# Removing the old gdb first works better if it is running, at least on SunOS.
+gdb$(EXEEXT): $(OBS) $(BUILD_TUI) $(TSOBS) $(ADD_DEPS) $(CDEPS) init.o
+ rm -f gdb$(EXEEXT)
+ $(HLDENV) $(CC_LD) $(INTERNAL_LDFLAGS) $(WIN32LDAPP) -o gdb$(EXEEXT) \
+ init.o $(OBS) $(TSOBS) $(TUI_LIBRARY) $(ADD_FILES) $(CLIBS) $(LOADLIBES)
+
+nlm: force
+ rootme=`pwd`; export rootme; $(MAKE) $(TARGET_FLAGS_TO_PASS) DO=all DODIRS=nlm subdir_do
+
+libgdb: libgdb-files $(LIBGDB_OBS)
+
+# libproc is not listed here because all-libproc is a dependency of all-gui,
+# not all-gdb, and thus might be built after us.
+LIBGDBDEPS=$(COMMON_OBS) $(LIBGDB_OBS) $(TSOBS) $(ADD_DEPS) $(CDEPS) init.o
+# libproc needs to be before libiberty for alloca.
+LIBGDBFILES=$(COMMON_OBS) $(LIBGDB_OBS) $(TSOBS) ../libproc/libproc.a \
+ $(ADD_DEPS) $(CDEPS) init.o
+
+libgdb-files: $(LIBGDBDEPS) Makefile.in
+ -rm -f libgdb-files
+ for i in $(LIBGDBFILES); do\
+ echo $$i >> libgdb-files;\
+ done
+
+saber_gdb: $(SFILES) $(DEPFILES) copying.c version.c
+ #setopt load_flags $(CFLAGS) $(BFD_CFLAGS) -DHOST_SYS=SUN4_SYS
+ #load ./init.c $(SFILES)
+ #unload $(srcdir)/c-exp.y
+ #unload $(srcdir)/jv-exp.y
+ #unload $(srcdir)/m2-exp.y
+ #unload vx-share/*.h
+ #unload nindy-share/[A-Z]*
+ #load c-exp.tab.c
+ #load jv-exp.tab.c
+ #load m2-exp.tab.c
+ #load copying.c version.c
+ #load ../opcodes/libopcodes.a
+ #load ../libiberty/libiberty.a
+ #load ../bfd/libbfd.a
+ #load ../readline/libreadline.a
+ #load ../mmalloc/libmmalloc.a
+ #load ../intl/libintl.a
+ #load -ltermcap
+ #load `echo " "$(DEPFILES) | sed -e 's/\.o/.c/g' -e 's, , ../,g'`
+ echo "Load .c corresponding to:" $(DEPFILES)
+
+
+# A Mach 3.0 program to force gdb back to command level
+
+stop-gdb: stop-gdb.o
+ ${CC_LD} $(GLOBAL_CFLAGS) $(LDFLAGS) -o stop-gdb \
+ stop-gdb.o $(CLIBS) $(LOADLIBES)
+
+# This is useful when debugging GDB, because some Unix's don't let you run GDB
+# on itself without copying the executable. So "make gdb1" will make
+# gdb and put a copy in gdb1, and you can run it with "gdb gdb1".
+# Removing gdb1 before the copy is the right thing if gdb1 is open
+# in another process.
+gdb1$(EXEEXT): gdb$(EXEEXT)
+ rm -f gdb1$(EXEEXT)
+ cp gdb$(EXEEXT) gdb1$(EXEEXT)
+
+# FIXME. These are not generated by "make depend" because they only are there
+# for some machines.
+# But these rules don't do what we want; we want to hack the foo.o: tm.h
+# dependency to do the right thing.
+tm-isi.h tm-sun3.h tm-news.h tm-hp300bsd.h tm-altos.h: tm-m68k.h
+tm-hp300hpux.h tm-sun2.h tm-3b1.h: tm-m68k.h
+xm-news1000.h: xm-news.h
+xm-i386-sv32.h: xm-i386.h
+tm-i386gas.h: tm-i386.h
+xm-sun4os4.h: xm-sparc.h
+tm-sun4os4.h: tm-sparc.h
+xm-vaxult.h: xm-vax.h
+xm-vaxbsd.h: xm-vax.h
+
+kdb: $(NTSSTART) $(OBS) $(NTSOBS) $(ADD_DEPS) $(CDEPS)
+ ld -o kdb $(NTSSTART) $(OBS) $(NTSOBS) init.o $(ADD_FILES) \
+ -lc $(CLIBS)
+
+# Have the TUI library depend on a phony target, so we'll always
+# recurse and make sure it's up to date. If it is, then the file will
+# be unchanged, and we won't rebuild it.
+# .PHONY: check-tui
+all-tui:
+ @(cd tui; ${MAKE} ${FLAGS_TO_PASS} all)
+
+# Put the proper machine-specific files first, so M-. on a machine
+# specific routine gets the one for the correct machine. (FIXME: those
+# files go in twice; we should be removing them from the main list).
+
+# TAGS depends on all the files that go into it so you can rebuild TAGS
+# with `make TAGS' and not have to say `rm TAGS' first.
+
+TAGS: $(TAGFILES_NO_SRCDIR) $(TAGFILES_WITH_SRCDIR)
+ @echo Making TAGS
+ @etags $(srcdir)/$(TM_FILE) \
+ $(srcdir)/$(XM_FILE) \
+ $(srcdir)/$(NAT_FILE) \
+ `(for i in $(DEPFILES) $(TAGFILES_NO_SRCDIR); do \
+ echo $(srcdir)/$$i ; \
+ done ; for i in $(TAGFILES_WITH_SRCDIR); do \
+ echo $$i ; \
+ done) | sed -e 's/\.o$$/\.c/'` \
+ `find $(srcdir)/config -name '*.h' -print`
+
+tags: TAGS
+
+clean mostlyclean:
+ @$(MAKE) $(FLAGS_TO_PASS) DO=clean "DODIRS=$(SUBDIRS)" subdir_do
+ rm -f *.o *.a $(ADD_FILES) *~ init.c-tmp
+ rm -f init.c version.c
+ rm -f gdb$(EXEEXT) core make.log libgdb-files
+ rm -f gdb[0-9]$(EXEEXT)
+
+# This used to depend on c-exp.tab.c m2-exp.tab.c TAGS
+# I believe this is wrong; the makefile standards for distclean just
+# describe removing files; the only sort of "re-create a distribution"
+# functionality described is if the distributed files are unmodified.
+distclean: clean
+ @$(MAKE) $(FLAGS_TO_PASS) DO=distclean "DODIRS=$(SUBDIRS)" subdir_do
+ rm -f nm.h tm.h xm.h config.status config.h stamp-h .gdbinit
+ rm -f y.output yacc.acts yacc.tmp y.tab.h
+ rm -f config.log config.cache
+ rm -f Makefile
+
+maintainer-clean: local-maintainer-clean do-maintainer-clean distclean
+realclean: maintainer-clean
+
+local-maintainer-clean:
+ @echo "This command is intended for maintainers to use;"
+ @echo "it deletes files that may require special tools to rebuild."
+ rm -f c-exp.tab.c \
+ jv-exp.tab \
+ f-exp.tab.c m2-exp.tab.c
+ rm -f TAGS $(INFOFILES)
+ rm -f $(YYFILES)
+ rm -f nm.h tm.h xm.h config.status
+
+do-maintainer-clean:
+ @$(MAKE) $(FLAGS_TO_PASS) DO=maintainer-clean "DODIRS=$(SUBDIRS)" \
+ subdir_do
+
+diststuff: $(DISTSTUFF)
+ cd doc; $(MAKE) $(MFLAGS) all-doc
+
+subdir_do: force
+ @for i in $(DODIRS); do \
+ if [ -f ./$$i/Makefile ] ; then \
+ if (cd ./$$i; \
+ $(MAKE) $(FLAGS_TO_PASS) $(DO)) ; then true ; \
+ else exit 1 ; fi ; \
+ else true ; fi ; \
+ done
+
+Makefile: Makefile.in config.status @frags@
+ $(SHELL) config.status
+
+config.h: stamp-h ; @true
+stamp-h: config.in config.status
+ CONFIG_HEADERS=config.h:config.in $(SHELL) config.status
+
+config.status: configure
+ $(SHELL) config.status --recheck
+
+force:
+
+# Documentation!
+# GDB QUICK REFERENCE (TeX dvi file, CM fonts)
+doc/refcard.dvi:
+ cd doc; $(MAKE) refcard.dvi $(FLAGS_TO_PASS)
+
+# GDB QUICK REFERENCE (PostScript output, common PS fonts)
+doc/refcard.ps:
+ cd doc; $(MAKE) refcard.ps $(FLAGS_TO_PASS)
+
+# GDB MANUAL: TeX dvi file
+doc/gdb.dvi:
+ cd doc; $(MAKE) gdb.dvi $(FLAGS_TO_PASS)
+
+# GDB MANUAL: info file
+doc/gdb.info:
+ cd doc; $(MAKE) gdb.info $(FLAGS_TO_PASS)
+
+# Make copying.c from COPYING
+copying.c: COPYING copying.awk
+ awk -f $(srcdir)/copying.awk < $(srcdir)/COPYING > copying.c
+
+version.c: Makefile
+ echo 'char *version = "$(VERSION)";' >version.c
+ echo 'char *host_name = "$(host_alias)";' >> version.c
+ echo 'char *target_name = "$(target_alias)";' >> version.c
+
+# c-exp.tab.c is generated in objdir from c-exp.y if it doesn't exist
+# in srcdir, then compiled in objdir to c-exp.tab.o.
+
+# If we said c-exp.tab.c rather than ./c-exp.tab.c some makes
+# would sometimes re-write it into $(srcdir)/c-exp.tab.c.
+
+# Remove bogus decls for malloc/realloc/free which conflict with everything
+# else. Strictly speaking c-exp.tab.c should therefore depend on
+# Makefile.in, but that was a pretty big annoyance.
+c-exp.tab.o: c-exp.tab.c
+c-exp.tab.c: c-exp.y
+ $(SHELL) $(YLWRAP) "$(YACC)" $(srcdir)/c-exp.y y.tab.c c-exp.tmp -- $(YFLAGS)
+ -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' \
+ -e '/^#line.*y.tab.c/d' \
+ < c-exp.tmp > c-exp.new
+ -rm c-exp.tmp
+ mv c-exp.new ./c-exp.tab.c
+
+jv-exp.tab.o: jv-exp.tab.c
+jv-exp.tab.c: jv-exp.y
+ $(SHELL) $(YLWRAP) "$(YACC)" $(srcdir)/jv-exp.y y.tab.c jv-exp.tmp -- $(YFLAGS)
+ -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' \
+ -e '/^#line.*y.tab.c/d' \
+ < jv-exp.tmp > jv-exp.new
+ -rm jv-exp.tmp
+ mv jv-exp.new ./jv-exp.tab.c
+
+f-exp.tab.o: f-exp.tab.c
+f-exp.tab.c: f-exp.y c-exp.tab.c
+ $(SHELL) $(YLWRAP) "$(YACC)" $(srcdir)/f-exp.y y.tab.c f-exp.tmp -- $(YFLAGS)
+ -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' \
+ -e '/^#line.*y.tab.c/d' \
+ < f-exp.tmp > f-exp.new
+ -rm f-exp.tmp
+ mv f-exp.new ./f-exp.tab.c
+
+# m2-exp.tab.c is generated in objdir from m2-exp.y if it doesn't exist
+# in srcdir, then compiled in objdir to m2-exp.tab.o.
+# Remove bogus decls for malloc/realloc/free which conflict with everything
+# else.
+m2-exp.tab.o: m2-exp.tab.c
+m2-exp.tab.c: m2-exp.y
+ $(SHELL) $(YLWRAP) "$(YACC)" $(srcdir)/m2-exp.y y.tab.c m2-exp.tmp -- $(YFLAGS)
+ -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' \
+ -e '/^#line.*y.tab.c/d' \
+ < m2-exp.tmp > m2-exp.new
+ -rm m2-exp.tmp
+ mv m2-exp.new ./m2-exp.tab.c
+
+# These files are updated atomically, so make never has to remove them
+.PRECIOUS: m2-exp.tab.c f-exp.tab.c c-exp.tab.c
+.PRECIOUS: jv-exp.tab.c
+
+lint: $(LINTFILES)
+ $(LINT) $(INCLUDE_CFLAGS) $(LINTFLAGS) $(LINTFILES) \
+ `echo $(DEPFILES) | sed 's/\.o /\.c /g'`
+
+gdb.cxref: $(SFILES)
+ cxref -I. $(SFILES) >gdb.cxref
+
+force_update:
+
+# GNU Make has an annoying habit of putting *all* the Makefile variables
+# into the environment, unless you include this target as a circumvention.
+# Rumor is that this will be fixed (and this target can be removed)
+# in GNU Make 4.0.
+.NOEXPORT:
+
+# GNU Make 3.63 has a different problem: it keeps tacking command line
+# overrides onto the definition of $(MAKE). This variable setting
+# will remove them.
+MAKEOVERRIDES=
+
+## This is ugly, but I don't want GNU make to put these variables in
+## the environment. Older makes will see this as a set of targets
+## with no dependencies and no actions.
+unexport CHILLFLAGS CHILL_LIB CHILL_FOR_TARGET :
+
+ALLDEPFILES = 29k-share/udi/udip2soc.c 29k-share/udi/udr.c \
+ 29k-share/udi/udi2go32.c \
+ a29k-tdep.c a68v-nat.c alpha-nat.c alpha-tdep.c \
+ altos-xdep.c arm-convert.s \
+ arm-tdep.c arm-xdep.c coff-solib.c \
+ convex-tdep.c convex-xdep.c \
+ core-sol2.c core-regset.c core-aout.c corelow.c \
+ dcache.c delta68-nat.c dpx2-nat.c dstread.c exec.c fork-child.c \
+ go32-xdep.c gould-tdep.c gould-xdep.c h8300-tdep.c h8500-tdep.c \
+ hp300ux-nat.c hppa-tdep.c hppab-nat.c hppah-nat.c \
+ hp-psymtab-read.c hp-symtab-read.c \
+ i386-tdep.c i386b-nat.c i386mach-nat.c i386v-nat.c \
+ i386aix-nat.c i386m3-nat.c i386v4-nat.c i386ly-tdep.c \
+ i387-tdep.c \
+ i960-tdep.c \
+ infptrace.c inftarg.c irix4-nat.c irix5-nat.c isi-xdep.c \
+ lynx-nat.c m3-nat.c \
+ m68k-tdep.c \
+ m88k-nat.c m88k-tdep.c mac-nat.c mips-nat.c \
+ mips-tdep.c mipsm3-nat.c mipsv4-nat.c news-xdep.c \
+ nindy-share/Onindy.c nindy-share/nindy.c \
+ nindy-share/ttyflush.c nindy-tdep.c \
+ ns32k-tdep.c ns32km3-nat.c osfsolib.c \
+ somread.c somsolib.c $(HPREAD_SOURCE) \
+ procfs.c pyr-tdep.c pyr-xdep.c \
+ remote-adapt.c remote-array.c remote-bug.c remote-e7000.c remote-eb.c \
+ remote-es.c remote-hms.c remote-mips.c \
+ remote-mm.c remote-nindy.c remote-os9k.c remote-rdp.c remote-sim.c \
+ remote-st.c remote-utils.c dcache.c \
+ remote-udi.c remote-vx.c remote-vx29k.c \
+ rs6000-nat.c rs6000-tdep.c \
+ ser-go32.c ser-ocd.c ser-tcp.c sh-tdep.c solib.c sparc-nat.c \
+ sparc-tdep.c sparcl-tdep.c sun3-nat.c sun386-nat.c \
+ symm-tdep.c symm-nat.c \
+ tahoe-tdep.c ultra3-nat.c ultra3-xdep.c umax-xdep.c \
+ vax-tdep.c \
+ vx-share/xdr_ld.c vx-share/xdr_ptrace.c vx-share/xdr_rdb.c \
+ win32-nat.c \
+ xcoffread.c xcoffsolib.c z8k-tdep.c
+
+udip2soc.o: $(srcdir)/29k-share/udi/udip2soc.c $(udiheaders)
+ $(CC) -c $(INTERNAL_CFLAGS) $(srcdir)/29k-share/udi/udip2soc.c
+
+udi2go32.o: $(srcdir)/29k-share/udi/udi2go32.c $(udiheaders)
+ $(CC) -c $(INTERNAL_CFLAGS) $(srcdir)/29k-share/udi/udi2go32.c
+
+udr.o: $(srcdir)/29k-share/udi/udr.c $(udiheaders)
+ $(CC) -c $(INTERNAL_CFLAGS) $(srcdir)/29k-share/udi/udr.c
+
+a29k-tdep.o: a29k-tdep.c $(gdbcmd_h) $(gdbcore_h) $(inferior_h) $(defs_h)
+
+a68v-nat.o: a68v-nat.c $(defs_h) $(gdbcore_h) $(inferior_h)
+
+alpha-nat.o: alpha-nat.c $(defs_h) $(gdbcore_h) $(inferior_h) target.h
+
+alpha-tdep.o: alpha-tdep.c $(defs_h) $(gdbcmd_h) $(gdbcore_h) \
+ $(inferior_h) $(symtab_h) $(dis-asm.h) gdb_string.h
+
+altos-xdep.o: altos-xdep.c $(defs_h) $(gdbcore_h) $(inferior_h)
+
+annotate.o: annotate.c $(defs_h) annotate.h $(value_h) target.h $(gdbtypes_h)
+
+arm-tdep.o: arm-tdep.c $(gdbcmd_h) $(gdbcore_h) $(inferior_h) $(defs_h) \
+ $(gdbcore_h)
+
+bcache.o: bcache.c bcache.h $(defs_h)
+
+blockframe.o: blockframe.c $(defs_h) $(gdbcore_h) $(inferior_h) \
+ objfiles.h symfile.h target.h
+
+breakpoint.o: breakpoint.c $(defs_h) $(gdbcmd_h) $(gdbcore_h) \
+ $(inferior_h) language.h target.h gdbthread.h gdb_string.h
+
+buildsym.o: buildsym.c $(bfd_h) buildsym.h complaints.h $(defs_h) \
+ objfiles.h symfile.h $(symtab_h) gdb_string.h
+
+c-lang.o: c-lang.c c-lang.h $(defs_h) $(expression_h) $(gdbtypes_h) \
+ language.h parser-defs.h $(symtab_h)
+
+c-typeprint.o: c-typeprint.c c-lang.h $(defs_h) $(expression_h) \
+ $(gdbcmd_h) $(gdbcore_h) $(gdbtypes_h) language.h $(symtab_h) \
+ target.h typeprint.h $(value_h) gdb_string.h
+
+c-valprint.o: c-valprint.c $(defs_h) $(expression_h) $(gdbtypes_h) \
+ language.h $(symtab_h) valprint.h $(value_h)
+
+f-lang.o: f-lang.c f-lang.h $(defs_h) $(expression_h) $(gdbtypes_h) \
+ language.h parser-defs.h $(symtab_h) gdb_string.h
+
+f-typeprint.o: f-typeprint.c f-lang.h $(defs_h) $(expression_h) \
+ $(gdbcmd_h) $(gdbcore_h) $(gdbtypes_h) language.h $(symtab_h) \
+ target.h typeprint.h $(value_h) gdb_string.h
+
+f-valprint.o: f-valprint.c $(defs_h) $(expression_h) $(gdbtypes_h) \
+ language.h $(symtab_h) valprint.h $(value_h) gdb_string.h
+
+ch-exp.o: ch-exp.c ch-lang.h $(defs_h) language.h parser-defs.h $(bfd_h) symfile.h objfiles.h $(value_h)
+
+ch-lang.o: ch-lang.c ch-lang.h $(defs_h) $(expression_h) $(gdbtypes_h) \
+ language.h parser-defs.h $(symtab_h)
+
+ch-typeprint.o: ch-typeprint.c ch-lang.h $(defs_h) $(expression_h) \
+ $(gdbcmd_h) $(gdbcore_h) $(gdbtypes_h) language.h $(symtab_h) \
+ target.h $(value_h) typeprint.h gdb_string.h
+
+ch-valprint.o: ch-valprint.c $(defs_h) $(expression_h) $(gdbtypes_h) \
+ language.h $(symtab_h) valprint.h $(value_h) c-lang.h
+
+coff-solib.o: coff-solib.c $(defs_h)
+
+coffread.o: coffread.c $(bfd_h) $(breakpoint_h) buildsym.h \
+ complaints.h $(defs_h) $(expression_h) $(gdbtypes_h) objfiles.h \
+ symfile.h $(symtab_h) gdb-stabs.h stabsread.h target.h \
+ gdb_string.h
+
+command.o: command.c $(defs_h) $(expression_h) $(gdbcmd_h) \
+ $(gdbtypes_h) $(symtab_h) $(value_h) gdb_string.h $(wait_h)
+
+complaints.o: complaints.c complaints.h $(defs_h) $(gdbcmd_h)
+
+convex-tdep.o: convex-tdep.c $(wait_h) $(defs_h) $(gdbcmd_h) \
+ $(gdbcore_h) $(inferior_h)
+
+convex-xdep.o: convex-xdep.c $(defs_h) $(gdbcmd_h) $(gdbcore_h) \
+ $(inferior_h)
+
+copying.o: copying.c $(defs_h) $(gdbcmd_h)
+
+core-aout.o: core-aout.c $(defs_h) $(gdbcore_h) $(value_h) $(inferior_h)
+
+core-sol2.o: core-sol2.c $(command_h) $(defs_h) $(gdbcore_h) \
+ $(inferior_h) target.h gdb_string.h
+
+core-regset.o: core-regset.c $(command_h) $(defs_h) $(gdbcore_h) \
+ $(inferior_h) target.h gdb_string.h
+
+corefile.o: corefile.c $(dis-asm_h) $(defs_h) $(gdbcmd_h) $(gdbcore_h) \
+ $(inferior_h) target.h language.h gdb_string.h
+
+corelow.o: corelow.c $(command_h) $(defs_h) $(gdbcore_h) $(inferior_h) \
+ target.h gdbthread.h gdb_string.h
+
+cp-valprint.o: cp-valprint.c $(defs_h) $(expression_h) $(gdbcmd_h) \
+ $(gdbtypes_h) $(symtab_h) $(value_h) gdb_string.h
+
+dcache.o: dcache.c $(dcache_h) $(defs_h) $(gdbcmd_h) gdb_string.h $(gdbcore_h)
+
+dbxread.o: dbxread.c $(breakpoint_h) buildsym.h $(command_h) \
+ complaints.h $(defs_h) $(expression_h) gdb-stabs.h $(gdbcore_h) \
+ $(gdbtypes_h) language.h objfiles.h partial-stab.h stabsread.h \
+ symfile.h $(symtab_h) target.h gdb_string.h
+
+delta68-nat.o: delta68-nat.c $(defs_h)
+
+demangle.o: demangle.c $(defs_h) $(gdbcmd_h) gdb_string.h
+
+dink32-rom.o: dink32-rom.c monitor.h $(bfd_h) $(wait_h) $(defs_h) $(gdbcmd_h) \
+ $(inferior_h) target.h serial.h terminal.h
+
+dpx2-nat.o: dpx2-nat.c $(defs_h) $(gdbcore_h) gdb_string.h
+
+dstread.o: dstread.c gdb_string.h
+
+dwarfread.o: dwarfread.c $(bfd_h) buildsym.h complaints.h $(defs_h) \
+ $(expression_h) $(gdbtypes_h) language.h objfiles.h symfile.h \
+ $(symtab_h) gdb_string.h
+
+dwarf2read.o: dwarf2read.c $(bfd_h) buildsym.h $(defs_h) \
+ $(expression_h) $(gdbtypes_h) language.h objfiles.h symfile.h \
+ $(symtab_h) gdb_string.h
+
+elfread.o: elfread.c $(bfd_h) buildsym.h complaints.h $(defs_h) \
+ gdb-stabs.h objfiles.h symfile.h $(symtab_h) gdb_string.h \
+ $(BFD_SRC)/elf-bfd.h $(INCLUDE_DIR)/elf/mips.h
+
+environ.o: environ.c $(defs_h) environ.h $(gdbcore_h) gdb_string.h
+
+eval.o: eval.c $(bfd_h) $(defs_h) $(expression_h) $(frame_h) \
+ $(gdbtypes_h) language.h $(symtab_h) target.h $(value_h) \
+ gdb_string.h
+
+exec.o: exec.c $(defs_h) $(gdbcmd_h) $(gdbcore_h) $(inferior_h) \
+ target.h language.h gdb_string.h
+
+expprint.o: expprint.c $(defs_h) $(expression_h) $(gdbtypes_h) \
+ language.h parser-defs.h $(symtab_h) $(value_h)
+
+findvar.o: findvar.c $(defs_h) $(gdbcore_h) $(inferior_h) target.h \
+ gdb_string.h
+
+fork-child.o: fork-child.c $(wait_h) $(defs_h) $(gdbcore_h) \
+ $(inferior_h) target.h terminal.h gdbthread.h gdb_string.h
+
+tracepoint.o: tracepoint.c $(defs_h) $(symtab_h) $(frame_h) $(tracepoint_h) \
+ $(gdbtypes_h) $(expression_h) $(gdbcmd_h) $(value_h) target.h \
+ language.h gdb_string.h $(readline_headers)
+
+gdbarch.o: gdbarch.c $(defs_h) $(bfd_h) $(gdbcmd_h)
+
+gdbtypes.o: gdbtypes.c $(bfd_h) complaints.h $(defs_h) $(expression_h) \
+ $(gdbtypes_h) language.h objfiles.h symfile.h $(symtab_h) target.h \
+ $(value_h) gdb_string.h
+
+gnu-nat.o: process_reply_S.h exc_request_S.h notify_S.h msg_reply_S.h \
+ exc_request_U.h msg_U.h gnu-nat.h
+
+go32-xdep.o: go32-xdep.c
+
+# OBSOLETE gould-tdep.o: gould-tdep.c $(OP_INCLUDE)/np1.h $(defs_h) $(frame_h) \
+# OBSOLETE $(gdbcore_h) $(symtab_h)
+
+# OBSOLETE gould-xdep.o: gould-xdep.c $(defs_h) $(gdbcore_h) $(inferior_h)
+
+h8300-tdep.o: h8300-tdep.c $(defs_h) $(frame_h) $(symtab_h)
+
+h8500-tdep.o: h8500-tdep.c $(bfd_h) $(dis-asm_h) $(defs_h) \
+ $(expression_h) $(frame_h) $(gdbcmd_h) $(gdbtypes_h) $(symtab_h) \
+ $(value_h)
+
+hp300ux-nat.o: hp300ux-nat.c $(defs_h) $(gdbcore_h) $(inferior_h)
+
+hppa-tdep.o: hppa-tdep.c $(wait_h) $(defs_h) $(gdbcmd_h) $(gdbcore_h) \
+ $(inferior_h) objfiles.h symfile.h target.h
+
+hppab-nat.o: hppab-nat.c $(bfd_h) $(defs_h) $(inferior_h) target.h
+
+hppah-nat.o: hppah-nat.c $(bfd_h) $(defs_h) $(inferior_h) target.h
+
+i386gnu-nat.o: gnu-nat.h
+
+i386-tdep.o: i386-tdep.c $(defs_h) $(gdbcore_h) $(inferior_h) target.h \
+ gdb_string.h
+
+i386aix-nat.o: i386aix-nat.c $(defs_h) $(frame_h) $(inferior_h) \
+ language.h $(gdbcore_h) $(floatformat_h) target.h
+
+i386b-nat.o: i386b-nat.c $(defs_h)
+
+i386ly-nat.o: i386ly-nat.c $(defs_h) $(frame_h) $(inferior_h) target.h
+
+i386ly-tdep.o: i386ly-tdep.c $(defs_h) $(inferior_h) target.h $(gdbcore_h)
+
+i386m3-nat.o: i386m3-nat.c $(defs_h) $(inferior_h) $(floatformat_h) target.h
+
+i386mach-nat.o: i386mach-nat.c $(defs_h) $(gdbcore_h) $(inferior_h)
+
+i386v-nat.o: i386v-nat.c $(floatformat_h) $(defs_h) $(gdbcore_h) \
+ $(inferior_h) language.h target.h
+
+i386v4-nat.o: i386v4-nat.c $(defs_h)
+
+i387-tdep.o: i387-tdep.c $(floatformat_h) $(defs_h) $(gdbcore_h) \
+ $(inferior_h) language.h
+
+i960-tdep.o: i960-tdep.c $(floatformat_h) $(defs_h) $(expression_h) \
+ $(frame_h) $(gdbtypes_h) $(symtab_h) $(value_h) $(gdbcore_h)
+
+infcmd.o: infcmd.c $(defs_h) environ.h $(gdbcmd_h) $(gdbcore_h) \
+ $(inferior_h) target.h language.h gdb_string.h
+
+inflow.o: inflow.c $(bfd_h) $(command_h) $(defs_h) $(inferior_h) \
+ signals.h target.h terminal.h gdbthread.h gdb_string.h
+
+infptrace.o: infptrace.c $(defs_h) $(gdbcore_h) $(inferior_h) target.h \
+ gdb_string.h $(wait_h) $(command_h)
+
+infrun.o: infrun.c $(wait_h) $(defs_h) $(gdbcmd_h) $(gdbcore_h) \
+ $(inferior_h) target.h gdbthread.h gdb_string.h
+
+inftarg.o: inftarg.c $(wait_h) $(defs_h) $(gdbcore_h) $(inferior_h) \
+ target.h terminal.h $(command_h)
+
+irix4-nat.o: irix4-nat.c $(defs_h) $(inferior_h) $(gdbcore_h)
+irix5-nat.o: irix5-nat.c $(defs_h) $(inferior_h) $(gdbcore_h) target.h \
+ $(symtab_h) symfile.h objfiles.h $(command_h) $(frame_h) gnu-regex.h \
+ language.h gdb_string.h
+
+isi-xdep.o: isi-xdep.c
+
+jv-lang.o: jv-lang.c $(bfd_h) $(defs_h) $(symtab_h) $(gdbtypes_h) \
+ $(expression_h) parser-defs.h language.h symfile.h objfiles.h \
+ gdb_string.h $(value_h) c-lang.h jv-lang.h $(gdbcore_h)
+
+jv-typeprint.o: jv-typeprint.c $(bfd_h) $(defs_h) $(symtab_h) $(gdbtypes_h) \
+ $(value_h) $(INCLUDE_DIR)/demangle.h jv-lang.h gdb_string.h \
+ typeprint.h
+
+jv-valprint.o: jv-valprint.c $(bfd_h) $(defs_h) $(symtab_h) $(gdbtypes_h) \
+ $(expression_h) $(value_h) $(INCLUDE_DIR)/demangle.h valprint.h \
+ language.h jv-lang.h c-lang.h
+
+language.o: language.c $(bfd_h) $(defs_h) $(expression_h) $(frame_h) \
+ $(gdbcmd_h) $(gdbtypes_h) language.h parser-defs.h $(symtab_h) \
+ target.h $(value_h) gdb_string.h
+
+lynx-nat.o: lynx-nat.c $(defs_h) $(frame_h) $(inferior_h) $(gdbcore_h) \
+ target.h
+
+m2-lang.o: m2-lang.c $(defs_h) $(expression_h) $(gdbtypes_h) \
+ language.h m2-lang.h parser-defs.h $(symtab_h)
+
+m2-typeprint.o: m2-typeprint.c $(defs_h) $(expression_h) $(gdbcmd_h) \
+ $(gdbcore_h) $(gdbtypes_h) language.h m2-lang.h $(symtab_h) target.h \
+ $(value_h) gdb_string.h
+
+m2-valprint.o: m2-valprint.c $(defs_h) $(gdbtypes_h) $(symtab_h) \
+ valprint.h m2-lang.h
+
+m3-nat.o: m3-nat.c $(defs_h) $(inferior_h) $(value_h) language.h target.h \
+ $(wait_h) $(gdbcmd_h) $(gdbcore_h)
+
+m68k-tdep.o: m68k-tdep.c $(defs_h) $(frame_h) $(symtab_h) $(value_h) \
+ $(gdbcore_h) gdb_string.h
+
+m68kly-nat.o: m68kly-nat.c $(defs_h) $(frame_h) $(inferior_h) target.h
+
+m68klinux-nat.o: m68klinux-nat.c $(defs_h) $(frame_h) $(inferior_h) \
+ $(language_h) $(gdbcore_h) $(floatformat_h) target.h
+
+m88k-nat.o: m88k-nat.c $(defs_h) $(gdbcore_h) $(inferior_h)
+
+m88k-tdep.o: m88k-tdep.c $(defs_h) $(gdbcore_h) $(inferior_h)
+
+mac-nat.o: mac-nat.c $(defs_h) gdb_string.h
+
+main.o: main.c top.h $(defs_h) gdb_string.h
+
+maint.o: maint.c $(defs_h) $(gdbcmd_h) $(gdbtypes_h) $(symtab_h) language.h \
+ $(expression_h) objfiles.h symfile.h
+
+mdebugread.o: mdebugread.c buildsym.h complaints.h $(bfd_h) $(defs_h) \
+ $(expression_h) gdb-stabs.h $(gdbcore_h) $(gdbtypes_h) language.h \
+ objfiles.h partial-stab.h stabsread.h symfile.h $(symtab_h) \
+ gdb_string.h
+
+mipsm3-nat.o: mipsm3-nat.c $(defs_h) $(inferior_h)
+
+os9kread.o: os9kread.c buildsym.h complaints.h $(bfd_h) $(defs_h) \
+ $(expression_h) gdb-stabs.h $(gdbcore_h) $(gdbtypes_h) language.h \
+ objfiles.h stabsread.h symfile.h $(symtab_h) \
+ target.h gdb_string.h
+
+mem-break.o: mem-break.c $(defs_h)
+
+minsyms.o: minsyms.c $(bfd_h) $(defs_h) objfiles.h symfile.h \
+ $(symtab_h) gdb_string.h
+
+mips-nat.o: mips-nat.c $(defs_h) $(gdbcore_h) $(inferior_h)
+
+mips-tdep.o: mips-tdep.c $(defs_h) $(gdbcmd_h) $(gdbcore_h) \
+ $(inferior_h) language.h objfiles.h symfile.h gdb_string.h
+
+mipsread.o: mipsread.c buildsym.h complaints.h $(bfd_h) $(defs_h) \
+ $(expression_h) gdb-stabs.h $(gdbcore_h) $(gdbtypes_h) language.h \
+ objfiles.h partial-stab.h stabsread.h symfile.h $(symtab_h) \
+ gdb_string.h
+
+mipsv4-nat.o: mipsv4-nat.c $(defs_h) $(gdbcore_h) $(inferior_h) target.h
+
+monitor.o: monitor.c monitor.h $(bfd_h) $(wait_h) $(defs_h) $(gdbcmd_h) \
+ $(inferior_h) target.h serial.h terminal.h gdb_string.h
+
+news-xdep.o: news-xdep.c
+
+Onindy.o: nindy-share/Onindy.c $(wait_h) nindy-share/block_io.h \
+ nindy-share/env.h
+ $(CC) -c $(INTERNAL_CFLAGS) $(srcdir)/nindy-share/Onindy.c
+
+nindy.o: nindy-share/nindy.c $(wait_h) nindy-share/block_io.h \
+ nindy-share/env.h
+ $(CC) -c $(INTERNAL_CFLAGS) $(srcdir)/nindy-share/nindy.c
+
+nlmread.o: nlmread.c $(bfd_h) buildsym.h complaints.h $(defs_h) \
+ gdb-stabs.h objfiles.h symfile.h $(symtab_h) stabsread.h \
+ gdb_string.h
+
+ns32km3-nat.o: ns32km3-nat.c $(defs_h) $(inferior_h)
+
+ttyflush.o: nindy-share/ttyflush.c
+ $(CC) -c $(INTERNAL_CFLAGS) $(srcdir)/nindy-share/ttyflush.c
+
+nindy-tdep.o: nindy-tdep.c $(defs_h) $(frame_h) $(symtab_h) $(gdbcore_h)
+
+ns32k-tdep.o: ns32k-tdep.c $(bfd_h) $(dis-asm_h) $(defs_h)
+
+objfiles.o: objfiles.c $(bfd_h) $(defs_h) objfiles.h symfile.h \
+ $(symtab_h) gdb_string.h
+
+osfsolib.o: osfsolib.c $(command_h) $(defs_h) $(gdbcore_h) $(inferior_h) \
+ objfiles.h gnu-regex.h symfile.h target.h language.h gdb_string.h
+
+somread.o: somread.c $(bfd_h) buildsym.h complaints.h $(defs_h) \
+ gdb-stabs.h objfiles.h symfile.h $(symtab_h) gdb_string.h
+
+somsolib.o: somsolib.c $(defs_h)
+
+hpux-thread.o: hpux-thread.c $(defs_h) gdbthread.h target.h inferior.h
+ $(CC) -c $(INTERNAL_CFLAGS) -I$(srcdir)/osf-share \
+ -I$(srcdir)/osf-share/HP800 -I/usr/include/dce $(srcdir)/hpux-thread.c
+
+# FIXME!!!
+hpread.o: hpread.c $(bfd_h) buildsym.h complaints.h $(defs_h) \
+ gdb-stabs.h objfiles.h symfile.h $(symtab_h) gdb_string.h
+
+hp-psymtab-read.o: hp-psymtab-read.c hpread.h $(bfd_h) buildsym.h complaints.h \
+ $(defs_h) gdb-stabs.h objfiles.h symfile.h $(symtab_h) gdb_string.h
+
+hp-symtab-read.o: hp-symtab-read.c hpread.h $(bfd_h) buildsym.h complaints.h \
+ $(defs_h) gdb-stabs.h objfiles.h symfile.h $(symtab_h) gdb_string.h
+# END FIXME!!!
+
+parse.o: parse.c $(command_h) $(defs_h) $(expression_h) $(frame_h) \
+ $(gdbtypes_h) language.h parser-defs.h $(symtab_h) $(value_h) \
+ gdb_string.h
+
+ppc-bdm.o: ppc-bdm.c $(defs_h) $(gdbcore_h) gdb_string.h $(frame_h) \
+ $(inferior_h) $(bfd_h) symfile.h target.h $(wait_h) $(gdbcmd_h) \
+ objfiles.h gdb-stabs.h serial.h ocd.h
+
+ppcbug-rom.o: ppcbug-rom.c monitor.h $(bfd_h) $(wait_h) $(defs_h) $(gdbcmd_h) \
+ $(inferior_h) target.h serial.h terminal.h
+
+printcmd.o: printcmd.c $(breakpoint_h) $(defs_h) $(expression_h) \
+ $(gdbcmd_h) $(gdbcore_h) $(gdbtypes_h) language.h objfiles.h \
+ symfile.h $(symtab_h) target.h gdb_string.h
+
+procfs.o: procfs.c $(command_h) $(defs_h) $(gdbcore_h) $(inferior_h) \
+ target.h gdb_string.h
+
+pyr-tdep.o: pyr-tdep.c $(defs_h)
+
+pyr-xdep.o: pyr-xdep.c $(defs_h) $(gdbcore_h) $(inferior_h)
+
+gnu-regex.o: gnu-regex.c gnu-regex.h $(defs_h) gdb_string.h
+
+remote-adapt.o: remote-adapt.c $(wait_h) $(defs_h) $(gdbcore_h) \
+ $(inferior_h) target.h terminal.h gdb_string.h
+
+remote-array.o: remote-array.c $(wait_h) $(defs_h) $(gdbcore_h) target.h \
+ gdb_string.h $(command_h) serial.h monitor.h $(remote_utils_h)
+
+remote-rdi.o: remote-rdi.c $(wait_h) $(defs_h) $(gdbcore_h) \
+ $(inferior_h) gdb_string.h
+
+rdi-share/libangsd.a: force
+ @dir=rdi-share; \
+ if [ -f ./$${dir}/Makefile ] ; then \
+ r=`pwd`; export r; \
+ srcroot=`cd $(srcdir); pwd`; export srcroot; \
+ (cd $${dir}; $(MAKE) $(FLAGS_TO_PASS) all); \
+ else \
+ true; \
+ fi
+
+remote-d10v.o: remote-d10v.c $(bfd_h) $(wait_h) $(defs_h) $(gdbcmd_h) \
+ $(inferior_h) $(remote_utils_h) symfile.h terminal.h gdb_string.h
+
+remote-rdp.o: remote-rdp.c $(wait_h) $(defs_h) $(gdbcore_h) \
+ $(inferior_h) gdb_string.h
+
+remote-bug.o: remote-bug.c $(wait_h) $(defs_h) $(gdbcore_h) \
+ $(inferior_h) target.h terminal.h $(remote_utils_h) gdb_string.h
+
+remote-e7000.o: remote-e7000.c $(defs_h) $(gdbcore_h) target.h \
+ $(wait_h) serial.h gdb_string.h
+
+remote-eb.o: remote-eb.c $(wait_h) $(srcdir)/config/a29k/tm-a29k.h \
+ $(defs_h) $(gdbcore_h) $(inferior_h) symfile.h target.h terminal.h \
+ gdb_string.h
+
+remote-es.o: remote-es.c $(bfd_h) $(wait_h) $(command_h) $(defs_h) \
+ $(inferior_h) $(remote_utils_h) terminal.h gdb_string.h
+
+remote-hms.o: remote-hms.c $(wait_h) $(defs_h) $(gdbcore_h) \
+ $(inferior_h) serial.h target.h terminal.h gdb_string.h
+
+remote-mips.o: remote-mips.c $(wait_h) $(defs_h) $(gdbcmd_h) \
+ $(gdbcore_h) $(inferior_h) serial.h symfile.h target.h
+
+remote-mm.o: remote-mm.c $(bfd_h) $(wait_h) $(defs_h) $(inferior_h) \
+ minimon.h target.h terminal.h gdb_string.h
+
+remote-nindy.o: remote-nindy.c $(floatformat_h) $(wait_h) $(command_h) \
+ $(defs_h) $(gdbcore_h) $(inferior_h) \
+ nindy-share/env.h nindy-share/stop.h $(remote_utils_h) \
+ symfile.h
+
+remote-os9k.o: remote-os9k.c $(defs_h) $(gdbcore_h) $(wait_h) \
+ $(command_h) monitor.h $(remote_utils_h) $(symtab_h) symfile.h \
+ objfiles.h gdb-stabs.h gdb_string.h
+
+remote-sds.o: remote-sds.c $(bfd_h) $(wait_h) $(defs_h) $(gdbcmd_h) \
+ $(inferior_h) $(remote_utils_h) symfile.h terminal.h gdb_string.h
+
+remote-sim.o: remote-sim.c $(wait_h) $(defs_h) $(gdbcore_h) \
+ $(inferior_h) target.h terminal.h gdb_string.h \
+ $(INCLUDE_DIR)/callback.h
+
+remote-st.o: remote-st.c $(wait_h) $(defs_h) $(gdbcore_h) serial.h \
+ target.h gdb_string.h
+
+remote-udi.o: remote-udi.c $(bfd_h) $(wait_h) $(defs_h) $(gdbcmd_h) \
+ $(inferior_h) target.h terminal.h $(udiheaders) gdb_string.h
+
+remote-vx.o: remote-vx.c $(wait_h) complaints.h $(defs_h) $(gdbcmd_h) \
+ $(gdbcore_h) $(inferior_h) target.h vx-share/dbgRpcLib.h \
+ vx-share/ptrace.h vx-share/xdr_ld.h vx-share/xdr_ptrace.h \
+ vx-share/xdr_rdb.h gdb-stabs.h objfiles.h symfile.h $(bfd_h) \
+ gdb_string.h
+
+remote-vx29k.o: remote-vx29k.c $(wait_h) complaints.h $(defs_h) $(gdbcmd_h) \
+ $(gdbcore_h) $(inferior_h) target.h vx-share/dbgRpcLib.h \
+ vx-share/ptrace.h vx-share/xdr_ld.h vx-share/xdr_ptrace.h \
+ vx-share/xdr_rdb.h gdb_string.h
+
+ocd.o: ocd.c ocd.h $(gdbcore_h) gdb_string.h $(frame_h) $(inferior_h) \
+ $(bfd_h) symfile.h target.h $(wait_h) $(gdbcmd_h) objfiles.h \
+ gdb-stabs.h $(dcache_h) serial.h
+
+remote-utils.o: remote-utils.c $(defs_h) $(gdbcmd_h) $(gdbcore_h) \
+ $(inferior_h) $(remote_utils_h) gdb_string.h
+
+remote.o: remote.c $(bfd_h) $(wait_h) $(defs_h) $(gdbcmd_h) \
+ $(inferior_h) $(remote_utils_h) symfile.h terminal.h gdb_string.h
+
+remote-nrom.o: remote-nrom.c $(bfd_h) $(wait_h) $(defs_h) $(gdbcmd_h) \
+ $(inferior_h) $(remote_utils_h) symfile.h terminal.h
+
+rom68k-rom.o: rom68k-rom.c monitor.h $(bfd_h) $(wait_h) $(defs_h) $(gdbcmd_h) \
+ $(inferior_h) target.h serial.h terminal.h
+
+rs6000-nat.o: rs6000-nat.c $(bfd_h) $(defs_h) $(inferior_h) target.h \
+ xcoffsolib.h
+
+rs6000-tdep.o: rs6000-tdep.c $(defs_h) $(gdbcore_h) $(inferior_h) \
+ target.h xcoffsolib.h
+
+scm-exp.o: $(defs_h) $(value_h) parser-defs.h language.h c-lang.h \
+ scm-lang.h scm-tags.h
+
+scm-lang.o: $(defs_h) $(value_h) parser-defs.h language.h c-lang.h \
+ scm-lang.h scm-tags.h gdb_string.h $(gdbcore_h)
+
+scm-valprint.o: $(defs_h) $(value_h) parser-defs.h language.h \
+ scm-lang.h valprint.h $(gdbcore_h)
+
+ser-go32.o: ser-go32.c $(defs_h) serial.h
+
+ser-mac.o: ser-mac.c $(defs_h) serial.h signals.h
+
+ser-ocd.o: ser-ocd.c $(defs_h) serial.h signals.h gdb_string.h
+
+ser-tcp.o: ser-tcp.c $(defs_h) serial.h signals.h gdb_string.h
+
+ser-unix.o: ser-unix.c $(defs_h) serial.h
+
+serial.o: serial.c $(defs_h) serial.h gdb_string.h
+
+sh-tdep.o: sh-tdep.c $(bfd_h) $(dis-asm_h) \
+ $(srcdir)/../opcodes/sh-opc.h $(defs_h) $(expression_h) $(frame_h) \
+ $(gdbcmd_h) $(gdbtypes_h) $(symtab_h) $(value_h)
+
+sh3-rom.o: sh3-rom.c monitor.h $(bfd_h) $(wait_h) $(defs_h) $(gdbcmd_h) \
+ $(inferior_h) target.h serial.h terminal.h
+
+mon960-rom.o: mon960-rom.c monitor.h $(bfd_h) $(wait_h) $(defs_h) $(gdbcmd_h) \
+ $(inferior_h) target.h serial.h terminal.h
+
+solib.o: solib.c $(command_h) $(defs_h) $(gdbcore_h) $(inferior_h) \
+ objfiles.h gnu-regex.h symfile.h target.h gdb_string.h
+
+source.o: source.c $(defs_h) $(expression_h) $(frame_h) $(gdbcmd_h) \
+ $(gdbcore_h) language.h objfiles.h gnu-regex.h symfile.h $(symtab_h) \
+ gdb_string.h
+
+sparc-nat.o: sparc-nat.c $(bfd_h) $(defs_h) $(inferior_h) $(gdbcore_h) \
+ target.h
+
+sparc-tdep.o: sparc-tdep.c $(floatformat_h) $(defs_h) $(gdbcore_h) \
+ $(inferior_h) objfiles.h symfile.h target.h gdb_string.h
+
+sparcl-tdep.o: sparcl-tdep.c $(defs_h) $(gdbcore_h) target.h
+
+dsrec.o: dsrec.c $(defs_h) srec.h
+
+stabsread.o: stabsread.c $(bfd_h) $(INCLUDE_DIR)/aout/stab.def \
+ $(INCLUDE_DIR)/aout/stab_gnu.h buildsym.h complaints.h $(defs_h) \
+ $(gdbtypes_h) objfiles.h stabsread.h symfile.h $(symtab_h) \
+ gdb_string.h
+
+stack.o: stack.c $(defs_h) $(gdbcmd_h) $(gdbcore_h) $(inferior_h) \
+ language.h target.h gdb_string.h
+
+ax-general.o: ax-general.c $(ax_h) $(defs_h)
+ax-gdb.o: ax-gdb.c $(defs_h) $(symtab_h) symfile.h $(gdbtypes_h) \
+ $(value_h) $(expression_h) $(command_h) $(ax_h) $(gdbcmd_h) ax-gdb.h
+
+sun3-nat.o: sun3-nat.c $(defs_h) $(gdbcore_h) $(inferior_h)
+
+sun386-nat.o: sun386-nat.c $(defs_h) $(inferior_h) $(gdbcore_h)
+
+symfile.o: symfile.c $(breakpoint_h) complaints.h $(defs_h) \
+ $(expression_h) $(gdbcmd_h) $(gdbcore_h) $(gdbtypes_h) \
+ language.h objfiles.h symfile.h $(symtab_h) target.h \
+ gdb_string.h
+
+symm-tdep.o: symm-tdep.c $(defs_h) $(gdbcore_h) $(inferior_h)
+
+symm-nat.o: symm-nat.c $(defs_h) $(gdbcore_h) $(inferior_h)
+
+symmisc.o: symmisc.c $(bfd_h) $(breakpoint_h) $(command_h) $(defs_h) \
+ $(expression_h) $(gdbtypes_h) language.h objfiles.h symfile.h \
+ $(symtab_h) gdb_string.h
+
+symtab.o: symtab.c call-cmds.h $(defs_h) $(expression_h) $(frame_h) \
+ $(gdbcmd_h) $(gdbcore_h) $(gdbtypes_h) language.h objfiles.h \
+ gnu-regex.h symfile.h $(symtab_h) target.h $(value_h) \
+ gdb_string.h
+
+tahoe-tdep.o: tahoe-tdep.c $(OP_INCLUDE)/tahoe.h $(defs_h) \
+ $(symtab_h)
+
+target.o: target.c $(bfd_h) $(defs_h) $(gdbcmd_h) $(inferior_h) \
+ objfiles.h symfile.h target.h gdb_string.h
+
+thread.o: thread.c $(defs_h) gdbthread.h $(gdbcmd_h)
+
+top.o: top.c top.h $(bfd_h) $(getopt_h) $(readline_headers) call-cmds.h \
+ $(defs_h) $(gdbcmd_h) $(inferior_h) language.h signals.h \
+ $(remote_utils_h) gdb_string.h
+
+typeprint.o: typeprint.c $(defs_h) $(expression_h) $(gdbcmd_h) \
+ $(gdbcore_h) $(gdbtypes_h) language.h $(symtab_h) target.h \
+ $(value_h) gdb_string.h
+
+ultra3-nat.o: ultra3-nat.c $(defs_h) $(gdbcore_h) $(inferior_h)
+
+ultra3-xdep.o: ultra3-xdep.c $(defs_h) $(gdbcore_h) $(inferior_h)
+
+umax-xdep.o: umax-xdep.c $(defs_h) $(gdbcore_h) $(inferior_h)
+
+utils.o: utils.c $(bfd_h) $(defs_h) $(expression_h) $(gdbcmd_h) \
+ language.h signals.h target.h terminal.h $(readline_headers) \
+ gdb_string.h
+
+valarith.o: valarith.c $(bfd_h) $(defs_h) $(expression_h) \
+ $(gdbtypes_h) language.h $(symtab_h) target.h $(value_h) \
+ gdb_string.h
+
+valops.o: valops.c $(defs_h) $(gdbcore_h) $(inferior_h) target.h \
+ gdb_string.h
+
+valprint.o: valprint.c $(defs_h) $(expression_h) $(gdbcmd_h) \
+ $(gdbcore_h) $(gdbtypes_h) language.h $(symtab_h) target.h \
+ $(value_h) gdb_string.h valprint.h
+
+values.o: values.c $(defs_h) $(expression_h) $(frame_h) $(gdbcmd_h) \
+ $(gdbcore_h) $(gdbtypes_h) $(symtab_h) target.h $(value_h) \
+ gdb_string.h scm-lang.h
+
+vax-tdep.o: vax-tdep.c $(OP_INCLUDE)/vax.h $(defs_h) $(symtab_h)
+
+w65-tdep.o : w65-tdep.c $(gdbcore_h)
+
+win32-nat.o: win32-nat.c $(gdbcmd_h) $(gdbcore_h) $(inferior_h) $(defs_h) \
+ gdb_string.h
+
+xdr_ld.o: vx-share/xdr_ld.c $(defs_h) vx-share/vxTypes.h \
+ vx-share/vxWorks.h vx-share/xdr_ld.h
+ $(CC) -c $(INTERNAL_CFLAGS) $(srcdir)/vx-share/xdr_ld.c
+
+xdr_ptrace.o: vx-share/xdr_ptrace.c $(defs_h) vx-share/vxTypes.h \
+ vx-share/vxWorks.h vx-share/xdr_ptrace.h
+ $(CC) -c $(INTERNAL_CFLAGS) $(srcdir)/vx-share/xdr_ptrace.c
+
+xdr_rdb.o: vx-share/xdr_rdb.c $(defs_h) vx-share/vxTypes.h \
+ vx-share/vxWorks.h vx-share/xdr_rdb.h
+ $(CC) -c $(INTERNAL_CFLAGS) $(srcdir)/vx-share/xdr_rdb.c
+
+xcoffread.o: xcoffread.c $(bfd_h) $(INCLUDE_DIR)/aout/stab.def \
+ $(INCLUDE_DIR)/aout/stab_gnu.h $(INCLUDE_DIR)/coff/internal.h \
+ $(INCLUDE_DIR)/coff/rs6000.h $(BFD_SRC)/libcoff.h buildsym.h \
+ complaints.h $(defs_h) $(gdbtypes_h) objfiles.h stabsread.h symfile.h \
+ $(symtab_h) partial-stab.h gdb_string.h
+
+xcoffsolib.o: xcoffsolib.c $(bfd_h) $(defs_h) xcoffsolib.h
+
+z8k-tdep.o: z8k-tdep.c $(bfd_h) $(dis-asm_h) $(defs_h) $(frame_h) \
+ $(gdbcmd_h) $(gdbtypes_h) $(symtab_h) $(gdbcore_h)
+
+c-exp.tab.o: c-exp.tab.c c-lang.h $(defs_h) $(expression_h) \
+ $(gdbtypes_h) language.h parser-defs.h $(symtab_h) $(value_h) \
+ $(bfd_h) objfiles.h symfile.h
+
+jv-exp.tab.o: jv-exp.tab.c jv-lang.h $(defs_h) $(expression_h) \
+ $(gdbtypes_h) language.h parser-defs.h $(symtab_h) $(value_h) \
+ $(bfd_h) objfiles.h symfile.h
+
+f-exp.tab.o: f-exp.tab.c f-lang.h $(defs_h) $(expression_h) \
+ language.h parser-defs.h $(value_h) $(bfd_h) objfiles.h symfile.h
+
+m2-exp.tab.o: m2-exp.tab.c $(defs_h) $(expression_h) $(gdbtypes_h) \
+ language.h m2-lang.h parser-defs.h $(symtab_h) $(value_h) \
+ $(bfd_h) objfiles.h symfile.h
+
+### end of the gdb Makefile.in.
diff --git a/gdb/NEWS b/gdb/NEWS
new file mode 100644
index 00000000000..e6aaba318a1
--- /dev/null
+++ b/gdb/NEWS
@@ -0,0 +1,1611 @@
+ What has changed in GDB?
+ (Organized release by release)
+
+*** Changes in GDB-4.18:
+
+* New native configurations
+
+HP-UX 10.20 hppa*-*-hpux10.20
+HP-UX 11.x hppa*-*-hpux11.0*
+M68K Linux m68*-*-linux*
+
+* New targets
+
+Fujitsu FR30 fr30-*-elf*
+Intel StrongARM strongarm-*-*
+Mitsubishi D30V d30v-*-*
+
+* OBSOLETE configurations
+
+Gould PowerNode, NP1 np1-*-*, pn-*-*
+
+Configurations that have been declared obsolete will be commented out,
+but the code will be left in place. If there is no activity to revive
+these configurations before the next release of GDB, the sources will
+be permanently REMOVED.
+
+* ANSI/ISO C
+
+As a compatibility experiment, GDB's source files buildsym.h and
+buildsym.c have been converted to pure standard C, no longer
+containing any K&R compatibility code. We believe that all systems in
+use today either come with a standard C compiler, or have a GCC port
+available. If this is not true, please report the affected
+configuration to bug-gdb@gnu.org immediately. See the README file for
+information about getting a standard C compiler if you don't have one
+already.
+
+* Readline 2.2
+
+GDB now uses readline 2.2.
+
+* set extension-language
+
+You can now control the mapping between filename extensions and source
+languages by using the `set extension-language' command. For instance,
+you can ask GDB to treat .c files as C++ by saying
+ set extension-language .c c++
+The command `info extensions' lists all of the recognized extensions
+and their associated languages.
+
+* Setting processor type for PowerPC and RS/6000
+
+When GDB is configured for a powerpc*-*-* or an rs6000*-*-* target,
+you can use the `set processor' command to specify what variant of the
+PowerPC family you are debugging. The command
+
+ set processor NAME
+
+sets the PowerPC/RS6000 variant to NAME. GDB knows about the
+following PowerPC and RS6000 variants:
+
+ ppc-uisa PowerPC UISA - a PPC processor as viewed by user-level code
+ rs6000 IBM RS6000 ("POWER") architecture, user-level view
+ 403 IBM PowerPC 403
+ 403GC IBM PowerPC 403GC
+ 505 Motorola PowerPC 505
+ 860 Motorola PowerPC 860 or 850
+ 601 Motorola PowerPC 601
+ 602 Motorola PowerPC 602
+ 603 Motorola/IBM PowerPC 603 or 603e
+ 604 Motorola PowerPC 604 or 604e
+ 750 Motorola/IBM PowerPC 750 or 750
+
+At the moment, this command just tells GDB what to name the
+special-purpose processor registers. Since almost all the affected
+registers are inaccessible to user-level programs, this command is
+only useful for remote debugging in its present form.
+
+* HP-UX support
+
+Thanks to a major code donation from Hewlett-Packard, GDB now has much
+more extensive support for HP-UX. Added features include shared
+library support, kernel threads and hardware watchpoints for 11.00,
+support for HP's ANSI C and C++ compilers, and a compatibility mode
+for xdb and dbx commands.
+
+* Catchpoints
+
+HP's donation includes the new concept of catchpoints, which is a
+generalization of the old catch command. On HP-UX, it is now possible
+to catch exec, fork, and vfork, as well as library loading.
+
+This means that the existing catch command has changed; its first
+argument now specifies the type of catch to be set up. See the
+output of "help catch" for a list of catchpoint types.
+
+* Debugging across forks
+
+On HP-UX, you can choose which process to debug when a fork() happens
+in the inferior.
+
+* TUI
+
+HP has donated a curses-based terminal user interface (TUI). To get
+it, build with --enable-tui. Although this can be enabled for any
+configuration, at present it only works for native HP debugging.
+
+* GDB remote protocol additions
+
+A new protocol packet 'X' that writes binary data is now available.
+Default behavior is to try 'X', then drop back to 'M' if the stub
+fails to respond. The settable variable `remotebinarydownload'
+allows explicit control over the use of 'X'.
+
+For 64-bit targets, the memory packets ('M' and 'm') can now contain a
+full 64-bit address. The command
+
+ set remoteaddresssize 32
+
+can be used to revert to the old behaviour. For existing remote stubs
+the change should not be noticed, as the additional address information
+will be discarded.
+
+In order to assist in debugging stubs, you may use the maintenance
+command `packet' to send any text string to the stub. For instance,
+
+ maint packet heythere
+
+sends the packet "$heythere#<checksum>". Note that it is very easy to
+disrupt a debugging session by sending the wrong packet at the wrong
+time.
+
+The compare-sections command allows you to compare section data on the
+target to what is in the executable file without uploading or
+downloading, by comparing CRC checksums.
+
+* Tracing can collect general expressions
+
+You may now collect general expressions at tracepoints. This requires
+further additions to the target-side stub; see tracepoint.c and
+doc/agentexpr.texi for further details.
+
+* mask-address variable for Mips
+
+For Mips targets, you may control the zeroing of the upper 32 bits of
+a 64-bit address by entering `set mask-address on'. This is mainly
+of interest to users of embedded R4xxx and R5xxx processors.
+
+* Higher serial baud rates
+
+GDB's serial code now allows you to specify baud rates 57600, 115200,
+230400, and 460800 baud. (Note that your host system may not be able
+to achieve all of these rates.)
+
+* i960 simulator
+
+The i960 configuration now includes an initial implementation of a
+builtin simulator, contributed by Jim Wilson.
+
+
+*** Changes in GDB-4.17:
+
+* New native configurations
+
+Alpha GNU/Linux alpha*-*-linux*
+Unixware 2.x i[3456]86-unixware2*
+Irix 6.x mips*-sgi-irix6*
+PowerPC GNU/Linux powerpc-*-linux*
+PowerPC Solaris powerpcle-*-solaris*
+Sparc GNU/Linux sparc-*-linux*
+Motorola sysV68 R3V7.1 m68k-motorola-sysv
+
+* New targets
+
+Argonaut Risc Chip (ARC) arc-*-*
+Hitachi H8/300S h8300*-*-*
+Matsushita MN10200 w/simulator mn10200-*-*
+Matsushita MN10300 w/simulator mn10300-*-*
+MIPS NEC VR4100 mips64*vr4100*{,el}-*-elf*
+MIPS NEC VR5000 mips64*vr5000*{,el}-*-elf*
+MIPS Toshiba TX39 mips64*tx39*{,el}-*-elf*
+Mitsubishi D10V w/simulator d10v-*-*
+Mitsubishi M32R/D w/simulator m32r-*-elf*
+Tsqware Sparclet sparclet-*-*
+NEC V850 w/simulator v850-*-*
+
+* New debugging protocols
+
+ARM with RDI protocol arm*-*-*
+M68K with dBUG monitor m68*-*-{aout,coff,elf}
+DDB and LSI variants of PMON protocol mips*-*-*
+PowerPC with DINK32 monitor powerpc{,le}-*-eabi
+PowerPC with SDS protocol powerpc{,le}-*-eabi
+Macraigor OCD (Wiggler) devices powerpc{,le}-*-eabi
+
+* DWARF 2
+
+All configurations can now understand and use the DWARF 2 debugging
+format. The choice is automatic, if the symbol file contains DWARF 2
+information.
+
+* Java frontend
+
+GDB now includes basic Java language support. This support is
+only useful with Java compilers that produce native machine code.
+
+* solib-absolute-prefix and solib-search-path
+
+For SunOS and SVR4 shared libraries, you may now set the prefix for
+loading absolute shared library symbol files, and the search path for
+locating non-absolute shared library symbol files.
+
+* Live range splitting
+
+GDB can now effectively debug code for which GCC has performed live
+range splitting as part of its optimization. See gdb/doc/LRS for
+more details on the expected format of the stabs information.
+
+* Hurd support
+
+GDB's support for the GNU Hurd, including thread debugging, has been
+updated to work with current versions of the Hurd.
+
+* ARM Thumb support
+
+GDB's ARM target configuration now handles the ARM7T (Thumb) 16-bit
+instruction set. ARM GDB automatically detects when Thumb
+instructions are in use, and adjusts disassembly and backtracing
+accordingly.
+
+* MIPS16 support
+
+GDB's MIPS target configurations now handle the MIP16 16-bit
+instruction set.
+
+* Overlay support
+
+GDB now includes support for overlays; if an executable has been
+linked such that multiple sections are based at the same address, GDB
+will decide which section to use for symbolic info. You can choose to
+control the decision manually, using overlay commands, or implement
+additional target-side support and use "overlay load-target" to bring
+in the overlay mapping. Do "help overlay" for more detail.
+
+* info symbol
+
+The command "info symbol <address>" displays information about
+the symbol at the specified address.
+
+* Trace support
+
+The standard remote protocol now includes an extension that allows
+asynchronous collection and display of trace data. This requires
+extensive support in the target-side debugging stub. Tracing mode
+includes a new interaction mode in GDB and new commands: see the
+file tracepoint.c for more details.
+
+* MIPS simulator
+
+Configurations for embedded MIPS now include a simulator contributed
+by Cygnus Solutions. The simulator supports the instruction sets
+of most MIPS variants.
+
+* Sparc simulator
+
+Sparc configurations may now include the ERC32 simulator contributed
+by the European Space Agency. The simulator is not built into
+Sparc targets by default; configure with --enable-sim to include it.
+
+* set architecture
+
+For target configurations that may include multiple variants of a
+basic architecture (such as MIPS and SH), you may now set the
+architecture explicitly. "set arch" sets, "info arch" lists
+the possible architectures.
+
+*** Changes in GDB-4.16:
+
+* New native configurations
+
+Windows 95, x86 Windows NT i[345]86-*-cygwin32
+M68K NetBSD m68k-*-netbsd*
+PowerPC AIX 4.x powerpc-*-aix*
+PowerPC MacOS powerpc-*-macos*
+PowerPC Windows NT powerpcle-*-cygwin32
+RS/6000 AIX 4.x rs6000-*-aix4*
+
+* New targets
+
+ARM with RDP protocol arm-*-*
+I960 with MON960 i960-*-coff
+MIPS VxWorks mips*-*-vxworks*
+MIPS VR4300 with PMON mips64*vr4300{,el}-*-elf*
+PowerPC with PPCBUG monitor powerpc{,le}-*-eabi*
+Hitachi SH3 sh-*-*
+Matra Sparclet sparclet-*-*
+
+* PowerPC simulator
+
+The powerpc-eabi configuration now includes the PSIM simulator,
+contributed by Andrew Cagney, with assistance from Mike Meissner.
+PSIM is a very elaborate model of the PowerPC, including not only
+basic instruction set execution, but also details of execution unit
+performance and I/O hardware. See sim/ppc/README for more details.
+
+* Solaris 2.5
+
+GDB now works with Solaris 2.5.
+
+* Windows 95/NT native
+
+GDB will now work as a native debugger on Windows 95 and Windows NT.
+To build it from source, you must use the "gnu-win32" environment,
+which uses a DLL to emulate enough of Unix to run the GNU tools.
+Further information, binaries, and sources are available at
+ftp.cygnus.com, under pub/gnu-win32.
+
+* dont-repeat command
+
+If a user-defined command includes the command `dont-repeat', then the
+command will not be repeated if the user just types return. This is
+useful if the command is time-consuming to run, so that accidental
+extra keystrokes don't run the same command many times.
+
+* Send break instead of ^C
+
+The standard remote protocol now includes an option to send a break
+rather than a ^C to the target in order to interrupt it. By default,
+GDB will send ^C; to send a break, set the variable `remotebreak' to 1.
+
+* Remote protocol timeout
+
+The standard remote protocol includes a new variable `remotetimeout'
+that allows you to set the number of seconds before GDB gives up trying
+to read from the target. The default value is 2.
+
+* Automatic tracking of dynamic object loading (HPUX and Solaris only)
+
+By default GDB will automatically keep track of objects as they are
+loaded and unloaded by the dynamic linker. By using the command `set
+stop-on-solib-events 1' you can arrange for GDB to stop the inferior
+when shared library events occur, thus allowing you to set breakpoints
+in shared libraries which are explicitly loaded by the inferior.
+
+Note this feature does not work on hpux8. On hpux9 you must link
+/usr/lib/end.o into your program. This feature should work
+automatically on hpux10.
+
+* Irix 5.x hardware watchpoint support
+
+Irix 5 configurations now support the use of hardware watchpoints.
+
+* Mips protocol "SYN garbage limit"
+
+When debugging a Mips target using the `target mips' protocol, you
+may set the number of characters that GDB will ignore by setting
+the `syn-garbage-limit'. A value of -1 means that GDB will ignore
+every character. The default value is 1050.
+
+* Recording and replaying remote debug sessions
+
+If you set `remotelogfile' to the name of a file, gdb will write to it
+a recording of a remote debug session. This recording may then be
+replayed back to gdb using "gdbreplay". See gdbserver/README for
+details. This is useful when you have a problem with GDB while doing
+remote debugging; you can make a recording of the session and send it
+to someone else, who can then recreate the problem.
+
+* Speedups for remote debugging
+
+GDB includes speedups for downloading and stepping MIPS systems using
+the IDT monitor, fast downloads to the Hitachi SH E7000 emulator,
+and more efficient S-record downloading.
+
+* Memory use reductions and statistics collection
+
+GDB now uses less memory and reports statistics about memory usage.
+Try the `maint print statistics' command, for example.
+
+*** Changes in GDB-4.15:
+
+* Psymtabs for XCOFF
+
+The symbol reader for AIX GDB now uses partial symbol tables. This
+can greatly improve startup time, especially for large executables.
+
+* Remote targets use caching
+
+Remote targets now use a data cache to speed up communication with the
+remote side. The data cache could lead to incorrect results because
+it doesn't know about volatile variables, thus making it impossible to
+debug targets which use memory mapped I/O devices. `set remotecache
+off' turns the the data cache off.
+
+* Remote targets may have threads
+
+The standard remote protocol now includes support for multiple threads
+in the target system, using new protocol commands 'H' and 'T'. See
+gdb/remote.c for details.
+
+* NetROM support
+
+If GDB is configured with `--enable-netrom', then it will include
+support for the NetROM ROM emulator from XLNT Designs. The NetROM
+acts as though it is a bank of ROM on the target board, but you can
+write into it over the network. GDB's support consists only of
+support for fast loading into the emulated ROM; to debug, you must use
+another protocol, such as standard remote protocol. The usual
+sequence is something like
+
+ target nrom <netrom-hostname>
+ load <prog>
+ target remote <netrom-hostname>:1235
+
+* Macintosh host
+
+GDB now includes support for the Apple Macintosh, as a host only. It
+may be run as either an MPW tool or as a standalone application, and
+it can debug through the serial port. All the usual GDB commands are
+available, but to the target command, you must supply "serial" as the
+device type instead of "/dev/ttyXX". See mpw-README in the main
+directory for more information on how to build. The MPW configuration
+scripts */mpw-config.in support only a few targets, and only the
+mips-idt-ecoff target has been tested.
+
+* Autoconf
+
+GDB configuration now uses autoconf. This is not user-visible,
+but does simplify configuration and building.
+
+* hpux10
+
+GDB now supports hpux10.
+
+*** Changes in GDB-4.14:
+
+* New native configurations
+
+x86 FreeBSD i[345]86-*-freebsd
+x86 NetBSD i[345]86-*-netbsd
+NS32k NetBSD ns32k-*-netbsd
+Sparc NetBSD sparc-*-netbsd
+
+* New targets
+
+A29K VxWorks a29k-*-vxworks
+HP PA PRO embedded (WinBond W89K & Oki OP50N) hppa*-*-pro*
+CPU32 EST-300 emulator m68*-*-est*
+PowerPC ELF powerpc-*-elf
+WDC 65816 w65-*-*
+
+* Alpha OSF/1 support for procfs
+
+GDB now supports procfs under OSF/1-2.x and higher, which makes it
+possible to attach to running processes. As the mounting of the /proc
+filesystem is optional on the Alpha, GDB automatically determines
+the availability of /proc during startup. This can lead to problems
+if /proc is unmounted after GDB has been started.
+
+* Arguments to user-defined commands
+
+User commands may accept up to 10 arguments separated by whitespace.
+Arguments are accessed within the user command via $arg0..$arg9. A
+trivial example:
+define adder
+ print $arg0 + $arg1 + $arg2
+
+To execute the command use:
+adder 1 2 3
+
+Defines the command "adder" which prints the sum of its three arguments.
+Note the arguments are text substitutions, so they may reference variables,
+use complex expressions, or even perform inferior function calls.
+
+* New `if' and `while' commands
+
+This makes it possible to write more sophisticated user-defined
+commands. Both commands take a single argument, which is the
+expression to evaluate, and must be followed by the commands to
+execute, one per line, if the expression is nonzero, the list being
+terminated by the word `end'. The `if' command list may include an
+`else' word, which causes the following commands to be executed only
+if the expression is zero.
+
+* Fortran source language mode
+
+GDB now includes partial support for Fortran 77. It will recognize
+Fortran programs and can evaluate a subset of Fortran expressions, but
+variables and functions may not be handled correctly. GDB will work
+with G77, but does not yet know much about symbols emitted by other
+Fortran compilers.
+
+* Better HPUX support
+
+Most debugging facilities now work on dynamic executables for HPPAs
+running hpux9 or later. You can attach to running dynamically linked
+processes, but by default the dynamic libraries will be read-only, so
+for instance you won't be able to put breakpoints in them. To change
+that behavior do the following before running the program:
+
+ adb -w a.out
+ __dld_flags?W 0x5
+ control-d
+
+This will cause the libraries to be mapped private and read-write.
+To revert to the normal behavior, do this:
+
+ adb -w a.out
+ __dld_flags?W 0x4
+ control-d
+
+You cannot set breakpoints or examine data in the library until after
+the library is loaded if the function/data symbols do not have
+external linkage.
+
+GDB can now also read debug symbols produced by the HP C compiler on
+HPPAs (sorry, no C++, Fortran or 68k support).
+
+* Target byte order now dynamically selectable
+
+You can choose which byte order to use with a target system, via the
+commands "set endian big" and "set endian little", and you can see the
+current setting by using "show endian". You can also give the command
+"set endian auto", in which case GDB will use the byte order
+associated with the executable. Currently, only embedded MIPS
+configurations support dynamic selection of target byte order.
+
+* New DOS host serial code
+
+This version uses DPMI interrupts to handle buffered I/O, so you
+no longer need to run asynctsr when debugging boards connected to
+a PC's serial port.
+
+*** Changes in GDB-4.13:
+
+* New "complete" command
+
+This lists all the possible completions for the rest of the line, if it
+were to be given as a command itself. This is intended for use by emacs.
+
+* Trailing space optional in prompt
+
+"set prompt" no longer adds a space for you after the prompt you set. This
+allows you to set a prompt which ends in a space or one that does not.
+
+* Breakpoint hit counts
+
+"info break" now displays a count of the number of times the breakpoint
+has been hit. This is especially useful in conjunction with "ignore"; you
+can ignore a large number of breakpoint hits, look at the breakpoint info
+to see how many times the breakpoint was hit, then run again, ignoring one
+less than that number, and this will get you quickly to the last hit of
+that breakpoint.
+
+* Ability to stop printing at NULL character
+
+"set print null-stop" will cause GDB to stop printing the characters of
+an array when the first NULL is encountered. This is useful when large
+arrays actually contain only short strings.
+
+* Shared library breakpoints
+
+In SunOS 4.x, SVR4, and Alpha OSF/1 configurations, you can now set
+breakpoints in shared libraries before the executable is run.
+
+* Hardware watchpoints
+
+There is a new hardware breakpoint for the watch command for sparclite
+targets. See gdb/sparclite/hw_breakpoint.note.
+
+Hardware watchpoints are also now supported under Linux.
+
+* Annotations
+
+Annotations have been added. These are for use with graphical interfaces,
+and are still experimental. Currently only gdba.el uses these.
+
+* Improved Irix 5 support
+
+GDB now works properly with Irix 5.2.
+
+* Improved HPPA support
+
+GDB now works properly with the latest GCC and GAS.
+
+* New native configurations
+
+Sequent PTX4 i[34]86-sequent-ptx4
+HPPA running OSF/1 hppa*-*-osf*
+Atari TT running SVR4 m68*-*-sysv4*
+RS/6000 LynxOS rs6000-*-lynxos*
+
+* New targets
+
+OS/9000 i[34]86-*-os9k
+MIPS R4000 mips64*{,el}-*-{ecoff,elf}
+Sparc64 sparc64-*-*
+
+* Hitachi SH7000 and E7000-PC ICE support
+
+There is now support for communicating with the Hitachi E7000-PC ICE.
+This is available automatically when GDB is configured for the SH.
+
+* Fixes
+
+As usual, a variety of small fixes and improvements, both generic
+and configuration-specific. See the ChangeLog for more detail.
+
+*** Changes in GDB-4.12:
+
+* Irix 5 is now supported
+
+* HPPA support
+
+GDB-4.12 on the HPPA has a number of changes which make it unable
+to debug the output from the currently released versions of GCC and
+GAS (GCC 2.5.8 and GAS-2.2 or PAGAS-1.36). Until the next major release
+of GCC and GAS, versions of these tools designed to work with GDB-4.12
+can be retrieved via anonymous ftp from jaguar.cs.utah.edu:/dist.
+
+
+*** Changes in GDB-4.11:
+
+* User visible changes:
+
+* Remote Debugging
+
+The "set remotedebug" option is now consistent between the mips remote
+target, remote targets using the gdb-specific protocol, UDI (AMD's
+debug protocol for the 29k) and the 88k bug monitor. It is now an
+integer specifying a debug level (normally 0 or 1, but 2 means more
+debugging info for the mips target).
+
+* DEC Alpha native support
+
+GDB now works on the DEC Alpha. GCC 2.4.5 does not produce usable
+debug info, but GDB works fairly well with the DEC compiler and should
+work with a future GCC release. See the README file for a few
+Alpha-specific notes.
+
+* Preliminary thread implementation
+
+GDB now has preliminary thread support for both SGI/Irix and LynxOS.
+
+* LynxOS native and target support for 386
+
+This release has been hosted on LynxOS 2.2, and also can be configured
+to remotely debug programs running under LynxOS (see gdb/gdbserver/README
+for details).
+
+* Improvements in C++ mangling/demangling.
+
+This release has much better g++ debugging, specifically in name
+mangling/demangling, virtual function calls, print virtual table,
+call methods, ...etc.
+
+*** Changes in GDB-4.10:
+
+ * User visible changes:
+
+Remote debugging using the GDB-specific (`target remote') protocol now
+supports the `load' command. This is only useful if you have some
+other way of getting the stub to the target system, and you can put it
+somewhere in memory where it won't get clobbered by the download.
+
+Filename completion now works.
+
+When run under emacs mode, the "info line" command now causes the
+arrow to point to the line specified. Also, "info line" prints
+addresses in symbolic form (as well as hex).
+
+All vxworks based targets now support a user settable option, called
+vxworks-timeout. This option represents the number of seconds gdb
+should wait for responses to rpc's. You might want to use this if
+your vxworks target is, perhaps, a slow software simulator or happens
+to be on the far side of a thin network line.
+
+ * DEC alpha support
+
+This release contains support for using a DEC alpha as a GDB host for
+cross debugging. Native alpha debugging is not supported yet.
+
+
+*** Changes in GDB-4.9:
+
+ * Testsuite
+
+This is the first GDB release which is accompanied by a matching testsuite.
+The testsuite requires installation of dejagnu, which should be available
+via ftp from most sites that carry GNU software.
+
+ * C++ demangling
+
+'Cfront' style demangling has had its name changed to 'ARM' style, to
+emphasize that it was written from the specifications in the C++ Annotated
+Reference Manual, not necessarily to be compatible with AT&T cfront. Despite
+disclaimers, it still generated too much confusion with users attempting to
+use gdb with AT&T cfront.
+
+ * Simulators
+
+GDB now uses a standard remote interface to a simulator library.
+So far, the library contains simulators for the Zilog Z8001/2, the
+Hitachi H8/300, H8/500 and Super-H.
+
+ * New targets supported
+
+H8/300 simulator h8300-hitachi-hms or h8300hms
+H8/500 simulator h8500-hitachi-hms or h8500hms
+SH simulator sh-hitachi-hms or sh
+Z8000 simulator z8k-zilog-none or z8ksim
+IDT MIPS board over serial line mips-idt-ecoff
+
+Cross-debugging to GO32 targets is supported. It requires a custom
+version of the i386-stub.c module which is integrated with the
+GO32 memory extender.
+
+ * New remote protocols
+
+MIPS remote debugging protocol.
+
+ * New source languages supported
+
+This version includes preliminary support for Chill, a Pascal like language
+used by telecommunications companies. Chill support is also being integrated
+into the GNU compiler, but we don't know when it will be publically available.
+
+
+*** Changes in GDB-4.8:
+
+ * HP Precision Architecture supported
+
+GDB now supports HP PA-RISC machines running HPUX. A preliminary
+version of this support was available as a set of patches from the
+University of Utah. GDB does not support debugging of programs
+compiled with the HP compiler, because HP will not document their file
+format. Instead, you must use GCC (version 2.3.2 or later) and PA-GAS
+(as available from jaguar.cs.utah.edu:/dist/pa-gas.u4.tar.Z).
+
+Many problems in the preliminary version have been fixed.
+
+ * Faster and better demangling
+
+We have improved template demangling and fixed numerous bugs in the GNU style
+demangler. It can now handle type modifiers such as `static' or `const'. Wide
+character types (wchar_t) are now supported. Demangling of each symbol is now
+only done once, and is cached when the symbol table for a file is read in.
+This results in a small increase in memory usage for C programs, a moderate
+increase in memory usage for C++ programs, and a fantastic speedup in
+symbol lookups.
+
+`Cfront' style demangling still doesn't work with AT&T cfront. It was written
+from the specifications in the Annotated Reference Manual, which AT&T's
+compiler does not actually implement.
+
+ * G++ multiple inheritance compiler problem
+
+In the 2.3.2 release of gcc/g++, how the compiler resolves multiple
+inheritance lattices was reworked to properly discover ambiguities. We
+recently found an example which causes this new algorithm to fail in a
+very subtle way, producing bad debug information for those classes.
+The file 'gcc.patch' (in this directory) can be applied to gcc to
+circumvent the problem. A future GCC release will contain a complete
+fix.
+
+The previous G++ debug info problem (mentioned below for the gdb-4.7
+release) is fixed in gcc version 2.3.2.
+
+ * Improved configure script
+
+The `configure' script will now attempt to guess your system type if
+you don't supply a host system type. The old scheme of supplying a
+host system triplet is preferable over using this. All the magic is
+done in the new `config.guess' script. Examine it for details.
+
+We have also brought our configure script much more in line with the FSF's
+version. It now supports the --with-xxx options. In particular,
+`--with-minimal-bfd' can be used to make the GDB binary image smaller.
+The resulting GDB will not be able to read arbitrary object file formats --
+only the format ``expected'' to be used on the configured target system.
+We hope to make this the default in a future release.
+
+ * Documentation improvements
+
+There's new internal documentation on how to modify GDB, and how to
+produce clean changes to the code. We implore people to read it
+before submitting changes.
+
+The GDB manual uses new, sexy Texinfo conditionals, rather than arcane
+M4 macros. The new texinfo.tex is provided in this release. Pre-built
+`info' files are also provided. To build `info' files from scratch,
+you will need the latest `makeinfo' release, which will be available in
+a future texinfo-X.Y release.
+
+*NOTE* The new texinfo.tex can cause old versions of TeX to hang.
+We're not sure exactly which versions have this problem, but it has
+been seen in 3.0. We highly recommend upgrading to TeX version 3.141
+or better. If that isn't possible, there is a patch in
+`texinfo/tex3patch' that will modify `texinfo/texinfo.tex' to work
+around this problem.
+
+ * New features
+
+GDB now supports array constants that can be used in expressions typed in by
+the user. The syntax is `{element, element, ...}'. Ie: you can now type
+`print {1, 2, 3}', and it will build up an array in memory malloc'd in
+the target program.
+
+The new directory `gdb/sparclite' contains a program that demonstrates
+how the sparc-stub.c remote stub runs on a Fujitsu SPARClite processor.
+
+ * New native hosts supported
+
+HP/PA-RISC under HPUX using GNU tools hppa1.1-hp-hpux
+386 CPUs running SCO Unix 3.2v4 i386-unknown-sco3.2v4
+
+ * New targets supported
+
+AMD 29k family via UDI a29k-amd-udi or udi29k
+
+ * New file formats supported
+
+BFD now supports reading HP/PA-RISC executables (SOM file format?),
+HPUX core files, and SCO 3.2v2 core files.
+
+ * Major bug fixes
+
+Attaching to processes now works again; thanks for the many bug reports.
+
+We have also stomped on a bunch of core dumps caused by
+printf_filtered("%s") problems.
+
+We eliminated a copyright problem on the rpc and ptrace header files
+for VxWorks, which was discovered at the last minute during the 4.7
+release. You should now be able to build a VxWorks GDB.
+
+You can now interrupt gdb while an attached process is running. This
+will cause the attached process to stop, and give control back to GDB.
+
+We fixed problems caused by using too many file descriptors
+for reading symbols from object files and libraries. This was
+especially a problem for programs that used many (~100) shared
+libraries.
+
+The `step' command now only enters a subroutine if there is line number
+information for the subroutine. Otherwise it acts like the `next'
+command. Previously, `step' would enter subroutines if there was
+any debugging information about the routine. This avoids problems
+when using `cc -g1' on MIPS machines.
+
+ * Internal improvements
+
+GDB's internal interfaces have been improved to make it easier to support
+debugging of multiple languages in the future.
+
+GDB now uses a common structure for symbol information internally.
+Minimal symbols (derived from linkage symbols in object files), partial
+symbols (from a quick scan of debug information), and full symbols
+contain a common subset of information, making it easier to write
+shared code that handles any of them.
+
+ * New command line options
+
+We now accept --silent as an alias for --quiet.
+
+ * Mmalloc licensing
+
+The memory-mapped-malloc library is now licensed under the GNU Library
+General Public License.
+
+*** Changes in GDB-4.7:
+
+ * Host/native/target split
+
+GDB has had some major internal surgery to untangle the support for
+hosts and remote targets. Now, when you configure GDB for a remote
+target, it will no longer load in all of the support for debugging
+local programs on the host. When fully completed and tested, this will
+ensure that arbitrary host/target combinations are possible.
+
+The primary conceptual shift is to separate the non-portable code in
+GDB into three categories. Host specific code is required any time GDB
+is compiled on that host, regardless of the target. Target specific
+code relates to the peculiarities of the target, but can be compiled on
+any host. Native specific code is everything else: it can only be
+built when the host and target are the same system. Child process
+handling and core file support are two common `native' examples.
+
+GDB's use of /proc for controlling Unix child processes is now cleaner.
+It has been split out into a single module under the `target_ops' vector,
+plus two native-dependent functions for each system that uses /proc.
+
+ * New hosts supported
+
+HP/Apollo 68k (under the BSD domain) m68k-apollo-bsd or apollo68bsd
+386 CPUs running various BSD ports i386-unknown-bsd or 386bsd
+386 CPUs running SCO Unix i386-unknown-scosysv322 or i386sco
+
+ * New targets supported
+
+Fujitsu SPARClite sparclite-fujitsu-none or sparclite
+68030 and CPU32 m68030-*-*, m68332-*-*
+
+ * New native hosts supported
+
+386 CPUs running various BSD ports i386-unknown-bsd or 386bsd
+ (386bsd is not well tested yet)
+386 CPUs running SCO Unix i386-unknown-scosysv322 or sco
+
+ * New file formats supported
+
+BFD now supports COFF files for the Zilog Z8000 microprocessor. It
+supports reading of `a.out.adobe' object files, which are an a.out
+format extended with minimal information about multiple sections.
+
+ * New commands
+
+`show copying' is the same as the old `info copying'.
+`show warranty' is the same as `info warrantee'.
+These were renamed for consistency. The old commands continue to work.
+
+`info handle' is a new alias for `info signals'.
+
+You can now define pre-command hooks, which attach arbitrary command
+scripts to any command. The commands in the hook will be executed
+prior to the user's command. You can also create a hook which will be
+executed whenever the program stops. See gdb.texinfo.
+
+ * C++ improvements
+
+We now deal with Cfront style name mangling, and can even extract type
+info from mangled symbols. GDB can automatically figure out which
+symbol mangling style your C++ compiler uses.
+
+Calling of methods and virtual functions has been improved as well.
+
+ * Major bug fixes
+
+The crash that occured when debugging Sun Ansi-C compiled binaries is
+fixed. This was due to mishandling of the extra N_SO stabs output
+by the compiler.
+
+We also finally got Ultrix 4.2 running in house, and fixed core file
+support, with help from a dozen people on the net.
+
+John M. Farrell discovered that the reason that single-stepping was so
+slow on all of the Mips based platforms (primarily SGI and DEC) was
+that we were trying to demangle and lookup a symbol used for internal
+purposes on every instruction that was being stepped through. Changing
+the name of that symbol so that it couldn't be mistaken for a C++
+mangled symbol sped things up a great deal.
+
+Rich Pixley sped up symbol lookups in general by getting much smarter
+about when C++ symbol mangling is necessary. This should make symbol
+completion (TAB on the command line) much faster. It's not as fast as
+we'd like, but it's significantly faster than gdb-4.6.
+
+ * AMD 29k support
+
+A new user controllable variable 'call_scratch_address' can
+specify the location of a scratch area to be used when GDB
+calls a function in the target. This is necessary because the
+usual method of putting the scratch area on the stack does not work
+in systems that have separate instruction and data spaces.
+
+We integrated changes to support the 29k UDI (Universal Debugger
+Interface), but discovered at the last minute that we didn't have all
+of the appropriate copyright paperwork. We are working with AMD to
+resolve this, and hope to have it available soon.
+
+ * Remote interfaces
+
+We have sped up the remote serial line protocol, especially for targets
+with lots of registers. It now supports a new `expedited status' ('T')
+message which can be used in place of the existing 'S' status message.
+This allows the remote stub to send only the registers that GDB
+needs to make a quick decision about single-stepping or conditional
+breakpoints, eliminating the need to fetch the entire register set for
+each instruction being stepped through.
+
+The GDB remote serial protocol now implements a write-through cache for
+registers, only re-reading the registers if the target has run.
+
+There is also a new remote serial stub for SPARC processors. You can
+find it in gdb-4.7/gdb/sparc-stub.c. This was written to support the
+Fujitsu SPARClite processor, but will run on any stand-alone SPARC
+processor with a serial port.
+
+ * Configuration
+
+Configure.in files have become much easier to read and modify. A new
+`table driven' format makes it more obvious what configurations are
+supported, and what files each one uses.
+
+ * Library changes
+
+There is a new opcodes library which will eventually contain all of the
+disassembly routines and opcode tables. At present, it only contains
+Sparc and Z8000 routines. This will allow the assembler, debugger, and
+disassembler (binutils/objdump) to share these routines.
+
+The libiberty library is now copylefted under the GNU Library General
+Public License. This allows more liberal use, and was done so libg++
+can use it. This makes no difference to GDB, since the Library License
+grants all the rights from the General Public License.
+
+ * Documentation
+
+The file gdb-4.7/gdb/doc/stabs.texinfo is a (relatively) complete
+reference to the stabs symbol info used by the debugger. It is (as far
+as we know) the only published document on this fascinating topic. We
+encourage you to read it, compare it to the stabs information on your
+system, and send improvements on the document in general (to
+bug-gdb@prep.ai.mit.edu).
+
+And, of course, many bugs have been fixed.
+
+
+*** Changes in GDB-4.6:
+
+ * Better support for C++ function names
+
+GDB now accepts as input the "demangled form" of C++ overloaded function
+names and member function names, and can do command completion on such names
+(using TAB, TAB-TAB, and ESC-?). The names have to be quoted with a pair of
+single quotes. Examples are 'func (int, long)' and 'obj::operator==(obj&)'.
+Make use of command completion, it is your friend.
+
+GDB also now accepts a variety of C++ mangled symbol formats. They are
+the GNU g++ style, the Cfront (ARM) style, and the Lucid (lcc) style.
+You can tell GDB which format to use by doing a 'set demangle-style {gnu,
+lucid, cfront, auto}'. 'gnu' is the default. Do a 'set demangle-style foo'
+for the list of formats.
+
+ * G++ symbol mangling problem
+
+Recent versions of gcc have a bug in how they emit debugging information for
+C++ methods (when using dbx-style stabs). The file 'gcc.patch' (in this
+directory) can be applied to gcc to fix the problem. Alternatively, if you
+can't fix gcc, you can #define GCC_MANGLE_BUG when compling gdb/symtab.c. The
+usual symptom is difficulty with setting breakpoints on methods. GDB complains
+about the method being non-existent. (We believe that version 2.2.2 of GCC has
+this problem.)
+
+ * New 'maintenance' command
+
+All of the commands related to hacking GDB internals have been moved out of
+the main command set, and now live behind the 'maintenance' command. This
+can also be abbreviated as 'mt'. The following changes were made:
+
+ dump-me -> maintenance dump-me
+ info all-breakpoints -> maintenance info breakpoints
+ printmsyms -> maintenance print msyms
+ printobjfiles -> maintenance print objfiles
+ printpsyms -> maintenance print psymbols
+ printsyms -> maintenance print symbols
+
+The following commands are new:
+
+ maintenance demangle Call internal GDB demangler routine to
+ demangle a C++ link name and prints the result.
+ maintenance print type Print a type chain for a given symbol
+
+ * Change to .gdbinit file processing
+
+We now read the $HOME/.gdbinit file before processing the argv arguments
+(e.g. reading symbol files or core files). This allows global parameters to
+be set, which will apply during the symbol reading. The ./.gdbinit is still
+read after argv processing.
+
+ * New hosts supported
+
+Solaris-2.0 !!! sparc-sun-solaris2 or sun4sol2
+
+Linux support i386-unknown-linux or linux
+
+We are also including code to support the HP/PA running BSD and HPUX. This
+is almost guaranteed not to work, as we didn't have time to test or build it
+for this release. We are including it so that the more adventurous (or
+masochistic) of you can play with it. We also had major problems with the
+fact that the compiler that we got from HP doesn't support the -g option.
+It costs extra.
+
+ * New targets supported
+
+Hitachi H8/300 h8300-hitachi-hms or h8300hms
+
+ * More smarts about finding #include files
+
+GDB now remembers the compilation directory for all include files, and for
+all files from which C is generated (like yacc and lex sources). This
+greatly improves GDB's ability to find yacc/lex sources, and include files,
+especially if you are debugging your program from a directory different from
+the one that contains your sources.
+
+We also fixed a bug which caused difficulty with listing and setting
+breakpoints in include files which contain C code. (In the past, you had to
+try twice in order to list an include file that you hadn't looked at before.)
+
+ * Interesting infernals change
+
+GDB now deals with arbitrary numbers of sections, where the symbols for each
+section must be relocated relative to that section's landing place in the
+target's address space. This work was needed to support ELF with embedded
+stabs used by Solaris-2.0.
+
+ * Bug fixes (of course!)
+
+There have been loads of fixes for the following things:
+ mips, rs6000, 29k/udi, m68k, g++, type handling, elf/dwarf, m88k,
+ i960, stabs, DOS(GO32), procfs, etc...
+
+See the ChangeLog for details.
+
+*** Changes in GDB-4.5:
+
+ * New machines supported (host and target)
+
+IBM RS6000 running AIX rs6000-ibm-aix or rs6000
+
+SGI Irix-4.x mips-sgi-irix4 or iris4
+
+ * New malloc package
+
+GDB now uses a new memory manager called mmalloc, based on gmalloc.
+Mmalloc is capable of handling mutiple heaps of memory. It is also
+capable of saving a heap to a file, and then mapping it back in later.
+This can be used to greatly speedup the startup of GDB by using a
+pre-parsed symbol table which lives in a mmalloc managed heap. For
+more details, please read mmalloc/mmalloc.texi.
+
+ * info proc
+
+The 'info proc' command (SVR4 only) has been enhanced quite a bit. See
+'help info proc' for details.
+
+ * MIPS ecoff symbol table format
+
+The code that reads MIPS symbol table format is now supported on all hosts.
+Thanks to MIPS for releasing the sym.h and symconst.h files to make this
+possible.
+
+ * File name changes for MS-DOS
+
+Many files in the config directories have been renamed to make it easier to
+support GDB on MS-DOSe systems (which have very restrictive file name
+conventions :-( ). MS-DOSe host support (under DJ Delorie's GO32
+environment) is close to working but has some remaining problems. Note
+that debugging of DOS programs is not supported, due to limitations
+in the ``operating system'', but it can be used to host cross-debugging.
+
+ * Cross byte order fixes
+
+Many fixes have been made to support cross debugging of Sparc and MIPS
+targets from hosts whose byte order differs.
+
+ * New -mapped and -readnow options
+
+If memory-mapped files are available on your system through the 'mmap'
+system call, you can use the -mapped option on the `file' or
+`symbol-file' commands to cause GDB to write the symbols from your
+program into a reusable file. If the program you are debugging is
+called `/path/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. Using the '-mapped'
+option in a GDB `file' or `symbol-file' command has the same effect as
+starting GDB with the '-mapped' command-line option.
+
+You can cause GDB to read the entire symbol table immediately by using
+the '-readnow' option with any of the commands that load symbol table
+information (or on the GDB command line). This makes the command
+slower, but makes future operations faster.
+
+The -mapped and -readnow options are typically combined in order to
+build a `fred.syms' file that contains complete symbol information.
+A simple GDB invocation to do nothing but build a `.syms' file for future
+use is:
+
+ gdb -batch -nx -mapped -readnow programname
+
+The `.syms' file is specific to the host machine on which GDB is run.
+It holds an exact image of GDB's internal symbol table. It cannot be
+shared across multiple host platforms.
+
+ * longjmp() handling
+
+GDB is now capable of stepping and nexting over longjmp(), _longjmp(), and
+siglongjmp() without losing control. This feature has not yet been ported to
+all systems. It currently works on many 386 platforms, all MIPS-based
+platforms (SGI, DECstation, etc), and Sun3/4.
+
+ * Solaris 2.0
+
+Preliminary work has been put in to support the new Solaris OS from Sun. At
+this time, it can control and debug processes, but it is not capable of
+reading symbols.
+
+ * Bug fixes
+
+As always, many many bug fixes. The major areas were with g++, and mipsread.
+People using the MIPS-based platforms should experience fewer mysterious
+crashes and trashed symbol tables.
+
+*** Changes in GDB-4.4:
+
+ * New machines supported (host and target)
+
+SCO Unix on i386 IBM PC clones i386-sco-sysv or i386sco
+ (except core files)
+BSD Reno on Vax vax-dec-bsd
+Ultrix on Vax vax-dec-ultrix
+
+ * New machines supported (target)
+
+AMD 29000 embedded, using EBMON a29k-none-none
+
+ * C++ support
+
+GDB continues to improve its handling of C++. `References' work better.
+The demangler has also been improved, and now deals with symbols mangled as
+per the Annotated C++ Reference Guide.
+
+GDB also now handles `stabs' symbol information embedded in MIPS
+`ecoff' symbol tables. Since the ecoff format was not easily
+extensible to handle new languages such as C++, this appeared to be a
+good way to put C++ debugging info into MIPS binaries. This option
+will be supported in the GNU C compiler, version 2, when it is
+released.
+
+ * New features for SVR4
+
+GDB now handles SVR4 shared libraries, in the same fashion as SunOS
+shared libraries. Debugging dynamically linked programs should present
+only minor differences from debugging statically linked programs.
+
+The `info proc' command will print out information about any process
+on an SVR4 system (including the one you are debugging). At the moment,
+it prints the address mappings of the process.
+
+If you bring up GDB on another SVR4 system, please send mail to
+bug-gdb@prep.ai.mit.edu to let us know what changes were reqired (if any).
+
+ * Better dynamic linking support in SunOS
+
+Reading symbols from shared libraries which contain debugging symbols
+now works properly. However, there remain issues such as automatic
+skipping of `transfer vector' code during function calls, which
+make it harder to debug code in a shared library, than to debug the
+same code linked statically.
+
+ * New Getopt
+
+GDB is now using the latest `getopt' routines from the FSF. This
+version accepts the -- prefix for options with long names. GDB will
+continue to accept the old forms (-option and +option) as well.
+Various single letter abbreviations for options have been explicity
+added to the option table so that they won't get overshadowed in the
+future by other options that begin with the same letter.
+
+ * Bugs fixed
+
+The `cleanup_undefined_types' bug that many of you noticed has been squashed.
+Many assorted bugs have been handled. Many more remain to be handled.
+See the various ChangeLog files (primarily in gdb and bfd) for details.
+
+
+*** Changes in GDB-4.3:
+
+ * New machines supported (host and target)
+
+Amiga 3000 running Amix m68k-cbm-svr4 or amix
+NCR 3000 386 running SVR4 i386-ncr-svr4 or ncr3000
+Motorola Delta 88000 running Sys V m88k-motorola-sysv or delta88
+
+ * Almost SCO Unix support
+
+We had hoped to support:
+SCO Unix on i386 IBM PC clones i386-sco-sysv or i386sco
+(except for core file support), but we discovered very late in the release
+that it has problems with process groups that render gdb unusable. Sorry
+about that. I encourage people to fix it and post the fixes.
+
+ * Preliminary ELF and DWARF support
+
+GDB can read ELF object files on System V Release 4, and can handle
+debugging records for C, in DWARF format, in ELF files. This support
+is preliminary. If you bring up GDB on another SVR4 system, please
+send mail to bug-gdb@prep.ai.mit.edu to let us know what changes were
+reqired (if any).
+
+ * New Readline
+
+GDB now uses the latest `readline' library. One user-visible change
+is that two tabs will list possible command completions, which previously
+required typing M-? (meta-question mark, or ESC ?).
+
+ * Bugs fixed
+
+The `stepi' bug that many of you noticed has been squashed.
+Many bugs in C++ have been handled. Many more remain to be handled.
+See the various ChangeLog files (primarily in gdb and bfd) for details.
+
+ * State of the MIPS world (in case you wondered):
+
+GDB can understand the symbol tables emitted by the compilers
+supplied by most vendors of MIPS-based machines, including DEC. These
+symbol tables are in a format that essentially nobody else uses.
+
+Some versions of gcc come with an assembler post-processor called
+mips-tfile. This program is required if you want to do source-level
+debugging of gcc-compiled programs. I believe FSF does not ship
+mips-tfile with gcc version 1, but it will eventually come with gcc
+version 2.
+
+Debugging of g++ output remains a problem. g++ version 1.xx does not
+really support it at all. (If you're lucky, you should be able to get
+line numbers and stack traces to work, but no parameters or local
+variables.) With some work it should be possible to improve the
+situation somewhat.
+
+When gcc version 2 is released, you will have somewhat better luck.
+However, even then you will get confusing results for inheritance and
+methods.
+
+We will eventually provide full debugging of g++ output on
+DECstations. This will probably involve some kind of stabs-in-ecoff
+encapulation, but the details have not been worked out yet.
+
+
+*** Changes in GDB-4.2:
+
+ * Improved configuration
+
+Only one copy of `configure' exists now, and it is not self-modifying.
+Porting BFD is simpler.
+
+ * Stepping improved
+
+The `step' and `next' commands now only stop at the first instruction
+of a source line. This prevents the multiple stops that used to occur
+in switch statements, for-loops, etc. `Step' continues to stop if a
+function that has debugging information is called within the line.
+
+ * Bug fixing
+
+Lots of small bugs fixed. More remain.
+
+ * New host supported (not target)
+
+Intel 386 PC clone running Mach i386-none-mach
+
+
+*** Changes in GDB-4.1:
+
+ * Multiple source language support
+
+GDB now has internal scaffolding to handle several source languages.
+It determines the type of each source file from its filename extension,
+and will switch expression parsing and number formatting to match the
+language of the function in the currently selected stack frame.
+You can also specifically set the language to be used, with
+`set language c' or `set language modula-2'.
+
+ * GDB and 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. Development of both GDB and the GNU Modula-2 compiler will
+continue through the fall of 1991 and into 1992.
+
+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 is read. Feel free to work on it, though!
+
+There are hooks in GDB for strict type checking and range checking,
+in the `Modula-2 philosophy', but they do not currently work.
+
+ * set write on/off
+
+GDB can now write to executable and core files (e.g. patch
+a variable's value). You must turn this switch on, specify
+the file ("exec foo" or "core foo"), *then* modify it, e.g.
+by assigning a new value to a variable. Modifications take
+effect immediately.
+
+ * Automatic SunOS shared library reading
+
+When you run your program, GDB automatically determines where its
+shared libraries (if any) have been loaded, and reads their symbols.
+The `share' command is no longer needed. This also works when
+examining core files.
+
+ * set listsize
+
+You can specify the number of lines that the `list' command shows.
+The default is 10.
+
+ * New machines supported (host and target)
+
+SGI Iris (MIPS) running Irix V3: mips-sgi-irix or iris
+Sony NEWS (68K) running NEWSOS 3.x: m68k-sony-sysv or news
+Ultracomputer (29K) running Sym1: a29k-nyu-sym1 or ultra3
+
+ * New hosts supported (not targets)
+
+IBM RT/PC: romp-ibm-aix or rtpc
+
+ * New targets supported (not hosts)
+
+AMD 29000 embedded with COFF a29k-none-coff
+AMD 29000 embedded with a.out a29k-none-aout
+Ultracomputer remote kernel debug a29k-nyu-kern
+
+ * New remote interfaces
+
+AMD 29000 Adapt
+AMD 29000 Minimon
+
+
+*** Changes in GDB-4.0:
+
+ * New Facilities
+
+Wide output is wrapped at good places to make the output more readable.
+
+Gdb now supports cross-debugging from a host machine of one type to a
+target machine of another type. Communication with the target system
+is over serial lines. The ``target'' command handles connecting to the
+remote system; the ``load'' command will download a program into the
+remote system. Serial stubs for the m68k and i386 are provided. Gdb
+also supports debugging of realtime processes running under VxWorks,
+using SunRPC Remote Procedure Calls over TCP/IP to talk to a debugger
+stub on the target system.
+
+New CPUs supported include the AMD 29000 and Intel 960.
+
+GDB now reads object files and symbol tables via a ``binary file''
+library, which allows a single copy of GDB to debug programs of multiple
+object file types such as a.out and coff.
+
+There is now a GDB reference card in "doc/refcard.tex". (Make targets
+refcard.dvi and refcard.ps are available to format it).
+
+
+ * Control-Variable user interface simplified
+
+All variables that control the operation of the debugger can be set
+by the ``set'' command, and displayed by the ``show'' command.
+
+For example, ``set prompt new-gdb=>'' will change your prompt to new-gdb=>.
+``Show prompt'' produces the response:
+Gdb's prompt is new-gdb=>.
+
+What follows are the NEW set commands. The command ``help set'' will
+print a complete list of old and new set commands. ``help set FOO''
+will give a longer description of the variable FOO. ``show'' will show
+all of the variable descriptions and their current settings.
+
+confirm on/off: Enables warning questions for operations that are
+ hard to recover from, e.g. rerunning the program while
+ it is already running. Default is ON.
+
+editing on/off: Enables EMACS style command line editing
+ of input. Previous lines can be recalled with
+ control-P, the current line can be edited with control-B,
+ you can search for commands with control-R, etc.
+ Default is ON.
+
+history filename NAME: NAME is where the gdb command history
+ will be stored. The default is .gdb_history,
+ or the value of the environment variable
+ GDBHISTFILE.
+
+history size N: The size, in commands, of the command history. The
+ default is 256, or the value of the environment variable
+ HISTSIZE.
+
+history save on/off: If this value is set to ON, the history file will
+ be saved after exiting gdb. If set to OFF, the
+ file will not be saved. The default is OFF.
+
+history expansion on/off: If this value is set to ON, then csh-like
+ history expansion will be performed on
+ command line input. The default is OFF.
+
+radix N: Sets the default radix for input and output. It can be set
+ to 8, 10, or 16. Note that the argument to "radix" is interpreted
+ in the current radix, so "set radix 10" is always a no-op.
+
+height N: This integer value is the number of lines on a page. Default
+ is 24, the current `stty rows'' setting, or the ``li#''
+ setting from the termcap entry matching the environment
+ variable TERM.
+
+width N: This integer value is the number of characters on a line.
+ Default is 80, the current `stty cols'' setting, or the ``co#''
+ setting from the termcap entry matching the environment
+ variable TERM.
+
+Note: ``set screensize'' is obsolete. Use ``set height'' and
+``set width'' instead.
+
+print address on/off: Print memory addresses in various command displays,
+ such as stack traces and structure values. Gdb looks
+ more ``symbolic'' if you turn this off; it looks more
+ ``machine level'' with it on. Default is ON.
+
+print array on/off: Prettyprint arrays. New convenient format! Default
+ is OFF.
+
+print demangle on/off: Print C++ symbols in "source" form if on,
+ "raw" form if off.
+
+print asm-demangle on/off: Same, for assembler level printouts
+ like instructions.
+
+print vtbl on/off: Prettyprint C++ virtual function tables. Default is OFF.
+
+
+ * Support for Epoch Environment.
+
+The epoch environment is a version of Emacs v18 with windowing. One
+new command, ``inspect'', is identical to ``print'', except that if you
+are running in the epoch environment, the value is printed in its own
+window.
+
+
+ * Support for Shared Libraries
+
+GDB can now debug programs and core files that use SunOS shared libraries.
+Symbols from a shared library cannot be referenced
+before the shared library has been linked with the program (this
+happens after you type ``run'' and before the function main() is entered).
+At any time after this linking (including when examining core files
+from dynamically linked programs), gdb reads the symbols from each
+shared library when you type the ``sharedlibrary'' command.
+It can be abbreviated ``share''.
+
+sharedlibrary REGEXP: Load shared object library symbols for files
+ matching a unix regular expression. No argument
+ indicates to load symbols for all shared libraries.
+
+info sharedlibrary: Status of loaded shared libraries.
+
+
+ * Watchpoints
+
+A watchpoint stops execution of a program whenever the value of an
+expression changes. Checking for this slows down execution
+tremendously whenever you are in the scope of the expression, but is
+quite useful for catching tough ``bit-spreader'' or pointer misuse
+problems. Some machines such as the 386 have hardware for doing this
+more quickly, and future versions of gdb will use this hardware.
+
+watch EXP: Set a watchpoint (breakpoint) for an expression.
+
+info watchpoints: Information about your watchpoints.
+
+delete N: Deletes watchpoint number N (same as breakpoints).
+disable N: Temporarily turns off watchpoint number N (same as breakpoints).
+enable N: Re-enables watchpoint number N (same as breakpoints).
+
+
+ * C++ multiple inheritance
+
+When used with a GCC version 2 compiler, GDB supports multiple inheritance
+for C++ programs.
+
+ * C++ exception handling
+
+Gdb now supports limited C++ exception handling. Besides the existing
+ability to breakpoint on an exception handler, gdb can breakpoint on
+the raising of an exception (before the stack is peeled back to the
+handler's context).
+
+catch FOO: If there is a FOO exception handler in the dynamic scope,
+ set a breakpoint to catch exceptions which may be raised there.
+ Multiple exceptions (``catch foo bar baz'') may be caught.
+
+info catch: Lists all exceptions which may be caught in the
+ current stack frame.
+
+
+ * Minor command changes
+
+The command ``call func (arg, arg, ...)'' now acts like the print
+command, except it does not print or save a value if the function's result
+is void. This is similar to dbx usage.
+
+The ``up'' and ``down'' commands now always print the frame they end up
+at; ``up-silently'' and `down-silently'' can be used in scripts to change
+frames without printing.
+
+ * New directory command
+
+'dir' now adds directories to the FRONT of the source search path.
+The path starts off empty. Source files that contain debug information
+about the directory in which they were compiled can be found even
+with an empty path; Sun CC and GCC include this information. If GDB can't
+find your source file in the current directory, type "dir .".
+
+ * Configuring GDB for compilation
+
+For normal use, type ``./configure host''. See README or gdb.texinfo
+for more details.
+
+GDB now handles cross debugging. If you are remotely debugging between
+two different machines, type ``./configure host -target=targ''.
+Host is the machine where GDB will run; targ is the machine
+where the program that you are debugging will run.
diff --git a/gdb/README b/gdb/README
new file mode 100644
index 00000000000..fd791ced523
--- /dev/null
+++ b/gdb/README
@@ -0,0 +1,618 @@
+ README for gdb-4.18 release
+ Updated 4 Apr 1999 by Jim Blandy
+
+This is GDB, the GNU source-level debugger.
+A summary of new features is in the file `NEWS'.
+
+See the GDB home page at http://www.cygnus.com/gdb/ for up to date
+release information, mailing list links and archives, etc.
+
+
+Unpacking and Installation -- quick overview
+==========================
+
+In this release, the GDB debugger sources, the generic GNU include
+files, the BFD ("binary file description") library, the readline
+library, and other libraries all have directories of their own
+underneath the gdb-4.18 directory. The idea is that a variety of GNU
+tools can share a common copy of these things. Be aware of variation
+over time--for example don't try to build gdb with a copy of bfd from
+a release other than the gdb release (such as a binutils or gas
+release), especially if the releases are more than a few weeks apart.
+Configuration scripts and makefiles exist to cruise up and down this
+directory tree and automatically build all the pieces in the right
+order.
+
+When you unpack the gdb-4.18.tar.gz file, you'll find a directory
+called `gdb-4.18', which contains:
+
+ COPYING config.sub* libiberty/ opcodes/
+ COPYING.LIB configure* mmalloc/ readline/
+ Makefile.in configure.in move-if-change* sim/
+ README etc/ mpw-README texinfo/
+ bfd/ gdb/ mpw-build.in utils/
+ config/ include/ mpw-config.in
+ config.guess* install.sh* mpw-configure
+
+To build GDB, you can just do:
+
+ cd gdb-4.18
+ ./configure
+ make
+ cp gdb/gdb /usr/local/bin/gdb (or wherever you want)
+
+This will configure and build all the libraries as well as GDB.
+If `configure' can't determine your system type, specify one as its
+argument, e.g., sun4 or decstation.
+
+If you get compiler warnings during this stage, see the `Reporting Bugs'
+section below; there are a few known problems.
+
+GDB requires an ANSI C compiler. If you do not have an ANSI C
+compiler for your system, you may be able to download and install the
+GNU CC compiler. It is available via anonymous FTP from ftp.gnu.org,
+in /pub/gnu/gcc (as a URL, that's ftp://ftp.gnu.org/pub/gnu/gcc).
+
+GDB can be used as a cross-debugger, running on a machine of one type
+while debugging a program running on a machine of another type. See below.
+
+
+More 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 `texi2roff') to typeset the printed version.
+
+ GDB includes an already formatted copy of the on-line Info version of
+this manual in the `gdb/doc' subdirectory. The main Info file is
+`gdb-4.18/gdb/doc/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.18', in the case of version 4.18), you can make
+the Info file by typing:
+
+ cd gdb/doc
+ make 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. This file is included in the GDB
+distribution, in the directory `gdb-4.18/texinfo'.
+
+ 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-4.18/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.18/gdb') and then type:
+
+ make gdb.dvi
+
+
+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.18 distribution is in the `gdb-4.18'
+directory. That directory contains:
+
+`gdb-4.18/{COPYING,COPYING.LIB}'
+ Standard GNU license files. Please read them.
+
+`gdb-4.18/bfd'
+ source for the Binary File Descriptor library
+
+`gdb-4.18/config*'
+ script for configuring GDB, along with other support files
+
+`gdb-4.18/gdb'
+ the source specific to GDB itself
+
+`gdb-4.18/include'
+ GNU include files
+
+`gdb-4.18/libiberty'
+ source for the `-liberty' free software library
+
+`gdb-4.18/mmalloc'
+ source for the GNU memory-mapped malloc package
+
+`gdb-4.18/opcodes'
+ source for the library of opcode tables and disassemblers
+
+`gdb-4.18/readline'
+ source for the GNU command-line interface
+
+`gdb-4.18/sim'
+ source for some simulators (ARM, D10V, SPARC, M32R, MIPS, PPC, V850, etc)
+
+`gdb-4.18/intl'
+ source for the GNU gettext library, for internationalization.
+ This is slightly modified from the standalone gettext
+ distribution you can get from GNU.
+
+`gdb-4.18/texinfo'
+ The `texinfo.tex' file, which you need in order to make a printed
+ manual using TeX.
+
+`gdb-4.18/etc'
+ Coding standards, useful files for editing GDB, and other
+ miscellanea.
+
+`gdb-4.18/utils'
+ A grab bag of random utilities.
+
+
+ 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.18' directory.
+
+ First switch to the `gdb-VERSION-NUMBER' source directory if you are
+not already in it; then run `configure'.
+
+ For example:
+
+ cd gdb-4.18
+ ./configure
+ make
+
+ Running `configure' followed by `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
+
+ If you run `configure' from a directory that contains source
+directories for multiple libraries or programs, such as the `gdb-4.18'
+source directory for version 4.18, `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.18, type the following to configure only
+the `bfd' subdirectory:
+
+ cd gdb-4.18/bfd
+ ../configure
+
+ 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.
+
+
+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 correctly (GNU `make' and SunOS 'make' are two that should),
+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.18, you can build GDB in a separate
+directory for a Sun 4 like this:
+
+ cd gdb-4.18
+ mkdir ../gdb-sun4
+ cd ../gdb-sun4
+ ../gdb-4.18/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.18' (or in a separate configured directory configured with
+`--srcdir=PATH/gdb-4.18'), 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.
+
+
+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 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-pc-sysv
+ % sh config.sub i786v
+ Invalid configuration `i786v': machine `i786v' not recognized
+
+`config.sub' is also distributed in the GDB source directory
+(`gdb-4.18', for version 4.18).
+
+
+`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]
+ [--enable-build-warnings]
+ [--target=TARGET]
+ [--host=HOST]
+ [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 compatibly 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 the configuration that the other arguments specify.
+
+`--enable-build-warnings'
+ When building the GDB sources, ask the compiler to warn about any
+ code which looks even vaguely suspicious. You should only using
+ this feature if you're compiling with GNU CC. It passes the
+ following flags:
+ -Wall
+ -Wpointer-arith
+ -Wstrict-prototypes
+ -Wmissing-prototypes
+ -Wmissing-declarations
+
+`--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=HOST'
+ Configure GDB to run on the specified HOST.
+
+ There is no convenient way to generate a list of all available
+ hosts.
+
+`HOST ...'
+ Same as `--host=HOST'. If you omit this, GDB will guess; it's
+ quite accurate.
+
+`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.
+
+
+Languages other than C
+=======================
+
+See the GDB manual (gdb/doc/gdb.texinfo) for information on this.
+
+
+Kernel debugging
+=================
+
+I have't done this myself so I can't really offer any advice.
+Remote debugging over serial lines works fine, but the kernel debugging
+code in here has not been tested in years. Van Jacobson has
+better kernel debugging, but the UC lawyers won't let FSF have it.
+
+
+Remote debugging
+=================
+
+The files m68k-stub.c, i386-stub.c, and sparc-stub.c are examples of
+remote stubs to be used with remote.c. They are designed to run
+standalone on an m68k, i386, or SPARC cpu and communicate properly with
+the remote.c stub over a serial line.
+
+The directory gdb/gdbserver/ contains `gdbserver', a program that
+allows remote debugging for Unix applications. gdbserver is only
+supported for some native configurations, including Sun 3, Sun 4,
+and Linux.
+
+There are a number of remote interfaces for talking to existing ROM
+monitors and other hardware:
+
+ remote-adapt.c AMD 29000 "Adapt"
+ remote-array.c Array Tech RAID controller
+ remote-bug.c Motorola BUG monitor
+ remote-d10v.c GDB protocol, talking to a d10v chip
+ remote-e7000.c Hitachi E7000 ICE
+ remote-eb.c AMD 29000 "EBMON"
+ remote-es.c Ericsson 1800 monitor
+ remote-est.c EST emulator
+ remote-hms.c Hitachi Micro Systems H8/300 monitor
+ remote-mips.c MIPS remote debugging protocol
+ remote-mm.c AMD 29000 "minimon"
+ remote-nindy.c Intel 960 "Nindy"
+ remote-nrom.c NetROM ROM emulator
+ remote-os9k.c PC running OS/9000
+ remote-rdi.c ARM with Angel monitor
+ remote-rdp.c ARM with Demon monitor
+ remote-sds.c PowerPC SDS monitor
+ remote-sim.c Generalized simulator protocol
+ remote-st.c Tandem ST-2000 monitor
+ remote-udi.c AMD 29000 using the AMD "Universal Debug Interface"
+ remote-vx.c VxWorks realtime kernel
+
+Remote-vx.c and the vx-share subdirectory contain a remote interface for the
+VxWorks realtime kernel, which communicates over TCP using the Sun
+RPC library. This would be a useful starting point for other remote-
+via-ethernet back ends.
+
+Remote-udi.c and the 29k-share subdirectory contain a remote interface
+for AMD 29000 programs, which uses the AMD "Universal Debug Interface".
+This allows GDB to talk to software simulators, emulators, and/or bare
+hardware boards, via network or serial interfaces. Note that GDB only
+provides an interface that speaks UDI, not a complete solution. You
+will need something on the other end that also speaks UDI.
+
+
+Reporting Bugs
+===============
+
+The correct address for reporting bugs found in gdb is
+"bug-gdb@gnu.org". Please email all bugs, and all requests for
+help with GDB, to that address. Please include the GDB version number
+(e.g., gdb-4.18), and how you configured it (e.g., "sun4" or "mach386
+host, i586-intel-synopsys target"). Since GDB now supports so many
+different configurations, it is important that you be precise about this.
+If at all possible, you should include the actual banner that GDB prints
+when it starts up, or failing that, the actual configure command that
+you used when configuring GDB.
+
+For more information on how/whether to report bugs, see the GDB Bugs
+section of the GDB manual (gdb/doc/gdb.texinfo).
+
+Known bugs:
+
+ * Under Ultrix 4.2 (DECstation-3100) or Alphas under OSF/1, we have
+ seen problems with backtraces after interrupting the inferior out
+ of a read(). The problem is caused by ptrace() returning an
+ incorrect value for the frame pointer register (register 15 or
+ 30). As far as we can tell, this is a kernel problem. Any help
+ with this would be greatly appreciated.
+
+ * Under Ultrix 4.4 (DECstation-3100), setting the TERMCAP environment
+ variable to a string without a trailing ':' can cause GDB to dump
+ core upon startup. Although the core file makes it look as though
+ GDB code failed, the crash actually occurs within a call to the
+ termcap library function tgetent(). The problem can be solved by
+ using the GNU Termcap library.
+
+ Alphas running OSF/1 (versions 1.0 through 2.1) have the same buggy
+ termcap code, but GDB behaves strangely rather than crashing.
+
+ * On DECstations there are warnings about shift counts out of range in
+ various BFD modules. None of them is a cause for alarm, they are actually
+ a result of bugs in the DECstation compiler.
+
+ * Notes for the DEC Alpha using OSF/1:
+ The debugging output of native cc has two known problems; we view these
+ as compiler bugs.
+ The linker miscompacts symbol tables, which causes gdb to confuse the
+ type of variables or results in `struct <illegal>' type outputs.
+ dbx has the same problems with those executables. A workaround is to
+ specify -Wl,-b when linking, but that will increase the executable size
+ considerably.
+ If a structure has incomplete type in one file (e.g., "struct foo *"
+ without a definition for "struct foo"), gdb will be unable to find the
+ structure definition from another file.
+ It has been reported that the Ultrix 4.3A compiler on decstations has the
+ same problems.
+
+ * Notes for Solaris 2.x, using the SPARCworks cc compiler:
+ You have to compile your program with the -xs option of the SPARCworks
+ compiler to be able to debug your program with gdb.
+ Under Solaris 2.3 you also need patch 101409-03 (Jumbo linker patch).
+ Under Solaris 2.2, if you have patch 101052 installed, make sure
+ that it is at least at revision 101052-06.
+
+ * Under Irix 5 for SGIs, you must have installed the `compiler_dev.hdr'
+ subsystem that is on the IDO CD, otherwise you will get complaints
+ that certain files such as `/usr/include/syms.h' cannot be found.
+
+ * Notes for BSD/386:
+ To compile gdb-4.18 on BSD/386, you must run the configure script and
+ its subscripts with bash. Here is an easy way to do this:
+
+ bash -c 'CONFIG_SHELL=/bin/bash ./configure'
+
+ (configure will report i386-unknown-bsd). Then, compile with the
+ standard "make" command.
+
+GDB can produce warnings about symbols that it does not understand. By
+default, these warnings are disabled. You can enable them by executing
+`set complaint 10' (which you can put in your ~/.gdbinit if you like).
+I recommend doing this if you are working on a compiler, assembler,
+linker, or GDB, since it will point out problems that you may be able
+to fix. Warnings produced during symbol reading indicate some mismatch
+between the object file and GDB's symbol reading code. In many cases,
+it's a mismatch between the specs for the object file format, and what
+the compiler actually outputs or the debugger actually understands.
+
+
+X Windows versus GDB
+=====================
+
+You should check out DDD, the Data Display Debugger. Here's the blurb
+from the DDD web site, http://www.cs.tu-bs.de/softech/ddd:
+
+ The Data Display Debugger (DDD) is a popular graphical user
+ interface for command-line debuggers such as GDB, DBX, JDB, WDB,
+ XDB, the Perl debugger, and the Python debugger. Besides ``usual''
+ front-end features such as viewing source texts, DDD has become
+ famous through its interactive graphical data display, where data
+ structures are displayed as graphs. A simple mouse click
+ dereferences pointers or views structure contents, updated each
+ time the program stops. Using DDD, you can reason about your
+ application by watching its data, not just by viewing it execute
+ lines of source code.
+
+Emacs users will very likely enjoy the Grand Unified Debugger mode;
+try typing `M-x gdb RET'.
+
+Those interested in experimenting with a new kind of gdb-mode
+should load gdb/gdba.el into GNU Emacs 19.25 or later. Comments
+on this mode are also welcome.
+
+
+Writing Code for GDB
+=====================
+
+There is a lot of information about writing code for GDB in the
+internals manual, distributed with GDB in gdb/doc/gdbint.texinfo. You
+can read it by hand, print it by using TeX and texinfo, or process it
+into an `info' file for use with Emacs' info mode or the standalone
+`info' program.
+
+If you are pondering writing anything but a short patch, especially
+take note of the information about copyrights in the node Submitting
+Patches. It can take quite a while to get all the paperwork done, so
+we encourage you to start that process as soon as you decide you are
+planning to work on something, or at least well ahead of when you
+think you will be ready to submit the patches.
+
+
+GDB Testsuite
+=============
+
+There is a DejaGNU based testsuite available for testing your newly
+built GDB, or for regression testing GDBs with local modifications.
+
+Running the testsuite requires the prior installation of DejaGNU,
+which is generally available via ftp; you'll need a pretty recent
+release. Once DejaGNU is installed, you can run the tests in one of
+two ways:
+
+ (1) cd gdb-4.18/gdb (assuming you also unpacked gdb)
+ make check
+
+or
+
+ (2) cd gdb-4.18/gdb/testsuite
+ make site.exp (builds the site specific file)
+ runtest -tool gdb GDB=../gdb (or GDB=<somepath> as appropriate)
+
+The second method gives you slightly more control in case of problems with
+building one or more test executables or if you are using the testsuite
+'standalone', without it being part of the GDB source tree.
+
+See the DejaGNU documentation for further details.
+
+
+(this is for editing this file with GNU emacs)
+Local Variables:
+mode: text
+End:
diff --git a/gdb/TODO b/gdb/TODO
new file mode 100644
index 00000000000..fcbcd16bea6
--- /dev/null
+++ b/gdb/TODO
@@ -0,0 +1,471 @@
+If you find inaccuracies in this list, please send mail to
+bug-gdb@prep.ai.mit.edu. If you would like to work on any of these,
+you should consider sending mail to the same address, to find out
+whether anyone else is working on it.
+
+General To Do List
+------------------
+
+This list is probably not up to date, and opinions vary about the
+importance or even desirability of some of the items.
+
+Add an "info bfd" command that displays supported object formats,
+similarly to objdump -i.
+
+START_INFERIOR_TRAPS_EXPECTED need never be defined to 2, since that
+is its default value. Clean this up.
+
+It should be possible to use symbols from shared libraries before we know
+exactly where the libraries will be loaded. E.g. "b perror" before running
+the program. This could maybe be done as an extension of the "breakpoint
+re-evaluation" after new symbols are loaded.
+
+Make single_step() insert and remove breakpoints in one operation.
+
+Speed up single stepping by avoiding extraneous ptrace calls.
+
+Speed up single stepping by not inserting and removing breakpoints
+each time the inferior starts and stops.
+
+Breakpoints should not be inserted and deleted all the time. Only the
+one(s) there should be removed when we have to step over one. Support
+breakpoints that don't have to be removed to step over them.
+
+Update gdbint.texinfo to include doc on the directory structure and
+the various tricks of building gdb.
+
+Do a tutorial in gdb.texinfo on how to do simple things in gdb.
+E.g. how to set a breakpoint that just prints something and continues.
+How to break on aborts. Etc.
+
+Provide "voodoo" debugging of core files. This creates a zombie
+process as a child of the debugger, and loads it up with the data,
+stack, and regs of the core file. This allows you to call functions
+in the executable, to manipulate the data in the core file.
+
+GDB reopens the source file on every line, as you "next" through it.
+
+Referencing the vtbl member of a struct doesn't work. It prints OK
+if you print the struct, but it gets 0 if you try to deref it.
+
+Persistent command history: A feature where you could save off a list
+of the commands you did, so you can edit it into something that will bring
+the target to the same place every time you source it.
+This would also be useful for automated fast watchpointing; if you go
+past the place where it watchpoints, you just start it over again and
+do it more carefully.
+
+Deal with the SunOS 4.0 and 4.1.1 ptrace bug that loses the registers if
+the stack is paged out.
+
+Finish the C++ exception handling stub routines. Lint points them out
+as unused statics functions.
+
+Perhaps "i source" should take an argument like that of "list".
+
+See if core-aout.c's fetch_core_registers can be used on more machines.
+E.g. MIPS (mips-xdep.c).
+
+unpack_double() does not handle IEEE float on the target unless the host
+is also IEEE. Death on a vax.
+
+Set up interface between GDB and INFO so that you can hop into interactive
+INFO and back out again. When running under Emacs, should use Emacs
+info, else fork the info program. Installation of GDB should install
+its texinfo files into the info tree automagically, including the readline
+texinfo files.
+
+"help address" ought to find the "help set print address" entry.
+
+Remove the VTBL internal guts from printouts of C++ structs, unless
+vtblprint is set.
+
+Remove "at 0xnnnn" from the "b foo" response, if `print address off' and if
+it matches the source line indicated.
+
+The prompt at end of screen should accept space as well as CR.
+
+Check STORE_RETURN_VALUE on all architectures. Check near it in tm-sparc.h
+for other bogosities.
+
+Check for storage leaks in GDB, I'm sure there are a lot!
+
+vtblprint of a vtbl should demangle the names it's printing.
+
+Backtrace should point out what the currently selected frame is, in
+its display, perhaps showing "@3 foo (bar, ...)" or ">3 foo (bar,
+...)" rather than "#3 foo (bar, ...)".
+
+"i program" should work for core files, and display more info, like what
+actually caused it to die.
+
+"x/10i" should shorten the long name, if any, on subsequent lines.
+
+Check through the code for FIXME comments and fix them. dbxread.c,
+blockframe.c, and plenty more. (I count 634 as of 940621 - sts)
+
+"next" over a function that longjumps, never stops until next time you happen
+to get to that spot by accident. E.g. "n" over execute_command which has
+an error.
+
+"set zeroprint off", don't bother printing members of structs which
+are entirely zero. Useful for those big structs with few useful
+members.
+
+GDB does four ioctl's for every command, probably switching terminal modes
+to/from inferior or for readline or something.
+
+terminal_ours versus terminal_inferior: cache state. Switch should be a noop
+if the state is the same, too.
+
+ptype $i6 = void??!
+
+Clean up invalid_float handling so gdb doesn't coredump when it tries to
+access a NaN. While this might work on SPARC, other machines are not
+configured right.
+
+"b value_at ; commands ; continue ; end" stops EVERY OTHER TIME!
+Then once you enter a command, it does the command, runs two more
+times, and then stops again! Bizarre... (This behaviour has been
+modified, but it is not yet 100% predictable when e.g. the commands
+call functions in the child, and while there, the child is interrupted
+with a signal, or hits a breakpoint.)
+
+help completion, help history should work.
+
+Check that we can handle stack trace through varargs AND alloca in same
+function, on 29K.
+
+wait_for_inferior loops forever if wait() gives it an error.
+
+"i frame" shows wrong "arglist at" location, doesn't show where the args
+should be found, only their actual values.
+
+There should be a way for "set" commands to validate the new setting
+before it takes effect.
+
+A mess of floating point opcodes are missing from sparc-opcode.h.
+Also, a little program should test the table for bits that are
+overspecified or underspecified. E.g. if the must-be-ones bits
+and the must-be-zeroes bits leave some fields unexamined, and the format
+string leaves them unprinted, then point this out. If multiple
+non-alias patterns match, point this out too. Finally, there should
+be a sparc-optest.s file that tries each pattern out. This file
+should end up coming back the same (modulo transformation comments)
+if fed to "gas" then the .o is fed to gdb for disassembly.
+
+Eliminate all the core_file_command's in all the xdep files.
+Eliminate separate declarations of registers[] everywhere.
+
+"ena d" is ambiguous, why? "ena delete" seems to think it is a command!
+
+Perhaps move the tdep, xdep, and nat files, into the config
+subdirectories. If not, at least straighten out their names so that
+they all start with the machine name.
+
+inferior_status should include stop_print_frame. It won't need to be
+reset in wait_for_inferior after bpstat_stop_status call, then.
+
+i line VAR produces "Line number not known for symbol ``var''.". I
+thought we were stashing that info now!
+
+We should be able to write to random files at hex offsets like adb.
+
+Make "target xxx" command interruptible.
+
+Handle add_file with separate text, data, and bss addresses. Maybe
+handle separate addresses for each segment in the object file?
+
+Handle free_named_symtab to cope with multiply-loaded object files
+in a dynamic linking environment. Should remember the last copy loaded,
+but not get too snowed if it finds references to the older copy.
+
+Generalize and Standardize the RPC interface to a target program,
+improve it beyond the "ptrace" interface, and see if it can become a
+standard for remote debugging. (This is talking about the vxworks
+interface. Seems unlikely to me that there will be "a standard" for
+remote debugging anytime soon --kingdon, 8 Nov 1994).
+
+Remove all references to:
+ text_offset
+ data_offset
+ text_data_start
+ text_end
+ exec_data_offset
+ ...
+now that we have BFD. All remaining are in machine dependent files.
+
+When quitting with a running program, if a core file was previously
+examined, you get "Couldn't read float regs from core file"...if
+indeed it can't. generic_mourn_inferior...
+
+Have remote targets give a warning on a signal argument to
+target_resume. Or better yet, extend the protocols so that it works
+like it does on the Unix-like systems.
+
+Sort help and info output.
+
+Re-organize help categories into things that tend to fit on a screen
+and hang together.
+
+renote-nindy.c handles interrupts poorly; it error()s out of badly
+chosen places, e.g. leaving current_frame zero, which causes core dumps
+on the next command.
+
+Add in commands like ADB's for searching for patterns, etc. We should
+be able to examine and patch raw unsymboled binaries as well in gdb as
+we can in adb. (E.g. increase the timeout in /bin/login without source).
+
+Those xdep files that call register_addr without defining it are
+probably simply broken. When reconfiguring this part of gdb, I could
+only make guesses about how to redo some of those files, and I
+probably guessed wrong, or left them "for later" when I have a
+machine that can attempt to build them.
+
+When doing "step" or "next", if a few lines of source are skipped between
+the previous line and the current one, print those lines, not just the
+last line of a multiline statement.
+
+When searching for C++ superclasses in value_cast in valops.c, we must
+not search the "fields", only the "superclasses". There might be a
+struct with a field name that matches the superclass name. This can
+happen when the struct was defined before the superclass (before the
+name became a typedef).
+
+Handling of "&" address-of operator needs some serious overhaul
+for ANSI C and consistency on arrays and functions.
+ For "float point[15];":
+ptype &point[4] ==> Attempt to take address of non-lvalue.
+ For "char *malloc();":
+ptype malloc ==> "char *()"; should be same as
+ptype &malloc ==> "char *(*)()"
+call printf ("%x\n", malloc) ==> weird value, should be same as
+call printf ("%x\n", &malloc) ==> correct value
+
+Fix dbxread.c symbol reading in the presence of interrupts. It
+currently leaves a cleanup to blow away the entire symbol table when a
+QUIT occurs. (What's wrong with that? -kingdon, 28 Oct 1993).
+
+Mipsread.c reads include files depth-first, because the dependencies
+in the psymtabs are way too inclusive (it seems to me). Figure out what
+really depends on what, to avoid recursing 20 or 30 times while reading
+real symtabs.
+
+value_add() should be subtracting the lower bound of arrays, if known,
+and possibly checking against the upper bound for error reporting.
+
+mipsread.c symbol table allocation and deallocation should be checked.
+My suspicion is that it's full of memory leaks.
+
+SunOS should have a target_lookup_symbol() for common'd things allocated
+by the shared library linker ld.so.
+
+When listing source lines, check for a preceding \n, to verify that
+the file hasn't changed out from under us.
+
+When listing source lines, eat leading whitespace corresponding to the
+line-number prefix we print. This avoids long lines wrapping.
+
+mipsread.c needs to check for old symtabs and psymtabs for the same
+files, the way it happens for dbxread.c and coffread.c, for VxWorks
+incremental symbol table reloading.
+
+Get all the remote systems (where the protocol allows it) to be able to
+stop the remote system when the GDB user types ^C (like remote.c
+does). For ebmon, use ^Ak.
+
+Possible feature: A version of the "disassemble" command which shows
+both source and assembly code ("set symbol-filename on" is a partial
+solution).
+
+investigate "x/s 0" (right now stops early) (I think maybe GDB is
+using a 0 address for bad purposes internally).
+
+Make "info path" and path_command work again (but independent of the
+environment either of gdb or that we'll pass to the inferior).
+
+Make GDB understand the GCC feature for putting octal constants in
+enums. Make it so overflow on an enum constant does not error_type
+the whole type. Allow arbitrarily large enums with type attributes.
+Put all this stuff in the testsuite.
+
+Make TYPE_CODE_ERROR with a non-zero TYPE_LENGTH more useful (print
+the value in hex; process type attributes). Add this to the
+testsuite. This way future compilers can add new types and old
+versions of GDB can do something halfway reasonable.
+
+Clean up formatting of "info registers" on MIPS and 88k. See if it
+is possible to do this generically across all target architectures.
+
+GDB gets bfd/corefile.c and gdb/corefile.c confused (this should be easy to
+repeat even with something more recent than GDB 4.9).
+
+Check that unmatched RBRAC doesn't abort().
+
+Fix mdebugread.c:parse_type to do fundamental types right (see
+rs6000_builtin_type in stabsread.c for what "right" is--the point is
+that the debug format fixes the sizes of these things and it shouldn't
+depend on stuff like TARGET_PTR_BIT and so on. For mdebug, there seem
+to be separate bt* codes for 64 bit and 32 bit things, and GDB should
+be aware of that). Also use a switch statement for clarity and speed.
+
+Investigate adding symbols in target_load--some targets do, some
+don't.
+
+Put dirname in psymtabs and change lookup*symtab to use dirname (so
+/foo/bar.c works whether compiled by cc /foo/bar.c, or cd /foo; cc
+bar.c).
+
+Merge xcoffread.c and coffread.c. Use breakpoint_re_set instead of
+fixup_breakpoints.
+
+Fix byte order and int size sins in tm-a29k.h
+(EXTRACT_RETURN_VALUE). Perhaps should reproduce bug and verify fix
+(or perhaps should just fix it...).
+
+Make a watchpoint on a constant expression an error (or warning
+perhaps)
+
+Make a watchpoint which contains a function call an error (it is
+broken now, making it work is probably not worth the effort).
+
+Re-do calls to signal() in remote.c, and inflow.c (set_sigint_trap and
+so on) to be independent of the debugging target, using target_stop to
+stop the inferior. Probably the part which is now handled by
+interrupt_query in remote.c can be done without any new features in
+the debugging target.
+
+New test case based on weird.exp but in which type numbers are not
+renumbered (thus multiply defining a type). This currently causes an
+infinite loop on "p v_comb".
+
+Nuke baseclass_addr.
+
+Nuke USG define.
+
+"source file more recent" loses on re-read
+
+Fix 386 floating point so that floating point registers are real
+registers (but code can deal at run-time if they are missing, like
+mips and 68k). This would clean up "info float" and related stuff.
+
+Look at Solaris bug in interrupt.exp. Can get out of syscall with
+PRSABORT (syscall will return EINTR) but merely doing that leads to a
+"can't read memory" error.
+
+gcc -g -c enummask.c then gdb enummask.o, then "p v". GDB complains
+about not being able to access memory location 0.
+
+-------------------- enummask.c
+enum mask
+{
+ ANIMAL = 0,
+ VEGETABLE = 1,
+ MINERAL = 2,
+ BASIC_CATEGORY = 3,
+
+ WHITE = 0,
+ BLUE = 4,
+ GREEN = 8,
+ BLACK = 0xc,
+ COLOR = 0xc,
+
+ ALIVE = 0x10,
+
+ LARGE = 0x20
+} v;
+
+If try to modify value in file with "set write off" should give
+appropriate error not "cannot access memory at address 0x65e0".
+
+Why do we allow a target to omit standard register names (NO_STD_REGS
+in tm-z8k.h)? I thought the standard register names were supposed to
+be just that, standard.
+
+Make DEBUG_EXPRESSIONS a maintenance command, dependent on
+MAINTENANCE_COMMANDS.
+
+Allow core file without exec file on RS/6000.
+
+Make sure "shell" with no arguments works right on DOS.
+
+Make gdb.ini (as well as .gdbinit) be checked on all platforms, so
+the same directory can be NFS-mounted on unix or DOS, and work the
+same way.
+
+cd ~/tmp/<M-?> causes infinite loop (where ~/tmp is a directory).
+
+Get SECT_OFF_TEXT stuff out of objfile_relocate (might be needed to
+get RS/6000 to work right, might not be immediately relevant).
+
+Clean up add_toc_to_loadinfo
+
+Think about attached processes and sharing terminal.
+
+John sez in reference to ignoring errors from tcsegpgrp if attach_flag:
+set_tty_state should not have any trouble with attached processes.
+Instead, the tty handling should leave the pgrp of the tty alone when
+attaching to processes (perhaps pass terminal_init_inferior a flag
+saying whether we're attaching).
+
+PAGE_SIZE redefined warnings on AIX. Probably should be using
+BFD_PAGE_SIZE throughout BFD.
+
+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.
+
+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"?).
+
+Modify the naked "until" command to step until past the current source
+line, rather than past the current pc value. This is tricky simply
+because the low level routines have no way of specifying a multi-line
+step range, and there is no way of saying "don't print stuff when we
+stop" from above (otherwise could just call step many times).
+
+Modify the handling of symbols grouped through BINCL/EINCL stabs to
+allocate a partial symtab for each BINCL/EINCL grouping. This will
+seriously decrease the size of inter-psymtab dependencies and hence
+lessen the amount that needs to be read in when a new source file is
+accessed.
+
+Do an "x/i $pc" after each stepi or nexti.
+
+Modify all of the disassemblers to use printf_filtered to get correct
+more filtering.
+
+Modify gdb to work correctly with Pascal.
+
+Add a command for searching memory, a la adb. It specifies size,
+mask, value, start address. ADB searches until it finds it or hits
+an error (or is interrupted).
+
+# Local Variables:
+# mode: text
+# End:
diff --git a/gdb/a29k-tdep.c b/gdb/a29k-tdep.c
new file mode 100644
index 00000000000..b3c056723ad
--- /dev/null
+++ b/gdb/a29k-tdep.c
@@ -0,0 +1,1040 @@
+/* Target-machine dependent code for the AMD 29000
+ Copyright 1990, 1991, 1992, 1993, 1994, 1995
+ Free Software Foundation, Inc.
+ Contributed by Cygnus Support. Written by Jim Kingdon.
+
+This file is part of GDB.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "gdbcore.h"
+#include "frame.h"
+#include "value.h"
+#include "symtab.h"
+#include "inferior.h"
+#include "gdbcmd.h"
+
+/* If all these bits in an instruction word are zero, it is a "tag word"
+ which precedes a function entry point and gives stack traceback info.
+ This used to be defined as 0xff000000, but that treated 0x00000deb as
+ a tag word, while it is really used as a breakpoint. */
+#define TAGWORD_ZERO_MASK 0xff00f800
+
+extern CORE_ADDR text_start; /* FIXME, kludge... */
+
+/* The user-settable top of the register stack in virtual memory. We
+ won't attempt to access any stored registers above this address, if set
+ nonzero. */
+
+static CORE_ADDR rstack_high_address = UINT_MAX;
+
+
+/* Should call_function allocate stack space for a struct return? */
+/* On the a29k objects over 16 words require the caller to allocate space. */
+int
+a29k_use_struct_convention (gcc_p, type)
+ int gcc_p;
+ struct type *type;
+{
+ return (TYPE_LENGTH (type) > 16 * 4);
+}
+
+
+/* Structure to hold cached info about function prologues. */
+
+struct prologue_info
+{
+ CORE_ADDR pc; /* First addr after fn prologue */
+ unsigned rsize, msize; /* register stack frame size, mem stack ditto */
+ unsigned mfp_used : 1; /* memory frame pointer used */
+ unsigned rsize_valid : 1; /* Validity bits for the above */
+ unsigned msize_valid : 1;
+ unsigned mfp_valid : 1;
+};
+
+/* Examine the prologue of a function which starts at PC. Return
+ the first addess past the prologue. If MSIZE is non-NULL, then
+ set *MSIZE to the memory stack frame size. If RSIZE is non-NULL,
+ then set *RSIZE to the register stack frame size (not including
+ incoming arguments and the return address & frame pointer stored
+ with them). If no prologue is found, *RSIZE is set to zero.
+ If no prologue is found, or a prologue which doesn't involve
+ allocating a memory stack frame, then set *MSIZE to zero.
+
+ Note that both msize and rsize are in bytes. This is not consistent
+ with the _User's Manual_ with respect to rsize, but it is much more
+ convenient.
+
+ If MFP_USED is non-NULL, *MFP_USED is set to nonzero if a memory
+ frame pointer is being used. */
+
+CORE_ADDR
+examine_prologue (pc, rsize, msize, mfp_used)
+ CORE_ADDR pc;
+ unsigned *msize;
+ unsigned *rsize;
+ int *mfp_used;
+{
+ long insn;
+ CORE_ADDR p = pc;
+ struct minimal_symbol *msymbol = lookup_minimal_symbol_by_pc (pc);
+ struct prologue_info *mi = 0;
+
+ if (msymbol != NULL)
+ mi = (struct prologue_info *) msymbol -> info;
+
+ if (mi != 0)
+ {
+ int valid = 1;
+ if (rsize != NULL)
+ {
+ *rsize = mi->rsize;
+ valid &= mi->rsize_valid;
+ }
+ if (msize != NULL)
+ {
+ *msize = mi->msize;
+ valid &= mi->msize_valid;
+ }
+ if (mfp_used != NULL)
+ {
+ *mfp_used = mi->mfp_used;
+ valid &= mi->mfp_valid;
+ }
+ if (valid)
+ return mi->pc;
+ }
+
+ if (rsize != NULL)
+ *rsize = 0;
+ if (msize != NULL)
+ *msize = 0;
+ if (mfp_used != NULL)
+ *mfp_used = 0;
+
+ /* Prologue must start with subtracting a constant from gr1.
+ Normally this is sub gr1,gr1,<rsize * 4>. */
+ insn = read_memory_integer (p, 4);
+ if ((insn & 0xffffff00) != 0x25010100)
+ {
+ /* If the frame is large, instead of a single instruction it
+ might be a pair of instructions:
+ const <reg>, <rsize * 4>
+ sub gr1,gr1,<reg>
+ */
+ int reg;
+ /* Possible value for rsize. */
+ unsigned int rsize0;
+
+ if ((insn & 0xff000000) != 0x03000000)
+ {
+ p = pc;
+ goto done;
+ }
+ reg = (insn >> 8) & 0xff;
+ rsize0 = (((insn >> 8) & 0xff00) | (insn & 0xff));
+ p += 4;
+ insn = read_memory_integer (p, 4);
+ if ((insn & 0xffffff00) != 0x24010100
+ || (insn & 0xff) != reg)
+ {
+ p = pc;
+ goto done;
+ }
+ if (rsize != NULL)
+ *rsize = rsize0;
+ }
+ else
+ {
+ if (rsize != NULL)
+ *rsize = (insn & 0xff);
+ }
+ p += 4;
+
+ /* Next instruction ought to be asgeu V_SPILL,gr1,rab.
+ * We don't check the vector number to allow for kernel debugging. The
+ * kernel will use a different trap number.
+ * If this insn is missing, we just keep going; Metaware R2.3u compiler
+ * generates prologue that intermixes initializations and puts the asgeu
+ * way down.
+ */
+ insn = read_memory_integer (p, 4);
+ if ((insn & 0xff00ffff) == (0x5e000100|RAB_HW_REGNUM))
+ {
+ p += 4;
+ }
+
+ /* Next instruction usually sets the frame pointer (lr1) by adding
+ <size * 4> from gr1. However, this can (and high C does) be
+ deferred until anytime before the first function call. So it is
+ OK if we don't see anything which sets lr1.
+ To allow for alternate register sets (gcc -mkernel-registers) the msp
+ register number is a compile time constant. */
+
+ /* Normally this is just add lr1,gr1,<size * 4>. */
+ insn = read_memory_integer (p, 4);
+ if ((insn & 0xffffff00) == 0x15810100)
+ p += 4;
+ else
+ {
+ /* However, for large frames it can be
+ const <reg>, <size *4>
+ add lr1,gr1,<reg>
+ */
+ int reg;
+ CORE_ADDR q;
+
+ if ((insn & 0xff000000) == 0x03000000)
+ {
+ reg = (insn >> 8) & 0xff;
+ q = p + 4;
+ insn = read_memory_integer (q, 4);
+ if ((insn & 0xffffff00) == 0x14810100
+ && (insn & 0xff) == reg)
+ p = q;
+ }
+ }
+
+ /* Next comes "add lr{<rsize-1>},msp,0", but only if a memory
+ frame pointer is in use. We just check for add lr<anything>,msp,0;
+ we don't check this rsize against the first instruction, and
+ we don't check that the trace-back tag indicates a memory frame pointer
+ is in use.
+ To allow for alternate register sets (gcc -mkernel-registers) the msp
+ register number is a compile time constant.
+
+ The recommended instruction is actually "sll lr<whatever>,msp,0".
+ We check for that, too. Originally Jim Kingdon's code seemed
+ to be looking for a "sub" instruction here, but the mask was set
+ up to lose all the time. */
+ insn = read_memory_integer (p, 4);
+ if (((insn & 0xff80ffff) == (0x15800000|(MSP_HW_REGNUM<<8))) /* add */
+ || ((insn & 0xff80ffff) == (0x81800000|(MSP_HW_REGNUM<<8)))) /* sll */
+ {
+ p += 4;
+ if (mfp_used != NULL)
+ *mfp_used = 1;
+ }
+
+ /* Next comes a subtraction from msp to allocate a memory frame,
+ but only if a memory frame is
+ being used. We don't check msize against the trace-back tag.
+
+ To allow for alternate register sets (gcc -mkernel-registers) the msp
+ register number is a compile time constant.
+
+ Normally this is just
+ sub msp,msp,<msize>
+ */
+ insn = read_memory_integer (p, 4);
+ if ((insn & 0xffffff00) ==
+ (0x25000000|(MSP_HW_REGNUM<<16)|(MSP_HW_REGNUM<<8)))
+ {
+ p += 4;
+ if (msize != NULL)
+ *msize = insn & 0xff;
+ }
+ else
+ {
+ /* For large frames, instead of a single instruction it might
+ be
+
+ const <reg>, <msize>
+ consth <reg>, <msize> ; optional
+ sub msp,msp,<reg>
+ */
+ int reg;
+ unsigned msize0;
+ CORE_ADDR q = p;
+
+ if ((insn & 0xff000000) == 0x03000000)
+ {
+ reg = (insn >> 8) & 0xff;
+ msize0 = ((insn >> 8) & 0xff00) | (insn & 0xff);
+ q += 4;
+ insn = read_memory_integer (q, 4);
+ /* Check for consth. */
+ if ((insn & 0xff000000) == 0x02000000
+ && (insn & 0x0000ff00) == reg)
+ {
+ msize0 |= (insn << 8) & 0xff000000;
+ msize0 |= (insn << 16) & 0x00ff0000;
+ q += 4;
+ insn = read_memory_integer (q, 4);
+ }
+ /* Check for sub msp,msp,<reg>. */
+ if ((insn & 0xffffff00) ==
+ (0x24000000|(MSP_HW_REGNUM<<16)|(MSP_HW_REGNUM<<8))
+ && (insn & 0xff) == reg)
+ {
+ p = q + 4;
+ if (msize != NULL)
+ *msize = msize0;
+ }
+ }
+ }
+
+ /* Next instruction might be asgeu V_SPILL,gr1,rab.
+ * We don't check the vector number to allow for kernel debugging. The
+ * kernel will use a different trap number.
+ * Metaware R2.3u compiler
+ * generates prologue that intermixes initializations and puts the asgeu
+ * way down after everything else.
+ */
+ insn = read_memory_integer (p, 4);
+ if ((insn & 0xff00ffff) == (0x5e000100|RAB_HW_REGNUM))
+ {
+ p += 4;
+ }
+
+ done:
+ if (msymbol != NULL)
+ {
+ if (mi == 0)
+ {
+ /* Add a new cache entry. */
+ mi = (struct prologue_info *)xmalloc (sizeof (struct prologue_info));
+ msymbol -> info = (char *)mi;
+ mi->rsize_valid = 0;
+ mi->msize_valid = 0;
+ mi->mfp_valid = 0;
+ }
+ /* else, cache entry exists, but info is incomplete. */
+ mi->pc = p;
+ if (rsize != NULL)
+ {
+ mi->rsize = *rsize;
+ mi->rsize_valid = 1;
+ }
+ if (msize != NULL)
+ {
+ mi->msize = *msize;
+ mi->msize_valid = 1;
+ }
+ if (mfp_used != NULL)
+ {
+ mi->mfp_used = *mfp_used;
+ mi->mfp_valid = 1;
+ }
+ }
+ return p;
+}
+
+/* Advance PC across any function entry prologue instructions
+ to reach some "real" code. */
+
+CORE_ADDR
+skip_prologue (pc)
+ CORE_ADDR pc;
+{
+ return examine_prologue (pc, NULL, NULL, NULL);
+}
+
+/*
+ * Examine the one or two word tag at the beginning of a function.
+ * The tag word is expect to be at 'p', if it is not there, we fail
+ * by returning 0. The documentation for the tag word was taken from
+ * page 7-15 of the 29050 User's Manual. We are assuming that the
+ * m bit is in bit 22 of the tag word, which seems to be the agreed upon
+ * convention today (1/15/92).
+ * msize is return in bytes.
+ */
+
+static int /* 0/1 - failure/success of finding the tag word */
+examine_tag (p, is_trans, argcount, msize, mfp_used)
+ CORE_ADDR p;
+ int *is_trans;
+ int *argcount;
+ unsigned *msize;
+ int *mfp_used;
+{
+ unsigned int tag1, tag2;
+
+ tag1 = read_memory_integer (p, 4);
+ if ((tag1 & TAGWORD_ZERO_MASK) != 0) /* Not a tag word */
+ return 0;
+ if (tag1 & (1<<23)) /* A two word tag */
+ {
+ tag2 = read_memory_integer (p-4, 4);
+ if (msize)
+ *msize = tag2 * 2;
+ }
+ else /* A one word tag */
+ {
+ if (msize)
+ *msize = tag1 & 0x7ff;
+ }
+ if (is_trans)
+ *is_trans = ((tag1 & (1<<21)) ? 1 : 0);
+ /* Note that this includes the frame pointer and the return address
+ register, so the actual number of registers of arguments is two less.
+ argcount can be zero, however, sometimes, for strange assembler
+ routines. */
+ if (argcount)
+ *argcount = (tag1 >> 16) & 0x1f;
+ if (mfp_used)
+ *mfp_used = ((tag1 & (1<<22)) ? 1 : 0);
+ return 1;
+}
+
+/* Initialize the frame. In addition to setting "extra" frame info,
+ we also set ->frame because we use it in a nonstandard way, and ->pc
+ because we need to know it to get the other stuff. See the diagram
+ of stacks and the frame cache in tm-a29k.h for more detail. */
+
+static void
+init_frame_info (innermost_frame, frame)
+ int innermost_frame;
+ struct frame_info *frame;
+{
+ CORE_ADDR p;
+ long insn;
+ unsigned rsize;
+ unsigned msize;
+ int mfp_used, trans;
+ struct symbol *func;
+
+ p = frame->pc;
+
+ if (innermost_frame)
+ frame->frame = read_register (GR1_REGNUM);
+ else
+ frame->frame = frame->next->frame + frame->next->rsize;
+
+#if 0 /* CALL_DUMMY_LOCATION == ON_STACK */
+ This wont work;
+#else
+ if (PC_IN_CALL_DUMMY (p, 0, 0))
+#endif
+ {
+ frame->rsize = DUMMY_FRAME_RSIZE;
+ /* This doesn't matter since we never try to get locals or args
+ from a dummy frame. */
+ frame->msize = 0;
+ /* Dummy frames always use a memory frame pointer. */
+ frame->saved_msp =
+ read_register_stack_integer (frame->frame + DUMMY_FRAME_RSIZE - 4, 4);
+ frame->flags |= (TRANSPARENT_FRAME|MFP_USED);
+ return;
+ }
+
+ func = find_pc_function (p);
+ if (func != NULL)
+ p = BLOCK_START (SYMBOL_BLOCK_VALUE (func));
+ else
+ {
+ /* Search backward to find the trace-back tag. However,
+ do not trace back beyond the start of the text segment
+ (just as a sanity check to avoid going into never-never land). */
+#if 1
+ while (p >= text_start
+ && ((insn = read_memory_integer (p, 4)) & TAGWORD_ZERO_MASK) != 0)
+ p -= 4;
+#else /* 0 */
+ char pat[4] = {0, 0, 0, 0};
+ char mask[4];
+ char insn_raw[4];
+ store_unsigned_integer (mask, 4, TAGWORD_ZERO_MASK);
+ /* Enable this once target_search is enabled and tested. */
+ target_search (4, pat, mask, p, -4, text_start, p+1, &p, &insn_raw);
+ insn = extract_unsigned_integer (insn_raw, 4);
+#endif /* 0 */
+
+ if (p < text_start)
+ {
+ /* Couldn't find the trace-back tag.
+ Something strange is going on. */
+ frame->saved_msp = 0;
+ frame->rsize = 0;
+ frame->msize = 0;
+ frame->flags = TRANSPARENT_FRAME;
+ return;
+ }
+ else
+ /* Advance to the first word of the function, i.e. the word
+ after the trace-back tag. */
+ p += 4;
+ }
+
+ /* We've found the start of the function.
+ Try looking for a tag word that indicates whether there is a
+ memory frame pointer and what the memory stack allocation is.
+ If one doesn't exist, try using a more exhaustive search of
+ the prologue. */
+
+ if (examine_tag(p-4,&trans,(int *)NULL,&msize,&mfp_used)) /* Found good tag */
+ examine_prologue (p, &rsize, 0, 0);
+ else /* No tag try prologue */
+ examine_prologue (p, &rsize, &msize, &mfp_used);
+
+ frame->rsize = rsize;
+ frame->msize = msize;
+ frame->flags = 0;
+ if (mfp_used)
+ frame->flags |= MFP_USED;
+ if (trans)
+ frame->flags |= TRANSPARENT_FRAME;
+ if (innermost_frame)
+ {
+ frame->saved_msp = read_register (MSP_REGNUM) + msize;
+ }
+ else
+ {
+ if (mfp_used)
+ frame->saved_msp =
+ read_register_stack_integer (frame->frame + rsize - 4, 4);
+ else
+ frame->saved_msp = frame->next->saved_msp + msize;
+ }
+}
+
+void
+init_extra_frame_info (frame)
+ struct frame_info *frame;
+{
+ if (frame->next == 0)
+ /* Assume innermost frame. May produce strange results for "info frame"
+ but there isn't any way to tell the difference. */
+ init_frame_info (1, frame);
+ else {
+ /* We're in get_prev_frame_info.
+ Take care of everything in init_frame_pc. */
+ ;
+ }
+}
+
+void
+init_frame_pc (fromleaf, frame)
+ int fromleaf;
+ struct frame_info *frame;
+{
+ frame->pc = (fromleaf ? SAVED_PC_AFTER_CALL (frame->next) :
+ frame->next ? FRAME_SAVED_PC (frame->next) : read_pc ());
+ init_frame_info (fromleaf, frame);
+}
+
+/* Local variables (i.e. LOC_LOCAL) are on the memory stack, with their
+ offsets being relative to the memory stack pointer (high C) or
+ saved_msp (gcc). */
+
+CORE_ADDR
+frame_locals_address (fi)
+ struct frame_info *fi;
+{
+ if (fi->flags & MFP_USED)
+ return fi->saved_msp;
+ else
+ return fi->saved_msp - fi->msize;
+}
+
+/* Routines for reading the register stack. The caller gets to treat
+ the register stack as a uniform stack in memory, from address $gr1
+ straight through $rfb and beyond. */
+
+/* Analogous to read_memory except the length is understood to be 4.
+ Also, myaddr can be NULL (meaning don't bother to read), and
+ if actual_mem_addr is non-NULL, store there the address that it
+ was fetched from (or if from a register the offset within
+ registers). Set *LVAL to lval_memory or lval_register, depending
+ on where it came from. The contents written into MYADDR are in
+ target format. */
+void
+read_register_stack (memaddr, myaddr, actual_mem_addr, lval)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ CORE_ADDR *actual_mem_addr;
+ enum lval_type *lval;
+{
+ long rfb = read_register (RFB_REGNUM);
+ long rsp = read_register (RSP_REGNUM);
+
+ /* If we don't do this 'info register' stops in the middle. */
+ if (memaddr >= rstack_high_address)
+ {
+ /* a bogus value */
+ static char val[] = {~0, ~0, ~0, ~0};
+ /* It's in a local register, but off the end of the stack. */
+ int regnum = (memaddr - rsp) / 4 + LR0_REGNUM;
+ if (myaddr != NULL)
+ {
+ /* Provide bogusness */
+ memcpy (myaddr, val, 4);
+ }
+ supply_register(regnum, val); /* More bogusness */
+ if (lval != NULL)
+ *lval = lval_register;
+ if (actual_mem_addr != NULL)
+ *actual_mem_addr = REGISTER_BYTE (regnum);
+ }
+ /* If it's in the part of the register stack that's in real registers,
+ get the value from the registers. If it's anywhere else in memory
+ (e.g. in another thread's saved stack), skip this part and get
+ it from real live memory. */
+ else if (memaddr < rfb && memaddr >= rsp)
+ {
+ /* It's in a register. */
+ int regnum = (memaddr - rsp) / 4 + LR0_REGNUM;
+ if (regnum > LR0_REGNUM + 127)
+ error ("Attempt to read register stack out of range.");
+ if (myaddr != NULL)
+ read_register_gen (regnum, myaddr);
+ if (lval != NULL)
+ *lval = lval_register;
+ if (actual_mem_addr != NULL)
+ *actual_mem_addr = REGISTER_BYTE (regnum);
+ }
+ else
+ {
+ /* It's in the memory portion of the register stack. */
+ if (myaddr != NULL)
+ read_memory (memaddr, myaddr, 4);
+ if (lval != NULL)
+ *lval = lval_memory;
+ if (actual_mem_addr != NULL)
+ *actual_mem_addr = memaddr;
+ }
+}
+
+/* Analogous to read_memory_integer
+ except the length is understood to be 4. */
+long
+read_register_stack_integer (memaddr, len)
+ CORE_ADDR memaddr;
+ int len;
+{
+ char buf[4];
+ read_register_stack (memaddr, buf, NULL, NULL);
+ return extract_signed_integer (buf, 4);
+}
+
+/* Copy 4 bytes from GDB memory at MYADDR into inferior memory
+ at MEMADDR and put the actual address written into in
+ *ACTUAL_MEM_ADDR. */
+static void
+write_register_stack (memaddr, myaddr, actual_mem_addr)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ CORE_ADDR *actual_mem_addr;
+{
+ long rfb = read_register (RFB_REGNUM);
+ long rsp = read_register (RSP_REGNUM);
+ /* If we don't do this 'info register' stops in the middle. */
+ if (memaddr >= rstack_high_address)
+ {
+ /* It's in a register, but off the end of the stack. */
+ if (actual_mem_addr != NULL)
+ *actual_mem_addr = 0;
+ }
+ else if (memaddr < rfb)
+ {
+ /* It's in a register. */
+ int regnum = (memaddr - rsp) / 4 + LR0_REGNUM;
+ if (regnum < LR0_REGNUM || regnum > LR0_REGNUM + 127)
+ error ("Attempt to read register stack out of range.");
+ if (myaddr != NULL)
+ write_register (regnum, *(long *)myaddr);
+ if (actual_mem_addr != NULL)
+ *actual_mem_addr = 0;
+ }
+ else
+ {
+ /* It's in the memory portion of the register stack. */
+ if (myaddr != NULL)
+ write_memory (memaddr, myaddr, 4);
+ if (actual_mem_addr != NULL)
+ *actual_mem_addr = memaddr;
+ }
+}
+
+/* Find register number REGNUM relative to FRAME and put its
+ (raw) contents in *RAW_BUFFER. Set *OPTIMIZED if the variable
+ was optimized out (and thus can't be fetched). If the variable
+ was fetched from memory, set *ADDRP to where it was fetched from,
+ otherwise it was fetched from a register.
+
+ The argument RAW_BUFFER must point to aligned memory. */
+
+void
+get_saved_register (raw_buffer, optimized, addrp, frame, regnum, lvalp)
+ char *raw_buffer;
+ int *optimized;
+ CORE_ADDR *addrp;
+ struct frame_info *frame;
+ int regnum;
+ enum lval_type *lvalp;
+{
+ struct frame_info *fi;
+ CORE_ADDR addr;
+ enum lval_type lval;
+
+ if (!target_has_registers)
+ error ("No registers.");
+
+ /* Probably now redundant with the target_has_registers check. */
+ if (frame == 0)
+ return;
+
+ /* Once something has a register number, it doesn't get optimized out. */
+ if (optimized != NULL)
+ *optimized = 0;
+ if (regnum == RSP_REGNUM)
+ {
+ if (raw_buffer != NULL)
+ {
+ store_address (raw_buffer, REGISTER_RAW_SIZE (regnum), frame->frame);
+ }
+ if (lvalp != NULL)
+ *lvalp = not_lval;
+ return;
+ }
+ else if (regnum == PC_REGNUM && frame->next != NULL)
+ {
+ if (raw_buffer != NULL)
+ {
+ store_address (raw_buffer, REGISTER_RAW_SIZE (regnum), frame->pc);
+ }
+
+ /* Not sure we have to do this. */
+ if (lvalp != NULL)
+ *lvalp = not_lval;
+
+ return;
+ }
+ else if (regnum == MSP_REGNUM)
+ {
+ if (raw_buffer != NULL)
+ {
+ if (frame->next != NULL)
+ {
+ store_address (raw_buffer, REGISTER_RAW_SIZE (regnum),
+ frame->next->saved_msp);
+ }
+ else
+ read_register_gen (MSP_REGNUM, raw_buffer);
+ }
+ /* The value may have been computed, not fetched. */
+ if (lvalp != NULL)
+ *lvalp = not_lval;
+ return;
+ }
+ else if (regnum < LR0_REGNUM || regnum >= LR0_REGNUM + 128)
+ {
+ /* These registers are not saved over procedure calls,
+ so just print out the current values. */
+ if (raw_buffer != NULL)
+ read_register_gen (regnum, raw_buffer);
+ if (lvalp != NULL)
+ *lvalp = lval_register;
+ if (addrp != NULL)
+ *addrp = REGISTER_BYTE (regnum);
+ return;
+ }
+
+ addr = frame->frame + (regnum - LR0_REGNUM) * 4;
+ if (raw_buffer != NULL)
+ read_register_stack (addr, raw_buffer, &addr, &lval);
+ if (lvalp != NULL)
+ *lvalp = lval;
+ if (addrp != NULL)
+ *addrp = addr;
+}
+
+
+/* Discard from the stack the innermost frame,
+ restoring all saved registers. */
+
+void
+pop_frame ()
+{
+ struct frame_info *frame = get_current_frame ();
+ CORE_ADDR rfb = read_register (RFB_REGNUM);
+ CORE_ADDR gr1 = frame->frame + frame->rsize;
+ CORE_ADDR lr1;
+ CORE_ADDR original_lr0;
+ int must_fix_lr0 = 0;
+ int i;
+
+ /* If popping a dummy frame, need to restore registers. */
+ if (PC_IN_CALL_DUMMY (read_register (PC_REGNUM),
+ read_register (SP_REGNUM),
+ FRAME_FP (frame)))
+ {
+ int lrnum = LR0_REGNUM + DUMMY_ARG/4;
+ for (i = 0; i < DUMMY_SAVE_SR128; ++i)
+ write_register (SR_REGNUM (i + 128),read_register (lrnum++));
+ for (i = 0; i < DUMMY_SAVE_SR160; ++i)
+ write_register (SR_REGNUM(i+160), read_register (lrnum++));
+ for (i = 0; i < DUMMY_SAVE_GREGS; ++i)
+ write_register (RETURN_REGNUM + i, read_register (lrnum++));
+ /* Restore the PCs and prepare to restore LR0. */
+ write_register(PC_REGNUM, read_register (lrnum++));
+ write_register(NPC_REGNUM, read_register (lrnum++));
+ write_register(PC2_REGNUM, read_register (lrnum++));
+ original_lr0 = read_register (lrnum++);
+ must_fix_lr0 = 1;
+ }
+
+ /* Restore the memory stack pointer. */
+ write_register (MSP_REGNUM, frame->saved_msp);
+ /* Restore the register stack pointer. */
+ write_register (GR1_REGNUM, gr1);
+
+ /* If we popped a dummy frame, restore lr0 now that gr1 has been restored. */
+ if (must_fix_lr0)
+ write_register (LR0_REGNUM, original_lr0);
+
+ /* Check whether we need to fill registers. */
+ lr1 = read_register (LR0_REGNUM + 1);
+ if (lr1 > rfb)
+ {
+ /* Fill. */
+ int num_bytes = lr1 - rfb;
+ int i;
+ long word;
+
+ write_register (RAB_REGNUM, read_register (RAB_REGNUM) + num_bytes);
+ write_register (RFB_REGNUM, lr1);
+ for (i = 0; i < num_bytes; i += 4)
+ {
+ /* Note: word is in host byte order. */
+ word = read_memory_integer (rfb + i, 4);
+ write_register (LR0_REGNUM + ((rfb - gr1) % 0x80) + i / 4, word);
+ }
+ }
+ flush_cached_frames ();
+}
+
+/* Push an empty stack frame, to record the current PC, etc. */
+
+void
+push_dummy_frame ()
+{
+ long w;
+ CORE_ADDR rab, gr1;
+ CORE_ADDR msp = read_register (MSP_REGNUM);
+ int lrnum, i;
+ CORE_ADDR original_lr0;
+
+ /* Read original lr0 before changing gr1. This order isn't really needed
+ since GDB happens to have a snapshot of all the regs and doesn't toss
+ it when gr1 is changed. But it's The Right Thing To Do. */
+ original_lr0 = read_register (LR0_REGNUM);
+
+ /* Allocate the new frame. */
+ gr1 = read_register (GR1_REGNUM) - DUMMY_FRAME_RSIZE;
+ write_register (GR1_REGNUM, gr1);
+
+#ifdef VXWORKS_TARGET
+ /* We force re-reading all registers to get the new local registers set
+ after gr1 has been modified. This fix is due to the lack of single
+ register read/write operation in the RPC interface between VxGDB and
+ VxWorks. This really must be changed ! */
+
+ vx_read_register (-1);
+
+#endif /* VXWORK_TARGET */
+
+ rab = read_register (RAB_REGNUM);
+ if (gr1 < rab)
+ {
+ /* We need to spill registers. */
+ int num_bytes = rab - gr1;
+ CORE_ADDR rfb = read_register (RFB_REGNUM);
+ int i;
+ long word;
+
+ write_register (RFB_REGNUM, rfb - num_bytes);
+ write_register (RAB_REGNUM, gr1);
+ for (i = 0; i < num_bytes; i += 4)
+ {
+ /* Note: word is in target byte order. */
+ read_register_gen (LR0_REGNUM + i / 4, (char *) &word);
+ write_memory (rfb - num_bytes + i, (char *) &word, 4);
+ }
+ }
+
+ /* There are no arguments in to the dummy frame, so we don't need
+ more than rsize plus the return address and lr1. */
+ write_register (LR0_REGNUM + 1, gr1 + DUMMY_FRAME_RSIZE + 2 * 4);
+
+ /* Set the memory frame pointer. */
+ write_register (LR0_REGNUM + DUMMY_FRAME_RSIZE / 4 - 1, msp);
+
+ /* Allocate arg_slop. */
+ write_register (MSP_REGNUM, msp - 16 * 4);
+
+ /* Save registers. */
+ lrnum = LR0_REGNUM + DUMMY_ARG/4;
+ for (i = 0; i < DUMMY_SAVE_SR128; ++i)
+ write_register (lrnum++, read_register (SR_REGNUM (i + 128)));
+ for (i = 0; i < DUMMY_SAVE_SR160; ++i)
+ write_register (lrnum++, read_register (SR_REGNUM (i + 160)));
+ for (i = 0; i < DUMMY_SAVE_GREGS; ++i)
+ write_register (lrnum++, read_register (RETURN_REGNUM + i));
+ /* Save the PCs and LR0. */
+ write_register (lrnum++, read_register (PC_REGNUM));
+ write_register (lrnum++, read_register (NPC_REGNUM));
+ write_register (lrnum++, read_register (PC2_REGNUM));
+
+ /* Why are we saving LR0? What would clobber it? (the dummy frame should
+ be below it on the register stack, no?). */
+ write_register (lrnum++, original_lr0);
+}
+
+
+
+/*
+ This routine takes three arguments and makes the cached frames look
+ as if these arguments defined a frame on the cache. This allows the
+ rest of `info frame' to extract the important arguments without much
+ difficulty. Since an individual frame on the 29K is determined by
+ three values (FP, PC, and MSP), we really need all three to do a
+ good job. */
+
+struct frame_info *
+setup_arbitrary_frame (argc, argv)
+ int argc;
+ CORE_ADDR *argv;
+{
+ struct frame_info *frame;
+
+ if (argc != 3)
+ error ("AMD 29k frame specifications require three arguments: rsp pc msp");
+
+ frame = create_new_frame (argv[0], argv[1]);
+
+ if (!frame)
+ fatal ("internal: create_new_frame returned invalid frame id");
+
+ /* Creating a new frame munges the `frame' value from the current
+ GR1, so we restore it again here. FIXME, untangle all this
+ 29K frame stuff... */
+ frame->frame = argv[0];
+
+ /* Our MSP is in argv[2]. It'd be intelligent if we could just
+ save this value in the FRAME. But the way it's set up (FIXME),
+ we must save our caller's MSP. We compute that by adding our
+ memory stack frame size to our MSP. */
+ frame->saved_msp = argv[2] + frame->msize;
+
+ return frame;
+}
+
+int
+gdb_print_insn_a29k (memaddr, info)
+ bfd_vma memaddr;
+ disassemble_info *info;
+{
+ if (TARGET_BYTE_ORDER == BIG_ENDIAN)
+ return print_insn_big_a29k (memaddr, info);
+ else
+ return print_insn_little_a29k (memaddr, info);
+}
+
+enum a29k_processor_types processor_type = a29k_unknown;
+
+void
+a29k_get_processor_type ()
+{
+ unsigned int cfg_reg = (unsigned int) read_register (CFG_REGNUM);
+
+ /* Most of these don't have freeze mode. */
+ processor_type = a29k_no_freeze_mode;
+
+ switch ((cfg_reg >> 28) & 0xf)
+ {
+ case 0:
+ fprintf_filtered (gdb_stderr, "Remote debugging an Am29000");
+ break;
+ case 1:
+ fprintf_filtered (gdb_stderr, "Remote debugging an Am29005");
+ break;
+ case 2:
+ fprintf_filtered (gdb_stderr, "Remote debugging an Am29050");
+ processor_type = a29k_freeze_mode;
+ break;
+ case 3:
+ fprintf_filtered (gdb_stderr, "Remote debugging an Am29035");
+ break;
+ case 4:
+ fprintf_filtered (gdb_stderr, "Remote debugging an Am29030");
+ break;
+ case 5:
+ fprintf_filtered (gdb_stderr, "Remote debugging an Am2920*");
+ break;
+ case 6:
+ fprintf_filtered (gdb_stderr, "Remote debugging an Am2924*");
+ break;
+ case 7:
+ fprintf_filtered (gdb_stderr, "Remote debugging an Am29040");
+ break;
+ default:
+ fprintf_filtered (gdb_stderr, "Remote debugging an unknown Am29k\n");
+ /* Don't bother to print the revision. */
+ return;
+ }
+ fprintf_filtered (gdb_stderr, " revision %c\n", 'A' + ((cfg_reg >> 24) & 0x0f));
+}
+
+#ifdef GET_LONGJMP_TARGET
+/* Figure out where the longjmp will land. We expect that we have just entered
+ longjmp and haven't yet setup the stack frame, so the args are still in the
+ output regs. lr2 (LR2_REGNUM) points at the jmp_buf structure from which we
+ extract the pc (JB_PC) that we will land at. The pc is copied into ADDR.
+ This routine returns true on success */
+
+int
+get_longjmp_target(pc)
+ CORE_ADDR *pc;
+{
+ CORE_ADDR jb_addr;
+ char buf[sizeof(CORE_ADDR)];
+
+ jb_addr = read_register(LR2_REGNUM);
+
+ if (target_read_memory(jb_addr + JB_PC * JB_ELEMENT_SIZE, (char *) buf,
+ sizeof(CORE_ADDR)))
+ return 0;
+
+ *pc = extract_address ((PTR) buf, sizeof(CORE_ADDR));
+ return 1;
+}
+#endif /* GET_LONGJMP_TARGET */
+
+void
+_initialize_a29k_tdep ()
+{
+ extern CORE_ADDR text_end;
+
+ tm_print_insn = gdb_print_insn_a29k;
+
+ /* FIXME, there should be a way to make a CORE_ADDR variable settable. */
+ add_show_from_set
+ (add_set_cmd ("rstack_high_address", class_support, var_uinteger,
+ (char *)&rstack_high_address,
+ "Set top address in memory of the register stack.\n\
+Attempts to access registers saved above this address will be ignored\n\
+or will produce the value -1.", &setlist),
+ &showlist);
+
+ /* FIXME, there should be a way to make a CORE_ADDR variable settable. */
+ add_show_from_set
+ (add_set_cmd ("call_scratch_address", class_support, var_uinteger,
+ (char *)&text_end,
+"Set address in memory where small amounts of RAM can be used\n\
+when making function calls into the inferior.", &setlist),
+ &showlist);
+}
diff --git a/gdb/a68v-nat.c b/gdb/a68v-nat.c
new file mode 100644
index 00000000000..95bb3c83716
--- /dev/null
+++ b/gdb/a68v-nat.c
@@ -0,0 +1,123 @@
+/* Host-dependent code for Apollo-68ks 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "inferior.h"
+
+#ifndef _ISP__M68K
+#define _ISP__M68K 1
+#endif
+
+#include <ptrace.h>
+
+extern int errno;
+
+void
+fetch_inferior_registers (ignored)
+ int ignored;
+{
+ struct ptrace_$data_regs_m68k inferior_registers;
+ struct ptrace_$floating_regs_m68k inferior_fp_registers;
+ struct ptrace_$control_regs_m68k inferior_control_registers;
+ extern char registers[];
+
+ ptrace_$init_control(&inferior_control_registers);
+ inferior_fp_registers.size = sizeof(inferior_fp_registers);
+
+ registers_fetched ();
+
+ ptrace (PTRACE_GETREGS, inferior_pid,
+ (PTRACE_ARG3_TYPE) &inferior_registers,
+ ptrace_$data_set,
+ (PTRACE_ARG3_TYPE) &inferior_registers,
+ ptrace_$data_set);
+
+ ptrace (PTRACE_GETREGS, inferior_pid,
+ (PTRACE_ARG3_TYPE) &inferior_fp_registers,
+ ptrace_$floating_set_m68k,
+ (PTRACE_ARG3_TYPE) &inferior_fp_registers,
+ ptrace_$floating_set_m68k);
+
+ ptrace (PTRACE_GETREGS, inferior_pid,
+ (PTRACE_ARG3_TYPE) &inferior_control_registers,
+ ptrace_$control_set_m68k,
+ (PTRACE_ARG3_TYPE) &inferior_control_registers,
+ ptrace_$control_set_m68k);
+
+ bcopy (&inferior_registers, registers, 16 * 4);
+ bcopy (&inferior_fp_registers, &registers[REGISTER_BYTE (FP0_REGNUM)],
+ sizeof inferior_fp_registers.regs);
+ *(int *)&registers[REGISTER_BYTE (PS_REGNUM)] = inferior_control_registers.sr;
+ *(int *)&registers[REGISTER_BYTE (PC_REGNUM)] = inferior_control_registers.pc;
+}
+
+/* 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;
+{
+ struct ptrace_$data_regs_m68k inferior_registers;
+ struct ptrace_$floating_regs_m68k inferior_fp_registers;
+ struct ptrace_$control_regs_m68k inferior_control_registers;
+ extern char registers[];
+
+ ptrace_$init_control(&inferior_control_registers);
+ inferior_fp_registers.size = sizeof(inferior_fp_registers);
+
+ ptrace (PTRACE_GETREGS, inferior_pid,
+ (PTRACE_ARG3_TYPE) &inferior_fp_registers,
+ ptrace_$floating_set_m68k,
+ (PTRACE_ARG3_TYPE) &inferior_fp_registers,
+ ptrace_$floating_set_m68k);
+
+ ptrace (PTRACE_GETREGS, inferior_pid,
+ (PTRACE_ARG3_TYPE) &inferior_control_registers,
+ ptrace_$control_set_m68k,
+ (PTRACE_ARG3_TYPE) &inferior_control_registers,
+ ptrace_$control_set_m68k);
+
+ bcopy (registers, &inferior_registers, sizeof(inferior_registers));
+
+ bcopy (&registers[REGISTER_BYTE (FP0_REGNUM)], inferior_fp_registers.regs,
+ sizeof inferior_fp_registers.regs);
+
+ inferior_control_registers.sr = *(int *)&registers[REGISTER_BYTE (PS_REGNUM)];
+ inferior_control_registers.pc = *(int *)&registers[REGISTER_BYTE (PC_REGNUM)];
+
+ ptrace (PTRACE_SETREGS, inferior_pid,
+ (PTRACE_ARG3_TYPE) &inferior_registers,
+ ptrace_$data_set_m68k,
+ (PTRACE_ARG3_TYPE) &inferior_registers,
+ ptrace_$data_set_m68k);
+
+ ptrace (PTRACE_SETREGS, inferior_pid,
+ (PTRACE_ARG3_TYPE) &inferior_fp_registers,
+ ptrace_$floating_set_m68k,
+ (PTRACE_ARG3_TYPE) &inferior_fp_registers,
+ ptrace_$floating_set_m68k);
+
+ ptrace (PTRACE_SETREGS, inferior_pid,
+ (PTRACE_ARG3_TYPE) &inferior_control_registers,
+ ptrace_$control_set_m68k,
+ (PTRACE_ARG3_TYPE) &inferior_control_registers,
+ ptrace_$control_set_m68k);
+}
diff --git a/gdb/abug-rom.c b/gdb/abug-rom.c
new file mode 100644
index 00000000000..97ff0f8d322
--- /dev/null
+++ b/gdb/abug-rom.c
@@ -0,0 +1,169 @@
+/* Remote debugging interface for ABug Rom monitor for GDB, the GNU debugger.
+ Copyright 1995, 1996, 1998 Free Software Foundation, Inc.
+
+ Written by Rob Savoye of 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "gdbcore.h"
+#include "target.h"
+#include "monitor.h"
+#include "serial.h"
+
+/* Prototypes for local functions. */
+
+static void abug_open PARAMS ((char *args, int from_tty));
+
+static void
+abug_supply_register (regname, regnamelen, val, vallen)
+ char *regname;
+ int regnamelen;
+ char *val;
+ int vallen;
+{
+ int regno;
+
+ if (regnamelen != 2)
+ return;
+
+ switch (regname[0])
+ {
+ case 'S':
+ if (regname[1] != 'R')
+ return;
+ regno = PS_REGNUM;
+ break;
+ case 'P':
+ if (regname[1] != 'C')
+ return;
+ regno = PC_REGNUM;
+ break;
+ case 'D':
+ if (regname[1] < '0' || regname[1] > '7')
+ return;
+ regno = regname[1] - '0' + D0_REGNUM;
+ break;
+ case 'A':
+ if (regname[1] < '0' || regname[1] > '7')
+ return;
+ regno = regname[1] - '0' + A0_REGNUM;
+ break;
+ default:
+ return;
+ }
+
+ monitor_supply_register (regno, val);
+}
+
+/*
+ * This array of registers needs to match the indexes used by GDB. The
+ * whole reason this exists is because the various ROM monitors use
+ * different names than GDB does, and don't support all the
+ * registers either. So, typing "info reg sp" becomes an "A7".
+ */
+
+static char *abug_regnames[NUM_REGS] =
+{
+ "D0", "D1", "D2", "D3", "D4", "D5", "D6", "D7",
+ "A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7",
+ "PC",
+};
+
+/*
+ * Define the monitor command strings. Since these are passed directly
+ * through to a printf style function, we need can include formatting
+ * strings. We also need a CR or LF on the end.
+ */
+
+static struct target_ops abug_ops;
+
+static char *abug_inits[] = {"\r", NULL};
+
+static struct monitor_ops abug_cmds ;
+
+static void
+init_abug_cmds(void)
+{
+ abug_cmds.flags = MO_CLR_BREAK_USES_ADDR;
+ abug_cmds.init = abug_inits; /* Init strings */
+ abug_cmds.cont = "g\r"; /* continue command */
+ abug_cmds.step = "t\r"; /* single step */
+ abug_cmds.stop = NULL; /* interrupt command */
+ abug_cmds.set_break = "br %x\r"; /* set a breakpoint */
+ abug_cmds.clr_break = "nobr %x\r"; /* clear a breakpoint */
+ abug_cmds.clr_all_break = "nobr\r"; /* clear all breakpoints */
+ abug_cmds.fill = "bf %x:%x %x;b\r"; /* fill (start count val) */
+ abug_cmds.setmem.cmdb = "ms %x %02x\r"; /* setmem.cmdb (addr, value) */
+ abug_cmds.setmem.cmdw = "ms %x %04x\r"; /* setmem.cmdw (addr, value) */
+ abug_cmds.setmem.cmdl = "ms %x %08x\r"; /* setmem.cmdl (addr, value) */
+ abug_cmds.setmem.cmdll = NULL; /* setmem.cmdll (addr, value) */
+ abug_cmds.setmem.resp_delim = NULL; /* setreg.resp_delim */
+ abug_cmds.setmem.term = NULL; /* setreg.term */
+ abug_cmds.setmem.term_cmd = NULL; /* setreg.term_cmd */
+ abug_cmds.getmem.cmdb = "md %x:%x;b\r"; /* getmem.cmdb (addr, len) */
+ abug_cmds.getmem.cmdw = "md %x:%x;b\r"; /* getmem.cmdw (addr, len) */
+ abug_cmds.getmem.cmdl = "md %x:%x;b\r"; /* getmem.cmdl (addr, len) */
+ abug_cmds.getmem.cmdll = NULL; /* getmem.cmdll (addr, len) */
+ abug_cmds.getmem.resp_delim = " "; /* getmem.resp_delim */
+ abug_cmds.getmem.term = NULL; /* getmem.term */
+ abug_cmds.getmem.term_cmd = NULL; /* getmem.term_cmd */
+ abug_cmds.setreg.cmd = "rm %s %x\r"; /* setreg.cmd (name, value) */
+ abug_cmds.setreg.resp_delim = "="; /* setreg.resp_delim */
+ abug_cmds.setreg.term = "? "; /* setreg.term */
+ abug_cmds.setreg.term_cmd = ".\r" ; /* setreg.term_cmd */
+ abug_cmds.getreg.cmd = "rm %s\r"; /* getreg.cmd (name) */
+ abug_cmds.getreg.resp_delim = "="; /* getreg.resp_delim */
+ abug_cmds.getreg.term = "? "; /* getreg.term */
+ abug_cmds.getreg.term_cmd = ".\r" ; /* getreg.term_cmd */
+ abug_cmds.dump_registers = "rd\r"; /* dump_registers */
+ abug_cmds.register_pattern = "\\(\\w+\\) +=\\([0-9a-fA-F]+\\b\\)"; /* register_pattern */
+ abug_cmds.supply_register = abug_supply_register; /* supply_register */
+ abug_cmds.load_routine = NULL; /* load_routine (defaults to SRECs) */
+ abug_cmds.load = "lo 0\r"; /* download command */
+ abug_cmds.loadresp = "\n"; /* load response */
+ abug_cmds.prompt = "135Bug>"; /* monitor command prompt */
+ abug_cmds.line_term = "\r"; /* end-of-line terminator */
+ abug_cmds.cmd_end = NULL; /* optional command terminator */
+ abug_cmds.target = &abug_ops; /* target operations */
+ abug_cmds.stopbits = SERIAL_1_STOPBITS; /* number of stop bits */
+ abug_cmds.regnames = abug_regnames; /* registers names */
+ abug_cmds.magic = MONITOR_OPS_MAGIC ; /* magic */
+};
+
+static void
+abug_open(args, from_tty)
+ char *args;
+ int from_tty;
+{
+ monitor_open (args, &abug_cmds, from_tty);
+}
+
+void
+_initialize_abug_rom ()
+{
+ init_abug_cmds() ;
+ init_monitor_ops (&abug_ops);
+
+ abug_ops.to_shortname = "abug";
+ abug_ops.to_longname = "ABug monitor";
+ abug_ops.to_doc = "Debug via the ABug monitor.\n\
+Specify the serial device it is connected to (e.g. /dev/ttya).";
+ abug_ops.to_open = abug_open;
+
+ add_target (&abug_ops);
+}
diff --git a/gdb/acconfig.h b/gdb/acconfig.h
new file mode 100644
index 00000000000..9ad502094fb
--- /dev/null
+++ b/gdb/acconfig.h
@@ -0,0 +1,95 @@
+
+/* Whether malloc must be declared even if <stdlib.h> is included. */
+#undef NEED_DECLARATION_MALLOC
+
+/* Whether realloc must be declared even if <stdlib.h> is included. */
+#undef NEED_DECLARATION_REALLOC
+
+/* Whether free must be declared even if <stdlib.h> is included. */
+#undef NEED_DECLARATION_FREE
+
+/* Whether strerror must be declared even if <string.h> is included. */
+#undef NEED_DECLARATION_STRERROR
+@TOP@
+
+/* Define if pstatus_t type is available */
+#undef HAVE_PSTATUS_T
+
+/* Define if prrun_t type is available */
+#undef HAVE_PRRUN_T
+
+/* Define if fpregset_t type is available. */
+#undef HAVE_FPREGSET_T
+
+/* Define if gregset_t type is available. */
+#undef HAVE_GREGSET_T
+
+/* Define if ioctl argument PIOCSET is available. */
+#undef HAVE_PROCFS_PIOCSET
+
+/* /proc PID entries are directories containing the files
+ ctl as map status */
+#undef HAVE_MULTIPLE_PROC_FDS
+
+/* Define if the `long long' type works. */
+#undef CC_HAS_LONG_LONG
+
+/* Define if the "ll" format works to print long long ints. */
+#undef PRINTF_HAS_LONG_LONG
+
+/* Define if the "%Lg" format works to print long doubles. */
+#undef PRINTF_HAS_LONG_DOUBLE
+
+/* Define if the "%Lg" format works to scan long doubles. */
+#undef SCANF_HAS_LONG_DOUBLE
+
+/* Define if using Solaris thread debugging. */
+#undef HAVE_THREAD_DB_LIB
+
+/* Define on a GNU/Linux system to work around problems in sys/procfs.h. */
+#undef START_INFERIOR_TRAPS_EXPECTED
+#undef sys_quotactl
+
+/* Define if you have HPUX threads */
+#undef HAVE_HPUX_THREAD_SUPPORT
+
+/* Define if you want to use the memory mapped malloc package (mmalloc). */
+#undef USE_MMALLOC
+
+/* Define if the runtime uses a routine from mmalloc before gdb has a chance
+ to initialize mmalloc, and we want to force checking to be used anyway.
+ This may cause spurious memory corruption messages if the runtime tries
+ to explicitly deallocate that memory when gdb calls exit. */
+#undef MMCHECK_FORCE
+
+/* Define to 1 if NLS is requested. */
+#undef ENABLE_NLS
+
+/* Define as 1 if you have catgets and don't want to use GNU gettext. */
+#undef HAVE_CATGETS
+
+/* Define as 1 if you have gettext and don't want to use GNU gettext. */
+#undef HAVE_GETTEXT
+
+/* Define as 1 if you have the stpcpy function. */
+#undef HAVE_STPCPY
+
+/* Define if your locale.h file contains LC_MESSAGES. */
+#undef HAVE_LC_MESSAGES
+
+/* Define if you want to use the full-screen terminal user interface. */
+#undef TUI
+
+/* Define if <proc_service.h> on solaris uses int instead of
+ size_t, and assorted other type changes. */
+#undef PROC_SERVICE_IS_OLD
+
+/* If you want to specify a default CPU variant, define this to be its
+ name, as a C string. */
+#undef TARGET_CPU_DEFAULT
+
+/* Set to true if the save_state_t structure is present */
+#define HAVE_STRUCT_SAVE_STATE_T 0
+
+/* Set to true if the save_state_t structure has the ss_wide member */
+#define HAVE_STRUCT_MEMBER_SS_WIDE 0
diff --git a/gdb/acinclude.m4 b/gdb/acinclude.m4
new file mode 100644
index 00000000000..43a0b0d57e7
--- /dev/null
+++ b/gdb/acinclude.m4
@@ -0,0 +1,861 @@
+dnl written by Rob Savoye <rob@cygnus.com> for Cygnus Support
+dnl major rewriting for Tcl 7.5 by Don Libes <libes@nist.gov>
+
+dnl gdb/configure.in uses BFD_NEED_DECLARATION, so get its definition.
+sinclude(../bfd/acinclude.m4)
+
+dnl This gets the standard macros, like the TCL, TK, etc ones.
+sinclude(../config/acinclude.m4)
+
+dnl CYGNUS LOCAL: This gets the right posix flag for gcc
+AC_DEFUN(CY_AC_TCL_LYNX_POSIX,
+[AC_REQUIRE([AC_PROG_CC])AC_REQUIRE([AC_PROG_CPP])
+AC_MSG_CHECKING([if running LynxOS])
+AC_CACHE_VAL(ac_cv_os_lynx,
+[AC_EGREP_CPP(yes,
+[/*
+ * The old Lynx "cc" only defines "Lynx", but the newer one uses "__Lynx__"
+ */
+#if defined(__Lynx__) || defined(Lynx)
+yes
+#endif
+], ac_cv_os_lynx=yes, ac_cv_os_lynx=no)])
+#
+if test "$ac_cv_os_lynx" = "yes" ; then
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(LYNX)
+ AC_MSG_CHECKING([whether -mposix or -X is available])
+ AC_CACHE_VAL(ac_cv_c_posix_flag,
+ [AC_TRY_COMPILE(,[
+ /*
+ * This flag varies depending on how old the compiler is.
+ * -X is for the old "cc" and "gcc" (based on 1.42).
+ * -mposix is for the new gcc (at least 2.5.8).
+ */
+ #if defined(__GNUC__) && __GNUC__ >= 2
+ choke me
+ #endif
+ ], ac_cv_c_posix_flag=" -mposix", ac_cv_c_posix_flag=" -X")])
+ CC="$CC $ac_cv_c_posix_flag"
+ AC_MSG_RESULT($ac_cv_c_posix_flag)
+ else
+ AC_MSG_RESULT(no)
+fi
+])
+
+#
+# Sometimes the native compiler is a bogus stub for gcc or /usr/ucb/cc. This
+# makes configure think it's cross compiling. If --target wasn't used, then
+# we can't configure, so something is wrong. We don't use the cache
+# here cause if somebody fixes their compiler install, we want this to work.
+AC_DEFUN(CY_AC_C_WORKS,
+[# If we cannot compile and link a trivial program, we can't expect anything to work
+AC_MSG_CHECKING(whether the compiler ($CC) actually works)
+AC_TRY_COMPILE(, [/* don't need anything here */],
+ c_compiles=yes, c_compiles=no)
+
+AC_TRY_LINK(, [/* don't need anything here */],
+ c_links=yes, c_links=no)
+
+if test x"${c_compiles}" = x"no" ; then
+ AC_MSG_ERROR(the native compiler is broken and won't compile.)
+fi
+
+if test x"${c_links}" = x"no" ; then
+ AC_MSG_ERROR(the native compiler is broken and won't link.)
+fi
+AC_MSG_RESULT(yes)
+])
+
+AC_DEFUN(CY_AC_PATH_TCLH, [
+#
+# Ok, lets find the tcl source trees so we can use the headers
+# Warning: transition of version 9 to 10 will break this algorithm
+# because 10 sorts before 9. We also look for just tcl. We have to
+# be careful that we don't match stuff like tclX by accident.
+# the alternative search directory is involked by --with-tclinclude
+#
+
+no_tcl=true
+AC_MSG_CHECKING(for Tcl private headers. dir=${configdir})
+AC_ARG_WITH(tclinclude, [ --with-tclinclude=DIR Directory where tcl private headers are], with_tclinclude=${withval})
+AC_CACHE_VAL(ac_cv_c_tclh,[
+# first check to see if --with-tclinclude was specified
+if test x"${with_tclinclude}" != x ; then
+ if test -f ${with_tclinclude}/tclInt.h ; then
+ ac_cv_c_tclh=`(cd ${with_tclinclude}; pwd)`
+ elif test -f ${with_tclinclude}/generic/tclInt.h ; then
+ ac_cv_c_tclh=`(cd ${with_tclinclude}/generic; pwd)`
+ else
+ AC_MSG_ERROR([${with_tclinclude} directory doesn't contain private headers])
+ fi
+fi
+
+# next check if it came with Tcl configuration file
+if test x"${ac_cv_c_tclconfig}" = x ; then
+ if test -f $ac_cv_c_tclconfig/../generic/tclInt.h ; then
+ ac_cv_c_tclh=`(cd $ac_cv_c_tclconfig/..; pwd)`
+ fi
+fi
+
+# next check in private source directory
+#
+# since ls returns lowest version numbers first, reverse its output
+if test x"${ac_cv_c_tclh}" = x ; then
+ for i in \
+ ${srcdir}/../tcl \
+ `ls -dr ${srcdir}/../tcl[[7-9]]* 2>/dev/null` \
+ ${srcdir}/../../tcl \
+ `ls -dr ${srcdir}/../../tcl[[7-9]]* 2>/dev/null` \
+ ${srcdir}/../../../tcl \
+ `ls -dr ${srcdir}/../../../tcl[[7-9]]* 2>/dev/null ` ; do
+ if test -f $i/generic/tclInt.h ; then
+ ac_cv_c_tclh=`(cd $i/generic; pwd)`
+ break
+ fi
+ done
+fi
+# finally check in a few common install locations
+#
+# since ls returns lowest version numbers first, reverse its output
+if test x"${ac_cv_c_tclh}" = x ; then
+ for i in \
+ `ls -dr /usr/local/src/tcl[[7-9]]* 2>/dev/null` \
+ `ls -dr /usr/local/lib/tcl[[7-9]]* 2>/dev/null` \
+ /usr/local/src/tcl \
+ /usr/local/lib/tcl \
+ ${prefix}/include ; do
+ if test -f $i/generic/tclInt.h ; then
+ ac_cv_c_tclh=`(cd $i/generic; pwd)`
+ break
+ fi
+ done
+fi
+# see if one is installed
+if test x"${ac_cv_c_tclh}" = x ; then
+ AC_HEADER_CHECK(tclInt.h, ac_cv_c_tclh=installed, ac_cv_c_tclh="")
+fi
+])
+if test x"${ac_cv_c_tclh}" = x ; then
+ TCLHDIR="# no Tcl private headers found"
+ AC_MSG_ERROR([Can't find Tcl private headers])
+fi
+if test x"${ac_cv_c_tclh}" != x ; then
+ no_tcl=""
+ if test x"${ac_cv_c_tclh}" = x"installed" ; then
+ AC_MSG_RESULT([is installed])
+ TCLHDIR=""
+ else
+ AC_MSG_RESULT([found in ${ac_cv_c_tclh}])
+ # this hack is cause the TCLHDIR won't print if there is a "-I" in it.
+ TCLHDIR="-I${ac_cv_c_tclh}"
+ fi
+fi
+
+AC_SUBST(TCLHDIR)
+])
+
+
+AC_DEFUN(CY_AC_PATH_TCLCONFIG, [
+#
+# Ok, lets find the tcl configuration
+# First, look for one uninstalled.
+# the alternative search directory is invoked by --with-tclconfig
+#
+
+if test x"${no_tcl}" = x ; then
+ # we reset no_tcl in case something fails here
+ no_tcl=true
+ AC_ARG_WITH(tclconfig, [ --with-tclconfig=DIR Directory containing tcl configuration (tclConfig.sh)],
+ with_tclconfig=${withval})
+ AC_MSG_CHECKING([for Tcl configuration])
+ AC_CACHE_VAL(ac_cv_c_tclconfig,[
+
+ # First check to see if --with-tclconfig was specified.
+ if test x"${with_tclconfig}" != x ; then
+ if test -f "${with_tclconfig}/tclConfig.sh" ; then
+ ac_cv_c_tclconfig=`(cd ${with_tclconfig}; pwd)`
+ else
+ AC_MSG_ERROR([${with_tclconfig} directory doesn't contain tclConfig.sh])
+ fi
+ fi
+
+ # then check for a private Tcl installation
+ if test x"${ac_cv_c_tclconfig}" = x ; then
+ for i in \
+ ../tcl \
+ `ls -dr ../tcl[[7-9]]* 2>/dev/null` \
+ ../../tcl \
+ `ls -dr ../../tcl[[7-9]]* 2>/dev/null` \
+ ../../../tcl \
+ `ls -dr ../../../tcl[[7-9]]* 2>/dev/null` ; do
+ if test -f "$i/${configdir}/tclConfig.sh" ; then
+ ac_cv_c_tclconfig=`(cd $i/${configdir}; pwd)`
+ break
+ fi
+ done
+ fi
+ # check in a few common install locations
+ if test x"${ac_cv_c_tclconfig}" = x ; then
+ for i in `ls -d ${prefix}/lib /usr/local/lib 2>/dev/null` ; do
+ if test -f "$i/tclConfig.sh" ; then
+ ac_cv_c_tclconfig=`(cd $i; pwd)`
+ break
+ fi
+ done
+ fi
+ # check in a few other private locations
+ if test x"${ac_cv_c_tclconfig}" = x ; then
+ for i in \
+ ${srcdir}/../tcl \
+ `ls -dr ${srcdir}/../tcl[[7-9]]* 2>/dev/null` ; do
+ if test -f "$i/${configdir}/tclConfig.sh" ; then
+ ac_cv_c_tclconfig=`(cd $i/${configdir}; pwd)`
+ break
+ fi
+ done
+ fi
+ ])
+ if test x"${ac_cv_c_tclconfig}" = x ; then
+ TCLCONFIG="# no Tcl configs found"
+ AC_MSG_WARN(Can't find Tcl configuration definitions)
+ else
+ no_tcl=
+ TCLCONFIG=${ac_cv_c_tclconfig}/tclConfig.sh
+ AC_MSG_RESULT(found $TCLCONFIG)
+ fi
+fi
+])
+
+# Defined as a separate macro so we don't have to cache the values
+# from PATH_TCLCONFIG (because this can also be cached).
+AC_DEFUN(CY_AC_LOAD_TCLCONFIG, [
+ . $TCLCONFIG
+
+ AC_SUBST(TCL_VERSION)
+ AC_SUBST(TCL_MAJOR_VERSION)
+ AC_SUBST(TCL_MINOR_VERSION)
+ AC_SUBST(TCL_CC)
+ AC_SUBST(TCL_DEFS)
+
+dnl not used, don't export to save symbols
+dnl AC_SUBST(TCL_LIB_FILE)
+
+dnl don't export, not used outside of configure
+dnl AC_SUBST(TCL_LIBS)
+dnl not used, don't export to save symbols
+dnl AC_SUBST(TCL_PREFIX)
+
+dnl not used, don't export to save symbols
+dnl AC_SUBST(TCL_EXEC_PREFIX)
+
+ AC_SUBST(TCL_SHLIB_CFLAGS)
+ AC_SUBST(TCL_SHLIB_LD)
+dnl don't export, not used outside of configure
+ AC_SUBST(TCL_SHLIB_LD_LIBS)
+ AC_SUBST(TCL_SHLIB_SUFFIX)
+dnl not used, don't export to save symbols
+ AC_SUBST(TCL_DL_LIBS)
+ AC_SUBST(TCL_LD_FLAGS)
+dnl don't export, not used outside of configure
+ AC_SUBST(TCL_LD_SEARCH_FLAGS)
+ AC_SUBST(TCL_COMPAT_OBJS)
+ AC_SUBST(TCL_RANLIB)
+ AC_SUBST(TCL_BUILD_LIB_SPEC)
+ AC_SUBST(TCL_LIB_SPEC)
+ AC_SUBST(TCL_LIB_VERSIONS_OK)
+
+dnl not used, don't export to save symbols
+dnl AC_SUBST(TCL_SHARED_LIB_SUFFIX)
+
+dnl not used, don't export to save symbols
+dnl AC_SUBST(TCL_UNSHARED_LIB_SUFFIX)
+])
+
+# Warning: Tk definitions are very similar to Tcl definitions but
+# are not precisely the same. There are a couple of differences,
+# so don't do changes to Tcl thinking you can cut and paste it do
+# the Tk differences and later simply substitute "Tk" for "Tcl".
+# Known differences:
+# - Acceptable Tcl major version #s is 7-9 while Tk is 4-9
+# - Searching for Tcl includes looking for tclInt.h, Tk looks for tk.h
+# - Computing major/minor versions is different because Tk depends on
+# headers to Tcl, Tk, and X.
+# - Symbols in tkConfig.sh are different than tclConfig.sh
+# - Acceptable for Tk to be missing but not Tcl.
+
+AC_DEFUN(CY_AC_PATH_TKH, [
+#
+# Ok, lets find the tk source trees so we can use the headers
+# If the directory (presumably symlink) named "tk" exists, use that one
+# in preference to any others. Same logic is used when choosing library
+# and again with Tcl. The search order is the best place to look first, then in
+# decreasing significance. The loop breaks if the trigger file is found.
+# Note the gross little conversion here of srcdir by cd'ing to the found
+# directory. This converts the path from a relative to an absolute, so
+# recursive cache variables for the path will work right. We check all
+# the possible paths in one loop rather than many seperate loops to speed
+# things up.
+# the alternative search directory is involked by --with-tkinclude
+#
+no_tk=true
+AC_MSG_CHECKING(for Tk private headers)
+AC_ARG_WITH(tkinclude, [ --with-tkinclude=DIR Directory where tk private headers are], with_tkinclude=${withval})
+AC_CACHE_VAL(ac_cv_c_tkh,[
+# first check to see if --with-tkinclude was specified
+if test x"${with_tkinclude}" != x ; then
+ if test -f ${with_tkinclude}/tk.h ; then
+ ac_cv_c_tkh=`(cd ${with_tkinclude}; pwd)`
+ elif test -f ${with_tkinclude}/generic/tk.h ; then
+ ac_cv_c_tkh=`(cd ${with_tkinclude}/generic; pwd)`
+ else
+ AC_MSG_ERROR([${with_tkinclude} directory doesn't contain private headers])
+ fi
+fi
+
+# next check if it came with Tk configuration file
+if test x"${ac_cv_c_tkconfig}" = x ; then
+ if test -f $ac_cv_c_tkconfig/../generic/tk.h ; then
+ ac_cv_c_tkh=`(cd $ac_cv_c_tkconfig/..; pwd)`
+ fi
+fi
+
+# next check in private source directory
+#
+# since ls returns lowest version numbers first, reverse its output
+if test x"${ac_cv_c_tkh}" = x ; then
+ for i in \
+ ${srcdir}/../tk \
+ `ls -dr ${srcdir}/../tk[[4-9]]* 2>/dev/null` \
+ ${srcdir}/../../tk \
+ `ls -dr ${srcdir}/../../tk[[4-9]]* 2>/dev/null` \
+ ${srcdir}/../../../tk \
+ `ls -dr ${srcdir}/../../../tk[[4-9]]* 2>/dev/null ` ; do
+ if test -f $i/generic/tk.h ; then
+ ac_cv_c_tkh=`(cd $i/generic; pwd)`
+ break
+ fi
+ done
+fi
+# finally check in a few common install locations
+#
+# since ls returns lowest version numbers first, reverse its output
+if test x"${ac_cv_c_tkh}" = x ; then
+ for i in \
+ `ls -dr /usr/local/src/tk[[4-9]]* 2>/dev/null` \
+ `ls -dr /usr/local/lib/tk[[4-9]]* 2>/dev/null` \
+ /usr/local/src/tk \
+ /usr/local/lib/tk \
+ ${prefix}/include ; do
+ if test -f $i/generic/tk.h ; then
+ ac_cv_c_tkh=`(cd $i/generic; pwd)`
+ break
+ fi
+ done
+fi
+# see if one is installed
+if test x"${ac_cv_c_tkh}" = x ; then
+ AC_HEADER_CHECK(tk.h, ac_cv_c_tkh=installed, ac_cv_c_tkh="")
+fi
+])
+if test x"${ac_cv_c_tkh}" != x ; then
+ no_tk=""
+ if test x"${ac_cv_c_tkh}" = x"installed" ; then
+ AC_MSG_RESULT([is installed])
+ TKHDIR=""
+ else
+ AC_MSG_RESULT([found in ${ac_cv_c_tkh}])
+ # this hack is cause the TKHDIR won't print if there is a "-I" in it.
+ TKHDIR="-I${ac_cv_c_tkh}"
+ fi
+else
+ TKHDIR="# no Tk directory found"
+ AC_MSG_WARN([Can't find Tk private headers])
+ no_tk=true
+fi
+
+AC_SUBST(TKHDIR)
+])
+
+
+AC_DEFUN(CY_AC_PATH_TKCONFIG, [
+#
+# Ok, lets find the tk configuration
+# First, look for one uninstalled.
+# the alternative search directory is invoked by --with-tkconfig
+#
+
+if test x"${no_tk}" = x ; then
+ # we reset no_tk in case something fails here
+ no_tk=true
+ AC_ARG_WITH(tkconfig, [ --with-tkconfig=DIR Directory containing tk configuration (tkConfig.sh)],
+ with_tkconfig=${withval})
+ AC_MSG_CHECKING([for Tk configuration])
+ AC_CACHE_VAL(ac_cv_c_tkconfig,[
+
+ # First check to see if --with-tkconfig was specified.
+ if test x"${with_tkconfig}" != x ; then
+ if test -f "${with_tkconfig}/tkConfig.sh" ; then
+ ac_cv_c_tkconfig=`(cd ${with_tkconfig}; pwd)`
+ else
+ AC_MSG_ERROR([${with_tkconfig} directory doesn't contain tkConfig.sh])
+ fi
+ fi
+
+ # then check for a private Tk library
+ if test x"${ac_cv_c_tkconfig}" = x ; then
+ for i in \
+ ../tk \
+ `ls -dr ../tk[[4-9]]* 2>/dev/null` \
+ ../../tk \
+ `ls -dr ../../tk[[4-9]]* 2>/dev/null` \
+ ../../../tk \
+ `ls -dr ../../../tk[[4-9]]* 2>/dev/null` ; do
+ if test -f "$i/${configdir}/tkConfig.sh" ; then
+ ac_cv_c_tkconfig=`(cd $i/${configdir}; pwd)`
+ break
+ fi
+ done
+ fi
+ # check in a few common install locations
+ if test x"${ac_cv_c_tkconfig}" = x ; then
+ for i in `ls -d ${prefix}/lib /usr/local/lib 2>/dev/null` ; do
+ if test -f "$i/tkConfig.sh" ; then
+ ac_cv_c_tkconfig=`(cd $i; pwd)`
+ break
+ fi
+ done
+ fi
+ # check in a few other private locations
+ if test x"${ac_cv_c_tkconfig}" = x ; then
+ for i in \
+ ${srcdir}/../tk \
+ `ls -dr ${srcdir}/../tk[[4-9]]* 2>/dev/null` ; do
+ if test -f "$i/${configdir}/tkConfig.sh" ; then
+ ac_cv_c_tkconfig=`(cd $i/${configdir}; pwd)`
+ break
+ fi
+ done
+ fi
+ ])
+ if test x"${ac_cv_c_tkconfig}" = x ; then
+ TKCONFIG="# no Tk configs found"
+ AC_MSG_WARN(Can't find Tk configuration definitions)
+ else
+ no_tk=
+ TKCONFIG=${ac_cv_c_tkconfig}/tkConfig.sh
+ AC_MSG_RESULT(found $TKCONFIG)
+ fi
+fi
+
+])
+
+# Defined as a separate macro so we don't have to cache the values
+# from PATH_TKCONFIG (because this can also be cached).
+AC_DEFUN(CY_AC_LOAD_TKCONFIG, [
+ if test -f "$TKCONFIG" ; then
+ . $TKCONFIG
+ fi
+
+ AC_SUBST(TK_VERSION)
+dnl not actually used, don't export to save symbols
+dnl AC_SUBST(TK_MAJOR_VERSION)
+dnl AC_SUBST(TK_MINOR_VERSION)
+ AC_SUBST(TK_DEFS)
+
+dnl not used, don't export to save symbols
+ dnl AC_SUBST(TK_LIB_FILE)
+
+dnl not used outside of configure
+dnl AC_SUBST(TK_LIBS)
+dnl not used, don't export to save symbols
+dnl AC_SUBST(TK_PREFIX)
+
+dnl not used, don't export to save symbols
+dnl AC_SUBST(TK_EXEC_PREFIX)
+
+ AC_SUBST(TK_BUILD_INCLUDES)
+ AC_SUBST(TK_XINCLUDES)
+ AC_SUBST(TK_XLIBSW)
+ AC_SUBST(TK_BUILD_LIB_SPEC)
+ AC_SUBST(TK_LIB_SPEC)
+])
+
+# check for Itcl headers.
+
+AC_DEFUN(CY_AC_PATH_ITCLCONFIG, [
+#
+# Ok, lets find the itcl configuration
+# First, look for one uninstalled.
+# the alternative search directory is invoked by --with-itclconfig
+#
+
+if test x"${no_itcl}" = x ; then
+ # we reset no_itcl in case something fails here
+ no_itcl=true
+ AC_ARG_WITH(itclconfig, [ --with-itclconfig directory containing itcl configuration (itclConfig.sh)],
+ with_itclconfig=${withval})
+ AC_MSG_CHECKING([for Itcl configuration])
+ AC_CACHE_VAL(ac_cv_c_itclconfig,[
+
+ # First check to see if --with-itclconfig was specified.
+ if test x"${with_itclconfig}" != x ; then
+ if test -f "${with_itclconfig}/itclConfig.sh" ; then
+ ac_cv_c_itclconfig=`(cd ${with_itclconfig}; pwd)`
+ else
+ AC_MSG_ERROR([${with_itclconfig} directory doesn't contain itclConfig.sh])
+ fi
+ fi
+
+ # then check for a private Itcl library
+ if test x"${ac_cv_c_itclconfig}" = x ; then
+ for i in \
+ ../itcl/itcl \
+ `ls -dr ../itcl[[4-9]]*/itcl 2>/dev/null` \
+ ../../itcl \
+ `ls -dr ../../itcl[[4-9]]*/itcl 2>/dev/null` \
+ ../../../itcl \
+ `ls -dr ../../../itcl[[4-9]]*/itcl 2>/dev/null` ; do
+ if test -f "$i/itclConfig.sh" ; then
+ ac_cv_c_itclconfig=`(cd $i; pwd)`
+ break
+ fi
+ done
+ fi
+ # check in a few common install locations
+ if test x"${ac_cv_c_itclconfig}" = x ; then
+ for i in `ls -d ${prefix}/lib /usr/local/lib 2>/dev/null` ; do
+ if test -f "$i/itclConfig.sh" ; then
+ ac_cv_c_itclconfig=`(cd $i; pwd)`
+ break
+ fi
+ done
+ fi
+ # check in a few other private locations
+ if test x"${ac_cv_c_itclconfig}" = x ; then
+ for i in \
+ ${srcdir}/../itcl/itcl \
+ `ls -dr ${srcdir}/../itcl[[4-9]]*/itcl 2>/dev/null` ; do
+ if test -f "$i/itclConfig.sh" ; then
+ ac_cv_c_itclconfig=`(cd $i; pwd)`
+ break
+ fi
+ done
+ fi
+ ])
+ if test x"${ac_cv_c_itclconfig}" = x ; then
+ ITCLCONFIG="# no Itcl configs found"
+ AC_MSG_WARN(Can't find Itcl configuration definitions)
+ else
+ no_itcl=
+ ITCLCONFIG=${ac_cv_c_itclconfig}/itclConfig.sh
+ AC_MSG_RESULT(found $ITCLCONFIG)
+ fi
+fi
+])
+
+# Defined as a separate macro so we don't have to cache the values
+# from PATH_ITCLCONFIG (because this can also be cached).
+AC_DEFUN(CY_AC_LOAD_ITCLCONFIG, [
+ if test -f "$ITCLCONFIG" ; then
+ . $ITCLCONFIG
+ fi
+
+ AC_SUBST(ITCL_VERSION)
+dnl not actually used, don't export to save symbols
+dnl AC_SUBST(ITCL_MAJOR_VERSION)
+dnl AC_SUBST(ITCL_MINOR_VERSION)
+ AC_SUBST(ITCL_DEFS)
+
+dnl not used, don't export to save symbols
+ dnl AC_SUBST(ITCL_LIB_FILE)
+
+dnl not used outside of configure
+dnl AC_SUBST(ITCL_LIBS)
+dnl not used, don't export to save symbols
+dnl AC_SUBST(ITCL_PREFIX)
+
+dnl not used, don't export to save symbols
+dnl AC_SUBST(ITCL_EXEC_PREFIX)
+
+ AC_SUBST(ITCL_BUILD_INCLUDES)
+ AC_SUBST(ITCL_BUILD_LIB_SPEC)
+ AC_SUBST(ITCL_LIB_SPEC)
+])
+
+# check for Itcl headers.
+
+AC_DEFUN(CY_AC_PATH_ITCLH, [
+AC_MSG_CHECKING(for Itcl private headers. srcdir=${srcdir})
+if test x"${ac_cv_c_itclh}" = x ; then
+ for i in ${srcdir}/../itcl ${srcdir}/../../itcl ${srcdir}/../../../itcl ${srcdir}/../itcl/itcl; do
+ if test -f $i/generic/itcl.h ; then
+ ac_cv_c_itclh=`(cd $i/generic; pwd)`
+ break
+ fi
+ done
+fi
+if test x"${ac_cv_c_itclh}" = x ; then
+ ITCLHDIR="# no Itcl private headers found"
+ AC_MSG_ERROR([Can't find Itcl private headers])
+fi
+if test x"${ac_cv_c_itclh}" != x ; then
+ ITCLHDIR="-I${ac_cv_c_itclh}"
+fi
+# should always be here
+# ITCLLIB="../itcl/itcl/unix/libitcl.a"
+AC_SUBST(ITCLHDIR)
+#AC_SUBST(ITCLLIB)
+])
+
+
+AC_DEFUN(CY_AC_PATH_ITKCONFIG, [
+#
+# Ok, lets find the itk configuration
+# First, look for one uninstalled.
+# the alternative search directory is invoked by --with-itkconfig
+#
+
+if test x"${no_itk}" = x ; then
+ # we reset no_itk in case something fails here
+ no_itk=true
+ AC_ARG_WITH(itkconfig, [ --with-itkconfig directory containing itk configuration (itkConfig.sh)],
+ with_itkconfig=${withval})
+ AC_MSG_CHECKING([for Itk configuration])
+ AC_CACHE_VAL(ac_cv_c_itkconfig,[
+
+ # First check to see if --with-itkconfig was specified.
+ if test x"${with_itkconfig}" != x ; then
+ if test -f "${with_itkconfig}/itkConfig.sh" ; then
+ ac_cv_c_itkconfig=`(cd ${with_itkconfig}; pwd)`
+ else
+ AC_MSG_ERROR([${with_itkconfig} directory doesn't contain itkConfig.sh])
+ fi
+ fi
+
+ # then check for a private Itk library
+ if test x"${ac_cv_c_itkconfig}" = x ; then
+ for i in \
+ ../itcl/itk \
+ `ls -dr ../itcl[[4-9]]*/itk 2>/dev/null` \
+ ../../itk \
+ `ls -dr ../../itcl[[4-9]]*/itk 2>/dev/null` \
+ ../../../itk \
+ `ls -dr ../../../itcl[[4-9]]*/itk 2>/dev/null` ; do
+ if test -f "$i/itkConfig.sh" ; then
+ ac_cv_c_itkconfig=`(cd $i; pwd)`
+ break
+ fi
+ done
+ fi
+ # check in a few common install locations
+ if test x"${ac_cv_c_itkconfig}" = x ; then
+ for i in `ls -d ${prefix}/lib /usr/local/lib 2>/dev/null` ; do
+ if test -f "$i/itkConfig.sh" ; then
+ ac_cv_c_itkconfig=`(cd $i; pwd)`
+ break
+ fi
+ done
+ fi
+ # check in a few other private locations
+ if test x"${ac_cv_c_itkconfig}" = x ; then
+ for i in \
+ ${srcdir}/../itcl/itk \
+ `ls -dr ${srcdir}/../itcl[[4-9]]*/itk 2>/dev/null` ; do
+ if test -f "$i/itkConfig.sh" ; then
+ ac_cv_c_itkconfig=`(cd $i; pwd)`
+ break
+ fi
+ done
+ fi
+ ])
+ if test x"${ac_cv_c_itkconfig}" = x ; then
+ ITKCONFIG="# no Itk configs found"
+ AC_MSG_WARN(Can't find Itk configuration definitions)
+ else
+ no_itk=
+ ITKCONFIG=${ac_cv_c_itkconfig}/itkConfig.sh
+ AC_MSG_RESULT(found $ITKCONFIG)
+ fi
+fi
+
+])
+
+# Defined as a separate macro so we don't have to cache the values
+# from PATH_ITKCONFIG (because this can also be cached).
+AC_DEFUN(CY_AC_LOAD_ITKCONFIG, [
+ if test -f "$ITKCONFIG" ; then
+ . $ITKCONFIG
+ fi
+
+ AC_SUBST(ITK_VERSION)
+dnl not actually used, don't export to save symbols
+dnl AC_SUBST(ITK_MAJOR_VERSION)
+dnl AC_SUBST(ITK_MINOR_VERSION)
+ AC_SUBST(ITK_DEFS)
+
+dnl not used, don't export to save symbols
+ dnl AC_SUBST(ITK_LIB_FILE)
+
+dnl not used outside of configure
+dnl AC_SUBST(ITK_LIBS)
+dnl not used, don't export to save symbols
+dnl AC_SUBST(ITK_PREFIX)
+
+dnl not used, don't export to save symbols
+dnl AC_SUBST(ITK_EXEC_PREFIX)
+
+ AC_SUBST(ITK_BUILD_INCLUDES)
+ AC_SUBST(ITK_BUILD_LIB_SPEC)
+ AC_SUBST(ITK_LIB_SPEC)
+])
+
+AC_DEFUN(CY_AC_PATH_ITKH, [
+AC_MSG_CHECKING(for Itk private headers. srcdir=${srcdir})
+if test x"${ac_cv_c_itkh}" = x ; then
+ for i in ${srcdir}/../itcl ${srcdir}/../../itcl ${srcdir}/../../../itcl ${srcdir}/../itcl/itk; do
+ if test -f $i/generic/itk.h ; then
+ ac_cv_c_itkh=`(cd $i/generic; pwd)`
+ break
+ fi
+ done
+fi
+if test x"${ac_cv_c_itkh}" = x ; then
+ ITKHDIR="# no Itk private headers found"
+ AC_MSG_ERROR([Can't find Itk private headers])
+fi
+if test x"${ac_cv_c_itkh}" != x ; then
+ ITKHDIR="-I${ac_cv_c_itkh}"
+fi
+# should always be here
+# ITKLIB="../itcl/itk/unix/libitk.a"
+AC_SUBST(ITKHDIR)
+#AC_SUBST(ITKLIB)
+])
+
+# check for Tix headers.
+
+AC_DEFUN(CY_AC_PATH_TIXH, [
+AC_MSG_CHECKING(for Tix private headers. srcdir=${srcdir})
+if test x"${ac_cv_c_tixh}" = x ; then
+ for i in ${srcdir}/../tix ${srcdir}/../../tix ${srcdir}/../../../tix ; do
+ if test -f $i/generic/tix.h ; then
+ ac_cv_c_tixh=`(cd $i/generic; pwd)`
+ break
+ fi
+ done
+fi
+if test x"${ac_cv_c_tixh}" = x ; then
+ TIXHDIR="# no Tix private headers found"
+ AC_MSG_ERROR([Can't find Tix private headers])
+fi
+if test x"${ac_cv_c_tixh}" != x ; then
+ TIXHDIR="-I${ac_cv_c_tixh}"
+fi
+AC_SUBST(TIXHDIR)
+])
+
+AC_DEFUN(CY_AC_PATH_TIXCONFIG, [
+#
+# Ok, lets find the tix configuration
+# First, look for one uninstalled.
+# the alternative search directory is invoked by --with-itkconfig
+#
+
+if test x"${no_tix}" = x ; then
+ # we reset no_tix in case something fails here
+ no_tix=true
+ AC_ARG_WITH(tixconfig, [ --with-tixconfig directory containing tix configuration (tixConfig.sh)],
+ with_tixconfig=${withval})
+ AC_MSG_CHECKING([for Tix configuration])
+ AC_CACHE_VAL(ac_cv_c_tixconfig,[
+
+ # First check to see if --with-tixconfig was specified.
+ if test x"${with_tixconfig}" != x ; then
+ if test -f "${with_tixconfig}/tixConfig.sh" ; then
+ ac_cv_c_tixconfig=`(cd ${with_tixconfig}; pwd)`
+ else
+ AC_MSG_ERROR([${with_tixconfig} directory doesn't contain tixConfig.sh])
+ fi
+ fi
+
+ # then check for a private Tix library
+ if test x"${ac_cv_c_tixconfig}" = x ; then
+ for i in \
+ ../tix \
+ `ls -dr ../tix 2>/dev/null` \
+ ../../tix \
+ `ls -dr ../../tix 2>/dev/null` \
+ ../../../tix \
+ `ls -dr ../../../tix 2>/dev/null` ; do
+ echo "**** Looking at $i - with ${configdir}"
+ if test -f "$i/tixConfig.sh" ; then
+ ac_cv_c_tixconfig=`(cd $i; pwd)`
+ break
+ fi
+ done
+ fi
+ # check in a few common install locations
+ if test x"${ac_cv_c_tixconfig}" = x ; then
+ for i in `ls -d ${prefix}/lib /usr/local/lib 2>/dev/null` ; do
+ echo "**** Looking at $i"
+ if test -f "$i/tixConfig.sh" ; then
+ ac_cv_c_tixconfig=`(cd $i; pwd)`
+ break
+ fi
+ done
+ fi
+ # check in a few other private locations
+ echo "**** Other private locations"
+ if test x"${ac_cv_c_tixconfig}" = x ; then
+ for i in \
+ ${srcdir}/../tix \
+ `ls -dr ${srcdir}/../tix 2>/dev/null` ; do
+ echo "**** Looking at $i - with ${configdir}"
+ if test -f "$i/${configdir}/tixConfig.sh" ; then
+ ac_cv_c_tixconfig=`(cd $i/${configdir}; pwd)`
+ break
+ fi
+ done
+ fi
+ ])
+ if test x"${ac_cv_c_tixconfig}" = x ; then
+ TIXCONFIG="# no Tix configs found"
+ AC_MSG_WARN(Can't find Tix configuration definitions)
+ else
+ no_tix=
+ TIXCONFIG=${ac_cv_c_tixconfig}/tixConfig.sh
+ AC_MSG_RESULT(found $TIXCONFIG)
+ fi
+fi
+
+])
+
+# Defined as a separate macro so we don't have to cache the values
+# from PATH_TIXCONFIG (because this can also be cached).
+AC_DEFUN(CY_AC_LOAD_TIXCONFIG, [
+ if test -f "$TIXCONFIG" ; then
+ . $TIXCONFIG
+ fi
+
+ AC_SUBST(TIX_VERSION)
+dnl not actually used, don't export to save symbols
+dnl AC_SUBST(TIX_MAJOR_VERSION)
+dnl AC_SUBST(TIX_MINOR_VERSION)
+dnl AC_SUBST(TIX_DEFS)
+
+dnl not used, don't export to save symbols
+dnl dnl AC_SUBST(TIX_LIB_FILE)
+
+dnl not used outside of configure
+dnl AC_SUBST(TIX_LIBS)
+dnl not used, don't export to save symbols
+dnl AC_SUBST(TIX_PREFIX)
+
+dnl not used, don't export to save symbols
+dnl AC_SUBST(TIX_EXEC_PREFIX)
+
+dnl AC_SUBST(TIX_BUILD_INCLUDES)
+ AC_SUBST(TIX_BUILD_LIB_SPEC)
+dnl AC_SUBST(TIX_LIB_SPEC)
+])
diff --git a/gdb/aclocal.m4 b/gdb/aclocal.m4
new file mode 100644
index 00000000000..4fd3658dd6b
--- /dev/null
+++ b/gdb/aclocal.m4
@@ -0,0 +1,1307 @@
+dnl aclocal.m4 generated automatically by aclocal 1.4
+
+dnl Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+dnl This program is distributed in the hope that it will be useful,
+dnl but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+dnl even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+dnl PARTICULAR PURPOSE.
+
+dnl written by Rob Savoye <rob@cygnus.com> for Cygnus Support
+dnl major rewriting for Tcl 7.5 by Don Libes <libes@nist.gov>
+
+dnl gdb/configure.in uses BFD_NEED_DECLARATION, so get its definition.
+sinclude(../bfd/acinclude.m4)
+
+dnl This gets the standard macros, like the TCL, TK, etc ones.
+sinclude(../config/acinclude.m4)
+
+dnl CYGNUS LOCAL: This gets the right posix flag for gcc
+AC_DEFUN(CY_AC_TCL_LYNX_POSIX,
+[AC_REQUIRE([AC_PROG_CC])AC_REQUIRE([AC_PROG_CPP])
+AC_MSG_CHECKING([if running LynxOS])
+AC_CACHE_VAL(ac_cv_os_lynx,
+[AC_EGREP_CPP(yes,
+[/*
+ * The old Lynx "cc" only defines "Lynx", but the newer one uses "__Lynx__"
+ */
+#if defined(__Lynx__) || defined(Lynx)
+yes
+#endif
+], ac_cv_os_lynx=yes, ac_cv_os_lynx=no)])
+#
+if test "$ac_cv_os_lynx" = "yes" ; then
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(LYNX)
+ AC_MSG_CHECKING([whether -mposix or -X is available])
+ AC_CACHE_VAL(ac_cv_c_posix_flag,
+ [AC_TRY_COMPILE(,[
+ /*
+ * This flag varies depending on how old the compiler is.
+ * -X is for the old "cc" and "gcc" (based on 1.42).
+ * -mposix is for the new gcc (at least 2.5.8).
+ */
+ #if defined(__GNUC__) && __GNUC__ >= 2
+ choke me
+ #endif
+ ], ac_cv_c_posix_flag=" -mposix", ac_cv_c_posix_flag=" -X")])
+ CC="$CC $ac_cv_c_posix_flag"
+ AC_MSG_RESULT($ac_cv_c_posix_flag)
+ else
+ AC_MSG_RESULT(no)
+fi
+])
+
+#
+# Sometimes the native compiler is a bogus stub for gcc or /usr/ucb/cc. This
+# makes configure think it's cross compiling. If --target wasn't used, then
+# we can't configure, so something is wrong. We don't use the cache
+# here cause if somebody fixes their compiler install, we want this to work.
+AC_DEFUN(CY_AC_C_WORKS,
+[# If we cannot compile and link a trivial program, we can't expect anything to work
+AC_MSG_CHECKING(whether the compiler ($CC) actually works)
+AC_TRY_COMPILE(, [/* don't need anything here */],
+ c_compiles=yes, c_compiles=no)
+
+AC_TRY_LINK(, [/* don't need anything here */],
+ c_links=yes, c_links=no)
+
+if test x"${c_compiles}" = x"no" ; then
+ AC_MSG_ERROR(the native compiler is broken and won't compile.)
+fi
+
+if test x"${c_links}" = x"no" ; then
+ AC_MSG_ERROR(the native compiler is broken and won't link.)
+fi
+AC_MSG_RESULT(yes)
+])
+
+AC_DEFUN(CY_AC_PATH_TCLH, [
+#
+# Ok, lets find the tcl source trees so we can use the headers
+# Warning: transition of version 9 to 10 will break this algorithm
+# because 10 sorts before 9. We also look for just tcl. We have to
+# be careful that we don't match stuff like tclX by accident.
+# the alternative search directory is involked by --with-tclinclude
+#
+
+no_tcl=true
+AC_MSG_CHECKING(for Tcl private headers. dir=${configdir})
+AC_ARG_WITH(tclinclude, [ --with-tclinclude=DIR Directory where tcl private headers are], with_tclinclude=${withval})
+AC_CACHE_VAL(ac_cv_c_tclh,[
+# first check to see if --with-tclinclude was specified
+if test x"${with_tclinclude}" != x ; then
+ if test -f ${with_tclinclude}/tclInt.h ; then
+ ac_cv_c_tclh=`(cd ${with_tclinclude}; pwd)`
+ elif test -f ${with_tclinclude}/generic/tclInt.h ; then
+ ac_cv_c_tclh=`(cd ${with_tclinclude}/generic; pwd)`
+ else
+ AC_MSG_ERROR([${with_tclinclude} directory doesn't contain private headers])
+ fi
+fi
+
+# next check if it came with Tcl configuration file
+if test x"${ac_cv_c_tclconfig}" = x ; then
+ if test -f $ac_cv_c_tclconfig/../generic/tclInt.h ; then
+ ac_cv_c_tclh=`(cd $ac_cv_c_tclconfig/..; pwd)`
+ fi
+fi
+
+# next check in private source directory
+#
+# since ls returns lowest version numbers first, reverse its output
+if test x"${ac_cv_c_tclh}" = x ; then
+ for i in \
+ ${srcdir}/../tcl \
+ `ls -dr ${srcdir}/../tcl[[7-9]]* 2>/dev/null` \
+ ${srcdir}/../../tcl \
+ `ls -dr ${srcdir}/../../tcl[[7-9]]* 2>/dev/null` \
+ ${srcdir}/../../../tcl \
+ `ls -dr ${srcdir}/../../../tcl[[7-9]]* 2>/dev/null ` ; do
+ if test -f $i/generic/tclInt.h ; then
+ ac_cv_c_tclh=`(cd $i/generic; pwd)`
+ break
+ fi
+ done
+fi
+# finally check in a few common install locations
+#
+# since ls returns lowest version numbers first, reverse its output
+if test x"${ac_cv_c_tclh}" = x ; then
+ for i in \
+ `ls -dr /usr/local/src/tcl[[7-9]]* 2>/dev/null` \
+ `ls -dr /usr/local/lib/tcl[[7-9]]* 2>/dev/null` \
+ /usr/local/src/tcl \
+ /usr/local/lib/tcl \
+ ${prefix}/include ; do
+ if test -f $i/generic/tclInt.h ; then
+ ac_cv_c_tclh=`(cd $i/generic; pwd)`
+ break
+ fi
+ done
+fi
+# see if one is installed
+if test x"${ac_cv_c_tclh}" = x ; then
+ AC_HEADER_CHECK(tclInt.h, ac_cv_c_tclh=installed, ac_cv_c_tclh="")
+fi
+])
+if test x"${ac_cv_c_tclh}" = x ; then
+ TCLHDIR="# no Tcl private headers found"
+ AC_MSG_ERROR([Can't find Tcl private headers])
+fi
+if test x"${ac_cv_c_tclh}" != x ; then
+ no_tcl=""
+ if test x"${ac_cv_c_tclh}" = x"installed" ; then
+ AC_MSG_RESULT([is installed])
+ TCLHDIR=""
+ else
+ AC_MSG_RESULT([found in ${ac_cv_c_tclh}])
+ # this hack is cause the TCLHDIR won't print if there is a "-I" in it.
+ TCLHDIR="-I${ac_cv_c_tclh}"
+ fi
+fi
+
+AC_SUBST(TCLHDIR)
+])
+
+
+AC_DEFUN(CY_AC_PATH_TCLCONFIG, [
+#
+# Ok, lets find the tcl configuration
+# First, look for one uninstalled.
+# the alternative search directory is invoked by --with-tclconfig
+#
+
+if test x"${no_tcl}" = x ; then
+ # we reset no_tcl in case something fails here
+ no_tcl=true
+ AC_ARG_WITH(tclconfig, [ --with-tclconfig=DIR Directory containing tcl configuration (tclConfig.sh)],
+ with_tclconfig=${withval})
+ AC_MSG_CHECKING([for Tcl configuration])
+ AC_CACHE_VAL(ac_cv_c_tclconfig,[
+
+ # First check to see if --with-tclconfig was specified.
+ if test x"${with_tclconfig}" != x ; then
+ if test -f "${with_tclconfig}/tclConfig.sh" ; then
+ ac_cv_c_tclconfig=`(cd ${with_tclconfig}; pwd)`
+ else
+ AC_MSG_ERROR([${with_tclconfig} directory doesn't contain tclConfig.sh])
+ fi
+ fi
+
+ # then check for a private Tcl installation
+ if test x"${ac_cv_c_tclconfig}" = x ; then
+ for i in \
+ ../tcl \
+ `ls -dr ../tcl[[7-9]]* 2>/dev/null` \
+ ../../tcl \
+ `ls -dr ../../tcl[[7-9]]* 2>/dev/null` \
+ ../../../tcl \
+ `ls -dr ../../../tcl[[7-9]]* 2>/dev/null` ; do
+ if test -f "$i/${configdir}/tclConfig.sh" ; then
+ ac_cv_c_tclconfig=`(cd $i/${configdir}; pwd)`
+ break
+ fi
+ done
+ fi
+ # check in a few common install locations
+ if test x"${ac_cv_c_tclconfig}" = x ; then
+ for i in `ls -d ${prefix}/lib /usr/local/lib 2>/dev/null` ; do
+ if test -f "$i/tclConfig.sh" ; then
+ ac_cv_c_tclconfig=`(cd $i; pwd)`
+ break
+ fi
+ done
+ fi
+ # check in a few other private locations
+ if test x"${ac_cv_c_tclconfig}" = x ; then
+ for i in \
+ ${srcdir}/../tcl \
+ `ls -dr ${srcdir}/../tcl[[7-9]]* 2>/dev/null` ; do
+ if test -f "$i/${configdir}/tclConfig.sh" ; then
+ ac_cv_c_tclconfig=`(cd $i/${configdir}; pwd)`
+ break
+ fi
+ done
+ fi
+ ])
+ if test x"${ac_cv_c_tclconfig}" = x ; then
+ TCLCONFIG="# no Tcl configs found"
+ AC_MSG_WARN(Can't find Tcl configuration definitions)
+ else
+ no_tcl=
+ TCLCONFIG=${ac_cv_c_tclconfig}/tclConfig.sh
+ AC_MSG_RESULT(found $TCLCONFIG)
+ fi
+fi
+])
+
+# Defined as a separate macro so we don't have to cache the values
+# from PATH_TCLCONFIG (because this can also be cached).
+AC_DEFUN(CY_AC_LOAD_TCLCONFIG, [
+ . $TCLCONFIG
+
+ AC_SUBST(TCL_VERSION)
+ AC_SUBST(TCL_MAJOR_VERSION)
+ AC_SUBST(TCL_MINOR_VERSION)
+ AC_SUBST(TCL_CC)
+ AC_SUBST(TCL_DEFS)
+
+dnl not used, don't export to save symbols
+dnl AC_SUBST(TCL_LIB_FILE)
+
+dnl don't export, not used outside of configure
+dnl AC_SUBST(TCL_LIBS)
+dnl not used, don't export to save symbols
+dnl AC_SUBST(TCL_PREFIX)
+
+dnl not used, don't export to save symbols
+dnl AC_SUBST(TCL_EXEC_PREFIX)
+
+ AC_SUBST(TCL_SHLIB_CFLAGS)
+ AC_SUBST(TCL_SHLIB_LD)
+dnl don't export, not used outside of configure
+ AC_SUBST(TCL_SHLIB_LD_LIBS)
+ AC_SUBST(TCL_SHLIB_SUFFIX)
+dnl not used, don't export to save symbols
+ AC_SUBST(TCL_DL_LIBS)
+ AC_SUBST(TCL_LD_FLAGS)
+dnl don't export, not used outside of configure
+ AC_SUBST(TCL_LD_SEARCH_FLAGS)
+ AC_SUBST(TCL_COMPAT_OBJS)
+ AC_SUBST(TCL_RANLIB)
+ AC_SUBST(TCL_BUILD_LIB_SPEC)
+ AC_SUBST(TCL_LIB_SPEC)
+ AC_SUBST(TCL_LIB_VERSIONS_OK)
+
+dnl not used, don't export to save symbols
+dnl AC_SUBST(TCL_SHARED_LIB_SUFFIX)
+
+dnl not used, don't export to save symbols
+dnl AC_SUBST(TCL_UNSHARED_LIB_SUFFIX)
+])
+
+# Warning: Tk definitions are very similar to Tcl definitions but
+# are not precisely the same. There are a couple of differences,
+# so don't do changes to Tcl thinking you can cut and paste it do
+# the Tk differences and later simply substitute "Tk" for "Tcl".
+# Known differences:
+# - Acceptable Tcl major version #s is 7-9 while Tk is 4-9
+# - Searching for Tcl includes looking for tclInt.h, Tk looks for tk.h
+# - Computing major/minor versions is different because Tk depends on
+# headers to Tcl, Tk, and X.
+# - Symbols in tkConfig.sh are different than tclConfig.sh
+# - Acceptable for Tk to be missing but not Tcl.
+
+AC_DEFUN(CY_AC_PATH_TKH, [
+#
+# Ok, lets find the tk source trees so we can use the headers
+# If the directory (presumably symlink) named "tk" exists, use that one
+# in preference to any others. Same logic is used when choosing library
+# and again with Tcl. The search order is the best place to look first, then in
+# decreasing significance. The loop breaks if the trigger file is found.
+# Note the gross little conversion here of srcdir by cd'ing to the found
+# directory. This converts the path from a relative to an absolute, so
+# recursive cache variables for the path will work right. We check all
+# the possible paths in one loop rather than many seperate loops to speed
+# things up.
+# the alternative search directory is involked by --with-tkinclude
+#
+no_tk=true
+AC_MSG_CHECKING(for Tk private headers)
+AC_ARG_WITH(tkinclude, [ --with-tkinclude=DIR Directory where tk private headers are], with_tkinclude=${withval})
+AC_CACHE_VAL(ac_cv_c_tkh,[
+# first check to see if --with-tkinclude was specified
+if test x"${with_tkinclude}" != x ; then
+ if test -f ${with_tkinclude}/tk.h ; then
+ ac_cv_c_tkh=`(cd ${with_tkinclude}; pwd)`
+ elif test -f ${with_tkinclude}/generic/tk.h ; then
+ ac_cv_c_tkh=`(cd ${with_tkinclude}/generic; pwd)`
+ else
+ AC_MSG_ERROR([${with_tkinclude} directory doesn't contain private headers])
+ fi
+fi
+
+# next check if it came with Tk configuration file
+if test x"${ac_cv_c_tkconfig}" = x ; then
+ if test -f $ac_cv_c_tkconfig/../generic/tk.h ; then
+ ac_cv_c_tkh=`(cd $ac_cv_c_tkconfig/..; pwd)`
+ fi
+fi
+
+# next check in private source directory
+#
+# since ls returns lowest version numbers first, reverse its output
+if test x"${ac_cv_c_tkh}" = x ; then
+ for i in \
+ ${srcdir}/../tk \
+ `ls -dr ${srcdir}/../tk[[4-9]]* 2>/dev/null` \
+ ${srcdir}/../../tk \
+ `ls -dr ${srcdir}/../../tk[[4-9]]* 2>/dev/null` \
+ ${srcdir}/../../../tk \
+ `ls -dr ${srcdir}/../../../tk[[4-9]]* 2>/dev/null ` ; do
+ if test -f $i/generic/tk.h ; then
+ ac_cv_c_tkh=`(cd $i/generic; pwd)`
+ break
+ fi
+ done
+fi
+# finally check in a few common install locations
+#
+# since ls returns lowest version numbers first, reverse its output
+if test x"${ac_cv_c_tkh}" = x ; then
+ for i in \
+ `ls -dr /usr/local/src/tk[[4-9]]* 2>/dev/null` \
+ `ls -dr /usr/local/lib/tk[[4-9]]* 2>/dev/null` \
+ /usr/local/src/tk \
+ /usr/local/lib/tk \
+ ${prefix}/include ; do
+ if test -f $i/generic/tk.h ; then
+ ac_cv_c_tkh=`(cd $i/generic; pwd)`
+ break
+ fi
+ done
+fi
+# see if one is installed
+if test x"${ac_cv_c_tkh}" = x ; then
+ AC_HEADER_CHECK(tk.h, ac_cv_c_tkh=installed, ac_cv_c_tkh="")
+fi
+])
+if test x"${ac_cv_c_tkh}" != x ; then
+ no_tk=""
+ if test x"${ac_cv_c_tkh}" = x"installed" ; then
+ AC_MSG_RESULT([is installed])
+ TKHDIR=""
+ else
+ AC_MSG_RESULT([found in ${ac_cv_c_tkh}])
+ # this hack is cause the TKHDIR won't print if there is a "-I" in it.
+ TKHDIR="-I${ac_cv_c_tkh}"
+ fi
+else
+ TKHDIR="# no Tk directory found"
+ AC_MSG_WARN([Can't find Tk private headers])
+ no_tk=true
+fi
+
+AC_SUBST(TKHDIR)
+])
+
+
+AC_DEFUN(CY_AC_PATH_TKCONFIG, [
+#
+# Ok, lets find the tk configuration
+# First, look for one uninstalled.
+# the alternative search directory is invoked by --with-tkconfig
+#
+
+if test x"${no_tk}" = x ; then
+ # we reset no_tk in case something fails here
+ no_tk=true
+ AC_ARG_WITH(tkconfig, [ --with-tkconfig=DIR Directory containing tk configuration (tkConfig.sh)],
+ with_tkconfig=${withval})
+ AC_MSG_CHECKING([for Tk configuration])
+ AC_CACHE_VAL(ac_cv_c_tkconfig,[
+
+ # First check to see if --with-tkconfig was specified.
+ if test x"${with_tkconfig}" != x ; then
+ if test -f "${with_tkconfig}/tkConfig.sh" ; then
+ ac_cv_c_tkconfig=`(cd ${with_tkconfig}; pwd)`
+ else
+ AC_MSG_ERROR([${with_tkconfig} directory doesn't contain tkConfig.sh])
+ fi
+ fi
+
+ # then check for a private Tk library
+ if test x"${ac_cv_c_tkconfig}" = x ; then
+ for i in \
+ ../tk \
+ `ls -dr ../tk[[4-9]]* 2>/dev/null` \
+ ../../tk \
+ `ls -dr ../../tk[[4-9]]* 2>/dev/null` \
+ ../../../tk \
+ `ls -dr ../../../tk[[4-9]]* 2>/dev/null` ; do
+ if test -f "$i/${configdir}/tkConfig.sh" ; then
+ ac_cv_c_tkconfig=`(cd $i/${configdir}; pwd)`
+ break
+ fi
+ done
+ fi
+ # check in a few common install locations
+ if test x"${ac_cv_c_tkconfig}" = x ; then
+ for i in `ls -d ${prefix}/lib /usr/local/lib 2>/dev/null` ; do
+ if test -f "$i/tkConfig.sh" ; then
+ ac_cv_c_tkconfig=`(cd $i; pwd)`
+ break
+ fi
+ done
+ fi
+ # check in a few other private locations
+ if test x"${ac_cv_c_tkconfig}" = x ; then
+ for i in \
+ ${srcdir}/../tk \
+ `ls -dr ${srcdir}/../tk[[4-9]]* 2>/dev/null` ; do
+ if test -f "$i/${configdir}/tkConfig.sh" ; then
+ ac_cv_c_tkconfig=`(cd $i/${configdir}; pwd)`
+ break
+ fi
+ done
+ fi
+ ])
+ if test x"${ac_cv_c_tkconfig}" = x ; then
+ TKCONFIG="# no Tk configs found"
+ AC_MSG_WARN(Can't find Tk configuration definitions)
+ else
+ no_tk=
+ TKCONFIG=${ac_cv_c_tkconfig}/tkConfig.sh
+ AC_MSG_RESULT(found $TKCONFIG)
+ fi
+fi
+
+])
+
+# Defined as a separate macro so we don't have to cache the values
+# from PATH_TKCONFIG (because this can also be cached).
+AC_DEFUN(CY_AC_LOAD_TKCONFIG, [
+ if test -f "$TKCONFIG" ; then
+ . $TKCONFIG
+ fi
+
+ AC_SUBST(TK_VERSION)
+dnl not actually used, don't export to save symbols
+dnl AC_SUBST(TK_MAJOR_VERSION)
+dnl AC_SUBST(TK_MINOR_VERSION)
+ AC_SUBST(TK_DEFS)
+
+dnl not used, don't export to save symbols
+ dnl AC_SUBST(TK_LIB_FILE)
+
+dnl not used outside of configure
+dnl AC_SUBST(TK_LIBS)
+dnl not used, don't export to save symbols
+dnl AC_SUBST(TK_PREFIX)
+
+dnl not used, don't export to save symbols
+dnl AC_SUBST(TK_EXEC_PREFIX)
+
+ AC_SUBST(TK_BUILD_INCLUDES)
+ AC_SUBST(TK_XINCLUDES)
+ AC_SUBST(TK_XLIBSW)
+ AC_SUBST(TK_BUILD_LIB_SPEC)
+ AC_SUBST(TK_LIB_SPEC)
+])
+
+# check for Itcl headers.
+
+AC_DEFUN(CY_AC_PATH_ITCLCONFIG, [
+#
+# Ok, lets find the itcl configuration
+# First, look for one uninstalled.
+# the alternative search directory is invoked by --with-itclconfig
+#
+
+if test x"${no_itcl}" = x ; then
+ # we reset no_itcl in case something fails here
+ no_itcl=true
+ AC_ARG_WITH(itclconfig, [ --with-itclconfig directory containing itcl configuration (itclConfig.sh)],
+ with_itclconfig=${withval})
+ AC_MSG_CHECKING([for Itcl configuration])
+ AC_CACHE_VAL(ac_cv_c_itclconfig,[
+
+ # First check to see if --with-itclconfig was specified.
+ if test x"${with_itclconfig}" != x ; then
+ if test -f "${with_itclconfig}/itclConfig.sh" ; then
+ ac_cv_c_itclconfig=`(cd ${with_itclconfig}; pwd)`
+ else
+ AC_MSG_ERROR([${with_itclconfig} directory doesn't contain itclConfig.sh])
+ fi
+ fi
+
+ # then check for a private Itcl library
+ if test x"${ac_cv_c_itclconfig}" = x ; then
+ for i in \
+ ../itcl/itcl \
+ `ls -dr ../itcl[[4-9]]*/itcl 2>/dev/null` \
+ ../../itcl \
+ `ls -dr ../../itcl[[4-9]]*/itcl 2>/dev/null` \
+ ../../../itcl \
+ `ls -dr ../../../itcl[[4-9]]*/itcl 2>/dev/null` ; do
+ if test -f "$i/itclConfig.sh" ; then
+ ac_cv_c_itclconfig=`(cd $i; pwd)`
+ break
+ fi
+ done
+ fi
+ # check in a few common install locations
+ if test x"${ac_cv_c_itclconfig}" = x ; then
+ for i in `ls -d ${prefix}/lib /usr/local/lib 2>/dev/null` ; do
+ if test -f "$i/itclConfig.sh" ; then
+ ac_cv_c_itclconfig=`(cd $i; pwd)`
+ break
+ fi
+ done
+ fi
+ # check in a few other private locations
+ if test x"${ac_cv_c_itclconfig}" = x ; then
+ for i in \
+ ${srcdir}/../itcl/itcl \
+ `ls -dr ${srcdir}/../itcl[[4-9]]*/itcl 2>/dev/null` ; do
+ if test -f "$i/itclConfig.sh" ; then
+ ac_cv_c_itclconfig=`(cd $i; pwd)`
+ break
+ fi
+ done
+ fi
+ ])
+ if test x"${ac_cv_c_itclconfig}" = x ; then
+ ITCLCONFIG="# no Itcl configs found"
+ AC_MSG_WARN(Can't find Itcl configuration definitions)
+ else
+ no_itcl=
+ ITCLCONFIG=${ac_cv_c_itclconfig}/itclConfig.sh
+ AC_MSG_RESULT(found $ITCLCONFIG)
+ fi
+fi
+])
+
+# Defined as a separate macro so we don't have to cache the values
+# from PATH_ITCLCONFIG (because this can also be cached).
+AC_DEFUN(CY_AC_LOAD_ITCLCONFIG, [
+ if test -f "$ITCLCONFIG" ; then
+ . $ITCLCONFIG
+ fi
+
+ AC_SUBST(ITCL_VERSION)
+dnl not actually used, don't export to save symbols
+dnl AC_SUBST(ITCL_MAJOR_VERSION)
+dnl AC_SUBST(ITCL_MINOR_VERSION)
+ AC_SUBST(ITCL_DEFS)
+
+dnl not used, don't export to save symbols
+ dnl AC_SUBST(ITCL_LIB_FILE)
+
+dnl not used outside of configure
+dnl AC_SUBST(ITCL_LIBS)
+dnl not used, don't export to save symbols
+dnl AC_SUBST(ITCL_PREFIX)
+
+dnl not used, don't export to save symbols
+dnl AC_SUBST(ITCL_EXEC_PREFIX)
+
+ AC_SUBST(ITCL_BUILD_INCLUDES)
+ AC_SUBST(ITCL_BUILD_LIB_SPEC)
+ AC_SUBST(ITCL_LIB_SPEC)
+])
+
+# check for Itcl headers.
+
+AC_DEFUN(CY_AC_PATH_ITCLH, [
+AC_MSG_CHECKING(for Itcl private headers. srcdir=${srcdir})
+if test x"${ac_cv_c_itclh}" = x ; then
+ for i in ${srcdir}/../itcl ${srcdir}/../../itcl ${srcdir}/../../../itcl ${srcdir}/../itcl/itcl; do
+ if test -f $i/generic/itcl.h ; then
+ ac_cv_c_itclh=`(cd $i/generic; pwd)`
+ break
+ fi
+ done
+fi
+if test x"${ac_cv_c_itclh}" = x ; then
+ ITCLHDIR="# no Itcl private headers found"
+ AC_MSG_ERROR([Can't find Itcl private headers])
+fi
+if test x"${ac_cv_c_itclh}" != x ; then
+ ITCLHDIR="-I${ac_cv_c_itclh}"
+fi
+# should always be here
+# ITCLLIB="../itcl/itcl/unix/libitcl.a"
+AC_SUBST(ITCLHDIR)
+#AC_SUBST(ITCLLIB)
+])
+
+
+AC_DEFUN(CY_AC_PATH_ITKCONFIG, [
+#
+# Ok, lets find the itk configuration
+# First, look for one uninstalled.
+# the alternative search directory is invoked by --with-itkconfig
+#
+
+if test x"${no_itk}" = x ; then
+ # we reset no_itk in case something fails here
+ no_itk=true
+ AC_ARG_WITH(itkconfig, [ --with-itkconfig directory containing itk configuration (itkConfig.sh)],
+ with_itkconfig=${withval})
+ AC_MSG_CHECKING([for Itk configuration])
+ AC_CACHE_VAL(ac_cv_c_itkconfig,[
+
+ # First check to see if --with-itkconfig was specified.
+ if test x"${with_itkconfig}" != x ; then
+ if test -f "${with_itkconfig}/itkConfig.sh" ; then
+ ac_cv_c_itkconfig=`(cd ${with_itkconfig}; pwd)`
+ else
+ AC_MSG_ERROR([${with_itkconfig} directory doesn't contain itkConfig.sh])
+ fi
+ fi
+
+ # then check for a private Itk library
+ if test x"${ac_cv_c_itkconfig}" = x ; then
+ for i in \
+ ../itcl/itk \
+ `ls -dr ../itcl[[4-9]]*/itk 2>/dev/null` \
+ ../../itk \
+ `ls -dr ../../itcl[[4-9]]*/itk 2>/dev/null` \
+ ../../../itk \
+ `ls -dr ../../../itcl[[4-9]]*/itk 2>/dev/null` ; do
+ if test -f "$i/itkConfig.sh" ; then
+ ac_cv_c_itkconfig=`(cd $i; pwd)`
+ break
+ fi
+ done
+ fi
+ # check in a few common install locations
+ if test x"${ac_cv_c_itkconfig}" = x ; then
+ for i in `ls -d ${prefix}/lib /usr/local/lib 2>/dev/null` ; do
+ if test -f "$i/itkConfig.sh" ; then
+ ac_cv_c_itkconfig=`(cd $i; pwd)`
+ break
+ fi
+ done
+ fi
+ # check in a few other private locations
+ if test x"${ac_cv_c_itkconfig}" = x ; then
+ for i in \
+ ${srcdir}/../itcl/itk \
+ `ls -dr ${srcdir}/../itcl[[4-9]]*/itk 2>/dev/null` ; do
+ if test -f "$i/itkConfig.sh" ; then
+ ac_cv_c_itkconfig=`(cd $i; pwd)`
+ break
+ fi
+ done
+ fi
+ ])
+ if test x"${ac_cv_c_itkconfig}" = x ; then
+ ITKCONFIG="# no Itk configs found"
+ AC_MSG_WARN(Can't find Itk configuration definitions)
+ else
+ no_itk=
+ ITKCONFIG=${ac_cv_c_itkconfig}/itkConfig.sh
+ AC_MSG_RESULT(found $ITKCONFIG)
+ fi
+fi
+
+])
+
+# Defined as a separate macro so we don't have to cache the values
+# from PATH_ITKCONFIG (because this can also be cached).
+AC_DEFUN(CY_AC_LOAD_ITKCONFIG, [
+ if test -f "$ITKCONFIG" ; then
+ . $ITKCONFIG
+ fi
+
+ AC_SUBST(ITK_VERSION)
+dnl not actually used, don't export to save symbols
+dnl AC_SUBST(ITK_MAJOR_VERSION)
+dnl AC_SUBST(ITK_MINOR_VERSION)
+ AC_SUBST(ITK_DEFS)
+
+dnl not used, don't export to save symbols
+ dnl AC_SUBST(ITK_LIB_FILE)
+
+dnl not used outside of configure
+dnl AC_SUBST(ITK_LIBS)
+dnl not used, don't export to save symbols
+dnl AC_SUBST(ITK_PREFIX)
+
+dnl not used, don't export to save symbols
+dnl AC_SUBST(ITK_EXEC_PREFIX)
+
+ AC_SUBST(ITK_BUILD_INCLUDES)
+ AC_SUBST(ITK_BUILD_LIB_SPEC)
+ AC_SUBST(ITK_LIB_SPEC)
+])
+
+AC_DEFUN(CY_AC_PATH_ITKH, [
+AC_MSG_CHECKING(for Itk private headers. srcdir=${srcdir})
+if test x"${ac_cv_c_itkh}" = x ; then
+ for i in ${srcdir}/../itcl ${srcdir}/../../itcl ${srcdir}/../../../itcl ${srcdir}/../itcl/itk; do
+ if test -f $i/generic/itk.h ; then
+ ac_cv_c_itkh=`(cd $i/generic; pwd)`
+ break
+ fi
+ done
+fi
+if test x"${ac_cv_c_itkh}" = x ; then
+ ITKHDIR="# no Itk private headers found"
+ AC_MSG_ERROR([Can't find Itk private headers])
+fi
+if test x"${ac_cv_c_itkh}" != x ; then
+ ITKHDIR="-I${ac_cv_c_itkh}"
+fi
+# should always be here
+# ITKLIB="../itcl/itk/unix/libitk.a"
+AC_SUBST(ITKHDIR)
+#AC_SUBST(ITKLIB)
+])
+
+# check for Tix headers.
+
+AC_DEFUN(CY_AC_PATH_TIXH, [
+AC_MSG_CHECKING(for Tix private headers. srcdir=${srcdir})
+if test x"${ac_cv_c_tixh}" = x ; then
+ for i in ${srcdir}/../tix ${srcdir}/../../tix ${srcdir}/../../../tix ; do
+ if test -f $i/generic/tix.h ; then
+ ac_cv_c_tixh=`(cd $i/generic; pwd)`
+ break
+ fi
+ done
+fi
+if test x"${ac_cv_c_tixh}" = x ; then
+ TIXHDIR="# no Tix private headers found"
+ AC_MSG_ERROR([Can't find Tix private headers])
+fi
+if test x"${ac_cv_c_tixh}" != x ; then
+ TIXHDIR="-I${ac_cv_c_tixh}"
+fi
+AC_SUBST(TIXHDIR)
+])
+
+AC_DEFUN(CY_AC_PATH_TIXCONFIG, [
+#
+# Ok, lets find the tix configuration
+# First, look for one uninstalled.
+# the alternative search directory is invoked by --with-itkconfig
+#
+
+if test x"${no_tix}" = x ; then
+ # we reset no_tix in case something fails here
+ no_tix=true
+ AC_ARG_WITH(tixconfig, [ --with-tixconfig directory containing tix configuration (tixConfig.sh)],
+ with_tixconfig=${withval})
+ AC_MSG_CHECKING([for Tix configuration])
+ AC_CACHE_VAL(ac_cv_c_tixconfig,[
+
+ # First check to see if --with-tixconfig was specified.
+ if test x"${with_tixconfig}" != x ; then
+ if test -f "${with_tixconfig}/tixConfig.sh" ; then
+ ac_cv_c_tixconfig=`(cd ${with_tixconfig}; pwd)`
+ else
+ AC_MSG_ERROR([${with_tixconfig} directory doesn't contain tixConfig.sh])
+ fi
+ fi
+
+ # then check for a private Tix library
+ if test x"${ac_cv_c_tixconfig}" = x ; then
+ for i in \
+ ../tix \
+ `ls -dr ../tix 2>/dev/null` \
+ ../../tix \
+ `ls -dr ../../tix 2>/dev/null` \
+ ../../../tix \
+ `ls -dr ../../../tix 2>/dev/null` ; do
+ echo "**** Looking at $i - with ${configdir}"
+ if test -f "$i/tixConfig.sh" ; then
+ ac_cv_c_tixconfig=`(cd $i; pwd)`
+ break
+ fi
+ done
+ fi
+ # check in a few common install locations
+ if test x"${ac_cv_c_tixconfig}" = x ; then
+ for i in `ls -d ${prefix}/lib /usr/local/lib 2>/dev/null` ; do
+ echo "**** Looking at $i"
+ if test -f "$i/tixConfig.sh" ; then
+ ac_cv_c_tixconfig=`(cd $i; pwd)`
+ break
+ fi
+ done
+ fi
+ # check in a few other private locations
+ echo "**** Other private locations"
+ if test x"${ac_cv_c_tixconfig}" = x ; then
+ for i in \
+ ${srcdir}/../tix \
+ `ls -dr ${srcdir}/../tix 2>/dev/null` ; do
+ echo "**** Looking at $i - with ${configdir}"
+ if test -f "$i/${configdir}/tixConfig.sh" ; then
+ ac_cv_c_tixconfig=`(cd $i/${configdir}; pwd)`
+ break
+ fi
+ done
+ fi
+ ])
+ if test x"${ac_cv_c_tixconfig}" = x ; then
+ TIXCONFIG="# no Tix configs found"
+ AC_MSG_WARN(Can't find Tix configuration definitions)
+ else
+ no_tix=
+ TIXCONFIG=${ac_cv_c_tixconfig}/tixConfig.sh
+ AC_MSG_RESULT(found $TIXCONFIG)
+ fi
+fi
+
+])
+
+# Defined as a separate macro so we don't have to cache the values
+# from PATH_TIXCONFIG (because this can also be cached).
+AC_DEFUN(CY_AC_LOAD_TIXCONFIG, [
+ if test -f "$TIXCONFIG" ; then
+ . $TIXCONFIG
+ fi
+
+ AC_SUBST(TIX_VERSION)
+dnl not actually used, don't export to save symbols
+dnl AC_SUBST(TIX_MAJOR_VERSION)
+dnl AC_SUBST(TIX_MINOR_VERSION)
+dnl AC_SUBST(TIX_DEFS)
+
+dnl not used, don't export to save symbols
+dnl dnl AC_SUBST(TIX_LIB_FILE)
+
+dnl not used outside of configure
+dnl AC_SUBST(TIX_LIBS)
+dnl not used, don't export to save symbols
+dnl AC_SUBST(TIX_PREFIX)
+
+dnl not used, don't export to save symbols
+dnl AC_SUBST(TIX_EXEC_PREFIX)
+
+dnl AC_SUBST(TIX_BUILD_INCLUDES)
+ AC_SUBST(TIX_BUILD_LIB_SPEC)
+dnl AC_SUBST(TIX_LIB_SPEC)
+])
+
+
+# serial 1
+
+# @defmac AC_PROG_CC_STDC
+# @maindex PROG_CC_STDC
+# @ovindex CC
+# If the C compiler in not in ANSI C mode by default, try to add an option
+# to output variable @code{CC} to make it so. This macro tries various
+# options that select ANSI C on some system or another. It considers the
+# compiler to be in ANSI C mode if it handles function prototypes correctly.
+#
+# If you use this macro, you should check after calling it whether the C
+# compiler has been set to accept ANSI C; if not, the shell variable
+# @code{am_cv_prog_cc_stdc} is set to @samp{no}. If you wrote your source
+# code in ANSI C, you can make an un-ANSIfied copy of it by using the
+# program @code{ansi2knr}, which comes with Ghostscript.
+# @end defmac
+
+AC_DEFUN(AM_PROG_CC_STDC,
+[AC_REQUIRE([AC_PROG_CC])
+AC_BEFORE([$0], [AC_C_INLINE])
+AC_BEFORE([$0], [AC_C_CONST])
+dnl Force this before AC_PROG_CPP. Some cpp's, eg on HPUX, require
+dnl a magic option to avoid problems with ANSI preprocessor commands
+dnl like #elif.
+dnl FIXME: can't do this because then AC_AIX won't work due to a
+dnl circular dependency.
+dnl AC_BEFORE([$0], [AC_PROG_CPP])
+AC_MSG_CHECKING(for ${CC-cc} option to accept ANSI C)
+AC_CACHE_VAL(am_cv_prog_cc_stdc,
+[am_cv_prog_cc_stdc=no
+ac_save_CC="$CC"
+# Don't try gcc -ansi; that turns off useful extensions and
+# breaks some systems' header files.
+# AIX -qlanglvl=ansi
+# Ultrix and OSF/1 -std1
+# HP-UX -Aa -D_HPUX_SOURCE
+# SVR4 -Xc -D__EXTENSIONS__
+for ac_arg in "" -qlanglvl=ansi -std1 "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+ CC="$ac_save_CC $ac_arg"
+ AC_TRY_COMPILE(
+[#include <stdarg.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+ char **p;
+ int i;
+{
+ return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+ char *s;
+ va_list v;
+ va_start (v,p);
+ s = g (p, va_arg (v,int));
+ va_end (v);
+ return s;
+}
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+], [
+return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1];
+],
+[am_cv_prog_cc_stdc="$ac_arg"; break])
+done
+CC="$ac_save_CC"
+])
+if test -z "$am_cv_prog_cc_stdc"; then
+ AC_MSG_RESULT([none needed])
+else
+ AC_MSG_RESULT($am_cv_prog_cc_stdc)
+fi
+case "x$am_cv_prog_cc_stdc" in
+ x|xno) ;;
+ *) CC="$CC $am_cv_prog_cc_stdc" ;;
+esac
+])
+
+# This file is derived from `gettext.m4'. The difference is that the
+# included macros assume Cygnus-style source and build trees.
+
+# Macro to add for using GNU gettext.
+# Ulrich Drepper <drepper@cygnus.com>, 1995.
+#
+# This file file be copied and used freely without restrictions. It can
+# be used in projects which are not available under the GNU Public License
+# but which still want to provide support for the GNU gettext functionality.
+# Please note that the actual code is *not* freely available.
+
+# serial 3
+
+AC_DEFUN(CY_WITH_NLS,
+ [AC_MSG_CHECKING([whether NLS is requested])
+ dnl Default is enabled NLS
+ AC_ARG_ENABLE(nls,
+ [ --disable-nls do not use Native Language Support],
+ USE_NLS=$enableval, USE_NLS=yes)
+ AC_MSG_RESULT($USE_NLS)
+ AC_SUBST(USE_NLS)
+
+ USE_INCLUDED_LIBINTL=no
+
+ dnl If we use NLS figure out what method
+ if test "$USE_NLS" = "yes"; then
+ AC_DEFINE(ENABLE_NLS, 1, [Define to 1 if NLS is requested])
+ AC_MSG_CHECKING([whether included gettext is requested])
+ AC_ARG_WITH(included-gettext,
+ [ --with-included-gettext use the GNU gettext library included here],
+ nls_cv_force_use_gnu_gettext=$withval,
+ nls_cv_force_use_gnu_gettext=no)
+ AC_MSG_RESULT($nls_cv_force_use_gnu_gettext)
+
+ nls_cv_use_gnu_gettext="$nls_cv_force_use_gnu_gettext"
+ if test "$nls_cv_force_use_gnu_gettext" != "yes"; then
+ dnl User does not insist on using GNU NLS library. Figure out what
+ dnl to use. If gettext or catgets are available (in this order) we
+ dnl use this. Else we have to fall back to GNU NLS library.
+ dnl catgets is only used if permitted by option --with-catgets.
+ nls_cv_header_intl=
+ nls_cv_header_libgt=
+ CATOBJEXT=NONE
+
+ AC_CHECK_HEADER(libintl.h,
+ [AC_CACHE_CHECK([for gettext in libc], gt_cv_func_gettext_libc,
+ [AC_TRY_LINK([#include <libintl.h>], [return (int) gettext ("")],
+ gt_cv_func_gettext_libc=yes, gt_cv_func_gettext_libc=no)])
+
+ if test "$gt_cv_func_gettext_libc" != "yes"; then
+ AC_CHECK_LIB(intl, bindtextdomain,
+ [AC_CACHE_CHECK([for gettext in libintl],
+ gt_cv_func_gettext_libintl,
+ [AC_TRY_LINK([], [return (int) gettext ("")],
+ gt_cv_func_gettext_libintl=yes,
+ gt_cv_func_gettext_libintl=no)])])
+ fi
+
+ if test "$gt_cv_func_gettext_libc" = "yes" \
+ || test "$gt_cv_func_gettext_libintl" = "yes"; then
+ AC_DEFINE(HAVE_GETTEXT, 1,
+ [Define as 1 if you have gettext and don't want to use GNU gettext.])
+ AM_PATH_PROG_WITH_TEST(MSGFMT, msgfmt,
+ [test -z "`$ac_dir/$ac_word -h 2>&1 | grep 'dv '`"], no)dnl
+ if test "$MSGFMT" != "no"; then
+ AC_CHECK_FUNCS(dcgettext)
+ AC_PATH_PROG(GMSGFMT, gmsgfmt, $MSGFMT)
+ AM_PATH_PROG_WITH_TEST(XGETTEXT, xgettext,
+ [test -z "`$ac_dir/$ac_word -h 2>&1 | grep '(HELP)'`"], :)
+ AC_TRY_LINK(, [extern int _nl_msg_cat_cntr;
+ return _nl_msg_cat_cntr],
+ [CATOBJEXT=.gmo
+ DATADIRNAME=share],
+ [CATOBJEXT=.mo
+ DATADIRNAME=lib])
+ INSTOBJEXT=.mo
+ fi
+ fi
+ ])
+
+ dnl In the standard gettext, we would now check for catgets.
+ dnl However, we never want to use catgets for our releases.
+
+ if test "$CATOBJEXT" = "NONE"; then
+ dnl Neither gettext nor catgets in included in the C library.
+ dnl Fall back on GNU gettext library.
+ nls_cv_use_gnu_gettext=yes
+ fi
+ fi
+
+ if test "$nls_cv_use_gnu_gettext" = "yes"; then
+ dnl Mark actions used to generate GNU NLS library.
+ INTLOBJS="\$(GETTOBJS)"
+ AM_PATH_PROG_WITH_TEST(MSGFMT, msgfmt,
+ [test -z "`$ac_dir/$ac_word -h 2>&1 | grep 'dv '`"], msgfmt)
+ AC_PATH_PROG(GMSGFMT, gmsgfmt, $MSGFMT)
+ AM_PATH_PROG_WITH_TEST(XGETTEXT, xgettext,
+ [test -z "`$ac_dir/$ac_word -h 2>&1 | grep '(HELP)'`"], :)
+ AC_SUBST(MSGFMT)
+ USE_INCLUDED_LIBINTL=yes
+ CATOBJEXT=.gmo
+ INSTOBJEXT=.mo
+ DATADIRNAME=share
+ INTLDEPS='$(top_builddir)/../intl/libintl.a'
+ INTLLIBS=$INTLDEPS
+ LIBS=`echo $LIBS | sed -e 's/-lintl//'`
+ nls_cv_header_intl=libintl.h
+ nls_cv_header_libgt=libgettext.h
+ fi
+
+ dnl Test whether we really found GNU xgettext.
+ if test "$XGETTEXT" != ":"; then
+ dnl If it is no GNU xgettext we define it as : so that the
+ dnl Makefiles still can work.
+ if $XGETTEXT --omit-header /dev/null 2> /dev/null; then
+ : ;
+ else
+ AC_MSG_RESULT(
+ [found xgettext programs is not GNU xgettext; ignore it])
+ XGETTEXT=":"
+ fi
+ fi
+
+ # We need to process the po/ directory.
+ POSUB=po
+ else
+ DATADIRNAME=share
+ nls_cv_header_intl=libintl.h
+ nls_cv_header_libgt=libgettext.h
+ fi
+
+ # If this is used in GNU gettext we have to set USE_NLS to `yes'
+ # because some of the sources are only built for this goal.
+ if test "$PACKAGE" = gettext; then
+ USE_NLS=yes
+ USE_INCLUDED_LIBINTL=yes
+ fi
+
+ dnl These rules are solely for the distribution goal. While doing this
+ dnl we only have to keep exactly one list of the available catalogs
+ dnl in configure.in.
+ for lang in $ALL_LINGUAS; do
+ GMOFILES="$GMOFILES $lang.gmo"
+ POFILES="$POFILES $lang.po"
+ done
+
+ dnl Make all variables we use known to autoconf.
+ AC_SUBST(USE_INCLUDED_LIBINTL)
+ AC_SUBST(CATALOGS)
+ AC_SUBST(CATOBJEXT)
+ AC_SUBST(DATADIRNAME)
+ AC_SUBST(GMOFILES)
+ AC_SUBST(INSTOBJEXT)
+ AC_SUBST(INTLDEPS)
+ AC_SUBST(INTLLIBS)
+ AC_SUBST(INTLOBJS)
+ AC_SUBST(POFILES)
+ AC_SUBST(POSUB)
+ ])
+
+AC_DEFUN(CY_GNU_GETTEXT,
+ [AC_REQUIRE([AC_PROG_MAKE_SET])dnl
+ AC_REQUIRE([AC_PROG_CC])dnl
+ AC_REQUIRE([AC_PROG_RANLIB])dnl
+ AC_REQUIRE([AC_ISC_POSIX])dnl
+ AC_REQUIRE([AC_HEADER_STDC])dnl
+ AC_REQUIRE([AC_C_CONST])dnl
+ AC_REQUIRE([AC_C_INLINE])dnl
+ AC_REQUIRE([AC_TYPE_OFF_T])dnl
+ AC_REQUIRE([AC_TYPE_SIZE_T])dnl
+ AC_REQUIRE([AC_FUNC_ALLOCA])dnl
+ AC_REQUIRE([AC_FUNC_MMAP])dnl
+
+ AC_CHECK_HEADERS([argz.h limits.h locale.h nl_types.h malloc.h string.h \
+unistd.h values.h sys/param.h])
+ AC_CHECK_FUNCS([getcwd munmap putenv setenv setlocale strchr strcasecmp \
+__argz_count __argz_stringify __argz_next])
+
+ if test "${ac_cv_func_stpcpy+set}" != "set"; then
+ AC_CHECK_FUNCS(stpcpy)
+ fi
+ if test "${ac_cv_func_stpcpy}" = "yes"; then
+ AC_DEFINE(HAVE_STPCPY, 1, [Define if you have the stpcpy function])
+ fi
+
+ AM_LC_MESSAGES
+ CY_WITH_NLS
+
+ if test "x$CATOBJEXT" != "x"; then
+ if test "x$ALL_LINGUAS" = "x"; then
+ LINGUAS=
+ else
+ AC_MSG_CHECKING(for catalogs to be installed)
+ NEW_LINGUAS=
+ for lang in ${LINGUAS=$ALL_LINGUAS}; do
+ case "$ALL_LINGUAS" in
+ *$lang*) NEW_LINGUAS="$NEW_LINGUAS $lang" ;;
+ esac
+ done
+ LINGUAS=$NEW_LINGUAS
+ AC_MSG_RESULT($LINGUAS)
+ fi
+
+ dnl Construct list of names of catalog files to be constructed.
+ if test -n "$LINGUAS"; then
+ for lang in $LINGUAS; do CATALOGS="$CATALOGS $lang$CATOBJEXT"; done
+ fi
+ fi
+
+ dnl The reference to <locale.h> in the installed <libintl.h> file
+ dnl must be resolved because we cannot expect the users of this
+ dnl to define HAVE_LOCALE_H.
+ if test $ac_cv_header_locale_h = yes; then
+ INCLUDE_LOCALE_H="#include <locale.h>"
+ else
+ INCLUDE_LOCALE_H="\
+/* The system does not provide the header <locale.h>. Take care yourself. */"
+ fi
+ AC_SUBST(INCLUDE_LOCALE_H)
+
+ dnl Determine which catalog format we have (if any is needed)
+ dnl For now we know about two different formats:
+ dnl Linux libc-5 and the normal X/Open format
+ if test -f $srcdir/po2tbl.sed.in; then
+ if test "$CATOBJEXT" = ".cat"; then
+ AC_CHECK_HEADER(linux/version.h, msgformat=linux, msgformat=xopen)
+
+ dnl Transform the SED scripts while copying because some dumb SEDs
+ dnl cannot handle comments.
+ sed -e '/^#/d' $srcdir/$msgformat-msg.sed > po2msg.sed
+ fi
+ dnl po2tbl.sed is always needed.
+ sed -e '/^#.*[^\\]$/d' -e '/^#$/d' \
+ $srcdir/po2tbl.sed.in > po2tbl.sed
+ fi
+
+ dnl In the intl/Makefile.in we have a special dependency which makes
+ dnl only sense for gettext. We comment this out for non-gettext
+ dnl packages.
+ if test "$PACKAGE" = "gettext"; then
+ GT_NO="#NO#"
+ GT_YES=
+ else
+ GT_NO=
+ GT_YES="#YES#"
+ fi
+ AC_SUBST(GT_NO)
+ AC_SUBST(GT_YES)
+
+ MKINSTALLDIRS="\$(srcdir)/../../mkinstalldirs"
+ AC_SUBST(MKINSTALLDIRS)
+
+ dnl *** For now the libtool support in intl/Makefile is not for real.
+ l=
+ AC_SUBST(l)
+
+ dnl Generate list of files to be processed by xgettext which will
+ dnl be included in po/Makefile. But only do this if the po directory
+ dnl exists in srcdir.
+ if test -d $srcdir/po; then
+ test -d po || mkdir po
+ if test "x$srcdir" != "x."; then
+ if test "x`echo $srcdir | sed 's@/.*@@'`" = "x"; then
+ posrcprefix="$srcdir/"
+ else
+ posrcprefix="../$srcdir/"
+ fi
+ else
+ posrcprefix="../"
+ fi
+ rm -f po/POTFILES
+ sed -e "/^#/d" -e "/^\$/d" -e "s,.*, $posrcprefix& \\\\," -e "\$s/\(.*\) \\\\/\1/" \
+ < $srcdir/po/POTFILES.in > po/POTFILES
+ fi
+ ])
+
+# Search path for a program which passes the given test.
+# Ulrich Drepper <drepper@cygnus.com>, 1996.
+#
+# This file file be copied and used freely without restrictions. It can
+# be used in projects which are not available under the GNU Public License
+# but which still want to provide support for the GNU gettext functionality.
+# Please note that the actual code is *not* freely available.
+
+# serial 1
+
+dnl AM_PATH_PROG_WITH_TEST(VARIABLE, PROG-TO-CHECK-FOR,
+dnl TEST-PERFORMED-ON-FOUND_PROGRAM [, VALUE-IF-NOT-FOUND [, PATH]])
+AC_DEFUN(AM_PATH_PROG_WITH_TEST,
+[# Extract the first word of "$2", so it can be a program name with args.
+set dummy $2; ac_word=[$]2
+AC_MSG_CHECKING([for $ac_word])
+AC_CACHE_VAL(ac_cv_path_$1,
+[case "[$]$1" in
+ /*)
+ ac_cv_path_$1="[$]$1" # Let the user override the test with a path.
+ ;;
+ *)
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+ for ac_dir in ifelse([$5], , $PATH, [$5]); do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ if [$3]; then
+ ac_cv_path_$1="$ac_dir/$ac_word"
+ break
+ fi
+ fi
+ done
+ IFS="$ac_save_ifs"
+dnl If no 4th arg is given, leave the cache variable unset,
+dnl so AC_PATH_PROGS will keep looking.
+ifelse([$4], , , [ test -z "[$]ac_cv_path_$1" && ac_cv_path_$1="$4"
+])dnl
+ ;;
+esac])dnl
+$1="$ac_cv_path_$1"
+if test -n "[$]$1"; then
+ AC_MSG_RESULT([$]$1)
+else
+ AC_MSG_RESULT(no)
+fi
+AC_SUBST($1)dnl
+])
+
+# Check whether LC_MESSAGES is available in <locale.h>.
+# Ulrich Drepper <drepper@cygnus.com>, 1995.
+#
+# This file file be copied and used freely without restrictions. It can
+# be used in projects which are not available under the GNU Public License
+# but which still want to provide support for the GNU gettext functionality.
+# Please note that the actual code is *not* freely available.
+
+# serial 1
+
+AC_DEFUN(AM_LC_MESSAGES,
+ [if test $ac_cv_header_locale_h = yes; then
+ AC_CACHE_CHECK([for LC_MESSAGES], am_cv_val_LC_MESSAGES,
+ [AC_TRY_LINK([#include <locale.h>], [return LC_MESSAGES],
+ am_cv_val_LC_MESSAGES=yes, am_cv_val_LC_MESSAGES=no)])
+ if test $am_cv_val_LC_MESSAGES = yes; then
+ AC_DEFINE(HAVE_LC_MESSAGES, 1,
+ [Define if your locale.h file contains LC_MESSAGES.])
+ fi
+ fi])
+
diff --git a/gdb/alpha-nat.c b/gdb/alpha-nat.c
new file mode 100644
index 00000000000..59bd0d887e5
--- /dev/null
+++ b/gdb/alpha-nat.c
@@ -0,0 +1,297 @@
+/* Low level Alpha interface, for GDB when running native.
+ Copyright 1993, 1995, 1996, 1998 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "inferior.h"
+#include "gdbcore.h"
+#include "target.h"
+#include <sys/ptrace.h>
+#ifdef __linux__
+# include <asm/reg.h>
+# include <alpha/ptrace.h>
+#else
+# include <machine/reg.h>
+#endif
+#include <sys/user.h>
+
+/* Prototypes for local functions. */
+
+static void fetch_osf_core_registers PARAMS ((char *,
+ unsigned, int, CORE_ADDR));
+static void fetch_elf_core_registers PARAMS ((char *,
+ unsigned, int, CORE_ADDR));
+
+/* Size of elements in jmpbuf */
+
+#define JB_ELEMENT_SIZE 8
+
+/* The definition for JB_PC in machine/reg.h is wrong.
+ And we can't get at the correct definition in setjmp.h as it is
+ not always available (eg. if _POSIX_SOURCE is defined which is the
+ default). As the defintion is unlikely to change (see comment
+ in <setjmp.h>, define the correct value here. */
+
+#undef JB_PC
+#define JB_PC 2
+
+/* Figure out where the longjmp will land.
+ 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;
+{
+ CORE_ADDR jb_addr;
+ char raw_buffer[MAX_REGISTER_RAW_SIZE];
+
+ jb_addr = read_register(A0_REGNUM);
+
+ if (target_read_memory(jb_addr + JB_PC * JB_ELEMENT_SIZE, raw_buffer,
+ sizeof(CORE_ADDR)))
+ return 0;
+
+ *pc = extract_address (raw_buffer, sizeof(CORE_ADDR));
+ return 1;
+}
+
+/* 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.
+ */
+
+static void
+fetch_osf_core_registers (core_reg_sect, core_reg_size, which, reg_addr)
+ char *core_reg_sect;
+ unsigned core_reg_size;
+ int which;
+ CORE_ADDR reg_addr;
+{
+ register int regno;
+ register int addr;
+ int bad_reg = -1;
+
+ /* Table to map a gdb regnum to an index in the core register section.
+ The floating point register values are garbage in OSF/1.2 core files. */
+ static int core_reg_mapping[NUM_REGS] =
+ {
+#define EFL (EF_SIZE / 8)
+ EF_V0, EF_T0, EF_T1, EF_T2, EF_T3, EF_T4, EF_T5, EF_T6,
+ EF_T7, EF_S0, EF_S1, EF_S2, EF_S3, EF_S4, EF_S5, EF_S6,
+ EF_A0, EF_A1, EF_A2, EF_A3, EF_A4, EF_A5, EF_T8, EF_T9,
+ EF_T10, EF_T11, EF_RA, EF_T12, EF_AT, EF_GP, EF_SP, -1,
+ EFL+0, EFL+1, EFL+2, EFL+3, EFL+4, EFL+5, EFL+6, EFL+7,
+ EFL+8, EFL+9, EFL+10, EFL+11, EFL+12, EFL+13, EFL+14, EFL+15,
+ EFL+16, EFL+17, EFL+18, EFL+19, EFL+20, EFL+21, EFL+22, EFL+23,
+ EFL+24, EFL+25, EFL+26, EFL+27, EFL+28, EFL+29, EFL+30, EFL+31,
+ EF_PC, -1
+ };
+ static char zerobuf[MAX_REGISTER_RAW_SIZE] = {0};
+
+ for (regno = 0; regno < NUM_REGS; regno++)
+ {
+ if (CANNOT_FETCH_REGISTER (regno))
+ {
+ supply_register (regno, zerobuf);
+ continue;
+ }
+ addr = 8 * core_reg_mapping[regno];
+ if (addr < 0 || 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.", REGISTER_NAME (bad_reg));
+ }
+}
+
+static void
+fetch_elf_core_registers (core_reg_sect, core_reg_size, which, reg_addr)
+ char *core_reg_sect;
+ unsigned core_reg_size;
+ int which;
+ CORE_ADDR reg_addr;
+{
+ if (core_reg_size < 32*8)
+ {
+ error ("Core file register section too small (%u bytes).", core_reg_size);
+ return;
+ }
+
+ if (which == 2)
+ {
+ /* The FPU Registers. */
+ memcpy (&registers[REGISTER_BYTE (FP0_REGNUM)], core_reg_sect, 31*8);
+ memset (&registers[REGISTER_BYTE (FP0_REGNUM+31)], 0, 8);
+ memset (&register_valid[FP0_REGNUM], 1, 32);
+ }
+ else
+ {
+ /* The General Registers. */
+ memcpy (&registers[REGISTER_BYTE (V0_REGNUM)], core_reg_sect, 31*8);
+ memcpy (&registers[REGISTER_BYTE (PC_REGNUM)], core_reg_sect+31*8, 8);
+ memset (&registers[REGISTER_BYTE (ZERO_REGNUM)], 0, 8);
+ memset (&register_valid[V0_REGNUM], 1, 32);
+ register_valid[PC_REGNUM] = 1;
+ }
+}
+
+
+/* Map gdb internal register number to a ptrace ``address''.
+ These ``addresses'' are defined in <sys/ptrace.h> */
+
+#define REGISTER_PTRACE_ADDR(regno) \
+ (regno < FP0_REGNUM ? GPR_BASE + (regno) \
+ : regno == PC_REGNUM ? PC \
+ : regno >= FP0_REGNUM ? FPR_BASE + ((regno) - FP0_REGNUM) \
+ : 0)
+
+/* Return the ptrace ``address'' of register REGNO. */
+
+CORE_ADDR
+register_addr (regno, blockend)
+ int regno;
+ CORE_ADDR blockend;
+{
+ return REGISTER_PTRACE_ADDR (regno);
+}
+
+int
+kernel_u_size ()
+{
+ return (sizeof (struct user));
+}
+
+#if defined(USE_PROC_FS) || defined(HAVE_GREGSET_T)
+#include <sys/procfs.h>
+
+/*
+ * See the comment in m68k-tdep.c regarding the utility of these functions.
+ */
+
+void
+supply_gregset (gregsetp)
+ gregset_t *gregsetp;
+{
+ register int regi;
+ register long *regp = ALPHA_REGSET_BASE (gregsetp);
+ static char zerobuf[MAX_REGISTER_RAW_SIZE] = {0};
+
+ for (regi = 0; regi < 31; regi++)
+ supply_register (regi, (char *)(regp + regi));
+
+ supply_register (PC_REGNUM, (char *)(regp + 31));
+
+ /* Fill inaccessible registers with zero. */
+ supply_register (ZERO_REGNUM, zerobuf);
+ supply_register (FP_REGNUM, zerobuf);
+}
+
+void
+fill_gregset (gregsetp, regno)
+ gregset_t *gregsetp;
+ int regno;
+{
+ int regi;
+ register long *regp = ALPHA_REGSET_BASE (gregsetp);
+
+ for (regi = 0; regi < 31; regi++)
+ if ((regno == -1) || (regno == regi))
+ *(regp + regi) = *(long *) &registers[REGISTER_BYTE (regi)];
+
+ if ((regno == -1) || (regno == PC_REGNUM))
+ *(regp + 31) = *(long *) &registers[REGISTER_BYTE (PC_REGNUM)];
+}
+
+/*
+ * Now we do the same thing for floating-point registers.
+ * Again, see the comments in m68k-tdep.c.
+ */
+
+void
+supply_fpregset (fpregsetp)
+ fpregset_t *fpregsetp;
+{
+ register int regi;
+ register long *regp = ALPHA_REGSET_BASE (fpregsetp);
+
+ for (regi = 0; regi < 32; regi++)
+ supply_register (regi + FP0_REGNUM, (char *)(regp + regi));
+}
+
+void
+fill_fpregset (fpregsetp, regno)
+ fpregset_t *fpregsetp;
+ int regno;
+{
+ int regi;
+ register long *regp = ALPHA_REGSET_BASE (fpregsetp);
+
+ for (regi = FP0_REGNUM; regi < FP0_REGNUM + 32; regi++)
+ {
+ if ((regno == -1) || (regno == regi))
+ {
+ *(regp + regi - FP0_REGNUM) =
+ *(long *) &registers[REGISTER_BYTE (regi)];
+ }
+ }
+}
+#endif
+
+
+/* Register that we are able to handle alpha core file formats. */
+
+static struct core_fns alpha_osf_core_fns =
+{
+ /* This really is bfd_target_unknown_flavour. */
+
+ bfd_target_unknown_flavour,
+ fetch_osf_core_registers,
+ NULL
+};
+
+static struct core_fns alpha_elf_core_fns =
+{
+ bfd_target_elf_flavour,
+ fetch_elf_core_registers,
+ NULL
+};
+
+void
+_initialize_core_alpha ()
+{
+ add_core_fns (&alpha_osf_core_fns);
+ add_core_fns (&alpha_elf_core_fns);
+}
diff --git a/gdb/alpha-tdep.c b/gdb/alpha-tdep.c
new file mode 100644
index 00000000000..02010160b96
--- /dev/null
+++ b/gdb/alpha-tdep.c
@@ -0,0 +1,1410 @@
+/* Target-dependent code for the ALPHA architecture, for GDB, the GNU Debugger.
+ Copyright 1993, 94, 95, 96, 97, 1998 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "frame.h"
+#include "inferior.h"
+#include "symtab.h"
+#include "value.h"
+#include "gdbcmd.h"
+#include "gdbcore.h"
+#include "dis-asm.h"
+#include "symfile.h"
+#include "objfiles.h"
+#include "gdb_string.h"
+
+/* FIXME: Some of this code should perhaps be merged with mips-tdep.c. */
+
+/* Prototypes for local functions. */
+
+static alpha_extra_func_info_t push_sigtramp_desc PARAMS ((CORE_ADDR low_addr));
+
+static CORE_ADDR read_next_frame_reg PARAMS ((struct frame_info *, int));
+
+static CORE_ADDR heuristic_proc_start PARAMS ((CORE_ADDR));
+
+static alpha_extra_func_info_t heuristic_proc_desc PARAMS ((CORE_ADDR,
+ CORE_ADDR,
+ struct frame_info *));
+
+static alpha_extra_func_info_t find_proc_desc PARAMS ((CORE_ADDR,
+ struct frame_info *));
+
+#if 0
+static int alpha_in_lenient_prologue PARAMS ((CORE_ADDR, CORE_ADDR));
+#endif
+
+static void reinit_frame_cache_sfunc PARAMS ((char *, int,
+ struct cmd_list_element *));
+
+static CORE_ADDR after_prologue PARAMS ((CORE_ADDR pc,
+ alpha_extra_func_info_t proc_desc));
+
+static int alpha_in_prologue PARAMS ((CORE_ADDR pc,
+ alpha_extra_func_info_t proc_desc));
+
+/* Heuristic_proc_start may hunt through the text section for a long
+ time across a 2400 baud serial line. Allows the user to limit this
+ search. */
+static unsigned int heuristic_fence_post = 0;
+
+/* Layout of a stack frame on the alpha:
+
+ | |
+ pdr members: | 7th ... nth arg, |
+ | `pushed' by caller. |
+ | |
+----------------|-------------------------------|<-- old_sp == vfp
+ ^ ^ ^ ^ | |
+ | | | | | |
+ | |localoff | Copies of 1st .. 6th |
+ | | | | | argument if necessary. |
+ | | | v | |
+ | | | --- |-------------------------------|<-- FRAME_LOCALS_ADDRESS
+ | | | | |
+ | | | | Locals and temporaries. |
+ | | | | |
+ | | | |-------------------------------|
+ | | | | |
+ |-fregoffset | Saved float registers. |
+ | | | | F9 |
+ | | | | . |
+ | | | | . |
+ | | | | F2 |
+ | | v | |
+ | | -------|-------------------------------|
+ | | | |
+ | | | Saved registers. |
+ | | | S6 |
+ |-regoffset | . |
+ | | | . |
+ | | | S0 |
+ | | | pdr.pcreg |
+ | v | |
+ | ----------|-------------------------------|
+ | | |
+ frameoffset | Argument build area, gets |
+ | | 7th ... nth arg for any |
+ | | called procedure. |
+ v | |
+ -------------|-------------------------------|<-- sp
+ | |
+*/
+
+#define PROC_LOW_ADDR(proc) ((proc)->pdr.adr) /* least address */
+#define PROC_HIGH_ADDR(proc) ((proc)->pdr.iline) /* upper address bound */
+#define PROC_DUMMY_FRAME(proc) ((proc)->pdr.iopt) /* frame for CALL_DUMMY */
+#define PROC_FRAME_OFFSET(proc) ((proc)->pdr.frameoffset)
+#define PROC_FRAME_REG(proc) ((proc)->pdr.framereg)
+#define PROC_REG_MASK(proc) ((proc)->pdr.regmask)
+#define PROC_FREG_MASK(proc) ((proc)->pdr.fregmask)
+#define PROC_REG_OFFSET(proc) ((proc)->pdr.regoffset)
+#define PROC_FREG_OFFSET(proc) ((proc)->pdr.fregoffset)
+#define PROC_PC_REG(proc) ((proc)->pdr.pcreg)
+#define PROC_LOCALOFF(proc) ((proc)->pdr.localoff)
+#define PROC_SYMBOL(proc) (*(struct symbol**)&(proc)->pdr.isym)
+#define _PROC_MAGIC_ 0x0F0F0F0F
+#define PROC_DESC_IS_DUMMY(proc) ((proc)->pdr.isym == _PROC_MAGIC_)
+#define SET_PROC_DESC_IS_DUMMY(proc) ((proc)->pdr.isym = _PROC_MAGIC_)
+
+struct linked_proc_info
+{
+ struct alpha_extra_func_info info;
+ struct linked_proc_info *next;
+} *linked_proc_desc_table = NULL;
+
+
+/* Under GNU/Linux, signal handler invocations can be identified by the
+ designated code sequence that is used to return from a signal
+ handler. In particular, the return address of a signal handler
+ points to the following sequence (the first instruction is quadword
+ aligned):
+
+ bis $30,$30,$16
+ addq $31,0x67,$0
+ call_pal callsys
+
+ Each instruction has a unique encoding, so we simply attempt to
+ match the instruction the pc is pointing to with any of the above
+ instructions. If there is a hit, we know the offset to the start
+ of the designated sequence and can then check whether we really are
+ executing in a designated sequence. If not, -1 is returned,
+ otherwise the offset from the start of the desingated sequence is
+ returned.
+
+ There is a slight chance of false hits: code could jump into the
+ middle of the designated sequence, in which case there is no
+ guarantee that we are in the middle of a sigreturn syscall. Don't
+ think this will be a problem in praxis, though.
+*/
+
+long
+alpha_linux_sigtramp_offset (CORE_ADDR pc)
+{
+ unsigned int i[3], w;
+ long off;
+
+ if (read_memory_nobpt(pc, (char *) &w, 4) != 0)
+ return -1;
+
+ off = -1;
+ switch (w)
+ {
+ case 0x47de0410: off = 0; break; /* bis $30,$30,$16 */
+ case 0x43ecf400: off = 4; break; /* addq $31,0x67,$0 */
+ case 0x00000083: off = 8; break; /* call_pal callsys */
+ default: return -1;
+ }
+ pc -= off;
+ if (pc & 0x7)
+ {
+ /* designated sequence is not quadword aligned */
+ return -1;
+ }
+
+ if (read_memory_nobpt(pc, (char *) i, sizeof(i)) != 0)
+ return -1;
+
+ if (i[0] == 0x47de0410 && i[1] == 0x43ecf400 && i[2] == 0x00000083)
+ return off;
+
+ return -1;
+}
+
+
+/* Under OSF/1, the __sigtramp routine is frameless and has a frame
+ size of zero, but we are able to backtrace through it. */
+CORE_ADDR
+alpha_osf_skip_sigtramp_frame (frame, pc)
+ struct frame_info *frame;
+ CORE_ADDR pc;
+{
+ char *name;
+ find_pc_partial_function (pc, &name, (CORE_ADDR *)NULL, (CORE_ADDR *)NULL);
+ if (IN_SIGTRAMP (pc, name))
+ return frame->frame;
+ else
+ return 0;
+}
+
+
+/* Dynamically create a signal-handler caller procedure descriptor for
+ the signal-handler return code starting at address LOW_ADDR. The
+ descriptor is added to the linked_proc_desc_table. */
+
+static alpha_extra_func_info_t
+push_sigtramp_desc (low_addr)
+ CORE_ADDR low_addr;
+{
+ struct linked_proc_info *link;
+ alpha_extra_func_info_t proc_desc;
+
+ link = (struct linked_proc_info *)
+ xmalloc (sizeof (struct linked_proc_info));
+ link->next = linked_proc_desc_table;
+ linked_proc_desc_table = link;
+
+ proc_desc = &link->info;
+
+ proc_desc->numargs = 0;
+ PROC_LOW_ADDR (proc_desc) = low_addr;
+ PROC_HIGH_ADDR (proc_desc) = low_addr + 3 * 4;
+ PROC_DUMMY_FRAME (proc_desc) = 0;
+ PROC_FRAME_OFFSET (proc_desc) = 0x298; /* sizeof(struct sigcontext_struct) */
+ PROC_FRAME_REG (proc_desc) = SP_REGNUM;
+ PROC_REG_MASK (proc_desc) = 0xffff;
+ PROC_FREG_MASK (proc_desc) = 0xffff;
+ PROC_PC_REG (proc_desc) = 26;
+ PROC_LOCALOFF (proc_desc) = 0;
+ SET_PROC_DESC_IS_DYN_SIGTRAMP (proc_desc);
+ return (proc_desc);
+}
+
+
+/* Guaranteed to set frame->saved_regs to some values (it never leaves it
+ NULL). */
+
+void
+alpha_find_saved_regs (frame)
+ struct frame_info *frame;
+{
+ int ireg;
+ CORE_ADDR reg_position;
+ unsigned long mask;
+ alpha_extra_func_info_t proc_desc;
+ int returnreg;
+
+ frame_saved_regs_zalloc (frame);
+
+ /* If it is the frame for __sigtramp, the saved registers are located
+ in a sigcontext structure somewhere on the stack. __sigtramp
+ passes a pointer to the sigcontext structure on the stack.
+ If the stack layout for __sigtramp changes, or if sigcontext offsets
+ change, we might have to update this code. */
+#ifndef SIGFRAME_PC_OFF
+#define SIGFRAME_PC_OFF (2 * 8)
+#define SIGFRAME_REGSAVE_OFF (4 * 8)
+#define SIGFRAME_FPREGSAVE_OFF (SIGFRAME_REGSAVE_OFF + 32 * 8 + 8)
+#endif
+ if (frame->signal_handler_caller)
+ {
+ CORE_ADDR sigcontext_addr;
+
+ sigcontext_addr = SIGCONTEXT_ADDR (frame);
+ for (ireg = 0; ireg < 32; ireg++)
+ {
+ reg_position = sigcontext_addr + SIGFRAME_REGSAVE_OFF + ireg * 8;
+ frame->saved_regs[ireg] = reg_position;
+ }
+ for (ireg = 0; ireg < 32; ireg++)
+ {
+ reg_position = sigcontext_addr + SIGFRAME_FPREGSAVE_OFF + ireg * 8;
+ frame->saved_regs[FP0_REGNUM + ireg] = reg_position;
+ }
+ frame->saved_regs[PC_REGNUM] = sigcontext_addr + SIGFRAME_PC_OFF;
+ return;
+ }
+
+ proc_desc = frame->proc_desc;
+ if (proc_desc == NULL)
+ /* I'm not sure how/whether this can happen. Normally when we can't
+ find a proc_desc, we "synthesize" one using heuristic_proc_desc
+ and set the saved_regs right away. */
+ return;
+
+ /* Fill in the offsets for the registers which gen_mask says
+ were saved. */
+
+ reg_position = frame->frame + PROC_REG_OFFSET (proc_desc);
+ mask = PROC_REG_MASK (proc_desc);
+
+ returnreg = PROC_PC_REG (proc_desc);
+
+ /* Note that RA is always saved first, regardless of its actual
+ register number. */
+ if (mask & (1 << returnreg))
+ {
+ frame->saved_regs[returnreg] = reg_position;
+ reg_position += 8;
+ mask &= ~(1 << returnreg); /* Clear bit for RA so we
+ don't save again later. */
+ }
+
+ for (ireg = 0; ireg <= 31 ; ++ireg)
+ if (mask & (1 << ireg))
+ {
+ frame->saved_regs[ireg] = reg_position;
+ reg_position += 8;
+ }
+
+ /* Fill in the offsets for the registers which float_mask says
+ were saved. */
+
+ reg_position = frame->frame + PROC_FREG_OFFSET (proc_desc);
+ mask = PROC_FREG_MASK (proc_desc);
+
+ for (ireg = 0; ireg <= 31 ; ++ireg)
+ if (mask & (1 << ireg))
+ {
+ frame->saved_regs[FP0_REGNUM+ireg] = reg_position;
+ reg_position += 8;
+ }
+
+ frame->saved_regs[PC_REGNUM] = frame->saved_regs[returnreg];
+}
+
+static CORE_ADDR
+read_next_frame_reg(fi, regno)
+ struct frame_info *fi;
+ int regno;
+{
+ for (; fi; fi = fi->next)
+ {
+ /* We have to get the saved sp from the sigcontext
+ if it is a signal handler frame. */
+ if (regno == SP_REGNUM && !fi->signal_handler_caller)
+ return fi->frame;
+ else
+ {
+ if (fi->saved_regs == NULL)
+ alpha_find_saved_regs (fi);
+ if (fi->saved_regs[regno])
+ return read_memory_integer(fi->saved_regs[regno], 8);
+ }
+ }
+ return read_register(regno);
+}
+
+CORE_ADDR
+alpha_frame_saved_pc(frame)
+ struct frame_info *frame;
+{
+ alpha_extra_func_info_t proc_desc = frame->proc_desc;
+ /* We have to get the saved pc from the sigcontext
+ if it is a signal handler frame. */
+ int pcreg = frame->signal_handler_caller ? PC_REGNUM : frame->pc_reg;
+
+ if (proc_desc && PROC_DESC_IS_DUMMY(proc_desc))
+ return read_memory_integer(frame->frame - 8, 8);
+
+ return read_next_frame_reg(frame, pcreg);
+}
+
+CORE_ADDR
+alpha_saved_pc_after_call (frame)
+ struct frame_info *frame;
+{
+ CORE_ADDR pc = frame->pc;
+ CORE_ADDR tmp;
+ alpha_extra_func_info_t proc_desc;
+ int pcreg;
+
+ /* Skip over shared library trampoline if necessary. */
+ tmp = SKIP_TRAMPOLINE_CODE (pc);
+ if (tmp != 0)
+ pc = tmp;
+
+ proc_desc = find_proc_desc (pc, frame->next);
+ pcreg = proc_desc ? PROC_PC_REG (proc_desc) : RA_REGNUM;
+
+ if (frame->signal_handler_caller)
+ return alpha_frame_saved_pc (frame);
+ else
+ return read_register (pcreg);
+}
+
+
+static struct alpha_extra_func_info temp_proc_desc;
+static struct frame_saved_regs temp_saved_regs;
+
+/* Nonzero if instruction at PC is a return instruction. "ret
+ $zero,($ra),1" on alpha. */
+
+static int
+alpha_about_to_return (pc)
+ CORE_ADDR pc;
+{
+ return read_memory_integer (pc, 4) == 0x6bfa8001;
+}
+
+
+
+/* This fencepost looks highly suspicious to me. Removing it also
+ seems suspicious as it could affect remote debugging across serial
+ lines. */
+
+static CORE_ADDR
+heuristic_proc_start(pc)
+ CORE_ADDR pc;
+{
+ CORE_ADDR start_pc = pc;
+ CORE_ADDR fence = start_pc - heuristic_fence_post;
+
+ if (start_pc == 0) return 0;
+
+ if (heuristic_fence_post == UINT_MAX
+ || fence < VM_MIN_ADDRESS)
+ fence = VM_MIN_ADDRESS;
+
+ /* search back for previous return */
+ for (start_pc -= 4; ; start_pc -= 4)
+ if (start_pc < fence)
+ {
+ /* It's not clear to me why we reach this point when
+ stop_soon_quietly, but with this test, at least we
+ don't print out warnings for every child forked (eg, on
+ decstation). 22apr93 rich@cygnus.com. */
+ if (!stop_soon_quietly)
+ {
+ static int blurb_printed = 0;
+
+ if (fence == VM_MIN_ADDRESS)
+ warning("Hit beginning of text section without finding");
+ else
+ warning("Hit heuristic-fence-post without finding");
+
+ warning("enclosing function for address 0x%lx", pc);
+ if (!blurb_printed)
+ {
+ printf_filtered ("\
+This warning occurs if you are debugging a function without any symbols\n\
+(for example, in a stripped executable). In that case, you may wish to\n\
+increase the size of the search with the `set heuristic-fence-post' command.\n\
+\n\
+Otherwise, you told GDB there was a function where there isn't one, or\n\
+(more likely) you have encountered a bug in GDB.\n");
+ blurb_printed = 1;
+ }
+ }
+
+ return 0;
+ }
+ else if (alpha_about_to_return (start_pc))
+ break;
+
+ start_pc += 4; /* skip return */
+ return start_pc;
+}
+
+static alpha_extra_func_info_t
+heuristic_proc_desc(start_pc, limit_pc, next_frame)
+ CORE_ADDR start_pc, limit_pc;
+ struct frame_info *next_frame;
+{
+ CORE_ADDR sp = read_next_frame_reg (next_frame, SP_REGNUM);
+ CORE_ADDR cur_pc;
+ int frame_size;
+ int has_frame_reg = 0;
+ unsigned long reg_mask = 0;
+ int pcreg = -1;
+
+ if (start_pc == 0)
+ return NULL;
+ memset (&temp_proc_desc, '\0', sizeof(temp_proc_desc));
+ memset (&temp_saved_regs, '\0', sizeof(struct frame_saved_regs));
+ PROC_LOW_ADDR (&temp_proc_desc) = start_pc;
+
+ if (start_pc + 200 < limit_pc)
+ limit_pc = start_pc + 200;
+ frame_size = 0;
+ for (cur_pc = start_pc; cur_pc < limit_pc; cur_pc += 4)
+ {
+ char buf[4];
+ unsigned long word;
+ int status;
+
+ status = read_memory_nobpt (cur_pc, buf, 4);
+ if (status)
+ memory_error (status, cur_pc);
+ word = extract_unsigned_integer (buf, 4);
+
+ if ((word & 0xffff0000) == 0x23de0000) /* lda $sp,n($sp) */
+ {
+ if (word & 0x8000)
+ frame_size += (-word) & 0xffff;
+ else
+ /* Exit loop if a positive stack adjustment is found, which
+ usually means that the stack cleanup code in the function
+ epilogue is reached. */
+ break;
+ }
+ else if ((word & 0xfc1f0000) == 0xb41e0000 /* stq reg,n($sp) */
+ && (word & 0xffff0000) != 0xb7fe0000) /* reg != $zero */
+ {
+ int reg = (word & 0x03e00000) >> 21;
+ reg_mask |= 1 << reg;
+ temp_saved_regs.regs[reg] = sp + (short)word;
+
+ /* Starting with OSF/1-3.2C, the system libraries are shipped
+ without local symbols, but they still contain procedure
+ descriptors without a symbol reference. GDB is currently
+ unable to find these procedure descriptors and uses
+ heuristic_proc_desc instead.
+ As some low level compiler support routines (__div*, __add*)
+ use a non-standard return address register, we have to
+ add some heuristics to determine the return address register,
+ or stepping over these routines will fail.
+ Usually the return address register is the first register
+ saved on the stack, but assembler optimization might
+ rearrange the register saves.
+ So we recognize only a few registers (t7, t9, ra) within
+ the procedure prologue as valid return address registers.
+ If we encounter a return instruction, we extract the
+ the return address register from it.
+
+ FIXME: Rewriting GDB to access the procedure descriptors,
+ e.g. via the minimal symbol table, might obviate this hack. */
+ if (pcreg == -1
+ && cur_pc < (start_pc + 80)
+ && (reg == T7_REGNUM || reg == T9_REGNUM || reg == RA_REGNUM))
+ pcreg = reg;
+ }
+ else if ((word & 0xffe0ffff) == 0x6be08001) /* ret zero,reg,1 */
+ pcreg = (word >> 16) & 0x1f;
+ else if (word == 0x47de040f) /* bis sp,sp fp */
+ has_frame_reg = 1;
+ }
+ if (pcreg == -1)
+ {
+ /* If we haven't found a valid return address register yet,
+ keep searching in the procedure prologue. */
+ while (cur_pc < (limit_pc + 80) && cur_pc < (start_pc + 80))
+ {
+ char buf[4];
+ unsigned long word;
+
+ if (read_memory_nobpt (cur_pc, buf, 4))
+ break;
+ cur_pc += 4;
+ word = extract_unsigned_integer (buf, 4);
+
+ if ((word & 0xfc1f0000) == 0xb41e0000 /* stq reg,n($sp) */
+ && (word & 0xffff0000) != 0xb7fe0000) /* reg != $zero */
+ {
+ int reg = (word & 0x03e00000) >> 21;
+ if (reg == T7_REGNUM || reg == T9_REGNUM || reg == RA_REGNUM)
+ {
+ pcreg = reg;
+ break;
+ }
+ }
+ else if ((word & 0xffe0ffff) == 0x6be08001) /* ret zero,reg,1 */
+ {
+ pcreg = (word >> 16) & 0x1f;
+ break;
+ }
+ }
+ }
+
+ if (has_frame_reg)
+ PROC_FRAME_REG(&temp_proc_desc) = GCC_FP_REGNUM;
+ else
+ PROC_FRAME_REG(&temp_proc_desc) = SP_REGNUM;
+ PROC_FRAME_OFFSET(&temp_proc_desc) = frame_size;
+ PROC_REG_MASK(&temp_proc_desc) = reg_mask;
+ PROC_PC_REG(&temp_proc_desc) = (pcreg == -1) ? RA_REGNUM : pcreg;
+ PROC_LOCALOFF(&temp_proc_desc) = 0; /* XXX - bogus */
+ return &temp_proc_desc;
+}
+
+/* This returns the PC of the first inst after the prologue. If we can't
+ find the prologue, then return 0. */
+
+static CORE_ADDR
+after_prologue (pc, proc_desc)
+ CORE_ADDR pc;
+ alpha_extra_func_info_t proc_desc;
+{
+ struct symtab_and_line sal;
+ CORE_ADDR func_addr, func_end;
+
+ if (!proc_desc)
+ proc_desc = find_proc_desc (pc, NULL);
+
+ if (proc_desc)
+ {
+ if (PROC_DESC_IS_DYN_SIGTRAMP (proc_desc))
+ return PROC_LOW_ADDR (proc_desc); /* "prologue" is in kernel */
+
+ /* If function is frameless, then we need to do it the hard way. I
+ strongly suspect that frameless always means prologueless... */
+ if (PROC_FRAME_REG (proc_desc) == SP_REGNUM
+ && PROC_FRAME_OFFSET (proc_desc) == 0)
+ return 0;
+ }
+
+ if (!find_pc_partial_function (pc, NULL, &func_addr, &func_end))
+ return 0; /* Unknown */
+
+ sal = find_pc_line (func_addr, 0);
+
+ if (sal.end < func_end)
+ return sal.end;
+
+ /* The line after the prologue is after the end of the function. In this
+ case, tell the caller to find the prologue the hard way. */
+
+ return 0;
+}
+
+/* Return non-zero if we *might* be in a function prologue. Return zero if we
+ are definitively *not* in a function prologue. */
+
+static int
+alpha_in_prologue (pc, proc_desc)
+ CORE_ADDR pc;
+ alpha_extra_func_info_t proc_desc;
+{
+ CORE_ADDR after_prologue_pc;
+
+ after_prologue_pc = after_prologue (pc, proc_desc);
+
+ if (after_prologue_pc == 0
+ || pc < after_prologue_pc)
+ return 1;
+ else
+ return 0;
+}
+
+static alpha_extra_func_info_t
+find_proc_desc (pc, next_frame)
+ CORE_ADDR pc;
+ struct frame_info *next_frame;
+{
+ alpha_extra_func_info_t proc_desc;
+ struct block *b;
+ struct symbol *sym;
+ CORE_ADDR startaddr;
+
+ /* Try to get the proc_desc from the linked call dummy proc_descs
+ if the pc is in the call dummy.
+ This is hairy. In the case of nested dummy calls we have to find the
+ right proc_desc, but we might not yet know the frame for the dummy
+ as it will be contained in the proc_desc we are searching for.
+ So we have to find the proc_desc whose frame is closest to the current
+ stack pointer. */
+
+ if (PC_IN_CALL_DUMMY (pc, 0, 0))
+ {
+ struct linked_proc_info *link;
+ CORE_ADDR sp = read_next_frame_reg (next_frame, SP_REGNUM);
+ alpha_extra_func_info_t found_proc_desc = NULL;
+ long min_distance = LONG_MAX;
+
+ for (link = linked_proc_desc_table; link; link = link->next)
+ {
+ long distance = (CORE_ADDR) PROC_DUMMY_FRAME (&link->info) - sp;
+ if (distance > 0 && distance < min_distance)
+ {
+ min_distance = distance;
+ found_proc_desc = &link->info;
+ }
+ }
+ if (found_proc_desc != NULL)
+ return found_proc_desc;
+ }
+
+ b = block_for_pc(pc);
+
+ find_pc_partial_function (pc, NULL, &startaddr, NULL);
+ if (b == NULL)
+ sym = NULL;
+ else
+ {
+ if (startaddr > BLOCK_START (b))
+ /* This is the "pathological" case referred to in a comment in
+ print_frame_info. It might be better to move this check into
+ symbol reading. */
+ sym = NULL;
+ else
+ sym = lookup_symbol (MIPS_EFI_SYMBOL_NAME, b, LABEL_NAMESPACE,
+ 0, NULL);
+ }
+
+ /* If we never found a PDR for this function in symbol reading, then
+ examine prologues to find the information. */
+ if (sym && ((mips_extra_func_info_t) SYMBOL_VALUE (sym))->pdr.framereg == -1)
+ sym = NULL;
+
+ if (sym)
+ {
+ /* IF this is the topmost frame AND
+ * (this proc does not have debugging information OR
+ * the PC is in the procedure prologue)
+ * THEN create a "heuristic" proc_desc (by analyzing
+ * the actual code) to replace the "official" proc_desc.
+ */
+ proc_desc = (alpha_extra_func_info_t)SYMBOL_VALUE(sym);
+ if (next_frame == NULL)
+ {
+ if (PROC_DESC_IS_DUMMY (proc_desc) || alpha_in_prologue (pc, proc_desc))
+ {
+ alpha_extra_func_info_t found_heuristic =
+ heuristic_proc_desc (PROC_LOW_ADDR (proc_desc),
+ pc, next_frame);
+ if (found_heuristic)
+ {
+ PROC_LOCALOFF (found_heuristic) =
+ PROC_LOCALOFF (proc_desc);
+ PROC_PC_REG (found_heuristic) = PROC_PC_REG (proc_desc);
+ proc_desc = found_heuristic;
+ }
+ }
+ }
+ }
+ else
+ {
+ long offset;
+
+ /* Is linked_proc_desc_table really necessary? It only seems to be used
+ by procedure call dummys. However, the procedures being called ought
+ to have their own proc_descs, and even if they don't,
+ heuristic_proc_desc knows how to create them! */
+
+ register struct linked_proc_info *link;
+ for (link = linked_proc_desc_table; link; link = link->next)
+ if (PROC_LOW_ADDR(&link->info) <= pc
+ && PROC_HIGH_ADDR(&link->info) > pc)
+ return &link->info;
+
+ /* If PC is inside a dynamically generated sigtramp handler,
+ create and push a procedure descriptor for that code: */
+ offset = DYNAMIC_SIGTRAMP_OFFSET (pc);
+ if (offset >= 0)
+ return push_sigtramp_desc (pc - offset);
+
+ /* If heuristic_fence_post is non-zero, determine the procedure
+ start address by examining the instructions.
+ This allows us to find the start address of static functions which
+ have no symbolic information, as startaddr would have been set to
+ the preceding global function start address by the
+ find_pc_partial_function call above. */
+ if (startaddr == 0 || heuristic_fence_post != 0)
+ startaddr = heuristic_proc_start (pc);
+
+ proc_desc =
+ heuristic_proc_desc (startaddr, pc, next_frame);
+ }
+ return proc_desc;
+}
+
+alpha_extra_func_info_t cached_proc_desc;
+
+CORE_ADDR
+alpha_frame_chain(frame)
+ struct frame_info *frame;
+{
+ alpha_extra_func_info_t proc_desc;
+ CORE_ADDR saved_pc = FRAME_SAVED_PC(frame);
+
+ if (saved_pc == 0 || inside_entry_file (saved_pc))
+ return 0;
+
+ proc_desc = find_proc_desc(saved_pc, frame);
+ if (!proc_desc)
+ return 0;
+
+ cached_proc_desc = proc_desc;
+
+ /* Fetch the frame pointer for a dummy frame from the procedure
+ descriptor. */
+ if (PROC_DESC_IS_DUMMY(proc_desc))
+ return (CORE_ADDR) PROC_DUMMY_FRAME(proc_desc);
+
+ /* If no frame pointer and frame size is zero, we must be at end
+ of stack (or otherwise hosed). If we don't check frame size,
+ we loop forever if we see a zero size frame. */
+ if (PROC_FRAME_REG (proc_desc) == SP_REGNUM
+ && PROC_FRAME_OFFSET (proc_desc) == 0
+ /* The previous frame from a sigtramp frame might be frameless
+ and have frame size zero. */
+ && !frame->signal_handler_caller)
+ return FRAME_PAST_SIGTRAMP_FRAME (frame, saved_pc);
+ else
+ return read_next_frame_reg(frame, PROC_FRAME_REG(proc_desc))
+ + PROC_FRAME_OFFSET(proc_desc);
+}
+
+void
+init_extra_frame_info (frame)
+ struct frame_info *frame;
+{
+ /* Use proc_desc calculated in frame_chain */
+ alpha_extra_func_info_t proc_desc =
+ frame->next ? cached_proc_desc : find_proc_desc(frame->pc, frame->next);
+
+ frame->saved_regs = NULL;
+ frame->localoff = 0;
+ frame->pc_reg = RA_REGNUM;
+ frame->proc_desc = proc_desc == &temp_proc_desc ? 0 : proc_desc;
+ if (proc_desc)
+ {
+ /* Get the locals offset and the saved pc register from the
+ procedure descriptor, they are valid even if we are in the
+ middle of the prologue. */
+ frame->localoff = PROC_LOCALOFF(proc_desc);
+ frame->pc_reg = PROC_PC_REG(proc_desc);
+
+ /* Fixup frame-pointer - only needed for top frame */
+
+ /* Fetch the frame pointer for a dummy frame from the procedure
+ descriptor. */
+ if (PROC_DESC_IS_DUMMY(proc_desc))
+ frame->frame = (CORE_ADDR) PROC_DUMMY_FRAME(proc_desc);
+
+ /* This may not be quite right, if proc has a real frame register.
+ Get the value of the frame relative sp, procedure might have been
+ interrupted by a signal at it's very start. */
+ else if (frame->pc == PROC_LOW_ADDR (proc_desc)
+ && !PROC_DESC_IS_DYN_SIGTRAMP (proc_desc))
+ frame->frame = read_next_frame_reg (frame->next, SP_REGNUM);
+ else
+ frame->frame = read_next_frame_reg (frame->next, PROC_FRAME_REG (proc_desc))
+ + PROC_FRAME_OFFSET (proc_desc);
+
+ if (proc_desc == &temp_proc_desc)
+ {
+ char *name;
+
+ /* Do not set the saved registers for a sigtramp frame,
+ alpha_find_saved_registers will do that for us.
+ We can't use frame->signal_handler_caller, it is not yet set. */
+ find_pc_partial_function (frame->pc, &name,
+ (CORE_ADDR *)NULL,(CORE_ADDR *)NULL);
+ if (!IN_SIGTRAMP (frame->pc, name))
+ {
+ frame->saved_regs = (CORE_ADDR*)
+ frame_obstack_alloc (SIZEOF_FRAME_SAVED_REGS);
+ memcpy (frame->saved_regs, temp_saved_regs.regs, SIZEOF_FRAME_SAVED_REGS);
+ frame->saved_regs[PC_REGNUM]
+ = frame->saved_regs[RA_REGNUM];
+ }
+ }
+ }
+}
+
+/* ALPHA stack frames are almost impenetrable. When execution stops,
+ we basically have to look at symbol information for the function
+ that we stopped in, which tells us *which* register (if any) is
+ the base of the frame pointer, and what offset from that register
+ the frame itself is at.
+
+ This presents a problem when trying to examine a stack in memory
+ (that isn't executing at the moment), using the "frame" command. We
+ don't have a PC, nor do we have any registers except SP.
+
+ This routine takes two arguments, SP and PC, and tries to make the
+ cached frames look as if these two arguments defined a frame on the
+ cache. This allows the rest of info frame to extract the important
+ arguments without difficulty. */
+
+struct frame_info *
+setup_arbitrary_frame (argc, argv)
+ int argc;
+ CORE_ADDR *argv;
+{
+ if (argc != 2)
+ error ("ALPHA frame specifications require two arguments: sp and pc");
+
+ return create_new_frame (argv[0], argv[1]);
+}
+
+/* The alpha passes the first six arguments in the registers, the rest on
+ the stack. The register arguments are eventually transferred to the
+ argument transfer area immediately below the stack by the called function
+ anyway. So we `push' at least six arguments on the stack, `reload' the
+ argument registers and then adjust the stack pointer to point past the
+ sixth argument. This algorithm simplifies the passing of a large struct
+ which extends from the registers to the stack.
+ If the called function is returning a structure, the address of the
+ structure to be returned is passed as a hidden first argument. */
+
+CORE_ADDR
+alpha_push_arguments (nargs, args, sp, struct_return, struct_addr)
+ int nargs;
+ value_ptr *args;
+ CORE_ADDR sp;
+ int struct_return;
+ CORE_ADDR struct_addr;
+{
+ register i;
+ int accumulate_size = struct_return ? 8 : 0;
+ int arg_regs_size = ALPHA_NUM_ARG_REGS * 8;
+ struct alpha_arg { char *contents; int len; int offset; };
+ struct alpha_arg *alpha_args =
+ (struct alpha_arg*)alloca (nargs * sizeof (struct alpha_arg));
+ register struct alpha_arg *m_arg;
+ char raw_buffer[sizeof (CORE_ADDR)];
+ int required_arg_regs;
+
+ for (i = 0, m_arg = alpha_args; i < nargs; i++, m_arg++)
+ {
+ value_ptr arg = args[i];
+ struct type *arg_type = check_typedef (VALUE_TYPE (arg));
+ /* Cast argument to long if necessary as the compiler does it too. */
+ switch (TYPE_CODE (arg_type))
+ {
+ case TYPE_CODE_INT:
+ case TYPE_CODE_BOOL:
+ case TYPE_CODE_CHAR:
+ case TYPE_CODE_RANGE:
+ case TYPE_CODE_ENUM:
+ if (TYPE_LENGTH (arg_type) < TYPE_LENGTH (builtin_type_long))
+ {
+ arg_type = builtin_type_long;
+ arg = value_cast (arg_type, arg);
+ }
+ break;
+ default:
+ break;
+ }
+ m_arg->len = TYPE_LENGTH (arg_type);
+ m_arg->offset = accumulate_size;
+ accumulate_size = (accumulate_size + m_arg->len + 7) & ~7;
+ m_arg->contents = VALUE_CONTENTS(arg);
+ }
+
+ /* Determine required argument register loads, loading an argument register
+ is expensive as it uses three ptrace calls. */
+ required_arg_regs = accumulate_size / 8;
+ if (required_arg_regs > ALPHA_NUM_ARG_REGS)
+ required_arg_regs = ALPHA_NUM_ARG_REGS;
+
+ /* Make room for the arguments on the stack. */
+ if (accumulate_size < arg_regs_size)
+ accumulate_size = arg_regs_size;
+ sp -= accumulate_size;
+
+ /* Keep sp aligned to a multiple of 16 as the compiler does it too. */
+ sp &= ~15;
+
+ /* `Push' arguments on the stack. */
+ for (i = nargs; m_arg--, --i >= 0; )
+ write_memory(sp + m_arg->offset, m_arg->contents, m_arg->len);
+ if (struct_return)
+ {
+ store_address (raw_buffer, sizeof (CORE_ADDR), struct_addr);
+ write_memory (sp, raw_buffer, sizeof (CORE_ADDR));
+ }
+
+ /* Load the argument registers. */
+ for (i = 0; i < required_arg_regs; i++)
+ {
+ LONGEST val;
+
+ val = read_memory_integer (sp + i * 8, 8);
+ write_register (A0_REGNUM + i, val);
+ write_register (FPA0_REGNUM + i, val);
+ }
+
+ return sp + arg_regs_size;
+}
+
+void
+alpha_push_dummy_frame()
+{
+ int ireg;
+ struct linked_proc_info *link;
+ alpha_extra_func_info_t proc_desc;
+ CORE_ADDR sp = read_register (SP_REGNUM);
+ CORE_ADDR save_address;
+ char raw_buffer[MAX_REGISTER_RAW_SIZE];
+ unsigned long mask;
+
+ link = (struct linked_proc_info *) xmalloc(sizeof (struct linked_proc_info));
+ link->next = linked_proc_desc_table;
+ linked_proc_desc_table = link;
+
+ proc_desc = &link->info;
+
+ /*
+ * The registers we must save are all those not preserved across
+ * procedure calls.
+ * In addition, we must save the PC and RA.
+ *
+ * Dummy frame layout:
+ * (high memory)
+ * Saved PC
+ * Saved F30
+ * ...
+ * Saved F0
+ * Saved R29
+ * ...
+ * Saved R0
+ * Saved R26 (RA)
+ * Parameter build area
+ * (low memory)
+ */
+
+/* MASK(i,j) == (1<<i) + (1<<(i+1)) + ... + (1<<j)). Assume i<=j<31. */
+#define MASK(i,j) ((((LONGEST)1 << ((j)+1)) - 1) ^ (((LONGEST)1 << (i)) - 1))
+#define GEN_REG_SAVE_MASK (MASK(0,8) | MASK(16,29))
+#define GEN_REG_SAVE_COUNT 24
+#define FLOAT_REG_SAVE_MASK (MASK(0,1) | MASK(10,30))
+#define FLOAT_REG_SAVE_COUNT 23
+ /* The special register is the PC as we have no bit for it in the save masks.
+ alpha_frame_saved_pc knows where the pc is saved in a dummy frame. */
+#define SPECIAL_REG_SAVE_COUNT 1
+
+ PROC_REG_MASK(proc_desc) = GEN_REG_SAVE_MASK;
+ PROC_FREG_MASK(proc_desc) = FLOAT_REG_SAVE_MASK;
+ /* PROC_REG_OFFSET is the offset from the dummy frame to the saved RA,
+ but keep SP aligned to a multiple of 16. */
+ PROC_REG_OFFSET(proc_desc) =
+ - ((8 * (SPECIAL_REG_SAVE_COUNT
+ + GEN_REG_SAVE_COUNT
+ + FLOAT_REG_SAVE_COUNT)
+ + 15) & ~15);
+ PROC_FREG_OFFSET(proc_desc) =
+ PROC_REG_OFFSET(proc_desc) + 8 * GEN_REG_SAVE_COUNT;
+
+ /* Save general registers.
+ The return address register is the first saved register, all other
+ registers follow in ascending order.
+ The PC is saved immediately below the SP. */
+ save_address = sp + PROC_REG_OFFSET(proc_desc);
+ store_address (raw_buffer, 8, read_register (RA_REGNUM));
+ write_memory (save_address, raw_buffer, 8);
+ save_address += 8;
+ mask = PROC_REG_MASK(proc_desc) & 0xffffffffL;
+ for (ireg = 0; mask; ireg++, mask >>= 1)
+ if (mask & 1)
+ {
+ if (ireg == RA_REGNUM)
+ continue;
+ store_address (raw_buffer, 8, read_register (ireg));
+ write_memory (save_address, raw_buffer, 8);
+ save_address += 8;
+ }
+
+ store_address (raw_buffer, 8, read_register (PC_REGNUM));
+ write_memory (sp - 8, raw_buffer, 8);
+
+ /* Save floating point registers. */
+ save_address = sp + PROC_FREG_OFFSET(proc_desc);
+ mask = PROC_FREG_MASK(proc_desc) & 0xffffffffL;
+ for (ireg = 0; mask; ireg++, mask >>= 1)
+ if (mask & 1)
+ {
+ store_address (raw_buffer, 8, read_register (ireg + FP0_REGNUM));
+ write_memory (save_address, raw_buffer, 8);
+ save_address += 8;
+ }
+
+ /* Set and save the frame address for the dummy.
+ This is tricky. The only registers that are suitable for a frame save
+ are those that are preserved across procedure calls (s0-s6). But if
+ a read system call is interrupted and then a dummy call is made
+ (see testsuite/gdb.t17/interrupt.exp) the dummy call hangs till the read
+ is satisfied. Then it returns with the s0-s6 registers set to the values
+ on entry to the read system call and our dummy frame pointer would be
+ destroyed. So we save the dummy frame in the proc_desc and handle the
+ retrieval of the frame pointer of a dummy specifically. The frame register
+ is set to the virtual frame (pseudo) register, it's value will always
+ be read as zero and will help us to catch any errors in the dummy frame
+ retrieval code. */
+ PROC_DUMMY_FRAME(proc_desc) = sp;
+ PROC_FRAME_REG(proc_desc) = FP_REGNUM;
+ PROC_FRAME_OFFSET(proc_desc) = 0;
+ sp += PROC_REG_OFFSET(proc_desc);
+ write_register (SP_REGNUM, sp);
+
+ PROC_LOW_ADDR(proc_desc) = CALL_DUMMY_ADDRESS ();
+ PROC_HIGH_ADDR(proc_desc) = PROC_LOW_ADDR(proc_desc) + 4;
+
+ SET_PROC_DESC_IS_DUMMY(proc_desc);
+ PROC_PC_REG(proc_desc) = RA_REGNUM;
+}
+
+void
+alpha_pop_frame()
+{
+ register int regnum;
+ struct frame_info *frame = get_current_frame ();
+ CORE_ADDR new_sp = frame->frame;
+
+ alpha_extra_func_info_t proc_desc = frame->proc_desc;
+
+ write_register (PC_REGNUM, FRAME_SAVED_PC(frame));
+ if (frame->saved_regs == NULL)
+ alpha_find_saved_regs (frame);
+ if (proc_desc)
+ {
+ for (regnum = 32; --regnum >= 0; )
+ if (PROC_REG_MASK(proc_desc) & (1 << regnum))
+ write_register (regnum,
+ read_memory_integer (frame->saved_regs[regnum],
+ 8));
+ for (regnum = 32; --regnum >= 0; )
+ if (PROC_FREG_MASK(proc_desc) & (1 << regnum))
+ write_register (regnum + FP0_REGNUM,
+ read_memory_integer (frame->saved_regs[regnum + FP0_REGNUM], 8));
+ }
+ write_register (SP_REGNUM, new_sp);
+ flush_cached_frames ();
+
+ if (proc_desc && (PROC_DESC_IS_DUMMY(proc_desc)
+ || PROC_DESC_IS_DYN_SIGTRAMP (proc_desc)))
+ {
+ struct linked_proc_info *pi_ptr, *prev_ptr;
+
+ for (pi_ptr = linked_proc_desc_table, prev_ptr = NULL;
+ pi_ptr != NULL;
+ prev_ptr = pi_ptr, pi_ptr = pi_ptr->next)
+ {
+ if (&pi_ptr->info == proc_desc)
+ break;
+ }
+
+ if (pi_ptr == NULL)
+ error ("Can't locate dummy extra frame info\n");
+
+ if (prev_ptr != NULL)
+ prev_ptr->next = pi_ptr->next;
+ else
+ linked_proc_desc_table = pi_ptr->next;
+
+ free (pi_ptr);
+ }
+}
+
+/* To skip prologues, I use this predicate. Returns either PC itself
+ if the code at PC does not look like a function prologue; otherwise
+ returns an address that (if we're lucky) follows the prologue. If
+ LENIENT, then we must skip everything which is involved in setting
+ up the frame (it's OK to skip more, just so long as we don't skip
+ anything which might clobber the registers which are being saved.
+ Currently we must not skip more on the alpha, but we might the lenient
+ stuff some day. */
+
+CORE_ADDR
+alpha_skip_prologue (pc, lenient)
+ CORE_ADDR pc;
+ int lenient;
+{
+ unsigned long inst;
+ int offset;
+ CORE_ADDR post_prologue_pc;
+ char buf[4];
+
+#ifdef GDB_TARGET_HAS_SHARED_LIBS
+ /* Silently return the unaltered pc upon memory errors.
+ This could happen on OSF/1 if decode_line_1 tries to skip the
+ prologue for quickstarted shared library functions when the
+ shared library is not yet mapped in.
+ Reading target memory is slow over serial lines, so we perform
+ this check only if the target has shared libraries. */
+ if (target_read_memory (pc, buf, 4))
+ return pc;
+#endif
+
+ /* See if we can determine the end of the prologue via the symbol table.
+ If so, then return either PC, or the PC after the prologue, whichever
+ is greater. */
+
+ post_prologue_pc = after_prologue (pc, NULL);
+
+ if (post_prologue_pc != 0)
+ return max (pc, post_prologue_pc);
+
+ /* Can't determine prologue from the symbol table, need to examine
+ instructions. */
+
+ /* Skip the typical prologue instructions. These are the stack adjustment
+ instruction and the instructions that save registers on the stack
+ or in the gcc frame. */
+ for (offset = 0; offset < 100; offset += 4)
+ {
+ int status;
+
+ status = read_memory_nobpt (pc + offset, buf, 4);
+ if (status)
+ memory_error (status, pc + offset);
+ inst = extract_unsigned_integer (buf, 4);
+
+ /* The alpha has no delay slots. But let's keep the lenient stuff,
+ we might need it for something else in the future. */
+ if (lenient && 0)
+ continue;
+
+ if ((inst & 0xffff0000) == 0x27bb0000) /* ldah $gp,n($t12) */
+ continue;
+ if ((inst & 0xffff0000) == 0x23bd0000) /* lda $gp,n($gp) */
+ continue;
+ if ((inst & 0xffff0000) == 0x23de0000) /* lda $sp,n($sp) */
+ continue;
+ else if ((inst & 0xfc1f0000) == 0xb41e0000
+ && (inst & 0xffff0000) != 0xb7fe0000)
+ continue; /* stq reg,n($sp) */
+ /* reg != $zero */
+ else if ((inst & 0xfc1f0000) == 0x9c1e0000
+ && (inst & 0xffff0000) != 0x9ffe0000)
+ continue; /* stt reg,n($sp) */
+ /* reg != $zero */
+ else if (inst == 0x47de040f) /* bis sp,sp,fp */
+ continue;
+ else
+ break;
+ }
+ return pc + offset;
+}
+
+#if 0
+/* Is address PC in the prologue (loosely defined) for function at
+ STARTADDR? */
+
+static int
+alpha_in_lenient_prologue (startaddr, pc)
+ CORE_ADDR startaddr;
+ CORE_ADDR pc;
+{
+ CORE_ADDR end_prologue = alpha_skip_prologue (startaddr, 1);
+ return pc >= startaddr && pc < end_prologue;
+}
+#endif
+
+/* The alpha needs a conversion between register and memory format if
+ the register is a floating point register and
+ memory format is float, as the register format must be double
+ or
+ memory format is an integer with 4 bytes or less, as the representation
+ of integers in floating point registers is different. */
+void
+alpha_register_convert_to_virtual (regnum, valtype, raw_buffer, virtual_buffer)
+ int regnum;
+ struct type *valtype;
+ char *raw_buffer;
+ char *virtual_buffer;
+{
+ if (TYPE_LENGTH (valtype) >= REGISTER_RAW_SIZE (regnum))
+ {
+ memcpy (virtual_buffer, raw_buffer, REGISTER_VIRTUAL_SIZE (regnum));
+ return;
+ }
+
+ if (TYPE_CODE (valtype) == TYPE_CODE_FLT)
+ {
+ double d = extract_floating (raw_buffer, REGISTER_RAW_SIZE (regnum));
+ store_floating (virtual_buffer, TYPE_LENGTH (valtype), d);
+ }
+ else if (TYPE_CODE (valtype) == TYPE_CODE_INT && TYPE_LENGTH (valtype) <= 4)
+ {
+ ULONGEST l;
+ l = extract_unsigned_integer (raw_buffer, REGISTER_RAW_SIZE (regnum));
+ l = ((l >> 32) & 0xc0000000) | ((l >> 29) & 0x3fffffff);
+ store_unsigned_integer (virtual_buffer, TYPE_LENGTH (valtype), l);
+ }
+ else
+ error ("Cannot retrieve value from floating point register");
+}
+
+void
+alpha_register_convert_to_raw (valtype, regnum, virtual_buffer, raw_buffer)
+ struct type *valtype;
+ int regnum;
+ char *virtual_buffer;
+ char *raw_buffer;
+{
+ if (TYPE_LENGTH (valtype) >= REGISTER_RAW_SIZE (regnum))
+ {
+ memcpy (raw_buffer, virtual_buffer, REGISTER_RAW_SIZE (regnum));
+ return;
+ }
+
+ if (TYPE_CODE (valtype) == TYPE_CODE_FLT)
+ {
+ double d = extract_floating (virtual_buffer, TYPE_LENGTH (valtype));
+ store_floating (raw_buffer, REGISTER_RAW_SIZE (regnum), d);
+ }
+ else if (TYPE_CODE (valtype) == TYPE_CODE_INT && TYPE_LENGTH (valtype) <= 4)
+ {
+ ULONGEST l;
+ if (TYPE_UNSIGNED (valtype))
+ l = extract_unsigned_integer (virtual_buffer, TYPE_LENGTH (valtype));
+ else
+ l = extract_signed_integer (virtual_buffer, TYPE_LENGTH (valtype));
+ l = ((l & 0xc0000000) << 32) | ((l & 0x3fffffff) << 29);
+ store_unsigned_integer (raw_buffer, REGISTER_RAW_SIZE (regnum), l);
+ }
+ else
+ error ("Cannot store value in floating point register");
+}
+
+/* Given a return value in `regbuf' with a type `valtype',
+ extract and copy its value into `valbuf'. */
+
+void
+alpha_extract_return_value (valtype, regbuf, valbuf)
+ struct type *valtype;
+ char regbuf[REGISTER_BYTES];
+ char *valbuf;
+{
+ if (TYPE_CODE (valtype) == TYPE_CODE_FLT)
+ alpha_register_convert_to_virtual (FP0_REGNUM, valtype,
+ regbuf + REGISTER_BYTE (FP0_REGNUM),
+ valbuf);
+ else
+ memcpy (valbuf, regbuf + REGISTER_BYTE (V0_REGNUM), TYPE_LENGTH (valtype));
+}
+
+/* Given a return value in `regbuf' with a type `valtype',
+ write its value into the appropriate register. */
+
+void
+alpha_store_return_value (valtype, valbuf)
+ struct type *valtype;
+ char *valbuf;
+{
+ char raw_buffer[MAX_REGISTER_RAW_SIZE];
+ int regnum = V0_REGNUM;
+ int length = TYPE_LENGTH (valtype);
+
+ if (TYPE_CODE (valtype) == TYPE_CODE_FLT)
+ {
+ regnum = FP0_REGNUM;
+ length = REGISTER_RAW_SIZE (regnum);
+ alpha_register_convert_to_raw (valtype, regnum, valbuf, raw_buffer);
+ }
+ else
+ memcpy (raw_buffer, valbuf, length);
+
+ write_register_bytes (REGISTER_BYTE (regnum), raw_buffer, length);
+}
+
+/* Just like reinit_frame_cache, but with the right arguments to be
+ callable as an sfunc. */
+
+static void
+reinit_frame_cache_sfunc (args, from_tty, c)
+ char *args;
+ int from_tty;
+ struct cmd_list_element *c;
+{
+ reinit_frame_cache ();
+}
+
+/* This is the definition of CALL_DUMMY_ADDRESS. It's a heuristic that is used
+ to find a convenient place in the text segment to stick a breakpoint to
+ detect the completion of a target function call (ala call_function_by_hand).
+ */
+
+CORE_ADDR
+alpha_call_dummy_address ()
+{
+ CORE_ADDR entry;
+ struct minimal_symbol *sym;
+
+ entry = entry_point_address ();
+
+ if (entry != 0)
+ return entry;
+
+ sym = lookup_minimal_symbol ("_Prelude", NULL, symfile_objfile);
+
+ if (!sym || MSYMBOL_TYPE (sym) != mst_text)
+ return 0;
+ else
+ return SYMBOL_VALUE_ADDRESS (sym) + 4;
+}
+
+void
+_initialize_alpha_tdep ()
+{
+ struct cmd_list_element *c;
+
+ tm_print_insn = print_insn_alpha;
+
+ /* Let the user set the fence post for heuristic_proc_start. */
+
+ /* We really would like to have both "0" and "unlimited" work, but
+ command.c doesn't deal with that. So make it a var_zinteger
+ because the user can always use "999999" or some such for unlimited. */
+ c = add_set_cmd ("heuristic-fence-post", class_support, var_zinteger,
+ (char *) &heuristic_fence_post,
+ "\
+Set the distance searched for the start of a function.\n\
+If you are debugging a stripped executable, GDB needs to search through the\n\
+program for the start of a function. This command sets the distance of the\n\
+search. The only need to set it is when debugging a stripped executable.",
+ &setlist);
+ /* We need to throw away the frame cache when we set this, since it
+ might change our ability to get backtraces. */
+ c->function.sfunc = reinit_frame_cache_sfunc;
+ add_show_from_set (c, &showlist);
+}
diff --git a/gdb/altos-xdep.c b/gdb/altos-xdep.c
new file mode 100644
index 00000000000..5727332cf6f
--- /dev/null
+++ b/gdb/altos-xdep.c
@@ -0,0 +1,164 @@
+/* Low level interface to ptrace, for GDB when running under m68k SVR2 Unix
+ on Altos 3068. Report bugs to Jyrki Kuoppala <jkp@cs.hut.fi>
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "frame.h"
+#include "inferior.h"
+
+#ifdef USG
+#include <sys/types.h>
+#endif
+
+#include <sys/param.h>
+#include <sys/dir.h>
+#include <signal.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#ifdef USG
+#include <sys/page.h>
+#ifdef ALTOS
+#include <sys/net.h>
+#include <errno.h>
+#endif
+#endif
+
+#include "gdbcore.h"
+#include <sys/user.h> /* After a.out.h */
+#include <sys/file.h>
+#include "gdb_stat.h"
+
+
+/* Work with core dump and executable files, for GDB.
+ This code would be in corefile.c if it weren't machine-dependent. */
+
+void
+core_file_command (filename, from_tty)
+ char *filename;
+ int from_tty;
+{
+ int val;
+ extern char registers[];
+
+ /* Discard all vestiges of any previous core file
+ and mark data and stack spaces as empty. */
+
+ if (corefile)
+ free (corefile);
+ corefile = 0;
+
+ if (corechan >= 0)
+ close (corechan);
+ corechan = -1;
+
+ data_start = 0;
+ data_end = 0;
+ stack_start = STACK_END_ADDR;
+ stack_end = STACK_END_ADDR;
+
+ /* Now, if a new core file was specified, open it and digest it. */
+
+ if (filename)
+ {
+ filename = tilde_expand (filename);
+ make_cleanup (free, filename);
+
+ if (have_inferior_p ())
+ error ("To look at a core file, you must kill the program with \"kill\".");
+ corechan = open (filename, O_RDONLY, 0);
+ if (corechan < 0)
+ perror_with_name (filename);
+ /* 4.2-style (and perhaps also sysV-style) core dump file. */
+ {
+ struct user u;
+
+ unsigned int reg_offset;
+
+ val = myread (corechan, &u, sizeof u);
+ if (val < 0)
+ perror_with_name ("Not a core file: reading upage");
+ if (val != sizeof u)
+ error ("Not a core file: could only read %d bytes", val);
+ data_start = exec_data_start;
+
+#if !defined (NBPG)
+#define NBPG NBPP
+#endif
+#if !defined (UPAGES)
+#define UPAGES USIZE
+#endif
+
+ data_end = data_start + NBPG * u.u_dsize;
+ stack_start = stack_end - NBPG * u.u_ssize;
+ data_offset = NBPG * UPAGES + exec_data_start % NBPG /* Not sure about this //jkp */;
+ stack_offset = NBPG * (UPAGES + u.u_dsize);
+
+ /* Some machines put an absolute address in here and some put
+ the offset in the upage of the regs. */
+ reg_offset = (int) u.u_state;
+ if (reg_offset > NBPG * UPAGES)
+ reg_offset -= KERNEL_U_ADDR;
+
+ memcpy (&core_aouthdr, &u.u_exdata, sizeof (AOUTHDR));
+ printf_unfiltered ("Core file is from \"%s\".\n", u.u_comm);
+
+ /* I don't know where to find this info.
+ So, for now, mark it as not available. */
+ N_SET_MAGIC (core_aouthdr, 0);
+
+ /* Read the register values out of the core file and store
+ them where `read_register' will find them. */
+
+ {
+ register int regno;
+
+ for (regno = 0; regno < NUM_REGS; regno++)
+ {
+ char buf[MAX_REGISTER_RAW_SIZE];
+
+ val = lseek (corechan, register_addr (regno, reg_offset), 0);
+ if (val < 0
+ || (val = myread (corechan, buf, sizeof buf)) < 0)
+ {
+ char * buffer = (char *) alloca (strlen (REGISTER_NAME (regno))
+ + 30);
+ strcpy (buffer, "Reading register ");
+ strcat (buffer, REGISTER_NAME (regno));
+
+ perror_with_name (buffer);
+ }
+
+ supply_register (regno, buf);
+ }
+ }
+ }
+ if (filename[0] == '/')
+ corefile = savestring (filename, strlen (filename));
+ else
+ {
+ corefile = concat (current_directory, "/", filename, NULL);
+ }
+
+ flush_cached_frames ();
+ select_frame (get_current_frame (), 0);
+ validate_files ();
+ }
+ else if (from_tty)
+ printf_unfiltered ("No core file now.\n");
+}
diff --git a/gdb/annotate.c b/gdb/annotate.c
new file mode 100644
index 00000000000..ec3e4245c9b
--- /dev/null
+++ b/gdb/annotate.c
@@ -0,0 +1,577 @@
+/* Annotation routines for GDB.
+ Copyright 1986, 89, 90, 91, 92, 95, 1998 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "annotate.h"
+#include "value.h"
+#include "target.h"
+#include "gdbtypes.h"
+#include "breakpoint.h"
+
+
+/* Prototypes for local functions. */
+
+static void print_value_flags PARAMS ((struct type *));
+
+static void breakpoint_changed PARAMS ((struct breakpoint *));
+
+void (*annotate_starting_hook) PARAMS ((void));
+void (*annotate_stopped_hook) PARAMS ((void));
+void (*annotate_signalled_hook) PARAMS ((void));
+void (*annotate_exited_hook) PARAMS ((void));
+
+static void
+print_value_flags (t)
+ struct type *t;
+{
+ if (can_dereference (t))
+ printf_filtered ("*");
+ else
+ printf_filtered ("-");
+}
+
+void
+breakpoints_changed ()
+{
+ if (annotation_level > 1)
+ {
+ target_terminal_ours ();
+ printf_unfiltered ("\n\032\032breakpoints-invalid\n");
+ }
+}
+
+void
+annotate_breakpoint (num)
+ int num;
+{
+ if (annotation_level > 1)
+ printf_filtered ("\n\032\032breakpoint %d\n", num);
+}
+
+void
+annotate_catchpoint (num)
+ int num;
+{
+ if (annotation_level > 1)
+ printf_filtered ("\n\032\032catchpoint %d\n", num);
+}
+
+void
+annotate_watchpoint (num)
+ int num;
+{
+ if (annotation_level > 1)
+ printf_filtered ("\n\032\032watchpoint %d\n", num);
+}
+
+void
+annotate_starting ()
+{
+
+ if (annotate_starting_hook)
+ annotate_starting_hook ();
+ else
+ {
+ if (annotation_level > 1)
+ {
+ printf_filtered ("\n\032\032starting\n");
+ }
+ }
+}
+
+void
+annotate_stopped ()
+{
+ if (annotate_stopped_hook)
+ annotate_stopped_hook ();
+ else
+ {
+ if (annotation_level > 1)
+ printf_filtered ("\n\032\032stopped\n");
+ }
+}
+
+void
+annotate_exited (exitstatus)
+ int exitstatus;
+{
+ if (annotate_exited_hook)
+ annotate_exited_hook ();
+ else
+ {
+ if (annotation_level > 1)
+ printf_filtered ("\n\032\032exited %d\n", exitstatus);
+ }
+}
+
+void
+annotate_signalled ()
+{
+ if (annotate_signalled_hook)
+ annotate_signalled_hook ();
+
+ if (annotation_level > 1)
+ printf_filtered ("\n\032\032signalled\n");
+}
+
+void
+annotate_signal_name ()
+{
+ if (annotation_level > 1)
+ printf_filtered ("\n\032\032signal-name\n");
+}
+
+void
+annotate_signal_name_end ()
+{
+ if (annotation_level > 1)
+ printf_filtered ("\n\032\032signal-name-end\n");
+}
+
+void
+annotate_signal_string ()
+{
+ if (annotation_level > 1)
+ printf_filtered ("\n\032\032signal-string\n");
+}
+
+void
+annotate_signal_string_end ()
+{
+ if (annotation_level > 1)
+ printf_filtered ("\n\032\032signal-string-end\n");
+}
+
+void
+annotate_signal ()
+{
+ if (annotation_level > 1)
+ printf_filtered ("\n\032\032signal\n");
+}
+
+void
+annotate_breakpoints_headers ()
+{
+ if (annotation_level > 1)
+ printf_filtered ("\n\032\032breakpoints-headers\n");
+}
+
+void
+annotate_field (num)
+ int num;
+{
+ if (annotation_level > 1)
+ printf_filtered ("\n\032\032field %d\n", num);
+}
+
+void
+annotate_breakpoints_table ()
+{
+ if (annotation_level > 1)
+ printf_filtered ("\n\032\032breakpoints-table\n");
+}
+
+void
+annotate_record ()
+{
+ if (annotation_level > 1)
+ printf_filtered ("\n\032\032record\n");
+}
+
+void
+annotate_breakpoints_table_end ()
+{
+ if (annotation_level > 1)
+ printf_filtered ("\n\032\032breakpoints-table-end\n");
+}
+
+void
+annotate_frames_invalid ()
+{
+ if (annotation_level > 1)
+ {
+ target_terminal_ours ();
+ printf_unfiltered ("\n\032\032frames-invalid\n");
+ }
+}
+
+void
+annotate_field_begin (type)
+ struct type *type;
+{
+ if (annotation_level > 1)
+ {
+ printf_filtered ("\n\032\032field-begin ");
+ print_value_flags (type);
+ printf_filtered ("\n");
+ }
+}
+
+void
+annotate_field_name_end ()
+{
+ if (annotation_level > 1)
+ printf_filtered ("\n\032\032field-name-end\n");
+}
+
+void
+annotate_field_value ()
+{
+ if (annotation_level > 1)
+ printf_filtered ("\n\032\032field-value\n");
+}
+
+void
+annotate_field_end ()
+{
+ if (annotation_level > 1)
+ printf_filtered ("\n\032\032field-end\n");
+}
+
+void
+annotate_quit ()
+{
+ if (annotation_level > 1)
+ printf_filtered ("\n\032\032quit\n");
+}
+
+void
+annotate_error ()
+{
+ if (annotation_level > 1)
+ printf_filtered ("\n\032\032error\n");
+}
+
+void
+annotate_error_begin ()
+{
+ if (annotation_level > 1)
+ fprintf_filtered (gdb_stderr, "\n\032\032error-begin\n");
+}
+
+void
+annotate_value_history_begin (histindex, type)
+ int histindex;
+ struct type *type;
+{
+ if (annotation_level > 1)
+ {
+ printf_filtered ("\n\032\032value-history-begin %d ", histindex);
+ print_value_flags (type);
+ printf_filtered ("\n");
+ }
+}
+
+void
+annotate_value_begin (type)
+ struct type *type;
+{
+ if (annotation_level > 1)
+ {
+ printf_filtered ("\n\032\032value-begin ");
+ print_value_flags (type);
+ printf_filtered ("\n");
+ }
+}
+
+void
+annotate_value_history_value ()
+{
+ if (annotation_level > 1)
+ printf_filtered ("\n\032\032value-history-value\n");
+}
+
+void
+annotate_value_history_end ()
+{
+ if (annotation_level > 1)
+ printf_filtered ("\n\032\032value-history-end\n");
+}
+
+void
+annotate_value_end ()
+{
+ if (annotation_level > 1)
+ printf_filtered ("\n\032\032value-end\n");
+}
+
+void
+annotate_display_begin ()
+{
+ if (annotation_level > 1)
+ printf_filtered ("\n\032\032display-begin\n");
+}
+
+void
+annotate_display_number_end ()
+{
+ if (annotation_level > 1)
+ printf_filtered ("\n\032\032display-number-end\n");
+}
+
+void
+annotate_display_format ()
+{
+ if (annotation_level > 1)
+ printf_filtered ("\n\032\032display-format\n");
+}
+
+void
+annotate_display_expression ()
+{
+ if (annotation_level > 1)
+ printf_filtered ("\n\032\032display-expression\n");
+}
+
+void
+annotate_display_expression_end ()
+{
+ if (annotation_level > 1)
+ printf_filtered ("\n\032\032display-expression-end\n");
+}
+
+void
+annotate_display_value ()
+{
+ if (annotation_level > 1)
+ printf_filtered ("\n\032\032display-value\n");
+}
+
+void
+annotate_display_end ()
+{
+ if (annotation_level > 1)
+ printf_filtered ("\n\032\032display-end\n");
+}
+
+void
+annotate_arg_begin ()
+{
+ if (annotation_level > 1)
+ printf_filtered ("\n\032\032arg-begin\n");
+}
+
+void
+annotate_arg_name_end ()
+{
+ if (annotation_level > 1)
+ printf_filtered ("\n\032\032arg-name-end\n");
+}
+
+void
+annotate_arg_value (type)
+ struct type *type;
+{
+ if (annotation_level > 1)
+ {
+ printf_filtered ("\n\032\032arg-value ");
+ print_value_flags (type);
+ printf_filtered ("\n");
+ }
+}
+
+void
+annotate_arg_end ()
+{
+ if (annotation_level > 1)
+ printf_filtered ("\n\032\032arg-end\n");
+}
+
+void
+annotate_source (filename, line, character, mid, pc)
+ char *filename;
+ int line;
+ int character;
+ int mid;
+ CORE_ADDR pc;
+{
+ if (annotation_level > 1)
+ printf_filtered ("\n\032\032source ");
+ else
+ printf_filtered ("\032\032");
+
+ printf_filtered ("%s:%d:%d:%s:0x", filename,
+ line, character,
+ mid ? "middle" : "beg");
+ print_address_numeric (pc, 0, gdb_stdout);
+ printf_filtered ("\n");
+}
+
+void
+annotate_frame_begin (level, pc)
+ int level;
+ CORE_ADDR pc;
+{
+ if (annotation_level > 1)
+ {
+ printf_filtered ("\n\032\032frame-begin %d 0x", level);
+ print_address_numeric (pc, 0, gdb_stdout);
+ printf_filtered ("\n");
+ }
+}
+
+void
+annotate_function_call ()
+{
+ if (annotation_level > 1)
+ printf_filtered ("\n\032\032function-call\n");
+}
+
+void
+annotate_signal_handler_caller ()
+{
+ if (annotation_level > 1)
+ printf_filtered ("\n\032\032signal-handler-caller\n");
+}
+
+void
+annotate_frame_address ()
+{
+ if (annotation_level > 1)
+ printf_filtered ("\n\032\032frame-address\n");
+}
+
+void
+annotate_frame_address_end ()
+{
+ if (annotation_level > 1)
+ printf_filtered ("\n\032\032frame-address-end\n");
+}
+
+void
+annotate_frame_function_name ()
+{
+ if (annotation_level > 1)
+ printf_filtered ("\n\032\032frame-function-name\n");
+}
+
+void
+annotate_frame_args ()
+{
+ if (annotation_level > 1)
+ printf_filtered ("\n\032\032frame-args\n");
+}
+
+void
+annotate_frame_source_begin ()
+{
+ if (annotation_level > 1)
+ printf_filtered ("\n\032\032frame-source-begin\n");
+}
+
+void
+annotate_frame_source_file ()
+{
+ if (annotation_level > 1)
+ printf_filtered ("\n\032\032frame-source-file\n");
+}
+
+void
+annotate_frame_source_file_end ()
+{
+ if (annotation_level > 1)
+ printf_filtered ("\n\032\032frame-source-file-end\n");
+}
+
+void
+annotate_frame_source_line ()
+{
+ if (annotation_level > 1)
+ printf_filtered ("\n\032\032frame-source-line\n");
+}
+
+void
+annotate_frame_source_end ()
+{
+ if (annotation_level > 1)
+ printf_filtered ("\n\032\032frame-source-end\n");
+}
+
+void
+annotate_frame_where ()
+{
+ if (annotation_level > 1)
+ printf_filtered ("\n\032\032frame-where\n");
+}
+
+void
+annotate_frame_end ()
+{
+ if (annotation_level > 1)
+ printf_filtered ("\n\032\032frame-end\n");
+}
+
+void
+annotate_array_section_begin (index, elttype)
+ int index;
+ struct type *elttype;
+{
+ if (annotation_level > 1)
+ {
+ printf_filtered ("\n\032\032array-section-begin %d ", index);
+ print_value_flags (elttype);
+ printf_filtered ("\n");
+ }
+}
+
+void
+annotate_elt_rep (repcount)
+ unsigned int repcount;
+{
+ if (annotation_level > 1)
+ printf_filtered ("\n\032\032elt-rep %u\n", repcount);
+}
+
+void
+annotate_elt_rep_end ()
+{
+ if (annotation_level > 1)
+ printf_filtered ("\n\032\032elt-rep-end\n");
+}
+
+void
+annotate_elt ()
+{
+ if (annotation_level > 1)
+ printf_filtered ("\n\032\032elt\n");
+}
+
+void
+annotate_array_section_end ()
+{
+ if (annotation_level > 1)
+ printf_filtered ("\n\032\032array-section-end\n");
+}
+
+static void
+breakpoint_changed (b)
+ struct breakpoint *b;
+{
+ breakpoints_changed ();
+}
+
+void
+_initialize_annotate ()
+{
+ if (annotation_level > 1)
+ {
+ delete_breakpoint_hook = breakpoint_changed;
+ modify_breakpoint_hook = breakpoint_changed;
+ }
+}
diff --git a/gdb/annotate.h b/gdb/annotate.h
new file mode 100644
index 00000000000..59739db68da
--- /dev/null
+++ b/gdb/annotate.h
@@ -0,0 +1,104 @@
+/* Annotation routines for GDB.
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "symtab.h"
+#include "gdbtypes.h"
+
+extern void breakpoints_changed PARAMS ((void));
+
+extern void annotate_breakpoint PARAMS ((int));
+extern void annotate_catchpoint PARAMS ((int));
+extern void annotate_watchpoint PARAMS ((int));
+extern void annotate_starting PARAMS ((void));
+extern void annotate_stopped PARAMS ((void));
+extern void annotate_exited PARAMS ((int));
+extern void annotate_signalled PARAMS ((void));
+extern void annotate_signal_name PARAMS ((void));
+extern void annotate_signal_name_end PARAMS ((void));
+extern void annotate_signal_string PARAMS ((void));
+extern void annotate_signal_string_end PARAMS ((void));
+extern void annotate_signal PARAMS ((void));
+
+extern void annotate_breakpoints_headers PARAMS ((void));
+extern void annotate_field PARAMS ((int));
+extern void annotate_breakpoints_table PARAMS ((void));
+extern void annotate_record PARAMS ((void));
+extern void annotate_breakpoints_table_end PARAMS ((void));
+
+extern void annotate_frames_invalid PARAMS ((void));
+
+#ifdef __STDC__
+struct type;
+#endif
+
+extern void annotate_field_begin PARAMS ((struct type *));
+extern void annotate_field_name_end PARAMS ((void));
+extern void annotate_field_value PARAMS ((void));
+extern void annotate_field_end PARAMS ((void));
+
+extern void annotate_quit PARAMS ((void));
+extern void annotate_error PARAMS ((void));
+extern void annotate_error_begin PARAMS ((void));
+
+extern void annotate_value_history_begin PARAMS ((int, struct type *));
+extern void annotate_value_begin PARAMS ((struct type *));
+extern void annotate_value_history_value PARAMS ((void));
+extern void annotate_value_history_end PARAMS ((void));
+extern void annotate_value_end PARAMS ((void));
+
+extern void annotate_display_begin PARAMS ((void));
+extern void annotate_display_number_end PARAMS ((void));
+extern void annotate_display_format PARAMS ((void));
+extern void annotate_display_expression PARAMS ((void));
+extern void annotate_display_expression_end PARAMS ((void));
+extern void annotate_display_value PARAMS ((void));
+extern void annotate_display_end PARAMS ((void));
+
+extern void annotate_arg_begin PARAMS ((void));
+extern void annotate_arg_name_end PARAMS ((void));
+extern void annotate_arg_value PARAMS ((struct type *));
+extern void annotate_arg_end PARAMS ((void));
+
+extern void annotate_source PARAMS ((char *, int, int, int, CORE_ADDR));
+
+extern void annotate_frame_begin PARAMS ((int, CORE_ADDR));
+extern void annotate_function_call PARAMS ((void));
+extern void annotate_signal_handler_caller PARAMS ((void));
+extern void annotate_frame_address PARAMS ((void));
+extern void annotate_frame_address_end PARAMS ((void));
+extern void annotate_frame_function_name PARAMS ((void));
+extern void annotate_frame_args PARAMS ((void));
+extern void annotate_frame_source_begin PARAMS ((void));
+extern void annotate_frame_source_file PARAMS ((void));
+extern void annotate_frame_source_file_end PARAMS ((void));
+extern void annotate_frame_source_line PARAMS ((void));
+extern void annotate_frame_source_end PARAMS ((void));
+extern void annotate_frame_where PARAMS ((void));
+extern void annotate_frame_end PARAMS ((void));
+
+extern void annotate_array_section_begin PARAMS ((int, struct type *));
+extern void annotate_elt_rep PARAMS ((unsigned int));
+extern void annotate_elt_rep_end PARAMS ((void));
+extern void annotate_elt PARAMS ((void));
+extern void annotate_array_section_end PARAMS ((void));
+
+extern void (*annotate_starting_hook) PARAMS ((void));
+extern void (*annotate_stopped_hook) PARAMS ((void));
+extern void (*annotate_signalled_hook) PARAMS ((void));
+extern void (*annotate_exited_hook) PARAMS ((void));
diff --git a/gdb/arc-tdep.c b/gdb/arc-tdep.c
new file mode 100644
index 00000000000..92957700f9c
--- /dev/null
+++ b/gdb/arc-tdep.c
@@ -0,0 +1,733 @@
+/* ARC target-dependent stuff.
+ Copyright (C) 1995, 1997 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "frame.h"
+#include "inferior.h"
+#include "gdbcore.h"
+#include "target.h"
+#include "floatformat.h"
+#include "symtab.h"
+#include "gdbcmd.h"
+
+/* Current CPU, set with the "set cpu" command. */
+static int arc_bfd_mach_type;
+char *arc_cpu_type;
+char *tmp_arc_cpu_type;
+
+/* Table of cpu names. */
+struct {
+ char *name;
+ int value;
+} arc_cpu_type_table[] = {
+ { "base", bfd_mach_arc_base },
+ { NULL, 0 }
+};
+
+/* Used by simulator. */
+int display_pipeline_p;
+int cpu_timer;
+/* This one must have the same type as used in the emulator.
+ It's currently an enum so this should be ok for now. */
+int debug_pipeline_p;
+
+#define ARC_CALL_SAVED_REG(r) ((r) >= 16 && (r) < 24)
+
+#define OPMASK 0xf8000000
+
+/* Instruction field accessor macros.
+ See the Programmer's Reference Manual. */
+#define X_OP(i) (((i) >> 27) & 0x1f)
+#define X_A(i) (((i) >> 21) & 0x3f)
+#define X_B(i) (((i) >> 15) & 0x3f)
+#define X_C(i) (((i) >> 9) & 0x3f)
+#define X_D(i) ((((i) & 0x1ff) ^ 0x100) - 0x100)
+#define X_L(i) (((((i) >> 5) & 0x3ffffc) ^ 0x200000) - 0x200000)
+#define X_N(i) (((i) >> 5) & 3)
+#define X_Q(i) ((i) & 0x1f)
+
+/* Return non-zero if X is a short immediate data indicator. */
+#define SHIMM_P(x) ((x) == 61 || (x) == 63)
+
+/* Return non-zero if X is a "long" (32 bit) immediate data indicator. */
+#define LIMM_P(x) ((x) == 62)
+
+/* Build a simple instruction. */
+#define BUILD_INSN(op, a, b, c, d) \
+ ((((op) & 31) << 27) \
+ | (((a) & 63) << 21) \
+ | (((b) & 63) << 15) \
+ | (((c) & 63) << 9) \
+ | ((d) & 511))
+
+/* Codestream stuff. */
+static void codestream_read PARAMS ((unsigned int *, int));
+static void codestream_seek PARAMS ((CORE_ADDR));
+static unsigned int codestream_fill PARAMS ((int));
+
+#define CODESTREAM_BUFSIZ 16
+static CORE_ADDR codestream_next_addr;
+static CORE_ADDR codestream_addr;
+static unsigned int codestream_buf[CODESTREAM_BUFSIZ];
+static int codestream_off;
+static int codestream_cnt;
+
+#define codestream_tell() \
+ (codestream_addr + codestream_off * sizeof (codestream_buf[0]))
+#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 int
+codestream_fill (peek_flag)
+ int peek_flag;
+{
+ codestream_addr = codestream_next_addr;
+ codestream_next_addr += CODESTREAM_BUFSIZ * sizeof (codestream_buf[0]);
+ codestream_off = 0;
+ codestream_cnt = CODESTREAM_BUFSIZ;
+ read_memory (codestream_addr, (char *) codestream_buf,
+ CODESTREAM_BUFSIZ * sizeof (codestream_buf[0]));
+ /* FIXME: check return code? */
+
+ /* Handle byte order differences. */
+ if (HOST_BYTE_ORDER != TARGET_BYTE_ORDER)
+ {
+ register unsigned int i, j, n = sizeof (codestream_buf[0]);
+ register char tmp, *p;
+ for (i = 0, p = (char *) codestream_buf; i < CODESTREAM_BUFSIZ;
+ ++i, p += n)
+ for (j = 0; j < n / 2; ++j)
+ tmp = p[j], p[j] = p[n - 1 - j], p[n - 1 - j] = tmp;
+ }
+
+ if (peek_flag)
+ return codestream_peek ();
+ else
+ return codestream_get ();
+}
+
+static void
+codestream_seek (place)
+ CORE_ADDR place;
+{
+ codestream_next_addr = place / CODESTREAM_BUFSIZ;
+ codestream_next_addr *= CODESTREAM_BUFSIZ;
+ codestream_cnt = 0;
+ codestream_fill (1);
+ while (codestream_tell () != place)
+ codestream_get ();
+}
+
+/* This function is currently unused but leave in for now. */
+
+static void
+codestream_read (buf, count)
+ unsigned int *buf;
+ int count;
+{
+ unsigned int *p;
+ int i;
+ p = buf;
+ for (i = 0; i < count; i++)
+ *p++ = codestream_get ();
+}
+
+/* Set up prologue scanning and return the first insn. */
+
+static unsigned int
+setup_prologue_scan (pc)
+ CORE_ADDR pc;
+{
+ unsigned int insn;
+
+ codestream_seek (pc);
+ insn = codestream_get ();
+
+ return insn;
+}
+
+/*
+ * Find & return amount 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
+arc_get_frame_setup (pc)
+ CORE_ADDR pc;
+{
+ unsigned int insn;
+ /* Size of frame or -1 if unrecognizable prologue. */
+ int frame_size = -1;
+ /* An initial "sub sp,sp,N" may or may not be for a stdarg fn. */
+ int maybe_stdarg_decr = -1;
+
+ insn = setup_prologue_scan (pc);
+
+ /* The authority for what appears here is the home-grown ABI.
+ The most recent version is 1.2. */
+
+ /* First insn may be "sub sp,sp,N" if stdarg fn. */
+ if ((insn & BUILD_INSN (-1, -1, -1, -1, 0))
+ == BUILD_INSN (10, SP_REGNUM, SP_REGNUM, SHIMM_REGNUM, 0))
+ {
+ maybe_stdarg_decr = X_D (insn);
+ insn = codestream_get ();
+ }
+
+ if ((insn & BUILD_INSN (-1, 0, -1, -1, -1)) /* st blink,[sp,4] */
+ == BUILD_INSN (2, 0, SP_REGNUM, BLINK_REGNUM, 4))
+ {
+ insn = codestream_get ();
+ /* Frame may not be necessary, even though blink is saved.
+ At least this is something we recognize. */
+ frame_size = 0;
+ }
+
+ if ((insn & BUILD_INSN (-1, 0, -1, -1, -1)) /* st fp,[sp] */
+ == BUILD_INSN (2, 0, SP_REGNUM, FP_REGNUM, 0))
+ {
+ insn = codestream_get ();
+ if ((insn & BUILD_INSN (-1, -1, -1, -1, 0))
+ != BUILD_INSN (12, FP_REGNUM, SP_REGNUM, SP_REGNUM, 0))
+ return -1;
+
+ /* Check for stack adjustment sub sp,sp,N. */
+ insn = codestream_peek ();
+ if ((insn & BUILD_INSN (-1, -1, -1, 0, 0))
+ == BUILD_INSN (10, SP_REGNUM, SP_REGNUM, 0, 0))
+ {
+ if (LIMM_P (X_C (insn)))
+ frame_size = codestream_get ();
+ else if (SHIMM_P (X_C (insn)))
+ frame_size = X_D (insn);
+ else
+ return -1;
+ if (frame_size < 0)
+ return -1;
+
+ codestream_get ();
+
+ /* This sequence is used to get the address of the return
+ buffer for a function that returns a structure. */
+ insn = codestream_peek ();
+ if (insn & OPMASK == 0x60000000)
+ codestream_get ();
+ }
+ /* Frameless fn. */
+ else
+ {
+ frame_size = 0;
+ }
+ }
+
+ /* If we found a "sub sp,sp,N" and nothing else, it may or may not be a
+ stdarg fn. The stdarg decrement is not treated as part of the frame size,
+ so we have a dilemma: what do we return? For now, if we get a
+ "sub sp,sp,N" and nothing else assume this isn't a stdarg fn. One way
+ to fix this completely would be to add a bit to the function descriptor
+ that says the function is a stdarg function. */
+
+ if (frame_size < 0 && maybe_stdarg_decr > 0)
+ return maybe_stdarg_decr;
+ return frame_size;
+}
+
+/* Given a pc value, skip it forward past the function prologue by
+ disassembling instructions that appear to be a prologue.
+
+ If FRAMELESS_P is set, we are only testing to see if the function
+ is frameless. If it is a frameless function, return PC unchanged.
+ This allows a quicker answer. */
+
+CORE_ADDR
+skip_prologue (pc, frameless_p)
+ CORE_ADDR pc;
+ int frameless_p;
+{
+ unsigned int insn;
+ int i, frame_size;
+
+ if ((frame_size = arc_get_frame_setup (pc)) < 0)
+ return (pc);
+
+ if (frameless_p)
+ return frame_size == 0 ? pc : codestream_tell ();
+
+ /* Skip over register saves. */
+ for (i = 0; i < 8; i++)
+ {
+ insn = codestream_peek ();
+ if ((insn & BUILD_INSN (-1, 0, -1, 0, 0))
+ != BUILD_INSN (2, 0, SP_REGNUM, 0, 0))
+ break; /* not st insn */
+ if (! ARC_CALL_SAVED_REG (X_C (insn)))
+ break;
+ codestream_get ();
+ }
+
+ return codestream_tell ();
+}
+
+/* Return the return address for a frame.
+ This is used to implement FRAME_SAVED_PC.
+ This is taken from frameless_look_for_prologue. */
+
+CORE_ADDR
+arc_frame_saved_pc (frame)
+ struct frame_info *frame;
+{
+ CORE_ADDR func_start;
+ unsigned int insn;
+
+ func_start = get_pc_function_start (frame->pc) + FUNCTION_START_OFFSET;
+ if (func_start == 0)
+ {
+ /* Best guess. */
+ return ARC_PC_TO_REAL_ADDRESS (read_memory_integer (FRAME_FP (frame) + 4, 4));
+ }
+
+ /* The authority for what appears here is the home-grown ABI.
+ The most recent version is 1.2. */
+
+ insn = setup_prologue_scan (func_start);
+
+ /* First insn may be "sub sp,sp,N" if stdarg fn. */
+ if ((insn & BUILD_INSN (-1, -1, -1, -1, 0))
+ == BUILD_INSN (10, SP_REGNUM, SP_REGNUM, SHIMM_REGNUM, 0))
+ insn = codestream_get ();
+
+ /* If the next insn is "st blink,[sp,4]" we can get blink from there.
+ Otherwise this is a leaf function and we can use blink. Note that
+ this still allows for the case where a leaf function saves/clobbers/
+ restores blink. */
+
+ if ((insn & BUILD_INSN (-1, 0, -1, -1, -1)) /* st blink,[sp,4] */
+ != BUILD_INSN (2, 0, SP_REGNUM, BLINK_REGNUM, 4))
+ return ARC_PC_TO_REAL_ADDRESS (read_register (BLINK_REGNUM));
+ else
+ return ARC_PC_TO_REAL_ADDRESS (read_memory_integer (FRAME_FP (frame) + 4, 4));
+}
+
+/*
+ * Parse the first few instructions of the function to see
+ * what registers were stored.
+ *
+ * The startup sequence can be at the start of the function.
+ * 'st blink,[sp+4], st fp,[sp], mov fp,sp'
+ *
+ * Local space is allocated just below by sub sp,sp,nnn.
+ * Next, the registers used by this function are stored (as offsets from sp).
+ */
+
+void
+frame_find_saved_regs (fip, fsrp)
+ struct frame_info *fip;
+ struct frame_saved_regs *fsrp;
+{
+ long locals;
+ unsigned int insn;
+ CORE_ADDR dummy_bottom;
+ CORE_ADDR adr;
+ int i, regnum, offset;
+
+ 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 = arc_get_frame_setup (get_pc_function_start (fip->pc));
+
+ if (locals >= 0)
+ {
+ /* Set `adr' to the value of `sp'. */
+ adr = fip->frame - locals;
+ for (i = 0; i < 8; i++)
+ {
+ insn = codestream_get ();
+ if ((insn & BUILD_INSN (-1, 0, -1, 0, 0))
+ != BUILD_INSN (2, 0, SP_REGNUM, 0, 0))
+ break;
+ regnum = X_C (insn);
+ offset = X_D (insn);
+ fsrp->regs[regnum] = adr + offset;
+ }
+ }
+
+ fsrp->regs[PC_REGNUM] = fip->frame + 4;
+ fsrp->regs[FP_REGNUM] = fip->frame;
+}
+
+void
+push_dummy_frame ()
+{
+ CORE_ADDR sp = read_register (SP_REGNUM);
+ int regnum;
+ char regbuf[MAX_REGISTER_RAW_SIZE];
+
+ read_register_gen (PC_REGNUM, regbuf);
+ write_memory (sp+4, regbuf, REGISTER_SIZE);
+ read_register_gen (FP_REGNUM, regbuf);
+ write_memory (sp, regbuf, REGISTER_SIZE);
+ 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));
+ }
+ sp += (2*REGISTER_SIZE);
+ write_register (SP_REGNUM, sp);
+}
+
+void
+pop_frame ()
+{
+ struct frame_info *frame = get_current_frame ();
+ CORE_ADDR fp;
+ int regnum;
+ struct frame_saved_regs fsr;
+ char regbuf[MAX_REGISTER_RAW_SIZE];
+
+ fp = FRAME_FP (frame);
+ get_frame_saved_regs (frame, &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 ();
+}
+
+/* Simulate single-step. */
+
+typedef enum
+{
+ NORMAL4, /* a normal 4 byte insn */
+ NORMAL8, /* a normal 8 byte insn */
+ BRANCH4, /* a 4 byte branch insn, including ones without delay slots */
+ BRANCH8, /* an 8 byte branch insn, including ones with delay slots */
+} insn_type;
+
+/* Return the type of INSN and store in TARGET the destination address of a
+ branch if this is one. */
+/* ??? Need to verify all cases are properly handled. */
+
+static insn_type
+get_insn_type (insn, pc, target)
+ unsigned long insn;
+ CORE_ADDR pc, *target;
+{
+ unsigned long limm;
+
+ switch (insn >> 27)
+ {
+ case 0 : case 1 : case 2 : /* load/store insns */
+ if (LIMM_P (X_A (insn))
+ || LIMM_P (X_B (insn))
+ || LIMM_P (X_C (insn)))
+ return NORMAL8;
+ return NORMAL4;
+ case 4 : case 5 : case 6 : /* branch insns */
+ *target = pc + 4 + X_L (insn);
+ /* ??? It isn't clear that this is always the right answer.
+ The problem occurs when the next insn is an 8 byte insn. If the
+ branch is conditional there's no worry as there shouldn't be an 8
+ byte insn following. The programmer may be cheating if s/he knows
+ the branch will never be taken, but we don't deal with that.
+ Note that the programmer is also allowed to play games by putting
+ an insn with long immediate data in the delay slot and then duplicate
+ the long immediate data at the branch target. Ugh! */
+ if (X_N (insn) == 0)
+ return BRANCH4;
+ return BRANCH8;
+ case 7 : /* jump insns */
+ if (LIMM_P (X_B (insn)))
+ {
+ limm = read_memory_integer (pc + 4, 4);
+ *target = ARC_PC_TO_REAL_ADDRESS (limm);
+ return BRANCH8;
+ }
+ if (SHIMM_P (X_B (insn)))
+ *target = ARC_PC_TO_REAL_ADDRESS (X_D (insn));
+ else
+ *target = ARC_PC_TO_REAL_ADDRESS (read_register (X_B (insn)));
+ if (X_Q (insn) == 0 && X_N (insn) == 0)
+ return BRANCH4;
+ return BRANCH8;
+ default : /* arithmetic insns, etc. */
+ if (LIMM_P (X_A (insn))
+ || LIMM_P (X_B (insn))
+ || LIMM_P (X_C (insn)))
+ return NORMAL8;
+ return NORMAL4;
+ }
+}
+
+/* single_step() is called just before we want to resume the inferior, if we
+ want to single-step it but there is no hardware or kernel single-step
+ support. We find all the possible targets of the coming instruction and
+ breakpoint them.
+
+ single_step is also called just after the inferior stops. If we had
+ set up a simulated single-step, we undo our damage. */
+
+void
+arc_software_single_step (ignore, insert_breakpoints_p)
+ enum target_signal ignore; /* sig but we don't need it */
+ int insert_breakpoints_p;
+{
+ static CORE_ADDR next_pc, target;
+ static int brktrg_p;
+ typedef char binsn_quantum[BREAKPOINT_MAX];
+ static binsn_quantum break_mem[2];
+
+ if (insert_breakpoints_p)
+ {
+ insn_type type;
+ CORE_ADDR pc;
+ unsigned long insn;
+
+ pc = read_register (PC_REGNUM);
+ insn = read_memory_integer (pc, 4);
+ type = get_insn_type (insn, pc, &target);
+
+ /* Always set a breakpoint for the insn after the branch. */
+ next_pc = pc + ((type == NORMAL8 || type == BRANCH8) ? 8 : 4);
+ target_insert_breakpoint (next_pc, break_mem[0]);
+
+ brktrg_p = 0;
+
+ if ((type == BRANCH4 || type == BRANCH8)
+ /* Watch out for branches to the following location.
+ We just stored a breakpoint there and another call to
+ target_insert_breakpoint will think the real insn is the
+ breakpoint we just stored there. */
+ && target != next_pc)
+ {
+ brktrg_p = 1;
+ target_insert_breakpoint (target, break_mem[1]);
+ }
+
+ }
+ else
+ {
+ /* Remove breakpoints. */
+ target_remove_breakpoint (next_pc, break_mem[0]);
+
+ if (brktrg_p)
+ target_remove_breakpoint (target, break_mem[1]);
+
+ /* Fix the pc. */
+ stop_pc -= DECR_PC_AFTER_BREAK;
+ write_pc (stop_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 */
+
+/* Disassemble one instruction. */
+
+static int
+arc_print_insn (vma, info)
+ bfd_vma vma;
+ disassemble_info *info;
+{
+ static int current_mach;
+ static int current_endian;
+ static disassembler_ftype current_disasm;
+
+ if (current_disasm == NULL
+ || arc_bfd_mach_type != current_mach
+ || TARGET_BYTE_ORDER != current_endian)
+ {
+ current_mach = arc_bfd_mach_type;
+ current_endian = TARGET_BYTE_ORDER;
+ current_disasm = arc_get_disassembler (current_mach,
+ current_endian == BIG_ENDIAN);
+ }
+
+ return (*current_disasm) (vma, info);
+}
+
+/* Command to set cpu type. */
+
+void
+arc_set_cpu_type_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ int i;
+
+ if (tmp_arc_cpu_type == NULL || *tmp_arc_cpu_type == '\0')
+ {
+ printf_unfiltered ("The known ARC cpu types are as follows:\n");
+ for (i = 0; arc_cpu_type_table[i].name != NULL; ++i)
+ printf_unfiltered ("%s\n", arc_cpu_type_table[i].name);
+
+ /* Restore the value. */
+ tmp_arc_cpu_type = strsave (arc_cpu_type);
+
+ return;
+ }
+
+ if (!arc_set_cpu_type (tmp_arc_cpu_type))
+ {
+ error ("Unknown cpu type `%s'.", tmp_arc_cpu_type);
+ /* Restore its value. */
+ tmp_arc_cpu_type = strsave (arc_cpu_type);
+ }
+}
+
+static void
+arc_show_cpu_type_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+}
+
+/* Modify the actual cpu type.
+ Result is a boolean indicating success. */
+
+int
+arc_set_cpu_type (str)
+ char *str;
+{
+ int i, j;
+
+ if (str == NULL)
+ return 0;
+
+ for (i = 0; arc_cpu_type_table[i].name != NULL; ++i)
+ {
+ if (strcasecmp (str, arc_cpu_type_table[i].name) == 0)
+ {
+ arc_cpu_type = str;
+ arc_bfd_mach_type = arc_cpu_type_table[i].value;
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+void
+_initialize_arc_tdep ()
+{
+ struct cmd_list_element *c;
+
+ c = add_set_cmd ("cpu", class_support, var_string_noescape,
+ (char *) &tmp_arc_cpu_type,
+ "Set the type of ARC cpu in use.\n\
+This command has two purposes. In a multi-cpu system it lets one\n\
+change the cpu being debugged. It also gives one access to\n\
+cpu-type-specific registers and recognize cpu-type-specific instructions.\
+",
+ &setlist);
+ c->function.cfunc = arc_set_cpu_type_command;
+ c = add_show_from_set (c, &showlist);
+ c->function.cfunc = arc_show_cpu_type_command;
+
+ /* We have to use strsave here because the `set' command frees it before
+ setting a new value. */
+ tmp_arc_cpu_type = strsave (DEFAULT_ARC_CPU_TYPE);
+ arc_set_cpu_type (tmp_arc_cpu_type);
+
+ c = add_set_cmd ("displaypipeline", class_support, var_zinteger,
+ (char *) &display_pipeline_p,
+ "Set pipeline display (simulator only).\n\
+When enabled, the state of the pipeline after each cycle is displayed.",
+ &setlist);
+ c = add_show_from_set (c, &showlist);
+
+ c = add_set_cmd ("debugpipeline", class_support, var_zinteger,
+ (char *) &debug_pipeline_p,
+ "Set pipeline debug display (simulator only).\n\
+When enabled, debugging information about the pipeline is displayed.",
+ &setlist);
+ c = add_show_from_set (c, &showlist);
+
+ c = add_set_cmd ("cputimer", class_support, var_zinteger,
+ (char *) &cpu_timer,
+ "Set maximum cycle count (simulator only).\n\
+Control will return to gdb if the timer expires.\n\
+A negative value disables the timer.",
+ &setlist);
+ c = add_show_from_set (c, &showlist);
+
+ tm_print_insn = arc_print_insn;
+}
diff --git a/gdb/arm-convert.s b/gdb/arm-convert.s
new file mode 100644
index 00000000000..416132b77c7
--- /dev/null
+++ b/gdb/arm-convert.s
@@ -0,0 +1,16 @@
+ .text
+ .global _convert_from_extended
+
+_convert_from_extended:
+
+ ldfe f0,[a1]
+ stfd f0,[a2]
+ movs pc,lr
+
+ .global _convert_to_extended
+
+_convert_to_extended:
+
+ ldfd f0,[a1]
+ stfe f0,[a2]
+ movs pc,lr
diff --git a/gdb/arm-tdep.c b/gdb/arm-tdep.c
new file mode 100644
index 00000000000..607dc8fb5af
--- /dev/null
+++ b/gdb/arm-tdep.c
@@ -0,0 +1,1626 @@
+/* Target-dependent code for the Acorn Risc Machine, for GDB, the GNU Debugger.
+ Copyright (C) 1988, 1989, 1991, 1992, 1993, 1995, 1996, 1998, 1999
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "frame.h"
+#include "inferior.h"
+#include "gdbcmd.h"
+#include "gdbcore.h"
+#include "symfile.h"
+#include "gdb_string.h"
+#include "coff/internal.h" /* Internal format of COFF symbols in BFD */
+
+/*
+ The following macros are actually wrong. Neither arm nor thumb can
+ or should set the lsb on addr.
+ The thumb addresses are mod 2, so (addr & 2) would be a good heuristic
+ to use when checking for thumb (see arm_pc_is_thumb() below).
+ Unfortunately, something else depends on these (incorrect) macros, so
+ fixing them actually breaks gdb. I didn't have time to investigate. Z.R.
+*/
+/* Thumb function addresses are odd (bit 0 is set). Here are some
+ macros to test, set, or clear bit 0 of addresses. */
+#define IS_THUMB_ADDR(addr) ((addr) & 1)
+#define MAKE_THUMB_ADDR(addr) ((addr) | 1)
+#define UNMAKE_THUMB_ADDR(addr) ((addr) & ~1)
+
+/* Macros to round N up or down to the next A boundary; A must be
+ a power of two. */
+#define ROUND_DOWN(n,a) ((n) & ~((a) - 1))
+#define ROUND_UP(n,a) (((n) + (a) - 1) & ~((a) - 1))
+
+/* Should call_function allocate stack space for a struct return? */
+/* The system C compiler uses a similar structure return convention to gcc */
+int
+arm_use_struct_convention (gcc_p, type)
+ int gcc_p;
+ struct type *type;
+{
+ return (TYPE_LENGTH (type) > 4);
+}
+
+int
+arm_frame_chain_valid (chain, thisframe)
+ CORE_ADDR chain;
+ struct frame_info *thisframe;
+{
+#define LOWEST_PC 0x20 /* the first 0x20 bytes are the trap vectors. */
+ return (chain != 0 && (FRAME_SAVED_PC (thisframe) >= LOWEST_PC));
+}
+
+/* Set to true if the 32-bit mode is in use. */
+
+int arm_apcs_32 = 1;
+
+/* Flag set by arm_fix_call_dummy that tells whether the target function
+ is a Thumb function. This flag is checked by arm_push_arguments.
+ FIXME: Change the PUSH_ARGUMENTS macro (and its use in valops.c) to
+ pass the function address as an additional parameter. */
+
+static int target_is_thumb;
+
+/* Flag set by arm_fix_call_dummy that tells whether the calling function
+ is a Thumb function. This flag is checked by arm_pc_is_thumb
+ and arm_call_dummy_breakpoint_offset. */
+
+static int caller_is_thumb;
+
+/* Tell if the program counter value in MEMADDR is in a Thumb function. */
+
+int
+arm_pc_is_thumb (memaddr)
+ bfd_vma memaddr;
+{
+ struct minimal_symbol * sym;
+ CORE_ADDR sp;
+
+ /* If bit 0 of the address is set, assume this is a Thumb address. */
+ if (IS_THUMB_ADDR (memaddr))
+ return 1;
+
+ /* Thumb function have a "special" bit set in minimal symbols */
+ sym = lookup_minimal_symbol_by_pc (memaddr);
+ if (sym)
+ {
+ return (MSYMBOL_IS_SPECIAL(sym));
+ }
+ else
+ return 0;
+}
+
+/* Tell if the program counter value in MEMADDR is in a call dummy that
+ is being called from a Thumb function. */
+
+int
+arm_pc_is_thumb_dummy (memaddr)
+ bfd_vma memaddr;
+{
+ CORE_ADDR sp = read_sp();
+
+ if (PC_IN_CALL_DUMMY (memaddr, sp, sp+64))
+ return caller_is_thumb;
+ else
+ return 0;
+}
+
+CORE_ADDR
+arm_addr_bits_remove (val)
+ CORE_ADDR val;
+{
+ if (arm_pc_is_thumb (val))
+ return (val & (arm_apcs_32 ? 0xfffffffe : 0x03fffffe));
+ else
+ return (val & (arm_apcs_32 ? 0xfffffffc : 0x03fffffc));
+}
+
+CORE_ADDR
+arm_saved_pc_after_call (frame)
+ struct frame_info *frame;
+{
+ return ADDR_BITS_REMOVE (read_register (LR_REGNUM));
+}
+
+/* A typical Thumb prologue looks like this:
+ push {r7, lr}
+ add sp, sp, #-28
+ add r7, sp, #12
+ Sometimes the latter instruction may be replaced by:
+ mov r7, sp
+*/
+
+static CORE_ADDR
+thumb_skip_prologue (pc)
+ CORE_ADDR pc;
+{
+ CORE_ADDR current_pc;
+
+ for (current_pc = pc; current_pc < pc + 20; current_pc += 2)
+ {
+ unsigned short insn = read_memory_unsigned_integer (current_pc, 2);
+
+ if ( (insn & 0xfe00) != 0xb400 /* push {..., r7, lr} */
+ && (insn & 0xff00) != 0xb000 /* add sp, #simm */
+ && (insn & 0xff00) != 0xaf00 /* add r7, sp, #imm */
+ && insn != 0x466f /* mov r7, sp */
+ && (insn & 0xffc0) != 0x4640) /* mov r0-r7, r8-r15 */
+ break;
+ }
+
+ return current_pc;
+}
+
+/* APCS (ARM procedure call standard) defines the following prologue:
+
+ mov ip, sp
+ [stmfd sp!, {a1,a2,a3,a4}]
+ stmfd sp!, {...,fp,ip,lr,pc}
+ [stfe f7, [sp, #-12]!]
+ [stfe f6, [sp, #-12]!]
+ [stfe f5, [sp, #-12]!]
+ [stfe f4, [sp, #-12]!]
+ sub fp, ip, #nn // nn == 20 or 4 depending on second ins
+*/
+
+CORE_ADDR
+arm_skip_prologue (pc)
+ CORE_ADDR pc;
+{
+ unsigned long inst;
+ CORE_ADDR skip_pc;
+ CORE_ADDR func_addr, func_end;
+ struct symtab_and_line sal;
+
+ /* See what the symbol table says. */
+ if (find_pc_partial_function (pc, NULL, & func_addr, & func_end))
+ {
+ sal = find_pc_line (func_addr, 0);
+ if (sal.line != 0 && sal.end < func_end)
+ return sal.end;
+ }
+
+ /* Check if this is Thumb code. */
+ if (arm_pc_is_thumb (pc))
+ return thumb_skip_prologue (pc);
+
+ /* Can't find the prologue end in the symbol table, try it the hard way
+ by disassembling the instructions. */
+ skip_pc = pc;
+ inst = read_memory_integer (skip_pc, 4);
+ if (inst != 0xe1a0c00d) /* mov ip, sp */
+ return pc;
+
+ skip_pc += 4;
+ inst = read_memory_integer (skip_pc, 4);
+ if ((inst & 0xfffffff0) == 0xe92d0000) /* stmfd sp!,{a1,a2,a3,a4} */
+ {
+ skip_pc += 4;
+ inst = read_memory_integer (skip_pc, 4);
+ }
+
+ if ((inst & 0xfffff800) != 0xe92dd800) /* stmfd sp!,{...,fp,ip,lr,pc} */
+ return pc;
+
+ skip_pc += 4;
+ inst = read_memory_integer (skip_pc, 4);
+
+ /* Any insns after this point may float into the code, if it makes
+ for better instruction scheduling, so we skip them only if
+ we find them, but still consdier the function to be frame-ful */
+
+ /* We may have either one sfmfd instruction here, or several stfe insns,
+ depending on the version of floating point code we support. */
+ if ((inst & 0xffbf0fff) == 0xec2d0200) /* sfmfd fn, <cnt>, [sp]! */
+ {
+ skip_pc += 4;
+ inst = read_memory_integer (skip_pc, 4);
+ }
+ else
+ {
+ while ((inst & 0xffff8fff) == 0xed6d0103) /* stfe fn, [sp, #-12]! */
+ {
+ skip_pc += 4;
+ inst = read_memory_integer (skip_pc, 4);
+ }
+ }
+
+ if ((inst & 0xfffff000) == 0xe24cb000) /* sub fp, ip, #nn */
+ skip_pc += 4;
+
+ return skip_pc;
+}
+
+
+
+/* Function: thumb_scan_prologue (helper function for arm_scan_prologue)
+ This function decodes a Thumb function prologue to determine:
+ 1) the size of the stack frame
+ 2) which registers are saved on it
+ 3) the offsets of saved regs
+ 4) the offset from the stack pointer to the frame pointer
+ This information is stored in the "extra" fields of the frame_info.
+
+ A typical Thumb function prologue might look like this:
+ push {r7, lr}
+ sub sp, #28,
+ add r7, sp, #12
+ Which would create this stack frame (offsets relative to FP)
+ old SP -> 24 stack parameters
+ 20 LR
+ 16 R7
+ R7 -> 0 local variables (16 bytes)
+ SP -> -12 additional stack space (12 bytes)
+ The frame size would thus be 36 bytes, and the frame offset would be
+ 12 bytes. The frame register is R7. */
+
+static void
+thumb_scan_prologue (fi)
+ struct frame_info * fi;
+{
+ CORE_ADDR prologue_start;
+ CORE_ADDR prologue_end;
+ CORE_ADDR current_pc;
+ int saved_reg[16]; /* which register has been copied to register n? */
+ int i;
+
+ if (find_pc_partial_function (fi->pc, NULL, & prologue_start, & prologue_end))
+ {
+ struct symtab_and_line sal = find_pc_line (prologue_start, 0);
+
+ if (sal.line == 0) /* no line info, use current PC */
+ prologue_end = fi->pc;
+ else if (sal.end < prologue_end) /* next line begins after fn end */
+ prologue_end = sal.end; /* (probably means no prologue) */
+ }
+ else
+ prologue_end = prologue_start + 40; /* We're in the boondocks: allow for */
+ /* 16 pushes, an add, and "mv fp,sp" */
+
+ prologue_end = min (prologue_end, fi->pc);
+
+ /* Initialize the saved register map. When register H is copied to
+ register L, we will put H in saved_reg[L]. */
+ for (i = 0; i < 16; i++)
+ saved_reg[i] = i;
+
+ /* Search the prologue looking for instructions that set up the
+ frame pointer, adjust the stack pointer, and save registers. */
+
+ fi->framesize = 0;
+ for (current_pc = prologue_start; current_pc < prologue_end; current_pc += 2)
+ {
+ unsigned short insn;
+ int regno;
+ int offset;
+
+ insn = read_memory_unsigned_integer (current_pc, 2);
+
+ if ((insn & 0xfe00) == 0xb400) /* push { rlist } */
+ {
+ /* Bits 0-7 contain a mask for registers R0-R7. Bit 8 says
+ whether to save LR (R14). */
+ int mask = (insn & 0xff) | ((insn & 0x100) << 6);
+
+ /* Calculate offsets of saved R0-R7 and LR. */
+ for (regno = LR_REGNUM; regno >= 0; regno--)
+ if (mask & (1 << regno))
+ {
+ fi->framesize += 4;
+ fi->fsr.regs[saved_reg[regno]] = -(fi->framesize);
+ saved_reg[regno] = regno; /* reset saved register map */
+ }
+ }
+ else if ((insn & 0xff00) == 0xb000) /* add sp, #simm */
+ {
+ offset = (insn & 0x7f) << 2; /* get scaled offset */
+ if (insn & 0x80) /* is it signed? */
+ offset = -offset;
+ fi->framesize -= offset;
+ }
+ else if ((insn & 0xff00) == 0xaf00) /* add r7, sp, #imm */
+ {
+ fi->framereg = THUMB_FP_REGNUM;
+ fi->frameoffset = (insn & 0xff) << 2; /* get scaled offset */
+ }
+ else if (insn == 0x466f) /* mov r7, sp */
+ {
+ fi->framereg = THUMB_FP_REGNUM;
+ fi->frameoffset = 0;
+ saved_reg[THUMB_FP_REGNUM] = SP_REGNUM;
+ }
+ else if ((insn & 0xffc0) == 0x4640) /* mov r0-r7, r8-r15 */
+ {
+ int lo_reg = insn & 7; /* dest. register (r0-r7) */
+ int hi_reg = ((insn >> 3) & 7) + 8; /* source register (r8-15) */
+ saved_reg[lo_reg] = hi_reg; /* remember hi reg was saved */
+ }
+ else
+ break; /* anything else isn't prologue */
+ }
+}
+
+/* Function: check_prologue_cache
+ Check if prologue for this frame's PC has already been scanned.
+ If it has, copy the relevant information about that prologue and
+ return non-zero. Otherwise do not copy anything and return zero.
+
+ The information saved in the cache includes:
+ * the frame register number;
+ * the size of the stack frame;
+ * the offsets of saved regs (relative to the old SP); and
+ * the offset from the stack pointer to the frame pointer
+
+ The cache contains only one entry, since this is adequate
+ for the typical sequence of prologue scan requests we get.
+ When performing a backtrace, GDB will usually ask to scan
+ the same function twice in a row (once to get the frame chain,
+ and once to fill in the extra frame information).
+*/
+
+static struct frame_info prologue_cache;
+
+static int
+check_prologue_cache (fi)
+ struct frame_info * fi;
+{
+ int i;
+
+ if (fi->pc == prologue_cache.pc)
+ {
+ fi->framereg = prologue_cache.framereg;
+ fi->framesize = prologue_cache.framesize;
+ fi->frameoffset = prologue_cache.frameoffset;
+ for (i = 0; i <= NUM_REGS; i++)
+ fi->fsr.regs[i] = prologue_cache.fsr.regs[i];
+ return 1;
+ }
+ else
+ return 0;
+}
+
+
+/* Function: save_prologue_cache
+ Copy the prologue information from fi to the prologue cache.
+*/
+
+static void
+save_prologue_cache (fi)
+ struct frame_info * fi;
+{
+ int i;
+
+ prologue_cache.pc = fi->pc;
+ prologue_cache.framereg = fi->framereg;
+ prologue_cache.framesize = fi->framesize;
+ prologue_cache.frameoffset = fi->frameoffset;
+
+ for (i = 0; i <= NUM_REGS; i++)
+ prologue_cache.fsr.regs[i] = fi->fsr.regs[i];
+}
+
+
+/* Function: arm_scan_prologue
+ This function decodes an ARM function prologue to determine:
+ 1) the size of the stack frame
+ 2) which registers are saved on it
+ 3) the offsets of saved regs
+ 4) the offset from the stack pointer to the frame pointer
+ This information is stored in the "extra" fields of the frame_info.
+
+ A typical Arm function prologue might look like this:
+ mov ip, sp
+ stmfd sp!, {fp, ip, lr, pc}
+ sub fp, ip, #4
+ sub sp, sp, #16
+ Which would create this stack frame (offsets relative to FP):
+ IP -> 4 (caller's stack)
+ FP -> 0 PC (points to address of stmfd instruction + 12 in callee)
+ -4 LR (return address in caller)
+ -8 IP (copy of caller's SP)
+ -12 FP (caller's FP)
+ SP -> -28 Local variables
+ The frame size would thus be 32 bytes, and the frame offset would be
+ 28 bytes. */
+
+static void
+arm_scan_prologue (fi)
+ struct frame_info * fi;
+{
+ int regno, sp_offset, fp_offset;
+ CORE_ADDR prologue_start, prologue_end, current_pc;
+
+ /* Check if this function is already in the cache of frame information. */
+ if (check_prologue_cache (fi))
+ return;
+
+ /* Assume there is no frame until proven otherwise. */
+ fi->framereg = SP_REGNUM;
+ fi->framesize = 0;
+ fi->frameoffset = 0;
+
+ /* Check for Thumb prologue. */
+ if (arm_pc_is_thumb (fi->pc))
+ {
+ thumb_scan_prologue (fi);
+ save_prologue_cache (fi);
+ return;
+ }
+
+ /* Find the function prologue. If we can't find the function in
+ the symbol table, peek in the stack frame to find the PC. */
+ if (find_pc_partial_function (fi->pc, NULL, &prologue_start, &prologue_end))
+ {
+ /* Assume the prologue is everything between the first instruction
+ in the function and the first source line. */
+ struct symtab_and_line sal = find_pc_line (prologue_start, 0);
+
+ if (sal.line == 0) /* no line info, use current PC */
+ prologue_end = fi->pc;
+ else if (sal.end < prologue_end) /* next line begins after fn end */
+ prologue_end = sal.end; /* (probably means no prologue) */
+ }
+ else
+ {
+ /* Get address of the stmfd in the prologue of the callee; the saved
+ PC is the address of the stmfd + 12. */
+ prologue_start = (read_memory_integer (fi->frame, 4) & 0x03fffffc) - 12;
+ prologue_end = prologue_start + 40; /* FIXME: should be big enough */
+ }
+
+ /* Now search the prologue looking for instructions that set up the
+ frame pointer, adjust the stack pointer, and save registers. */
+
+ sp_offset = fp_offset = 0;
+ for (current_pc = prologue_start; current_pc < prologue_end; current_pc += 4)
+ {
+ unsigned int insn = read_memory_unsigned_integer (current_pc, 4);
+
+ if ((insn & 0xffff0000) == 0xe92d0000) /* stmfd sp!, {..., r7, lr} */
+ {
+ int mask = insn & 0xffff;
+
+ /* Calculate offsets of saved registers. */
+ for (regno = PC_REGNUM; regno >= 0; regno--)
+ if (mask & (1 << regno))
+ {
+ sp_offset -= 4;
+ fi->fsr.regs[regno] = sp_offset;
+ }
+ }
+ else if ((insn & 0xfffff000) == 0xe24cb000) /* sub fp, ip #n */
+ {
+ unsigned imm = insn & 0xff; /* immediate value */
+ unsigned rot = (insn & 0xf00) >> 7; /* rotate amount */
+ imm = (imm >> rot) | (imm << (32-rot));
+ fp_offset = -imm;
+ fi->framereg = FP_REGNUM;
+ }
+ else if ((insn & 0xfffff000) == 0xe24dd000) /* sub sp, sp #n */
+ {
+ unsigned imm = insn & 0xff; /* immediate value */
+ unsigned rot = (insn & 0xf00) >> 7; /* rotate amount */
+ imm = (imm >> rot) | (imm << (32-rot));
+ sp_offset -= imm;
+ }
+ else if ((insn & 0xffff7fff) == 0xed6d0103) /* stfe f?, [sp, -#c]! */
+ {
+ sp_offset -= 12;
+ regno = F0_REGNUM + ((insn >> 12) & 0x07);
+ fi->fsr.regs[regno] = sp_offset;
+ }
+ else if (insn == 0xe1a0c00d) /* mov ip, sp */
+ continue;
+ else
+ break; /* not a recognized prologue instruction */
+ }
+
+ /* The frame size is just the negative of the offset (from the original SP)
+ of the last thing thing we pushed on the stack. The frame offset is
+ [new FP] - [new SP]. */
+ fi->framesize = -sp_offset;
+ fi->frameoffset = fp_offset - sp_offset;
+
+ save_prologue_cache (fi);
+}
+
+
+/* Function: find_callers_reg
+ Find REGNUM on the stack. Otherwise, it's in an active register. One thing
+ we might want to do here is to check REGNUM against the clobber mask, and
+ somehow flag it as invalid if it isn't saved on the stack somewhere. This
+ would provide a graceful failure mode when trying to get the value of
+ caller-saves registers for an inner frame. */
+
+static CORE_ADDR
+arm_find_callers_reg (fi, regnum)
+ struct frame_info * fi;
+ int regnum;
+{
+ for (; fi; fi = fi->next)
+
+#if 0 /* FIXME: enable this code if we convert to new call dummy scheme. */
+ if (PC_IN_CALL_DUMMY (fi->pc, fi->frame, fi->frame))
+ return generic_read_register_dummy (fi->pc, fi->frame, regnum);
+ else
+#endif
+ if (fi->fsr.regs[regnum] != 0)
+ return read_memory_integer (fi->fsr.regs[regnum],
+ REGISTER_RAW_SIZE(regnum));
+ return read_register (regnum);
+}
+
+
+/* Function: 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
+ INIT_EXTRA_FRAME_INFO and INIT_FRAME_PC will be called for the new frame.
+ For ARM, we save the frame size when we initialize the frame_info.
+
+ The original definition of this function was a macro in tm-arm.h:
+ { In the case of the ARM, the frame's nominal address is the FP value,
+ and 12 bytes before comes the saved previous FP value as a 4-byte word. }
+
+ #define FRAME_CHAIN(thisframe) \
+ ((thisframe)->pc >= LOWEST_PC ? \
+ read_memory_integer ((thisframe)->frame - 12, 4) :\
+ 0)
+*/
+
+CORE_ADDR
+arm_frame_chain (fi)
+ struct frame_info * fi;
+{
+#if 0 /* FIXME: enable this code if we convert to new call dummy scheme. */
+ CORE_ADDR fn_start, callers_pc, fp;
+
+ /* is this a dummy frame? */
+ if (PC_IN_CALL_DUMMY (fi->pc, fi->frame, fi->frame))
+ return fi->frame; /* dummy frame same as caller's frame */
+
+ /* is caller-of-this a dummy frame? */
+ callers_pc = FRAME_SAVED_PC(fi); /* find out who called us: */
+ fp = arm_find_callers_reg (fi, FP_REGNUM);
+ if (PC_IN_CALL_DUMMY (callers_pc, fp, fp))
+ return fp; /* dummy frame's frame may bear no relation to ours */
+
+ if (find_pc_partial_function (fi->pc, 0, &fn_start, 0))
+ if (fn_start == entry_point_address ())
+ return 0; /* in _start fn, don't chain further */
+#endif
+ CORE_ADDR caller_pc, fn_start;
+ struct frame_info caller_fi;
+ int framereg = fi->framereg;
+
+ if (fi->pc < LOWEST_PC)
+ return 0;
+
+ /* If the caller is the startup code, we're at the end of the chain. */
+ caller_pc = FRAME_SAVED_PC (fi);
+ if (find_pc_partial_function (caller_pc, 0, &fn_start, 0))
+ if (fn_start == entry_point_address ())
+ return 0;
+
+ /* If the caller is Thumb and the caller is ARM, or vice versa,
+ the frame register of the caller is different from ours.
+ So we must scan the prologue of the caller to determine its
+ frame register number. */
+ if (arm_pc_is_thumb (caller_pc) != arm_pc_is_thumb (fi->pc))
+ {
+ memset (& caller_fi, 0, sizeof (caller_fi));
+ caller_fi.pc = caller_pc;
+ arm_scan_prologue (& caller_fi);
+ framereg = caller_fi.framereg;
+ }
+
+ /* If the caller used a frame register, return its value.
+ Otherwise, return the caller's stack pointer. */
+ if (framereg == FP_REGNUM || framereg == THUMB_FP_REGNUM)
+ return arm_find_callers_reg (fi, framereg);
+ else
+ return fi->frame + fi->framesize;
+}
+
+/* Function: init_extra_frame_info
+ This function actually figures out the frame address for a given pc and
+ sp. This is tricky because we sometimes don't use an explicit
+ frame pointer, and the previous stack pointer isn't necessarily recorded
+ on the stack. The only reliable way to get this info is to
+ examine the prologue. */
+
+void
+arm_init_extra_frame_info (fi)
+ struct frame_info * fi;
+{
+ int reg;
+
+ if (fi->next)
+ fi->pc = FRAME_SAVED_PC (fi->next);
+
+ memset (fi->fsr.regs, '\000', sizeof fi->fsr.regs);
+
+#if 0 /* FIXME: enable this code if we convert to new call dummy scheme. */
+ if (PC_IN_CALL_DUMMY (fi->pc, fi->frame, fi->frame))
+ {
+ /* We need to setup fi->frame here because run_stack_dummy gets it wrong
+ by assuming it's always FP. */
+ fi->frame = generic_read_register_dummy (fi->pc, fi->frame, SP_REGNUM);
+ fi->framesize = 0;
+ fi->frameoffset = 0;
+ return;
+ }
+ else
+#endif
+ {
+ arm_scan_prologue (fi);
+
+ if (!fi->next) /* this is the innermost frame? */
+ fi->frame = read_register (fi->framereg);
+ else /* not the innermost frame */
+ /* If we have an FP, the callee saved it. */
+ if (fi->framereg == FP_REGNUM || fi->framereg == THUMB_FP_REGNUM)
+ if (fi->next->fsr.regs[fi->framereg] != 0)
+ fi->frame = read_memory_integer (fi->next->fsr.regs[fi->framereg],
+ 4);
+
+ /* Calculate actual addresses of saved registers using offsets determined
+ by arm_scan_prologue. */
+ for (reg = 0; reg < NUM_REGS; reg++)
+ if (fi->fsr.regs[reg] != 0)
+ fi->fsr.regs[reg] += fi->frame + fi->framesize - fi->frameoffset;
+ }
+}
+
+
+/* Function: frame_saved_pc
+ Find the caller of this frame. We do this by seeing if LR_REGNUM is saved
+ in the stack anywhere, otherwise we get it from the registers.
+
+ The old definition of this function was a macro:
+ #define FRAME_SAVED_PC(FRAME) \
+ ADDR_BITS_REMOVE (read_memory_integer ((FRAME)->frame - 4, 4))
+*/
+
+CORE_ADDR
+arm_frame_saved_pc (fi)
+ struct frame_info * fi;
+{
+#if 0 /* FIXME: enable this code if we convert to new call dummy scheme. */
+ if (PC_IN_CALL_DUMMY (fi->pc, fi->frame, fi->frame))
+ return generic_read_register_dummy (fi->pc, fi->frame, PC_REGNUM);
+ else
+#endif
+ {
+ CORE_ADDR pc = arm_find_callers_reg (fi, LR_REGNUM);
+ return IS_THUMB_ADDR (pc) ? UNMAKE_THUMB_ADDR (pc) : pc;
+ }
+}
+
+
+/* Return the frame address. On ARM, it is R11; on Thumb it is R7.
+ Examine the Program Status Register to decide which state we're in. */
+
+CORE_ADDR
+arm_target_read_fp ()
+{
+ if (read_register (PS_REGNUM) & 0x20) /* Bit 5 is Thumb state bit */
+ return read_register (THUMB_FP_REGNUM); /* R7 if Thumb */
+ else
+ return read_register (FP_REGNUM); /* R11 if ARM */
+}
+
+
+/* Calculate the frame offsets of the saved registers (ARM version). */
+void
+arm_frame_find_saved_regs (fi, regaddr)
+ struct frame_info *fi;
+ struct frame_saved_regs *regaddr;
+{
+ memcpy (regaddr, &fi->fsr, sizeof (struct frame_saved_regs));
+}
+
+
+void
+arm_push_dummy_frame ()
+{
+ CORE_ADDR old_sp = read_register (SP_REGNUM);
+ CORE_ADDR sp = old_sp;
+ CORE_ADDR fp, prologue_start;
+ int regnum;
+
+ /* Push the two dummy prologue instructions in reverse order,
+ so that they'll be in the correct low-to-high order in memory. */
+ /* sub fp, ip, #4 */
+ sp = push_word (sp, 0xe24cb004);
+ /* stmdb sp!, {r0-r10, fp, ip, lr, pc} */
+ prologue_start = sp = push_word (sp, 0xe92ddfff);
+
+ /* push a pointer to the dummy prologue + 12, because when
+ stm instruction stores the PC, it stores the address of the stm
+ instruction itself plus 12. */
+ fp = sp = push_word (sp, prologue_start + 12);
+ sp = push_word (sp, read_register (PC_REGNUM)); /* FIXME: was PS_REGNUM */
+ sp = push_word (sp, old_sp);
+ sp = push_word (sp, read_register (FP_REGNUM));
+
+ for (regnum = 10; regnum >= 0; regnum --)
+ sp = push_word (sp, read_register (regnum));
+
+ write_register (FP_REGNUM, fp);
+ write_register (THUMB_FP_REGNUM, fp);
+ write_register (SP_REGNUM, sp);
+}
+
+/* Fix up the call dummy, based on whether the processor is currently
+ in Thumb or ARM mode, and whether the target function is Thumb
+ or ARM. There are three different situations requiring three
+ different dummies:
+
+ * ARM calling ARM: uses the call dummy in tm-arm.h, which has already
+ been copied into the dummy parameter to this function.
+ * ARM calling Thumb: uses the call dummy in tm-arm.h, but with the
+ "mov pc,r4" instruction patched to be a "bx r4" instead.
+ * Thumb calling anything: uses the Thumb dummy defined below, which
+ works for calling both ARM and Thumb functions.
+
+ All three call dummies expect to receive the target function address
+ in R4, with the low bit set if it's a Thumb function.
+*/
+
+void
+arm_fix_call_dummy (dummy, pc, fun, nargs, args, type, gcc_p)
+ char * dummy;
+ CORE_ADDR pc;
+ CORE_ADDR fun;
+ int nargs;
+ value_ptr * args;
+ struct type * type;
+ int gcc_p;
+{
+ static short thumb_dummy[4] =
+ {
+ 0xf000, 0xf801, /* bl label */
+ 0xdf18, /* swi 24 */
+ 0x4720, /* label: bx r4 */
+ };
+ static unsigned long arm_bx_r4 = 0xe12fff14; /* bx r4 instruction */
+
+ /* Set flag indicating whether the current PC is in a Thumb function. */
+ caller_is_thumb = arm_pc_is_thumb (read_pc());
+
+ /* If the target function is Thumb, set the low bit of the function address.
+ And if the CPU is currently in ARM mode, patch the second instruction
+ of call dummy to use a BX instruction to switch to Thumb mode. */
+ target_is_thumb = arm_pc_is_thumb (fun);
+ if (target_is_thumb)
+ {
+ fun |= 1;
+ if (!caller_is_thumb)
+ store_unsigned_integer (dummy + 4, sizeof (arm_bx_r4), arm_bx_r4);
+ }
+
+ /* If the CPU is currently in Thumb mode, use the Thumb call dummy
+ instead of the ARM one that's already been copied. This will
+ work for both Thumb and ARM target functions. */
+ if (caller_is_thumb)
+ {
+ int i;
+ char *p = dummy;
+ int len = sizeof (thumb_dummy) / sizeof (thumb_dummy[0]);
+
+ for (i = 0; i < len; i++)
+ {
+ store_unsigned_integer (p, sizeof (thumb_dummy[0]), thumb_dummy[i]);
+ p += sizeof (thumb_dummy[0]);
+ }
+ }
+
+ /* Put the target address in r4; the call dummy will copy this to the PC. */
+ write_register (4, fun);
+}
+
+
+/* Return the offset in the call dummy of the instruction that needs
+ to have a breakpoint placed on it. This is the offset of the 'swi 24'
+ instruction, which is no longer actually used, but simply acts
+ as a place-holder now.
+
+ This implements the CALL_DUMMY_BREAK_OFFSET macro.
+*/
+
+int
+arm_call_dummy_breakpoint_offset ()
+{
+ if (caller_is_thumb)
+ return 4;
+ else
+ return 8;
+}
+
+
+CORE_ADDR
+arm_push_arguments(nargs, args, sp, struct_return, struct_addr)
+ int nargs;
+ value_ptr * args;
+ CORE_ADDR sp;
+ int struct_return;
+ CORE_ADDR struct_addr;
+{
+ int argreg;
+ int float_argreg;
+ int argnum;
+ int stack_offset;
+ struct stack_arg {
+ char *val;
+ int len;
+ int offset;
+ };
+ struct stack_arg *stack_args =
+ (struct stack_arg*)alloca (nargs * sizeof (struct stack_arg));
+ int nstack_args = 0;
+
+
+ /* Initialize the integer and float register pointers. */
+ argreg = A1_REGNUM;
+ float_argreg = F0_REGNUM;
+
+ /* the struct_return pointer occupies the first parameter-passing reg */
+ if (struct_return)
+ write_register (argreg++, struct_addr);
+
+ /* The offset onto the stack at which we will start copying parameters
+ (after the registers are used up) begins at 16 in the old ABI.
+ This leaves room for the "home" area for register parameters. */
+ stack_offset = REGISTER_SIZE * 4;
+
+ /* Process args from left to right. Store as many as allowed in
+ registers, save the rest to be pushed on the stack */
+ for(argnum = 0; argnum < nargs; argnum++)
+ {
+ char * val;
+ value_ptr arg = args[argnum];
+ struct type * arg_type = check_typedef (VALUE_TYPE (arg));
+ struct type * target_type = TYPE_TARGET_TYPE (arg_type);
+ int len = TYPE_LENGTH (arg_type);
+ enum type_code typecode = TYPE_CODE (arg_type);
+ CORE_ADDR regval;
+ int newarg;
+
+ val = (char *) VALUE_CONTENTS (arg);
+
+ /* If the argument is a pointer to a function, and it's a Thumb
+ function, set the low bit of the pointer. */
+ if (typecode == TYPE_CODE_PTR
+ && target_type != NULL
+ && TYPE_CODE (target_type) == TYPE_CODE_FUNC)
+ {
+ regval = extract_address (val, len);
+ if (arm_pc_is_thumb (regval))
+ store_address (val, len, MAKE_THUMB_ADDR (regval));
+ }
+
+#define MAPCS_FLOAT 0 /* --mapcs-float not implemented by the compiler yet */
+#if MAPCS_FLOAT
+ /* Up to four floating point arguments can be passed in floating
+ point registers on ARM (not on Thumb). */
+ if (typecode == TYPE_CODE_FLT
+ && float_argreg <= ARM_LAST_FP_ARG_REGNUM
+ && !target_is_thumb)
+ {
+ /* This is a floating point value that fits entirely
+ in a single register. */
+ regval = extract_address (val, len);
+ write_register (float_argreg++, regval);
+ }
+ else
+#endif
+ {
+ /* Copy the argument to general registers or the stack in
+ register-sized pieces. Large arguments are split between
+ registers and stack. */
+ while (len > 0)
+ {
+ if (argreg <= ARM_LAST_ARG_REGNUM)
+ {
+ int partial_len = len < REGISTER_SIZE ? len : REGISTER_SIZE;
+ regval = extract_address (val, partial_len);
+
+ /* It's a simple argument being passed in a general
+ register. */
+ write_register (argreg, regval);
+ argreg++;
+ len -= partial_len;
+ val += partial_len;
+ }
+ else
+ {
+ /* keep for later pushing */
+ stack_args[nstack_args].val = val;
+ stack_args[nstack_args++].len = len;
+ break;
+ }
+ }
+ }
+ }
+ /* now do the real stack pushing, process args right to left */
+ while(nstack_args--)
+ {
+ sp -= stack_args[nstack_args].len;
+ write_memory(sp, stack_args[nstack_args].val,
+ stack_args[nstack_args].len);
+ }
+
+ /* Return adjusted stack pointer. */
+ return sp;
+}
+
+void
+arm_pop_frame ()
+{
+ struct frame_info *frame = get_current_frame();
+ int regnum;
+
+ for (regnum = 0; regnum < NUM_REGS; regnum++)
+ if (frame->fsr.regs[regnum] != 0)
+ write_register (regnum,
+ read_memory_integer (frame->fsr.regs[regnum], 4));
+
+ write_register (PC_REGNUM, FRAME_SAVED_PC (frame));
+ write_register (SP_REGNUM, read_register (frame->framereg));
+
+ flush_cached_frames ();
+}
+
+static void
+print_fpu_flags (flags)
+ int flags;
+{
+ if (flags & (1 << 0)) fputs ("IVO ", stdout);
+ if (flags & (1 << 1)) fputs ("DVZ ", stdout);
+ if (flags & (1 << 2)) fputs ("OFL ", stdout);
+ if (flags & (1 << 3)) fputs ("UFL ", stdout);
+ if (flags & (1 << 4)) fputs ("INX ", stdout);
+ putchar ('\n');
+}
+
+void
+arm_float_info ()
+{
+ register unsigned long status = read_register (FPS_REGNUM);
+ int type;
+
+ type = (status >> 24) & 127;
+ printf ("%s FPU type %d\n",
+ (status & (1<<31)) ? "Hardware" : "Software",
+ type);
+ fputs ("mask: ", stdout);
+ print_fpu_flags (status >> 16);
+ fputs ("flags: ", stdout);
+ print_fpu_flags (status);
+}
+
+static char *original_register_names[] =
+{ "a1", "a2", "a3", "a4", /* 0 1 2 3 */
+ "v1", "v2", "v3", "v4", /* 4 5 6 7 */
+ "v5", "v6", "sl", "fp", /* 8 9 10 11 */
+ "ip", "sp", "lr", "pc", /* 12 13 14 15 */
+ "f0", "f1", "f2", "f3", /* 16 17 18 19 */
+ "f4", "f5", "f6", "f7", /* 20 21 22 23 */
+ "fps","ps" } /* 24 25 */;
+
+/* These names are the ones which gcc emits, and
+ I find them less confusing. Toggle between them
+ using the `othernames' command. */
+static char *additional_register_names[] =
+{ "r0", "r1", "r2", "r3", /* 0 1 2 3 */
+ "r4", "r5", "r6", "r7", /* 4 5 6 7 */
+ "r8", "r9", "sl", "fp", /* 8 9 10 11 */
+ "ip", "sp", "lr", "pc", /* 12 13 14 15 */
+ "f0", "f1", "f2", "f3", /* 16 17 18 19 */
+ "f4", "f5", "f6", "f7", /* 20 21 22 23 */
+ "fps","ps" } /* 24 25 */;
+
+char **arm_register_names = original_register_names;
+
+
+static void
+arm_othernames ()
+{
+ static int toggle;
+ arm_register_names = (toggle
+ ? additional_register_names
+ : original_register_names);
+ toggle = !toggle;
+}
+
+/* FIXME: Fill in with the 'right thing', see asm
+ template in arm-convert.s */
+
+void
+convert_from_extended (ptr, dbl)
+ void * ptr;
+ double * dbl;
+{
+ *dbl = *(double*)ptr;
+}
+
+void
+convert_to_extended (dbl, ptr)
+ void * ptr;
+ double * dbl;
+{
+ *(double*)ptr = *dbl;
+}
+
+static int
+condition_true (cond, status_reg)
+ unsigned long cond;
+ unsigned long status_reg;
+{
+ if (cond == INST_AL || cond == INST_NV)
+ return 1;
+
+ switch (cond)
+ {
+ case INST_EQ:
+ return ((status_reg & FLAG_Z) != 0);
+ case INST_NE:
+ return ((status_reg & FLAG_Z) == 0);
+ case INST_CS:
+ return ((status_reg & FLAG_C) != 0);
+ case INST_CC:
+ return ((status_reg & FLAG_C) == 0);
+ case INST_MI:
+ return ((status_reg & FLAG_N) != 0);
+ case INST_PL:
+ return ((status_reg & FLAG_N) == 0);
+ case INST_VS:
+ return ((status_reg & FLAG_V) != 0);
+ case INST_VC:
+ return ((status_reg & FLAG_V) == 0);
+ case INST_HI:
+ return ((status_reg & (FLAG_C | FLAG_Z)) == FLAG_C);
+ case INST_LS:
+ return ((status_reg & (FLAG_C | FLAG_Z)) != FLAG_C);
+ case INST_GE:
+ return (((status_reg & FLAG_N) == 0) == ((status_reg & FLAG_V) == 0));
+ case INST_LT:
+ return (((status_reg & FLAG_N) == 0) != ((status_reg & FLAG_V) == 0));
+ case INST_GT:
+ return (((status_reg & FLAG_Z) == 0) &&
+ (((status_reg & FLAG_N) == 0) == ((status_reg & FLAG_V) == 0)));
+ case INST_LE:
+ return (((status_reg & FLAG_Z) != 0) ||
+ (((status_reg & FLAG_N) == 0) != ((status_reg & FLAG_V) == 0)));
+ }
+ return 1;
+}
+
+#define submask(x) ((1L << ((x) + 1)) - 1)
+#define bit(obj,st) (((obj) >> (st)) & 1)
+#define bits(obj,st,fn) (((obj) >> (st)) & submask ((fn) - (st)))
+#define sbits(obj,st,fn) \
+ ((long) (bits(obj,st,fn) | ((long) bit(obj,fn) * ~ submask (fn - st))))
+#define BranchDest(addr,instr) \
+ ((CORE_ADDR) (((long) (addr)) + 8 + (sbits (instr, 0, 23) << 2)))
+#define ARM_PC_32 1
+
+static unsigned long
+shifted_reg_val (inst, carry, pc_val, status_reg)
+ unsigned long inst;
+ int carry;
+ unsigned long pc_val;
+ unsigned long status_reg;
+{
+ unsigned long res, shift;
+ int rm = bits (inst, 0, 3);
+ unsigned long shifttype = bits (inst, 5, 6);
+
+ if (bit(inst, 4))
+ {
+ int rs = bits (inst, 8, 11);
+ shift = (rs == 15 ? pc_val + 8 : read_register (rs)) & 0xFF;
+ }
+ else
+ shift = bits (inst, 7, 11);
+
+ res = (rm == 15
+ ? ((pc_val | (ARM_PC_32 ? 0 : status_reg))
+ + (bit (inst, 4) ? 12 : 8))
+ : read_register (rm));
+
+ switch (shifttype)
+ {
+ case 0: /* LSL */
+ res = shift >= 32 ? 0 : res << shift;
+ break;
+
+ case 1: /* LSR */
+ res = shift >= 32 ? 0 : res >> shift;
+ break;
+
+ case 2: /* ASR */
+ if (shift >= 32) shift = 31;
+ res = ((res & 0x80000000L)
+ ? ~((~res) >> shift) : res >> shift);
+ break;
+
+ case 3: /* ROR/RRX */
+ shift &= 31;
+ if (shift == 0)
+ res = (res >> 1) | (carry ? 0x80000000L : 0);
+ else
+ res = (res >> shift) | (res << (32-shift));
+ break;
+ }
+
+ return res & 0xffffffff;
+}
+
+
+/* Return number of 1-bits in VAL. */
+
+static int
+bitcount (val)
+ unsigned long val;
+{
+ int nbits;
+ for (nbits = 0; val != 0; nbits++)
+ val &= val - 1; /* delete rightmost 1-bit in val */
+ return nbits;
+}
+
+
+static CORE_ADDR
+thumb_get_next_pc (pc)
+ CORE_ADDR pc;
+{
+ unsigned long pc_val = ((unsigned long)pc) + 4; /* PC after prefetch */
+ unsigned short inst1 = read_memory_integer (pc, 2);
+ CORE_ADDR nextpc = pc + 2; /* default is next instruction */
+ unsigned long offset;
+
+ if ((inst1 & 0xff00) == 0xbd00) /* pop {rlist, pc} */
+ {
+ CORE_ADDR sp;
+
+ /* Fetch the saved PC from the stack. It's stored above
+ all of the other registers. */
+ offset = bitcount (bits (inst1, 0, 7)) * REGISTER_SIZE;
+ sp = read_register (SP_REGNUM);
+ nextpc = (CORE_ADDR) read_memory_integer (sp + offset, 4);
+ nextpc = ADDR_BITS_REMOVE (nextpc);
+ if (nextpc == pc)
+ error ("Infinite loop detected");
+ }
+ else if ((inst1 & 0xf000) == 0xd000) /* conditional branch */
+ {
+ unsigned long status = read_register (PS_REGNUM);
+ unsigned long cond = bits (inst1, 8, 11);
+ if (cond != 0x0f && condition_true (cond, status)) /* 0x0f = SWI */
+ nextpc = pc_val + (sbits (inst1, 0, 7) << 1);
+ }
+ else if ((inst1 & 0xf800) == 0xe000) /* unconditional branch */
+ {
+ nextpc = pc_val + (sbits (inst1, 0, 10) << 1);
+ }
+ else if ((inst1 & 0xf800) == 0xf000) /* long branch with link */
+ {
+ unsigned short inst2 = read_memory_integer (pc + 2, 2);
+ offset = (sbits (inst1, 0, 10) << 12) + (bits (inst2, 0, 10) << 1);
+ nextpc = pc_val + offset;
+ }
+
+ return nextpc;
+}
+
+
+CORE_ADDR
+arm_get_next_pc (pc)
+ CORE_ADDR pc;
+{
+ unsigned long pc_val;
+ unsigned long this_instr;
+ unsigned long status;
+ CORE_ADDR nextpc;
+
+ if (arm_pc_is_thumb (pc))
+ return thumb_get_next_pc (pc);
+
+ pc_val = (unsigned long) pc;
+ this_instr = read_memory_integer (pc, 4);
+ status = read_register (PS_REGNUM);
+ nextpc = (CORE_ADDR) (pc_val + 4); /* Default case */
+
+ if (condition_true (bits (this_instr, 28, 31), status))
+ {
+ switch (bits (this_instr, 24, 27))
+ {
+ case 0x0: case 0x1: /* data processing */
+ case 0x2: case 0x3:
+ {
+ unsigned long operand1, operand2, result = 0;
+ unsigned long rn;
+ int c;
+
+ if (bits (this_instr, 12, 15) != 15)
+ break;
+
+ if (bits (this_instr, 22, 25) == 0
+ && bits (this_instr, 4, 7) == 9) /* multiply */
+ error ("Illegal update to pc in instruction");
+
+ /* Multiply into PC */
+ c = (status & FLAG_C) ? 1 : 0;
+ rn = bits (this_instr, 16, 19);
+ operand1 = (rn == 15) ? pc_val + 8 : read_register (rn);
+
+ if (bit (this_instr, 25))
+ {
+ unsigned long immval = bits (this_instr, 0, 7);
+ unsigned long rotate = 2 * bits (this_instr, 8, 11);
+ operand2 = ((immval >> rotate) | (immval << (32-rotate)))
+ & 0xffffffff;
+ }
+ else /* operand 2 is a shifted register */
+ operand2 = shifted_reg_val (this_instr, c, pc_val, status);
+
+ switch (bits (this_instr, 21, 24))
+ {
+ case 0x0: /*and*/
+ result = operand1 & operand2;
+ break;
+
+ case 0x1: /*eor*/
+ result = operand1 ^ operand2;
+ break;
+
+ case 0x2: /*sub*/
+ result = operand1 - operand2;
+ break;
+
+ case 0x3: /*rsb*/
+ result = operand2 - operand1;
+ break;
+
+ case 0x4: /*add*/
+ result = operand1 + operand2;
+ break;
+
+ case 0x5: /*adc*/
+ result = operand1 + operand2 + c;
+ break;
+
+ case 0x6: /*sbc*/
+ result = operand1 - operand2 + c;
+ break;
+
+ case 0x7: /*rsc*/
+ result = operand2 - operand1 + c;
+ break;
+
+ case 0x8: case 0x9: case 0xa: case 0xb: /* tst, teq, cmp, cmn */
+ result = (unsigned long) nextpc;
+ break;
+
+ case 0xc: /*orr*/
+ result = operand1 | operand2;
+ break;
+
+ case 0xd: /*mov*/
+ /* Always step into a function. */
+ result = operand2;
+ break;
+
+ case 0xe: /*bic*/
+ result = operand1 & ~operand2;
+ break;
+
+ case 0xf: /*mvn*/
+ result = ~operand2;
+ break;
+ }
+ nextpc = (CORE_ADDR) ADDR_BITS_REMOVE (result);
+
+ if (nextpc == pc)
+ error ("Infinite loop detected");
+ break;
+ }
+
+ case 0x4: case 0x5: /* data transfer */
+ case 0x6: case 0x7:
+ if (bit (this_instr, 20))
+ {
+ /* load */
+ if (bits (this_instr, 12, 15) == 15)
+ {
+ /* rd == pc */
+ unsigned long rn;
+ unsigned long base;
+
+ if (bit (this_instr, 22))
+ error ("Illegal update to pc in instruction");
+
+ /* byte write to PC */
+ rn = bits (this_instr, 16, 19);
+ base = (rn == 15) ? pc_val + 8 : read_register (rn);
+ if (bit (this_instr, 24))
+ {
+ /* pre-indexed */
+ int c = (status & FLAG_C) ? 1 : 0;
+ unsigned long offset =
+ (bit (this_instr, 25)
+ ? shifted_reg_val (this_instr, c, pc_val)
+ : bits (this_instr, 0, 11));
+
+ if (bit (this_instr, 23))
+ base += offset;
+ else
+ base -= offset;
+ }
+ nextpc = (CORE_ADDR) read_memory_integer ((CORE_ADDR) base,
+ 4);
+
+ nextpc = ADDR_BITS_REMOVE (nextpc);
+
+ if (nextpc == pc)
+ error ("Infinite loop detected");
+ }
+ }
+ break;
+
+ case 0x8: case 0x9: /* block transfer */
+ if (bit (this_instr, 20))
+ {
+ /* LDM */
+ if (bit (this_instr, 15))
+ {
+ /* loading pc */
+ int offset = 0;
+
+ if (bit (this_instr, 23))
+ {
+ /* up */
+ unsigned long reglist = bits (this_instr, 0, 14);
+ offset = bitcount (reglist) * 4;
+ if (bit (this_instr, 24)) /* pre */
+ offset += 4;
+ }
+ else if (bit (this_instr, 24))
+ offset = -4;
+
+ {
+ unsigned long rn_val =
+ read_register (bits (this_instr, 16, 19));
+ nextpc =
+ (CORE_ADDR) read_memory_integer ((CORE_ADDR) (rn_val
+ + offset),
+ 4);
+ }
+ nextpc = ADDR_BITS_REMOVE (nextpc);
+ if (nextpc == pc)
+ error ("Infinite loop detected");
+ }
+ }
+ break;
+
+ case 0xb: /* branch & link */
+ case 0xa: /* branch */
+ {
+ nextpc = BranchDest (pc, this_instr);
+
+ nextpc = ADDR_BITS_REMOVE (nextpc);
+ if (nextpc == pc)
+ error ("Infinite loop detected");
+ break;
+ }
+
+ case 0xc: case 0xd:
+ case 0xe: /* coproc ops */
+ case 0xf: /* SWI */
+ break;
+
+ default:
+ fprintf (stderr, "Bad bit-field extraction\n");
+ return (pc);
+ }
+ }
+
+ return nextpc;
+}
+
+#include "bfd-in2.h"
+#include "libcoff.h"
+
+static int
+gdb_print_insn_arm (memaddr, info)
+ bfd_vma memaddr;
+ disassemble_info * info;
+{
+ if (arm_pc_is_thumb (memaddr))
+ {
+ static asymbol * asym;
+ static combined_entry_type ce;
+ static struct coff_symbol_struct csym;
+ static struct _bfd fake_bfd;
+ static bfd_target fake_target;
+
+ if (csym.native == NULL)
+ {
+ /* Create a fake symbol vector containing a Thumb symbol. This is
+ solely so that the code in print_insn_little_arm() and
+ print_insn_big_arm() in opcodes/arm-dis.c will detect the presence
+ of a Thumb symbol and switch to decoding Thumb instructions. */
+
+ fake_target.flavour = bfd_target_coff_flavour;
+ fake_bfd.xvec = & fake_target;
+ ce.u.syment.n_sclass = C_THUMBEXTFUNC;
+ csym.native = & ce;
+ csym.symbol.the_bfd = & fake_bfd;
+ csym.symbol.name = "fake";
+ asym = (asymbol *) & csym;
+ }
+
+ memaddr = UNMAKE_THUMB_ADDR (memaddr);
+ info->symbols = & asym;
+ }
+ else
+ info->symbols = NULL;
+
+ if (TARGET_BYTE_ORDER == BIG_ENDIAN)
+ return print_insn_big_arm (memaddr, info);
+ else
+ return print_insn_little_arm (memaddr, info);
+}
+
+/* Sequence of bytes for breakpoint instruction. */
+#define ARM_LE_BREAKPOINT {0xFE,0xDE,0xFF,0xE7} /* Recognized illegal opcodes */
+#define ARM_BE_BREAKPOINT {0xE7,0xFF,0xDE,0xFE}
+#define THUMB_LE_BREAKPOINT {0xfe,0xdf}
+#define THUMB_BE_BREAKPOINT {0xdf,0xfe}
+
+/* The following has been superseded by BREAKPOINT_FOR_PC, but
+ is defined merely to keep mem-break.c happy. */
+#define LITTLE_BREAKPOINT ARM_LE_BREAKPOINT
+#define BIG_BREAKPOINT ARM_BE_BREAKPOINT
+
+/* This function implements the BREAKPOINT_FROM_PC macro. It uses the program
+ counter value to determine whether a 16- or 32-bit breakpoint should be
+ used. It returns a pointer to a string of bytes that encode a breakpoint
+ instruction, stores the length of the string to *lenptr, and adjusts pc
+ (if necessary) to point to the actual memory location where the
+ breakpoint should be inserted. */
+
+unsigned char *
+arm_breakpoint_from_pc (pcptr, lenptr)
+ CORE_ADDR * pcptr;
+ int * lenptr;
+{
+ if (arm_pc_is_thumb (*pcptr) || arm_pc_is_thumb_dummy (*pcptr))
+ {
+ if (TARGET_BYTE_ORDER == BIG_ENDIAN)
+ {
+ static char thumb_breakpoint[] = THUMB_BE_BREAKPOINT;
+ *pcptr = UNMAKE_THUMB_ADDR (*pcptr);
+ *lenptr = sizeof (thumb_breakpoint);
+ return thumb_breakpoint;
+ }
+ else
+ {
+ static char thumb_breakpoint[] = THUMB_LE_BREAKPOINT;
+ *pcptr = UNMAKE_THUMB_ADDR (*pcptr);
+ *lenptr = sizeof (thumb_breakpoint);
+ return thumb_breakpoint;
+ }
+ }
+ else
+ {
+ if (TARGET_BYTE_ORDER == BIG_ENDIAN)
+ {
+ static char arm_breakpoint[] = ARM_BE_BREAKPOINT;
+ *lenptr = sizeof (arm_breakpoint);
+ return arm_breakpoint;
+ }
+ else
+ {
+ static char arm_breakpoint[] = ARM_LE_BREAKPOINT;
+ *lenptr = sizeof (arm_breakpoint);
+ return arm_breakpoint;
+ }
+ }
+}
+/* Return non-zero if the PC is inside a call thunk (aka stub or trampoline).
+ This implements the IN_SOLIB_CALL_TRAMPOLINE macro. */
+
+int
+arm_in_call_stub (pc, name)
+ CORE_ADDR pc;
+ char * name;
+{
+ CORE_ADDR start_addr;
+
+ /* Find the starting address of the function containing the PC. If the
+ caller didn't give us a name, look it up at the same time. */
+ if (find_pc_partial_function (pc, name ? NULL : &name, &start_addr, NULL) == 0)
+ return 0;
+
+ return strncmp (name, "_call_via_r", 11) == 0;
+}
+
+
+/* If PC is in a Thumb call or return stub, return the address of the target
+ PC, which is in a register. The thunk functions are called _called_via_xx,
+ where x is the register name. The possible names are r0-r9, sl, fp, ip,
+ sp, and lr. */
+
+CORE_ADDR
+arm_skip_stub (pc)
+ CORE_ADDR pc;
+{
+ char * name;
+ CORE_ADDR start_addr;
+
+ /* Find the starting address and name of the function containing the PC. */
+ if (find_pc_partial_function (pc, &name, &start_addr, NULL) == 0)
+ return 0;
+
+ /* Call thunks always start with "_call_via_". */
+ if (strncmp (name, "_call_via_", 10) == 0)
+ {
+ /* Use the name suffix to determine which register contains
+ the target PC. */
+ static char *table[15] =
+ { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
+ "r8", "r9", "sl", "fp", "ip", "sp", "lr"
+ };
+ int regno;
+
+ for (regno = 0; regno <= 14; regno++)
+ if (strcmp (&name[10], table[regno]) == 0)
+ return read_register (regno);
+ }
+ return 0; /* not a stub */
+}
+
+
+void
+_initialize_arm_tdep ()
+{
+ tm_print_insn = gdb_print_insn_arm;
+
+ add_com ("othernames", class_obscure, arm_othernames,
+ "Switch to the other set of register names.");
+
+ /* ??? Maybe this should be a boolean. */
+ add_show_from_set (add_set_cmd ("apcs32", no_class,
+ var_zinteger, (char *)&arm_apcs_32,
+ "Set usage of ARM 32-bit mode.\n", &setlist),
+ & showlist);
+
+}
+
+/* Test whether the coff symbol specific value corresponds to a Thumb function */
+int
+coff_sym_is_thumb(int val)
+{
+ return (val == C_THUMBEXT ||
+ val == C_THUMBSTAT ||
+ val == C_THUMBEXTFUNC ||
+ val == C_THUMBSTATFUNC ||
+ val == C_THUMBLABEL);
+}
diff --git a/gdb/arm-xdep.c b/gdb/arm-xdep.c
new file mode 100644
index 00000000000..f0d806e82e7
--- /dev/null
+++ b/gdb/arm-xdep.c
@@ -0,0 +1,559 @@
+/* Acorn Risc Machine host machine support.
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "frame.h"
+#include "inferior.h"
+#include "arm-opcode.h"
+
+#include <sys/param.h>
+#include <sys/dir.h>
+#include <signal.h>
+#include <sys/ioctl.h>
+#include <sys/ptrace.h>
+#include <machine/reg.h>
+
+#define N_TXTADDR(hdr) 0x8000
+#define N_DATADDR(hdr) (hdr.a_text + 0x8000)
+
+#include "gdbcore.h"
+
+#include <sys/user.h> /* After a.out.h */
+#include <sys/file.h>
+#include "gdb_stat.h"
+
+#include <errno.h>
+
+void
+fetch_inferior_registers (regno)
+ int regno; /* Original value discarded */
+{
+ register unsigned int regaddr;
+ char buf[MAX_REGISTER_RAW_SIZE];
+ register int i;
+
+ struct user u;
+ unsigned int offset = (char *) &u.u_ar0 - (char *) &u;
+ offset = ptrace (PT_READ_U, inferior_pid, (PTRACE_ARG3_TYPE) offset, 0)
+ - KERNEL_U_ADDR;
+
+ registers_fetched ();
+
+ for (regno = 0; regno < 16; regno++)
+ {
+ regaddr = offset + regno * 4;
+ *(int *)&buf[0] = ptrace (PT_READ_U, inferior_pid,
+ (PTRACE_ARG3_TYPE) regaddr, 0);
+ if (regno == PC_REGNUM)
+ *(int *)&buf[0] = GET_PC_PART(*(int *)&buf[0]);
+ supply_register (regno, buf);
+ }
+ *(int *)&buf[0] = ptrace (PT_READ_U, inferior_pid,
+ (PTRACE_ARG3_TYPE) (offset + PC*4), 0);
+ supply_register (PS_REGNUM, buf); /* set virtual register ps same as pc */
+
+ /* read the floating point registers */
+ offset = (char *) &u.u_fp_regs - (char *)&u;
+ *(int *)buf = ptrace (PT_READ_U, inferior_pid, (PTRACE_ARG3_TYPE) offset, 0);
+ supply_register (FPS_REGNUM, buf);
+ for (regno = 16; regno < 24; regno++) {
+ regaddr = offset + 4 + 12 * (regno - 16);
+ for (i = 0; i < 12; i += sizeof(int))
+ *(int *) &buf[i] = ptrace (PT_READ_U, inferior_pid,
+ (PTRACE_ARG3_TYPE) (regaddr + i), 0);
+ supply_register (regno, buf);
+ }
+}
+
+/* Store our register values back into the inferior.
+ If REGNO is -1, do this for all registers.
+ Otherwise, REGNO specifies which register (so we can save time). */
+
+void
+store_inferior_registers (regno)
+ int regno;
+{
+ register unsigned int regaddr;
+ char buf[80];
+
+ struct user u;
+ unsigned long value;
+ unsigned int offset = (char *) &u.u_ar0 - (char *) &u;
+ offset = ptrace (PT_READ_U, inferior_pid, (PTRACE_ARG3_TYPE) offset, 0)
+ - KERNEL_U_ADDR;
+
+ if (regno >= 0) {
+ if (regno >= 16) return;
+ regaddr = offset + 4 * regno;
+ errno = 0;
+ value = read_register(regno);
+ if (regno == PC_REGNUM)
+ value = SET_PC_PART(read_register (PS_REGNUM), value);
+ ptrace (PT_WRITE_U, inferior_pid, (PTRACE_ARG3_TYPE) regaddr, value);
+ if (errno != 0)
+ {
+ sprintf (buf, "writing register number %d", regno);
+ perror_with_name (buf);
+ }
+ }
+ else for (regno = 0; regno < 15; regno++)
+ {
+ regaddr = offset + regno * 4;
+ errno = 0;
+ value = read_register(regno);
+ if (regno == PC_REGNUM)
+ value = SET_PC_PART(read_register (PS_REGNUM), value);
+ ptrace (6, inferior_pid, (PTRACE_ARG3_TYPE) regaddr, value);
+ if (errno != 0)
+ {
+ sprintf (buf, "writing all regs, number %d", regno);
+ perror_with_name (buf);
+ }
+ }
+}
+
+/* Work with core dump and executable files, for GDB.
+ This code would be in corefile.c if it weren't machine-dependent. */
+
+/* Structure to describe the chain of shared libraries used
+ by the execfile.
+ e.g. prog shares Xt which shares X11 which shares c. */
+
+struct shared_library {
+ struct exec_header header;
+ char name[SHLIBLEN];
+ CORE_ADDR text_start; /* CORE_ADDR of 1st byte of text, this file */
+ long data_offset; /* offset of data section in file */
+ int chan; /* file descriptor for the file */
+ struct shared_library *shares; /* library this one shares */
+};
+static struct shared_library *shlib = 0;
+
+/* Hook for `exec_file_command' command to call. */
+
+extern void (*exec_file_display_hook) ();
+
+static CORE_ADDR unshared_text_start;
+
+/* extended header from exec file (for shared library info) */
+
+static struct exec_header exec_header;
+
+void
+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 program with \"kill\".");
+ corechan = open (filename, O_RDONLY, 0);
+ if (corechan < 0)
+ perror_with_name (filename);
+ /* 4.2-style (and perhaps also sysV-style) core dump file. */
+ {
+ struct user u;
+
+ unsigned int reg_offset, fp_reg_offset;
+
+ val = myread (corechan, &u, sizeof u);
+ if (val < 0)
+ perror_with_name ("Not a core file: reading upage");
+ if (val != sizeof u)
+ error ("Not a core file: could only read %d bytes", val);
+
+ /* We are depending on exec_file_command having been called
+ previously to set exec_data_start. Since the executable
+ and the core file share the same text segment, the address
+ of the data segment will be the same in both. */
+ data_start = exec_data_start;
+
+ data_end = data_start + NBPG * u.u_dsize;
+ stack_start = stack_end - NBPG * u.u_ssize;
+ data_offset = NBPG * UPAGES;
+ stack_offset = NBPG * (UPAGES + u.u_dsize);
+
+ /* Some machines put an absolute address in here and some put
+ the offset in the upage of the regs. */
+ reg_offset = (int) u.u_ar0;
+ if (reg_offset > NBPG * UPAGES)
+ reg_offset -= KERNEL_U_ADDR;
+ fp_reg_offset = (char *) &u.u_fp_regs - (char *)&u;
+
+ /* I don't know where to find this info.
+ So, for now, mark it as not available. */
+ N_SET_MAGIC (core_aouthdr, 0);
+
+ /* Read the register values out of the core file and store
+ them where `read_register' will find them. */
+
+ {
+ register int regno;
+
+ for (regno = 0; regno < NUM_REGS; regno++)
+ {
+ char buf[MAX_REGISTER_RAW_SIZE];
+
+ if (regno < 16)
+ val = lseek (corechan, reg_offset + 4 * regno, 0);
+ else if (regno < 24)
+ val = lseek (corechan, fp_reg_offset + 4 + 12*(regno - 24), 0);
+ else if (regno == 24)
+ val = lseek (corechan, fp_reg_offset, 0);
+ else if (regno == 25)
+ val = lseek (corechan, reg_offset + 4 * PC, 0);
+ if (val < 0
+ || (val = myread (corechan, buf, sizeof buf)) < 0)
+ {
+ char * buffer = (char *) alloca (strlen (REGISTER_NAME (regno))
+ + 30);
+ strcpy (buffer, "Reading register ");
+ strcat (buffer, REGISTER_NAME (regno));
+
+ perror_with_name (buffer);
+ }
+
+ if (regno == PC_REGNUM)
+ *(int *)buf = GET_PC_PART(*(int *)buf);
+ supply_register (regno, buf);
+ }
+ }
+ }
+ if (filename[0] == '/')
+ corefile = savestring (filename, strlen (filename));
+ else
+ {
+ corefile = concat (current_directory, "/", filename, NULL);
+ }
+
+ flush_cached_frames ();
+ select_frame (get_current_frame (), 0);
+ validate_files ();
+ }
+ else if (from_tty)
+ printf ("No core file now.\n");
+}
+
+#if 0
+/* Work with core dump and executable files, for GDB.
+ This code would be in corefile.c if it weren't machine-dependent. */
+
+/* Structure to describe the chain of shared libraries used
+ by the execfile.
+ e.g. prog shares Xt which shares X11 which shares c. */
+
+struct shared_library {
+ struct exec_header header;
+ char name[SHLIBLEN];
+ CORE_ADDR text_start; /* CORE_ADDR of 1st byte of text, this file */
+ long data_offset; /* offset of data section in file */
+ int chan; /* file descriptor for the file */
+ struct shared_library *shares; /* library this one shares */
+};
+static struct shared_library *shlib = 0;
+
+/* Hook for `exec_file_command' command to call. */
+
+extern void (*exec_file_display_hook) ();
+
+static CORE_ADDR unshared_text_start;
+
+/* extended header from exec file (for shared library info) */
+
+static struct exec_header exec_header;
+
+void
+exec_file_command (filename, from_tty)
+ char *filename;
+ int from_tty;
+{
+ int val;
+
+ /* Eliminate all traces of old exec file.
+ Mark text segment as empty. */
+
+ if (execfile)
+ free (execfile);
+ execfile = 0;
+ data_start = 0;
+ data_end -= exec_data_start;
+ text_start = 0;
+ unshared_text_start = 0;
+ text_end = 0;
+ exec_data_start = 0;
+ exec_data_end = 0;
+ if (execchan >= 0)
+ close (execchan);
+ execchan = -1;
+ if (shlib) {
+ close_shared_library(shlib);
+ shlib = 0;
+ }
+
+ /* Now open and digest the file the user requested, if any. */
+
+ if (filename)
+ {
+ filename = tilde_expand (filename);
+ make_cleanup (free, filename);
+
+ execchan = openp (getenv ("PATH"), 1, filename, O_RDONLY, 0,
+ &execfile);
+ if (execchan < 0)
+ perror_with_name (filename);
+
+ {
+ struct stat st_exec;
+
+#ifdef HEADER_SEEK_FD
+ HEADER_SEEK_FD (execchan);
+#endif
+
+ val = myread (execchan, &exec_header, sizeof exec_header);
+ exec_aouthdr = exec_header.a_exec;
+
+ if (val < 0)
+ perror_with_name (filename);
+
+ text_start = 0x8000;
+
+ /* Look for shared library if needed */
+ if (exec_header.a_exec.a_magic & MF_USES_SL)
+ shlib = open_shared_library(exec_header.a_shlibname, text_start);
+
+ text_offset = N_TXTOFF (exec_aouthdr);
+ exec_data_offset = N_TXTOFF (exec_aouthdr) + exec_aouthdr.a_text;
+
+ if (shlib) {
+ unshared_text_start = shared_text_end(shlib) & ~0x7fff;
+ stack_start = shlib->header.a_exec.a_sldatabase;
+ stack_end = STACK_END_ADDR;
+ } else
+ unshared_text_start = 0x8000;
+ text_end = unshared_text_start + exec_aouthdr.a_text;
+
+ exec_data_start = unshared_text_start + exec_aouthdr.a_text;
+ exec_data_end = exec_data_start + exec_aouthdr.a_data;
+
+ data_start = exec_data_start;
+ data_end += exec_data_start;
+
+ fstat (execchan, &st_exec);
+ exec_mtime = st_exec.st_mtime;
+ }
+
+ validate_files ();
+ }
+ else if (from_tty)
+ printf ("No executable file now.\n");
+
+ /* Tell display code (if any) about the changed file name. */
+ if (exec_file_display_hook)
+ (*exec_file_display_hook) (filename);
+}
+#endif
+
+#if 0
+/* Read from the program's memory (except for inferior processes).
+ This function is misnamed, since it only reads, never writes; and
+ since it will use the core file and/or executable file as necessary.
+
+ It should be extended to write as well as read, FIXME, for patching files.
+
+ Return 0 if address could be read, EIO if addresss out of bounds. */
+
+int
+xfer_core_file (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+{
+ register int i;
+ register int val;
+ int xferchan;
+ char **xferfile;
+ int fileptr;
+ int returnval = 0;
+
+ while (len > 0)
+ {
+ xferfile = 0;
+ xferchan = 0;
+
+ /* Determine which file the next bunch of addresses reside in,
+ and where in the file. Set the file's read/write pointer
+ to point at the proper place for the desired address
+ and set xferfile and xferchan for the correct file.
+
+ If desired address is nonexistent, leave them zero.
+
+ i is set to the number of bytes that can be handled
+ along with the next address.
+
+ We put the most likely tests first for efficiency. */
+
+ /* Note that if there is no core file
+ data_start and data_end are equal. */
+ if (memaddr >= data_start && memaddr < data_end)
+ {
+ i = min (len, data_end - memaddr);
+ fileptr = memaddr - data_start + data_offset;
+ xferfile = &corefile;
+ xferchan = corechan;
+ }
+ /* Note that if there is no core file
+ stack_start and stack_end define the shared library data. */
+ else if (memaddr >= stack_start && memaddr < stack_end)
+ {
+ if (corechan < 0) {
+ struct shared_library *lib;
+ for (lib = shlib; lib; lib = lib->shares)
+ if (memaddr >= lib->header.a_exec.a_sldatabase &&
+ memaddr < lib->header.a_exec.a_sldatabase +
+ lib->header.a_exec.a_data)
+ break;
+ if (lib) {
+ i = min (len, lib->header.a_exec.a_sldatabase +
+ lib->header.a_exec.a_data - memaddr);
+ fileptr = lib->data_offset + memaddr -
+ lib->header.a_exec.a_sldatabase;
+ xferfile = execfile;
+ xferchan = lib->chan;
+ }
+ } else {
+ i = min (len, stack_end - memaddr);
+ fileptr = memaddr - stack_start + stack_offset;
+ xferfile = &corefile;
+ xferchan = corechan;
+ }
+ }
+ else if (corechan < 0
+ && memaddr >= exec_data_start && memaddr < exec_data_end)
+ {
+ i = min (len, exec_data_end - memaddr);
+ fileptr = memaddr - exec_data_start + exec_data_offset;
+ xferfile = &execfile;
+ xferchan = execchan;
+ }
+ else if (memaddr >= text_start && memaddr < text_end)
+ {
+ struct shared_library *lib;
+ for (lib = shlib; lib; lib = lib->shares)
+ if (memaddr >= lib->text_start &&
+ memaddr < lib->text_start + lib->header.a_exec.a_text)
+ break;
+ if (lib) {
+ i = min (len, lib->header.a_exec.a_text +
+ lib->text_start - memaddr);
+ fileptr = memaddr - lib->text_start + text_offset;
+ xferfile = &execfile;
+ xferchan = lib->chan;
+ } else {
+ i = min (len, text_end - memaddr);
+ fileptr = memaddr - unshared_text_start + text_offset;
+ xferfile = &execfile;
+ xferchan = execchan;
+ }
+ }
+ else if (memaddr < text_start)
+ {
+ i = min (len, text_start - memaddr);
+ }
+ else if (memaddr >= text_end
+ && memaddr < (corechan >= 0? data_start : exec_data_start))
+ {
+ i = min (len, data_start - memaddr);
+ }
+ else if (corechan >= 0
+ && memaddr >= data_end && memaddr < stack_start)
+ {
+ i = min (len, stack_start - memaddr);
+ }
+ else if (corechan < 0 && memaddr >= exec_data_end)
+ {
+ i = min (len, - memaddr);
+ }
+ else if (memaddr >= stack_end && stack_end != 0)
+ {
+ i = min (len, - memaddr);
+ }
+ else
+ {
+ /* Address did not classify into one of the known ranges.
+ This shouldn't happen; we catch the endpoints. */
+ fatal ("Internal: Bad case logic in xfer_core_file.");
+ }
+
+ /* Now we know which file to use.
+ Set up its pointer and transfer the data. */
+ if (xferfile)
+ {
+ if (*xferfile == 0)
+ if (xferfile == &execfile)
+ error ("No program file to examine.");
+ else
+ error ("No core dump file or running program to examine.");
+ val = lseek (xferchan, fileptr, 0);
+ if (val < 0)
+ perror_with_name (*xferfile);
+ val = myread (xferchan, myaddr, i);
+ if (val < 0)
+ perror_with_name (*xferfile);
+ }
+ /* If this address is for nonexistent memory,
+ read zeros if reading, or do nothing if writing.
+ Actually, we never right. */
+ else
+ {
+ memset (myaddr, '\0', i);
+ returnval = EIO;
+ }
+
+ memaddr += i;
+ myaddr += i;
+ len -= i;
+ }
+ return returnval;
+}
+#endif
diff --git a/gdb/ax-gdb.c b/gdb/ax-gdb.c
new file mode 100644
index 00000000000..c518e19e0da
--- /dev/null
+++ b/gdb/ax-gdb.c
@@ -0,0 +1,1942 @@
+/* GDB-specific functions for operating on agent expressions
+ Copyright 1998 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* $Id$ */
+
+#include "defs.h"
+#include "symtab.h"
+#include "symfile.h"
+#include "gdbtypes.h"
+#include "value.h"
+#include "expression.h"
+#include "command.h"
+#include "gdbcmd.h"
+#include "frame.h"
+#include "target.h"
+#include "ax.h"
+#include "ax-gdb.h"
+
+/* Probably the best way to read this file is to start with the types
+ and enums in ax-gdb.h, and then look at gen_expr, towards the
+ bottom; that's the main function that looks at the GDB expressions
+ and calls everything else to generate code.
+
+ I'm beginning to wonder whether it wouldn't be nicer to internally
+ generate trees, with types, and then spit out the bytecode in
+ linear form afterwards; we could generate fewer `swap', `ext', and
+ `zero_ext' bytecodes that way; it would make good constant folding
+ easier, too. But at the moment, I think we should be willing to
+ pay for the simplicity of this code with less-than-optimal bytecode
+ strings.
+
+ Remember, "GBD" stands for "Great Britain, Dammit!" So be careful. */
+
+
+
+/* Prototypes for local functions. */
+
+/* There's a standard order to the arguments of these functions:
+ union exp_element ** --- pointer into expression
+ struct agent_expr * --- agent expression buffer to generate code into
+ struct axs_value * --- describes value left on top of stack */
+
+static struct value *const_var_ref PARAMS ((struct symbol *var));
+static struct value *const_expr PARAMS ((union exp_element **pc));
+static struct value *maybe_const_expr PARAMS ((union exp_element **pc));
+
+static void gen_traced_pop PARAMS ((struct agent_expr *, struct axs_value *));
+
+static void gen_sign_extend PARAMS ((struct agent_expr *, struct type *));
+static void gen_extend PARAMS ((struct agent_expr *, struct type *));
+static void gen_fetch PARAMS ((struct agent_expr *, struct type *));
+static void gen_left_shift PARAMS ((struct agent_expr *, int));
+
+
+static void gen_frame_args_address PARAMS ((struct agent_expr *));
+static void gen_frame_locals_address PARAMS ((struct agent_expr *));
+static void gen_offset PARAMS ((struct agent_expr *ax, int offset));
+static void gen_sym_offset PARAMS ((struct agent_expr *, struct symbol *));
+static void gen_var_ref PARAMS ((struct agent_expr *ax,
+ struct axs_value *value,
+ struct symbol *var));
+
+
+static void gen_int_literal PARAMS ((struct agent_expr *ax,
+ struct axs_value *value,
+ LONGEST k, struct type *type));
+
+
+static void require_rvalue PARAMS ((struct agent_expr *ax,
+ struct axs_value *value));
+static void gen_usual_unary PARAMS ((struct agent_expr *ax,
+ struct axs_value *value));
+static int type_wider_than PARAMS ((struct type *type1,
+ struct type *type2));
+static struct type *max_type PARAMS ((struct type *type1,
+ struct type *type2));
+static void gen_conversion PARAMS ((struct agent_expr *ax,
+ struct type *from,
+ struct type *to));
+static int is_nontrivial_conversion PARAMS ((struct type *from,
+ struct type *to));
+static void gen_usual_arithmetic PARAMS ((struct agent_expr *ax,
+ struct axs_value *value1,
+ struct axs_value *value2));
+static void gen_integral_promotions PARAMS ((struct agent_expr *ax,
+ struct axs_value *value));
+static void gen_cast PARAMS ((struct agent_expr *ax,
+ struct axs_value *value,
+ struct type *type));
+static void gen_scale PARAMS ((struct agent_expr *ax,
+ enum agent_op op,
+ struct type *type));
+static void gen_add PARAMS ((struct agent_expr *ax,
+ struct axs_value *value,
+ struct axs_value *value1,
+ struct axs_value *value2,
+ char *name));
+static void gen_sub PARAMS ((struct agent_expr *ax,
+ struct axs_value *value,
+ struct axs_value *value1,
+ struct axs_value *value2));
+static void gen_binop PARAMS ((struct agent_expr *ax,
+ struct axs_value *value,
+ struct axs_value *value1,
+ struct axs_value *value2,
+ enum agent_op op,
+ enum agent_op op_unsigned,
+ int may_carry,
+ char *name));
+static void gen_logical_not PARAMS ((struct agent_expr *ax,
+ struct axs_value *value));
+static void gen_complement PARAMS ((struct agent_expr *ax,
+ struct axs_value *value));
+static void gen_deref PARAMS ((struct agent_expr *, struct axs_value *));
+static void gen_address_of PARAMS ((struct agent_expr *, struct axs_value *));
+static int find_field PARAMS ((struct type *type, char *name));
+static void gen_bitfield_ref PARAMS ((struct agent_expr *ax,
+ struct axs_value *value,
+ struct type *type,
+ int start, int end));
+static void gen_struct_ref PARAMS ((struct agent_expr *ax,
+ struct axs_value *value,
+ char *field,
+ char *operator_name,
+ char *operand_name));
+static void gen_repeat PARAMS ((union exp_element **pc,
+ struct agent_expr *ax,
+ struct axs_value *value));
+static void gen_sizeof PARAMS ((union exp_element **pc,
+ struct agent_expr *ax,
+ struct axs_value *value));
+static void gen_expr PARAMS ((union exp_element **pc,
+ struct agent_expr *ax,
+ struct axs_value *value));
+
+static void print_axs_value PARAMS ((GDB_FILE *f, struct axs_value *value));
+static void agent_command PARAMS ((char *exp, int from_tty));
+
+
+/* Detecting constant expressions. */
+
+/* If the variable reference at *PC is a constant, return its value.
+ Otherwise, return zero.
+
+ Hey, Wally! How can a variable reference be a constant?
+
+ Well, Beav, this function really handles the OP_VAR_VALUE operator,
+ not specifically variable references. GDB uses OP_VAR_VALUE to
+ refer to any kind of symbolic reference: function names, enum
+ elements, and goto labels are all handled through the OP_VAR_VALUE
+ operator, even though they're constants. It makes sense given the
+ situation.
+
+ Gee, Wally, don'cha wonder sometimes if data representations that
+ subvert commonly accepted definitions of terms in favor of heavily
+ context-specific interpretations are really just a tool of the
+ programming hegemony to preserve their power and exclude the
+ proletariat? */
+
+static struct value *
+const_var_ref (var)
+ struct symbol *var;
+{
+ struct type *type = SYMBOL_TYPE (var);
+
+ switch (SYMBOL_CLASS (var))
+ {
+ case LOC_CONST:
+ return value_from_longest (type, (LONGEST) SYMBOL_VALUE (var));
+
+ case LOC_LABEL:
+ return value_from_longest (type, (LONGEST) SYMBOL_VALUE_ADDRESS (var));
+
+ default:
+ return 0;
+ }
+}
+
+
+/* If the expression starting at *PC has a constant value, return it.
+ Otherwise, return zero. If we return a value, then *PC will be
+ advanced to the end of it. If we return zero, *PC could be
+ anywhere. */
+static struct value *
+const_expr (pc)
+ union exp_element **pc;
+{
+ enum exp_opcode op = (*pc)->opcode;
+ struct value *v1;
+
+ switch (op)
+ {
+ case OP_LONG:
+ {
+ struct type *type = (*pc)[1].type;
+ LONGEST k = (*pc)[2].longconst;
+ (*pc) += 4;
+ return value_from_longest (type, k);
+ }
+
+ case OP_VAR_VALUE:
+ {
+ struct value *v = const_var_ref ((*pc)[2].symbol);
+ (*pc) += 4;
+ return v;
+ }
+
+ /* We could add more operators in here. */
+
+ case UNOP_NEG:
+ (*pc)++;
+ v1 = const_expr (pc);
+ if (v1)
+ return value_neg (v1);
+ else
+ return 0;
+
+ default:
+ return 0;
+ }
+}
+
+
+/* Like const_expr, but guarantee also that *PC is undisturbed if the
+ expression is not constant. */
+static struct value *
+maybe_const_expr (pc)
+ union exp_element **pc;
+{
+ union exp_element *tentative_pc = *pc;
+ struct value *v = const_expr (&tentative_pc);
+
+ /* If we got a value, then update the real PC. */
+ if (v)
+ *pc = tentative_pc;
+
+ return v;
+}
+
+
+/* Generating bytecode from GDB expressions: general assumptions */
+
+/* Here are a few general assumptions made throughout the code; if you
+ want to make a change that contradicts one of these, then you'd
+ better scan things pretty thoroughly.
+
+ - We assume that all values occupy one stack element. For example,
+ sometimes we'll swap to get at the left argument to a binary
+ operator. If we decide that void values should occupy no stack
+ elements, or that synthetic arrays (whose size is determined at
+ run time, created by the `@' operator) should occupy two stack
+ elements (address and length), then this will cause trouble.
+
+ - We assume the stack elements are infinitely wide, and that we
+ don't have to worry what happens if the user requests an
+ operation that is wider than the actual interpreter's stack.
+ That is, it's up to the interpreter to handle directly all the
+ integer widths the user has access to. (Woe betide the language
+ with bignums!)
+
+ - We don't support side effects. Thus, we don't have to worry about
+ GCC's generalized lvalues, function calls, etc.
+
+ - We don't support floating point. Many places where we switch on
+ some type don't bother to include cases for floating point; there
+ may be even more subtle ways this assumption exists. For
+ example, the arguments to % must be integers.
+
+ - We assume all subexpressions have a static, unchanging type. If
+ we tried to support convenience variables, this would be a
+ problem.
+
+ - All values on the stack should always be fully zero- or
+ sign-extended.
+
+ (I wasn't sure whether to choose this or its opposite --- that
+ only addresses are assumed extended --- but it turns out that
+ neither convention completely eliminates spurious extend
+ operations (if everything is always extended, then you have to
+ extend after add, because it could overflow; if nothing is
+ extended, then you end up producing extends whenever you change
+ sizes), and this is simpler.) */
+
+
+/* Generating bytecode from GDB expressions: the `trace' kludge */
+
+/* The compiler in this file is a general-purpose mechanism for
+ translating GDB expressions into bytecode. One ought to be able to
+ find a million and one uses for it.
+
+ However, at the moment it is HOPELESSLY BRAIN-DAMAGED for the sake
+ of expediency. Let he who is without sin cast the first stone.
+
+ For the data tracing facility, we need to insert `trace' bytecodes
+ before each data fetch; this records all the memory that the
+ expression touches in the course of evaluation, so that memory will
+ be available when the user later tries to evaluate the expression
+ in GDB.
+
+ This should be done (I think) in a post-processing pass, that walks
+ an arbitrary agent expression and inserts `trace' operations at the
+ appropriate points. But it's much faster to just hack them
+ directly into the code. And since we're in a crunch, that's what
+ I've done.
+
+ Setting the flag trace_kludge to non-zero enables the code that
+ emits the trace bytecodes at the appropriate points. */
+static int trace_kludge;
+
+/* Trace the lvalue on the stack, if it needs it. In either case, pop
+ the value. Useful on the left side of a comma, and at the end of
+ an expression being used for tracing. */
+static void
+gen_traced_pop (ax, value)
+ struct agent_expr *ax;
+ struct axs_value *value;
+{
+ if (trace_kludge)
+ switch (value->kind)
+ {
+ case axs_rvalue:
+ /* We don't trace rvalues, just the lvalues necessary to
+ produce them. So just dispose of this value. */
+ ax_simple (ax, aop_pop);
+ break;
+
+ case axs_lvalue_memory:
+ {
+ int length = TYPE_LENGTH (value->type);
+
+ /* There's no point in trying to use a trace_quick bytecode
+ here, since "trace_quick SIZE pop" is three bytes, whereas
+ "const8 SIZE trace" is also three bytes, does the same
+ thing, and the simplest code which generates that will also
+ work correctly for objects with large sizes. */
+ ax_const_l (ax, length);
+ ax_simple (ax, aop_trace);
+ }
+ break;
+
+ case axs_lvalue_register:
+ /* We need to mention the register somewhere in the bytecode,
+ so ax_reqs will pick it up and add it to the mask of
+ registers used. */
+ ax_reg (ax, value->u.reg);
+ ax_simple (ax, aop_pop);
+ break;
+ }
+ else
+ /* If we're not tracing, just pop the value. */
+ ax_simple (ax, aop_pop);
+}
+
+
+
+/* Generating bytecode from GDB expressions: helper functions */
+
+/* Assume that the lower bits of the top of the stack is a value of
+ type TYPE, and the upper bits are zero. Sign-extend if necessary. */
+static void
+gen_sign_extend (ax, type)
+ struct agent_expr *ax;
+ struct type *type;
+{
+ /* Do we need to sign-extend this? */
+ if (! TYPE_UNSIGNED (type))
+ ax_ext (ax, type->length * TARGET_CHAR_BIT);
+}
+
+
+/* Assume the lower bits of the top of the stack hold a value of type
+ TYPE, and the upper bits are garbage. Sign-extend or truncate as
+ needed. */
+static void
+gen_extend (ax, type)
+ struct agent_expr *ax;
+ struct type *type;
+{
+ int bits = type->length * TARGET_CHAR_BIT;
+ /* I just had to. */
+ ((TYPE_UNSIGNED (type) ? ax_zero_ext : ax_ext) (ax, bits));
+}
+
+
+/* Assume that the top of the stack contains a value of type "pointer
+ to TYPE"; generate code to fetch its value. Note that TYPE is the
+ target type, not the pointer type. */
+static void
+gen_fetch (ax, type)
+ struct agent_expr *ax;
+ struct type *type;
+{
+ if (trace_kludge)
+ {
+ /* Record the area of memory we're about to fetch. */
+ ax_trace_quick (ax, TYPE_LENGTH (type));
+ }
+
+ switch (type->code)
+ {
+ case TYPE_CODE_PTR:
+ case TYPE_CODE_ENUM:
+ case TYPE_CODE_INT:
+ case TYPE_CODE_CHAR:
+ /* It's a scalar value, so we know how to dereference it. How
+ many bytes long is it? */
+ switch (type->length)
+ {
+ case 8 / TARGET_CHAR_BIT: ax_simple (ax, aop_ref8 ); break;
+ case 16 / TARGET_CHAR_BIT: ax_simple (ax, aop_ref16); break;
+ case 32 / TARGET_CHAR_BIT: ax_simple (ax, aop_ref32); break;
+ case 64 / TARGET_CHAR_BIT: ax_simple (ax, aop_ref64); break;
+
+ /* Either our caller shouldn't have asked us to dereference
+ that pointer (other code's fault), or we're not
+ implementing something we should be (this code's fault).
+ In any case, it's a bug the user shouldn't see. */
+ default:
+ error ("GDB bug: ax-gdb.c (gen_fetch): strange size");
+ }
+
+ gen_sign_extend (ax, type);
+ break;
+
+ default:
+ /* Either our caller shouldn't have asked us to dereference that
+ pointer (other code's fault), or we're not implementing
+ something we should be (this code's fault). In any case,
+ it's a bug the user shouldn't see. */
+ error ("GDB bug: ax-gdb.c (gen_fetch): bad type code");
+ }
+}
+
+
+/* Generate code to left shift the top of the stack by DISTANCE bits, or
+ right shift it by -DISTANCE bits if DISTANCE < 0. This generates
+ unsigned (logical) right shifts. */
+static void
+gen_left_shift (ax, distance)
+ struct agent_expr *ax;
+ int distance;
+{
+ if (distance > 0)
+ {
+ ax_const_l (ax, distance);
+ ax_simple (ax, aop_lsh);
+ }
+ else if (distance < 0)
+ {
+ ax_const_l (ax, -distance);
+ ax_simple (ax, aop_rsh_unsigned);
+ }
+}
+
+
+
+/* Generating bytecode from GDB expressions: symbol references */
+
+/* Generate code to push the base address of the argument portion of
+ the top stack frame. */
+static void
+gen_frame_args_address (ax)
+ struct agent_expr *ax;
+{
+ long frame_reg, frame_offset;
+
+ TARGET_VIRTUAL_FRAME_POINTER (ax->scope, &frame_reg, &frame_offset);
+ ax_reg (ax, frame_reg);
+ gen_offset (ax, frame_offset);
+}
+
+
+/* Generate code to push the base address of the locals portion of the
+ top stack frame. */
+static void
+gen_frame_locals_address (ax)
+ struct agent_expr *ax;
+{
+ long frame_reg, frame_offset;
+
+ TARGET_VIRTUAL_FRAME_POINTER (ax->scope, &frame_reg, &frame_offset);
+ ax_reg (ax, frame_reg);
+ gen_offset (ax, frame_offset);
+}
+
+
+/* Generate code to add OFFSET to the top of the stack. Try to
+ generate short and readable code. We use this for getting to
+ variables on the stack, and structure members. If we were
+ programming in ML, it would be clearer why these are the same
+ thing. */
+static void
+gen_offset (ax, offset)
+ struct agent_expr *ax;
+ int offset;
+{
+ /* It would suffice to simply push the offset and add it, but this
+ makes it easier to read positive and negative offsets in the
+ bytecode. */
+ if (offset > 0)
+ {
+ ax_const_l (ax, offset);
+ ax_simple (ax, aop_add);
+ }
+ else if (offset < 0)
+ {
+ ax_const_l (ax, -offset);
+ ax_simple (ax, aop_sub);
+ }
+}
+
+
+/* In many cases, a symbol's value is the offset from some other
+ address (stack frame, base register, etc.) Generate code to add
+ VAR's value to the top of the stack. */
+static void
+gen_sym_offset (ax, var)
+ struct agent_expr *ax;
+ struct symbol *var;
+{
+ gen_offset (ax, SYMBOL_VALUE (var));
+}
+
+
+/* Generate code for a variable reference to AX. The variable is the
+ symbol VAR. Set VALUE to describe the result. */
+
+static void
+gen_var_ref (ax, value, var)
+ struct agent_expr *ax;
+ struct axs_value *value;
+ struct symbol *var;
+{
+ /* Dereference any typedefs. */
+ value->type = check_typedef (SYMBOL_TYPE (var));
+
+ /* I'm imitating the code in read_var_value. */
+ switch (SYMBOL_CLASS (var))
+ {
+ case LOC_CONST: /* A constant, like an enum value. */
+ ax_const_l (ax, (LONGEST) SYMBOL_VALUE (var));
+ value->kind = axs_rvalue;
+ break;
+
+ case LOC_LABEL: /* A goto label, being used as a value. */
+ ax_const_l (ax, (LONGEST) SYMBOL_VALUE_ADDRESS (var));
+ value->kind = axs_rvalue;
+ break;
+
+ case LOC_CONST_BYTES:
+ error ("GDB bug: ax-gdb.c (gen_var_ref): LOC_CONST_BYTES symbols are not supported");
+
+ /* Variable at a fixed location in memory. Easy. */
+ case LOC_STATIC:
+ /* Push the address of the variable. */
+ ax_const_l (ax, SYMBOL_VALUE_ADDRESS (var));
+ value->kind = axs_lvalue_memory;
+ break;
+
+ case LOC_ARG: /* var lives in argument area of frame */
+ gen_frame_args_address (ax);
+ gen_sym_offset (ax, var);
+ value->kind = axs_lvalue_memory;
+ break;
+
+ case LOC_REF_ARG: /* As above, but the frame slot really
+ holds the address of the variable. */
+ gen_frame_args_address (ax);
+ gen_sym_offset (ax, var);
+ /* Don't assume any particular pointer size. */
+ gen_fetch (ax, lookup_pointer_type (builtin_type_void));
+ value->kind = axs_lvalue_memory;
+ break;
+
+ case LOC_LOCAL: /* var lives in locals area of frame */
+ case LOC_LOCAL_ARG:
+ gen_frame_locals_address (ax);
+ gen_sym_offset (ax, var);
+ value->kind = axs_lvalue_memory;
+ break;
+
+ case LOC_BASEREG: /* relative to some base register */
+ case LOC_BASEREG_ARG:
+ ax_reg (ax, SYMBOL_BASEREG (var));
+ gen_sym_offset (ax, var);
+ value->kind = axs_lvalue_memory;
+ break;
+
+ case LOC_TYPEDEF:
+ error ("Cannot compute value of typedef `%s'.",
+ SYMBOL_SOURCE_NAME (var));
+ break;
+
+ case LOC_BLOCK:
+ ax_const_l (ax, BLOCK_START (SYMBOL_BLOCK_VALUE (var)));
+ value->kind = axs_rvalue;
+ break;
+
+ case LOC_REGISTER:
+ case LOC_REGPARM:
+ /* Don't generate any code at all; in the process of treating
+ this as an lvalue or rvalue, the caller will generate the
+ right code. */
+ value->kind = axs_lvalue_register;
+ value->u.reg = SYMBOL_VALUE (var);
+ break;
+
+ /* A lot like LOC_REF_ARG, but the pointer lives directly in a
+ register, not on the stack. Simpler than LOC_REGISTER and
+ LOC_REGPARM, because it's just like any other case where the
+ thing has a real address. */
+ case LOC_REGPARM_ADDR:
+ ax_reg (ax, SYMBOL_VALUE (var));
+ value->kind = axs_lvalue_memory;
+ break;
+
+ case LOC_UNRESOLVED:
+ {
+ struct minimal_symbol *msym
+ = lookup_minimal_symbol (SYMBOL_NAME (var), NULL, NULL);
+ if (! msym)
+ error ("Couldn't resolve symbol `%s'.", SYMBOL_SOURCE_NAME (var));
+
+ /* Push the address of the variable. */
+ ax_const_l (ax, SYMBOL_VALUE_ADDRESS (msym));
+ value->kind = axs_lvalue_memory;
+ }
+ break;
+
+ case LOC_OPTIMIZED_OUT:
+ error ("The variable `%s' has been optimized out.",
+ SYMBOL_SOURCE_NAME (var));
+ break;
+
+ default:
+ error ("Cannot find value of botched symbol `%s'.",
+ SYMBOL_SOURCE_NAME (var));
+ break;
+ }
+}
+
+
+
+/* Generating bytecode from GDB expressions: literals */
+
+static void
+gen_int_literal (ax, value, k, type)
+ struct agent_expr *ax;
+ struct axs_value *value;
+ LONGEST k;
+ struct type *type;
+{
+ ax_const_l (ax, k);
+ value->kind = axs_rvalue;
+ value->type = type;
+}
+
+
+
+/* Generating bytecode from GDB expressions: unary conversions, casts */
+
+/* Take what's on the top of the stack (as described by VALUE), and
+ try to make an rvalue out of it. Signal an error if we can't do
+ that. */
+static void
+require_rvalue (ax, value)
+ struct agent_expr *ax;
+ struct axs_value *value;
+{
+ switch (value->kind)
+ {
+ case axs_rvalue:
+ /* It's already an rvalue. */
+ break;
+
+ case axs_lvalue_memory:
+ /* The top of stack is the address of the object. Dereference. */
+ gen_fetch (ax, value->type);
+ break;
+
+ case axs_lvalue_register:
+ /* There's nothing on the stack, but value->u.reg is the
+ register number containing the value.
+
+ When we add floating-point support, this is going to have to
+ change. What about SPARC register pairs, for example? */
+ ax_reg (ax, value->u.reg);
+ gen_extend (ax, value->type);
+ break;
+ }
+
+ value->kind = axs_rvalue;
+}
+
+
+/* Assume the top of the stack is described by VALUE, and perform the
+ usual unary conversions. This is motivated by ANSI 6.2.2, but of
+ course GDB expressions are not ANSI; they're the mishmash union of
+ a bunch of languages. Rah.
+
+ NOTE! This function promises to produce an rvalue only when the
+ incoming value is of an appropriate type. In other words, the
+ consumer of the value this function produces may assume the value
+ is an rvalue only after checking its type.
+
+ The immediate issue is that if the user tries to use a structure or
+ union as an operand of, say, the `+' operator, we don't want to try
+ to convert that structure to an rvalue; require_rvalue will bomb on
+ structs and unions. Rather, we want to simply pass the struct
+ lvalue through unchanged, and let `+' raise an error. */
+
+static void
+gen_usual_unary (ax, value)
+ struct agent_expr *ax;
+ struct axs_value *value;
+{
+ /* We don't have to generate any code for the usual integral
+ conversions, since values are always represented as full-width on
+ the stack. Should we tweak the type? */
+
+ /* Some types require special handling. */
+ switch (value->type->code)
+ {
+ /* Functions get converted to a pointer to the function. */
+ case TYPE_CODE_FUNC:
+ value->type = lookup_pointer_type (value->type);
+ value->kind = axs_rvalue; /* Should always be true, but just in case. */
+ break;
+
+ /* Arrays get converted to a pointer to their first element, and
+ are no longer an lvalue. */
+ case TYPE_CODE_ARRAY:
+ {
+ struct type *elements = TYPE_TARGET_TYPE (value->type);
+ value->type = lookup_pointer_type (elements);
+ value->kind = axs_rvalue;
+ /* We don't need to generate any code; the address of the array
+ is also the address of its first element. */
+ }
+ break;
+
+ /* Don't try to convert structures and unions to rvalues. Let the
+ consumer signal an error. */
+ case TYPE_CODE_STRUCT:
+ case TYPE_CODE_UNION:
+ return;
+
+ /* If the value is an enum, call it an integer. */
+ case TYPE_CODE_ENUM:
+ value->type = builtin_type_int;
+ break;
+ }
+
+ /* If the value is an lvalue, dereference it. */
+ require_rvalue (ax, value);
+}
+
+
+/* Return non-zero iff the type TYPE1 is considered "wider" than the
+ type TYPE2, according to the rules described in gen_usual_arithmetic. */
+static int
+type_wider_than (type1, type2)
+ struct type *type1, *type2;
+{
+ return (TYPE_LENGTH (type1) > TYPE_LENGTH (type2)
+ || (TYPE_LENGTH (type1) == TYPE_LENGTH (type2)
+ && TYPE_UNSIGNED (type1)
+ && ! TYPE_UNSIGNED (type2)));
+}
+
+
+/* Return the "wider" of the two types TYPE1 and TYPE2. */
+static struct type *
+max_type (type1, type2)
+ struct type *type1, *type2;
+{
+ return type_wider_than (type1, type2) ? type1 : type2;
+}
+
+
+/* Generate code to convert a scalar value of type FROM to type TO. */
+static void
+gen_conversion (ax, from, to)
+ struct agent_expr *ax;
+ struct type *from, *to;
+{
+ /* Perhaps there is a more graceful way to state these rules. */
+
+ /* If we're converting to a narrower type, then we need to clear out
+ the upper bits. */
+ if (TYPE_LENGTH (to) < TYPE_LENGTH (from))
+ gen_extend (ax, from);
+
+ /* If the two values have equal width, but different signednesses,
+ then we need to extend. */
+ else if (TYPE_LENGTH (to) == TYPE_LENGTH (from))
+ {
+ if (TYPE_UNSIGNED (from) != TYPE_UNSIGNED (to))
+ gen_extend (ax, to);
+ }
+
+ /* If we're converting to a wider type, and becoming unsigned, then
+ we need to zero out any possible sign bits. */
+ else if (TYPE_LENGTH (to) > TYPE_LENGTH (from))
+ {
+ if (TYPE_UNSIGNED (to))
+ gen_extend (ax, to);
+ }
+}
+
+
+/* Return non-zero iff the type FROM will require any bytecodes to be
+ emitted to be converted to the type TO. */
+static int
+is_nontrivial_conversion (from, to)
+ struct type *from, *to;
+{
+ struct agent_expr *ax = new_agent_expr (0);
+ int nontrivial;
+
+ /* Actually generate the code, and see if anything came out. At the
+ moment, it would be trivial to replicate the code in
+ gen_conversion here, but in the future, when we're supporting
+ floating point and the like, it may not be. Doing things this
+ way allows this function to be independent of the logic in
+ gen_conversion. */
+ gen_conversion (ax, from, to);
+ nontrivial = ax->len > 0;
+ free_agent_expr (ax);
+ return nontrivial;
+}
+
+
+/* Generate code to perform the "usual arithmetic conversions" (ANSI C
+ 6.2.1.5) for the two operands of an arithmetic operator. This
+ effectively finds a "least upper bound" type for the two arguments,
+ and promotes each argument to that type. *VALUE1 and *VALUE2
+ describe the values as they are passed in, and as they are left. */
+static void
+gen_usual_arithmetic (ax, value1, value2)
+ struct agent_expr *ax;
+ struct axs_value *value1, *value2;
+{
+ /* Do the usual binary conversions. */
+ if (TYPE_CODE (value1->type) == TYPE_CODE_INT
+ && TYPE_CODE (value2->type) == TYPE_CODE_INT)
+ {
+ /* The ANSI integral promotions seem to work this way: Order the
+ integer types by size, and then by signedness: an n-bit
+ unsigned type is considered "wider" than an n-bit signed
+ type. Promote to the "wider" of the two types, and always
+ promote at least to int. */
+ struct type *target = max_type (builtin_type_int,
+ max_type (value1->type, value2->type));
+
+ /* Deal with value2, on the top of the stack. */
+ gen_conversion (ax, value2->type, target);
+
+ /* Deal with value1, not on the top of the stack. Don't
+ generate the `swap' instructions if we're not actually going
+ to do anything. */
+ if (is_nontrivial_conversion (value1->type, target))
+ {
+ ax_simple (ax, aop_swap);
+ gen_conversion (ax, value1->type, target);
+ ax_simple (ax, aop_swap);
+ }
+
+ value1->type = value2->type = target;
+ }
+}
+
+
+/* Generate code to perform the integral promotions (ANSI 6.2.1.1) on
+ the value on the top of the stack, as described by VALUE. Assume
+ the value has integral type. */
+static void
+gen_integral_promotions (ax, value)
+ struct agent_expr *ax;
+ struct axs_value *value;
+{
+ if (! type_wider_than (value->type, builtin_type_int))
+ {
+ gen_conversion (ax, value->type, builtin_type_int);
+ value->type = builtin_type_int;
+ }
+ else if (! type_wider_than (value->type, builtin_type_unsigned_int))
+ {
+ gen_conversion (ax, value->type, builtin_type_unsigned_int);
+ value->type = builtin_type_unsigned_int;
+ }
+}
+
+
+/* Generate code for a cast to TYPE. */
+static void
+gen_cast (ax, value, type)
+ struct agent_expr *ax;
+ struct axs_value *value;
+ struct type *type;
+{
+ /* GCC does allow casts to yield lvalues, so this should be fixed
+ before merging these changes into the trunk. */
+ require_rvalue (ax, value);
+ /* Dereference typedefs. */
+ type = check_typedef (type);
+
+ switch (type->code)
+ {
+ case TYPE_CODE_PTR:
+ /* It's implementation-defined, and I'll bet this is what GCC
+ does. */
+ break;
+
+ case TYPE_CODE_ARRAY:
+ case TYPE_CODE_STRUCT:
+ case TYPE_CODE_UNION:
+ case TYPE_CODE_FUNC:
+ error ("Illegal type cast: intended type must be scalar.");
+
+ case TYPE_CODE_ENUM:
+ /* We don't have to worry about the size of the value, because
+ all our integral values are fully sign-extended, and when
+ casting pointers we can do anything we like. Is there any
+ way for us to actually know what GCC actually does with a
+ cast like this? */
+ value->type = type;
+ break;
+
+ case TYPE_CODE_INT:
+ gen_conversion (ax, value->type, type);
+ break;
+
+ case TYPE_CODE_VOID:
+ /* We could pop the value, and rely on everyone else to check
+ the type and notice that this value doesn't occupy a stack
+ slot. But for now, leave the value on the stack, and
+ preserve the "value == stack element" assumption. */
+ break;
+
+ default:
+ error ("Casts to requested type are not yet implemented.");
+ }
+
+ value->type = type;
+}
+
+
+
+/* Generating bytecode from GDB expressions: arithmetic */
+
+/* Scale the integer on the top of the stack by the size of the target
+ of the pointer type TYPE. */
+static void
+gen_scale (ax, op, type)
+ struct agent_expr *ax;
+ enum agent_op op;
+ struct type *type;
+{
+ struct type *element = TYPE_TARGET_TYPE (type);
+
+ if (element->length != 1)
+ {
+ ax_const_l (ax, element->length);
+ ax_simple (ax, op);
+ }
+}
+
+
+/* Generate code for an addition; non-trivial because we deal with
+ pointer arithmetic. We set VALUE to describe the result value; we
+ assume VALUE1 and VALUE2 describe the two operands, and that
+ they've undergone the usual binary conversions. Used by both
+ BINOP_ADD and BINOP_SUBSCRIPT. NAME is used in error messages. */
+static void
+gen_add (ax, value, value1, value2, name)
+ struct agent_expr *ax;
+ struct axs_value *value, *value1, *value2;
+ char *name;
+{
+ /* Is it INT+PTR? */
+ if (value1->type->code == TYPE_CODE_INT
+ && value2->type->code == TYPE_CODE_PTR)
+ {
+ /* Swap the values and proceed normally. */
+ ax_simple (ax, aop_swap);
+ gen_scale (ax, aop_mul, value2->type);
+ ax_simple (ax, aop_add);
+ gen_extend (ax, value2->type); /* Catch overflow. */
+ value->type = value2->type;
+ }
+
+ /* Is it PTR+INT? */
+ else if (value1->type->code == TYPE_CODE_PTR
+ && value2->type->code == TYPE_CODE_INT)
+ {
+ gen_scale (ax, aop_mul, value1->type);
+ ax_simple (ax, aop_add);
+ gen_extend (ax, value1->type); /* Catch overflow. */
+ value->type = value1->type;
+ }
+
+ /* Must be number + number; the usual binary conversions will have
+ brought them both to the same width. */
+ else if (value1->type->code == TYPE_CODE_INT
+ && value2->type->code == TYPE_CODE_INT)
+ {
+ ax_simple (ax, aop_add);
+ gen_extend (ax, value1->type); /* Catch overflow. */
+ value->type = value1->type;
+ }
+
+ else
+ error ("Illegal combination of types in %s.", name);
+
+ value->kind = axs_rvalue;
+}
+
+
+/* Generate code for an addition; non-trivial because we have to deal
+ with pointer arithmetic. We set VALUE to describe the result
+ value; we assume VALUE1 and VALUE2 describe the two operands, and
+ that they've undergone the usual binary conversions. */
+static void
+gen_sub (ax, value, value1, value2)
+ struct agent_expr *ax;
+ struct axs_value *value, *value1, *value2;
+{
+ struct type *element;
+
+ if (value1->type->code == TYPE_CODE_PTR)
+ {
+ /* Is it PTR - INT? */
+ if (value2->type->code == TYPE_CODE_INT)
+ {
+ gen_scale (ax, aop_mul, value1->type);
+ ax_simple (ax, aop_sub);
+ gen_extend (ax, value1->type); /* Catch overflow. */
+ value->type = value1->type;
+ }
+
+ /* Is it PTR - PTR? Strictly speaking, the types ought to
+ match, but this is what the normal GDB expression evaluator
+ tests for. */
+ else if (value2->type->code == TYPE_CODE_PTR
+ && (TYPE_LENGTH (TYPE_TARGET_TYPE (value1->type))
+ == TYPE_LENGTH (TYPE_TARGET_TYPE (value2->type))))
+ {
+ ax_simple (ax, aop_sub);
+ gen_scale (ax, aop_div_unsigned, value1->type);
+ value->type = builtin_type_long; /* FIXME --- should be ptrdiff_t */
+ }
+ else
+ error ("\
+First argument of `-' is a pointer, but second argument is neither\n\
+an integer nor a pointer of the same type.");
+ }
+
+ /* Must be number + number. */
+ else if (value1->type->code == TYPE_CODE_INT
+ && value2->type->code == TYPE_CODE_INT)
+ {
+ ax_simple (ax, aop_sub);
+ gen_extend (ax, value1->type); /* Catch overflow. */
+ value->type = value1->type;
+ }
+
+ else
+ error ("Illegal combination of types in subtraction.");
+
+ value->kind = axs_rvalue;
+}
+
+/* Generate code for a binary operator that doesn't do pointer magic.
+ We set VALUE to describe the result value; we assume VALUE1 and
+ VALUE2 describe the two operands, and that they've undergone the
+ usual binary conversions. MAY_CARRY should be non-zero iff the
+ result needs to be extended. NAME is the English name of the
+ operator, used in error messages */
+static void
+gen_binop (ax, value, value1, value2, op, op_unsigned, may_carry, name)
+ struct agent_expr *ax;
+ struct axs_value *value, *value1, *value2;
+ enum agent_op op, op_unsigned;
+ int may_carry;
+ char *name;
+{
+ /* We only handle INT op INT. */
+ if ((value1->type->code != TYPE_CODE_INT)
+ || (value2->type->code != TYPE_CODE_INT))
+ error ("Illegal combination of types in %s.", name);
+
+ ax_simple (ax,
+ TYPE_UNSIGNED (value1->type) ? op_unsigned : op);
+ if (may_carry)
+ gen_extend (ax, value1->type); /* catch overflow */
+ value->type = value1->type;
+ value->kind = axs_rvalue;
+}
+
+
+static void
+gen_logical_not (ax, value)
+ struct agent_expr *ax;
+ struct axs_value *value;
+{
+ if (TYPE_CODE (value->type) != TYPE_CODE_INT
+ && TYPE_CODE (value->type) != TYPE_CODE_PTR)
+ error ("Illegal type of operand to `!'.");
+
+ gen_usual_unary (ax, value);
+ ax_simple (ax, aop_log_not);
+ value->type = builtin_type_int;
+}
+
+
+static void
+gen_complement (ax, value)
+ struct agent_expr *ax;
+ struct axs_value *value;
+{
+ if (TYPE_CODE (value->type) != TYPE_CODE_INT)
+ error ("Illegal type of operand to `~'.");
+
+ gen_usual_unary (ax, value);
+ gen_integral_promotions (ax, value);
+ ax_simple (ax, aop_bit_not);
+ gen_extend (ax, value->type);
+}
+
+
+
+/* Generating bytecode from GDB expressions: * & . -> @ sizeof */
+
+/* Dereference the value on the top of the stack. */
+static void
+gen_deref (ax, value)
+ struct agent_expr *ax;
+ struct axs_value *value;
+{
+ /* The caller should check the type, because several operators use
+ this, and we don't know what error message to generate. */
+ if (value->type->code != TYPE_CODE_PTR)
+ error ("GDB bug: ax-gdb.c (gen_deref): expected a pointer");
+
+ /* We've got an rvalue now, which is a pointer. We want to yield an
+ lvalue, whose address is exactly that pointer. So we don't
+ actually emit any code; we just change the type from "Pointer to
+ T" to "T", and mark the value as an lvalue in memory. Leave it
+ to the consumer to actually dereference it. */
+ value->type = check_typedef (TYPE_TARGET_TYPE (value->type));
+ value->kind = ((value->type->code == TYPE_CODE_FUNC)
+ ? axs_rvalue : axs_lvalue_memory);
+}
+
+
+/* Produce the address of the lvalue on the top of the stack. */
+static void
+gen_address_of (ax, value)
+ struct agent_expr *ax;
+ struct axs_value *value;
+{
+ /* Special case for taking the address of a function. The ANSI
+ standard describes this as a special case, too, so this
+ arrangement is not without motivation. */
+ if (value->type->code == TYPE_CODE_FUNC)
+ /* The value's already an rvalue on the stack, so we just need to
+ change the type. */
+ value->type = lookup_pointer_type (value->type);
+ else
+ switch (value->kind)
+ {
+ case axs_rvalue:
+ error ("Operand of `&' is an rvalue, which has no address.");
+
+ case axs_lvalue_register:
+ error ("Operand of `&' is in a register, and has no address.");
+
+ case axs_lvalue_memory:
+ value->kind = axs_rvalue;
+ value->type = lookup_pointer_type (value->type);
+ break;
+ }
+}
+
+
+/* A lot of this stuff will have to change to support C++. But we're
+ not going to deal with that at the moment. */
+
+/* Find the field in the structure type TYPE named NAME, and return
+ its index in TYPE's field array. */
+static int
+find_field (type, name)
+ struct type *type;
+ char *name;
+{
+ int i;
+
+ CHECK_TYPEDEF (type);
+
+ /* Make sure this isn't C++. */
+ if (TYPE_N_BASECLASSES (type) != 0)
+ error ("GDB bug: ax-gdb.c (find_field): derived classes supported");
+
+ for (i = 0; i < TYPE_NFIELDS (type); i++)
+ {
+ char *this_name = TYPE_FIELD_NAME (type, i);
+
+ if (this_name && STREQ (name, this_name))
+ return i;
+
+ if (this_name[0] == '\0')
+ error ("GDB bug: ax-gdb.c (find_field): anonymous unions not supported");
+ }
+
+ error ("Couldn't find member named `%s' in struct/union `%s'",
+ name, type->tag_name);
+
+ return 0;
+}
+
+
+/* Generate code to push the value of a bitfield of a structure whose
+ address is on the top of the stack. START and END give the
+ starting and one-past-ending *bit* numbers of the field within the
+ structure. */
+static void
+gen_bitfield_ref (ax, value, type, start, end)
+ struct agent_expr *ax;
+ struct axs_value *value;
+ struct type *type;
+ int start, end;
+{
+ /* Note that ops[i] fetches 8 << i bits. */
+ static enum agent_op ops[]
+ = { aop_ref8, aop_ref16, aop_ref32, aop_ref64 };
+ static int num_ops = (sizeof (ops) / sizeof (ops[0]));
+
+ /* We don't want to touch any byte that the bitfield doesn't
+ actually occupy; we shouldn't make any accesses we're not
+ explicitly permitted to. We rely here on the fact that the
+ bytecode `ref' operators work on unaligned addresses.
+
+ It takes some fancy footwork to get the stack to work the way
+ we'd like. Say we're retrieving a bitfield that requires three
+ fetches. Initially, the stack just contains the address:
+ addr
+ For the first fetch, we duplicate the address
+ addr addr
+ then add the byte offset, do the fetch, and shift and mask as
+ needed, yielding a fragment of the value, properly aligned for
+ the final bitwise or:
+ addr frag1
+ then we swap, and repeat the process:
+ frag1 addr --- address on top
+ frag1 addr addr --- duplicate it
+ frag1 addr frag2 --- get second fragment
+ frag1 frag2 addr --- swap again
+ frag1 frag2 frag3 --- get third fragment
+ Notice that, since the third fragment is the last one, we don't
+ bother duplicating the address this time. Now we have all the
+ fragments on the stack, and we can simply `or' them together,
+ yielding the final value of the bitfield. */
+
+ /* The first and one-after-last bits in the field, but rounded down
+ and up to byte boundaries. */
+ int bound_start = (start / TARGET_CHAR_BIT) * TARGET_CHAR_BIT;
+ int bound_end = (((end + TARGET_CHAR_BIT - 1)
+ / TARGET_CHAR_BIT)
+ * TARGET_CHAR_BIT);
+
+ /* current bit offset within the structure */
+ int offset;
+
+ /* The index in ops of the opcode we're considering. */
+ int op;
+
+ /* The number of fragments we generated in the process. Probably
+ equal to the number of `one' bits in bytesize, but who cares? */
+ int fragment_count;
+
+ /* Dereference any typedefs. */
+ type = check_typedef (type);
+
+ /* Can we fetch the number of bits requested at all? */
+ if ((end - start) > ((1 << num_ops) * 8))
+ error ("GDB bug: ax-gdb.c (gen_bitfield_ref): bitfield too wide");
+
+ /* Note that we know here that we only need to try each opcode once.
+ That may not be true on machines with weird byte sizes. */
+ offset = bound_start;
+ fragment_count = 0;
+ for (op = num_ops - 1; op >= 0; op--)
+ {
+ /* number of bits that ops[op] would fetch */
+ int op_size = 8 << op;
+
+ /* The stack at this point, from bottom to top, contains zero or
+ more fragments, then the address. */
+
+ /* Does this fetch fit within the bitfield? */
+ if (offset + op_size <= bound_end)
+ {
+ /* Is this the last fragment? */
+ int last_frag = (offset + op_size == bound_end);
+
+ if (! last_frag)
+ ax_simple (ax, aop_dup); /* keep a copy of the address */
+
+ /* Add the offset. */
+ gen_offset (ax, offset / TARGET_CHAR_BIT);
+
+ if (trace_kludge)
+ {
+ /* Record the area of memory we're about to fetch. */
+ ax_trace_quick (ax, op_size / TARGET_CHAR_BIT);
+ }
+
+ /* Perform the fetch. */
+ ax_simple (ax, ops[op]);
+
+ /* Shift the bits we have to their proper position.
+ gen_left_shift will generate right shifts when the operand
+ is negative.
+
+ A big-endian field diagram to ponder:
+ byte 0 byte 1 byte 2 byte 3 byte 4 byte 5 byte 6 byte 7
+ +------++------++------++------++------++------++------++------+
+ xxxxAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBCCCCCxxxxxxxxxxx
+ ^ ^ ^ ^
+ bit number 16 32 48 53
+ These are bit numbers as supplied by GDB. Note that the
+ bit numbers run from right to left once you've fetched the
+ value!
+
+ A little-endian field diagram to ponder:
+ byte 7 byte 6 byte 5 byte 4 byte 3 byte 2 byte 1 byte 0
+ +------++------++------++------++------++------++------++------+
+ xxxxxxxxxxxAAAAABBBBBBBBBBBBBBBBCCCCCCCCCCCCCCCCCCCCCCCCCCCCxxxx
+ ^ ^ ^ ^ ^
+ bit number 48 32 16 4 0
+
+ In both cases, the most significant end is on the left
+ (i.e. normal numeric writing order), which means that you
+ don't go crazy thinking about `left' and `right' shifts.
+
+ We don't have to worry about masking yet:
+ - If they contain garbage off the least significant end, then we
+ must be looking at the low end of the field, and the right
+ shift will wipe them out.
+ - If they contain garbage off the most significant end, then we
+ must be looking at the most significant end of the word, and
+ the sign/zero extension will wipe them out.
+ - If we're in the interior of the word, then there is no garbage
+ on either end, because the ref operators zero-extend. */
+ if (TARGET_BYTE_ORDER == BIG_ENDIAN)
+ gen_left_shift (ax, end - (offset + op_size));
+ else
+ gen_left_shift (ax, offset - start);
+
+ if (! last_frag)
+ /* Bring the copy of the address up to the top. */
+ ax_simple (ax, aop_swap);
+
+ offset += op_size;
+ fragment_count++;
+ }
+ }
+
+ /* Generate enough bitwise `or' operations to combine all the
+ fragments we left on the stack. */
+ while (fragment_count-- > 1)
+ ax_simple (ax, aop_bit_or);
+
+ /* Sign- or zero-extend the value as appropriate. */
+ ((TYPE_UNSIGNED (type) ? ax_zero_ext : ax_ext) (ax, end - start));
+
+ /* This is *not* an lvalue. Ugh. */
+ value->kind = axs_rvalue;
+ value->type = type;
+}
+
+
+/* Generate code to reference the member named FIELD of a structure or
+ union. The top of the stack, as described by VALUE, should have
+ type (pointer to a)* struct/union. OPERATOR_NAME is the name of
+ the operator being compiled, and OPERAND_NAME is the kind of thing
+ it operates on; we use them in error messages. */
+static void
+gen_struct_ref (ax, value, field, operator_name, operand_name)
+ struct agent_expr *ax;
+ struct axs_value *value;
+ char *field;
+ char *operator_name;
+ char *operand_name;
+{
+ struct type *type;
+ int i;
+
+ /* Follow pointers until we reach a non-pointer. These aren't the C
+ semantics, but they're what the normal GDB evaluator does, so we
+ should at least be consistent. */
+ while (value->type->code == TYPE_CODE_PTR)
+ {
+ gen_usual_unary (ax, value);
+ gen_deref (ax, value);
+ }
+ type = value->type;
+
+ /* This must yield a structure or a union. */
+ if (TYPE_CODE (type) != TYPE_CODE_STRUCT
+ && TYPE_CODE (type) != TYPE_CODE_UNION)
+ error ("The left operand of `%s' is not a %s.",
+ operator_name, operand_name);
+
+ /* And it must be in memory; we don't deal with structure rvalues,
+ or structures living in registers. */
+ if (value->kind != axs_lvalue_memory)
+ error ("Structure does not live in memory.");
+
+ i = find_field (type, field);
+
+ /* Is this a bitfield? */
+ if (TYPE_FIELD_PACKED (type, i))
+ gen_bitfield_ref (ax, value, TYPE_FIELD_TYPE (type, i),
+ TYPE_FIELD_BITPOS (type, i),
+ (TYPE_FIELD_BITPOS (type, i)
+ + TYPE_FIELD_BITSIZE (type, i)));
+ else
+ {
+ gen_offset (ax, TYPE_FIELD_BITPOS (type, i) / TARGET_CHAR_BIT);
+ value->kind = axs_lvalue_memory;
+ value->type = TYPE_FIELD_TYPE (type, i);
+ }
+}
+
+
+/* Generate code for GDB's magical `repeat' operator.
+ LVALUE @ INT creates an array INT elements long, and whose elements
+ have the same type as LVALUE, located in memory so that LVALUE is
+ its first element. For example, argv[0]@argc gives you the array
+ of command-line arguments.
+
+ Unfortunately, because we have to know the types before we actually
+ have a value for the expression, we can't implement this perfectly
+ without changing the type system, having values that occupy two
+ stack slots, doing weird things with sizeof, etc. So we require
+ the right operand to be a constant expression. */
+static void
+gen_repeat (pc, ax, value)
+ union exp_element **pc;
+ struct agent_expr *ax;
+ struct axs_value *value;
+{
+ struct axs_value value1;
+ /* We don't want to turn this into an rvalue, so no conversions
+ here. */
+ gen_expr (pc, ax, &value1);
+ if (value1.kind != axs_lvalue_memory)
+ error ("Left operand of `@' must be an object in memory.");
+
+ /* Evaluate the length; it had better be a constant. */
+ {
+ struct value *v = const_expr (pc);
+ int length;
+
+ if (! v)
+ error ("Right operand of `@' must be a constant, in agent expressions.");
+ if (v->type->code != TYPE_CODE_INT)
+ error ("Right operand of `@' must be an integer.");
+ length = value_as_long (v);
+ if (length <= 0)
+ error ("Right operand of `@' must be positive.");
+
+ /* The top of the stack is already the address of the object, so
+ all we need to do is frob the type of the lvalue. */
+ {
+ /* FIXME-type-allocation: need a way to free this type when we are
+ done with it. */
+ struct type *range
+ = create_range_type (0, builtin_type_int, 0, length - 1);
+ struct type *array = create_array_type (0, value1.type, range);
+
+ value->kind = axs_lvalue_memory;
+ value->type = array;
+ }
+ }
+}
+
+
+/* Emit code for the `sizeof' operator.
+ *PC should point at the start of the operand expression; we advance it
+ to the first instruction after the operand. */
+static void
+gen_sizeof (pc, ax, value)
+ union exp_element **pc;
+ struct agent_expr *ax;
+ struct axs_value *value;
+{
+ /* We don't care about the value of the operand expression; we only
+ care about its type. However, in the current arrangement, the
+ only way to find an expression's type is to generate code for it.
+ So we generate code for the operand, and then throw it away,
+ replacing it with code that simply pushes its size. */
+ int start = ax->len;
+ gen_expr (pc, ax, value);
+
+ /* Throw away the code we just generated. */
+ ax->len = start;
+
+ ax_const_l (ax, TYPE_LENGTH (value->type));
+ value->kind = axs_rvalue;
+ value->type = builtin_type_int;
+}
+
+
+/* Generating bytecode from GDB expressions: general recursive thingy */
+
+/* A gen_expr function written by a Gen-X'er guy.
+ Append code for the subexpression of EXPR starting at *POS_P to AX. */
+static void
+gen_expr (pc, ax, value)
+ union exp_element **pc;
+ struct agent_expr *ax;
+ struct axs_value *value;
+{
+ /* Used to hold the descriptions of operand expressions. */
+ struct axs_value value1, value2;
+ enum exp_opcode op = (*pc)[0].opcode;
+
+ /* If we're looking at a constant expression, just push its value. */
+ {
+ struct value *v = maybe_const_expr (pc);
+
+ if (v)
+ {
+ ax_const_l (ax, value_as_long (v));
+ value->kind = axs_rvalue;
+ value->type = check_typedef (VALUE_TYPE (v));
+ return;
+ }
+ }
+
+ /* Otherwise, go ahead and generate code for it. */
+ switch (op)
+ {
+ /* Binary arithmetic operators. */
+ case BINOP_ADD:
+ case BINOP_SUB:
+ case BINOP_MUL:
+ case BINOP_DIV:
+ case BINOP_REM:
+ case BINOP_SUBSCRIPT:
+ case BINOP_BITWISE_AND:
+ case BINOP_BITWISE_IOR:
+ case BINOP_BITWISE_XOR:
+ (*pc)++;
+ gen_expr (pc, ax, &value1);
+ gen_usual_unary (ax, &value1);
+ gen_expr (pc, ax, &value2);
+ gen_usual_unary (ax, &value2);
+ gen_usual_arithmetic (ax, &value1, &value2);
+ switch (op)
+ {
+ case BINOP_ADD:
+ gen_add (ax, value, &value1, &value2, "addition");
+ break;
+ case BINOP_SUB:
+ gen_sub (ax, value, &value1, &value2);
+ break;
+ case BINOP_MUL:
+ gen_binop (ax, value, &value1, &value2,
+ aop_mul, aop_mul, 1, "multiplication");
+ break;
+ case BINOP_DIV:
+ gen_binop (ax, value, &value1, &value2,
+ aop_div_signed, aop_div_unsigned, 1, "division");
+ break;
+ case BINOP_REM:
+ gen_binop (ax, value, &value1, &value2,
+ aop_rem_signed, aop_rem_unsigned, 1, "remainder");
+ break;
+ case BINOP_SUBSCRIPT:
+ gen_add (ax, value, &value1, &value2, "array subscripting");
+ if (TYPE_CODE (value->type) != TYPE_CODE_PTR)
+ error ("Illegal combination of types in array subscripting.");
+ gen_deref (ax, value);
+ break;
+ case BINOP_BITWISE_AND:
+ gen_binop (ax, value, &value1, &value2,
+ aop_bit_and, aop_bit_and, 0, "bitwise and");
+ break;
+
+ case BINOP_BITWISE_IOR:
+ gen_binop (ax, value, &value1, &value2,
+ aop_bit_or, aop_bit_or, 0, "bitwise or");
+ break;
+
+ case BINOP_BITWISE_XOR:
+ gen_binop (ax, value, &value1, &value2,
+ aop_bit_xor, aop_bit_xor, 0, "bitwise exclusive-or");
+ break;
+
+ default:
+ /* We should only list operators in the outer case statement
+ that we actually handle in the inner case statement. */
+ error ("GDB bug: ax-gdb.c (gen_expr): op case sets don't match");
+ }
+ break;
+
+ /* Note that we need to be a little subtle about generating code
+ for comma. In C, we can do some optimizations here because
+ we know the left operand is only being evaluated for effect.
+ However, if the tracing kludge is in effect, then we always
+ need to evaluate the left hand side fully, so that all the
+ variables it mentions get traced. */
+ case BINOP_COMMA:
+ (*pc)++;
+ gen_expr (pc, ax, &value1);
+ /* Don't just dispose of the left operand. We might be tracing,
+ in which case we want to emit code to trace it if it's an
+ lvalue. */
+ gen_traced_pop (ax, &value1);
+ gen_expr (pc, ax, value);
+ /* It's the consumer's responsibility to trace the right operand. */
+ break;
+
+ case OP_LONG: /* some integer constant */
+ {
+ struct type *type = (*pc)[1].type;
+ LONGEST k = (*pc)[2].longconst;
+ (*pc) += 4;
+ gen_int_literal (ax, value, k, type);
+ }
+ break;
+
+ case OP_VAR_VALUE:
+ gen_var_ref (ax, value, (*pc)[2].symbol);
+ (*pc) += 4;
+ break;
+
+ case OP_REGISTER:
+ {
+ int reg = (int) (*pc)[1].longconst;
+ (*pc) += 3;
+ value->kind = axs_lvalue_register;
+ value->u.reg = reg;
+ value->type = REGISTER_VIRTUAL_TYPE (reg);
+ }
+ break;
+
+ case OP_INTERNALVAR:
+ error ("GDB agent expressions cannot use convenience variables.");
+
+ /* Weirdo operator: see comments for gen_repeat for details. */
+ case BINOP_REPEAT:
+ /* Note that gen_repeat handles its own argument evaluation. */
+ (*pc)++;
+ gen_repeat (pc, ax, value);
+ break;
+
+ case UNOP_CAST:
+ {
+ struct type *type = (*pc)[1].type;
+ (*pc) += 3;
+ gen_expr (pc, ax, value);
+ gen_cast (ax, value, type);
+ }
+ break;
+
+ case UNOP_MEMVAL:
+ {
+ struct type *type = check_typedef ((*pc)[1].type);
+ (*pc) += 3;
+ gen_expr (pc, ax, value);
+ /* I'm not sure I understand UNOP_MEMVAL entirely. I think
+ it's just a hack for dealing with minsyms; you take some
+ integer constant, pretend it's the address of an lvalue of
+ the given type, and dereference it. */
+ if (value->kind != axs_rvalue)
+ /* This would be weird. */
+ error ("GDB bug: ax-gdb.c (gen_expr): OP_MEMVAL operand isn't an rvalue???");
+ value->type = type;
+ value->kind = axs_lvalue_memory;
+ }
+ break;
+
+ case UNOP_NEG:
+ (*pc)++;
+ /* -FOO is equivalent to 0 - FOO. */
+ gen_int_literal (ax, &value1, (LONGEST) 0, builtin_type_int);
+ gen_usual_unary (ax, &value1); /* shouldn't do much */
+ gen_expr (pc, ax, &value2);
+ gen_usual_unary (ax, &value2);
+ gen_usual_arithmetic (ax, &value1, &value2);
+ gen_sub (ax, value, &value1, &value2);
+ break;
+
+ case UNOP_LOGICAL_NOT:
+ (*pc)++;
+ gen_expr (pc, ax, value);
+ gen_logical_not (ax, value);
+ break;
+
+ case UNOP_COMPLEMENT:
+ (*pc)++;
+ gen_expr (pc, ax, value);
+ gen_complement (ax, value);
+ break;
+
+ case UNOP_IND:
+ (*pc)++;
+ gen_expr (pc, ax, value);
+ gen_usual_unary (ax, value);
+ if (TYPE_CODE (value->type) != TYPE_CODE_PTR)
+ error ("Argument of unary `*' is not a pointer.");
+ gen_deref (ax, value);
+ break;
+
+ case UNOP_ADDR:
+ (*pc)++;
+ gen_expr (pc, ax, value);
+ gen_address_of (ax, value);
+ break;
+
+ case UNOP_SIZEOF:
+ (*pc)++;
+ /* Notice that gen_sizeof handles its own operand, unlike most
+ of the other unary operator functions. This is because we
+ have to throw away the code we generate. */
+ gen_sizeof (pc, ax, value);
+ break;
+
+ case STRUCTOP_STRUCT:
+ case STRUCTOP_PTR:
+ {
+ int length = (*pc)[1].longconst;
+ char *name = &(*pc)[2].string;
+
+ (*pc) += 4 + BYTES_TO_EXP_ELEM (length + 1);
+ gen_expr (pc, ax, value);
+ if (op == STRUCTOP_STRUCT)
+ gen_struct_ref (ax, value, name, ".", "structure or union");
+ else if (op == STRUCTOP_PTR)
+ gen_struct_ref (ax, value, name, "->",
+ "pointer to a structure or union");
+ else
+ /* If this `if' chain doesn't handle it, then the case list
+ shouldn't mention it, and we shouldn't be here. */
+ error ("GDB bug: ax-gdb.c (gen_expr): unhandled struct case");
+ }
+ break;
+
+ case OP_TYPE:
+ error ("Attempt to use a type name as an expression.");
+
+ default:
+ error ("Unsupported operator in expression.");
+ }
+}
+
+
+
+#if 0 /* not used */
+/* Generating bytecode from GDB expressions: driver */
+
+/* Given a GDB expression EXPR, produce a string of agent bytecode
+ which computes its value. Return the agent expression, and set
+ *VALUE to describe its type, and whether it's an lvalue or rvalue. */
+struct agent_expr *
+expr_to_agent (expr, value)
+ struct expression *expr;
+ struct axs_value *value;
+{
+ struct cleanup *old_chain = 0;
+ struct agent_expr *ax = new_agent_expr ();
+ union exp_element *pc;
+
+ old_chain = make_cleanup ((make_cleanup_func) free_agent_expr, ax);
+
+ pc = expr->elts;
+ trace_kludge = 0;
+ gen_expr (&pc, ax, value);
+
+ /* We have successfully built the agent expr, so cancel the cleanup
+ request. If we add more cleanups that we always want done, this
+ will have to get more complicated. */
+ discard_cleanups (old_chain);
+ return ax;
+}
+
+
+/* Given a GDB expression EXPR denoting an lvalue in memory, produce a
+ string of agent bytecode which will leave its address and size on
+ the top of stack. Return the agent expression.
+
+ Not sure this function is useful at all. */
+struct agent_expr *
+expr_to_address_and_size (expr)
+ struct expression *expr;
+{
+ struct axs_value value;
+ struct agent_expr *ax = expr_to_agent (expr, &value);
+
+ /* Complain if the result is not a memory lvalue. */
+ if (value.kind != axs_lvalue_memory)
+ {
+ free_agent_expr (ax);
+ error ("Expression does not denote an object in memory.");
+ }
+
+ /* Push the object's size on the stack. */
+ ax_const_l (ax, TYPE_LENGTH (value.type));
+
+ return ax;
+}
+#endif /* 0 */
+
+/* Given a GDB expression EXPR, return bytecode to trace its value.
+ The result will use the `trace' and `trace_quick' bytecodes to
+ record the value of all memory touched by the expression. The
+ caller can then use the ax_reqs function to discover which
+ registers it relies upon. */
+struct agent_expr *
+gen_trace_for_expr (scope, expr)
+ CORE_ADDR scope;
+ struct expression *expr;
+{
+ struct cleanup *old_chain = 0;
+ struct agent_expr *ax = new_agent_expr (scope);
+ union exp_element *pc;
+ struct axs_value value;
+
+ old_chain = make_cleanup ((make_cleanup_func) free_agent_expr, ax);
+
+ pc = expr->elts;
+ trace_kludge = 1;
+ gen_expr (&pc, ax, &value);
+
+ /* Make sure we record the final object, and get rid of it. */
+ gen_traced_pop (ax, &value);
+
+ /* Oh, and terminate. */
+ ax_simple (ax, aop_end);
+
+ /* We have successfully built the agent expr, so cancel the cleanup
+ request. If we add more cleanups that we always want done, this
+ will have to get more complicated. */
+ discard_cleanups (old_chain);
+ return ax;
+}
+
+
+
+/* The "agent" command, for testing: compile and disassemble an expression. */
+
+static void
+print_axs_value (f, value)
+ GDB_FILE *f;
+ struct axs_value *value;
+{
+ switch (value->kind)
+ {
+ case axs_rvalue:
+ fputs_filtered ("rvalue", f);
+ break;
+
+ case axs_lvalue_memory:
+ fputs_filtered ("memory lvalue", f);
+ break;
+
+ case axs_lvalue_register:
+ fprintf_filtered (f, "register %d lvalue", value->u.reg);
+ break;
+ }
+
+ fputs_filtered (" : ", f);
+ type_print (value->type, "", f, -1);
+}
+
+
+static void
+agent_command (exp, from_tty)
+ char *exp;
+ int from_tty;
+{
+ struct cleanup *old_chain = 0;
+ struct expression *expr;
+ struct agent_expr *agent;
+ struct agent_reqs reqs;
+ struct frame_info *fi = get_current_frame (); /* need current scope */
+
+ /* We don't deal with overlay debugging at the moment. We need to
+ think more carefully about this. If you copy this code into
+ another command, change the error message; the user shouldn't
+ have to know anything about agent expressions. */
+ if (overlay_debugging)
+ error ("GDB can't do agent expression translation with overlays.");
+
+ if (exp == 0)
+ error_no_arg ("expression to translate");
+
+ expr = parse_expression (exp);
+ old_chain = make_cleanup ((make_cleanup_func) free_current_contents, &expr);
+ agent = gen_trace_for_expr (fi->pc, expr);
+ make_cleanup ((make_cleanup_func) free_agent_expr, agent);
+ ax_print (gdb_stdout, agent);
+ ax_reqs (agent, &reqs);
+
+ do_cleanups (old_chain);
+ dont_repeat ();
+}
+
+
+/* Initialization code. */
+
+void _initialize_ax_gdb PARAMS ((void));
+void
+_initialize_ax_gdb ()
+{
+ struct cmd_list_element *c;
+
+ add_cmd ("agent", class_maintenance, agent_command,
+ "Translate an expression into remote agent bytecode.",
+ &maintenancelist);
+}
diff --git a/gdb/ax-gdb.h b/gdb/ax-gdb.h
new file mode 100644
index 00000000000..bca70d64beb
--- /dev/null
+++ b/gdb/ax-gdb.h
@@ -0,0 +1,111 @@
+/* GDB-specific functions for operating on agent expressions
+ Copyright 1998 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* $Id$ */
+
+#ifndef AX_GDB_H
+#define AX_GDB_H
+
+
+/* Types and enums */
+
+/* GDB stores expressions in the form of a flattened tree (struct
+ expression), so we just walk that tree and generate agent bytecodes
+ as we go along.
+
+ GDB's normal evaluation uses struct value, which contains the
+ expression's value as well as its address or the register it came
+ from. The `+' operator uses the value, whereas the unary `&'
+ operator will use the address portion. The `=' operator will use
+ the address or register number of its left hand side.
+
+ The issues are different when generating agent bytecode. Given a
+ variable reference expression, we should not necessarily generate
+ code to fetch its value, because the next operator may be `=' or
+ unary `&'. Instead, when we recurse on a subexpression, we
+ indicate whether we want that expression to produce an lvalue or an
+ rvalue. If we requested an lvalue, then the recursive call tells
+ us whether it generated code to compute an address on the stack, or
+ whether the lvalue lives in a register.
+
+ The `axs' prefix here means `agent expression, static', because
+ this is all static analysis of the expression, i.e. analysis which
+ doesn't depend on the contents of memory and registers. */
+
+
+/* Different kinds of agent expression static values. */
+enum axs_lvalue_kind {
+ /* We generated code to compute the subexpression's value.
+ Constants and arithmetic operators yield this. */
+ axs_rvalue,
+
+ /* We generated code to yield the subexpression's value's address on
+ the top of the stack. If the caller needs an rvalue, it should
+ call require_rvalue to produce the rvalue from this address. */
+ axs_lvalue_memory,
+
+ /* We didn't generate any code, and the stack is undisturbed,
+ because the subexpression's value lives in a register; u.reg is
+ the register number. If the caller needs an rvalue, it should
+ call require_rvalue to produce the rvalue from this register
+ number. */
+ axs_lvalue_register
+};
+
+/* Structure describing what we got from a subexpression. Think of
+ this as parallel to value.h's enum lval_type, except that we're
+ describing a value which will exist when the expression is
+ evaluated in the future, not a value we have in our hand. */
+struct axs_value {
+ enum axs_lvalue_kind kind; /* see above */
+
+ /* The type of the subexpression. Even if lvalue == axs_lvalue_memory,
+ this is the type of the value itself; the value on the stack is a
+ "pointer to" an object of this type. */
+ struct type *type;
+
+ union {
+ /* if kind == axs_lvalue_register, this is the register number */
+ int reg;
+ } u;
+};
+
+
+/* Translating GDB expressions into agent expressions. */
+
+/* Given a GDB expression EXPR, translate it into the agent bytecode,
+ and return it. FLAGS are from enum expr_to_agent_flags. */
+extern struct agent_expr *expr_to_agent PARAMS ((struct expression *EXPR,
+ struct axs_value *VALUE));
+
+/* Given a GDB expression EXPR denoting an lvalue in memory, produce a
+ string of agent bytecode which will leave its address and size on
+ the top of stack. Return the agent expression. */
+extern struct agent_expr *expr_to_address_and_size
+ PARAMS ((struct expression *EXPR));
+
+/* Given a GDB expression EXPR, return bytecode to trace its value.
+ The result will use the `trace' and `trace_quick' bytecodes to
+ record the value of all memory touched by the expression, and leave
+ no values on the stack. The caller can then use the ax_reqs
+ function to discover which registers the expression uses. */
+extern struct agent_expr *gen_trace_for_expr PARAMS ((CORE_ADDR,
+ struct expression *));
+
+#endif /* AX_GDB_H */
diff --git a/gdb/ax-general.c b/gdb/ax-general.c
new file mode 100644
index 00000000000..76e9bb462db
--- /dev/null
+++ b/gdb/ax-general.c
@@ -0,0 +1,552 @@
+/* Functions for manipulating expressions designed to be executed on the agent
+ Copyright 1998 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* $Id$ */
+
+/* Despite what the above comment says about this file being part of
+ GDB, we would like to keep these functions free of GDB
+ dependencies, since we want to be able to use them in contexts
+ outside of GDB (test suites, the stub, etc.) */
+
+#include "defs.h"
+#include "ax.h"
+
+
+/* Functions for building expressions. */
+
+/* Allocate a new, empty agent expression. */
+struct agent_expr *
+new_agent_expr (scope)
+ CORE_ADDR scope;
+{
+ struct agent_expr *x = xmalloc (sizeof (*x));
+ x->len = 0;
+ x->size = 1; /* Change this to a larger value once
+ reallocation code is tested. */
+ x->buf = xmalloc (x->size);
+ x->scope = scope;
+
+ return x;
+}
+
+/* Free a agent expression. */
+void
+free_agent_expr (x)
+ struct agent_expr *x;
+{
+ free (x->buf);
+ free (x);
+}
+
+
+/* Make sure that X has room for at least N more bytes. This doesn't
+ affect the length, just the allocated size. */
+static void
+grow_expr (x, n)
+ struct agent_expr *x;
+ int n;
+{
+ if (x->len + n > x->size)
+ {
+ x->size *= 2;
+ if (x->size < x->len + n)
+ x->size = x->len + n + 10;
+ x->buf = xrealloc (x->buf, x->size);
+ }
+}
+
+
+/* Append the low N bytes of VAL as an N-byte integer to the
+ expression X, in big-endian order. */
+static void
+append_const (x, val, n)
+ struct agent_expr *x;
+ LONGEST val;
+ int n;
+{
+ int i;
+
+ grow_expr (x, n);
+ for (i = n - 1; i >= 0; i--)
+ {
+ x->buf[x->len + i] = val & 0xff;
+ val >>= 8;
+ }
+ x->len += n;
+}
+
+
+/* Extract an N-byte big-endian unsigned integer from expression X at
+ offset O. */
+static LONGEST
+read_const (x, o, n)
+ struct agent_expr *x;
+ int o, n;
+{
+ int i;
+ LONGEST accum = 0;
+
+ /* Make sure we're not reading off the end of the expression. */
+ if (o + n > x->len)
+ error ("GDB bug: ax-general.c (read_const): incomplete constant");
+
+ for (i = 0; i < n; i++)
+ accum = (accum << 8) | x->buf[o + i];
+
+ return accum;
+}
+
+
+/* Append a simple operator OP to EXPR. */
+void
+ax_simple (x, op)
+ struct agent_expr *x;
+ enum agent_op op;
+{
+ grow_expr (x, 1);
+ x->buf[x->len++] = op;
+}
+
+
+/* Append a sign-extension or zero-extension instruction to EXPR, to
+ extend an N-bit value. */
+static void
+generic_ext (x, op, n)
+ struct agent_expr *x;
+ enum agent_op op;
+ int n;
+{
+ /* N must fit in a byte. */
+ if (n < 0 || n > 255)
+ error ("GDB bug: ax-general.c (generic_ext): bit count out of range");
+ /* That had better be enough range. */
+ if (sizeof (LONGEST) * 8 > 255)
+ error ("GDB bug: ax-general.c (generic_ext): opcode has inadequate range");
+
+ grow_expr (x, 2);
+ x->buf[x->len++] = op;
+ x->buf[x->len++] = n;
+}
+
+
+/* Append a sign-extension instruction to EXPR, to extend an N-bit value. */
+void
+ax_ext (x, n)
+ struct agent_expr *x;
+ int n;
+{
+ generic_ext (x, aop_ext, n);
+}
+
+
+/* Append a zero-extension instruction to EXPR, to extend an N-bit value. */
+void
+ax_zero_ext (x, n)
+ struct agent_expr *x;
+ int n;
+{
+ generic_ext (x, aop_zero_ext, n);
+}
+
+
+/* Append a trace_quick instruction to EXPR, to record N bytes. */
+void
+ax_trace_quick (x, n)
+ struct agent_expr *x;
+ int n;
+{
+ /* N must fit in a byte. */
+ if (n < 0 || n > 255)
+ error ("GDB bug: ax-general.c (ax_trace_quick): size out of range for trace_quick");
+
+ grow_expr (x, 2);
+ x->buf[x->len++] = aop_trace_quick;
+ x->buf[x->len++] = n;
+}
+
+
+/* Append a goto op to EXPR. OP is the actual op (must be aop_goto or
+ aop_if_goto). We assume we don't know the target offset yet,
+ because it's probably a forward branch, so we leave space in EXPR
+ for the target, and return the offset in EXPR of that space, so we
+ can backpatch it once we do know the target offset. Use ax_label
+ to do the backpatching. */
+int ax_goto (x, op)
+ struct agent_expr *x;
+ enum agent_op op;
+{
+ grow_expr (x, 3);
+ x->buf[x->len + 0] = op;
+ x->buf[x->len + 1] = 0xff;
+ x->buf[x->len + 2] = 0xff;
+ x->len += 3;
+ return x->len - 2;
+}
+
+/* Suppose a given call to ax_goto returns some value PATCH. When you
+ know the offset TARGET that goto should jump to, call
+ ax_label (EXPR, PATCH, TARGET)
+ to patch TARGET into the ax_goto instruction. */
+void
+ax_label (x, patch, target)
+ struct agent_expr *x;
+ int patch;
+ int target;
+{
+ /* Make sure the value is in range. Don't accept 0xffff as an
+ offset; that's our magic sentinel value for unpatched branches. */
+ if (target < 0 || target >= 0xffff)
+ error ("GDB bug: ax-general.c (ax_label): label target out of range");
+
+ x->buf[patch] = (target >> 8) & 0xff;
+ x->buf[patch + 1] = target & 0xff;
+}
+
+
+/* Assemble code to push a constant on the stack. */
+void
+ax_const_l (x, l)
+ struct agent_expr *x;
+ LONGEST l;
+{
+ static enum agent_op ops[]
+ = { aop_const8, aop_const16, aop_const32, aop_const64 };
+ int size;
+ int op;
+
+ /* How big is the number? 'op' keeps track of which opcode to use.
+ Notice that we don't really care whether the original number was
+ signed or unsigned; we always reproduce the value exactly, and
+ use the shortest representation. */
+ for (op = 0, size = 8; size < 64; size *= 2, op++)
+ if (-((LONGEST) 1 << size) <= l && l < ((LONGEST) 1 << size))
+ break;
+
+ /* Emit the right opcode... */
+ ax_simple (x, ops[op]);
+
+ /* Emit the low SIZE bytes as an unsigned number. We know that
+ sign-extending this will yield l. */
+ append_const (x, l, size / 8);
+
+ /* Now, if it was negative, and not full-sized, sign-extend it. */
+ if (l < 0 && size < 64)
+ ax_ext (x, size);
+}
+
+
+void
+ax_const_d (x, d)
+ struct agent_expr *x;
+ LONGEST d;
+{
+ /* FIXME: floating-point support not present yet. */
+ error ("GDB bug: ax-general.c (ax_const_d): floating point not supported yet");
+}
+
+
+/* Assemble code to push the value of register number REG on the
+ stack. */
+void ax_reg (x, reg)
+ struct agent_expr *x;
+ int reg;
+{
+ /* Make sure the register number is in range. */
+ if (reg < 0 || reg > 0xffff)
+ error ("GDB bug: ax-general.c (ax_reg): register number out of range");
+ grow_expr (x, 3);
+ x->buf[x->len ] = aop_reg;
+ x->buf[x->len + 1] = (reg >> 8) & 0xff;
+ x->buf[x->len + 2] = (reg ) & 0xff;
+ x->len += 3;
+}
+
+
+
+/* Functions for disassembling agent expressions, and otherwise
+ debugging the expression compiler. */
+
+struct aop_map aop_map[] = {
+ { 0, 0, 0, 0, 0 },
+ { "float", 0, 0, 0, 0 }, /* 0x01 */
+ { "add", 0, 0, 2, 1 }, /* 0x02 */
+ { "sub", 0, 0, 2, 1 }, /* 0x03 */
+ { "mul", 0, 0, 2, 1 }, /* 0x04 */
+ { "div_signed", 0, 0, 2, 1 }, /* 0x05 */
+ { "div_unsigned", 0, 0, 2, 1 }, /* 0x06 */
+ { "rem_signed", 0, 0, 2, 1 }, /* 0x07 */
+ { "rem_unsigned", 0, 0, 2, 1 }, /* 0x08 */
+ { "lsh", 0, 0, 2, 1 }, /* 0x09 */
+ { "rsh_signed", 0, 0, 2, 1 }, /* 0x0a */
+ { "rsh_unsigned", 0, 0, 2, 1 }, /* 0x0b */
+ { "trace", 0, 0, 2, 0 }, /* 0x0c */
+ { "trace_quick", 1, 0, 1, 1 }, /* 0x0d */
+ { "log_not", 0, 0, 1, 1 }, /* 0x0e */
+ { "bit_and", 0, 0, 2, 1 }, /* 0x0f */
+ { "bit_or", 0, 0, 2, 1 }, /* 0x10 */
+ { "bit_xor", 0, 0, 2, 1 }, /* 0x11 */
+ { "bit_not", 0, 0, 1, 1 }, /* 0x12 */
+ { "equal", 0, 0, 2, 1 }, /* 0x13 */
+ { "less_signed", 0, 0, 2, 1 }, /* 0x14 */
+ { "less_unsigned", 0, 0, 2, 1 }, /* 0x15 */
+ { "ext", 1, 0, 1, 1 }, /* 0x16 */
+ { "ref8", 0, 8, 1, 1 }, /* 0x17 */
+ { "ref16", 0, 16, 1, 1 }, /* 0x18 */
+ { "ref32", 0, 32, 1, 1 }, /* 0x19 */
+ { "ref64", 0, 64, 1, 1 }, /* 0x1a */
+ { "ref_float", 0, 0, 1, 1 }, /* 0x1b */
+ { "ref_double", 0, 0, 1, 1 }, /* 0x1c */
+ { "ref_long_double", 0, 0, 1, 1 }, /* 0x1d */
+ { "l_to_d", 0, 0, 1, 1 }, /* 0x1e */
+ { "d_to_l", 0, 0, 1, 1 }, /* 0x1f */
+ { "if_goto", 2, 0, 1, 0 }, /* 0x20 */
+ { "goto", 2, 0, 0, 0 }, /* 0x21 */
+ { "const8", 1, 8, 0, 1 }, /* 0x22 */
+ { "const16", 2, 16, 0, 1 }, /* 0x23 */
+ { "const32", 4, 32, 0, 1 }, /* 0x24 */
+ { "const64", 8, 64, 0, 1 }, /* 0x25 */
+ { "reg", 2, 0, 0, 1 }, /* 0x26 */
+ { "end", 0, 0, 0, 0 }, /* 0x27 */
+ { "dup", 0, 0, 1, 2 }, /* 0x28 */
+ { "pop", 0, 0, 1, 0 }, /* 0x29 */
+ { "zero_ext", 1, 0, 1, 1 }, /* 0x2a */
+ { "swap", 0, 0, 2, 2 }, /* 0x2b */
+ { 0, 0, 0, 0, 0 }, /* 0x2c */
+ { 0, 0, 0, 0, 0 }, /* 0x2d */
+ { 0, 0, 0, 0, 0 }, /* 0x2e */
+ { 0, 0, 0, 0, 0 }, /* 0x2f */
+ { "trace16", 2, 0, 1, 1 }, /* 0x30 */
+};
+
+
+/* Disassemble the expression EXPR, writing to F. */
+void
+ax_print (f, x)
+ GDB_FILE *f;
+ struct agent_expr *x;
+{
+ int i;
+ int is_float = 0;
+
+ /* Check the size of the name array against the number of entries in
+ the enum, to catch additions that people didn't sync. */
+ if ((sizeof (aop_map) / sizeof (aop_map[0]))
+ != aop_last)
+ error ("GDB bug: ax-general.c (ax_print): opcode map out of sync");
+
+ for (i = 0; i < x->len; )
+ {
+ enum agent_op op = x->buf[i];
+
+ if (op >= (sizeof (aop_map) / sizeof (aop_map[0]))
+ || ! aop_map[op].name)
+ {
+ fprintf_filtered (f, "%3d <bad opcode %02x>\n", i, op);
+ i++;
+ continue;
+ }
+ if (i + 1 + aop_map[op].op_size > x->len)
+ {
+ fprintf_filtered (f, "%3d <incomplete opcode %s>\n",
+ i, aop_map[op].name);
+ break;
+ }
+
+ fprintf_filtered (f, "%3d %s", i, aop_map[op].name);
+ if (aop_map[op].op_size > 0)
+ {
+ fputs_filtered (" ", f);
+
+ print_longest (f, 'd', 0,
+ read_const (x, i + 1, aop_map[op].op_size));
+ }
+ fprintf_filtered (f, "\n");
+ i += 1 + aop_map[op].op_size;
+
+ is_float = (op == aop_float);
+ }
+}
+
+
+/* Given an agent expression AX, fill in an agent_reqs structure REQS
+ describing it. */
+void
+ax_reqs (ax, reqs)
+ struct agent_expr *ax;
+ struct agent_reqs *reqs;
+{
+ int i;
+ int height;
+
+ /* Bit vector for registers used. */
+ int reg_mask_len = 1;
+ unsigned char *reg_mask = xmalloc (reg_mask_len * sizeof (reg_mask[0]));
+
+ /* Jump target table. targets[i] is non-zero iff there is a jump to
+ offset i. */
+ char *targets = (char *) alloca (ax->len * sizeof (targets[0]));
+
+ /* Instruction boundary table. boundary[i] is non-zero iff an
+ instruction starts at offset i. */
+ char *boundary = (char *) alloca (ax->len * sizeof (boundary[0]));
+
+ /* Stack height record. iff either targets[i] or boundary[i] is
+ non-zero, heights[i] is the height the stack should have before
+ executing the bytecode at that point. */
+ int *heights = (int *) alloca (ax->len * sizeof (heights[0]));
+
+ /* Pointer to a description of the present op. */
+ struct aop_map *op;
+
+ memset (reg_mask, 0, reg_mask_len * sizeof (reg_mask[0]));
+ memset (targets, 0, ax->len * sizeof (targets[0]));
+ memset (boundary, 0, ax->len * sizeof (boundary[0]));
+
+ reqs->max_height = reqs->min_height = height = 0;
+ reqs->flaw = agent_flaw_none;
+ reqs->max_data_size = 0;
+
+ for (i = 0; i < ax->len; i += 1 + op->op_size)
+ {
+ if (ax->buf[i] > (sizeof (aop_map) / sizeof (aop_map[0])))
+ {
+ reqs->flaw = agent_flaw_bad_instruction;
+ free (reg_mask);
+ return;
+ }
+
+ op = &aop_map[ax->buf[i]];
+
+ if (! op->name)
+ {
+ reqs->flaw = agent_flaw_bad_instruction;
+ free (reg_mask);
+ return;
+ }
+
+ if (i + 1 + op->op_size > ax->len)
+ {
+ reqs->flaw = agent_flaw_incomplete_instruction;
+ free (reg_mask);
+ return;
+ }
+
+ /* If this instruction is a jump target, does the current stack
+ height match the stack height at the jump source? */
+ if (targets[i] && (heights[i] != height))
+ {
+ reqs->flaw = agent_flaw_height_mismatch;
+ free (reg_mask);
+ return;
+ }
+
+ boundary[i] = 1;
+ heights[i] = height;
+
+ height -= op->consumed;
+ if (height < reqs->min_height)
+ reqs->min_height = height;
+ height += op->produced;
+ if (height > reqs->max_height)
+ reqs->max_height = height;
+
+ if (op->data_size > reqs->max_data_size)
+ reqs->max_data_size = op->data_size;
+
+ /* For jump instructions, check that the target is a valid
+ offset. If it is, record the fact that that location is a
+ jump target, and record the height we expect there. */
+ if (aop_goto == op - aop_map
+ || aop_if_goto == op - aop_map)
+ {
+ int target = read_const (ax, i + 1, 2);
+ if (target < 0 || target >= ax->len)
+ {
+ reqs->flaw = agent_flaw_bad_jump;
+ free (reg_mask);
+ return;
+ }
+ /* Have we already found other jumps to the same location? */
+ else if (targets[target])
+ {
+ if (heights[i] != height)
+ {
+ reqs->flaw = agent_flaw_height_mismatch;
+ free (reg_mask);
+ return;
+ }
+ }
+ else
+ {
+ targets[target] = 1;
+ heights[target] = height;
+ }
+ }
+
+ /* For unconditional jumps with a successor, check that the
+ successor is a target, and pick up its stack height. */
+ if (aop_goto == op - aop_map
+ && i + 3 < ax->len)
+ {
+ if (! targets[i + 3])
+ {
+ reqs->flaw = agent_flaw_hole;
+ free (reg_mask);
+ return;
+ }
+
+ height = heights[i + 3];
+ }
+
+ /* For reg instructions, record the register in the bit mask. */
+ if (aop_reg == op - aop_map)
+ {
+ int reg = read_const (ax, i + 1, 2);
+ int byte = reg / 8;
+
+ /* Grow the bit mask if necessary. */
+ if (byte >= reg_mask_len)
+ {
+ /* It's not appropriate to double here. This isn't a
+ string buffer. */
+ int new_len = byte + 1;
+ reg_mask = xrealloc (reg_mask,
+ new_len * sizeof (reg_mask[0]));
+ memset (reg_mask + reg_mask_len, 0,
+ (new_len - reg_mask_len) * sizeof (reg_mask[0]));
+ reg_mask_len = new_len;
+ }
+
+ reg_mask[byte] |= 1 << (reg % 8);
+ }
+ }
+
+ /* Check that all the targets are on boundaries. */
+ for (i = 0; i < ax->len; i++)
+ if (targets[i] && !boundary[i])
+ {
+ reqs->flaw = agent_flaw_bad_jump;
+ free (reg_mask);
+ return;
+ }
+
+ reqs->final_height = height;
+ reqs->reg_mask_len = reg_mask_len;
+ reqs->reg_mask = reg_mask;
+}
diff --git a/gdb/ax.h b/gdb/ax.h
new file mode 100644
index 00000000000..2ee0f0bdb41
--- /dev/null
+++ b/gdb/ax.h
@@ -0,0 +1,285 @@
+/* Definitions for expressions designed to be executed on the agent
+ Copyright 1998 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* $Id$ */
+
+#ifndef AGENTEXPR_H
+#define AGENTEXPR_H
+
+/* It's sometimes useful to be able to debug programs that you can't
+ really stop for more than a fraction of a second. To this end, the
+ user can specify a tracepoint (like a breakpoint, but you don't
+ stop at it), and specify a bunch of expressions to record the
+ values of when that tracepoint is reached. As the program runs,
+ GDB collects the values. At any point (possibly while values are
+ still being collected), the user can display the collected values.
+
+ This is used with remote debugging; we don't really support it on
+ native configurations.
+
+ This means that expressions are being evaluated by the remote agent,
+ which doesn't have any access to the symbol table information, and
+ needs to be small and simple.
+
+ The agent_expr routines and datatypes are a bytecode language
+ designed to be executed by the agent. Agent expressions work in
+ terms of fixed-width values, operators, memory references, and
+ register references. You can evaluate a agent expression just given
+ a bunch of memory and register values to sniff at; you don't need
+ any symbolic information like variable names, types, etc.
+
+ GDB translates source expressions, whose meaning depends on
+ symbolic information, into agent bytecode expressions, whose meaning
+ is independent of symbolic information. This means the agent can
+ evaluate them on the fly without reference to data only available
+ to the host GDB. */
+
+
+/* Agent expression data structures. */
+
+/* The type of an element of the agent expression stack.
+ The bytecode operation indicates which element we should access;
+ the value itself has no typing information. GDB generates all
+ bytecode streams, so we don't have to worry about type errors. */
+
+union agent_val {
+ LONGEST l;
+ DOUBLEST d;
+};
+
+/* A buffer containing a agent expression. */
+struct agent_expr {
+ unsigned char *buf;
+ int len; /* number of characters used */
+ int size; /* allocated size */
+ CORE_ADDR scope;
+};
+
+
+
+
+/* The actual values of the various bytecode operations.
+
+ Other independent implementations of the agent bytecode engine will
+ rely on the exact values of these enums, and may not be recompiled
+ when we change this table. The numeric values should remain fixed
+ whenever possible. Thus, we assign them values explicitly here (to
+ allow gaps to form safely), and the disassembly table in
+ agentexpr.h behaves like an opcode map. If you want to see them
+ grouped logically, see doc/agentexpr.texi. */
+
+enum agent_op {
+ aop_float = 0x01,
+ aop_add = 0x02,
+ aop_sub = 0x03,
+ aop_mul = 0x04,
+ aop_div_signed = 0x05,
+ aop_div_unsigned = 0x06,
+ aop_rem_signed = 0x07,
+ aop_rem_unsigned = 0x08,
+ aop_lsh = 0x09,
+ aop_rsh_signed = 0x0a,
+ aop_rsh_unsigned = 0x0b,
+ aop_trace = 0x0c,
+ aop_trace_quick = 0x0d,
+ aop_log_not = 0x0e,
+ aop_bit_and = 0x0f,
+ aop_bit_or = 0x10,
+ aop_bit_xor = 0x11,
+ aop_bit_not = 0x12,
+ aop_equal = 0x13,
+ aop_less_signed = 0x14,
+ aop_less_unsigned = 0x15,
+ aop_ext = 0x16,
+ aop_ref8 = 0x17,
+ aop_ref16 = 0x18,
+ aop_ref32 = 0x19,
+ aop_ref64 = 0x1a,
+ aop_ref_float = 0x1b,
+ aop_ref_double = 0x1c,
+ aop_ref_long_double = 0x1d,
+ aop_l_to_d = 0x1e,
+ aop_d_to_l = 0x1f,
+ aop_if_goto = 0x20,
+ aop_goto = 0x21,
+ aop_const8 = 0x22,
+ aop_const16 = 0x23,
+ aop_const32 = 0x24,
+ aop_const64 = 0x25,
+ aop_reg = 0x26,
+ aop_end = 0x27,
+ aop_dup = 0x28,
+ aop_pop = 0x29,
+ aop_zero_ext = 0x2a,
+ aop_swap = 0x2b,
+ aop_trace16 = 0x30,
+ aop_last
+};
+
+
+
+/* Functions for building expressions. */
+
+/* Allocate a new, empty agent expression. */
+extern struct agent_expr *new_agent_expr PARAMS ((CORE_ADDR));
+
+/* Free a agent expression. */
+extern void free_agent_expr PARAMS ((struct agent_expr *));
+
+/* Append a simple operator OP to EXPR. */
+extern void ax_simple PARAMS ((struct agent_expr *EXPR, enum agent_op OP));
+
+/* Append the floating-point prefix, for the next bytecode. */
+#define ax_float(EXPR) (ax_simple ((EXPR), aop_float))
+
+/* Append a sign-extension instruction to EXPR, to extend an N-bit value. */
+extern void ax_ext PARAMS ((struct agent_expr *EXPR, int N));
+
+/* Append a zero-extension instruction to EXPR, to extend an N-bit value. */
+extern void ax_zero_ext PARAMS ((struct agent_expr *EXPR, int N));
+
+/* Append a trace_quick instruction to EXPR, to record N bytes. */
+extern void ax_trace_quick PARAMS ((struct agent_expr *EXPR, int N));
+
+/* Append a goto op to EXPR. OP is the actual op (must be aop_goto or
+ aop_if_goto). We assume we don't know the target offset yet,
+ because it's probably a forward branch, so we leave space in EXPR
+ for the target, and return the offset in EXPR of that space, so we
+ can backpatch it once we do know the target offset. Use ax_label
+ to do the backpatching. */
+extern int ax_goto PARAMS ((struct agent_expr *EXPR, enum agent_op OP));
+
+/* Suppose a given call to ax_goto returns some value PATCH. When you
+ know the offset TARGET that goto should jump to, call
+ ax_label (EXPR, PATCH, TARGET)
+ to patch TARGET into the ax_goto instruction. */
+extern void ax_label PARAMS ((struct agent_expr *EXPR, int patch, int target));
+
+/* Assemble code to push a constant on the stack. */
+extern void ax_const_l PARAMS ((struct agent_expr *EXPR, LONGEST l));
+extern void ax_const_d PARAMS ((struct agent_expr *EXPR, LONGEST d));
+
+/* Assemble code to push the value of register number REG on the
+ stack. */
+extern void ax_reg PARAMS ((struct agent_expr *EXPR, int REG));
+
+
+/* Functions for printing out expressions, and otherwise debugging
+ things. */
+
+/* Disassemble the expression EXPR, writing to F. */
+extern void ax_print PARAMS ((GDB_FILE *f, struct agent_expr *EXPR));
+
+/* An entry in the opcode map. */
+struct aop_map {
+
+ /* The name of the opcode. Null means that this entry is not a
+ valid opcode --- a hole in the opcode space. */
+ char *name;
+
+ /* All opcodes take no operands from the bytecode stream, or take
+ unsigned integers of various sizes. If this is a positive number
+ n, then the opcode is followed by an n-byte operand, which should
+ be printed as an unsigned integer. If this is zero, then the
+ opcode takes no operands from the bytecode stream.
+
+ If we get more complicated opcodes in the future, don't add other
+ magic values of this; that's a crock. Add an `enum encoding'
+ field to this, or something like that. */
+ int op_size;
+
+ /* The size of the data operated upon, in bits, for bytecodes that
+ care about that (ref and const). Zero for all others. */
+ int data_size;
+
+ /* Number of stack elements consumed, and number produced. */
+ int consumed, produced;
+};
+
+/* Map of the bytecodes, indexed by bytecode number. */
+extern struct aop_map aop_map[];
+
+/* Different kinds of flaws an agent expression might have, as
+ detected by agent_reqs. */
+enum agent_flaws {
+ agent_flaw_none = 0, /* code is good */
+
+ /* There is an invalid instruction in the stream. */
+ agent_flaw_bad_instruction,
+
+ /* There is an incomplete instruction at the end of the expression. */
+ agent_flaw_incomplete_instruction,
+
+ /* agent_reqs was unable to prove that every jump target is to a
+ valid offset. Valid offsets are within the bounds of the
+ expression, and to a valid instruction boundary. */
+ agent_flaw_bad_jump,
+
+ /* agent_reqs was unable to prove to its satisfaction that, for each
+ jump target location, the stack will have the same height whether
+ that location is reached via a jump or by straight execution. */
+ agent_flaw_height_mismatch,
+
+ /* agent_reqs was unable to prove that every instruction following
+ an unconditional jump was the target of some other jump. */
+ agent_flaw_hole
+};
+
+/* Structure describing the requirements of a bytecode expression. */
+struct agent_reqs {
+
+ /* If the following is not equal to agent_flaw_none, the rest of the
+ information in this structure is suspect. */
+ enum agent_flaws flaw;
+
+ /* Number of elements left on stack at end; may be negative if expr
+ only consumes elements. */
+ int final_height;
+
+ /* Maximum and minimum stack height, relative to initial height. */
+ int max_height, min_height;
+
+ /* Largest `ref' or `const' opcode used, in bits. Zero means the
+ expression has no such instructions. */
+ int max_data_size;
+
+ /* Bit vector of registers used. Register R is used iff
+
+ reg_mask[R / 8] & (1 << (R % 8))
+
+ is non-zero. Note! You may not assume that this bitmask is long
+ enough to hold bits for all the registers of the machine; the
+ agent expression code has no idea how many registers the machine
+ has. However, the bitmask is reg_mask_len bytes long, so the
+ valid register numbers run from 0 to reg_mask_len * 8 - 1.
+
+ We're assuming eight-bit bytes. So sue me.
+
+ The caller should free reg_list when done. */
+ int reg_mask_len;
+ unsigned char *reg_mask;
+};
+
+
+/* Given an agent expression AX, fill in an agent_reqs structure REQS
+ describing it. */
+extern void ax_reqs PARAMS ((struct agent_expr *ax,
+ struct agent_reqs *reqs));
+
+#endif /* AGENTEXPR_H */
diff --git a/gdb/bcache.c b/gdb/bcache.c
new file mode 100644
index 00000000000..d28515b846c
--- /dev/null
+++ b/gdb/bcache.c
@@ -0,0 +1,219 @@
+/* Implement a cached obstack.
+ Written by Fred Fish (fnf@cygnus.com)
+ Copyright 1995, 1998 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "obstack.h"
+#include "bcache.h"
+#include "gdb_string.h" /* For memcpy declaration */
+
+/* Prototypes for local functions. */
+
+static unsigned int hash PARAMS ((void *, int));
+
+static void *lookup_cache PARAMS ((void *, int, int, struct bcache *));
+
+/* FIXME: Incredibly simplistic hash generator. Probably way too expensive
+ (consider long strings) and unlikely to have good distribution across hash
+ values for typical input. */
+
+static unsigned int
+hash (bytes, count)
+ void *bytes;
+ int count;
+{
+ unsigned int len;
+ unsigned long hashval;
+ unsigned int c;
+ const unsigned char *data = bytes;
+
+ hashval = 0;
+ len = 0;
+ while (count-- > 0)
+ {
+ c = *data++;
+ hashval += c + (c << 17);
+ hashval ^= hashval >> 2;
+ ++len;
+ }
+ hashval += len + (len << 17);
+ hashval ^= hashval >> 2;
+ return (hashval % BCACHE_HASHSIZE);
+}
+
+static void *
+lookup_cache (bytes, count, hashval, bcachep)
+ void *bytes;
+ int count;
+ int hashval;
+ struct bcache *bcachep;
+{
+ void *location = NULL;
+ struct hashlink **hashtablep;
+ struct hashlink *linkp;
+
+ hashtablep = bcachep -> indextable[count];
+ if (hashtablep != NULL)
+ {
+ linkp = hashtablep[hashval];
+ while (linkp != NULL)
+ {
+ if (memcmp (BCACHE_DATA (linkp), bytes, count) == 0)
+ {
+ location = BCACHE_DATA (linkp);
+ break;
+ }
+ linkp = linkp -> next;
+ }
+ }
+ return (location);
+}
+
+void *
+bcache (bytes, count, bcachep)
+ void *bytes;
+ int count;
+ struct bcache *bcachep;
+{
+ int hashval;
+ void *location;
+ struct hashlink *newlink;
+ struct hashlink **linkpp;
+ struct hashlink ***hashtablepp;
+
+ if (count >= BCACHE_MAXLENGTH)
+ {
+ /* Rare enough to just stash unique copies */
+ location = (void *) obstack_alloc (&bcachep->cache, count);
+ bcachep -> cache_bytes += count;
+ memcpy (location, bytes, count);
+ bcachep -> bcache_overflows++;
+ }
+ else
+ {
+ hashval = hash (bytes, count);
+ location = lookup_cache (bytes, count, hashval, bcachep);
+ if (location != NULL)
+ {
+ bcachep -> cache_savings += count;
+ bcachep -> cache_hits++;
+ }
+ else
+ {
+ bcachep -> cache_misses++;
+ hashtablepp = &bcachep -> indextable[count];
+ if (*hashtablepp == NULL)
+ {
+ *hashtablepp = (struct hashlink **)
+ obstack_alloc (&bcachep->cache, BCACHE_HASHSIZE * sizeof (struct hashlink *));
+ bcachep -> cache_bytes += BCACHE_HASHSIZE * sizeof (struct hashlink *);
+ memset (*hashtablepp, 0, BCACHE_HASHSIZE * sizeof (struct hashlink *));
+ }
+ linkpp = &(*hashtablepp)[hashval];
+ newlink = (struct hashlink *)
+ obstack_alloc (&bcachep->cache, BCACHE_DATA_ALIGNMENT + count);
+ bcachep -> cache_bytes += BCACHE_DATA_ALIGNMENT + count;
+ memcpy (BCACHE_DATA (newlink), bytes, count);
+ newlink -> next = *linkpp;
+ *linkpp = newlink;
+ location = BCACHE_DATA (newlink);
+ }
+ }
+ return (location);
+}
+
+#if MAINTENANCE_CMDS
+
+void
+print_bcache_statistics (bcachep, id)
+ struct bcache *bcachep;
+ char *id;
+{
+ struct hashlink **hashtablep;
+ struct hashlink *linkp;
+ int tidx, tcount, hidx, hcount, lcount, lmax, temp, lmaxt, lmaxh;
+
+ for (lmax = lcount = tcount = hcount = tidx = 0; tidx < BCACHE_MAXLENGTH; tidx++)
+ {
+ hashtablep = bcachep -> indextable[tidx];
+ if (hashtablep != NULL)
+ {
+ tcount++;
+ for (hidx = 0; hidx < BCACHE_HASHSIZE; hidx++)
+ {
+ linkp = hashtablep[hidx];
+ if (linkp != NULL)
+ {
+ hcount++;
+ for (temp = 0; linkp != NULL; linkp = linkp -> next)
+ {
+ lcount++;
+ temp++;
+ }
+ if (temp > lmax)
+ {
+ lmax = temp;
+ lmaxt = tidx;
+ lmaxh = hidx;
+ }
+ }
+ }
+ }
+ }
+ printf_filtered (" Cached '%s' statistics:\n", id);
+ printf_filtered (" Cache hits: %d\n", bcachep -> cache_hits);
+ printf_filtered (" Cache misses: %d\n", bcachep -> cache_misses);
+ printf_filtered (" Cache hit ratio: ");
+ if (bcachep -> cache_hits + bcachep -> cache_misses > 0)
+ {
+ printf_filtered ("%d%%\n", ((bcachep -> cache_hits) * 100) /
+ (bcachep -> cache_hits + bcachep -> cache_misses));
+ }
+ else
+ {
+ printf_filtered ("(not applicable)\n");
+ }
+ printf_filtered (" Space used for caching: %d\n", bcachep -> cache_bytes);
+ printf_filtered (" Space saved by cache hits: %d\n", bcachep -> cache_savings);
+ printf_filtered (" Number of bcache overflows: %d\n", bcachep -> bcache_overflows);
+ printf_filtered (" Number of index buckets used: %d\n", tcount);
+ printf_filtered (" Number of hash table buckets used: %d\n", hcount);
+ printf_filtered (" Number of chained items: %d\n", lcount);
+ printf_filtered (" Average hash table population: ");
+ if (tcount > 0)
+ {
+ printf_filtered ("%d%%\n", (hcount * 100) / (tcount * BCACHE_HASHSIZE));
+ }
+ else
+ {
+ printf_filtered ("(not applicable)\n");
+ }
+ printf_filtered (" Average chain length ");
+ if (hcount > 0)
+ {
+ printf_filtered ("%d\n", lcount / hcount);
+ }
+ else
+ {
+ printf_filtered ("(not applicable)\n");
+ }
+ printf_filtered (" Maximum chain length %d at %d:%d\n", lmax, lmaxt, lmaxh);
+}
+
+#endif /* MAINTENANCE_CMDS */
diff --git a/gdb/bcache.h b/gdb/bcache.h
new file mode 100644
index 00000000000..cf0c62eeda1
--- /dev/null
+++ b/gdb/bcache.h
@@ -0,0 +1,72 @@
+/* Include file cached obstack implementation.
+ Written by Fred Fish (fnf@cygnus.com)
+ Copyright 1995 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef BCACHE_H
+#define BCACHE_H 1
+
+#define BCACHE_HASHLENGTH 12 /* Number of bits in hash value */
+#define BCACHE_HASHSIZE (1 << BCACHE_HASHLENGTH)
+#define BCACHE_MAXLENGTH 128
+
+/* Note that the user data is stored in data[]. Since it can be any type,
+ it needs to have the same alignment as the most strict alignment of
+ any type on the host machine. So do it the same way obstack does. */
+
+struct hashlink {
+ struct hashlink *next;
+ union {
+ char data[1];
+ double dummy;
+ } d;
+};
+
+/* BCACHE_DATA is used to get the address of the cached data. */
+
+#define BCACHE_DATA(p) ((p)->d.data)
+
+/* BCACHE_DATA_ALIGNMENT is used to get the offset of the start of
+ cached data within the hashlink struct. This value, plus the
+ size of the cached data, is the amount of space to allocate for
+ a hashlink struct to hold the next pointer and the data. */
+
+#define BCACHE_DATA_ALIGNMENT \
+ (((char *) BCACHE_DATA((struct hashlink*) 0) - (char *) 0))
+
+struct bcache {
+ struct obstack cache;
+ struct hashlink **indextable[BCACHE_MAXLENGTH];
+ int cache_hits;
+ int cache_misses;
+ int cache_bytes;
+ int cache_savings;
+ int bcache_overflows;
+};
+
+extern void *
+bcache PARAMS ((void *bytes, int count, struct bcache *bcachep));
+
+#if MAINTENANCE_CMDS
+
+extern void
+print_bcache_statistics PARAMS ((struct bcache *, char *));
+
+#endif /* MAINTENANCE_CMDS */
+
+#endif /* BCACHE_H */
diff --git a/gdb/blockframe.c b/gdb/blockframe.c
new file mode 100644
index 00000000000..9366ca650e2
--- /dev/null
+++ b/gdb/blockframe.c
@@ -0,0 +1,1301 @@
+/* Get info from stack frames;
+ convert between frames, blocks, functions and pc values.
+ Copyright 1986, 87, 88, 89, 91, 94, 95, 96, 97, 1998
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 */
+#include "annotate.h"
+
+/* Prototypes for exported functions. */
+
+void _initialize_blockframe PARAMS ((void));
+
+/* 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. */
+
+int
+default_frame_chain_valid (chain, thisframe)
+ CORE_ADDR chain;
+ struct frame_info *thisframe;
+{
+ return ((chain) != 0
+ && !inside_main_func ((thisframe) -> pc)
+ && !inside_entry_func ((thisframe) -> pc));
+}
+
+/* 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. */
+
+int
+alternate_frame_chain_valid (chain, thisframe)
+ CORE_ADDR chain;
+ struct frame_info *thisframe;
+{
+ return ((chain) != 0
+ && !inside_entry_file (FRAME_SAVED_PC (thisframe)));
+}
+
+/* A very simple method of determining a valid frame */
+
+int
+nonnull_frame_chain_valid (chain, thisframe)
+ CORE_ADDR chain;
+ struct frame_info *thisframe;
+{
+ return ((chain) != 0);
+}
+
+/* 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. */
+/* FIXME: Won't always work with zeros for the last two arguments */
+ 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;
+
+ /* If the addr range is not set up at symbol reading time, set it up now.
+ This is for FRAME_CHAIN_VALID_ALTERNATE. I do this for coff, because
+ it is unable to set it up and symbol reading time. */
+
+ if (symfile_objfile -> ei.main_func_lowpc == INVALID_ENTRY_LOWPC &&
+ symfile_objfile -> ei.main_func_highpc == INVALID_ENTRY_HIGHPC)
+ {
+ struct symbol *mainsym;
+
+ mainsym = lookup_symbol ("main", NULL, VAR_NAMESPACE, NULL, NULL);
+ if (mainsym && SYMBOL_CLASS(mainsym) == LOC_BLOCK)
+ {
+ symfile_objfile->ei.main_func_lowpc =
+ BLOCK_START (SYMBOL_BLOCK_VALUE (mainsym));
+ symfile_objfile->ei.main_func_highpc =
+ BLOCK_END (SYMBOL_BLOCK_VALUE (mainsym));
+ }
+ }
+ 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. */
+/* FIXME: Won't always work with zeros for the last two arguments */
+ 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);
+}
+
+/* Info about the innermost stack frame (contents of FP register) */
+
+static struct frame_info *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. */
+
+static struct obstack frame_cache_obstack;
+
+void *
+frame_obstack_alloc (size)
+ unsigned long size;
+{
+ return obstack_alloc (&frame_cache_obstack, size);
+}
+
+void
+frame_saved_regs_zalloc (fi)
+ struct frame_info *fi;
+{
+ fi->saved_regs = (CORE_ADDR*)
+ frame_obstack_alloc (SIZEOF_FRAME_SAVED_REGS);
+ memset (fi->saved_regs, 0, SIZEOF_FRAME_SAVED_REGS);
+}
+
+
+/* Return the innermost (currently executing) stack frame. */
+
+struct frame_info *
+get_current_frame ()
+{
+ if (current_frame == NULL)
+ {
+ if (target_has_stack)
+ current_frame = create_new_frame (read_fp (), read_pc ());
+ else
+ error ("No stack.");
+ }
+ return current_frame;
+}
+
+void
+set_current_frame (frame)
+ struct frame_info *frame;
+{
+ current_frame = frame;
+}
+
+/* Create an arbitrary (i.e. address specified by user) or innermost frame.
+ Always returns a non-NULL value. */
+
+struct frame_info *
+create_new_frame (addr, pc)
+ CORE_ADDR addr;
+ CORE_ADDR pc;
+{
+ struct frame_info *fi;
+ char *name;
+
+ fi = (struct frame_info *)
+ obstack_alloc (&frame_cache_obstack,
+ sizeof (struct frame_info));
+
+ /* Arbitrary frame */
+ fi->saved_regs = NULL;
+ fi->next = NULL;
+ fi->prev = NULL;
+ fi->frame = addr;
+ fi->pc = pc;
+ find_pc_partial_function (pc, &name, (CORE_ADDR *)NULL,(CORE_ADDR *)NULL);
+ fi->signal_handler_caller = IN_SIGTRAMP (fi->pc, name);
+
+#ifdef INIT_EXTRA_FRAME_INFO
+ INIT_EXTRA_FRAME_INFO (0, fi);
+#endif
+
+ return fi;
+}
+
+/* Return the frame that called FI.
+ If FI is the original frame (it has no caller), return 0. */
+
+struct frame_info *
+get_prev_frame (frame)
+ struct frame_info *frame;
+{
+ return get_prev_frame_info (frame);
+}
+
+/* Return the frame that FRAME calls (NULL if FRAME is the innermost
+ frame). */
+
+struct frame_info *
+get_next_frame (frame)
+ struct frame_info *frame;
+{
+ 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 = NULL; /* Invalidate cache */
+ select_frame (NULL, -1);
+ annotate_frames_invalid ();
+}
+
+/* Flush the frame cache, and start a new one if necessary. */
+
+void
+reinit_frame_cache ()
+{
+ flush_cached_frames ();
+
+ /* FIXME: The inferior_pid test is wrong if there is a corefile. */
+ if (inferior_pid != 0)
+ {
+ select_frame (get_current_frame (), 0);
+ }
+}
+
+/* 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)
+ struct frame_info *frame;
+{
+ CORE_ADDR func_start, after_prologue;
+ func_start = get_pc_function_start (frame->pc);
+ if (func_start)
+ {
+ func_start += FUNCTION_START_OFFSET;
+ 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 (frame->pc == 0)
+ /* A frame with a zero PC is usually created by dereferencing a NULL
+ function pointer, normally causing an immediate core dump of the
+ inferior. Mark function as frameless, as the inferior has no chance
+ of setting up a stack frame. */
+ return 1;
+ 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)
+ struct frame_info *next_frame;
+{
+ CORE_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 = FRAME_FP (next_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));
+
+ prev->saved_regs = NULL;
+ 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.
+
+ Assuming that some machines need INIT_FRAME_PC after
+ INIT_EXTRA_FRAME_INFO, one possible 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. This should
+ also return a flag saying whether to keep the new frame, or
+ whether to discard it, because on some machines (e.g. mips) it
+ is really awkward to have FRAME_CHAIN_VALID called *before*
+ INIT_EXTRA_FRAME_INFO (there is no good way to get information
+ deduced in FRAME_CHAIN_VALID into the extra fields of the new frame).
+ 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, 31Jan94, 14Dec94. */
+
+#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 its value
+ (see tm-sparc.h). We want the pc saved in the inferior frame. */
+ INIT_FRAME_PC(fromleaf, prev);
+
+ /* If ->frame and ->pc are unchanged, we are in the process of getting
+ ourselves into an infinite backtrace. Some architectures check this
+ in FRAME_CHAIN or thereabouts, but it seems like there is no reason
+ this can't be an architecture-independent check. */
+ if (next_frame != NULL)
+ {
+ if (prev->frame == next_frame->frame
+ && prev->pc == next_frame->pc)
+ {
+ next_frame->prev = NULL;
+ obstack_free (&frame_cache_obstack, prev);
+ return NULL;
+ }
+ }
+
+ 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)
+ struct frame_info *frame;
+{
+ return frame->pc;
+}
+
+
+#ifdef FRAME_FIND_SAVED_REGS
+/* XXX - deprecated. This is a compatibility function for targets
+ that do not yet implement FRAME_INIT_SAVED_REGS. */
+/* Find the addresses in which registers are saved in FRAME. */
+
+void
+get_frame_saved_regs (frame, saved_regs_addr)
+ struct frame_info *frame;
+ struct frame_saved_regs *saved_regs_addr;
+{
+ if (frame->saved_regs == NULL)
+ {
+ frame->saved_regs = (CORE_ADDR*)
+ frame_obstack_alloc (SIZEOF_FRAME_SAVED_REGS);
+ }
+ if (saved_regs_addr == NULL)
+ {
+ struct frame_saved_regs saved_regs;
+ FRAME_FIND_SAVED_REGS (frame, saved_regs);
+ memcpy (frame->saved_regs, &saved_regs, SIZEOF_FRAME_SAVED_REGS);
+ }
+ else
+ {
+ FRAME_FIND_SAVED_REGS (frame, *saved_regs_addr);
+ memcpy (frame->saved_regs, saved_regs_addr, SIZEOF_FRAME_SAVED_REGS);
+ }
+}
+#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)
+ struct frame_info *frame;
+{
+ CORE_ADDR pc;
+
+ pc = frame->pc;
+ if (frame->next != 0 && frame->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 frame->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)
+ struct frame_info *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 and section, 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_sect (pc, section, pindex, symtab)
+ register CORE_ADDR pc;
+ struct sec *section;
+ int *pindex;
+ struct symtab *symtab;
+
+{
+ register struct block *b;
+ register int bot, top, half;
+ struct blockvector *bl;
+
+ if (symtab == 0) /* if no symtab specified by caller */
+ {
+ /* First search all symtabs for one whose file contains our pc */
+ if ((symtab = find_pc_sect_symtab (pc, section)) == 0)
+ return 0;
+ }
+
+ bl = BLOCKVECTOR (symtab);
+ 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 blockvector immediately containing the innermost lexical block
+ containing the specified pc value, or 0 if there is none.
+ Backward compatibility, no section. */
+
+struct blockvector *
+blockvector_for_pc (pc, pindex)
+ register CORE_ADDR pc;
+ int *pindex;
+{
+ return blockvector_for_pc_sect (pc, find_pc_mapped_section (pc),
+ pindex, NULL);
+}
+
+/* Return the innermost lexical block containing the specified pc value
+ in the specified section, or 0 if there is none. */
+
+struct block *
+block_for_pc_sect (pc, section)
+ register CORE_ADDR pc;
+ struct sec *section;
+{
+ register struct blockvector *bl;
+ int index;
+
+ bl = blockvector_for_pc_sect (pc, section, &index, NULL);
+ if (bl)
+ return BLOCKVECTOR_BLOCK (bl, index);
+ return 0;
+}
+
+/* Return the innermost lexical block containing the specified pc value,
+ or 0 if there is none. Backward compatibility, no section. */
+
+struct block *
+block_for_pc (pc)
+ register CORE_ADDR pc;
+{
+ return block_for_pc_sect (pc, find_pc_mapped_section (pc));
+}
+
+/* Return the function containing pc value PC in section SECTION.
+ Returns 0 if function is not known. */
+
+struct symbol *
+find_pc_sect_function (pc, section)
+ CORE_ADDR pc;
+ struct sec *section;
+{
+ register struct block *b = block_for_pc_sect (pc, section);
+ if (b == 0)
+ return 0;
+ return block_function (b);
+}
+
+/* Return the function containing pc value PC.
+ Returns 0 if function is not known. Backward compatibility, no section */
+
+struct symbol *
+find_pc_function (pc)
+ CORE_ADDR pc;
+{
+ return find_pc_sect_function (pc, find_pc_mapped_section (pc));
+}
+
+/* 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;
+static struct sec *cache_pc_function_section = NULL;
+
+/* 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;
+ cache_pc_function_section = NULL;
+}
+
+/* Finds the "function" (text symbol) that is smaller than PC but
+ greatest of all of the potential text symbols in SECTION. 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_sect_partial_function (pc, section, name, address, endaddr)
+ CORE_ADDR pc;
+ asection *section;
+ 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 *osect;
+ int i;
+ CORE_ADDR mapped_pc;
+
+ mapped_pc = overlay_mapped_address (pc, section);
+
+ if (mapped_pc >= cache_pc_function_low &&
+ mapped_pc < cache_pc_function_high &&
+ section == cache_pc_function_section)
+ 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 (mapped_pc, (char *)NULL))
+ {
+ cache_pc_function_low = SIGTRAMP_START (mapped_pc);
+ cache_pc_function_high = SIGTRAMP_END (mapped_pc);
+ cache_pc_function_name = "<sigtramp>";
+ cache_pc_function_section = section;
+ goto return_cached_value;
+ }
+#endif
+
+ msymbol = lookup_minimal_symbol_by_pc_section (mapped_pc, section);
+ pst = find_pc_sect_psymtab (mapped_pc, section);
+ 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_sect_function (mapped_pc, section);
+ 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);
+ cache_pc_function_section = section;
+ 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_sect_psymbol (pst, mapped_pc, section);
+
+ 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. */
+
+ osect = find_pc_sect_section (mapped_pc, section);
+
+ if (!osect)
+ 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;
+ }
+
+ cache_pc_function_low = SYMBOL_VALUE_ADDRESS (msymbol);
+ cache_pc_function_name = SYMBOL_NAME (msymbol);
+ cache_pc_function_section = section;
+
+ /* Use the lesser of the next minimal symbol in the same section, or
+ the end of the section, as the end of the function. */
+
+ /* Step over other symbols at this same address, and symbols in
+ other sections, to find the next symbol in this section with
+ a different address. */
+
+ for (i=1; SYMBOL_NAME (msymbol+i) != NULL; i++)
+ {
+ if (SYMBOL_VALUE_ADDRESS (msymbol+i) != SYMBOL_VALUE_ADDRESS (msymbol)
+ && SYMBOL_BFD_SECTION (msymbol+i) == SYMBOL_BFD_SECTION (msymbol))
+ break;
+ }
+
+ if (SYMBOL_NAME (msymbol + i) != NULL
+ && SYMBOL_VALUE_ADDRESS (msymbol + i) < osect->endaddr)
+ cache_pc_function_high = SYMBOL_VALUE_ADDRESS (msymbol + i);
+ 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 = osect->endaddr;
+
+ return_cached_value:
+
+ if (address)
+ {
+ if (pc_in_unmapped_range (pc, section))
+ *address = overlay_unmapped_address (cache_pc_function_low, section);
+ else
+ *address = cache_pc_function_low;
+ }
+
+ if (name)
+ *name = cache_pc_function_name;
+
+ if (endaddr)
+ {
+ if (pc_in_unmapped_range (pc, section))
+ {
+ /* Because the high address is actually beyond the end of
+ the function (and therefore possibly beyond the end of
+ the overlay), we must actually convert (high - 1)
+ and then add one to that. */
+
+ *endaddr = 1 + overlay_unmapped_address (cache_pc_function_high - 1,
+ section);
+ }
+ else
+ *endaddr = cache_pc_function_high;
+ }
+
+ return 1;
+}
+
+/* Backward compatibility, no section argument */
+
+int
+find_pc_partial_function (pc, name, address, endaddr)
+ CORE_ADDR pc;
+ char **name;
+ CORE_ADDR *address;
+ CORE_ADDR *endaddr;
+{
+ asection *section;
+
+ section = find_pc_overlay (pc);
+ return find_pc_sect_partial_function (pc, section, name, address, endaddr);
+}
+
+/* Return the innermost stack frame executing inside of BLOCK,
+ or NULL if there is no such frame. If BLOCK is NULL, just return NULL. */
+
+struct frame_info *
+block_innermost_frame (block)
+ struct block *block;
+{
+ struct frame_info *frame;
+ register CORE_ADDR start;
+ register CORE_ADDR end;
+
+ if (block == NULL)
+ return NULL;
+
+ start = BLOCK_START (block);
+ end = BLOCK_END (block);
+
+ frame = NULL;
+ while (1)
+ {
+ frame = get_prev_frame (frame);
+ if (frame == NULL)
+ return NULL;
+ if (frame->pc >= start && frame->pc < end)
+ return frame;
+ }
+}
+
+/* Return the full FRAME which corresponds to the given CORE_ADDR
+ or NULL if no FRAME on the chain corresponds to CORE_ADDR. */
+
+struct frame_info *
+find_frame_addr_in_frame_chain (frame_addr)
+ CORE_ADDR frame_addr;
+{
+ struct frame_info *frame = NULL;
+
+ if (frame_addr == (CORE_ADDR)0)
+ return NULL;
+
+ while (1)
+ {
+ frame = get_prev_frame (frame);
+ if (frame == NULL)
+ return NULL;
+ if (FRAME_FP (frame) == frame_addr)
+ return frame;
+ }
+}
+
+#ifdef SIGCONTEXT_PC_OFFSET
+/* Get saved user PC for sigtramp from sigcontext for BSD style sigtramp. */
+
+CORE_ADDR
+sigtramp_saved_pc (frame)
+ struct frame_info *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 */
+
+#ifdef USE_GENERIC_DUMMY_FRAMES
+
+/*
+ * GENERIC DUMMY FRAMES
+ *
+ * The following code serves to maintain the dummy stack frames for
+ * inferior function calls (ie. when gdb calls into the inferior via
+ * call_function_by_hand). This code saves the machine state before
+ * the call in host memory, so we must maintain an independant stack
+ * and keep it consistant etc. I am attempting to make this code
+ * generic enough to be used by many targets.
+ *
+ * The cheapest and most generic way to do CALL_DUMMY on a new target
+ * is probably to define CALL_DUMMY to be empty, CALL_DUMMY_LENGTH to
+ * zero, and CALL_DUMMY_LOCATION to AT_ENTRY. Then you must remember
+ * to define PUSH_RETURN_ADDRESS, because no call instruction will be
+ * being executed by the target. Also FRAME_CHAIN_VALID as
+ * generic_frame_chain_valid. */
+
+static struct dummy_frame *dummy_frame_stack = NULL;
+
+/* Function: find_dummy_frame(pc, fp, sp)
+ Search the stack of dummy frames for one matching the given PC, FP and SP.
+ This is the work-horse for pc_in_call_dummy and read_register_dummy */
+
+char *
+generic_find_dummy_frame (pc, fp)
+ CORE_ADDR pc;
+ CORE_ADDR fp;
+{
+ struct dummy_frame * dummyframe;
+
+ if (pc != entry_point_address ())
+ return 0;
+
+ for (dummyframe = dummy_frame_stack; dummyframe != NULL;
+ dummyframe = dummyframe->next)
+ if (fp == dummyframe->fp || fp == dummyframe->sp)
+ /* The frame in question lies between the saved fp and sp, inclusive */
+ return dummyframe->regs;
+
+ return 0;
+}
+
+/* Function: pc_in_call_dummy (pc, fp)
+ Return true if this is a dummy frame created by gdb for an inferior call */
+
+int
+generic_pc_in_call_dummy (pc, fp)
+ CORE_ADDR pc;
+ CORE_ADDR fp;
+{
+ /* if find_dummy_frame succeeds, then PC is in a call dummy */
+ return (generic_find_dummy_frame (pc, fp) != 0);
+}
+
+/* Function: read_register_dummy
+ Find a saved register from before GDB calls a function in the inferior */
+
+CORE_ADDR
+generic_read_register_dummy (pc, fp, regno)
+ CORE_ADDR pc;
+ CORE_ADDR fp;
+ int regno;
+{
+ char *dummy_regs = generic_find_dummy_frame (pc, fp);
+
+ if (dummy_regs)
+ return extract_address (&dummy_regs[REGISTER_BYTE (regno)],
+ REGISTER_RAW_SIZE(regno));
+ else
+ return 0;
+}
+
+/* Save all the registers on the dummy frame stack. Most ports save the
+ registers on the target stack. This results in lots of unnecessary memory
+ references, which are slow when debugging via a serial line. Instead, we
+ save all the registers internally, and never write them to the stack. The
+ registers get restored when the called function returns to the entry point,
+ where a breakpoint is laying in wait. */
+
+void
+generic_push_dummy_frame ()
+{
+ struct dummy_frame *dummy_frame;
+ CORE_ADDR fp = (get_current_frame ())->frame;
+
+ /* check to see if there are stale dummy frames,
+ perhaps left over from when a longjump took us out of a
+ function that was called by the debugger */
+
+ dummy_frame = dummy_frame_stack;
+ while (dummy_frame)
+ if (INNER_THAN (dummy_frame->fp, fp)) /* stale -- destroy! */
+ {
+ dummy_frame_stack = dummy_frame->next;
+ free (dummy_frame);
+ dummy_frame = dummy_frame_stack;
+ }
+ else
+ dummy_frame = dummy_frame->next;
+
+ dummy_frame = xmalloc (sizeof (struct dummy_frame));
+ dummy_frame->pc = read_register (PC_REGNUM);
+ dummy_frame->sp = read_register (SP_REGNUM);
+ dummy_frame->fp = fp;
+ read_register_bytes (0, dummy_frame->regs, REGISTER_BYTES);
+ dummy_frame->next = dummy_frame_stack;
+ dummy_frame_stack = dummy_frame;
+}
+
+/* Function: pop_frame
+ Restore the machine state from either the saved dummy stack or a
+ real stack frame. */
+
+void
+generic_pop_current_frame (pop)
+ void (*pop) PARAMS ((struct frame_info *frame));
+{
+ struct frame_info *frame = get_current_frame ();
+ if (PC_IN_CALL_DUMMY(frame->pc, frame->frame, frame->frame))
+ generic_pop_dummy_frame ();
+ else
+ pop (frame);
+}
+
+/* Function: pop_dummy_frame
+ Restore the machine state from a saved dummy stack frame. */
+
+void
+generic_pop_dummy_frame ()
+{
+ struct dummy_frame *dummy_frame = dummy_frame_stack;
+
+ /* FIXME: what if the first frame isn't the right one, eg..
+ because one call-by-hand function has done a longjmp into another one? */
+
+ if (!dummy_frame)
+ error ("Can't pop dummy frame!");
+ dummy_frame_stack = dummy_frame->next;
+ write_register_bytes (0, dummy_frame->regs, REGISTER_BYTES);
+ flush_cached_frames ();
+ free (dummy_frame);
+}
+
+/* Function: frame_chain_valid
+ Returns true for a user frame or a call_function_by_hand dummy frame,
+ and false for the CRT0 start-up frame. Purpose is to terminate backtrace */
+
+int
+generic_frame_chain_valid (fp, fi)
+ CORE_ADDR fp;
+ struct frame_info *fi;
+{
+ if (PC_IN_CALL_DUMMY(FRAME_SAVED_PC(fi), fp, fp))
+ return 1; /* don't prune CALL_DUMMY frames */
+ else /* fall back to default algorithm (see frame.h) */
+ return (fp != 0
+ && (INNER_THAN (fi->frame, fp) || fi->frame == fp)
+ && !inside_entry_file (FRAME_SAVED_PC(fi)));
+}
+
+/* Function: get_saved_register
+ 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). Note that this is never set to anything other than zero
+ in this implementation.
+
+ 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). We will use not_lval for values
+ fetched from generic dummy frames.
+
+ Set *ADDRP to the address, either in memory on as a REGISTER_BYTE
+ offset into the registers array. If the value is stored in a dummy
+ frame, set *ADDRP to zero.
+
+ To use this implementation, define a function called
+ "get_saved_register" in your target code, which simply passes all
+ of its arguments to this function.
+
+ The argument RAW_BUFFER must point to aligned memory. */
+
+void
+generic_get_saved_register (raw_buffer, optimized, addrp, frame, regnum, lval)
+ char *raw_buffer;
+ int *optimized;
+ CORE_ADDR *addrp;
+ struct frame_info *frame;
+ int regnum;
+ enum lval_type *lval;
+{
+ if (!target_has_registers)
+ error ("No registers.");
+
+ /* Normal systems don't optimize out things with register numbers. */
+ if (optimized != NULL)
+ *optimized = 0;
+
+ if (addrp) /* default assumption: not found in memory */
+ *addrp = 0;
+
+ /* Note: since the current frame's registers could only have been
+ saved by frames INTERIOR TO the current frame, we skip examining
+ the current frame itself: otherwise, we would be getting the
+ previous frame's registers which were saved by the current frame. */
+
+ while (frame && ((frame = frame->next) != NULL))
+ {
+ if (PC_IN_CALL_DUMMY (frame->pc, frame->frame, frame->frame))
+ {
+ if (lval) /* found it in a CALL_DUMMY frame */
+ *lval = not_lval;
+ if (raw_buffer)
+ memcpy (raw_buffer,
+ generic_find_dummy_frame (frame->pc, frame->frame) +
+ REGISTER_BYTE (regnum),
+ REGISTER_RAW_SIZE (regnum));
+ return;
+ }
+
+ FRAME_INIT_SAVED_REGS (frame);
+ if (frame->saved_regs != NULL
+ && frame->saved_regs[regnum] != 0)
+ {
+ if (lval) /* found it saved on the stack */
+ *lval = lval_memory;
+ if (regnum == SP_REGNUM)
+ {
+ if (raw_buffer) /* SP register treated specially */
+ store_address (raw_buffer, REGISTER_RAW_SIZE (regnum),
+ frame->saved_regs[regnum]);
+ }
+ else
+ {
+ if (addrp) /* any other register */
+ *addrp = frame->saved_regs[regnum];
+ if (raw_buffer)
+ read_memory (frame->saved_regs[regnum], raw_buffer,
+ REGISTER_RAW_SIZE (regnum));
+ }
+ return;
+ }
+ }
+
+ /* If we get thru the loop to this point, it means the register was
+ not saved in any frame. Return the actual live-register value. */
+
+ if (lval) /* found it in a live register */
+ *lval = lval_register;
+ if (addrp)
+ *addrp = REGISTER_BYTE (regnum);
+ if (raw_buffer)
+ read_register_gen (regnum, raw_buffer);
+}
+#endif /* USE_GENERIC_DUMMY_FRAMES */
+
+void
+_initialize_blockframe ()
+{
+ obstack_init (&frame_cache_obstack);
+}
diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
new file mode 100644
index 00000000000..4b05949b59b
--- /dev/null
+++ b/gdb/breakpoint.c
@@ -0,0 +1,6686 @@
+/* Everything about breakpoints, for GDB.
+ Copyright 1986, 87, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 1999
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 "command.h"
+#include "inferior.h"
+#include "gdbthread.h"
+#include "target.h"
+#include "language.h"
+#include "gdb_string.h"
+#include "demangle.h"
+#include "annotate.h"
+#include "symfile.h"
+#include "objfiles.h"
+
+/* Prototypes for local functions. */
+
+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
+enable_command PARAMS ((char *, int));
+
+static void
+map_breakpoint_numbers PARAMS ((char *, void (*)(struct breakpoint *)));
+
+static void
+ignore_command PARAMS ((char *, int));
+
+static int breakpoint_re_set_one PARAMS ((PTR));
+
+static void
+clear_command PARAMS ((char *, int));
+
+static void
+catch_command PARAMS ((char *, int));
+
+static void
+handle_gnu_4_16_catch_command PARAMS ((char *, int, int));
+
+static struct symtabs_and_lines
+get_catch_sals PARAMS ((int));
+
+static void
+watch_command PARAMS ((char *, int));
+
+static int
+can_use_hardware_watchpoint PARAMS ((struct value *));
+
+void
+tbreak_command PARAMS ((char *, int));
+
+static void
+break_command_1 PARAMS ((char *, int, int));
+
+static void
+mention PARAMS ((struct breakpoint *));
+
+struct breakpoint *
+set_raw_breakpoint PARAMS ((struct symtab_and_line));
+
+static void
+check_duplicates PARAMS ((CORE_ADDR, asection *));
+
+static void
+describe_other_breakpoints PARAMS ((CORE_ADDR, asection *));
+
+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 ((PTR));
+
+static void
+cleanup_executing_breakpoints PARAMS ((PTR));
+
+static void
+commands_command PARAMS ((char *, int));
+
+static void
+condition_command PARAMS ((char *, int));
+
+static int
+get_number PARAMS ((char **));
+
+void
+set_breakpoint_count PARAMS ((int));
+
+#if 0
+static struct breakpoint *
+create_temp_exception_breakpoint PARAMS ((CORE_ADDR));
+#endif
+
+typedef enum {
+ mark_inserted,
+ mark_uninserted
+} insertion_state_t;
+
+static int
+remove_breakpoint PARAMS ((struct breakpoint *, insertion_state_t));
+
+static int print_it_normal PARAMS ((bpstat));
+
+typedef struct {
+ enum exception_event_kind kind;
+ int enable;
+} args_for_catchpoint_enable;
+
+static int watchpoint_check PARAMS ((PTR));
+
+static int cover_target_enable_exception_callback PARAMS ((PTR));
+
+static int print_it_done PARAMS ((bpstat));
+
+static int print_it_noop PARAMS ((bpstat));
+
+static void maintenance_info_breakpoints PARAMS ((char *, int));
+
+#ifdef GET_LONGJMP_TARGET
+static void create_longjmp_breakpoint PARAMS ((char *));
+#endif
+
+static int hw_breakpoint_used_count PARAMS ((void));
+
+static int hw_watchpoint_used_count PARAMS ((enum bptype, int *));
+
+static void hbreak_command PARAMS ((char *, int));
+
+static void thbreak_command PARAMS ((char *, int));
+
+static void watch_command_1 PARAMS ((char *, int, int));
+
+static void rwatch_command PARAMS ((char *, int));
+
+static void awatch_command PARAMS ((char *, int));
+
+static void do_enable_breakpoint PARAMS ((struct breakpoint *, enum bpdisp));
+
+/* Prototypes for exported functions. */
+
+static void
+awatch_command PARAMS ((char *, int));
+
+static void
+do_enable_breakpoint PARAMS ((struct breakpoint *, enum bpdisp));
+
+/* If FALSE, gdb will not use hardware support for watchpoints, even
+ if such is available. */
+static int can_use_hw_watchpoints;
+
+void delete_command PARAMS ((char *, int));
+
+void _initialize_breakpoint PARAMS ((void));
+
+void set_breakpoint_count PARAMS ((int));
+
+extern int addressprint; /* Print machine addresses? */
+
+#if defined (GET_LONGJMP_TARGET) || defined (SOLIB_ADD)
+static int internal_breakpoint_number = -1;
+#endif
+
+/* 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)
+
+/* True if SHIFT_INST_REGS defined, false otherwise. */
+
+int must_shift_inst_regs =
+#if defined(SHIFT_INST_REGS)
+1
+#else
+0
+#endif
+;
+
+/* True if breakpoint hit counts should be displayed in breakpoint info. */
+
+int show_breakpoint_hit_counts = 1;
+
+/* Chain of all breakpoints defined. */
+
+struct breakpoint *breakpoint_chain;
+
+/* Number of last breakpoint made. */
+
+int breakpoint_count;
+
+/* Pointer to current exception event record */
+static struct exception_event_record * current_exception_event;
+
+/* Indicator of whether exception catchpoints should be nuked
+ between runs of a program */
+int exception_catchpoints_are_fragile = 0;
+
+/* Indicator of when exception catchpoints set-up should be
+ reinitialized -- e.g. when program is re-run */
+int exception_support_initialized = 0;
+
+/* This function returns a pointer to the string representation of the
+ pathname of the dynamically-linked library that has just been
+ loaded.
+
+ This function must be used only when SOLIB_HAVE_LOAD_EVENT is TRUE,
+ or undefined results are guaranteed.
+
+ This string's contents are only valid immediately after the
+ inferior has stopped in the dynamic linker hook, and becomes
+ invalid as soon as the inferior is continued. Clients should make
+ a copy of this string if they wish to continue the inferior and
+ then access the string. */
+
+#ifndef SOLIB_LOADED_LIBRARY_PATHNAME
+#define SOLIB_LOADED_LIBRARY_PATHNAME(pid) ""
+#endif
+
+/* This function returns a pointer to the string representation of the
+ pathname of the dynamically-linked library that has just been
+ unloaded.
+
+ This function must be used only when SOLIB_HAVE_UNLOAD_EVENT is
+ TRUE, or undefined results are guaranteed.
+
+ This string's contents are only valid immediately after the
+ inferior has stopped in the dynamic linker hook, and becomes
+ invalid as soon as the inferior is continued. Clients should make
+ a copy of this string if they wish to continue the inferior and
+ then access the string. */
+
+#ifndef SOLIB_UNLOADED_LIBRARY_PATHNAME
+#define SOLIB_UNLOADED_LIBRARY_PATHNAME(pid) ""
+#endif
+
+/* This function is called by the "catch load" command. It allows the
+ debugger to be notified by the dynamic linker when a specified
+ library file (or any library file, if filename is NULL) is loaded. */
+
+#ifndef SOLIB_CREATE_CATCH_LOAD_HOOK
+#define SOLIB_CREATE_CATCH_LOAD_HOOK(pid,tempflag,filename,cond_string) \
+ error ("catch of library loads not yet implemented on this platform")
+#endif
+
+/* This function is called by the "catch unload" command. It allows
+ the debugger to be notified by the dynamic linker when a specified
+ library file (or any library file, if filename is NULL) is
+ unloaded. */
+
+#ifndef SOLIB_CREATE_CATCH_UNLOAD_HOOK
+#define SOLIB_CREATE_CATCH_UNLOAD_HOOK(pid,tempflag,filename,cond_string) \
+ error ("catch of library unloads not yet implemented on this platform")
+#endif
+
+/* Set breakpoint count to NUM. */
+
+void
+set_breakpoint_count (num)
+ int num;
+{
+ breakpoint_count = num;
+ set_internalvar (lookup_internalvar ("bpnum"),
+ value_from_longest (builtin_type_int, (LONGEST) num));
+}
+
+/* Used in run_command to zero the hit count when a new run starts. */
+
+void
+clear_breakpoint_hit_counts ()
+{
+ struct breakpoint *b;
+
+ ALL_BREAKPOINTS (b)
+ b->hit_count = 0;
+}
+
+/* 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;
+
+/* *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_ptr 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");
+ }
+ breakpoints_changed ();
+ 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)
+ {
+ char tmpbuf[128];
+ sprintf (tmpbuf, "Type commands for when breakpoint %d is hit, one per line.", bnum);
+ l = read_command_lines (tmpbuf, from_tty);
+ free_command_lines (&b->commands);
+ b->commands = l;
+ breakpoints_changed ();
+ return;
+ }
+ error ("No breakpoint number %d.", bnum);
+}
+
+/* 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;
+ CORE_ADDR bp_addr = 0;
+ int bp_size = 0;
+
+ if (BREAKPOINT_FROM_PC (&bp_addr, &bp_size) == NULL)
+ /* No breakpoints on this machine. */
+ return target_read_memory (memaddr, myaddr, len);
+
+ ALL_BREAKPOINTS (b)
+ {
+ if (b->type == bp_none)
+ warning ("attempted to read through apparently deleted breakpoint #%d?\n", b->number);
+
+ /* memory breakpoint? */
+ if (b->type == bp_watchpoint
+ || b->type == bp_hardware_watchpoint
+ || b->type == bp_read_watchpoint
+ || b->type == bp_access_watchpoint)
+ continue;
+ /* bp in memory? */
+ if (!b->inserted)
+ continue;
+ /* Addresses and length of the part of the breakpoint that
+ we need to copy. */
+ /* XXXX The m68k, sh and h8300 have different local and remote
+ breakpoint values. BREAKPOINT_FROM_PC still manages to
+ correctly determine the breakpoints memory address and size
+ for these targets. */
+ bp_addr = b->address;
+ bp_size = 0;
+ if (BREAKPOINT_FROM_PC (&bp_addr, &bp_size) == NULL)
+ continue;
+ if (bp_size == 0)
+ /* bp isn't valid */
+ continue;
+ if (bp_addr + bp_size <= memaddr)
+ /* The breakpoint is entirely before the chunk of memory we
+ are reading. */
+ continue;
+ if (bp_addr >= memaddr + len)
+ /* The breakpoint is entirely after the chunk of memory we are
+ reading. */
+ continue;
+ /* Copy the breakpoint from the shadow contents, and recurse for
+ the things before and after. */
+ {
+ /* Offset within shadow_contents. */
+ int bptoffset = 0;
+
+ if (bp_addr < memaddr)
+ {
+ /* Only copy the second part of the breakpoint. */
+ bp_size -= memaddr - bp_addr;
+ bptoffset = memaddr - bp_addr;
+ bp_addr = memaddr;
+ }
+
+ if (bp_addr + bp_size > memaddr + len)
+ {
+ /* Only copy the first part of the breakpoint. */
+ bp_size -= (bp_addr + bp_size) - (memaddr + len);
+ }
+
+ memcpy (myaddr + bp_addr - memaddr,
+ b->shadow_contents + bptoffset, bp_size);
+
+ if (bp_addr > memaddr)
+ {
+ /* Copy the section of memory before the breakpoint. */
+ status = read_memory_nobpt (memaddr, myaddr, bp_addr - memaddr);
+ if (status != 0)
+ return status;
+ }
+
+ if (bp_addr + bp_size < memaddr + len)
+ {
+ /* Copy the section of memory after the breakpoint. */
+ status = read_memory_nobpt
+ (bp_addr + bp_size,
+ myaddr + bp_addr + bp_size - memaddr,
+ memaddr + len - (bp_addr + bp_size));
+ 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, *temp;
+ int val = 0;
+ int disabled_breaks = 0;
+
+ static char message1[] = "Error inserting catchpoint %d:\n";
+ static char message[sizeof (message1) + 30];
+
+
+ ALL_BREAKPOINTS_SAFE (b, temp)
+ {
+ if (b->type != bp_watchpoint
+ && b->type != bp_hardware_watchpoint
+ && b->type != bp_read_watchpoint
+ && b->type != bp_access_watchpoint
+ && b->type != bp_catch_fork
+ && b->type != bp_catch_vfork
+ && b->type != bp_catch_exec
+ && b->type != bp_catch_throw
+ && b->type != bp_catch_catch
+ && b->enable != disabled
+ && b->enable != shlib_disabled
+ && b->enable != call_disabled
+ && ! b->inserted
+ && ! b->duplicate)
+ {
+ if (b->type == bp_hardware_breakpoint)
+ val = target_insert_hw_breakpoint(b->address, b->shadow_contents);
+ else
+ {
+ /* Check to see if breakpoint is in an overlay section;
+ if so, we should set the breakpoint at the LMA address.
+ Only if the section is currently mapped should we ALSO
+ set a break at the VMA address. */
+ if (overlay_debugging && b->section &&
+ section_is_overlay (b->section))
+ {
+ CORE_ADDR addr;
+
+ addr = overlay_unmapped_address (b->address, b->section);
+ val = target_insert_breakpoint (addr, b->shadow_contents);
+ /* This would be the time to check val, to see if the
+ breakpoint write to the load address succeeded.
+ However, this might be an ordinary occurrance, eg. if
+ the unmapped overlay is in ROM. */
+ val = 0; /* in case unmapped address failed */
+ if (section_is_mapped (b->section))
+ val = target_insert_breakpoint (b->address,
+ b->shadow_contents);
+ }
+ else /* ordinary (non-overlay) address */
+ 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))
+ {
+ /* See also: disable_breakpoints_in_shlibs. */
+ val = 0;
+ b->enable = shlib_disabled;
+ if (!disabled_breaks)
+ {
+ target_terminal_ours_for_output ();
+ fprintf_unfiltered (gdb_stderr,
+ "Cannot insert breakpoint %d:\n", b->number);
+ printf_filtered ("Temporarily disabling shared library breakpoints:\n");
+ }
+ disabled_breaks = 1;
+ printf_filtered ("%d ", b->number);
+ }
+ else
+#endif
+ {
+ target_terminal_ours_for_output ();
+ fprintf_unfiltered (gdb_stderr, "Cannot insert breakpoint %d:\n", b->number);
+#ifdef ONE_PROCESS_WRITETEXT
+ fprintf_unfiltered (gdb_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;
+ }
+ else if (ep_is_exception_catchpoint (b)
+ && b->enable != disabled
+ && b->enable != shlib_disabled
+ && b->enable != call_disabled
+ && ! b->inserted
+ && ! b->duplicate)
+
+ {
+ /* If we get here, we must have a callback mechanism for exception
+ events -- with g++ style embedded label support, we insert
+ ordinary breakpoints and not catchpoints. */
+ sprintf (message, message1, b->number); /* Format possible error message */
+
+ val = target_insert_breakpoint(b->address, b->shadow_contents);
+ if (val)
+ {
+ /* Couldn't set breakpoint for some reason */
+ target_terminal_ours_for_output ();
+ fprintf_unfiltered (gdb_stderr,
+ "Cannot insert catchpoint %d; disabling it\n", b->number);
+ b->enable = disabled;
+ }
+ else
+ {
+ /* Bp set, now make sure callbacks are enabled */
+ int val;
+ args_for_catchpoint_enable args;
+ args.kind = b->type == bp_catch_catch ? EX_EVENT_CATCH : EX_EVENT_THROW;
+ args.enable = 1;
+ val = catch_errors (cover_target_enable_exception_callback,
+ &args,
+ message, RETURN_MASK_ALL);
+ if (val != 0 && val != -1)
+ {
+ b->inserted = 1;
+ }
+ /* Check if something went wrong; val == 0 can be ignored */
+ if (val == -1)
+ {
+ /* something went wrong */
+ target_terminal_ours_for_output ();
+ fprintf_unfiltered (gdb_stderr, "Cannot insert catchpoint %d; disabling it\n", b->number);
+ b->enable = disabled;
+ }
+ }
+ }
+
+ else if ((b->type == bp_hardware_watchpoint ||
+ b->type == bp_read_watchpoint ||
+ b->type == bp_access_watchpoint)
+ && b->enable == enabled
+ && ! b->inserted
+ && ! b->duplicate)
+ {
+ struct frame_info *saved_frame;
+ int saved_level, within_current_scope;
+ value_ptr mark = value_mark ();
+ value_ptr v;
+
+ /* Save the current frame and level so we can restore it after
+ evaluating the watchpoint expression on its own frame. */
+ saved_frame = selected_frame;
+ saved_level = selected_frame_level;
+
+ /* Determine if the watchpoint is within scope. */
+ if (b->exp_valid_block == NULL)
+ within_current_scope = 1;
+ else
+ {
+ struct frame_info *fi;
+
+ /* There might be no current frame at this moment if we are
+ resuming from a step over a breakpoint.
+ Set up current frame before trying to find the watchpoint
+ frame. */
+ get_current_frame ();
+ fi = find_frame_addr_in_frame_chain (b->watchpoint_frame);
+ within_current_scope = (fi != NULL);
+ if (within_current_scope)
+ select_frame (fi, -1);
+ }
+
+ if (within_current_scope)
+ {
+ /* Evaluate the expression and cut the chain of values
+ produced off from the value chain. */
+ v = evaluate_expression (b->exp);
+ value_release_to_mark (mark);
+
+ b->val_chain = v;
+ b->inserted = 1;
+
+ /* Look at each value on the value chain. */
+ for ( ; v; v=v->next)
+ {
+ /* If it's a memory location, then we must watch it. */
+ if (v->lval == lval_memory)
+ {
+ int addr, len, type;
+
+ addr = VALUE_ADDRESS (v) + VALUE_OFFSET (v);
+ len = TYPE_LENGTH (VALUE_TYPE (v));
+ type = 0;
+ if (b->type == bp_read_watchpoint)
+ type = 1;
+ else if (b->type == bp_access_watchpoint)
+ type = 2;
+
+ val = target_insert_watchpoint (addr, len, type);
+ if (val == -1)
+ {
+ b->inserted = 0;
+ break;
+ }
+ val = 0;
+ }
+ }
+ /* Failure to insert a watchpoint on any memory value in the
+ value chain brings us here. */
+ if (!b->inserted)
+ warning ("Hardware watchpoint %d: Could not insert watchpoint\n",
+ b->number);
+ }
+ else
+ {
+ printf_filtered ("\
+Hardware watchpoint %d deleted because the program has left the block in\n\
+which its expression is valid.\n", b->number);
+ if (b->related_breakpoint)
+ b->related_breakpoint->disposition = del_at_next_stop;
+ b->disposition = del_at_next_stop;
+ }
+
+ /* Restore the frame and level. */
+ if ((saved_frame != selected_frame) ||
+ (saved_level != selected_frame_level))
+ select_and_print_frame (saved_frame, saved_level);
+ }
+ else if ((b->type == bp_catch_fork
+ || b->type == bp_catch_vfork
+ || b->type == bp_catch_exec)
+ && b->enable == enabled
+ && ! b->inserted
+ && ! b->duplicate)
+ {
+ val = -1;
+ switch (b->type)
+ {
+ case bp_catch_fork :
+ val = target_insert_fork_catchpoint (inferior_pid);
+ break;
+ case bp_catch_vfork :
+ val = target_insert_vfork_catchpoint (inferior_pid);
+ break;
+ case bp_catch_exec :
+ val = target_insert_exec_catchpoint (inferior_pid);
+ break;
+ }
+ if (val < 0)
+ {
+ target_terminal_ours_for_output ();
+ fprintf_unfiltered (gdb_stderr, "Cannot insert catchpoint %d:\n", b->number);
+ }
+ else
+ b->inserted = 1;
+ }
+ }
+ if (disabled_breaks)
+ printf_filtered ("\n");
+
+ return val;
+}
+
+
+int
+remove_breakpoints ()
+{
+ register struct breakpoint *b;
+ int val;
+
+ ALL_BREAKPOINTS (b)
+ {
+ if (b->inserted)
+ {
+ val = remove_breakpoint (b, mark_uninserted);
+ if (val != 0)
+ return val;
+ }
+ }
+ return 0;
+}
+
+int
+reattach_breakpoints (pid)
+ int pid;
+{
+ register struct breakpoint *b;
+ int val;
+ int saved_inferior_pid = inferior_pid;
+
+ inferior_pid = pid; /* Because remove_breakpoint will use this global. */
+ ALL_BREAKPOINTS (b)
+ {
+ if (b->inserted)
+ {
+ remove_breakpoint (b, mark_inserted);
+ if (b->type == bp_hardware_breakpoint)
+ val = target_insert_hw_breakpoint(b->address, b->shadow_contents);
+ else
+ val = target_insert_breakpoint(b->address, b->shadow_contents);
+ if (val != 0)
+ {
+ inferior_pid = saved_inferior_pid;
+ return val;
+ }
+ }
+ }
+ inferior_pid = saved_inferior_pid;
+ return 0;
+}
+
+void
+update_breakpoints_after_exec ()
+{
+ struct breakpoint * b;
+ struct breakpoint * temp;
+
+ /* Doing this first prevents the badness of having delete_breakpoint()
+ write a breakpoint's current "shadow contents" to lift the bp. That
+ shadow is NOT valid after an exec()! */
+ mark_breakpoints_out ();
+
+ ALL_BREAKPOINTS_SAFE (b, temp)
+ {
+ /* Solib breakpoints must be explicitly reset after an exec(). */
+ if (b->type == bp_shlib_event)
+ {
+ delete_breakpoint (b);
+ continue;
+ }
+
+ /* Step-resume breakpoints are meaningless after an exec(). */
+ if (b->type == bp_step_resume)
+ {
+ delete_breakpoint (b);
+ continue;
+ }
+
+ /* Ditto the sigtramp handler breakpoints. */
+ if (b->type == bp_through_sigtramp)
+ {
+ delete_breakpoint (b);
+ continue;
+ }
+
+ /* Ditto the exception-handling catchpoints. */
+ if ((b->type == bp_catch_catch) || (b->type == bp_catch_throw))
+ {
+ delete_breakpoint (b);
+ continue;
+ }
+
+ /* Don't delete an exec catchpoint, because else the inferior
+ won't stop when it ought!
+
+ Similarly, we probably ought to keep vfork catchpoints, 'cause
+ on this target, we may not be able to stop when the vfork is seen,
+ but only when the subsequent exec is seen. (And because deleting
+ fork catchpoints here but not vfork catchpoints will seem mysterious
+ to users, keep those too.)
+
+ ??rehrauer: Let's hope that merely clearing out this catchpoint's
+ target address field, if any, is sufficient to have it be reset
+ automagically. Certainly on HP-UX that's true. */
+ if ((b->type == bp_catch_exec) ||
+ (b->type == bp_catch_vfork) ||
+ (b->type == bp_catch_fork))
+ {
+ b->address = (CORE_ADDR) NULL;
+ continue;
+ }
+
+ /* bp_finish is a special case. The only way we ought to be able
+ to see one of these when an exec() has happened, is if the user
+ caught a vfork, and then said "finish". Ordinarily a finish just
+ carries them to the call-site of the current callee, by setting
+ a temporary bp there and resuming. But in this case, the finish
+ will carry them entirely through the vfork & exec.
+
+ We don't want to allow a bp_finish to remain inserted now. But
+ we can't safely delete it, 'cause finish_command has a handle to
+ the bp on a bpstat, and will later want to delete it. There's a
+ chance (and I've seen it happen) that if we delete the bp_finish
+ here, that its storage will get reused by the time finish_command
+ gets 'round to deleting the "use to be a bp_finish" breakpoint.
+ We really must allow finish_command to delete a bp_finish.
+
+ In the absense of a general solution for the "how do we know it's
+ safe to delete something others may have handles to?" problem, what
+ we'll do here is just uninsert the bp_finish, and let finish_command
+ delete it.
+
+ (We know the bp_finish is "doomed" in the sense that it's momentary,
+ and will be deleted as soon as finish_command sees the inferior stopped.
+ So it doesn't matter that the bp's address is probably bogus in the
+ new a.out, unlike e.g., the solib breakpoints.) */
+ if (b->type == bp_finish)
+ {
+ continue;
+ }
+
+ /* Without a symbolic address, we have little hope of the
+ pre-exec() address meaning the same thing in the post-exec()
+ a.out. */
+ if (b->addr_string == NULL)
+ {
+ delete_breakpoint (b);
+ continue;
+ }
+
+ /* If this breakpoint has survived the above battery of checks, then
+ it must have a symbolic address. Be sure that it gets reevaluated
+ to a target address, rather than reusing the old evaluation. */
+ b->address = (CORE_ADDR) NULL;
+ }
+}
+
+int
+detach_breakpoints (pid)
+ int pid;
+{
+ register struct breakpoint *b;
+ int val;
+ int saved_inferior_pid = inferior_pid;
+
+ if (pid == inferior_pid)
+ error ("Cannot detach breakpoints of inferior_pid");
+
+ inferior_pid = pid; /* Because remove_breakpoint will use this global. */
+ ALL_BREAKPOINTS (b)
+ {
+ if (b->inserted)
+ {
+ val = remove_breakpoint (b, mark_inserted);
+ if (val != 0)
+ {
+ inferior_pid = saved_inferior_pid;
+ return val;
+ }
+ }
+ }
+ inferior_pid = saved_inferior_pid;
+ return 0;
+}
+
+static int
+remove_breakpoint (b, is)
+ struct breakpoint *b;
+ insertion_state_t is;
+{
+ int val;
+
+ if (b->type == bp_none)
+ warning ("attempted to remove apparently deleted breakpoint #%d?\n", b->number);
+
+ if (b->type != bp_watchpoint
+ && b->type != bp_hardware_watchpoint
+ && b->type != bp_read_watchpoint
+ && b->type != bp_access_watchpoint
+ && b->type != bp_catch_fork
+ && b->type != bp_catch_vfork
+ && b->type != bp_catch_exec
+ && b->type != bp_catch_catch
+ && b->type != bp_catch_throw)
+
+ {
+ if (b->type == bp_hardware_breakpoint)
+ val = target_remove_hw_breakpoint(b->address, b->shadow_contents);
+ else
+ {
+ /* Check to see if breakpoint is in an overlay section;
+ if so, we should remove the breakpoint at the LMA address.
+ If that is not equal to the raw address, then we should
+ presumable remove the breakpoint there as well. */
+ if (overlay_debugging && b->section &&
+ section_is_overlay (b->section))
+ {
+ CORE_ADDR addr;
+
+ addr = overlay_unmapped_address (b->address, b->section);
+ val = target_remove_breakpoint (addr, b->shadow_contents);
+ /* This would be the time to check val, to see if the
+ shadow breakpoint write to the load address succeeded.
+ However, this might be an ordinary occurrance, eg. if
+ the unmapped overlay is in ROM. */
+ val = 0; /* in case unmapped address failed */
+ if (section_is_mapped (b->section))
+ val = target_remove_breakpoint (b->address,
+ b->shadow_contents);
+ }
+ else /* ordinary (non-overlay) address */
+ val = target_remove_breakpoint(b->address, b->shadow_contents);
+ }
+ if (val)
+ return val;
+ b->inserted = (is == mark_inserted);
+ }
+ else if ((b->type == bp_hardware_watchpoint ||
+ b->type == bp_read_watchpoint ||
+ b->type == bp_access_watchpoint)
+ && b->enable == enabled
+ && ! b->duplicate)
+ {
+ value_ptr v, n;
+
+ b->inserted = (is == mark_inserted);
+ /* Walk down the saved value chain. */
+ for (v = b->val_chain; v; v = v->next)
+ {
+ /* For each memory reference remove the watchpoint
+ at that address. */
+ if (v->lval == lval_memory)
+ {
+ int addr, len, type;
+
+ addr = VALUE_ADDRESS (v) + VALUE_OFFSET (v);
+ len = TYPE_LENGTH (VALUE_TYPE (v));
+ type = 0;
+ if (b->type == bp_read_watchpoint)
+ type = 1;
+ else if (b->type == bp_access_watchpoint)
+ type = 2;
+
+ val = target_remove_watchpoint (addr, len, type);
+ if (val == -1)
+ b->inserted = 1;
+ val = 0;
+ }
+ }
+ /* Failure to remove any of the hardware watchpoints comes here. */
+ if ((is == mark_uninserted) && (b->inserted))
+ warning ("Hardware watchpoint %d: Could not remove watchpoint\n",
+ b->number);
+
+ /* Free the saved value chain. We will construct a new one
+ the next time the watchpoint is inserted. */
+ for (v = b->val_chain; v; v = n)
+ {
+ n = v->next;
+ value_free (v);
+ }
+ b->val_chain = NULL;
+ }
+ else if ((b->type == bp_catch_fork ||
+ b->type == bp_catch_vfork ||
+ b->type == bp_catch_exec)
+ && b->enable == enabled
+ && ! b->duplicate)
+ {
+ val = -1;
+ switch (b->type)
+ {
+ case bp_catch_fork:
+ val = target_remove_fork_catchpoint (inferior_pid);
+ break;
+ case bp_catch_vfork :
+ val = target_remove_vfork_catchpoint (inferior_pid);
+ break;
+ case bp_catch_exec :
+ val = target_remove_exec_catchpoint (inferior_pid);
+ break;
+ }
+ if (val)
+ return val;
+ b->inserted = (is == mark_inserted);
+ }
+ else if ((b->type == bp_catch_catch ||
+ b->type == bp_catch_throw)
+ && b->enable == enabled
+ && ! b->duplicate)
+ {
+
+ val = target_remove_breakpoint(b->address, b->shadow_contents);
+ if (val)
+ return val;
+ b->inserted = (is == mark_inserted);
+ }
+ else if (ep_is_exception_catchpoint (b)
+ && b->inserted /* sometimes previous insert doesn't happen */
+ && b->enable == enabled
+ && ! b->duplicate)
+ {
+
+ val = target_remove_breakpoint(b->address, b->shadow_contents);
+ if (val)
+ return val;
+
+ b->inserted = (is == mark_inserted);
+ }
+
+ 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.
+
+ Plus other such housekeeping that has to be done for breakpoints
+ between runs.
+
+ Note: this function gets called at the end of a run (by generic_mourn_inferior)
+ and when a run begins (by init_wait_for_inferior). */
+
+
+
+void
+breakpoint_init_inferior (context)
+ enum inf_context context;
+{
+ register struct breakpoint *b, *temp;
+ static int warning_needed = 0;
+
+ ALL_BREAKPOINTS_SAFE (b, temp)
+ {
+ b->inserted = 0;
+
+ switch (b->type)
+ {
+ case bp_call_dummy:
+ case bp_watchpoint_scope:
+
+ /* 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.
+
+ Also get rid of scope breakpoints. */
+ delete_breakpoint (b);
+ break;
+
+ case bp_watchpoint:
+ case bp_hardware_watchpoint:
+ case bp_read_watchpoint:
+ case bp_access_watchpoint:
+
+ /* Likewise for watchpoints on local expressions. */
+ if (b->exp_valid_block != NULL)
+ delete_breakpoint (b);
+ break;
+ default:
+ /* Likewise for exception catchpoints in dynamic-linked
+ executables where required */
+ if (ep_is_exception_catchpoint (b) &&
+ exception_catchpoints_are_fragile)
+ {
+ warning_needed = 1;
+ delete_breakpoint (b);
+ }
+ break;
+ }
+ }
+
+ if (exception_catchpoints_are_fragile)
+ exception_support_initialized = 0;
+
+ /* Don't issue the warning unless it's really needed... */
+ if (warning_needed && (context != inf_exited))
+ {
+ warning ("Exception catchpoints from last run were deleted, you must reinsert them explicitly");
+ warning_needed = 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 == enabled
+ && b->enable != shlib_disabled
+ && b->enable != call_disabled
+ && b->address == pc) /* bp is enabled and matches pc */
+ {
+ if (overlay_debugging &&
+ section_is_overlay (b->section) &&
+ !section_is_mapped (b->section))
+ continue; /* unmapped overlay -- can't be a match */
+ else
+ return 1;
+ }
+
+ return 0;
+}
+
+/* breakpoint_inserted_here_p (PC) is just like breakpoint_here_p(), but it
+ only returns true if there is actually a breakpoint inserted at PC. */
+
+int
+breakpoint_inserted_here_p (pc)
+ CORE_ADDR pc;
+{
+ register struct breakpoint *b;
+
+ ALL_BREAKPOINTS (b)
+ if (b->inserted
+ && b->address == pc) /* bp is inserted and matches pc */
+ {
+ if (overlay_debugging &&
+ section_is_overlay (b->section) &&
+ !section_is_mapped (b->section))
+ continue; /* unmapped overlay -- can't be a match */
+ else
+ return 1;
+ }
+
+ return 0;
+}
+
+/* Return nonzero if FRAME is a dummy frame. We can't use PC_IN_CALL_DUMMY
+ because figuring out the saved SP would take too much time, at least using
+ get_saved_register on the 68k. This means that for this function to
+ work right a port must use the bp_call_dummy breakpoint. */
+
+int
+frame_in_dummy (frame)
+ struct frame_info *frame;
+{
+#ifdef CALL_DUMMY
+#ifdef USE_GENERIC_DUMMY_FRAMES
+ return generic_pc_in_call_dummy (frame->pc, frame->frame);
+#else
+ struct breakpoint *b;
+
+ ALL_BREAKPOINTS (b)
+ {
+ static ULONGEST dummy[] = CALL_DUMMY;
+
+ if (b->type == bp_call_dummy
+ && b->frame == frame->frame
+
+ /* We need to check the PC as well as the frame on the sparc,
+ for signals.exp in the testsuite. */
+ && (frame->pc
+ >= (b->address
+ - sizeof (dummy) / sizeof (LONGEST) * REGISTER_SIZE))
+ && frame->pc <= b->address)
+ return 1;
+ }
+#endif /* GENERIC_DUMMY_FRAMES */
+#endif /* CALL_DUMMY */
+ 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->enable != shlib_disabled
+ && b->enable != call_disabled
+ && b->address == pc
+ && (b->thread == -1 || b->thread == thread))
+ {
+ if (overlay_debugging &&
+ section_is_overlay (b->section) &&
+ !section_is_mapped (b->section))
+ continue; /* unmapped overlay -- can't be a match */
+ else
+ return 1;
+ }
+
+ return 0;
+}
+
+
+/* bpstat stuff. External routines' interfaces are documented
+ in breakpoint.h. */
+
+int
+ep_is_catchpoint (ep)
+ struct breakpoint * ep;
+{
+ return
+ (ep->type == bp_catch_load)
+ || (ep->type == bp_catch_unload)
+ || (ep->type == bp_catch_fork)
+ || (ep->type == bp_catch_vfork)
+ || (ep->type == bp_catch_exec)
+ || (ep->type == bp_catch_catch)
+ || (ep->type == bp_catch_throw)
+
+
+ /* ??rehrauer: Add more kinds here, as are implemented... */
+ ;
+}
+
+int
+ep_is_shlib_catchpoint (ep)
+ struct breakpoint * ep;
+{
+ return
+ (ep->type == bp_catch_load)
+ || (ep->type == bp_catch_unload)
+ ;
+}
+
+int
+ep_is_exception_catchpoint (ep)
+ struct breakpoint * ep;
+{
+ return
+ (ep->type == bp_catch_catch)
+ || (ep->type == bp_catch_throw)
+ ;
+}
+
+/* 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;
+}
+
+/* Find a step_resume breakpoint associated with this bpstat.
+ (If there are multiple step_resume bp's on the list, this function
+ will arbitrarily pick one.)
+
+ It is an error to use this function if BPSTAT doesn't contain a
+ step_resume breakpoint.
+
+ See wait_for_inferior's use of this function. */
+struct breakpoint *
+bpstat_find_step_resume_breakpoint (bsp)
+ bpstat bsp;
+{
+ if (bsp == NULL)
+ error ("Internal error (bpstat_find_step_resume_breakpoint)");
+
+ for (; bsp != NULL; bsp = bsp->next)
+ {
+ if ((bsp->breakpoint_at != NULL) &&
+ (bsp->breakpoint_at->type == bp_step_resume))
+ return bsp->breakpoint_at;
+ }
+
+ error ("Internal error (no step_resume breakpoint found)");
+}
+
+
+/* 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)
+ PTR 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;
+ struct command_line *cmd;
+
+ /* Avoid endless recursion if a `source' command is contained
+ in bs->commands. */
+ if (executing_breakpoint_commands)
+ return;
+
+ executing_breakpoint_commands = 1;
+ old_chain = make_cleanup (cleanup_executing_breakpoints, 0);
+
+top:
+ /* Note that (as of this writing), our callers all appear to
+ be passing us the address of global stop_bpstat. And, if
+ our calls to execute_control_command cause the inferior to
+ proceed, that global (and hence, *bsp) will change.
+
+ We must be careful to not touch *bsp unless the inferior
+ has not proceeded. */
+
+ /* This pointer will iterate over the list of bpstat's. */
+ bs = *bsp;
+
+ breakpoint_proceeded = 0;
+ for (; bs != NULL; bs = bs->next)
+ {
+ cmd = bs->commands;
+ while (cmd != NULL)
+ {
+ execute_control_command (cmd);
+
+ if (breakpoint_proceeded)
+ break;
+ else
+ cmd = cmd->next;
+ }
+ if (breakpoint_proceeded)
+ /* 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. */
+ goto top;
+ else
+ bs->commands = NULL;
+ }
+
+ 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.
+
+ Current scheme: When we stop, bpstat_print() is called.
+ It loops through the bpstat list of things causing this stop,
+ calling the print_it function for each one. The default
+ print_it function, used for breakpoints, is print_it_normal().
+ (Also see print_it_noop() and print_it_done()).
+
+ Return values from this routine (used by bpstat_print() to
+ decide what to do):
+ 1: Means we printed something, and we do *not* desire that
+ something to be followed by a location.
+ 0: Means we printed something, and we *do* desire that
+ something to be followed by a location.
+ -1: Means we printed nothing. */
+
+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_catch_load
+ && bs->breakpoint_at->type != bp_catch_unload
+ && bs->breakpoint_at->type != bp_catch_fork
+ && bs->breakpoint_at->type != bp_catch_vfork
+ && bs->breakpoint_at->type != bp_catch_exec
+ && bs->breakpoint_at->type != bp_catch_catch
+ && bs->breakpoint_at->type != bp_catch_throw
+ && bs->breakpoint_at->type != bp_hardware_breakpoint
+ && bs->breakpoint_at->type != bp_watchpoint
+ && bs->breakpoint_at->type != bp_read_watchpoint
+ && bs->breakpoint_at->type != bp_access_watchpoint
+ && bs->breakpoint_at->type != bp_hardware_watchpoint))
+ return -1;
+
+ if (ep_is_shlib_catchpoint (bs->breakpoint_at))
+ {
+ annotate_catchpoint (bs->breakpoint_at->number);
+ printf_filtered ("\nCatchpoint %d (", bs->breakpoint_at->number);
+ if (bs->breakpoint_at->type == bp_catch_load)
+ printf_filtered ("loaded");
+ else if (bs->breakpoint_at->type == bp_catch_unload)
+ printf_filtered ("unloaded");
+ printf_filtered (" %s), ", bs->breakpoint_at->triggered_dll_pathname);
+ return 0;
+ }
+ else if (bs->breakpoint_at->type == bp_catch_fork ||
+ bs->breakpoint_at->type == bp_catch_vfork)
+ {
+ annotate_catchpoint (bs->breakpoint_at->number);
+ printf_filtered ("\nCatchpoint %d (", bs->breakpoint_at->number);
+ if (bs->breakpoint_at->type == bp_catch_fork)
+ printf_filtered ("forked");
+ else if (bs->breakpoint_at->type == bp_catch_vfork)
+ printf_filtered ("vforked");
+ printf_filtered (" process %d), ", bs->breakpoint_at->forked_inferior_pid);
+ return 0;
+ }
+ else if (bs->breakpoint_at->type == bp_catch_exec)
+ {
+ annotate_catchpoint (bs->breakpoint_at->number);
+ printf_filtered ("\nCatchpoint %d (exec'd %s), ",
+ bs->breakpoint_at->number,
+ bs->breakpoint_at->exec_pathname);
+ return 0;
+ }
+ else if (bs->breakpoint_at->type == bp_catch_catch)
+ {
+ if (current_exception_event && (CURRENT_EXCEPTION_KIND == EX_EVENT_CATCH))
+ {
+ annotate_catchpoint (bs->breakpoint_at->number);
+ printf_filtered ("\nCatchpoint %d (exception caught), ", bs->breakpoint_at->number);
+ printf_filtered ("throw location ");
+ if (CURRENT_EXCEPTION_THROW_PC && CURRENT_EXCEPTION_THROW_LINE)
+ printf_filtered ("%s:%d",
+ CURRENT_EXCEPTION_THROW_FILE,
+ CURRENT_EXCEPTION_THROW_LINE);
+ else
+ printf_filtered ("unknown");
+
+ printf_filtered (", catch location ");
+ if (CURRENT_EXCEPTION_CATCH_PC && CURRENT_EXCEPTION_CATCH_LINE)
+ printf_filtered ("%s:%d",
+ CURRENT_EXCEPTION_CATCH_FILE,
+ CURRENT_EXCEPTION_CATCH_LINE);
+ else
+ printf_filtered ("unknown");
+
+ printf_filtered ("\n");
+ return 1; /* don't bother to print location frame info */
+ }
+ else
+ {
+ return -1; /* really throw, some other bpstat will handle it */
+ }
+ }
+ else if (bs->breakpoint_at->type == bp_catch_throw)
+ {
+ if (current_exception_event && (CURRENT_EXCEPTION_KIND == EX_EVENT_THROW))
+ {
+ annotate_catchpoint (bs->breakpoint_at->number);
+ printf_filtered ("\nCatchpoint %d (exception thrown), ", bs->breakpoint_at->number);
+ printf_filtered ("throw location ");
+ if (CURRENT_EXCEPTION_THROW_PC && CURRENT_EXCEPTION_THROW_LINE)
+ printf_filtered ("%s:%d",
+ CURRENT_EXCEPTION_THROW_FILE,
+ CURRENT_EXCEPTION_THROW_LINE);
+ else
+ printf_filtered ("unknown");
+
+ printf_filtered (", catch location ");
+ if (CURRENT_EXCEPTION_CATCH_PC && CURRENT_EXCEPTION_CATCH_LINE)
+ printf_filtered ("%s:%d",
+ CURRENT_EXCEPTION_CATCH_FILE,
+ CURRENT_EXCEPTION_CATCH_LINE);
+ else
+ printf_filtered ("unknown");
+
+ printf_filtered ("\n");
+ return 1; /* don't bother to print location frame info */
+ }
+ else
+ {
+ return -1; /* really catch, some other bpstat willhandle it */
+ }
+ }
+
+ else if (bs->breakpoint_at->type == bp_breakpoint ||
+ bs->breakpoint_at->type == bp_hardware_breakpoint)
+ {
+ /* I think the user probably only wants to see one breakpoint
+ number, not all of them. */
+ annotate_breakpoint (bs->breakpoint_at->number);
+ printf_filtered ("\nBreakpoint %d, ", bs->breakpoint_at->number);
+ return 0;
+ }
+ else if ((bs->old_val != NULL) &&
+ (bs->breakpoint_at->type == bp_watchpoint ||
+ bs->breakpoint_at->type == bp_access_watchpoint ||
+ bs->breakpoint_at->type == bp_hardware_watchpoint))
+ {
+ annotate_watchpoint (bs->breakpoint_at->number);
+ mention (bs->breakpoint_at);
+ printf_filtered ("\nOld value = ");
+ value_print (bs->old_val, gdb_stdout, 0, Val_pretty_default);
+ printf_filtered ("\nNew value = ");
+ value_print (bs->breakpoint_at->val, gdb_stdout, 0,
+ Val_pretty_default);
+ printf_filtered ("\n");
+ value_free (bs->old_val);
+ bs->old_val = NULL;
+ /* More than one watchpoint may have been triggered. */
+ return -1;
+ }
+ else if (bs->breakpoint_at->type == bp_access_watchpoint ||
+ bs->breakpoint_at->type == bp_read_watchpoint)
+ {
+ mention (bs->breakpoint_at);
+ printf_filtered ("\nValue = ");
+ value_print (bs->breakpoint_at->val, gdb_stdout, 0,
+ Val_pretty_default);
+ printf_filtered ("\n");
+ return -1;
+ }
+ /* We can't deal with it. Maybe another member of the bpstat chain can. */
+ return -1;
+}
+
+/* Print a message indicating what happened.
+ This is called from normal_stop().
+ The input to this routine is the head of the bpstat list - a list
+ of the eventpoints that caused this stop.
+ This routine calls the "print_it" routine(s) associated
+ with these eventpoints. This will print (for example)
+ the "Breakpoint n," part of the output.
+ The return value of this routine is one of:
+
+ -1: Means we printed nothing
+ 0: Means we printed something, and expect subsequent
+ code to print the location. An example is
+ "Breakpoint 1, " which should be followed by
+ the location.
+ 1 : Means we printed something, but there is no need
+ to also print the location part of the message.
+ An example is the catch/throw messages, which
+ don't require a location appended to the end. */
+
+int
+bpstat_print (bs)
+ bpstat bs;
+{
+ int val;
+
+ if (bs == NULL)
+ return -1;
+
+ 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 -1;
+}
+
+/* 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)
+ PTR exp;
+{
+ value_ptr mark = value_mark ();
+ int i = !value_true (evaluate_expression ((struct expression *)exp));
+ value_free_to_mark (mark);
+ return i;
+}
+
+/* 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;
+}
+
+/* Possible return values for watchpoint_check (this can't be an enum
+ because of check_errors). */
+/* The watchpoint has been deleted. */
+#define WP_DELETED 1
+/* The value has changed. */
+#define WP_VALUE_CHANGED 2
+/* The value has not changed. */
+#define WP_VALUE_NOT_CHANGED 3
+
+#define BP_TEMPFLAG 1
+#define BP_HARDWAREFLAG 2
+
+/* Check watchpoint condition. */
+
+static int
+watchpoint_check (p)
+ PTR p;
+{
+ bpstat bs = (bpstat) p;
+ struct breakpoint *b;
+ struct frame_info *fr;
+ int within_current_scope;
+
+ b = bs->breakpoint_at;
+
+ if (b->exp_valid_block == NULL)
+ within_current_scope = 1;
+ else
+ {
+ /* There is no current frame at this moment. If we're going to have
+ any chance of handling watchpoints on local variables, we'll need
+ the frame chain (so we can determine if we're in scope). */
+ reinit_frame_cache();
+ fr = find_frame_addr_in_frame_chain (b->watchpoint_frame);
+ 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_ptr mark = value_mark ();
+ value_ptr new_val = evaluate_expression (bs->breakpoint_at->exp);
+ if (!value_equal (b->val, new_val))
+ {
+ release_value (new_val);
+ value_free_to_mark (mark);
+ bs->old_val = b->val;
+ b->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). */
+ printf_filtered ("\
+Watchpoint %d deleted because the program has left the block in\n\
+which its expression is valid.\n", bs->breakpoint_at->number);
+ if (b->related_breakpoint)
+ b->related_breakpoint->disposition = del_at_next_stop;
+ b->disposition = del_at_next_stop;
+
+ return WP_DELETED;
+ }
+}
+
+/* This is used when everything which needs to be printed has
+ already been printed. But we still want to print the frame. */
+
+/* Background: When we stop, bpstat_print() is called.
+ It loops through the bpstat list of things causing this stop,
+ calling the print_it function for each one. The default
+ print_it function, used for breakpoints, is print_it_normal().
+ Also see print_it_noop() and print_it_done() are the other
+ two possibilities. See comments in bpstat_print() and
+ in header of print_it_normal() for more detail. */
+
+static int
+print_it_done (bs)
+ bpstat bs;
+{
+ return 0;
+}
+
+/* This is used when nothing should be printed for this bpstat entry. */
+/* Background: When we stop, bpstat_print() is called.
+ It loops through the bpstat list of things causing this stop,
+ calling the print_it function for each one. The default
+ print_it function, used for breakpoints, is print_it_normal().
+ Also see print_it_noop() and print_it_done() are the other
+ two possibilities. See comments in bpstat_print() and
+ in header of print_it_normal() for more detail. */
+
+static int
+print_it_noop (bs)
+ bpstat bs;
+{
+ return -1;
+}
+
+/* Get a bpstat associated with having just stopped at address *PC
+ and frame address CORE_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, not_a_breakpoint)
+ CORE_ADDR *pc;
+ int not_a_breakpoint;
+{
+ register struct breakpoint *b, *temp;
+ CORE_ADDR bp_addr;
+ /* True if we've hit a breakpoint (as opposed to a watchpoint). */
+ int real_breakpoint = 0;
+ /* Root of the chain of bpstat's */
+ struct bpstats root_bs[1];
+ /* Pointer to the last thing in the chain currently. */
+ bpstat bs = root_bs;
+ static char message1[] =
+ "Error evaluating expression for watchpoint %d\n";
+ char message[sizeof (message1) + 30 /* slop */];
+
+ /* Get the address where the breakpoint would have been. */
+ bp_addr = *pc - DECR_PC_AFTER_BREAK;
+
+ ALL_BREAKPOINTS_SAFE (b, temp)
+ {
+ if (b->enable == disabled
+ || b->enable == shlib_disabled
+ || b->enable == call_disabled)
+ continue;
+
+ if (b->type != bp_watchpoint
+ && b->type != bp_hardware_watchpoint
+ && b->type != bp_read_watchpoint
+ && b->type != bp_access_watchpoint
+ && b->type != bp_hardware_breakpoint
+ && b->type != bp_catch_fork
+ && b->type != bp_catch_vfork
+ && b->type != bp_catch_exec
+ && b->type != bp_catch_catch
+ && b->type != bp_catch_throw) /* a non-watchpoint bp */
+ if (b->address != bp_addr || /* address doesn't match or */
+ (overlay_debugging && /* overlay doesn't match */
+ section_is_overlay (b->section) &&
+ !section_is_mapped (b->section)))
+ continue;
+
+ if (b->type == bp_hardware_breakpoint
+ && b->address != (*pc - DECR_PC_AFTER_HW_BREAK))
+ continue;
+
+ if (b->type != bp_watchpoint
+ && b->type != bp_hardware_watchpoint
+ && b->type != bp_read_watchpoint
+ && b->type != bp_access_watchpoint
+ && not_a_breakpoint)
+ continue;
+
+ /* Is this a catchpoint of a load or unload? If so, did we
+ get a load or unload of the specified library? If not,
+ ignore it. */
+ if ((b->type == bp_catch_load)
+#if defined(SOLIB_HAVE_LOAD_EVENT)
+ && (!SOLIB_HAVE_LOAD_EVENT(inferior_pid)
+ || ((b->dll_pathname != NULL)
+ && (strcmp (b->dll_pathname, SOLIB_LOADED_LIBRARY_PATHNAME(inferior_pid)) != 0)))
+#endif
+ )
+ continue;
+
+ if ((b->type == bp_catch_unload)
+#if defined(SOLIB_HAVE_UNLOAD_EVENT)
+ && (!SOLIB_HAVE_UNLOAD_EVENT(inferior_pid)
+ || ((b->dll_pathname != NULL)
+ && (strcmp (b->dll_pathname, SOLIB_UNLOADED_LIBRARY_PATHNAME(inferior_pid)) != 0)))
+#endif
+ )
+ continue;
+
+ if ((b->type == bp_catch_fork)
+ && ! target_has_forked (inferior_pid, &b->forked_inferior_pid))
+ continue;
+
+ if ((b->type == bp_catch_vfork)
+ && ! target_has_vforked (inferior_pid, &b->forked_inferior_pid))
+ continue;
+
+ if ((b->type == bp_catch_exec)
+ && ! target_has_execd (inferior_pid, &b->exec_pathname))
+ continue;
+
+ if (ep_is_exception_catchpoint (b) &&
+ !(current_exception_event = target_get_current_exception_event ()))
+ 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 */
+
+ /* Watchpoints may change this, if not found to have triggered. */
+ bs->stop = 1;
+ bs->print = 1;
+
+ sprintf (message, message1, b->number);
+ if (b->type == bp_watchpoint || b->type == bp_hardware_watchpoint)
+ {
+ switch (catch_errors (watchpoint_check, bs, message, RETURN_MASK_ALL))
+ {
+ case WP_DELETED:
+ /* We've already printed what needs to be printed. */
+ bs->print_it = print_it_done;
+ /* Stop. */
+ break;
+ case WP_VALUE_CHANGED:
+ /* Stop. */
+ ++(b->hit_count);
+ break;
+ case WP_VALUE_NOT_CHANGED:
+ /* Don't stop. */
+ bs->print_it = print_it_noop;
+ bs->stop = 0;
+ /* Don't consider this a hit. */
+ --(b->hit_count);
+ continue;
+ default:
+ /* Can't happen. */
+ /* FALLTHROUGH */
+ case 0:
+ /* Error from catch_errors. */
+ printf_filtered ("Watchpoint %d deleted.\n", b->number);
+ if (b->related_breakpoint)
+ b->related_breakpoint->disposition = del_at_next_stop;
+ b->disposition = del_at_next_stop;
+ /* We've already printed what needs to be printed. */
+ bs->print_it = print_it_done;
+
+ /* Stop. */
+ break;
+ }
+ }
+ else if (b->type == bp_read_watchpoint || b->type == bp_access_watchpoint)
+ {
+ CORE_ADDR addr;
+ value_ptr v;
+ int found = 0;
+
+ addr = target_stopped_data_address();
+ if (addr == 0) continue;
+ for (v = b->val_chain; v; v = v->next)
+ {
+ if (v->lval == lval_memory)
+ {
+ CORE_ADDR vaddr;
+
+ vaddr = VALUE_ADDRESS (v) + VALUE_OFFSET (v);
+ if (addr == vaddr)
+ found = 1;
+ }
+ }
+ if (found)
+ switch (catch_errors (watchpoint_check, bs, message, RETURN_MASK_ALL))
+ {
+ case WP_DELETED:
+ /* We've already printed what needs to be printed. */
+ bs->print_it = print_it_done;
+ /* Stop. */
+ break;
+ case WP_VALUE_CHANGED:
+ case WP_VALUE_NOT_CHANGED:
+ /* Stop. */
+ ++(b->hit_count);
+ break;
+ default:
+ /* Can't happen. */
+ case 0:
+ /* Error from catch_errors. */
+ printf_filtered ("Watchpoint %d deleted.\n", b->number);
+ if (b->related_breakpoint)
+ b->related_breakpoint->disposition = del_at_next_stop;
+ b->disposition = del_at_next_stop;
+ /* We've already printed what needs to be printed. */
+ bs->print_it = print_it_done;
+ break;
+ }
+ }
+ else
+ {
+ /* By definition, an encountered breakpoint is a triggered
+ breakpoint. */
+ ++(b->hit_count);
+
+ real_breakpoint = 1;
+ }
+
+ if (b->frame && b->frame != (get_current_frame ())->frame &&
+ (b->type == bp_step_resume &&
+ (INNER_THAN (get_current_frame ()->frame, b->frame))))
+ 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, (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;
+ /* Don't consider this a hit. */
+ --(b->hit_count);
+ }
+ 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) ||
+ (xdb_commands && STREQ ("Q", 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 (real_breakpoint && bs)
+ {
+ if (bs->breakpoint_at->type == bp_hardware_breakpoint)
+ {
+ if (DECR_PC_AFTER_HW_BREAK != 0)
+ {
+ *pc = *pc - DECR_PC_AFTER_HW_BREAK;
+ write_pc (*pc);
+ }
+ }
+ else
+ {
+ if (DECR_PC_AFTER_BREAK != 0 || must_shift_inst_regs)
+ {
+ *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. */
+ }
+ }
+ }
+
+ /* The value of a hardware watchpoint hasn't changed, but the
+ intermediate memory locations we are watching may have. */
+ if (bs && ! bs->stop &&
+ (bs->breakpoint_at->type == bp_hardware_watchpoint ||
+ bs->breakpoint_at->type == bp_read_watchpoint ||
+ bs->breakpoint_at->type == bp_access_watchpoint))
+ {
+ remove_breakpoints ();
+ insert_breakpoints ();
+ }
+ 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,
+
+ /* We hit the step_resume breakpoint. */
+ step_resume,
+
+ /* We hit the through_sigtramp breakpoint. */
+ through_sig,
+
+ /* We hit the shared library event breakpoint. */
+ shlib_event,
+
+ /* We caught a shared library event. */
+ catch_shlib_event,
+
+ /* 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 kc BPSTAT_WHAT_KEEP_CHECKING
+#define ss BPSTAT_WHAT_STOP_SILENT
+#define sn BPSTAT_WHAT_STOP_NOISY
+#define sgl BPSTAT_WHAT_SINGLE
+#define slr BPSTAT_WHAT_SET_LONGJMP_RESUME
+#define clr BPSTAT_WHAT_CLEAR_LONGJMP_RESUME
+#define clrs BPSTAT_WHAT_CLEAR_LONGJMP_RESUME_SINGLE
+#define sr BPSTAT_WHAT_STEP_RESUME
+#define ts BPSTAT_WHAT_THROUGH_SIGTRAMP
+#define shl BPSTAT_WHAT_CHECK_SHLIBS
+#define shlr BPSTAT_WHAT_CHECK_SHLIBS_RESUME_FROM_HOOK
+
+/* "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. */
+
+ /* step_resume entries: a step resume breakpoint overrides another
+ breakpoint of signal handling (see comment in wait_for_inferior
+ at first IN_SIGTRAMP where we set the step_resume breakpoint). */
+ /* We handle the through_sigtramp_breakpoint the same way; having both
+ one of those and a step_resume_breakpoint is probably very rare (?). */
+
+ static const enum bpstat_what_main_action
+ table[(int)class_last][(int)BPSTAT_WHAT_LAST] =
+ {
+ /* old action */
+ /* kc ss sn sgl slr clr clrs sr ts shl shlr
+ */
+/*no_effect*/ {kc, ss, sn, sgl, slr, clr, clrs, sr, ts, shl, shlr},
+/*wp_silent*/ {ss, ss, sn, ss, ss, ss, ss, sr, ts, shl, shlr},
+/*wp_noisy*/ {sn, sn, sn, sn, sn, sn, sn, sr, ts, shl, shlr},
+/*bp_nostop*/ {sgl, ss, sn, sgl, slr, clrs, clrs, sr, ts, shl, shlr},
+/*bp_silent*/ {ss, ss, sn, ss, ss, ss, ss, sr, ts, shl, shlr},
+/*bp_noisy*/ {sn, sn, sn, sn, sn, sn, sn, sr, ts, shl, shlr},
+/*long_jump*/ {slr, ss, sn, slr, err, err, err, sr, ts, shl, shlr},
+/*long_resume*/ {clr, ss, sn, clrs, err, err, err, sr, ts, shl, shlr},
+/*step_resume*/ {sr, sr, sr, sr, sr, sr, sr, sr, ts, shl, shlr},
+/*through_sig*/ {ts, ts, ts, ts, ts, ts, ts, ts, ts, shl, shlr},
+/*shlib*/ {shl, shl, shl, shl, shl, shl, shl, shl, ts, shl, shlr},
+/*catch_shlib*/ {shlr, shlr, shlr, shlr, shlr, shlr, shlr, shlr, ts, shlr, shlr}
+ };
+
+#undef kc
+#undef ss
+#undef sn
+#undef sgl
+#undef slr
+#undef clr
+#undef clrs
+#undef err
+#undef sr
+#undef ts
+#undef shl
+#undef shlr
+ enum bpstat_what_main_action current_action = BPSTAT_WHAT_KEEP_CHECKING;
+ struct bpstat_what retval;
+
+ retval.call_dummy = 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_none:
+ continue;
+
+ case bp_breakpoint:
+ case bp_hardware_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:
+ case bp_hardware_watchpoint:
+ case bp_read_watchpoint:
+ case bp_access_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 (bs->stop)
+ {
+ bs_class = step_resume;
+ }
+ else
+ /* It is for the wrong frame. */
+ bs_class = bp_nostop;
+ break;
+ case bp_through_sigtramp:
+ bs_class = through_sig;
+ break;
+ case bp_watchpoint_scope:
+ bs_class = bp_nostop;
+ break;
+ case bp_shlib_event:
+ bs_class = shlib_event;
+ break;
+ case bp_catch_load:
+ case bp_catch_unload:
+ /* Only if this catchpoint triggered should we cause the
+ step-out-of-dld behaviour. Otherwise, we ignore this
+ catchpoint. */
+ if (bs->stop)
+ bs_class = catch_shlib_event;
+ else
+ bs_class = no_effect;
+ break;
+ case bp_catch_fork:
+ case bp_catch_vfork:
+ case bp_catch_exec:
+ if (bs->stop)
+ {
+ if (bs->print)
+ bs_class = bp_noisy;
+ else
+ bs_class = bp_silent;
+ }
+ else
+ /* There was a catchpoint, but we're not stopping. This requires
+ no further action. */
+ bs_class = no_effect;
+ break;
+ case bp_catch_catch:
+ if (!bs->stop || CURRENT_EXCEPTION_KIND != EX_EVENT_CATCH)
+ bs_class = bp_nostop;
+ else if (bs->stop)
+ bs_class = bs->print ? bp_noisy : bp_silent;
+ break;
+ case bp_catch_throw:
+ if (!bs->stop || CURRENT_EXCEPTION_KIND != EX_EVENT_THROW)
+ bs_class = bp_nostop;
+ else if (bs->stop)
+ bs_class = bs->print ? bp_noisy : bp_silent;
+ 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;
+}
+
+/* Nonzero if there are enabled hardware watchpoints. */
+int
+bpstat_have_active_hw_watchpoints ()
+{
+ struct breakpoint *b;
+ ALL_BREAKPOINTS (b)
+ if ((b->enable == enabled) &&
+ (b->inserted) &&
+ ((b->type == bp_hardware_watchpoint) ||
+ (b->type == bp_read_watchpoint) ||
+ (b->type == bp_access_watchpoint)))
+ return 1;
+ return 0;
+}
+
+
+/* Given a bpstat that records zero or more triggered eventpoints, this
+ function returns another bpstat which contains only the catchpoints
+ on that first list, if any. */
+void
+bpstat_get_triggered_catchpoints (ep_list, cp_list)
+ bpstat ep_list;
+ bpstat * cp_list;
+{
+ struct bpstats root_bs[1];
+ bpstat bs = root_bs;
+ struct breakpoint * ep;
+ char * dll_pathname;
+
+ bpstat_clear (cp_list);
+ root_bs->next = NULL;
+
+ for (; ep_list != NULL; ep_list = ep_list->next )
+ {
+ /* Is this eventpoint a catchpoint? If not, ignore it. */
+ ep = ep_list->breakpoint_at;
+ if (ep == NULL)
+ break;
+ if ((ep->type != bp_catch_load) &&
+ (ep->type != bp_catch_unload) &&
+ (ep->type != bp_catch_catch) &&
+ (ep->type != bp_catch_throw)) /* pai: (temp) ADD fork/vfork here!! */
+ continue;
+
+ /* Yes; add it to the list. */
+ bs = bpstat_alloc (ep, bs);
+ *bs = *ep_list;
+ bs->next = NULL;
+ bs = root_bs->next;
+
+#if defined(SOLIB_ADD)
+ /* Also, for each triggered catchpoint, tag it with the name of
+ the library that caused this trigger. (We copy the name now,
+ because it's only guaranteed to be available NOW, when the
+ catchpoint triggers. Clients who may wish to know the name
+ later must get it from the catchpoint itself.) */
+ if (ep->triggered_dll_pathname != NULL)
+ free (ep->triggered_dll_pathname);
+ if (ep->type == bp_catch_load)
+ dll_pathname = SOLIB_LOADED_LIBRARY_PATHNAME (inferior_pid);
+ else
+ dll_pathname = SOLIB_UNLOADED_LIBRARY_PATHNAME (inferior_pid);
+#else
+ dll_pathname = NULL;
+#endif
+ if (dll_pathname)
+ {
+ ep->triggered_dll_pathname = (char *) xmalloc (strlen (dll_pathname) + 1);
+ strcpy (ep->triggered_dll_pathname, dll_pathname);
+ }
+ else
+ ep->triggered_dll_pathname = NULL;
+ }
+
+ *cp_list = bs;
+}
+
+/* Print information on breakpoint number BNUM, or -1 if all.
+ If WATCHPOINTS is zero, process only breakpoints; if WATCHPOINTS
+ is nonzero, process only watchpoints. */
+
+typedef struct {
+ enum bptype type;
+ char * description;
+} ep_type_description_t;
+
+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 ep_type_description_t bptypes[] =
+ {
+ {bp_none, "?deleted?"},
+ {bp_breakpoint, "breakpoint"},
+ {bp_hardware_breakpoint, "hw breakpoint"},
+ {bp_until, "until"},
+ {bp_finish, "finish"},
+ {bp_watchpoint, "watchpoint"},
+ {bp_hardware_watchpoint, "hw watchpoint"},
+ {bp_read_watchpoint, "read watchpoint"},
+ {bp_access_watchpoint, "acc watchpoint"},
+ {bp_longjmp, "longjmp"},
+ {bp_longjmp_resume, "longjmp resume"},
+ {bp_step_resume, "step resume"},
+ {bp_through_sigtramp, "sigtramp"},
+ {bp_watchpoint_scope, "watchpoint scope"},
+ {bp_call_dummy, "call dummy"},
+ {bp_shlib_event, "shlib events"},
+ {bp_catch_load, "catch load"},
+ {bp_catch_unload, "catch unload"},
+ {bp_catch_fork, "catch fork"},
+ {bp_catch_vfork, "catch vfork"},
+ {bp_catch_exec, "catch exec"},
+ {bp_catch_catch, "catch catch"},
+ {bp_catch_throw, "catch throw"}
+ };
+
+ static char *bpdisps[] = {"del", "dstp", "dis", "keep"};
+ static char bpenables[] = "nyn";
+ 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_catch_load
+ && b->type != bp_catch_unload
+ && b->type != bp_catch_fork
+ && b->type != bp_catch_vfork
+ && b->type != bp_catch_exec
+ && b->type != bp_catch_catch
+ && b->type != bp_catch_throw
+ && b->type != bp_hardware_breakpoint
+ && b->type != bp_watchpoint
+ && b->type != bp_read_watchpoint
+ && b->type != bp_access_watchpoint
+ && b->type != bp_hardware_watchpoint)
+ continue;
+
+ if (!found_a_breakpoint++)
+ {
+ annotate_breakpoints_headers ();
+
+ annotate_field (0);
+ printf_filtered ("Num ");
+ annotate_field (1);
+ printf_filtered ("Type ");
+ annotate_field (2);
+ printf_filtered ("Disp ");
+ annotate_field (3);
+ printf_filtered ("Enb ");
+ if (addressprint)
+ {
+ annotate_field (4);
+ printf_filtered ("Address ");
+ }
+ annotate_field (5);
+ printf_filtered ("What\n");
+
+ annotate_breakpoints_table ();
+ }
+
+ annotate_record ();
+ annotate_field (0);
+ printf_filtered ("%-3d ", b->number);
+ annotate_field (1);
+ if ((int)b->type > (sizeof(bptypes)/sizeof(bptypes[0])))
+ error ("bptypes table does not describe type #%d.", (int)b->type);
+ if ((int)b->type != bptypes[(int)b->type].type)
+ error ("bptypes table does not describe type #%d?", (int)b->type);
+ printf_filtered ("%-14s ", bptypes[(int)b->type].description);
+ annotate_field (2);
+ printf_filtered ("%-4s ", bpdisps[(int)b->disposition]);
+ annotate_field (3);
+ printf_filtered ("%-3c ", bpenables[(int)b->enable]);
+
+ strcpy (wrap_indent, " ");
+ if (addressprint)
+ strcat (wrap_indent, " ");
+ switch (b->type)
+ {
+ case bp_watchpoint:
+ case bp_hardware_watchpoint:
+ case bp_read_watchpoint:
+ case bp_access_watchpoint:
+ /* Field 4, the address, is omitted (which makes the columns
+ not line up too nicely with the headers, but the effect
+ is relatively readable). */
+ annotate_field (5);
+ print_expression (b->exp, gdb_stdout);
+ break;
+
+ case bp_catch_load:
+ case bp_catch_unload:
+ /* Field 4, the address, is omitted (which makes the columns
+ not line up too nicely with the headers, but the effect
+ is relatively readable). */
+ annotate_field (5);
+ if (b->dll_pathname == NULL)
+ printf_filtered ("<any library> ");
+ else
+ printf_filtered ("library \"%s\" ", b->dll_pathname);
+ break;
+
+ case bp_catch_fork:
+ case bp_catch_vfork:
+ /* Field 4, the address, is omitted (which makes the columns
+ not line up too nicely with the headers, but the effect
+ is relatively readable). */
+ annotate_field (5);
+ if (b->forked_inferior_pid != 0)
+ printf_filtered ("process %d ", b->forked_inferior_pid);
+ break;
+
+ case bp_catch_exec:
+ /* Field 4, the address, is omitted (which makes the columns
+ not line up too nicely with the headers, but the effect
+ is relatively readable). */
+ annotate_field (5);
+ if (b->exec_pathname != NULL)
+ printf_filtered ("program \"%s\" ", b->exec_pathname);
+ break;
+ case bp_catch_catch:
+ /* Field 4, the address, is omitted (which makes the columns
+ not line up too nicely with the headers, but the effect
+ is relatively readable). */
+ annotate_field (5);
+ printf_filtered ("exception catch ");
+ break;
+ case bp_catch_throw:
+ /* Field 4, the address, is omitted (which makes the columns
+ not line up too nicely with the headers, but the effect
+ is relatively readable). */
+ annotate_field (5);
+ printf_filtered ("exception throw ");
+ break;
+
+ case bp_breakpoint:
+ case bp_hardware_breakpoint:
+ case bp_until:
+ case bp_finish:
+ case bp_longjmp:
+ case bp_longjmp_resume:
+ case bp_step_resume:
+ case bp_through_sigtramp:
+ case bp_watchpoint_scope:
+ case bp_call_dummy:
+ case bp_shlib_event:
+ if (addressprint)
+ {
+ annotate_field (4);
+ /* FIXME-32x64: need a print_address_numeric with
+ field width */
+ printf_filtered
+ ("%s ",
+ local_hex_string_custom
+ ((unsigned long) b->address, "08l"));
+ }
+
+ annotate_field (5);
+
+ last_addr = b->address;
+ if (b->source_file)
+ {
+ sym = find_pc_sect_function (b->address, b->section);
+ if (sym)
+ {
+ fputs_filtered ("in ", gdb_stdout);
+ fputs_filtered (SYMBOL_SOURCE_NAME (sym), gdb_stdout);
+ wrap_here (wrap_indent);
+ fputs_filtered (" at ", gdb_stdout);
+ }
+ fputs_filtered (b->source_file, gdb_stdout);
+ printf_filtered (":%d", b->line_number);
+ }
+ else
+ print_address_symbolic (b->address, gdb_stdout, demangle, " ");
+ break;
+ }
+
+ if (b->thread != -1)
+ printf_filtered (" thread %d", b->thread );
+
+ printf_filtered ("\n");
+
+ if (b->frame)
+ {
+ annotate_field (6);
+
+ printf_filtered ("\tstop only in stack frame at ");
+ print_address_numeric (b->frame, 1, gdb_stdout);
+ printf_filtered ("\n");
+ }
+
+ if (b->cond)
+ {
+ annotate_field (7);
+
+ printf_filtered ("\tstop only if ");
+ print_expression (b->cond, gdb_stdout);
+ printf_filtered ("\n");
+ }
+
+ if (b->thread != -1)
+ {
+ /* FIXME should make an annotation for this */
+ printf_filtered ("\tstop only in thread %d\n", b->thread);
+ }
+
+ if (show_breakpoint_hit_counts && b->hit_count)
+ {
+ /* FIXME should make an annotation for this */
+ if (ep_is_catchpoint (b))
+ printf_filtered ("\tcatchpoint");
+ else
+ printf_filtered ("\tbreakpoint");
+ printf_filtered (" already hit %d time%s\n",
+ b->hit_count, (b->hit_count == 1 ? "" : "s"));
+ }
+
+ if (b->ignore_count)
+ {
+ annotate_field (8);
+
+ printf_filtered ("\tignore next %d hits\n", b->ignore_count);
+ }
+
+ if ((l = b->commands))
+ {
+ annotate_field (9);
+
+ while (l)
+ {
+ print_command_line (l, 4);
+ 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);
+
+ annotate_breakpoints_table_end ();
+}
+
+/* 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 */
+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, section)
+ CORE_ADDR pc;
+ asection *section;
+{
+ register int others = 0;
+ register struct breakpoint *b;
+
+ ALL_BREAKPOINTS (b)
+ if (b->address == pc)
+ if (overlay_debugging == 0 ||
+ b->section == section)
+ others++;
+ if (others > 0)
+ {
+ printf_filtered ("Note: breakpoint%s ", (others > 1) ? "s" : "");
+ ALL_BREAKPOINTS (b)
+ if (b->address == pc)
+ if (overlay_debugging == 0 ||
+ b->section == section)
+ {
+ others--;
+ printf_filtered
+ ("%d%s%s ",
+ b->number,
+ ((b->enable == disabled || b->enable == shlib_disabled || b->enable == call_disabled)
+ ? " (disabled)" : ""),
+ (others > 1) ? "," : ((others == 1) ? " and" : ""));
+ }
+ printf_filtered ("also set at pc ");
+ print_address_numeric (pc, 1, gdb_stdout);
+ printf_filtered (".\n");
+ }
+}
+
+/* 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, section)
+ CORE_ADDR address;
+ asection *section;
+{
+ register struct breakpoint *b;
+ register int count = 0;
+
+ if (address == 0) /* Watchpoints are uninteresting */
+ return;
+
+ ALL_BREAKPOINTS (b)
+ if (b->enable != disabled
+ && b->enable != shlib_disabled
+ && b->enable != call_disabled
+ && b->address == address
+ && (overlay_debugging == 0 || b->section == section))
+ {
+ 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! */
+
+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->section = sal.section;
+ b->language = current_language->la_language;
+ b->input_radix = input_radix;
+ 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;
+ b->dll_pathname = NULL;
+ b->triggered_dll_pathname = NULL;
+ b->forked_inferior_pid = 0;
+ b->exec_pathname = NULL;
+
+ /* Add this breakpoint to the end of the chain
+ so that a list of breakpoints will come out in order
+ of increasing numbers. */
+
+ b1 = breakpoint_chain;
+ if (b1 == 0)
+ breakpoint_chain = b;
+ else
+ {
+ while (b1->next)
+ b1 = b1->next;
+ b1->next = b;
+ }
+
+ check_duplicates (sal.pc, sal.section);
+ breakpoints_changed ();
+
+ return b;
+}
+
+#ifdef GET_LONGJMP_TARGET
+
+static void
+create_longjmp_breakpoint (func_name)
+ char *func_name;
+{
+ struct symtab_and_line sal;
+ struct breakpoint *b;
+
+ INIT_SAL (&sal); /* initialize to zeroes */
+ if (func_name != NULL)
+ {
+ struct minimal_symbol *m;
+
+ m = lookup_minimal_symbol_text (func_name, NULL, (struct objfile *)NULL);
+ if (m)
+ sal.pc = SYMBOL_VALUE_ADDRESS (m);
+ else
+ return;
+ }
+ sal.section = find_pc_overlay (sal.pc);
+ 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--;
+}
+
+#endif /* #ifdef GET_LONGJMP_TARGET */
+
+/* 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, b->section);
+ }
+}
+
+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, b->section);
+ }
+}
+
+#ifdef SOLIB_ADD
+void
+remove_solib_event_breakpoints ()
+{
+ register struct breakpoint *b, *temp;
+
+ ALL_BREAKPOINTS_SAFE (b, temp)
+ if (b->type == bp_shlib_event)
+ delete_breakpoint (b);
+}
+
+void
+create_solib_event_breakpoint (address)
+ CORE_ADDR address;
+{
+ struct breakpoint *b;
+ struct symtab_and_line sal;
+
+ INIT_SAL (&sal); /* initialize to zeroes */
+ sal.pc = address;
+ sal.section = find_pc_overlay (sal.pc);
+ b = set_raw_breakpoint (sal);
+ b->number = internal_breakpoint_number--;
+ b->disposition = donttouch;
+ b->type = bp_shlib_event;
+}
+
+void
+disable_breakpoints_in_shlibs (silent)
+ int silent;
+{
+ struct breakpoint * b;
+ int disabled_shlib_breaks = 0;
+
+ /* See also: insert_breakpoints, under DISABLE_UNSETTABLE_BREAK. */
+ ALL_BREAKPOINTS (b)
+ {
+#if defined (PC_SOLIB)
+ if (((b->type == bp_breakpoint) ||
+ (b->type == bp_hardware_breakpoint)) &&
+ (b->enable != shlib_disabled) &&
+ (b->enable != call_disabled) &&
+ ! b->duplicate &&
+ PC_SOLIB (b->address))
+ {
+ b->enable = shlib_disabled;
+ if (!silent)
+ {
+ if (!disabled_shlib_breaks)
+ {
+ target_terminal_ours_for_output ();
+ printf_filtered ("Temporarily disabling shared library breakpoints:\n");
+ }
+ disabled_shlib_breaks = 1;
+ printf_filtered ("%d ", b->number);
+ }
+ }
+#endif
+ }
+ if (disabled_shlib_breaks && !silent)
+ printf_filtered ("\n");
+}
+
+/* Try to reenable any breakpoints in shared libraries. */
+void
+re_enable_breakpoints_in_shlibs ()
+{
+ struct breakpoint *b;
+
+ ALL_BREAKPOINTS (b)
+ if (b->enable == shlib_disabled)
+ {
+ char buf[1];
+
+ /* Do not reenable the breakpoint if the shared library
+ is still not mapped in. */
+ if (target_read_memory (b->address, buf, 1) == 0)
+ b->enable = enabled;
+ }
+}
+
+#endif
+
+static void
+create_solib_load_unload_event_breakpoint (hookname, tempflag, dll_pathname, cond_string, bp_kind)
+ char * hookname;
+ int tempflag;
+ char * dll_pathname;
+ char * cond_string;
+ enum bptype bp_kind;
+{
+ struct breakpoint * b;
+ struct symtabs_and_lines sals;
+ struct symtab_and_line sal;
+ struct cleanup * old_chain;
+ struct cleanup * canonical_strings_chain = NULL;
+ int i;
+ char * addr_start = hookname;
+ char * addr_end = NULL;
+ char ** canonical = (char **) NULL;
+ int thread = -1; /* All threads. */
+
+ /* Set a breakpoint on the specified hook. */
+ sals = decode_line_1 (&hookname, 1, (struct symtab *) NULL, 0, &canonical);
+ addr_end = hookname;
+
+ if (sals.nelts == 0)
+ {
+ warning ("Unable to set a breakpoint on dynamic linker callback.");
+ warning ("Suggest linking with /opt/langtools/lib/end.o.");
+ warning ("GDB will be unable to track shl_load/shl_unload calls");
+ return;
+ }
+ if (sals.nelts != 1)
+ {
+ warning ("Unable to set a unique breakpoint on dynamic linker callback.");
+ warning ("GDB will be unable to track shl_load/shl_unload calls");
+ return;
+ }
+
+ /* Make sure that all storage allocated in decode_line_1 gets freed in case
+ the following 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);
+ if (canonical[0] != NULL)
+ make_cleanup (free, canonical[0]);
+ }
+
+ resolve_sal_pc (&sals.sals[0]);
+
+ /* Remove the canonical strings from the cleanup, they are needed below. */
+ if (canonical != (char **)NULL)
+ discard_cleanups (canonical_strings_chain);
+
+ b = set_raw_breakpoint (sals.sals[0]);
+ set_breakpoint_count (breakpoint_count + 1);
+ b->number = breakpoint_count;
+ b->cond = NULL;
+ b->cond_string = (cond_string == NULL) ? NULL : savestring (cond_string, strlen (cond_string));
+ b->thread = thread;
+
+ if (canonical != (char **)NULL && canonical[0] != NULL)
+ b->addr_string = canonical[0];
+ else if (addr_start)
+ b->addr_string = savestring (addr_start, addr_end - addr_start);
+
+ b->enable = enabled;
+ b->disposition = tempflag ? del : donttouch;
+
+ if (dll_pathname == NULL)
+ b->dll_pathname = NULL;
+ else
+ {
+ b->dll_pathname = (char *) xmalloc (strlen (dll_pathname) + 1);
+ strcpy (b->dll_pathname, dll_pathname);
+ }
+ b->type = bp_kind;
+
+ mention (b);
+ do_cleanups (old_chain);
+}
+
+void
+create_solib_load_event_breakpoint (hookname, tempflag, dll_pathname, cond_string)
+ char * hookname;
+ int tempflag;
+ char * dll_pathname;
+ char * cond_string;
+{
+ create_solib_load_unload_event_breakpoint (hookname,
+ tempflag,
+ dll_pathname,
+ cond_string,
+ bp_catch_load);
+}
+
+void
+create_solib_unload_event_breakpoint (hookname, tempflag, dll_pathname, cond_string)
+ char * hookname;
+ int tempflag;
+ char * dll_pathname;
+ char * cond_string;
+{
+ create_solib_load_unload_event_breakpoint (hookname,
+ tempflag,
+ dll_pathname,
+ cond_string,
+ bp_catch_unload);
+}
+
+static void
+create_fork_vfork_event_catchpoint (tempflag, cond_string, bp_kind)
+ int tempflag;
+ char * cond_string;
+ enum bptype bp_kind;
+{
+ struct symtab_and_line sal;
+ struct breakpoint * b;
+ int thread = -1; /* All threads. */
+
+ INIT_SAL(&sal);
+ sal.pc = 0;
+ sal.symtab = NULL;
+ sal.line = 0;
+
+ b = set_raw_breakpoint (sal);
+ set_breakpoint_count (breakpoint_count + 1);
+ b->number = breakpoint_count;
+ b->cond = NULL;
+ b->cond_string = (cond_string == NULL) ? NULL : savestring (cond_string, strlen (cond_string));
+ b->thread = thread;
+ b->addr_string = NULL;
+ b->enable = enabled;
+ b->disposition = tempflag ? del : donttouch;
+ b->forked_inferior_pid = 0;
+
+ b->type = bp_kind;
+
+ mention (b);
+}
+
+void
+create_fork_event_catchpoint (tempflag, cond_string)
+ int tempflag;
+ char * cond_string;
+{
+ create_fork_vfork_event_catchpoint (tempflag, cond_string, bp_catch_fork);
+}
+
+void
+create_vfork_event_catchpoint (tempflag, cond_string)
+ int tempflag;
+ char * cond_string;
+{
+ create_fork_vfork_event_catchpoint (tempflag, cond_string, bp_catch_vfork);
+}
+
+void
+create_exec_event_catchpoint (tempflag, cond_string)
+ int tempflag;
+ char * cond_string;
+{
+ struct symtab_and_line sal;
+ struct breakpoint * b;
+ int thread = -1; /* All threads. */
+
+ INIT_SAL(&sal);
+ sal.pc = 0;
+ sal.symtab = NULL;
+ sal.line = 0;
+
+ b = set_raw_breakpoint (sal);
+ set_breakpoint_count (breakpoint_count + 1);
+ b->number = breakpoint_count;
+ b->cond = NULL;
+ b->cond_string = (cond_string == NULL) ? NULL : savestring (cond_string, strlen (cond_string));
+ b->thread = thread;
+ b->addr_string = NULL;
+ b->enable = enabled;
+ b->disposition = tempflag ? del : donttouch;
+
+ b->type = bp_catch_exec;
+
+ mention (b);
+}
+
+static int
+hw_breakpoint_used_count()
+{
+ register struct breakpoint *b;
+ int i = 0;
+
+ ALL_BREAKPOINTS (b)
+ {
+ if (b->type == bp_hardware_breakpoint && b->enable == enabled)
+ i++;
+ }
+
+ return i;
+}
+
+static int
+hw_watchpoint_used_count(type, other_type_used)
+ enum bptype type;
+ int *other_type_used;
+{
+ register struct breakpoint *b;
+ int i = 0;
+
+ *other_type_used = 0;
+ ALL_BREAKPOINTS (b)
+ {
+ if (b->enable == enabled)
+ {
+ if (b->type == type) i++;
+ else if ((b->type == bp_hardware_watchpoint ||
+ b->type == bp_read_watchpoint ||
+ b->type == bp_access_watchpoint)
+ && b->enable == enabled)
+ *other_type_used = 1;
+ }
+ }
+ return i;
+}
+
+/* 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;
+ struct frame_info *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->frame;
+ else
+ b->frame = 0;
+ check_duplicates (b->address, b->section);
+ return;
+ }
+}
+
+void
+disable_watchpoints_before_interactive_call_start ()
+{
+ struct breakpoint * b;
+
+ ALL_BREAKPOINTS (b)
+ {
+ if (((b->type == bp_watchpoint)
+ || (b->type == bp_hardware_watchpoint)
+ || (b->type == bp_read_watchpoint)
+ || (b->type == bp_access_watchpoint)
+ || ep_is_exception_catchpoint (b))
+ && (b->enable == enabled))
+ {
+ b->enable = call_disabled;
+ check_duplicates (b->address, b->section);
+ }
+ }
+}
+
+void
+enable_watchpoints_after_interactive_call_stop ()
+{
+ struct breakpoint * b;
+
+ ALL_BREAKPOINTS (b)
+ {
+ if (((b->type == bp_watchpoint)
+ || (b->type == bp_hardware_watchpoint)
+ || (b->type == bp_read_watchpoint)
+ || (b->type == bp_access_watchpoint)
+ || ep_is_exception_catchpoint (b))
+ && (b->enable == call_disabled))
+ {
+ b->enable = enabled;
+ check_duplicates (b->address, b->section);
+ }
+ }
+}
+
+
+/* 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;
+ struct frame_info *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->frame : 0);
+
+ /* If we're debugging a multi-threaded program, then we
+ want momentary breakpoints to be active in only a
+ single thread of control. */
+ if (in_thread_list (inferior_pid))
+ b->thread = pid_to_thread_id (inferior_pid);
+
+ return b;
+}
+
+
+/* Tell the user we have just set a breakpoint B. */
+
+static void
+mention (b)
+ struct breakpoint *b;
+{
+ int say_where = 0;
+
+ /* FIXME: This is misplaced; mention() is called by things (like hitting a
+ watchpoint) other than breakpoint creation. It should be possible to
+ clean this up and at the same time replace the random calls to
+ breakpoint_changed with this hook, as has already been done for
+ delete_breakpoint_hook and so on. */
+ if (create_breakpoint_hook)
+ create_breakpoint_hook (b);
+
+ switch (b->type)
+ {
+ case bp_none:
+ printf_filtered ("(apparently deleted?) Eventpoint %d: ", b->number);
+ break;
+ case bp_watchpoint:
+ printf_filtered ("Watchpoint %d: ", b->number);
+ print_expression (b->exp, gdb_stdout);
+ break;
+ case bp_hardware_watchpoint:
+ printf_filtered ("Hardware watchpoint %d: ", b->number);
+ print_expression (b->exp, gdb_stdout);
+ break;
+ case bp_read_watchpoint:
+ printf_filtered ("Hardware read watchpoint %d: ", b->number);
+ print_expression (b->exp, gdb_stdout);
+ break;
+ case bp_access_watchpoint:
+ printf_filtered ("Hardware access (read/write) watchpoint %d: ",b->number);
+ print_expression (b->exp, gdb_stdout);
+ break;
+ case bp_breakpoint:
+ printf_filtered ("Breakpoint %d", b->number);
+ say_where = 1;
+ break;
+ case bp_hardware_breakpoint:
+ printf_filtered ("Hardware assisted breakpoint %d", b->number);
+ say_where = 1;
+ break;
+ case bp_catch_load:
+ case bp_catch_unload:
+ printf_filtered ("Catchpoint %d (%s %s)",
+ b->number,
+ (b->type == bp_catch_load) ? "load" : "unload",
+ (b->dll_pathname != NULL) ? b->dll_pathname : "<any library>");
+ break;
+ case bp_catch_fork:
+ case bp_catch_vfork:
+ printf_filtered ("Catchpoint %d (%s)",
+ b->number,
+ (b->type == bp_catch_fork) ? "fork" : "vfork");
+ break;
+ case bp_catch_exec:
+ printf_filtered ("Catchpoint %d (exec)",
+ b->number);
+ break;
+ case bp_catch_catch:
+ case bp_catch_throw:
+ printf_filtered ("Catchpoint %d (%s)",
+ b->number,
+ (b->type == bp_catch_catch) ? "catch" : "throw");
+ break;
+
+ case bp_until:
+ case bp_finish:
+ case bp_longjmp:
+ case bp_longjmp_resume:
+ case bp_step_resume:
+ case bp_through_sigtramp:
+ case bp_call_dummy:
+ case bp_watchpoint_scope:
+ case bp_shlib_event:
+ break;
+ }
+ if (say_where)
+ {
+ if (addressprint || b->source_file == NULL)
+ {
+ printf_filtered (" at ");
+ print_address_numeric (b->address, 1, gdb_stdout);
+ }
+ if (b->source_file)
+ printf_filtered (": file %s, line %d.",
+ b->source_file, b->line_number);
+ TUIDO(((TuiOpaqueFuncPtr)tui_vAllSetHasBreakAt, b, 1));
+ TUIDO(((TuiOpaqueFuncPtr)tuiUpdateAllExecInfos));
+ }
+ printf_filtered ("\n");
+}
+
+
+/* Set a breakpoint according to ARG (function, linenum or *address)
+ flag: first bit : 0 non-temporary, 1 temporary.
+ second bit : 0 normal breakpoint, 1 hardware breakpoint. */
+
+static void
+break_command_1 (arg, flag, from_tty)
+ char *arg;
+ int flag, from_tty;
+{
+ int tempflag, hardwareflag;
+ 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;
+
+ hardwareflag = flag & BP_HARDWAREFLAG;
+ tempflag = flag & BP_TEMPFLAG;
+
+ sals.sals = NULL;
+ sals.nelts = 0;
+
+ INIT_SAL (&sal); /* initialize to zeroes */
+
+ /* 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;
+ sal.section = find_pc_overlay (sal.pc);
+ 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]);
+
+ /* It's possible for the PC to be nonzero, but still an illegal
+ value on some targets.
+
+ For example, on HP-UX if you start gdb, and before running the
+ inferior you try to set a breakpoint on a shared library function
+ "foo" where the inferior doesn't call "foo" directly but does
+ pass its address to another function call, then we do find a
+ minimal symbol for the "foo", but it's address is invalid.
+ (Appears to be an index into a table that the loader sets up
+ when the inferior is run.)
+
+ Give the target a chance to bless sals.sals[i].pc before we
+ try to make a breakpoint for it. */
+ if (PC_REQUIRES_RUN_BEFORE_USE(sals.sals[i].pc))
+ {
+ error ("Cannot break on %s without a running program.", addr_start);
+ }
+
+ 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.");
+ }
+ }
+ if (hardwareflag)
+ {
+ int i, target_resources_ok;
+
+ i = hw_breakpoint_used_count ();
+ target_resources_ok = TARGET_CAN_USE_HARDWARE_WATCHPOINT (
+ bp_hardware_breakpoint, i + sals.nelts, 0);
+ if (target_resources_ok == 0)
+ error ("No hardware breakpoint support in the target.");
+ else if (target_resources_ok < 0)
+ error ("Hardware breakpoints used exceeds limit.");
+ }
+
+ /* 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, sal.section);
+
+ b = set_raw_breakpoint (sal);
+ set_breakpoint_count (breakpoint_count + 1);
+ b->number = breakpoint_count;
+ b->type = hardwareflag ? bp_hardware_breakpoint : 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 ? del : donttouch;
+ mention (b);
+ }
+
+ if (sals.nelts > 1)
+ {
+ printf_filtered ("Multiple breakpoints were set.\n");
+ printf_filtered ("Use the \"delete\" command to delete unwanted breakpoints.\n");
+ }
+ do_cleanups (old_chain);
+}
+
+static void
+break_at_finish_at_depth_command_1 (arg, flag, from_tty)
+ char *arg;
+ int flag;
+ int from_tty;
+{
+ struct frame_info *frame;
+ CORE_ADDR low, high, selected_pc = 0;
+ char *extra_args, *level_arg, *addr_string;
+ int extra_args_len = 0, if_arg = 0;
+
+ if (!arg ||
+ (arg[0] == 'i' && arg[1] == 'f' && (arg[2] == ' ' || arg[2] == '\t')))
+ {
+
+ if (default_breakpoint_valid)
+ {
+ if (selected_frame)
+ {
+ selected_pc = selected_frame->pc;
+ if (arg)
+ if_arg = 1;
+ }
+ else
+ error ("No selected frame.");
+ }
+ else
+ error ("No default breakpoint address now.");
+ }
+ else
+ {
+ extra_args = strchr (arg, ' ');
+ if (extra_args)
+ {
+ extra_args++;
+ extra_args_len = strlen (extra_args);
+ level_arg = (char *) xmalloc (extra_args - arg);
+ strncpy (level_arg, arg, extra_args - arg - 1);
+ level_arg[extra_args - arg - 1] = '\0';
+ }
+ else
+ {
+ level_arg = (char *) xmalloc (strlen (arg) + 1);
+ strcpy (level_arg, arg);
+ }
+
+ frame = parse_frame_specification (level_arg);
+ if (frame)
+ selected_pc = frame->pc;
+ else
+ selected_pc = 0;
+ }
+ if (if_arg)
+ {
+ extra_args = arg;
+ extra_args_len = strlen (arg);
+ }
+
+ if (selected_pc)
+ {
+ if (find_pc_partial_function(selected_pc, (char **)NULL, &low, &high))
+ {
+ addr_string = (char *) xmalloc (26 + extra_args_len);
+ if (extra_args_len)
+ sprintf (addr_string, "*0x%x %s", high, extra_args);
+ else
+ sprintf (addr_string, "*0x%x", high);
+ break_command_1 (addr_string, flag, from_tty);
+ free (addr_string);
+ }
+ else
+ error ("No function contains the specified address");
+ }
+ else
+ error ("Unable to set breakpoint at procedure exit");
+}
+
+
+static void
+break_at_finish_command_1 (arg, flag, from_tty)
+ char *arg;
+ int flag;
+ int from_tty;
+{
+ char *addr_string, *break_string, *beg_addr_string;
+ CORE_ADDR low, high;
+ struct symtabs_and_lines sals;
+ struct symtab_and_line sal;
+ struct cleanup *old_chain;
+ char *extra_args;
+ int extra_args_len = 0;
+ int i, if_arg = 0;
+
+ if (!arg ||
+ (arg[0] == 'i' && arg[1] == 'f' && (arg[2] == ' ' || arg[2] == '\t')))
+ {
+ if (default_breakpoint_valid)
+ {
+ if (selected_frame)
+ {
+ addr_string = (char *) xmalloc (15);
+ sprintf (addr_string, "*0x%x", selected_frame->pc);
+ if (arg)
+ if_arg = 1;
+ }
+ else
+ error ("No selected frame.");
+ }
+ else
+ error ("No default breakpoint address now.");
+ }
+ else
+ {
+ addr_string = (char *) xmalloc (strlen (arg) + 1);
+ strcpy (addr_string, arg);
+ }
+
+ if (if_arg)
+ {
+ extra_args = arg;
+ extra_args_len = strlen (arg);
+ }
+ else
+ if (arg)
+ {
+ /* get the stuff after the function name or address */
+ extra_args = strchr (arg, ' ');
+ if (extra_args)
+ {
+ extra_args++;
+ extra_args_len = strlen (extra_args);
+ }
+ }
+
+ sals.sals = NULL;
+ sals.nelts = 0;
+
+ beg_addr_string = addr_string;
+ sals = decode_line_1 (&addr_string, 1, (struct symtab *)NULL, 0,
+ (char ***)NULL);
+
+ free (beg_addr_string);
+ old_chain = make_cleanup (free, sals.sals);
+ for (i = 0; (i < sals.nelts); i++)
+ {
+ sal = sals.sals[i];
+ if (find_pc_partial_function (sal.pc, (char **)NULL, &low, &high))
+ {
+ break_string = (char *) xmalloc (extra_args_len + 26);
+ if (extra_args_len)
+ sprintf (break_string, "*0x%x %s", high, extra_args);
+ else
+ sprintf (break_string, "*0x%x", high);
+ break_command_1 (break_string, flag, from_tty);
+ free(break_string);
+ }
+ else
+ error ("No function contains the specified address");
+ }
+ if (sals.nelts > 1)
+ {
+ printf_filtered ("Multiple breakpoints were set.\n");
+ printf_filtered ("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 != NULL)
+ {
+ if (!find_line_pc (sal->symtab, sal->line, &pc))
+ error ("No line %d in file \"%s\".",
+ sal->line, sal->symtab->filename);
+ sal->pc = pc;
+ }
+
+ if (sal->section == 0 && sal->symtab != NULL)
+ {
+ struct blockvector *bv;
+ struct block *b;
+ struct symbol *sym;
+ int index;
+
+ bv = blockvector_for_pc_sect (sal->pc, 0, &index, sal->symtab);
+ if (bv != NULL)
+ {
+ b = BLOCKVECTOR_BLOCK (bv, index);
+ sym = block_function (b);
+ if (sym != NULL)
+ {
+ fixup_symbol_section (sym, sal->symtab->objfile);
+ sal->section = SYMBOL_BFD_SECTION (sym);
+ }
+ else
+ {
+ /* It really is worthwhile to have the section, so we'll just
+ have to look harder. This case can be executed if we have
+ line numbers but no functions (as can happen in assembly
+ source). */
+
+ struct minimal_symbol *msym;
+
+ msym = lookup_minimal_symbol_by_pc (sal->pc);
+ if (msym)
+ sal->section = SYMBOL_BFD_SECTION (msym);
+ }
+ }
+ }
+}
+
+void
+break_command (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ break_command_1 (arg, 0, from_tty);
+}
+
+void
+break_at_finish_command (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ break_at_finish_command_1 (arg, 0, from_tty);
+}
+
+void
+break_at_finish_at_depth_command (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ break_at_finish_at_depth_command_1 (arg, 0, from_tty);
+}
+
+void
+tbreak_command (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ break_command_1 (arg, BP_TEMPFLAG, from_tty);
+}
+
+void
+tbreak_at_finish_command (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ break_at_finish_command_1 (arg, BP_TEMPFLAG, from_tty);
+}
+
+static void
+hbreak_command (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ break_command_1 (arg, BP_HARDWAREFLAG, from_tty);
+}
+
+static void
+thbreak_command (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ break_command_1 (arg, (BP_TEMPFLAG | BP_HARDWAREFLAG), from_tty);
+}
+
+static void
+stop_command (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ printf_filtered ("Specify the type of breakpoint to set.\n\
+Usage: stop in <function | address>\n\
+ stop at <line>\n");
+}
+
+static void
+stopin_command (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ int badInput = 0;
+
+ if (arg == (char *)NULL)
+ badInput = 1;
+ else if (*arg != '*')
+ {
+ char *argptr = arg;
+ int hasColon = 0;
+
+ /* look for a ':'. If this is a line number specification, then say
+ it is bad, otherwise, it should be an address or function/method
+ name */
+ while (*argptr && !hasColon)
+ {
+ hasColon = (*argptr == ':');
+ argptr++;
+ }
+
+ if (hasColon)
+ badInput = (*argptr != ':'); /* Not a class::method */
+ else
+ badInput = isdigit(*arg); /* a simple line number */
+ }
+
+ if (badInput)
+ printf_filtered("Usage: stop in <function | address>\n");
+ else
+ break_command_1 (arg, 0, from_tty);
+}
+
+static void
+stopat_command (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ int badInput = 0;
+
+ if (arg == (char *)NULL || *arg == '*') /* no line number */
+ badInput = 1;
+ else
+ {
+ char *argptr = arg;
+ int hasColon = 0;
+
+ /* look for a ':'. If there is a '::' then get out, otherwise
+ it is probably a line number. */
+ while (*argptr && !hasColon)
+ {
+ hasColon = (*argptr == ':');
+ argptr++;
+ }
+
+ if (hasColon)
+ badInput = (*argptr == ':'); /* we have class::method */
+ else
+ badInput = !isdigit(*arg); /* not a line number */
+ }
+
+ if (badInput)
+ printf_filtered("Usage: stop at <line>\n");
+ else
+ break_command_1 (arg, 0, from_tty);
+}
+
+/* ARGSUSED */
+/* accessflag: 0: watch write, 1: watch read, 2: watch access(read or write) */
+static void
+watch_command_1 (arg, accessflag, from_tty)
+ char *arg;
+ int accessflag;
+ int from_tty;
+{
+ struct breakpoint *b;
+ struct symtab_and_line sal;
+ struct expression *exp;
+ struct block *exp_valid_block;
+ struct value *val, *mark;
+ struct frame_info *frame;
+ struct frame_info *prev_frame = NULL;
+ char *exp_start = NULL;
+ char *exp_end = NULL;
+ char *tok, *end_tok;
+ int toklen;
+ char *cond_start = NULL;
+ char *cond_end = NULL;
+ struct expression *cond = NULL;
+ int i, other_type_used, target_resources_ok = 0;
+ enum bptype bp_type;
+ int mem_cnt = 0;
+
+ INIT_SAL (&sal); /* initialize to zeroes */
+
+ /* Parse arguments. */
+ innermost_block = NULL;
+ exp_start = arg;
+ exp = parse_exp_1 (&arg, 0, 0);
+ exp_end = arg;
+ exp_valid_block = innermost_block;
+ mark = value_mark ();
+ val = evaluate_expression (exp);
+ release_value (val);
+ if (VALUE_LAZY (val))
+ value_fetch_lazy (val);
+
+ tok = arg;
+ 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, 0, 0);
+ cond_end = tok;
+ }
+ if (*tok)
+ error("Junk at end of command.");
+
+ if (accessflag == 1) bp_type = bp_read_watchpoint;
+ else if (accessflag == 2) bp_type = bp_access_watchpoint;
+ else bp_type = bp_hardware_watchpoint;
+
+ mem_cnt = can_use_hardware_watchpoint (val);
+ if (mem_cnt == 0 && bp_type != bp_hardware_watchpoint)
+ error ("Expression cannot be implemented with read/access watchpoint.");
+ if (mem_cnt != 0) {
+ i = hw_watchpoint_used_count (bp_type, &other_type_used);
+ target_resources_ok = TARGET_CAN_USE_HARDWARE_WATCHPOINT(
+ bp_type, i + mem_cnt, other_type_used);
+ if (target_resources_ok == 0 && bp_type != bp_hardware_watchpoint)
+ error ("Target does not have this type of hardware watchpoint support.");
+ if (target_resources_ok < 0 && bp_type != bp_hardware_watchpoint)
+ error ("Target resources have been allocated for other types of watchpoints.");
+ }
+
+#if defined(HPUXHPPA)
+ /* On HP-UX if you set a h/w
+ watchpoint before the "run" command, the inferior dies with a e.g.,
+ SIGILL once you start it. I initially believed this was due to a
+ bad interaction between page protection traps and the initial
+ startup sequence by the dynamic linker.
+
+ However, I tried avoiding that by having HP-UX's implementation of
+ TARGET_CAN_USE_HW_WATCHPOINT return FALSE if there was no inferior_pid
+ yet, which forced slow watches before a "run" or "attach", and it
+ still fails somewhere in the startup code.
+
+ Until I figure out what's happening, I'm disallowing watches altogether
+ before the "run" or "attach" command. We'll tell the user they must
+ set watches after getting the program started. */
+ if (! target_has_execution)
+ {
+ warning ("can't do that without a running program; try \"break main\", \"run\" first");
+ return;
+ }
+#endif /* HPUXHPPA */
+
+ /* Now set up the breakpoint. */
+ b = set_raw_breakpoint (sal);
+ set_breakpoint_count (breakpoint_count + 1);
+ b->number = breakpoint_count;
+ b->disposition = donttouch;
+ b->exp = exp;
+ b->exp_valid_block = exp_valid_block;
+ b->exp_string = savestring (exp_start, exp_end - exp_start);
+ b->val = val;
+ b->cond = cond;
+ if (cond_start)
+ b->cond_string = savestring (cond_start, cond_end - cond_start);
+ else
+ b->cond_string = 0;
+
+ frame = block_innermost_frame (exp_valid_block);
+ if (frame)
+ {
+ prev_frame = get_prev_frame (frame);
+ b->watchpoint_frame = frame->frame;
+ }
+ else
+ b->watchpoint_frame = (CORE_ADDR)0;
+
+ if (mem_cnt && target_resources_ok > 0)
+ b->type = bp_type;
+ else
+ b->type = bp_watchpoint;
+
+ /* If the expression is "local", then set up a "watchpoint scope"
+ breakpoint at the point where we've left the scope of the watchpoint
+ expression. */
+ if (innermost_block)
+ {
+ if (prev_frame)
+ {
+ struct breakpoint *scope_breakpoint;
+ struct symtab_and_line scope_sal;
+
+ INIT_SAL (&scope_sal); /* initialize to zeroes */
+ scope_sal.pc = get_frame_pc (prev_frame);
+ scope_sal.section = find_pc_overlay (scope_sal.pc);
+
+ scope_breakpoint = set_raw_breakpoint (scope_sal);
+ set_breakpoint_count (breakpoint_count + 1);
+ scope_breakpoint->number = breakpoint_count;
+
+ scope_breakpoint->type = bp_watchpoint_scope;
+ scope_breakpoint->enable = enabled;
+
+ /* Automatically delete the breakpoint when it hits. */
+ scope_breakpoint->disposition = del;
+
+ /* Only break in the proper frame (help with recursion). */
+ scope_breakpoint->frame = prev_frame->frame;
+
+ /* Set the address at which we will stop. */
+ scope_breakpoint->address = get_frame_pc (prev_frame);
+
+ /* The scope breakpoint is related to the watchpoint. We
+ will need to act on them together. */
+ b->related_breakpoint = scope_breakpoint;
+ }
+ }
+ value_free_to_mark (mark);
+ mention (b);
+}
+
+/* Return count of locations need to be watched and can be handled
+ in hardware. If the watchpoint can not be handled
+ in hardware return zero. */
+
+#if !defined(TARGET_REGION_SIZE_OK_FOR_HW_WATCHPOINT)
+#define TARGET_REGION_SIZE_OK_FOR_HW_WATCHPOINT(byte_size) \
+ ((byte_size) <= (REGISTER_SIZE))
+#endif
+
+static int
+can_use_hardware_watchpoint (v)
+ struct value *v;
+{
+ int found_memory_cnt = 0;
+
+ /* Did the user specifically forbid us to use hardware watchpoints? */
+ if (! can_use_hw_watchpoints)
+ return 0;
+
+ /* Make sure all the intermediate values are in memory. Also make sure
+ we found at least one memory expression. Guards against watch 0x12345,
+ which is meaningless, but could cause errors if one tries to insert a
+ hardware watchpoint for the constant expression. */
+ for ( ; v; v = v->next)
+ {
+ if (v->lval == lval_memory)
+ {
+ if (TARGET_REGION_SIZE_OK_FOR_HW_WATCHPOINT (TYPE_LENGTH (VALUE_TYPE (v))))
+ found_memory_cnt++;
+ }
+ else if (v->lval != not_lval && v->modifiable == 0)
+ return 0;
+ }
+
+ /* The expression itself looks suitable for using a hardware
+ watchpoint, but give the target machine a chance to reject it. */
+ return found_memory_cnt;
+}
+
+static void watch_command (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ watch_command_1 (arg, 0, from_tty);
+}
+
+static void rwatch_command (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ watch_command_1 (arg, 1, from_tty);
+}
+
+static void awatch_command (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ watch_command_1 (arg, 2, from_tty);
+}
+
+
+/* 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;
+ struct frame_info *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 ((make_cleanup_func) delete_breakpoint, breakpoint);
+
+ /* Keep within the current frame */
+
+ if (prev_frame)
+ {
+ sal = find_pc_line (prev_frame->pc, 0);
+ sal.pc = prev_frame->pc;
+ breakpoint = set_momentary_breakpoint (sal, prev_frame, bp_until);
+ make_cleanup ((make_cleanup_func) delete_breakpoint, breakpoint);
+ }
+
+ proceed (-1, TARGET_SIGNAL_DEFAULT, 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;
+};
+
+/* Not really used -- invocation in handle_gnu_4_16_catch_command
+ had been commented out in the v.4.16 sources, and stays
+ disabled there now because "catch NAME" syntax isn't allowed.
+ pai/1997-07-11 */
+/* 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_unfiltered ("No catch clause for exception %s.\n", p);
+#if 0
+ win:
+#endif
+ p = p1;
+ while (*p == ' ' || *p == '\t') p++;
+ }
+}
+
+/* This shares a lot of code with `print_frame_label_vars' from stack.c. */
+
+static struct symtabs_and_lines
+get_catch_sals (this_level_only)
+ int this_level_only;
+{
+ register struct blockvector *bl;
+ register struct block *block;
+ int index, have_default = 0;
+ 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);
+ pc = selected_frame->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;
+}
+
+static void
+ep_skip_leading_whitespace (s)
+ char ** s;
+{
+ if ((s == NULL) || (*s == NULL))
+ return;
+ while (isspace(**s))
+ *s += 1;
+}
+
+/* This function examines a string, and attempts to find a token
+ that might be an event name in the leading characters. If a
+ possible match is found, a pointer to the last character of
+ the token is returned. Else, NULL is returned. */
+static char *
+ep_find_event_name_end (arg)
+ char * arg;
+{
+ char * s = arg;
+ char * event_name_end = NULL;
+
+ /* If we could depend upon the presense of strrpbrk, we'd use that... */
+ if (arg == NULL)
+ return NULL;
+
+ /* We break out of the loop when we find a token delimiter.
+ Basically, we're looking for alphanumerics and underscores;
+ anything else delimites the token. */
+ while (*s != '\0')
+ {
+ if (! isalnum(*s) && (*s != '_'))
+ break;
+ event_name_end = s;
+ s++;
+ }
+
+ return event_name_end;
+}
+
+
+/* This function attempts to parse an optional "if <cond>" clause
+ from the arg string. If one is not found, it returns NULL.
+
+ Else, it returns a pointer to the condition string. (It does not
+ attempt to evaluate the string against a particular block.) And,
+ it updates arg to point to the first character following the parsed
+ if clause in the arg string. */
+static char *
+ep_parse_optional_if_clause (arg)
+ char ** arg;
+{
+ char * cond_string;
+
+ if (((*arg)[0] != 'i') || ((*arg)[1] != 'f') || !isspace((*arg)[2]))
+ return NULL;
+
+ /* Skip the "if" keyword. */
+ (*arg) += 2;
+
+ /* Skip any extra leading whitespace, and record the start of the
+ condition string. */
+ ep_skip_leading_whitespace (arg);
+ cond_string = *arg;
+
+ /* Assume that the condition occupies the remainder of the arg string. */
+ (*arg) += strlen (cond_string);
+
+ return cond_string;
+}
+
+/* This function attempts to parse an optional filename from the arg
+ string. If one is not found, it returns NULL.
+
+ Else, it returns a pointer to the parsed filename. (This function
+ makes no attempt to verify that a file of that name exists, or is
+ accessible.) And, it updates arg to point to the first character
+ following the parsed filename in the arg string.
+
+ Note that clients needing to preserve the returned filename for
+ future access should copy it to their own buffers. */
+static char *
+ep_parse_optional_filename (arg)
+ char ** arg;
+{
+ static char filename [1024];
+ char * arg_p = *arg;
+ int i;
+ char c;
+
+ if ((*arg_p == '\0') || isspace (*arg_p))
+ return NULL;
+
+ for (i=0; ; i++)
+ {
+ c = *arg_p;
+ if (isspace (c))
+ c = '\0';
+ filename[i] = c;
+ if (c == '\0')
+ break;
+ arg_p++;
+ }
+ *arg = arg_p;
+
+ return filename;
+}
+
+/* Commands to deal with catching events, such as signals, exceptions,
+ process start/exit, etc. */
+
+typedef enum {catch_fork, catch_vfork} catch_fork_kind;
+
+static void
+catch_fork_command_1 (fork_kind, arg, tempflag, from_tty)
+ catch_fork_kind fork_kind;
+ char * arg;
+ int tempflag;
+ int from_tty;
+{
+ char * cond_string = NULL;
+
+ ep_skip_leading_whitespace (&arg);
+
+ /* The allowed syntax is:
+ catch [v]fork
+ catch [v]fork if <cond>
+
+ First, check if there's an if clause. */
+ cond_string = ep_parse_optional_if_clause (&arg);
+
+ if ((*arg != '\0') && !isspace (*arg))
+ error ("Junk at end of arguments.");
+
+ /* If this target supports it, create a fork or vfork catchpoint
+ and enable reporting of such events. */
+ switch (fork_kind) {
+ case catch_fork :
+ create_fork_event_catchpoint (tempflag, cond_string);
+ break;
+ case catch_vfork :
+ create_vfork_event_catchpoint (tempflag, cond_string);
+ break;
+ default :
+ error ("unsupported or unknown fork kind; cannot catch it");
+ break;
+ }
+}
+
+static void
+catch_exec_command_1 (arg, tempflag, from_tty)
+ char * arg;
+ int tempflag;
+ int from_tty;
+{
+ char * cond_string = NULL;
+
+ ep_skip_leading_whitespace (&arg);
+
+ /* The allowed syntax is:
+ catch exec
+ catch exec if <cond>
+
+ First, check if there's an if clause. */
+ cond_string = ep_parse_optional_if_clause (&arg);
+
+ if ((*arg != '\0') && !isspace (*arg))
+ error ("Junk at end of arguments.");
+
+ /* If this target supports it, create an exec catchpoint
+ and enable reporting of such events. */
+ create_exec_event_catchpoint (tempflag, cond_string);
+}
+
+#if defined(SOLIB_ADD)
+static void
+catch_load_command_1 (arg, tempflag, from_tty)
+ char * arg;
+ int tempflag;
+ int from_tty;
+{
+ char * dll_pathname = NULL;
+ char * cond_string = NULL;
+
+ ep_skip_leading_whitespace (&arg);
+
+ /* The allowed syntax is:
+ catch load
+ catch load if <cond>
+ catch load <filename>
+ catch load <filename> if <cond>
+
+ The user is not allowed to specify the <filename> after an
+ if clause.
+
+ We'll ignore the pathological case of a file named "if".
+
+ First, check if there's an if clause. If so, then there
+ cannot be a filename. */
+ cond_string = ep_parse_optional_if_clause (&arg);
+
+ /* If there was an if clause, then there cannot be a filename.
+ Else, there might be a filename and an if clause. */
+ if (cond_string == NULL)
+ {
+ dll_pathname = ep_parse_optional_filename (&arg);
+ ep_skip_leading_whitespace (&arg);
+ cond_string = ep_parse_optional_if_clause (&arg);
+ }
+
+ if ((*arg != '\0') && !isspace (*arg))
+ error ("Junk at end of arguments.");
+
+ /* Create a load breakpoint that only triggers when a load of
+ the specified dll (or any dll, if no pathname was specified)
+ occurs. */
+ SOLIB_CREATE_CATCH_LOAD_HOOK (inferior_pid, tempflag, dll_pathname, cond_string);
+}
+
+static void
+catch_unload_command_1 (arg, tempflag, from_tty)
+ char * arg;
+ int tempflag;
+ int from_tty;
+{
+ char * dll_pathname = NULL;
+ char * cond_string = NULL;
+
+ ep_skip_leading_whitespace (&arg);
+
+ /* The allowed syntax is:
+ catch unload
+ catch unload if <cond>
+ catch unload <filename>
+ catch unload <filename> if <cond>
+
+ The user is not allowed to specify the <filename> after an
+ if clause.
+
+ We'll ignore the pathological case of a file named "if".
+
+ First, check if there's an if clause. If so, then there
+ cannot be a filename. */
+ cond_string = ep_parse_optional_if_clause (&arg);
+
+ /* If there was an if clause, then there cannot be a filename.
+ Else, there might be a filename and an if clause. */
+ if (cond_string == NULL)
+ {
+ dll_pathname = ep_parse_optional_filename (&arg);
+ ep_skip_leading_whitespace (&arg);
+ cond_string = ep_parse_optional_if_clause (&arg);
+ }
+
+ if ((*arg != '\0') && !isspace (*arg))
+ error ("Junk at end of arguments.");
+
+ /* Create an unload breakpoint that only triggers when an unload of
+ the specified dll (or any dll, if no pathname was specified)
+ occurs. */
+ SOLIB_CREATE_CATCH_UNLOAD_HOOK (inferior_pid, tempflag, dll_pathname, cond_string);
+}
+#endif /* SOLIB_ADD */
+
+/* Commands to deal with catching exceptions. */
+
+/* Set a breakpoint at the specified callback routine for an
+ exception event callback */
+
+static void
+create_exception_catchpoint (tempflag, cond_string, ex_event, sal)
+ int tempflag;
+ char * cond_string;
+ enum exception_event_kind ex_event;
+ struct symtab_and_line * sal;
+{
+ struct breakpoint * b;
+ int i;
+ int thread = -1; /* All threads. */
+
+ if (!sal) /* no exception support? */
+ return;
+
+ b = set_raw_breakpoint (*sal);
+ set_breakpoint_count (breakpoint_count + 1);
+ b->number = breakpoint_count;
+ b->cond = NULL;
+ b->cond_string = (cond_string == NULL) ? NULL : savestring (cond_string, strlen (cond_string));
+ b->thread = thread;
+ b->addr_string = NULL;
+ b->enable = enabled;
+ b->disposition = tempflag ? del : donttouch;
+ switch (ex_event)
+ {
+ case EX_EVENT_THROW:
+ b->type = bp_catch_throw;
+ break;
+ case EX_EVENT_CATCH:
+ b->type = bp_catch_catch;
+ break;
+ default: /* error condition */
+ b->type = bp_none;
+ b->enable = disabled;
+ error ("Internal error -- invalid catchpoint kind");
+ }
+ mention (b);
+}
+
+/* Deal with "catch catch" and "catch throw" commands */
+
+static void
+catch_exception_command_1 (ex_event, arg, tempflag, from_tty)
+ enum exception_event_kind ex_event;
+ char * arg;
+ int tempflag;
+ int from_tty;
+{
+ char * cond_string = NULL;
+ struct symtab_and_line * sal = NULL;
+
+ ep_skip_leading_whitespace (&arg);
+
+ cond_string = ep_parse_optional_if_clause (&arg);
+
+ if ((*arg != '\0') && !isspace (*arg))
+ error ("Junk at end of arguments.");
+
+ if ((ex_event != EX_EVENT_THROW) &&
+ (ex_event != EX_EVENT_CATCH))
+ error ("Unsupported or unknown exception event; cannot catch it");
+
+ /* See if we can find a callback routine */
+ sal = target_enable_exception_callback (ex_event, 1);
+
+ if (sal)
+ {
+ /* We have callbacks from the runtime system for exceptions.
+ Set a breakpoint on the sal found, if no errors */
+ if (sal != (struct symtab_and_line *) -1)
+ create_exception_catchpoint (tempflag, cond_string, ex_event, sal);
+ else
+ return; /* something went wrong with setting up callbacks */
+ }
+ else
+ {
+ /* No callbacks from runtime system for exceptions.
+ Try GNU C++ exception breakpoints using labels in debug info. */
+ if (ex_event == EX_EVENT_CATCH)
+ {
+ handle_gnu_4_16_catch_command (arg, tempflag, from_tty);
+ }
+ else if (ex_event == EX_EVENT_THROW)
+ {
+ /* Set a breakpoint on __raise_exception () */
+
+ fprintf_filtered (gdb_stderr, "Unsupported with this platform/compiler combination.\n");
+ fprintf_filtered (gdb_stderr, "Perhaps you can achieve the effect you want by setting\n");
+ fprintf_filtered (gdb_stderr, "a breakpoint on __raise_exception().\n");
+ }
+ }
+}
+
+/* Cover routine to allow wrapping target_enable_exception_catchpoints
+ inside a catch_errors */
+
+static int
+cover_target_enable_exception_callback (arg)
+ PTR arg;
+{
+ args_for_catchpoint_enable *args = arg;
+ struct symtab_and_line *sal;
+ sal = target_enable_exception_callback (args->kind, args->enable);
+ if (sal == NULL)
+ return 0;
+ else if (sal == (struct symtab_and_line *) -1)
+ return -1;
+ else
+ return 1; /*is valid*/
+}
+
+
+
+/* This is the original v.4.16 and earlier version of the
+ catch_command_1() function. Now that other flavours of "catch"
+ have been introduced, and since exception handling can be handled
+ in other ways (through target ops) also, this is used only for the
+ GNU C++ exception handling system.
+ Note: Only the "catch" flavour of GDB 4.16 is handled here. The
+ "catch NAME" is now no longer allowed in catch_command_1(). Also,
+ there was no code in GDB 4.16 for "catch throw".
+
+ Called from catch_exception_command_1 () */
+
+
+static void
+handle_gnu_4_16_catch_command (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;
+
+ INIT_SAL (&sal); /* initialize to zeroes */
+
+ /* 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
+ /* Not sure why this code has been disabled. I'm leaving
+ it disabled. We can never come here now anyway
+ since we don't allow the "catch NAME" syntax.
+ pai/1997-07-11 */
+
+ /* 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, sal.section);
+
+ b = set_raw_breakpoint (sal);
+ set_breakpoint_count (breakpoint_count + 1);
+ b->number = breakpoint_count;
+ b->type = bp_breakpoint; /* Important -- this is an ordinary breakpoint.
+ For platforms with callback support for exceptions,
+ create_exception_catchpoint() will create special
+ bp types (bp_catch_catch and bp_catch_throw), and
+ there is code in insert_breakpoints() and elsewhere
+ that depends on that. */
+
+ b->cond = cond;
+ b->enable = enabled;
+ b->disposition = tempflag ? del : donttouch;
+
+ mention (b);
+ }
+
+ if (sals.nelts > 1)
+ {
+ printf_unfiltered ("Multiple breakpoints were set.\n");
+ printf_unfiltered ("Use the \"delete\" command to delete unwanted breakpoints.\n");
+ }
+ free ((PTR)sals.sals);
+}
+
+#if 0
+/* This creates a temporary internal breakpoint
+ just to placate infrun */
+static struct breakpoint *
+create_temp_exception_breakpoint (pc)
+ CORE_ADDR pc;
+{
+ struct symtab_and_line sal;
+ struct breakpoint *b;
+
+ INIT_SAL(&sal);
+ sal.pc = pc;
+ sal.symtab = NULL;
+ sal.line = 0;
+
+ b = set_raw_breakpoint (sal);
+ if (!b)
+ error ("Internal error -- couldn't set temp exception breakpoint");
+
+ b->type = bp_breakpoint;
+ b->disposition = del;
+ b->enable = enabled;
+ b->silent = 1;
+ b->number = internal_breakpoint_number--;
+ return b;
+}
+#endif
+
+static void
+catch_command_1 (arg, tempflag, from_tty)
+ char *arg;
+ int tempflag;
+ int from_tty;
+{
+
+ /* The first argument may be an event name, such as "start" or "load".
+ If so, then handle it as such. If it doesn't match an event name,
+ then attempt to interpret it as an exception name. (This latter is
+ the v4.16-and-earlier GDB meaning of the "catch" command.)
+
+ First, try to find the bounds of what might be an event name. */
+ char * arg1_start = arg;
+ char * arg1_end;
+ int arg1_length;
+
+ if (arg1_start == NULL)
+ {
+ /* Old behaviour was to use pre-v-4.16 syntax */
+ /* catch_throw_command_1 (arg1_start, tempflag, from_tty); */
+ /* return; */
+ /* Now, this is not allowed */
+ error ("Catch requires an event name.");
+
+ }
+ arg1_end = ep_find_event_name_end (arg1_start);
+ if (arg1_end == NULL)
+ error ("catch requires an event");
+ arg1_length = arg1_end + 1 - arg1_start;
+
+ /* Try to match what we found against known event names. */
+ if (strncmp (arg1_start, "signal", arg1_length) == 0)
+ {
+ error ("Catch of signal not yet implemented");
+ }
+ else if (strncmp (arg1_start, "catch", arg1_length) == 0)
+ {
+ catch_exception_command_1 (EX_EVENT_CATCH, arg1_end+1, tempflag, from_tty);
+ }
+ else if (strncmp (arg1_start, "throw", arg1_length) == 0)
+ {
+ catch_exception_command_1 (EX_EVENT_THROW, arg1_end+1, tempflag, from_tty);
+ }
+ else if (strncmp (arg1_start, "thread_start", arg1_length) == 0)
+ {
+ error ("Catch of thread_start not yet implemented");
+ }
+ else if (strncmp (arg1_start, "thread_exit", arg1_length) == 0)
+ {
+ error ("Catch of thread_exit not yet implemented");
+ }
+ else if (strncmp (arg1_start, "thread_join", arg1_length) == 0)
+ {
+ error ("Catch of thread_join not yet implemented");
+ }
+ else if (strncmp (arg1_start, "start", arg1_length) == 0)
+ {
+ error ("Catch of start not yet implemented");
+ }
+ else if (strncmp (arg1_start, "exit", arg1_length) == 0)
+ {
+ error ("Catch of exit not yet implemented");
+ }
+ else if (strncmp (arg1_start, "fork", arg1_length) == 0)
+ {
+#if defined(CHILD_INSERT_FORK_CATCHPOINT)
+ catch_fork_command_1 (catch_fork, arg1_end+1, tempflag, from_tty);
+#else
+ error ("Catch of fork not yet implemented");
+#endif
+ }
+ else if (strncmp (arg1_start, "vfork", arg1_length) == 0)
+ {
+#if defined(CHILD_INSERT_VFORK_CATCHPOINT)
+ catch_fork_command_1 (catch_vfork, arg1_end+1, tempflag, from_tty);
+#else
+ error ("Catch of vfork not yet implemented");
+#endif
+ }
+ else if (strncmp (arg1_start, "exec", arg1_length) == 0)
+ {
+#if defined(CHILD_INSERT_EXEC_CATCHPOINT)
+ catch_exec_command_1 (arg1_end+1, tempflag, from_tty);
+#else
+ error ("Catch of exec not yet implemented");
+#endif
+ }
+ else if (strncmp (arg1_start, "load", arg1_length) == 0)
+ {
+#if defined(SOLIB_ADD)
+ catch_load_command_1 (arg1_end+1, tempflag, from_tty);
+#else
+ error ("Catch of load not implemented");
+#endif
+ }
+ else if (strncmp (arg1_start, "unload", arg1_length) == 0)
+ {
+#if defined(SOLIB_ADD)
+ catch_unload_command_1 (arg1_end+1, tempflag, from_tty);
+#else
+ error ("Catch of load not implemented");
+#endif
+ }
+ else if (strncmp (arg1_start, "stop", arg1_length) == 0)
+ {
+ error ("Catch of stop not yet implemented");
+ }
+
+ /* This doesn't appear to be an event name */
+
+ else
+ {
+ /* Pre-v.4.16 behaviour was to treat the argument
+ as the name of an exception */
+ /* catch_throw_command_1 (arg1_start, tempflag, from_tty); */
+ /* Now this is not allowed */
+ error ("Unknown event kind specified for catch");
+
+ }
+}
+
+/* Used by the gui, could be made a worker for other things. */
+
+struct breakpoint *
+set_breakpoint_sal (sal)
+ struct symtab_and_line sal;
+{
+ struct breakpoint *b;
+ b = set_raw_breakpoint (sal);
+ set_breakpoint_count (breakpoint_count + 1);
+ b->number = breakpoint_count;
+ b->type = bp_breakpoint;
+ b->cond = 0;
+ b->thread = -1;
+ return b;
+}
+
+#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
+tcatch_command (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ catch_command_1 (arg, 1, from_tty);
+}
+
+
+static void
+clear_command (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ register struct breakpoint *b, *b1;
+ int default_match;
+ struct symtabs_and_lines sals;
+ struct symtab_and_line sal;
+ register struct breakpoint *found;
+ int i;
+
+ if (arg)
+ {
+ sals = decode_line_spec (arg, 1);
+ default_match = 0;
+ }
+ else
+ {
+ sals.sals = (struct symtab_and_line *)
+ xmalloc (sizeof (struct symtab_and_line));
+ INIT_SAL (&sal); /* initialize to zeroes */
+ sal.line = default_breakpoint_line;
+ sal.symtab = default_breakpoint_symtab;
+ sal.pc = default_breakpoint_address;
+ if (sal.symtab == 0)
+ error ("No source file specified.");
+
+ sals.sals[0] = sal;
+ sals.nelts = 1;
+
+ default_match = 1;
+ }
+
+ /* For each line spec given, delete bps which correspond
+ to it. We do this in two loops: the first loop looks at
+ the initial bp(s) in the chain which should be deleted,
+ the second goes down the rest of the chain looking ahead
+ one so it can take those bps off the chain without messing
+ up the chain. */
+
+
+ for (i = 0; i < sals.nelts; i++)
+ {
+ /* If exact pc given, clear bpts at that pc.
+ If line given (pc == 0), clear all bpts on specified line.
+ If defaulting, clear all bpts on default line
+ or at default pc.
+
+ defaulting sal.pc != 0 tests to do
+
+ 0 1 pc
+ 1 1 pc _and_ line
+ 0 0 line
+ 1 0 <can't happen> */
+
+ sal = sals.sals[i];
+ found = (struct breakpoint *) 0;
+
+
+ while (breakpoint_chain
+ /* Why don't we check here that this is not
+ a watchpoint, etc., as we do below?
+ I can't make it fail, but don't know
+ what's stopping the failure: a watchpoint
+ of the same address as "sal.pc" should
+ wind up being deleted. */
+
+ && ( ((sal.pc && (breakpoint_chain->address == sal.pc)) &&
+ (overlay_debugging == 0 ||
+ breakpoint_chain->section == sal.section))
+ || ((default_match || (0 == 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_none
+ && b->next->type != bp_watchpoint
+ && b->next->type != bp_hardware_watchpoint
+ && b->next->type != bp_read_watchpoint
+ && b->next->type != bp_access_watchpoint
+ && ( ((sal.pc && (b->next->address == sal.pc)) &&
+ (overlay_debugging == 0 ||
+ b->next->section == sal.section))
+ || ((default_match || (0 == 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_unfiltered ("Deleted breakpoint%s ", found->next ? "s" : "");
+ breakpoints_changed ();
+ while (found)
+ {
+ if (from_tty) printf_unfiltered ("%d ", found->number);
+ b1 = found->next;
+ delete_breakpoint (found);
+ found = b1;
+ }
+ if (from_tty) putchar_unfiltered ('\n');
+ }
+ free ((PTR)sals.sals);
+}
+
+/* Delete breakpoint in BS if they are `delete' breakpoints and
+ all breakpoints that are marked for deletion, whether hit or not.
+ This is called after any breakpoint is hit, or after errors. */
+
+void
+breakpoint_auto_delete (bs)
+ bpstat bs;
+{
+ struct breakpoint *b, *temp;
+
+ for (; bs; bs = bs->next)
+ if (bs->breakpoint_at && bs->breakpoint_at->disposition == del
+ && bs->stop)
+ delete_breakpoint (bs->breakpoint_at);
+
+ ALL_BREAKPOINTS_SAFE (b, temp)
+ {
+ if (b->disposition == del_at_next_stop)
+ delete_breakpoint (b);
+ }
+}
+
+/* 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 == NULL)
+ error ("Internal error (attempted to delete a NULL breakpoint)");
+
+
+ /* Has this bp already been deleted? This can happen because multiple
+ lists can hold pointers to bp's. bpstat lists are especial culprits.
+
+ One example of this happening is a watchpoint's scope bp. When the
+ scope bp triggers, we notice that the watchpoint is out of scope, and
+ delete it. We also delete its scope bp. But the scope bp is marked
+ "auto-deleting", and is already on a bpstat. That bpstat is then
+ checked for auto-deleting bp's, which are deleted.
+
+ A real solution to this problem might involve reference counts in bp's,
+ and/or giving them pointers back to their referencing bpstat's, and
+ teaching delete_breakpoint to only free a bp's storage when no more
+ references were extent. A cheaper bandaid was chosen. */
+ if (bpt->type == bp_none)
+ return;
+
+ if (delete_breakpoint_hook)
+ delete_breakpoint_hook (bpt);
+
+ if (bpt->inserted)
+ remove_breakpoint (bpt, mark_uninserted);
+
+ if (breakpoint_chain == bpt)
+ breakpoint_chain = bpt->next;
+
+ /* If we have callback-style exception catchpoints, don't go through
+ the adjustments to the C++ runtime library etc. if the inferior
+ isn't actually running. target_enable_exception_callback for a
+ null target ops vector gives an undesirable error message, so we
+ check here and avoid it. Since currently (1997-09-17) only HP-UX aCC's
+ exceptions are supported in this way, it's OK for now. FIXME */
+ if (ep_is_exception_catchpoint (bpt) && target_has_execution)
+ {
+ static char message1[] = "Error in deleting catchpoint %d:\n";
+ static char message[sizeof (message1) + 30];
+ args_for_catchpoint_enable args;
+
+ sprintf (message, message1, bpt->number); /* Format possible error msg */
+ args.kind = bpt->type == bp_catch_catch ? EX_EVENT_CATCH : EX_EVENT_THROW;
+ args.enable = 0;
+ catch_errors (cover_target_enable_exception_callback, &args,
+ message, RETURN_MASK_ALL);
+ }
+
+
+ ALL_BREAKPOINTS (b)
+ if (b->next == bpt)
+ {
+ b->next = bpt->next;
+ break;
+ }
+
+ /* Before turning off the visuals for the bp, check to see that
+ there are no other bps at the same address. */
+ if (tui_version)
+ {
+ int clearIt;
+
+ ALL_BREAKPOINTS (b)
+ {
+ clearIt = (b->address != bpt->address);
+ if (!clearIt)
+ break;
+ }
+
+ if (clearIt)
+ {
+ TUIDO(((TuiOpaqueFuncPtr)tui_vAllSetHasBreakAt, bpt, 0));
+ TUIDO(((TuiOpaqueFuncPtr)tuiUpdateAllExecInfos));
+ }
+ }
+
+ check_duplicates (bpt->address, bpt->section);
+ /* If this breakpoint was inserted, and there is another breakpoint
+ at the same address, we need to insert the other breakpoint. */
+ if (bpt->inserted
+ && bpt->type != bp_hardware_watchpoint
+ && bpt->type != bp_read_watchpoint
+ && bpt->type != bp_access_watchpoint
+ && bpt->type != bp_catch_fork
+ && bpt->type != bp_catch_vfork
+ && bpt->type != bp_catch_exec)
+ {
+ ALL_BREAKPOINTS (b)
+ if (b->address == bpt->address
+ && b->section == bpt->section
+ && !b->duplicate
+ && b->enable != disabled
+ && b->enable != shlib_disabled
+ && b->enable != call_disabled)
+ {
+ int val;
+ val = target_insert_breakpoint (b->address, b->shadow_contents);
+ if (val != 0)
+ {
+ target_terminal_ours_for_output ();
+ fprintf_unfiltered (gdb_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 != NULL)
+ free (bpt->exp);
+ if (bpt->exp_string != NULL)
+ free (bpt->exp_string);
+ if (bpt->val != NULL)
+ value_free (bpt->val);
+ if (bpt->source_file != NULL)
+ free (bpt->source_file);
+ if (bpt->dll_pathname != NULL)
+ free (bpt->dll_pathname);
+ if (bpt->triggered_dll_pathname != NULL)
+ free (bpt->triggered_dll_pathname);
+ if (bpt->exec_pathname != NULL)
+ free (bpt->exec_pathname);
+
+ /* 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;
+
+ /* we'd call bpstat_clear_actions, but that free's stuff and due
+ to the multiple pointers pointing to one item with no
+ reference counts found anywhere through out the bpstat's (how
+ do you spell fragile?), we don't want to free things twice --
+ better a memory leak than a corrupt malloc pool! */
+ bs->commands = NULL;
+ bs->old_val = NULL;
+ }
+ /* On the chance that someone will soon try again to delete this same
+ bp, we mark it as deleted before freeing its storage. */
+ bpt->type = bp_none;
+
+ free ((PTR)bpt);
+}
+
+void
+delete_command (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ struct breakpoint *b, *temp;
+
+ if (arg == 0)
+ {
+ int breaks_to_delete = 0;
+
+ /* Delete all breakpoints if no argument.
+ Do not delete internal or call-dummy breakpoints, these
+ have to be deleted with an explicit breakpoint number argument. */
+ ALL_BREAKPOINTS (b)
+ {
+ if (b->type != bp_call_dummy &&
+ b->type != bp_shlib_event &&
+ b->number >= 0)
+ breaks_to_delete = 1;
+ }
+
+ /* Ask user only if there are some breakpoints to delete. */
+ if (!from_tty
+ || (breaks_to_delete && query ("Delete all breakpoints? ")))
+ {
+ ALL_BREAKPOINTS_SAFE (b, temp)
+ {
+ if (b->type != bp_call_dummy &&
+ b->type != bp_shlib_event &&
+ b->number >= 0)
+ delete_breakpoint (b);
+ }
+ }
+ }
+ 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)
+ PTR bint;
+{
+ struct breakpoint *b = (struct breakpoint *)bint; /* get past catch_errs */
+ struct value *mark;
+ int i;
+ struct symtabs_and_lines sals;
+ char *s;
+ enum enable save_enable;
+
+ switch (b->type)
+ {
+ case bp_none:
+ warning ("attempted to reset apparently deleted breakpoint #%d?\n", b->number);
+ return 0;
+ case bp_breakpoint:
+ case bp_hardware_breakpoint:
+ case bp_catch_load:
+ case bp_catch_unload:
+ 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;
+
+ set_language (b->language);
+ input_radix = b->input_radix;
+ 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;
+
+ /* Used to check for duplicates here, but that can
+ cause trouble, as it doesn't check for disable
+ breakpoints. */
+
+ mention (b);
+
+ /* Might be better to do this just once per breakpoint_re_set,
+ rather than once for every breakpoint. */
+ breakpoints_changed ();
+ }
+ b->section = sals.sals[i].section;
+ b->enable = save_enable; /* Restore it, this worked. */
+
+
+ /* Now that this is re-enabled, check_duplicates
+ can be used. */
+ check_duplicates (b->address, b->section);
+
+ }
+ free ((PTR)sals.sals);
+ break;
+
+ case bp_watchpoint:
+ case bp_hardware_watchpoint:
+ case bp_read_watchpoint:
+ case bp_access_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. */
+ if (b->exp)
+ free ((PTR)b->exp);
+ b->exp = parse_expression (b->exp_string);
+ b->exp_valid_block = innermost_block;
+ mark = value_mark ();
+ if (b->val)
+ value_free (b->val);
+ 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;
+ if (b->cond)
+ free ((PTR)b->cond);
+ b->cond = parse_exp_1 (&s, (struct block *)0, 0);
+ }
+ if (b->enable == enabled)
+ mention (b);
+ value_free_to_mark (mark);
+ break;
+ case bp_catch_catch:
+ case bp_catch_throw:
+ break;
+ /* We needn't really do anything to reset these, since the mask
+ that requests them is unaffected by e.g., new libraries being
+ loaded. */
+ case bp_catch_fork:
+ case bp_catch_vfork:
+ case bp_catch_exec:
+ break;
+
+ default:
+ printf_filtered ("Deleting unknown breakpoint type %d\n", b->type);
+ /* fall through */
+ /* Delete longjmp breakpoints, they will be reset later by
+ breakpoint_re_set. */
+ case bp_longjmp:
+ case bp_longjmp_resume:
+ delete_breakpoint (b);
+ break;
+
+ /* This breakpoint is special, it's set up when the inferior
+ starts and we really don't want to touch it. */
+ case bp_shlib_event:
+
+ /* Keep temporary breakpoints, which can be encountered when we step
+ over a dlopen call and SOLIB_ADD is resetting the breakpoints.
+ Otherwise these should have been blown away via the cleanup chain
+ or by breakpoint_init_inferior when we rerun the executable. */
+ case bp_until:
+ case bp_finish:
+ case bp_watchpoint_scope:
+ case bp_call_dummy:
+ case bp_step_resume:
+ break;
+ }
+
+ return 0;
+}
+
+/* Re-set all breakpoints after symbols have been re-loaded. */
+void
+breakpoint_re_set ()
+{
+ struct breakpoint *b, *temp;
+ enum language save_language;
+ int save_input_radix;
+ static char message1[] = "Error in re-setting breakpoint %d:\n";
+ char message[sizeof (message1) + 30 /* slop */];
+
+ save_language = current_language->la_language;
+ save_input_radix = input_radix;
+ ALL_BREAKPOINTS_SAFE (b, temp)
+ {
+ sprintf (message, message1, b->number); /* Format possible error msg */
+ catch_errors (breakpoint_re_set_one, b, message, RETURN_MASK_ALL);
+ }
+ set_language (save_language);
+ input_radix = save_input_radix;
+
+#ifdef GET_LONGJMP_TARGET
+ create_longjmp_breakpoint ("longjmp");
+ create_longjmp_breakpoint ("_longjmp");
+ create_longjmp_breakpoint ("siglongjmp");
+ create_longjmp_breakpoint ("_siglongjmp");
+ create_longjmp_breakpoint (NULL);
+#endif
+
+#if 0
+ /* Took this out (temporarily 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). */
+
+/* Reset the thread number of this breakpoint:
+
+ - If the breakpoint is for all threads, leave it as-is.
+ - Else, reset it to the current thread for inferior_pid. */
+void
+breakpoint_re_set_thread (b)
+ struct breakpoint * b;
+{
+ if (b->thread != -1)
+ {
+ if (in_thread_list (inferior_pid))
+ b->thread = pid_to_thread_id (inferior_pid);
+ }
+}
+
+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);
+ breakpoints_changed ();
+ 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");
+ breakpoints_changed ();
+}
+
+/* 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)
+ {
+ struct breakpoint *related_breakpoint = b->related_breakpoint;
+ function (b);
+ if (related_breakpoint)
+ function (related_breakpoint);
+ goto win;
+ }
+ printf_unfiltered ("No breakpoint number %d.\n", num);
+ win:
+ p = p1;
+ }
+}
+
+void
+disable_breakpoint (bpt)
+ struct breakpoint *bpt;
+{
+ /* Never disable a watchpoint scope breakpoint; we want to
+ hit them when we leave scope so we can delete both the
+ watchpoint and its scope breakpoint at that time. */
+ if (bpt->type == bp_watchpoint_scope)
+ return;
+
+ bpt->enable = disabled;
+
+ check_duplicates (bpt->address, bpt->section);
+
+ if (modify_breakpoint_hook)
+ modify_breakpoint_hook (bpt);
+}
+
+/* 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_none:
+ warning ("attempted to disable apparently deleted breakpoint #%d?\n", bpt->number);
+ continue;
+ case bp_breakpoint:
+ case bp_catch_load:
+ case bp_catch_unload:
+ case bp_catch_fork:
+ case bp_catch_vfork:
+ case bp_catch_exec:
+ case bp_catch_catch:
+ case bp_catch_throw:
+ case bp_hardware_breakpoint:
+ case bp_watchpoint:
+ case bp_hardware_watchpoint:
+ case bp_read_watchpoint:
+ case bp_access_watchpoint:
+ disable_breakpoint (bpt);
+ default:
+ continue;
+ }
+ else
+ map_breakpoint_numbers (args, disable_breakpoint);
+}
+
+static void
+do_enable_breakpoint (bpt, disposition)
+ struct breakpoint *bpt;
+ enum bpdisp disposition;
+{
+ struct frame_info *save_selected_frame = NULL;
+ int save_selected_frame_level = -1;
+ int target_resources_ok, other_type_used;
+ struct value *mark;
+
+ if (bpt->type == bp_hardware_breakpoint)
+ {
+ int i;
+ i = hw_breakpoint_used_count();
+ target_resources_ok = TARGET_CAN_USE_HARDWARE_WATCHPOINT(
+ bp_hardware_breakpoint, i+1, 0);
+ if (target_resources_ok == 0)
+ error ("No hardware breakpoint support in the target.");
+ else if (target_resources_ok < 0)
+ error ("Hardware breakpoints used exceeds limit.");
+ }
+
+ bpt->enable = enabled;
+ bpt->disposition = disposition;
+ check_duplicates (bpt->address, bpt->section);
+ breakpoints_changed ();
+
+ if (bpt->type == bp_watchpoint || bpt->type == bp_hardware_watchpoint ||
+ bpt->type == bp_read_watchpoint || bpt->type == bp_access_watchpoint)
+ {
+ if (bpt->exp_valid_block != NULL)
+ {
+ struct frame_info *fr =
+
+ /* Ensure that we have the current frame. Else, this
+ next query may pessimistically be answered as, "No,
+ not within current scope". */
+ get_current_frame ();
+ fr = find_frame_addr_in_frame_chain (bpt->watchpoint_frame);
+ 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);
+ mark = value_mark ();
+ bpt->val = evaluate_expression (bpt->exp);
+ release_value (bpt->val);
+ if (VALUE_LAZY (bpt->val))
+ value_fetch_lazy (bpt->val);
+
+ if (bpt->type == bp_hardware_watchpoint ||
+ bpt->type == bp_read_watchpoint ||
+ bpt->type == bp_access_watchpoint)
+ {
+ int i = hw_watchpoint_used_count (bpt->type, &other_type_used);
+ int mem_cnt = can_use_hardware_watchpoint (bpt->val);
+
+ /* Hack around 'unused var' error for some targets here */
+ (void) mem_cnt, i;
+ target_resources_ok = TARGET_CAN_USE_HARDWARE_WATCHPOINT(
+ bpt->type, i + mem_cnt, other_type_used);
+ /* we can consider of type is bp_hardware_watchpoint, convert to
+ bp_watchpoint in the following condition */
+ if (target_resources_ok < 0)
+ {
+ printf_filtered("\
+Cannot enable watchpoint %d because target watch resources\n\
+have been allocated for other watchpoints.\n", bpt->number);
+ bpt->enable = disabled;
+ value_free_to_mark (mark);
+ return;
+ }
+ }
+
+ if (save_selected_frame_level >= 0)
+ select_and_print_frame (save_selected_frame, save_selected_frame_level);
+ value_free_to_mark (mark);
+ }
+ if (modify_breakpoint_hook)
+ modify_breakpoint_hook (bpt);
+}
+
+void
+enable_breakpoint (bpt)
+ struct breakpoint *bpt;
+{
+ do_enable_breakpoint (bpt, bpt->disposition);
+}
+
+/* The enable command enables the specified breakpoints (or all defined
+ breakpoints) so they once again become (or continue to be) effective
+ in stopping the inferior. */
+
+/* ARGSUSED */
+static void
+enable_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ register struct breakpoint *bpt;
+ if (args == 0)
+ ALL_BREAKPOINTS (bpt)
+ switch (bpt->type)
+ {
+ case bp_none:
+ warning ("attempted to enable apparently deleted breakpoint #%d?\n", bpt->number);
+ continue;
+ case bp_breakpoint:
+ case bp_catch_load:
+ case bp_catch_unload:
+ case bp_catch_fork:
+ case bp_catch_vfork:
+ case bp_catch_exec:
+ case bp_catch_catch:
+ case bp_catch_throw:
+ case bp_hardware_breakpoint:
+ case bp_watchpoint:
+ case bp_hardware_watchpoint:
+ case bp_read_watchpoint:
+ case bp_access_watchpoint:
+ enable_breakpoint (bpt);
+ default:
+ continue;
+ }
+ else
+ map_breakpoint_numbers (args, enable_breakpoint);
+}
+
+static void
+enable_once_breakpoint (bpt)
+ struct breakpoint *bpt;
+{
+ do_enable_breakpoint (bpt, disable);
+}
+
+/* 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;
+{
+ do_enable_breakpoint (bpt, del);
+}
+
+/* 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 ()
+{
+ struct cmd_list_element *c;
+
+ 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.\n\
+Usage is `ignore N COUNT'.");
+ if (xdb_commands)
+ add_com_alias("bc", "ignore", class_breakpoint, 1);
+
+ 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\
+Usage is `condition N COND', where N is an integer and COND is an\n\
+expression to be evaluated whenever 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 temporary,\n\
+so it will be deleted when hit. Equivalent to \"break\" followed\n\
+by using \"enable delete\" on the breakpoint number.");
+ add_com("txbreak", class_breakpoint, tbreak_at_finish_command,
+ "Set temporary breakpoint at procedure exit. Either there should\n\
+be no argument or the argument must be a depth.\n");
+
+ add_com ("hbreak", class_breakpoint, hbreak_command,
+ "Set a hardware assisted breakpoint. Args like \"break\" command.\n\
+Like \"break\" except the breakpoint requires hardware support,\n\
+some target hardware may not have this support.");
+
+ add_com ("thbreak", class_breakpoint, thbreak_command,
+ "Set a temporary hardware assisted breakpoint. Args like \"break\" command.\n\
+Like \"hbreak\" except the breakpoint is only temporary,\n\
+so it will be deleted when hit.");
+
+ 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);
+ if (xdb_commands)
+ add_com("ab", 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.");
+
+ add_com_alias ("en", "enable", class_breakpoint, 1);
+
+ 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.",
+ &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.",
+ &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);
+ if (xdb_commands)
+ add_com("sb", 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.");
+
+ 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);
+ if (xdb_commands)
+ add_com ("db", class_breakpoint, delete_command,
+ "Delete some breakpoints.\n\
+Arguments are breakpoint numbers with spaces in between.\n\
+To delete all breakpoints, give no argument.\n");
+
+ 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,
+ concat ("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.", NULL));
+
+ add_com ("break", class_breakpoint, break_command,
+ concat ("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.", NULL));
+ 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_com("xbreak", class_breakpoint, break_at_finish_command,
+ concat("Set breakpoint at procedure exit. \n\
+Argument may be function name, or \"*\" and an address.\n\
+If function is specified, break at end of code for that function.\n\
+If an address is specified, break at the end of the function that contains \n\
+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.", NULL));
+ add_com_alias ("xb", "xbreak", class_breakpoint, 1);
+ add_com_alias ("xbr", "xbreak", class_breakpoint, 1);
+ add_com_alias ("xbre", "xbreak", class_breakpoint, 1);
+ add_com_alias ("xbrea", "xbreak", class_breakpoint, 1);
+
+ if (xdb_commands)
+ {
+ add_com_alias ("ba", "break", class_breakpoint, 1);
+ add_com_alias ("bu", "ubreak", class_breakpoint, 1);
+ add_com ("bx", class_breakpoint, break_at_finish_at_depth_command,
+ "Set breakpoint at procedure exit. Either there should\n\
+be no argument or the argument must be a depth.\n");
+ }
+
+ if (dbx_commands)
+ {
+ add_abbrev_prefix_cmd("stop", class_breakpoint, stop_command,
+ "Break in function/address or break at a line in the current file.",
+ &stoplist, "stop ", 1, &cmdlist);
+ add_cmd("in", class_breakpoint, stopin_command,
+ "Break in function or address.\n", &stoplist);
+ add_cmd("at", class_breakpoint, stopat_command,
+ "Break at a line in the current file.\n", &stoplist);
+ add_com("status", class_info, breakpoints_info,
+ concat ("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.", NULL));
+ }
+
+ add_info ("breakpoints", breakpoints_info,
+ concat ("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.", NULL));
+
+ if (xdb_commands)
+ add_com("lb", class_breakpoint, breakpoints_info,
+ concat ("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.", NULL));
+
+#if MAINTENANCE_CMDS
+
+ add_cmd ("breakpoints", class_maintenance, maintenance_info_breakpoints,
+ concat ("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.", NULL),
+ &maintenanceinfolist);
+
+#endif /* MAINTENANCE_CMDS */
+
+ add_com ("catch", class_breakpoint, catch_command,
+ "Set catchpoints to catch events.\n\
+Raised signals may be caught:\n\
+\tcatch signal - all signals\n\
+\tcatch signal <signame> - a particular signal\n\
+Raised exceptions may be caught:\n\
+\tcatch throw - all exceptions, when thrown\n\
+\tcatch throw <exceptname> - a particular exception, when thrown\n\
+\tcatch catch - all exceptions, when caught\n\
+\tcatch catch <exceptname> - a particular exception, when caught\n\
+Thread or process events may be caught:\n\
+\tcatch thread_start - any threads, just after creation\n\
+\tcatch thread_exit - any threads, just before expiration\n\
+\tcatch thread_join - any threads, just after joins\n\
+Process events may be caught:\n\
+\tcatch start - any processes, just after creation\n\
+\tcatch exit - any processes, just before expiration\n\
+\tcatch fork - calls to fork()\n\
+\tcatch vfork - calls to vfork()\n\
+\tcatch exec - calls to exec()\n\
+Dynamically-linked library events may be caught:\n\
+\tcatch load - loads of any library\n\
+\tcatch load <libname> - loads of a particular library\n\
+\tcatch unload - unloads of any library\n\
+\tcatch unload <libname> - unloads of a particular library\n\
+The act of your program's execution stopping may also be caught:\n\
+\tcatch stop\n\n\
+C++ exceptions may be caught:\n\
+\tcatch throw - all exceptions, when thrown\n\
+\tcatch catch - all exceptions, when caught\n\
+\n\
+Do \"help set follow-fork-mode\" for info on debugging your program\n\
+after a fork or vfork is caught.\n\n\
+Do \"help breakpoints\" for info on other commands dealing with breakpoints.");
+
+ add_com ("tcatch", class_breakpoint, tcatch_command,
+ "Set temporary catchpoints to catch events.\n\
+Args like \"catch\" command.\n\
+Like \"catch\" except the catchpoint is only temporary,\n\
+so it will be deleted when hit. Equivalent to \"catch\" followed\n\
+by using \"enable delete\" on the catchpoint number.");
+
+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_com ("rwatch", class_breakpoint, rwatch_command,
+ "Set a read watchpoint for an expression.\n\
+A watchpoint stops execution of your program whenever the value of\n\
+an expression is read.");
+
+ add_com ("awatch", class_breakpoint, awatch_command,
+ "Set a watchpoint for an expression.\n\
+A watchpoint stops execution of your program whenever the value of\n\
+an expression is either read or written.");
+
+ add_info ("watchpoints", breakpoints_info,
+ "Synonym for ``info breakpoints''.");
+
+
+ c = add_set_cmd ("can-use-hw-watchpoints", class_support, var_zinteger,
+ (char *) &can_use_hw_watchpoints,
+ "Set debugger's willingness to use watchpoint hardware.\n\
+If zero, gdb will not use hardware for new watchpoints, even if\n\
+such is available. (However, any hardware watchpoints that were\n\
+created before setting this to nonzero, will continue to use watchpoint\n\
+hardware.)",
+ &setlist);
+ add_show_from_set (c, &showlist);
+
+ can_use_hw_watchpoints = 1;
+}
diff --git a/gdb/breakpoint.h b/gdb/breakpoint.h
new file mode 100644
index 00000000000..e2febaccca3
--- /dev/null
+++ b/gdb/breakpoint.h
@@ -0,0 +1,604 @@
+/* Data structures associated with breakpoints in GDB.
+ Copyright (C) 1992, 93, 94, 95, 96, 98, 1999 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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_none = 0, /* Eventpoint has been deleted. */
+ bp_breakpoint, /* Normal breakpoint */
+ bp_hardware_breakpoint, /* Hardware assisted breakpoint */
+ bp_until, /* used by until command */
+ bp_finish, /* used by finish command */
+ bp_watchpoint, /* Watchpoint */
+ bp_hardware_watchpoint, /* Hardware assisted watchpoint */
+ bp_read_watchpoint, /* read watchpoint, (hardware assisted) */
+ bp_access_watchpoint, /* access watchpoint, (hardware assisted) */
+ 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,
+
+ /* Used by wait_for_inferior for stepping over signal handlers. */
+ bp_through_sigtramp,
+
+ /* Used to detect when a watchpoint expression has gone out of
+ scope. These breakpoints are usually not visible to the user.
+
+ This breakpoint has some interesting properties:
+
+ 1) There's always a 1:1 mapping between watchpoints
+ on local variables and watchpoint_scope breakpoints.
+
+ 2) It automatically deletes itself and the watchpoint it's
+ associated with when hit.
+
+ 3) It can never be disabled. */
+ bp_watchpoint_scope,
+
+ /* 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,
+
+ /* Some dynamic linkers (HP, maybe Solaris) can arrange for special
+ code in the inferior to run when significant events occur in the
+ dynamic linker (for example a library is loaded or unloaded).
+
+ By placing a breakpoint in this magic code GDB will get control
+ when these significant events occur. GDB can then re-examine
+ the dynamic linker's data structures to discover any newly loaded
+ dynamic libraries. */
+ bp_shlib_event,
+
+ /* These breakpoints are used to implement the "catch load" command
+ on platforms whose dynamic linkers support such functionality. */
+ bp_catch_load,
+
+ /* These breakpoints are used to implement the "catch unload" command
+ on platforms whose dynamic linkers support such functionality. */
+ bp_catch_unload,
+
+ /* These are not really breakpoints, but are catchpoints that
+ implement the "catch fork", "catch vfork" and "catch exec" commands
+ on platforms whose kernel support such functionality. (I.e.,
+ kernels which can raise an event when a fork or exec occurs, as
+ opposed to the debugger setting breakpoints on functions named
+ "fork" or "exec".) */
+ bp_catch_fork,
+ bp_catch_vfork,
+ bp_catch_exec,
+
+ /* These are catchpoints to implement "catch catch" and "catch throw"
+ commands for C++ exception handling. */
+ bp_catch_catch,
+ bp_catch_throw
+
+};
+
+/* States of enablement of breakpoint. */
+
+enum enable {
+ disabled, /* The eventpoint is inactive, and cannot trigger. */
+ enabled, /* The eventpoint is active, and can trigger. */
+ shlib_disabled, /* The eventpoint's address is within an unloaded solib.
+ The eventpoint will be automatically enabled & reset
+ when that solib is loaded. */
+ call_disabled /* The eventpoint has been disabled while a call into
+ the inferior is "in flight", because some eventpoints
+ interfere with the implementation of a call on some
+ targets. The eventpoint will be automatically enabled
+ & reset when the call "lands" (either completes, or
+ stops at another eventpoint). */
+};
+
+
+/* Disposition of breakpoint. Ie: what to do after hitting it. */
+
+enum bpdisp {
+ del, /* Delete it */
+ del_at_next_stop, /* Delete at next stop, whether hit or not */
+ 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. */
+ CORE_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;
+ /* Language we used to set the breakpoint. */
+ enum language language;
+ /* Input radix we used to set the breakpoint. */
+ int input_radix;
+ /* 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_ptr val;
+
+ /* Holds the value chain for a hardware watchpoint expression. */
+ value_ptr val_chain;
+
+ /* Holds the address of the related watchpoint_scope breakpoint
+ when using watchpoints on local variables (might the concept
+ of a related breakpoint be useful elsewhere, if not just call
+ it the watchpoint_scope breakpoint or something like that. FIXME). */
+ struct breakpoint *related_breakpoint;
+
+ /* Holds the frame address which identifies the frame this watchpoint
+ should be evaluated in, or NULL if the watchpoint should be evaluated
+ on the outermost frame. */
+ CORE_ADDR watchpoint_frame;
+
+ /* Thread number for thread-specific breakpoint, or -1 if don't care */
+ int thread;
+
+ /* Count of the number of times this breakpoint was taken, dumped
+ with the info, but not used for anything else. Useful for
+ seeing how many times you hit a break prior to the program
+ aborting, so you can back up to just before the abort. */
+ int hit_count;
+
+ /* Filename of a dynamically-linked library (dll), used for bp_catch_load
+ and bp_catch_unload (malloc'd), or NULL if any library is significant. */
+ char * dll_pathname;
+
+ /* Filename of a dll whose state change (e.g., load or unload)
+ triggered this catchpoint. This field is only vaid immediately
+ after this catchpoint has triggered. */
+ char * triggered_dll_pathname;
+
+ /* Process id of a child process whose forking triggered this catchpoint.
+ This field is only vaid immediately after this catchpoint has triggered. */
+ int forked_inferior_pid;
+
+ /* Filename of a program whose exec triggered this catchpoint. This
+ field is only vaid immediately after this catchpoint has triggered. */
+ char * exec_pathname;
+
+ asection *section;
+};
+
+/* 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 bpstats *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));
+
+extern bpstat bpstat_stop_status PARAMS ((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,
+
+ /* Clear step resume breakpoint, and keep checking. */
+ BPSTAT_WHAT_STEP_RESUME,
+
+ /* Clear through_sigtramp breakpoint, muck with trap_expected, and keep
+ checking. */
+ BPSTAT_WHAT_THROUGH_SIGTRAMP,
+
+ /* Check the dynamic linker's data structures for new libraries, then
+ keep checking. */
+ BPSTAT_WHAT_CHECK_SHLIBS,
+
+ /* Check the dynamic linker's data structures for new libraries, then
+ resume out of the dynamic linker's callback, stop and print. */
+ BPSTAT_WHAT_CHECK_SHLIBS_RESUME_FROM_HOOK,
+
+ /* 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 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 *));
+
+/* Find a step_resume breakpoint associated with this bpstat.
+ (If there are multiple step_resume bp's on the list, this function
+ will arbitrarily pick one.)
+
+ It is an error to use this function if BPSTAT doesn't contain a
+ step_resume breakpoint.
+
+ See wait_for_inferior's use of this function.
+ */
+extern struct breakpoint *
+bpstat_find_step_resume_breakpoint PARAMS ((bpstat));
+
+/* 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));
+
+/* Nonzero if there are enabled hardware watchpoints. */
+extern int bpstat_have_active_hw_watchpoints 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));
+
+/* Given a bpstat that records zero or more triggered eventpoints, this
+ function returns another bpstat which contains only the catchpoints
+ on that first list, if any.
+ */
+extern void bpstat_get_triggered_catchpoints PARAMS ((bpstat, bpstat *));
+
+/* Implementation: */
+struct bpstats
+{
+ /* 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_ptr 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));
+};
+
+enum inf_context
+{
+ inf_starting,
+ inf_running,
+ inf_exited
+};
+
+
+/* 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_inserted_here_p PARAMS ((CORE_ADDR));
+
+extern int frame_in_dummy PARAMS ((struct frame_info *));
+
+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 breakpoint_re_set_thread PARAMS ((struct breakpoint *));
+
+extern int ep_is_exception_catchpoint PARAMS ((struct breakpoint *));
+
+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 ((enum inf_context));
+
+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 void tbreak_command PARAMS ((char *, int));
+
+extern int insert_breakpoints PARAMS ((void));
+
+extern int remove_breakpoints PARAMS ((void));
+
+/* This function can be used to physically insert eventpoints from the
+ specified traced inferior process, without modifying the breakpoint
+ package's state. This can be useful for those targets which support
+ following the processes of a fork() or vfork() system call, when both
+ of the resulting two processes are to be followed. */
+extern int reattach_breakpoints PARAMS ((int));
+
+/* This function can be used to update the breakpoint package's state
+ after an exec() system call has been executed.
+
+ This function causes the following:
+
+ - All eventpoints are marked "not inserted".
+ - All eventpoints with a symbolic address are reset such that
+ the symbolic address must be reevaluated before the eventpoints
+ can be reinserted.
+ - The solib breakpoints are explicitly removed from the breakpoint
+ list.
+ - A step-resume breakpoint, if any, is explicitly removed from the
+ breakpoint list.
+ - All eventpoints without a symbolic address are removed from the
+ breakpoint list. */
+extern void update_breakpoints_after_exec PARAMS ((void));
+
+/* This function can be used to physically remove hardware breakpoints
+ and watchpoints from the specified traced inferior process, without
+ modifying the breakpoint package's state. This can be useful for
+ those targets which support following the processes of a fork() or
+ vfork() system call, when one of the resulting two processes is to
+ be detached and allowed to run free.
+
+ It is an error to use this function on the process whose id is
+ inferior_pid. */
+extern int detach_breakpoints PARAMS ((int));
+
+extern void enable_longjmp_breakpoint PARAMS ((void));
+
+extern void disable_longjmp_breakpoint PARAMS ((void));
+
+extern void set_longjmp_resume_breakpoint PARAMS ((CORE_ADDR,
+ struct frame_info *));
+/* These functions respectively disable or reenable all currently
+ enabled watchpoints. When disabled, the watchpoints are marked
+ call_disabled. When reenabled, they are marked enabled.
+
+ The intended client of these functions is infcmd.c\run_stack_dummy.
+
+ The inferior must be stopped, and all breakpoints removed, when
+ these functions are used.
+
+ The need for these functions is that on some targets (e.g., HP-UX),
+ gdb is unable to unwind through the dummy frame that is pushed as
+ part of the implementation of a call command. Watchpoints can
+ cause the inferior to stop in places where this frame is visible,
+ and that can cause execution control to become very confused.
+
+ Note that if a user sets breakpoints in an interactively call
+ function, the call_disabled watchpoints will have been reenabled
+ when the first such breakpoint is reached. However, on targets
+ that are unable to unwind through the call dummy frame, watches
+ of stack-based storage may then be deleted, because gdb will
+ believe that their watched storage is out of scope. (Sigh.) */
+extern void
+disable_watchpoints_before_interactive_call_start PARAMS ((void));
+
+extern void
+enable_watchpoints_after_interactive_call_stop PARAMS ((void));
+
+
+extern void clear_breakpoint_hit_counts PARAMS ((void));
+
+/* 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));
+
+extern void disable_breakpoint PARAMS ((struct breakpoint *));
+
+extern void enable_breakpoint PARAMS ((struct breakpoint *));
+
+extern void create_solib_event_breakpoint PARAMS ((CORE_ADDR));
+
+extern void remove_solib_event_breakpoints PARAMS ((void));
+
+extern void disable_breakpoints_in_shlibs PARAMS ((int silent));
+
+extern void re_enable_breakpoints_in_shlibs PARAMS ((void));
+
+extern void create_solib_load_event_breakpoint PARAMS ((char *, int, char *, char *));
+
+extern void create_solib_unload_event_breakpoint PARAMS ((char *, int, char *, char *));
+
+extern void create_fork_event_catchpoint PARAMS ((int, char *));
+
+extern void create_vfork_event_catchpoint PARAMS ((int, char *));
+
+extern void create_exec_event_catchpoint PARAMS ((int, char *));
+
+/* This function returns TRUE if ep is a catchpoint. */
+extern int ep_is_catchpoint PARAMS ((struct breakpoint *));
+
+/* This function returns TRUE if ep is a catchpoint of a
+ shared library (aka dynamically-linked library) event,
+ such as a library load or unload. */
+extern int ep_is_shlib_catchpoint PARAMS ((struct breakpoint *));
+
+extern struct breakpoint *set_breakpoint_sal PARAMS ((struct symtab_and_line));
+
+#endif /* !defined (BREAKPOINT_H) */
diff --git a/gdb/buildsym.c b/gdb/buildsym.c
new file mode 100644
index 00000000000..24b64bead2e
--- /dev/null
+++ b/gdb/buildsym.c
@@ -0,0 +1,1130 @@
+/* Support routines for building symbol tables in GDB's internal format.
+ Copyright 1986-1999 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 "gdbtypes.h"
+#include "complaints.h"
+#include "gdb_string.h"
+
+/* Ask buildsym.h to define the vars it normally declares `extern'. */
+#define EXTERN /**/
+#include "buildsym.h" /* Our own declarations */
+#undef EXTERN
+
+/* For cleanup_undefined_types and finish_global_stabs (somewhat
+ questionable--see comment where we call them). */
+
+#include "stabsread.h"
+
+/* List of free `struct pending' structures for reuse. */
+
+static struct pending *free_pendings;
+
+/* Non-zero if symtab has line number info. This prevents an
+ otherwise empty symtab from being tossed. */
+
+static int have_line_numbers;
+
+static int compare_line_numbers (const void *ln1p, const void *ln2p);
+
+
+/* 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 block_end_complaint =
+{"block end address less than block start address in %s (patched it)", 0, 0};
+
+struct complaint anon_block_end_complaint =
+{"block end address 0x%lx less than block start address 0x%lx (patched it)", 0, 0};
+
+struct complaint innerblock_complaint =
+{"inner block not inside outer block in %s", 0, 0};
+
+struct complaint innerblock_anon_complaint =
+{"inner block (0x%lx-0x%lx) not inside outer block (0x%lx-0x%lx)", 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 (struct symbol *symbol, struct pending **listhead)
+{
+ register struct pending *link;
+
+ /* If this is an alias for another symbol, don't add it. */
+ if (symbol->ginfo.name && symbol->ginfo.name[0] == '#')
+ return;
+
+ /* 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 (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 (int foo)
+{
+ struct pending *next, *next1;
+
+ for (next = free_pendings; next; next = next1)
+ {
+ next1 = next->next;
+ free ((void *) next);
+ }
+ free_pendings = NULL;
+
+ free_pending_blocks ();
+
+ for (next = file_symbols; next != NULL; next = next1)
+ {
+ next1 = next->next;
+ free ((void *) next);
+ }
+ file_symbols = NULL;
+
+ for (next = global_symbols; next != NULL; next = next1)
+ {
+ next1 = next->next;
+ free ((void *) next);
+ }
+ global_symbols = NULL;
+}
+
+/* This function is called to discard any pending blocks. */
+
+void
+free_pending_blocks (void)
+{
+#if 0 /* Now we make the links in the
+ symbol_obstack, so don't free
+ them. */
+ struct pending_block *bnext, *bnext1;
+
+ for (bnext = pending_blocks; bnext; bnext = bnext1)
+ {
+ bnext1 = bnext->next;
+ free ((void *) bnext);
+ }
+#endif
+ pending_blocks = 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 (struct symbol *symbol, struct pending **listhead,
+ struct pending_block *old_blocks,
+ CORE_ADDR start, CORE_ADDR 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)
+ {
+ struct type *ftype = SYMBOL_TYPE (symbol);
+ SYMBOL_BLOCK_VALUE (symbol) = block;
+ BLOCK_FUNCTION (block) = symbol;
+
+ if (TYPE_NFIELDS (ftype) <= 0)
+ {
+ /* No parameter type information is recorded with the
+ function's type. Set that from the type of the
+ parameter symbols. */
+ int nparams = 0, iparams;
+ struct symbol *sym;
+ for (i = 0; i < BLOCK_NSYMS (block); i++)
+ {
+ sym = BLOCK_SYM (block, i);
+ switch (SYMBOL_CLASS (sym))
+ {
+ case LOC_ARG:
+ case LOC_REF_ARG:
+ case LOC_REGPARM:
+ case LOC_REGPARM_ADDR:
+ case LOC_BASEREG_ARG:
+ case LOC_LOCAL_ARG:
+ nparams++;
+ break;
+ case LOC_UNDEF:
+ case LOC_CONST:
+ case LOC_STATIC:
+ case LOC_INDIRECT:
+ case LOC_REGISTER:
+ case LOC_LOCAL:
+ case LOC_TYPEDEF:
+ case LOC_LABEL:
+ case LOC_BLOCK:
+ case LOC_CONST_BYTES:
+ case LOC_BASEREG:
+ case LOC_UNRESOLVED:
+ case LOC_OPTIMIZED_OUT:
+ default:
+ break;
+ }
+ }
+ if (nparams > 0)
+ {
+ TYPE_NFIELDS (ftype) = nparams;
+ TYPE_FIELDS (ftype) = (struct field *)
+ TYPE_ALLOC (ftype, nparams * sizeof (struct field));
+
+ for (i = iparams = 0; iparams < nparams; i++)
+ {
+ sym = BLOCK_SYM (block, i);
+ switch (SYMBOL_CLASS (sym))
+ {
+ case LOC_ARG:
+ case LOC_REF_ARG:
+ case LOC_REGPARM:
+ case LOC_REGPARM_ADDR:
+ case LOC_BASEREG_ARG:
+ case LOC_LOCAL_ARG:
+ TYPE_FIELD_TYPE (ftype, iparams) = SYMBOL_TYPE (sym);
+ iparams++;
+ break;
+ case LOC_UNDEF:
+ case LOC_CONST:
+ case LOC_STATIC:
+ case LOC_INDIRECT:
+ case LOC_REGISTER:
+ case LOC_LOCAL:
+ case LOC_TYPEDEF:
+ case LOC_LABEL:
+ case LOC_BLOCK:
+ case LOC_CONST_BYTES:
+ case LOC_BASEREG:
+ case LOC_UNRESOLVED:
+ case LOC_OPTIMIZED_OUT:
+ default:
+ break;
+ }
+ }
+ }
+ }
+ }
+ 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;
+
+#if 1
+ /* Check to be sure that the blocks have an end address that is
+ greater than starting address */
+
+ if (BLOCK_END (block) < BLOCK_START (block))
+ {
+ if (symbol)
+ {
+ complain (&block_end_complaint, SYMBOL_SOURCE_NAME (symbol));
+ }
+ else
+ {
+ complain (&anon_block_end_complaint, BLOCK_END (block), BLOCK_START (block));
+ }
+ /* Better than nothing */
+ BLOCK_END (block) = BLOCK_START (block);
+ }
+#endif
+
+ /* 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_END (pblock->block), BLOCK_START (block),
+ BLOCK_END (block));
+ }
+ if (BLOCK_START (pblock->block) < BLOCK_START (block))
+ BLOCK_START (pblock->block) = BLOCK_START (block);
+ if (BLOCK_END (pblock->block) > BLOCK_END (block))
+ BLOCK_END (pblock->block) = BLOCK_END (block);
+ }
+#endif
+ BLOCK_SUPERBLOCK (pblock->block) = block;
+ }
+ opblock = pblock;
+ }
+
+ record_pending_block (objfile, block, opblock);
+}
+
+/* Record BLOCK on the list of all blocks in the file. Put it after
+ OPBLOCK, or at the beginning if opblock is NULL. This puts the
+ block in the list after all its subblocks.
+
+ Allocate the pending block struct in the symbol_obstack to save
+ time. This wastes a little space. FIXME: Is it worth it? */
+
+void
+record_pending_block (struct objfile *objfile, struct block *block,
+ struct pending_block *opblock)
+{
+ register struct pending_block *pblock;
+
+ 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;
+ }
+}
+
+/* Note that this is only used in this file and in dstread.c, which
+ should be fixed to not need direct access to this function. When
+ that is done, it can be made static again. */
+
+struct blockvector *
+make_blockvector (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)))
+ {
+
+ /* FIXME-32x64: loses if CORE_ADDR doesn't fit in a
+ long. Possible solutions include a version of
+ complain which takes a callback, a
+ sprintf_address_numeric to match
+ print_address_numeric, or a way to set up a GDB_FILE
+ which causes sprintf rather than fprintf to be
+ called. */
+
+ 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 (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 : savestring (name, strlen (name));
+ subfile->dirname =
+ (dirname == NULL) ? NULL : savestring (dirname, strlen (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;
+ }
+
+ /* Initialize the debug format string to NULL. We may supply it
+ later via a call to record_debugformat. */
+ subfile->debugformat = NULL;
+
+ /* 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). */
+ /* Likewise for f2c. */
+
+ if (subfile->name)
+ {
+ struct subfile *s;
+ enum language sublang = deduce_language_from_filename (subfile->name);
+
+ if (sublang == language_cplus || sublang == language_fortran)
+ for (s = subfiles; s != NULL; s = s->next)
+ if (s->language == language_c)
+ s->language = sublang;
+ }
+
+ /* And patch up this file if necessary. */
+ if (subfile->language == language_c
+ && subfile->next != NULL
+ && (subfile->next->language == language_cplus
+ || subfile->next->language == language_fortran))
+ {
+ subfile->language = subfile->next->language;
+ }
+}
+
+/* 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 (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 = savestring (name, strlen (name));
+ last_source_file = 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 (void)
+{
+ 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 (void)
+{
+ register char *name;
+ register struct subfile_stack *link = subfile_stack;
+
+ if (link == NULL)
+ {
+ abort ();
+ }
+ name = link->name;
+ subfile_stack = link->next;
+ free ((void *) link);
+ return (name);
+}
+
+/* Add a linetable entry for line number LINE and address PC to the
+ line vector for SUBFILE. */
+
+void
+record_line (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;
+ have_line_numbers = 1;
+ }
+
+ 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 (const void *ln1p, const void *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 (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;
+ have_line_numbers = 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 (CORE_ADDR end_addr, 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)
+ {
+ cstk = pop_context ();
+ /* 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;
+ }
+ }
+
+ /* Reordered executables may have out of order pending blocks; if
+ OBJF_REORDERED is true, then sort the pending blocks. */
+ if ((objfile->flags & OBJF_REORDERED) && pending_blocks)
+ {
+ /* FIXME! Remove this horrid bubble sort and use merge sort!!! */
+ 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
+ && have_line_numbers == 0)
+ {
+ /* 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);
+ }
+
+#ifndef PROCESS_LINENUMBER_HOOK
+#define PROCESS_LINENUMBER_HOOK()
+#endif
+ PROCESS_LINENUMBER_HOOK (); /* Needed for xcoff. */
+
+ /* 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;
+ symtab = NULL;
+
+ /* If we have blocks of symbols, make a symtab. Otherwise, just
+ ignore this file and any line number info in it. */
+ 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
+
+ /* Like the pending blocks, the line table may be
+ scrambled in reordered executables. Sort it if
+ OBJF_REORDERED is true. */
+ if (objfile->flags & OBJF_REORDERED)
+ 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;
+
+ /* Save the debug format string (if any) in the symtab */
+ if (subfile->debugformat != NULL)
+ {
+ symtab->debugformat = obsavestring (subfile->debugformat,
+ strlen (subfile->debugformat),
+ &objfile->symbol_obstack);
+ }
+
+ /* 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 ((void *) subfile->name);
+ }
+ if (subfile->dirname != NULL)
+ {
+ free ((void *) subfile->dirname);
+ }
+ if (subfile->line_vector != NULL)
+ {
+ free ((void *) subfile->line_vector);
+ }
+ if (subfile->debugformat != NULL)
+ {
+ free ((void *) subfile->debugformat);
+ }
+
+ nextsub = subfile->next;
+ free ((void *) 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 (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->params = param_symbols;
+ new->old_blocks = pending_blocks;
+ new->start_addr = valu;
+ new->name = NULL;
+
+ local_symbols = NULL;
+ param_symbols = NULL;
+
+ return new;
+}
+
+/* Compute a small integer hash code for the given name. */
+
+int
+hashname (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);
+}
+
+
+void
+record_debugformat (char *format)
+{
+ current_subfile->debugformat = savestring (format, strlen (format));
+}
+
+/* Merge the first symbol list SRCLIST into the second symbol list
+ TARGETLIST by repeated calls to add_symbol_to_list(). This
+ procedure "frees" each link of SRCLIST by adding it to the
+ free_pendings list. Caller must set SRCLIST to a null list after
+ calling this function.
+
+ Void return. */
+
+void
+merge_symbol_lists (struct pending **srclist, struct pending **targetlist)
+{
+ register int i;
+
+ if (!srclist || !*srclist)
+ return;
+
+ /* Merge in elements from current link. */
+ for (i = 0; i < (*srclist)->nsyms; i++)
+ add_symbol_to_list ((*srclist)->symbol[i], targetlist);
+
+ /* Recurse on next. */
+ merge_symbol_lists (&(*srclist)->next, targetlist);
+
+ /* "Free" the current link. */
+ (*srclist)->next = free_pendings;
+ free_pendings = (*srclist);
+}
+
+/* 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 ();
+}
diff --git a/gdb/buildsym.h b/gdb/buildsym.h
new file mode 100644
index 00000000000..e3a34c9d080
--- /dev/null
+++ b/gdb/buildsym.h
@@ -0,0 +1,297 @@
+/* Build symbol tables in GDB's internal format.
+ Copyright 1986-1993, 1996-1999 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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;
+ char *debugformat;
+ };
+
+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;
+
+/* elz: added this flag to know when a block is compiled with HP
+ compilers (cc, aCC). This is necessary because of the macro
+ COERCE_FLOAT_TO_DOUBLE defined in tm_hppa.h, which causes a
+ coercion of float to double to always occur in parameter passing
+ for a function called by gdb (see the function value_arg_coerce in
+ valops.c). This is necessary only if the target was compiled with
+ gcc, not with HP compilers or with g++ */
+
+EXTERN unsigned char processing_hp_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];
+ };
+
+/* Here are the three lists that symbols are put on. */
+
+/* static at top level, and types */
+
+EXTERN struct pending *file_symbols;
+
+/* global functions and variables */
+
+EXTERN struct pending *global_symbols;
+
+/* everything local to lexical context */
+
+EXTERN struct pending *local_symbols;
+
+/* func params local to lexical context */
+
+EXTERN struct pending *param_symbols;
+
+/* Stack representing unclosed lexical contexts (that will become
+ blocks, eventually). */
+
+struct context_stack
+ {
+ /* Outer locals at the time we entered */
+
+ struct pending *locals;
+
+ /* Pending func params at the time we entered */
+
+ struct pending *params;
+
+ /* 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;
+ };
+
+/* Pointer to the head of a linked list of symbol blocks which have
+ already been finalized (lexical contexts already closed) and which
+ are just waiting to be built into a blockvector when finalizing the
+ associated symtab. */
+
+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(objfile) (*next_symbol_text_func)(objfile)
+
+/* Function to invoke get the next symbol. Return the symbol name. */
+
+EXTERN char *(*next_symbol_text_func) (struct objfile *);
+
+/* 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 (struct symbol *symbol,
+ struct pending **listhead);
+
+extern struct symbol *find_symbol_in_list (struct pending *list,
+ char *name, int length);
+
+extern void finish_block (struct symbol *symbol,
+ struct pending **listhead,
+ struct pending_block *old_blocks,
+ CORE_ADDR start, CORE_ADDR end,
+ struct objfile *objfile);
+
+extern void really_free_pendings (int foo);
+
+extern void start_subfile (char *name, char *dirname);
+
+extern void patch_subfile_names (struct subfile *subfile, char *name);
+
+extern void push_subfile (void);
+
+extern char *pop_subfile (void);
+
+extern struct symtab *end_symtab (CORE_ADDR end_addr,
+ struct objfile *objfile, int section);
+
+/* Defined in stabsread.c. */
+
+extern void scan_file_globals (struct objfile *objfile);
+
+extern void buildsym_new_init (void);
+
+extern void buildsym_init (void);
+
+extern struct context_stack *push_context (int desc, CORE_ADDR valu);
+
+extern void record_line (struct subfile *subfile, int line, CORE_ADDR pc);
+
+extern void start_symtab (char *name, char *dirname, CORE_ADDR start_addr);
+
+extern int hashname (char *name);
+
+extern void free_pending_blocks (void);
+
+/* FIXME: Note that this is used only in buildsym.c and dstread.c,
+ which should be fixed to not need direct access to
+ make_blockvector. */
+
+extern struct blockvector *make_blockvector (struct objfile *objfile);
+
+/* FIXME: Note that this is used only in buildsym.c and dstread.c,
+ which should be fixed to not need direct access to
+ record_pending_block. */
+
+extern void record_pending_block (struct objfile *objfile,
+ struct block *block,
+ struct pending_block *opblock);
+
+extern void record_debugformat (char *format);
+
+extern void merge_symbol_lists (struct pending **srclist,
+ struct pending **targetlist);
+
+#undef EXTERN
+
+#endif /* defined (BUILDSYM_H) */
diff --git a/gdb/c-exp.y b/gdb/c-exp.y
new file mode 100644
index 00000000000..377f92a9fb1
--- /dev/null
+++ b/gdb/c-exp.y
@@ -0,0 +1,1740 @@
+/* YACC parser for C expressions, for GDB.
+ Copyright (C) 1986, 1989, 1990, 1991, 1993, 1994, 1996, 1997
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 "gdb_string.h"
+#include <ctype.h>
+#include "expression.h"
+#include "value.h"
+#include "parser-defs.h"
+#include "language.h"
+#include "c-lang.h"
+#include "bfd.h" /* Required by objfiles.h. */
+#include "symfile.h" /* Required by objfiles.h. */
+#include "objfiles.h" /* For have_full_symbols and have_partial_symbols */
+
+/* Flag indicating we're dealing with HP-compiled objects */
+extern int hp_som_som_object_present;
+
+/* 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 */
+#define yylhs c_yylhs
+#define yylen c_yylen
+#define yydefred c_yydefred
+#define yydgoto c_yydgoto
+#define yysindex c_yysindex
+#define yyrindex c_yyrindex
+#define yygindex c_yygindex
+#define yytable c_yytable
+#define yycheck c_yycheck
+
+#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_int;
+ struct {
+ DOUBLEST dval;
+ struct type *type;
+ } typed_val_float;
+ 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> INT
+%token <typed_val_float> 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 DOUBLE_KEYWORD
+
+%token <voidval> VARIABLE
+
+%token <opcode> ASSIGN_MODIFY
+
+/* C++ */
+%token THIS
+%token TRUEKEYWORD
+%token FALSEKEYWORD
+
+
+%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
+%token <bval> FILENAME
+%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_int.type);
+ write_exp_elt_longcst ((LONGEST)val.typed_val_int.val);
+ write_exp_elt_opcode (OP_LONG);
+ }
+ ;
+
+
+exp : FLOAT
+ { write_exp_elt_opcode (OP_DOUBLE);
+ write_exp_elt_type ($1.type);
+ write_exp_elt_dblcst ($1.dval);
+ write_exp_elt_opcode (OP_DOUBLE); }
+ ;
+
+exp : variable
+ ;
+
+exp : VARIABLE
+ /* Already written by write_dollar_variable. */
+ ;
+
+exp : SIZEOF '(' type ')' %prec UNARY
+ { write_exp_elt_opcode (OP_LONG);
+ write_exp_elt_type (builtin_type_int);
+ CHECK_TYPEDEF ($3);
+ 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); }
+ ;
+
+exp : TRUEKEYWORD
+ { write_exp_elt_opcode (OP_LONG);
+ write_exp_elt_type (builtin_type_bool);
+ write_exp_elt_longcst ((LONGEST) 1);
+ write_exp_elt_opcode (OP_LONG); }
+ ;
+
+exp : FALSEKEYWORD
+ { write_exp_elt_opcode (OP_LONG);
+ write_exp_elt_type (builtin_type_bool);
+ write_exp_elt_longcst ((LONGEST) 0);
+ write_exp_elt_opcode (OP_LONG); }
+ ;
+
+/* end of C++. */
+
+block : BLOCKNAME
+ {
+ if ($1.sym)
+ $$ = SYMBOL_BLOCK_VALUE ($1.sym);
+ else
+ error ("No file or function \"%s\".",
+ copy_name ($1.stoken));
+ }
+ | FILENAME
+ {
+ $$ = $1;
+ }
+ ;
+
+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));
+
+ 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;
+
+ /* Check for valid destructor name. */
+ destructor_name_p (tmp_token.ptr, type);
+ 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, NULL, NULL);
+ if (msymbol != NULL)
+ {
+ write_exp_msymbol (msymbol,
+ lookup_function_type (builtin_type_int),
+ builtin_type_int);
+ }
+ 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, NULL, NULL);
+ if (msymbol != NULL)
+ {
+ write_exp_msymbol (msymbol,
+ lookup_function_type (builtin_type_int),
+ builtin_type_int);
+ }
+ 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));
+ }
+ }
+ ;
+
+
+ptype : typebase
+ /* "const" and "volatile" are curently ignored. A type qualifier
+ before the type is currently handled in the typebase rule.
+ The reason for recognizing these here (shift/reduce conflicts)
+ might be obsolete now that some pointer to member rules have
+ been deleted. */
+ | 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;
+ }
+
+ | 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; }
+ ;
+
+/* We used to try to recognize more pointer to member types here, but
+ that didn't work (shift/reduce conflicts meant that these rules never
+ got executed). The problem is that
+ int (foo::bar::baz::bizzle)
+ is a function type but
+ int (foo::bar::baz::bizzle::*)
+ is a pointer to member type. Stroustrup loses again! */
+
+type : ptype
+ | typebase COLONCOLON '*'
+ { $$ = lookup_member_type (builtin_type_int, $1); }
+ ;
+
+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; }
+ | DOUBLE_KEYWORD
+ { $$ = builtin_type_double; }
+ | LONG DOUBLE_KEYWORD
+ { $$ = builtin_type_long_double; }
+ | 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; }
+ /* It appears that this rule for templates is never
+ reduced; template recognition happens by lookahead
+ in the token processing code in yylex. */
+ | 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;
+{
+ /* FIXME: Shouldn't these be unsigned? We don't deal with negative values
+ here, and we do kind of silly things like cast to unsigned. */
+ register LONGEST n = 0;
+ register LONGEST prevn = 0;
+ ULONGEST un;
+
+ register int i = 0;
+ register int c;
+ register int base = input_radix;
+ int unsigned_p = 0;
+
+ /* Number of "L" suffixes encountered. */
+ int long_p = 0;
+
+ /* We have found a "L" or "U" suffix. */
+ int found_suffix = 0;
+
+ ULONGEST 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. */
+ char c;
+ int num = 0; /* number of tokens scanned by scanf */
+ char saved_char = p[len];
+
+ p[len] = 0; /* null-terminate the token */
+ if (sizeof (putithere->typed_val_float.dval) <= sizeof (float))
+ num = sscanf (p, "%g%c", (float *) &putithere->typed_val_float.dval,&c);
+ else if (sizeof (putithere->typed_val_float.dval) <= sizeof (double))
+ num = sscanf (p, "%lg%c", (double *) &putithere->typed_val_float.dval,&c);
+ else
+ {
+#ifdef SCANF_HAS_LONG_DOUBLE
+ num = sscanf (p, "%Lg%c", &putithere->typed_val_float.dval,&c);
+#else
+ /* Scan it into a double, then assign it to the long double.
+ This at least wins with values representable in the range
+ of doubles. */
+ double temp;
+ num = sscanf (p, "%lg%c", &temp,&c);
+ putithere->typed_val_float.dval = temp;
+#endif
+ }
+ p[len] = saved_char; /* restore the input stream */
+ if (num != 1) /* check scanf found ONLY a float ... */
+ return ERROR;
+ /* See if it has `f' or `l' suffix (float or long double). */
+
+ c = tolower (p[len - 1]);
+
+ if (c == 'f')
+ putithere->typed_val_float.type = builtin_type_float;
+ else if (c == 'l')
+ putithere->typed_val_float.type = builtin_type_long_double;
+ else if (isdigit (c) || c == '.')
+ putithere->typed_val_float.type = builtin_type_double;
+ else
+ return ERROR;
+
+ 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')
+ {
+ if (found_suffix)
+ return ERROR;
+ n += i = c - '0';
+ }
+ else
+ {
+ if (base > 10 && c >= 'a' && c <= 'f')
+ {
+ if (found_suffix)
+ return ERROR;
+ n += i = c - 'a' + 10;
+ }
+ else if (c == 'l')
+ {
+ ++long_p;
+ found_suffix = 1;
+ }
+ else if (c == 'u')
+ {
+ unsigned_p = 1;
+ found_suffix = 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). FIXME: Can't we just make n and prevn
+ unsigned and avoid this? */
+ if (c != 'l' && c != 'u' && (prevn >= n) && n != 0)
+ unsigned_p = 1; /* Try something unsigned */
+
+ /* Portably test for unsigned overflow.
+ FIXME: This check is wrong; for example it doesn't find overflow
+ on 0x123456789 when LONGEST is 32 bits. */
+ if (c != 'l' && c != 'u' && n != 0)
+ {
+ if ((unsigned_p && (ULONGEST) prevn >= (ULONGEST) n))
+ error ("Numeric constant too large.");
+ }
+ prevn = n;
+ }
+
+ /* An integer constant is an int, a long, or a long long. An L
+ suffix forces it to be long; an LL suffix forces it to be long
+ long. If not forced to a larger size, it gets the first type of
+ the above that it fits in. To figure out whether it fits, we
+ shift it right and see whether anything remains. Note that we
+ can't shift sizeof (LONGEST) * HOST_CHAR_BIT bits or more in one
+ operation, because many compilers will warn about such a shift
+ (which always produces a zero result). Sometimes TARGET_INT_BIT
+ or TARGET_LONG_BIT will be that big, sometimes not. To deal with
+ the case where it is we just always shift the value more than
+ once, with fewer bits each time. */
+
+ un = (ULONGEST)n >> 2;
+ if (long_p == 0
+ && (un >> (TARGET_INT_BIT - 2)) == 0)
+ {
+ high_bit = ((ULONGEST)1) << (TARGET_INT_BIT-1);
+
+ /* A large decimal (not hex or octal) constant (between INT_MAX
+ and UINT_MAX) is a long or unsigned long, according to ANSI,
+ never an unsigned int, but this code treats it as unsigned
+ int. This probably should be fixed. GCC gives a warning on
+ such constants. */
+
+ unsigned_type = builtin_type_unsigned_int;
+ signed_type = builtin_type_int;
+ }
+ else if (long_p <= 1
+ && (un >> (TARGET_LONG_BIT - 2)) == 0)
+ {
+ high_bit = ((ULONGEST)1) << (TARGET_LONG_BIT-1);
+ unsigned_type = builtin_type_unsigned_long;
+ signed_type = builtin_type_long;
+ }
+ else
+ {
+ int shift;
+ if (sizeof (ULONGEST) * HOST_CHAR_BIT < TARGET_LONG_LONG_BIT)
+ /* A long long does not fit in a LONGEST. */
+ shift = (sizeof (ULONGEST) * HOST_CHAR_BIT - 1);
+ else
+ shift = (TARGET_LONG_LONG_BIT - 1);
+ high_bit = (ULONGEST) 1 << shift;
+ unsigned_type = builtin_type_unsigned_long_long;
+ signed_type = builtin_type_long_long;
+ }
+
+ putithere->typed_val_int.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_int.type = unsigned_type;
+ }
+ else
+ {
+ putithere->typed_val_int.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;
+ struct symbol * sym_class = NULL;
+ char * token_string = NULL;
+ int class_prefix = 0;
+ int unquoted_expr;
+
+ retry:
+
+ unquoted_expr = 1;
+
+ 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);
+ else if (c == '\'')
+ error ("Empty character constant.");
+
+ yylval.typed_val_int.val = c;
+ yylval.typed_val_int.type = builtin_type_char;
+
+ c = *lexptr++;
+ if (c != '\'')
+ {
+ namelen = skip_quoted (tokstart) - tokstart;
+ if (namelen > 2)
+ {
+ lexptr = tokstart + namelen;
+ unquoted_expr = 0;
+ 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 == '<');)
+ {
+ /* Template parameter lists are part of the name.
+ FIXME: This mishandles `print $a<4&&$a>3'. */
+
+ if (c == '<')
+ {
+ if (hp_som_som_object_present)
+ {
+ /* Scan ahead to get rest of the template specification. Note
+ that we look ahead only when the '<' adjoins non-whitespace
+ characters; for comparison expressions, e.g. "a < b > c",
+ there must be spaces before the '<', etc. */
+
+ char * p = find_template_name_end (tokstart + namelen);
+ if (p)
+ namelen = p - tokstart;
+ break;
+ }
+ else
+ {
+ int i = namelen;
+ int nesting_level = 1;
+ while (tokstart[++i])
+ {
+ if (tokstart[i] == '<')
+ nesting_level++;
+ else if (tokstart[i] == '>')
+ {
+ if (--nesting_level == 0)
+ break;
+ }
+ }
+ if (tokstart[i] == '>')
+ namelen = i;
+ else
+ break;
+ }
+ }
+ 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;
+
+ tryname:
+
+ /* 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;
+ if (STREQN (tokstart, "double", 6))
+ return DOUBLE_KEYWORD;
+ break;
+ case 5:
+ if (current_language->la_language == language_cplus)
+ {
+ if (STREQN (tokstart, "false", 5))
+ return FALSEKEYWORD;
+ if (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)
+ {
+ if (STREQN (tokstart, "true", 4))
+ return TRUEKEYWORD;
+
+ if (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;
+
+ if (*tokstart == '$')
+ {
+ write_dollar_variable (yylval.sval);
+ return VARIABLE;
+ }
+
+ /* Look ahead and see if we can consume more of the input
+ string to get a reasonable class/namespace spec or a
+ fully-qualified name. This is a kludge to get around the
+ HP aCC compiler's generation of symbol names with embedded
+ colons for namespace and nested classes. */
+ if (unquoted_expr)
+ {
+ /* Only do it if not inside single quotes */
+ sym_class = parse_nested_classes_for_hpacc (yylval.sval.ptr, yylval.sval.length,
+ &token_string, &class_prefix, &lexptr);
+ if (sym_class)
+ {
+ /* Replace the current token with the bigger one we found */
+ yylval.sval.ptr = token_string;
+ yylval.sval.length = strlen (token_string);
+ }
+ }
+
+ /* 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);
+ /* Call lookup_symtab, not lookup_partial_symtab, in case there are
+ no psymtabs (coff, xcoff, or some future change to blow away the
+ psymtabs once once symbols are read). */
+ if (sym && SYMBOL_CLASS (sym) == LOC_BLOCK)
+ {
+ yylval.ssym.sym = sym;
+ yylval.ssym.is_a_field_of_this = is_a_field_of_this;
+ return BLOCKNAME;
+ }
+ else if (!sym)
+ { /* See if it's a file name. */
+ struct symtab *symtab;
+
+ symtab = lookup_symtab (tmp);
+
+ if (symtab)
+ {
+ yylval.bval = BLOCKVECTOR_BLOCK (BLOCKVECTOR (symtab), STATIC_BLOCK);
+ return FILENAME;
+ }
+ }
+
+ if (sym && SYMBOL_CLASS (sym) == LOC_TYPEDEF)
+ {
+#if 1
+ /* Despite the following flaw, we need to keep this code enabled.
+ Because we can get called from check_stub_method, if we don't
+ handle nested types then it screws many operations in any
+ program which uses nested types. */
+ /* In "A::x", if x is a member function of A and there happens
+ to be a type (nested or not, since the stabs don't make that
+ distinction) named x, then this code incorrectly thinks we
+ are dealing with nested types rather than a member function. */
+
+ 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 *ncopy = alloca (strlen (tmp)+strlen (namestart)+3);
+ char *tmp1;
+
+ tmp1 = ncopy;
+ memcpy (tmp1, tmp, strlen (tmp));
+ tmp1 += strlen (tmp);
+ memcpy (tmp1, "::", 2);
+ tmp1 += 2;
+ memcpy (tmp1, namestart, p - namestart);
+ tmp1[p - namestart] = '\0';
+ cur_sym = lookup_symbol (ncopy, 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);
+#else /* not 0 */
+ yylval.tsym.type = SYMBOL_TYPE (sym);
+#endif /* not 0 */
+ 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 ("A %s in expression, near `%s'.", (msg ? msg : "error"), lexptr);
+}
diff --git a/gdb/c-lang.c b/gdb/c-lang.c
new file mode 100644
index 00000000000..e7aa05574ca
--- /dev/null
+++ b/gdb/c-lang.c
@@ -0,0 +1,527 @@
+/* C language support routines for GDB, the GNU debugger.
+ Copyright 1992, 1993, 1994 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "symtab.h"
+#include "gdbtypes.h"
+#include "expression.h"
+#include "parser-defs.h"
+#include "language.h"
+#include "c-lang.h"
+
+static void c_emit_char PARAMS ((int c, GDB_FILE *stream, int quoter));
+
+/* 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
+c_emit_char (c, stream, quoter)
+ register int c;
+ GDB_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;
+ }
+ }
+}
+
+void
+c_printchar (c, stream)
+ int c;
+ GDB_FILE *stream;
+{
+ fputc_filtered ('\'', stream);
+ LA_EMIT_CHAR (c, stream, '\'');
+ fputc_filtered ('\'', stream);
+}
+
+/* Print the character string STRING, printing at most LENGTH characters.
+ LENGTH is -1 if the string is nul terminated. Each character is WIDTH bytes
+ long. 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
+c_printstr (stream, string, length, width, force_ellipses)
+ GDB_FILE *stream;
+ char *string;
+ unsigned int length;
+ int width;
+ 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
+ && extract_unsigned_integer (string + (length - 1) * width, width) == '\0')
+ length--;
+
+ if (length == 0)
+ {
+ fputs_filtered ("\"\"", 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;
+ unsigned long current_char;
+
+ QUIT;
+
+ if (need_comma)
+ {
+ fputs_filtered (", ", stream);
+ need_comma = 0;
+ }
+
+ current_char = extract_unsigned_integer (string + i * width, width);
+
+ rep1 = i + 1;
+ reps = 1;
+ while (rep1 < length
+ && extract_unsigned_integer (string + rep1 * width, width)
+ == current_char)
+ {
+ ++rep1;
+ ++reps;
+ }
+
+ if (reps > repeat_count_threshold)
+ {
+ if (in_quotes)
+ {
+ if (inspect_it)
+ fputs_filtered ("\\\", ", stream);
+ else
+ fputs_filtered ("\", ", stream);
+ in_quotes = 0;
+ }
+ LA_PRINT_CHAR (current_char, 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;
+ }
+ LA_EMIT_CHAR (current_char, 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 */
+
+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_BOOLEAN:
+ type = init_type (TYPE_CODE_BOOL,
+ TARGET_CHAR_BIT / TARGET_CHAR_BIT,
+ 0, "bool", objfile);
+
+ break;
+ case FT_CHAR:
+ type = init_type (TYPE_CODE_INT,
+ TARGET_CHAR_BIT / TARGET_CHAR_BIT,
+ 0, "char", objfile);
+ TYPE_FLAGS (type) |= TYPE_FLAG_NOSIGN;
+ break;
+ case FT_SIGNED_CHAR:
+ type = init_type (TYPE_CODE_INT,
+ TARGET_CHAR_BIT / TARGET_CHAR_BIT,
+ 0, "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,
+ 0, "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,
+ 0, "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,
+ 0, "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,
+ 0, "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;
+ case FT_TEMPLATE_ARG:
+ type = init_type (TYPE_CODE_TEMPLATE_ARG,
+ 0,
+ 0, "<template arg>", objfile);
+
+ break;
+ }
+ return (type);
+}
+
+
+/* Table mapping opcodes into strings for printing operators
+ and precedences of the operators. */
+
+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_PTR (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,
+ evaluate_subexp_standard,
+ c_printchar, /* Print a character constant */
+ c_printstr, /* Function to print string constant */
+ c_emit_char, /* Print a single char */
+ 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 */
+ c_value_print, /* Print a top-level value */
+ {"", "", "", ""}, /* 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 */
+ 1, /* c-style arrays */
+ 0, /* String lower bound */
+ &builtin_type_char, /* Type of string elements */
+ LANG_MAGIC
+};
+
+struct type ** const (cplus_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,
+ &builtin_type_bool,
+ 0
+};
+
+const struct language_defn cplus_language_defn = {
+ "c++", /* Language name */
+ language_cplus,
+ cplus_builtin_types,
+ range_check_off,
+ type_check_off,
+ c_parse,
+ c_error,
+ evaluate_subexp_standard,
+ c_printchar, /* Print a character constant */
+ c_printstr, /* Function to print string constant */
+ c_emit_char, /* Print a single char */
+ 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 */
+ c_value_print, /* Print a top-level value */
+ {"", "", "", ""}, /* 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 */
+ 1, /* c-style arrays */
+ 0, /* String lower bound */
+ &builtin_type_char, /* Type of string elements */
+ LANG_MAGIC
+};
+
+const struct language_defn asm_language_defn = {
+ "asm", /* Language name */
+ language_asm,
+ c_builtin_types,
+ range_check_off,
+ type_check_off,
+ c_parse,
+ c_error,
+ evaluate_subexp_standard,
+ c_printchar, /* Print a character constant */
+ c_printstr, /* Function to print string constant */
+ c_emit_char, /* Print a single char */
+ 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 */
+ c_value_print, /* Print a top-level value */
+ {"", "", "", ""}, /* 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 */
+ 1, /* c-style arrays */
+ 0, /* String lower bound */
+ &builtin_type_char, /* Type of string elements */
+ LANG_MAGIC
+};
+
+void
+_initialize_c_language ()
+{
+ add_language (&c_language_defn);
+ add_language (&cplus_language_defn);
+ add_language (&asm_language_defn);
+}
diff --git a/gdb/c-lang.h b/gdb/c-lang.h
new file mode 100644
index 00000000000..28486fd73b3
--- /dev/null
+++ b/gdb/c-lang.h
@@ -0,0 +1,87 @@
+/* C language support definitions for GDB, the GNU debugger.
+ Copyright 1992, 1996 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+
+#if !defined (C_LANG_H)
+#define C_LANG_H 1
+
+#include "value.h"
+
+
+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 *, GDB_FILE *, int, int));
+
+extern int
+c_val_print PARAMS ((struct type *, char *, int, CORE_ADDR, GDB_FILE *, int, int,
+ int, enum val_prettyprint));
+
+extern int
+c_value_print PARAMS ((struct value *, GDB_FILE *, int, enum val_prettyprint));
+
+/* These are in c-lang.c: */
+
+extern void c_printchar PARAMS ((int, GDB_FILE*));
+
+extern void c_printstr PARAMS ((GDB_FILE *stream, char *string,
+ unsigned int length, int width,
+ int force_ellipses));
+
+extern struct type * c_create_fundamental_type PARAMS ((struct objfile*, int));
+
+extern struct type ** CONST_PTR (c_builtin_types[]);
+
+/* These are in c-typeprint.c: */
+
+extern void
+c_type_print_base PARAMS ((struct type *, GDB_FILE *, int, int));
+
+extern void
+c_type_print_varspec_prefix PARAMS ((struct type *, GDB_FILE *, int, int));
+
+/* These are in cp-valprint.c */
+
+extern int vtblprint; /* Controls printing of vtbl's */
+
+extern int static_field_print;
+
+extern void
+cp_print_class_member PARAMS ((char *, struct type *, GDB_FILE *, char *));
+
+extern void
+cp_print_class_method PARAMS ((char *, struct type *, GDB_FILE *));
+
+extern void
+cp_print_value_fields PARAMS ((struct type *, struct type *, char *, int, CORE_ADDR,
+ GDB_FILE *, int, int, enum val_prettyprint,
+ struct type**, int));
+
+extern int
+cp_is_vtbl_ptr_type PARAMS ((struct type *));
+
+extern int
+cp_is_vtbl_member PARAMS ((struct type *));
+
+
+#endif /* !defined (C_LANG_H) */
diff --git a/gdb/c-typeprint.c b/gdb/c-typeprint.c
new file mode 100644
index 00000000000..e15550309dc
--- /dev/null
+++ b/gdb/c-typeprint.c
@@ -0,0 +1,1089 @@
+/* Support for printing C and C++ types for GDB, the GNU debugger.
+ Copyright 1986, 1988, 1989, 1991, 1993, 1994, 1995, 1996, 1998, 1999
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 "gdb_string.h"
+#include <errno.h>
+#include <ctype.h>
+
+/* Flag indicating target was compiled by HP compiler */
+extern int hp_som_som_object_present;
+
+static void
+c_type_print_args PARAMS ((struct type *, GDB_FILE *));
+
+static void
+cp_type_print_derivation_info PARAMS ((GDB_FILE *, struct type *));
+
+void
+c_type_print_varspec_prefix PARAMS ((struct type *, GDB_FILE *, int, int));
+
+static void
+c_type_print_cv_qualifier PARAMS ((struct type *, GDB_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;
+ GDB_FILE *stream;
+{
+ CHECK_TYPEDEF (type);
+ 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:
+ fprintf_filtered(stream, "SYNMODE ");
+ 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
+ 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;
+ GDB_FILE *stream;
+ int show;
+ int level;
+{
+ register enum type_code code;
+ int demangled_args;
+
+ if (show > 0)
+ CHECK_TYPEDEF (type);
+
+ 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);
+
+ if (varstring != NULL)
+ {
+ 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 = strchr(varstring, '(') != NULL;
+ c_type_print_varspec_suffix (type, stream, show, 0, demangled_args);
+ }
+}
+
+/* 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.
+ Note that in case of protected derivation gcc will not say 'protected'
+ but 'private'. The HP's aCC compiler emits specific information for
+ derivation via protected inheritance, so gdb can print it out */
+
+static void
+cp_type_print_derivation_info (stream, type)
+ GDB_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"
+ : (TYPE_FIELD_PROTECTED (type, i) ? "protected" : "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 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;
+ GDB_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;
+ }
+ }
+ else if (current_language->la_language == language_cplus)
+ {
+ fprintf_filtered (stream, "void");
+ }
+
+ 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. */
+
+void
+c_type_print_varspec_prefix (type, stream, show, passed_a_ptr)
+ struct type *type;
+ GDB_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, "*");
+ c_type_print_cv_qualifier (type, stream, 1, 0);
+ 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_filtered (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, "&");
+ c_type_print_cv_qualifier (type, stream, 1, 0);
+ 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:
+ case TYPE_CODE_COMPLEX:
+ case TYPE_CODE_TYPEDEF:
+ /* These types need no prefix. They are listed here so that
+ gcc -Wall will reveal any types that haven't been handled. */
+ break;
+ }
+}
+
+/* Print out "const" and "volatile" attributes.
+ TYPE is a pointer to the type being printed out.
+ STREAM is the output destination.
+ NEED_SPACE = 1 indicates an initial white space is needed */
+
+static void
+c_type_print_cv_qualifier (type, stream, need_pre_space, need_post_space)
+ struct type *type;
+ GDB_FILE *stream;
+ int need_pre_space;
+ int need_post_space;
+{
+ int flag = 0;
+
+ if (TYPE_CONST (type))
+ {
+ if (need_pre_space)
+ fprintf_filtered (stream, " ");
+ fprintf_filtered (stream, "const");
+ flag = 1;
+ }
+
+ if (TYPE_VOLATILE (type))
+ {
+ if (flag || need_pre_space)
+ fprintf_filtered (stream, " ");
+ fprintf_filtered (stream, "volatile");
+ flag = 1;
+ }
+
+ if (flag && need_post_space)
+ fprintf_filtered (stream, " ");
+}
+
+
+
+
+static void
+c_type_print_args (type, stream)
+ struct type *type;
+ GDB_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 if ((args[1]->code == TYPE_CODE_VOID) &&
+ (current_language->la_language == language_cplus))
+ {
+ fprintf_filtered (stream, "void");
+ }
+ 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 (" ");
+ }
+ }
+ }
+ }
+ else if (current_language->la_language == language_cplus)
+ {
+ fprintf_filtered (stream, "void");
+ }
+
+ 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. */
+
+void
+c_type_print_varspec_suffix (type, stream, show, passed_a_ptr, demangled_args)
+ struct type *type;
+ GDB_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
+ && TYPE_ARRAY_UPPER_BOUND_TYPE(type) != BOUND_CANNOT_BE_DETERMINED)
+ 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:
+ if (passed_a_ptr)
+ fprintf_filtered (stream, ")");
+ if (!demangled_args)
+ { int i, len = TYPE_NFIELDS (type);
+ fprintf_filtered (stream, "(");
+ if ((len == 0) && (current_language->la_language == language_cplus))
+ {
+ fprintf_filtered (stream, "void");
+ }
+ else
+ for (i = 0; i < len; i++)
+ {
+ if (i > 0)
+ {
+ fputs_filtered (", ", stream);
+ wrap_here (" ");
+ }
+ c_print_type (TYPE_FIELD_TYPE (type, i), "", stream, -1, 0);
+ }
+ fprintf_filtered (stream, ")");
+ }
+ c_type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, 0,
+ passed_a_ptr, 0);
+ 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:
+ case TYPE_CODE_COMPLEX:
+ case TYPE_CODE_TYPEDEF:
+ /* 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 negative 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 zero means just print the type name or struct tag if there is one.
+ If there is no name, print something sensible but not as concise like
+ "struct {int x; int y;}".
+
+ 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;
+ GDB_FILE *stream;
+ int show;
+ int level;
+{
+ register int i;
+ register int len;
+ register int lastval;
+ char *mangled_name;
+ char *demangled_name;
+ char *demangled_no_static;
+ enum {s_none, s_public, s_private, s_protected} section_type;
+ int need_access_label = 0;
+ int j, len2;
+
+ 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)
+ {
+ c_type_print_cv_qualifier (type, stream, 0, 1);
+ fputs_filtered (TYPE_NAME (type), stream);
+ return;
+ }
+
+ CHECK_TYPEDEF (type);
+
+ switch (TYPE_CODE (type))
+ {
+ case TYPE_CODE_TYPEDEF:
+ 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:
+ c_type_print_cv_qualifier (type, stream, 0, 1);
+ /* Note TYPE_CODE_STRUCT and TYPE_CODE_CLASS have the same value,
+ * so we use another means for distinguishing them.
+ */
+ if (HAVE_CPLUS_STRUCT (type)) {
+ switch (TYPE_DECLARED_TYPE(type)) {
+ case DECLARED_TYPE_CLASS:
+ fprintf_filtered (stream, "class ");
+ break;
+ case DECLARED_TYPE_UNION:
+ fprintf_filtered (stream, "union ");
+ break;
+ case DECLARED_TYPE_STRUCT:
+ fprintf_filtered (stream, "struct ");
+ break;
+ default:
+ /* If there is a CPLUS_STRUCT, assume class if not
+ * otherwise specified in the declared_type field.
+ */
+ fprintf_filtered (stream, "class ");
+ break;
+ } /* switch */
+ } else {
+ /* If not CPLUS_STRUCT, then assume it's a C struct */
+ fprintf_filtered (stream, "struct ");
+ }
+ goto struct_union;
+
+ case TYPE_CODE_UNION:
+ c_type_print_cv_qualifier (type, stream, 0, 1);
+ fprintf_filtered (stream, "union ");
+
+ struct_union:
+
+ /* Print the tag if it exists.
+ * The HP aCC compiler emits
+ * a spurious "{unnamed struct}"/"{unnamed union}"/"{unnamed enum}"
+ * tag for unnamed struct/union/enum's, which we don't
+ * want to print.
+ */
+ if (TYPE_TAG_NAME (type) != NULL &&
+ strncmp(TYPE_TAG_NAME(type), "{unnamed", 8))
+ {
+ 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 || TYPE_TAG_NAME (type) == NULL)
+ {
+ 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;
+
+ /* For a class, if all members are private, there's no need
+ for a "private:" label; similarly, for a struct or union
+ masquerading as a class, if all members are public, there's
+ no need for a "public:" label. */
+
+ if ((TYPE_DECLARED_TYPE (type) == DECLARED_TYPE_CLASS) ||
+ (TYPE_DECLARED_TYPE (type) == DECLARED_TYPE_TEMPLATE))
+ {
+ QUIT;
+ len = TYPE_NFIELDS (type);
+ for (i = TYPE_N_BASECLASSES (type); i < len; i++)
+ if (!TYPE_FIELD_PRIVATE (type, i))
+ {
+ need_access_label = 1;
+ break;
+ }
+ QUIT;
+ if (!need_access_label)
+ {
+ len2 = TYPE_NFN_FIELDS (type);
+ for (j = 0; j < len2; j++)
+ {
+ len = TYPE_FN_FIELDLIST_LENGTH (type, j);
+ for (i = 0; i < len; i++)
+ if (!TYPE_FN_FIELD_PRIVATE (TYPE_FN_FIELDLIST1 (type, j), i))
+ {
+ need_access_label = 1;
+ break;
+ }
+ if (need_access_label)
+ break;
+ }
+ }
+ }
+ else if ((TYPE_DECLARED_TYPE (type) == DECLARED_TYPE_STRUCT) ||
+ (TYPE_DECLARED_TYPE (type) == DECLARED_TYPE_UNION))
+ {
+ QUIT;
+ len = TYPE_NFIELDS (type);
+ for (i = TYPE_N_BASECLASSES (type); i < len; i++)
+ if (TYPE_FIELD_PRIVATE (type, i) || TYPE_FIELD_PROTECTED (type, i))
+ {
+ need_access_label = 1;
+ break;
+ }
+ QUIT;
+ if (!need_access_label)
+ {
+ len2 = TYPE_NFN_FIELDS (type);
+ for (j = 0; j < len2; j++)
+ {
+ QUIT;
+ len = TYPE_FN_FIELDLIST_LENGTH (type, j);
+ for (i = 0; i < len; i++)
+ if (TYPE_FN_FIELD_PRIVATE (TYPE_FN_FIELDLIST1 (type, j), i) ||
+ TYPE_FN_FIELD_PROTECTED (TYPE_FN_FIELDLIST1 (type, j), i))
+ {
+ need_access_label = 1;
+ break;
+ }
+ if (need_access_label)
+ break;
+ }
+ }
+ }
+
+ /* 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. */
+ /* HP ANSI C++ case */
+ if (TYPE_HAS_VTABLE(type) && (STREQN (TYPE_FIELD_NAME (type, i), "__vfp", 5)))
+ continue;
+ /* Other compilers */
+ /* pai:: FIXME : check for has_vtable < 0 */
+ if (STREQN (TYPE_FIELD_NAME (type, i), "_vptr", 5)
+ && is_cplus_marker ((TYPE_FIELD_NAME (type, i))[5]))
+ continue;
+
+ /* If this is a C++ class we can print the various C++ section
+ labels. */
+
+ if (HAVE_CPLUS_STRUCT (type) && need_access_label)
+ {
+ 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++)
+ {
+ char *physname = TYPE_FN_FIELD_PHYSNAME (f, j);
+ int is_full_physname_constructor =
+ ((physname[0] == '_' && physname[1] == '_'
+ && strchr ("0123456789Qt", physname[2]))
+ || STREQN (physname, "__ct__", 6)
+ || DESTRUCTOR_PREFIX_P (physname)
+ || STREQN (physname, "__dt__", 6));
+
+ 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_filtered (stream, "<undefined type> %s;\n",
+ TYPE_FN_FIELD_PHYSNAME (f, j));
+ break;
+ }
+ else if (!is_constructor && /* constructors don't have declared types */
+ !is_full_physname_constructor && /* " " */
+ !strstr (method_name, "operator ")) /* Not a type conversion operator */
+ /* (note space -- other operators don't have it) */
+ {
+ type_print (TYPE_TARGET_TYPE (TYPE_FN_FIELD_TYPE (f, j)),
+ "", stream, -1);
+ fputs_filtered (" ", stream);
+ }
+ if (TYPE_FN_FIELD_STUB (f, j))
+ /* Build something we can demangle. */
+ mangled_name = gdb_mangle_name (type, i, j);
+ else
+ mangled_name = TYPE_FN_FIELD_PHYSNAME (f, j);
+
+ demangled_name =
+ cplus_demangle (mangled_name,
+ DMGL_ANSI | DMGL_PARAMS);
+ if (demangled_name == NULL)
+ {
+ /* in some cases (for instance with the HP demangling),
+ if a function has more than 10 arguments,
+ the demangling will fail.
+ Let's try to reconstruct the function signature from
+ the symbol information */
+ if (!TYPE_FN_FIELD_STUB (f, j))
+ cp_type_print_method_args (TYPE_FN_FIELD_ARGS (f, j), "",
+ method_name,
+ TYPE_FN_FIELD_STATIC_P (f, j),
+ stream);
+ else
+ fprintf_filtered (stream, "<badly mangled name '%s'>",
+ mangled_name);
+ }
+ else
+ {
+ char *p;
+ char *demangled_no_class = demangled_name;
+
+ while (p = strchr (demangled_no_class, ':'))
+ {
+ demangled_no_class = p;
+ if (*++demangled_no_class == ':')
+ ++demangled_no_class;
+ }
+ /* get rid of the static word appended by the demangler */
+ p = strstr (demangled_no_class, " static");
+ if (p != NULL)
+ {
+ int length = p - demangled_no_class;
+ demangled_no_static = (char *) xmalloc (length + 1);
+ strncpy (demangled_no_static, demangled_no_class, length);
+ *(demangled_no_static + length) = '\0';
+ fputs_filtered (demangled_no_static, stream);
+ free (demangled_no_static);
+ }
+ else
+ fputs_filtered (demangled_no_class, stream);
+ free (demangled_name);
+ }
+
+ if (TYPE_FN_FIELD_STUB (f, j))
+ free (mangled_name);
+
+ fprintf_filtered (stream, ";\n");
+ }
+ }
+
+ if (TYPE_LOCALTYPE_PTR (type) && show >= 0)
+ fprintfi_filtered (level, stream, " (Local at %s:%d)\n",
+ TYPE_LOCALTYPE_FILE (type),
+ TYPE_LOCALTYPE_LINE (type));
+
+ fprintfi_filtered (level, stream, "}");
+ }
+ if (TYPE_CODE(type) == TYPE_CODE_TEMPLATE)
+ goto go_back;
+ break;
+
+ case TYPE_CODE_ENUM:
+ c_type_print_cv_qualifier (type, stream, 0, 1);
+ /* HP C supports sized enums */
+ if (hp_som_som_object_present)
+ switch (TYPE_LENGTH (type))
+ {
+ case 1:
+ fputs_filtered ("char ", stream);
+ break;
+ case 2:
+ fputs_filtered ("short ", stream);
+ break;
+ default:
+ break;
+ }
+ fprintf_filtered (stream, "enum ");
+ /* Print the tag name if it exists.
+ The aCC compiler emits a spurious
+ "{unnamed struct}"/"{unnamed union}"/"{unnamed enum}"
+ tag for unnamed struct/union/enum's, which we don't
+ want to print. */
+ if (TYPE_TAG_NAME (type) != NULL &&
+ strncmp(TYPE_TAG_NAME(type), "{unnamed", 8))
+ {
+ 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 || TYPE_TAG_NAME (type) == NULL)
+ {
+ 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;
+
+ case TYPE_CODE_TEMPLATE:
+ /* Called on "ptype t" where "t" is a template.
+ Prints the template header (with args), e.g.:
+ template <class T1, class T2> class "
+ and then merges with the struct/union/class code to
+ print the rest of the definition. */
+ c_type_print_cv_qualifier (type, stream, 0, 1);
+ fprintf_filtered (stream, "template <");
+ for (i = 0; i < TYPE_NTEMPLATE_ARGS(type); i++) {
+ struct template_arg templ_arg;
+ templ_arg = TYPE_TEMPLATE_ARG(type, i);
+ fprintf_filtered (stream, "class %s", templ_arg.name);
+ if (i < TYPE_NTEMPLATE_ARGS(type)-1)
+ fprintf_filtered (stream, ", ");
+ }
+ fprintf_filtered (stream, "> class ");
+ /* Yuck, factor this out to a subroutine so we can call
+ it and return to the point marked with the "goback:" label... - RT */
+ goto struct_union;
+go_back:
+ if (TYPE_NINSTANTIATIONS(type) > 0) {
+ fprintf_filtered (stream, "\ntemplate instantiations:\n");
+ for (i = 0; i < TYPE_NINSTANTIATIONS(type); i++) {
+ fprintf_filtered(stream, " ");
+ c_type_print_base (TYPE_INSTANTIATION(type, i), stream, 0, level);
+ if (i < TYPE_NINSTANTIATIONS(type)-1) fprintf_filtered(stream, "\n");
+ }
+ }
+ 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)
+ {
+ c_type_print_cv_qualifier (type, stream, 0, 1);
+ 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/gdb/c-valprint.c b/gdb/c-valprint.c
new file mode 100644
index 00000000000..7a9c6bec0d6
--- /dev/null
+++ b/gdb/c-valprint.c
@@ -0,0 +1,535 @@
+/* Support for printing C values for GDB, the GNU debugger.
+ Copyright 1986, 1988, 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1997
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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"
+#include "c-lang.h"
+
+
+/* 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, embedded_offset, address, stream, format, deref_ref, recurse,
+ pretty)
+ struct type *type;
+ char *valaddr;
+ int embedded_offset;
+ CORE_ADDR address;
+ GDB_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;
+
+ CHECK_TYPEDEF (type);
+ switch (TYPE_CODE (type))
+ {
+ case TYPE_CODE_ARRAY:
+ elttype = check_typedef (TYPE_TARGET_TYPE (type));
+ if (TYPE_LENGTH (type) > 0 && TYPE_LENGTH (TYPE_TARGET_TYPE (type)) > 0)
+ {
+ 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)
+ || ((current_language->la_language == language_m2)
+ && (TYPE_CODE (elttype) == TYPE_CODE_CHAR)))
+ && (format == 0 || format == 's'))
+ {
+ /* If requested, look for the first null char and only print
+ elements up to it. */
+ if (stop_print_at_null)
+ {
+ int temp_len;
+
+ /* Look for a NULL char. */
+ for (temp_len = 0;
+ (valaddr + embedded_offset)[temp_len]
+ && temp_len < len && temp_len < print_max;
+ temp_len++);
+ len = temp_len;
+ }
+
+ LA_PRINT_STRING (stream, valaddr + embedded_offset, len, eltlen, 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 + embedded_offset, 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 + embedded_offset, type, format, 0, stream);
+ break;
+ }
+ if (vtblprint && cp_is_vtbl_ptr_type(type))
+ {
+ /* Print the unmangled name if desired. */
+ /* Print vtable entry - we only get here if we ARE using
+ -fvtable_thunks. (Otherwise, look under TYPE_CODE_STRUCT.) */
+ print_address_demangle(extract_address (valaddr + embedded_offset, TYPE_LENGTH (type)),
+ stream, demangle);
+ break;
+ }
+ elttype = check_typedef (TYPE_TARGET_TYPE (type));
+ if (TYPE_CODE (elttype) == TYPE_CODE_METHOD)
+ {
+ cp_print_class_method (valaddr + embedded_offset, type, stream);
+ }
+ else if (TYPE_CODE (elttype) == TYPE_CODE_MEMBER)
+ {
+ cp_print_class_member (valaddr + embedded_offset,
+ TYPE_DOMAIN_TYPE (TYPE_TARGET_TYPE (type)),
+ stream, "&");
+ }
+ else
+ {
+ addr = unpack_pointer (type, valaddr + embedded_offset);
+ print_unpacked_pointer:
+ elttype = check_typedef (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')
+ {
+ print_address_numeric (addr, 1, stream);
+ }
+
+ /* For a pointer to char or unsigned char, also print the string
+ pointed to, unless pointer is null. */
+ /* FIXME: need to handle wchar_t here... */
+
+ if (TYPE_LENGTH (elttype) == 1
+ && TYPE_CODE (elttype) == TYPE_CODE_INT
+ && (format == 0 || format == 's')
+ && addr != 0)
+ {
+ i = val_print_string (addr, -1, TYPE_LENGTH (elttype), stream);
+ }
+ else if (cp_is_vtbl_member(type))
+ {
+ /* print vtbl's nicely */
+ CORE_ADDR vt_address = unpack_pointer (type, valaddr + embedded_offset);
+
+ 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 (vt_address && vtblprint)
+ {
+ value_ptr vt_val;
+ struct symbol *wsym = (struct symbol *)NULL;
+ struct type *wtype;
+ struct symtab *s;
+ struct block *block = (struct block *)NULL;
+ int is_this_fld;
+
+ if (msymbol != NULL)
+ 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, NULL);
+ val_print (VALUE_TYPE (vt_val), VALUE_CONTENTS (vt_val), 0,
+ 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, including the terminating
+ '\0' if we reached the end. val_print_string takes care including
+ the terminating '\0' if necessary. */
+ return i;
+ }
+ break;
+
+ case TYPE_CODE_MEMBER:
+ error ("not implemented: member type in c_val_print");
+ break;
+
+ case TYPE_CODE_REF:
+ elttype = check_typedef (TYPE_TARGET_TYPE (type));
+ if (TYPE_CODE (elttype) == TYPE_CODE_MEMBER)
+ {
+ cp_print_class_member (valaddr + embedded_offset,
+ TYPE_DOMAIN_TYPE (elttype),
+ stream, "");
+ break;
+ }
+ if (addressprint)
+ {
+ fprintf_filtered (stream, "@");
+ print_address_numeric
+ (extract_address (valaddr + embedded_offset,
+ TARGET_PTR_BIT / HOST_CHAR_BIT), 1, stream);
+ if (deref_ref)
+ fputs_filtered (": ", stream);
+ }
+ /* De-reference the reference. */
+ if (deref_ref)
+ {
+ if (TYPE_CODE (elttype) != TYPE_CODE_UNDEF)
+ {
+ value_ptr deref_val =
+ value_at
+ (TYPE_TARGET_TYPE (type),
+ unpack_pointer (lookup_pointer_type (builtin_type_void),
+ valaddr + embedded_offset),
+ NULL);
+ val_print (VALUE_TYPE (deref_val),
+ VALUE_CONTENTS (deref_val),
+ 0,
+ VALUE_ADDRESS (deref_val),
+ stream,
+ format,
+ deref_ref,
+ recurse,
+ 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 vtable entry - we only get here if NOT using
+ -fvtable_thunks. (Otherwise, look under TYPE_CODE_PTR.) */
+ print_address_demangle (extract_address (
+ valaddr + embedded_offset +
+ TYPE_FIELD_BITPOS (type, VTBL_FNADDR_OFFSET) / 8,
+ TYPE_LENGTH (TYPE_FIELD_TYPE (type, VTBL_FNADDR_OFFSET))),
+ stream, demangle);
+ }
+ else
+ cp_print_value_fields (type, type, valaddr, embedded_offset, address, stream, format,
+ recurse, pretty, NULL, 0);
+ break;
+
+ case TYPE_CODE_ENUM:
+ if (format)
+ {
+ print_scalar_formatted (valaddr + embedded_offset, type, format, 0, stream);
+ break;
+ }
+ len = TYPE_NFIELDS (type);
+ val = unpack_long (type, valaddr + embedded_offset);
+ 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 + embedded_offset, 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:
+ format = format ? format : output_format;
+ if (format)
+ print_scalar_formatted (valaddr + embedded_offset, type, format, 0, stream);
+ else
+ {
+ val = unpack_long (type, valaddr + embedded_offset);
+ if (val == 0)
+ fputs_filtered ("false", stream);
+ else if (val == 1)
+ fputs_filtered ("true", stream);
+ else
+ print_longest (stream, 'd', 0, val);
+ }
+ break;
+
+ case TYPE_CODE_RANGE:
+ /* FIXME: create_range_type does not set the unsigned bit in a
+ range type (I think it probably should copy it from the target
+ type), so we won't print values which are too large to
+ fit in a signed integer correctly. */
+ /* FIXME: Doesn't handle ranges of enums correctly. (Can't just
+ print with the target type, though, because the size of our type
+ and the target type might differ). */
+ /* FALLTHROUGH */
+
+ case TYPE_CODE_INT:
+ format = format ? format : output_format;
+ if (format)
+ {
+ print_scalar_formatted (valaddr + embedded_offset, type, format, 0, stream);
+ }
+ else
+ {
+ val_print_type_code_int (type, valaddr + embedded_offset, 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 + embedded_offset),
+ stream);
+ }
+ }
+ break;
+
+ case TYPE_CODE_CHAR:
+ format = format ? format : output_format;
+ if (format)
+ {
+ print_scalar_formatted (valaddr + embedded_offset, type, format, 0, stream);
+ }
+ else
+ {
+ fprintf_filtered (stream, TYPE_UNSIGNED (type) ? "%u" : "%d",
+ unpack_long (type, valaddr + embedded_offset));
+ fputs_filtered (" ", stream);
+ LA_PRINT_CHAR ((unsigned char) unpack_long (type, valaddr + embedded_offset), stream);
+ }
+ break;
+
+ case TYPE_CODE_FLT:
+ if (format)
+ {
+ print_scalar_formatted (valaddr + embedded_offset, type, format, 0, stream);
+ }
+ else
+ {
+ print_floating (valaddr + embedded_offset, type, stream);
+ }
+ break;
+
+ case TYPE_CODE_METHOD:
+ cp_print_class_method (valaddr + embedded_offset, lookup_pointer_type (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_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));
+ }
+ gdb_flush (stream);
+ return (0);
+}
+
+int
+c_value_print (val, stream, format, pretty)
+ value_ptr val;
+ GDB_FILE *stream;
+ int format;
+ enum val_prettyprint pretty;
+{
+ struct type *type = VALUE_TYPE (val);
+ struct type * real_type;
+ int full, top, using_enc;
+
+ /* 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_NAME (type) == NULL &&
+ TYPE_NAME (TYPE_TARGET_TYPE (type)) != NULL &&
+ STREQ (TYPE_NAME (TYPE_TARGET_TYPE (type)), "char"))
+ {
+ /* Print nothing */
+ }
+ else if (objectprint && (TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_CLASS))
+ {
+ /* Pointer to class, check real type of object */
+ fprintf_filtered (stream, "(");
+ type = value_rtti_target_type (val, &full, &top, &using_enc);
+ if (type)
+ {
+ /* RTTI entry found */
+ type = lookup_pointer_type (type);
+ type_print (type, "", stream, -1);
+ }
+ else
+ {
+ /* No RTTI fields, do whatever we can */
+ type = VALUE_ENCLOSING_TYPE (val);
+ type_print (type, "", stream, -1);
+ fprintf_filtered (stream, " ?");
+ }
+ fprintf_filtered (stream, ") ");
+ }
+ else
+ {
+ /* normal case */
+ fprintf_filtered (stream, "(");
+ type_print (type, "", stream, -1);
+ fprintf_filtered (stream, ") ");
+ }
+ }
+ if (objectprint && (TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_CLASS))
+ {
+ /* Attempt to determine real type of object */
+ real_type = value_rtti_type (val, &full, &top, &using_enc);
+ if (real_type)
+ {
+ /* We have RTTI information, so use it */
+ val = value_full_object (val, real_type, full, top, using_enc);
+ fprintf_filtered (stream, "(%s%s) ",
+ TYPE_NAME (real_type),
+ full ? "" : " [incomplete object]");
+ /* Print out object: enclosing type is same as real_type if full */
+ return val_print (VALUE_ENCLOSING_TYPE (val), VALUE_CONTENTS_ALL (val), 0,
+ VALUE_ADDRESS (val), stream, format, 1, 0, pretty);
+ }
+ else if (type != VALUE_ENCLOSING_TYPE (val))
+ {
+ /* No RTTI information, so let's do our best */
+ fprintf_filtered (stream, "(%s ?) ",
+ TYPE_NAME (VALUE_ENCLOSING_TYPE (val)));
+ return val_print (VALUE_ENCLOSING_TYPE (val), VALUE_CONTENTS_ALL (val), 0,
+ VALUE_ADDRESS (val), stream, format, 1, 0, pretty);
+ }
+ /* Otherwise, we end up at the return outside this "if" */
+ }
+
+ return val_print (type, VALUE_CONTENTS_ALL (val), VALUE_EMBEDDED_OFFSET (val),
+ VALUE_ADDRESS (val),
+ stream, format, 1, 0, pretty);
+}
diff --git a/gdb/call-cmds.h b/gdb/call-cmds.h
new file mode 100644
index 00000000000..4c02004f075
--- /dev/null
+++ b/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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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/gdb/ch-exp.c b/gdb/ch-exp.c
new file mode 100644
index 00000000000..45436a3bee8
--- /dev/null
+++ b/gdb/ch-exp.c
@@ -0,0 +1,2169 @@
+/* Parser for GNU CHILL (CCITT High-Level Language) -*- C -*-
+ Copyright (C) 1992, 1993, 1995 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 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 "gdb_string.h"
+#include <ctype.h>
+#include "expression.h"
+#include "language.h"
+#include "value.h"
+#include "parser-defs.h"
+#include "ch-lang.h"
+#include "bfd.h" /* Required by objfiles.h. */
+#include "symfile.h" /* Required by objfiles.h. */
+#include "objfiles.h" /* For have_full_symbols and have_partial_symbols */
+
+#ifdef __GNUC__
+#define INLINE __inline__
+#endif
+
+typedef union
+
+ {
+ LONGEST lval;
+ ULONGEST 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;
+ }YYSTYPE;
+
+enum ch_terminal {
+ END_TOKEN = 0,
+ /* '\001' ... '\xff' come first. */
+ OPEN_PAREN = '(',
+ TOKEN_NOT_READ = 999,
+ INTEGER_LITERAL,
+ BOOLEAN_LITERAL,
+ CHARACTER_LITERAL,
+ FLOAT_LITERAL,
+ GENERAL_PROCEDURE_NAME,
+ LOCATION_NAME,
+ EMPTINESS_LITERAL,
+ CHARACTER_STRING_LITERAL,
+ BIT_STRING_LITERAL,
+ TYPENAME,
+ DOT_FIELD_NAME, /* '.' followed by <field name> */
+ CASE,
+ OF,
+ ESAC,
+ LOGIOR,
+ ORIF,
+ LOGXOR,
+ LOGAND,
+ ANDIF,
+ NOTEQUAL,
+ GEQ,
+ LEQ,
+ IN,
+ SLASH_SLASH,
+ MOD,
+ REM,
+ NOT,
+ POINTER,
+ RECEIVE,
+ UP,
+ IF,
+ THEN,
+ ELSE,
+ FI,
+ ELSIF,
+ ILLEGAL_TOKEN,
+ NUM,
+ PRED,
+ SUCC,
+ ABS,
+ CARD,
+ MAX_TOKEN,
+ MIN_TOKEN,
+ ADDR_TOKEN,
+ SIZE,
+ UPPER,
+ LOWER,
+ LENGTH,
+ ARRAY,
+ GDB_VARIABLE,
+ GDB_ASSIGNMENT
+};
+
+/* Forward declarations. */
+
+static void write_lower_upper_value PARAMS ((enum exp_opcode, struct type *));
+static enum ch_terminal match_bitstring_literal PARAMS ((void));
+static enum ch_terminal match_integer_literal PARAMS ((void));
+static enum ch_terminal match_character_literal PARAMS ((void));
+static enum ch_terminal match_string_literal PARAMS ((void));
+static enum ch_terminal match_float_literal PARAMS ((void));
+static enum ch_terminal match_float_literal PARAMS ((void));
+static int decode_integer_literal PARAMS ((LONGEST *, char **));
+static int decode_integer_value PARAMS ((int, char **, LONGEST *));
+static char *match_simple_name_string PARAMS ((void));
+static void growbuf_by_size PARAMS ((int));
+static void parse_untyped_expr PARAMS ((void));
+static void parse_if_expression PARAMS ((void));
+static void parse_else_alternative PARAMS ((void));
+static void parse_then_alternative PARAMS ((void));
+static void parse_expr PARAMS ((void));
+static void parse_operand0 PARAMS ((void));
+static void parse_operand1 PARAMS ((void));
+static void parse_operand2 PARAMS ((void));
+static void parse_operand3 PARAMS ((void));
+static void parse_operand4 PARAMS ((void));
+static void parse_operand5 PARAMS ((void));
+static void parse_operand6 PARAMS ((void));
+static void parse_primval PARAMS ((void));
+static void parse_tuple PARAMS ((struct type *));
+static void parse_opt_element_list PARAMS ((struct type *));
+static void parse_tuple_element PARAMS ((struct type *));
+static void parse_named_record_element PARAMS ((void));
+static void parse_call PARAMS ((void));
+static struct type *parse_mode_or_normal_call PARAMS ((void));
+#if 0
+static struct type *parse_mode_call PARAMS ((void));
+#endif
+static void parse_unary_call PARAMS ((void));
+static int parse_opt_untyped_expr PARAMS ((void));
+static void parse_case_label PARAMS ((void));
+static int expect PARAMS ((enum ch_terminal, char *));
+static void parse_expr PARAMS ((void));
+static void parse_primval PARAMS ((void));
+static void parse_untyped_expr PARAMS ((void));
+static int parse_opt_untyped_expr PARAMS ((void));
+static void parse_if_expression_body PARAMS((void));
+static enum ch_terminal ch_lex PARAMS ((void));
+INLINE static enum ch_terminal PEEK_TOKEN PARAMS ((void));
+static enum ch_terminal peek_token_ PARAMS ((int));
+static void forward_token_ PARAMS ((void));
+static void require PARAMS ((enum ch_terminal));
+static int check_token PARAMS ((enum ch_terminal));
+
+#define MAX_LOOK_AHEAD 2
+static enum ch_terminal terminal_buffer[MAX_LOOK_AHEAD+1] = {
+ TOKEN_NOT_READ, TOKEN_NOT_READ, TOKEN_NOT_READ};
+static YYSTYPE yylval;
+static YYSTYPE val_buffer[MAX_LOOK_AHEAD+1];
+
+/*int current_token, lookahead_token;*/
+
+INLINE static enum ch_terminal
+PEEK_TOKEN()
+{
+ if (terminal_buffer[0] == TOKEN_NOT_READ)
+ {
+ terminal_buffer[0] = ch_lex ();
+ val_buffer[0] = yylval;
+ }
+ return terminal_buffer[0];
+}
+#define PEEK_LVAL() val_buffer[0]
+#define PEEK_TOKEN1() peek_token_(1)
+#define PEEK_TOKEN2() peek_token_(2)
+static enum ch_terminal
+peek_token_ (i)
+ int i;
+{
+ if (i > MAX_LOOK_AHEAD)
+ fatal ("internal error - too much lookahead");
+ if (terminal_buffer[i] == TOKEN_NOT_READ)
+ {
+ terminal_buffer[i] = ch_lex ();
+ val_buffer[i] = yylval;
+ }
+ return terminal_buffer[i];
+}
+
+#if 0
+
+static void
+pushback_token (code, node)
+ enum ch_terminal code;
+ YYSTYPE node;
+{
+ int i;
+ if (terminal_buffer[MAX_LOOK_AHEAD] != TOKEN_NOT_READ)
+ fatal ("internal error - cannot pushback token");
+ for (i = MAX_LOOK_AHEAD; i > 0; i--)
+ {
+ terminal_buffer[i] = terminal_buffer[i - 1];
+ val_buffer[i] = val_buffer[i - 1];
+ }
+ terminal_buffer[0] = code;
+ val_buffer[0] = node;
+}
+
+#endif
+
+static void
+forward_token_()
+{
+ int i;
+ for (i = 0; i < MAX_LOOK_AHEAD; i++)
+ {
+ terminal_buffer[i] = terminal_buffer[i+1];
+ val_buffer[i] = val_buffer[i+1];
+ }
+ terminal_buffer[MAX_LOOK_AHEAD] = TOKEN_NOT_READ;
+}
+#define FORWARD_TOKEN() forward_token_()
+
+/* Skip the next token.
+ if it isn't TOKEN, the parser is broken. */
+
+static void
+require(token)
+ enum ch_terminal token;
+{
+ if (PEEK_TOKEN() != token)
+ {
+ char buf[80];
+ sprintf (buf, "internal parser error - expected token %d", (int)token);
+ fatal(buf);
+ }
+ FORWARD_TOKEN();
+}
+
+static int
+check_token (token)
+ enum ch_terminal token;
+{
+ if (PEEK_TOKEN() != token)
+ return 0;
+ FORWARD_TOKEN ();
+ return 1;
+}
+
+/* return 0 if expected token was not found,
+ else return 1.
+*/
+static int
+expect (token, message)
+ enum ch_terminal token;
+ char *message;
+{
+ if (PEEK_TOKEN() != token)
+ {
+ if (message)
+ error (message);
+ else if (token < 256)
+ error ("syntax error - expected a '%c' here \"%s\"", token, lexptr);
+ else
+ error ("syntax error");
+ return 0;
+ }
+ else
+ FORWARD_TOKEN();
+ return 1;
+}
+
+#if 0
+static tree
+parse_opt_name_string (allow_all)
+ int allow_all; /* 1 if ALL is allowed as a postfix */
+{
+ int token = PEEK_TOKEN();
+ tree name;
+ if (token != NAME)
+ {
+ if (token == ALL && allow_all)
+ {
+ FORWARD_TOKEN ();
+ return ALL_POSTFIX;
+ }
+ return NULL_TREE;
+ }
+ name = PEEK_LVAL();
+ for (;;)
+ {
+ FORWARD_TOKEN ();
+ token = PEEK_TOKEN();
+ if (token != '!')
+ return name;
+ FORWARD_TOKEN();
+ token = PEEK_TOKEN();
+ if (token == ALL && allow_all)
+ return get_identifier3(IDENTIFIER_POINTER (name), "!", "*");
+ if (token != NAME)
+ {
+ if (pass == 1)
+ error ("'%s!' is not followed by an identifier",
+ IDENTIFIER_POINTER (name));
+ return name;
+ }
+ name = get_identifier3(IDENTIFIER_POINTER(name),
+ "!", IDENTIFIER_POINTER(PEEK_LVAL()));
+ }
+}
+
+static tree
+parse_simple_name_string ()
+{
+ int token = PEEK_TOKEN();
+ tree name;
+ if (token != NAME)
+ {
+ error ("expected a name here");
+ return error_mark_node;
+ }
+ name = PEEK_LVAL ();
+ FORWARD_TOKEN ();
+ return name;
+}
+
+static tree
+parse_name_string ()
+{
+ tree name = parse_opt_name_string (0);
+ if (name)
+ return name;
+ if (pass == 1)
+ error ("expected a name string here");
+ return error_mark_node;
+}
+
+/* Matches: <name_string>
+ Returns if pass 1: the identifier.
+ Returns if pass 2: a decl or value for identifier. */
+
+static tree
+parse_name ()
+{
+ tree name = parse_name_string ();
+ if (pass == 1 || ignoring)
+ return name;
+ else
+ {
+ tree decl = lookup_name (name);
+ if (decl == NULL_TREE)
+ {
+ error ("`%s' undeclared", IDENTIFIER_POINTER (name));
+ return error_mark_node;
+ }
+ else if (TREE_CODE (TREE_TYPE (decl)) == ERROR_MARK)
+ return error_mark_node;
+ else if (TREE_CODE (decl) == CONST_DECL)
+ return DECL_INITIAL (decl);
+ else if (TREE_CODE (TREE_TYPE (decl)) == REFERENCE_TYPE)
+ return convert_from_reference (decl);
+ else
+ return decl;
+ }
+}
+#endif
+
+#if 0
+static void
+pushback_paren_expr (expr)
+ tree expr;
+{
+ if (pass == 1 && !ignoring)
+ expr = build1 (PAREN_EXPR, NULL_TREE, expr);
+ pushback_token (EXPR, expr);
+}
+#endif
+
+/* Matches: <case label> */
+
+static void
+parse_case_label ()
+{
+ if (check_token (ELSE))
+ error ("ELSE in tuples labels not implemented");
+ /* Does not handle the case of a mode name. FIXME */
+ parse_expr ();
+ if (check_token (':'))
+ {
+ parse_expr ();
+ write_exp_elt_opcode (BINOP_RANGE);
+ }
+}
+
+static int
+parse_opt_untyped_expr ()
+{
+ switch (PEEK_TOKEN ())
+ {
+ case ',':
+ case ':':
+ case ')':
+ return 0;
+ default:
+ parse_untyped_expr ();
+ return 1;
+ }
+}
+
+static void
+parse_unary_call ()
+{
+ FORWARD_TOKEN ();
+ expect ('(', NULL);
+ parse_expr ();
+ expect (')', NULL);
+}
+
+/* Parse NAME '(' MODENAME ')'. */
+
+#if 0
+
+static struct type *
+parse_mode_call ()
+{
+ struct type *type;
+ FORWARD_TOKEN ();
+ expect ('(', NULL);
+ if (PEEK_TOKEN () != TYPENAME)
+ error ("expect MODENAME here `%s'", lexptr);
+ type = PEEK_LVAL().tsym.type;
+ FORWARD_TOKEN ();
+ expect (')', NULL);
+ return type;
+}
+
+#endif
+
+static struct type *
+parse_mode_or_normal_call ()
+{
+ struct type *type;
+ FORWARD_TOKEN ();
+ expect ('(', NULL);
+ if (PEEK_TOKEN () == TYPENAME)
+ {
+ type = PEEK_LVAL().tsym.type;
+ FORWARD_TOKEN ();
+ }
+ else
+ {
+ parse_expr ();
+ type = NULL;
+ }
+ expect (')', NULL);
+ return type;
+}
+
+/* Parse something that looks like a function call.
+ Assume we have parsed the function, and are at the '('. */
+
+static void
+parse_call ()
+{
+ int arg_count;
+ require ('(');
+ /* This is to save the value of arglist_len
+ being accumulated for each dimension. */
+ start_arglist ();
+ if (parse_opt_untyped_expr ())
+ {
+ int tok = PEEK_TOKEN ();
+ arglist_len = 1;
+ if (tok == UP || tok == ':')
+ {
+ FORWARD_TOKEN ();
+ parse_expr ();
+ expect (')', "expected ')' to terminate slice");
+ end_arglist ();
+ write_exp_elt_opcode (tok == UP ? TERNOP_SLICE_COUNT
+ : TERNOP_SLICE);
+ return;
+ }
+ while (check_token (','))
+ {
+ parse_untyped_expr ();
+ arglist_len++;
+ }
+ }
+ else
+ arglist_len = 0;
+ expect (')', NULL);
+ arg_count = end_arglist ();
+ write_exp_elt_opcode (MULTI_SUBSCRIPT);
+ write_exp_elt_longcst (arg_count);
+ write_exp_elt_opcode (MULTI_SUBSCRIPT);
+}
+
+static void
+parse_named_record_element ()
+{
+ struct stoken label;
+ char buf[256];
+
+ label = PEEK_LVAL ().sval;
+ sprintf (buf, "expected a field name here `%s'", lexptr);
+ expect (DOT_FIELD_NAME, buf);
+ if (check_token (','))
+ parse_named_record_element ();
+ else if (check_token (':'))
+ parse_expr ();
+ else
+ error ("syntax error near `%s' in named record tuple element", lexptr);
+ write_exp_elt_opcode (OP_LABELED);
+ write_exp_string (label);
+ write_exp_elt_opcode (OP_LABELED);
+}
+
+/* Returns one or more TREE_LIST nodes, in reverse order. */
+
+static void
+parse_tuple_element (type)
+ struct type *type;
+{
+ if (PEEK_TOKEN () == DOT_FIELD_NAME)
+ {
+ /* Parse a labelled structure tuple. */
+ parse_named_record_element ();
+ return;
+ }
+
+ if (check_token ('('))
+ {
+ if (check_token ('*'))
+ {
+ expect (')', "missing ')' after '*' case label list");
+ if (type)
+ {
+ if (TYPE_CODE (type) == TYPE_CODE_ARRAY)
+ {
+ /* do this as a range from low to high */
+ struct type *range_type = TYPE_FIELD_TYPE (type, 0);
+ LONGEST low_bound, high_bound;
+ if (get_discrete_bounds (range_type, &low_bound, &high_bound) < 0)
+ error ("cannot determine bounds for (*)");
+ /* lower bound */
+ write_exp_elt_opcode (OP_LONG);
+ write_exp_elt_type (range_type);
+ write_exp_elt_longcst (low_bound);
+ write_exp_elt_opcode (OP_LONG);
+ /* upper bound */
+ write_exp_elt_opcode (OP_LONG);
+ write_exp_elt_type (range_type);
+ write_exp_elt_longcst (high_bound);
+ write_exp_elt_opcode (OP_LONG);
+ write_exp_elt_opcode (BINOP_RANGE);
+ }
+ else
+ error ("(*) in invalid context");
+ }
+ else
+ error ("(*) only possible with modename in front of tuple (mode[..])");
+ }
+ else
+ {
+ parse_case_label ();
+ while (check_token (','))
+ {
+ parse_case_label ();
+ write_exp_elt_opcode (BINOP_COMMA);
+ }
+ expect (')', NULL);
+ }
+ }
+ else
+ parse_untyped_expr ();
+ if (check_token (':'))
+ {
+ /* A powerset range or a labeled Array. */
+ parse_untyped_expr ();
+ write_exp_elt_opcode (BINOP_RANGE);
+ }
+}
+
+/* Matches: a COMMA-separated list of tuple elements.
+ Returns a list (of TREE_LIST nodes). */
+static void
+parse_opt_element_list (type)
+ struct type *type;
+{
+ arglist_len = 0;
+ if (PEEK_TOKEN () == ']')
+ return;
+ for (;;)
+ {
+ parse_tuple_element (type);
+ arglist_len++;
+ if (PEEK_TOKEN () == ']')
+ break;
+ if (!check_token (','))
+ error ("bad syntax in tuple");
+ }
+}
+
+/* Parses: '[' elements ']'
+ If modename is non-NULL it prefixed the tuple. */
+
+static void
+parse_tuple (mode)
+ struct type *mode;
+{
+ struct type *type;
+ if (mode)
+ type = check_typedef (mode);
+ else
+ type = 0;
+ require ('[');
+ start_arglist ();
+ parse_opt_element_list (type);
+ expect (']', "missing ']' after tuple");
+ write_exp_elt_opcode (OP_ARRAY);
+ write_exp_elt_longcst ((LONGEST) 0);
+ write_exp_elt_longcst ((LONGEST) end_arglist () - 1);
+ write_exp_elt_opcode (OP_ARRAY);
+ if (type)
+ {
+ if (TYPE_CODE (type) != TYPE_CODE_ARRAY
+ && TYPE_CODE (type) != TYPE_CODE_STRUCT
+ && TYPE_CODE (type) != TYPE_CODE_SET)
+ error ("invalid tuple mode");
+ write_exp_elt_opcode (UNOP_CAST);
+ write_exp_elt_type (mode);
+ write_exp_elt_opcode (UNOP_CAST);
+ }
+}
+
+static void
+parse_primval ()
+{
+ struct type *type;
+ enum exp_opcode op;
+ char *op_name;
+ switch (PEEK_TOKEN ())
+ {
+ case INTEGER_LITERAL:
+ case CHARACTER_LITERAL:
+ write_exp_elt_opcode (OP_LONG);
+ write_exp_elt_type (PEEK_LVAL ().typed_val.type);
+ write_exp_elt_longcst (PEEK_LVAL ().typed_val.val);
+ write_exp_elt_opcode (OP_LONG);
+ FORWARD_TOKEN ();
+ break;
+ case BOOLEAN_LITERAL:
+ write_exp_elt_opcode (OP_BOOL);
+ write_exp_elt_longcst ((LONGEST) PEEK_LVAL ().ulval);
+ write_exp_elt_opcode (OP_BOOL);
+ FORWARD_TOKEN ();
+ break;
+ case FLOAT_LITERAL:
+ write_exp_elt_opcode (OP_DOUBLE);
+ write_exp_elt_type (builtin_type_double);
+ write_exp_elt_dblcst (PEEK_LVAL ().dval);
+ write_exp_elt_opcode (OP_DOUBLE);
+ FORWARD_TOKEN ();
+ break;
+ case EMPTINESS_LITERAL:
+ write_exp_elt_opcode (OP_LONG);
+ write_exp_elt_type (lookup_pointer_type (builtin_type_void));
+ write_exp_elt_longcst (0);
+ write_exp_elt_opcode (OP_LONG);
+ FORWARD_TOKEN ();
+ break;
+ case CHARACTER_STRING_LITERAL:
+ write_exp_elt_opcode (OP_STRING);
+ write_exp_string (PEEK_LVAL ().sval);
+ write_exp_elt_opcode (OP_STRING);
+ FORWARD_TOKEN ();
+ break;
+ case BIT_STRING_LITERAL:
+ write_exp_elt_opcode (OP_BITSTRING);
+ write_exp_bitstring (PEEK_LVAL ().sval);
+ write_exp_elt_opcode (OP_BITSTRING);
+ FORWARD_TOKEN ();
+ break;
+ case ARRAY:
+ FORWARD_TOKEN ();
+ /* This is pseudo-Chill, similar to C's '(TYPE[])EXPR'
+ which casts to an artificial array. */
+ expect ('(', NULL);
+ expect (')', NULL);
+ if (PEEK_TOKEN () != TYPENAME)
+ error ("missing MODENAME after ARRAY()");
+ type = PEEK_LVAL().tsym.type;
+ FORWARD_TOKEN ();
+ expect ('(', NULL);
+ parse_expr ();
+ expect (')', "missing right parenthesis");
+ type = create_array_type ((struct type *) NULL, type,
+ create_range_type ((struct type *) NULL,
+ builtin_type_int, 0, 0));
+ TYPE_ARRAY_UPPER_BOUND_TYPE(type) = BOUND_CANNOT_BE_DETERMINED;
+ write_exp_elt_opcode (UNOP_CAST);
+ write_exp_elt_type (type);
+ write_exp_elt_opcode (UNOP_CAST);
+ break;
+#if 0
+ case CONST:
+ case EXPR:
+ val = PEEK_LVAL();
+ FORWARD_TOKEN ();
+ break;
+#endif
+ case '(':
+ FORWARD_TOKEN ();
+ parse_expr ();
+ expect (')', "missing right parenthesis");
+ break;
+ case '[':
+ parse_tuple (NULL);
+ break;
+ case GENERAL_PROCEDURE_NAME:
+ case LOCATION_NAME:
+ write_exp_elt_opcode (OP_VAR_VALUE);
+ write_exp_elt_block (NULL);
+ write_exp_elt_sym (PEEK_LVAL ().ssym.sym);
+ write_exp_elt_opcode (OP_VAR_VALUE);
+ FORWARD_TOKEN ();
+ break;
+ case GDB_VARIABLE: /* gdb specific */
+ FORWARD_TOKEN ();
+ break;
+ case NUM:
+ parse_unary_call ();
+ write_exp_elt_opcode (UNOP_CAST);
+ write_exp_elt_type (builtin_type_int);
+ write_exp_elt_opcode (UNOP_CAST);
+ break;
+ case CARD:
+ parse_unary_call ();
+ write_exp_elt_opcode (UNOP_CARD);
+ break;
+ case MAX_TOKEN:
+ parse_unary_call ();
+ write_exp_elt_opcode (UNOP_CHMAX);
+ break;
+ case MIN_TOKEN:
+ parse_unary_call ();
+ write_exp_elt_opcode (UNOP_CHMIN);
+ break;
+ case PRED: op_name = "PRED"; goto unimplemented_unary_builtin;
+ case SUCC: op_name = "SUCC"; goto unimplemented_unary_builtin;
+ case ABS: op_name = "ABS"; goto unimplemented_unary_builtin;
+ unimplemented_unary_builtin:
+ parse_unary_call ();
+ error ("not implemented: %s builtin function", op_name);
+ break;
+ case ADDR_TOKEN:
+ parse_unary_call ();
+ write_exp_elt_opcode (UNOP_ADDR);
+ break;
+ case SIZE:
+ type = parse_mode_or_normal_call ();
+ if (type)
+ { write_exp_elt_opcode (OP_LONG);
+ write_exp_elt_type (builtin_type_int);
+ CHECK_TYPEDEF (type);
+ write_exp_elt_longcst ((LONGEST) TYPE_LENGTH (type));
+ write_exp_elt_opcode (OP_LONG);
+ }
+ else
+ write_exp_elt_opcode (UNOP_SIZEOF);
+ break;
+ case LOWER:
+ op = UNOP_LOWER;
+ goto lower_upper;
+ case UPPER:
+ op = UNOP_UPPER;
+ goto lower_upper;
+ lower_upper:
+ type = parse_mode_or_normal_call ();
+ write_lower_upper_value (op, type);
+ break;
+ case LENGTH:
+ parse_unary_call ();
+ write_exp_elt_opcode (UNOP_LENGTH);
+ break;
+ case TYPENAME:
+ type = PEEK_LVAL ().tsym.type;
+ FORWARD_TOKEN ();
+ switch (PEEK_TOKEN())
+ {
+ case '[':
+ parse_tuple (type);
+ break;
+ case '(':
+ FORWARD_TOKEN ();
+ parse_expr ();
+ expect (')', "missing right parenthesis");
+ write_exp_elt_opcode (UNOP_CAST);
+ write_exp_elt_type (type);
+ write_exp_elt_opcode (UNOP_CAST);
+ break;
+ default:
+ error ("typename in invalid context");
+ }
+ break;
+
+ default:
+ error ("invalid expression syntax at `%s'", lexptr);
+ }
+ for (;;)
+ {
+ switch (PEEK_TOKEN ())
+ {
+ case DOT_FIELD_NAME:
+ write_exp_elt_opcode (STRUCTOP_STRUCT);
+ write_exp_string (PEEK_LVAL ().sval);
+ write_exp_elt_opcode (STRUCTOP_STRUCT);
+ FORWARD_TOKEN ();
+ continue;
+ case POINTER:
+ FORWARD_TOKEN ();
+ if (PEEK_TOKEN () == TYPENAME)
+ {
+ type = PEEK_LVAL ().tsym.type;
+ write_exp_elt_opcode (UNOP_CAST);
+ write_exp_elt_type (lookup_pointer_type (type));
+ write_exp_elt_opcode (UNOP_CAST);
+ FORWARD_TOKEN ();
+ }
+ write_exp_elt_opcode (UNOP_IND);
+ continue;
+ case OPEN_PAREN:
+ parse_call ();
+ continue;
+ case CHARACTER_STRING_LITERAL:
+ case CHARACTER_LITERAL:
+ case BIT_STRING_LITERAL:
+ /* Handle string repetition. (See comment in parse_operand5.) */
+ parse_primval ();
+ write_exp_elt_opcode (MULTI_SUBSCRIPT);
+ write_exp_elt_longcst (1);
+ write_exp_elt_opcode (MULTI_SUBSCRIPT);
+ continue;
+ case END_TOKEN:
+ case TOKEN_NOT_READ:
+ case INTEGER_LITERAL:
+ case BOOLEAN_LITERAL:
+ case FLOAT_LITERAL:
+ case GENERAL_PROCEDURE_NAME:
+ case LOCATION_NAME:
+ case EMPTINESS_LITERAL:
+ case TYPENAME:
+ case CASE:
+ case OF:
+ case ESAC:
+ case LOGIOR:
+ case ORIF:
+ case LOGXOR:
+ case LOGAND:
+ case ANDIF:
+ case NOTEQUAL:
+ case GEQ:
+ case LEQ:
+ case IN:
+ case SLASH_SLASH:
+ case MOD:
+ case REM:
+ case NOT:
+ case RECEIVE:
+ case UP:
+ case IF:
+ case THEN:
+ case ELSE:
+ case FI:
+ case ELSIF:
+ case ILLEGAL_TOKEN:
+ case NUM:
+ case PRED:
+ case SUCC:
+ case ABS:
+ case CARD:
+ case MAX_TOKEN:
+ case MIN_TOKEN:
+ case ADDR_TOKEN:
+ case SIZE:
+ case UPPER:
+ case LOWER:
+ case LENGTH:
+ case ARRAY:
+ case GDB_VARIABLE:
+ case GDB_ASSIGNMENT:
+ break;
+ }
+ break;
+ }
+ return;
+}
+
+static void
+parse_operand6 ()
+{
+ if (check_token (RECEIVE))
+ {
+ parse_primval ();
+ error ("not implemented: RECEIVE expression");
+ }
+ else if (check_token (POINTER))
+ {
+ parse_primval ();
+ write_exp_elt_opcode (UNOP_ADDR);
+ }
+ else
+ parse_primval();
+}
+
+static void
+parse_operand5()
+{
+ enum exp_opcode op;
+ /* We are supposed to be looking for a <string repetition operator>,
+ but in general we can't distinguish that from a parenthesized
+ expression. This is especially difficult if we allow the
+ string operand to be a constant expression (as requested by
+ some users), and not just a string literal.
+ Consider: LPRN expr RPRN LPRN expr RPRN
+ Is that a function call or string repetition?
+ Instead, we handle string repetition in parse_primval,
+ and build_generalized_call. */
+ switch (PEEK_TOKEN())
+ {
+ case NOT: op = UNOP_LOGICAL_NOT; break;
+ case '-': op = UNOP_NEG; break;
+ default:
+ op = OP_NULL;
+ }
+ if (op != OP_NULL)
+ FORWARD_TOKEN();
+ parse_operand6();
+ if (op != OP_NULL)
+ write_exp_elt_opcode (op);
+}
+
+static void
+parse_operand4 ()
+{
+ enum exp_opcode op;
+ parse_operand5();
+ for (;;)
+ {
+ switch (PEEK_TOKEN())
+ {
+ case '*': op = BINOP_MUL; break;
+ case '/': op = BINOP_DIV; break;
+ case MOD: op = BINOP_MOD; break;
+ case REM: op = BINOP_REM; break;
+ default:
+ return;
+ }
+ FORWARD_TOKEN();
+ parse_operand5();
+ write_exp_elt_opcode (op);
+ }
+}
+
+static void
+parse_operand3 ()
+{
+ enum exp_opcode op;
+ parse_operand4 ();
+ for (;;)
+ {
+ switch (PEEK_TOKEN())
+ {
+ case '+': op = BINOP_ADD; break;
+ case '-': op = BINOP_SUB; break;
+ case SLASH_SLASH: op = BINOP_CONCAT; break;
+ default:
+ return;
+ }
+ FORWARD_TOKEN();
+ parse_operand4();
+ write_exp_elt_opcode (op);
+ }
+}
+
+static void
+parse_operand2 ()
+{
+ enum exp_opcode op;
+ parse_operand3 ();
+ for (;;)
+ {
+ if (check_token (IN))
+ {
+ parse_operand3();
+ write_exp_elt_opcode (BINOP_IN);
+ }
+ else
+ {
+ switch (PEEK_TOKEN())
+ {
+ case '>': op = BINOP_GTR; break;
+ case GEQ: op = BINOP_GEQ; break;
+ case '<': op = BINOP_LESS; break;
+ case LEQ: op = BINOP_LEQ; break;
+ case '=': op = BINOP_EQUAL; break;
+ case NOTEQUAL: op = BINOP_NOTEQUAL; break;
+ default:
+ return;
+ }
+ FORWARD_TOKEN();
+ parse_operand3();
+ write_exp_elt_opcode (op);
+ }
+ }
+}
+
+static void
+parse_operand1 ()
+{
+ enum exp_opcode op;
+ parse_operand2 ();
+ for (;;)
+ {
+ switch (PEEK_TOKEN())
+ {
+ case LOGAND: op = BINOP_BITWISE_AND; break;
+ case ANDIF: op = BINOP_LOGICAL_AND; break;
+ default:
+ return;
+ }
+ FORWARD_TOKEN();
+ parse_operand2();
+ write_exp_elt_opcode (op);
+ }
+}
+
+static void
+parse_operand0 ()
+{
+ enum exp_opcode op;
+ parse_operand1();
+ for (;;)
+ {
+ switch (PEEK_TOKEN())
+ {
+ case LOGIOR: op = BINOP_BITWISE_IOR; break;
+ case LOGXOR: op = BINOP_BITWISE_XOR; break;
+ case ORIF: op = BINOP_LOGICAL_OR; break;
+ default:
+ return;
+ }
+ FORWARD_TOKEN();
+ parse_operand1();
+ write_exp_elt_opcode (op);
+ }
+}
+
+static void
+parse_expr ()
+{
+ parse_operand0 ();
+ if (check_token (GDB_ASSIGNMENT))
+ {
+ parse_expr ();
+ write_exp_elt_opcode (BINOP_ASSIGN);
+ }
+}
+
+static void
+parse_then_alternative ()
+{
+ expect (THEN, "missing 'THEN' in 'IF' expression");
+ parse_expr ();
+}
+
+static void
+parse_else_alternative ()
+{
+ if (check_token (ELSIF))
+ parse_if_expression_body ();
+ else if (check_token (ELSE))
+ parse_expr ();
+ else
+ error ("missing ELSE/ELSIF in IF expression");
+}
+
+/* Matches: <boolean expression> <then alternative> <else alternative> */
+
+static void
+parse_if_expression_body ()
+{
+ parse_expr ();
+ parse_then_alternative ();
+ parse_else_alternative ();
+ write_exp_elt_opcode (TERNOP_COND);
+}
+
+static void
+parse_if_expression ()
+{
+ require (IF);
+ parse_if_expression_body ();
+ expect (FI, "missing 'FI' at end of conditional expression");
+}
+
+/* An <untyped_expr> is a superset of <expr>. It also includes
+ <conditional expressions> and untyped <tuples>, whose types
+ are not given by their constituents. Hence, these are only
+ allowed in certain contexts that expect a certain type.
+ You should call convert() to fix up the <untyped_expr>. */
+
+static void
+parse_untyped_expr ()
+{
+ switch (PEEK_TOKEN())
+ {
+ case IF:
+ parse_if_expression ();
+ return;
+ case CASE:
+ error ("not implemented: CASE expression");
+ case '(':
+ switch (PEEK_TOKEN1())
+ {
+ case IF:
+ case CASE:
+ goto skip_lprn;
+ case '[':
+ skip_lprn:
+ FORWARD_TOKEN ();
+ parse_untyped_expr ();
+ expect (')', "missing ')'");
+ return;
+ default: ;
+ /* fall through */
+ }
+ default:
+ parse_operand0 ();
+ }
+}
+
+int
+chill_parse ()
+{
+ terminal_buffer[0] = TOKEN_NOT_READ;
+ if (PEEK_TOKEN () == TYPENAME && PEEK_TOKEN1 () == END_TOKEN)
+ {
+ write_exp_elt_opcode(OP_TYPE);
+ write_exp_elt_type(PEEK_LVAL ().tsym.type);
+ write_exp_elt_opcode(OP_TYPE);
+ FORWARD_TOKEN ();
+ }
+ else
+ parse_expr ();
+ if (terminal_buffer[0] != END_TOKEN)
+ {
+ if (comma_terminates && terminal_buffer[0] == ',')
+ lexptr--; /* Put the comma back. */
+ else
+ error ("Junk after end of expression.");
+ }
+ return 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 *) xmalloc (tempbufsize);
+ }
+ else
+ {
+ tempbuf = (char *) xrealloc (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) || *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);
+ 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;
+ LONGEST *ivalptr;
+{
+ char *tokptr = *tokptrptr;
+ int temp;
+ int digits = 0;
+
+ while (*tokptr != '\0')
+ {
+ temp = *tokptr;
+ if (isupper (temp))
+ temp = tolower (temp);
+ 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)
+ LONGEST *valptr;
+ char **tokptrptr;
+{
+ char *tokptr = *tokptrptr;
+ int base = 0;
+ LONGEST 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 enum ch_terminal
+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 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 enum ch_terminal
+match_string_literal ()
+{
+ char *tokptr = lexptr;
+ int in_ctrlseq = 0;
+ LONGEST ival;
+
+ for (tempbufindex = 0, tokptr++; *tokptr != '\0'; tokptr++)
+ {
+ CHECKBUF (1);
+ tryagain: ;
+ if (in_ctrlseq)
+ {
+ /* skip possible whitespaces */
+ while ((*tokptr == ' ' || *tokptr == '\t') && *tokptr)
+ tokptr++;
+ if (*tokptr == ')')
+ {
+ in_ctrlseq = 0;
+ tokptr++;
+ goto tryagain;
+ }
+ else if (*tokptr != ',')
+ error ("Invalid control sequence");
+ tokptr++;
+ /* skip possible whitespaces */
+ while ((*tokptr == ' ' || *tokptr == '\t') && *tokptr)
+ tokptr++;
+ if (!decode_integer_literal (&ival, &tokptr))
+ error ("Invalid control sequence");
+ tokptr--;
+ }
+ else if (*tokptr == *lexptr)
+ {
+ if (*(tokptr + 1) == *lexptr)
+ {
+ ival = *tokptr++;
+ }
+ else
+ {
+ break;
+ }
+ }
+ else if (*tokptr == '^')
+ {
+ if (*(tokptr + 1) == '(')
+ {
+ in_ctrlseq = 1;
+ tokptr += 2;
+ if (!decode_integer_literal (&ival, &tokptr))
+ error ("Invalid control sequence");
+ tokptr--;
+ }
+ else if (*(tokptr + 1) == '^')
+ ival = *tokptr++;
+ else
+ error ("Invalid control sequence");
+ }
+ else
+ ival = *tokptr;
+ tempbuf[tempbufindex++] = ival;
+ }
+ if (in_ctrlseq)
+ error ("Invalid control sequence");
+
+ if (*tokptr == '\0' /* no terminator */
+ || (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.
+
+ Returns CHARACTER_LITERAL if a match is found.
+ */
+
+static enum ch_terminal
+match_character_literal ()
+{
+ char *tokptr = lexptr;
+ LONGEST ival = 0;
+
+ if ((*tokptr == 'c' || *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 == '^')
+ {
+ if (*(tokptr + 1) == '(')
+ {
+ /* 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 ')'. */
+ tokptr += 2;
+ if (!decode_integer_literal (&ival, &tokptr) || (*tokptr++ != ')'))
+ {
+ return (0);
+ }
+ }
+ else if (*(tokptr + 1) == '^')
+ {
+ ival = *tokptr;
+ tokptr += 2;
+ }
+ else
+ /* fail */
+ error ("Invalid control sequence");
+ }
+ else if (*tokptr == '\'')
+ {
+ /* this must be duplicated */
+ ival = *tokptr;
+ tokptr += 2;
+ }
+ 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 enum ch_terminal
+match_integer_literal ()
+{
+ char *tokptr = lexptr;
+ LONGEST ival;
+
+ if (!decode_integer_literal (&ival, &tokptr))
+ {
+ return (0);
+ }
+ else
+ {
+ yylval.typed_val.val = ival;
+#if defined(CC_HAS_LONG_LONG) && defined(__STDC__)
+ if (ival > (LONGEST)2147483647U || ival < -(LONGEST)2147483648U)
+ yylval.typed_val.type = builtin_type_long_long;
+ else
+#endif
+ 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 enum ch_terminal
+match_bitstring_literal ()
+{
+ register char *tokptr = lexptr;
+ int bitoffset = 0;
+ int bitcount = 0;
+ int bits_per_char;
+ int digit;
+
+ tempbufindex = 0;
+ CHECKBUF (1);
+ tempbuf[0] = 0;
+
+ /* Look for the required explicit base specifier. */
+
+ switch (*tokptr++)
+ {
+ case 'b':
+ case 'B':
+ bits_per_char = 1;
+ break;
+ case 'o':
+ case 'O':
+ bits_per_char = 3;
+ break;
+ case 'h':
+ case 'H':
+ bits_per_char = 4;
+ 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 = *tokptr;
+ if (isupper (digit))
+ digit = tolower (digit);
+ 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:
+ /* this is not a bitstring literal, probably an integer */
+ return 0;
+ }
+ if (digit >= 1 << bits_per_char)
+ {
+ /* Found something not in domain for current base. */
+ error ("Too-large digit in bitstring or integer.");
+ }
+ else
+ {
+ /* Extract bits from digit, packing them into the bitstring byte. */
+ int k = TARGET_BYTE_ORDER == BIG_ENDIAN ? bits_per_char - 1 : 0;
+ for (; TARGET_BYTE_ORDER == BIG_ENDIAN ? k >= 0 : k < bits_per_char;
+ TARGET_BYTE_ORDER == BIG_ENDIAN ? k-- : k++)
+ {
+ bitcount++;
+ if (digit & (1 << k))
+ {
+ tempbuf[tempbufindex] |=
+ (TARGET_BYTE_ORDER == BIG_ENDIAN)
+ ? (1 << (HOST_CHAR_BIT - 1 - bitoffset))
+ : (1 << bitoffset);
+ }
+ bitoffset++;
+ if (bitoffset == HOST_CHAR_BIT)
+ {
+ bitoffset = 0;
+ tempbufindex++;
+ CHECKBUF(1);
+ tempbuf[tempbufindex] = 0;
+ }
+ }
+ }
+ }
+
+ /* 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);
+ }
+}
+
+struct token
+{
+ char *operator;
+ int token;
+};
+
+static const struct token idtokentab[] =
+{
+ { "array", ARRAY },
+ { "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 },
+ { "up", UP },
+ { "addr", ADDR_TOKEN },
+ { "null", EMPTINESS_LITERAL }
+};
+
+static const struct token tokentab2[] =
+{
+ { ":=", GDB_ASSIGNMENT },
+ { "//", SLASH_SLASH },
+ { "->", POINTER },
+ { "/=", NOTEQUAL },
+ { "<=", LEQ },
+ { ">=", GEQ }
+};
+
+/* 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 enum ch_terminal
+ch_lex ()
+{
+ unsigned int i;
+ enum ch_terminal token;
+ char *inputname;
+ 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 END_TOKEN;
+ 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
+ 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 '$':
+ yylval.sval.ptr = lexptr;
+ do {
+ lexptr++;
+ } while (isalnum (*lexptr) || *lexptr == '_' || *lexptr == '$');
+ yylval.sval.length = lexptr - yylval.sval.ptr;
+ write_dollar_variable (yylval.sval);
+ return GDB_VARIABLE;
+ 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. */
+
+ inputname = match_simple_name_string ();
+
+ if (inputname != NULL)
+ {
+ char *simplename = (char*) alloca (strlen (inputname) + 1);
+
+ char *dptr = simplename, *sptr = inputname;
+ for (; *sptr; sptr++)
+ *dptr++ = isupper (*sptr) ? tolower(*sptr) : *sptr;
+ *dptr = '\0';
+
+ /* 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 (inputname, expression_context_block,
+ VAR_NAMESPACE, (int *) NULL,
+ (struct symtab **) NULL);
+ if (sym == NULL && strcmp (inputname, simplename) != 0)
+ {
+ 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.", inputname);
+ break;
+ case LOC_UNRESOLVED:
+ error ("unhandled SYMBOL_CLASS in ch_lex()");
+ 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.", inputname);
+ }
+ }
+
+ /* Catch single character tokens which are not part of some
+ longer token. */
+
+ switch (*lexptr)
+ {
+ case '.': /* Not float for example. */
+ lexptr++;
+ while (isspace (*lexptr)) lexptr++;
+ inputname = match_simple_name_string ();
+ if (!inputname)
+ return '.';
+ return DOT_FIELD_NAME;
+ }
+
+ return (ILLEGAL_TOKEN);
+}
+
+static void
+write_lower_upper_value (opcode, type)
+ enum exp_opcode opcode; /* Either UNOP_LOWER or UNOP_UPPER */
+ struct type *type;
+{
+ if (type == NULL)
+ write_exp_elt_opcode (opcode);
+ else
+ {
+ struct type *result_type;
+ LONGEST val = type_lower_upper (opcode, type, &result_type);
+ write_exp_elt_opcode (OP_LONG);
+ write_exp_elt_type (result_type);
+ write_exp_elt_longcst (val);
+ write_exp_elt_opcode (OP_LONG);
+ }
+}
+
+void
+chill_error (msg)
+ char *msg;
+{
+ /* Never used. */
+}
diff --git a/gdb/ch-lang.c b/gdb/ch-lang.c
new file mode 100644
index 00000000000..c54e8bb3619
--- /dev/null
+++ b/gdb/ch-lang.c
@@ -0,0 +1,675 @@
+/* Chill language support routines for GDB, the GNU debugger.
+ Copyright 1992, 1995, 1996 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "symtab.h"
+#include "gdbtypes.h"
+#include "value.h"
+#include "expression.h"
+#include "parser-defs.h"
+#include "language.h"
+#include "ch-lang.h"
+
+static value_ptr
+evaluate_subexp_chill PARAMS ((struct type *, struct expression *, int *, enum noside));
+
+static value_ptr
+value_chill_max_min PARAMS ((enum exp_opcode, value_ptr));
+
+static value_ptr
+value_chill_card PARAMS ((value_ptr));
+
+static value_ptr
+ value_chill_length PARAMS ((value_ptr));
+
+static struct type *
+chill_create_fundamental_type PARAMS ((struct objfile *, int));
+
+static void
+chill_printstr PARAMS ((GDB_FILE *stream, char *string, unsigned int length, int width, int force_ellipses));
+
+static void
+chill_printchar PARAMS ((int, GDB_FILE *));
+
+/* 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;
+{
+ const char *joiner = NULL;
+ char *demangled;
+ const char *cp = mangled;
+
+ while (*cp)
+ {
+ if (is_cplus_marker (*cp))
+ {
+ joiner = cp;
+ break;
+ }
+ cp++;
+ }
+ if (joiner != NULL && *(joiner + 1) == *joiner)
+ {
+ demangled = savestring (mangled, joiner - mangled);
+ }
+ else
+ {
+ demangled = NULL;
+ }
+ return (demangled);
+}
+
+static void
+chill_printchar (c, stream)
+ register int c;
+ GDB_FILE *stream;
+{
+ c &= 0xFF; /* Avoid sign bit follies */
+
+ if (PRINT_LITERAL_FORM (c))
+ {
+ if (c == '\'' || c == '^')
+ fprintf_filtered (stream, "'%c%c'", c, c);
+ else
+ fprintf_filtered (stream, "'%c'", c);
+ }
+ else
+ {
+ fprintf_filtered (stream, "'^(%u)'", (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, width, force_ellipses)
+ GDB_FILE *stream;
+ char *string;
+ unsigned int length;
+ int width;
+ 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)
+ {
+ fputs_filtered ("\"\"", 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)
+ {
+ if (in_control_form)
+ fputs_filtered (")", stream);
+ 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 (! in_literal_form && ! in_control_form)
+ fputs_filtered ("\"", stream);
+ if (PRINT_LITERAL_FORM (c))
+ {
+ if (!in_literal_form)
+ {
+ if (in_control_form)
+ {
+ fputs_filtered (")", stream);
+ in_control_form = 0;
+ }
+ in_literal_form = 1;
+ }
+ fprintf_filtered (stream, "%c", c);
+ if (c == '"' || c == '^')
+ /* duplicate this one as must be done at input */
+ fprintf_filtered (stream, "%c", c);
+ }
+ else
+ {
+ if (!in_control_form)
+ {
+ if (in_literal_form)
+ {
+ in_literal_form = 0;
+ }
+ fputs_filtered ("^(", stream);
+ in_control_form = 1;
+ }
+ else
+ fprintf_filtered (stream, ",");
+ c = c & 0xff;
+ fprintf_filtered (stream, "%u", (unsigned int) c);
+ }
+ ++things_printed;
+ }
+ }
+
+ /* Terminate the quotes if necessary. */
+ if (in_control_form)
+ {
+ fputs_filtered (")", stream);
+ }
+ 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, 0, "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, 0, "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, 0, "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},
+ {"SIZE",UNOP_SIZEOF, PREC_BUILTIN_FUNCTION, 0},
+ {"LOWER",UNOP_LOWER, PREC_BUILTIN_FUNCTION, 0},
+ {"UPPER",UNOP_UPPER, PREC_BUILTIN_FUNCTION, 0},
+ {"CARD",UNOP_CARD, PREC_BUILTIN_FUNCTION, 0},
+ {"MAX",UNOP_CHMAX, PREC_BUILTIN_FUNCTION, 0},
+ {"MIN",UNOP_CHMIN, PREC_BUILTIN_FUNCTION, 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},
+ {"->", UNOP_IND, PREC_SUFFIX, 1},
+ {"->", UNOP_ADDR, PREC_PREFIX, 0},
+ {":", BINOP_RANGE, PREC_ASSIGN, 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_PTR (chill_builtin_types[]) =
+{
+ &builtin_type_chill_bool,
+ &builtin_type_chill_char,
+ &builtin_type_chill_long,
+ &builtin_type_chill_ulong,
+ &builtin_type_chill_real,
+ 0
+};
+
+/* Calculate LOWER or UPPER of TYPE.
+ Returns the result as an integer.
+ *RESULT_TYPE is the appropriate type for the result. */
+
+LONGEST
+type_lower_upper (op, type, result_type)
+ enum exp_opcode op; /* Either UNOP_LOWER or UNOP_UPPER */
+ struct type *type;
+ struct type **result_type;
+{
+ LONGEST low, high;
+ *result_type = type;
+ CHECK_TYPEDEF (type);
+ switch (TYPE_CODE (type))
+ {
+ case TYPE_CODE_STRUCT:
+ *result_type = builtin_type_int;
+ if (chill_varying_type (type))
+ return type_lower_upper (op, TYPE_FIELD_TYPE (type, 1), result_type);
+ break;
+ case TYPE_CODE_ARRAY:
+ case TYPE_CODE_BITSTRING:
+ case TYPE_CODE_STRING:
+ type = TYPE_FIELD_TYPE (type, 0); /* Get index type */
+
+ /* ... fall through ... */
+ case TYPE_CODE_RANGE:
+ *result_type = TYPE_TARGET_TYPE (type);
+ return op == UNOP_LOWER ? TYPE_LOW_BOUND (type) : TYPE_HIGH_BOUND (type);
+
+ case TYPE_CODE_ENUM:
+ case TYPE_CODE_BOOL:
+ case TYPE_CODE_INT:
+ case TYPE_CODE_CHAR:
+ if (get_discrete_bounds (type, &low, &high) >= 0)
+ {
+ *result_type = type;
+ return op == UNOP_LOWER ? low : high;
+ }
+ break;
+ case TYPE_CODE_UNDEF:
+ case TYPE_CODE_PTR:
+ case TYPE_CODE_UNION:
+ case TYPE_CODE_FUNC:
+ case TYPE_CODE_FLT:
+ case TYPE_CODE_VOID:
+ case TYPE_CODE_SET:
+ case TYPE_CODE_ERROR:
+ case TYPE_CODE_MEMBER:
+ case TYPE_CODE_METHOD:
+ case TYPE_CODE_REF:
+ case TYPE_CODE_COMPLEX:
+ default:
+ break;
+ }
+ error ("unknown mode for LOWER/UPPER builtin");
+}
+
+static value_ptr
+value_chill_length (val)
+ value_ptr val;
+{
+ LONGEST tmp;
+ struct type *type = VALUE_TYPE (val);
+ struct type *ttype;
+ CHECK_TYPEDEF (type);
+ switch (TYPE_CODE (type))
+ {
+ case TYPE_CODE_ARRAY:
+ case TYPE_CODE_BITSTRING:
+ case TYPE_CODE_STRING:
+ tmp = type_lower_upper (UNOP_UPPER, type, &ttype)
+ - type_lower_upper (UNOP_LOWER, type, &ttype) + 1;
+ break;
+ case TYPE_CODE_STRUCT:
+ if (chill_varying_type (type))
+ {
+ tmp = unpack_long (TYPE_FIELD_TYPE (type, 0), VALUE_CONTENTS (val));
+ break;
+ }
+ /* ... else fall through ... */
+ default:
+ error ("bad argument to LENGTH builtin");
+ }
+ return value_from_longest (builtin_type_int, tmp);
+}
+
+static value_ptr
+value_chill_card (val)
+ value_ptr val;
+{
+ LONGEST tmp = 0;
+ struct type *type = VALUE_TYPE (val);
+ CHECK_TYPEDEF (type);
+
+ if (TYPE_CODE (type) == TYPE_CODE_SET)
+ {
+ struct type *range_type = TYPE_INDEX_TYPE (type);
+ LONGEST lower_bound, upper_bound;
+ int i;
+
+ get_discrete_bounds (range_type, &lower_bound, &upper_bound);
+ for (i = lower_bound; i <= upper_bound; i++)
+ if (value_bit_index (type, VALUE_CONTENTS (val), i) > 0)
+ tmp++;
+ }
+ else
+ error ("bad argument to CARD builtin");
+
+ return value_from_longest (builtin_type_int, tmp);
+}
+
+static value_ptr
+value_chill_max_min (op, val)
+ enum exp_opcode op;
+ value_ptr val;
+{
+ LONGEST tmp = 0;
+ struct type *type = VALUE_TYPE (val);
+ struct type *elttype;
+ CHECK_TYPEDEF (type);
+
+ if (TYPE_CODE (type) == TYPE_CODE_SET)
+ {
+ LONGEST lower_bound, upper_bound;
+ int i, empty = 1;
+
+ elttype = TYPE_INDEX_TYPE (type);
+ CHECK_TYPEDEF (elttype);
+ get_discrete_bounds (elttype, &lower_bound, &upper_bound);
+
+ if (op == UNOP_CHMAX)
+ {
+ for (i = upper_bound; i >= lower_bound; i--)
+ {
+ if (value_bit_index (type, VALUE_CONTENTS (val), i) > 0)
+ {
+ tmp = i;
+ empty = 0;
+ break;
+ }
+ }
+ }
+ else
+ {
+ for (i = lower_bound; i <= upper_bound; i++)
+ {
+ if (value_bit_index (type, VALUE_CONTENTS (val), i) > 0)
+ {
+ tmp = i;
+ empty = 0;
+ break;
+ }
+ }
+ }
+ if (empty)
+ error ("%s for empty powerset", op == UNOP_CHMAX ? "MAX" : "MIN");
+ }
+ else
+ error ("bad argument to %s builtin", op == UNOP_CHMAX ? "MAX" : "MIN");
+
+ return value_from_longest (TYPE_CODE (elttype) == TYPE_CODE_RANGE
+ ? TYPE_TARGET_TYPE (elttype)
+ : elttype,
+ tmp);
+}
+
+static value_ptr
+evaluate_subexp_chill (expect_type, exp, pos, noside)
+ struct type *expect_type;
+ register struct expression *exp;
+ register int *pos;
+ enum noside noside;
+{
+ int pc = *pos;
+ struct type *type;
+ int tem, nargs;
+ value_ptr arg1;
+ value_ptr *argvec;
+ enum exp_opcode op = exp->elts[*pos].opcode;
+ switch (op)
+ {
+ case MULTI_SUBSCRIPT:
+ if (noside == EVAL_SKIP)
+ break;
+ (*pos) += 3;
+ nargs = longest_to_int (exp->elts[pc + 1].longconst);
+ arg1 = evaluate_subexp_with_coercion (exp, pos, noside);
+ type = check_typedef (VALUE_TYPE (arg1));
+
+ if (nargs == 1 && TYPE_CODE (type) == TYPE_CODE_INT)
+ {
+ /* Looks like string repetition. */
+ value_ptr string = evaluate_subexp_with_coercion (exp, pos, noside);
+ return value_concat (arg1, string);
+ }
+
+ switch (TYPE_CODE (type))
+ {
+ case TYPE_CODE_PTR:
+ type = check_typedef (TYPE_TARGET_TYPE (type));
+ if (!type || TYPE_CODE (type) != TYPE_CODE_FUNC)
+ error ("reference value used as function");
+ /* ... fall through ... */
+ case TYPE_CODE_FUNC:
+ /* It's a function call. */
+ if (noside == EVAL_AVOID_SIDE_EFFECTS)
+ break;
+
+ /* Allocate arg vector, including space for the function to be
+ called in argvec[0] and a terminating NULL */
+ argvec = (value_ptr *) alloca (sizeof (value_ptr) * (nargs + 2));
+ argvec[0] = arg1;
+ tem = 1;
+ for (; tem <= nargs && tem <= TYPE_NFIELDS (type); tem++)
+ {
+ argvec[tem]
+ = evaluate_subexp_chill (TYPE_FIELD_TYPE (type, tem-1),
+ exp, pos, noside);
+ }
+ for (; tem <= nargs; tem++)
+ argvec[tem] = evaluate_subexp_with_coercion (exp, pos, noside);
+ argvec[tem] = 0; /* signal end of arglist */
+
+ return call_function_by_hand (argvec[0], nargs, argvec + 1);
+ default:
+ break;
+ }
+
+ while (nargs-- > 0)
+ {
+ value_ptr index = evaluate_subexp_with_coercion (exp, pos, noside);
+ arg1 = value_subscript (arg1, index);
+ }
+ return (arg1);
+
+ case UNOP_LOWER:
+ case UNOP_UPPER:
+ (*pos)++;
+ if (noside == EVAL_SKIP)
+ {
+ (*exp->language_defn->evaluate_exp) (NULL_TYPE, exp, pos, EVAL_SKIP);
+ goto nosideret;
+ }
+ arg1 = (*exp->language_defn->evaluate_exp) (NULL_TYPE, exp, pos,
+ EVAL_AVOID_SIDE_EFFECTS);
+ tem = type_lower_upper (op, VALUE_TYPE (arg1), &type);
+ return value_from_longest (type, tem);
+
+ case UNOP_LENGTH:
+ (*pos)++;
+ arg1 = (*exp->language_defn->evaluate_exp) (NULL_TYPE, exp, pos, noside);
+ return value_chill_length (arg1);
+
+ case UNOP_CARD:
+ (*pos)++;
+ arg1 = (*exp->language_defn->evaluate_exp) (NULL_TYPE, exp, pos, noside);
+ return value_chill_card (arg1);
+
+ case UNOP_CHMAX:
+ case UNOP_CHMIN:
+ (*pos)++;
+ arg1 = (*exp->language_defn->evaluate_exp) (NULL_TYPE, exp, pos, noside);
+ return value_chill_max_min (op, arg1);
+
+ case BINOP_COMMA:
+ error ("',' operator used in invalid context");
+
+ default:
+ break;
+ }
+
+ return evaluate_subexp_standard (expect_type, exp, pos, noside);
+ nosideret:
+ return value_from_longest (builtin_type_long, (LONGEST) 1);
+}
+
+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 */
+ evaluate_subexp_chill,
+ chill_printchar, /* print a character constant */
+ chill_printstr, /* function to print a string constant */
+ NULL, /* Function to print a single char */
+ 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 */
+ chill_value_print, /* Print a top-levl value */
+ {"", "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 */
+ 0, /* arrays are first-class (not c-style) */
+ 0, /* String lower bound */
+ &builtin_type_chill_char, /* Type of string elements */
+ 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/gdb/ch-lang.h b/gdb/ch-lang.h
new file mode 100644
index 00000000000..6525c3066c6
--- /dev/null
+++ b/gdb/ch-lang.h
@@ -0,0 +1,42 @@
+/* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifdef __STDC__ /* Forward decls for prototypes */
+struct value;
+#endif
+
+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 *, GDB_FILE *, int, int));
+
+extern int
+chill_val_print PARAMS ((struct type *, char *, int, CORE_ADDR, GDB_FILE *, int, int,
+ int, enum val_prettyprint));
+
+extern int
+chill_value_print PARAMS ((struct value *, GDB_FILE *,
+ int, enum val_prettyprint));
+
+extern LONGEST
+type_lower_upper PARAMS ((enum exp_opcode, struct type *, struct type **));
diff --git a/gdb/ch-typeprint.c b/gdb/ch-typeprint.c
new file mode 100644
index 00000000000..a6b1944d387
--- /dev/null
+++ b/gdb/ch-typeprint.c
@@ -0,0 +1,346 @@
+/* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 "typeprint.h"
+
+#include "gdb_string.h"
+#include <errno.h>
+
+static void
+chill_type_print_base PARAMS ((struct type *, GDB_FILE *, int, int));
+
+void
+chill_print_type (type, varstring, stream, show, level)
+ struct type *type;
+ char *varstring;
+ GDB_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;
+ GDB_FILE *stream;
+ int show;
+ int level;
+{
+ 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;
+ }
+
+ if (TYPE_CODE (type) != TYPE_CODE_TYPEDEF)
+ CHECK_TYPEDEF (type);
+
+ switch (TYPE_CODE (type))
+ {
+ case TYPE_CODE_TYPEDEF:
+ chill_type_print_base (TYPE_TARGET_TYPE (type), stream, 0, level);
+ break;
+ case TYPE_CODE_PTR:
+ if (TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_VOID)
+ {
+ fprintf_filtered (stream,
+ TYPE_NAME (type) ? TYPE_NAME (type) : "PTR");
+ break;
+ }
+ fprintf_filtered (stream, "REF ");
+ chill_type_print_base (TYPE_TARGET_TYPE (type), stream, 0, level);
+ break;
+
+ case TYPE_CODE_BOOL:
+ /* FIXME: we should probably just print the TYPE_NAME, in case
+ anyone ever fixes the compiler to give us the real names
+ in the presence of the chill equivalent of typedef (assuming
+ there is one). */
+ fprintf_filtered (stream,
+ TYPE_NAME (type) ? TYPE_NAME (type) : "BOOL");
+ break;
+
+ case TYPE_CODE_ARRAY:
+ fputs_filtered ("ARRAY (", stream);
+ range_type = TYPE_FIELD_TYPE (type, 0);
+ if (TYPE_CODE (range_type) != TYPE_CODE_RANGE)
+ chill_print_type (range_type, "", stream, 0, level);
+ else
+ {
+ index_type = TYPE_TARGET_TYPE (range_type);
+ low_bound = TYPE_FIELD_BITPOS (range_type, 0);
+ high_bound = TYPE_FIELD_BITPOS (range_type, 1);
+ 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, 0, level);
+ break;
+
+ case TYPE_CODE_BITSTRING:
+ fprintf_filtered (stream, "BOOLS (%d)",
+ TYPE_FIELD_BITPOS (TYPE_FIELD_TYPE(type,0), 1) + 1);
+ break;
+
+ case TYPE_CODE_SET:
+ fputs_filtered ("POWERSET ", stream);
+ chill_print_type (TYPE_INDEX_TYPE (type), "", stream,
+ show - 1, 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 ("CHARS (", 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, 0, 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 (");
+ len = TYPE_NFIELDS (type);
+ for (i = 0; i < len; i++)
+ {
+ struct type *param_type = TYPE_FIELD_TYPE (type, i);
+ if (i > 0)
+ {
+ fputs_filtered (", ", stream);
+ wrap_here (" ");
+ }
+ if (TYPE_CODE (param_type) == TYPE_CODE_REF)
+ {
+ chill_type_print_base (TYPE_TARGET_TYPE (param_type),
+ stream, 0, level);
+ fputs_filtered (" LOC", stream);
+ }
+ else
+ chill_type_print_base (param_type, stream, show, level);
+ }
+ fprintf_filtered (stream, ")");
+ if (TYPE_CODE (TYPE_TARGET_TYPE (type)) != TYPE_CODE_VOID)
+ {
+ fputs_filtered (" RETURNS (", stream);
+ chill_type_print_base (TYPE_TARGET_TYPE (type), stream, 0, level);
+ fputs_filtered (")", stream);
+ }
+ break;
+
+ case TYPE_CODE_STRUCT:
+ if (chill_varying_type (type))
+ {
+ chill_type_print_base (TYPE_FIELD_TYPE (type, 1),
+ stream, 0, level);
+ fputs_filtered (" VARYING", stream);
+ }
+ else
+ {
+ fprintf_filtered (stream, "STRUCT ");
+
+ 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++)
+ {
+ struct type *field_type = TYPE_FIELD_TYPE (type, i);
+ QUIT;
+ print_spaces_filtered (level + 4, stream);
+ if (TYPE_CODE (field_type) == TYPE_CODE_UNION)
+ { int j; /* variant number */
+ fputs_filtered ("CASE OF\n", stream);
+ for (j = 0; j < TYPE_NFIELDS (field_type); j++)
+ { int k; /* variant field index */
+ struct type *variant_type
+ = TYPE_FIELD_TYPE (field_type, j);
+ int var_len = TYPE_NFIELDS (variant_type);
+ print_spaces_filtered (level + 4, stream);
+ if (strcmp (TYPE_FIELD_NAME (field_type, j),
+ "else") == 0)
+ fputs_filtered ("ELSE\n", stream);
+ else
+ fputs_filtered (":\n", stream);
+ if (TYPE_CODE (variant_type) != TYPE_CODE_STRUCT)
+ error ("variant record confusion");
+ for (k = 0; k < var_len; k++)
+ {
+ print_spaces_filtered (level + 8, stream);
+ chill_print_type (TYPE_FIELD_TYPE (variant_type, k),
+ TYPE_FIELD_NAME (variant_type, k),
+ stream, show - 1, level + 8);
+ if (k < (var_len - 1))
+ fputs_filtered (",", stream);
+ fputs_filtered ("\n", stream);
+ }
+ }
+ print_spaces_filtered (level + 4, stream);
+ fputs_filtered ("ESAC", stream);
+ }
+ else
+ chill_print_type (field_type,
+ 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_RANGE:
+ {
+ struct type *target = TYPE_TARGET_TYPE (type);
+ if (target && TYPE_NAME (target))
+ fputs_filtered (TYPE_NAME (target), stream);
+ else
+ fputs_filtered ("RANGE", stream);
+ if (target == NULL)
+ target = builtin_type_long;
+ fputs_filtered (" (", stream);
+ print_type_scalar (target, TYPE_LOW_BOUND (type), stream);
+ fputs_filtered (":", stream);
+ print_type_scalar (target, TYPE_HIGH_BOUND (type), stream);
+ fputs_filtered (")", stream);
+ }
+ break;
+
+ case TYPE_CODE_ENUM:
+ {
+ register int lastval = 0;
+ fprintf_filtered (stream, "SET (");
+ len = TYPE_NFIELDS (type);
+ 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:
+ case TYPE_CODE_UNDEF:
+ case TYPE_CODE_ERROR:
+ 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/gdb/ch-valprint.c b/gdb/ch-valprint.c
new file mode 100644
index 00000000000..663ba6428c1
--- /dev/null
+++ b/gdb/ch-valprint.c
@@ -0,0 +1,630 @@
+/* Support for printing Chill values for GDB, the GNU debugger.
+ Copyright 1986, 1988, 1989, 1991, 1992, 1993, 1994
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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"
+#include "c-lang.h" /* For c_val_print */
+#include "typeprint.h"
+#include "ch-lang.h"
+#include "annotate.h"
+
+static void
+chill_print_value_fields PARAMS ((struct type *, char *, GDB_FILE *, int, int,
+ enum val_prettyprint, struct type **));
+
+static void
+chill_print_type_scalar PARAMS ((struct type *, LONGEST, GDB_FILE *));
+
+static void
+chill_val_print_array_elements PARAMS ((struct type *, char *, CORE_ADDR, GDB_FILE *,
+ int, int, int, enum val_prettyprint));
+
+
+/* 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. */
+
+static void
+chill_print_type_scalar (type, val, stream)
+ struct type *type;
+ LONGEST val;
+ GDB_FILE *stream;
+{
+ switch (TYPE_CODE (type))
+ {
+ case TYPE_CODE_RANGE:
+ if (TYPE_TARGET_TYPE (type))
+ {
+ chill_print_type_scalar (TYPE_TARGET_TYPE (type), val, stream);
+ return;
+ }
+ break;
+ case TYPE_CODE_UNDEF:
+ case TYPE_CODE_PTR:
+ case TYPE_CODE_ARRAY:
+ case TYPE_CODE_STRUCT:
+ case TYPE_CODE_UNION:
+ case TYPE_CODE_ENUM:
+ case TYPE_CODE_FUNC:
+ case TYPE_CODE_INT:
+ case TYPE_CODE_FLT:
+ case TYPE_CODE_VOID:
+ case TYPE_CODE_SET:
+ case TYPE_CODE_STRING:
+ case TYPE_CODE_BITSTRING:
+ case TYPE_CODE_ERROR:
+ case TYPE_CODE_MEMBER:
+ case TYPE_CODE_METHOD:
+ case TYPE_CODE_REF:
+ case TYPE_CODE_CHAR:
+ case TYPE_CODE_BOOL:
+ case TYPE_CODE_COMPLEX:
+ case TYPE_CODE_TYPEDEF:
+ default:
+ break;
+ }
+ print_type_scalar (type, val, stream);
+}
+
+/* Print the elements of an array.
+ Similar to val_print_array_elements, but prints
+ element indexes (in Chill syntax). */
+
+static void
+chill_val_print_array_elements (type, valaddr, address, stream,
+ format, deref_ref, recurse, pretty)
+ struct type *type;
+ char *valaddr;
+ CORE_ADDR address;
+ GDB_FILE *stream;
+ int format;
+ int deref_ref;
+ int recurse;
+ enum val_prettyprint pretty;
+{
+ unsigned int i = 0;
+ unsigned int things_printed = 0;
+ unsigned len;
+ struct type *elttype;
+ struct type *range_type = TYPE_FIELD_TYPE (type, 0);
+ struct type *index_type = TYPE_TARGET_TYPE (range_type);
+ 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;
+ LONGEST low_bound = TYPE_FIELD_BITPOS (range_type, 0);
+
+ elttype = check_typedef (TYPE_TARGET_TYPE (type));
+ eltlen = TYPE_LENGTH (elttype);
+ len = TYPE_LENGTH (type) / eltlen;
+
+ annotate_array_section_begin (i, elttype);
+
+ 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;
+ }
+
+ fputs_filtered ("(", stream);
+ chill_print_type_scalar (index_type, low_bound + i, stream);
+ if (reps > 1)
+ {
+ fputs_filtered (":", stream);
+ chill_print_type_scalar (index_type, low_bound + i + reps - 1,
+ stream);
+ fputs_filtered ("): ", stream);
+ val_print (elttype, valaddr + i * eltlen, 0, 0, stream, format,
+ deref_ref, recurse + 1, pretty);
+
+ i = rep1 - 1;
+ things_printed += 1;
+ }
+ else
+ {
+ fputs_filtered ("): ", stream);
+ val_print (elttype, valaddr + i * eltlen, 0, 0, stream, format,
+ deref_ref, recurse + 1, pretty);
+ annotate_elt ();
+ things_printed++;
+ }
+ }
+ annotate_array_section_end ();
+ if (i < len)
+ {
+ fprintf_filtered (stream, "...");
+ }
+}
+
+/* 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, embedded_offset, address,
+ stream, format, deref_ref, recurse, pretty)
+ struct type *type;
+ char *valaddr;
+ int embedded_offset;
+ CORE_ADDR address;
+ GDB_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;
+
+ CHECK_TYPEDEF (type);
+
+ 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, "[");
+ chill_val_print_array_elements (type, valaddr, address, stream,
+ format, deref_ref, recurse, pretty);
+ 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
+ {
+ /* FIXME: Why is this using builtin_type_chill_bool not type? */
+ 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 = check_typedef (TYPE_TARGET_TYPE (type));
+
+ /* We assume a NULL pointer is all zeros ... */
+ if (addr == 0)
+ {
+ fputs_filtered ("NULL", stream);
+ return 0;
+ }
+
+ 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')
+ {
+ print_address_numeric (addr, 1, stream);
+ }
+
+ /* 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, -1, TYPE_LENGTH (elttype), 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:
+ i = TYPE_LENGTH (type);
+ LA_PRINT_STRING (stream, valaddr, i, 1, 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_BITSTRING:
+ case TYPE_CODE_SET:
+ elttype = TYPE_INDEX_TYPE (type);
+ CHECK_TYPEDEF (elttype);
+ if (TYPE_FLAGS (elttype) & TYPE_FLAG_STUB)
+ {
+ fprintf_filtered (stream, "<incomplete type>");
+ gdb_flush (stream);
+ break;
+ }
+ {
+ struct type *range = elttype;
+ LONGEST low_bound, high_bound;
+ int i;
+ int is_bitstring = TYPE_CODE (type) == TYPE_CODE_BITSTRING;
+ int need_comma = 0;
+
+ if (is_bitstring)
+ fputs_filtered ("B'", stream);
+ else
+ fputs_filtered ("[", stream);
+
+ i = get_discrete_bounds (range, &low_bound, &high_bound);
+ maybe_bad_bstring:
+ if (i < 0)
+ {
+ fputs_filtered ("<error value>", stream);
+ goto done;
+ }
+
+ for (i = low_bound; i <= high_bound; i++)
+ {
+ int element = value_bit_index (type, valaddr, i);
+ if (element < 0)
+ {
+ i = element;
+ goto maybe_bad_bstring;
+ }
+ if (is_bitstring)
+ fprintf_filtered (stream, "%d", element);
+ else if (element)
+ {
+ if (need_comma)
+ fputs_filtered (", ", stream);
+ chill_print_type_scalar (range, (LONGEST) i, stream);
+ need_comma = 1;
+
+ /* Look for a continuous range of true elements. */
+ if (i+1 <= high_bound && value_bit_index (type, valaddr, ++i))
+ {
+ int j = i; /* j is the upper bound so far of the range */
+ fputs_filtered (":", stream);
+ while (i+1 <= high_bound
+ && value_bit_index (type, valaddr, ++i))
+ j = i;
+ chill_print_type_scalar (range, (LONGEST) j, stream);
+ }
+ }
+ }
+ done:
+ if (is_bitstring)
+ fputs_filtered ("'", stream);
+ else
+ fputs_filtered ("]", stream);
+ }
+ break;
+
+ case TYPE_CODE_STRUCT:
+ if (chill_varying_type (type))
+ {
+ struct type *inner = check_typedef (TYPE_FIELD_TYPE (type, 1));
+ long length = unpack_long (TYPE_FIELD_TYPE (type, 0), valaddr);
+ char *data_addr = valaddr + TYPE_FIELD_BITPOS (type, 1) / 8;
+
+ switch (TYPE_CODE (inner))
+ {
+ case TYPE_CODE_STRING:
+ if (length > TYPE_LENGTH (type) - 2)
+ {
+ fprintf_filtered (stream,
+ "<dynamic length %ld > static length %d> *invalid*",
+ length, TYPE_LENGTH (type));
+
+ /* Don't print the string; doing so might produce a
+ segfault. */
+ return length;
+ }
+ LA_PRINT_STRING (stream, data_addr, length, 1, 0);
+ return length;
+ default:
+ break;
+ }
+ }
+ chill_print_value_fields (type, valaddr, stream, format, recurse, pretty,
+ 0);
+ break;
+
+ case TYPE_CODE_REF:
+ if (addressprint)
+ {
+ fprintf_filtered (stream, "LOC(");
+ print_address_numeric
+ (extract_address (valaddr, TARGET_PTR_BIT / HOST_CHAR_BIT),
+ 1,
+ stream);
+ fprintf_filtered (stream, ")");
+ if (deref_ref)
+ fputs_filtered (": ", stream);
+ }
+ /* De-reference the reference. */
+ if (deref_ref)
+ {
+ if (TYPE_CODE (TYPE_TARGET_TYPE (type)) != TYPE_CODE_UNDEF)
+ {
+ value_ptr deref_val =
+ value_at
+ (TYPE_TARGET_TYPE (type),
+ unpack_pointer (lookup_pointer_type (builtin_type_void),
+ valaddr),
+ NULL);
+ val_print (VALUE_TYPE (deref_val),
+ VALUE_CONTENTS (deref_val),
+ 0,
+ 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, 0, address, stream, format,
+ deref_ref, recurse, pretty);
+ break;
+
+ case TYPE_CODE_RANGE:
+ if (TYPE_TARGET_TYPE (type))
+ chill_val_print (TYPE_TARGET_TYPE (type), valaddr, 0, 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:
+ default:
+ /* Let's defer printing to the C printer, rather than
+ print an error message. FIXME! */
+ c_val_print (type, valaddr, 0, address, stream, format,
+ deref_ref, recurse, pretty);
+ }
+ gdb_flush (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;
+ GDB_FILE *stream;
+ int format;
+ int recurse;
+ enum val_prettyprint pretty;
+ struct type **dont_print;
+{
+ int i, len;
+ int fields_seen = 0;
+
+ CHECK_TYPEDEF (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_ptr 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, 0,
+ stream, format, 0, recurse + 1, pretty);
+ }
+ else
+ {
+ chill_val_print (TYPE_FIELD_TYPE (type, i),
+ valaddr + TYPE_FIELD_BITPOS (type, i) / 8, 0,
+ 0, stream, format, 0, recurse + 1, pretty);
+ }
+ }
+ if (pretty)
+ {
+ fprintf_filtered (stream, "\n");
+ print_spaces_filtered (2 * recurse, stream);
+ }
+ }
+ fprintf_filtered (stream, "]");
+}
+
+int
+chill_value_print (val, stream, format, pretty)
+ value_ptr val;
+ GDB_FILE *stream;
+ int format;
+ enum val_prettyprint pretty;
+{
+ struct type *type = VALUE_TYPE (val);
+ struct type *real_type = check_typedef (type);
+
+ /* If it is a pointer, indicate what it points to.
+
+ Print type also if it is a reference. */
+
+ if (TYPE_CODE (real_type) == TYPE_CODE_PTR ||
+ TYPE_CODE (real_type) == TYPE_CODE_REF)
+ {
+ char *valaddr = VALUE_CONTENTS (val);
+ CORE_ADDR addr = unpack_pointer (type, valaddr);
+ if (TYPE_CODE (type) != TYPE_CODE_PTR || addr != 0)
+ {
+ int i;
+ char *name = TYPE_NAME (type);
+ if (name)
+ fputs_filtered (name, stream);
+ else if (TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_VOID)
+ fputs_filtered ("PTR", stream);
+ else
+ {
+ fprintf_filtered (stream, "(");
+ type_print (type, "", stream, -1);
+ fprintf_filtered (stream, ")");
+ }
+ fprintf_filtered (stream, "(");
+ i = val_print (type, valaddr, 0, VALUE_ADDRESS (val),
+ stream, format, 1, 0, pretty);
+ fprintf_filtered (stream, ")");
+ return i;
+ }
+ }
+ return (val_print (type, VALUE_CONTENTS (val), 0,
+ VALUE_ADDRESS (val), stream, format, 1, 0, pretty));
+}
+
+
diff --git a/gdb/coff-solib.c b/gdb/coff-solib.c
new file mode 100644
index 00000000000..6be68697928
--- /dev/null
+++ b/gdb/coff-solib.c
@@ -0,0 +1,134 @@
+/* Handle COFF SVR3 shared libraries for GDB, the GNU Debugger.
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+
+#include "defs.h"
+
+#include "frame.h"
+#include "bfd.h"
+#include "gdbcore.h"
+#include "symtab.h"
+
+/*
+
+GLOBAL FUNCTION
+
+ coff_solib_add -- add a shared library files to the symtab list. We
+ examine the `.lib' section of the exec file and determine the names of
+ the shared libraries.
+
+ 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.
+
+SYNOPSIS
+
+ void coff_solib_add (char *arg_string, int from_tty,
+ struct target_ops *target)
+
+DESCRIPTION
+
+*/
+
+void
+coff_solib_add (arg_string, from_tty, target)
+ char *arg_string;
+ int from_tty;
+ struct target_ops *target;
+{
+ asection *libsect;
+
+ libsect = bfd_get_section_by_name (exec_bfd, ".lib");
+
+ if (libsect)
+ {
+ int libsize;
+ unsigned char *lib;
+ struct libent
+ {
+ bfd_byte len[4];
+ bfd_byte nameoffset[4];
+ };
+
+ libsize = bfd_section_size (exec_bfd, libsect);
+
+ lib = (unsigned char *) alloca (libsize);
+
+ bfd_get_section_contents (exec_bfd, libsect, lib, 0, libsize);
+
+ while (libsize > 0)
+ {
+ struct libent *ent;
+ struct objfile *objfile;
+ int len, nameoffset;
+ char *filename;
+
+ ent = (struct libent *)lib;
+
+ len = bfd_get_32 (exec_bfd, ent->len);
+
+ nameoffset = bfd_get_32 (exec_bfd, ent->nameoffset);
+
+ if (len <= 0)
+ break;
+
+ filename = (char *)ent + nameoffset * 4;
+
+ objfile = symbol_file_add (filename, from_tty,
+ 0, /* addr */
+ 0, /* not mainline */
+ 0, /* not mapped */
+ 0, /* Not readnow */
+ 0, /* Not user loaded */
+ 1); /* Is a solib */
+
+ libsize -= len * 4;
+ lib += len * 4;
+ }
+
+ /* Getting new symbols may change our opinion about what is
+ frameless. */
+ reinit_frame_cache ();
+ }
+}
+
+/*
+
+GLOBAL FUNCTION
+
+ coff_solib_create_inferior_hook -- shared library startup support
+
+SYNOPSIS
+
+ void coff_solib_create_inferior_hook()
+
+DESCRIPTION
+
+ When gdb starts up the inferior, the kernel maps in the shared
+ libraries. We get here with the target stopped at it's first
+ instruction, and the libraries already mapped. At this point, this
+ function gets called via expansion of the macro
+ SOLIB_CREATE_INFERIOR_HOOK.
+ */
+
+void
+coff_solib_create_inferior_hook()
+{
+ coff_solib_add ((char *) 0, 0, (struct target_ops *) 0);
+}
diff --git a/gdb/coff-solib.h b/gdb/coff-solib.h
new file mode 100644
index 00000000000..43375ccd460
--- /dev/null
+++ b/gdb/coff-solib.h
@@ -0,0 +1,190 @@
+/* COFF (SVR3) 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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. */
+
+#if 0
+#define CLEAR_SOLIB coff_clear_solib
+
+extern void
+coff_clear_solib PARAMS ((void));
+#endif
+
+/* Called to add symbols from a shared library to gdb's symbol table. */
+
+#define SOLIB_ADD(filename, from_tty, targ) \
+ coff_solib_add (filename, from_tty, targ)
+
+extern void
+coff_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) coff_solib_create_inferior_hook()
+
+extern void
+coff_solib_create_inferior_hook PARAMS((void)); /* solib.c */
+
+/* Function to be called to remove the connection between debugger and
+ dynamic linker that was established by SOLIB_CREATE_INFERIOR_HOOK.
+ (This operation does not remove shared library information from
+ the debugger, as CLEAR_SOLIB does.)
+
+ This functionality is presently not implemented for this target.
+ */
+#define SOLIB_REMOVE_INFERIOR_HOOK(PID) (0)
+
+/* This function is called by the "catch load" command. It allows
+ the debugger to be notified by the dynamic linker when a specified
+ library file (or any library file, if filename is NULL) is loaded.
+
+ Presently, this functionality is not implemented.
+ */
+#define SOLIB_CREATE_CATCH_LOAD_HOOK(pid,tempflag,filename,cond_string) \
+ error("catch of library loads/unloads not yet implemented on this platform")
+
+/* This function is called by the "catch unload" command. It allows
+ the debugger to be notified by the dynamic linker when a specified
+ library file (or any library file, if filename is NULL) is unloaded.
+
+ Presently, this functionality is not implemented.
+ */
+#define SOLIB_CREATE_CATCH_UNLOAD_HOOK(pid,tempflag,filename,cond_string) \
+ error("catch of library loads/unloads not yet implemented on this platform")
+
+/* This function returns TRUE if the dynamic linker has just reported
+ a load of a library.
+
+ This function must be used only when the inferior has stopped in
+ the dynamic linker hook, or undefined results are guaranteed.
+
+ Presently, this functionality is not implemented.
+ */
+/*
+#define SOLIB_HAVE_LOAD_EVENT(pid) \
+ error("catch of library loads/unloads not yet implemented on this platform")
+*/
+
+#define SOLIB_HAVE_LOAD_EVENT(pid) \
+(0)
+
+/* This function returns a pointer to the string representation of the
+ pathname of the dynamically-linked library that has just been loaded.
+
+ This function must be used only when SOLIB_HAVE_LOAD_EVENT is TRUE,
+ or undefined results are guaranteed.
+
+ This string's contents are only valid immediately after the inferior
+ has stopped in the dynamic linker hook, and becomes invalid as soon
+ as the inferior is continued. Clients should make a copy of this
+ string if they wish to continue the inferior and then access the string.
+
+ Presently, this functionality is not implemented.
+ */
+
+/*
+#define SOLIB_LOADED_LIBRARY_PATHNAME(pid) \
+ error("catch of library loads/unloads not yet implemented on this platform")
+*/
+
+#define SOLIB_LOADED_LIBRARY_PATHNAME(pid) \
+(0)
+
+/* This function returns TRUE if the dynamic linker has just reported
+ an unload of a library.
+
+ This function must be used only when the inferior has stopped in
+ the dynamic linker hook, or undefined results are guaranteed.
+
+ Presently, this functionality is not implemented.
+ */
+/*
+#define SOLIB_HAVE_UNLOAD_EVENT(pid) \
+ error("catch of library loads/unloads not yet implemented on this platform")
+*/
+
+#define SOLIB_HAVE_UNLOAD_EVENT(pid) \
+(0)
+
+/* This function returns a pointer to the string representation of the
+ pathname of the dynamically-linked library that has just been unloaded.
+
+ This function must be used only when SOLIB_HAVE_UNLOAD_EVENT is TRUE,
+ or undefined results are guaranteed.
+
+ This string's contents are only valid immediately after the inferior
+ has stopped in the dynamic linker hook, and becomes invalid as soon
+ as the inferior is continued. Clients should make a copy of this
+ string if they wish to continue the inferior and then access the string.
+
+ Presently, this functionality is not implemented.
+ */
+/*
+#define SOLIB_UNLOADED_LIBRARY_PATHNAME(pid) \
+ error("catch of library loads/unloads not yet implemented on this platform")
+*/
+
+#define SOLIB_UNLOADED_LIBRARY_PATHNAME(pid) \
+(0)
+
+/* This function returns TRUE if pc is the address of an instruction that
+ lies within the dynamic linker (such as the event hook, or the dld
+ itself).
+
+ This function must be used only when a dynamic linker event has been
+ caught, and the inferior is being stepped out of the hook, or undefined
+ results are guaranteed.
+
+ Presently, this functionality is not implemented.
+ */
+
+/*
+#define SOLIB_IN_DYNAMIC_LINKER(pid,pc) \
+ error("catch of library loads/unloads not yet implemented on this platform")
+*/
+
+#define SOLIB_IN_DYNAMIC_LINKER(pid,pc) \
+(0)
+
+/* This function must be called when the inferior is killed, and the program
+ restarted. This is not the same as CLEAR_SOLIB, in that it doesn't discard
+ any symbol tables.
+
+ Presently, this functionality is not implemented.
+ */
+#define SOLIB_RESTART() \
+ (0)
+
+/* If we can't set a breakpoint, and it's in a shared library, just
+ disable it. */
+
+#if 0
+#define DISABLE_UNSETTABLE_BREAK(addr) coff_solib_address(addr)
+
+extern int
+solib_address PARAMS ((CORE_ADDR)); /* solib.c */
+#endif
diff --git a/gdb/coffread.c b/gdb/coffread.c
new file mode 100644
index 00000000000..340e77f84c0
--- /dev/null
+++ b/gdb/coffread.c
@@ -0,0 +1,2255 @@
+/* Read coff symbol tables and convert to internal format, for GDB.
+ Copyright 1987, 88, 89, 90, 91, 92, 93, 94, 96, 97, 1998
+ Free Software Foundation, Inc.
+ Contributed by David D. Johnson, Brown University (ddj@cs.brown.edu).
+
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "symtab.h"
+#include "gdbtypes.h"
+#include "demangle.h"
+#include "breakpoint.h"
+
+#include "bfd.h"
+#include "obstack.h"
+
+#include "gdb_string.h"
+#include <ctype.h>
+
+#include "coff/internal.h" /* Internal format of COFF symbols in BFD */
+#include "libcoff.h" /* FIXME secret internal data from BFD */
+
+#include "symfile.h"
+#include "objfiles.h"
+#include "buildsym.h"
+#include "gdb-stabs.h"
+#include "stabsread.h"
+#include "complaints.h"
+#include "target.h"
+
+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 */
+
+ CORE_ADDR textaddr; /* Addr of .text section. */
+ unsigned int textsize; /* Size of .text section. */
+ struct stab_section_list *stabsects; /* .stab sections. */
+ asection *stabstrsect; /* Section pointer for .stab 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 current_source_start_addr;
+static CORE_ADDR current_source_end_addr;
+
+/* The addresses of the symbol table stream and number of symbols
+ of the object file we are reading (as copied into core). */
+
+static bfd *nlist_bfd_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 include/coff/internal.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;
+
+/* This is set if this is a PE format file. */
+
+static int pe_file;
+
+/* 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];
+
+/* 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 ef_stack_complaint =
+ {"`.ef' symbol without matching `.bf' symbol ignored starting at symnum %d", 0, 0};
+
+struct complaint eb_stack_complaint =
+ {"`.eb' symbol without matching `.bb' symbol 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 section_offsets *,
+ 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, struct section_offsets *));
+
+static void free_linetab PARAMS ((void));
+
+static int init_lineno PARAMS ((bfd *, long, int));
+
+static char *getsymname PARAMS ((struct internal_syment *));
+
+static char *coff_getfilename PARAMS ((union internal_auxent *));
+
+static void free_stringtab PARAMS ((void));
+
+static int init_stringtab PARAMS ((bfd *, long));
+
+static void read_one_sym PARAMS ((struct coff_symbol *,
+ struct internal_syment *,
+ union internal_auxent *));
+
+static void coff_symtab_read PARAMS ((long, int, struct section_offsets *,
+ 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,
+ struct objfile *));
+
+static void coff_end_symtab PARAMS ((struct objfile *));
+
+static void complete_symtab PARAMS ((char *, CORE_ADDR, unsigned int));
+
+static void coff_start_symtab PARAMS ((char *));
+
+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 (abfd, sectp, csip)
+ bfd *abfd;
+ asection *sectp;
+ PTR csip;
+{
+ register struct coff_symfile_info *csi;
+ const char *name;
+
+ csi = (struct coff_symfile_info *) csip;
+ name = bfd_get_section_name (abfd, sectp);
+ if (STREQ (name, ".text"))
+ {
+ csi->textaddr = bfd_section_vma (abfd, sectp);
+ csi->textsize += bfd_section_size (abfd, sectp);
+ }
+ else if (strncmp (name, ".text", sizeof ".text" - 1) == 0)
+ {
+ csi->textsize += bfd_section_size (abfd, sectp);
+ }
+ else if (STREQ (name, ".stabstr"))
+ {
+ csi->stabstrsect = sectp;
+ }
+ else if (strncmp (name, ".stab", sizeof ".stab" - 1) == 0)
+ {
+ const char *s;
+
+ /* We can have multiple .stab sections if linked with
+ --split-by-reloc. */
+ for (s = name + sizeof ".stab" - 1; *s != '\0'; s++)
+ if (! isdigit (*s))
+ break;
+ if (*s == '\0')
+ {
+ struct stab_section_list *n, **pn;
+
+ n = ((struct stab_section_list *)
+ xmalloc (sizeof (struct stab_section_list)));
+ n->section = sectp;
+ n->next = NULL;
+ for (pn = &csi->stabsects; *pn != NULL; pn = &(*pn)->next)
+ ;
+ *pn = n;
+
+ /* This will be run after coffstab_build_psymtabs is called
+ in coff_symfile_read, at which point we no longer need
+ the information. */
+ make_cleanup (free, n);
+ }
+ }
+}
+
+/* Return the section_offsets* that CS points to. */
+static int cs_to_section PARAMS ((struct coff_symbol *, struct objfile *));
+
+struct find_targ_sec_arg {
+ int targ_index;
+ asection **resultp;
+};
+
+static void find_targ_sec PARAMS ((bfd *, asection *, void *));
+
+static void find_targ_sec (abfd, sect, obj)
+ bfd *abfd;
+ asection *sect;
+ PTR obj;
+{
+ struct find_targ_sec_arg *args = (struct find_targ_sec_arg *)obj;
+ if (sect->target_index == args->targ_index)
+ *args->resultp = sect;
+}
+
+/* Return the section number (SECT_OFF_*) that CS points to. */
+static int
+cs_to_section (cs, objfile)
+ struct coff_symbol *cs;
+ struct objfile *objfile;
+{
+ asection *sect = NULL;
+ struct find_targ_sec_arg args;
+ int off = SECT_OFF_TEXT;
+
+ args.targ_index = cs->c_secnum;
+ args.resultp = &sect;
+ bfd_map_over_sections (objfile->obfd, find_targ_sec, &args);
+ if (sect != NULL)
+ {
+ /* This is the section. Figure out what SECT_OFF_* code it is. */
+ if (bfd_get_section_flags (abfd, sect) & SEC_CODE)
+ off = SECT_OFF_TEXT;
+ else if (bfd_get_section_flags (abfd, sect) & SEC_LOAD)
+ off = SECT_OFF_DATA;
+ else
+ off = SECT_OFF_BSS;
+ }
+ return off;
+}
+
+/* Return the address of the section of a COFF symbol. */
+
+static CORE_ADDR cs_section_address PARAMS ((struct coff_symbol *, bfd *));
+
+static CORE_ADDR
+cs_section_address (cs, abfd)
+ struct coff_symbol *cs;
+ bfd *abfd;
+{
+ asection *sect = NULL;
+ struct find_targ_sec_arg args;
+ CORE_ADDR addr = 0;
+
+ args.targ_index = cs->c_secnum;
+ args.resultp = &sect;
+ bfd_map_over_sections (abfd, find_targ_sec, &args);
+ if (sect != NULL)
+ addr = bfd_get_section_vma (objfile->obfd, sect);
+ return addr;
+}
+
+/* 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 (name)
+ char *name;
+{
+ start_symtab (
+ /* We fill in the filename later. start_symtab puts
+ this pointer into last_source_file and we put it in
+ subfiles->name, which end_symtab frees; that's why
+ it must be malloc'd. */
+ savestring (name, strlen(name)),
+ /* 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);
+ record_debugformat ("COFF");
+
+ /* 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;
+{
+ if (last_source_file != NULL)
+ free (last_source_file);
+ last_source_file = savestring (name, strlen (name));
+ current_source_start_addr = start_addr;
+ current_source_end_addr = start_addr + size;
+
+ if (current_objfile -> ei.entry_point >= current_source_start_addr &&
+ current_objfile -> ei.entry_point < current_source_end_addr)
+ {
+ current_objfile -> ei.entry_file_lowpc = current_source_start_addr;
+ current_objfile -> ei.entry_file_highpc = current_source_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 = current_source_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;
+
+ symtab = end_symtab (current_source_end_addr, 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, objfile)
+ char *name;
+ CORE_ADDR address;
+ enum minimal_symbol_type type;
+ struct objfile *objfile;
+{
+ /* We don't want TDESC entry points in the minimal symbol table */
+ if (name[0] == '@') return;
+
+ prim_record_minimal_symbol (name, address, type, objfile);
+}
+
+/* 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 void
+coff_symfile_init (objfile)
+ struct objfile *objfile;
+{
+ /* Allocate struct to keep track of stab reading. */
+ objfile->sym_stab_info = (struct dbx_symfile_info *)
+ 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));
+
+ /* COFF objects may be reordered, so set OBJF_REORDERED. If we
+ find this causes a significant slowdown in gdb then we could
+ set it in the debug symbol readers only when necessary. */
+ objfile->flags |= OBJF_REORDERED;
+
+ init_entry_point_info (objfile);
+}
+
+/* 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. */
+
+/* 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);
+ register int val;
+ int num_symbols;
+ int symtab_offset;
+ int stringtab_offset;
+ struct cleanup *back_to;
+ int stabstrsize;
+
+ info = (struct coff_symfile_info *) objfile -> sym_private;
+ dbxinfo = objfile->sym_stab_info;
+ symfile_bfd = abfd; /* Kludge for swap routines */
+
+/* WARNING WILL ROBINSON! ACCESSING BFD-PRIVATE DATA HERE! FIXME! */
+ 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 ((make_cleanup_func) free_current_contents, &temp_sym);
+
+ /* We need to know whether this is a PE file, because in PE files,
+ unlike standard COFF files, symbol values are stored as offsets
+ from the section address, rather than as absolute addresses.
+ FIXME: We should use BFD to read the symbol table, and thus avoid
+ this problem. */
+ pe_file = strncmp (bfd_get_target (objfile->obfd), "pe", 2) == 0;
+
+/* 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 ((make_cleanup_func) free_linetab, 0);
+ val = init_lineno (abfd, 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 ((make_cleanup_func) free_stringtab, 0);
+ val = init_stringtab (abfd, stringtab_offset);
+ if (val < 0)
+ error ("\"%s\": can't get string table", name);
+
+ init_minimal_symbol_collection ();
+ make_cleanup ((make_cleanup_func) discard_minimal_symbols, 0);
+
+ /* Now that the executable file is positioned at symbol table,
+ process it and define symbols accordingly. */
+
+ coff_symtab_read ((long) symtab_offset, num_symbols, section_offsets,
+ objfile);
+
+ /* Sort symbols alphabetically within each block. */
+
+ {
+ struct symtab *s;
+
+ for (s = objfile -> symtabs; s != NULL; s = s -> next)
+ sort_symtab_syms (s);
+ }
+
+ /* 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->stabsects)
+ {
+ /* FIXME: dubious. Why can't we use something normal like
+ bfd_get_section_contents? */
+ bfd_seek (abfd, abfd->where, 0);
+
+ stabstrsize = bfd_section_size (abfd, info->stabstrsect);
+
+ coffstab_build_psymtabs (objfile,
+ section_offsets,
+ mainline,
+ info->textaddr, info->textsize,
+ info->stabsects,
+ 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
+coff_symtab_read (symtab_offset, nsyms, section_offsets, objfile)
+ long symtab_offset;
+ int nsyms;
+ struct section_offsets *section_offsets;
+ struct objfile *objfile;
+{
+ 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 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;
+ CORE_ADDR tmpaddr;
+
+ /* 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 (former) rewind().
+
+ FIXME: Find out if this has been reported to Sun, whether it has
+ been fixed in a later release, etc. */
+
+ bfd_seek (objfile->obfd, 0, 0);
+
+ /* Position to read the symbol table. */
+ val = bfd_seek (objfile->obfd, (long) symtab_offset, 0);
+ if (val < 0)
+ perror_with_name (objfile->name);
+
+ current_objfile = objfile;
+ nlist_bfd_global = objfile->obfd;
+ 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);
+
+ if (cs->c_symnum == next_file_symnum && cs->c_sclass != C_FILE)
+ {
+ if (last_source_file)
+ coff_end_symtab (objfile);
+
+ coff_start_symtab ("_globals_");
+ complete_symtab ("_globals_", 0, 0);
+ /* 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. */
+ tmpaddr = cs->c_value + ANOFFSET (section_offsets, SECT_OFF_TEXT);
+ record_minimal_symbol (cs->c_name, tmpaddr, mst_text, objfile);
+
+ fcn_line_ptr = main_aux.x_sym.x_fcnary.x_fcn.x_lnnoptr;
+ fcn_start_addr = tmpaddr;
+ 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 = coff_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 (filestring);
+ }
+ in_source_file = 1;
+ break;
+
+ /* C_LABEL is used for labels and static functions. Including
+ it here allows gdb to see static functions when no debug
+ info is available. */
+ case C_LABEL:
+ /* However, labels within a function can make weird backtraces,
+ so filter them out (from phdm@macqel.be). */
+ if (within_function)
+ break;
+ case C_STAT:
+ case C_THUMBLABEL:
+ case C_THUMBSTAT:
+ case C_THUMBSTATFUNC:
+ if (cs->c_name[0] == '.')
+ {
+ if (STREQ (cs->c_name, ".text")) {
+ /* FIXME: don't wire in ".text" as section name
+ or symbol name! */
+ /* 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 + ANOFFSET (section_offsets, SECT_OFF_TEXT),
+ 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_THUMBEXT:
+ case C_THUMBEXTFUNC:
+ case C_EXT:
+ {
+ /* Record it in the minimal symbols regardless of
+ SDB_TYPE. This parallels what we do for other debug
+ formats, and probably is needed to make
+ print_address_symbolic work right without the (now
+ gone) "set fast-symbolic-addr off" kludge. */
+
+ /* FIXME: should use mst_abs, and not relocate, if absolute. */
+ enum minimal_symbol_type ms_type;
+ int sec;
+
+ if (cs->c_secnum == N_UNDEF)
+ {
+ /* This is a common symbol. See if the target
+ environment knows where it has been relocated to. */
+ CORE_ADDR reladdr;
+ if (target_lookup_symbol (cs->c_name, &reladdr))
+ {
+ /* Error in lookup; ignore symbol. */
+ break;
+ }
+ tmpaddr = reladdr;
+ /* The address has already been relocated; make sure that
+ objfile_relocate doesn't relocate it again. */
+ sec = -2;
+ ms_type = cs->c_sclass == C_EXT
+ || cs->c_sclass == C_THUMBEXT ?
+ mst_bss : mst_file_bss;
+ }
+ else
+ {
+ sec = cs_to_section (cs, objfile);
+ tmpaddr = cs->c_value;
+ if (cs->c_sclass == C_EXT || cs->c_sclass == C_THUMBEXTFUNC
+ || cs->c_sclass == C_THUMBEXT)
+ tmpaddr += ANOFFSET (section_offsets, sec);
+
+ switch (sec)
+ {
+ case SECT_OFF_TEXT:
+ case SECT_OFF_RODATA:
+ ms_type =
+ cs->c_sclass == C_EXT || cs->c_sclass == C_THUMBEXTFUNC
+ || cs->c_sclass == C_THUMBEXT ?
+ mst_text : mst_file_text;
+#ifdef SMASH_TEXT_ADDRESS
+ if (tmpaddr & 1) /* FIXME: delete this line */
+ SMASH_TEXT_ADDRESS (tmpaddr);
+#endif
+ break;
+ case SECT_OFF_DATA:
+ ms_type =
+ cs->c_sclass == C_EXT || cs->c_sclass == C_THUMBEXT ?
+ mst_data : mst_file_data;
+ break;
+ case SECT_OFF_BSS:
+ ms_type =
+ cs->c_sclass == C_EXT || cs->c_sclass == C_THUMBEXT ?
+ mst_data : mst_file_data;
+ break;
+ default:
+ ms_type = mst_unknown;
+ break;
+ }
+ }
+
+ if (cs->c_name[0] != '@' /* Skip tdesc symbols */)
+ {
+ struct minimal_symbol *msym;
+
+ msym = prim_record_minimal_symbol_and_info
+ (cs->c_name, tmpaddr, ms_type, (char *)cs->c_sclass, sec,
+ NULL, objfile);
+#ifdef COFF_MAKE_MSYMBOL_SPECIAL
+ if(msym)
+ COFF_MAKE_MSYMBOL_SPECIAL(cs->c_sclass, msym);
+#endif
+ }
+ if (SDB_TYPE (cs->c_type))
+ {
+ struct symbol *sym;
+ sym = process_coff_symbol
+ (cs, &main_aux, section_offsets, objfile);
+ SYMBOL_VALUE (sym) = tmpaddr;
+ SYMBOL_SECTION (sym) = sec;
+ }
+ }
+ 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,
+ section_offsets, 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 '}' */
+
+ if (context_stack_depth <= 0)
+ { /* We attempted to pop an empty context stack */
+ complain (&ef_stack_complaint, cs->c_symnum);
+ within_function = 0;
+ break;
+ }
+
+ 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,
+ section_offsets);
+
+ 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
+ + ANOFFSET (section_offsets, SECT_OFF_TEXT),
+#else
+ fcn_cs_saved.c_value
+ + fcn_aux_saved.x_sym.x_misc.x_fsize
+ + ANOFFSET (section_offsets, SECT_OFF_TEXT),
+#endif
+ objfile
+ );
+ within_function = 0;
+ }
+ break;
+
+ case C_BLOCK:
+ if (STREQ (cs->c_name, ".bb"))
+ {
+ tmpaddr = cs->c_value;
+ tmpaddr += ANOFFSET (section_offsets, SECT_OFF_TEXT);
+ push_context (++depth, tmpaddr);
+ }
+ else if (STREQ (cs->c_name, ".eb"))
+ {
+ if (context_stack_depth <= 0)
+ { /* We attempted to pop an empty context stack */
+ complain (&eb_stack_complaint, cs->c_symnum);
+ break;
+ }
+
+ new = pop_context ();
+ if (depth-- != new->depth)
+ {
+ complain (&eb_complaint, symnum);
+ break;
+ }
+ if (local_symbols && context_stack_depth > 0)
+ {
+ tmpaddr =
+ cs->c_value + ANOFFSET (section_offsets, SECT_OFF_TEXT);
+ /* Make a block for the local symbols within. */
+ finish_block (0, &local_symbols, new->old_blocks,
+ new->start_addr, tmpaddr, objfile);
+ }
+ /* Now pop locals of block just finished. */
+ local_symbols = new->locals;
+ }
+ break;
+
+ default:
+ process_coff_symbol (cs, &main_aux, section_offsets, 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. */
+
+/* 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;
+ bfd_read (temp_sym, local_symesz, 1, nlist_bfd_global);
+ bfd_coff_swap_sym_in (symfile_bfd, temp_sym, (char *)sym);
+ cs->c_naux = sym->n_numaux & 0xff;
+ if (cs->c_naux >= 1)
+ {
+ bfd_read (temp_aux, local_auxesz, 1, nlist_bfd_global);
+ bfd_coff_swap_aux_in (symfile_bfd, temp_aux, sym->n_type, sym->n_sclass,
+ 0, cs->c_naux, (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++)
+ bfd_read (temp_aux, local_auxesz, 1, nlist_bfd_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;
+
+#if 0
+ if (cs->c_sclass & 128)
+ printf("thumb symbol %s, class 0x%x\n", cs->c_name, cs->c_sclass);
+#endif
+
+ symnum += 1 + cs->c_naux;
+
+ /* The PE file format stores symbol values as offsets within the
+ section, rather than as absolute addresses. We correct that
+ here, if the symbol has an appropriate storage class. FIXME: We
+ should use BFD to read the symbols, rather than duplicating the
+ work here. */
+ if (pe_file)
+ {
+ switch (cs->c_sclass)
+ {
+ case C_EXT:
+ case C_THUMBEXT:
+ case C_THUMBEXTFUNC:
+ case C_SECTION:
+ case C_NT_WEAK:
+ case C_STAT:
+ case C_THUMBSTAT:
+ case C_THUMBSTATFUNC:
+ case C_LABEL:
+ case C_THUMBLABEL:
+ case C_BLOCK:
+ case C_FCN:
+ case C_EFCN:
+ if (cs->c_secnum != 0)
+ cs->c_value += cs_section_address (cs, symfile_bfd);
+ break;
+ }
+ }
+}
+
+/* Support for string table handling */
+
+static char *stringtab = NULL;
+
+static int
+init_stringtab (abfd, offset)
+ bfd *abfd;
+ long offset;
+{
+ long length;
+ int val;
+ unsigned char lengthbuf[4];
+
+ free_stringtab ();
+
+ /* If the file is stripped, the offset might be zero, indicating no
+ string table. Just return with `stringtab' set to null. */
+ if (offset == 0)
+ return 0;
+
+ if (bfd_seek (abfd, offset, 0) < 0)
+ return -1;
+
+ val = bfd_read ((char *)lengthbuf, sizeof lengthbuf, 1, abfd);
+ 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);
+ /* This is in target format (probably not very useful, and not currently
+ used), not host format. */
+ memcpy (stringtab, lengthbuf, sizeof lengthbuf);
+ if (length == sizeof length) /* Empty table -- just the count */
+ return 0;
+
+ val = bfd_read (stringtab + sizeof lengthbuf, length - sizeof lengthbuf, 1, abfd);
+ 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)
+ {
+ /* FIXME: Probably should be detecting corrupt symbol files by
+ seeing whether offset points to within the stringtab. */
+ 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 *
+coff_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;
+
+ /* FIXME: We should not be throwing away the information about what
+ directory. It should go into dirname of the symtab, or some such
+ place. */
+ 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 (abfd, offset, size)
+ bfd *abfd;
+ long offset;
+ int size;
+{
+ int val;
+
+ linetab_offset = offset;
+ linetab_size = size;
+
+ free_linetab();
+
+ if (size == 0)
+ return 0;
+
+ if (bfd_seek (abfd, offset, 0) < 0)
+ return -1;
+
+ /* Allocate the desired table, plus a sentinel */
+ linetab = (char *) xmalloc (size + local_linesz);
+
+ val = bfd_read (linetab, size, 1, abfd);
+ 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, section_offsets)
+ long file_offset;
+ register int first_line;
+ register int last_line;
+ struct section_offsets *section_offsets;
+{
+ register char *rawptr;
+ struct internal_lineno lptr;
+
+ if (!linetab)
+ return ;
+ 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
+ + ANOFFSET (section_offsets, SECT_OFF_TEXT));
+ 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, section_offsets, objfile)
+ register struct coff_symbol *cs;
+ register union internal_auxent *aux;
+ struct section_offsets *section_offsets;
+ struct objfile *objfile;
+{
+ register struct symbol *sym
+ = (struct symbol *) obstack_alloc (&objfile->symbol_obstack,
+ sizeof (struct symbol));
+ char *name;
+
+ memset (sym, 0, sizeof (struct symbol));
+ name = cs->c_name;
+ name = EXTERNAL_NAME (name, objfile->obfd);
+ SYMBOL_NAME (sym) = obsavestring (name, strlen (name),
+ &objfile->symbol_obstack);
+ SYMBOL_LANGUAGE (sym) = language_auto;
+ SYMBOL_INIT_DEMANGLED_NAME (sym, &objfile->symbol_obstack);
+
+ /* default assumptions */
+ SYMBOL_VALUE (sym) = cs->c_value;
+ SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
+ SYMBOL_SECTION (sym) = cs_to_section (cs, objfile);
+
+ if (ISFCN (cs->c_type))
+ {
+ SYMBOL_VALUE (sym) += ANOFFSET (section_offsets, SECT_OFF_TEXT);
+ SYMBOL_TYPE(sym) =
+ lookup_function_type (decode_function_type (cs, cs->c_type, aux));
+
+ SYMBOL_CLASS (sym) = LOC_BLOCK;
+ if (cs->c_sclass == C_STAT || cs->c_sclass == C_THUMBSTAT
+ || cs->c_sclass == C_THUMBSTATFUNC)
+ add_symbol_to_list (sym, &file_symbols);
+ else if (cs->c_sclass == C_EXT || cs->c_sclass == C_THUMBEXT
+ || cs->c_sclass == C_THUMBEXTFUNC)
+ 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_THUMBEXT:
+ case C_THUMBEXTFUNC:
+ case C_EXT:
+ SYMBOL_CLASS (sym) = LOC_STATIC;
+ SYMBOL_VALUE_ADDRESS (sym) = (CORE_ADDR) cs->c_value;
+ SYMBOL_VALUE_ADDRESS (sym) += ANOFFSET (section_offsets, SECT_OFF_TEXT);
+ add_symbol_to_list (sym, &global_symbols);
+ break;
+
+ case C_THUMBSTAT:
+ case C_THUMBSTATFUNC:
+ case C_STAT:
+ SYMBOL_CLASS (sym) = LOC_STATIC;
+ SYMBOL_VALUE_ADDRESS (sym) = (CORE_ADDR) cs->c_value;
+ SYMBOL_VALUE_ADDRESS (sym) += ANOFFSET (section_offsets, SECT_OFF_TEXT);
+ 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_THUMBLABEL:
+ case C_LABEL:
+ break;
+
+ case C_ARG:
+ SYMBOL_CLASS (sym) = LOC_ARG;
+ add_symbol_to_list (sym, &local_symbols);
+#if !defined (BELIEVE_PCC_PROMOTION)
+ if (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. */
+ struct type *temptype;
+ 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. */
+ struct type *temptype;
+ 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)
+ {
+ 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; 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 C_TPDEF 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)) =
+ concat (SYMBOL_NAME (sym), NULL);
+ }
+#ifdef CXUX_TARGET
+ /* Ignore vendor section for Harris CX/UX targets. */
+ else if (cs->c_name[0] == '$')
+ break;
+#endif /* CXUX_TARGET */
+
+ /* 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:
+ if (cs->c_sclass == C_FIELD
+ && aux->x_sym.x_misc.x_lnsz.x_size > TARGET_LONG_BIT)
+ return lookup_fundamental_type (current_objfile, FT_LONG_LONG);
+ else
+ 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_LNGDBL:
+ return lookup_fundamental_type (current_objfile, FT_EXT_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:
+ if (cs->c_sclass == C_FIELD
+ && aux->x_sym.x_misc.x_lnsz.x_size > TARGET_LONG_BIT)
+ return lookup_fundamental_type (current_objfile, FT_UNSIGNED_LONG_LONG);
+ else
+ 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 =
+ obsavestring (name,
+ strlen (name),
+ &current_objfile->symbol_obstack);
+ FIELD_TYPE (list->field) = decode_type (ms, ms->c_type, &sub_aux);
+ FIELD_BITPOS (list->field) = 8 * ms->c_value;
+ FIELD_BITSIZE (list->field) = 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 =
+ obsavestring (name,
+ strlen (name),
+ &current_objfile->symbol_obstack);
+ FIELD_TYPE (list->field) = decode_type (ms, ms->c_type, &sub_aux);
+ FIELD_BITPOS (list->field) = ms->c_value;
+ FIELD_BITSIZE (list->field) = 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;
+ int unsigned_enum = 1;
+
+ 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 *) obstack_alloc
+ (&current_objfile->symbol_obstack,
+ sizeof (struct symbol));
+ memset (sym, 0, sizeof (struct symbol));
+
+ SYMBOL_NAME (sym) =
+ obsavestring (name, strlen (name),
+ &current_objfile->symbol_obstack);
+ 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_BITPOS (type, n) = SYMBOL_VALUE (xsym);
+ if (SYMBOL_VALUE (xsym) < 0)
+ unsigned_enum = 0;
+ TYPE_FIELD_BITSIZE (type, n) = 0;
+ }
+ if (syms == osyms)
+ break;
+ }
+
+ if (unsigned_enum)
+ TYPE_FLAGS (type) |= TYPE_FLAG_UNSIGNED;
+
+ return type;
+}
+
+/* Register our ability to parse symbols for coff BFD files. */
+
+static struct sym_fns coff_sym_fns =
+{
+ bfd_target_coff_flavour,
+ 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 */
+ default_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/gdb/command.c b/gdb/command.c
new file mode 100644
index 00000000000..58af56701f5
--- /dev/null
+++ b/gdb/command.c
@@ -0,0 +1,1564 @@
+/* Handle lists of commands, their decoding and documentation, for GDB.
+ Copyright 1986, 1989, 1990, 1991, 1998 Free Software Foundation, Inc.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "gdbcmd.h"
+#include "symtab.h"
+#include "value.h"
+#include <ctype.h>
+#include "gdb_string.h"
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#ifdef HAVE_WAIT_H
+# include <wait.h>
+#else
+# ifdef HAVE_SYS_WAIT_H
+# include <sys/wait.h>
+# endif
+#endif
+
+#include "wait.h"
+
+/* Prototypes for local functions */
+
+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 *, GDB_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 ((GDB_FILE *, char *));
+
+void _initialize_command PARAMS ((void));
+
+/* 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.
+
+ 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.
+
+ Add this command to command list *LIST.
+
+ Returns a pointer to the added command (not necessarily the head
+ of *LIST). */
+
+struct cmd_list_element *
+add_cmd (name, class, fun, doc, list)
+ char *name;
+ 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));
+ struct cmd_list_element *p;
+
+ delete_cmd (name, list);
+
+ if (*list == NULL || STRCMP ((*list)->name, name) >= 0)
+ {
+ c->next = *list;
+ *list = c;
+ }
+ else
+ {
+ p = *list;
+ while (p->next && STRCMP (p->next->name, name) <= 0)
+ {
+ p = p->next;
+ }
+ c->next = p->next;
+ p->next = c;
+ }
+
+ c->name = name;
+ c->class = class;
+ c->function.cfunc = fun;
+ c->doc = doc;
+ c->hook = NULL;
+ c->prefixlist = NULL;
+ c->prefixname = NULL;
+ c->allow_unknown = 0;
+ c->abbrev_flag = 0;
+ c->completer = make_symbol_completion_list;
+ c->type = not_set_cmd;
+ c->var = NULL;
+ c->var_type = var_boolean;
+ c->enums = NULL;
+ c->user_commands = NULL;
+ c->hookee = NULL;
+ c->cmd_pointer = NULL;
+
+ 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;
+ enum command_class class;
+ void (*fun) PARAMS ((char *, int));
+ char *doc;
+ struct cmd_list_element **list;
+{
+ register struct cmd_list_element *c
+ = add_cmd (name, class, fun, doc, list);
+
+ c->abbrev_flag = 1;
+ return c;
+}
+
+#endif
+
+struct cmd_list_element *
+add_alias_cmd (name, oldname, class, abbrev_flag, list)
+ char *name;
+ char *oldname;
+ enum command_class class;
+ int abbrev_flag;
+ struct cmd_list_element **list;
+{
+ /* Must do this since lookup_cmd tries to side-effect its first arg */
+ char *copied_name;
+ register struct cmd_list_element *old;
+ register struct cmd_list_element *c;
+ copied_name = (char *) alloca (strlen (oldname) + 1);
+ strcpy (copied_name, oldname);
+ old = lookup_cmd (&copied_name, *list, "", 1, 1);
+
+ if (old == 0)
+ {
+ delete_cmd (name, list);
+ return 0;
+ }
+
+ c = add_cmd (name, class, old->function.cfunc, old->doc, list);
+ c->prefixlist = old->prefixlist;
+ c->prefixname = old->prefixname;
+ c->allow_unknown = old->allow_unknown;
+ c->abbrev_flag = abbrev_flag;
+ c->cmd_pointer = old;
+ return c;
+}
+
+/* Like add_cmd but adds an element for a command prefix:
+ a name that should be followed by a subcommand to be looked up
+ in another command list. PREFIXLIST should be the address
+ of the variable containing that list. */
+
+struct cmd_list_element *
+add_prefix_cmd (name, class, fun, doc, prefixlist, prefixname,
+ allow_unknown, list)
+ char *name;
+ enum command_class class;
+ void (*fun) PARAMS ((char *, int));
+ char *doc;
+ struct cmd_list_element **prefixlist;
+ char *prefixname;
+ int allow_unknown;
+ struct cmd_list_element **list;
+{
+ register struct cmd_list_element *c = add_cmd (name, class, fun, doc, list);
+ c->prefixlist = prefixlist;
+ c->prefixname = prefixname;
+ c->allow_unknown = allow_unknown;
+ return c;
+}
+
+/* Like add_prefix_cmd 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)
+ char *name;
+ enum command_class class;
+ void (*fun) PARAMS ((char *, int));
+ char *doc;
+ struct cmd_list_element **prefixlist;
+ char *prefixname;
+ int allow_unknown;
+ struct cmd_list_element **list;
+{
+ register struct cmd_list_element *c = add_cmd (name, class, fun, doc, list);
+ c->prefixlist = prefixlist;
+ c->prefixname = prefixname;
+ c->allow_unknown = allow_unknown;
+ c->abbrev_flag = 1;
+ return c;
+}
+
+/* This is an empty "cfunc". */
+void
+not_just_help_class_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+}
+
+/* This is an empty "sfunc". */
+static void empty_sfunc PARAMS ((char *, int, struct cmd_list_element *));
+
+static void
+empty_sfunc (args, from_tty, c)
+ char *args;
+ int from_tty;
+ struct cmd_list_element *c;
+{
+}
+
+/* Add element named NAME to command list LIST (the list for set
+ or some sublist thereof).
+ CLASS is as in add_cmd.
+ VAR_TYPE is the kind of thing we are setting.
+ VAR is address of the variable being controlled by this command.
+ DOC is the documentation string. */
+
+struct cmd_list_element *
+add_set_cmd (name, class, var_type, var, doc, list)
+ char *name;
+ enum command_class class;
+ var_types var_type;
+ char *var;
+ char *doc;
+ struct cmd_list_element **list;
+{
+ struct cmd_list_element *c
+ = add_cmd (name, class, NO_FUNCTION, doc, list);
+
+ c->type = set_cmd;
+ c->var_type = var_type;
+ c->var = var;
+ /* This needs to be something besides NO_FUNCTION so that this isn't
+ treated as a help class. */
+ c->function.sfunc = empty_sfunc;
+ return c;
+}
+
+/* Add element named NAME to command list LIST (the list for set
+ or some sublist thereof).
+ CLASS is as in add_cmd.
+ ENUMLIST is a list of strings which may follow NAME.
+ VAR is address of the variable which will contain the matching string
+ (from ENUMLIST).
+ DOC is the documentation string. */
+
+struct cmd_list_element *
+add_set_enum_cmd (name, class, enumlist, var, doc, list)
+ char *name;
+ enum command_class class;
+ char *enumlist[];
+ char *var;
+ char *doc;
+ struct cmd_list_element **list;
+{
+ struct cmd_list_element *c
+ = add_set_cmd (name, class, var_enum, var, doc, list);
+ c->enums = enumlist;
+
+ return c;
+}
+
+/* Where SETCMD has already been added, add the corresponding show
+ command to LIST and return a pointer to the added command (not
+ necessarily the head of LIST). */
+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));
+ struct cmd_list_element *p;
+
+ 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_unfiltered (gdb_stderr, "GDB internal error: Bad docstring for set command\n");
+
+ if (*list == NULL || STRCMP ((*list)->name, showcmd->name) >= 0)
+ {
+ showcmd->next = *list;
+ *list = showcmd;
+ }
+ else
+ {
+ p = *list;
+ while (p->next && STRCMP (p->next->name, showcmd->name) <= 0)
+ {
+ p = p->next;
+ }
+ showcmd->next = p->next;
+ p->next = showcmd;
+ }
+
+ return showcmd;
+}
+
+/* Remove the command named NAME from the command list. */
+
+void
+delete_cmd (name, list)
+ char *name;
+ struct cmd_list_element **list;
+{
+ register struct cmd_list_element *c;
+ struct cmd_list_element *p;
+
+ while (*list && STREQ ((*list)->name, name))
+ {
+ 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 (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;
+ }
+}
+
+/* This command really has to deal with two things:
+ * 1) I want documentation on *this string* (usually called by
+ * "help commandname").
+ * 2) I want documentation on *this list* (usually called by
+ * giving a command that requires subcommands. Also called by saying
+ * just "help".)
+ *
+ * I am going to split this into two seperate comamnds, help_cmd and
+ * help_list.
+ */
+
+void
+help_cmd (command, stream)
+ char *command;
+ GDB_FILE *stream;
+{
+ struct cmd_list_element *c;
+ extern struct cmd_list_element *cmdlist;
+
+ if (!command)
+ {
+ help_list (cmdlist, "", all_classes, stream);
+ return;
+ }
+
+ c = lookup_cmd (&command, cmdlist, "", 0, 0);
+
+ if (c == 0)
+ return;
+
+ /* There are three cases here.
+ If c->prefixlist is nonzero, we have a prefix command.
+ Print its documentation, then list its subcommands.
+
+ If c->function is nonzero, we really have a command.
+ Print its documentation and return.
+
+ If c->function is zero, we have a class name.
+ Print its documentation (as if it were a command)
+ and then set class to the number of this class
+ so that the commands in the class will be listed. */
+
+ fputs_filtered (c->doc, stream);
+ fputs_filtered ("\n", stream);
+
+ if (c->prefixlist == 0 && c->function.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, all_commands, stream);
+
+ /* If this is a class name, print all of the commands in the class */
+ 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);
+}
+
+/*
+ * Get a specific kind of help on a command list.
+ *
+ * LIST is the list.
+ * CMDTYPE is the prefix to use in the title string.
+ * CLASS is the class with which to list the nodes of this list (see
+ * documentation for help_cmd_list below), As usual, ALL_COMMANDS for
+ * everything, ALL_CLASSES for just classes, and non-negative for only things
+ * in a specific class.
+ * and STREAM is the output stream on which to print things.
+ * If you call this routine with a class >= 0, it recurses.
+ */
+void
+help_list (list, cmdtype, class, stream)
+ struct cmd_list_element *list;
+ char *cmdtype;
+ enum command_class class;
+ GDB_FILE *stream;
+{
+ int len;
+ char *cmdtype1, *cmdtype2;
+
+ /* If CMDTYPE is "foo ", CMDTYPE1 gets " foo" and CMDTYPE2 gets "foo sub" */
+ len = strlen (cmdtype);
+ cmdtype1 = (char *) alloca (len + 1);
+ cmdtype1[0] = 0;
+ cmdtype2 = (char *) alloca (len + 4);
+ cmdtype2[0] = 0;
+ if (len)
+ {
+ cmdtype1[0] = ' ';
+ strncpy (cmdtype1 + 1, cmdtype, len - 1);
+ cmdtype1[len] = 0;
+ strncpy (cmdtype2, cmdtype, len - 1);
+ strcpy (cmdtype2 + len - 1, " sub");
+ }
+
+ if (class == all_classes)
+ fprintf_filtered (stream, "List of classes of %scommands:\n\n", cmdtype2);
+ else
+ fprintf_filtered (stream, "List of %scommands:\n\n", cmdtype2);
+
+ help_cmd_list (list, class, cmdtype, (int)class >= 0, stream);
+
+ if (class == all_classes)
+ fprintf_filtered (stream, "\n\
+Type \"help%s\" followed by a class name for a list of commands in that class.",
+ cmdtype1);
+
+ fprintf_filtered (stream, "\n\
+Type \"help%s\" followed by %scommand name for full documentation.\n\
+Command name abbreviations are allowed if unambiguous.\n",
+ cmdtype1, cmdtype2);
+}
+
+/* Print only the first line of STR on STREAM. */
+static void
+print_doc_line (stream, str)
+ GDB_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.
+ * RECURSE should be non-zero if this should be done recursively on
+ * all sublists of LIST.
+ * PREFIX is the prefix to print before each command name.
+ * STREAM is the stream upon which the output should be written.
+ * CLASS should be:
+ * A non-negative class number to list only commands in that
+ * class.
+ * ALL_COMMANDS to list all commands in list.
+ * ALL_CLASSES to list all classes in list.
+ *
+ * Note that RECURSE will be active on *all* sublists, not just the
+ * ones 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;
+ enum command_class class;
+ char *prefix;
+ int recurse;
+ GDB_FILE *stream;
+{
+ register struct cmd_list_element *c;
+
+ for (c = list; c; c = c->next)
+ {
+ if (c->abbrev_flag == 0 &&
+ (class == all_commands
+ || (class == all_classes && c->function.cfunc == NULL)
+ || (class == c->class && c->function.cfunc != NULL)))
+ {
+ fprintf_filtered (stream, "%s%s -- ", prefix, c->name);
+ print_doc_line (stream, c->doc);
+ fputs_filtered ("\n", stream);
+ }
+ if (recurse
+ && c->prefixlist != 0
+ && c->abbrev_flag == 0)
+ help_cmd_list (*c->prefixlist, class, c->prefixname, 1, stream);
+ }
+}
+
+
+/* Search the input clist for 'command'. Return the command if
+ found (or NULL if not), and return the number of commands
+ found in nfound */
+
+static struct cmd_list_element *
+find_cmd(command, len, clist, ignore_help_classes, nfound)
+ char *command;
+ struct cmd_list_element *clist;
+ int ignore_help_classes;
+ int *nfound;
+{
+ struct cmd_list_element *found, *c;
+
+ found = (struct cmd_list_element *)NULL;
+ *nfound = 0;
+ for (c = clist; c; c = c->next)
+ if (!strncmp (command, c->name, len)
+ && (!ignore_help_classes || c->function.cfunc))
+ {
+ found = c;
+ (*nfound)++;
+ if (c->name[len] == '\0')
+ {
+ *nfound = 1;
+ break;
+ }
+ }
+ return found;
+}
+
+/* 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 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 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)
+ char **text;
+ struct cmd_list_element *clist, **result_list;
+ int ignore_help_classes;
+{
+ char *p, *command;
+ int len, tmp, nfound;
+ struct cmd_list_element *found, *c;
+
+ while (**text == ' ' || **text == '\t')
+ (*text)++;
+
+ /* Treating underscores as part of command words is important
+ so that "set args_foo()" doesn't get interpreted as
+ "set args _foo()". */
+ for (p = *text;
+ *p && (isalnum(*p) || *p == '-' || *p == '_' ||
+ (tui_version &&
+ (*p == '+' || *p == '<' || *p == '>' || *p == '$')) ||
+ (xdb_commands && (*p == '!' || *p == '/' || *p == '?')));
+ p++)
+ ;
+
+ /* If nothing but whitespace, return 0. */
+ if (p == *text)
+ return 0;
+
+ len = p - *text;
+
+ /* *text and p now bracket the first command word to lookup (and
+ it's length is len). We copy this into a local temporary */
+
+
+ command = (char *) alloca (len + 1);
+ for (tmp = 0; tmp < len; tmp++)
+ {
+ char x = (*text)[tmp];
+ command[tmp] = x;
+ }
+ command[len] = '\0';
+
+ /* Look it up. */
+ found = 0;
+ nfound = 0;
+ found = find_cmd(command, len, clist, ignore_help_classes, &nfound);
+
+ /*
+ ** We didn't find the command in the entered case, so lower case it
+ ** and search again.
+ */
+ if (!found || nfound == 0)
+ {
+ for (tmp = 0; tmp < len; tmp++)
+ {
+ char x = command[tmp];
+ command[tmp] = isupper(x) ? tolower(x) : x;
+ }
+ found = find_cmd(command, len, clist, ignore_help_classes, &nfound);
+ }
+
+ /* If nothing matches, we have a simple failure. */
+ if (nfound == 0)
+ return 0;
+
+ if (nfound > 1)
+ {
+ if (result_list != NULL)
+ /* Will be modified in calling routine
+ if we know what the prefix command is. */
+ *result_list = 0;
+ return (struct cmd_list_element *) -1; /* Ambiguous. */
+ }
+
+ /* We've matched something on this list. Move text pointer forward. */
+
+ *text = p;
+
+ /* If 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,
+ ignore_help_classes);
+ if (!c)
+ {
+ /* Didn't find anything; this is as far as we got. */
+ if (result_list != NULL)
+ *result_list = clist;
+ return found;
+ }
+ else if (c == (struct cmd_list_element *) -1)
+ {
+ /* We've gotten this far properly, but the next step
+ is ambiguous. We need to set the result list to the best
+ we've found (if an inferior hasn't already set it). */
+ if (result_list != NULL)
+ if (!*result_list)
+ /* This used to say *result_list = *found->prefixlist
+ If that was correct, need to modify the documentation
+ at the top of this function to clarify what is supposed
+ to be going on. */
+ *result_list = found;
+ return c;
+ }
+ else
+ {
+ /* We matched! */
+ return c;
+ }
+ }
+ else
+ {
+ if (result_list != NULL)
+ *result_list = clist;
+ return found;
+ }
+}
+
+/* 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
+ and update *LINE to point after the command name, at the first argument.
+ If not found, call error if ALLOW_UNKNOWN is zero
+ otherwise (or if error returns) return zero.
+ Call error if specified command is ambiguous,
+ unless ALLOW_UNKNOWN is negative.
+ CMDTYPE precedes the word "command" in the error message.
+
+ If INGNORE_HELP_CLASSES is nonzero, ignore any command list
+ elements which are actually help classes rather than commands (i.e.
+ the function field of the struct cmd_list_element is 0). */
+
+struct cmd_list_element *
+lookup_cmd (line, list, cmdtype, allow_unknown, ignore_help_classes)
+ char **line;
+ struct cmd_list_element *list;
+ char *cmdtype;
+ int allow_unknown;
+ int ignore_help_classes;
+{
+ struct cmd_list_element *last_list = 0;
+ struct cmd_list_element *c =
+ lookup_cmd_1 (line, list, &last_list, ignore_help_classes);
+#if 0
+ /* This is wrong for complete_command. */
+ char *ptr = (*line) + strlen (*line) - 1;
+
+ /* Clear off trailing whitespace. */
+ while (ptr >= *line && (*ptr == ' ' || *ptr == '\t'))
+ ptr--;
+ *(ptr + 1) = '\0';
+#endif
+
+ if (!c)
+ {
+ if (!allow_unknown)
+ {
+ if (!*line)
+ error ("Lack of needed %scommand", cmdtype);
+ else
+ {
+ char *p = *line, *q;
+
+ while (isalnum(*p) || *p == '-')
+ p++;
+
+ q = (char *) alloca (p - *line + 1);
+ strncpy (q, *line, p - *line);
+ q[p - *line] = '\0';
+ undef_cmd_error (cmdtype, q);
+ }
+ }
+ else
+ return 0;
+ }
+ else if (c == (struct cmd_list_element *) -1)
+ {
+ /* Ambigous. Local values should be off prefixlist or called
+ values. */
+ int local_allow_unknown = (last_list ? last_list->allow_unknown :
+ allow_unknown);
+ char *local_cmdtype = last_list ? last_list->prefixname : cmdtype;
+ struct cmd_list_element *local_list =
+ (last_list ? *(last_list->prefixlist) : list);
+
+ if (local_allow_unknown < 0)
+ {
+ if (last_list)
+ return last_list; /* Found something. */
+ else
+ return 0; /* Found nothing. */
+ }
+ else
+ {
+ /* Report as error. */
+ int amb_len;
+ char ambbuf[100];
+
+ for (amb_len = 0;
+ ((*line)[amb_len] && (*line)[amb_len] != ' '
+ && (*line)[amb_len] != '\t');
+ amb_len++)
+ ;
+
+ ambbuf[0] = 0;
+ for (c = local_list; c; c = c->next)
+ if (!strncmp (*line, c->name, amb_len))
+ {
+ if (strlen (ambbuf) + strlen (c->name) + 6 < (int)sizeof ambbuf)
+ {
+ if (strlen (ambbuf))
+ strcat (ambbuf, ", ");
+ strcat (ambbuf, c->name);
+ }
+ else
+ {
+ strcat (ambbuf, "..");
+ break;
+ }
+ }
+ error ("Ambiguous %scommand \"%s\": %s.", local_cmdtype,
+ *line, ambbuf);
+ return 0; /* lint */
+ }
+ }
+ else
+ {
+ /* We've got something. It may still not be what the caller
+ wants (if this command *needs* a subcommand). */
+ while (**line == ' ' || **line == '\t')
+ (*line)++;
+
+ if (c->prefixlist && **line && !c->allow_unknown)
+ undef_cmd_error (c->prefixname, *line);
+
+ /* Seems to be what he wants. Return it. */
+ return c;
+ }
+ return 0;
+}
+
+#if 0
+/* Look up the contents of *LINE as a command in the command list LIST.
+ LIST is a chain of struct cmd_list_element's.
+ If it is found, return the struct cmd_list_element for that command
+ and update *LINE to point after the command name, at the first argument.
+ If not found, call error if ALLOW_UNKNOWN is zero
+ otherwise (or if error returns) return zero.
+ Call error if specified command is ambiguous,
+ unless ALLOW_UNKNOWN is negative.
+ CMDTYPE precedes the word "command" in the error message. */
+
+struct cmd_list_element *
+lookup_cmd (line, list, cmdtype, allow_unknown)
+ char **line;
+ struct cmd_list_element *list;
+ char *cmdtype;
+ int allow_unknown;
+{
+ register char *p;
+ register struct cmd_list_element *c, *found;
+ int nfound;
+ char ambbuf[100];
+ char *processed_cmd;
+ int i, cmd_len;
+
+ /* Skip leading whitespace. */
+
+ while (**line == ' ' || **line == '\t')
+ (*line)++;
+
+ /* Clear out trailing whitespace. */
+
+ p = *line + strlen (*line);
+ while (p != *line && (p[-1] == ' ' || p[-1] == '\t'))
+ p--;
+ *p = 0;
+
+ /* Find end of command name. */
+
+ p = *line;
+ while (*p == '-' || isalnum(*p))
+ p++;
+
+ /* Look up the command name.
+ If exact match, keep that.
+ Otherwise, take command abbreviated, if unique. Note that (in my
+ opinion) a null string does *not* indicate ambiguity; simply the
+ end of the argument. */
+
+ if (p == *line)
+ {
+ if (!allow_unknown)
+ error ("Lack of needed %scommand", cmdtype);
+ return 0;
+ }
+
+ /* Copy over to a local buffer, converting to lowercase on the way.
+ This is in case the command being parsed is a subcommand which
+ doesn't match anything, and that's ok. We want the original
+ untouched for the routine of the original command. */
+
+ processed_cmd = (char *) alloca (p - *line + 1);
+ for (cmd_len = 0; cmd_len < p - *line; cmd_len++)
+ {
+ char x = (*line)[cmd_len];
+ if (isupper(x))
+ processed_cmd[cmd_len] = tolower(x);
+ else
+ processed_cmd[cmd_len] = x;
+ }
+ processed_cmd[cmd_len] = '\0';
+
+ /* Check all possibilities in the current command list. */
+ found = 0;
+ nfound = 0;
+ for (c = list; c; c = c->next)
+ {
+ if (!strncmp (processed_cmd, c->name, cmd_len))
+ {
+ found = c;
+ nfound++;
+ if (c->name[cmd_len] == 0)
+ {
+ nfound = 1;
+ break;
+ }
+ }
+ }
+
+ /* Report error for undefined command name. */
+
+ if (nfound != 1)
+ {
+ if (nfound > 1 && allow_unknown >= 0)
+ {
+ ambbuf[0] = 0;
+ for (c = list; c; c = c->next)
+ if (!strncmp (processed_cmd, c->name, cmd_len))
+ {
+ if (strlen (ambbuf) + strlen (c->name) + 6 < sizeof ambbuf)
+ {
+ if (strlen (ambbuf))
+ strcat (ambbuf, ", ");
+ strcat (ambbuf, c->name);
+ }
+ else
+ {
+ strcat (ambbuf, "..");
+ break;
+ }
+ }
+ error ("Ambiguous %scommand \"%s\": %s.", cmdtype,
+ processed_cmd, ambbuf);
+ }
+ else if (!allow_unknown)
+ error ("Undefined %scommand: \"%s\".", cmdtype, processed_cmd);
+ return 0;
+ }
+
+ /* Skip whitespace before the argument. */
+
+ while (*p == ' ' || *p == '\t') p++;
+ *line = p;
+
+ if (found->prefixlist && *p)
+ {
+ c = lookup_cmd (line, *found->prefixlist, found->prefixname,
+ found->allow_unknown);
+ if (c)
+ return c;
+ }
+
+ return found;
+}
+#endif
+
+/* Helper function for SYMBOL_COMPLETION_FUNCTION. */
+
+/* Return a vector of char pointers which point to the different
+ possible completions in LIST of TEXT.
+
+ 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, word)
+ struct cmd_list_element *list;
+ char *text;
+ char *word;
+{
+ struct cmd_list_element *ptr;
+ char **matchlist;
+ int sizeof_matchlist;
+ int matches;
+ int textlen = strlen (text);
+
+ sizeof_matchlist = 10;
+ matchlist = (char **) xmalloc (sizeof_matchlist * sizeof (char *));
+ matches = 0;
+
+ for (ptr = list; ptr; ptr = ptr->next)
+ if (!strncmp (ptr->name, text, textlen)
+ && !ptr->abbrev_flag
+ && (ptr->function.cfunc
+ || ptr->prefixlist))
+ {
+ if (matches == sizeof_matchlist)
+ {
+ sizeof_matchlist *= 2;
+ matchlist = (char **) xrealloc ((char *)matchlist,
+ (sizeof_matchlist
+ * sizeof (char *)));
+ }
+
+ matchlist[matches] = (char *)
+ 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 ((PTR)matchlist);
+ matchlist = 0;
+ }
+ else
+ {
+ matchlist = (char **) xrealloc ((char *)matchlist, ((matches + 1)
+ * sizeof (char *)));
+ matchlist[matches] = (char *) 0;
+ }
+
+ return matchlist;
+}
+
+/* Helper function for SYMBOL_COMPLETION_FUNCTION. */
+
+/* Return a vector of char pointers which point to the different
+ possible completions in CMD 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_enum (enumlist, text, word)
+ char **enumlist;
+ char *text;
+ char *word;
+{
+ char **matchlist;
+ int sizeof_matchlist;
+ int matches;
+ int textlen = strlen (text);
+ int i;
+ char *name;
+
+ sizeof_matchlist = 10;
+ matchlist = (char **) xmalloc (sizeof_matchlist * sizeof (char *));
+ matches = 0;
+
+ for (i = 0; (name = enumlist[i]) != NULL; i++)
+ if (strncmp (name, text, textlen) == 0)
+ {
+ if (matches == sizeof_matchlist)
+ {
+ sizeof_matchlist *= 2;
+ matchlist = (char **) xrealloc ((char *)matchlist,
+ (sizeof_matchlist
+ * sizeof (char *)));
+ }
+
+ matchlist[matches] = (char *)
+ xmalloc (strlen (word) + strlen (name) + 1);
+ if (word == text)
+ strcpy (matchlist[matches], name);
+ else if (word > text)
+ {
+ /* Return some portion of name. */
+ strcpy (matchlist[matches], name + (word - text));
+ }
+ else
+ {
+ /* Return some of text plus name. */
+ strncpy (matchlist[matches], word, text - word);
+ matchlist[matches][text - word] = '\0';
+ strcat (matchlist[matches], name);
+ }
+ ++matches;
+ }
+
+ if (matches == 0)
+ {
+ free ((PTR)matchlist);
+ matchlist = 0;
+ }
+ else
+ {
+ matchlist = (char **) xrealloc ((char *)matchlist, ((matches + 1)
+ * sizeof (char *)));
+ matchlist[matches] = (char *) 0;
+ }
+
+ return matchlist;
+}
+
+static int
+parse_binary_operation (arg)
+ char *arg;
+{
+ int length;
+
+ if (!arg || !*arg)
+ return 1;
+
+ length = strlen (arg);
+
+ while (arg[length - 1] == ' ' || arg[length - 1] == '\t')
+ length--;
+
+ if (!strncmp (arg, "on", length)
+ || !strncmp (arg, "1", length)
+ || !strncmp (arg, "yes", length))
+ return 1;
+ else
+ if (!strncmp (arg, "off", length)
+ || !strncmp (arg, "0", length)
+ || !strncmp (arg, "no", length))
+ return 0;
+ else
+ {
+ error ("\"on\" or \"off\" expected.");
+ return 0;
+ }
+}
+
+/* Do a "set" or "show" command. ARG is NULL if no argument, or the text
+ of the argument, and FROM_TTY is nonzero if this command is being entered
+ directly by the user (i.e. these are just like any other
+ command). C is the command list element for the command. */
+void
+do_setshow_command (arg, from_tty, c)
+ char *arg;
+ int from_tty;
+ struct cmd_list_element *c;
+{
+ if (c->type == set_cmd)
+ {
+ switch (c->var_type)
+ {
+ case var_string:
+ {
+ char *new;
+ char *p;
+ char *q;
+ int ch;
+
+ if (arg == NULL)
+ arg = "";
+ new = (char *) xmalloc (strlen (arg) + 2);
+ p = arg; q = new;
+ while ((ch = *p++) != '\000')
+ {
+ if (ch == '\\')
+ {
+ /* \ at end of argument is used after spaces
+ so they won't be lost. */
+ /* This is obsolete now that we no longer strip
+ trailing whitespace and actually, the backslash
+ didn't get here in my test, readline or
+ something did something funky with a backslash
+ right before a newline. */
+ if (*p == 0)
+ break;
+ ch = parse_escape (&p);
+ if (ch == 0)
+ break; /* C loses */
+ else if (ch > 0)
+ *q++ = ch;
+ }
+ else
+ *q++ = ch;
+ }
+#if 0
+ if (*(p - 1) != '\\')
+ *q++ = ' ';
+#endif
+ *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;
+ case var_enum:
+ {
+ int i;
+ int len;
+ int nmatches;
+ char *match = NULL;
+ char *p;
+
+ /* if no argument was supplied, print an informative error message */
+ if (arg == NULL)
+ {
+ char msg[1024];
+ strcpy (msg, "Requires an argument. Valid arguments are ");
+ for (i = 0; c->enums[i]; i++)
+ {
+ if (i != 0)
+ strcat (msg, ", ");
+ strcat (msg, c->enums[i]);
+ }
+ strcat (msg, ".");
+ error (msg);
+ }
+
+ p = strchr (arg, ' ');
+
+ if (p)
+ len = p - arg;
+ else
+ len = strlen (arg);
+
+ nmatches = 0;
+ for (i = 0; c->enums[i]; i++)
+ if (strncmp (arg, c->enums[i], len) == 0)
+ {
+ match = c->enums[i];
+ nmatches++;
+ }
+
+ if (nmatches <= 0)
+ error ("Undefined item: \"%s\".", arg);
+
+ if (nmatches > 1)
+ error ("Ambiguous item \"%s\".", arg);
+
+ *(char **)c->var = match;
+ }
+ 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 (gdb_stdout, c->doc + 5);
+
+ fputs_filtered (" is ", gdb_stdout);
+ wrap_here (" ");
+ switch (c->var_type)
+ {
+ case var_string:
+ {
+ unsigned char *p;
+
+ fputs_filtered ("\"", gdb_stdout);
+ if (*(unsigned char **)c->var)
+ for (p = *(unsigned char **) c->var; *p != '\0'; p++)
+ gdb_printchar (*p, gdb_stdout, '"');
+ fputs_filtered ("\"", gdb_stdout);
+ }
+ break;
+ case var_string_noescape:
+ case var_filename:
+ case var_enum:
+ fputs_filtered ("\"", gdb_stdout);
+ if (*(char **)c->var)
+ fputs_filtered (*(char **) c->var, gdb_stdout);
+ fputs_filtered ("\"", gdb_stdout);
+ break;
+ case var_boolean:
+ fputs_filtered (*(int *) c->var ? "on" : "off", gdb_stdout);
+ break;
+ case var_uinteger:
+ if (*(unsigned int *) c->var == UINT_MAX) {
+ fputs_filtered ("unlimited", gdb_stdout);
+ break;
+ }
+ /* else fall through */
+ case var_zinteger:
+ fprintf_filtered (gdb_stdout, "%u", *(unsigned int *) c->var);
+ break;
+ case var_integer:
+ if (*(int *) c->var == INT_MAX)
+ {
+ fputs_filtered ("unlimited", gdb_stdout);
+ }
+ else
+ fprintf_filtered (gdb_stdout, "%d", *(int *) c->var);
+ break;
+
+ default:
+ error ("gdb internal error: bad var_type in do_setshow_command");
+ }
+ fputs_filtered (".\n", gdb_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, gdb_stdout);
+ fputs_filtered (list->name, gdb_stdout);
+ fputs_filtered (": ", gdb_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;
+
+ if ((user_shell = (char *) getenv ("SHELL")) == NULL)
+ user_shell = "/bin/sh";
+
+ /* Get the name of the shell for arg0 */
+ if ((p = strrchr (user_shell, '/')) == NULL)
+ p = user_shell;
+ else
+ p++; /* Get past '/' */
+
+ if ((pid = fork()) == 0)
+ {
+ if (!arg)
+ execl (user_shell, p, 0);
+ else
+ execl (user_shell, p, "-c", arg, 0);
+
+ fprintf_unfiltered (gdb_stderr, "Cannot execute %s: %s\n", user_shell,
+ safe_strerror (errno));
+ gdb_flush (gdb_stderr);
+ _exit (0177);
+ }
+
+ if (pid != -1)
+ while ((rc = wait (&status)) != pid && rc != -1)
+ ;
+ 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;
+ GDB_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)
+ {
+ print_command_line (cmdlines, 4);
+ 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, gdb_stdout);
+ }
+ else
+ {
+ for (c = cmdlist; c; c = c->next)
+ {
+ if (c->class == class_user)
+ show_user_1 (c, gdb_stdout);
+ }
+ }
+}
+
+void
+_initialize_command ()
+{
+ add_com ("shell", class_support, shell_escape,
+ "Execute the rest of the line as a shell command. \n\
+With no arguments, run an inferior shell.");
+
+ if (xdb_commands)
+ add_com_alias("!", "shell", class_support, 0);
+
+ 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/gdb/command.h b/gdb/command.h
new file mode 100644
index 00000000000..5a209234e08
--- /dev/null
+++ b/gdb/command.h
@@ -0,0 +1,259 @@
+/* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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,
+ /* Enumerated type. Can only have one of the specified values. *VAR is a
+ char pointer to the name of the element that we find. */
+ var_enum
+} 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.
+ NO_FUNCTION for command class names and for help topics that
+ are not really commands. */
+ union
+ {
+ /* If type is not_set_cmd, call it like this: */
+ void (*cfunc) PARAMS ((char *args, int from_tty));
+
+ /* If type is cmd_set or show_cmd, first set the variables, and
+ then call this. */
+ 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 NULL terminated list of enumerated values (like argv). */
+ char **enums;
+
+ /* 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 char **
+complete_on_enum PARAMS ((char **enumlist, char *, char *));
+
+extern void
+delete_cmd PARAMS ((char *, struct cmd_list_element **));
+
+extern void
+help_cmd PARAMS ((char *, GDB_FILE *));
+
+extern void
+help_list PARAMS ((struct cmd_list_element *, char *, enum command_class,
+ GDB_FILE *));
+
+extern void
+help_cmd_list PARAMS ((struct cmd_list_element *, enum command_class, char *,
+ int, GDB_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_set_enum_cmd PARAMS ((char *name, enum command_class, char *list[],
+ char *var, char *doc, struct cmd_list_element **c));
+
+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/gdb/complaints.c b/gdb/complaints.c
new file mode 100644
index 00000000000..e38038d26fb
--- /dev/null
+++ b/gdb/complaints.c
@@ -0,0 +1,166 @@
+/* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "complaints.h"
+#include "gdbcmd.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
+#ifdef ANSI_PROTOTYPES
+complain (struct complaint *complaint, ...)
+#else
+complain (va_alist)
+ va_dcl
+#endif
+{
+ va_list args;
+#ifdef ANSI_PROTOTYPES
+ va_start (args, complaint);
+#else
+ struct complaint *complaint;
+
+ va_start (args);
+ complaint = va_arg (args, struct complaint *);
+#endif
+
+ 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. */
+ gdb_flush (gdb_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/gdb/complaints.h b/gdb/complaints.h
new file mode 100644
index 00000000000..4b9b5de5236
--- /dev/null
+++ b/gdb/complaints.h
@@ -0,0 +1,53 @@
+/* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+
+#if !defined (COMPLAINTS_H)
+#define COMPLAINTS_H
+
+
+/* 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 PARAMS ((struct complaint *, ...));
+
+extern void
+clear_complaints PARAMS ((int, int));
+
+
+#endif /* !defined (COMPLAINTS_H) */
diff --git a/gdb/config.in b/gdb/config.in
new file mode 100644
index 00000000000..d6bfe942126
--- /dev/null
+++ b/gdb/config.in
@@ -0,0 +1,325 @@
+/* config.in. Generated automatically from configure.in by autoheader. */
+
+/* Whether malloc must be declared even if <stdlib.h> is included. */
+#undef NEED_DECLARATION_MALLOC
+
+/* Whether realloc must be declared even if <stdlib.h> is included. */
+#undef NEED_DECLARATION_REALLOC
+
+/* Whether free must be declared even if <stdlib.h> is included. */
+#undef NEED_DECLARATION_FREE
+
+/* Whether strerror must be declared even if <string.h> is included. */
+#undef NEED_DECLARATION_STRERROR
+
+/* Define if on AIX 3.
+ System headers sometimes define this.
+ We just want to avoid a redefinition error message. */
+#ifndef _ALL_SOURCE
+#undef _ALL_SOURCE
+#endif
+
+/* Define if using alloca.c. */
+#undef C_ALLOCA
+
+/* Define to empty if the keyword does not work. */
+#undef const
+
+/* Define to one of _getb67, GETB67, getb67 for Cray-2 and Cray-YMP systems.
+ This function is required for alloca.c support on those systems. */
+#undef CRAY_STACKSEG_END
+
+/* Define if you have alloca, as a function or macro. */
+#undef HAVE_ALLOCA
+
+/* Define if you have <alloca.h> and it should be used (not on Ultrix). */
+#undef HAVE_ALLOCA_H
+
+/* Define if the `long double' type works. */
+#undef HAVE_LONG_DOUBLE
+
+/* Define if you have a working `mmap' system call. */
+#undef HAVE_MMAP
+
+/* Define as __inline if that's what the C compiler calls it. */
+#undef inline
+
+/* Define to `long' if <sys/types.h> doesn't define. */
+#undef off_t
+
+/* Define if you need to in order for stat and other things to work. */
+#undef _POSIX_SOURCE
+
+/* Define as the return type of signal handlers (int or void). */
+#undef RETSIGTYPE
+
+/* Define to `unsigned' if <sys/types.h> doesn't define. */
+#undef size_t
+
+/* If using the C implementation of alloca, define if you know the
+ direction of stack growth for your system; otherwise it will be
+ automatically deduced at run-time.
+ STACK_DIRECTION > 0 => grows toward higher addresses
+ STACK_DIRECTION < 0 => grows toward lower addresses
+ STACK_DIRECTION = 0 => direction of growth unknown
+ */
+#undef STACK_DIRECTION
+
+/* Define if the `S_IS*' macros in <sys/stat.h> do not work properly. */
+#undef STAT_MACROS_BROKEN
+
+/* Define if you have the ANSI C header files. */
+#undef STDC_HEADERS
+
+/* Define if ioctl argument PIOCSET is available. */
+#undef HAVE_PROCFS_PIOCSET
+
+/* /proc PID entries are directories containing the files
+ ctl as map status */
+#undef HAVE_MULTIPLE_PROC_FDS
+
+/* Define if the `long long' type works. */
+#undef CC_HAS_LONG_LONG
+
+/* Define if the "ll" format works to print long long ints. */
+#undef PRINTF_HAS_LONG_LONG
+
+/* Define if the "%Lg" format works to print long doubles. */
+#undef PRINTF_HAS_LONG_DOUBLE
+
+/* Define if the "%Lg" format works to scan long doubles. */
+#undef SCANF_HAS_LONG_DOUBLE
+
+/* Define if using Solaris thread debugging. */
+#undef HAVE_THREAD_DB_LIB
+
+/* Define on a GNU/Linux system to work around problems in sys/procfs.h. */
+#undef START_INFERIOR_TRAPS_EXPECTED
+#undef sys_quotactl
+
+/* Define if you have HPUX threads */
+#undef HAVE_HPUX_THREAD_SUPPORT
+
+/* Define if you want to use the memory mapped malloc package (mmalloc). */
+#undef USE_MMALLOC
+
+/* Define if the runtime uses a routine from mmalloc before gdb has a chance
+ to initialize mmalloc, and we want to force checking to be used anyway.
+ This may cause spurious memory corruption messages if the runtime tries
+ to explicitly deallocate that memory when gdb calls exit. */
+#undef MMCHECK_FORCE
+
+/* Define if you want to use the full-screen terminal user interface. */
+#undef TUI
+
+/* Define if <proc_service.h> on solaris uses int instead of
+ size_t, and assorted other type changes. */
+#undef PROC_SERVICE_IS_OLD
+
+/* Set to true if the save_state_t structure is present */
+#define HAVE_STRUCT_SAVE_STATE_T 0
+
+/* Set to true if the save_state_t structure has the ss_wide member */
+#define HAVE_STRUCT_MEMBER_SS_WIDE 0
+
+/* Define if you have the __argz_count function. */
+#undef HAVE___ARGZ_COUNT
+
+/* Define if you have the __argz_next function. */
+#undef HAVE___ARGZ_NEXT
+
+/* Define if you have the __argz_stringify function. */
+#undef HAVE___ARGZ_STRINGIFY
+
+/* Define if you have the bcopy function. */
+#undef HAVE_BCOPY
+
+/* Define if you have the btowc function. */
+#undef HAVE_BTOWC
+
+/* Define if you have the bzero function. */
+#undef HAVE_BZERO
+
+/* Define if you have the dcgettext function. */
+#undef HAVE_DCGETTEXT
+
+/* Define if you have the getcwd function. */
+#undef HAVE_GETCWD
+
+/* Define if you have the getpagesize function. */
+#undef HAVE_GETPAGESIZE
+
+/* Define if you have the isascii function. */
+#undef HAVE_ISASCII
+
+/* Define if you have the munmap function. */
+#undef HAVE_MUNMAP
+
+/* Define if you have the putenv function. */
+#undef HAVE_PUTENV
+
+/* Define if you have the sbrk function. */
+#undef HAVE_SBRK
+
+/* Define if you have the setenv function. */
+#undef HAVE_SETENV
+
+/* Define if you have the setlocale function. */
+#undef HAVE_SETLOCALE
+
+/* Define if you have the setpgid function. */
+#undef HAVE_SETPGID
+
+/* Define if you have the sigaction function. */
+#undef HAVE_SIGACTION
+
+/* Define if you have the stpcpy function. */
+#undef HAVE_STPCPY
+
+/* Define if you have the strcasecmp function. */
+#undef HAVE_STRCASECMP
+
+/* Define if you have the strchr function. */
+#undef HAVE_STRCHR
+
+/* Define if you have the <argz.h> header file. */
+#undef HAVE_ARGZ_H
+
+/* Define if you have the <asm/debugreg.h> header file. */
+#undef HAVE_ASM_DEBUGREG_H
+
+/* Define if you have the <ctype.h> header file. */
+#undef HAVE_CTYPE_H
+
+/* Define if you have the <curses.h> header file. */
+#undef HAVE_CURSES_H
+
+/* Define if you have the <endian.h> header file. */
+#undef HAVE_ENDIAN_H
+
+/* Define if you have the <limits.h> header file. */
+#undef HAVE_LIMITS_H
+
+/* Define if you have the <link.h> header file. */
+#undef HAVE_LINK_H
+
+/* Define if you have the <locale.h> header file. */
+#undef HAVE_LOCALE_H
+
+/* Define if you have the <malloc.h> header file. */
+#undef HAVE_MALLOC_H
+
+/* Define if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H
+
+/* Define if you have the <nl_types.h> header file. */
+#undef HAVE_NL_TYPES_H
+
+/* Define if you have the <objlist.h> header file. */
+#undef HAVE_OBJLIST_H
+
+/* Define if you have the <ptrace.h> header file. */
+#undef HAVE_PTRACE_H
+
+/* Define if you have the <sgtty.h> header file. */
+#undef HAVE_SGTTY_H
+
+/* Define if you have the <stddef.h> header file. */
+#undef HAVE_STDDEF_H
+
+/* Define if you have the <stdlib.h> header file. */
+#undef HAVE_STDLIB_H
+
+/* Define if you have the <string.h> header file. */
+#undef HAVE_STRING_H
+
+/* Define if you have the <sys/debugreg.h> header file. */
+#undef HAVE_SYS_DEBUGREG_H
+
+/* Define if you have the <sys/param.h> header file. */
+#undef HAVE_SYS_PARAM_H
+
+/* Define if you have the <sys/procfs.h> header file. */
+#undef HAVE_SYS_PROCFS_H
+
+/* Define if you have the <sys/ptrace.h> header file. */
+#undef HAVE_SYS_PTRACE_H
+
+/* Define if you have the <sys/reg.h> header file. */
+#undef HAVE_SYS_REG_H
+
+/* Define if you have the <sys/wait.h> header file. */
+#undef HAVE_SYS_WAIT_H
+
+/* Define if you have the <term.h> header file. */
+#undef HAVE_TERM_H
+
+/* Define if you have the <termio.h> header file. */
+#undef HAVE_TERMIO_H
+
+/* Define if you have the <termios.h> header file. */
+#undef HAVE_TERMIOS_H
+
+/* Define if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* Define if you have the <values.h> header file. */
+#undef HAVE_VALUES_H
+
+/* Define if you have the <wait.h> header file. */
+#undef HAVE_WAIT_H
+
+/* Define if you have the <wchar.h> header file. */
+#undef HAVE_WCHAR_H
+
+/* Define if you have the <wctype.h> header file. */
+#undef HAVE_WCTYPE_H
+
+/* Define if you have the dl library (-ldl). */
+#undef HAVE_LIBDL
+
+/* Define if you have the m library (-lm). */
+#undef HAVE_LIBM
+
+/* Define if you have the w library (-lw). */
+#undef HAVE_LIBW
+
+/* Define if you have the stpcpy function */
+#undef HAVE_STPCPY
+
+/* Define if your locale.h file contains LC_MESSAGES. */
+#undef HAVE_LC_MESSAGES
+
+/* Define to 1 if NLS is requested */
+#undef ENABLE_NLS
+
+/* Define as 1 if you have gettext and don't want to use GNU gettext. */
+#undef HAVE_GETTEXT
+
+/* Define if malloc is not declared in system header files. */
+#undef NEED_DECLARATION_MALLOC
+
+/* Define if realloc is not declared in system header files. */
+#undef NEED_DECLARATION_REALLOC
+
+/* Define if free is not declared in system header files. */
+#undef NEED_DECLARATION_FREE
+
+/* Define if strerror is not declared in system header files. */
+#undef NEED_DECLARATION_STRERROR
+
+/* Define if strdup is not declared in system header files. */
+#undef NEED_DECLARATION_STRDUP
+
+/* Define if <sys/procfs.h> has pstatus_t. */
+#undef HAVE_PSTATUS_T
+
+/* Define if <sys/procfs.h> has prrun_t. */
+#undef HAVE_PRRUN_T
+
+/* Define if <sys/procfs.h> has gregset_t. */
+#undef HAVE_GREGSET_T
+
+/* Define if <sys/procfs.h> has fpregset_t. */
+#undef HAVE_FPREGSET_T
+
diff --git a/gdb/config/a29k/a29k-kern.mt b/gdb/config/a29k/a29k-kern.mt
new file mode 100644
index 00000000000..f1a2e521b0b
--- /dev/null
+++ b/gdb/config/a29k/a29k-kern.mt
@@ -0,0 +1,13 @@
+# Target: Remote AMD 29000 that runs Unix kernel on NYU Ultra3 processor board
+
+# This builds a gdb that should run on a host (we use sun3os4) that
+# then communicates over the serial line to either an Adapt or MiniMon,
+# for use in debugging Unix kernels.
+# As compared to ordinary remote 29K debugging, this changes the register
+# numbering a bit, to hold kernel regs, and adds support for looking at
+# the upage.
+
+TDEPFILES= a29k-tdep.o remote-mm.o remote-adapt.o
+TM_FILE= tm-ultra3.h
+
+MT_CFLAGS = -DKERNEL_DEBUGGING -DNO_HIF_SUPPORT
diff --git a/gdb/config/a29k/a29k-udi.mt b/gdb/config/a29k/a29k-udi.mt
new file mode 100644
index 00000000000..15b33e62815
--- /dev/null
+++ b/gdb/config/a29k/a29k-udi.mt
@@ -0,0 +1,5 @@
+# Target: AMD 29000 on EB29K board over a serial line
+TDEPFILES= a29k-tdep.o remote-udi.o udip2soc.o udr.o udi2go32.o
+TM_FILE= tm-a29k.h
+
+MT_CFLAGS = $(HOST_IPC)
diff --git a/gdb/config/a29k/a29k.mt b/gdb/config/a29k/a29k.mt
new file mode 100644
index 00000000000..a3f5910b18f
--- /dev/null
+++ b/gdb/config/a29k/a29k.mt
@@ -0,0 +1,5 @@
+# Target: AMD 29000
+TDEPFILES= a29k-tdep.o remote-eb.o remote-adapt.o
+TM_FILE= tm-a29k.h
+
+MT_CFLAGS = -DNO_HIF_SUPPORT
diff --git a/gdb/config/a29k/nm-ultra3.h b/gdb/config/a29k/nm-ultra3.h
new file mode 100644
index 00000000000..a3bc47452c4
--- /dev/null
+++ b/gdb/config/a29k/nm-ultra3.h
@@ -0,0 +1,26 @@
+/* Host definitions for GDB running on an a29k NYU Ultracomputer
+ Copyright (C) 1986, 1987, 1989, 1991, 1992 Free Software Foundation, Inc.
+ Contributed by David Wood (wood@lab.ultra.nyu.edu).
+
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* If we ever *do* end up using the standard fetch_inferior_registers,
+ this is the right value for U_REGS_OFFSET. */
+#define U_REGS_OFFSET 0
+
+/* Override copies of {fetch,store}_inferior_registers in infptrace.c. */
+#define FETCH_INFERIOR_REGISTERS
diff --git a/gdb/config/a29k/tm-a29k.h b/gdb/config/a29k/tm-a29k.h
new file mode 100644
index 00000000000..4892ec52cb4
--- /dev/null
+++ b/gdb/config/a29k/tm-a29k.h
@@ -0,0 +1,707 @@
+/* Parameters for target machine AMD 29000, for GDB, the GNU debugger.
+ Copyright 1990, 1991, 1993, 1994 Free Software Foundation, Inc.
+ Contributed by Cygnus Support. Written by Jim Kingdon.
+
+This file is part of GDB.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Parameters for an EB29K (a board which plugs into a PC and is
+ accessed through EBMON software running on the PC, which we
+ use as we'd use a remote stub (see remote-eb.c).
+
+ If gdb is ported to other a29k machines/systems, the
+ machine/system-specific parts should be removed from this file (a
+ la tm-m68k.h). */
+
+/* Byte order is configurable, but this machine runs big-endian. */
+#define TARGET_BYTE_ORDER BIG_ENDIAN
+
+/* Floating point uses IEEE representations. */
+#define IEEE_FLOAT
+
+/* Recognize our magic number. */
+#define BADMAG(x) ((x).f_magic != 0572)
+
+/* Offset from address of function to start of its code.
+ Zero on most machines. */
+
+#define FUNCTION_START_OFFSET 0
+
+/* Advance PC across any function entry prologue instructions
+ to reach some "real" code. */
+
+#define SKIP_PROLOGUE(pc) \
+ { pc = skip_prologue (pc); }
+CORE_ADDR skip_prologue ();
+
+/* Immediately after a function call, return the saved pc.
+ Can't go through the frames for this because on some machines
+ the new frame is not set up until the new function executes
+ some instructions. */
+
+#define SAVED_PC_AFTER_CALL(frame) ((frame->flags & TRANSPARENT_FRAME) \
+ ? read_register (TPC_REGNUM) \
+ : read_register (LR0_REGNUM))
+
+/* Stack grows downward. */
+
+#define INNER_THAN(lhs,rhs) ((lhs) < (rhs))
+
+/* Stack must be aligned on 32-bit boundaries when synthesizing
+ function calls. */
+
+#define STACK_ALIGN(ADDR) (((ADDR) + 3) & ~3)
+
+/* Sequence of bytes for breakpoint instruction. */
+/* ASNEQ 0x50, gr1, gr1
+ The trap number 0x50 is chosen arbitrarily.
+ We let the command line (or previously included files) override this
+ setting. */
+#ifndef BREAKPOINT
+#if TARGET_BYTE_ORDER == BIG_ENDIAN
+#define BREAKPOINT {0x72, 0x50, 0x01, 0x01}
+#else /* Target is little-endian. */
+#define BREAKPOINT {0x01, 0x01, 0x50, 0x72}
+#endif /* Target is little-endian. */
+#endif /* BREAKPOINT */
+
+/* Amount PC must be decremented by after a breakpoint.
+ This is often the number of bytes in BREAKPOINT
+ but not always. */
+
+#define DECR_PC_AFTER_BREAK 0
+
+/* Say how long (ordinary) registers are. This is a piece of bogosity
+ used in push_word and a few other places; REGISTER_RAW_SIZE is the
+ real way to know how big a register is. */
+
+#define REGISTER_SIZE 4
+
+/* Allow the register declarations here to be overridden for remote
+ kernel debugging. */
+#if !defined (REGISTER_NAMES)
+
+/* Number of machine registers */
+
+#define NUM_REGS 205
+
+/* Initializer for an array of names of registers.
+ There should be NUM_REGS strings in this initializer.
+
+ FIXME, add floating point registers and support here.
+
+ Also note that this list does not attempt to deal with kernel
+ debugging (in which the first 32 registers are gr64-gr95). */
+
+#define REGISTER_NAMES \
+{"gr96", "gr97", "gr98", "gr99", "gr100", "gr101", "gr102", "gr103", "gr104", \
+ "gr105", "gr106", "gr107", "gr108", "gr109", "gr110", "gr111", "gr112", \
+ "gr113", "gr114", "gr115", "gr116", "gr117", "gr118", "gr119", "gr120", \
+ "gr121", "gr122", "gr123", "gr124", "gr125", "gr126", "gr127", \
+ "lr0", "lr1", "lr2", "lr3", "lr4", "lr5", "lr6", "lr7", "lr8", "lr9", \
+ "lr10", "lr11", "lr12", "lr13", "lr14", "lr15", "lr16", "lr17", "lr18", \
+ "lr19", "lr20", "lr21", "lr22", "lr23", "lr24", "lr25", "lr26", "lr27", \
+ "lr28", "lr29", "lr30", "lr31", "lr32", "lr33", "lr34", "lr35", "lr36", \
+ "lr37", "lr38", "lr39", "lr40", "lr41", "lr42", "lr43", "lr44", "lr45", \
+ "lr46", "lr47", "lr48", "lr49", "lr50", "lr51", "lr52", "lr53", "lr54", \
+ "lr55", "lr56", "lr57", "lr58", "lr59", "lr60", "lr61", "lr62", "lr63", \
+ "lr64", "lr65", "lr66", "lr67", "lr68", "lr69", "lr70", "lr71", "lr72", \
+ "lr73", "lr74", "lr75", "lr76", "lr77", "lr78", "lr79", "lr80", "lr81", \
+ "lr82", "lr83", "lr84", "lr85", "lr86", "lr87", "lr88", "lr89", "lr90", \
+ "lr91", "lr92", "lr93", "lr94", "lr95", "lr96", "lr97", "lr98", "lr99", \
+ "lr100", "lr101", "lr102", "lr103", "lr104", "lr105", "lr106", "lr107", \
+ "lr108", "lr109", "lr110", "lr111", "lr112", "lr113", "lr114", "lr115", \
+ "lr116", "lr117", "lr118", "lr119", "lr120", "lr121", "lr122", "lr123", \
+ "lr124", "lr125", "lr126", "lr127", \
+ "AI0", "AI1", "AI2", "AI3", "AI4", "AI5", "AI6", "AI7", "AI8", "AI9", \
+ "AI10", "AI11", "AI12", "AI13", "AI14", "AI15", "FP", \
+ "bp", "fc", "cr", "q", \
+ "vab", "ops", "cps", "cfg", "cha", "chd", "chc", "rbp", "tmc", "tmr", \
+ "pc0", "pc1", "pc2", "mmu", "lru", "fpe", "inte", "fps", "exo", "gr1", \
+ "alu", "ipc", "ipa", "ipb" }
+
+/*
+ * Converts an sdb register number to an internal gdb register number.
+ * Currently under epi, gr96->0...gr127->31...lr0->32...lr127->159, or...
+ * gr64->0...gr95->31, lr0->32...lr127->159.
+ */
+#define SDB_REG_TO_REGNUM(value) \
+ (((value) >= 96 && (value) <= 127) ? ((value) - 96) : \
+ ((value) >= 128 && (value) <= 255) ? ((value) - 128 + LR0_REGNUM) : \
+ (value))
+
+/*
+ * Provide the processor register numbers of some registers that are
+ * expected/written in instructions that might change under different
+ * register sets. Namely, gcc can compile (-mkernel-registers) so that
+ * it uses gr64-gr95 in stead of gr96-gr127.
+ */
+#define MSP_HW_REGNUM 125 /* gr125 */
+#define RAB_HW_REGNUM 126 /* gr126 */
+
+/* Convert Processor Special register #x to REGISTER_NAMES register # */
+#define SR_REGNUM(x) \
+ ((x) < 15 ? VAB_REGNUM + (x) \
+ : (x) >= 128 && (x) < 131 ? IPC_REGNUM + (x) - 128 \
+ : (x) == 131 ? Q_REGNUM \
+ : (x) == 132 ? ALU_REGNUM \
+ : (x) >= 133 && (x) < 136 ? BP_REGNUM + (x) - 133 \
+ : (x) >= 160 && (x) < 163 ? FPE_REGNUM + (x) - 160 \
+ : (x) == 164 ? EXO_REGNUM \
+ : (error ("Internal error in SR_REGNUM"), 0))
+#define GR96_REGNUM 0
+
+/* Define the return register separately, so it can be overridden for
+ kernel procedure calling conventions. */
+#define RETURN_REGNUM GR96_REGNUM
+#define GR1_REGNUM 200
+/* This needs to be the memory stack pointer, not the register stack pointer,
+ to make call_function work right. */
+#define SP_REGNUM MSP_REGNUM
+#define FP_REGNUM 33 /* lr1 */
+
+/* Return register for transparent calling convention (gr122). */
+#define TPC_REGNUM (122 - 96 + GR96_REGNUM)
+
+/* Large Return Pointer (gr123). */
+#define LRP_REGNUM (123 - 96 + GR96_REGNUM)
+
+/* Static link pointer (gr124). */
+#define SLP_REGNUM (124 - 96 + GR96_REGNUM)
+
+/* Memory Stack Pointer (gr125). */
+#define MSP_REGNUM (125 - 96 + GR96_REGNUM)
+
+/* Register allocate bound (gr126). */
+#define RAB_REGNUM (126 - 96 + GR96_REGNUM)
+
+/* Register Free Bound (gr127). */
+#define RFB_REGNUM (127 - 96 + GR96_REGNUM)
+
+/* Register Stack Pointer. */
+#define RSP_REGNUM GR1_REGNUM
+#define LR0_REGNUM 32
+#define BP_REGNUM 177
+#define FC_REGNUM 178
+#define CR_REGNUM 179
+#define Q_REGNUM 180
+#define VAB_REGNUM 181
+#define OPS_REGNUM (VAB_REGNUM + 1)
+#define CPS_REGNUM (VAB_REGNUM + 2)
+#define CFG_REGNUM (VAB_REGNUM + 3)
+#define CHA_REGNUM (VAB_REGNUM + 4)
+#define CHD_REGNUM (VAB_REGNUM + 5)
+#define CHC_REGNUM (VAB_REGNUM + 6)
+#define RBP_REGNUM (VAB_REGNUM + 7)
+#define TMC_REGNUM (VAB_REGNUM + 8)
+#define TMR_REGNUM (VAB_REGNUM + 9)
+#define NPC_REGNUM (VAB_REGNUM + 10) /* pc0 */
+#define PC_REGNUM (VAB_REGNUM + 11) /* pc1 */
+#define PC2_REGNUM (VAB_REGNUM + 12)
+#define MMU_REGNUM (VAB_REGNUM + 13)
+#define LRU_REGNUM (VAB_REGNUM + 14)
+#define FPE_REGNUM (VAB_REGNUM + 15)
+#define INTE_REGNUM (VAB_REGNUM + 16)
+#define FPS_REGNUM (VAB_REGNUM + 17)
+#define EXO_REGNUM (VAB_REGNUM + 18)
+/* gr1 is defined above as 200 = VAB_REGNUM + 19 */
+#define ALU_REGNUM (VAB_REGNUM + 20)
+#define PS_REGNUM ALU_REGNUM
+#define IPC_REGNUM (VAB_REGNUM + 21)
+#define IPA_REGNUM (VAB_REGNUM + 22)
+#define IPB_REGNUM (VAB_REGNUM + 23)
+
+#endif /* !defined(REGISTER_NAMES) */
+
+/* Total amount of space needed to store our copies of the machine's
+ register state, the array `registers'. */
+#define REGISTER_BYTES (NUM_REGS * 4)
+
+/* Index within `registers' of the first byte of the space for
+ register N. */
+#define REGISTER_BYTE(N) ((N)*4)
+
+/* Number of bytes of storage in the actual machine representation
+ for register N. */
+
+/* All regs are 4 bytes. */
+
+#define REGISTER_RAW_SIZE(N) (4)
+
+/* Number of bytes of storage in the program's representation
+ for register N. */
+
+/* All regs are 4 bytes. */
+
+#define REGISTER_VIRTUAL_SIZE(N) (4)
+
+/* Largest value REGISTER_RAW_SIZE can have. */
+
+#define MAX_REGISTER_RAW_SIZE (4)
+
+/* Largest value REGISTER_VIRTUAL_SIZE can have. */
+
+#define MAX_REGISTER_VIRTUAL_SIZE (4)
+
+/* Return the GDB type object for the "standard" data type
+ of data in register N. */
+
+#define REGISTER_VIRTUAL_TYPE(N) \
+ (((N) == PC_REGNUM || (N) == LRP_REGNUM || (N) == SLP_REGNUM \
+ || (N) == MSP_REGNUM || (N) == RAB_REGNUM || (N) == RFB_REGNUM \
+ || (N) == GR1_REGNUM || (N) == FP_REGNUM || (N) == LR0_REGNUM \
+ || (N) == NPC_REGNUM || (N) == PC2_REGNUM) \
+ ? lookup_pointer_type (builtin_type_void) : builtin_type_int)
+
+/* Store the address of the place in which to copy the structure the
+ subroutine will return. This is called from call_function. */
+/* On the a29k the LRP points to the part of the structure beyond the first
+ 16 words. */
+#define STORE_STRUCT_RETURN(ADDR, SP) \
+ write_register (LRP_REGNUM, (ADDR) + 16 * 4);
+
+/* Should call_function allocate stack space for a struct return? */
+/* On the a29k objects over 16 words require the caller to allocate space. */
+extern use_struct_convention_fn a29k_use_struct_convention;
+#define USE_STRUCT_CONVENTION(gcc_p, type) a29k_use_struct_convention (gcc_p, type)
+
+/* Extract from an array REGBUF containing the (raw) register state
+ a function return value of type TYPE, and copy that, in virtual format,
+ into VALBUF. */
+
+#define EXTRACT_RETURN_VALUE(TYPE,REGBUF,VALBUF) \
+ { \
+ int reg_length = TYPE_LENGTH (TYPE); \
+ if (reg_length > 16 * 4) \
+ { \
+ reg_length = 16 * 4; \
+ read_memory (*((int *)(REGBUF) + LRP_REGNUM), (VALBUF) + 16 * 4, \
+ TYPE_LENGTH (TYPE) - 16 * 4); \
+ } \
+ memcpy ((VALBUF), ((int *)(REGBUF))+RETURN_REGNUM, reg_length); \
+ }
+
+/* Write into appropriate registers a function return value
+ of type TYPE, given in virtual format. */
+
+#define STORE_RETURN_VALUE(TYPE,VALBUF) \
+ { \
+ int reg_length = TYPE_LENGTH (TYPE); \
+ if (reg_length > 16 * 4) \
+ { \
+ reg_length = 16 * 4; \
+ write_memory (read_register (LRP_REGNUM), \
+ (char *)(VALBUF) + 16 * 4, \
+ TYPE_LENGTH (TYPE) - 16 * 4); \
+ } \
+ write_register_bytes (REGISTER_BYTE (RETURN_REGNUM), (char *)(VALBUF), \
+ TYPE_LENGTH (TYPE)); \
+ }
+
+/* The a29k user's guide documents well what the stacks look like.
+ But what isn't so clear there is how this interracts with the
+ symbols, or with GDB.
+ In the following saved_msp, saved memory stack pointer (which functions
+ as a memory frame pointer), means either
+ a register containing the memory frame pointer or, in the case of
+ functions with fixed size memory frames (i.e. those who don't use
+ alloca()), the result of the calculation msp + msize.
+
+ LOC_ARG, LOC_LOCAL - For GCC, these are relative to saved_msp.
+ For high C, these are relative to msp (making alloca impossible).
+ LOC_REGISTER, LOC_REGPARM - The register number is the number at the
+ time the function is running (after the prologue), or in the case
+ of LOC_REGPARM, may be a register number in the range 160-175.
+
+ The compilers do things like store an argument into memory, and then put out
+ a LOC_ARG for it, or put it into global registers and put out a
+ LOC_REGPARM. Thus is it important to execute the first line of
+ code (i.e. the line of the open brace, i.e. the prologue) of a function
+ before trying to print arguments or anything.
+
+ The following diagram attempts to depict what is going on in memory
+ (see also the _a29k user's guide_) and also how that interacts with
+ GDB frames. We arbitrarily pick fci->frame to point the same place
+ as the register stack pointer; since we set it ourself in
+ INIT_EXTRA_FRAME_INFO, and access it only through the FRAME_*
+ macros, it doesn't really matter exactly how we
+ do it. However, note that FRAME_FP is used in two ways in GDB:
+ (1) as a "magic cookie" which uniquely identifies frames (even over
+ calls to the inferior), (2) (in PC_IN_CALL_DUMMY [ON_STACK])
+ as the value of SP_REGNUM before the dummy frame was pushed. These
+ two meanings would be incompatible for the a29k if we defined
+ CALL_DUMMY_LOCATION == ON_STACK (but we don't, so don't worry about it).
+ Also note that "lr1" below, while called a frame pointer
+ in the user's guide, has only one function: To determine whether
+ registers need to be filled in the function epilogue.
+
+ Consider the code:
+ < call bar>
+ loc1: . . .
+ bar: sub gr1,gr1,rsize_b
+ . . .
+ add mfp,msp,0
+ sub msp,msp,msize_b
+ . . .
+ < call foo >
+ loc2: . . .
+ foo: sub gr1,gr1,rsize_f
+ . . .
+ add mfp,msp,0
+ sub msp,msp,msize_f
+ . . .
+ loc3: < suppose the inferior stops here >
+
+ memory stack register stack
+ | | |____________|
+ | | |____loc1____|
+ +------->|___________| | | ^
+ | | ^ | | locals_b | |
+ | | | | |____________| |
+ | | | | | | | rsize_b
+ | | | msize_b | | args_to_f | |
+ | | | | |____________| |
+ | | | | |____lr1_____| V
+ | | V | |____loc2____|<----------------+
+ | +--->|___________|<---------mfp | ^ |
+ | | | ^ | | locals_f | | |
+ | | | | msize_f | |____________| | |
+ | | | | | | | | rsize_f |
+ | | | V | | args | | |
+ | | |___________|<msp |____________| | |
+ | | |_____lr1____| V |
+ | | |___garbage__| <- gr1 <----+ |
+ | | | |
+ | | | |
+ | | pc=loc3 | |
+ | | | |
+ | | | |
+ | | frame cache | |
+ | | |_________________| | |
+ | | |rsize=rsize_b | | |
+ | | |msize=msize_b | | |
+ +---|--------saved_msp | | |
+ | |frame------------------------------------|---+
+ | |pc=loc2 | |
+ | |_________________| |
+ | |rsize=rsize_f | |
+ | |msize=msize_f | |
+ +--------saved_msp | |
+ |frame------------------------------------+
+ |pc=loc3 |
+ |_________________|
+
+ So, is that sufficiently confusing? Welcome to the 29000.
+ Notes:
+ * The frame for foo uses a memory frame pointer but the frame for
+ bar does not. In the latter case the saved_msp is
+ computed by adding msize to the saved_msp of the
+ next frame.
+ * msize is in the frame cache only for high C's sake. */
+
+void read_register_stack ();
+long read_register_stack_integer ();
+
+#define FRAME_INIT_SAVED_REGS(fi) /*no-op*/
+
+#define EXTRA_FRAME_INFO \
+ CORE_ADDR saved_msp; \
+ unsigned int rsize; \
+ unsigned int msize; \
+ unsigned char flags;
+
+/* Bits for flags in EXTRA_FRAME_INFO */
+#define TRANSPARENT_FRAME 0x1 /* This is a transparent frame */
+#define MFP_USED 0x2 /* A memory frame pointer is used */
+
+/* Because INIT_FRAME_PC gets passed fromleaf, that's where we init
+ not only ->pc and ->frame, but all the extra stuff, when called from
+ get_prev_frame_info, that is. */
+#define INIT_EXTRA_FRAME_INFO(fromleaf, fci) init_extra_frame_info(fci)
+void init_extra_frame_info ();
+
+#define INIT_FRAME_PC(fromleaf, fci) init_frame_pc(fromleaf, fci)
+void init_frame_pc ();
+
+
+/* FRAME_CHAIN takes a FRAME
+ and produces the frame's chain-pointer.
+
+ However, if FRAME_CHAIN_VALID returns zero,
+ it means the given frame is the outermost one and has no caller. */
+
+/* On the a29k, the nominal address of a frame is the address on the
+ register stack of the return address (the one next to the incoming
+ arguments, not down at the bottom so nominal address == stack pointer).
+
+ GDB expects "nominal address" to equal contents of FP_REGNUM,
+ at least when it comes time to create the innermost frame.
+ However, that doesn't work for us, so when creating the innermost
+ frame we set ->frame ourselves in INIT_EXTRA_FRAME_INFO. */
+
+/* These are mostly dummies for the a29k because INIT_FRAME_PC
+ sets prev->frame instead. */
+/* If rsize is zero, we must be at end of stack (or otherwise hosed).
+ If we don't check rsize, we loop forever if we see rsize == 0. */
+#define FRAME_CHAIN(thisframe) \
+ ((thisframe)->rsize == 0 \
+ ? 0 \
+ : (thisframe)->frame + (thisframe)->rsize)
+
+/* Determine if the frame has a 'previous' and back-traceable frame. */
+#define FRAME_IS_UNCHAINED(frame) ((frame)->flags & TRANSPARENT_FRAME)
+
+/* Find the previous frame of a transparent routine.
+ * For now lets not try and trace through a transparent routine (we might
+ * have to assume that all transparent routines are traps).
+ */
+#define FIND_PREV_UNCHAINED_FRAME(frame) 0
+
+/* Define other aspects of the stack frame. */
+
+/* A macro that tells us whether the function invocation represented
+ by FI does not have a frame on the stack associated with it. If it
+ does not, FRAMELESS is set to 1, else 0. */
+#define FRAMELESS_FUNCTION_INVOCATION(FI, FRAMELESS) \
+ (FRAMELESS) = frameless_look_for_prologue(FI)
+
+/* Saved pc (i.e. return address). */
+#define FRAME_SAVED_PC(fraim) \
+ (read_register_stack_integer ((fraim)->frame + (fraim)->rsize, 4))
+
+/* Local variables (i.e. LOC_LOCAL) are on the memory stack, with their
+ offsets being relative to the memory stack pointer (high C) or
+ saved_msp (gcc). */
+
+#define FRAME_LOCALS_ADDRESS(fi) frame_locals_address (fi)
+extern CORE_ADDR frame_locals_address ();
+
+/* Return number of args passed to a frame.
+ Can return -1, meaning no way to tell. */
+/* We tried going to the effort of finding the tags word and getting
+ the argcount field from it, to support debugging assembler code.
+ Problem was, the "argcount" field never did hold the argument
+ count. */
+#define FRAME_NUM_ARGS(numargs, fi) ((numargs) = -1)
+
+#define FRAME_ARGS_ADDRESS(fi) FRAME_LOCALS_ADDRESS (fi)
+
+/* Return number of bytes at start of arglist that are not really args. */
+
+#define FRAME_ARGS_SKIP 0
+
+/* Provide our own get_saved_register. HAVE_REGISTER_WINDOWS is insufficient
+ because registers get renumbered on the a29k without getting saved. */
+
+#define GET_SAVED_REGISTER
+
+/* Call function stuff. */
+
+/* The dummy frame looks like this (see also the general frame picture
+ above):
+
+ register stack
+
+ | | frame for function
+ | locals_sproc | executing at time
+ |________________| of call_function.
+ | | We must not disturb
+ | args_out_sproc | it.
+ memory stack |________________|
+ |____lr1_sproc___|<-+
+ | | |__retaddr_sproc_| | <-- gr1 (at start)
+ |____________|<-msp 0 <-----------mfp_dummy_____| |
+ | | (at start) | save regs | |
+ | arg_slop | | pc0,pc1 | |
+ | | | pc2,lr0 sproc | |
+ | (16 words) | | gr96-gr124 | |
+ |____________|<-msp 1--after | sr160-sr162 | |
+ | | PUSH_DUMMY_FRAME| sr128-sr135 | |
+ | struct ret | |________________| |
+ | 17+ | | | |
+ |____________|<- lrp | args_out_dummy | |
+ | struct ret | | (16 words) | |
+ | 16 | |________________| |
+ | (16 words) | |____lr1_dummy___|--+
+ |____________|<- msp 2--after |_retaddr_dummy__|<- gr1 after
+ | | struct ret | | PUSH_DUMMY_FRAME
+ | margs17+ | area allocated | locals_inf |
+ | | |________________| called
+ |____________|<- msp 4--when | | function's
+ | | inf called | args_out_inf | frame (set up
+ | margs16 | |________________| by called
+ | (16 words) | |_____lr1_inf____| function).
+ |____________|<- msp 3--after | . |
+ | | args pushed | . |
+ | | | . |
+ | |
+
+ arg_slop: This area is so that when the call dummy adds 16 words to
+ the msp, it won't end up larger than mfp_dummy (it is needed in the
+ case where margs and struct_ret do not add up to at least 16 words).
+ struct ret: This area is allocated by GDB if the return value is more
+ than 16 words. struct ret_16 is not used on the a29k.
+ margs: Pushed by GDB. The call dummy copies the first 16 words to
+ args_out_dummy.
+ retaddr_sproc: Contains the PC at the time we call the function.
+ set by PUSH_DUMMY_FRAME and read by POP_FRAME.
+ retaddr_dummy: This points to a breakpoint instruction in the dummy. */
+
+/* Rsize for dummy frame, in bytes. */
+
+/* Bytes for outgoing args, lr1, and retaddr. */
+#define DUMMY_ARG (2 * 4 + 16 * 4)
+
+/* Number of special registers (sr128-) to save. */
+#define DUMMY_SAVE_SR128 8
+/* Number of special registers (sr160-) to save. */
+#define DUMMY_SAVE_SR160 3
+/* Number of general (gr96- or gr64-) registers to save. */
+#define DUMMY_SAVE_GREGS 29
+
+#define DUMMY_FRAME_RSIZE \
+(4 /* mfp_dummy */ \
+ + 4 * 4 /* pc0, pc1, pc2, lr0 */ \
+ + DUMMY_SAVE_GREGS * 4 \
+ + DUMMY_SAVE_SR160 * 4 \
+ + DUMMY_SAVE_SR128 * 4 \
+ + DUMMY_ARG \
+ + 4 /* pad to doubleword */ )
+
+/* Push an empty stack frame, to record the current PC, etc. */
+
+#define PUSH_DUMMY_FRAME push_dummy_frame()
+extern void push_dummy_frame ();
+
+/* Discard from the stack the innermost frame,
+ restoring all saved registers. */
+
+#define POP_FRAME pop_frame()
+extern void pop_frame ();
+
+/* This sequence of words is the instructions
+ mtsrim cr, 15
+ loadm 0, 0, lr2, msp ; load first 16 words of arguments into registers
+ add msp, msp, 16 * 4 ; point to the remaining arguments
+ CONST_INSN:
+ const lr0,inf ; (replaced by half of target addr)
+ consth lr0,inf ; (replaced by other half of target addr)
+ calli lr0, lr0
+ aseq 0x40,gr1,gr1 ; nop
+ BREAKPT_INSN:
+ asneq 0x50,gr1,gr1 ; breakpoint (replaced by local breakpoint insn)
+ */
+
+#if TARGET_BYTE_ORDER == HOST_BYTE_ORDER
+#define BS(const) const
+#else
+#define BS(const) (((const) & 0xff) << 24) | \
+ (((const) & 0xff00) << 8) | \
+ (((const) & 0xff0000) >> 8) | \
+ (((const) & 0xff000000) >> 24)
+#endif
+
+/* Position of the "const" and blkt instructions within CALL_DUMMY in bytes. */
+#define CONST_INSN (3 * 4)
+#define BREAKPT_INSN (7 * 4)
+#define CALL_DUMMY { \
+ BS(0x0400870f),\
+ BS(0x36008200|(MSP_HW_REGNUM)), \
+ BS(0x15000040|(MSP_HW_REGNUM<<8)|(MSP_HW_REGNUM<<16)), \
+ BS(0x03ff80ff), \
+ BS(0x02ff80ff), \
+ BS(0xc8008080), \
+ BS(0x70400101), \
+ BS(0x72500101)}
+#define CALL_DUMMY_LENGTH (8 * 4)
+
+#define CALL_DUMMY_START_OFFSET 0 /* Start execution at beginning of dummy */
+
+/* Helper macro for FIX_CALL_DUMMY. WORDP is a long * which points to a
+ word in target byte order; bits 0-7 and 16-23 of *WORDP are replaced with
+ bits 0-7 and 8-15 of DATA (which is in host byte order). */
+
+#if TARGET_BYTE_ORDER == BIG_ENDIAN
+#define STUFF_I16(WORDP, DATA) \
+ { \
+ *((char *)(WORDP) + 3) = ((DATA) & 0xff);\
+ *((char *)(WORDP) + 1) = (((DATA) >> 8) & 0xff);\
+ }
+#else /* Target is little endian. */
+#define STUFF_I16(WORDP, DATA) \
+ {
+ *(char *)(WORDP) = ((DATA) & 0xff);
+ *((char *)(WORDP) + 2) = (((DATA) >> 8) & 0xff);
+ }
+#endif /* Target is little endian. */
+
+/* Insert the specified number of args and function address
+ into a call sequence of the above form stored at DUMMYNAME. */
+
+/* Currently this stuffs in the address of the function that we are calling.
+ Since different a29k systems use different breakpoint instructions, it
+ also stuffs BREAKPOINT in the right place (to avoid having to
+ duplicate CALL_DUMMY in each tm-*.h file). */
+
+#define FIX_CALL_DUMMY(dummyname, pc, fun, nargs, args, type, gcc_p) \
+ {\
+ STUFF_I16((char *)dummyname + CONST_INSN, fun); \
+ STUFF_I16((char *)dummyname + CONST_INSN + 4, fun >> 16); \
+ /* FIXME memcpy ((char *)(dummyname) + BREAKPT_INSN, break_insn, 4); */ \
+ }
+
+/* a29k architecture has separate data & instruction memories -- wired to
+ different pins on the chip -- and can't execute the data memory.
+ Also, there should be space after text_end;
+ we won't get a SIGSEGV or scribble on data space. */
+
+#define CALL_DUMMY_LOCATION AFTER_TEXT_END
+
+/* Because of this, we need (as a kludge) to know the addresses of the
+ text section. */
+
+#define NEED_TEXT_START_END 1
+
+/* How to translate register numbers in the .stab's into gdb's internal register
+ numbers. We don't translate them, but we warn if an invalid register
+ number is seen. Note that FIXME, we use the value "sym" as an implicit
+ argument in printing the error message. It happens to be available where
+ this macro is used. (This macro definition appeared in a late revision
+ of gdb-3.91.6 and is not well tested. Also, it should be a "complaint".) */
+
+#define STAB_REG_TO_REGNUM(num) \
+ (((num) > LR0_REGNUM + 127) \
+ ? fprintf(stderr, \
+ "Invalid register number %d in symbol table entry for %s\n", \
+ (num), SYMBOL_SOURCE_NAME (sym)), (num) \
+ : (num))
+
+extern enum a29k_processor_types {
+ a29k_unknown,
+
+ /* Bit 0x400 of the CPS does *not* identify freeze mode, i.e. 29000,
+ 29030, etc. */
+ a29k_no_freeze_mode,
+
+ /* Bit 0x400 of the CPS does identify freeze mode, i.e. 29050. */
+ a29k_freeze_mode
+} processor_type;
+
+/* We need three arguments for a general frame specification for the
+ "frame" or "info frame" command. */
+
+#define SETUP_ARBITRARY_FRAME(argc, argv) setup_arbitrary_frame (argc, argv)
+extern struct frame_info *setup_arbitrary_frame PARAMS ((int, CORE_ADDR *));
diff --git a/gdb/config/a29k/tm-ultra3.h b/gdb/config/a29k/tm-ultra3.h
new file mode 100644
index 00000000000..8b96210e475
--- /dev/null
+++ b/gdb/config/a29k/tm-ultra3.h
@@ -0,0 +1,226 @@
+/* Parameters for NYU Ultracomputer 29000 target, for GDB, the GNU debugger.
+ Copyright 1990, 1991 Free Software Foundation, Inc.
+ Contributed by David Wood @ New York University (wood@nyu.edu).
+
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* This file includes tm-a29k.h, but predefines REGISTER_NAMES and
+ related macros. The file supports a a29k running our flavor of
+ Unix on our Ultra3 PE Boards. */
+
+/* Byte order is configurable, but this machine runs big-endian. */
+#define TARGET_BYTE_ORDER BIG_ENDIAN
+
+/* Initializer for an array of names of registers.
+ There should be NUM_REGS strings in this initializer.
+ */
+#define NUM_REGS (EXO_REGNUM + 1)
+
+#define REGISTER_NAMES { \
+ "gr1", \
+ "gr64", "gr65", "gr66", "gr67", "gr68", "gr69", "gr70", "gr71", "gr72", \
+ "gr73", "gr74", "gr75", "gr76", "gr77", "gr78", "gr79", "gr80", "gr81", \
+ "gr82", "gr83", "gr84", "gr85", "gr86", "gr87", "gr88", "gr89", "gr90", \
+ "gr91", "gr92", "gr93", "gr94", "gr95", \
+ "gr96", "gr97", "gr98", "gr99", "gr100", "gr101", "gr102", "gr103", "gr104", \
+ "gr105", "gr106", "gr107", "gr108", "gr109", "gr110", "gr111", "gr112", \
+ "gr113", "gr114", "gr115", "gr116", "gr117", "gr118", "gr119", "gr120", \
+ "gr121", "gr122", "gr123", "gr124", "gr125", "gr126", "gr127", \
+ "lr0", "lr1", "lr2", "lr3", "lr4", "lr5", "lr6", "lr7", "lr8", "lr9", \
+ "lr10", "lr11", "lr12", "lr13", "lr14", "lr15", "lr16", "lr17", "lr18", \
+ "lr19", "lr20", "lr21", "lr22", "lr23", "lr24", "lr25", "lr26", "lr27", \
+ "lr28", "lr29", "lr30", "lr31", "lr32", "lr33", "lr34", "lr35", "lr36", \
+ "lr37", "lr38", "lr39", "lr40", "lr41", "lr42", "lr43", "lr44", "lr45", \
+ "lr46", "lr47", "lr48", "lr49", "lr50", "lr51", "lr52", "lr53", "lr54", \
+ "lr55", "lr56", "lr57", "lr58", "lr59", "lr60", "lr61", "lr62", "lr63", \
+ "lr64", "lr65", "lr66", "lr67", "lr68", "lr69", "lr70", "lr71", "lr72", \
+ "lr73", "lr74", "lr75", "lr76", "lr77", "lr78", "lr79", "lr80", "lr81", \
+ "lr82", "lr83", "lr84", "lr85", "lr86", "lr87", "lr88", "lr89", "lr90", \
+ "lr91", "lr92", "lr93", "lr94", "lr95", "lr96", "lr97", "lr98", "lr99", \
+ "lr100", "lr101", "lr102", "lr103", "lr104", "lr105", "lr106", "lr107", \
+ "lr108", "lr109", "lr110", "lr111", "lr112", "lr113", "lr114", "lr115", \
+ "lr116", "lr117", "lr118", "lr119", "lr120", "lr121", "lr122", "lr123", \
+ "lr124", "lr125", "lr126", "lr127", \
+ "vab", "ops", "cps", "cfg", "cha", "chd", "chc", "rbp", "tmc", "tmr", \
+ "pc0", "pc1", "pc2", "mmu", "lru", \
+ "ipc", "ipa", "ipb", "q", "alu", "bp", "fc", "cr", \
+ "fpe", "int", "fps", "exo" }
+
+
+#ifdef KERNEL_DEBUGGING
+# define PADDR_U_REGNUM 22 /* gr86 */
+# define RETURN_REGNUM GR64_REGNUM
+#else
+# define RETURN_REGNUM GR96_REGNUM
+#endif /* KERNEL_DEBUGGING */
+
+
+/* Should rename all GR96_REGNUM to RETURN_REGNUM */
+#define GR1_REGNUM (0)
+#define GR64_REGNUM 1
+#define GR96_REGNUM (GR64_REGNUM + 32)
+/* This needs to be the memory stack pointer, not the register stack pointer,
+ to make call_function work right. */
+#define SP_REGNUM MSP_REGNUM
+
+#define FP_REGNUM (LR0_REGNUM + 1) /* lr1 */
+/* Large Return Pointer */
+#define LRP_REGNUM (123 - 96 + RETURN_REGNUM)
+/* Static link pointer */
+#define SLP_REGNUM (124 - 96 + RETURN_REGNUM)
+/* Memory Stack Pointer. */
+#define MSP_REGNUM (125 - 96 + RETURN_REGNUM)
+/* Register allocate bound. */
+#define RAB_REGNUM (126 - 96 + RETURN_REGNUM)
+/* Register Free Bound. */
+#define RFB_REGNUM (127 - 96 + RETURN_REGNUM)
+/* Register Stack Pointer. */
+#define RSP_REGNUM GR1_REGNUM
+#define LR0_REGNUM ( 32 + GR96_REGNUM)
+
+/* Protected Special registers */
+#define VAB_REGNUM (LR0_REGNUM + 128)
+#define OPS_REGNUM (VAB_REGNUM + 1)
+#define CPS_REGNUM (VAB_REGNUM + 2)
+#define CFG_REGNUM (VAB_REGNUM + 3)
+#define CHA_REGNUM (VAB_REGNUM + 4)
+#define CHD_REGNUM (VAB_REGNUM + 5)
+#define CHC_REGNUM (VAB_REGNUM + 6)
+#define RBP_REGNUM (VAB_REGNUM + 7)
+#define TMC_REGNUM (VAB_REGNUM + 8)
+#define TMR_REGNUM (VAB_REGNUM + 9)
+#define NPC_REGNUM (VAB_REGNUM + 10) /* pc0 */
+#define PC_REGNUM (VAB_REGNUM + 11) /* pc1 */
+#define PC2_REGNUM (VAB_REGNUM + 12) /* pc2 */
+#define MMU_REGNUM (VAB_REGNUM + 13)
+#define LRU_REGNUM (VAB_REGNUM + 14)
+ /* Register sequence gap */
+/* Unprotected Special registers */
+#define IPC_REGNUM (LRU_REGNUM + 1)
+#define IPA_REGNUM (IPC_REGNUM + 1)
+#define IPB_REGNUM (IPC_REGNUM + 2)
+#define Q_REGNUM (IPC_REGNUM + 3)
+#define ALU_REGNUM (IPC_REGNUM + 4)
+#define PS_REGNUM ALU_REGNUM
+#define BP_REGNUM (IPC_REGNUM + 5)
+#define FC_REGNUM (IPC_REGNUM + 6)
+#define CR_REGNUM (IPC_REGNUM + 7)
+ /* Register sequence gap */
+#define FPE_REGNUM (CR_REGNUM + 1)
+#define INT_REGNUM (FPE_REGNUM + 1)
+#define FPS_REGNUM (FPE_REGNUM + 2)
+ /* Register sequence gap */
+#define EXO_REGNUM (FPS_REGNUM + 1)
+
+/* Special register #x. */
+#define SR_REGNUM(x) \
+ ((x) < 15 ? VAB_REGNUM + (x) \
+ : (x) >= 128 && (x) < 136 ? IPC_REGNUM + (x-128) \
+ : (x) >= 160 && (x) < 163 ? FPE_REGNUM + (x-160) \
+ : (x) == 164 ? EXO_REGNUM \
+ : (error ("Internal error in SR_REGNUM"), 0))
+
+#ifndef KERNEL_DEBUGGING
+/*
+ * This macro defines the register numbers (from REGISTER_NAMES) that
+ * are effectively unavailable to the user through ptrace(). It allows
+ * us to include the whole register set in REGISTER_NAMES (inorder to
+ * better support remote debugging). If it is used in
+ * fetch/store_inferior_registers() gdb will not complain about I/O errors
+ * on fetching these registers. If all registers in REGISTER_NAMES
+ * are available, then return false (0).
+ */
+#define CANNOT_STORE_REGISTER(regno) \
+ (((regno)>=GR64_REGNUM && (regno)<GR64_REGNUM+32) || \
+ ((regno)==VAB_REGNUM) || \
+ ((regno)==OPS_REGNUM) || \
+ ((regno)>=CFG_REGNUM && (regno)<=TMR_REGNUM) || \
+ ((regno)==MMU_REGNUM) || \
+ ((regno)==LRU_REGNUM) || \
+ ((regno)>=ALU_REGNUM) || \
+ ((regno)==CR_REGNUM) || \
+ ((regno)==EXO_REGNUM))
+#define CANNOT_FETCH_REGISTER(regno) CANNOT_STORE_REGISTER(regno)
+#endif /* KERNEL_DEBUGGING */
+
+/*
+ * Converts an sdb register number to an internal gdb register number.
+ * Currently under gcc, gr96->0...gr128->31...lr0->32...lr127->159, or...
+ * gr64->0...gr95->31, lr0->32...lr127->159.
+ */
+#define SDB_REG_TO_REGNUM(value) (((value)<32) ? ((value)+RETURN_REGNUM) : \
+ ((value)-32+LR0_REGNUM))
+
+#ifdef KERNEL_DEBUGGING
+ /* ublock virtual address as defined in our sys/param.h */
+ /* FIXME: Should get this from sys/param.h */
+# define UVADDR ((32*0x100000)-8192)
+#endif
+
+/*
+ * Are we in sigtramp(), needed in infrun.c. Specific to ultra3, because
+ * we take off the leading '_'.
+ */
+#if !defined(KERNEL_DEBUGGING)
+#ifdef SYM1
+# define IN_SIGTRAMP(pc, name) (name && STREQ ("sigtramp", name))
+#else
+ Need to define IN_SIGTRAMP() for sym2.
+#endif
+#endif /* !KERNEL_DEBUGGING */
+
+#include "a29k/tm-a29k.h"
+
+/**** The following are definitions that override those in tm-a29k.h ****/
+
+/* This sequence of words is the instructions
+ mtsrim cr, 15
+ loadm 0, 0, lr2, msp ; load first 16 words of arguments into registers
+ add msp, msp, 16 * 4 ; point to the remaining arguments
+ CONST_INSN:
+ const gr96,inf
+ consth gr96,inf
+ calli lr0, gr96
+ aseq 0x40,gr1,gr1 ; nop
+ asneq 0x50,gr1,gr1 ; breakpoint
+ When KERNEL_DEBUGGIN is defined, msp -> gr93, gr96 -> gr64,
+ 7d -> 5d, 60 -> 40
+ */
+
+/* Position of the "const" instruction within CALL_DUMMY in bytes. */
+#undef CALL_DUMMY
+#if TARGET_BYTE_ORDER == HOST_BYTE_ORDER
+#ifdef KERNEL_DEBUGGING /* gr96 -> gr64 */
+# define CALL_DUMMY {0x0400870f, 0x3600825d, 0x155d5d40, 0x03ff40ff, \
+ 0x02ff40ff, 0xc8008040, 0x70400101, 0x72500101}
+#else
+# define CALL_DUMMY {0x0400870f, 0x3600827d, 0x157d7d40, 0x03ff60ff, \
+ 0x02ff60ff, 0xc8008060, 0x70400101, 0x72500101}
+#endif /* KERNEL_DEBUGGING */
+#else /* Byte order differs. */
+ you lose
+#endif /* Byte order differs. */
+
+#if !defined(KERNEL_DEBUGGING)
+# ifdef SYM1
+# undef DECR_PC_AFTER_BREAK
+# define DECR_PC_AFTER_BREAK 0 /* Sym1 kernel does the decrement */
+# else
+ ->"ULTRA3 running other than sym1 OS"!;
+# endif
+#endif /* !KERNEL_DEBUGGING */
+
diff --git a/gdb/config/a29k/tm-vx29k.h b/gdb/config/a29k/tm-vx29k.h
new file mode 100644
index 00000000000..487df82df86
--- /dev/null
+++ b/gdb/config/a29k/tm-vx29k.h
@@ -0,0 +1,229 @@
+/* Target machine description for VxWorks on the 29k, for GDB, the GNU debugger.
+ Copyright 1994 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "a29k/tm-a29k.h"
+
+#define GDBINIT_FILENAME ".vxgdbinit"
+
+#define DEFAULT_PROMPT "(vxgdb) "
+
+/* Number of registers in a ptrace_getregs call. */
+
+#define VX_NUM_REGS (NUM_REGS)
+
+/* Number of registers in a ptrace_getfpregs call. */
+
+/* #define VX_SIZE_FPREGS */
+
+/* This is almost certainly the wrong place for this: */
+#define LR2_REGNUM 34
+
+
+/* Vxworks has its own CALL_DUMMY since it manages breakpoints in the kernel */
+
+#undef CALL_DUMMY
+
+/* Replace the breakpoint instruction in the CALL_DUMMY with a nop.
+ For Vxworks, the breakpoint is set and deleted by calls to
+ CALL_DUMMY_BREAK_SET and CALL_DUMMY_BREAK_DELETE. */
+
+#if TARGET_BYTE_ORDER == HOST_BYTE_ORDER
+#define CALL_DUMMY {0x0400870f,\
+ 0x36008200|(MSP_HW_REGNUM), \
+ 0x15000040|(MSP_HW_REGNUM<<8)|(MSP_HW_REGNUM<<16), \
+ 0x03ff80ff, 0x02ff80ff, 0xc8008080, 0x70400101, 0x70400101}
+#else /* Byte order differs. */
+#define CALL_DUMMY {0x0f870004,\
+ 0x00820036|(MSP_HW_REGNUM << 24), \
+ 0x40000015|(MSP_HW_REGNUM<<8)|(MSP_HW_REGNUM<<16), \
+ 0xff80ff03, 0xff80ff02, 0x808000c8, 0x01014070, 0x01014070}
+#endif /* Byte order differs. */
+
+
+/* For the basic CALL_DUMMY definitions, see "tm-29k.h." We use the
+ same CALL_DUMMY code, but define FIX_CALL_DUMMY (and related macros)
+ locally to handle remote debugging of VxWorks targets. The difference
+ is in the setting and clearing of the breakpoint at the end of the
+ CALL_DUMMY code fragment; under VxWorks, we can't simply insert a
+ breakpoint instruction into the code, since that would interfere with
+ the breakpoint management mechanism on the target.
+ Note that CALL_DUMMY is a piece of code that is used to call any C function
+ thru VxGDB */
+
+/* The offset of the instruction within the CALL_DUMMY code where we
+ want the inferior to stop after the function call has completed.
+ call_function_by_hand () sets a breakpoint here (via CALL_DUMMY_BREAK_SET),
+ which POP_FRAME later deletes (via CALL_DUMMY_BREAK_DELETE). */
+
+#define CALL_DUMMY_STOP_OFFSET (7 * 4)
+
+/* The offset of the first instruction of the CALL_DUMMY code fragment
+ relative to the frame pointer for a dummy frame. This is equal to
+ the size of the CALL_DUMMY plus the arg_slop area size (see the diagram
+ in "tm-29k.h"). */
+/* PAD : the arg_slop area size doesn't appear to me to be useful since, the
+ call dummy code no longer modify the msp. See below. This must be checked. */
+
+#define CALL_DUMMY_OFFSET_IN_FRAME (CALL_DUMMY_LENGTH + 16 * 4)
+
+/* Insert the specified number of args and function address
+ into a CALL_DUMMY sequence stored at DUMMYNAME, replace the third
+ instruction (add msp, msp, 16*4) with a nop, and leave the final nop.
+ We can't keep using a CALL_DUMMY that modify the msp since, for VxWorks,
+ CALL_DUMMY is stored in the Memory Stack. Adding 16 words to the msp
+ would then make possible for the inferior to overwrite the CALL_DUMMY code,
+ thus creating a lot of trouble when exiting the inferior to come back in
+ a CALL_DUMMY code that no longer exists... Furthermore, ESF are also stored
+ from the msp in the memory stack. If msp is set higher than the dummy code,
+ an ESF may clobber this code. */
+
+#if TARGET_BYTE_ORDER == BIG_ENDIAN
+#define NOP_INSTR 0x70400101
+#else /* Target is little endian */
+#define NOP_INSTR 0x01014070
+#endif
+
+#undef FIX_CALL_DUMMY
+#define FIX_CALL_DUMMY(dummyname, pc, fun, nargs, args, type, gcc_p) \
+ { \
+ *(int *)((char *)dummyname + 8) = NOP_INSTR; \
+ STUFF_I16((char *)dummyname + CONST_INSN, fun); \
+ STUFF_I16((char *)dummyname + CONST_INSN + 4, fun >> 16); \
+ }
+
+/* For VxWorks, CALL_DUMMY must be stored in the stack of the task that is
+ being debugged and executed "in the context of" this task */
+
+#undef CALL_DUMMY_LOCATION
+#define CALL_DUMMY_LOCATION ON_STACK
+
+/* Set or delete a breakpoint at the location within a CALL_DUMMY code
+ fragment where we want the target program to stop after the function
+ call is complete. CALL_DUMMY_ADDR is the address of the first
+ instruction in the CALL_DUMMY. DUMMY_FRAME_ADDR is the value of the
+ frame pointer in the dummy frame.
+
+ NOTE: in the both of the following definitions, we take advantage of
+ knowledge of the implementation of the target breakpoint operation,
+ in that we pass a null pointer as the second argument. It seems
+ reasonable to assume that any target requiring the use of
+ CALL_DUMMY_BREAK_{SET,DELETE} will not store the breakpoint
+ shadow contents in GDB; in any case, this assumption is vaild
+ for all VxWorks-related targets. */
+
+#define CALL_DUMMY_BREAK_SET(call_dummy_addr) \
+ target_insert_breakpoint ((call_dummy_addr) + CALL_DUMMY_STOP_OFFSET, \
+ (char *) 0)
+
+#define CALL_DUMMY_BREAK_DELETE(dummy_frame_addr) \
+ target_remove_breakpoint ((dummy_frame_addr) - (CALL_DUMMY_OFFSET_IN_FRAME \
+ - CALL_DUMMY_STOP_OFFSET), \
+ (char *) 0)
+
+/* Return nonzero if the pc is executing within a CALL_DUMMY frame. */
+
+#define PC_IN_CALL_DUMMY(pc, sp, frame_address) \
+ ((pc) >= (sp) \
+ && (pc) <= (sp) + CALL_DUMMY_OFFSET_IN_FRAME + CALL_DUMMY_LENGTH)
+
+/* Defining this prevents us from trying to pass a structure-valued argument
+ to a function called via the CALL_DUMMY mechanism. This is not handled
+ properly in call_function_by_hand (), and the fix might require re-writing
+ the CALL_DUMMY handling for all targets (at least, a clean solution
+ would probably require this). Arguably, this should go in "tm-29k.h"
+ rather than here. */
+
+#define STRUCT_VAL_ARGS_UNSUPPORTED
+
+#define BKPT_OFFSET (7 * 4)
+#define BKPT_INSTR 0x72500101
+
+#undef FIX_CALL_DUMMY
+#define FIX_CALL_DUMMY(dummyname, pc, fun, nargs, args, type, gcc_p) \
+ {\
+ STUFF_I16((char *)dummyname + CONST_INSN, fun);\
+ STUFF_I16((char *)dummyname + CONST_INSN + 4, fun >> 16);\
+ *(int *)((char *)dummyname + BKPT_OFFSET) = BKPT_INSTR;\
+ }
+
+
+/* Offsets into jmp_buf. They are derived from VxWorks' REG_SET struct
+ (see VxWorks' setjmp.h). Note that Sun2, Sun3 and SunOS4 and VxWorks have
+ different REG_SET structs, hence different layouts for the jmp_buf struct.
+ Only JB_PC is needed for getting the saved PC value. */
+
+#define JB_ELEMENT_SIZE 4 /* size of each element in jmp_buf */
+#define JB_PC 3 /* offset of pc (pc1) in jmp_buf */
+
+/* Figure out where the longjmp will land. We expect that we have just entered
+ longjmp and haven't yet setup the stack frame, so the args are still in the
+ output regs. lr2 (LR2_REGNUM) points at the jmp_buf structure from which we
+ extract the pc (JB_PC) that we will land at. The pc is copied into ADDR.
+ This routine returns true on success */
+
+#define GET_LONGJMP_TARGET(ADDR) get_longjmp_target(ADDR)
+extern int get_longjmp_target PARAMS ((CORE_ADDR *));
+
+/* VxWorks adjusts the PC after a breakpoint has been hit. */
+
+#undef DECR_PC_AFTER_BREAK
+#define DECR_PC_AFTER_BREAK 0
+
+/* Do whatever promotions are appropriate on a value being returned
+ from a function. VAL is the user-supplied value, and FUNC_TYPE
+ is the return type of the function if known, else 0.
+
+ For the Am29k, as far as I understand, if the function return type is known,
+ cast the value to that type; otherwise, ensure that integer return values
+ fill all of gr96.
+
+ This definition really belongs in "tm-29k.h", since it applies
+ to most Am29K-based systems; but once moved into that file, it might
+ need to be redefined for all Am29K-based targets that also redefine
+ STORE_RETURN_VALUE. For now, to be safe, we define it here. */
+
+#define PROMOTE_RETURN_VALUE(val, func_type) \
+ do { \
+ if (func_type) \
+ val = value_cast (func_type, val); \
+ if ((TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_INT \
+ || TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_ENUM) \
+ && TYPE_LENGTH (VALUE_TYPE (val)) < REGISTER_RAW_SIZE (0)) \
+ val = value_cast (builtin_type_int, val); \
+ } while (0)
+
+extern int vx29k_frame_chain_valid PARAMS ((CORE_ADDR, struct frame_info *));
+#define FRAME_CHAIN_VALID(chain, thisframe) vx29k_frame_chain_valid (chain, thisframe)
+
+extern CORE_ADDR frame_saved_call_site ();
+
+#undef PREPARE_TO_INIT_FRAME_INFO
+#define PREPARE_TO_INIT_FRAME_INFO(fci) do { \
+ long current_msp = read_register (MSP_REGNUM); \
+ if (PC_IN_CALL_DUMMY (fci->pc, current_msp, 0)) \
+ { \
+ fci->rsize = DUMMY_FRAME_RSIZE; \
+ fci->msize = 0; \
+ fci->saved_msp = \
+ read_register_stack_integer (fci->frame + DUMMY_FRAME_RSIZE - 4, 4); \
+ fci->flags |= (TRANSPARENT|MFP_USED); \
+ return; \
+ } \
+ } while (0)
diff --git a/gdb/config/a29k/ultra3.mh b/gdb/config/a29k/ultra3.mh
new file mode 100644
index 00000000000..2f211c5226b
--- /dev/null
+++ b/gdb/config/a29k/ultra3.mh
@@ -0,0 +1,13 @@
+# Host: NYU Ultracomputer (AMD 29000 running Unix)
+
+CC=u3cc
+
+XM_FILE= xm-ultra3.h
+XDEPFILES= ultra3-xdep.o
+
+MH_CFLAGS = -DSYM1
+XM_CLIBS = -lsysv -ljobs -ltermlib
+
+NAT_FILE= nm-ultra3.h
+NATDEPFILES= infptrace.o inftarg.o fork-child.o ultra3-nat.o
+
diff --git a/gdb/config/a29k/ultra3.mt b/gdb/config/a29k/ultra3.mt
new file mode 100644
index 00000000000..1f5fd2f12e4
--- /dev/null
+++ b/gdb/config/a29k/ultra3.mt
@@ -0,0 +1,6 @@
+# Target: AMD 29000 running Unix on New York University processor board
+TDEPFILES= a29k-tdep.o
+TM_FILE= tm-ultra3.h
+
+# SYM1 is some OS they have.
+MT_CFLAGS = -DSYM1
diff --git a/gdb/config/a29k/vx29k.mt b/gdb/config/a29k/vx29k.mt
new file mode 100644
index 00000000000..4d6f5cc1e4b
--- /dev/null
+++ b/gdb/config/a29k/vx29k.mt
@@ -0,0 +1,4 @@
+# Target: AMD 29k running VxWorks
+TDEPFILES= a29k-tdep.o remote-vx.o remote-vx29k.o xdr_ld.o xdr_ptrace.o xdr_rdb.o
+TM_FILE= tm-vx29k.h
+MT_CFLAGS = -DNO_HIF_SUPPORT
diff --git a/gdb/config/a29k/xm-ultra3.h b/gdb/config/a29k/xm-ultra3.h
new file mode 100644
index 00000000000..ec0b1081cf2
--- /dev/null
+++ b/gdb/config/a29k/xm-ultra3.h
@@ -0,0 +1,52 @@
+/* Host definitions for GDB running on an a29k NYU Ultracomputer
+ Copyright (C) 1986, 1987, 1989, 1991 Free Software Foundation, Inc.
+ Contributed by David Wood (wood@lab.ultra.nyu.edu).
+
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Here at NYU we have what we call an ULTRA3 PE board. So
+ ifdefs for ULTRA3 are my doing. At this point in time,
+ I don't know of any other Unixi running on the a29k. */
+
+#define HOST_BYTE_ORDER BIG_ENDIAN
+
+#define HAVE_WAIT_STRUCT
+
+#ifndef L_SET
+# define L_SET 0 /* set the seek pointer */
+# define L_INCR 1 /* increment the seek pointer */
+# define L_XTND 2 /* extend the file size */
+#endif
+
+#ifndef O_RDONLY
+# define O_RDONLY 0
+# define O_WRONLY 1
+# define O_RDWR 2
+#endif
+
+#ifndef F_OK
+# define R_OK 4
+# define W_OK 2
+# define X_OK 1
+# define F_OK 0
+#endif
+
+/* System doesn't provide siginterrupt(). */
+#define NO_SIGINTERRUPT
+
+/* System uses a `short' to hold a process group ID. */
+#define SHORT_PGRP
diff --git a/gdb/config/alpha/alpha-linux.mh b/gdb/config/alpha/alpha-linux.mh
new file mode 100644
index 00000000000..aa4a06956b8
--- /dev/null
+++ b/gdb/config/alpha/alpha-linux.mh
@@ -0,0 +1,9 @@
+# Host: Little-endian Alpha running Linux
+XDEPFILES= ser-tcp.o
+XM_FILE= xm-alphalinux.h
+NAT_FILE= nm-linux.h
+NATDEPFILES= infptrace.o inftarg.o corelow.o core-regset.o alpha-nat.o \
+ fork-child.o solib.o
+
+MMALLOC =
+MMALLOC_CFLAGS = -DNO_MMALLOC
diff --git a/gdb/config/alpha/alpha-linux.mt b/gdb/config/alpha/alpha-linux.mt
new file mode 100644
index 00000000000..7789252daf6
--- /dev/null
+++ b/gdb/config/alpha/alpha-linux.mt
@@ -0,0 +1,3 @@
+# Target: Little-endian Alpha
+TDEPFILES= alpha-tdep.o
+TM_FILE= tm-alphalinux.h
diff --git a/gdb/config/alpha/alpha-osf1.mh b/gdb/config/alpha/alpha-osf1.mh
new file mode 100644
index 00000000000..6ed0f95ffcf
--- /dev/null
+++ b/gdb/config/alpha/alpha-osf1.mh
@@ -0,0 +1,5 @@
+# Host: Little-endian Alpha running OSF/1-1.x
+XDEPFILES=
+XM_FILE= xm-alphaosf.h
+NAT_FILE= nm-osf.h
+NATDEPFILES= infptrace.o inftarg.o corelow.o alpha-nat.o fork-child.o osfsolib.o
diff --git a/gdb/config/alpha/alpha-osf1.mt b/gdb/config/alpha/alpha-osf1.mt
new file mode 100644
index 00000000000..98f87c1134f
--- /dev/null
+++ b/gdb/config/alpha/alpha-osf1.mt
@@ -0,0 +1,3 @@
+# Target: Little-endian Alpha
+TDEPFILES= alpha-tdep.o
+TM_FILE= tm-alpha.h
diff --git a/gdb/config/alpha/alpha-osf2.mh b/gdb/config/alpha/alpha-osf2.mh
new file mode 100644
index 00000000000..569b6fd556a
--- /dev/null
+++ b/gdb/config/alpha/alpha-osf2.mh
@@ -0,0 +1,5 @@
+# Host: Little-endian Alpha running OSF/1-2.x using procfs
+XDEPFILES=
+XM_FILE= xm-alphaosf.h
+NAT_FILE= nm-osf2.h
+NATDEPFILES= infptrace.o inftarg.o corelow.o alpha-nat.o fork-child.o osfsolib.o procfs.o
diff --git a/gdb/config/alpha/alpha-osf3.mh b/gdb/config/alpha/alpha-osf3.mh
new file mode 100644
index 00000000000..49975313674
--- /dev/null
+++ b/gdb/config/alpha/alpha-osf3.mh
@@ -0,0 +1,5 @@
+# Host: Little-endian Alpha running OSF/1-3.x and higher using procfs
+XDEPFILES=
+XM_FILE= xm-alphaosf.h
+NAT_FILE= nm-osf3.h
+NATDEPFILES= infptrace.o inftarg.o corelow.o alpha-nat.o fork-child.o osfsolib.o procfs.o
diff --git a/gdb/config/alpha/nm-linux.h b/gdb/config/alpha/nm-linux.h
new file mode 100644
index 00000000000..eedb1a93a37
--- /dev/null
+++ b/gdb/config/alpha/nm-linux.h
@@ -0,0 +1,66 @@
+/* Native definitions for alpha running Linux.
+ Copyright (C) 1993, 1994 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. */
+
+/* Figure out where the longjmp will land. We expect that we have just entered
+ longjmp and haven't yet setup the stack frame, so the args are still in the
+ argument regs. A0_REGNUM points at the jmp_buf structure from which we
+ extract the pc (JB_PC) that we will land at. The pc is copied into ADDR.
+ This routine returns true on success */
+
+#define GET_LONGJMP_TARGET(ADDR) get_longjmp_target(ADDR)
+extern int
+get_longjmp_target PARAMS ((CORE_ADDR *));
+
+/* Tell gdb that we can attach and detach other processes */
+#define ATTACH_DETACH
+
+/* ptrace register ``addresses'' are absolute. */
+
+#define U_REGS_OFFSET 0
+
+#define PTRACE_ARG3_TYPE long
+
+/* ptrace transfers longs, the ptrace man page is lying. */
+
+#define PTRACE_XFER_TYPE long
+
+/* The alpha does not step over a breakpoint, the manpage is lying again. */
+
+#define CANNOT_STEP_BREAKPOINT
+
+/* Linux has shared libraries. */
+
+#define GDB_TARGET_HAS_SHARED_LIBS
+
+/* Support for shared libraries. */
+
+#include "solib.h"
+
+#ifdef __ELF__
+#define SVR4_SHARED_LIBS
+#define TARGET_ELF64
+#endif
+
+/* This is a lie. It's actually in stdio.h. */
+
+#define PSIGNAL_IN_SIGNAL_H
+
+/* Given a pointer to either a gregset_t or fpregset_t, return a
+ pointer to the first register. */
+#define ALPHA_REGSET_BASE(regsetp) ((long *) (regsetp))
diff --git a/gdb/config/alpha/nm-osf.h b/gdb/config/alpha/nm-osf.h
new file mode 100644
index 00000000000..e06140d95a4
--- /dev/null
+++ b/gdb/config/alpha/nm-osf.h
@@ -0,0 +1,56 @@
+/* Native definitions for alpha running OSF/1.
+ Copyright (C) 1993, 1994 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Figure out where the longjmp will land. We expect that we have just entered
+ longjmp and haven't yet setup the stack frame, so the args are still in the
+ argument regs. A0_REGNUM points at the jmp_buf structure from which we
+ extract the pc (JB_PC) that we will land at. The pc is copied into ADDR.
+ This routine returns true on success */
+
+#define GET_LONGJMP_TARGET(ADDR) get_longjmp_target(ADDR)
+extern int
+get_longjmp_target PARAMS ((CORE_ADDR *));
+
+/* ptrace register ``addresses'' are absolute. */
+
+#define U_REGS_OFFSET 0
+
+/* FIXME: Shouldn't the default definition in inferior.h be int* ? */
+
+#define PTRACE_ARG3_TYPE int*
+
+/* ptrace transfers longs, the ptrace man page is lying. */
+
+#define PTRACE_XFER_TYPE long
+
+/* The alpha does not step over a breakpoint, the manpage is lying again. */
+
+#define CANNOT_STEP_BREAKPOINT
+
+/* OSF/1 has shared libraries. */
+
+#define GDB_TARGET_HAS_SHARED_LIBS
+
+/* Support for shared libraries. */
+
+#include "solib.h"
+
+/* Given a pointer to either a gregset_t or fpregset_t, return a
+ pointer to the first register. */
+#define ALPHA_REGSET_BASE(regsetp) ((regsetp)->regs)
diff --git a/gdb/config/alpha/nm-osf2.h b/gdb/config/alpha/nm-osf2.h
new file mode 100644
index 00000000000..01725efd5ce
--- /dev/null
+++ b/gdb/config/alpha/nm-osf2.h
@@ -0,0 +1,54 @@
+/* Native definitions for alpha running OSF/1-2.x, using procfs.
+ Copyright (C) 1995 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Get generic OSF/1 definitions. */
+#include "alpha/nm-osf.h"
+
+/* OSF/1-2.x has optional /proc support, try to use it instead of ptrace. */
+#define USE_PROC_FS
+#define HAVE_OPTIONAL_PROC_FS
+
+/* OSF/1 doesn't provide the standard fault definitions, so don't use them. */
+#define FAULTED_USE_SIGINFO
+
+/* Don't trace faults under OSF/1, rely on the posting of the appropriate
+ signal if fault tracing is disabled.
+ Tracing T_IFAULT under Alpha OSF/1 causes a `floating point enable'
+ fault from which we cannot continue (except by disabling the
+ tracing).
+ And as OSF/1 doesn't provide the standard fault definitions, the
+ mapping of faults to appropriate signals in procfs_wait is difficult. */
+#define PROCFS_DONT_TRACE_FAULTS
+
+/* Work around some peculiarities in the OSF/1 procfs implementation. */
+#define PROCFS_SIGPEND_OFFSET
+#define PROCFS_NEED_PIOCSSIG_FOR_KILL
+#define PROCFS_DONT_PIOCSSIG_CURSIG
+
+/* Return sizeof user struct to callers in less machine dependent routines */
+
+#define KERNEL_U_SIZE kernel_u_size()
+extern int kernel_u_size PARAMS ((void));
+
+/* poll() doesn't seem to work properly for /proc in this version of the OS.
+ If we only specify POLLPRI, things hang. It seems to get better when we set
+ POLLOUT, but that always returns POLLNVAL!!! Also, POLLOUT causes problems
+ on other OSes. */
+
+#define LOSING_POLL
diff --git a/gdb/config/alpha/nm-osf3.h b/gdb/config/alpha/nm-osf3.h
new file mode 100644
index 00000000000..a1871a68136
--- /dev/null
+++ b/gdb/config/alpha/nm-osf3.h
@@ -0,0 +1,26 @@
+/* Native definitions for alpha running OSF/1-3.x and higher, using procfs.
+ Copyright (C) 1995 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* OSF/1-3.x fixes some OSF/1-2.x procfs peculiarities and adds
+ a new one. */
+#include "alpha/nm-osf2.h"
+
+#undef PROCFS_NEED_PIOCSSIG_FOR_KILL
+#undef PROCFS_DONT_PIOCSSIG_CURSIG
+#define PROCFS_NEED_CLEAR_CURSIG_FOR_KILL
diff --git a/gdb/config/alpha/tm-alpha.h b/gdb/config/alpha/tm-alpha.h
new file mode 100644
index 00000000000..d9b98126bb2
--- /dev/null
+++ b/gdb/config/alpha/tm-alpha.h
@@ -0,0 +1,479 @@
+/* Definitions to make GDB run on an Alpha box under OSF1. This is
+ also used by the Alpha/Netware and Alpha/Linux targets.
+ Copyright 1993, 1994, 1995, 1996 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef TM_ALPHA_H
+#define TM_ALPHA_H
+
+#include "bfd.h"
+#include "coff/sym.h" /* Needed for PDR below. */
+#include "coff/symconst.h"
+
+#ifdef __STDC__
+struct frame_info;
+struct type;
+struct value;
+struct symbol;
+#endif
+
+#if !defined (TARGET_BYTE_ORDER)
+#define TARGET_BYTE_ORDER LITTLE_ENDIAN
+#endif
+
+/* Redefine some target bit sizes from the default. */
+
+#define TARGET_LONG_BIT 64
+#define TARGET_LONG_LONG_BIT 64
+#define TARGET_PTR_BIT 64
+
+/* Floating point is IEEE compliant */
+#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.
+ */
+#define START_INFERIOR_TRAPS_EXPECTED 3
+
+/* Offset from address of function to start of its code.
+ Zero on most machines. */
+
+#define FUNCTION_START_OFFSET 0
+
+/* Advance PC across any function entry prologue instructions
+ to reach some "real" code. */
+
+#define SKIP_PROLOGUE(pc) pc = alpha_skip_prologue(pc, 0)
+extern CORE_ADDR alpha_skip_prologue PARAMS ((CORE_ADDR addr, int lenient));
+
+/* 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) alpha_saved_pc_after_call(frame)
+extern CORE_ADDR
+alpha_saved_pc_after_call PARAMS ((struct frame_info *));
+
+/* Are we currently handling a signal ? */
+
+#define IN_SIGTRAMP(pc, name) ((name) && STREQ ("__sigtramp", (name)))
+
+/* Stack grows downward. */
+
+#define INNER_THAN(lhs,rhs) ((lhs) < (rhs))
+
+#define BREAKPOINT {0x80, 0, 0, 0} /* call_pal bpt */
+
+/* Amount PC must be decremented by after a breakpoint.
+ This is often the number of bytes in BREAKPOINT
+ but not always. */
+
+#ifndef DECR_PC_AFTER_BREAK
+#define DECR_PC_AFTER_BREAK 4
+#endif
+
+/* Say how long (ordinary) registers are. This is a piece of bogosity
+ used in push_word and a few other places; REGISTER_RAW_SIZE is the
+ real way to know how big a register is. */
+
+#define REGISTER_SIZE 8
+
+/* Number of machine registers */
+
+#define NUM_REGS 66
+
+/* Initializer for an array of names of registers.
+ There should be NUM_REGS strings in this initializer. */
+
+#define REGISTER_NAMES \
+ { "v0", "t0", "t1", "t2", "t3", "t4", "t5", "t6", \
+ "t7", "s0", "s1", "s2", "s3", "s4", "s5", "fp", \
+ "a0", "a1", "a2", "a3", "a4", "a5", "t8", "t9", \
+ "t10", "t11", "ra", "t12", "at", "gp", "sp", "zero", \
+ "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", \
+ "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", \
+ "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",\
+ "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",\
+ "pc", "vfp", \
+ }
+
+/* Register numbers of various important registers.
+ Note that most of these values are "real" register numbers,
+ and correspond to the general registers of the machine,
+ and FP_REGNUM is a "phony" register number which is too large
+ to be an actual register number as far as the user is concerned
+ but serves to get the desired value when passed to read_register. */
+
+#define V0_REGNUM 0 /* Function integer return value */
+#define T7_REGNUM 8 /* Return address register for OSF/1 __add* */
+#define GCC_FP_REGNUM 15 /* Used by gcc as frame register */
+#define A0_REGNUM 16 /* Loc of first arg during a subr call */
+#define T9_REGNUM 23 /* Return address register for OSF/1 __div* */
+#define T12_REGNUM 27 /* Contains start addr of current proc */
+#define SP_REGNUM 30 /* Contains address of top of stack */
+#define RA_REGNUM 26 /* Contains return address value */
+#define ZERO_REGNUM 31 /* Read-only register, always 0 */
+#define FP0_REGNUM 32 /* Floating point register 0 */
+#define FPA0_REGNUM 48 /* First float arg during a subr call */
+#define PC_REGNUM 64 /* Contains program counter */
+#define FP_REGNUM 65 /* Virtual frame pointer */
+
+#define CANNOT_FETCH_REGISTER(regno) \
+ ((regno) == FP_REGNUM || (regno) == ZERO_REGNUM)
+#define CANNOT_STORE_REGISTER(regno) \
+ ((regno) == FP_REGNUM || (regno) == ZERO_REGNUM)
+
+/* Total amount of space needed to store our copies of the machine's
+ register state, the array `registers'. */
+#define REGISTER_BYTES (NUM_REGS * 8)
+
+/* Index within `registers' of the first byte of the space for
+ register N. */
+
+#define REGISTER_BYTE(N) ((N) * 8)
+
+/* Number of bytes of storage in the actual machine representation
+ for register N. On Alphas, all regs are 8 bytes. */
+
+#define REGISTER_RAW_SIZE(N) 8
+
+/* Number of bytes of storage in the program's representation
+ for register N. On Alphas, all regs are 8 bytes. */
+
+#define REGISTER_VIRTUAL_SIZE(N) 8
+
+/* Largest value REGISTER_RAW_SIZE can have. */
+
+#define MAX_REGISTER_RAW_SIZE 8
+
+/* Largest value REGISTER_VIRTUAL_SIZE can have. */
+
+#define MAX_REGISTER_VIRTUAL_SIZE 8
+
+/* Nonzero if register N requires conversion
+ from raw format to virtual format.
+ The alpha needs a conversion between register and memory format if
+ the register is a floating point register and
+ memory format is float, as the register format must be double
+ or
+ memory format is an integer with 4 bytes or less, as the representation
+ of integers in floating point registers is different. */
+
+#define REGISTER_CONVERTIBLE(N) ((N) >= FP0_REGNUM && (N) < FP0_REGNUM + 32)
+
+/* Convert data from raw format for register REGNUM in buffer FROM
+ to virtual format with type TYPE in buffer TO. */
+
+#define REGISTER_CONVERT_TO_VIRTUAL(REGNUM, TYPE, FROM, TO) \
+ alpha_register_convert_to_virtual (REGNUM, TYPE, FROM, TO)
+extern void
+alpha_register_convert_to_virtual PARAMS ((int, struct type *, char *, char *));
+
+/* Convert data from virtual format with type TYPE in buffer FROM
+ to raw format for register REGNUM in buffer TO. */
+
+#define REGISTER_CONVERT_TO_RAW(TYPE, REGNUM, FROM, TO) \
+ alpha_register_convert_to_raw (TYPE, REGNUM, FROM, TO)
+extern void
+alpha_register_convert_to_raw PARAMS ((struct type *, int, char *, char *));
+
+/* Return the GDB type object for the "standard" data type
+ of data in register N. */
+
+#define REGISTER_VIRTUAL_TYPE(N) \
+ (((N) >= FP0_REGNUM && (N) < FP0_REGNUM+32) \
+ ? builtin_type_double : builtin_type_long) \
+
+/* Store the address of the place in which to copy the structure the
+ subroutine will return. Handled by alpha_push_arguments. */
+
+#define STORE_STRUCT_RETURN(addr, sp) /**/
+
+/* Extract from an array REGBUF containing the (raw) register state
+ a function return value of type TYPE, and copy that, in virtual format,
+ into VALBUF. */
+
+#define EXTRACT_RETURN_VALUE(TYPE,REGBUF,VALBUF) \
+ alpha_extract_return_value(TYPE, REGBUF, VALBUF)
+extern void
+alpha_extract_return_value PARAMS ((struct type *, char *, char *));
+
+/* Write into appropriate registers a function return value
+ of type TYPE, given in virtual format. */
+
+#define STORE_RETURN_VALUE(TYPE,VALBUF) \
+ alpha_store_return_value(TYPE, VALBUF)
+extern void
+alpha_store_return_value PARAMS ((struct type *, char *));
+
+/* 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). */
+/* The address is passed in a0 upon entry to the function, but when
+ the function exits, the compiler has copied the value to v0. This
+ convention is specified by the System V ABI, so I think we can rely
+ on it. */
+
+#define EXTRACT_STRUCT_VALUE_ADDRESS(REGBUF) \
+ (extract_address (REGBUF + REGISTER_BYTE (V0_REGNUM), \
+ REGISTER_RAW_SIZE (V0_REGNUM)))
+
+/* Structures are returned by ref in extra arg0 */
+#define USE_STRUCT_CONVENTION(gcc_p, type) 1
+
+
+/* Describe the pointer in each stack frame to the previous stack frame
+ (its caller). */
+
+/* FRAME_CHAIN takes a frame's nominal address
+ and produces the frame's chain-pointer. */
+
+#define FRAME_CHAIN(thisframe) (CORE_ADDR) alpha_frame_chain (thisframe)
+extern CORE_ADDR alpha_frame_chain PARAMS ((struct frame_info *));
+
+/* Define other aspects of the stack frame. */
+
+
+/* A macro that tells us whether the function invocation represented
+ by FI does not have a frame on the stack associated with it. If it
+ does not, FRAMELESS is set to 1, else 0. */
+/* We handle this differently for alpha, and maybe we should not */
+
+#define FRAMELESS_FUNCTION_INVOCATION(FI, FRAMELESS) {(FRAMELESS) = 0;}
+
+/* Saved Pc. */
+
+#define FRAME_SAVED_PC(FRAME) (alpha_frame_saved_pc(FRAME))
+extern CORE_ADDR
+alpha_frame_saved_pc PARAMS ((struct frame_info *));
+
+/* The alpha has two different virtual pointers for arguments and locals.
+
+ The virtual argument pointer is pointing to the bottom of the argument
+ transfer area, which is located immediately below the virtual frame
+ pointer. Its size is fixed for the native compiler, it is either zero
+ (for the no arguments case) or large enough to hold all argument registers.
+ gcc uses a variable sized argument transfer area. As it has
+ to stay compatible with the native debugging tools it has to use the same
+ virtual argument pointer and adjust the argument offsets accordingly.
+
+ The virtual local pointer is localoff bytes below the virtual frame
+ pointer, the value of localoff is obtained from the PDR. */
+
+#define ALPHA_NUM_ARG_REGS 6
+
+#define FRAME_ARGS_ADDRESS(fi) ((fi)->frame - (ALPHA_NUM_ARG_REGS * 8))
+
+#define FRAME_LOCALS_ADDRESS(fi) ((fi)->frame - (fi)->localoff)
+
+/* Return number of args passed to a frame.
+ Can return -1, meaning no way to tell. */
+
+#define FRAME_NUM_ARGS(num, fi) ((num) = -1)
+
+/* Return number of bytes at start of arglist that are not really args. */
+
+#define FRAME_ARGS_SKIP 0
+
+/* Put here the code to store, into a struct frame_saved_regs,
+ the addresses of the saved registers of frame described by FRAME_INFO.
+ This includes special registers such as pc and fp saved in special
+ ways in the stack frame. sp is even more special:
+ the address we return for it IS the sp for the next frame. */
+
+extern void alpha_find_saved_regs PARAMS ((struct frame_info *));
+
+#define FRAME_INIT_SAVED_REGS(frame_info) \
+ do { \
+ if ((frame_info)->saved_regs == NULL) \
+ alpha_find_saved_regs (frame_info); \
+ (frame_info)->saved_regs[SP_REGNUM] = (frame_info)->frame; \
+ } while (0)
+
+
+/* Things needed for making the inferior call functions. */
+
+#define PUSH_ARGUMENTS(nargs, args, sp, struct_return, struct_addr) \
+ sp = alpha_push_arguments((nargs), (args), (sp), (struct_return), (struct_addr))
+extern CORE_ADDR
+alpha_push_arguments PARAMS ((int, struct value **, CORE_ADDR, int, CORE_ADDR));
+
+/* Push an empty stack frame, to record the current PC, etc. */
+
+#define PUSH_DUMMY_FRAME alpha_push_dummy_frame()
+extern void
+alpha_push_dummy_frame PARAMS ((void));
+
+/* Discard from the stack the innermost frame, restoring all registers. */
+
+#define POP_FRAME alpha_pop_frame()
+extern void
+alpha_pop_frame PARAMS ((void));
+
+/* Alpha OSF/1 inhibits execution of code on the stack.
+ But there is no need for a dummy on the alpha. PUSH_ARGUMENTS
+ takes care of all argument handling and bp_call_dummy takes care
+ of stopping the dummy. */
+
+#define CALL_DUMMY_LOCATION AT_ENTRY_POINT
+
+/* On the Alpha the call dummy code is never copied to user space,
+ stopping the user call is achieved via a bp_call_dummy breakpoint.
+ But we need a fake CALL_DUMMY definition to enable the proper
+ call_function_by_hand and to avoid zero length array warnings
+ in valops.c */
+
+#define CALL_DUMMY { 0 } /* Content doesn't matter. */
+
+#define CALL_DUMMY_START_OFFSET (0)
+
+#define CALL_DUMMY_BREAKPOINT_OFFSET (0)
+
+extern CORE_ADDR alpha_call_dummy_address PARAMS ((void));
+#define CALL_DUMMY_ADDRESS() alpha_call_dummy_address()
+
+/* Insert the specified number of args and function address
+ into a call sequence of the above form stored at DUMMYNAME.
+ We only have to set RA_REGNUM to the dummy breakpoint address
+ and T12_REGNUM (the `procedure value register') to the function address. */
+
+#define FIX_CALL_DUMMY(dummyname, pc, fun, nargs, args, type, gcc_p) \
+{ \
+ CORE_ADDR bp_address = CALL_DUMMY_ADDRESS (); \
+ if (bp_address == 0) \
+ error ("no place to put call"); \
+ write_register (RA_REGNUM, bp_address); \
+ write_register (T12_REGNUM, fun); \
+}
+
+/* There's a mess in stack frame creation. See comments in blockframe.c
+ near reference to INIT_FRAME_PC_FIRST. */
+
+#define INIT_FRAME_PC(fromleaf, prev) /* nada */
+
+#define INIT_FRAME_PC_FIRST(fromleaf, prev) \
+ (prev)->pc = ((fromleaf) ? SAVED_PC_AFTER_CALL ((prev)->next) : \
+ (prev)->next ? FRAME_SAVED_PC ((prev)->next) : read_pc ());
+
+/* Special symbol found in blocks associated with routines. We can hang
+ alpha_extra_func_info_t's off of this. */
+
+#define MIPS_EFI_SYMBOL_NAME "__GDB_EFI_INFO__"
+extern void ecoff_relocate_efi PARAMS ((struct symbol *, CORE_ADDR));
+
+/* Specific information about a procedure.
+ This overlays the ALPHA's PDR records,
+ alpharead.c (ab)uses this to save memory */
+
+typedef struct alpha_extra_func_info {
+ long numargs; /* number of args to procedure (was iopt) */
+ PDR pdr; /* Procedure descriptor record */
+} *alpha_extra_func_info_t;
+
+/* Define the extra_func_info that mipsread.c needs.
+ FIXME: We should define our own PDR interface, perhaps in a separate
+ header file. This would get rid of the <bfd.h> inclusion in all sources
+ and would abstract the mips/alpha interface from ecoff. */
+#define mips_extra_func_info alpha_extra_func_info
+#define mips_extra_func_info_t alpha_extra_func_info_t
+
+#define EXTRA_FRAME_INFO \
+ int localoff; \
+ int pc_reg; \
+ alpha_extra_func_info_t proc_desc;
+
+#define INIT_EXTRA_FRAME_INFO(fromleaf, fci) init_extra_frame_info(fci)
+extern void
+init_extra_frame_info PARAMS ((struct frame_info *));
+
+#define PRINT_EXTRA_FRAME_INFO(fi) \
+ { \
+ if (fi && fi->proc_desc && fi->proc_desc->pdr.framereg < NUM_REGS) \
+ printf_filtered (" frame pointer is at %s+%d\n", \
+ REGISTER_NAME (fi->proc_desc->pdr.framereg), \
+ fi->proc_desc->pdr.frameoffset); \
+ }
+
+/* It takes two values to specify a frame on the ALPHA. Sigh.
+
+ In fact, at the moment, the *PC* is the primary value that sets up
+ a frame. The PC is looked up to see what function it's in; symbol
+ information from that function tells us which register is the frame
+ pointer base, and what offset from there is the "virtual frame pointer".
+ (This is usually an offset from SP.) FIXME -- this should be cleaned
+ up so that the primary value is the SP, and the PC is used to disambiguate
+ multiple functions with the same SP that are at different stack levels. */
+
+#define SETUP_ARBITRARY_FRAME(argc, argv) setup_arbitrary_frame (argc, argv)
+extern struct frame_info *setup_arbitrary_frame PARAMS ((int, CORE_ADDR *));
+
+/* This is used by heuristic_proc_start. It should be shot it the head. */
+#ifndef VM_MIN_ADDRESS
+#define VM_MIN_ADDRESS (CORE_ADDR)0x120000000
+#endif
+
+/* If PC is in a shared library trampoline code, return the PC
+ where the function itself actually starts. If not, return 0. */
+#define SKIP_TRAMPOLINE_CODE(pc) find_solib_trampoline_target (pc)
+
+/* If the current gcc for for this target does not produce correct debugging
+ information for float parameters, both prototyped and unprototyped, then
+ define this macro. This forces gdb to always assume that floats are
+ passed as doubles and then converted in the callee.
+
+ For the alpha, it appears that the debug info marks the parameters as
+ floats regardless of whether the function is prototyped, but the actual
+ values are always passed in as doubles. Thus by setting this to 1, both
+ types of calls will work. */
+
+#define COERCE_FLOAT_TO_DOUBLE 1
+
+/* Return TRUE if procedure descriptor PROC is a procedure descriptor
+ that refers to a dynamically generated sigtramp function.
+
+ OSF/1 doesn't use dynamic sigtramp functions, so this is always
+ FALSE. */
+
+#define PROC_DESC_IS_DYN_SIGTRAMP(proc) (0)
+#define SET_PROC_DESC_IS_DYN_SIGTRAMP(proc)
+
+/* If PC is inside a dynamically generated sigtramp function, return
+ how many bytes the program counter is beyond the start of that
+ function. Otherwise, return a negative value.
+
+ OSF/1 doesn't use dynamic sigtramp functions, so this always
+ returns -1. */
+
+#define DYNAMIC_SIGTRAMP_OFFSET(pc) (-1)
+
+/* Translate a signal handler frame into the address of the sigcontext
+ structure. */
+
+#define SIGCONTEXT_ADDR(frame) \
+ (read_memory_integer ((frame)->next ? frame->next->frame : frame->frame, 8))
+
+/* If FRAME refers to a sigtramp frame, return the address of the next
+ frame. */
+
+#define FRAME_PAST_SIGTRAMP_FRAME(frame, pc) \
+ (alpha_osf_skip_sigtramp_frame (frame, pc))
+extern CORE_ADDR alpha_osf_skip_sigtramp_frame PARAMS ((struct frame_info *, CORE_ADDR));
+
+#endif /* TM_ALPHA_H */
diff --git a/gdb/config/alpha/tm-alphalinux.h b/gdb/config/alpha/tm-alphalinux.h
new file mode 100644
index 00000000000..d836a7054c8
--- /dev/null
+++ b/gdb/config/alpha/tm-alphalinux.h
@@ -0,0 +1,80 @@
+/* Definitions to make GDB run on an Alpha box under Linux. The
+ definitions here are used when the _target_ system is running Linux.
+ Copyright 1996 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef TM_LINUXALPHA_H
+#define TM_LINUXALPHA_H
+
+#include "alpha/tm-alpha.h"
+
+/* Are we currently handling a signal ? */
+
+extern long alpha_linux_sigtramp_offset PARAMS ((CORE_ADDR));
+#undef IN_SIGTRAMP
+#define IN_SIGTRAMP(pc, name) (alpha_linux_sigtramp_offset (pc) >= 0)
+
+/* Get start and end address of sigtramp handler. */
+
+#define SIGTRAMP_START(pc) (pc - alpha_linux_sigtramp_offset (pc))
+#define SIGTRAMP_END(pc) (SIGTRAMP_START(pc) + 3*4)
+
+
+/* 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 Linux and most implementations. */
+
+#undef START_INFERIOR_TRAPS_EXPECTED
+#define START_INFERIOR_TRAPS_EXPECTED 2
+
+/* Return TRUE if procedure descriptor PROC is a procedure descriptor
+ that refers to a dynamically generated sigtramp function. */
+
+#undef PROC_DESC_IS_DYN_SIGTRAMP
+#define PROC_SIGTRAMP_MAGIC 0x0e0f0f0f
+#define PROC_DESC_IS_DYN_SIGTRAMP(proc) ((proc)->pdr.isym \
+ == PROC_SIGTRAMP_MAGIC)
+#undef SET_PROC_DESC_IS_DYN_SIGTRAMP
+#define SET_PROC_DESC_IS_DYN_SIGTRAMP(proc) ((proc)->pdr.isym \
+ = PROC_SIGTRAMP_MAGIC)
+
+/* If PC is inside a dynamically generated sigtramp function, return
+ how many bytes the program counter is beyond the start of that
+ function. Otherwise, return a negative value. */
+
+#undef DYNAMIC_SIGTRAMP_OFFSET
+#define DYNAMIC_SIGTRAMP_OFFSET(pc) (alpha_linux_sigtramp_offset (pc))
+
+/* Translate a signal handler frame into the address of the sigcontext
+ structure. */
+
+#undef SIGCONTEXT_ADDR
+#define SIGCONTEXT_ADDR(frame) ((frame)->frame - 0x298)
+
+/* If FRAME refers to a sigtramp frame, return the address of the next frame.
+
+ Under Linux, sigtramp handlers have dynamically generated procedure
+ descriptors that make this hack unnecessary. */
+
+#undef FRAME_PAST_SIGTRAMP_FRAME
+#define FRAME_PAST_SIGTRAMP_FRAME(frame, pc) (0)
+
+/* We need this for the SOLIB_TRAMPOLINE stuff. */
+#include "tm-sysv4.h"
+
+#endif /* TM_LINUXALPHA_H */
diff --git a/gdb/config/alpha/xm-alphalinux.h b/gdb/config/alpha/xm-alphalinux.h
new file mode 100644
index 00000000000..a7aeab01707
--- /dev/null
+++ b/gdb/config/alpha/xm-alphalinux.h
@@ -0,0 +1,29 @@
+/* Host definitions for GDB running on an Alpha under Linux
+ Copyright (C) 1996 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 (HOST_BYTE_ORDER)
+#define HOST_BYTE_ORDER LITTLE_ENDIAN
+#endif
+
+/* The alpha has no siginterrupt routine. */
+#define NO_SIGINTERRUPT
+
+#define HAVE_TERMIOS
+#define HAVE_SIGSETMASK 1
+#define USG
diff --git a/gdb/config/alpha/xm-alphaosf.h b/gdb/config/alpha/xm-alphaosf.h
new file mode 100644
index 00000000000..40b7fe0a204
--- /dev/null
+++ b/gdb/config/alpha/xm-alphaosf.h
@@ -0,0 +1,27 @@
+/* Host definitions for GDB running on an alpha under OSF/1
+ Copyright (C) 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. */
+
+#if !defined (HOST_BYTE_ORDER)
+#define HOST_BYTE_ORDER LITTLE_ENDIAN
+#endif
+
+/* The alpha has no siginterrupt routine. */
+#define NO_SIGINTERRUPT
+
+#define HAVE_TERMIOS
diff --git a/gdb/config/arc/arc.mt b/gdb/config/arc/arc.mt
new file mode 100644
index 00000000000..8ee8c3d0619
--- /dev/null
+++ b/gdb/config/arc/arc.mt
@@ -0,0 +1,3 @@
+# Target: ARC processor
+TDEPFILES = arc-tdep.o
+TM_FILE = tm-arc.h
diff --git a/gdb/config/arc/tm-arc.h b/gdb/config/arc/tm-arc.h
new file mode 100644
index 00000000000..e964bef1645
--- /dev/null
+++ b/gdb/config/arc/tm-arc.h
@@ -0,0 +1,347 @@
+/* Parameters for target machine ARC, for GDB, the GNU debugger.
+ Copyright (C) 1995 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Used by arc-tdep.c to set the default cpu type. */
+#define DEFAULT_ARC_CPU_TYPE "base"
+
+/* Byte order is selectable. */
+#define TARGET_BYTE_ORDER_SELECTABLE
+
+/* We have IEEE floating point, if we have any float at all. */
+#define IEEE_FLOAT
+
+/* 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. SKIP_PROLOGUE_FRAMELESS_P advances
+ the PC past some of the prologue, but stops as soon as it
+ knows that the function has a frame. Its result is equal
+ to its input PC if the function is frameless, unequal otherwise. */
+
+#define SKIP_PROLOGUE(pc) \
+ { pc = skip_prologue (pc, 0); }
+#define SKIP_PROLOGUE_FRAMELESS_P(pc) \
+ { pc = skip_prologue (pc, 1); }
+extern CORE_ADDR skip_prologue PARAMS ((CORE_ADDR, int));
+
+/* Sequence of bytes for breakpoint instruction.
+ ??? The current value is "sr -1,[-1]" and is for the simulator only.
+ The simulator watches for this and does the right thing.
+ The hardware version will have to associate with each breakpoint
+ the sequence "flag 1; nop; nop; nop". IE: The breakpoint insn will not
+ be a fixed set of bits but instead will be a branch to a semi-random
+ address. Presumably this will be cleaned up for "second silicon". */
+#define BIG_BREAKPOINT { 0x12, 0x1f, 0xff, 0xff }
+#define LITTLE_BREAKPOINT { 0xff, 0xff, 0x1f, 0x12 }
+
+/* Given the exposed pipeline, there isn't any one correct value.
+ However, this value must be 4. GDB can't handle any other value (other than
+ zero). See for example infrun.c:
+ "prev_pc != stop_pc - DECR_PC_AFTER_BREAK" */
+/* FIXME */
+#define DECR_PC_AFTER_BREAK 8
+
+/* We don't have a reliable single step facility.
+ ??? We do have a cycle single step facility, but that won't work. */
+#define SOFTWARE_SINGLE_STEP_P 1
+extern void arc_software_single_step PARAMS ((unsigned int, int));
+#define SOFTWARE_SINGLE_STEP(sig,bp_p) arc_software_single_step (sig, bp_p)
+
+/* FIXME: Need to set STEP_SKIPS_DELAY. */
+
+/* Given a pc value as defined by the hardware, return the real address.
+ Remember that on the ARC blink contains that status register which
+ includes PC + flags (so we have to mask out the flags). */
+#define ARC_PC_TO_REAL_ADDRESS(pc) (((pc) & 0xffffff) << 2)
+
+/* 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) \
+ (ARC_PC_TO_REAL_ADDRESS (read_register (BLINK_REGNUM)))
+
+/* Stack grows upward */
+
+#define INNER_THAN(lhs,rhs) ((lhs) < (rhs))
+
+/* Say how long (ordinary) registers are. This is a piece of bogosity
+ used in push_word and a few other places; REGISTER_RAW_SIZE is the
+ real way to know how big a register is. */
+#define REGISTER_SIZE 4
+
+/* Number of machine registers */
+#define NUM_REGS 92
+
+/* Initializer for an array of names of registers.
+ There should be NUM_REGS strings in this initializer. */
+
+#define REGISTER_NAMES \
+{ \
+ /* 0 */ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", \
+ /* 8 */ "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", \
+ /* 16 */ "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", \
+ /* 24 */ "r24", "r25", "r26", "fp", "sp", "ilink1", "ilink2", "blink", \
+ /* 32 */ "r32", "r33", "r34", "r35", "r36", "r37", "r38", "r39", \
+ /* 40 */ "r40", "r41", "r42", "r43", "r44", "r45", "r46", "r47", \
+ /* 48 */ "r48", "r49", "r50", "r51", "r52", "r53", "r54", "r55", \
+ /* 56 */ "r56", "mlo", "mmid", "mhi", "lp_count", \
+ /* 61 */ "status", "sema", "lp_start", "lp_end", "identity", "debug", \
+ /* 67 */ "aux10", "aux11", "aux12", "aux13", "aux14", \
+ /* 72 */ "aux15", "aux16", "aux17", "aux18", "aux19", \
+ /* 77 */ "aux1a", "aux1b", "aux1c", "aux1d", "aux1e", \
+ /* 82 */ "aux1f", "aux20", "aux21", "aux22", \
+ /* 86 */ "aux30", "aux31", "aux32", "aux33", "aux40", \
+ /* 91 */ "pc" \
+}
+
+/* Register numbers of various important registers (used to index
+ into arrays of register names and register values). */
+
+#define R0_REGNUM 0 /* First local register */
+#define R59_REGNUM 59 /* Last local register */
+#define FP_REGNUM 27 /* Contains address of executing stack frame */
+#define SP_REGNUM 28 /* stack pointer */
+#define BLINK_REGNUM 31 /* link register */
+#define STA_REGNUM 61 /* processor status word */
+#define PC_REGNUM 91 /* instruction pointer */
+#define AUX_BEG_REGNUM 61 /* aux reg begins */
+#define AUX_END_REGNUM 90 /* aux reg ends, pc not real aux reg */
+
+/* Fake registers used to mark immediate data. */
+#define SHIMM_FLAG_REGNUM 61
+#define LIMM_REGNUM 62
+#define SHIMM_REGNUM 63
+
+#define AUX_REG_MAP \
+{ \
+ { 0, 1, 2, 3, 4, 5, \
+ 16, -1, -1, -1, -1, \
+ -1, -1, -1, -1, -1, \
+ -1, -1, -1, -1, 30, \
+ -1, 32, 33, -1, \
+ 48, 49, 50, 51, 64, \
+ 0 \
+ }, \
+ { 0, 1, 2, 3, 4, 5, \
+ 16, -1, -1, -1, -1, \
+ -1, -1, -1, -1, -1, \
+ -1, -1, -1, -1, 30, \
+ 31, 32, 33, -1, \
+ -1, -1, -1, -1, -1, \
+ 0 \
+ }, \
+ { 0, 1, 2, 3, 4, 5, \
+ 16, 17, 18, 19, 20, \
+ 21, 22, 23, 24, 25, \
+ 26, 27, 28, 29, 30, \
+ 31, 32, 33, 34, \
+ -1, -1, -1, -1, -1, \
+ 0 \
+ } \
+}
+
+#define PFP_REGNUM R0_REGNUM /* Previous frame pointer */
+
+/* Total amount of space needed to store our copies of the machine's
+ register state, the array `registers'. */
+#define REGISTER_BYTES (NUM_REGS * 4)
+
+/* Index within `registers' of the first byte of the space for register N. */
+#define REGISTER_BYTE(N) (4*(N))
+
+/* 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
+
+/* Return the GDB type object for the "standard" data type
+ of data in register N. */
+#define REGISTER_VIRTUAL_TYPE(N) (builtin_type_int)
+
+
+/* Macros for understanding function return values... */
+
+/* Does the specified function use the "struct returning" convention
+ or the "value returning" convention? The "value returning" convention
+ almost invariably returns the entire value in registers. The
+ "struct returning" convention often returns the entire value in
+ memory, and passes a pointer (out of or into the function) saying
+ where the value (is or should go).
+
+ Since this sometimes depends on whether it was compiled with GCC,
+ this is also an argument. This is used in call_function to build a
+ stack, and in value_being_returned to print return values.
+
+ On arc, a structure is always retunred with pointer in r0. */
+
+#define USE_STRUCT_CONVENTION(gcc_p, type) 1
+
+/* Extract from an array REGBUF containing the (raw) register state
+ a function return value of type TYPE, and copy that, in virtual format,
+ into VALBUF. This is only called if USE_STRUCT_CONVENTION for this
+ type is 0.
+*/
+#define EXTRACT_RETURN_VALUE(TYPE,REGBUF,VALBUF) \
+ memcpy(VALBUF, REGBUF+REGISTER_BYTE(R0_REGNUM), TYPE_LENGTH (TYPE))
+
+/* If USE_STRUCT_CONVENTION produces a 1,
+ extract from an array REGBUF containing the (raw) register state
+ the address in which a function should return its structure value,
+ as a CORE_ADDR (or an expression that can be used as one). */
+#define EXTRACT_STRUCT_VALUE_ADDRESS(REGBUF) \
+ (error("Don't know where large structure is returned on arc"), 0)
+
+/* Write into appropriate registers a function return value
+ of type TYPE, given in virtual format, for "value returning" functions.
+ For 'return' command: not (yet) implemented for arc. */
+#define STORE_RETURN_VALUE(TYPE,VALBUF) \
+ error ("Returning values from functions is not implemented in arc gdb")
+
+/* Store the address of the place in which to copy the structure the
+ subroutine will return. This is called from call_function. */
+#define STORE_STRUCT_RETURN(ADDR, SP) \
+ error ("Returning values from functions is not implemented in arc gdb")
+
+
+/* Describe the pointer in each stack frame to the previous stack frame
+ (its caller). */
+
+/* We cache information about saved registers in the frame structure,
+ to save us from having to re-scan function prologues every time
+ a register in a non-current frame is accessed. */
+
+#define EXTRA_FRAME_INFO \
+ struct frame_saved_regs *fsr; \
+ CORE_ADDR arg_pointer;
+
+/* Zero the frame_saved_regs pointer when the frame is initialized,
+ so that FRAME_FIND_SAVED_REGS () will know to allocate and
+ initialize a frame_saved_regs struct the first time it is called.
+ Set the arg_pointer to -1, which is not valid; 0 and other values
+ indicate real, cached values. */
+
+#define INIT_EXTRA_FRAME_INFO(fromleaf, fi) \
+ ((fi)->fsr = 0, (fi)->arg_pointer = -1)
+
+/* FRAME_CHAIN takes a frame's nominal address
+ and produces the frame's chain-pointer.
+ However, if FRAME_CHAIN_VALID returns zero,
+ it means the given frame is the outermost one and has no caller. */
+/* On the arc, we get the chain pointer by reading the PFP saved
+ on the stack. */
+/* The PFP and RPC is in fp and fp+4. */
+
+#define FRAME_CHAIN(thisframe) \
+ (read_memory_integer (FRAME_FP (thisframe), 4))
+
+/* FRAME_CHAIN_VALID returns zero if the given frame is the outermost one
+ and has no caller. */
+#define FRAME_CHAIN_VALID(chain, thisframe) nonnull_frame_chain_valid (chain, thisframe)
+
+/* 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) \
+ do { \
+ if ((FI)->signal_handler_caller) \
+ (FRAMELESS) = 0; \
+ else \
+ (FRAMELESS) = frameless_look_for_prologue (FI); \
+ } while (0)
+
+/* Where is the PC for a specific frame.
+ A leaf function may never save blink, so we have to check for that here. */
+
+#define FRAME_SAVED_PC(frame) (arc_frame_saved_pc (frame))
+struct frame_info; /* in case frame.h not included yet */
+CORE_ADDR arc_frame_saved_pc PARAMS ((struct frame_info *));
+
+/* If the argument is on the stack, it will be here.
+ We cache this value in the frame info if we've already looked it up. */
+/* ??? Is the arg_pointer check necessary? */
+
+#define FRAME_ARGS_ADDRESS(fi) \
+ (((fi)->arg_pointer != -1) ? (fi)->arg_pointer : (fi)->frame)
+
+/* This is the same except it should return 0 when
+ it does not really know where the args are, rather than guessing.
+ This value is not cached since it is only used infrequently. */
+
+#define FRAME_LOCALS_ADDRESS(fi) ((fi)->frame)
+
+/* Set NUMARGS to the number of args passed to a frame.
+ Can return -1, meaning no way to tell. */
+
+#define FRAME_NUM_ARGS(numargs, fi) (numargs = -1)
+
+/* Return number of bytes at start of arglist that are not really args. */
+
+#define FRAME_ARGS_SKIP 0
+
+/* Produce the positions of the saved registers in a stack frame. */
+
+#define FRAME_FIND_SAVED_REGS(frame_info_addr, sr) \
+ frame_find_saved_regs (frame_info_addr, &sr)
+extern void frame_find_saved_regs(); /* See arc-tdep.c */
+
+
+/* Things needed for making calls to functions in the inferior process */
+#define PUSH_DUMMY_FRAME \
+ push_dummy_frame ()
+
+/* Discard from the stack the innermost frame, restoring all registers. */
+#define POP_FRAME \
+ pop_frame ()
+
+/* This sequence of words is the instructions bl xxxx, flag 1 */
+#define CALL_DUMMY { 0x28000000, 0x1fbe8001 }
+#define CALL_DUMMY_LENGTH 8
+
+/* Start execution at beginning of dummy */
+#define CALL_DUMMY_START_OFFSET 0
+
+/* Insert the specified number of args and function address
+ into a call sequence of the above form stored at 'dummyname'.*/
+#define FIX_CALL_DUMMY(dummyname, pc, fun, nargs, args, type, gcc_p) \
+{ \
+ int from, to, delta, loc; \
+ loc = (int)(read_register (SP_REGNUM) - CALL_DUMMY_LENGTH); \
+ from = loc + 4; \
+ to = (int)(fun); \
+ delta = (to - from) >> 2; \
+ *((char *)(dummyname) + 1) = (delta & 0x1); \
+ *((char *)(dummyname) + 2) = ((delta >> 1) & 0xff); \
+ *((char *)(dummyname) + 3) = ((delta >> 9) & 0xff); \
+ *((char *)(dummyname) + 4) = ((delta >> 17) & 0x7); \
+}
+
diff --git a/gdb/config/arm/arm.mh b/gdb/config/arm/arm.mh
new file mode 100644
index 00000000000..4fcf0de6951
--- /dev/null
+++ b/gdb/config/arm/arm.mh
@@ -0,0 +1,5 @@
+# Host: Acorn RISC machine running RISCiX (4.3bsd)
+XDEPFILES= infptrace.o inftarg.o fork-child.o arm-xdep.o arm-convert.o
+XM_FILE= xm-arm.h
+
+NAT_FILE= nm-arm.h
diff --git a/gdb/config/arm/arm.mt b/gdb/config/arm/arm.mt
new file mode 100644
index 00000000000..4933c46bcde
--- /dev/null
+++ b/gdb/config/arm/arm.mt
@@ -0,0 +1,6 @@
+# Target: Acorn RISC machine (ARM) with simulator
+TDEPFILES= arm-tdep.o remote-rdp.o
+TM_FILE= tm-arm.h
+
+SIM_OBS = remote-sim.o
+SIM = ../sim/arm/libsim.a
diff --git a/gdb/config/arm/nm-arm.h b/gdb/config/arm/nm-arm.h
new file mode 100644
index 00000000000..970a885363f
--- /dev/null
+++ b/gdb/config/arm/nm-arm.h
@@ -0,0 +1,27 @@
+/* Definitions to make GDB run on an ARM under RISCiX (4.3bsd).
+ Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* This is the amount to subtract from u.u_ar0
+ to get the offset in the core file of the register values. */
+
+#define KERNEL_U_ADDR (0x01000000 - (UPAGES * NBPG))
+
+/* Override copies of {fetch,store}_inferior_registers in infptrace.c. */
+#define FETCH_INFERIOR_REGISTERS
+#define HOST_BYTE_ORDER LITTLE_ENDIAN
diff --git a/gdb/config/arm/tm-arm.h b/gdb/config/arm/tm-arm.h
new file mode 100644
index 00000000000..b327ac381f2
--- /dev/null
+++ b/gdb/config/arm/tm-arm.h
@@ -0,0 +1,453 @@
+/* Definitions to make GDB target for an ARM
+ Copyright 1986, 1987, 1989, 1991, 1993, 1997, 1998 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifdef __STDC__ /* Forward decls for prototypes */
+struct type;
+struct value;
+#endif
+
+#define TARGET_BYTE_ORDER_SELECTABLE
+
+/* IEEE format floating point */
+
+#define IEEE_FLOAT
+
+/* FIXME: may need a floatformat_ieee_double_bigbyte_littleword format for
+ BIG_ENDIAN use. -fnf */
+
+#define TARGET_DOUBLE_FORMAT (target_byte_order == BIG_ENDIAN \
+ ? &floatformat_ieee_double_big \
+ : &floatformat_ieee_double_littlebyte_bigword)
+
+/* When reading symbols, we need to zap the low bit of the address, which
+ may be set to 1 for Thumb functions. */
+
+#define SMASH_TEXT_ADDRESS(addr) ((addr) &= ~0x1)
+
+/* Remove useless bits from addresses in a running program. */
+
+CORE_ADDR arm_addr_bits_remove PARAMS ((CORE_ADDR));
+
+#define ADDR_BITS_REMOVE(val) (arm_addr_bits_remove (val))
+
+/* 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. */
+
+extern CORE_ADDR arm_skip_prologue PARAMS ((CORE_ADDR pc));
+
+#define SKIP_PROLOGUE(pc) { pc = arm_skip_prologue (pc); }
+
+/* Immediately after a function call, return the saved pc.
+ Can't always go through the frames for this because on some machines
+ the new frame is not set up until the new function executes
+ some instructions. */
+
+#define SAVED_PC_AFTER_CALL(frame) arm_saved_pc_after_call (frame)
+struct frame_info;
+extern CORE_ADDR arm_saved_pc_after_call PARAMS ((struct frame_info *));
+
+/* I don't know the real values for these. */
+#define TARGET_UPAGES UPAGES
+#define TARGET_NBPG NBPG
+
+/* Address of end of stack space. */
+
+#define STACK_END_ADDR (0x01000000 - (TARGET_UPAGES * TARGET_NBPG))
+
+/* Stack grows downward. */
+
+#define INNER_THAN(lhs,rhs) ((lhs) < (rhs))
+
+/* !!!! if we're using RDP, then we're inserting breakpoints and storing
+ their handles instread of what was in memory. It is nice that
+ this is the same size as a handle - otherwise remote-rdp will
+ have to change. */
+
+/* BREAKPOINT_FROM_PC uses the program counter value to determine whether a
+ 16- or 32-bit breakpoint should be used. It returns a pointer
+ to a string of bytes that encode a breakpoint instruction, stores
+ the length of the string to *lenptr, and adjusts the pc (if necessary) to
+ point to the actual memory location where the breakpoint should be
+ inserted. */
+
+extern breakpoint_from_pc_fn arm_breakpoint_from_pc;
+#define BREAKPOINT_FROM_PC(pcptr, lenptr) arm_breakpoint_from_pc (pcptr, lenptr)
+
+/* Amount PC must be decremented by after a breakpoint.
+ This is often the number of bytes in BREAKPOINT
+ but not always. */
+
+#define DECR_PC_AFTER_BREAK 0
+
+/* code to execute to print interesting information about the
+ * floating point processor (if any)
+ * No need to define if there is nothing to do.
+ */
+#define FLOAT_INFO { arm_float_info (); }
+
+/* Say how long (ordinary) registers are. This is a piece of bogosity
+ used in push_word and a few other places; REGISTER_RAW_SIZE is the
+ real way to know how big a register is. */
+
+#define REGISTER_SIZE 4
+
+/* Number of machine registers */
+
+/* Note: I make a fake copy of the pc in register 25 (calling it ps) so
+ that I can clear the status bits from pc (register 15) */
+
+#define NUM_REGS 26
+
+/* An array of names of registers. */
+
+extern char **arm_register_names;
+#define REGISTER_NAME(i) arm_register_names[i]
+
+/* Register numbers of various important registers.
+ Note that some of these values are "real" register numbers,
+ and correspond to the general registers of the machine,
+ and some are "phony" register numbers which are too large
+ to be actual register numbers as far as the user is concerned
+ but do serve to get the desired values when passed to read_register. */
+
+#define A1_REGNUM 0 /* first integer-like argument */
+#define A4_REGNUM 3 /* last integer-like argument */
+#define AP_REGNUM 11
+#define FP_REGNUM 11 /* Contains address of executing stack frame */
+#define SP_REGNUM 13 /* Contains address of top of stack */
+#define LR_REGNUM 14 /* address to return to from a function call */
+#define PC_REGNUM 15 /* Contains program counter */
+#define F0_REGNUM 16 /* first floating point register */
+#define F3_REGNUM 19 /* last floating point argument register */
+#define F7_REGNUM 23 /* last floating point register */
+#define FPS_REGNUM 24 /* floating point status register */
+#define PS_REGNUM 25 /* Contains processor status */
+
+#define THUMB_FP_REGNUM 7 /* R7 is frame register on Thumb */
+
+#define ARM_NUM_ARG_REGS 4
+#define ARM_LAST_ARG_REGNUM A4_REGNUM
+#define ARM_NUM_FP_ARG_REGS 4
+#define ARM_LAST_FP_ARG_REGNUM F3_REGNUM
+
+/* Instruction condition field values. */
+#define INST_EQ 0x0
+#define INST_NE 0x1
+#define INST_CS 0x2
+#define INST_CC 0x3
+#define INST_MI 0x4
+#define INST_PL 0x5
+#define INST_VS 0x6
+#define INST_VC 0x7
+#define INST_HI 0x8
+#define INST_LS 0x9
+#define INST_GE 0xa
+#define INST_LT 0xb
+#define INST_GT 0xc
+#define INST_LE 0xd
+#define INST_AL 0xe
+#define INST_NV 0xf
+
+#define FLAG_N 0x80000000
+#define FLAG_Z 0x40000000
+#define FLAG_C 0x20000000
+#define FLAG_V 0x10000000
+
+
+
+/* Total amount of space needed to store our copies of the machine's
+ register state, the array `registers'. */
+#define REGISTER_BYTES (16*4 + 12*8 + 4 + 4)
+
+/* Index within `registers' of the first byte of the space for
+ register N. */
+
+#define REGISTER_BYTE(N) (((N) < F0_REGNUM) ? (N)*4 : \
+ (((N) < PS_REGNUM) ? 16*4 + ((N) - 16)*12 : \
+ 16*4 + 8*12 + ((N) - FPS_REGNUM) * 4))
+
+/* Number of bytes of storage in the actual machine representation
+ for register N. On the vax, all regs are 4 bytes. */
+
+#define REGISTER_RAW_SIZE(N) (((N) < F0_REGNUM || (N) >= FPS_REGNUM) ? 4 : 12)
+
+/* Number of bytes of storage in the program's representation
+ for register N. On the vax, all regs are 4 bytes. */
+
+#define REGISTER_VIRTUAL_SIZE(N) (((N) < F0_REGNUM || (N) >= FPS_REGNUM) ? 4 : 8)
+
+/* Largest value REGISTER_RAW_SIZE can have. */
+
+#define MAX_REGISTER_RAW_SIZE 12
+
+/* Largest value REGISTER_VIRTUAL_SIZE can have. */
+
+#define MAX_REGISTER_VIRTUAL_SIZE 8
+
+/* Nonzero if register N requires conversion
+ from raw format to virtual format. */
+#define REGISTER_CONVERTIBLE(N) ((unsigned)(N) - F0_REGNUM < 8)
+
+/* Convert data from raw format for register REGNUM in buffer FROM
+ to virtual format with type TYPE in buffer TO. */
+
+#define REGISTER_CONVERT_TO_VIRTUAL(REGNUM,TYPE,FROM,TO) \
+{ \
+ double val; \
+ convert_from_extended ((FROM), & val); \
+ store_floating ((TO), TYPE_LENGTH (TYPE), val); \
+}
+
+/* Convert data from virtual format with type TYPE in buffer FROM
+ to raw format for register REGNUM in buffer TO. */
+
+#define REGISTER_CONVERT_TO_RAW(TYPE,REGNUM,FROM,TO) \
+{ \
+ double val = extract_floating ((FROM), TYPE_LENGTH (TYPE)); \
+ convert_to_extended (&val, (TO)); \
+}
+/* Return the GDB type object for the "standard" data type
+ of data in register N. */
+
+#define REGISTER_VIRTUAL_TYPE(N) \
+ (((unsigned)(N) - F0_REGNUM) < 8 ? builtin_type_double : builtin_type_int)
+
+/* The system C compiler uses a similar structure return convention to gcc */
+extern use_struct_convention_fn arm_use_struct_convention;
+#define USE_STRUCT_CONVENTION(gcc_p, type) arm_use_struct_convention (gcc_p, type)
+
+/* Store the address of the place in which to copy the structure the
+ subroutine will return. This is called from call_function. */
+
+#define STORE_STRUCT_RETURN(ADDR, SP) \
+ { write_register (0, (ADDR)); }
+
+/* Extract from an array REGBUF containing the (raw) register state
+ a function return value of type TYPE, and copy that, in virtual format,
+ into VALBUF. */
+
+#define EXTRACT_RETURN_VALUE(TYPE,REGBUF,VALBUF) \
+ if (TYPE_CODE (TYPE) == TYPE_CODE_FLT) \
+ convert_from_extended (REGBUF + REGISTER_BYTE (F0_REGNUM), VALBUF); \
+ else \
+ memcpy (VALBUF, REGBUF, TYPE_LENGTH (TYPE))
+
+/* Write into appropriate registers a function return value
+ of type TYPE, given in virtual format. */
+
+#define STORE_RETURN_VALUE(TYPE,VALBUF) \
+ if (TYPE_CODE (TYPE) == TYPE_CODE_FLT) { \
+ char _buf[MAX_REGISTER_RAW_SIZE]; \
+ convert_to_extended (VALBUF, _buf); \
+ write_register_bytes (REGISTER_BYTE (F0_REGNUM), _buf, MAX_REGISTER_RAW_SIZE); \
+ } else \
+ write_register_bytes (0, VALBUF, TYPE_LENGTH (TYPE))
+
+/* Extract from an array REGBUF containing the (raw) register state
+ the address in which a function should return its structure value,
+ as a CORE_ADDR (or an expression that can be used as one). */
+
+#define EXTRACT_STRUCT_VALUE_ADDRESS(REGBUF) (*(int *)(REGBUF))
+
+/* Specify that for the native compiler variables for a particular
+ lexical context are listed after the beginning LBRAC instead of
+ before in the executables list of symbols. */
+#define VARIABLES_INSIDE_BLOCK(desc, gcc_p) (!(gcc_p))
+
+
+/* Define other aspects of the stack frame.
+ We keep the offsets of all saved registers, 'cause we need 'em a lot!
+ We also keep the current size of the stack frame, and the offset of
+ the frame pointer from the stack pointer (for frameless functions, and
+ when we're still in the prologue of a function with a frame) */
+
+#define EXTRA_FRAME_INFO \
+ struct frame_saved_regs fsr; \
+ int framesize; \
+ int frameoffset; \
+ int framereg;
+
+extern void arm_init_extra_frame_info PARAMS ((struct frame_info *fi));
+#define INIT_EXTRA_FRAME_INFO(fromleaf, fi) arm_init_extra_frame_info (fi)
+
+/* Return the frame address. On ARM, it is R11; on Thumb it is R7. */
+CORE_ADDR arm_target_read_fp PARAMS ((void));
+#define TARGET_READ_FP() arm_target_read_fp ()
+
+/* 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.
+
+ However, if FRAME_CHAIN_VALID returns zero,
+ it means the given frame is the outermost one and has no caller. */
+
+#define FRAME_CHAIN(thisframe) (CORE_ADDR) arm_frame_chain (thisframe)
+extern CORE_ADDR arm_frame_chain PARAMS ((struct frame_info *));
+
+extern int arm_frame_chain_valid PARAMS ((CORE_ADDR, struct frame_info *));
+#define FRAME_CHAIN_VALID(chain, thisframe) arm_frame_chain_valid (chain, thisframe)
+
+/* Define other aspects of the stack frame. */
+
+/* A macro that tells us whether the function invocation represented
+ by FI does not have a frame on the stack associated with it. If it
+ does not, FRAMELESS is set to 1, else 0. */
+#define FRAMELESS_FUNCTION_INVOCATION(FI, FRAMELESS) \
+{ \
+ CORE_ADDR func_start, after_prologue; \
+ func_start = (get_pc_function_start ((FI)->pc) + \
+ FUNCTION_START_OFFSET); \
+ after_prologue = func_start; \
+ SKIP_PROLOGUE (after_prologue); \
+ (FRAMELESS) = (after_prologue == func_start); \
+}
+
+/* Saved Pc. */
+
+#define FRAME_SAVED_PC(FRAME) arm_frame_saved_pc (FRAME)
+extern CORE_ADDR arm_frame_saved_pc PARAMS ((struct frame_info *));
+
+#define FRAME_ARGS_ADDRESS(fi) (fi->frame)
+
+#define FRAME_LOCALS_ADDRESS(fi) ((fi)->frame)
+
+/* Return number of args passed to a frame.
+ Can return -1, meaning no way to tell. */
+
+#define FRAME_NUM_ARGS(numargs, fi) (numargs = -1)
+
+/* Return number of bytes at start of arglist that are not really args. */
+
+#define FRAME_ARGS_SKIP 0
+
+/* Put here the code to store, into a struct frame_saved_regs,
+ the addresses of the saved registers of frame described by FRAME_INFO.
+ This includes special registers such as pc and fp saved in special
+ ways in the stack frame. sp is even more special:
+ the address we return for it IS the sp for the next frame. */
+
+struct frame_saved_regs;
+struct frame_info;
+void frame_find_saved_regs PARAMS((struct frame_info *fi,
+ struct frame_saved_regs *fsr));
+
+#define FRAME_FIND_SAVED_REGS(frame_info, frame_saved_regs) \
+ arm_frame_find_saved_regs (frame_info, &(frame_saved_regs));
+
+
+/* Things needed for making the inferior call functions. */
+
+#define PUSH_ARGUMENTS(nargs, args, sp, struct_return, struct_addr) \
+ sp = arm_push_arguments ((nargs), (args), (sp), (struct_return), (struct_addr))
+extern CORE_ADDR
+arm_push_arguments PARAMS ((int, struct value **, CORE_ADDR, int, CORE_ADDR));
+
+/* Push an empty stack frame, to record the current PC, etc. */
+
+void arm_push_dummy_frame PARAMS ((void));
+
+#define PUSH_DUMMY_FRAME arm_push_dummy_frame ()
+
+/* Discard from the stack the innermost frame, restoring all registers. */
+
+void arm_pop_frame PARAMS ((void));
+
+#define POP_FRAME arm_pop_frame ()
+
+/* This sequence of words is the instructions
+
+ mov lr,pc
+ mov pc,r4
+ illegal
+
+ Note this is 12 bytes. */
+
+#define CALL_DUMMY {0xe1a0e00f, 0xe1a0f004, 0xE7FFDEFE}
+
+#define CALL_DUMMY_START_OFFSET 0 /* Start execution at beginning of dummy */
+
+#define CALL_DUMMY_BREAKPOINT_OFFSET arm_call_dummy_breakpoint_offset()
+extern int arm_call_dummy_breakpoint_offset PARAMS ((void));
+
+/* Insert the specified number of args and function address
+ into a call sequence of the above form stored at DUMMYNAME. */
+
+#define FIX_CALL_DUMMY(dummyname, pc, fun, nargs, args, type, gcc_p) \
+ arm_fix_call_dummy (dummyname, pc, fun, nargs, args, type, gcc_p)
+
+void arm_fix_call_dummy PARAMS ((char *dummy, CORE_ADDR pc, CORE_ADDR fun,
+ int nargs, struct value **args,
+ struct type *type, int gcc_p));
+
+CORE_ADDR arm_get_next_pc PARAMS ((CORE_ADDR));
+
+/* Functions for dealing with Thumb call thunks. */
+#define IN_SOLIB_CALL_TRAMPOLINE(pc, name) arm_in_call_stub (pc, name)
+#define SKIP_TRAMPOLINE_CODE(pc) arm_skip_stub (pc)
+extern int arm_in_call_stub PARAMS ((CORE_ADDR pc, char *name));
+extern CORE_ADDR arm_skip_stub PARAMS ((CORE_ADDR pc));
+
+/* Function to determine whether MEMADDR is in a Thumb function. */
+extern int arm_pc_is_thumb PARAMS ((bfd_vma memaddr));
+
+/* Function to determine whether MEMADDR is in a call dummy called from
+ a Thumb function. */
+extern int arm_pc_is_thumb_dummy PARAMS ((bfd_vma memaddr));
+
+/* Macros for setting and testing a bit in a minimal symbol that
+ marks it as Thumb function. The MSB of the minimal symbol's
+ "info" field is used for this purpose. This field is already
+ being used to store the symbol size, so the assumption is
+ that the symbol size cannot exceed 2^31.
+
+ COFF_MAKE_MSYMBOL_SPECIAL
+ ELF_MAKE_MSYMBOL_SPECIAL tests whether the COFF or ELF symbol corresponds
+ to a thumb function, and sets a "special" bit in a
+ minimal symbol to indicate that it does
+ MSYMBOL_SET_SPECIAL actually sets the "special" bit
+ MSYMBOL_IS_SPECIAL tests the "special" bit in a minimal symbol
+ MSYMBOL_SIZE returns the size of the minimal symbol, i.e.
+ the "info" field with the "special" bit masked out
+*/
+
+extern int coff_sym_is_thumb(int val);
+#define MSYMBOL_SET_SPECIAL(msym) \
+ MSYMBOL_INFO (msym) = (char *) (((long) MSYMBOL_INFO (msym)) | 0x80000000)
+#define MSYMBOL_IS_SPECIAL(msym) \
+ (((long) MSYMBOL_INFO (msym) & 0x80000000) != 0)
+#define MSYMBOL_SIZE(msym) \
+ ((long) MSYMBOL_INFO (msym) & 0x7fffffff)
+
+/* Thumb symbol are of type STT_LOPROC, (synonymous with STT_ARM_TFUNC) */
+#define ELF_MAKE_MSYMBOL_SPECIAL(sym,msym) \
+ { if(ELF_ST_TYPE(((elf_symbol_type *)(sym))->internal_elf_sym.st_info) == STT_LOPROC) \
+ MSYMBOL_SET_SPECIAL(msym); }
+
+#define COFF_MAKE_MSYMBOL_SPECIAL(val,msym) \
+ { if(coff_sym_is_thumb(val)) MSYMBOL_SET_SPECIAL(msym); }
+
+#undef IN_SIGTRAMP
+#define IN_SIGTRAMP(pc, name) 0
diff --git a/gdb/config/arm/xm-arm.h b/gdb/config/arm/xm-arm.h
new file mode 100644
index 00000000000..34c0bd376b5
--- /dev/null
+++ b/gdb/config/arm/xm-arm.h
@@ -0,0 +1,76 @@
+/* Definitions to make GDB run on an ARM under RISCiX (4.3bsd).
+ Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define HOST_BYTE_ORDER LITTLE_ENDIAN
+
+
+#if 0
+/* Interface definitions for kernel debugger KDB. */
+
+/* Map machine fault codes into signal numbers.
+ First subtract 0, divide by 4, then index in a table.
+ Faults for which the entry in this table is 0
+ are not handled by KDB; the program's own trap handler
+ gets to handle then. */
+
+#define FAULT_CODE_ORIGIN 0
+#define FAULT_CODE_UNITS 4
+#define FAULT_TABLE \
+{ 0, SIGKILL, SIGSEGV, 0, 0, 0, 0, 0, \
+ 0, 0, SIGTRAP, SIGTRAP, 0, 0, 0, 0, \
+ 0, 0, 0, 0, 0, 0, 0, 0}
+
+/* Start running with a stack stretching from BEG to END.
+ BEG and END should be symbols meaningful to the assembler.
+ This is used only for kdb. */
+
+#define INIT_STACK(beg, end) \
+{ asm (".globl end"); \
+ asm ("movl $ end, sp"); \
+ asm ("clrl fp"); }
+
+/* Push the frame pointer register on the stack. */
+#define PUSH_FRAME_PTR \
+ asm ("pushl fp");
+
+/* Copy the top-of-stack to the frame pointer register. */
+#define POP_FRAME_PTR \
+ asm ("movl (sp), fp");
+
+/* After KDB is entered by a fault, push all registers
+ that GDB thinks about (all NUM_REGS of them),
+ so that they appear in order of ascending GDB register number.
+ The fault code will be on the stack beyond the last register. */
+
+#define PUSH_REGISTERS \
+{ asm ("pushl 8(sp)"); \
+ asm ("pushl 8(sp)"); \
+ asm ("pushal 0x14(sp)"); \
+ asm ("pushr $037777"); }
+
+/* Assuming the registers (including processor status) have been
+ pushed on the stack in order of ascending GDB register number,
+ restore them and return to the address in the saved PC register. */
+
+#define POP_REGISTERS \
+{ asm ("popr $037777"); \
+ asm ("subl2 $8,(sp)"); \
+ asm ("movl (sp),sp"); \
+ asm ("rei"); }
+#endif /* 0 */
diff --git a/gdb/config/convex/Convex.notes b/gdb/config/convex/Convex.notes
new file mode 100644
index 00000000000..28d336bfed8
--- /dev/null
+++ b/gdb/config/convex/Convex.notes
@@ -0,0 +1,163 @@
+
+@node Convex,,, Top
+@appendix Convex-specific info
+@cindex Convex notes
+
+Scalar registers are 64 bits long, which is a pain since
+left half of an S register frequently contains noise.
+Therefore there are two ways to obtain the value of an S register.
+
+@table @kbd
+@item $s0
+returns the low half of the register as an int
+
+@item $S0
+returns the whole register as a long long
+@end table
+
+You can print the value in floating point by using @samp{p/f $s0} or @samp{p/f $S0}
+to print a single or double precision value.
+
+@cindex vector registers
+Vector registers are handled similarly, with @samp{$V0} denoting the whole
+64-bit register and @kbd{$v0} denoting the 32-bit low half; @samp{p/f $v0}
+or @samp{p/f $V0} can be used to examine the register in floating point.
+The length of the vector registers is taken from @samp{$vl}.
+
+Individual elements of a vector register are denoted in the obvious way;
+@samp{print $v3[9]} prints the tenth element of register @kbd{v3}, and
+@samp{set $v3[9] = 1234} alters it.
+
+@kbd{$vl} and @kbd{$vs} are int, and @kbd{$vm} is an int vector.
+Elements of @kbd{$vm} can't be assigned to.
+
+@cindex communication registers
+@kindex info comm-registers
+Communication registers have names @kbd{$C0 .. $C63}, with @kbd{$c0 .. $c63}
+denoting the low-order halves. @samp{info comm-registers} will print them
+all out, and tell which are locked. (A communication register is
+locked when a value is sent to it, and unlocked when the value is
+received.) Communication registers are, of course, global to all
+threads, so it does not matter what the currently selected thread is.
+@samp{info comm-reg @var{name}} prints just that one communication
+register; @samp{name} may also be a communication register number
+@samp{nn} or @samp{0xnn}.
+@samp{info comm-reg @var{address}} prints the contents of the resource
+structure at that address.
+
+@kindex info psw
+The command @samp{info psw} prints the processor status word @kbd{$ps}
+bit by bit.
+
+@kindex set base
+GDB normally prints all integers in base 10, but the leading
+@kbd{0x80000000} of pointers is intolerable in decimal, so the default
+output radix has been changed to try to print addresses appropriately.
+The @samp{set base} command can be used to change this.
+
+@table @code
+@item set base 10
+Integer values always print in decimal.
+
+@item set base 16
+Integer values always print in hex.
+
+@item set base
+Go back to the initial state, which prints integer values in hex if they
+look like pointers (specifically, if they start with 0x8 or 0xf in the
+stack), otherwise in decimal.
+@end table
+
+@kindex set pipeline
+When an exception such as a bus error or overflow happens, usually the PC
+is several instructions ahead by the time the exception is detected.
+The @samp{set pipe} command will disable this.
+
+@table @code
+@item set pipeline off
+Forces serial execution of instructions; no vector chaining and no
+scalar instruction overlap. With this, exceptions are detected with
+the PC pointing to the instruction after the one in error.
+
+@item set pipeline on
+Returns to normal, fast, execution. This is the default.
+@end table
+
+@cindex parallel
+In a parallel program, multiple threads may be executing, each
+with its own registers, stack, and local memory. When one of them
+hits a breakpoint, that thread is selected. Other threads do
+not run while the thread is in the breakpoint.
+
+@kindex 1cont
+The selected thread can be single-stepped, given signals, and so
+on. Any other threads remain stopped. When a @samp{cont} command is given,
+all threads are resumed. To resume just the selected thread, use
+the command @samp{1cont}.
+
+@kindex thread
+The @samp{thread} command will show the active threads and the
+instruction they are about to execute. The selected thread is marked
+with an asterisk. The command @samp{thread @var{n}} will select thread @var{n},
+shifting the debugger's attention to it for single-stepping,
+registers, local memory, and so on.
+
+@kindex info threads
+The @samp{info threads} command will show what threads, if any, have
+invisibly hit breakpoints or signals and are waiting to be noticed.
+
+@kindex set parallel
+The @samp{set parallel} command controls how many threads can be active.
+
+@table @code
+@item set parallel off
+One thread. Requests by the program that other threads join in
+(spawn and pfork instructions) do not cause other threads to start up.
+This does the same thing as the @samp{limit concurrency 1} command.
+
+@item set parallel fixed
+All CPUs are assigned to your program whenever it runs. When it
+executes a pfork or spawn instruction, it begins parallel execution
+immediately. This does the same thing as the @samp{mpa -f} command.
+
+@item set parallel on
+One or more threads. Spawn and pfork cause CPUs to join in when and if
+they are free. This is the default. It is very good for system
+throughput, but not very good for finding bugs in parallel code. If you
+suspect a bug in parallel code, you probably want @samp{set parallel fixed.}
+@end table
+
+@subsection Limitations
+
+WARNING: Convex GDB evaluates expressions in long long, because S
+registers are 64 bits long. However, GDB expression semantics are not
+exactly C semantics. This is a bug, strictly speaking, but it's not one I
+know how to fix. If @samp{x} is a program variable of type int, then it
+is also type int to GDB, but @samp{x + 1} is long long, as is @samp{x + y}
+or any other expression requiring computation. So is the expression
+@samp{1}, or any other constant. You only really have to watch out for
+calls. The innocuous expression @samp{list_node (0x80001234)} has an
+argument of type long long. You must explicitly cast it to int.
+
+It is not possible to continue after an uncaught fatal signal by using
+@samp{signal 0}, @samp{return}, @samp{jump}, or anything else. The difficulty is with
+Unix, not GDB.
+
+I have made no big effort to make such things as single-stepping a
+@kbd{join} instruction do something reasonable. If the program seems to
+hang when doing this, type @kbd{ctrl-c} and @samp{cont}, or use
+@samp{thread} to shift to a live thread. Single-stepping a @kbd{spawn}
+instruction apparently causes new threads to be born with their T bit set;
+this is not handled gracefully. When a thread has hit a breakpoint, other
+threads may have invisibly hit the breakpoint in the background; if you
+clear the breakpoint gdb will be surprised when threads seem to continue
+to stop at it. All of these situations produce spurious signal 5 traps;
+if this happens, just type @samp{cont}. If it becomes a nuisance, use
+@samp{handle 5 nostop}. (It will ask if you are sure. You are.)
+
+There is no way in GDB to store a float in a register, as with
+@kbd{set $s0 = 3.1416}. The identifier @kbd{$s0} denotes an integer,
+and like any C expression which assigns to an integer variable, the
+right-hand side is casted to type int. If you should need to do
+something like this, you can assign the value to @kbd{@{float@} ($sp-4)}
+and then do @kbd{set $s0 = $sp[-4]}. Same deal with @kbd{set $v0[69] = 6.9}.
diff --git a/gdb/config/convex/convex.mh b/gdb/config/convex/convex.mh
new file mode 100644
index 00000000000..35a121fdcf0
--- /dev/null
+++ b/gdb/config/convex/convex.mh
@@ -0,0 +1,3 @@
+# Host: Convex Unix (4bsd)
+XDEPFILES= convex-xdep.o
+XM_FILE= xm-convex.h
diff --git a/gdb/config/convex/convex.mt b/gdb/config/convex/convex.mt
new file mode 100644
index 00000000000..eefbeb3ee45
--- /dev/null
+++ b/gdb/config/convex/convex.mt
@@ -0,0 +1,3 @@
+# Target: Convex Unix (4bsd)
+TDEPFILES= convex-tdep.o
+TM_FILE= tm-convex.h
diff --git a/gdb/config/convex/tm-convex.h b/gdb/config/convex/tm-convex.h
new file mode 100644
index 00000000000..5eb9f6ed89e
--- /dev/null
+++ b/gdb/config/convex/tm-convex.h
@@ -0,0 +1,511 @@
+/* Definitions to make GDB run on Convex Unix (4bsd)
+ Copyright 1989, 1991, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define TARGET_BYTE_ORDER BIG_ENDIAN
+
+/* There is come problem with the debugging symbols generated by the
+ compiler such that the debugging symbol for the first line of a
+ function overlap with the function prologue. */
+#define PROLOGUE_FIRSTLINE_OVERLAP
+
+/* When convex pcc says CHAR or SHORT, it provides the correct address. */
+
+#define BELIEVE_PCC_PROMOTION 1
+
+/* Symbol types to ignore. */
+/* 0xc4 is N_MONPT. Use the numeric value for the benefit of people
+ with (rather) old OS's. */
+#define IGNORE_SYMBOL(TYPE) \
+ (((TYPE) & ~N_EXT) == N_TBSS \
+ || ((TYPE) & ~N_EXT) == N_TDATA \
+ || ((TYPE) & ~N_EXT) == 0xc4)
+
+/* Offset from address of function to start of its code.
+ Zero on most machines. */
+
+#define FUNCTION_START_OFFSET 0
+
+/* Advance PC across any function entry prologue instructions
+ to reach some "real" code.
+ Convex prolog is:
+ [sub.w #-,sp] in one of 3 possible sizes
+ [mov psw,- fc/vc main program prolog
+ and #-,- (skip it because the "mov psw" saves the
+ mov -,psw] T bit, so continue gets a surprise trap)
+ [and #-,sp] fc/vc O2 main program prolog
+ [ld.- -(ap),-] pcc/gcc register arg loads
+*/
+
+#define SKIP_PROLOGUE(pc) \
+{ int op, ix; \
+ op = read_memory_integer (pc, 2); \
+ if ((op & 0xffc7) == 0x5ac0) pc += 2; \
+ else if (op == 0x1580) pc += 4; \
+ else if (op == 0x15c0) pc += 6; \
+ if ((read_memory_integer (pc, 2) & 0xfff8) == 0x7c40 \
+ && (read_memory_integer (pc + 2, 2) & 0xfff8) == 0x1240 \
+ && (read_memory_integer (pc + 8, 2) & 0xfff8) == 0x7c48) \
+ pc += 10; \
+ if (read_memory_integer (pc, 2) == 0x1240) pc += 6; \
+ for (;;) { \
+ op = read_memory_integer (pc, 2); \
+ ix = (op >> 3) & 7; \
+ if (ix != 6) break; \
+ if ((op & 0xfcc0) == 0x3000) pc += 4; \
+ else if ((op & 0xfcc0) == 0x3040) pc += 6; \
+ else if ((op & 0xfcc0) == 0x2800) pc += 4; \
+ else if ((op & 0xfcc0) == 0x2840) pc += 6; \
+ else break;}}
+
+/* Immediately after a function call, return the saved pc.
+ (ignore frame and return *$sp so we can handle both calls and callq) */
+
+#define SAVED_PC_AFTER_CALL(frame) \
+ read_memory_integer (read_register (SP_REGNUM), 4)
+
+/* Address of end of stack space.
+ This is ((USRSTACK + 0xfff) & -0x1000)) from <convex/vmparam.h> but
+ that expression depends on the kernel version; instead, fetch a
+ page-zero pointer and get it from that. This will be invalid if
+ they ever change the way bkpt signals are delivered. */
+
+#define STACK_END_ADDR (0xfffff000 & *(unsigned *) 0x80000050)
+
+/* User-mode traps push an extended rtn block,
+ then fault with one of the following PCs */
+
+#define is_trace_pc(pc) ((unsigned) ((pc) - (*(int *) 0x80000040)) <= 4)
+#define is_arith_pc(pc) ((unsigned) ((pc) - (*(int *) 0x80000044)) <= 4)
+#define is_break_pc(pc) ((unsigned) ((pc) - (*(int *) 0x80000050)) <= 4)
+
+/* We need to manipulate trap bits in the psw */
+
+#define PSW_TRAP_FLAGS 0x69670000
+#define PSW_T_BIT 0x08000000
+#define PSW_S_BIT 0x01000000
+
+/* Stack grows downward. */
+
+#define INNER_THAN(lhs,rhs) ((lhs) < (rhs))
+
+/* Sequence of bytes for breakpoint instruction. (bkpt) */
+
+#define BREAKPOINT {0x7d,0x50}
+
+/* Amount PC must be decremented by after a breakpoint.
+ This is often the number of bytes in BREAKPOINT but not always.
+ (The break PC needs to be decremented by 2, but we do it when the
+ break frame is recognized and popped. That way gdb can tell breaks
+ from trace traps with certainty.) */
+
+#define DECR_PC_AFTER_BREAK 0
+
+/* Say how long (ordinary) registers are. This is a piece of bogosity
+ used in push_word and a few other places; REGISTER_RAW_SIZE is the
+ real way to know how big a register is. */
+
+#define REGISTER_SIZE 8
+
+/* Number of machine registers */
+
+#define NUM_REGS 26
+
+/* Initializer for an array of names of registers.
+ There should be NUM_REGS strings in this initializer. */
+
+#define REGISTER_NAMES {"pc","psw","fp","ap","a5","a4","a3","a2","a1","sp",\
+ "s7","s6","s5","s4","s3","s2","s1","s0",\
+ "S7","S6","S5","S4","S3","S2","S1","S0"}
+
+/* Register numbers of various important registers.
+ Note that some of these values are "real" register numbers,
+ and correspond to the general registers of the machine,
+ and some are "phony" register numbers which are too large
+ to be actual register numbers as far as the user is concerned
+ but do serve to get the desired values when passed to read_register. */
+
+#define S0_REGNUM 25 /* the real S regs */
+#define S7_REGNUM 18
+#define s0_REGNUM 17 /* low-order halves of S regs */
+#define s7_REGNUM 10
+#define SP_REGNUM 9 /* A regs */
+#define A1_REGNUM 8
+#define A5_REGNUM 4
+#define AP_REGNUM 3
+#define FP_REGNUM 2 /* Contains address of executing stack frame */
+#define PS_REGNUM 1 /* Contains processor status */
+#define PC_REGNUM 0 /* Contains program counter */
+
+/* convert dbx stab register number (from `r' declaration) to a gdb REGNUM */
+
+#define STAB_REG_TO_REGNUM(value) \
+ ((value) < 8 ? S0_REGNUM - (value) : SP_REGNUM - ((value) - 8))
+
+/* Vector register numbers, not handled as ordinary regs.
+ They are treated as convenience variables whose values are read
+ from the inferior when needed. */
+
+#define V0_REGNUM 0
+#define V7_REGNUM 7
+#define VM_REGNUM 8
+#define VS_REGNUM 9
+#define VL_REGNUM 10
+
+/* Total amount of space needed to store our copies of the machine's
+ register state, the array `registers'. */
+#define REGISTER_BYTES (4*10 + 8*8)
+
+/* Index within `registers' of the first byte of the space for
+ register N.
+ NB: must match structure of struct syscall_context for correct operation */
+
+#define REGISTER_BYTE(N) ((N) < s7_REGNUM ? 4*(N) : \
+ (N) < S7_REGNUM ? 44 + 8 * ((N)-s7_REGNUM) : \
+ 40 + 8 * ((N)-S7_REGNUM))
+
+/* Number of bytes of storage in the actual machine representation
+ for register N. */
+
+#define REGISTER_RAW_SIZE(N) ((N) < S7_REGNUM ? 4 : 8)
+
+/* Number of bytes of storage in the program's representation
+ for register N. */
+
+#define REGISTER_VIRTUAL_SIZE(N) REGISTER_RAW_SIZE(N)
+
+/* Largest value REGISTER_RAW_SIZE can have. */
+
+#define MAX_REGISTER_RAW_SIZE 8
+
+/* Largest value REGISTER_VIRTUAL_SIZE can have. */
+
+#define MAX_REGISTER_VIRTUAL_SIZE 8
+
+/* Return the GDB type object for the "standard" data type
+ of data in register N. */
+
+#define REGISTER_VIRTUAL_TYPE(N) \
+ ((N) < S7_REGNUM ? builtin_type_int : builtin_type_long_long)
+
+/* Store the address of the place in which to copy the structure the
+ subroutine will return. This is called from call_function. */
+
+#define STORE_STRUCT_RETURN(ADDR, SP) \
+ { write_register (A1_REGNUM, (ADDR)); }
+
+/* Extract from an array REGBUF containing the (raw) register state
+ a function return value of type TYPE, and copy that, in virtual format,
+ into VALBUF. */
+
+#define EXTRACT_RETURN_VALUE(TYPE,REGBUF,VALBUF) \
+ memcpy (VALBUF, &((char *) REGBUF) [REGISTER_BYTE (S0_REGNUM) + \
+ 8 - TYPE_LENGTH (TYPE)],\
+ TYPE_LENGTH (TYPE))
+
+/* Write into appropriate registers a function return value
+ of type TYPE, given in virtual format. */
+
+#define STORE_RETURN_VALUE(TYPE,VALBUF) \
+ write_register_bytes (REGISTER_BYTE (S0_REGNUM), VALBUF, 8)
+
+/* Extract from an array REGBUF containing the (raw) register state
+ the address in which a function should return its structure value,
+ as a CORE_ADDR (or an expression that can be used as one). */
+
+#define EXTRACT_STRUCT_VALUE_ADDRESS(REGBUF) \
+ (*(int *) & ((char *) REGBUF) [REGISTER_BYTE (s0_REGNUM)])
+
+/* Define trapped internal variable hooks to read and write
+ vector and communication registers. */
+
+#define IS_TRAPPED_INTERNALVAR is_trapped_internalvar
+#define VALUE_OF_TRAPPED_INTERNALVAR value_of_trapped_internalvar
+#define SET_TRAPPED_INTERNALVAR set_trapped_internalvar
+
+extern struct value *value_of_trapped_internalvar ();
+
+/* Hooks to read data from soff exec and core files,
+ and to describe the files. */
+
+#define FILES_INFO_HOOK print_maps
+
+/* Hook to call to print a typeless integer value, normally printed in decimal.
+ For convex, use hex instead if the number looks like an address. */
+
+#define PRINT_TYPELESS_INTEGER decout
+
+/* For the native compiler, variables for a particular lexical context
+ are listed after the beginning LBRAC instead of before in the
+ executables list of symbols. Using "gcc_compiled." to distinguish
+ between GCC and native compiler doesn't work on Convex because the
+ linker sorts the symbols to put "gcc_compiled." in the wrong place.
+ desc is nonzero for native, zero for gcc. */
+#define VARIABLES_INSIDE_BLOCK(desc, gcc_p) (desc != 0)
+
+/* Pcc occaisionally puts an SO where there should be an SOL. */
+#define PCC_SOL_BROKEN
+
+/* Describe the pointer in each stack frame to the previous stack frame
+ (its caller). */
+
+/* FRAME_CHAIN takes a frame_info with a frame's nominal address in fi->frame,
+ and produces the frame's chain-pointer. */
+
+/* (caller fp is saved at 8(fp)) */
+
+#define FRAME_CHAIN(fi) (read_memory_integer ((fi)->frame + 8, 4))
+
+/* Define other aspects of the stack frame. */
+
+/* We need the boundaries of the text in the exec file, as a kludge,
+ for FRAMELESS_FUNCTION_INVOCATION and CALL_DUMMY_LOCATION. */
+
+#define NEED_TEXT_START_END 1
+
+/* A macro that tells us whether the function invocation represented
+ by FI does not have a frame on the stack associated with it. If it
+ does not, FRAMELESS is set to 1, else 0.
+ On convex, check at the return address for `callq' -- if so, frameless,
+ otherwise, not. */
+
+#define FRAMELESS_FUNCTION_INVOCATION(FI, FRAMELESS) \
+{ \
+ extern CORE_ADDR text_start, text_end; \
+ CORE_ADDR call_addr = SAVED_PC_AFTER_CALL (FI); \
+ (FRAMELESS) = (call_addr >= text_start && call_addr < text_end \
+ && read_memory_integer (call_addr - 6, 1) == 0x22); \
+}
+
+#define FRAME_SAVED_PC(fi) (read_memory_integer ((fi)->frame, 4))
+
+#define FRAME_ARGS_ADDRESS(fi) (read_memory_integer ((fi)->frame + 12, 4))
+
+#define FRAME_LOCALS_ADDRESS(fi) (fi)->frame
+
+/* Return number of args passed to a frame.
+ Can return -1, meaning no way to tell. */
+
+#define FRAME_NUM_ARGS(numargs, fi) \
+{ numargs = read_memory_integer (FRAME_ARGS_ADDRESS (fi) - 4, 4); \
+ if (numargs < 0 || numargs >= 256) numargs = -1;}
+
+/* Return number of bytes at start of arglist that are not really args. */
+
+#define FRAME_ARGS_SKIP 0
+
+/* Put here the code to store, into a struct frame_saved_regs,
+ the addresses of the saved registers of frame described by FRAME_INFO.
+ This includes special registers such as pc and fp saved in special
+ ways in the stack frame. sp is even more special:
+ the address we return for it IS the sp for the next frame. */
+
+/* Normal (short) frames save only PC, FP, (callee's) AP. To reasonably
+ handle gcc and pcc register variables, scan the code following the
+ call for the instructions the compiler inserts to reload register
+ variables from stack slots and record the stack slots as the saved
+ locations of those registers. This will occasionally identify some
+ random load as a saved register; this is harmless. vc does not
+ declare its register allocation actions in the stabs. */
+
+#define FRAME_FIND_SAVED_REGS(frame_info, frame_saved_regs) \
+{ register int regnum; \
+ register int frame_length = /* 3 short, 2 long, 1 extended, 0 context */\
+ (read_memory_integer ((frame_info)->frame + 4, 4) >> 25) & 3; \
+ register CORE_ADDR frame_fp = \
+ read_memory_integer ((frame_info)->frame + 8, 4); \
+ register CORE_ADDR next_addr; \
+ memset (&frame_saved_regs, '\0', sizeof frame_saved_regs); \
+ (frame_saved_regs).regs[PC_REGNUM] = (frame_info)->frame + 0; \
+ (frame_saved_regs).regs[PS_REGNUM] = (frame_info)->frame + 4; \
+ (frame_saved_regs).regs[FP_REGNUM] = (frame_info)->frame + 8; \
+ (frame_saved_regs).regs[AP_REGNUM] = frame_fp + 12; \
+ next_addr = (frame_info)->frame + 12; \
+ if (frame_length < 3) \
+ for (regnum = A5_REGNUM; regnum < SP_REGNUM; ++regnum) \
+ (frame_saved_regs).regs[regnum] = (next_addr += 4); \
+ if (frame_length < 2) \
+ (frame_saved_regs).regs[SP_REGNUM] = (next_addr += 4); \
+ next_addr -= 4; \
+ if (frame_length < 3) \
+ for (regnum = S7_REGNUM; regnum < S0_REGNUM; ++regnum) \
+ (frame_saved_regs).regs[regnum] = (next_addr += 8); \
+ if (frame_length < 2) \
+ (frame_saved_regs).regs[S0_REGNUM] = (next_addr += 8); \
+ else \
+ (frame_saved_regs).regs[SP_REGNUM] = next_addr + 8; \
+ if (frame_length == 3) { \
+ CORE_ADDR pc = read_memory_integer ((frame_info)->frame, 4); \
+ int op, ix, disp; \
+ op = read_memory_integer (pc, 2); \
+ if ((op & 0xffc7) == 0x1480) pc += 4; /* add.w #-,sp */ \
+ else if ((op & 0xffc7) == 0x58c0) pc += 2; /* add.w #-,sp */ \
+ op = read_memory_integer (pc, 2); \
+ if ((op & 0xffc7) == 0x2a06) pc += 4; /* ld.w -,ap */ \
+ for (;;) { \
+ op = read_memory_integer (pc, 2); \
+ ix = (op >> 3) & 7; \
+ if ((op & 0xfcc0) == 0x2800) { /* ld.- -,ak */ \
+ regnum = SP_REGNUM - (op & 7); \
+ disp = read_memory_integer (pc + 2, 2); \
+ pc += 4;} \
+ else if ((op & 0xfcc0) == 0x2840) { /* ld.- -,ak */ \
+ regnum = SP_REGNUM - (op & 7); \
+ disp = read_memory_integer (pc + 2, 4); \
+ pc += 6;} \
+ if ((op & 0xfcc0) == 0x3000) { /* ld.- -,sk */ \
+ regnum = S0_REGNUM - (op & 7); \
+ disp = read_memory_integer (pc + 2, 2); \
+ pc += 4;} \
+ else if ((op & 0xfcc0) == 0x3040) { /* ld.- -,sk */ \
+ regnum = S0_REGNUM - (op & 7); \
+ disp = read_memory_integer (pc + 2, 4); \
+ pc += 6;} \
+ else if ((op & 0xff00) == 0x7100) { /* br crossjump */ \
+ pc += 2 * (char) op; \
+ continue;} \
+ else if (op == 0x0140) { /* jmp crossjump */ \
+ pc = read_memory_integer (pc + 2, 4); \
+ continue;} \
+ else break; \
+ if ((frame_saved_regs).regs[regnum]) \
+ break; \
+ if (ix == 7) disp += frame_fp; \
+ else if (ix == 6) disp += read_memory_integer (frame_fp + 12, 4); \
+ else if (ix != 0) break; \
+ (frame_saved_regs).regs[regnum] = \
+ disp - 8 + (1 << ((op >> 8) & 3)); \
+ if (regnum >= S7_REGNUM) \
+ (frame_saved_regs).regs[regnum - S0_REGNUM + s0_REGNUM] = \
+ disp - 4 + (1 << ((op >> 8) & 3)); \
+ } \
+ } \
+}
+
+/* Things needed for making the inferior call functions. */
+
+#define CALL_DUMMY_LOCATION BEFORE_TEXT_END
+
+/* Push an empty stack frame, to record the current PC, etc. */
+
+#define PUSH_DUMMY_FRAME \
+{ register CORE_ADDR sp = read_register (SP_REGNUM); \
+ register int regnum; \
+ char buf[8]; \
+ long word; \
+ for (regnum = S0_REGNUM; regnum >= S7_REGNUM; --regnum) { \
+ read_register_bytes (REGISTER_BYTE (regnum), buf, 8); \
+ sp = push_bytes (sp, buf, 8);} \
+ for (regnum = SP_REGNUM; regnum >= FP_REGNUM; --regnum) { \
+ word = read_register (regnum); \
+ sp = push_bytes (sp, &word, 4);} \
+ word = (read_register (PS_REGNUM) &~ (3<<25)) | (1<<25); \
+ sp = push_bytes (sp, &word, 4); \
+ word = read_register (PC_REGNUM); \
+ sp = push_bytes (sp, &word, 4); \
+ write_register (SP_REGNUM, sp); \
+ write_register (FP_REGNUM, sp); \
+ write_register (AP_REGNUM, sp);}
+
+/* Discard from the stack the innermost frame, restoring all registers. */
+
+#define POP_FRAME do {\
+ register CORE_ADDR fp = read_register (FP_REGNUM); \
+ register int regnum; \
+ register int frame_length = /* 3 short, 2 long, 1 extended, 0 context */ \
+ (read_memory_integer (fp + 4, 4) >> 25) & 3; \
+ char buf[8]; \
+ write_register (PC_REGNUM, read_memory_integer (fp, 4)); \
+ write_register (PS_REGNUM, read_memory_integer (fp += 4, 4)); \
+ write_register (FP_REGNUM, read_memory_integer (fp += 4, 4)); \
+ write_register (AP_REGNUM, read_memory_integer (fp += 4, 4)); \
+ if (frame_length < 3) \
+ for (regnum = A5_REGNUM; regnum < SP_REGNUM; ++regnum) \
+ write_register (regnum, read_memory_integer (fp += 4, 4)); \
+ if (frame_length < 2) \
+ write_register (SP_REGNUM, read_memory_integer (fp += 4, 4)); \
+ fp -= 4; \
+ if (frame_length < 3) \
+ for (regnum = S7_REGNUM; regnum < S0_REGNUM; ++regnum) { \
+ read_memory (fp += 8, buf, 8); \
+ write_register_bytes (REGISTER_BYTE (regnum), buf, 8);} \
+ if (frame_length < 2) { \
+ read_memory (fp += 8, buf, 8); \
+ write_register_bytes (REGISTER_BYTE (regnum), buf, 8);} \
+ else write_register (SP_REGNUM, fp + 8); \
+ flush_cached_frames (); \
+} while (0)
+
+/* This sequence of words is the instructions
+ mov sp,ap
+ pshea 69696969
+ calls 32323232
+ bkpt
+ Note this is 16 bytes. */
+
+#define CALL_DUMMY {0x50860d4069696969LL,0x2140323232327d50LL}
+
+#define CALL_DUMMY_LENGTH 16
+
+#define CALL_DUMMY_START_OFFSET 0
+
+/* Insert the specified number of args and function address
+ into a call sequence of the above form stored at DUMMYNAME. */
+
+#define FIX_CALL_DUMMY(dummyname, pc, fun, nargs, args, type, gcc_p) \
+{ *(int *)((char *) dummyname + 4) = nargs; \
+ *(int *)((char *) dummyname + 10) = fun; }
+
+/* Defs to read soff symbol tables, see dbxread.c */
+
+#define NUMBER_OF_SYMBOLS ((long) opthdr.o_nsyms)
+#define STRING_TABLE_OFFSET ((long) filehdr.h_strptr)
+#define SYMBOL_TABLE_OFFSET ((long) opthdr.o_symptr)
+#define STRING_TABLE_SIZE ((long) filehdr.h_strsiz)
+#define SIZE_OF_TEXT_SEGMENT ((long) txthdr.s_size)
+#define ENTRY_POINT ((long) opthdr.o_entry)
+
+#define READ_STRING_TABLE_SIZE(BUFFER) \
+ (BUFFER = STRING_TABLE_SIZE)
+
+#define DECLARE_FILE_HEADERS \
+ FILEHDR filehdr; \
+ OPTHDR opthdr; \
+ SCNHDR txthdr
+
+#define READ_FILE_HEADERS(DESC,NAME) \
+{ \
+ int n; \
+ val = myread (DESC, &filehdr, sizeof filehdr); \
+ if (val < 0) \
+ perror_with_name (NAME); \
+ if (! IS_SOFF_MAGIC (filehdr.h_magic)) \
+ error ("%s: not an executable file.", NAME); \
+ lseek (DESC, 0L, 0); \
+ if (myread (DESC, &filehdr, sizeof filehdr) < 0) \
+ perror_with_name (NAME); \
+ if (myread (DESC, &opthdr, filehdr.h_opthdr) <= 0) \
+ perror_with_name (NAME); \
+ for (n = 0; n < filehdr.h_nscns; n++) \
+ { \
+ if (myread (DESC, &txthdr, sizeof txthdr) < 0) \
+ perror_with_name (NAME); \
+ if ((txthdr.s_flags & S_TYPMASK) == S_TEXT) \
+ break; \
+ } \
+}
diff --git a/gdb/config/convex/xm-convex.h b/gdb/config/convex/xm-convex.h
new file mode 100644
index 00000000000..cfcee4e8a55
--- /dev/null
+++ b/gdb/config/convex/xm-convex.h
@@ -0,0 +1,35 @@
+/* Definitions to make GDB run on Convex Unix (4bsd)
+ Copyright 1989, 1991, 1992, 1996 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define HOST_BYTE_ORDER BIG_ENDIAN
+
+#define ATTACH_DETACH
+#define HAVE_WAIT_STRUCT
+#define NO_SIGINTERRUPT
+
+/* Use SIGCONT rather than SIGTSTP because convex Unix occasionally
+ turkeys SIGTSTP. I think. */
+
+#define STOP_SIGNAL SIGCONT
+
+/* Hook to call after creating inferior process. Now init_trace_fun
+ is in the same place. So re-write this to use the init_trace_fun
+ (making convex a debugging target). FIXME. */
+
+#define CREATE_INFERIOR_HOOK create_inferior_hook
diff --git a/gdb/config/d10v/d10v.mt b/gdb/config/d10v/d10v.mt
new file mode 100644
index 00000000000..eddb1b3f3e2
--- /dev/null
+++ b/gdb/config/d10v/d10v.mt
@@ -0,0 +1,5 @@
+# Target: Mitsubishi D10V processor
+TDEPFILES= d10v-tdep.o remote-d10v.o
+TM_FILE= tm-d10v.h
+SIM_OBS= remote-sim.o
+SIM= ../sim/d10v/libsim.a
diff --git a/gdb/config/d10v/tm-d10v.h b/gdb/config/d10v/tm-d10v.h
new file mode 100644
index 00000000000..ef75bc5307f
--- /dev/null
+++ b/gdb/config/d10v/tm-d10v.h
@@ -0,0 +1,337 @@
+/* Target-specific definition for the Mitsubishi D10V
+ Copyright (C) 1996 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Contributed by Martin Hunt, hunt@cygnus.com */
+
+#define GDB_TARGET_IS_D10V
+
+/* Define the bit, byte, and word ordering of the machine. */
+
+#define TARGET_BYTE_ORDER BIG_ENDIAN
+
+/* Offset from address of function to start of its code.
+ Zero on most machines. */
+
+#define FUNCTION_START_OFFSET 0
+
+/* these are the addresses the D10V-EVA board maps data */
+/* and instruction memory to. */
+
+#define DMEM_START 0x0000000
+#define IMEM_START 0x1000000
+#define STACK_START 0x0007ffe
+
+#ifdef __STDC__ /* Forward decls for prototypes */
+struct frame_info;
+struct frame_saved_regs;
+struct type;
+struct value;
+#endif
+
+/* Advance PC across any function entry prologue instructions
+ to reach some "real" code. */
+
+extern CORE_ADDR d10v_skip_prologue ();
+#define SKIP_PROLOGUE(ip) \
+ {(ip) = d10v_skip_prologue(ip);}
+
+
+/* Stack grows downward. */
+#define INNER_THAN(lhs,rhs) ((lhs) < (rhs))
+
+/* for a breakpoint, use "dbt || nop" */
+#define BREAKPOINT {0x2f, 0x90, 0x5e, 0x00}
+
+/* If your kernel resets the pc after the trap happens you may need to
+ define this before including this file. */
+#define DECR_PC_AFTER_BREAK 4
+
+#define REGISTER_NAMES \
+{ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", \
+ "r8", "r9", "r10","r11","r12", "r13", "r14","r15",\
+ "psw","bpsw","pc","bpc", "cr4", "cr5", "cr6", "rpt_c",\
+ "rpt_s","rpt_e", "mod_s", "mod_e", "cr12", "cr13", "iba", "cr15",\
+ "imap0","imap1","dmap","a0", "a1"\
+ }
+
+#define NUM_REGS 37
+
+/* 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 R0_REGNUM 0
+#define LR_REGNUM 13
+#define SP_REGNUM 15
+#define FP_REGNUM 11
+#define PC_REGNUM 18
+#define PSW_REGNUM 16
+#define IMAP0_REGNUM 32
+#define IMAP1_REGNUM 33
+#define DMAP_REGNUM 34
+#define A0_REGNUM 35
+
+/* Say how much memory is needed to store a copy of the register set */
+#define REGISTER_BYTES ((NUM_REGS-2)*2+16)
+
+/* Index within `registers' of the first byte of the space for
+ register N. */
+
+#define REGISTER_BYTE(N) \
+( ((N) > A0_REGNUM) ? ( ((N)-A0_REGNUM)*8 + A0_REGNUM*2 ) : ((N) * 2) )
+
+/* Number of bytes of storage in the actual machine representation
+ for register N. */
+
+#define REGISTER_RAW_SIZE(N) ( ((N) >= A0_REGNUM) ? 8 : 2 )
+
+/* Number of bytes of storage in the program's representation
+ for register N. */
+#define REGISTER_VIRTUAL_SIZE(N) ( ((N) >= A0_REGNUM) ? 8 : ( ((N) == PC_REGNUM || (N) == SP_REGNUM) ? 4 : 2 ))
+
+/* Largest value REGISTER_RAW_SIZE can have. */
+
+#define MAX_REGISTER_RAW_SIZE 8
+
+/* Largest value REGISTER_VIRTUAL_SIZE can have. */
+
+#define MAX_REGISTER_VIRTUAL_SIZE 8
+
+/* Return the GDB type object for the "standard" data type
+ of data in register N. */
+
+#define REGISTER_VIRTUAL_TYPE(N) \
+( ((N) < A0_REGNUM ) ? ((N) == PC_REGNUM || (N) == SP_REGNUM ? builtin_type_long : builtin_type_short) : builtin_type_long_long)
+
+
+/* convert $pc and $sp to/from virtual addresses */
+#define REGISTER_CONVERTIBLE(N) ((N) == PC_REGNUM || (N) == SP_REGNUM)
+#define REGISTER_CONVERT_TO_VIRTUAL(REGNUM,TYPE,FROM,TO) \
+{ \
+ ULONGEST x = extract_unsigned_integer ((FROM), REGISTER_RAW_SIZE (REGNUM)); \
+ if (REGNUM == PC_REGNUM) x = (x << 2) | IMEM_START; \
+ else x |= DMEM_START; \
+ store_unsigned_integer ((TO), TYPE_LENGTH(TYPE), x); \
+}
+#define REGISTER_CONVERT_TO_RAW(TYPE,REGNUM,FROM,TO) \
+{ \
+ ULONGEST x = extract_unsigned_integer ((FROM), TYPE_LENGTH(TYPE)); \
+ x &= 0x3ffff; \
+ if (REGNUM == PC_REGNUM) x >>= 2; \
+ store_unsigned_integer ((TO), 2, x); \
+}
+
+#define D10V_MAKE_DADDR(x) ((x) | DMEM_START)
+#define D10V_MAKE_IADDR(x) (((x) << 2) | IMEM_START)
+
+#define D10V_DADDR_P(X) (((X) & 0x3000000) == DMEM_START)
+#define D10V_IADDR_P(X) (((X) & 0x3000000) == IMEM_START)
+
+#define D10V_CONVERT_IADDR_TO_RAW(X) (((X) >> 2) & 0xffff)
+#define D10V_CONVERT_DADDR_TO_RAW(X) ((X) & 0xffff)
+
+#define ARG1_REGNUM R0_REGNUM
+#define ARGN_REGNUM 3
+#define RET1_REGNUM R0_REGNUM
+
+/* Store the address of the place in which to copy the structure the
+ subroutine will return. This is called from call_function.
+
+ We store structs through a pointer passed in the first Argument
+ register. */
+
+#define STORE_STRUCT_RETURN(ADDR, SP) \
+ { write_register (ARG1_REGNUM, (ADDR)); }
+
+
+/* Write into appropriate registers a function return value
+ of type TYPE, given in virtual format.
+
+ Things always get returned in RET1_REGNUM, RET2_REGNUM, ... */
+
+#define STORE_RETURN_VALUE(TYPE,VALBUF) \
+ write_register_bytes (REGISTER_BYTE(RET1_REGNUM), VALBUF, TYPE_LENGTH (TYPE))
+
+
+/* Extract from an array REGBUF containing the (raw) register state
+ the address in which a function should return its structure value,
+ as a CORE_ADDR (or an expression that can be used as one). */
+
+#define EXTRACT_STRUCT_VALUE_ADDRESS(REGBUF) \
+ (extract_address ((REGBUF) + REGISTER_BYTE (ARG1_REGNUM), REGISTER_RAW_SIZE (ARG1_REGNUM)) | DMEM_START)
+
+/* 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).
+
+ The d10v returns anything less than 8 bytes in size in
+ registers. */
+
+extern use_struct_convention_fn d10v_use_struct_convention;
+#define USE_STRUCT_CONVENTION(gcc_p, type) d10v_use_struct_convention (gcc_p, type)
+
+
+
+/* Define other aspects of the stack frame.
+ we keep a copy of the worked out return pc lying around, since it
+ is a useful bit of info */
+
+#define EXTRA_FRAME_INFO \
+ CORE_ADDR return_pc; \
+ int frameless; \
+ int size;
+
+#define INIT_EXTRA_FRAME_INFO(fromleaf, fi) \
+ d10v_init_extra_frame_info(fromleaf, fi)
+
+extern void d10v_init_extra_frame_info PARAMS (( int fromleaf, struct frame_info *fi ));
+
+/* A macro that tells us whether the function invocation represented
+ by FI does not have a frame on the stack associated with it. If it
+ does not, FRAMELESS is set to 1, else 0. */
+
+#define FRAMELESS_FUNCTION_INVOCATION(FI, FRAMELESS) \
+ (FRAMELESS) = frameless_look_for_prologue(FI)
+
+#define FRAME_CHAIN(FRAME) d10v_frame_chain(FRAME)
+extern int d10v_frame_chain_valid PARAMS ((CORE_ADDR, struct frame_info *));
+#define FRAME_CHAIN_VALID(chain, thisframe) d10v_frame_chain_valid (chain, thisframe)
+#define FRAME_SAVED_PC(FRAME) ((FRAME)->return_pc)
+#define FRAME_ARGS_ADDRESS(fi) (fi)->frame
+#define FRAME_LOCALS_ADDRESS(fi) (fi)->frame
+
+/* Immediately after a function call, return the saved pc. We can't */
+/* use frame->return_pc beause that is determined by reading R13 off the */
+/*stack and that may not be written yet. */
+
+#define SAVED_PC_AFTER_CALL(frame) ((read_register(LR_REGNUM) << 2) | IMEM_START)
+
+/* Set VAL to the number of args passed to frame described by FI.
+ Can set VAL to -1, meaning no way to tell. */
+/* We can't tell how many args there are */
+
+#define FRAME_NUM_ARGS(val,fi) (val = -1)
+
+/* Return number of bytes at start of arglist that are not really args. */
+
+#define FRAME_ARGS_SKIP 0
+
+
+/* Put here the code to store, into a struct frame_saved_regs,
+ the addresses of the saved registers of frame described by FRAME_INFO.
+ This includes special registers such as pc and fp saved in special
+ ways in the stack frame. sp is even more special:
+ the address we return for it IS the sp for the next frame. */
+
+#define FRAME_FIND_SAVED_REGS(frame_info, frame_saved_regs) \
+ d10v_frame_find_saved_regs(frame_info, &(frame_saved_regs))
+
+extern void d10v_frame_find_saved_regs PARAMS ((struct frame_info *, struct frame_saved_regs *));
+
+#define NAMES_HAVE_UNDERSCORE
+
+
+/* DUMMY FRAMES. Need these to support inferior function calls. They
+ work like this on D10V: First we set a breakpoint at 0 or __start.
+ Then we push all the registers onto the stack. Then put the
+ function arguments in the proper registers and set r13 to our
+ breakpoint address. Finally, the PC is set to the start of the
+ function being called (no JSR/BSR insn). When it hits the
+ breakpoint, clear the break point and pop the old register contents
+ off the stack. */
+
+extern void d10v_pop_frame PARAMS ((struct frame_info *frame));
+#define POP_FRAME generic_pop_current_frame (d10v_pop_frame)
+
+#define USE_GENERIC_DUMMY_FRAMES
+#define CALL_DUMMY {0}
+#define CALL_DUMMY_START_OFFSET (0)
+#define CALL_DUMMY_BREAKPOINT_OFFSET (0)
+#define CALL_DUMMY_LOCATION AT_ENTRY_POINT
+#define FIX_CALL_DUMMY(DUMMY, START, FUNADDR, NARGS, ARGS, TYPE, GCCP)
+#define CALL_DUMMY_ADDRESS() entry_point_address ()
+extern CORE_ADDR d10v_push_return_address PARAMS ((CORE_ADDR pc, CORE_ADDR sp));
+#define PUSH_RETURN_ADDRESS(PC, SP) d10v_push_return_address (PC, SP)
+
+#define PC_IN_CALL_DUMMY(PC, SP, FP) generic_pc_in_call_dummy (PC, SP)
+/* #define PC_IN_CALL_DUMMY(pc, sp, frame_address) ( pc == IMEM_START + 4 ) */
+
+#define PUSH_DUMMY_FRAME generic_push_dummy_frame ()
+
+/* override the default get_saved_register function with one that
+ takes account of generic CALL_DUMMY frames */
+#define GET_SAVED_REGISTER
+#define get_saved_register generic_get_saved_register
+
+#define PUSH_ARGUMENTS(nargs, args, sp, struct_return, struct_addr) \
+ sp = d10v_push_arguments((nargs), (args), (sp), (struct_return), (struct_addr))
+extern CORE_ADDR d10v_push_arguments PARAMS ((int, struct value **, CORE_ADDR, int, CORE_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) \
+d10v_extract_return_value(TYPE, REGBUF, VALBUF)
+ extern void
+d10v_extract_return_value PARAMS ((struct type *, char *, char *));
+
+
+#define REGISTER_SIZE 2
+
+#ifdef CC_HAS_LONG_LONG
+# define LONGEST long long
+#else
+# define LONGEST long
+#endif
+#define ULONGEST unsigned LONGEST
+
+void d10v_write_pc PARAMS ((CORE_ADDR val, int pid));
+CORE_ADDR d10v_read_pc PARAMS ((int pid));
+void d10v_write_sp PARAMS ((CORE_ADDR val));
+CORE_ADDR d10v_read_sp PARAMS ((void));
+void d10v_write_fp PARAMS ((CORE_ADDR val));
+CORE_ADDR d10v_read_fp PARAMS ((void));
+
+#define TARGET_READ_PC(pid) d10v_read_pc (pid)
+#define TARGET_WRITE_PC(val,pid) d10v_write_pc (val, pid)
+#define TARGET_READ_FP() d10v_read_fp ()
+#define TARGET_WRITE_FP(val) d10v_write_fp (val)
+#define TARGET_READ_SP() d10v_read_sp ()
+#define TARGET_WRITE_SP(val) d10v_write_sp (val)
+
+/* Number of bits in the appropriate type */
+#define TARGET_INT_BIT (2 * TARGET_CHAR_BIT)
+#define TARGET_PTR_BIT (4 * TARGET_CHAR_BIT)
+#define TARGET_DOUBLE_BIT (4 * TARGET_CHAR_BIT)
+#define TARGET_LONG_DOUBLE_BIT (8 * TARGET_CHAR_BIT)
+
+
+/* For the d10v when talking to the remote d10v board, GDB addresses
+ need to be translated into a format that the d10v rom monitor
+ understands. */
+
+int remote_d10v_translate_xfer_address PARAMS ((CORE_ADDR gdb_addr, int gdb_len, CORE_ADDR *rem_addr));
+#define REMOTE_TRANSLATE_XFER_ADDRESS(GDB_ADDR, GDB_LEN, REM_ADDR, REM_LEN) \
+(REM_LEN) = remote_d10v_translate_xfer_address ((GDB_ADDR), (GDB_LEN), &(REM_ADDR))
+
diff --git a/gdb/config/d30v/d30v.mt b/gdb/config/d30v/d30v.mt
new file mode 100644
index 00000000000..da0af2fd2eb
--- /dev/null
+++ b/gdb/config/d30v/d30v.mt
@@ -0,0 +1,5 @@
+# Target: Mitsubishi D30V processor
+TDEPFILES= d30v-tdep.o
+TM_FILE= tm-d30v.h
+SIM_OBS= remote-sim.o
+SIM= ../sim/d30v/libsim.a
diff --git a/gdb/config/d30v/tm-d30v.h b/gdb/config/d30v/tm-d30v.h
new file mode 100644
index 00000000000..7a69ca36d90
--- /dev/null
+++ b/gdb/config/d30v/tm-d30v.h
@@ -0,0 +1,325 @@
+/* Target-specific definition for the Mitsubishi D30V
+ Copyright (C) 1997 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef TM_D30V_H
+#define TM_D30V_H
+
+/* Define the bit, byte, and word ordering of the machine. */
+
+#define TARGET_BYTE_ORDER BIG_ENDIAN
+
+/* Offset from address of function to start of its code.
+ Zero on most machines. */
+
+#define FUNCTION_START_OFFSET 0
+
+/* these are the addresses the D30V-EVA board maps data */
+/* and instruction memory to. */
+
+#define DMEM_START 0x20000000
+#define IMEM_START 0x00000000 /* was 0x10000000 */
+#define STACK_START 0x20007ffe
+
+#ifdef __STDC__ /* Forward decls for prototypes */
+struct frame_info;
+struct frame_saved_regs;
+struct type;
+struct value;
+#endif
+
+/* Advance PC across any function entry prologue instructions
+ to reach some "real" code. */
+
+extern CORE_ADDR d30v_skip_prologue ();
+#define SKIP_PROLOGUE(ip) \
+ {(ip) = d30v_skip_prologue(ip);}
+
+
+/* Stack grows downward. */
+#define INNER_THAN(lhs,rhs) ((lhs) < (rhs))
+
+/* for a breakpoint, use "dbt || nop" */
+#define BREAKPOINT {0x00, 0xb0, 0x00, 0x00,\
+ 0x00, 0xf0, 0x00, 0x00}
+
+/* If your kernel resets the pc after the trap happens you may need to
+ define this before including this file. */
+#define DECR_PC_AFTER_BREAK 0
+
+#define REGISTER_NAMES \
+{ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", \
+ "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", \
+ "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", \
+ "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31", \
+ "r32", "r33", "r34", "r35", "r36", "r37", "r38", "r39", \
+ "r40", "r41", "r42", "r43", "r44", "r45", "r46", "r47", \
+ "r48", "r49", "r50", "r51", "r52", "r53", "r54", "r55", \
+ "r56", "r57", "r58", "r59", "r60", "r61", "r62", "r63", \
+ "spi", "spu", \
+ "psw", "bpsw", "pc", "bpc", "dpsw", "dpc", "cr6", "rpt_c", \
+ "rpt_s", "rpt_e", "mod_s", "mod_e", "cr12", "cr13", "iba", "eit_vb",\
+ "int_s", "int_m", "a0", "a1" \
+ }
+
+#define NUM_REGS 86
+
+/* 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 R0_REGNUM 0
+#define FP_REGNUM 61
+#define LR_REGNUM 62
+#define SP_REGNUM 63
+#define SPI_REGNUM 64 /* Interrupt stack pointer */
+#define SPU_REGNUM 65 /* User stack pointer */
+#define CREGS_START 66
+
+#define PSW_REGNUM (CREGS_START + 0) /* psw, bpsw, or dpsw??? */
+#define PSW_SM (((unsigned long)0x80000000) >> 0) /* Stack mode: 0/SPI */
+ /* 1/SPU */
+#define PSW_EA (((unsigned long)0x80000000) >> 2) /* Execution status */
+#define PSW_DB (((unsigned long)0x80000000) >> 3) /* Debug mode */
+#define PSW_DS (((unsigned long)0x80000000) >> 4) /* Debug EIT status */
+#define PSW_IE (((unsigned long)0x80000000) >> 5) /* Interrupt enable */
+#define PSW_RP (((unsigned long)0x80000000) >> 6) /* Repeat enable */
+#define PSW_MD (((unsigned long)0x80000000) >> 7) /* Modulo enable */
+#define PSW_F0 (((unsigned long)0x80000000) >> 17) /* F0 flag */
+#define PSW_F1 (((unsigned long)0x80000000) >> 19) /* F1 flag */
+#define PSW_F2 (((unsigned long)0x80000000) >> 21) /* F2 flag */
+#define PSW_F3 (((unsigned long)0x80000000) >> 23) /* F3 flag */
+#define PSW_S (((unsigned long)0x80000000) >> 25) /* Saturation flag */
+#define PSW_V (((unsigned long)0x80000000) >> 27) /* Overflow flag */
+#define PSW_VA (((unsigned long)0x80000000) >> 29) /* Accum. overflow */
+#define PSW_C (((unsigned long)0x80000000) >> 31) /* Carry/Borrow flag */
+
+#define BPSW_REGNUM (CREGS_START + 1) /* Backup PSW (on interrupt) */
+#define PC_REGNUM (CREGS_START + 2) /* pc, bpc, or dpc??? */
+#define BPC_REGNUM (CREGS_START + 3) /* Backup PC (on interrupt) */
+#define DPSW_REGNUM (CREGS_START + 4) /* Backup PSW (on debug trap) */
+#define DPC_REGNUM (CREGS_START + 5) /* Backup PC (on debug trap) */
+#define RPT_C_REGNUM (CREGS_START + 7) /* Loop count */
+#define RPT_S_REGNUM (CREGS_START + 8) /* Loop start address*/
+#define RPT_E_REGNUM (CREGS_START + 9) /* Loop end address */
+#define MOD_S_REGNUM (CREGS_START + 10)
+#define MOD_E_REGNUM (CREGS_START + 11)
+#define IBA_REGNUM (CREGS_START + 14) /* Instruction break address */
+#define EIT_VB_REGNUM (CREGS_START + 15) /* Vector base address */
+#define INT_S_REGNUM (CREGS_START + 16) /* Interrupt status */
+#define INT_M_REGNUM (CREGS_START + 17) /* Interrupt mask */
+#define A0_REGNUM 84
+#define A1_REGNUM 85
+
+/* Say how much memory is needed to store a copy of the register set */
+#define REGISTER_BYTES ((NUM_REGS - 2) * 4 + 2 * 8)
+
+/* Index within `registers' of the first byte of the space for
+ register N. */
+
+#define REGISTER_BYTE(N) \
+( ((N) >= A0_REGNUM) ? ( ((N) - A0_REGNUM) * 8 + A0_REGNUM * 4 ) : ((N) * 4) )
+
+/* Number of bytes of storage in the actual machine representation
+ for register N. */
+
+#define REGISTER_RAW_SIZE(N) ( ((N) >= A0_REGNUM) ? 8 : 4 )
+
+/* Number of bytes of storage in the program's representation
+ for register N. */
+#define REGISTER_VIRTUAL_SIZE(N) REGISTER_RAW_SIZE(N)
+
+/* Largest value REGISTER_RAW_SIZE can have. */
+
+#define MAX_REGISTER_RAW_SIZE 8
+
+/* Largest value REGISTER_VIRTUAL_SIZE can have. */
+
+#define MAX_REGISTER_VIRTUAL_SIZE 8
+
+/* Return the GDB type object for the "standard" data type
+ of data in register N. */
+
+#define REGISTER_VIRTUAL_TYPE(N) \
+( ((N) < A0_REGNUM ) ? builtin_type_long : builtin_type_long_long)
+
+/* Writing to r0 is a noop (not an error or exception or anything like
+ that, however). */
+
+#define CANNOT_STORE_REGISTER(regno) ((regno) == R0_REGNUM)
+
+void d30v_do_registers_info PARAMS ((int regnum, int fpregs));
+
+#define DO_REGISTERS_INFO d30v_do_registers_info
+
+/* Store the address of the place in which to copy the structure the
+ subroutine will return. This is called from call_function.
+
+ We store structs through a pointer passed in R2 */
+
+#define STORE_STRUCT_RETURN(ADDR, SP) \
+ { write_register (2, (ADDR)); }
+
+
+/* Write into appropriate registers a function return value
+ of type TYPE, given in virtual format.
+
+ Things always get returned in R2/R3 */
+
+#define STORE_RETURN_VALUE(TYPE,VALBUF) \
+ write_register_bytes (REGISTER_BYTE(2), VALBUF, TYPE_LENGTH (TYPE))
+
+
+/* Extract from an array REGBUF containing the (raw) register state
+ the address in which a function should return its structure value,
+ as a CORE_ADDR (or an expression that can be used as one). */
+#define EXTRACT_STRUCT_VALUE_ADDRESS(REGBUF) (((CORE_ADDR *)(REGBUF))[2])
+
+
+/* Define other aspects of the stack frame.
+ we keep a copy of the worked out return pc lying around, since it
+ is a useful bit of info */
+
+#define EXTRA_FRAME_INFO \
+ CORE_ADDR return_pc; \
+ CORE_ADDR dummy; \
+ int frameless; \
+ int size;
+
+#define INIT_EXTRA_FRAME_INFO(fromleaf, fi) \
+ d30v_init_extra_frame_info(fromleaf, fi)
+
+extern void d30v_init_extra_frame_info PARAMS (( int fromleaf, struct frame_info *fi ));
+
+/* A macro that tells us whether the function invocation represented
+ by FI does not have a frame on the stack associated with it. If it
+ does not, FRAMELESS is set to 1, else 0. */
+
+#define FRAMELESS_FUNCTION_INVOCATION(FI, FRAMELESS) \
+ (FRAMELESS) = frameless_look_for_prologue(FI)
+
+#define FRAME_CHAIN(FRAME) d30v_frame_chain(FRAME)
+extern int d30v_frame_chain_valid PARAMS ((CORE_ADDR, struct frame_info *));
+#define FRAME_CHAIN_VALID(chain, thisframe) d30v_frame_chain_valid (chain, thisframe)
+#define FRAME_SAVED_PC(FRAME) ((FRAME)->return_pc)
+#define FRAME_ARGS_ADDRESS(fi) (fi)->frame
+#define FRAME_LOCALS_ADDRESS(fi) (fi)->frame
+
+#define INIT_FRAME_PC_FIRST(fromleaf, prev) d30v_init_frame_pc(fromleaf, prev)
+#define INIT_FRAME_PC(fromleaf, prev) /* nada */
+
+/* Immediately after a function call, return the saved pc. We can't */
+/* use frame->return_pc beause that is determined by reading R62 off the */
+/* stack and that may not be written yet. */
+
+#define SAVED_PC_AFTER_CALL(frame) (read_register(LR_REGNUM))
+
+/* Set VAL to the number of args passed to frame described by FI.
+ Can set VAL to -1, meaning no way to tell. */
+/* We can't tell how many args there are */
+
+#define FRAME_NUM_ARGS(val,fi) (val = -1)
+
+/* Return number of bytes at start of arglist that are not really args. */
+
+#define FRAME_ARGS_SKIP 0
+
+
+/* Put here the code to store, into a struct frame_saved_regs,
+ the addresses of the saved registers of frame described by FRAME_INFO.
+ This includes special registers such as pc and fp saved in special
+ ways in the stack frame. sp is even more special:
+ the address we return for it IS the sp for the next frame. */
+
+#define FRAME_FIND_SAVED_REGS(frame_info, frame_saved_regs) \
+ d30v_frame_find_saved_regs(frame_info, &(frame_saved_regs))
+
+extern void d30v_frame_find_saved_regs PARAMS ((struct frame_info *, struct frame_saved_regs *));
+
+#define NAMES_HAVE_UNDERSCORE
+
+/* DUMMY FRAMES. Need these to support inferior function calls.
+ They work like this on D30V:
+ First we set a breakpoint at 0 or __start.
+ Then we push all the registers onto the stack.
+ Then put the function arguments in the proper registers and set r13
+ to our breakpoint address.
+ Finally call the function directly.
+ When it hits the breakpoint, clear the break point and pop the old
+ register contents off the stack. */
+
+#define CALL_DUMMY { 0 }
+#define PUSH_DUMMY_FRAME
+#define CALL_DUMMY_START_OFFSET 0
+#define CALL_DUMMY_LOCATION AT_ENTRY_POINT
+#define CALL_DUMMY_BREAKPOINT_OFFSET (0)
+
+extern CORE_ADDR d30v_call_dummy_address PARAMS ((void));
+#define CALL_DUMMY_ADDRESS() d30v_call_dummy_address()
+
+#define FIX_CALL_DUMMY(dummyname, pc, fun, nargs, args, type, gcc_p) \
+sp = d30v_fix_call_dummy (dummyname, pc, fun, nargs, args, type, gcc_p)
+
+#define PC_IN_CALL_DUMMY(pc, sp, frame_address) ( pc == IMEM_START + 4 )
+
+extern CORE_ADDR d30v_fix_call_dummy PARAMS ((char *, CORE_ADDR, CORE_ADDR,
+ int, struct value **,
+ struct type *, int));
+#define PUSH_ARGUMENTS(nargs, args, sp, struct_return, struct_addr) \
+ sp = d30v_push_arguments((nargs), (args), (sp), (struct_return), (struct_addr))
+extern CORE_ADDR d30v_push_arguments PARAMS ((int, struct value **, CORE_ADDR, int, CORE_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) \
+d30v_extract_return_value(TYPE, REGBUF, VALBUF)
+ extern void
+d30v_extract_return_value PARAMS ((struct type *, char *, char *));
+
+
+/* Discard from the stack the innermost frame,
+ restoring all saved registers. */
+#define POP_FRAME d30v_pop_frame();
+extern void d30v_pop_frame PARAMS((void));
+
+#define REGISTER_SIZE 4
+
+/* Need to handle SP special, as we need to select between spu and spi. */
+#if 0 /* XXX until the simulator is fixed */
+#define TARGET_READ_SP() ((read_register (PSW_REGNUM) & PSW_SM) \
+ ? read_register (SPU_REGNUM) \
+ : read_register (SPI_REGNUM))
+
+#define TARGET_WRITE_SP(val) ((read_register (PSW_REGNUM) & PSW_SM) \
+ ? write_register (SPU_REGNUM, (val)) \
+ : write_register (SPI_REGNUM, (val)))
+#endif
+
+#define STACK_ALIGN(len) (((len) + 7 ) & ~7)
+
+/* Turn this on to cause remote-sim.c to use sim_set/clear_breakpoint. */
+
+#define SIM_HAS_BREAKPOINTS
+
+#endif /* TM_D30V_H */
diff --git a/gdb/config/fr30/fr30.mt b/gdb/config/fr30/fr30.mt
new file mode 100644
index 00000000000..fac307ea01c
--- /dev/null
+++ b/gdb/config/fr30/fr30.mt
@@ -0,0 +1,5 @@
+# Target: Fujitsu FR30 processor
+TDEPFILES= fr30-tdep.o
+TM_FILE= tm-fr30.h
+SIM_OBS = remote-sim.o
+SIM = ../sim/fr30/libsim.a
diff --git a/gdb/config/fr30/tm-fr30.h b/gdb/config/fr30/tm-fr30.h
new file mode 100644
index 00000000000..ea32792dcc4
--- /dev/null
+++ b/gdb/config/fr30/tm-fr30.h
@@ -0,0 +1,232 @@
+/* Parameters for execution on a Fujitsu FR30 processor.
+
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define FR30_GENREGS 16
+#define FR30_DEDICATEDREGS 8
+#define FR30_REGSIZE 4 /* bytes */
+
+#define NUM_REGS (FR30_GENREGS + FR30_DEDICATEDREGS)
+#define REGISTER_BYTES ((FR30_GENREGS + FR30_DEDICATEDREGS)*FR30_REGSIZE)
+
+/* Index within `registers' of the first byte of the space for
+ register N. */
+#define REGISTER_BYTE(N) ((N) * FR30_REGSIZE)
+
+/* Initializer for an array of names of registers.
+ There should be NUM_REGS strings in this initializer. */
+#define REGISTER_NAMES \
+{ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", \
+ "r9", "r10", "r11", "r12", "r13", "r14", "r15", \
+ "pc", "ps", "tbr", "rp", "ssp", "usp", "mdh", "mdl" }
+
+/* Offset from address of function to start of its code.
+ Zero on most machines. */
+#define FUNCTION_START_OFFSET 0
+
+/* Amount PC must be decremented by after a breakpoint.
+ This is often the number of bytes in BREAKPOINT
+ but not always. */
+
+#define DECR_PC_AFTER_BREAK 0
+
+/* Stack grows downward. */
+
+#define INNER_THAN(lhs,rhs) ((lhs) < (rhs))
+
+#define TARGET_BYTE_ORDER BIG_ENDIAN
+
+#define R0_REGNUM 0
+#define R1_REGNUM 1
+#define R2_REGNUM 2
+#define R3_REGNUM 3
+#define R4_REGNUM 4
+#define R5_REGNUM 5
+#define R6_REGNUM 6
+#define R7_REGNUM 7
+#define R8_REGNUM 8
+#define R9_REGNUM 9
+#define R10_REGNUM 10
+#define R11_REGNUM 11
+#define R12_REGNUM 12
+#define R13_REGNUM 13
+#define FP_REGNUM 14 /* Frame pointer */
+#define SP_REGNUM 15 /* Stack pointer */
+#define PC_REGNUM 16 /* Program counter */
+#define RP_REGNUM 19 /* Return pointer */
+
+#define FIRST_ARGREG R4_REGNUM /* first arg (or struct ret val addr) */
+#define LAST_ARGREG R7_REGNUM /* fourth (or third arg) */
+#define RETVAL_REG R4_REGNUM /* return vaue */
+
+/* Say how long (ordinary) registers are. This is a piece of bogosity
+ used in push_word and a few other places; REGISTER_RAW_SIZE is the
+ real way to know how big a register is. */
+#define REGISTER_SIZE FR30_REGSIZE
+
+/* Number of bytes of storage in the actual machine representation
+ for register N. */
+#define REGISTER_RAW_SIZE(N) FR30_REGSIZE
+
+/* Largest value REGISTER_RAW_SIZE can have. */
+#define MAX_REGISTER_RAW_SIZE FR30_REGSIZE
+
+/* Number of bytes of storage in the program's representation
+ for register N. */
+#define REGISTER_VIRTUAL_SIZE(N) REGISTER_RAW_SIZE(N)
+
+/* Largest value REGISTER_VIRTUAL_SIZE can have. */
+#define MAX_REGISTER_VIRTUAL_SIZE FR30_REGSIZE
+
+extern void fr30_pop_frame PARAMS ((void));
+#define POP_FRAME fr30_pop_frame()
+
+#define USE_GENERIC_DUMMY_FRAMES
+#define CALL_DUMMY {0}
+#define CALL_DUMMY_START_OFFSET (0)
+#define CALL_DUMMY_BREAKPOINT_OFFSET (0)
+#define CALL_DUMMY_LOCATION AT_ENTRY_POINT
+#define FIX_CALL_DUMMY(DUMMY, START, FUNADDR, NARGS, ARGS, TYPE, GCCP)
+#define CALL_DUMMY_ADDRESS() entry_point_address ()
+#define PUSH_RETURN_ADDRESS(PC, SP) (write_register(RP_REGNUM, CALL_DUMMY_ADDRESS()), SP)
+#define PUSH_DUMMY_FRAME generic_push_dummy_frame ()
+
+/* Number of bytes at start of arglist that are not really args. */
+#define FRAME_ARGS_SKIP 0
+
+/* Return the GDB type object for the "standard" data type
+ of data in register N. */
+#define REGISTER_VIRTUAL_TYPE(REG) builtin_type_int
+
+/* 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) \
+ memcpy (VALBUF, REGBUF + REGISTER_BYTE(RETVAL_REG) + \
+ (TYPE_LENGTH(TYPE) < 4 ? 4 - TYPE_LENGTH(TYPE) : 0), 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) \
+ extract_address (REGBUF + REGISTER_BYTE (RETVAL_REG), \
+ REGISTER_RAW_SIZE (RETVAL_REG))
+
+#define STORE_STRUCT_RETURN(ADDR, SP) \
+ { write_register (RETVAL_REG, (ADDR)); }
+
+#define FRAME_ARGS_ADDRESS(fi) (fi->frame)
+#define FRAME_LOCALS_ADDRESS(fi) ((fi)->frame)
+
+/* Return number of args passed to a frame.
+ Can return -1, meaning no way to tell. */
+#define FRAME_NUM_ARGS(numargs, fi) (numargs = -1)
+
+#ifdef __STDC__ /* Forward decls for prototypes */
+struct frame_info;
+struct frame_saved_regs;
+struct type;
+struct value;
+#endif
+
+#define EXTRA_FRAME_INFO \
+ struct frame_saved_regs fsr; \
+ int framesize; \
+ int frameoffset; \
+ int framereg;
+
+extern CORE_ADDR fr30_frame_chain PARAMS ((struct frame_info *fi));
+#define FRAME_CHAIN(fi) fr30_frame_chain (fi)
+
+extern CORE_ADDR fr30_frame_saved_pc PARAMS ((struct frame_info *));
+#define FRAME_SAVED_PC(fi) (fr30_frame_saved_pc (fi))
+
+#define SAVED_PC_AFTER_CALL(fi) read_register (RP_REGNUM)
+
+extern CORE_ADDR fr30_skip_prologue PARAMS ((CORE_ADDR pc));
+#define SKIP_PROLOGUE(pc) pc = fr30_skip_prologue (pc)
+
+/* 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))
+
+/* 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(fi, regaddr) regaddr = fi->fsr
+
+/* Use INT #BREAKPOINT_INTNUM instruction for breakpoint */
+#define FR30_BREAKOP 0x1f /* opcode, type D instruction */
+#define BREAKPOINT_INTNUM 9 /* one of the reserved traps */
+#define BREAKPOINT {FR30_BREAKOP, BREAKPOINT_INTNUM}
+
+/* Define this for Wingdb */
+#define TARGET_FR30
+
+/* IEEE format floating point */
+#define IEEE_FLOAT
+
+/* Define other aspects of the stack frame. */
+
+/* A macro that tells us whether the function invocation represented
+ by FI does not have a frame on the stack associated with it. If it
+ does not, FRAMELESS is set to 1, else 0. */
+#define FRAMELESS_FUNCTION_INVOCATION(FI, FRAMELESS) \
+{ \
+ CORE_ADDR func_start, after_prologue; \
+ func_start = (get_pc_function_start ((FI)->pc) + \
+ FUNCTION_START_OFFSET); \
+ after_prologue = func_start; \
+ SKIP_PROLOGUE (after_prologue); \
+ (FRAMELESS) = (after_prologue == func_start); \
+}
+
+extern void fr30_init_extra_frame_info PARAMS ((struct frame_info *fi));
+#define INIT_EXTRA_FRAME_INFO(fromleaf, fi) fr30_init_extra_frame_info (fi)
+
+#define FRAME_CHAIN_VALID(FP, FI) generic_frame_chain_valid (FP, FI)
+
+extern CORE_ADDR
+fr30_push_arguments PARAMS ((int nargs, struct value **args, CORE_ADDR sp,
+ int struct_return,
+ CORE_ADDR struct_addr));
+#define PUSH_ARGUMENTS(NARGS, ARGS, SP, STRUCT_RETURN, STRUCT_ADDR) \
+ (SP) = fr30_push_arguments (NARGS, ARGS, SP, STRUCT_RETURN, STRUCT_ADDR)
+
+#define PC_IN_CALL_DUMMY(PC, SP, FP) generic_pc_in_call_dummy (PC, SP)
+
+/* Fujitsu's ABI requires all structs to be passed using a pointer.
+ That is obviously not very efficient, so I am leaving the definitions
+ to make gdb work with GCC style struct passing, in case we decide
+ to go for better performance, rather than for compatibility with
+ Fujitsu (just change STRUCT_ALWAYS_BY_ADDR to 0) */
+
+#define STRUCT_ALWAYS_BY_ADDR 1
+
+#if(STRUCT_ALWAYS_BY_ADDR)
+#define REG_STRUCT_HAS_ADDR(gcc_p,type) 1
+#else
+/* more standard GCC (optimized) */
+#define REG_STRUCT_HAS_ADDR(gcc_p,type) \
+ ((TYPE_LENGTH(type) > 4) && (TYPE_LENGTH(type) & 0x3))
+#endif
+/* alway return struct by value by input pointer */
+#define USE_STRUCT_CONVENTION(GCC_P, TYPE) 1
diff --git a/gdb/config/gould/np1.mh b/gdb/config/gould/np1.mh
new file mode 100644
index 00000000000..322f2078ac5
--- /dev/null
+++ b/gdb/config/gould/np1.mh
@@ -0,0 +1,3 @@
+# OBSOLETE # Host: Gould NP1
+# OBSOLETE XDEPFILES= infptrace.o inftarg.o fork-child.o gould-xdep.o
+# OBSOLETE XM_FILE= xm-np1.h
diff --git a/gdb/config/gould/np1.mt b/gdb/config/gould/np1.mt
new file mode 100644
index 00000000000..4ea2da5ab45
--- /dev/null
+++ b/gdb/config/gould/np1.mt
@@ -0,0 +1,3 @@
+# OBSOLETE # Target: Gould NP1
+# OBSOLETE TDEPFILES= gould-tdep.o
+# OBSOLETE TM_FILE= tm-np1.h
diff --git a/gdb/config/gould/pn.mh b/gdb/config/gould/pn.mh
new file mode 100644
index 00000000000..9d69f905d8d
--- /dev/null
+++ b/gdb/config/gould/pn.mh
@@ -0,0 +1,3 @@
+# OBSOLETE # Host: Gould Powernode
+# OBSOLETE XDEPFILES= infptrace.o inftarg.o fork-child.o corelow.o core-aout.o
+# OBSOLETE XM_FILE= xm-pn.h
diff --git a/gdb/config/gould/pn.mt b/gdb/config/gould/pn.mt
new file mode 100644
index 00000000000..7f73fc9f041
--- /dev/null
+++ b/gdb/config/gould/pn.mt
@@ -0,0 +1,3 @@
+# OBSOLETE # Target: Gould Powernode
+# OBSOLETE TDEPFILES= gould-tdep.o
+# OBSOLETE TM_FILE= tm-pn.h
diff --git a/gdb/config/gould/tm-np1.h b/gdb/config/gould/tm-np1.h
new file mode 100644
index 00000000000..7287155dd36
--- /dev/null
+++ b/gdb/config/gould/tm-np1.h
@@ -0,0 +1,490 @@
+/* OBSOLETE /* Parameters for targeting on a Gould NP1, for GDB, the GNU debugger. */
+/* OBSOLETE Copyright 1986, 1987, 1989, 1991, 1993 Free Software Foundation, Inc. */
+/* OBSOLETE */
+/* OBSOLETE This file is part of GDB. */
+/* OBSOLETE */
+/* OBSOLETE This program is free software; you can redistribute it and/or modify */
+/* OBSOLETE it under the terms of the GNU General Public License as published by */
+/* OBSOLETE the Free Software Foundation; either version 2 of the License, or */
+/* OBSOLETE (at your option) any later version. */
+/* OBSOLETE */
+/* OBSOLETE This program is distributed in the hope that it will be useful, */
+/* OBSOLETE but WITHOUT ANY WARRANTY; without even the implied warranty of */
+/* OBSOLETE MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
+/* OBSOLETE GNU General Public License for more details. */
+/* OBSOLETE */
+/* OBSOLETE You should have received a copy of the GNU General Public License */
+/* OBSOLETE along with this program; if not, write to the Free Software */
+/* OBSOLETE Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *x/ */
+/* OBSOLETE */
+/* OBSOLETE #define GOULD_NPL */
+/* OBSOLETE */
+/* OBSOLETE #define TARGET_BYTE_ORDER BIG_ENDIAN */
+/* OBSOLETE */
+/* OBSOLETE /* N_ENTRY appears in libraries on Gould machines. */
+/* OBSOLETE Don't know what 0xa4 is; it's mentioned in stab.h */
+/* OBSOLETE but only in the sdb symbol list. *x/ */
+/* OBSOLETE #define IGNORE_SYMBOL(type) (type == N_ENTRY || type == 0xa4) */
+/* OBSOLETE */
+/* OBSOLETE /* We don't want the extra gnu symbols on the machine; */
+/* OBSOLETE they will interfere with the shared segment symbols. *x/ */
+/* OBSOLETE #define NO_GNU_STABS */
+/* OBSOLETE */
+/* OBSOLETE /* Macro for text-offset and data info (in NPL a.out format). *x/ */
+/* OBSOLETE #define TEXTINFO \ */
+/* OBSOLETE text_offset = N_TXTOFF (exec_coffhdr, exec_aouthdr); \ */
+/* OBSOLETE exec_data_offset = N_TXTOFF (exec_coffhdr, exec_aouthdr)\ */
+/* OBSOLETE + exec_aouthdr.a_text */
+/* OBSOLETE */
+/* OBSOLETE /* Macro for number of symbol table entries *x/ */
+/* OBSOLETE #define NUMBER_OF_SYMBOLS \ */
+/* OBSOLETE (coffhdr.f_nsyms) */
+/* OBSOLETE */
+/* OBSOLETE /* Macro for file-offset of symbol table (in NPL a.out format). *x/ */
+/* OBSOLETE #define SYMBOL_TABLE_OFFSET \ */
+/* OBSOLETE N_SYMOFF (coffhdr) */
+/* OBSOLETE */
+/* OBSOLETE /* Macro for file-offset of string table (in NPL a.out format). *x/ */
+/* OBSOLETE #define STRING_TABLE_OFFSET \ */
+/* OBSOLETE (N_STROFF (coffhdr)) */
+/* OBSOLETE */
+/* OBSOLETE /* Macro to store the length of the string table data in INTO. *x/ */
+/* OBSOLETE #define READ_STRING_TABLE_SIZE(INTO) \ */
+/* OBSOLETE { INTO = hdr.a_stsize; } */
+/* OBSOLETE */
+/* OBSOLETE /* Macro to declare variables to hold the file's header data. *x/ */
+/* OBSOLETE #define DECLARE_FILE_HEADERS struct exec hdr; \ */
+/* OBSOLETE FILHDR coffhdr */
+/* OBSOLETE */
+/* OBSOLETE /* Macro to read the header data from descriptor DESC and validate it. */
+/* OBSOLETE NAME is the file name, for error messages. *x/ */
+/* OBSOLETE #define READ_FILE_HEADERS(DESC, NAME) \ */
+/* OBSOLETE { val = myread (DESC, &coffhdr, sizeof coffhdr); \ */
+/* OBSOLETE if (val < 0) \ */
+/* OBSOLETE perror_with_name (NAME); \ */
+/* OBSOLETE val = myread (DESC, &hdr, sizeof hdr); \ */
+/* OBSOLETE if (val < 0) \ */
+/* OBSOLETE perror_with_name (NAME); \ */
+/* OBSOLETE if (coffhdr.f_magic != GNP1MAGIC) \ */
+/* OBSOLETE error ("File \"%s\" not in coff executable format.", NAME); \ */
+/* OBSOLETE if (N_BADMAG (hdr)) \ */
+/* OBSOLETE error ("File \"%s\" not in executable format.", NAME); } */
+/* OBSOLETE */
+/* OBSOLETE /* Define COFF and other symbolic names needed on NP1 *x/ */
+/* OBSOLETE #define NS32GMAGIC GNP1MAGIC */
+/* OBSOLETE #define NS32SMAGIC GPNMAGIC */
+/* OBSOLETE */
+/* OBSOLETE /* Address of blocks in N_LBRAC and N_RBRAC symbols are absolute addresses, */
+/* OBSOLETE not relative to start of source address. *x/ */
+/* OBSOLETE #define BLOCK_ADDRESS_ABSOLUTE */
+/* OBSOLETE */
+/* OBSOLETE /* Offset from address of function to start of its code. */
+/* OBSOLETE Zero on most machines. *x/ */
+/* OBSOLETE #define FUNCTION_START_OFFSET 8 */
+/* OBSOLETE */
+/* OBSOLETE /* Advance PC across any function entry prologue instructions */
+/* OBSOLETE to reach some "real" code. One NPL we can have one two startup */
+/* OBSOLETE sequences depending on the size of the local stack: */
+/* OBSOLETE */
+/* OBSOLETE Either: */
+/* OBSOLETE "suabr b2, #" */
+/* OBSOLETE of */
+/* OBSOLETE "lil r4, #", "suabr b2, #(r4)" */
+/* OBSOLETE */
+/* OBSOLETE "lwbr b6, #", "stw r1, 8(b2)" */
+/* OBSOLETE Optional "stwbr b3, c(b2)" */
+/* OBSOLETE Optional "trr r2,r7" (Gould first argument register passing) */
+/* OBSOLETE or */
+/* OBSOLETE Optional "stw r2,8(b3)" (Gould first argument register passing) */
+/* OBSOLETE *x/ */
+/* OBSOLETE #define SKIP_PROLOGUE(pc) { \ */
+/* OBSOLETE register int op = read_memory_integer ((pc), 4); \ */
+/* OBSOLETE if ((op & 0xffff0000) == 0xFA0B0000) { \ */
+/* OBSOLETE pc += 4; \ */
+/* OBSOLETE op = read_memory_integer ((pc), 4); \ */
+/* OBSOLETE if ((op & 0xffff0000) == 0x59400000) { \ */
+/* OBSOLETE pc += 4; \ */
+/* OBSOLETE op = read_memory_integer ((pc), 4); \ */
+/* OBSOLETE if ((op & 0xffff0000) == 0x5F000000) { \ */
+/* OBSOLETE pc += 4; \ */
+/* OBSOLETE op = read_memory_integer ((pc), 4); \ */
+/* OBSOLETE if (op == 0xD4820008) { \ */
+/* OBSOLETE pc += 4; \ */
+/* OBSOLETE op = read_memory_integer ((pc), 4); \ */
+/* OBSOLETE if (op == 0x5582000C) { \ */
+/* OBSOLETE pc += 4; \ */
+/* OBSOLETE op = read_memory_integer ((pc), 2); \ */
+/* OBSOLETE if (op == 0x2fa0) { \ */
+/* OBSOLETE pc += 2; \ */
+/* OBSOLETE } else { \ */
+/* OBSOLETE op = read_memory_integer ((pc), 4); \ */
+/* OBSOLETE if (op == 0xd5030008) { \ */
+/* OBSOLETE pc += 4; \ */
+/* OBSOLETE } \ */
+/* OBSOLETE } \ */
+/* OBSOLETE } else { \ */
+/* OBSOLETE op = read_memory_integer ((pc), 2); \ */
+/* OBSOLETE if (op == 0x2fa0) { \ */
+/* OBSOLETE pc += 2; \ */
+/* OBSOLETE } \ */
+/* OBSOLETE } \ */
+/* OBSOLETE } \ */
+/* OBSOLETE } \ */
+/* OBSOLETE } \ */
+/* OBSOLETE } \ */
+/* OBSOLETE if ((op & 0xffff0000) == 0x59000000) { \ */
+/* OBSOLETE pc += 4; \ */
+/* OBSOLETE op = read_memory_integer ((pc), 4); \ */
+/* OBSOLETE if ((op & 0xffff0000) == 0x5F000000) { \ */
+/* OBSOLETE pc += 4; \ */
+/* OBSOLETE op = read_memory_integer ((pc), 4); \ */
+/* OBSOLETE if (op == 0xD4820008) { \ */
+/* OBSOLETE pc += 4; \ */
+/* OBSOLETE op = read_memory_integer ((pc), 4); \ */
+/* OBSOLETE if (op == 0x5582000C) { \ */
+/* OBSOLETE pc += 4; \ */
+/* OBSOLETE op = read_memory_integer ((pc), 2); \ */
+/* OBSOLETE if (op == 0x2fa0) { \ */
+/* OBSOLETE pc += 2; \ */
+/* OBSOLETE } else { \ */
+/* OBSOLETE op = read_memory_integer ((pc), 4); \ */
+/* OBSOLETE if (op == 0xd5030008) { \ */
+/* OBSOLETE pc += 4; \ */
+/* OBSOLETE } \ */
+/* OBSOLETE } \ */
+/* OBSOLETE } else { \ */
+/* OBSOLETE op = read_memory_integer ((pc), 2); \ */
+/* OBSOLETE if (op == 0x2fa0) { \ */
+/* OBSOLETE pc += 2; \ */
+/* OBSOLETE } \ */
+/* OBSOLETE } \ */
+/* OBSOLETE } \ */
+/* OBSOLETE } \ */
+/* OBSOLETE } \ */
+/* OBSOLETE } */
+/* OBSOLETE */
+/* OBSOLETE /* Immediately after a function call, return the saved pc. */
+/* OBSOLETE Can't go through the frames for this because on some machines */
+/* OBSOLETE the new frame is not set up until the new function executes */
+/* OBSOLETE some instructions. True on NPL! Return address is in R1. */
+/* OBSOLETE The true return address is REALLY 4 past that location! *x/ */
+/* OBSOLETE #define SAVED_PC_AFTER_CALL(frame) \ */
+/* OBSOLETE (read_register(R1_REGNUM) + 4) */
+/* OBSOLETE */
+/* OBSOLETE /* Address of end of stack space. *x/ */
+/* OBSOLETE #define STACK_END_ADDR 0x7fffc000 */
+/* OBSOLETE */
+/* OBSOLETE /* Stack grows downward. *x/ */
+/* OBSOLETE #define INNER_THAN(lhs,rhs) ((lhs) < (rhs)) */
+/* OBSOLETE */
+/* OBSOLETE /* Sequence of bytes for breakpoint instruction. */
+/* OBSOLETE This is padded out to the size of a machine word. When it was just */
+/* OBSOLETE {0x28, 0x09} it gave problems if hit breakpoint on returning from a */
+/* OBSOLETE function call. *x/ */
+/* OBSOLETE #define BREAKPOINT {0x28, 0x09, 0x0, 0x0} */
+/* OBSOLETE */
+/* OBSOLETE /* Amount PC must be decremented by after a breakpoint. */
+/* OBSOLETE This is often the number of bytes in BREAKPOINT */
+/* OBSOLETE but not always. *x/ */
+/* OBSOLETE #define DECR_PC_AFTER_BREAK 2 */
+/* OBSOLETE */
+/* OBSOLETE /* Return 1 if P points to an invalid floating point value. *x/ */
+/* OBSOLETE #define INVALID_FLOAT(p, len) ((*(short *)p & 0xff80) == 0x8000) */
+/* OBSOLETE */
+/* OBSOLETE /* Say how long (ordinary) registers are. This is a piece of bogosity */
+/* OBSOLETE used in push_word and a few other places; REGISTER_RAW_SIZE is the */
+/* OBSOLETE real way to know how big a register is. *x/ */
+/* OBSOLETE */
+/* OBSOLETE #define REGISTER_SIZE 4 */
+/* OBSOLETE */
+/* OBSOLETE /* Size of bytes of vector register (NP1 only), 32 elements * sizeof(int) *x/ */
+/* OBSOLETE #define VR_SIZE 128 */
+/* OBSOLETE */
+/* OBSOLETE /* Number of machine registers *x/ */
+/* OBSOLETE #define NUM_REGS 27 */
+/* OBSOLETE #define NUM_GEN_REGS 16 */
+/* OBSOLETE #define NUM_CPU_REGS 4 */
+/* OBSOLETE #define NUM_VECTOR_REGS 7 */
+/* OBSOLETE */
+/* OBSOLETE /* Initializer for an array of names of registers. */
+/* OBSOLETE There should be NUM_REGS strings in this initializer. *x/ */
+/* OBSOLETE #define REGISTER_NAMES { \ */
+/* OBSOLETE "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", \ */
+/* OBSOLETE "b0", "b1", "b2", "b3", "b4", "b5", "b6", "b7", \ */
+/* OBSOLETE "sp", "ps", "pc", "ve", \ */
+/* OBSOLETE "v1", "v2", "v3", "v4", "v5", "v6", "v7", \ */
+/* OBSOLETE } */
+/* OBSOLETE */
+/* OBSOLETE /* Register numbers of various important registers. */
+/* OBSOLETE Note that some of these values are "real" register numbers, */
+/* OBSOLETE and correspond to the general registers of the machine, */
+/* OBSOLETE and some are "phony" register numbers which are too large */
+/* OBSOLETE to be actual register numbers as far as the user is concerned */
+/* OBSOLETE but do serve to get the desired values when passed to read_register. *x/ */
+/* OBSOLETE #define R1_REGNUM 1 /* Gr1 => return address of caller *x/ */
+/* OBSOLETE #define R2_REGNUM 2 /* Gr2 => return value from function *x/ */
+/* OBSOLETE #define R4_REGNUM 4 /* Gr4 => register save area *x/ */
+/* OBSOLETE #define R5_REGNUM 5 /* Gr5 => register save area *x/ */
+/* OBSOLETE #define R6_REGNUM 6 /* Gr6 => register save area *x/ */
+/* OBSOLETE #define R7_REGNUM 7 /* Gr7 => register save area *x/ */
+/* OBSOLETE #define B1_REGNUM 9 /* Br1 => start of this code routine *x/ */
+/* OBSOLETE #define SP_REGNUM 10 /* Br2 == (sp) *x/ */
+/* OBSOLETE #define AP_REGNUM 11 /* Br3 == (ap) *x/ */
+/* OBSOLETE #define FP_REGNUM 16 /* A copy of Br2 saved in trap *x/ */
+/* OBSOLETE #define PS_REGNUM 17 /* Contains processor status *x/ */
+/* OBSOLETE #define PC_REGNUM 18 /* Contains program counter *x/ */
+/* OBSOLETE #define VE_REGNUM 19 /* Vector end (user setup) register *x/ */
+/* OBSOLETE #define V1_REGNUM 20 /* First vector register *x/ */
+/* OBSOLETE #define V7_REGNUM 26 /* First vector register *x/ */
+/* OBSOLETE */
+/* OBSOLETE /* Total amount of space needed to store our copies of the machine's */
+/* OBSOLETE register state, the array `registers'. *x/ */
+/* OBSOLETE #define REGISTER_BYTES \ */
+/* OBSOLETE (NUM_GEN_REGS*4 + NUM_VECTOR_REGS*VR_SIZE + NUM_CPU_REGS*4) */
+/* OBSOLETE */
+/* OBSOLETE /* Index within `registers' of the first byte of the space for */
+/* OBSOLETE register N. *x/ */
+/* OBSOLETE #define REGISTER_BYTE(N) \ */
+/* OBSOLETE (((N) < V1_REGNUM) ? ((N) * 4) : (((N) - V1_REGNUM) * VR_SIZE) + 80) */
+/* OBSOLETE */
+/* OBSOLETE /* Number of bytes of storage in the actual machine representation */
+/* OBSOLETE for register N. On the NP1, all normal regs are 4 bytes, but */
+/* OBSOLETE the vector registers are VR_SIZE*4 bytes long. *x/ */
+/* OBSOLETE #define REGISTER_RAW_SIZE(N) \ */
+/* OBSOLETE (((N) < V1_REGNUM) ? 4 : VR_SIZE) */
+/* OBSOLETE */
+/* OBSOLETE /* Number of bytes of storage in the program's representation */
+/* OBSOLETE for register N. On the NP1, all regs are 4 bytes. *x/ */
+/* OBSOLETE #define REGISTER_VIRTUAL_SIZE(N) \ */
+/* OBSOLETE (((N) < V1_REGNUM) ? 4 : VR_SIZE) */
+/* OBSOLETE */
+/* OBSOLETE /* Largest value REGISTER_RAW_SIZE can have. *x/ */
+/* OBSOLETE #define MAX_REGISTER_RAW_SIZE VR_SIZE */
+/* OBSOLETE */
+/* OBSOLETE /* Largest value REGISTER_VIRTUAL_SIZE can have. *x/ */
+/* OBSOLETE #define MAX_REGISTER_VIRTUAL_SIZE VR_SIZE */
+/* OBSOLETE */
+/* OBSOLETE /* Return the GDB type object for the "standard" data type */
+/* OBSOLETE of data in register N. *x/ */
+/* OBSOLETE #define REGISTER_VIRTUAL_TYPE(N) \ */
+/* OBSOLETE ((N) > VE_REGNUM ? builtin_type_np1_vector : builtin_type_int) */
+/* OBSOLETE extern struct type *builtin_type_np1_vector; */
+/* OBSOLETE */
+/* OBSOLETE /* Store the address of the place in which to copy the structure the */
+/* OBSOLETE subroutine will return. This is called from call_function. */
+/* OBSOLETE */
+/* OBSOLETE On this machine this is a no-op, because gcc isn't used on it */
+/* OBSOLETE yet. So this calling convention is not used. *x/ */
+/* OBSOLETE */
+/* OBSOLETE #define STORE_STRUCT_RETURN(ADDR, SP) push_word(SP + 8, ADDR) */
+/* OBSOLETE */
+/* OBSOLETE /* Extract from an arrary REGBUF containing the (raw) register state */
+/* OBSOLETE a function return value of type TYPE, and copy that, in virtual format, */
+/* OBSOLETE into VALBUF. *x/ */
+/* OBSOLETE */
+/* OBSOLETE #define EXTRACT_RETURN_VALUE(TYPE,REGBUF,VALBUF) \ */
+/* OBSOLETE memcpy (VALBUF, ((int *)(REGBUF)) + 2, TYPE_LENGTH (TYPE)) */
+/* OBSOLETE */
+/* OBSOLETE /* Write into appropriate registers a function return value */
+/* OBSOLETE of type TYPE, given in virtual format. *x/ */
+/* OBSOLETE */
+/* OBSOLETE #define STORE_RETURN_VALUE(TYPE,VALBUF) \ */
+/* OBSOLETE write_register_bytes (REGISTER_BYTE (R2_REGNUM), VALBUF, \ */
+/* OBSOLETE TYPE_LENGTH (TYPE)) */
+/* OBSOLETE */
+/* OBSOLETE /* Extract from an array REGBUF containing the (raw) register state */
+/* OBSOLETE the address in which a function should return its structure value, */
+/* OBSOLETE as a CORE_ADDR (or an expression that can be used as one). *x/ */
+/* OBSOLETE */
+/* OBSOLETE #define EXTRACT_STRUCT_VALUE_ADDRESS(REGBUF) (*((int *)(REGBUF) + 2)) */
+/* OBSOLETE */
+/* OBSOLETE /* Both gcc and cc return small structs in registers (i.e. in GDB */
+/* OBSOLETE terminology, small structs don't use the struct return convention). *x/ */
+/* OBSOLETE extern use_struct_convention_fn gould_use_struct_convention; */
+/* OBSOLETE #define USE_STRUCT_CONVENTION(gcc_p, type) gould_use_struct_convention (gcc_p, type) */
+/* OBSOLETE */
+/* OBSOLETE /* Describe the pointer in each stack frame to the previous stack frame */
+/* OBSOLETE (its caller). *x/ */
+/* OBSOLETE */
+/* OBSOLETE /* FRAME_CHAIN takes a frame's nominal address */
+/* OBSOLETE and produces the frame's chain-pointer. */
+/* OBSOLETE */
+/* OBSOLETE However, if FRAME_CHAIN_VALID returns zero, */
+/* OBSOLETE it means the given frame is the outermost one and has no caller. *x/ */
+/* OBSOLETE */
+/* OBSOLETE /* In the case of the NPL, the frame's norminal address is Br2 and the */
+/* OBSOLETE previous routines frame is up the stack X bytes, where X is the */
+/* OBSOLETE value stored in the code function header xA(Br1). *x/ */
+/* OBSOLETE #define FRAME_CHAIN(thisframe) (findframe(thisframe)) */
+/* OBSOLETE */
+/* OBSOLETE extern int gould_frame_chain_valid PARAMS ((CORE_ADDR, struct frame_info *)); */
+/* OBSOLETE #define FRAME_CHAIN_VALID(chain, thisframe) gould_frame_chain_valid (chain, thisframe) */
+/* OBSOLETE */
+/* OBSOLETE /* Define other aspects of the stack frame on NPL. *x/ */
+/* OBSOLETE #define FRAME_SAVED_PC(FRAME) \ */
+/* OBSOLETE (read_memory_integer ((FRAME)->frame + 8, 4)) */
+/* OBSOLETE */
+/* OBSOLETE #define FRAME_ARGS_ADDRESS(fi) \ */
+/* OBSOLETE ((fi)->next ? \ */
+/* OBSOLETE read_memory_integer ((fi)->frame + 12, 4) : \ */
+/* OBSOLETE read_register (AP_REGNUM)) */
+/* OBSOLETE */
+/* OBSOLETE #define FRAME_LOCALS_ADDRESS(fi) ((fi)->frame) */
+/* OBSOLETE */
+/* OBSOLETE /* Set VAL to the number of args passed to frame described by FI. */
+/* OBSOLETE Can set VAL to -1, meaning no way to tell. *x/ */
+/* OBSOLETE */
+/* OBSOLETE /* We can check the stab info to see how */
+/* OBSOLETE many arg we have. No info in stack will tell us *x/ */
+/* OBSOLETE #define FRAME_NUM_ARGS(val,fi) (val = findarg(fi)) */
+/* OBSOLETE */
+/* OBSOLETE /* Return number of bytes at start of arglist that are not really args. *x/ */
+/* OBSOLETE #define FRAME_ARGS_SKIP 8 */
+/* OBSOLETE */
+/* OBSOLETE /* Put here the code to store, into a struct frame_saved_regs, */
+/* OBSOLETE the addresses of the saved registers of frame described by FRAME_INFO. */
+/* OBSOLETE This includes special registers such as pc and fp saved in special */
+/* OBSOLETE ways in the stack frame. sp is even more special: */
+/* OBSOLETE the address we return for it IS the sp for the next frame. *x/ */
+/* OBSOLETE */
+/* OBSOLETE #define FRAME_FIND_SAVED_REGS(frame_info, frame_saved_regs) \ */
+/* OBSOLETE { \ */
+/* OBSOLETE memset (&frame_saved_regs, '\0', sizeof frame_saved_regs); \ */
+/* OBSOLETE (frame_saved_regs).regs[SP_REGNUM] = framechain (frame_info); \ */
+/* OBSOLETE (frame_saved_regs).regs[PC_REGNUM] = (frame_info)->frame + 8; \ */
+/* OBSOLETE (frame_saved_regs).regs[R4_REGNUM] = (frame_info)->frame + 0x30; \ */
+/* OBSOLETE (frame_saved_regs).regs[R5_REGNUM] = (frame_info)->frame + 0x34; \ */
+/* OBSOLETE (frame_saved_regs).regs[R6_REGNUM] = (frame_info)->frame + 0x38; \ */
+/* OBSOLETE (frame_saved_regs).regs[R7_REGNUM] = (frame_info)->frame + 0x3C; \ */
+/* OBSOLETE } */
+/* OBSOLETE */
+/* OBSOLETE /* Things needed for making the inferior call functions. *x/ */
+/* OBSOLETE */
+/* OBSOLETE #define CALL_DUMMY_LOCATION BEFORE_TEXT_END */
+/* OBSOLETE #define NEED_TEXT_START_END 1 */
+/* OBSOLETE */
+/* OBSOLETE /* Push an empty stack frame, to record the current PC, etc. *x/ */
+/* OBSOLETE */
+/* OBSOLETE #define PUSH_DUMMY_FRAME \ */
+/* OBSOLETE { register CORE_ADDR sp = read_register (SP_REGNUM); \ */
+/* OBSOLETE register int regnum; \ */
+/* OBSOLETE for (regnum = 0; regnum < FP_REGNUM; regnum++) \ */
+/* OBSOLETE sp = push_word (sp, read_register (regnum)); \ */
+/* OBSOLETE sp = push_word (sp, read_register (PS_REGNUM)); \ */
+/* OBSOLETE sp = push_word (sp, read_register (PC_REGNUM)); \ */
+/* OBSOLETE write_register (SP_REGNUM, sp);} */
+/* OBSOLETE */
+/* OBSOLETE /* Discard from the stack the innermost frame, */
+/* OBSOLETE restoring all saved registers. *x/ */
+/* OBSOLETE /* FIXME: Should be using {store,extract}_unsigned_integer. *x/ */
+/* OBSOLETE */
+/* OBSOLETE #define POP_FRAME \ */
+/* OBSOLETE { CORE_ADDR sp = read_register(SP_REGNUM); \ */
+/* OBSOLETE ULONGEST reg; \ */
+/* OBSOLETE int regnum; \ */
+/* OBSOLETE for(regnum = 0;regnum < FP_REGNUM;regnum++){ \ */
+/* OBSOLETE sp-=REGISTER_SIZE; \ */
+/* OBSOLETE read_memory(sp,&reg,REGISTER_SIZE); \ */
+/* OBSOLETE write_register(regnum,reg);} \ */
+/* OBSOLETE sp-=REGISTER_SIZE; \ */
+/* OBSOLETE read_memory(sp,&reg,REGISTER_SIZE); \ */
+/* OBSOLETE write_register(PS_REGNUM,reg); \ */
+/* OBSOLETE sp-=REGISTER_SIZE; \ */
+/* OBSOLETE read_memory(sp,&reg,REGISTER_SIZE); \ */
+/* OBSOLETE write_register(PC_REGNUM,reg);} */
+/* OBSOLETE */
+/* OBSOLETE /* MJD - Size of dummy frame pushed onto stack by PUSH_DUMMY_FRAME *x/ */
+/* OBSOLETE */
+/* OBSOLETE #define DUMMY_FRAME_SIZE (0x48) */
+/* OBSOLETE */
+/* OBSOLETE /* MJD - The sequence of words in the instructions is */
+/* OBSOLETE halt */
+/* OBSOLETE halt */
+/* OBSOLETE halt */
+/* OBSOLETE halt */
+/* OBSOLETE subr b2,stack size,0 grab stack space for dummy call */
+/* OBSOLETE labr b3,x0(b2),0 set AP_REGNUM to point at arguments */
+/* OBSOLETE lw r2,x8(b3),0 load r2 with first argument */
+/* OBSOLETE lwbr b1,arguments size(b2),0 load address of function to be called */
+/* OBSOLETE brlnk r1,x8(b1),0 call function */
+/* OBSOLETE halt */
+/* OBSOLETE halt */
+/* OBSOLETE labr b2,stack size(b2),0 give back stack */
+/* OBSOLETE break break */
+/* OBSOLETE *x/ */
+/* OBSOLETE */
+/* OBSOLETE #define CALL_DUMMY {0x00000000, \ */
+/* OBSOLETE 0x00000000, \ */
+/* OBSOLETE 0x59000000, \ */
+/* OBSOLETE 0x598a0000, \ */
+/* OBSOLETE 0xb5030008, \ */
+/* OBSOLETE 0x5c820000, \ */
+/* OBSOLETE 0x44810008, \ */
+/* OBSOLETE 0x00000000, \ */
+/* OBSOLETE 0x590a0000, \ */
+/* OBSOLETE 0x28090000 } */
+/* OBSOLETE */
+/* OBSOLETE #define CALL_DUMMY_LENGTH 40 */
+/* OBSOLETE */
+/* OBSOLETE #define CALL_DUMMY_START_OFFSET 8 */
+/* OBSOLETE */
+/* OBSOLETE #define CALL_DUMMY_STACK_ADJUST 8 */
+/* OBSOLETE */
+/* OBSOLETE /* MJD - Fixup CALL_DUMMY for the specific function call. */
+/* OBSOLETE OK heres the problems */
+/* OBSOLETE 1) On a trap there are two copies of the stack pointer, one in SP_REGNUM */
+/* OBSOLETE which is read/write and one in FP_REGNUM which is only read. It seems */
+/* OBSOLETE that when restarting the GOULD NP1 uses FP_REGNUM's value. */
+/* OBSOLETE 2) Loading function address into b1 looks a bit difficult if bigger than */
+/* OBSOLETE 0x0000fffc, infact from what I can tell the compiler sets up table of */
+/* OBSOLETE function address in base3 through which function calls are referenced. */
+/* OBSOLETE */
+/* OBSOLETE OK my solutions */
+/* OBSOLETE Calculate the size of the dummy stack frame and do adjustments of */
+/* OBSOLETE SP_REGNUM in the dummy call. */
+/* OBSOLETE Push function address onto the stack and load it in the dummy call */
+/* OBSOLETE *x/ */
+/* OBSOLETE */
+/* OBSOLETE #define FIX_CALL_DUMMY(dummyname, sp, fun, nargs, args, type, gcc_p) \ */
+/* OBSOLETE { int i;\ */
+/* OBSOLETE int arg_len = 0, total_len;\ */
+/* OBSOLETE old_sp = push_word(old_sp,fun);\ */
+/* OBSOLETE for(i = nargs - 1;i >= 0;i--)\ */
+/* OBSOLETE arg_len += TYPE_LENGTH (VALUE_TYPE (value_arg_coerce (args[i])));\ */
+/* OBSOLETE if(struct_return)\ */
+/* OBSOLETE arg_len += TYPE_LENGTH(value_type);\ */
+/* OBSOLETE total_len = DUMMY_FRAME_SIZE+CALL_DUMMY_STACK_ADJUST+4+arg_len;\ */
+/* OBSOLETE dummyname[0] += total_len;\ */
+/* OBSOLETE dummyname[2] += total_len;\ */
+/* OBSOLETE dummyname[5] += arg_len+CALL_DUMMY_STACK_ADJUST;\ */
+/* OBSOLETE dummyname[8] += total_len;} */
+/* OBSOLETE */
+/* OBSOLETE /* MJD - So the stack should end up looking like this */
+/* OBSOLETE */
+/* OBSOLETE | Normal stack frame | */
+/* OBSOLETE | from normal program | */
+/* OBSOLETE | flow | */
+/* OBSOLETE +---------------------+ <- Final sp - 0x08 - argument size */
+/* OBSOLETE | | - 0x4 - dummy_frame_size */
+/* OBSOLETE | Pushed dummy frame | */
+/* OBSOLETE | b0-b7, r0-r7 | */
+/* OBSOLETE | pc and ps | */
+/* OBSOLETE | | */
+/* OBSOLETE +---------------------+ */
+/* OBSOLETE | Function address | */
+/* OBSOLETE +---------------------+ <- Final sp - 0x8 - arguments size */
+/* OBSOLETE | | */
+/* OBSOLETE | | */
+/* OBSOLETE | | */
+/* OBSOLETE | Arguments to | */
+/* OBSOLETE | Function | */
+/* OBSOLETE | | */
+/* OBSOLETE | | */
+/* OBSOLETE | | */
+/* OBSOLETE +---------------------+ <- Final sp - 0x8 */
+/* OBSOLETE | Dummy_stack_adjust | */
+/* OBSOLETE +---------------------+ <- Final sp */
+/* OBSOLETE | | */
+/* OBSOLETE | where call will | */
+/* OBSOLETE | build frame | */
+/* OBSOLETE *x/ */
diff --git a/gdb/config/gould/tm-pn.h b/gdb/config/gould/tm-pn.h
new file mode 100644
index 00000000000..b44d4ee3aa8
--- /dev/null
+++ b/gdb/config/gould/tm-pn.h
@@ -0,0 +1,409 @@
+/* OBSOLETE /* Parameters for targe of a Gould Powernode, for GDB, the GNU debugger. */
+/* OBSOLETE Copyright 1986, 1987, 1989, 1991, 1993 Free Software Foundation, Inc. */
+/* OBSOLETE */
+/* OBSOLETE This file is part of GDB. */
+/* OBSOLETE */
+/* OBSOLETE This program is free software; you can redistribute it and/or modify */
+/* OBSOLETE it under the terms of the GNU General Public License as published by */
+/* OBSOLETE the Free Software Foundation; either version 2 of the License, or */
+/* OBSOLETE (at your option) any later version. */
+/* OBSOLETE */
+/* OBSOLETE This program is distributed in the hope that it will be useful, */
+/* OBSOLETE but WITHOUT ANY WARRANTY; without even the implied warranty of */
+/* OBSOLETE MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
+/* OBSOLETE GNU General Public License for more details. */
+/* OBSOLETE */
+/* OBSOLETE You should have received a copy of the GNU General Public License */
+/* OBSOLETE along with this program; if not, write to the Free Software */
+/* OBSOLETE Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *x/ */
+/* OBSOLETE */
+/* OBSOLETE #define GOULD_PN */
+/* OBSOLETE */
+/* OBSOLETE #define TARGET_BYTE_ORDER BIG_ENDIAN */
+/* OBSOLETE */
+/* OBSOLETE /* This code appears in libraries on Gould machines. Ignore it. *x/ */
+/* OBSOLETE #define IGNORE_SYMBOL(type) (type == N_ENTRY) */
+/* OBSOLETE */
+/* OBSOLETE /* We don't want the extra gnu symbols on the machine; */
+/* OBSOLETE they will interfere with the shared segment symbols. *x/ */
+/* OBSOLETE #define NO_GNU_STABS */
+/* OBSOLETE */
+/* OBSOLETE /* Macro for text-offset and data info (in PN a.out format). *x/ */
+/* OBSOLETE #define TEXTINFO \ */
+/* OBSOLETE text_offset = N_TXTOFF (exec_coffhdr); \ */
+/* OBSOLETE exec_data_offset = N_TXTOFF (exec_coffhdr) \ */
+/* OBSOLETE + exec_aouthdr.a_text */
+/* OBSOLETE */
+/* OBSOLETE /* Macro for number of symbol table entries (this used to be checked */
+/* OBSOLETE in dbxread.c and caused the last psymtab to use this as the end of */
+/* OBSOLETE text. I'm not sure whether it would still be necessary). *x/ */
+/* OBSOLETE #define END_OF_TEXT_DEFAULT \ */
+/* OBSOLETE (0xffffff) */
+/* OBSOLETE */
+/* OBSOLETE /* Macro for number of symbol table entries *x/ */
+/* OBSOLETE #define NUMBER_OF_SYMBOLS \ */
+/* OBSOLETE (coffhdr.f_nsyms) */
+/* OBSOLETE */
+/* OBSOLETE /* Macro for file-offset of symbol table (in usual a.out format). *x/ */
+/* OBSOLETE #define SYMBOL_TABLE_OFFSET \ */
+/* OBSOLETE N_SYMOFF (coffhdr) */
+/* OBSOLETE */
+/* OBSOLETE /* Macro for file-offset of string table (in usual a.out format). *x/ */
+/* OBSOLETE #define STRING_TABLE_OFFSET \ */
+/* OBSOLETE (N_STROFF (coffhdr) + sizeof(int)) */
+/* OBSOLETE */
+/* OBSOLETE /* Macro to store the length of the string table data in INTO. *x/ */
+/* OBSOLETE #define READ_STRING_TABLE_SIZE(INTO) \ */
+/* OBSOLETE { INTO = hdr.a_stsize; } */
+/* OBSOLETE */
+/* OBSOLETE /* Macro to declare variables to hold the file's header data. *x/ */
+/* OBSOLETE #define DECLARE_FILE_HEADERS struct old_exec hdr; \ */
+/* OBSOLETE FILHDR coffhdr */
+/* OBSOLETE */
+/* OBSOLETE /* Macro to read the header data from descriptor DESC and validate it. */
+/* OBSOLETE NAME is the file name, for error messages. *x/ */
+/* OBSOLETE #define READ_FILE_HEADERS(DESC, NAME) \ */
+/* OBSOLETE { val = myread (DESC, &coffhdr, sizeof coffhdr); \ */
+/* OBSOLETE if (val < 0) \ */
+/* OBSOLETE perror_with_name (NAME); \ */
+/* OBSOLETE val = myread (DESC, &hdr, sizeof hdr); \ */
+/* OBSOLETE if (val < 0) \ */
+/* OBSOLETE perror_with_name (NAME); \ */
+/* OBSOLETE if (coffhdr.f_magic != GNP1MAGIC) \ */
+/* OBSOLETE error ("File \"%s\" not in coff executable format.", NAME); \ */
+/* OBSOLETE if (N_BADMAG (hdr)) \ */
+/* OBSOLETE error ("File \"%s\" not in executable format.", NAME); } */
+/* OBSOLETE */
+/* OBSOLETE /* Define COFF and other symbolic names needed on NP1 *x/ */
+/* OBSOLETE #define NS32GMAGIC GDPMAGIC */
+/* OBSOLETE #define NS32SMAGIC PN_MAGIC */
+/* OBSOLETE */
+/* OBSOLETE /* Offset from address of function to start of its code. */
+/* OBSOLETE Zero on most machines. *x/ */
+/* OBSOLETE #define FUNCTION_START_OFFSET 4 */
+/* OBSOLETE */
+/* OBSOLETE /* Advance PC across any function entry prologue instructions */
+/* OBSOLETE to reach some "real" code. One PN we can have one or two startup */
+/* OBSOLETE sequences depending on the size of the local stack: */
+/* OBSOLETE */
+/* OBSOLETE Either: */
+/* OBSOLETE "suabr b2, #" */
+/* OBSOLETE of */
+/* OBSOLETE "lil r4, #", "suabr b2, #(r4)" */
+/* OBSOLETE */
+/* OBSOLETE "lwbr b6, #", "stw r1, 8(b2)" */
+/* OBSOLETE Optional "stwbr b3, c(b2)" */
+/* OBSOLETE Optional "trr r2,r7" (Gould first argument register passing) */
+/* OBSOLETE or */
+/* OBSOLETE Optional "stw r2,8(b3)" (Gould first argument register passing) */
+/* OBSOLETE *x/ */
+/* OBSOLETE #define SKIP_PROLOGUE(pc) { \ */
+/* OBSOLETE register int op = read_memory_integer ((pc), 4); \ */
+/* OBSOLETE if ((op & 0xffff0000) == 0x580B0000) { \ */
+/* OBSOLETE pc += 4; \ */
+/* OBSOLETE op = read_memory_integer ((pc), 4); \ */
+/* OBSOLETE if ((op & 0xffff0000) == 0x59400000) { \ */
+/* OBSOLETE pc += 4; \ */
+/* OBSOLETE op = read_memory_integer ((pc), 4); \ */
+/* OBSOLETE if ((op & 0xffff0000) == 0x5F000000) { \ */
+/* OBSOLETE pc += 4; \ */
+/* OBSOLETE op = read_memory_integer ((pc), 4); \ */
+/* OBSOLETE if (op == 0xD4820008) { \ */
+/* OBSOLETE pc += 4; \ */
+/* OBSOLETE op = read_memory_integer ((pc), 4); \ */
+/* OBSOLETE if (op == 0x5582000C) { \ */
+/* OBSOLETE pc += 4; \ */
+/* OBSOLETE op = read_memory_integer ((pc), 2); \ */
+/* OBSOLETE if (op == 0x2fa0) { \ */
+/* OBSOLETE pc += 2; \ */
+/* OBSOLETE } else { \ */
+/* OBSOLETE op = read_memory_integer ((pc), 4); \ */
+/* OBSOLETE if (op == 0xd5030008) { \ */
+/* OBSOLETE pc += 4; \ */
+/* OBSOLETE } \ */
+/* OBSOLETE } \ */
+/* OBSOLETE } else { \ */
+/* OBSOLETE op = read_memory_integer ((pc), 2); \ */
+/* OBSOLETE if (op == 0x2fa0) { \ */
+/* OBSOLETE pc += 2; \ */
+/* OBSOLETE } \ */
+/* OBSOLETE } \ */
+/* OBSOLETE } \ */
+/* OBSOLETE } \ */
+/* OBSOLETE } \ */
+/* OBSOLETE } \ */
+/* OBSOLETE if ((op & 0xffff0000) == 0x59000000) { \ */
+/* OBSOLETE pc += 4; \ */
+/* OBSOLETE op = read_memory_integer ((pc), 4); \ */
+/* OBSOLETE if ((op & 0xffff0000) == 0x5F000000) { \ */
+/* OBSOLETE pc += 4; \ */
+/* OBSOLETE op = read_memory_integer ((pc), 4); \ */
+/* OBSOLETE if (op == 0xD4820008) { \ */
+/* OBSOLETE pc += 4; \ */
+/* OBSOLETE op = read_memory_integer ((pc), 4); \ */
+/* OBSOLETE if (op == 0x5582000C) { \ */
+/* OBSOLETE pc += 4; \ */
+/* OBSOLETE op = read_memory_integer ((pc), 2); \ */
+/* OBSOLETE if (op == 0x2fa0) { \ */
+/* OBSOLETE pc += 2; \ */
+/* OBSOLETE } else { \ */
+/* OBSOLETE op = read_memory_integer ((pc), 4); \ */
+/* OBSOLETE if (op == 0xd5030008) { \ */
+/* OBSOLETE pc += 4; \ */
+/* OBSOLETE } \ */
+/* OBSOLETE } \ */
+/* OBSOLETE } else { \ */
+/* OBSOLETE op = read_memory_integer ((pc), 2); \ */
+/* OBSOLETE if (op == 0x2fa0) { \ */
+/* OBSOLETE pc += 2; \ */
+/* OBSOLETE } \ */
+/* OBSOLETE } \ */
+/* OBSOLETE } \ */
+/* OBSOLETE } \ */
+/* OBSOLETE } \ */
+/* OBSOLETE } */
+/* OBSOLETE */
+/* OBSOLETE /* Immediately after a function call, return the saved pc. */
+/* OBSOLETE Can't go through the frames for this because on some machines */
+/* OBSOLETE the new frame is not set up until the new function executes */
+/* OBSOLETE some instructions. True on PN! Return address is in R1. */
+/* OBSOLETE Note: true return location is 4 bytes past R1! *x/ */
+/* OBSOLETE #define SAVED_PC_AFTER_CALL(frame) \ */
+/* OBSOLETE (read_register(R1_REGNUM) + 4) */
+/* OBSOLETE */
+/* OBSOLETE /* Address of end of stack space. *x/ */
+/* OBSOLETE #define STACK_END_ADDR 0x480000 */
+/* OBSOLETE */
+/* OBSOLETE /* Stack grows downward. *x/ */
+/* OBSOLETE #define INNER_THAN(lhs,rhs) ((lhs) < (rhs)) */
+/* OBSOLETE */
+/* OBSOLETE /* Sequence of bytes for breakpoint instruction. *x/ */
+/* OBSOLETE #define BREAKPOINT {0x28, 0x09} */
+/* OBSOLETE */
+/* OBSOLETE /* Amount PC must be decremented by after a breakpoint. */
+/* OBSOLETE This is often the number of bytes in BREAKPOINT */
+/* OBSOLETE but not always. *x/ */
+/* OBSOLETE #define DECR_PC_AFTER_BREAK 2 */
+/* OBSOLETE */
+/* OBSOLETE /* Return 1 if P points to an invalid floating point value. *x/ */
+/* OBSOLETE #define INVALID_FLOAT(p, len) ((*(short *)p & 0xff80) == 0x8000) */
+/* OBSOLETE */
+/* OBSOLETE /* Say how long (ordinary) registers are. This is a piece of bogosity */
+/* OBSOLETE used in push_word and a few other places; REGISTER_RAW_SIZE is the */
+/* OBSOLETE real way to know how big a register is. *x/ */
+/* OBSOLETE */
+/* OBSOLETE #define REGISTER_SIZE 4 */
+/* OBSOLETE */
+/* OBSOLETE /* Number of machine registers *x/ */
+/* OBSOLETE #define NUM_REGS 19 */
+/* OBSOLETE #define NUM_GEN_REGS 16 */
+/* OBSOLETE #define NUM_CPU_REGS 3 */
+/* OBSOLETE */
+/* OBSOLETE /* Initializer for an array of names of registers. */
+/* OBSOLETE There should be NUM_REGS strings in this initializer. *x/ */
+/* OBSOLETE #define REGISTER_NAMES { \ */
+/* OBSOLETE "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", \ */
+/* OBSOLETE "b0", "b1", "b2", "b3", "b4", "b5", "b6", "b7", \ */
+/* OBSOLETE "sp", "ps", "pc", \ */
+/* OBSOLETE } */
+/* OBSOLETE */
+/* OBSOLETE /* Register numbers of various important registers. */
+/* OBSOLETE Note that some of these values are "real" register numbers, */
+/* OBSOLETE and correspond to the general registers of the machine, */
+/* OBSOLETE and some are "phony" register numbers which are too large */
+/* OBSOLETE to be actual register numbers as far as the user is concerned */
+/* OBSOLETE but do serve to get the desired values when passed to read_register. *x/ */
+/* OBSOLETE #define R1_REGNUM 1 /* Gr1 => return address of caller *x/ */
+/* OBSOLETE #define R4_REGNUM 4 /* Gr4 => register save area *x/ */
+/* OBSOLETE #define R5_REGNUM 5 /* Gr5 => register save area *x/ */
+/* OBSOLETE #define R6_REGNUM 6 /* Gr6 => register save area *x/ */
+/* OBSOLETE #define R7_REGNUM 7 /* Gr7 => register save area *x/ */
+/* OBSOLETE #define B1_REGNUM 9 /* Br1 => start of this code routine *x/ */
+/* OBSOLETE #define FP_REGNUM 10 /* Br2 == (sp) *x/ */
+/* OBSOLETE #define AP_REGNUM 11 /* Br3 == (ap) *x/ */
+/* OBSOLETE #define SP_REGNUM 16 /* A copy of Br2 saved in trap *x/ */
+/* OBSOLETE #define PS_REGNUM 17 /* Contains processor status *x/ */
+/* OBSOLETE #define PC_REGNUM 18 /* Contains program counter *x/ */
+/* OBSOLETE */
+/* OBSOLETE /* Total amount of space needed to store our copies of the machine's */
+/* OBSOLETE register state, the array `registers'. *x/ */
+/* OBSOLETE #define REGISTER_BYTES (NUM_GEN_REGS*4 + NUM_CPU_REGS*4) */
+/* OBSOLETE */
+/* OBSOLETE /* Index within `registers' of the first byte of the space for */
+/* OBSOLETE register N. *x/ */
+/* OBSOLETE #define REGISTER_BYTE(N) ((N) * 4) */
+/* OBSOLETE */
+/* OBSOLETE /* Number of bytes of storage in the actual machine representation */
+/* OBSOLETE for register N. On the PN, all normal regs are 4 bytes. *x/ */
+/* OBSOLETE #define REGISTER_RAW_SIZE(N) (4) */
+/* OBSOLETE */
+/* OBSOLETE /* Number of bytes of storage in the program's representation */
+/* OBSOLETE for register N. On the PN, all regs are 4 bytes. *x/ */
+/* OBSOLETE #define REGISTER_VIRTUAL_SIZE(N) (4) */
+/* OBSOLETE */
+/* OBSOLETE /* Largest value REGISTER_RAW_SIZE can have. *x/ */
+/* OBSOLETE #define MAX_REGISTER_RAW_SIZE (4) */
+/* OBSOLETE */
+/* OBSOLETE /* Largest value REGISTER_VIRTUAL_SIZE can have. *x/ */
+/* OBSOLETE #define MAX_REGISTER_VIRTUAL_SIZE (4) */
+/* OBSOLETE */
+/* OBSOLETE /* Return the GDB type object for the "standard" data type */
+/* OBSOLETE of data in register N. *x/ */
+/* OBSOLETE #define REGISTER_VIRTUAL_TYPE(N) (builtin_type_int) */
+/* OBSOLETE */
+/* OBSOLETE /* Store the address of the place in which to copy the structure the */
+/* OBSOLETE subroutine will return. This is called from call_function. */
+/* OBSOLETE */
+/* OBSOLETE On this machine this is a no-op, because gcc isn't used on it */
+/* OBSOLETE yet. So this calling convention is not used. *x/ */
+/* OBSOLETE */
+/* OBSOLETE #define STORE_STRUCT_RETURN(ADDR, SP) */
+/* OBSOLETE */
+/* OBSOLETE /* Extract from an arrary REGBUF containing the (raw) register state */
+/* OBSOLETE a function return value of type TYPE, and copy that, in virtual format, */
+/* OBSOLETE into VALBUF. *x/ */
+/* OBSOLETE */
+/* OBSOLETE #define EXTRACT_RETURN_VALUE(TYPE,REGBUF,VALBUF) \ */
+/* OBSOLETE memcpy (VALBUF, REGBUF, TYPE_LENGTH (TYPE)) */
+/* OBSOLETE */
+/* OBSOLETE /* Write into appropriate registers a function return value */
+/* OBSOLETE of type TYPE, given in virtual format. *x/ */
+/* OBSOLETE */
+/* OBSOLETE #define STORE_RETURN_VALUE(TYPE,VALBUF) \ */
+/* OBSOLETE write_register_bytes (0, VALBUF, TYPE_LENGTH (TYPE)) */
+/* OBSOLETE */
+/* OBSOLETE /* Extract from an array REGBUF containing the (raw) register state */
+/* OBSOLETE the address in which a function should return its structure value, */
+/* OBSOLETE as a CORE_ADDR (or an expression that can be used as one). *x/ */
+/* OBSOLETE */
+/* OBSOLETE #define EXTRACT_STRUCT_VALUE_ADDRESS(REGBUF) (*(int *)(REGBUF)) */
+/* OBSOLETE */
+/* OBSOLETE */
+/* OBSOLETE /* Describe the pointer in each stack frame to the previous stack frame */
+/* OBSOLETE (its caller). *x/ */
+/* OBSOLETE */
+/* OBSOLETE /* FRAME_CHAIN takes a frame's nominal address */
+/* OBSOLETE and produces the frame's chain-pointer. */
+/* OBSOLETE */
+/* OBSOLETE However, if FRAME_CHAIN_VALID returns zero, */
+/* OBSOLETE it means the given frame is the outermost one and has no caller. *x/ */
+/* OBSOLETE */
+/* OBSOLETE /* In the case of the NPL, the frame's norminal address is Br2 and the */
+/* OBSOLETE previous routines frame is up the stack X bytes, where X is the */
+/* OBSOLETE value stored in the code function header xA(Br1). *x/ */
+/* OBSOLETE #define FRAME_CHAIN(thisframe) (findframe(thisframe)) */
+/* OBSOLETE */
+/* OBSOLETE extern int gould_frame_chain_valid PARAMS ((CORE_ADDR, struct frame_info *)); */
+/* OBSOLETE #define FRAME_CHAIN_VALID(chain, thisframe) gould_frame_chain_valid (chain, thisframe) */
+/* OBSOLETE */
+/* OBSOLETE /* Define other aspects of the stack frame on NPL. *x/ */
+/* OBSOLETE #define FRAME_SAVED_PC(frame) \ */
+/* OBSOLETE (read_memory_integer ((frame)->frame + 8, 4)) */
+/* OBSOLETE */
+/* OBSOLETE #define FRAME_ARGS_ADDRESS(fi) \ */
+/* OBSOLETE ((fi)->next ? \ */
+/* OBSOLETE read_memory_integer ((fi)->frame + 12, 4) : \ */
+/* OBSOLETE read_register (AP_REGNUM)) */
+/* OBSOLETE */
+/* OBSOLETE #define FRAME_LOCALS_ADDRESS(fi) ((fi)->frame + 80) */
+/* OBSOLETE */
+/* OBSOLETE /* Set VAL to the number of args passed to frame described by FI. */
+/* OBSOLETE Can set VAL to -1, meaning no way to tell. *x/ */
+/* OBSOLETE */
+/* OBSOLETE /* We can check the stab info to see how */
+/* OBSOLETE many arg we have. No info in stack will tell us *x/ */
+/* OBSOLETE #define FRAME_NUM_ARGS(val,fi) (val = findarg(fi)) */
+/* OBSOLETE */
+/* OBSOLETE /* Return number of bytes at start of arglist that are not really args. *x/ */
+/* OBSOLETE #define FRAME_ARGS_SKIP 8 */
+/* OBSOLETE */
+/* OBSOLETE /* Put here the code to store, into a struct frame_saved_regs, */
+/* OBSOLETE the addresses of the saved registers of frame described by FRAME_INFO. */
+/* OBSOLETE This includes special registers such as pc and fp saved in special */
+/* OBSOLETE ways in the stack frame. sp is even more special: */
+/* OBSOLETE the address we return for it IS the sp for the next frame. *x/ */
+/* OBSOLETE */
+/* OBSOLETE #define FRAME_FIND_SAVED_REGS(frame_info, frame_saved_regs) \ */
+/* OBSOLETE { \ */
+/* OBSOLETE memset (&frame_saved_regs, '\0', sizeof frame_saved_regs); \ */
+/* OBSOLETE (frame_saved_regs).regs[PC_REGNUM] = (frame_info)->frame + 8; \ */
+/* OBSOLETE (frame_saved_regs).regs[R4_REGNUM] = (frame_info)->frame + 0x30; \ */
+/* OBSOLETE (frame_saved_regs).regs[R5_REGNUM] = (frame_info)->frame + 0x34; \ */
+/* OBSOLETE (frame_saved_regs).regs[R6_REGNUM] = (frame_info)->frame + 0x38; \ */
+/* OBSOLETE (frame_saved_regs).regs[R7_REGNUM] = (frame_info)->frame + 0x3C; \ */
+/* OBSOLETE } */
+/* OBSOLETE */
+/* OBSOLETE /* Things needed for making the inferior call functions. *x/ */
+/* OBSOLETE */
+/* OBSOLETE /* Push an empty stack frame, to record the current PC, etc. *x/ */
+/* OBSOLETE */
+/* OBSOLETE #define PUSH_DUMMY_FRAME \ */
+/* OBSOLETE { register CORE_ADDR sp = read_register (SP_REGNUM); \ */
+/* OBSOLETE register int regnum; \ */
+/* OBSOLETE sp = push_word (sp, read_register (PC_REGNUM)); \ */
+/* OBSOLETE sp = push_word (sp, read_register (FP_REGNUM)); \ */
+/* OBSOLETE write_register (FP_REGNUM, sp); \ */
+/* OBSOLETE for (regnum = FP_REGNUM - 1; regnum >= 0; regnum--) \ */
+/* OBSOLETE sp = push_word (sp, read_register (regnum)); \ */
+/* OBSOLETE sp = push_word (sp, read_register (PS_REGNUM)); \ */
+/* OBSOLETE write_register (SP_REGNUM, sp); } */
+/* OBSOLETE */
+/* OBSOLETE /* Discard from the stack the innermost frame, */
+/* OBSOLETE restoring all saved registers. *x/ */
+/* OBSOLETE */
+/* OBSOLETE #define POP_FRAME \ */
+/* OBSOLETE { register struct frame_info *frame = get_current_frame (); \ */
+/* OBSOLETE register CORE_ADDR fp; \ */
+/* OBSOLETE register int regnum; \ */
+/* OBSOLETE struct frame_saved_regs fsr; \ */
+/* OBSOLETE struct frame_info *fi; \ */
+/* OBSOLETE fp = frame->frame; \ */
+/* OBSOLETE get_frame_saved_regs (frame, &fsr); \ */
+/* OBSOLETE for (regnum = FP_REGNUM - 1; regnum >= 0; regnum--) \ */
+/* OBSOLETE if (fsr.regs[regnum]) \ */
+/* OBSOLETE write_register (regnum, read_memory_integer (fsr.regs[regnum], 4)); \ */
+/* OBSOLETE if (fsr.regs[PS_REGNUM]) \ */
+/* OBSOLETE write_register (PS_REGNUM, read_memory_integer (fsr.regs[PS_REGNUM], 4)); \ */
+/* OBSOLETE write_register (FP_REGNUM, read_memory_integer (fp, 4)); \ */
+/* OBSOLETE write_register (PC_REGNUM, read_memory_integer (fp + 4, 4)); \ */
+/* OBSOLETE write_register (SP_REGNUM, fp + 8); \ */
+/* OBSOLETE flush_cached_frames (); \ */
+/* OBSOLETE } */
+/* OBSOLETE */
+/* OBSOLETE /* This sequence of words is the instructions: */
+/* OBSOLETE halt */
+/* OBSOLETE halt */
+/* OBSOLETE halt */
+/* OBSOLETE halt */
+/* OBSOLETE suabr b2, #<stacksize> */
+/* OBSOLETE lwbr b6, #con */
+/* OBSOLETE stw r1, 8(b2) - save caller address, do we care? */
+/* OBSOLETE lw r2, 60(b2) - arg1 */
+/* OBSOLETE labr b3, 50(b2) */
+/* OBSOLETE std r4, 30(b2) - save r4-r7 */
+/* OBSOLETE std r6, 38(b2) */
+/* OBSOLETE lwbr b1, #<func> - load function call address */
+/* OBSOLETE brlnk r1, 8(b1) - call function */
+/* OBSOLETE halt */
+/* OBSOLETE halt */
+/* OBSOLETE ld r4, 30(b2) - restore r4-r7 */
+/* OBSOLETE ld r6, 38(b2) */
+/* OBSOLETE */
+/* OBSOLETE Setup our stack frame, load argumemts, call and then restore registers. */
+/* OBSOLETE *x/ */
+/* OBSOLETE */
+/* OBSOLETE /* FIXME: The below defines an m68k CALL_DUMMY, which looks nothing like what */
+/* OBSOLETE is documented above. *x/ */
+/* OBSOLETE */
+/* OBSOLETE #define CALL_DUMMY {0xf227e0ff, 0x48e7fffc, 0x426742e7, 0x4eb93232, 0x3232dffc, 0x69696969, 0x4e4f4e71} */
+/* OBSOLETE */
+/* OBSOLETE #define CALL_DUMMY_LENGTH 28 */
+/* OBSOLETE */
+/* OBSOLETE #define CALL_DUMMY_START_OFFSET 12 */
+/* OBSOLETE */
+/* OBSOLETE /* Insert the specified number of args and function address */
+/* OBSOLETE into a call sequence of the above form stored at DUMMYNAME. *x/ */
+/* OBSOLETE */
+/* OBSOLETE #define FIX_CALL_DUMMY(dummyname, pc, fun, nargs, args, type, gcc_p) \ */
+/* OBSOLETE { *(int *)((char *) dummyname + 20) = nargs * 4; \ */
+/* OBSOLETE *(int *)((char *) dummyname + 14) = fun; } */
diff --git a/gdb/config/gould/xm-np1.h b/gdb/config/gould/xm-np1.h
new file mode 100644
index 00000000000..63bc4501d9f
--- /dev/null
+++ b/gdb/config/gould/xm-np1.h
@@ -0,0 +1,94 @@
+/* OBSOLETE /* Parameters for execution on a Gould NP1, for GDB, the GNU debugger. */
+/* OBSOLETE Copyright 1986, 1987, 1989, 1992 Free Software Foundation, Inc. */
+/* OBSOLETE */
+/* OBSOLETE This file is part of GDB. */
+/* OBSOLETE */
+/* OBSOLETE This program is free software; you can redistribute it and/or modify */
+/* OBSOLETE it under the terms of the GNU General Public License as published by */
+/* OBSOLETE the Free Software Foundation; either version 2 of the License, or */
+/* OBSOLETE (at your option) any later version. */
+/* OBSOLETE */
+/* OBSOLETE This program is distributed in the hope that it will be useful, */
+/* OBSOLETE but WITHOUT ANY WARRANTY; without even the implied warranty of */
+/* OBSOLETE MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
+/* OBSOLETE GNU General Public License for more details. */
+/* OBSOLETE */
+/* OBSOLETE You should have received a copy of the GNU General Public License */
+/* OBSOLETE along with this program; if not, write to the Free Software */
+/* OBSOLETE Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *x/ */
+/* OBSOLETE */
+/* OBSOLETE #define HOST_BYTE_ORDER BIG_ENDIAN */
+/* OBSOLETE */
+/* OBSOLETE /* Address of U in kernel space *x/ */
+/* OBSOLETE #define KERNEL_U_ADDR 0x7fffc000 */
+/* OBSOLETE */
+/* OBSOLETE /* This is a piece of magic that is given a register number REGNO */
+/* OBSOLETE and as BLOCKEND the address in the system of the end of the user structure */
+/* OBSOLETE and stores in ADDR the address in the kernel or core dump */
+/* OBSOLETE of that register. *x/ */
+/* OBSOLETE #define REGISTER_U_ADDR(addr, blockend, regno) { \ */
+/* OBSOLETE addr = blockend + regno * 4; \ */
+/* OBSOLETE if (regno == VE_REGNUM) addr = blockend - 9 * 4; \ */
+/* OBSOLETE if (regno == PC_REGNUM) addr = blockend - 8 * 4; \ */
+/* OBSOLETE if (regno == PS_REGNUM) addr = blockend - 7 * 4; \ */
+/* OBSOLETE if (regno == FP_REGNUM) addr = blockend - 6 * 4; \ */
+/* OBSOLETE if (regno >= V1_REGNUM) \ */
+/* OBSOLETE addr = blockend + 16 * 4 + (regno - V1_REGNUM) * VR_SIZE; \ */
+/* OBSOLETE } */
+/* OBSOLETE */
+/* OBSOLETE /* Don't try to write the frame pointer. *x/ */
+/* OBSOLETE #define CANNOT_STORE_REGISTER(regno) ((regno) == FP_REGNUM) */
+/* OBSOLETE */
+/* OBSOLETE /* */
+/* OBSOLETE * No KDB support, Yet! *x/ */
+/* OBSOLETE /* Interface definitions for kernel debugger KDB. *x/ */
+/* OBSOLETE */
+/* OBSOLETE /* Map machine fault codes into signal numbers. */
+/* OBSOLETE First subtract 0, divide by 4, then index in a table. */
+/* OBSOLETE Faults for which the entry in this table is 0 */
+/* OBSOLETE are not handled by KDB; the program's own trap handler */
+/* OBSOLETE gets to handle then. *x/ */
+/* OBSOLETE */
+/* OBSOLETE #define FAULT_CODE_ORIGIN 0 */
+/* OBSOLETE #define FAULT_CODE_UNITS 4 */
+/* OBSOLETE #define FAULT_TABLE \ */
+/* OBSOLETE { 0, 0, 0, 0, SIGTRAP, 0, 0, 0, \ */
+/* OBSOLETE 0, SIGTRAP, 0, 0, 0, 0, 0, SIGKILL, \ */
+/* OBSOLETE 0, 0, 0, 0, 0, 0, 0, 0, \ */
+/* OBSOLETE SIGILL } */
+/* OBSOLETE */
+/* OBSOLETE /* Start running with a stack stretching from BEG to END. */
+/* OBSOLETE BEG and END should be symbols meaningful to the assembler. */
+/* OBSOLETE This is used only for kdb. *x/ */
+/* OBSOLETE */
+/* OBSOLETE #define INIT_STACK(beg, end) \ */
+/* OBSOLETE { asm (".globl end"); \ */
+/* OBSOLETE asm ("movel $ end, sp"); \ */
+/* OBSOLETE asm ("clrl fp"); } */
+/* OBSOLETE */
+/* OBSOLETE /* Push the frame pointer register on the stack. *x/ */
+/* OBSOLETE #define PUSH_FRAME_PTR \ */
+/* OBSOLETE asm ("movel fp, -(sp)"); */
+/* OBSOLETE */
+/* OBSOLETE /* Copy the top-of-stack to the frame pointer register. *x/ */
+/* OBSOLETE #define POP_FRAME_PTR \ */
+/* OBSOLETE asm ("movl (sp), fp"); */
+/* OBSOLETE */
+/* OBSOLETE /* After KDB is entered by a fault, push all registers */
+/* OBSOLETE that GDB thinks about (all NUM_REGS of them), */
+/* OBSOLETE so that they appear in order of ascending GDB register number. */
+/* OBSOLETE The fault code will be on the stack beyond the last register. *x/ */
+/* OBSOLETE */
+/* OBSOLETE #define PUSH_REGISTERS \ */
+/* OBSOLETE { asm ("clrw -(sp)"); \ */
+/* OBSOLETE asm ("pea 10(sp)"); \ */
+/* OBSOLETE asm ("movem $ 0xfffe,-(sp)"); } */
+/* OBSOLETE */
+/* OBSOLETE /* Assuming the registers (including processor status) have been */
+/* OBSOLETE pushed on the stack in order of ascending GDB register number, */
+/* OBSOLETE restore them and return to the address in the saved PC register. *x/ */
+/* OBSOLETE */
+/* OBSOLETE #define POP_REGISTERS \ */
+/* OBSOLETE { asm ("subil $8,28(sp)"); \ */
+/* OBSOLETE asm ("movem (sp),$ 0xffff"); \ */
+/* OBSOLETE asm ("rte"); } */
diff --git a/gdb/config/gould/xm-pn.h b/gdb/config/gould/xm-pn.h
new file mode 100644
index 00000000000..2540cfc1203
--- /dev/null
+++ b/gdb/config/gould/xm-pn.h
@@ -0,0 +1,87 @@
+/* OBSOLETE /* Parameters for execution on a Gould PN, for GDB, the GNU debugger. */
+/* OBSOLETE Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc. */
+/* OBSOLETE */
+/* OBSOLETE This file is part of GDB. */
+/* OBSOLETE */
+/* OBSOLETE This program is free software; you can redistribute it and/or modify */
+/* OBSOLETE it under the terms of the GNU General Public License as published by */
+/* OBSOLETE the Free Software Foundation; either version 2 of the License, or */
+/* OBSOLETE (at your option) any later version. */
+/* OBSOLETE */
+/* OBSOLETE This program is distributed in the hope that it will be useful, */
+/* OBSOLETE but WITHOUT ANY WARRANTY; without even the implied warranty of */
+/* OBSOLETE MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
+/* OBSOLETE GNU General Public License for more details. */
+/* OBSOLETE */
+/* OBSOLETE You should have received a copy of the GNU General Public License */
+/* OBSOLETE along with this program; if not, write to the Free Software */
+/* OBSOLETE Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *x/ */
+/* OBSOLETE */
+/* OBSOLETE #define HOST_BYTE_ORDER BIG_ENDIAN */
+/* OBSOLETE */
+/* OBSOLETE /* Address of U in kernel space *x/ */
+/* OBSOLETE #define KERNEL_U_ADDR 0x3fc000 */
+/* OBSOLETE */
+/* OBSOLETE /* This is a piece of magic that is given a register number REGNO */
+/* OBSOLETE and as BLOCKEND the address in the system of the end of the user structure */
+/* OBSOLETE and stores in ADDR the address in the kernel or core dump */
+/* OBSOLETE of that register. *x/ */
+/* OBSOLETE #define REGISTER_U_ADDR(addr, blockend, regno) { \ */
+/* OBSOLETE addr = blockend + regno * 4; \ */
+/* OBSOLETE if (regno == PC_REGNUM) addr = blockend - 8 * 4; \ */
+/* OBSOLETE if (regno == PS_REGNUM) addr = blockend - 7 * 4; \ */
+/* OBSOLETE if (regno == SP_REGNUM) addr = blockend - 6 * 4; \ */
+/* OBSOLETE } */
+/* OBSOLETE */
+/* OBSOLETE /* No KDB support, Yet! *x/ */
+/* OBSOLETE /* Interface definitions for kernel debugger KDB. *x/ */
+/* OBSOLETE */
+/* OBSOLETE /* Map machine fault codes into signal numbers. */
+/* OBSOLETE First subtract 0, divide by 4, then index in a table. */
+/* OBSOLETE Faults for which the entry in this table is 0 */
+/* OBSOLETE are not handled by KDB; the program's own trap handler */
+/* OBSOLETE gets to handle then. *x/ */
+/* OBSOLETE */
+/* OBSOLETE #define FAULT_CODE_ORIGIN 0 */
+/* OBSOLETE #define FAULT_CODE_UNITS 4 */
+/* OBSOLETE #define FAULT_TABLE \ */
+/* OBSOLETE { 0, 0, 0, 0, SIGTRAP, 0, 0, 0, \ */
+/* OBSOLETE 0, SIGTRAP, 0, 0, 0, 0, 0, SIGKILL, \ */
+/* OBSOLETE 0, 0, 0, 0, 0, 0, 0, 0, \ */
+/* OBSOLETE SIGILL } */
+/* OBSOLETE */
+/* OBSOLETE /* Start running with a stack stretching from BEG to END. */
+/* OBSOLETE BEG and END should be symbols meaningful to the assembler. */
+/* OBSOLETE This is used only for kdb. *x/ */
+/* OBSOLETE */
+/* OBSOLETE #define INIT_STACK(beg, end) \ */
+/* OBSOLETE { asm (".globl end"); \ */
+/* OBSOLETE asm ("movel $ end, sp"); \ */
+/* OBSOLETE asm ("clrl fp"); } */
+/* OBSOLETE */
+/* OBSOLETE /* Push the frame pointer register on the stack. *x/ */
+/* OBSOLETE #define PUSH_FRAME_PTR \ */
+/* OBSOLETE asm ("movel fp, -(sp)"); */
+/* OBSOLETE */
+/* OBSOLETE /* Copy the top-of-stack to the frame pointer register. *x/ */
+/* OBSOLETE #define POP_FRAME_PTR \ */
+/* OBSOLETE asm ("movl (sp), fp"); */
+/* OBSOLETE */
+/* OBSOLETE /* After KDB is entered by a fault, push all registers */
+/* OBSOLETE that GDB thinks about (all NUM_REGS of them), */
+/* OBSOLETE so that they appear in order of ascending GDB register number. */
+/* OBSOLETE The fault code will be on the stack beyond the last register. *x/ */
+/* OBSOLETE */
+/* OBSOLETE #define PUSH_REGISTERS \ */
+/* OBSOLETE { asm ("clrw -(sp)"); \ */
+/* OBSOLETE asm ("pea 10(sp)"); \ */
+/* OBSOLETE asm ("movem $ 0xfffe,-(sp)"); } */
+/* OBSOLETE */
+/* OBSOLETE /* Assuming the registers (including processor status) have been */
+/* OBSOLETE pushed on the stack in order of ascending GDB register number, */
+/* OBSOLETE restore them and return to the address in the saved PC register. *x/ */
+/* OBSOLETE */
+/* OBSOLETE #define POP_REGISTERS \ */
+/* OBSOLETE { asm ("subil $8,28(sp)"); \ */
+/* OBSOLETE asm ("movem (sp),$ 0xffff"); \ */
+/* OBSOLETE asm ("rte"); } */
diff --git a/gdb/config/h8300/h8300.mt b/gdb/config/h8300/h8300.mt
new file mode 100644
index 00000000000..c6e25ab8ced
--- /dev/null
+++ b/gdb/config/h8300/h8300.mt
@@ -0,0 +1,6 @@
+# Target: H8300 with HMS monitor, E7000 ICE and H8 simulator
+TDEPFILES= h8300-tdep.o remote-e7000.o ser-e7kpc.o monitor.o remote-hms.o dsrec.o
+TM_FILE= tm-h8300.h
+
+SIM_OBS = remote-sim.o
+SIM = ../sim/h8300/libsim.a
diff --git a/gdb/config/h8300/tm-h8300.h b/gdb/config/h8300/tm-h8300.h
new file mode 100644
index 00000000000..b398d2f0f9c
--- /dev/null
+++ b/gdb/config/h8300/tm-h8300.h
@@ -0,0 +1,303 @@
+/* Parameters for execution on a H8/300 series machine.
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Contributed by Steve Chamberlain sac@cygnus.com */
+
+#ifdef __STDC__
+struct frame_info;
+struct frame_saved_regs;
+struct value;
+struct type;
+#endif
+
+/* 1 if debugging H8/300H application */
+extern int h8300hmode;
+extern int h8300smode;
+
+/* Number of bytes in a word */
+
+#define BINWORD (h8300hmode?4:2)
+
+#define EXTRA_FRAME_INFO \
+ struct frame_saved_regs *fsr; \
+ CORE_ADDR from_pc; \
+ CORE_ADDR args_pointer;\
+ CORE_ADDR locals_pointer ;
+
+/* Zero the frame_saved_regs pointer when the frame is initialized,
+ so that FRAME_FIND_SAVED_REGS () will know to allocate and
+ initialize a frame_saved_regs struct the first time it is called.
+ Set the arg_pointer to -1, which is not valid; 0 and other values
+ indicate real, cached values. */
+
+#define INIT_EXTRA_FRAME_INFO(fromleaf, fi) \
+ h8300_init_extra_frame_info (fromleaf, fi)
+
+extern void h8300_init_extra_frame_info ();
+
+#define IEEE_FLOAT
+/* Define the bit, byte, and word ordering of the machine. */
+#define TARGET_BYTE_ORDER BIG_ENDIAN
+#undef TARGET_INT_BIT
+#define TARGET_INT_BIT 16
+#undef TARGET_LONG_BIT
+#define TARGET_LONG_BIT 32
+#undef TARGET_PTR_BIT
+#define TARGET_PTR_BIT (h8300hmode ? 32:16)
+
+/* 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(ip) {(ip) = h8300_skip_prologue(ip);}
+extern CORE_ADDR h8300_skip_prologue ();
+
+/* 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_unsigned_integer (read_register (SP_REGNUM), BINWORD)
+
+/* Stack grows downward. */
+
+#define INNER_THAN(lhs,rhs) ((lhs) < (rhs))
+
+/*#define BREAKPOINT {0x7A, 0xFF}*/
+#define BREAKPOINT {0x01, 0x80} /* Sleep */
+#define REMOTE_BREAKPOINT { 0x57, 0x30} /* trapa #3 */
+/* If your kernel resets the pc after the trap happens you may need to
+ define this before including this file. */
+
+#define DECR_PC_AFTER_BREAK 0
+
+/* Say how long registers are. */
+
+#define REGISTER_SIZE 4
+
+#define NUM_REGS 13
+
+#define REGISTER_BYTES (NUM_REGS * 4)
+
+/* Index within `registers' of the first byte of the space for
+ register N. */
+
+#define REGISTER_BYTE(N) ((N) * 4)
+
+/* Number of bytes of storage in the actual machine representation
+ for register N. On the H8/300, all regs are 2 bytes. */
+
+#define REGISTER_RAW_SIZE(N) (h8300hmode ? 4 : 2)
+
+/* Number of bytes of storage in the program's representation
+ for register N. */
+
+#define REGISTER_VIRTUAL_SIZE(N) (h8300hmode ? 4 : 2)
+
+/* 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
+
+/* Return the GDB type object for the "standard" data type
+ of data in register N. */
+
+#define REGISTER_VIRTUAL_TYPE(N) \
+(h8300hmode ? builtin_type_unsigned_long : builtin_type_unsigned_short)
+
+/* Initializer for an array of names of registers.
+ Entries beyond the first NUM_REGS are ignored. */
+
+#define REGISTER_NAMES \
+ {"r0", "r1", "r2", "r3", "r4", "r5", "r6", "sp", "ccr","pc","cycles","tick","inst"}
+
+/* An array of names of registers. */
+
+extern char **h8300_register_names;
+#define REGISTER_NAME(i) h8300_register_names[i]
+
+/* 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 ARG0_REGNUM 0 /* first reg in which an arg may be passed */
+#define ARGLAST_REGNUM 2 /* last reg in which an arg may be passed */
+#define FP_REGNUM 6 /* Contain saddress of executing stack frame */
+#define SP_REGNUM 7 /* Contains address of top of stack */
+#define CCR_REGNUM 8 /* Contains processor status */
+#define PC_REGNUM 9 /* Contains program counter */
+
+/* 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. */
+
+/* FIXME: Won't work with both h8/300's. */
+
+extern void h8300_extract_return_value PARAMS((struct type *, char *, char *));
+#define EXTRACT_RETURN_VALUE(TYPE,REGBUF,VALBUF) \
+ h8300_extract_return_value (TYPE, (char *)(REGBUF), (char *)(VALBUF))
+
+/* Write into appropriate registers a function return value
+ of type TYPE, given in virtual format. Assumes floats are passed
+ in d0/d1. */
+/* FIXME: Won't work with both h8/300's. */
+
+extern void h8300_store_return_value PARAMS((struct type *, char *));
+#define STORE_RETURN_VALUE(TYPE,VALBUF) \
+ h8300_store_return_value(TYPE, (char *) (VALBUF))
+
+/* struct passing and returning stuff */
+#define STORE_STRUCT_RETURN(STRUCT_ADDR, SP) \
+ write_register (0, STRUCT_ADDR)
+
+#define USE_STRUCT_CONVENTION(gcc_p, type) (1)
+
+/* Extract from an array REGBUF containing the (raw) register state
+ the address in which a function should return its structure value,
+ as a CORE_ADDR (or an expression that can be used as one). */
+
+#define EXTRACT_STRUCT_VALUE_ADDRESS(REGBUF) \
+ extract_address (REGBUF + REGISTER_BYTE (0), \
+ REGISTER_RAW_SIZE (0))
+
+/* 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.
+
+ However, if FRAME_CHAIN_VALID returns zero,
+ it means the given frame is the outermost one and has no caller. */
+
+#define FRAME_CHAIN(FRAME) h8300_frame_chain(FRAME)
+CORE_ADDR h8300_frame_chain PARAMS ((struct frame_info *));
+
+/* In the case of the H8/300, the frame's nominal address
+ is the address of a 2-byte word containing the calling frame's address. */
+
+/* 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 objfile.h */
+
+#define FRAME_CHAIN_VALID(fp,fi) alternate_frame_chain_valid (fp, fi)
+
+/* Define other aspects of the stack frame. */
+
+/* A macro that tells us whether the function invocation represented
+ by FI does not have a frame on the stack associated with it. If it
+ does not, FRAMELESS is set to 1, else 0. */
+#define FRAMELESS_FUNCTION_INVOCATION(FI, FRAMELESS) \
+ (FRAMELESS) = frameless_look_for_prologue(FI)
+
+/* Any function with a frame looks like this
+ SECOND ARG
+ FIRST ARG
+ RET PC
+ SAVED R2
+ SAVED R3
+ SAVED FP <-FP POINTS HERE
+ LOCALS0
+ LOCALS1 <-SP POINTS HERE
+ */
+
+#define FRAME_SAVED_PC(FRAME) h8300_frame_saved_pc(FRAME)
+
+#define FRAME_ARGS_ADDRESS(fi) frame_args_address(fi)
+
+#define FRAME_LOCALS_ADDRESS(fi) frame_locals_address(fi);
+
+/* Set VAL to the number of args passed to frame described by FI.
+ Can set VAL to -1, meaning no way to tell. */
+
+/* We can't tell how many args there are
+ now that the C compiler delays popping them. */
+
+#define FRAME_NUM_ARGS(val,fi) (val = -1)
+
+/* Return number of bytes at start of arglist that are not really args. */
+
+#define FRAME_ARGS_SKIP 0
+
+/* Put here the code to store, into a struct frame_saved_regs,
+ the addresses of the saved registers of frame described by FRAME_INFO.
+ This includes special registers such as pc and fp saved in special
+ ways in the stack frame. sp is even more special:
+ the address we return for it IS the sp for the next frame. */
+
+#define FRAME_FIND_SAVED_REGS(frame_info, frame_saved_regs) \
+ h8300_frame_find_saved_regs(frame_info, &(frame_saved_regs))
+
+
+typedef unsigned short INSN_WORD;
+
+
+#define PRINT_REGISTER_HOOK(regno) print_register_hook(regno)
+
+#define GDB_TARGET_IS_H8300
+
+#define NUM_REALREGS 10
+#define NOP { 0x01, 0x80} /* A sleep insn */
+
+#define BELIEVE_PCC_PROMOTION 1
+
+/*
+ * CALL_DUMMY stuff:
+ */
+
+#define USE_GENERIC_DUMMY_FRAMES
+#define CALL_DUMMY {0}
+#define CALL_DUMMY_LENGTH (0)
+#define CALL_DUMMY_ADDRESS() entry_point_address ()
+#define CALL_DUMMY_LOCATION AT_ENTRY_POINT
+#define CALL_DUMMY_START_OFFSET (0)
+#define CALL_DUMMY_BREAKPOINT_OFFSET (0)
+
+extern CORE_ADDR h8300_push_arguments PARAMS ((int nargs,
+ struct value **args,
+ CORE_ADDR sp,
+ unsigned char struct_return,
+ CORE_ADDR struct_addr));
+extern CORE_ADDR h8300_push_return_address PARAMS ((CORE_ADDR, CORE_ADDR));
+
+#define PC_IN_CALL_DUMMY(PC, SP, FP) generic_pc_in_call_dummy (PC, SP)
+#define FIX_CALL_DUMMY(DUMMY, START_SP, FUNADDR, NARGS, ARGS, TYPE, GCCP)
+#define PUSH_ARGUMENTS(NARGS, ARGS, SP, STRUCT_RETURN, STRUCT_ADDR) \
+ (SP) = h8300_push_arguments (NARGS, ARGS, SP, STRUCT_RETURN, STRUCT_ADDR)
+/* Push an empty stack frame, to record the current PC, etc. */
+#define PUSH_DUMMY_FRAME generic_push_dummy_frame ()
+/* Discard from the stack the innermost frame, restoring all registers. */
+#define POP_FRAME h8300_pop_frame ()
+#define PUSH_RETURN_ADDRESS(PC, SP) h8300_push_return_address (PC, SP)
+
+/* override the standard get_saved_register function with
+ one that takes account of generic CALL_DUMMY frames */
+#define GET_SAVED_REGISTER
+
+
diff --git a/gdb/config/h8500/h8500.mt b/gdb/config/h8500/h8500.mt
new file mode 100644
index 00000000000..35f6b4ddc86
--- /dev/null
+++ b/gdb/config/h8500/h8500.mt
@@ -0,0 +1,6 @@
+# Target: H8500 with HMS monitor and H8 simulator
+TDEPFILES= h8500-tdep.o monitor.o remote-hms.o dsrec.o
+TM_FILE= tm-h8500.h
+
+SIM_OBS = remote-sim.o
+SIM = ../sim/h8500/libsim.a
diff --git a/gdb/config/h8500/tm-h8500.h b/gdb/config/h8500/tm-h8500.h
new file mode 100644
index 00000000000..8f7d9664efd
--- /dev/null
+++ b/gdb/config/h8500/tm-h8500.h
@@ -0,0 +1,293 @@
+/* Parameters for execution on a H8/500 series machine.
+ Copyright (C) 1993, 1995 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Contributed by Steve Chamberlain sac@cygnus.com */
+
+#define GDB_TARGET_IS_H8500
+
+#define IEEE_FLOAT 1
+
+/* Define the bit, byte, and word ordering of the machine. */
+
+#define TARGET_BYTE_ORDER BIG_ENDIAN
+
+/* Define the sizes of integers and pointers. */
+
+#define TARGET_INT_BIT 16
+
+#define TARGET_LONG_BIT 32
+
+#define TARGET_PTR_BIT (minimum_mode ? 16 : 32)
+
+/* 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(ip) { (ip) = h8500_skip_prologue(ip); }
+extern CORE_ADDR h8500_skip_prologue PARAMS ((CORE_ADDR));
+
+/* 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) saved_pc_after_call()
+extern CORE_ADDR saved_pc_after_call PARAMS ((void));
+
+/* Stack grows downward. */
+
+#define INNER_THAN(lhs,rhs) ((lhs) < (rhs))
+
+/* Illegal instruction - used by the simulator for breakpoint
+ detection */
+
+#define BREAKPOINT {0x0b}
+
+/* If your kernel resets the pc after the trap happens you may need to
+ define this before including this file. */
+
+#define DECR_PC_AFTER_BREAK 0
+
+/* Say how long registers are. */
+
+#define REGISTER_TYPE unsigned long
+
+/* Say how much memory is needed to store a copy of the register set */
+
+#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) h8500_register_size(N)
+extern int h8500_register_size PARAMS ((int regno));
+
+#define REGISTER_SIZE 4
+
+#define REGISTER_VIRTUAL_SIZE(N) h8500_register_size(N)
+
+/* 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
+
+/* Return the GDB type object for the "standard" data type
+ of data in register N. */
+
+#define REGISTER_VIRTUAL_TYPE(N) h8500_register_virtual_type(N)
+extern struct type *h8500_register_virtual_type PARAMS ((int regno));
+
+/* Initializer for an array of names of registers.
+ Entries beyond the first NUM_REGS are ignored. */
+
+#define REGISTER_NAMES \
+ { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", \
+ "pr0","pr1","pr2","pr3","pr4","pr5","pr6","pr7", \
+ "cp", "dp", "ep", "tp", "sr", "pc"}
+
+/* Register numbers of various important registers. Note that some of
+ these values are "real" register numbers, and correspond to the
+ general registers of the machine, and some are "phony" register
+ numbers which are too large to be actual register numbers as far as
+ the user is concerned but do serve to get the desired values when
+ passed to read_register. */
+
+#define R0_REGNUM 0
+#define R1_REGNUM 1
+#define R2_REGNUM 2
+#define R3_REGNUM 3
+#define R4_REGNUM 4
+#define R5_REGNUM 5
+#define R6_REGNUM 6
+#define R7_REGNUM 7
+
+#define PR0_REGNUM 8
+#define PR1_REGNUM 9
+#define PR2_REGNUM 10
+#define PR3_REGNUM 11
+#define PR4_REGNUM 12
+#define PR5_REGNUM 13
+#define PR6_REGNUM 14
+#define PR7_REGNUM 15
+
+#define SEG_C_REGNUM 16 /* Segment registers */
+#define SEG_D_REGNUM 17
+#define SEG_E_REGNUM 18
+#define SEG_T_REGNUM 19
+
+#define CCR_REGNUM 20 /* Contains processor status */
+#define PC_REGNUM 21 /* Contains program counter */
+
+#define NUM_REGS 22
+
+#define SP_REGNUM PR7_REGNUM /* Contains address of top of stack */
+#define FP_REGNUM PR6_REGNUM /* Contains address of executing stack frame */
+
+#define PTR_SIZE (minimum_mode ? 2 : 4)
+#define PTR_MASK (minimum_mode ? 0x0000ffff : 0x00ffffff)
+
+/* Store the address of the place in which to copy the structure the
+ subroutine will return. This is called from call_function. */
+
+/*#define STORE_STRUCT_RETURN(ADDR, SP) \
+ { write_register (0, (ADDR)); abort(); }*/
+
+/* 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) \
+ memcpy (VALBUF, (char *)(REGBUF), 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) (*(CORE_ADDR *)(REGBUF))
+
+
+/* Define other aspects of the stack frame. */
+
+/* A macro that tells us whether the function invocation represented
+ by FI does not have a frame on the stack associated with it. If it
+ does not, FRAMELESS is set to 1, else 0. */
+
+#define FRAMELESS_FUNCTION_INVOCATION(FI, FRAMELESS) \
+ (FRAMELESS) = frameless_look_for_prologue(FI)
+
+/* Any function with a frame looks like this
+ SECOND ARG
+ FIRST ARG
+ RET PC
+ SAVED R2
+ SAVED R3
+ SAVED FP <-FP POINTS HERE
+ LOCALS0
+ LOCALS1 <-SP POINTS HERE
+
+ */
+
+#define INIT_EXTRA_FRAME_INFO(fromleaf, fci) ;
+/* (fci)->frame |= read_register(SEG_T_REGNUM) << 16;*/
+
+#define FRAME_CHAIN(FRAME) h8500_frame_chain(FRAME)
+struct frame_info;
+extern CORE_ADDR h8500_frame_chain PARAMS ((struct frame_info *));
+
+#define FRAME_SAVED_PC(FRAME) frame_saved_pc(FRAME)
+extern CORE_ADDR frame_saved_pc PARAMS ((struct frame_info *frame));
+
+#define FRAME_ARGS_ADDRESS(fi) ((fi)->frame)
+
+#define FRAME_LOCALS_ADDRESS(fi) ((fi)->frame)
+
+/* Set VAL to the number of args passed to frame described by FI.
+ Can set VAL to -1, meaning no way to tell. */
+
+/* We can't tell how many args there are
+ now that the C compiler delays popping them. */
+
+#define FRAME_NUM_ARGS(val,fi) (val = -1)
+
+/* Return number of bytes at start of arglist that are not really args. */
+
+#define FRAME_ARGS_SKIP 0
+
+/* Put here the code to store, into a struct frame_saved_regs,
+ the addresses of the saved registers of frame described by FRAME_INFO.
+ This includes special registers such as pc and fp saved in special
+ ways in the stack frame. sp is even more special:
+ the address we return for it IS the sp for the next frame. */
+
+#define FRAME_FIND_SAVED_REGS(frame_info, frame_saved_regs) \
+ frame_find_saved_regs(frame_info, &(frame_saved_regs))
+struct frame_saved_regs;
+extern void frame_find_saved_regs PARAMS ((struct frame_info *frame_info, struct frame_saved_regs *frame_saved_regs));
+
+
+/* Discard from the stack the innermost frame, restoring all registers. */
+
+#define POP_FRAME { h8500_pop_frame (); }
+extern void h8500_pop_frame PARAMS ((void));
+
+#define SHORT_INT_MAX 32767
+#define SHORT_INT_MIN -32768
+
+#define NAMES_HAVE_UNDERSCORE
+
+typedef unsigned short INSN_WORD;
+
+extern CORE_ADDR h8500_addr_bits_remove PARAMS ((CORE_ADDR));
+#define ADDR_BITS_REMOVE(addr) h8500_addr_bits_remove (addr)
+
+#define read_memory_short(x) (read_memory_integer(x,2) & 0xffff)
+
+#define PRINT_REGISTER_HOOK(regno) print_register_hook(regno)
+extern void print_register_hook PARAMS ((int));
+
+extern int minimum_mode;
+
+#define CALL_DUMMY_LENGTH 10
+
+/* Fake variables to make it easy to use 24 bit register pointers */
+
+#define IS_TRAPPED_INTERNALVAR h8500_is_trapped_internalvar
+extern int h8500_is_trapped_internalvar PARAMS ((char *name));
+
+#define VALUE_OF_TRAPPED_INTERNALVAR h8500_value_of_trapped_internalvar
+extern struct value * h8500_value_of_trapped_internalvar (/* struct internalvar *var */);
+
+#define SET_TRAPPED_INTERNALVAR h8500_set_trapped_internalvar
+extern void h8500_set_trapped_internalvar (/* struct internalvar *var, value newval, int bitpos, int bitsize, int offset */);
+
+extern CORE_ADDR h8500_read_sp PARAMS ((void));
+extern void h8500_write_sp PARAMS ((CORE_ADDR));
+
+extern CORE_ADDR h8500_read_fp PARAMS ((void));
+extern void h8500_write_fp PARAMS ((CORE_ADDR));
+
+extern CORE_ADDR h8500_read_pc PARAMS ((int));
+extern void h8500_write_pc PARAMS ((CORE_ADDR, int));
+
+#define TARGET_READ_SP() h8500_read_sp()
+#define TARGET_WRITE_SP(x) h8500_write_sp(x)
+
+#define TARGET_READ_PC(pid) h8500_read_pc(pid)
+#define TARGET_WRITE_PC(x,pid) h8500_write_pc(x,pid)
+
+#define TARGET_READ_FP() h8500_read_fp()
+#define TARGET_WRITE_FP(x) h8500_write_fp(x)
diff --git a/gdb/config/i386/cygwin.mh b/gdb/config/i386/cygwin.mh
new file mode 100644
index 00000000000..d93acb696cd
--- /dev/null
+++ b/gdb/config/i386/cygwin.mh
@@ -0,0 +1,6 @@
+MH_CFLAGS=
+XM_FILE=xm-cygwin.h
+XDEPFILES=ser-tcp.o
+NATDEPFILES= win32-nat.o
+NAT_FILE=../nm-empty.h
+XM_CLIBS=
diff --git a/gdb/config/i386/cygwin.mt b/gdb/config/i386/cygwin.mt
new file mode 100644
index 00000000000..4dfc0c23721
--- /dev/null
+++ b/gdb/config/i386/cygwin.mt
@@ -0,0 +1,6 @@
+# Target: Intel 386 run win32
+TDEPFILES= i386-tdep.o i387-tdep.o
+TM_FILE= tm-cygwin.h
+
+
+
diff --git a/gdb/config/i386/fbsd.mh b/gdb/config/i386/fbsd.mh
new file mode 100644
index 00000000000..499ed48f45f
--- /dev/null
+++ b/gdb/config/i386/fbsd.mh
@@ -0,0 +1,5 @@
+# Host: Intel 386 running FreeBSD
+XDEPFILES= ser-tcp.o
+NATDEPFILES= fork-child.o infptrace.o inftarg.o corelow.o core-aout.o i386b-nat.o
+XM_FILE= xm-i386bsd.h
+NAT_FILE= nm-fbsd.h
diff --git a/gdb/config/i386/fbsd.mt b/gdb/config/i386/fbsd.mt
new file mode 100644
index 00000000000..e644f1c891b
--- /dev/null
+++ b/gdb/config/i386/fbsd.mt
@@ -0,0 +1,3 @@
+# Target: Intel 386 running FreeBSD
+TDEPFILES= i386-tdep.o i387-tdep.o solib.o
+TM_FILE= tm-fbsd.h
diff --git a/gdb/config/i386/gdbserve.mt b/gdb/config/i386/gdbserve.mt
new file mode 100644
index 00000000000..d8a7cbaf43d
--- /dev/null
+++ b/gdb/config/i386/gdbserve.mt
@@ -0,0 +1,3 @@
+# Target: GDBSERVE.NLM running on a i386
+TDEPFILES= i386.o
+CPU_FILE= i386
diff --git a/gdb/config/i386/go32.mh b/gdb/config/i386/go32.mh
new file mode 100644
index 00000000000..311ee1c272b
--- /dev/null
+++ b/gdb/config/i386/go32.mh
@@ -0,0 +1,8 @@
+MH_CFLAGS=-D__GO32__ -D__MSDOS__
+XDEPFILES= go32-xdep.o
+XM_FILE= xm-go32.h
+HOST_IPC=-DDOS_IPC
+SER_HARDWIRE= ser-go32.o
+CC=i386-go32-gcc -O2 -fno-omit-frame-pointer
+
+
diff --git a/gdb/config/i386/i386aix.mh b/gdb/config/i386/i386aix.mh
new file mode 100644
index 00000000000..cea05f0a3b2
--- /dev/null
+++ b/gdb/config/i386/i386aix.mh
@@ -0,0 +1,10 @@
+# Host: IBM PS/2 (i386) running AIX PS/2
+
+XM_FILE= xm-i386aix.h
+XDEPFILES=
+
+NAT_FILE= nm-i386aix.h
+NATDEPFILES= infptrace.o inftarg.o fork-child.o corelow.o i386aix-nat.o
+
+# Use gcc. Only coff output can be debugged
+CC=gcc
diff --git a/gdb/config/i386/i386aix.mt b/gdb/config/i386/i386aix.mt
new file mode 100644
index 00000000000..12e0e1fc79a
--- /dev/null
+++ b/gdb/config/i386/i386aix.mt
@@ -0,0 +1,7 @@
+# This port, for aix ps/2 (i386), will allow you to debug the coff
+# output generated gcc-2.3.3 + gas. It will not understand IBM's
+# proprietary debug info.
+#
+# Target: IBM PS/2 (i386) running AIX PS/2
+TDEPFILES= i386-tdep.o i387-tdep.o
+TM_FILE= tm-i386aix.h
diff --git a/gdb/config/i386/i386aout.mt b/gdb/config/i386/i386aout.mt
new file mode 100644
index 00000000000..1c94ba5216c
--- /dev/null
+++ b/gdb/config/i386/i386aout.mt
@@ -0,0 +1,3 @@
+# Target: Intel 386 with a.out
+TDEPFILES= i386-tdep.o
+TM_FILE= tm-i386v.h
diff --git a/gdb/config/i386/i386bsd.mh b/gdb/config/i386/i386bsd.mh
new file mode 100644
index 00000000000..f95c6ed8b12
--- /dev/null
+++ b/gdb/config/i386/i386bsd.mh
@@ -0,0 +1,7 @@
+# Host: Intel 386 running 386BSD
+
+XM_FILE= xm-i386bsd.h
+XDEPFILES=
+
+NAT_FILE= nm-i386bsd.h
+NATDEPFILES= fork-child.o infptrace.o inftarg.o corelow.o core-aout.o i386b-nat.o
diff --git a/gdb/config/i386/i386bsd.mt b/gdb/config/i386/i386bsd.mt
new file mode 100644
index 00000000000..ef617311115
--- /dev/null
+++ b/gdb/config/i386/i386bsd.mt
@@ -0,0 +1,3 @@
+# Target: Intel 386 running BSD
+TM_FILE= tm-i386bsd.h
+TDEPFILES= i386-tdep.o
diff --git a/gdb/config/i386/i386dgux.mh b/gdb/config/i386/i386dgux.mh
new file mode 100644
index 00000000000..e05ebcd8393
--- /dev/null
+++ b/gdb/config/i386/i386dgux.mh
@@ -0,0 +1,9 @@
+# Host: Intel 386 running DGUX, cloned from SVR4
+
+XM_FILE= xm-i386v4.h
+XDEPFILES= ser-tcp.o
+# for network communication
+XM_CLIBS= -lsocket -lnsl
+
+NAT_FILE= nm-i386v4.h
+NATDEPFILES= corelow.o core-regset.o solib.o procfs.o fork-child.o i386v4-nat.o
diff --git a/gdb/config/i386/i386gnu.mh b/gdb/config/i386/i386gnu.mh
new file mode 100644
index 00000000000..4ceac7eb83d
--- /dev/null
+++ b/gdb/config/i386/i386gnu.mh
@@ -0,0 +1,31 @@
+# Host: Intel 386 running the GNU Hurd
+XDEPFILES= i387-tdep.o
+NATDEPFILES= i386gnu-nat.o gnu-nat.o fork-child.o solib.o corelow.o notify_S.o process_reply_S.o msg_reply_S.o msg_U.o exc_request_U.o exc_request_S.o
+XM_FILE= xm-i386gnu.h
+NAT_FILE= nm-gnu.h
+MH_CFLAGS = -D_GNU_SOURCE
+
+XM_CLIBS = -lshouldbeinlibc
+
+# Use our own user stubs for the msg rpcs, so we can make them time out, in
+# case the program is fucked, or we guess the wrong signal thread.
+msg-MIGUFLAGS = -D'MSG_IMPORTS=waittime 1000;'
+
+# ick
+MIG = mig
+MIGCOM = $(MIG) -cc cat - /dev/null
+
+# Reply servers need special massaging of the code mig generates, to make
+# them work correctly for error returns in some cases.
+%_reply_S.h %_reply_S.c: %_reply.defs
+ $(CPP) $(CPPFLAGS) -DSERVERPREFIX=S_ -x c $< \
+ | $(MIGCOM) -sheader $*_reply_S.h -server $*_reply_S.raw -user /dev/null -header /dev/null \
+ && $(AWK) -f $(srcdir)/reply_mig_hack.awk < $*_reply_S.raw > $*_reply_S.c
+# Normal servers
+%_S.h %_S.c: %.defs
+ $(CPP) $(CPPFLAGS) -DSERVERPREFIX=S_ -x c $< \
+ | $(MIGCOM) -sheader $*_S.h -server $*_S.c -user /dev/null -header /dev/null
+# User rpc stubs
+%_U.h %_U.c: %.defs
+ $(CPP) $(CPPFLAGS) $($*-MIGUFLAGS) -x c $< \
+ | $(MIGCOM) -sheader /dev/null -server /dev/null -user $*_U.c -header $*_U.h
diff --git a/gdb/config/i386/i386gnu.mt b/gdb/config/i386/i386gnu.mt
new file mode 100644
index 00000000000..64fb0189712
--- /dev/null
+++ b/gdb/config/i386/i386gnu.mt
@@ -0,0 +1,3 @@
+# Target: Intel 386/elf/GNU Hurd
+TDEPFILES= i386-tdep.o
+TM_FILE= tm-i386gnu.h
diff --git a/gdb/config/i386/i386lynx.mh b/gdb/config/i386/i386lynx.mh
new file mode 100644
index 00000000000..9cb086f6e39
--- /dev/null
+++ b/gdb/config/i386/i386lynx.mh
@@ -0,0 +1,11 @@
+# Host: Intel 386 running LynxOS
+
+XM_FILE= xm-i386lynx.h
+XM_CLIBS= -lbsd
+XDEPFILES= ser-tcp.o
+
+NAT_FILE= nm-i386lynx.h
+NATDEPFILES= fork-child.o infptrace.o inftarg.o corelow.o lynx-nat.o
+
+GDBSERVER_LIBS= -lbsd
+GDBSERVER_DEPFILES= low-lynx.o
diff --git a/gdb/config/i386/i386lynx.mt b/gdb/config/i386/i386lynx.mt
new file mode 100644
index 00000000000..6704b43e5b9
--- /dev/null
+++ b/gdb/config/i386/i386lynx.mt
@@ -0,0 +1,3 @@
+# Target: Intel 386 running LynxOS
+TDEPFILES= coff-solib.o i386-tdep.o i386ly-tdep.o
+TM_FILE= tm-i386lynx.h
diff --git a/gdb/config/i386/i386m3.mh b/gdb/config/i386/i386m3.mh
new file mode 100644
index 00000000000..0a83ebf7eac
--- /dev/null
+++ b/gdb/config/i386/i386m3.mh
@@ -0,0 +1,7 @@
+# Host: Intel 386 running Mach3
+
+XDEPFILES= i387-tdep.o core-aout.o
+NATDEPFILES= i386m3-nat.o m3-nat.o fork-child.o
+NAT_CLIBS= -lmachid -lnetname -lmach
+XM_FILE= xm-i386m3.h
+NAT_FILE= nm-m3.h
diff --git a/gdb/config/i386/i386m3.mt b/gdb/config/i386/i386m3.mt
new file mode 100644
index 00000000000..e985ae345d9
--- /dev/null
+++ b/gdb/config/i386/i386m3.mt
@@ -0,0 +1,3 @@
+# Target: Intel 386 with a.out under Mach 3
+TDEPFILES= i386-tdep.o
+TM_FILE= tm-i386m3.h
diff --git a/gdb/config/i386/i386mach.mh b/gdb/config/i386/i386mach.mh
new file mode 100644
index 00000000000..44766c51c52
--- /dev/null
+++ b/gdb/config/i386/i386mach.mh
@@ -0,0 +1,10 @@
+# Host: Intel 386 running Mach
+
+# This is for mach2, maybe, or is obsolete (and seems to have only
+# host and native, not target). Once we get the mach3 stuff working,
+# I think it can go away.
+
+XDEPFILES=
+XM_FILE= xm-i386mach.h
+NAT_FILE= nm-i386mach.h
+NATDEPFILES= infptrace.o inftarg.o fork-child.o i386mach-nat.o
diff --git a/gdb/config/i386/i386mk.mh b/gdb/config/i386/i386mk.mh
new file mode 100644
index 00000000000..849677cee07
--- /dev/null
+++ b/gdb/config/i386/i386mk.mh
@@ -0,0 +1,4 @@
+# Host: Intel 386 running Mach3 with OSF 1/MK
+
+XDEPFILES= os-mach3.o i386mach3-xdep.o i387-tdep.o
+XM_FILE= xm-i386osf1mk.h
diff --git a/gdb/config/i386/i386mk.mt b/gdb/config/i386/i386mk.mt
new file mode 100644
index 00000000000..fc59442ac0d
--- /dev/null
+++ b/gdb/config/i386/i386mk.mt
@@ -0,0 +1,6 @@
+# Target: Intel 386 with a.out in osf 1/mk
+TDEPFILES= i386-tdep.o
+TM_FILE= tm-i386osf1mk.h
+
+TM_CFLAGS= -I/usr/mach3/include
+TM_CLIBS= /usr/mach3/ccs/lib/libmachid.a /usr/mach3/ccs/lib/libnetname.a /usr/mach3/ccs/lib/libmach.a
diff --git a/gdb/config/i386/i386nw.mt b/gdb/config/i386/i386nw.mt
new file mode 100644
index 00000000000..3109c42149e
--- /dev/null
+++ b/gdb/config/i386/i386nw.mt
@@ -0,0 +1,3 @@
+# Target: Intel 386 running NetWare
+TDEPFILES= i386-tdep.o i387-tdep.o
+TM_FILE= tm-i386nw.h
diff --git a/gdb/config/i386/i386os9k.mt b/gdb/config/i386/i386os9k.mt
new file mode 100644
index 00000000000..5a8794db58f
--- /dev/null
+++ b/gdb/config/i386/i386os9k.mt
@@ -0,0 +1,3 @@
+# Target: Intel 386 running OS9000
+TDEPFILES= i386-tdep.o remote-os9k.o
+TM_FILE= tm-i386os9k.h
diff --git a/gdb/config/i386/i386sco.mh b/gdb/config/i386/i386sco.mh
new file mode 100644
index 00000000000..69076b54fae
--- /dev/null
+++ b/gdb/config/i386/i386sco.mh
@@ -0,0 +1,13 @@
+# Host: Intel 386 running SCO Unix (pre-SVR4)
+
+XM_FILE= xm-i386sco.h
+XDEPFILES=
+XM_CLIBS= -lPW
+
+NAT_FILE= nm-i386sco.h
+NATDEPFILES= infptrace.o inftarg.o fork-child.o corelow.o core-aout.o i386v-nat.o
+
+#msg The SCO C compiler cannot parse symtab.h when value.h has been included.
+#msg This is a bug in the compiler; the code is valid.
+#msg Therefore, you must use GCC to compile GDB on SCO machines.
+CC=gcc -D_POSIX_SOURCE=1
diff --git a/gdb/config/i386/i386sco4.mh b/gdb/config/i386/i386sco4.mh
new file mode 100644
index 00000000000..a13f99399f0
--- /dev/null
+++ b/gdb/config/i386/i386sco4.mh
@@ -0,0 +1,12 @@
+# Host: Intel 386 running SCO Unix 3.2v4
+
+XM_FILE= xm-i386sco.h
+XDEPFILES=
+XM_CLIBS= -lPW
+
+NAT_FILE= nm-i386sco4.h
+NATDEPFILES= infptrace.o inftarg.o fork-child.o corelow.o core-aout.o i386v-nat.o
+
+# The cc compiler mishandles const in cases like
+# struct type ** const (c_builtin_types[]) =
+MH_CFLAGS=-Dconst=
diff --git a/gdb/config/i386/i386sco5.mh b/gdb/config/i386/i386sco5.mh
new file mode 100644
index 00000000000..3bea87a2cdc
--- /dev/null
+++ b/gdb/config/i386/i386sco5.mh
@@ -0,0 +1,17 @@
+# Host: Intel 386 running SCO OpenServer 5
+# Much like 3.2v4, except we don't have to avoid problems with const
+
+XM_FILE= xm-i386sco.h
+
+#
+# Not all configurations of SCO OpenServer 5 come with the TCP/IP
+# runtime, but all come with the development system, so we always
+# have socket(), gethostbyname(), and friends.
+#
+XDEPFILES= ser-tcp.o
+XM_CLIBS= -lPW -lsocket
+
+NAT_FILE= nm-i386sco5.h
+NATDEPFILES= infptrace.o inftarg.o fork-child.o corefile.o core-aout.o \
+ corelow.o i386v-nat.o solib.o
+
diff --git a/gdb/config/i386/i386sco5.mt b/gdb/config/i386/i386sco5.mt
new file mode 100644
index 00000000000..54dc68d16ca
--- /dev/null
+++ b/gdb/config/i386/i386sco5.mt
@@ -0,0 +1,3 @@
+# Target: Intel 386 running SCO Open Server 5
+TDEPFILES= i386-tdep.o i387-tdep.o
+TM_FILE= tm-i386sco5.h
diff --git a/gdb/config/i386/i386sol2.mh b/gdb/config/i386/i386sol2.mh
new file mode 100644
index 00000000000..ff242940950
--- /dev/null
+++ b/gdb/config/i386/i386sol2.mh
@@ -0,0 +1,7 @@
+# Host: Intel 386 running Solaris 2 (SVR4)
+
+XM_FILE= xm-i386v4.h
+XDEPFILES=
+
+NAT_FILE= nm-i386sol2.h
+NATDEPFILES= core-regset.o procfs.o fork-child.o i386v4-nat.o corelow.o
diff --git a/gdb/config/i386/i386sol2.mt b/gdb/config/i386/i386sol2.mt
new file mode 100644
index 00000000000..80b576ffe3f
--- /dev/null
+++ b/gdb/config/i386/i386sol2.mt
@@ -0,0 +1,3 @@
+# Target: Intel 386 running SVR4
+TDEPFILES= i386-tdep.o i387-tdep.o solib.o
+TM_FILE= tm-i386sol2.h
diff --git a/gdb/config/i386/i386v.mh b/gdb/config/i386/i386v.mh
new file mode 100644
index 00000000000..d67a30f73ec
--- /dev/null
+++ b/gdb/config/i386/i386v.mh
@@ -0,0 +1,8 @@
+# Host: Intel 386 running System V
+
+XM_FILE= xm-i386v.h
+XDEPFILES=
+XM_CLIBS= -lPW
+
+NAT_FILE= nm-i386v.h
+NATDEPFILES= infptrace.o inftarg.o fork-child.o corelow.o core-aout.o i386v-nat.o
diff --git a/gdb/config/i386/i386v.mt b/gdb/config/i386/i386v.mt
new file mode 100644
index 00000000000..7242d3e8f38
--- /dev/null
+++ b/gdb/config/i386/i386v.mt
@@ -0,0 +1,3 @@
+# Target: Intel 386 running System V
+TDEPFILES= i386-tdep.o i387-tdep.o
+TM_FILE= tm-i386v.h
diff --git a/gdb/config/i386/i386v32.mh b/gdb/config/i386/i386v32.mh
new file mode 100644
index 00000000000..5b4175fa08c
--- /dev/null
+++ b/gdb/config/i386/i386v32.mh
@@ -0,0 +1,9 @@
+# Host: Intel 386 running System V release 3.2
+
+XM_FILE= xm-i386v32.h
+XDEPFILES=
+XM_CLIBS= -lPW
+
+NAT_FILE= nm-i386v.h
+NATDEPFILES= infptrace.o inftarg.o fork-child.o corelow.o core-aout.o i386v-nat.o
+
diff --git a/gdb/config/i386/i386v4.mh b/gdb/config/i386/i386v4.mh
new file mode 100644
index 00000000000..465388790b7
--- /dev/null
+++ b/gdb/config/i386/i386v4.mh
@@ -0,0 +1,9 @@
+# Host: Intel 386 running SVR4
+
+XM_FILE= xm-i386v4.h
+XDEPFILES=
+# for network communication
+XM_CLIBS= -lsocket -lnsl
+
+NAT_FILE= nm-i386v4.h
+NATDEPFILES= corelow.o core-regset.o solib.o procfs.o fork-child.o i386v4-nat.o
diff --git a/gdb/config/i386/i386v4.mt b/gdb/config/i386/i386v4.mt
new file mode 100644
index 00000000000..c22b6755985
--- /dev/null
+++ b/gdb/config/i386/i386v4.mt
@@ -0,0 +1,3 @@
+# Target: Intel 386 running SVR4
+TDEPFILES= i386-tdep.o i387-tdep.o
+TM_FILE= tm-i386v4.h
diff --git a/gdb/config/i386/i386v42mp.mh b/gdb/config/i386/i386v42mp.mh
new file mode 100644
index 00000000000..94b6c06324b
--- /dev/null
+++ b/gdb/config/i386/i386v42mp.mh
@@ -0,0 +1,11 @@
+# Host: Intel 386 running SVR4
+
+XM_FILE= xm-i386v4.h
+XDEPFILES=
+# for network communication
+XM_CLIBS= -lsocket -lnsl
+
+# we don't want nm-i386v4.h since that defines LOSING_POLL which isn't
+# appropriate for i386v42mp
+NAT_FILE= nm-i386v42mp.h
+NATDEPFILES= corelow.o core-regset.o solib.o procfs.o fork-child.o i386v4-nat.o
diff --git a/gdb/config/i386/i386v42mp.mt b/gdb/config/i386/i386v42mp.mt
new file mode 100644
index 00000000000..0b2dea8af04
--- /dev/null
+++ b/gdb/config/i386/i386v42mp.mt
@@ -0,0 +1,3 @@
+# Target: Intel 386 running SVR4.2MP
+TDEPFILES= i386-tdep.o i387-tdep.o
+TM_FILE= tm-i386v42mp.h
diff --git a/gdb/config/i386/linux.mh b/gdb/config/i386/linux.mh
new file mode 100644
index 00000000000..30de91d7d7f
--- /dev/null
+++ b/gdb/config/i386/linux.mh
@@ -0,0 +1,7 @@
+# Host: Intel 386 running GNU/Linux
+
+XM_FILE= xm-linux.h
+XDEPFILES= ser-tcp.o
+
+NAT_FILE= nm-linux.h
+NATDEPFILES= infptrace.o solib.o inftarg.o fork-child.o corelow.o core-aout.o core-regset.o i386v-nat.o i386v4-nat.o
diff --git a/gdb/config/i386/linux.mt b/gdb/config/i386/linux.mt
new file mode 100644
index 00000000000..66cc97dbde5
--- /dev/null
+++ b/gdb/config/i386/linux.mt
@@ -0,0 +1,5 @@
+# Target: Intel 386 running GNU/Linux
+TDEPFILES= i386-tdep.o i387-tdep.o
+TM_FILE= tm-linux.h
+
+GDBSERVER_DEPFILES= low-linux.o
diff --git a/gdb/config/i386/nbsd.mh b/gdb/config/i386/nbsd.mh
new file mode 100644
index 00000000000..c76b897d764
--- /dev/null
+++ b/gdb/config/i386/nbsd.mh
@@ -0,0 +1,5 @@
+# Host: Intel 386 running NetBSD
+XDEPFILES= ser-tcp.o
+NATDEPFILES= fork-child.o infptrace.o inftarg.o corelow.o i386b-nat.o
+XM_FILE= xm-nbsd.h
+NAT_FILE= nm-nbsd.h
diff --git a/gdb/config/i386/nbsd.mt b/gdb/config/i386/nbsd.mt
new file mode 100644
index 00000000000..757085074d8
--- /dev/null
+++ b/gdb/config/i386/nbsd.mt
@@ -0,0 +1,3 @@
+# Target: Intel 386 running NetBSD
+TDEPFILES= i386-tdep.o i387-tdep.o solib.o
+TM_FILE= tm-nbsd.h
diff --git a/gdb/config/i386/ncr3000.mh b/gdb/config/i386/ncr3000.mh
new file mode 100644
index 00000000000..4f60756231e
--- /dev/null
+++ b/gdb/config/i386/ncr3000.mh
@@ -0,0 +1,16 @@
+# Host: NCR 3000 (Intel 386 running SVR4)
+
+# The NCR 3000 ships with a MetaWare compiler installed as /bin/cc.
+# This compiler not only emits obnoxious copyright messages every time
+# you run it, but it chokes and dies on a whole bunch of GNU source
+# files. Default to using the AT&T compiler installed in /usr/ccs/ATT/cc.
+# Unfortunately though, the AT&T compiler sometimes generates code that
+# the assembler barfs on if -g is used, so disable it by default as well.
+CC = /usr/ccs/ATT/cc
+CFLAGS =
+
+XM_FILE= xm-i386v4.h
+XDEPFILES=
+
+NAT_FILE= nm-i386v4.h
+NATDEPFILES= corelow.o core-regset.o procfs.o fork-child.o i386v4-nat.o
diff --git a/gdb/config/i386/ncr3000.mt b/gdb/config/i386/ncr3000.mt
new file mode 100644
index 00000000000..0bbf9b369cb
--- /dev/null
+++ b/gdb/config/i386/ncr3000.mt
@@ -0,0 +1,3 @@
+# Target: Intel 386 running SVR4
+TDEPFILES= i386-tdep.o i387-tdep.o solib.o
+TM_FILE= tm-i386v4.h
diff --git a/gdb/config/i386/nm-fbsd.h b/gdb/config/i386/nm-fbsd.h
new file mode 100644
index 00000000000..727623c0a40
--- /dev/null
+++ b/gdb/config/i386/nm-fbsd.h
@@ -0,0 +1,98 @@
+/* Native-dependent definitions for Intel 386 running BSD Unix, for GDB.
+ Copyright 1986, 1987, 1989, 1992, 1996 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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
+
+#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*
+
+/* make structure definitions match up with those expected in solib.c */
+#define link_object sod
+#define lo_name sod_name
+#define lo_library sod_library
+#define lo_unused sod_reserved
+#define lo_major sod_major
+#define lo_minor sod_minor
+#define lo_next sod_next
+
+#define link_map so_map
+#define lm_addr som_addr
+#define lm_name som_path
+#define lm_next som_next
+#define lm_lop som_sod
+#define lm_lob som_sodbase
+#define lm_rwt som_write
+#define lm_ld som_dynamic
+#define lm_lpd som_spd
+
+#define link_dynamic_2 section_dispatch_table
+#define ld_loaded sdt_loaded
+#define ld_need sdt_sods
+#define ld_rules sdt_filler1
+#define ld_got sdt_got
+#define ld_plt sdt_plt
+#define ld_rel sdt_rel
+#define ld_hash sdt_hash
+#define ld_stab sdt_nzlist
+#define ld_stab_hash sdt_filler2
+#define ld_buckets sdt_buckets
+#define ld_symbols sdt_strings
+#define ld_symb_size sdt_str_sz
+#define ld_text sdt_text_sz
+#define ld_plt_sz sdt_plt_sz
+
+#define rtc_symb rt_symbol
+#define rtc_sp rt_sp
+#define rtc_next rt_next
+
+#define ld_debug so_debug
+#define ldd_version dd_version
+#define ldd_in_debugger dd_in_debugger
+#define ldd_sym_loaded dd_sym_loaded
+#define ldd_bp_addr dd_bpt_addr
+#define ldd_bp_inst dd_bpt_shadow
+#define ldd_cp dd_cc
+
+#define link_dynamic _dynamic
+#define ld_version d_version
+#define ldd d_debug
+#define ld_un d_un
+#define ld_2 d_sdt
+
+/* Return sizeof user struct to callers in less machine dependent routines */
+
+#define KERNEL_U_SIZE kernel_u_size()
+extern int kernel_u_size PARAMS ((void));
+
+#endif /* NM_FREEBSD_H */
diff --git a/gdb/config/i386/nm-gnu.h b/gdb/config/i386/nm-gnu.h
new file mode 100644
index 00000000000..95f25a52e3d
--- /dev/null
+++ b/gdb/config/i386/nm-gnu.h
@@ -0,0 +1,22 @@
+/* Native-dependent definitions for Intel 386 running the GNU Hurd
+ Copyright 1994, 1995 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Include the generic hurd definitions. */
+
+#include "nm-gnu.h"
diff --git a/gdb/config/i386/nm-i386aix.h b/gdb/config/i386/nm-i386aix.h
new file mode 100644
index 00000000000..42403939637
--- /dev/null
+++ b/gdb/config/i386/nm-i386aix.h
@@ -0,0 +1,42 @@
+/* Native support for i386 aix ps/2.
+ Copyright 1986, 1987, 1989, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/*
+ * Changes for IBM AIX PS/2 by Minh Tran-Le (tranle@intellicorp.com)
+ * Revision: 5-May-93 00:11:35
+ */
+
+#ifndef NM_I386AIX_H
+#define NM_I386AIX_H 1
+
+/* 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 (); }
+
+/* This is the amount to subtract from u.u_ar0
+ to get the offset in the core file of the register values. */
+#undef KERNEL_U_ADDR
+#define KERNEL_U_ADDR 0xf03fd000
+
+/* Override copies of {fetch,store}_inferior_registers in infptrace.c. */
+#define FETCH_INFERIOR_REGISTERS
+
+#endif /* NM_I386AIX_H */
diff --git a/gdb/config/i386/nm-i386bsd.h b/gdb/config/i386/nm-i386bsd.h
new file mode 100644
index 00000000000..7366f2d17bf
--- /dev/null
+++ b/gdb/config/i386/nm-i386bsd.h
@@ -0,0 +1,39 @@
+/* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef NM_I386BSD_H
+#define NM_I386BSD_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 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_I386BSD_H */
diff --git a/gdb/config/i386/nm-i386lynx.h b/gdb/config/i386/nm-i386lynx.h
new file mode 100644
index 00000000000..e29821f29dd
--- /dev/null
+++ b/gdb/config/i386/nm-i386lynx.h
@@ -0,0 +1,25 @@
+/* Native-dependent definitions for Intel 386 running LynxOS.
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef NM_I386LYNX_H
+#define NM_I386LYNX_H
+
+#include "nm-lynx.h"
+
+#endif /* NM_I386LYNX_H */
diff --git a/gdb/config/i386/nm-i386mach.h b/gdb/config/i386/nm-i386mach.h
new file mode 100644
index 00000000000..f01d2b142b1
--- /dev/null
+++ b/gdb/config/i386/nm-i386mach.h
@@ -0,0 +1,26 @@
+/* Native definitions for Mach on an Intel 386
+ Copyright (C) 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Do implement the attach and detach commands. */
+/* #define ATTACH_DETACH 1 */
+
+/* Override copies of {fetch,store}_inferior_registers in infptrace.c. */
+#define FETCH_INFERIOR_REGISTERS
+
+#define CHILD_PREPARE_TO_STORE() read_register_bytes (0, NULL, REGISTER_BYTES)
diff --git a/gdb/config/i386/nm-i386sco.h b/gdb/config/i386/nm-i386sco.h
new file mode 100644
index 00000000000..33ab6de4060
--- /dev/null
+++ b/gdb/config/i386/nm-i386sco.h
@@ -0,0 +1,41 @@
+/* Native support for i386.
+ Copyright 1986, 1987, 1989, 1992 Free Software Foundation, Inc.
+ Changes for 80386 by Pace Willisson (pace@prep.ai.mit.edu), July 1988.
+
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#if 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.
+ On the 386, unfortunately this code is host-dependent (and lives
+ in the i386-xdep.c file), so we can't
+ do this unless we *know* we aren't cross-debugging. FIXME.
+ */
+#define FLOAT_INFO { i386_float_info (); }
+#endif /*0*/
+
+#define REGISTER_U_ADDR(addr, blockend, regno) \
+ (addr) = i386_register_u_addr ((blockend),(regno));
+
+extern int
+i386_register_u_addr PARAMS ((int, int));
+
+/* When calling functions on SCO, sometimes we get an error writing some
+ of the segment registers. This would appear to be a kernel
+ bug/non-feature. */
+#define CANNOT_STORE_REGISTER(regno) ((regno) == 14 || (regno) == 15)
diff --git a/gdb/config/i386/nm-i386sco4.h b/gdb/config/i386/nm-i386sco4.h
new file mode 100644
index 00000000000..41daef5b926
--- /dev/null
+++ b/gdb/config/i386/nm-i386sco4.h
@@ -0,0 +1,32 @@
+/* Native support for SCO 3.2v4.
+ Copyright 1993 Free Software Foundation, Inc.
+ Contributed by Cygnus Support. By Ian Lance Taylor
+ <ian@cygnus.com> based on work by Martin Walker <maw@netcom.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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* SCO 3.2v4 is actually just like SCO 3.2v2, except that it
+ additionally supports attaching to a process. */
+
+#include "i386/nm-i386sco.h"
+
+#define ATTACH_DETACH
+
+/* SCO, in its wisdom, does not provide <sys/ptrace.h>. infptrace.c
+ does not have defaults for these values. */
+#define PTRACE_ATTACH 10
+#define PTRACE_DETACH 11
diff --git a/gdb/config/i386/nm-i386sco5.h b/gdb/config/i386/nm-i386sco5.h
new file mode 100644
index 00000000000..10e749ba1ff
--- /dev/null
+++ b/gdb/config/i386/nm-i386sco5.h
@@ -0,0 +1,39 @@
+/* Native support for SCO OpenServer 5
+ Copyright 1996, 1998 Free Software Foundation, Inc.
+ Re-written by J. Kean Johnston <jkj@sco.com>.
+ Originally written by Robert Lipe <robertl@dgii.com>, based on
+ work by Ian Lance Taylor <ian@cygnus.com> and
+ Martin Walker <maw@netcom.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. */
+
+/* Basically, its a lot like the older versions ... */
+#include "i386/nm-i386sco.h"
+
+/* ... but it can do a lot of SVR4 type stuff too. */
+#define SVR4_SHARED_LIBS
+#include "solib.h" /* Pick up shared library support */
+
+#define ATTACH_DETACH
+
+/* SCO does not provide <sys/ptrace.h>. infptrace.c does not
+ have defaults for these values. */
+
+#define PTRACE_ATTACH 10
+#define PTRACE_DETACH 11
+
+
diff --git a/gdb/config/i386/nm-i386sol2.h b/gdb/config/i386/nm-i386sol2.h
new file mode 100644
index 00000000000..2ae966ca52a
--- /dev/null
+++ b/gdb/config/i386/nm-i386sol2.h
@@ -0,0 +1,35 @@
+/* Native support for i386 running Solaris 2.
+ Copyright 1998 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "nm-sysv4.h"
+
+#ifdef HAVE_THREAD_DB_LIB
+
+#ifdef __STDC__
+struct objfile;
+#endif
+
+#define target_new_objfile(OBJFILE) sol_thread_new_objfile (OBJFILE)
+
+void sol_thread_new_objfile PARAMS ((struct objfile *objfile));
+
+#define FIND_NEW_THREADS sol_find_new_threads
+void sol_find_new_threads PARAMS ((void));
+
+#endif
diff --git a/gdb/config/i386/nm-i386v.h b/gdb/config/i386/nm-i386v.h
new file mode 100644
index 00000000000..8e6877e7a44
--- /dev/null
+++ b/gdb/config/i386/nm-i386v.h
@@ -0,0 +1,36 @@
+/* Native support for i386.
+ Copyright 1986, 1987, 1989, 1992 Free Software Foundation, Inc.
+ Changes for 80386 by Pace Willisson (pace@prep.ai.mit.edu), July 1988.
+
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#if 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.
+ On the 386, unfortunately this code is host-dependent (and lives
+ in the i386-xdep.c file), so we can't
+ do this unless we *know* we aren't cross-debugging. FIXME.
+ */
+#define FLOAT_INFO { i386_float_info (); }
+#endif /*0*/
+
+#define REGISTER_U_ADDR(addr, blockend, regno) \
+ (addr) = i386_register_u_addr ((blockend),(regno));
+
+extern int
+i386_register_u_addr PARAMS ((int, int));
diff --git a/gdb/config/i386/nm-i386v4.h b/gdb/config/i386/nm-i386v4.h
new file mode 100644
index 00000000000..8722a40b131
--- /dev/null
+++ b/gdb/config/i386/nm-i386v4.h
@@ -0,0 +1,24 @@
+/* Native support for i386 running SVR4.
+ Copyright 1986, 1987, 1989, 1992, 1996 Free Software Foundation, Inc.
+ Changes for 80386 by Pace Willisson (pace@prep.ai.mit.edu), July 1988.
+
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "nm-sysv4.h"
+
+/* Poll causes GDB to hang, at least under Unixware 1.1.2. */
+#define LOSING_POLL
diff --git a/gdb/config/i386/nm-i386v42mp.h b/gdb/config/i386/nm-i386v42mp.h
new file mode 100644
index 00000000000..6ffd128d4b7
--- /dev/null
+++ b/gdb/config/i386/nm-i386v42mp.h
@@ -0,0 +1,22 @@
+/* Native support for i386 running SVR4.
+ Copyright 1986, 1987, 1989, 1992, 1996 Free Software Foundation, Inc.
+ Changes for 80386 by Pace Willisson (pace@prep.ai.mit.edu), July 1988.
+
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "nm-sysv4.h"
+
diff --git a/gdb/config/i386/nm-linux.h b/gdb/config/i386/nm-linux.h
new file mode 100644
index 00000000000..ad0b8db716c
--- /dev/null
+++ b/gdb/config/i386/nm-linux.h
@@ -0,0 +1,73 @@
+/* Native support for GNU/Linux, for GDB, the GNU debugger.
+ Copyright (C) 1986, 1987, 1989, 1992, 1996, 1998
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef NM_LINUX_H
+#define NM_LINUX_H
+
+#include "i386/nm-i386v.h"
+
+/* Return sizeof user struct to callers in less machine dependent routines */
+
+#define KERNEL_U_SIZE kernel_u_size()
+extern int kernel_u_size PARAMS ((void));
+
+/* Tell gdb that we can attach and detach other processes */
+#define ATTACH_DETACH
+
+#define U_REGS_OFFSET 0
+
+/* GNU/Linux supports the 386 hardware debugging registers. */
+
+#define TARGET_HAS_HARDWARE_WATCHPOINTS
+
+#define TARGET_CAN_USE_HARDWARE_WATCHPOINT(type, cnt, ot) 1
+
+/* After a watchpoint trap, the PC points to the instruction after
+ the one that caused the trap. Therefore we don't need to step over it.
+ But we do need to reset the status register to avoid another trap. */
+#define HAVE_CONTINUABLE_WATCHPOINT
+
+#define STOPPED_BY_WATCHPOINT(W) \
+ i386_stopped_by_watchpoint (inferior_pid)
+
+/* Use these macros for watchpoint insertion/removal. */
+
+#define target_insert_watchpoint(addr, len, type) \
+ i386_insert_watchpoint (inferior_pid, addr, len, type)
+
+#define target_remove_watchpoint(addr, len, type) \
+ i386_remove_watchpoint (inferior_pid, addr, len)
+
+/* We define this if link.h is available, because with ELF we use SVR4 style
+ shared libraries. */
+
+#ifdef HAVE_LINK_H
+#define SVR4_SHARED_LIBS
+#include "solib.h" /* Support for shared libraries. */
+#endif
+
+extern CORE_ADDR
+i386_stopped_by_watchpoint PARAMS ((int));
+extern int
+i386_insert_watchpoint PARAMS ((int pid, CORE_ADDR addr, int len, int rw));
+extern int
+i386_remove_watchpoint PARAMS ((int pid, CORE_ADDR addr, int len));
+
+#endif /* #ifndef NM_LINUX_H */
diff --git a/gdb/config/i386/nm-m3.h b/gdb/config/i386/nm-m3.h
new file mode 100644
index 00000000000..51270917422
--- /dev/null
+++ b/gdb/config/i386/nm-m3.h
@@ -0,0 +1,22 @@
+/* Native-dependent definitions for Intel 386 running Mach 3.
+ Copyright 1994 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Include the generic Mach 3 definitions. */
+
+#include "nm-m3.h"
diff --git a/gdb/config/i386/nm-nbsd.h b/gdb/config/i386/nm-nbsd.h
new file mode 100644
index 00000000000..b59fec68214
--- /dev/null
+++ b/gdb/config/i386/nm-nbsd.h
@@ -0,0 +1,34 @@
+/* Native-dependent definitions for Intel 386 running NetBSD, for GDB.
+ Copyright 1986, 1987, 1989, 1992, 1994 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef NM_NBSD_H
+#define NM_NBSD_H
+
+/* Get generic NetBSD native definitions. */
+#include "nm-nbsd.h"
+
+/* #define 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));
+
+#endif /* NM_NBSD_H */
diff --git a/gdb/config/i386/nm-ptx4.h b/gdb/config/i386/nm-ptx4.h
new file mode 100644
index 00000000000..5e6cd569f8c
--- /dev/null
+++ b/gdb/config/i386/nm-ptx4.h
@@ -0,0 +1,62 @@
+/* Definitions to make GDB run on a Sequent Symmetry under ptx
+ with Weitek 1167 and i387 support.
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "nm-sysv4.h"
+
+#undef USE_PROC_FS
+
+#include "nm-symmetry.h"
+
+#define PTRACE_READ_REGS(pid,regaddr) mptrace (XPT_RREGS, (pid), (regaddr), 0)
+#define PTRACE_WRITE_REGS(pid,regaddr) \
+ mptrace (XPT_WREGS, (pid), (regaddr), 0)
+
+/* Override copies of {fetch,store}_inferior_registers in infptrace.c. */
+
+#define FETCH_INFERIOR_REGISTERS
+
+/* We must fetch all the regs before storing, since we store all at once. */
+
+#define CHILD_PREPARE_TO_STORE() read_register_bytes (0, NULL, REGISTER_BYTES)
+
+#define CHILD_WAIT
+struct target_waitstatus;
+extern int child_wait PARAMS ((int, struct target_waitstatus *));
+
+/*
+ * ptx does attach as of ptx version 2.1. Prior to that, the interface
+ * exists but does not work.
+ *
+ * FIXME: Using attach/detach requires using the ptx MPDEBUGGER
+ * interface. There are still problems with that, so for now don't
+ * enable attach/detach. If you turn it on anyway, it will mostly
+ * work, but has a number of bugs. -fubar, 2/94.
+ */
+/*#define ATTACH_DETACH 1*/
+#undef ATTACH_DETACH
+#define PTRACE_ATTACH XPT_DEBUG
+#define PTRACE_DETACH XPT_UNDEBUG
+/*
+ * The following drivel is needed because there are two ptrace-ish
+ * calls on ptx: ptrace() and mptrace(), each of which does about half
+ * of the ptrace functions.
+ */
+#define PTRACE_ATTACH_CALL(pid) ptx_do_attach(pid)
+#define PTRACE_DETACH_CALL(pid, signo) ptx_do_detach(pid, signo)
diff --git a/gdb/config/i386/nm-sun386.h b/gdb/config/i386/nm-sun386.h
new file mode 100644
index 00000000000..f7a904b4f1a
--- /dev/null
+++ b/gdb/config/i386/nm-sun386.h
@@ -0,0 +1,27 @@
+/* Native support for Sun 386i, for GDB, the GNU debugger.
+ Copyright (C) 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Do implement the attach and detach commands. */
+
+#define ATTACH_DETACH
+
+/* Override copies of {fetch,store}_inferior_registers in infptrace.c. */
+#define FETCH_INFERIOR_REGISTERS
+
+#define CHILD_PREPARE_TO_STORE() read_register_bytes (0, NULL, REGISTER_BYTES)
diff --git a/gdb/config/i386/nm-symmetry.h b/gdb/config/i386/nm-symmetry.h
new file mode 100644
index 00000000000..80cf09779df
--- /dev/null
+++ b/gdb/config/i386/nm-symmetry.h
@@ -0,0 +1,46 @@
+/* Definitions to make GDB run on a Sequent Symmetry under dynix 3.0,
+ with Weitek 1167 and i387 support.
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Override copies of {fetch,store}_inferior_registers in infptrace.c. */
+
+#define FETCH_INFERIOR_REGISTERS
+
+/* We must fetch all the regs before storing, since we store all at once. */
+
+#define CHILD_PREPARE_TO_STORE() read_register_bytes (0, NULL, REGISTER_BYTES)
+
+#ifdef _SEQUENT_
+#define CHILD_WAIT
+extern int child_wait PARAMS ((int, struct target_waitstatus *));
+#endif
+
+/* This is the amount to subtract from u.u_ar0
+ to get the offset in the core file of the register values. */
+
+#ifdef _SEQUENT_
+#include <sys/param.h>
+#include <sys/user.h>
+#include <sys/mc_vmparam.h>
+/* VA_UAREA is defined in <sys/mc_vmparam.h>, and is dependant upon
+ sizeof(struct user) */
+#define KERNEL_U_ADDR (VA_UAREA) /* ptx */
+#else
+#define KERNEL_U_ADDR (0x80000000 - (UPAGES * NBPG)) /* dynix */
+#endif
diff --git a/gdb/config/i386/ptx.mh b/gdb/config/i386/ptx.mh
new file mode 100644
index 00000000000..e623538e156
--- /dev/null
+++ b/gdb/config/i386/ptx.mh
@@ -0,0 +1,7 @@
+# Host: Sequent Symmetry running ptx 1.3, with Weitek 1167 or i387
+
+XM_FILE= xm-ptx.h
+XDEPFILES= inftarg.o fork-child.o symm-nat.o corelow.o core-aout.o
+XM_CLIBS= -lPW -lseq
+
+NAT_FILE= nm-symmetry.h
diff --git a/gdb/config/i386/ptx.mt b/gdb/config/i386/ptx.mt
new file mode 100644
index 00000000000..757df3328fc
--- /dev/null
+++ b/gdb/config/i386/ptx.mt
@@ -0,0 +1,3 @@
+# Target: Sequent Symmetry running ptx 2.0, with Weitek 1167 or i387.
+TDEPFILES= symm-tdep.o i387-tdep.o i386-tdep.o
+TM_FILE= tm-ptx.h
diff --git a/gdb/config/i386/ptx4.mh b/gdb/config/i386/ptx4.mh
new file mode 100644
index 00000000000..7b9d11b0c85
--- /dev/null
+++ b/gdb/config/i386/ptx4.mh
@@ -0,0 +1,7 @@
+# Host: Sequent Symmetry running ptx 1.3, with Weitek 1167 or i387
+
+XM_FILE= xm-ptx4.h
+XDEPFILES= inftarg.o fork-child.o symm-nat.o corelow.o core-aout.o solib.o core-regset.o
+XM_CLIBS= -lseq
+
+NAT_FILE= nm-ptx4.h
diff --git a/gdb/config/i386/ptx4.mt b/gdb/config/i386/ptx4.mt
new file mode 100644
index 00000000000..f3478091996
--- /dev/null
+++ b/gdb/config/i386/ptx4.mt
@@ -0,0 +1,3 @@
+# Target: Sequent Symmetry running ptx 4.0, with Weitek 1167 or i387.
+TDEPFILES= symm-tdep.o i387-tdep.o i386-tdep.o
+TM_FILE= tm-ptx4.h
diff --git a/gdb/config/i386/sun386.mh b/gdb/config/i386/sun386.mh
new file mode 100644
index 00000000000..d2496610b17
--- /dev/null
+++ b/gdb/config/i386/sun386.mh
@@ -0,0 +1,5 @@
+# Host: Sun 386i
+XDEPFILES=
+XM_FILE= xm-sun386.h
+NAT_FILE= nm-sun386.h
+NATDEPFILES= infptrace.o inftarg.o fork-child.o sun386-nat.o
diff --git a/gdb/config/i386/sun386.mt b/gdb/config/i386/sun386.mt
new file mode 100644
index 00000000000..665ca643fd5
--- /dev/null
+++ b/gdb/config/i386/sun386.mt
@@ -0,0 +1,3 @@
+# Target: Sun 386i target configuration file.
+TDEPFILES= i386-tdep.o solib.o
+TM_FILE= tm-sun386.h
diff --git a/gdb/config/i386/symmetry.mh b/gdb/config/i386/symmetry.mh
new file mode 100644
index 00000000000..69c05bc1db3
--- /dev/null
+++ b/gdb/config/i386/symmetry.mh
@@ -0,0 +1,5 @@
+# Host: Sequent Symmetry running Dynix 3.0, with Weitek 1167 or i387.
+XDEPFILES=
+XM_FILE= xm-symmetry.h
+NAT_FILE= nm-symmetry.h
+NATDEPFILES= inftarg.o fork-child.o corelow.o core-aout.o symm-nat.o
diff --git a/gdb/config/i386/symmetry.mt b/gdb/config/i386/symmetry.mt
new file mode 100644
index 00000000000..a3dba70bd82
--- /dev/null
+++ b/gdb/config/i386/symmetry.mt
@@ -0,0 +1,3 @@
+# Target: Sequent Symmetry running Dynix 3.0, with Weitek 1167 or i387.
+TDEPFILES= i386-tdep.o symm-tdep.o i387-tdep.o
+TM_FILE= tm-symmetry.h
diff --git a/gdb/config/i386/tm-cygwin.h b/gdb/config/i386/tm-cygwin.h
new file mode 100644
index 00000000000..b1ad894aa3a
--- /dev/null
+++ b/gdb/config/i386/tm-cygwin.h
@@ -0,0 +1,127 @@
+/* Macro definitions for i386 running under the win32 API Unix.
+ Copyright 1995, 1996 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+
+#include "i386/tm-i386v.h"
+
+#undef MAX_REGISTER_RAW_SIZE
+#undef MAX_REGISTER_VIRTUAL_SIZE
+#undef NUM_REGS
+#undef REGISTER_BYTE
+#undef REGISTER_BYTES
+#undef REGISTER_CONVERTIBLE
+#undef REGISTER_CONVERT_TO_RAW
+#undef REGISTER_CONVERT_TO_VIRTUAL
+#undef REGISTER_NAMES
+#undef REGISTER_RAW_SIZE
+#undef REGISTER_VIRTUAL_SIZE
+#undef REGISTER_VIRTUAL_TYPE
+
+/* Number of machine registers */
+
+#define NUM_REGS 24
+
+/* 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", \
+ "st", "st(1)","st(2)","st(3)",\
+ "st(4)","st(5)","st(6)","st(7)",}
+
+#define FP0_REGNUM 16
+
+/* Total amount of space needed to store our copies of the machine's
+ register state, the array `registers'. */
+
+#define REGISTER_BYTES (16 * 4 + 8 * 10)
+
+/* Index within `registers' of the first byte of the space for
+ register N. */
+
+#define REGISTER_BYTE(N) (((N) < 16) ? (N) * 4 : (((N) - 16) * 10) + (16 * 4))
+
+/* Number of bytes of storage in the actual machine representation
+ for register N. */
+
+#define REGISTER_RAW_SIZE(N) (((N) < 16) ? 4 : 10)
+
+/* Number of bytes of storage in the program's representation
+ for register N. */
+
+#define REGISTER_VIRTUAL_SIZE(N) (((N) < 16) ? 4 : 10)
+
+/* Largest value REGISTER_RAW_SIZE can have. */
+
+#define MAX_REGISTER_RAW_SIZE 10
+
+/* Largest value REGISTER_VIRTUAL_SIZE can have. */
+
+#define MAX_REGISTER_VIRTUAL_SIZE 10
+
+/* Nonzero if register N requires conversion
+ from raw format to virtual format. */
+
+#define REGISTER_CONVERTIBLE(N) \
+ ((N < FP0_REGNUM) ? 0 : 1)
+
+/* Convert data from raw format for register REGNUM in buffer FROM
+ to virtual format with type TYPE in buffer TO. */
+extern void
+i387_to_double PARAMS ((char *, char *));
+
+
+#define REGISTER_CONVERT_TO_VIRTUAL(REGNUM,TYPE,FROM,TO) \
+{ \
+ double val; \
+ i387_to_double ((FROM), (char *)&val); \
+ store_floating ((TO), TYPE_LENGTH (TYPE), val); \
+}
+
+extern void
+double_to_i387 PARAMS ((char *, char *));
+
+#define REGISTER_CONVERT_TO_RAW(TYPE,REGNUM,FROM,TO) \
+{ \
+ double val = extract_floating ((FROM), TYPE_LENGTH (TYPE)); \
+ double_to_i387((char *)&val, (TO)); \
+}
+
+/* Return the GDB type object for the "standard" data type
+ of data in register N. */
+
+#define REGISTER_VIRTUAL_TYPE(N) \
+ ((N < FP0_REGNUM) ? builtin_type_int : \
+ builtin_type_double)
+
+#define NAMES_HAVE_UNDERSCORE
+
+#define IN_SOLIB_CALL_TRAMPOLINE(pc, name) skip_trampoline_code (pc, name)
+#define SKIP_TRAMPOLINE_CODE(pc) skip_trampoline_code (pc, 0)
+extern CORE_ADDR skip_trampoline_code PARAMS ((CORE_ADDR pc, char *name));
+
+extern char *cygwin_pid_to_str PARAMS ((int pid));
+#define target_pid_to_str(PID) cygwin_pid_to_str (PID)
diff --git a/gdb/config/i386/tm-fbsd.h b/gdb/config/i386/tm-fbsd.h
new file mode 100644
index 00000000000..9933e10a60f
--- /dev/null
+++ b/gdb/config/i386/tm-fbsd.h
@@ -0,0 +1,32 @@
+/* Target macro definitions for i386 running FreeBSD
+ Copyright (C) 1997 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 "i386/tm-i386bsd.h"
+
+
+#undef NUM_REGS
+#define NUM_REGS 14
+
+
+#undef IN_SOLIB_CALL_TRAMPOLINE
+#define IN_SOLIB_CALL_TRAMPOLINE(pc, name) STREQ (name, "_DYNAMIC")
+
+
+extern i386_float_info ();
+#define FLOAT_INFO i386_float_info ()
diff --git a/gdb/config/i386/tm-i386.h b/gdb/config/i386/tm-i386.h
new file mode 100644
index 00000000000..e2039e5fbfa
--- /dev/null
+++ b/gdb/config/i386/tm-i386.h
@@ -0,0 +1,307 @@
+/* Macro definitions for GDB on an Intel i[345]86.
+ Copyright (C) 1995, 1996 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 TM_I386_H
+#define TM_I386_H 1
+
+#ifdef __STDC__ /* Forward decl's for prototypes */
+struct frame_info;
+struct frame_saved_regs;
+struct type;
+#endif
+
+#define TARGET_BYTE_ORDER LITTLE_ENDIAN
+
+/* Used for example in valprint.c:print_floating() to enable checking
+ for NaN's */
+
+#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. */
+
+#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));}
+
+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 some instructions. */
+
+#define SAVED_PC_AFTER_CALL(frame) (read_memory_integer (read_register (SP_REGNUM), 4))
+
+/* Stack grows downward. */
+
+#define INNER_THAN(lhs,rhs) ((lhs) < (rhs))
+
+/* 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
+
+/* Say how long (ordinary) registers are. This is a piece of bogosity
+ used in push_word and a few other places; REGISTER_RAW_SIZE is the
+ real way to know how big a register is. */
+
+#define REGISTER_SIZE 4
+
+/* Number of machine registers */
+
+#define NUM_FREGS 0 /*8*/ /* Number of FP regs */
+#define NUM_REGS (16 + NUM_FREGS) /* Basic i*86 regs + FP regs */
+
+/* Initializer for an array of names of registers. There should be at least
+ NUM_REGS strings in this initializer. Any excess ones are simply ignored.
+ The order of the first 8 registers must match the compiler's numbering
+ scheme (which is the same as the 386 scheme) and also regmap in the various
+ *-nat.c files. */
+
+#define REGISTER_NAMES { "eax", "ecx", "edx", "ebx", \
+ "esp", "ebp", "esi", "edi", \
+ "eip", "eflags", "cs", "ss", \
+ "ds", "es", "fs", "gs", \
+ "st0", "st1", "st2", "st3", \
+ "st4", "st5", "st6", "st7", \
+ }
+
+/* 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 /* (ebp) Contains address of executing stack frame */
+#define SP_REGNUM 4 /* (usp) Contains address of top of stack */
+#define PC_REGNUM 8 /* (eip) Contains program counter */
+#define PS_REGNUM 9 /* (ps) Contains processor status */
+
+#define FP0_REGNUM 16 /* (st0) 387 register */
+#define FPC_REGNUM 25 /* 80387 control register */
+
+/* Total amount of space needed to store our copies of the machine's register
+ state, the array `registers'. */
+
+#define REGISTER_BYTES ((NUM_REGS - NUM_FREGS)*4 + NUM_FREGS*10)
+
+/* Index within `registers' of the first byte of the space for register N. */
+
+#define REGISTER_BYTE(N) \
+ (((N) < FP0_REGNUM) ? ((N) * 4) : ((((N) - FP0_REGNUM) * 10) + 64))
+
+/* Number of bytes of storage in the actual machine representation for
+ register N. All registers are 4 bytes, except 387 st(0) - st(7),
+ which are 80 bits each. */
+
+#define REGISTER_RAW_SIZE(N) (((N) < FP0_REGNUM) ? 4 : 10)
+
+/* Largest value REGISTER_RAW_SIZE can have. */
+
+#define MAX_REGISTER_RAW_SIZE 10
+
+/* Number of bytes of storage in the program's representation
+ for register N. */
+
+#define REGISTER_VIRTUAL_SIZE(N) (((N) < FP0_REGNUM) ? 4 : 8)
+
+/* Largest value REGISTER_VIRTUAL_SIZE can have. */
+
+#define MAX_REGISTER_VIRTUAL_SIZE 8
+
+/* Return the GDB type object for the "standard" data type of data in
+ register N. 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) \
+ : (((N) < FP0_REGNUM) \
+ ? builtin_type_int \
+ : builtin_type_double))
+
+/* Store the address of the place in which to copy the structure the
+ subroutine will return. This is called from call_function. */
+
+#define STORE_STRUCT_RETURN(ADDR, SP) \
+ { char buf[REGISTER_SIZE]; \
+ (SP) -= sizeof (ADDR); \
+ store_address (buf, sizeof (ADDR), ADDR); \
+ write_memory ((SP), buf, 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) \
+ i386_extract_return_value ((TYPE),(REGBUF),(VALBUF))
+
+extern void i386_extract_return_value PARAMS ((struct type *, char [], char *));
+
+/* Write into appropriate registers a function return value of type TYPE, given
+ in virtual format. */
+
+#define STORE_RETURN_VALUE(TYPE,VALBUF) \
+ { \
+ if (TYPE_CODE (TYPE) == TYPE_CODE_FLT) \
+ write_register_bytes (REGISTER_BYTE (FP0_REGNUM), (VALBUF), \
+ TYPE_LENGTH (TYPE)); \
+ else \
+ write_register_bytes (0, (VALBUF), TYPE_LENGTH (TYPE)); \
+ }
+
+/* Extract from an array REGBUF containing the (raw) register state the address
+ in which a function should return its structure value, as a CORE_ADDR (or an
+ expression that can be used as one). */
+
+#define EXTRACT_STRUCT_VALUE_ADDRESS(REGBUF) (*(int *)(REGBUF))
+
+/* 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. */
+
+#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. */
+
+#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. */
+
+#define FRAME_SAVED_PC(FRAME) \
+ (((FRAME)->signal_handler_caller \
+ ? sigtramp_saved_pc (FRAME) \
+ : read_memory_integer ((FRAME)->frame + 4, 4)) \
+ )
+
+extern CORE_ADDR sigtramp_saved_pc PARAMS ((struct frame_info *));
+
+#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, which is typical now that the C compiler delays popping them. */
+
+#define FRAME_NUM_ARGS(numargs, fi) (numargs) = i386_frame_num_args(fi)
+
+extern int i386_frame_num_args PARAMS ((struct frame_info *));
+
+/* 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)); }
+
+extern void i386_frame_find_saved_regs PARAMS ((struct frame_info *,
+ struct frame_saved_regs *));
+
+
+/* Things needed for making the inferior call functions. */
+
+/* Push an empty stack frame, to record the current PC, etc. */
+
+#define PUSH_DUMMY_FRAME { i386_push_dummy_frame (); }
+
+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
+ */
+
+#define CALL_DUMMY { 0x223344e8, 0xcc11 }
+
+#define CALL_DUMMY_LENGTH 8
+
+#define CALL_DUMMY_START_OFFSET 0 /* Start execution at beginning of dummy */
+
+#define CALL_DUMMY_BREAKPOINT_OFFSET 5
+
+/* Insert the specified number of args and function address
+ into a call sequence of the above form stored at DUMMYNAME. */
+
+#define FIX_CALL_DUMMY(dummyname, pc, fun, nargs, args, type, gcc_p) \
+{ \
+ int from, to, delta, loc; \
+ loc = (int)(read_register (SP_REGNUM) - CALL_DUMMY_LENGTH); \
+ from = loc + 5; \
+ to = (int)(fun); \
+ delta = to - from; \
+ *((char *)(dummyname) + 1) = (delta & 0xff); \
+ *((char *)(dummyname) + 2) = ((delta >> 8) & 0xff); \
+ *((char *)(dummyname) + 3) = ((delta >> 16) & 0xff); \
+ *((char *)(dummyname) + 4) = ((delta >> 24) & 0xff); \
+}
+
+extern void print_387_control_word PARAMS ((unsigned int));
+extern void print_387_status_word PARAMS ((unsigned int));
+
+/* Offset from SP to first arg on stack at first instruction of a function */
+
+#define SP_ARG0 (1 * 4)
+
+#endif /* ifndef TM_I386_H */
diff --git a/gdb/config/i386/tm-i386aix.h b/gdb/config/i386/tm-i386aix.h
new file mode 100644
index 00000000000..b0121fa92df
--- /dev/null
+++ b/gdb/config/i386/tm-i386aix.h
@@ -0,0 +1,67 @@
+/* Macro defintions for IBM AIX PS/2 (i386).
+ Copyright 1986, 1987, 1989, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Changes for IBM AIX PS/2 by Minh Tran-Le (tranle@intellicorp.com). */
+
+#ifndef TM_I386AIX_H
+#define TM_I386AIX_H 1
+
+#include "i386/tm-i386.h"
+#include <sys/reg.h>
+
+#ifndef I386
+# define I386 1
+#endif
+#ifndef I386_AIX_TARGET
+# define I386_AIX_TARGET 1
+#endif
+
+/* Nonzero if register N requires conversion
+ from raw format to virtual format. */
+
+#undef REGISTER_CONVERTIBLE
+#define REGISTER_CONVERTIBLE(N) \
+ ((N < FP0_REGNUM) ? 0 : 1)
+
+/* Convert data from raw format for register REGNUM in buffer FROM
+ to virtual format with type TYPE in buffer TO. */
+
+#undef REGISTER_CONVERT_TO_VIRTUAL
+#define REGISTER_CONVERT_TO_VIRTUAL(REGNUM,TYPE,FROM,TO) \
+{ \
+ double val; \
+ i387_to_double ((FROM), (char *)&val); \
+ store_floating ((TO), TYPE_LENGTH (TYPE), val); \
+}
+extern void
+i387_to_double PARAMS ((char *, char *));
+
+/* Convert data from virtual format with type TYPE in buffer FROM
+ to raw format for register REGNUM in buffer TO. */
+
+#undef REGISTER_CONVERT_TO_RAW
+#define REGISTER_CONVERT_TO_RAW(TYPE,REGNUM,FROM,TO) \
+{ \
+ double val = extract_floating ((FROM), TYPE_LENGTH (TYPE)); \
+ double_to_i387((char *)&val, (TO)); \
+}
+extern void
+double_to_i387 PARAMS ((char *, char *));
+
+#endif /* TM_I386AIX_H */
diff --git a/gdb/config/i386/tm-i386bsd.h b/gdb/config/i386/tm-i386bsd.h
new file mode 100644
index 00000000000..8b8c3a9708a
--- /dev/null
+++ b/gdb/config/i386/tm-i386bsd.h
@@ -0,0 +1,43 @@
+/* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef TM_I386BSD_H
+#define TM_I386BSD_H 1
+
+#include "i386/tm-i386.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(pc) 0xfdbfdfc0
+#define SIGTRAMP_END(pc) 0xfdbfe000
+
+/* Saved Pc. Get it from sigcontext if within sigtramp. */
+
+/* Offset to saved PC in sigcontext, from <sys/signal.h>. */
+#define SIGCONTEXT_PC_OFFSET 20
+
+#endif /* ifndef TM_I386BSD_H */
diff --git a/gdb/config/i386/tm-i386gnu.h b/gdb/config/i386/tm-i386gnu.h
new file mode 100644
index 00000000000..a6e3c087d4d
--- /dev/null
+++ b/gdb/config/i386/tm-i386gnu.h
@@ -0,0 +1,48 @@
+/* Macro definitions for i386, GNU Hurd
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Include common definitions for gnu systems */
+#include "nm-gnu.h"
+
+/* Thread flavors used in re-setting the T bit.
+ * @@ this is also bad for cross debugging.
+ */
+#define THREAD_STATE_FLAVOR i386_THREAD_STATE
+#define THREAD_STATE_SIZE i386_THREAD_STATE_COUNT
+#define THREAD_STATE_SET_TRACED(state) \
+ ((struct i386_thread_state *)state)->efl |= 0x100
+#define THREAD_STATE_CLEAR_TRACED(state) \
+ ((((struct i386_thread_state *)state)->efl &= ~0x100), 1)
+
+/* we can do it */
+#define ATTACH_DETACH 1
+
+/* Sigh. There should be a file for i386 but no sysv stuff in it */
+#include "i386/tm-i386v.h"
+
+/* I want to test this float info code. See comment in tm-i386v.h */
+#undef FLOAT_INFO
+#define FLOAT_INFO { i386_mach3_float_info (); }
+
+/* Address of end of stack space.
+ * for MACH, see <machine/vmparam.h>
+ * @@@ I don't know what is in the 5 ints...
+ */
+#undef STACK_END_ADDR
+#define STACK_END_ADDR (0xc0000000-sizeof(int [5]))
diff --git a/gdb/config/i386/tm-i386lynx.h b/gdb/config/i386/tm-i386lynx.h
new file mode 100644
index 00000000000..9e732b32e6b
--- /dev/null
+++ b/gdb/config/i386/tm-i386lynx.h
@@ -0,0 +1,33 @@
+/* Macro definitions for Intel 386 running under LynxOS.
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef TM_I386LYNX_H
+#define TM_I386LYNX_H
+
+#include "tm-lynx.h"
+
+/* Most definitions from sysv could be used. */
+#include "i386/tm-i386.h"
+
+#undef SAVED_PC_AFTER_CALL
+
+#define SAVED_PC_AFTER_CALL i386lynx_saved_pc_after_call
+CORE_ADDR i386lynx_saved_pc_after_call ();
+
+#endif /* TM_I386LYNX_H */
diff --git a/gdb/config/i386/tm-i386m3.h b/gdb/config/i386/tm-i386m3.h
new file mode 100644
index 00000000000..2f97505a19a
--- /dev/null
+++ b/gdb/config/i386/tm-i386m3.h
@@ -0,0 +1,60 @@
+/* Macro definitions for i386, Mach 3.0
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Include common definitions for Mach3 systems */
+#include "nm-m3.h"
+
+/* Define offsets to access CPROC stack when it does not have
+ * a kernel thread.
+ */
+#define MACHINE_CPROC_SP_OFFSET 20
+#define MACHINE_CPROC_PC_OFFSET 16
+#define MACHINE_CPROC_FP_OFFSET 12
+
+/* Thread flavors used in re-setting the T bit.
+ * @@ this is also bad for cross debugging.
+ */
+#define TRACE_FLAVOR i386_THREAD_STATE
+#define TRACE_FLAVOR_SIZE i386_THREAD_STATE_COUNT
+#define TRACE_SET(x,state) \
+ ((struct i386_thread_state *)state)->efl |= 0x100
+#define TRACE_CLEAR(x,state) \
+ ((((struct i386_thread_state *)state)->efl &= ~0x100), 1)
+
+/* we can do it */
+#define ATTACH_DETACH 1
+
+/* 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
+
+/* Sigh. There should be a file for i386 but no sysv stuff in it */
+#include "i386/tm-i386.h"
+
+/* I want to test this float info code. See comment in tm-i386v.h */
+#undef FLOAT_INFO
+#define FLOAT_INFO { i386_mach3_float_info (); }
+
+/* Address of end of stack space.
+ * for MACH, see <machine/vmparam.h>
+ * @@@ I don't know what is in the 5 ints...
+ */
+#undef STACK_END_ADDR
+#define STACK_END_ADDR (0xc0000000-sizeof(int [5]))
diff --git a/gdb/config/i386/tm-i386mk.h b/gdb/config/i386/tm-i386mk.h
new file mode 100644
index 00000000000..3625efbf6df
--- /dev/null
+++ b/gdb/config/i386/tm-i386mk.h
@@ -0,0 +1,25 @@
+/* Macro definitions for i386, Mach 3.0, OSF 1/MK
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Until OSF switches to a newer Mach kernel that has
+ * a different get_emul_vector() interface.
+ */
+#define MK67 1
+
+#include "i386/tm-i386m3.h"
diff --git a/gdb/config/i386/tm-i386nw.h b/gdb/config/i386/tm-i386nw.h
new file mode 100644
index 00000000000..e5cdadecb47
--- /dev/null
+++ b/gdb/config/i386/tm-i386nw.h
@@ -0,0 +1,49 @@
+/* Macro definitions for i386 running NetWare.
+ Copyright 1993, 1994 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef TM_I386NW_H
+#define TM_I386NW_H 1
+
+#include "i386/tm-i386.h"
+
+/* Stop backtracing when we wander into main. */
+
+#define FRAME_CHAIN_VALID(fp,fi) alternate_frame_chain_valid (fp, fi)
+
+
+/* Offsets (in target ints) into jmp_buf. Not defined in any system header
+ file, so we have to step through setjmp/longjmp with a debugger and figure
+ them out. */
+
+#define JB_ELEMENT_SIZE 4 /* jmp_buf[] is array of ints */
+
+#define JB_PC 6 /* Setjmp()'s return PC saved here */
+
+/* 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 ADDR.
+ This routine returns true on success */
+
+extern int
+get_longjmp_target PARAMS ((CORE_ADDR *));
+
+#define GET_LONGJMP_TARGET(ADDR) get_longjmp_target(ADDR)
+
+#endif /* ifndef TM_I386NW_H */
+
diff --git a/gdb/config/i386/tm-i386os9k.h b/gdb/config/i386/tm-i386os9k.h
new file mode 100644
index 00000000000..2b486419659
--- /dev/null
+++ b/gdb/config/i386/tm-i386os9k.h
@@ -0,0 +1,63 @@
+/* Macro definitions for i386 running under BSD Unix.
+ Copyright 1986, 1987, 1989, 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 General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef TM_I386OS9K_H
+#define TM_I386OS9K_H 1
+
+#include "i386/tm-i386.h"
+
+/* Number of machine registers */
+
+#undef NUM_REGS
+#define NUM_REGS (16) /* Basic i*86 regs */
+
+/* Initializer for an array of names of registers. There should be at least
+ NUM_REGS strings in this initializer. Any excess ones are simply ignored.
+ The order of the first 8 registers must match the compiler's numbering
+ scheme (which is the same as the 386 scheme) and also regmap in the various
+ *-nat.c files. */
+
+#undef REGISTER_NAMES
+#define REGISTER_NAMES { "eax", "ecx", "edx", "ebx", \
+ "esp", "ebp", "esi", "edi", \
+ "eip", "eflags", "cs", "ss", \
+ "ds", "es", "fs", "gs", \
+ }
+
+#define DATABASE_REG 3 /* ebx */
+
+/* Amount PC must be decremented by after a breakpoint. This is often the
+ number of bytes in BREAKPOINT but not always (such as now). */
+
+#undef DECR_PC_AFTER_BREAK
+#define DECR_PC_AFTER_BREAK 0
+
+/* 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(pc) 0xfdbfdfc0
+#define SIGTRAMP_END(pc) 0xfdbfe000
+
+/* Saved Pc. Get it from sigcontext if within sigtramp. */
+
+/* Offset to saved PC in sigcontext, from <sys/signal.h>. */
+#define SIGCONTEXT_PC_OFFSET 20
+
+#define BELIEVE_PCC_PROMOTION 1
+
+#endif /* #ifndef TM_I386OS9K_H */
diff --git a/gdb/config/i386/tm-i386sco5.h b/gdb/config/i386/tm-i386sco5.h
new file mode 100644
index 00000000000..ffac5b3b561
--- /dev/null
+++ b/gdb/config/i386/tm-i386sco5.h
@@ -0,0 +1,62 @@
+/* Macro definitions for GDB on an Intel i386 running SCO Open Server 5.
+ Copyright (C) 1998 Free Software Foundation, Inc.
+ Written by J. Kean Johnston (jkj@sco.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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef TM_I386SCO5_H
+#define TM_I386SCO5_H 1
+
+/* Pick up most of what we need from the generic i386 target include file. */
+
+#include "i386/tm-i386.h"
+
+/* Pick up more stuff from the generic SYSV and SVR4 host include files. */
+#include "i386/tm-i386v.h"
+#include "tm-sysv4.h"
+
+#define KERNEL_U_SIZE kernel_u_size()
+
+/*
+ * SCO is unlike other SVR3 targets in that it has SVR4 style shared
+ * libs, with a slight twist. We expect 3 traps (2 for the exec and
+ * one for the dynamic loader). After the third trap we insert the
+ * SOLIB breakpoints, then wait for the 4th trap.
+ */
+#undef START_INFERIOR_TRAPS_EXPECTED
+#define START_INFERIOR_TRAPS_EXPECTED 3
+
+/* We can also do hardware watchpoints */
+#define TARGET_HAS_HARDWARE_WATCHPOINTS
+#define TARGET_CAN_USE_HARDWARE_WATCHPOINT(type, cnt, ot) 1
+
+/* After a watchpoint trap, the PC points to the instruction which
+ caused the trap. But we can continue over it without disabling the
+ trap. */
+#define HAVE_CONTINUABLE_WATCHPOINT
+#define HAVE_STEPPABLE_WATCHPOINT
+
+#define STOPPED_BY_WATCHPOINT(W) \
+ i386_stopped_by_watchpoint (inferior_pid)
+
+#define target_insert_watchpoint(addr, len, type) \
+ i386_insert_watchpoint (inferior_pid, addr, len, type)
+
+#define target_remove_watchpoint(addr, len, type) \
+ i386_remove_watchpoint (inferior_pid, addr, len)
+
+#endif /* ifndef TM_I386SCO5_H */
diff --git a/gdb/config/i386/tm-i386sol2.h b/gdb/config/i386/tm-i386sol2.h
new file mode 100644
index 00000000000..dbd6317b65b
--- /dev/null
+++ b/gdb/config/i386/tm-i386sol2.h
@@ -0,0 +1,64 @@
+/* Macro definitions for GDB on an Intel i386 running Solaris 2.
+ Copyright (C) 1998 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef TM_I386SOL2_H
+#define TM_I386SOL2_H 1
+
+#include "i386/tm-i386v4.h"
+
+/* Signal handler frames under Solaris 2 are recognized by a return address
+ of 0xFFFFFFFF, the third parameter on the signal handler stack is
+ a pointer to an ucontext. */
+#undef sigtramp_saved_pc
+#undef I386V4_SIGTRAMP_SAVED_PC
+#define SIGCONTEXT_PC_OFFSET (36 + 14 * 4)
+#undef IN_SIGTRAMP
+#define IN_SIGTRAMP(pc, name) (pc == 0xFFFFFFFF)
+
+/* The SunPRO compiler puts out 0 instead of the address in N_SO symbols,
+ and for SunPRO 3.0, N_FUN symbols too. */
+#define SOFUN_ADDRESS_MAYBE_MISSING
+
+extern char *sunpro_static_transform_name PARAMS ((char *));
+#define STATIC_TRANSFORM_NAME(x) sunpro_static_transform_name (x)
+#define IS_STATIC_TRANSFORM_NAME(name) ((name)[0] == '.')
+
+#define FAULTED_USE_SIGINFO
+
+/* Macros to extract process id and thread id from a composite pid/tid */
+#define PIDGET(pid) ((pid) & 0xffff)
+#define TIDGET(pid) (((pid) >> 16) & 0xffff)
+
+/* Macro to extract carry from given regset. */
+#define PS_FLAG_CARRY 0x1 /* Carry bit in PS */
+#define PROCFS_GET_CARRY(regset) ((regset)[EFL] & PS_FLAG_CARRY)
+
+#ifdef HAVE_THREAD_DB_LIB
+
+extern char *solaris_pid_to_str PARAMS ((int pid));
+#define target_pid_to_str(PID) solaris_pid_to_str (PID)
+
+#else
+
+extern char *procfs_pid_to_str PARAMS ((int pid));
+#define target_pid_to_str(PID) procfs_pid_to_str (PID)
+
+#endif
+
+#endif /* ifndef TM_I386SOL2_H */
diff --git a/gdb/config/i386/tm-i386v.h b/gdb/config/i386/tm-i386v.h
new file mode 100644
index 00000000000..bb31cb0c796
--- /dev/null
+++ b/gdb/config/i386/tm-i386v.h
@@ -0,0 +1,163 @@
+/* Macro definitions for i386, Unix System V.
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef TM_I386V_H
+#define TM_I386V_H 1
+
+/* First pick up the generic *86 target file. */
+
+#include "i386/tm-i386.h"
+
+/* 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. Override here to 4. */
+
+#undef START_INFERIOR_TRAPS_EXPECTED
+#define START_INFERIOR_TRAPS_EXPECTED 4
+
+/* Number of machine registers */
+
+#undef NUM_REGS
+#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.
+ */
+
+#undef REGISTER_NAMES
+#define REGISTER_NAMES { "eax", "ecx", "edx", "ebx", \
+ "esp", "ebp", "esi", "edi", \
+ "eip", "ps", "cs", "ss", \
+ "ds", "es", "fs", "gs", \
+ }
+
+/* Total amount of space needed to store our copies of the machine's
+ register state, the array `registers'. */
+
+#undef REGISTER_BYTES
+#define REGISTER_BYTES (NUM_REGS * 4)
+
+/* Index within `registers' of the first byte of the space for
+ register N. */
+
+#undef REGISTER_BYTE
+#define REGISTER_BYTE(N) ((N)*4)
+
+/* Number of bytes of storage in the actual machine representation
+ for register N. */
+
+#undef REGISTER_RAW_SIZE
+#define REGISTER_RAW_SIZE(N) (4)
+
+/* Number of bytes of storage in the program's representation
+ for register N. */
+
+#undef REGISTER_VIRTUAL_SIZE
+#define REGISTER_VIRTUAL_SIZE(N) (4)
+
+/* Largest value REGISTER_RAW_SIZE can have. */
+
+#undef MAX_REGISTER_RAW_SIZE
+#define MAX_REGISTER_RAW_SIZE 4
+
+/* Largest value REGISTER_VIRTUAL_SIZE can have. */
+
+#undef MAX_REGISTER_VIRTUAL_SIZE
+#define MAX_REGISTER_VIRTUAL_SIZE 4
+
+/* Return the GDB type object for the "standard" data type
+ of data in register N. */
+/* Perhaps si and di should go here, but potentially they could be
+ used for things other than address. */
+
+#undef REGISTER_VIRTUAL_TYPE
+#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. */
+
+#undef STORE_STRUCT_RETURN
+#define STORE_STRUCT_RETURN(ADDR, SP) \
+ { char buf[REGISTER_SIZE]; \
+ (SP) -= sizeof (ADDR); \
+ store_address (buf, sizeof (ADDR), ADDR); \
+ write_memory ((SP), buf, 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. */
+
+#undef EXTRACT_RETURN_VALUE
+#define EXTRACT_RETURN_VALUE(TYPE,REGBUF,VALBUF) \
+ memcpy ((VALBUF), (REGBUF), TYPE_LENGTH (TYPE))
+
+/* Write into appropriate registers a function return value
+ of type TYPE, given in virtual format. */
+
+#undef STORE_RETURN_VALUE
+#define STORE_RETURN_VALUE(TYPE,VALBUF) \
+ write_register_bytes (0, VALBUF, TYPE_LENGTH (TYPE))
+
+
+/* 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. */
+
+#undef FRAME_CHAIN
+#define FRAME_CHAIN(thisframe) \
+ (!inside_entry_file ((thisframe)->pc) ? \
+ read_memory_integer ((thisframe)->frame, 4) :\
+ 0)
+
+/* Define other aspects of the stack frame. */
+
+/* A macro that tells us whether the function invocation represented
+ by FI does not have a frame on the stack associated with it. If it
+ does not, FRAMELESS is set to 1, else 0. */
+
+#undef FRAMELESS_FUNCTION_INVOCATION
+#define FRAMELESS_FUNCTION_INVOCATION(FI, FRAMELESS) \
+ (FRAMELESS) = frameless_look_for_prologue(FI)
+
+#undef FRAME_SAVED_PC
+#define FRAME_SAVED_PC(FRAME) (read_memory_integer ((FRAME)->frame + 4, 4))
+
+/* Return number of args passed to a frame.
+ Can return -1, meaning no way to tell. */
+
+#undef FRAME_NUM_ARGS
+#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 *));
+
+#endif /* ifndef TM_I386V_H */
diff --git a/gdb/config/i386/tm-i386v4.h b/gdb/config/i386/tm-i386v4.h
new file mode 100644
index 00000000000..eafff0178c0
--- /dev/null
+++ b/gdb/config/i386/tm-i386v4.h
@@ -0,0 +1,78 @@
+/* Macro definitions for GDB on an Intel i386 running SVR4.
+ Copyright (C) 1991, 1994 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef TM_I386V4_H
+#define TM_I386V4_H 1
+
+/* Pick up most of what we need from the generic i386 target include file. */
+
+#include "i386/tm-i386.h"
+
+/* Pick up more stuff from the generic SVR4 host include file. */
+
+#include "tm-sysv4.h"
+
+/* Use the alternate method of determining valid frame chains. */
+
+#define FRAME_CHAIN_VALID(fp,fi) alternate_frame_chain_valid (fp, fi)
+
+/* Offsets (in target ints) into jmp_buf. Not defined in any system header
+ file, so we have to step through setjmp/longjmp with a debugger and figure
+ them out. Note that <setjmp> defines _JBLEN as 10, which is the default
+ if no specific machine is selected, even though we only use 6 slots. */
+
+#define JB_ELEMENT_SIZE sizeof(int) /* jmp_buf[_JBLEN] is array of ints */
+
+#define JB_EBX 0
+#define JB_ESI 1
+#define JB_EDI 2
+#define JB_EBP 3
+#define JB_ESP 4
+#define JB_EDX 5
+
+#define JB_PC JB_EDX /* Setjmp()'s return PC saved in EDX */
+
+/* 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 ADDR.
+ This routine returns true on success */
+
+extern int
+get_longjmp_target PARAMS ((CORE_ADDR *));
+
+#define GET_LONGJMP_TARGET(ADDR) get_longjmp_target(ADDR)
+
+/* The following redefines make backtracing through sigtramp work.
+ They manufacture a fake sigtramp frame and obtain the saved pc in sigtramp
+ from the ucontext structure which is pushed by the kernel on the
+ user stack. Unfortunately there are three variants of sigtramp handlers. */
+
+#define I386V4_SIGTRAMP_SAVED_PC
+#define IN_SIGTRAMP(pc, name) ((name) \
+ && (STREQ ("_sigreturn", name) \
+ || STREQ ("_sigacthandler", name) \
+ || STREQ ("sigvechandler", name)))
+
+/* Saved Pc. Get it from ucontext if within sigtramp. */
+
+#define sigtramp_saved_pc i386v4_sigtramp_saved_pc
+extern CORE_ADDR i386v4_sigtramp_saved_pc PARAMS ((struct frame_info *));
+
+#endif /* ifndef TM_I386V4_H */
diff --git a/gdb/config/i386/tm-i386v42mp.h b/gdb/config/i386/tm-i386v42mp.h
new file mode 100644
index 00000000000..81df85bcbbe
--- /dev/null
+++ b/gdb/config/i386/tm-i386v42mp.h
@@ -0,0 +1,44 @@
+/* Macro definitions for GDB on an Intel i386 running SVR4.2MP
+ Copyright (C) 1991, 1994 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef TM_I386V42MP_H
+#define TM_I386V42MP_H 1
+
+/* pick up more generic x86 sysv4 stuff */
+
+#include "i386/tm-i386v4.h"
+
+/* procfs on this architecture has multiple fds (ctl, as, map, status)
+ including a control fd */
+
+#ifndef HAVE_MULTIPLE_PROC_FDS
+#define HAVE_MULTIPLE_PROC_FDS
+#endif
+
+/* procfs on this architecture communicates with read/write instead
+ of ioctl */
+
+#define PROCFS_USE_READ_WRITE
+
+/* define to select for other sysv4.2mp weirdness */
+
+#define UNIXWARE
+
+#endif /* ifndef TM_I386V42MP_H */
diff --git a/gdb/config/i386/tm-linux.h b/gdb/config/i386/tm-linux.h
new file mode 100644
index 00000000000..417d1514d75
--- /dev/null
+++ b/gdb/config/i386/tm-linux.h
@@ -0,0 +1,38 @@
+/* Definitions to target GDB to GNU/Linux on 386.
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef TM_LINUX_H
+#define TM_LINUX_H
+
+/* FIXME: If nothing else gets added to this file, it could be removed
+ and configure could just use tm-i386.h instead. -fnf */
+
+#include "i386/tm-i386.h"
+
+/* Offset to saved PC in sigcontext, from <linux/signal.h>. */
+#define SIGCONTEXT_PC_OFFSET 38
+
+/* We need this file for the SOLIB_TRAMPOLINE stuff. */
+
+#include "tm-sysv4.h"
+
+/* The following works around a problem with /usr/include/sys/procfs.h */
+#define sys_quotactl 1
+
+#endif /* #ifndef TM_LINUX_H */
diff --git a/gdb/config/i386/tm-nbsd.h b/gdb/config/i386/tm-nbsd.h
new file mode 100644
index 00000000000..cf5159f2655
--- /dev/null
+++ b/gdb/config/i386/tm-nbsd.h
@@ -0,0 +1,42 @@
+/* Macro definitions for i386 running under NetBSD.
+ Copyright 1994 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef TM_NBSD_H
+#define TM_NBSD_H
+
+#include "i386/tm-i386bsd.h"
+#include "tm-nbsd.h"
+
+#undef NUM_REGS
+#define NUM_REGS 16
+
+#define JB_ELEMENT_SIZE sizeof(int) /* jmp_buf[_JBLEN] is array of ints */
+#define JB_PC 0 /* Setjmp()'s return PC saved here */
+
+/* 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 ADDR.
+ This routine returns true on success */
+
+extern int
+get_longjmp_target PARAMS ((CORE_ADDR *));
+
+#define GET_LONGJMP_TARGET(ADDR) get_longjmp_target(ADDR)
+
+#endif /* TM_NBSD_H */
diff --git a/gdb/config/i386/tm-ptx.h b/gdb/config/i386/tm-ptx.h
new file mode 100644
index 00000000000..c9f67d7f6d8
--- /dev/null
+++ b/gdb/config/i386/tm-ptx.h
@@ -0,0 +1,232 @@
+/* Target machine definitions for GDB on a Sequent Symmetry under ptx
+ with Weitek 1167 and i387 support.
+ Copyright 1986, 1987, 1989, 1991, 1992, 1993 Free Software Foundation, Inc.
+ Symmetry version by Jay Vosburgh (fubar@sequent.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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef TM_PTX_H
+#define TM_PTX_H 1
+
+/* I don't know if this will work for cross-debugging, even if you do get
+ a copy of the right include file. */
+
+#include <sys/reg.h>
+
+#ifdef SEQUENT_PTX4
+#include "i386/tm-i386v4.h"
+#else /* !SEQUENT_PTX4 */
+#include "i386/tm-i386v.h"
+#endif
+
+/* 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. Here we have to undo what tm-i386v.h gave
+ us and restore the default. */
+
+#undef START_INFERIOR_TRAPS_EXPECTED
+#define START_INFERIOR_TRAPS_EXPECTED 2
+
+/* Amount PC must be decremented by after a breakpoint. This is often the
+ number of bytes in BREAKPOINT but not always (such as now). */
+
+#undef DECR_PC_AFTER_BREAK
+#define DECR_PC_AFTER_BREAK 0
+
+#if 0
+ --- this code can't be used unless we know we are running native,
+ since it uses host specific ptrace calls.
+/* code for 80387 fpu. Functions are from i386-dep.c, copied into
+ * symm-dep.c.
+ */
+#define FLOAT_INFO { i386_float_info(); }
+#endif
+
+/* Number of machine registers */
+
+#undef NUM_REGS
+#define NUM_REGS 49
+
+/* Initializer for an array of names of registers. There should be at least
+ NUM_REGS strings in this initializer. Any excess ones are simply ignored.
+ The order of the first 8 registers must match the compiler's numbering
+ scheme (which is the same as the 386 scheme) and also regmap in the various
+ *-nat.c files. */
+
+#undef REGISTER_NAMES
+#define REGISTER_NAMES { "eax", "ecx", "edx", "ebx", \
+ "esp", "ebp", "esi", "edi", \
+ "eip", "eflags", "st0", "st1", \
+ "st2", "st3", "st4", "st5", \
+ "st6", "st7", "fp1", "fp2", \
+ "fp3", "fp4", "fp5", "fp6", \
+ "fp7", "fp8", "fp9", "fp10", \
+ "fp11", "fp12", "fp13", "fp14", \
+ "fp15", "fp16", "fp17", "fp18", \
+ "fp19", "fp20", "fp21", "fp22", \
+ "fp23", "fp24", "fp25", "fp26", \
+ "fp27", "fp28", "fp29", "fp30", \
+ "fp31" }
+
+/* Register numbers of various important registers.
+ Note that some of these values are "real" register numbers,
+ and correspond to the general registers of the machine,
+ and some are "phony" register numbers which are too large
+ to be actual register numbers as far as the user is concerned
+ but do serve to get the desired values when passed to read_register. */
+
+#define EAX_REGNUM 0
+#define ECX_REGNUM 1
+#define EDX_REGNUM 2
+#define EBX_REGNUM 3
+
+#define ESP_REGNUM 4
+#define EBP_REGNUM 5
+
+#define ESI_REGNUM 6
+#define EDI_REGNUM 7
+
+#define EIP_REGNUM 8
+#define EFLAGS_REGNUM 9
+
+#define ST0_REGNUM 10
+#define ST1_REGNUM 11
+#define ST2_REGNUM 12
+#define ST3_REGNUM 13
+
+#define ST4_REGNUM 14
+#define ST5_REGNUM 15
+#define ST6_REGNUM 16
+#define ST7_REGNUM 17
+
+#define FP1_REGNUM 18 /* first 1167 register */
+/* Get %fp2 - %fp31 by addition, since they are contiguous */
+
+#undef SP_REGNUM
+#define SP_REGNUM ESP_REGNUM /* Contains address of top of stack */
+#undef FP_REGNUM
+#define FP_REGNUM EBP_REGNUM /* Contains address of executing stack frame */
+#undef PC_REGNUM
+#define PC_REGNUM EIP_REGNUM /* Contains program counter */
+#undef PS_REGNUM
+#define PS_REGNUM EFLAGS_REGNUM /* Contains processor status */
+
+/*
+ * For ptx, this is a little bit bizarre, since the register block
+ * is below the u area in memory. This means that blockend here ends
+ * up being negative (for the call from coredep.c) since the value in
+ * u.u_ar0 will be less than KERNEL_U_ADDR (and coredep.c passes us
+ * u.u_ar0 - KERNEL_U_ADDR in blockend). Since we also define
+ * FETCH_INFERIOR_REGISTERS (and supply our own functions for that),
+ * the core file case will be the only use of this function.
+ */
+
+#define REGISTER_U_ADDR(addr, blockend, regno) \
+{ (addr) = ptx_register_u_addr((blockend), (regno)); }
+
+extern int
+ptx_register_u_addr PARAMS ((int, int));
+
+/* Total amount of space needed to store our copies of the machine's
+ register state, the array `registers'. 10 i*86 registers, 8 i387
+ registers, and 31 Weitek 1167 registers */
+
+#undef REGISTER_BYTES
+#define REGISTER_BYTES ((10 * 4) + (8 * 10) + (31 * 4))
+
+/* Index within `registers' of the first byte of the space for register N. */
+
+#undef REGISTER_BYTE
+#define REGISTER_BYTE(N) \
+(((N) < ST0_REGNUM) ? ((N) * 4) : \
+ ((N) < FP1_REGNUM) ? (40 + (((N) - ST0_REGNUM) * 10)) : \
+ (40 + 80 + (((N) - FP1_REGNUM) * 4)))
+
+/* Number of bytes of storage in the actual machine representation for
+ register N. All registers are 4 bytes, except 387 st(0) - st(7),
+ which are 80 bits each. */
+
+#undef REGISTER_RAW_SIZE
+#define REGISTER_RAW_SIZE(N) \
+(((N) < ST0_REGNUM) ? 4 : \
+ ((N) < FP1_REGNUM) ? 10 : \
+ 4)
+
+/* Largest value REGISTER_RAW_SIZE can have. */
+
+#undef MAX_REGISTER_RAW_SIZE
+#define MAX_REGISTER_RAW_SIZE 10
+
+/* Nonzero if register N requires conversion
+ from raw format to virtual format. */
+
+#undef REGISTER_CONVERTIBLE
+#define REGISTER_CONVERTIBLE(N) \
+((N < ST0_REGNUM) ? 0 : \
+ (N < FP1_REGNUM) ? 1 : \
+ 0)
+
+/* Convert data from raw format for register REGNUM
+ to virtual format for register REGNUM. */
+extern const struct floatformat floatformat_i387_ext; /* from floatformat.h */
+
+#undef REGISTER_CONVERT_TO_VIRTUAL
+#define REGISTER_CONVERT_TO_VIRTUAL(REGNUM,TYPE,FROM,TO) \
+((REGNUM < ST0_REGNUM) ? (void)memcpy ((TO), (FROM), 4) : \
+ (REGNUM < FP1_REGNUM) ? (void)floatformat_to_double(&floatformat_i387_ext, \
+ (FROM),(TO)) : \
+ (void)memcpy ((TO), (FROM), 4))
+
+/* Convert data from virtual format for register REGNUM
+ to raw format for register REGNUM. */
+
+#undef REGISTER_CONVERT_TO_RAW
+#define REGISTER_CONVERT_TO_RAW(TYPE,REGNUM,FROM,TO) \
+((REGNUM < ST0_REGNUM) ? (void)memcpy ((TO), (FROM), 4) : \
+ (REGNUM < FP1_REGNUM) ? (void)floatformat_from_double(&floatformat_i387_ext, \
+ (FROM),(TO)) : \
+ (void)memcpy ((TO), (FROM), 4))
+
+/* Return the GDB type object for the "standard" data type
+ of data in register N. */
+/*
+ * Note: the 1167 registers (the last line, builtin_type_float) are
+ * generally used in pairs, with each pair being treated as a double.
+ * It it also possible to use them singly as floats. I'm not sure how
+ * in gdb to treat the register pair pseudo-doubles. -fubar
+ */
+#undef REGISTER_VIRTUAL_TYPE
+#define REGISTER_VIRTUAL_TYPE(N) \
+((N < ST0_REGNUM) ? builtin_type_int : \
+ (N < FP1_REGNUM) ? builtin_type_double : \
+ builtin_type_float)
+
+/* 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. */
+
+#undef EXTRACT_RETURN_VALUE
+#define EXTRACT_RETURN_VALUE(TYPE,REGBUF,VALBUF) \
+ symmetry_extract_return_value(TYPE, REGBUF, VALBUF)
+
+/*
+#undef FRAME_FIND_SAVED_REGS
+#define FRAME_FIND_SAVED_REGS(frame_info, frame_saved_regs) \
+{ ptx_frame_find_saved_regs((frame_info), &(frame_saved_regs)); }
+*/
+
+#endif /* ifndef TM_PTX_H */
diff --git a/gdb/config/i386/tm-ptx4.h b/gdb/config/i386/tm-ptx4.h
new file mode 100644
index 00000000000..a576accb46b
--- /dev/null
+++ b/gdb/config/i386/tm-ptx4.h
@@ -0,0 +1,24 @@
+/* Target machine definitions for GDB on a Sequent Symmetry under ptx
+ with Weitek 1167 and i387 support.
+ Copyright 1986, 1987, 1989, 1991, 1992, 1993 Free Software Foundation, Inc.
+ Symmetry version by Jay Vosburgh (fubar@sequent.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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define SEQUENT_PTX4
+
+#include "tm-ptx.h"
diff --git a/gdb/config/i386/tm-sun386.h b/gdb/config/i386/tm-sun386.h
new file mode 100644
index 00000000000..259fd518238
--- /dev/null
+++ b/gdb/config/i386/tm-sun386.h
@@ -0,0 +1,205 @@
+/* Parameters for a Sun 386i target machine, for GDB, the GNU debugger.
+ Copyright 1986, 1987, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#if !defined (TM_SUN386_H)
+#define TM_SUN386_H 1
+
+#include "i386/tm-i386.h"
+
+#ifndef sun386
+#define sun386
+#endif
+#define GDB_TARGET_IS_SUN386 1
+#define SUNOS4
+#define USE_MACHINE_REG_H
+
+/* Perhaps some day this will work even without the following #define */
+#define COFF_ENCAPSULATE
+
+#ifdef COFF_ENCAPSULATE
+/* Avoid conflicts between our include files and <sys/exec.h>
+ (maybe not needed anymore). */
+#define _EXEC_
+#endif
+
+/* sun386 ptrace seems unable to change the frame pointer */
+#define PTRACE_FP_BUG
+
+/* Address of end of stack space. */
+
+#define STACK_END_ADDR 0xfc000000
+
+/* Number of machine registers */
+
+#undef NUM_REGS
+#define NUM_REGS 35
+
+/* Initializer for an array of names of registers. There should be NUM_REGS
+ strings in this initializer. The order of the first 8 registers must match
+ the compiler's numbering scheme (which is the same as the 386 scheme) also,
+ this table must match regmap in i386-pinsn.c. */
+
+#undef REGISTER_NAMES
+#define REGISTER_NAMES { "gs", "fs", "es", "ds", \
+ "edi", "esi", "ebp", "esp", \
+ "ebx", "edx", "ecx", "eax", \
+ "retaddr", "trapnum", "errcode", "ip", \
+ "cs", "ps", "sp", "ss", \
+ "fst0", "fst1", "fst2", "fst3", \
+ "fst4", "fst5", "fst6", "fst7", \
+ "fctrl", "fstat", "ftag", "fip", \
+ "fcs", "fopoff", "fopsel" \
+ }
+
+/* Register numbers of various important registers.
+ Note that some of these values are "real" register numbers,
+ and correspond to the general registers of the machine,
+ and some are "phony" register numbers which are too large
+ to be actual register numbers as far as the user is concerned
+ but do serve to get the desired values when passed to read_register. */
+
+#undef FP_REGNUM
+#define FP_REGNUM 6 /* (ebp) Contains address of executing stack frame */
+#undef SP_REGNUM
+#define SP_REGNUM 18 /* (usp) Contains address of top of stack */
+#undef PS_REGNUM
+#define PS_REGNUM 17 /* (ps) Contains processor status */
+#undef PC_REGNUM
+#define PC_REGNUM 15 /* (eip) Contains program counter */
+#undef FP0_REGNUM
+#define FP0_REGNUM 20 /* Floating point register 0 */
+#undef FPC_REGNUM
+#define FPC_REGNUM 28 /* 80387 control register */
+
+/* Total amount of space needed to store our copies of the machine's
+ register state, the array `registers'. */
+
+#undef REGISTER_BYTES
+#define REGISTER_BYTES (20*4+8*10+7*4)
+
+/* Index within `registers' of the first byte of the space for
+ register N. */
+
+#undef REGISTER_BYTE
+#define REGISTER_BYTE(N) \
+ ((N) >= FPC_REGNUM ? (((N) - FPC_REGNUM) * 4) + 160 \
+ : (N) >= FP0_REGNUM ? (((N) - FP0_REGNUM) * 10) + 80 \
+ : (N) * 4)
+
+/* Number of bytes of storage in the actual machine representation
+ for register N. */
+
+#undef REGISTER_RAW_SIZE
+#define REGISTER_RAW_SIZE(N) (((unsigned)((N) - FP0_REGNUM)) < 8 ? 10 : 4)
+
+/* Number of bytes of storage in the program's representation
+ for register N. */
+
+#undef REGISTER_VIRTUAL_SIZE
+#define REGISTER_VIRTUAL_SIZE(N) (((unsigned)((N) - FP0_REGNUM)) < 8 ? 8 : 4)
+
+/* Nonzero if register N requires conversion
+ from raw format to virtual format. */
+
+#undef REGISTER_CONVERTIBLE
+#define REGISTER_CONVERTIBLE(N) (((unsigned)((N) - FP0_REGNUM)) < 8)
+
+/* Convert data from raw format for register REGNUM in buffer FROM
+ to virtual format with type TYPE in buffer TO. */
+
+#undef REGISTER_CONVERT_TO_VIRTUAL
+#define REGISTER_CONVERT_TO_VIRTUAL(REGNUM,TYPE,FROM,TO) \
+{ \
+ double val; \
+ i387_to_double ((FROM), (char *)&val); \
+ store_floating ((TO), TYPE_LENGTH (TYPE), val); \
+}
+extern void
+i387_to_double PARAMS ((char *, char *));
+
+/* Convert data from virtual format with type TYPE in buffer FROM
+ to raw format for register REGNUM in buffer TO. */
+
+#undef REGISTER_CONVERT_TO_RAW
+#define REGISTER_CONVERT_TO_RAW(TYPE,REGNUM,FROM,TO) \
+{ \
+ double val = extract_floating ((FROM), TYPE_LENGTH (TYPE)); \
+ double_to_i387((char *)&val, (TO)); \
+}
+extern void
+double_to_i387 PARAMS ((char *, char *));
+
+/* Return the GDB type object for the "standard" data type
+ of data in register N. */
+
+#undef REGISTER_VIRTUAL_TYPE
+#define REGISTER_VIRTUAL_TYPE(N) \
+ (((unsigned)((N) - FP0_REGNUM)) < 8 ? builtin_type_double : builtin_type_int)
+
+/* 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. */
+
+#undef EXTRACT_RETURN_VALUE
+#define EXTRACT_RETURN_VALUE(TYPE,REGBUF,VALBUF) \
+ memcpy (VALBUF, REGBUF + REGISTER_BYTE (TYPE_CODE (TYPE) == TYPE_CODE_FLT ? FP0_REGNUM : 11), TYPE_LENGTH (TYPE))
+
+/* Write into appropriate registers a function return value
+ of type TYPE, given in virtual format. */
+
+#undef STORE_RETURN_VALUE
+#define STORE_RETURN_VALUE(TYPE,VALBUF) \
+ write_register_bytes (REGISTER_BYTE (TYPE_CODE (TYPE) == TYPE_CODE_FLT ? FP0_REGNUM : 11), VALBUF, TYPE_LENGTH (TYPE))
+
+/* 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. */
+
+#undef FRAME_CHAIN
+#define FRAME_CHAIN(thisframe) \
+ (!inside_entry_file ((thisframe)->pc) ? \
+ read_memory_integer ((thisframe)->frame, 4) :\
+ 0)
+
+/* Define other aspects of the stack frame. */
+
+/* A macro that tells us whether the function invocation represented
+ by FI does not have a frame on the stack associated with it. If it
+ does not, FRAMELESS is set to 1, else 0. */
+
+#undef FRAMELESS_FUNCTION_INVOCATION
+#define FRAMELESS_FUNCTION_INVOCATION(FI, FRAMELESS) \
+{ (FRAMELESS) = frameless_look_for_prologue (FI); }
+
+#undef FRAME_SAVED_PC
+#define FRAME_SAVED_PC(FRAME) (read_memory_integer ((FRAME)->frame + 4, 4))
+
+/* Insert the specified number of args and function address
+ into a call sequence of the above form stored at DUMMYNAME. */
+
+#undef FIX_CALL_DUMMY
+#define FIX_CALL_DUMMY(dummyname, pc, fun, nargs, args, type, gcc_p) \
+{ \
+ *(int *)((char *)(dummyname) + 1) = (int)(fun) - (pc) - 5; \
+}
+
+#endif /* !defined (TM_SUN386_H) */
+
diff --git a/gdb/config/i386/tm-symmetry.h b/gdb/config/i386/tm-symmetry.h
new file mode 100644
index 00000000000..11931d41724
--- /dev/null
+++ b/gdb/config/i386/tm-symmetry.h
@@ -0,0 +1,321 @@
+/* Target machine definitions for GDB on a Sequent Symmetry under dynix 3.0,
+ with Weitek 1167 and i387 support.
+ Copyright 1986, 1987, 1989, 1991, 1992, 1993, 1994
+ Free Software Foundation, Inc.
+ Symmetry version by Jay Vosburgh (fubar@sequent.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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef TM_SYMMETRY_H
+#define TM_SYMMETRY_H 1
+
+/* I don't know if this will work for cross-debugging, even if you do get
+ a copy of the right include file. */
+#include <machine/reg.h>
+
+#include "i386/tm-i386v.h"
+
+#undef START_INFERIOR_TRAPS_EXPECTED
+#define START_INFERIOR_TRAPS_EXPECTED 2
+
+/* Amount PC must be decremented by after a breakpoint. This is often the
+ number of bytes in BREAKPOINT but not always (such as now). */
+
+#undef DECR_PC_AFTER_BREAK
+#define DECR_PC_AFTER_BREAK 0
+
+#if 0
+/* --- this code can't be used unless we know we are running native,
+ since it uses host specific ptrace calls. */
+/* code for 80387 fpu. Functions are from i386-dep.c, copied into
+ * symm-dep.c.
+ */
+#define FLOAT_INFO { i386_float_info(); }
+#endif
+
+/* Number of machine registers */
+
+#undef NUM_REGS
+#define NUM_REGS 49
+
+/* Initializer for an array of names of registers.
+ There should be NUM_REGS strings in this initializer. */
+
+/* Initializer for an array of names of registers. There should be at least
+ NUM_REGS strings in this initializer. Any excess ones are simply ignored.
+ Symmetry registers are in this weird order to match the register numbers
+ in the symbol table entries. If you change the order, things will probably
+ break mysteriously for no apparent reason. Also note that the st(0)...
+ st(7) 387 registers are represented as st0...st7. */
+
+#undef REGISTER_NAMES
+#define REGISTER_NAMES { "eax", "edx", "ecx", "st0", "st1", \
+ "ebx", "esi", "edi", "st2", "st3", \
+ "st4", "st5", "st6", "st7", "esp", \
+ "ebp", "eip", "eflags","fp1", "fp2", \
+ "fp3", "fp4", "fp5", "fp6", "fp7", \
+ "fp8", "fp9", "fp10", "fp11", "fp12", \
+ "fp13", "fp14", "fp15", "fp16", "fp17", \
+ "fp18", "fp19", "fp20", "fp21", "fp22", \
+ "fp23", "fp24", "fp25", "fp26", "fp27", \
+ "fp28", "fp29", "fp30", "fp31" }
+
+/* Register numbers of various important registers.
+ Note that some of these values are "real" register numbers,
+ and correspond to the general registers of the machine,
+ and some are "phony" register numbers which are too large
+ to be actual register numbers as far as the user is concerned
+ but do serve to get the desired values when passed to read_register. */
+
+#define EAX_REGNUM 0
+#define EDX_REGNUM 1
+#define ECX_REGNUM 2
+#define ST0_REGNUM 3
+#define ST1_REGNUM 4
+#define EBX_REGNUM 5
+#define ESI_REGNUM 6
+#define EDI_REGNUM 7
+#define ST2_REGNUM 8
+#define ST3_REGNUM 9
+
+#define ST4_REGNUM 10
+#define ST5_REGNUM 11
+#define ST6_REGNUM 12
+#define ST7_REGNUM 13
+
+#define FP1_REGNUM 18 /* first 1167 register */
+/* Get %fp2 - %fp31 by addition, since they are contiguous */
+
+#undef SP_REGNUM
+#define SP_REGNUM 14 /* (usp) Contains address of top of stack */
+#define ESP_REGNUM 14
+#undef FP_REGNUM
+#define FP_REGNUM 15 /* (ebp) Contains address of executing stack frame */
+#define EBP_REGNUM 15
+#undef PC_REGNUM
+#define PC_REGNUM 16 /* (eip) Contains program counter */
+#define EIP_REGNUM 16
+#undef PS_REGNUM
+#define PS_REGNUM 17 /* (ps) Contains processor status */
+#define EFLAGS_REGNUM 17
+
+/*
+ * Following macro translates i386 opcode register numbers to Symmetry
+ * register numbers. This is used by i386_frame_find_saved_regs.
+ *
+ * %eax %ecx %edx %ebx %esp %ebp %esi %edi
+ * i386 0 1 2 3 4 5 6 7
+ * Symmetry 0 2 1 5 14 15 6 7
+ *
+ */
+#define I386_REGNO_TO_SYMMETRY(n) \
+((n)==0?0 :(n)==1?2 :(n)==2?1 :(n)==3?5 :(n)==4?14 :(n)==5?15 :(n))
+
+/* The magic numbers below are offsets into u_ar0 in the user struct.
+ * They live in <machine/reg.h>. Gdb calls this macro with blockend
+ * holding u.u_ar0 - KERNEL_U_ADDR. Only the registers listed are
+ * saved in the u area (along with a few others that aren't useful
+ * here. See <machine/reg.h>).
+ */
+
+#define REGISTER_U_ADDR(addr, blockend, regno) \
+{ struct user foo; /* needed for finding fpu regs */ \
+switch (regno) { \
+ case 0: \
+ addr = blockend + EAX * sizeof(int); break; \
+ case 1: \
+ addr = blockend + EDX * sizeof(int); break; \
+ case 2: \
+ addr = blockend + ECX * sizeof(int); break; \
+ case 3: /* st(0) */ \
+ addr = ((int)&foo.u_fpusave.fpu_stack[0][0] - (int)&foo); \
+ break; \
+ case 4: /* st(1) */ \
+ addr = ((int) &foo.u_fpusave.fpu_stack[1][0] - (int)&foo); \
+ break; \
+ case 5: \
+ addr = blockend + EBX * sizeof(int); break; \
+ case 6: \
+ addr = blockend + ESI * sizeof(int); break; \
+ case 7: \
+ addr = blockend + EDI * sizeof(int); break; \
+ case 8: /* st(2) */ \
+ addr = ((int) &foo.u_fpusave.fpu_stack[2][0] - (int)&foo); \
+ break; \
+ case 9: /* st(3) */ \
+ addr = ((int) &foo.u_fpusave.fpu_stack[3][0] - (int)&foo); \
+ break; \
+ case 10: /* st(4) */ \
+ addr = ((int) &foo.u_fpusave.fpu_stack[4][0] - (int)&foo); \
+ break; \
+ case 11: /* st(5) */ \
+ addr = ((int) &foo.u_fpusave.fpu_stack[5][0] - (int)&foo); \
+ break; \
+ case 12: /* st(6) */ \
+ addr = ((int) &foo.u_fpusave.fpu_stack[6][0] - (int)&foo); \
+ break; \
+ case 13: /* st(7) */ \
+ addr = ((int) &foo.u_fpusave.fpu_stack[7][0] - (int)&foo); \
+ break; \
+ case 14: \
+ addr = blockend + ESP * sizeof(int); break; \
+ case 15: \
+ addr = blockend + EBP * sizeof(int); break; \
+ case 16: \
+ addr = blockend + EIP * sizeof(int); break; \
+ case 17: \
+ addr = blockend + FLAGS * sizeof(int); break; \
+ case 18: /* fp1 */ \
+ case 19: /* fp2 */ \
+ case 20: /* fp3 */ \
+ case 21: /* fp4 */ \
+ case 22: /* fp5 */ \
+ case 23: /* fp6 */ \
+ case 24: /* fp7 */ \
+ case 25: /* fp8 */ \
+ case 26: /* fp9 */ \
+ case 27: /* fp10 */ \
+ case 28: /* fp11 */ \
+ case 29: /* fp12 */ \
+ case 30: /* fp13 */ \
+ case 31: /* fp14 */ \
+ case 32: /* fp15 */ \
+ case 33: /* fp16 */ \
+ case 34: /* fp17 */ \
+ case 35: /* fp18 */ \
+ case 36: /* fp19 */ \
+ case 37: /* fp20 */ \
+ case 38: /* fp21 */ \
+ case 39: /* fp22 */ \
+ case 40: /* fp23 */ \
+ case 41: /* fp24 */ \
+ case 42: /* fp25 */ \
+ case 43: /* fp26 */ \
+ case 44: /* fp27 */ \
+ case 45: /* fp28 */ \
+ case 46: /* fp29 */ \
+ case 47: /* fp30 */ \
+ case 48: /* fp31 */ \
+ addr = ((int) &foo.u_fpasave.fpa_regs[(regno)-18] - (int)&foo); \
+ } \
+}
+
+/* Total amount of space needed to store our copies of the machine's
+ register state, the array `registers'. 10 i*86 registers, 8 i387
+ registers, and 31 Weitek 1167 registers */
+
+#undef REGISTER_BYTES
+#define REGISTER_BYTES ((10 * 4) + (8 * 10) + (31 * 4))
+
+/* Index within `registers' of the first byte of the space for
+ register N. */
+
+#undef REGISTER_BYTE
+#define REGISTER_BYTE(N) \
+(((N) < 3) ? ((N) * 4) : \
+((N) < 5) ? ((((N) - 2) * 10) + 2) : \
+((N) < 8) ? ((((N) - 5) * 4) + 32) : \
+((N) < 14) ? ((((N) - 8) * 10) + 44) : \
+ ((((N) - 14) * 4) + 104))
+
+/* Number of bytes of storage in the actual machine representation
+ * for register N. All registers are 4 bytes, except 387 st(0) - st(7),
+ * which are 80 bits each.
+ */
+
+#undef REGISTER_RAW_SIZE
+#define REGISTER_RAW_SIZE(N) \
+(((N) < 3) ? 4 : \
+((N) < 5) ? 10 : \
+((N) < 8) ? 4 : \
+((N) < 14) ? 10 : \
+ 4)
+
+/* Nonzero if register N requires conversion
+ from raw format to virtual format. */
+
+#undef REGISTER_CONVERTIBLE
+#define REGISTER_CONVERTIBLE(N) \
+(((N) < 3) ? 0 : \
+((N) < 5) ? 1 : \
+((N) < 8) ? 0 : \
+((N) < 14) ? 1 : \
+ 0)
+
+#include "floatformat.h"
+
+/* Convert data from raw format for register REGNUM in buffer FROM
+ to virtual format with type TYPE in buffer TO. */
+
+#undef REGISTER_CONVERT_TO_VIRTUAL
+#define REGISTER_CONVERT_TO_VIRTUAL(REGNUM,TYPE,FROM,TO) \
+{ \
+ double val; \
+ floatformat_to_double (&floatformat_i387_ext, (FROM), &val); \
+ store_floating ((TO), TYPE_LENGTH (TYPE), val); \
+}
+
+/* Convert data from virtual format with type TYPE in buffer FROM
+ to raw format for register REGNUM in buffer TO. */
+
+#undef REGISTER_CONVERT_TO_RAW
+#define REGISTER_CONVERT_TO_RAW(TYPE,REGNUM,FROM,TO) \
+{ \
+ double val = extract_floating ((FROM), TYPE_LENGTH (TYPE)); \
+ floatformat_from_double (&floatformat_i387_ext, &val, (TO)); \
+}
+
+/* Return the GDB type object for the "standard" data type
+ of data in register N. */
+
+#undef REGISTER_VIRTUAL_TYPE
+#define REGISTER_VIRTUAL_TYPE(N) \
+((N < 3) ? builtin_type_int : \
+(N < 5) ? builtin_type_double : \
+(N < 8) ? builtin_type_int : \
+(N < 14) ? builtin_type_double : \
+ builtin_type_int)
+
+/* Store the address of the place in which to copy the structure the
+ subroutine will return. This is called from call_function.
+ Native cc passes the address in eax, gcc (up to version 2.5.8)
+ passes it on the stack. gcc should be fixed in future versions to
+ adopt native cc conventions. */
+
+#undef STORE_STRUCT_RETURN
+#define STORE_STRUCT_RETURN(ADDR, SP) write_register(0, (ADDR))
+
+/* Extract from an array REGBUF containing the (raw) register state
+ a function return value of type TYPE, and copy that, in virtual format,
+ into VALBUF. */
+
+#undef EXTRACT_RETURN_VALUE
+#define EXTRACT_RETURN_VALUE(TYPE,REGBUF,VALBUF) \
+ symmetry_extract_return_value(TYPE, REGBUF, VALBUF)
+
+/* 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. */
+
+#define IN_SIGTRAMP(pc, name) ((name) && STREQ ("_sigcode", name))
+
+/* Offset to saved PC in sigcontext, from <signal.h>. */
+#define SIGCONTEXT_PC_OFFSET 16
+
+#endif /* ifndef TM_SYMMETRY_H */
+
diff --git a/gdb/config/i386/xm-cygwin.h b/gdb/config/i386/xm-cygwin.h
new file mode 100644
index 00000000000..f0b8227d2d3
--- /dev/null
+++ b/gdb/config/i386/xm-cygwin.h
@@ -0,0 +1,34 @@
+/* Definitions for hosting on WIN32, for GDB.
+ Copyright 1995, 1996, 1997, 1998 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define HOST_BYTE_ORDER LITTLE_ENDIAN
+
+#include "fopen-bin.h"
+
+#define GDBINIT_FILENAME "gdb.ini"
+
+#define SLASH_P(X) ((X)=='\\' || (X) == '/')
+#define ROOTED_P(X) ((SLASH_P((X)[0]))|| ((X)[1] ==':'))
+#define SLASH_CHAR '/'
+#define SLASH_STRING "/"
+
+/* Define this if source files use \r\n rather than just \n. */
+#define CRLF_SOURCE_FILES
+
+#define HAVE_SIGSETMASK 0
diff --git a/gdb/config/i386/xm-go32.h b/gdb/config/i386/xm-go32.h
new file mode 100644
index 00000000000..07978332207
--- /dev/null
+++ b/gdb/config/i386/xm-go32.h
@@ -0,0 +1,31 @@
+/* Definitions for hosting on GO32, for GDB.
+ Copyright 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define HOST_BYTE_ORDER LITTLE_ENDIAN
+#include "fopen-bin.h"
+
+/* Define this lseek(n) != nth byte of file */
+#define LSEEK_NOT_LINEAR
+
+#define CANT_FORK
+
+#undef QUIT
+#define QUIT { pollquit(); }
+
+#define GDBINIT_FILENAME "gdb.ini"
diff --git a/gdb/config/i386/xm-i386aix.h b/gdb/config/i386/xm-i386aix.h
new file mode 100644
index 00000000000..652a149d6cb
--- /dev/null
+++ b/gdb/config/i386/xm-i386aix.h
@@ -0,0 +1,33 @@
+/* Macro defintions for AIX PS/2 (i386)
+ Copyright 1986, 1987, 1989, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/*
+ * Changed for IBM AIX ps/2 by Minh Tran Le (tranle@intellicorp.com)
+ * Revision: 23-Oct-92 17:42:49
+ */
+
+#include "i386/xm-i386v.h"
+
+#undef HAVE_TERMIO
+#define HAVE_SGTTY
+
+#include <limits.h>
+
+/* Use setpgid instead of setpgrp on AIX */
+#define NEED_POSIX_SETPGID
diff --git a/gdb/config/i386/xm-i386bsd.h b/gdb/config/i386/xm-i386bsd.h
new file mode 100644
index 00000000000..e5c4c89f07f
--- /dev/null
+++ b/gdb/config/i386/xm-i386bsd.h
@@ -0,0 +1,22 @@
+/* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define HOST_BYTE_ORDER LITTLE_ENDIAN
+
+#include <machine/limits.h> /* for INT_MIN */
diff --git a/gdb/config/i386/xm-i386gnu.h b/gdb/config/i386/xm-i386gnu.h
new file mode 100644
index 00000000000..60307b21183
--- /dev/null
+++ b/gdb/config/i386/xm-i386gnu.h
@@ -0,0 +1,23 @@
+/* Definitions to make GDB run on the GNU Hurd on an Intel 386
+ Copyright (C) 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define HOST_BYTE_ORDER LITTLE_ENDIAN
+
+/* Do implement the attach and detach commands. */
+#define ATTACH_DETACH 1
diff --git a/gdb/config/i386/xm-i386lynx.h b/gdb/config/i386/xm-i386lynx.h
new file mode 100644
index 00000000000..6078cb6f2cb
--- /dev/null
+++ b/gdb/config/i386/xm-i386lynx.h
@@ -0,0 +1,24 @@
+/* Host-dependent definitions for Intel 386 running LynxOS.
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define HOST_BYTE_ORDER LITTLE_ENDIAN
+
+/* Get generic LynxOS host definitions. */
+
+#include "xm-lynx.h"
diff --git a/gdb/config/i386/xm-i386m3.h b/gdb/config/i386/xm-i386m3.h
new file mode 100644
index 00000000000..b667409f0da
--- /dev/null
+++ b/gdb/config/i386/xm-i386m3.h
@@ -0,0 +1,33 @@
+/* Definitions to make GDB run on Mach 3 on an Intel 386
+ Copyright (C) 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define HOST_BYTE_ORDER LITTLE_ENDIAN
+
+/* Do implement the attach and detach commands. */
+#define ATTACH_DETACH 1
+
+/* Not needeed */
+#define KERNEL_U_ADDR 0
+
+#ifndef EMULATOR_BASE
+/* For EMULATOR_BASE and EMULATOR_END.
+ * OSF 1/MK has different values in some other place.
+ */
+#include <machine/vmparam.h>
+#endif /* EMULATOR_BASE */
diff --git a/gdb/config/i386/xm-i386mach.h b/gdb/config/i386/xm-i386mach.h
new file mode 100644
index 00000000000..eb47bfb06f4
--- /dev/null
+++ b/gdb/config/i386/xm-i386mach.h
@@ -0,0 +1,30 @@
+/* Definitions to make GDB run on Mach on an Intel 386
+ Copyright (C) 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define HOST_BYTE_ORDER LITTLE_ENDIAN
+
+/* This is the amount to subtract from u.u_ar0
+ to get the offset in the core file of the register values. */
+
+#define KERNEL_U_ADDR (0x80000000 - (UPAGES * NBPG))
+
+/* <errno.h> only defines this if __STDC__!!! */
+extern int errno;
+
+extern char *strdup();
diff --git a/gdb/config/i386/xm-i386mk.h b/gdb/config/i386/xm-i386mk.h
new file mode 100644
index 00000000000..661c9cbd36c
--- /dev/null
+++ b/gdb/config/i386/xm-i386mk.h
@@ -0,0 +1,25 @@
+/* Definitions to make GDB run on Mach 3 OSF 1/MK on an Intel 386
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define HAVE_TERMIO 1
+
+#define EMULATOR_BASE 0xa0000000
+#define EMULATOR_END 0xa0040000
+
+#include "i386/xm-i386m3.h"
diff --git a/gdb/config/i386/xm-i386sco.h b/gdb/config/i386/xm-i386sco.h
new file mode 100644
index 00000000000..31fa7e6b980
--- /dev/null
+++ b/gdb/config/i386/xm-i386sco.h
@@ -0,0 +1,42 @@
+/* Macro defintions for i386, running SCO Unix System V/386 3.2.
+ Copyright (C) 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* In 3.2v4 <sys/user.h> requires on <sys/dir.h>. */
+#include <sys/types.h>
+#include <sys/dir.h>
+
+#include "i386/xm-i386v.h"
+
+/* Apparently there is inconsistency among various System V's about what
+ the name of this field is. */
+#define U_FPSTATE(u) u.u_fps.u_fpstate
+
+/* SCO 3.2v2 and later have job control. */
+/* SCO 3.2v4 I know has termios; I'm not sure about earlier versions.
+ GDB does not currently support the termio/job control combination. */
+#undef HAVE_TERMIO
+#define HAVE_TERMIOS
+
+/* SCO's assembler doesn't grok dollar signs in identifiers.
+ So we use dots instead. This item must be coordinated with G++. */
+#undef CPLUS_MARKER
+#define CPLUS_MARKER '.'
+
+/* Use setpgid instead of setpgrp on SCO */
+#define NEED_POSIX_SETPGID
diff --git a/gdb/config/i386/xm-i386v.h b/gdb/config/i386/xm-i386v.h
new file mode 100644
index 00000000000..480dfd671a0
--- /dev/null
+++ b/gdb/config/i386/xm-i386v.h
@@ -0,0 +1,45 @@
+/* Host support for i386.
+ Copyright 1986, 1987, 1989, 1992 Free Software Foundation, Inc.
+ Changes for 80386 by Pace Willisson (pace@prep.ai.mit.edu), July 1988.
+
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define HOST_BYTE_ORDER LITTLE_ENDIAN
+
+/* I'm running gdb 3.4 under 386/ix 2.0.2, which is a derivative of AT&T's
+Sys V/386 3.2.
+
+On some machines, gdb crashes when it's starting up while calling the
+vendor's termio tgetent() routine. It always works when run under
+itself (actually, under 3.2, it's not an infinitely recursive bug.)
+After some poking around, it appears that depending on the environment
+size, or whether you're running YP, or the phase of the moon or something,
+the stack is not always long-aligned when main() is called, and tgetent()
+takes strong offense at that. On some machines this bug never appears, but
+on those where it does, it occurs quite reliably. */
+#define ALIGN_STACK_ON_STARTUP
+
+/* define USG if you are using sys5 /usr/include's */
+#define USG
+
+#define HAVE_TERMIO
+
+/* 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
+
diff --git a/gdb/config/i386/xm-i386v32.h b/gdb/config/i386/xm-i386v32.h
new file mode 100644
index 00000000000..daaac8047c5
--- /dev/null
+++ b/gdb/config/i386/xm-i386v32.h
@@ -0,0 +1,24 @@
+/* Macro defintions for i386, running System V 3.2.
+ Copyright (C) 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "i386/xm-i386v.h"
+
+/* Apparently there is inconsistency among various System V's about what
+ the name of this field is. */
+#define U_FPSTATE(u) u.u_fps.u_fpstate
diff --git a/gdb/config/i386/xm-i386v4.h b/gdb/config/i386/xm-i386v4.h
new file mode 100644
index 00000000000..7f782db2496
--- /dev/null
+++ b/gdb/config/i386/xm-i386v4.h
@@ -0,0 +1,27 @@
+/* Macro definitions for GDB on an Intel i386 running SVR4.
+ Copyright 1991, 1992 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Pick up most of what we need from the generic i386 host include file. */
+
+#include "i386/xm-i386v.h"
+
+/* Pick up more stuff from the generic SVR4 host include file. */
+
+#include "xm-sysv4.h"
diff --git a/gdb/config/i386/xm-linux.h b/gdb/config/i386/xm-linux.h
new file mode 100644
index 00000000000..217c6d4d094
--- /dev/null
+++ b/gdb/config/i386/xm-linux.h
@@ -0,0 +1,36 @@
+/* Native support for GNU/Linux, for GDB, the GNU debugger.
+ Copyright (C) 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef XM_LINUX_H
+#define XM_LINUX_H
+
+#define HOST_BYTE_ORDER LITTLE_ENDIAN
+
+#define HAVE_TERMIOS
+
+/* 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 0x0
+
+#define NEED_POSIX_SETPGID
+
+/* Need R_OK etc, but USG isn't defined. */
+#include <unistd.h>
+
+#endif /* #ifndef XM_LINUX_H */
diff --git a/gdb/config/i386/xm-nbsd.h b/gdb/config/i386/xm-nbsd.h
new file mode 100644
index 00000000000..b5624acc60f
--- /dev/null
+++ b/gdb/config/i386/xm-nbsd.h
@@ -0,0 +1,21 @@
+/* Parameters for execution on a i386 running NetBSD, for GDB.
+ Copyright 1994 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Get generic NetBSD host definitions. */
+#include "xm-nbsd.h"
diff --git a/gdb/config/i386/xm-ptx.h b/gdb/config/i386/xm-ptx.h
new file mode 100644
index 00000000000..99b46ccd149
--- /dev/null
+++ b/gdb/config/i386/xm-ptx.h
@@ -0,0 +1,41 @@
+/* Definitions to make GDB run on a Sequent Symmetry under ptx, with
+ Weitek 1167 and i387 support.
+ Copyright 1986, 1987, 1989, 1992, 1993, 1996
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Symmetry version by Jay Vosburgh (fubar@sequent.com) */
+
+#ifdef _SEQUENT_PTX4_
+#include "xm-sysv4.h"
+#endif /* _SEQUENT_PTX4_ */
+
+/* This machine doesn't have the siginterrupt call. */
+#define NO_SIGINTERRUPT
+
+#define HAVE_WAIT_STRUCT
+
+#undef HAVE_TERMIO
+#define HAVE_TERMIOS
+#define USG
+
+#define NEED_POSIX_SETPGID
+
+#define USE_O_NOCTTY
+
+#define HOST_BYTE_ORDER LITTLE_ENDIAN
diff --git a/gdb/config/i386/xm-ptx4.h b/gdb/config/i386/xm-ptx4.h
new file mode 100644
index 00000000000..bdbdefd6ec8
--- /dev/null
+++ b/gdb/config/i386/xm-ptx4.h
@@ -0,0 +1,25 @@
+/* Definitions to make GDB run on a Sequent Symmetry under ptx, with
+ Weitek 1167 and i387 support. Copyright 1986, 1987, 1989, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Symmetry version by Jay Vosburgh (fubar@sequent.com) */
+
+#include "xm-sysv4.h"
+
+#include "xm-ptx.h"
diff --git a/gdb/config/i386/xm-sun386.h b/gdb/config/i386/xm-sun386.h
new file mode 100644
index 00000000000..51c3b58c11b
--- /dev/null
+++ b/gdb/config/i386/xm-sun386.h
@@ -0,0 +1,20 @@
+/* Host support for Sun 386i, for GDB, the GNU debugger.
+ Copyright (C) 1986, 1987, 1989, 1992, 1996 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define HOST_BYTE_ORDER LITTLE_ENDIAN
diff --git a/gdb/config/i386/xm-symmetry.h b/gdb/config/i386/xm-symmetry.h
new file mode 100644
index 00000000000..52e9a9a2341
--- /dev/null
+++ b/gdb/config/i386/xm-symmetry.h
@@ -0,0 +1,28 @@
+/* Definitions to make GDB run on a Sequent Symmetry under
+ dynix 3.1, with Weitek 1167 and i387 support.
+ Copyright 1986, 1987, 1989, 1992, 1993, 1994 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Symmetry version by Jay Vosburgh (fubar@sequent.com) */
+
+/* This machine doesn't have the siginterrupt call. */
+#define NO_SIGINTERRUPT
+
+#define HAVE_WAIT_STRUCT
+
+#define HOST_BYTE_ORDER LITTLE_ENDIAN
diff --git a/gdb/config/i386/xm-windows.h b/gdb/config/i386/xm-windows.h
new file mode 100644
index 00000000000..e083010067c
--- /dev/null
+++ b/gdb/config/i386/xm-windows.h
@@ -0,0 +1,35 @@
+/* Definitions for hosting on WIN32, built with Microsoft Visual C/C++, for GDB.
+ Copyright 1996, 1998 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "i386/xm-cygwin.h"
+
+#undef PRINTF_HAS_LONG_LONG
+#undef HAVE_UNISTD_H
+#undef HAVE_TERMIO_H
+#undef HAVE_TERMIOS_H
+#undef HAVE_SGTTY_H
+#undef HAVE_SBRK
+#define CANT_FORK
+
+#define MALLOC_INCOMPATIBLE
+
+#include <malloc.h>
+
+#define SIGQUIT 3
+#define SIGTRAP 5
diff --git a/gdb/config/i960/mon960.mt b/gdb/config/i960/mon960.mt
new file mode 100644
index 00000000000..6cd73459f7e
--- /dev/null
+++ b/gdb/config/i960/mon960.mt
@@ -0,0 +1,6 @@
+# Target: Intel 960 rom monitor
+TDEPFILES= i960-tdep.o monitor.o mon960-rom.o ttyflush.o xmodem.o dsrec.o
+TM_FILE= tm-mon960.h
+SIM_OBS = remote-sim.o
+SIM = ../sim/i960/libsim.a
+
diff --git a/gdb/config/i960/nindy960.mt b/gdb/config/i960/nindy960.mt
new file mode 100644
index 00000000000..f37c1da4b7c
--- /dev/null
+++ b/gdb/config/i960/nindy960.mt
@@ -0,0 +1,3 @@
+# Target: Intel 80960, in an embedded system under the NINDY monitor
+TDEPFILES= i960-tdep.o nindy-tdep.o remote-nindy.o nindy.o Onindy.o ttyflush.o
+TM_FILE= tm-nindy960.h
diff --git a/gdb/config/i960/tm-i960.h b/gdb/config/i960/tm-i960.h
new file mode 100644
index 00000000000..a6d93b00a24
--- /dev/null
+++ b/gdb/config/i960/tm-i960.h
@@ -0,0 +1,372 @@
+/* Parameters for target machine Intel 960, for GDB, the GNU debugger.
+ Copyright (C) 1990, 1991, 1993 Free Software Foundation, Inc.
+ Contributed by Intel Corporation.
+This file is part of GDB.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Definitions to target GDB to any i960. */
+
+#ifndef I80960
+#define I80960
+#endif
+
+/* Hook for the SYMBOL_CLASS of a parameter when decoding DBX symbol
+ information. In the i960, parameters can be stored as locals or as
+ args, depending on the type of the debug record.
+
+ From empirical observation, gcc960 uses N_LSYM to indicate
+ arguments passed in registers and then copied immediately
+ to the frame, and N_PSYM to indicate arguments passed in a
+ g14-relative argument block. */
+
+#define DBX_PARM_SYMBOL_CLASS(type) ((type == N_LSYM)? LOC_LOCAL_ARG: LOC_ARG)
+
+/* Byte order is configurable, but this machine runs little-endian. */
+#define TARGET_BYTE_ORDER LITTLE_ENDIAN
+
+/* We have IEEE floating point, if we have any float at all. */
+
+#define IEEE_FLOAT
+
+/* Offset from address of function to start of its code.
+ Zero on most machines. */
+
+#define FUNCTION_START_OFFSET 0
+
+/* Advance ip across any function entry prologue instructions
+ to reach some "real" code. */
+
+#define SKIP_PROLOGUE(ip) { ip = skip_prologue (ip); }
+extern CORE_ADDR skip_prologue ();
+
+/* Immediately after a function call, return the saved ip.
+ Can't always go through the frames for this because on some machines
+ the new frame is not set up until the new function
+ executes some instructions. */
+
+#define SAVED_PC_AFTER_CALL(frame) (saved_pc_after_call (frame))
+extern CORE_ADDR saved_pc_after_call ();
+
+/* Stack grows upward */
+
+#define INNER_THAN(lhs,rhs) ((lhs) > (rhs))
+
+/* Say how long (ordinary) registers are. This is a piece of bogosity
+ used in push_word and a few other places; REGISTER_RAW_SIZE is the
+ real way to know how big a register is. */
+
+#define REGISTER_SIZE 4
+
+/* Number of machine registers */
+#define NUM_REGS 40
+
+/* Initializer for an array of names of registers.
+ There should be NUM_REGS strings in this initializer. */
+
+#define REGISTER_NAMES { \
+ /* 0 */ "pfp", "sp", "rip", "r3", "r4", "r5", "r6", "r7", \
+ /* 8 */ "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",\
+ /* 16 */ "g0", "g1", "g2", "g3", "g4", "g5", "g6", "g7", \
+ /* 24 */ "g8", "g9", "g10", "g11", "g12", "g13", "g14", "fp", \
+ /* 32 */ "pcw", "ac", "tc", "ip", "fp0", "fp1", "fp2", "fp3",\
+}
+
+/* Register numbers of various important registers (used to index
+ into arrays of register names and register values). */
+
+#define R0_REGNUM 0 /* First local register */
+#define SP_REGNUM 1 /* Contains address of top of stack */
+#define RIP_REGNUM 2 /* Return instruction pointer (local r2) */
+#define R15_REGNUM 15 /* Last local register */
+#define G0_REGNUM 16 /* First global register */
+#define G13_REGNUM 29 /* g13 - holds struct return address */
+#define G14_REGNUM 30 /* g14 - ptr to arg block / leafproc return address */
+#define FP_REGNUM 31 /* Contains address of executing stack frame */
+#define PCW_REGNUM 32 /* process control word */
+#define ACW_REGNUM 33 /* arithmetic control word */
+#define TCW_REGNUM 34 /* trace control word */
+#define IP_REGNUM 35 /* instruction pointer */
+#define FP0_REGNUM 36 /* First floating point register */
+
+/* Some registers have more than one name */
+
+#define PC_REGNUM IP_REGNUM /* GDB refers to ip as the Program Counter */
+#define PFP_REGNUM R0_REGNUM /* Previous frame pointer */
+
+/* Total amount of space needed to store our copies of the machine's
+ register state, the array `registers'. */
+#define REGISTER_BYTES ((36*4) + (4*10))
+
+/* Index within `registers' of the first byte of the space for register N. */
+
+#define REGISTER_BYTE(N) ( (N) < FP0_REGNUM ? \
+ (4*(N)) : ((10*(N)) - (6*FP0_REGNUM)) )
+
+/* The i960 has register windows, sort of. */
+
+#define HAVE_REGISTER_WINDOWS
+
+/* Is this register part of the register window system? A yes answer
+ implies that 1) The name of this register will not be the same in
+ other frames, and 2) This register is automatically "saved" upon
+ subroutine calls and thus there is no need to search more than one
+ stack frame for it.
+
+ On the i960, in fact, the name of this register in another frame is
+ "mud" -- there is no overlap between the windows. Each window is
+ simply saved into the stack (true for our purposes, after having been
+ flushed; normally they reside on-chip and are restored from on-chip
+ without ever going to memory). */
+
+#define REGISTER_IN_WINDOW_P(regnum) ((regnum) <= R15_REGNUM)
+
+/* Number of bytes of storage in the actual machine representation
+ for register N. On the i960, all regs are 4 bytes except for floating
+ point, which are 10. NINDY only sends us 8 byte values for these,
+ which is a pain, but VxWorks handles this correctly, so we must. */
+
+#define REGISTER_RAW_SIZE(N) ( (N) < FP0_REGNUM ? 4 : 10 )
+
+/* Number of bytes of storage in the program's representation for register N. */
+
+#define REGISTER_VIRTUAL_SIZE(N) ( (N) < FP0_REGNUM ? 4 : 8 )
+
+/* Largest value REGISTER_RAW_SIZE can have. */
+
+#define MAX_REGISTER_RAW_SIZE 10
+
+/* Largest value REGISTER_VIRTUAL_SIZE can have. */
+
+#define MAX_REGISTER_VIRTUAL_SIZE 8
+
+/* Nonzero if register N requires conversion from raw format to virtual
+ format. */
+
+#define REGISTER_CONVERTIBLE(N) ((N) >= FP0_REGNUM)
+
+#include "floatformat.h"
+
+#define TARGET_LONG_DOUBLE_FORMAT &floatformat_i960_ext
+
+/* Convert data from raw format for register REGNUM in buffer FROM
+ to virtual format with type TYPE in buffer TO. */
+
+#define REGISTER_CONVERT_TO_VIRTUAL(REGNUM,TYPE,FROM,TO) \
+{ \
+ DOUBLEST val; \
+ floatformat_to_doublest (&floatformat_i960_ext, (FROM), &val); \
+ store_floating ((TO), TYPE_LENGTH (TYPE), val); \
+}
+
+/* Convert data from virtual format with type TYPE in buffer FROM
+ to raw format for register REGNUM in buffer TO. */
+
+#define REGISTER_CONVERT_TO_RAW(TYPE,REGNUM,FROM,TO) \
+{ \
+ DOUBLEST val = extract_floating ((FROM), TYPE_LENGTH (TYPE)); \
+ floatformat_from_doublest (&floatformat_i960_ext, &val, (TO)); \
+}
+
+/* Return the GDB type object for the "standard" data type
+ of data in register N. */
+
+#define REGISTER_VIRTUAL_TYPE(N) ((N) < FP0_REGNUM ? \
+ builtin_type_int : builtin_type_double)
+
+/* Macros for understanding function return values... */
+
+/* Does the specified function use the "struct returning" convention
+ or the "value returning" convention? The "value returning" convention
+ almost invariably returns the entire value in registers. The
+ "struct returning" convention often returns the entire value in
+ memory, and passes a pointer (out of or into the function) saying
+ where the value (is or should go).
+
+ Since this sometimes depends on whether it was compiled with GCC,
+ this is also an argument. This is used in call_function to build a
+ stack, and in value_being_returned to print return values.
+
+ On i960, a structure is returned in registers g0-g3, if it will fit.
+ If it's more than 16 bytes long, g13 pointed to it on entry. */
+
+extern use_struct_convention_fn i960_use_struct_convention;
+#define USE_STRUCT_CONVENTION(gcc_p, type) i960_use_struct_convention (gcc_p, type)
+
+/* Extract from an array REGBUF containing the (raw) register state
+ a function return value of type TYPE, and copy that, in virtual format,
+ into VALBUF. This is only called if USE_STRUCT_CONVENTION for this
+ type is 0.
+
+ On the i960 we just take as many bytes as we need from G0 through G3. */
+
+#define EXTRACT_RETURN_VALUE(TYPE,REGBUF,VALBUF) \
+ memcpy(VALBUF, REGBUF+REGISTER_BYTE(G0_REGNUM), TYPE_LENGTH (TYPE))
+
+/* If USE_STRUCT_CONVENTION produces a 1,
+ extract from an array REGBUF containing the (raw) register state
+ the address in which a function should return its structure value,
+ as a CORE_ADDR (or an expression that can be used as one).
+
+ Address of where to put structure was passed in in global
+ register g13 on entry. God knows what's in g13 now. The
+ (..., 0) below is to make it appear to return a value, though
+ actually all it does is call error(). */
+
+#define EXTRACT_STRUCT_VALUE_ADDRESS(REGBUF) \
+ (error("Don't know where large structure is returned on i960"), 0)
+
+/* Write into appropriate registers a function return value
+ of type TYPE, given in virtual format, for "value returning" functions.
+
+ For 'return' command: not (yet) implemented for i960. */
+
+#define STORE_RETURN_VALUE(TYPE,VALBUF) \
+ error ("Returning values from functions is not implemented in i960 gdb")
+
+/* Store the address of the place in which to copy the structure the
+ subroutine will return. This is called from call_function. */
+
+#define STORE_STRUCT_RETURN(ADDR, SP) \
+ error ("Returning values from functions is not implemented in i960 gdb")
+
+/* 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.
+
+ However, if FRAME_CHAIN_VALID returns zero,
+ it means the given frame is the outermost one and has no caller. */
+
+/* We cache information about saved registers in the frame structure,
+ to save us from having to re-scan function prologues every time
+ a register in a non-current frame is accessed. */
+
+#define EXTRA_FRAME_INFO \
+ struct frame_saved_regs *fsr; \
+ CORE_ADDR arg_pointer;
+
+/* Zero the frame_saved_regs pointer when the frame is initialized,
+ so that FRAME_FIND_SAVED_REGS () will know to allocate and
+ initialize a frame_saved_regs struct the first time it is called.
+ Set the arg_pointer to -1, which is not valid; 0 and other values
+ indicate real, cached values. */
+
+#define INIT_EXTRA_FRAME_INFO(fromleaf, fi) \
+ ((fi)->fsr = 0, (fi)->arg_pointer = -1)
+
+/* On the i960, we get the chain pointer by reading the PFP saved
+ on the stack and clearing the status bits. */
+
+#define FRAME_CHAIN(thisframe) \
+ (read_memory_integer (FRAME_FP(thisframe), 4) & ~0xf)
+
+/* FRAME_CHAIN_VALID returns zero if the given frame is the outermost one
+ and has no caller.
+
+ On the i960, each various target system type must define FRAME_CHAIN_VALID,
+ since it differs between NINDY and VxWorks, the two currently supported
+ targets types. We leave it undefined here. */
+
+
+/* A macro that tells us whether the function invocation represented
+ by FI does not have a frame on the stack associated with it. If it
+ does not, FRAMELESS is set to 1, else 0. */
+
+#define FRAMELESS_FUNCTION_INVOCATION(FI, FRAMELESS) \
+ { (FRAMELESS) = (leafproc_return ((FI)->pc) != 0); }
+
+/* Note that in the i960 architecture the return pointer is saved in the
+ *caller's* stack frame.
+
+ Make sure to zero low-order bits because of bug in 960CA A-step part
+ (instruction addresses should always be word-aligned anyway). */
+
+#define FRAME_SAVED_PC(frame) \
+ ((read_memory_integer(FRAME_CHAIN(frame)+8,4)) & ~3)
+
+/* On the i960, FRAME_ARGS_ADDRESS should return the value of
+ g14 as passed into the frame, if known. We need a function for this.
+ We cache this value in the frame info if we've already looked it up. */
+
+#define FRAME_ARGS_ADDRESS(fi) \
+ (((fi)->arg_pointer != -1)? (fi)->arg_pointer: frame_args_address (fi, 0))
+extern CORE_ADDR frame_args_address (); /* i960-tdep.c */
+
+/* This is the same except it should return 0 when
+ it does not really know where the args are, rather than guessing.
+ This value is not cached since it is only used infrequently. */
+
+#define FRAME_ARGS_ADDRESS_CORRECT(fi) (frame_args_address (fi, 1))
+
+#define FRAME_LOCALS_ADDRESS(fi) (fi)->frame
+
+/* Set NUMARGS to the number of args passed to a frame.
+ Can return -1, meaning no way to tell. */
+
+#define FRAME_NUM_ARGS(numargs, fi) (numargs = -1)
+
+/* Return number of bytes at start of arglist that are not really args. */
+
+#define FRAME_ARGS_SKIP 0
+
+/* Produce the positions of the saved registers in a stack frame. */
+
+#define FRAME_FIND_SAVED_REGS(frame_info_addr, sr) \
+ frame_find_saved_regs (frame_info_addr, &sr)
+extern void frame_find_saved_regs(); /* See i960-tdep.c */
+
+/* Things needed for making calls to functions in the inferior process */
+
+/* Push an empty stack frame, to record the current ip, etc.
+
+ Not (yet?) implemented for i960. */
+
+#define PUSH_DUMMY_FRAME \
+error("Function calls into the inferior process are not supported on the i960")
+
+/* Discard from the stack the innermost frame, restoring all registers. */
+
+#define POP_FRAME \
+ pop_frame ()
+
+
+/* This sequence of words is the instructions
+
+ callx 0x00000000
+ fmark
+ */
+
+/* #define CALL_DUMMY { 0x86003000, 0x00000000, 0x66003e00 } */
+
+/* #define CALL_DUMMY_START_OFFSET 0 *//* Start execution at beginning of dummy */
+
+/* Indicate that we don't support calling inferior child functions. */
+
+#undef CALL_DUMMY
+
+/* Insert the specified number of args and function address
+ into a call sequence of the above form stored at 'dummyname'.
+
+ Ignore arg count on i960. */
+
+/* #define FIX_CALL_DUMMY(dummyname, fun, nargs) *(((int *)dummyname)+1) = fun */
+
+#undef FIX_CALL_DUMMY
+
+
+/* Interface definitions for kernel debugger KDB */
+/* (Not relevant to i960.) */
diff --git a/gdb/config/i960/tm-mon960.h b/gdb/config/i960/tm-mon960.h
new file mode 100644
index 00000000000..e441e052b5a
--- /dev/null
+++ b/gdb/config/i960/tm-mon960.h
@@ -0,0 +1,70 @@
+/* Parameters for Intel 960 running MON960 monitor, for GDB, the GNU debugger.
+ Copyright (C) 1990-1991 Free Software Foundation, Inc.
+ Contributed by Intel Corporation and Cygnus Support.
+
+This file is part of GDB.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/*****************************************************************************
+ * Definitions to target GDB to an i960 debugged over a serial line.
+ ******************************************************************************/
+
+#include "i960/tm-i960.h"
+
+/* forward declarations */
+#ifdef __STDC__
+struct frame_info;
+#endif
+
+/* redefined from tm-i960.h */
+/* Number of machine registers */
+#undef NUM_REGS
+#define NUM_REGS 40
+
+/* Initializer for an array of names of registers.
+ There should be NUM_REGS strings in this initializer. */
+#undef REGISTER_NAMES
+#define REGISTER_NAMES { \
+ /* 0 */ "pfp", "sp", "rip", "r3", "r4", "r5", "r6", "r7", \
+ /* 8 */ "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",\
+ /* 16 */ "g0", "g1", "g2", "g3", "g4", "g5", "g6", "g7", \
+ /* 24 */ "g8", "g9", "g10", "g11", "g12", "g13", "g14", "fp", \
+ /* 32 */ "pc", "ac", "tc", "ip", "fp0", "fp1", "fp2", "fp3",\
+}
+
+/* Override the standard gdb prompt when compiled for this target. */
+
+#define DEFAULT_PROMPT "(gdb960) "
+
+/* FRAME_CHAIN_VALID returns zero if the given frame is the outermost one
+ and has no caller.
+
+ On the i960, each various target system type defines FRAME_CHAIN_VALID,
+ since it differs between Nindy, Mon960 and VxWorks, the currently supported
+ target types. */
+
+extern int mon960_frame_chain_valid PARAMS ((CORE_ADDR, struct frame_info *));
+#define FRAME_CHAIN_VALID(chain, thisframe) mon960_frame_chain_valid (chain, thisframe)
+
+/* Sequence of bytes for breakpoint instruction */
+
+#define BREAKPOINT {0x00, 0x3e, 0x00, 0x66}
+
+/* Amount ip must be decremented by after a breakpoint.
+ * This is often the number of bytes in BREAKPOINT but not always.
+ */
+
+#define DECR_PC_AFTER_BREAK 4
diff --git a/gdb/config/i960/tm-nindy960.h b/gdb/config/i960/tm-nindy960.h
new file mode 100644
index 00000000000..d0c46c0a39f
--- /dev/null
+++ b/gdb/config/i960/tm-nindy960.h
@@ -0,0 +1,106 @@
+/* Parameters for Intel 960 running NINDY monitor, for GDB, the GNU debugger.
+ Copyright (C) 1990-1991 Free Software Foundation, Inc.
+ Contributed by Intel Corporation and Cygnus Support.
+
+This file is part of GDB.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/*****************************************************************************
+ * Definitions to target GDB to an i960 debugged over a serial line.
+ ******************************************************************************/
+
+#include "i960/tm-i960.h"
+
+/* forward declarations */
+#ifdef __STDC__
+struct frame_info;
+#endif
+
+/* Override the standard gdb prompt when compiled for this target. */
+
+#define DEFAULT_PROMPT "(gdb960) "
+
+/* Additional command line options accepted by nindy gdb's, for handling
+ the remote-nindy.c interface. These should really be target-specific
+ rather than architecture-specific. */
+
+extern int nindy_old_protocol; /* nonzero if old NINDY serial protocol */
+extern int nindy_initial_brk; /* Send a BREAK to reset board first */
+extern char *nindy_ttyname; /* Name of serial port to talk to nindy */
+
+#define ADDITIONAL_OPTIONS \
+ {"O", no_argument, &nindy_old_protocol, 1}, \
+ {"brk", no_argument, &nindy_initial_brk, 1}, \
+ {"ser", required_argument, 0, 1004}, /* 1004 is magic cookie for ADDL_CASES */
+
+#define ADDITIONAL_OPTION_CASES \
+ case 1004: /* -ser option: remote nindy auto-start */ \
+ nindy_ttyname = optarg; \
+ break;
+
+#define ADDITIONAL_OPTION_HELP \
+ "\
+ -O Use old protocol to talk to a Nindy target\n\
+ -brk Send a break to a Nindy target to reset it.\n\
+ -ser SERIAL Open remote Nindy session to SERIAL port.\n\
+"
+
+/* If specified on the command line, open tty for talking to nindy,
+ and download the executable file if one was specified. */
+
+#define ADDITIONAL_OPTION_HANDLER \
+ if (!SET_TOP_LEVEL () && nindy_ttyname) { \
+ nindy_open (nindy_ttyname, !batch); \
+ if (!SET_TOP_LEVEL () && execarg) { \
+ target_load (execarg, !batch); \
+ } \
+ }
+
+/* If configured for i960 target, we take control before main loop
+ and demand that we configure for a nindy target. */
+
+#define BEFORE_MAIN_LOOP_HOOK \
+ nindy_before_main_loop();
+
+extern void
+nindy_before_main_loop(); /* In remote-nindy.c */
+
+/* FRAME_CHAIN_VALID returns zero if the given frame is the outermost one
+ and has no caller.
+
+ On the i960, each various target system type defines FRAME_CHAIN_VALID,
+ since it differs between NINDY and VxWorks, the two currently supported
+ targets types. */
+
+extern int nindy_frame_chain_valid PARAMS ((CORE_ADDR, struct frame_info *));
+#define FRAME_CHAIN_VALID(chain, thisframe) nindy_frame_chain_valid (chain, thisframe)
+
+extern int
+nindy_frame_chain_valid(); /* See nindy-tdep.c */
+
+/* Sequence of bytes for breakpoint instruction */
+
+#define BREAKPOINT {0x00, 0x3e, 0x00, 0x66}
+
+/* Amount ip must be decremented by after a breakpoint.
+ * This is often the number of bytes in BREAKPOINT but not always.
+ */
+
+#define DECR_PC_AFTER_BREAK 0
+
+#undef REGISTER_CONVERT_TO_VIRTUAL
+#undef REGISTER_CONVERT_TO_RAW
+#undef REGISTER_CONVERTIBLE
diff --git a/gdb/config/i960/tm-vx960.h b/gdb/config/i960/tm-vx960.h
new file mode 100644
index 00000000000..17e28119b29
--- /dev/null
+++ b/gdb/config/i960/tm-vx960.h
@@ -0,0 +1,53 @@
+/* Parameters for VxWorks Intel 960's, for GDB, the GNU debugger.
+ Copyright (C) 1986-1991 Free Software Foundation, Inc.
+ Contributed by Cygnus Support.
+
+This file is part of GDB.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "i960/tm-i960.h"
+
+/* Under VxWorks the IP isn't filled in. Skip it, go with RIP, which has
+ the real value. */
+#undef PC_REGNUM
+#define PC_REGNUM RIP_REGNUM
+
+#define GDBINIT_FILENAME ".vxgdbinit"
+
+#define DEFAULT_PROMPT "(vxgdb) "
+
+/* We have more complex, useful breakpoints on the target.
+ Amount ip must be decremented by after a breakpoint. */
+
+#define DECR_PC_AFTER_BREAK 0
+
+/* We are guaranteed to have a zero frame pointer at bottom of stack, too. */
+
+#define FRAME_CHAIN_VALID(chain, thisframe) nonnull_frame_chain_valid (chain, thisframe)
+
+/* Breakpoint patching is handled at the target end in VxWorks. */
+/* #define BREAKPOINT {0x00, 0x3e, 0x00, 0x66} */
+
+/* Number of registers in a ptrace_getregs call. */
+
+#define VX_NUM_REGS (16 + 16 + 3)
+
+/* Number of registers in a ptrace_getfpregs call. */
+
+ /* @@ Can't use this -- the rdb library for the 960 target
+ doesn't support setting or retrieving FP regs. KR */
+
+/* #define VX_SIZE_FPREGS (REGISTER_RAW_SIZE (FP0_REGNUM) * 4) */
diff --git a/gdb/config/i960/vxworks960.mt b/gdb/config/i960/vxworks960.mt
new file mode 100644
index 00000000000..ad3293421f7
--- /dev/null
+++ b/gdb/config/i960/vxworks960.mt
@@ -0,0 +1,6 @@
+# Target: VxWorks running on an Intel 960
+TDEPFILES= i960-tdep.o remote-vx.o remote-vx960.o xdr_ld.o xdr_ptrace.o xdr_rdb.o
+TM_FILE= tm-vx960.h
+
+# Define this for the vx-share routines, which don't see param.h.
+MT_CFLAGS= -DI80960
diff --git a/gdb/config/m32r/m32r.mt b/gdb/config/m32r/m32r.mt
new file mode 100644
index 00000000000..8b957059ca1
--- /dev/null
+++ b/gdb/config/m32r/m32r.mt
@@ -0,0 +1,7 @@
+# Target: Mitsubishi m32r processor
+TDEPFILES= m32r-tdep.o monitor.o m32r-rom.o dsrec.o
+TM_FILE= tm-m32r.h
+SIM_OBS = remote-sim.o
+SIM = ../sim/m32r/libsim.a
+GDBSERVER_DEPFILES= low-sim.o
+GDBSERVER_LIBS = ../../sim/m32r/libsim.a ../../bfd/libbfd.a ../../libiberty/libiberty.a ../../opcodes/libopcodes.a
diff --git a/gdb/config/m32r/tm-m32r.h b/gdb/config/m32r/tm-m32r.h
new file mode 100644
index 00000000000..8273b4e7fde
--- /dev/null
+++ b/gdb/config/m32r/tm-m32r.h
@@ -0,0 +1,234 @@
+/* Parameters for execution on a Mitsubishi m32r processor.
+ Copyright 1996, 1997 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Used by mswin. */
+#define TARGET_M32R 1
+
+/* mvs_check TARGET_BYTE_ORDER BIG_ENDIAN */
+#define TARGET_BYTE_ORDER BIG_ENDIAN
+
+/* mvs_check REGISTER_NAMES */
+#define REGISTER_NAMES \
+{ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", \
+ "r8", "r9", "r10", "r11", "r12", "fp", "lr", "sp", \
+ "psw", "cbr", "spi", "spu", "bpc", "pc", "accl", "acch", \
+ /* "cond", "sm", "bsm", "ie", "bie", "bcarry", */ \
+}
+/* mvs_check NUM_REGS */
+#define NUM_REGS 24
+
+/* mvs_check REGISTER_SIZE */
+#define REGISTER_SIZE 4
+/* mvs_check MAX_REGISTER_RAW_SIZE */
+#define MAX_REGISTER_RAW_SIZE 4
+
+/* mvs_check *_REGNUM */
+#define R0_REGNUM 0
+#define STRUCT_RETURN_REGNUM 0
+#define ARG0_REGNUM 0
+#define ARGLAST_REGNUM 3
+#define V0_REGNUM 0
+#define V1_REGNUM 1
+#define FP_REGNUM 13
+#define RP_REGNUM 14
+#define SP_REGNUM 15
+#define PSW_REGNUM 16
+#define CBR_REGNUM 17
+#define SPI_REGNUM 18
+#define SPU_REGNUM 19
+#define BPC_REGNUM 20
+#define PC_REGNUM 21
+#define ACCL_REGNUM 22
+#define ACCH_REGNUM 23
+
+/* mvs_check REGISTER_BYTES */
+#define REGISTER_BYTES (NUM_REGS * 4)
+
+/* mvs_check REGISTER_VIRTUAL_TYPE */
+#define REGISTER_VIRTUAL_TYPE(REG) builtin_type_int
+
+/* mvs_check REGISTER_BYTE */
+#define REGISTER_BYTE(REG) ((REG) * 4)
+/* mvs_check REGISTER_VIRTUAL_SIZE */
+#define REGISTER_VIRTUAL_SIZE(REG) 4
+/* mvs_check REGISTER_RAW_SIZE */
+#define REGISTER_RAW_SIZE(REG) 4
+
+/* mvs_check MAX_REGISTER_VIRTUAL_SIZE */
+#define MAX_REGISTER_VIRTUAL_SIZE 4
+
+/* mvs_check BREAKPOINT */
+#define BREAKPOINT {0x10, 0xf1}
+
+/* mvs_no_check FUNCTION_START_OFFSET */
+#define FUNCTION_START_OFFSET 0
+
+/* mvs_check DECR_PC_AFTER_BREAK */
+#define DECR_PC_AFTER_BREAK 0
+
+/* mvs_check INNER_THAN */
+#define INNER_THAN(lhs,rhs) ((lhs) < (rhs))
+
+/* mvs_check SAVED_PC_AFTER_CALL */
+#define SAVED_PC_AFTER_CALL(fi) read_register (RP_REGNUM)
+
+#ifdef __STDC__
+struct frame_info;
+struct frame_saved_regs;
+struct type;
+struct value;
+#endif
+
+/* Define other aspects of the stack frame.
+ We keep the offsets of all saved registers, 'cause we need 'em a lot!
+ We also keep the current size of the stack frame, and whether
+ the frame pointer is valid (for frameless functions, and when we're
+ still in the prologue of a function with a frame) */
+
+/* mvs_check EXTRA_FRAME_INFO */
+#define EXTRA_FRAME_INFO \
+ struct frame_saved_regs fsr; \
+ int framesize; \
+ int using_frame_pointer;
+
+
+extern void m32r_init_extra_frame_info PARAMS ((struct frame_info *fi));
+/* mvs_check INIT_EXTRA_FRAME_INFO */
+#define INIT_EXTRA_FRAME_INFO(fromleaf, fi) m32r_init_extra_frame_info (fi)
+/* mvs_no_check INIT_FRAME_PC */
+#define INIT_FRAME_PC /* Not necessary */
+
+extern void
+m32r_frame_find_saved_regs PARAMS ((struct frame_info *fi,
+ struct frame_saved_regs *regaddr));
+
+/* 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. */
+
+/* mvs_check FRAME_FIND_SAVED_REGS */
+#define FRAME_FIND_SAVED_REGS(frame_info, frame_saved_regs) \
+ m32r_frame_find_saved_regs(frame_info, &(frame_saved_regs))
+
+extern CORE_ADDR m32r_frame_chain PARAMS ((struct frame_info *fi));
+/* mvs_check FRAME_CHAIN */
+#define FRAME_CHAIN(fi) m32r_frame_chain (fi)
+
+#define FRAME_CHAIN_VALID(fp, frame) generic_frame_chain_valid (fp, frame)
+
+extern CORE_ADDR m32r_find_callers_reg PARAMS ((struct frame_info *fi,
+ int regnum));
+extern CORE_ADDR m32r_frame_saved_pc PARAMS((struct frame_info *));
+/* mvs_check FRAME_SAVED_PC */
+#define FRAME_SAVED_PC(fi) m32r_frame_saved_pc (fi)
+
+/* mvs_check EXTRACT_RETURN_VALUE */
+#define EXTRACT_RETURN_VALUE(TYPE, REGBUF, VALBUF) \
+ memcpy ((VALBUF), \
+ (char *)(REGBUF) + REGISTER_BYTE (V0_REGNUM) + \
+ ((TYPE_LENGTH (TYPE) > 4 ? 8 : 4) - TYPE_LENGTH (TYPE)), \
+ TYPE_LENGTH (TYPE))
+
+/* mvs_check STORE_RETURN_VALUE */
+#define STORE_RETURN_VALUE(TYPE, VALBUF) \
+ write_register_bytes(REGISTER_BYTE (V0_REGNUM) + \
+ ((TYPE_LENGTH (TYPE) > 4 ? 8:4) - TYPE_LENGTH (TYPE)),\
+ (VALBUF), TYPE_LENGTH (TYPE));
+
+extern CORE_ADDR m32r_skip_prologue PARAMS ((CORE_ADDR pc));
+/* mvs_check SKIP_PROLOGUE */
+#define SKIP_PROLOGUE(pc) pc = m32r_skip_prologue (pc)
+
+/* mvs_no_check FRAME_ARGS_SKIP */
+#define FRAME_ARGS_SKIP 0
+
+/* mvs_no_check FRAME_ARGS_ADDRESS */
+#define FRAME_ARGS_ADDRESS(fi) ((fi)->frame)
+/* mvs_no_check FRAME_LOCALS_ADDRESS */
+#define FRAME_LOCALS_ADDRESS(fi) ((fi)->frame)
+/* mvs_no_check FRAME_NUM_ARGS */
+#define FRAME_NUM_ARGS(val, fi) ((val) = -1)
+
+#define COERCE_FLOAT_TO_DOUBLE 1
+
+#define TARGET_WRITE_SP m32r_write_sp
+
+
+
+
+
+
+/* struct passing and returning stuff */
+#define STORE_STRUCT_RETURN(STRUCT_ADDR, SP) \
+ write_register (0, STRUCT_ADDR)
+
+extern use_struct_convention_fn m32r_use_struct_convention;
+#define USE_STRUCT_CONVENTION(GCC_P, TYPE) m32r_use_struct_convention (GCC_P, TYPE)
+
+#define EXTRACT_STRUCT_VALUE_ADDRESS(REGBUF) \
+ extract_address (REGBUF + REGISTER_BYTE (V0_REGNUM), \
+ REGISTER_RAW_SIZE (V0_REGNUM))
+
+#define REG_STRUCT_HAS_ADDR(gcc_p,type) (TYPE_LENGTH (type) > 8)
+
+
+/* generic dummy frame stuff */
+
+#define PUSH_DUMMY_FRAME generic_push_dummy_frame ()
+#define PC_IN_CALL_DUMMY(PC, SP, FP) generic_pc_in_call_dummy (PC, SP)
+
+
+/* target-specific dummy_frame stuff */
+
+extern struct frame_info *m32r_pop_frame PARAMS ((struct frame_info *frame));
+/* mvs_check POP_FRAME */
+#define POP_FRAME m32r_pop_frame (get_current_frame ())
+
+/* mvs_no_check STACK_ALIGN */
+/* #define STACK_ALIGN(x) ((x + 3) & ~3) */
+
+extern CORE_ADDR m32r_push_return_address PARAMS ((CORE_ADDR, CORE_ADDR));
+extern CORE_ADDR m32r_push_arguments PARAMS ((int nargs,
+ struct value **args,
+ CORE_ADDR sp,
+ unsigned char struct_return,
+ CORE_ADDR struct_addr));
+
+
+
+/* mvs_no_check PUSH_ARGUMENTS */
+#define PUSH_ARGUMENTS(NARGS, ARGS, SP, STRUCT_RETURN, STRUCT_ADDR) \
+ (SP) = m32r_push_arguments (NARGS, ARGS, SP, STRUCT_RETURN, STRUCT_ADDR)
+
+#define PUSH_RETURN_ADDRESS(PC, SP) m32r_push_return_address (PC, SP)
+
+/* override the standard get_saved_register function with
+ one that takes account of generic CALL_DUMMY frames */
+#define GET_SAVED_REGISTER
+
+#define USE_GENERIC_DUMMY_FRAMES
+#define CALL_DUMMY {0}
+#define CALL_DUMMY_LENGTH (0)
+#define CALL_DUMMY_START_OFFSET (0)
+#define CALL_DUMMY_BREAKPOINT_OFFSET (0)
+#define FIX_CALL_DUMMY(DUMMY1, STARTADDR, FUNADDR, NARGS, ARGS, TYPE, GCCP)
+#define CALL_DUMMY_LOCATION AT_ENTRY_POINT
+#define CALL_DUMMY_ADDRESS() entry_point_address ()
diff --git a/gdb/config/m68k/3b1.mh b/gdb/config/m68k/3b1.mh
new file mode 100644
index 00000000000..2516ccedb5b
--- /dev/null
+++ b/gdb/config/m68k/3b1.mh
@@ -0,0 +1,12 @@
+# Host: AT&T 3b1/Unix pc
+# I don't think cc has been tried. -traditional for <sys/ioctl.h>
+# (not sure whether necessary).
+CC= gcc -traditional
+# GCC runs out of virtual memory.
+# A separate CC for pinsn routines is no longer supported, though.
+# FIXME -- someone unlucky enough to have a 3B1, let bug-gcc@prep.ai.mit.edu
+# know what works and what fails on the 3B1.
+#PINSN_CC= cc
+
+XDEPFILES= infptrace.o inftarg.o fork-child.o corelow.o core-aout.o
+XM_FILE= xm-3b1.h
diff --git a/gdb/config/m68k/3b1.mt b/gdb/config/m68k/3b1.mt
new file mode 100644
index 00000000000..4c5d9d4bb07
--- /dev/null
+++ b/gdb/config/m68k/3b1.mt
@@ -0,0 +1,3 @@
+# Target: AT&T 3b1/Unix pc
+TDEPFILES= m68k-tdep.o
+TM_FILE= tm-3b1.h
diff --git a/gdb/config/m68k/altos.mh b/gdb/config/m68k/altos.mh
new file mode 100644
index 00000000000..1073751fd76
--- /dev/null
+++ b/gdb/config/m68k/altos.mh
@@ -0,0 +1,5 @@
+# Host: Altos 3068 (m68k, System V release 2)
+
+XM_FILE= xm-altos.h
+XDEPFILES= infptrace.o inftarg.o fork-child.o altos-xdep.o
+
diff --git a/gdb/config/m68k/altos.mt b/gdb/config/m68k/altos.mt
new file mode 100644
index 00000000000..521e958bfed
--- /dev/null
+++ b/gdb/config/m68k/altos.mt
@@ -0,0 +1,3 @@
+# Target: Altos 3068 (m68k, System V release 2)
+TDEPFILES= m68k-tdep.o
+TM_FILE= tm-altos.h
diff --git a/gdb/config/m68k/apollo68b.mh b/gdb/config/m68k/apollo68b.mh
new file mode 100644
index 00000000000..6f554978939
--- /dev/null
+++ b/gdb/config/m68k/apollo68b.mh
@@ -0,0 +1,6 @@
+# Host: Apollo m68k, BSD mode.
+
+XM_FILE= xm-apollo68b.h
+XDEPFILES=
+NAT_FILE= nm-apollo68b.h
+NATDEPFILES= infptrace.o inftarg.o fork-child.o a68v-nat.o
diff --git a/gdb/config/m68k/apollo68b.mt b/gdb/config/m68k/apollo68b.mt
new file mode 100644
index 00000000000..2383d3b6156
--- /dev/null
+++ b/gdb/config/m68k/apollo68b.mt
@@ -0,0 +1,3 @@
+# Target: Apollo m68k in BSD mode
+TDEPFILES= m68k-tdep.o dstread.o
+TM_FILE= tm-apollo68b.h
diff --git a/gdb/config/m68k/apollo68v.mh b/gdb/config/m68k/apollo68v.mh
new file mode 100644
index 00000000000..9204f111b06
--- /dev/null
+++ b/gdb/config/m68k/apollo68v.mh
@@ -0,0 +1,11 @@
+# Host: Apollo, System V mode (?)
+
+XM_FILE= xm-apollo68v.h
+XM_CLIBS= -lPW
+XDEPFILES=
+
+NAT_FILE= nm-apollo68v.h
+NATDEPFILES= infptrace.o inftarg.o fork-child.o a68v-nat.o
+
+RANLIB=echo >/dev/null
+CC= cc -A ansi -A runtype,any -A systype,any -U__STDC__ -DNO_SYS_FILE
diff --git a/gdb/config/m68k/cisco.mt b/gdb/config/m68k/cisco.mt
new file mode 100644
index 00000000000..bc2e9214d7f
--- /dev/null
+++ b/gdb/config/m68k/cisco.mt
@@ -0,0 +1,3 @@
+# Target: Cisco Router with 68K processor
+TDEPFILES= m68k-tdep.o corelow.o core-aout.o
+TM_FILE= tm-cisco.h
diff --git a/gdb/config/m68k/delta68.mh b/gdb/config/m68k/delta68.mh
new file mode 100644
index 00000000000..5492af08d73
--- /dev/null
+++ b/gdb/config/m68k/delta68.mh
@@ -0,0 +1,5 @@
+# Host: Motorola Delta Series sysV68 R3V7.1
+
+XM_FILE= xm-delta68.h
+NAT_FILE= nm-delta68.h
+NATDEPFILES= infptrace.o inftarg.o fork-child.o corelow.o core-aout.o delta68-nat.o
diff --git a/gdb/config/m68k/delta68.mt b/gdb/config/m68k/delta68.mt
new file mode 100644
index 00000000000..2761329f2c8
--- /dev/null
+++ b/gdb/config/m68k/delta68.mt
@@ -0,0 +1,3 @@
+# Motorola Delta Series sysV68 R3V7.1
+TDEPFILES= m68k-tdep.o
+TM_FILE= tm-delta68.h
diff --git a/gdb/config/m68k/dpx2.mh b/gdb/config/m68k/dpx2.mh
new file mode 100644
index 00000000000..4f22ed538ac
--- /dev/null
+++ b/gdb/config/m68k/dpx2.mh
@@ -0,0 +1,7 @@
+# Host: Bull DPX2 (68k, System V release 3)
+
+XM_FILE= xm-dpx2.h
+XDEPFILES=
+
+NAT_FILE= nm-dpx2.h
+NATDEPFILES= infptrace.o corelow.o core-aout.o inftarg.o dpx2-nat.o fork-child.o
diff --git a/gdb/config/m68k/dpx2.mt b/gdb/config/m68k/dpx2.mt
new file mode 100644
index 00000000000..5bbbbe6fd8d
--- /dev/null
+++ b/gdb/config/m68k/dpx2.mt
@@ -0,0 +1,3 @@
+# Target: Bull DPX2 (68k, System V release 3)
+TDEPFILES= m68k-tdep.o
+TM_FILE= tm-dpx2.h
diff --git a/gdb/config/m68k/es1800.mt b/gdb/config/m68k/es1800.mt
new file mode 100644
index 00000000000..d809c610718
--- /dev/null
+++ b/gdb/config/m68k/es1800.mt
@@ -0,0 +1,9 @@
+# Target: Ericsson ES-1800 emulator (remote) for m68k.
+
+# remote-es.o should perhaps be part of the standard monitor.mt
+# configuration, if it is desirable to reduce the number of different
+# configurations. However, before that happens remote-es.c has to be
+# fixed to compile on a DOS host.
+
+TDEPFILES= m68k-tdep.o remote-es.o
+TM_FILE= tm-es1800.h
diff --git a/gdb/config/m68k/hp300bsd.mh b/gdb/config/m68k/hp300bsd.mh
new file mode 100644
index 00000000000..3ca036250f8
--- /dev/null
+++ b/gdb/config/m68k/hp300bsd.mh
@@ -0,0 +1,7 @@
+# Host: Hewlett-Packard 9000 series 300, running BSD
+
+XM_FILE= xm-hp300bsd.h
+XDEPFILES=
+
+NAT_FILE= nm-hp300bsd.h
+NATDEPFILES= infptrace.o inftarg.o fork-child.o corelow.o core-aout.o
diff --git a/gdb/config/m68k/hp300bsd.mt b/gdb/config/m68k/hp300bsd.mt
new file mode 100644
index 00000000000..cbcc5edb7db
--- /dev/null
+++ b/gdb/config/m68k/hp300bsd.mt
@@ -0,0 +1,3 @@
+# Target: Hewlett-Packard 9000 series 300, running BSD
+TDEPFILES= m68k-tdep.o
+TM_FILE= tm-hp300bsd.h
diff --git a/gdb/config/m68k/hp300hpux.mh b/gdb/config/m68k/hp300hpux.mh
new file mode 100644
index 00000000000..8ceb1872ca5
--- /dev/null
+++ b/gdb/config/m68k/hp300hpux.mh
@@ -0,0 +1,8 @@
+# Host: Hewlett-Packard 9000 series 300, running HPUX
+# The following is true because gcc uses a different .o file format
+# than the native HPUX compiler
+
+XM_FILE= xm-hp300hpux.h
+
+NAT_FILE= nm-hp300hpux.h
+NATDEPFILES= infptrace.o inftarg.o fork-child.o hp300ux-nat.o corelow.o core-aout.o
diff --git a/gdb/config/m68k/hp300hpux.mt b/gdb/config/m68k/hp300hpux.mt
new file mode 100644
index 00000000000..0fa801dee25
--- /dev/null
+++ b/gdb/config/m68k/hp300hpux.mt
@@ -0,0 +1,8 @@
+# Target: Hewlett-Packard 9000 series 300, running HPUX
+
+#msg Note that GDB can only read symbols from programs that were
+#msg compiled with GCC using GAS.
+#msg
+
+TDEPFILES= m68k-tdep.o
+TM_FILE= tm-hp300hpux.h
diff --git a/gdb/config/m68k/isi.mh b/gdb/config/m68k/isi.mh
new file mode 100644
index 00000000000..c406b4c51d8
--- /dev/null
+++ b/gdb/config/m68k/isi.mh
@@ -0,0 +1,5 @@
+# Host: ISI Optimum V (3.05) under 4.3bsd.
+# corelow.o commented out because core dumps are broken on this machine,
+# as of GDB 4.8, according to lam@tfs.com
+XDEPFILES= infptrace.o inftarg.o fork-child.o core-aout.o isi-xdep.o
+XM_FILE= xm-isi.h
diff --git a/gdb/config/m68k/isi.mt b/gdb/config/m68k/isi.mt
new file mode 100644
index 00000000000..7c4cdee7d33
--- /dev/null
+++ b/gdb/config/m68k/isi.mt
@@ -0,0 +1,3 @@
+# Target: ISI Optimum V (3.05) under 4.3bsd.
+TDEPFILES=
+TM_FILE= tm-isi.h
diff --git a/gdb/config/m68k/linux.mh b/gdb/config/m68k/linux.mh
new file mode 100644
index 00000000000..c3850b16470
--- /dev/null
+++ b/gdb/config/m68k/linux.mh
@@ -0,0 +1,9 @@
+# Host: Motorola m68k running Linux
+
+XM_FILE= xm-linux.h
+XDEPFILES= ser-tcp.o
+
+NAT_FILE= nm-linux.h
+NATDEPFILES= infptrace.o solib.o inftarg.o fork-child.o corelow.o core-aout.o core-regset.o m68klinux-nat.o
+
+GDBSERVER_DEPFILES= low-linux.o
diff --git a/gdb/config/m68k/linux.mt b/gdb/config/m68k/linux.mt
new file mode 100644
index 00000000000..0c0a149ccc1
--- /dev/null
+++ b/gdb/config/m68k/linux.mt
@@ -0,0 +1,3 @@
+# Target: Motorola m68k with a.out and ELF
+TDEPFILES= m68k-tdep.o
+TM_FILE= tm-linux.h
diff --git a/gdb/config/m68k/m68klynx.mh b/gdb/config/m68k/m68klynx.mh
new file mode 100644
index 00000000000..48fdf2915ec
--- /dev/null
+++ b/gdb/config/m68k/m68klynx.mh
@@ -0,0 +1,11 @@
+# Host: Motorola 680x0 running LynxOS
+
+XM_FILE= xm-m68klynx.h
+XM_CLIBS= -lbsd
+XDEPFILES= ser-tcp.o
+
+NAT_FILE= nm-m68klynx.h
+NATDEPFILES= fork-child.o infptrace.o inftarg.o corelow.o lynx-nat.o
+
+GDBSERVER_LIBS= -lbsd
+GDBSERVER_DEPFILES= low-lynx.o
diff --git a/gdb/config/m68k/m68klynx.mt b/gdb/config/m68k/m68klynx.mt
new file mode 100644
index 00000000000..4aeac96d881
--- /dev/null
+++ b/gdb/config/m68k/m68klynx.mt
@@ -0,0 +1,4 @@
+# Target: Motorola 680x0 running LynxOS
+TDEPFILES= coff-solib.o m68k-tdep.o
+# m68kly-tdep.o
+TM_FILE= tm-m68klynx.h
diff --git a/gdb/config/m68k/m68kv4.mh b/gdb/config/m68k/m68kv4.mh
new file mode 100644
index 00000000000..f2db3d97971
--- /dev/null
+++ b/gdb/config/m68k/m68kv4.mh
@@ -0,0 +1,7 @@
+# Host: Motorola 680x0 running SVR4 (Commodore Amiga amix or Atari TT ASV)
+
+XM_FILE= xm-m68kv4.h
+XDEPFILES=
+
+NAT_FILE= nm-sysv4.h
+NATDEPFILES= corelow.o core-regset.o solib.o procfs.o fork-child.o
diff --git a/gdb/config/m68k/m68kv4.mt b/gdb/config/m68k/m68kv4.mt
new file mode 100644
index 00000000000..fcabb172d50
--- /dev/null
+++ b/gdb/config/m68k/m68kv4.mt
@@ -0,0 +1,3 @@
+# Target: Motorola 680x0 running SVR4 (Commodore Amiga amix or Atari TT ASV)
+TDEPFILES= m68k-tdep.o
+TM_FILE= tm-m68kv4.h
diff --git a/gdb/config/m68k/monitor.mt b/gdb/config/m68k/monitor.mt
new file mode 100644
index 00000000000..46b1c55ad63
--- /dev/null
+++ b/gdb/config/m68k/monitor.mt
@@ -0,0 +1,3 @@
+# Target: Motorola m68k embedded (EST emulator, rom68k and bug monitors)
+TDEPFILES= m68k-tdep.o monitor.o remote-est.o cpu32bug-rom.o rom68k-rom.o abug-rom.o dbug-rom.o dsrec.o
+TM_FILE= tm-monitor.h
diff --git a/gdb/config/m68k/nbsd.mh b/gdb/config/m68k/nbsd.mh
new file mode 100644
index 00000000000..a9e39425c99
--- /dev/null
+++ b/gdb/config/m68k/nbsd.mh
@@ -0,0 +1,5 @@
+# Host: Motorola m68k running NetBSD
+XDEPFILES= ser-tcp.o
+NATDEPFILES= infptrace.o inftarg.o fork-child.o corelow.o m68knbsd-nat.o
+XM_FILE= xm-nbsd.h
+NAT_FILE= nm-nbsd.h
diff --git a/gdb/config/m68k/nbsd.mt b/gdb/config/m68k/nbsd.mt
new file mode 100644
index 00000000000..1ad2882681f
--- /dev/null
+++ b/gdb/config/m68k/nbsd.mt
@@ -0,0 +1,3 @@
+# Target: Motorola m68k running NetBSD
+TDEPFILES= m68k-tdep.o solib.o
+TM_FILE= tm-nbsd.h
diff --git a/gdb/config/m68k/news.mh b/gdb/config/m68k/news.mh
new file mode 100644
index 00000000000..e94af1886f9
--- /dev/null
+++ b/gdb/config/m68k/news.mh
@@ -0,0 +1,5 @@
+# Host: Sony news series 700/800/900 (68020) running NewsOS version 3.
+XDEPFILES= news-xdep.o
+XM_FILE= xm-news.h
+NAT_FILE= nm-news.h
+NATDEPFILES= inftarg.o fork-child.o corelow.o core-aout.o infptrace.o
diff --git a/gdb/config/m68k/news.mt b/gdb/config/m68k/news.mt
new file mode 100644
index 00000000000..42f241717dc
--- /dev/null
+++ b/gdb/config/m68k/news.mt
@@ -0,0 +1,3 @@
+# Target: Sony news series 700/800/900 (68020) running NewsOS version 3.
+TDEPFILES= m68k-tdep.o
+TM_FILE= tm-news.h
diff --git a/gdb/config/m68k/news1000.mh b/gdb/config/m68k/news1000.mh
new file mode 100644
index 00000000000..b1bf0a573c2
--- /dev/null
+++ b/gdb/config/m68k/news1000.mh
@@ -0,0 +1,3 @@
+# Host: Sony news series 1000 (68030) running NewsOS version 3.
+XDEPFILES= infptrace.o inftarg.o fork-child.o corelow.o core-aout.o news-xdep.o
+XM_FILE= xm-news1000.h
diff --git a/gdb/config/m68k/nm-apollo68b.h b/gdb/config/m68k/nm-apollo68b.h
new file mode 100644
index 00000000000..4048a8b4ad3
--- /dev/null
+++ b/gdb/config/m68k/nm-apollo68b.h
@@ -0,0 +1,41 @@
+/* Macro defintions for an Apollo m68k in BSD mode
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define FETCH_INFERIOR_REGISTERS
+
+/* Tell gdb that we can attach and detach other processes */
+#define ATTACH_DETACH
+
+#define U_REGS_OFFSET 6
+
+/* 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 0
+
+#undef FLOAT_INFO /* No float info yet */
+
+#define REGISTER_U_ADDR(addr, blockend, regno) \
+ (addr) = (6 + 4 * (regno))
+
+/* Apollos don't really have a USER area,so trying to read it from the
+ * process address space will fail. It does support a read from a faked
+ * USER area using the "PEEKUSER" ptrace call.
+ */
+#define PT_READ_U 3
diff --git a/gdb/config/m68k/nm-apollo68v.h b/gdb/config/m68k/nm-apollo68v.h
new file mode 100644
index 00000000000..3a56f4a0192
--- /dev/null
+++ b/gdb/config/m68k/nm-apollo68v.h
@@ -0,0 +1,20 @@
+/* Macro defintions for an Apollo.
+ Copyright (C) 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define FETCH_INFERIOR_REGISTERS
diff --git a/gdb/config/m68k/nm-delta68.h b/gdb/config/m68k/nm-delta68.h
new file mode 100644
index 00000000000..cb7ffbf2be8
--- /dev/null
+++ b/gdb/config/m68k/nm-delta68.h
@@ -0,0 +1,21 @@
+/* Macro definitions for a Motorola Delta Series sysV68 R3V7.1.
+ Copyright (C) 1993, 1998 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+
+#define KERNEL_U_SIZE kernel_u_size()
diff --git a/gdb/config/m68k/nm-dpx2.h b/gdb/config/m68k/nm-dpx2.h
new file mode 100644
index 00000000000..50da268f4ae
--- /dev/null
+++ b/gdb/config/m68k/nm-dpx2.h
@@ -0,0 +1,29 @@
+/* Native support for a Bull DPX2.
+ Copyright (C) 1986, 1987, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* KERNEL_U_ADDR is determined upon startup in dpx2-xdep.c. */
+
+#define REGISTER_U_ADDR(addr, blockend, regno) \
+ (addr) = dpx2_register_u_addr ((blockend),(regno));
+
+extern int
+dpx2_register_u_addr PARAMS ((int, int));
+
+/* Kernel is a bit tenacious about sharing text segments, disallowing bpts. */
+#define ONE_PROCESS_WRITETEXT
diff --git a/gdb/config/m68k/nm-hp300bsd.h b/gdb/config/m68k/nm-hp300bsd.h
new file mode 100644
index 00000000000..7aacbb18b35
--- /dev/null
+++ b/gdb/config/m68k/nm-hp300bsd.h
@@ -0,0 +1,88 @@
+/* Parameters for Hewlett-Packard 9000/300 native support under bsd.
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Detect whether this is 4.3 or 4.4. */
+
+#include <errno.h>
+#include <sys/param.h>
+#ifdef BSD4_4
+
+/* BSD 4.4 alpha or better */
+
+/* We can attach to processes using ptrace. */
+
+#define ATTACH_DETACH
+#define PTRACE_ATTACH 10
+#define PTRACE_DETACH 11
+
+/* The third argument of ptrace is declared as this type. */
+
+#define PTRACE_ARG3_TYPE caddr_t
+
+/* U_REGS_OFFSET is the offset of the registers within the u area for
+ ptrace purposes. */
+#define U_REGS_OFFSET \
+ ptrace (PT_READ_U, inferior_pid, \
+ (PTRACE_ARG3_TYPE) \
+ (offsetof (struct user, u_kproc.kp_proc.p_md.md_regs)), 0) \
+ - USRSTACK
+
+/* No user structure in 4.4, registers are relative to kernel stack
+ which is fixed. */
+#define KERNEL_U_ADDR 0xFFF00000
+
+/* FIXME: Is ONE_PROCESS_WRITETEXT still true now that the kernel has
+ copy-on-write? It not, move it to the 4.3-specific section below
+ (now it is in xm-hp300bsd.h). */
+
+#else
+
+/* This is BSD 4.3 or something like it. */
+
+/* Get kernel u area address at run-time using BSD style nlist (). */
+#define KERNEL_U_ADDR_BSD
+
+#endif
+
+/* This was once broken for 4.4, but probably because we had the wrong
+ KERNEL_U_ADDR. */
+
+/* This is a piece of magic that is given a register number REGNO
+ and as BLOCKEND the address in the system of the end of the user structure
+ and stores in ADDR the address in the kernel or core dump
+ of that register. */
+
+#define REGISTER_U_ADDR(addr, blockend, regno) \
+{ \
+ if (regno < PS_REGNUM) \
+ addr = (int) &((struct frame *)(blockend))->f_regs[regno]; \
+ else if (regno == PS_REGNUM) \
+ addr = (int) &((struct frame *)(blockend))->f_stackadj; \
+ else if (regno == PC_REGNUM) \
+ addr = (int) &((struct frame *)(blockend))->f_pc; \
+ else if (regno < FPC_REGNUM) \
+ addr = (int) \
+ &((struct user *)0)->u_pcb.pcb_fpregs.fpf_regs[((regno)-FP0_REGNUM)*3];\
+ else if (regno == FPC_REGNUM) \
+ addr = (int) &((struct user *)0)->u_pcb.pcb_fpregs.fpf_fpcr; \
+ else if (regno == FPS_REGNUM) \
+ addr = (int) &((struct user *)0)->u_pcb.pcb_fpregs.fpf_fpsr; \
+ else \
+ addr = (int) &((struct user *)0)->u_pcb.pcb_fpregs.fpf_fpiar; \
+}
diff --git a/gdb/config/m68k/nm-hp300hpux.h b/gdb/config/m68k/nm-hp300hpux.h
new file mode 100644
index 00000000000..83e7b2bfba8
--- /dev/null
+++ b/gdb/config/m68k/nm-hp300hpux.h
@@ -0,0 +1,53 @@
+/* Parameters for native support on HP 9000 model 320, for GDB, the GNU debugger.
+ Copyright (C) 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Do implement the attach and detach commands. */
+
+#define ATTACH_DETACH
+
+/* fetch_inferior_registers is in nat-hp300hpux.c. */
+#define FETCH_INFERIOR_REGISTERS
+
+/* Get registers from a core file. The floating point stuff is just
+ guesses. */
+#define NEED_SYS_CORE_H
+#define REGISTER_U_ADDR(addr, blockend, regno) \
+{ \
+ if (regno < PS_REGNUM) \
+ addr = (int) (&((struct proc_regs *)(blockend))->d0 + regno); \
+ else if (regno == PS_REGNUM) \
+ addr = (int) ((char *) (&((struct proc_regs *)(blockend))->ps) - 2); \
+ else if (regno == PC_REGNUM) \
+ addr = (int) &((struct proc_regs *)(blockend))->pc; \
+ else if (regno < FPC_REGNUM) \
+ addr = (int) (((struct proc_regs *)(blockend))->mc68881 \
+ + ((regno) - FP0_REGNUM) / 2); \
+ else \
+ addr = (int) (((struct proc_regs *)(blockend))->p_float \
+ + (regno) - FPC_REGNUM); \
+}
+
+/* HPUX 8.0, in its infinite wisdom, has chosen to prototype ptrace
+ with five arguments, so programs written for normal ptrace lose.
+
+ Idiots.
+
+ (They should have just made it varadic). */
+
+#define FIVE_ARG_PTRACE
diff --git a/gdb/config/m68k/nm-linux.h b/gdb/config/m68k/nm-linux.h
new file mode 100644
index 00000000000..d7a44ec3bb4
--- /dev/null
+++ b/gdb/config/m68k/nm-linux.h
@@ -0,0 +1,47 @@
+/* Native support for linux, for GDB, the GNU debugger.
+ Copyright (C) 1996,1998 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef NM_LINUX_H
+#define NM_LINUX_H
+
+/* Return sizeof user struct to callers in less machine dependent routines */
+
+#define KERNEL_U_SIZE kernel_u_size()
+extern int kernel_u_size PARAMS ((void));
+
+/* Tell gdb that we can attach and detach other processes */
+#define ATTACH_DETACH
+
+#define U_REGS_OFFSET 0
+
+/* We define this if link.h is available, because with ELF we use SVR4 style
+ shared libraries. */
+
+#ifdef HAVE_LINK_H
+#define SVR4_SHARED_LIBS
+#include "solib.h" /* Support for shared libraries. */
+#endif
+
+#define REGISTER_U_ADDR(addr, blockend, regno) \
+ (addr) = m68k_linux_register_u_addr ((blockend),(regno));
+
+extern int
+m68k_linux_register_u_addr PARAMS ((int, int));
+
+#endif /* #ifndef NM_LINUX_H */
diff --git a/gdb/config/m68k/nm-m68klynx.h b/gdb/config/m68k/nm-m68klynx.h
new file mode 100644
index 00000000000..62b8d243ec8
--- /dev/null
+++ b/gdb/config/m68k/nm-m68klynx.h
@@ -0,0 +1,25 @@
+/* Native-dependent definitions for Motorola 680x0 running LynxOS.
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef NM_M68KLYNX_H
+#define NM_M68KLYNX_H
+
+#include "nm-lynx.h"
+
+#endif /* NM_M68KLYNX_H */
diff --git a/gdb/config/m68k/nm-nbsd.h b/gdb/config/m68k/nm-nbsd.h
new file mode 100644
index 00000000000..ce22c4d5e28
--- /dev/null
+++ b/gdb/config/m68k/nm-nbsd.h
@@ -0,0 +1,21 @@
+/* Native-dependent definitions for Motorola m68k running NetBSD, for GDB.
+ Copyright 1996 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Get generic NetBSD native definitions. */
+#include "nm-nbsd.h"
diff --git a/gdb/config/m68k/nm-news.h b/gdb/config/m68k/nm-news.h
new file mode 100644
index 00000000000..643d217c349
--- /dev/null
+++ b/gdb/config/m68k/nm-news.h
@@ -0,0 +1,26 @@
+/* Parameters for execution on a Sony/NEWS, for GDB, the GNU debugger.
+ Copyright 1987, 1989, 1992, 1996 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef NM_HEWS_H
+#define NM_NEWS_H 1
+
+/* Supply missing typedef needed in inftarg.c */
+typedef int pid_t;
+
+#endif /* NM_NEWS_H */
diff --git a/gdb/config/m68k/nm-sun2.h b/gdb/config/m68k/nm-sun2.h
new file mode 100644
index 00000000000..90352504ebf
--- /dev/null
+++ b/gdb/config/m68k/nm-sun2.h
@@ -0,0 +1,33 @@
+/* Parameters for execution on a Sun2, for GDB, the GNU debugger.
+ Copyright (C) 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Do implement the attach and detach commands. */
+
+#define ATTACH_DETACH
+
+/* Override copies of {fetch,store}_inferior_registers in infptrace.c. */
+#define FETCH_INFERIOR_REGISTERS
+
+/* This is a piece of magic that is given a register number REGNO
+ and as BLOCKEND the address in the system of the end of the user structure
+ and stores in ADDR the address in the kernel or core dump
+ of that register. */
+
+#define REGISTER_U_ADDR(addr, blockend, regno) \
+{ addr = blockend + regno * 4; }
diff --git a/gdb/config/m68k/nm-sun3.h b/gdb/config/m68k/nm-sun3.h
new file mode 100644
index 00000000000..e4ef8f4a56c
--- /dev/null
+++ b/gdb/config/m68k/nm-sun3.h
@@ -0,0 +1,31 @@
+/* Native-only definitions for Sun-3 for GDB, the GNU debugger.
+ Copyright (C) 1986, 1987, 1989, 1991, 1992, 1996
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Do implement the attach and detach commands. */
+
+#define ATTACH_DETACH
+
+/* Override copies of {fetch,store}_inferior_registers in infptrace.c. */
+
+#define FETCH_INFERIOR_REGISTERS
+
+/* We have to grab the regs since we store all regs at once. */
+
+#define CHILD_PREPARE_TO_STORE() read_register_bytes (0, NULL, REGISTER_BYTES)
diff --git a/gdb/config/m68k/nm-sysv4.h b/gdb/config/m68k/nm-sysv4.h
new file mode 100644
index 00000000000..67731313d28
--- /dev/null
+++ b/gdb/config/m68k/nm-sysv4.h
@@ -0,0 +1,22 @@
+/* Native-dependent definitions for Motorola 680x0 running SVR4.
+ Copyright 1994 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Include the generic SVR4 definitions. */
+
+#include "nm-sysv4.h"
diff --git a/gdb/config/m68k/os68k.mt b/gdb/config/m68k/os68k.mt
new file mode 100644
index 00000000000..391dd894366
--- /dev/null
+++ b/gdb/config/m68k/os68k.mt
@@ -0,0 +1,3 @@
+# Target: VxWorks running on a 68000
+TDEPFILES= m68k-tdep.o
+TM_FILE= tm-os68k.h
diff --git a/gdb/config/m68k/st2000.mt b/gdb/config/m68k/st2000.mt
new file mode 100644
index 00000000000..06dfe5cbc0d
--- /dev/null
+++ b/gdb/config/m68k/st2000.mt
@@ -0,0 +1,3 @@
+# Target: Tandem ST-2000 phone switch
+TDEPFILES= m68k-tdep.o remote-st.o
+TM_FILE= tm-st2000.h
diff --git a/gdb/config/m68k/sun2os3.mh b/gdb/config/m68k/sun2os3.mh
new file mode 100644
index 00000000000..a3ef6278eb2
--- /dev/null
+++ b/gdb/config/m68k/sun2os3.mh
@@ -0,0 +1,5 @@
+# Host: Sun 2, running SunOS 3
+XDEPFILES=
+XM_FILE= xm-sun2.h
+NAT_FILE= nm-sun2.h
+NATDEPFILES= infptrace.o inftarg.o fork-child.o corelow.o sun3-nat.o
diff --git a/gdb/config/m68k/sun2os3.mt b/gdb/config/m68k/sun2os3.mt
new file mode 100644
index 00000000000..12b7c7fec8a
--- /dev/null
+++ b/gdb/config/m68k/sun2os3.mt
@@ -0,0 +1,7 @@
+# Target: Sun 2, running SunOS 3
+# The system-supplied assembler re-orders the symbols so that gdb
+# can't find "gcc_compiled.".
+#msg If you compile your program with GCC, use the GNU assembler.
+#msg
+TDEPFILES= m68k-tdep.o
+TM_FILE= tm-sun2.h
diff --git a/gdb/config/m68k/sun2os4.mh b/gdb/config/m68k/sun2os4.mh
new file mode 100644
index 00000000000..617642d93c7
--- /dev/null
+++ b/gdb/config/m68k/sun2os4.mh
@@ -0,0 +1,5 @@
+# Host: Sun 2, running SunOS 4
+XDEPFILES=
+XM_FILE= xm-sun2.h
+NAT_FILE= nm-sun2.h
+NATDEPFILES= infptrace.o inftarg.o fork-child.o corelow.o sun3-nat.o
diff --git a/gdb/config/m68k/sun2os4.mt b/gdb/config/m68k/sun2os4.mt
new file mode 100644
index 00000000000..d0c56fe1384
--- /dev/null
+++ b/gdb/config/m68k/sun2os4.mt
@@ -0,0 +1,3 @@
+# Target: Sun 2, running SunOS 4
+TDEPFILES= solib.o m68k-tdep.o
+TM_FILE= tm-sun2os4.h
diff --git a/gdb/config/m68k/sun3os3.mh b/gdb/config/m68k/sun3os3.mh
new file mode 100644
index 00000000000..1b937932a81
--- /dev/null
+++ b/gdb/config/m68k/sun3os3.mh
@@ -0,0 +1,5 @@
+# Host: Sun 3, running SunOS 3
+XDEPFILES=
+XM_FILE= xm-sun3.h
+NAT_FILE= nm-sun3.h
+NATDEPFILES= fork-child.o inftarg.o infptrace.o corelow.o sun3-nat.o
diff --git a/gdb/config/m68k/sun3os3.mt b/gdb/config/m68k/sun3os3.mt
new file mode 100644
index 00000000000..8f9dac85e0e
--- /dev/null
+++ b/gdb/config/m68k/sun3os3.mt
@@ -0,0 +1,8 @@
+# Target: Sun 3, running SunOS 3
+# The system-supplied assembler re-orders the symbols so that gdb
+# can't find "gcc_compiled.".
+#msg If you compile your program with GCC, use the GNU assembler.
+#msg
+
+TDEPFILES= m68k-tdep.o
+TM_FILE= tm-sun3.h
diff --git a/gdb/config/m68k/sun3os4.mh b/gdb/config/m68k/sun3os4.mh
new file mode 100644
index 00000000000..5d1bf523665
--- /dev/null
+++ b/gdb/config/m68k/sun3os4.mh
@@ -0,0 +1,6 @@
+# Host: Sun 3, running SunOS 4
+XDEPFILES=
+XM_FILE= xm-sun3os4.h
+NAT_FILE= nm-sun3.h
+NATDEPFILES= fork-child.o inftarg.o infptrace.o corelow.o sun3-nat.o
+GDBSERVER_DEPFILES= low-sun3.o
diff --git a/gdb/config/m68k/sun3os4.mt b/gdb/config/m68k/sun3os4.mt
new file mode 100644
index 00000000000..dbc265fec7d
--- /dev/null
+++ b/gdb/config/m68k/sun3os4.mt
@@ -0,0 +1,3 @@
+# Target: Sun 3, running SunOS 4, as a target system
+TDEPFILES= solib.o m68k-tdep.o
+TM_FILE= tm-sun3os4.h
diff --git a/gdb/config/m68k/tm-3b1.h b/gdb/config/m68k/tm-3b1.h
new file mode 100644
index 00000000000..f917760755b
--- /dev/null
+++ b/gdb/config/m68k/tm-3b1.h
@@ -0,0 +1,32 @@
+/* Parameters for targeting GDB to a 3b1.
+ Copyright 1986, 1987, 1989, 1991, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* The child target can't deal with floating registers. */
+#define CANNOT_STORE_REGISTER(regno) ((regno) >= FP0_REGNUM)
+
+/* Define BPT_VECTOR if it is different than the default.
+ This is the vector number used by traps to indicate a breakpoint. */
+
+#define BPT_VECTOR 0x1
+
+/* Address of end of stack space. */
+
+#define STACK_END_ADDR 0x300000
+
+#include "m68k/tm-m68k.h"
diff --git a/gdb/config/m68k/tm-altos.h b/gdb/config/m68k/tm-altos.h
new file mode 100644
index 00000000000..2d77fea6563
--- /dev/null
+++ b/gdb/config/m68k/tm-altos.h
@@ -0,0 +1,57 @@
+/* Target definitions for GDB on an Altos 3068 (m68k running SVR2)
+ Copyright 1987, 1989, 1991, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* The child target can't deal with floating registers. */
+#define CANNOT_STORE_REGISTER(regno) ((regno) >= FP0_REGNUM)
+
+/* Define BPT_VECTOR if it is different than the default.
+ This is the vector number used by traps to indicate a breakpoint. */
+
+#define BPT_VECTOR 0xe
+
+/* Address of end of stack space. */
+
+/*#define STACK_END_ADDR (0xffffff)*/
+#define STACK_END_ADDR (0x1000000)
+
+/* Amount PC must be decremented by after a breakpoint.
+ On the Altos, the kernel resets the pc to the trap instr */
+
+#define DECR_PC_AFTER_BREAK 0
+
+/* The only reason this is here is the tm-altos.h reference below. It
+ was moved back here from tm-m68k.h. FIXME? */
+
+#define SKIP_PROLOGUE(pc) \
+{ register int op = read_memory_integer (pc, 2); \
+ if (op == 0047126) \
+ pc += 4; /* Skip link #word */ \
+ else if (op == 0044016) \
+ pc += 6; /* Skip link #long */ \
+ /* Not sure why branches are here. */ \
+ /* From tm-isi.h, tm-altos.h */ \
+ else if (op == 0060000) \
+ pc += 4; /* Skip bra #word */ \
+ else if (op == 00600377) \
+ pc += 6; /* skip bra #long */ \
+ else if ((op & 0177400) == 0060000) \
+ pc += 2; /* skip bra #char */ \
+}
+
+#include "m68k/tm-m68k.h"
diff --git a/gdb/config/m68k/tm-apollo68b.h b/gdb/config/m68k/tm-apollo68b.h
new file mode 100644
index 00000000000..ee10410d329
--- /dev/null
+++ b/gdb/config/m68k/tm-apollo68b.h
@@ -0,0 +1,59 @@
+/* Parameters for execution on Apollo 68k running BSD.
+ Copyright (C) 1986, 1987, 1989, 1991 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Apollos use vector 0xb for the breakpoint vector */
+
+#define BPT_VECTOR 0xb
+
+#include "m68k/tm-m68k.h"
+
+#define FRAME_CHAIN_VALID(chain, thisframe) nonnull_frame_chain_valid (chain, thisframe)
+
+/* These are the jmp_buf registers I could guess. There are 13 registers
+ * in the buffer. There are 8 data registers, 6 general address registers,
+ * the Frame Pointer, the Stack Pointer, the PC and the SR in the chip. I would
+ * guess that 12 is the SR, but we don't need that anyway. 0 and 1 have
+ * me stumped. 4 appears to be a5 for some unknown reason. If you care
+ * about this, disassemble setjmp to find out. But don't do it with gdb :)
+ */
+
+#undef JB_SP
+#undef JB_FP
+#undef JB_PC
+#undef JB_D0
+#undef JB_D1
+#undef JB_D2
+#undef JB_D3
+#undef JB_D4
+#undef JB_D5
+
+#define JB_SP 2
+#define JB_FP 3
+#define JB_PC 5
+#define JB_D0 6
+#define JB_D1 7
+#define JB_D2 8
+#define JB_D3 9
+#define JB_D4 10
+#define JB_D5 11
+
+/* How to decide if we're in a shared library function. (Probably a wrong
+ definintion inherited from the VxWorks config file). */
+#define IN_SOLIB_CALL_TRAMPOLINE(pc, name) (name && strcmp(name, "<end_of_program>") == 0)
diff --git a/gdb/config/m68k/tm-cisco.h b/gdb/config/m68k/tm-cisco.h
new file mode 100644
index 00000000000..c3628d00fe4
--- /dev/null
+++ b/gdb/config/m68k/tm-cisco.h
@@ -0,0 +1,55 @@
+/* Parameters for CISCO m68k.
+ Copyright (C) 1994 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define GDBINIT_FILENAME ".cisco-gdbinit" /* Init file */
+
+#define DEFAULT_PROMPT "(cisco-68k-gdb) " /* Default prompt */
+
+#include "m68k/tm-m68k.h"
+
+/* Offsets (in target ints) into jmp_buf. Defined in /csc/sys/sun/asm.S. */
+
+#define JB_ELEMENT_SIZE 4
+
+#define JB_PC 0
+#define JB_D2 1
+#define JB_D3 2
+#define JB_D4 3
+#define JB_D5 4
+#define JB_D6 5
+#define JB_D7 6
+#define JB_A2 7
+#define JB_A3 8
+#define JB_A4 9
+#define JB_A5 10
+#define JB_A6 11
+#define JB_SP 12
+
+/* 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 ADDR.
+ This routine returns true on success */
+
+#define GET_LONGJMP_TARGET(ADDR) get_longjmp_target(ADDR)
+extern int get_longjmp_target PARAMS ((CORE_ADDR *));
+
+/* BFD handles finding the registers in the core file, so they are at
+ the start of the BFD .reg section. */
+#define REGISTER_U_ADDR(addr,blockend,regno) (addr = REGISTER_BYTE (regno))
+#define KERNEL_U_ADDR 0
diff --git a/gdb/config/m68k/tm-delta68.h b/gdb/config/m68k/tm-delta68.h
new file mode 100644
index 00000000000..5965bb56f9c
--- /dev/null
+++ b/gdb/config/m68k/tm-delta68.h
@@ -0,0 +1,103 @@
+/* Target definitions for delta68.
+ Copyright 1993, 1994, 1998 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Define BPT_VECTOR if it is different than the default.
+ This is the vector number used by traps to indicate a breakpoint. */
+
+#define BPT_VECTOR 0x1
+
+#define GCC_COMPILED_FLAG_SYMBOL "gcc_compiled%"
+#define GCC2_COMPILED_FLAG_SYMBOL "gcc2_compiled%"
+
+/* Amount PC must be decremented by after a breakpoint.
+ On the Delta, the kernel decrements it for us. */
+
+#define DECR_PC_AFTER_BREAK 0
+
+/* Not sure what happens if we try to store this register, but
+ phdm@info.ucl.ac.be says we need this define. */
+
+#define CANNOT_STORE_REGISTER(regno) (regno == FPI_REGNUM)
+
+/* Extract from an array REGBUF containing the (raw) register state
+ a function return value of type TYPE, and copy that, in virtual format,
+ into VALBUF. */
+
+/* When it returns a float/double value, use fp0 in sysV68. */
+/* When it returns a pointer value, use a0 in sysV68. */
+
+#define EXTRACT_RETURN_VALUE(TYPE,REGBUF,VALBUF) \
+ if (TYPE_CODE (TYPE) == TYPE_CODE_FLT) \
+ REGISTER_CONVERT_TO_VIRTUAL (FP0_REGNUM, TYPE, \
+ &REGBUF[REGISTER_BYTE (FP0_REGNUM)], \
+ VALBUF); \
+ else \
+ memcpy ((VALBUF), \
+ (char *) ((REGBUF) + \
+ (TYPE_CODE(TYPE) == TYPE_CODE_PTR ? 8 * 4 : \
+ (TYPE_LENGTH(TYPE) >= 4 ? 0 : 4 - TYPE_LENGTH(TYPE)))), \
+ TYPE_LENGTH(TYPE))
+
+/* Write into appropriate registers a function return value
+ of type TYPE, given in virtual format. */
+
+/* When it returns a float/double value, use fp0 in sysV68. */
+/* When it returns a pointer value, use a0 in sysV68. */
+
+#define STORE_RETURN_VALUE(TYPE,VALBUF) \
+ if (TYPE_CODE (TYPE) == TYPE_CODE_FLT) \
+ { \
+ char raw_buf[REGISTER_RAW_SIZE (FP0_REGNUM)]; \
+ REGISTER_CONVERT_TO_RAW (TYPE, FP0_REGNUM, VALBUF, raw_buf); \
+ write_register_bytes (REGISTER_BYTE (FP0_REGNUM), \
+ raw_buf, REGISTER_RAW_SIZE (FP0_REGNUM)); \
+ } \
+ else \
+ write_register_bytes ((TYPE_CODE(TYPE) == TYPE_CODE_PTR ? 8 * 4 : 0), \
+ VALBUF, TYPE_LENGTH (TYPE))
+
+/* Return number of args passed to a frame.
+ Can return -1, meaning no way to tell. */
+
+#define FRAME_NUM_ARGS(val, fi) \
+{ register CORE_ADDR pc = FRAME_SAVED_PC (fi); \
+ register int insn = 0177777 & read_memory_integer (pc, 2); \
+ val = 0; \
+ if (insn == 0047757 || insn == 0157374) /* lea W(sp),sp or addaw #W,sp */ \
+ val = read_memory_integer (pc + 2, 2); \
+ else if ((insn & 0170777) == 0050217 /* addql #N, sp */ \
+ || (insn & 0170777) == 0050117) /* addqw */ \
+ { val = (insn >> 9) & 7; if (val == 0) val = 8; } \
+ else if (insn == 0157774) /* addal #WW, sp */ \
+ val = read_memory_integer (pc + 2, 4); \
+ val >>= 2; }
+
+/* On M68040 versions of sysV68 R3V7.1, ptrace(PT_WRITE_I) does not clear
+ the processor's instruction cache as it should. */
+#define CLEAR_INSN_CACHE() clear_insn_cache()
+
+#include "m68k/tm-m68k.h"
+
+/* 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). */
+
+#undef EXTRACT_STRUCT_VALUE_ADDRESS
+#define EXTRACT_STRUCT_VALUE_ADDRESS(REGBUF)\
+ (*(CORE_ADDR *)((char*)(REGBUF) + 8 * 4))
diff --git a/gdb/config/m68k/tm-dpx2.h b/gdb/config/m68k/tm-dpx2.h
new file mode 100644
index 00000000000..8b1bfdad9aa
--- /dev/null
+++ b/gdb/config/m68k/tm-dpx2.h
@@ -0,0 +1,33 @@
+/* Parameters for targeting to a Bull DPX2.
+ Copyright (C) 1986, 1987, 1989, 1991, 1994 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Define BPT_VECTOR if it is different than the default.
+ This is the vector number used by traps to indicate a breakpoint. */
+
+#define BPT_VECTOR 0xe
+
+/* Need to get function ends by adding this to epilogue address from .bf
+ record, not using x_fsize field. */
+#define FUNCTION_EPILOGUE_SIZE 4
+
+/* The child target can't deal with writing floating registers. */
+#define CANNOT_STORE_REGISTER(regno) ((regno) >= FP0_REGNUM)
+
+#include <sys/types.h>
+#include "m68k/tm-m68k.h"
diff --git a/gdb/config/m68k/tm-es1800.h b/gdb/config/m68k/tm-es1800.h
new file mode 100644
index 00000000000..ce2af1d627d
--- /dev/null
+++ b/gdb/config/m68k/tm-es1800.h
@@ -0,0 +1,59 @@
+/* Parameters for execution on ES-1800 emulator for 68000.
+ The code was originally written by Johan Holmberg TT/SJ Ericsson Telecom
+ AB and later modified by Johan Henriksson TT/SJ. It was adapted to GDB 4.0
+ by Jan Norden TX/DK.
+ 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
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define GDBINIT_FILENAME ".esgdbinit"
+
+#define DEFAULT_PROMPT "(esgdb) "
+
+#include "m68k/tm-m68k.h"
+
+/* Longjmp stuff borrowed from sun3 configuration. Don't know if correct.
+ FIXME. */
+/* Offsets (in target ints) into jmp_buf. Not defined by Sun, but at least
+ documented in a comment in <machine/setjmp.h>! */
+
+#define JB_ELEMENT_SIZE 4
+
+#define JB_ONSSTACK 0
+#define JB_SIGMASK 1
+#define JB_SP 2
+#define JB_PC 3
+#define JB_PSL 4
+#define JB_D2 5
+#define JB_D3 6
+#define JB_D4 7
+#define JB_D5 8
+#define JB_D6 9
+#define JB_D7 10
+#define JB_A2 11
+#define JB_A3 12
+#define JB_A4 13
+#define JB_A5 14
+#define JB_A6 15
+
+/* 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 ADDR.
+ This routine returns true on success */
+
+#define GET_LONGJMP_TARGET(ADDR) get_longjmp_target(ADDR)
+extern int get_longjmp_target PARAMS ((CORE_ADDR *));
diff --git a/gdb/config/m68k/tm-hp300bsd.h b/gdb/config/m68k/tm-hp300bsd.h
new file mode 100644
index 00000000000..cdd75dc881a
--- /dev/null
+++ b/gdb/config/m68k/tm-hp300bsd.h
@@ -0,0 +1,62 @@
+/* Parameters for target machine Hewlett-Packard 9000/300, running bsd.
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Configuration file for HP9000/300 series machine running BSD,
+ including Utah, Mt. Xinu or Berkeley variants. This is NOT for HP-UX.
+ Problems to hpbsd-bugs@cs.utah.edu. */
+
+/* GCC is the only compiler used on this OS. So get this right even if
+ the code which detects gcc2_compiled. is still broken. */
+
+#define BELIEVE_PCC_PROMOTION 1
+
+/* Define BPT_VECTOR if it is different than the default.
+ This is the vector number used by traps to indicate a breakpoint.
+
+ For hp300bsd the normal breakpoint vector is 0x2 (for debugging via
+ ptrace); for remote kernel debugging the breakpoint vector is 0xf. */
+
+#define BPT_VECTOR 0x2
+#define REMOTE_BPT_VECTOR 0xf
+
+#define TARGET_NBPG 4096
+
+/* For 4.4 this would be 2, but it is OK for us to detect an area a
+ bit bigger than necessary. This way the same gdb binary can target
+ either 4.3 or 4.4. */
+
+#define TARGET_UPAGES 3
+
+/* On the HP300, sigtramp is in the u area. Gak! User struct is not
+ mapped to the same virtual address in user/kernel address space
+ (hence STACK_END_ADDR as opposed to KERNEL_U_ADDR). This tests
+ for the whole u area, since we don't necessarily have hp300bsd
+ include files around. */
+
+/* For 4.4, it is actually right 20 bytes *before* STACK_END_ADDR, so
+ include that in the area we test for. */
+
+#define SIGTRAMP_START(pc) (STACK_END_ADDR - 20)
+#define SIGTRAMP_END(pc) (STACK_END_ADDR + TARGET_UPAGES * TARGET_NBPG)
+
+/* Address of end of stack space. */
+
+#define STACK_END_ADDR 0xfff00000
+
+#include "m68k/tm-m68k.h"
diff --git a/gdb/config/m68k/tm-hp300hpux.h b/gdb/config/m68k/tm-hp300hpux.h
new file mode 100644
index 00000000000..fce0d99df72
--- /dev/null
+++ b/gdb/config/m68k/tm-hp300hpux.h
@@ -0,0 +1,31 @@
+/* Parameters for execution on an HP 9000 model 320, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* GCC is the only compiler used for stabs on this OS. So get this
+ right even if the code which detects gcc2_compiled. is still
+ broken. */
+
+#define BELIEVE_PCC_PROMOTION 1
+
+/* Define BPT_VECTOR if it is different than the default.
+ This is the vector number used by traps to indicate a breakpoint. */
+
+#define BPT_VECTOR 0x1
+
+#include "m68k/tm-m68k.h"
diff --git a/gdb/config/m68k/tm-isi.h b/gdb/config/m68k/tm-isi.h
new file mode 100644
index 00000000000..f994524dd69
--- /dev/null
+++ b/gdb/config/m68k/tm-isi.h
@@ -0,0 +1,150 @@
+/* Definitions to target GDB on an ISI Optimum V (3.05) under 4.3bsd.
+ Copyright (C) 1987, 1989, 1991, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* This has not been tested on ISI's running BSD 4.2, but it will probably
+ work. */
+
+/* Data segment starts at etext rounded up to DATAROUND in {N,Z}MAGIC files */
+
+#define DATAROUND 0x20000
+#define N_DATADDR(hdr) (hdr.a_magic != OMAGIC ? \
+ (hdr.a_text + DATAROUND) & ~(DATAROUND-1) : hdr.a_text)
+
+/* Text segment starts at sizeof (struct exec) in {N,Z}MAGIC files */
+
+#define N_TXTADDR(hdr) (hdr.a_magic != OMAGIC ? sizeof (struct exec) : 0)
+
+/* Amount PC must be decremented by after a breakpoint.
+ This is often the number of bytes in BREAKPOINT
+ but not always.
+ On the ISI, the kernel resets the pc to the trap instr */
+
+#define DECR_PC_AFTER_BREAK 0
+
+
+/* Return number of args passed to a frame.
+ Can return -1, meaning no way to tell. */
+
+#define FRAME_NUM_ARGS(val, fi) \
+{ register CORE_ADDR pc = FRAME_SAVED_PC (fi); \
+ register int insn = 0177777 & read_memory_integer (pc, 2); \
+ val = 0; \
+ if (insn == 0047757 || insn == 0157374) /* lea W(sp),sp or addaw #W,sp */ \
+ val = read_memory_integer (pc + 2, 2); \
+ else if ((insn & 0170777) == 0050217 /* addql #N, sp */ \
+ || (insn & 0170777) == 0050117) /* addqw */ \
+ { val = (insn >> 9) & 7; if (val == 0) val = 8; } \
+ else if (insn == 0157774) /* addal #WW, sp */ \
+ val = read_memory_integer (pc + 2, 4); \
+ val >>= 2; }
+
+/* Put here the code to store, into a struct frame_saved_regs,
+ the addresses of the saved registers of frame described by FRAME_INFO.
+ This includes special registers such as pc and fp saved in special
+ ways in the stack frame. sp is even more special:
+ the address we return for it IS the sp for the next frame. */
+
+#define FRAME_FIND_SAVED_REGS(frame_info, frame_saved_regs) \
+{ register int regnum; \
+ register int regmask; \
+ register CORE_ADDR next_addr; \
+ register CORE_ADDR pc; \
+ register int insn; \
+ register int offset; \
+ memset (&frame_saved_regs, '\0', sizeof frame_saved_regs); \
+ if ((frame_info)->pc >= (frame_info)->frame - CALL_DUMMY_LENGTH - FP_REGNUM*4 - 8*12 - 4 \
+ && (frame_info)->pc <= (frame_info)->frame) \
+ { next_addr = (frame_info)->frame; \
+ pc = (frame_info)->frame - CALL_DUMMY_LENGTH - FP_REGNUM * 4 - 8*12 - 4; }\
+ else \
+ { pc = get_pc_function_start ((frame_info)->pc); \
+ /* Verify we have a link a6 instruction next, \
+ or a branch followed by a link a6 instruction; \
+ if not we lose. If we win, find the address above the saved \
+ regs using the amount of storage from the link instruction. */\
+retry: \
+ insn = read_memory_integer (pc, 2); \
+ if (insn == 044016) \
+ next_addr = (frame_info)->frame - read_memory_integer (pc += 2, 4), pc+=4; \
+ else if (insn == 047126) \
+ next_addr = (frame_info)->frame - read_memory_integer (pc += 2, 2), pc+=2; \
+ else if ((insn & 0177400) == 060000) /* bra insn */ \
+ { offset = insn & 0377; \
+ pc += 2; /* advance past bra */ \
+ if (offset == 0) /* bra #word */ \
+ offset = read_memory_integer (pc, 2), pc += 2; \
+ else if (offset == 0377) /* bra #long */ \
+ offset = read_memory_integer (pc, 4), pc += 4; \
+ pc += offset; \
+ goto retry; \
+ } else goto lose; \
+ /* If have an addal #-n, sp next, adjust next_addr. */ \
+ if ((0177777 & read_memory_integer (pc, 2)) == 0157774) \
+ next_addr += read_memory_integer (pc += 2, 4), pc += 4; \
+ } \
+ /* next should be a moveml to (sp) or -(sp) or a movl r,-(sp) */ \
+ insn = read_memory_integer (pc, 2), pc += 2; \
+ regmask = read_memory_integer (pc, 2); \
+ if ((insn & 0177760) == 022700) /* movl rn, (sp) */ \
+ (frame_saved_regs).regs[(insn&7) + ((insn&010)?8:0)] = next_addr; \
+ else if ((insn & 0177760) == 024700) /* movl rn, -(sp) */ \
+ (frame_saved_regs).regs[(insn&7) + ((insn&010)?8:0)] = next_addr-=4; \
+ else if (insn == 0044327) /* moveml mask, (sp) */ \
+ { pc += 2; \
+ /* Regmask's low bit is for register 0, the first written */ \
+ next_addr -= 4; \
+ for (regnum = 0; regnum < 16; regnum++, regmask >>= 1) \
+ if (regmask & 1) \
+ (frame_saved_regs).regs[regnum] = (next_addr += 4); \
+ } else if (insn == 0044347) /* moveml mask, -(sp) */ \
+ { pc += 2; \
+ /* Regmask's low bit is for register 15, the first pushed */ \
+ for (regnum = 15; regnum >= 0; regnum--, regmask >>= 1) \
+ if (regmask & 1) \
+ (frame_saved_regs).regs[regnum] = (next_addr -= 4); } \
+ /* clrw -(sp); movw ccr,-(sp) may follow. */ \
+ if (read_memory_integer (pc, 2) == 041147 \
+ && read_memory_integer (pc+2, 2) == 042347) \
+ (frame_saved_regs).regs[PS_REGNUM] = (next_addr -= 4); \
+ lose: ; \
+ (frame_saved_regs).regs[SP_REGNUM] = (frame_info)->frame + 8; \
+ (frame_saved_regs).regs[FP_REGNUM] = (frame_info)->frame; \
+ (frame_saved_regs).regs[PC_REGNUM] = (frame_info)->frame + 4; \
+}
+
+/* The only reason this is here is the tm-isi.h reference below. It
+ was moved back here from tm-m68k.h. FIXME? */
+
+#define SKIP_PROLOGUE(pc) \
+{ register int op = read_memory_integer (pc, 2); \
+ if (op == 0047126) \
+ pc += 4; /* Skip link #word */ \
+ else if (op == 0044016) \
+ pc += 6; /* Skip link #long */ \
+ /* Not sure why branches are here. */ \
+ /* From tm-isi.h, tm-altos.h */ \
+ else if (op == 0060000) \
+ pc += 4; /* Skip bra #word */ \
+ else if (op == 00600377) \
+ pc += 6; /* skip bra #long */ \
+ else if ((op & 0177400) == 0060000) \
+ pc += 2; /* skip bra #char */ \
+}
+
+#include "m68k/tm-m68k.h"
diff --git a/gdb/config/m68k/tm-linux.h b/gdb/config/m68k/tm-linux.h
new file mode 100644
index 00000000000..6c119982ff5
--- /dev/null
+++ b/gdb/config/m68k/tm-linux.h
@@ -0,0 +1,109 @@
+/* Definitions to target GDB to Linux on m680x0
+ Copyright (C) 1996,1998 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* 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
+
+/* The following definitions are appropriate when using the ELF
+ format, where floating point values are returned in fp0, pointer
+ values in a0 and other values in d0. */
+
+/* Extract from an array REGBUF containing the (raw) register state a
+ function return value of type TYPE, and copy that, in virtual
+ format, into VALBUF. */
+
+#define EXTRACT_RETURN_VALUE(TYPE,REGBUF,VALBUF) \
+{ \
+ if (TYPE_CODE (TYPE) == TYPE_CODE_FLT) \
+ { \
+ REGISTER_CONVERT_TO_VIRTUAL (FP0_REGNUM, TYPE, \
+ ((char *) (REGBUF) \
+ + REGISTER_BYTE (FP0_REGNUM)), \
+ VALBUF); \
+ } \
+ else if (TYPE_CODE (TYPE) == TYPE_CODE_PTR) \
+ memcpy (VALBUF, (char *) (REGBUF) + REGISTER_BYTE (A0_REGNUM), \
+ TYPE_LENGTH (TYPE)); \
+ else \
+ memcpy (VALBUF, \
+ ((char *) (REGBUF) \
+ + (TYPE_LENGTH (TYPE) >= 4 ? 0 : 4 - TYPE_LENGTH (TYPE))), \
+ TYPE_LENGTH (TYPE)); \
+}
+
+/* Write into appropriate registers a function return value of type
+ TYPE, given in virtual format. */
+
+#define STORE_RETURN_VALUE(TYPE,VALBUF) \
+{ \
+ if (TYPE_CODE (TYPE) == TYPE_CODE_FLT) \
+ { \
+ char raw_buffer[REGISTER_RAW_SIZE (FP0_REGNUM)]; \
+ REGISTER_CONVERT_TO_RAW (TYPE, FP0_REGNUM, VALBUF, raw_buffer); \
+ write_register_bytes (REGISTER_BYTE (FP0_REGNUM), \
+ raw_buffer, TYPE_LENGTH (TYPE)); \
+ } \
+ else \
+ { \
+ if (TYPE_CODE (TYPE) == TYPE_CODE_PTR) \
+ write_register_bytes (REGISTER_BYTE (A0_REGNUM), VALBUF, \
+ TYPE_LENGTH (TYPE)); \
+ write_register_bytes (0, VALBUF, TYPE_LENGTH (TYPE)); \
+ } \
+}
+
+#include "tm-sysv4.h"
+#include "m68k/tm-m68k.h"
+
+/* 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). */
+
+#undef EXTRACT_STRUCT_VALUE_ADDRESS
+#define EXTRACT_STRUCT_VALUE_ADDRESS(REGBUF) \
+ (*(CORE_ADDR *)((char *) (REGBUF) + REGISTER_BYTE (A0_REGNUM)))
+
+/* Offsets (in target ints) into jmp_buf. */
+
+#define JB_ELEMENT_SIZE 4
+#define JB_PC 7
+
+/* 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 ADDR.
+ This routine returns true on success */
+
+#define GET_LONGJMP_TARGET(ADDR) get_longjmp_target(ADDR)
+
+/* Offset to saved PC in sigcontext, from <asm/sigcontext.h>. */
+#define SIGCONTEXT_PC_OFFSET 26
+
+#undef FRAME_SAVED_PC
+#define FRAME_SAVED_PC(FRAME) \
+ (((FRAME)->signal_handler_caller \
+ ? sigtramp_saved_pc (FRAME) \
+ : read_memory_integer ((FRAME)->frame + 4, 4)))
+
+extern CORE_ADDR sigtramp_saved_pc PARAMS ((struct frame_info *));
+
+#define IN_SIGTRAMP(pc,name) in_sigtramp (pc)
+extern int in_sigtramp PARAMS ((CORE_ADDR pc));
diff --git a/gdb/config/m68k/tm-m68k.h b/gdb/config/m68k/tm-m68k.h
new file mode 100644
index 00000000000..098500c4fcb
--- /dev/null
+++ b/gdb/config/m68k/tm-m68k.h
@@ -0,0 +1,393 @@
+/* Parameters for execution on a 68000 series machine.
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Generic 68000 stuff, to be included by other tm-*.h files. */
+
+#define IEEE_FLOAT 1
+
+/* Define the bit, byte, and word ordering of the machine. */
+#define TARGET_BYTE_ORDER BIG_ENDIAN
+
+/* Offset from address of function to start of its code.
+ Zero on most machines. */
+
+#define FUNCTION_START_OFFSET 0
+
+/* Advance PC across any function entry prologue instructions
+ to reach some "real" code. */
+
+#if !defined(SKIP_PROLOGUE)
+#define SKIP_PROLOGUE(ip) {(ip) = m68k_skip_prologue(ip);}
+extern CORE_ADDR m68k_skip_prologue PARAMS ((CORE_ADDR ip));
+#endif
+
+/* 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. */
+
+#ifdef __STDC__
+struct frame_info;
+struct frame_saved_regs;
+#endif
+
+extern CORE_ADDR m68k_saved_pc_after_call PARAMS ((struct frame_info *));
+extern void m68k_find_saved_regs PARAMS ((struct frame_info *, struct frame_saved_regs *));
+
+#define SAVED_PC_AFTER_CALL(frame) \
+ m68k_saved_pc_after_call(frame)
+
+/* Stack grows downward. */
+
+#define INNER_THAN(lhs,rhs) ((lhs) < (rhs))
+
+/* Stack must be kept short aligned when doing function calls. */
+
+#define STACK_ALIGN(ADDR) (((ADDR) + 1) & ~1)
+
+/* Sequence of bytes for breakpoint instruction.
+ This is a TRAP instruction. The last 4 bits (0xf below) is the
+ vector. Systems which don't use 0xf should define BPT_VECTOR
+ themselves before including this file. */
+
+#if !defined (BPT_VECTOR)
+#define BPT_VECTOR 0xf
+#endif
+
+#if !defined (BREAKPOINT)
+#define BREAKPOINT {0x4e, (0x40 | BPT_VECTOR)}
+#endif
+
+/* We default to vector 1 for the "remote" target, but allow targets
+ to override. */
+#if !defined (REMOTE_BPT_VECTOR)
+#define REMOTE_BPT_VECTOR 1
+#endif
+
+#if !defined (REMOTE_BREAKPOINT)
+#define REMOTE_BREAKPOINT {0x4e, (0x40 | REMOTE_BPT_VECTOR)}
+#endif
+
+/* If your kernel resets the pc after the trap happens you may need to
+ define this before including this file. */
+
+#if !defined (DECR_PC_AFTER_BREAK)
+#define DECR_PC_AFTER_BREAK 2
+#endif
+
+/* Say how long (ordinary) registers are. This is a piece of bogosity
+ used in push_word and a few other places; REGISTER_RAW_SIZE is the
+ real way to know how big a register is. */
+
+#define REGISTER_SIZE 4
+
+#define REGISTER_BYTES_FP (16*4 + 8 + 8*12 + 3*4)
+#define REGISTER_BYTES_NOFP (16*4 + 8)
+
+#ifndef NUM_REGS
+#define NUM_REGS 29
+#endif
+
+#define NUM_FREGS (NUM_REGS-24)
+
+#ifndef REGISTER_BYTES_OK
+#define REGISTER_BYTES_OK(b) \
+ ((b) == REGISTER_BYTES_FP \
+ || (b) == REGISTER_BYTES_NOFP)
+#endif
+
+#ifndef REGISTER_BYTES
+#define REGISTER_BYTES (16*4 + 8 + 8*12 + 3*4)
+#endif
+
+/* Index within `registers' of the first byte of the space for
+ register N. */
+
+#define REGISTER_BYTE(N) \
+ ((N) >= FPC_REGNUM ? (((N) - FPC_REGNUM) * 4) + 168 \
+ : (N) >= FP0_REGNUM ? (((N) - FP0_REGNUM) * 12) + 72 \
+ : (N) * 4)
+
+/* Number of bytes of storage in the actual machine representation
+ for register N. On the 68000, all regs are 4 bytes
+ except the floating point regs which are 12 bytes. */
+/* Note that the unsigned cast here forces the result of the
+ subtraction to very high positive values if N < FP0_REGNUM */
+
+#define REGISTER_RAW_SIZE(N) (((unsigned)(N) - FP0_REGNUM) < 8 ? 12 : 4)
+
+/* Number of bytes of storage in the program's representation
+ for register N. On the 68000, all regs are 4 bytes
+ except the floating point regs which are 8-byte doubles. */
+
+#define REGISTER_VIRTUAL_SIZE(N) (((unsigned)(N) - FP0_REGNUM) < 8 ? 8 : 4)
+
+/* Largest value REGISTER_RAW_SIZE can have. */
+
+#define MAX_REGISTER_RAW_SIZE 12
+
+/* Largest value REGISTER_VIRTUAL_SIZE can have. */
+
+#define MAX_REGISTER_VIRTUAL_SIZE 8
+
+/* Nonzero if register N requires conversion
+ from raw format to virtual format. */
+
+#define REGISTER_CONVERTIBLE(N) (((unsigned)(N) - FP0_REGNUM) < 8)
+
+#include "floatformat.h"
+
+/* Convert data from raw format for register REGNUM in buffer FROM
+ to virtual format with type TYPE in buffer TO. */
+
+#define REGISTER_CONVERT_TO_VIRTUAL(REGNUM,TYPE,FROM,TO) \
+do \
+ { \
+ DOUBLEST dbl_tmp_val; \
+ floatformat_to_doublest (&floatformat_m68881_ext, (FROM), &dbl_tmp_val); \
+ store_floating ((TO), TYPE_LENGTH (TYPE), dbl_tmp_val); \
+ } while (0)
+
+/* Convert data from virtual format with type TYPE in buffer FROM
+ to raw format for register REGNUM in buffer TO. */
+
+#define REGISTER_CONVERT_TO_RAW(TYPE,REGNUM,FROM,TO) \
+do \
+ { \
+ DOUBLEST dbl_tmp_val; \
+ dbl_tmp_val = extract_floating ((FROM), TYPE_LENGTH (TYPE)); \
+ floatformat_from_doublest (&floatformat_m68881_ext, &dbl_tmp_val, (TO)); \
+ } while (0)
+
+/* Return the GDB type object for the "standard" data type of data
+ in register N. This should be int for D0-D7, double for FP0-FP7,
+ and void pointer for all others (A0-A7, PC, SR, FPCONTROL etc).
+ Note, for registers which contain addresses return pointer to void,
+ not pointer to char, because we don't want to attempt to print
+ the string after printing the address. */
+
+#define REGISTER_VIRTUAL_TYPE(N) \
+ ((unsigned) (N) >= FPC_REGNUM ? lookup_pointer_type (builtin_type_void) : \
+ (unsigned) (N) >= FP0_REGNUM ? builtin_type_double : \
+ (unsigned) (N) >= A0_REGNUM ? lookup_pointer_type (builtin_type_void) : \
+ builtin_type_int)
+
+/* Initializer for an array of names of registers.
+ Entries beyond the first NUM_REGS are ignored. */
+
+#define REGISTER_NAMES \
+ {"d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", \
+ "a0", "a1", "a2", "a3", "a4", "a5", "fp", "sp", \
+ "ps", "pc", \
+ "fp0", "fp1", "fp2", "fp3", "fp4", "fp5", "fp6", "fp7", \
+ "fpcontrol", "fpstatus", "fpiaddr", "fpcode", "fpflags" }
+
+/* Register numbers of various important registers.
+ Note that some of these values are "real" register numbers,
+ and correspond to the general registers of the machine,
+ and some are "phony" register numbers which are too large
+ to be actual register numbers as far as the user is concerned
+ but do serve to get the desired values when passed to read_register. */
+
+#define D0_REGNUM 0
+#define A0_REGNUM 8
+#define A1_REGNUM 9
+#define FP_REGNUM 14 /* Contains address of executing stack frame */
+#define SP_REGNUM 15 /* Contains address of top of stack */
+#define PS_REGNUM 16 /* Contains processor status */
+#define PC_REGNUM 17 /* Contains program counter */
+#define FP0_REGNUM 18 /* Floating point register 0 */
+#define FPC_REGNUM 26 /* 68881 control register */
+#define FPS_REGNUM 27 /* 68881 status register */
+#define FPI_REGNUM 28 /* 68881 iaddr register */
+
+/* Store the address of the place in which to copy the structure the
+ subroutine will return. This is called from call_function. */
+
+#define STORE_STRUCT_RETURN(ADDR, SP) \
+ { write_register (A1_REGNUM, (ADDR)); }
+
+/* Extract from an array REGBUF containing the (raw) register state
+ a function return value of type TYPE, and copy that, in virtual format,
+ into VALBUF. This is assuming that floating point values are returned
+ as doubles in d0/d1. */
+
+#if !defined (EXTRACT_RETURN_VALUE)
+#define EXTRACT_RETURN_VALUE(TYPE,REGBUF,VALBUF) \
+ memcpy ((VALBUF), \
+ (char *)(REGBUF) + \
+ (TYPE_LENGTH(TYPE) >= 4 ? 0 : 4 - TYPE_LENGTH(TYPE)), \
+ TYPE_LENGTH(TYPE))
+#endif
+
+/* Write into appropriate registers a function return value
+ of type TYPE, given in virtual format. Assumes floats are passed
+ in d0/d1. */
+
+#if !defined (STORE_RETURN_VALUE)
+#define STORE_RETURN_VALUE(TYPE,VALBUF) \
+ write_register_bytes (0, VALBUF, TYPE_LENGTH (TYPE))
+#endif
+
+/* Extract from an array REGBUF containing the (raw) register state
+ the address in which a function should return its structure value,
+ as a CORE_ADDR (or an expression that can be used as one). */
+
+#define EXTRACT_STRUCT_VALUE_ADDRESS(REGBUF) (*(CORE_ADDR *)(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.
+ In the case of the 68000, the frame's nominal address
+ is the address of a 4-byte word containing the calling frame's address. */
+
+/* If we are chaining from sigtramp, then manufacture a sigtramp frame
+ (which isn't really on the stack. I'm not sure this is right for anything
+ but BSD4.3 on an hp300. */
+#define FRAME_CHAIN(thisframe) \
+ (thisframe->signal_handler_caller \
+ ? thisframe->frame \
+ : (!inside_entry_file ((thisframe)->pc) \
+ ? read_memory_integer ((thisframe)->frame, 4) \
+ : 0))
+
+/* Define other aspects of the stack frame. */
+
+/* A macro that tells us whether the function invocation represented
+ by FI does not have a frame on the stack associated with it. If it
+ does not, FRAMELESS is set to 1, else 0. */
+#define FRAMELESS_FUNCTION_INVOCATION(FI, FRAMELESS) \
+ do { \
+ if ((FI)->signal_handler_caller) \
+ (FRAMELESS) = 0; \
+ else \
+ (FRAMELESS) = frameless_look_for_prologue(FI); \
+ } while (0)
+
+/* This was determined by experimentation on hp300 BSD 4.3. Perhaps
+ it corresponds to some offset in /usr/include/sys/user.h or
+ something like that. Using some system include file would
+ have the advantage of probably being more robust in the face
+ of OS upgrades, but the disadvantage of being wrong for
+ cross-debugging. */
+
+#define SIG_PC_FP_OFFSET 530
+
+#define FRAME_SAVED_PC(FRAME) \
+ (((FRAME)->signal_handler_caller \
+ ? ((FRAME)->next \
+ ? read_memory_integer ((FRAME)->next->frame + SIG_PC_FP_OFFSET, 4) \
+ : read_memory_integer (read_register (SP_REGNUM) \
+ + SIG_PC_FP_OFFSET - 8, 4) \
+ ) \
+ : read_memory_integer ((FRAME)->frame + 4, 4)) \
+ )
+
+#define FRAME_ARGS_ADDRESS(fi) ((fi)->frame)
+
+#define FRAME_LOCALS_ADDRESS(fi) ((fi)->frame)
+
+/* Set VAL to the number of args passed to frame described by FI.
+ Can set VAL to -1, meaning no way to tell. */
+
+/* We can't tell how many args there are
+ now that the C compiler delays popping them. */
+#if !defined (FRAME_NUM_ARGS)
+#define FRAME_NUM_ARGS(val,fi) (val = -1)
+#endif
+
+/* Return number of bytes at start of arglist that are not really args. */
+
+#define FRAME_ARGS_SKIP 8
+
+/* Put here the code to store, into a struct frame_saved_regs,
+ the addresses of the saved registers of frame described by FRAME_INFO.
+ This includes special registers such as pc and fp saved in special
+ ways in the stack frame. sp is even more special:
+ the address we return for it IS the sp for the next frame. */
+
+#if !defined (FRAME_FIND_SAVED_REGS)
+#define FRAME_FIND_SAVED_REGS(fi,fsr) m68k_find_saved_regs ((fi), &(fsr))
+#endif /* no FIND_FRAME_SAVED_REGS. */
+
+
+/* Things needed for making the inferior call functions. */
+
+/* The CALL_DUMMY macro is the sequence of instructions, as disassembled
+ by gdb itself:
+
+ These instructions exist only so that m68k_find_saved_regs can parse
+ them as a "prologue"; they are never executed.
+
+ fmovemx fp0-fp7,sp@- 0xf227 0xe0ff
+ moveml d0-a5,sp@- 0x48e7 0xfffc
+ clrw sp@- 0x4267
+ movew ccr,sp@- 0x42e7
+
+ The arguments are pushed at this point by GDB; no code is needed in
+ the dummy for this. The CALL_DUMMY_START_OFFSET gives the position
+ of the following jsr instruction. That is where we start
+ executing.
+
+ jsr @#0x32323232 0x4eb9 0x3232 0x3232
+ addal #0x69696969,sp 0xdffc 0x6969 0x6969
+ trap #<your BPT_VECTOR number here> 0x4e4?
+ nop 0x4e71
+
+ Note this is CALL_DUMMY_LENGTH bytes (28 for the above example).
+
+ The dummy frame always saves the floating-point registers, whether they
+ actually exist on this target or not. */
+
+/* FIXME: Wrong to hardwire this as BPT_VECTOR when sometimes it
+ should be REMOTE_BPT_VECTOR. Best way to fix it would be to define
+ CALL_DUMMY_BREAKPOINT_OFFSET. */
+
+#define CALL_DUMMY {0xf227e0ff, 0x48e7fffc, 0x426742e7, 0x4eb93232, 0x3232dffc, 0x69696969, (0x4e404e71 | (BPT_VECTOR << 16))}
+#define CALL_DUMMY_LENGTH 28 /* Size of CALL_DUMMY */
+#define CALL_DUMMY_START_OFFSET 12 /* Offset to jsr instruction*/
+#define CALL_DUMMY_BREAKPOINT_OFFSET (CALL_DUMMY_START_OFFSET + 12)
+
+/* Insert the specified number of args and function address
+ into a call sequence of the above form stored at DUMMYNAME.
+ We use the BFD routines to store a big-endian value of known size. */
+
+#define FIX_CALL_DUMMY(dummyname, pc, fun, nargs, args, type, gcc_p) \
+{ bfd_putb32 (fun, (unsigned char *) dummyname + CALL_DUMMY_START_OFFSET + 2); \
+ bfd_putb32 (nargs*4, (unsigned char *) dummyname + CALL_DUMMY_START_OFFSET + 8); }
+
+/* Push an empty stack frame, to record the current PC, etc. */
+
+#define PUSH_DUMMY_FRAME { m68k_push_dummy_frame (); }
+
+extern void m68k_push_dummy_frame PARAMS ((void));
+
+extern void m68k_pop_frame PARAMS ((void));
+
+/* Discard from the stack the innermost frame, restoring all registers. */
+
+#define POP_FRAME { m68k_pop_frame (); }
+
+/* Offset from SP to first arg on stack at first instruction of a function */
+
+#define SP_ARG0 (1 * 4)
+
+#define TARGET_M68K
diff --git a/gdb/config/m68k/tm-m68klynx.h b/gdb/config/m68k/tm-m68klynx.h
new file mode 100644
index 00000000000..fbe57076f3c
--- /dev/null
+++ b/gdb/config/m68k/tm-m68klynx.h
@@ -0,0 +1,38 @@
+/* Macro definitions for Motorola 680x0 running under LynxOS.
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef TM_M68KLYNX_H
+#define TM_M68KLYNX_H
+
+#include "tm-lynx.h"
+
+/* If PC-2 contains this instruction, then we know what we are in a system
+ call stub, and the return PC is is at SP+4, instead of SP. */
+
+#define SYSCALL_TRAP 0x4e4a /* trap #10 */
+#define SYSCALL_TRAP_OFFSET 2 /* PC is after trap instruction */
+
+/* Use the generic 68k definitions. */
+
+#include "m68k/tm-m68k.h"
+
+/* Disable dumbshit alternate breakpoint mechanism needed by 68k stub. */
+#undef REMOTE_BREAKPOINT
+
+#endif /* TM_M68KLYNX_H */
diff --git a/gdb/config/m68k/tm-m68kv4.h b/gdb/config/m68k/tm-m68kv4.h
new file mode 100644
index 00000000000..67306073c80
--- /dev/null
+++ b/gdb/config/m68k/tm-m68kv4.h
@@ -0,0 +1,70 @@
+/* Target definitions for GDB on a Motorola 680x0 running SVR4.
+ (Commodore Amiga with amix or Atari TT with ASV)
+ Copyright (C) 1991, 1995 Free Software Foundation, Inc.
+ Written by Fred Fish at Cygnus Support (fnf@cygint)
+
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Define BPT_VECTOR if it is different than the default.
+ This is the vector number used by traps to indicate a breakpoint. */
+
+#define BPT_VECTOR 0x1
+
+/* How much to decrement the PC after a trap. Depends on kernel. */
+
+#define DECR_PC_AFTER_BREAK 0 /* No decrement required */
+
+/* Use the alternate method of determining valid frame chains. */
+
+#define FRAME_CHAIN_VALID(fp,fi) alternate_frame_chain_valid (fp, fi)
+
+#include "tm-sysv4.h"
+#include "m68k/tm-m68k.h"
+
+/* Offsets (in target ints) into jmp_buf. Not defined in any system header
+ file, so we have to step through setjmp/longjmp with a debugger and figure
+ them out. As a double check, note that <setjmp> defines _JBLEN as 13,
+ which matches the number of elements we see saved by setjmp(). */
+
+#define JB_ELEMENT_SIZE sizeof(int) /* jmp_buf[_JBLEN] is array of ints */
+
+#define JB_D2 0
+#define JB_D3 1
+#define JB_D4 2
+#define JB_D5 3
+#define JB_D6 4
+#define JB_D7 5
+#define JB_A1 6
+#define JB_A2 7
+#define JB_A3 8
+#define JB_A4 9
+#define JB_A5 10
+#define JB_A6 11
+#define JB_A7 12
+
+#define JB_PC JB_A1 /* Setjmp()'s return PC saved in A1 */
+
+/* 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 ADDR.
+ This routine returns true on success */
+
+#define GET_LONGJMP_TARGET(ADDR) get_longjmp_target(ADDR)
+extern int get_longjmp_target PARAMS ((CORE_ADDR *));
+
+/* Convert a DWARF register number to a gdb REGNUM. */
+#define DWARF_REG_TO_REGNUM(num) ((num) < 16 ? (num) : (num)+FP0_REGNUM-16)
diff --git a/gdb/config/m68k/tm-mac.h b/gdb/config/m68k/tm-mac.h
new file mode 100644
index 00000000000..90b4fabf5cb
--- /dev/null
+++ b/gdb/config/m68k/tm-mac.h
@@ -0,0 +1,20 @@
+/* Target-dependent definitions for Mac running MacOS.
+ Copyright (C) 1994 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "m68k/tm-m68k.h"
diff --git a/gdb/config/m68k/tm-monitor.h b/gdb/config/m68k/tm-monitor.h
new file mode 100644
index 00000000000..7a48d9c9a49
--- /dev/null
+++ b/gdb/config/m68k/tm-monitor.h
@@ -0,0 +1,44 @@
+/* Target machine definitions for a generic m68k monitor/emulator.
+ Copyright (C) 1986, 1987, 1989, 1993, 1995 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* The definitions here are appropriate for several embedded m68k-based
+ targets, including IDP (rom68k), BCC (cpu32bug), and EST's emulator. */
+
+/* GCC is probably the only compiler used on this configuration. So
+ get this right even if the code which detects gcc2_compiled. is
+ still broken. */
+
+#define BELIEVE_PCC_PROMOTION 1
+
+/* The target system handles breakpoints. */
+
+#define DECR_PC_AFTER_BREAK 0
+
+/* No float registers. */
+
+/*#define NUM_REGS 18*/
+
+#include "m68k/tm-m68k.h"
+
+/* Need to do this for ELF targets, where we can't figure out the boundaries of
+ the entry file. This method stops the backtrace when we reach main. */
+
+#define FRAME_CHAIN_VALID(fp,fi) alternate_frame_chain_valid (fp, fi)
+
+/* FIXME, should do GET_LONGJMP_TARGET for newlib. */
diff --git a/gdb/config/m68k/tm-nbsd.h b/gdb/config/m68k/tm-nbsd.h
new file mode 100644
index 00000000000..cc86cc8d4d2
--- /dev/null
+++ b/gdb/config/m68k/tm-nbsd.h
@@ -0,0 +1,41 @@
+/* Macro definitions for i386 running under NetBSD.
+ Copyright 1994 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef TM_NBSD_H
+#define TM_NBSD_H
+
+#include <sys/param.h>
+#include <machine/vmparam.h>
+
+/* Define BPT_VECTOR if it is different than the default.
+ This is the vector number used by traps to indicate a breakpoint. */
+
+#define BPT_VECTOR 0x2
+
+/* Address of end of stack space. */
+#define STACK_END_ADDR USRSTACK
+
+/* For NetBSD, sigtramp is 32 bytes before STACK_END_ADDR. */
+#define SIGTRAMP_START(pc) (STACK_END_ADDR - 32)
+#define SIGTRAMP_END(pc) (STACK_END_ADDR)
+
+#include "m68k/tm-m68k.h"
+#include "tm-nbsd.h"
+
+#endif /* TM_NBSD_H */
diff --git a/gdb/config/m68k/tm-news.h b/gdb/config/m68k/tm-news.h
new file mode 100644
index 00000000000..9fca4467659
--- /dev/null
+++ b/gdb/config/m68k/tm-news.h
@@ -0,0 +1,75 @@
+/* Parameters for execution on a Sony/NEWS, for GDB, the GNU debugger.
+ Copyright 1987, 1989, 1991, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* See following cpu type determination macro to get the machine type.
+
+Here is an m-news.h file for gdb. It supports the 68881 registers.
+ by hikichi@srava.sra.junet
+
+* Ptrace for handling floating register has a bug(before NEWS OS version 2.2),
+* After NEWS OS version 3.2, some of ptrace's bug is fixed.
+ But we cannot change the floating register(see adb(1) in OS 3.2) yet. */
+
+/* Extract from an array REGBUF containing the (raw) register state
+ a function return value of type TYPE, and copy that, in virtual format,
+ into VALBUF. */
+
+/* when it return the floating value, use the FP0 in NEWS. */
+#define EXTRACT_RETURN_VALUE(TYPE,REGBUF,VALBUF) \
+ { if (TYPE_CODE (TYPE) == TYPE_CODE_FLT) \
+ { \
+ REGISTER_CONVERT_TO_VIRTUAL (FP0_REGNUM, TYPE, \
+ &REGBUF[REGISTER_BYTE (FP0_REGNUM)], \
+ VALBUF); \
+ } \
+ else \
+ memcpy (VALBUF, REGBUF, TYPE_LENGTH (TYPE)); }
+
+/* Write into appropriate registers a function return value
+ of type TYPE, given in virtual format. */
+
+/* when it return the floating value, use the FP0 in NEWS. */
+#define STORE_RETURN_VALUE(TYPE,VALBUF) \
+ { if (TYPE_CODE (TYPE) == TYPE_CODE_FLT) \
+ { \
+ char raw_buf[REGISTER_RAW_SIZE (FP0_REGNUM)]; \
+ REGISTER_CONVERT_TO_RAW (TYPE, FP0_REGNUM, VALBUF, raw_buf); \
+ write_register_bytes (REGISTER_BYTE (FP0_REGNUM), \
+ raw_buf, REGISTER_RAW_SIZE (FP0_REGNUM)); \
+ } \
+ else \
+ write_register_bytes (0, VALBUF, TYPE_LENGTH (TYPE)); }
+
+/* Return number of args passed to a frame.
+ Can return -1, meaning no way to tell. */
+
+#define FRAME_NUM_ARGS(val, fi) \
+{ register CORE_ADDR pc = FRAME_SAVED_PC (fi); \
+ register int insn = 0177777 & read_memory_integer (pc, 2); \
+ val = 0; \
+ if (insn == 0047757 || insn == 0157374) /* lea W(sp),sp or addaw #W,sp */ \
+ val = read_memory_integer (pc + 2, 2); \
+ else if ((insn & 0170777) == 0050217 /* addql #N, sp */ \
+ || (insn & 0170777) == 0050117) /* addqw */ \
+ { val = (insn >> 9) & 7; if (val == 0) val = 8; } \
+ else if (insn == 0157774) /* addal #WW, sp */ \
+ val = read_memory_integer (pc + 2, 4); \
+ val >>= 2; }
+
+#include "m68k/tm-m68k.h"
diff --git a/gdb/config/m68k/tm-os68k.h b/gdb/config/m68k/tm-os68k.h
new file mode 100644
index 00000000000..a69573f761b
--- /dev/null
+++ b/gdb/config/m68k/tm-os68k.h
@@ -0,0 +1,46 @@
+/* Parameters for execution on VxWorks m68k's, for GDB, the GNU debugger.
+ Copyright (C) 1986, 1987, 1989, 1991 Free Software Foundation, Inc.
+ Contributed by Cygnus Support.
+
+This file is part of GDB.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define GDBINIT_FILENAME ".os68gdbinit"
+
+#define DEFAULT_PROMPT "(os68k) "
+
+#include "m68k/tm-m68k.h"
+
+/* We have more complex, useful breakpoints on the target. */
+#undef DECR_PC_AFTER_BREAK
+#define DECR_PC_AFTER_BREAK 0
+
+/* Takes the current frame-struct pointer and returns the chain-pointer
+ to get to the calling frame.
+
+ If our current frame pointer is zero, we're at the top; else read out
+ the saved FP from memory pointed to by the current FP. */
+
+#undef FRAME_CHAIN
+#define FRAME_CHAIN(thisframe) ((thisframe)->frame? read_memory_integer ((thisframe)->frame, 4): 0)
+
+/* If the chain pointer is zero (either because the saved value fetched
+ by FRAME_CHAIN was zero, or because the current FP was zero so FRAME_CHAIN
+ never fetched anything), we are at the top of the stack. */
+/* We are guaranteed to have a zero frame pointer at bottom of stack, too. */
+
+#undef FRAME_CHAIN_VALID
+#define FRAME_CHAIN_VALID(chain, thisframe) nonnull_frame_chain_valid (chain, thisframe)
diff --git a/gdb/config/m68k/tm-st2000.h b/gdb/config/m68k/tm-st2000.h
new file mode 100644
index 00000000000..8ddf0e9aead
--- /dev/null
+++ b/gdb/config/m68k/tm-st2000.h
@@ -0,0 +1,20 @@
+/* Parameters for a Tandem ST2000 phone switch.
+ Copyright (C) 1986, 1987, 1989, 199 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "m68k/tm-m68k.h"
diff --git a/gdb/config/m68k/tm-sun2.h b/gdb/config/m68k/tm-sun2.h
new file mode 100644
index 00000000000..9970f1ef5c2
--- /dev/null
+++ b/gdb/config/m68k/tm-sun2.h
@@ -0,0 +1,23 @@
+/* Parameters for execution on a Sun, for GDB, the GNU debugger.
+ Copyright (C) 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* The child target can't deal with floating registers. */
+#define CANNOT_STORE_REGISTER(regno) ((regno) >= FP0_REGNUM)
+
+#include "m68k/tm-m68k.h"
diff --git a/gdb/config/m68k/tm-sun2os4.h b/gdb/config/m68k/tm-sun2os4.h
new file mode 100644
index 00000000000..76c7f99f217
--- /dev/null
+++ b/gdb/config/m68k/tm-sun2os4.h
@@ -0,0 +1,20 @@
+/* Copyright (C) 1990, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "m68k/tm-sun2.h"
+#include "tm-sunos.h"
diff --git a/gdb/config/m68k/tm-sun3.h b/gdb/config/m68k/tm-sun3.h
new file mode 100644
index 00000000000..be45db4cf8c
--- /dev/null
+++ b/gdb/config/m68k/tm-sun3.h
@@ -0,0 +1,107 @@
+/* Parameters for execution on a Sun, for GDB, the GNU debugger.
+ Copyright (C) 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef TM_SUN3_H
+#define TM_SUN3_H
+
+/* Sun3 status includes fpflags, which shows whether the FPU has been used
+ by the process, and whether the FPU was done with an instruction or
+ was interrupted in the middle of a long instruction. See
+ <machine/reg.h>. */
+/* a&d, pc,sr, fp, fpstat, fpflags */
+
+#define REGISTER_BYTES (16*4 + 8 + 8*12 + 3*4 + 4)
+
+#define NUM_REGS 31
+
+#define REGISTER_BYTES_OK(b) \
+ ((b) == REGISTER_BYTES \
+ || (b) == REGISTER_BYTES_FP \
+ || (b) == REGISTER_BYTES_NOFP)
+
+/* If PC contains this instruction, then we know what we are in a system
+ call stub, and the return PC is is at SP+4, instead of SP. */
+
+#define SYSCALL_TRAP 0x4e40 /* trap #0 */
+#define SYSCALL_TRAP_OFFSET 0 /* PC points at trap instruction */
+
+#include "m68k/tm-m68k.h"
+
+/* Disable alternate breakpoint mechanism needed by 68k stub. */
+#undef REMOTE_BREAKPOINT
+
+/* Offsets (in target ints) into jmp_buf. Not defined by Sun, but at least
+ documented in a comment in <machine/setjmp.h>! */
+
+#define JB_ELEMENT_SIZE 4
+
+#define JB_ONSSTACK 0
+#define JB_SIGMASK 1
+#define JB_SP 2
+#define JB_PC 3
+#define JB_PSL 4
+#define JB_D2 5
+#define JB_D3 6
+#define JB_D4 7
+#define JB_D5 8
+#define JB_D6 9
+#define JB_D7 10
+#define JB_A2 11
+#define JB_A3 12
+#define JB_A4 13
+#define JB_A5 14
+#define JB_A6 15
+
+/* 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 ADDR.
+ This routine returns true on success */
+
+#define GET_LONGJMP_TARGET(ADDR) get_longjmp_target(ADDR)
+extern int get_longjmp_target PARAMS ((CORE_ADDR *));
+
+/* If sun3 pcc says that a parameter is a short, it's a short. */
+#define BELIEVE_PCC_PROMOTION_TYPE
+
+/* Can't define BELIEVE_PCC_PROMOTION for SunOS /bin/cc of SunOS 4.1.1.
+ Apparently Sun fixed this for the sparc but not the sun3. */
+
+/* The code which tries to deal with this bug is never harmful on a sun3. */
+#define SUN_FIXED_LBRAC_BUG (0)
+
+/* On the sun3 the kernel pushes a sigcontext on the user stack and then
+ `calls' _sigtramp in user code. _sigtramp saves the floating point status
+ on the stack and calls the signal handler function. The stack does not
+ contain enough information to allow a normal backtrace, but sigcontext
+ contains the saved user pc/sp. FRAME_CHAIN and friends in tm-m68k.h and
+ m68k_find_saved_regs deal with this situation by manufacturing a fake frame
+ for _sigtramp.
+ SIG_PC_FP_OFFSET is the offset from the signal handler frame to the
+ saved pc in sigcontext.
+ SIG_SP_FP_OFFSET is the offset from the signal handler frame to the end
+ of sigcontext which is identical to the saved sp at SIG_PC_FP_OFFSET - 4.
+
+ Please note that it is impossible to correctly backtrace from a breakpoint
+ in _sigtramp as _sigtramp modifies the stack pointer a few times. */
+
+#undef SIG_PC_FP_OFFSET
+#define SIG_PC_FP_OFFSET 324
+#define SIG_SP_FP_OFFSET 332
+
+#endif /* TM_SUN3_H */
diff --git a/gdb/config/m68k/tm-sun3os4.h b/gdb/config/m68k/tm-sun3os4.h
new file mode 100644
index 00000000000..927587b7819
--- /dev/null
+++ b/gdb/config/m68k/tm-sun3os4.h
@@ -0,0 +1,21 @@
+/* Target machine parameters for Sun-3 under SunOS 4.x, for GDB.
+ Copyright (C) 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "m68k/tm-sun3.h"
+#include "tm-sunos.h"
diff --git a/gdb/config/m68k/tm-vx68.h b/gdb/config/m68k/tm-vx68.h
new file mode 100644
index 00000000000..e601bda737c
--- /dev/null
+++ b/gdb/config/m68k/tm-vx68.h
@@ -0,0 +1,91 @@
+/* Target machine description for VxWorks m68k's, for GDB, the GNU debugger.
+ Copyright 1986, 1987, 1989, 1991, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define GDBINIT_FILENAME ".vxgdbinit"
+
+#define DEFAULT_PROMPT "(vxgdb) "
+
+/* GCC is probably the only compiler used on this configuration. So
+ get this right even if the code which detects gcc2_compiled. is
+ still broken. */
+
+#define BELIEVE_PCC_PROMOTION 1
+
+/* We have more complex, useful breakpoints on the target. */
+#define DECR_PC_AFTER_BREAK 0
+
+#include "m68k/tm-m68k.h"
+
+/* Takes the current frame-struct pointer and returns the chain-pointer
+ to get to the calling frame.
+
+ If our current frame pointer is zero, we're at the top; else read out
+ the saved FP from memory pointed to by the current FP. */
+
+#undef FRAME_CHAIN
+#define FRAME_CHAIN(thisframe) ((thisframe)->frame? read_memory_integer ((thisframe)->frame, 4): 0)
+
+/* If the chain pointer is zero (either because the saved value fetched
+ by FRAME_CHAIN was zero, or because the current FP was zero so FRAME_CHAIN
+ never fetched anything), we are at the top of the stack. */
+/* We are guaranteed to have a zero frame pointer at bottom of stack, too. */
+
+#undef FRAME_CHAIN_VALID
+#define FRAME_CHAIN_VALID(chain, thisframe) nonnull_frame_chain_valid (chain, thisframe)
+
+/* FIXME, Longjmp information stolen from Sun-3 config. Dunno if right. */
+/* Offsets (in target ints) into jmp_buf. Not defined by Sun, but at least
+ documented in a comment in <machine/setjmp.h>! */
+
+#define JB_ELEMENT_SIZE 4
+
+#define JB_ONSSTACK 0
+#define JB_SIGMASK 1
+#define JB_SP 2
+#define JB_PC 3
+#define JB_PSL 4
+#define JB_D2 5
+#define JB_D3 6
+#define JB_D4 7
+#define JB_D5 8
+#define JB_D6 9
+#define JB_D7 10
+#define JB_A2 11
+#define JB_A3 12
+#define JB_A4 13
+#define JB_A5 14
+#define JB_A6 15
+
+/* 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 ADDR.
+ This routine returns true on success */
+
+#define GET_LONGJMP_TARGET(ADDR) get_longjmp_target(ADDR)
+extern int get_longjmp_target PARAMS ((CORE_ADDR *));
+
+/* Number of registers in a ptrace_getregs call. */
+
+#define VX_NUM_REGS (18)
+
+/* Number of registers in a ptrace_getfpregs call. */
+
+#define VX_SIZE_FPREGS (8 * REGISTER_RAW_SIZE (FP0_REGNUM) \
+ + (3 * REGISTER_SIZE))
diff --git a/gdb/config/m68k/vxworks68.mt b/gdb/config/m68k/vxworks68.mt
new file mode 100644
index 00000000000..8c9774496cb
--- /dev/null
+++ b/gdb/config/m68k/vxworks68.mt
@@ -0,0 +1,3 @@
+# Target: Motorola m68k running VxWorks
+TDEPFILES= m68k-tdep.o remote-vx.o remote-vx68.o xdr_ld.o xdr_ptrace.o xdr_rdb.o
+TM_FILE= tm-vx68.h
diff --git a/gdb/config/m68k/xm-3b1.h b/gdb/config/m68k/xm-3b1.h
new file mode 100644
index 00000000000..d1cc7f151eb
--- /dev/null
+++ b/gdb/config/m68k/xm-3b1.h
@@ -0,0 +1,85 @@
+/* Parameters for execution on a 3b1.
+ Copyright (C) 1986, 1987, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define HOST_BYTE_ORDER BIG_ENDIAN
+
+#define HAVE_TERMIO
+#define USG
+
+/* This is the amount to subtract from u.u_ar0
+ to get the offset in the core file of the register values. */
+
+#define KERNEL_U_ADDR 0x70000
+
+#define REGISTER_U_ADDR(addr, blockend, regno) \
+{ addr = blockend + regno * 4; }
+
+/* Interface definitions for kernel debugger KDB. */
+
+/* Map machine fault codes into signal numbers.
+ First subtract 0, divide by 4, then index in a table.
+ Faults for which the entry in this table is 0
+ are not handled by KDB; the program's own trap handler
+ gets to handle then. */
+
+#define FAULT_CODE_ORIGIN 0
+#define FAULT_CODE_UNITS 4
+#define FAULT_TABLE \
+{ 0, 0, 0, 0, SIGTRAP, 0, 0, 0, \
+ 0, SIGTRAP, 0, 0, 0, 0, 0, SIGKILL, \
+ 0, 0, 0, 0, 0, 0, 0, 0, \
+ SIGILL }
+
+/* Start running with a stack stretching from BEG to END.
+ BEG and END should be symbols meaningful to the assembler.
+ This is used only for kdb. */
+
+#define INIT_STACK(beg, end) \
+{ asm (".globl end"); \
+ asm ("movel $ end, sp"); \
+ asm ("clrl fp"); }
+
+/* Push the frame pointer register on the stack. */
+#define PUSH_FRAME_PTR \
+ asm ("movel fp, -(sp)");
+
+/* Copy the top-of-stack to the frame pointer register. */
+#define POP_FRAME_PTR \
+ asm ("movl (sp), fp");
+
+/* After KDB is entered by a fault, push all registers
+ that GDB thinks about (all NUM_REGS of them),
+ so that they appear in order of ascending GDB register number.
+ The fault code will be on the stack beyond the last register. */
+
+#define PUSH_REGISTERS \
+{ asm ("clrw -(sp)"); \
+ asm ("pea 10(sp)"); \
+ asm ("movem $ 0xfffe,-(sp)"); }
+
+/* Assuming the registers (including processor status) have been
+ pushed on the stack in order of ascending GDB register number,
+ restore them and return to the address in the saved PC register. */
+
+#define POP_REGISTERS \
+{ asm ("subil $8,28(sp)"); \
+ asm ("movem (sp),$ 0xffff"); \
+ asm ("rte"); }
+
+#endif
diff --git a/gdb/config/m68k/xm-altos.h b/gdb/config/m68k/xm-altos.h
new file mode 100644
index 00000000000..ca93bd1b7a0
--- /dev/null
+++ b/gdb/config/m68k/xm-altos.h
@@ -0,0 +1,202 @@
+/* Definitions to make GDB run on an Altos 3068 (m68k running SVR2)
+ Copyright (C) 1987,1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define HOST_BYTE_ORDER BIG_ENDIAN
+
+/* The altos support would make a good base for a port to other USGR2 systems
+ (like the 3b1 and the Convergent miniframe). */
+
+/* This is only needed in one file, but it's cleaner to put it here than
+ putting in more #ifdef's. */
+#include <sys/page.h>
+#include <sys/net.h>
+
+#define USG
+
+#define HAVE_TERMIO
+
+#define CBREAK XTABS /* It takes all kinds... */
+
+#ifndef R_OK
+#define R_OK 4
+#define W_OK 2
+#define X_OK 1
+#define F_OK 0
+#endif
+
+/* Get sys/wait.h ie. from a Sun and edit it a little (mc68000 to m68k) */
+/* Why bother? */
+#if 0
+#define HAVE_WAIT_STRUCT
+#endif
+
+/* This is the amount to subtract from u.u_ar0
+ to get the offset in the core file of the register values. */
+
+#define KERNEL_U_ADDR 0x1fbf000
+
+#define REGISTER_U_ADDR(addr, blockend, regno) \
+{ if (regno <= SP_REGNUM) \
+ addr = blockend + regno * 4; \
+ else if (regno == PS_REGNUM) \
+ addr = blockend + regno * 4 + 4; \
+ else if (regno == PC_REGNUM) \
+ addr = blockend + regno * 4 + 2; \
+}
+
+#define REGISTER_ADDR(u_ar0, regno) \
+ (((regno) < PS_REGNUM) \
+ ? (&((struct exception_stack *) (u_ar0))->e_regs[(regno + R0)]) \
+ : (((regno) == PS_REGNUM) \
+ ? ((int *) (&((struct exception_stack *) (u_ar0))->e_PS)) \
+ : (&((struct exception_stack *) (u_ar0))->e_PC)))
+
+#define FP_REGISTER_ADDR(u, regno) \
+ (((char *) \
+ (((regno) < FPC_REGNUM) \
+ ? (&u.u_pcb.pcb_mc68881[FMC68881_R0 + (((regno) - FP0_REGNUM) * 3)]) \
+ : (&u.u_pcb.pcb_mc68881[FMC68881_C + ((regno) - FPC_REGNUM)]))) \
+ - ((char *) (& u)))
+
+
+#ifndef __GNUC__
+#undef USE_GAS
+#define ALTOS_AS
+#else
+#define USE_GAS
+#endif
+
+/* Motorola assembly format */
+#if !defined(USE_GAS) && !defined(ALTOS)
+#define MOTOROLA
+#endif
+
+/* Interface definitions for kernel debugger KDB. */
+
+/* Map machine fault codes into signal numbers.
+ First subtract 0, divide by 4, then index in a table.
+ Faults for which the entry in this table is 0
+ are not handled by KDB; the program's own trap handler
+ gets to handle then. */
+
+#define FAULT_CODE_ORIGIN 0
+#define FAULT_CODE_UNITS 4
+#define FAULT_TABLE \
+{ 0, 0, 0, 0, SIGTRAP, 0, 0, 0, \
+ 0, SIGTRAP, 0, 0, 0, 0, 0, SIGKILL, \
+ 0, 0, 0, 0, 0, 0, 0, 0, \
+ SIGILL }
+
+/* Start running with a stack stretching from BEG to END.
+ BEG and END should be symbols meaningful to the assembler.
+ This is used only for kdb. */
+
+#ifdef MOTOROLA
+#define INIT_STACK(beg, end) \
+{ asm (".globl end"); \
+ asm ("move.l $ end, sp"); \
+ asm ("clr.l fp"); }
+#else
+#ifdef ALTOS_AS
+#define INIT_STACK(beg, end) \
+{ asm ("global end"); \
+ asm ("mov.l &end,%sp"); \
+ asm ("clr.l %fp"); }
+#else
+#define INIT_STACK(beg, end) \
+{ asm (".globl end"); \
+ asm ("movel $ end, sp"); \
+ asm ("clrl fp"); }
+#endif
+#endif
+
+/* Push the frame pointer register on the stack. */
+#ifdef MOTOROLA
+#define PUSH_FRAME_PTR \
+ asm ("move.l fp, -(sp)");
+#else
+#ifdef ALTOS_AS
+#define PUSH_FRAME_PTR \
+ asm ("mov.l %fp, -(%sp)");
+#else
+#define PUSH_FRAME_PTR \
+ asm ("movel fp, -(sp)");
+#endif
+#endif
+
+/* Copy the top-of-stack to the frame pointer register. */
+#ifdef MOTOROLA
+#define POP_FRAME_PTR \
+ asm ("move.l (sp), fp");
+#else
+#ifdef ALTOS_AS
+#define POP_FRAME_PTR \
+ asm ("mov.l (%sp), %fp");
+#else
+#define POP_FRAME_PTR \
+ asm ("movl (sp), fp");
+#endif
+#endif
+
+/* After KDB is entered by a fault, push all registers
+ that GDB thinks about (all NUM_REGS of them),
+ so that they appear in order of ascending GDB register number.
+ The fault code will be on the stack beyond the last register. */
+
+#ifdef MOTOROLA
+#define PUSH_REGISTERS \
+{ asm ("clr.w -(sp)"); \
+ asm ("pea (10,sp)"); \
+ asm ("movem $ 0xfffe,-(sp)"); }
+#else
+#ifdef ALTOS_AS
+#define PUSH_REGISTERS \
+{ asm ("clr.w -(%sp)"); \
+ asm ("pea (10,%sp)"); \
+ asm ("movm.l &0xfffe,-(%sp)"); }
+#else
+#define PUSH_REGISTERS \
+{ asm ("clrw -(sp)"); \
+ asm ("pea 10(sp)"); \
+ asm ("movem $ 0xfffe,-(sp)"); }
+#endif
+#endif
+
+/* Assuming the registers (including processor status) have been
+ pushed on the stack in order of ascending GDB register number,
+ restore them and return to the address in the saved PC register. */
+
+#ifdef MOTOROLA
+#define POP_REGISTERS \
+{ asm ("subi.l $8,28(sp)"); \
+ asm ("movem (sp),$ 0xffff"); \
+ asm ("rte"); }
+#else
+#ifdef ALTOS_AS
+#define POP_REGISTERS \
+{ asm ("sub.l &8,28(%sp)"); \
+ asm ("movem (%sp),&0xffff"); \
+ asm ("rte"); }
+#else
+#define POP_REGISTERS \
+{ asm ("subil $8,28(sp)"); \
+ asm ("movem (sp),$ 0xffff"); \
+ asm ("rte"); }
+#endif
+#endif
diff --git a/gdb/config/m68k/xm-apollo68b.h b/gdb/config/m68k/xm-apollo68b.h
new file mode 100644
index 00000000000..f0defdaa91d
--- /dev/null
+++ b/gdb/config/m68k/xm-apollo68b.h
@@ -0,0 +1,24 @@
+/* Macro definitions for an Apollo m68k in BSD mode
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define HOST_BYTE_ORDER BIG_ENDIAN
+
+#define ALIGN_STACK_ON_STARTUP
+
+extern char *strdup();
diff --git a/gdb/config/m68k/xm-apollo68v.h b/gdb/config/m68k/xm-apollo68v.h
new file mode 100644
index 00000000000..c87ff478390
--- /dev/null
+++ b/gdb/config/m68k/xm-apollo68v.h
@@ -0,0 +1,44 @@
+/* Macro defintions for an Apollo.
+ Copyright (C) 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/*
+ * Changes for 80386 by Pace Willisson (pace@prep.ai.mit.edu)
+ * July 1988
+ */
+
+#define HOST_BYTE_ORDER BIG_ENDIAN
+
+/* I'm running gdb 3.4 under 386/ix 2.0.2, which is a derivative of AT&T's
+Sys V/386 3.2.
+
+On some machines, gdb crashes when it's starting up while calling the
+vendor's termio tgetent() routine. It always works when run under
+itself (actually, under 3.2, it's not an infinitely recursive bug.)
+After some poking around, it appears that depending on the environment
+size, or whether you're running YP, or the phase of the moon or something,
+the stack is not always long-aligned when main() is called, and tgetent()
+takes strong offense at that. On some machines this bug never appears, but
+on those where it does, it occurs quite reliably. */
+#define ALIGN_STACK_ON_STARTUP
+
+/* define USG if you are using sys5 /usr/include's */
+#define USG
+
+#define HAVE_TERMIO
+
diff --git a/gdb/config/m68k/xm-delta68.h b/gdb/config/m68k/xm-delta68.h
new file mode 100644
index 00000000000..6ce705cf85f
--- /dev/null
+++ b/gdb/config/m68k/xm-delta68.h
@@ -0,0 +1,36 @@
+/* Macro definitions for a Delta.
+ Copyright (C) 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define HOST_BYTE_ORDER BIG_ENDIAN
+
+/* I'm running gdb 4.9 under sysV68 R3V7.1.
+
+ 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
+
+#define HAVE_TERMIO
diff --git a/gdb/config/m68k/xm-dpx2.h b/gdb/config/m68k/xm-dpx2.h
new file mode 100644
index 00000000000..e5532e7229c
--- /dev/null
+++ b/gdb/config/m68k/xm-dpx2.h
@@ -0,0 +1,26 @@
+/* Parameters for execution on a Bull DPX2.
+ Copyright (C) 1986, 1987, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define HOST_BYTE_ORDER BIG_ENDIAN
+
+#define HAVE_TERMIOS
+#define USG
+
+/* Avoid redefinition errors */
+#include <limits.h>
diff --git a/gdb/config/m68k/xm-hp300bsd.h b/gdb/config/m68k/xm-hp300bsd.h
new file mode 100644
index 00000000000..5e67792dad1
--- /dev/null
+++ b/gdb/config/m68k/xm-hp300bsd.h
@@ -0,0 +1,85 @@
+/* Parameters for hosting on a Hewlett-Packard 9000/300, running bsd.
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/*
+ * Configuration file for HP9000/300 series machine running
+ * University of Utah's 4.3bsd (or 4.4BSD) port. This is NOT for HP-UX.
+ * Problems to hpbsd-bugs@cs.utah.edu
+ */
+
+#define HOST_BYTE_ORDER BIG_ENDIAN
+
+#include <sys/param.h> /* For INT_MIN */
+
+/* Kernel is a bit tenacious about sharing text segments, disallowing bpts. */
+#define ONE_PROCESS_WRITETEXT
+
+extern char *strdup PARAMS ((const char *));
+
+/* Interface definitions for kernel debugger KDB. */
+
+/* Map machine fault codes into signal numbers.
+ First subtract 0, divide by 4, then index in a table.
+ Faults for which the entry in this table is 0
+ are not handled by KDB; the program's own trap handler
+ gets to handle then. */
+
+#define FAULT_CODE_ORIGIN 0
+#define FAULT_CODE_UNITS 4
+#define FAULT_TABLE \
+{ 0, 0, 0, 0, SIGTRAP, 0, 0, 0, \
+ 0, SIGTRAP, 0, 0, 0, 0, 0, SIGKILL, \
+ 0, 0, 0, 0, 0, 0, 0, 0, \
+ SIGILL }
+
+/* Start running with a stack stretching from BEG to END.
+ BEG and END should be symbols meaningful to the assembler.
+ This is used only for kdb. */
+
+#define INIT_STACK(beg, end) \
+{ asm (".globl end"); \
+ asm ("movel #end, sp"); \
+ asm ("movel #0,a6"); }
+
+/* Push the frame pointer register on the stack. */
+#define PUSH_FRAME_PTR \
+ asm ("movel a6,sp@-");
+
+/* Copy the top-of-stack to the frame pointer register. */
+#define POP_FRAME_PTR \
+ asm ("movl sp@,a6");
+
+/* After KDB is entered by a fault, push all registers
+ that GDB thinks about (all NUM_REGS of them),
+ so that they appear in order of ascending GDB register number.
+ The fault code will be on the stack beyond the last register. */
+
+#define PUSH_REGISTERS \
+{ asm ("clrw -(sp)"); \
+ asm ("pea sp@(10)"); \
+ asm ("movem #0xfffe,sp@-"); }
+
+/* Assuming the registers (including processor status) have been
+ pushed on the stack in order of ascending GDB register number,
+ restore them and return to the address in the saved PC register. */
+
+#define POP_REGISTERS \
+{ asm ("subil #8,sp@(28)"); \
+ asm ("movem sp@,#0xffff"); \
+ asm ("rte"); }
diff --git a/gdb/config/m68k/xm-hp300hpux.h b/gdb/config/m68k/xm-hp300hpux.h
new file mode 100644
index 00000000000..b6d75d611e4
--- /dev/null
+++ b/gdb/config/m68k/xm-hp300hpux.h
@@ -0,0 +1,150 @@
+/* Parameters for HP 9000 model 320 hosting, for GDB, the GNU debugger.
+ Copyright (C) 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define HOST_BYTE_ORDER BIG_ENDIAN
+
+/* Define this to indicate problems with traps after continuing. */
+#define HP_OS_BUG
+
+/* Set flag to indicate whether HP's assembler is in use. */
+#ifdef __GNUC__
+#ifdef __HPUX_ASM__
+#define HPUX_ASM
+#endif
+#else /* not GNU C. */
+#define HPUX_ASM
+#endif /* not GNU C. */
+
+/* Define this for versions of hp-ux older than 6.0 */
+/* #define HPUX_VERSION_5 */
+
+/* define USG if you are using sys5 /usr/include's */
+#undef USG /* In case it was defined in the Makefile for cplus-dem.c */
+#define USG
+
+#define HAVE_TERMIOS
+
+#define REGISTER_ADDR(u_ar0, regno) \
+ (unsigned int) \
+ (((regno) < PS_REGNUM) \
+ ? (&((struct exception_stack *) (u_ar0))->e_regs[(regno + R0)]) \
+ : (((regno) == PS_REGNUM) \
+ ? ((int *) (&((struct exception_stack *) (u_ar0))->e_PS)) \
+ : (&((struct exception_stack *) (u_ar0))->e_PC)))
+
+#define FP_REGISTER_ADDR(u, regno) \
+ (((char *) \
+ (((regno) < FPC_REGNUM) \
+ ? (&u.u_pcb.pcb_mc68881[FMC68881_R0 + (((regno) - FP0_REGNUM) * 3)]) \
+ : (&u.u_pcb.pcb_mc68881[FMC68881_C + ((regno) - FPC_REGNUM)]))) \
+ - ((char *) (& u)))
+
+/* Interface definitions for kernel debugger KDB. */
+
+/* Map machine fault codes into signal numbers.
+ First subtract 0, divide by 4, then index in a table.
+ Faults for which the entry in this table is 0
+ are not handled by KDB; the program's own trap handler
+ gets to handle then. */
+
+#define FAULT_CODE_ORIGIN 0
+#define FAULT_CODE_UNITS 4
+#define FAULT_TABLE \
+{ 0, 0, 0, 0, SIGTRAP, 0, 0, 0, \
+ 0, SIGTRAP, 0, 0, 0, 0, 0, SIGKILL, \
+ 0, 0, 0, 0, 0, 0, 0, 0, \
+ SIGILL }
+
+#ifndef HPUX_ASM
+
+/* Start running with a stack stretching from BEG to END.
+ BEG and END should be symbols meaningful to the assembler.
+ This is used only for kdb. */
+
+#define INIT_STACK(beg, end) \
+{ asm (".globl end"); \
+ asm ("movel $ end, sp"); \
+ asm ("clrl fp"); }
+
+/* Push the frame pointer register on the stack. */
+#define PUSH_FRAME_PTR \
+ asm ("movel fp, -(sp)");
+
+/* Copy the top-of-stack to the frame pointer register. */
+#define POP_FRAME_PTR \
+ asm ("movl (sp), fp");
+
+/* After KDB is entered by a fault, push all registers
+ that GDB thinks about (all NUM_REGS of them),
+ so that they appear in order of ascending GDB register number.
+ The fault code will be on the stack beyond the last register. */
+
+#define PUSH_REGISTERS \
+{ asm ("clrw -(sp)"); \
+ asm ("pea 10(sp)"); \
+ asm ("movem $ 0xfffe,-(sp)"); }
+
+/* Assuming the registers (including processor status) have been
+ pushed on the stack in order of ascending GDB register number,
+ restore them and return to the address in the saved PC register. */
+
+#define POP_REGISTERS \
+{ asm ("subil $8,28(sp)"); \
+ asm ("movem (sp),$ 0xffff"); \
+ asm ("rte"); }
+
+#else /* HPUX_ASM */
+
+/* Start running with a stack stretching from BEG to END.
+ BEG and END should be symbols meaningful to the assembler.
+ This is used only for kdb. */
+
+#define INIT_STACK(beg, end) \
+{ asm ("global end"); \
+ asm ("mov.l &end,%sp"); \
+ asm ("clr.l %a6"); }
+
+/* Push the frame pointer register on the stack. */
+#define PUSH_FRAME_PTR \
+ asm ("mov.l %fp,-(%sp)");
+
+/* Copy the top-of-stack to the frame pointer register. */
+#define POP_FRAME_PTR \
+ asm ("mov.l (%sp),%fp");
+
+/* After KDB is entered by a fault, push all registers
+ that GDB thinks about (all NUM_REGS of them),
+ so that they appear in order of ascending GDB register number.
+ The fault code will be on the stack beyond the last register. */
+
+#define PUSH_REGISTERS \
+{ asm ("clr.w -(%sp)"); \
+ asm ("pea 10(%sp)"); \
+ asm ("movm.l &0xfffe,-(%sp)"); }
+
+/* Assuming the registers (including processor status) have been
+ pushed on the stack in order of ascending GDB register number,
+ restore them and return to the address in the saved PC register. */
+
+#define POP_REGISTERS \
+{ asm ("subi.l &8,28(%sp)"); \
+ asm ("mov.m (%sp),&0xffff"); \
+ asm ("rte"); }
+
+#endif /* HPUX_ASM */
diff --git a/gdb/config/m68k/xm-isi.h b/gdb/config/m68k/xm-isi.h
new file mode 100644
index 00000000000..4e75333fcbb
--- /dev/null
+++ b/gdb/config/m68k/xm-isi.h
@@ -0,0 +1,92 @@
+/* Definitions to make GDB run on an ISI Optimum V (3.05) under 4.3bsd.
+ Copyright 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define HOST_BYTE_ORDER BIG_ENDIAN
+
+/* This has not been tested on ISI's running BSD 4.2, but it will probably
+ work. */
+
+/* This is the amount to subtract from u.u_ar0
+ to get the offset in the core file of the register values. */
+
+/*#define KERNEL_U_ADDR 0x10800000*/
+#define KERNEL_U_ADDR 0
+
+/* expects blockend to be u.u_ar0 */
+extern int rloc[]; /* Defined in isi-dep.c */
+#define REGISTER_U_ADDR(addr, blockend, regno) \
+{ blockend &= UPAGES*NBPG - 1; \
+ if (regno < 18) addr = (int)blockend + rloc[regno]*4; \
+ else if (regno < 26) addr = (int) &((struct user *)0)->u_68881_regs \
+ + (regno - 18) * 12; \
+ else if (regno < 29) addr = (int) &((struct user *)0)->u_68881_regs \
+ + 8 * 12 + (regno - 26) * 4; \
+}
+
+/* Interface definitions for kernel debugger KDB. */
+
+/* Map machine fault codes into signal numbers.
+ First subtract 0, divide by 4, then index in a table.
+ Faults for which the entry in this table is 0
+ are not handled by KDB; the program's own trap handler
+ gets to handle then. */
+
+#define FAULT_CODE_ORIGIN 0
+#define FAULT_CODE_UNITS 4
+#define FAULT_TABLE \
+{ 0, 0, 0, 0, SIGTRAP, 0, 0, 0, \
+ 0, SIGTRAP, 0, 0, 0, 0, 0, SIGKILL, \
+ 0, 0, 0, 0, 0, 0, 0, 0, \
+ SIGILL }
+
+/* Start running with a stack stretching from BEG to END.
+ BEG and END should be symbols meaningful to the assembler.
+ This is used only for kdb. */
+
+#define INIT_STACK(beg, end) \
+{ asm (".globl end"); \
+ asm ("movl $ end, sp"); \
+ asm ("clrl fp"); }
+
+/* Push the frame pointer register on the stack. */
+#define PUSH_FRAME_PTR \
+ asm ("movel fp, -(sp)");
+
+/* Copy the top-of-stack to the frame pointer register. */
+#define POP_FRAME_PTR \
+ asm ("movl (sp), fp");
+
+/* After KDB is entered by a fault, push all registers
+ that GDB thinks about (all NUM_REGS of them),
+ so that they appear in order of ascending GDB register number.
+ The fault code will be on the stack beyond the last register. */
+
+#define PUSH_REGISTERS \
+{ asm ("clrw -(sp)"); \
+ asm ("pea 10(sp)"); \
+ asm ("movem $ 0xfffe,-(sp)"); }
+
+/* Assuming the registers (including processor status) have been
+ pushed on the stack in order of ascending GDB register number,
+ restore them and return to the address in the saved PC register. */
+
+#define POP_REGISTERS \
+{ asm ("subil $8,28(sp)"); \
+ asm ("movem (sp),$ 0xffff"); \
+ asm ("rte"); }
diff --git a/gdb/config/m68k/xm-linux.h b/gdb/config/m68k/xm-linux.h
new file mode 100644
index 00000000000..7266cffdfa2
--- /dev/null
+++ b/gdb/config/m68k/xm-linux.h
@@ -0,0 +1,40 @@
+/* Native support for linux, for GDB, the GNU debugger.
+ Copyright (C) 1996,1998 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef XM_LINUX_H
+#define XM_LINUX_H
+
+/* Pick up most of what we need from the generic m68k host include file. */
+
+#include "m68k/xm-m68k.h"
+
+/* 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 0x0
+
+#define HAVE_TERMIOS
+#define NEED_POSIX_SETPGID
+
+/* Linux has sigsetjmp and siglongjmp */
+#define HAVE_SIGSETJMP
+
+/* Need R_OK etc, but USG isn't defined. */
+#include <unistd.h>
+
+#endif /* #ifndef XM_LINUX_H */
diff --git a/gdb/config/m68k/xm-m68k.h b/gdb/config/m68k/xm-m68k.h
new file mode 100644
index 00000000000..547940877f1
--- /dev/null
+++ b/gdb/config/m68k/xm-m68k.h
@@ -0,0 +1,22 @@
+/* Macro definitions for running gdb on host machines with m68k cpu's.
+ Copyright (C) 1991, Free Software Foundation, Inc.
+ Written by Fred Fish at Cygnus Support (fnf@cygint)
+
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define HOST_BYTE_ORDER BIG_ENDIAN
+
diff --git a/gdb/config/m68k/xm-m68klynx.h b/gdb/config/m68k/xm-m68klynx.h
new file mode 100644
index 00000000000..ded6844c907
--- /dev/null
+++ b/gdb/config/m68k/xm-m68klynx.h
@@ -0,0 +1,24 @@
+/* Host-dependent definitions for Motorola 680x0 running LynxOS, for GDB.
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define HOST_BYTE_ORDER BIG_ENDIAN
+
+/* Get generic LynxOS host definitions. */
+
+#include "xm-lynx.h"
diff --git a/gdb/config/m68k/xm-m68kv4.h b/gdb/config/m68k/xm-m68kv4.h
new file mode 100644
index 00000000000..2149c8ffd65
--- /dev/null
+++ b/gdb/config/m68k/xm-m68kv4.h
@@ -0,0 +1,28 @@
+/* Host definitions for GDB on a Motorola 680x0 running SVR4.
+ (Commodore Amiga with amix or Atari TT with ASV)
+ Copyright 1991, 1992 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Pick up most of what we need from the generic m68k host include file. */
+
+#include "m68k/xm-m68k.h"
+
+/* Pick up more stuff from the generic SVR4 host include file. */
+
+#include "xm-sysv4.h"
diff --git a/gdb/config/m68k/xm-mpw.h b/gdb/config/m68k/xm-mpw.h
new file mode 100644
index 00000000000..f0585b38a3a
--- /dev/null
+++ b/gdb/config/m68k/xm-mpw.h
@@ -0,0 +1,24 @@
+/* Macro definitions for running GDB on Apple 68k-based Macintoshes.
+ Copyright (C) 1994, 1995 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define HOST_BYTE_ORDER BIG_ENDIAN
+
+/* Use angle brackets so that the common xm-mpw.h is found. */
+
+#include <xm-mpw.h>
diff --git a/gdb/config/m68k/xm-nbsd.h b/gdb/config/m68k/xm-nbsd.h
new file mode 100644
index 00000000000..aa28e19bdf7
--- /dev/null
+++ b/gdb/config/m68k/xm-nbsd.h
@@ -0,0 +1,21 @@
+/* Parameters for execution on a Motorola m68k running NetBSD, for GDB.
+ Copyright 1996 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Get generic NetBSD host definitions. */
+#include "xm-nbsd.h"
diff --git a/gdb/config/m68k/xm-news.h b/gdb/config/m68k/xm-news.h
new file mode 100644
index 00000000000..081337bcf33
--- /dev/null
+++ b/gdb/config/m68k/xm-news.h
@@ -0,0 +1,137 @@
+/* Parameters for execution on a Sony/NEWS, for GDB, the GNU debugger.
+ Copyright 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define HOST_BYTE_ORDER BIG_ENDIAN
+
+#include <sys/param.h> /* For INT_MIN */
+
+#define HAVE_WAIT_STRUCT
+
+/* We can't use "isatty" or "fileno" on this machine. This isn't good,
+ but it will have to do. */
+#define ISATTY(FP) ((FP) == stdin || (FP) == stdout)
+
+/* THis is the amount to subtract from u.u_ar0
+ to get the offset in the core file of the register values. */
+
+#define KERNEL_U_ADDR UADDR
+
+/* The offsets in this macro are from /usr/include/machine/reg.h */
+
+#define REGISTER_U_ADDR(addr, blockend, regno) \
+{ static char offsets[] = { \
+ /*d0-d7:*/1,2,3,4,5,6,7,8, \
+ /*a0-a6:*/9,10,11,12,13,14,15, /*sp:*/-4, /*ps:*/0, /*pc:*/-1, \
+ /*fp0-fp7:*/19,22,25,28,31,34,37,40, /*fpc:*/16,17,18 }; \
+ addr = blockend + 4 * offsets[regno]; \
+}
+
+/* NewsOS 3.3 does not define errno in <errno.h>. */
+extern int errno;
+
+/* Interface definitions for kernel debugger KDB. */
+
+/* Use GNU assembler instead of standard assembler */
+#define USE_GAS
+
+/* Motorola assembly format */
+#ifndef USE_GAS
+#define MOTOROLA
+#endif
+
+/* Map machine fault codes into signal numbers.
+ First subtract 0, divide by 4, then index in a table.
+ Faults for which the entry in this table is 0
+ are not handled by KDB; the program's own trap handler
+ gets to handle then. */
+
+#define FAULT_CODE_ORIGIN 0
+#define FAULT_CODE_UNITS 4
+#define FAULT_TABLE \
+{ 0, 0, 0, 0, SIGTRAP, 0, 0, 0, \
+ 0, SIGTRAP, 0, 0, 0, 0, 0, SIGKILL, \
+ 0, 0, 0, 0, 0, 0, 0, 0, \
+ SIGILL }
+
+/* Start running with a stack stretching from BEG to END.
+ BEG and END should be symbols meaningful to the assembler.
+ This is used only for kdb. */
+
+#ifdef MOTOROLA
+#define INIT_STACK(beg, end) \
+{ asm (".globl end"); \
+ asm ("move.l $ end, sp"); \
+ asm ("clr.l fp"); }
+#else
+#define INIT_STACK(beg, end) \
+{ asm (".globl end"); \
+ asm ("movel $ end, sp"); \
+ asm ("clrl fp"); }
+#endif
+
+/* Push the frame pointer register on the stack. */
+#ifdef MOTOROLA
+#define PUSH_FRAME_PTR \
+ asm ("move.l fp, -(sp)");
+#else
+#define PUSH_FRAME_PTR \
+ asm ("movel fp, -(sp)");
+#endif
+
+/* Copy the top-of-stack to the frame pointer register. */
+#ifdef MOTOROLA
+#define POP_FRAME_PTR \
+ asm ("move.l (sp), fp");
+#else
+#define POP_FRAME_PTR \
+ asm ("movl (sp), fp");
+#endif
+
+/* After KDB is entered by a fault, push all registers
+ that GDB thinks about (all NUM_REGS of them),
+ so that they appear in order of ascending GDB register number.
+ The fault code will be on the stack beyond the last register. */
+
+#ifdef MOTOROLA
+#define PUSH_REGISTERS \
+{ asm ("clr.w -(sp)"); \
+ asm ("pea (10,sp)"); \
+ asm ("movem $ 0xfffe,-(sp)"); }
+#else
+#define PUSH_REGISTERS \
+{ asm ("clrw -(sp)"); \
+ asm ("pea 10(sp)"); \
+ asm ("movem $ 0xfffe,-(sp)"); }
+#endif
+
+/* Assuming the registers (including processor status) have been
+ pushed on the stack in order of ascending GDB register number,
+ restore them and return to the address in the saved PC register. */
+
+#ifdef MOTOROLA
+#define POP_REGISTERS \
+{ asm ("subi.l $8,28(sp)"); \
+ asm ("movem (sp),$ 0xffff"); \
+ asm ("rte"); }
+#else
+#define POP_REGISTERS \
+{ asm ("subil $8,28(sp)"); \
+ asm ("movem (sp),$ 0xffff"); \
+ asm ("rte"); }
+#endif
diff --git a/gdb/config/m68k/xm-news1000.h b/gdb/config/m68k/xm-news1000.h
new file mode 100644
index 00000000000..b70234c058a
--- /dev/null
+++ b/gdb/config/m68k/xm-news1000.h
@@ -0,0 +1,26 @@
+/* Parameters for a Sony/NEWS series 1000 with News-OS version 3,
+ for GDB, the GNU debugger.
+ Copyright (C) 1990 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* This is required by Sony include files like <sys/user.h> so we
+ get the right offset into the u area. Relying on the compiler
+ to define this only works for cc, not gcc. */
+#undef mc68030
+#define mc68030
+#include "m68k/xm-news.h"
diff --git a/gdb/config/m68k/xm-sun2.h b/gdb/config/m68k/xm-sun2.h
new file mode 100644
index 00000000000..457451c4d74
--- /dev/null
+++ b/gdb/config/m68k/xm-sun2.h
@@ -0,0 +1,78 @@
+/* Parameters for execution on a Sun, for GDB, the GNU debugger.
+ Copyright (C) 1986, 1987, 1989, 1996 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define HOST_BYTE_ORDER BIG_ENDIAN
+
+/* This is the amount to subtract from u.u_ar0
+ to get the offset in the core file of the register values. */
+
+#define KERNEL_U_ADDR 0x2800
+
+
+/* Interface definitions for kernel debugger KDB. */
+
+/* Map machine fault codes into signal numbers.
+ First subtract 0, divide by 4, then index in a table.
+ Faults for which the entry in this table is 0
+ are not handled by KDB; the program's own trap handler
+ gets to handle then. */
+
+#define FAULT_CODE_ORIGIN 0
+#define FAULT_CODE_UNITS 4
+#define FAULT_TABLE \
+{ 0, 0, 0, 0, SIGTRAP, 0, 0, 0, \
+ 0, SIGTRAP, 0, 0, 0, 0, 0, SIGKILL, \
+ 0, 0, 0, 0, 0, 0, 0, 0, \
+ SIGILL }
+
+/* Start running with a stack stretching from BEG to END.
+ BEG and END should be symbols meaningful to the assembler.
+ This is used only for kdb. */
+
+#define INIT_STACK(beg, end) \
+{ asm (".globl end"); \
+ asm ("movel $ end, sp"); \
+ asm ("clrl fp"); }
+
+/* Push the frame pointer register on the stack. */
+#define PUSH_FRAME_PTR \
+ asm ("movel fp, -(sp)");
+
+/* Copy the top-of-stack to the frame pointer register. */
+#define POP_FRAME_PTR \
+ asm ("movl (sp), fp");
+
+/* After KDB is entered by a fault, push all registers
+ that GDB thinks about (all NUM_REGS of them),
+ so that they appear in order of ascending GDB register number.
+ The fault code will be on the stack beyond the last register. */
+
+#define PUSH_REGISTERS \
+{ asm ("clrw -(sp)"); \
+ asm ("pea 10(sp)"); \
+ asm ("movem $ 0xfffe,-(sp)"); }
+
+/* Assuming the registers (including processor status) have been
+ pushed on the stack in order of ascending GDB register number,
+ restore them and return to the address in the saved PC register. */
+
+#define POP_REGISTERS \
+{ asm ("subil $8,28(sp)"); \
+ asm ("movem (sp),$ 0xffff"); \
+ asm ("rte"); }
diff --git a/gdb/config/m68k/xm-sun3.h b/gdb/config/m68k/xm-sun3.h
new file mode 100644
index 00000000000..3de7446d184
--- /dev/null
+++ b/gdb/config/m68k/xm-sun3.h
@@ -0,0 +1,73 @@
+/* Parameters for execution on a Sun, for GDB, the GNU debugger.
+ Copyright (C) 1986, 1987, 1989, 1996 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define HOST_BYTE_ORDER BIG_ENDIAN
+
+
+/* Interface definitions for kernel debugger KDB. */
+
+/* Map machine fault codes into signal numbers.
+ First subtract 0, divide by 4, then index in a table.
+ Faults for which the entry in this table is 0
+ are not handled by KDB; the program's own trap handler
+ gets to handle then. */
+
+#define FAULT_CODE_ORIGIN 0
+#define FAULT_CODE_UNITS 4
+#define FAULT_TABLE \
+{ 0, 0, 0, 0, SIGTRAP, 0, 0, 0, \
+ 0, SIGTRAP, 0, 0, 0, 0, 0, SIGKILL, \
+ 0, 0, 0, 0, 0, 0, 0, 0, \
+ SIGILL }
+
+/* Start running with a stack stretching from BEG to END.
+ BEG and END should be symbols meaningful to the assembler.
+ This is used only for kdb. */
+
+#define INIT_STACK(beg, end) \
+{ asm (".globl end"); \
+ asm ("movel #end, sp"); \
+ asm ("movel #0,a6"); }
+
+/* Push the frame pointer register on the stack. */
+#define PUSH_FRAME_PTR \
+ asm ("movel a6,sp@-");
+
+/* Copy the top-of-stack to the frame pointer register. */
+#define POP_FRAME_PTR \
+ asm ("movl sp@,a6");
+
+/* After KDB is entered by a fault, push all registers
+ that GDB thinks about (all NUM_REGS of them),
+ so that they appear in order of ascending GDB register number.
+ The fault code will be on the stack beyond the last register. */
+
+#define PUSH_REGISTERS \
+{ asm ("clrw -(sp)"); \
+ asm ("pea sp@(10)"); \
+ asm ("movem #0xfffe,sp@-"); }
+
+/* Assuming the registers (including processor status) have been
+ pushed on the stack in order of ascending GDB register number,
+ restore them and return to the address in the saved PC register. */
+
+#define POP_REGISTERS \
+{ asm ("subil #8,sp@(28)"); \
+ asm ("movem sp@,#0xffff"); \
+ asm ("rte"); }
diff --git a/gdb/config/m68k/xm-sun3os4.h b/gdb/config/m68k/xm-sun3os4.h
new file mode 100644
index 00000000000..faf3b7de7ed
--- /dev/null
+++ b/gdb/config/m68k/xm-sun3os4.h
@@ -0,0 +1,21 @@
+/* Macro definitions for a sun 3 running os 4.
+ Copyright (C) 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "m68k/xm-sun3.h"
+#define FPU
diff --git a/gdb/config/m88k/cxux.mh b/gdb/config/m88k/cxux.mh
new file mode 100644
index 00000000000..cb02225cbd2
--- /dev/null
+++ b/gdb/config/m88k/cxux.mh
@@ -0,0 +1,7 @@
+# Host: Motorola 88k running CX/UX
+
+XM_FILE= xm-cxux.h
+XDEPFILES=
+
+NAT_FILE= nm-cxux.h
+NATDEPFILES= infptrace.o inftarg.o fork-child.o cxux-nat.o corelow.o core-aout.o
diff --git a/gdb/config/m88k/cxux.mt b/gdb/config/m88k/cxux.mt
new file mode 100644
index 00000000000..295de84c903
--- /dev/null
+++ b/gdb/config/m88k/cxux.mt
@@ -0,0 +1,3 @@
+# Target: Motorola 88k running Harris CX/UX
+TDEPFILES= m88k-tdep.o remote-bug.o
+TM_FILE= tm-cxux.h
diff --git a/gdb/config/m88k/delta88.mh b/gdb/config/m88k/delta88.mh
new file mode 100644
index 00000000000..824967a61cd
--- /dev/null
+++ b/gdb/config/m88k/delta88.mh
@@ -0,0 +1,7 @@
+# Host: Motorola 88k running SVR3
+
+XM_FILE= xm-delta88.h
+XDEPFILES=
+
+NAT_FILE= nm-m88k.h
+NATDEPFILES= infptrace.o inftarg.o fork-child.o m88k-nat.o corelow.o core-aout.o
diff --git a/gdb/config/m88k/delta88.mt b/gdb/config/m88k/delta88.mt
new file mode 100644
index 00000000000..c8e669b687c
--- /dev/null
+++ b/gdb/config/m88k/delta88.mt
@@ -0,0 +1,3 @@
+# Target: Motorola 88k running SVR3
+TDEPFILES= m88k-tdep.o
+TM_FILE= tm-delta88.h
diff --git a/gdb/config/m88k/delta88v4.mh b/gdb/config/m88k/delta88v4.mh
new file mode 100644
index 00000000000..82be8833236
--- /dev/null
+++ b/gdb/config/m88k/delta88v4.mh
@@ -0,0 +1,7 @@
+# Host: Motorola 88k running SVR4
+
+XM_FILE= xm-delta88v4.h
+XDEPFILES=
+
+NAT_FILE= nm-delta88v4.h
+NATDEPFILES= fork-child.o m88k-nat.o corelow.o core-regset.o procfs.o solib.o
diff --git a/gdb/config/m88k/delta88v4.mt b/gdb/config/m88k/delta88v4.mt
new file mode 100644
index 00000000000..7797d4b6295
--- /dev/null
+++ b/gdb/config/m88k/delta88v4.mt
@@ -0,0 +1,3 @@
+# Target: Motorola 88k running SVR4
+TDEPFILES= m88k-tdep.o
+TM_FILE= tm-delta88v4.h
diff --git a/gdb/config/m88k/m88k.mh b/gdb/config/m88k/m88k.mh
new file mode 100644
index 00000000000..6933265e3e7
--- /dev/null
+++ b/gdb/config/m88k/m88k.mh
@@ -0,0 +1,5 @@
+# Host: Motorola 88000 running DGUX
+XDEPFILES=
+XM_FILE= xm-dgux.h
+NAT_FILE= nm-m88k.h
+NATDEPFILES= infptrace.o inftarg.o fork-child.o m88k-nat.o
diff --git a/gdb/config/m88k/m88k.mt b/gdb/config/m88k/m88k.mt
new file mode 100644
index 00000000000..ca3fab41165
--- /dev/null
+++ b/gdb/config/m88k/m88k.mt
@@ -0,0 +1,3 @@
+# Target: Motorola 88k Binary Compatibility Standard
+TDEPFILES= m88k-tdep.o remote-bug.o
+TM_FILE= tm-m88k.h
diff --git a/gdb/config/m88k/nm-cxux.h b/gdb/config/m88k/nm-cxux.h
new file mode 100644
index 00000000000..fec953650c8
--- /dev/null
+++ b/gdb/config/m88k/nm-cxux.h
@@ -0,0 +1,32 @@
+/* Native definitions for Motorola 88K running Harris CX/UX
+ Copyright 1993, 1994 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Override the standard fetch/store definitions. */
+
+#define FETCH_INFERIOR_REGISTERS
+
+#define REGISTER_U_ADDR(addr, blockend, regno) \
+ (addr) = m88k_register_u_addr ((blockend),(regno));
+
+#define ATTACH_DETACH
+
+#define PTRACE_ATTACH 128
+#define PTRACE_DETACH 129
+
+
diff --git a/gdb/config/m88k/nm-delta88v4.h b/gdb/config/m88k/nm-delta88v4.h
new file mode 100644
index 00000000000..9c1a30eb2bc
--- /dev/null
+++ b/gdb/config/m88k/nm-delta88v4.h
@@ -0,0 +1,21 @@
+/* Native machine description for Motorola Delta 88 box, for GDB.
+ Copyright 1986, 1987, 1988, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "m88k/nm-m88k.h"
+#include "nm-sysv4.h"
diff --git a/gdb/config/m88k/nm-m88k.h b/gdb/config/m88k/nm-m88k.h
new file mode 100644
index 00000000000..95eca0a00f9
--- /dev/null
+++ b/gdb/config/m88k/nm-m88k.h
@@ -0,0 +1,24 @@
+/* Native support macros for m88k, for 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define FETCH_INFERIOR_REGISTERS
+
+#define REGISTER_U_ADDR(addr, blockend, regno) \
+ (addr) = m88k_register_u_addr ((blockend),(regno));
diff --git a/gdb/config/m88k/tm-cxux.h b/gdb/config/m88k/tm-cxux.h
new file mode 100644
index 00000000000..e59c6dabfb9
--- /dev/null
+++ b/gdb/config/m88k/tm-cxux.h
@@ -0,0 +1,59 @@
+/* Target definitions for m88k running Harris CX/UX.
+ Copyright 1993, 1994 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define HARRIS_TARGET 1
+
+#define CXUX_TARGET 1
+
+/* Type of X registers, as supplied by the OS */
+
+typedef struct {
+ long w1, w2, w3, w4;
+} X_REGISTER_RAW_TYPE;
+
+#define X_REGISTER_VIRTUAL_TYPE double
+
+#include "m88k/tm-m88k.h"
+
+#define ADD_SHARED_SYMBOL_FILES(args,have_tty) add_shared_symbol_files ()
+
+#define CONVERT_REGISTER_ADDRESS
+
+/* Always allocate space for both, but recognize that the m88100 has no
+ FP_REGS. */
+
+#undef ARCH_NUM_REGS
+#define ARCH_NUM_REGS (target_is_m88110 ? (GP_REGS + FP_REGS) : (GP_REGS))
+
+/* Don't need this grotesquerie. */
+
+#undef SHIFT_INST_REGS
+
+/* Extended registers are treated as 16 bytes by Harris' OS's.
+ We treat them as 16 bytes here for consistency's sake. */
+
+#undef REGISTER_RAW_SIZE
+#define REGISTER_RAW_SIZE(N) ((N) < XFP_REGNUM ? 4 : 16)
+
+#undef REGISTER_BYTE
+#define REGISTER_BYTE(N) \
+ ((N) >= XFP_REGNUM \
+ ? (((GP_REGS) * REGISTER_RAW_SIZE(0)) + \
+ (((N) - XFP_REGNUM) * REGISTER_RAW_SIZE(XFP_REGNUM))) \
+ : ((N) * REGISTER_RAW_SIZE(0)))
diff --git a/gdb/config/m88k/tm-delta88.h b/gdb/config/m88k/tm-delta88.h
new file mode 100644
index 00000000000..c0a9c4a4f73
--- /dev/null
+++ b/gdb/config/m88k/tm-delta88.h
@@ -0,0 +1,26 @@
+/* Target machine description for Motorola Delta 88 box, for GDB.
+ Copyright 1986, 1987, 1988, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "m88k/tm-m88k.h"
+
+#define DELTA88
+
+#define IN_SIGTRAMP(pc, name) ((name) && STREQ ("_sigcode", (name)))
+#define SIGTRAMP_FRAME_FIXUP(frame) (frame) += 0x20
+#define SIGTRAMP_SP_FIXUP(sp) (sp) = read_memory_integer((sp), 4)
diff --git a/gdb/config/m88k/tm-delta88v4.h b/gdb/config/m88k/tm-delta88v4.h
new file mode 100644
index 00000000000..112a4a6d65b
--- /dev/null
+++ b/gdb/config/m88k/tm-delta88v4.h
@@ -0,0 +1,30 @@
+/* Target machine description for Motorola Delta 88 box, for GDB.
+ Copyright 1986, 1987, 1988, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define DELTA88
+
+#include "m88k/tm-m88k.h"
+#include "tm-sysv4.h"
+
+/* If we don't define this, backtraces go on forever. */
+#define FRAME_CHAIN_VALID(fp,fi) alternate_frame_chain_valid (fp, fi)
+
+#define IN_SIGTRAMP(pc, name) ((name) && (STREQ ("signalhandler", (name)) \
+ || STREQ("sigacthandler", (name))))
+#define SIGTRAMP_SP_FIXUP(sp) (sp) = read_memory_integer((sp)+0xcd8, 4)
diff --git a/gdb/config/m88k/tm-m88k.h b/gdb/config/m88k/tm-m88k.h
new file mode 100644
index 00000000000..390cdef96ea
--- /dev/null
+++ b/gdb/config/m88k/tm-m88k.h
@@ -0,0 +1,620 @@
+/* Target machine description for generic Motorola 88000, for GDB.
+ Copyright 1986, 1987, 1988, 1989, 1990, 1991, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* g++ support is not yet included. */
+
+/* Define the bit, byte, and word ordering of the machine. */
+#define TARGET_BYTE_ORDER BIG_ENDIAN
+
+/* We cache information about saved registers in the frame structure,
+ to save us from having to re-scan function prologues every time
+ a register in a non-current frame is accessed. */
+
+#define EXTRA_FRAME_INFO \
+ struct frame_saved_regs *fsr; \
+ CORE_ADDR locals_pointer; \
+ CORE_ADDR args_pointer;
+
+/* Zero the frame_saved_regs pointer when the frame is initialized,
+ so that FRAME_FIND_SAVED_REGS () will know to allocate and
+ initialize a frame_saved_regs struct the first time it is called.
+ Set the arg_pointer to -1, which is not valid; 0 and other values
+ indicate real, cached values. */
+
+#define INIT_EXTRA_FRAME_INFO(fromleaf, fi) \
+ init_extra_frame_info (fromleaf, fi)
+extern void init_extra_frame_info ();
+
+#define IEEE_FLOAT
+
+/* 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) = skip_prologue (frompc); }
+extern CORE_ADDR skip_prologue ();
+
+/* The m88k kernel aligns all instructions on 4-byte boundaries. The
+ kernel also uses the least significant two bits for its own hocus
+ pocus. When gdb receives an address from the kernel, it needs to
+ preserve those right-most two bits, but gdb also needs to be careful
+ to realize that those two bits are not really a part of the address
+ of an instruction. Shrug. */
+
+extern CORE_ADDR m88k_addr_bits_remove PARAMS ((CORE_ADDR));
+#define ADDR_BITS_REMOVE(addr) m88k_addr_bits_remove (addr)
+
+/* 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) \
+ (ADDR_BITS_REMOVE (read_register (SRP_REGNUM)))
+
+/* Stack grows downward. */
+
+#define INNER_THAN(lhs,rhs) ((lhs) < (rhs))
+
+/* Sequence of bytes for breakpoint instruction. */
+
+/* instruction 0xF000D1FF is 'tb0 0,r0,511'
+ If Bit bit 0 of r0 is clear (always true),
+ initiate exception processing (trap).
+ */
+#define BREAKPOINT {0xF0, 0x00, 0xD1, 0xFF}
+
+/* Amount PC must be decremented by after a breakpoint.
+ This is often the number of bytes in BREAKPOINT
+ but not always. */
+
+#define DECR_PC_AFTER_BREAK 0
+
+/* Say how long (ordinary) registers are. This is a piece of bogosity
+ used in push_word and a few other places; REGISTER_RAW_SIZE is the
+ real way to know how big a register is. */
+
+#define REGISTER_SIZE 4
+
+/* Number of machine registers */
+
+#define GP_REGS (38)
+#define FP_REGS (32)
+#define NUM_REGS (GP_REGS + FP_REGS)
+
+/* Initializer for an array of names of registers.
+ There should be NUM_REGS strings in this initializer. */
+
+#define REGISTER_NAMES {\
+ "r0",\
+ "r1",\
+ "r2",\
+ "r3",\
+ "r4",\
+ "r5",\
+ "r6",\
+ "r7",\
+ "r8",\
+ "r9",\
+ "r10",\
+ "r11",\
+ "r12",\
+ "r13",\
+ "r14",\
+ "r15",\
+ "r16",\
+ "r17",\
+ "r18",\
+ "r19",\
+ "r20",\
+ "r21",\
+ "r22",\
+ "r23",\
+ "r24",\
+ "r25",\
+ "r26",\
+ "r27",\
+ "r28",\
+ "r29",\
+ "r30",\
+ "r31",\
+ "psr",\
+ "fpsr",\
+ "fpcr",\
+ "sxip",\
+ "snip",\
+ "sfip",\
+ "x0",\
+ "x1",\
+ "x2",\
+ "x3",\
+ "x4",\
+ "x5",\
+ "x6",\
+ "x7",\
+ "x8",\
+ "x9",\
+ "x10",\
+ "x11",\
+ "x12",\
+ "x13",\
+ "x14",\
+ "x15",\
+ "x16",\
+ "x17",\
+ "x18",\
+ "x19",\
+ "x20",\
+ "x21",\
+ "x22",\
+ "x23",\
+ "x24",\
+ "x25",\
+ "x26",\
+ "x27",\
+ "x28",\
+ "x29",\
+ "x30",\
+ "x31",\
+ "vbr",\
+ "dmt0",\
+ "dmd0",\
+ "dma0",\
+ "dmt1",\
+ "dmd1",\
+ "dma1",\
+ "dmt2",\
+ "dmd2",\
+ "dma2",\
+ "sr0",\
+ "sr1",\
+ "sr2",\
+ "sr3",\
+ "fpecr",\
+ "fphs1",\
+ "fpls1",\
+ "fphs2",\
+ "fpls2",\
+ "fppt",\
+ "fprh",\
+ "fprl",\
+ "fpit",\
+ "fpsr",\
+ "fpcr",\
+ }
+
+
+/* Register numbers of various important registers.
+ Note that some of these values are "real" register numbers,
+ and correspond to the general registers of the machine,
+ and some are "phony" register numbers which are too large
+ to be actual register numbers as far as the user is concerned
+ but do serve to get the desired values when passed to read_register. */
+
+#define R0_REGNUM 0 /* Contains the constant zero */
+#define SRP_REGNUM 1 /* Contains subroutine return pointer */
+#define RV_REGNUM 2 /* Contains simple return values */
+#define SRA_REGNUM 12 /* Contains address of struct return values */
+#define SP_REGNUM 31 /* Contains address of top of stack */
+
+/* Instruction pointer notes...
+
+ On the m88100:
+
+ * cr04 = sxip. On exception, contains the excepting pc (probably).
+ On rte, is ignored.
+
+ * cr05 = snip. On exception, contains the NPC (next pc). On rte,
+ pc is loaded from here.
+
+ * cr06 = sfip. On exception, contains the NNPC (next next pc). On
+ rte, the NPC is loaded from here.
+
+ * lower two bits of each are flag bits. Bit 1 is V means address
+ is valid. If address is not valid, bit 0 is ignored. Otherwise,
+ bit 0 is E and asks for an exception to be taken if this
+ instruction is executed.
+
+ On the m88110:
+
+ * cr04 = exip. On exception, contains the address of the excepting
+ pc (always). On rte, pc is loaded from here. Bit 0, aka the D
+ bit, is a flag saying that the offending instruction was in a
+ branch delay slot. If set, then cr05 contains the NPC.
+
+ * cr05 = enip. On exception, if the instruction pointed to by cr04
+ was in a delay slot as indicated by the bit 0 of cr04, aka the D
+ bit, the cr05 contains the NPC. Otherwise ignored.
+
+ * cr06 is invalid */
+
+/* Note that the Harris Unix kernels emulate the m88100's behavior on
+ the m88110. */
+
+#define SXIP_REGNUM 35 /* On m88100, Contains Shadow Execute
+ Instruction Pointer. */
+#define SNIP_REGNUM 36 /* On m88100, Contains Shadow Next
+ Instruction Pointer. */
+#define SFIP_REGNUM 37 /* On m88100, Contains Shadow Fetched
+ Intruction pointer. */
+
+#define EXIP_REGNUM 35 /* On m88110, Contains Exception
+ Executing Instruction Pointer. */
+#define ENIP_REGNUM 36 /* On m88110, Contains the Exception
+ Next Instruction Pointer. */
+
+#define PC_REGNUM SXIP_REGNUM /* Program Counter */
+#define NPC_REGNUM SNIP_REGNUM /* Next Program Counter */
+#define NNPC_REGNUM SFIP_REGNUM /* Next Next Program Counter */
+
+#define PSR_REGNUM 32 /* Processor Status Register */
+#define FPSR_REGNUM 33 /* Floating Point Status Register */
+#define FPCR_REGNUM 34 /* Floating Point Control Register */
+#define XFP_REGNUM 38 /* First Extended Float Register */
+#define X0_REGNUM XFP_REGNUM /* Which also contains the constant zero */
+
+/* This is rather a confusing lie. Our m88k port using a stack pointer value
+ for the frame address. Hence, the frame address and the frame pointer are
+ only indirectly related. The value of this macro is the register number
+ fetched by the machine "independent" portions of gdb when they want to know
+ about a frame address. Thus, we lie here and claim that FP_REGNUM is
+ SP_REGNUM. */
+#define FP_REGNUM SP_REGNUM /* Reg fetched to locate frame when pgm stops */
+#define ACTUAL_FP_REGNUM 30
+
+/* PSR status bit definitions. */
+
+#define PSR_MODE 0x80000000
+#define PSR_BYTE_ORDER 0x40000000
+#define PSR_SERIAL_MODE 0x20000000
+#define PSR_CARRY 0x10000000
+#define PSR_SFU_DISABLE 0x000003f0
+#define PSR_SFU1_DISABLE 0x00000008
+#define PSR_MXM 0x00000004
+#define PSR_IND 0x00000002
+#define PSR_SFRZ 0x00000001
+
+
+
+/* The following two comments come from the days prior to the m88110
+ port. The m88110 handles the instruction pointers differently. I
+ do not know what any m88110 kernels do as the m88110 port I'm
+ working with is for an embedded system. rich@cygnus.com
+ 13-sept-93. */
+
+/* BCS requires that the SXIP_REGNUM (or PC_REGNUM) contain the
+ address of the next instr to be executed when a breakpoint occurs.
+ Because the kernel gets the next instr (SNIP_REGNUM), the instr in
+ SNIP needs to be put back into SFIP, and the instr in SXIP should
+ be shifted to SNIP */
+
+/* Are you sitting down? It turns out that the 88K BCS (binary
+ compatibility standard) folks originally felt that the debugger
+ should be responsible for backing up the IPs, not the kernel (as is
+ usually done). Well, they have reversed their decision, and in
+ future releases our kernel will be handling the backing up of the
+ IPs. So, eventually, we won't need to do the SHIFT_INST_REGS
+ stuff. But, for now, since there are 88K systems out there that do
+ need the debugger to do the IP shifting, and since there will be
+ systems where the kernel does the shifting, the code is a little
+ more complex than perhaps it needs to be (we still go inside
+ SHIFT_INST_REGS, and if the shifting hasn't occurred then gdb goes
+ ahead and shifts). */
+
+extern int target_is_m88110;
+#define SHIFT_INST_REGS() \
+if (!target_is_m88110) \
+{ \
+ CORE_ADDR pc = read_register (PC_REGNUM); \
+ CORE_ADDR npc = read_register (NPC_REGNUM); \
+ if (pc != npc) \
+ { \
+ write_register (NNPC_REGNUM, npc); \
+ write_register (NPC_REGNUM, pc); \
+ } \
+}
+
+ /* Storing the following registers is a no-op. */
+#define CANNOT_STORE_REGISTER(regno) (((regno) == R0_REGNUM) \
+ || ((regno) == X0_REGNUM))
+
+ /* Number of bytes of storage in the actual machine representation
+ for register N. On the m88k, the general purpose registers are 4
+ bytes and the 88110 extended registers are 10 bytes. */
+
+#define REGISTER_RAW_SIZE(N) ((N) < XFP_REGNUM ? 4 : 10)
+
+ /* Total amount of space needed to store our copies of the machine's
+ register state, the array `registers'. */
+
+#define REGISTER_BYTES ((GP_REGS * REGISTER_RAW_SIZE(0)) \
+ + (FP_REGS * REGISTER_RAW_SIZE(XFP_REGNUM)))
+
+ /* Index within `registers' of the first byte of the space for
+ register N. */
+
+#define REGISTER_BYTE(N) (((N) * REGISTER_RAW_SIZE(0)) \
+ + ((N) >= XFP_REGNUM \
+ ? (((N) - XFP_REGNUM) \
+ * REGISTER_RAW_SIZE(XFP_REGNUM)) \
+ : 0))
+
+ /* Number of bytes of storage in the program's representation for
+ register N. On the m88k, all registers are 4 bytes excepting the
+ m88110 extended registers which are 8 byte doubles. */
+
+#define REGISTER_VIRTUAL_SIZE(N) ((N) < XFP_REGNUM ? 4 : 8)
+
+ /* Largest value REGISTER_RAW_SIZE can have. */
+
+#define MAX_REGISTER_RAW_SIZE (REGISTER_RAW_SIZE(XFP_REGNUM))
+
+ /* Largest value REGISTER_VIRTUAL_SIZE can have.
+ Are FPS1, FPS2, FPR "virtual" regisers? */
+
+#define MAX_REGISTER_VIRTUAL_SIZE (REGISTER_RAW_SIZE(XFP_REGNUM))
+
+ /* Nonzero if register N requires conversion
+ from raw format to virtual format. */
+
+#define REGISTER_CONVERTIBLE(N) ((N) >= XFP_REGNUM)
+
+#include "floatformat.h"
+
+/* Convert data from raw format for register REGNUM in buffer FROM
+ to virtual format with type TYPE in buffer TO. */
+
+#define REGISTER_CONVERT_TO_VIRTUAL(REGNUM,TYPE,FROM,TO) \
+{ \
+ double val; \
+ floatformat_to_double (&floatformat_m88110_ext, (FROM), &val); \
+ store_floating ((TO), TYPE_LENGTH (TYPE), val); \
+}
+
+/* Convert data from virtual format with type TYPE in buffer FROM
+ to raw format for register REGNUM in buffer TO. */
+
+#define REGISTER_CONVERT_TO_RAW(TYPE,REGNUM,FROM,TO) \
+{ \
+ double val = extract_floating ((FROM), TYPE_LENGTH (TYPE)); \
+ floatformat_from_double (&floatformat_m88110_ext, &val, (TO)); \
+}
+
+/* Return the GDB type object for the "standard" data type
+ of data in register N. */
+
+#define REGISTER_VIRTUAL_TYPE(N) \
+((N) >= XFP_REGNUM \
+ ? builtin_type_double \
+ : ((N) == PC_REGNUM || (N) == FP_REGNUM || (N) == SP_REGNUM \
+ ? lookup_pointer_type (builtin_type_void) : builtin_type_int))
+
+/* The 88k call/return conventions call for "small" values to be returned
+ into consecutive registers starting from r2. */
+
+#define EXTRACT_RETURN_VALUE(TYPE,REGBUF,VALBUF) \
+ memcpy ((VALBUF), &(((char *)REGBUF)[REGISTER_BYTE(RV_REGNUM)]), TYPE_LENGTH (TYPE))
+
+#define EXTRACT_STRUCT_VALUE_ADDRESS(REGBUF) (*(int *)(REGBUF))
+
+/* Write into appropriate registers a function return value
+ of type TYPE, given in virtual format. */
+
+#define STORE_RETURN_VALUE(TYPE,VALBUF) \
+ write_register_bytes (2*REGISTER_RAW_SIZE(0), (VALBUF), TYPE_LENGTH (TYPE))
+
+/* In COFF, if PCC says a parameter is a short or a char, do not
+ change it to int (it seems the convention is to change it). */
+
+#define BELIEVE_PCC_PROMOTION 1
+
+/* Describe the pointer in each stack frame to the previous stack frame
+ (its caller). */
+
+/* FRAME_CHAIN takes a frame's nominal address
+ and produces the frame's chain-pointer.
+
+ However, if FRAME_CHAIN_VALID returns zero,
+ it means the given frame is the outermost one and has no caller. */
+
+extern CORE_ADDR frame_chain ();
+extern int frame_chain_valid ();
+extern int frameless_function_invocation ();
+
+#define FRAME_CHAIN(thisframe) \
+ frame_chain (thisframe)
+
+#define FRAMELESS_FUNCTION_INVOCATION(frame, fromleaf) \
+ fromleaf = frameless_function_invocation (frame)
+
+/* Define other aspects of the stack frame. */
+
+#define FRAME_SAVED_PC(FRAME) \
+ frame_saved_pc (FRAME)
+extern CORE_ADDR frame_saved_pc ();
+
+#define FRAME_ARGS_ADDRESS(fi) \
+ frame_args_address (fi)
+extern CORE_ADDR frame_args_address ();
+
+#define FRAME_LOCALS_ADDRESS(fi) \
+ frame_locals_address (fi)
+extern CORE_ADDR frame_locals_address ();
+
+/* Return number of args passed to a frame.
+ Can return -1, meaning no way to tell. */
+
+#define FRAME_NUM_ARGS(numargs, fi) ((numargs) = -1)
+
+/* Return number of bytes at start of arglist that are not really args. */
+
+#define FRAME_ARGS_SKIP 0
+
+/* Put here the code to store, into a struct frame_saved_regs,
+ the addresses of the saved registers of frame described by FRAME_INFO.
+ This includes special registers such as pc and fp saved in special
+ ways in the stack frame. sp is even more special:
+ the address we return for it IS the sp for the next frame. */
+
+/* On the 88k, parameter registers get stored into the so called "homing"
+ area. This *always* happens when you compiled with GCC and use -g.
+ Also, (with GCC and -g) the saving of the parameter register values
+ always happens right within the function prologue code, so these register
+ values can generally be relied upon to be already copied into their
+ respective homing slots by the time you will normally try to look at
+ them (we hope).
+
+ Note that homing area stack slots are always at *positive* offsets from
+ the frame pointer. Thus, the homing area stack slots for the parameter
+ registers (passed values) for a given function are actually part of the
+ frame area of the caller. This is unusual, but it should not present
+ any special problems for GDB.
+
+ Note also that on the 88k, we are only interested in finding the
+ registers that might have been saved in memory. This is a subset of
+ the whole set of registers because the standard calling sequence allows
+ the called routine to clobber many registers.
+
+ We could manage to locate values for all of the so called "preserved"
+ registers (some of which may get saved within any particular frame) but
+ that would require decoding all of the tdesc information. That would be
+ nice information for GDB to have, but it is not strictly manditory if we
+ can live without the ability to look at values within (or backup to)
+ previous frames.
+*/
+
+struct frame_saved_regs;
+struct frame_info;
+
+void frame_find_saved_regs PARAMS((struct frame_info *fi,
+ struct frame_saved_regs *fsr));
+
+#define FRAME_FIND_SAVED_REGS(frame_info, frame_saved_regs) \
+ frame_find_saved_regs (frame_info, &frame_saved_regs)
+
+
+#define POP_FRAME pop_frame ()
+extern void pop_frame ();
+
+/* Call function stuff contributed by Kevin Buettner of Motorola. */
+
+#define CALL_DUMMY_LOCATION AFTER_TEXT_END
+
+extern void m88k_push_dummy_frame();
+#define PUSH_DUMMY_FRAME m88k_push_dummy_frame()
+
+#define CALL_DUMMY { \
+0x67ff00c0, /* 0: subu #sp,#sp,0xc0 */ \
+0x243f0004, /* 4: st #r1,#sp,0x4 */ \
+0x245f0008, /* 8: st #r2,#sp,0x8 */ \
+0x247f000c, /* c: st #r3,#sp,0xc */ \
+0x249f0010, /* 10: st #r4,#sp,0x10 */ \
+0x24bf0014, /* 14: st #r5,#sp,0x14 */ \
+0x24df0018, /* 18: st #r6,#sp,0x18 */ \
+0x24ff001c, /* 1c: st #r7,#sp,0x1c */ \
+0x251f0020, /* 20: st #r8,#sp,0x20 */ \
+0x253f0024, /* 24: st #r9,#sp,0x24 */ \
+0x255f0028, /* 28: st #r10,#sp,0x28 */ \
+0x257f002c, /* 2c: st #r11,#sp,0x2c */ \
+0x259f0030, /* 30: st #r12,#sp,0x30 */ \
+0x25bf0034, /* 34: st #r13,#sp,0x34 */ \
+0x25df0038, /* 38: st #r14,#sp,0x38 */ \
+0x25ff003c, /* 3c: st #r15,#sp,0x3c */ \
+0x261f0040, /* 40: st #r16,#sp,0x40 */ \
+0x263f0044, /* 44: st #r17,#sp,0x44 */ \
+0x265f0048, /* 48: st #r18,#sp,0x48 */ \
+0x267f004c, /* 4c: st #r19,#sp,0x4c */ \
+0x269f0050, /* 50: st #r20,#sp,0x50 */ \
+0x26bf0054, /* 54: st #r21,#sp,0x54 */ \
+0x26df0058, /* 58: st #r22,#sp,0x58 */ \
+0x26ff005c, /* 5c: st #r23,#sp,0x5c */ \
+0x271f0060, /* 60: st #r24,#sp,0x60 */ \
+0x273f0064, /* 64: st #r25,#sp,0x64 */ \
+0x275f0068, /* 68: st #r26,#sp,0x68 */ \
+0x277f006c, /* 6c: st #r27,#sp,0x6c */ \
+0x279f0070, /* 70: st #r28,#sp,0x70 */ \
+0x27bf0074, /* 74: st #r29,#sp,0x74 */ \
+0x27df0078, /* 78: st #r30,#sp,0x78 */ \
+0x63df0000, /* 7c: addu #r30,#sp,0x0 */ \
+0x145f0000, /* 80: ld #r2,#sp,0x0 */ \
+0x147f0004, /* 84: ld #r3,#sp,0x4 */ \
+0x149f0008, /* 88: ld #r4,#sp,0x8 */ \
+0x14bf000c, /* 8c: ld #r5,#sp,0xc */ \
+0x14df0010, /* 90: ld #r6,#sp,0x10 */ \
+0x14ff0014, /* 94: ld #r7,#sp,0x14 */ \
+0x151f0018, /* 98: ld #r8,#sp,0x18 */ \
+0x153f001c, /* 9c: ld #r9,#sp,0x1c */ \
+0x5c200000, /* a0: or.u #r1,#r0,0x0 */ \
+0x58210000, /* a4: or #r1,#r1,0x0 */ \
+0xf400c801, /* a8: jsr #r1 */ \
+0xf000d1ff /* ac: tb0 0x0,#r0,0x1ff */ \
+}
+
+#define CALL_DUMMY_START_OFFSET 0x80
+#define CALL_DUMMY_LENGTH 0xb0
+
+/* FIXME: byteswapping. */
+#define FIX_CALL_DUMMY(dummy, pc, fun, nargs, args, type, gcc_p) \
+{ \
+ *(unsigned long *)((char *) (dummy) + 0xa0) |= \
+ (((unsigned long) (fun)) >> 16); \
+ *(unsigned long *)((char *) (dummy) + 0xa4) |= \
+ (((unsigned long) (fun)) & 0xffff); \
+ pc = text_end; \
+}
+
+/* Stack must be aligned on 64-bit boundaries when synthesizing
+ function calls. */
+
+#define STACK_ALIGN(addr) (((addr) + 7) & -8)
+
+#define STORE_STRUCT_RETURN(addr, sp) \
+ write_register (SRA_REGNUM, (addr))
+
+#define NEED_TEXT_START_END 1
+
+/* According to the MC88100 RISC Microprocessor User's Manual, section
+ 6.4.3.1.2:
+
+ ... can be made to return to a particular instruction by placing a
+ valid instruction address in the SNIP and the next sequential
+ instruction address in the SFIP (with V bits set and E bits clear).
+ The rte resumes execution at the instruction pointed to by the
+ SNIP, then the SFIP.
+
+ The E bit is the least significant bit (bit 0). The V (valid) bit is
+ bit 1. This is why we logical or 2 into the values we are writing
+ below. It turns out that SXIP plays no role when returning from an
+ exception so nothing special has to be done with it. We could even
+ (presumably) give it a totally bogus value.
+
+ -- Kevin Buettner
+*/
+
+#define TARGET_WRITE_PC(val, pid) { \
+ write_register_pid(SXIP_REGNUM, (long) val, pid); \
+ write_register_pid(SNIP_REGNUM, (long) val | 2, pid); \
+ write_register_pid(SFIP_REGNUM, ((long) val | 2) + 4, pid); \
+}
diff --git a/gdb/config/m88k/xm-cxux.h b/gdb/config/m88k/xm-cxux.h
new file mode 100644
index 00000000000..582c613436b
--- /dev/null
+++ b/gdb/config/m88k/xm-cxux.h
@@ -0,0 +1,66 @@
+/* Host-machine dependent parameters for Motorola 88000, for GDB.
+ Copyright 1986, 1987, 1988, 1989, 1990, 1991, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "m88k/xm-m88k.h"
+
+#define HOST_BYTE_ORDER BIG_ENDIAN
+
+#if !defined (USG)
+#define USG 1
+#endif
+
+#include <sys/param.h>
+
+#define x_foff _x_x._x_offset
+#define x_fname _x_name
+#define USER ptrace_user
+/*
+#define _BSD_WAIT_FLAVOR
+*/
+
+#define HAVE_TERMIO
+
+#ifndef USIZE
+#define USIZE 2048
+#ifndef UPAGES
+#define UPAGES USIZE
+#endif
+#endif
+#define NBPG NBPC
+
+/* Get rid of any system-imposed stack limit if possible. */
+
+#define SET_STACK_LIMIT_HUGE
+
+/* This is the amount to subtract from u.u_ar0
+ to get the offset in the core file of the register values. */
+
+/* Since registers r0 through r31 are stored directly in the struct ptrace_user,
+ (for m88k BCS)
+ the ptrace_user offsets are sufficient and KERNEL_U_ADDRESS can be 0 */
+
+#define KERNEL_U_ADDR 0
+
+/* The CX/UX C compiler doesn't permit complex expressions as array bounds. */
+#define STRICT_ANSI_BOUNDS
+
+#define CORE_REGISTER_ADDR(regno, reg_ptr) \
+ m88k_harris_core_register_addr(regno, reg_ptr)
+
diff --git a/gdb/config/m88k/xm-delta88.h b/gdb/config/m88k/xm-delta88.h
new file mode 100644
index 00000000000..21669473e60
--- /dev/null
+++ b/gdb/config/m88k/xm-delta88.h
@@ -0,0 +1,45 @@
+/* Host machine description for Motorola Delta 88 system, for 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "m88k/xm-m88k.h"
+
+#if !defined (USG)
+#define USG 1
+#endif
+
+#include <sys/param.h>
+#include <sys/time.h>
+
+#define HAVE_TERMIO
+
+/*#define USIZE 2048*/
+/*#define NBPG NBPC*/
+/* Might be defined in <sys/param.h>. I suspect this define was a relic
+ from before when BFD did core files. */
+/* #define UPAGES USIZE */
+
+/* This is the amount to subtract from u.u_ar0
+ to get the offset in the core file of the register values. */
+
+/* Since registers r0 through r31 are stored directly in the struct ptrace_user,
+ (for m88k BCS)
+ the ptrace_user offsets are sufficient and KERNEL_U_ADDRESS can be 0 */
+
+#define KERNEL_U_ADDR 0
diff --git a/gdb/config/m88k/xm-delta88v4.h b/gdb/config/m88k/xm-delta88v4.h
new file mode 100644
index 00000000000..55c9e2de538
--- /dev/null
+++ b/gdb/config/m88k/xm-delta88v4.h
@@ -0,0 +1,22 @@
+/* Host machine description for Motorola Delta 88 box, for GDB.
+ Copyright 1986, 1987, 1988, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "m88k/xm-m88k.h"
+
+#include "xm-sysv4.h"
diff --git a/gdb/config/m88k/xm-dgux.h b/gdb/config/m88k/xm-dgux.h
new file mode 100644
index 00000000000..b3608e7d5c7
--- /dev/null
+++ b/gdb/config/m88k/xm-dgux.h
@@ -0,0 +1,58 @@
+/* Host-machine dependent parameters for Motorola 88000, for GDB.
+ Copyright 1986, 1987, 1988, 1989, 1990, 1991, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "m88k/xm-m88k.h"
+
+#define HOST_BYTE_ORDER BIG_ENDIAN
+
+#if !defined (USG)
+#define USG 1
+#endif
+
+#include <sys/param.h>
+
+#ifdef __GNUC__
+#define memcpy __builtin_memcpy
+/* gcc doesn't have this, at least not gcc 1.92. */
+/* #define memset __builtin_memset */
+#define strcmp __builtin_strcmp
+#endif
+
+#define x_foff _x_x._x_offset
+#define x_fname _x_name
+#define USER ptrace_user
+#define _BSD_WAIT_FLAVOR
+
+#define HAVE_TERMIO
+
+#ifndef USIZE
+#define USIZE 2048
+#endif
+#define NBPG NBPC
+#define UPAGES USIZE
+
+/* This is the amount to subtract from u.u_ar0
+ to get the offset in the core file of the register values. */
+
+/* Since registers r0 through r31 are stored directly in the struct ptrace_user,
+ (for m88k BCS)
+ the ptrace_user offsets are sufficient and KERNEL_U_ADDRESS can be 0 */
+
+#define KERNEL_U_ADDR 0
diff --git a/gdb/config/m88k/xm-m88k.h b/gdb/config/m88k/xm-m88k.h
new file mode 100644
index 00000000000..35620a0ce01
--- /dev/null
+++ b/gdb/config/m88k/xm-m88k.h
@@ -0,0 +1,20 @@
+/* Host-machine dependent parameters for Motorola 88000, for GDB.
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define HOST_BYTE_ORDER BIG_ENDIAN
diff --git a/gdb/config/mips/bigmips.mt b/gdb/config/mips/bigmips.mt
new file mode 100644
index 00000000000..38f03f2f8e4
--- /dev/null
+++ b/gdb/config/mips/bigmips.mt
@@ -0,0 +1,3 @@
+# Target: Big-endian MIPS machine such as Sony News
+TDEPFILES= mips-tdep.o
+TM_FILE= tm-bigmips.h
diff --git a/gdb/config/mips/bigmips64.mt b/gdb/config/mips/bigmips64.mt
new file mode 100644
index 00000000000..fcb7b21dae5
--- /dev/null
+++ b/gdb/config/mips/bigmips64.mt
@@ -0,0 +1,3 @@
+# Target: Big-endian MIPS machine such as Sony News
+TDEPFILES= mips-tdep.o
+TM_FILE= tm-bigmips64.h
diff --git a/gdb/config/mips/decstation.mh b/gdb/config/mips/decstation.mh
new file mode 100644
index 00000000000..da417b29fda
--- /dev/null
+++ b/gdb/config/mips/decstation.mh
@@ -0,0 +1,5 @@
+# Host: Little-endian MIPS machine such as DECstation.
+XDEPFILES=
+XM_FILE= xm-mips.h
+NAT_FILE= nm-mips.h
+NATDEPFILES= infptrace.o inftarg.o corelow.o mips-nat.o fork-child.o
diff --git a/gdb/config/mips/decstation.mt b/gdb/config/mips/decstation.mt
new file mode 100644
index 00000000000..19847224d2f
--- /dev/null
+++ b/gdb/config/mips/decstation.mt
@@ -0,0 +1,3 @@
+# Target: Little-endian MIPS machine such as DECstation.
+TDEPFILES= mips-tdep.o
+TM_FILE= tm-mips.h
diff --git a/gdb/config/mips/embed.mt b/gdb/config/mips/embed.mt
new file mode 100644
index 00000000000..42ab4aa47b9
--- /dev/null
+++ b/gdb/config/mips/embed.mt
@@ -0,0 +1,5 @@
+# Target: Big-endian mips board, typically an IDT.
+TDEPFILES= mips-tdep.o remote-mips.o remote-array.o
+TM_FILE= tm-embed.h
+SIM_OBS = remote-sim.o
+SIM = ../sim/mips/libsim.a
diff --git a/gdb/config/mips/embed64.mt b/gdb/config/mips/embed64.mt
new file mode 100644
index 00000000000..ed60fd25031
--- /dev/null
+++ b/gdb/config/mips/embed64.mt
@@ -0,0 +1,5 @@
+# Target: Big-endian mips board, typically an IDT.
+TDEPFILES= mips-tdep.o remote-mips.o remote-array.o
+TM_FILE= tm-embed64.h
+SIM_OBS = remote-sim.o
+SIM = ../sim/mips/libsim.a
diff --git a/gdb/config/mips/embedl.mt b/gdb/config/mips/embedl.mt
new file mode 100644
index 00000000000..0ed8b8d5021
--- /dev/null
+++ b/gdb/config/mips/embedl.mt
@@ -0,0 +1,5 @@
+# Target: Big-endian mips board, typically an IDT.
+TDEPFILES= mips-tdep.o remote-mips.o remote-array.o
+TM_FILE= tm-embedl.h
+SIM_OBS = remote-sim.o
+SIM = ../sim/mips/libsim.a
diff --git a/gdb/config/mips/embedl64.mt b/gdb/config/mips/embedl64.mt
new file mode 100644
index 00000000000..28c41be48fb
--- /dev/null
+++ b/gdb/config/mips/embedl64.mt
@@ -0,0 +1,5 @@
+# Target: Big-endian mips board, typically an IDT.
+TDEPFILES= mips-tdep.o remote-mips.o remote-array.o
+TM_FILE= tm-embedl64.h
+SIM_OBS = remote-sim.o
+SIM = ../sim/mips/libsim.a
diff --git a/gdb/config/mips/irix3.mh b/gdb/config/mips/irix3.mh
new file mode 100644
index 00000000000..311d697cb58
--- /dev/null
+++ b/gdb/config/mips/irix3.mh
@@ -0,0 +1,6 @@
+# Host: SGI Iris running irix 3.x
+XDEPFILES=
+XM_FILE= xm-irix3.h
+NAT_FILE= nm-irix3.h
+NATDEPFILES= fork-child.o corelow.o infptrace.o inftarg.o mips-nat.o
+XM_CLIBS=-lbsd
diff --git a/gdb/config/mips/irix3.mt b/gdb/config/mips/irix3.mt
new file mode 100644
index 00000000000..b3fa4dda384
--- /dev/null
+++ b/gdb/config/mips/irix3.mt
@@ -0,0 +1,3 @@
+# Target: MIPS SGI running Irix 3
+TDEPFILES= mips-tdep.o
+TM_FILE= tm-irix3.h
diff --git a/gdb/config/mips/irix4.mh b/gdb/config/mips/irix4.mh
new file mode 100644
index 00000000000..68511e6b9a4
--- /dev/null
+++ b/gdb/config/mips/irix4.mh
@@ -0,0 +1,8 @@
+# Host: SGI Iris running irix 4.x
+XDEPFILES= ser-tcp.o
+XM_FILE= xm-irix4.h
+NAT_FILE= nm-irix4.h
+NATDEPFILES= fork-child.o procfs.o irix4-nat.o corelow.o
+XM_CLIBS=-lbsd -lsun
+# use cc in K&R mode, bump up some static compiler tables.
+CC = cc -cckr -Wf,-XNg1500 -Wf,-XNk1000 -Wf,-XNh1100
diff --git a/gdb/config/mips/irix5.mh b/gdb/config/mips/irix5.mh
new file mode 100644
index 00000000000..0e276864800
--- /dev/null
+++ b/gdb/config/mips/irix5.mh
@@ -0,0 +1,6 @@
+# Host: SGI Iris running irix 5.x
+XDEPFILES= ser-tcp.o
+XM_FILE= xm-irix5.h
+NAT_FILE= nm-irix5.h
+NATDEPFILES= fork-child.o procfs.o irix5-nat.o corelow.o
+XM_CLIBS=-lbsd -lsun
diff --git a/gdb/config/mips/irix5.mt b/gdb/config/mips/irix5.mt
new file mode 100644
index 00000000000..5b17bcdf1dd
--- /dev/null
+++ b/gdb/config/mips/irix5.mt
@@ -0,0 +1,3 @@
+# Target: MIPS SGI running Irix 5
+TDEPFILES= mips-tdep.o
+TM_FILE= tm-irix5.h
diff --git a/gdb/config/mips/littlemips.mh b/gdb/config/mips/littlemips.mh
new file mode 100644
index 00000000000..103919d230e
--- /dev/null
+++ b/gdb/config/mips/littlemips.mh
@@ -0,0 +1,3 @@
+# Host: Little-endian MIPS machine such as DECstation.
+XDEPFILES= infptrace.o inftarg.o fork-child.o corelow.o core-aout.o
+XM_FILE= xm-mips.h
diff --git a/gdb/config/mips/littlemips.mt b/gdb/config/mips/littlemips.mt
new file mode 100644
index 00000000000..19847224d2f
--- /dev/null
+++ b/gdb/config/mips/littlemips.mt
@@ -0,0 +1,3 @@
+# Target: Little-endian MIPS machine such as DECstation.
+TDEPFILES= mips-tdep.o
+TM_FILE= tm-mips.h
diff --git a/gdb/config/mips/mipsm3.mh b/gdb/config/mips/mipsm3.mh
new file mode 100644
index 00000000000..e049d682a39
--- /dev/null
+++ b/gdb/config/mips/mipsm3.mh
@@ -0,0 +1,7 @@
+# Host: Little endian MIPS machine such as pmax
+# running Mach 3.0 operating system
+
+XDEPFILES= core-aout.o
+NATDEPFILES= mipsm3-nat.o m3-nat.o
+XM_FILE= xm-mipsm3.h
+NAT_FILE= ../nm-m3.h
diff --git a/gdb/config/mips/mipsm3.mt b/gdb/config/mips/mipsm3.mt
new file mode 100644
index 00000000000..66856d16c04
--- /dev/null
+++ b/gdb/config/mips/mipsm3.mt
@@ -0,0 +1,4 @@
+# Target: Little-endian MIPS machine such as pmax
+# running Mach 3.0 operating system
+TDEPFILES= mips-tdep.o
+TM_FILE= tm-mipsm3.h
diff --git a/gdb/config/mips/mipsv4.mh b/gdb/config/mips/mipsv4.mh
new file mode 100644
index 00000000000..87cb7e42393
--- /dev/null
+++ b/gdb/config/mips/mipsv4.mh
@@ -0,0 +1,4 @@
+# Host: Mips running SVR4
+XM_FILE= xm-mipsv4.h
+NAT_FILE= ../nm-sysv4.h
+NATDEPFILES= fork-child.o procfs.o mipsv4-nat.o corelow.o core-regset.o solib.o
diff --git a/gdb/config/mips/mipsv4.mt b/gdb/config/mips/mipsv4.mt
new file mode 100644
index 00000000000..6d3b47d024a
--- /dev/null
+++ b/gdb/config/mips/mipsv4.mt
@@ -0,0 +1,3 @@
+# Target: MIPS running SVR4
+TDEPFILES= mips-tdep.o
+TM_FILE= tm-mipsv4.h
diff --git a/gdb/config/mips/news-mips.mh b/gdb/config/mips/news-mips.mh
new file mode 100644
index 00000000000..620fbaad7c0
--- /dev/null
+++ b/gdb/config/mips/news-mips.mh
@@ -0,0 +1,4 @@
+# Host: Big-endian MIPS machine such as Sony News
+NATDEPFILES= infptrace.o inftarg.o fork-child.o corelow.o mips-nat.o
+XM_FILE= xm-news-mips.h
+NAT_FILE= nm-news-mips.h
diff --git a/gdb/config/mips/nm-irix3.h b/gdb/config/mips/nm-irix3.h
new file mode 100644
index 00000000000..3f4b06463c9
--- /dev/null
+++ b/gdb/config/mips/nm-irix3.h
@@ -0,0 +1,37 @@
+/* Definitions for SGI irix3 native support.
+ Copyright 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Don't need special routines for Irix v3 -- we can use infptrace.c */
+#undef FETCH_INFERIOR_REGISTERS
+
+#define U_REGS_OFFSET 0
+
+/* Figure out where the longjmp will land. We expect that we have just entered
+ longjmp and haven't yet setup the stack frame, so the args are still in the
+ argument regs. a0 (CALL_ARG0) points at the jmp_buf structure from which we
+ extract the pc (JB_PC) that we will land at. The pc is copied into ADDR.
+ This routine returns true on success */
+
+#define GET_LONGJMP_TARGET(ADDR) get_longjmp_target(ADDR)
+extern int get_longjmp_target PARAMS ((CORE_ADDR *));
+
+/* Is this really true or is this just a leftover from a DECstation
+ config file? */
+
+#define ONE_PROCESS_WRITETEXT
diff --git a/gdb/config/mips/nm-irix4.h b/gdb/config/mips/nm-irix4.h
new file mode 100644
index 00000000000..017695ca295
--- /dev/null
+++ b/gdb/config/mips/nm-irix4.h
@@ -0,0 +1,61 @@
+/* Definitions for native support of irix4.
+
+Copyright (C) 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/*
+ * Let's use /debug instead of all this dangerous mucking about
+ * with ptrace(), which seems *extremely* fragile, anyway.
+ */
+#define USE_PROC_FS
+#define CTL_PROC_NAME_FMT "/debug/%d"
+#define AS_PROC_NAME_FMT "/debug/%d"
+#define MAP_PROC_NAME_FMT "/debug/%d"
+#define STATUS_PROC_NAME_FMT "/debug/%d"
+
+/* Don't need special routines for the SGI -- we can use infptrace.c */
+#undef FETCH_INFERIOR_REGISTERS
+
+#define U_REGS_OFFSET 0
+
+/* Is this really true or is this just a leftover from a DECstation
+ config file? */
+
+#define ONE_PROCESS_WRITETEXT
+
+#define TARGET_HAS_HARDWARE_WATCHPOINTS
+
+/* Temporary new watchpoint stuff */
+#define TARGET_CAN_USE_HARDWARE_WATCHPOINT(type, cnt, ot) \
+ ((type) == bp_hardware_watchpoint)
+
+/* When a hardware watchpoint fires off the PC will be left at the
+ instruction which caused the watchpoint. It will be necessary for
+ GDB to step over the watchpoint. */
+
+#define STOPPED_BY_WATCHPOINT(W) \
+ procfs_stopped_by_watchpoint(inferior_pid)
+extern int procfs_stopped_by_watchpoint PARAMS ((int));
+
+#define HAVE_NONSTEPPABLE_WATCHPOINT
+
+/* Use these macros for watchpoint insertion/deletion. */
+/* type can be 0: write watch, 1: read watch, 2: access watch (read/write) */
+#define target_insert_watchpoint(addr, len, type) procfs_set_watchpoint (inferior_pid, addr, len, 2)
+#define target_remove_watchpoint(addr, len, type) procfs_set_watchpoint (inferior_pid, addr, 0, 0)
+extern int procfs_set_watchpoint PARAMS ((int, CORE_ADDR, int, int));
diff --git a/gdb/config/mips/nm-irix5.h b/gdb/config/mips/nm-irix5.h
new file mode 100644
index 00000000000..90d454bb418
--- /dev/null
+++ b/gdb/config/mips/nm-irix5.h
@@ -0,0 +1,44 @@
+/* Definitions for native support of irix5.
+
+Copyright (C) 1993, 1998 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "nm-sysv4.h"
+#undef IN_SOLIB_DYNSYM_RESOLVE_CODE
+
+#define TARGET_HAS_HARDWARE_WATCHPOINTS
+
+/* Temporary new watchpoint stuff */
+#define TARGET_CAN_USE_HARDWARE_WATCHPOINT(type, cnt, ot) \
+ ((type) == bp_hardware_watchpoint)
+
+/* When a hardware watchpoint fires off the PC will be left at the
+ instruction which caused the watchpoint. It will be necessary for
+ GDB to step over the watchpoint. */
+
+#define STOPPED_BY_WATCHPOINT(W) \
+ procfs_stopped_by_watchpoint(inferior_pid)
+extern int procfs_stopped_by_watchpoint PARAMS ((int));
+
+#define HAVE_NONSTEPPABLE_WATCHPOINT
+
+/* Use these macros for watchpoint insertion/deletion. */
+/* type can be 0: write watch, 1: read watch, 2: access watch (read/write) */
+#define target_insert_watchpoint(addr, len, type) procfs_set_watchpoint (inferior_pid, addr, len, 2)
+#define target_remove_watchpoint(addr, len, type) procfs_set_watchpoint (inferior_pid, addr, 0, 0)
+extern int procfs_set_watchpoint PARAMS ((int, CORE_ADDR, int, int));
diff --git a/gdb/config/mips/nm-mips.h b/gdb/config/mips/nm-mips.h
new file mode 100644
index 00000000000..6418b86ee92
--- /dev/null
+++ b/gdb/config/mips/nm-mips.h
@@ -0,0 +1,32 @@
+/* Native definitions for GDB on DECstations, Sony News. and MIPS Riscos systems
+ Copyright (C) 1986, 1987, 1989, 1992 Free Software Foundation, Inc.
+ Contributed by Per Bothner(bothner@cs.wisc.edu) at U.Wisconsin
+ and by Alessandro Forin(af@cs.cmu.edu) at CMU
+
+This file is part of GDB.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Override copies of {fetch,store}_inferior_registers in infptrace.c. */
+#define FETCH_INFERIOR_REGISTERS
+
+/* Figure out where the longjmp will land. We expect that we have just entered
+ longjmp and haven't yet setup the stack frame, so the args are still in the
+ argument regs. a0 (CALL_ARG0) points at the jmp_buf structure from which we
+ extract the pc (JB_PC) that we will land at. The pc is copied into ADDR.
+ This routine returns true on success */
+
+#define GET_LONGJMP_TARGET(ADDR) get_longjmp_target(ADDR)
+extern int get_longjmp_target PARAMS ((CORE_ADDR *));
diff --git a/gdb/config/mips/nm-news-mips.h b/gdb/config/mips/nm-news-mips.h
new file mode 100644
index 00000000000..1ab63ba2b12
--- /dev/null
+++ b/gdb/config/mips/nm-news-mips.h
@@ -0,0 +1,42 @@
+/* Definitions to make GDB run on a mips box under 4.3bsd.
+ Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
+ Contributed by Per Bothner(bothner@cs.wisc.edu) at U.Wisconsin
+ and by Alessandro Forin(af@cs.cmu.edu) at CMU
+
+This file is part of GDB.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef NM_NEWS_MIPS_H
+#define NM_NEWS_MIPS_H 1
+
+/* Needed for RISC NEWS core files. */
+#include <machine/machparam.h>
+#include <sys/types.h>
+#define KERNEL_U_ADDR UADDR
+
+#define REGISTER_U_ADDR(addr, blockend, regno) \
+ if (regno < 38) addr = (NBPG*UPAGES) + (regno - 38)*sizeof(int);\
+ else addr = 0; /* ..somewhere in the pcb */
+
+/* Kernel is a bit tenacious about sharing text segments, disallowing bpts. */
+#define ONE_PROCESS_WRITETEXT
+
+#include "mips/nm-mips.h"
+
+/* Apparently not in <sys/types.h> */
+typedef int pid_t;
+
+#endif /* NM_NEWS_MIPS_H */
diff --git a/gdb/config/mips/nm-riscos.h b/gdb/config/mips/nm-riscos.h
new file mode 100644
index 00000000000..2d543455827
--- /dev/null
+++ b/gdb/config/mips/nm-riscos.h
@@ -0,0 +1,59 @@
+/* This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* MIPS running RISC/os 4.52C. */
+
+#define PCB_OFFSET(FIELD) ((int)&((struct user*)0)->u_pcb.FIELD)
+
+/* RISC/os 5.0 defines this in machparam.h. */
+#include <bsd43/machine/machparam.h>
+#define NBPG BSD43_NBPG
+#define UPAGES BSD43_UPAGES
+
+/* Where is this used? I don't see any uses in mips-nat.c, and I don't think
+ the uses in infptrace.c are used if FETCH_INFERIOR_REGISTERS is defined.
+ Does the compiler react badly to "extern CORE_ADDR kernel_u_addr" (even
+ if never referenced)? */
+#define KERNEL_U_ADDR BSD43_UADDR
+
+#define REGISTER_U_ADDR(addr, blockend, regno) \
+ if (regno < FP0_REGNUM) \
+ addr = UPAGES*NBPG-EF_SIZE+4*((regno)+EF_AT-1); \
+ else if (regno < PC_REGNUM) \
+ addr = PCB_OFFSET(pcb_fpregs[0]) + 4*(regno-FP0_REGNUM); \
+ else if (regno == PS_REGNUM) \
+ addr = UPAGES*NBPG-EF_SIZE+4*EF_SR; \
+ else if (regno == BADVADDR_REGNUM) \
+ addr = UPAGES*NBPG-EF_SIZE+4*EF_BADVADDR; \
+ else if (regno == LO_REGNUM) \
+ addr = UPAGES*NBPG-EF_SIZE+4*EF_MDLO; \
+ else if (regno == HI_REGNUM) \
+ addr = UPAGES*NBPG-EF_SIZE+4*EF_MDHI; \
+ else if (regno == CAUSE_REGNUM) \
+ addr = UPAGES*NBPG-EF_SIZE+4*EF_CAUSE; \
+ else if (regno == PC_REGNUM) \
+ addr = UPAGES*NBPG-EF_SIZE+4*EF_EPC; \
+ else if (regno < FCRCS_REGNUM) \
+ addr = PCB_OFFSET(pcb_fpregs[0]) + 4*(regno-FP0_REGNUM); \
+ else if (regno == FCRCS_REGNUM) \
+ addr = PCB_OFFSET(pcb_fpc_csr); \
+ else if (regno == FCRIR_REGNUM) \
+ addr = PCB_OFFSET(pcb_fpc_eir); \
+ else \
+ addr = 0;
+
+#include "mips/nm-mips.h"
+
+/* Override copies of {fetch,store}_inferior_registers in infptrace.c. */
+#define FETCH_INFERIOR_REGISTERS
diff --git a/gdb/config/mips/riscos.mh b/gdb/config/mips/riscos.mh
new file mode 100644
index 00000000000..6a3192f382b
--- /dev/null
+++ b/gdb/config/mips/riscos.mh
@@ -0,0 +1,16 @@
+# Host: MIPS running RISC/os
+
+XM_FILE= xm-riscos.h
+
+NAT_FILE= nm-riscos.h
+NATDEPFILES= infptrace.o inftarg.o fork-child.o corelow.o mips-nat.o
+
+MH_CFLAGS=-Wf,-XNh10000
+
+# ptrace(2) apparently has problems in the BSD environment. No workaround is
+# known except to select the sysv environment. Could we use /proc instead?
+# These "sysv environments" and "bsd environments" often end up being a pain.
+#
+# This is not part of CFLAGS because perhaps not all C compilers have this
+# option.
+CC= cc -systype sysv
diff --git a/gdb/config/mips/tm-bigmips.h b/gdb/config/mips/tm-bigmips.h
new file mode 100644
index 00000000000..271ceb0b363
--- /dev/null
+++ b/gdb/config/mips/tm-bigmips.h
@@ -0,0 +1,21 @@
+/* Copyright (C) 1990 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define TARGET_BYTE_ORDER_DEFAULT BIG_ENDIAN
+
+#include "mips/tm-mips.h"
diff --git a/gdb/config/mips/tm-bigmips64.h b/gdb/config/mips/tm-bigmips64.h
new file mode 100644
index 00000000000..8b255a5a326
--- /dev/null
+++ b/gdb/config/mips/tm-bigmips64.h
@@ -0,0 +1,23 @@
+/* Target machine parameters for MIPS r4000
+ Copyright 1994 Free Software Foundation, Inc.
+ Contributed by Ian Lance Taylor (ian@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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define TARGET_BYTE_ORDER_DEFAULT BIG_ENDIAN
+
+#include "mips/tm-mips64.h"
diff --git a/gdb/config/mips/tm-embed.h b/gdb/config/mips/tm-embed.h
new file mode 100644
index 00000000000..7bf17597706
--- /dev/null
+++ b/gdb/config/mips/tm-embed.h
@@ -0,0 +1,49 @@
+/* Copyright (C) 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define TARGET_BYTE_ORDER_SELECTABLE_P 1
+
+#include "mips/tm-bigmips.h"
+
+#undef DEFAULT_MIPS_TYPE
+#define DEFAULT_MIPS_TYPE "r3051"
+
+/* Watchpoint support */
+
+#define TARGET_HAS_HARDWARE_WATCHPOINTS
+
+/* Use these macros for watchpoint insertion/deletion. */
+/* type can be 0: write watch, 1: read watch, 2: access watch (read/write) */
+
+#define target_insert_watchpoint(addr, len, type) \
+ remote_mips_set_watchpoint (addr, len, type)
+int remote_mips_set_watchpoint PARAMS ((CORE_ADDR addr, int len, int type));
+
+#define target_remove_watchpoint(addr, len, type) \
+ remote_mips_remove_watchpoint (addr, len, type)
+int remote_mips_remove_watchpoint PARAMS ((CORE_ADDR addr, int len, int type));
+
+/* We need to remove watchpoints when stepping, else we hit them again! */
+
+#define HAVE_NONSTEPPABLE_WATCHPOINT
+
+#define STOPPED_BY_WATCHPOINT(w) remote_mips_stopped_by_watchpoint ()
+
+#define TARGET_CAN_USE_HARDWARE_WATCHPOINT(type, cnt, ot) \
+ remote_mips_can_use_hardware_watchpoint(cnt)
+int remote_mips_can_use_hardware_watchpoint PARAMS ((int cnt));
diff --git a/gdb/config/mips/tm-embed64.h b/gdb/config/mips/tm-embed64.h
new file mode 100644
index 00000000000..df90f58fa98
--- /dev/null
+++ b/gdb/config/mips/tm-embed64.h
@@ -0,0 +1,21 @@
+/* Copyright (C) 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define TARGET_BYTE_ORDER_SELECTABLE_P 1
+
+#include "mips/tm-bigmips64.h"
diff --git a/gdb/config/mips/tm-embedl.h b/gdb/config/mips/tm-embedl.h
new file mode 100644
index 00000000000..23abcd9db84
--- /dev/null
+++ b/gdb/config/mips/tm-embedl.h
@@ -0,0 +1,21 @@
+/* Copyright (C) 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define TARGET_BYTE_ORDER_SELECTABLE_P 1
+
+#include "mips/tm-mips.h"
diff --git a/gdb/config/mips/tm-embedl64.h b/gdb/config/mips/tm-embedl64.h
new file mode 100644
index 00000000000..c7dca195324
--- /dev/null
+++ b/gdb/config/mips/tm-embedl64.h
@@ -0,0 +1,21 @@
+/* Copyright (C) 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define TARGET_BYTE_ORDER_SELECTABLE_P 1
+
+#include "mips/tm-mips64.h"
diff --git a/gdb/config/mips/tm-irix3.h b/gdb/config/mips/tm-irix3.h
new file mode 100644
index 00000000000..7e8e53eb326
--- /dev/null
+++ b/gdb/config/mips/tm-irix3.h
@@ -0,0 +1,81 @@
+/* Target machine description for SGI Iris under Irix, for GDB.
+ Copyright 1990, 1991, 1992, 1993, 1995 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "mips/tm-bigmips.h"
+
+/* SGI's assembler doesn't grok dollar signs in identifiers.
+ So we use dots instead. This item must be coordinated with G++. */
+#undef CPLUS_MARKER
+#define CPLUS_MARKER '.'
+
+/* Redefine register numbers for SGI. */
+
+#undef NUM_REGS
+#undef REGISTER_NAMES
+#undef FP0_REGNUM
+#undef PC_REGNUM
+#undef PS_REGNUM
+#undef HI_REGNUM
+#undef LO_REGNUM
+#undef CAUSE_REGNUM
+#undef BADVADDR_REGNUM
+#undef FCRCS_REGNUM
+#undef FCRIR_REGNUM
+
+/* Number of machine registers */
+
+#define NUM_REGS 71
+
+/* Initializer for an array of names of registers.
+ There should be NUM_REGS strings in this initializer. */
+
+#define REGISTER_NAMES \
+ { "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3", \
+ "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", \
+ "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", \
+ "t8", "t9", "k0", "k1", "gp", "sp", "fp", "ra", \
+ "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", \
+ "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", \
+ "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",\
+ "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",\
+ "pc", "cause", "bad", "hi", "lo", "fsr", "fir" \
+ }
+
+/* Register numbers of various important registers.
+ Note that some of these values are "real" register numbers,
+ and correspond to the general registers of the machine,
+ and some are "phony" register numbers which are too large
+ to be actual register numbers as far as the user is concerned
+ but do serve to get the desired values when passed to read_register. */
+
+#define FP0_REGNUM 32 /* Floating point register 0 (single float) */
+#define PC_REGNUM 64 /* Contains program counter */
+#define CAUSE_REGNUM 65 /* describes last exception */
+#define BADVADDR_REGNUM 66 /* bad vaddr for addressing exception */
+#define HI_REGNUM 67 /* Multiple/divide temp */
+#define LO_REGNUM 68 /* ... */
+#define FCRCS_REGNUM 69 /* FP control/status */
+#define FCRIR_REGNUM 70 /* FP implementation/revision */
+
+/* Offsets for register values in _sigtramp frame.
+ sigcontext is immediately above the _sigtramp frame on Irix. */
+#define SIGFRAME_BASE 0x0
+#define SIGFRAME_PC_OFF (SIGFRAME_BASE + 2 * 4)
+#define SIGFRAME_REGSAVE_OFF (SIGFRAME_BASE + 3 * 4)
+#define SIGFRAME_FPREGSAVE_OFF (SIGFRAME_BASE + 3 * 4 + 32 * 4 + 4)
diff --git a/gdb/config/mips/tm-irix5.h b/gdb/config/mips/tm-irix5.h
new file mode 100644
index 00000000000..ad98e881859
--- /dev/null
+++ b/gdb/config/mips/tm-irix5.h
@@ -0,0 +1,75 @@
+/* Target machine description for SGI Iris under Irix 5, for GDB.
+ Copyright 1990, 1991, 1992, 1993, 1995 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "mips/tm-irix3.h"
+
+#if defined (_MIPS_SIM_NABI32) && _MIPS_SIM == _MIPS_SIM_NABI32
+/*
+ * Irix 6 (n32 ABI) has 32-bit GP regs and 64-bit FP regs
+ */
+
+#undef REGISTER_BYTES
+#define REGISTER_BYTES (MIPS_NUMREGS * 8 + (NUM_REGS - MIPS_NUMREGS) * MIPS_REGSIZE)
+
+#undef REGISTER_BYTE
+#define REGISTER_BYTE(N) \
+ (((N) < FP0_REGNUM) ? (N) * MIPS_REGSIZE : \
+ ((N) < FP0_REGNUM + 32) ? \
+ FP0_REGNUM * MIPS_REGSIZE + \
+ ((N) - FP0_REGNUM) * sizeof(double) : \
+ 32 * sizeof(double) + ((N) - 32) * MIPS_REGSIZE)
+
+#undef REGISTER_VIRTUAL_TYPE
+#define REGISTER_VIRTUAL_TYPE(N) \
+ (((N) >= FP0_REGNUM && (N) < FP0_REGNUM+32) ? builtin_type_double \
+ : ((N) == 32 /*SR*/) ? builtin_type_uint32 \
+ : ((N) >= 70 && (N) <= 89) ? builtin_type_uint32 \
+ : builtin_type_int)
+
+#undef MIPS_LAST_ARG_REGNUM
+#define MIPS_LAST_ARG_REGNUM 11 /* N32 uses R4 through R11 for args */
+
+#undef MIPS_NUM_ARG_REGS
+#define MIPS_NUM_ARG_REGS 8
+
+#endif /* N32 */
+
+/* When calling functions on Irix 5 (or any MIPS SVR4 ABI compliant
+ platform) $25 must hold the function address. Dest_Reg is a macro
+ used in CALL_DUMMY in tm-mips.h. */
+#undef Dest_Reg
+#define Dest_Reg 25
+
+/* The signal handler trampoline is called _sigtramp. */
+#undef IN_SIGTRAMP
+#define IN_SIGTRAMP(pc, name) ((name) && STREQ ("_sigtramp", name))
+
+/* Irix 5 saves a full 64 bits for each register. We skip 2 * 4 to
+ get to the saved PC (the register mask and status register are both
+ 32 bits) and then another 4 to get to the lower 32 bits. We skip
+ the same 4 bytes, plus the 8 bytes for the PC to get to the
+ registers, and add another 4 to get to the lower 32 bits. We skip
+ 8 bytes per register. */
+#undef SIGFRAME_PC_OFF
+#define SIGFRAME_PC_OFF (SIGFRAME_BASE + 2 * 4 + 4)
+#undef SIGFRAME_REGSAVE_OFF
+#define SIGFRAME_REGSAVE_OFF (SIGFRAME_BASE + 2 * 4 + 8 + 4)
+#undef SIGFRAME_FPREGSAVE_OFF
+#define SIGFRAME_FPREGSAVE_OFF (SIGFRAME_BASE + 2 * 4 + 8 + 32 * 8 + 4)
+#define SIGFRAME_REG_SIZE 8
diff --git a/gdb/config/mips/tm-mips.h b/gdb/config/mips/tm-mips.h
new file mode 100644
index 00000000000..6a7091a5282
--- /dev/null
+++ b/gdb/config/mips/tm-mips.h
@@ -0,0 +1,560 @@
+/* Definitions to make GDB run on a mips box under 4.3bsd.
+ Copyright 1986, 1987, 1989, 1991, 1992, 1993, 1994, 1995
+ Free Software Foundation, Inc.
+ Contributed by Per Bothner (bothner@cs.wisc.edu) at U.Wisconsin
+ and by Alessandro Forin (af@cs.cmu.edu) at CMU..
+
+This file is part of GDB.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef TM_MIPS_H
+#define TM_MIPS_H 1
+
+#ifdef __STDC__
+struct frame_info;
+struct symbol;
+struct type;
+struct value;
+#endif
+
+#include <bfd.h>
+#include "coff/sym.h" /* Needed for PDR below. */
+#include "coff/symconst.h"
+
+#if !defined (TARGET_BYTE_ORDER_DEFAULT)
+#define TARGET_BYTE_ORDER_DEFAULT LITTLE_ENDIAN
+#endif
+
+#if !defined (GDB_TARGET_IS_MIPS64)
+#define GDB_TARGET_IS_MIPS64 0
+#endif
+
+#if !defined (MIPS_EABI)
+#define MIPS_EABI 0
+#endif
+
+#if !defined (TARGET_MONITOR_PROMPT)
+#define TARGET_MONITOR_PROMPT "<IDT>"
+#endif
+
+/* PC should be masked to remove possible MIPS16 flag */
+#if !defined (GDB_TARGET_MASK_DISAS_PC)
+#define GDB_TARGET_MASK_DISAS_PC(addr) UNMAKE_MIPS16_ADDR(addr)
+#endif
+#if !defined (GDB_TARGET_UNMASK_DISAS_PC)
+#define GDB_TARGET_UNMASK_DISAS_PC(addr) MAKE_MIPS16_ADDR(addr)
+#endif
+
+/* Floating point is IEEE compliant */
+#define IEEE_FLOAT
+
+/* The name of the usual type of MIPS processor that is in the target
+ system. */
+
+#define DEFAULT_MIPS_TYPE "generic"
+
+/* Remove useless bits from an instruction address. */
+
+#define ADDR_BITS_REMOVE(addr) mips_addr_bits_remove(addr)
+CORE_ADDR mips_addr_bits_remove PARAMS ((CORE_ADDR addr));
+
+/* Remove useless bits from the stack pointer. */
+
+#define TARGET_READ_SP() ADDR_BITS_REMOVE (read_register (SP_REGNUM))
+
+/* Offset from address of function to start of its code.
+ Zero on most machines. */
+
+#define FUNCTION_START_OFFSET 0
+
+/* Advance PC across any function entry prologue instructions
+ to reach some "real" code. */
+
+#define SKIP_PROLOGUE(pc) pc = mips_skip_prologue (pc, 0)
+extern CORE_ADDR mips_skip_prologue PARAMS ((CORE_ADDR addr, int lenient));
+
+/* Return non-zero if PC points to an instruction which will cause a step
+ to execute both the instruction at PC and an instruction at PC+4. */
+extern int mips_step_skips_delay PARAMS ((CORE_ADDR));
+#define STEP_SKIPS_DELAY_P (1)
+#define STEP_SKIPS_DELAY(pc) (mips_step_skips_delay (pc))
+
+/* Immediately after a function call, return the saved pc.
+ Can't always go through the frames for this because on some machines
+ the new frame is not set up until the new function executes
+ some instructions. */
+
+#define SAVED_PC_AFTER_CALL(frame) read_register(RA_REGNUM)
+
+/* Are we currently handling a signal */
+
+extern int in_sigtramp PARAMS ((CORE_ADDR, char *));
+#define IN_SIGTRAMP(pc, name) in_sigtramp(pc, name)
+
+/* Stack grows downward. */
+
+#define INNER_THAN(lhs,rhs) ((lhs) < (rhs))
+
+#define BIG_ENDIAN 4321
+
+/* BREAKPOINT_FROM_PC uses the program counter value to determine whether a
+ 16- or 32-bit breakpoint should be used. It returns a pointer
+ to a string of bytes that encode a breakpoint instruction, stores
+ the length of the string to *lenptr, and adjusts the pc (if necessary) to
+ point to the actual memory location where the breakpoint should be
+ inserted. */
+
+extern breakpoint_from_pc_fn mips_breakpoint_from_pc;
+#define BREAKPOINT_FROM_PC(pcptr, lenptr) mips_breakpoint_from_pc(pcptr, lenptr)
+
+/* Amount PC must be decremented by after a breakpoint.
+ This is often the number of bytes in BREAKPOINT
+ but not always. */
+
+#define DECR_PC_AFTER_BREAK 0
+
+/* Say how long (ordinary) registers are. This is a piece of bogosity
+ used in push_word and a few other places; REGISTER_RAW_SIZE is the
+ real way to know how big a register is. */
+
+#define REGISTER_SIZE 4
+
+/* The size of a register. This is predefined in tm-mips64.h. We
+ can't use REGISTER_SIZE because that is used for various other
+ things. */
+
+#ifndef MIPS_REGSIZE
+#define MIPS_REGSIZE 4
+#endif
+
+/* The sizes of floating point registers. */
+
+#define MIPS_FPU_SINGLE_REGSIZE 4
+#define MIPS_FPU_DOUBLE_REGSIZE 8
+
+/* Number of machine registers */
+
+#ifndef NUM_REGS
+#define NUM_REGS 90
+#endif
+
+/* Initializer for an array of names of registers.
+ There should be NUM_REGS strings in this initializer. */
+
+#ifndef REGISTER_NAMES
+#define REGISTER_NAMES \
+ { "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3", \
+ "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", \
+ "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", \
+ "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra", \
+ "sr", "lo", "hi", "bad", "cause","pc", \
+ "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", \
+ "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", \
+ "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",\
+ "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",\
+ "fsr", "fir", "fp", "", \
+ "", "", "", "", "", "", "", "", \
+ "", "", "", "", "", "", "", "", \
+ }
+#endif
+
+/* 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 ZERO_REGNUM 0 /* read-only register, always 0 */
+#define V0_REGNUM 2 /* Function integer return value */
+#define A0_REGNUM 4 /* Loc of first arg during a subr call */
+#if MIPS_EABI
+# define MIPS_LAST_ARG_REGNUM 11 /* EABI uses R4 through R11 for args */
+# define MIPS_NUM_ARG_REGS 8
+#else
+# define MIPS_LAST_ARG_REGNUM 7 /* old ABI uses R4 through R7 for args */
+# define MIPS_NUM_ARG_REGS 4
+#endif
+#define T9_REGNUM 25 /* Contains address of callee in PIC */
+#define SP_REGNUM 29 /* Contains address of top of stack */
+#define RA_REGNUM 31 /* Contains return address value */
+#define PS_REGNUM 32 /* Contains processor status */
+#define HI_REGNUM 34 /* Multiple/divide temp */
+#define LO_REGNUM 33 /* ... */
+#define BADVADDR_REGNUM 35 /* bad vaddr for addressing exception */
+#define CAUSE_REGNUM 36 /* describes last exception */
+#define PC_REGNUM 37 /* Contains program counter */
+#define FP0_REGNUM 38 /* Floating point register 0 (single float) */
+#define FPA0_REGNUM (FP0_REGNUM+12) /* First float argument register */
+#if MIPS_EABI /* EABI uses F12 through F19 for args */
+# define MIPS_LAST_FP_ARG_REGNUM (FP0_REGNUM+19)
+# define MIPS_NUM_FP_ARG_REGS 8
+#else /* old ABI uses F12 through F15 for args */
+# define MIPS_LAST_FP_ARG_REGNUM (FP0_REGNUM+15)
+# define MIPS_NUM_FP_ARG_REGS 4
+#endif
+#define FCRCS_REGNUM 70 /* FP control/status */
+#define FCRIR_REGNUM 71 /* FP implementation/revision */
+#define FP_REGNUM 72 /* Pseudo register that contains true address of executing stack frame */
+#define UNUSED_REGNUM 73 /* Never used, FIXME */
+#define FIRST_EMBED_REGNUM 74 /* First CP0 register for embedded use */
+#define PRID_REGNUM 89 /* Processor ID */
+#define LAST_EMBED_REGNUM 89 /* Last one */
+
+/* Define DO_REGISTERS_INFO() to do machine-specific formatting
+ of register dumps. */
+
+#define DO_REGISTERS_INFO(_regnum, fp) mips_do_registers_info(_regnum, fp)
+extern void mips_do_registers_info PARAMS ((int, int));
+
+/* Total amount of space needed to store our copies of the machine's
+ register state, the array `registers'. */
+
+#define REGISTER_BYTES (NUM_REGS*MIPS_REGSIZE)
+
+/* Index within `registers' of the first byte of the space for
+ register N. */
+
+#define REGISTER_BYTE(N) ((N) * MIPS_REGSIZE)
+
+/* Number of bytes of storage in the actual machine representation
+ for register N. */
+
+#define REGISTER_RAW_SIZE(N) REGISTER_VIRTUAL_SIZE(N)
+
+/* Number of bytes of storage in the program's representation
+ for register N. */
+
+#define REGISTER_VIRTUAL_SIZE(N) TYPE_LENGTH (REGISTER_VIRTUAL_TYPE (N))
+
+/* Largest value REGISTER_RAW_SIZE can have. */
+
+#define MAX_REGISTER_RAW_SIZE 8
+
+/* Largest value REGISTER_VIRTUAL_SIZE can have. */
+
+#define MAX_REGISTER_VIRTUAL_SIZE 8
+
+/* Return the GDB type object for the "standard" data type of data in
+ register N. */
+
+#ifndef REGISTER_VIRTUAL_TYPE
+#define REGISTER_VIRTUAL_TYPE(N) \
+ (((N) >= FP0_REGNUM && (N) < FP0_REGNUM+32) ? builtin_type_float \
+ : ((N) == 32 /*SR*/) ? builtin_type_uint32 \
+ : ((N) >= 70 && (N) <= 89) ? builtin_type_uint32 \
+ : builtin_type_int)
+#endif
+
+/* All mips targets store doubles in a register pair with the least
+ significant register in the lower numbered register.
+ If the target is big endian, double register values need conversion
+ between memory and register formats. */
+
+#define REGISTER_CONVERT_TO_TYPE(n, type, buffer) \
+ do {if (TARGET_BYTE_ORDER == BIG_ENDIAN \
+ && REGISTER_RAW_SIZE (n) == 4 \
+ && (n) >= FP0_REGNUM && (n) < FP0_REGNUM + 32 \
+ && TYPE_CODE(type) == TYPE_CODE_FLT \
+ && TYPE_LENGTH(type) == 8) { \
+ char __temp[4]; \
+ memcpy (__temp, ((char *)(buffer))+4, 4); \
+ memcpy (((char *)(buffer))+4, (buffer), 4); \
+ memcpy (((char *)(buffer)), __temp, 4); }} while (0)
+
+#define REGISTER_CONVERT_FROM_TYPE(n, type, buffer) \
+ do {if (TARGET_BYTE_ORDER == BIG_ENDIAN \
+ && REGISTER_RAW_SIZE (n) == 4 \
+ && (n) >= FP0_REGNUM && (n) < FP0_REGNUM + 32 \
+ && TYPE_CODE(type) == TYPE_CODE_FLT \
+ && TYPE_LENGTH(type) == 8) { \
+ char __temp[4]; \
+ memcpy (__temp, ((char *)(buffer))+4, 4); \
+ memcpy (((char *)(buffer))+4, (buffer), 4); \
+ memcpy (((char *)(buffer)), __temp, 4); }} while (0)
+
+/* Store the address of the place in which to copy the structure the
+ subroutine will return. Handled by mips_push_arguments. */
+
+#define STORE_STRUCT_RETURN(addr, sp) /**/
+
+/* Extract from an array REGBUF containing the (raw) register state
+ a function return value of type TYPE, and copy that, in virtual format,
+ into VALBUF. XXX floats */
+
+#define EXTRACT_RETURN_VALUE(TYPE,REGBUF,VALBUF) \
+ mips_extract_return_value(TYPE, REGBUF, VALBUF)
+extern void
+mips_extract_return_value PARAMS ((struct type *, char [], char *));
+
+/* Write into appropriate registers a function return value
+ of type TYPE, given in virtual format. */
+
+#define STORE_RETURN_VALUE(TYPE,VALBUF) \
+ mips_store_return_value(TYPE, VALBUF)
+extern void mips_store_return_value PARAMS ((struct type *, char *));
+
+/* 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). */
+/* The address is passed in a0 upon entry to the function, but when
+ the function exits, the compiler has copied the value to v0. This
+ convention is specified by the System V ABI, so I think we can rely
+ on it. */
+
+#define EXTRACT_STRUCT_VALUE_ADDRESS(REGBUF) \
+ (extract_address (REGBUF + REGISTER_BYTE (V0_REGNUM), \
+ REGISTER_RAW_SIZE (V0_REGNUM)))
+
+extern use_struct_convention_fn mips_use_struct_convention;
+#define USE_STRUCT_CONVENTION(gcc_p, type) mips_use_struct_convention (gcc_p, type)
+
+/* 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. */
+
+#define FRAME_CHAIN(thisframe) (CORE_ADDR) mips_frame_chain (thisframe)
+extern CORE_ADDR mips_frame_chain PARAMS ((struct frame_info *));
+
+/* Define other aspects of the stack frame. */
+
+
+/* A macro that tells us whether the function invocation represented
+ by FI does not have a frame on the stack associated with it. If it
+ does not, FRAMELESS is set to 1, else 0. */
+/* We handle this differently for mips, and maybe we should not */
+
+#define FRAMELESS_FUNCTION_INVOCATION(FI, FRAMELESS) {(FRAMELESS) = 0;}
+
+/* Saved Pc. */
+
+#define FRAME_SAVED_PC(FRAME) (mips_frame_saved_pc(FRAME))
+extern CORE_ADDR mips_frame_saved_pc PARAMS ((struct frame_info *));
+
+#define FRAME_ARGS_ADDRESS(fi) (fi)->frame
+
+#define FRAME_LOCALS_ADDRESS(fi) (fi)->frame
+
+/* Return number of args passed to a frame.
+ Can return -1, meaning no way to tell. */
+
+#define FRAME_NUM_ARGS(num, fi) (num = mips_frame_num_args(fi))
+extern int mips_frame_num_args PARAMS ((struct frame_info *));
+
+/* Return number of bytes at start of arglist that are not really args. */
+
+#define FRAME_ARGS_SKIP 0
+
+/* Put here the code to store, into a struct frame_saved_regs,
+ the addresses of the saved registers of frame described by FRAME_INFO.
+ This includes special registers such as pc and fp saved in special
+ ways in the stack frame. sp is even more special:
+ the address we return for it IS the sp for the next frame. */
+
+#define FRAME_INIT_SAVED_REGS(frame_info) \
+ do { \
+ if ((frame_info)->saved_regs == NULL) \
+ mips_find_saved_regs (frame_info); \
+ (frame_info)->saved_regs[SP_REGNUM] = (frame_info)->frame; \
+ } while (0)
+extern void mips_find_saved_regs PARAMS ((struct frame_info *));
+
+
+/* Things needed for making the inferior call functions. */
+
+/* Stack must be aligned on 32-bit boundaries when synthesizing
+ function calls. We don't need STACK_ALIGN, PUSH_ARGUMENTS will
+ handle it. */
+
+#define PUSH_ARGUMENTS(nargs, args, sp, struct_return, struct_addr) \
+ sp = mips_push_arguments((nargs), (args), (sp), (struct_return), (struct_addr))
+extern CORE_ADDR
+mips_push_arguments PARAMS ((int, struct value **, CORE_ADDR, int, CORE_ADDR));
+
+/* Push an empty stack frame, to record the current PC, etc. */
+
+#define PUSH_DUMMY_FRAME mips_push_dummy_frame()
+extern void mips_push_dummy_frame PARAMS ((void));
+
+/* Discard from the stack the innermost frame, restoring all registers. */
+
+#define POP_FRAME mips_pop_frame()
+extern void mips_pop_frame PARAMS ((void));
+
+#define CALL_DUMMY { 0 }
+
+#define CALL_DUMMY_START_OFFSET (0)
+
+#define CALL_DUMMY_BREAKPOINT_OFFSET (0)
+
+/* On Irix, $t9 ($25) contains the address of the callee (used for PIC).
+ It doesn't hurt to do this on other systems; $t9 will be ignored. */
+#define FIX_CALL_DUMMY(dummyname, start_sp, fun, nargs, args, rettype, gcc_p) \
+ write_register(T9_REGNUM, fun)
+
+#define CALL_DUMMY_LOCATION AT_ENTRY_POINT
+
+#define CALL_DUMMY_ADDRESS() (mips_call_dummy_address ())
+extern CORE_ADDR mips_call_dummy_address PARAMS ((void));
+
+/* There's a mess in stack frame creation. See comments in blockframe.c
+ near reference to INIT_FRAME_PC_FIRST. */
+
+#define INIT_FRAME_PC(fromleaf, prev) /* nada */
+
+#define INIT_FRAME_PC_FIRST(fromleaf, prev) \
+ mips_init_frame_pc_first(fromleaf, prev)
+extern void mips_init_frame_pc_first PARAMS ((int, struct frame_info *));
+
+/* Special symbol found in blocks associated with routines. We can hang
+ mips_extra_func_info_t's off of this. */
+
+#define MIPS_EFI_SYMBOL_NAME "__GDB_EFI_INFO__"
+extern void ecoff_relocate_efi PARAMS ((struct symbol *, CORE_ADDR));
+
+/* Specific information about a procedure.
+ This overlays the MIPS's PDR records,
+ mipsread.c (ab)uses this to save memory */
+
+typedef struct mips_extra_func_info {
+ long numargs; /* number of args to procedure (was iopt) */
+ bfd_vma high_addr; /* upper address bound */
+ long frame_adjust; /* offset of FP from SP (used on MIPS16) */
+ PDR pdr; /* Procedure descriptor record */
+} *mips_extra_func_info_t;
+
+#define EXTRA_FRAME_INFO \
+ mips_extra_func_info_t proc_desc; \
+ int num_args;
+
+#define INIT_EXTRA_FRAME_INFO(fromleaf, fci) init_extra_frame_info(fci)
+extern void init_extra_frame_info PARAMS ((struct frame_info *));
+
+#define PRINT_EXTRA_FRAME_INFO(fi) \
+ { \
+ if (fi && fi->proc_desc && fi->proc_desc->pdr.framereg < NUM_REGS) \
+ printf_filtered (" frame pointer is at %s+%d\n", \
+ REGISTER_NAME (fi->proc_desc->pdr.framereg), \
+ fi->proc_desc->pdr.frameoffset); \
+ }
+
+/* It takes two values to specify a frame on the MIPS.
+
+ In fact, the *PC* is the primary value that sets up a frame. The
+ PC is looked up to see what function it's in; symbol information
+ from that function tells us which register is the frame pointer
+ base, and what offset from there is the "virtual frame pointer".
+ (This is usually an offset from SP.) On most non-MIPS machines,
+ the primary value is the SP, and the PC, if needed, disambiguates
+ multiple functions with the same SP. But on the MIPS we can't do
+ that since the PC is not stored in the same part of the frame every
+ time. This does not seem to be a very clever way to set up frames,
+ but there is nothing we can do about that). */
+
+#define SETUP_ARBITRARY_FRAME(argc, argv) setup_arbitrary_frame (argc, argv)
+extern struct frame_info *setup_arbitrary_frame PARAMS ((int, CORE_ADDR *));
+
+/* Convert a dbx stab register number (from `r' declaration) to a gdb REGNUM */
+
+#define STAB_REG_TO_REGNUM(num) ((num) < 32 ? (num) : (num)+FP0_REGNUM-38)
+
+/* Convert a ecoff register number to a gdb REGNUM */
+
+#define ECOFF_REG_TO_REGNUM(num) ((num) < 32 ? (num) : (num)+FP0_REGNUM-32)
+
+/* If the current gcc for for this target does not produce correct debugging
+ information for float parameters, both prototyped and unprototyped, then
+ define this macro. This forces gdb to always assume that floats are
+ passed as doubles and then converted in the callee.
+
+ For the mips chip, it appears that the debug info marks the parameters as
+ floats regardless of whether the function is prototyped, but the actual
+ values are passed as doubles for the non-prototyped case and floats for
+ the prototyped case. Thus we choose to make the non-prototyped case work
+ for C and break the prototyped case, since the non-prototyped case is
+ probably much more common. (FIXME). */
+
+#define COERCE_FLOAT_TO_DOUBLE (current_language -> la_language == language_c)
+
+/* Select the default mips disassembler */
+
+#define TM_PRINT_INSN_MACH 0
+
+
+/* These are defined in mdebugread.c and are used in mips-tdep.c */
+extern CORE_ADDR sigtramp_address, sigtramp_end;
+extern void fixup_sigtramp PARAMS ((void));
+
+/* Defined in mips-tdep.c and used in remote-mips.c */
+extern char *mips_read_processor_type PARAMS ((void));
+
+/* Functions for dealing with MIPS16 call and return stubs. */
+#define IN_SOLIB_CALL_TRAMPOLINE(pc, name) mips_in_call_stub (pc, name)
+#define IN_SOLIB_RETURN_TRAMPOLINE(pc, name) mips_in_return_stub (pc, name)
+#define SKIP_TRAMPOLINE_CODE(pc) mips_skip_stub (pc)
+#define IGNORE_HELPER_CALL(pc) mips_ignore_helper (pc)
+extern int mips_in_call_stub PARAMS ((CORE_ADDR pc, char *name));
+extern int mips_in_return_stub PARAMS ((CORE_ADDR pc, char *name));
+extern CORE_ADDR mips_skip_stub PARAMS ((CORE_ADDR pc));
+extern int mips_ignore_helper PARAMS ((CORE_ADDR pc));
+
+#ifndef TARGET_MIPS
+#define TARGET_MIPS
+#endif
+
+/* Definitions and declarations used by mips-tdep.c and remote-mips.c */
+#define MIPS_INSTLEN 4 /* Length of an instruction */
+#define MIPS16_INSTLEN 2 /* Length of an instruction on MIPS16*/
+#define MIPS_NUMREGS 32 /* Number of integer or float registers */
+typedef unsigned long t_inst; /* Integer big enough to hold an instruction */
+
+/* MIPS16 function addresses are odd (bit 0 is set). Here are some
+ macros to test, set, or clear bit 0 of addresses. */
+#define IS_MIPS16_ADDR(addr) ((addr) & 1)
+#define MAKE_MIPS16_ADDR(addr) ((addr) | 1)
+#define UNMAKE_MIPS16_ADDR(addr) ((addr) & ~1)
+
+#endif /* TM_MIPS_H */
+
+/* Macros for setting and testing a bit in a minimal symbol that
+ marks it as 16-bit function. The MSB of the minimal symbol's
+ "info" field is used for this purpose. This field is already
+ being used to store the symbol size, so the assumption is
+ that the symbol size cannot exceed 2^31.
+
+ ELF_MAKE_MSYMBOL_SPECIAL
+ tests whether an ELF symbol is "special", i.e. refers
+ to a 16-bit function, and sets a "special" bit in a
+ minimal symbol to mark it as a 16-bit function
+ MSYMBOL_IS_SPECIAL tests the "special" bit in a minimal symbol
+ MSYMBOL_SIZE returns the size of the minimal symbol, i.e.
+ the "info" field with the "special" bit masked out
+*/
+
+#define ELF_MAKE_MSYMBOL_SPECIAL(sym,msym) \
+ { \
+ if (((elf_symbol_type *)(sym))->internal_elf_sym.st_other == STO_MIPS16) { \
+ MSYMBOL_INFO (msym) = (char *) (((long) MSYMBOL_INFO (msym)) | 0x80000000); \
+ SYMBOL_VALUE_ADDRESS (msym) |= 1; \
+ } \
+ }
+
+#define MSYMBOL_IS_SPECIAL(msym) \
+ (((long) MSYMBOL_INFO (msym) & 0x80000000) != 0)
+#define MSYMBOL_SIZE(msym) \
+ ((long) MSYMBOL_INFO (msym) & 0x7fffffff)
diff --git a/gdb/config/mips/tm-mips64.h b/gdb/config/mips/tm-mips64.h
new file mode 100644
index 00000000000..56a8927314d
--- /dev/null
+++ b/gdb/config/mips/tm-mips64.h
@@ -0,0 +1,54 @@
+/* Target machine parameters for MIPS r4000
+ Copyright 1994, 1996 Free Software Foundation, Inc.
+ Contributed by Ian Lance Taylor (ian@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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define GDB_TARGET_IS_MIPS64 1
+
+/* Use eight byte registers. */
+#define MIPS_REGSIZE 8
+
+/* define 8 byte register type */
+#define REGISTER_VIRTUAL_TYPE(N) \
+ (((N) >= FP0_REGNUM && (N) < FP0_REGNUM+32) ? builtin_type_double \
+ : ((N) == 32 /*SR*/) ? builtin_type_uint32 \
+ : ((N) >= 70 && (N) <= 89) ? builtin_type_uint32 \
+ : builtin_type_long_long)
+
+/* Load double words in CALL_DUMMY. */
+#define OP_LDFPR 065 /* ldc1 */
+#define OP_LDGPR 067 /* ld */
+
+#if defined(MIPS_EABI) && (MIPS_EABI != 0)
+/* Define sizes for 64-bit data types, allow specific targets to override
+ these values. Doing so may violate the strict EABI, but it's necessary
+ for some MIPS III and MIPS IV machines that want 64bit longs, but 32bit
+ pointers. */
+#ifndef TARGET_LONG_BIT
+#define TARGET_LONG_BIT 64
+#endif
+#ifndef TARGET_LONG_LONG_BIT
+#define TARGET_LONG_LONG_BIT 64
+#endif
+#ifndef TARGET_PTR_BIT
+#define TARGET_PTR_BIT 64
+#endif
+#endif /* MIPS_EABI */
+
+/* Get the basic MIPS definitions. */
+#include "tm-mips.h"
diff --git a/gdb/config/mips/tm-mipsm3.h b/gdb/config/mips/tm-mipsm3.h
new file mode 100644
index 00000000000..f73660479ff
--- /dev/null
+++ b/gdb/config/mips/tm-mipsm3.h
@@ -0,0 +1,66 @@
+/* Definitions to make GDB run on a mips box under Mach 3.0
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Mach specific definitions for little endian mips (e.g. pmax)
+ * running Mach 3.0
+ *
+ * Author: Jukka Virtanen <jtv@hut.fi>
+ */
+
+/* Include common definitions for Mach3 systems */
+#include "nm-m3.h"
+
+/* Define offsets to access CPROC stack when it does not have
+ * a kernel thread.
+ */
+
+/* From mk/user/threads/mips/csw.s */
+#define SAVED_FP (12*4)
+#define SAVED_PC (13*4)
+#define SAVED_BYTES (14*4)
+
+/* Using these, define our offsets to items strored in
+ * cproc_switch in csw.s
+ */
+#define MACHINE_CPROC_SP_OFFSET SAVED_BYTES
+#define MACHINE_CPROC_PC_OFFSET SAVED_PC
+#define MACHINE_CPROC_FP_OFFSET SAVED_FP
+
+/* Thread flavors used in setting the Trace state.
+ *
+ * In <mach/machine/thread_status.h>
+ */
+#define TRACE_FLAVOR MIPS_EXC_STATE
+#define TRACE_FLAVOR_SIZE MIPS_EXC_STATE_COUNT
+#define TRACE_SET(x,state) ((struct mips_exc_state *)state)->cause = EXC_SST;
+#define TRACE_CLEAR(x,state) 0
+
+/* Mach supports attach/detach */
+#define ATTACH_DETACH 1
+
+#include "mips/tm-mips.h"
+
+/* Address of end of user stack space.
+ * for MACH, see <machine/vmparam.h>
+ */
+#undef STACK_END_ADDR
+#define STACK_END_ADDR USRSTACK
+
+/* Output registers in tabular format */
+#define TABULAR_REGISTER_OUTPUT
diff --git a/gdb/config/mips/tm-mipsv4.h b/gdb/config/mips/tm-mipsv4.h
new file mode 100644
index 00000000000..dd7aaa16d9b
--- /dev/null
+++ b/gdb/config/mips/tm-mipsv4.h
@@ -0,0 +1,45 @@
+/* Target machine description for MIPS running SVR4, for GDB.
+ Copyright 1994, 1995 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "mips/tm-bigmips.h"
+#include "tm-sysv4.h"
+
+/* When calling functions on a MIPS SVR4 ABI compliant platform
+ $25 must hold the function address. Dest_Reg is a macro
+ used in CALL_DUMMY in tm-mips.h. */
+#undef Dest_Reg
+#define Dest_Reg 25
+
+/* The signal handler trampoline is called _sigtramp. */
+#undef IN_SIGTRAMP
+#define IN_SIGTRAMP(pc, name) ((name) && STREQ ("_sigtramp", name))
+
+/* On entry to the signal handler trampoline, an ucontext is already
+ pushed on the stack. We can get at the saved registers via the
+ mcontext which is contained within the ucontext. */
+#define SIGFRAME_BASE 0
+#define SIGFRAME_REGSAVE_OFF (SIGFRAME_BASE + 40)
+#define SIGFRAME_PC_OFF (SIGFRAME_BASE + 40 + 35 * 4)
+#define SIGFRAME_FPREGSAVE_OFF (SIGFRAME_BASE + 40 + 36 * 4)
+
+/* Use the alternate method of determining valid frame chains. */
+#define FRAME_CHAIN_VALID(fp,fi) alternate_frame_chain_valid (fp, fi)
+
+/* Convert a DWARF register number to a gdb REGNUM. */
+#define DWARF_REG_TO_REGNUM(num) ((num) < 32 ? (num) : (num)+FP0_REGNUM-32)
diff --git a/gdb/config/mips/tm-tx39.h b/gdb/config/mips/tm-tx39.h
new file mode 100644
index 00000000000..ee99a282259
--- /dev/null
+++ b/gdb/config/mips/tm-tx39.h
@@ -0,0 +1,39 @@
+/* Copyright (C) 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define TARGET_BYTE_ORDER_SELECTABLE_P 1
+#define MIPS_EABI 1
+#define MIPS_DEFAULT_FPU_TYPE MIPS_FPU_NONE
+
+#include "mips/tm-bigmips.h"
+
+#undef REGISTER_NAMES
+#define REGISTER_NAMES \
+ { "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3", \
+ "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", \
+ "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", \
+ "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra", \
+ "sr", "lo", "hi", "bad", "cause","pc", \
+ "", "", "", "", "", "", "", "", \
+ "", "", "", "", "", "", "", "", \
+ "", "", "", "", "", "", "", "", \
+ "", "", "", "", "", "", "", "", \
+ "", "", "", "", \
+ "", "", "", "", "", "", "", "", \
+ "", "", "config", "cache", "debug", "depc", "epc", "" \
+ }
diff --git a/gdb/config/mips/tm-tx39l.h b/gdb/config/mips/tm-tx39l.h
new file mode 100644
index 00000000000..8ceec7296ea
--- /dev/null
+++ b/gdb/config/mips/tm-tx39l.h
@@ -0,0 +1,39 @@
+/* Copyright (C) 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define TARGET_BYTE_ORDER_SELECTABLE_P 1
+#define MIPS_EABI 1
+#define MIPS_DEFAULT_FPU_TYPE MIPS_FPU_NONE
+
+#include "mips/tm-mips.h"
+
+#undef REGISTER_NAMES
+#define REGISTER_NAMES \
+ { "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3", \
+ "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", \
+ "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", \
+ "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra", \
+ "sr", "lo", "hi", "bad", "cause","pc", \
+ "", "", "", "", "", "", "", "", \
+ "", "", "", "", "", "", "", "", \
+ "", "", "", "", "", "", "", "", \
+ "", "", "", "", "", "", "", "", \
+ "", "", "", "", \
+ "", "", "", "", "", "", "", "", \
+ "", "", "config", "cache", "debug", "depc", "epc", "" \
+ }
diff --git a/gdb/config/mips/tm-vr4100.h b/gdb/config/mips/tm-vr4100.h
new file mode 100644
index 00000000000..843f49c2222
--- /dev/null
+++ b/gdb/config/mips/tm-vr4100.h
@@ -0,0 +1,25 @@
+/* Copyright (C) 1998 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define TARGET_BYTE_ORDER_SELECTABLE_P 1
+#define MIPS_EABI 1
+#define MIPS_DEFAULT_FPU_TYPE MIPS_FPU_NONE
+#define TARGET_MONITOR_PROMPT "<RISQ> "
+#define TARGET_PTR_BIT 64
+
+#include "mips/tm-bigmips64.h"
diff --git a/gdb/config/mips/tm-vr4300.h b/gdb/config/mips/tm-vr4300.h
new file mode 100644
index 00000000000..541ca44611d
--- /dev/null
+++ b/gdb/config/mips/tm-vr4300.h
@@ -0,0 +1,22 @@
+/* Copyright (C) 1993, 1996 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define TARGET_BYTE_ORDER_SELECTABLE_P 1
+#define TARGET_MONITOR_PROMPT "<RISQ> "
+
+#include "mips/tm-bigmips64.h"
diff --git a/gdb/config/mips/tm-vr4300el.h b/gdb/config/mips/tm-vr4300el.h
new file mode 100644
index 00000000000..75e8693dfbb
--- /dev/null
+++ b/gdb/config/mips/tm-vr4300el.h
@@ -0,0 +1,22 @@
+/* Copyright (C) 1993, 1996 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define TARGET_BYTE_ORDER_SELECTABLE_P 1
+#define TARGET_MONITOR_PROMPT "<RISQ> "
+
+#include "mips/tm-mips64.h"
diff --git a/gdb/config/mips/tm-vr5000.h b/gdb/config/mips/tm-vr5000.h
new file mode 100644
index 00000000000..b834a7762fc
--- /dev/null
+++ b/gdb/config/mips/tm-vr5000.h
@@ -0,0 +1,23 @@
+/* Copyright (C) 1996 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define TARGET_BYTE_ORDER_SELECTABLE_P 1
+#define TARGET_MONITOR_PROMPT "<RISQ> "
+#define MIPS_EABI 1
+
+#include "mips/tm-bigmips64.h"
diff --git a/gdb/config/mips/tm-vr5000el.h b/gdb/config/mips/tm-vr5000el.h
new file mode 100644
index 00000000000..c6897d12ee1
--- /dev/null
+++ b/gdb/config/mips/tm-vr5000el.h
@@ -0,0 +1,23 @@
+/* Copyright (C) 1996 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define TARGET_BYTE_ORDER_SELECTABLE_P 1
+#define TARGET_MONITOR_PROMPT "<RISQ> "
+#define MIPS_EABI 1
+
+#include "mips/tm-mips64.h"
diff --git a/gdb/config/mips/tm-vxmips.h b/gdb/config/mips/tm-vxmips.h
new file mode 100644
index 00000000000..392a929c200
--- /dev/null
+++ b/gdb/config/mips/tm-vxmips.h
@@ -0,0 +1,31 @@
+/* Target machine description for VxWorks MIPS's, for GDB, the GNU debugger.
+ Copyright 1996 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define GDBINIT_FILENAME ".vxgdbinit"
+
+#define DEFAULT_PROMPT "(vxgdb) "
+
+#include "mips/tm-mips.h"
+
+/* FIXME: These are almost certainly wrong. */
+
+/* Number of registers in a ptrace_getregs call. */
+
+#define VX_NUM_REGS (NUM_REGS)
diff --git a/gdb/config/mips/tx39.mt b/gdb/config/mips/tx39.mt
new file mode 100644
index 00000000000..8b4c1a92c24
--- /dev/null
+++ b/gdb/config/mips/tx39.mt
@@ -0,0 +1,5 @@
+# Target: Big-endian mips board, typically an IDT.
+TDEPFILES= mips-tdep.o remote-mips.o dve3900-rom.o monitor.o dsrec.o
+TM_FILE= tm-tx39.h
+SIM_OBS = remote-sim.o
+SIM = ../sim/mips/libsim.a
diff --git a/gdb/config/mips/tx39l.mt b/gdb/config/mips/tx39l.mt
new file mode 100644
index 00000000000..35083293d45
--- /dev/null
+++ b/gdb/config/mips/tx39l.mt
@@ -0,0 +1,5 @@
+# Target: Big-endian mips board, typically an IDT.
+TDEPFILES= mips-tdep.o remote-mips.o dve3900-rom.o monitor.o dsrec.o
+TM_FILE= tm-tx39l.h
+SIM_OBS = remote-sim.o
+SIM = ../sim/mips/libsim.a
diff --git a/gdb/config/mips/vr4100.mt b/gdb/config/mips/vr4100.mt
new file mode 100644
index 00000000000..c5ae4f94a6d
--- /dev/null
+++ b/gdb/config/mips/vr4100.mt
@@ -0,0 +1,5 @@
+# Target: Big-endian SIM monitor board.
+TDEPFILES= mips-tdep.o remote-mips.o
+TM_FILE= tm-vr4100.h
+SIM_OBS = remote-sim.o
+SIM = ../sim/mips/libsim.a
diff --git a/gdb/config/mips/vr4300.mt b/gdb/config/mips/vr4300.mt
new file mode 100644
index 00000000000..22cb25eb425
--- /dev/null
+++ b/gdb/config/mips/vr4300.mt
@@ -0,0 +1,5 @@
+# Target: Big-endian SIM monitor board.
+TDEPFILES= mips-tdep.o remote-mips.o
+TM_FILE= tm-vr4300.h
+SIM_OBS = remote-sim.o
+SIM = ../sim/mips/libsim.a
diff --git a/gdb/config/mips/vr4300el.mt b/gdb/config/mips/vr4300el.mt
new file mode 100644
index 00000000000..cff7241597b
--- /dev/null
+++ b/gdb/config/mips/vr4300el.mt
@@ -0,0 +1,5 @@
+# Target: Little-endian SIM monitor board.
+TDEPFILES= mips-tdep.o remote-mips.o
+TM_FILE= tm-vr4300el.h
+SIM_OBS = remote-sim.o
+SIM = ../sim/mips/libsim.a
diff --git a/gdb/config/mips/vr5000.mt b/gdb/config/mips/vr5000.mt
new file mode 100644
index 00000000000..316c548de09
--- /dev/null
+++ b/gdb/config/mips/vr5000.mt
@@ -0,0 +1,7 @@
+# Target: Big-endian SIM monitor board.
+TDEPFILES= mips-tdep.o remote-mips.o
+TM_FILE= tm-vr5000.h
+SIM_OBS = remote-sim.o
+SIM = ../sim/mips/libsim.a
+GDBSERVER_DEPFILES= low-sim.o
+GDBSERVER_LIBS = ../../sim/mips/libsim.a ../../bfd/libbfd.a ../../libiberty/libiberty.a -lm
diff --git a/gdb/config/mips/vr5000el.mt b/gdb/config/mips/vr5000el.mt
new file mode 100644
index 00000000000..99687edcefc
--- /dev/null
+++ b/gdb/config/mips/vr5000el.mt
@@ -0,0 +1,5 @@
+# Target: Little-endian SIM monitor board.
+TDEPFILES= mips-tdep.o remote-mips.o
+TM_FILE= tm-vr5000el.h
+SIM_OBS = remote-sim.o
+SIM = ../sim/mips/libsim.a
diff --git a/gdb/config/mips/vxmips.mt b/gdb/config/mips/vxmips.mt
new file mode 100644
index 00000000000..a20cf96ab72
--- /dev/null
+++ b/gdb/config/mips/vxmips.mt
@@ -0,0 +1,3 @@
+# Target: MIPS running VxWorks
+TDEPFILES= mips-tdep.o remote-vx.o remote-vxmips.o xdr_ld.o xdr_ptrace.o xdr_rdb.o
+TM_FILE= tm-vxmips.h
diff --git a/gdb/config/mips/xm-irix3.h b/gdb/config/mips/xm-irix3.h
new file mode 100644
index 00000000000..d096594c6be
--- /dev/null
+++ b/gdb/config/mips/xm-irix3.h
@@ -0,0 +1,31 @@
+/* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* This is for the iris. */
+
+#define HAVE_TERMIO
+
+#define HOST_BYTE_ORDER BIG_ENDIAN
+
+/* Override register locations in upage for SGI machines */
+#undef REGISTER_U_ADDR
+#define REGISTER_U_ADDR(addr, blockend, regno) \
+ if (regno < PC_REGNUM) \
+ addr = regno; \
+ else \
+ addr = regno + NSIG_HNDLRS; /* Skip over signal handlers */
diff --git a/gdb/config/mips/xm-irix4.h b/gdb/config/mips/xm-irix4.h
new file mode 100644
index 00000000000..14d21f04fea
--- /dev/null
+++ b/gdb/config/mips/xm-irix4.h
@@ -0,0 +1,33 @@
+/* Definitions for irix4 hosting support.
+
+Copyright (C) 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* This is for the iris. */
+
+#include "mips/xm-irix3.h"
+
+#define BROKEN_SIGINFO_H /* <sys/siginfo.h> si_pid & si_uid are bogus */
+
+/* Irix 4.0.1 and later have termios. Not sure about earlier versions. */
+#undef HAVE_TERMIO
+#define HAVE_TERMIOS
+
+/* This enables reliable signals (and the associated setjmp/longjmp), and gives
+ bsdish prototypes for getpgrp/setpgrg/setgroups and initgroups. */
+#define _BSD_COMPAT
diff --git a/gdb/config/mips/xm-irix5.h b/gdb/config/mips/xm-irix5.h
new file mode 100644
index 00000000000..a64277b3142
--- /dev/null
+++ b/gdb/config/mips/xm-irix5.h
@@ -0,0 +1,35 @@
+/* Definitions for irix5 hosting support.
+
+Copyright (C) 1993, 1996 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "xm-sysv4.h"
+
+#define HOST_BYTE_ORDER BIG_ENDIAN
+
+/* Override register locations in upage for SGI machines */
+#undef REGISTER_U_ADDR
+#define REGISTER_U_ADDR(addr, blockend, regno) \
+ if (regno < PC_REGNUM) \
+ addr = regno; \
+ else \
+ addr = regno + NSIG_HNDLRS; /* Skip over signal handlers */
+
+/* This enables reliable signals (and the associated setjmp/longjmp), and gives
+ bsdish prototypes for getpgrp/setpgrg/setgroups and initgroups. */
+#define _BSD_COMPAT
diff --git a/gdb/config/mips/xm-mips.h b/gdb/config/mips/xm-mips.h
new file mode 100644
index 00000000000..a2e9a509915
--- /dev/null
+++ b/gdb/config/mips/xm-mips.h
@@ -0,0 +1,61 @@
+/* Definitions to make GDB run on a mips box under 4.3bsd.
+ Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
+ Contributed by Per Bothner(bothner@cs.wisc.edu) at U.Wisconsin
+ and by Alessandro Forin(af@cs.cmu.edu) at CMU
+
+This file is part of GDB.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#if !defined (HOST_BYTE_ORDER)
+#define HOST_BYTE_ORDER LITTLE_ENDIAN
+#endif
+
+#ifdef ultrix
+/* Needed for DECstation core files. */
+#include <machine/param.h>
+#define KERNEL_U_ADDR UADDR
+
+/* Native Ultrix cc has broken long long support. */
+#ifndef __GNUC__
+#undef CC_HAS_LONG_LONG
+#endif
+#endif
+
+#if ! defined (__STDC__) && ! defined (offsetof)
+# define offsetof(TYPE, MEMBER) ((unsigned long) &((TYPE *)0)->MEMBER)
+#endif
+
+/* Only used for core files on DECstations.
+ First four registers at u.u_ar0 are saved arguments, and
+ there is no r0 saved. Float registers are saved
+ in u_pcb.pcb_fpregs, not relative to u.u_ar0. */
+
+#define REGISTER_U_ADDR(addr, blockend, regno) \
+ { \
+ if (regno < FP0_REGNUM) \
+ addr = blockend + sizeof(int) * (4 + regno - 1); \
+ else \
+ addr = offsetof (struct user, u_pcb.pcb_fpregs[0]) + \
+ sizeof (int) * (regno - FP0_REGNUM); \
+ }
+
+/* Kernel is a bit tenacious about sharing text segments, disallowing bpts. */
+#define ONE_PROCESS_WRITETEXT
+
+/* HAVE_SGTTY also works, last we tried.
+
+ But we have termios, at least as of Ultrix 4.2A, so use it. */
+#define HAVE_TERMIOS
diff --git a/gdb/config/mips/xm-mipsm3.h b/gdb/config/mips/xm-mipsm3.h
new file mode 100644
index 00000000000..6a5a73cd833
--- /dev/null
+++ b/gdb/config/mips/xm-mipsm3.h
@@ -0,0 +1,32 @@
+/* Definitions to make GDB run on a mips box under 4.3bsd.
+ Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
+ Contributed by Per Bothner(bothner@cs.wisc.edu) at U.Wisconsin
+ and by Alessandro Forin(af@cs.cmu.edu) at CMU
+
+This file is part of GDB.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#if !defined (HOST_BYTE_ORDER)
+#define HOST_BYTE_ORDER LITTLE_ENDIAN
+#endif
+
+#define KERNEL_U_ADDR 0 /* Not needed. */
+
+/* Only used for core files on DECstations. */
+
+#define REGISTER_U_ADDR(addr, blockend, regno) \
+ if (regno < 38) addr = (NBPG*UPAGES) + (regno - 38)*sizeof(int);\
+ else addr = 0; /* ..somewhere in the pcb */
diff --git a/gdb/config/mips/xm-mipsv4.h b/gdb/config/mips/xm-mipsv4.h
new file mode 100644
index 00000000000..d80ba433e29
--- /dev/null
+++ b/gdb/config/mips/xm-mipsv4.h
@@ -0,0 +1,23 @@
+/* Definitions for MIPS running SVR4 hosting support.
+
+Copyright (C) 1994 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "xm-sysv4.h"
+
+#define HOST_BYTE_ORDER BIG_ENDIAN
diff --git a/gdb/config/mips/xm-news-mips.h b/gdb/config/mips/xm-news-mips.h
new file mode 100644
index 00000000000..06aac1ad3b7
--- /dev/null
+++ b/gdb/config/mips/xm-news-mips.h
@@ -0,0 +1,24 @@
+/* Definitions to make GDB run on a mips box under 4.3bsd.
+ Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
+ Contributed by Per Bothner(bothner@cs.wisc.edu) at U.Wisconsin
+ and by Alessandro Forin(af@cs.cmu.edu) at CMU
+
+This file is part of GDB.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#if !defined (HOST_BYTE_ORDER)
+#define HOST_BYTE_ORDER BIG_ENDIAN
+#endif
diff --git a/gdb/config/mips/xm-riscos.h b/gdb/config/mips/xm-riscos.h
new file mode 100644
index 00000000000..467f32ac11b
--- /dev/null
+++ b/gdb/config/mips/xm-riscos.h
@@ -0,0 +1,28 @@
+/* Copyright (C) 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define HAVE_TERMIO
+
+#if !defined (HOST_BYTE_ORDER)
+#define HOST_BYTE_ORDER BIG_ENDIAN
+#endif
+
+#define USG 1
+
+/* setjmp.h requires uid_t. */
+#include <sys/types.h>
diff --git a/gdb/config/mn10200/mn10200.mt b/gdb/config/mn10200/mn10200.mt
new file mode 100644
index 00000000000..c85a2fb6884
--- /dev/null
+++ b/gdb/config/mn10200/mn10200.mt
@@ -0,0 +1,6 @@
+# Target: Matsushita mn10200
+TDEPFILES= mn10200-tdep.o
+TM_FILE= tm-mn10200.h
+
+SIM_OBS = remote-sim.o
+SIM = ../sim/mn10200/libsim.a
diff --git a/gdb/config/mn10200/tm-mn10200.h b/gdb/config/mn10200/tm-mn10200.h
new file mode 100644
index 00000000000..671b53473fc
--- /dev/null
+++ b/gdb/config/mn10200/tm-mn10200.h
@@ -0,0 +1,212 @@
+/* Parameters for execution on a Matsushita mn10200 processor.
+ Copyright 1997 Free Software Foundation, Inc.
+
+ Contributed by Geoffrey Noer <noer@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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* The mn10200 is little endian. */
+#define TARGET_BYTE_ORDER LITTLE_ENDIAN
+
+/* ints are only 16bits on the mn10200. */
+#undef TARGET_INT_BIT
+#define TARGET_INT_BIT 16
+
+/* The mn10200 doesn't support long long types. */
+#undef TARGET_LONG_LONG_BIT
+#define TARGET_LONG_LONG_BIT 32
+
+/* The mn10200 doesn't support double or long double either. */
+#undef TARGET_DOUBLE_BIT
+#undef TARGET_LONG_DOUBLE_BIT
+#define TARGET_DOUBLE_BIT 32
+#define TARGET_LONG_DOUBLE_BIT 32
+
+/* Not strictly correct, but the machine independent code is not
+ ready to handle any of the basic sizes not being a power of two. */
+#undef TARGET_PTR_BIT
+#define TARGET_PTR_BIT 32
+
+/* The mn10200 really has 24 bit registers but the simulator reads/writes
+ them as 32bit values, so we claim they're 32bits each. This may have
+ to be tweaked if the Matsushita emulator/board really deals with them
+ as 24bits each. */
+#define REGISTER_SIZE 4
+
+#define MAX_REGISTER_RAW_SIZE REGISTER_SIZE
+#define NUM_REGS 11
+
+#define REGISTER_BYTES (NUM_REGS * REGISTER_SIZE)
+
+#define REGISTER_NAMES \
+{ "d0", "d1", "d2", "d3", "a0", "a1", "a2", "sp", \
+ "pc", "mdr", "psw"}
+
+#define FP_REGNUM 6
+#define SP_REGNUM 7
+#define PC_REGNUM 8
+#define MDR_REGNUM 9
+#define PSW_REGNUM 10
+
+/* Treat the registers as 32bit values. */
+#define REGISTER_VIRTUAL_TYPE(REG) builtin_type_long
+
+#define REGISTER_BYTE(REG) ((REG) * REGISTER_SIZE)
+#define REGISTER_VIRTUAL_SIZE(REG) REGISTER_SIZE
+#define REGISTER_RAW_SIZE(REG) REGISTER_SIZE
+
+#define MAX_REGISTER_VIRTUAL_SIZE REGISTER_SIZE
+
+/* The breakpoint instruction must be the same size as te smallest
+ instruction in the instruction set.
+
+ The Matsushita mn10x00 processors have single byte instructions
+ so we need a single byte breakpoint. Matsushita hasn't defined
+ one, so we defined it ourselves.
+
+ 0xff is the only available single byte insn left on the mn10200. */
+#define BREAKPOINT {0xff}
+
+#define FUNCTION_START_OFFSET 0
+
+#define DECR_PC_AFTER_BREAK 0
+
+/* Stacks grow the normal way. */
+#define INNER_THAN(lhs,rhs) ((lhs) < (rhs))
+
+#define SAVED_PC_AFTER_CALL(frame) \
+ (read_memory_integer (read_register (SP_REGNUM), REGISTER_SIZE) & 0xffffff)
+
+#ifdef __STDC__
+struct frame_info;
+struct frame_saved_regs;
+struct type;
+struct value;
+#endif
+
+#define EXTRA_FRAME_INFO struct frame_saved_regs fsr; int status; int stack_size;
+
+extern void mn10200_init_extra_frame_info PARAMS ((struct frame_info *));
+#define INIT_EXTRA_FRAME_INFO(fromleaf, fi) mn10200_init_extra_frame_info (fi)
+#define INIT_FRAME_PC(x,y)
+
+extern void mn10200_frame_find_saved_regs PARAMS ((struct frame_info *,
+ struct frame_saved_regs *));
+#define FRAME_FIND_SAVED_REGS(fi, regaddr) regaddr = fi->fsr
+
+extern CORE_ADDR mn10200_frame_chain PARAMS ((struct frame_info *));
+#define FRAME_CHAIN(fi) mn10200_frame_chain (fi)
+#define FRAME_CHAIN_VALID(FP, FI) generic_frame_chain_valid (FP, FI)
+
+extern CORE_ADDR mn10200_find_callers_reg PARAMS ((struct frame_info *, int));
+extern CORE_ADDR mn10200_frame_saved_pc PARAMS ((struct frame_info *));
+#define FRAME_SAVED_PC(FI) (mn10200_frame_saved_pc (FI))
+
+/* Extract from an array REGBUF containing the (raw) register state
+ a function return value of type TYPE, and copy that, in virtual format,
+ into VALBUF. */
+
+#define EXTRACT_RETURN_VALUE(TYPE, REGBUF, VALBUF) \
+ { \
+ if (TYPE_LENGTH (TYPE) > 8) \
+ abort (); \
+ else if (TYPE_LENGTH (TYPE) > 2 && TYPE_CODE (TYPE) != TYPE_CODE_PTR) \
+ { \
+ memcpy (VALBUF, REGBUF + REGISTER_BYTE (0), 2); \
+ memcpy (VALBUF + 2, REGBUF + REGISTER_BYTE (1), 2); \
+ } \
+ else if (TYPE_CODE (TYPE) == TYPE_CODE_PTR)\
+ { \
+ memcpy (VALBUF, REGBUF + REGISTER_BYTE (4), TYPE_LENGTH (TYPE)); \
+ } \
+ else \
+ { \
+ memcpy (VALBUF, REGBUF + REGISTER_BYTE (0), TYPE_LENGTH (TYPE)); \
+ } \
+ }
+
+#define EXTRACT_STRUCT_VALUE_ADDRESS(REGBUF) \
+ extract_address (REGBUF + REGISTER_BYTE (4), \
+ REGISTER_RAW_SIZE (4))
+
+#define STORE_RETURN_VALUE(TYPE, VALBUF) \
+ { \
+ if (TYPE_LENGTH (TYPE) > 8) \
+ abort (); \
+ else if (TYPE_LENGTH (TYPE) > 2 && TYPE_CODE (TYPE) != TYPE_CODE_PTR) \
+ { \
+ write_register_bytes (REGISTER_BYTE (0), VALBUF, 2); \
+ write_register_bytes (REGISTER_BYTE (1), VALBUF + 2, 2); \
+ } \
+ else if (TYPE_CODE (TYPE) == TYPE_CODE_PTR)\
+ { \
+ write_register_bytes (REGISTER_BYTE (4), VALBUF, TYPE_LENGTH (TYPE)); \
+ } \
+ else \
+ { \
+ write_register_bytes (REGISTER_BYTE (0), VALBUF, TYPE_LENGTH (TYPE)); \
+ } \
+ }
+
+#define STORE_STRUCT_RETURN(STRUCT_ADDR, SP) \
+ (SP) = mn10200_store_struct_return (STRUCT_ADDR, SP)
+
+extern CORE_ADDR mn10200_skip_prologue PARAMS ((CORE_ADDR));
+#define SKIP_PROLOGUE(pc) pc = mn10200_skip_prologue (pc)
+
+#define FRAME_ARGS_SKIP 0
+
+#define FRAME_ARGS_ADDRESS(fi) ((fi)->frame)
+#define FRAME_LOCALS_ADDRESS(fi) ((fi)->frame)
+#define FRAME_NUM_ARGS(val, fi) ((val) = -1)
+
+extern void mn10200_pop_frame PARAMS ((struct frame_info *));
+#define POP_FRAME mn10200_pop_frame (get_current_frame ())
+
+#define USE_GENERIC_DUMMY_FRAMES
+#define CALL_DUMMY {0}
+#define CALL_DUMMY_START_OFFSET (0)
+#define CALL_DUMMY_BREAKPOINT_OFFSET (0)
+#define CALL_DUMMY_LOCATION AT_ENTRY_POINT
+#define FIX_CALL_DUMMY(DUMMY, START, FUNADDR, NARGS, ARGS, TYPE, GCCP)
+#define CALL_DUMMY_ADDRESS() entry_point_address ()
+
+extern CORE_ADDR mn10200_push_return_address PARAMS ((CORE_ADDR, CORE_ADDR));
+#define PUSH_RETURN_ADDRESS(PC, SP) mn10200_push_return_address (PC, SP)
+
+#define PUSH_DUMMY_FRAME generic_push_dummy_frame ()
+
+extern CORE_ADDR
+mn10200_push_arguments PARAMS ((int, struct value **, CORE_ADDR,
+ unsigned char, CORE_ADDR));
+#define PUSH_ARGUMENTS(NARGS, ARGS, SP, STRUCT_RETURN, STRUCT_ADDR) \
+ (SP) = mn10200_push_arguments (NARGS, ARGS, SP, STRUCT_RETURN, STRUCT_ADDR)
+
+#define PC_IN_CALL_DUMMY(PC, SP, FP) generic_pc_in_call_dummy (PC, SP)
+
+#define REG_STRUCT_HAS_ADDR(gcc_p,TYPE) \
+ (TYPE_LENGTH (TYPE) > 8)
+
+extern use_struct_convention_fn mn10200_use_struct_convention;
+#define USE_STRUCT_CONVENTION(GCC_P, TYPE) mn10200_use_struct_convention (GCC_P, TYPE)
+
+/* Override the default get_saved_register function with
+ one that takes account of generic CALL_DUMMY frames. */
+#define GET_SAVED_REGISTER
+
+/* Define this for Wingdb */
+#define TARGET_MN10200
diff --git a/gdb/config/mn10300/mn10300.mt b/gdb/config/mn10300/mn10300.mt
new file mode 100644
index 00000000000..fc503bdeef3
--- /dev/null
+++ b/gdb/config/mn10300/mn10300.mt
@@ -0,0 +1,6 @@
+# Target: Matsushita mn10300
+TDEPFILES= mn10300-tdep.o
+TM_FILE= tm-mn10300.h
+
+SIM_OBS = remote-sim.o
+SIM = ../sim/mn10300/libsim.a
diff --git a/gdb/config/mn10300/tm-mn10300.h b/gdb/config/mn10300/tm-mn10300.h
new file mode 100644
index 00000000000..e7d3fd7f96e
--- /dev/null
+++ b/gdb/config/mn10300/tm-mn10300.h
@@ -0,0 +1,165 @@
+/* Parameters for execution on a Matsushita mn10300 processor.
+ Copyright 1996, 1997 Free Software Foundation, Inc.
+
+ Contributed by Geoffrey Noer <noer@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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* The mn10300 is little endian. */
+#define TARGET_BYTE_ORDER_DEFAULT LITTLE_ENDIAN
+
+/* All registers are 32bits (phew!). */
+#define REGISTER_SIZE 4
+#define MAX_REGISTER_RAW_SIZE 4
+#define NUM_REGS 32
+
+#define REGISTER_VIRTUAL_TYPE(REG) builtin_type_int
+
+#define REGISTER_BYTE(REG) ((REG) * 4)
+#define REGISTER_VIRTUAL_SIZE(REG) 4
+#define REGISTER_RAW_SIZE(REG) 4
+
+#define MAX_REGISTER_VIRTUAL_SIZE 4
+
+#define REGISTER_BYTES (NUM_REGS * REGISTER_SIZE)
+
+extern char **mn10300_register_names;
+#define REGISTER_NAME(i) mn10300_register_names[i]
+
+#define D2_REGNUM 2
+#define D3_REGNUM 3
+#define A2_REGNUM 6
+#define A3_REGNUM 7
+#define SP_REGNUM 8
+#define PC_REGNUM 9
+#define MDR_REGNUM 10
+#define PSW_REGNUM 11
+#define LIR_REGNUM 12
+#define LAR_REGNUM 13
+
+/* Pseudo register that contains true address of executing stack frame */
+#define FP_REGNUM 31
+
+/* BREAKPOINT_FROM_PC uses the program counter value to determine the
+ breakpoint that should be used */
+extern breakpoint_from_pc_fn mn10300_breakpoint_from_pc;
+#define BREAKPOINT_FROM_PC(pcptr, lenptr) mn10300_breakpoint_from_pc (pcptr, lenptr)
+
+#define FUNCTION_START_OFFSET 0
+
+#define DECR_PC_AFTER_BREAK 0
+
+#define INNER_THAN(lhs,rhs) ((lhs) < (rhs))
+
+#define SAVED_PC_AFTER_CALL(frame) \
+ read_memory_integer (read_register (SP_REGNUM), 4)
+
+#ifdef __STDC__
+struct frame_info;
+struct type;
+struct value;
+#endif
+
+extern void mn10300_init_extra_frame_info PARAMS ((struct frame_info *));
+#define INIT_EXTRA_FRAME_INFO(fromleaf, fi) mn10300_init_extra_frame_info (fi)
+#define INIT_FRAME_PC /* Not necessary */
+
+#define FRAME_INIT_SAVED_REGS(fi) /* handled by init_extra_frame_info */
+
+extern CORE_ADDR mn10300_frame_chain PARAMS ((struct frame_info *));
+#define FRAME_CHAIN(fi) mn10300_frame_chain (fi)
+#define FRAME_CHAIN_VALID(FP, FI) generic_frame_chain_valid (FP, FI)
+
+extern CORE_ADDR mn10300_find_callers_reg PARAMS ((struct frame_info *, int));
+extern CORE_ADDR mn10300_frame_saved_pc PARAMS ((struct frame_info *));
+#define FRAME_SAVED_PC(FI) (mn10300_frame_saved_pc (FI))
+
+/* Extract from an array REGBUF containing the (raw) register state
+ a function return value of type TYPE, and copy that, in virtual format,
+ into VALBUF. */
+
+#define EXTRACT_RETURN_VALUE(TYPE, REGBUF, VALBUF) \
+ if (TYPE_CODE (TYPE) == TYPE_CODE_PTR) \
+ memcpy (VALBUF, REGBUF + REGISTER_BYTE (4), TYPE_LENGTH (TYPE)); \
+ else \
+ memcpy (VALBUF, REGBUF + REGISTER_BYTE (0), TYPE_LENGTH (TYPE));
+
+
+#define EXTRACT_STRUCT_VALUE_ADDRESS(REGBUF) \
+ extract_address (REGBUF + REGISTER_BYTE (4), \
+ REGISTER_RAW_SIZE (4))
+
+#define STORE_RETURN_VALUE(TYPE, VALBUF) \
+ if (TYPE_CODE (TYPE) == TYPE_CODE_PTR) \
+ write_register_bytes(REGISTER_BYTE (4), VALBUF, TYPE_LENGTH (TYPE)); \
+ else \
+ write_register_bytes(REGISTER_BYTE (0), VALBUF, TYPE_LENGTH (TYPE));
+
+#define STORE_STRUCT_RETURN(STRUCT_ADDR, SP) \
+ (SP) = mn10300_store_struct_return (STRUCT_ADDR, SP)
+
+extern CORE_ADDR mn10300_skip_prologue PARAMS ((CORE_ADDR));
+#define SKIP_PROLOGUE(pc) pc = mn10300_skip_prologue (pc)
+
+#define FRAME_ARGS_SKIP 0
+
+#define FRAME_ARGS_ADDRESS(fi) ((fi)->frame)
+#define FRAME_LOCALS_ADDRESS(fi) ((fi)->frame)
+#define FRAME_NUM_ARGS(val, fi) ((val) = -1)
+
+extern void mn10300_pop_frame PARAMS ((struct frame_info *));
+#define POP_FRAME mn10300_pop_frame (get_current_frame ())
+
+#define USE_GENERIC_DUMMY_FRAMES
+#define CALL_DUMMY {0}
+#define CALL_DUMMY_START_OFFSET (0)
+#define CALL_DUMMY_BREAKPOINT_OFFSET (0)
+#define CALL_DUMMY_LOCATION AT_ENTRY_POINT
+#define FIX_CALL_DUMMY(DUMMY, START, FUNADDR, NARGS, ARGS, TYPE, GCCP)
+#define CALL_DUMMY_ADDRESS() entry_point_address ()
+
+extern CORE_ADDR mn10300_push_return_address PARAMS ((CORE_ADDR, CORE_ADDR));
+#define PUSH_RETURN_ADDRESS(PC, SP) mn10300_push_return_address (PC, SP)
+
+#define PUSH_DUMMY_FRAME generic_push_dummy_frame ()
+
+extern CORE_ADDR
+mn10300_push_arguments PARAMS ((int, struct value **, CORE_ADDR,
+ unsigned char, CORE_ADDR ));
+#define PUSH_ARGUMENTS(NARGS, ARGS, SP, STRUCT_RETURN, STRUCT_ADDR) \
+ (SP) = mn10300_push_arguments (NARGS, ARGS, SP, STRUCT_RETURN, STRUCT_ADDR)
+
+#define PC_IN_CALL_DUMMY(PC, SP, FP) generic_pc_in_call_dummy (PC, SP)
+
+#define REG_STRUCT_HAS_ADDR(gcc_p,TYPE) \
+ (TYPE_LENGTH (TYPE) > 8)
+
+extern use_struct_convention_fn mn10300_use_struct_convention;
+#define USE_STRUCT_CONVENTION(GCC_P, TYPE) mn10300_use_struct_convention (GCC_P, TYPE)
+
+/* override the default get_saved_register function with
+ one that takes account of generic CALL_DUMMY frames */
+#define GET_SAVED_REGISTER
+
+/* Cons up virtual frame pointer for trace */
+extern void mn10300_virtual_frame_pointer PARAMS ((CORE_ADDR, long *, long *));
+#define TARGET_VIRTUAL_FRAME_POINTER(PC, REGP, OFFP) \
+ mn10300_virtual_frame_pointer ((PC), (REGP), (OFFP))
+
+/* Define this for Wingdb */
+
+#define TARGET_MN10300
diff --git a/gdb/config/nm-empty.h b/gdb/config/nm-empty.h
new file mode 100644
index 00000000000..7069d8c8a4e
--- /dev/null
+++ b/gdb/config/nm-empty.h
@@ -0,0 +1,2 @@
+/* This is just a dummy file to symlink to when GDB is configured as a
+ cross-only debugger. */
diff --git a/gdb/config/nm-gnu.h b/gdb/config/nm-gnu.h
new file mode 100644
index 00000000000..b7ee4dc769b
--- /dev/null
+++ b/gdb/config/nm-gnu.h
@@ -0,0 +1,45 @@
+/* Common declarations for the GNU Hurd
+
+ Copyright (C) 1995, 1998 Free Software Foundation, Inc.
+
+ Written by Miles Bader <miles@gnu.ai.mit.edu>
+
+ The GNU Hurd is free software; you can redistribute 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.
+
+ The GNU Hurd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You 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_GNU_H__
+#define __NM_GNU_H__
+
+#include <unistd.h>
+#include <mach.h>
+#include <mach/exception.h>
+
+#undef target_pid_to_str
+#define target_pid_to_str(pid) gnu_target_pid_to_str(pid)
+extern char *gnu_target_pid_to_str (int pid);
+
+/* Before storing, we need to read all the registers. */
+#define CHILD_PREPARE_TO_STORE() read_register_bytes (0, NULL, REGISTER_BYTES)
+
+/* Don't do wait_for_inferior on attach. */
+#define ATTACH_NO_WAIT
+
+/* Use SVR4 style shared library support */
+#define SVR4_SHARED_LIBS
+#include "solib.h"
+#define NO_CORE_OPS
+
+#define MAINTENANCE_CMDS 1
+
+#endif /* __NM_GNU_H__ */
diff --git a/gdb/config/nm-lynx.h b/gdb/config/nm-lynx.h
new file mode 100644
index 00000000000..2daf0faaef8
--- /dev/null
+++ b/gdb/config/nm-lynx.h
@@ -0,0 +1,83 @@
+/* Native-dependent definitions for LynxOS.
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef NM_LYNX_H
+#define NM_LYNX_H
+
+#include <sys/conf.h>
+#include <sys/kernel.h>
+/* sys/kernel.h should define this, but doesn't always, sigh. */
+#ifndef __LYNXOS
+#define __LYNXOS
+#endif
+#include <sys/mem.h>
+#include <sys/signal.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <sys/itimer.h>
+#include <sys/file.h>
+#include <sys/proc.h>
+#include "gdbthread.h"
+
+/* 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 USRSTACK
+
+#undef FLOAT_INFO /* No float info yet */
+
+/* As of LynxOS 2.2.2 (beta 8/15/94), this is int. Previous versions seem to
+ have had no prototype, so I'm not sure why GDB used to define this to
+ char *. */
+#define PTRACE_ARG3_TYPE int
+
+/* Override copies of {fetch,store}_inferior_registers in infptrace.c. */
+
+#define FETCH_INFERIOR_REGISTERS
+
+/* Thread ID of stopped thread. */
+
+#define WIFTID(x) (((union wait *)&x)->w_tid)
+
+/* Override child_wait in inftarg.c */
+
+#define CHILD_WAIT
+
+/* Override child_resume in infptrace.c */
+
+#define CHILD_RESUME
+
+/* Override child_thread_alive in intarg.c */
+
+#define CHILD_THREAD_ALIVE
+
+#include "target.h"
+
+extern int child_wait PARAMS ((int pid, struct target_waitstatus *status));
+
+/* Lynx needs a special definition of this so that we can
+ print out the pid and thread number seperatly. */
+
+#undef target_pid_to_str
+
+#define target_pid_to_str(PID) lynx_pid_to_str (PID)
+
+extern char *lynx_pid_to_str PARAMS ((int pid));
+
+#endif /* NM_LYNX_H */
diff --git a/gdb/config/nm-m3.h b/gdb/config/nm-m3.h
new file mode 100644
index 00000000000..6ea52565b94
--- /dev/null
+++ b/gdb/config/nm-m3.h
@@ -0,0 +1,123 @@
+/* Mach 3.0 common definitions and global vars.
+
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef NM_M3_H
+#define NM_M3_H
+
+#include <mach.h>
+
+/* Mach3 doesn't declare errno in <errno.h>. */
+extern int errno;
+
+/* Task port of our debugged inferior. */
+
+extern task_t inferior_task;
+
+/* Thread port of the current thread in the inferior. */
+
+extern thread_t current_thread;
+
+/* If nonzero, we must suspend/abort && resume threads
+ * when setting or getting the state.
+ */
+extern int must_suspend_thread;
+
+#define PREPARE_TO_PROCEED(select_it) mach3_prepare_to_proceed(select_it)
+
+/* Try to get the privileged host port for authentication to machid
+ *
+ * If you can get this, you may debug anything on this host.
+ *
+ * If you can't, gdb gives it's own task port as the
+ * authentication port
+ */
+#define mach_privileged_host_port() task_by_pid(-1)
+
+/*
+ * This is the MIG ID number of the emulator/server bsd_execve() RPC call.
+ *
+ * It SHOULD never change, but if it does, gdb `run'
+ * command won't work until you fix this define.
+ *
+ */
+#define MIG_EXEC_SYSCALL_ID 101000
+
+/* If our_message_port gets a msg with this ID,
+ * GDB suspends it's inferior and enters command level.
+ * (Useful at least if ^C does not work)
+ */
+#define GDB_MESSAGE_ID_STOP 0x41151
+
+/* wait3 WNOHANG is defined in <sys/wait.h> but
+ * for some reason gdb does not want to include
+ * that file.
+ *
+ * If your system defines WNOHANG differently, this has to be changed.
+ */
+#define WNOHANG 1
+
+/* Before storing, we need to read all the registers. */
+
+#define CHILD_PREPARE_TO_STORE() read_register_bytes (0, NULL, REGISTER_BYTES)
+
+/* Check if the inferior exists */
+#define MACH_ERROR_NO_INFERIOR \
+ do if (!MACH_PORT_VALID (inferior_task)) \
+ error ("Inferior task does not exist."); while(0)
+
+/* Error handler for mach calls */
+#define CHK(str,ret) \
+ do if (ret != KERN_SUCCESS) \
+ error ("Gdb %s [%d] %s : %s\n",__FILE__,__LINE__,str, \
+ mach_error_string(ret)); while(0)
+
+/* This is from POE9 emulator/emul_stack.h
+ */
+/*
+ * Top of emulator stack holds link and reply port.
+ */
+struct emul_stack_top {
+ struct emul_stack_top *link;
+ mach_port_t reply_port;
+};
+
+#define EMULATOR_STACK_SIZE (4096*4)
+
+#define THREAD_ALLOWED_TO_BREAK(mid) mach_thread_for_breakpoint (mid)
+
+#define THREAD_PARSE_ID(arg) mach_thread_parse_id (arg)
+
+#define THREAD_OUTPUT_ID(mid) mach_thread_output_id (mid)
+
+#define ATTACH_TO_THREAD attach_to_thread
+
+/* Don't do wait_for_inferior on attach. */
+#define ATTACH_NO_WAIT
+
+/* Do Mach 3 dependent operations when ^C or a STOP is requested */
+#define DO_QUIT() mach3_quit ()
+
+#if 0
+/* This is bogus. It is NOT OK to quit out of target_wait. */
+/* If in mach_msg() and ^C is typed set immediate_quit */
+#define REQUEST_QUIT() mach3_request_quit ()
+#endif
+
+#endif /* NM_M3_H */
diff --git a/gdb/config/nm-nbsd.h b/gdb/config/nm-nbsd.h
new file mode 100644
index 00000000000..bc1d6a621ac
--- /dev/null
+++ b/gdb/config/nm-nbsd.h
@@ -0,0 +1,86 @@
+/* Native-dependent definitions for NetBSD.
+ Copyright 1994, 1996 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* 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
+
+#define PTRACE_ARG3_TYPE char*
+
+#define FETCH_INFERIOR_REGISTERS
+
+#define ATTACH_DETACH
+
+#include "solib.h" /* Support for shared libraries. */
+
+/* make structure definitions match up with those expected in solib.c */
+#define link_object sod
+#define lo_name sod_name
+#define lo_library sod_library
+#define lo_unused sod_reserved
+#define lo_major sod_major
+#define lo_minor sod_minor
+#define lo_next sod_next
+
+#define link_map so_map
+#define lm_addr som_addr
+#define lm_name som_path
+#define lm_next som_next
+#define lm_lop som_sod
+#define lm_lob som_sodbase
+#define lm_rwt som_write
+#define lm_ld som_dynamic
+#define lm_lpd som_spd
+
+#define link_dynamic_2 section_dispatch_table
+#define ld_loaded sdt_loaded
+#define ld_need sdt_sods
+#define ld_rules sdt_filler1
+#define ld_got sdt_got
+#define ld_plt sdt_plt
+#define ld_rel sdt_rel
+#define ld_hash sdt_hash
+#define ld_stab sdt_nzlist
+#define ld_stab_hash sdt_filler2
+#define ld_buckets sdt_buckets
+#define ld_symbols sdt_strings
+#define ld_symb_size sdt_str_sz
+#define ld_text sdt_text_sz
+#define ld_plt_sz sdt_plt_sz
+
+#define rtc_symb rt_symbol
+#define rtc_sp rt_sp
+#define rtc_next rt_next
+
+#define ld_debug so_debug
+#define ldd_version dd_version
+#define ldd_in_debugger dd_in_debugger
+#define ldd_sym_loaded dd_sym_loaded
+#define ldd_bp_addr dd_bpt_addr
+#define ldd_bp_inst dd_bpt_shadow
+#define ldd_cp dd_cc
+
+#define link_dynamic _dynamic
+#define ld_version d_version
+#define ldd d_debug
+#define ld_un d_un
+#define ld_2 d_sdt
diff --git a/gdb/config/nm-sysv4.h b/gdb/config/nm-sysv4.h
new file mode 100644
index 00000000000..b891d4d9138
--- /dev/null
+++ b/gdb/config/nm-sysv4.h
@@ -0,0 +1,33 @@
+/* Definitions for running gdb on a host machine running any flavor of SVR4.
+ Copyright 1991, 1992, 1998 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Use SVR4 style shared library support */
+
+#define SVR4_SHARED_LIBS
+#include "solib.h"
+
+/* SVR4 has /proc support, so use it instead of ptrace. */
+
+#define USE_PROC_FS
+
+/* SVR4 machines can easily do attach and detach via /proc (procfs.c)
+ support */
+
+#define ATTACH_DETACH
diff --git a/gdb/config/none/nm-none.h b/gdb/config/none/nm-none.h
new file mode 100644
index 00000000000..9d630f36e4e
--- /dev/null
+++ b/gdb/config/none/nm-none.h
@@ -0,0 +1,18 @@
+/* Defines needed when configuring for "none".
+ Copyright (C) 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
diff --git a/gdb/config/none/none.mh b/gdb/config/none/none.mh
new file mode 100644
index 00000000000..33d5e4a3768
--- /dev/null
+++ b/gdb/config/none/none.mh
@@ -0,0 +1,5 @@
+# Host: "no target". This can be used to build you
+# a Makefile that only runs administrative commands like 'clean',
+# 'gdb.tar.Z', etc.
+NAT_FILE= nm-none.h
+XM_FILE= xm-none.h
diff --git a/gdb/config/none/none.mt b/gdb/config/none/none.mt
new file mode 100644
index 00000000000..300e2dcd05f
--- /dev/null
+++ b/gdb/config/none/none.mt
@@ -0,0 +1,4 @@
+# Target: "no target".
+# This can be used to build you a Makefile that only runs administrative
+# commands like 'clean', 'gdb.tar.Z', etc.
+TM_FILE= tm-none.h
diff --git a/gdb/config/none/tm-none.h b/gdb/config/none/tm-none.h
new file mode 100644
index 00000000000..4b16b3bc141
--- /dev/null
+++ b/gdb/config/none/tm-none.h
@@ -0,0 +1,23 @@
+/* Defines needed when configuring for "none".
+ Copyright (C) 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* This define is needed so that "gcc -MM" doesn't get errors and fail on
+ source files that use the value of INNER_THAN in preprocessor lines. */
+
+#define INNER_THAN(lhs,rhs) ((lhs) < (rhs))
diff --git a/gdb/config/none/xm-none.h b/gdb/config/none/xm-none.h
new file mode 100644
index 00000000000..9d630f36e4e
--- /dev/null
+++ b/gdb/config/none/xm-none.h
@@ -0,0 +1,18 @@
+/* Defines needed when configuring for "none".
+ Copyright (C) 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
diff --git a/gdb/config/ns32k/merlin.mh b/gdb/config/ns32k/merlin.mh
new file mode 100644
index 00000000000..f9c3e7b8a6a
--- /dev/null
+++ b/gdb/config/ns32k/merlin.mh
@@ -0,0 +1,16 @@
+# Host: Merlin running utek 2.1
+XDEPFILES= infptrace.o inftarg.o fork-child.o corelow.o core-aout.o
+XM_FILE= xm-merlin.h
+
+# FIXME: M_INSTALL is gone from the gdb makefile. If anyone cares
+# about the Merlin anymore, and the bug which inspired
+# SHELL_FILE/gdb-sh is still there, will need to reinstate it. Also,
+# this should be done for native only.
+
+# See SHELL_FILE in xm-merlin.h for a explanation of this.
+
+# FIXME: This should use $prefix, but only if SHELL_FILE does too.
+
+M_INSTALL=cp /bin/sh /usr/local/lib/gdb-sh; \
+chmod ogu+rw /usr/local/lib/gdb-sh
+M_UNINSTALL = rm -f /usr/local/lib/gdb-sh
diff --git a/gdb/config/ns32k/merlin.mt b/gdb/config/ns32k/merlin.mt
new file mode 100644
index 00000000000..b346077344e
--- /dev/null
+++ b/gdb/config/ns32k/merlin.mt
@@ -0,0 +1,3 @@
+# Target: Merlin running utek 2.1
+TDEPFILES= ns32k-tdep.o
+TM_FILE= tm-merlin.h
diff --git a/gdb/config/ns32k/nbsd.mh b/gdb/config/ns32k/nbsd.mh
new file mode 100644
index 00000000000..aae025b56fc
--- /dev/null
+++ b/gdb/config/ns32k/nbsd.mh
@@ -0,0 +1,5 @@
+# Host: PC532 running NetBSD
+XDEPFILES= ser-tcp.o
+XM_FILE= xm-nbsd.h
+NAT_FILE= nm-nbsd.h
+NATDEPFILES= fork-child.o infptrace.o inftarg.o corelow.o ns32knbsd-nat.o
diff --git a/gdb/config/ns32k/nbsd.mt b/gdb/config/ns32k/nbsd.mt
new file mode 100644
index 00000000000..512132a757f
--- /dev/null
+++ b/gdb/config/ns32k/nbsd.mt
@@ -0,0 +1,3 @@
+# Target: PC532 running NetBSD
+TDEPFILES= ns32k-tdep.o solib.o
+TM_FILE= tm-nbsd.h
diff --git a/gdb/config/ns32k/nm-nbsd.h b/gdb/config/ns32k/nm-nbsd.h
new file mode 100644
index 00000000000..cef536e4050
--- /dev/null
+++ b/gdb/config/ns32k/nm-nbsd.h
@@ -0,0 +1,36 @@
+/* Native-dependent definitions for ns32k running NetBSD, for GDB.
+ Copyright 1986, 1987, 1989, 1992, 1994 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef NM_NBSD_H
+#define NM_NBSD_H
+
+/* Get generic NetBSD native definitions. */
+#include "nm-nbsd.h"
+
+#if 0
+#define FLOAT_INFO { extern ns32k_float_info(); ns32k_float_info(); }
+#endif
+
+#define REGISTER_U_ADDR(addr, blockend, regno) \
+ (addr) = ns32k_register_u_addr ((blockend),(regno));
+
+extern int
+ns32k_register_u_addr PARAMS ((int, int));
+
+#endif /* NM_NBSD_H */
diff --git a/gdb/config/ns32k/nm-umax.h b/gdb/config/ns32k/nm-umax.h
new file mode 100644
index 00000000000..add6e70f31b
--- /dev/null
+++ b/gdb/config/ns32k/nm-umax.h
@@ -0,0 +1,54 @@
+/* Definitions to make GDB run on an encore under umax 4.2
+ Copyright 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Do implement the attach and detach commands... */
+#define ATTACH_DETACH
+
+/* Offset of registers within u area. */
+#define U_REGS_OFFSET 0
+
+/* called from register_addr() -- blockend not used for now */
+#define REGISTER_U_ADDR(addr, blockend, regno) \
+{ \
+ switch (regno) { \
+ case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: \
+ addr = PU_R0 - (regno * sizeof (int)); break; \
+ case SP_REGNUM: \
+ addr = PU_SP; break; \
+ case PC_REGNUM: \
+ addr = PU_PC; break; \
+ case FP_REGNUM: \
+ addr = PU_FP; break; \
+ case PS_REGNUM: \
+ addr = PU_PSL; break; \
+ case FPS_REGNUM: \
+ addr = PU_FSR; break; \
+ case FP0_REGNUM + 0: case FP0_REGNUM + 1: \
+ case FP0_REGNUM + 2: case FP0_REGNUM + 3: \
+ case FP0_REGNUM + 4: case FP0_REGNUM + 5: \
+ case FP0_REGNUM + 6: case FP0_REGNUM + 7: \
+ addr = PU_F0 + (regno - FP0_REGNUM) * sizeof (float); break; \
+ case LP0_REGNUM + 0: case LP0_REGNUM + 1: \
+ case LP0_REGNUM + 2: case LP0_REGNUM + 3: \
+ addr = PU_F0 + (regno - LP0_REGNUM) * sizeof (double); break; \
+ default: \
+ printf ("bad argument to REGISTER_U_ADDR %d\n", regno); \
+ abort (); \
+ } \
+}
diff --git a/gdb/config/ns32k/ns32km3.mh b/gdb/config/ns32k/ns32km3.mh
new file mode 100644
index 00000000000..7f0992afa40
--- /dev/null
+++ b/gdb/config/ns32k/ns32km3.mh
@@ -0,0 +1,7 @@
+# Host: ns32k running Mach3
+
+XDEPFILES=
+NATDEPFILES= m3-nat.o ns32km3-nat.o fork-child.o corelow.o core-aout.o
+NAT_CLIBS= -L/usr/mach/lib -lnetname -lmachid -lmach
+XM_FILE= xm-ns32km3.h
+NAT_FILE= nm-m3.h
diff --git a/gdb/config/ns32k/ns32km3.mt b/gdb/config/ns32k/ns32km3.mt
new file mode 100644
index 00000000000..9391176fc56
--- /dev/null
+++ b/gdb/config/ns32k/ns32km3.mt
@@ -0,0 +1,3 @@
+# Target: ns32k with a.out on Mach 3
+TDEPFILES= ns32k-tdep.o
+TM_FILE= tm-ns32km3.h
diff --git a/gdb/config/ns32k/tm-merlin.h b/gdb/config/ns32k/tm-merlin.h
new file mode 100644
index 00000000000..f90c5e79778
--- /dev/null
+++ b/gdb/config/ns32k/tm-merlin.h
@@ -0,0 +1,313 @@
+/* Definitions to target GDB to a merlin under utek 2.1
+ Copyright 1986, 1987, 1989, 1991, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define TARGET_BYTE_ORDER LITTLE_ENDIAN
+
+/* Offset from address of function to start of its code.
+ Zero on most machines. */
+
+#define FUNCTION_START_OFFSET 0
+
+/* Advance PC across any function entry prologue instructions
+ to reach some "real" code. */
+
+#define SKIP_PROLOGUE(pc) \
+{ register int op = read_memory_integer (pc, 1); \
+ if (op == 0x82) \
+ { op = read_memory_integer (pc+2,1); \
+ if ((op & 0x80) == 0) pc += 3; \
+ else if ((op & 0xc0) == 0x80) pc += 4; \
+ else pc += 6; \
+ }}
+
+/* Immediately after a function call, return the saved pc.
+ Can't always go through the frames for this because on some machines
+ the new frame is not set up until the new function executes
+ some instructions. */
+
+#define SAVED_PC_AFTER_CALL(frame) \
+ read_memory_integer (read_register (SP_REGNUM), 4)
+
+/* Address of end of stack space. */
+
+#define STACK_END_ADDR (0x800000)
+
+/* Stack grows downward. */
+
+#define INNER_THAN(lhs,rhs) ((lhs) < (rhs))
+
+/* Sequence of bytes for breakpoint instruction. */
+
+#define BREAKPOINT {0xf2}
+
+/* Amount PC must be decremented by after a breakpoint.
+ This is often the number of bytes in BREAKPOINT
+ but not always. */
+
+#define DECR_PC_AFTER_BREAK 0
+
+/* Define this to say that the "svc" insn is followed by
+ codes in memory saying which kind of system call it is. */
+
+#define NS32K_SVC_IMMED_OPERANDS
+
+/* Say how long (ordinary) registers are. This is a piece of bogosity
+ used in push_word and a few other places; REGISTER_RAW_SIZE is the
+ real way to know how big a register is. */
+
+#define REGISTER_SIZE 4
+
+/* Number of machine registers */
+
+#define NUM_REGS 25
+
+#define NUM_GENERAL_REGS 8
+
+/* Initializer for an array of names of registers.
+ There should be NUM_REGS strings in this initializer. */
+
+#define REGISTER_NAMES {"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", \
+ "pc", "sp", "fp", "ps", \
+ "fsr", \
+ "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", \
+ "l0", "l1", "l2", "l3", "l4", \
+ }
+
+/* Register numbers of various important registers.
+ Note that some of these values are "real" register numbers,
+ and correspond to the general registers of the machine,
+ and some are "phony" register numbers which are too large
+ to be actual register numbers as far as the user is concerned
+ but do serve to get the desired values when passed to read_register. */
+
+#define AP_REGNUM FP_REGNUM
+#define FP_REGNUM 10 /* Contains address of executing stack frame */
+#define SP_REGNUM 9 /* Contains address of top of stack */
+#define PC_REGNUM 8 /* Contains program counter */
+#define PS_REGNUM 11 /* Contains processor status */
+#define FPS_REGNUM 12 /* Floating point status register */
+#define FP0_REGNUM 13 /* Floating point register 0 */
+#define LP0_REGNUM 21 /* Double register 0 (same as FP0) */
+
+/* Total amount of space needed to store our copies of the machine's
+ register state, the array `registers'. */
+#define REGISTER_BYTES ((NUM_REGS - 4) * sizeof (int) + 4 * sizeof (double))
+
+/* Index within `registers' of the first byte of the space for
+ register N. */
+
+#define REGISTER_BYTE(N) ((N) >= LP0_REGNUM ? \
+ LP0_REGNUM * 4 + ((N) - LP0_REGNUM) * 8 : (N) * 4)
+
+/* Number of bytes of storage in the actual machine representation
+ for register N. On the 32000, all regs are 4 bytes
+ except for the doubled floating registers. */
+
+#define REGISTER_RAW_SIZE(N) ((N) >= LP0_REGNUM ? 8 : 4)
+
+/* Number of bytes of storage in the program's representation
+ for register N. On the 32000, all regs are 4 bytes
+ except for the doubled floating registers. */
+
+#define REGISTER_VIRTUAL_SIZE(N) ((N) >= LP0_REGNUM ? 8 : 4)
+
+/* Largest value REGISTER_RAW_SIZE can have. */
+
+#define MAX_REGISTER_RAW_SIZE 8
+
+/* Largest value REGISTER_VIRTUAL_SIZE can have. */
+
+#define MAX_REGISTER_VIRTUAL_SIZE 8
+
+/* Return the GDB type object for the "standard" data type
+ of data in register N. */
+
+#define REGISTER_VIRTUAL_TYPE(N) \
+ ((N) >= FP0_REGNUM ? \
+ ((N) >= LP0_REGNUM ? \
+ builtin_type_double \
+ : builtin_type_float) \
+ : builtin_type_int)
+
+/* Store the address of the place in which to copy the structure the
+ subroutine will return. This is called from call_function.
+
+ On this machine this is a no-op, as gcc doesn't run on it yet.
+ This calling convention is not used. */
+
+#define STORE_STRUCT_RETURN(ADDR, SP)
+
+/* Extract from an array REGBUF containing the (raw) register state
+ a function return value of type TYPE, and copy that, in virtual format,
+ into VALBUF. */
+
+#define EXTRACT_RETURN_VALUE(TYPE,REGBUF,VALBUF) \
+ memcpy (VALBUF, REGBUF, 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. */
+
+/* In the case of the Merlin, the frame's nominal address is the FP value,
+ and at that address is saved previous FP value as a 4-byte word. */
+
+#define FRAME_CHAIN(thisframe) \
+ (!inside_entry_file ((thisframe)->pc) ? \
+ read_memory_integer ((thisframe)->frame, 4) :\
+ 0)
+
+/* Define other aspects of the stack frame. */
+
+#define FRAME_SAVED_PC(FRAME) (read_memory_integer ((FRAME)->frame + 4, 4))
+
+/* compute base of arguments */
+#define FRAME_ARGS_ADDRESS(fi) ((fi)->frame)
+
+#define FRAME_LOCALS_ADDRESS(fi) ((fi)->frame)
+
+/* Return number of args passed to a frame.
+ Can return -1, meaning no way to tell. */
+
+#define FRAME_NUM_ARGS(numargs, fi) \
+{ CORE_ADDR pc; \
+ int insn; \
+ int addr_mode; \
+ int width; \
+ \
+ pc = FRAME_SAVED_PC (fi); \
+ insn = read_memory_integer (pc,2); \
+ addr_mode = (insn >> 11) & 0x1f; \
+ insn = insn & 0x7ff; \
+ if ((insn & 0x7fc) == 0x57c \
+ && addr_mode == 0x14) /* immediate */ \
+ { if (insn == 0x57c) /* adjspb */ \
+ width = 1; \
+ else if (insn == 0x57d) /* adjspw */ \
+ width = 2; \
+ else if (insn == 0x57f) /* adjspd */ \
+ width = 4; \
+ numargs = read_memory_integer (pc+2,width); \
+ if (width > 1) \
+ flip_bytes (&numargs, width); \
+ numargs = - sign_extend (numargs, width*8) / 4; } \
+ else numargs = -1; \
+}
+
+/* Return number of bytes at start of arglist that are not really args. */
+
+#define FRAME_ARGS_SKIP 8
+
+/* Put here the code to store, into a struct frame_saved_regs,
+ the addresses of the saved registers of frame described by FRAME_INFO.
+ This includes special registers such as pc and fp saved in special
+ ways in the stack frame. sp is even more special:
+ the address we return for it IS the sp for the next frame. */
+
+#define FRAME_FIND_SAVED_REGS(frame_info, frame_saved_regs) \
+{ int regmask,regnum; \
+ int localcount; \
+ CORE_ADDR enter_addr; \
+ CORE_ADDR next_addr; \
+ \
+ enter_addr = get_pc_function_start ((frame_info)->pc); \
+ regmask = read_memory_integer (enter_addr+1, 1); \
+ localcount = ns32k_localcount (enter_addr); \
+ next_addr = (frame_info)->frame + localcount; \
+ for (regnum = 0; regnum < 8; regnum++, regmask >>= 1) \
+ (frame_saved_regs).regs[regnum] \
+ = (regmask & 1) ? (next_addr -= 4) : 0; \
+ (frame_saved_regs).regs[SP_REGNUM] = (frame_info)->frame + 4; \
+ (frame_saved_regs).regs[PC_REGNUM] = (frame_info)->frame + 4; \
+ (frame_saved_regs).regs[FP_REGNUM] \
+ = read_memory_integer ((frame_info)->frame, 4); }
+
+
+/* Things needed for making the inferior call functions. */
+
+/* Push an empty stack frame, to record the current PC, etc. */
+
+#define PUSH_DUMMY_FRAME \
+{ register CORE_ADDR sp = read_register (SP_REGNUM); \
+ register int regnum; \
+ sp = push_word (sp, read_register (PC_REGNUM)); \
+ sp = push_word (sp, read_register (FP_REGNUM)); \
+ write_register (FP_REGNUM, sp); \
+ for (regnum = 0; regnum < 8; regnum++) \
+ sp = push_word (sp, read_register (regnum)); \
+ write_register (SP_REGNUM, sp); \
+}
+
+/* Discard from the stack the innermost frame, restoring all registers. */
+
+#define POP_FRAME \
+{ register struct frame_info *frame = get_current_frame (); \
+ register CORE_ADDR fp; \
+ register int regnum; \
+ struct frame_saved_regs fsr; \
+ struct frame_info *fi; \
+ fp = frame->frame; \
+ get_frame_saved_regs (frame, &fsr); \
+ for (regnum = 0; regnum < 8; regnum++) \
+ if (fsr.regs[regnum]) \
+ write_register (regnum, read_memory_integer (fsr.regs[regnum], 4)); \
+ write_register (FP_REGNUM, read_memory_integer (fp, 4)); \
+ write_register (PC_REGNUM, read_memory_integer (fp + 4, 4)); \
+ write_register (SP_REGNUM, fp + 8); \
+ flush_cached_frames (); \
+}
+
+/* This sequence of words is the instructions
+ enter 0xff,0 82 ff 00
+ jsr @0x00010203 7f ae c0 01 02 03
+ adjspd 0x69696969 7f a5 01 02 03 04
+ bpt f2
+ Note this is 16 bytes. */
+
+#define CALL_DUMMY { 0x7f00ff82, 0x0201c0ae, 0x01a57f03, 0xf2040302 }
+
+#define CALL_DUMMY_START_OFFSET 3
+#define CALL_DUMMY_LENGTH 16
+#define CALL_DUMMY_ADDR 5
+#define CALL_DUMMY_NARGS 11
+
+/* Insert the specified number of args and function address
+ into a call sequence of the above form stored at DUMMYNAME. */
+
+#define FIX_CALL_DUMMY(dummyname, pc, fun, nargs, args, type, gcc_p) \
+{ int flipped = fun | 0xc0000000; \
+ flip_bytes (&flipped, 4); \
+ *((int *) (((char *) dummyname)+CALL_DUMMY_ADDR)) = flipped; \
+ flipped = - nargs * 4; \
+ flip_bytes (&flipped, 4); \
+ *((int *) (((char *) dummyname)+CALL_DUMMY_NARGS)) = flipped; \
+}
diff --git a/gdb/config/ns32k/tm-nbsd.h b/gdb/config/ns32k/tm-nbsd.h
new file mode 100644
index 00000000000..6e61de31e56
--- /dev/null
+++ b/gdb/config/ns32k/tm-nbsd.h
@@ -0,0 +1,79 @@
+/* Macro definitions for ns32k running under NetBSD.
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Override number of expected traps from sysv. */
+#define START_INFERIOR_TRAPS_EXPECTED 2
+
+/* Most definitions from umax could be used. */
+
+#include "ns32k/tm-umax.h"
+
+/* Generic NetBSD definitions. */
+
+#include "tm-nbsd.h"
+
+/* Saved Pc. Get it from sigcontext if within sigtramp. */
+
+/* Offset to saved PC in sigcontext, from <machine/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)) \
+ )
+
+
+/* tm-umax.h assumes a 32082 fpu. We have a 32382 fpu. */
+#undef REGISTER_NAMES
+#undef NUM_REGS
+#undef REGISTER_BYTES
+#undef REGISTER_BYTE
+/* Initializer for an array of names of registers.
+ There should be NUM_REGS strings in this initializer. */
+
+#define REGISTER_NAMES {"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", \
+ "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", \
+ "sp", "fp", "pc", "ps", \
+ "fsr", \
+ "l0", "l1", "l2", "l3", "l4", "l5", "l6", "l7", "xx", \
+ }
+
+#define NUM_REGS 29
+
+/* Total amount of space needed to store our copies of the machine's
+ register state, the array `registers'. */
+#define REGISTER_BYTES \
+ ((NUM_REGS - 4) * REGISTER_RAW_SIZE(R0_REGNUM) \
+ + 8 * REGISTER_RAW_SIZE(LP0_REGNUM))
+
+/* Index within `registers' of the first byte of the space for
+ register N. */
+
+/* This is a bit yuck. The even numbered double precision floating
+ point long registers occupy the same space as the even:odd numbered
+ single precision floating point registers, but the extra 32381 fpu
+ registers are at the end. Doing it this way is compatable for both
+ 32081 and 32381 equiped machines. */
+
+#define REGISTER_BYTE(N) (((N) < LP0_REGNUM? (N)\
+ : ((N) - LP0_REGNUM) & 1? (N) - 1 \
+ : ((N) - LP0_REGNUM + FP0_REGNUM)) * 4)
+
diff --git a/gdb/config/ns32k/tm-ns32km3.h b/gdb/config/ns32k/tm-ns32km3.h
new file mode 100644
index 00000000000..27d07d75cd5
--- /dev/null
+++ b/gdb/config/ns32k/tm-ns32km3.h
@@ -0,0 +1,73 @@
+/* Macro definitions for ns532, Mach 3.0
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Include common definitions for Mach3 systems */
+#include "nm-m3.h"
+
+/* Define offsets to access CPROC stack when it does not have
+ * a kernel thread.
+ */
+#define MACHINE_CPROC_SP_OFFSET 20
+#define MACHINE_CPROC_PC_OFFSET 16
+#define MACHINE_CPROC_FP_OFFSET 12
+
+#include <ns532/psl.h>
+#include <ns532/vmparam.h>
+
+/* Thread flavors used in re-setting the T bit.
+ * @@ this is also bad for cross debugging.
+ */
+#define TRACE_FLAVOR NS532_THREAD_STATE
+#define TRACE_FLAVOR_SIZE NS532_THREAD_STATE_COUNT
+#define TRACE_SET(x,state) \
+ ((struct ns532_thread_state *)state)->psr |= PSR_T
+#define TRACE_CLEAR(x,state) \
+ ((((struct ns532_thread_state *)state)->psr &= ~PSR_T), 1)
+
+/* we can do it */
+#define ATTACH_DETACH 1
+
+/* Address of end of stack space.
+ * for MACH, see <ns532/vmparam.h>
+ */
+#define STACK_END_ADDR USRSTACK
+
+#include "ns32k/tm-umax.h"
+
+/* tm-umax.h assumes a 32082 fpu. We have a 32382 fpu. */
+#undef REGISTER_NAMES
+#undef NUM_REGS
+#undef REGISTER_BYTES
+/* Initializer for an array of names of registers.
+ There should be NUM_REGS strings in this initializer. */
+
+#define REGISTER_NAMES {"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", \
+ "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", \
+ "sp", "fp", "pc", "ps", \
+ "fsr", \
+ "l0", "l1", "l2", "l3", "l4", "l5", "l6", "l7", "xx", \
+ }
+
+#define NUM_REGS 29
+
+/* Total amount of space needed to store our copies of the machine's
+ register state, the array `registers'. */
+#define REGISTER_BYTES \
+ ((NUM_REGS - 4) * REGISTER_RAW_SIZE(R0_REGNUM) \
+ + 8 * REGISTER_RAW_SIZE(LP0_REGNUM))
diff --git a/gdb/config/ns32k/tm-umax.h b/gdb/config/ns32k/tm-umax.h
new file mode 100644
index 00000000000..1fdfb2fccd0
--- /dev/null
+++ b/gdb/config/ns32k/tm-umax.h
@@ -0,0 +1,370 @@
+/* Definitions to make GDB run on an encore under umax 4.2
+ Copyright 1987, 1989, 1991, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* This is also included by tm-ns32km3.h, as well as being used by umax. */
+
+#define TARGET_BYTE_ORDER LITTLE_ENDIAN
+
+/* Need to get function ends by adding this to epilogue address from .bf
+ record, not using x_fsize field. */
+#define FUNCTION_EPILOGUE_SIZE 4
+
+/* Offset from address of function to start of its code.
+ Zero on most machines. */
+
+#define FUNCTION_START_OFFSET 0
+
+/* Advance PC across any function entry prologue instructions
+ to reach some "real" code. */
+
+#define SKIP_PROLOGUE(pc) \
+{ register unsigned char op = read_memory_integer (pc, 1); \
+ if (op == 0x82) { op = read_memory_integer (pc+2,1); \
+ if ((op & 0x80) == 0) pc += 3; \
+ else if ((op & 0xc0) == 0x80) pc += 4; \
+ else pc += 6; \
+ } \
+}
+
+/* Immediately after a function call, return the saved pc.
+ Can't always go through the frames for this because on some machines
+ the new frame is not set up until the new function executes
+ some instructions. */
+
+#define SAVED_PC_AFTER_CALL(frame) \
+ read_memory_integer (read_register (SP_REGNUM), 4)
+
+/* Address of end of stack space. */
+
+#ifndef STACK_END_ADDR
+#define STACK_END_ADDR (0xfffff000)
+#endif
+
+/* Stack grows downward. */
+
+#define INNER_THAN(lhs,rhs) ((lhs) < (rhs))
+
+/* Sequence of bytes for breakpoint instruction. */
+
+#define BREAKPOINT {0xf2}
+
+/* Amount PC must be decremented by after a breakpoint.
+ This is often the number of bytes in BREAKPOINT
+ but not always. */
+
+#define DECR_PC_AFTER_BREAK 0
+
+#if 0 /* Disable until fixed *correctly*. */
+#ifndef INVALID_FLOAT
+#ifndef NaN
+#include <nan.h>
+#endif NaN
+
+/* Return 1 if P points to an invalid floating point value. */
+/* Surely wrong for cross-debugging. */
+#define INVALID_FLOAT(p, s) \
+ ((s == sizeof (float))? \
+ NaF (*(float *) p) : \
+ NaD (*(double *) p))
+#endif /* INVALID_FLOAT */
+#endif
+
+/* Say how long (ordinary) registers are. This is a piece of bogosity
+ used in push_word and a few other places; REGISTER_RAW_SIZE is the
+ real way to know how big a register is. */
+
+#define REGISTER_SIZE 4
+
+/* Number of machine registers */
+
+#define NUM_REGS 25
+
+#define NUM_GENERAL_REGS 8
+
+/* Initializer for an array of names of registers.
+ There should be NUM_REGS strings in this initializer. */
+
+#define REGISTER_NAMES {"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", \
+ "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", \
+ "sp", "fp", "pc", "ps", \
+ "fsr", \
+ "l0", "l1", "l2", "l3", "xx", \
+ }
+
+/* Register numbers of various important registers.
+ Note that some of these values are "real" register numbers,
+ and correspond to the general registers of the machine,
+ and some are "phony" register numbers which are too large
+ to be actual register numbers as far as the user is concerned
+ but do serve to get the desired values when passed to read_register. */
+
+#define R0_REGNUM 0 /* General register 0 */
+#define FP0_REGNUM 8 /* Floating point register 0 */
+#define SP_REGNUM 16 /* Contains address of top of stack */
+#define AP_REGNUM FP_REGNUM
+#define FP_REGNUM 17 /* Contains address of executing stack frame */
+#define PC_REGNUM 18 /* Contains program counter */
+#define PS_REGNUM 19 /* Contains processor status */
+#define FPS_REGNUM 20 /* Floating point status register */
+#define LP0_REGNUM 21 /* Double register 0 (same as FP0) */
+
+/* Total amount of space needed to store our copies of the machine's
+ register state, the array `registers'. */
+#define REGISTER_BYTES \
+ ((NUM_REGS - 4) * REGISTER_RAW_SIZE(R0_REGNUM) \
+ + 4 * REGISTER_RAW_SIZE(LP0_REGNUM))
+
+/* Index within `registers' of the first byte of the space for
+ register N. */
+
+#define REGISTER_BYTE(N) ((N) >= LP0_REGNUM ? \
+ LP0_REGNUM * 4 + ((N) - LP0_REGNUM) * 8 : (N) * 4)
+
+/* Number of bytes of storage in the actual machine representation
+ for register N. On the 32000, all regs are 4 bytes
+ except for the doubled floating registers. */
+
+#define REGISTER_RAW_SIZE(N) ((N) >= LP0_REGNUM ? 8 : 4)
+
+/* Number of bytes of storage in the program's representation
+ for register N. On the 32000, all regs are 4 bytes
+ except for the doubled floating registers. */
+
+#define REGISTER_VIRTUAL_SIZE(N) ((N) >= LP0_REGNUM ? 8 : 4)
+
+/* Largest value REGISTER_RAW_SIZE can have. */
+
+#define MAX_REGISTER_RAW_SIZE 8
+
+/* Largest value REGISTER_VIRTUAL_SIZE can have. */
+
+#define MAX_REGISTER_VIRTUAL_SIZE 8
+
+/* Return the GDB type object for the "standard" data type
+ of data in register N. */
+
+#define REGISTER_VIRTUAL_TYPE(N) \
+ (((N) < FP0_REGNUM) ? \
+ builtin_type_int : \
+ ((N) < FP0_REGNUM + 8) ? \
+ builtin_type_float : \
+ ((N) < LP0_REGNUM) ? \
+ builtin_type_int : \
+ builtin_type_double)
+
+/* Store the address of the place in which to copy the structure the
+ subroutine will return. This is called from call_function.
+
+ On this machine this is a no-op, because gcc isn't used on it
+ yet. So this calling convention is not used. */
+
+#define STORE_STRUCT_RETURN(ADDR, SP)
+
+/* Extract from an array REGBUF containing the (raw) register state
+ a function return value of type TYPE, and copy that, in virtual format,
+ into VALBUF. */
+
+#define EXTRACT_RETURN_VALUE(TYPE,REGBUF,VALBUF) \
+ memcpy (VALBUF, REGBUF+REGISTER_BYTE (TYPE_CODE (TYPE) == TYPE_CODE_FLT ? FP0_REGNUM : 0), TYPE_LENGTH (TYPE))
+
+/* Write into appropriate registers a function return value
+ of type TYPE, given in virtual format. */
+
+#define STORE_RETURN_VALUE(TYPE,VALBUF) \
+ write_register_bytes (REGISTER_BYTE (TYPE_CODE (TYPE) == TYPE_CODE_FLT ? FP0_REGNUM : 0), VALBUF, TYPE_LENGTH (TYPE))
+
+/* Extract from an array REGBUF containing the (raw) register state
+ the address in which a function should return its structure value,
+ as a CORE_ADDR (or an expression that can be used as one). */
+
+#define EXTRACT_STRUCT_VALUE_ADDRESS(REGBUF) (*(int *)(REGBUF))
+
+/* 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. */
+
+/* In the case of the ns32000 series, the frame's nominal address is the FP
+ value, and at that address is saved previous FP value as a 4-byte word. */
+
+#define FRAME_CHAIN(thisframe) \
+ (!inside_entry_file ((thisframe)->pc) ? \
+ read_memory_integer ((thisframe)->frame, 4) :\
+ 0)
+
+/* Define other aspects of the stack frame. */
+
+#define FRAME_SAVED_PC(FRAME) (read_memory_integer ((FRAME)->frame + 4, 4))
+
+/* Compute base of arguments. */
+
+#define FRAME_ARGS_ADDRESS(fi) \
+ ((ns32k_get_enter_addr ((fi)->pc) > 1) ? \
+ ((fi)->frame) : (read_register (SP_REGNUM) - 4))
+
+#define FRAME_LOCALS_ADDRESS(fi) ((fi)->frame)
+
+/* Get the address of the enter opcode for this function, if it is active.
+ Returns positive address > 1 if pc is between enter/exit,
+ 1 if pc before enter or after exit, 0 otherwise. */
+
+extern CORE_ADDR ns32k_get_enter_addr ();
+
+/* Return number of args passed to a frame.
+ Can return -1, meaning no way to tell.
+ Encore's C compiler often reuses same area on stack for args,
+ so this will often not work properly. If the arg names
+ are known, it's likely most of them will be printed. */
+
+#define FRAME_NUM_ARGS(numargs, fi) \
+{ CORE_ADDR pc; \
+ CORE_ADDR enter_addr; \
+ unsigned int insn; \
+ unsigned int addr_mode; \
+ int width; \
+ \
+ numargs = -1; \
+ enter_addr = ns32k_get_enter_addr ((fi)->pc); \
+ if (enter_addr > 0) \
+ { \
+ pc = (enter_addr == 1) ? \
+ SAVED_PC_AFTER_CALL (fi) : \
+ FRAME_SAVED_PC (fi); \
+ insn = read_memory_integer (pc,2); \
+ addr_mode = (insn >> 11) & 0x1f; \
+ insn = insn & 0x7ff; \
+ if ((insn & 0x7fc) == 0x57c && \
+ addr_mode == 0x14) /* immediate */ \
+ { \
+ if (insn == 0x57c) /* adjspb */ \
+ width = 1; \
+ else if (insn == 0x57d) /* adjspw */ \
+ width = 2; \
+ else if (insn == 0x57f) /* adjspd */ \
+ width = 4; \
+ numargs = read_memory_integer (pc+2,width); \
+ if (width > 1) \
+ flip_bytes (&numargs, width); \
+ numargs = - sign_extend (numargs, width*8) / 4;\
+ } \
+ } \
+}
+
+/* Return number of bytes at start of arglist that are not really args. */
+
+#define FRAME_ARGS_SKIP 8
+
+/* Put here the code to store, into a struct frame_saved_regs,
+ the addresses of the saved registers of frame described by FRAME_INFO.
+ This includes special registers such as pc and fp saved in special
+ ways in the stack frame. sp is even more special:
+ the address we return for it IS the sp for the next frame. */
+
+#define FRAME_FIND_SAVED_REGS(frame_info, frame_saved_regs) \
+{ \
+ register int regmask, regnum; \
+ int localcount; \
+ register CORE_ADDR enter_addr; \
+ register CORE_ADDR next_addr; \
+ \
+ memset (&(frame_saved_regs), '\0', sizeof (frame_saved_regs)); \
+ enter_addr = ns32k_get_enter_addr ((frame_info)->pc); \
+ if (enter_addr > 1) \
+ { \
+ regmask = read_memory_integer (enter_addr+1, 1) & 0xff; \
+ localcount = ns32k_localcount (enter_addr); \
+ next_addr = (frame_info)->frame + localcount; \
+ for (regnum = 0; regnum < 8; regnum++, regmask >>= 1) \
+ (frame_saved_regs).regs[regnum] = (regmask & 1) ? \
+ (next_addr -= 4) : 0; \
+ (frame_saved_regs).regs[SP_REGNUM] = (frame_info)->frame + 4;\
+ (frame_saved_regs).regs[PC_REGNUM] = (frame_info)->frame + 4;\
+ (frame_saved_regs).regs[FP_REGNUM] = \
+ (read_memory_integer ((frame_info)->frame, 4));\
+ } \
+ else if (enter_addr == 1) \
+ { \
+ CORE_ADDR sp = read_register (SP_REGNUM); \
+ (frame_saved_regs).regs[PC_REGNUM] = sp; \
+ (frame_saved_regs).regs[SP_REGNUM] = sp + 4; \
+ } \
+}
+
+/* Things needed for making the inferior call functions. */
+
+/* Push an empty stack frame, to record the current PC, etc. */
+
+#define PUSH_DUMMY_FRAME \
+{ register CORE_ADDR sp = read_register (SP_REGNUM);\
+ register int regnum; \
+ sp = push_word (sp, read_register (PC_REGNUM)); \
+ sp = push_word (sp, read_register (FP_REGNUM)); \
+ write_register (FP_REGNUM, sp); \
+ for (regnum = 0; regnum < 8; regnum++) \
+ sp = push_word (sp, read_register (regnum)); \
+ write_register (SP_REGNUM, sp); \
+}
+
+/* Discard from the stack the innermost frame, restoring all registers. */
+
+#define POP_FRAME \
+{ register struct frame_info *frame = get_current_frame (); \
+ register CORE_ADDR fp; \
+ register int regnum; \
+ struct frame_saved_regs fsr; \
+ struct frame_info *fi; \
+ fp = frame->frame; \
+ get_frame_saved_regs (frame, &fsr); \
+ for (regnum = 0; regnum < 8; regnum++) \
+ if (fsr.regs[regnum]) \
+ write_register (regnum, read_memory_integer (fsr.regs[regnum], 4)); \
+ write_register (FP_REGNUM, read_memory_integer (fp, 4)); \
+ write_register (PC_REGNUM, read_memory_integer (fp + 4, 4)); \
+ write_register (SP_REGNUM, fp + 8); \
+ flush_cached_frames (); \
+}
+
+/* This sequence of words is the instructions
+ enter 0xff,0 82 ff 00
+ jsr @0x00010203 7f ae c0 01 02 03
+ adjspd 0x69696969 7f a5 01 02 03 04
+ bpt f2
+ Note this is 16 bytes. */
+
+#define CALL_DUMMY { 0x7f00ff82, 0x0201c0ae, 0x01a57f03, 0xf2040302 }
+
+#define CALL_DUMMY_START_OFFSET 3
+#define CALL_DUMMY_LENGTH 16
+#define CALL_DUMMY_ADDR 5
+#define CALL_DUMMY_NARGS 11
+
+/* Insert the specified number of args and function address
+ into a call sequence of the above form stored at DUMMYNAME. */
+
+#define FIX_CALL_DUMMY(dummyname, pc, fun, nargs, args, type, gcc_p) \
+{ \
+ int flipped; \
+ flipped = fun | 0xc0000000; \
+ flip_bytes (&flipped, 4); \
+ *((int *) (((char *) dummyname)+CALL_DUMMY_ADDR)) = flipped; \
+ flipped = - nargs * 4; \
+ flip_bytes (&flipped, 4); \
+ *((int *) (((char *) dummyname)+CALL_DUMMY_NARGS)) = flipped; \
+}
diff --git a/gdb/config/ns32k/umax.mh b/gdb/config/ns32k/umax.mh
new file mode 100644
index 00000000000..e43f6ec8dae
--- /dev/null
+++ b/gdb/config/ns32k/umax.mh
@@ -0,0 +1,5 @@
+# Host: Encore running umax 4.2
+XDEPFILES= umax-xdep.o
+XM_FILE= xm-umax.h
+NAT_FILE= nm-umax.h
+NATDEPFILES= infptrace.o inftarg.o fork-child.o
diff --git a/gdb/config/ns32k/umax.mt b/gdb/config/ns32k/umax.mt
new file mode 100644
index 00000000000..4c9169d8e76
--- /dev/null
+++ b/gdb/config/ns32k/umax.mt
@@ -0,0 +1,3 @@
+# Target: Encore running umax 4.2
+TDEPFILES= ns32k-tdep.o
+TM_FILE= tm-umax.h
diff --git a/gdb/config/ns32k/xm-merlin.h b/gdb/config/ns32k/xm-merlin.h
new file mode 100644
index 00000000000..b8329f65d1b
--- /dev/null
+++ b/gdb/config/ns32k/xm-merlin.h
@@ -0,0 +1,65 @@
+/* Definitions to make GDB run on a merlin under utek 2.1
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include <machine/reg.h>
+
+/* This machine doesn't have the siginterrupt call. */
+#define NO_SIGINTERRUPT
+
+/* Under Utek, a ptrace'd process can be the only active process for
+ an executable. Therefore instead of /bin/sh use gdb-sh (which should
+ just be a copy of /bin/sh which is world readable and writeable). */
+/* FIXME: name should be passed in from Makefile so it can use prefix. */
+#define SHELL_FILE "/usr/local/lib/gdb-sh"
+
+#define HOST_BYTE_ORDER LITTLE_ENDIAN
+
+/* This is the amount to subtract from u.u_ar0
+ to get the offset in the core file of the register values. */
+
+#define KERNEL_U_ADDR (0xfef000)
+
+#define REGISTER_U_ADDR(addr, blockend, regno) \
+{ \
+ switch (regno) { \
+ case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: \
+ addr = blockend + (R0 - regno) * sizeof (int); break; \
+ case PC_REGNUM: \
+ addr = blockend + PC * sizeof (int); break; \
+ case SP_REGNUM: \
+ addr = blockend + SP * sizeof (int); break; \
+ case FP_REGNUM: \
+ addr = blockend + FP * sizeof (int); break; \
+ case PS_REGNUM: \
+ addr = blockend + 12 * sizeof (int); break; \
+ case FPS_REGNUM: \
+ addr = 108; break; \
+ case FP0_REGNUM + 0: case FP0_REGNUM + 1: \
+ case FP0_REGNUM + 2: case FP0_REGNUM + 3: \
+ case FP0_REGNUM + 4: case FP0_REGNUM + 5: \
+ case FP0_REGNUM + 6: case FP0_REGNUM + 7: \
+ addr = 76 + (regno - FP0_REGNUM) * sizeof (float); break; \
+ case LP0_REGNUM + 0: case LP0_REGNUM + 1: \
+ case LP0_REGNUM + 2: case LP0_REGNUM + 3: \
+ addr = 76 + (regno - LP0_REGNUM) * sizeof (double); break; \
+ default: \
+ printf ("bad argument to REGISTER_U_ADDR %d\n", regno); \
+ abort (); \
+ } \
+}
diff --git a/gdb/config/ns32k/xm-nbsd.h b/gdb/config/ns32k/xm-nbsd.h
new file mode 100644
index 00000000000..db8c0bcff1a
--- /dev/null
+++ b/gdb/config/ns32k/xm-nbsd.h
@@ -0,0 +1,21 @@
+/* Parameters for execution on a ns32k running NetBSD, for GDB.
+ Copyright 1994 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Get generic NetBSD host definitions. */
+#include "xm-nbsd.h"
diff --git a/gdb/config/ns32k/xm-ns32km3.h b/gdb/config/ns32k/xm-ns32km3.h
new file mode 100644
index 00000000000..3d08e67c82d
--- /dev/null
+++ b/gdb/config/ns32k/xm-ns32km3.h
@@ -0,0 +1,23 @@
+/* Definitions to make GDB run on Mach 3 on an National ns32k
+ Copyright (C) 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define HOST_BYTE_ORDER LITTLE_ENDIAN
+
+/* Do implement the attach and detach commands. */
+#define ATTACH_DETACH 1
diff --git a/gdb/config/ns32k/xm-umax.h b/gdb/config/ns32k/xm-umax.h
new file mode 100644
index 00000000000..1bb00714daf
--- /dev/null
+++ b/gdb/config/ns32k/xm-umax.h
@@ -0,0 +1,26 @@
+/* Definitions to make GDB run on an encore under umax 4.2
+ Copyright 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define HOST_BYTE_ORDER LITTLE_ENDIAN
+
+#define HAVE_WAIT_STRUCT
+
+/* Doesn't have siginterupt. */
+#define NO_SIGINTERRUPT
+
diff --git a/gdb/config/pa/hppabsd.mh b/gdb/config/pa/hppabsd.mh
new file mode 100644
index 00000000000..dfd2d4cca4b
--- /dev/null
+++ b/gdb/config/pa/hppabsd.mh
@@ -0,0 +1,7 @@
+# Host: Hewlett-Packard PA-RISC machine, running BSD
+XDEPFILES= ser-tcp.o
+XM_FILE= xm-hppab.h
+NAT_FILE= nm-hppab.h
+NATDEPFILES= hppab-nat.o corelow.o core-aout.o inftarg.o fork-child.o somread.o infptrace.o hp-psymtab-read.o hp-symtab-read.o somsolib.o
+
+GDBSERVER_DEPFILES= low-hppabsd.o
diff --git a/gdb/config/pa/hppabsd.mt b/gdb/config/pa/hppabsd.mt
new file mode 100644
index 00000000000..0fc0380c26a
--- /dev/null
+++ b/gdb/config/pa/hppabsd.mt
@@ -0,0 +1,3 @@
+# Target: HP PA-RISC running bsd
+TDEPFILES= hppa-tdep.o
+TM_FILE= tm-hppab.h
diff --git a/gdb/config/pa/hppahpux.mh b/gdb/config/pa/hppahpux.mh
new file mode 100644
index 00000000000..0d302448417
--- /dev/null
+++ b/gdb/config/pa/hppahpux.mh
@@ -0,0 +1,9 @@
+# Host: Hewlett-Packard PA-RISC machine, running HPUX
+
+XM_FILE= xm-hppah.h
+XDEPFILES= ser-tcp.o
+
+NAT_FILE= nm-hppah.h
+NATDEPFILES= hppah-nat.o corelow.o core-aout.o inftarg.o fork-child.o somread.o infptrace.o hp-psymtab-read.o hp-symtab-read.o somsolib.o
+
+HOST_IPC=-DBSD_IPC -DPOSIX_WAIT
diff --git a/gdb/config/pa/hppahpux.mt b/gdb/config/pa/hppahpux.mt
new file mode 100644
index 00000000000..dddb3f569a2
--- /dev/null
+++ b/gdb/config/pa/hppahpux.mt
@@ -0,0 +1,3 @@
+# Target: HP PA-RISC running hpux
+TDEPFILES= hppa-tdep.o
+TM_FILE= tm-hppah.h
diff --git a/gdb/config/pa/hppaosf.mh b/gdb/config/pa/hppaosf.mh
new file mode 100644
index 00000000000..6bde9c09aa6
--- /dev/null
+++ b/gdb/config/pa/hppaosf.mh
@@ -0,0 +1,9 @@
+# Host: Hewlett-Packard PA-RISC machine, running BSD
+XDEPFILES= ser-tcp.o
+XM_FILE= xm-hppab.h
+NAT_FILE= nm-hppao.h
+NATDEPFILES= fork-child.o m3-nat.o hppam3-nat.o somread.o hp-psymtab-read.o hp-symtab-read.o somsolib.o
+NAT_CLIBS= -lmachid -lnetname -lmach
+
+GDBSERVER_DEPFILES= low-hppabsd.o
+
diff --git a/gdb/config/pa/hppaosf.mt b/gdb/config/pa/hppaosf.mt
new file mode 100644
index 00000000000..675402387b6
--- /dev/null
+++ b/gdb/config/pa/hppaosf.mt
@@ -0,0 +1,3 @@
+# Target: HP PA-RISC running OSF1
+TDEPFILES= hppa-tdep.o
+TM_FILE= tm-hppao.h
diff --git a/gdb/config/pa/hppapro.mt b/gdb/config/pa/hppapro.mt
new file mode 100644
index 00000000000..4851b1896e7
--- /dev/null
+++ b/gdb/config/pa/hppapro.mt
@@ -0,0 +1,3 @@
+# Target: PA based debug monitor
+TDEPFILES= hppa-tdep.o op50-rom.o w89k-rom.o monitor.o xmodem.o dsrec.o
+TM_FILE= tm-pro.h
diff --git a/gdb/config/pa/hpux1020.mh b/gdb/config/pa/hpux1020.mh
new file mode 100644
index 00000000000..28eae11cf5c
--- /dev/null
+++ b/gdb/config/pa/hpux1020.mh
@@ -0,0 +1,11 @@
+# Host: Hewlett-Packard PA-RISC machine, running HPUX 10.20
+
+MH_CFLAGS = -D__HP_CURSES
+
+XM_FILE= xm-hppah.h
+XDEPFILES= ser-tcp.o
+
+NAT_FILE= nm-hppah.h
+NATDEPFILES= hppah-nat.o corelow.o core-aout.o inftarg.o fork-child.o infptrace.o somread.o hp-psymtab-read.o hp-symtab-read.o somsolib.o
+
+HOST_IPC=-DBSD_IPC -DPOSIX_WAIT
diff --git a/gdb/config/pa/hpux1020.mt b/gdb/config/pa/hpux1020.mt
new file mode 100644
index 00000000000..a856d8c1d1d
--- /dev/null
+++ b/gdb/config/pa/hpux1020.mt
@@ -0,0 +1,3 @@
+# Target: HP PA-RISC running hpux
+TDEPFILES= hppa-tdep.o remote-pa.o somsolib.o corelow.o
+TM_FILE= tm-hppah.h
diff --git a/gdb/config/pa/hpux1100.mh b/gdb/config/pa/hpux1100.mh
new file mode 100644
index 00000000000..10fbd7eb3bd
--- /dev/null
+++ b/gdb/config/pa/hpux1100.mh
@@ -0,0 +1,11 @@
+# Host: Hewlett-Packard PA-RISC machine, running HPUX 11.00
+
+MH_CFLAGS = -D__HP_CURSES
+
+XM_FILE= xm-hppah.h
+XDEPFILES= ser-tcp.o
+
+NAT_FILE= nm-hppah11.h
+NATDEPFILES= hppah-nat.o corelow.o core-aout.o inftarg.o fork-child.o infttrace.o somread.o hp-psymtab-read.o hp-symtab-read.o somsolib.o
+
+HOST_IPC=-DBSD_IPC -DPOSIX_WAIT
diff --git a/gdb/config/pa/hpux1100.mt b/gdb/config/pa/hpux1100.mt
new file mode 100644
index 00000000000..405f73a791a
--- /dev/null
+++ b/gdb/config/pa/hpux1100.mt
@@ -0,0 +1,3 @@
+# Target: HP PA-RISC running HPUX 11.00
+TDEPFILES= hppa-tdep.o remote-pa.o somsolib.o
+TM_FILE= tm-hppah.h
diff --git a/gdb/config/pa/nm-hppab.h b/gdb/config/pa/nm-hppab.h
new file mode 100644
index 00000000000..6b6367419c0
--- /dev/null
+++ b/gdb/config/pa/nm-hppab.h
@@ -0,0 +1,135 @@
+/* HPPA PA-RISC machine native support for BSD, for GDB.
+ Copyright 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "somsolib.h"
+
+#define U_REGS_OFFSET 0
+
+#define KERNEL_U_ADDR 0
+
+/* What a coincidence! */
+#define REGISTER_U_ADDR(addr, blockend, regno) \
+{ addr = (int)(blockend) + REGISTER_BYTE (regno);}
+
+/* 3rd argument to ptrace is supposed to be a caddr_t. */
+
+#define PTRACE_ARG3_TYPE caddr_t
+
+/* HPUX 8.0, in its infinite wisdom, has chosen to prototype ptrace
+ with five arguments, so programs written for normal ptrace lose. */
+#define FIVE_ARG_PTRACE
+
+
+/* This macro defines the register numbers (from REGISTER_NAMES) that
+ are effectively unavailable to the user through ptrace(). It allows
+ us to include the whole register set in REGISTER_NAMES (inorder to
+ better support remote debugging). If it is used in
+ fetch/store_inferior_registers() gdb will not complain about I/O errors
+ on fetching these registers. If all registers in REGISTER_NAMES
+ are available, then return false (0). */
+
+#define CANNOT_STORE_REGISTER(regno) \
+ ((regno) == 0) || \
+ ((regno) == PCSQ_HEAD_REGNUM) || \
+ ((regno) >= PCSQ_TAIL_REGNUM && (regno) < IPSW_REGNUM) || \
+ ((regno) > IPSW_REGNUM && (regno) < FP4_REGNUM)
+
+/* fetch_inferior_registers is in hppab-nat.c. */
+#define FETCH_INFERIOR_REGISTERS
+
+/* attach/detach works to some extent under BSD and HPUX. So long
+ as the process you're attaching to isn't blocked waiting on io,
+ blocked waiting on a signal, or in a system call things work
+ fine. (The problems in those cases are related to the fact that
+ the kernel can't provide complete register information for the
+ target process... Which really pisses off GDB.) */
+
+#define ATTACH_DETACH
+
+/* The PA-BSD kernel has support for using the data memory break bit
+ to implement fast watchpoints.
+
+ Watchpoints on the PA act much like traditional page protection
+ schemes, but with some notable differences.
+
+ First, a special bit in the page table entry is used to cause
+ a trap when a specific page is written to. This avoids having
+ to overload watchpoints on the page protection bits. This makes
+ it possible for the kernel to easily decide if a trap was caused
+ by a watchpoint or by the user writing to protected memory and can
+ signal the user program differently in each case.
+
+ Second, the PA has a bit in the processor status word which causes
+ data memory breakpoints (aka watchpoints) to be disabled for a single
+ instruction. This bit can be used to avoid the overhead of unprotecting
+ and reprotecting pages when it becomes necessary to step over a watchpoint.
+
+
+ When the kernel receives a trap indicating a write to a page which
+ is being watched, the kernel performs a couple of simple actions. First
+ is sets the magic "disable memory breakpoint" bit in the processor
+ status word, it then sends a SIGTRAP to the process which caused the
+ trap.
+
+ GDB will take control and catch the signal for the inferior. GDB then
+ examines the PSW-X bit to determine if the SIGTRAP was caused by a
+ watchpoint firing. If so GDB single steps the inferior over the
+ instruction which caused the watchpoint to trigger (note because the
+ kernel disabled the data memory break bit for one instruction no trap
+ will be taken!). GDB will then determines the appropriate action to
+ take. (this may include restarting the inferior if the watchpoint
+ fired because of a write to an address on the same page as a watchpoint,
+ but no write to the watched address occured). */
+
+#define TARGET_HAS_HARDWARE_WATCHPOINTS /* Enable the code in procfs.c */
+
+/* The PA can watch any number of locations, there's no need for it to reject
+ anything (generic routines already check that all intermediates are
+ in memory). */
+#define TARGET_CAN_USE_HARDWARE_WATCHPOINT(type, cnt, ot) \
+ ((type) == bp_hardware_watchpoint)
+
+/* When a hardware watchpoint fires off the PC will be left at the
+ instruction which caused the watchpoint. It will be necessary for
+ GDB to step over the watchpoint.
+
+ On a PA running BSD, it is trivial to identify when it will be
+ necessary to step over a hardware watchpoint as we can examine
+ the PSW-X bit. If the bit is on, then we trapped because of a
+ watchpoint, else we trapped for some other reason. */
+#define STOPPED_BY_WATCHPOINT(W) \
+ ((W).kind == TARGET_WAITKIND_STOPPED \
+ && (W).value.sig == TARGET_SIGNAL_TRAP \
+ && ((int) read_register (IPSW_REGNUM) & 0x00100000))
+
+/* The PA can single step over a watchpoint if the kernel has set the
+ "X" bit in the processor status word (disable data memory breakpoint
+ for one instruction).
+
+ The kernel will always set this bit before notifying the inferior
+ that it hit a watchpoint. Thus, the inferior can single step over
+ the instruction which caused the watchpoint to fire. This avoids
+ the traditional need to disable the watchpoint, step the inferior,
+ then enable the watchpoint again. */
+#define HAVE_STEPPABLE_WATCHPOINT
+
+/* Use these macros for watchpoint insertion/deletion. */
+/* type can be 0: write watch, 1: read watch, 2: access watch (read/write) */
+#define target_insert_watchpoint(addr, len, type) hppa_set_watchpoint (addr, len, 1)
+#define target_remove_watchpoint(addr, len, type) hppa_set_watchpoint (addr, len, 0)
diff --git a/gdb/config/pa/nm-hppah.h b/gdb/config/pa/nm-hppah.h
new file mode 100644
index 00000000000..0f5ef018bad
--- /dev/null
+++ b/gdb/config/pa/nm-hppah.h
@@ -0,0 +1,281 @@
+/* Native support for HPPA-RISC machine running HPUX, for GDB.
+ Copyright 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define U_REGS_OFFSET 0
+
+#define KERNEL_U_ADDR 0
+
+/* What a coincidence! */
+#define REGISTER_U_ADDR(addr, blockend, regno) \
+{ addr = (int)(blockend) + REGISTER_BYTE (regno);}
+
+/* HPUX 8.0, in its infinite wisdom, has chosen to prototype ptrace
+ with five arguments, so programs written for normal ptrace lose. */
+#define FIVE_ARG_PTRACE
+
+/* We need to figure out where the text region is so that we use the
+ appropriate ptrace operator to manipulate text. Simply reading/writing
+ user space will crap out HPUX. */
+#define NEED_TEXT_START_END 1
+
+/* This macro defines the register numbers (from REGISTER_NAMES) that
+ are effectively unavailable to the user through ptrace(). It allows
+ us to include the whole register set in REGISTER_NAMES (inorder to
+ better support remote debugging). If it is used in
+ fetch/store_inferior_registers() gdb will not complain about I/O errors
+ on fetching these registers. If all registers in REGISTER_NAMES
+ are available, then return false (0). */
+
+#define CANNOT_STORE_REGISTER(regno) \
+ ((regno) == 0) || \
+ ((regno) == PCSQ_HEAD_REGNUM) || \
+ ((regno) >= PCSQ_TAIL_REGNUM && (regno) < IPSW_REGNUM) || \
+ ((regno) > IPSW_REGNUM && (regno) < FP4_REGNUM)
+
+/* In hppah-nat.c: */
+#define FETCH_INFERIOR_REGISTERS
+#define CHILD_XFER_MEMORY
+#define CHILD_POST_FOLLOW_INFERIOR_BY_CLONE
+#define CHILD_POST_FOLLOW_VFORK
+
+/* While this is for use by threaded programs, it doesn't appear
+ * to hurt non-threaded ones. This is used in infrun.c: */
+#define PREPARE_TO_PROCEED() hppa_prepare_to_proceed()
+extern int hppa_prepare_to_proceed PARAMS(( void ));
+
+/* In infptrace.c or infttrace.c: */
+#define CHILD_PID_TO_EXEC_FILE
+#define CHILD_POST_STARTUP_INFERIOR
+#define CHILD_ACKNOWLEDGE_CREATED_INFERIOR
+#define CHILD_INSERT_FORK_CATCHPOINT
+#define CHILD_REMOVE_FORK_CATCHPOINT
+#define CHILD_INSERT_VFORK_CATCHPOINT
+#define CHILD_REMOVE_VFORK_CATCHPOINT
+#define CHILD_HAS_FORKED
+#define CHILD_HAS_VFORKED
+#define CHILD_CAN_FOLLOW_VFORK_PRIOR_TO_EXEC
+#define CHILD_INSERT_EXEC_CATCHPOINT
+#define CHILD_REMOVE_EXEC_CATCHPOINT
+#define CHILD_HAS_EXECD
+#define CHILD_REPORTED_EXEC_EVENTS_PER_EXEC_CALL
+#define CHILD_HAS_SYSCALL_EVENT
+#define CHILD_POST_ATTACH
+#define CHILD_THREAD_ALIVE
+
+#define REQUIRE_ATTACH(pid) hppa_require_attach(pid)
+extern int hppa_require_attach PARAMS ((int));
+
+#define REQUIRE_DETACH(pid,signal) hppa_require_detach(pid,signal)
+extern int hppa_require_detach PARAMS ((int,int));
+
+/* So we can cleanly use code in infptrace.c. */
+#define PT_KILL PT_EXIT
+#define PT_STEP PT_SINGLE
+#define PT_CONTINUE PT_CONTIN
+
+/* FIXME HP MERGE : Previously, PT_RDUAREA. this is actually fixed
+ in gdb-hp-snapshot-980509 */
+#define PT_READ_U PT_RUAREA
+#define PT_WRITE_U PT_WUAREA
+#define PT_READ_I PT_RIUSER
+#define PT_READ_D PT_RDUSER
+#define PT_WRITE_I PT_WIUSER
+#define PT_WRITE_D PT_WDUSER
+
+/* attach/detach works to some extent under BSD and HPUX. So long
+ as the process you're attaching to isn't blocked waiting on io,
+ blocked waiting on a signal, or in a system call things work
+ fine. (The problems in those cases are related to the fact that
+ the kernel can't provide complete register information for the
+ target process... Which really pisses off GDB.) */
+
+#define ATTACH_DETACH
+
+/* In infptrace or infttrace.c: */
+
+/* Starting with HP-UX 10.30, support is provided (in the form of
+ ttrace requests) for memory-protection-based hardware watchpoints.
+
+ The 10.30 implementation of these functions reside in infttrace.c.
+
+ Stubs of these functions will be provided in infptrace.c, so that
+ 10.20 will at least link. However, the "can I use a fast watchpoint?"
+ query will always return "No" for 10.20. */
+
+#define TARGET_HAS_HARDWARE_WATCHPOINTS
+
+/* The PA can watch any number of locations (generic routines already check
+ that all intermediates are in watchable memory locations). */
+#define TARGET_CAN_USE_HARDWARE_WATCHPOINT(type, cnt, ot) \
+ hppa_can_use_hw_watchpoint(type, cnt, ot)
+
+/* The PA can also watch memory regions of arbitrary size, since we're using
+ a page-protection scheme. (On some targets, apparently watch registers
+ are used, which can only accomodate regions of REGISTER_SIZE.) */
+#define TARGET_REGION_SIZE_OK_FOR_HW_WATCHPOINT(byte_count) \
+ (1)
+
+/* However, some addresses may not be profitable to use hardware to watch,
+ or may be difficult to understand when the addressed object is out of
+ scope, and hence should be unwatched. On some targets, this may have
+ severe performance penalties, such that we might as well use regular
+ watchpoints, and save (possibly precious) hardware watchpoints for other
+ locations.
+
+ On HP-UX, we choose not to watch stack-based addresses, because
+
+ [1] Our implementation relies on page protection traps. The granularity
+ of these is large and so can generate many false hits, which are expensive
+ to respond to.
+
+ [2] Watches of "*p" where we may not know the symbol that p points to,
+ make it difficult to know when the addressed object is out of scope, and
+ hence shouldn't be watched. Page protection that isn't removed when the
+ addressed object is out of scope will either degrade execution speed
+ (false hits) or give false triggers (when the address is recycled by
+ other calls).
+
+ Since either of these points results in a slow-running inferior, we might
+ as well use normal watchpoints, aka single-step & test. */
+#define TARGET_RANGE_PROFITABLE_FOR_HW_WATCHPOINT(pid,start,len) \
+ hppa_range_profitable_for_hw_watchpoint(pid, start, (LONGEST)(len))
+
+/* On HP-UX, we're using page-protection to implement hardware watchpoints.
+ When an instruction attempts to write to a write-protected memory page,
+ a SIGBUS is raised. At that point, the write has not actually occurred.
+
+ We must therefore remove page-protections; single-step the inferior (to
+ allow the write to happen); restore page-protections; and check whether
+ any watchpoint triggered.
+
+ If none did, then the write was to a "nearby" location that just happens
+ to fall on the same page as a watched location, and so can be ignored.
+
+ The only intended client of this macro is wait_for_inferior(), in infrun.c.
+ When HAVE_NONSTEPPABLE_WATCHPOINT is true, that function will take care
+ of the stepping & etc. */
+
+#define STOPPED_BY_WATCHPOINT(W) \
+ ((W.kind == TARGET_WAITKIND_STOPPED) && \
+ (stop_signal == TARGET_SIGNAL_BUS) && \
+ ! stepped_after_stopped_by_watchpoint && \
+ bpstat_have_active_hw_watchpoints ())
+
+/* When a hardware watchpoint triggers, we'll move the inferior past it
+ by removing all eventpoints; stepping past the instruction that caused
+ the trigger; reinserting eventpoints; and checking whether any watched
+ location changed. */
+#define HAVE_NONSTEPPABLE_WATCHPOINT
+
+/* Our implementation of "hardware" watchpoints uses memory page-protection
+ faults. However, HP-UX has unfortunate interactions between these and
+ system calls; basically, it's unsafe to have page protections on when a
+ syscall is running. Therefore, we also ask for notification of syscall
+ entries and returns. When the inferior enters a syscall, we disable
+ h/w watchpoints. When the inferior returns from a syscall, we reenable
+ h/w watchpoints.
+
+ infptrace.c supplies dummy versions of these; infttrace.c is where the
+ meaningful implementations are.
+ */
+#define TARGET_ENABLE_HW_WATCHPOINTS(pid) \
+ hppa_enable_page_protection_events (pid)
+extern void hppa_enable_page_protection_events PARAMS ((int));
+
+#define TARGET_DISABLE_HW_WATCHPOINTS(pid) \
+ hppa_disable_page_protection_events (pid)
+extern void hppa_disable_page_protection_events PARAMS ((int));
+
+/* Use these macros for watchpoint insertion/deletion. */
+#define target_insert_watchpoint(addr, len, type) \
+ hppa_insert_hw_watchpoint (inferior_pid, addr, (LONGEST)(len), type)
+
+#define target_remove_watchpoint(addr, len, type) \
+ hppa_remove_hw_watchpoint (inferior_pid, addr, (LONGEST)(len), type)
+
+/* We call our k-thread processes "threads", rather
+ * than processes. So we need a new way to print
+ * the string. Code is in hppah-nat.c.
+ */
+#define target_pid_to_str( pid ) \
+ hppa_pid_to_str( pid )
+extern char * hppa_pid_to_str PARAMS ((pid_t));
+
+#define target_tid_to_str( pid ) \
+ hppa_tid_to_str( pid )
+extern char * hppa_tid_to_str PARAMS ((pid_t));
+
+/* For this, ID can be either a process or thread ID, and the function
+ will describe it appropriately, returning the description as a printable
+ string.
+
+ The function that implements this macro is defined in infptrace.c and
+ infttrace.c.
+ */
+#define target_pid_or_tid_to_str(ID) \
+ hppa_pid_or_tid_to_str (ID)
+extern char * hppa_pid_or_tid_to_str PARAMS ((pid_t));
+
+/* This is used when handling events caused by a call to vfork(). On ptrace-
+ based HP-UXs, when you resume the vforked child, the parent automagically
+ begins running again. To prevent this runaway, this function is used.
+
+ Note that for vfork on HP-UX, we receive three events of interest:
+
+ 1. the vfork event for the new child process
+ 2. the exit or exec event of the new child process (actually, you get
+ two exec events on ptrace-based HP-UXs)
+ 3. the vfork event for the original parent process
+
+ The first is always received first. The other two may be received in any
+ order; HP-UX doesn't guarantee an order.
+ */
+#define ENSURE_VFORKING_PARENT_REMAINS_STOPPED(PID) \
+ hppa_ensure_vforking_parent_remains_stopped (PID)
+extern void hppa_ensure_vforking_parent_remains_stopped PARAMS((int));
+
+/* This is used when handling events caused by a call to vfork().
+
+ On ttrace-based HP-UXs, the parent vfork and child exec arrive more or less
+ together. That is, you could do two wait()s without resuming either parent
+ or child, and get both events.
+
+ On ptrace-based HP-UXs, you must resume the child after its exec event is
+ delivered or you won't get the parent's vfork. I.e., you can't just wait()
+ and get the parent vfork, after receiving the child exec.
+ */
+#define RESUME_EXECD_VFORKING_CHILD_TO_GET_PARENT_VFORK() \
+ hppa_resume_execd_vforking_child_to_get_parent_vfork ()
+extern int hppa_resume_execd_vforking_child_to_get_parent_vfork PARAMS ((void));
+
+#ifdef HAVE_HPUX_THREAD_SUPPORT
+
+#ifdef __STDC__
+struct objfile;
+#endif
+
+void hpux_thread_new_objfile PARAMS ((struct objfile *objfile));
+#define target_new_objfile(OBJFILE) hpux_thread_new_objfile (OBJFILE)
+
+extern char *hpux_pid_to_str PARAMS ((int pid));
+#define target_pid_to_str(PID) hpux_pid_to_str (PID)
+
+#endif /* HAVE_HPUX_THREAD_SUPPORT */
+
+#define HPUXHPPA
diff --git a/gdb/config/pa/nm-hppah11.h b/gdb/config/pa/nm-hppah11.h
new file mode 100644
index 00000000000..7a73c241b7e
--- /dev/null
+++ b/gdb/config/pa/nm-hppah11.h
@@ -0,0 +1,22 @@
+/* Native support for HPPA-RISC machine running HPUX 11.x, for GDB.
+ Copyright 1998 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define GDB_NATIVE_HPUX_11
+
+#include "pa/nm-hppah.h"
diff --git a/gdb/config/pa/nm-hppao.h b/gdb/config/pa/nm-hppao.h
new file mode 100644
index 00000000000..a09dfd1c14c
--- /dev/null
+++ b/gdb/config/pa/nm-hppao.h
@@ -0,0 +1,56 @@
+/* HPPA PA-RISC machine native support for Lites, for GDB.
+ Copyright 1995 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "nm-m3.h"
+#define U_REGS_OFFSET 0
+
+#define KERNEL_U_ADDR 0
+
+/* What a coincidence! */
+#define REGISTER_U_ADDR(addr, blockend, regno) \
+{ addr = (int)(blockend) + REGISTER_BYTE (regno);}
+
+/* This macro defines the register numbers (from REGISTER_NAMES) that
+ are effectively unavailable to the user through ptrace(). It allows
+ us to include the whole register set in REGISTER_NAMES (inorder to
+ better support remote debugging). If it is used in
+ fetch/store_inferior_registers() gdb will not complain about I/O errors
+ on fetching these registers. If all registers in REGISTER_NAMES
+ are available, then return false (0). */
+
+#define CANNOT_STORE_REGISTER(regno) \
+ ((regno) == 0) || \
+ ((regno) == PCSQ_HEAD_REGNUM) || \
+ ((regno) >= PCSQ_TAIL_REGNUM && (regno) < IPSW_REGNUM) || \
+ ((regno) > IPSW_REGNUM && (regno) < FP4_REGNUM)
+
+/* fetch_inferior_registers is in hppab-nat.c. */
+#define FETCH_INFERIOR_REGISTERS
+
+/* attach/detach works to some extent under BSD and HPUX. So long
+ as the process you're attaching to isn't blocked waiting on io,
+ blocked waiting on a signal, or in a system call things work
+ fine. (The problems in those cases are related to the fact that
+ the kernel can't provide complete register information for the
+ target process... Which really pisses off GDB.) */
+
+#define ATTACH_DETACH
+
+#define EMULATOR_BASE 0x90100000
+#define EMULATOR_END 0x90200000
diff --git a/gdb/config/pa/tm-hppa.h b/gdb/config/pa/tm-hppa.h
new file mode 100644
index 00000000000..559534a050c
--- /dev/null
+++ b/gdb/config/pa/tm-hppa.h
@@ -0,0 +1,788 @@
+/* Parameters for execution on any Hewlett-Packard PA-RISC machine.
+ Copyright 1986, 1987, 1989, 1990, 1991, 1992, 1993, 1995
+ Free Software Foundation, Inc.
+
+ Contributed by the Center for Software Science at the
+ University of Utah (pa-gdb-bugs@cs.utah.edu).
+
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Forward declarations of some types we use in prototypes */
+
+#ifdef __STDC__
+struct frame_info;
+struct frame_saved_regs;
+struct value;
+struct type;
+struct inferior_status;
+#endif
+
+/* Target system byte order. */
+
+#define TARGET_BYTE_ORDER BIG_ENDIAN
+
+/* By default assume we don't have to worry about software floating point. */
+#ifndef SOFT_FLOAT
+#define SOFT_FLOAT 0
+#endif
+
+/* Get at various relevent fields of an instruction word. */
+
+#define MASK_5 0x1f
+#define MASK_11 0x7ff
+#define MASK_14 0x3fff
+#define MASK_21 0x1fffff
+
+/* This macro gets bit fields using HP's numbering (MSB = 0) */
+#ifndef GET_FIELD
+#define GET_FIELD(X, FROM, TO) \
+ ((X) >> (31 - (TO)) & ((1 << ((TO) - (FROM) + 1)) - 1))
+#endif
+
+/* Watch out for NaNs */
+
+#define IEEE_FLOAT
+
+/* On the PA, any pass-by-value structure > 8 bytes is actually
+ passed via a pointer regardless of its type or the compiler
+ used. */
+
+#define REG_STRUCT_HAS_ADDR(gcc_p,type) \
+ (TYPE_LENGTH (type) > 8)
+
+/* Offset from address of function to start of its code.
+ Zero on most machines. */
+
+#define FUNCTION_START_OFFSET 0
+
+/* Advance PC across any function entry prologue instructions
+ to reach some "real" code. */
+
+#define SKIP_PROLOGUE(pc) pc = skip_prologue (pc)
+extern CORE_ADDR skip_prologue PARAMS ((CORE_ADDR));
+
+/* If PC is in some function-call trampoline code, return the PC
+ where the function itself actually starts. If not, return NULL. */
+
+#define SKIP_TRAMPOLINE_CODE(pc) skip_trampoline_code (pc, NULL)
+extern CORE_ADDR skip_trampoline_code PARAMS ((CORE_ADDR, char *));
+
+/* Return non-zero if we are in an appropriate trampoline. */
+
+#define IN_SOLIB_CALL_TRAMPOLINE(pc, name) \
+ in_solib_call_trampoline (pc, name)
+extern int in_solib_call_trampoline PARAMS ((CORE_ADDR, char *));
+
+#define IN_SOLIB_RETURN_TRAMPOLINE(pc, name) \
+ in_solib_return_trampoline (pc, name)
+extern int in_solib_return_trampoline PARAMS ((CORE_ADDR, char *));
+
+/* Immediately after a function call, return the saved pc.
+ Can't go through the frames for this because on some machines
+ the new frame is not set up until the new function executes
+ some instructions. */
+
+#undef SAVED_PC_AFTER_CALL
+#define SAVED_PC_AFTER_CALL(frame) saved_pc_after_call (frame)
+extern CORE_ADDR saved_pc_after_call PARAMS ((struct frame_info *));
+
+/* Stack grows upward */
+#define INNER_THAN(lhs,rhs) ((lhs) > (rhs))
+
+/* elz: adjust the quantity to the next highest value which is 64-bit aligned.
+ This is used in valops.c, when the sp is adjusted.
+ On hppa the sp must always be kept 64-bit aligned*/
+
+#define STACK_ALIGN(arg) ( ((arg)%8) ? (((arg)+7)&-8) : (arg))
+#define NO_EXTRA_ALIGNMENT_NEEDED 1
+
+/* Sequence of bytes for breakpoint instruction. */
+
+#define BREAKPOINT {0x00, 0x01, 0x00, 0x04}
+#define BREAKPOINT32 0x10004
+
+/* Amount PC must be decremented by after a breakpoint.
+ This is often the number of bytes in BREAKPOINT
+ but not always.
+
+ Not on the PA-RISC */
+
+#define DECR_PC_AFTER_BREAK 0
+
+/* Sometimes we may pluck out a minimal symbol that has a negative
+ address.
+
+ An example of this occurs when an a.out is linked against a foo.sl.
+ The foo.sl defines a global bar(), and the a.out declares a signature
+ for bar(). However, the a.out doesn't directly call bar(), but passes
+ its address in another call.
+
+ If you have this scenario and attempt to "break bar" before running,
+ gdb will find a minimal symbol for bar() in the a.out. But that
+ symbol's address will be negative. What this appears to denote is
+ an index backwards from the base of the procedure linkage table (PLT)
+ into the data linkage table (DLT), the end of which is contiguous
+ with the start of the PLT. This is clearly not a valid address for
+ us to set a breakpoint on.
+
+ Note that one must be careful in how one checks for a negative address.
+ 0xc0000000 is a legitimate address of something in a shared text
+ segment, for example. Since I don't know what the possible range
+ is of these "really, truly negative" addresses that come from the
+ minimal symbols, I'm resorting to the gross hack of checking the
+ top byte of the address for all 1's. Sigh.
+ */
+#define PC_REQUIRES_RUN_BEFORE_USE(pc) \
+ (! target_has_stack && (pc & 0xFF000000))
+
+/* return instruction is bv r0(rp) or bv,n r0(rp)*/
+
+#define ABOUT_TO_RETURN(pc) ((read_memory_integer (pc, 4) | 0x2) == 0xE840C002)
+
+/* Say how long (ordinary) registers are. This is a piece of bogosity
+ used in push_word and a few other places; REGISTER_RAW_SIZE is the
+ real way to know how big a register is. */
+
+#define REGISTER_SIZE 4
+
+/* Number of machine registers */
+
+#define NUM_REGS 128
+
+/* Initializer for an array of names of registers.
+ There should be NUM_REGS strings in this initializer.
+ They are in rows of eight entries */
+
+#define REGISTER_NAMES \
+ {"flags", "r1", "rp", "r3", "r4", "r5", "r6", "r7", \
+ "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", \
+ "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", \
+ "r24", "r25", "r26", "dp", "ret0", "ret1", "sp", "r31", \
+ "sar", "pcoqh", "pcsqh", "pcoqt", "pcsqt", "eiem", "iir", "isr", \
+ "ior", "ipsw", "goto", "sr4", "sr0", "sr1", "sr2", "sr3", \
+ "sr5", "sr6", "sr7", "cr0", "cr8", "cr9", "ccr", "cr12", \
+ "cr13", "cr24", "cr25", "cr26", "mpsfu_high","mpsfu_low","mpsfu_ovflo","pad",\
+ "fpsr", "fpe1", "fpe2", "fpe3", "fpe4", "fpe5", "fpe6", "fpe7", \
+ "fr4", "fr4R", "fr5", "fr5R", "fr6", "fr6R", "fr7", "fr7R", \
+ "fr8", "fr8R", "fr9", "fr9R", "fr10", "fr10R", "fr11", "fr11R", \
+ "fr12", "fr12R", "fr13", "fr13R", "fr14", "fr14R", "fr15", "fr15R", \
+ "fr16", "fr16R", "fr17", "fr17R", "fr18", "fr18R", "fr19", "fr19R", \
+ "fr20", "fr20R", "fr21", "fr21R", "fr22", "fr22R", "fr23", "fr23R", \
+ "fr24", "fr24R", "fr25", "fr25R", "fr26", "fr26R", "fr27", "fr27R", \
+ "fr28", "fr28R", "fr29", "fr29R", "fr30", "fr30R", "fr31", "fr31R"}
+
+/* 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 R0_REGNUM 0 /* Doesn't actually exist, used as base for
+ other r registers. */
+#define FLAGS_REGNUM 0 /* Various status flags */
+#define RP_REGNUM 2 /* return pointer */
+#define FP_REGNUM 3 /* Contains address of executing stack */
+ /* frame */
+#define SP_REGNUM 30 /* Contains address of top of stack */
+#define SAR_REGNUM 32 /* Shift Amount Register */
+#define IPSW_REGNUM 41 /* Interrupt Processor Status Word */
+#define PCOQ_HEAD_REGNUM 33 /* instruction offset queue head */
+#define PCSQ_HEAD_REGNUM 34 /* instruction space queue head */
+#define PCOQ_TAIL_REGNUM 35 /* instruction offset queue tail */
+#define PCSQ_TAIL_REGNUM 36 /* instruction space queue tail */
+#define EIEM_REGNUM 37 /* External Interrupt Enable Mask */
+#define IIR_REGNUM 38 /* Interrupt Instruction Register */
+#define IOR_REGNUM 40 /* Interrupt Offset Register */
+#define SR4_REGNUM 43 /* space register 4 */
+#define RCR_REGNUM 51 /* Recover Counter (also known as cr0) */
+#define CCR_REGNUM 54 /* Coprocessor Configuration Register */
+#define TR0_REGNUM 57 /* Temporary Registers (cr24 -> cr31) */
+#define CR27_REGNUM 60 /* Base register for thread-local storage, cr27 */
+#define FP0_REGNUM 64 /* floating point reg. 0 (fspr)*/
+#define FP4_REGNUM 72
+
+#define ARG0_REGNUM 26 /* The first argument of a callee. */
+#define ARG1_REGNUM 25 /* The second argument of a callee. */
+#define ARG2_REGNUM 24 /* The third argument of a callee. */
+#define ARG3_REGNUM 23 /* The fourth argument of a callee. */
+
+/* compatibility with the rest of gdb. */
+#define PC_REGNUM PCOQ_HEAD_REGNUM
+#define NPC_REGNUM PCOQ_TAIL_REGNUM
+
+/*
+ * Processor Status Word Masks
+ */
+
+#define PSW_T 0x01000000 /* Taken Branch Trap Enable */
+#define PSW_H 0x00800000 /* Higher-Privilege Transfer Trap Enable */
+#define PSW_L 0x00400000 /* Lower-Privilege Transfer Trap Enable */
+#define PSW_N 0x00200000 /* PC Queue Front Instruction Nullified */
+#define PSW_X 0x00100000 /* Data Memory Break Disable */
+#define PSW_B 0x00080000 /* Taken Branch in Previous Cycle */
+#define PSW_C 0x00040000 /* Code Address Translation Enable */
+#define PSW_V 0x00020000 /* Divide Step Correction */
+#define PSW_M 0x00010000 /* High-Priority Machine Check Disable */
+#define PSW_CB 0x0000ff00 /* Carry/Borrow Bits */
+#define PSW_R 0x00000010 /* Recovery Counter Enable */
+#define PSW_Q 0x00000008 /* Interruption State Collection Enable */
+#define PSW_P 0x00000004 /* Protection ID Validation Enable */
+#define PSW_D 0x00000002 /* Data Address Translation Enable */
+#define PSW_I 0x00000001 /* External, Power Failure, Low-Priority */
+ /* Machine Check Interruption Enable */
+
+/* When fetching register values from an inferior or a core file,
+ clean them up using this macro. BUF is a char pointer to
+ the raw value of the register in the registers[] array. */
+
+#define CLEAN_UP_REGISTER_VALUE(regno, buf) \
+ do { \
+ if ((regno) == PCOQ_HEAD_REGNUM || (regno) == PCOQ_TAIL_REGNUM) \
+ (buf)[3] &= ~0x3; \
+ } while (0)
+
+/* Define DO_REGISTERS_INFO() to do machine-specific formatting
+ of register dumps. */
+
+#define DO_REGISTERS_INFO(_regnum, fp) pa_do_registers_info (_regnum, fp)
+extern void pa_do_registers_info PARAMS ((int, int));
+
+#if 0
+#define STRCAT_REGISTER(regnum, fpregs, stream, precision) pa_do_strcat_registers_info (regnum, fpregs, stream, precision)
+extern void pa_do_strcat_registers_info PARAMS ((int, int, GDB_FILE *, enum precision_type));
+#endif
+
+/* PA specific macro to see if the current instruction is nullified. */
+#ifndef INSTRUCTION_NULLIFIED
+#define INSTRUCTION_NULLIFIED \
+ (((int)read_register (IPSW_REGNUM) & 0x00200000) && \
+ !((int)read_register (FLAGS_REGNUM) & 0x2))
+#endif
+
+/* Number of bytes of storage in the actual machine representation
+ for register N. On the PA-RISC, all regs are 4 bytes, including
+ the FP registers (they're accessed as two 4 byte halves). */
+
+#define REGISTER_RAW_SIZE(N) 4
+
+/* 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 program's representation
+ for register N. */
+
+#define REGISTER_VIRTUAL_SIZE(N) REGISTER_RAW_SIZE(N)
+
+/* Largest value REGISTER_RAW_SIZE can have. */
+
+#define MAX_REGISTER_RAW_SIZE 4
+
+/* Largest value REGISTER_VIRTUAL_SIZE can have. */
+
+#define MAX_REGISTER_VIRTUAL_SIZE 8
+
+/* Return the GDB type object for the "standard" data type
+ of data in register N. */
+
+#define REGISTER_VIRTUAL_TYPE(N) \
+ ((N) < FP4_REGNUM ? builtin_type_int : builtin_type_float)
+
+/* Store the address of the place in which to copy the structure the
+ subroutine will return. This is called from call_function. */
+
+#define STORE_STRUCT_RETURN(ADDR, SP) {write_register (28, (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.
+
+ elz: changed what to return when length is > 4: the stored result is
+ in register 28 and in register 29, with the lower order word being in reg 29,
+ so we must start reading it from somehere in the middle of reg28
+
+ FIXME: Not sure what to do for soft float here. */
+
+#define EXTRACT_RETURN_VALUE(TYPE,REGBUF,VALBUF) \
+ { \
+ if (TYPE_CODE (TYPE) == TYPE_CODE_FLT && !SOFT_FLOAT) \
+ memcpy ((VALBUF), \
+ ((char *)(REGBUF)) + REGISTER_BYTE (FP4_REGNUM), \
+ TYPE_LENGTH (TYPE)); \
+ else \
+ memcpy ((VALBUF), \
+ (char *)(REGBUF) + REGISTER_BYTE (28) + \
+ (TYPE_LENGTH (TYPE) > 4 ? (8 - TYPE_LENGTH (TYPE)) : (4 - TYPE_LENGTH (TYPE))), \
+ TYPE_LENGTH (TYPE)); \
+ }
+
+
+ /* elz: decide whether the function returning a value of type type
+ will put it on the stack or in the registers.
+ The pa calling convention says that:
+ register 28 (called ret0 by gdb) contains any ASCII char,
+ and any non_floating point value up to 32-bits.
+ reg 28 and 29 contain non-floating point up tp 64 bits and larger
+ than 32 bits. (higer order word in reg 28).
+ fr4: floating point up to 64 bits
+ sr1: space identifier (32-bit)
+ stack: any lager than 64-bit, with the address in r28
+ */
+extern use_struct_convention_fn hppa_use_struct_convention;
+#define USE_STRUCT_CONVENTION(gcc_p,type) hppa_use_struct_convention (gcc_p,type)
+
+/* Write into appropriate registers a function return value
+ of type TYPE, given in virtual format.
+
+ For software floating point the return value goes into the integer
+ registers. But we don't have any flag to key this on, so we always
+ store the value into the integer registers, and if it's a float value,
+ then we put it in the float registers too. */
+
+#define STORE_RETURN_VALUE(TYPE,VALBUF) \
+ write_register_bytes (REGISTER_BYTE (28),(VALBUF), TYPE_LENGTH (TYPE)) ; \
+ if (!SOFT_FLOAT) \
+ write_register_bytes ((TYPE_CODE(TYPE) == TYPE_CODE_FLT \
+ ? REGISTER_BYTE (FP4_REGNUM) \
+ : REGISTER_BYTE (28)), \
+ (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) + REGISTER_BYTE (28)))
+
+/* elz: Return a large value, which is stored on the stack at addr.
+ This is defined only for the hppa, at this moment.
+ The above macro EXTRACT_STRUCT_VALUE_ADDRESS is not called anymore,
+ because it assumes that on exit from a called function which returns
+ a large structure on the stack, the address of the ret structure is
+ still in register 28. Unfortunately this register is usually overwritten
+ by the called function itself, on hppa. This is specified in the calling
+ convention doc. As far as I know, the only way to get the return value
+ is to have the caller tell us where it told the callee to put it, rather
+ than have the callee tell us.
+*/
+#define VALUE_RETURNED_FROM_STACK(valtype,addr) \
+ hppa_value_returned_from_stack (valtype, addr)
+
+/*
+ * This macro defines the register numbers (from REGISTER_NAMES) that
+ * are effectively unavailable to the user through ptrace(). It allows
+ * us to include the whole register set in REGISTER_NAMES (inorder to
+ * better support remote debugging). If it is used in
+ * fetch/store_inferior_registers() gdb will not complain about I/O errors
+ * on fetching these registers. If all registers in REGISTER_NAMES
+ * are available, then return false (0).
+ */
+
+#define CANNOT_STORE_REGISTER(regno) \
+ ((regno) == 0) || \
+ ((regno) == PCSQ_HEAD_REGNUM) || \
+ ((regno) >= PCSQ_TAIL_REGNUM && (regno) < IPSW_REGNUM) || \
+ ((regno) > IPSW_REGNUM && (regno) < FP4_REGNUM)
+
+#define INIT_EXTRA_FRAME_INFO(fromleaf, frame) init_extra_frame_info (fromleaf, frame)
+extern void init_extra_frame_info PARAMS ((int, struct frame_info *));
+
+/* Describe the pointer in each stack frame to the previous stack frame
+ (its caller). */
+
+/* FRAME_CHAIN takes a frame's nominal address
+ and produces the frame's chain-pointer.
+
+ FRAME_CHAIN_COMBINE takes the chain pointer and the frame's nominal address
+ and produces the nominal address of the caller frame.
+
+ However, if FRAME_CHAIN_VALID returns zero,
+ it means the given frame is the outermost one and has no caller.
+ In that case, FRAME_CHAIN_COMBINE is not used. */
+
+/* In the case of the PA-RISC, the frame's nominal address
+ is the address of a 4-byte word containing the calling frame's
+ address (previous FP). */
+
+#define FRAME_CHAIN(thisframe) frame_chain (thisframe)
+extern CORE_ADDR frame_chain PARAMS ((struct frame_info *));
+
+extern int hppa_frame_chain_valid PARAMS ((CORE_ADDR, struct frame_info *));
+#define FRAME_CHAIN_VALID(chain, thisframe) hppa_frame_chain_valid (chain, thisframe)
+
+#define FRAME_CHAIN_COMBINE(chain, thisframe) (chain)
+
+/* Define other aspects of the stack frame. */
+
+/* A macro that tells us whether the function invocation represented
+ by FI does not have a frame on the stack associated with it. If it
+ does not, FRAMELESS is set to 1, else 0. */
+#define FRAMELESS_FUNCTION_INVOCATION(FI, FRAMELESS) \
+ (FRAMELESS) = frameless_function_invocation(FI)
+extern int frameless_function_invocation PARAMS ((struct frame_info *));
+
+extern CORE_ADDR hppa_frame_saved_pc PARAMS ((struct frame_info *frame));
+#define FRAME_SAVED_PC(FRAME) hppa_frame_saved_pc (FRAME)
+
+#define FRAME_ARGS_ADDRESS(fi) ((fi)->frame)
+
+#define FRAME_LOCALS_ADDRESS(fi) ((fi)->frame)
+/* Set VAL to the number of args passed to frame described by FI.
+ Can set VAL to -1, meaning no way to tell. */
+
+/* We can't tell how many args there are
+ now that the C compiler delays popping them. */
+#define FRAME_NUM_ARGS(val,fi) (val = -1)
+
+/* Return number of bytes at start of arglist that are not really args. */
+
+#define FRAME_ARGS_SKIP 0
+
+#define FRAME_FIND_SAVED_REGS(frame_info, frame_saved_regs) \
+ hppa_frame_find_saved_regs (frame_info, &frame_saved_regs)
+extern void
+hppa_frame_find_saved_regs PARAMS ((struct frame_info *,
+ struct frame_saved_regs *));
+
+
+/* Things needed for making the inferior call functions. */
+
+/* Push an empty stack frame, to record the current PC, etc. */
+
+#define PUSH_DUMMY_FRAME push_dummy_frame (&inf_status)
+extern void push_dummy_frame PARAMS ((struct inferior_status *));
+
+/* Discard from the stack the innermost frame,
+ restoring all saved registers. */
+#define POP_FRAME hppa_pop_frame ()
+extern void hppa_pop_frame PARAMS ((void));
+
+#define INSTRUCTION_SIZE 4
+
+#ifndef PA_LEVEL_0
+
+/* Non-level zero PA's have space registers (but they don't always have
+ floating-point, do they???? */
+
+/* This sequence of words is the instructions
+
+; Call stack frame has already been built by gdb. Since we could be calling
+; a varargs function, and we do not have the benefit of a stub to put things in
+; the right place, we load the first 4 word of arguments into both the general
+; and fp registers.
+call_dummy
+ ldw -36(sp), arg0
+ ldw -40(sp), arg1
+ ldw -44(sp), arg2
+ ldw -48(sp), arg3
+ ldo -36(sp), r1
+ fldws 0(0, r1), fr4
+ fldds -4(0, r1), fr5
+ fldws -8(0, r1), fr6
+ fldds -12(0, r1), fr7
+ ldil 0, r22 ; FUNC_LDIL_OFFSET must point here
+ ldo 0(r22), r22 ; FUNC_LDO_OFFSET must point here
+ ldsid (0,r22), r4
+ ldil 0, r1 ; SR4EXPORT_LDIL_OFFSET must point here
+ ldo 0(r1), r1 ; SR4EXPORT_LDO_OFFSET must point here
+ ldsid (0,r1), r20
+ combt,=,n r4, r20, text_space ; If target is in data space, do a
+ ble 0(sr5, r22) ; "normal" procedure call
+ copy r31, r2
+ break 4, 8
+ mtsp r21, sr0
+ ble,n 0(sr0, r22)
+text_space ; Otherwise, go through _sr4export,
+ ble (sr4, r1) ; which will return back here.
+ stw r31,-24(r30)
+ break 4, 8
+ mtsp r21, sr0
+ ble,n 0(sr0, r22)
+ nop ; To avoid kernel bugs
+ nop ; and keep the dummy 8 byte aligned
+
+ The dummy decides if the target is in text space or data space. If
+ it's in data space, there's no problem because the target can
+ return back to the dummy. However, if the target is in text space,
+ the dummy calls the secret, undocumented routine _sr4export, which
+ calls a function in text space and can return to any space. Instead
+ of including fake instructions to represent saved registers, we
+ know that the frame is associated with the call dummy and treat it
+ specially.
+
+ The trailing NOPs are needed to avoid a bug in HPUX, BSD and OSF1
+ kernels. If the memory at the location pointed to by the PC is
+ 0xffffffff then a ptrace step call will fail (even if the instruction
+ is nullified).
+
+ The code to pop a dummy frame single steps three instructions
+ starting with the last mtsp. This includes the nullified "instruction"
+ following the ble (which is uninitialized junk). If the
+ "instruction" following the last BLE is 0xffffffff, then the ptrace
+ will fail and the dummy frame is not correctly popped.
+
+ By placing a NOP in the delay slot of the BLE instruction we can be
+ sure that we never try to execute a 0xffffffff instruction and
+ avoid the kernel bug. The second NOP is needed to keep the call
+ dummy 8 byte aligned. */
+
+/* Define offsets into the call dummy for the target function address */
+#define FUNC_LDIL_OFFSET (INSTRUCTION_SIZE * 9)
+#define FUNC_LDO_OFFSET (INSTRUCTION_SIZE * 10)
+
+/* Define offsets into the call dummy for the _sr4export address */
+#define SR4EXPORT_LDIL_OFFSET (INSTRUCTION_SIZE * 12)
+#define SR4EXPORT_LDO_OFFSET (INSTRUCTION_SIZE * 13)
+
+#define CALL_DUMMY {0x4BDA3FB9, 0x4BD93FB1, 0x4BD83FA9, 0x4BD73FA1,\
+ 0x37C13FB9, 0x24201004, 0x2C391005, 0x24311006,\
+ 0x2C291007, 0x22C00000, 0x36D60000, 0x02C010A4,\
+ 0x20200000, 0x34210000, 0x002010b4, 0x82842022,\
+ 0xe6c06000, 0x081f0242, 0x00010004, 0x00151820,\
+ 0xe6c00002, 0xe4202000, 0x6bdf3fd1, 0x00010004,\
+ 0x00151820, 0xe6c00002, 0x08000240, 0x08000240}
+
+#define CALL_DUMMY_LENGTH (INSTRUCTION_SIZE * 28)
+
+#else /* defined PA_LEVEL_0 */
+
+/* This is the call dummy for a level 0 PA. Level 0's don't have space
+ registers (or floating point??), so we skip all that inter-space call stuff,
+ and avoid touching the fp regs.
+
+call_dummy
+
+ ldw -36(%sp), %arg0
+ ldw -40(%sp), %arg1
+ ldw -44(%sp), %arg2
+ ldw -48(%sp), %arg3
+ ldil 0, %r31 ; FUNC_LDIL_OFFSET must point here
+ ldo 0(%r31), %r31 ; FUNC_LDO_OFFSET must point here
+ ble 0(%sr0, %r31)
+ copy %r31, %r2
+ break 4, 8
+ nop ; restore_pc_queue expects these
+ bv,n 0(%r22) ; instructions to be here...
+ nop
+*/
+
+/* Define offsets into the call dummy for the target function address */
+#define FUNC_LDIL_OFFSET (INSTRUCTION_SIZE * 4)
+#define FUNC_LDO_OFFSET (INSTRUCTION_SIZE * 5)
+
+#define CALL_DUMMY {0x4bda3fb9, 0x4bd93fb1, 0x4bd83fa9, 0x4bd73fa1,\
+ 0x23e00000, 0x37ff0000, 0xe7e00000, 0x081f0242,\
+ 0x00010004, 0x08000240, 0xeac0c002, 0x08000240}
+
+#define CALL_DUMMY_LENGTH (INSTRUCTION_SIZE * 12)
+
+#endif
+
+#define CALL_DUMMY_START_OFFSET 0
+
+/* If we've reached a trap instruction within the call dummy, then
+ we'll consider that to mean that we've reached the call dummy's
+ end after its successful completion. */
+#define CALL_DUMMY_HAS_COMPLETED(pc, sp, frame_address) \
+ (PC_IN_CALL_DUMMY((pc), (sp), (frame_address)) && \
+ (read_memory_integer((pc), 4) == BREAKPOINT32))
+
+/*
+ * Insert the specified number of args and function address
+ * into a call sequence of the above form stored at DUMMYNAME.
+ *
+ * On the hppa we need to call the stack dummy through $$dyncall.
+ * Therefore our version of FIX_CALL_DUMMY takes an extra argument,
+ * real_pc, which is the location where gdb should start up the
+ * inferior to do the function call.
+ */
+
+#define FIX_CALL_DUMMY hppa_fix_call_dummy
+
+extern CORE_ADDR
+hppa_fix_call_dummy PARAMS ((char *, CORE_ADDR, CORE_ADDR, int,
+ struct value **, struct type *, int));
+
+#define PUSH_ARGUMENTS(nargs, args, sp, struct_return, struct_addr) \
+ sp = hppa_push_arguments((nargs), (args), (sp), (struct_return), (struct_addr))
+extern CORE_ADDR
+hppa_push_arguments PARAMS ((int, struct value **, CORE_ADDR, int,
+ CORE_ADDR));
+
+/* The low two bits of the PC on the PA contain the privilege level. Some
+ genius implementing a (non-GCC) compiler apparently decided this means
+ that "addresses" in a text section therefore include a privilege level,
+ and thus symbol tables should contain these bits. This seems like a
+ bonehead thing to do--anyway, it seems to work for our purposes to just
+ ignore those bits. */
+#define SMASH_TEXT_ADDRESS(addr) ((addr) &= ~0x3)
+
+#define GDB_TARGET_IS_HPPA
+
+#define BELIEVE_PCC_PROMOTION 1
+
+/*
+ * Unwind table and descriptor.
+ */
+
+struct unwind_table_entry {
+ unsigned int region_start;
+ unsigned int region_end;
+
+ unsigned int Cannot_unwind : 1; /* 0 */
+ unsigned int Millicode : 1; /* 1 */
+ unsigned int Millicode_save_sr0 : 1; /* 2 */
+ unsigned int Region_description : 2; /* 3..4 */
+ unsigned int reserved1 : 1; /* 5 */
+ unsigned int Entry_SR : 1; /* 6 */
+ unsigned int Entry_FR : 4; /* number saved */ /* 7..10 */
+ unsigned int Entry_GR : 5; /* number saved */ /* 11..15 */
+ unsigned int Args_stored : 1; /* 16 */
+ unsigned int Variable_Frame : 1; /* 17 */
+ unsigned int Separate_Package_Body : 1; /* 18 */
+ unsigned int Frame_Extension_Millicode:1; /* 19 */
+ unsigned int Stack_Overflow_Check : 1; /* 20 */
+ unsigned int Two_Instruction_SP_Increment:1; /* 21 */
+ unsigned int Ada_Region : 1; /* 22 */
+ unsigned int cxx_info : 1; /* 23 */
+ unsigned int cxx_try_catch : 1; /* 24 */
+ unsigned int sched_entry_seq : 1; /* 25 */
+ unsigned int reserved2 : 1; /* 26 */
+ unsigned int Save_SP : 1; /* 27 */
+ unsigned int Save_RP : 1; /* 28 */
+ unsigned int Save_MRP_in_frame : 1; /* 29 */
+ unsigned int extn_ptr_defined : 1; /* 30 */
+ unsigned int Cleanup_defined : 1; /* 31 */
+
+ unsigned int MPE_XL_interrupt_marker: 1; /* 0 */
+ unsigned int HP_UX_interrupt_marker: 1; /* 1 */
+ unsigned int Large_frame : 1; /* 2 */
+ unsigned int Pseudo_SP_Set : 1; /* 3 */
+ unsigned int reserved4 : 1; /* 4 */
+ unsigned int Total_frame_size : 27; /* 5..31 */
+
+ /* This is *NOT* part of an actual unwind_descriptor in an object
+ file. It is *ONLY* part of the "internalized" descriptors that
+ we create from those in a file.
+ */
+ struct {
+ unsigned int stub_type : 4; /* 0..3 */
+ unsigned int padding : 28; /* 4..31 */
+ } stub_unwind;
+};
+
+/* HP linkers also generate unwinds for various linker-generated stubs.
+ GDB reads in the stubs from the $UNWIND_END$ subspace, then
+ "converts" them into normal unwind entries using some of the reserved
+ fields to store the stub type. */
+
+struct stub_unwind_entry
+{
+ /* The offset within the executable for the associated stub. */
+ unsigned stub_offset;
+
+ /* The type of stub this unwind entry describes. */
+ char type;
+
+ /* Unknown. Not needed by GDB at this time. */
+ char prs_info;
+
+ /* Length (in instructions) of the associated stub. */
+ short stub_length;
+};
+
+/* Sizes (in bytes) of the native unwind entries. */
+#define UNWIND_ENTRY_SIZE 16
+#define STUB_UNWIND_ENTRY_SIZE 8
+
+/* The gaps represent linker stubs used in MPE and space for future
+ expansion. */
+enum unwind_stub_types
+{
+ LONG_BRANCH = 1,
+ PARAMETER_RELOCATION = 2,
+ EXPORT = 10,
+ IMPORT = 11,
+};
+
+/* We use the objfile->obj_private pointer for two things:
+ *
+ * 1. An unwind table;
+ *
+ * 2. A pointer to any associated shared library object.
+ *
+ * #defines are used to help refer to these objects.
+ */
+
+/* Info about the unwind table associated with an object file.
+ *
+ * This is hung off of the "objfile->obj_private" pointer, and
+ * is allocated in the objfile's psymbol obstack. This allows
+ * us to have unique unwind info for each executable and shared
+ * library that we are debugging.
+ */
+struct obj_unwind_info {
+ struct unwind_table_entry *table; /* Pointer to unwind info */
+ struct unwind_table_entry *cache; /* Pointer to last entry we found */
+ int last; /* Index of last entry */
+};
+
+typedef struct obj_private_struct {
+ struct obj_unwind_info *unwind_info; /* a pointer */
+ struct so_list *so_info; /* a pointer */
+} obj_private_data_t;
+
+#if 0
+extern void target_write_pc PARAMS ((CORE_ADDR, int))
+extern CORE_ADDR target_read_pc PARAMS ((int));
+extern CORE_ADDR skip_trampoline_code PARAMS ((CORE_ADDR, char *));
+#endif
+
+#define TARGET_READ_PC(pid) target_read_pc (pid)
+extern CORE_ADDR target_read_pc PARAMS ((int));
+
+#define TARGET_WRITE_PC(v,pid) target_write_pc (v,pid)
+extern void target_write_pc PARAMS ((CORE_ADDR, int));
+
+#define TARGET_READ_FP() target_read_fp (inferior_pid)
+extern CORE_ADDR target_read_fp PARAMS ((int));
+
+/* For a number of horrible reasons we may have to adjust the location
+ of variables on the stack. Ugh. */
+#define HPREAD_ADJUST_STACK_ADDRESS(ADDR) hpread_adjust_stack_address(ADDR)
+
+extern int hpread_adjust_stack_address PARAMS ((CORE_ADDR));
+
+/* If the current gcc for for this target does not produce correct debugging
+ information for float parameters, both prototyped and unprototyped, then
+ define this macro. This forces gdb to always assume that floats are
+ passed as doubles and then converted in the callee.
+
+ For the pa, it appears that the debug info marks the parameters as
+ floats regardless of whether the function is prototyped, but the actual
+ values are passed as doubles for the non-prototyped case and floats for
+ the prototyped case. Thus we choose to make the non-prototyped case work
+ for C and break the prototyped case, since the non-prototyped case is
+ probably much more common. (FIXME). */
+
+#define COERCE_FLOAT_TO_DOUBLE (current_language -> la_language == language_c)
diff --git a/gdb/config/pa/tm-hppab.h b/gdb/config/pa/tm-hppab.h
new file mode 100644
index 00000000000..1cd438df75e
--- /dev/null
+++ b/gdb/config/pa/tm-hppab.h
@@ -0,0 +1,47 @@
+/* Parameters for execution on an HP PA-RISC machine running BSD, for GDB.
+ Contributed by the Center for Software Science at the
+ University of Utah (pa-gdb-bugs@cs.utah.edu). */
+
+/* For BSD:
+
+ The signal context structure pointer is always saved at the base
+ of the frame + 0x4.
+
+ We get the PC & SP directly from the sigcontext structure itself.
+ For other registers we have to dive in a little deeper:
+
+ The hardware save state pointer is at offset 0x10 within the
+ signal context structure.
+
+ Within the hardware save state, registers are found in the same order
+ as the register numbers in GDB. */
+
+#define FRAME_SAVED_PC_IN_SIGTRAMP(FRAME, TMP) \
+{ \
+ *(TMP) = read_memory_integer ((FRAME)->frame + 0x4, 4); \
+ *(TMP) = read_memory_integer (*(TMP) + 0x18, 4); \
+}
+
+#define FRAME_BASE_BEFORE_SIGTRAMP(FRAME, TMP) \
+{ \
+ *(TMP) = read_memory_integer ((FRAME)->frame + 0x4, 4); \
+ *(TMP) = read_memory_integer (*(TMP) + 0x8, 4); \
+}
+
+#define FRAME_FIND_SAVED_REGS_IN_SIGTRAMP(FRAME, FSR) \
+{ \
+ int i; \
+ CORE_ADDR TMP; \
+ TMP = read_memory_integer ((FRAME)->frame + 0x4, 4); \
+ TMP = read_memory_integer (TMP + 0x10, 4); \
+ for (i = 0; i < NUM_REGS; i++) \
+ { \
+ if (i == SP_REGNUM) \
+ (FSR)->regs[SP_REGNUM] = read_memory_integer (TMP + SP_REGNUM * 4, 4); \
+ else \
+ (FSR)->regs[i] = TMP + i * 4; \
+ } \
+}
+
+/* It's mostly just the common stuff. */
+#include "pa/tm-hppa.h"
diff --git a/gdb/config/pa/tm-hppah.h b/gdb/config/pa/tm-hppah.h
new file mode 100644
index 00000000000..a8f11668c57
--- /dev/null
+++ b/gdb/config/pa/tm-hppah.h
@@ -0,0 +1,79 @@
+/* Parameters for execution on an HP PA-RISC machine, running HPUX, for GDB.
+ Copyright 1991, 1992 Free Software Foundation, Inc.
+
+ Contributed by the Center for Software Science at the
+ University of Utah (pa-gdb-bugs@cs.utah.edu).
+
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define HPUX_SNAP1
+#define HPUX_SNAP2
+
+#include "somsolib.h"
+
+/* Actually, for a PA running HPUX the kernel calls the signal handler
+ without an intermediate trampoline. Luckily the kernel always sets
+ the return pointer for the signal handler to point to _sigreturn. */
+#define IN_SIGTRAMP(pc, name) (name && STREQ ("_sigreturn", name))
+
+/* For HPUX:
+
+ The signal context structure pointer is always saved at the base
+ of the frame which "calls" the signal handler. We only want to find
+ the hardware save state structure, which lives 10 32bit words into
+ sigcontext structure.
+
+ Within the hardware save state structure, registers are found in the
+ same order as the register numbers in GDB.
+
+ At one time we peeked at %r31 rather than the PC queues to determine
+ what instruction took the fault. This was done on purpose, but I don't
+ remember why. Looking at the PC queues is really the right way, and
+ I don't remember why that didn't work when this code was originally
+ written. */
+
+#define FRAME_SAVED_PC_IN_SIGTRAMP(FRAME, TMP) \
+{ \
+ *(TMP) = read_memory_integer ((FRAME)->frame + (43 * 4) , 4); \
+}
+
+#define FRAME_BASE_BEFORE_SIGTRAMP(FRAME, TMP) \
+{ \
+ *(TMP) = read_memory_integer ((FRAME)->frame + (40 * 4), 4); \
+}
+
+#define FRAME_FIND_SAVED_REGS_IN_SIGTRAMP(FRAME, FSR) \
+{ \
+ int i; \
+ CORE_ADDR TMP; \
+ TMP = (FRAME)->frame + (10 * 4); \
+ for (i = 0; i < NUM_REGS; i++) \
+ { \
+ if (i == SP_REGNUM) \
+ (FSR)->regs[SP_REGNUM] = read_memory_integer (TMP + SP_REGNUM * 4, 4); \
+ else \
+ (FSR)->regs[i] = TMP + i * 4; \
+ } \
+}
+
+/* For HP-UX on PA-RISC we have an implementation
+ for the exception handling target op (in hppa-tdep.c) */
+#define CHILD_ENABLE_EXCEPTION_CALLBACK
+#define CHILD_GET_CURRENT_EXCEPTION_EVENT
+
+/* Mostly it's common to all HPPA's. */
+#include "pa/tm-hppa.h"
diff --git a/gdb/config/pa/tm-hppao.h b/gdb/config/pa/tm-hppao.h
new file mode 100644
index 00000000000..7df42474744
--- /dev/null
+++ b/gdb/config/pa/tm-hppao.h
@@ -0,0 +1,96 @@
+/* Parameters for execution on an HP PA-RISC machine running OSF1, for GDB.
+ Contributed by the Center for Software Science at the
+ University of Utah (pa-gdb-bugs@cs.utah.edu). */
+
+/* Define offsets to access CPROC stack when it does not have
+ * a kernel thread.
+ */
+#define MACHINE_CPROC_SP_OFFSET 20
+#define MACHINE_CPROC_PC_OFFSET 16
+#define MACHINE_CPROC_FP_OFFSET 12
+
+/*
+ * Software defined PSW masks.
+ */
+#define PSW_SS 0x10000000 /* Kernel managed single step */
+
+/* Thread flavors used in re-setting the T bit.
+ * @@ this is also bad for cross debugging.
+ */
+#define TRACE_FLAVOR HP800_THREAD_STATE
+#define TRACE_FLAVOR_SIZE HP800_THREAD_STATE_COUNT
+#define TRACE_SET(x,state) \
+ ((struct hp800_thread_state *)state)->cr22 |= PSW_SS
+#define TRACE_CLEAR(x,state) \
+ ((((struct hp800_thread_state *)state)->cr22 &= ~PSW_SS), 1)
+
+/* For OSF1 (Should be close if not identical to BSD, but I haven't
+ tested it yet):
+
+ The signal context structure pointer is always saved at the base
+ of the frame + 0x4.
+
+ We get the PC & SP directly from the sigcontext structure itself.
+ For other registers we have to dive in a little deeper:
+
+ The hardware save state pointer is at offset 0x10 within the
+ signal context structure.
+
+ Within the hardware save state, registers are found in the same order
+ as the register numbers in GDB. */
+
+#define FRAME_SAVED_PC_IN_SIGTRAMP(FRAME, TMP) \
+{ \
+ *(TMP) = read_memory_integer ((FRAME)->frame + 0x4, 4); \
+ *(TMP) = read_memory_integer (*(TMP) + 0x18, 4); \
+}
+
+#define FRAME_BASE_BEFORE_SIGTRAMP(FRAME, TMP) \
+{ \
+ *(TMP) = read_memory_integer ((FRAME)->frame + 0x4, 4); \
+ *(TMP) = read_memory_integer (*(TMP) + 0x8, 4); \
+}
+
+#define FRAME_FIND_SAVED_REGS_IN_SIGTRAMP(FRAME, FSR) \
+{ \
+ int i; \
+ CORE_ADDR TMP; \
+ TMP = read_memory_integer ((FRAME)->frame + 0x4, 4); \
+ TMP = read_memory_integer (TMP + 0x10, 4); \
+ for (i = 0; i < NUM_REGS; i++) \
+ { \
+ if (i == SP_REGNUM) \
+ (FSR)->regs[SP_REGNUM] = read_memory_integer (TMP + SP_REGNUM * 4, 4); \
+ else \
+ (FSR)->regs[i] = TMP + i * 4; \
+ } \
+}
+
+/* OSF1 does not need the pc space queue restored. */
+#define NO_PC_SPACE_QUEUE_RESTORE
+
+/* The mach kernel uses the recovery counter to implement single
+ stepping. While this greatly simplifies the kernel support
+ necessary for single stepping, it unfortunately does the wrong
+ thing in the presense of a nullified instruction (gives control
+ back two insns after the nullifed insn). This is an artifact
+ of the HP architecture (recovery counter doesn't tick for
+ nullified insns).
+
+ Do our best to avoid losing in such situations. */
+#define INSTRUCTION_NULLIFIED \
+(({ \
+ int ipsw = (int)read_register(IPSW_REGNUM); \
+ if (ipsw & PSW_N) \
+ { \
+ int pcoqt = (int)read_register(PCOQ_TAIL_REGNUM); \
+ write_register(PCOQ_HEAD_REGNUM, pcoqt); \
+ write_register(PCOQ_TAIL_REGNUM, pcoqt + 0x4); \
+ write_register(IPSW_REGNUM, ipsw & ~(PSW_N | PSW_B | PSW_X)); \
+ stop_pc = pcoqt; \
+ } \
+ }), 0)
+
+/* It's mostly just the common stuff. */
+
+#include "pa/tm-hppa.h"
diff --git a/gdb/config/pa/tm-pro.h b/gdb/config/pa/tm-pro.h
new file mode 100644
index 00000000000..05ecb62f7dc
--- /dev/null
+++ b/gdb/config/pa/tm-pro.h
@@ -0,0 +1,14 @@
+/* Parameters for execution on an HP PA-RISC level 0 embedded system.
+ This is based on tm-hppab.h.
+ Contributed by the Center for Software Science at the
+ University of Utah (pa-gdb-bugs@cs.utah.edu). */
+
+#define PA_LEVEL_0 /* Disables touching space regs and fp */
+
+/* All the PRO targets use software floating point at the moment. */
+#define SOFT_FLOAT 1
+
+/* It's mostly just the common stuff. */
+#include "pa/tm-hppa.h"
+
+#define GDB_TARGET_IS_PA_ELF
diff --git a/gdb/config/pa/xm-hppab.h b/gdb/config/pa/xm-hppab.h
new file mode 100644
index 00000000000..9f6467fcf0a
--- /dev/null
+++ b/gdb/config/pa/xm-hppab.h
@@ -0,0 +1,27 @@
+/* Parameters for hosting on an HPPA PA-RISC machine, running BSD, for GDB.
+ Copyright 1991, 1992 Free Software Foundation, Inc.
+
+ Contributed by the Center for Software Science at the
+ University of Utah (pa-gdb-bugs@cs.utah.edu).
+
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* This is a big-endian host. */
+
+#define HOST_BYTE_ORDER BIG_ENDIAN
+
+#include "pa/xm-pa.h"
diff --git a/gdb/config/pa/xm-hppah.h b/gdb/config/pa/xm-hppah.h
new file mode 100644
index 00000000000..2cd47ddcf03
--- /dev/null
+++ b/gdb/config/pa/xm-hppah.h
@@ -0,0 +1,49 @@
+/* Parameters for hosting on an HPPA-RISC machine running HPUX, for GDB.
+ Copyright 1991, 1992 Free Software Foundation, Inc.
+
+ Contributed by the Center for Software Science at the
+ University of Utah (pa-gdb-bugs@cs.utah.edu).
+
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Host is big-endian. */
+#define HOST_BYTE_ORDER BIG_ENDIAN
+
+#include "pa/xm-pa.h"
+
+#define USG
+
+#ifndef __STDC__
+/* This define is discussed in decode_line_1 in symtab.c */
+#define HPPA_COMPILER_BUG
+#endif
+
+#define HAVE_TERMIOS
+
+/* HP defines malloc and realloc as returning void *, even for non-ANSI
+ compilations (such as with the native compiler). */
+
+#define MALLOC_INCOMPATIBLE
+
+extern void *
+malloc PARAMS ((size_t));
+
+extern void *
+realloc PARAMS ((void *, size_t));
+
+extern void
+free PARAMS ((void *));
diff --git a/gdb/config/pa/xm-pa.h b/gdb/config/pa/xm-pa.h
new file mode 100644
index 00000000000..979609d4776
--- /dev/null
+++ b/gdb/config/pa/xm-pa.h
@@ -0,0 +1,5 @@
+/* Definitions for all PA machines. */
+
+/* This was created for "makeva", which is obsolete. This file can
+ probably go away (unless someone can think of some other host thing
+ which is common to various pa machines). */
diff --git a/gdb/config/powerpc/aix.mh b/gdb/config/powerpc/aix.mh
new file mode 100644
index 00000000000..bac3e30216c
--- /dev/null
+++ b/gdb/config/powerpc/aix.mh
@@ -0,0 +1,11 @@
+# Host: IBM PowerPC running AIX
+
+XM_FILE= xm-aix.h
+XDEPFILES=
+
+NAT_FILE= nm-aix.h
+NATDEPFILES= fork-child.o infptrace.o inftarg.o corelow.o rs6000-nat.o xcoffread.o
+
+# When compiled with cc, for debugging, this argument should be passed.
+# We have no idea who our current compiler is though, so we skip it.
+# MH_CFLAGS = -bnodelcsect
diff --git a/gdb/config/powerpc/aix.mt b/gdb/config/powerpc/aix.mt
new file mode 100644
index 00000000000..6d03b7de26b
--- /dev/null
+++ b/gdb/config/powerpc/aix.mt
@@ -0,0 +1,3 @@
+# Target: PowerPC running AIX
+TDEPFILES= rs6000-tdep.o xcoffsolib.o
+TM_FILE= tm-ppc-aix.h
diff --git a/gdb/config/powerpc/cygwin.mh b/gdb/config/powerpc/cygwin.mh
new file mode 100644
index 00000000000..0c257092e70
--- /dev/null
+++ b/gdb/config/powerpc/cygwin.mh
@@ -0,0 +1,5 @@
+MH_CFLAGS=
+XM_FILE=xm-cygwin.h
+XDEP_FILES=ser-tcp.o
+NATDEPFILES=win32-nat.o
+XM_CLIBS=-lkernel32
diff --git a/gdb/config/powerpc/cygwin.mt b/gdb/config/powerpc/cygwin.mt
new file mode 100644
index 00000000000..b86b2afa285
--- /dev/null
+++ b/gdb/config/powerpc/cygwin.mt
@@ -0,0 +1,6 @@
+# Target: Powerpc running cygnus's unix api over win32
+TDEPFILES= rs6000-tdep.o
+TM_FILE= tm-cygwin.h
+
+
+
diff --git a/gdb/config/powerpc/gdbserve.mt b/gdb/config/powerpc/gdbserve.mt
new file mode 100644
index 00000000000..77284077db6
--- /dev/null
+++ b/gdb/config/powerpc/gdbserve.mt
@@ -0,0 +1,3 @@
+# Target: GDBSERVE.NLM running on a Power-PC
+TDEPFILES= ppc.o
+CPU_FILE= ppc
diff --git a/gdb/config/powerpc/linux.mh b/gdb/config/powerpc/linux.mh
new file mode 100644
index 00000000000..0de0e20ad7f
--- /dev/null
+++ b/gdb/config/powerpc/linux.mh
@@ -0,0 +1,10 @@
+# Host: PowerPC, running Linux
+
+XM_FILE= xm-linux.h
+XDEPFILES= ser-tcp.o
+XM_CLIBS=
+
+NAT_FILE= ../nm-sysv4.h
+NATDEPFILES= solib.o corelow.o # infptrace.o inftarg.o fork-child.o core-aout.o core-regset.o
+
+GDBSERVER_DEPFILES= low-linux.o
diff --git a/gdb/config/powerpc/macos.mh b/gdb/config/powerpc/macos.mh
new file mode 100644
index 00000000000..63b064878cd
--- /dev/null
+++ b/gdb/config/powerpc/macos.mh
@@ -0,0 +1,4 @@
+# Host: PowerMac (PowerPC running MacOS)
+
+NATDEPFILES= mac-nat.o
+NAT_FILE= nm-macos.h
diff --git a/gdb/config/powerpc/macos.mt b/gdb/config/powerpc/macos.mt
new file mode 100644
index 00000000000..07ad0d2208f
--- /dev/null
+++ b/gdb/config/powerpc/macos.mt
@@ -0,0 +1,3 @@
+# Target: PowerMac (PowerPC running MacOS)
+TDEPFILES= rs6000-tdep.o xcoffread.o
+TM_FILE= tm-macos.h
diff --git a/gdb/config/powerpc/nm-aix.h b/gdb/config/powerpc/nm-aix.h
new file mode 100644
index 00000000000..9661d50f668
--- /dev/null
+++ b/gdb/config/powerpc/nm-aix.h
@@ -0,0 +1,22 @@
+/* IBM PowerPC native-dependent macros for GDB, the GNU debugger.
+ Copyright 1995 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 "rs6000/nm-rs6000.h"
+
+#define PTRACE_ARG3_TYPE int*
diff --git a/gdb/config/powerpc/nm-macos.h b/gdb/config/powerpc/nm-macos.h
new file mode 100644
index 00000000000..a1a3d9e6c3d
--- /dev/null
+++ b/gdb/config/powerpc/nm-macos.h
@@ -0,0 +1,20 @@
+/* PowerMac native-dependent macros for GDB, the GNU debugger.
+ Copyright (C) 1995 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Nothing needed, at least so far. */
diff --git a/gdb/config/powerpc/nm-solaris.h b/gdb/config/powerpc/nm-solaris.h
new file mode 100644
index 00000000000..b276a7151ef
--- /dev/null
+++ b/gdb/config/powerpc/nm-solaris.h
@@ -0,0 +1,30 @@
+/* Native-dependent definitions for PowerPC running Solaris.
+ Copyright 1996 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Include the generic SVR4 definitions. */
+
+#include <nm-sysv4.h>
+
+/* Before storing, we need to read all the registers. */
+
+#define CHILD_PREPARE_TO_STORE() read_register_bytes (0, NULL, REGISTER_BYTES)
+
+/* Solaris PSRVADDR support does not seem to include a place for nPC. */
+
+#define PRSVADDR_BROKEN
diff --git a/gdb/config/powerpc/ppc-eabi.mt b/gdb/config/powerpc/ppc-eabi.mt
new file mode 100644
index 00000000000..c4e21c8177e
--- /dev/null
+++ b/gdb/config/powerpc/ppc-eabi.mt
@@ -0,0 +1,3 @@
+# Target: PowerPC running eabi
+TDEPFILES= ser-ocd.o rs6000-tdep.o monitor.o dsrec.o ppcbug-rom.o dink32-rom.o ppc-bdm.o ocd.o remote-sds.o
+TM_FILE= tm-ppc-eabi.h
diff --git a/gdb/config/powerpc/ppc-nw.mt b/gdb/config/powerpc/ppc-nw.mt
new file mode 100644
index 00000000000..0eaa23d55b7
--- /dev/null
+++ b/gdb/config/powerpc/ppc-nw.mt
@@ -0,0 +1,3 @@
+# Target: PowerPC running Netware
+TDEPFILES= rs6000-tdep.o
+TM_FILE= tm-ppc-nw.h
diff --git a/gdb/config/powerpc/ppc-sim.mt b/gdb/config/powerpc/ppc-sim.mt
new file mode 100644
index 00000000000..c73fef2885d
--- /dev/null
+++ b/gdb/config/powerpc/ppc-sim.mt
@@ -0,0 +1,6 @@
+# Target: PowerPC running eabi and including the simulator
+TDEPFILES= ser-ocd.o rs6000-tdep.o monitor.o dsrec.o ppcbug-rom.o dink32-rom.o ppc-bdm.o ocd.o remote-sds.o
+TM_FILE= tm-ppc-eabi.h
+
+SIM_OBS = remote-sim.o
+SIM = ../sim/ppc/libsim.a
diff --git a/gdb/config/powerpc/ppcle-eabi.mt b/gdb/config/powerpc/ppcle-eabi.mt
new file mode 100644
index 00000000000..b336a111ce2
--- /dev/null
+++ b/gdb/config/powerpc/ppcle-eabi.mt
@@ -0,0 +1,3 @@
+# Target: PowerPC running eabi in little endian mode
+TDEPFILES= ser-ocd.o rs6000-tdep.o monitor.o dsrec.o ppcbug-rom.o ppc-bdm.o ocd.o
+TM_FILE= tm-ppcle-eabi.h
diff --git a/gdb/config/powerpc/ppcle-sim.mt b/gdb/config/powerpc/ppcle-sim.mt
new file mode 100644
index 00000000000..f08dafe53ac
--- /dev/null
+++ b/gdb/config/powerpc/ppcle-sim.mt
@@ -0,0 +1,6 @@
+# Target: PowerPC running eabi in little endian mode under the simulator
+TDEPFILES= ser-ocd.o rs6000-tdep.o monitor.o dsrec.o ppcbug-rom.o ppc-bdm.o ocd.o
+TM_FILE= tm-ppcle-eabi.h
+
+SIM_OBS = remote-sim.o
+SIM = ../sim/ppc/libsim.a
diff --git a/gdb/config/powerpc/solaris.mh b/gdb/config/powerpc/solaris.mh
new file mode 100644
index 00000000000..7d3444e2b1b
--- /dev/null
+++ b/gdb/config/powerpc/solaris.mh
@@ -0,0 +1,18 @@
+# Host: PowerPC, running Solaris 2
+
+XM_FILE= xm-solaris.h
+XDEPFILES= ser-tcp.o
+XM_CLIBS= -lsocket -lnsl
+
+NAT_FILE= nm-solaris.h
+NATDEPFILES= corelow.o core-sol2.o solib.o procfs.o fork-child.o
+
+# If you are compiling with Sun's compiler, add the -xs option to CC
+# (e.g. `make CC="cc -xs"').
+# Sun's compilers require the -xs option to produce debug information
+# in the final linked executable. Otherwise they leave it in the .o
+# files only, with undocumented pointers to it in the linked executable.
+# This is commented out because we don't assume that the Sun compiler
+# is in use.
+#MH_CFLAGS=-xs
+HOST_IPC=-DBSD_IPC
diff --git a/gdb/config/powerpc/solaris.mt b/gdb/config/powerpc/solaris.mt
new file mode 100644
index 00000000000..a6e421e7e02
--- /dev/null
+++ b/gdb/config/powerpc/solaris.mt
@@ -0,0 +1,3 @@
+# Target: PowerPC, running Solaris 2
+TDEPFILES= rs6000-tdep.o
+TM_FILE= tm-solaris.h
diff --git a/gdb/config/powerpc/tm-cygwin.h b/gdb/config/powerpc/tm-cygwin.h
new file mode 100644
index 00000000000..27ae24aefcd
--- /dev/null
+++ b/gdb/config/powerpc/tm-cygwin.h
@@ -0,0 +1,21 @@
+/* Macro definitions PowerPC running under the Cygwin API.
+ Copyright 1996 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "powerpc/tm-ppcle-eabi.h"
+
diff --git a/gdb/config/powerpc/tm-macos.h b/gdb/config/powerpc/tm-macos.h
new file mode 100644
index 00000000000..b29d285b4ab
--- /dev/null
+++ b/gdb/config/powerpc/tm-macos.h
@@ -0,0 +1,26 @@
+/* Macro definitions for Power PC running MacOS.
+ Copyright (C) 1995 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. */
+
+/* Use generic RS6000 definitions. */
+#include "rs6000/tm-rs6000.h"
+
+#define GDB_TARGET_POWERPC
+
+/* This is no use to us. */
+#undef PC_LOAD_SEGMENT
diff --git a/gdb/config/powerpc/tm-ppc-aix.h b/gdb/config/powerpc/tm-ppc-aix.h
new file mode 100644
index 00000000000..5dfb3c47644
--- /dev/null
+++ b/gdb/config/powerpc/tm-ppc-aix.h
@@ -0,0 +1,28 @@
+/* Macro definitions for Power PC running AIX.
+ Copyright 1995 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 TM_PPC_AIX_H
+#define TM_PPC_AIX_H
+
+/* Use generic RS6000 definitions. */
+#include "rs6000/tm-rs6000.h"
+
+#define GDB_TARGET_POWERPC
+
+#endif /* TM_PPC_AIX_H */
diff --git a/gdb/config/powerpc/tm-ppc-eabi.h b/gdb/config/powerpc/tm-ppc-eabi.h
new file mode 100644
index 00000000000..c2828b29b68
--- /dev/null
+++ b/gdb/config/powerpc/tm-ppc-eabi.h
@@ -0,0 +1,84 @@
+/* Macro definitions for Power PC running embedded ABI.
+ Copyright 1995, 1996, 1997 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef TM_PPC_EABI_H
+#define TM_PPC_EABI_H
+
+/* Use generic RS6000 definitions. */
+#include "rs6000/tm-rs6000.h"
+/* except we want to allow single stepping */
+#undef SOFTWARE_SINGLE_STEP_P
+#define SOFTWARE_SINGLE_STEP_P 0
+
+#undef DEFAULT_LR_SAVE
+#define DEFAULT_LR_SAVE 4 /* eabi saves LR at 4 off of SP */
+
+#define GDB_TARGET_POWERPC
+
+#undef PC_LOAD_SEGMENT
+#undef PROCESS_LINENUMBER_HOOK
+
+#undef TEXT_SEGMENT_BASE
+#define TEXT_SEGMENT_BASE 1
+
+/* Say that we're using ELF, not XCOFF. */
+#define ELF_OBJECT_FORMAT 1
+
+#define TARGET_BYTE_ORDER_SELECTABLE_P 1
+
+/* return true if a given `pc' value is in `call dummy' function. */
+/* FIXME: This just checks for the end of the stack, which is broken
+ for things like stepping through gcc nested function stubs. */
+#undef PC_IN_CALL_DUMMY
+#define PC_IN_CALL_DUMMY(STOP_PC, STOP_SP, STOP_FRAME_ADDR) \
+ (STOP_SP < STOP_PC)
+
+/* generic dummy frame stuff */
+
+
+
+/* target-specific dummy_frame stuff */
+
+extern struct frame_info *rs6000_pop_frame PARAMS ((struct frame_info *frame));
+
+extern CORE_ADDR ppc_push_return_address PARAMS ((CORE_ADDR, CORE_ADDR));
+extern CORE_ADDR rs6000_push_arguments PARAMS ((int nargs,
+ struct value **args,
+ CORE_ADDR sp,
+ unsigned char struct_return,
+ CORE_ADDR struct_addr));
+
+#undef PUSH_DUMMY_FRAME
+#define PUSH_DUMMY_FRAME generic_push_dummy_frame ()
+
+#define PUSH_RETURN_ADDRESS(PC, SP) ppc_push_return_address (PC, SP)
+
+/* override the standard get_saved_register function with
+ one that takes account of generic CALL_DUMMY frames */
+#define GET_SAVED_REGISTER
+
+#define USE_GENERIC_DUMMY_FRAMES
+#define CALL_DUMMY_BREAKPOINT_OFFSET (0)
+#define CALL_DUMMY_LOCATION AT_ENTRY_POINT
+#define CALL_DUMMY_ADDRESS() entry_point_address ()
+#undef CALL_DUMMY_START_OFFSET
+#define CALL_DUMMY_START_OFFSET 0
+
+
+#endif /* TM_PPC_EABI_H */
diff --git a/gdb/config/powerpc/tm-ppc-nw.h b/gdb/config/powerpc/tm-ppc-nw.h
new file mode 100644
index 00000000000..38f72112bb4
--- /dev/null
+++ b/gdb/config/powerpc/tm-ppc-nw.h
@@ -0,0 +1,31 @@
+/* Macro definitions for Power PC running Netware.
+ Copyright 1994 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef TM_PPC_NW_H
+#define TM_PPC_NW_H
+
+/* Use generic RS6000 definitions. */
+#include "rs6000/tm-rs6000.h"
+
+#define GDB_TARGET_POWERPC
+
+#undef PC_LOAD_SEGMENT
+#undef PROCESS_LINENUMBER_HOOK
+
+#endif /* TM_PPC_NW_H */
diff --git a/gdb/config/powerpc/tm-ppc-sim.h b/gdb/config/powerpc/tm-ppc-sim.h
new file mode 100644
index 00000000000..e4116bcc686
--- /dev/null
+++ b/gdb/config/powerpc/tm-ppc-sim.h
@@ -0,0 +1,26 @@
+/* Macro definitions for Power PC running embedded ABI under the simulator.
+ Copyright 1995 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef TM_PPC_SIM_H
+#define TM_PPC_SIM_H
+
+#include "powerpc/tm-ppc-eabi.h"
+
+#endif /* TM_PPC_SIM_H */
+
diff --git a/gdb/config/powerpc/tm-ppcle-eabi.h b/gdb/config/powerpc/tm-ppcle-eabi.h
new file mode 100644
index 00000000000..355195d8a0e
--- /dev/null
+++ b/gdb/config/powerpc/tm-ppcle-eabi.h
@@ -0,0 +1,30 @@
+/* Macro definitions for Power PC running embedded ABI
+ in little endian mode.
+ Copyright 1995 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef TM_PPCLE_EABI_H
+#define TM_PPCLE_EABI_H
+
+/* Use normal ppc-eabi definitions */
+#include "powerpc/tm-ppc-eabi.h"
+
+#undef TARGET_BYTE_ORDER_DEFAULT
+#define TARGET_BYTE_ORDER_DEFAULT LITTLE_ENDIAN
+
+#endif /* TM_PPCLE_EABI_H */
diff --git a/gdb/config/powerpc/tm-ppcle-sim.h b/gdb/config/powerpc/tm-ppcle-sim.h
new file mode 100644
index 00000000000..76564f2cdc3
--- /dev/null
+++ b/gdb/config/powerpc/tm-ppcle-sim.h
@@ -0,0 +1,26 @@
+/* Macro definitions for Power PC running embedded ABI under the simulator.
+ Copyright 1995 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef TM_PPCLE_SIM_H
+#define TM_PPCLE_SIM_H
+
+#include "powerpc/tm-ppcle-eabi.h"
+
+#endif /* TM_PPCLE_SIM_H */
+
diff --git a/gdb/config/powerpc/tm-solaris.h b/gdb/config/powerpc/tm-solaris.h
new file mode 100644
index 00000000000..bd9373fad87
--- /dev/null
+++ b/gdb/config/powerpc/tm-solaris.h
@@ -0,0 +1,74 @@
+/* Macro definitions for GDB for a PowerPC running Solaris 2
+ Copyright 1996 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "powerpc/tm-ppc-eabi.h"
+
+/* There are two different signal handler trampolines in Solaris2. */
+#define IN_SIGTRAMP(pc, name) \
+ ((name) \
+ && (STREQ ("sigacthandler", name) || STREQ ("ucbsigvechandler", name)))
+
+/* The signal handler gets a pointer to an ucontext as third argument
+ if it is called from sigacthandler. This is the offset to the saved
+ PC within it. sparc_frame_saved_pc knows how to deal with
+ ucbsigvechandler. */
+#define SIGCONTEXT_PC_OFFSET 44
+
+#if 0 /* FIXME Setjmp/longjmp are not as well doc'd in SunOS 5.x yet */
+
+/* Offsets into jmp_buf. Not defined by Sun, but at least documented in a
+ comment in <machine/setjmp.h>! */
+
+#define JB_ELEMENT_SIZE 4 /* Size of each element in jmp_buf */
+
+#define JB_ONSSTACK 0
+#define JB_SIGMASK 1
+#define JB_SP 2
+#define JB_PC 3
+#define JB_NPC 4
+#define JB_PSR 5
+#define JB_G1 6
+#define JB_O0 7
+#define JB_WBCNT 8
+
+/* Figure out where the longjmp will land. We expect that we have just entered
+ longjmp and haven't yet setup the stack frame, so the args are still in the
+ output regs. %o0 (O0_REGNUM) points at the jmp_buf structure from which we
+ extract the pc (JB_PC) that we will land at. The pc is copied into ADDR.
+ This routine returns true on success */
+
+extern int
+get_longjmp_target PARAMS ((CORE_ADDR *));
+
+#define GET_LONGJMP_TARGET(ADDR) get_longjmp_target(ADDR)
+#endif /* 0 */
+
+/* The SunPRO compiler puts out 0 instead of the address in N_SO symbols,
+ and for SunPRO 3.0, N_FUN symbols too. */
+#define SOFUN_ADDRESS_MAYBE_MISSING
+
+#if 0
+extern char *sunpro_static_transform_name PARAMS ((char *));
+#define STATIC_TRANSFORM_NAME(x) sunpro_static_transform_name (x)
+#endif
+
+#define FAULTED_USE_SIGINFO
+
+/* Enable handling of shared libraries for a.out executables. */
+#define HANDLE_SVR4_EXEC_EMULATORS
diff --git a/gdb/config/powerpc/xm-aix.h b/gdb/config/powerpc/xm-aix.h
new file mode 100644
index 00000000000..efd0e7424b3
--- /dev/null
+++ b/gdb/config/powerpc/xm-aix.h
@@ -0,0 +1,30 @@
+/* Parameters for hosting on an PowerPC, for GDB, the GNU debugger.
+ Copyright 1995 Free Software Foundation, Inc.
+ Contributed by Cygnus Corporation.
+
+This file is part of GDB.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You 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 "xm-aix4.h"
+
+/* This doesn't seem to be declared in any header file I can find. */
+char *termdef PARAMS ((int, int));
+
+/* UINT_MAX is defined in <sys/limits.h> as a decimal constant (4294967295)
+ which is too large to fit in a signed int when it is parsed by the
+ compiler, so it issues a diagnostic. Just undef it here so that we
+ use gdb's version in defs.h */
+#undef UINT_MAX
diff --git a/gdb/config/powerpc/xm-cygwin.h b/gdb/config/powerpc/xm-cygwin.h
new file mode 100644
index 00000000000..82aa0fb2b62
--- /dev/null
+++ b/gdb/config/powerpc/xm-cygwin.h
@@ -0,0 +1,32 @@
+/* Definitions for hosting on WIN32, for GDB.
+ Copyright 1995, 1996, 1998 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define HOST_BYTE_ORDER LITTLE_ENDIAN
+
+#include "fopen-bin.h"
+
+#define GDBINIT_FILENAME "gdb.ini"
+
+#define SLASH_P(X) ((X)=='\\' || (X) == '/')
+#define ROOTED_P(X) ((SLASH_P((X)[0]))|| ((X)[1] ==':'))
+#define SLASH_CHAR '/'
+#define SLASH_STRING "/"
+
+/* Define this lseek(n) != nth byte of file */
+#define LSEEK_NOT_LINEAR
diff --git a/gdb/config/powerpc/xm-linux.h b/gdb/config/powerpc/xm-linux.h
new file mode 100644
index 00000000000..41c8ba71dc5
--- /dev/null
+++ b/gdb/config/powerpc/xm-linux.h
@@ -0,0 +1,21 @@
+/* Host definitions for a Sun 4, for GDB, the GNU debugger.
+ Copyright 1996
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define HOST_BYTE_ORDER BIG_ENDIAN
diff --git a/gdb/config/powerpc/xm-mpw.h b/gdb/config/powerpc/xm-mpw.h
new file mode 100644
index 00000000000..6b33ca206ba
--- /dev/null
+++ b/gdb/config/powerpc/xm-mpw.h
@@ -0,0 +1,22 @@
+/* Macro definitions for running GDB on Apple Power Macintoshes.
+ Copyright (C) 1994 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define HOST_BYTE_ORDER BIG_ENDIAN
+
+#include <xm-mpw.h>
diff --git a/gdb/config/powerpc/xm-solaris.h b/gdb/config/powerpc/xm-solaris.h
new file mode 100644
index 00000000000..9ead87a3887
--- /dev/null
+++ b/gdb/config/powerpc/xm-solaris.h
@@ -0,0 +1,21 @@
+/* Host definitions for a Sun 4, for GDB, the GNU debugger.
+ Copyright 1996
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define HOST_BYTE_ORDER LITTLE_ENDIAN
diff --git a/gdb/config/pyr/pyramid.mh b/gdb/config/pyr/pyramid.mh
new file mode 100644
index 00000000000..cd25e57e4a3
--- /dev/null
+++ b/gdb/config/pyr/pyramid.mh
@@ -0,0 +1,8 @@
+# Host: Pyramid under OSx 4.0 (4.2bsd).
+
+#msg If you don't compile GDB with GCC, you'll need to add
+#msg ALLOCA=alloca.o and ALLOCA1=alloca.o to the Makefile.
+#msg
+
+XDEPFILES= pyr-xdep.o infptrace.o inftarg.o fork-child.o
+XM_FILE= xm-pyr.h
diff --git a/gdb/config/pyr/pyramid.mt b/gdb/config/pyr/pyramid.mt
new file mode 100644
index 00000000000..48f955769d0
--- /dev/null
+++ b/gdb/config/pyr/pyramid.mt
@@ -0,0 +1,3 @@
+# Target: Pyramid under OSx 4.0 (4.2bsd).
+TDEPFILES= pyr-tdep.o
+TM_FILE= tm-pyr.h
diff --git a/gdb/config/pyr/tm-pyr.h b/gdb/config/pyr/tm-pyr.h
new file mode 100644
index 00000000000..b97ebe73b88
--- /dev/null
+++ b/gdb/config/pyr/tm-pyr.h
@@ -0,0 +1,483 @@
+/* Definitions to make GDB run on a Pyramid under OSx 4.0 (4.2bsd).
+ Copyright 1988, 1989, 1991, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define TARGET_BYTE_ORDER BIG_ENDIAN
+
+/* Traditional Unix virtual address spaces have thre regions: text,
+ data and stack. The text, initialised data, and uninitialised data
+ are represented in separate segments of the a.out file.
+ When a process dumps core, the data and stack regions are written
+ to a core file. This gives a debugger enough information to
+ reconstruct (and debug) the virtual address space at the time of
+ the coredump.
+ Pyramids have an distinct fourth region of the virtual address
+ space, in which the contents of the windowed registers are stacked
+ in fixed-size frames. Pyramid refer to this region as the control
+ stack. Each call (or trap) automatically allocates a new register
+ frame; each return deallocates the current frame and restores the
+ windowed registers to their values before the call.
+
+ When dumping core, the control stack is written to a core files as
+ a third segment. The core-handling functions need to know to deal
+ with it. */
+
+/* Tell corefile.c there is an extra segment. */
+#define REG_STACK_SEGMENT
+
+/* Floating point is IEEE compatible on most Pyramid hardware
+ (Older processors do not have IEEE NaNs). */
+#define IEEE_FLOAT
+
+/* Offset from address of function to start of its code.
+ Zero on most machines. */
+
+#define FUNCTION_START_OFFSET 0
+
+/* Advance PC across any function entry prologue instructions
+ to reach some "real" code. */
+
+/* FIXME -- do we want to skip insns to allocate the local frame?
+ If so, what do they look like?
+ This is becoming harder, since tege@sics.SE wants to change
+ gcc to not output a prologue when no frame is needed. */
+#define SKIP_PROLOGUE(pc) do {} while (0)
+
+
+/* Immediately after a function call, return the saved pc.
+ Can't always go through the frames for this because on some machines
+ the new frame is not set up until the new function executes
+ some instructions. */
+
+#define SAVED_PC_AFTER_CALL(frame) FRAME_SAVED_PC(frame)
+
+/* Address of end of stack space. */
+/* This seems to be right for the 90x comp.vuw.ac.nz.
+ The correct value at any site may be a function of the configured
+ maximum control stack depth. If so, I don't know where the
+ control-stack depth is configured, so I can't #include it here. */
+#define STACK_END_ADDR (0xc00cc000)
+
+/* Register window stack (Control stack) stack definitions
+ - Address of beginning of control stack.
+ - size of control stack frame
+ (Note that since crts0 is usually the first function called,
+ main()'s control stack is one frame (0x80 bytes) beyond this value. */
+
+#define CONTROL_STACK_ADDR (0xc00cd000)
+
+/* Bytes in a register window -- 16 parameter regs, 16 local regs
+ for each call, is 32 regs * 4 bytes */
+
+#define CONTROL_STACK_FRAME_SIZE (32*4)
+
+/* FIXME. On a pyr, Data Stack grows downward; control stack goes upwards.
+ Which direction should we use for INNER_THAN, PC_INNER_THAN ?? */
+
+#define INNER_THAN(lhs,rhs) ((lhs) < (rhs))
+
+/* Stack must be aligned on 32-bit boundaries when synthesizing
+ function calls. */
+
+#define STACK_ALIGN(ADDR) (((ADDR) + 3) & -4)
+
+/* Sequence of bytes for breakpoint instruction. */
+
+#define BREAKPOINT {0xf0, 00, 00, 00}
+
+/* Amount PC must be decremented by after a breakpoint.
+ This is often the number of bytes in BREAKPOINT
+ but not always. */
+
+#define DECR_PC_AFTER_BREAK 0
+
+/* Say how long (ordinary) registers are. This is a piece of bogosity
+ used in push_word and a few other places; REGISTER_RAW_SIZE is the
+ real way to know how big a register is. */
+
+#define REGISTER_SIZE 4
+
+/* Number of machine registers */
+/* pyramids have 64, plus one for the PSW; plus perhaps one more for the
+ kernel stack pointer (ksp) and control-stack pointer (CSP) */
+
+#define NUM_REGS 67
+
+/* Initializer for an array of names of registers.
+ There should be NUM_REGS strings in this initializer. */
+
+#define REGISTER_NAMES \
+{"gr0", "gr1", "gr2", "gr3", "gr4", "gr5", "gr6", "gr7", \
+ "gr8", "gr9", "gr10", "gr11", "logpsw", "cfp", "sp", "pc", \
+ "pr0", "pr1", "pr2", "pr3", "pr4", "pr5", "pr6", "pr7", \
+ "pr8", "pr9", "pr10", "pr11", "pr12", "pr13", "pr14", "pr15", \
+ "lr0", "lr1", "lr2", "lr3", "lr4", "lr5", "lr6", "lr7", \
+ "lr8", "lr9", "lr10", "lr11", "lr12", "lr13", "lr14", "lr15", \
+ "tr0", "tr1", "tr2", "tr3", "tr4", "tr5", "tr6", "tr7", \
+ "tr8", "tr9", "tr10", "tr11", "tr12", "tr13", "tr14", "tr15", \
+ "psw", "ksp", "csp"}
+
+/* Register numbers of various important registers.
+ Note that some of these values are "real" register numbers,
+ and correspond to the general registers of the machine,
+ and some are "phony" register numbers which are too large
+ to be actual register numbers as far as the user is concerned
+ but do serve to get the desired values when passed to read_register. */
+
+/* pseudo-registers: */
+#define PS_REGNUM 64 /* Contains processor status */
+#define PSW_REGNUM 64 /* Contains current psw, whatever it is.*/
+#define CSP_REGNUM 65 /* address of this control stack frame*/
+#define KSP_REGNUM 66 /* Contains process's Kernel Stack Pointer */
+
+#define CFP_REGNUM 13 /* Current data-stack frame ptr */
+#define TR0_REGNUM 48 /* After function call, contains
+ function result */
+
+/* Registers interesting to the machine-independent part of gdb*/
+
+#define FP_REGNUM CSP_REGNUM /* Contains address of executing (control)
+ stack frame */
+#define SP_REGNUM 14 /* Contains address of top of stack -??*/
+#define PC_REGNUM 15 /* Contains program counter */
+
+/* Define DO_REGISTERS_INFO() to do machine-specific formatting
+ of register dumps. */
+
+#define DO_REGISTERS_INFO(_regnum, fp) pyr_do_registers_info(_regnum, fp)
+
+/* need this so we can find the global registers: they never get saved. */
+extern unsigned int global_reg_offset;
+extern unsigned int last_frame_offset;
+
+/* Total amount of space needed to store our copies of the machine's
+ register state, the array `registers'. */
+#define REGISTER_BYTES (NUM_REGS*4)
+
+/* the Pyramid has register windows. */
+
+#define HAVE_REGISTER_WINDOWS
+
+/* Is this register part of the register window system? A yes answer
+ implies that 1) The name of this register will not be the same in
+ other frames, and 2) This register is automatically "saved" (out
+ registers shifting into ins counts) upon subroutine calls and thus
+ there is no need to search more than one stack frame for it. */
+
+#define REGISTER_IN_WINDOW_P(regnum) \
+ ((regnum) >= 16 && (regnum) < 64)
+
+/* Index within `registers' of the first byte of the space for
+ register N. */
+
+#define REGISTER_BYTE(N) ((N) * 4)
+
+/* Number of bytes of storage in the actual machine representation
+ for register N. On the Pyramid, all regs are 4 bytes. */
+
+#define REGISTER_RAW_SIZE(N) 4
+
+/* Number of bytes of storage in the program's representation
+ for register N. On the Pyramid, all regs are 4 bytes. */
+
+#define REGISTER_VIRTUAL_SIZE(N) 4
+
+/* Largest value REGISTER_RAW_SIZE can have. */
+
+#define MAX_REGISTER_RAW_SIZE 4
+
+/* Largest value REGISTER_VIRTUAL_SIZE can have. */
+
+#define MAX_REGISTER_VIRTUAL_SIZE 4
+
+/* Return the GDB type object for the "standard" data type
+ of data in register N. */
+
+#define REGISTER_VIRTUAL_TYPE(N) builtin_type_int
+
+/* FIXME: It seems impossible for both EXTRACT_RETURN_VALUE and
+ STORE_RETURN_VALUE to be correct. */
+
+/* Store the address of the place in which to copy the structure the
+ subroutine will return. This is called from call_function. */
+
+/****FIXME****/
+#define STORE_STRUCT_RETURN(ADDR, SP) \
+ { write_register (TR0_REGNUM, (ADDR)); }
+
+/* Extract from an array REGBUF containing the (raw) register state
+ a function return value of type TYPE, and copy that, in virtual format,
+ into VALBUF. */
+
+/* Note that on a register-windowing machine (eg, Pyr, SPARC), this is
+ where the value is found after the function call -- ie, it should
+ correspond to GNU CC's FUNCTION_VALUE rather than FUNCTION_OUTGOING_VALUE.*/
+
+#define EXTRACT_RETURN_VALUE(TYPE,REGBUF,VALBUF) \
+ memcpy (VALBUF, ((int *)(REGBUF))+TR0_REGNUM, TYPE_LENGTH (TYPE))
+
+/* Write into appropriate registers a function return value
+ of type TYPE, given in virtual format. */
+/* on pyrs, values are returned in */
+
+#define STORE_RETURN_VALUE(TYPE,VALBUF) \
+ write_register_bytes (REGISTER_BYTE(TR0_REGNUM), VALBUF, TYPE_LENGTH (TYPE))
+
+/* Extract from an array REGBUF containing the (raw) register state
+ the address in which a function should return its structure value,
+ as a CORE_ADDR (or an expression that can be used as one). */
+/* FIXME */
+#define EXTRACT_STRUCT_VALUE_ADDRESS(REGBUF) \
+ ( ((int *)(REGBUF)) [TR0_REGNUM])
+
+
+/* Describe the pointer in each stack frame to the previous stack frame
+ (its caller). */
+
+#define EXTRA_FRAME_INFO \
+ CORE_ADDR bottom; \
+ CORE_ADDR frame_cfp; \
+ CORE_ADDR frame_window_addr;
+
+/* The bottom field is misnamed, since it might imply that memory from
+ bottom to frame contains this frame. That need not be true if
+ stack frames are allocated in different segments (e.g. some on a
+ stack, some on a heap in the data segment). */
+
+#define INIT_EXTRA_FRAME_INFO(fromleaf, fci) \
+do { \
+ (fci)->frame_window_addr = (fci)->frame; \
+ (fci)->bottom = \
+ ((fci)->next ? \
+ ((fci)->frame == (fci)->next->frame ? \
+ (fci)->next->bottom : (fci)->next->frame) : \
+ read_register (SP_REGNUM)); \
+ (fci)->frame_cfp = \
+ read_register (CFP_REGNUM); \
+ /***fprintf (stderr, \
+ "[[creating new frame for %0x,pc=%0x,csp=%0x]]\n", \
+ (fci)->frame, (fci)->pc,(fci)->frame_cfp);*/ \
+} while (0);
+
+/* FRAME_CHAIN takes a frame's nominal address
+ and produces the frame's chain-pointer. */
+
+/* In the case of the pyr, the frame's nominal address is the address
+ of parameter register 0. The previous frame is found 32 words up. */
+
+#define FRAME_CHAIN(thisframe) \
+ ( (thisframe) -> frame - CONTROL_STACK_FRAME_SIZE)
+
+ /*((thisframe) >= CONTROL_STACK_ADDR))*/
+
+/* Define other aspects of the stack frame. */
+
+/* A macro that tells us whether the function invocation represented
+ by FI does not have a frame on the stack associated with it. If it
+ does not, FRAMELESS is set to 1, else 0.
+
+ I do not understand what this means on a Pyramid, where functions
+ *always* have a control-stack frame, but may or may not have a
+ frame on the data stack. Since GBD uses the value of the
+ control stack pointer as its "address" of a frame, FRAMELESS
+ is always 1, so does not need to be defined. */
+
+
+/* Where is the PC for a specific frame */
+
+#define FRAME_SAVED_PC(fi) \
+ ((CORE_ADDR) (read_memory_integer ( (fi) -> frame + 60, 4)))
+
+/* There may be bugs in FRAME_ARGS_ADDRESS and FRAME_LOCALS_ADDRESS;
+ or there may be bugs in accessing the registers that break
+ their definitions.
+ Having the macros expand into functions makes them easier to debug.
+ When the bug is finally located, the inline macro defintions can
+ be un-#if 0ed, and frame_args_addr and frame_locals_address can
+ be deleted from pyr-dep.c */
+
+/* If the argument is on the stack, it will be here. */
+#define FRAME_ARGS_ADDRESS(fi) \
+ frame_args_addr(fi)
+
+#define FRAME_LOCALS_ADDRESS(fi) \
+ frame_locals_address(fi)
+
+/* The following definitions doesn't seem to work.
+ I don't understand why. */
+#if 0
+#define FRAME_ARGS_ADDRESS(fi) \
+ /*(FRAME_FP(fi) + (13*4))*/ (read_register (CFP_REGNUM))
+
+#define FRAME_LOCALS_ADDRESS(fi) \
+ ((fi)->frame +(16*4))
+
+#endif /* 0 */
+
+/* Return number of args passed to a frame.
+ Can return -1, meaning no way to tell. */
+
+#define FRAME_NUM_ARGS(val, fi) (val = -1)
+
+/* Return number of bytes at start of arglist that are not really args. */
+
+#define FRAME_ARGS_SKIP 0
+
+/* Put here the code to store, into a struct frame_saved_regs,
+ the addresses of the saved registers of frame described by FRAME_INFO.
+ This includes special registers such as pc and fp saved in special
+ ways in the stack frame. sp is even more special:
+ the address we return for it IS the sp for the next frame.
+
+ Note that on register window machines, we are currently making the
+ assumption that window registers are being saved somewhere in the
+ frame in which they are being used. If they are stored in an
+ inferior frame, find_saved_register will break.
+
+ On pyrs, frames of window registers are stored contiguously on a
+ separate stack. All window registers are always stored.
+ The pc and psw (gr15 and gr14) are also always saved: the call
+ insn saves them in pr15 and pr14 of the new frame (tr15,tr14 of the
+ old frame).
+ The data-stack frame pointer (CFP) is only saved in functions which
+ allocate a (data)stack frame (with "adsf"). We detect them by
+ looking at the first insn of the procedure.
+
+ Other non-window registers (gr0-gr11) are never saved. Pyramid's C
+ compiler and gcc currently ignore them, so it's not an issue. */
+
+#define FRAME_FIND_SAVED_REGS(fi_p, frame_saved_regs) \
+{ register int regnum; \
+ register CORE_ADDR pc; \
+ register CORE_ADDR fn_start_pc; \
+ register int first_insn; \
+ register CORE_ADDR prev_cf_addr; \
+ register int window_ptr; \
+ if (!fi_p) fatal ("Bad frame info struct in FRAME_FIND_SAVED_REGS"); \
+ memset (&(frame_saved_regs), '\0', sizeof (frame_saved_regs)); \
+ \
+ window_ptr = prev_cf_addr = FRAME_FP(fi_p); \
+ \
+ for (regnum = 16 ; regnum < 64; regnum++,window_ptr+=4) \
+ { \
+ (frame_saved_regs).regs[regnum] = window_ptr; \
+ } \
+ \
+ /* In each window, psw, and pc are "saved" in tr14,tr15. */ \
+ /*** psw is sometimes saved in gr12 (so sez <sys/pcb.h>) */ \
+ (frame_saved_regs).regs[PS_REGNUM] = FRAME_FP(fi_p) + (14*4); \
+ \
+/*(frame_saved_regs).regs[PC_REGNUM] = (frame_saved_regs).regs[31];*/ \
+ (frame_saved_regs).regs[PC_REGNUM] = FRAME_FP(fi_p) + ((15+32)*4); \
+ \
+ /* Functions that allocate a frame save sp *where*? */ \
+/*first_insn = read_memory_integer (get_pc_function_start ((fi_p)->pc),4); */ \
+ \
+ fn_start_pc = (get_pc_function_start ((fi_p)->pc)); \
+ first_insn = read_memory_integer(fn_start_pc, 4); \
+ \
+ if (0x08 == ((first_insn >> 20) &0x0ff)) { \
+ /* NB: because WINDOW_REGISTER_P(cfp) is false, a saved cfp \
+ in this frame is only visible in this frame's callers. \
+ That means the cfp we mark saved is my caller's cfp, ie pr13. \
+ I don't understand why we don't have to do that for pc, too. */ \
+ \
+ (frame_saved_regs).regs[CFP_REGNUM] = FRAME_FP(fi_p)+(13*4); \
+ \
+ (frame_saved_regs).regs[SP_REGNUM] = \
+ read_memory_integer (FRAME_FP(fi_p)+((13+32)*4),4); \
+ } \
+ \
+/* \
+ *(frame_saved_regs).regs[CFP_REGNUM] = (frame_saved_regs).regs[61]; \
+ * (frame_saved_regs).regs[SP_REGNUM] = \
+ * read_memory_integer (FRAME_FP(fi_p)+((13+32)*4),4); \
+ */ \
+ \
+ (frame_saved_regs).regs[CSP_REGNUM] = prev_cf_addr; \
+}
+
+/* Things needed for making the inferior call functions. */
+#if 0
+/* These are all lies. These macro definitions are appropriate for a
+ SPARC. On a pyramid, pushing a dummy frame will
+ surely involve writing the control stack pointer,
+ then saving the pc. This requires a privileged instruction.
+ Maybe one day Pyramid can be persuaded to add a syscall to do this.
+ Until then, we are out of luck. */
+
+/* Push an empty stack frame, to record the current PC, etc. */
+
+#define PUSH_DUMMY_FRAME \
+{ register CORE_ADDR sp = read_register (SP_REGNUM);\
+ register int regnum; \
+ sp = push_word (sp, 0); /* arglist */ \
+ for (regnum = 11; regnum >= 0; regnum--) \
+ sp = push_word (sp, read_register (regnum)); \
+ sp = push_word (sp, read_register (PC_REGNUM)); \
+ sp = push_word (sp, read_register (FP_REGNUM)); \
+/* sp = push_word (sp, read_register (AP_REGNUM));*/ \
+ sp = push_word (sp, (read_register (PS_REGNUM) & 0xffef) \
+ + 0x2fff0000); \
+ sp = push_word (sp, 0); \
+ write_register (SP_REGNUM, sp); \
+ write_register (FP_REGNUM, sp); \
+/* write_register (AP_REGNUM, sp + 17 * sizeof (int));*/ }
+
+/* Discard from the stack the innermost frame, restoring all registers. */
+
+#define POP_FRAME \
+{ register CORE_ADDR fp = read_register (FP_REGNUM); \
+ register int regnum; \
+ register int regmask = read_memory_integer (fp + 4, 4); \
+ write_register (PS_REGNUM, \
+ (regmask & 0xffff) \
+ | (read_register (PS_REGNUM) & 0xffff0000)); \
+ write_register (PC_REGNUM, read_memory_integer (fp + 16, 4)); \
+ write_register (FP_REGNUM, read_memory_integer (fp + 12, 4)); \
+/* write_register (AP_REGNUM, read_memory_integer (fp + 8, 4));*/ \
+ fp += 16; \
+ for (regnum = 0; regnum < 12; regnum++) \
+ if (regmask & (0x10000 << regnum)) \
+ write_register (regnum, read_memory_integer (fp += 4, 4)); \
+ fp = fp + 4 + ((regmask >> 30) & 3); \
+ if (regmask & 0x20000000) \
+ { regnum = read_memory_integer (fp, 4); \
+ fp += (regnum + 1) * 4; } \
+ write_register (SP_REGNUM, fp); \
+ set_current_frame (read_register (FP_REGNUM)); }
+
+/* This sequence of words is the instructions
+ calls #69, @#32323232
+ bpt
+ Note this is 8 bytes. */
+
+#define CALL_DUMMY {0x329f69fb, 0x03323232}
+
+#define CALL_DUMMY_START_OFFSET 0 /* Start execution at beginning of dummy */
+
+/* Insert the specified number of args and function address
+ into a call sequence of the above form stored at DUMMYNAME. */
+
+#define FIX_CALL_DUMMY(dummyname, pc, fun, nargs, args, type, gcc_p) \
+{ *((char *) dummyname + 1) = nargs; \
+ *(int *)((char *) dummyname + 3) = fun; }
+#endif /* 0 */
+
+#define POP_FRAME \
+ { error ("The return command is not supported on this machine."); }
diff --git a/gdb/config/pyr/xm-pyr.h b/gdb/config/pyr/xm-pyr.h
new file mode 100644
index 00000000000..f45d10aa8ca
--- /dev/null
+++ b/gdb/config/pyr/xm-pyr.h
@@ -0,0 +1,92 @@
+/* Definitions to make GDB run on a Pyramidax under OSx 4.0 (4.2bsd).
+ Copyright 1988, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define HOST_BYTE_ORDER BIG_ENDIAN
+
+/* Define PYRAMID_CONTROL_FRAME_DEBUGGING to get copious messages
+ about reading the control stack on standard output. This
+ makes gdb unusable as a debugger. */
+
+/* #define PYRAMID_CONTROL_FRAME_DEBUGGING */
+
+/* Define PYRAMID_FRAME_DEBUGGING for ? */
+
+/* use Pyramid's slightly strange ptrace */
+#define PYRAMID_PTRACE
+
+/* Traditional Unix virtual address spaces have thre regions: text,
+ data and stack. The text, initialised data, and uninitialised data
+ are represented in separate segments of the a.out file.
+ When a process dumps core, the data and stack regions are written
+ to a core file. This gives a debugger enough information to
+ reconstruct (and debug) the virtual address space at the time of
+ the coredump.
+ Pyramids have an distinct fourth region of the virtual address
+ space, in which the contents of the windowed registers are stacked
+ in fixed-size frames. Pyramid refer to this region as the control
+ stack. Each call (or trap) automatically allocates a new register
+ frame; each return deallocates the current frame and restores the
+ windowed registers to their values before the call.
+
+ When dumping core, the control stack is written to a core files as
+ a third segment. The core-handling functions need to know to deal
+ with it. */
+
+/* Tell dep.c what the extra segment is. */
+#define PYRAMID_CORE
+
+#define NO_SIGINTERRUPT
+
+#define HAVE_WAIT_STRUCT
+
+/* This is the amount to subtract from u.u_ar0
+ to get the offset in the core file of the register values. */
+
+#define KERNEL_U_ADDR (0x80000000 - (UPAGES * NBPG))
+
+/* Define offsets of registers in the core file (or maybe u area) */
+#define REGISTER_U_ADDR(addr, blockend, regno) \
+{ struct user __u; \
+ addr = blockend + (regno - 16 ) * 4; \
+ if (regno == 67) { \
+ printf("\\geting reg 67\\"); \
+ addr = (int)(&__u.u_pcb.pcb_csp) - (int) &__u; \
+ } else if (regno == KSP_REGNUM) { \
+ printf("\\geting KSP (reg %d)\\", KSP_REGNUM); \
+ addr = (int)(&__u.u_pcb.pcb_ksp) - (int) &__u; \
+ } else if (regno == CSP_REGNUM) { \
+ printf("\\geting CSP (reg %d\\",CSP_REGNUM); \
+ addr = (int)(&__u.u_pcb.pcb_csp) - (int) &__u; \
+ } else if (regno == 64) { \
+ printf("\\geting reg 64\\"); \
+ addr = (int)(&__u.u_pcb.pcb_csp) - (int) &__u; \
+ } else if (regno == PS_REGNUM) \
+ addr = blockend - 4; \
+ else if (1 && ((16 > regno) && (regno > 11))) \
+ addr = last_frame_offset + (4 *(regno+32)); \
+ else if (0 && (12 > regno)) \
+ addr = global_reg_offset + (4 *regno); \
+ else if (16 > regno) \
+ addr = global_reg_offset + (4 *regno); \
+ else \
+ addr = blockend + (regno - 16 ) * 4; \
+}
+
+/* Override copies of {fetch,store}_inferior_registers in infptrace.c. */
+#define FETCH_INFERIOR_REGISTERS
diff --git a/gdb/config/romp/rtbsd.mh b/gdb/config/romp/rtbsd.mh
new file mode 100644
index 00000000000..003c42f9a48
--- /dev/null
+++ b/gdb/config/romp/rtbsd.mh
@@ -0,0 +1,8 @@
+# IBM RT/PC running BSD unix.
+# This file contributed at NYU, where we are using the RT to remote
+# debug an a29k running unix. No attempt, as of 7/16/91, has been made
+# to support debugging of RT executables.
+XDEPFILES corelow.o core-aout.o infptrace.o inftarg.o fork-child.o
+MH_CFLAGS=-DHOSTING_ONLY # No debugging of RT executables
+XM_FILE= xm-rtbsd.h
+CC=gcc -traditional # hc/pcc just can't cut it.
diff --git a/gdb/config/romp/xm-rtbsd.h b/gdb/config/romp/xm-rtbsd.h
new file mode 100644
index 00000000000..d99b57f44ae
--- /dev/null
+++ b/gdb/config/romp/xm-rtbsd.h
@@ -0,0 +1,40 @@
+/* Definitions to host GDB on an IBM RT/PC running BSD Unix.
+ Copyright 1986, 1987, 1989, 1991, 1992 Free Software Foundation, Inc.
+ Contributed by David Wood @ New York University (wood@lab.ultra.nyu.edu).
+
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* This machine is most significant byte first */
+#define HOST_BYTE_ORDER BIG_ENDIAN
+
+/* This OS has the wait structure */
+#define HAVE_WAIT_STRUCT
+
+#ifdef HOSTING_ONLY
+/*
+ * This next two defines are to get GDB up and running as a host to
+ * do remote debugging. I know there is a gdb for the RT, but there wasn't
+ * an xconfig/rt* file.
+ */
+#define KERNEL_U_ADDR_BSD /* This may be correct, but hasn't been tested */
+#define REGISTER_U_ADDR(a,b,c) \
+ (printf("GDB can not debug IBM RT/PC BSD executables (yet)\n"),\
+ quit(),0)
+#else
+# include "GDB for the RT is not included in the distribution"
+#endif
+
diff --git a/gdb/config/rs6000/aix4.mh b/gdb/config/rs6000/aix4.mh
new file mode 100644
index 00000000000..c5bc2dae91f
--- /dev/null
+++ b/gdb/config/rs6000/aix4.mh
@@ -0,0 +1,11 @@
+# Host: IBM RS/6000 running AIX4
+
+XM_FILE= xm-aix4.h
+XDEPFILES=
+
+NAT_FILE= nm-rs6000.h
+NATDEPFILES= fork-child.o infptrace.o inftarg.o corelow.o rs6000-nat.o
+
+# When compiled with cc, for debugging, this argument should be passed.
+# We have no idea who our current compiler is though, so we skip it.
+# MH_CFLAGS = -bnodelcsect
diff --git a/gdb/config/rs6000/aix4.mt b/gdb/config/rs6000/aix4.mt
new file mode 100644
index 00000000000..f213f0f6f2f
--- /dev/null
+++ b/gdb/config/rs6000/aix4.mt
@@ -0,0 +1,3 @@
+# Target: IBM RS/6000 running AIX4
+TDEPFILES= rs6000-tdep.o xcoffsolib.o xcoffread.o
+TM_FILE= tm-rs6000-aix4.h
diff --git a/gdb/config/rs6000/nm-rs6000.h b/gdb/config/rs6000/nm-rs6000.h
new file mode 100644
index 00000000000..cf0d53dde35
--- /dev/null
+++ b/gdb/config/rs6000/nm-rs6000.h
@@ -0,0 +1,60 @@
+/* IBM RS/6000 native-dependent macros for GDB, the GNU debugger.
+ Copyright 1986, 1987, 1989, 1991, 1992, 1994 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Do implement the attach and detach commands. */
+
+#define ATTACH_DETACH
+
+#define PTRACE_ATTACH PT_ATTACH
+#define PTRACE_DETACH PT_DETACH
+
+/* Override copies of {fetch,store}_inferior_registers in infptrace.c. */
+
+#define FETCH_INFERIOR_REGISTERS
+
+/* When a child process is just starting, we sneak in and relocate
+ the symbol table (and other stuff) after the dynamic linker has
+ figured out where they go. */
+
+#define SOLIB_CREATE_INFERIOR_HOOK(PID) \
+ do { \
+ xcoff_relocate_symtab (PID); \
+ } while (0)
+
+/* When a target process or core-file has been attached, we sneak in
+ and figure out where the shared libraries have got to. */
+
+#define SOLIB_ADD(a, b, c) \
+ if (inferior_pid) \
+ /* Attach to process. */ \
+ xcoff_relocate_symtab (inferior_pid); \
+ else \
+ /* Core file. */ \
+ xcoff_relocate_core (c);
+
+extern void xcoff_relocate_symtab PARAMS ((unsigned int));
+#ifdef __STDC__
+struct target_ops;
+#endif
+extern void xcoff_relocate_core PARAMS ((struct target_ops *));
+
+/* Return sizeof user struct to callers in less machine dependent routines */
+
+#define KERNEL_U_SIZE kernel_u_size()
+extern int kernel_u_size PARAMS ((void));
diff --git a/gdb/config/rs6000/nm-rs6000ly.h b/gdb/config/rs6000/nm-rs6000ly.h
new file mode 100644
index 00000000000..4159822e20c
--- /dev/null
+++ b/gdb/config/rs6000/nm-rs6000ly.h
@@ -0,0 +1,25 @@
+/* Native-dependent definitions for RS6000 running LynxOS.
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef NM_RS6000LYNX_H
+#define NM_RS6000LYNX_H
+
+#include "nm-lynx.h"
+
+#endif /* NM_RS6000LYNX_H */
diff --git a/gdb/config/rs6000/rs6000.mh b/gdb/config/rs6000/rs6000.mh
new file mode 100644
index 00000000000..600d616124c
--- /dev/null
+++ b/gdb/config/rs6000/rs6000.mh
@@ -0,0 +1,11 @@
+# Host: IBM RS/6000 running AIX
+
+XM_FILE= xm-rs6000.h
+XDEPFILES=
+
+NAT_FILE= nm-rs6000.h
+NATDEPFILES= fork-child.o infptrace.o inftarg.o corelow.o rs6000-nat.o
+
+# When compiled with cc, for debugging, this argument should be passed.
+# We have no idea who our current compiler is though, so we skip it.
+# MH_CFLAGS = -bnodelcsect
diff --git a/gdb/config/rs6000/rs6000.mt b/gdb/config/rs6000/rs6000.mt
new file mode 100644
index 00000000000..a2294b2c55a
--- /dev/null
+++ b/gdb/config/rs6000/rs6000.mt
@@ -0,0 +1,3 @@
+# Target: IBM RS/6000 running AIX
+TDEPFILES= rs6000-tdep.o xcoffsolib.o xcoffread.o
+TM_FILE= tm-rs6000.h
diff --git a/gdb/config/rs6000/rs6000lynx.mh b/gdb/config/rs6000/rs6000lynx.mh
new file mode 100644
index 00000000000..b93815233e7
--- /dev/null
+++ b/gdb/config/rs6000/rs6000lynx.mh
@@ -0,0 +1,11 @@
+# Host: RS6000 running LynxOS
+
+XM_FILE= xm-rs6000ly.h
+XDEPFILES= ser-tcp.o
+XM_CLIBS= -lbsd
+
+NAT_FILE= nm-rs6000ly.h
+NATDEPFILES= fork-child.o infptrace.o inftarg.o corelow.o lynx-nat.o xcoffread.o
+
+GDBSERVER_LIBS= -lbsd
+GDBSERVER_DEPFILES= low-lynx.o
diff --git a/gdb/config/rs6000/rs6000lynx.mt b/gdb/config/rs6000/rs6000lynx.mt
new file mode 100644
index 00000000000..978030c539e
--- /dev/null
+++ b/gdb/config/rs6000/rs6000lynx.mt
@@ -0,0 +1,3 @@
+# Target: IBM RS6000 running LynxOS
+TDEPFILES= coff-solib.o rs6000-tdep.o
+TM_FILE= tm-rs6000ly.h
diff --git a/gdb/config/rs6000/tm-rs6000-aix4.h b/gdb/config/rs6000/tm-rs6000-aix4.h
new file mode 100644
index 00000000000..f65eae38681
--- /dev/null
+++ b/gdb/config/rs6000/tm-rs6000-aix4.h
@@ -0,0 +1,26 @@
+/* Macro definitions for RS/6000 running AIX4.
+ Copyright 1995, 1997 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 TM_RS6000_AIX4_H
+#define TM_RS6000_AIX4_H
+
+/* Use generic RS6000 definitions. */
+#include "rs6000/tm-rs6000.h"
+
+#endif /* TM_RS6000_AIX4_H */
diff --git a/gdb/config/rs6000/tm-rs6000.h b/gdb/config/rs6000/tm-rs6000.h
new file mode 100644
index 00000000000..52beec1adc6
--- /dev/null
+++ b/gdb/config/rs6000/tm-rs6000.h
@@ -0,0 +1,564 @@
+/* Parameters for target execution on an RS6000, for GDB, the GNU debugger.
+ Copyright 1986, 1987, 1989, 1991, 1992, 1993, 1994, 1997
+ Free Software Foundation, Inc.
+ Contributed by IBM Corporation.
+
+This file is part of GDB.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifdef __STDC__ /* Forward decls for prototypes */
+struct frame_info;
+struct type;
+struct value;
+#endif
+
+/* Minimum possible text address in AIX */
+
+#define TEXT_SEGMENT_BASE 0x10000000
+
+/* Load segment of a given pc value. */
+
+#define PC_LOAD_SEGMENT(PC) pc_load_segment_name(PC)
+extern char *pc_load_segment_name PARAMS ((CORE_ADDR));
+
+/* AIX cc seems to get this right. */
+
+#define BELIEVE_PCC_PROMOTION 1
+
+/* return true if a given `pc' value is in `call dummy' function. */
+/* FIXME: This just checks for the end of the stack, which is broken
+ for things like stepping through gcc nested function stubs. */
+#define PC_IN_CALL_DUMMY(STOP_PC, STOP_SP, STOP_FRAME_ADDR) \
+ (STOP_SP < STOP_PC && STOP_PC < STACK_END_ADDR)
+
+#if 0
+extern unsigned int text_start, data_start;
+extern char *corefile;
+#endif
+extern int inferior_pid;
+
+/* We are missing register descriptions in the system header files. Sigh! */
+
+struct regs {
+ int gregs [32]; /* general purpose registers */
+ int pc; /* program conter */
+ int ps; /* processor status, or machine state */
+};
+
+struct fp_status {
+ double fpregs [32]; /* floating GP registers */
+};
+
+
+/* To be used by skip_prologue. */
+
+struct rs6000_framedata {
+ int offset; /* total size of frame --- the distance
+ by which we decrement sp to allocate
+ the frame */
+ int saved_gpr; /* smallest # of saved gpr */
+ int saved_fpr; /* smallest # of saved fpr */
+ int alloca_reg; /* alloca register number (frame ptr) */
+ char frameless; /* true if frameless functions. */
+ char nosavedpc; /* true if pc not saved. */
+ int gpr_offset; /* offset of saved gprs from prev sp */
+ int fpr_offset; /* offset of saved fprs from prev sp */
+ int lr_offset; /* offset of saved lr */
+ int cr_offset; /* offset of saved cr */
+};
+
+/* Define the byte order of the machine. */
+
+#define TARGET_BYTE_ORDER_DEFAULT BIG_ENDIAN
+
+/* AIX's assembler doesn't grok dollar signs in identifiers.
+ So we use dots instead. This item must be coordinated with G++. */
+#undef CPLUS_MARKER
+#define CPLUS_MARKER '.'
+
+/* Offset from address of function to start of its code.
+ Zero on most machines. */
+
+#define FUNCTION_START_OFFSET 0
+
+/* Advance PC across any function entry prologue instructions
+ to reach some "real" code. */
+
+#define SKIP_PROLOGUE(pc) \
+do { \
+ struct rs6000_framedata _frame; \
+ pc = skip_prologue (pc, &_frame); \
+} while (0)
+
+extern CORE_ADDR skip_prologue PARAMS((CORE_ADDR, struct rs6000_framedata *));
+
+
+/* If PC is in some function-call trampoline code, return the PC
+ where the function itself actually starts. If not, return NULL. */
+
+#define SKIP_TRAMPOLINE_CODE(pc) skip_trampoline_code (pc)
+extern CORE_ADDR skip_trampoline_code PARAMS ((CORE_ADDR));
+
+/* Number of trap signals we need to skip over, once the inferior process
+ starts running. */
+
+#define START_INFERIOR_TRAPS_EXPECTED 2
+
+/* AIX has a couple of strange returns from wait(). */
+
+#define CHILD_SPECIAL_WAITSTATUS(ourstatus, hoststatus) ( \
+ /* "stop after load" status. */ \
+ (hoststatus) == 0x57c ? (ourstatus)->kind = TARGET_WAITKIND_LOADED, 1 : \
+ \
+ /* signal 0. I have no idea why wait(2) returns with this status word. */ \
+ /* It looks harmless. */ \
+ (hoststatus) == 0x7f ? (ourstatus)->kind = TARGET_WAITKIND_SPURIOUS, 1 : \
+ \
+ /* A normal waitstatus. Let the usual macros deal with it. */ \
+ 0)
+
+/* In xcoff, we cannot process line numbers when we see them. This is
+ mainly because we don't know the boundaries of the include files. So,
+ we postpone that, and then enter and sort(?) the whole line table at
+ once, when we are closing the current symbol table in end_symtab(). */
+
+#define PROCESS_LINENUMBER_HOOK() aix_process_linenos ()
+extern void aix_process_linenos PARAMS ((void));
+
+/* Immediately after a function call, return the saved pc.
+ Can't go through the frames for this because on some machines
+ the new frame is not set up until the new function executes
+ some instructions. */
+
+#define SAVED_PC_AFTER_CALL(frame) read_register (LR_REGNUM)
+
+/* Address of end of stack space. */
+
+#define STACK_END_ADDR 0x2ff80000
+
+/* Stack grows downward. */
+
+#define INNER_THAN(lhs,rhs) ((lhs) < (rhs))
+
+/* This is how arguments pushed onto stack or passed in registers.
+ Stack must be aligned on 64-bit boundaries when synthesizing
+ function calls. We don't need STACK_ALIGN, PUSH_ARGUMENTS will
+ handle it. */
+
+#define PUSH_ARGUMENTS(nargs, args, sp, struct_return, struct_addr) \
+ sp = push_arguments((nargs), (args), (sp), (struct_return), (struct_addr))
+extern CORE_ADDR push_arguments PARAMS ((int, struct value **, CORE_ADDR,
+ int, CORE_ADDR));
+
+/* BREAKPOINT_FROM_PC uses the program counter value to determine the
+ breakpoint that should be used */
+extern breakpoint_from_pc_fn rs6000_breakpoint_from_pc;
+#define BREAKPOINT_FROM_PC(pcptr, lenptr) rs6000_breakpoint_from_pc (pcptr, lenptr)
+
+/* Amount PC must be decremented by after a breakpoint.
+ This is often the number of bytes in BREAKPOINT
+ but not always. */
+
+#define DECR_PC_AFTER_BREAK 0
+
+/* Say how long (ordinary) registers are. This is a piece of bogosity
+ used in push_word and a few other places; REGISTER_RAW_SIZE is the
+ real way to know how big a register is. */
+#define REGISTER_SIZE 4
+
+
+/* Return the name of register number REG. This may return "" to
+ indicate a register number that's not used on this variant.
+ (Register numbers may be sparse for consistency between variants.) */
+#define REGISTER_NAME(reg) (rs6000_register_name(reg))
+extern char *rs6000_register_name (int reg);
+
+/* Number of machine registers */
+#define NUM_REGS 183
+
+/* 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 1 /* Contains address of executing stack frame */
+#define SP_REGNUM 1 /* Contains address of top of stack */
+#define TOC_REGNUM 2 /* TOC register */
+#define FP0_REGNUM 32 /* Floating point register 0 */
+#define GP0_REGNUM 0 /* GPR register 0 */
+#define FP0_REGNUM 32 /* FPR (Floating point) register 0 */
+#define FPLAST_REGNUM 63 /* Last floating point register */
+
+/* Special purpose registers... */
+/* P.S. keep these in the same order as in /usr/mstsave.h `mstsave'
+ structure, for easier processing */
+
+#define PC_REGNUM 64 /* Program counter (instruction address %iar)*/
+#define PS_REGNUM 65 /* Processor (or machine) status (%msr) */
+#define CR_REGNUM 66 /* Condition register */
+#define LR_REGNUM 67 /* Link register */
+#define CTR_REGNUM 68 /* Count register */
+#define XER_REGNUM 69 /* Fixed point exception registers */
+#define MQ_REGNUM 70 /* Multiply/quotient register */
+
+/* These #defines are used to parse core files and talk to ptrace, so they
+ must remain fixed. */
+#define FIRST_UISA_SP_REGNUM 64 /* first special register number */
+#define LAST_UISA_SP_REGNUM 70 /* last special register number */
+
+/* This is the offset in REG_NAMES at which the `set processor'
+ command starts plugging in its names. */
+#define FIRST_VARIANT_REGISTER 66
+
+/* Total amount of space needed to store our copies of the machine's
+ register state, the array `registers'.
+ 32 4-byte gpr's
+ 32 8-byte fpr's
+ 7 4-byte UISA special purpose registers,
+ 16 4-byte segment registers,
+ 32 4-byte standard OEA special-purpose registers,
+ and up to 64 4-byte non-standard OEA special purpose regs.
+ total: (+ (* 32 4) (* 32 8) (* 7 4) (* 16 4) (* 32 4) (* 64 4)) 860 bytes
+ Keep some extra space for now, in case to add more. */
+#define REGISTER_BYTES 880
+
+
+/* Index within `registers' of the first byte of the space for
+ register N. */
+
+#define REGISTER_BYTE(N) \
+ ( \
+ ((N) > FPLAST_REGNUM) ? ((((N) - FPLAST_REGNUM -1) * 4) + 384)\
+ :((N) >= FP0_REGNUM) ? ((((N) - FP0_REGNUM) * 8) + 128) \
+ :((N) * 4) )
+
+/* Number of bytes of storage in the actual machine representation
+ for register N. */
+/* Note that the unsigned cast here forces the result of the
+ subtraction to very high positive values if N < FP0_REGNUM */
+
+#define REGISTER_RAW_SIZE(N) (((unsigned)(N) - FP0_REGNUM) < 32 ? 8 : 4)
+
+/* Number of bytes of storage in the program's representation
+ for register N. On the RS6000, all regs are 4 bytes
+ except the floating point regs which are 8-byte doubles. */
+
+#define REGISTER_VIRTUAL_SIZE(N) (((unsigned)(N) - FP0_REGNUM) < 32 ? 8 : 4)
+
+/* Largest value REGISTER_RAW_SIZE can have. */
+
+#define MAX_REGISTER_RAW_SIZE 8
+
+/* Largest value REGISTER_VIRTUAL_SIZE can have. */
+
+#define MAX_REGISTER_VIRTUAL_SIZE 8
+
+/* convert a dbx stab register number (from `r' declaration) to a gdb REGNUM */
+
+#define STAB_REG_TO_REGNUM(value) (value)
+
+/* Nonzero if register N requires conversion
+ from raw format to virtual format.
+ The register format for rs6000 floating point registers is always
+ double, we need a conversion if the memory format is float. */
+
+#define REGISTER_CONVERTIBLE(N) ((N) >= FP0_REGNUM && (N) <= FPLAST_REGNUM)
+
+/* Convert data from raw format for register REGNUM in buffer FROM
+ to virtual format with type TYPE in buffer TO. */
+
+#define REGISTER_CONVERT_TO_VIRTUAL(REGNUM,TYPE,FROM,TO) \
+{ \
+ if (TYPE_LENGTH (TYPE) != REGISTER_RAW_SIZE (REGNUM)) \
+ { \
+ double val = extract_floating ((FROM), REGISTER_RAW_SIZE (REGNUM)); \
+ store_floating ((TO), TYPE_LENGTH (TYPE), val); \
+ } \
+ else \
+ memcpy ((TO), (FROM), REGISTER_RAW_SIZE (REGNUM)); \
+}
+
+/* Convert data from virtual format with type TYPE in buffer FROM
+ to raw format for register REGNUM in buffer TO. */
+
+#define REGISTER_CONVERT_TO_RAW(TYPE,REGNUM,FROM,TO) \
+{ \
+ if (TYPE_LENGTH (TYPE) != REGISTER_RAW_SIZE (REGNUM)) \
+ { \
+ double val = extract_floating ((FROM), TYPE_LENGTH (TYPE)); \
+ store_floating ((TO), REGISTER_RAW_SIZE (REGNUM), val); \
+ } \
+ else \
+ memcpy ((TO), (FROM), REGISTER_RAW_SIZE (REGNUM)); \
+}
+
+/* Return the GDB type object for the "standard" data type
+ of data in register N. */
+
+#define REGISTER_VIRTUAL_TYPE(N) \
+ (((unsigned)(N) - FP0_REGNUM) < 32 ? builtin_type_double : builtin_type_int)
+
+/* Store the address of the place in which to copy the structure the
+ subroutine will return. This is called from call_function. */
+/* in RS6000, struct return addresses are passed as an extra parameter in r3.
+ In function return, callee is not responsible of returning this address back.
+ Since gdb needs to find it, we will store in a designated variable
+ `rs6000_struct_return_address'. */
+
+extern CORE_ADDR rs6000_struct_return_address;
+
+#define STORE_STRUCT_RETURN(ADDR, SP) \
+ { write_register (3, (ADDR)); \
+ rs6000_struct_return_address = (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) \
+ memcpy (VALBUF, REGBUF, TYPE_LENGTH (TYPE)) */
+
+#define EXTRACT_RETURN_VALUE(TYPE,REGBUF,VALBUF) \
+ extract_return_value(TYPE,REGBUF,VALBUF)
+extern void extract_return_value PARAMS ((struct type *, char [], char *));
+
+/* Write into appropriate registers a function return value
+ of type TYPE, given in virtual format. */
+
+#define STORE_RETURN_VALUE(TYPE,VALBUF) \
+ { \
+ if (TYPE_CODE (TYPE) == TYPE_CODE_FLT) \
+ \
+ /* Floating point values are returned starting from FPR1 and up. \
+ Say a double_double_double type could be returned in \
+ FPR1/FPR2/FPR3 triple. */ \
+ \
+ write_register_bytes (REGISTER_BYTE (FP0_REGNUM+1), (VALBUF), \
+ TYPE_LENGTH (TYPE)); \
+ else \
+ /* Everything else is returned in GPR3 and up. */ \
+ write_register_bytes (REGISTER_BYTE (GP0_REGNUM+3), (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) rs6000_struct_return_address
+
+/* 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. */
+
+/* In the case of the RS6000, the frame's nominal address
+ is the address of a 4-byte word containing the calling frame's address. */
+
+#define FRAME_CHAIN(thisframe) rs6000_frame_chain (thisframe)
+CORE_ADDR rs6000_frame_chain PARAMS ((struct frame_info *));
+
+/* Define other aspects of the stack frame. */
+
+/* A macro that tells us whether the function invocation represented
+ by FI does not have a frame on the stack associated with it. If it
+ does not, FRAMELESS is set to 1, else 0. */
+
+#define FRAMELESS_FUNCTION_INVOCATION(FI, FRAMELESS) \
+ FRAMELESS = frameless_function_invocation (FI)
+
+extern int frameless_function_invocation PARAMS((struct frame_info *));
+
+#define INIT_FRAME_PC_FIRST(fromleaf, prev) \
+ prev->pc = (fromleaf ? SAVED_PC_AFTER_CALL (prev->next) : \
+ prev->next ? FRAME_SAVED_PC (prev->next) : read_pc ());
+#define INIT_FRAME_PC(fromleaf, prev) /* nothing */
+extern void rs6000_init_extra_frame_info (int fromleaf, struct frame_info *);
+#define INIT_EXTRA_FRAME_INFO(fromleaf, fi) rs6000_init_extra_frame_info (fromleaf, fi)
+
+/* If the kernel has to deliver a signal, it pushes a sigcontext
+ structure on the stack and then calls the signal handler, passing
+ the address of the sigcontext in an argument register. Usually
+ the signal handler doesn't save this register, so we have to
+ access the sigcontext structure via an offset from the signal handler
+ frame.
+ The following constants were determined by experimentation on AIX 3.2. */
+#define SIG_FRAME_PC_OFFSET 96
+#define SIG_FRAME_LR_OFFSET 108
+#define SIG_FRAME_FP_OFFSET 284
+
+/* Default offset from SP where the LR is stored */
+#define DEFAULT_LR_SAVE 8
+
+/* Return saved PC from a frame */
+#define FRAME_SAVED_PC(FRAME) frame_saved_pc (FRAME)
+
+extern unsigned long frame_saved_pc PARAMS ((struct frame_info *));
+
+extern CORE_ADDR rs6000_frame_args_address PARAMS ((struct frame_info *));
+#define FRAME_ARGS_ADDRESS(FI) rs6000_frame_args_address (FI)
+
+#define FRAME_LOCALS_ADDRESS(FI) FRAME_ARGS_ADDRESS(FI)
+
+
+/* Set VAL to the number of args passed to frame described by FI.
+ Can set VAL to -1, meaning no way to tell. */
+
+/* We can't tell how many args there are
+ now that the C compiler delays popping them. */
+
+#define FRAME_NUM_ARGS(val,fi) (val = -1)
+
+/* Return number of bytes at start of arglist that are not really args. */
+
+#define FRAME_ARGS_SKIP 8 /* Not sure on this. FIXMEmgo */
+
+/* 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. */
+/* In the following implementation for RS6000, we did *not* save sp. I am
+ not sure if it will be needed. The following macro takes care of gpr's
+ and fpr's only. */
+
+extern void rs6000_frame_init_saved_regs PARAMS ((struct frame_info *));
+#define FRAME_INIT_SAVED_REGS(FI) rs6000_frame_init_saved_regs (FI)
+
+/* Things needed for making the inferior call functions. */
+
+/* Push an empty stack frame, to record the current PC, etc. */
+/* Change these names into rs6k_{push, pop}_frame(). FIXMEmgo. */
+
+#define PUSH_DUMMY_FRAME push_dummy_frame ()
+extern void push_dummy_frame PARAMS ((void));
+
+/* Discard from the stack the innermost frame,
+ restoring all saved registers. */
+
+#define POP_FRAME pop_frame ()
+extern void pop_frame PARAMS ((void));
+
+/* This sequence of words is the instructions:
+
+ mflr r0 // 0x7c0802a6
+ // save fpr's
+ stfd r?, num(r1) // 0xd8010000 there should be 32 of this??
+ // save gpr's
+ stm r0, num(r1) // 0xbc010000
+ stu r1, num(r1) // 0x94210000
+
+ // the function we want to branch might be in a different load
+ // segment. reset the toc register. Note that the actual toc address
+ // will be fix by fix_call_dummy () along with function address.
+
+ st r2, 0x14(r1) // 0x90410014 save toc register
+ liu r2, 0x1234 // 0x3c401234 reset a new toc value 0x12345678
+ oril r2, r2,0x5678 // 0x60425678
+
+ // load absolute address 0x12345678 to r0
+ liu r0, 0x1234 // 0x3c001234
+ oril r0, r0,0x5678 // 0x60005678
+ mtctr r0 // 0x7c0903a6 ctr <- r0
+ bctrl // 0x4e800421 jump subroutine 0x12345678 (%ctr)
+ cror 0xf, 0xf, 0xf // 0x4def7b82
+ brpt // 0x7d821008, breakpoint
+ cror 0xf, 0xf, 0xf // 0x4def7b82 (for 8 byte alignment)
+
+
+ We actually start executing by saving the toc register first, since the pushing
+ of the registers is done by PUSH_DUMMY_FRAME. If this were real code,
+ the arguments for the function called by the `bctrl' would be pushed
+ between the `stu' and the `bctrl', and we could allow it to execute through.
+ But the arguments have to be pushed by GDB after the PUSH_DUMMY_FRAME is done,
+ and we cannot allow to push the registers again.
+*/
+
+#define CALL_DUMMY {0x7c0802a6, 0xd8010000, 0xbc010000, 0x94210000, \
+ 0x90410014, 0x3c401234, 0x60425678, \
+ 0x3c001234, 0x60005678, 0x7c0903a6, 0x4e800421, \
+ 0x4def7b82, 0x7d821008, 0x4def7b82 }
+
+
+/* keep this as multiple of 8 (%sp requires 8 byte alignment) */
+#define CALL_DUMMY_LENGTH 56
+
+#define CALL_DUMMY_START_OFFSET 16
+
+/* Insert the specified number of args and function address into a
+ call sequence of the above form stored at DUMMYNAME. */
+
+#define FIX_CALL_DUMMY(dummyname, pc, fun, nargs, args, type, gcc_p) \
+ rs6000_fix_call_dummy (dummyname, pc, fun, nargs, args, type, gcc_p)
+extern void rs6000_fix_call_dummy PARAMS ((char *, CORE_ADDR, CORE_ADDR,
+ int, struct value **,
+ struct type *, int));
+
+/* Hook in rs6000-tdep.c for determining the TOC address when
+ calling functions in the inferior. */
+extern CORE_ADDR (*find_toc_address_hook) PARAMS ((CORE_ADDR));
+
+/* xcoffread.c provides a function to determine the TOC offset
+ for a given object file.
+ It is used under native AIX configurations for determining the
+ TOC address when calling functions in the inferior. */
+#ifdef __STDC__
+struct objfile;
+#endif
+extern CORE_ADDR get_toc_offset PARAMS ((struct objfile *));
+
+/* Usually a function pointer's representation is simply the address
+ of the function. On the RS/6000 however, a function pointer is
+ represented by a pointer to a TOC entry. This TOC entry contains
+ three words, the first word is the address of the function, the
+ second word is the TOC pointer (r2), and the third word is the
+ static chain value. Throughout GDB it is currently assumed that a
+ function pointer contains the address of the function, which is not
+ easy to fix. In addition, the conversion of a function address to
+ a function pointer would require allocation of a TOC entry in the
+ inferior's memory space, with all its drawbacks. To be able to
+ call C++ virtual methods in the inferior (which are called via
+ function pointers), find_function_addr uses this macro to get the
+ function address from a function pointer. */
+
+#define CONVERT_FROM_FUNC_PTR_ADDR(ADDR) \
+ (is_magic_function_pointer (ADDR) ? read_memory_integer (ADDR, 4) : (ADDR))
+extern int is_magic_function_pointer PARAMS ((CORE_ADDR));
+
+/* Flag for machine-specific stuff in shared files. FIXME */
+#define IBM6000_TARGET
+
+/* RS6000/AIX does not support PT_STEP. Has to be simulated. */
+
+#define SOFTWARE_SINGLE_STEP_P 1
+extern void rs6000_software_single_step PARAMS ((unsigned int, int));
+#define SOFTWARE_SINGLE_STEP(sig,bp_p) rs6000_software_single_step (sig, bp_p)
+
+/* If the current gcc for for this target does not produce correct debugging
+ information for float parameters, both prototyped and unprototyped, then
+ define this macro. This forces gdb to always assume that floats are
+ passed as doubles and then converted in the callee.
+
+ For the PowerPC, it appears that the debug info marks the parameters as
+ floats regardless of whether the function is prototyped, but the actual
+ values are always passed in as doubles. Thus by setting this to 1, both
+ types of calls will work. */
+
+#define COERCE_FLOAT_TO_DOUBLE 1
diff --git a/gdb/config/rs6000/tm-rs6000ly.h b/gdb/config/rs6000/tm-rs6000ly.h
new file mode 100644
index 00000000000..0946b0f476a
--- /dev/null
+++ b/gdb/config/rs6000/tm-rs6000ly.h
@@ -0,0 +1,32 @@
+/* Macro definitions for RS6000 running under LynxOS.
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef TM_RS6000LYNX_H
+#define TM_RS6000LYNX_H
+
+#include "tm-lynx.h"
+
+/* Use generic RS6000 definitions. */
+#include "rs6000/tm-rs6000.h"
+
+#undef PC_LOAD_SEGMENT
+
+#define CANNOT_STORE_REGISTER(regno) (regno == PS_REGNUM)
+
+#endif /* TM_RS6000LYNX_H */
diff --git a/gdb/config/rs6000/xm-aix4.h b/gdb/config/rs6000/xm-aix4.h
new file mode 100644
index 00000000000..1bc5cae9326
--- /dev/null
+++ b/gdb/config/rs6000/xm-aix4.h
@@ -0,0 +1,26 @@
+/* Parameters for hosting on an RS6000, for GDB, the GNU debugger.
+ Copyright 1986, 1987, 1989, 1991, 1992, 1993 Free Software Foundation, Inc.
+ Contributed by IBM Corporation.
+
+This file is part of GDB.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "xm-aix4.h"
+
+/* AIX 4.x uses nonstandard "int *" as type of third argument to ptrace() */
+
+#define PTRACE_ARG3_TYPE int*
+
diff --git a/gdb/config/rs6000/xm-rs6000.h b/gdb/config/rs6000/xm-rs6000.h
new file mode 100644
index 00000000000..44b8b244e94
--- /dev/null
+++ b/gdb/config/rs6000/xm-rs6000.h
@@ -0,0 +1,107 @@
+/* Parameters for hosting on an RS6000, for GDB, the GNU debugger.
+ Copyright 1986-87, 1989, 1991-96, 1998 Free Software Foundation, Inc.
+ Contributed by IBM Corporation.
+
+This file is part of GDB.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* The following text is taken from config/rs6000.mh:
+ * # The IBM version of /usr/include/rpc/rpc.h has a bug -- it says
+ * # `extern fd_set svc_fdset;' without ever defining the type fd_set.
+ * # Unfortunately this occurs in the vx-share code, which is not configured
+ * # like the rest of GDB (e.g. it doesn't include "defs.h").
+ * # We circumvent this bug by #define-ing fd_set here, but undefining it in
+ * # the xm-rs6000.h file before ordinary modules try to use it. FIXME, IBM!
+ * MH_CFLAGS='-Dfd_set=int'
+ * So, here we do the undefine...which has to occur before we include
+ * <sys/select.h> below.
+ */
+#undef fd_set
+
+#include <sys/select.h>
+
+/* Big end is at the low address */
+
+#define HOST_BYTE_ORDER BIG_ENDIAN
+
+/* At least as of AIX 3.2, we have termios. */
+#define HAVE_TERMIOS 1
+/* #define HAVE_TERMIO 1 */
+
+#define USG 1
+#define HAVE_SIGSETMASK 1
+
+#define FIVE_ARG_PTRACE
+
+/* This system requires that we open a terminal with O_NOCTTY for it to
+ not become our controlling terminal. */
+
+#define USE_O_NOCTTY
+
+/* Brain death inherited from PC's pervades. */
+#undef NULL
+#define NULL 0
+
+/* The IBM compiler requires this in order to properly compile alloca(). */
+#pragma alloca
+
+/* There is no vfork. */
+
+#define vfork fork
+
+/* Setpgrp() takes arguments, unlike ordinary Sys V's. */
+
+#define SETPGRP_ARGS 1
+
+/* AIX doesn't have strdup, so we need to declare it for libiberty */
+extern char *strdup PARAMS ((char *));
+
+/* Signal handler for SIGWINCH `window size changed'. */
+
+#define SIGWINCH_HANDLER aix_resizewindow
+extern void aix_resizewindow PARAMS ((int));
+
+/* This doesn't seem to be declared in any header file I can find. */
+char *termdef PARAMS ((int, int));
+
+/* `lines_per_page' and `chars_per_line' are local to utils.c. Rectify this. */
+
+#define SIGWINCH_HANDLER_BODY \
+ \
+/* Respond to SIGWINCH `window size changed' signal, and reset GDB's \
+ window settings appropriately. */ \
+ \
+void \
+aix_resizewindow (signo) \
+ int signo; \
+{ \
+ int fd = fileno (stdout); \
+ if (isatty (fd)) { \
+ int val; \
+ \
+ val = atoi (termdef (fd, 'l')); \
+ if (val > 0) \
+ lines_per_page = val; \
+ val = atoi (termdef (fd, 'c')); \
+ if (val > 0) \
+ chars_per_line = val; \
+ } \
+}
+
+/* setpgrp() messes up controling terminal. The other version of it
+ requires libbsd.a. */
+#define setpgrp(XX,YY) setpgid (XX, YY)
+
diff --git a/gdb/config/rs6000/xm-rs6000ly.h b/gdb/config/rs6000/xm-rs6000ly.h
new file mode 100644
index 00000000000..f75cfab139f
--- /dev/null
+++ b/gdb/config/rs6000/xm-rs6000ly.h
@@ -0,0 +1,29 @@
+/* Host-dependent definitions for RS6000 running LynxOS, for GDB.
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef XM_RS6000LYNX_H
+#define XM_RS6000LYNX_H
+
+#define HOST_BYTE_ORDER BIG_ENDIAN
+
+/* Get generic LynxOS host definitions. */
+
+#include "xm-lynx.h"
+
+#endif /* XM_RS6000LYNX_H */
diff --git a/gdb/config/sh/sh.mt b/gdb/config/sh/sh.mt
new file mode 100644
index 00000000000..a6604d4f1d3
--- /dev/null
+++ b/gdb/config/sh/sh.mt
@@ -0,0 +1,6 @@
+# Target: Hitachi Super-H with ICE and simulator
+TDEPFILES= sh-tdep.o monitor.o sh3-rom.o remote-e7000.o ser-e7kpc.o dsrec.o
+TM_FILE= tm-sh.h
+
+SIM_OBS = remote-sim.o
+SIM = ../sim/sh/libsim.a
diff --git a/gdb/config/sh/tm-sh.h b/gdb/config/sh/tm-sh.h
new file mode 100644
index 00000000000..21779094f65
--- /dev/null
+++ b/gdb/config/sh/tm-sh.h
@@ -0,0 +1,281 @@
+/* Target-specific definition for a Hitachi Super-H.
+ Copyright (C) 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Contributed by Steve Chamberlain sac@cygnus.com */
+
+#ifdef __STDC__
+struct frame_info;
+struct frame_saved_regs;
+struct value;
+struct type;
+#endif
+
+#define GDB_TARGET_IS_SH
+
+#define IEEE_FLOAT 1
+
+/* Define the bit, byte, and word ordering of the machine. */
+
+#define TARGET_BYTE_ORDER_SELECTABLE
+
+
+/* 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. */
+
+extern CORE_ADDR sh_skip_prologue ();
+#define SKIP_PROLOGUE(ip) \
+ {(ip) = sh_skip_prologue(ip);}
+
+
+/* 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.
+
+ The return address is the value saved in the PR register + 4 */
+
+#define SAVED_PC_AFTER_CALL(frame) (ADDR_BITS_REMOVE(read_register(PR_REGNUM)))
+
+/* Stack grows downward. */
+
+#define INNER_THAN(lhs,rhs) ((lhs) < (rhs))
+
+/* Illegal instruction - used by the simulator for breakpoint
+ detection */
+
+#define BREAKPOINT {0xc3, 0xc3} /* 0xc3c3 is trapa #c3, and it works in big
+ and little endian modes */
+
+#define BIG_REMOTE_BREAKPOINT { 0xc3, 0x20 }
+#define LITTLE_REMOTE_BREAKPOINT { 0x20, 0xc3 }
+
+/* If your kernel resets the pc after the trap happens you may need to
+ define this before including this file. */
+#define DECR_PC_AFTER_BREAK 0
+
+/* Say how long registers are. */
+#define REGISTER_TYPE long
+
+/* Say how much memory is needed to store a copy of the register set */
+#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
+
+#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
+
+/* Return the GDB type object for the "standard" data type
+ of data in register N. */
+
+#define REGISTER_VIRTUAL_TYPE(N) \
+ ((((N) >= FP0_REGNUM && (N) <= FP15_REGNUM) \
+ || (N) == FPUL_REGNUM) \
+ ? builtin_type_float : builtin_type_int)
+
+/* Initializer for an array of names of registers.
+ Entries beyond the first NUM_REGS are ignored. */
+
+extern char **sh_register_names;
+#define REGISTER_NAME(i) sh_register_names[i]
+
+#define NUM_REGS 59
+
+/* 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 R0_REGNUM 0
+#define STRUCT_RETURN_REGNUM 2
+#define ARG0_REGNUM 4
+#define ARGLAST_REGNUM 7
+#define FP_REGNUM 14
+#define SP_REGNUM 15
+#define PC_REGNUM 16
+#define PR_REGNUM 17
+#define GBR_REGNUM 18
+#define VBR_REGNUM 19
+#define MACH_REGNUM 20
+#define MACL_REGNUM 21
+#define SR_REGNUM 22
+#define FPUL_REGNUM 23
+#define FPSCR_REGNUM 24
+#define FP0_REGNUM 25
+#define FP15_REGNUM 40
+#define SSR_REGNUM 41
+#define SPC_REGNUM 42
+#define R0B0_REGNUM 43
+#define R0B1_REGNUM 51
+
+#define NUM_REALREGS 59
+
+/* Store the address of the place in which to copy the structure the
+ subroutine will return. This is called from call_function.
+
+ We store structs through a pointer passed in R0 */
+
+#define STORE_STRUCT_RETURN(ADDR, SP) \
+ { write_register (STRUCT_RETURN_REGNUM, (ADDR)); }
+
+extern use_struct_convention_fn sh_use_struct_convention;
+#define USE_STRUCT_CONVENTION(gcc_p, type) sh_use_struct_convention (gcc_p, type)
+
+/* 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. */
+
+extern void sh_extract_return_value PARAMS ((struct type *, void *, void *));
+#define EXTRACT_RETURN_VALUE(TYPE,REGBUF,VALBUF) \
+ sh_extract_return_value (TYPE, REGBUF, VALBUF)
+
+/* Write into appropriate registers a function return value
+ of type TYPE, given in virtual format.
+
+ Things always get returned in R0/R1 */
+
+#define STORE_RETURN_VALUE(TYPE,VALBUF) \
+ write_register_bytes (REGISTER_BYTE(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) \
+ extract_address (REGBUF, REGISTER_RAW_SIZE (0))
+
+
+/* Define other aspects of the stack frame.
+ we keep a copy of the worked out return pc lying around, since it
+ is a useful bit of info */
+
+#define EXTRA_FRAME_INFO \
+ CORE_ADDR return_pc; \
+ int leaf_function; \
+ int f_offset;
+
+#define INIT_EXTRA_FRAME_INFO(fromleaf, fi) \
+ sh_init_extra_frame_info(fromleaf, fi)
+extern void sh_init_extra_frame_info PARAMS ((int, struct frame_info *));
+
+/* A macro that tells us whether the function invocation represented
+ by FI does not have a frame on the stack associated with it. If it
+ does not, FRAMELESS is set to 1, else 0. */
+
+#define FRAMELESS_FUNCTION_INVOCATION(FI, FRAMELESS) \
+ (FRAMELESS) = frameless_look_for_prologue(FI)
+
+#define FRAME_SAVED_PC(FRAME) ((FRAME)->return_pc)
+#define FRAME_ARGS_ADDRESS(fi) ((fi)->frame)
+#define FRAME_LOCALS_ADDRESS(fi) ((fi)->frame)
+
+/* Set VAL to the number of args passed to frame described by FI.
+ Can set VAL to -1, meaning no way to tell. */
+
+/* We can't tell how many args there are */
+
+#define FRAME_NUM_ARGS(val,fi) (val = -1)
+
+/* Return number of bytes at start of arglist that are not really args. */
+
+#define FRAME_ARGS_SKIP 0
+
+extern void sh_frame_find_saved_regs PARAMS ((struct frame_info *fi,
+ struct frame_saved_regs *fsr));
+
+/* 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) \
+ sh_frame_find_saved_regs(frame_info, &(frame_saved_regs))
+
+#define NAMES_HAVE_UNDERSCORE
+
+typedef unsigned short INSN_WORD;
+
+extern CORE_ADDR sh_push_arguments PARAMS ((int nargs,
+ struct value **args,
+ CORE_ADDR sp,
+ unsigned char struct_return,
+ CORE_ADDR struct_addr));
+
+#define USE_GENERIC_DUMMY_FRAMES
+#define CALL_DUMMY {0}
+#define CALL_DUMMY_LENGTH (0)
+#define CALL_DUMMY_START_OFFSET (0)
+#define CALL_DUMMY_BREAKPOINT_OFFSET (0)
+#define FIX_CALL_DUMMY(DUMMY, STARTADDR, FUNADDR, NARGS, ARGS, TYPE, GCCP)
+#define CALL_DUMMY_LOCATION AT_ENTRY_POINT
+#define CALL_DUMMY_ADDRESS() entry_point_address ()
+extern CORE_ADDR sh_push_return_address PARAMS ((CORE_ADDR, CORE_ADDR));
+#define PUSH_RETURN_ADDRESS(PC, SP) sh_push_return_address (PC, SP)
+
+
+extern CORE_ADDR sh_frame_chain PARAMS ((struct frame_info *));
+#define FRAME_CHAIN(FRAME) sh_frame_chain(FRAME)
+#define PUSH_DUMMY_FRAME generic_push_dummy_frame ()
+#define FRAME_CHAIN_VALID(FP, FRAME) generic_frame_chain_valid (FP, FRAME)
+#define PC_IN_CALL_DUMMY(PC, SP, FP) generic_pc_in_call_dummy (PC, SP)
+#define PUSH_ARGUMENTS(NARGS, ARGS, SP, STRUCT_RETURN, STRUCT_ADDR) \
+ (SP) = sh_push_arguments (NARGS, ARGS, SP, STRUCT_RETURN, STRUCT_ADDR)
+
+/* override the standard get_saved_register function with
+ one that takes account of generic CALL_DUMMY frames */
+#define GET_SAVED_REGISTER
+
+/* Discard from the stack the innermost frame, restoring all saved
+ registers. */
+
+extern void sh_pop_frame PARAMS ((void));
+#define POP_FRAME sh_pop_frame();
+
+#define NOP {0x20, 0x0b}
+
+#define REGISTER_SIZE 4
+
+#define COERCE_FLOAT_TO_DOUBLE 1
+
+#define BELIEVE_PCC_PROMOTION 1
+
+/* Need this for WinGDB. See gdb/mswin/{regdoc.h, gdbwin.c, gui.cpp}. */
+#define TARGET_SH
diff --git a/gdb/config/sparc/linux.mh b/gdb/config/sparc/linux.mh
new file mode 100644
index 00000000000..954398fb2dd
--- /dev/null
+++ b/gdb/config/sparc/linux.mh
@@ -0,0 +1,7 @@
+# Host: Sparcstation, running Linux
+XDEPFILES= ser-tcp.o
+XM_FILE= xm-linux.h
+NAT_FILE= nm-linux.h
+NATDEPFILES= fork-child.o infptrace.o inftarg.o corelow.o sparc-nat.o
+HOST_IPC=-DBSD_IPC
+GDBSERVER_DEPFILES= low-sparc.o
diff --git a/gdb/config/sparc/linux.mt b/gdb/config/sparc/linux.mt
new file mode 100644
index 00000000000..ca422e93c65
--- /dev/null
+++ b/gdb/config/sparc/linux.mt
@@ -0,0 +1,3 @@
+# Target: Sparcstation, running Linux
+TDEPFILES= sparc-tdep.o solib.o
+TM_FILE= tm-linux.h
diff --git a/gdb/config/sparc/nbsd.mh b/gdb/config/sparc/nbsd.mh
new file mode 100644
index 00000000000..310838d6acf
--- /dev/null
+++ b/gdb/config/sparc/nbsd.mh
@@ -0,0 +1,6 @@
+# Host: Sun 4 or Sparcstation, running NetBSD
+XDEPFILES= ser-tcp.o
+XM_FILE= xm-nbsd.h
+NAT_FILE= nm-nbsd.h
+NATDEPFILES= fork-child.o infptrace.o inftarg.o corelow.o sparc-nat.o
+HOST_IPC=-DBSD_IPC
diff --git a/gdb/config/sparc/nbsd.mt b/gdb/config/sparc/nbsd.mt
new file mode 100644
index 00000000000..be8a3489095
--- /dev/null
+++ b/gdb/config/sparc/nbsd.mt
@@ -0,0 +1,3 @@
+# Target: Sun 4 or Sparcstation, running NetBSD
+TDEPFILES= sparc-tdep.o solib.o
+TM_FILE= tm-nbsd.h
diff --git a/gdb/config/sparc/nm-linux.h b/gdb/config/sparc/nm-linux.h
new file mode 100644
index 00000000000..b2b2a917f3e
--- /dev/null
+++ b/gdb/config/sparc/nm-linux.h
@@ -0,0 +1,31 @@
+/* Macro definitions for running gdb on a Sparc running Linux.
+ Copyright (C) 1989, 1992, 1996, 1998 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include <nm-sysv4.h>
+#include "solib.h"
+
+#define FETCH_INFERIOR_REGISTERS
+
+/* Return sizeof user struct to callers in less machine dependent routines */
+
+#define KERNEL_U_SIZE kernel_u_size()
+extern int kernel_u_size PARAMS ((void));
+
+/* Linux is svr4ish but not that much */
+#undef USE_PROC_FS
diff --git a/gdb/config/sparc/nm-nbsd.h b/gdb/config/sparc/nm-nbsd.h
new file mode 100644
index 00000000000..016772ae372
--- /dev/null
+++ b/gdb/config/sparc/nm-nbsd.h
@@ -0,0 +1,57 @@
+/* Native-dependent definitions for Sparc running NetBSD, for GDB.
+ Copyright (C) 1986, 1987, 1989, 1992, 1995, 1996
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef NM_NBSD_H
+#define NM_NBSD_H
+
+/* Get generic NetBSD native definitions. */
+
+#include "nm-nbsd.h"
+
+#define FETCH_INFERIOR_REGISTERS
+
+/* Before storing, we need to read all the registers. */
+
+#define CHILD_PREPARE_TO_STORE() read_register_bytes (0, NULL, REGISTER_BYTES)
+
+/* Make things match up with what is expected in sparc-nat.c. */
+
+#define regs trapframe
+#define fp_status fpstate
+
+#define r_g1 tf_global[1]
+#define r_ps tf_psr
+#define r_pc tf_pc
+#define r_npc tf_npc
+#define r_y tf_y
+
+#define fpu fpstate
+#define fpu_regs fs_regs
+#define fpu_fsr fs_fsr
+#define fpu_fr fs_regs
+#define Fpu_fsr fs_fsr
+#define FPU_FSR_TYPE int
+
+#define PTRACE_GETREGS PT_GETREGS
+#define PTRACE_GETFPREGS PT_GETFPREGS
+#define PTRACE_SETREGS PT_SETREGS
+#define PTRACE_SETFPREGS PT_SETFPREGS
+
+#endif /* NM_NBSD_H */
diff --git a/gdb/config/sparc/nm-sparclynx.h b/gdb/config/sparc/nm-sparclynx.h
new file mode 100644
index 00000000000..24011dca649
--- /dev/null
+++ b/gdb/config/sparc/nm-sparclynx.h
@@ -0,0 +1,25 @@
+/* Native-dependent definitions for Sparc running LynxOS.
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef NM_SPARCLYNX_H
+#define NM_SPARCLYNX_H
+
+#include "nm-lynx.h"
+
+#endif /* NM_SPARCLYNX_H */
diff --git a/gdb/config/sparc/nm-sun4os4.h b/gdb/config/sparc/nm-sun4os4.h
new file mode 100644
index 00000000000..9da96be5ddc
--- /dev/null
+++ b/gdb/config/sparc/nm-sun4os4.h
@@ -0,0 +1,35 @@
+/* Macro definitions for running gdb on a Sun 4 running sunos 4.
+ Copyright (C) 1989, 1992, 1996 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Do implement the attach and detach commands. */
+
+#define ATTACH_DETACH
+
+/* Override copies of {fetch,store}_inferior_registers in infptrace.c. */
+
+#define FETCH_INFERIOR_REGISTERS
+
+/* Before storing, we need to read all the registers. */
+
+#define CHILD_PREPARE_TO_STORE() read_register_bytes (0, NULL, REGISTER_BYTES)
+
+/* Return sizeof user struct to callers in less machine dependent routines */
+
+#define KERNEL_U_SIZE kernel_u_size()
+extern int kernel_u_size PARAMS ((void));
diff --git a/gdb/config/sparc/nm-sun4sol2.h b/gdb/config/sparc/nm-sun4sol2.h
new file mode 100644
index 00000000000..f6833f42a61
--- /dev/null
+++ b/gdb/config/sparc/nm-sun4sol2.h
@@ -0,0 +1,45 @@
+/* Native-dependent definitions for Sparc running SVR4.
+ Copyright 1994 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Include the generic SVR4 definitions. */
+
+#include <nm-sysv4.h>
+
+/* Before storing, we need to read all the registers. */
+
+#define CHILD_PREPARE_TO_STORE() read_register_bytes (0, NULL, REGISTER_BYTES)
+
+/* Solaris PSRVADDR support does not seem to include a place for nPC. */
+
+#define PRSVADDR_BROKEN
+
+#ifdef HAVE_THREAD_DB_LIB
+
+#ifdef __STDC__
+struct objfile;
+#endif
+
+#define target_new_objfile(OBJFILE) sol_thread_new_objfile (OBJFILE)
+
+void sol_thread_new_objfile PARAMS ((struct objfile *objfile));
+
+#define FIND_NEW_THREADS sol_find_new_threads
+void sol_find_new_threads PARAMS ((void));
+
+#endif
diff --git a/gdb/config/sparc/sp64.mt b/gdb/config/sparc/sp64.mt
new file mode 100644
index 00000000000..8bb1e07ed1c
--- /dev/null
+++ b/gdb/config/sparc/sp64.mt
@@ -0,0 +1,9 @@
+# Target: SPARC64
+# solib.o and procfs.o taken out for now. We don't have shared libraries yet,
+# and the elf version requires procfs.o but the a.out version doesn't.
+# Then again, having procfs.o in a target makefile fragment seems wrong.
+TDEPFILES = sparc-tdep.o
+TM_FILE= tm-sp64.h
+
+# Need gcc for long long support.
+CC = gcc
diff --git a/gdb/config/sparc/sp64sim.mt b/gdb/config/sparc/sp64sim.mt
new file mode 100644
index 00000000000..a9c5ac94cd4
--- /dev/null
+++ b/gdb/config/sparc/sp64sim.mt
@@ -0,0 +1,13 @@
+# Target: SPARC64 (with simulator)
+# solib.o and procfs.o taken out for now. We don't have shared libraries yet,
+# and the elf version requires procfs.o but the a.out version doesn't.
+# Then again, having procfs.o in a target makefile fragment seems wrong.
+TDEPFILES = sparc-tdep.o
+TM_FILE= tm-sp64.h
+
+# Need gcc for long long support.
+CC = gcc
+
+MH_CFLAGS = -I${srcdir}/../sim/sp64
+SIM_OBS = remote-sim.o
+SIM = ../sim/sp64/libsim.a
diff --git a/gdb/config/sparc/sp64sol2.mt b/gdb/config/sparc/sp64sol2.mt
new file mode 100644
index 00000000000..ce2f0d82df0
--- /dev/null
+++ b/gdb/config/sparc/sp64sol2.mt
@@ -0,0 +1,3 @@
+# Target: Ultrasparc, running Solaris 2
+TDEPFILES= sparc-tdep.o
+TM_FILE= tm-sun4sol2.h
diff --git a/gdb/config/sparc/sparc-em.mt b/gdb/config/sparc/sparc-em.mt
new file mode 100644
index 00000000000..13b0c6a29e2
--- /dev/null
+++ b/gdb/config/sparc/sparc-em.mt
@@ -0,0 +1,3 @@
+# Target: SPARC embedded
+TDEPFILES= sparc-tdep.o
+TM_FILE= tm-spc-em.h
diff --git a/gdb/config/sparc/sparclet.mt b/gdb/config/sparc/sparclet.mt
new file mode 100644
index 00000000000..f08cfd70e5b
--- /dev/null
+++ b/gdb/config/sparc/sparclet.mt
@@ -0,0 +1,3 @@
+# Target: SPARC embedded Sparclet monitor
+TDEPFILES= sparc-tdep.o monitor.o sparclet-rom.o dsrec.o
+TM_FILE= tm-sparclet.h
diff --git a/gdb/config/sparc/sparclite.mt b/gdb/config/sparc/sparclite.mt
new file mode 100644
index 00000000000..43cb38cafa6
--- /dev/null
+++ b/gdb/config/sparc/sparclite.mt
@@ -0,0 +1,5 @@
+# Target: Fujitsu SPARClite processor
+TDEPFILES= sparc-tdep.o sparcl-tdep.o
+TM_FILE= tm-sparclite.h
+SIM_OBS = remote-sim.o
+SIM = ../sim/erc32/libsim.a
diff --git a/gdb/config/sparc/sparclynx.mh b/gdb/config/sparc/sparclynx.mh
new file mode 100644
index 00000000000..6fdddddb6ec
--- /dev/null
+++ b/gdb/config/sparc/sparclynx.mh
@@ -0,0 +1,11 @@
+# Host: Sparc running LynxOS
+
+XM_FILE= xm-sparclynx.h
+XDEPFILES= ser-tcp.o
+XM_CLIBS= -lbsd
+
+NAT_FILE= nm-sparclynx.h
+NATDEPFILES= fork-child.o infptrace.o inftarg.o corelow.o lynx-nat.o
+
+GDBSERVER_LIBS= -lbsd
+GDBSERVER_DEPFILES= low-lynx.o
diff --git a/gdb/config/sparc/sparclynx.mt b/gdb/config/sparc/sparclynx.mt
new file mode 100644
index 00000000000..5e61645caaa
--- /dev/null
+++ b/gdb/config/sparc/sparclynx.mt
@@ -0,0 +1,3 @@
+# Target: Sparc running LynxOS
+TDEPFILES= coff-solib.o sparc-tdep.o
+TM_FILE= tm-sparclynx.h
diff --git a/gdb/config/sparc/sun4os4.mh b/gdb/config/sparc/sun4os4.mh
new file mode 100644
index 00000000000..4047c5cb82a
--- /dev/null
+++ b/gdb/config/sparc/sun4os4.mh
@@ -0,0 +1,11 @@
+# Host: Sun 4 or Sparcstation, running SunOS 4
+XDEPFILES= ser-tcp.o
+XM_FILE= xm-sun4os4.h
+NAT_FILE= nm-sun4os4.h
+NATDEPFILES= fork-child.o infptrace.o inftarg.o corelow.o sparc-nat.o
+HOST_IPC=-DBSD_IPC
+GDBSERVER_DEPFILES= low-sparc.o
+# Setting XM_CLIBS=-lresolv would let us use the DNS, but that would screw
+# anyone who wants to use NIS, which includes at least one Cygnus customer
+# (PR 3593). So leave it this way until/unless we find a resolver which can
+# get names from either DNS or NIS from the same GDB binary.
diff --git a/gdb/config/sparc/sun4os4.mt b/gdb/config/sparc/sun4os4.mt
new file mode 100644
index 00000000000..5a4ecb9546e
--- /dev/null
+++ b/gdb/config/sparc/sun4os4.mt
@@ -0,0 +1,3 @@
+# Target: Sun 4 or Sparcstation, running SunOS 4
+TDEPFILES= sparc-tdep.o solib.o
+TM_FILE= tm-sun4os4.h
diff --git a/gdb/config/sparc/sun4sol2.mh b/gdb/config/sparc/sun4sol2.mh
new file mode 100644
index 00000000000..468b362158b
--- /dev/null
+++ b/gdb/config/sparc/sun4sol2.mh
@@ -0,0 +1,18 @@
+# Host: Sun 4 or Sparcstation, running Solaris 2
+
+XM_FILE= xm-sun4sol2.h
+XDEPFILES= ser-tcp.o
+XM_CLIBS= -lsocket -lnsl
+
+NAT_FILE= nm-sun4sol2.h
+NATDEPFILES= corelow.o core-sol2.o solib.o procfs.o fork-child.o
+
+# If you are compiling with Sun's compiler, add the -xs option to CC
+# (e.g. `make CC="cc -xs"').
+# Sun's compilers require the -xs option to produce debug information
+# in the final linked executable. Otherwise they leave it in the .o
+# files only, with undocumented pointers to it in the linked executable.
+# This is commented out because we don't assume that the Sun compiler
+# is in use.
+#MH_CFLAGS=-xs
+HOST_IPC=-DBSD_IPC
diff --git a/gdb/config/sparc/sun4sol2.mt b/gdb/config/sparc/sun4sol2.mt
new file mode 100644
index 00000000000..af70e9f9f9f
--- /dev/null
+++ b/gdb/config/sparc/sun4sol2.mt
@@ -0,0 +1,3 @@
+# Target: Sun 4 or Sparcstation, running Solaris 2
+TDEPFILES= sparc-tdep.o
+TM_FILE= tm-sun4sol2.h
diff --git a/gdb/config/sparc/tm-linux.h b/gdb/config/sparc/tm-linux.h
new file mode 100644
index 00000000000..2cc708aa080
--- /dev/null
+++ b/gdb/config/sparc/tm-linux.h
@@ -0,0 +1,29 @@
+/* Macro definitions for GDB for a Sparc running Linux.
+ Copyright 1989, 1992, 1994, 1995, 1998 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef TM_SPARCLINUX_H
+#define TM_SPARCLINUX_H
+
+#include "sparc/tm-sparc.h"
+
+#define SIGCONTEXT_PC_OFFSET 12
+
+#include "tm-sysv4.h"
+
+#endif /* TM_SPARCLINUX_H */
diff --git a/gdb/config/sparc/tm-nbsd.h b/gdb/config/sparc/tm-nbsd.h
new file mode 100644
index 00000000000..1a310844194
--- /dev/null
+++ b/gdb/config/sparc/tm-nbsd.h
@@ -0,0 +1,27 @@
+/* Macro definitions for Sparc running under NetBSD.
+ Copyright 1994 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef TM_NBSD_H
+#define TM_NBSD_H
+
+#include "sparc/tm-sparc.h"
+
+#include "tm-nbsd.h"
+
+#endif /* TM_NBSD_H */
diff --git a/gdb/config/sparc/tm-sp64.h b/gdb/config/sparc/tm-sp64.h
new file mode 100644
index 00000000000..40a9a626d0d
--- /dev/null
+++ b/gdb/config/sparc/tm-sp64.h
@@ -0,0 +1,378 @@
+/* Target machine sub-parameters for SPARC64, for GDB, the GNU debugger.
+ This is included by other tm-*.h files to define SPARC64 cpu-related info.
+ Copyright 1994, 1995, 1996, 1998 Free Software Foundation, Inc.
+ This is (obviously) based on the SPARC Vn (n<9) port.
+ Contributed by Doug Evans (dje@cygnus.com).
+ Further modified by Bob Manson (manson@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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define GDB_TARGET_IS_SPARC64
+
+#ifdef __STDC__
+struct value;
+#endif
+
+/* Eeeew. Ok, we have to assume (for now) that the processor really is
+ in sparc64 mode. While this is the same instruction sequence as
+ on the Sparc, the stack frames are offset by +2047 (and the arguments
+ are 8 bytes instead of 4). */
+/* Instructions are:
+ std %f10, [ %fp + 0x7a7 ]
+ std %f8, [ %fp + 0x79f ]
+ std %f6, [ %fp + 0x797 ]
+ std %f4, [ %fp + 0x78f ]
+ std %f2, [ %fp + 0x787 ]
+ std %f0, [ %fp + 0x77f ]
+ std %g6, [ %fp + 0x777 ]
+ std %g4, [ %fp + 0x76f ]
+ std %g2, [ %fp + 0x767 ]
+ std %g0, [ %fp + 0x75f ]
+ std %fp, [ %fp + 0x757 ]
+ std %i4, [ %fp + 0x74f ]
+ std %i2, [ %fp + 0x747 ]
+ std %i0, [ %fp + 0x73f ]
+ nop
+ nop
+ nop
+ nop
+ rd %tbr, %o0
+ st %o0, [ %fp + 0x72b ]
+ rd %tpc, %o0
+ st %o0, [ %fp + 0x727 ]
+ rd %psr, %o0
+ st %o0, [ %fp + 0x723 ]
+ rd %y, %o0
+ st %o0, [ %fp + 0x71f ]
+ ldx [ %sp + 0x8a7 ], %o5
+ ldx [ %sp + 0x89f ], %o4
+ ldx [ %sp + 0x897 ], %o3
+ ldx [ %sp + 0x88f ], %o2
+ ldx [ %sp + 0x887 ], %o1
+ call %g0
+ ldx [ %sp + 0x87f ], %o0
+ nop
+ ta 1
+ nop
+ nop
+ */
+
+#define CALL_DUMMY { 0x9de3bec0fd3fa7f7LL, 0xf93fa7eff53fa7e7LL,\
+ 0xf13fa7dfed3fa7d7LL, 0xe93fa7cfe53fa7c7LL,\
+ 0xe13fa7bfdd3fa7b7LL, 0xd93fa7afd53fa7a7LL,\
+ 0xd13fa79fcd3fa797LL, 0xc93fa78fc53fa787LL,\
+ 0xc13fa77fcc3fa777LL, 0xc83fa76fc43fa767LL,\
+ 0xc03fa75ffc3fa757LL, 0xf83fa74ff43fa747LL,\
+ 0xf03fa73f01000000LL, 0x0100000001000000LL,\
+ 0x0100000091580000LL, 0xd027a72b93500000LL,\
+ 0xd027a72791480000LL, 0xd027a72391400000LL,\
+ 0xd027a71fda5ba8a7LL, 0xd85ba89fd65ba897LL,\
+ 0xd45ba88fd25ba887LL, 0x9fc02000d05ba87fLL,\
+ 0x0100000091d02001LL, 0x0100000001000000LL }
+
+
+/* 128 is to reserve space to write the %i/%l registers that will be restored
+ when we resume. */
+#define CALL_DUMMY_STACK_ADJUST 128
+
+#define CALL_DUMMY_LENGTH 192
+
+#define CALL_DUMMY_START_OFFSET 148
+
+#define CALL_DUMMY_CALL_OFFSET (CALL_DUMMY_START_OFFSET + (5 * 4))
+
+#define CALL_DUMMY_BREAKPOINT_OFFSET (CALL_DUMMY_START_OFFSET + (8 * 4))
+
+#include "sparc/tm-sparc.h"
+
+/* Stack must be aligned on 128-bit boundaries when synthesizing
+ function calls. */
+
+#undef STACK_ALIGN
+#define STACK_ALIGN(ADDR) (((ADDR) + 15 ) & -16)
+
+/* Number of machine registers. */
+
+#undef NUM_REGS
+#define NUM_REGS 125
+
+/* Initializer for an array of names of registers.
+ There should be NUM_REGS strings in this initializer. */
+/* Some of these registers are only accessible from priviledged mode.
+ They are here for kernel debuggers, etc. */
+/* FIXME: icc and xcc are currently considered separate registers.
+ This may have to change and consider them as just one (ccr).
+ Let's postpone this as long as we can. It's nice to be able to set
+ them individually. */
+/* FIXME: fcc0-3 are currently separate, even though they are also part of
+ fsr. May have to remove them but let's postpone this as long as
+ possible. It's nice to be able to set them individually. */
+/* FIXME: Whether to include f33, f35, etc. here is not clear.
+ There are advantages and disadvantages. */
+
+#undef REGISTER_NAMES
+#define REGISTER_NAMES \
+{ "g0", "g1", "g2", "g3", "g4", "g5", "g6", "g7", \
+ "o0", "o1", "o2", "o3", "o4", "o5", "sp", "o7", \
+ "l0", "l1", "l2", "l3", "l4", "l5", "l6", "l7", \
+ "i0", "i1", "i2", "i3", "i4", "i5", "fp", "i7", \
+ \
+ "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", \
+ "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", \
+ "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23", \
+ "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", \
+ "f32", "f34", "f36", "f38", "f40", "f42", "f44", "f46", \
+ "f48", "f50", "f52", "f54", "f56", "f58", "f60", "f62", \
+ \
+ "pc", "npc", "ccr", "fsr", "fprs", "y", "asi", \
+ "ver", "tick", "pil", "pstate", \
+ "tstate", "tba", "tl", "tt", "tpc", "tnpc", "wstate", \
+ "cwp", "cansave", "canrestore", "cleanwin", "otherwin", \
+ "asr16", "asr17", "asr18", "asr19", "asr20", "asr21", \
+ "asr22", "asr23", "asr24", "asr25", "asr26", "asr27", \
+ "asr28", "asr29", "asr30", "asr31", \
+ /* These are here at the end to simplify removing them if we have to. */ \
+ "icc", "xcc", "fcc0", "fcc1", "fcc2", "fcc3" \
+}
+
+/* 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. */
+
+#if 0 /* defined in tm-sparc.h, replicated for doc purposes */
+#define G0_REGNUM 0 /* %g0 */
+#define G1_REGNUM 1 /* %g1 */
+#define O0_REGNUM 8 /* %o0 */
+#define SP_REGNUM 14 /* Contains address of top of stack, \
+ which is also the bottom of the frame. */
+#define RP_REGNUM 15 /* Contains return address value, *before* \
+ any windows get switched. */
+#define O7_REGNUM 15 /* Last local reg not saved on stack frame */
+#define L0_REGNUM 16 /* First local reg that's saved on stack frame
+ rather than in machine registers */
+#define I0_REGNUM 24 /* %i0 */
+#define FP_REGNUM 30 /* Contains address of executing stack frame */
+#define I7_REGNUM 31 /* Last local reg saved on stack frame */
+#define FP0_REGNUM 32 /* Floating point register 0 */
+#endif
+
+#define FP_MAX_REGNUM 80 /* 1 + last fp reg number */
+
+/* #undef v8 misc. regs */
+
+#undef Y_REGNUM
+#undef PS_REGNUM
+#undef WIM_REGNUM
+#undef TBR_REGNUM
+#undef PC_REGNUM
+#undef NPC_REGNUM
+#undef FPS_REGNUM
+#undef CPS_REGNUM
+
+/* v9 misc. and priv. regs */
+
+#define C0_REGNUM FP_MAX_REGNUM /* Start of control registers */
+#define PC_REGNUM (C0_REGNUM + 0) /* Current PC */
+#define NPC_REGNUM (C0_REGNUM + 1) /* Next PC */
+#define CCR_REGNUM (C0_REGNUM + 2) /* Condition Code Register (%xcc,%icc) */
+#define FSR_REGNUM (C0_REGNUM + 3) /* Floating Point State */
+#define FPRS_REGNUM (C0_REGNUM + 4) /* Floating Point Registers State */
+#define Y_REGNUM (C0_REGNUM + 5) /* Temp register for multiplication, etc. */
+#define ASI_REGNUM (C0_REGNUM + 6) /* Alternate Space Identifier */
+#define VER_REGNUM (C0_REGNUM + 7) /* Version register */
+#define TICK_REGNUM (C0_REGNUM + 8) /* Tick register */
+#define PIL_REGNUM (C0_REGNUM + 9) /* Processor Interrupt Level */
+#define PSTATE_REGNUM (C0_REGNUM + 10) /* Processor State */
+#define TSTATE_REGNUM (C0_REGNUM + 11) /* Trap State */
+#define TBA_REGNUM (C0_REGNUM + 12) /* Trap Base Address */
+#define TL_REGNUM (C0_REGNUM + 13) /* Trap Level */
+#define TT_REGNUM (C0_REGNUM + 14) /* Trap Type */
+#define TPC_REGNUM (C0_REGNUM + 15) /* Trap pc */
+#define TNPC_REGNUM (C0_REGNUM + 16) /* Trap npc */
+#define WSTATE_REGNUM (C0_REGNUM + 17) /* Window State */
+#define CWP_REGNUM (C0_REGNUM + 18) /* Current Window Pointer */
+#define CANSAVE_REGNUM (C0_REGNUM + 19) /* Savable Windows */
+#define CANRESTORE_REGNUM (C0_REGNUM + 20) /* Restorable Windows */
+#define CLEANWIN_REGNUM (C0_REGNUM + 21) /* Clean Windows */
+#define OTHERWIN_REGNUM (C0_REGNUM + 22) /* Other Windows */
+#define ASR_REGNUM(n) (C0_REGNUM+(23-16)+(n)) /* Ancillary State Register
+ (n = 16...31) */
+#define ICC_REGNUM (C0_REGNUM + 39) /* 32 bit condition codes */
+#define XCC_REGNUM (C0_REGNUM + 40) /* 64 bit condition codes */
+#define FCC0_REGNUM (C0_REGNUM + 41) /* fp cc reg 0 */
+#define FCC1_REGNUM (C0_REGNUM + 42) /* fp cc reg 1 */
+#define FCC2_REGNUM (C0_REGNUM + 43) /* fp cc reg 2 */
+#define FCC3_REGNUM (C0_REGNUM + 44) /* fp cc reg 3 */
+
+/* Total amount of space needed to store our copies of the machine's
+ register state, the array `registers'.
+ Some of the registers aren't 64 bits, but it's a lot simpler just to assume
+ they all are (since most of them are). */
+#undef REGISTER_BYTES
+#define REGISTER_BYTES (32*8+32*8+45*8)
+
+/* Index within `registers' of the first byte of the space for
+ register N. */
+#undef REGISTER_BYTE
+#define REGISTER_BYTE(N) \
+ ((N) < 32 ? (N)*8 \
+ : (N) < 64 ? 32*8 + ((N)-32)*4 \
+ : (N) < C0_REGNUM ? 32*8 + 32*4 + ((N)-64)*8 \
+ : 64*8 + ((N)-C0_REGNUM)*8)
+
+/* Say how long (ordinary) registers are. This is a piece of bogosity
+ used in push_word and a few other places; REGISTER_RAW_SIZE is the
+ real way to know how big a register is. */
+
+#undef REGISTER_SIZE
+#define REGISTER_SIZE 8
+
+/* Number of bytes of storage in the actual machine representation
+ for register N. */
+
+#undef REGISTER_RAW_SIZE
+#define REGISTER_RAW_SIZE(N) \
+ ((N) < 32 ? 8 : (N) < 64 ? 4 : 8)
+
+/* Number of bytes of storage in the program's representation
+ for register N. */
+
+#undef REGISTER_VIRTUAL_SIZE
+#define REGISTER_VIRTUAL_SIZE(N) \
+ ((N) < 32 ? 8 : (N) < 64 ? 4 : 8)
+
+/* Largest value REGISTER_RAW_SIZE can have. */
+/* tm-sparc.h defines this as 8, but play it safe. */
+
+#undef MAX_REGISTER_RAW_SIZE
+#define MAX_REGISTER_RAW_SIZE 8
+
+/* Largest value REGISTER_VIRTUAL_SIZE can have. */
+/* tm-sparc.h defines this as 8, but play it safe. */
+
+#undef MAX_REGISTER_VIRTUAL_SIZE
+#define MAX_REGISTER_VIRTUAL_SIZE 8
+
+/* Return the GDB type object for the "standard" data type
+ of data in register N. */
+
+#undef REGISTER_VIRTUAL_TYPE
+#define REGISTER_VIRTUAL_TYPE(N) \
+ ((N) < 32 ? builtin_type_long_long \
+ : (N) < 64 ? builtin_type_float \
+ : (N) < 80 ? builtin_type_double \
+ : builtin_type_long_long)
+
+/* We use to support both 32 bit and 64 bit pointers.
+ We can't anymore because TARGET_PTR_BIT must now be a constant. */
+#undef TARGET_PTR_BIT
+#define TARGET_PTR_BIT 64
+
+/* Longs are 64 bits. */
+#undef TARGET_LONG_BIT
+#define TARGET_LONG_BIT 64
+
+#undef TARGET_LONG_LONG_BIT
+#define TARGET_LONG_LONG_BIT 64
+
+/* Does the specified function use the "struct returning" convention
+ or the "value returning" convention? The "value returning" convention
+ almost invariably returns the entire value in registers. The
+ "struct returning" convention often returns the entire value in
+ memory, and passes a pointer (out of or into the function) saying
+ where the value (is or should go).
+
+ Since this sometimes depends on whether it was compiled with GCC,
+ this is also an argument. This is used in call_function to build a
+ stack, and in value_being_returned to print return values.
+
+ On Sparc64, we only pass pointers to structs if they're larger then
+ 32 bytes. Otherwise they're stored in %o0-%o3 (floating-point
+ values go into %fp0-%fp3). */
+
+
+#undef USE_STRUCT_CONVENTION
+#define USE_STRUCT_CONVENTION(gcc_p, type) (TYPE_LENGTH (type) > 32)
+
+#undef REG_STRUCT_HAS_ADDR
+#define REG_STRUCT_HAS_ADDR(gcc_p,type) (TYPE_LENGTH (type) > 32)
+
+/* Store the address of the place in which to copy the structure the
+ subroutine will return. This is called from call_function. */
+/* FIXME: V9 uses %o0 for this. */
+
+#undef STORE_STRUCT_RETURN
+#define STORE_STRUCT_RETURN(ADDR, SP) \
+ { target_write_memory ((SP)+(16*8), (char *)&(ADDR), 8); }
+
+/* Return number of bytes at start of arglist that are not really args. */
+
+#undef FRAME_ARGS_SKIP
+#define FRAME_ARGS_SKIP 136
+
+/* Offsets into jmp_buf.
+ FIXME: This was borrowed from the v8 stuff and will probably have to change
+ for v9. */
+
+#define JB_ELEMENT_SIZE 8 /* Size of each element in jmp_buf */
+
+#define JB_ONSSTACK 0
+#define JB_SIGMASK 1
+#define JB_SP 2
+#define JB_PC 3
+#define JB_NPC 4
+#define JB_PSR 5
+#define JB_G1 6
+#define JB_O0 7
+#define JB_WBCNT 8
+
+/* Figure out where the longjmp will land. We expect that we have just entered
+ longjmp and haven't yet setup the stack frame, so the args are still in the
+ output regs. %o0 (O0_REGNUM) points at the jmp_buf structure from which we
+ extract the pc (JB_PC) that we will land at. The pc is copied into ADDR.
+ This routine returns true on success */
+
+extern int
+get_longjmp_target PARAMS ((CORE_ADDR *));
+
+#define GET_LONGJMP_TARGET(ADDR) get_longjmp_target(ADDR)
+
+extern CORE_ADDR sparc64_read_sp ();
+extern CORE_ADDR sparc64_read_fp ();
+extern void sparc64_write_sp PARAMS ((CORE_ADDR));
+extern void sparc64_write_fp PARAMS ((CORE_ADDR));
+
+#define TARGET_READ_SP() (sparc64_read_sp ())
+#define TARGET_READ_FP() (sparc64_read_fp ())
+#define TARGET_WRITE_SP(X) (sparc64_write_sp (X))
+#define TARGET_WRITE_FP(X) (sparc64_write_fp (X))
+
+#undef TM_PRINT_INSN_MACH
+#define TM_PRINT_INSN_MACH bfd_mach_sparc_v9a
+
+CORE_ADDR sp64_push_arguments PARAMS ((int, struct value **, CORE_ADDR, unsigned char, CORE_ADDR));
+#undef PUSH_ARGUMENTS
+#define PUSH_ARGUMENTS(A,B,C,D,E) (sp = sp64_push_arguments ((A), (B), (C), (D), (E)))
+
+#undef EXTRACT_RETURN_VALUE
+#define EXTRACT_RETURN_VALUE(TYPE,REGBUF,VALBUF) \
+ sparc64_extract_return_value(TYPE, REGBUF, VALBUF, 0)
+extern void
+sparc64_extract_return_value PARAMS ((struct type *, char [], char *, int));
diff --git a/gdb/config/sparc/tm-sp64sim.h b/gdb/config/sparc/tm-sp64sim.h
new file mode 100644
index 00000000000..4545f32b4f4
--- /dev/null
+++ b/gdb/config/sparc/tm-sp64sim.h
@@ -0,0 +1,50 @@
+/* Macro definitions for GDB with the SPARC64 Simulator.
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* ??? This file is based on tm-spc-em.h. Our contents are probably bogus
+ but it's a good start. */
+
+#include "sparc/tm-sp64.h"
+#include "tm-sunos.h"
+
+/* Offsets into jmp_buf. Not defined by Sun, but at least documented in a
+ comment in <machine/setjmp.h>! */
+
+#define JB_ELEMENT_SIZE 8 /* Size of each element in jmp_buf */
+
+#define JB_ONSSTACK 0
+#define JB_SIGMASK 1
+#define JB_SP 2
+#define JB_PC 3
+#define JB_NPC 4
+#define JB_PSR 5
+#define JB_G1 6
+#define JB_O0 7
+#define JB_WBCNT 8
+
+/* Figure out where the longjmp will land. We expect that we have just entered
+ longjmp and haven't yet setup the stack frame, so the args are still in the
+ output regs. %o0 (O0_REGNUM) points at the jmp_buf structure from which we
+ extract the pc (JB_PC) that we will land at. The pc is copied into ADDR.
+ This routine returns true on success */
+
+extern int
+get_longjmp_target PARAMS ((CORE_ADDR *));
+
+#define GET_LONGJMP_TARGET(ADDR) get_longjmp_target(ADDR)
diff --git a/gdb/config/sparc/tm-sparc.h b/gdb/config/sparc/tm-sparc.h
new file mode 100644
index 00000000000..ecbe9e2285d
--- /dev/null
+++ b/gdb/config/sparc/tm-sparc.h
@@ -0,0 +1,584 @@
+/* Target machine sub-parameters for SPARC, for GDB, the GNU debugger.
+ This is included by other tm-*.h files to define SPARC cpu-related info.
+ Copyright 1986, 1987, 1989, 1991, 1992, 1993, 1994
+ Free Software Foundation, Inc.
+ Contributed by Michael Tiemann (tiemann@mcc.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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifdef __STDC__
+struct frame_info;
+struct type;
+struct value;
+#endif
+
+#define TARGET_BYTE_ORDER BIG_ENDIAN
+
+/* Floating point is IEEE compatible. */
+#define IEEE_FLOAT
+
+/* If an argument is declared "register", Sun cc will keep it in a register,
+ never saving it onto the stack. So we better not believe the "p" symbol
+ descriptor stab. */
+
+#define USE_REGISTER_NOT_ARG
+
+/* When passing a structure to a function, Sun cc passes the address
+ not the structure itself. It (under SunOS4) creates two symbols,
+ which we need to combine to a LOC_REGPARM. Gcc version two (as of
+ 1.92) behaves like sun cc. REG_STRUCT_HAS_ADDR is smart enough to
+ distinguish between Sun cc, gcc version 1 and gcc version 2. */
+
+#define REG_STRUCT_HAS_ADDR(gcc_p,type) (gcc_p != 1)
+
+/* Sun /bin/cc gets this right as of SunOS 4.1.x. We need to define
+ BELIEVE_PCC_PROMOTION to get this right now that the code which
+ detects gcc2_compiled. is broken. This loses for SunOS 4.0.x and
+ earlier. */
+
+#define BELIEVE_PCC_PROMOTION 1
+
+/* For acc, there's no need to correct LBRAC entries by guessing how
+ they should work. In fact, this is harmful because the LBRAC
+ entries now all appear at the end of the function, not intermixed
+ with the SLINE entries. n_opt_found detects acc for Solaris binaries;
+ function_stab_type detects acc for SunOS4 binaries.
+
+ For binary from SunOS4 /bin/cc, need to correct LBRAC's.
+
+ For gcc, like acc, don't correct. */
+
+#define SUN_FIXED_LBRAC_BUG \
+ (n_opt_found \
+ || function_stab_type == N_STSYM \
+ || function_stab_type == N_GSYM \
+ || processing_gcc_compilation)
+
+/* Do variables in the debug stabs occur after the N_LBRAC or before it?
+ acc: after, gcc: before, SunOS4 /bin/cc: before. */
+
+#define VARIABLES_INSIDE_BLOCK(desc, gcc_p) \
+ (!(gcc_p) \
+ && (n_opt_found \
+ || function_stab_type == N_STSYM \
+ || function_stab_type == N_GSYM))
+
+/* 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. SKIP_PROLOGUE_FRAMELESS_P advances
+ the PC past some of the prologue, but stops as soon as it
+ knows that the function has a frame. Its result is equal
+ to its input PC if the function is frameless, unequal otherwise. */
+
+#define SKIP_PROLOGUE(pc) \
+ { pc = skip_prologue (pc, 0); }
+#define SKIP_PROLOGUE_FRAMELESS_P(pc) \
+ { pc = skip_prologue (pc, 1); }
+extern CORE_ADDR skip_prologue PARAMS ((CORE_ADDR, int));
+
+/* Immediately after a function call, return the saved pc.
+ Can't go through the frames for this because on some machines
+ the new frame is not set up until the new function executes
+ some instructions. */
+
+/* On the Sun 4 under SunOS, the compile will leave a fake insn which
+ encodes the structure size being returned. If we detect such
+ a fake insn, step past it. */
+
+#define PC_ADJUST(pc) sparc_pc_adjust(pc)
+extern CORE_ADDR sparc_pc_adjust PARAMS ((CORE_ADDR));
+
+#define SAVED_PC_AFTER_CALL(frame) PC_ADJUST (read_register (RP_REGNUM))
+
+/* Stack grows downward. */
+
+#define INNER_THAN(lhs,rhs) ((lhs) < (rhs))
+
+/* Stack must be aligned on 64-bit boundaries when synthesizing
+ function calls. */
+
+#define STACK_ALIGN(ADDR) (((ADDR) + 7) & -8)
+
+/* Sequence of bytes for breakpoint instruction (ta 1). */
+
+#define BREAKPOINT {0x91, 0xd0, 0x20, 0x01}
+
+/* Amount PC must be decremented by after a breakpoint.
+ This is often the number of bytes in BREAKPOINT
+ but not always. */
+
+#define DECR_PC_AFTER_BREAK 0
+
+/* Say how long (ordinary) registers are. This is a piece of bogosity
+ used in push_word and a few other places; REGISTER_RAW_SIZE is the
+ real way to know how big a register is. */
+
+#define REGISTER_SIZE 4
+
+/* Number of machine registers */
+
+#define NUM_REGS 72
+
+/* Initializer for an array of names of registers.
+ There should be NUM_REGS strings in this initializer. */
+
+#define REGISTER_NAMES \
+{ "g0", "g1", "g2", "g3", "g4", "g5", "g6", "g7", \
+ "o0", "o1", "o2", "o3", "o4", "o5", "sp", "o7", \
+ "l0", "l1", "l2", "l3", "l4", "l5", "l6", "l7", \
+ "i0", "i1", "i2", "i3", "i4", "i5", "fp", "i7", \
+ \
+ "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", \
+ "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", \
+ "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23", \
+ "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", \
+ \
+ "y", "psr", "wim", "tbr", "pc", "npc", "fpsr", "cpsr" }
+
+/* Register numbers of various important registers.
+ Note that some of these values are "real" register numbers,
+ and correspond to the general registers of the machine,
+ and some are "phony" register numbers which are too large
+ to be actual register numbers as far as the user is concerned
+ but do serve to get the desired values when passed to read_register. */
+
+#define G0_REGNUM 0 /* %g0 */
+#define G1_REGNUM 1 /* %g1 */
+#define O0_REGNUM 8 /* %o0 */
+#define SP_REGNUM 14 /* Contains address of top of stack, \
+ which is also the bottom of the frame. */
+#define RP_REGNUM 15 /* Contains return address value, *before* \
+ any windows get switched. */
+#define O7_REGNUM 15 /* Last local reg not saved on stack frame */
+#define L0_REGNUM 16 /* First local reg that's saved on stack frame
+ rather than in machine registers */
+#define I0_REGNUM 24 /* %i0 */
+#define FP_REGNUM 30 /* Contains address of executing stack frame */
+#define I7_REGNUM 31 /* Last local reg saved on stack frame */
+#define FP0_REGNUM 32 /* Floating point register 0 */
+#define Y_REGNUM 64 /* Temp register for multiplication, etc. */
+#define PS_REGNUM 65 /* Contains processor status */
+#define PS_FLAG_CARRY 0x100000 /* Carry bit in PS */
+#define WIM_REGNUM 66 /* Window Invalid Mask (not really supported) */
+#define TBR_REGNUM 67 /* Trap Base Register (not really supported) */
+#define PC_REGNUM 68 /* Contains program counter */
+#define NPC_REGNUM 69 /* Contains next PC */
+#define FPS_REGNUM 70 /* Floating point status register */
+#define CPS_REGNUM 71 /* Coprocessor status register */
+
+/* Total amount of space needed to store our copies of the machine's
+ register state, the array `registers'. On the sparc, `registers'
+ contains the ins and locals, even though they are saved on the
+ stack rather than with the other registers, and this causes hair
+ and confusion in places like pop_frame. It might be
+ better to remove the ins and locals from `registers', make sure
+ that get_saved_register can get them from the stack (even in the
+ innermost frame), and make this the way to access them. For the
+ frame pointer we would do that via TARGET_READ_FP. On the other hand,
+ that is likely to be confusing or worse for flat frames. */
+
+#define REGISTER_BYTES (32*4+32*4+8*4)
+
+/* Index within `registers' of the first byte of the space for
+ register N. */
+/* ?? */
+#define REGISTER_BYTE(N) ((N)*4)
+
+/* We need to override GET_SAVED_REGISTER so that we can deal with the way
+ outs change into ins in different frames. HAVE_REGISTER_WINDOWS can't
+ deal with this case and also handle flat frames at the same time. */
+
+#define GET_SAVED_REGISTER 1
+
+/* Number of bytes of storage in the actual machine representation
+ for register N. */
+
+/* On the SPARC, all regs are 4 bytes. */
+
+#define REGISTER_RAW_SIZE(N) (4)
+
+/* Number of bytes of storage in the program's representation
+ for register N. */
+
+/* On the SPARC, all regs are 4 bytes. */
+
+#define REGISTER_VIRTUAL_SIZE(N) (4)
+
+/* Largest value REGISTER_RAW_SIZE can have. */
+
+#define MAX_REGISTER_RAW_SIZE 8
+
+/* Largest value REGISTER_VIRTUAL_SIZE can have. */
+
+#define MAX_REGISTER_VIRTUAL_SIZE 8
+
+/* Return the GDB type object for the "standard" data type
+ of data in register N. */
+
+#define REGISTER_VIRTUAL_TYPE(N) \
+ ((N) < 32 ? builtin_type_int : (N) < 64 ? builtin_type_float : \
+ builtin_type_int)
+
+/* Writing to %g0 is a noop (not an error or exception or anything like
+ that, however). */
+
+#define CANNOT_STORE_REGISTER(regno) ((regno) == G0_REGNUM)
+
+/* Store the address of the place in which to copy the structure the
+ subroutine will return. This is called from call_function_by_hand.
+ The ultimate mystery is, tho, what is the value "16"? */
+
+#define STORE_STRUCT_RETURN(ADDR, SP) \
+ { char val[4]; \
+ store_unsigned_integer (val, 4, (ADDR)); \
+ write_memory ((SP)+(16*4), val, 4); }
+
+/* Extract from an array REGBUF containing the (raw) register state
+ a function return value of type TYPE, and copy that, in virtual format,
+ into VALBUF. */
+
+#define EXTRACT_RETURN_VALUE(TYPE,REGBUF,VALBUF) \
+ sparc_extract_return_value(TYPE, REGBUF, VALBUF)
+extern void
+sparc_extract_return_value PARAMS ((struct type *, char [], char *));
+
+/* Write into appropriate registers a function return value
+ of type TYPE, given in virtual format. */
+#define STORE_RETURN_VALUE(TYPE,VALBUF) \
+ sparc_store_return_value(TYPE, VALBUF)
+extern void sparc_store_return_value PARAMS ((struct type *, char *));
+
+/* 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) \
+ (sparc_extract_struct_value_address (REGBUF))
+
+extern CORE_ADDR
+sparc_extract_struct_value_address PARAMS ((char [REGISTER_BYTES]));
+
+
+/* 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. */
+
+/* In the case of the Sun 4, the frame-chain's nominal address
+ is held in the frame pointer register.
+
+ On the Sun4, the frame (in %fp) is %sp for the previous frame.
+ From the previous frame's %sp, we can find the previous frame's
+ %fp: it is in the save area just above the previous frame's %sp.
+
+ If we are setting up an arbitrary frame, we'll need to know where
+ it ends. Hence the following. This part of the frame cache
+ structure should be checked before it is assumed that this frame's
+ bottom is in the stack pointer.
+
+ If there isn't a frame below this one, the bottom of this frame is
+ in the stack pointer.
+
+ If there is a frame below this one, and the frame pointers are
+ identical, it's a leaf frame and the bottoms are the same also.
+
+ Otherwise the bottom of this frame is the top of the next frame.
+
+ The bottom field is misnamed, since it might imply that memory from
+ bottom to frame contains this frame. That need not be true if
+ stack frames are allocated in different segments (e.g. some on a
+ stack, some on a heap in the data segment).
+
+ GCC 2.6 and later can generate ``flat register window'' code that
+ makes frames by explicitly saving those registers that need to be
+ saved. %i7 is used as the frame pointer, and the frame is laid out so
+ that flat and non-flat calls can be intermixed freely within a
+ program. Unfortunately for GDB, this means it must detect and record
+ the flatness of frames.
+
+ Since the prologue in a flat frame also tells us where fp and pc
+ have been stashed (the frame is of variable size, so their location
+ is not fixed), it's convenient to record them in the frame info. */
+
+#define EXTRA_FRAME_INFO \
+ CORE_ADDR bottom; \
+ int in_prologue; \
+ int flat; \
+ /* Following fields only relevant for flat frames. */ \
+ CORE_ADDR pc_addr; \
+ CORE_ADDR fp_addr; \
+ /* Add this to ->frame to get the value of the stack pointer at the */ \
+ /* time of the register saves. */ \
+ int sp_offset;
+
+#define FRAME_INIT_SAVED_REGS(fp) /*no-op*/
+
+#define INIT_EXTRA_FRAME_INFO(fromleaf, fci) \
+ sparc_init_extra_frame_info (fromleaf, fci)
+extern void sparc_init_extra_frame_info PARAMS((int, struct frame_info *));
+
+#define PRINT_EXTRA_FRAME_INFO(fi) \
+ { \
+ if ((fi) && (fi)->flat) \
+ printf_filtered (" flat, pc saved at 0x%x, fp saved at 0x%x\n", \
+ (fi)->pc_addr, (fi)->fp_addr); \
+ }
+
+#define FRAME_CHAIN(thisframe) (sparc_frame_chain (thisframe))
+extern CORE_ADDR sparc_frame_chain PARAMS ((struct frame_info *));
+
+/* INIT_EXTRA_FRAME_INFO needs the PC to detect flat frames. */
+
+#define INIT_FRAME_PC(fromleaf, prev) /* nothing */
+#define INIT_FRAME_PC_FIRST(fromleaf, prev) \
+ (prev)->pc = ((fromleaf) ? SAVED_PC_AFTER_CALL ((prev)->next) : \
+ (prev)->next ? FRAME_SAVED_PC ((prev)->next) : read_pc ());
+
+/* Define other aspects of the stack frame. */
+
+/* A macro that tells us whether the function invocation represented
+ by FI does not have a frame on the stack associated with it. If it
+ does not, FRAMELESS is set to 1, else 0. */
+#define FRAMELESS_FUNCTION_INVOCATION(FI, FRAMELESS) \
+ (FRAMELESS) = frameless_look_for_prologue(FI)
+
+/* The location of I0 w.r.t SP. This is actually dependent on how the system's
+ window overflow/underflow routines are written. Most vendors save the L regs
+ followed by the I regs (at the higher address). Some vendors get it wrong.
+ */
+
+#define FRAME_SAVED_L0 0
+#define FRAME_SAVED_I0 (8 * REGISTER_RAW_SIZE (L0_REGNUM))
+
+/* Where is the PC for a specific frame */
+
+#define FRAME_SAVED_PC(FRAME) sparc_frame_saved_pc (FRAME)
+extern CORE_ADDR sparc_frame_saved_pc PARAMS ((struct frame_info *));
+
+/* If the argument is on the stack, it will be here. */
+#define FRAME_ARGS_ADDRESS(fi) ((fi)->frame)
+
+#define FRAME_STRUCT_ARGS_ADDRESS(fi) ((fi)->frame)
+
+#define FRAME_LOCALS_ADDRESS(fi) ((fi)->frame)
+
+/* Set VAL to the number of args passed to frame described by FI.
+ Can set VAL to -1, meaning no way to tell. */
+
+/* We can't tell how many args there are
+ now that the C compiler delays popping them. */
+#define FRAME_NUM_ARGS(val,fi) (val = -1)
+
+/* Return number of bytes at start of arglist that are not really args. */
+
+#define FRAME_ARGS_SKIP 68
+
+/* Things needed for making the inferior call functions. */
+/*
+ * First of all, let me give my opinion of what the DUMMY_FRAME
+ * actually looks like.
+ *
+ * | |
+ * | |
+ * + - - - - - - - - - - - - - - - - +<-- fp (level 0)
+ * | |
+ * | |
+ * | |
+ * | |
+ * | Frame of innermost program |
+ * | function |
+ * | |
+ * | |
+ * | |
+ * | |
+ * | |
+ * |---------------------------------|<-- sp (level 0), fp (c)
+ * | |
+ * DUMMY | fp0-31 |
+ * | |
+ * | ------ |<-- fp - 0x80
+ * FRAME | g0-7 |<-- fp - 0xa0
+ * | i0-7 |<-- fp - 0xc0
+ * | other |<-- fp - 0xe0
+ * | ? |
+ * | ? |
+ * |---------------------------------|<-- sp' = fp - 0x140
+ * | |
+ * xcution start | |
+ * sp' + 0x94 -->| CALL_DUMMY (x code) |
+ * | |
+ * | |
+ * |---------------------------------|<-- sp'' = fp - 0x200
+ * | align sp to 8 byte boundary |
+ * | ==> args to fn <== |
+ * Room for | |
+ * i & l's + agg | CALL_DUMMY_STACK_ADJUST = 0x0x44|
+ * |---------------------------------|<-- final sp (variable)
+ * | |
+ * | Where function called will |
+ * | build frame. |
+ * | |
+ * | |
+ *
+ * I understand everything in this picture except what the space
+ * between fp - 0xe0 and fp - 0x140 is used for. Oh, and I don't
+ * understand why there's a large chunk of CALL_DUMMY that never gets
+ * executed (its function is superceeded by PUSH_DUMMY_FRAME; they
+ * are designed to do the same thing).
+ *
+ * PUSH_DUMMY_FRAME saves the registers above sp' and pushes the
+ * register file stack down one.
+ *
+ * call_function then writes CALL_DUMMY, pushes the args onto the
+ * stack, and adjusts the stack pointer.
+ *
+ * run_stack_dummy then starts execution (in the middle of
+ * CALL_DUMMY, as directed by call_function).
+ */
+
+/* Push an empty stack frame, to record the current PC, etc. */
+
+#define PUSH_DUMMY_FRAME sparc_push_dummy_frame ()
+#define POP_FRAME sparc_pop_frame ()
+
+void sparc_push_dummy_frame PARAMS ((void)), sparc_pop_frame PARAMS ((void));
+
+#ifndef CALL_DUMMY
+/* This sequence of words is the instructions
+
+ 0: bc 10 00 01 mov %g1, %fp
+ 4: 9d e3 80 00 save %sp, %g0, %sp
+ 8: bc 10 00 02 mov %g2, %fp
+ c: be 10 00 03 mov %g3, %i7
+ 10: da 03 a0 58 ld [ %sp + 0x58 ], %o5
+ 14: d8 03 a0 54 ld [ %sp + 0x54 ], %o4
+ 18: d6 03 a0 50 ld [ %sp + 0x50 ], %o3
+ 1c: d4 03 a0 4c ld [ %sp + 0x4c ], %o2
+ 20: d2 03 a0 48 ld [ %sp + 0x48 ], %o1
+ 24: 40 00 00 00 call <fun>
+ 28: d0 03 a0 44 ld [ %sp + 0x44 ], %o0
+ 2c: 01 00 00 00 nop
+ 30: 91 d0 20 01 ta 1
+ 34: 01 00 00 00 nop
+
+ NOTES:
+ * the first four instructions are necessary only on the simulator.
+ * this is a multiple of 8 (not only 4) bytes.
+ * the `call' insn is a relative, not an absolute call.
+ * the `nop' at the end is needed to keep the trap from
+ clobbering things (if NPC pointed to garbage instead).
+*/
+
+#define CALL_DUMMY { 0xbc100001, 0x9de38000, 0xbc100002, 0xbe100003, \
+ 0xda03a058, 0xd803a054, 0xd603a050, 0xd403a04c, \
+ 0xd203a048, 0x40000000, 0xd003a044, 0x01000000, \
+ 0x91d02001, 0x01000000 }
+
+
+/* Size of the call dummy in bytes. */
+
+#define CALL_DUMMY_LENGTH 0x38
+
+/* Offset within call dummy of first instruction to execute. */
+
+#define CALL_DUMMY_START_OFFSET 0
+
+/* Offset within CALL_DUMMY of the 'call' instruction. */
+
+#define CALL_DUMMY_CALL_OFFSET (CALL_DUMMY_START_OFFSET + 0x24)
+
+/* Offset within CALL_DUMMY of the 'ta 1' instruction. */
+
+#define CALL_DUMMY_BREAKPOINT_OFFSET (CALL_DUMMY_START_OFFSET + 0x30)
+
+#define CALL_DUMMY_STACK_ADJUST 68
+
+#endif
+/* Insert the specified number of args and function address
+ into a call sequence of the above form stored at DUMMYNAME. */
+
+#define FIX_CALL_DUMMY(dummyname, pc, fun, nargs, args, type, gcc_p) \
+ sparc_fix_call_dummy (dummyname, pc, fun, type, gcc_p)
+void sparc_fix_call_dummy PARAMS ((char *dummy, CORE_ADDR pc, CORE_ADDR fun,
+ struct type *value_type, int using_gcc));
+
+/* The Sparc returns long doubles on the stack. */
+
+#define RETURN_VALUE_ON_STACK(TYPE) \
+ (TYPE_CODE(TYPE) == TYPE_CODE_FLT \
+ && TYPE_LENGTH(TYPE) > 8)
+
+/* Sparc has no reliable single step ptrace call */
+
+#define SOFTWARE_SINGLE_STEP_P 1
+extern void sparc_software_single_step PARAMS ((unsigned int, int));
+#define SOFTWARE_SINGLE_STEP(sig,bp_p) sparc_software_single_step (sig,bp_p)
+
+/* We need more arguments in a frame specification for the
+ "frame" or "info frame" command. */
+
+#define SETUP_ARBITRARY_FRAME(argc, argv) setup_arbitrary_frame (argc, argv)
+extern struct frame_info *setup_arbitrary_frame PARAMS ((int, CORE_ADDR *));
+
+/* To print every pair of float registers as a double, we use this hook.
+ We also print the condition code registers in a readable format
+ (FIXME: can expand this to all control regs). */
+
+#undef PRINT_REGISTER_HOOK
+#define PRINT_REGISTER_HOOK(regno) \
+ sparc_print_register_hook (regno)
+extern void sparc_print_register_hook PARAMS ((int regno));
+
+
+/* Optimization for storing registers to the inferior. The hook
+ DO_DEFERRED_STORES
+ actually executes any deferred stores. It is called any time
+ we are going to proceed the child, or read its registers.
+ The hook CLEAR_DEFERRED_STORES is called when we want to throw
+ away the inferior process, e.g. when it dies or we kill it.
+ FIXME, this does not handle remote debugging cleanly. */
+
+extern int deferred_stores;
+#define DO_DEFERRED_STORES \
+ if (deferred_stores) \
+ target_store_registers (-2);
+#define CLEAR_DEFERRED_STORES \
+ deferred_stores = 0;
+
+/* If the current gcc for for this target does not produce correct debugging
+ information for float parameters, both prototyped and unprototyped, then
+ define this macro. This forces gdb to always assume that floats are
+ passed as doubles and then converted in the callee. */
+
+#define COERCE_FLOAT_TO_DOUBLE 1
+
+/* Select the sparc disassembler */
+
+#define TM_PRINT_INSN_MACH bfd_mach_sparc
+
+/* Arguments smaller than an int must promoted to ints when synthesizing
+ function calls. */
+
+#define PUSH_ARGUMENTS(nargs, args, sp, struct_return, struct_addr) \
+ sp = sparc_push_arguments((nargs), (args), (sp), (struct_return), (struct_addr))
+extern CORE_ADDR
+sparc_push_arguments PARAMS ((int, struct value **, CORE_ADDR, int, CORE_ADDR));
diff --git a/gdb/config/sparc/tm-sparclet.h b/gdb/config/sparc/tm-sparclet.h
new file mode 100644
index 00000000000..bc430830b8b
--- /dev/null
+++ b/gdb/config/sparc/tm-sparclet.h
@@ -0,0 +1,132 @@
+/* Target machine definitions for GDB for an embedded SPARC.
+ Copyright 1996 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "sparc/tm-sparc.h"
+
+#define TARGET_SPARCLET 1
+
+/* Select the sparclet disassembler. Slightly different instruction set from
+ the V8 sparc. */
+
+#undef TM_PRINT_INSN_MACH
+#define TM_PRINT_INSN_MACH bfd_mach_sparc_sparclet
+
+/* overrides of tm-sparc.h */
+
+#undef TARGET_BYTE_ORDER
+#define TARGET_BYTE_ORDER_SELECTABLE
+
+/* Sequence of bytes for breakpoint instruction (ta 1). */
+#undef BREAKPOINT
+#define BIG_BREAKPOINT {0x91, 0xd0, 0x20, 0x01}
+#define LITTLE_BREAKPOINT {0x01, 0x20, 0xd0, 0x91}
+
+#undef NUM_REGS /* formerly "72" */
+/* WIN FP CPU CCP ASR AWR APSR */
+#define NUM_REGS (32 + 32 + 8 + 8 + 8/*+ 32 + 1*/)
+
+#undef REGISTER_BYTES /* formerly "(32*4 + 32*4 + 8*4)" */
+#define REGISTER_BYTES (32*4 + 32*4 + 8*4 + 8*4 + 8*4/* + 32*4 + 1*4*/)
+
+/* Initializer for an array of names of registers.
+ There should be NUM_REGS strings in this initializer. */
+/* Sparclet has no fp! */
+/* Compiler maps types for floats by number, so can't
+ change the numbers here. */
+
+#undef REGISTER_NAMES
+#define REGISTER_NAMES \
+{ "g0", "g1", "g2", "g3", "g4", "g5", "g6", "g7", \
+ "o0", "o1", "o2", "o3", "o4", "o5", "o6", "o7", \
+ "l0", "l1", "l2", "l3", "l4", "l5", "l6", "l7", \
+ "i0", "i1", "i2", "i3", "i4", "i5", "i6", "i7", \
+ \
+ "", "", "", "", "", "", "", "", /* no FPU regs */ \
+ "", "", "", "", "", "", "", "", \
+ "", "", "", "", "", "", "", "", \
+ "", "", "", "", "", "", "", "", \
+ /* no CPSR, FPSR */ \
+ "y", "psr", "wim", "tbr", "pc", "npc", "", "", \
+ \
+ "ccsr", "ccpr", "cccrcr", "ccor", "ccobr", "ccibr", "ccir", "", \
+ \
+ /* ASR15 ASR19 (don't display them) */ \
+ "asr1", "", "asr17", "asr18", "", "asr20", "asr21", "asr22", \
+/* \
+ "awr0", "awr1", "awr2", "awr3", "awr4", "awr5", "awr6", "awr7", \
+ "awr8", "awr9", "awr10", "awr11", "awr12", "awr13", "awr14", "awr15", \
+ "awr16", "awr17", "awr18", "awr19", "awr20", "awr21", "awr22", "awr23", \
+ "awr24", "awr25", "awr26", "awr27", "awr28", "awr29", "awr30", "awr31", \
+ "apsr", \
+ */ \
+}
+
+/* Remove FP dependant code which was defined in tm-sparc.h */
+#undef FP0_REGNUM /* Floating point register 0 */
+#undef FPS_REGNUM /* Floating point status register */
+#undef CPS_REGNUM /* Coprocessor status register */
+
+/* sparclet register numbers */
+#define CCSR_REGNUM 72
+
+#undef EXTRACT_RETURN_VALUE
+#define EXTRACT_RETURN_VALUE(TYPE,REGBUF,VALBUF) \
+ { \
+ memcpy ((VALBUF), \
+ (char *)(REGBUF) + REGISTER_RAW_SIZE (O0_REGNUM) * 8 + \
+ (TYPE_LENGTH(TYPE) >= REGISTER_RAW_SIZE (O0_REGNUM) \
+ ? 0 : REGISTER_RAW_SIZE (O0_REGNUM) - TYPE_LENGTH(TYPE)), \
+ TYPE_LENGTH(TYPE)); \
+ }
+#undef STORE_RETURN_VALUE
+#define STORE_RETURN_VALUE(TYPE,VALBUF) \
+ { \
+ /* Other values are returned in register %o0. */ \
+ write_register_bytes (REGISTER_BYTE (O0_REGNUM), (VALBUF), \
+ TYPE_LENGTH (TYPE)); \
+ }
+
+#undef PRINT_REGISTER_HOOK
+#define PRINT_REGISTER_HOOK(regno)
+
+/* Offsets into jmp_buf. Not defined by Sun, but at least documented in a
+ comment in <machine/setjmp.h>! */
+
+#define JB_ELEMENT_SIZE 4 /* Size of each element in jmp_buf */
+
+#define JB_ONSSTACK 0
+#define JB_SIGMASK 1
+#define JB_SP 2
+#define JB_PC 3
+#define JB_NPC 4
+#define JB_PSR 5
+#define JB_G1 6
+#define JB_O0 7
+#define JB_WBCNT 8
+
+/* Figure out where the longjmp will land. We expect that we have just entered
+ longjmp and haven't yet setup the stack frame, so the args are still in the
+ output regs. %o0 (O0_REGNUM) points at the jmp_buf structure from which we
+ extract the pc (JB_PC) that we will land at. The pc is copied into ADDR.
+ This routine returns true on success */
+
+extern int
+get_longjmp_target PARAMS ((CORE_ADDR *));
+
+#define GET_LONGJMP_TARGET(ADDR) get_longjmp_target(ADDR)
diff --git a/gdb/config/sparc/tm-sparclite.h b/gdb/config/sparc/tm-sparclite.h
new file mode 100644
index 00000000000..d841f89c356
--- /dev/null
+++ b/gdb/config/sparc/tm-sparclite.h
@@ -0,0 +1,98 @@
+/* Macro definitions for GDB for a Fujitsu SPARClite.
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define TARGET_SPARCLITE 1
+
+#include "sparc/tm-sparc.h"
+
+/* overrides of tm-sparc.h */
+
+#undef TARGET_BYTE_ORDER
+#define TARGET_BYTE_ORDER_SELECTABLE
+
+/* Select the sparclite disassembler. Slightly different instruction set from
+ the V8 sparc. */
+
+#undef TM_PRINT_INSN_MACH
+#define TM_PRINT_INSN_MACH bfd_mach_sparc_sparclite
+
+/* Amount PC must be decremented by after a hardware instruction breakpoint.
+ This is often the number of bytes in BREAKPOINT
+ but not always. */
+
+#define DECR_PC_AFTER_HW_BREAK 4
+
+#define FRAME_CHAIN_VALID(fp,fi) alternate_frame_chain_valid (fp, fi)
+
+#undef NUM_REGS
+#define NUM_REGS 80
+
+#undef REGISTER_BYTES
+#define REGISTER_BYTES (32*4+32*4+8*4+8*4)
+
+#undef REGISTER_NAMES
+#define REGISTER_NAMES \
+{ "g0", "g1", "g2", "g3", "g4", "g5", "g6", "g7", \
+ "o0", "o1", "o2", "o3", "o4", "o5", "sp", "o7", \
+ "l0", "l1", "l2", "l3", "l4", "l5", "l6", "l7", \
+ "i0", "i1", "i2", "i3", "i4", "i5", "fp", "i7", \
+ \
+ "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", \
+ "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", \
+ "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23", \
+ "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", \
+ \
+ "y", "psr", "wim", "tbr", "pc", "npc", "fpsr", "cpsr", \
+ "dia1", "dia2", "dda1", "dda2", "ddv1", "ddv2", "dcr", "dsr" }
+
+#define DIA1_REGNUM 72 /* debug instr address register 1 */
+#define DIA2_REGNUM 73 /* debug instr address register 2 */
+#define DDA1_REGNUM 74 /* debug data address register 1 */
+#define DDA2_REGNUM 75 /* debug data address register 2 */
+#define DDV1_REGNUM 76 /* debug data value register 1 */
+#define DDV2_REGNUM 77 /* debug data value register 2 */
+#define DCR_REGNUM 78 /* debug control register */
+#define DSR_REGNUM 79 /* debug status regsiter */
+
+#define TARGET_HW_BREAK_LIMIT 2
+#define TARGET_HW_WATCH_LIMIT 2
+
+/* Enable watchpoint macro's */
+
+#define TARGET_HAS_HARDWARE_WATCHPOINTS
+
+#define TARGET_CAN_USE_HARDWARE_WATCHPOINT(type, cnt, ot) \
+ sparclite_check_watch_resources (type, cnt, ot)
+
+/* When a hardware watchpoint fires off the PC will be left at the
+ instruction which caused the watchpoint. It will be necessary for
+ GDB to step over the watchpoint. ***
+
+#define STOPPED_BY_WATCHPOINT(W) \
+ ((W).kind == TARGET_WAITKIND_STOPPED \
+ && (W).value.sig == TARGET_SIGNAL_TRAP \
+ && ((int) read_register (IPSW_REGNUM) & 0x00100000))
+*/
+
+/* Use these macros for watchpoint insertion/deletion. */
+#define target_insert_watchpoint(addr, len, type) sparclite_insert_watchpoint (addr, len, type)
+#define target_remove_watchpoint(addr, len, type) sparclite_remove_watchpoint (addr, len, type)
+#define target_insert_hw_breakpoint(addr, len) sparclite_insert_hw_breakpoint (addr, len)
+#define target_remove_hw_breakpoint(addr, len) sparclite_remove_hw_breakpoint (addr, len)
+#define target_stopped_data_address() sparclite_stopped_data_address()
diff --git a/gdb/config/sparc/tm-sparclynx.h b/gdb/config/sparc/tm-sparclynx.h
new file mode 100644
index 00000000000..5a0d908c658
--- /dev/null
+++ b/gdb/config/sparc/tm-sparclynx.h
@@ -0,0 +1,36 @@
+/* Macro definitions for Sparc running under LynxOS.
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef TM_SPARCLYNX_H
+#define TM_SPARCLYNX_H
+
+#include "tm-lynx.h"
+
+/* Use generic Sparc definitions. */
+#include "sparc/tm-sparc.h"
+
+/* Lynx does this backwards from everybody else */
+
+#undef FRAME_SAVED_I0
+#undef FRAME_SAVED_L0
+
+#define FRAME_SAVED_I0 0
+#define FRAME_SAVED_L0 (8 * REGISTER_RAW_SIZE (I0_REGNUM))
+
+#endif /* TM_SPARCLYNX_H */
diff --git a/gdb/config/sparc/tm-spc-em.h b/gdb/config/sparc/tm-spc-em.h
new file mode 100644
index 00000000000..3a9b4572c53
--- /dev/null
+++ b/gdb/config/sparc/tm-spc-em.h
@@ -0,0 +1,46 @@
+/* Target machine definitions for GDB for an embedded SPARC.
+ Copyright 1989, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "sparc/tm-sparc.h"
+
+/* Offsets into jmp_buf. Not defined by Sun, but at least documented in a
+ comment in <machine/setjmp.h>! */
+
+#define JB_ELEMENT_SIZE 4 /* Size of each element in jmp_buf */
+
+#define JB_ONSSTACK 0
+#define JB_SIGMASK 1
+#define JB_SP 2
+#define JB_PC 3
+#define JB_NPC 4
+#define JB_PSR 5
+#define JB_G1 6
+#define JB_O0 7
+#define JB_WBCNT 8
+
+/* Figure out where the longjmp will land. We expect that we have just entered
+ longjmp and haven't yet setup the stack frame, so the args are still in the
+ output regs. %o0 (O0_REGNUM) points at the jmp_buf structure from which we
+ extract the pc (JB_PC) that we will land at. The pc is copied into ADDR.
+ This routine returns true on success */
+
+extern int
+get_longjmp_target PARAMS ((CORE_ADDR *));
+
+#define GET_LONGJMP_TARGET(ADDR) get_longjmp_target(ADDR)
diff --git a/gdb/config/sparc/tm-sun4os4.h b/gdb/config/sparc/tm-sun4os4.h
new file mode 100644
index 00000000000..985e18c45a9
--- /dev/null
+++ b/gdb/config/sparc/tm-sun4os4.h
@@ -0,0 +1,58 @@
+/* Macro definitions for GDB for a Sun 4 running sunos 4.
+ Copyright 1989, 1992, 1994, 1995 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "sparc/tm-sparc.h"
+#include "tm-sunos.h"
+
+/* Redefine SKIP_TRAMPOLINE_CODE to handle PIC compiled modules
+ in main executables. */
+
+#undef SKIP_TRAMPOLINE_CODE
+#define SKIP_TRAMPOLINE_CODE(pc) sunos4_skip_trampoline_code (pc)
+extern CORE_ADDR sunos4_skip_trampoline_code PARAMS ((CORE_ADDR));
+
+/* Offsets into jmp_buf. Not defined by Sun, but at least documented in a
+ comment in <machine/setjmp.h>! */
+
+#define JB_ELEMENT_SIZE 4 /* Size of each element in jmp_buf */
+
+#define JB_ONSSTACK 0
+#define JB_SIGMASK 1
+#define JB_SP 2
+#define JB_PC 3
+#define JB_NPC 4
+#define JB_PSR 5
+#define JB_G1 6
+#define JB_O0 7
+#define JB_WBCNT 8
+
+/* Figure out where the longjmp will land. We expect that we have just entered
+ longjmp and haven't yet setup the stack frame, so the args are still in the
+ output regs. %o0 (O0_REGNUM) points at the jmp_buf structure from which we
+ extract the pc (JB_PC) that we will land at. The pc is copied into ADDR.
+ This routine returns true on success */
+
+extern int
+get_longjmp_target PARAMS ((CORE_ADDR *));
+
+#define GET_LONGJMP_TARGET(ADDR) get_longjmp_target(ADDR)
+
+extern char *sunpro_static_transform_name PARAMS ((char *));
+#define STATIC_TRANSFORM_NAME(x) sunpro_static_transform_name (x)
+#define IS_STATIC_TRANSFORM_NAME(name) ((name)[0] == '$')
diff --git a/gdb/config/sparc/tm-sun4sol2.h b/gdb/config/sparc/tm-sun4sol2.h
new file mode 100644
index 00000000000..7bab6e6778a
--- /dev/null
+++ b/gdb/config/sparc/tm-sun4sol2.h
@@ -0,0 +1,94 @@
+/* Macro definitions for GDB for a Sun 4 running Solaris 2
+ Copyright 1989, 1992, 1993, 1994, 1995, 1997, 1998
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "sparc/tm-sparc.h"
+#include "tm-sysv4.h"
+
+/* There are two different signal handler trampolines in Solaris2. */
+#define IN_SIGTRAMP(pc, name) \
+ ((name) \
+ && (STREQ ("sigacthandler", name) || STREQ ("ucbsigvechandler", name)))
+
+/* The signal handler gets a pointer to an ucontext as third argument
+ if it is called from sigacthandler. This is the offset to the saved
+ PC within it. sparc_frame_saved_pc knows how to deal with
+ ucbsigvechandler. */
+#define SIGCONTEXT_PC_OFFSET 44
+
+#if 0 /* FIXME Setjmp/longjmp are not as well doc'd in SunOS 5.x yet */
+
+/* Offsets into jmp_buf. Not defined by Sun, but at least documented in a
+ comment in <machine/setjmp.h>! */
+
+#define JB_ELEMENT_SIZE 4 /* Size of each element in jmp_buf */
+
+#define JB_ONSSTACK 0
+#define JB_SIGMASK 1
+#define JB_SP 2
+#define JB_PC 3
+#define JB_NPC 4
+#define JB_PSR 5
+#define JB_G1 6
+#define JB_O0 7
+#define JB_WBCNT 8
+
+/* Figure out where the longjmp will land. We expect that we have just entered
+ longjmp and haven't yet setup the stack frame, so the args are still in the
+ output regs. %o0 (O0_REGNUM) points at the jmp_buf structure from which we
+ extract the pc (JB_PC) that we will land at. The pc is copied into ADDR.
+ This routine returns true on success */
+
+extern int
+get_longjmp_target PARAMS ((CORE_ADDR *));
+
+#define GET_LONGJMP_TARGET(ADDR) get_longjmp_target(ADDR)
+#endif /* 0 */
+
+/* The SunPRO compiler puts out 0 instead of the address in N_SO symbols,
+ and for SunPRO 3.0, N_FUN symbols too. */
+#define SOFUN_ADDRESS_MAYBE_MISSING
+
+extern char *sunpro_static_transform_name PARAMS ((char *));
+#define STATIC_TRANSFORM_NAME(x) sunpro_static_transform_name (x)
+#define IS_STATIC_TRANSFORM_NAME(name) ((name)[0] == '$')
+
+#define FAULTED_USE_SIGINFO
+
+/* Enable handling of shared libraries for a.out executables. */
+#define HANDLE_SVR4_EXEC_EMULATORS
+
+/* Macros to extract process id and thread id from a composite pid/tid */
+#define PIDGET(pid) ((pid) & 0xffff)
+#define TIDGET(pid) (((pid) >> 16) & 0xffff)
+
+/* Macro to extract carry from given regset. */
+#define PROCFS_GET_CARRY(regset) ((regset)[R_PSR] & PS_FLAG_CARRY)
+
+#ifdef HAVE_THREAD_DB_LIB
+
+extern char *solaris_pid_to_str PARAMS ((int pid));
+#define target_pid_to_str(PID) solaris_pid_to_str (PID)
+
+#else
+
+extern char *procfs_pid_to_str PARAMS ((int pid));
+#define target_pid_to_str(PID) procfs_pid_to_str (PID)
+
+#endif
diff --git a/gdb/config/sparc/tm-vxsparc.h b/gdb/config/sparc/tm-vxsparc.h
new file mode 100644
index 00000000000..66129432a54
--- /dev/null
+++ b/gdb/config/sparc/tm-vxsparc.h
@@ -0,0 +1,36 @@
+/* Target machine description for VxWorks sparc's, for GDB, the GNU debugger.
+ Copyright 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define GDBINIT_FILENAME ".vxgdbinit"
+
+#define DEFAULT_PROMPT "(vxgdb) "
+
+#include "sparc/tm-spc-em.h"
+
+/* FIXME: These are almost certainly wrong. */
+
+/* Number of registers in a ptrace_getregs call. */
+
+#define VX_NUM_REGS (NUM_REGS)
+
+/* Number of registers in a ptrace_getfpregs call. */
+
+/* #define VX_SIZE_FPREGS (don't know how many) */
+
diff --git a/gdb/config/sparc/vxsparc.mt b/gdb/config/sparc/vxsparc.mt
new file mode 100644
index 00000000000..9eadd17451d
--- /dev/null
+++ b/gdb/config/sparc/vxsparc.mt
@@ -0,0 +1,3 @@
+# Target: SPARC running VxWorks
+TDEPFILES= sparc-tdep.o remote-vx.o remote-vxsparc.o xdr_ld.o xdr_ptrace.o xdr_rdb.o
+TM_FILE= tm-vxsparc.h
diff --git a/gdb/config/sparc/xm-linux.h b/gdb/config/sparc/xm-linux.h
new file mode 100644
index 00000000000..7d68b63b73c
--- /dev/null
+++ b/gdb/config/sparc/xm-linux.h
@@ -0,0 +1,48 @@
+/* Macro definitions for running gdb on a Sparc running Linux.
+ Copyright (C) 1989, 1993, 1994, 1995, 1996, 1998
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef XM_SPARCLINUX_H
+#define XM_SPARCLINUX_H
+
+#include "sparc/xm-sparc.h"
+
+#define HAVE_TERMIOS
+/* 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 0x0
+
+#define U_REGS_OFFSET 0
+
+#define NEED_POSIX_SETPGID
+
+/* Need R_OK etc, but USG isn't defined. */
+#include <unistd.h>
+
+/* If you expect to use the mmalloc package to obtain mapped symbol files,
+ for now you have to specify some parameters that determine how gdb places
+ the mappings in it's address space. See the comments in map_to_address()
+ for details. This is expected to only be a short term solution. Yes it
+ is a kludge.
+ FIXME: Make this more automatic. */
+
+#define MMAP_BASE_ADDRESS 0xE0000000 /* First mapping here */
+#define MMAP_INCREMENT 0x01000000 /* Increment to next mapping */
+
+#endif /* _XM_SPARCLINUX_H */
diff --git a/gdb/config/sparc/xm-nbsd.h b/gdb/config/sparc/xm-nbsd.h
new file mode 100644
index 00000000000..95fe8464c64
--- /dev/null
+++ b/gdb/config/sparc/xm-nbsd.h
@@ -0,0 +1,21 @@
+/* Parameters for execution on a Sparc running NetBSD, for GDB.
+ Copyright 1994 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Get generic NetBSD host definitions. */
+#include "xm-nbsd.h"
diff --git a/gdb/config/sparc/xm-sparc.h b/gdb/config/sparc/xm-sparc.h
new file mode 100644
index 00000000000..06c247ea9c7
--- /dev/null
+++ b/gdb/config/sparc/xm-sparc.h
@@ -0,0 +1,22 @@
+/* Host definitions for a Sun 4, for GDB, the GNU debugger.
+ Copyright 1986, 1987, 1989, 1991, 1992, 1996
+ Free Software Foundation, Inc.
+ Contributed by Michael Tiemann (tiemann@mcc.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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define HOST_BYTE_ORDER BIG_ENDIAN
diff --git a/gdb/config/sparc/xm-sparclynx.h b/gdb/config/sparc/xm-sparclynx.h
new file mode 100644
index 00000000000..7e62628e4e1
--- /dev/null
+++ b/gdb/config/sparc/xm-sparclynx.h
@@ -0,0 +1,24 @@
+/* Host-dependent definitions for Sparc running LynxOS, for GDB.
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define HOST_BYTE_ORDER BIG_ENDIAN
+
+/* Get generic LynxOS host definitions. */
+
+#include "xm-lynx.h"
diff --git a/gdb/config/sparc/xm-sun4os4.h b/gdb/config/sparc/xm-sun4os4.h
new file mode 100644
index 00000000000..e50a2132f8a
--- /dev/null
+++ b/gdb/config/sparc/xm-sun4os4.h
@@ -0,0 +1,34 @@
+/* Macro definitions for running gdb on a Sun 4 running sunos 4.
+ Copyright (C) 1989, 1993, 1994, 1995, 1996
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "sparc/xm-sparc.h"
+
+#define FPU
+
+/* /usr/include/malloc.h is included by vx-share/xdr_ld, and might
+ declare these using char * not void *. The following should work with
+ acc, gcc, or /bin/cc. */
+
+#define MALLOC_INCOMPATIBLE
+#include <malloc.h>
+
+/* SunOS 4.x uses nonstandard "char *" as type of third argument to ptrace() */
+
+#define PTRACE_ARG3_TYPE char*
diff --git a/gdb/config/sparc/xm-sun4sol2.h b/gdb/config/sparc/xm-sun4sol2.h
new file mode 100644
index 00000000000..bc49ce418d4
--- /dev/null
+++ b/gdb/config/sparc/xm-sun4sol2.h
@@ -0,0 +1,49 @@
+/* Macro definitions for running gdb on a Sun 4 running Solaris 2.
+ Copyright 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Most of what we know is generic to SPARC hosts. */
+
+#include "sparc/xm-sparc.h"
+
+/* Pick up more stuff from the generic SVR4 host include file. */
+
+#include "xm-sysv4.h"
+
+/* gdb wants to use the prgregset_t interface rather than
+ the gregset_t interface, partly because that's what's
+ used in core-sol2.c */
+
+#define GDB_GREGSET_TYPE prgregset_t
+#define GDB_FPREGSET_TYPE prfpregset_t
+
+/* These are not currently used in SVR4 (but should be, FIXME!). */
+#undef DO_DEFERRED_STORES
+#undef CLEAR_DEFERRED_STORES
+
+/* May be needed, may be not? From Pace Willisson's port. FIXME. */
+#define NEED_POSIX_SETPGID
+
+/* solaris doesn't have siginterrupt, though it has sigaction; however,
+ in this case siginterrupt would just be setting the default. */
+#define NO_SIGINTERRUPT
+
+/* On sol2.7, <curses.h> emits a bunch of 'macro redefined'
+ warnings, which makes autoconf think curses.h doesn't
+ exist. Compensate fot that here. */
+#define HAVE_CURSES_H 1
diff --git a/gdb/config/tahoe/tahoe.mh b/gdb/config/tahoe/tahoe.mh
new file mode 100644
index 00000000000..0814c01d33a
--- /dev/null
+++ b/gdb/config/tahoe/tahoe.mh
@@ -0,0 +1,4 @@
+# Host: CCI or Harris Tahoe running BSD Unix
+
+XM_FILE= xm-tahoe.h
+XDEPFILES= infptrace.o inftarg.o fork-child.o corelow.o core-aout.o
diff --git a/gdb/config/tahoe/tahoe.mt b/gdb/config/tahoe/tahoe.mt
new file mode 100644
index 00000000000..b91a77e6b23
--- /dev/null
+++ b/gdb/config/tahoe/tahoe.mt
@@ -0,0 +1,3 @@
+# Target: CCI or Harris Tahoe running BSD Unix
+TDEPFILES= tahoe-tdep.o
+TM_FILE= tm-tahoe.h
diff --git a/gdb/config/tahoe/tm-tahoe.h b/gdb/config/tahoe/tm-tahoe.h
new file mode 100644
index 00000000000..a9df37411dd
--- /dev/null
+++ b/gdb/config/tahoe/tm-tahoe.h
@@ -0,0 +1,289 @@
+/* Definitions to make GDB target for a tahoe running 4.3-Reno.
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/*
+ * Ported by the State University of New York at Buffalo by the Distributed
+ * Computer Systems Lab, Department of Computer Science, 1991.
+ */
+
+#define TARGET_BYTE_ORDER BIG_ENDIAN
+#define BITS_BIG_ENDIAN 0
+
+/* Offset from address of function to start of its code.
+ Zero on most machines. */
+
+#define FUNCTION_START_OFFSET 2
+
+/* Advance PC across any function entry prologue instructions
+ to reach some "real" code. */
+
+#define SKIP_PROLOGUE(pc) \
+{ register int op = (unsigned char) read_memory_integer (pc, 1); \
+ if (op == 0x11) pc += 2; /* skip brb */ \
+ if (op == 0x13) pc += 3; /* skip brw */ \
+ if (op == 0x2c && \
+ ((unsigned char) read_memory_integer (pc+2, 1)) == 0x5e) \
+ pc += 3; /* skip subl2 */ \
+ if (op == 0xe9 && \
+ ((unsigned char) read_memory_integer (pc+1, 1)) == 0xae && \
+ ((unsigned char) read_memory_integer(pc+3, 1)) == 0x5e) \
+ pc += 4; /* skip movab */ \
+ if (op == 0xe9 && \
+ ((unsigned char) read_memory_integer (pc+1, 1)) == 0xce && \
+ ((unsigned char) read_memory_integer(pc+4, 1)) == 0x5e) \
+ pc += 5; /* skip movab */ \
+ if (op == 0xe9 && \
+ ((unsigned char) read_memory_integer (pc+1, 1)) == 0xee && \
+ ((unsigned char) read_memory_integer(pc+6, 1)) == 0x5e) \
+ pc += 7; /* skip movab */ \
+}
+
+/* Immediately after a function call, return the saved pc.
+ Can't always go through the frames for this because on some machines
+ the new frame is not set up until the new function executes
+ some instructions. */
+
+#define SAVED_PC_AFTER_CALL(frame) FRAME_SAVED_PC(frame)
+
+/* Wrong for cross-debugging. I don't know the real values. */
+#include <machine/param.h>
+#define TARGET_UPAGES UPAGES
+#define TARGET_NBPG NBPG
+
+/* Address of end of stack space. */
+
+#define STACK_END_ADDR (0xc0000000 - (TARGET_UPAGES * TARGET_NBPG))
+
+/* On BSD, sigtramp is in the u area. Can't check the exact
+ addresses because for cross-debugging we don't have target include
+ files around. This should be close enough. */
+#define IN_SIGTRAMP(pc, name) ((pc) >= STACK_END_ADDR && (pc < 0xc0000000))
+
+/* Stack grows downward. */
+
+#define INNER_THAN(lhs,rhs) ((lhs) < (rhs))
+
+/* Sequence of bytes for breakpoint instruction. */
+
+#define BREAKPOINT {0x30}
+
+/* Amount PC must be decremented by after a breakpoint.
+ This is often the number of bytes in BREAKPOINT
+ but not always. */
+
+#define DECR_PC_AFTER_BREAK 0
+
+/* Return 1 if P points to an invalid floating point value.
+ LEN is the length in bytes -- not relevant on the Tahoe. */
+
+#define INVALID_FLOAT(p, len) ((*(short *) p & 0xff80) == 0x8000)
+
+/* Say how long (ordinary) registers are. This is a piece of bogosity
+ used in push_word and a few other places; REGISTER_RAW_SIZE is the
+ real way to know how big a register is. */
+
+#define REGISTER_SIZE 4
+
+/* Number of machine registers */
+
+#define NUM_REGS 19
+
+/* Initializer for an array of names of registers.
+ There should be NUM_REGS strings in this initializer. */
+
+#define REGISTER_NAMES {"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "fp", "sp", "pc", "ps", "al", "ah"}
+
+#define FP_REGNUM 13 /* Contains address of executing stack frame */
+#define SP_REGNUM 14 /* Contains address of top of stack */
+#define PC_REGNUM 15 /* Contains program counter */
+#define PS_REGNUM 16 /* Contains processor status */
+
+#define AL_REGNUM 17 /* Contains accumulator */
+#define AH_REGNUM 18
+
+/* Total amount of space needed to store our copies of the machine's
+ register state, the array `registers'. */
+
+#define REGISTER_BYTES (19*4)
+
+/* Index within `registers' of the first byte of the space for
+ register N. */
+
+#define REGISTER_BYTE(N) ((N) * 4)
+
+/* Number of bytes of storage in the actual machine representation
+ for register N. On the tahoe, all regs are 4 bytes. */
+
+#define REGISTER_RAW_SIZE(N) 4
+
+/* Number of bytes of storage in the program's representation
+ for register N. On the tahoe, all regs are 4 bytes. */
+
+#define REGISTER_VIRTUAL_SIZE(N) 4
+
+/* Largest value REGISTER_RAW_SIZE can have. */
+
+#define MAX_REGISTER_RAW_SIZE 4
+
+/* Largest value REGISTER_VIRTUAL_SIZE can have. */
+
+#define MAX_REGISTER_VIRTUAL_SIZE 4
+
+/* Return the GDB type object for the "standard" data type
+ of data in register N. */
+
+#define REGISTER_VIRTUAL_TYPE(N) builtin_type_int
+
+/* Store the address of the place in which to copy the structure the
+ subroutine will return. This is called from call_function. */
+
+#define STORE_STRUCT_RETURN(ADDR, SP) \
+ { write_register (1, (ADDR)); }
+
+/* Extract from an array REGBUF containing the (raw) register state
+ a function return value of type TYPE, and copy that, in virtual format,
+ into VALBUF. */
+
+#define EXTRACT_RETURN_VALUE(TYPE,REGBUF,VALBUF) \
+ memcpy (VALBUF, REGBUF, 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. */
+
+/* In the case of the Tahoe, the frame's nominal address is the FP value,
+ and it points to the old FP */
+
+#define FRAME_CHAIN(thisframe) \
+ (!inside_entry_file ((thisframe)->pc) ? \
+ read_memory_integer ((thisframe)->frame, 4) :\
+ 0)
+
+/* Define other aspects of the stack frame. */
+
+/* Saved PC */
+
+#define FRAME_SAVED_PC(FRAME) (read_memory_integer ((FRAME)->frame - 8, 4))
+
+/* In most of GDB, getting the args address is too important to
+ just say "I don't know". */
+
+#define FRAME_ARGS_ADDRESS(fi) ((fi)->frame)
+
+/* Address to use as an anchor for finding local variables */
+
+#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 = ((0xffff & read_memory_integer(((fi)->frame-4),4)) - 4) >> 2; }
+
+/* Return number of bytes at start of arglist that are not really args. */
+
+#define FRAME_ARGS_SKIP 0
+
+/* Put here the code to store, into a struct frame_saved_regs,
+ the addresses of the saved registers of frame described by FRAME_INFO.
+ This includes special registers such as pc and fp saved in special
+ ways in the stack frame. sp is even more special:
+ the address we return for it IS the sp for the next frame. */
+
+#define FRAME_FIND_SAVED_REGS(frame_info, frame_saved_regs) \
+{ register int regnum; \
+ register int rmask = read_memory_integer ((frame_info)->frame-4, 4) >> 16;\
+ register CORE_ADDR next_addr; \
+ memset (&frame_saved_regs, '\0', sizeof frame_saved_regs); \
+ next_addr = (frame_info)->frame - 8; \
+ for (regnum = 12; regnum >= 0; regnum--, rmask <<= 1) \
+ (frame_saved_regs).regs[regnum] = (rmask & 0x1000) ? (next_addr -= 4) : 0;\
+ (frame_saved_regs).regs[SP_REGNUM] = (frame_info)->frame + 4; \
+ (frame_saved_regs).regs[PC_REGNUM] = (frame_info)->frame - 8; \
+ (frame_saved_regs).regs[FP_REGNUM] = (frame_info)->frame; \
+}
+
+/* Things needed for making the inferior call functions. */
+
+/* Push an empty stack frame, to record the current PC, etc. */
+
+#define PUSH_DUMMY_FRAME \
+{ register CORE_ADDR sp = read_register (SP_REGNUM); \
+ register int regnum; \
+printf("PUSH_DUMMY_FRAME\n"); \
+ sp = push_word (sp, read_register (FP_REGNUM)); \
+ write_register (FP_REGNUM, sp); \
+ sp = push_word (sp, 0x1fff0004); /*SAVE MASK*/ \
+ sp = push_word (sp, read_register (PC_REGNUM)); \
+ for (regnum = 12; regnum >= 0; regnum--) \
+ sp = push_word (sp, read_register (regnum)); \
+ write_register (SP_REGNUM, sp); \
+}
+
+/* Discard from the stack the innermost frame, restoring all registers. */
+
+#define POP_FRAME \
+{ register CORE_ADDR fp = read_register (FP_REGNUM); \
+ register int regnum; \
+ register int regmask = read_memory_integer (fp-4, 4); \
+printf("POP_FRAME\n"); \
+ regmask >>= 16; \
+ write_register (SP_REGNUM, fp+4); \
+ write_register (PC_REGNUM, read_memory_integer(fp-8, 4)); \
+ write_register (FP_REGNUM, read_memory_integer(fp, 4)); \
+ fp -= 8; \
+ for (regnum = 12; regnum >= 0; regnum--, regmask <<= 1) \
+ if (regmask & 0x1000) \
+ write_register (regnum, read_memory_integer (fp-=4, 4)); \
+ flush_cached_frames (); \
+}
+
+/* This sequence of words is the instructions
+ calls #69, @#32323232
+ bpt
+ Note this is 8 bytes. */
+
+#define CALL_DUMMY {0xbf699f32, 0x32323230}
+
+/* Start execution at beginning of dummy */
+
+#define CALL_DUMMY_START_OFFSET 0
+
+/* Insert the specified number of args and function address
+ into a call sequence of the above form stored at DUMMYNAME. */
+
+#define FIX_CALL_DUMMY(dummyname, pc, fun, nargs, args, valtype, using_gcc) \
+{ int temp = (int) fun; \
+ *((char *) dummyname + 1) = nargs; \
+ memcpy((char *)dummyname+3,&temp,4); }
+
diff --git a/gdb/config/tahoe/xm-tahoe.h b/gdb/config/tahoe/xm-tahoe.h
new file mode 100644
index 00000000000..99af344c17c
--- /dev/null
+++ b/gdb/config/tahoe/xm-tahoe.h
@@ -0,0 +1,136 @@
+/* Definitions to make GDB hosted on a tahoe running 4.3-Reno
+ Copyright 1986, 1987, 1989, 1991, 1992 Free Software Foundation, Inc.
+ Contributed by the State University of New York at Buffalo, by the
+ Distributed Computer Systems Lab, Department of Computer Science, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Make sure the system include files define BIG_ENDIAN, UINT_MAX, const,
+ etc, rather than GDB's files. */
+#include <stdio.h>
+#include <sys/param.h>
+
+/* Host is big-endian */
+
+#define HOST_BYTE_ORDER BIG_ENDIAN
+
+/* This is the amount to subtract from u.u_ar0
+ to get the offset in the core file of the register values. */
+
+#define KERNEL_U_ADDR (0xc0000000 - (TARGET_UPAGES * TARGET_NBPG))
+
+#define REGISTER_U_ADDR(addr, blockend, regno) \
+{ addr = blockend - 100 + regno * 4; \
+ if (regno == PC_REGNUM) addr = blockend - 8; \
+ if (regno == PS_REGNUM) addr = blockend - 4; \
+ if (regno == FP_REGNUM) addr = blockend - 40; \
+ if (regno == SP_REGNUM) addr = blockend - 36; \
+ if (regno == AL_REGNUM) addr = blockend - 20; \
+ if (regno == AH_REGNUM) addr = blockend - 24;}
+
+/* Interface definitions for kernel debugger KDB. */
+
+/* Map machine fault codes into signal numbers.
+ First subtract 0, divide by 4, then index in a table.
+ Faults for which the entry in this table is 0
+ are not handled by KDB; the program's own trap handler
+ gets to handle then. */
+
+#define FAULT_CODE_ORIGIN 0
+#define FAULT_CODE_UNITS 4
+#define FAULT_TABLE \
+{ 0, SIGKILL, SIGSEGV, 0, 0, 0, 0, 0, \
+ 0, 0, SIGTRAP, SIGTRAP, 0, 0, 0, 0, \
+ 0, 0, 0, 0, 0, 0, 0, 0}
+
+/* Start running with a stack stretching from BEG to END.
+ BEG and END should be symbols meaningful to the assembler.
+ This is used only for kdb. */
+
+#define INIT_STACK(beg, end) \
+{ asm (".globl end"); \
+ asm ("movl $ end, sp"); \
+ asm ("clrl fp"); }
+
+/* Push the frame pointer register on the stack. */
+
+#define PUSH_FRAME_PTR \
+ asm ("pushl fp");
+
+/* Copy the top-of-stack to the frame pointer register. */
+
+#define POP_FRAME_PTR \
+ asm ("movl (sp), fp");
+
+/* After KDB is entered by a fault, push all registers
+ that GDB thinks about (all NUM_REGS of them),
+ so that they appear in order of ascending GDB register number.
+ The fault code will be on the stack beyond the last register. */
+
+#define PUSH_REGISTERS \
+{ asm ("pushl 8(sp)"); \
+ asm ("pushl 8(sp)"); \
+ asm ("pushal 0x41(sp)"); \
+ asm ("pushl r0" ); \
+ asm ("pushl r1" ); \
+ asm ("pushl r2" ); \
+ asm ("pushl r3" ); \
+ asm ("pushl r4" ); \
+ asm ("pushl r5" ); \
+ asm ("pushl r6" ); \
+ asm ("pushl r7" ); \
+ asm ("pushl r8" ); \
+ asm ("pushl r9" ); \
+ asm ("pushl r10" ); \
+ asm ("pushl r11" ); \
+ asm ("pushl r12" ); \
+ asm ("pushl fp" ); \
+ asm ("pushl sp" ); \
+ asm ("pushl pc" ); \
+ asm ("pushl ps" ); \
+ asm ("pushl aclo" ); \
+ asm ("pushl achi" ); \
+}
+
+/* Assuming the registers (including processor status) have been
+ pushed on the stack in order of ascending GDB register number,
+ restore them and return to the address in the saved PC register. */
+
+#define POP_REGISTERS \
+{ \
+ asm ("movl (sp)+, achi"); \
+ asm ("movl (sp)+, aclo"); \
+ asm ("movl (sp)+, ps"); \
+ asm ("movl (sp)+, pc"); \
+ asm ("movl (sp)+, sp"); \
+ asm ("movl (sp)+, fp"); \
+ asm ("movl (sp)+, r12"); \
+ asm ("movl (sp)+, r11"); \
+ asm ("movl (sp)+, r10"); \
+ asm ("movl (sp)+, r9"); \
+ asm ("movl (sp)+, r8"); \
+ asm ("movl (sp)+, r7"); \
+ asm ("movl (sp)+, r6"); \
+ asm ("movl (sp)+, r5"); \
+ asm ("movl (sp)+, r4"); \
+ asm ("movl (sp)+, r3"); \
+ asm ("movl (sp)+, r2"); \
+ asm ("movl (sp)+, r1"); \
+ asm ("movl (sp)+, r0"); \
+ asm ("subl2 $8,(sp)"); \
+ asm ("movl (sp),sp"); \
+ asm ("rei"); }
diff --git a/gdb/config/tm-lynx.h b/gdb/config/tm-lynx.h
new file mode 100644
index 00000000000..7107241420c
--- /dev/null
+++ b/gdb/config/tm-lynx.h
@@ -0,0 +1,34 @@
+/* Macro definitions for LynxOS targets.
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef TM_LYNX_H
+#define TM_LYNX_H
+
+/* Override number of expected traps from sysv. */
+#define START_INFERIOR_TRAPS_EXPECTED 2
+
+#include "coff-solib.h" /* COFF shared library support */
+
+/* Lynx's signal.h doesn't seem to have any macros for what signal numbers
+ the real-time events are. */
+#define REALTIME_LO 33
+/* One more than the last one. */
+#define REALTIME_HI 64
+
+#endif /* TM_LYNX_H */
diff --git a/gdb/config/tm-nbsd.h b/gdb/config/tm-nbsd.h
new file mode 100644
index 00000000000..e295d85ea2d
--- /dev/null
+++ b/gdb/config/tm-nbsd.h
@@ -0,0 +1,19 @@
+/* Target machine sub-description for NetBSD.
+ This is included by other tm-*.h files to specify NetBSD-specific stuff.
+ Copyright 1993, 1994 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
diff --git a/gdb/config/tm-sunos.h b/gdb/config/tm-sunos.h
new file mode 100644
index 00000000000..26ec3cff866
--- /dev/null
+++ b/gdb/config/tm-sunos.h
@@ -0,0 +1,31 @@
+/* Target machine sub-description for SunOS version 4.
+ This is included by other tm-*.h files to specify SunOS-specific stuff.
+ Copyright 1990, 1991, 1992, 1993, 1994 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "solib.h" /* Support for shared libraries. */
+
+/* Return non-zero if we are in a shared library trampoline code stub. */
+
+#define IN_SOLIB_CALL_TRAMPOLINE(pc, name) \
+ lookup_solib_trampoline_symbol_by_pc (pc)
+
+/* If PC is in a shared library trampoline code, return the PC
+ where the function itself actually starts. If not, return 0. */
+
+#define SKIP_TRAMPOLINE_CODE(pc) find_solib_trampoline_target (pc)
diff --git a/gdb/config/tm-sysv4.h b/gdb/config/tm-sysv4.h
new file mode 100644
index 00000000000..2c085410c09
--- /dev/null
+++ b/gdb/config/tm-sysv4.h
@@ -0,0 +1,45 @@
+/* Macro definitions for GDB on all SVR4 target systems.
+ Copyright 1991, 1992, 1993, 1994 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* For SVR4 shared libraries, each call to a library routine goes through
+ a small piece of trampoline code in the ".plt" section.
+ The horribly ugly wait_for_inferior() routine uses this macro to detect
+ when we have stepped into one of these fragments.
+ We do not use lookup_solib_trampoline_symbol_by_pc, because
+ we cannot always find the shared library trampoline symbols
+ (e.g. on Irix5). */
+
+#define IN_SOLIB_CALL_TRAMPOLINE(pc, name) in_plt_section((pc), (name))
+extern int in_plt_section PARAMS ((CORE_ADDR, char *));
+
+/* If PC is in a shared library trampoline code, return the PC
+ where the function itself actually starts. If not, return 0. */
+
+#define SKIP_TRAMPOLINE_CODE(pc) find_solib_trampoline_target (pc)
+
+/* It is unknown which, if any, SVR4 assemblers do not accept dollar signs
+ in identifiers. The default in G++ is to use dots instead, for all SVR4
+ systems, so we make that our default also. FIXME: There should be some
+ way to get G++ to tell us what CPLUS_MARKER it is using, perhaps by
+ stashing it in the debugging information as part of the name of an
+ invented symbol ("gcc_cplus_marker$" for example). */
+
+#undef CPLUS_MARKER
+#define CPLUS_MARKER '.'
diff --git a/gdb/config/v850/tm-v850.h b/gdb/config/v850/tm-v850.h
new file mode 100644
index 00000000000..14dd7f09ced
--- /dev/null
+++ b/gdb/config/v850/tm-v850.h
@@ -0,0 +1,174 @@
+/* Parameters for execution on an NEC V850 processor.
+ Copyright 1996
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define TARGET_BYTE_ORDER LITTLE_ENDIAN
+
+#define NUM_REGS 66
+
+#define REGISTER_NAMES \
+{ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", \
+ "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", \
+ "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", \
+ "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31", \
+ \
+ "eipc", "eipsw", "fepc", "fepsw", "ecr", "psw", "sr6", "sr7", \
+ "sr8", "sr9", "sr10", "sr11", "sr12", "sr13", "sr14", "sr15", \
+ "sr16", "sr17", "sr18", "sr19", "sr20", "sr21", "sr22", "sr23", \
+ "sr24", "sr25", "sr26", "sr27", "sr28", "sr29", "sr30", "sr31", \
+ \
+ "pc", "fp" }
+
+/* Initializer for an array of names of registers.
+ Entries beyond the first NUM_REGS are ignored. */
+
+extern char **v850_register_names;
+#define REGISTER_NAME(i) v850_register_names[i]
+
+
+#define REGISTER_BYTES (NUM_REGS * 4)
+
+#define REGISTER_SIZE 4
+#define MAX_REGISTER_RAW_SIZE 4
+
+#define R0_REGNUM 0
+#define R1_REGNUM 1
+#define SAVE1_START_REGNUM 2
+#define SAVE1_END_REGNUM 2
+#define SP_REGNUM 3
+#define ARG0_REGNUM 6
+#define ARGLAST_REGNUM 9
+#define V0_REGNUM 10
+#define V1_REGNUM 11
+#define R12_REGNUM 12
+#define SAVE2_START_REGNUM 20
+#define SAVE2_END_REGNUM 29
+#define EP_REGNUM 30
+#define SAVE3_START_REGNUM 31
+#define SAVE3_END_REGNUM 31
+#define RP_REGNUM 31
+#define SR0_REGNUM 32
+#define PS_REGNUM (SR0_REGNUM+5)
+#define CTBP_REGNUM (SR0_REGNUM+20)
+#define PC_REGNUM 64
+#define FP_REGNUM 65
+#define FP_RAW_REGNUM 29
+
+#define TARGET_READ_FP() read_register (FP_RAW_REGNUM)
+#define TARGET_WRITE_FP(VAL) write_register (FP_REGNUM, (VAL))
+
+#define REGISTER_VIRTUAL_TYPE(REG) builtin_type_int
+
+#define REGISTER_BYTE(REG) ((REG) * 4)
+#define REGISTER_VIRTUAL_SIZE(REG) 4
+#define REGISTER_RAW_SIZE(REG) 4
+
+#define MAX_REGISTER_VIRTUAL_SIZE 4
+
+#define BREAKPOINT {0x40, 0xF8} /* little-ended */
+
+#define FUNCTION_START_OFFSET 0
+
+#define DECR_PC_AFTER_BREAK 0
+
+#define INNER_THAN(lhs,rhs) ((lhs) < (rhs))
+
+#define SAVED_PC_AFTER_CALL(fi) read_register (RP_REGNUM)
+
+#ifdef __STDC__
+struct frame_info;
+struct frame_saved_regs;
+struct type;
+struct value;
+#endif
+
+#define EXTRA_FRAME_INFO struct frame_saved_regs fsr;
+
+extern void v850_init_extra_frame_info PARAMS ((struct frame_info *fi));
+#define INIT_EXTRA_FRAME_INFO(fromleaf, fi) v850_init_extra_frame_info (fi)
+#define INIT_FRAME_PC /* Not necessary */
+
+extern void v850_frame_find_saved_regs PARAMS ((struct frame_info *fi, struct frame_saved_regs *regaddr));
+#define FRAME_FIND_SAVED_REGS(fi, regaddr) regaddr = fi->fsr
+
+extern CORE_ADDR v850_frame_chain PARAMS ((struct frame_info *fi));
+#define FRAME_CHAIN(fi) v850_frame_chain (fi)
+#define FRAME_CHAIN_VALID(FP, FI) generic_frame_chain_valid (FP, FI)
+
+extern CORE_ADDR v850_find_callers_reg PARAMS ((struct frame_info *fi, int regnum));
+extern CORE_ADDR v850_frame_saved_pc PARAMS ((struct frame_info *));
+#define FRAME_SAVED_PC(FI) (v850_frame_saved_pc (FI))
+
+#define EXTRACT_RETURN_VALUE(TYPE, REGBUF, VALBUF) \
+ memcpy (VALBUF, REGBUF + REGISTER_BYTE (V0_REGNUM), TYPE_LENGTH (TYPE))
+
+#define EXTRACT_STRUCT_VALUE_ADDRESS(REGBUF) \
+ extract_address (REGBUF + REGISTER_BYTE (V0_REGNUM), \
+ REGISTER_RAW_SIZE (V0_REGNUM))
+
+#define STORE_RETURN_VALUE(TYPE, VALBUF) \
+ write_register_bytes(REGISTER_BYTE (V0_REGNUM), VALBUF, TYPE_LENGTH (TYPE));
+
+extern CORE_ADDR v850_skip_prologue PARAMS ((CORE_ADDR pc));
+#define SKIP_PROLOGUE(pc) pc = v850_skip_prologue (pc)
+
+#define FRAME_ARGS_SKIP 0
+
+#define FRAME_ARGS_ADDRESS(fi) ((fi)->frame)
+#define FRAME_LOCALS_ADDRESS(fi) ((fi)->frame)
+#define FRAME_NUM_ARGS(val, fi) ((val) = -1)
+
+extern void v850_pop_frame PARAMS ((struct frame_info *frame));
+#define POP_FRAME v850_pop_frame (get_current_frame ())
+
+#define USE_GENERIC_DUMMY_FRAMES
+#define CALL_DUMMY {0}
+#define CALL_DUMMY_START_OFFSET (0)
+#define CALL_DUMMY_BREAKPOINT_OFFSET (0)
+#define CALL_DUMMY_LOCATION AT_ENTRY_POINT
+#define FIX_CALL_DUMMY(DUMMY, START, FUNADDR, NARGS, ARGS, TYPE, GCCP)
+#define CALL_DUMMY_ADDRESS() entry_point_address ()
+extern CORE_ADDR v850_push_return_address PARAMS ((CORE_ADDR, CORE_ADDR));
+#define PUSH_RETURN_ADDRESS(PC, SP) v850_push_return_address (PC, SP)
+
+
+#define PUSH_DUMMY_FRAME generic_push_dummy_frame ()
+
+extern CORE_ADDR
+v850_push_arguments PARAMS ((int nargs, struct value **args, CORE_ADDR sp,
+ unsigned char struct_return,
+ CORE_ADDR struct_addr));
+#define PUSH_ARGUMENTS(NARGS, ARGS, SP, STRUCT_RETURN, STRUCT_ADDR) \
+ (SP) = v850_push_arguments (NARGS, ARGS, SP, STRUCT_RETURN, STRUCT_ADDR)
+
+#define STORE_STRUCT_RETURN(STRUCT_ADDR, SP)
+
+
+#define PC_IN_CALL_DUMMY(PC, SP, FP) generic_pc_in_call_dummy (PC, SP)
+
+extern use_struct_convention_fn v850_use_struct_convention;
+#define USE_STRUCT_CONVENTION(GCC_P, TYPE) v850_use_struct_convention (GCC_P, TYPE);
+
+/* override the default get_saved_register function with
+ one that takes account of generic CALL_DUMMY frames */
+#define GET_SAVED_REGISTER
+
+/* Define this for Wingdb */
+
+#define TARGET_V850
diff --git a/gdb/config/v850/v850.mt b/gdb/config/v850/v850.mt
new file mode 100644
index 00000000000..848bc8d043b
--- /dev/null
+++ b/gdb/config/v850/v850.mt
@@ -0,0 +1,5 @@
+# Target: NEC V850 processor
+TDEPFILES= v850-tdep.o
+TM_FILE= tm-v850.h
+SIM_OBS = remote-sim.o
+SIM = ../sim/v850/libsim.a
diff --git a/gdb/config/vax/nm-vax.h b/gdb/config/vax/nm-vax.h
new file mode 100644
index 00000000000..11f7dc9f64f
--- /dev/null
+++ b/gdb/config/vax/nm-vax.h
@@ -0,0 +1,28 @@
+/* Common definitions for GDB native support on Vaxen under 4.2bsd and Ultrix.
+ Copyright (C) 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define REGISTER_U_ADDR(addr, blockend, regno) \
+{ addr = blockend - 0110 + regno * 4; \
+ if (regno == PC_REGNUM) addr = blockend - 8; \
+ if (regno == PS_REGNUM) addr = blockend - 4; \
+ if (regno == FP_REGNUM) addr = blockend - 0120; \
+ if (regno == AP_REGNUM) addr = blockend - 0124; \
+ if (regno == SP_REGNUM) addr = blockend - 20; }
+
+
diff --git a/gdb/config/vax/tm-vax.h b/gdb/config/vax/tm-vax.h
new file mode 100644
index 00000000000..ad10fb7de3f
--- /dev/null
+++ b/gdb/config/vax/tm-vax.h
@@ -0,0 +1,330 @@
+/* Definitions to make GDB run on a vax under 4.2bsd.
+ Copyright 1986, 1987, 1989, 1991, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+
+#define TARGET_BYTE_ORDER LITTLE_ENDIAN
+
+/* Offset from address of function to start of its code.
+ Zero on most machines. */
+
+#define FUNCTION_START_OFFSET 2
+
+/* Advance PC across any function entry prologue instructions
+ to reach some "real" code. */
+
+#define SKIP_PROLOGUE(pc) \
+{ register int op = (unsigned char) read_memory_integer (pc, 1); \
+ if (op == 0x11) pc += 2; /* skip brb */ \
+ if (op == 0x31) pc += 3; /* skip brw */ \
+ if (op == 0xC2 && \
+ ((unsigned char) read_memory_integer (pc+2, 1)) == 0x5E) \
+ pc += 3; /* skip subl2 */ \
+ if (op == 0x9E && \
+ ((unsigned char) read_memory_integer (pc+1, 1)) == 0xAE && \
+ ((unsigned char) read_memory_integer(pc+3, 1)) == 0x5E) \
+ pc += 4; /* skip movab */ \
+ if (op == 0x9E && \
+ ((unsigned char) read_memory_integer (pc+1, 1)) == 0xCE && \
+ ((unsigned char) read_memory_integer(pc+4, 1)) == 0x5E) \
+ pc += 5; /* skip movab */ \
+ if (op == 0x9E && \
+ ((unsigned char) read_memory_integer (pc+1, 1)) == 0xEE && \
+ ((unsigned char) read_memory_integer(pc+6, 1)) == 0x5E) \
+ pc += 7; /* skip movab */ \
+}
+
+/* Immediately after a function call, return the saved pc.
+ Can't always go through the frames for this because on some machines
+ the new frame is not set up until the new function executes
+ some instructions. */
+
+#define SAVED_PC_AFTER_CALL(frame) FRAME_SAVED_PC(frame)
+
+#define TARGET_UPAGES 14
+#define TARGET_NBPG 512
+#define STACK_END_ADDR (0x80000000 - (TARGET_UPAGES * TARGET_NBPG))
+
+/* On the VAX, sigtramp is in the u area. Can't check the exact
+ addresses because for cross-debugging we don't have VAX include
+ files around. This should be close enough. */
+#define SIGTRAMP_START(pc) STACK_END_ADDR
+#define SIGTRAMP_END(pc) 0x80000000
+
+/* Stack grows downward. */
+
+#define INNER_THAN(lhs,rhs) ((lhs) < (rhs))
+
+/* Sequence of bytes for breakpoint instruction. */
+
+#define BREAKPOINT {3}
+
+/* Amount PC must be decremented by after a breakpoint.
+ This is often the number of bytes in BREAKPOINT
+ but not always. */
+
+#define DECR_PC_AFTER_BREAK 0
+
+/* Return 1 if P points to an invalid floating point value.
+ LEN is the length in bytes -- not relevant on the Vax. */
+
+#define INVALID_FLOAT(p, len) ((*(short *) p & 0xff80) == 0x8000)
+
+/* Say how long (ordinary) registers are. This is a piece of bogosity
+ used in push_word and a few other places; REGISTER_RAW_SIZE is the
+ real way to know how big a register is. */
+
+#define REGISTER_SIZE 4
+
+/* Number of machine registers */
+
+#define NUM_REGS 17
+
+/* Initializer for an array of names of registers.
+ There should be NUM_REGS strings in this initializer. */
+
+#define REGISTER_NAMES {"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "ap", "fp", "sp", "pc", "ps"}
+
+/* Register numbers of various important registers.
+ Note that some of these values are "real" register numbers,
+ and correspond to the general registers of the machine,
+ and some are "phony" register numbers which are too large
+ to be actual register numbers as far as the user is concerned
+ but do serve to get the desired values when passed to read_register. */
+
+#define AP_REGNUM 12
+#define FP_REGNUM 13 /* Contains address of executing stack frame */
+#define SP_REGNUM 14 /* Contains address of top of stack */
+#define PC_REGNUM 15 /* Contains program counter */
+#define PS_REGNUM 16 /* Contains processor status */
+
+/* Total amount of space needed to store our copies of the machine's
+ register state, the array `registers'. */
+#define REGISTER_BYTES (17*4)
+
+/* Index within `registers' of the first byte of the space for
+ register N. */
+
+#define REGISTER_BYTE(N) ((N) * 4)
+
+/* Number of bytes of storage in the actual machine representation
+ for register N. On the vax, all regs are 4 bytes. */
+
+#define REGISTER_RAW_SIZE(N) 4
+
+/* Number of bytes of storage in the program's representation
+ for register N. On the vax, all regs are 4 bytes. */
+
+#define REGISTER_VIRTUAL_SIZE(N) 4
+
+/* Largest value REGISTER_RAW_SIZE can have. */
+
+#define MAX_REGISTER_RAW_SIZE 4
+
+/* Largest value REGISTER_VIRTUAL_SIZE can have. */
+
+#define MAX_REGISTER_VIRTUAL_SIZE 4
+
+/* Return the GDB type object for the "standard" data type
+ of data in register N. */
+
+#define REGISTER_VIRTUAL_TYPE(N) builtin_type_int
+
+/* Store the address of the place in which to copy the structure the
+ subroutine will return. This is called from call_function. */
+
+#define STORE_STRUCT_RETURN(ADDR, SP) \
+ { write_register (1, (ADDR)); }
+
+/* Extract from an array REGBUF containing the (raw) register state
+ a function return value of type TYPE, and copy that, in virtual format,
+ into VALBUF. */
+
+#define EXTRACT_RETURN_VALUE(TYPE,REGBUF,VALBUF) \
+ memcpy (VALBUF, REGBUF, 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. */
+
+/* In the case of the Vax, the frame's nominal address is the FP value,
+ and 12 bytes later comes the saved previous FP value as a 4-byte word. */
+
+#define FRAME_CHAIN(thisframe) \
+ (!inside_entry_file ((thisframe)->pc) ? \
+ read_memory_integer ((thisframe)->frame + 12, 4) :\
+ 0)
+
+/* Define other aspects of the stack frame. */
+
+/* A macro that tells us whether the function invocation represented
+ by FI does not have a frame on the stack associated with it. If it
+ does not, FRAMELESS is set to 1, else 0. */
+/* On the vax, all functions have frames. */
+#define FRAMELESS_FUNCTION_INVOCATION(FI, FRAMELESS) {(FRAMELESS) = 0;}
+
+/* Saved Pc. Get it from sigcontext if within sigtramp. */
+
+/* Offset to saved PC in sigcontext, from <sys/signal.h>. */
+#define SIGCONTEXT_PC_OFFSET 12
+
+#define FRAME_SAVED_PC(FRAME) \
+ (((FRAME)->signal_handler_caller \
+ ? sigtramp_saved_pc (FRAME) \
+ : read_memory_integer ((FRAME)->frame + 16, 4)) \
+ )
+
+/* Cannot find the AP register value directly from the FP value. Must
+ find it saved in the frame called by this one, or in the AP
+ register for the innermost frame. However, there is no way to tell
+ the difference between the innermost frame and a frame for which we
+ just don't know the frame that it called (e.g. "info frame
+ 0x7ffec789"). For the sake of argument suppose that the stack is
+ somewhat trashed (which is one reason that "info frame" exists).
+ So return 0 (indicating we don't know the address of
+ the arglist) if we don't know what frame this frame calls. */
+#define FRAME_ARGS_ADDRESS_CORRECT(fi) \
+ (((fi)->next \
+ ? read_memory_integer ((fi)->next->frame + 8, 4) \
+ : /* read_register (AP_REGNUM) */ 0))
+
+/* In most of GDB, getting the args address is too important to
+ just say "I don't know". This is sometimes wrong for functions
+ that aren't on top of the stack, but c'est la vie. */
+#define FRAME_ARGS_ADDRESS(fi) \
+ (((fi)->next \
+ ? read_memory_integer ((fi)->next->frame + 8, 4) \
+ : read_register (AP_REGNUM) /* 0 */))
+
+#define FRAME_LOCALS_ADDRESS(fi) ((fi)->frame)
+
+/* Return number of args passed to a frame.
+ Can return -1, meaning no way to tell. */
+
+#define FRAME_NUM_ARGS(numargs, fi) \
+{ numargs = (0xff & read_memory_integer (FRAME_ARGS_ADDRESS (fi), 1)); }
+
+/* Return number of bytes at start of arglist that are not really args. */
+
+#define FRAME_ARGS_SKIP 4
+
+/* Put here the code to store, into a struct frame_saved_regs,
+ the addresses of the saved registers of frame described by FRAME_INFO.
+ This includes special registers such as pc and fp saved in special
+ ways in the stack frame. sp is even more special:
+ the address we return for it IS the sp for the next frame. */
+
+#define FRAME_FIND_SAVED_REGS(frame_info, frame_saved_regs) \
+{ register int regnum; \
+ register int regmask = read_memory_integer ((frame_info)->frame+4, 4) >> 16; \
+ register CORE_ADDR next_addr; \
+ memset (&frame_saved_regs, '\0', sizeof frame_saved_regs); \
+ next_addr = (frame_info)->frame + 16; \
+ /* Regmask's low bit is for register 0, \
+ which is the first one that would be pushed. */ \
+ for (regnum = 0; regnum < 12; regnum++, regmask >>= 1) \
+ (frame_saved_regs).regs[regnum] = (regmask & 1) ? (next_addr += 4) : 0; \
+ (frame_saved_regs).regs[SP_REGNUM] = next_addr + 4; \
+ if (read_memory_integer ((frame_info)->frame + 4, 4) & 0x20000000) \
+ (frame_saved_regs).regs[SP_REGNUM] += 4 + 4 * read_memory_integer (next_addr + 4, 4); \
+ (frame_saved_regs).regs[PC_REGNUM] = (frame_info)->frame + 16; \
+ (frame_saved_regs).regs[FP_REGNUM] = (frame_info)->frame + 12; \
+ (frame_saved_regs).regs[AP_REGNUM] = (frame_info)->frame + 8; \
+ (frame_saved_regs).regs[PS_REGNUM] = (frame_info)->frame + 4; \
+}
+
+/* Things needed for making the inferior call functions. */
+
+/* Push an empty stack frame, to record the current PC, etc. */
+
+#define PUSH_DUMMY_FRAME \
+{ register CORE_ADDR sp = read_register (SP_REGNUM);\
+ register int regnum; \
+ sp = push_word (sp, 0); /* arglist */ \
+ for (regnum = 11; regnum >= 0; regnum--) \
+ sp = push_word (sp, read_register (regnum)); \
+ sp = push_word (sp, read_register (PC_REGNUM)); \
+ sp = push_word (sp, read_register (FP_REGNUM)); \
+ sp = push_word (sp, read_register (AP_REGNUM)); \
+ sp = push_word (sp, (read_register (PS_REGNUM) & 0xffef) \
+ + 0x2fff0000); \
+ sp = push_word (sp, 0); \
+ write_register (SP_REGNUM, sp); \
+ write_register (FP_REGNUM, sp); \
+ write_register (AP_REGNUM, sp + 17 * sizeof (int)); }
+
+/* Discard from the stack the innermost frame, restoring all registers. */
+
+#define POP_FRAME \
+{ register CORE_ADDR fp = read_register (FP_REGNUM); \
+ register int regnum; \
+ register int regmask = read_memory_integer (fp + 4, 4); \
+ write_register (PS_REGNUM, \
+ (regmask & 0xffff) \
+ | (read_register (PS_REGNUM) & 0xffff0000)); \
+ write_register (PC_REGNUM, read_memory_integer (fp + 16, 4)); \
+ write_register (FP_REGNUM, read_memory_integer (fp + 12, 4)); \
+ write_register (AP_REGNUM, read_memory_integer (fp + 8, 4)); \
+ fp += 16; \
+ for (regnum = 0; regnum < 12; regnum++) \
+ if (regmask & (0x10000 << regnum)) \
+ write_register (regnum, read_memory_integer (fp += 4, 4)); \
+ fp = fp + 4 + ((regmask >> 30) & 3); \
+ if (regmask & 0x20000000) \
+ { regnum = read_memory_integer (fp, 4); \
+ fp += (regnum + 1) * 4; } \
+ write_register (SP_REGNUM, fp); \
+ flush_cached_frames (); \
+}
+
+/* This sequence of words is the instructions
+ calls #69, @#32323232
+ bpt
+ Note this is 8 bytes. */
+
+#define CALL_DUMMY {0x329f69fb, 0x03323232}
+
+#define CALL_DUMMY_START_OFFSET 0 /* Start execution at beginning of dummy */
+
+#define CALL_DUMMY_BREAKPOINT_OFFSET 7
+
+/* Insert the specified number of args and function address
+ into a call sequence of the above form stored at DUMMYNAME. */
+
+#define FIX_CALL_DUMMY(dummyname, pc, fun, nargs, args, type, gcc_p) \
+{ *((char *) dummyname + 1) = nargs; \
+ *(int *)((char *) dummyname + 3) = fun; }
+
+/* If vax pcc says CHAR or SHORT, it provides the correct address. */
+
+#define BELIEVE_PCC_PROMOTION 1
diff --git a/gdb/config/vax/vax.mt b/gdb/config/vax/vax.mt
new file mode 100644
index 00000000000..ebdf942b3d9
--- /dev/null
+++ b/gdb/config/vax/vax.mt
@@ -0,0 +1,3 @@
+# Target: DEC VAX running BSD or Ultrix
+TDEPFILES= vax-tdep.o
+TM_FILE= tm-vax.h
diff --git a/gdb/config/vax/vaxbsd.mh b/gdb/config/vax/vaxbsd.mh
new file mode 100644
index 00000000000..078687d29ad
--- /dev/null
+++ b/gdb/config/vax/vaxbsd.mh
@@ -0,0 +1,13 @@
+# Host: DEC VAX running BSD
+
+# The following types of /bin/cc failures have been observed:
+# 1. Something in readline.c which I have never seen
+# 2. ``"values.c", line 816: compiler error: schain botch''
+#msg /bin/cc has been known to fail on VAXen running BSD4.3
+#msg If this occurs, use gcc
+#msg (but see comments in Makefile.dist about compiling with gcc).
+
+XM_FILE= xm-vaxbsd.h
+XDEPFILES= infptrace.o inftarg.o fork-child.o corelow.o core-aout.o
+
+NAT_FILE= nm-vax.h
diff --git a/gdb/config/vax/vaxult.mh b/gdb/config/vax/vaxult.mh
new file mode 100644
index 00000000000..4afcbc85099
--- /dev/null
+++ b/gdb/config/vax/vaxult.mh
@@ -0,0 +1,7 @@
+# Host: DEC VAX running Ultrix
+
+XM_FILE= xm-vaxult.h
+XDEPFILES=
+
+NAT_FILE= nm-vax.h
+NATDEPFILES= infptrace.o inftarg.o fork-child.o corelow.o core-aout.o
diff --git a/gdb/config/vax/vaxult2.mh b/gdb/config/vax/vaxult2.mh
new file mode 100644
index 00000000000..dac73d63e0f
--- /dev/null
+++ b/gdb/config/vax/vaxult2.mh
@@ -0,0 +1,7 @@
+# Host: DEC VAX running Ultrix
+
+XM_FILE= xm-vaxult2.h
+XDEPFILES=
+
+NAT_FILE= nm-vax.h
+NATDEPFILES= infptrace.o inftarg.o fork-child.o corelow.o core-aout.o
diff --git a/gdb/config/vax/xm-vax.h b/gdb/config/vax/xm-vax.h
new file mode 100644
index 00000000000..fea11c715d5
--- /dev/null
+++ b/gdb/config/vax/xm-vax.h
@@ -0,0 +1,81 @@
+/* Common definitions to make GDB run on Vaxen under 4.2bsd and Ultrix.
+ Copyright (C) 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define HOST_BYTE_ORDER LITTLE_ENDIAN
+
+/* This is the amount to subtract from u.u_ar0
+ to get the offset in the core file of the register values. */
+
+#define KERNEL_U_ADDR (0x80000000 - (UPAGES * NBPG))
+
+/* Kernel is a bit tenacious about sharing text segments, disallowing bpts. */
+#define ONE_PROCESS_WRITETEXT
+
+/* Interface definitions for kernel debugger KDB. */
+
+/* Map machine fault codes into signal numbers.
+ First subtract 0, divide by 4, then index in a table.
+ Faults for which the entry in this table is 0
+ are not handled by KDB; the program's own trap handler
+ gets to handle then. */
+
+#define FAULT_CODE_ORIGIN 0
+#define FAULT_CODE_UNITS 4
+#define FAULT_TABLE \
+{ 0, SIGKILL, SIGSEGV, 0, 0, 0, 0, 0, \
+ 0, 0, SIGTRAP, SIGTRAP, 0, 0, 0, 0, \
+ 0, 0, 0, 0, 0, 0, 0, 0}
+
+/* Start running with a stack stretching from BEG to END.
+ BEG and END should be symbols meaningful to the assembler.
+ This is used only for kdb. */
+
+#define INIT_STACK(beg, end) \
+{ asm (".globl end"); \
+ asm ("movl $ end, sp"); \
+ asm ("clrl fp"); }
+
+/* Push the frame pointer register on the stack. */
+#define PUSH_FRAME_PTR \
+ asm ("pushl fp");
+
+/* Copy the top-of-stack to the frame pointer register. */
+#define POP_FRAME_PTR \
+ asm ("movl (sp), fp");
+
+/* After KDB is entered by a fault, push all registers
+ that GDB thinks about (all NUM_REGS of them),
+ so that they appear in order of ascending GDB register number.
+ The fault code will be on the stack beyond the last register. */
+
+#define PUSH_REGISTERS \
+{ asm ("pushl 8(sp)"); \
+ asm ("pushl 8(sp)"); \
+ asm ("pushal 0x14(sp)"); \
+ asm ("pushr $037777"); }
+
+/* Assuming the registers (including processor status) have been
+ pushed on the stack in order of ascending GDB register number,
+ restore them and return to the address in the saved PC register. */
+
+#define POP_REGISTERS \
+{ asm ("popr $037777"); \
+ asm ("subl2 $8,(sp)"); \
+ asm ("movl (sp),sp"); \
+ asm ("rei"); }
diff --git a/gdb/config/vax/xm-vaxbsd.h b/gdb/config/vax/xm-vaxbsd.h
new file mode 100644
index 00000000000..b42bd704681
--- /dev/null
+++ b/gdb/config/vax/xm-vaxbsd.h
@@ -0,0 +1,10 @@
+/* Definitions to make GDB run on a vax under BSD, 4.3 or 4.4. */
+
+/* We have to include these files now, so that GDB will not make
+ competing definitions in defs.h. */
+#include <machine/endian.h>
+/* This should exist on either 4.3 or 4.4. 4.3 doesn't have limits.h
+ or machine/limits.h. */
+#include <sys/param.h>
+
+#include "vax/xm-vax.h"
diff --git a/gdb/config/vax/xm-vaxult.h b/gdb/config/vax/xm-vaxult.h
new file mode 100644
index 00000000000..24c64370601
--- /dev/null
+++ b/gdb/config/vax/xm-vaxult.h
@@ -0,0 +1,12 @@
+/* Definitions to make GDB run on a vax under Ultrix. */
+
+#include "vax/xm-vax.h"
+extern char *strdup();
+
+/* This is required for Ultrix 3.1b, not for later versions. Ultrix
+ 3.1b can't just use xm-vaxult2.h because Ultrix 3.1b does define
+ FD_SET. Sure, we could have separate configurations for vaxult2,
+ vaxult3, and vaxult, but why bother? Defining the ptrace constants
+ in infptrace.c isn't going to do any harm; it's not like they are
+ going to change. */
+#define NO_PTRACE_H
diff --git a/gdb/config/vax/xm-vaxult2.h b/gdb/config/vax/xm-vaxult2.h
new file mode 100644
index 00000000000..d0d3d62c7aa
--- /dev/null
+++ b/gdb/config/vax/xm-vaxult2.h
@@ -0,0 +1,11 @@
+/* Definitions to make GDB run on a vax under Ultrix. */
+
+#include "vax/xm-vax.h"
+extern char *strdup();
+
+#define NO_PTRACE_H
+
+/* Old versions of ultrix have fd_set but not the FD_* macros. */
+
+#define FD_SET(bit,fdsetp) ((fdsetp)->fds_bits[(n) / 32] |= (1 << ((n) % 32)))
+#define FD_ZERO(fdsetp) memset (fdsetp, 0, sizeof (*fdsetp))
diff --git a/gdb/config/w65/tm-w65.h b/gdb/config/w65/tm-w65.h
new file mode 100644
index 00000000000..2e354bbb18f
--- /dev/null
+++ b/gdb/config/w65/tm-w65.h
@@ -0,0 +1,213 @@
+/* Parameters for execution on a WDC 65816 machine.
+ Copyright (C) 1995 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Contributed by Steve Chamberlain sac@cygnus.com */
+
+#define GDB_TARGET_IS_W65
+
+#define IEEE_FLOAT 1
+
+/* Define the bit, byte, and word ordering of the machine. */
+
+#define TARGET_BYTE_ORDER LITTLE_ENDIAN
+
+
+/* Offset from address of function to start of its code.
+ Zero on most machines. */
+
+#define FUNCTION_START_OFFSET 0
+
+/* Advance PC across any function entry prologue instructions
+ to reach some "real" code. */
+
+extern CORE_ADDR w65_skip_prologue ();
+
+#define SKIP_PROLOGUE(ip) \
+ {(ip) = w65_skip_prologue(ip);}
+
+
+/* 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.
+
+ The return address is the value saved in the PR register + 4 */
+
+#define SAVED_PC_AFTER_CALL(frame) \
+ saved_pc_after_call(frame)
+
+
+/* Stack grows downward. */
+
+#define INNER_THAN(lhs,rhs) ((lhs) < (rhs))
+
+/* Illegal instruction - used by the simulator for breakpoint
+ detection */
+
+#define BREAKPOINT {0xcb} /* WAI */
+
+/* If your kernel resets the pc after the trap happens you may need to
+ define this before including this file. */
+#define DECR_PC_AFTER_BREAK 0
+
+/* Return 1 if P points to an invalid floating point value. */
+
+#define INVALID_FLOAT(p, len) 0 /* Just a first guess; not checked */
+
+/* Say how long registers are. */
+/*#define REGISTER_TYPE int*/
+
+/* Say how much memory is needed to store a copy of the register set */
+#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) (((N) < 16) ? 2 : 4)
+
+#define REGISTER_VIRTUAL_SIZE(N) REGISTER_RAW_SIZE(N)
+
+/* 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
+
+/* Return the GDB type object for the "standard" data type
+ of data in register N. */
+
+#define REGISTER_VIRTUAL_TYPE(N) \
+ (REGISTER_VIRTUAL_SIZE(N) == 2 ? builtin_type_unsigned_short : builtin_type_unsigned_long)
+
+/* Initializer for an array of names of registers.
+ Entries beyond the first NUM_REGS are ignored. */
+
+#define REGISTER_NAMES \
+ {"r0","r1","r2", "r3", "r4", "r5", "r6", "r7", \
+ "r8","r9","r10","r11","r12","r13","r14","r15", \
+ "pc","a", "x", "y", "dbr","d", "s", "p", \
+ "ticks","cycles","insts"}
+
+/* Register numbers of various important registers.
+ Note that some of these values are "real" register numbers,
+ and correspond to the general registers of the machine,
+ and some are "phony" register numbers which are too large
+ to be actual register numbers as far as the user is concerned
+ but do serve to get the desired values when passed to read_register. */
+
+#define SP_REGNUM 22
+#define FP_REGNUM 15
+#define NUM_REGS 27
+#define PC_REGNUM 16
+#define P_REGNUM 23
+
+/* Store the address of the place in which to copy the structure the
+ subroutine will return. This is called from call_function.
+
+ We store structs through a pointer passed in R4 */
+
+#define STORE_STRUCT_RETURN(ADDR, SP) \
+ { write_register (4, (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) \
+ memcpy (VALBUF, (char *)(REGBUF), TYPE_LENGTH(TYPE))
+
+
+/* Write into appropriate registers a function return value
+ of type TYPE, given in virtual format.
+
+ Things always get returned in R4/R5 */
+
+#define STORE_RETURN_VALUE(TYPE,VALBUF) \
+ write_register_bytes (REGISTER_BYTE(4), 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) (*(CORE_ADDR *)(REGBUF))
+
+/* A macro that tells us whether the function invocation represented
+ by FI does not have a frame on the stack associated with it. If it
+ does not, FRAMELESS is set to 1, else 0. */
+
+#define FRAMELESS_FUNCTION_INVOCATION(FI, FRAMELESS) \
+ (FRAMELESS) = frameless_look_for_prologue(FI)
+
+#define FRAME_CHAIN(FRAME) w65_frame_chain(FRAME)
+#define FRAME_SAVED_PC(FRAME) (w65_frame_saved_pc(FRAME))
+#define FRAME_ARGS_ADDRESS(fi) (fi)->frame
+#define FRAME_LOCALS_ADDRESS(fi) (fi)->frame
+
+/* Set VAL to the number of args passed to frame described by FI.
+ Can set VAL to -1, meaning no way to tell. */
+
+/* We can't tell how many args there are */
+
+#define FRAME_NUM_ARGS(val,fi) (val = -1)
+
+/* Return number of bytes at start of arglist that are not really args. */
+
+#define FRAME_ARGS_SKIP 0
+
+/* Put here the code to store, into a struct frame_saved_regs,
+ the addresses of the saved registers of frame described by FRAME_INFO.
+ This includes special registers such as pc and fp saved in special
+ ways in the stack frame. sp is even more special:
+ the address we return for it IS the sp for the next frame. */
+
+#define FRAME_FIND_SAVED_REGS(frame_info, frame_saved_regs) \
+ frame_find_saved_regs(frame_info, &(frame_saved_regs))
+
+#define NAMES_HAVE_UNDERSCORE
+
+typedef unsigned short INSN_WORD;
+
+extern CORE_ADDR w65_addr_bits_remove PARAMS ((CORE_ADDR));
+#define ADDR_BITS_REMOVE(addr) w65_addr_bits_remove (addr)
+
+#define CALL_DUMMY_LENGTH 10
+
+/* Discard from the stack the innermost frame,
+ restoring all saved registers. */
+
+#define POP_FRAME pop_frame();
+
+
+#define NOP {0xea}
+
+#define REGISTER_SIZE 4
+
+#define PRINT_REGISTER_HOOK(regno) print_register_hook(regno)
+
+#define TARGET_INT_BIT 16
+#define TARGET_LONG_BIT 32
+#define TARGET_PTR_BIT 32
diff --git a/gdb/config/w65/w65.mt b/gdb/config/w65/w65.mt
new file mode 100644
index 00000000000..06d2325f761
--- /dev/null
+++ b/gdb/config/w65/w65.mt
@@ -0,0 +1,8 @@
+# Target: WDC 65816 with simulator
+TDEPFILES= w65-tdep.o
+TM_FILE= tm-w65.h
+
+SIM_OBS = remote-sim.o
+SIM = ../sim/w65/libsim.a
+
+
diff --git a/gdb/config/xm-aix4.h b/gdb/config/xm-aix4.h
new file mode 100644
index 00000000000..87062f77e5f
--- /dev/null
+++ b/gdb/config/xm-aix4.h
@@ -0,0 +1,99 @@
+/* Parameters for hosting on an PowerPC, for GDB, the GNU debugger.
+ Copyright 1995, 1998 Free Software Foundation, Inc.
+ Contributed by Cygnus Corporation.
+
+This file is part of GDB.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* The following text is taken from config/rs6000.mh:
+ * # The IBM version of /usr/include/rpc/rpc.h has a bug -- it says
+ * # `extern fd_set svc_fdset;' without ever defining the type fd_set.
+ * # Unfortunately this occurs in the vx-share code, which is not configured
+ * # like the rest of GDB (e.g. it doesn't include "defs.h").
+ * # We circumvent this bug by #define-ing fd_set here, but undefining it in
+ * # the xm-rs6000.h file before ordinary modules try to use it. FIXME, IBM!
+ * MH_CFLAGS='-Dfd_set=int'
+ * So, here we do the undefine...which has to occur before we include
+ * <sys/select.h> below.
+ */
+#undef fd_set
+
+#include <sys/select.h>
+
+/* Big end is at the low address */
+
+#define HOST_BYTE_ORDER BIG_ENDIAN
+
+/* At least as of AIX 3.2, we have termios. */
+#define HAVE_TERMIOS 1
+/* #define HAVE_TERMIO 1 */
+
+#define USG 1
+#define HAVE_SIGSETMASK 1
+
+#define FIVE_ARG_PTRACE
+
+/* AIX declares the mem functions differently than defs.h does. AIX is
+ right, but defs.h works on more old systems. For now, override it. */
+
+#define MEM_FNS_DECLARED 1
+
+/* This system requires that we open a terminal with O_NOCTTY for it to
+ not become our controlling terminal. */
+
+#define USE_O_NOCTTY
+
+/* Brain death inherited from PC's pervades. */
+#undef NULL
+#define NULL 0
+
+/* The IBM compiler requires this in order to properly compile alloca(). */
+#pragma alloca
+
+/* There is no vfork. */
+
+#define vfork fork
+
+char *termdef();
+
+/* Signal handler for SIGWINCH `window size changed'. */
+
+#define SIGWINCH_HANDLER aix_resizewindow
+extern void aix_resizewindow PARAMS ((int));
+
+/* `lines_per_page' and `chars_per_line' are local to utils.c. Rectify this. */
+
+#define SIGWINCH_HANDLER_BODY \
+ \
+/* Respond to SIGWINCH `window size changed' signal, and reset GDB's \
+ window settings appropriately. */ \
+ \
+void \
+aix_resizewindow (signo) \
+ int signo; \
+{ \
+ int fd = fileno (stdout); \
+ if (isatty (fd)) { \
+ int val; \
+ \
+ val = atoi (termdef (fd, 'l')); \
+ if (val > 0) \
+ lines_per_page = val; \
+ val = atoi (termdef (fd, 'c')); \
+ if (val > 0) \
+ chars_per_line = val; \
+ } \
+}
diff --git a/gdb/config/xm-lynx.h b/gdb/config/xm-lynx.h
new file mode 100644
index 00000000000..d73e2c10619
--- /dev/null
+++ b/gdb/config/xm-lynx.h
@@ -0,0 +1,20 @@
+/* Host-dependent definitions for any CPU running LynxOS.
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include <limits.h> /* for INT_MIN */
diff --git a/gdb/config/xm-mpw.h b/gdb/config/xm-mpw.h
new file mode 100644
index 00000000000..0c473d75572
--- /dev/null
+++ b/gdb/config/xm-mpw.h
@@ -0,0 +1,81 @@
+/* Macro definitions for running GDB on Apple Macintoshes.
+ Copyright (C) 1994, 1995 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "mpw.h"
+
+#include "fopen-bin.h"
+
+#include "spin.h"
+
+#define CANT_FORK
+
+/* Map these standard functions to versions that can do I/O in a console
+ window. */
+
+#define printf hacked_printf
+#define fprintf hacked_fprintf
+#define vprintf hacked_vfprintf
+#define fputs hacked_fputs
+#define fputc hacked_fputc
+#undef putc
+#define putc hacked_putc
+#define fflush hacked_fflush
+
+#define fgetc hacked_fgetc
+
+#define POSIX_UTIME
+
+/* No declaration of strdup in MPW's string.h, oddly enough. */
+
+char *strdup (char *s1);
+
+/* '.' indicates drivers on the Mac, so we need a different filename. */
+
+#define GDBINIT_FILENAME "_gdbinit"
+
+/* Commas are more common to separate dirnames in a path on Macs. */
+
+#define DIRNAME_SEPARATOR ','
+
+/* This is a real crufty hack. */
+
+#define HAVE_TERMIO
+
+/* Addons to the basic MPW-supported signal list. */
+
+#ifndef SIGQUIT
+#define SIGQUIT (1<<6)
+#endif
+#ifndef SIGHUP
+#define SIGHUP (1<<7)
+#endif
+
+/* If __STDC__ is on, then this definition will be missing. */
+
+#ifndef fileno
+#define fileno(p) (p)->_file
+#endif
+
+#ifndef R_OK
+#define R_OK 4
+#endif
+
+extern int StandAlone;
+
+extern int mac_app;
diff --git a/gdb/config/xm-nbsd.h b/gdb/config/xm-nbsd.h
new file mode 100644
index 00000000000..2332bb520a4
--- /dev/null
+++ b/gdb/config/xm-nbsd.h
@@ -0,0 +1,32 @@
+/* Host-dependent definitions for any CPU running NetBSD.
+ Copyright 1993, 1994, 1996 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* We have to include these files now, so that GDB will not make
+ competing definitions in defs.h. */
+#include <limits.h>
+
+#include <machine/endian.h>
+#if BYTE_ORDER == BIG_ENDIAN
+#define HOST_BYTE_ORDER BIG_ENDIAN
+#else
+#define HOST_BYTE_ORDER LITTLE_ENDIAN
+#endif
+
+/* NetBSD has termios facilities. */
+#define HAVE_TERMIOS
diff --git a/gdb/config/xm-sysv4.h b/gdb/config/xm-sysv4.h
new file mode 100644
index 00000000000..06215e64057
--- /dev/null
+++ b/gdb/config/xm-sysv4.h
@@ -0,0 +1,39 @@
+/* Definitions for running gdb on a host machine running any flavor of SVR4.
+ Copyright 1991, 1992 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* SVR4 has termios facilities. */
+
+#undef HAVE_TERMIO
+#define HAVE_TERMIOS
+
+/* SVR4 is a derivative of System V Release 3 (USG) */
+
+#define USG
+
+/* Use setpgid(0,0) to run inferior in a separate process group */
+
+#define NEED_POSIX_SETPGID
+
+/* SVR4 has sigsetjmp and siglongjmp */
+#define HAVE_SIGSETJMP
+
+/* We have to include these files now, so that GDB will not make
+ competing definitions in defs.h. */
+#include <limits.h>
diff --git a/gdb/config/z8k/tm-z8k.h b/gdb/config/z8k/tm-z8k.h
new file mode 100644
index 00000000000..babde906c98
--- /dev/null
+++ b/gdb/config/z8k/tm-z8k.h
@@ -0,0 +1,287 @@
+/* Parameters for execution on a z8000 series machine.
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define IEEE_FLOAT 1
+
+#undef TARGET_INT_BIT
+#undef TARGET_LONG_BIT
+#undef TARGET_SHORT_BIT
+#undef TARGET_PTR_BIT
+
+#define TARGET_SHORT_BIT 16
+#define TARGET_INT_BIT 16
+#define TARGET_LONG_BIT 32
+#define TARGET_PTR_BIT (BIG ? 32: 16)
+
+/* Define the bit, byte, and word ordering of the machine. */
+#define TARGET_BYTE_ORDER BIG_ENDIAN
+
+/* Offset from address of function to start of its code.
+ Zero on most machines. */
+
+#define FUNCTION_START_OFFSET 0
+
+/* Advance PC across any function entry prologue instructions
+ to reach some "real" code. */
+
+#define SKIP_PROLOGUE(ip) {(ip) = z8k_skip_prologue(ip);}
+extern CORE_ADDR mz8k_skip_prologue PARAMS ((CORE_ADDR ip));
+
+
+/* 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) saved_pc_after_call(frame)
+
+/* Stack grows downward. */
+
+#define INNER_THAN(lhs,rhs) ((lhs) < (rhs))
+
+/* Sequence of bytes for breakpoint instruction. */
+
+#define BREAKPOINT {0x36,0x00}
+
+/* If your kernel resets the pc after the trap happens you may need to
+ define this before including this file. */
+
+#define DECR_PC_AFTER_BREAK 0
+
+/* Say how long registers are. */
+
+#define REGISTER_TYPE unsigned int
+
+#define NUM_REGS 23 /* 16 registers + 1 ccr + 1 pc + 3 debug
+ regs + fake fp + fake sp*/
+#define REGISTER_BYTES (NUM_REGS *4)
+
+/* Index within `registers' of the first byte of the space for
+ register N. */
+
+#define REGISTER_BYTE(N) ((N)*4)
+
+/* Number of bytes of storage in the actual machine representation
+ for register N. On the z8k, all but the pc are 2 bytes, but we
+ keep them all as 4 bytes and trim them on I/O */
+
+
+#define REGISTER_RAW_SIZE(N) (((N) < 16)? 2:4)
+
+/* Number of bytes of storage in the program's representation
+ for register N. */
+
+#define REGISTER_VIRTUAL_SIZE(N) REGISTER_RAW_SIZE(N)
+
+/* Largest value REGISTER_RAW_SIZE can have. */
+
+#define MAX_REGISTER_RAW_SIZE 4
+
+/* Largest value REGISTER_VIRTUAL_SIZE can have. */
+
+#define MAX_REGISTER_VIRTUAL_SIZE 4
+
+/* Return the GDB type object for the "standard" data type
+ of data in register N. */
+
+#define REGISTER_VIRTUAL_TYPE(N) \
+ (REGISTER_VIRTUAL_SIZE(N) == 2? builtin_type_unsigned_int : builtin_type_long)
+
+/*#define INIT_FRAME_PC(x,y) init_frame_pc(x,y)*/
+/* Initializer for an array of names of registers.
+ Entries beyond the first NUM_REGS are ignored. */
+
+#define REGISTER_NAMES \
+ {"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", \
+ "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", \
+ "ccr", "pc", "cycles","insts","time","fp","sp"}
+
+/* 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 CCR_REGNUM 16 /* Contains processor status */
+#define PC_REGNUM 17 /* Contains program counter */
+#define CYCLES_REGNUM 18
+#define INSTS_REGNUM 19
+#define TIME_REGNUM 20
+#define FP_REGNUM 21 /* Contains fp, whatever memory model */
+#define SP_REGNUM 22 /* Conatins sp, whatever memory model */
+
+
+
+#define PTR_SIZE (BIG ? 4: 2)
+#define PTR_MASK (BIG ? 0xff00ffff : 0x0000ffff)
+
+/* 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) abort();
+
+/* Extract from an array REGBUF containing the (raw) register state
+ a function return value of type TYPE, and copy that, in virtual format,
+ into VALBUF. This is assuming that floating point values are returned
+ as doubles in d0/d1. */
+
+
+#define EXTRACT_RETURN_VALUE(TYPE,REGBUF,VALBUF) \
+ memcpy(VALBUF, REGBUF + REGISTER_BYTE(2), TYPE_LENGTH(TYPE));
+
+/* Write into appropriate registers a function return value
+ of type TYPE, given in virtual format. */
+
+#define STORE_RETURN_VALUE(TYPE,VALBUF) abort();
+
+/* 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) (*(CORE_ADDR *)(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.
+ In the case of the Z8000, the frame's nominal address
+ is the address of a ptr sized byte word containing the calling
+ frame's address. */
+
+#define FRAME_CHAIN(thisframe) frame_chain(thisframe);
+
+
+
+/* Define other aspects of the stack frame. */
+
+/* A macro that tells us whether the function invocation represented
+ by FI does not have a frame on the stack associated with it. If it
+ does not, FRAMELESS is set to 1, else 0. */
+#define FRAMELESS_FUNCTION_INVOCATION(FI, FRAMELESS) \
+ (FRAMELESS) = frameless_look_for_prologue(FI)
+
+#define FRAME_SAVED_PC(FRAME) frame_saved_pc(FRAME)
+
+#define FRAME_ARGS_ADDRESS(fi) ((fi)->frame)
+
+#define FRAME_LOCALS_ADDRESS(fi) ((fi)->frame)
+
+/* Set VAL to the number of args passed to frame described by FI.
+ Can set VAL to -1, meaning no way to tell. */
+
+/* We can't tell how many args there are
+ now that the C compiler delays popping them. */
+#if !defined (FRAME_NUM_ARGS)
+#define FRAME_NUM_ARGS(val,fi) (val = -1)
+#endif
+
+/* Return number of bytes at start of arglist that are not really args. */
+
+#define FRAME_ARGS_SKIP 8
+
+#ifdef __STDC__
+struct frame_info;
+#endif
+extern void z8k_frame_init_saved_regs PARAMS ((struct frame_info *));
+#define FRAME_INIT_SAVED_REGS(fi) z8k_frame_init_saved_regs (fi)
+
+
+/* Things needed for making the inferior call functions.
+ It seems like every m68k based machine has almost identical definitions
+ in the individual machine's configuration files. Most other cpu types
+ (mips, i386, etc) have routines in their *-tdep.c files to handle this
+ for most configurations. The m68k family should be able to do this as
+ well. These macros can still be overridden when necessary. */
+
+/* The CALL_DUMMY macro is the sequence of instructions, as disassembled
+ by gdb itself:
+
+ fmovemx fp0-fp7,sp@- 0xf227 0xe0ff
+ moveml d0-a5,sp@- 0x48e7 0xfffc
+ clrw sp@- 0x4267
+ movew ccr,sp@- 0x42e7
+
+ /..* The arguments are pushed at this point by GDB;
+ no code is needed in the dummy for this.
+ The CALL_DUMMY_START_OFFSET gives the position of
+ the following jsr instruction. *../
+
+ jsr @#0x32323232 0x4eb9 0x3232 0x3232
+ addal #0x69696969,sp 0xdffc 0x6969 0x6969
+ trap #<your BPT_VECTOR number here> 0x4e4?
+ nop 0x4e71
+
+ Note this is CALL_DUMMY_LENGTH bytes (28 for the above example).
+ We actually start executing at the jsr, since the pushing of the
+ registers is done by PUSH_DUMMY_FRAME. If this were real code,
+ the arguments for the function called by the jsr would be pushed
+ between the moveml and the jsr, and we could allow it to execute through.
+ But the arguments have to be pushed by GDB after the PUSH_DUMMY_FRAME is
+ done, and we cannot allow the moveml to push the registers again lest
+ they be taken for the arguments. */
+
+
+#define CALL_DUMMY { 0 }
+#define CALL_DUMMY_LENGTH 24 /* Size of CALL_DUMMY */
+#define CALL_DUMMY_START_OFFSET 8 /* Offset to jsr instruction*/
+
+
+/* Insert the specified number of args and function address
+ into a call sequence of the above form stored at DUMMYNAME.
+ We use the BFD routines to store a big-endian value of known size. */
+
+#define FIX_CALL_DUMMY(dummyname, pc, fun, nargs, args, type, gcc_p) \
+{ bfd_putb32 (fun, (char *) dummyname + CALL_DUMMY_START_OFFSET + 2); \
+ bfd_putb32 (nargs*4, (char *) dummyname + CALL_DUMMY_START_OFFSET + 8); }
+
+/* Push an empty stack frame, to record the current PC, etc. */
+
+#define PUSH_DUMMY_FRAME { z8k_push_dummy_frame (); }
+
+extern void z8k_push_dummy_frame PARAMS ((void));
+
+extern void z8k_pop_frame PARAMS ((void));
+
+/* Discard from the stack the innermost frame, restoring all registers. */
+
+#define POP_FRAME { z8k_pop_frame (); }
+
+/* Offset from SP to first arg on stack at first instruction of a function */
+
+#define SP_ARG0 (1 * 4)
+
+extern CORE_ADDR z8k_addr_bits_remove PARAMS ((CORE_ADDR));
+#define ADDR_BITS_REMOVE(addr) z8k_addr_bits_remove (addr)
+int sim_z8001_mode;
+#define BIG (sim_z8001_mode)
+
+#define read_memory_short(x) (read_memory_integer(x,2) & 0xffff)
+
+#define NO_STD_REGS
+
+#define PRINT_REGISTER_HOOK(regno) print_register_hook(regno)
+
+
+#define INIT_EXTRA_SYMTAB_INFO \
+ z8k_set_pointer_size(objfile->obfd->arch_info->bits_per_address);
+
+#define REGISTER_SIZE 4
+
diff --git a/gdb/config/z8k/z8k.mt b/gdb/config/z8k/z8k.mt
new file mode 100644
index 00000000000..cb8d04376e7
--- /dev/null
+++ b/gdb/config/z8k/z8k.mt
@@ -0,0 +1,7 @@
+# Target: Z8000 with simulator
+TDEPFILES= z8k-tdep.o
+TM_FILE= tm-z8k.h
+
+SIM_OBS = remote-sim.o
+SIM = ../sim/z8k/libsim.a
+
diff --git a/gdb/configure b/gdb/configure
new file mode 100755
index 00000000000..f70d0465af3
--- /dev/null
+++ b/gdb/configure
@@ -0,0 +1,6279 @@
+#! /bin/sh
+
+# Guess values for system-dependent variables and create Makefiles.
+# Generated automatically using autoconf version 2.13
+# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc.
+#
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+
+# Defaults:
+ac_help=
+ac_default_prefix=/usr/local
+# Any additions from configure.in:
+ac_help="$ac_help
+ --disable-nls do not use Native Language Support"
+ac_help="$ac_help
+ --with-included-gettext use the GNU gettext library included here"
+ac_help="$ac_help
+ --enable-tui Enable full-screen terminal user interface"
+ac_help="$ac_help
+ --enable-netrom Enable NetROM support"
+ac_help="$ac_help
+ --enable-build-warnings Enable build-time compiler warnings if gcc is used"
+ac_help="$ac_help
+ --with-mmalloc Use memory mapped malloc package"
+ac_help="$ac_help
+ --with-x use the X Window System"
+ac_help="$ac_help
+ --enable-shared Use shared libraries"
+
+# Initialize some variables set by options.
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+build=NONE
+cache_file=./config.cache
+exec_prefix=NONE
+host=NONE
+no_create=
+nonopt=NONE
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+target=NONE
+verbose=
+x_includes=NONE
+x_libraries=NONE
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datadir='${prefix}/share'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+libdir='${exec_prefix}/lib'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+infodir='${prefix}/info'
+mandir='${prefix}/man'
+
+# Initialize some other variables.
+subdirs=
+MFLAGS= MAKEFLAGS=
+SHELL=${CONFIG_SHELL-/bin/sh}
+# Maximum number of lines to put in a shell here document.
+ac_max_here_lines=12
+
+ac_prev=
+for ac_option
+do
+
+ # If the previous option needs an argument, assign it.
+ if test -n "$ac_prev"; then
+ eval "$ac_prev=\$ac_option"
+ ac_prev=
+ continue
+ fi
+
+ case "$ac_option" in
+ -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
+ *) ac_optarg= ;;
+ esac
+
+ # Accept the important Cygnus configure options, so we can diagnose typos.
+
+ case "$ac_option" in
+
+ -bindir | --bindir | --bindi | --bind | --bin | --bi)
+ ac_prev=bindir ;;
+ -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+ bindir="$ac_optarg" ;;
+
+ -build | --build | --buil | --bui | --bu)
+ ac_prev=build ;;
+ -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+ build="$ac_optarg" ;;
+
+ -cache-file | --cache-file | --cache-fil | --cache-fi \
+ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+ ac_prev=cache_file ;;
+ -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+ cache_file="$ac_optarg" ;;
+
+ -datadir | --datadir | --datadi | --datad | --data | --dat | --da)
+ ac_prev=datadir ;;
+ -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \
+ | --da=*)
+ datadir="$ac_optarg" ;;
+
+ -disable-* | --disable-*)
+ ac_feature=`echo $ac_option|sed -e 's/-*disable-//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then
+ { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
+ fi
+ ac_feature=`echo $ac_feature| sed 's/-/_/g'`
+ eval "enable_${ac_feature}=no" ;;
+
+ -enable-* | --enable-*)
+ ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then
+ { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
+ fi
+ ac_feature=`echo $ac_feature| sed 's/-/_/g'`
+ case "$ac_option" in
+ *=*) ;;
+ *) ac_optarg=yes ;;
+ esac
+ eval "enable_${ac_feature}='$ac_optarg'" ;;
+
+ -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+ | --exec | --exe | --ex)
+ ac_prev=exec_prefix ;;
+ -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+ | --exec=* | --exe=* | --ex=*)
+ exec_prefix="$ac_optarg" ;;
+
+ -gas | --gas | --ga | --g)
+ # Obsolete; use --with-gas.
+ with_gas=yes ;;
+
+ -help | --help | --hel | --he)
+ # Omit some internal or obsolete options to make the list less imposing.
+ # This message is too long to be a string in the A/UX 3.1 sh.
+ cat << EOF
+Usage: configure [options] [host]
+Options: [defaults in brackets after descriptions]
+Configuration:
+ --cache-file=FILE cache test results in FILE
+ --help print this message
+ --no-create do not create output files
+ --quiet, --silent do not print \`checking...' messages
+ --version print the version of autoconf that created configure
+Directory and file names:
+ --prefix=PREFIX install architecture-independent files in PREFIX
+ [$ac_default_prefix]
+ --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
+ [same as prefix]
+ --bindir=DIR user executables in DIR [EPREFIX/bin]
+ --sbindir=DIR system admin executables in DIR [EPREFIX/sbin]
+ --libexecdir=DIR program executables in DIR [EPREFIX/libexec]
+ --datadir=DIR read-only architecture-independent data in DIR
+ [PREFIX/share]
+ --sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc]
+ --sharedstatedir=DIR modifiable architecture-independent data in DIR
+ [PREFIX/com]
+ --localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var]
+ --libdir=DIR object code libraries in DIR [EPREFIX/lib]
+ --includedir=DIR C header files in DIR [PREFIX/include]
+ --oldincludedir=DIR C header files for non-gcc in DIR [/usr/include]
+ --infodir=DIR info documentation in DIR [PREFIX/info]
+ --mandir=DIR man documentation in DIR [PREFIX/man]
+ --srcdir=DIR find the sources in DIR [configure dir or ..]
+ --program-prefix=PREFIX prepend PREFIX to installed program names
+ --program-suffix=SUFFIX append SUFFIX to installed program names
+ --program-transform-name=PROGRAM
+ run sed PROGRAM on installed program names
+EOF
+ cat << EOF
+Host type:
+ --build=BUILD configure for building on BUILD [BUILD=HOST]
+ --host=HOST configure for HOST [guessed]
+ --target=TARGET configure for TARGET [TARGET=HOST]
+Features and packages:
+ --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
+ --enable-FEATURE[=ARG] include FEATURE [ARG=yes]
+ --with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
+ --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
+ --x-includes=DIR X include files are in DIR
+ --x-libraries=DIR X library files are in DIR
+EOF
+ if test -n "$ac_help"; then
+ echo "--enable and --with options recognized:$ac_help"
+ fi
+ exit 0 ;;
+
+ -host | --host | --hos | --ho)
+ ac_prev=host ;;
+ -host=* | --host=* | --hos=* | --ho=*)
+ host="$ac_optarg" ;;
+
+ -includedir | --includedir | --includedi | --included | --include \
+ | --includ | --inclu | --incl | --inc)
+ ac_prev=includedir ;;
+ -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+ | --includ=* | --inclu=* | --incl=* | --inc=*)
+ includedir="$ac_optarg" ;;
+
+ -infodir | --infodir | --infodi | --infod | --info | --inf)
+ ac_prev=infodir ;;
+ -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+ infodir="$ac_optarg" ;;
+
+ -libdir | --libdir | --libdi | --libd)
+ ac_prev=libdir ;;
+ -libdir=* | --libdir=* | --libdi=* | --libd=*)
+ libdir="$ac_optarg" ;;
+
+ -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+ | --libexe | --libex | --libe)
+ ac_prev=libexecdir ;;
+ -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+ | --libexe=* | --libex=* | --libe=*)
+ libexecdir="$ac_optarg" ;;
+
+ -localstatedir | --localstatedir | --localstatedi | --localstated \
+ | --localstate | --localstat | --localsta | --localst \
+ | --locals | --local | --loca | --loc | --lo)
+ ac_prev=localstatedir ;;
+ -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+ | --localstate=* | --localstat=* | --localsta=* | --localst=* \
+ | --locals=* | --local=* | --loca=* | --loc=* | --lo=*)
+ localstatedir="$ac_optarg" ;;
+
+ -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+ ac_prev=mandir ;;
+ -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+ mandir="$ac_optarg" ;;
+
+ -nfp | --nfp | --nf)
+ # Obsolete; use --without-fp.
+ with_fp=no ;;
+
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c)
+ no_create=yes ;;
+
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+ no_recursion=yes ;;
+
+ -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+ | --oldin | --oldi | --old | --ol | --o)
+ ac_prev=oldincludedir ;;
+ -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+ oldincludedir="$ac_optarg" ;;
+
+ -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+ ac_prev=prefix ;;
+ -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+ prefix="$ac_optarg" ;;
+
+ -program-prefix | --program-prefix | --program-prefi | --program-pref \
+ | --program-pre | --program-pr | --program-p)
+ ac_prev=program_prefix ;;
+ -program-prefix=* | --program-prefix=* | --program-prefi=* \
+ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+ program_prefix="$ac_optarg" ;;
+
+ -program-suffix | --program-suffix | --program-suffi | --program-suff \
+ | --program-suf | --program-su | --program-s)
+ ac_prev=program_suffix ;;
+ -program-suffix=* | --program-suffix=* | --program-suffi=* \
+ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+ program_suffix="$ac_optarg" ;;
+
+ -program-transform-name | --program-transform-name \
+ | --program-transform-nam | --program-transform-na \
+ | --program-transform-n | --program-transform- \
+ | --program-transform | --program-transfor \
+ | --program-transfo | --program-transf \
+ | --program-trans | --program-tran \
+ | --progr-tra | --program-tr | --program-t)
+ ac_prev=program_transform_name ;;
+ -program-transform-name=* | --program-transform-name=* \
+ | --program-transform-nam=* | --program-transform-na=* \
+ | --program-transform-n=* | --program-transform-=* \
+ | --program-transform=* | --program-transfor=* \
+ | --program-transfo=* | --program-transf=* \
+ | --program-trans=* | --program-tran=* \
+ | --progr-tra=* | --program-tr=* | --program-t=*)
+ program_transform_name="$ac_optarg" ;;
+
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ silent=yes ;;
+
+ -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+ ac_prev=sbindir ;;
+ -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+ | --sbi=* | --sb=*)
+ sbindir="$ac_optarg" ;;
+
+ -sharedstatedir | --sharedstatedir | --sharedstatedi \
+ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+ | --sharedst | --shareds | --shared | --share | --shar \
+ | --sha | --sh)
+ ac_prev=sharedstatedir ;;
+ -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+ | --sha=* | --sh=*)
+ sharedstatedir="$ac_optarg" ;;
+
+ -site | --site | --sit)
+ ac_prev=site ;;
+ -site=* | --site=* | --sit=*)
+ site="$ac_optarg" ;;
+
+ -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+ ac_prev=srcdir ;;
+ -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+ srcdir="$ac_optarg" ;;
+
+ -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+ | --syscon | --sysco | --sysc | --sys | --sy)
+ ac_prev=sysconfdir ;;
+ -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+ sysconfdir="$ac_optarg" ;;
+
+ -target | --target | --targe | --targ | --tar | --ta | --t)
+ ac_prev=target ;;
+ -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+ target="$ac_optarg" ;;
+
+ -v | -verbose | --verbose | --verbos | --verbo | --verb)
+ verbose=yes ;;
+
+ -version | --version | --versio | --versi | --vers)
+ echo "configure generated by autoconf version 2.13"
+ exit 0 ;;
+
+ -with-* | --with-*)
+ ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then
+ { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
+ fi
+ ac_package=`echo $ac_package| sed 's/-/_/g'`
+ case "$ac_option" in
+ *=*) ;;
+ *) ac_optarg=yes ;;
+ esac
+ eval "with_${ac_package}='$ac_optarg'" ;;
+
+ -without-* | --without-*)
+ ac_package=`echo $ac_option|sed -e 's/-*without-//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then
+ { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
+ fi
+ ac_package=`echo $ac_package| sed 's/-/_/g'`
+ eval "with_${ac_package}=no" ;;
+
+ --x)
+ # Obsolete; use --with-x.
+ with_x=yes ;;
+
+ -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+ | --x-incl | --x-inc | --x-in | --x-i)
+ ac_prev=x_includes ;;
+ -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+ x_includes="$ac_optarg" ;;
+
+ -x-libraries | --x-libraries | --x-librarie | --x-librari \
+ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+ ac_prev=x_libraries ;;
+ -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+ x_libraries="$ac_optarg" ;;
+
+ -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; }
+ ;;
+
+ *)
+ if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then
+ echo "configure: warning: $ac_option: invalid host type" 1>&2
+ fi
+ if test "x$nonopt" != xNONE; then
+ { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; }
+ fi
+ nonopt="$ac_option"
+ ;;
+
+ esac
+done
+
+if test -n "$ac_prev"; then
+ { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; }
+fi
+
+trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
+
+# File descriptor usage:
+# 0 standard input
+# 1 file creation
+# 2 errors and warnings
+# 3 some systems may open it to /dev/tty
+# 4 used on the Kubota Titan
+# 6 checking for... messages and results
+# 5 compiler messages saved in config.log
+if test "$silent" = yes; then
+ exec 6>/dev/null
+else
+ exec 6>&1
+fi
+exec 5>./config.log
+
+echo "\
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+" 1>&5
+
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Also quote any args containing shell metacharacters.
+ac_configure_args=
+for ac_arg
+do
+ case "$ac_arg" in
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c) ;;
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;;
+ *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*)
+ ac_configure_args="$ac_configure_args '$ac_arg'" ;;
+ *) ac_configure_args="$ac_configure_args $ac_arg" ;;
+ esac
+done
+
+# NLS nuisances.
+# Only set these to C if already set. These must not be set unconditionally
+# because not all systems understand e.g. LANG=C (notably SCO).
+# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'!
+# Non-C LC_CTYPE values break the ctype check.
+if test "${LANG+set}" = set; then LANG=C; export LANG; fi
+if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi
+if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi
+if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -rf conftest* confdefs.h
+# AIX cpp loses on an empty file, so make sure it contains at least a newline.
+echo > confdefs.h
+
+# A filename unique to this package, relative to the directory that
+# configure is in, which we can look for to find out if srcdir is correct.
+ac_unique_file=main.c
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+ ac_srcdir_defaulted=yes
+ # Try the directory containing this script, then its parent.
+ ac_prog=$0
+ ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'`
+ test "x$ac_confdir" = "x$ac_prog" && ac_confdir=.
+ srcdir=$ac_confdir
+ if test ! -r $srcdir/$ac_unique_file; then
+ srcdir=..
+ fi
+else
+ ac_srcdir_defaulted=no
+fi
+if test ! -r $srcdir/$ac_unique_file; then
+ if test "$ac_srcdir_defaulted" = yes; then
+ { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; }
+ else
+ { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; }
+ fi
+fi
+srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'`
+
+# Prefer explicitly selected file to automatically selected ones.
+if test -z "$CONFIG_SITE"; then
+ if test "x$prefix" != xNONE; then
+ CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site"
+ else
+ CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
+ fi
+fi
+for ac_site_file in $CONFIG_SITE; do
+ if test -r "$ac_site_file"; then
+ echo "loading site script $ac_site_file"
+ . "$ac_site_file"
+ fi
+done
+
+if test -r "$cache_file"; then
+ echo "loading cache $cache_file"
+ . $cache_file
+else
+ echo "creating cache $cache_file"
+ > $cache_file
+fi
+
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+ac_exeext=
+ac_objext=o
+if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then
+ # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu.
+ if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then
+ ac_n= ac_c='
+' ac_t=' '
+ else
+ ac_n=-n ac_c= ac_t=
+ fi
+else
+ ac_n= ac_c='\c' ac_t=
+fi
+
+
+
+
+# Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:546: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_CC="gcc"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+ echo "$ac_t""$CC" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+if test -z "$CC"; then
+ # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:576: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_prog_rejected=no
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then
+ ac_prog_rejected=yes
+ continue
+ fi
+ ac_cv_prog_CC="cc"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+if test $ac_prog_rejected = yes; then
+ # We found a bogon in the path, so make sure we never use it.
+ set dummy $ac_cv_prog_CC
+ shift
+ if test $# -gt 0; then
+ # We chose a different compiler from the bogus one.
+ # However, it has the same basename, so the bogon will be chosen
+ # first if we set CC to just the basename; use the full file name.
+ shift
+ set dummy "$ac_dir/$ac_word" "$@"
+ shift
+ ac_cv_prog_CC="$@"
+ fi
+fi
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+ echo "$ac_t""$CC" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ if test -z "$CC"; then
+ case "`uname -s`" in
+ *win32* | *WIN32*)
+ # Extract the first word of "cl", so it can be a program name with args.
+set dummy cl; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:627: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_CC="cl"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+ echo "$ac_t""$CC" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+ ;;
+ esac
+ fi
+ test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; }
+fi
+
+echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6
+echo "configure:659: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5
+
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+cat > conftest.$ac_ext << EOF
+
+#line 670 "configure"
+#include "confdefs.h"
+
+main(){return(0);}
+EOF
+if { (eval echo configure:675: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ ac_cv_prog_cc_works=yes
+ # If we can't run a trivial program, we are probably using a cross compiler.
+ if (./conftest; exit) 2>/dev/null; then
+ ac_cv_prog_cc_cross=no
+ else
+ ac_cv_prog_cc_cross=yes
+ fi
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ ac_cv_prog_cc_works=no
+fi
+rm -fr conftest*
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+echo "$ac_t""$ac_cv_prog_cc_works" 1>&6
+if test $ac_cv_prog_cc_works = no; then
+ { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; }
+fi
+echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6
+echo "configure:701: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5
+echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6
+cross_compiling=$ac_cv_prog_cc_cross
+
+echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6
+echo "configure:706: checking whether we are using GNU C" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.c <<EOF
+#ifdef __GNUC__
+ yes;
+#endif
+EOF
+if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:715: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
+ ac_cv_prog_gcc=yes
+else
+ ac_cv_prog_gcc=no
+fi
+fi
+
+echo "$ac_t""$ac_cv_prog_gcc" 1>&6
+
+if test $ac_cv_prog_gcc = yes; then
+ GCC=yes
+else
+ GCC=
+fi
+
+ac_test_CFLAGS="${CFLAGS+set}"
+ac_save_CFLAGS="$CFLAGS"
+CFLAGS=
+echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6
+echo "configure:734: checking whether ${CC-cc} accepts -g" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ echo 'void f(){}' > conftest.c
+if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then
+ ac_cv_prog_cc_g=yes
+else
+ ac_cv_prog_cc_g=no
+fi
+rm -f conftest*
+
+fi
+
+echo "$ac_t""$ac_cv_prog_cc_g" 1>&6
+if test "$ac_test_CFLAGS" = set; then
+ CFLAGS="$ac_save_CFLAGS"
+elif test $ac_cv_prog_cc_g = yes; then
+ if test "$GCC" = yes; then
+ CFLAGS="-g -O2"
+ else
+ CFLAGS="-g"
+ fi
+else
+ if test "$GCC" = yes; then
+ CFLAGS="-O2"
+ else
+ CFLAGS=
+ fi
+fi
+
+echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6
+echo "configure:766: checking how to run the C preprocessor" >&5
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+ CPP=
+fi
+if test -z "$CPP"; then
+if eval "test \"`echo '$''{'ac_cv_prog_CPP'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ # This must be in double quotes, not single quotes, because CPP may get
+ # substituted into the Makefile and "${CC-cc}" will confuse make.
+ CPP="${CC-cc} -E"
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp.
+ cat > conftest.$ac_ext <<EOF
+#line 781 "configure"
+#include "confdefs.h"
+#include <assert.h>
+Syntax Error
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:787: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ :
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ CPP="${CC-cc} -E -traditional-cpp"
+ cat > conftest.$ac_ext <<EOF
+#line 798 "configure"
+#include "confdefs.h"
+#include <assert.h>
+Syntax Error
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:804: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ :
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ CPP="${CC-cc} -nologo -E"
+ cat > conftest.$ac_ext <<EOF
+#line 815 "configure"
+#include "confdefs.h"
+#include <assert.h>
+Syntax Error
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:821: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ :
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ CPP=/lib/cpp
+fi
+rm -f conftest*
+fi
+rm -f conftest*
+fi
+rm -f conftest*
+ ac_cv_prog_CPP="$CPP"
+fi
+ CPP="$ac_cv_prog_CPP"
+else
+ ac_cv_prog_CPP="$CPP"
+fi
+echo "$ac_t""$CPP" 1>&6
+
+echo $ac_n "checking for AIX""... $ac_c" 1>&6
+echo "configure:846: checking for AIX" >&5
+cat > conftest.$ac_ext <<EOF
+#line 848 "configure"
+#include "confdefs.h"
+#ifdef _AIX
+ yes
+#endif
+
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "yes" >/dev/null 2>&1; then
+ rm -rf conftest*
+ echo "$ac_t""yes" 1>&6; cat >> confdefs.h <<\EOF
+#define _ALL_SOURCE 1
+EOF
+
+else
+ rm -rf conftest*
+ echo "$ac_t""no" 1>&6
+fi
+rm -f conftest*
+
+
+echo $ac_n "checking for POSIXized ISC""... $ac_c" 1>&6
+echo "configure:870: checking for POSIXized ISC" >&5
+if test -d /etc/conf/kconfig.d &&
+ grep _POSIX_VERSION /usr/include/sys/unistd.h >/dev/null 2>&1
+then
+ echo "$ac_t""yes" 1>&6
+ ISC=yes # If later tests want to check for ISC.
+ cat >> confdefs.h <<\EOF
+#define _POSIX_SOURCE 1
+EOF
+
+ if test "$GCC" = yes; then
+ CC="$CC -posix"
+ else
+ CC="$CC -Xp"
+ fi
+else
+ echo "$ac_t""no" 1>&6
+ ISC=
+fi
+
+
+
+
+echo $ac_n "checking for ${CC-cc} option to accept ANSI C""... $ac_c" 1>&6
+echo "configure:894: checking for ${CC-cc} option to accept ANSI C" >&5
+if eval "test \"`echo '$''{'am_cv_prog_cc_stdc'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ am_cv_prog_cc_stdc=no
+ac_save_CC="$CC"
+# Don't try gcc -ansi; that turns off useful extensions and
+# breaks some systems' header files.
+# AIX -qlanglvl=ansi
+# Ultrix and OSF/1 -std1
+# HP-UX -Aa -D_HPUX_SOURCE
+# SVR4 -Xc -D__EXTENSIONS__
+for ac_arg in "" -qlanglvl=ansi -std1 "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+ CC="$ac_save_CC $ac_arg"
+ cat > conftest.$ac_ext <<EOF
+#line 910 "configure"
+#include "confdefs.h"
+#include <stdarg.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+ char **p;
+ int i;
+{
+ return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+ char *s;
+ va_list v;
+ va_start (v,p);
+ s = g (p, va_arg (v,int));
+ va_end (v);
+ return s;
+}
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+
+int main() {
+
+return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1];
+
+; return 0; }
+EOF
+if { (eval echo configure:947: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ am_cv_prog_cc_stdc="$ac_arg"; break
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+fi
+rm -f conftest*
+done
+CC="$ac_save_CC"
+
+fi
+
+if test -z "$am_cv_prog_cc_stdc"; then
+ echo "$ac_t""none needed" 1>&6
+else
+ echo "$ac_t""$am_cv_prog_cc_stdc" 1>&6
+fi
+case "x$am_cv_prog_cc_stdc" in
+ x|xno) ;;
+ *) CC="$CC $am_cv_prog_cc_stdc" ;;
+esac
+
+
+ac_aux_dir=
+for ac_dir in `cd $srcdir;pwd`/.. $srcdir/`cd $srcdir;pwd`/..; do
+ if test -f $ac_dir/install-sh; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install-sh -c"
+ break
+ elif test -f $ac_dir/install.sh; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install.sh -c"
+ break
+ fi
+done
+if test -z "$ac_aux_dir"; then
+ { echo "configure: error: can not find install-sh or install.sh in `cd $srcdir;pwd`/.. $srcdir/`cd $srcdir;pwd`/.." 1>&2; exit 1; }
+fi
+ac_config_guess=$ac_aux_dir/config.guess
+ac_config_sub=$ac_aux_dir/config.sub
+ac_configure=$ac_aux_dir/configure # This should be Cygnus configure.
+
+
+# Do some error checking and defaulting for the host and target type.
+# The inputs are:
+# configure --host=HOST --target=TARGET --build=BUILD NONOPT
+#
+# The rules are:
+# 1. You are not allowed to specify --host, --target, and nonopt at the
+# same time.
+# 2. Host defaults to nonopt.
+# 3. If nonopt is not specified, then host defaults to the current host,
+# as determined by config.guess.
+# 4. Target and build default to nonopt.
+# 5. If nonopt is not specified, then target and build default to host.
+
+# The aliases save the names the user supplied, while $host etc.
+# will get canonicalized.
+case $host---$target---$nonopt in
+NONE---*---* | *---NONE---* | *---*---NONE) ;;
+*) { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; } ;;
+esac
+
+
+# Make sure we can run config.sub.
+if ${CONFIG_SHELL-/bin/sh} $ac_config_sub sun4 >/dev/null 2>&1; then :
+else { echo "configure: error: can not run $ac_config_sub" 1>&2; exit 1; }
+fi
+
+echo $ac_n "checking host system type""... $ac_c" 1>&6
+echo "configure:1018: checking host system type" >&5
+
+host_alias=$host
+case "$host_alias" in
+NONE)
+ case $nonopt in
+ NONE)
+ if host_alias=`${CONFIG_SHELL-/bin/sh} $ac_config_guess`; then :
+ else { echo "configure: error: can not guess host type; you must specify one" 1>&2; exit 1; }
+ fi ;;
+ *) host_alias=$nonopt ;;
+ esac ;;
+esac
+
+host=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $host_alias`
+host_cpu=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+host_vendor=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+host_os=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+echo "$ac_t""$host" 1>&6
+
+echo $ac_n "checking target system type""... $ac_c" 1>&6
+echo "configure:1039: checking target system type" >&5
+
+target_alias=$target
+case "$target_alias" in
+NONE)
+ case $nonopt in
+ NONE) target_alias=$host_alias ;;
+ *) target_alias=$nonopt ;;
+ esac ;;
+esac
+
+target=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $target_alias`
+target_cpu=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+target_vendor=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+target_os=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+echo "$ac_t""$target" 1>&6
+
+echo $ac_n "checking build system type""... $ac_c" 1>&6
+echo "configure:1057: checking build system type" >&5
+
+build_alias=$build
+case "$build_alias" in
+NONE)
+ case $nonopt in
+ NONE) build_alias=$host_alias ;;
+ *) build_alias=$nonopt ;;
+ esac ;;
+esac
+
+build=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $build_alias`
+build_cpu=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+build_vendor=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+build_os=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+echo "$ac_t""$build" 1>&6
+
+test "$host_alias" != "$target_alias" &&
+ test "$program_prefix$program_suffix$program_transform_name" = \
+ NONENONEs,x,x, &&
+ program_prefix=${target_alias}-
+
+
+ALL_LINGUAS=
+echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6
+echo "configure:1082: checking whether ${MAKE-make} sets \${MAKE}" >&5
+set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftestmake <<\EOF
+all:
+ @echo 'ac_maketemp="${MAKE}"'
+EOF
+# GNU make sometimes prints "make[1]: Entering...", which would confuse us.
+eval `${MAKE-make} -f conftestmake 2>/dev/null | grep temp=`
+if test -n "$ac_maketemp"; then
+ eval ac_cv_prog_make_${ac_make}_set=yes
+else
+ eval ac_cv_prog_make_${ac_make}_set=no
+fi
+rm -f conftestmake
+fi
+if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ SET_MAKE=
+else
+ echo "$ac_t""no" 1>&6
+ SET_MAKE="MAKE=${MAKE-make}"
+fi
+
+# Extract the first word of "ranlib", so it can be a program name with args.
+set dummy ranlib; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:1111: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$RANLIB"; then
+ ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_RANLIB="ranlib"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ test -z "$ac_cv_prog_RANLIB" && ac_cv_prog_RANLIB=":"
+fi
+fi
+RANLIB="$ac_cv_prog_RANLIB"
+if test -n "$RANLIB"; then
+ echo "$ac_t""$RANLIB" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6
+echo "configure:1139: checking for ANSI C header files" >&5
+if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1144 "configure"
+#include "confdefs.h"
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:1152: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ ac_cv_header_stdc=yes
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+if test $ac_cv_header_stdc = yes; then
+ # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+cat > conftest.$ac_ext <<EOF
+#line 1169 "configure"
+#include "confdefs.h"
+#include <string.h>
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "memchr" >/dev/null 2>&1; then
+ :
+else
+ rm -rf conftest*
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+cat > conftest.$ac_ext <<EOF
+#line 1187 "configure"
+#include "confdefs.h"
+#include <stdlib.h>
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "free" >/dev/null 2>&1; then
+ :
+else
+ rm -rf conftest*
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+if test "$cross_compiling" = yes; then
+ :
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1208 "configure"
+#include "confdefs.h"
+#include <ctype.h>
+#define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+#define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int main () { int i; for (i = 0; i < 256; i++)
+if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2);
+exit (0); }
+
+EOF
+if { (eval echo configure:1219: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+ :
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -fr conftest*
+ ac_cv_header_stdc=no
+fi
+rm -fr conftest*
+fi
+
+fi
+fi
+
+echo "$ac_t""$ac_cv_header_stdc" 1>&6
+if test $ac_cv_header_stdc = yes; then
+ cat >> confdefs.h <<\EOF
+#define STDC_HEADERS 1
+EOF
+
+fi
+
+echo $ac_n "checking for working const""... $ac_c" 1>&6
+echo "configure:1243: checking for working const" >&5
+if eval "test \"`echo '$''{'ac_cv_c_const'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1248 "configure"
+#include "confdefs.h"
+
+int main() {
+
+/* Ultrix mips cc rejects this. */
+typedef int charset[2]; const charset x;
+/* SunOS 4.1.1 cc rejects this. */
+char const *const *ccp;
+char **p;
+/* NEC SVR4.0.2 mips cc rejects this. */
+struct point {int x, y;};
+static struct point const zero = {0,0};
+/* AIX XL C 1.02.0.0 rejects this.
+ It does not let you subtract one const X* pointer from another in an arm
+ of an if-expression whose if-part is not a constant expression */
+const char *g = "string";
+ccp = &g + (g ? g-g : 0);
+/* HPUX 7.0 cc rejects these. */
+++ccp;
+p = (char**) ccp;
+ccp = (char const *const *) p;
+{ /* SCO 3.2v4 cc rejects this. */
+ char *t;
+ char const *s = 0 ? (char *) 0 : (char const *) 0;
+
+ *t++ = 0;
+}
+{ /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */
+ int x[] = {25, 17};
+ const int *foo = &x[0];
+ ++foo;
+}
+{ /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */
+ typedef const int *iptr;
+ iptr p = 0;
+ ++p;
+}
+{ /* AIX XL C 1.02.0.0 rejects this saying
+ "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */
+ struct s { int j; const int *ap[3]; };
+ struct s *b; b->j = 5;
+}
+{ /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */
+ const int foo = 10;
+}
+
+; return 0; }
+EOF
+if { (eval echo configure:1297: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_c_const=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_c_const=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_c_const" 1>&6
+if test $ac_cv_c_const = no; then
+ cat >> confdefs.h <<\EOF
+#define const
+EOF
+
+fi
+
+echo $ac_n "checking for inline""... $ac_c" 1>&6
+echo "configure:1318: checking for inline" >&5
+if eval "test \"`echo '$''{'ac_cv_c_inline'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_cv_c_inline=no
+for ac_kw in inline __inline__ __inline; do
+ cat > conftest.$ac_ext <<EOF
+#line 1325 "configure"
+#include "confdefs.h"
+
+int main() {
+} $ac_kw foo() {
+; return 0; }
+EOF
+if { (eval echo configure:1332: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_c_inline=$ac_kw; break
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+fi
+rm -f conftest*
+done
+
+fi
+
+echo "$ac_t""$ac_cv_c_inline" 1>&6
+case "$ac_cv_c_inline" in
+ inline | yes) ;;
+ no) cat >> confdefs.h <<\EOF
+#define inline
+EOF
+ ;;
+ *) cat >> confdefs.h <<EOF
+#define inline $ac_cv_c_inline
+EOF
+ ;;
+esac
+
+echo $ac_n "checking for off_t""... $ac_c" 1>&6
+echo "configure:1358: checking for off_t" >&5
+if eval "test \"`echo '$''{'ac_cv_type_off_t'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1363 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#if STDC_HEADERS
+#include <stdlib.h>
+#include <stddef.h>
+#endif
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "(^|[^a-zA-Z_0-9])off_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then
+ rm -rf conftest*
+ ac_cv_type_off_t=yes
+else
+ rm -rf conftest*
+ ac_cv_type_off_t=no
+fi
+rm -f conftest*
+
+fi
+echo "$ac_t""$ac_cv_type_off_t" 1>&6
+if test $ac_cv_type_off_t = no; then
+ cat >> confdefs.h <<\EOF
+#define off_t long
+EOF
+
+fi
+
+echo $ac_n "checking for size_t""... $ac_c" 1>&6
+echo "configure:1391: checking for size_t" >&5
+if eval "test \"`echo '$''{'ac_cv_type_size_t'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1396 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#if STDC_HEADERS
+#include <stdlib.h>
+#include <stddef.h>
+#endif
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "(^|[^a-zA-Z_0-9])size_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then
+ rm -rf conftest*
+ ac_cv_type_size_t=yes
+else
+ rm -rf conftest*
+ ac_cv_type_size_t=no
+fi
+rm -f conftest*
+
+fi
+echo "$ac_t""$ac_cv_type_size_t" 1>&6
+if test $ac_cv_type_size_t = no; then
+ cat >> confdefs.h <<\EOF
+#define size_t unsigned
+EOF
+
+fi
+
+# The Ultrix 4.2 mips builtin alloca declared by alloca.h only works
+# for constant arguments. Useless!
+echo $ac_n "checking for working alloca.h""... $ac_c" 1>&6
+echo "configure:1426: checking for working alloca.h" >&5
+if eval "test \"`echo '$''{'ac_cv_header_alloca_h'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1431 "configure"
+#include "confdefs.h"
+#include <alloca.h>
+int main() {
+char *p = alloca(2 * sizeof(int));
+; return 0; }
+EOF
+if { (eval echo configure:1438: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ ac_cv_header_alloca_h=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_header_alloca_h=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_header_alloca_h" 1>&6
+if test $ac_cv_header_alloca_h = yes; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_ALLOCA_H 1
+EOF
+
+fi
+
+echo $ac_n "checking for alloca""... $ac_c" 1>&6
+echo "configure:1459: checking for alloca" >&5
+if eval "test \"`echo '$''{'ac_cv_func_alloca_works'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1464 "configure"
+#include "confdefs.h"
+
+#ifdef __GNUC__
+# define alloca __builtin_alloca
+#else
+# ifdef _MSC_VER
+# include <malloc.h>
+# define alloca _alloca
+# else
+# if HAVE_ALLOCA_H
+# include <alloca.h>
+# else
+# ifdef _AIX
+ #pragma alloca
+# else
+# ifndef alloca /* predefined by HP cc +Olibcalls */
+char *alloca ();
+# endif
+# endif
+# endif
+# endif
+#endif
+
+int main() {
+char *p = (char *) alloca(1);
+; return 0; }
+EOF
+if { (eval echo configure:1492: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ ac_cv_func_alloca_works=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_func_alloca_works=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_func_alloca_works" 1>&6
+if test $ac_cv_func_alloca_works = yes; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_ALLOCA 1
+EOF
+
+fi
+
+if test $ac_cv_func_alloca_works = no; then
+ # The SVR3 libPW and SVR4 libucb both contain incompatible functions
+ # that cause trouble. Some versions do not even contain alloca or
+ # contain a buggy version. If you still want to use their alloca,
+ # use ar to extract alloca.o from them instead of compiling alloca.c.
+ ALLOCA=alloca.${ac_objext}
+ cat >> confdefs.h <<\EOF
+#define C_ALLOCA 1
+EOF
+
+
+echo $ac_n "checking whether alloca needs Cray hooks""... $ac_c" 1>&6
+echo "configure:1524: checking whether alloca needs Cray hooks" >&5
+if eval "test \"`echo '$''{'ac_cv_os_cray'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1529 "configure"
+#include "confdefs.h"
+#if defined(CRAY) && ! defined(CRAY2)
+webecray
+#else
+wenotbecray
+#endif
+
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "webecray" >/dev/null 2>&1; then
+ rm -rf conftest*
+ ac_cv_os_cray=yes
+else
+ rm -rf conftest*
+ ac_cv_os_cray=no
+fi
+rm -f conftest*
+
+fi
+
+echo "$ac_t""$ac_cv_os_cray" 1>&6
+if test $ac_cv_os_cray = yes; then
+for ac_func in _getb67 GETB67 getb67; do
+ echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+echo "configure:1554: checking for $ac_func" >&5
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1559 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $ac_func();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:1582: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ cat >> confdefs.h <<EOF
+#define CRAY_STACKSEG_END $ac_func
+EOF
+
+ break
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+done
+fi
+
+echo $ac_n "checking stack direction for C alloca""... $ac_c" 1>&6
+echo "configure:1609: checking stack direction for C alloca" >&5
+if eval "test \"`echo '$''{'ac_cv_c_stack_direction'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test "$cross_compiling" = yes; then
+ ac_cv_c_stack_direction=0
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1617 "configure"
+#include "confdefs.h"
+find_stack_direction ()
+{
+ static char *addr = 0;
+ auto char dummy;
+ if (addr == 0)
+ {
+ addr = &dummy;
+ return find_stack_direction ();
+ }
+ else
+ return (&dummy > addr) ? 1 : -1;
+}
+main ()
+{
+ exit (find_stack_direction() < 0);
+}
+EOF
+if { (eval echo configure:1636: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+ ac_cv_c_stack_direction=1
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -fr conftest*
+ ac_cv_c_stack_direction=-1
+fi
+rm -fr conftest*
+fi
+
+fi
+
+echo "$ac_t""$ac_cv_c_stack_direction" 1>&6
+cat >> confdefs.h <<EOF
+#define STACK_DIRECTION $ac_cv_c_stack_direction
+EOF
+
+fi
+
+for ac_hdr in unistd.h
+do
+ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
+echo "configure:1661: checking for $ac_hdr" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1666 "configure"
+#include "confdefs.h"
+#include <$ac_hdr>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:1671: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=yes"
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_hdr 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+for ac_func in getpagesize
+do
+echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+echo "configure:1700: checking for $ac_func" >&5
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1705 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $ac_func();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:1728: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_func 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+echo $ac_n "checking for working mmap""... $ac_c" 1>&6
+echo "configure:1753: checking for working mmap" >&5
+if eval "test \"`echo '$''{'ac_cv_func_mmap_fixed_mapped'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test "$cross_compiling" = yes; then
+ ac_cv_func_mmap_fixed_mapped=no
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1761 "configure"
+#include "confdefs.h"
+
+/* Thanks to Mike Haertel and Jim Avera for this test.
+ Here is a matrix of mmap possibilities:
+ mmap private not fixed
+ mmap private fixed at somewhere currently unmapped
+ mmap private fixed at somewhere already mapped
+ mmap shared not fixed
+ mmap shared fixed at somewhere currently unmapped
+ mmap shared fixed at somewhere already mapped
+ For private mappings, we should verify that changes cannot be read()
+ back from the file, nor mmap's back from the file at a different
+ address. (There have been systems where private was not correctly
+ implemented like the infamous i386 svr4.0, and systems where the
+ VM page cache was not coherent with the filesystem buffer cache
+ like early versions of FreeBSD and possibly contemporary NetBSD.)
+ For shared mappings, we should conversely verify that changes get
+ propogated back to all the places they're supposed to be.
+
+ Grep wants private fixed already mapped.
+ The main things grep needs to know about mmap are:
+ * does it exist and is it safe to write into the mmap'd area
+ * how to use it (BSD variants) */
+#include <sys/types.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+
+/* This mess was copied from the GNU getpagesize.h. */
+#ifndef HAVE_GETPAGESIZE
+# ifdef HAVE_UNISTD_H
+# include <unistd.h>
+# endif
+
+/* Assume that all systems that can run configure have sys/param.h. */
+# ifndef HAVE_SYS_PARAM_H
+# define HAVE_SYS_PARAM_H 1
+# endif
+
+# ifdef _SC_PAGESIZE
+# define getpagesize() sysconf(_SC_PAGESIZE)
+# else /* no _SC_PAGESIZE */
+# ifdef HAVE_SYS_PARAM_H
+# include <sys/param.h>
+# ifdef EXEC_PAGESIZE
+# define getpagesize() EXEC_PAGESIZE
+# else /* no EXEC_PAGESIZE */
+# ifdef NBPG
+# define getpagesize() NBPG * CLSIZE
+# ifndef CLSIZE
+# define CLSIZE 1
+# endif /* no CLSIZE */
+# else /* no NBPG */
+# ifdef NBPC
+# define getpagesize() NBPC
+# else /* no NBPC */
+# ifdef PAGESIZE
+# define getpagesize() PAGESIZE
+# endif /* PAGESIZE */
+# endif /* no NBPC */
+# endif /* no NBPG */
+# endif /* no EXEC_PAGESIZE */
+# else /* no HAVE_SYS_PARAM_H */
+# define getpagesize() 8192 /* punt totally */
+# endif /* no HAVE_SYS_PARAM_H */
+# endif /* no _SC_PAGESIZE */
+
+#endif /* no HAVE_GETPAGESIZE */
+
+#ifdef __cplusplus
+extern "C" { void *malloc(unsigned); }
+#else
+char *malloc();
+#endif
+
+int
+main()
+{
+ char *data, *data2, *data3;
+ int i, pagesize;
+ int fd;
+
+ pagesize = getpagesize();
+
+ /*
+ * First, make a file with some known garbage in it.
+ */
+ data = malloc(pagesize);
+ if (!data)
+ exit(1);
+ for (i = 0; i < pagesize; ++i)
+ *(data + i) = rand();
+ umask(0);
+ fd = creat("conftestmmap", 0600);
+ if (fd < 0)
+ exit(1);
+ if (write(fd, data, pagesize) != pagesize)
+ exit(1);
+ close(fd);
+
+ /*
+ * Next, try to mmap the file at a fixed address which
+ * already has something else allocated at it. If we can,
+ * also make sure that we see the same garbage.
+ */
+ fd = open("conftestmmap", O_RDWR);
+ if (fd < 0)
+ exit(1);
+ data2 = malloc(2 * pagesize);
+ if (!data2)
+ exit(1);
+ data2 += (pagesize - ((int) data2 & (pagesize - 1))) & (pagesize - 1);
+ if (data2 != mmap(data2, pagesize, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_FIXED, fd, 0L))
+ exit(1);
+ for (i = 0; i < pagesize; ++i)
+ if (*(data + i) != *(data2 + i))
+ exit(1);
+
+ /*
+ * Finally, make sure that changes to the mapped area
+ * do not percolate back to the file as seen by read().
+ * (This is a bug on some variants of i386 svr4.0.)
+ */
+ for (i = 0; i < pagesize; ++i)
+ *(data2 + i) = *(data2 + i) + 1;
+ data3 = malloc(pagesize);
+ if (!data3)
+ exit(1);
+ if (read(fd, data3, pagesize) != pagesize)
+ exit(1);
+ for (i = 0; i < pagesize; ++i)
+ if (*(data + i) != *(data3 + i))
+ exit(1);
+ close(fd);
+ unlink("conftestmmap");
+ exit(0);
+}
+
+EOF
+if { (eval echo configure:1901: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+ ac_cv_func_mmap_fixed_mapped=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -fr conftest*
+ ac_cv_func_mmap_fixed_mapped=no
+fi
+rm -fr conftest*
+fi
+
+fi
+
+echo "$ac_t""$ac_cv_func_mmap_fixed_mapped" 1>&6
+if test $ac_cv_func_mmap_fixed_mapped = yes; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_MMAP 1
+EOF
+
+fi
+
+
+ for ac_hdr in argz.h limits.h locale.h nl_types.h malloc.h string.h \
+unistd.h values.h sys/param.h
+do
+ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
+echo "configure:1929: checking for $ac_hdr" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1934 "configure"
+#include "confdefs.h"
+#include <$ac_hdr>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:1939: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=yes"
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_hdr 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+ for ac_func in getcwd munmap putenv setenv setlocale strchr strcasecmp \
+__argz_count __argz_stringify __argz_next
+do
+echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+echo "configure:1969: checking for $ac_func" >&5
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1974 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $ac_func();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:1997: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_func 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+
+ if test "${ac_cv_func_stpcpy+set}" != "set"; then
+ for ac_func in stpcpy
+do
+echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+echo "configure:2026: checking for $ac_func" >&5
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2031 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $ac_func();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:2054: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_func 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+ fi
+ if test "${ac_cv_func_stpcpy}" = "yes"; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_STPCPY 1
+EOF
+
+ fi
+
+ if test $ac_cv_header_locale_h = yes; then
+ echo $ac_n "checking for LC_MESSAGES""... $ac_c" 1>&6
+echo "configure:2088: checking for LC_MESSAGES" >&5
+if eval "test \"`echo '$''{'am_cv_val_LC_MESSAGES'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2093 "configure"
+#include "confdefs.h"
+#include <locale.h>
+int main() {
+return LC_MESSAGES
+; return 0; }
+EOF
+if { (eval echo configure:2100: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ am_cv_val_LC_MESSAGES=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ am_cv_val_LC_MESSAGES=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$am_cv_val_LC_MESSAGES" 1>&6
+ if test $am_cv_val_LC_MESSAGES = yes; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_LC_MESSAGES 1
+EOF
+
+ fi
+ fi
+ echo $ac_n "checking whether NLS is requested""... $ac_c" 1>&6
+echo "configure:2121: checking whether NLS is requested" >&5
+ # Check whether --enable-nls or --disable-nls was given.
+if test "${enable_nls+set}" = set; then
+ enableval="$enable_nls"
+ USE_NLS=$enableval
+else
+ USE_NLS=yes
+fi
+
+ echo "$ac_t""$USE_NLS" 1>&6
+
+
+ USE_INCLUDED_LIBINTL=no
+
+ if test "$USE_NLS" = "yes"; then
+ cat >> confdefs.h <<\EOF
+#define ENABLE_NLS 1
+EOF
+
+ echo $ac_n "checking whether included gettext is requested""... $ac_c" 1>&6
+echo "configure:2141: checking whether included gettext is requested" >&5
+ # Check whether --with-included-gettext or --without-included-gettext was given.
+if test "${with_included_gettext+set}" = set; then
+ withval="$with_included_gettext"
+ nls_cv_force_use_gnu_gettext=$withval
+else
+ nls_cv_force_use_gnu_gettext=no
+fi
+
+ echo "$ac_t""$nls_cv_force_use_gnu_gettext" 1>&6
+
+ nls_cv_use_gnu_gettext="$nls_cv_force_use_gnu_gettext"
+ if test "$nls_cv_force_use_gnu_gettext" != "yes"; then
+ nls_cv_header_intl=
+ nls_cv_header_libgt=
+ CATOBJEXT=NONE
+
+ ac_safe=`echo "libintl.h" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for libintl.h""... $ac_c" 1>&6
+echo "configure:2160: checking for libintl.h" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2165 "configure"
+#include "confdefs.h"
+#include <libintl.h>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:2170: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=yes"
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ echo $ac_n "checking for gettext in libc""... $ac_c" 1>&6
+echo "configure:2187: checking for gettext in libc" >&5
+if eval "test \"`echo '$''{'gt_cv_func_gettext_libc'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2192 "configure"
+#include "confdefs.h"
+#include <libintl.h>
+int main() {
+return (int) gettext ("")
+; return 0; }
+EOF
+if { (eval echo configure:2199: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ gt_cv_func_gettext_libc=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ gt_cv_func_gettext_libc=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$gt_cv_func_gettext_libc" 1>&6
+
+ if test "$gt_cv_func_gettext_libc" != "yes"; then
+ echo $ac_n "checking for bindtextdomain in -lintl""... $ac_c" 1>&6
+echo "configure:2215: checking for bindtextdomain in -lintl" >&5
+ac_lib_var=`echo intl'_'bindtextdomain | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lintl $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 2223 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char bindtextdomain();
+
+int main() {
+bindtextdomain()
+; return 0; }
+EOF
+if { (eval echo configure:2234: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ echo $ac_n "checking for gettext in libintl""... $ac_c" 1>&6
+echo "configure:2250: checking for gettext in libintl" >&5
+if eval "test \"`echo '$''{'gt_cv_func_gettext_libintl'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2255 "configure"
+#include "confdefs.h"
+
+int main() {
+return (int) gettext ("")
+; return 0; }
+EOF
+if { (eval echo configure:2262: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ gt_cv_func_gettext_libintl=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ gt_cv_func_gettext_libintl=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$gt_cv_func_gettext_libintl" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ fi
+
+ if test "$gt_cv_func_gettext_libc" = "yes" \
+ || test "$gt_cv_func_gettext_libintl" = "yes"; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_GETTEXT 1
+EOF
+
+ # Extract the first word of "msgfmt", so it can be a program name with args.
+set dummy msgfmt; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:2290: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_path_MSGFMT'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ case "$MSGFMT" in
+ /*)
+ ac_cv_path_MSGFMT="$MSGFMT" # Let the user override the test with a path.
+ ;;
+ *)
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+ for ac_dir in $PATH; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ if test -z "`$ac_dir/$ac_word -h 2>&1 | grep 'dv '`"; then
+ ac_cv_path_MSGFMT="$ac_dir/$ac_word"
+ break
+ fi
+ fi
+ done
+ IFS="$ac_save_ifs"
+ test -z "$ac_cv_path_MSGFMT" && ac_cv_path_MSGFMT="no"
+ ;;
+esac
+fi
+MSGFMT="$ac_cv_path_MSGFMT"
+if test -n "$MSGFMT"; then
+ echo "$ac_t""$MSGFMT" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+ if test "$MSGFMT" != "no"; then
+ for ac_func in dcgettext
+do
+echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+echo "configure:2324: checking for $ac_func" >&5
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2329 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $ac_func();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:2352: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_func 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+ # Extract the first word of "gmsgfmt", so it can be a program name with args.
+set dummy gmsgfmt; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:2379: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_path_GMSGFMT'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ case "$GMSGFMT" in
+ /*)
+ ac_cv_path_GMSGFMT="$GMSGFMT" # Let the user override the test with a path.
+ ;;
+ ?:/*)
+ ac_cv_path_GMSGFMT="$GMSGFMT" # Let the user override the test with a dos path.
+ ;;
+ *)
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_path_GMSGFMT="$ac_dir/$ac_word"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ test -z "$ac_cv_path_GMSGFMT" && ac_cv_path_GMSGFMT="$MSGFMT"
+ ;;
+esac
+fi
+GMSGFMT="$ac_cv_path_GMSGFMT"
+if test -n "$GMSGFMT"; then
+ echo "$ac_t""$GMSGFMT" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ # Extract the first word of "xgettext", so it can be a program name with args.
+set dummy xgettext; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:2415: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_path_XGETTEXT'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ case "$XGETTEXT" in
+ /*)
+ ac_cv_path_XGETTEXT="$XGETTEXT" # Let the user override the test with a path.
+ ;;
+ *)
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+ for ac_dir in $PATH; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ if test -z "`$ac_dir/$ac_word -h 2>&1 | grep '(HELP)'`"; then
+ ac_cv_path_XGETTEXT="$ac_dir/$ac_word"
+ break
+ fi
+ fi
+ done
+ IFS="$ac_save_ifs"
+ test -z "$ac_cv_path_XGETTEXT" && ac_cv_path_XGETTEXT=":"
+ ;;
+esac
+fi
+XGETTEXT="$ac_cv_path_XGETTEXT"
+if test -n "$XGETTEXT"; then
+ echo "$ac_t""$XGETTEXT" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ cat > conftest.$ac_ext <<EOF
+#line 2447 "configure"
+#include "confdefs.h"
+
+int main() {
+extern int _nl_msg_cat_cntr;
+ return _nl_msg_cat_cntr
+; return 0; }
+EOF
+if { (eval echo configure:2455: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ CATOBJEXT=.gmo
+ DATADIRNAME=share
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ CATOBJEXT=.mo
+ DATADIRNAME=lib
+fi
+rm -f conftest*
+ INSTOBJEXT=.mo
+ fi
+ fi
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+
+
+ if test "$CATOBJEXT" = "NONE"; then
+ nls_cv_use_gnu_gettext=yes
+ fi
+ fi
+
+ if test "$nls_cv_use_gnu_gettext" = "yes"; then
+ INTLOBJS="\$(GETTOBJS)"
+ # Extract the first word of "msgfmt", so it can be a program name with args.
+set dummy msgfmt; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:2487: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_path_MSGFMT'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ case "$MSGFMT" in
+ /*)
+ ac_cv_path_MSGFMT="$MSGFMT" # Let the user override the test with a path.
+ ;;
+ *)
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+ for ac_dir in $PATH; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ if test -z "`$ac_dir/$ac_word -h 2>&1 | grep 'dv '`"; then
+ ac_cv_path_MSGFMT="$ac_dir/$ac_word"
+ break
+ fi
+ fi
+ done
+ IFS="$ac_save_ifs"
+ test -z "$ac_cv_path_MSGFMT" && ac_cv_path_MSGFMT="msgfmt"
+ ;;
+esac
+fi
+MSGFMT="$ac_cv_path_MSGFMT"
+if test -n "$MSGFMT"; then
+ echo "$ac_t""$MSGFMT" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ # Extract the first word of "gmsgfmt", so it can be a program name with args.
+set dummy gmsgfmt; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:2521: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_path_GMSGFMT'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ case "$GMSGFMT" in
+ /*)
+ ac_cv_path_GMSGFMT="$GMSGFMT" # Let the user override the test with a path.
+ ;;
+ ?:/*)
+ ac_cv_path_GMSGFMT="$GMSGFMT" # Let the user override the test with a dos path.
+ ;;
+ *)
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_path_GMSGFMT="$ac_dir/$ac_word"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ test -z "$ac_cv_path_GMSGFMT" && ac_cv_path_GMSGFMT="$MSGFMT"
+ ;;
+esac
+fi
+GMSGFMT="$ac_cv_path_GMSGFMT"
+if test -n "$GMSGFMT"; then
+ echo "$ac_t""$GMSGFMT" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ # Extract the first word of "xgettext", so it can be a program name with args.
+set dummy xgettext; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:2557: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_path_XGETTEXT'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ case "$XGETTEXT" in
+ /*)
+ ac_cv_path_XGETTEXT="$XGETTEXT" # Let the user override the test with a path.
+ ;;
+ *)
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+ for ac_dir in $PATH; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ if test -z "`$ac_dir/$ac_word -h 2>&1 | grep '(HELP)'`"; then
+ ac_cv_path_XGETTEXT="$ac_dir/$ac_word"
+ break
+ fi
+ fi
+ done
+ IFS="$ac_save_ifs"
+ test -z "$ac_cv_path_XGETTEXT" && ac_cv_path_XGETTEXT=":"
+ ;;
+esac
+fi
+XGETTEXT="$ac_cv_path_XGETTEXT"
+if test -n "$XGETTEXT"; then
+ echo "$ac_t""$XGETTEXT" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+
+ USE_INCLUDED_LIBINTL=yes
+ CATOBJEXT=.gmo
+ INSTOBJEXT=.mo
+ DATADIRNAME=share
+ INTLDEPS='$(top_builddir)/../intl/libintl.a'
+ INTLLIBS=$INTLDEPS
+ LIBS=`echo $LIBS | sed -e 's/-lintl//'`
+ nls_cv_header_intl=libintl.h
+ nls_cv_header_libgt=libgettext.h
+ fi
+
+ if test "$XGETTEXT" != ":"; then
+ if $XGETTEXT --omit-header /dev/null 2> /dev/null; then
+ : ;
+ else
+ echo "$ac_t""found xgettext programs is not GNU xgettext; ignore it" 1>&6
+ XGETTEXT=":"
+ fi
+ fi
+
+ # We need to process the po/ directory.
+ POSUB=po
+ else
+ DATADIRNAME=share
+ nls_cv_header_intl=libintl.h
+ nls_cv_header_libgt=libgettext.h
+ fi
+
+ # If this is used in GNU gettext we have to set USE_NLS to `yes'
+ # because some of the sources are only built for this goal.
+ if test "$PACKAGE" = gettext; then
+ USE_NLS=yes
+ USE_INCLUDED_LIBINTL=yes
+ fi
+
+ for lang in $ALL_LINGUAS; do
+ GMOFILES="$GMOFILES $lang.gmo"
+ POFILES="$POFILES $lang.po"
+ done
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ if test "x$CATOBJEXT" != "x"; then
+ if test "x$ALL_LINGUAS" = "x"; then
+ LINGUAS=
+ else
+ echo $ac_n "checking for catalogs to be installed""... $ac_c" 1>&6
+echo "configure:2647: checking for catalogs to be installed" >&5
+ NEW_LINGUAS=
+ for lang in ${LINGUAS=$ALL_LINGUAS}; do
+ case "$ALL_LINGUAS" in
+ *$lang*) NEW_LINGUAS="$NEW_LINGUAS $lang" ;;
+ esac
+ done
+ LINGUAS=$NEW_LINGUAS
+ echo "$ac_t""$LINGUAS" 1>&6
+ fi
+
+ if test -n "$LINGUAS"; then
+ for lang in $LINGUAS; do CATALOGS="$CATALOGS $lang$CATOBJEXT"; done
+ fi
+ fi
+
+ if test $ac_cv_header_locale_h = yes; then
+ INCLUDE_LOCALE_H="#include <locale.h>"
+ else
+ INCLUDE_LOCALE_H="\
+/* The system does not provide the header <locale.h>. Take care yourself. */"
+ fi
+
+
+ if test -f $srcdir/po2tbl.sed.in; then
+ if test "$CATOBJEXT" = ".cat"; then
+ ac_safe=`echo "linux/version.h" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for linux/version.h""... $ac_c" 1>&6
+echo "configure:2675: checking for linux/version.h" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2680 "configure"
+#include "confdefs.h"
+#include <linux/version.h>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:2685: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=yes"
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ msgformat=linux
+else
+ echo "$ac_t""no" 1>&6
+msgformat=xopen
+fi
+
+
+ sed -e '/^#/d' $srcdir/$msgformat-msg.sed > po2msg.sed
+ fi
+ sed -e '/^#.*[^\\]$/d' -e '/^#$/d' \
+ $srcdir/po2tbl.sed.in > po2tbl.sed
+ fi
+
+ if test "$PACKAGE" = "gettext"; then
+ GT_NO="#NO#"
+ GT_YES=
+ else
+ GT_NO=
+ GT_YES="#YES#"
+ fi
+
+
+
+ MKINSTALLDIRS="\$(srcdir)/../../mkinstalldirs"
+
+
+ l=
+
+
+ if test -d $srcdir/po; then
+ test -d po || mkdir po
+ if test "x$srcdir" != "x."; then
+ if test "x`echo $srcdir | sed 's@/.*@@'`" = "x"; then
+ posrcprefix="$srcdir/"
+ else
+ posrcprefix="../$srcdir/"
+ fi
+ else
+ posrcprefix="../"
+ fi
+ rm -f po/POTFILES
+ sed -e "/^#/d" -e "/^\$/d" -e "s,.*, $posrcprefix& \\\\," -e "\$s/\(.*\) \\\\/\1/" \
+ < $srcdir/po/POTFILES.in > po/POTFILES
+ fi
+
+
+
+CONFIG_OBS=
+CONFIG_DEPS=
+CONFIG_SRCS=
+
+configdirs="doc testsuite"
+
+
+. ${srcdir}/configure.host
+
+. ${srcdir}/configure.tgt
+
+
+# Find a good install program. We prefer a C program (faster),
+# so one script is as good as another. But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# ./install, which can be erroneously created by make from ./install.sh.
+echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6
+echo "configure:2772: checking for a BSD compatible install" >&5
+if test -z "$INSTALL"; then
+if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ IFS="${IFS= }"; ac_save_IFS="$IFS"; IFS=":"
+ for ac_dir in $PATH; do
+ # Account for people who put trailing slashes in PATH elements.
+ case "$ac_dir/" in
+ /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;;
+ *)
+ # OSF1 and SCO ODT 3.0 have their own names for install.
+ # Don't use installbsd from OSF since it installs stuff as root
+ # by default.
+ for ac_prog in ginstall scoinst install; do
+ if test -f $ac_dir/$ac_prog; then
+ if test $ac_prog = install &&
+ grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then
+ # AIX install. It has an incompatible calling convention.
+ :
+ else
+ ac_cv_path_install="$ac_dir/$ac_prog -c"
+ break 2
+ fi
+ fi
+ done
+ ;;
+ esac
+ done
+ IFS="$ac_save_IFS"
+
+fi
+ if test "${ac_cv_path_install+set}" = set; then
+ INSTALL="$ac_cv_path_install"
+ else
+ # As a last resort, use the slow shell script. We don't cache a
+ # path for INSTALL within a source directory, because that will
+ # break other packages using the cache if that directory is
+ # removed, or if the path is relative.
+ INSTALL="$ac_install_sh"
+ fi
+fi
+echo "$ac_t""$INSTALL" 1>&6
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL_PROGRAM}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+if test $host != $build; then
+ ac_tool_prefix=${host_alias}-
+else
+ ac_tool_prefix=
+fi
+
+# Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ar; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:2833: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_AR'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$AR"; then
+ ac_cv_prog_AR="$AR" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_AR="${ac_tool_prefix}ar"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ test -z "$ac_cv_prog_AR" && ac_cv_prog_AR="ar"
+fi
+fi
+AR="$ac_cv_prog_AR"
+if test -n "$AR"; then
+ echo "$ac_t""$AR" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+
+
+# Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ranlib; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:2865: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$RANLIB"; then
+ ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+fi
+fi
+RANLIB="$ac_cv_prog_RANLIB"
+if test -n "$RANLIB"; then
+ echo "$ac_t""$RANLIB" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+
+if test -z "$ac_cv_prog_RANLIB"; then
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "ranlib", so it can be a program name with args.
+set dummy ranlib; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:2897: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$RANLIB"; then
+ ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_RANLIB="ranlib"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ test -z "$ac_cv_prog_RANLIB" && ac_cv_prog_RANLIB=":"
+fi
+fi
+RANLIB="$ac_cv_prog_RANLIB"
+if test -n "$RANLIB"; then
+ echo "$ac_t""$RANLIB" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+else
+ RANLIB=":"
+fi
+fi
+
+for ac_prog in 'bison -y' byacc
+do
+# Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:2934: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_YACC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$YACC"; then
+ ac_cv_prog_YACC="$YACC" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_YACC="$ac_prog"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+fi
+fi
+YACC="$ac_cv_prog_YACC"
+if test -n "$YACC"; then
+ echo "$ac_t""$YACC" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+test -n "$YACC" && break
+done
+test -n "$YACC" || YACC="yacc"
+
+
+if test "$program_transform_name" = s,x,x,; then
+ program_transform_name=
+else
+ # Double any \ or $. echo might interpret backslashes.
+ cat <<\EOF_SED > conftestsed
+s,\\,\\\\,g; s,\$,$$,g
+EOF_SED
+ program_transform_name="`echo $program_transform_name|sed -f conftestsed`"
+ rm -f conftestsed
+fi
+test "$program_prefix" != NONE &&
+ program_transform_name="s,^,${program_prefix},; $program_transform_name"
+# Use a double $ so make ignores it.
+test "$program_suffix" != NONE &&
+ program_transform_name="s,\$\$,${program_suffix},; $program_transform_name"
+
+# sed with no file args requires a program.
+test "$program_transform_name" = "" && program_transform_name="s,x,x,"
+
+
+echo $ac_n "checking return type of signal handlers""... $ac_c" 1>&6
+echo "configure:2986: checking return type of signal handlers" >&5
+if eval "test \"`echo '$''{'ac_cv_type_signal'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2991 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <signal.h>
+#ifdef signal
+#undef signal
+#endif
+#ifdef __cplusplus
+extern "C" void (*signal (int, void (*)(int)))(int);
+#else
+void (*signal ()) ();
+#endif
+
+int main() {
+int i;
+; return 0; }
+EOF
+if { (eval echo configure:3008: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_type_signal=void
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_type_signal=int
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_type_signal" 1>&6
+cat >> confdefs.h <<EOF
+#define RETSIGTYPE $ac_cv_type_signal
+EOF
+
+
+
+echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6
+echo "configure:3028: checking for ANSI C header files" >&5
+if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 3033 "configure"
+#include "confdefs.h"
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:3041: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ ac_cv_header_stdc=yes
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+if test $ac_cv_header_stdc = yes; then
+ # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+cat > conftest.$ac_ext <<EOF
+#line 3058 "configure"
+#include "confdefs.h"
+#include <string.h>
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "memchr" >/dev/null 2>&1; then
+ :
+else
+ rm -rf conftest*
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+cat > conftest.$ac_ext <<EOF
+#line 3076 "configure"
+#include "confdefs.h"
+#include <stdlib.h>
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "free" >/dev/null 2>&1; then
+ :
+else
+ rm -rf conftest*
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+if test "$cross_compiling" = yes; then
+ :
+else
+ cat > conftest.$ac_ext <<EOF
+#line 3097 "configure"
+#include "confdefs.h"
+#include <ctype.h>
+#define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+#define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int main () { int i; for (i = 0; i < 256; i++)
+if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2);
+exit (0); }
+
+EOF
+if { (eval echo configure:3108: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+ :
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -fr conftest*
+ ac_cv_header_stdc=no
+fi
+rm -fr conftest*
+fi
+
+fi
+fi
+
+echo "$ac_t""$ac_cv_header_stdc" 1>&6
+if test $ac_cv_header_stdc = yes; then
+ cat >> confdefs.h <<\EOF
+#define STDC_HEADERS 1
+EOF
+
+fi
+
+
+for ac_hdr in ctype.h curses.h endian.h link.h \
+ memory.h objlist.h ptrace.h sgtty.h stddef.h stdlib.h \
+ string.h sys/procfs.h sys/ptrace.h sys/reg.h \
+ term.h termio.h termios.h unistd.h wait.h sys/wait.h \
+ wchar.h wctype.h asm/debugreg.h sys/debugreg.h
+do
+ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
+echo "configure:3140: checking for $ac_hdr" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 3145 "configure"
+#include "confdefs.h"
+#include <$ac_hdr>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:3150: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=yes"
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_hdr 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+echo $ac_n "checking whether stat file-mode macros are broken""... $ac_c" 1>&6
+echo "configure:3177: checking whether stat file-mode macros are broken" >&5
+if eval "test \"`echo '$''{'ac_cv_header_stat_broken'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 3182 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#if defined(S_ISBLK) && defined(S_IFDIR)
+# if S_ISBLK (S_IFDIR)
+You lose.
+# endif
+#endif
+
+#if defined(S_ISBLK) && defined(S_IFCHR)
+# if S_ISBLK (S_IFCHR)
+You lose.
+# endif
+#endif
+
+#if defined(S_ISLNK) && defined(S_IFREG)
+# if S_ISLNK (S_IFREG)
+You lose.
+# endif
+#endif
+
+#if defined(S_ISSOCK) && defined(S_IFREG)
+# if S_ISSOCK (S_IFREG)
+You lose.
+# endif
+#endif
+
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "You lose" >/dev/null 2>&1; then
+ rm -rf conftest*
+ ac_cv_header_stat_broken=yes
+else
+ rm -rf conftest*
+ ac_cv_header_stat_broken=no
+fi
+rm -f conftest*
+
+fi
+
+echo "$ac_t""$ac_cv_header_stat_broken" 1>&6
+if test $ac_cv_header_stat_broken = yes; then
+ cat >> confdefs.h <<\EOF
+#define STAT_MACROS_BROKEN 1
+EOF
+
+fi
+
+
+echo $ac_n "checking for working const""... $ac_c" 1>&6
+echo "configure:3234: checking for working const" >&5
+if eval "test \"`echo '$''{'ac_cv_c_const'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 3239 "configure"
+#include "confdefs.h"
+
+int main() {
+
+/* Ultrix mips cc rejects this. */
+typedef int charset[2]; const charset x;
+/* SunOS 4.1.1 cc rejects this. */
+char const *const *ccp;
+char **p;
+/* NEC SVR4.0.2 mips cc rejects this. */
+struct point {int x, y;};
+static struct point const zero = {0,0};
+/* AIX XL C 1.02.0.0 rejects this.
+ It does not let you subtract one const X* pointer from another in an arm
+ of an if-expression whose if-part is not a constant expression */
+const char *g = "string";
+ccp = &g + (g ? g-g : 0);
+/* HPUX 7.0 cc rejects these. */
+++ccp;
+p = (char**) ccp;
+ccp = (char const *const *) p;
+{ /* SCO 3.2v4 cc rejects this. */
+ char *t;
+ char const *s = 0 ? (char *) 0 : (char const *) 0;
+
+ *t++ = 0;
+}
+{ /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */
+ int x[] = {25, 17};
+ const int *foo = &x[0];
+ ++foo;
+}
+{ /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */
+ typedef const int *iptr;
+ iptr p = 0;
+ ++p;
+}
+{ /* AIX XL C 1.02.0.0 rejects this saying
+ "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */
+ struct s { int j; const int *ap[3]; };
+ struct s *b; b->j = 5;
+}
+{ /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */
+ const int foo = 10;
+}
+
+; return 0; }
+EOF
+if { (eval echo configure:3288: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_c_const=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_c_const=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_c_const" 1>&6
+if test $ac_cv_c_const = no; then
+ cat >> confdefs.h <<\EOF
+#define const
+EOF
+
+fi
+
+
+for ac_func in setpgid sbrk sigaction isascii bzero bcopy btowc
+do
+echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+echo "configure:3312: checking for $ac_func" >&5
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 3317 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $ac_func();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:3340: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_func 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+# The Ultrix 4.2 mips builtin alloca declared by alloca.h only works
+# for constant arguments. Useless!
+echo $ac_n "checking for working alloca.h""... $ac_c" 1>&6
+echo "configure:3367: checking for working alloca.h" >&5
+if eval "test \"`echo '$''{'ac_cv_header_alloca_h'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 3372 "configure"
+#include "confdefs.h"
+#include <alloca.h>
+int main() {
+char *p = alloca(2 * sizeof(int));
+; return 0; }
+EOF
+if { (eval echo configure:3379: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ ac_cv_header_alloca_h=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_header_alloca_h=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_header_alloca_h" 1>&6
+if test $ac_cv_header_alloca_h = yes; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_ALLOCA_H 1
+EOF
+
+fi
+
+echo $ac_n "checking for alloca""... $ac_c" 1>&6
+echo "configure:3400: checking for alloca" >&5
+if eval "test \"`echo '$''{'ac_cv_func_alloca_works'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 3405 "configure"
+#include "confdefs.h"
+
+#ifdef __GNUC__
+# define alloca __builtin_alloca
+#else
+# ifdef _MSC_VER
+# include <malloc.h>
+# define alloca _alloca
+# else
+# if HAVE_ALLOCA_H
+# include <alloca.h>
+# else
+# ifdef _AIX
+ #pragma alloca
+# else
+# ifndef alloca /* predefined by HP cc +Olibcalls */
+char *alloca ();
+# endif
+# endif
+# endif
+# endif
+#endif
+
+int main() {
+char *p = (char *) alloca(1);
+; return 0; }
+EOF
+if { (eval echo configure:3433: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ ac_cv_func_alloca_works=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_func_alloca_works=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_func_alloca_works" 1>&6
+if test $ac_cv_func_alloca_works = yes; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_ALLOCA 1
+EOF
+
+fi
+
+if test $ac_cv_func_alloca_works = no; then
+ # The SVR3 libPW and SVR4 libucb both contain incompatible functions
+ # that cause trouble. Some versions do not even contain alloca or
+ # contain a buggy version. If you still want to use their alloca,
+ # use ar to extract alloca.o from them instead of compiling alloca.c.
+ ALLOCA=alloca.${ac_objext}
+ cat >> confdefs.h <<\EOF
+#define C_ALLOCA 1
+EOF
+
+
+echo $ac_n "checking whether alloca needs Cray hooks""... $ac_c" 1>&6
+echo "configure:3465: checking whether alloca needs Cray hooks" >&5
+if eval "test \"`echo '$''{'ac_cv_os_cray'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 3470 "configure"
+#include "confdefs.h"
+#if defined(CRAY) && ! defined(CRAY2)
+webecray
+#else
+wenotbecray
+#endif
+
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "webecray" >/dev/null 2>&1; then
+ rm -rf conftest*
+ ac_cv_os_cray=yes
+else
+ rm -rf conftest*
+ ac_cv_os_cray=no
+fi
+rm -f conftest*
+
+fi
+
+echo "$ac_t""$ac_cv_os_cray" 1>&6
+if test $ac_cv_os_cray = yes; then
+for ac_func in _getb67 GETB67 getb67; do
+ echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+echo "configure:3495: checking for $ac_func" >&5
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 3500 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $ac_func();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:3523: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ cat >> confdefs.h <<EOF
+#define CRAY_STACKSEG_END $ac_func
+EOF
+
+ break
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+done
+fi
+
+echo $ac_n "checking stack direction for C alloca""... $ac_c" 1>&6
+echo "configure:3550: checking stack direction for C alloca" >&5
+if eval "test \"`echo '$''{'ac_cv_c_stack_direction'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test "$cross_compiling" = yes; then
+ ac_cv_c_stack_direction=0
+else
+ cat > conftest.$ac_ext <<EOF
+#line 3558 "configure"
+#include "confdefs.h"
+find_stack_direction ()
+{
+ static char *addr = 0;
+ auto char dummy;
+ if (addr == 0)
+ {
+ addr = &dummy;
+ return find_stack_direction ();
+ }
+ else
+ return (&dummy > addr) ? 1 : -1;
+}
+main ()
+{
+ exit (find_stack_direction() < 0);
+}
+EOF
+if { (eval echo configure:3577: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+ ac_cv_c_stack_direction=1
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -fr conftest*
+ ac_cv_c_stack_direction=-1
+fi
+rm -fr conftest*
+fi
+
+fi
+
+echo "$ac_t""$ac_cv_c_stack_direction" 1>&6
+cat >> confdefs.h <<EOF
+#define STACK_DIRECTION $ac_cv_c_stack_direction
+EOF
+
+fi
+
+
+echo $ac_n "checking whether malloc must be declared""... $ac_c" 1>&6
+echo "configure:3600: checking whether malloc must be declared" >&5
+if eval "test \"`echo '$''{'bfd_cv_decl_needed_malloc'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 3605 "configure"
+#include "confdefs.h"
+
+#include <stdio.h>
+#ifdef HAVE_STRING_H
+#include <string.h>
+#else
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+int main() {
+char *(*pfn) = (char *(*)) malloc
+; return 0; }
+EOF
+if { (eval echo configure:3626: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ bfd_cv_decl_needed_malloc=no
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ bfd_cv_decl_needed_malloc=yes
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$bfd_cv_decl_needed_malloc" 1>&6
+if test $bfd_cv_decl_needed_malloc = yes; then
+ cat >> confdefs.h <<\EOF
+#define NEED_DECLARATION_MALLOC 1
+EOF
+
+fi
+
+echo $ac_n "checking whether realloc must be declared""... $ac_c" 1>&6
+echo "configure:3647: checking whether realloc must be declared" >&5
+if eval "test \"`echo '$''{'bfd_cv_decl_needed_realloc'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 3652 "configure"
+#include "confdefs.h"
+
+#include <stdio.h>
+#ifdef HAVE_STRING_H
+#include <string.h>
+#else
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+int main() {
+char *(*pfn) = (char *(*)) realloc
+; return 0; }
+EOF
+if { (eval echo configure:3673: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ bfd_cv_decl_needed_realloc=no
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ bfd_cv_decl_needed_realloc=yes
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$bfd_cv_decl_needed_realloc" 1>&6
+if test $bfd_cv_decl_needed_realloc = yes; then
+ cat >> confdefs.h <<\EOF
+#define NEED_DECLARATION_REALLOC 1
+EOF
+
+fi
+
+echo $ac_n "checking whether free must be declared""... $ac_c" 1>&6
+echo "configure:3694: checking whether free must be declared" >&5
+if eval "test \"`echo '$''{'bfd_cv_decl_needed_free'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 3699 "configure"
+#include "confdefs.h"
+
+#include <stdio.h>
+#ifdef HAVE_STRING_H
+#include <string.h>
+#else
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+int main() {
+char *(*pfn) = (char *(*)) free
+; return 0; }
+EOF
+if { (eval echo configure:3720: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ bfd_cv_decl_needed_free=no
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ bfd_cv_decl_needed_free=yes
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$bfd_cv_decl_needed_free" 1>&6
+if test $bfd_cv_decl_needed_free = yes; then
+ cat >> confdefs.h <<\EOF
+#define NEED_DECLARATION_FREE 1
+EOF
+
+fi
+
+echo $ac_n "checking whether strerror must be declared""... $ac_c" 1>&6
+echo "configure:3741: checking whether strerror must be declared" >&5
+if eval "test \"`echo '$''{'bfd_cv_decl_needed_strerror'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 3746 "configure"
+#include "confdefs.h"
+
+#include <stdio.h>
+#ifdef HAVE_STRING_H
+#include <string.h>
+#else
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+int main() {
+char *(*pfn) = (char *(*)) strerror
+; return 0; }
+EOF
+if { (eval echo configure:3767: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ bfd_cv_decl_needed_strerror=no
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ bfd_cv_decl_needed_strerror=yes
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$bfd_cv_decl_needed_strerror" 1>&6
+if test $bfd_cv_decl_needed_strerror = yes; then
+ cat >> confdefs.h <<\EOF
+#define NEED_DECLARATION_STRERROR 1
+EOF
+
+fi
+
+echo $ac_n "checking whether strdup must be declared""... $ac_c" 1>&6
+echo "configure:3788: checking whether strdup must be declared" >&5
+if eval "test \"`echo '$''{'bfd_cv_decl_needed_strdup'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 3793 "configure"
+#include "confdefs.h"
+
+#include <stdio.h>
+#ifdef HAVE_STRING_H
+#include <string.h>
+#else
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+int main() {
+char *(*pfn) = (char *(*)) strdup
+; return 0; }
+EOF
+if { (eval echo configure:3814: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ bfd_cv_decl_needed_strdup=no
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ bfd_cv_decl_needed_strdup=yes
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$bfd_cv_decl_needed_strdup" 1>&6
+if test $bfd_cv_decl_needed_strdup = yes; then
+ cat >> confdefs.h <<\EOF
+#define NEED_DECLARATION_STRDUP 1
+EOF
+
+fi
+
+
+
+# The following save_state_t checkery is only necessary for HPUX
+# versions earlier than 10.20. When those fade from memory, this
+# could be expunged. --jsm 1999-03-22
+
+echo $ac_n "checking for HPUX save_state structure""... $ac_c" 1>&6
+echo "configure:3841: checking for HPUX save_state structure" >&5
+cat > conftest.$ac_ext <<EOF
+#line 3843 "configure"
+#include "confdefs.h"
+#include <machine/save_state.h>
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "save_state_t" >/dev/null 2>&1; then
+ rm -rf conftest*
+ gdb_cv_hpux_savestate=yes
+else
+ rm -rf conftest*
+ gdb_cv_hpux_savestate=no
+fi
+rm -f conftest*
+
+cat > conftest.$ac_ext <<EOF
+#line 3858 "configure"
+#include "confdefs.h"
+#include <machine/save_state.h>
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "ss_wide" >/dev/null 2>&1; then
+ rm -rf conftest*
+ gdb_cv_hpux_sswide=yes
+else
+ rm -rf conftest*
+ gdb_cv_hpux_sswide=no
+fi
+rm -f conftest*
+
+if test $gdb_cv_hpux_savestate = yes
+then
+ cat >> confdefs.h <<\EOF
+#define HAVE_STRUCT_SAVE_STATE_T 1
+EOF
+
+fi
+if test $gdb_cv_hpux_sswide = yes
+then
+ cat >> confdefs.h <<\EOF
+#define HAVE_STRUCT_MEMBER_SS_WIDE 1
+EOF
+
+fi
+echo "$ac_t""$gdb_cv_hpux_sswide" 1>&6
+
+
+# If we are configured native on GNU/Linux, work around problems with
+# sys/procfs.h
+# Also detect which type of /proc is in use, such as for Unixware.
+
+if test "${target}" = "${host}"; then
+ case "${host}" in
+ i[3456]86-*-linux*)
+ cat >> confdefs.h <<\EOF
+#define START_INFERIOR_TRAPS_EXPECTED 2
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define sys_quotactl 1
+EOF
+
+ ;;
+ esac
+ echo $ac_n "checking for directory proc entries""... $ac_c" 1>&6
+echo "configure:3907: checking for directory proc entries" >&5
+# The [gdb_host != sun4sol2] hack is because Solaris does provide the
+# multiple procfs files as of Solaris 2.6, but GDB can't use it right now.
+ if test "$ac_cv_header_sys_procfs_h" = yes -a "$gdb_host" != sun4sol2 \
+ -a -d /proc/$$ \
+ -a -f /proc/$$/ctl \
+ -a -f /proc/$$/as \
+ -a -f /proc/$$/map \
+ -a -f /proc/$$/status; then
+ echo "$ac_t""yes" 1>&6
+ cat >> confdefs.h <<\EOF
+#define HAVE_MULTIPLE_PROC_FDS 1
+EOF
+
+ else
+ echo "$ac_t""no" 1>&6
+ fi
+fi
+
+if test "$ac_cv_header_sys_procfs_h" = yes; then
+ echo $ac_n "checking for pstatus_t in sys/procfs.h""... $ac_c" 1>&6
+echo "configure:3928: checking for pstatus_t in sys/procfs.h" >&5
+ if eval "test \"`echo '$''{'bfd_cv_have_sys_procfs_type_pstatus_t'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 3933 "configure"
+#include "confdefs.h"
+#include <sys/procfs.h>
+int main() {
+pstatus_t avar
+; return 0; }
+EOF
+if { (eval echo configure:3940: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ bfd_cv_have_sys_procfs_type_pstatus_t=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ bfd_cv_have_sys_procfs_type_pstatus_t=no
+
+fi
+rm -f conftest*
+fi
+
+ if test $bfd_cv_have_sys_procfs_type_pstatus_t = yes; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_PSTATUS_T 1
+EOF
+
+ fi
+ echo "$ac_t""$bfd_cv_have_sys_procfs_type_pstatus_t" 1>&6
+
+ echo $ac_n "checking for prrun_t in sys/procfs.h""... $ac_c" 1>&6
+echo "configure:3962: checking for prrun_t in sys/procfs.h" >&5
+ if eval "test \"`echo '$''{'bfd_cv_have_sys_procfs_type_prrun_t'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 3967 "configure"
+#include "confdefs.h"
+#include <sys/procfs.h>
+int main() {
+prrun_t avar
+; return 0; }
+EOF
+if { (eval echo configure:3974: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ bfd_cv_have_sys_procfs_type_prrun_t=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ bfd_cv_have_sys_procfs_type_prrun_t=no
+
+fi
+rm -f conftest*
+fi
+
+ if test $bfd_cv_have_sys_procfs_type_prrun_t = yes; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_PRRUN_T 1
+EOF
+
+ fi
+ echo "$ac_t""$bfd_cv_have_sys_procfs_type_prrun_t" 1>&6
+
+ echo $ac_n "checking for gregset_t in sys/procfs.h""... $ac_c" 1>&6
+echo "configure:3996: checking for gregset_t in sys/procfs.h" >&5
+ if eval "test \"`echo '$''{'bfd_cv_have_sys_procfs_type_gregset_t'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 4001 "configure"
+#include "confdefs.h"
+#include <sys/procfs.h>
+int main() {
+gregset_t avar
+; return 0; }
+EOF
+if { (eval echo configure:4008: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ bfd_cv_have_sys_procfs_type_gregset_t=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ bfd_cv_have_sys_procfs_type_gregset_t=no
+
+fi
+rm -f conftest*
+fi
+
+ if test $bfd_cv_have_sys_procfs_type_gregset_t = yes; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_GREGSET_T 1
+EOF
+
+ fi
+ echo "$ac_t""$bfd_cv_have_sys_procfs_type_gregset_t" 1>&6
+
+ echo $ac_n "checking for fpregset_t in sys/procfs.h""... $ac_c" 1>&6
+echo "configure:4030: checking for fpregset_t in sys/procfs.h" >&5
+ if eval "test \"`echo '$''{'bfd_cv_have_sys_procfs_type_fpregset_t'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 4035 "configure"
+#include "confdefs.h"
+#include <sys/procfs.h>
+int main() {
+fpregset_t avar
+; return 0; }
+EOF
+if { (eval echo configure:4042: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ bfd_cv_have_sys_procfs_type_fpregset_t=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ bfd_cv_have_sys_procfs_type_fpregset_t=no
+
+fi
+rm -f conftest*
+fi
+
+ if test $bfd_cv_have_sys_procfs_type_fpregset_t = yes; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_FPREGSET_T 1
+EOF
+
+ fi
+ echo "$ac_t""$bfd_cv_have_sys_procfs_type_fpregset_t" 1>&6
+
+
+
+ echo $ac_n "checking for PIOCSET ioctl entry in sys/procfs.h""... $ac_c" 1>&6
+echo "configure:4066: checking for PIOCSET ioctl entry in sys/procfs.h" >&5
+ if eval "test \"`echo '$''{'gdb_cv_have_procfs_piocset'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 4071 "configure"
+#include "confdefs.h"
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/procfs.h>
+
+int main() {
+
+ int dummy;;
+ dummy = ioctl(0, PIOCSET, &dummy);
+
+; return 0; }
+EOF
+if { (eval echo configure:4084: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ gdb_cv_have_procfs_piocset=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ gdb_cv_have_procfs_piocset=no
+fi
+rm -f conftest*
+fi
+
+ echo "$ac_t""$gdb_cv_have_procfs_piocset" 1>&6
+ if test $gdb_cv_have_procfs_piocset = yes; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_PROCFS_PIOCSET 1
+EOF
+
+ fi
+fi
+
+echo $ac_n "checking for main in -lm""... $ac_c" 1>&6
+echo "configure:4106: checking for main in -lm" >&5
+ac_lib_var=`echo m'_'main | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lm $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 4114 "configure"
+#include "confdefs.h"
+
+int main() {
+main()
+; return 0; }
+EOF
+if { (eval echo configure:4121: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_lib=HAVE_LIB`echo m | sed -e 's/[^a-zA-Z0-9_]/_/g' \
+ -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_lib 1
+EOF
+
+ LIBS="-lm $LIBS"
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+
+echo $ac_n "checking for wctype in -lc""... $ac_c" 1>&6
+echo "configure:4150: checking for wctype in -lc" >&5
+ac_lib_var=`echo c'_'wctype | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lc $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 4158 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char wctype();
+
+int main() {
+wctype()
+; return 0; }
+EOF
+if { (eval echo configure:4169: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ :
+else
+ echo "$ac_t""no" 1>&6
+echo $ac_n "checking for wctype in -lw""... $ac_c" 1>&6
+echo "configure:4188: checking for wctype in -lw" >&5
+ac_lib_var=`echo w'_'wctype | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lw $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 4196 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char wctype();
+
+int main() {
+wctype()
+; return 0; }
+EOF
+if { (eval echo configure:4207: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_lib=HAVE_LIB`echo w | sed -e 's/^a-zA-Z0-9_/_/g' \
+ -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_lib 1
+EOF
+
+ LIBS="-lw $LIBS"
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+fi
+
+
+
+echo $ac_n "checking for long long support in compiler""... $ac_c" 1>&6
+echo "configure:4239: checking for long long support in compiler" >&5
+if eval "test \"`echo '$''{'gdb_cv_c_long_long'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 4244 "configure"
+#include "confdefs.h"
+
+int main() {
+
+ extern long long foo;
+ switch (foo & 2) { case 0: return 1; }
+
+; return 0; }
+EOF
+if { (eval echo configure:4254: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ gdb_cv_c_long_long=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ gdb_cv_c_long_long=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$gdb_cv_c_long_long" 1>&6
+if test $gdb_cv_c_long_long = yes; then
+ cat >> confdefs.h <<\EOF
+#define CC_HAS_LONG_LONG 1
+EOF
+
+fi
+
+
+echo $ac_n "checking for long long support in printf""... $ac_c" 1>&6
+echo "configure:4276: checking for long long support in printf" >&5
+if eval "test \"`echo '$''{'gdb_cv_printf_has_long_long'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test "$cross_compiling" = yes; then
+ gdb_cv_printf_has_long_long=no
+else
+ cat > conftest.$ac_ext <<EOF
+#line 4284 "configure"
+#include "confdefs.h"
+
+int main () {
+ char buf[32];
+ long long l = 0;
+ l = (l << 16) + 0x0123;
+ l = (l << 16) + 0x4567;
+ l = (l << 16) + 0x89ab;
+ l = (l << 16) + 0xcdef;
+ sprintf (buf, "0x%016llx", l);
+ return (strcmp ("0x0123456789abcdef", buf));
+}
+EOF
+if { (eval echo configure:4298: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+ gdb_cv_printf_has_long_long=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -fr conftest*
+ gdb_cv_printf_has_long_long=no
+fi
+rm -fr conftest*
+fi
+
+fi
+
+if test $gdb_cv_printf_has_long_long = yes; then
+ cat >> confdefs.h <<\EOF
+#define PRINTF_HAS_LONG_LONG 1
+EOF
+
+fi
+echo "$ac_t""$gdb_cv_printf_has_long_long" 1>&6
+
+
+echo $ac_n "checking for long double support in compiler""... $ac_c" 1>&6
+echo "configure:4322: checking for long double support in compiler" >&5
+if eval "test \"`echo '$''{'ac_cv_c_long_double'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 4327 "configure"
+#include "confdefs.h"
+
+int main() {
+long double foo;
+; return 0; }
+EOF
+if { (eval echo configure:4334: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_c_long_double=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_c_long_double=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_c_long_double" 1>&6
+if test $ac_cv_c_long_double = yes; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_LONG_DOUBLE 1
+EOF
+
+fi
+
+
+echo $ac_n "checking for long double support in printf""... $ac_c" 1>&6
+echo "configure:4356: checking for long double support in printf" >&5
+if eval "test \"`echo '$''{'gdb_cv_printf_has_long_double'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test "$cross_compiling" = yes; then
+ gdb_cv_printf_has_long_double=no
+else
+ cat > conftest.$ac_ext <<EOF
+#line 4364 "configure"
+#include "confdefs.h"
+
+int main () {
+ char buf[16];
+ long double f = 3.141592653;
+ sprintf (buf, "%Lg", f);
+ return (strncmp ("3.14159", buf, 7));
+}
+EOF
+if { (eval echo configure:4374: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+ gdb_cv_printf_has_long_double=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -fr conftest*
+ gdb_cv_printf_has_long_double=no
+fi
+rm -fr conftest*
+fi
+
+fi
+
+if test $gdb_cv_printf_has_long_double = yes; then
+ cat >> confdefs.h <<\EOF
+#define PRINTF_HAS_LONG_DOUBLE 1
+EOF
+
+fi
+echo "$ac_t""$gdb_cv_printf_has_long_double" 1>&6
+
+
+echo $ac_n "checking for long double support in scanf""... $ac_c" 1>&6
+echo "configure:4398: checking for long double support in scanf" >&5
+if eval "test \"`echo '$''{'gdb_cv_scanf_has_long_double'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test "$cross_compiling" = yes; then
+ gdb_cv_scanf_has_long_double=no
+else
+ cat > conftest.$ac_ext <<EOF
+#line 4406 "configure"
+#include "confdefs.h"
+
+int main () {
+ char *buf = "3.141592653";
+ long double f = 0;
+ sscanf (buf, "%Lg", &f);
+ return !(f > 3.14159 && f < 3.14160);
+}
+EOF
+if { (eval echo configure:4416: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+ gdb_cv_scanf_has_long_double=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -fr conftest*
+ gdb_cv_scanf_has_long_double=no
+fi
+rm -fr conftest*
+fi
+
+fi
+
+if test $gdb_cv_scanf_has_long_double = yes; then
+ cat >> confdefs.h <<\EOF
+#define SCANF_HAS_LONG_DOUBLE 1
+EOF
+
+fi
+echo "$ac_t""$gdb_cv_scanf_has_long_double" 1>&6
+
+for ac_hdr in unistd.h
+do
+ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
+echo "configure:4442: checking for $ac_hdr" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 4447 "configure"
+#include "confdefs.h"
+#include <$ac_hdr>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:4452: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=yes"
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_hdr 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+for ac_func in getpagesize
+do
+echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+echo "configure:4481: checking for $ac_func" >&5
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 4486 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $ac_func();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:4509: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_func 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+echo $ac_n "checking for working mmap""... $ac_c" 1>&6
+echo "configure:4534: checking for working mmap" >&5
+if eval "test \"`echo '$''{'ac_cv_func_mmap_fixed_mapped'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test "$cross_compiling" = yes; then
+ ac_cv_func_mmap_fixed_mapped=no
+else
+ cat > conftest.$ac_ext <<EOF
+#line 4542 "configure"
+#include "confdefs.h"
+
+/* Thanks to Mike Haertel and Jim Avera for this test.
+ Here is a matrix of mmap possibilities:
+ mmap private not fixed
+ mmap private fixed at somewhere currently unmapped
+ mmap private fixed at somewhere already mapped
+ mmap shared not fixed
+ mmap shared fixed at somewhere currently unmapped
+ mmap shared fixed at somewhere already mapped
+ For private mappings, we should verify that changes cannot be read()
+ back from the file, nor mmap's back from the file at a different
+ address. (There have been systems where private was not correctly
+ implemented like the infamous i386 svr4.0, and systems where the
+ VM page cache was not coherent with the filesystem buffer cache
+ like early versions of FreeBSD and possibly contemporary NetBSD.)
+ For shared mappings, we should conversely verify that changes get
+ propogated back to all the places they're supposed to be.
+
+ Grep wants private fixed already mapped.
+ The main things grep needs to know about mmap are:
+ * does it exist and is it safe to write into the mmap'd area
+ * how to use it (BSD variants) */
+#include <sys/types.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+
+/* This mess was copied from the GNU getpagesize.h. */
+#ifndef HAVE_GETPAGESIZE
+# ifdef HAVE_UNISTD_H
+# include <unistd.h>
+# endif
+
+/* Assume that all systems that can run configure have sys/param.h. */
+# ifndef HAVE_SYS_PARAM_H
+# define HAVE_SYS_PARAM_H 1
+# endif
+
+# ifdef _SC_PAGESIZE
+# define getpagesize() sysconf(_SC_PAGESIZE)
+# else /* no _SC_PAGESIZE */
+# ifdef HAVE_SYS_PARAM_H
+# include <sys/param.h>
+# ifdef EXEC_PAGESIZE
+# define getpagesize() EXEC_PAGESIZE
+# else /* no EXEC_PAGESIZE */
+# ifdef NBPG
+# define getpagesize() NBPG * CLSIZE
+# ifndef CLSIZE
+# define CLSIZE 1
+# endif /* no CLSIZE */
+# else /* no NBPG */
+# ifdef NBPC
+# define getpagesize() NBPC
+# else /* no NBPC */
+# ifdef PAGESIZE
+# define getpagesize() PAGESIZE
+# endif /* PAGESIZE */
+# endif /* no NBPC */
+# endif /* no NBPG */
+# endif /* no EXEC_PAGESIZE */
+# else /* no HAVE_SYS_PARAM_H */
+# define getpagesize() 8192 /* punt totally */
+# endif /* no HAVE_SYS_PARAM_H */
+# endif /* no _SC_PAGESIZE */
+
+#endif /* no HAVE_GETPAGESIZE */
+
+#ifdef __cplusplus
+extern "C" { void *malloc(unsigned); }
+#else
+char *malloc();
+#endif
+
+int
+main()
+{
+ char *data, *data2, *data3;
+ int i, pagesize;
+ int fd;
+
+ pagesize = getpagesize();
+
+ /*
+ * First, make a file with some known garbage in it.
+ */
+ data = malloc(pagesize);
+ if (!data)
+ exit(1);
+ for (i = 0; i < pagesize; ++i)
+ *(data + i) = rand();
+ umask(0);
+ fd = creat("conftestmmap", 0600);
+ if (fd < 0)
+ exit(1);
+ if (write(fd, data, pagesize) != pagesize)
+ exit(1);
+ close(fd);
+
+ /*
+ * Next, try to mmap the file at a fixed address which
+ * already has something else allocated at it. If we can,
+ * also make sure that we see the same garbage.
+ */
+ fd = open("conftestmmap", O_RDWR);
+ if (fd < 0)
+ exit(1);
+ data2 = malloc(2 * pagesize);
+ if (!data2)
+ exit(1);
+ data2 += (pagesize - ((int) data2 & (pagesize - 1))) & (pagesize - 1);
+ if (data2 != mmap(data2, pagesize, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_FIXED, fd, 0L))
+ exit(1);
+ for (i = 0; i < pagesize; ++i)
+ if (*(data + i) != *(data2 + i))
+ exit(1);
+
+ /*
+ * Finally, make sure that changes to the mapped area
+ * do not percolate back to the file as seen by read().
+ * (This is a bug on some variants of i386 svr4.0.)
+ */
+ for (i = 0; i < pagesize; ++i)
+ *(data2 + i) = *(data2 + i) + 1;
+ data3 = malloc(pagesize);
+ if (!data3)
+ exit(1);
+ if (read(fd, data3, pagesize) != pagesize)
+ exit(1);
+ for (i = 0; i < pagesize; ++i)
+ if (*(data + i) != *(data3 + i))
+ exit(1);
+ close(fd);
+ unlink("conftestmmap");
+ exit(0);
+}
+
+EOF
+if { (eval echo configure:4682: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+ ac_cv_func_mmap_fixed_mapped=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -fr conftest*
+ ac_cv_func_mmap_fixed_mapped=no
+fi
+rm -fr conftest*
+fi
+
+fi
+
+echo "$ac_t""$ac_cv_func_mmap_fixed_mapped" 1>&6
+if test $ac_cv_func_mmap_fixed_mapped = yes; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_MMAP 1
+EOF
+
+fi
+
+
+
+
+if test ${build} = ${host} -a ${host} = ${target} ; then
+ case ${host_os} in
+ hpux*)
+ echo $ac_n "checking for HPUX/OSF thread support""... $ac_c" 1>&6
+echo "configure:4711: checking for HPUX/OSF thread support" >&5
+ if test -f /usr/include/dce/cma_config.h ; then
+ if test "$GCC" = "yes" ; then
+ echo "$ac_t""yes" 1>&6
+ cat >> confdefs.h <<\EOF
+#define HAVE_HPUX_THREAD_SUPPORT 1
+EOF
+
+ CONFIG_OBS="${CONFIG_OJS} hpux-thread.o"
+ CONFIG_SRCS="${CONFIG_SRCS} hpux-thread.c"
+ else
+ echo "$ac_t""no (suppressed because you are not using GCC)" 1>&6
+ fi
+ else
+ echo "$ac_t""no" 1>&6
+ fi
+ ;;
+ solaris*)
+ echo $ac_n "checking for Solaris thread debugging library""... $ac_c" 1>&6
+echo "configure:4730: checking for Solaris thread debugging library" >&5
+ if test -f /usr/lib/libthread_db.so.1 ; then
+ echo "$ac_t""yes" 1>&6
+ cat >> confdefs.h <<\EOF
+#define HAVE_THREAD_DB_LIB 1
+EOF
+
+ CONFIG_OBS="${CONFIG_OBS} sol-thread.o"
+ CONFIG_SRCS="${CONFIG_SRCS} sol-thread.c"
+ echo $ac_n "checking for dlopen in -ldl""... $ac_c" 1>&6
+echo "configure:4740: checking for dlopen in -ldl" >&5
+ac_lib_var=`echo dl'_'dlopen | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-ldl $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 4748 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char dlopen();
+
+int main() {
+dlopen()
+; return 0; }
+EOF
+if { (eval echo configure:4759: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_lib=HAVE_LIB`echo dl | sed -e 's/[^a-zA-Z0-9_]/_/g' \
+ -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_lib 1
+EOF
+
+ LIBS="-ldl $LIBS"
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ if test "$GCC" = "yes" ; then
+ # The GNU linker requires the -export-dynamic option to make
+ # all symbols visible in the dynamic symbol table.
+ hold_ldflags=$LDFLAGS
+ echo $ac_n "checking for the ld -export-dynamic flag""... $ac_c" 1>&6
+echo "configure:4791: checking for the ld -export-dynamic flag" >&5
+ LDFLAGS="${LDFLAGS} -Wl,-export-dynamic"
+ cat > conftest.$ac_ext <<EOF
+#line 4794 "configure"
+#include "confdefs.h"
+
+int main() {
+int i;
+; return 0; }
+EOF
+if { (eval echo configure:4801: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ found=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ found=no
+fi
+rm -f conftest*
+ LDFLAGS=$hold_ldflags
+ echo "$ac_t""$found" 1>&6
+ if test $found = yes; then
+ CONFIG_LDFLAGS="${CONFIG_LDFLAGS} -Wl,-export-dynamic"
+ fi
+ fi
+ # Sun randomly tweaked the prototypes in <proc_service.h>
+ # at one point.
+ echo $ac_n "checking if <proc_service.h> is old""... $ac_c" 1>&6
+echo "configure:4820: checking if <proc_service.h> is old" >&5
+ if eval "test \"`echo '$''{'gdb_cv_proc_service_is_old'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+
+ cat > conftest.$ac_ext <<EOF
+#line 4826 "configure"
+#include "confdefs.h"
+
+ #include <proc_service.h>
+ ps_err_e ps_pdwrite
+ (struct ps_prochandle*, psaddr_t, const void*, size_t);
+
+int main() {
+
+; return 0; }
+EOF
+if { (eval echo configure:4837: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ gdb_cv_proc_service_is_old=no
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ gdb_cv_proc_service_is_old=yes
+fi
+rm -f conftest*
+
+fi
+
+ echo "$ac_t""$gdb_cv_proc_service_is_old" 1>&6
+ if test $gdb_cv_proc_service_is_old = yes; then
+ cat >> confdefs.h <<\EOF
+#define PROC_SERVICE_IS_OLD 1
+EOF
+
+ fi
+ else
+ echo "$ac_t""no" 1>&6
+ fi
+ ;;
+ esac
+
+fi
+
+ENABLE_CFLAGS=
+
+# Check whether --enable-tui or --disable-tui was given.
+if test "${enable_tui+set}" = set; then
+ enableval="$enable_tui"
+
+ case "${enable_tui}" in
+ yes | no) ;;
+ "") enable_tui=yes ;;
+ *)
+ { echo "configure: error: Bad value for --enable-tui: ${enableval}" 1>&2; exit 1; }
+ ;;
+ esac
+
+fi
+
+case ${enable_tui} in
+ "yes" )
+ cat >> confdefs.h <<\EOF
+#define TUI 1
+EOF
+
+ BUILD_TUI=all-tui
+ TUI_LIBRARY=tui/libtui.a
+ ;;
+ * )
+ BUILD_TUI=
+ TUI_LIBRARY=
+ ;;
+esac
+
+
+
+# Check whether --enable-netrom or --disable-netrom was given.
+if test "${enable_netrom+set}" = set; then
+ enableval="$enable_netrom"
+ case "${enableval}" in
+yes) enable_netrom=yes ;;
+no) enable_netrom=no ;;
+*) { echo "configure: error: bad value ${enableval} given for netrom option" 1>&2; exit 1; } ;;
+esac
+fi
+
+
+if test "${enable_netrom}" = "yes"; then
+ CONFIG_OBS="${CONFIG_OBS} remote-nrom.o"
+ CONFIG_SRCS="${CONFIG_SRCS} remote-nrom.c"
+fi
+
+# Check whether --enable-build-warnings or --disable-build-warnings was given.
+if test "${enable_build_warnings+set}" = set; then
+ enableval="$enable_build_warnings"
+ build_warnings="-Wall -Wpointer-arith -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations"
+case "${enableval}" in
+ yes) ;;
+ no) build_warnings="-w";;
+ ,*) t=`echo "${enableval}" | sed -e "s/,/ /g"`
+ build_warnings="${build_warnings} ${t}";;
+ *,) t=`echo "${enableval}" | sed -e "s/,/ /g"`
+ build_warnings="${t} ${build_warnings}";;
+ *) build_warnings=`echo "${enableval}" | sed -e "s/,/ /g"`;;
+esac
+else
+ build_warnings=""
+fi
+
+if test "x${build_warnings}" != x -a "x$GCC" = xyes
+then
+ WARN_CFLAGS="${build_warnings}"
+else
+ WARN_CFLAGS=""
+fi
+
+
+MMALLOC_CFLAGS=
+MMALLOC=
+
+
+
+# Check whether --with-mmalloc or --without-mmalloc was given.
+if test "${with_mmalloc+set}" = set; then
+ withval="$with_mmalloc"
+ case "${withval}" in
+ yes) want_mmalloc=true ;;
+ no) want_mmalloc=false;;
+ *) { echo "configure: error: bad value ${withval} for GDB with-mmalloc option" 1>&2; exit 1; } ;;
+esac
+else
+ want_mmalloc=false
+fi
+
+if test x$want_mmalloc = xtrue; then
+ cat >> confdefs.h <<\EOF
+#define USE_MMALLOC 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define MMCHECK_FORCE 1
+EOF
+
+ MMALLOC_CFLAGS="-I$srcdir/../mmalloc"
+ MMALLOC='../mmalloc/libmmalloc.a'
+fi
+
+if test x$gdb_cv_os_cygwin = xyes; then
+ TERM_LIB='`if test -r ../libtermcap/libtermcap.a; then echo ../libtermcap/libtermcap.a; else echo -ltermcap; fi`'
+else
+ TERM_LIB=
+ echo $ac_n "checking for tgetent in -lncurses""... $ac_c" 1>&6
+echo "configure:4974: checking for tgetent in -lncurses" >&5
+ac_lib_var=`echo ncurses'_'tgetent | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lncurses $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 4982 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char tgetent();
+
+int main() {
+tgetent()
+; return 0; }
+EOF
+if { (eval echo configure:4993: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ TERM_LIB=-lncurses
+else
+ echo "$ac_t""no" 1>&6
+echo $ac_n "checking for tgetent in -lHcurses""... $ac_c" 1>&6
+echo "configure:5012: checking for tgetent in -lHcurses" >&5
+ac_lib_var=`echo Hcurses'_'tgetent | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lHcurses $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 5020 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char tgetent();
+
+int main() {
+tgetent()
+; return 0; }
+EOF
+if { (eval echo configure:5031: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ TERM_LIB=-lHcurses
+else
+ echo "$ac_t""no" 1>&6
+echo $ac_n "checking for tgetent in -ltermlib""... $ac_c" 1>&6
+echo "configure:5050: checking for tgetent in -ltermlib" >&5
+ac_lib_var=`echo termlib'_'tgetent | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-ltermlib $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 5058 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char tgetent();
+
+int main() {
+tgetent()
+; return 0; }
+EOF
+if { (eval echo configure:5069: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ TERM_LIB=-ltermlib
+else
+ echo "$ac_t""no" 1>&6
+echo $ac_n "checking for tgetent in -ltermcap""... $ac_c" 1>&6
+echo "configure:5088: checking for tgetent in -ltermcap" >&5
+ac_lib_var=`echo termcap'_'tgetent | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-ltermcap $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 5096 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char tgetent();
+
+int main() {
+tgetent()
+; return 0; }
+EOF
+if { (eval echo configure:5107: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ TERM_LIB=-ltermcap
+else
+ echo "$ac_t""no" 1>&6
+echo $ac_n "checking for tgetent in -lcurses""... $ac_c" 1>&6
+echo "configure:5126: checking for tgetent in -lcurses" >&5
+ac_lib_var=`echo curses'_'tgetent | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lcurses $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 5134 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char tgetent();
+
+int main() {
+tgetent()
+; return 0; }
+EOF
+if { (eval echo configure:5145: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ TERM_LIB=-lcurses
+else
+ echo "$ac_t""no" 1>&6
+echo $ac_n "checking for tgetent in -lterminfo""... $ac_c" 1>&6
+echo "configure:5164: checking for tgetent in -lterminfo" >&5
+ac_lib_var=`echo terminfo'_'tgetent | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lterminfo $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 5172 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char tgetent();
+
+int main() {
+tgetent()
+; return 0; }
+EOF
+if { (eval echo configure:5183: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ TERM_LIB=-lterminfo
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+fi
+
+fi
+
+fi
+
+fi
+
+fi
+
+
+ if test "x$TERM_LIB" = x
+ then
+ { echo "configure: error: Could not find a term library" 1>&2; exit 1; }
+ fi
+fi
+
+
+
+# If we find X, set shell vars x_includes and x_libraries to the
+# paths, otherwise set no_x=yes.
+# Uses ac_ vars as temps to allow command line to override cache and checks.
+# --without-x overrides everything else, but does not touch the cache.
+echo $ac_n "checking for X""... $ac_c" 1>&6
+echo "configure:5227: checking for X" >&5
+
+# Check whether --with-x or --without-x was given.
+if test "${with_x+set}" = set; then
+ withval="$with_x"
+ :
+fi
+
+# $have_x is `yes', `no', `disabled', or empty when we do not yet know.
+if test "x$with_x" = xno; then
+ # The user explicitly disabled X.
+ have_x=disabled
+else
+ if test "x$x_includes" != xNONE && test "x$x_libraries" != xNONE; then
+ # Both variables are already set.
+ have_x=yes
+ else
+if eval "test \"`echo '$''{'ac_cv_have_x'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ # One or both of the vars are not set, and there is no cached value.
+ac_x_includes=NO ac_x_libraries=NO
+rm -fr conftestdir
+if mkdir conftestdir; then
+ cd conftestdir
+ # Make sure to not put "make" in the Imakefile rules, since we grep it out.
+ cat > Imakefile <<'EOF'
+acfindx:
+ @echo 'ac_im_incroot="${INCROOT}"; ac_im_usrlibdir="${USRLIBDIR}"; ac_im_libdir="${LIBDIR}"'
+EOF
+ if (xmkmf) >/dev/null 2>/dev/null && test -f Makefile; then
+ # GNU make sometimes prints "make[1]: Entering...", which would confuse us.
+ eval `${MAKE-make} acfindx 2>/dev/null | grep -v make`
+ # Open Windows xmkmf reportedly sets LIBDIR instead of USRLIBDIR.
+ for ac_extension in a so sl; do
+ if test ! -f $ac_im_usrlibdir/libX11.$ac_extension &&
+ test -f $ac_im_libdir/libX11.$ac_extension; then
+ ac_im_usrlibdir=$ac_im_libdir; break
+ fi
+ done
+ # Screen out bogus values from the imake configuration. They are
+ # bogus both because they are the default anyway, and because
+ # using them would break gcc on systems where it needs fixed includes.
+ case "$ac_im_incroot" in
+ /usr/include) ;;
+ *) test -f "$ac_im_incroot/X11/Xos.h" && ac_x_includes="$ac_im_incroot" ;;
+ esac
+ case "$ac_im_usrlibdir" in
+ /usr/lib | /lib) ;;
+ *) test -d "$ac_im_usrlibdir" && ac_x_libraries="$ac_im_usrlibdir" ;;
+ esac
+ fi
+ cd ..
+ rm -fr conftestdir
+fi
+
+if test "$ac_x_includes" = NO; then
+ # Guess where to find include files, by looking for this one X11 .h file.
+ test -z "$x_direct_test_include" && x_direct_test_include=X11/Intrinsic.h
+
+ # First, try using that file with no special directory specified.
+cat > conftest.$ac_ext <<EOF
+#line 5289 "configure"
+#include "confdefs.h"
+#include <$x_direct_test_include>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:5294: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ # We can compile using X headers with no special include directory.
+ac_x_includes=
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ # Look for the header file in a standard set of common directories.
+# Check X11 before X11Rn because it is often a symlink to the current release.
+ for ac_dir in \
+ /usr/X11/include \
+ /usr/X11R6/include \
+ /usr/X11R5/include \
+ /usr/X11R4/include \
+ \
+ /usr/include/X11 \
+ /usr/include/X11R6 \
+ /usr/include/X11R5 \
+ /usr/include/X11R4 \
+ \
+ /usr/local/X11/include \
+ /usr/local/X11R6/include \
+ /usr/local/X11R5/include \
+ /usr/local/X11R4/include \
+ \
+ /usr/local/include/X11 \
+ /usr/local/include/X11R6 \
+ /usr/local/include/X11R5 \
+ /usr/local/include/X11R4 \
+ \
+ /usr/X386/include \
+ /usr/x386/include \
+ /usr/XFree86/include/X11 \
+ \
+ /usr/include \
+ /usr/local/include \
+ /usr/unsupported/include \
+ /usr/athena/include \
+ /usr/local/x11r5/include \
+ /usr/lpp/Xamples/include \
+ \
+ /usr/openwin/include \
+ /usr/openwin/share/include \
+ ; \
+ do
+ if test -r "$ac_dir/$x_direct_test_include"; then
+ ac_x_includes=$ac_dir
+ break
+ fi
+ done
+fi
+rm -f conftest*
+fi # $ac_x_includes = NO
+
+if test "$ac_x_libraries" = NO; then
+ # Check for the libraries.
+
+ test -z "$x_direct_test_library" && x_direct_test_library=Xt
+ test -z "$x_direct_test_function" && x_direct_test_function=XtMalloc
+
+ # See if we find them without any special options.
+ # Don't add to $LIBS permanently.
+ ac_save_LIBS="$LIBS"
+ LIBS="-l$x_direct_test_library $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 5363 "configure"
+#include "confdefs.h"
+
+int main() {
+${x_direct_test_function}()
+; return 0; }
+EOF
+if { (eval echo configure:5370: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ LIBS="$ac_save_LIBS"
+# We can link X programs with no special library path.
+ac_x_libraries=
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ LIBS="$ac_save_LIBS"
+# First see if replacing the include by lib works.
+# Check X11 before X11Rn because it is often a symlink to the current release.
+for ac_dir in `echo "$ac_x_includes" | sed s/include/lib/` \
+ /usr/X11/lib \
+ /usr/X11R6/lib \
+ /usr/X11R5/lib \
+ /usr/X11R4/lib \
+ \
+ /usr/lib/X11 \
+ /usr/lib/X11R6 \
+ /usr/lib/X11R5 \
+ /usr/lib/X11R4 \
+ \
+ /usr/local/X11/lib \
+ /usr/local/X11R6/lib \
+ /usr/local/X11R5/lib \
+ /usr/local/X11R4/lib \
+ \
+ /usr/local/lib/X11 \
+ /usr/local/lib/X11R6 \
+ /usr/local/lib/X11R5 \
+ /usr/local/lib/X11R4 \
+ \
+ /usr/X386/lib \
+ /usr/x386/lib \
+ /usr/XFree86/lib/X11 \
+ \
+ /usr/lib \
+ /usr/local/lib \
+ /usr/unsupported/lib \
+ /usr/athena/lib \
+ /usr/local/x11r5/lib \
+ /usr/lpp/Xamples/lib \
+ /lib/usr/lib/X11 \
+ \
+ /usr/openwin/lib \
+ /usr/openwin/share/lib \
+ ; \
+do
+ for ac_extension in a so sl; do
+ if test -r $ac_dir/lib${x_direct_test_library}.$ac_extension; then
+ ac_x_libraries=$ac_dir
+ break 2
+ fi
+ done
+done
+fi
+rm -f conftest*
+fi # $ac_x_libraries = NO
+
+if test "$ac_x_includes" = NO || test "$ac_x_libraries" = NO; then
+ # Didn't find X anywhere. Cache the known absence of X.
+ ac_cv_have_x="have_x=no"
+else
+ # Record where we found X for the cache.
+ ac_cv_have_x="have_x=yes \
+ ac_x_includes=$ac_x_includes ac_x_libraries=$ac_x_libraries"
+fi
+fi
+ fi
+ eval "$ac_cv_have_x"
+fi # $with_x != no
+
+if test "$have_x" != yes; then
+ echo "$ac_t""$have_x" 1>&6
+ no_x=yes
+else
+ # If each of the values was on the command line, it overrides each guess.
+ test "x$x_includes" = xNONE && x_includes=$ac_x_includes
+ test "x$x_libraries" = xNONE && x_libraries=$ac_x_libraries
+ # Update the cache value to reflect the command line values.
+ ac_cv_have_x="have_x=yes \
+ ac_x_includes=$x_includes ac_x_libraries=$x_libraries"
+ echo "$ac_t""libraries $x_libraries, headers $x_includes" 1>&6
+fi
+
+
+
+
+
+
+
+
+# Begin stuff to support --enable-shared
+# Check whether --enable-shared or --disable-shared was given.
+if test "${enable_shared+set}" = set; then
+ enableval="$enable_shared"
+ case "${enableval}" in
+ yes) shared=true ;;
+ no) shared=false ;;
+ *) shared=true ;;
+esac
+fi
+
+HLDFLAGS=
+HLDENV=
+# If we have shared libraries, try to set rpath reasonably.
+if test "${shared}" = "true"; then
+ case "${host}" in
+ *-*-hpux*)
+ HLDFLAGS='-Wl,+s,+b,$(libdir)'
+ ;;
+ *-*-irix5* | *-*-irix6*)
+ HLDFLAGS='-Wl,-rpath,$(libdir)'
+ ;;
+ *-*-linux*aout*)
+ ;;
+ *-*-linux* | *-pc-linux-gnu)
+ HLDFLAGS='-Wl,-rpath,$(libdir)'
+ ;;
+ *-*-solaris*)
+ HLDFLAGS='-R $(libdir)'
+ ;;
+ *-*-sysv4*)
+ HLDENV='if test -z "$${LD_RUN_PATH}"; then LD_RUN_PATH=$(libdir); else LD_RUN_PATH=$${LD_RUN_PATH}:$(libdir); fi; export LD_RUN_PATH;'
+ ;;
+ esac
+fi
+
+# On SunOS, if the linker supports the -rpath option, use it to
+# prevent ../bfd and ../opcodes from being included in the run time
+# search path.
+case "${host}" in
+ *-*-sunos*)
+ echo 'main () { }' > conftest.c
+ ${CC} -o conftest -Wl,-rpath= conftest.c >/dev/null 2>conftest.t
+ if grep 'unrecognized' conftest.t >/dev/null 2>&1; then
+ :
+ elif grep 'No such file' conftest.t >/dev/null 2>&1; then
+ :
+ elif grep 'do not mix' conftest.t >/dev/null 2>&1; then
+ :
+ elif grep 'some text already loaded' conftest.t >/dev/null 2>&1; then
+ :
+ elif test "${shared}" = "true"; then
+ HLDFLAGS='-Wl,-rpath=$(libdir)'
+ else
+ HLDFLAGS='-Wl,-rpath='
+ fi
+ rm -f conftest.t conftest.c conftest
+ ;;
+esac
+
+
+# End stuff to support --enable-shared
+
+# target_subdir is used by the testsuite to find the target libraries.
+target_subdir=
+if test "${host}" != "${target}"; then
+ target_subdir="${target_alias}/"
+fi
+
+
+frags=
+host_makefile_frag=${srcdir}/config/${gdb_host_cpu}/${gdb_host}.mh
+if test ! -f ${host_makefile_frag}; then
+{ echo "configure: error: "*** Gdb does not support host ${host}"" 1>&2; exit 1; }
+fi
+frags="$frags $host_makefile_frag"
+
+target_makefile_frag=${srcdir}/config/${gdb_target_cpu}/${gdb_target}.mt
+if test ! -f ${target_makefile_frag}; then
+{ echo "configure: error: "*** Gdb does not support target ${target}"" 1>&2; exit 1; }
+fi
+frags="$frags $target_makefile_frag"
+
+
+
+
+
+hostfile=`sed -n '
+s/XM_FILE[ ]*=[ ]*\([^ ]*\)/\1/p
+' ${host_makefile_frag}`
+
+targetfile=`sed -n '
+s/TM_FILE[ ]*=[ ]*\([^ ]*\)/\1/p
+' ${target_makefile_frag}`
+
+# these really aren't orthogonal true/false values of the same condition,
+# but shells are slow enough that I like to reuse the test conditions
+# whenever possible
+if test "${target}" = "${host}"; then
+nativefile=`sed -n '
+s/NAT_FILE[ ]*=[ ]*\([^ ]*\)/\1/p
+' ${host_makefile_frag}`
+# else
+# GDBserver is only useful in a "native" enviroment
+# configdirs=`echo $configdirs | sed 's/gdbserver//'`
+fi
+
+
+# If hostfile (XM_FILE) and/or targetfile (TM_FILE) and/or nativefile
+# (NAT_FILE) is not set in config/*/*.m[ht] files, we don't make the
+# corresponding links. But we have to remove the xm.h files and tm.h
+# files anyway, e.g. when switching from "configure host" to
+# "configure none".
+
+files=
+links=
+rm -f xm.h
+if test "${hostfile}" != ""; then
+files="${files} config/${gdb_host_cpu}/${hostfile}"
+links="${links} xm.h"
+fi
+rm -f tm.h
+if test "${targetfile}" != ""; then
+files="${files} config/${gdb_target_cpu}/${targetfile}"
+links="${links} tm.h"
+fi
+rm -f nm.h
+if test "${nativefile}" != ""; then
+files="${files} config/${gdb_host_cpu}/${nativefile}"
+links="${links} nm.h"
+else
+# A cross-only configuration.
+files="${files} config/nm-empty.h"
+links="${links} nm.h"
+fi
+
+
+
+echo $ac_n "checking for Cygwin environment""... $ac_c" 1>&6
+echo "configure:5602: checking for Cygwin environment" >&5
+if eval "test \"`echo '$''{'ac_cv_cygwin'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 5607 "configure"
+#include "confdefs.h"
+
+int main() {
+
+#ifndef __CYGWIN__
+#define __CYGWIN__ __CYGWIN32__
+#endif
+return __CYGWIN__;
+; return 0; }
+EOF
+if { (eval echo configure:5618: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_cygwin=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_cygwin=no
+fi
+rm -f conftest*
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_cygwin" 1>&6
+CYGWIN=
+test "$ac_cv_cygwin" = yes && CYGWIN=yes
+echo $ac_n "checking for mingw32 environment""... $ac_c" 1>&6
+echo "configure:5635: checking for mingw32 environment" >&5
+if eval "test \"`echo '$''{'ac_cv_mingw32'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 5640 "configure"
+#include "confdefs.h"
+
+int main() {
+return __MINGW32__;
+; return 0; }
+EOF
+if { (eval echo configure:5647: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_mingw32=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_mingw32=no
+fi
+rm -f conftest*
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_mingw32" 1>&6
+MINGW32=
+test "$ac_cv_mingw32" = yes && MINGW32=yes
+
+
+echo $ac_n "checking for executable suffix""... $ac_c" 1>&6
+echo "configure:5666: checking for executable suffix" >&5
+if eval "test \"`echo '$''{'ac_cv_exeext'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test "$CYGWIN" = yes || test "$MINGW32" = yes; then
+ ac_cv_exeext=.exe
+else
+ rm -f conftest*
+ echo 'int main () { return 0; }' > conftest.$ac_ext
+ ac_cv_exeext=
+ if { (eval echo configure:5676: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
+ for file in conftest.*; do
+ case $file in
+ *.c | *.o | *.obj | *.ilk | *.pdb) ;;
+ *) ac_cv_exeext=`echo $file | sed -e s/conftest//` ;;
+ esac
+ done
+ else
+ { echo "configure: error: installation or configuration problem: compiler cannot create executables." 1>&2; exit 1; }
+ fi
+ rm -f conftest*
+ test x"${ac_cv_exeext}" = x && ac_cv_exeext=no
+fi
+fi
+
+EXEEXT=""
+test x"${ac_cv_exeext}" != xno && EXEEXT=${ac_cv_exeext}
+echo "$ac_t""${ac_cv_exeext}" 1>&6
+ac_exeext=$EXEEXT
+
+
+subdirs="$configdirs"
+
+trap '' 1 2 15
+cat > confcache <<\EOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs. It is not useful on other systems.
+# If it contains results you don't want to keep, you may remove or edit it.
+#
+# By default, configure uses ./config.cache as the cache file,
+# creating it if it does not exist already. You can give configure
+# the --cache-file=FILE option to use a different cache file; that is
+# what configure does when it calls configure scripts in
+# subdirectories, so they share the cache.
+# Giving --cache-file=/dev/null disables caching, for debugging configure.
+# config.status only pays attention to the cache file if you give it the
+# --recheck option to rerun configure.
+#
+EOF
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, don't put newlines in cache variables' values.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(set) 2>&1 |
+ case `(ac_space=' '; set | grep ac_space) 2>&1` in
+ *ac_space=\ *)
+ # `set' does not quote correctly, so add quotes (double-quote substitution
+ # turns \\\\ into \\, and sed turns \\ into \).
+ sed -n \
+ -e "s/'/'\\\\''/g" \
+ -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p"
+ ;;
+ *)
+ # `set' quotes correctly as required by POSIX, so do not add quotes.
+ sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p'
+ ;;
+ esac >> confcache
+if cmp -s $cache_file confcache; then
+ :
+else
+ if test -w $cache_file; then
+ echo "updating cache $cache_file"
+ cat confcache > $cache_file
+ else
+ echo "not updating unwritable cache $cache_file"
+ fi
+fi
+rm -f confcache
+
+trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+# Any assignment to VPATH causes Sun make to only execute
+# the first set of double-colon rules, so remove it if not needed.
+# If there is a colon in the path, we need to keep it.
+if test "x$srcdir" = x.; then
+ ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d'
+fi
+
+trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15
+
+DEFS=-DHAVE_CONFIG_H
+
+# Without the "./", some shells look in PATH for config.status.
+: ${CONFIG_STATUS=./config.status}
+
+echo creating $CONFIG_STATUS
+rm -f $CONFIG_STATUS
+cat > $CONFIG_STATUS <<EOF
+#! /bin/sh
+# Generated automatically by configure.
+# Run this file to recreate the current configuration.
+# This directory was configured as follows,
+# on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+#
+# $0 $ac_configure_args
+#
+# Compiler output produced by configure, useful for debugging
+# configure, is in ./config.log if it exists.
+
+ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]"
+for ac_option
+do
+ case "\$ac_option" in
+ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+ echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion"
+ exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;;
+ -version | --version | --versio | --versi | --vers | --ver | --ve | --v)
+ echo "$CONFIG_STATUS generated by autoconf version 2.13"
+ exit 0 ;;
+ -help | --help | --hel | --he | --h)
+ echo "\$ac_cs_usage"; exit 0 ;;
+ *) echo "\$ac_cs_usage"; exit 1 ;;
+ esac
+done
+
+ac_given_srcdir=$srcdir
+ac_given_INSTALL="$INSTALL"
+
+trap 'rm -fr `echo "Makefile tui/Makefile .gdbinit:gdbinit.in config.h:config.in" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15
+EOF
+cat >> $CONFIG_STATUS <<EOF
+
+# Protect against being on the right side of a sed subst in config.status.
+sed 's/%@/@@/; s/@%/@@/; s/%g\$/@g/; /@g\$/s/[\\\\&%]/\\\\&/g;
+ s/@@/%@/; s/@@/@%/; s/@g\$/%g/' > conftest.subs <<\\CEOF
+$ac_vpsub
+$extrasub
+s%@SHELL@%$SHELL%g
+s%@CFLAGS@%$CFLAGS%g
+s%@CPPFLAGS@%$CPPFLAGS%g
+s%@CXXFLAGS@%$CXXFLAGS%g
+s%@FFLAGS@%$FFLAGS%g
+s%@DEFS@%$DEFS%g
+s%@LDFLAGS@%$LDFLAGS%g
+s%@LIBS@%$LIBS%g
+s%@exec_prefix@%$exec_prefix%g
+s%@prefix@%$prefix%g
+s%@program_transform_name@%$program_transform_name%g
+s%@bindir@%$bindir%g
+s%@sbindir@%$sbindir%g
+s%@libexecdir@%$libexecdir%g
+s%@datadir@%$datadir%g
+s%@sysconfdir@%$sysconfdir%g
+s%@sharedstatedir@%$sharedstatedir%g
+s%@localstatedir@%$localstatedir%g
+s%@libdir@%$libdir%g
+s%@includedir@%$includedir%g
+s%@oldincludedir@%$oldincludedir%g
+s%@infodir@%$infodir%g
+s%@mandir@%$mandir%g
+s%@CC@%$CC%g
+s%@CPP@%$CPP%g
+s%@host@%$host%g
+s%@host_alias@%$host_alias%g
+s%@host_cpu@%$host_cpu%g
+s%@host_vendor@%$host_vendor%g
+s%@host_os@%$host_os%g
+s%@target@%$target%g
+s%@target_alias@%$target_alias%g
+s%@target_cpu@%$target_cpu%g
+s%@target_vendor@%$target_vendor%g
+s%@target_os@%$target_os%g
+s%@build@%$build%g
+s%@build_alias@%$build_alias%g
+s%@build_cpu@%$build_cpu%g
+s%@build_vendor@%$build_vendor%g
+s%@build_os@%$build_os%g
+s%@SET_MAKE@%$SET_MAKE%g
+s%@RANLIB@%$RANLIB%g
+s%@ALLOCA@%$ALLOCA%g
+s%@USE_NLS@%$USE_NLS%g
+s%@MSGFMT@%$MSGFMT%g
+s%@GMSGFMT@%$GMSGFMT%g
+s%@XGETTEXT@%$XGETTEXT%g
+s%@USE_INCLUDED_LIBINTL@%$USE_INCLUDED_LIBINTL%g
+s%@CATALOGS@%$CATALOGS%g
+s%@CATOBJEXT@%$CATOBJEXT%g
+s%@DATADIRNAME@%$DATADIRNAME%g
+s%@GMOFILES@%$GMOFILES%g
+s%@INSTOBJEXT@%$INSTOBJEXT%g
+s%@INTLDEPS@%$INTLDEPS%g
+s%@INTLLIBS@%$INTLLIBS%g
+s%@INTLOBJS@%$INTLOBJS%g
+s%@POFILES@%$POFILES%g
+s%@POSUB@%$POSUB%g
+s%@INCLUDE_LOCALE_H@%$INCLUDE_LOCALE_H%g
+s%@GT_NO@%$GT_NO%g
+s%@GT_YES@%$GT_YES%g
+s%@MKINSTALLDIRS@%$MKINSTALLDIRS%g
+s%@l@%$l%g
+s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g
+s%@INSTALL_SCRIPT@%$INSTALL_SCRIPT%g
+s%@INSTALL_DATA@%$INSTALL_DATA%g
+s%@AR@%$AR%g
+s%@YACC@%$YACC%g
+s%@CONFIG_LDFLAGS@%$CONFIG_LDFLAGS%g
+s%@BUILD_TUI@%$BUILD_TUI%g
+s%@TUI_LIBRARY@%$TUI_LIBRARY%g
+s%@WARN_CFLAGS@%$WARN_CFLAGS%g
+s%@MMALLOC_CFLAGS@%$MMALLOC_CFLAGS%g
+s%@MMALLOC@%$MMALLOC%g
+s%@TERM_LIB@%$TERM_LIB%g
+s%@ENABLE_CFLAGS@%$ENABLE_CFLAGS%g
+s%@CONFIG_OBS@%$CONFIG_OBS%g
+s%@CONFIG_DEPS@%$CONFIG_DEPS%g
+s%@CONFIG_SRCS@%$CONFIG_SRCS%g
+s%@HLDFLAGS@%$HLDFLAGS%g
+s%@HLDENV@%$HLDENV%g
+s%@target_subdir@%$target_subdir%g
+/@host_makefile_frag@/r $host_makefile_frag
+s%@host_makefile_frag@%%g
+/@target_makefile_frag@/r $target_makefile_frag
+s%@target_makefile_frag@%%g
+s%@frags@%$frags%g
+s%@EXEEXT@%$EXEEXT%g
+s%@subdirs@%$subdirs%g
+
+CEOF
+EOF
+
+cat >> $CONFIG_STATUS <<\EOF
+
+# Split the substitutions into bite-sized pieces for seds with
+# small command number limits, like on Digital OSF/1 and HP-UX.
+ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script.
+ac_file=1 # Number of current file.
+ac_beg=1 # First line for current file.
+ac_end=$ac_max_sed_cmds # Line after last line for current file.
+ac_more_lines=:
+ac_sed_cmds=""
+while $ac_more_lines; do
+ if test $ac_beg -gt 1; then
+ sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file
+ else
+ sed "${ac_end}q" conftest.subs > conftest.s$ac_file
+ fi
+ if test ! -s conftest.s$ac_file; then
+ ac_more_lines=false
+ rm -f conftest.s$ac_file
+ else
+ if test -z "$ac_sed_cmds"; then
+ ac_sed_cmds="sed -f conftest.s$ac_file"
+ else
+ ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file"
+ fi
+ ac_file=`expr $ac_file + 1`
+ ac_beg=$ac_end
+ ac_end=`expr $ac_end + $ac_max_sed_cmds`
+ fi
+done
+if test -z "$ac_sed_cmds"; then
+ ac_sed_cmds=cat
+fi
+EOF
+
+cat >> $CONFIG_STATUS <<EOF
+
+CONFIG_FILES=\${CONFIG_FILES-"Makefile tui/Makefile .gdbinit:gdbinit.in"}
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then
+ # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+ case "$ac_file" in
+ *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'`
+ ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
+ *) ac_file_in="${ac_file}.in" ;;
+ esac
+
+ # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories.
+
+ # Remove last slash and all that follows it. Not all systems have dirname.
+ ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
+ if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
+ # The file is in a subdirectory.
+ test ! -d "$ac_dir" && mkdir "$ac_dir"
+ ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`"
+ # A "../" for each directory in $ac_dir_suffix.
+ ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'`
+ else
+ ac_dir_suffix= ac_dots=
+ fi
+
+ case "$ac_given_srcdir" in
+ .) srcdir=.
+ if test -z "$ac_dots"; then top_srcdir=.
+ else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;;
+ /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;;
+ *) # Relative path.
+ srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix"
+ top_srcdir="$ac_dots$ac_given_srcdir" ;;
+ esac
+
+ case "$ac_given_INSTALL" in
+ [/$]*) INSTALL="$ac_given_INSTALL" ;;
+ *) INSTALL="$ac_dots$ac_given_INSTALL" ;;
+ esac
+
+ echo creating "$ac_file"
+ rm -f "$ac_file"
+ configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure."
+ case "$ac_file" in
+ *Makefile*) ac_comsub="1i\\
+# $configure_input" ;;
+ *) ac_comsub= ;;
+ esac
+
+ ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"`
+ sed -e "$ac_comsub
+s%@configure_input@%$configure_input%g
+s%@srcdir@%$srcdir%g
+s%@top_srcdir@%$top_srcdir%g
+s%@INSTALL@%$INSTALL%g
+" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file
+fi; done
+rm -f conftest.s*
+
+# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where
+# NAME is the cpp macro being defined and VALUE is the value it is being given.
+#
+# ac_d sets the value in "#define NAME VALUE" lines.
+ac_dA='s%^\([ ]*\)#\([ ]*define[ ][ ]*\)'
+ac_dB='\([ ][ ]*\)[^ ]*%\1#\2'
+ac_dC='\3'
+ac_dD='%g'
+# ac_u turns "#undef NAME" with trailing blanks into "#define NAME VALUE".
+ac_uA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)'
+ac_uB='\([ ]\)%\1#\2define\3'
+ac_uC=' '
+ac_uD='\4%g'
+# ac_e turns "#undef NAME" without trailing blanks into "#define NAME VALUE".
+ac_eA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)'
+ac_eB='$%\1#\2define\3'
+ac_eC=' '
+ac_eD='%g'
+
+if test "${CONFIG_HEADERS+set}" != set; then
+EOF
+cat >> $CONFIG_STATUS <<EOF
+ CONFIG_HEADERS="config.h:config.in"
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+fi
+for ac_file in .. $CONFIG_HEADERS; do if test "x$ac_file" != x..; then
+ # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+ case "$ac_file" in
+ *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'`
+ ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
+ *) ac_file_in="${ac_file}.in" ;;
+ esac
+
+ echo creating $ac_file
+
+ rm -f conftest.frag conftest.in conftest.out
+ ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"`
+ cat $ac_file_inputs > conftest.in
+
+EOF
+
+# Transform confdefs.h into a sed script conftest.vals that substitutes
+# the proper values into config.h.in to produce config.h. And first:
+# Protect against being on the right side of a sed subst in config.status.
+# Protect against being in an unquoted here document in config.status.
+rm -f conftest.vals
+cat > conftest.hdr <<\EOF
+s/[\\&%]/\\&/g
+s%[\\$`]%\\&%g
+s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD}%gp
+s%ac_d%ac_u%gp
+s%ac_u%ac_e%gp
+EOF
+sed -n -f conftest.hdr confdefs.h > conftest.vals
+rm -f conftest.hdr
+
+# This sed command replaces #undef with comments. This is necessary, for
+# example, in the case of _POSIX_SOURCE, which is predefined and required
+# on some systems where configure will not decide to define it.
+cat >> conftest.vals <<\EOF
+s%^[ ]*#[ ]*undef[ ][ ]*[a-zA-Z_][a-zA-Z_0-9]*%/* & */%
+EOF
+
+# Break up conftest.vals because some shells have a limit on
+# the size of here documents, and old seds have small limits too.
+
+rm -f conftest.tail
+while :
+do
+ ac_lines=`grep -c . conftest.vals`
+ # grep -c gives empty output for an empty file on some AIX systems.
+ if test -z "$ac_lines" || test "$ac_lines" -eq 0; then break; fi
+ # Write a limited-size here document to conftest.frag.
+ echo ' cat > conftest.frag <<CEOF' >> $CONFIG_STATUS
+ sed ${ac_max_here_lines}q conftest.vals >> $CONFIG_STATUS
+ echo 'CEOF
+ sed -f conftest.frag conftest.in > conftest.out
+ rm -f conftest.in
+ mv conftest.out conftest.in
+' >> $CONFIG_STATUS
+ sed 1,${ac_max_here_lines}d conftest.vals > conftest.tail
+ rm -f conftest.vals
+ mv conftest.tail conftest.vals
+done
+rm -f conftest.vals
+
+cat >> $CONFIG_STATUS <<\EOF
+ rm -f conftest.frag conftest.h
+ echo "/* $ac_file. Generated automatically by configure. */" > conftest.h
+ cat conftest.in >> conftest.h
+ rm -f conftest.in
+ if cmp -s $ac_file conftest.h 2>/dev/null; then
+ echo "$ac_file is unchanged"
+ rm -f conftest.h
+ else
+ # Remove last slash and all that follows it. Not all systems have dirname.
+ ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
+ if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
+ # The file is in a subdirectory.
+ test ! -d "$ac_dir" && mkdir "$ac_dir"
+ fi
+ rm -f $ac_file
+ mv conftest.h $ac_file
+ fi
+fi; done
+
+EOF
+
+cat >> $CONFIG_STATUS <<EOF
+ac_sources="$files"
+ac_dests="$links"
+EOF
+
+cat >> $CONFIG_STATUS <<\EOF
+srcdir=$ac_given_srcdir
+while test -n "$ac_sources"; do
+ set $ac_dests; ac_dest=$1; shift; ac_dests=$*
+ set $ac_sources; ac_source=$1; shift; ac_sources=$*
+
+ echo "linking $srcdir/$ac_source to $ac_dest"
+
+ if test ! -r $srcdir/$ac_source; then
+ { echo "configure: error: $srcdir/$ac_source: File not found" 1>&2; exit 1; }
+ fi
+ rm -f $ac_dest
+
+ # Make relative symlinks.
+ # Remove last slash and all that follows it. Not all systems have dirname.
+ ac_dest_dir=`echo $ac_dest|sed 's%/[^/][^/]*$%%'`
+ if test "$ac_dest_dir" != "$ac_dest" && test "$ac_dest_dir" != .; then
+ # The dest file is in a subdirectory.
+ test ! -d "$ac_dest_dir" && mkdir "$ac_dest_dir"
+ ac_dest_dir_suffix="/`echo $ac_dest_dir|sed 's%^\./%%'`"
+ # A "../" for each directory in $ac_dest_dir_suffix.
+ ac_dots=`echo $ac_dest_dir_suffix|sed 's%/[^/]*%../%g'`
+ else
+ ac_dest_dir_suffix= ac_dots=
+ fi
+
+ case "$srcdir" in
+ [/$]*) ac_rel_source="$srcdir/$ac_source" ;;
+ *) ac_rel_source="$ac_dots$srcdir/$ac_source" ;;
+ esac
+
+ # Make a symlink if possible; otherwise try a hard link.
+ if ln -s $ac_rel_source $ac_dest 2>/dev/null ||
+ ln $srcdir/$ac_source $ac_dest; then :
+ else
+ { echo "configure: error: can not link $ac_dest to $srcdir/$ac_source" 1>&2; exit 1; }
+ fi
+done
+EOF
+cat >> $CONFIG_STATUS <<EOF
+
+gdb_host_cpu=$gdb_host_cpu
+gdb_target_cpu=$gdb_target_cpu
+nativefile=$nativefile
+
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+
+if test "${nativefile}" = ""; then
+sed -e '/^NATDEPFILES[ ]*=[ ]*/s//# NATDEPFILES=/' \
+ < Makefile > Makefile.tem
+mv -f Makefile.tem Makefile
+fi
+
+sed -e '/^TM_FILE[ ]*=/s,^TM_FILE[ ]*=[ ]*,&config/'"${gdb_target_cpu}"'/,
+/^XM_FILE[ ]*=/s,^XM_FILE[ ]*=[ ]*,&config/'"${gdb_host_cpu}"'/,
+/^NAT_FILE[ ]*=/s,^NAT_FILE[ ]*=[ ]*,&config/'"${gdb_host_cpu}"'/,' <Makefile >Makefile.tmp
+mv -f Makefile.tmp Makefile
+
+case x$CONFIG_HEADERS in
+xconfig.h:config.in)
+echo > stamp-h ;;
+esac
+
+exit 0
+EOF
+chmod +x $CONFIG_STATUS
+rm -fr confdefs* $ac_clean_files
+test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1
+
+if test "$no_recursion" != yes; then
+
+ # Remove --cache-file and --srcdir arguments so they do not pile up.
+ ac_sub_configure_args=
+ ac_prev=
+ for ac_arg in $ac_configure_args; do
+ if test -n "$ac_prev"; then
+ ac_prev=
+ continue
+ fi
+ case "$ac_arg" in
+ -cache-file | --cache-file | --cache-fil | --cache-fi \
+ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+ ac_prev=cache_file ;;
+ -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+ ;;
+ -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+ ac_prev=srcdir ;;
+ -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+ ;;
+ *) ac_sub_configure_args="$ac_sub_configure_args $ac_arg" ;;
+ esac
+ done
+
+ for ac_config_dir in $configdirs; do
+
+ # Do not complain, so a configure script can configure whichever
+ # parts of a large source tree are present.
+ if test ! -d $srcdir/$ac_config_dir; then
+ continue
+ fi
+
+ echo configuring in $ac_config_dir
+
+ case "$srcdir" in
+ .) ;;
+ *)
+ if test -d ./$ac_config_dir || mkdir ./$ac_config_dir; then :;
+ else
+ { echo "configure: error: can not create `pwd`/$ac_config_dir" 1>&2; exit 1; }
+ fi
+ ;;
+ esac
+
+ ac_popdir=`pwd`
+ cd $ac_config_dir
+
+ # A "../" for each directory in /$ac_config_dir.
+ ac_dots=`echo $ac_config_dir|sed -e 's%^\./%%' -e 's%[^/]$%&/%' -e 's%[^/]*/%../%g'`
+
+ case "$srcdir" in
+ .) # No --srcdir option. We are building in place.
+ ac_sub_srcdir=$srcdir ;;
+ /*) # Absolute path.
+ ac_sub_srcdir=$srcdir/$ac_config_dir ;;
+ *) # Relative path.
+ ac_sub_srcdir=$ac_dots$srcdir/$ac_config_dir ;;
+ esac
+
+ # Check for guested configure; otherwise get Cygnus style configure.
+ if test -f $ac_sub_srcdir/configure; then
+ ac_sub_configure=$ac_sub_srcdir/configure
+ elif test -f $ac_sub_srcdir/configure.in; then
+ ac_sub_configure=$ac_configure
+ else
+ echo "configure: warning: no configuration information is in $ac_config_dir" 1>&2
+ ac_sub_configure=
+ fi
+
+ # The recursion is here.
+ if test -n "$ac_sub_configure"; then
+
+ # Make the cache file name correct relative to the subdirectory.
+ case "$cache_file" in
+ /*) ac_sub_cache_file=$cache_file ;;
+ *) # Relative path.
+ ac_sub_cache_file="$ac_dots$cache_file" ;;
+ esac
+ case "$ac_given_INSTALL" in
+ [/$]*) INSTALL="$ac_given_INSTALL" ;;
+ *) INSTALL="$ac_dots$ac_given_INSTALL" ;;
+ esac
+
+ echo "running ${CONFIG_SHELL-/bin/sh} $ac_sub_configure $ac_sub_configure_args --cache-file=$ac_sub_cache_file --srcdir=$ac_sub_srcdir"
+ # The eval makes quoting arguments work.
+ if eval ${CONFIG_SHELL-/bin/sh} $ac_sub_configure $ac_sub_configure_args --cache-file=$ac_sub_cache_file --srcdir=$ac_sub_srcdir
+ then :
+ else
+ { echo "configure: error: $ac_sub_configure failed for $ac_config_dir" 1>&2; exit 1; }
+ fi
+ fi
+
+ cd $ac_popdir
+ done
+fi
+
+
+exit 0
diff --git a/gdb/configure.host b/gdb/configure.host
new file mode 100644
index 00000000000..aca63e62e27
--- /dev/null
+++ b/gdb/configure.host
@@ -0,0 +1,162 @@
+# Mapping of configurations into GDB host definitions. This is
+# invoked from the autoconf generated configure script.
+
+# This file sets the following shell variables:
+# gdb_host_cpu generic name of host's CPU
+# gdb_host name of GDB host definition to use
+
+# Map host cpu into the config cpu subdirectory name.
+# The default is $host_cpu.
+
+case "${host_cpu}" in
+
+alpha*) gdb_host_cpu=alpha ;;
+c[12]) gdb_host_cpu=convex ;;
+hppa*) gdb_host_cpu=pa ;;
+i[3456]86*) gdb_host_cpu=i386 ;;
+m68*) gdb_host_cpu=m68k ;;
+m88*) gdb_host_cpu=m88k ;;
+# OBSOLETE np1) gdb_host_cpu=gould ;;
+pyramid) gdb_host_cpu=pyr ;;
+powerpc*) gdb_host_cpu=powerpc ;;
+sparc64) gdb_host_cpu=sparc ;;
+*) gdb_host_cpu=$host_cpu ;;
+
+esac
+
+# map host info into gdb names.
+
+case "${host}" in
+
+a29k-*-*) gdb_host=ultra3 ;;
+
+alpha*-*-osf1*) gdb_host=alpha-osf1 ;;
+alpha*-*-osf2*) gdb_host=alpha-osf2 ;;
+alpha*-*-osf[3456789]*) gdb_host=alpha-osf3 ;;
+alpha*-*-linux*) gdb_host=alpha-linux ;;
+
+arm-*-*) gdb_host=arm ;;
+
+c[12]-*-*) gdb_host=convex ;;
+
+hppa*-*-bsd*) gdb_host=hppabsd ;;
+hppa*-*-hiux*) gdb_host=hppahpux ;;
+hppa*-*-hpux10.20) gdb_host=hpux1020 ;;
+hppa*-*-hpux11.0*) gdb_host=hpux1100 ;;
+hppa*-*-hpux*) gdb_host=hppahpux ;;
+hppa*-*-osf*) gdb_host=hppaosf ;;
+
+i[3456]86-ncr-*) gdb_host=ncr3000 ;;
+i[3456]86-sequent-bsd*) gdb_host=symmetry ;; # dynix
+i[3456]86-sequent-sysv4*) gdb_host=ptx4 ;;
+i[3456]86-sequent-sysv*) gdb_host=ptx ;;
+i[3456]86-*-aix*) gdb_host=i386aix ;;
+i[3456]86-*-bsd*) gdb_host=i386bsd ;;
+i[3456]86-*-dgux*) gdb_host=i386dgux ;;
+i[3456]86-*-freebsd*) gdb_host=fbsd ;;
+i[3456]86-*-netbsd*) gdb_host=nbsd ;;
+i[3456]86-*-go32*) gdb_host=go32 ;;
+i[3456]86-*-linux*) gdb_host=linux ;;
+i[3456]86-*-lynxos*) gdb_host=i386lynx ;;
+i[3456]86-*-mach3*) gdb_host=i386m3 ;;
+i[3456]86-*-mach*) gdb_host=i386mach ;;
+i[3456]86-*-gnu*) gdb_host=i386gnu ;;
+i[3456]86-*-osf1mk*) gdb_host=i386mk ;;
+i[3456]86-*-sco3.2v5*) gdb_host=i386sco5 ;;
+i[3456]86-*-sco3.2v4*) gdb_host=i386sco4 ;;
+i[3456]86-*-sco*) gdb_host=i386sco ;;
+i[3456]86-*-solaris*) gdb_host=i386sol2 ;;
+i[3456]86-*-sunos*) gdb_host=sun386 ;;
+i[3456]86-*-sysv3.2*) gdb_host=i386v32 ;;
+i[3456]86-*-sysv32*) gdb_host=i386v32 ;;
+i[3456]86-*-sysv4.2*) gdb_host=i386v42mp ;;
+i[3456]86-*-sysv4*) gdb_host=i386v4 ;;
+i[3456]86-*-sysv5*) gdb_host=i386v42mp ;;
+i[3456]86-*-unixware2*) gdb_host=i386v42mp ;;
+i[3456]86-*-unixware*) gdb_host=i386v4 ;;
+i[3456]86-*-sysv*) gdb_host=i386v ;;
+i[3456]86-*-isc*) gdb_host=i386v32 ;;
+i[3456]86-*-cygwin*) gdb_host=cygwin ;;
+m680[01]0-sun-sunos3*) gdb_host=sun2os3 ;;
+m680[01]0-sun-sunos4*) gdb_host=sun2os4 ;;
+m68030-sony-*) gdb_host=news1000 ;;
+
+m68*-altos-*) gdb_host=altos ;;
+m68*-apollo*-sysv*) gdb_host=apollo68v ;;
+m68*-apollo*-bsd*) gdb_host=apollo68b ;;
+m68*-att-*) gdb_host=3b1 ;;
+m68*-bull*-sysv*) gdb_host=dpx2 ;;
+m68*-hp-bsd*) gdb_host=hp300bsd ;;
+m68*-hp-hpux*) gdb_host=hp300hpux ;;
+m68*-isi-*) gdb_host=isi ;;
+m68*-*-linux*) gdb_host=linux ;;
+m68*-*-lynxos*) gdb_host=m68klynx ;;
+m68*-*-netbsd*) gdb_host=nbsd ;;
+m68*-*-sysv4*) gdb_host=m68kv4 ;;
+m68*-motorola-*) gdb_host=delta68 ;;
+m68*-sony-*) gdb_host=news ;;
+m68*-sun-sunos3*) gdb_host=sun3os3 ;;
+m68*-sun-sunos4*) gdb_host=sun3os4 ;;
+m68*-sun-*) gdb_host=sun3os4 ;;
+
+m88*-harris-cxux*) gdb_host=cxux ;;
+m88*-motorola-sysv4*) gdb_host=delta88v4 ;;
+m88*-motorola-sysv*) gdb_host=delta88 ;;
+m88*-*-*) gdb_host=m88k ;;
+
+mips-dec-mach3*) gdb_host=mach3 ;;
+mips-dec-*) gdb_host=decstation ;;
+mips-little-*) gdb_host=littlemips ;;
+mips-sgi-irix3*) gdb_host=irix3 ;;
+mips-sgi-irix4*) gdb_host=irix4 ;;
+mips-sgi-irix5*) gdb_host=irix5 ;;
+# Close enough for now.
+mips-sgi-irix6*) gdb_host=irix5 ;;
+mips-sony-*) gdb_host=news-mips ;;
+mips-*-mach3*) gdb_host=mipsm3 ;;
+mips-*-sysv4*) gdb_host=mipsv4 ;;
+mips-*-sysv*) gdb_host=riscos ;;
+mips-*-riscos*) gdb_host=riscos ;;
+
+none-*-*) gdb_host=none ;;
+
+# OBSOLETE np1-*-*) gdb_host=np1 ;;
+
+ns32k-*-mach3*) gdb_host=ns32km3 ;;
+ns32k-*-netbsd*) gdb_host=nbsd ;;
+ns32k-umax-*) gdb_host=umax ;;
+ns32k-utek-sysv*) gdb_host=merlin ;;
+
+powerpc-*-aix*) gdb_host=aix ;;
+powerpcle-*-cygwin*) gdb_host=cygwin ;;
+powerpcle-*-solaris*) gdb_host=solaris ;;
+powerpc-*-linux*) gdb_host=linux ;;
+
+# OBSOLETE pn-*-*) gdb_host=pn ;;
+
+pyramid-*-*) gdb_host=pyramid ;;
+
+romp-*-*) gdb_host=rtbsd ;;
+
+rs6000-*-lynxos*) gdb_host=rs6000lynx ;;
+rs6000-*-aix4*) gdb_host=aix4 ;;
+rs6000-*-*) gdb_host=rs6000 ;;
+
+sparc-*-linux*) gdb_host=linux ;;
+sparc-*-lynxos*) gdb_host=sparclynx ;;
+sparc-*-netbsd*) gdb_host=nbsd ;;
+sparc-*-solaris2*) gdb_host=sun4sol2 ;;
+sparc-*-sunos4*) gdb_host=sun4os4 ;;
+sparc-*-sunos5*) gdb_host=sun4sol2 ;;
+sparc-*-*) gdb_host=sun4os4 ;;
+sparc64-*-*) gdb_host=sun4sol2 ;;
+
+strongarm-*-*) gdb_host=arm ;;
+
+tahoe-*-*) gdb_host=tahoe ;;
+
+vax-*-bsd*) gdb_host=vaxbsd ;;
+vax-*-ultrix2*) gdb_host=vaxult2 ;;
+vax-*-ultrix*) gdb_host=vaxult ;;
+
+esac
diff --git a/gdb/configure.in b/gdb/configure.in
new file mode 100644
index 00000000000..d6581183792
--- /dev/null
+++ b/gdb/configure.in
@@ -0,0 +1,606 @@
+dnl Autoconf configure script for GDB, the GNU debugger.
+dnl Copyright 1995, 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
+dnl
+dnl This file is part of GDB.
+dnl
+dnl This program is free software; you can redistribute it and/or modify
+dnl it under the terms of the GNU General Public License as published by
+dnl the Free Software Foundation; either version 2 of the License, or
+dnl (at your option) any later version.
+dnl
+dnl This program is distributed in the hope that it will be useful,
+dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
+dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+dnl GNU General Public License for more details.
+dnl
+dnl You should have received a copy of the GNU General Public License
+dnl along with this program; if not, write to the Free Software
+dnl Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+dnl Process this file with autoconf to produce a configure script.
+
+AC_PREREQ(2.13)dnl
+AC_INIT(main.c)
+AC_CONFIG_HEADER(config.h:config.in)
+
+AC_PROG_CC
+AC_AIX
+AC_ISC_POSIX
+AM_PROG_CC_STDC
+
+AC_CONFIG_AUX_DIR(`cd $srcdir;pwd`/..)
+AC_CANONICAL_SYSTEM
+
+dnl gdb doesn't use gettext, but bfd does. We call this to ensure we
+dnl link with the correct libraries.
+ALL_LINGUAS=
+CY_GNU_GETTEXT
+
+dnl List of object files added by configure.
+
+CONFIG_OBS=
+CONFIG_DEPS=
+CONFIG_SRCS=
+
+configdirs="doc testsuite"
+
+dnl
+changequote(,)dnl
+
+. ${srcdir}/configure.host
+
+. ${srcdir}/configure.tgt
+
+dnl
+changequote([,])dnl
+
+AC_PROG_INSTALL
+AC_CHECK_TOOL(AR, ar)
+AC_CHECK_TOOL(RANLIB, ranlib, :)
+AC_PROG_YACC
+
+AC_ARG_PROGRAM
+
+AC_TYPE_SIGNAL
+
+AC_HEADER_STDC
+
+AC_CHECK_HEADERS(ctype.h curses.h endian.h link.h \
+ memory.h objlist.h ptrace.h sgtty.h stddef.h stdlib.h \
+ string.h sys/procfs.h sys/ptrace.h sys/reg.h \
+ term.h termio.h termios.h unistd.h wait.h sys/wait.h \
+ wchar.h wctype.h asm/debugreg.h sys/debugreg.h)
+AC_HEADER_STAT
+
+AC_C_CONST
+
+AC_CHECK_FUNCS(setpgid sbrk sigaction isascii bzero bcopy btowc)
+AC_FUNC_ALLOCA
+
+BFD_NEED_DECLARATION(malloc)
+BFD_NEED_DECLARATION(realloc)
+BFD_NEED_DECLARATION(free)
+BFD_NEED_DECLARATION(strerror)
+BFD_NEED_DECLARATION(strdup)
+
+
+# The following save_state_t checkery is only necessary for HPUX
+# versions earlier than 10.20. When those fade from memory, this
+# could be expunged. --jsm 1999-03-22
+
+AC_MSG_CHECKING(for HPUX save_state structure)
+AC_EGREP_HEADER(save_state_t, machine/save_state.h,
+ gdb_cv_hpux_savestate=yes, gdb_cv_hpux_savestate=no)
+AC_EGREP_HEADER(ss_wide, machine/save_state.h, gdb_cv_hpux_sswide=yes,
+ gdb_cv_hpux_sswide=no)
+if test $gdb_cv_hpux_savestate = yes
+then
+ AC_DEFINE(HAVE_STRUCT_SAVE_STATE_T, 1)
+fi
+if test $gdb_cv_hpux_sswide = yes
+then
+ AC_DEFINE(HAVE_STRUCT_MEMBER_SS_WIDE, 1)
+fi
+AC_MSG_RESULT($gdb_cv_hpux_sswide)
+
+
+# If we are configured native on GNU/Linux, work around problems with
+# sys/procfs.h
+# Also detect which type of /proc is in use, such as for Unixware.
+
+if test "${target}" = "${host}"; then
+ case "${host}" in
+ i[[3456]]86-*-linux*)
+ AC_DEFINE(START_INFERIOR_TRAPS_EXPECTED,2)
+ AC_DEFINE(sys_quotactl)
+ ;;
+ esac
+ AC_MSG_CHECKING(for directory proc entries)
+# The [gdb_host != sun4sol2] hack is because Solaris does provide the
+# multiple procfs files as of Solaris 2.6, but GDB can't use it right now.
+ if test "$ac_cv_header_sys_procfs_h" = yes -a "$gdb_host" != sun4sol2 \
+ -a -d /proc/$$ \
+ -a -f /proc/$$/ctl \
+ -a -f /proc/$$/as \
+ -a -f /proc/$$/map \
+ -a -f /proc/$$/status; then
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_MULTIPLE_PROC_FDS)
+ else
+ AC_MSG_RESULT(no)
+ fi
+fi
+
+if test "$ac_cv_header_sys_procfs_h" = yes; then
+ BFD_HAVE_SYS_PROCFS_TYPE(pstatus_t)
+ BFD_HAVE_SYS_PROCFS_TYPE(prrun_t)
+ BFD_HAVE_SYS_PROCFS_TYPE(gregset_t)
+ BFD_HAVE_SYS_PROCFS_TYPE(fpregset_t)
+
+ dnl Check for PIOCSET ioctl entry
+
+ AC_MSG_CHECKING(for PIOCSET ioctl entry in sys/procfs.h)
+ AC_CACHE_VAL(gdb_cv_have_procfs_piocset,
+ [AC_TRY_COMPILE([#include <unistd.h>
+#include <sys/types.h>
+#include <sys/procfs.h>
+], [
+ int dummy;;
+ dummy = ioctl(0, PIOCSET, &dummy);
+ ],
+ gdb_cv_have_procfs_piocset=yes, gdb_cv_have_procfs_piocset=no)])
+ AC_MSG_RESULT($gdb_cv_have_procfs_piocset)
+ if test $gdb_cv_have_procfs_piocset = yes; then
+ AC_DEFINE(HAVE_PROCFS_PIOCSET)
+ fi
+fi
+
+dnl See if host has libm. This is usually needed by simulators.
+AC_CHECK_LIB(m, main)
+
+dnl Solaris puts wctype in /usr/lib/libw.a before Solaris 2.6.
+dnl
+dnl A bug in GNU ld 2.9.1 causes a problem if we link in -lw
+dnl under Solaris 2.6 because it is some funky empty library.
+dnl So only link in libw if we have to.
+AC_CHECK_LIB(c, wctype,: ,AC_CHECK_LIB(w, wctype))
+
+dnl See if compiler supports "long long" type.
+
+AC_MSG_CHECKING(for long long support in compiler)
+AC_CACHE_VAL(gdb_cv_c_long_long,
+[AC_TRY_COMPILE(, [
+ extern long long foo;
+ switch (foo & 2) { case 0: return 1; }
+],
+gdb_cv_c_long_long=yes, gdb_cv_c_long_long=no)])
+AC_MSG_RESULT($gdb_cv_c_long_long)
+if test $gdb_cv_c_long_long = yes; then
+ AC_DEFINE(CC_HAS_LONG_LONG)
+fi
+
+dnl See if the compiler and runtime support printing long long
+
+AC_MSG_CHECKING(for long long support in printf)
+AC_CACHE_VAL(gdb_cv_printf_has_long_long,
+[AC_TRY_RUN([
+int main () {
+ char buf[32];
+ long long l = 0;
+ l = (l << 16) + 0x0123;
+ l = (l << 16) + 0x4567;
+ l = (l << 16) + 0x89ab;
+ l = (l << 16) + 0xcdef;
+ sprintf (buf, "0x%016llx", l);
+ return (strcmp ("0x0123456789abcdef", buf));
+}],
+gdb_cv_printf_has_long_long=yes,
+gdb_cv_printf_has_long_long=no,
+gdb_cv_printf_has_long_long=no)])
+if test $gdb_cv_printf_has_long_long = yes; then
+ AC_DEFINE(PRINTF_HAS_LONG_LONG)
+fi
+AC_MSG_RESULT($gdb_cv_printf_has_long_long)
+
+dnl See if compiler supports "long double" type. Can't use AC_C_LONG_DOUBLE
+dnl because autoconf complains about cross-compilation issues. However, this
+dnl code uses the same variables as the macro for compatibility.
+
+AC_MSG_CHECKING(for long double support in compiler)
+AC_CACHE_VAL(ac_cv_c_long_double,
+[AC_TRY_COMPILE(, [long double foo;],
+ac_cv_c_long_double=yes, ac_cv_c_long_double=no)])
+AC_MSG_RESULT($ac_cv_c_long_double)
+if test $ac_cv_c_long_double = yes; then
+ AC_DEFINE(HAVE_LONG_DOUBLE)
+fi
+
+dnl See if the compiler and runtime support printing long doubles
+
+AC_MSG_CHECKING(for long double support in printf)
+AC_CACHE_VAL(gdb_cv_printf_has_long_double,
+[AC_TRY_RUN([
+int main () {
+ char buf[16];
+ long double f = 3.141592653;
+ sprintf (buf, "%Lg", f);
+ return (strncmp ("3.14159", buf, 7));
+}],
+gdb_cv_printf_has_long_double=yes,
+gdb_cv_printf_has_long_double=no,
+gdb_cv_printf_has_long_double=no)])
+if test $gdb_cv_printf_has_long_double = yes; then
+ AC_DEFINE(PRINTF_HAS_LONG_DOUBLE)
+fi
+AC_MSG_RESULT($gdb_cv_printf_has_long_double)
+
+dnl See if the compiler and runtime support scanning long doubles
+
+AC_MSG_CHECKING(for long double support in scanf)
+AC_CACHE_VAL(gdb_cv_scanf_has_long_double,
+[AC_TRY_RUN([
+int main () {
+ char *buf = "3.141592653";
+ long double f = 0;
+ sscanf (buf, "%Lg", &f);
+ return !(f > 3.14159 && f < 3.14160);
+}],
+gdb_cv_scanf_has_long_double=yes,
+gdb_cv_scanf_has_long_double=no,
+gdb_cv_scanf_has_long_double=no)])
+if test $gdb_cv_scanf_has_long_double = yes; then
+ AC_DEFINE(SCANF_HAS_LONG_DOUBLE)
+fi
+AC_MSG_RESULT($gdb_cv_scanf_has_long_double)
+
+AC_FUNC_MMAP
+
+dnl See if thread_db library is around for Solaris thread debugging. Note that
+dnl we must explicitly test for version 1 of the library because version 0
+dnl (present on Solaris 2.4 or earlier) doesn't have the same API.
+
+dnl Note that we only want this if we are both native (host == target), and
+dnl not doing a canadian cross build (build == host).
+
+if test ${build} = ${host} -a ${host} = ${target} ; then
+ case ${host_os} in
+ hpux*)
+ AC_MSG_CHECKING(for HPUX/OSF thread support)
+ if test -f /usr/include/dce/cma_config.h ; then
+ if test "$GCC" = "yes" ; then
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_HPUX_THREAD_SUPPORT)
+ CONFIG_OBS="${CONFIG_OJS} hpux-thread.o"
+ CONFIG_SRCS="${CONFIG_SRCS} hpux-thread.c"
+ else
+ AC_MSG_RESULT(no (suppressed because you are not using GCC))
+ fi
+ else
+ AC_MSG_RESULT(no)
+ fi
+ ;;
+ solaris*)
+ AC_MSG_CHECKING(for Solaris thread debugging library)
+ if test -f /usr/lib/libthread_db.so.1 ; then
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_THREAD_DB_LIB)
+ CONFIG_OBS="${CONFIG_OBS} sol-thread.o"
+ CONFIG_SRCS="${CONFIG_SRCS} sol-thread.c"
+ AC_CHECK_LIB(dl, dlopen)
+ if test "$GCC" = "yes" ; then
+ # The GNU linker requires the -export-dynamic option to make
+ # all symbols visible in the dynamic symbol table.
+ hold_ldflags=$LDFLAGS
+ AC_MSG_CHECKING(for the ld -export-dynamic flag)
+ LDFLAGS="${LDFLAGS} -Wl,-export-dynamic"
+ AC_TRY_LINK(, [int i;], found=yes, found=no)
+ LDFLAGS=$hold_ldflags
+ AC_MSG_RESULT($found)
+ if test $found = yes; then
+ CONFIG_LDFLAGS="${CONFIG_LDFLAGS} -Wl,-export-dynamic"
+ fi
+ fi
+ # Sun randomly tweaked the prototypes in <proc_service.h>
+ # at one point.
+ AC_MSG_CHECKING(if <proc_service.h> is old)
+ AC_CACHE_VAL(gdb_cv_proc_service_is_old,[
+ AC_TRY_COMPILE([
+ #include <proc_service.h>
+ ps_err_e ps_pdwrite
+ (struct ps_prochandle*, psaddr_t, const void*, size_t);
+ ],, gdb_cv_proc_service_is_old=no,
+ gdb_cv_proc_service_is_old=yes)
+ ])
+ AC_MSG_RESULT($gdb_cv_proc_service_is_old)
+ if test $gdb_cv_proc_service_is_old = yes; then
+ AC_DEFINE(PROC_SERVICE_IS_OLD)
+ fi
+ else
+ AC_MSG_RESULT(no)
+ fi
+ ;;
+ esac
+ AC_SUBST(CONFIG_LDFLAGS)
+fi
+
+dnl Handle optional features that can be enabled.
+ENABLE_CFLAGS=
+
+AC_ARG_ENABLE(tui,
+[ --enable-tui Enable full-screen terminal user interface],
+[
+ case "${enable_tui}" in
+ yes | no) ;;
+ "") enable_tui=yes ;;
+ *)
+ AC_MSG_ERROR(Bad value for --enable-tui: ${enableval})
+ ;;
+ esac
+])
+case ${enable_tui} in
+ "yes" )
+ AC_DEFINE(TUI)
+ BUILD_TUI=all-tui
+ TUI_LIBRARY=tui/libtui.a
+ ;;
+ * )
+ BUILD_TUI=
+ TUI_LIBRARY=
+ ;;
+esac
+AC_SUBST(BUILD_TUI)
+AC_SUBST(TUI_LIBRARY)
+
+AC_ARG_ENABLE(netrom,
+[ --enable-netrom Enable NetROM support],
+[case "${enableval}" in
+yes) enable_netrom=yes ;;
+no) enable_netrom=no ;;
+*) AC_MSG_ERROR(bad value ${enableval} given for netrom option) ;;
+esac])
+
+if test "${enable_netrom}" = "yes"; then
+ CONFIG_OBS="${CONFIG_OBS} remote-nrom.o"
+ CONFIG_SRCS="${CONFIG_SRCS} remote-nrom.c"
+fi
+
+AC_ARG_ENABLE(build-warnings,
+[ --enable-build-warnings Enable build-time compiler warnings if gcc is used],
+[build_warnings="-Wall -Wpointer-arith -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations"
+case "${enableval}" in
+ yes) ;;
+ no) build_warnings="-w";;
+ ,*) t=`echo "${enableval}" | sed -e "s/,/ /g"`
+ build_warnings="${build_warnings} ${t}";;
+ *,) t=`echo "${enableval}" | sed -e "s/,/ /g"`
+ build_warnings="${t} ${build_warnings}";;
+ *) build_warnings=`echo "${enableval}" | sed -e "s/,/ /g"`;;
+esac],[build_warnings=""])dnl
+
+if test "x${build_warnings}" != x -a "x$GCC" = xyes
+then
+ WARN_CFLAGS="${build_warnings}"
+else
+ WARN_CFLAGS=""
+fi
+AC_SUBST(WARN_CFLAGS)
+
+MMALLOC_CFLAGS=
+MMALLOC=
+AC_SUBST(MMALLOC_CFLAGS)
+AC_SUBST(MMALLOC)
+
+AC_ARG_WITH(mmalloc,
+[ --with-mmalloc Use memory mapped malloc package],
+[case "${withval}" in
+ yes) want_mmalloc=true ;;
+ no) want_mmalloc=false;;
+ *) AC_MSG_ERROR(bad value ${withval} for GDB with-mmalloc option) ;;
+esac],[want_mmalloc=false])dnl
+
+if test x$want_mmalloc = xtrue; then
+ AC_DEFINE(USE_MMALLOC)
+ AC_DEFINE(MMCHECK_FORCE)
+ MMALLOC_CFLAGS="-I$srcdir/../mmalloc"
+ MMALLOC='../mmalloc/libmmalloc.a'
+fi
+
+dnl Figure out which term library to use.
+if test x$gdb_cv_os_cygwin = xyes; then
+ TERM_LIB='`if test -r ../libtermcap/libtermcap.a; then echo ../libtermcap/libtermcap.a; else echo -ltermcap; fi`'
+else
+ TERM_LIB=
+ AC_CHECK_LIB(ncurses, tgetent, TERM_LIB=-lncurses,
+ AC_CHECK_LIB(Hcurses, tgetent, TERM_LIB=-lHcurses,
+ AC_CHECK_LIB(termlib, tgetent, TERM_LIB=-ltermlib,
+ AC_CHECK_LIB(termcap, tgetent, TERM_LIB=-ltermcap,
+ AC_CHECK_LIB(curses, tgetent, TERM_LIB=-lcurses,
+ AC_CHECK_LIB(terminfo, tgetent, TERM_LIB=-lterminfo))))))
+
+ if test "x$TERM_LIB" = x
+ then
+ AC_MSG_ERROR(Could not find a term library, e.g. termcap or termlib!)
+ fi
+fi
+AC_SUBST(TERM_LIB)
+
+
+AC_PATH_X
+
+AC_SUBST(ENABLE_CFLAGS)
+
+AC_SUBST(CONFIG_OBS)
+AC_SUBST(CONFIG_DEPS)
+AC_SUBST(CONFIG_SRCS)
+
+# Begin stuff to support --enable-shared
+AC_ARG_ENABLE(shared,
+[ --enable-shared Use shared libraries],
+[case "${enableval}" in
+ yes) shared=true ;;
+ no) shared=false ;;
+ *) shared=true ;;
+esac])dnl
+
+HLDFLAGS=
+HLDENV=
+# If we have shared libraries, try to set rpath reasonably.
+if test "${shared}" = "true"; then
+ case "${host}" in
+ *-*-hpux*)
+ HLDFLAGS='-Wl,+s,+b,$(libdir)'
+ ;;
+ *-*-irix5* | *-*-irix6*)
+ HLDFLAGS='-Wl,-rpath,$(libdir)'
+ ;;
+ *-*-linux*aout*)
+ ;;
+ *-*-linux* | *-pc-linux-gnu)
+ HLDFLAGS='-Wl,-rpath,$(libdir)'
+ ;;
+ *-*-solaris*)
+ HLDFLAGS='-R $(libdir)'
+ ;;
+ *-*-sysv4*)
+ HLDENV='if test -z "$${LD_RUN_PATH}"; then LD_RUN_PATH=$(libdir); else LD_RUN_PATH=$${LD_RUN_PATH}:$(libdir); fi; export LD_RUN_PATH;'
+ ;;
+ esac
+fi
+
+# On SunOS, if the linker supports the -rpath option, use it to
+# prevent ../bfd and ../opcodes from being included in the run time
+# search path.
+case "${host}" in
+ *-*-sunos*)
+ echo 'main () { }' > conftest.c
+ ${CC} -o conftest -Wl,-rpath= conftest.c >/dev/null 2>conftest.t
+ if grep 'unrecognized' conftest.t >/dev/null 2>&1; then
+ :
+ elif grep 'No such file' conftest.t >/dev/null 2>&1; then
+ :
+ elif grep 'do not mix' conftest.t >/dev/null 2>&1; then
+ :
+ elif grep 'some text already loaded' conftest.t >/dev/null 2>&1; then
+ :
+ elif test "${shared}" = "true"; then
+ HLDFLAGS='-Wl,-rpath=$(libdir)'
+ else
+ HLDFLAGS='-Wl,-rpath='
+ fi
+ rm -f conftest.t conftest.c conftest
+ ;;
+esac
+AC_SUBST(HLDFLAGS)
+AC_SUBST(HLDENV)
+# End stuff to support --enable-shared
+
+# target_subdir is used by the testsuite to find the target libraries.
+target_subdir=
+if test "${host}" != "${target}"; then
+ target_subdir="${target_alias}/"
+fi
+AC_SUBST(target_subdir)
+
+frags=
+host_makefile_frag=${srcdir}/config/${gdb_host_cpu}/${gdb_host}.mh
+if test ! -f ${host_makefile_frag}; then
+AC_MSG_ERROR("*** Gdb does not support host ${host}")
+fi
+frags="$frags $host_makefile_frag"
+
+target_makefile_frag=${srcdir}/config/${gdb_target_cpu}/${gdb_target}.mt
+if test ! -f ${target_makefile_frag}; then
+AC_MSG_ERROR("*** Gdb does not support target ${target}")
+fi
+frags="$frags $target_makefile_frag"
+
+AC_SUBST_FILE(host_makefile_frag)
+AC_SUBST_FILE(target_makefile_frag)
+AC_SUBST(frags)
+
+changequote(,)dnl
+hostfile=`sed -n '
+s/XM_FILE[ ]*=[ ]*\([^ ]*\)/\1/p
+' ${host_makefile_frag}`
+
+targetfile=`sed -n '
+s/TM_FILE[ ]*=[ ]*\([^ ]*\)/\1/p
+' ${target_makefile_frag}`
+
+# these really aren't orthogonal true/false values of the same condition,
+# but shells are slow enough that I like to reuse the test conditions
+# whenever possible
+if test "${target}" = "${host}"; then
+nativefile=`sed -n '
+s/NAT_FILE[ ]*=[ ]*\([^ ]*\)/\1/p
+' ${host_makefile_frag}`
+# else
+# GDBserver is only useful in a "native" enviroment
+# configdirs=`echo $configdirs | sed 's/gdbserver//'`
+fi
+changequote([,])
+
+# If hostfile (XM_FILE) and/or targetfile (TM_FILE) and/or nativefile
+# (NAT_FILE) is not set in config/*/*.m[ht] files, we don't make the
+# corresponding links. But we have to remove the xm.h files and tm.h
+# files anyway, e.g. when switching from "configure host" to
+# "configure none".
+
+files=
+links=
+rm -f xm.h
+if test "${hostfile}" != ""; then
+files="${files} config/${gdb_host_cpu}/${hostfile}"
+links="${links} xm.h"
+fi
+rm -f tm.h
+if test "${targetfile}" != ""; then
+files="${files} config/${gdb_target_cpu}/${targetfile}"
+links="${links} tm.h"
+fi
+rm -f nm.h
+if test "${nativefile}" != ""; then
+files="${files} config/${gdb_host_cpu}/${nativefile}"
+links="${links} nm.h"
+else
+# A cross-only configuration.
+files="${files} config/nm-empty.h"
+links="${links} nm.h"
+fi
+
+AC_LINK_FILES($files, $links)
+
+dnl Check for exe extension set on certain hosts (e.g. Win32)
+AC_EXEEXT
+
+AC_CONFIG_SUBDIRS($configdirs)
+AC_OUTPUT(Makefile tui/Makefile .gdbinit:gdbinit.in,
+[
+dnl Autoconf doesn't provide a mechanism for modifying definitions
+dnl provided by makefile fragments.
+dnl
+if test "${nativefile}" = ""; then
+sed -e '/^NATDEPFILES[[ ]]*=[[ ]]*/s//# NATDEPFILES=/' \
+ < Makefile > Makefile.tem
+mv -f Makefile.tem Makefile
+fi
+
+changequote(,)dnl
+sed -e '/^TM_FILE[ ]*=/s,^TM_FILE[ ]*=[ ]*,&config/'"${gdb_target_cpu}"'/,
+/^XM_FILE[ ]*=/s,^XM_FILE[ ]*=[ ]*,&config/'"${gdb_host_cpu}"'/,
+/^NAT_FILE[ ]*=/s,^NAT_FILE[ ]*=[ ]*,&config/'"${gdb_host_cpu}"'/,' <Makefile >Makefile.tmp
+mv -f Makefile.tmp Makefile
+changequote([,])dnl
+
+case x$CONFIG_HEADERS in
+xconfig.h:config.in)
+echo > stamp-h ;;
+esac
+],
+[
+gdb_host_cpu=$gdb_host_cpu
+gdb_target_cpu=$gdb_target_cpu
+nativefile=$nativefile
+])
+
+exit 0
diff --git a/gdb/configure.tgt b/gdb/configure.tgt
new file mode 100644
index 00000000000..95fc2741943
--- /dev/null
+++ b/gdb/configure.tgt
@@ -0,0 +1,282 @@
+# Mappings from configurations to GDB target definitions. This is
+# invoked from the autoconf generated configure script.
+
+# This file sets the following shell variables:
+# gdb_target_cpu generic name of CPU
+# gdb_target name of GDB target definition to use
+
+# This file may also modify configdirs.
+
+# Map target cpu into the config cpu subdirectory name.
+# The default is $target_cpu.
+
+case "${target_cpu}" in
+
+alpha*) gdb_target_cpu=alpha ;;
+c[12]) gdb_target_cpu=convex ;;
+hppa*) gdb_target_cpu=pa ;;
+i[3456]86*) gdb_target_cpu=i386 ;;
+m68*) gdb_target_cpu=m68k ;;
+m88*) gdb_target_cpu=m88k ;;
+mips*) gdb_target_cpu=mips ;;
+# OBSOLETE np1) gdb_target_cpu=gould ;;
+powerpc*) gdb_target_cpu=powerpc ;;
+# OBSOLETE pn) gdb_target_cpu=gould ;;
+pyramid) gdb_target_cpu=pyr ;;
+sparc*) gdb_target_cpu=sparc ;;
+thumb*) gdb_target_cpu=arm ;;
+strongarm*) gdb_target_cpu=arm ;;
+v850*) gdb_target_cpu=v850 ;;
+*) gdb_target_cpu=$target_cpu ;;
+
+esac
+
+# map target info into gdb names.
+
+case "${target}" in
+
+a29k-*-aout*) gdb_target=a29k ;;
+a29k-*-coff*) gdb_target=a29k ;;
+a29k-*-elf*) gdb_target=a29k ;;
+a29k-*-ebmon*) gdb_target=a29k ;;
+a29k-*-kern*) gdb_target=a29k-kern ;;
+a29k-*-none*) gdb_target=a29k ;;
+a29k-*-sym1*) gdb_target=ultra3 ;;
+a29k-*-udi*) gdb_target=a29k-udi ;;
+a29k-*-vxworks*) gdb_target=vx29k ;;
+
+alpha*-*-osf*) gdb_target=alpha-osf1 ;;
+alpha*-*-linux*) gdb_target=alpha-linux ;;
+
+arc-*-*) gdb_target=arc ;;
+
+arm-*-* | thumb-*-* | strongarm-*-*) gdb_target=arm
+
+ # rdi doesn't work for wingdb yet
+ case $gdb_host in
+ windows) ;;
+ *)
+ configdirs="$configdirs rdi-share"
+ CONFIG_OBS="$CONFIG_OBS remote-rdi.o rdi-share/libangsd.a"
+ ;;
+ esac
+ ;;
+
+c1-*-*) gdb_target=convex ;;
+c2-*-*) gdb_target=convex ;;
+
+d10v-*-*) gdb_target=d10v ;;
+d30v-*-*) gdb_target=d30v ;;
+
+h8300-*-*) gdb_target=h8300 ;;
+h8500-*-*) gdb_target=h8500 ;;
+
+sh-*-*) gdb_target=sh ;;
+
+fr30-*-elf*) gdb_target=fr30 ;;
+
+hppa*-*-bsd*) gdb_target=hppabsd ;;
+hppa*-*-pro*) gdb_target=hppapro ;;
+hppa*-*-hpux*) gdb_target=hppahpux ;;
+hppa*-*-hiux*) gdb_target=hppahpux ;;
+hppa*-*-osf*) gdb_target=hppaosf ;;
+
+i[3456]86-sequent-bsd*) gdb_target=symmetry ;;
+i[3456]86-sequent-sysv4*) gdb_target=ptx4 ;;
+i[3456]86-sequent-sysv*) gdb_target=ptx ;;
+i[3456]86-ncr-*) gdb_target=ncr3000 ;;
+i[3456]86-*-aout*) gdb_target=i386aout ;;
+i[3456]86-*-coff*) gdb_target=i386v ;;
+i[3456]86-*-elf*) gdb_target=i386v ;;
+i[3456]86-*-aix*) gdb_target=i386aix ;;
+i[3456]86-*-bsd*) gdb_target=i386bsd ;;
+i[3456]86-*-freebsd*) gdb_target=fbsd ;;
+i[3456]86-*-netbsd*) gdb_target=nbsd ;;
+i[3456]86-*-os9k) gdb_target=i386os9k ;;
+i[3456]86-*-go32*) gdb_target=i386aout ;;
+i[3456]86-*-lynxos*) gdb_target=i386lynx
+ configdirs="${configdirs} gdbserver" ;;
+i[3456]86-*-solaris*) gdb_target=i386sol2 ;;
+i[3456]86-*-sunos*) gdb_target=sun386 ;;
+i[3456]86-*-sysv4.2MP) gdb_target=i386v42mp ;;
+i[3456]86-*-sysv4.2uw2*) gdb_target=i386v42mp ;;
+i[3456]86-*-sysv4*) gdb_target=i386v4 ;;
+i[3456]86-*-unixware2*) gdb_target=i386v42mp ;;
+i[3456]86-*-unixware*) gdb_target=i386v4 ;;
+i[3456]86-*-sco3.2v4*) gdb_target=i386sco4 ;;
+i[3456]86-*-sco3.2v5*) gdb_target=i386sco5 ;;
+i[3456]86-*-sco*) gdb_target=i386v ;;
+i[3456]86-*-sysv*) gdb_target=i386v ;;
+i[3456]86-*-linux*) gdb_target=linux
+ configdirs="${configdirs} gdbserver" ;;
+i[3456]86-pc-linux-gnu) gdb_target=linux
+ configdirs="${configdirs} gdbserver" ;;
+i[3456]86-*-isc*) gdb_target=i386v ;;
+i[3456]86-*-mach3*) gdb_target=i386m3 ;;
+i[3456]86-*-gnu*) gdb_target=i386gnu ;;
+i[3456]86-*-netware*) gdb_target=i386nw
+ configdirs="${configdirs} nlm" ;;
+i[3456]86-*-osf1mk*) gdb_target=i386mk ;;
+i[3456]86-*-cygwin*) gdb_target=cygwin ;;
+i960-*-bout*) gdb_target=vxworks960 ;;
+i960-nindy-coff*) gdb_target=nindy960 ;;
+i960-*-coff*) gdb_target=mon960 ;;
+i960-nindy-elf*) gdb_target=nindy960 ;;
+i960-*-elf*) gdb_target=mon960 ;;
+
+i960-*-nindy*) gdb_target=nindy960 ;;
+i960-*-vxworks*) gdb_target=vxworks960 ;;
+
+m32r-*-elf*) gdb_target=m32r ;;
+
+m68000-*-sunos3*) gdb_target=sun2os3 ;;
+m68000-*-sunos4*) gdb_target=sun2os4 ;;
+
+m68*-apollo*-bsd*) gdb_target=apollo68b ;;
+m68*-bull-sysv*) gdb_target=dpx2 ;;
+m68*-hp-bsd*) gdb_target=hp300bsd ;;
+m68*-hp-hpux*) gdb_target=hp300hpux ;;
+m68*-altos-*) gdb_target=altos ;;
+m68*-att-*) gdb_target=3b1 ;;
+m68*-cisco*-*) gdb_target=cisco ;;
+m68*-ericsson-*) gdb_target=es1800 ;;
+m68*-isi-*) gdb_target=isi ;;
+m68*-motorola-*) gdb_target=delta68 ;;
+m68*-netx-*) gdb_target=vxworks68 ;;
+m68*-sony-*) gdb_target=news ;;
+m68*-tandem-*) gdb_target=st2000 ;;
+m68*-rom68k-*) gdb_target=monitor ;;
+m68*-*bug-*) gdb_target=monitor ;;
+m68*-monitor-*) gdb_target=monitor ;;
+m68*-est-*) gdb_target=monitor ;;
+m68*-*-aout*) gdb_target=monitor ;;
+m68*-*-coff*) gdb_target=monitor ;;
+m68*-*-elf*) gdb_target=monitor ;;
+m68*-*-linux*) gdb_target=linux
+ configdirs="${configdirs} gdbserver" ;;
+m68*-*-lynxos*) gdb_target=m68klynx
+ configdirs="${configdirs} gdbserver" ;;
+m68*-*-netbsd*) gdb_target=nbsd ;;
+m68*-*-os68k*) gdb_target=os68k ;;
+m68*-*-sunos3*) gdb_target=sun3os3 ;;
+m68*-*-sunos4*) gdb_target=sun3os4 ;;
+m68*-*-sysv4*) gdb_target=m68kv4 ;;
+m68*-*-vxworks*) gdb_target=vxworks68 ;;
+
+m88*-harris-cxux*) gdb_target=cxux ;;
+m88*-motorola-sysv4*) gdb_target=delta88v4 ;;
+m88*-motorola-*) gdb_target=delta88 ;;
+m88*-*-*) gdb_target=m88k ;;
+
+mips64*-big-*) gdb_target=bigmips64 ;;
+mips*-big-*) gdb_target=bigmips ;;
+mips*-dec-mach3*) gdb_target=mach3 ;;
+mips*-dec-*) gdb_target=decstation ;;
+mips64*el-*-ecoff*) gdb_target=embedl64 ;;
+mips64*-*-ecoff*) gdb_target=embed64 ;;
+mips64*vr4300*el-*-elf*) gdb_target=vr4300el ;;
+mips64*vr4300*-*-elf*) gdb_target=vr4300 ;;
+mips64*vr4100*el-*-elf*) gdb_target=vr4300el ;;
+mips64*vr4100*-*-elf*) gdb_target=vr4100 ;;
+mips64*vr5000*el-*-elf*) gdb_target=vr5000el ;;
+mips64*vr5000*-*-elf*) gdb_target=vr5000
+ configdirs="${configdirs} gdbserver" ;;
+mips*tx39*el*-elf*) gdb_target=tx39l ;;
+mips*tx39*-elf*) gdb_target=tx39 ;;
+mips64*el-*-elf*) gdb_target=embedl64 ;;
+mips64*-*-elf*) gdb_target=embed64 ;;
+mips*el-*-ecoff*) gdb_target=embedl ;;
+mips*-*-ecoff*) gdb_target=embed ;;
+mips*el-*-elf*) gdb_target=embedl ;;
+mips*-*-elf*) gdb_target=embed ;;
+mips*-little-*) gdb_target=littlemips ;;
+mips*-*-lnews*) gdb_target=embedl ;;
+mips*-sgi-irix5*) gdb_target=irix5 ;;
+mips*-sgi-irix6*) gdb_target=irix5 ;;
+mips*-sgi-*) gdb_target=irix3 ;;
+mips*-sony-*) gdb_target=bigmips ;;
+mips*-*-mach3*) gdb_target=mipsm3 ;;
+mips*-*-sysv4*) gdb_target=mipsv4 ;;
+mips*-*-sysv*) gdb_target=bigmips ;;
+mips*-*-riscos*) gdb_target=bigmips ;;
+mips*-*-vxworks*) gdb_target=vxmips ;;
+
+mn10200-*-*) gdb_target=mn10200 ;;
+mn10300-*-*) gdb_target=mn10300 ;;
+
+none-*-*) gdb_target=none ;;
+
+# OBSOLETE np1-*-*) gdb_target=np1 ;;
+
+ns32k-*-mach3*) gdb_target=ns32km3 ;;
+ns32k-*-netbsd*) gdb_target=nbsd ;;
+ns32k-utek-sysv*) gdb_target=merlin ;;
+ns32k-utek-*) gdb_target=umax ;;
+
+# OBSOLETE pn-*-*) gdb_target=pn ;;
+
+powerpc-*-macos*) gdb_target=macos ;;
+powerpc-*-netware*) gdb_target=ppc-nw
+ configdirs="${configdirs} nlm" ;;
+
+powerpc-*-aix*) gdb_target=aix ;;
+powerpcle-*-cygwin*) gdb_target=cygwin ;;
+powerpcle-*-solaris*) gdb_target=solaris ;;
+powerpc-*-eabi* | powerpc-*-linux* | powerpc-*-sysv* | powerpc-*-elf*)
+ if test -f ../sim/ppc/Makefile; then
+ gdb_target=ppc-sim
+ else
+ gdb_target=ppc-eabi
+ fi ;;
+powerpcle-*-eabi* | powerpcle-*-sysv* | powerpcle-*-elf*)
+ if test -f ../sim/ppc/Makefile; then
+ gdb_target=ppcle-sim
+ else
+ gdb_target=ppcle-eabi
+ fi ;;
+
+pyramid-*-*) gdb_target=pyramid ;;
+
+rs6000-*-lynxos*) gdb_target=rs6000lynx ;;
+rs6000-*-aix4*) gdb_target=aix4 ;;
+rs6000-*-*) gdb_target=rs6000 ;;
+
+sparc-*-aout*) gdb_target=sparc-em ;;
+sparc-*-coff*) gdb_target=sparc-em ;;
+sparc-*-elf*) gdb_target=sparc-em ;;
+sparc-*-linux*) gdb_target=linux ;;
+sparc-*-lynxos*) gdb_target=sparclynx
+ configdirs="${configdirs} gdbserver" ;;
+sparc-*-netbsd*) gdb_target=nbsd ;;
+sparc-*-solaris2*) gdb_target=sun4sol2 ;;
+sparc-*-sunos4*) gdb_target=sun4os4 ;;
+sparc-*-sunos5*) gdb_target=sun4sol2 ;;
+sparc-*-vxworks*) gdb_target=vxsparc ;;
+sparc-*-*) gdb_target=sun4os4 ;;
+sparclet-*-*) gdb_target=sparclet;;
+sparclite-*-*) gdb_target=sparclite ;;
+sparc86x-*-*) gdb_target=sparclite ;;
+# It's not clear what the right solution for "v8plus" systems is yet.
+# For now, stick with sparc-sun-solaris2 since that's what config.guess
+# should return. Work is still needed to get gdb to print the 64 bit
+# regs (some of which are usable in v8plus) so sp64sol.mt hasn't been
+# deleted though presumably it should be eventually.
+#sparc64-*-solaris2*) gdb_target=sp64sol2 ;;
+sparc64-*-*) gdb_target=sp64 ;;
+
+tahoe-*-*) gdb_target=tahoe ;;
+
+
+vax-*-*) gdb_target=vax ;;
+
+fr30-*-*) gdb_target=fr30
+ ;;
+
+v850*-*-*) gdb_target=v850
+ ;;
+
+w65-*-*) gdb_target=w65 ;;
+
+z8k-*-coff*) gdb_target=z8k ;;
+
+esac
diff --git a/gdb/convex-tdep.c b/gdb/convex-tdep.c
new file mode 100644
index 00000000000..8eeb2b348a0
--- /dev/null
+++ b/gdb/convex-tdep.c
@@ -0,0 +1,1217 @@
+/* Convex stuff for GDB.
+ Copyright (C) 1990, 1991, 1996 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "command.h"
+#include "symtab.h"
+#include "value.h"
+#include "frame.h"
+#include "inferior.h"
+#include "wait.h"
+
+#include <signal.h>
+#include <fcntl.h>
+
+#include "gdbcore.h"
+#include <sys/param.h>
+#include <sys/dir.h>
+#include <sys/user.h>
+#include <sys/ioctl.h>
+#include <sys/pcntl.h>
+#include <sys/thread.h>
+#include <sys/proc.h>
+#include <sys/file.h>
+#include "gdb_stat.h"
+#include <sys/mman.h>
+
+#include "gdbcmd.h"
+
+exec_file_command (filename, from_tty)
+ char *filename;
+ int from_tty;
+{
+ int val;
+ int n;
+ struct stat st_exec;
+
+ /* Eliminate all traces of old exec file.
+ Mark text segment as empty. */
+
+ if (execfile)
+ free (execfile);
+ execfile = 0;
+ data_start = 0;
+ data_end = 0;
+ text_start = 0;
+ text_end = 0;
+ exec_data_start = 0;
+ exec_data_end = 0;
+ if (execchan >= 0)
+ close (execchan);
+ execchan = -1;
+
+ n_exec = 0;
+
+ /* Now open and digest the file the user requested, if any. */
+
+ if (filename)
+ {
+ filename = tilde_expand (filename);
+ make_cleanup (free, filename);
+
+ execchan = openp (getenv ("PATH"), 1, filename, O_RDONLY, 0,
+ &execfile);
+ if (execchan < 0)
+ perror_with_name (filename);
+
+ if (myread (execchan, &filehdr, sizeof filehdr) < 0)
+ perror_with_name (filename);
+
+ if (! IS_SOFF_MAGIC (filehdr.h_magic))
+ error ("%s: not an executable file.", filename);
+
+ if (myread (execchan, &opthdr, filehdr.h_opthdr) <= 0)
+ perror_with_name (filename);
+
+ /* Read through the section headers.
+ For text, data, etc, record an entry in the exec file map.
+ Record text_start and text_end. */
+
+ lseek (execchan, (long) filehdr.h_scnptr, 0);
+
+ for (n = 0; n < filehdr.h_nscns; n++)
+ {
+ if (myread (execchan, &scnhdr, sizeof scnhdr) < 0)
+ perror_with_name (filename);
+
+ if ((scnhdr.s_flags & S_TYPMASK) >= S_TEXT
+ && (scnhdr.s_flags & S_TYPMASK) <= S_COMON)
+ {
+ exec_map[n_exec].mem_addr = scnhdr.s_vaddr;
+ exec_map[n_exec].mem_end = scnhdr.s_vaddr + scnhdr.s_size;
+ exec_map[n_exec].file_addr = scnhdr.s_scnptr;
+ exec_map[n_exec].type = scnhdr.s_flags & S_TYPMASK;
+ n_exec++;
+
+ if ((scnhdr.s_flags & S_TYPMASK) == S_TEXT)
+ {
+ text_start = scnhdr.s_vaddr;
+ text_end = scnhdr.s_vaddr + scnhdr.s_size;
+ }
+ }
+ }
+
+ fstat (execchan, &st_exec);
+ exec_mtime = st_exec.st_mtime;
+
+ validate_files ();
+ }
+ else if (from_tty)
+ printf_filtered ("No executable file now.\n");
+
+ /* Tell display code (if any) about the changed file name. */
+ if (exec_file_display_hook)
+ (*exec_file_display_hook) (filename);
+}
+
+#if 0
+/* Read data from SOFF exec or core file.
+ Return 0 on success, EIO if address out of bounds. */
+
+int
+xfer_core_file (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+{
+ register int i;
+ register int n;
+ register int val;
+ int xferchan;
+ char **xferfile;
+ int fileptr;
+ int returnval = 0;
+
+ while (len > 0)
+ {
+ xferfile = 0;
+ xferchan = 0;
+
+ /* Determine which file the next bunch of addresses reside in,
+ and where in the file. Set the file's read/write pointer
+ to point at the proper place for the desired address
+ and set xferfile and xferchan for the correct file.
+ If desired address is nonexistent, leave them zero.
+ i is set to the number of bytes that can be handled
+ along with the next address. */
+
+ i = len;
+
+ for (n = 0; n < n_core; n++)
+ {
+ if (memaddr >= core_map[n].mem_addr && memaddr < core_map[n].mem_end
+ && (core_map[n].thread == -1
+ || core_map[n].thread == inferior_thread))
+ {
+ i = min (len, core_map[n].mem_end - memaddr);
+ fileptr = core_map[n].file_addr + memaddr - core_map[n].mem_addr;
+ if (core_map[n].file_addr)
+ {
+ xferfile = &corefile;
+ xferchan = corechan;
+ }
+ break;
+ }
+ else if (core_map[n].mem_addr >= memaddr
+ && core_map[n].mem_addr < memaddr + i)
+ i = core_map[n].mem_addr - memaddr;
+ }
+
+ if (!xferfile)
+ for (n = 0; n < n_exec; n++)
+ {
+ if (memaddr >= exec_map[n].mem_addr
+ && memaddr < exec_map[n].mem_end)
+ {
+ i = min (len, exec_map[n].mem_end - memaddr);
+ fileptr = exec_map[n].file_addr + memaddr
+ - exec_map[n].mem_addr;
+ if (exec_map[n].file_addr)
+ {
+ xferfile = &execfile;
+ xferchan = execchan;
+ }
+ break;
+ }
+ else if (exec_map[n].mem_addr >= memaddr
+ && exec_map[n].mem_addr < memaddr + i)
+ i = exec_map[n].mem_addr - memaddr;
+ }
+
+ /* Now we know which file to use.
+ Set up its pointer and transfer the data. */
+ if (xferfile)
+ {
+ if (*xferfile == 0)
+ if (xferfile == &execfile)
+ error ("No program file to examine.");
+ else
+ error ("No core dump file or running program to examine.");
+ val = lseek (xferchan, fileptr, 0);
+ if (val < 0)
+ perror_with_name (*xferfile);
+ val = myread (xferchan, myaddr, i);
+ if (val < 0)
+ perror_with_name (*xferfile);
+ }
+ /* If this address is for nonexistent memory,
+ read zeros if reading, or do nothing if writing. */
+ else
+ {
+ memset (myaddr, '\0', i);
+ returnval = EIO;
+ }
+
+ memaddr += i;
+ myaddr += i;
+ len -= i;
+ }
+ return returnval;
+}
+#endif
+
+/* Here from info files command to print an address map. */
+
+print_maps ()
+{
+ struct pmap ptrs[200];
+ int n;
+
+ /* ID strings for core and executable file sections */
+
+ static char *idstr[] =
+ {
+ "0", "text", "data", "tdata", "bss", "tbss",
+ "common", "ttext", "ctx", "tctx", "10", "11", "12",
+ };
+
+ for (n = 0; n < n_core; n++)
+ {
+ core_map[n].which = 0;
+ ptrs[n] = core_map[n];
+ }
+ for (n = 0; n < n_exec; n++)
+ {
+ exec_map[n].which = 1;
+ ptrs[n_core+n] = exec_map[n];
+ }
+
+ qsort (ptrs, n_core + n_exec, sizeof *ptrs, ptr_cmp);
+
+ for (n = 0; n < n_core + n_exec; n++)
+ {
+ struct pmap *p = &ptrs[n];
+ if (n > 0)
+ {
+ if (p->mem_addr < ptrs[n-1].mem_end)
+ p->mem_addr = ptrs[n-1].mem_end;
+ if (p->mem_addr >= p->mem_end)
+ continue;
+ }
+ printf_filtered ("%08x .. %08x %-6s %s\n",
+ p->mem_addr, p->mem_end, idstr[p->type],
+ p->which ? execfile : corefile);
+ }
+}
+
+/* Compare routine to put file sections in order.
+ Sort into increasing order on address, and put core file sections
+ before exec file sections if both files contain the same addresses. */
+
+static ptr_cmp (a, b)
+ struct pmap *a, *b;
+{
+ if (a->mem_addr != b->mem_addr) return a->mem_addr - b->mem_addr;
+ return a->which - b->which;
+}
+
+/* Trapped internal variables are used to handle special registers.
+ A trapped i.v. calls a hook here every time it is dereferenced,
+ to provide a new value for the variable, and it calls a hook here
+ when a new value is assigned, to do something with the value.
+
+ The vector registers are $vl, $vs, $vm, $vN, $VN (N in 0..7).
+ The communication registers are $cN, $CN (N in 0..63).
+ They not handled as regular registers because it's expensive to
+ read them, and their size varies, and they have too many names. */
+
+
+/* Return 1 if NAME is a trapped internal variable, else 0. */
+
+int
+is_trapped_internalvar (name)
+ char *name;
+{
+ if ((name[0] == 'c' || name[0] == 'C')
+ && name[1] >= '0' && name[1] <= '9'
+ && (name[2] == '\0'
+ || (name[2] >= '0' && name[2] <= '9'
+ && name[3] == '\0' && name[1] != '0'))
+ && atoi (&name[1]) < 64) return 1;
+
+ if ((name[0] == 'v' || name[0] == 'V')
+ && (((name[1] & -8) == '0' && name[2] == '\0')
+ || STREQ (name, "vl")
+ || STREQ (name, "vs")
+ || STREQ (name, "vm")))
+ return 1;
+ else return 0;
+}
+
+/* Return the value of trapped internal variable VAR */
+
+value
+value_of_trapped_internalvar (var)
+ struct internalvar *var;
+{
+ char *name = var->name;
+ value val;
+ struct type *type;
+ struct type *range_type;
+ long len = *read_vector_register (VL_REGNUM);
+ if (len <= 0 || len > 128) len = 128;
+
+ if (STREQ (name, "vl"))
+ {
+ val = value_from_longest (builtin_type_int,
+ (LONGEST) *read_vector_register_1 (VL_REGNUM));
+ }
+ else if (STREQ (name, "vs"))
+ {
+ val = value_from_longest (builtin_type_int,
+ (LONGEST) *read_vector_register_1 (VS_REGNUM));
+ }
+ else if (STREQ (name, "vm"))
+ {
+ long vm[4];
+ long i, *p;
+ memcpy (vm, read_vector_register_1 (VM_REGNUM), sizeof vm);
+ range_type =
+ create_range_type ((struct type *) NULL, builtin_type_int, 0, len - 1);
+ type =
+ create_array_type ((struct type *) NULL, builtin_type_int, range_type);
+ val = allocate_value (type);
+ p = (long *) VALUE_CONTENTS (val);
+ for (i = 0; i < len; i++)
+ *p++ = !! (vm[3 - (i >> 5)] & (1 << (i & 037)));
+ }
+ else if (name[0] == 'V')
+ {
+ range_type =
+ create_range_type ((struct type *) NULL, builtin_type_int 0, len - 1);
+ type =
+ create_array_type ((struct type *) NULL, builtin_type_long_long,
+ range_type);
+ val = allocate_value (type);
+ memcpy (VALUE_CONTENTS (val),
+ read_vector_register_1 (name[1] - '0'),
+ TYPE_LENGTH (type));
+ }
+ else if (name[0] == 'v')
+ {
+ long *p1, *p2;
+ range_type =
+ create_range_type ((struct type *) NULL, builtin_type_int 0, len - 1);
+ type =
+ create_array_type ((struct type *) NULL, builtin_type_long,
+ range_type);
+ val = allocate_value (type);
+ p1 = read_vector_register_1 (name[1] - '0');
+ p2 = (long *) VALUE_CONTENTS (val);
+ while (--len >= 0) {p1++; *p2++ = *p1++;}
+ }
+
+ else if (name[0] == 'c')
+ val = value_from_longest (builtin_type_int,
+ read_comm_register (atoi (&name[1])));
+ else if (name[0] == 'C')
+ val = value_from_longest (builtin_type_long_long,
+ read_comm_register (atoi (&name[1])));
+
+ VALUE_LVAL (val) = lval_internalvar;
+ VALUE_INTERNALVAR (val) = var;
+ return val;
+}
+
+/* Handle a new value assigned to a trapped internal variable */
+
+void
+set_trapped_internalvar (var, val, bitpos, bitsize, offset)
+ struct internalvar *var;
+ value val;
+ int bitpos, bitsize, offset;
+{
+ char *name = var->name;
+ long long newval = value_as_long (val);
+
+ if (STREQ (name, "vl"))
+ write_vector_register (VL_REGNUM, 0, newval);
+ else if (STREQ (name, "vs"))
+ write_vector_register (VS_REGNUM, 0, newval);
+ else if (name[0] == 'c' || name[0] == 'C')
+ write_comm_register (atoi (&name[1]), newval);
+ else if (STREQ (name, "vm"))
+ error ("can't assign to $vm");
+ else
+ {
+ offset /= bitsize / 8;
+ write_vector_register (name[1] - '0', offset, newval);
+ }
+}
+
+/* Print an integer value when no format was specified. gdb normally
+ prints these values in decimal, but the the leading 0x80000000 of
+ pointers produces intolerable 10-digit negative numbers.
+ If it looks like an address, print it in hex instead. */
+
+decout (stream, type, val)
+ GDB_FILE *stream;
+ struct type *type;
+ LONGEST val;
+{
+ long lv = val;
+
+ switch (output_radix)
+ {
+ case 0:
+ if ((lv == val || (unsigned) lv == val)
+ && ((lv & 0xf0000000) == 0x80000000
+ || ((lv & 0xf0000000) == 0xf0000000 && lv < STACK_END_ADDR)))
+ {
+ print_longest (stream, "x", 0, val);
+ return;
+ }
+
+ case 10:
+ print_longest (stream, TYPE_UNSIGNED (type) ? "u" : "d", 0, val);
+ return;
+
+ case 8:
+ print_longest (stream, "o", 0, val);
+ return;
+
+ case 16:
+ print_longest (stream, "x", 0, val);
+ return;
+ }
+}
+
+/* Change the default output radix to 10 or 16, or set it to 0 (heuristic).
+ This command is mostly obsolete now that the print command allows
+ formats to apply to aggregates, but is still handy occasionally. */
+
+static void
+set_base_command (arg)
+ char *arg;
+{
+ int new_radix;
+
+ if (!arg)
+ output_radix = 0;
+ else
+ {
+ new_radix = atoi (arg);
+ if (new_radix != 10 && new_radix != 16 && new_radix != 8)
+ error ("base must be 8, 10 or 16, or null");
+ else output_radix = new_radix;
+ }
+}
+
+/* Turn pipelining on or off in the inferior. */
+
+static void
+set_pipelining_command (arg)
+ char *arg;
+{
+ if (!arg)
+ {
+ sequential = !sequential;
+ printf_filtered ("%s\n", sequential ? "off" : "on");
+ }
+ else if (STREQ (arg, "on"))
+ sequential = 0;
+ else if (STREQ (arg, "off"))
+ sequential = 1;
+ else error ("valid args are `on', to allow instructions to overlap, or\n\
+`off', to prevent it and thereby pinpoint exceptions.");
+}
+
+/* Enable, disable, or force parallel execution in the inferior. */
+
+static void
+set_parallel_command (arg)
+ char *arg;
+{
+ struct rlimit rl;
+ int prevparallel = parallel;
+
+ if (!strncmp (arg, "fixed", strlen (arg)))
+ parallel = 2;
+ else if (STREQ (arg, "on"))
+ parallel = 1;
+ else if (STREQ (arg, "off"))
+ parallel = 0;
+ else error ("valid args are `on', to allow multiple threads, or\n\
+`fixed', to force multiple threads, or\n\
+`off', to run with one thread only.");
+
+ if ((prevparallel == 0) != (parallel == 0) && inferior_pid)
+ printf_filtered ("will take effect at next run.\n");
+
+ getrlimit (RLIMIT_CONCUR, &rl);
+ rl.rlim_cur = parallel ? rl.rlim_max : 1;
+ setrlimit (RLIMIT_CONCUR, &rl);
+
+ if (inferior_pid)
+ set_fixed_scheduling (inferior_pid, parallel == 2);
+}
+
+/* Add a new name for an existing command. */
+
+static void
+alias_command (arg)
+ char *arg;
+{
+ static char *aliaserr = "usage is `alias NEW OLD', no args allowed";
+ char *newname = arg;
+ struct cmd_list_element *new, *old;
+
+ if (!arg)
+ error_no_arg ("newname oldname");
+
+ new = lookup_cmd (&arg, cmdlist, "", -1);
+ if (new && !strncmp (newname, new->name, strlen (new->name)))
+ {
+ newname = new->name;
+ if (!(*arg == '-'
+ || (*arg >= 'a' && *arg <= 'z')
+ || (*arg >= 'A' && *arg <= 'Z')
+ || (*arg >= '0' && *arg <= '9')))
+ error (aliaserr);
+ }
+ else
+ {
+ arg = newname;
+ while (*arg == '-'
+ || (*arg >= 'a' && *arg <= 'z')
+ || (*arg >= 'A' && *arg <= 'Z')
+ || (*arg >= '0' && *arg <= '9'))
+ arg++;
+ if (*arg != ' ' && *arg != '\t')
+ error (aliaserr);
+ *arg = '\0';
+ arg++;
+ }
+
+ old = lookup_cmd (&arg, cmdlist, "", 0);
+
+ if (*arg != '\0')
+ error (aliaserr);
+
+ if (new && !strncmp (newname, new->name, strlen (new->name)))
+ {
+ char *tem;
+ if (new->class == (int) class_user || new->class == (int) class_alias)
+ tem = "Redefine command \"%s\"? ";
+ else
+ tem = "Really redefine built-in command \"%s\"? ";
+ if (!query (tem, new->name))
+ error ("Command \"%s\" not redefined.", new->name);
+ }
+
+ add_com (newname, class_alias, old->function, old->doc);
+}
+
+
+
+/* Print the current thread number, and any threads with signals in the
+ queue. */
+
+thread_info ()
+{
+ struct threadpid *p;
+
+ if (have_inferior_p ())
+ {
+ ps.pi_buffer = (char *) &comm_registers;
+ ps.pi_nbytes = sizeof comm_registers;
+ ps.pi_offset = 0;
+ ps.pi_thread = inferior_thread;
+ ioctl (inferior_fd, PIXRDCREGS, &ps);
+ }
+
+ /* FIXME: stop_signal is from target.h but stop_sigcode is a
+ convex-specific thing. */
+ printf_filtered ("Current thread %d stopped with signal %d.%d (%s).\n",
+ inferior_thread, stop_signal, stop_sigcode,
+ subsig_name (stop_signal, stop_sigcode));
+
+ for (p = signal_stack; p->pid; p--)
+ printf_filtered ("Thread %d stopped with signal %d.%d (%s).\n",
+ p->thread, p->signo, p->subsig,
+ subsig_name (p->signo, p->subsig));
+
+ if (iscrlbit (comm_registers.crctl.lbits.cc, 64+13))
+ printf_filtered ("New thread start pc %#x\n",
+ (long) (comm_registers.crreg.pcpsw >> 32));
+}
+
+/* Return string describing a signal.subcode number */
+
+static char *
+subsig_name (signo, subcode)
+ int signo, subcode;
+{
+ static char *subsig4[] = {
+ "error exit", "privileged instruction", "unknown",
+ "unknown", "undefined opcode",
+ 0};
+ static char *subsig5[] = {0,
+ "breakpoint", "single step", "fork trap", "exec trap", "pfork trap",
+ "join trap", "idle trap", "last thread", "wfork trap",
+ "process breakpoint", "trap instruction",
+ 0};
+ static char *subsig8[] = {0,
+ "int overflow", "int divide check", "float overflow",
+ "float divide check", "float underflow", "reserved operand",
+ "sqrt error", "exp error", "ln error", "sin error", "cos error",
+ 0};
+ static char *subsig10[] = {0,
+ "invalid inward ring address", "invalid outward ring call",
+ "invalid inward ring return", "invalid syscall gate",
+ "invalid rtn frame length", "invalid comm reg address",
+ "invalid trap gate",
+ 0};
+ static char *subsig11[] = {0,
+ "read access denied", "write access denied", "execute access denied",
+ "segment descriptor fault", "page table fault", "data reference fault",
+ "i/o access denied", "levt pte invalid",
+ 0};
+
+ static char **subsig_list[] =
+ {0, 0, 0, 0, subsig4, subsig5, 0, 0, subsig8, 0, subsig10, subsig11, 0};
+
+ int i;
+ char *p;
+
+ if ((p = strsignal (signo)) == NULL)
+ p = "unknown";
+ if (signo >= (sizeof subsig_list / sizeof *subsig_list)
+ || !subsig_list[signo])
+ return p;
+ for (i = 1; subsig_list[signo][i]; i++)
+ if (i == subcode)
+ return subsig_list[signo][subcode];
+ return p;
+}
+
+
+/* Print a compact display of thread status, essentially x/i $pc
+ for all active threads. */
+
+static void
+threadstat ()
+{
+ int t;
+
+ for (t = 0; t < n_threads; t++)
+ if (thread_state[t] == PI_TALIVE)
+ {
+ printf_filtered ("%d%c %08x%c %d.%d ", t,
+ (t == inferior_thread ? '*' : ' '), thread_pc[t],
+ (thread_is_in_kernel[t] ? '#' : ' '),
+ thread_signal[t], thread_sigcode[t]);
+ print_insn (thread_pc[t], stdout);
+ printf_filtered ("\n");
+ }
+}
+
+/* Change the current thread to ARG. */
+
+set_thread_command (arg)
+ char *arg;
+{
+ int thread;
+
+ if (!arg)
+ {
+ threadstat ();
+ return;
+ }
+
+ thread = parse_and_eval_address (arg);
+
+ if (thread < 0 || thread > n_threads || thread_state[thread] != PI_TALIVE)
+ error ("no such thread.");
+
+ select_thread (thread);
+
+ stop_pc = read_pc ();
+ flush_cached_frames ();
+ select_frame (get_current_frame (), 0);
+ print_stack_frame (selected_frame, selected_frame_level, -1);
+}
+
+/* Here on CONT command; gdb's dispatch address is changed to come here.
+ Set global variable ALL_CONTINUE to tell resume() that it should
+ start up all threads, and that a thread switch will not blow gdb's
+ mind. */
+
+static void
+convex_cont_command (proc_count_exp, from_tty)
+ char *proc_count_exp;
+ int from_tty;
+{
+ all_continue = 1;
+ cont_command (proc_count_exp, from_tty);
+}
+
+/* Here on 1CONT command. Resume only the current thread. */
+
+one_cont_command (proc_count_exp, from_tty)
+ char *proc_count_exp;
+ int from_tty;
+{
+ cont_command (proc_count_exp, from_tty);
+}
+
+/* Print the contents and lock bits of all communication registers,
+ or just register ARG if ARG is a communication register,
+ or the 3-word resource structure in memory at address ARG. */
+
+comm_registers_info (arg)
+ char *arg;
+{
+ int i, regnum;
+
+ if (arg)
+ {
+ if (sscanf (arg, "$c%d", &regnum) == 1) {
+ ;
+ } else if (sscanf (arg, "$C%d", &regnum) == 1) {
+ ;
+ } else {
+ regnum = parse_and_eval_address (arg);
+ if (regnum > 0)
+ regnum &= ~0x8000;
+ }
+
+ if (regnum >= 64)
+ error ("%s: invalid register name.", arg);
+
+ /* if we got a (user) address, examine the resource struct there */
+
+ if (regnum < 0)
+ {
+ static int buf[3];
+ read_memory (regnum, buf, sizeof buf);
+ printf_filtered ("%08x %08x%08x%s\n", regnum, buf[1], buf[2],
+ buf[0] & 0xff ? " locked" : "");
+ return;
+ }
+ }
+
+ ps.pi_buffer = (char *) &comm_registers;
+ ps.pi_nbytes = sizeof comm_registers;
+ ps.pi_offset = 0;
+ ps.pi_thread = inferior_thread;
+ ioctl (inferior_fd, PIXRDCREGS, &ps);
+
+ for (i = 0; i < 64; i++)
+ if (!arg || i == regnum)
+ printf_filtered ("%2d 0x8%03x %016llx%s\n", i, i,
+ comm_registers.crreg.r4[i],
+ (iscrlbit (comm_registers.crctl.lbits.cc, i)
+ ? " locked" : ""));
+}
+
+/* Print the psw */
+
+static void
+psw_info (arg)
+ char *arg;
+{
+ struct pswbit
+ {
+ int bit;
+ int pos;
+ char *text;
+ };
+
+ static struct pswbit pswbit[] =
+ {
+ { 0x80000000, -1, "A carry" },
+ { 0x40000000, -1, "A integer overflow" },
+ { 0x20000000, -1, "A zero divide" },
+ { 0x10000000, -1, "Integer overflow enable" },
+ { 0x08000000, -1, "Trace" },
+ { 0x06000000, 25, "Frame length" },
+ { 0x01000000, -1, "Sequential" },
+ { 0x00800000, -1, "S carry" },
+ { 0x00400000, -1, "S integer overflow" },
+ { 0x00200000, -1, "S zero divide" },
+ { 0x00100000, -1, "Zero divide enable" },
+ { 0x00080000, -1, "Floating underflow" },
+ { 0x00040000, -1, "Floating overflow" },
+ { 0x00020000, -1, "Floating reserved operand" },
+ { 0x00010000, -1, "Floating zero divide" },
+ { 0x00008000, -1, "Floating error enable" },
+ { 0x00004000, -1, "Floating underflow enable" },
+ { 0x00002000, -1, "IEEE" },
+ { 0x00001000, -1, "Sequential stores" },
+ { 0x00000800, -1, "Intrinsic error" },
+ { 0x00000400, -1, "Intrinsic error enable" },
+ { 0x00000200, -1, "Trace thread creates" },
+ { 0x00000100, -1, "Thread init trap" },
+ { 0x000000e0, 5, "Reserved" },
+ { 0x0000001f, 0, "Intrinsic error code" },
+ {0, 0, 0},
+ };
+
+ long psw;
+ struct pswbit *p;
+
+ if (arg)
+ psw = parse_and_eval_address (arg);
+ else
+ psw = read_register (PS_REGNUM);
+
+ for (p = pswbit; p->bit; p++)
+ {
+ if (p->pos < 0)
+ printf_filtered ("%08x %s %s\n", p->bit,
+ (psw & p->bit) ? "yes" : "no ", p->text);
+ else
+ printf_filtered ("%08x %3d %s\n", p->bit,
+ (psw & p->bit) >> p->pos, p->text);
+ }
+}
+
+#include "symtab.h"
+
+/* reg (fmt_field, inst_field) --
+ the {first,second,third} operand of instruction as fmt_field = [ijk]
+ gets the value of the field from the [ijk] position of the instruction */
+
+#define reg(a,b) ((char (*)[3])(op[fmt->a]))[inst.f0.b]
+
+/* lit (fmt_field) -- field [ijk] is a literal (PSW, VL, eg) */
+
+#define lit(i) op[fmt->i]
+
+/* aj[j] -- name for A register j */
+
+#define aj ((char (*)[3])(op[A]))
+
+union inst {
+ struct {
+ unsigned : 7;
+ unsigned i : 3;
+ unsigned j : 3;
+ unsigned k : 3;
+ unsigned : 16;
+ unsigned : 32;
+ } f0;
+ struct {
+ unsigned : 8;
+ unsigned indir : 1;
+ unsigned len : 1;
+ unsigned j : 3;
+ unsigned k : 3;
+ unsigned : 16;
+ unsigned : 32;
+ } f1;
+ unsigned char byte[8];
+ unsigned short half[4];
+ char signed_byte[8];
+ short signed_half[4];
+};
+
+struct opform {
+ int mask; /* opcode mask */
+ int shift; /* opcode align */
+ struct formstr *formstr[3]; /* ST, E0, E1 */
+};
+
+struct formstr {
+ unsigned lop:8, rop:5; /* opcode */
+ unsigned fmt:5; /* inst format */
+ unsigned i:5, j:5, k:2; /* operand formats */
+};
+
+#include "opcode/convex.h"
+
+CONST unsigned char formdecode [] = {
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
+ 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
+ 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
+ 4,4,4,4,4,4,4,4,5,5,5,5,6,6,7,8,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+};
+
+CONST struct opform opdecode[] = {
+ 0x7e00, 9, format0, e0_format0, e1_format0,
+ 0x3f00, 8, format1, e0_format1, e1_format1,
+ 0x1fc0, 6, format2, e0_format2, e1_format2,
+ 0x0fc0, 6, format3, e0_format3, e1_format3,
+ 0x0700, 8, format4, e0_format4, e1_format4,
+ 0x03c0, 6, format5, e0_format5, e1_format5,
+ 0x01f8, 3, format6, e0_format6, e1_format6,
+ 0x00f8, 3, format7, e0_format7, e1_format7,
+ 0x0000, 0, formatx, formatx, formatx,
+ 0x0f80, 7, formatx, formatx, formatx,
+ 0x0f80, 7, formatx, formatx, formatx,
+};
+
+/* Print the instruction at address MEMADDR in debugged memory,
+ on STREAM. Returns length of the instruction, in bytes. */
+
+int
+convex_print_insn (memaddr, stream)
+ CORE_ADDR memaddr;
+ FILE *stream;
+{
+ union inst inst;
+ struct formstr *fmt;
+ register int format, op1, pfx;
+ int l;
+
+ read_memory (memaddr, &inst, sizeof inst);
+
+ /* Remove and note prefix, if present */
+
+ pfx = inst.half[0];
+ if ((pfx & 0xfff0) == 0x7ef0)
+ {
+ pfx = ((pfx >> 3) & 1) + 1;
+ *(long long *) &inst = *(long long *) &inst.half[1];
+ }
+ else pfx = 0;
+
+ /* Split opcode into format.op1 and look up in appropriate table */
+
+ format = formdecode[inst.byte[0]];
+ op1 = (inst.half[0] & opdecode[format].mask) >> opdecode[format].shift;
+ if (format == 9)
+ {
+ if (pfx)
+ fmt = formatx;
+ else if (inst.f1.j == 0)
+ fmt = &format1a[op1];
+ else if (inst.f1.j == 1)
+ fmt = &format1b[op1];
+ else
+ fmt = formatx;
+ }
+ else
+ fmt = &opdecode[format].formstr[pfx][op1];
+
+ /* Print it */
+
+ if (fmt->fmt == xxx)
+ {
+ /* noninstruction */
+ fprintf (stream, "0x%04x", pfx ? pfx : inst.half[0]);
+ return 2;
+ }
+
+ if (pfx)
+ pfx = 2;
+
+ fprintf (stream, "%s%s%s", lop[fmt->lop], rop[fmt->rop],
+ &" "[strlen(lop[fmt->lop]) + strlen(rop[fmt->rop])]);
+
+ switch (fmt->fmt)
+ {
+ case rrr: /* three register */
+ fprintf (stream, "%s,%s,%s", reg(i,i), reg(j,j), reg(k,k));
+ return pfx + 2;
+
+ case rr: /* two register */
+ fprintf (stream, "%s,%s", reg(i,j), reg(j,k));
+ return pfx + 2;
+
+ case rxr: /* two register, reversed i and j fields */
+ fprintf (stream, "%s,%s", reg(i,k), reg(j,j));
+ return pfx + 2;
+
+ case r: /* one register */
+ fprintf (stream, "%s", reg(i,k));
+ return pfx + 2;
+
+ case nops: /* no operands */
+ return pfx + 2;
+
+ case nr: /* short immediate, one register */
+ fprintf (stream, "#%d,%s", inst.f0.j, reg(i,k));
+ return pfx + 2;
+
+ case pcrel: /* pc relative */
+ print_address (memaddr + 2 * inst.signed_byte[1], stream);
+ return pfx + 2;
+
+ case lr: /* literal, one register */
+ fprintf (stream, "%s,%s", lit(i), reg(j,k));
+ return pfx + 2;
+
+ case rxl: /* one register, literal */
+ fprintf (stream, "%s,%s", reg(i,k), lit(j));
+ return pfx + 2;
+
+ case rlr: /* register, literal, register */
+ fprintf (stream, "%s,%s,%s", reg(i,j), lit(j), reg(k,k));
+ return pfx + 2;
+
+ case rrl: /* register, register, literal */
+ fprintf (stream, "%s,%s,%s", reg(i,j), reg(j,k), lit(k));
+ return pfx + 2;
+
+ case iml: /* immediate, literal */
+ if (inst.f1.len)
+ {
+ fprintf (stream, "#%#x,%s",
+ (inst.signed_half[1] << 16) + inst.half[2], lit(i));
+ return pfx + 6;
+ }
+ else
+ {
+ fprintf (stream, "#%d,%s", inst.signed_half[1], lit(i));
+ return pfx + 4;
+ }
+
+ case imr: /* immediate, register */
+ if (inst.f1.len)
+ {
+ fprintf (stream, "#%#x,%s",
+ (inst.signed_half[1] << 16) + inst.half[2], reg(i,k));
+ return pfx + 6;
+ }
+ else
+ {
+ fprintf (stream, "#%d,%s", inst.signed_half[1], reg(i,k));
+ return pfx + 4;
+ }
+
+ case a1r: /* memory, register */
+ l = print_effa (inst, stream);
+ fprintf (stream, ",%s", reg(i,k));
+ return pfx + l;
+
+ case a1l: /* memory, literal */
+ l = print_effa (inst, stream);
+ fprintf (stream, ",%s", lit(i));
+ return pfx + l;
+
+ case a2r: /* register, memory */
+ fprintf (stream, "%s,", reg(i,k));
+ return pfx + print_effa (inst, stream);
+
+ case a2l: /* literal, memory */
+ fprintf (stream, "%s,", lit(i));
+ return pfx + print_effa (inst, stream);
+
+ case a3: /* memory */
+ return pfx + print_effa (inst, stream);
+
+ case a4: /* system call */
+ l = 29; goto a4a5;
+ case a5: /* trap */
+ l = 27;
+ a4a5:
+ if (inst.f1.len)
+ {
+ unsigned int m = (inst.signed_half[1] << 16) + inst.half[2];
+ fprintf (stream, "#%d,#%d", m >> l, m & (-1 >> (32-l)));
+ return pfx + 6;
+ }
+ else
+ {
+ unsigned int m = inst.signed_half[1];
+ fprintf (stream, "#%d,#%d", m >> l, m & (-1 >> (32-l)));
+ return pfx + 4;
+ }
+ }
+}
+
+
+/* print effective address @nnn(aj), return instruction length */
+
+int print_effa (inst, stream)
+ union inst inst;
+ FILE *stream;
+{
+ int n, l;
+
+ if (inst.f1.len)
+ {
+ n = (inst.signed_half[1] << 16) + inst.half[2];
+ l = 6;
+ }
+ else
+ {
+ n = inst.signed_half[1];
+ l = 4;
+ }
+
+ if (inst.f1.indir)
+ printf ("@");
+
+ if (!inst.f1.j)
+ {
+ print_address (n, stream);
+ return l;
+ }
+
+ fprintf (stream, (n & 0xf0000000) == 0x80000000 ? "%#x(%s)" : "%d(%s)",
+ n, aj[inst.f1.j]);
+
+ return l;
+}
+
+
+void
+_initialize_convex_dep ()
+{
+ add_com ("alias", class_support, alias_command,
+ "Add a new name for an existing command.");
+
+ add_cmd ("base", class_vars, set_base_command,
+ "Change the integer output radix to 8, 10 or 16\n\
+or use just `set base' with no args to return to the ad-hoc default,\n\
+which is 16 for integers that look like addresses, 10 otherwise.",
+ &setlist);
+
+ add_cmd ("pipeline", class_run, set_pipelining_command,
+ "Enable or disable overlapped execution of instructions.\n\
+With `set pipe off', exceptions are reported with\n\
+$pc pointing at the instruction after the faulting one.\n\
+The default is `set pipe on', which runs faster.",
+ &setlist);
+
+ add_cmd ("parallel", class_run, set_parallel_command,
+ "Enable or disable multi-threaded execution of parallel code.\n\
+`set parallel off' means run the program on a single CPU.\n\
+`set parallel fixed' means run the program with all CPUs assigned to it.\n\
+`set parallel on' means run the program on any CPUs that are available.",
+ &setlist);
+
+ add_com ("1cont", class_run, one_cont_command,
+ "Continue the program, activating only the current thread.\n\
+Args are the same as the `cont' command.");
+
+ add_com ("thread", class_run, set_thread_command,
+ "Change the current thread, the one under scrutiny and control.\n\
+With no arg, show the active threads, the current one marked with *.");
+
+ add_info ("threads", thread_info,
+ "List status of active threads.");
+
+ add_info ("comm-registers", comm_registers_info,
+ "List communication registers and their contents.\n\
+A communication register name as argument means describe only that register.\n\
+An address as argument means describe the resource structure at that address.\n\
+`Locked' means that the register has been sent to but not yet received from.");
+
+ add_info ("psw", psw_info,
+ "Display $ps, the processor status word, bit by bit.\n\
+An argument means display that value's interpretation as a psw.");
+
+ add_cmd ("convex", no_class, 0, "Convex-specific commands.\n\
+32-bit registers $pc $ps $sp $ap $fp $a1-5 $s0-7 $v0-7 $vl $vs $vm $c0-63\n\
+64-bit registers $S0-7 $V0-7 $C0-63\n\
+\n\
+info threads display info on stopped threads waiting to signal\n\
+thread display list of active threads\n\
+thread N select thread N (its registers, stack, memory, etc.)\n\
+step, next, etc step selected thread only\n\
+1cont continue selected thread only\n\
+cont continue all threads\n\
+info comm-registers display contents of comm register(s) or a resource struct\n\
+info psw display processor status word $ps\n\
+set base N change integer radix used by `print' without a format\n\
+set pipeline off exceptions are precise, $pc points after the faulting insn\n\
+set pipeline on normal mode, $pc is somewhere ahead of faulting insn\n\
+set parallel off program runs on a single CPU\n\
+set parallel fixed all CPUs are assigned to the program\n\
+set parallel on normal mode, parallel execution on random available CPUs\n\
+",
+ &cmdlist);
+
+}
diff --git a/gdb/convex-xdep.c b/gdb/convex-xdep.c
new file mode 100644
index 00000000000..8bfc0d8166e
--- /dev/null
+++ b/gdb/convex-xdep.c
@@ -0,0 +1,966 @@
+/* Convex host-dependent code for GDB.
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "command.h"
+#include "symtab.h"
+#include "value.h"
+#include "frame.h"
+#include "inferior.h"
+#include "wait.h"
+
+#include <signal.h>
+#include <fcntl.h>
+#include "gdbcore.h"
+
+#include <sys/param.h>
+#include <sys/dir.h>
+#include <sys/user.h>
+#include <sys/ioctl.h>
+#include <sys/pcntl.h>
+#include <sys/thread.h>
+#include <sys/proc.h>
+#include <sys/file.h>
+#include "gdb_stat.h"
+#include <sys/mman.h>
+
+#include <convex/vmparam.h>
+#include <convex/filehdr.h>
+#include <convex/opthdr.h>
+#include <convex/scnhdr.h>
+#include <convex/core.h>
+
+/* Per-thread data, read from the inferior at each stop and written
+ back at each resume. */
+
+/* Number of active threads.
+ Tables are valid for thread numbers less than this. */
+
+static int n_threads;
+
+#define MAXTHREADS 8
+
+/* Thread state. The remaining data is valid only if this is PI_TALIVE. */
+
+static int thread_state[MAXTHREADS];
+
+/* Stop pc, signal, signal subcode */
+
+static int thread_pc[MAXTHREADS];
+static int thread_signal[MAXTHREADS];
+static int thread_sigcode[MAXTHREADS];
+
+/* Thread registers.
+ If thread is selected, the regs are in registers[] instead. */
+
+static char thread_regs[MAXTHREADS][REGISTER_BYTES];
+
+/* 1 if the top frame on the thread's stack was a context frame,
+ meaning that the kernel is up to something and we should not
+ touch the thread at all except to resume it. */
+
+static char thread_is_in_kernel[MAXTHREADS];
+
+/* The currently selected thread's number. */
+
+static int inferior_thread;
+
+/* Inferior process's file handle and a process control block
+ to feed args to ioctl with. */
+
+static int inferior_fd;
+static struct pcntl ps;
+
+/* SOFF file headers for exec or core file. */
+
+static FILEHDR filehdr;
+static OPTHDR opthdr;
+static SCNHDR scnhdr;
+
+/* Address maps constructed from section headers of exec and core files.
+ Defines process address -> file address translation. */
+
+struct pmap
+{
+ long mem_addr; /* process start address */
+ long mem_end; /* process end+1 address */
+ long file_addr; /* file start address */
+ long thread; /* -1 shared; 0,1,... thread-local */
+ long type; /* S_TEXT S_DATA S_BSS S_TBSS etc */
+ long which; /* used to sort map for info files */
+};
+
+static int n_exec, n_core;
+static struct pmap exec_map[100];
+static struct pmap core_map[100];
+
+/* Offsets in the core file of core_context and core_tcontext blocks. */
+
+static int context_offset;
+static int tcontext_offset[MAXTHREADS];
+
+/* Core file control blocks. */
+
+static struct core_context_v70 c;
+static struct core_tcontext_v70 tc;
+static struct user u;
+static thread_t th;
+static proc_t pr;
+
+/* The registers of the currently selected thread. */
+
+extern char registers[REGISTER_BYTES];
+
+/* Vector and communication registers from core dump or from inferior.
+ These are read on demand, ie, not normally valid. */
+
+static struct vecst vector_registers;
+static struct creg_ctx comm_registers;
+
+/* Flag, set on a vanilla CONT command and cleared when the inferior
+ is continued. */
+
+static int all_continue;
+
+/* Flag, set when the inferior is continued by a vanilla CONT command,
+ cleared if it is continued for any other purpose. */
+
+static int thread_switch_ok;
+
+/* Stack of signals recieved from threads but not yet delivered to gdb. */
+
+struct threadpid
+{
+ int pid;
+ int thread;
+ int signo;
+ int subsig;
+ int pc;
+};
+
+static struct threadpid signal_stack_bot[100];
+static struct threadpid *signal_stack = signal_stack_bot;
+
+/* How to detect empty stack -- bottom frame is all zero. */
+
+#define signal_stack_is_empty() (signal_stack->pid == 0)
+
+/* Mode controlled by SET PIPE command, controls the psw SEQ bit
+ which forces each instruction to complete before the next one starts. */
+
+static int sequential = 0;
+
+/* Mode controlled by the SET PARALLEL command. Values are:
+ 0 concurrency limit 1 thread, dynamic scheduling
+ 1 no concurrency limit, dynamic scheduling
+ 2 no concurrency limit, fixed scheduling */
+
+static int parallel = 1;
+
+/* Mode controlled by SET BASE command, output radix for unformatted
+ integer typeout, as in argument lists, aggregates, and so on.
+ Zero means guess whether it's an address (hex) or not (decimal). */
+
+static int output_radix = 0;
+
+/* Signal subcode at last thread stop. */
+
+static int stop_sigcode;
+
+/* Hack, see wait() below. */
+
+static int exec_trap_timer;
+
+#include "gdbcmd.h"
+
+static struct type *vector_type ();
+static long *read_vector_register ();
+static long *read_vector_register_1 ();
+static void write_vector_register ();
+static ULONGEST read_comm_register ();
+static void write_comm_register ();
+static void convex_cont_command ();
+static void thread_continue ();
+static void select_thread ();
+static void scan_stack ();
+static void set_fixed_scheduling ();
+static char *subsig_name ();
+static void psw_info ();
+static sig_noop ();
+static ptr_cmp ();
+
+
+/* Execute ptrace. Convex V7 replaced ptrace with pattach.
+ Allow ptrace (0) as a no-op. */
+
+int
+call_ptrace (request, pid, procaddr, buf)
+ int request, pid;
+ PTRACE_ARG3_TYPE procaddr;
+ int buf;
+{
+ if (request == 0)
+ return;
+ error ("no ptrace");
+}
+
+/* Replacement for system execle routine.
+ Convert it to an equivalent exect, which pattach insists on. */
+
+execle (name, argv)
+ char *name, *argv;
+{
+ char ***envp = (char ***) &argv;
+ while (*envp++) ;
+
+ signal (SIGTRAP, sig_noop);
+ exect (name, &argv, *envp);
+}
+
+/* Stupid handler for stupid trace trap that otherwise causes
+ startup to stupidly hang. */
+
+static sig_noop ()
+{}
+
+/* Read registers from inferior into registers[] array.
+ For convex, they are already there, read in when the inferior stops. */
+
+void
+fetch_inferior_registers (regno)
+ int regno;
+{
+}
+
+/* Store our register values back into the inferior.
+ For Convex, do this only once, right before resuming inferior. */
+
+void
+store_inferior_registers (regno)
+ int regno;
+{
+}
+
+/* Copy LEN bytes from inferior's memory starting at MEMADDR
+ to debugger memory starting at MYADDR.
+ On failure (cannot read from inferior, usually because address is out
+ of bounds) returns the value of errno. */
+
+int
+read_inferior_memory (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+{
+ errno = 0;
+ while (len > 0)
+ {
+ /* little-known undocumented max request size */
+ int i = (len < 12288) ? len : 12288;
+
+ lseek (inferior_fd, memaddr, 0);
+ read (inferior_fd, myaddr, i);
+
+ memaddr += i;
+ myaddr += i;
+ len -= i;
+ }
+ if (errno)
+ memset (myaddr, '\0', len);
+ return errno;
+}
+
+/* Copy LEN bytes of data from debugger memory at MYADDR
+ to inferior's memory at MEMADDR.
+ Returns errno on failure (cannot write the inferior) */
+
+int
+write_inferior_memory (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+{
+ errno = 0;
+ lseek (inferior_fd, memaddr, 0);
+ write (inferior_fd, myaddr, len);
+ return errno;
+}
+
+/* Here from create_inferior when the inferior process has been created
+ and started up. We must do a pattach to grab it for debugging.
+
+ Also, intercept the CONT command by altering its dispatch address. */
+/* FIXME: This used to be called from a macro CREATE_INFERIOR_HOOK.
+ But now init_trace_fun is in the same place. So re-write this to
+ use the init_trace_fun (making convex a debugging target). */
+
+create_inferior_hook (pid)
+ int pid;
+{
+ static char cont[] = "cont";
+ static char cont1[] = "c";
+ char *linep = cont;
+ char *linep1 = cont1;
+ char **line = &linep;
+ char **line1 = &linep1;
+ struct cmd_list_element *c;
+
+ c = lookup_cmd (line, cmdlist, "", 0);
+ c->function = convex_cont_command;
+ c = lookup_cmd (line1, cmdlist, "", 0);
+ c->function = convex_cont_command;
+
+ inferior_fd = pattach (pid, O_EXCL);
+ if (inferior_fd < 0)
+ perror_with_name ("pattach");
+ inferior_thread = 0;
+ set_fixed_scheduling (pid, parallel == 2);
+}
+
+/* Attach process PID for debugging. */
+
+attach (pid)
+ int pid;
+{
+ int fd = pattach (pid, O_EXCL);
+ if (fd < 0)
+ perror_with_name ("pattach");
+ attach_flag = 1;
+ /* wait for strange kernel reverberations to go away */
+ sleep (1);
+
+ setpgrp (pid, pid);
+
+ inferior_fd = fd;
+ inferior_thread = 0;
+ return pid;
+}
+
+/* Stop debugging the process whose number is PID
+ and continue it with signal number SIGNAL.
+ SIGNAL = 0 means just continue it. */
+
+void
+detach (signal)
+ int signal;
+{
+ signal_stack = signal_stack_bot;
+ thread_continue (-1, 0, signal);
+ ioctl (inferior_fd, PIXDETACH, &ps);
+ close (inferior_fd);
+ inferior_fd = 0;
+ attach_flag = 0;
+}
+
+/* Kill off the inferior process. */
+
+kill_inferior ()
+{
+ if (inferior_pid == 0)
+ return;
+ ioctl (inferior_fd, PIXTERMINATE, 0);
+ wait (0);
+ target_mourn_inferior ();
+}
+
+/* Read vector register REG, and return a pointer to the value. */
+
+static long *
+read_vector_register (reg)
+ int reg;
+{
+ if (have_inferior_p ())
+ {
+ errno = 0;
+ ps.pi_buffer = (char *) &vector_registers;
+ ps.pi_nbytes = sizeof vector_registers;
+ ps.pi_offset = 0;
+ ps.pi_thread = inferior_thread;
+ ioctl (inferior_fd, PIXRDVREGS, &ps);
+ if (errno)
+ memset (&vector_registers, '\0', sizeof vector_registers);
+ }
+ else if (corechan >= 0)
+ {
+ lseek (corechan, tcontext_offset[inferior_thread], 0);
+ if (myread (corechan, &tc, sizeof tc) < 0)
+ perror_with_name (corefile);
+ lseek (corechan, tc.core_thread_p, 0);
+ if (myread (corechan, &th, sizeof th) < 0)
+ perror_with_name (corefile);
+ lseek (corechan, tc.core_vregs_p, 0);
+ if (myread (corechan, &vector_registers, 16*128) < 0)
+ perror_with_name (corefile);
+ vector_registers.vm[0] = th.t_vect_ctx.vc_vm[0];
+ vector_registers.vm[1] = th.t_vect_ctx.vc_vm[1];
+ vector_registers.vls = th.t_vect_ctx.vc_vls;
+ }
+
+ return read_vector_register_1 (reg);
+}
+
+/* Return a pointer to vector register REG, which must already have been
+ fetched from the inferior or core file. */
+
+static long *
+read_vector_register_1 (reg)
+ int reg;
+{
+ switch (reg)
+ {
+ case VM_REGNUM:
+ return (long *) vector_registers.vm;
+ case VS_REGNUM:
+ return (long *) &vector_registers.vls;
+ case VL_REGNUM:
+ return 1 + (long *) &vector_registers.vls;
+ default:
+ return (long *) &vector_registers.vr[reg];
+ }
+}
+
+/* Write vector register REG, element ELEMENT, new value VAL.
+ NB: must use read-modify-write on the entire vector state,
+ since pattach does not do offsetted writes correctly. */
+
+static void
+write_vector_register (reg, element, val)
+ int reg, element;
+ ULONGEST val;
+{
+ if (have_inferior_p ())
+ {
+ errno = 0;
+ ps.pi_thread = inferior_thread;
+ ps.pi_offset = 0;
+ ps.pi_buffer = (char *) &vector_registers;
+ ps.pi_nbytes = sizeof vector_registers;
+
+ ioctl (inferior_fd, PIXRDVREGS, &ps);
+
+ switch (reg)
+ {
+ case VL_REGNUM:
+ vector_registers.vls =
+ (vector_registers.vls & 0xffffffff00000000LL)
+ + (unsigned long) val;
+ break;
+
+ case VS_REGNUM:
+ vector_registers.vls =
+ (val << 32) + (unsigned long) vector_registers.vls;
+ break;
+
+ default:
+ vector_registers.vr[reg].el[element] = val;
+ break;
+ }
+
+ ioctl (inferior_fd, PIXWRVREGS, &ps);
+
+ if (errno)
+ perror_with_name ("writing vector register");
+ }
+}
+
+/* Return the contents of communication register NUM. */
+
+static ULONGEST
+read_comm_register (num)
+ int num;
+{
+ if (have_inferior_p ())
+ {
+ ps.pi_buffer = (char *) &comm_registers;
+ ps.pi_nbytes = sizeof comm_registers;
+ ps.pi_offset = 0;
+ ps.pi_thread = inferior_thread;
+ ioctl (inferior_fd, PIXRDCREGS, &ps);
+ }
+ return comm_registers.crreg.r4[num];
+}
+
+/* Store a new value VAL into communication register NUM.
+ NB: Must use read-modify-write on the whole comm register set
+ since pattach does not do offsetted writes correctly. */
+
+static void
+write_comm_register (num, val)
+ int num;
+ ULONGEST val;
+{
+ if (have_inferior_p ())
+ {
+ ps.pi_buffer = (char *) &comm_registers;
+ ps.pi_nbytes = sizeof comm_registers;
+ ps.pi_offset = 0;
+ ps.pi_thread = inferior_thread;
+ ioctl (inferior_fd, PIXRDCREGS, &ps);
+ comm_registers.crreg.r4[num] = val;
+ ioctl (inferior_fd, PIXWRCREGS, &ps);
+ }
+}
+
+/* Resume execution of the inferior process.
+ If STEP is nonzero, single-step it.
+ If SIGNAL is nonzero, give it that signal. */
+
+void
+resume (step, signal)
+ int step;
+ int signal;
+{
+ errno = 0;
+ if (step || signal)
+ thread_continue (inferior_thread, step, signal);
+ else
+ thread_continue (-1, 0, 0);
+}
+
+/* Maybe resume some threads.
+ THREAD is which thread to resume, or -1 to resume them all.
+ STEP and SIGNAL are as in resume.
+
+ Global variable ALL_CONTINUE is set when we are here to do a
+ `cont' command; otherwise we may be doing `finish' or a call or
+ something else that will not tolerate an automatic thread switch.
+
+ If there are stopped threads waiting to deliver signals, and
+ ALL_CONTINUE, do not actually resume anything. gdb will do a wait
+ and see one of the stopped threads in the queue. */
+
+static void
+thread_continue (thread, step, signal)
+ int thread, step, signal;
+{
+ int n;
+
+ /* If we are to continue all threads, but not for the CONTINUE command,
+ pay no attention and continue only the selected thread. */
+
+ if (thread < 0 && ! all_continue)
+ thread = inferior_thread;
+
+ /* If we are not stepping, we have now executed the continue part
+ of a CONTINUE command. */
+
+ if (! step)
+ all_continue = 0;
+
+ /* Allow wait() to switch threads if this is an all-out continue. */
+
+ thread_switch_ok = thread < 0;
+
+ /* If there are threads queued up, don't resume. */
+
+ if (thread_switch_ok && ! signal_stack_is_empty ())
+ return;
+
+ /* OK, do it. */
+
+ for (n = 0; n < n_threads; n++)
+ if (thread_state[n] == PI_TALIVE)
+ {
+ select_thread (n);
+
+ if ((thread < 0 || n == thread) && ! thread_is_in_kernel[n])
+ {
+ /* Blam the trace bits in the stack's saved psws to match
+ the desired step mode. This is required so that
+ single-stepping a return doesn't restore a psw with a
+ clear trace bit and fly away, and conversely,
+ proceeding through a return in a routine that was
+ stepped into doesn't cause a phantom break by restoring
+ a psw with the trace bit set. */
+ scan_stack (PSW_T_BIT, step);
+ scan_stack (PSW_S_BIT, sequential);
+ }
+
+ ps.pi_buffer = registers;
+ ps.pi_nbytes = REGISTER_BYTES;
+ ps.pi_offset = 0;
+ ps.pi_thread = n;
+ if (! thread_is_in_kernel[n])
+ if (ioctl (inferior_fd, PIXWRREGS, &ps))
+ perror_with_name ("PIXWRREGS");
+
+ if (thread < 0 || n == thread)
+ {
+ ps.pi_pc = 1;
+ ps.pi_signo = signal;
+ if (ioctl (inferior_fd, step ? PIXSTEP : PIXCONTINUE, &ps) < 0)
+ perror_with_name ("PIXCONTINUE");
+ }
+ }
+
+ if (ioctl (inferior_fd, PIXRUN, &ps) < 0)
+ perror_with_name ("PIXRUN");
+}
+
+/* Replacement for system wait routine.
+
+ The system wait returns with one or more threads stopped by
+ signals. Put stopped threads on a stack and return them one by
+ one, so that it appears that wait returns one thread at a time.
+
+ Global variable THREAD_SWITCH_OK is set when gdb can tolerate wait
+ returning a new thread. If it is false, then only one thread is
+ running; we will do a real wait, the thread will do something, and
+ we will return that. */
+
+pid_t
+wait (w)
+ union wait *w;
+{
+ int pid;
+
+ if (!w)
+ return wait3 (0, 0, 0);
+
+ /* Do a real wait if we were told to, or if there are no queued threads. */
+
+ if (! thread_switch_ok || signal_stack_is_empty ())
+ {
+ int thread;
+
+ pid = wait3 (w, 0, 0);
+
+ if (!WIFSTOPPED (*w) || pid != inferior_pid)
+ return pid;
+
+ /* The inferior has done something and stopped. Read in all the
+ threads' registers, and queue up any signals that happened. */
+
+ if (ioctl (inferior_fd, PIXGETTHCOUNT, &ps) < 0)
+ perror_with_name ("PIXGETTHCOUNT");
+
+ n_threads = ps.pi_othdcnt;
+ for (thread = 0; thread < n_threads; thread++)
+ {
+ ps.pi_thread = thread;
+ if (ioctl (inferior_fd, PIXGETSUBCODE, &ps) < 0)
+ perror_with_name ("PIXGETSUBCODE");
+ thread_state[thread] = ps.pi_otstate;
+
+ if (ps.pi_otstate == PI_TALIVE)
+ {
+ select_thread (thread);
+ ps.pi_buffer = registers;
+ ps.pi_nbytes = REGISTER_BYTES;
+ ps.pi_offset = 0;
+ ps.pi_thread = thread;
+ if (ioctl (inferior_fd, PIXRDREGS, &ps) < 0)
+ perror_with_name ("PIXRDREGS");
+
+ registers_fetched ();
+
+ thread_pc[thread] = read_pc ();
+ thread_signal[thread] = ps.pi_osigno;
+ thread_sigcode[thread] = ps.pi_osigcode;
+
+ /* If the thread's stack has a context frame
+ on top, something fucked is going on. I do not
+ know what, but do I know this: the only thing you
+ can do with such a thread is continue it. */
+
+ thread_is_in_kernel[thread] =
+ ((read_register (PS_REGNUM) >> 25) & 3) == 0;
+
+ /* Signals push an extended frame and then fault
+ with a ridiculous pc. Pop the frame. */
+
+ if (thread_pc[thread] > STACK_END_ADDR)
+ {
+ POP_FRAME;
+ if (is_break_pc (thread_pc[thread]))
+ thread_pc[thread] = read_pc () - 2;
+ else
+ thread_pc[thread] = read_pc ();
+ write_register (PC_REGNUM, thread_pc[thread]);
+ }
+
+ if (ps.pi_osigno || ps.pi_osigcode)
+ {
+ signal_stack++;
+ signal_stack->pid = pid;
+ signal_stack->thread = thread;
+ signal_stack->signo = thread_signal[thread];
+ signal_stack->subsig = thread_sigcode[thread];
+ signal_stack->pc = thread_pc[thread];
+ }
+
+ /* The following hackery is caused by a unix 7.1 feature:
+ the inferior's fixed scheduling mode is cleared when
+ it execs the shell (since the shell is not a parallel
+ program). So, note the 5.4 trap we get when
+ the shell does its exec, then catch the 5.0 trap
+ that occurs when the debuggee starts, and set fixed
+ scheduling mode properly. */
+
+ if (ps.pi_osigno == 5 && ps.pi_osigcode == 4)
+ exec_trap_timer = 1;
+ else
+ exec_trap_timer--;
+
+ if (ps.pi_osigno == 5 && exec_trap_timer == 0)
+ set_fixed_scheduling (pid, parallel == 2);
+ }
+ }
+
+ if (signal_stack_is_empty ())
+ error ("no active threads?!");
+ }
+
+ /* Select the thread that stopped, and return *w saying why. */
+
+ select_thread (signal_stack->thread);
+
+ FIXME: need to convert from host sig.
+ stop_signal = signal_stack->signo;
+ stop_sigcode = signal_stack->subsig;
+
+ WSETSTOP (*w, signal_stack->signo);
+ w->w_thread = signal_stack->thread;
+ return (signal_stack--)->pid;
+}
+
+/* Select thread THREAD -- its registers, stack, per-thread memory.
+ This is the only routine that may assign to inferior_thread
+ or thread_regs[]. */
+
+static void
+select_thread (thread)
+ int thread;
+{
+ if (thread == inferior_thread)
+ return;
+
+ memcpy (thread_regs[inferior_thread], registers, REGISTER_BYTES);
+ ps.pi_thread = inferior_thread = thread;
+ if (have_inferior_p ())
+ ioctl (inferior_fd, PISETRWTID, &ps);
+ memcpy (registers, thread_regs[thread], REGISTER_BYTES);
+}
+
+/* Routine to set or clear a psw bit in the psw and also all psws
+ saved on the stack. Quits when we get to a frame in which the
+ saved psw is correct. */
+
+static void
+scan_stack (bit, val)
+ long bit, val;
+{
+ long ps = read_register (PS_REGNUM);
+ long fp;
+ if (val ? !(ps & bit) : (ps & bit))
+ {
+ ps ^= bit;
+ write_register (PS_REGNUM, ps);
+
+ fp = read_register (FP_REGNUM);
+ while (fp & 0x80000000)
+ {
+ ps = read_memory_integer (fp + 4, 4);
+ if (val ? (ps & bit) : !(ps & bit))
+ break;
+ ps ^= bit;
+ write_memory (fp + 4, &ps, 4);
+ fp = read_memory_integer (fp + 8, 4);
+ }
+ }
+}
+
+/* Set fixed scheduling (alliant mode) of process PID to ARG (0 or 1). */
+
+static void
+set_fixed_scheduling (pid, arg)
+ int arg;
+{
+ struct pattributes pattr;
+ getpattr (pid, &pattr);
+ pattr.pattr_pfixed = arg;
+ setpattr (pid, &pattr);
+}
+
+void
+core_file_command (filename, from_tty)
+ char *filename;
+ int from_tty;
+{
+ int n;
+
+ /* Discard all vestiges of any previous core file
+ and mark data and stack spaces as empty. */
+
+ if (corefile)
+ free (corefile);
+ corefile = 0;
+
+ if (corechan >= 0)
+ close (corechan);
+ corechan = -1;
+
+ data_start = 0;
+ data_end = 0;
+ stack_start = STACK_END_ADDR;
+ stack_end = STACK_END_ADDR;
+ n_core = 0;
+
+ /* Now, if a new core file was specified, open it and digest it. */
+
+ if (filename)
+ {
+ filename = tilde_expand (filename);
+ make_cleanup (free, filename);
+
+ if (have_inferior_p ())
+ error ("To look at a core file, you must kill the program with \"kill\".");
+ corechan = open (filename, O_RDONLY, 0);
+ if (corechan < 0)
+ perror_with_name (filename);
+
+ if (myread (corechan, &filehdr, sizeof filehdr) < 0)
+ perror_with_name (filename);
+
+ if (!IS_CORE_SOFF_MAGIC (filehdr.h_magic))
+ error ("%s: not a core file.\n", filename);
+
+ if (myread (corechan, &opthdr, filehdr.h_opthdr) < 0)
+ perror_with_name (filename);
+
+ /* Read through the section headers.
+ For text, data, etc, record an entry in the core file map.
+ For context and tcontext, record the file address of
+ the context blocks. */
+
+ lseek (corechan, (long) filehdr.h_scnptr, 0);
+
+ n_threads = 0;
+ for (n = 0; n < filehdr.h_nscns; n++)
+ {
+ if (myread (corechan, &scnhdr, sizeof scnhdr) < 0)
+ perror_with_name (filename);
+ if ((scnhdr.s_flags & S_TYPMASK) >= S_TEXT
+ && (scnhdr.s_flags & S_TYPMASK) <= S_COMON)
+ {
+ core_map[n_core].mem_addr = scnhdr.s_vaddr;
+ core_map[n_core].mem_end = scnhdr.s_vaddr + scnhdr.s_size;
+ core_map[n_core].file_addr = scnhdr.s_scnptr;
+ core_map[n_core].type = scnhdr.s_flags & S_TYPMASK;
+ if (core_map[n_core].type != S_TBSS
+ && core_map[n_core].type != S_TDATA
+ && core_map[n_core].type != S_TTEXT)
+ core_map[n_core].thread = -1;
+ else if (n_core == 0
+ || core_map[n_core-1].mem_addr != scnhdr.s_vaddr)
+ core_map[n_core].thread = 0;
+ else
+ core_map[n_core].thread = core_map[n_core-1].thread + 1;
+ n_core++;
+ }
+ else if ((scnhdr.s_flags & S_TYPMASK) == S_CONTEXT)
+ context_offset = scnhdr.s_scnptr;
+ else if ((scnhdr.s_flags & S_TYPMASK) == S_TCONTEXT)
+ tcontext_offset[n_threads++] = scnhdr.s_scnptr;
+ }
+
+ /* Read the context block, struct user, struct proc,
+ and the comm regs. */
+
+ lseek (corechan, context_offset, 0);
+ if (myread (corechan, &c, sizeof c) < 0)
+ perror_with_name (filename);
+ lseek (corechan, c.core_user_p, 0);
+ if (myread (corechan, &u, sizeof u) < 0)
+ perror_with_name (filename);
+ lseek (corechan, c.core_proc_p, 0);
+ if (myread (corechan, &pr, sizeof pr) < 0)
+ perror_with_name (filename);
+ comm_registers = pr.p_creg;
+
+ /* Core file apparently is really there. Make it really exist
+ for xfer_core_file so we can do read_memory on it. */
+
+ if (filename[0] == '/')
+ corefile = savestring (filename, strlen (filename));
+ else
+ corefile = concat (current_directory, "/", filename, NULL);
+
+ printf_filtered ("Program %s ", u.u_comm);
+
+ /* Read the thread registers and fill in the thread_xxx[] data. */
+
+ for (n = 0; n < n_threads; n++)
+ {
+ select_thread (n);
+
+ lseek (corechan, tcontext_offset[n], 0);
+ if (myread (corechan, &tc, sizeof tc) < 0)
+ perror_with_name (corefile);
+ lseek (corechan, tc.core_thread_p, 0);
+ if (myread (corechan, &th, sizeof th) < 0)
+ perror_with_name (corefile);
+
+ lseek (corechan, tc.core_syscall_context_p, 0);
+ if (myread (corechan, registers, REGISTER_BYTES) < 0)
+ perror_with_name (corefile);
+
+ thread_signal[n] = th.t_cursig;
+ thread_sigcode[n] = th.t_code;
+ thread_state[n] = th.t_state;
+ thread_pc[n] = read_pc ();
+
+ if (thread_pc[n] > STACK_END_ADDR)
+ {
+ POP_FRAME;
+ if (is_break_pc (thread_pc[n]))
+ thread_pc[n] = read_pc () - 2;
+ else
+ thread_pc[n] = read_pc ();
+ write_register (PC_REGNUM, thread_pc[n]);
+ }
+
+ printf_filtered ("thread %d received signal %d, %s\n",
+ n, thread_signal[n],
+ safe_strsignal (thread_signal[n]));
+ }
+
+ /* Select an interesting thread -- also-rans died with SIGKILL,
+ so find one that didn't. */
+
+ for (n = 0; n < n_threads; n++)
+ if (thread_signal[n] != 0 && thread_signal[n] != SIGKILL)
+ {
+ select_thread (n);
+ stop_signal = thread_signal[n];
+ stop_sigcode = thread_sigcode[n];
+ break;
+ }
+
+ core_aouthdr.a_magic = 0;
+
+ flush_cached_frames ();
+ select_frame (get_current_frame (), 0);
+ validate_files ();
+
+ print_stack_frame (selected_frame, selected_frame_level, -1);
+ }
+ else if (from_tty)
+ printf_filtered ("No core file now.\n");
+}
diff --git a/gdb/copying.awk b/gdb/copying.awk
new file mode 100644
index 00000000000..4f53e92e88e
--- /dev/null
+++ b/gdb/copying.awk
@@ -0,0 +1,77 @@
+BEGIN {
+ FS="\"";
+ print "/* ==> Do not modify this file!! It is created automatically";
+ print " by copying.awk. Modify copying.awk instead. <== */";
+ print ""
+ print "#include \"defs.h\""
+ print "#include \"command.h\""
+ print "#include \"gdbcmd.h\""
+ print ""
+ print "static void show_copying_command PARAMS ((char *, int));"
+ print ""
+ print "static void show_warranty_command PARAMS ((char *, int));"
+ print ""
+ print "void _initialize_copying PARAMS ((void));"
+ print ""
+ print "extern int immediate_quit;";
+ print "static void";
+ print "show_copying_command (ignore, from_tty)";
+ print " char *ignore;";
+ print " int from_tty;";
+ print "{";
+ print " immediate_quit++;";
+ }
+NR == 1,/^[ ]*NO WARRANTY[ ]*$/ {
+ if ($0 ~ / /)
+ {
+ printf " printf_filtered (\"\\n\");\n";
+ }
+ else if ($0 !~ /^[ ]*NO WARRANTY[ ]*$/)
+ {
+ printf " printf_filtered (\"";
+ for (i = 1; i < NF; i++)
+ printf "%s\\\"", $i;
+ printf "%s\\n\");\n", $NF;
+ }
+ }
+/^[ ]*NO WARRANTY[ ]*$/ {
+ print " immediate_quit--;";
+ print "}";
+ print "";
+ print "static void";
+ print "show_warranty_command (ignore, from_tty)";
+ print " char *ignore;";
+ print " int from_tty;";
+ print "{";
+ print " immediate_quit++;";
+ }
+/^[ ]*NO WARRANTY[ ]*$/, /^[ ]*END OF TERMS AND CONDITIONS[ ]*$/{
+ if (! ($0 ~ /^[ ]*END OF TERMS AND CONDITIONS[ ]*$/))
+ {
+ printf " printf_filtered (\"";
+ for (i = 1; i < NF; i++)
+ printf "%s\\\"", $i;
+ printf "%s\\n\");\n", $NF;
+ }
+ }
+END {
+ print " immediate_quit--;";
+ print "}";
+ print "";
+ print "void"
+ print "_initialize_copying ()";
+ print "{";
+ print " add_cmd (\"copying\", no_class, show_copying_command,";
+ print " \"Conditions for redistributing copies of GDB.\",";
+ print " &showlist);";
+ print " add_cmd (\"warranty\", no_class, show_warranty_command,";
+ print " \"Various kinds of warranty you do not have.\",";
+ print " &showlist);";
+ print "";
+ print " /* For old-timers, allow \"info copying\", etc. */";
+ print " add_info (\"copying\", show_copying_command,";
+ print " \"Conditions for redistributing copies of GDB.\");";
+ print " add_info (\"warranty\", show_warranty_command,";
+ print " \"Various kinds of warranty you do not have.\");";
+ print "}";
+ }
diff --git a/gdb/copying.c b/gdb/copying.c
new file mode 100644
index 00000000000..a36db1fe0f4
--- /dev/null
+++ b/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));
+
+void _initialize_copying PARAMS ((void));
+
+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 (" 59 Temple Place, Suite 330, Boston, MA 02111-1307 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/gdb/core-aout.c b/gdb/core-aout.c
new file mode 100644
index 00000000000..3c1d499256e
--- /dev/null
+++ b/gdb/core-aout.c
@@ -0,0 +1,147 @@
+/* Extract registers from a "standard" core file, for GDB.
+ Copyright (C) 1988-1998 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Typically used on systems that have a.out format executables.
+ corefile.c is supposed to contain the more machine-independent
+ aspects of reading registers from core files, while this file is
+ more machine specific. */
+
+#include "defs.h"
+
+#ifdef HAVE_PTRACE_H
+# include <ptrace.h>
+#else
+# ifdef HAVE_SYS_PTRACE_H
+# include <sys/ptrace.h>
+# endif
+#endif
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include "gdbcore.h"
+#include "value.h" /* For supply_register. */
+#include "inferior.h" /* For ARCH_NUM_REGS. */
+
+/* These are needed on various systems to expand REGISTER_U_ADDR. */
+#ifndef USG
+#include <sys/dir.h>
+#include <sys/file.h>
+#include "gdb_stat.h"
+#include <sys/user.h>
+#endif
+
+#ifndef CORE_REGISTER_ADDR
+#define CORE_REGISTER_ADDR(regno, regptr) register_addr(regno, regptr)
+#endif /* CORE_REGISTER_ADDR */
+
+#ifdef NEED_SYS_CORE_H
+#include <sys/core.h>
+#endif
+
+static void fetch_core_registers PARAMS ((char *, unsigned, int, CORE_ADDR));
+
+void _initialize_core_aout PARAMS ((void));
+
+/* 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.
+ */
+
+static void
+fetch_core_registers (core_reg_sect, core_reg_size, which, reg_addr)
+ char *core_reg_sect;
+ unsigned core_reg_size;
+ int which;
+ CORE_ADDR reg_addr;
+{
+ int regno;
+ CORE_ADDR addr;
+ int bad_reg = -1;
+ CORE_ADDR reg_ptr = -reg_addr; /* Original u.u_ar0 is -reg_addr. */
+ int numregs = ARCH_NUM_REGS;
+
+ /* 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
+ CORE_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 < numregs; regno++)
+ {
+ addr = CORE_REGISTER_ADDR (regno, reg_ptr);
+ if (addr >= core_reg_size
+ && 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.", REGISTER_NAME (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. */
+
+CORE_ADDR
+register_addr (regno, blockend)
+ int regno;
+ CORE_ADDR blockend;
+{
+ CORE_ADDR addr;
+
+ if (regno < 0 || regno >= ARCH_NUM_REGS)
+ error ("Invalid register number %d.", regno);
+
+ REGISTER_U_ADDR (addr, blockend, regno);
+
+ return addr;
+}
+
+#endif /* REGISTER_U_ADDR */
+
+
+/* Register that we are able to handle aout (trad-core) file formats. */
+
+static struct core_fns aout_core_fns =
+{
+ bfd_target_unknown_flavour,
+ fetch_core_registers,
+ NULL
+};
+
+void
+_initialize_core_aout ()
+{
+ add_core_fns (&aout_core_fns);
+}
diff --git a/gdb/core-regset.c b/gdb/core-regset.c
new file mode 100644
index 00000000000..d925abea746
--- /dev/null
+++ b/gdb/core-regset.c
@@ -0,0 +1,134 @@
+/* Machine independent GDB support for core files on systems using "regsets".
+ Copyright 1993-1998 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+
+/* N O T E S
+
+This file is used by most systems that implement /proc. For these systems,
+the general registers are laid out the same way in both the core file and
+the gregset_p structure. The current exception to this is Irix-4.*, where
+the gregset_p structure is split up into two pieces in the core file.
+
+The general register and floating point register sets are manipulated by
+separate ioctl's. This file makes the assumption that if FP0_REGNUM is
+defined, then support for the floating point register set is desired,
+regardless of whether or not the actual target has floating point hardware.
+
+ */
+
+#include "defs.h"
+
+#include <time.h>
+#ifdef HAVE_SYS_PROCFS_H
+#include <sys/procfs.h>
+#endif
+#include <fcntl.h>
+#include <errno.h>
+#include "gdb_string.h"
+
+#include "inferior.h"
+#include "target.h"
+#include "command.h"
+#include "gdbcore.h"
+
+static void fetch_core_registers PARAMS ((char *, unsigned, int, CORE_ADDR));
+
+void _initialize_core_regset PARAMS ((void));
+
+/*
+
+GLOBAL FUNCTION
+
+ fetch_core_registers -- fetch current registers from core file
+
+SYNOPSIS
+
+ void fetch_core_registers (char *core_reg_sect,
+ unsigned core_reg_size,
+ int which, CORE_ADDR reg_addr)
+
+DESCRIPTION
+
+ Read the values of either the general register set (WHICH equals 0)
+ or the floating point register set (WHICH equals 2) from the core
+ file data (pointed to by CORE_REG_SECT), and update gdb's idea of
+ their current values. The CORE_REG_SIZE parameter is ignored.
+
+NOTES
+
+ Use the indicated sizes to validate the gregset and fpregset
+ structures.
+*/
+
+static void
+fetch_core_registers (core_reg_sect, core_reg_size, which, reg_addr)
+ char *core_reg_sect;
+ unsigned core_reg_size;
+ int which;
+ CORE_ADDR reg_addr; /* Unused in this version */
+{
+#if defined (HAVE_GREGSET_T) && defined (HAVE_FPREGSET_T)
+ gregset_t gregset;
+ fpregset_t fpregset;
+
+ if (which == 0)
+ {
+ if (core_reg_size != sizeof (gregset))
+ {
+ warning ("wrong size gregset struct in core file");
+ }
+ else
+ {
+ memcpy ((char *) &gregset, core_reg_sect, sizeof (gregset));
+ supply_gregset (&gregset);
+ }
+ }
+ else if (which == 2)
+ {
+ if (core_reg_size != sizeof (fpregset))
+ {
+ warning ("wrong size fpregset struct in core file");
+ }
+ else
+ {
+ memcpy ((char *) &fpregset, core_reg_sect, sizeof (fpregset));
+#if defined (FP0_REGNUM)
+ supply_fpregset (&fpregset);
+#endif
+ }
+ }
+#endif /* defined(HAVE_GREGSET_T) && defined (HAVE_FPREGSET_T) */
+}
+
+
+/* Register that we are able to handle ELF file formats using standard
+ procfs "regset" structures. */
+
+static struct core_fns regset_core_fns =
+{
+ bfd_target_elf_flavour,
+ fetch_core_registers,
+ NULL
+};
+
+void
+_initialize_core_regset ()
+{
+ add_core_fns (&regset_core_fns);
+}
diff --git a/gdb/core-sol2.c b/gdb/core-sol2.c
new file mode 100644
index 00000000000..3c69e63612d
--- /dev/null
+++ b/gdb/core-sol2.c
@@ -0,0 +1,133 @@
+/* Machine independent support for Solaris 2 core files for GDB.
+ Copyright 1994 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+
+/* Solaris comes with two flavours of core files, cores generated by
+ an ELF executable and cores generated by programs that were
+ run under BCP (the part of Solaris which allows it to run SunOS4
+ a.out files).
+ This file combines the core register fetching from core-regset.c
+ and sparc-nat.c to be able to read both flavours. */
+
+#include "defs.h"
+#include <time.h>
+#include <sys/types.h>
+#include <sys/regset.h>
+#include <sys/procfs.h>
+#include <fcntl.h>
+#include <errno.h>
+#include "gdb_string.h"
+
+#include "inferior.h"
+#include "target.h"
+#include "command.h"
+#include "gdbcore.h"
+
+static void fetch_core_registers PARAMS ((char *, unsigned, int, CORE_ADDR));
+
+static void
+fetch_core_registers (core_reg_sect, core_reg_size, which, reg_addr)
+ char *core_reg_sect;
+ unsigned core_reg_size;
+ int which;
+ CORE_ADDR reg_addr; /* Unused in this version */
+{
+ prgregset_t prgregset;
+ prfpregset_t prfpregset;
+
+ if (which == 0)
+ {
+ if (core_reg_size == sizeof (prgregset))
+ {
+ memcpy ((char *) &prgregset, core_reg_sect, sizeof (prgregset));
+ supply_gregset (&prgregset);
+ }
+ else if (core_reg_size == sizeof (struct regs))
+ {
+#define gregs ((struct regs *)core_reg_sect)
+ /* G0 *always* holds 0. */
+ *(int *)&registers[REGISTER_BYTE (0)] = 0;
+
+ /* The globals and output registers. */
+ memcpy (&registers[REGISTER_BYTE (G1_REGNUM)], &gregs->r_g1,
+ 15 * REGISTER_RAW_SIZE (G1_REGNUM));
+ *(int *)&registers[REGISTER_BYTE (PS_REGNUM)] = gregs->r_ps;
+ *(int *)&registers[REGISTER_BYTE (PC_REGNUM)] = gregs->r_pc;
+ *(int *)&registers[REGISTER_BYTE (NPC_REGNUM)] = gregs->r_npc;
+ *(int *)&registers[REGISTER_BYTE (Y_REGNUM)] = gregs->r_y;
+
+ /* My best guess at where to get the locals and input
+ registers is exactly where they usually are, right above
+ the stack pointer. If the core dump was caused by a bus error
+ from blowing away the stack pointer (as is possible) then this
+ won't work, but it's worth the try. */
+ {
+ int sp;
+
+ sp = *(int *)&registers[REGISTER_BYTE (SP_REGNUM)];
+ if (0 != target_read_memory (sp,
+ &registers[REGISTER_BYTE (L0_REGNUM)],
+ 16 * REGISTER_RAW_SIZE (L0_REGNUM)))
+ {
+ warning ("couldn't read input and local registers from core file\n");
+ }
+ }
+ }
+ else
+ {
+ warning ("wrong size gregset struct in core file");
+ }
+ }
+ else if (which == 2)
+ {
+ if (core_reg_size == sizeof (prfpregset))
+ {
+ memcpy ((char *) &prfpregset, core_reg_sect, sizeof (prfpregset));
+ supply_fpregset (&prfpregset);
+ }
+ else if (core_reg_size >= sizeof (struct fpu))
+ {
+#define fpuregs ((struct fpu *) core_reg_sect)
+ memcpy (&registers[REGISTER_BYTE (FP0_REGNUM)], &fpuregs->fpu_fr,
+ sizeof (fpuregs->fpu_fr));
+ memcpy (&registers[REGISTER_BYTE (FPS_REGNUM)], &fpuregs->fpu_fsr,
+ sizeof (FPU_FSR_TYPE));
+ }
+ else
+ {
+ warning ("wrong size fpregset struct in core file");
+ }
+ }
+}
+
+
+/* Register that we are able to handle solaris core file formats. */
+
+static struct core_fns solaris_core_fns =
+{
+ bfd_target_elf_flavour,
+ fetch_core_registers,
+ NULL
+};
+
+void
+_initialize_core_solaris ()
+{
+ add_core_fns (&solaris_core_fns);
+}
diff --git a/gdb/corefile.c b/gdb/corefile.c
new file mode 100644
index 00000000000..94e56ebffec
--- /dev/null
+++ b/gdb/corefile.c
@@ -0,0 +1,479 @@
+/* Core dump and executable file functions above target vector, for GDB.
+ Copyright 1986, 1987, 1989, 1991, 1992, 1993, 1994
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "gdb_string.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"
+#include "language.h"
+#include "gdb_stat.h"
+#include "symfile.h"
+#include "objfiles.h"
+
+extern char registers[];
+
+/* Local function declarations. */
+
+static void call_extra_exec_file_hooks PARAMS ((char *filename));
+
+/* You can have any number of hooks for `exec_file_command' command to call.
+ If there's only one hook, it is set in exec_file_display hook.
+ If there are two or more hooks, they are set in exec_file_extra_hooks[],
+ and exec_file_display_hook is set to a function that calls all of them.
+ This extra complexity is needed to preserve compatibility with
+ old code that assumed that only one hook could be set, and which called
+ exec_file_display_hook directly. */
+
+typedef void (*hook_type) PARAMS ((char *));
+
+hook_type exec_file_display_hook; /* the original hook */
+static hook_type *exec_file_extra_hooks; /* array of additional hooks */
+static int exec_file_hook_count = 0; /* size of array */
+
+/* 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
+ {
+ /* Yes, we were given the path of a core file. Do we already
+ have a symbol file? If not, can we determine it from the
+ core file? If we can, do so.
+ */
+#ifdef HPUXHPPA
+ if (symfile_objfile == NULL)
+ {
+ char * symfile;
+ symfile = t->to_core_file_to_sym_file (filename);
+ if (symfile)
+ {
+ char * symfile_copy = strdup (symfile);
+
+ make_cleanup (free, symfile_copy);
+ symbol_file_command (symfile_copy, from_tty);
+ }
+ else
+ warning ("Unknown symbols for '%s'; use the 'symbol-file' command.", filename);
+ }
+#endif
+ (t->to_open) (filename, from_tty);
+ }
+ else
+ error ("GDB can't read core files on this machine.");
+}
+
+
+/* If there are two or more functions that wish to hook into exec_file_command,
+ * this function will call all of the hook functions. */
+
+static void
+call_extra_exec_file_hooks (filename)
+ char *filename;
+{
+ int i;
+
+ for (i = 0; i < exec_file_hook_count; i++)
+ (*exec_file_extra_hooks[i])(filename);
+}
+
+/* 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 *));
+{
+ hook_type *new_array;
+
+ if (exec_file_display_hook != NULL)
+ {
+ /* There's already a hook installed. Arrange to have both it
+ * and the subsequent hooks called. */
+ if (exec_file_hook_count == 0)
+ {
+ /* If this is the first extra hook, initialize the hook array. */
+ exec_file_extra_hooks = (hook_type *) xmalloc (sizeof(hook_type));
+ exec_file_extra_hooks[0] = exec_file_display_hook;
+ exec_file_display_hook = call_extra_exec_file_hooks;
+ exec_file_hook_count = 1;
+ }
+
+ /* Grow the hook array by one and add the new hook to the end.
+ Yes, it's inefficient to grow it by one each time but since
+ this is hardly ever called it's not a big deal. */
+ exec_file_hook_count++;
+ new_array =
+ (hook_type *) xrealloc (exec_file_extra_hooks,
+ exec_file_hook_count * sizeof(hook_type));
+ exec_file_extra_hooks = new_array;
+ exec_file_extra_hooks[exec_file_hook_count - 1] = hook;
+ }
+ else
+ 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 0 /* FIXME */
+ if (exec_bfd)
+ bfd_tempclose (exec_bfd);
+#endif
+}
+
+void
+reopen_exec_file ()
+{
+#if 0 /* FIXME */
+ if (exec_bfd)
+ bfd_reopen (exec_bfd);
+#else
+ char *filename;
+ int res;
+ struct stat st;
+ long mtime;
+
+ /* Don't do anything if the current target isn't exec. */
+ if (exec_bfd == NULL || strcmp (target_shortname, "exec") != 0)
+ return;
+
+ /* If the timestamp of the exec file has changed, reopen it. */
+ filename = strdup (bfd_get_filename (exec_bfd));
+ make_cleanup (free, filename);
+ mtime = bfd_get_mtime(exec_bfd);
+ res = stat (filename, &st);
+
+ if (mtime && mtime != st.st_mtime)
+ exec_file_command (filename, 0);
+#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_begin ();
+ printf_filtered ("Cannot access memory at address ");
+ print_address_numeric (memaddr, 1, gdb_stdout);
+ printf_filtered (".\n");
+ return_to_top_level (RETURN_ERROR);
+ }
+ else
+ {
+ error_begin ();
+ printf_filtered ("Error accessing memory address ");
+ print_address_numeric (memaddr, 1, gdb_stdout);
+ printf_filtered (": %s.\n",
+ safe_strerror (status));
+ return_to_top_level (RETURN_ERROR);
+ }
+}
+
+/* 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);
+}
+
+void
+read_memory_section (memaddr, myaddr, len, bfd_section)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+ asection *bfd_section;
+{
+ int status;
+ status = target_read_memory_section (memaddr, myaddr, len, bfd_section);
+ 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);
+}
+
+ULONGEST
+read_memory_unsigned_integer (memaddr, len)
+ CORE_ADDR memaddr;
+ int len;
+{
+ char buf[sizeof (ULONGEST)];
+
+ read_memory (memaddr, buf, len);
+ return extract_unsigned_integer (buf, len);
+}
+
+void
+read_memory_string (memaddr, buffer, max_len)
+ CORE_ADDR memaddr;
+ char * buffer;
+ int max_len;
+{
+ register char * cp;
+ register int i;
+ int cnt;
+
+ cp = buffer;
+ while (1)
+ {
+ if (cp - buffer >= max_len)
+ {
+ buffer[max_len - 1] = '\0';
+ break;
+ }
+ cnt = max_len - (cp - buffer);
+ if (cnt > 8)
+ cnt = 8;
+ read_memory (memaddr + (int) (cp - buffer), cp, cnt);
+ for (i = 0; i < cnt && *cp; i++, cp++)
+ ; /* null body */
+
+ if (i < cnt && !*cp)
+ break;
+ }
+}
+
+
+#if 0
+/* Enable after 4.12. It is not tested. */
+
+/* Search code. Targets can just make this their search function, or
+ if the protocol has a less general search function, they can call this
+ in the cases it can't handle. */
+void
+generic_search (len, data, mask, startaddr, increment, lorange, hirange
+ addr_found, data_found)
+ int len;
+ char *data;
+ char *mask;
+ CORE_ADDR startaddr;
+ int increment;
+ CORE_ADDR lorange;
+ CORE_ADDR hirange;
+ CORE_ADDR *addr_found;
+ char *data_found;
+{
+ int i;
+ CORE_ADDR curaddr = startaddr;
+
+ while (curaddr >= lorange && curaddr < hirange)
+ {
+ read_memory (curaddr, data_found, len);
+ for (i = 0; i < len; ++i)
+ if ((data_found[i] & mask[i]) != data[i])
+ goto try_again;
+ /* It matches. */
+ *addr_found = curaddr;
+ return;
+
+ try_again:
+ curaddr += increment;
+ }
+ *addr_found = (CORE_ADDR)0;
+ return;
+}
+#endif /* 0 */
+
+/* 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/gdb/corelow.c b/gdb/corelow.c
new file mode 100644
index 00000000000..e635257b2f4
--- /dev/null
+++ b/gdb/corelow.c
@@ -0,0 +1,511 @@
+/* Core dump and executable file functions below target vector, for GDB.
+ Copyright 1986, 87, 89, 91, 92, 93, 94, 95, 96, 97, 1998
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "gdb_string.h"
+#include <errno.h>
+#include <signal.h>
+#include <fcntl.h>
+#include <unistd.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"
+#include "gdbthread.h"
+
+/* List of all available core_fns. On gdb startup, each core file register
+ reader calls add_core_fns() to register information on each core format it
+ is prepared to read. */
+
+static struct core_fns *core_file_fns = NULL;
+
+static void core_files_info PARAMS ((struct target_ops *));
+
+#ifdef SOLIB_ADD
+static int solib_add_stub PARAMS ((PTR));
+#endif
+
+static void core_open PARAMS ((char *, int));
+
+static void core_detach PARAMS ((char *, int));
+
+static void core_close PARAMS ((int));
+
+static void get_core_registers PARAMS ((int));
+
+static void add_to_thread_list PARAMS ((bfd *, asection *, PTR));
+
+static int ignore PARAMS ((CORE_ADDR, char *));
+
+static char *core_file_to_sym_file PARAMS ((char *));
+
+static int core_file_thread_alive PARAMS ((int tid));
+
+static void init_core_ops PARAMS ((void));
+
+void _initialize_corelow PARAMS ((void));
+
+struct target_ops core_ops;
+
+/* Link a new core_fns into the global core_file_fns list. Called on gdb
+ startup by the _initialize routine in each core file register reader, to
+ register information about each format the the reader is prepared to
+ handle. */
+
+void
+add_core_fns (cf)
+ struct core_fns *cf;
+{
+ cf -> next = core_file_fns;
+ core_file_fns = cf;
+}
+
+
+/* Discard all vestiges of any previous core file and mark data and stack
+ spaces as empty. */
+
+/* ARGSUSED */
+static void
+core_close (quitting)
+ int quitting;
+{
+ char *name;
+
+ if (core_bfd)
+ {
+ inferior_pid = 0; /* Avoid confusion from thread stuff */
+
+ name = bfd_get_filename (core_bfd);
+ if (!bfd_close (core_bfd))
+ warning ("cannot close \"%s\": %s",
+ name, bfd_errmsg (bfd_get_error ()));
+ free (name);
+ 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. FROM_TTYP
+ is really an int * which points to from_tty. */
+
+static int
+solib_add_stub (from_ttyp)
+ PTR from_ttyp;
+{
+ SOLIB_ADD (NULL, *(int *)from_ttyp, &current_target);
+ re_enable_breakpoints_in_shlibs ();
+ 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 (reg_sect != NULL
+ && 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. */
+
+static 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 */
+ /* FIXME: should be checking for errors from bfd_close (for one thing,
+ on error it does not free all the storage associated with the
+ bfd). */
+ make_cleanup ((make_cleanup_func) bfd_close, temp_bfd);
+ error ("\"%s\" is not a core dump: %s",
+ filename, bfd_errmsg (bfd_get_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 ((make_cleanup_func) 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 ("\"%s\": Can't find sections: %s",
+ bfd_get_filename (core_bfd), bfd_errmsg (bfd_get_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, &from_tty, (char *)0,
+ RETURN_MASK_ALL);
+#endif
+
+ /* Now, set up the frame cache, and print the top of stack. */
+ flush_cached_frames ();
+ 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''", target_longname);
+ }
+}
+
+static 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[30];
+ enum bfd_flavour our_flavour = bfd_get_flavour (core_bfd);
+ struct core_fns *cf = NULL;
+
+ if (core_file_fns == NULL)
+ {
+ fprintf_filtered (gdb_stderr,
+ "Can't fetch registers from this type of core file\n");
+ return;
+ }
+
+ /* 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);
+ /* Look for the core functions that match this flavor. Default to the
+ first one if nothing matches. */
+ for (cf = core_file_fns; cf != NULL; cf = cf -> next)
+ {
+ if (our_flavour == cf -> core_flavour)
+ {
+ break;
+ }
+ }
+ if (cf == NULL)
+ {
+ cf = core_file_fns;
+ }
+ if (cf != NULL &&
+ bfd_get_section_contents (core_bfd, reg_sec, the_regs, (file_ptr)0, size) &&
+ cf -> core_read_registers != NULL)
+ {
+ (cf -> core_read_registers (the_regs, size, 0,
+ (unsigned) bfd_section_vma (abfd,reg_sec)));
+ }
+ else
+ {
+cant:
+ fprintf_filtered (gdb_stderr,
+ "Couldn't fetch registers from core file: %s\n",
+ bfd_errmsg (bfd_get_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 (cf != NULL &&
+ bfd_get_section_contents (core_bfd, reg_sec, the_regs, (file_ptr)0, size) &&
+ cf -> core_read_registers != NULL)
+ {
+ (cf -> core_read_registers (the_regs, size, 2,
+ (unsigned) bfd_section_vma (abfd,reg_sec)));
+ }
+ else
+ {
+ fprintf_filtered (gdb_stderr,
+ "Couldn't fetch register set 2 from core file: %s\n",
+ bfd_errmsg (bfd_get_error ()));
+ }
+ }
+ registers_fetched ();
+}
+
+static char *
+core_file_to_sym_file (core)
+ char * core;
+{
+ CONST char * failing_command;
+ char * p;
+ char * temp;
+ bfd * temp_bfd;
+ int scratch_chan;
+
+ if (! core)
+ error ("No core file specified.");
+
+ core = tilde_expand (core);
+ if (core[0] != '/')
+ {
+ temp = concat (current_directory, "/", core, NULL);
+ core = temp;
+ }
+
+ scratch_chan = open (core, write_files ? O_RDWR : O_RDONLY, 0);
+ if (scratch_chan < 0)
+ perror_with_name (core);
+
+ temp_bfd = bfd_fdopenr (core, gnutarget, scratch_chan);
+ if (temp_bfd == NULL)
+ perror_with_name (core);
+
+ if (!bfd_check_format (temp_bfd, bfd_core))
+ {
+ /* Do it after the err msg */
+ /* FIXME: should be checking for errors from bfd_close (for one thing,
+ on error it does not free all the storage associated with the
+ bfd). */
+ make_cleanup ((make_cleanup_func) bfd_close, temp_bfd);
+ error ("\"%s\" is not a core dump: %s",
+ core, bfd_errmsg (bfd_get_error ()));
+ }
+
+ /* Find the data section */
+ if (build_section_table (temp_bfd, &core_ops.to_sections,
+ &core_ops.to_sections_end))
+ error ("\"%s\": Can't find sections: %s",
+ bfd_get_filename (temp_bfd), bfd_errmsg (bfd_get_error ()));
+
+ failing_command = bfd_core_file_failing_command (temp_bfd);
+
+ bfd_close (temp_bfd);
+
+ /* If we found a filename, remember that it is probably saved
+ relative to the executable that created it. If working directory
+ isn't there now, we may not be able to find the executable. Rather
+ than trying to be sauve about finding it, just check if the file
+ exists where we are now. If not, then punt and tell our client
+ we couldn't find the sym file.
+ */
+ p = (char *) failing_command;
+ if ((p != NULL) && (access (p, F_OK) != 0))
+ p = NULL;
+
+ return p;
+}
+
+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;
+{
+ return 0;
+}
+
+
+/* Okay, let's be honest: threads gleaned from a core file aren't
+ exactly lively, are they? On the other hand, if we don't claim
+ that each & every one is alive, then we don't get any of them
+ to appear in an "info thread" command, which is quite a useful
+ behaviour.
+ */
+static int
+core_file_thread_alive (tid)
+ int tid;
+{
+ return 1;
+}
+
+/* Fill in core_ops with its defined operations and properties. */
+
+static void
+init_core_ops ()
+{
+ core_ops.to_shortname = "core";
+ core_ops.to_longname = "Local core dump file";
+ core_ops.to_doc =
+ "Use a core file as a target. Specify the filename of the core file.";
+ core_ops.to_open = core_open;
+ core_ops.to_close = core_close;
+ core_ops.to_attach = find_default_attach;
+ core_ops.to_require_attach = find_default_require_attach;
+ core_ops.to_detach = core_detach;
+ core_ops.to_require_detach = find_default_require_detach;
+ core_ops.to_fetch_registers = get_core_registers;
+ core_ops.to_xfer_memory = xfer_memory;
+ core_ops.to_files_info = core_files_info;
+ core_ops.to_insert_breakpoint = ignore;
+ core_ops.to_remove_breakpoint = ignore;
+ core_ops.to_create_inferior = find_default_create_inferior;
+ core_ops.to_clone_and_follow_inferior = find_default_clone_and_follow_inferior;
+ core_ops.to_thread_alive = core_file_thread_alive;
+ core_ops.to_core_file_to_sym_file = core_file_to_sym_file;
+ core_ops.to_stratum = core_stratum;
+ core_ops.to_has_memory = 1;
+ core_ops.to_has_stack = 1;
+ core_ops.to_has_registers = 1;
+ core_ops.to_magic = OPS_MAGIC;
+}
+
+/* non-zero if we should not do the add_target call in
+ _initialize_corelow; not initialized (i.e., bss) so that
+ the target can initialize it (i.e., data) if appropriate.
+ This needs to be set at compile time because we don't know
+ for sure whether the target's initialize routine is called
+ before us or after us. */
+int coreops_suppress_target;
+
+void
+_initialize_corelow ()
+{
+ init_core_ops ();
+
+ if (!coreops_suppress_target)
+ add_target (&core_ops);
+}
diff --git a/gdb/cp-valprint.c b/gdb/cp-valprint.c
new file mode 100644
index 00000000000..eeeb79e010b
--- /dev/null
+++ b/gdb/cp-valprint.c
@@ -0,0 +1,826 @@
+/* Support for printing C++ values for GDB, the GNU debugger.
+ Copyright 1986, 1988, 1989, 1991, 1994, 1995, 1996
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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"
+#include "annotate.h"
+#include "gdb_string.h"
+#include "c-lang.h"
+#include "target.h"
+
+/* Indication of presence of HP-compiled object files */
+extern int hp_som_som_object_present; /* defined in symtab.c */
+
+
+int vtblprint; /* Controls printing of vtbl's */
+int objectprint; /* Controls looking up an object's derived type
+ using what we find in its vtables. */
+int static_field_print; /* Controls printing of static fields. */
+
+static struct obstack dont_print_vb_obstack;
+static struct obstack dont_print_statmem_obstack;
+
+static void
+cp_print_static_field PARAMS ((struct type *, value_ptr, GDB_FILE *, int, int,
+ enum val_prettyprint));
+
+static void
+cp_print_value PARAMS ((struct type *, struct type *, char *, int, CORE_ADDR, GDB_FILE *,
+ int, int, enum val_prettyprint, struct type **));
+
+static void
+cp_print_hpacc_virtual_table_entries PARAMS ((struct type *, int *, value_ptr, GDB_FILE *,
+ int, int, enum val_prettyprint));
+
+
+void
+cp_print_class_method (valaddr, type, stream)
+ char *valaddr;
+ struct type *type;
+ GDB_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;
+ struct type *target_type = check_typedef (TYPE_TARGET_TYPE (type));
+
+ domain = TYPE_DOMAIN_TYPE (target_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)
+ {
+ if (TYPE_FN_FIELD_STUB (f, j))
+ check_stub_method (domain, i, j);
+ kind = "virtual ";
+ goto common;
+ }
+ }
+ }
+ }
+ else
+ {
+ sym = find_pc_function (addr);
+ if (sym == 0)
+ {
+ /* 1997-08-01 Currently unsupported with HP aCC */
+ if (hp_som_som_object_present)
+ {
+ fputs_filtered ("?? <not supported with HP aCC>", stream);
+ return;
+ }
+ 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)
+ {
+ char *demangled_name;
+
+ fprintf_filtered (stream, "&");
+ fprintf_filtered (stream, kind);
+ demangled_name = cplus_demangle (TYPE_FN_FIELD_PHYSNAME (f, j),
+ DMGL_ANSI | DMGL_PARAMS);
+ if (demangled_name == NULL)
+ fprintf_filtered (stream, "<badly mangled name %s>",
+ TYPE_FN_FIELD_PHYSNAME (f, j));
+ else
+ {
+ fputs_filtered (demangled_name, stream);
+ free (demangled_name);
+ }
+ }
+ else
+ {
+ fprintf_filtered (stream, "(");
+ type_print (type, "", stream, -1);
+ fprintf_filtered (stream, ") %d", (int) addr >> 3);
+ }
+}
+
+/* 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. */
+const char vtbl_ptr_name[] =
+ { '_','_','v','t','b','l','_','p','t','r','_','t','y','p','e', 0 };
+
+/* HP aCC uses different names */
+const char hpacc_vtbl_ptr_name[] =
+ { '_', '_', 'v', 'f', 'p', 0 };
+const char hpacc_vtbl_ptr_type_name[] =
+ { '_', '_', 'v', 'f', 't', 'y', 'p', 0 };
+
+
+/* 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);
+
+ 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);
+ if (TYPE_CODE (type) == TYPE_CODE_ARRAY)
+ {
+ type = TYPE_TARGET_TYPE (type);
+ if (TYPE_CODE (type) == TYPE_CODE_STRUCT /* if not using thunks */
+ || TYPE_CODE (type) == TYPE_CODE_PTR) /* if using thunks */
+ {
+ /* Virtual functions tables are full of pointers
+ to virtual functions. */
+ return cp_is_vtbl_ptr_type (type);
+ }
+ }
+ }
+ return 0;
+}
+
+/* Mutually recursive subroutines of cp_print_value and c_val_print to
+ print out a structure's fields: cp_print_value_fields and cp_print_value.
+
+ TYPE, VALADDR, ADDRESS, STREAM, RECURSE, and PRETTY have the
+ same meanings as in cp_print_value and c_val_print.
+
+ 2nd argument REAL_TYPE is used to carry over the type of the derived
+ class across the recursion to base classes.
+
+ 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, real_type, valaddr, offset, address, stream, format, recurse, pretty,
+ dont_print_vb, dont_print_statmem)
+ struct type *type;
+ struct type *real_type;
+ char *valaddr;
+ int offset;
+ CORE_ADDR address;
+ GDB_FILE *stream;
+ int format;
+ int recurse;
+ enum val_prettyprint pretty;
+ struct type **dont_print_vb;
+ int dont_print_statmem;
+{
+ int i, len, n_baseclasses;
+ struct obstack tmp_obstack;
+ char *last_dont_print = obstack_next_free (&dont_print_statmem_obstack);
+ int fields_seen = 0;
+
+ CHECK_TYPEDEF (type);
+
+ fprintf_filtered (stream, "{");
+ len = TYPE_NFIELDS (type);
+ n_baseclasses = TYPE_N_BASECLASSES (type);
+
+ /* First, print out baseclasses such that we don't print
+ duplicates of virtual baseclasses. */
+
+ if (n_baseclasses > 0)
+ cp_print_value (type, real_type, valaddr, offset, address, stream,
+ format, recurse+1, pretty, dont_print_vb);
+
+ /* Second, print out data fields */
+
+ /* If there are no data fields, or if the only field is the
+ * vtbl pointer, skip this part */
+ if ((len == n_baseclasses) ||
+ ((len - n_baseclasses == 1) &&
+ TYPE_HAS_VTABLE(type) &&
+ STREQN(TYPE_FIELD_NAME (type, n_baseclasses), hpacc_vtbl_ptr_name, 5)) ||
+ !len)
+ fprintf_filtered (stream, "<No data fields>");
+ else
+ {
+ extern int inspect_it;
+
+ if (dont_print_statmem == 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_statmem_obstack;
+ obstack_finish (&dont_print_statmem_obstack);
+ }
+
+ for (i = n_baseclasses; i < len; i++)
+ {
+ /* If requested, skip printing of static fields. */
+ if (!static_field_print && TYPE_FIELD_STATIC (type, i))
+ continue;
+
+ /* If a vtable pointer appears, we'll print it out later */
+ if (TYPE_HAS_VTABLE(type) && STREQN(TYPE_FIELD_NAME (type, i), hpacc_vtbl_ptr_name, 5))
+ 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);
+ if (TYPE_FIELD_STATIC (type, i))
+ fputs_filtered ("static ", 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
+ {
+ annotate_field_begin (TYPE_FIELD_TYPE (type, i));
+
+ if (TYPE_FIELD_STATIC (type, i))
+ fputs_filtered ("static ", stream);
+ fprintf_symbol_filtered (stream, TYPE_FIELD_NAME (type, i),
+ language_cplus,
+ DMGL_PARAMS | DMGL_ANSI);
+ annotate_field_name_end ();
+ /* do not print leading '=' in case of anonymous unions */
+ if (strcmp (TYPE_FIELD_NAME (type, i), ""))
+ fputs_filtered (" = ", stream);
+ annotate_field_value ();
+ }
+
+ if (!TYPE_FIELD_STATIC (type, i) && TYPE_FIELD_PACKED (type, i))
+ {
+ value_ptr v;
+
+ /* Bitfields require special handling, especially due to byte
+ order problems. */
+ if (TYPE_FIELD_IGNORE (type, i))
+ {
+ fputs_filtered ("<optimized out or zero length>", stream);
+ }
+ else
+ {
+ v = value_from_longest (TYPE_FIELD_TYPE (type, i),
+ unpack_field_as_long (type, valaddr + offset, i));
+
+ val_print (TYPE_FIELD_TYPE(type, i), VALUE_CONTENTS (v), 0, 0,
+ stream, format, 0, recurse + 1, pretty);
+ }
+ }
+ else
+ {
+ if (TYPE_FIELD_IGNORE (type, i))
+ {
+ fputs_filtered ("<optimized out or zero length>", stream);
+ }
+ else if (TYPE_FIELD_STATIC (type, i))
+ {
+ value_ptr v = value_static_field (type, i);
+ if (v == NULL)
+ fputs_filtered ("<optimized out>", stream);
+ else
+ cp_print_static_field (TYPE_FIELD_TYPE (type, i), v,
+ stream, format, recurse + 1,
+ pretty);
+ }
+ else
+ {
+ val_print (TYPE_FIELD_TYPE (type, i),
+ valaddr, offset + TYPE_FIELD_BITPOS (type, i) / 8,
+ address + TYPE_FIELD_BITPOS (type, i) / 8,
+ stream, format, 0, recurse + 1, pretty);
+ }
+ }
+ annotate_field_end ();
+ }
+
+ if (dont_print_statmem == 0)
+ {
+ /* Free the space used to deal with the printing
+ of the members from top level. */
+ obstack_free (&dont_print_statmem_obstack, last_dont_print);
+ dont_print_statmem_obstack = tmp_obstack;
+ }
+
+ if (pretty)
+ {
+ fprintf_filtered (stream, "\n");
+ print_spaces_filtered (2 * recurse, stream);
+ }
+ } /* if there are data fields */
+ /* Now print out the virtual table pointer if there is one */
+ if (TYPE_HAS_VTABLE(type) && STREQN(TYPE_FIELD_NAME (type, n_baseclasses), hpacc_vtbl_ptr_name, 5))
+ {
+ value_ptr v;
+ /* First get the virtual table pointer and print it out*/
+
+#if 0
+ fputs_filtered ("__vfp = ", stream);
+#endif
+
+ fputs_filtered (", Virtual table at ", stream);
+
+ /* pai: FIXME 32x64 problem? */
+ /* Not sure what the best notation is in the case where there is no
+ baseclass name. */
+ v = value_from_longest (lookup_pointer_type (builtin_type_unsigned_long),
+ * (unsigned long *) (valaddr + offset));
+
+ val_print (VALUE_TYPE (v), VALUE_CONTENTS (v), 0, 0,
+ stream, format, 0, recurse + 1, pretty);
+ fields_seen = 1;
+
+ if (vtblprint)
+ {
+ /* Print out function pointers in vtable. */
+
+ /* FIXME: then-clause is for non-RRBC layout of virtual
+ * table. The RRBC case in the else-clause is yet to be
+ * implemented. The if (1) below should be changed to a
+ * test for whether the executable we have was compiled
+ * with a version of HP aCC that doesn't have RRBC
+ * support. */
+
+ if (1)
+ {
+ /* no RRBC support; function pointers embedded directly in vtable */
+
+ int vfuncs = count_virtual_fns (real_type);
+
+ fputs_filtered (" {", stream);
+
+ /* FIXME : doesn't work at present */
+#if 0
+ fprintf_filtered (stream, "%d entr%s: ", vfuncs, vfuncs == 1 ? "y" : "ies");
+#else
+ fputs_filtered ("not implemented", stream);
+
+
+#endif
+
+ /* recursive function that prints all virtual function entries */
+#if 0
+ cp_print_hpacc_virtual_table_entries (real_type, &vfuncs, v, stream, format, recurse, pretty);
+#endif
+ fputs_filtered ("}", stream);
+ } /* non-RRBC case */
+ else
+ {
+ /* FIXME -- seem comments above */
+ /* RRBC support present; function pointers are found
+ * by indirection through the class segment entries. */
+
+
+ } /* RRBC case */
+ } /* if vtblprint */
+
+ if (pretty)
+ {
+ fprintf_filtered (stream, "\n");
+ print_spaces_filtered (2 * recurse, stream);
+ }
+
+ } /* if vtable exists */
+
+ fprintf_filtered (stream, "}");
+}
+
+/* Special val_print routine to avoid printing multiple copies of virtual
+ baseclasses. */
+
+static void
+cp_print_value (type, real_type, valaddr, offset, address, stream, format, recurse, pretty,
+ dont_print_vb)
+ struct type *type;
+ struct type *real_type;
+ char *valaddr;
+ int offset;
+ CORE_ADDR address;
+ GDB_FILE *stream;
+ int format;
+ int recurse;
+ enum val_prettyprint pretty;
+ struct type **dont_print_vb;
+{
+ struct obstack tmp_obstack;
+ struct type **last_dont_print
+ = (struct type **)obstack_next_free (&dont_print_vb_obstack);
+ int i, n_baseclasses = TYPE_N_BASECLASSES (type);
+
+ if (dont_print_vb == 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_vb_obstack;
+ /* Bump up the high-water mark. Now alpha is omega. */
+ obstack_finish (&dont_print_vb_obstack);
+ }
+
+ for (i = 0; i < n_baseclasses; i++)
+ {
+ int boffset;
+ int skip;
+ struct type *baseclass = check_typedef (TYPE_BASECLASS (type, i));
+ char *basename = TYPE_NAME (baseclass);
+ char *base_valaddr;
+
+ if (BASETYPE_VIA_VIRTUAL (type, i))
+ {
+ struct type **first_dont_print
+ = (struct type **)obstack_base (&dont_print_vb_obstack);
+
+ int j = (struct type **)obstack_next_free (&dont_print_vb_obstack)
+ - first_dont_print;
+
+ while (--j >= 0)
+ if (baseclass == first_dont_print[j])
+ goto flush_it;
+
+ obstack_ptr_grow (&dont_print_vb_obstack, baseclass);
+ }
+
+ if (TYPE_HAS_VTABLE (type) && BASETYPE_VIA_VIRTUAL (type, i))
+ {
+ /* Assume HP/Taligent runtime convention */
+ find_rt_vbase_offset (type, TYPE_BASECLASS (type, i),
+ valaddr, offset, &boffset, &skip);
+ if (skip >= 0)
+ error ("Virtual base class offset not found from vtable while printing");
+ base_valaddr = valaddr;
+ }
+ else
+ {
+ boffset = baseclass_offset (type, i , valaddr + offset, address + offset);
+ skip = ((boffset == -1) || (boffset+offset) < 0 ) ? 1 : -1;
+
+ if (BASETYPE_VIA_VIRTUAL (type, i))
+ {
+ /* The virtual base class pointer might have been clobbered by the
+ user program. Make sure that it still points to a valid memory
+ location. */
+
+ if (boffset != -1 && ((boffset+offset) < 0 || (boffset+offset) >= TYPE_LENGTH (type)))
+ {
+ base_valaddr = (char *) alloca (TYPE_LENGTH (baseclass));
+ if (target_read_memory (address + boffset, base_valaddr,
+ TYPE_LENGTH (baseclass)) != 0)
+ skip = 1;
+ }
+ else
+ base_valaddr = valaddr;
+ }
+ else
+ base_valaddr = valaddr;
+ }
+
+ /* now do the printing */
+ 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 (skip >= 1)
+ fprintf_filtered (stream, "<invalid address>");
+ else
+ cp_print_value_fields (baseclass, real_type, base_valaddr, offset + boffset, address,
+ stream, format, recurse, pretty,
+ (struct type **) obstack_base (&dont_print_vb_obstack),
+ 0);
+ fputs_filtered (", ", stream);
+
+ flush_it:
+ ;
+ }
+
+ if (dont_print_vb == 0)
+ {
+ /* Free the space used to deal with the printing
+ of this type from top level. */
+ obstack_free (&dont_print_vb_obstack, last_dont_print);
+ /* Reset watermark so that we can continue protecting
+ ourselves from whatever we were protecting ourselves. */
+ dont_print_vb_obstack = tmp_obstack;
+ }
+}
+
+/* Print value of a static member.
+ To avoid infinite recursion when printing a class that contains
+ a static instance of the class, we keep the addresses of all printed
+ static member classes in an obstack and refuse to print them more
+ than once.
+
+ VAL contains the value to print, TYPE, STREAM, RECURSE, and PRETTY
+ have the same meanings as in c_val_print. */
+
+static void
+cp_print_static_field (type, val, stream, format, recurse, pretty)
+ struct type *type;
+ value_ptr val;
+ GDB_FILE *stream;
+ int format;
+ int recurse;
+ enum val_prettyprint pretty;
+{
+ if (TYPE_CODE (type) == TYPE_CODE_STRUCT)
+ {
+ CORE_ADDR *first_dont_print;
+ int i;
+
+ first_dont_print
+ = (CORE_ADDR *)obstack_base (&dont_print_statmem_obstack);
+ i = (CORE_ADDR *)obstack_next_free (&dont_print_statmem_obstack)
+ - first_dont_print;
+
+ while (--i >= 0)
+ {
+ if (VALUE_ADDRESS (val) == first_dont_print[i])
+ {
+ fputs_filtered ("<same as static member of an already seen type>",
+ stream);
+ return;
+ }
+ }
+
+ obstack_grow (&dont_print_statmem_obstack, (char *) &VALUE_ADDRESS (val),
+ sizeof (CORE_ADDR));
+
+ CHECK_TYPEDEF (type);
+ cp_print_value_fields (type, type, VALUE_CONTENTS_ALL (val), VALUE_EMBEDDED_OFFSET (val), VALUE_ADDRESS (val),
+ stream, format, recurse, pretty, NULL, 1);
+ return;
+ }
+ val_print (type, VALUE_CONTENTS_ALL (val), VALUE_EMBEDDED_OFFSET (val), VALUE_ADDRESS (val),
+ stream, format, 0, recurse, pretty);
+}
+
+void
+cp_print_class_member (valaddr, domain, stream, prefix)
+ char *valaddr;
+ struct type *domain;
+ GDB_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 */
+
+ /* Note: HP aCC generates offsets that are the real byte offsets added
+ to a constant bias 0x20000000 (1 << 29). This constant bias gets
+ shifted out in the code below -- joyous happenstance! */
+
+ /* Note: HP cfront uses a constant bias of 1; if we support this
+ compiler ever, we will have to adjust the computation below */
+
+ 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);
+}
+
+
+/* This function prints out virtual table entries for a class; it
+ * recurses on the base classes to find all virtual functions
+ * available in a class.
+ *
+ * pai/1997-05-21 Note: As the name suggests, it's currently
+ * implemented for HP aCC runtime only. g++ objects are handled
+ * differently and I have made no attempt to fold that logic in
+ * here. The runtime layout is different for the two cases. Also,
+ * this currently has only the code for non-RRBC layouts generated by
+ * the HP aCC compiler; RRBC code is stubbed out and will have to be
+ * added later. */
+
+
+static void
+cp_print_hpacc_virtual_table_entries (type, vfuncs, v, stream, format, recurse, pretty)
+ struct type * type;
+ int * vfuncs;
+ value_ptr v;
+ GDB_FILE *stream;
+ int format;
+ int recurse;
+ enum val_prettyprint pretty;
+{
+ int fn, oi;
+
+ /* pai: FIXME this function doesn't work. It should handle a given
+ * virtual function only once (latest redefinition in class hierarchy)
+ */
+
+ /* Recursion on other classes that can share the same vtable */
+ struct type * pbc = primary_base_class (type);
+ if (pbc)
+ cp_print_hpacc_virtual_table_entries (pbc, vfuncs, v, stream, format, recurse, pretty);
+
+ /* Now deal with vfuncs declared in this class */
+ for (fn = 0; fn < TYPE_NFN_FIELDS (type); fn++)
+ for (oi = 0; oi < TYPE_FN_FIELDLIST_LENGTH (type, fn); oi++)
+ if (TYPE_FN_FIELD_VIRTUAL_P (TYPE_FN_FIELDLIST1 (type, fn), oi))
+ {
+ char * vf_name;
+
+ /* virtual function offset */
+ int vx = TYPE_FN_FIELD_VOFFSET (TYPE_FN_FIELDLIST1 (type, fn), oi) - 1;
+
+ /* Get the address of the vfunction entry */
+ value_ptr vf = value_copy (v);
+ if (VALUE_LAZY (vf))
+ (void) value_fetch_lazy (vf);
+ vf->aligner.contents[0] += 4 * (HP_ACC_VFUNC_START + vx); /* adjust by offset */
+ vf = value_ind (vf); /* get the entry */
+ VALUE_TYPE (vf) = VALUE_TYPE (v); /* make it a pointer */
+
+ /* print out the entry */
+ val_print (VALUE_TYPE (vf), VALUE_CONTENTS (vf), 0, 0,
+ stream, format, 0, recurse + 1, pretty);
+ vf_name = cplus_demangle (TYPE_FN_FIELD_PHYSNAME (TYPE_FN_FIELDLIST1 (type, fn), oi),
+ DMGL_ARM); /* pai: (temp) FIXME Maybe this should be DMGL_ANSI */
+ fprintf_filtered (stream, " %s", vf_name);
+ if (--(*vfuncs) > 0)
+ fputs_filtered (", ", stream);
+ }
+}
+
+
+
+void
+_initialize_cp_valprint ()
+{
+ add_show_from_set
+ (add_set_cmd ("static-members", class_support, var_boolean,
+ (char *)&static_field_print,
+ "Set printing of C++ static members.",
+ &setprintlist),
+ &showprintlist);
+ /* Turn on printing of static fields. */
+ static_field_print = 1;
+
+ 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_vb_obstack, 32 * sizeof (struct type *));
+ obstack_specify_allocation (&dont_print_statmem_obstack,
+ 32 * sizeof (CORE_ADDR), sizeof (CORE_ADDR),
+ xmalloc, free);
+}
diff --git a/gdb/cpu32bug-rom.c b/gdb/cpu32bug-rom.c
new file mode 100644
index 00000000000..758c8caad9e
--- /dev/null
+++ b/gdb/cpu32bug-rom.c
@@ -0,0 +1,167 @@
+/* Remote debugging interface for CPU32Bug Rom monitor for GDB, the GNU debugger.
+ Copyright 1995 Free Software Foundation, Inc.
+
+ Written by Stu Grossman of 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "gdbcore.h"
+#include "target.h"
+#include "monitor.h"
+#include "serial.h"
+
+static void cpu32bug_open PARAMS ((char *args, int from_tty));
+
+static void
+cpu32bug_supply_register (regname, regnamelen, val, vallen)
+ char *regname;
+ int regnamelen;
+ char *val;
+ int vallen;
+{
+ int regno;
+
+ if (regnamelen != 2)
+ return;
+
+ switch (regname[0])
+ {
+ case 'S':
+ if (regname[1] != 'R')
+ return;
+ regno = PS_REGNUM;
+ break;
+ case 'P':
+ if (regname[1] != 'C')
+ return;
+ regno = PC_REGNUM;
+ break;
+ case 'D':
+ if (regname[1] < '0' || regname[1] > '7')
+ return;
+ regno = regname[1] - '0' + D0_REGNUM;
+ break;
+ case 'A':
+ if (regname[1] < '0' || regname[1] > '7')
+ return;
+ regno = regname[1] - '0' + A0_REGNUM;
+ break;
+ default:
+ return;
+ }
+
+ monitor_supply_register (regno, val);
+}
+
+/*
+ * This array of registers needs to match the indexes used by GDB. The
+ * whole reason this exists is because the various ROM monitors use
+ * different names than GDB does, and don't support all the
+ * registers either. So, typing "info reg sp" becomes an "A7".
+ */
+
+static char *cpu32bug_regnames[NUM_REGS] =
+{
+ "D0", "D1", "D2", "D3", "D4", "D5", "D6", "D7",
+ "A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7",
+ "SR", "PC",
+};
+
+/*
+ * Define the monitor command strings. Since these are passed directly
+ * through to a printf style function, we need can include formatting
+ * strings. We also need a CR or LF on the end.
+ */
+
+static struct target_ops cpu32bug_ops;
+
+static char *cpu32bug_inits[] = {"\r", NULL};
+
+static struct monitor_ops cpu32bug_cmds ;
+
+static void
+init_cpu32bug_cmds(void)
+{
+ cpu32bug_cmds.flags = MO_CLR_BREAK_USES_ADDR;
+ cpu32bug_cmds.init = cpu32bug_inits; /* Init strings */
+ cpu32bug_cmds.cont = "g\r"; /* continue command */
+ cpu32bug_cmds.step = "t\r"; /* single step */
+ cpu32bug_cmds.stop = NULL; /* interrupt command */
+ cpu32bug_cmds.set_break = "br %x\r"; /* set a breakpoint */
+ cpu32bug_cmds.clr_break = "nobr %x\r"; /* clear a breakpoint */
+ cpu32bug_cmds.clr_all_break = "nobr\r"; /* clear all breakpoints */
+ cpu32bug_cmds.fill = "bf %x:%x %x;b\r"; /* fill (start count val) */
+ cpu32bug_cmds.setmem.cmdb = "ms %x %02x\r"; /* setmem.cmdb (addr, value) */
+ cpu32bug_cmds.setmem.cmdw = "ms %x %04x\r"; /* setmem.cmdw (addr, value) */
+ cpu32bug_cmds.setmem.cmdl = "ms %x %08x\r"; /* setmem.cmdl (addr, value) */
+ cpu32bug_cmds.setmem.cmdll = NULL; /* setmem.cmdll (addr, value) */
+ cpu32bug_cmds.setmem.resp_delim = NULL; /* setreg.resp_delim */
+ cpu32bug_cmds.setmem.term = NULL; /* setreg.term */
+ cpu32bug_cmds.setmem.term_cmd = NULL; /* setreg.term_cmd */
+ cpu32bug_cmds.getmem.cmdb = "md %x:%x;b\r"; /* getmem.cmdb (addr, len) */
+ cpu32bug_cmds.getmem.cmdw = "md %x:%x;b\r"; /* getmem.cmdw (addr, len) */
+ cpu32bug_cmds.getmem.cmdl = "md %x:%x;b\r"; /* getmem.cmdl (addr, len) */
+ cpu32bug_cmds.getmem.cmdll = NULL; /* getmem.cmdll (addr, len) */
+ cpu32bug_cmds.getmem.resp_delim = " "; /* getmem.resp_delim */
+ cpu32bug_cmds.getmem.term = NULL; /* getmem.term */
+ cpu32bug_cmds.getmem.term_cmd = NULL; /* getmem.term_cmd */
+ cpu32bug_cmds.setreg.cmd = "rs %s %x\r"; /* setreg.cmd (name, value) */
+ cpu32bug_cmds.setreg.resp_delim = NULL; /* setreg.resp_delim */
+ cpu32bug_cmds.setreg.term = NULL; /* setreg.term */
+ cpu32bug_cmds.setreg.term_cmd = NULL; /* setreg.term_cmd */
+ cpu32bug_cmds.getreg.cmd = "rs %s\r"; /* getreg.cmd (name) */
+ cpu32bug_cmds.getreg.resp_delim = "="; /* getreg.resp_delim */
+ cpu32bug_cmds.getreg.term = NULL; /* getreg.term */
+ cpu32bug_cmds.getreg.term_cmd = NULL ; /* getreg.term_cmd */
+ cpu32bug_cmds.dump_registers = "rd\r"; /* dump_registers */
+ cpu32bug_cmds.register_pattern = "\\(\\w+\\) +=\\([0-9a-fA-F]+\\b\\)"; /* register_pattern */
+ cpu32bug_cmds.supply_register = cpu32bug_supply_register; /* supply_register */
+ cpu32bug_cmds.load_routine = NULL; /* load_routine (defaults to SRECs) */
+ cpu32bug_cmds.load = "lo\r"; /* download command */
+ cpu32bug_cmds.loadresp = "\n"; /* load response */
+ cpu32bug_cmds.prompt = "CPU32Bug>"; /* monitor command prompt */
+ cpu32bug_cmds.line_term = "\r"; /* end-of-line terminator */
+ cpu32bug_cmds.cmd_end = NULL; /* optional command terminator */
+ cpu32bug_cmds.target = &cpu32bug_ops; /* target operations */
+ cpu32bug_cmds.stopbits = SERIAL_1_STOPBITS; /* number of stop bits */
+ cpu32bug_cmds.regnames = cpu32bug_regnames; /* registers names */
+ cpu32bug_cmds.magic = MONITOR_OPS_MAGIC; /* magic */
+}; /* init_cpu32bug_cmds */
+
+static void
+cpu32bug_open(args, from_tty)
+ char *args;
+ int from_tty;
+{
+ monitor_open (args, &cpu32bug_cmds, from_tty);
+}
+
+void
+_initialize_cpu32bug_rom ()
+{
+ init_cpu32bug_cmds() ;
+ init_monitor_ops (&cpu32bug_ops);
+
+ cpu32bug_ops.to_shortname = "cpu32bug";
+ cpu32bug_ops.to_longname = "CPU32Bug monitor";
+ cpu32bug_ops.to_doc = "Debug via the CPU32Bug monitor.\n\
+Specify the serial device it is connected to (e.g. /dev/ttya).";
+ cpu32bug_ops.to_open = cpu32bug_open;
+
+ add_target (&cpu32bug_ops);
+}
diff --git a/gdb/cxux-nat.c b/gdb/cxux-nat.c
new file mode 100644
index 00000000000..2c4b6f1667d
--- /dev/null
+++ b/gdb/cxux-nat.c
@@ -0,0 +1,523 @@
+/* Native support for Motorola 88k running Harris CX/UX.
+ Copyright 1988, 1990, 1991, 1992, 1993, 1994 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "frame.h"
+#include "inferior.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/dir.h>
+#include <signal.h>
+#include "gdbcore.h"
+#include <sys/user.h>
+
+#include "bfd.h"
+#include "symfile.h"
+#include "objfiles.h"
+#include "symtab.h"
+
+#ifndef USER /* added to support BCS ptrace_user */
+#define USER ptrace_user
+#endif
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <sys/file.h>
+#include "gdb_stat.h"
+
+#include "symtab.h"
+#include "setjmp.h"
+#include "value.h"
+
+#include <sys/ptrace.h>
+
+/* CX/UX provides them already, but as word offsets instead of char offsets */
+#define SXIP_OFFSET (PT_SXIP * 4)
+#define SNIP_OFFSET (PT_SNIP * 4)
+#define SFIP_OFFSET (PT_SFIP * 4)
+#define PSR_OFFSET (PT_PSR * sizeof(int))
+#define FPSR_OFFSET (PT_FPSR * sizeof(int))
+#define FPCR_OFFSET (PT_FPCR * sizeof(int))
+
+#define XREGADDR(r) (((char *)&u.pt_x0-(char *)&u) + \
+ ((r)-X0_REGNUM)*sizeof(X_REGISTER_RAW_TYPE))
+
+extern int have_symbol_file_p();
+
+extern jmp_buf stack_jmp;
+
+extern int errno;
+extern char registers[REGISTER_BYTES];
+
+void
+fetch_inferior_registers (regno)
+ int regno; /* Original value discarded */
+{
+ register unsigned int regaddr;
+ char buf[MAX_REGISTER_RAW_SIZE];
+ register int i;
+
+ struct USER u;
+ unsigned int offset;
+
+ offset = (char *) &u.pt_r0 - (char *) &u;
+ regaddr = offset; /* byte offset to r0;*/
+
+/* offset = ptrace (3, inferior_pid, (PTRACE_ARG3_TYPE) offset, 0) - KERNEL_U_ADDR; */
+ for (regno = 0; regno < PC_REGNUM; regno++)
+ {
+ /*regaddr = register_addr (regno, offset);*/
+ /* 88k enhancement */
+
+ for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (int))
+ {
+ *(int *) &buf[i] = ptrace (3, inferior_pid,
+ (PTRACE_ARG3_TYPE) regaddr, 0);
+ regaddr += sizeof (int);
+ }
+ supply_register (regno, buf);
+ }
+ /* now load up registers 32-37; special pc registers */
+ *(int *) &buf[0] = ptrace (3, inferior_pid,
+ (PTRACE_ARG3_TYPE) PSR_OFFSET,0);
+ supply_register (PSR_REGNUM, buf);
+ *(int *) &buf[0] = ptrace (3, inferior_pid,
+ (PTRACE_ARG3_TYPE) FPSR_OFFSET,0);
+ supply_register (FPSR_REGNUM, buf);
+ *(int *) &buf[0] = ptrace (3, inferior_pid,
+ (PTRACE_ARG3_TYPE) FPCR_OFFSET,0);
+ supply_register (FPCR_REGNUM, buf);
+ *(int *) &buf[0] = ptrace (3,inferior_pid,
+ (PTRACE_ARG3_TYPE) SXIP_OFFSET ,0);
+ supply_register (SXIP_REGNUM, buf);
+ *(int *) &buf[0] = ptrace (3, inferior_pid,
+ (PTRACE_ARG3_TYPE) SNIP_OFFSET,0);
+ supply_register (SNIP_REGNUM, buf);
+ *(int *) &buf[0] = ptrace (3, inferior_pid,
+ (PTRACE_ARG3_TYPE) SFIP_OFFSET,0);
+ supply_register (SFIP_REGNUM, buf);
+
+ if (target_is_m88110)
+ {
+ for (regaddr = XREGADDR(X0_REGNUM), regno = X0_REGNUM;
+ regno < NUM_REGS;
+ regno++, regaddr += 16)
+ {
+ X_REGISTER_RAW_TYPE xval;
+
+ *(int *) &xval.w1 = ptrace (3, inferior_pid,
+ (PTRACE_ARG3_TYPE) regaddr, 0);
+ *(int *) &xval.w2 = ptrace (3, inferior_pid,
+ (PTRACE_ARG3_TYPE) (regaddr+4), 0);
+ *(int *) &xval.w3 = ptrace (3, inferior_pid,
+ (PTRACE_ARG3_TYPE) (regaddr+8), 0);
+ *(int *) &xval.w4 = ptrace (3, inferior_pid,
+ (PTRACE_ARG3_TYPE) (regaddr+12), 0);
+ supply_register(regno, (void *)&xval);
+ }
+ }
+}
+
+/* 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];
+
+ struct USER u;
+
+ unsigned int offset = (char *) &u.pt_r0 - (char *) &u;
+
+ regaddr = offset;
+
+ /* Don't try to deal with EXIP_REGNUM or ENIP_REGNUM, because I think either
+ svr3 doesn't run on an 88110, or the kernel isolates the different (not
+ completely sure this is true, but seems to be. */
+ if (regno >= 0)
+ {
+ /* regaddr = register_addr (regno, offset); */
+ if (regno < PC_REGNUM)
+ {
+ regaddr = offset + regno * sizeof (int);
+ errno = 0;
+ ptrace (6, inferior_pid,
+ (PTRACE_ARG3_TYPE) regaddr, read_register (regno));
+ if (errno != 0)
+ {
+ sprintf (buf, "writing register number %d", regno);
+ perror_with_name (buf);
+ }
+ }
+ else if (regno == PSR_REGNUM)
+ ptrace (6, inferior_pid,
+ (PTRACE_ARG3_TYPE) PSR_OFFSET, read_register(regno));
+ else if (regno == FPSR_REGNUM)
+ ptrace (6, inferior_pid,
+ (PTRACE_ARG3_TYPE) FPSR_OFFSET, read_register(regno));
+ else if (regno == FPCR_REGNUM)
+ ptrace (6, inferior_pid,
+ (PTRACE_ARG3_TYPE) FPCR_OFFSET, read_register(regno));
+ else if (regno == SXIP_REGNUM)
+ ptrace (6, inferior_pid,
+ (PTRACE_ARG3_TYPE) SXIP_OFFSET, read_register(regno));
+ else if (regno == SNIP_REGNUM)
+ ptrace (6, inferior_pid,
+ (PTRACE_ARG3_TYPE) SNIP_OFFSET, read_register(regno));
+ else if (regno == SFIP_REGNUM)
+ ptrace (6, inferior_pid,
+ (PTRACE_ARG3_TYPE) SFIP_OFFSET, read_register(regno));
+ else if (target_is_m88110 && regno < NUM_REGS)
+ {
+ X_REGISTER_RAW_TYPE xval;
+
+ read_register_bytes(REGISTER_BYTE(regno), (char *)&xval,
+ sizeof(X_REGISTER_RAW_TYPE));
+ regaddr = XREGADDR(regno);
+ ptrace (6, inferior_pid, (PTRACE_ARG3_TYPE) regaddr, xval.w1);
+ ptrace (6, inferior_pid, (PTRACE_ARG3_TYPE) regaddr+4, xval.w2);
+ ptrace (6, inferior_pid, (PTRACE_ARG3_TYPE) regaddr+8, xval.w3);
+ ptrace (6, inferior_pid, (PTRACE_ARG3_TYPE) regaddr+12, xval.w4);
+ }
+ else
+ printf_unfiltered ("Bad register number for store_inferior routine\n");
+ }
+ else
+ {
+ for (regno = 0; regno < PC_REGNUM; regno++)
+ {
+ /* regaddr = register_addr (regno, offset); */
+ errno = 0;
+ regaddr = offset + regno * sizeof (int);
+ ptrace (6, inferior_pid,
+ (PTRACE_ARG3_TYPE) regaddr, read_register (regno));
+ if (errno != 0)
+ {
+ sprintf (buf, "writing register number %d", regno);
+ perror_with_name (buf);
+ }
+ }
+ ptrace (6, inferior_pid,
+ (PTRACE_ARG3_TYPE) PSR_OFFSET, read_register(regno));
+ ptrace (6, inferior_pid,
+ (PTRACE_ARG3_TYPE) FPSR_OFFSET,read_register(regno));
+ ptrace (6, inferior_pid,
+ (PTRACE_ARG3_TYPE) FPCR_OFFSET,read_register(regno));
+ ptrace (6,inferior_pid,
+ (PTRACE_ARG3_TYPE) SXIP_OFFSET,read_register(SXIP_REGNUM));
+ ptrace (6,inferior_pid,
+ (PTRACE_ARG3_TYPE) SNIP_OFFSET,read_register(SNIP_REGNUM));
+ ptrace (6,inferior_pid,
+ (PTRACE_ARG3_TYPE) SFIP_OFFSET,read_register(SFIP_REGNUM));
+ if (target_is_m88110)
+ {
+ for (regno = X0_REGNUM; regno < NUM_REGS; regno++)
+ {
+ X_REGISTER_RAW_TYPE xval;
+
+ read_register_bytes(REGISTER_BYTE(regno), (char *)&xval,
+ sizeof(X_REGISTER_RAW_TYPE));
+ regaddr = XREGADDR(regno);
+ ptrace (6, inferior_pid, (PTRACE_ARG3_TYPE) regaddr, xval.w1);
+ ptrace (6, inferior_pid, (PTRACE_ARG3_TYPE) (regaddr+4), xval.w2);
+ ptrace (6, inferior_pid, (PTRACE_ARG3_TYPE) (regaddr+8), xval.w3);
+ ptrace (6, inferior_pid, (PTRACE_ARG3_TYPE) (regaddr+12), xval.w4);
+ }
+ }
+ }
+}
+
+/* blockend is the address of the end of the user structure */
+
+m88k_register_u_addr (blockend, regnum)
+ int blockend, regnum;
+{
+ struct USER u;
+ int ustart = blockend - sizeof (struct USER);
+
+ if (regnum < PSR_REGNUM)
+ return (ustart + ((int) &u.pt_r0 - (int) &u) +
+ REGISTER_SIZE * regnum);
+ else if (regnum == PSR_REGNUM)
+ return (ustart + ((int) &u.pt_psr) - (int) &u);
+ else if (regnum == FPSR_REGNUM)
+ return (ustart + ((int) &u.pt_fpsr) - (int) &u);
+ else if (regnum == FPCR_REGNUM)
+ return (ustart + ((int) &u.pt_fpcr) - (int) &u);
+ else if (regnum == SXIP_REGNUM)
+ return (ustart + SXIP_OFFSET);
+ else if (regnum == SNIP_REGNUM)
+ return (ustart + SNIP_OFFSET);
+ else if (regnum == SFIP_REGNUM)
+ return (ustart + SFIP_OFFSET);
+ else if (target_is_m88110)
+ return (ustart + ((int) &u.pt_x0 - (int) &u) + /* Must be X register */
+ sizeof(u.pt_x0) * (regnum - X0_REGNUM));
+ else
+ return (blockend + REGISTER_SIZE * regnum);
+}
+
+#ifdef USE_PROC_FS
+
+#include <sys/procfs.h>
+
+/* Given a pointer to a general register set in /proc format (gregset_t *),
+ unpack the register contents and supply them as gdb's idea of the current
+ register values. */
+
+void
+supply_gregset (gregsetp)
+ gregset_t *gregsetp;
+{
+ register int regi;
+ register greg_t *regp = (greg_t *) gregsetp;
+
+ for (regi=0; regi <= SP_REGNUM; regi++)
+ supply_register (regi, (char *) (regp + regi));
+
+ supply_register (SXIP_REGNUM, (char *) (regp + R_XIP));
+ supply_register (SNIP_REGNUM, (char *) (regp + R_NIP));
+ supply_register (SFIP_REGNUM, (char *) (regp + R_FIP));
+ supply_register (PSR_REGNUM, (char *) (regp + R_PSR));
+ supply_register (FPSR_REGNUM, (char *) (regp + R_FPSR));
+ supply_register (FPCR_REGNUM, (char *) (regp + R_FPCR));
+}
+
+void
+fill_gregset (gregsetp, regno)
+ gregset_t *gregsetp;
+ int regno;
+{
+ int regi;
+ register greg_t *regp = (greg_t *) gregsetp;
+ extern char registers[];
+
+ for (regi = 0 ; regi <= R_R31 ; regi++)
+ if ((regno == -1) || (regno == regi))
+ *(regp + regi) = *(int *) &registers[REGISTER_BYTE(regi)];
+
+ if ((regno == -1) || (regno == SXIP_REGNUM))
+ *(regp + R_XIP) = *(int *) &registers[REGISTER_BYTE(SXIP_REGNUM)];
+ if ((regno == -1) || (regno == SNIP_REGNUM))
+ *(regp + R_NIP) = *(int *) &registers[REGISTER_BYTE(SNIP_REGNUM)];
+ if ((regno == -1) || (regno == SFIP_REGNUM))
+ *(regp + R_FIP) = *(int *) &registers[REGISTER_BYTE(SFIP_REGNUM)];
+ if ((regno == -1) || (regno == PSR_REGNUM))
+ *(regp + R_PSR) = *(int *) &registers[REGISTER_BYTE(PSR_REGNUM)];
+ if ((regno == -1) || (regno == FPSR_REGNUM))
+ *(regp + R_FPSR) = *(int *) &registers[REGISTER_BYTE(FPSR_REGNUM)];
+ if ((regno == -1) || (regno == FPCR_REGNUM))
+ *(regp + R_FPCR) = *(int *) &registers[REGISTER_BYTE(FPCR_REGNUM)];
+}
+
+#endif /* USE_PROC_FS */
+
+/* This support adds the equivalent of adb's % command. When
+ the `add-shared-symbol-files' command is given, this routine scans
+ the dynamic linker's link map and reads the minimal symbols
+ from each shared object file listed in the map. */
+
+struct link_map {
+ unsigned long l_addr; /* address at which object is mapped */
+ char *l_name; /* full name of loaded object */
+ void *l_ld; /* dynamic structure of object */
+ struct link_map *l_next; /* next link object */
+ struct link_map *l_prev; /* previous link object */
+};
+
+#define LINKS_MAP_POINTER "_ld_tail"
+#define LIBC_FILE "/usr/lib/libc.so.1"
+#define SHARED_OFFSET 0xf0001000
+
+#ifndef PATH_MAX
+#define PATH_MAX 1023 /* maximum size of path name on OS */
+#endif
+
+void
+add_shared_symbol_files ()
+{
+ void *desc;
+ struct link_map *ld_map, *lm, lms;
+ struct minimal_symbol *minsym;
+ struct objfile *objfile;
+ char *path_name;
+
+ if (! inferior_pid)
+ {
+ warning ("The program has not yet been started.");
+ return;
+ }
+
+ objfile = symbol_file_add (LIBC_FILE, 0, 0, 0, 0, 1, 0, 0);
+ minsym = lookup_minimal_symbol (LINKS_MAP_POINTER, objfile);
+
+ ld_map = (struct link_map *)
+ read_memory_integer (((int)SYMBOL_VALUE_ADDRESS(minsym) + SHARED_OFFSET), 4);
+ lm = ld_map;
+ while (lm)
+ {
+ int local_errno = 0;
+
+ read_memory ((CORE_ADDR)lm, (char*)&lms, sizeof (struct link_map));
+ if (lms.l_name)
+ {
+ if (target_read_string ((CORE_ADDR)lms.l_name, &path_name,
+ PATH_MAX, &local_errno))
+ {
+ symbol_file_add (path_name, 1, lms.l_addr, 0, 0, 0, 0, 0);
+ free(path_name);
+ }
+ }
+ /* traverse links in reverse order so that we get the
+ the symbols the user actually gets. */
+ lm = lms.l_prev;
+ }
+
+ /* Getting new symbols may change our opinion about what is
+ frameless. */
+ reinit_frame_cache ();
+}
+
+#if defined(_ES_MP)
+
+#include <sys/regset.h>
+
+unsigned int
+m88k_harris_core_register_addr (regno, reg_ptr)
+ int regno, reg_ptr;
+{
+ unsigned int word_offset;
+
+ switch (regno)
+ {
+ case PSR_REGNUM:
+ word_offset = R_EPSR;
+ break;
+ case FPSR_REGNUM:
+ word_offset = R_FPSR;
+ break;
+ case FPCR_REGNUM:
+ word_offset = R_FPCR;
+ break;
+ case SXIP_REGNUM:
+ word_offset = R_EXIP;
+ break;
+ case SNIP_REGNUM:
+ word_offset = R_ENIP;
+ break;
+ case SFIP_REGNUM:
+ word_offset = R_EFIP;
+ break;
+ default:
+ if (regno <= FP_REGNUM)
+ word_offset = regno;
+ else
+ word_offset = ((regno - X0_REGNUM) * 4);
+ }
+ return (word_offset * 4);
+}
+
+#endif /* _ES_MP */
+
+void
+_initialize_m88k_nat()
+{
+#ifdef _ES_MP
+ /* Enable 88110 support, as we don't support the 88100 under ES/MP. */
+
+ target_is_m88110 = 1;
+#elif defined(_CX_UX)
+ /* Determine whether we're running on an 88100 or an 88110. */
+ target_is_m88110 = (sinfo(SYSMACHINE,0) == SYS5800);
+#endif /* _CX_UX */
+}
+
+#ifdef _ES_MP
+/* Given a pointer to a general register set in /proc format (gregset_t *),
+ unpack the register contents and supply them as gdb's idea of the current
+ register values. */
+
+void
+supply_gregset (gregsetp)
+ gregset_t *gregsetp;
+{
+ register int regi;
+ register greg_t *regp = (greg_t *) gregsetp;
+
+ for (regi = 0 ; regi < R_R31 ; regi++)
+ {
+ supply_register (regi, (char *) (regp + regi));
+ }
+ supply_register (PSR_REGNUM, (char *) (regp + R_EPSR));
+ supply_register (FPSR_REGNUM, (char *) (regp + R_FPSR));
+ supply_register (FPCR_REGNUM, (char *) (regp + R_FPCR));
+ supply_register (SXIP_REGNUM, (char *) (regp + R_EXIP));
+ supply_register (SNIP_REGNUM, (char *) (regp + R_ENIP));
+ supply_register (SFIP_REGNUM, (char *) (regp + R_EFIP));
+}
+
+/* Given a pointer to a floating point register set in /proc format
+ (fpregset_t *), unpack the register contents and supply them as gdb's
+ idea of the current floating point register values. */
+
+void
+supply_fpregset (fpregsetp)
+ fpregset_t *fpregsetp;
+{
+ register int regi;
+ char *from;
+
+ for (regi = FP0_REGNUM ; regi <= FPLAST_REGNUM ; regi++)
+ {
+ from = (char *) &((*fpregsetp)[regi-FP0_REGNUM]);
+ supply_register (regi, from);
+ }
+}
+
+#endif /* _ES_MP */
+
+#ifdef _CX_UX
+
+#include <sys/regset.h>
+
+unsigned int m88k_harris_core_register_addr(int regno, int reg_ptr)
+{
+ unsigned int word_offset;
+
+ switch (regno) {
+ case PSR_REGNUM : word_offset = R_PSR; break;
+ case FPSR_REGNUM : word_offset = R_FPSR; break;
+ case FPCR_REGNUM : word_offset = R_FPCR; break;
+ case SXIP_REGNUM : word_offset = R_XIP; break;
+ case SNIP_REGNUM : word_offset = R_NIP; break;
+ case SFIP_REGNUM : word_offset = R_FIP; break;
+ default :
+ if (regno <= FP_REGNUM)
+ word_offset = regno;
+ else
+ word_offset = ((regno - X0_REGNUM) * 4) + R_X0;
+ }
+ return (word_offset * 4);
+}
+
+#endif /* _CX_UX */
diff --git a/gdb/d10v-tdep.c b/gdb/d10v-tdep.c
new file mode 100644
index 00000000000..f4b52f62295
--- /dev/null
+++ b/gdb/d10v-tdep.c
@@ -0,0 +1,1028 @@
+/* Target-dependent code for Mitsubishi D10V, for GDB.
+ Copyright (C) 1996, 1997 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Contributed by Martin Hunt, hunt@cygnus.com */
+
+#include "defs.h"
+#include "frame.h"
+#include "obstack.h"
+#include "symtab.h"
+#include "gdbtypes.h"
+#include "gdbcmd.h"
+#include "gdbcore.h"
+#include "gdb_string.h"
+#include "value.h"
+#include "inferior.h"
+#include "dis-asm.h"
+#include "symfile.h"
+#include "objfiles.h"
+
+void d10v_frame_find_saved_regs PARAMS ((struct frame_info *fi,
+ struct frame_saved_regs *fsr));
+
+int
+d10v_frame_chain_valid (chain, frame)
+ CORE_ADDR chain;
+ struct frame_info *frame; /* not used here */
+{
+ return ((chain) != 0 && (frame) != 0 && (frame)->pc > IMEM_START);
+}
+
+
+/* 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).
+
+ The d10v returns anything less than 8 bytes in size in
+ registers. */
+
+int
+d10v_use_struct_convention (gcc_p, type)
+ int gcc_p;
+ struct type *type;
+{
+ return (TYPE_LENGTH (type) > 8);
+}
+
+
+/* Discard from the stack the innermost frame, restoring all saved
+ registers. */
+
+void
+d10v_pop_frame (frame)
+ struct frame_info *frame;
+{
+ CORE_ADDR fp;
+ int regnum;
+ struct frame_saved_regs fsr;
+ char raw_buffer[8];
+
+ fp = FRAME_FP (frame);
+ /* fill out fsr with the address of where each */
+ /* register was stored in the frame */
+ get_frame_saved_regs (frame, &fsr);
+
+ /* now update the current registers with the old values */
+ for (regnum = A0_REGNUM; regnum < A0_REGNUM+2 ; regnum++)
+ {
+ if (fsr.regs[regnum])
+ {
+ read_memory (fsr.regs[regnum], raw_buffer, REGISTER_RAW_SIZE(regnum));
+ write_register_bytes (REGISTER_BYTE (regnum), raw_buffer, REGISTER_RAW_SIZE(regnum));
+ }
+ }
+ for (regnum = 0; regnum < SP_REGNUM; regnum++)
+ {
+ if (fsr.regs[regnum])
+ {
+ write_register (regnum, read_memory_unsigned_integer (fsr.regs[regnum], REGISTER_RAW_SIZE(regnum)));
+ }
+ }
+ if (fsr.regs[PSW_REGNUM])
+ {
+ write_register (PSW_REGNUM, read_memory_unsigned_integer (fsr.regs[PSW_REGNUM], REGISTER_RAW_SIZE(PSW_REGNUM)));
+ }
+
+ write_register (PC_REGNUM, read_register (LR_REGNUM));
+ write_register (SP_REGNUM, fp + frame->size);
+ target_store_registers (-1);
+ flush_cached_frames ();
+}
+
+static int
+check_prologue (op)
+ unsigned short op;
+{
+ /* st rn, @-sp */
+ if ((op & 0x7E1F) == 0x6C1F)
+ return 1;
+
+ /* st2w rn, @-sp */
+ if ((op & 0x7E3F) == 0x6E1F)
+ return 1;
+
+ /* subi sp, n */
+ if ((op & 0x7FE1) == 0x01E1)
+ return 1;
+
+ /* mv r11, sp */
+ if (op == 0x417E)
+ return 1;
+
+ /* nop */
+ if (op == 0x5E00)
+ return 1;
+
+ /* st rn, @sp */
+ if ((op & 0x7E1F) == 0x681E)
+ return 1;
+
+ /* st2w rn, @sp */
+ if ((op & 0x7E3F) == 0x3A1E)
+ return 1;
+
+ return 0;
+}
+
+CORE_ADDR
+d10v_skip_prologue (pc)
+ CORE_ADDR pc;
+{
+ unsigned long op;
+ unsigned short op1, op2;
+ CORE_ADDR func_addr, func_end;
+ struct symtab_and_line sal;
+
+ /* If we have line debugging information, then the end of the */
+ /* prologue should the first assembly instruction of the first source line */
+ if (find_pc_partial_function (pc, NULL, &func_addr, &func_end))
+ {
+ sal = find_pc_line (func_addr, 0);
+ if ( sal.end && sal.end < func_end)
+ return sal.end;
+ }
+
+ if (target_read_memory (pc, (char *)&op, 4))
+ return pc; /* Can't access it -- assume no prologue. */
+
+ while (1)
+ {
+ op = (unsigned long)read_memory_integer (pc, 4);
+ if ((op & 0xC0000000) == 0xC0000000)
+ {
+ /* long instruction */
+ if ( ((op & 0x3FFF0000) != 0x01FF0000) && /* add3 sp,sp,n */
+ ((op & 0x3F0F0000) != 0x340F0000) && /* st rn, @(offset,sp) */
+ ((op & 0x3F1F0000) != 0x350F0000)) /* st2w rn, @(offset,sp) */
+ break;
+ }
+ else
+ {
+ /* short instructions */
+ if ((op & 0xC0000000) == 0x80000000)
+ {
+ op2 = (op & 0x3FFF8000) >> 15;
+ op1 = op & 0x7FFF;
+ }
+ else
+ {
+ op1 = (op & 0x3FFF8000) >> 15;
+ op2 = op & 0x7FFF;
+ }
+ if (check_prologue(op1))
+ {
+ if (!check_prologue(op2))
+ {
+ /* if the previous opcode was really part of the prologue */
+ /* and not just a NOP, then we want to break after both instructions */
+ if (op1 != 0x5E00)
+ pc += 4;
+ break;
+ }
+ }
+ else
+ break;
+ }
+ pc += 4;
+ }
+ return pc;
+}
+
+/* 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
+ INIT_EXTRA_FRAME_INFO and INIT_FRAME_PC will be called for the new frame.
+*/
+
+CORE_ADDR
+d10v_frame_chain (frame)
+ struct frame_info *frame;
+{
+ struct frame_saved_regs fsr;
+
+ d10v_frame_find_saved_regs (frame, &fsr);
+
+ if (frame->return_pc == IMEM_START || inside_entry_file(frame->return_pc))
+ return (CORE_ADDR)0;
+
+ if (!fsr.regs[FP_REGNUM])
+ {
+ if (!fsr.regs[SP_REGNUM] || fsr.regs[SP_REGNUM] == STACK_START)
+ return (CORE_ADDR)0;
+
+ return fsr.regs[SP_REGNUM];
+ }
+
+ if (!read_memory_unsigned_integer(fsr.regs[FP_REGNUM], REGISTER_RAW_SIZE(FP_REGNUM)))
+ return (CORE_ADDR)0;
+
+ return D10V_MAKE_DADDR (read_memory_unsigned_integer (fsr.regs[FP_REGNUM], REGISTER_RAW_SIZE (FP_REGNUM)));
+}
+
+static int next_addr, uses_frame;
+
+static int
+prologue_find_regs (op, fsr, addr)
+ unsigned short op;
+ struct frame_saved_regs *fsr;
+ CORE_ADDR addr;
+{
+ int n;
+
+ /* st rn, @-sp */
+ if ((op & 0x7E1F) == 0x6C1F)
+ {
+ n = (op & 0x1E0) >> 5;
+ next_addr -= 2;
+ fsr->regs[n] = next_addr;
+ return 1;
+ }
+
+ /* st2w rn, @-sp */
+ else if ((op & 0x7E3F) == 0x6E1F)
+ {
+ n = (op & 0x1E0) >> 5;
+ next_addr -= 4;
+ fsr->regs[n] = next_addr;
+ fsr->regs[n+1] = next_addr+2;
+ return 1;
+ }
+
+ /* subi sp, n */
+ if ((op & 0x7FE1) == 0x01E1)
+ {
+ n = (op & 0x1E) >> 1;
+ if (n == 0)
+ n = 16;
+ next_addr -= n;
+ return 1;
+ }
+
+ /* mv r11, sp */
+ if (op == 0x417E)
+ {
+ uses_frame = 1;
+ return 1;
+ }
+
+ /* nop */
+ if (op == 0x5E00)
+ return 1;
+
+ /* st rn, @sp */
+ if ((op & 0x7E1F) == 0x681E)
+ {
+ n = (op & 0x1E0) >> 5;
+ fsr->regs[n] = next_addr;
+ return 1;
+ }
+
+ /* st2w rn, @sp */
+ if ((op & 0x7E3F) == 0x3A1E)
+ {
+ n = (op & 0x1E0) >> 5;
+ fsr->regs[n] = next_addr;
+ fsr->regs[n+1] = next_addr+2;
+ return 1;
+ }
+
+ return 0;
+}
+
+/* Put here the code to store, into a struct frame_saved_regs, the
+ addresses of the saved registers of frame described by FRAME_INFO.
+ This includes special registers such as pc and fp saved in special
+ ways in the stack frame. sp is even more special: the address we
+ return for it IS the sp for the next frame. */
+void
+d10v_frame_find_saved_regs (fi, fsr)
+ struct frame_info *fi;
+ struct frame_saved_regs *fsr;
+{
+ CORE_ADDR fp, pc;
+ unsigned long op;
+ unsigned short op1, op2;
+ int i;
+
+ fp = fi->frame;
+ memset (fsr, 0, sizeof (*fsr));
+ next_addr = 0;
+
+ pc = get_pc_function_start (fi->pc);
+
+ uses_frame = 0;
+ while (1)
+ {
+ op = (unsigned long)read_memory_integer (pc, 4);
+ if ((op & 0xC0000000) == 0xC0000000)
+ {
+ /* long instruction */
+ if ((op & 0x3FFF0000) == 0x01FF0000)
+ {
+ /* add3 sp,sp,n */
+ short n = op & 0xFFFF;
+ next_addr += n;
+ }
+ else if ((op & 0x3F0F0000) == 0x340F0000)
+ {
+ /* st rn, @(offset,sp) */
+ short offset = op & 0xFFFF;
+ short n = (op >> 20) & 0xF;
+ fsr->regs[n] = next_addr + offset;
+ }
+ else if ((op & 0x3F1F0000) == 0x350F0000)
+ {
+ /* st2w rn, @(offset,sp) */
+ short offset = op & 0xFFFF;
+ short n = (op >> 20) & 0xF;
+ fsr->regs[n] = next_addr + offset;
+ fsr->regs[n+1] = next_addr + offset + 2;
+ }
+ else
+ break;
+ }
+ else
+ {
+ /* short instructions */
+ if ((op & 0xC0000000) == 0x80000000)
+ {
+ op2 = (op & 0x3FFF8000) >> 15;
+ op1 = op & 0x7FFF;
+ }
+ else
+ {
+ op1 = (op & 0x3FFF8000) >> 15;
+ op2 = op & 0x7FFF;
+ }
+ if (!prologue_find_regs(op1,fsr,pc) || !prologue_find_regs(op2,fsr,pc))
+ break;
+ }
+ pc += 4;
+ }
+
+ fi->size = -next_addr;
+
+ if (!(fp & 0xffff))
+ fp = D10V_MAKE_DADDR (read_register(SP_REGNUM));
+
+ for (i=0; i<NUM_REGS-1; i++)
+ if (fsr->regs[i])
+ {
+ fsr->regs[i] = fp - (next_addr - fsr->regs[i]);
+ }
+
+ if (fsr->regs[LR_REGNUM])
+ {
+ CORE_ADDR return_pc = read_memory_unsigned_integer (fsr->regs[LR_REGNUM], REGISTER_RAW_SIZE (LR_REGNUM));
+ fi->return_pc = D10V_MAKE_IADDR (return_pc);
+ }
+ else
+ {
+ fi->return_pc = D10V_MAKE_IADDR (read_register(LR_REGNUM));
+ }
+
+ /* th SP is not normally (ever?) saved, but check anyway */
+ if (!fsr->regs[SP_REGNUM])
+ {
+ /* if the FP was saved, that means the current FP is valid, */
+ /* otherwise, it isn't being used, so we use the SP instead */
+ if (uses_frame)
+ fsr->regs[SP_REGNUM] = read_register(FP_REGNUM) + fi->size;
+ else
+ {
+ fsr->regs[SP_REGNUM] = fp + fi->size;
+ fi->frameless = 1;
+ fsr->regs[FP_REGNUM] = 0;
+ }
+ }
+}
+
+void
+d10v_init_extra_frame_info (fromleaf, fi)
+ int fromleaf;
+ struct frame_info *fi;
+{
+ fi->frameless = 0;
+ fi->size = 0;
+ fi->return_pc = 0;
+
+ /* The call dummy doesn't save any registers on the stack, so we can
+ return now. */
+ if (PC_IN_CALL_DUMMY (fi->pc, fi->frame, fi->frame))
+ {
+ return;
+ }
+ else
+ {
+ struct frame_saved_regs dummy;
+ d10v_frame_find_saved_regs (fi, &dummy);
+ }
+}
+
+static void
+show_regs (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ int a;
+ printf_filtered ("PC=%04x (0x%x) PSW=%04x RPT_S=%04x RPT_E=%04x RPT_C=%04x\n",
+ read_register (PC_REGNUM), D10V_MAKE_IADDR (read_register (PC_REGNUM)),
+ read_register (PSW_REGNUM),
+ read_register (24),
+ read_register (25),
+ read_register (23));
+ printf_filtered ("R0-R7 %04x %04x %04x %04x %04x %04x %04x %04x\n",
+ read_register (0),
+ read_register (1),
+ read_register (2),
+ read_register (3),
+ read_register (4),
+ read_register (5),
+ read_register (6),
+ read_register (7));
+ printf_filtered ("R8-R15 %04x %04x %04x %04x %04x %04x %04x %04x\n",
+ read_register (8),
+ read_register (9),
+ read_register (10),
+ read_register (11),
+ read_register (12),
+ read_register (13),
+ read_register (14),
+ read_register (15));
+ printf_filtered ("IMAP0 %04x IMAP1 %04x DMAP %04x\n",
+ read_register (IMAP0_REGNUM),
+ read_register (IMAP1_REGNUM),
+ read_register (DMAP_REGNUM));
+ printf_filtered ("A0-A1");
+ for (a = A0_REGNUM; a <= A0_REGNUM + 1; a++)
+ {
+ char num[MAX_REGISTER_RAW_SIZE];
+ int i;
+ printf_filtered (" ");
+ read_register_gen (a, (char *)&num);
+ for (i = 0; i < MAX_REGISTER_RAW_SIZE; i++)
+ {
+ printf_filtered ("%02x", (num[i] & 0xff));
+ }
+ }
+ printf_filtered ("\n");
+}
+
+CORE_ADDR
+d10v_read_pc (pid)
+ int pid;
+{
+ int save_pid;
+ CORE_ADDR pc;
+ CORE_ADDR retval;
+
+ save_pid = inferior_pid;
+ inferior_pid = pid;
+ pc = (int) read_register (PC_REGNUM);
+ inferior_pid = save_pid;
+ retval = D10V_MAKE_IADDR (pc);
+ return retval;
+}
+
+void
+d10v_write_pc (val, pid)
+ CORE_ADDR val;
+ int pid;
+{
+ int save_pid;
+
+ save_pid = inferior_pid;
+ inferior_pid = pid;
+ write_register (PC_REGNUM, D10V_CONVERT_IADDR_TO_RAW (val));
+ inferior_pid = save_pid;
+}
+
+CORE_ADDR
+d10v_read_sp ()
+{
+ return (D10V_MAKE_DADDR (read_register (SP_REGNUM)));
+}
+
+void
+d10v_write_sp (val)
+ CORE_ADDR val;
+{
+ write_register (SP_REGNUM, D10V_CONVERT_DADDR_TO_RAW (val));
+}
+
+void
+d10v_write_fp (val)
+ CORE_ADDR val;
+{
+ write_register (FP_REGNUM, D10V_CONVERT_DADDR_TO_RAW (val));
+}
+
+CORE_ADDR
+d10v_read_fp ()
+{
+ return (D10V_MAKE_DADDR (read_register(FP_REGNUM)));
+}
+
+/* Function: push_return_address (pc)
+ Set up the return address for the inferior function call.
+ Needed for targets where we don't actually execute a JSR/BSR instruction */
+
+CORE_ADDR
+d10v_push_return_address (pc, sp)
+ CORE_ADDR pc;
+ CORE_ADDR sp;
+{
+ write_register (LR_REGNUM, D10V_CONVERT_IADDR_TO_RAW (CALL_DUMMY_ADDRESS ()));
+ return sp;
+}
+
+
+CORE_ADDR
+d10v_push_arguments (nargs, args, sp, struct_return, struct_addr)
+ int nargs;
+ value_ptr *args;
+ CORE_ADDR sp;
+ int struct_return;
+ CORE_ADDR struct_addr;
+{
+ int i;
+ int regnum = ARG1_REGNUM;
+
+ /* Fill in registers and arg lists */
+ for (i = 0; i < nargs; i++)
+ {
+ value_ptr arg = args[i];
+ struct type *type = check_typedef (VALUE_TYPE (arg));
+ char *contents = VALUE_CONTENTS (arg);
+ int len = TYPE_LENGTH (type);
+ /* printf ("push: type=%d len=%d\n", type->code, len); */
+ if (TYPE_CODE (type) == TYPE_CODE_PTR)
+ {
+ /* pointers require special handling - first convert and
+ then store */
+ long val = extract_signed_integer (contents, len);
+ len = 2;
+ if (TYPE_TARGET_TYPE (type)
+ && (TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_FUNC))
+ {
+ /* function pointer */
+ val = D10V_CONVERT_IADDR_TO_RAW (val);
+ }
+ else if (D10V_IADDR_P (val))
+ {
+ /* also function pointer! */
+ val = D10V_CONVERT_DADDR_TO_RAW (val);
+ }
+ else
+ {
+ /* data pointer */
+ val &= 0xFFFF;
+ }
+ if (regnum <= ARGN_REGNUM)
+ write_register (regnum++, val & 0xffff);
+ else
+ {
+ char ptr[2];
+ sp -= 2;
+ store_address (ptr, val & 0xffff, 2);
+ write_memory (sp, ptr, 2);
+ }
+ }
+ else
+ {
+ int aligned_regnum = (regnum + 1) & ~1;
+ if (len <= 2 && regnum <= ARGN_REGNUM)
+ /* fits in a single register, do not align */
+ {
+ long val = extract_unsigned_integer (contents, len);
+ write_register (regnum++, val);
+ }
+ else if (len <= (ARGN_REGNUM - aligned_regnum + 1) * 2)
+ /* value fits in remaining registers, store keeping left
+ aligned */
+ {
+ int b;
+ regnum = aligned_regnum;
+ for (b = 0; b < (len & ~1); b += 2)
+ {
+ long val = extract_unsigned_integer (&contents[b], 2);
+ write_register (regnum++, val);
+ }
+ if (b < len)
+ {
+ long val = extract_unsigned_integer (&contents[b], 1);
+ write_register (regnum++, (val << 8));
+ }
+ }
+ else
+ {
+ /* arg goes straight on stack */
+ regnum = ARGN_REGNUM + 1;
+ sp = (sp - len) & ~1;
+ write_memory (sp, contents, len);
+ }
+ }
+ }
+ return sp;
+}
+
+
+/* Given a return value in `regbuf' with a type `valtype',
+ extract and copy its value into `valbuf'. */
+
+void
+d10v_extract_return_value (type, regbuf, valbuf)
+ struct type *type;
+ char regbuf[REGISTER_BYTES];
+ char *valbuf;
+{
+ int len;
+ /* printf("RET: TYPE=%d len=%d r%d=0x%x\n",type->code, TYPE_LENGTH (type), RET1_REGNUM - R0_REGNUM, (int) extract_unsigned_integer (regbuf + REGISTER_BYTE(RET1_REGNUM), REGISTER_RAW_SIZE (RET1_REGNUM))); */
+ if (TYPE_CODE (type) == TYPE_CODE_PTR
+ && TYPE_TARGET_TYPE (type)
+ && (TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_FUNC))
+ {
+ /* pointer to function */
+ int num;
+ short snum;
+ snum = extract_address (regbuf + REGISTER_BYTE (RET1_REGNUM), REGISTER_RAW_SIZE (RET1_REGNUM));
+ store_address ( valbuf, 4, D10V_MAKE_IADDR(snum));
+ }
+ else if (TYPE_CODE(type) == TYPE_CODE_PTR)
+ {
+ /* pointer to data */
+ int num;
+ short snum;
+ snum = extract_address (regbuf + REGISTER_BYTE (RET1_REGNUM), REGISTER_RAW_SIZE (RET1_REGNUM));
+ store_address ( valbuf, 4, D10V_MAKE_DADDR(snum));
+ }
+ else
+ {
+ len = TYPE_LENGTH (type);
+ if (len == 1)
+ {
+ unsigned short c = extract_unsigned_integer (regbuf + REGISTER_BYTE (RET1_REGNUM), REGISTER_RAW_SIZE (RET1_REGNUM));
+ store_unsigned_integer (valbuf, 1, c);
+ }
+ else if ((len & 1) == 0)
+ memcpy (valbuf, regbuf + REGISTER_BYTE (RET1_REGNUM), len);
+ else
+ {
+ /* For return values of odd size, the first byte is in the
+ least significant part of the first register. The
+ remaining bytes in remaining registers. Interestingly,
+ when such values are passed in, the last byte is in the
+ most significant byte of that same register - wierd. */
+ memcpy (valbuf, regbuf + REGISTER_BYTE (RET1_REGNUM) + 1, len);
+ }
+ }
+}
+
+/* The following code implements access to, and display of, the D10V's
+ instruction trace buffer. The buffer consists of 64K or more
+ 4-byte words of data, of which each words includes an 8-bit count,
+ an 8-bit segment number, and a 16-bit instruction address.
+
+ In theory, the trace buffer is continuously capturing instruction
+ data that the CPU presents on its "debug bus", but in practice, the
+ ROMified GDB stub only enables tracing when it continues or steps
+ the program, and stops tracing when the program stops; so it
+ actually works for GDB to read the buffer counter out of memory and
+ then read each trace word. The counter records where the tracing
+ stops, but there is no record of where it started, so we remember
+ the PC when we resumed and then search backwards in the trace
+ buffer for a word that includes that address. This is not perfect,
+ because you will miss trace data if the resumption PC is the target
+ of a branch. (The value of the buffer counter is semi-random, any
+ trace data from a previous program stop is gone.) */
+
+/* The address of the last word recorded in the trace buffer. */
+
+#define DBBC_ADDR (0xd80000)
+
+/* The base of the trace buffer, at least for the "Board_0". */
+
+#define TRACE_BUFFER_BASE (0xf40000)
+
+static void trace_command PARAMS ((char *, int));
+
+static void untrace_command PARAMS ((char *, int));
+
+static void trace_info PARAMS ((char *, int));
+
+static void tdisassemble_command PARAMS ((char *, int));
+
+static void display_trace PARAMS ((int, int));
+
+/* True when instruction traces are being collected. */
+
+static int tracing;
+
+/* Remembered PC. */
+
+static CORE_ADDR last_pc;
+
+/* True when trace output should be displayed whenever program stops. */
+
+static int trace_display;
+
+/* True when trace listing should include source lines. */
+
+static int default_trace_show_source = 1;
+
+struct trace_buffer {
+ int size;
+ short *counts;
+ CORE_ADDR *addrs;
+} trace_data;
+
+static void
+trace_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ /* Clear the host-side trace buffer, allocating space if needed. */
+ trace_data.size = 0;
+ if (trace_data.counts == NULL)
+ trace_data.counts = (short *) xmalloc (65536 * sizeof(short));
+ if (trace_data.addrs == NULL)
+ trace_data.addrs = (CORE_ADDR *) xmalloc (65536 * sizeof(CORE_ADDR));
+
+ tracing = 1;
+
+ printf_filtered ("Tracing is now on.\n");
+}
+
+static void
+untrace_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ tracing = 0;
+
+ printf_filtered ("Tracing is now off.\n");
+}
+
+static void
+trace_info (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ int i;
+
+ if (trace_data.size)
+ {
+ printf_filtered ("%d entries in trace buffer:\n", trace_data.size);
+
+ for (i = 0; i < trace_data.size; ++i)
+ {
+ printf_filtered ("%d: %d instruction%s at 0x%x\n",
+ i, trace_data.counts[i],
+ (trace_data.counts[i] == 1 ? "" : "s"),
+ trace_data.addrs[i]);
+ }
+ }
+ else
+ printf_filtered ("No entries in trace buffer.\n");
+
+ printf_filtered ("Tracing is currently %s.\n", (tracing ? "on" : "off"));
+}
+
+/* Print the instruction at address MEMADDR in debugged memory,
+ on STREAM. Returns length of the instruction, in bytes. */
+
+static int
+print_insn (memaddr, stream)
+ CORE_ADDR memaddr;
+ GDB_FILE *stream;
+{
+ /* If there's no disassembler, something is very wrong. */
+ if (tm_print_insn == NULL)
+ abort ();
+
+ if (TARGET_BYTE_ORDER == BIG_ENDIAN)
+ tm_print_insn_info.endian = BFD_ENDIAN_BIG;
+ else
+ tm_print_insn_info.endian = BFD_ENDIAN_LITTLE;
+ return (*tm_print_insn) (memaddr, &tm_print_insn_info);
+}
+
+void
+d10v_eva_prepare_to_trace ()
+{
+ if (!tracing)
+ return;
+
+ last_pc = read_register (PC_REGNUM);
+}
+
+/* Collect trace data from the target board and format it into a form
+ more useful for display. */
+
+void
+d10v_eva_get_trace_data ()
+{
+ int count, i, j, oldsize;
+ int trace_addr, trace_seg, trace_cnt, next_cnt;
+ unsigned int last_trace, trace_word, next_word;
+ unsigned int *tmpspace;
+
+ if (!tracing)
+ return;
+
+ tmpspace = xmalloc (65536 * sizeof(unsigned int));
+
+ last_trace = read_memory_unsigned_integer (DBBC_ADDR, 2) << 2;
+
+ /* Collect buffer contents from the target, stopping when we reach
+ the word recorded when execution resumed. */
+
+ count = 0;
+ while (last_trace > 0)
+ {
+ QUIT;
+ trace_word =
+ read_memory_unsigned_integer (TRACE_BUFFER_BASE + last_trace, 4);
+ trace_addr = trace_word & 0xffff;
+ last_trace -= 4;
+ /* Ignore an apparently nonsensical entry. */
+ if (trace_addr == 0xffd5)
+ continue;
+ tmpspace[count++] = trace_word;
+ if (trace_addr == last_pc)
+ break;
+ if (count > 65535)
+ break;
+ }
+
+ /* Move the data to the host-side trace buffer, adjusting counts to
+ include the last instruction executed and transforming the address
+ into something that GDB likes. */
+
+ for (i = 0; i < count; ++i)
+ {
+ trace_word = tmpspace[i];
+ next_word = ((i == 0) ? 0 : tmpspace[i - 1]);
+ trace_addr = trace_word & 0xffff;
+ next_cnt = (next_word >> 24) & 0xff;
+ j = trace_data.size + count - i - 1;
+ trace_data.addrs[j] = (trace_addr << 2) + 0x1000000;
+ trace_data.counts[j] = next_cnt + 1;
+ }
+
+ oldsize = trace_data.size;
+ trace_data.size += count;
+
+ free (tmpspace);
+
+ if (trace_display)
+ display_trace (oldsize, trace_data.size);
+}
+
+static void
+tdisassemble_command (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ int i, count;
+ CORE_ADDR low, high;
+ char *space_index;
+
+ if (!arg)
+ {
+ low = 0;
+ high = trace_data.size;
+ }
+ else if (!(space_index = (char *) strchr (arg, ' ')))
+ {
+ low = parse_and_eval_address (arg);
+ high = low + 5;
+ }
+ else
+ {
+ /* Two arguments. */
+ *space_index = '\0';
+ low = parse_and_eval_address (arg);
+ high = parse_and_eval_address (space_index + 1);
+ if (high < low)
+ high = low;
+ }
+
+ printf_filtered ("Dump of trace from %d to %d:\n", low, high);
+
+ display_trace (low, high);
+
+ printf_filtered ("End of trace dump.\n");
+ gdb_flush (gdb_stdout);
+}
+
+static void
+display_trace (low, high)
+ int low, high;
+{
+ int i, count, trace_show_source, first, suppress;
+ CORE_ADDR next_address;
+
+ trace_show_source = default_trace_show_source;
+ if (!have_full_symbols () && !have_partial_symbols())
+ {
+ trace_show_source = 0;
+ printf_filtered ("No symbol table is loaded. Use the \"file\" command.\n");
+ printf_filtered ("Trace will not display any source.\n");
+ }
+
+ first = 1;
+ suppress = 0;
+ for (i = low; i < high; ++i)
+ {
+ next_address = trace_data.addrs[i];
+ count = trace_data.counts[i];
+ while (count-- > 0)
+ {
+ QUIT;
+ if (trace_show_source)
+ {
+ struct symtab_and_line sal, sal_prev;
+
+ sal_prev = find_pc_line (next_address - 4, 0);
+ sal = find_pc_line (next_address, 0);
+
+ if (sal.symtab)
+ {
+ if (first || sal.line != sal_prev.line)
+ print_source_lines (sal.symtab, sal.line, sal.line + 1, 0);
+ suppress = 0;
+ }
+ else
+ {
+ if (!suppress)
+ /* FIXME-32x64--assumes sal.pc fits in long. */
+ printf_filtered ("No source file for address %s.\n",
+ local_hex_string((unsigned long) sal.pc));
+ suppress = 1;
+ }
+ }
+ first = 0;
+ print_address (next_address, gdb_stdout);
+ printf_filtered (":");
+ printf_filtered ("\t");
+ wrap_here (" ");
+ next_address = next_address + print_insn (next_address, gdb_stdout);
+ printf_filtered ("\n");
+ gdb_flush (gdb_stdout);
+ }
+ }
+}
+
+extern void (*target_resume_hook) PARAMS ((void));
+extern void (*target_wait_loop_hook) PARAMS ((void));
+
+void
+_initialize_d10v_tdep ()
+{
+ tm_print_insn = print_insn_d10v;
+
+ target_resume_hook = d10v_eva_prepare_to_trace;
+ target_wait_loop_hook = d10v_eva_get_trace_data;
+
+ add_com ("regs", class_vars, show_regs, "Print all registers");
+
+ add_com ("trace", class_support, trace_command,
+ "Enable tracing of instruction execution.");
+
+ add_com ("untrace", class_support, untrace_command,
+ "Disable tracing of instruction execution.");
+
+ add_com ("tdisassemble", class_vars, tdisassemble_command,
+ "Disassemble the trace buffer.\n\
+Two optional arguments specify a range of trace buffer entries\n\
+as reported by info trace (NOT addresses!).");
+
+ add_info ("trace", trace_info,
+ "Display info about the trace data buffer.");
+
+ add_show_from_set (add_set_cmd ("tracedisplay", no_class,
+ var_integer, (char *)&trace_display,
+ "Set automatic display of trace.\n", &setlist),
+ &showlist);
+ add_show_from_set (add_set_cmd ("tracesource", no_class,
+ var_integer, (char *)&default_trace_show_source,
+ "Set display of source code with trace.\n", &setlist),
+ &showlist);
+
+}
diff --git a/gdb/d30v-tdep.c b/gdb/d30v-tdep.c
new file mode 100644
index 00000000000..ec464633141
--- /dev/null
+++ b/gdb/d30v-tdep.c
@@ -0,0 +1,1396 @@
+/* Target-dependent code for Mitsubishi D30V, for GDB.
+ Copyright (C) 1996, 1997 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Contributed by Martin Hunt, hunt@cygnus.com */
+
+#include "defs.h"
+#include "frame.h"
+#include "obstack.h"
+#include "symtab.h"
+#include "gdbtypes.h"
+#include "gdbcmd.h"
+#include "gdbcore.h"
+#include "gdb_string.h"
+#include "value.h"
+#include "inferior.h"
+#include "dis-asm.h"
+#include "symfile.h"
+#include "objfiles.h"
+
+void d30v_frame_find_saved_regs PARAMS ((struct frame_info *fi,
+ struct frame_saved_regs *fsr));
+void d30v_frame_find_saved_regs_offsets PARAMS ((struct frame_info *fi,
+ struct frame_saved_regs *fsr));
+static void d30v_pop_dummy_frame PARAMS ((struct frame_info *fi));
+static void d30v_print_flags PARAMS ((void));
+static void print_flags_command PARAMS ((char *, int));
+
+/* the following defines assume:
+ fp is r61, lr is r62, sp is r63, and ?? is r22
+ if that changes, they will need to be updated */
+
+#define OP_MASK_ALL_BUT_RA 0x0ffc0fff /* throw away Ra, keep the rest */
+
+#define OP_STW_SPM 0x054c0fc0 /* stw Ra, @(sp-) */
+#define OP_STW_SP_R0 0x05400fc0 /* stw Ra, @(sp,r0) */
+#define OP_STW_SP_IMM0 0x05480fc0 /* st Ra, @(sp, 0x0) */
+#define OP_STW_R22P_R0 0x05440580 /* stw Ra, @(r22+,r0) */
+
+#define OP_ST2W_SPM 0x056c0fc0 /* st2w Ra, @(sp-) */
+#define OP_ST2W_SP_R0 0x05600fc0 /* st2w Ra, @(sp, r0) */
+#define OP_ST2W_SP_IMM0 0x05680fc0 /* st2w Ra, @(sp, 0x0) */
+#define OP_ST2W_R22P_R0 0x05640580 /* st2w Ra, @(r22+, r0) */
+
+#define OP_MASK_OPCODE 0x0ffc0000 /* just the opcode, ign operands */
+#define OP_NOP 0x00f00000 /* nop */
+
+#define OP_MASK_ALL_BUT_IMM 0x0fffffc0 /* throw away imm, keep the rest */
+#define OP_SUB_SP_IMM 0x082bffc0 /* sub sp,sp,imm */
+#define OP_ADD_SP_IMM 0x080bffc0 /* add sp,sp,imm */
+#define OP_ADD_R22_SP_IMM 0x08096fc0 /* add r22,sp,imm */
+#define OP_STW_FP_SP_IMM 0x054bdfc0 /* stw fp,@(sp,imm) */
+#define OP_OR_SP_R0_IMM 0x03abf000 /* or sp,r0,imm */
+
+/* no mask */
+#define OP_OR_FP_R0_SP 0x03a3d03f /* or fp,r0,sp */
+#define OP_OR_FP_SP_R0 0x03a3dfc0 /* or fp,sp,r0 */
+#define OP_OR_FP_IMM0_SP 0x03abd03f /* or fp,0x0,sp */
+#define OP_STW_FP_R22P_R0 0x0547d580 /* stw fp,@(r22+,r0) */
+#define OP_STW_LR_R22P_R0 0x0547e580 /* stw lr,@(r22+,r0) */
+
+#define OP_MASK_OP_AND_RB 0x0ff80fc0 /* keep op and rb,throw away rest */
+#define OP_STW_SP_IMM 0x05480fc0 /* stw Ra,@(sp,imm) */
+#define OP_ST2W_SP_IMM 0x05680fc0 /* st2w Ra,@(sp,imm) */
+#define OP_STW_FP_IMM 0x05480f40 /* stw Ra,@(fp,imm) */
+#define OP_STW_FP_R0 0x05400f40 /* stw Ra,@(fp,r0) */
+
+#define OP_MASK_FM_BIT 0x80000000
+#define OP_MASK_CC_BITS 0x70000000
+#define OP_MASK_SUB_INST 0x0fffffff
+
+#define EXTRACT_RA(op) (((op) >> 12) & 0x3f)
+#define EXTRACT_RB(op) (((op) >> 6) & 0x3f)
+#define EXTRACT_RC(op) (((op) & 0x3f)
+#define EXTRACT_UIMM6(op) ((op) & 0x3f)
+#define EXTRACT_IMM6(op) ((((int)EXTRACT_UIMM6(op)) << 26) >> 26)
+#define EXTRACT_IMM26(op) ((((op)&0x0ff00000) >> 2) | ((op)&0x0003ffff))
+#define EXTRACT_IMM32(opl, opr) ((EXTRACT_UIMM6(opl) << 26)|EXTRACT_IMM26(opr))
+
+
+int
+d30v_frame_chain_valid (chain, fi)
+ CORE_ADDR chain;
+ struct frame_info *fi; /* not used here */
+{
+#if 0
+ return ((chain) != 0 && (fi) != 0 && (fi)->return_pc != 0);
+#else
+ return ((chain) != 0 && (fi) != 0 && (fi)->frame <= chain);
+#endif
+}
+
+/* Discard from the stack the innermost frame, restoring all saved
+ registers. */
+
+void
+d30v_pop_frame ()
+{
+ struct frame_info *frame = get_current_frame ();
+ CORE_ADDR fp;
+ int regnum;
+ struct frame_saved_regs fsr;
+ char raw_buffer[8];
+
+ fp = FRAME_FP (frame);
+ if (frame->dummy)
+ {
+ d30v_pop_dummy_frame(frame);
+ return;
+ }
+
+ /* fill out fsr with the address of where each */
+ /* register was stored in the frame */
+ get_frame_saved_regs (frame, &fsr);
+
+ /* now update the current registers with the old values */
+ for (regnum = A0_REGNUM; regnum < A0_REGNUM+2 ; regnum++)
+ {
+ if (fsr.regs[regnum])
+ {
+ read_memory (fsr.regs[regnum], raw_buffer, 8);
+ write_register_bytes (REGISTER_BYTE (regnum), raw_buffer, 8);
+ }
+ }
+ for (regnum = 0; regnum < SP_REGNUM; regnum++)
+ {
+ if (fsr.regs[regnum])
+ {
+ write_register (regnum, read_memory_unsigned_integer (fsr.regs[regnum], 4));
+ }
+ }
+ if (fsr.regs[PSW_REGNUM])
+ {
+ write_register (PSW_REGNUM, read_memory_unsigned_integer (fsr.regs[PSW_REGNUM], 4));
+ }
+
+ write_register (PC_REGNUM, read_register(LR_REGNUM));
+ write_register (SP_REGNUM, fp + frame->size);
+ target_store_registers (-1);
+ flush_cached_frames ();
+}
+
+static int
+check_prologue (op)
+ unsigned long op;
+{
+ /* add sp,sp,imm -- observed */
+ if ((op & OP_MASK_ALL_BUT_IMM) == OP_ADD_SP_IMM)
+ return 1;
+
+ /* add r22,sp,imm -- observed */
+ if ((op & OP_MASK_ALL_BUT_IMM) == OP_ADD_R22_SP_IMM)
+ return 1;
+
+ /* or fp,r0,sp -- observed */
+ if (op == OP_OR_FP_R0_SP)
+ return 1;
+
+ /* nop */
+ if ((op & OP_MASK_OPCODE) == OP_NOP)
+ return 1;
+
+ /* stw Ra,@(sp,r0) */
+ if ((op & OP_MASK_ALL_BUT_RA) == OP_STW_SP_R0)
+ return 1;
+
+ /* stw Ra,@(sp,0x0) */
+ if ((op & OP_MASK_ALL_BUT_RA) == OP_STW_SP_IMM0)
+ return 1;
+
+ /* st2w Ra,@(sp,r0) */
+ if ((op & OP_MASK_ALL_BUT_RA) == OP_ST2W_SP_R0)
+ return 1;
+
+ /* st2w Ra,@(sp,0x0) */
+ if ((op & OP_MASK_ALL_BUT_RA) == OP_ST2W_SP_IMM0)
+ return 1;
+
+ /* stw fp, @(r22+,r0) -- observed */
+ if (op == OP_STW_FP_R22P_R0)
+ return 1;
+
+ /* stw r62, @(r22+,r0) -- observed */
+ if (op == OP_STW_LR_R22P_R0)
+ return 1;
+
+ /* stw Ra, @(fp,r0) -- observed */
+ if ((op & OP_MASK_ALL_BUT_RA) == OP_STW_FP_R0)
+ return 1; /* first arg */
+
+ /* stw Ra, @(fp,imm) -- observed */
+ if ((op & OP_MASK_OP_AND_RB) == OP_STW_FP_IMM)
+ return 1; /* second and subsequent args */
+
+ /* stw fp,@(sp,imm) -- observed */
+ if ((op & OP_MASK_ALL_BUT_IMM) == OP_STW_FP_SP_IMM)
+ return 1;
+
+ /* st2w Ra,@(r22+,r0) */
+ if ((op & OP_MASK_ALL_BUT_RA) == OP_ST2W_R22P_R0)
+ return 1;
+
+ /* stw Ra, @(sp-) */
+ if ((op & OP_MASK_ALL_BUT_RA) == OP_STW_SPM)
+ return 1;
+
+ /* st2w Ra, @(sp-) */
+ if ((op & OP_MASK_ALL_BUT_RA) == OP_ST2W_SPM)
+ return 1;
+
+ /* sub.? sp,sp,imm */
+ if ((op & OP_MASK_ALL_BUT_IMM) == OP_SUB_SP_IMM)
+ return 1;
+
+ return 0;
+}
+
+CORE_ADDR
+d30v_skip_prologue (pc)
+ CORE_ADDR pc;
+{
+ unsigned long op[2];
+ unsigned long opl, opr; /* left / right sub operations */
+ unsigned long fm0, fm1; /* left / right mode bits */
+ unsigned long cc0, cc1;
+ unsigned long op1, op2;
+ CORE_ADDR func_addr, func_end;
+ struct symtab_and_line sal;
+
+ /* If we have line debugging information, then the end of the */
+ /* prologue should the first assembly instruction of the first source line */
+ if (find_pc_partial_function (pc, NULL, &func_addr, &func_end))
+ {
+ sal = find_pc_line (func_addr, 0);
+ if ( sal.end && sal.end < func_end)
+ return sal.end;
+ }
+
+ if (target_read_memory (pc, (char *)&op[0], 8))
+ return pc; /* Can't access it -- assume no prologue. */
+
+ while (1)
+ {
+ opl = (unsigned long)read_memory_integer (pc, 4);
+ opr = (unsigned long)read_memory_integer (pc+4, 4);
+
+ fm0 = (opl & OP_MASK_FM_BIT);
+ fm1 = (opr & OP_MASK_FM_BIT);
+
+ cc0 = (opl & OP_MASK_CC_BITS);
+ cc1 = (opr & OP_MASK_CC_BITS);
+
+ opl = (opl & OP_MASK_SUB_INST);
+ opr = (opr & OP_MASK_SUB_INST);
+
+ if (fm0 && fm1)
+ {
+ /* long instruction (opl contains the opcode) */
+ if (((opl & OP_MASK_ALL_BUT_IMM) != OP_ADD_SP_IMM) && /* add sp,sp,imm */
+ ((opl & OP_MASK_ALL_BUT_IMM) != OP_ADD_R22_SP_IMM) && /* add r22,sp,imm */
+ ((opl & OP_MASK_OP_AND_RB) != OP_STW_SP_IMM) && /* stw Ra, @(sp,imm) */
+ ((opl & OP_MASK_OP_AND_RB) != OP_ST2W_SP_IMM)) /* st2w Ra, @(sp,imm) */
+ break;
+ }
+ else
+ {
+ /* short instructions */
+ if (fm0 && !fm1)
+ {
+ op1 = opr;
+ op2 = opl;
+ }
+ else
+ {
+ op1 = opl;
+ op2 = opr;
+ }
+ if (check_prologue(op1))
+ {
+ if (!check_prologue(op2))
+ {
+ /* if the previous opcode was really part of the prologue */
+ /* and not just a NOP, then we want to break after both instructions */
+ if ((op1 & OP_MASK_OPCODE) != OP_NOP)
+ pc += 8;
+ break;
+ }
+ }
+ else
+ break;
+ }
+ pc += 8;
+ }
+ return pc;
+}
+
+static int end_of_stack;
+
+/* 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
+ INIT_EXTRA_FRAME_INFO and INIT_FRAME_PC will be called for the new frame.
+*/
+
+CORE_ADDR
+d30v_frame_chain (frame)
+ struct frame_info *frame;
+{
+ struct frame_saved_regs fsr;
+
+ d30v_frame_find_saved_regs (frame, &fsr);
+
+ if (end_of_stack)
+ return (CORE_ADDR)0;
+
+ if (frame->return_pc == IMEM_START)
+ return (CORE_ADDR)0;
+
+ if (!fsr.regs[FP_REGNUM])
+ {
+ if (!fsr.regs[SP_REGNUM] || fsr.regs[SP_REGNUM] == STACK_START)
+ return (CORE_ADDR)0;
+
+ return fsr.regs[SP_REGNUM];
+ }
+
+ if (!read_memory_unsigned_integer(fsr.regs[FP_REGNUM],4))
+ return (CORE_ADDR)0;
+
+ return read_memory_unsigned_integer(fsr.regs[FP_REGNUM],4);
+}
+
+static int next_addr, uses_frame;
+static int frame_size;
+
+static int
+prologue_find_regs (op, fsr, addr)
+ unsigned long op;
+ struct frame_saved_regs *fsr;
+ CORE_ADDR addr;
+{
+ int n;
+ int offset;
+
+ /* add sp,sp,imm -- observed */
+ if ((op & OP_MASK_ALL_BUT_IMM) == OP_ADD_SP_IMM)
+ {
+ offset = EXTRACT_IMM6(op);
+ /*next_addr += offset;*/
+ frame_size += -offset;
+ return 1;
+ }
+
+ /* add r22,sp,imm -- observed */
+ if ((op & OP_MASK_ALL_BUT_IMM) == OP_ADD_R22_SP_IMM)
+ {
+ offset = EXTRACT_IMM6(op);
+ next_addr = (offset - frame_size);
+ return 1;
+ }
+
+ /* stw Ra, @(fp, offset) -- observed */
+ if ((op & OP_MASK_OP_AND_RB) == OP_STW_FP_IMM)
+ {
+ n = EXTRACT_RA(op);
+ offset = EXTRACT_IMM6(op);
+ fsr->regs[n] = (offset - frame_size);
+ return 1;
+ }
+
+ /* stw Ra, @(fp, r0) -- observed */
+ if ((op & OP_MASK_ALL_BUT_RA) == OP_STW_FP_R0)
+ {
+ n = EXTRACT_RA(op);
+ fsr->regs[n] = (- frame_size);
+ return 1;
+ }
+
+ /* or fp,0,sp -- observed */
+ if ((op == OP_OR_FP_R0_SP) ||
+ (op == OP_OR_FP_SP_R0) ||
+ (op == OP_OR_FP_IMM0_SP))
+ {
+ uses_frame = 1;
+ return 1;
+ }
+
+ /* nop */
+ if ((op & OP_MASK_OPCODE) == OP_NOP)
+ return 1;
+
+ /* stw Ra,@(r22+,r0) -- observed */
+ if ((op & OP_MASK_ALL_BUT_RA) == OP_STW_R22P_R0)
+ {
+ n = EXTRACT_RA(op);
+ fsr->regs[n] = next_addr;
+ next_addr += 4;
+ return 1;
+ }
+#if 0 /* subsumed in pattern above */
+ /* stw fp,@(r22+,r0) -- observed */
+ if (op == OP_STW_FP_R22P_R0)
+ {
+ fsr->regs[FP_REGNUM] = next_addr; /* XXX */
+ next_addr += 4;
+ return 1;
+ }
+
+ /* stw r62,@(r22+,r0) -- observed */
+ if (op == OP_STW_LR_R22P_R0)
+ {
+ fsr->regs[LR_REGNUM] = next_addr;
+ next_addr += 4;
+ return 1;
+ }
+#endif
+ /* st2w Ra,@(r22+,r0) -- observed */
+ if ((op & OP_MASK_ALL_BUT_RA) == OP_ST2W_R22P_R0)
+ {
+ n = EXTRACT_RA(op);
+ fsr->regs[n] = next_addr;
+ fsr->regs[n+1] = next_addr + 4;
+ next_addr += 8;
+ return 1;
+ }
+
+ /* stw rn, @(sp-) */
+ if ((op & OP_MASK_ALL_BUT_RA) == OP_STW_SPM)
+ {
+ n = EXTRACT_RA(op);
+ fsr->regs[n] = next_addr;
+ next_addr -= 4;
+ return 1;
+ }
+
+ /* st2w Ra, @(sp-) */
+ else if ((op & OP_MASK_ALL_BUT_RA) == OP_ST2W_SPM)
+ {
+ n = EXTRACT_RA(op);
+ fsr->regs[n] = next_addr;
+ fsr->regs[n+1] = next_addr+4;
+ next_addr -= 8;
+ return 1;
+ }
+
+ /* sub sp,sp,imm */
+ if ((op & OP_MASK_ALL_BUT_IMM) == OP_SUB_SP_IMM)
+ {
+ offset = EXTRACT_IMM6(op);
+ frame_size += -offset;
+ return 1;
+ }
+
+ /* st rn, @(sp,0) -- observed */
+ if (((op & OP_MASK_ALL_BUT_RA) == OP_STW_SP_R0) ||
+ ((op & OP_MASK_ALL_BUT_RA) == OP_STW_SP_IMM0))
+ {
+ n = EXTRACT_RA(op);
+ fsr->regs[n] = (- frame_size);
+ return 1;
+ }
+
+ /* st2w rn, @(sp,0) */
+ if (((op & OP_MASK_ALL_BUT_RA) == OP_ST2W_SP_R0) ||
+ ((op & OP_MASK_ALL_BUT_RA) == OP_ST2W_SP_IMM0))
+ {
+ n = EXTRACT_RA(op);
+ fsr->regs[n] = (- frame_size);
+ fsr->regs[n+1] = (- frame_size) + 4;
+ return 1;
+ }
+
+ /* stw fp,@(sp,imm) -- observed */
+ if ((op & OP_MASK_ALL_BUT_IMM) == OP_STW_FP_SP_IMM)
+ {
+ offset = EXTRACT_IMM6(op);
+ fsr->regs[FP_REGNUM] = (offset - frame_size);
+ return 1;
+ }
+ return 0;
+}
+
+/* Put here the code to store, into a struct frame_saved_regs, the
+ addresses of the saved registers of frame described by FRAME_INFO.
+ This includes special registers such as pc and fp saved in special
+ ways in the stack frame. sp is even more special: the address we
+ return for it IS the sp for the next frame. */
+void
+d30v_frame_find_saved_regs (fi, fsr)
+ struct frame_info *fi;
+ struct frame_saved_regs *fsr;
+{
+ CORE_ADDR fp, pc;
+ unsigned long opl, opr;
+ unsigned long op1, op2;
+ unsigned long fm0, fm1;
+ int i;
+
+ fp = fi->frame;
+ memset (fsr, 0, sizeof (*fsr));
+ next_addr = 0;
+ frame_size = 0;
+ end_of_stack = 0;
+
+ uses_frame = 0;
+
+ d30v_frame_find_saved_regs_offsets (fi, fsr);
+
+ fi->size = frame_size;
+
+ if (!fp)
+ fp = read_register(SP_REGNUM);
+
+ for (i=0; i<NUM_REGS-1; i++)
+ if (fsr->regs[i])
+ {
+ fsr->regs[i] = fsr->regs[i] + fp + frame_size;
+ }
+
+ if (fsr->regs[LR_REGNUM])
+ fi->return_pc = read_memory_unsigned_integer(fsr->regs[LR_REGNUM],4);
+ else
+ fi->return_pc = read_register(LR_REGNUM);
+
+ /* the SP is not normally (ever?) saved, but check anyway */
+ if (!fsr->regs[SP_REGNUM])
+ {
+ /* if the FP was saved, that means the current FP is valid, */
+ /* otherwise, it isn't being used, so we use the SP instead */
+ if (uses_frame)
+ fsr->regs[SP_REGNUM] = read_register(FP_REGNUM) + fi->size;
+ else
+ {
+ fsr->regs[SP_REGNUM] = fp + fi->size;
+ fi->frameless = 1;
+ fsr->regs[FP_REGNUM] = 0;
+ }
+ }
+}
+
+void
+d30v_frame_find_saved_regs_offsets (fi, fsr)
+ struct frame_info *fi;
+ struct frame_saved_regs *fsr;
+{
+ CORE_ADDR fp, pc;
+ unsigned long opl, opr;
+ unsigned long op1, op2;
+ unsigned long fm0, fm1;
+ int i;
+
+ fp = fi->frame;
+ memset (fsr, 0, sizeof (*fsr));
+ next_addr = 0;
+ frame_size = 0;
+ end_of_stack = 0;
+
+ pc = get_pc_function_start (fi->pc);
+
+ uses_frame = 0;
+ while (pc < fi->pc)
+ {
+ opl = (unsigned long)read_memory_integer (pc, 4);
+ opr = (unsigned long)read_memory_integer (pc+4, 4);
+
+ fm0 = (opl & OP_MASK_FM_BIT);
+ fm1 = (opr & OP_MASK_FM_BIT);
+
+ opl = (opl & OP_MASK_SUB_INST);
+ opr = (opr & OP_MASK_SUB_INST);
+
+ if (fm0 && fm1)
+ {
+ /* long instruction */
+ if ((opl & OP_MASK_ALL_BUT_IMM) == OP_ADD_SP_IMM)
+ {
+ /* add sp,sp,n */
+ long offset = EXTRACT_IMM32(opl, opr);
+ frame_size += -offset;
+ }
+ else if ((opl & OP_MASK_ALL_BUT_IMM) == OP_ADD_R22_SP_IMM)
+ {
+ /* add r22,sp,offset */
+ long offset = EXTRACT_IMM32(opl,opr);
+ next_addr = (offset - frame_size);
+ }
+ else if ((opl & OP_MASK_OP_AND_RB) == OP_STW_SP_IMM)
+ {
+ /* st Ra, @(sp,imm) */
+ long offset = EXTRACT_IMM32(opl, opr);
+ short n = EXTRACT_RA(opl);
+ fsr->regs[n] = (offset - frame_size);
+ }
+ else if ((opl & OP_MASK_OP_AND_RB) == OP_ST2W_SP_IMM)
+ {
+ /* st2w Ra, @(sp,offset) */
+ long offset = EXTRACT_IMM32(opl, opr);
+ short n = EXTRACT_RA(opl);
+ fsr->regs[n] = (offset - frame_size);
+ fsr->regs[n+1] = (offset - frame_size) + 4;
+ }
+ else if ((opl & OP_MASK_ALL_BUT_IMM) == OP_OR_SP_R0_IMM)
+ {
+ end_of_stack = 1;
+ }
+ else
+ break;
+ }
+ else
+ {
+ /* short instructions */
+ if (fm0 && !fm1)
+ {
+ op2 = opl;
+ op1 = opr;
+ }
+ else
+ {
+ op1 = opl;
+ op2 = opr;
+ }
+ if (!prologue_find_regs(op1,fsr,pc) || !prologue_find_regs(op2,fsr,pc))
+ break;
+ }
+ pc += 8;
+ }
+
+#if 0
+ fi->size = frame_size;
+
+ if (!fp)
+ fp = read_register(SP_REGNUM);
+
+ for (i=0; i<NUM_REGS-1; i++)
+ if (fsr->regs[i])
+ {
+ fsr->regs[i] = fsr->regs[i] + fp + frame_size;
+ }
+
+ if (fsr->regs[LR_REGNUM])
+ fi->return_pc = read_memory_unsigned_integer(fsr->regs[LR_REGNUM],4);
+ else
+ fi->return_pc = read_register(LR_REGNUM);
+
+ /* the SP is not normally (ever?) saved, but check anyway */
+ if (!fsr->regs[SP_REGNUM])
+ {
+ /* if the FP was saved, that means the current FP is valid, */
+ /* otherwise, it isn't being used, so we use the SP instead */
+ if (uses_frame)
+ fsr->regs[SP_REGNUM] = read_register(FP_REGNUM) + fi->size;
+ else
+ {
+ fsr->regs[SP_REGNUM] = fp + fi->size;
+ fi->frameless = 1;
+ fsr->regs[FP_REGNUM] = 0;
+ }
+ }
+#endif
+}
+
+void
+d30v_init_extra_frame_info (fromleaf, fi)
+ int fromleaf;
+ struct frame_info *fi;
+{
+ struct frame_saved_regs dummy;
+
+ if (fi->next && (fi->pc == 0))
+ fi->pc = fi->next->return_pc;
+
+ d30v_frame_find_saved_regs_offsets (fi, &dummy);
+
+ if (uses_frame == 0)
+ fi->frameless = 1;
+ else
+ fi->frameless = 0;
+
+ if ((fi->next == 0) && (uses_frame == 0))
+ /* innermost frame and it's "frameless",
+ so the fi->frame field is wrong, fix it! */
+ fi->frame = read_sp ();
+
+ if (dummy.regs[LR_REGNUM])
+ {
+ /* it was saved, grab it! */
+ dummy.regs[LR_REGNUM] += (fi->frame + frame_size);
+ fi->return_pc = read_memory_unsigned_integer(dummy.regs[LR_REGNUM],4);
+ }
+ else
+ fi->return_pc = read_register(LR_REGNUM);
+}
+
+void
+d30v_init_frame_pc (fromleaf, prev)
+ int fromleaf;
+ struct frame_info *prev;
+{
+ /* default value, put here so we can breakpoint on it and
+ see if the default value is really the right thing to use */
+ prev->pc = (fromleaf ? SAVED_PC_AFTER_CALL (prev->next) : \
+ prev->next ? FRAME_SAVED_PC (prev->next) : read_pc ());
+}
+
+static void d30v_print_register PARAMS ((int regnum, int tabular));
+
+static void
+d30v_print_register (regnum, tabular)
+ int regnum;
+ int tabular;
+{
+ if (regnum < A0_REGNUM)
+ {
+ if (tabular)
+ printf_filtered ("%08x", read_register (regnum));
+ else
+ printf_filtered ("0x%x %d", read_register (regnum),
+ read_register (regnum));
+ }
+ else
+ {
+ char regbuf[MAX_REGISTER_RAW_SIZE];
+
+ read_relative_register_raw_bytes (regnum, regbuf);
+
+ val_print (REGISTER_VIRTUAL_TYPE (regnum), regbuf, 0, 0,
+ gdb_stdout, 'x', 1, 0, Val_pretty_default);
+
+ if (!tabular)
+ {
+ printf_filtered (" ");
+ val_print (REGISTER_VIRTUAL_TYPE (regnum), regbuf, 0, 0,
+ gdb_stdout, 'd', 1, 0, Val_pretty_default);
+ }
+ }
+}
+
+static void
+d30v_print_flags ()
+{
+ long psw = read_register (PSW_REGNUM);
+ printf_filtered ("flags #1");
+ printf_filtered (" (sm) %d", (psw & PSW_SM) != 0);
+ printf_filtered (" (ea) %d", (psw & PSW_EA) != 0);
+ printf_filtered (" (db) %d", (psw & PSW_DB) != 0);
+ printf_filtered (" (ds) %d", (psw & PSW_DS) != 0);
+ printf_filtered (" (ie) %d", (psw & PSW_IE) != 0);
+ printf_filtered (" (rp) %d", (psw & PSW_RP) != 0);
+ printf_filtered (" (md) %d\n", (psw & PSW_MD) != 0);
+
+ printf_filtered ("flags #2");
+ printf_filtered (" (f0) %d", (psw & PSW_F0) != 0);
+ printf_filtered (" (f1) %d", (psw & PSW_F1) != 0);
+ printf_filtered (" (f2) %d", (psw & PSW_F2) != 0);
+ printf_filtered (" (f3) %d", (psw & PSW_F3) != 0);
+ printf_filtered (" (s) %d", (psw & PSW_S) != 0);
+ printf_filtered (" (v) %d", (psw & PSW_V) != 0);
+ printf_filtered (" (va) %d", (psw & PSW_VA) != 0);
+ printf_filtered (" (c) %d\n", (psw & PSW_C) != 0);
+}
+
+static void
+print_flags_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ d30v_print_flags ();
+}
+
+void
+d30v_do_registers_info (regnum, fpregs)
+ int regnum;
+ int fpregs;
+{
+ long long num1, num2;
+ long psw;
+
+ if (regnum != -1)
+ {
+ if (REGISTER_NAME (0) == NULL || REGISTER_NAME (0)[0] == '\000')
+ return;
+
+ printf_filtered ("%s ", REGISTER_NAME (regnum));
+ d30v_print_register (regnum, 0);
+
+ printf_filtered ("\n");
+ return;
+ }
+
+ /* Have to print all the registers. Format them nicely. */
+
+ printf_filtered ("PC=");
+ print_address (read_pc (), gdb_stdout);
+
+ printf_filtered (" PSW=");
+ d30v_print_register (PSW_REGNUM, 1);
+
+ printf_filtered (" BPC=");
+ print_address (read_register (BPC_REGNUM), gdb_stdout);
+
+ printf_filtered (" BPSW=");
+ d30v_print_register (BPSW_REGNUM, 1);
+ printf_filtered ("\n");
+
+ printf_filtered ("DPC=");
+ print_address (read_register (DPC_REGNUM), gdb_stdout);
+
+ printf_filtered (" DPSW=");
+ d30v_print_register (DPSW_REGNUM, 1);
+
+ printf_filtered (" IBA=");
+ print_address (read_register (IBA_REGNUM), gdb_stdout);
+ printf_filtered ("\n");
+
+ printf_filtered ("RPT_C=");
+ d30v_print_register (RPT_C_REGNUM, 1);
+
+ printf_filtered (" RPT_S=");
+ print_address (read_register (RPT_S_REGNUM), gdb_stdout);
+
+ printf_filtered (" RPT_E=");
+ print_address (read_register (RPT_E_REGNUM), gdb_stdout);
+ printf_filtered ("\n");
+
+ printf_filtered ("MOD_S=");
+ print_address (read_register (MOD_S_REGNUM), gdb_stdout);
+
+ printf_filtered (" MOD_E=");
+ print_address (read_register (MOD_E_REGNUM), gdb_stdout);
+ printf_filtered ("\n");
+
+ printf_filtered ("EIT_VB=");
+ print_address (read_register (EIT_VB_REGNUM), gdb_stdout);
+
+ printf_filtered (" INT_S=");
+ d30v_print_register (INT_S_REGNUM, 1);
+
+ printf_filtered (" INT_M=");
+ d30v_print_register (INT_M_REGNUM, 1);
+ printf_filtered ("\n");
+
+ d30v_print_flags ();
+ for (regnum = 0; regnum <= 63;)
+ {
+ int i;
+
+ printf_filtered ("R%d-R%d ", regnum, regnum + 7);
+ if (regnum < 10)
+ printf_filtered (" ");
+ if (regnum + 7 < 10)
+ printf_filtered (" ");
+
+ for (i = 0; i < 8; i++)
+ {
+ printf_filtered (" ");
+ d30v_print_register (regnum++, 1);
+ }
+
+ printf_filtered ("\n");
+ }
+
+ printf_filtered ("A0-A1 ");
+
+ d30v_print_register (A0_REGNUM, 1);
+ printf_filtered (" ");
+ d30v_print_register (A1_REGNUM, 1);
+ printf_filtered ("\n");
+}
+
+CORE_ADDR
+d30v_fix_call_dummy (dummyname, start_sp, fun, nargs, args, type, gcc_p)
+ char *dummyname;
+ CORE_ADDR start_sp;
+ CORE_ADDR fun;
+ int nargs;
+ value_ptr *args;
+ struct type *type;
+ int gcc_p;
+{
+ int regnum;
+ CORE_ADDR sp;
+ char buffer[MAX_REGISTER_RAW_SIZE];
+ struct frame_info *frame = get_current_frame ();
+ frame->dummy = start_sp;
+ /*start_sp |= DMEM_START;*/
+
+ sp = start_sp;
+ for (regnum = 0; regnum < NUM_REGS; regnum++)
+ {
+ sp -= REGISTER_RAW_SIZE(regnum);
+ store_address (buffer, REGISTER_RAW_SIZE(regnum), read_register(regnum));
+ write_memory (sp, buffer, REGISTER_RAW_SIZE(regnum));
+ }
+ write_register (SP_REGNUM, (LONGEST)sp);
+ /* now we need to load LR with the return address */
+ write_register (LR_REGNUM, (LONGEST)d30v_call_dummy_address());
+ return sp;
+}
+
+static void
+d30v_pop_dummy_frame (fi)
+ struct frame_info *fi;
+{
+ CORE_ADDR sp = fi->dummy;
+ int regnum;
+
+ for (regnum = 0; regnum < NUM_REGS; regnum++)
+ {
+ sp -= REGISTER_RAW_SIZE(regnum);
+ write_register(regnum, read_memory_unsigned_integer (sp, REGISTER_RAW_SIZE(regnum)));
+ }
+ flush_cached_frames (); /* needed? */
+}
+
+
+CORE_ADDR
+d30v_push_arguments (nargs, args, sp, struct_return, struct_addr)
+ int nargs;
+ value_ptr *args;
+ CORE_ADDR sp;
+ int struct_return;
+ CORE_ADDR struct_addr;
+{
+ int i, len, index=0, regnum=2;
+ char buffer[4], *contents;
+ LONGEST val;
+ CORE_ADDR ptrs[10];
+
+#if 0
+ /* Pass 1. Put all large args on stack */
+ for (i = 0; i < nargs; i++)
+ {
+ value_ptr arg = args[i];
+ struct type *arg_type = check_typedef (VALUE_TYPE (arg));
+ len = TYPE_LENGTH (arg_type);
+ contents = VALUE_CONTENTS(arg);
+ val = extract_signed_integer (contents, len);
+ if (len > 4)
+ {
+ /* put on stack and pass pointers */
+ sp -= len;
+ write_memory (sp, contents, len);
+ ptrs[index++] = sp;
+ }
+ }
+#endif
+ index = 0;
+
+ for (i = 0; i < nargs; i++)
+ {
+ value_ptr arg = args[i];
+ struct type *arg_type = check_typedef (VALUE_TYPE (arg));
+ len = TYPE_LENGTH (arg_type);
+ contents = VALUE_CONTENTS(arg);
+ if (len > 4)
+ {
+ /* we need multiple registers */
+ int ndx;
+
+ for (ndx = 0; len > 0; ndx += 8, len -= 8)
+ {
+ if (regnum & 1)
+ regnum++; /* all args > 4 bytes start in even register */
+
+ if (regnum < 18)
+ {
+ val = extract_signed_integer (&contents[ndx], 4);
+ write_register (regnum++, val);
+
+ if (len >= 8)
+ val = extract_signed_integer (&contents[ndx+4], 4);
+ else
+ val = extract_signed_integer (&contents[ndx+4], len-4);
+ write_register (regnum++, val);
+ }
+ else
+ {
+ /* no more registers available. put it on the stack */
+
+ /* all args > 4 bytes are padded to a multiple of 8 bytes
+ and start on an 8 byte boundary */
+ if (sp & 7)
+ sp -= (sp & 7); /* align it */
+
+ sp -= ((len + 7) & ~7); /* allocate space */
+ write_memory (sp, &contents[ndx], len);
+ break;
+ }
+ }
+ }
+ else
+ {
+ if (regnum < 18 )
+ {
+ val = extract_signed_integer (contents, len);
+ write_register (regnum++, val);
+ }
+ else
+ {
+ /* all args are padded to a multiple of 4 bytes (at least) */
+ sp -= ((len + 3) & ~3);
+ write_memory (sp, contents, len);
+ }
+ }
+ }
+ if (sp & 7)
+ /* stack pointer is not on an 8 byte boundary -- align it */
+ sp -= (sp & 7);
+ return sp;
+}
+
+
+/* pick an out-of-the-way place to set the return value */
+/* for an inferior function call. The link register is set to this */
+/* value and a momentary breakpoint is set there. When the breakpoint */
+/* is hit, the dummy frame is popped and the previous environment is */
+/* restored. */
+
+CORE_ADDR
+d30v_call_dummy_address ()
+{
+ CORE_ADDR entry;
+ struct minimal_symbol *sym;
+
+ entry = entry_point_address ();
+
+ if (entry != 0)
+ return entry;
+
+ sym = lookup_minimal_symbol ("_start", NULL, symfile_objfile);
+
+ if (!sym || MSYMBOL_TYPE (sym) != mst_text)
+ return 0;
+ else
+ return SYMBOL_VALUE_ADDRESS (sym);
+}
+
+/* Given a return value in `regbuf' with a type `valtype',
+ extract and copy its value into `valbuf'. */
+
+void
+d30v_extract_return_value (valtype, regbuf, valbuf)
+ struct type *valtype;
+ char regbuf[REGISTER_BYTES];
+ char *valbuf;
+{
+ memcpy (valbuf, regbuf + REGISTER_BYTE (2), TYPE_LENGTH (valtype));
+}
+
+/* The following code implements access to, and display of, the D30V's
+ instruction trace buffer. The buffer consists of 64K or more
+ 4-byte words of data, of which each words includes an 8-bit count,
+ an 8-bit segment number, and a 16-bit instruction address.
+
+ In theory, the trace buffer is continuously capturing instruction
+ data that the CPU presents on its "debug bus", but in practice, the
+ ROMified GDB stub only enables tracing when it continues or steps
+ the program, and stops tracing when the program stops; so it
+ actually works for GDB to read the buffer counter out of memory and
+ then read each trace word. The counter records where the tracing
+ stops, but there is no record of where it started, so we remember
+ the PC when we resumed and then search backwards in the trace
+ buffer for a word that includes that address. This is not perfect,
+ because you will miss trace data if the resumption PC is the target
+ of a branch. (The value of the buffer counter is semi-random, any
+ trace data from a previous program stop is gone.) */
+
+/* The address of the last word recorded in the trace buffer. */
+
+#define DBBC_ADDR (0xd80000)
+
+/* The base of the trace buffer, at least for the "Board_0". */
+
+#define TRACE_BUFFER_BASE (0xf40000)
+
+static void trace_command PARAMS ((char *, int));
+
+static void untrace_command PARAMS ((char *, int));
+
+static void trace_info PARAMS ((char *, int));
+
+static void tdisassemble_command PARAMS ((char *, int));
+
+static void display_trace PARAMS ((int, int));
+
+/* True when instruction traces are being collected. */
+
+static int tracing;
+
+/* Remembered PC. */
+
+static CORE_ADDR last_pc;
+
+/* True when trace output should be displayed whenever program stops. */
+
+static int trace_display;
+
+/* True when trace listing should include source lines. */
+
+static int default_trace_show_source = 1;
+
+struct trace_buffer {
+ int size;
+ short *counts;
+ CORE_ADDR *addrs;
+} trace_data;
+
+static void
+trace_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ /* Clear the host-side trace buffer, allocating space if needed. */
+ trace_data.size = 0;
+ if (trace_data.counts == NULL)
+ trace_data.counts = (short *) xmalloc (65536 * sizeof(short));
+ if (trace_data.addrs == NULL)
+ trace_data.addrs = (CORE_ADDR *) xmalloc (65536 * sizeof(CORE_ADDR));
+
+ tracing = 1;
+
+ printf_filtered ("Tracing is now on.\n");
+}
+
+static void
+untrace_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ tracing = 0;
+
+ printf_filtered ("Tracing is now off.\n");
+}
+
+static void
+trace_info (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ int i;
+
+ if (trace_data.size)
+ {
+ printf_filtered ("%d entries in trace buffer:\n", trace_data.size);
+
+ for (i = 0; i < trace_data.size; ++i)
+ {
+ printf_filtered ("%d: %d instruction%s at 0x%x\n",
+ i, trace_data.counts[i],
+ (trace_data.counts[i] == 1 ? "" : "s"),
+ trace_data.addrs[i]);
+ }
+ }
+ else
+ printf_filtered ("No entries in trace buffer.\n");
+
+ printf_filtered ("Tracing is currently %s.\n", (tracing ? "on" : "off"));
+}
+
+/* Print the instruction at address MEMADDR in debugged memory,
+ on STREAM. Returns length of the instruction, in bytes. */
+
+static int
+print_insn (memaddr, stream)
+ CORE_ADDR memaddr;
+ GDB_FILE *stream;
+{
+ /* If there's no disassembler, something is very wrong. */
+ if (tm_print_insn == NULL)
+ abort ();
+
+ if (TARGET_BYTE_ORDER == BIG_ENDIAN)
+ tm_print_insn_info.endian = BFD_ENDIAN_BIG;
+ else
+ tm_print_insn_info.endian = BFD_ENDIAN_LITTLE;
+ return (*tm_print_insn) (memaddr, &tm_print_insn_info);
+}
+
+void
+d30v_eva_prepare_to_trace ()
+{
+ if (!tracing)
+ return;
+
+ last_pc = read_register (PC_REGNUM);
+}
+
+/* Collect trace data from the target board and format it into a form
+ more useful for display. */
+
+void
+d30v_eva_get_trace_data ()
+{
+ int count, i, j, oldsize;
+ int trace_addr, trace_seg, trace_cnt, next_cnt;
+ unsigned int last_trace, trace_word, next_word;
+ unsigned int *tmpspace;
+
+ if (!tracing)
+ return;
+
+ tmpspace = xmalloc (65536 * sizeof(unsigned int));
+
+ last_trace = read_memory_unsigned_integer (DBBC_ADDR, 2) << 2;
+
+ /* Collect buffer contents from the target, stopping when we reach
+ the word recorded when execution resumed. */
+
+ count = 0;
+ while (last_trace > 0)
+ {
+ QUIT;
+ trace_word =
+ read_memory_unsigned_integer (TRACE_BUFFER_BASE + last_trace, 4);
+ trace_addr = trace_word & 0xffff;
+ last_trace -= 4;
+ /* Ignore an apparently nonsensical entry. */
+ if (trace_addr == 0xffd5)
+ continue;
+ tmpspace[count++] = trace_word;
+ if (trace_addr == last_pc)
+ break;
+ if (count > 65535)
+ break;
+ }
+
+ /* Move the data to the host-side trace buffer, adjusting counts to
+ include the last instruction executed and transforming the address
+ into something that GDB likes. */
+
+ for (i = 0; i < count; ++i)
+ {
+ trace_word = tmpspace[i];
+ next_word = ((i == 0) ? 0 : tmpspace[i - 1]);
+ trace_addr = trace_word & 0xffff;
+ next_cnt = (next_word >> 24) & 0xff;
+ j = trace_data.size + count - i - 1;
+ trace_data.addrs[j] = (trace_addr << 2) + 0x1000000;
+ trace_data.counts[j] = next_cnt + 1;
+ }
+
+ oldsize = trace_data.size;
+ trace_data.size += count;
+
+ free (tmpspace);
+
+ if (trace_display)
+ display_trace (oldsize, trace_data.size);
+}
+
+static void
+tdisassemble_command (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ int i, count;
+ CORE_ADDR low, high;
+ char *space_index;
+
+ if (!arg)
+ {
+ low = 0;
+ high = trace_data.size;
+ }
+ else if (!(space_index = (char *) strchr (arg, ' ')))
+ {
+ low = parse_and_eval_address (arg);
+ high = low + 5;
+ }
+ else
+ {
+ /* Two arguments. */
+ *space_index = '\0';
+ low = parse_and_eval_address (arg);
+ high = parse_and_eval_address (space_index + 1);
+ if (high < low)
+ high = low;
+ }
+
+ printf_filtered ("Dump of trace from %d to %d:\n", low, high);
+
+ display_trace (low, high);
+
+ printf_filtered ("End of trace dump.\n");
+ gdb_flush (gdb_stdout);
+}
+
+static void
+display_trace (low, high)
+ int low, high;
+{
+ int i, count, trace_show_source, first, suppress;
+ CORE_ADDR next_address;
+
+ trace_show_source = default_trace_show_source;
+ if (!have_full_symbols () && !have_partial_symbols())
+ {
+ trace_show_source = 0;
+ printf_filtered ("No symbol table is loaded. Use the \"file\" command.\n");
+ printf_filtered ("Trace will not display any source.\n");
+ }
+
+ first = 1;
+ suppress = 0;
+ for (i = low; i < high; ++i)
+ {
+ next_address = trace_data.addrs[i];
+ count = trace_data.counts[i];
+ while (count-- > 0)
+ {
+ QUIT;
+ if (trace_show_source)
+ {
+ struct symtab_and_line sal, sal_prev;
+
+ sal_prev = find_pc_line (next_address - 4, 0);
+ sal = find_pc_line (next_address, 0);
+
+ if (sal.symtab)
+ {
+ if (first || sal.line != sal_prev.line)
+ print_source_lines (sal.symtab, sal.line, sal.line + 1, 0);
+ suppress = 0;
+ }
+ else
+ {
+ if (!suppress)
+ /* FIXME-32x64--assumes sal.pc fits in long. */
+ printf_filtered ("No source file for address %s.\n",
+ local_hex_string((unsigned long) sal.pc));
+ suppress = 1;
+ }
+ }
+ first = 0;
+ print_address (next_address, gdb_stdout);
+ printf_filtered (":");
+ printf_filtered ("\t");
+ wrap_here (" ");
+ next_address = next_address + print_insn (next_address, gdb_stdout);
+ printf_filtered ("\n");
+ gdb_flush (gdb_stdout);
+ }
+ }
+}
+
+extern void (*target_resume_hook) PARAMS ((void));
+extern void (*target_wait_loop_hook) PARAMS ((void));
+
+void
+_initialize_d30v_tdep ()
+{
+ tm_print_insn = print_insn_d30v;
+
+ target_resume_hook = d30v_eva_prepare_to_trace;
+ target_wait_loop_hook = d30v_eva_get_trace_data;
+
+ add_info ("flags", print_flags_command, "Print d30v flags.");
+
+ add_com ("trace", class_support, trace_command,
+ "Enable tracing of instruction execution.");
+
+ add_com ("untrace", class_support, untrace_command,
+ "Disable tracing of instruction execution.");
+
+ add_com ("tdisassemble", class_vars, tdisassemble_command,
+ "Disassemble the trace buffer.\n\
+Two optional arguments specify a range of trace buffer entries\n\
+as reported by info trace (NOT addresses!).");
+
+ add_info ("trace", trace_info,
+ "Display info about the trace data buffer.");
+
+ add_show_from_set (add_set_cmd ("tracedisplay", no_class,
+ var_integer, (char *)&trace_display,
+ "Set automatic display of trace.\n", &setlist),
+ &showlist);
+ add_show_from_set (add_set_cmd ("tracesource", no_class,
+ var_integer, (char *)&default_trace_show_source,
+ "Set display of source code with trace.\n", &setlist),
+ &showlist);
+
+}
diff --git a/gdb/dbug-rom.c b/gdb/dbug-rom.c
new file mode 100644
index 00000000000..fa9c97440ed
--- /dev/null
+++ b/gdb/dbug-rom.c
@@ -0,0 +1,164 @@
+/* Remote debugging interface to dBUG ROM monitor for GDB, the GNU debugger.
+ Copyright 1996 Free Software Foundation, Inc.
+
+ Written by Stan Shebs of 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* dBUG is a monitor supplied on various Motorola boards, including
+ m68k, ColdFire, and PowerPC-based designs. The code here assumes
+ the ColdFire, and (as of 9/25/96) has only been tested with a
+ ColdFire IDP board. */
+
+#include "defs.h"
+#include "gdbcore.h"
+#include "target.h"
+#include "monitor.h"
+#include "serial.h"
+
+static void dbug_open PARAMS ((char *args, int from_tty));
+
+static void
+dbug_supply_register (regname, regnamelen, val, vallen)
+ char *regname;
+ int regnamelen;
+ char *val;
+ int vallen;
+{
+ int regno;
+
+ if (regnamelen != 2)
+ return;
+
+ switch (regname[0])
+ {
+ case 'S':
+ if (regname[1] != 'R')
+ return;
+ regno = PS_REGNUM;
+ break;
+ case 'P':
+ if (regname[1] != 'C')
+ return;
+ regno = PC_REGNUM;
+ break;
+ case 'D':
+ if (regname[1] < '0' || regname[1] > '7')
+ return;
+ regno = regname[1] - '0' + D0_REGNUM;
+ break;
+ case 'A':
+ if (regname[1] < '0' || regname[1] > '7')
+ return;
+ regno = regname[1] - '0' + A0_REGNUM;
+ break;
+ default:
+ return;
+ }
+
+ monitor_supply_register (regno, val);
+}
+
+/* This array of registers needs to match the indexes used by GDB. The
+ whole reason this exists is because the various ROM monitors use
+ different names than GDB does, and don't support all the registers
+ either. So, typing "info reg sp" becomes an "A7". */
+
+static char *dbug_regnames[NUM_REGS] =
+{
+ "D0", "D1", "D2", "D3", "D4", "D5", "D6", "D7",
+ "A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7",
+ "SR", "PC"
+ /* no float registers */
+};
+static struct target_ops dbug_ops;
+static struct monitor_ops dbug_cmds ;
+
+static char *dbug_inits[] = {"\r", NULL};
+
+
+static void
+init_dbug_cmds(void)
+{
+ dbug_cmds.flags = MO_CLR_BREAK_USES_ADDR | MO_GETMEM_NEEDS_RANGE | MO_FILL_USES_ADDR;
+ dbug_cmds.init = dbug_inits; /* Init strings */
+ dbug_cmds.cont = "go\r"; /* continue command */
+ dbug_cmds.step = "step\r"; /* single step */
+ dbug_cmds.stop = NULL; /* interrupt command */
+ dbug_cmds.set_break = "br %x\r"; /* set a breakpoint */
+ dbug_cmds.clr_break = "br -c %x\r"; /* clear a breakpoint */
+ dbug_cmds.clr_all_break = "br -c\r"; /* clear all breakpoints */
+ dbug_cmds.fill = "bf.b %x %x %x"; /* fill (start end val) */
+ dbug_cmds.setmem.cmdb = "mm.b %x %x\r"; /* setmem.cmdb (addr, value) */
+ dbug_cmds.setmem.cmdw = "mm.w %x %x\r"; /* setmem.cmdw (addr, value) */
+ dbug_cmds.setmem.cmdl = "mm.l %x %x\r"; /* setmem.cmdl (addr, value) */
+ dbug_cmds.setmem.cmdll = NULL; /* setmem.cmdll (addr, value) */
+ dbug_cmds.setmem.resp_delim = NULL; /* setmem.resp_delim */
+ dbug_cmds.setmem.term = NULL; /* setmem.term */
+ dbug_cmds.setmem.term_cmd = NULL; /* setmem.term_cmd */
+ dbug_cmds.getmem.cmdb = "md.b %x %x\r"; /* getmem.cmdb (addr, addr2) */
+ dbug_cmds.getmem.cmdw = "md.w %x %x\r"; /* getmem.cmdw (addr, addr2) */
+ dbug_cmds.getmem.cmdl = "md.l %x %x\r"; /* getmem.cmdl (addr, addr2) */
+ dbug_cmds.getmem.cmdll = NULL; /* getmem.cmdll (addr, addr2) */
+ dbug_cmds.getmem.resp_delim = ":"; /* getmem.resp_delim */
+ dbug_cmds.getmem.term = NULL; /* getmem.term */
+ dbug_cmds.getmem.term_cmd = NULL; /* getmem.term_cmd */
+ dbug_cmds.setreg.cmd = "rm %s %x\r"; /* setreg.cmd (name, value) */
+ dbug_cmds.setreg.resp_delim = NULL; /* setreg.resp_delim */
+ dbug_cmds.setreg.term = NULL; /* setreg.term */
+ dbug_cmds.setreg.term_cmd = NULL; /* setreg.term_cmd */
+ dbug_cmds.getreg.cmd = "rd %s\r"; /* getreg.cmd (name) */
+ dbug_cmds.getreg.resp_delim = ":"; /* getreg.resp_delim */
+ dbug_cmds.getreg.term = NULL; /* getreg.term */
+ dbug_cmds.getreg.term_cmd = NULL; /* getreg.term_cmd */
+ dbug_cmds.dump_registers = "rd\r"; /* dump_registers */
+ dbug_cmds.register_pattern = "\\(\\w+\\) +:\\([0-9a-fA-F]+\\b\\)"; /* register_pattern */
+ dbug_cmds.supply_register = dbug_supply_register; /* supply_register */
+ dbug_cmds.load_routine = NULL; /* load_routine (defaults to SRECs) */
+ dbug_cmds.load = "dl\r"; /* download command */
+ dbug_cmds.loadresp = "\n"; /* load response */
+ dbug_cmds.prompt = "dBUG>"; /* monitor command prompt */
+ dbug_cmds.line_term = "\r"; /* end-of-line terminator */
+ dbug_cmds.cmd_end = NULL; /* optional command terminator */
+ dbug_cmds.target = &dbug_ops ; /* target operations */
+ dbug_cmds.stopbits = SERIAL_1_STOPBITS; /* number of stop bits */
+ dbug_cmds.regnames = dbug_regnames; /* registers names */
+ dbug_cmds.magic = MONITOR_OPS_MAGIC ; /* magic */
+} /* init_debug_ops */
+
+static void
+dbug_open(args, from_tty)
+ char *args;
+ int from_tty;
+{
+ monitor_open (args, &dbug_cmds, from_tty);
+}
+
+void
+_initialize_dbug_rom ()
+{
+ init_dbug_cmds() ;
+ init_monitor_ops (&dbug_ops);
+
+ dbug_ops.to_shortname = "dbug";
+ dbug_ops.to_longname = "dBUG monitor";
+ dbug_ops.to_doc = "Debug via the dBUG monitor.\n\
+Specify the serial device it is connected to (e.g. /dev/ttya).";
+ dbug_ops.to_open = dbug_open;
+
+ add_target (&dbug_ops);
+}
diff --git a/gdb/dbxread.c b/gdb/dbxread.c
new file mode 100644
index 00000000000..0749412cc35
--- /dev/null
+++ b/gdb/dbxread.c
@@ -0,0 +1,2738 @@
+/* Read dbx symbol tables and convert to internal format, for GDB.
+ Copyright 1986, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 1998
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 "gdb_string.h"
+
+#if defined(USG) || defined(__CYGNUSCLIB__)
+#include <sys/types.h>
+#include <fcntl.h>
+#endif
+
+#include "obstack.h"
+#include "gdb_stat.h"
+#include <ctype.h>
+#include "symtab.h"
+#include "breakpoint.h"
+#include "command.h"
+#include "target.h"
+#include "gdbcore.h" /* for bfd stuff */
+#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 */
+
+
+/* This macro returns the size field of a minimal symbol, which is normally
+ stored in the "info" field. The macro can be overridden for specific
+ targets (e.g. MIPS16) that use the info field for other purposes. */
+#ifndef MSYMBOL_SIZE
+#define MSYMBOL_SIZE(msym) ((long) MSYMBOL_INFO (msym))
+#endif
+
+
+/* We put a pointer to this structure in the read_symtab_private field
+ of the psymtab. */
+
+struct symloc {
+
+ /* Offset within the file symbol table of first local symbol for this
+ file. */
+
+ int ldsymoff;
+
+ /* 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). 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. */
+
+ int ldsymlen;
+
+ /* The size of each symbol in the symbol file (in external form). */
+
+ int symbol_size;
+
+ /* Further information needed to locate the symbols if they are in
+ an ELF file. */
+
+ int symbol_offset;
+ int string_offset;
+ int file_string_offset;
+};
+
+#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)
+
+
+/* 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;
+
+/* .o and NLM files contain unrelocated addresses which are based at
+ 0. When non-zero, this flag disables some of the special cases for
+ Solaris elf+stab text addresses at location 0. */
+
+static int symfile_relocatable = 0;
+
+/* If this is nonzero, N_LBRAC, N_RBRAC, and N_SLINE entries are
+ relative to the function start address. */
+
+static int block_address_function_relative = 0;
+
+/* The lowest text address we have yet encountered. This is needed
+ because in an a.out file, there is no header field which tells us
+ what address the program is actually going to be loaded at, so we
+ need to make guesses based on the symbols (which *are* relocated to
+ reflect the address it will be loaded at). */
+
+static CORE_ADDR lowest_text_address;
+
+/* Non-zero if there is any line number info in the objfile. Prevents
+ end_psymtab from discarding an otherwise empty psymtab. */
+
+static int has_line_numbers;
+
+/* 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 descriptor `%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 %s not previously seen, at symtab pos %d", 0, 0};
+
+struct complaint unclaimed_bincl_complaint =
+ {"N_BINCL %s not in entries for any file, at symtab pos %d", 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
+process_now PARAMS ((struct objfile *));
+
+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_dynamic_symtab PARAMS ((struct section_offsets *,
+ struct objfile *objfile));
+
+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 char *
+dbx_next_symbol_text PARAMS ((struct objfile *));
+
+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 ()
+{
+ if (this_object_header_files)
+ {
+ free ((PTR)this_object_header_files);
+ this_object_header_files = NULL;
+ }
+ n_allocated_this_object_header_files = 0;
+}
+
+/* Allocate new header file tables */
+
+static void
+init_header_files ()
+{
+ 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 (current_objfile);
+ register int i;
+
+ for (i = 0; i < N_HEADER_FILES (current_objfile); i++)
+ if (STREQ (p[i].name, name) && instance == p[i].instance)
+ {
+ add_this_object_header_file (i);
+ return;
+ }
+ complain (&repeated_header_complaint, name, 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 *hfile;
+
+ /* Make sure there is room for one more header file. */
+
+ i = N_ALLOCATED_HEADER_FILES (current_objfile);
+
+ if (N_HEADER_FILES (current_objfile) == i)
+ {
+ if (i == 0)
+ {
+ N_ALLOCATED_HEADER_FILES (current_objfile) = 10;
+ HEADER_FILES (current_objfile) = (struct header_file *)
+ xmalloc (10 * sizeof (struct header_file));
+ }
+ else
+ {
+ i *= 2;
+ N_ALLOCATED_HEADER_FILES (current_objfile) = i;
+ HEADER_FILES (current_objfile) = (struct header_file *)
+ xrealloc ((char *) HEADER_FILES (current_objfile),
+ (i * sizeof (struct header_file)));
+ }
+ }
+
+ /* Create an entry for this header file. */
+
+ i = N_HEADER_FILES (current_objfile)++;
+ hfile = HEADER_FILES (current_objfile) + i;
+ hfile->name = savestring (name, strlen(name));
+ hfile->instance = instance;
+ hfile->length = 10;
+ hfile->vector
+ = (struct type **) xmalloc (10 * sizeof (struct type *));
+ memset (hfile->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 (current_objfile)[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;
+ int section;
+ asection *bfd_section;
+
+ switch (type)
+ {
+ case N_TEXT | N_EXT:
+ ms_type = mst_text;
+ section = SECT_OFF_TEXT;
+ bfd_section = DBX_TEXT_SECTION (objfile);
+ break;
+ case N_DATA | N_EXT:
+ ms_type = mst_data;
+ section = SECT_OFF_DATA;
+ bfd_section = DBX_DATA_SECTION (objfile);
+ break;
+ case N_BSS | N_EXT:
+ ms_type = mst_bss;
+ section = SECT_OFF_BSS;
+ bfd_section = DBX_BSS_SECTION (objfile);
+ break;
+ case N_ABS | N_EXT:
+ ms_type = mst_abs;
+ section = -1;
+ bfd_section = NULL;
+ break;
+#ifdef N_SETV
+ case N_SETV | N_EXT:
+ ms_type = mst_data;
+ section = SECT_OFF_DATA;
+ bfd_section = DBX_DATA_SECTION (objfile);
+ 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;
+ section = SECT_OFF_DATA;
+ bfd_section = DBX_DATA_SECTION (objfile);
+ break;
+#endif
+ case N_TEXT:
+ case N_NBTEXT:
+ case N_FN:
+ case N_FN_SEQ:
+ ms_type = mst_file_text;
+ section = SECT_OFF_TEXT;
+ bfd_section = DBX_TEXT_SECTION (objfile);
+ 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;
+ }
+ section = SECT_OFF_DATA;
+ bfd_section = DBX_DATA_SECTION (objfile);
+ break;
+ case N_BSS:
+ ms_type = mst_file_bss;
+ section = SECT_OFF_BSS;
+ bfd_section = DBX_BSS_SECTION (objfile);
+ break;
+ default:
+ ms_type = mst_unknown;
+ section = -1;
+ bfd_section = NULL;
+ break;
+ }
+
+ if ((ms_type == mst_file_text || ms_type == mst_text)
+ && address < lowest_text_address)
+ lowest_text_address = address;
+
+ prim_record_minimal_symbol_and_info
+ (name, address, ms_type, NULL, section, bfd_section, objfile);
+}
+
+/* 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;
+
+ val = strlen (objfile->name);
+
+ sym_bfd = objfile->obfd;
+
+ /* .o and .nlm files are relocatables with text, data and bss segs based at
+ 0. This flag disables special (Solaris stabs-in-elf only) fixups for
+ symbols with a value of 0. */
+
+ symfile_relocatable = bfd_get_file_flags (sym_bfd) & HAS_RELOC;
+
+ /* This is true for Solaris (and all other systems which put stabs
+ in sections, 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 (sym_bfd), "elf", 3))
+ || (0 == strncmp (bfd_get_target (sym_bfd), "som", 3))
+ || (0 == strncmp (bfd_get_target (sym_bfd), "coff", 4))
+ || (0 == strncmp (bfd_get_target (sym_bfd), "pe", 2))
+ || (0 == strncmp (bfd_get_target (sym_bfd), "nlm", 3)));
+
+ val = bfd_seek (sym_bfd, 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, DBX_SYMCOUNT (objfile));
+
+ symbol_size = DBX_SYMBOL_SIZE (objfile);
+ symbol_table_offset = DBX_SYMTAB_OFFSET (objfile);
+
+ free_pending_blocks ();
+ back_to = make_cleanup ((make_cleanup_func) really_free_pendings, 0);
+
+ init_minimal_symbol_collection ();
+ make_cleanup ((make_cleanup_func) 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,
+ DBX_TEXT_ADDR (objfile),
+ DBX_TEXT_SIZE (objfile));
+
+ /* Add the dynamic symbols. */
+
+ read_dbx_dynamic_symtab (section_offsets, objfile);
+
+ /* Install any minimal symbols that have been collected as the current
+ minimal symbols for this objfile. */
+
+ install_minimal_symbols (objfile);
+
+ 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);
+ asection *text_sect;
+ unsigned char size_temp[DBX_STRINGTAB_SIZE_SIZE];
+
+ /* Allocate struct to keep track of the symfile */
+ objfile->sym_stab_info = (struct dbx_symfile_info *)
+ xmmalloc (objfile -> md, sizeof (struct dbx_symfile_info));
+ memset ((PTR) objfile->sym_stab_info, 0, sizeof (struct dbx_symfile_info));
+
+ DBX_TEXT_SECTION (objfile) = bfd_get_section_by_name (sym_bfd, ".text");
+ DBX_DATA_SECTION (objfile) = bfd_get_section_by_name (sym_bfd, ".data");
+ DBX_BSS_SECTION (objfile) = bfd_get_section_by_name (sym_bfd, ".bss");
+
+ /* 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;
+
+ text_sect = bfd_get_section_by_name (sym_bfd, ".text");
+ if (!text_sect)
+ error ("Can't find .text section in symbol file");
+ DBX_TEXT_ADDR (objfile) = bfd_section_vma (sym_bfd, text_sect);
+ DBX_TEXT_SIZE (objfile) = bfd_section_size (sym_bfd, text_sect);
+
+ 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));
+ OBJSTAT (objfile, sz_strtab += 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)
+ {
+ if (HEADER_FILES (objfile) != NULL)
+ {
+ register int i = N_HEADER_FILES (objfile);
+ register struct header_file *hfiles = HEADER_FILES (objfile);
+
+ while (--i >= 0)
+ {
+ free (hfiles [i].name);
+ free (hfiles [i].vector);
+ }
+ free ((PTR) hfiles);
+ }
+ mfree (objfile -> md, objfile->sym_stab_info);
+ }
+ free_header_files ();
+}
+
+
+/* Buffer for reading the symbol table entries. */
+static struct external_nlist symbuf[4096];
+static int symbuf_idx;
+static int symbuf_end;
+
+/* cont_elem is used for continuing information in cfront.
+ It saves information about which types need to be fixed up and
+ completed after all the stabs are read. */
+struct cont_elem
+ {
+ /* sym and stabsstring for continuing information in cfront */
+ struct symbol * sym;
+ char * stabs;
+ /* state dependancies (statics that must be preserved) */
+ int sym_idx;
+ int sym_end;
+ int symnum;
+ int (*func) PARAMS ((struct objfile *, struct symbol *, char *));
+ /* other state dependancies include:
+ (assumption is that these will not change since process_now FIXME!!)
+ stringtab_global
+ n_stabs
+ objfile
+ symfile_bfd */
+};
+
+static struct cont_elem *cont_list = 0;
+static int cont_limit = 0;
+static int cont_count = 0;
+
+/* Arrange for function F to be called with arguments SYM and P later
+ in the stabs reading process. */
+void
+process_later (sym, p, f)
+ struct symbol *sym;
+ char *p;
+ int (*f) PARAMS ((struct objfile *, struct symbol *, char *));
+{
+
+ /* Allocate more space for the deferred list. */
+ if (cont_count >= cont_limit - 1)
+ {
+ cont_limit += 32; /* chunk size */
+
+ cont_list
+ = (struct cont_elem *) xrealloc (cont_list,
+ (cont_limit
+ * sizeof (struct cont_elem)));
+ if (!cont_list)
+ error ("Virtual memory exhausted\n");
+ }
+
+ /* Save state variables so we can process these stabs later. */
+ cont_list[cont_count].sym_idx = symbuf_idx;
+ cont_list[cont_count].sym_end = symbuf_end;
+ cont_list[cont_count].symnum = symnum;
+ cont_list[cont_count].sym = sym;
+ cont_list[cont_count].stabs = p;
+ cont_list[cont_count].func = f;
+ cont_count++;
+}
+
+/* Call deferred funtions in CONT_LIST. */
+
+static void
+process_now (objfile)
+ struct objfile *objfile;
+{
+ int i;
+ int save_symbuf_idx;
+ int save_symbuf_end;
+ int save_symnum;
+ struct symbol *sym;
+ char *stabs;
+ int err;
+ int (*func) PARAMS ((struct objfile *, struct symbol *, char *));
+
+ /* Save the state of our caller, we'll want to restore it before
+ returning. */
+ save_symbuf_idx = symbuf_idx;
+ save_symbuf_end = symbuf_end;
+ save_symnum = symnum;
+
+ /* Iterate over all the deferred stabs. */
+ for (i = 0; i < cont_count; i++)
+ {
+ /* Restore the state for this deferred stab. */
+ symbuf_idx = cont_list[i].sym_idx;
+ symbuf_end = cont_list[i].sym_end;
+ symnum = cont_list[i].symnum;
+ sym = cont_list[i].sym;
+ stabs = cont_list[i].stabs;
+ func = cont_list[i].func;
+
+ /* Call the function to handle this deferrd stab. */
+ err = (*func) (objfile, sym, stabs);
+ if (err)
+ error ("Internal error: unable to resolve stab.\n");
+ }
+
+ /* Restore our caller's state. */
+ symbuf_idx = save_symbuf_idx;
+ symbuf_end = save_symbuf_end;
+ symnum = save_symnum;
+ cont_count = 0;
+}
+
+
+/* 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. FIXME: If that is true, we don't need it when
+ building psymtabs, right? */
+static char *stringtab_global;
+
+/* These variables are used to control fill_symbuf when the stabs
+ symbols are not contiguous (as may be the case when a COFF file is
+ linked using --split-by-reloc). */
+static struct stab_section_list *symbuf_sections;
+static unsigned int symbuf_left;
+static unsigned int symbuf_read;
+
+/* 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;
+{
+ unsigned int count;
+ int nbytes;
+
+ if (symbuf_sections == NULL)
+ count = sizeof (symbuf);
+ else
+ {
+ if (symbuf_left <= 0)
+ {
+ file_ptr filepos = symbuf_sections->section->filepos;
+ if (bfd_seek (sym_bfd, filepos, SEEK_SET) != 0)
+ perror_with_name (bfd_get_filename (sym_bfd));
+ symbuf_left = bfd_section_size (sym_bfd, symbuf_sections->section);
+ symbol_table_offset = filepos - symbuf_read;
+ symbuf_sections = symbuf_sections->next;
+ }
+
+ count = symbuf_left;
+ if (count > sizeof (symbuf))
+ count = sizeof (symbuf);
+ }
+
+ nbytes = bfd_read ((PTR)symbuf, count, 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;
+ symbuf_left -= nbytes;
+ symbuf_read += nbytes;
+}
+
+#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); \
+ }
+
+#define INTERNALIZE_SYMBOL(intern, extern, abfd) \
+ { \
+ (intern).n_type = bfd_h_get_8 (abfd, (extern)->e_type); \
+ (intern).n_strx = bfd_h_get_32 (abfd, (extern)->e_strx); \
+ (intern).n_desc = bfd_h_get_16 (abfd, (extern)->e_desc); \
+ (intern).n_value = bfd_h_get_32 (abfd, (extern)->e_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 (objfile)
+ struct objfile *objfile;
+{
+ struct internal_nlist nlist;
+
+ if (symbuf_idx == symbuf_end)
+ fill_symbuf (symfile_bfd);
+
+ symnum++;
+ INTERNALIZE_SYMBOL(nlist, &symbuf[symbuf_idx], symfile_bfd);
+ OBJSTAT (objfile, n_stabs++);
+
+ symbuf_idx++;
+
+ return nlist.n_strx + stringtab_global + file_string_table_offset;
+}
+
+/* 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;
+
+ complain (&repeated_header_complaint, name, symnum);
+ 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;
+}
+
+/* Scan a SunOs dynamic symbol table for symbols of interest and
+ add them to the minimal symbol table. */
+
+static void
+read_dbx_dynamic_symtab (section_offsets, objfile)
+ struct section_offsets *section_offsets;
+ struct objfile *objfile;
+{
+ bfd *abfd = objfile->obfd;
+ struct cleanup *back_to;
+ int counter;
+ long dynsym_size;
+ long dynsym_count;
+ asymbol **dynsyms;
+ asymbol **symptr;
+ arelent **relptr;
+ long dynrel_size;
+ long dynrel_count;
+ arelent **dynrels;
+ CORE_ADDR sym_value;
+ char *name;
+
+ /* Check that the symbol file has dynamic symbols that we know about.
+ bfd_arch_unknown can happen if we are reading a sun3 symbol file
+ on a sun4 host (and vice versa) and bfd is not configured
+ --with-target=all. This would trigger an assertion in bfd/sunos.c,
+ so we ignore the dynamic symbols in this case. */
+ if (bfd_get_flavour (abfd) != bfd_target_aout_flavour
+ || (bfd_get_file_flags (abfd) & DYNAMIC) == 0
+ || bfd_get_arch (abfd) == bfd_arch_unknown)
+ return;
+
+ dynsym_size = bfd_get_dynamic_symtab_upper_bound (abfd);
+ if (dynsym_size < 0)
+ return;
+
+ dynsyms = (asymbol **) xmalloc (dynsym_size);
+ back_to = make_cleanup (free, dynsyms);
+
+ dynsym_count = bfd_canonicalize_dynamic_symtab (abfd, dynsyms);
+ if (dynsym_count < 0)
+ {
+ do_cleanups (back_to);
+ return;
+ }
+
+ /* Enter dynamic symbols into the minimal symbol table
+ if this is a stripped executable. */
+ if (bfd_get_symcount (abfd) <= 0)
+ {
+ symptr = dynsyms;
+ for (counter = 0; counter < dynsym_count; counter++, symptr++)
+ {
+ asymbol *sym = *symptr;
+ asection *sec;
+ int type;
+
+ sec = bfd_get_section (sym);
+
+ /* BFD symbols are section relative. */
+ sym_value = sym->value + sec->vma;
+
+ if (bfd_get_section_flags (abfd, sec) & SEC_CODE)
+ {
+ sym_value += ANOFFSET (section_offsets, SECT_OFF_TEXT);
+ type = N_TEXT;
+ }
+ else if (bfd_get_section_flags (abfd, sec) & SEC_DATA)
+ {
+ sym_value += ANOFFSET (section_offsets, SECT_OFF_DATA);
+ type = N_DATA;
+ }
+ else if (bfd_get_section_flags (abfd, sec) & SEC_ALLOC)
+ {
+ sym_value += ANOFFSET (section_offsets, SECT_OFF_BSS);
+ type = N_BSS;
+ }
+ else
+ continue;
+
+ if (sym->flags & BSF_GLOBAL)
+ type |= N_EXT;
+
+ record_minimal_symbol ((char *) bfd_asymbol_name (sym), sym_value,
+ type, objfile);
+ }
+ }
+
+ /* Symbols from shared libraries have a dynamic relocation entry
+ that points to the associated slot in the procedure linkage table.
+ We make a mininal symbol table entry with type mst_solib_trampoline
+ at the address in the procedure linkage table. */
+ dynrel_size = bfd_get_dynamic_reloc_upper_bound (abfd);
+ if (dynrel_size < 0)
+ {
+ do_cleanups (back_to);
+ return;
+ }
+
+ dynrels = (arelent **) xmalloc (dynrel_size);
+ make_cleanup (free, dynrels);
+
+ dynrel_count = bfd_canonicalize_dynamic_reloc (abfd, dynrels, dynsyms);
+ if (dynrel_count < 0)
+ {
+ do_cleanups (back_to);
+ return;
+ }
+
+ for (counter = 0, relptr = dynrels;
+ counter < dynrel_count;
+ counter++, relptr++)
+ {
+ arelent *rel = *relptr;
+ CORE_ADDR address =
+ rel->address + ANOFFSET (section_offsets, SECT_OFF_DATA);
+
+ switch (bfd_get_arch (abfd))
+ {
+ case bfd_arch_sparc:
+ if (rel->howto->type != RELOC_JMP_SLOT)
+ continue;
+ break;
+ case bfd_arch_m68k:
+ /* `16' is the type BFD produces for a jump table relocation. */
+ if (rel->howto->type != 16)
+ continue;
+
+ /* Adjust address in the jump table to point to
+ the start of the bsr instruction. */
+ address -= 2;
+ break;
+ default:
+ continue;
+ }
+
+ name = (char *) bfd_asymbol_name (*rel->sym_ptr_ptr);
+ prim_record_minimal_symbol (name, address, mst_solib_trampoline,
+ objfile);
+ }
+
+ do_cleanups (back_to);
+}
+
+/* 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 external_nlist *bufp = 0; /* =0 avoids gcc -Wall glitch */
+ struct internal_nlist nlist;
+
+ register char *namestring;
+ int nsl;
+ int past_first_source_file = 0;
+ CORE_ADDR last_o_file_start = 0;
+ CORE_ADDR last_function_start = 0;
+ struct cleanup *back_to;
+ bfd *abfd;
+ int textlow_not_set;
+
+ /* 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 ((make_cleanup_func) free_bincl_list, objfile);
+
+ last_source_file = NULL;
+
+ lowest_text_address = (CORE_ADDR)-1;
+
+ symfile_bfd = objfile->obfd; /* For next_text_symbol */
+ abfd = objfile->obfd;
+ symbuf_end = symbuf_idx = 0;
+ next_symbol_text_func = dbx_next_symbol_text;
+ textlow_not_set = 1;
+ has_line_numbers = 0;
+
+ 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 (bfd_h_get_8 (abfd, bufp->e_type) == N_SLINE)
+ {
+ has_line_numbers = 1;
+ continue;
+ }
+
+ INTERNALIZE_SYMBOL (nlist, bufp, abfd);
+ OBJSTAT (objfile, n_stabs++);
+
+ /* 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 nlist. 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)CUR_SYMBOL_STRX + file_string_table_offset) >= \
+ DBX_STRINGTAB_SIZE (objfile)) { \
+ complain (&string_table_offset_complaint, symnum); \
+ namestring = "<bad string table offset>"; \
+ } else \
+ namestring = CUR_SYMBOL_STRX + file_string_table_offset + \
+ DBX_STRINGTAB (objfile)
+
+#define CUR_SYMBOL_TYPE nlist.n_type
+#define CUR_SYMBOL_VALUE nlist.n_value
+#define CUR_SYMBOL_STRX nlist.n_strx
+#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,textlow_not_set)\
+ end_psymtab(pst,ilist,ninc,c_off,c_text,dep_list,n_deps,textlow_not_set)
+
+#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 < nlist.n_value
+ && objfile -> ei.entry_point >= last_o_file_start)
+ {
+ objfile -> ei.entry_file_lowpc = last_o_file_start;
+ objfile -> ei.entry_file_highpc = nlist.n_value;
+ }
+
+ if (pst)
+ {
+ /* Don't set pst->texthigh lower than it already is. */
+ CORE_ADDR text_end =
+ (lowest_text_address == (CORE_ADDR)-1
+ ? (text_addr + section_offsets->offsets[SECT_OFF_TEXT])
+ : lowest_text_address)
+ + text_size;
+
+ end_psymtab (pst, psymtab_include_list, includes_used,
+ symnum * symbol_size,
+ text_end > pst->texthigh ? text_end : pst->texthigh,
+ dependency_list, dependencies_used, textlow_not_set);
+ }
+
+ 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, textlow_not_set)
+ 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;
+ int textlow_not_set;
+{
+ int i;
+ struct objfile *objfile = pst -> objfile;
+
+ if (capping_symbol_offset != -1)
+ LDSYMLEN(pst) = capping_symbol_offset - LDSYMOFF(pst);
+ pst->texthigh = capping_text;
+
+#ifdef SOFUN_ADDRESS_MAYBE_MISSING
+ /* 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 not set (ie: textlow_not_set), 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. */
+
+ 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 + 2);
+ strncpy (p, last_function_name, n);
+ p[n] = 0;
+
+ minsym = lookup_minimal_symbol (p, pst->filename, objfile);
+ if (minsym == NULL)
+ {
+ /* Sun Fortran appends an underscore to the minimal symbol name,
+ try again with an appended underscore if the minimal symbol
+ was not found. */
+ p[n] = '_';
+ p[n + 1] = 0;
+ minsym = lookup_minimal_symbol (p, pst->filename, objfile);
+ }
+
+ if (minsym)
+ pst->texthigh = SYMBOL_VALUE_ADDRESS (minsym) + MSYMBOL_SIZE (minsym);
+
+ last_function_name = NULL;
+ }
+
+ /* this test will be true if the last .o file is only data */
+ if (textlow_not_set)
+ pst->textlow = pst->texthigh;
+ else
+ {
+ struct partial_symtab *p1;
+
+ /* 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. */
+
+ 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. */
+#endif /* SOFUN_ADDRESS_MAYBE_MISSING. */
+
+ 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
+ && has_line_numbers == 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. */
+ /* Empty psymtabs happen as a result of header files which don't have
+ any symbols in them. There can be a lot of them. But this check
+ is wrong, in that a psymtab with N_SLINE entries but nothing else
+ is not empty, but we don't realize that. Fixing that without slowing
+ things down might be tricky. */
+
+ discard_psymtab (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_unfiltered (gdb_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 (" ", gdb_stdout);
+ wrap_here ("");
+ fputs_filtered ("and ", gdb_stdout);
+ wrap_here ("");
+ printf_filtered ("%s...", pst->dependencies[i]->filename);
+ wrap_here (""); /* Flush output */
+ gdb_flush (gdb_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 ((make_cleanup_func) 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_unfiltered (gdb_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);
+ gdb_flush (gdb_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 external_nlist *bufp;
+ struct internal_nlist nlist;
+ 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++];
+ INTERNALIZE_SYMBOL (nlist, bufp, abfd);
+ OBJSTAT (objfile, n_stabs++);
+
+ SET_NAMESTRING ();
+
+ processing_gcc_compilation = 0;
+ if (nlist.n_type == N_TEXT)
+ {
+ const char *tempstring = namestring;
+
+ if (STREQ (namestring, GCC_COMPILED_FLAG_SYMBOL))
+ processing_gcc_compilation = 1;
+ else if (STREQ (namestring, GCC2_COMPILED_FLAG_SYMBOL))
+ processing_gcc_compilation = 2;
+ if (tempstring[0] == bfd_get_symbol_leading_char (symfile_bfd))
+ ++tempstring;
+ if (STREQN (tempstring, "__gnu_compiled", 14))
+ 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 (bfd_h_get_8 (abfd, bufp->e_type) != 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++];
+ INTERNALIZE_SYMBOL (nlist, bufp, abfd);
+ OBJSTAT (objfile, n_stabs++);
+
+ type = bfd_h_get_8 (abfd, bufp->e_type);
+
+ SET_NAMESTRING ();
+
+ if (type & N_STAB) {
+ process_one_symbol (type, nlist.n_desc, nlist.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;
+
+ /* In reordered executables last_source_start_addr may not be the
+ lower bound for this symtab, instead use text_offset which comes
+ from pst->textlow which is correct. */
+ if (last_source_start_addr > text_offset)
+ last_source_start_addr = text_offset;
+
+ pst->symtab = end_symtab (text_offset + text_size, objfile, SECT_OFF_TEXT);
+
+ /* Process items which we had to "process_later" due to dependancies
+ on other stabs. */
+ process_now (objfile);
+
+ 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, 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;
+
+ 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,
+ but this should not be an error (). */
+ return;
+ }
+
+ switch (type)
+ {
+ case N_FUN:
+ case N_FNAME:
+
+ if (*name == '\000')
+ {
+ /* This N_FUN marks the end of a function. This closes off the
+ current block. */
+ within_function = 0;
+ new = pop_context ();
+
+ /* Make a block for the local symbols within. */
+ finish_block (new->name, &local_symbols, new->old_blocks,
+ new->start_addr, new->start_addr + valu,
+ objfile);
+
+ /* May be switching to an assembler file which may not be using
+ block relative stabs, so reset the offset. */
+ if (block_address_function_relative)
+ function_start_offset = 0;
+
+ break;
+ }
+
+ /* Relocate for dynamic loading */
+ valu += ANOFFSET (section_offsets, SECT_OFF_TEXT);
+#ifdef SMASH_TEXT_ADDRESS
+ SMASH_TEXT_ADDRESS (valu);
+#endif
+ goto define_a_symbol;
+
+ case N_LBRAC:
+ /* This "symbol" just indicates the start of an inner lexical
+ context within a function. */
+
+ /* Ignore extra outermost context from SunPRO cc and acc. */
+ if (n_opt_found && desc == 1)
+ break;
+
+ 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;
+
+#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. */
+
+ /* Ignore extra outermost context from SunPRO cc and acc. */
+ if (n_opt_found && desc == 1)
+ break;
+
+ 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;
+
+ 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 (context_stack_depth
+ > !VARIABLES_INSIDE_BLOCK(desc, processing_gcc_compilation))
+ {
+ /* 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. Define the block for them (but don't
+ bother if the block contains no symbols. Should we complain
+ on blocks without symbols? I can't think of any useful purpose
+ for them). */
+ if (local_symbols != NULL)
+ {
+ /* Muzzle a compiler bug that makes end < start. (which
+ compilers? Is this ever harmful?). */
+ 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
+ {
+ /* 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. We need to
+ indicate that we just moved outside of the function. */
+ 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, objfile, SECT_OFF_TEXT);
+ end_stabs ();
+ }
+
+ /* Null name means this just marks the end of text for this .o file.
+ Don't start a new symtab in this case. */
+ if (*name == '\000')
+ break;
+
+ if (block_address_function_relative)
+ function_start_offset = 0;
+
+ start_stabs ();
+ start_symtab (name, NULL, valu);
+ record_debugformat ("stabs");
+ 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;
+
+ /* .o files and NLMs have non-zero text seg offsets, but don't need
+ their static syms offset in this fashion. XXX - This is really a
+ crock that should be fixed in the solib handling code so that I
+ don't have to work around it here. */
+
+ if (!symfile_relocatable)
+ {
+ p = strchr (name, ':');
+ if (p != 0 && p[1] == 'S')
+ {
+ /* The linker relocated it. We don't want to add an
+ elfstab_offset_sections-type offset, but we *do* want
+ to add whatever solib.c passed to symbol_file_add as
+ addr (this is known to affect SunOS4, and I suspect ELF
+ too). Since elfstab_offset_sections currently does not
+ muck with the text offset (there is no Ttext.text
+ symbol), we can get addr from the text offset. If
+ elfstab_offset_sections ever starts dealing with the
+ text offset, and we still need to do this, we need to
+ invent a SECT_OFF_ADDR_KLUDGE or something. */
+ valu += ANOFFSET (section_offsets, SECT_OFF_TEXT);
+ 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 (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 SOFUN_ADDRESS_MAYBE_MISSING
+ /* Deal with the SunPRO 3.0 compiler which omits the address
+ from N_FUN symbols. */
+ if (type == N_FUN
+ && valu == ANOFFSET (section_offsets, SECT_OFF_TEXT))
+ {
+ struct minimal_symbol *msym;
+ char *p;
+ int n;
+
+ p = strchr (name, ':');
+ if (p == NULL)
+ p = name;
+ n = p - name;
+ p = alloca (n + 2);
+ strncpy (p, name, n);
+ p[n] = 0;
+
+ msym = lookup_minimal_symbol (p, last_source_file,
+ objfile);
+ if (msym == NULL)
+ {
+ /* Sun Fortran appends an underscore to the minimal
+ symbol name, try again with an appended underscore
+ if the minimal symbol was not found. */
+ p[n] = '_';
+ p[n + 1] = 0;
+ msym = lookup_minimal_symbol (p, last_source_file,
+ objfile);
+ }
+ if (msym)
+ valu = SYMBOL_VALUE_ADDRESS (msym);
+ }
+#endif
+
+#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. */
+
+ /* Starting with release 3.0, the Sun acc compiler,
+ under SunOS4, puts out functions with N_FUN and a value
+ of zero. This gets relocated to the start of the text
+ segment of the module, which is no good either.
+ Under SunOS4 we can deal with this as N_SLINE and N_SO
+ entries contain valid absolute addresses.
+ Release 3.0 acc also puts out N_OPT entries, which makes
+ it possible to discern acc from cc or gcc. */
+
+ if (type == N_GSYM || type == N_STSYM
+ || (type == N_FUN
+ && n_opt_found && !block_address_function_relative))
+ {
+ 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)
+ && SYMBOL_NAME (m) [l] == '\0')
+ /* last_pc_address was in this function */
+ valu = SYMBOL_VALUE (m);
+ else if (m && SYMBOL_NAME (m+1)
+ && STREQN (SYMBOL_NAME (m+1), name, l)
+ && SYMBOL_NAME (m+1) [l] == '\0')
+ /* 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. */
+ case N_ALIAS: /* SunPro F77: alias name, ignore for now. */
+ break;
+ }
+
+ /* '#' is a GNU C extension to allow one symbol to refer to another
+ related symbol.
+
+ Generally this is used so that an alias can refer to its main
+ symbol. */
+ if (name[0] == '#')
+ {
+ /* Initialize symbol reference names and determine if this is
+ a definition. If symbol reference is being defined, go
+ ahead and add it. Otherwise, just return sym. */
+
+ char *s = name;
+ int refnum;
+
+ /* If this stab defines a new reference ID that is not on the
+ reference list, then put it on the reference list.
+
+ We go ahead and advance NAME past the reference, even though
+ it is not strictly necessary at this time. */
+ refnum = symbol_reference_defined (&s);
+ if (refnum >= 0)
+ if (!ref_search (refnum))
+ ref_add (refnum, 0, name, valu);
+ name = s;
+ }
+
+
+ previous_stab_code = type;
+}
+
+/* FIXME: The only difference between this and elfstab_build_psymtabs
+ is the call to install_minimal_symbols for elf, and the support for
+ split sections. 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).
+ TEXTADDR is the address of the text section.
+ TEXTSIZE is the size of the text section.
+ STABSECTS is the list of .stab sections in OBJFILE.
+ 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,
+ textaddr, textsize, stabsects,
+ stabstroffset, stabstrsize)
+ struct objfile *objfile;
+ struct section_offsets *section_offsets;
+ int mainline;
+ CORE_ADDR textaddr;
+ unsigned int textsize;
+ struct stab_section_list *stabsects;
+ 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;
+ unsigned int stabsize;
+
+ /* 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 = objfile->sym_stab_info;
+
+ DBX_TEXT_ADDR (objfile) = textaddr;
+ DBX_TEXT_SIZE (objfile) = textsize;
+
+#define COFF_STABS_SYMBOL_SIZE 12 /* XXX FIXME XXX */
+ DBX_SYMBOL_SIZE (objfile) = COFF_STABS_SYMBOL_SIZE;
+ DBX_STRINGTAB_SIZE (objfile) = stabstrsize;
+
+ 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);
+ OBJSTAT (objfile, sz_strtab += 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. */
+ if (stabsects->next == NULL)
+ {
+ stabsize = bfd_section_size (sym_bfd, stabsects->section);
+ DBX_SYMCOUNT (objfile) = stabsize / DBX_SYMBOL_SIZE (objfile);
+ DBX_SYMTAB_OFFSET (objfile) = stabsects->section->filepos;
+ }
+ else
+ {
+ struct stab_section_list *stabsect;
+
+ DBX_SYMCOUNT (objfile) = 0;
+ for (stabsect = stabsects; stabsect != NULL; stabsect = stabsect->next)
+ {
+ stabsize = bfd_section_size (sym_bfd, stabsect->section);
+ DBX_SYMCOUNT (objfile) += stabsize / DBX_SYMBOL_SIZE (objfile);
+ }
+
+ DBX_SYMTAB_OFFSET (objfile) = stabsects->section->filepos;
+
+ symbuf_sections = stabsects->next;
+ symbuf_left = bfd_section_size (sym_bfd, stabsects->section);
+ symbuf_read = 0;
+ }
+
+ 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;
+ asection *text_sect;
+
+ /* 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 = objfile->sym_stab_info;
+
+ text_sect = bfd_get_section_by_name (sym_bfd, ".text");
+ if (!text_sect)
+ error ("Can't find .text section in symbol file");
+ DBX_TEXT_ADDR (objfile) = bfd_section_vma (sym_bfd, text_sect);
+ DBX_TEXT_SIZE (objfile) = bfd_section_size (sym_bfd, text_sect);
+
+#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);
+ OBJSTAT (objfile, sz_strtab += 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 file with special sections for stabs
+ and stabstrings. The file has already been processed to get its minimal
+ symbols, and any other symbols that might be necessary to resolve GSYMs.
+
+ 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).
+ STAB_NAME is the name of the section that contains the stabs.
+ STABSTR_NAME is the name of the section that contains the stab strings.
+
+ This routine is mostly copied from dbx_symfile_init and dbx_symfile_read. */
+
+void
+stabsect_build_psymtabs (objfile, section_offsets, mainline, stab_name,
+ stabstr_name, text_name)
+ struct objfile *objfile;
+ struct section_offsets *section_offsets;
+ int mainline;
+ char *stab_name;
+ char *stabstr_name;
+ char *text_name;
+{
+ int val;
+ bfd *sym_bfd = objfile->obfd;
+ char *name = bfd_get_filename (sym_bfd);
+ asection *stabsect;
+ asection *stabstrsect;
+ asection *text_sect;
+
+ stabsect = bfd_get_section_by_name (sym_bfd, stab_name);
+ stabstrsect = bfd_get_section_by_name (sym_bfd, stabstr_name);
+
+ if (!stabsect)
+ return;
+
+ if (!stabstrsect)
+ error ("stabsect_build_psymtabs: Found stabs (%s), but not string section (%s)",
+ stab_name, stabstr_name);
+
+ objfile->sym_stab_info = (struct dbx_symfile_info *)
+ xmalloc (sizeof (struct dbx_symfile_info));
+ memset (objfile->sym_stab_info, 0, sizeof (struct dbx_symfile_info));
+
+ text_sect = bfd_get_section_by_name (sym_bfd, text_name);
+ if (!text_sect)
+ error ("Can't find %s section in symbol file", text_name);
+ DBX_TEXT_ADDR (objfile) = bfd_section_vma (sym_bfd, text_sect);
+ DBX_TEXT_SIZE (objfile) = bfd_section_size (sym_bfd, text_sect);
+
+ DBX_SYMBOL_SIZE (objfile) = sizeof (struct external_nlist);
+ DBX_SYMCOUNT (objfile) = bfd_section_size (sym_bfd, stabsect)
+ / DBX_SYMBOL_SIZE (objfile);
+ DBX_STRINGTAB_SIZE (objfile) = bfd_section_size (sym_bfd, stabstrsect);
+ DBX_SYMTAB_OFFSET (objfile) = stabsect->filepos; /* XXX - FIXME: POKING INSIDE BFD DATA STRUCTURES */
+
+ if (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) + 1);
+ OBJSTAT (objfile, sz_strtab += DBX_STRINGTAB_SIZE (objfile) + 1);
+
+ /* Now read in the string table in one big gulp. */
+
+ val = bfd_get_section_contents (sym_bfd, /* bfd */
+ stabstrsect, /* bfd section */
+ DBX_STRINGTAB (objfile), /* input buffer */
+ 0, /* offset into section */
+ DBX_STRINGTAB_SIZE (objfile)); /* amount to read */
+
+ if (!val)
+ perror_with_name (name);
+
+ stabsread_new_init ();
+ buildsym_new_init ();
+ free_header_files ();
+ init_header_files ();
+ install_minimal_symbols (objfile);
+
+ /* Now, do an incremental load */
+
+ processing_acc_compilation = 1;
+ dbx_symfile_read (objfile, section_offsets, 0);
+}
+
+static struct sym_fns aout_sym_fns =
+{
+ bfd_target_aout_flavour,
+ 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 */
+ default_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(&aout_sym_fns);
+}
diff --git a/gdb/dcache.c b/gdb/dcache.c
new file mode 100644
index 00000000000..a97a940a4a6
--- /dev/null
+++ b/gdb/dcache.c
@@ -0,0 +1,558 @@
+/* Caching code. Typically used by remote back ends for
+ caching remote memory.
+
+ Copyright 1992, 1993, 1995, 1998 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "dcache.h"
+#include "gdbcmd.h"
+#include "gdb_string.h"
+#include "gdbcore.h"
+
+/*
+ The data cache could lead to incorrect results because it doesn't know
+ about volatile variables, thus making it impossible to debug
+ functions which use memory mapped I/O devices.
+
+ set remotecache 0
+
+ In those cases.
+
+ In general the dcache speeds up performance, some speed improvement
+ comes from the actual caching mechanism, but the major gain is in
+ the reduction of the remote protocol overhead; instead of reading
+ or writing a large area of memory in 4 byte requests, the cache
+ bundles up the requests into 32 byte (actually LINE_SIZE) chunks.
+ Reducing the overhead to an eighth of what it was. This is very
+ obvious when displaying a large amount of data,
+
+ eg, x/200x 0
+
+ caching | no yes
+ ----------------------------
+ first time | 4 sec 2 sec improvement due to chunking
+ second time | 4 sec 0 sec improvement due to caching
+
+ The cache structure is unusual, we keep a number of cache blocks
+ (DCACHE_SIZE) and each one caches a LINE_SIZEed area of memory.
+ Within each line we remember the address of the line (always a
+ multiple of the LINE_SIZE) and a vector of bytes over the range.
+ There's another vector which contains the state of the bytes.
+
+ ENTRY_BAD means that the byte is just plain wrong, and has no
+ correspondence with anything else (as it would when the cache is
+ turned on, but nothing has been done to it.
+
+ ENTRY_DIRTY means that the byte has some data in it which should be
+ written out to the remote target one day, but contains correct
+ data. ENTRY_OK means that the data is the same in the cache as it
+ is in remote memory.
+
+
+ The ENTRY_DIRTY state is necessary because GDB likes to write large
+ lumps of memory in small bits. If the caching mechanism didn't
+ maintain the DIRTY information, then something like a two byte
+ write would mean that the entire cache line would have to be read,
+ the two bytes modified and then written out again. The alternative
+ would be to not read in the cache line in the first place, and just
+ write the two bytes directly into target memory. The trouble with
+ that is that it really nails performance, because of the remote
+ protocol overhead. This way, all those little writes are bundled
+ up into an entire cache line write in one go, without having to
+ read the cache line in the first place.
+
+
+ */
+
+
+/* This value regulates the number of cache blocks stored.
+ Smaller values reduce the time spent searching for a cache
+ line, and reduce memory requirements, but increase the risk
+ of a line not being in memory */
+
+#define DCACHE_SIZE 64
+
+/* This value regulates the size of a cache line. Smaller values
+ reduce the time taken to read a single byte, but reduce overall
+ throughput. */
+
+#define LINE_SIZE_POWER (5)
+#define LINE_SIZE (1 << LINE_SIZE_POWER)
+
+/* Each cache block holds LINE_SIZE bytes of data
+ starting at a multiple-of-LINE_SIZE address. */
+
+#define LINE_SIZE_MASK ((LINE_SIZE - 1))
+#define XFORM(x) ((x) & LINE_SIZE_MASK)
+#define MASK(x) ((x) & ~LINE_SIZE_MASK)
+
+
+#define ENTRY_BAD 0 /* data at this byte is wrong */
+#define ENTRY_DIRTY 1 /* data at this byte needs to be written back */
+#define ENTRY_OK 2 /* data at this byte is same as in memory */
+
+
+struct dcache_block
+{
+ struct dcache_block *p; /* next in list */
+ CORE_ADDR addr; /* Address for which data is recorded. */
+ char data[LINE_SIZE]; /* bytes at given address */
+ unsigned char state[LINE_SIZE]; /* what state the data is in */
+
+ /* whether anything in state is dirty - used to speed up the
+ dirty scan. */
+ int anydirty;
+
+ int refs;
+};
+
+
+struct dcache_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 *free_head;
+ struct dcache_block *free_tail;
+
+ /* in use list */
+ struct dcache_block *valid_head;
+ struct dcache_block *valid_tail;
+
+ /* The cache itself. */
+ struct dcache_block *the_cache;
+
+ /* potentially, if the cache was enabled, and then turned off, and
+ then turned on again, the stuff in it could be stale, so this is
+ used to mark it */
+ int cache_has_stuff;
+} ;
+
+static int dcache_poke_byte PARAMS ((DCACHE *dcache, CORE_ADDR addr,
+ char *ptr));
+
+static int dcache_peek_byte PARAMS ((DCACHE *dcache, CORE_ADDR addr,
+ char *ptr));
+
+static struct dcache_block *dcache_hit PARAMS ((DCACHE *dcache,
+ CORE_ADDR addr));
+
+static int dcache_write_line PARAMS ((DCACHE *dcache,struct dcache_block *db));
+
+static struct dcache_block *dcache_alloc PARAMS ((DCACHE *dcache));
+
+static int dcache_writeback PARAMS ((DCACHE *dcache));
+
+static void dcache_info PARAMS ((char *exp, int tty));
+
+void _initialize_dcache PARAMS ((void));
+
+int remote_dcache = 0;
+
+DCACHE *last_cache; /* Used by info dcache */
+
+
+/* Free all the data cache blocks, thus discarding all cached data. */
+
+void
+dcache_flush (dcache)
+ DCACHE *dcache;
+{
+ int i;
+ dcache->valid_head = 0;
+ dcache->valid_tail = 0;
+
+ dcache->free_head = 0;
+ dcache->free_tail = 0;
+
+ for (i = 0; i < DCACHE_SIZE; i++)
+ {
+ struct dcache_block *db = dcache->the_cache + i;
+
+ if (!dcache->free_head)
+ dcache->free_head = db;
+ else
+ dcache->free_tail->p = db;
+ dcache->free_tail = db;
+ db->p = 0;
+ }
+
+ dcache->cache_has_stuff = 0;
+
+ 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;
+ CORE_ADDR addr;
+{
+ register struct dcache_block *db;
+
+ /* Search all cache blocks for one that is at this address. */
+ db = dcache->valid_head;
+
+ while (db)
+ {
+ if (MASK(addr) == db->addr)
+ {
+ db->refs++;
+ return db;
+ }
+ db = db->p;
+ }
+
+ return NULL;
+}
+
+/* Make sure that anything in this line which needs to
+ be written is. */
+
+static int
+dcache_write_line (dcache, db)
+ DCACHE *dcache;
+ register struct dcache_block *db;
+{
+ int s;
+ int e;
+ s = 0;
+ if (db->anydirty)
+ {
+ for (s = 0; s < LINE_SIZE; s++)
+ {
+ if (db->state[s] == ENTRY_DIRTY)
+ {
+ int len = 0;
+ for (e = s ; e < LINE_SIZE; e++, len++)
+ if (db->state[e] != ENTRY_DIRTY)
+ break;
+ {
+ /* all bytes from s..s+len-1 need to
+ be written out */
+ int done = 0;
+ while (done < len) {
+ int t = dcache->write_memory (db->addr + s + done,
+ db->data + s + done,
+ len - done);
+ if (t == 0)
+ return 0;
+ done += t;
+ }
+ memset (db->state + s, ENTRY_OK, len);
+ s = e;
+ }
+ }
+ }
+ db->anydirty = 0;
+ }
+ return 1;
+}
+
+
+/* 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 ();
+
+ /* Take something from the free list */
+ db = dcache->free_head;
+ if (db)
+ {
+ dcache->free_head = db->p;
+ }
+ else
+ {
+ /* Nothing left on free list, so grab one from the valid list */
+ db = dcache->valid_head;
+ dcache->valid_head = db->p;
+
+ dcache_write_line (dcache, db);
+ }
+
+ /* append this line to end of valid list */
+ if (!dcache->valid_head)
+ dcache->valid_head = db;
+ else
+ dcache->valid_tail->p = db;
+ dcache->valid_tail = db;
+ db->p = 0;
+
+ return db;
+}
+
+/* Using the data cache DCACHE return the contents of the byte at
+ address ADDR in the remote machine.
+
+ Returns 0 on error. */
+
+static int
+dcache_peek_byte (dcache, addr, ptr)
+ DCACHE *dcache;
+ CORE_ADDR addr;
+ char *ptr;
+{
+ register struct dcache_block *db = dcache_hit (dcache, addr);
+ int ok=1;
+ int done = 0;
+ if (db == 0
+ || db->state[XFORM (addr)] == ENTRY_BAD)
+ {
+ if (db)
+ {
+ dcache_write_line (dcache, db);
+ }
+ else
+ db = dcache_alloc (dcache);
+ immediate_quit++;
+ db->addr = MASK (addr);
+ while (done < LINE_SIZE)
+ {
+ int try =
+ (*dcache->read_memory)
+ (db->addr + done,
+ db->data + done,
+ LINE_SIZE - done);
+ if (try == 0)
+ return 0;
+ done += try;
+ }
+ immediate_quit--;
+
+ memset (db->state, ENTRY_OK, sizeof (db->data));
+ db->anydirty = 0;
+ }
+ *ptr = db->data[XFORM (addr)];
+ return ok;
+}
+
+/* Writeback any dirty lines to the remote. */
+static int
+dcache_writeback (dcache)
+ DCACHE *dcache;
+{
+ struct dcache_block *db;
+
+ db = dcache->valid_head;
+
+ while (db)
+ {
+ if (!dcache_write_line (dcache, db))
+ return 0;
+ db = db->p;
+ }
+ return 1;
+}
+
+
+/* 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;
+{
+ int res;
+
+ if (dcache_xfer_memory (dcache, addr, (char *)&res, sizeof res, 0) != sizeof res)
+ memory_error (EIO, addr);
+
+ return res;
+}
+
+
+/* Write the byte at PTR into ADDR in the data cache.
+ Return zero on write error.
+ */
+
+static int
+dcache_poke_byte (dcache, addr, ptr)
+ DCACHE *dcache;
+ CORE_ADDR addr;
+ char *ptr;
+{
+ register struct dcache_block *db = dcache_hit (dcache, addr);
+
+ if (!db)
+ {
+ db = dcache_alloc (dcache);
+ db->addr = MASK (addr);
+ memset (db->state, ENTRY_BAD, sizeof (db->data));
+ }
+
+ db->data[XFORM (addr)] = *ptr;
+ db->state[XFORM (addr)] = ENTRY_DIRTY;
+ db->anydirty = 1;
+ return 1;
+}
+
+/* Write the word at ADDR both in the data cache and in the remote machine.
+ Return zero on write error.
+ */
+
+int
+dcache_poke (dcache, addr, data)
+ DCACHE *dcache;
+ CORE_ADDR addr;
+ int data;
+{
+ if (dcache_xfer_memory (dcache, addr, (char *)&data, sizeof data, 1) != sizeof data)
+ return 0;
+
+ return dcache_writeback (dcache);
+}
+
+
+/* Initialize the data cache. */
+DCACHE *
+dcache_init (reading, writing)
+ memxferfunc reading;
+ memxferfunc writing;
+{
+ int csize = sizeof (struct dcache_block) * DCACHE_SIZE;
+ DCACHE *dcache;
+
+ dcache = (DCACHE *) xmalloc (sizeof (*dcache));
+ dcache->read_memory = reading;
+ dcache->write_memory = writing;
+
+ dcache->the_cache = (struct dcache_block *) xmalloc (csize);
+ memset (dcache->the_cache, 0, csize);
+
+ dcache_flush (dcache);
+
+ last_cache = dcache;
+ return dcache;
+}
+
+/* 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.
+
+ This routine is indended to be called by remote_xfer_ functions. */
+
+int
+dcache_xfer_memory (dcache, memaddr, myaddr, len, should_write)
+ DCACHE *dcache;
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+ int should_write;
+{
+ int i;
+
+ if (remote_dcache)
+ {
+ int (*xfunc) PARAMS ((DCACHE *dcache, CORE_ADDR addr, char *ptr));
+ xfunc = should_write ? dcache_poke_byte : dcache_peek_byte;
+
+ for (i = 0; i < len; i++)
+ {
+ if (!xfunc (dcache, memaddr + i, myaddr + i))
+ return 0;
+ }
+ dcache->cache_has_stuff = 1;
+ dcache_writeback (dcache);
+ }
+ else
+ {
+ memxferfunc xfunc;
+ xfunc = should_write ? dcache->write_memory : dcache->read_memory;
+
+ if (dcache->cache_has_stuff)
+ dcache_flush (dcache);
+
+ len = xfunc (memaddr, myaddr, len);
+ }
+ return len;
+}
+
+static void
+dcache_info (exp, tty)
+ char *exp;
+ int tty;
+{
+ struct dcache_block *p;
+
+ if (!remote_dcache)
+ {
+ printf_filtered ("Dcache not enabled\n");
+ return;
+ }
+ printf_filtered ("Dcache enabled, line width %d, depth %d\n",
+ LINE_SIZE, DCACHE_SIZE);
+
+ printf_filtered ("Cache state:\n");
+
+ for (p = last_cache->valid_head; p; p = p->p)
+ {
+ int j;
+ printf_filtered ("Line at %08xd, referenced %d times\n",
+ p->addr, p->refs);
+
+ for (j = 0; j < LINE_SIZE; j++)
+ printf_filtered ("%02x", p->data[j] & 0xFF);
+ printf_filtered ("\n");
+
+ for (j = 0; j < LINE_SIZE; j++)
+ printf_filtered (" %2x", p->state[j]);
+ printf_filtered ("\n");
+ }
+}
+
+void
+_initialize_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 on.",
+ &setlist),
+ &showlist);
+
+ add_info ("dcache", dcache_info,
+ "Print information on the dcache performance.");
+
+}
diff --git a/gdb/dcache.h b/gdb/dcache.h
new file mode 100644
index 00000000000..a0b762a2e13
--- /dev/null
+++ b/gdb/dcache.h
@@ -0,0 +1,50 @@
+/* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef DCACHE_H
+#define DCACHE_H
+
+typedef int (*memxferfunc) PARAMS((CORE_ADDR memaddr,
+ char *myaddr,
+ int len));
+
+typedef struct dcache_struct 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. */
+int dcache_poke PARAMS((DCACHE *dcache, CORE_ADDR addr, int data));
+
+/* Simple to call from <remote>_xfer_memory */
+
+int dcache_xfer_memory PARAMS((DCACHE *cache, CORE_ADDR mem, char *my, int len, int should_write));
+
+/* Write the bytes at ADDR into the data cache and the remote machine. */
+int dcache_poke_block PARAMS((DCACHE *cache, CORE_ADDR mem, char* my, int len));
+#endif /* DCACHE_H */
diff --git a/gdb/debugify.c b/gdb/debugify.c
new file mode 100644
index 00000000000..841b5891394
--- /dev/null
+++ b/gdb/debugify.c
@@ -0,0 +1,109 @@
+
+/* Debug macros for developemnt.
+ Copyright 1997
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define DEBUGIFY
+#include "debugify.h"
+#include "config.h"
+
+#include <stdio.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#else
+#include <strings.h>
+#endif
+
+#define REDIRECT
+
+static FILE *fout = NULL;
+static char fname[128];
+static int file_cnt = 0; /* count number of open files */
+
+void
+puts_dbg (data)
+ const char *data;
+{
+ FILE *fdbg;
+
+ fdbg = fopen ("dbg.log", "a+");
+ if (fdbg == NULL)
+ return;
+ fprintf (fdbg, data);
+ fclose (fdbg);
+}
+
+/* Can't easily get the message back to gdb... write to a log instead. */
+void
+fputs_dbg (data, fakestream)
+ const char *data;
+ FILE *fakestream;
+{
+#ifdef REDIRECT
+ puts_dbg (data);
+#else /* REDIRECT */
+
+ if (fakestream == stdout || fakestream == stderr || fakestream == NULL)
+ {
+ if (fout == NULL)
+ {
+ for (file_cnt = 0; file_cnt < 20; file_cnt++)
+ {
+ sprintf (fname, "dbg%d.log", file_cnt);
+ if ((fout = fopen (fname), "r") != NULL)
+ fclose (fout);
+ else
+ break;
+ }
+ fout = fopen (fname, "w");
+ if (fout == NULL)
+ return;
+ }
+ fakestream = fout;
+ }
+ fprintf (fakestream, data);
+ fflush (fakestream);
+#endif /* REDIRECT */
+}
+
+void
+#ifdef ANSI_PROTOTYPES
+printf_dbg (const char *format,...)
+#else
+printf_dbg (va_alist)
+ va_dcl
+#endif
+{
+ va_list args;
+ char buf[256];
+#ifdef ANSI_PROTOTYPES
+ va_start (args, format);
+#else
+ char *format;
+
+ va_start (args);
+ format = va_arg (args, char *);
+#endif
+ vsprintf (buf, format, args);
+ puts_dbg (buf);
+ va_end (args);
+}
diff --git a/gdb/debugify.h b/gdb/debugify.h
new file mode 100644
index 00000000000..b4ae92bc93b
--- /dev/null
+++ b/gdb/debugify.h
@@ -0,0 +1,83 @@
+
+/* Debug macros for development.
+ Copyright 1997
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef _DEBUGIFY_H_
+#define _DEBUGIFY_H_
+
+#include "ansidecl.h"
+
+#ifdef ANSI_PROTOTYPES
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+
+#ifdef DEBUGIFY
+#include <assert.h>
+#ifdef TO_SCREEN
+#ifdef _Win32
+#define DBG(x) OutputDebugString x
+#else
+#define DBG(x) printf x
+#endif
+#elif TO_GDB
+#define DBG(x) printf_unfiltered x
+#elif TO_POPUP
+#ifdef _Win32
+#define DBG(x) MessageBox x
+#else
+#define DBG(x) printf x
+#endif
+#else /* default: TO_FILE "gdb.log" */
+#define DBG(x) printf_dbg x
+#endif
+
+#define ASSERT(x) assert(x)
+
+#else /* DEBUGIFY */
+#define DBG(x)
+#define ASSERT(x)
+#endif
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#ifdef REDIRECT
+#define printf_unfiltered printf_dbg
+#define fputs_unfiltered fputs_dbg
+ extern void fputs_dbg PARAMS ((const char *fmt, FILE * fakestream));
+#endif /* REDIRECT */
+
+ extern void puts_dbg PARAMS ((const char *fmt));
+#ifdef ANSI_PROTOTYPES
+ extern void printf_dbg PARAMS ((const char *fmt,...));
+#else
+ extern void printf_dbg PARAMS ((va_alist va_dcl));
+#endif
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _DEBUGIFY_H_ */
diff --git a/gdb/defs.h b/gdb/defs.h
new file mode 100644
index 00000000000..c0552a17284
--- /dev/null
+++ b/gdb/defs.h
@@ -0,0 +1,1139 @@
+/* Basic, host-specific, and target-specific definitions for GDB.
+ Copyright (C) 1986, 89, 91, 92, 93, 94, 95, 96, 98, 1999
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef DEFS_H
+#define DEFS_H
+
+#include "config.h" /* Generated by configure */
+#include <stdio.h>
+#include <errno.h> /* System call error return status */
+#include <limits.h>
+
+#ifdef HAVE_STDDEF_H
+# include <stddef.h>
+#else
+# include <sys/types.h> /* for size_t */
+#endif
+
+/* Just in case they're not defined in stdio.h. */
+
+#ifndef SEEK_SET
+#define SEEK_SET 0
+#endif
+#ifndef SEEK_CUR
+#define SEEK_CUR 1
+#endif
+
+/* First include ansidecl.h so we can use the various macro definitions
+ here and in all subsequent file inclusions. */
+
+#include "ansidecl.h"
+
+#ifdef ANSI_PROTOTYPES
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+
+#include "libiberty.h"
+
+/* libiberty.h can't declare this one, but evidently we can. */
+extern char *strsignal PARAMS ((int));
+
+#include "progress.h"
+
+#ifdef USE_MMALLOC
+#include "mmalloc.h"
+#endif
+
+/* For BFD64 and bfd_vma. */
+#include "bfd.h"
+
+/* An address in the program being debugged. Host byte order. Rather
+ than duplicate all the logic in BFD which figures out what type
+ this is (long, long long, etc.) and whether it needs to be 64
+ bits (the host/target interactions are subtle), we just use
+ bfd_vma. */
+
+typedef bfd_vma CORE_ADDR;
+
+#ifndef min
+#define min(a, b) ((a) < (b) ? (a) : (b))
+#endif
+#ifndef max
+#define max(a, b) ((a) > (b) ? (a) : (b))
+#endif
+
+/* 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 */
+
+/* Check if a character is one of the commonly used C++ marker characters. */
+extern int is_cplus_marker PARAMS ((int));
+
+/* use tui interface if non-zero */
+extern int tui_version;
+
+#if defined(TUI)
+/* all invocations of TUIDO should have two sets of parens */
+#define TUIDO(x) tuiDo x
+#else
+#define TUIDO(x)
+#endif
+
+/* enable xdb commands if set */
+extern int xdb_commands;
+
+/* enable dbx commands if set */
+extern int dbx_commands;
+
+extern int quit_flag;
+extern int immediate_quit;
+extern int sevenbit_strings;
+
+extern void quit PARAMS ((void));
+
+#ifdef QUIT
+/* do twice to force compiler warning */
+#define QUIT_FIXME "FIXME"
+#define QUIT_FIXME "ignoring redefinition of QUIT"
+#else
+#define QUIT { \
+ if (quit_flag) quit (); \
+ if (interactive_hook) interactive_hook (); \
+ PROGRESS (1); \
+}
+#endif
+
+/* 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_trace,
+ class_alias, class_obscure, class_user, class_maintenance,
+ class_pseudo, class_tui, class_xdb
+};
+
+/* 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_java, /* Java */
+ language_chill, /* Chill */
+ language_fortran, /* Fortran */
+ language_m2, /* Modula-2 */
+ language_asm, /* Assembly language */
+ language_scm /* Scheme / Guile */
+};
+
+enum precision_type
+{
+ single_precision,
+ double_precision,
+ unspecified_precision
+};
+
+/* 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;
+};
+
+
+/* The ability to declare that a function never returns is useful, but
+ not really required to compile GDB successfully, so the NORETURN and
+ ATTR_NORETURN macros normally expand into nothing. */
+
+/* If compiling with older versions of GCC, a function may be declared
+ "volatile" to indicate that it does not return. */
+
+#ifndef NORETURN
+# if defined(__GNUC__) \
+ && (__GNUC__ == 1 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7))
+# define NORETURN volatile
+# else
+# define NORETURN /* nothing */
+# endif
+#endif
+
+/* GCC 2.5 and later versions define a function attribute "noreturn",
+ which is the preferred way to declare that a function never returns.
+ However GCC 2.7 appears to be the first version in which this fully
+ works everywhere we use it. */
+
+#ifndef ATTR_NORETURN
+# if defined(__GNUC__) && __GNUC__ >= 2 && __GNUC_MINOR__ >= 7
+# define ATTR_NORETURN __attribute__ ((noreturn))
+# else
+# define ATTR_NORETURN /* nothing */
+# endif
+#endif
+
+#ifndef ATTR_FORMAT
+# if defined(__GNUC__) && __GNUC__ >= 2 && __GNUC_MINOR__ >= 4 && defined (__ANSI_PROTOTYPES)
+# define ATTR_FORMAT(type, x, y) __attribute__ ((format(type, x, y)))
+# else
+# define ATTR_FORMAT(type, x, y) /* nothing */
+# endif
+#endif
+
+/* Needed for various prototypes */
+
+#ifdef __STDC__
+struct symtab;
+struct breakpoint;
+#endif
+
+/* 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 utils.c */
+
+extern void notice_quit PARAMS ((void));
+
+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 do_final_cleanups PARAMS ((struct cleanup *));
+extern void do_my_cleanups PARAMS ((struct cleanup **, struct cleanup *));
+extern void do_run_cleanups PARAMS ((struct cleanup *));
+
+extern void discard_cleanups PARAMS ((struct cleanup *));
+extern void discard_final_cleanups PARAMS ((struct cleanup *));
+extern void discard_my_cleanups PARAMS ((struct cleanup **, struct cleanup *));
+
+typedef void (*make_cleanup_func) PARAMS ((void *));
+
+extern struct cleanup *make_cleanup PARAMS ((make_cleanup_func, void *));
+
+extern struct cleanup *make_final_cleanup PARAMS ((make_cleanup_func, void *));
+
+extern struct cleanup *make_my_cleanup PARAMS ((struct cleanup **,
+ make_cleanup_func, void *));
+
+extern struct cleanup *make_run_cleanup PARAMS ((make_cleanup_func, void *));
+
+extern struct cleanup *save_cleanups PARAMS ((void));
+extern struct cleanup *save_final_cleanups PARAMS ((void));
+extern struct cleanup *save_my_cleanups PARAMS ((struct cleanup **));
+
+extern void restore_cleanups PARAMS ((struct cleanup *));
+extern void restore_final_cleanups PARAMS ((struct cleanup *));
+extern void restore_my_cleanups PARAMS ((struct cleanup **, struct cleanup *));
+
+extern void free_current_contents PARAMS ((char **));
+
+extern void null_cleanup PARAMS ((PTR));
+
+extern int myread PARAMS ((int, char *, int));
+
+extern int query PARAMS((char *, ...))
+ ATTR_FORMAT(printf, 1, 2);
+
+#if !defined (USE_MMALLOC)
+extern PTR mmalloc PARAMS ((PTR, size_t));
+extern PTR mrealloc PARAMS ((PTR, PTR, size_t));
+extern void mfree PARAMS ((PTR, PTR));
+#endif
+
+/* From demangle.c */
+
+extern void set_demangling_style PARAMS ((char *));
+
+/* From tm.h */
+
+struct type;
+typedef int (use_struct_convention_fn) PARAMS ((int gcc_p, struct type *value_type));
+extern use_struct_convention_fn generic_use_struct_convention;
+
+typedef unsigned char *(breakpoint_from_pc_fn) PARAMS ((CORE_ADDR *pcptr, int *lenptr));
+
+
+
+/* Annotation stuff. */
+
+extern int annotation_level; /* in stack.c */
+
+extern void begin_line PARAMS ((void));
+
+extern void wrap_here PARAMS ((char *));
+
+extern void reinitialize_more_filter PARAMS ((void));
+
+/* new */
+enum streamtype
+{
+ afile,
+ astring
+};
+
+/* new */
+typedef struct tui_stream
+{
+ enum streamtype ts_streamtype;
+ FILE *ts_filestream;
+ char *ts_strbuf;
+ int ts_buflen;
+} GDB_FILE;
+
+extern GDB_FILE *gdb_stdout;
+extern GDB_FILE *gdb_stderr;
+
+#if 0
+typedef FILE GDB_FILE;
+#define gdb_stdout stdout
+#define gdb_stderr stderr
+#endif
+
+#if defined(TUI)
+#include "tui.h"
+#include "tuiCommand.h"
+#include "tuiData.h"
+#include "tuiIO.h"
+#include "tuiLayout.h"
+#include "tuiWin.h"
+#endif
+
+extern void gdb_fclose PARAMS ((GDB_FILE **));
+
+extern void gdb_flush PARAMS ((GDB_FILE *));
+
+extern GDB_FILE *gdb_fopen PARAMS ((char * name, char * mode));
+
+extern void fputs_filtered PARAMS ((const char *, GDB_FILE *));
+
+extern void fputs_unfiltered PARAMS ((const char *, GDB_FILE *));
+
+extern int fputc_filtered PARAMS ((int c, GDB_FILE *));
+
+extern int fputc_unfiltered PARAMS ((int c, GDB_FILE *));
+
+extern int putchar_unfiltered PARAMS ((int c));
+
+extern void puts_filtered PARAMS ((const char *));
+
+extern void puts_unfiltered PARAMS ((const char *));
+
+extern void puts_debug PARAMS ((char *prefix, char *string, char *suffix));
+
+extern void vprintf_filtered PARAMS ((const char *, va_list))
+ ATTR_FORMAT(printf, 1, 0);
+
+extern void vfprintf_filtered PARAMS ((GDB_FILE *, const char *, va_list))
+ ATTR_FORMAT(printf, 2, 0);
+
+extern void fprintf_filtered PARAMS ((GDB_FILE *, const char *, ...))
+ ATTR_FORMAT(printf, 2, 3);
+
+extern void fprintfi_filtered PARAMS ((int, GDB_FILE *, const char *, ...))
+ ATTR_FORMAT(printf, 3, 4);
+
+extern void printf_filtered PARAMS ((const char *, ...))
+ ATTR_FORMAT(printf, 1, 2);
+
+extern void printfi_filtered PARAMS ((int, const char *, ...))
+ ATTR_FORMAT(printf, 2, 3);
+
+extern void vprintf_unfiltered PARAMS ((const char *, va_list))
+ ATTR_FORMAT(printf, 1, 0);
+
+extern void vfprintf_unfiltered PARAMS ((GDB_FILE *, const char *, va_list))
+ ATTR_FORMAT(printf, 2, 0);
+
+extern void fprintf_unfiltered PARAMS ((GDB_FILE *, const char *, ...))
+ ATTR_FORMAT(printf, 2, 3);
+
+extern void printf_unfiltered PARAMS ((const char *, ...))
+ ATTR_FORMAT(printf, 1, 2);
+
+extern int gdb_file_isatty PARAMS ((GDB_FILE *));
+
+extern GDB_FILE *gdb_file_init_astring PARAMS ((int));
+
+extern void gdb_file_deallocate PARAMS ((GDB_FILE **));
+
+extern char *gdb_file_get_strbuf PARAMS ((GDB_FILE *));
+
+extern void gdb_file_adjust_strbuf PARAMS ((int, GDB_FILE *));
+
+extern void print_spaces PARAMS ((int, GDB_FILE *));
+
+extern void print_spaces_filtered PARAMS ((int, GDB_FILE *));
+
+extern char *n_spaces PARAMS ((int));
+
+extern void gdb_printchar PARAMS ((int, GDB_FILE *, int));
+
+extern void gdb_print_address PARAMS ((void *, GDB_FILE *));
+
+typedef bfd_vma t_addr;
+typedef bfd_vma t_reg;
+extern char* paddr PARAMS ((t_addr addr));
+
+extern char* preg PARAMS ((t_reg reg));
+
+extern char* paddr_nz PARAMS ((t_addr addr));
+
+extern char* preg_nz PARAMS ((t_reg reg));
+
+extern void fprintf_symbol_filtered PARAMS ((GDB_FILE *, char *,
+ enum language, int));
+
+extern NORETURN void perror_with_name PARAMS ((char *)) ATTR_NORETURN;
+
+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 top.c */
+
+extern char *skip_quoted PARAMS ((char *));
+
+extern char *gdb_readline PARAMS ((char *));
+
+extern char *command_line_input PARAMS ((char *, int, char *));
+
+extern void print_prompt PARAMS ((void));
+
+extern int input_from_terminal_p PARAMS ((void));
+
+extern int info_verbose;
+
+/* From printcmd.c */
+
+extern void set_next_address PARAMS ((CORE_ADDR));
+
+extern void print_address_symbolic PARAMS ((CORE_ADDR, GDB_FILE *, int,
+ char *));
+
+extern void print_address_numeric PARAMS ((CORE_ADDR, int, GDB_FILE *));
+
+extern void print_address PARAMS ((CORE_ADDR, GDB_FILE *));
+
+/* From source.c */
+
+extern int openp PARAMS ((char *, int, char *, int, int, char **));
+
+extern int source_full_path_of PARAMS ((char *, char **));
+
+extern void mod_path PARAMS ((char *, char **));
+
+extern void directory_command PARAMS ((char *, int));
+
+extern void init_source_path PARAMS ((void));
+
+extern char *symtab_to_filename PARAMS ((struct symtab *));
+
+/* 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 *));
+
+/* Control types for commands */
+
+enum misc_command_type
+{
+ ok_command,
+ end_command,
+ else_command,
+ nop_command
+};
+
+enum command_control_type
+{
+ simple_control,
+ break_control,
+ continue_control,
+ while_control,
+ if_control,
+ invalid_control
+};
+
+/* Structure for saved commands lines
+ (for breakpoints, defined commands, etc). */
+
+struct command_line
+{
+ struct command_line *next;
+ char *line;
+ enum command_control_type control_type;
+ int body_count;
+ struct command_line **body_list;
+};
+
+extern struct command_line *read_command_lines PARAMS ((char *, int));
+
+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"
+
+/* Target machine definition. This will be a symlink to one of the
+ tm-*.h files, built by the `configure' script. */
+
+#include "tm.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
+
+/* Microsoft C can't deal with const pointers */
+
+#ifdef _MSC_VER
+#define CONST_PTR
+#else
+#define CONST_PTR const
+#endif
+
+/*
+ * Allow things in gdb to be declared "volatile". If compiling ANSI, it
+ * just works. If compiling with gcc but non-ansi, redefine to __volatile__.
+ * If non-ansi, non-gcc, then eliminate "volatile" entirely, making those
+ * objects be read-write rather than read-only.
+ */
+
+#ifndef volatile
+#ifndef __STDC__
+# ifdef __GNUC__
+# define volatile __volatile__
+# else
+# define volatile /*nothing*/
+# endif /* GNUC */
+#endif /* STDC */
+#endif /* volatile */
+
+/* Defaults for system-wide constants (if not defined by xm.h, we fake it).
+ FIXME: Assumes 2's complement arithmetic */
+
+#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)((int) ~0 ^ INT_MAX)) /* 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
+
+#ifndef LONGEST
+
+#ifdef BFD64
+
+/* This is to make sure that LONGEST is at least as big as CORE_ADDR. */
+
+#define LONGEST BFD_HOST_64_BIT
+#define ULONGEST BFD_HOST_U_64_BIT
+
+#else /* No BFD64 */
+
+# ifdef CC_HAS_LONG_LONG
+# define LONGEST long long
+# define ULONGEST unsigned long long
+# else
+/* BFD_HOST_64_BIT is defined for some hosts that don't have long long
+ (e.g. i386-windows) so try it. */
+# ifdef BFD_HOST_64_BIT
+# define LONGEST BFD_HOST_64_BIT
+# define ULONGEST BFD_HOST_U_64_BIT
+# else
+# define LONGEST long
+# define ULONGEST unsigned long
+# endif
+# endif
+
+#endif /* No BFD64 */
+
+#endif /* ! LONGEST */
+
+/* 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. */
+
+extern int longest_to_int PARAMS ((LONGEST));
+
+/* 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 *));
+
+#ifdef _MSC_VER /* FIXME; was long, but this causes compile errors in msvc if already defined */
+extern PTR xmmalloc PARAMS ((PTR, size_t));
+
+extern PTR xmrealloc PARAMS ((PTR, PTR, size_t));
+#else
+extern PTR xmmalloc PARAMS ((PTR, long));
+
+extern PTR xmrealloc PARAMS ((PTR, PTR, long));
+#endif
+
+extern int parse_escape PARAMS ((char **));
+
+/* compat - handle old targets that just define REGISTER_NAMES */
+#ifndef REGISTER_NAME
+extern char *gdb_register_names[];
+#define REGISTER_NAME(i) gdb_register_names[i]
+#endif
+
+/* Message to be printed before the error message, when an error occurs. */
+
+extern char *error_pre_print;
+
+/* Message to be printed before the error message, when an error occurs. */
+
+extern char *quit_pre_print;
+
+/* Message to be printed before the warning message, when a warning occurs. */
+
+extern char *warning_pre_print;
+
+extern NORETURN void error PARAMS((const char *, ...)) ATTR_NORETURN;
+
+extern void error_begin PARAMS ((void));
+
+extern NORETURN void fatal PARAMS((char *, ...)) ATTR_NORETURN;
+
+extern NORETURN void nomem PARAMS ((long)) ATTR_NORETURN;
+
+/* 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
+return_to_top_level PARAMS ((enum return_reason)) ATTR_NORETURN;
+
+typedef int (catch_errors_ftype) PARAMS ((PTR));
+extern int catch_errors PARAMS ((catch_errors_ftype *, PTR, char *, return_mask));
+
+extern void warning_begin PARAMS ((void));
+
+extern void warning PARAMS ((const char *, ...))
+ ATTR_FORMAT(printf, 1, 2);
+
+/* Global functions from other, non-gdb GNU thingies.
+ Libiberty thingies are no longer declared here. We include libiberty.h
+ above, instead. */
+
+#ifndef GETENV_PROVIDED
+extern char *getenv PARAMS ((const char *));
+#endif
+
+/* From other system libraries */
+
+#ifdef HAVE_STDDEF_H
+#include <stddef.h>
+#endif
+
+#ifdef HAVE_STDLIB_H
+#if defined(_MSC_VER) && !defined(__cplusplus)
+/* msvc defines these in stdlib.h for c code */
+#undef min
+#undef max
+#endif
+#include <stdlib.h>
+#endif
+#ifndef min
+#define min(a, b) ((a) < (b) ? (a) : (b))
+#endif
+#ifndef max
+#define max(a, b) ((a) > (b) ? (a) : (b))
+#endif
+
+
+/* We take the address of fclose later, but some stdio's forget
+ to declare this. We can't always declare it since there's
+ no way to declare the parameters without upsetting some compiler
+ somewhere. */
+
+#ifndef FCLOSE_PROVIDED
+extern int fclose PARAMS ((FILE *));
+#endif
+
+#ifndef atof
+extern double atof PARAMS ((const char *)); /* X3.159-1989 4.10.1.1 */
+#endif
+
+#ifndef MALLOC_INCOMPATIBLE
+
+#ifdef NEED_DECLARATION_MALLOC
+extern PTR malloc ();
+#endif
+
+#ifdef NEED_DECLARATION_REALLOC
+extern PTR realloc ();
+#endif
+
+#ifdef NEED_DECLARATION_FREE
+extern void free ();
+#endif
+
+#endif /* MALLOC_INCOMPATIBLE */
+
+/* Various possibilities for alloca. */
+#ifndef alloca
+# ifdef __GNUC__
+# define alloca __builtin_alloca
+# else /* Not GNU C */
+# ifdef HAVE_ALLOCA_H
+# include <alloca.h>
+# else
+# ifdef _AIX
+ #pragma alloca
+# else
+
+/* We need to be careful not to declare this in a way which conflicts with
+ bison. Bison never declares it as char *, but under various circumstances
+ (like __hpux) we need to use void *. */
+# if defined (__STDC__) || defined (__hpux)
+ extern void *alloca ();
+# else /* Don't use void *. */
+ extern char *alloca ();
+# endif /* Don't use void *. */
+# endif /* Not _AIX */
+# endif /* Not HAVE_ALLOCA_H */
+# endif /* Not GNU C */
+#endif /* alloca not defined */
+
+/* HOST_BYTE_ORDER must be defined to one of these. */
+
+#ifdef HAVE_ENDIAN_H
+#include <endian.h>
+#endif
+
+#if !defined (BIG_ENDIAN)
+#define BIG_ENDIAN 4321
+#endif
+
+#if !defined (LITTLE_ENDIAN)
+#define LITTLE_ENDIAN 1234
+#endif
+
+/* Dynamic target-system-dependent parameters for GDB. */
+#include "gdbarch.h"
+
+/* Static target-system-dependent parameters for GDB. */
+
+/* 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 pointer for the target machine */
+#if !defined (TARGET_PTR_BIT)
+#define TARGET_PTR_BIT TARGET_INT_BIT
+#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
+
+/* 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)
+#define BITS_BIG_ENDIAN (TARGET_BYTE_ORDER == BIG_ENDIAN)
+#endif
+
+/* In findvar.c. */
+
+extern LONGEST extract_signed_integer PARAMS ((void *, int));
+
+extern ULONGEST extract_unsigned_integer PARAMS ((void *, int));
+
+extern int extract_long_unsigned_integer PARAMS ((void *, int, LONGEST *));
+
+extern CORE_ADDR extract_address PARAMS ((void *, int));
+
+extern void store_signed_integer PARAMS ((PTR, int, LONGEST));
+
+extern void store_unsigned_integer PARAMS ((PTR, int, ULONGEST));
+
+extern void store_address PARAMS ((PTR, int, LONGEST));
+
+/* Setup definitions for host and target floating point formats. We need to
+ consider the format for `float', `double', and `long double' for both target
+ and host. We need to do this so that we know what kind of conversions need
+ to be done when converting target numbers to and from the hosts DOUBLEST
+ data type. */
+
+/* This is used to indicate that we don't know the format of the floating point
+ number. Typically, this is useful for native ports, where the actual format
+ is irrelevant, since no conversions will be taking place. */
+
+extern const struct floatformat floatformat_unknown;
+
+#if HOST_BYTE_ORDER == BIG_ENDIAN
+# ifndef HOST_FLOAT_FORMAT
+# define HOST_FLOAT_FORMAT &floatformat_ieee_single_big
+# endif
+# ifndef HOST_DOUBLE_FORMAT
+# define HOST_DOUBLE_FORMAT &floatformat_ieee_double_big
+# endif
+#else /* LITTLE_ENDIAN */
+# ifndef HOST_FLOAT_FORMAT
+# define HOST_FLOAT_FORMAT &floatformat_ieee_single_little
+# endif
+# ifndef HOST_DOUBLE_FORMAT
+# define HOST_DOUBLE_FORMAT &floatformat_ieee_double_little
+# endif
+#endif
+
+#ifndef HOST_LONG_DOUBLE_FORMAT
+#define HOST_LONG_DOUBLE_FORMAT &floatformat_unknown
+#endif
+
+#ifndef TARGET_FLOAT_FORMAT
+#define TARGET_FLOAT_FORMAT (TARGET_BYTE_ORDER == BIG_ENDIAN \
+ ? &floatformat_ieee_single_big \
+ : &floatformat_ieee_single_little)
+#endif
+#ifndef TARGET_DOUBLE_FORMAT
+#define TARGET_DOUBLE_FORMAT (TARGET_BYTE_ORDER == BIG_ENDIAN \
+ ? &floatformat_ieee_double_big \
+ : &floatformat_ieee_double_little)
+#endif
+
+#ifndef TARGET_LONG_DOUBLE_FORMAT
+# define TARGET_LONG_DOUBLE_FORMAT &floatformat_unknown
+#endif
+
+/* Use `long double' if the host compiler supports it. (Note that this is not
+ necessarily any longer than `double'. On SunOS/gcc, it's the same as
+ double.) This is necessary because GDB internally converts all floating
+ point values to the widest type supported by the host.
+
+ There are problems however, when the target `long double' is longer than the
+ host's `long double'. In general, we'll probably reduce the precision of
+ any such values and print a warning. */
+
+#ifdef HAVE_LONG_DOUBLE
+typedef long double DOUBLEST;
+#else
+typedef double DOUBLEST;
+#endif
+
+extern void floatformat_to_doublest PARAMS ((const struct floatformat *,
+ char *, DOUBLEST *));
+extern void floatformat_from_doublest PARAMS ((const struct floatformat *,
+ DOUBLEST *, char *));
+extern DOUBLEST extract_floating PARAMS ((void *, int));
+
+extern void store_floating PARAMS ((void *, int, DOUBLEST));
+
+/* 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));
+
+extern CORE_ADDR push_word PARAMS ((CORE_ADDR, ULONGEST));
+
+/* 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
+
+#ifdef MAINTENANCE_CMDS
+extern int watchdog;
+#endif
+
+/* Hooks for alternate command interfaces. */
+
+#ifdef __STDC__
+struct target_waitstatus;
+struct cmd_list_element;
+#endif
+
+extern void (*init_ui_hook) PARAMS ((char *argv0));
+extern void (*command_loop_hook) PARAMS ((void));
+extern void (*fputs_unfiltered_hook) PARAMS ((const char *linebuffer,
+ GDB_FILE *stream));
+extern void (*print_frame_info_listing_hook) PARAMS ((struct symtab *s,
+ int line, int stopline,
+ int noerror));
+extern struct frame_info *parse_frame_specification PARAMS ((char *frame_exp));
+extern int (*query_hook) PARAMS ((const char *, va_list));
+extern void (*warning_hook) PARAMS ((const char *, va_list));
+extern void (*flush_hook) PARAMS ((GDB_FILE *stream));
+extern void (*create_breakpoint_hook) PARAMS ((struct breakpoint *b));
+extern void (*delete_breakpoint_hook) PARAMS ((struct breakpoint *bpt));
+extern void (*modify_breakpoint_hook) PARAMS ((struct breakpoint *bpt));
+extern void (*target_output_hook) PARAMS ((char *));
+extern void (*interactive_hook) PARAMS ((void));
+extern void (*registers_changed_hook) PARAMS ((void));
+extern void (*readline_begin_hook) PARAMS ((char *, ...));
+extern char * (*readline_hook) PARAMS ((char *));
+extern void (*readline_end_hook) PARAMS ((void));
+extern void (*register_changed_hook) PARAMS ((int regno));
+extern void (*memory_changed_hook) PARAMS ((CORE_ADDR addr, int len));
+extern void (*context_hook) PARAMS ((int));
+extern int (*target_wait_hook) PARAMS ((int pid,
+ struct target_waitstatus *status));
+
+extern void (*call_command_hook) PARAMS ((struct cmd_list_element *c,
+ char *cmd, int from_tty));
+
+extern NORETURN void (*error_hook) PARAMS ((void)) ATTR_NORETURN;
+
+extern void (*error_begin_hook) PARAMS ((void));
+
+
+/* Inhibit window interface if non-zero. */
+
+extern int use_windows;
+
+/* Symbolic definitions of filename-related things. */
+/* FIXME, this doesn't work very well if host and executable
+ filesystems conventions are different. */
+
+#ifndef DIRNAME_SEPARATOR
+#define DIRNAME_SEPARATOR ':'
+#endif
+
+#ifndef SLASH_P
+#if defined(__GO32__)||defined(_WIN32)
+#define SLASH_P(X) ((X)=='\\')
+#else
+#define SLASH_P(X) ((X)=='/')
+#endif
+#endif
+
+#ifndef SLASH_CHAR
+#if defined(__GO32__)||defined(_WIN32)
+#define SLASH_CHAR '\\'
+#else
+#define SLASH_CHAR '/'
+#endif
+#endif
+
+#ifndef SLASH_STRING
+#if defined(__GO32__)||defined(_WIN32)
+#define SLASH_STRING "\\"
+#else
+#define SLASH_STRING "/"
+#endif
+#endif
+
+#ifndef ROOTED_P
+#define ROOTED_P(X) (SLASH_P((X)[0]))
+#endif
+
+/* On some systems, PIDGET is defined to extract the inferior pid from
+ an internal pid that has the thread id and pid in seperate bit
+ fields. If not defined, then just use the entire internal pid as
+ the actual pid. */
+
+#ifndef PIDGET
+#define PIDGET(pid) (pid)
+#endif
+
+/* If under Cygwin, provide backwards compatibility with older
+ Cygwin compilers that don't define the current cpp define. */
+#ifdef __CYGWIN32__
+#ifndef __CYGWIN__
+#define __CYGWIN__
+#endif
+#endif
+
+#endif /* #ifndef DEFS_H */
diff --git a/gdb/delta68-nat.c b/gdb/delta68-nat.c
new file mode 100644
index 00000000000..3995b235e04
--- /dev/null
+++ b/gdb/delta68-nat.c
@@ -0,0 +1,91 @@
+/* Functions specific to running gdb native on a Motorola Delta Series sysV68.
+ Copyright (C) 1993, 1997-98, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include <sys/signal.h> /* for MAXSIG in sys/user.h */
+#include <sys/types.h> /* for ushort in sys/dir.h */
+#include <sys/dir.h> /* for struct direct in sys/user.h */
+#include <sys/user.h>
+
+#include <nlist.h>
+
+#if !defined (offsetof)
+#define offsetof(TYPE, MEMBER) ((unsigned long) &((TYPE *)0)->MEMBER)
+#endif
+
+/* Return the address in the core dump or inferior of register REGNO.
+ BLOCKEND is the address of the end of the user structure. */
+
+CORE_ADDR
+register_addr (regno, blockend)
+ int regno;
+ CORE_ADDR blockend;
+{
+ static int sysv68reg[] =
+ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, -1, 15, 16 };
+
+ if (regno >= 0 && regno < sizeof(sysv68reg) / sizeof(sysv68reg[0]))
+ return blockend + sysv68reg[regno] * 4;
+ else if (regno < FPC_REGNUM)
+ return offsetof (struct user, u_fpu.regs.reg[regno - FP0_REGNUM][0]);
+ else if (regno == FPC_REGNUM)
+ return offsetof (struct user, u_fpu.regs.control);
+ else if (regno == FPS_REGNUM)
+ return offsetof (struct user, u_fpu.regs.status);
+ else if (regno == FPI_REGNUM)
+ return offsetof (struct user, u_fpu.regs.iaddr);
+ else
+ {
+ fprintf_unfiltered (gdb_stderr, "\
+Internal error: invalid register number %d in REGISTER_U_ADDR\n",
+ regno);
+ return blockend;
+ }
+}
+
+CORE_ADDR kernel_u_addr;
+
+/* Read the value of the u area from the kernel. */
+void
+_initialize_delta68_nat ()
+{
+ struct nlist nl[2];
+
+ nl[0].n_name = "u";
+ nl[1].n_name = NULL;
+ if (nlist ("/sysV68", nl) == 0 && nl[0].n_scnum != 0)
+ kernel_u_addr = nl[0].n_value;
+ else
+ {
+ perror ("Cannot get kernel u area address");
+ exit (1);
+ }
+}
+
+clear_insn_cache ()
+{
+#ifdef MCT_TEXT /* in sys/signal.h on sysV68 R3V7.1 */
+ memctl(0, 4096, MCT_TEXT);
+#endif
+}
+
+kernel_u_size ()
+{
+ return sizeof (struct user);
+}
diff --git a/gdb/demangle.c b/gdb/demangle.c
new file mode 100644
index 00000000000..669d9abcd28
--- /dev/null
+++ b/gdb/demangle.c
@@ -0,0 +1,237 @@
+/* Basic C++ demangling support for GDB.
+ Copyright 1991, 1992, 1996, 1999 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 "gdb_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", "hp", 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 demangle-style" command, printed as part of the output by the
+ "show demangle-style" 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"
+ }
+ ,
+ {
+ HP_DEMANGLING_STYLE_STRING,
+ hp_demangling,
+ "HP (aCC) style demangling"
+ }
+ ,
+ {
+ EDG_DEMANGLING_STYLE_STRING,
+ edg_demangling,
+ "EDG style demangling"
+ }
+ ,
+ {
+ NULL, unknown_demangling, NULL
+ }
+};
+
+static void
+set_demangling_command PARAMS ((char *, int, struct cmd_list_element *));
+
+/* Set current demangling style. Called by the "set demangle-style"
+ 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, c)
+ char *ignore;
+ int from_tty;
+ struct cmd_list_element *c;
+{
+ 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_unfiltered ("Unknown demangling style `%s'.\n",
+ current_demangling_style_string);
+ }
+ printf_unfiltered ("The currently understood settings are:\n\n");
+ for (dem = demanglers; dem->demangling_style_name != NULL; dem++)
+ {
+ printf_unfiltered ("%-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 =
+ savestring (dem->demangling_style_name,
+ strlen (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 =
+ savestring (demanglers[0].demangling_style_name,
+ strlen (demanglers[0].demangling_style_name));
+ warning ("`%s' style demangling chosen as the default.\n",
+ current_demangling_style_string);
+ }
+ }
+}
+
+/* Fake a "set demangle-style" command. */
+
+void
+set_demangling_style (style)
+ char *style;
+{
+ if (current_demangling_style_string != NULL)
+ {
+ free (current_demangling_style_string);
+ }
+ current_demangling_style_string = savestring (style, strlen (style));
+ set_demangling_command ((char *) NULL, 0, (struct cmd_list_element *) NULL);
+}
+
+/* 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). */
+
+static char cplus_markers[] = {CPLUS_MARKER, '.', '$', '\0'};
+
+int
+is_cplus_marker (c)
+ int c;
+{
+ return c && strchr (cplus_markers, c) != NULL;
+}
+
+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.sfunc = set_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/gdb/dink32-rom.c b/gdb/dink32-rom.c
new file mode 100644
index 00000000000..c0c2e510202
--- /dev/null
+++ b/gdb/dink32-rom.c
@@ -0,0 +1,198 @@
+/* Remote debugging interface for DINK32 (PowerPC) ROM monitor for
+ GDB, the GNU debugger.
+ Copyright 1997 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "gdbcore.h"
+#include "target.h"
+#include "monitor.h"
+#include "serial.h"
+
+static void dink32_open PARAMS ((char *args, int from_tty));
+
+static void
+dink32_supply_register (regname, regnamelen, val, vallen)
+ char *regname;
+ int regnamelen;
+ char *val;
+ int vallen;
+{
+ int regno = 0, base = 0;
+
+ if (regnamelen < 2 || regnamelen > 4)
+ return;
+
+ switch (regname[0])
+ {
+ case 'R':
+ if (regname[1] < '0' || regname[1] > '9')
+ return;
+ if (regnamelen == 2)
+ regno = regname[1] - '0';
+ else if (regnamelen == 3 && regname[2] >= '0' && regname[2] <= '9')
+ regno = (regname[1] - '0') * 10 + (regname[2] - '0');
+ else
+ return;
+ break;
+ case 'F':
+ if (regname[1] != 'R' || regname[2] < '0' || regname[2] > '9')
+ return;
+ if (regnamelen == 3)
+ regno = 32 + regname[2] - '0';
+ else if (regnamelen == 4 && regname[3] >= '0' && regname[3] <= '9')
+ regno = 32 + (regname[2] - '0') * 10 + (regname[3] - '0');
+ else
+ return;
+ break;
+ case 'I':
+ if (regnamelen != 2 || regname[1] != 'P')
+ return;
+ regno = 64;
+ break;
+ case 'M':
+ if (regnamelen != 3 || regname[1] != 'S' || regname[2] != 'R')
+ return;
+ regno = 65;
+ break;
+ case 'C':
+ if (regnamelen != 2 || regname[1] != 'R')
+ return;
+ regno = 66;
+ break;
+ case 'S':
+ if (regnamelen != 4 || regname[1] != 'P' || regname[2] != 'R')
+ return;
+ else if (regname[3] == '8')
+ regno = 67;
+ else if (regname[3] == '9')
+ regno = 68;
+ else if (regname[3] == '1')
+ regno = 69;
+ else if (regname[3] == '0')
+ regno = 70;
+ else
+ return;
+ break;
+ default:
+ return;
+ }
+
+ monitor_supply_register (regno, val);
+}
+
+static void
+dink32_load (monops, filename, from_tty)
+ struct monitor_ops *monops;
+ char *filename;
+ int from_tty;
+{
+ extern int inferior_pid;
+
+ generic_load (filename, from_tty);
+
+ /* Finally, make the PC point at the start address */
+ if (exec_bfd)
+ write_pc (bfd_get_start_address (exec_bfd));
+
+ inferior_pid = 0; /* No process now */
+}
+
+
+/* This array of registers needs to match the indexes used by GDB. The
+ whole reason this exists is because the various ROM monitors use
+ different names than GDB does, and don't support all the registers
+ either. */
+
+static char *dink32_regnames[NUM_REGS] =
+{
+ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
+ "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
+ "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
+ "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
+
+ "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
+ "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
+ "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
+ "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
+
+ "srr0", "msr", "cr", "lr", "ctr", "xer", "xer"
+};
+
+static struct target_ops dink32_ops;
+
+static char *dink32_inits[] = {"\r", NULL};
+
+static struct monitor_ops dink32_cmds;
+
+static void
+dink32_open (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ monitor_open (args, &dink32_cmds, from_tty);
+}
+
+void
+_initialize_dink32_rom ()
+{
+ dink32_cmds.flags = MO_HEX_PREFIX | MO_GETMEM_NEEDS_RANGE | MO_FILL_USES_ADDR | MO_HANDLE_NL | MO_32_REGS_PAIRED | MO_SETREG_INTERACTIVE | MO_SETMEM_INTERACTIVE | MO_GETMEM_16_BOUNDARY | MO_CLR_BREAK_1_BASED | MO_SREC_ACK | MO_SREC_ACK_ROTATE;
+ dink32_cmds.init = dink32_inits;
+ dink32_cmds.cont = "go +\r";
+ dink32_cmds.step = "tr +\r";
+ dink32_cmds.set_break = "bp 0x%x\r";
+ dink32_cmds.clr_break = "bp %d\r";
+#if 0 /* Would need to follow strict alignment rules.. */
+ dink32_cmds.fill = "mf %x %x %x\r";
+#endif
+ dink32_cmds.setmem.cmdb = "mm -b %x\r";
+ dink32_cmds.setmem.cmdw = "mm -w %x\r";
+ dink32_cmds.setmem.cmdl = "mm %x\r";
+ dink32_cmds.setmem.term = " ? ";
+ dink32_cmds.getmem.cmdb = "md %x\r";
+ dink32_cmds.getmem.resp_delim = " ";
+ dink32_cmds.setreg.cmd = "rm %s\r";
+ dink32_cmds.setreg.term = " ? ";
+ dink32_cmds.getreg.cmd = "rd %s\r";
+ dink32_cmds.getreg.resp_delim = ": ";
+ dink32_cmds.dump_registers = "rd r\r";
+ dink32_cmds.register_pattern = "\\(\\w+\\) +=\\([0-9a-fA-F]+\\b\\)";
+ dink32_cmds.supply_register = dink32_supply_register;
+ /* S-record download, via "keyboard port". */
+ dink32_cmds.load = "dl -k\r";
+ dink32_cmds.loadresp = "Set Input Port : set to Keyboard Port\r";
+#if 0 /* slow load routine not needed if S-records work... */
+ dink32_cmds.load_routine = dink32_load;
+#endif
+ dink32_cmds.prompt = "DINK32_603 >>";
+ dink32_cmds.line_term = "\r";
+ dink32_cmds.target = &dink32_ops;
+ dink32_cmds.stopbits = SERIAL_1_STOPBITS;
+ dink32_cmds.regnames = dink32_regnames;
+ dink32_cmds.magic = MONITOR_OPS_MAGIC;
+
+ init_monitor_ops (&dink32_ops);
+
+ dink32_ops.to_shortname = "dink32";
+ dink32_ops.to_longname = "DINK32 monitor";
+ dink32_ops.to_doc = "Debug using the DINK32 monitor.\n\
+Specify the serial device it is connected to (e.g. /dev/ttya).";
+ dink32_ops.to_open = dink32_open;
+
+ add_target (&dink32_ops);
+}
diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog
new file mode 100644
index 00000000000..1e03a80884b
--- /dev/null
+++ b/gdb/doc/ChangeLog
@@ -0,0 +1,1473 @@
+Thu Feb 11 18:00:59 1999 Stan Shebs <shebs@andros.cygnus.com>
+
+ * gdb.texinfo: Update the credits.
+
+Mon Feb 8 17:33:57 1999 Stan Shebs <shebs@andros.cygnus.com>
+
+ * gdb.texinfo: Fix mistakes noticed in printout of last
+ draft, add Alpha to discussion of heuristic fence post.
+
+Fri Feb 5 17:20:00 1999 Stan Shebs <shebs@andros.cygnus.com>
+
+ * gdb.texinfo, remote.texi: Many changes; update to Seventh
+ Edition, merge some HP changes into mainline, describe some
+ previously undocumented features, describe more of the target
+ commands available, eliminate obsolete section on renamed
+ commands.
+ * all-cfg.texi, HPPA-cfg.texi: Remove some obsolete conditionals.
+
+Wed Jan 20 17:47:45 1999 Stan Shebs <shebs@andros.cygnus.com>
+
+ * gdb.texinfo: Make many HPPA conditionals unconditional,
+ including catchpoint description, since now on for all configs.
+ * all-cfg.texi: @clear HPPA, since is mainly for very HP-specific
+ specializations.
+
+Thu Jan 14 17:10:12 1999 Stan Shebs <shebs@andros.cygnus.com>
+
+ * Makefile.in (GDBvn.texi): Fix match expression to work with
+ current format of VERSION in gdb/Makefile.in.
+ * gdb.texinfo: Fix node ref to match new readline.
+
+Wed Jan 13 10:38:40 1999 Edith Epstein <eepstein@sophia.cygnus.com>
+
+ * gdb.texinfo: Changes made as part of a project to merge in
+ changes made by HP. Documentation makes extensive use of
+ @ifclear HPPA and @ifset HPPA. The HP manual omits doumentation
+ on remote debugging. There are differences in documentation
+ (HP vs. non-HP) on C++ support (aCC vs. gnu gcc++). Also,
+ the HP manual discusses catchpoints, hardware watchpoints, and
+ some HPUX specific limitations for shared library support.
+
+ There are also a number of @node changes.
+
+1999-01-12 Jason Molenda (jsm@bugshack.cygnus.com)
+
+ * gdbint.texinfo (Formatting): Disambiguate a sentence.
+ (C Usage): Same.
+
+Wed Jan 6 11:55:34 1999 David Taylor <taylor@texas.cygnus.com>
+
+ The following changes were made by Edith Epstein
+ <eepstein@cygnus.com> as part of a project to merge in changes
+ made by HP.
+
+ * HPPA-cfg.texi: new file.
+
+ * all-cfg.texi: set HPPA for HP PA-RISC targets.
+
+ * refcard.tex: change documentation about catch.
+ removed info catch.
+
+Mon Jan 4 18:29:18 1999 Stan Shebs <shebs@andros.cygnus.com>
+
+ * gdbint.texinfo: Expand on GDB's coding standards,
+ specify the use of arg names with prototypes.
+
+1998-12-14 J.T. Conklin <jtc@redbacknetworks.com>
+
+ * gdb.texinfo: Fix tipo.
+
+Sun Dec 13 10:27:59 1998 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * gdbint.texinfo: Document TARGET_BYTE_ORDER_DEFAULT and
+ TARGET_BYTE_ORDER_SELECTABLE_P.
+
+Thu Dec 10 16:07:09 1998 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * gdbint.texinfo (FRAME_FIND_SAVED_REGS): Document.
+
+1998-12-09 Jim Blandy <jimb@zwingli.cygnus.com>
+
+ * agentexpr.texi: New file.
+
+Wed Dec 9 21:13:57 1998 Andrew Cagney <cagney@chook>
+
+ * gdbint.texinfo (REGISTER_NAME): Replace REGISTER_NAMES.
+
+1998-12-03 J.T. Conklin <jtc@redbacknetworks.com>
+
+ * remote.texi: Changed wording that implied that the GDB remote
+ protocol caches register values instead of GDB itself.
+
+Tue Dec 1 17:45:43 1998 Stan Shebs <shebs@andros.cygnus.com>
+
+ * gdbint.texinfo: Add some info about symbol readers.
+ (CHILL_PRODUCER, etc): Comment out descriptions, not useful.
+ (IN_SOLIB_CALL_TRAMPOLINE): Rename info from IN_SOLIB_TRAMPOLINE.
+ (IN_SOLIB_RETURN_TRAMPOLINE): Describe.
+ (KERNEL_DEBUGGING, MIPSEL): No info about these, remove.
+
+Mon Nov 30 11:32:21 1998 Andrew Cagney <cagney@chook>
+
+ * gdbint.texinfo (FRAME_CHAIN_VALID_ALTERNATE):
+
+Sat Nov 28 13:45:53 1998 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * gdbint.texinfo (INNER_THAN): Update, now takes parameters.
+
+Fri Nov 27 12:39:45 1998 Andrew Cagney <cagney@chook>
+
+ * gdbint.texinfo (NO_SINGLE_STEP): Replace with
+ SOFTWARE_SINGLE_STEP_P and SOFTWARE_SINGLE_STEP.
+
+Wed Oct 14 10:02:40 1998 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * gdbint.texinfo: Fix minor typos.
+
+Wed Sep 30 18:03:19 1998 Stan Shebs <shebs@andros.cygnus.com>
+
+ * gdbint.texinfo: Complete overhaul. Group descriptions more
+ logically, add more info on generic algorithms, remove much
+ obsolete and/or wrong material.
+
+Fri Jul 24 17:51:38 1998 Ian Lance Taylor <ian@cygnus.com>
+
+ * stabs.texinfo (Method Type Descriptor): Expand and correct.
+
+Mon May 4 10:37:12 1998 Brian Youmans (3diff@gnu.org)
+
+ * refcard.tex: Copyright, address updates.
+
+Tue Apr 21 18:09:56 1998 Stan Shebs <shebs@andros.cygnus.com>
+
+ * gdb.texinfo (EDITION, DATE): Update and change to use ordinals
+ for the edition instead of confusing GDB-version-like numbers.
+
+Mon Apr 13 14:05:00 1998 Fred Fish <fnf@cygnus.com>
+
+ * gdb.texinfo (hbreak, watch): Fix typo, "date" -> "data".
+
+Thu Apr 2 16:52:44 1998 Jason Molenda (crash@bugshack.cygnus.com)
+
+ * LRS: Reformat a bit to keep text under 80 columns.
+
+Thu Apr 2 16:10:36 1998 Stan Shebs <shebs@andros.cygnus.com>
+
+ * gdb.texinfo: Add some credits, mention bug monitor.
+ * remote.texi: Mention mips monitor targets.
+ * gdbint.texinfo: Describe SP_REGNUM, STEP_SKIPS_DELAY.
+
+Mon Feb 2 17:13:03 1998 Stan Shebs <shebs@andros.cygnus.com>
+
+ * gdbint.texinfo: Remove obsolete mentions of pinsn.c and opcode.h
+ files, finish sorting of host vs target vs native macros, describe
+ some more of them.
+
+Tue Jan 13 16:44:50 1998 Fred Fish <fnf@cygnus.com>
+
+ * gdbint.texinfo (Host Conditionals): Document change from
+ using NO_MMALLOC to it's inverse, USE_MMALLOC.
+
+Mon Nov 24 13:55:21 1997 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * gdbint.texinfo (Host Conditionals): Document
+ PRINTF_HAS_LONG_DOUBLE, SCANF_HAS_LONG_DOUBLE, HAVE_LONG_DOUBLE.
+
+Fri Jul 4 14:52:31 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * gdbint.texinfo (Host Conditionals): Add CRLF_SOURCE_LINES.
+ Document LSEEK_NOT_LINEAR.
+
+Tue Mar 25 14:44:09 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * stabs.texinfo (Stab Section Basics): Make it clear that only
+ some versions of the GNU linker remove the leading N_UNDF symbol.
+
+Thu Feb 27 17:45:19 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * stabs.texinfo (String Field): Document type number pairs here,
+ instead of in the Sun specific section.
+ (Include Files): The GNU linker supports the N_BINCL
+ optimization. Clarify the N_BINCL value, and what it is used
+ for.
+ (Procedures): Document N_FUN with an empty string to mark the end
+ of a function.
+ (Typedefs): Mention that Sun compilers may use N_GSYM for a type.
+ (Sun Differences): Remove this node, as the information is now
+ elsewhere in the main document.
+ (Stab Section Basics): Mention that the GNU linker may optimize
+ stabs and remove the leading N_UNDF symbol.
+
+Mon Dec 9 12:23:32 1996 Roland Pesch <roland@wrs.com>
+
+ * gdb.texinfo, refcard.tex: Restore author credit
+
+Wed Oct 2 22:01:36 1996 Fred Fish <fnf@fishfood.ninemoons.com>
+
+ * gdbint.texinfo (SIGTRAMP_START, SIGTRAMP_END): Update
+ documentation to account for START and END macros taking
+ one arg.
+
+Thu Aug 22 17:59:03 1996 Fred Fish <fnf@cygnus.com>
+
+ From: Eberhard Mattes <mattes@azu.informatik.uni-stuttgart.de>
+ * gdb.texinfo (Frames): Fix typo.
+
+Tue Jul 23 10:06:20 1996 Fred Fish <fnf@cygnus.com>
+
+ * gdbint.texinfo (NO_SINGLE_STEP): Document that single_step takes
+ a target_signal as arg type, not a pid.
+
+Fri Jul 12 11:10:05 1996 Stu Grossman (grossman@critters.cygnus.com)
+
+ * gdb.texinfo: Document `set assembly-language'.
+
+Thu Jul 11 13:50:28 1996 Stan Shebs <shebs@andros.cygnus.com>
+
+ * remote.texi: Update list of stubs in the GDB distribution.
+
+Fri Jul 5 15:38:54 1996 Fred Fish <fnf@cygnus.com>
+
+ * gdbint.texinfo (NO_MMCHECK): Renamed from NO_MMALLOC_CHECK.
+ Also document that some systems can use mmalloc but must define
+ this if their C runtime allocates memory that is later freed.
+ (MMCHECK_FORCE): Document new macro.
+
+Fri Jun 28 22:17:10 1996 Dawn Perchik <dawn@cygnus.com>
+
+ * remote.texi: Add documentation for target Sparclet.
+
+Mon Jun 24 18:12:22 1996 Jason Molenda (crash@godzilla.cygnus.co.jp)
+
+ * Makefile.in (srcdir, VPATH, prefix, infodir, INSTALL,
+ INSTALL_PROGRAM, INSTALL_DATA): Use autoconf set values.
+ * configure.in: Rewritten for autoconf.
+ * configure: New.
+
+Mon Jun 17 10:43:41 1996 Fred Fish <fnf@cygnus.com>
+
+ * Makefile.in (DVIPS): New define, set to dvips.
+ (dvi): Add stabs.dvi.
+ (ps): New target.
+ (all-doc): Depend on info, dvi, and ps targets.
+ (STAGESTUFF): Add *.ps and *.dvi files.
+ (clean-info, clean-dvi): Remove.
+ (mostlyclean): Does not depend upon clean-info or clean-dvi,
+ rules completely rewritten.
+ (maintainer-clean): Remove clean-info and clean-dvi
+ dependencies and put their actions in the rules.
+ (gdb.ps): New target
+ (gdb.dvi, gdbgui.dvi, gdbint.dvi, stabs.dvi): Remove
+ intermediate TeX files, whether they have 2 or 3 character
+ extensions.
+ (gdbint.ps): Add target and rules.
+ (gdb-internals): Delete unused target.
+ (Makefile): Depends upon config.status also.
+
+Sat Mar 30 15:46:58 1996 Fred Fish <fnf@cygnus.com>
+
+ * gdbint.texinfo (CC_HAS_LONG_LONG): Clarify when/how this is
+ set.
+
+Sat Mar 16 15:10:20 1996 Fred Fish <fnf@cygnus.com>
+
+ From Peter Schauer <Peter.Schauer@Regent.E-Technik.TU-Muenchen.DE>
+ * gdb.texinfo (Expressions): Fix erroneous array constant example.
+
+Sat Mar 16 13:28:45 1996 Fred Fish <fnf@cygnus.com>
+
+ * gdb.texinfo: Add missing "@bullet" to some "@itemize" commands.
+
+Sat Feb 10 03:28:36 1996 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * gdb.texinfo (Print settings): Document
+ `set/show print static-members' commands.
+
+Wed Jan 10 14:16:37 1996 Fred Fish <fnf@cygnus.com>
+
+ * gdbint.texinfo (Native): Document name change, coredep.c to
+ core-aout.c.
+
+Wed Dec 13 12:35:28 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * stabs.texinfo (Include Files): Document the values the SunOS4
+ linker creates for N_BINCL/N_EINCL/N_EXCL stabs.
+
+Fri Dec 8 21:08:44 1995 Fred Fish <fnf@cygnus.com>
+
+ * gdbint.texinfo (Releases): Change gdb.tar.Z to gdb.tar.gz.
+ Fix typo.
+
+Fri Dec 1 11:07:50 1995 Fred Fish <fnf@cygnus.com>
+
+ * gdbint.texinfo (Releases): Make "gdb.tar.gz" rather than
+ "gdb.tar.Z".
+
+Wed Sep 20 13:14:10 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * Makefile.in (maintainer-clean): New target, synonym for
+ realclean.
+
+Thu Aug 3 10:45:37 1995 Fred Fish <fnf@cygnus.com>
+
+ * Update all FSF addresses except those in COPYING* files.
+
+Wed Jul 19 18:43:03 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ From Richard Earnshaw (rearnsha@armltd.co.uk):
+ * gdb.texinfo (convenience variables): Document $_exitcode.
+ (quit): Document optional expression to use as exit code.
+
+Thu Jun 22 21:27:33 1995 Victoria Mixon <victoria@cygnus.com>
+
+ * gdb.texinfo, remote.texi: Brought up to date with various
+ GDB changes.
+
+Tue Jun 20 14:35:38 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ * gdb.texinfo: Update dates and versions, fix comments about
+ hardware watchpoints in future releases and about the
+ sharedlibrary command.
+
+Mon May 8 09:30:36 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabs.texinfo: Remove node `XCOFF differences'. Describe value of
+ C_FUN stab. Other cleanups.
+
+Wed Apr 19 07:02:19 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * remote.texi (Bootstrapping): Clarify that flush_i_cache is only
+ for the sparc stub.
+
+Tue Apr 11 11:41:49 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * annotate.texi: Clarify which addresses have differing formats
+ depending on the language and which do not.
+
+Tue Mar 28 16:56:22 1995 J.T. Conklin <jtc@rtl.cygnus.com>
+
+ * remote.texi (NetWare): Changed example to use BOARD= instead of
+ NODE= argument to reflect correspoding change to gdbserve.nlm.
+
+Fri Mar 17 06:47:02 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabs.texinfo (Negative Type Numbers): Mention the fact that
+ GDB, as well as AIX dbx, supports the size type attribute.
+
+Thu Mar 16 12:11:32 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabs.texinfo (Negative Type Numbers): Document types -31 to -34.
+
+Mon Mar 13 16:49:13 1995 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * gdb.texinfo (Define): Document $arg0... arguments to commands,
+ and new 'if' and 'while' commands.
+
+Fri Feb 17 15:24:35 1995 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * gdb.texinfo (Artificial arrays): Note use of coerce-to-array-type.
+
+Wed Feb 15 11:59:18 1995 J.T. Conklin <jtc@rtl.cygnus.com>
+
+ * all-cfg.texi: New flag, GDBSERVE, for NetWare's gdbserve.nlm.
+ * remote.texi (NetWare): New node, how to use gdbserve.nlm on
+ NetWare targets. Mostly stolen from the Server node.
+
+Fri Feb 10 20:20:08 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.texinfo (Setting): Talk about the language of a source file
+ versus the working language. The old documentation did not match
+ what GDB did.
+
+Wed Feb 1 20:26:36 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabs.texinfo (Source Files): Document N_SO used to mark the end
+ of a source file.
+
+Mon Jan 23 14:23:37 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.texinfo (Processes): New node.
+
+Tue Jan 17 14:09:03 1995 Ian Lance Taylor <ian@sanguine.cygnus.com>
+
+ * remote.texi: Update documentation of set/show mipsfpu.
+
+
+Sun Sep 4 16:47:21 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * gdbint.texinfo: Removed mentions of some incorrectly placed and
+ obsolete conditionals, described some others.
+
+Mon Aug 1 15:42:39 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdbint.texinfo: Remove references to BROKEN_LARGE_ALLOCA and
+ SET_STACK_LIMIT_HUGE; they were removed from GDB 14 May 1994.
+
+Mon Aug 1 15:12:02 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * gdbint.texinfo: Put regex conditionals in their own table.
+
+Tue Jul 26 18:32:52 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * gdbint.texinfo: Removed mentions of many obsolete conditionals,
+ described or fixed the descriptions of many others.
+
+Sun Jul 17 14:14:03 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * gdb.texinfo: Add some more credits.
+ * gdbint.texinfo: Capitalize GDB consistently, describe some
+ macros and remove some.
+
+Thu Jul 14 18:43:17 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * gdbint.texinfo: Removed mentions of many incorrectly placed and
+ obsolete conditionals, described some others.
+
+Tue Jul 12 12:23:15 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * gdb.texinfo (help targets): Changed to `help target', which
+ is the correct gdb command.
+
+Wed Jun 22 18:00:51 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * annotate.texi (TODO): New node, for keeping track of annotations
+ suggested but not yet implemented.
+
+Wed Jun 1 16:10:45 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabs.texinfo (Statics): Value of xcoff C_BSTAT points to
+ another symbol, it is not the address itself.
+
+Thu May 5 20:23:36 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * stabs.texinfo (Stab Section Basics): Add comment about alignment
+ of stabs-in-coff sections.
+
+Wed May 4 06:26:11 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * annotate.texi: Change edition to 0.5 and date to May 1994.
+ Add index.
+ (Frames): New node, for frame annotation.
+ (Displays): New node, for display annotation.
+
+ * remote.texi (MIPS Remote): Say that set timeout doesn't apply
+ when waiting for your program to stop.
+
+Fri Apr 29 18:24:46 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * annotate.texi (Breakpoint Info): Document annotation of header
+ fields and record annotation.
+
+Thu Apr 28 07:44:28 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * annotate.texi: New file, to document annotations.
+
+Thu Apr 21 14:20:51 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * Makefile.in (clean): Don't remove GDBvn.texi (apparently on Jan
+ 16 I meant to make this change but did not). Do remove gdb-cfg.texi.
+
+Wed Apr 20 11:22:48 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabs.texinfo (Stab Section Basics): Say what is in .stab
+ section, and say n_strx field is compilation unit relative.
+ * stabs.texinfo: Don't use @code for a.out when it is the name of
+ an object file format.
+
+Wed Apr 13 20:29:54 1994 Jim Kingdon (kingdon@deneb.cygnus.com)
+
+ * gdb.texinfo: Refer to file names, not path names, per rms
+ convention.
+ (Arguments): Fix typo.
+
+Thu Mar 24 08:09:12 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabs.texinfo (Global Variables): Talk about stabs in files
+ where variables are referenced, but not defined.
+
+Wed Mar 23 07:16:36 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabs.texinfo: Move stuff on @ and # type descriptors from node
+ Cplusplus to new nodes Member Type Descriptor and Method Type
+ Descriptor. Re-write stuff for #.
+
+Wed Mar 16 08:20:19 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.texinfo (Print Settings): Don't document "set print
+ fast-symbolic-addr off". The bug which it worked around was fixed
+ on 25 Feb 94 in coffread.c, so I'm nuking the command.
+
+ * stabs.texinfo (Alternate Entry Points): New node, rewritten from
+ N_ENTRY node.
+
+ * stabs.texinfo (Type Descriptors): Add 'Y' type descriptor.
+
+Tue Mar 15 08:43:02 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdbint.texinfo (Host Conditionals, Target Conditionals): Remove
+ references to ieee-float.c.
+
+Fri Mar 11 08:09:40 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.texinfo (Set Breaks): Update documentation for tbreak to
+ match what the code actually does.
+
+Wed Mar 9 19:43:05 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabs.texinfo (Symbol Descriptors): Add OS9000 symbol descriptor s.
+
+Tue Mar 1 17:04:43 1994 Jim Kingdon (kingdon@deneb.cygnus.com)
+
+ * stabs.texinfo (Type Descriptors): Add OS9000 type descriptors c,
+ i, and b.
+
+Wed Feb 23 10:44:18 1994 Jim Kingdon (kingdon@rtl.cygnus.com)
+
+ * stabs.texinfo: Document N_RBRAC as function relative for COFF as
+ well as for ELF and SOM. Unify the descriptions of ELF and SOM
+ as "stabs in sections" rather than just saying "ELF and SOM".
+ Also make that stuff apply to COFF.
+
+Fri Feb 18 08:25:58 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.texinfo (Formatting Documentation): Change GhostScript to
+ Ghostscript.
+
+Fri Feb 4 06:31:31 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.texinfo (Continuing and Stepping): When talking about "step"
+ versus functions without line numbers, also mention stepping into
+ them as well as "step" when you are in them. Tell the user how to
+ deal with the situation. Add comment about "debugging information".
+
+Thu Feb 3 11:39:59 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabs.texinfo (Enumerations): Document restriction on where
+ enumeration types can appear and still win with GDB.
+
+Wed Feb 2 11:29:17 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabs.texinfo (Negative Type Numbers): Document format for type
+ -16.
+
+Thu Jan 27 16:53:56 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.texinfo (Selection, Frame Info): Update information about
+ arbitrary frame specficiations.
+
+Wed Jan 26 15:31:57 1994 Roland H. Pesch (pesch@fowanton.cygnus.com)
+
+ * gdb.texinfo, remote.texi: general editing pass prior to Net release
+
+Tue Jan 25 12:12:04 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabs.texinfo (String Field): Discuss continuing stabs with ?.
+
+Wed Jan 19 06:39:24 1994 David J. Mackenzie (djm@thepub.cygnus.com)
+
+ * stabs.texinfo (Non-Stab Symbol Types): Mention N_SET* | N_EXT.
+
+Sun Jan 16 12:43:32 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabs.texinfo: Re-do stuff about C_BSTAT and move from XCOFF
+ Differences node to Statics node.
+ (Statics): Discuss XCOFF use of V symbol descriptor.
+
+ * Makefile.in: Remove refcard.dvi and GDBvn.texi in realclean,
+ not clean.
+
+Wed Jan 12 21:29:54 1994 John Gilmore (gnu@cygnus.com)
+
+ * gdb.texinfo (Print Settings): Document `set print
+ fast-symbolic-addr' and improve the doc for some other
+ `set print's.
+
+Mon Jan 3 17:23:07 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabs.texinfo (String Field): Talk about defining several type
+ numbers at once.
+ Fix lint regarding changing node ELF Transformations to
+ ELF and SOM Transformations.
+
+Fri Dec 31 00:42:43 1993 John Gilmore (gnu@cygnus.com)
+
+ * stabs.texinfo: Insert Peter Kessler's name as inventor (I think).
+
+Tue Dec 28 09:30:40 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabs.texinfo (Cross-References): `::' is for nested types only
+ within <>.
+ (Structures): Document static members.
+
+Mon Dec 27 13:55:04 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabs.texinfo: Document S type attribute.
+
+Sun Dec 26 20:46:36 1993 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * stabs.texinfo: Add notes about stabs-in-som where appropriate.
+
+Fri Dec 3 19:13:19 1993 John Gilmore (gnu@cygnus.com)
+
+ * gdbint.texinfo: Fix a few typos.
+
+Sun Nov 28 18:06:25 1993 Roland H. Pesch (pesch@fowanton.cygnus.com)
+
+ * gdb.texinfo, remote.texi: formatting improvements
+
+ * gdb.texinfo (New Features): mention threads.
+ (Summary, C): fix xrefs in newly contributed text.
+ (Threads): index entries, clarifications, example
+ (passim): minor typos fixed, phrasing improvements
+
+ * remote.texi (Bootstrapping): rephrase text on ^C and add index
+ entries; (Server): explain use of gdbserver w/real-time systems,
+ add example of conflicting TCP port; (MIPS Remote) break up
+ running text into table, highlighting commands, and add example.
+
+Wed Nov 24 14:15:56 1993 Roland H. Pesch (pesch@fowanton.cygnus.com)
+
+ * refcard.tex: avoid bad linebreaks even when REFEDITS=psrc.sed
+
+Fri Nov 12 16:10:58 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabs.texinfo (Nested Symbols): New node.
+ (String Field, Symbol Descriptors, Cross-References): Refer to it.
+
+Thu Nov 11 13:26:45 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabs.texinfo (Stabs in ELF): Clarify how Bbss.bss work with respect
+ to picking which Bbss.bss symbol to use, and (because there seems to
+ be no good way of doing it) re-write some of the text to make it
+ sound like Bbss.bss isn't such a great idea after all (as currently
+ designed).
+
+ * gdb.texinfo (C): In addition to saying people have to use g++ for
+ good results, say they have to use stabs. Specifically say cfront
+ doesn't work well.
+ (Summary): Merge in information on Modula-2, Pascal, and Chill from
+ the gdb README. Add xrefs to places where the support for the various
+ languages is described in detail.
+
+Mon Nov 8 11:47:34 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabs.texinfo: Clean up stuff about visibility and virtual
+ characters.
+
+ * stabs.texinfo (N_M2C): Cite Sun doc.
+
+Fri Nov 5 16:27:27 1993 Roland H. Pesch (pesch@fowanton.cygnus.com)
+
+ * gdb.texinfo: updates re threads.
+ * remote.texinfo: avoid index entries starting with digits.
+
+Tue Nov 2 09:08:37 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabs.texinfo (Enumerations): Talk about large, negative and
+ octal values. Clean up cross reference to type attributes.
+ (String Field): Say that GDB 4.11 supports size attribute.
+
+Sun Oct 31 13:31:10 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * remote.texi (VxWorks Remote): Clarify that rebuilding VxWorks kernel
+ is a mandatory step. Make the stuff about that more concise.
+
+Wed Oct 27 00:25:46 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabs.texinfo (Class Names): New node.
+
+ * gdb.texinfo (Command Files): Explain order of init file reading.
+
+ * remote.texi (Bootstrapping): Talk about getting the serial driver
+ to deal with ^C sent by gdb to stop the remote system.
+
+Mon Oct 25 03:25:41 1993 Tom Lord (lord@cygnus.com)
+
+ * libgdb.texinfo (I/O): incorporated better phrasing from rich.
+
+ * libgdb.texinfo (Defining Commands): made the DOC arg
+ to gdb_define_app_command a char * instead of char **
+ per a suggestion from kingdon.
+
+ * libgdb.texinfo: total rewrite from a different starting
+ premise.
+
+Wed Oct 20 18:07:44 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabs.texinfo (Local Variable Parameters): Re-write paragraph on
+ floats passed as doubles (to improve clarity).
+
+Tue Oct 19 14:21:18 1993 Roland H. Pesch (pesch@fowanton.cygnus.com)
+
+ * gdb.texinfo (Source 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/gdb/doc/HPPA-cfg.texi b/gdb/doc/HPPA-cfg.texi
new file mode 100644
index 00000000000..88a138cab8b
--- /dev/null
+++ b/gdb/doc/HPPA-cfg.texi
@@ -0,0 +1,114 @@
+@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:
+@clear GENERIC
+@c
+@c HP PA-RISC target:
+@set HPPA
+@c
+@c Hitachi H8/300 target:
+@clear H8
+@c Hitachi H8/300 target ONLY:
+@clear H8EXCLUSIVE
+@c
+@c remote MIPS target:
+@clear MIPS
+@c
+@c SPARC target:
+@clear SPARC
+@c
+@c AMD 29000 target:
+@clear AMD29K
+@c
+@c Intel 960 target:
+@clear I960
+@c
+@c Tandem ST2000 (phone switch) target:
+@clear ST2000
+@c
+@c Zilog 8000 target:
+@clear Z8K
+@c
+@c Wind River Systems VxWorks environment:
+@clear VXWORKS
+@c
+@c ----------------------------------------------------------------------
+@c DOC FEATURE FLAGS:
+@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?
+@clear FORTRAN
+@c
+@c Discuss Modula 2?
+@clear MOD2
+@c
+@c Specifically for host machine running DOS?
+@clear DOSHOST
+@c
+@c Talk about CPU simulator targets?
+@clear SIMS
+@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?
+@clear REMOTESTUB
+@c
+@c Discuss gdbserver?
+@set GDBSERVER
+@c
+@c Discuss gdbserve.nlm?
+@set GDBSERVE
+@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 target.
+@set TARGET HP 9000 Systems
+@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/gdb/doc/LRS b/gdb/doc/LRS
new file mode 100644
index 00000000000..7e25d432a3e
--- /dev/null
+++ b/gdb/doc/LRS
@@ -0,0 +1,197 @@
+What's LRS?
+===========
+
+LRS, or Live Range Splitting is an optimization technique which allows
+a user variable to reside in different locations during different parts
+of a function.
+
+For example, a variable might reside in the stack for part of a function
+and in a register during a loop and in a different register during
+another loop.
+
+Clearly, if a variable may reside in different locations, then the
+compiler must describe to the debugger where the variable resides for
+any given part of the function.
+
+This document describes the debug format for encoding these extensions
+in stabs.
+
+Since these extensions are gcc specific, these additional symbols and
+stabs can be disabled by the gcc command option -gstabs.
+
+
+GNU extensions for LRS under stabs:
+===================================
+
+
+range symbols:
+-------------
+
+ A range symbol will be used to mark the beginning or end of a
+ live range (the range which describes where a symbol is active,
+ or live). These symbols will later be referenced in the stabs for
+ debug purposes. For simplicity, we'll use the terms "range_start"
+ and "range_end" to identify the range symbols which mark the beginning
+ and end of a live range respectively.
+
+ Any text symbol which would normally appear in the symbol table
+ (eg. a function name) can be used as range symbol. If an address
+ is needed to delimit a live range and does not match any of the
+ values of symbols which would normally appear in the symbol table,
+ a new symbol will be added to the table whose value is that address.
+
+ The three new symbol types described below have been added for this
+ purpose.
+
+ For efficiency, the compiler should use existing symbols as range
+ symbols whenever possible; this reduces the number of additional
+ symbols which need to be added to the symbol table.
+
+
+New debug symbol type for defining ranges:
+------------------------------------------
+
+ range_off - contains PC function offset for start/end of a live range.
+ Its location is relative to the function start and therefore
+ eliminates the need for additional relocation.
+
+ This symbol has a values in the text section, and does not have a name.
+
+ NOTE: the following may not be needed but are included here just
+ in case.
+ range - contains PC value of beginning or end of a live range
+ (relocs required).
+
+ NOTE: the following will be required if we desire LRS debugging
+ to work with old style a.out stabs.
+ range_abs - contains absolute PC value of start/end of a live
+ range. The range_abs debug symbol is provided for
+ completeness, in case there is a need to describe addresses
+ in ROM, etc.
+
+
+Live range:
+-----------
+
+ The compiler and debugger view a variable with multiple homes as
+ a primary symbol and aliases for that symbol. The primary symbol
+ describes the default home of the variable while aliases describe
+ alternate homes for the variable.
+
+ A live range defines the interval of instructions beginning with
+ range_start and ending at range_end-1, and is used to specify a
+ range of instructions where an alias is active or "live". So,
+ the actual end of the range will be one less than the value of the
+ range_end symbol.
+
+ Ranges do not have to be nested. Eg. Two ranges may intersect while
+ each range contains subranges which are not in the other range.
+
+ There does not have to be a 1-1 mapping from range_start to
+ range_end symbols. Eg. Two range_starts can share the same
+ range_end, while one symbol's range_start can be another symbol's
+ range_end.
+
+ When a variable's storage class changes (eg. from stack to register,
+ or from one register to another), a new symbol entry will be
+ added to the symbol table with stabs describing the new type,
+ and appropriate live ranges refering to the variable's initial
+ symbol index.
+
+ For variables which are defined in the source but optimized away,
+ a symbol should be emitted with the live range l(0,0).
+
+ Live ranges for aliases of a particular variable should always
+ be disjoint. Overlapping ranges for aliases of the same variable
+ will be treated as an error by the debugger, and the overlapping
+ range will be ignored.
+
+ If no live range information is given, the live range will be assumed to
+ span the symbol's entire lexical scope.
+
+
+New stabs string identifiers:
+-----------------------------
+
+ "id" in "#id" in the following section refers to a numeric value.
+
+ New stab syntax for live range: l(<ref_from>,<ref_to>)
+
+ <ref_from> - "#id" where #id identifies the text symbol (range symbol) to
+ use as the start of live range (range_start). The value for
+ the referenced text symbol is the starting address of the
+ live range.
+
+ <ref_to> - "#id" where #id identifies the text symbol (range symbol) to
+ use as the end of live range (range_end). The value for
+ the referenced text symbol is ONE BYTE PAST the ending
+ address of the live range.
+
+
+ New stab syntax for identifying symbols.
+
+ <def> - "#id="
+
+ Uses:
+ <def><name>:<typedef1>...
+ When used in front of a symbol name, "#id=" defines a
+ unique reference number for this symbol. The reference
+ number can be used later when defining aliases for this
+ symbol.
+ <def>
+ When used as the entire stab string, "#id=" identifies this
+ nameless symbol as being the symbol for which "#id" refers to.
+
+
+ <ref> - "#id" where "#id" refers to the symbol for which the string
+ "#id=" identifies.
+ Uses:
+ <ref>:<typedef2>;<liverange>;<liverange>...
+ Defines an alias for the symbol identified by the reference
+ number ID.
+ l(<ref1>,<ref2>)
+ When used within a live range, "#id" refers to the text
+ symbol identified by "#id=" to use as the range symbol.
+
+ <liverange> - "l(<ref_from>,<ref_to>)" - specifies a live range for a
+ symbol. Multiple "l" specifiers can be combined to represent
+ mutiple live ranges, separated by semicolons.
+
+
+
+
+Example:
+========
+
+Consider a program of the form:
+
+ void foo(){
+ int a = ...;
+ ...
+ while (b--)
+ c += a;
+ ..
+ d = a;
+ ..
+ }
+
+Assume that "a" lives in the stack at offset -8, except for inside the
+loop where "a" resides in register "r5".
+
+The way to describe this is to create a stab for the variable "a" which
+describes "a" as living in the stack and an alias for the variable "a"
+which describes it as living in register "r5" in the loop.
+
+Let's assume that "#1" and "#2" are symbols which bound the area where
+"a" lives in a register.
+
+The stabs to describe "a" and its alias would look like this:
+
+ .stabs "#3=a:1",128,0,8,-8
+ .stabs "#3:r1;l(#1,#2)",64,0,0,5
+
+
+This design implies that the debugger will keep a chain of aliases for
+any given variable with aliases and that chain will be searched first
+to find out if an alias is active. If no alias is active, then the
+debugger will assume that the main variable is active.
diff --git a/gdb/doc/Makefile.in b/gdb/doc/Makefile.in
new file mode 100644
index 00000000000..4bcd62ec164
--- /dev/null
+++ b/gdb/doc/Makefile.in
@@ -0,0 +1,340 @@
+##Copyright (C) 1991, 1992, 1999 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+prefix = @prefix@
+
+infodir = @infodir@
+
+SHELL = @SHELL@
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA = @INSTALL_DATA@
+
+# 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
+
+# Program to generate Postscript files from DVI files.
+DVIPS = dvips
+
+# 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 gdbint.dvi stabs.dvi refcard.dvi
+ps: gdb.ps gdbint.ps stabs.ps refcard.ps
+all-doc: info dvi ps
+
+install-info: info
+ for i in *.info* ; do \
+ $(INSTALL_DATA) $$i $(infodir)/$$i ; \
+ done
+
+STAGESTUFF = *.info* gdb-all.texi GDBvn.texi *.ps *.dvi
+
+# 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
+
+# The "least clean" level of cleaning. Get rid of files which are
+# automatically generated files that are just intermediate files,
+#
+mostlyclean:
+ rm -f gdb.mm gdb.ms gdb.me links2roff
+ rm -f *.aux *.cp* *.fn* *.ky* *.log *.pg* *.toc *.tp* *.vr*
+ rm -f sedref.dvi sedref.tex tmp.sed
+
+clean: mostlyclean
+ rm -f rluser.texinfo inc-hist.texi gdb-cfg.texi
+
+distclean: clean
+ rm -f Makefile config.status
+
+# GDBvn.texi, the dvi files, the info files, and the postscript files,
+# are all part of the distribution, so it should not be removed by
+# "clean" or "distclean". Use maintainer-clean to remove them.
+
+maintainer-clean realclean: distclean
+ rm -f GDBvn.texi *.info* *.dvi *.ps
+
+# 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 -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.aux gdb.cp* gdb.fn* gdb.ky* gdb.log gdb.pg* gdb.toc \
+ gdb.tp* gdb.vr*
+
+gdb.ps: gdb.dvi
+ $(DVIPS) -o $@ $?
+
+# 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.aux gdbint.cp* gdbint.fn* gdbint.ky* \
+ gdbint.log gdbint.pg* gdbint.toc gdbint.tp* gdbint.vr*
+
+gdbint.ps : gdbint.dvi
+ $(DVIPS) -o $@ $?
+
+# GDB INTERNALS MANUAL: info file
+
+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.aux stabs.cp* stabs.fn* stabs.ky* \
+ stabs.log stabs.pg* stabs.toc stabs.tp* stabs.vr*
+
+stabs.ps: stabs.dvi
+ $(DVIPS) -o $@ $?
+
+force:
+
+Makefile: Makefile.in $(host_makefile_frag) $(target_makefile_frag) config.status
+ $(SHELL) ./config.status
diff --git a/gdb/doc/a4rc.sed b/gdb/doc/a4rc.sed
new file mode 100644
index 00000000000..22922904efc
--- /dev/null
+++ b/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/gdb/doc/agentexpr.texi b/gdb/doc/agentexpr.texi
new file mode 100644
index 00000000000..4b790f56af2
--- /dev/null
+++ b/gdb/doc/agentexpr.texi
@@ -0,0 +1,839 @@
+\input texinfo
+@c %**start of header
+@setfilename agentexpr.info
+@settitle GDB Agent Expressions
+@setchapternewpage off
+@c %**end of header
+
+Revision: $Id$
+
+@node The GDB Agent Expression Mechanism
+@chapter The GDB Agent Expression Mechanism
+
+In some applications, it is not feasable for the debugger to interrupt
+the program's execution long enough for the developer to learn anything
+helpful about its behavior. If the program's correctness depends on its
+real-time behavior, delays introduced by a debugger might cause the
+program to fail, even when the code itself is correct. It is useful to
+be able to observe the program's behavior without interrupting it.
+
+Using GDB's @code{trace} and @code{collect} commands, the user can
+specify locations in the program, and arbitrary expressions to evaluate
+when those locations are reached. Later, using the @code{tfind}
+command, she can examine the values those expressions had when the
+program hit the trace points. The expressions may also denote objects
+in memory --- structures or arrays, for example --- whose values GDB
+should record; while visiting a particular tracepoint, the user may
+inspect those objects as if they were in memory at that moment.
+However, because GDB records these values without interacting with the
+user, it can do so quickly and unobtrusively, hopefully not disturbing
+the program's behavior.
+
+When GDB is debugging a remote target, the GDB @dfn{agent} code running
+on the target computes the values of the expressions itself. To avoid
+having a full symbolic expression evaluator on the agent, GDB translates
+expressions in the source language into a simpler bytecode language, and
+then sends the bytecode to the agent; the agent then executes the
+bytecode, and records the values for GDB to retrieve later.
+
+The bytecode language is simple; there are forty-odd opcodes, the bulk
+of which are the usual vocabulary of C operands (addition, subtraction,
+shifts, and so on) and various sizes of literals and memory reference
+operations. The bytecode interpreter operates strictly on machine-level
+values --- various sizes of integers and floating point numbers --- and
+requires no information about types or symbols; thus, the interpreter's
+internal data structures are simple, and each bytecode requires only a
+few native machine instructions to implement it. The interpreter is
+small, and strict limits on the memory and time required to evaluate an
+expression are easy to determine, making it suitable for use by the
+debugging agent in real-time applications.
+
+@menu
+* General Bytecode Design:: Overview of the interpreter.
+* Bytecode Descriptions:: What each one does.
+* Using Agent Expressions:: How agent expressions fit into the big picture.
+* Varying Target Capabilities:: How to discover what the target can do.
+* Tracing on Symmetrix:: Special info for implementation on EMC's
+ boxes.
+* Rationale:: Why we did it this way.
+@end menu
+
+
+@c @node Rationale
+@c @section Rationale
+
+
+@node General Bytecode Design
+@section General Bytecode Design
+
+The agent represents bytecode expressions as an array of bytes. Each
+instruction is one byte long (thus the term @dfn{bytecode}). Some
+instructions are followed by operand bytes; for example, the @code{goto}
+instruction is followed by a destination for the jump.
+
+The bytecode interpreter is a stack-based machine; most instructions pop
+their operands off the stack, perform some operation, and push the
+result back on the stack for the next instruction to consume. Each
+element of the stack may contain either a integer or a floating point
+value; these values are as many bits wide as the largest integer that
+can be directly manipulated in the source language. Stack elements
+carry no record of their type; bytecode could push a value as an
+integer, then pop it as a floating point value. However, GDB will not
+generate code which does this. In C, one might define the type of a
+stack element as follows:
+@example
+union agent_val @{
+ LONGEST l;
+ DOUBLEST d;
+@};
+@end example
+@noindent
+where @code{LONGEST} and @code{DOUBLEST} are @code{typedef} names for
+the largest integer and floating point types on the machine.
+
+By the time the bytecode interpreter reaches the end of the expression,
+the value of the expression should be the only value left on the stack.
+For tracing applications, @code{trace} bytecodes in the expression will
+have recorded the necessary data, and the value on the stack may be
+discarded. For other applications, like conditional breakpoints, the
+value may be useful.
+
+Separate from the stack, the interpreter has two registers:
+@table @code
+@item pc
+The address of the next bytecode to execute.
+
+@item start
+The address of the start of the bytecode expression, necessary for
+interpreting the @code{goto} and @code{if_goto} instructions.
+
+@end table
+@noindent
+Neither of these registers is directly visible to the bytecode language
+itself, but they are useful for defining the meanings of the bytecode
+operations.
+
+There are no instructions to perform side effects on the running
+program, or call the program's functions; we assume that these
+expressions are only used for unobtrusive debugging, not for patching
+the running code.
+
+Most bytecode instructions do not distinguish between the various sizes
+of values, and operate on full-width values; the upper bits of the
+values are simply ignored, since they do not usually make a difference
+to the value computed. The exceptions to this rule are:
+@table @asis
+
+@item memory reference instructions (@code{ref}@var{n})
+There are distinct instructions to fetch different word sizes from
+memory. Once on the stack, however, the values are treated as full-size
+integers. They may need to be sign-extended; the @code{ext} instruction
+exists for this purpose.
+
+@item the sign-extension instruction (@code{ext} @var{n})
+These clearly need to know which portion of their operand is to be
+extended to occupy the full length of the word.
+
+@end table
+
+If the interpreter is unable to evaluate an expression completely for
+some reason (a memory location is inaccessible, or a divisor is zero,
+for example), we say that interpretation ``terminates with an error''.
+This means that the problem is reported back to the interpreter's caller
+in some helpful way. In general, code using agent expressions should
+assume that they may attempt to divide by zero, fetch arbitrary memory
+locations, and misbehave in other ways.
+
+Even complicated C expressions compile to a few bytecode instructions;
+for example, the expression @code{x + y * z} would typically produce
+code like the following, assuming that @code{x} and @code{y} live in
+registers, and @code{z} is a global variable holding a 32-bit
+@code{int}:
+@example
+reg 1
+reg 2
+const32 @i{address of z}
+ref32
+ext 32
+mul
+add
+end
+@end example
+
+In detail, these mean:
+@table @code
+
+@item reg 1
+Push the value of register 1 (presumably holding @code{x}) onto the
+stack.
+
+@item reg 2
+Push the value of register 2 (holding @code{y}).
+
+@item const32 @i{address of z}
+Push the address of @code{z} onto the stack.
+
+@item ref32
+Fetch a 32-bit word from the address at the top of the stack; replace
+the address on the stack with the value. Thus, we replace the address
+of @code{z} with @code{z}'s value.
+
+@item ext 32
+Sign-extend the value on the top of the stack from 32 bits to full
+length. This is necessary because @code{z} is a signed integer.
+
+@item mul
+Pop the top two numbers on the stack, multiply them, and push their
+product. Now the top of the stack contains the value of the expression
+@code{y * z}.
+
+@item add
+Pop the top two numbers, add them, and push the sum. Now the top of the
+stack contains the value of @code{x + y * z}.
+
+@item end
+Stop executing; the value left on the stack top is the value to be
+recorded.
+
+@end table
+
+
+@node Bytecode Descriptions
+@section Bytecode Descriptions
+
+Each bytecode description has the following form:
+
+@table @asis
+
+@item @code{add} (0x02): @var{a} @var{b} @result{} @var{a+b}
+
+Pop the top two stack items, @var{a} and @var{b}, as integers; push
+their sum, as an integer.
+
+@end table
+
+In this example, @code{add} is the name of the bytecode, and
+@code{(0x02)} is the one-byte value used to encode the bytecode, in
+hexidecimal. The phrase ``@var{a} @var{b} @result{} @var{a+b}'' shows
+the stack before and after the bytecode executes. Beforehand, the stack
+must contain at least two values, @var{a} and @var{b}; since the top of
+the stack is to the right, @var{b} is on the top of the stack, and
+@var{a} is underneath it. After execution, the bytecode will have
+popped @var{a} and @var{b} from the stack, and replaced them with a
+single value, @var{a+b}. There may be other values on the stack below
+those shown, but the bytecode affects only those shown.
+
+Here is another example:
+
+@table @asis
+
+@item @code{const8} (0x22) @var{n}: @result{} @var{n}
+Push the 8-bit integer constant @var{n} on the stack, without sign
+extension.
+
+@end table
+
+In this example, the bytecode @code{const8} takes an operand @var{n}
+directly from the bytecode stream; the operand follows the @code{const8}
+bytecode itself. We write any such operands immediately after the name
+of the bytecode, before the colon, and describe the exact encoding of
+the operand in the bytecode stream in the body of the bytecode
+description.
+
+For the @code{const8} bytecode, there are no stack items given before
+the @result{}; this simply means that the bytecode consumes no values
+from the stack. If a bytecode consumes no values, or produces no
+values, the list on either side of the @result{} may be empty.
+
+If a value is written as @var{a}, @var{b}, or @var{n}, then the bytecode
+treats it as an integer. If a value is written is @var{addr}, then the
+bytecode treats it as an address.
+
+We do not fully describe the floating point operations here; although
+this design can be extended in a clean way to handle floating point
+values, they are not of immediate interest to the customer, so we avoid
+describing them, to save time.
+
+
+@table @asis
+
+@item @code{float} (0x01): @result{}
+
+Prefix for floating-point bytecodes. Not implemented yet.
+
+@item @code{add} (0x02): @var{a} @var{b} @result{} @var{a+b}
+Pop two integers from the stack, and push their sum, as an integer.
+
+@item @code{sub} (0x03): @var{a} @var{b} @result{} @var{a-b}
+Pop two integers from the stack, subtract the top value from the
+next-to-top value, and push the difference.
+
+@item @code{mul} (0x04): @var{a} @var{b} @result{} @var{a*b}
+Pop two integers from the stack, multiply them, and push the product on
+the stack. Note that, when one multiplies two @var{n}-bit numbers
+yielding another @var{n}-bit number, it is irrelevant whether the
+numbers are signed or not; the results are the same.
+
+@item @code{div_signed} (0x05): @var{a} @var{b} @result{} @var{a/b}
+Pop two signed integers from the stack; divide the next-to-top value by
+the top value, and push the quotient. If the divisor is zero, terminate
+with an error.
+
+@item @code{div_unsigned} (0x06): @var{a} @var{b} @result{} @var{a/b}
+Pop two unsigned integers from the stack; divide the next-to-top value
+by the top value, and push the quotient. If the divisor is zero,
+terminate with an error.
+
+@item @code{rem_signed} (0x07): @var{a} @var{b} @result{} @var{a modulo b}
+Pop two signed integers from the stack; divide the next-to-top value by
+the top value, and push the remainder. If the divisor is zero,
+terminate with an error.
+
+@item @code{rem_unsigned} (0x08): @var{a} @var{b} @result{} @var{a modulo b}
+Pop two unsigned integers from the stack; divide the next-to-top value
+by the top value, and push the remainder. If the divisor is zero,
+terminate with an error.
+
+@item @code{lsh} (0x09): @var{a} @var{b} @result{} @var{a<<b}
+Pop two integers from the stack; let @var{a} be the next-to-top value,
+and @var{b} be the top value. Shift @var{a} left by @var{b} bits, and
+push the result.
+
+@item @code{rsh_signed} (0x0a): @var{a} @var{b} @result{} @var{@code{(signed)}a>>b}
+Pop two integers from the stack; let @var{a} be the next-to-top value,
+and @var{b} be the top value. Shift @var{a} right by @var{b} bits,
+inserting copies of the top bit at the high end, and push the result.
+
+@item @code{rsh_unsigned} (0x0b): @var{a} @var{b} @result{} @var{a>>b}
+Pop two integers from the stack; let @var{a} be the next-to-top value,
+and @var{b} be the top value. Shift @var{a} right by @var{b} bits,
+inserting zero bits at the high end, and push the result.
+
+@item @code{log_not} (0x0e): @var{a} @result{} @var{!a}
+Pop an integer from the stack; if it is zero, push the value one;
+otherwise, push the value zero.
+
+@item @code{bit_and} (0x0f): @var{a} @var{b} @result{} @var{a&b}
+Pop two integers from the stack, and push their bitwise @code{and}.
+
+@item @code{bit_or} (0x10): @var{a} @var{b} @result{} @var{a|b}
+Pop two integers from the stack, and push their bitwise @code{or}.
+
+@item @code{bit_xor} (0x11): @var{a} @var{b} @result{} @var{a^b}
+Pop two integers from the stack, and push their bitwise
+exclusive-@code{or}.
+
+@item @code{bit_not} (0x12): @var{a} @result{} @var{~a}
+Pop an integer from the stack, and push its bitwise complement.
+
+@item @code{equal} (0x13): @var{a} @var{b} @result{} @var{a=b}
+Pop two integers from the stack; if they are equal, push the value one;
+otherwise, push the value zero.
+
+@item @code{less_signed} (0x14): @var{a} @var{b} @result{} @var{a<b}
+Pop two signed integers from the stack; if the next-to-top value is less
+than the top value, push the value one; otherwise, push the value zero.
+
+@item @code{less_unsigned} (0x15): @var{a} @var{b} @result{} @var{a<b}
+Pop two unsigned integers from the stack; if the next-to-top value is less
+than the top value, push the value one; otherwise, push the value zero.
+
+@item @code{ext} (0x16) @var{n}: @var{a} @result{} @var{a}, sign-extended from @var{n} bits
+Pop an unsigned value from the stack; treating it as an @var{n}-bit
+twos-complement value, extend it to full length. This means that all
+bits to the left of bit @var{n-1} (where the least significant bit is bit
+0) are set to the value of bit @var{n-1}. Note that @var{n} may be
+larger than or equal to the width of the stack elements of the bytecode
+engine; in this case, the bytecode should have no effect.
+
+The number of source bits to preserve, @var{n}, is encoded as a single
+byte unsigned integer following the @code{ext} bytecode.
+
+@item @code{zero_ext} (0x2a) @var{n}: @var{a} @result{} @var{a}, zero-extended from @var{n} bits
+Pop an unsigned value from the stack; zero all but the bottom @var{n}
+bits. This means that all bits to the left of bit @var{n-1} (where the
+least significant bit is bit 0) are set to the value of bit @var{n-1}.
+
+The number of source bits to preserve, @var{n}, is encoded as a single
+byte unsigned integer following the @code{zero_ext} bytecode.
+
+@item @code{ref8} (0x17): @var{addr} @result{} @var{a}
+@itemx @code{ref16} (0x18): @var{addr} @result{} @var{a}
+@itemx @code{ref32} (0x19): @var{addr} @result{} @var{a}
+@itemx @code{ref64} (0x1a): @var{addr} @result{} @var{a}
+Pop an address @var{addr} from the stack. For bytecode
+@code{ref}@var{n}, fetch an @var{n}-bit value from @var{addr}, using the
+natural target endianness. Push the fetched value as an unsigned
+integer.
+
+Note that @var{addr} may not be aligned in any particular way; the
+@code{ref@var{n}} bytecodes should operate correctly for any address.
+
+If attempting to access memory at @var{addr} would cause a processor
+exception of some sort, terminate with an error.
+
+@item @code{ref_float} (0x1b): @var{addr} @result{} @var{d}
+@itemx @code{ref_double} (0x1c): @var{addr} @result{} @var{d}
+@itemx @code{ref_long_double} (0x1d): @var{addr} @result{} @var{d}
+@itemx @code{l_to_d} (0x1e): @var{a} @result{} @var{d}
+@itemx @code{d_to_l} (0x1f): @var{d} @result{} @var{a}
+Not implemented yet.
+
+@item @code{dup} (0x28): @var{a} => @var{a} @var{a}
+Push another copy of the stack's top element.
+
+@item @code{swap} (0x2b): @var{a} @var{b} => @var{b} @var{a}
+Exchange the top two items on the stack.
+
+@item @code{pop} (0x29): @var{a} =>
+Discard the top value on the stack.
+
+@item @code{if_goto} (0x20) @var{offset}: @var{a} @result{}
+Pop an integer off the stack; if it is non-zero, branch to the given
+offset in the bytecode string. Otherwise, continue to the next
+instruction in the bytecode stream. In other words, if @var{a} is
+non-zero, set the @code{pc} register to @code{start} + @var{offset}.
+Thus, an offset of zero denotes the beginning of the expression.
+
+The @var{offset} is stored as a sixteen-bit unsigned value, stored
+immediately following the @code{if_goto} bytecode. It is always stored
+most signficant byte first, regardless of the target's normal
+endianness. The offset is not guaranteed to fall at any particular
+alignment within the bytecode stream; thus, on machines where fetching a
+16-bit on an unaligned address raises an exception, you should fetch the
+offset one byte at a time.
+
+@item @code{goto} (0x21) @var{offset}: @result{}
+Branch unconditionally to @var{offset}; in other words, set the
+@code{pc} register to @code{start} + @var{offset}.
+
+The offset is stored in the same way as for the @code{if_goto} bytecode.
+
+@item @code{const8} (0x22) @var{n}: @result{} @var{n}
+@itemx @code{const16} (0x23) @var{n}: @result{} @var{n}
+@itemx @code{const32} (0x24) @var{n}: @result{} @var{n}
+@itemx @code{const64} (0x25) @var{n}: @result{} @var{n}
+Push the integer constant @var{n} on the stack, without sign extension.
+To produce a small negative value, push a small twos-complement value,
+and then sign-extend it using the @code{ext} bytecode.
+
+The constant @var{n} is stored in the appropriate number of bytes
+following the @code{const}@var{b} bytecode. The constant @var{n} is
+always stored most significant byte first, regardless of the target's
+normal endianness. The constant is not guaranteed to fall at any
+particular alignment within the bytecode stream; thus, on machines where
+fetching a 16-bit on an unaligned address raises an exception, you
+should fetch @var{n} one byte at a time.
+
+@item @code{reg} (0x26) @var{n}: @result{} @var{a}
+Push the value of register number @var{n}, without sign extension. The
+registers are numbered following GDB's conventions.
+
+The register number @var{n} is encoded as a 16-bit unsigned integer
+immediately following the @code{reg} bytecode. It is always stored most
+signficant byte first, regardless of the target's normal endianness.
+The register number is not guaranteed to fall at any particular
+alignment within the bytecode stream; thus, on machines where fetching a
+16-bit on an unaligned address raises an exception, you should fetch the
+register number one byte at a time.
+
+@item @code{trace} (0x0c): @var{addr} @var{size} @result{}
+Record the contents of the @var{size} bytes at @var{addr} in a trace
+buffer, for later retrieval by GDB.
+
+@item @code{trace_quick} (0x0d) @var{size}: @var{addr} @result{} @var{addr}
+Record the contents of the @var{size} bytes at @var{addr} in a trace
+buffer, for later retrieval by GDB. @var{size} is a single byte
+unsigned integer following the @code{trace} opcode.
+
+This bytecode is equivalent to the sequence @code{dup const8 @var{size}
+trace}, but we provide it anyway to save space in bytecode strings.
+
+@item @code{trace16} (0x30) @var{size}: @var{addr} @result{} @var{addr}
+Identical to trace_quick, except that @var{size} is a 16-bit big-endian
+unsigned integer, not a single byte. This should probably have been
+named @code{trace_quick16}, for consistency.
+
+@item @code{end} (0x27): @result{}
+Stop executing bytecode; the result should be the top element of the
+stack. If the purpose of the expression was to compute an lvalue or a
+range of memory, then the next-to-top of the stack is the lvalue's
+address, and the top of the stack is the lvalue's size, in bytes.
+
+@end table
+
+
+@node Using Agent Expressions
+@section Using Agent Expressions
+
+Here is a sketch of a full non-stop debugging cycle, showing how agent
+expressions fit into the process.
+
+@itemize @bullet
+
+@item
+The user selects trace points in the program's code at which GDB should
+collect data.
+
+@item
+The user specifies expressions to evaluate at each trace point. These
+expressions may denote objects in memory, in which case those objects'
+contents are recorded as the program runs, or computed values, in which
+case the values themselves are recorded.
+
+@item
+GDB transmits the tracepoints and their associated expressions to the
+GDB agent, running on the debugging target.
+
+@item
+The agent arranges to be notified when a trace point is hit. Note that,
+on some systems, the target operating system is completely responsible
+for collecting the data; see @ref{Tracing on Symmetrix}.
+
+@item
+When execution on the target reaches a trace point, the agent evaluates
+the expressions associated with that trace point, and records the
+resulting values and memory ranges.
+
+@item
+Later, when the user selects a given trace event and inspects the
+objects and expression values recorded, GDB talks to the agent to
+retrieve recorded data as necessary to meet the user's requests. If the
+user asks to see an object whose contents have not been recorded, GDB
+reports an error.
+
+@end itemize
+
+
+@node Varying Target Capabilities
+@section Varying Target Capabilities
+
+Some targets don't support floating-point, and some would rather not
+have to deal with @code{long long} operations. Also, different targets
+will have different stack sizes, and different bytecode buffer lengths.
+
+Thus, GDB needs a way to ask the target about itself. We haven't worked
+out the details yet, but in general, GDB should be able to send the
+target a packet asking it to describe itself. The reply should be a
+packet whose length is explicit, so we can add new information to the
+packet in future revisions of the agent, without confusing old versions
+of GDB, and it should contain a version number. It should contain at
+least the following information:
+
+@itemize @bullet
+
+@item
+whether floating point is supported
+
+@item
+whether @code{long long} is supported
+
+@item
+maximum acceptable size of bytecode stack
+
+@item
+maximum acceptable length of bytecode expressions
+
+@item
+which registers are actually available for collection
+
+@item
+whether the target supports disabled tracepoints
+
+@end itemize
+
+
+
+@node Tracing on Symmetrix
+@section Tracing on Symmetrix
+
+This section documents the API used by the GDB agent to collect data on
+Symmetrix systems.
+
+Cygnus originally implemented these tracing features to help EMC
+Corporation debug their Symmetrix high-availability disk drives. The
+Symmetrix application code already includes substantial tracing
+facilities; the GDB agent for the Symmetrix system uses those facilities
+for its own data collection, via the API described here.
+
+@deftypefn Function DTC_RESPONSE adbg_find_memory_in_frame (FRAME_DEF *@var{frame}, char *@var{address}, char **@var{buffer}, unsigned int *@var{size})
+Search the trace frame @var{frame} for memory saved from @var{address}.
+If the memory is available, provide the address of the buffer holding
+it; otherwise, provide the address of the next saved area.
+
+@itemize @bullet
+
+@item
+If the memory at @var{address} was saved in @var{frame}, set
+@code{*@var{buffer}} to point to the buffer in which that memory was
+saved, set @code{*@var{size}} to the number of bytes from @var{address}
+that are saved at @code{*@var{buffer}}, and return
+@code{OK_TARGET_RESPONSE}. (Clearly, in this case, the function will
+always set @code{*@var{size}} to a value greater than zero.)
+
+@item
+If @var{frame} does not record any memory at @var{address}, set
+@code{*@var{size}} to the distance from @var{address} to the start of
+the saved region with the lowest address higher than @var{address}. If
+there is no memory saved from any higher address, set @code{*@var{size}}
+to zero. Return @code{NOT_FOUND_TARGET_RESPONSE}.
+@end itemize
+
+These two possibilities allow the caller to either retrieve the data, or
+walk the address space to the next saved area.
+@end deftypefn
+
+This function allows the GDB agent to map the regions of memory saved in
+a particular frame, and retrieve their contents efficiently.
+
+This function also provides a clean interface between the GDB agent and
+the Symmetrix tracing structures, making it easier to adapt the GDB
+agent to future versions of the Symmetrix system, and vice versa. This
+function searches all data saved in @var{frame}, whether the data is
+there at the request of a bytecode expression, or because it falls in
+one of the format's memory ranges, or because it was saved from the top
+of the stack. EMC can arbitrarily change and enhance the tracing
+mechanism, but as long as this function works properly, all collected
+memory is visible to GDB.
+
+The function itself is straightforward to implement. A single pass over
+the trace frame's stack area, memory ranges, and expression blocks can
+yield the address of the buffer (if the requested address was saved),
+and also note the address of the next higher range of memory, to be
+returned when the search fails.
+
+As an example, suppose the trace frame @code{f} has saved sixteen bytes
+from address @code{0x8000} in a buffer at @code{0x1000}, and thirty-two
+bytes from address @code{0xc000} in a buffer at @code{0x1010}. Here are
+some sample calls, and the effect each would have:
+
+@table @code
+
+@item adbg_find_memory_in_frame (f, (char*) 0x8000, &buffer, &size)
+This would set @code{buffer} to @code{0x1000}, set @code{size} to
+sixteen, and return @code{OK_TARGET_RESPONSE}, since @code{f} saves
+sixteen bytes from @code{0x8000} at @code{0x1000}.
+
+@item adbg_find_memory_in_frame (f, (char *) 0x8004, &buffer, &size)
+This would set @code{buffer} to @code{0x1004}, set @code{size} to
+twelve, and return @code{OK_TARGET_RESPONSE}, since @file{f} saves the
+twelve bytes from @code{0x8004} starting four bytes into the buffer at
+@code{0x1000}. This shows that request addresses may fall in the middle
+of saved areas; the function should return the address and size of the
+remainder of the buffer.
+
+@item adbg_find_memory_in_frame (f, (char *) 0x8100, &buffer, &size)
+This would set @code{size} to @code{0x3f00} and return
+@code{NOT_FOUND_TARGET_RESPONSE}, since there is no memory saved in
+@code{f} from the address @code{0x8100}, and the next memory available
+is at @code{0x8100 + 0x3f00}, or @code{0xc000}. This shows that request
+addresses may fall outside of all saved memory ranges; the function
+should indicate the next saved area, if any.
+
+@item adbg_find_memory_in_frame (f, (char *) 0x7000, &buffer, &size)
+This would set @code{size} to @code{0x1000} and return
+@code{NOT_FOUND_TARGET_RESPONSE}, since the next saved memory is at
+@code{0x7000 + 0x1000}, or @code{0x8000}.
+
+@item adbg_find_memory_in_frame (f, (char *) 0xf000, &buffer, &size)
+This would set @code{size} to zero, and return
+@code{NOT_FOUND_TARGET_RESPONSE}. This shows how the function tells the
+caller that no further memory ranges have been saved.
+
+@end table
+
+As another example, here is a function which will print out the
+addresses of all memory saved in the trace frame @code{frame} on the
+Symmetrix INLINES console:
+@example
+void
+print_frame_addresses (FRAME_DEF *frame)
+@{
+ char *addr;
+ char *buffer;
+ unsigned long size;
+
+ addr = 0;
+ for (;;)
+ @{
+ /* Either find out how much memory we have here, or discover
+ where the next saved region is. */
+ if (adbg_find_memory_in_frame (frame, addr, &buffer, &size)
+ == OK_TARGET_RESPONSE)
+ printp ("saved %x to %x\n", addr, addr + size);
+ if (size == 0)
+ break;
+ addr += size;
+ @}
+@}
+@end example
+
+Note that there is not necessarily any connection between the order in
+which the data is saved in the trace frame, and the order in which
+@code{adbg_find_memory_in_frame} will return those memory ranges. The
+code above will always print the saved memory regions in order of
+increasing address, while the underlying frame structure might store the
+data in a random order.
+
+[[This section should cover the rest of the Symmetrix functions the stub
+relies upon, too.]]
+
+@node Rationale
+@section Rationale
+
+Some of the design decisions apparent above are arguable.
+
+@table @b
+
+@item What about stack overflow/underflow?
+GDB should be able to query the target to discover its stack size.
+Given that information, GDB can determine at translation time whether a
+given expression will overflow the stack. But this spec isn't about
+what kinds of error-checking GDB ought to do.
+
+@item Why are you doing everything in LONGEST?
+
+Speed isn't important, but agent code size is; using LONGEST brings in a
+bunch of support code to do things like division, etc. So this is a
+serious concern.
+
+First, note that you don't need different bytecodes for different
+operand sizes. You can generate code without @emph{knowing} how big the
+stack elements actually are on the target. If the target only supports
+32-bit ints, and you don't send any 64-bit bytecodes, everything just
+works. The observation here is that the MIPS and the Alpha have only
+fixed-size registers, and you can still get C's semantics even though
+most instructions only operate on full-sized words. You just need to
+make sure everything is properly sign-extended at the right times. So
+there is no need for 32- and 64-bit variants of the bytecodes. Just
+implement everything using the largest size you support.
+
+GDB should certainly check to see what sizes the target supports, so the
+user can get an error earlier, rather than later. But this information
+is not necessary for correctness.
+
+
+@item Why don't you have @code{>} or @code{<=} operators?
+I want to keep the interpreter small, and we don't need them. We can
+combine the @code{less_} opcodes with @code{log_not}, and swap the order
+of the operands, yielding all four asymmetrical comparison operators.
+For example, @code{(x <= y)} is @code{! (x > y)}, which is @code{! (y <
+x)}.
+
+@item Why do you have @code{log_not}?
+@itemx Why do you have @code{ext}?
+@itemx Why do you have @code{zero_ext}?
+These are all easily synthesized from other instructions, but I expect
+them to be used frequently, and they're simple, so I include them to
+keep bytecode strings short.
+
+@code{log_not} is equivalent to @code{const8 0 equal}; it's used in half
+the relational operators.
+
+@code{ext @var{n}} is equivalent to @code{const8 @var{s-n} lsh const8
+@var{s-n} rsh_signed}, where @var{s} is the size of the stack elements;
+it follows @code{ref@var{m}} and @var{reg} bytecodes when the value
+should be signed. See the next bulleted item.
+
+@code{zero_ext @var{n}} is equivalent to @code{const@var{m} @var{mask}
+log_and}; it's used whenever we push the value of a register, because we
+can't assume the upper bits of the register aren't garbage.
+
+@item Why not have sign-extending variants of the @code{ref} operators?
+Because that would double the number of @code{ref} operators, and we
+need the @code{ext} bytecode anyway for accessing bitfields.
+
+@item Why not have constant-address variants of the @code{ref} operators?
+Because that would double the number of @code{ref} operators again, and
+@code{const32 @var{address} ref32} is only one byte longer.
+
+@item Why do the @code{ref@var{n}} operators have to support unaligned fetches?
+GDB will generate bytecode that fetches multi-byte values at unaligned
+addresses whenever the executable's debugging information tells it to.
+Furthermore, GDB does not know the value the pointer will have when GDB
+generates the bytecode, so it cannot determine whether a particular
+fetch will be aligned or not.
+
+In particular, structure bitfields may be several bytes long, but follow
+no alignment rules; members of packed structures are not necessarily
+aligned either.
+
+In general, there are many cases where unaligned references occur in
+correct C code, either at the programmer's explicit request, or at the
+compiler's discretion. Thus, it is simpler to make the GDB agent
+bytecodes work correctly in all circumstances than to make GDB guess in
+each case whether the compiler did the usual thing.
+
+@item Why are there no side-effecting operators?
+Because our current client doesn't want them? That's a cheap answer. I
+think the real answer is that I'm afraid of implementing function
+calls. We should re-visit this issue after the present contract is
+delivered.
+
+@item Why aren't the @code{goto} ops PC-relative?
+The interpreter has the base address around anyway for PC bounds
+checking, and it seemed simpler.
+
+@item Why is there only one offset size for the @code{goto} ops?
+Offsets are currently sixteen bits. I'm not happy with this situation
+either:
+
+Suppose we have multiple branch ops with different offset sizes. As I
+generate code left-to-right, all my jumps are forward jumps (there are
+no loops in expressions), so I never know the target when I emit the
+jump opcode. Thus, I have to either always assume the largest offset
+size, or do jump relaxation on the code after I generate it, which seems
+like a big waste of time.
+
+I can imagine a reasonable expression being longer than 256 bytes. I
+can't imagine one being longer than 64k. Thus, we need 16-bit offsets.
+This kind of reasoning is so bogus, but relaxation is pathetic.
+
+The other approach would be to generate code right-to-left. Then I'd
+always know my offset size. That might be fun.
+
+@item Where is the function call bytecode?
+
+When we add side-effects, we should add this.
+
+@item Why does the @code{reg} bytecode take a 16-bit register number?
+
+Intel's IA64-architecture, Merced, has 128 general-purpose registers,
+and 128 floating-point registers, and I'm sure it has some random
+control registers.
+
+@item Why do we need @code{trace} and @code{trace_quick}?
+Because GDB needs to record all the memory contents and registers an
+expression touches. If the user wants to evaluate an expression
+@code{x->y->z}, the agent must record the values of @code{x} and
+@code{x->y} as well as the value of @code{x->y->z}.
+
+@item Don't the @code{trace} bytecodes make the interpreter less general?
+They do mean that the interpreter contains special-purpose code, but
+that doesn't mean the interpreter can only be used for that purpose. If
+an expression doesn't use the @code{trace} bytecodes, they don't get in
+its way.
+
+@item Why doesn't @code{trace_quick} consume its arguments the way everything else does?
+In general, you do want your operators to consume their arguments; it's
+consistent, and generally reduces the amount of stack rearrangement
+necessary. However, @code{trace_quick} is a kludge to save space; it
+only exists so we needn't write @code{dup const8 @var{SIZE} trace}
+before every memory reference. Therefore, it's okay for it not to
+consume its arguments; it's meant for a specific context in which we
+know exactly what it should do with the stack. If we're going to have a
+kludge, it should be an effective kludge.
+
+@item Why does @code{trace16} exist?
+That opcode was added by the customer that contracted Cygnus for the
+data tracing work. I personally think it is unnecessary; objects that
+large will be quite rare, so it is okay to use @code{dup const16
+@var{size} trace} in those cases.
+
+Whatever we decide to do with @code{trace16}, we should at least leave
+opcode 0x30 reserved, to remain compatible with the customer who added
+it.
+
+@end table
+
+@bye
diff --git a/gdb/doc/all-cfg.texi b/gdb/doc/all-cfg.texi
new file mode 100644
index 00000000000..74d8090b51b
--- /dev/null
+++ b/gdb/doc/all-cfg.texi
@@ -0,0 +1,112 @@
+@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 HP PA-RISC target ONLY:
+@clear HPPA
+@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
+@set SPARCLET
+@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 Wind River Systems VxWorks environment:
+@set VXWORKS
+@c
+@c ----------------------------------------------------------------------
+@c DOC FEATURE FLAGS:
+@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 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 Discuss gdbserve.nlm?
+@set GDBSERVE
+@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 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/gdb/doc/annotate.texi b/gdb/doc/annotate.texi
new file mode 100644
index 00000000000..9d5850dbf21
--- /dev/null
+++ b/gdb/doc/annotate.texi
@@ -0,0 +1,717 @@
+\input texinfo @c -*-texinfo-*-
+@c %**start of header
+@setfilename annotate.info
+@settitle GDB Annotations
+@setchapternewpage off
+@c %**end of header
+
+@set EDITION 0.5
+@set DATE May 1994
+
+@ifinfo
+This file documents GDB annotations.
+
+This is Edition @value{EDITION}, @value{DATE}, of @cite{GDB
+Annotations}. Copyright 1994 Free Software Foundation
+
+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 GDB Annotations
+@subtitle Edition @value{EDITION}
+@subtitle @value{DATE}
+@author Cygnus Support
+@page
+@vskip 0pt plus 1filll
+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.
+
+Copyright @copyright{} 1994 Free Software Foundation
+@end titlepage
+
+@ifinfo
+@node Top
+@top GDB Annotations
+
+This file describes annotations in GDB, the GNU symbolic debugger.
+Annotations are designed to interface GDB to graphical user interfaces
+or other similar programs which want to interact with GDB at a
+relatively high level.
+
+This is Edition @value{EDITION}, @value{DATE}.
+
+@menu
+* General:: What annotations are; the general syntax.
+* Server:: Issuing a command without affecting user state.
+* Values:: Values are marked as such.
+* Frames:: Stack frames are annotated.
+* Displays:: GDB can be told to display something periodically.
+* Prompting:: Annotations marking GDB's need for input.
+* Errors:: Annotations for error messages.
+* Breakpoint Info:: Information on breakpoints.
+* Invalidation:: Some annotations describe things now invalid.
+* Running:: Whether the program is running, how it stopped, etc.
+* Source:: Annotations describing source code.
+* TODO:: Annotations which might be added in the future.
+* Index:: Index
+@end menu
+@end ifinfo
+
+@node General
+@chapter What is an Annotation?
+
+To produce annotations, start GDB with the @code{--annotate=2} option.
+
+Annotations start with a newline character, two @samp{control-z}
+characters, and the name of the annotation. If there is no additional
+information associated with this annotation, the name of the annotation
+is followed immediately by a newline. If there is additional
+information, the name of the annotation is followed by a space, the
+additional information, and a newline. The additional information
+cannot contain newline characters.
+
+Any output not beginning with a newline and two @samp{control-z}
+characters denotes literal output from GDB. Currently there is no need
+for GDB to output a newline followed by two @samp{control-z} characters,
+but if there was such a need, the annotations could be extended with an
+@samp{escape} annotation which means those three characters as output.
+
+A simple example of starting up GDB with annotations is:
+
+@example
+$ gdb --annotate=2
+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.12.3 (sparc-sun-sunos4.1.3),
+Copyright 1994 Free Software Foundation, Inc.
+
+^Z^Zpre-prompt
+(gdb)
+^Z^Zprompt
+quit
+
+^Z^Zpost-prompt
+$
+@end example
+
+Here @samp{quit} is input to GDB; the rest is output from GDB. The three
+lines beginning @samp{^Z^Z} (where @samp{^Z} denotes a @samp{control-z}
+character) are annotations; the rest is output from GDB.
+
+@node Server
+@chapter The Server Prefix
+
+To issue a command to GDB without affecting certain aspects of the state
+which is seen by users, prefix it with @samp{server }. This means that
+this command will not affect the command history, nor will it affect
+GDB's notion of which command to repeat if @key{RET} is pressed on a
+line by itself.
+
+The server prefix does not affect the recording of values into the value
+history; to print a value without recording it into the value history,
+use the @code{output} command instead of the @code{print} command.
+
+@node Values
+@chapter Values
+
+When a value is printed in various contexts, GDB uses annotations to
+delimit the value from the surrounding text.
+
+@findex value-history-begin
+@findex value-history-value
+@findex value-history-end
+If a value is printed using @code{print} and added to the value history,
+the annotation looks like
+
+@example
+^Z^Zvalue-history-begin @var{history-number} @var{value-flags}
+@var{history-string}
+^Z^Zvalue-history-value
+@var{the-value}
+^Z^Zvalue-history-end
+@end example
+
+where @var{history-number} is the number it is getting in the value
+history, @var{history-string} is a string, such as @samp{$5 = }, which
+introduces the value to the user, @var{the-value} is the output
+corresponding to the value itself, and @var{value-flags} is @samp{*} for
+a value which can be dereferenced and @samp{-} for a value which cannot.
+
+@findex value-begin
+@findex value-end
+If the value is not added to the value history (it is an invalid float
+or it is printed with the @code{output} command), the annotation is similar:
+
+@example
+^Z^Zvalue-begin @var{value-flags}
+@var{the-value}
+^Z^Zvalue-end
+@end example
+
+@findex arg-begin
+@findex arg-name-end
+@findex arg-value
+@findex arg-end
+When GDB prints an argument to a function (for example, in the output
+from the @code{backtrace} command), it annotates it as follows:
+
+@example
+^Z^Zarg-begin
+@var{argument-name}
+^Z^Zarg-name-end
+@var{separator-string}
+^Z^Zarg-value @var{value-flags}
+@var{the-value}
+^Z^Zarg-end
+@end example
+
+where @var{argument-name} is the name of the argument,
+@var{separator-string} is text which separates the name from the value
+for the user's benefit (such as @samp{=}), and @var{value-flags} and
+@var{the-value} have the same meanings as in a
+@code{value-history-begin} annotation.
+
+@findex field-begin
+@findex field-name-end
+@findex field-value
+@findex field-end
+When printing a structure, GDB annotates it as follows:
+
+@example
+^Z^Zfield-begin @var{value-flags}
+@var{field-name}
+^Z^Zfield-name-end
+@var{separator-string}
+^Z^Zfield-value
+@var{the-value}
+^Z^Zfield-end
+@end example
+
+where @var{field-name} is the name of the field, @var{separator-string}
+is text which separates the name from the value for the user's benefit
+(such as @samp{=}), and @var{value-flags} and @var{the-value} have the
+same meanings as in a @code{value-history-begin} annotation.
+
+When printing an array, GDB annotates it as follows:
+
+@example
+^Z^Zarray-section-begin @var{array-index} @var{value-flags}
+@end example
+
+where @var{array-index} is the index of the first element being
+annotated and @var{value-flags} has the same meaning as in a
+@code{value-history-begin} annotation. This is followed by any number
+of elements, where is element can be either a single element:
+
+@findex elt
+@example
+@samp{,} @var{whitespace} ; @r{omitted for the first element}
+@var{the-value}
+^Z^Zelt
+@end example
+
+or a repeated element
+
+@findex elt-rep
+@findex elt-rep-end
+@example
+@samp{,} @var{whitespace} ; @r{omitted for the first element}
+@var{the-value}
+^Z^Zelt-rep @var{number-of-repititions}
+@var{repetition-string}
+^Z^Zelt-rep-end
+@end example
+
+In both cases, @var{the-value} is the output for the value of the
+element and @var{whitespace} can contain spaces, tabs, and newlines. In
+the repeated case, @var{number-of-repititons} is the number of
+consecutive array elements which contain that value, and
+@var{repetition-string} is a string which is designed to convey to the
+user that repitition is being depicted.
+
+@findex array-section-end
+Once all the array elements have been output, the array annotation is
+ended with
+
+@example
+^Z^Zarray-section-end
+@end example
+
+@node Frames
+@chapter Frames
+
+Whenever GDB prints a frame, it annotates it. For example, this applies
+to frames printed when GDB stops, output from commands such as
+@code{backtrace} or @code{up}, etc.
+
+@findex frame-begin
+The frame annotation begins with
+
+@example
+^Z^Zframe-begin @var{level} @var{address}
+@var{level-string}
+@end example
+
+where @var{level} is the number of the frame (0 is the innermost frame,
+and other frames have positive numbers), @var{address} is the address of
+the code executing in that frame, and @var{level-string} is a string
+designed to convey the level to the user. @var{address} is in the form
+@samp{0x} followed by one or more lowercase hex digits (note that this
+does not depend on the language). The frame ends with
+
+@findex frame-end
+@example
+^Z^Zframe-end
+@end example
+
+Between these annotations is the main body of the frame, which can
+consist of
+
+@itemize @bullet
+@item
+@findex function-call
+@example
+^Z^Zfunction-call
+@var{function-call-string}
+@end example
+
+where @var{function-call-string} is text designed to convey to the user
+that this frame is associated with a function call made by GDB to a
+function in the program being debugged.
+
+@item
+@findex signal-handler-caller
+@example
+^Z^Zsignal-handler-caller
+@var{signal-handler-caller-string}
+@end example
+
+where @var{signal-handler-caller-string} is text designed to convey to
+the user that this frame is associated with whatever mechanism is used
+by this operating system to call a signal handler (it is the frame which
+calls the signal handler, not the frame for the signal handler itself).
+
+@item
+A normal frame.
+
+@findex frame-address
+@findex frame-address-end
+This can optionally (depending on whether this is thought of as
+interesting information for the user to see) begin with
+
+@example
+^Z^Zframe-address
+@var{address}
+^Z^Zframe-address-end
+@var{separator-string}
+@end example
+
+where @var{address} is the address executing in the frame (the same
+address as in the @code{frame-begin} annotation, but printed in a form
+which is intended for user consumption---in particular, the syntax varies
+depending on the language), and @var{separator-string} is a string
+intended to separate this address from what follows for the user's
+benefit.
+
+@findex frame-function-name
+@findex frame-args
+Then comes
+
+@example
+^Z^Zframe-function-name
+@var{function-name}
+^Z^Zframe-args
+@var{arguments}
+@end example
+
+where @var{function-name} is the name of the function executing in the
+frame, or @samp{??} if not known, and @var{arguments} are the arguments
+to the frame, with parentheses around them (each argument is annotated
+individually as well @pxref{Values}).
+
+@findex frame-source-begin
+@findex frame-source-file
+@findex frame-source-file-end
+@findex frame-source-line
+@findex frame-source-end
+If source information is available, a reference to it is then printed:
+
+@example
+^Z^Zframe-source-begin
+@var{source-intro-string}
+^Z^Zframe-source-file
+@var{filename}
+^Z^Zframe-source-file-end
+:
+^Z^Zframe-source-line
+@var{line-number}
+^Z^Zframe-source-end
+@end example
+
+where @var{source-intro-string} separates for the user's benefit the
+reference from the text which precedes it, @var{filename} is the name of
+the source file, and @var{line-number} is the line number within that
+file (the first line is line 1).
+
+@findex frame-where
+If GDB prints some information about where the frame is from (which
+library, which load segment, etc.; currently only done on the RS/6000),
+it is annotated with
+
+@example
+^Z^Zframe-where
+@var{information}
+@end example
+
+Then, if source is to actually be displayed for this frame (for example,
+this is not true for output from the @code{backtrace} command), then a
+@code{source} annotation (@pxref{Source}) is displayed. Unlike most
+annotations, this is output instead of the normal text which would be
+output, not in addition.
+@end itemize
+
+@node Displays
+@chapter Displays
+
+@findex display-begin
+@findex display-number-end
+@findex display-format
+@findex display-expression
+@findex display-expression-end
+@findex display-value
+@findex display-end
+When GDB is told to display something using the @code{display} command,
+the results of the display are annotated:
+
+@example
+^Z^Zdisplay-begin
+@var{number}
+^Z^Zdisplay-number-end
+@var{number-separator}
+^Z^Zdisplay-format
+@var{format}
+^Z^Zdisplay-expression
+@var{expression}
+^Z^Zdisplay-expression-end
+@var{expression-separator}
+^Z^Zdisplay-value
+@var{value}
+^Z^Zdisplay-end
+@end example
+
+where @var{number} is the number of the display, @var{number-separator}
+is intended to separate the number from what follows for the user,
+@var{format} includes information such as the size, format, or other
+information about how the value is being displayed, @var{expression} is
+the expression being displayed, @var{expression-separator} is intended
+to separate the expression from the text that follows for the user,
+and @var{value} is the actual value being displayed.
+
+@node Prompting
+@chapter Annotation for GDB Input
+
+When GDB prompts for input, it annotates this fact so it is possible
+to know when to send output, when the output from a given command is
+over, etc.
+
+Different kinds of input each have a different @dfn{input type}. Each
+input type has three annotations: a @code{pre-} annotation, which
+denotes the beginning of any prompt which is being output, a plain
+annotation, which denotes the end of the prompt, and then a @code{post-}
+annotation which denotes the end of any echo which may (or may not) be
+associated with the input. For example, the @code{prompt} input type
+features the following annotations:
+
+@example
+^Z^Zpre-prompt
+^Z^Zprompt
+^Z^Zpost-prompt
+@end example
+
+The input types are
+
+@table @code
+@findex pre-prompt
+@findex prompt
+@findex post-prompt
+@item prompt
+When GDB is prompting for a command (the main GDB prompt).
+
+@findex pre-commands
+@findex commands
+@findex post-commands
+@item commands
+When GDB prompts for a set of commands, like in the @code{commands}
+command. The annotations are repeated for each command which is input.
+
+@findex pre-overload-choice
+@findex overload-choice
+@findex post-overload-choice
+@item overload-choice
+When GDB wants the user to select between various overloaded functions.
+
+@findex pre-query
+@findex query
+@findex post-query
+@item query
+When GDB wants the user to confirm a potentially dangerous operation.
+
+@findex pre-prompt-for-continue
+@findex prompt-for-continue
+@findex post-prompt-for-continue
+@item prompt-for-continue
+When GDB is asking the user to press return to continue. Note: Don't
+expect this to work well; instead use @code{set height 0} to disable
+prompting. This is because the counting of lines is buggy in the
+presence of annotations.
+@end table
+
+@node Errors
+@chapter Errors
+
+@findex quit
+@example
+^Z^Zquit
+@end example
+
+This annotation occurs right before GDB responds to an interrupt.
+
+@findex error
+@example
+^Z^Zerror
+@end example
+
+This annotation occurs right before GDB responds to an error.
+
+Quit and error annotations indicate that any annotations which GDB was
+in the middle of may end abruptly. For example, if a
+@code{value-history-begin} annotation is followed by a @code{error}, one
+cannot expect to receive the matching @code{value-history-end}. One
+cannot expect not to receive it either, however; an error annotation
+does not necessarily mean that GDB is immediately returning all the way
+to the top level.
+
+@findex error-begin
+A quit or error annotation may be preceded by
+
+@example
+^Z^Zerror-begin
+@end example
+
+Any output between that and the quit or error annotation is the error
+message.
+
+Warning messages are not yet annotated.
+@c If we want to change that, need to fix warning(), type_error(),
+@c range_error(), and possibly other places.
+
+@node Breakpoint Info
+@chapter Information on Breakpoints
+
+The output from the @code{info breakpoints} command is annotated as follows:
+
+@findex breakpoints-headers
+@findex breakpoints-table
+@example
+^Z^Zbreakpoints-headers
+@var{header-entry}
+^Z^Zbreakpoints-table
+@end example
+
+where @var{header-entry} has the same syntax as an entry (see below) but
+instead of containing data, it contains strings which are intended to
+convey the meaning of each field to the user. This is followed by any
+number of entries. If a field does not apply for this entry, it is
+omitted. Fields may contain trailing whitespace. Each entry consists
+of:
+
+@findex record
+@findex field
+@example
+^Z^Zrecord
+^Z^Zfield 0
+@var{number}
+^Z^Zfield 1
+@var{type}
+^Z^Zfield 2
+@var{disposition}
+^Z^Zfield 3
+@var{enable}
+^Z^Zfield 4
+@var{address}
+^Z^Zfield 5
+@var{what}
+^Z^Zfield 6
+@var{frame}
+^Z^Zfield 7
+@var{condition}
+^Z^Zfield 8
+@var{ignore-count}
+^Z^Zfield 9
+@var{commands}
+@end example
+
+Note that @var{address} is intended for user consumption---the syntax
+varies depending on the language.
+
+The output ends with
+
+@findex breakpoints-table-end
+@example
+^Z^Zbreakpoints-table-end
+@end example
+
+@node Invalidation
+@chapter Invalidation Notices
+
+The following annotations say that certain pieces of state may have
+changed.
+
+@table @code
+@findex frames-invalid
+@item ^Z^Zframes-invalid
+
+The frames (for example, output from the @code{backtrace} command) may
+have changed.
+
+@findex breakpoints-invalid
+@item ^Z^Zbreakpoints-invalid
+
+The breakpoints may have changed. For example, the user just added or
+deleted a breakpoint.
+@end table
+
+@node Running
+@chapter Running the Program
+
+@findex starting
+@findex stopping
+When the program starts executing due to a GDB command such as
+@code{step} or @code{continue},
+
+@example
+^Z^Zstarting
+@end example
+
+is output. When the program stops,
+
+@example
+^Z^Zstopped
+@end example
+
+is output. Before the @code{stopped} annotation, a variety of
+annotations describe how the program stopped.
+
+@table @code
+@findex exited
+@item ^Z^Zexited @var{exit-status}
+The program exited, and @var{exit-status} is the exit status (zero for
+successful exit, otherwise nonzero).
+
+@findex signalled
+@findex signal-name
+@findex signal-name-end
+@findex signal-string
+@findex signal-string-end
+@item ^Z^Zsignalled
+The program exited with a signal. After the @code{^Z^Zsignalled}, the
+annotation continues:
+
+@example
+@var{intro-text}
+^Z^Zsignal-name
+@var{name}
+^Z^Zsignal-name-end
+@var{middle-text}
+^Z^Zsignal-string
+@var{string}
+^Z^Zsignal-string-end
+@var{end-text}
+@end example
+
+where @var{name} is the name of the signal, such as @code{SIGILL} or
+@code{SIGSEGV}, and @var{string} is the explanation of the signal, such
+as @code{Illegal Instruction} or @code{Segmentation fault}.
+@var{intro-text}, @var{middle-text}, and @var{end-text} are for the
+user's benefit and have no particular format.
+
+@findex signal
+@item ^Z^Zsignal
+The syntax of this annotation is just like @code{signalled}, but GDB is
+just saying that the program received the signal, not that it was
+terminated with it.
+
+@findex breakpoint
+@item ^Z^Zbreakpoint @var{number}
+The program hit breakpoint number @var{number}.
+
+@findex watchpoint
+@item ^Z^Zwatchpoint @var{number}
+The program hit watchpoint number @var{number}.
+@end table
+
+@node Source
+@chapter Displaying Source
+
+@findex source
+The following annotation is used instead of displaying source code:
+
+@example
+^Z^Zsource @var{filename}:@var{line}:@var{character}:@var{middle}:@var{addr}
+@end example
+
+where @var{filename} is an absolute file name indicating which source
+file, @var{line} is the line number within that file (where 1 is the
+first line in the file), @var{character} is the character position
+within the file (where 0 is the first character in the file) (for most
+debug formats this will necessarily point to the beginning of a line),
+@var{middle} is @samp{middle} if @var{addr} is in the middle of the
+line, or @samp{beg} if @var{addr} is at the beginning of the line, and
+@var{addr} is the address in the target program associated with the
+source which is being displayed. @var{addr} is in the form @samp{0x}
+followed by one or more lowercase hex digits (note that this does not
+depend on the language).
+
+@node TODO
+@chapter Annotations We Might Want in the Future
+
+@format
+ - target-invalid
+ the target might have changed (registers, heap contents, or
+ execution status). For performance, we might eventually want
+ to hit `registers-invalid' and `all-registers-invalid' with
+ greater precision
+
+ - systematic annotation for set/show parameters (including
+ invalidation notices).
+
+ - similarly, `info' returns a list of candidates for invalidation
+ notices.
+@end format
+
+@node Index
+@unnumbered Index
+
+@printindex fn
+
+@bye
diff --git a/gdb/doc/configure b/gdb/doc/configure
new file mode 100755
index 00000000000..8c5591ce05e
--- /dev/null
+++ b/gdb/doc/configure
@@ -0,0 +1,862 @@
+#! /bin/sh
+
+# Guess values for system-dependent variables and create Makefiles.
+# Generated automatically using autoconf version 2.12.2
+# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc.
+#
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+
+# Defaults:
+ac_help=
+ac_default_prefix=/usr/local
+# Any additions from configure.in:
+
+# Initialize some variables set by options.
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+build=NONE
+cache_file=./config.cache
+exec_prefix=NONE
+host=NONE
+no_create=
+nonopt=NONE
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+target=NONE
+verbose=
+x_includes=NONE
+x_libraries=NONE
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datadir='${prefix}/share'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+libdir='${exec_prefix}/lib'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+infodir='${prefix}/info'
+mandir='${prefix}/man'
+
+# Initialize some other variables.
+subdirs=
+MFLAGS= MAKEFLAGS=
+SHELL=${CONFIG_SHELL-/bin/sh}
+# Maximum number of lines to put in a shell here document.
+ac_max_here_lines=12
+
+ac_prev=
+for ac_option
+do
+
+ # If the previous option needs an argument, assign it.
+ if test -n "$ac_prev"; then
+ eval "$ac_prev=\$ac_option"
+ ac_prev=
+ continue
+ fi
+
+ case "$ac_option" in
+ -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
+ *) ac_optarg= ;;
+ esac
+
+ # Accept the important Cygnus configure options, so we can diagnose typos.
+
+ case "$ac_option" in
+
+ -bindir | --bindir | --bindi | --bind | --bin | --bi)
+ ac_prev=bindir ;;
+ -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+ bindir="$ac_optarg" ;;
+
+ -build | --build | --buil | --bui | --bu)
+ ac_prev=build ;;
+ -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+ build="$ac_optarg" ;;
+
+ -cache-file | --cache-file | --cache-fil | --cache-fi \
+ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+ ac_prev=cache_file ;;
+ -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+ cache_file="$ac_optarg" ;;
+
+ -datadir | --datadir | --datadi | --datad | --data | --dat | --da)
+ ac_prev=datadir ;;
+ -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \
+ | --da=*)
+ datadir="$ac_optarg" ;;
+
+ -disable-* | --disable-*)
+ ac_feature=`echo $ac_option|sed -e 's/-*disable-//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then
+ { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
+ fi
+ ac_feature=`echo $ac_feature| sed 's/-/_/g'`
+ eval "enable_${ac_feature}=no" ;;
+
+ -enable-* | --enable-*)
+ ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then
+ { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
+ fi
+ ac_feature=`echo $ac_feature| sed 's/-/_/g'`
+ case "$ac_option" in
+ *=*) ;;
+ *) ac_optarg=yes ;;
+ esac
+ eval "enable_${ac_feature}='$ac_optarg'" ;;
+
+ -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+ | --exec | --exe | --ex)
+ ac_prev=exec_prefix ;;
+ -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+ | --exec=* | --exe=* | --ex=*)
+ exec_prefix="$ac_optarg" ;;
+
+ -gas | --gas | --ga | --g)
+ # Obsolete; use --with-gas.
+ with_gas=yes ;;
+
+ -help | --help | --hel | --he)
+ # Omit some internal or obsolete options to make the list less imposing.
+ # This message is too long to be a string in the A/UX 3.1 sh.
+ cat << EOF
+Usage: configure [options] [host]
+Options: [defaults in brackets after descriptions]
+Configuration:
+ --cache-file=FILE cache test results in FILE
+ --help print this message
+ --no-create do not create output files
+ --quiet, --silent do not print \`checking...' messages
+ --version print the version of autoconf that created configure
+Directory and file names:
+ --prefix=PREFIX install architecture-independent files in PREFIX
+ [$ac_default_prefix]
+ --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
+ [same as prefix]
+ --bindir=DIR user executables in DIR [EPREFIX/bin]
+ --sbindir=DIR system admin executables in DIR [EPREFIX/sbin]
+ --libexecdir=DIR program executables in DIR [EPREFIX/libexec]
+ --datadir=DIR read-only architecture-independent data in DIR
+ [PREFIX/share]
+ --sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc]
+ --sharedstatedir=DIR modifiable architecture-independent data in DIR
+ [PREFIX/com]
+ --localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var]
+ --libdir=DIR object code libraries in DIR [EPREFIX/lib]
+ --includedir=DIR C header files in DIR [PREFIX/include]
+ --oldincludedir=DIR C header files for non-gcc in DIR [/usr/include]
+ --infodir=DIR info documentation in DIR [PREFIX/info]
+ --mandir=DIR man documentation in DIR [PREFIX/man]
+ --srcdir=DIR find the sources in DIR [configure dir or ..]
+ --program-prefix=PREFIX prepend PREFIX to installed program names
+ --program-suffix=SUFFIX append SUFFIX to installed program names
+ --program-transform-name=PROGRAM
+ run sed PROGRAM on installed program names
+EOF
+ cat << EOF
+Host type:
+ --build=BUILD configure for building on BUILD [BUILD=HOST]
+ --host=HOST configure for HOST [guessed]
+ --target=TARGET configure for TARGET [TARGET=HOST]
+Features and packages:
+ --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
+ --enable-FEATURE[=ARG] include FEATURE [ARG=yes]
+ --with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
+ --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
+ --x-includes=DIR X include files are in DIR
+ --x-libraries=DIR X library files are in DIR
+EOF
+ if test -n "$ac_help"; then
+ echo "--enable and --with options recognized:$ac_help"
+ fi
+ exit 0 ;;
+
+ -host | --host | --hos | --ho)
+ ac_prev=host ;;
+ -host=* | --host=* | --hos=* | --ho=*)
+ host="$ac_optarg" ;;
+
+ -includedir | --includedir | --includedi | --included | --include \
+ | --includ | --inclu | --incl | --inc)
+ ac_prev=includedir ;;
+ -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+ | --includ=* | --inclu=* | --incl=* | --inc=*)
+ includedir="$ac_optarg" ;;
+
+ -infodir | --infodir | --infodi | --infod | --info | --inf)
+ ac_prev=infodir ;;
+ -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+ infodir="$ac_optarg" ;;
+
+ -libdir | --libdir | --libdi | --libd)
+ ac_prev=libdir ;;
+ -libdir=* | --libdir=* | --libdi=* | --libd=*)
+ libdir="$ac_optarg" ;;
+
+ -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+ | --libexe | --libex | --libe)
+ ac_prev=libexecdir ;;
+ -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+ | --libexe=* | --libex=* | --libe=*)
+ libexecdir="$ac_optarg" ;;
+
+ -localstatedir | --localstatedir | --localstatedi | --localstated \
+ | --localstate | --localstat | --localsta | --localst \
+ | --locals | --local | --loca | --loc | --lo)
+ ac_prev=localstatedir ;;
+ -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+ | --localstate=* | --localstat=* | --localsta=* | --localst=* \
+ | --locals=* | --local=* | --loca=* | --loc=* | --lo=*)
+ localstatedir="$ac_optarg" ;;
+
+ -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+ ac_prev=mandir ;;
+ -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+ mandir="$ac_optarg" ;;
+
+ -nfp | --nfp | --nf)
+ # Obsolete; use --without-fp.
+ with_fp=no ;;
+
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c)
+ no_create=yes ;;
+
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+ no_recursion=yes ;;
+
+ -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+ | --oldin | --oldi | --old | --ol | --o)
+ ac_prev=oldincludedir ;;
+ -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+ oldincludedir="$ac_optarg" ;;
+
+ -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+ ac_prev=prefix ;;
+ -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+ prefix="$ac_optarg" ;;
+
+ -program-prefix | --program-prefix | --program-prefi | --program-pref \
+ | --program-pre | --program-pr | --program-p)
+ ac_prev=program_prefix ;;
+ -program-prefix=* | --program-prefix=* | --program-prefi=* \
+ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+ program_prefix="$ac_optarg" ;;
+
+ -program-suffix | --program-suffix | --program-suffi | --program-suff \
+ | --program-suf | --program-su | --program-s)
+ ac_prev=program_suffix ;;
+ -program-suffix=* | --program-suffix=* | --program-suffi=* \
+ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+ program_suffix="$ac_optarg" ;;
+
+ -program-transform-name | --program-transform-name \
+ | --program-transform-nam | --program-transform-na \
+ | --program-transform-n | --program-transform- \
+ | --program-transform | --program-transfor \
+ | --program-transfo | --program-transf \
+ | --program-trans | --program-tran \
+ | --progr-tra | --program-tr | --program-t)
+ ac_prev=program_transform_name ;;
+ -program-transform-name=* | --program-transform-name=* \
+ | --program-transform-nam=* | --program-transform-na=* \
+ | --program-transform-n=* | --program-transform-=* \
+ | --program-transform=* | --program-transfor=* \
+ | --program-transfo=* | --program-transf=* \
+ | --program-trans=* | --program-tran=* \
+ | --progr-tra=* | --program-tr=* | --program-t=*)
+ program_transform_name="$ac_optarg" ;;
+
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ silent=yes ;;
+
+ -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+ ac_prev=sbindir ;;
+ -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+ | --sbi=* | --sb=*)
+ sbindir="$ac_optarg" ;;
+
+ -sharedstatedir | --sharedstatedir | --sharedstatedi \
+ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+ | --sharedst | --shareds | --shared | --share | --shar \
+ | --sha | --sh)
+ ac_prev=sharedstatedir ;;
+ -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+ | --sha=* | --sh=*)
+ sharedstatedir="$ac_optarg" ;;
+
+ -site | --site | --sit)
+ ac_prev=site ;;
+ -site=* | --site=* | --sit=*)
+ site="$ac_optarg" ;;
+
+ -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+ ac_prev=srcdir ;;
+ -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+ srcdir="$ac_optarg" ;;
+
+ -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+ | --syscon | --sysco | --sysc | --sys | --sy)
+ ac_prev=sysconfdir ;;
+ -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+ sysconfdir="$ac_optarg" ;;
+
+ -target | --target | --targe | --targ | --tar | --ta | --t)
+ ac_prev=target ;;
+ -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+ target="$ac_optarg" ;;
+
+ -v | -verbose | --verbose | --verbos | --verbo | --verb)
+ verbose=yes ;;
+
+ -version | --version | --versio | --versi | --vers)
+ echo "configure generated by autoconf version 2.12.2"
+ exit 0 ;;
+
+ -with-* | --with-*)
+ ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then
+ { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
+ fi
+ ac_package=`echo $ac_package| sed 's/-/_/g'`
+ case "$ac_option" in
+ *=*) ;;
+ *) ac_optarg=yes ;;
+ esac
+ eval "with_${ac_package}='$ac_optarg'" ;;
+
+ -without-* | --without-*)
+ ac_package=`echo $ac_option|sed -e 's/-*without-//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then
+ { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
+ fi
+ ac_package=`echo $ac_package| sed 's/-/_/g'`
+ eval "with_${ac_package}=no" ;;
+
+ --x)
+ # Obsolete; use --with-x.
+ with_x=yes ;;
+
+ -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+ | --x-incl | --x-inc | --x-in | --x-i)
+ ac_prev=x_includes ;;
+ -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+ x_includes="$ac_optarg" ;;
+
+ -x-libraries | --x-libraries | --x-librarie | --x-librari \
+ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+ ac_prev=x_libraries ;;
+ -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+ x_libraries="$ac_optarg" ;;
+
+ -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; }
+ ;;
+
+ *)
+ if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then
+ echo "configure: warning: $ac_option: invalid host type" 1>&2
+ fi
+ if test "x$nonopt" != xNONE; then
+ { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; }
+ fi
+ nonopt="$ac_option"
+ ;;
+
+ esac
+done
+
+if test -n "$ac_prev"; then
+ { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; }
+fi
+
+trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
+
+# File descriptor usage:
+# 0 standard input
+# 1 file creation
+# 2 errors and warnings
+# 3 some systems may open it to /dev/tty
+# 4 used on the Kubota Titan
+# 6 checking for... messages and results
+# 5 compiler messages saved in config.log
+if test "$silent" = yes; then
+ exec 6>/dev/null
+else
+ exec 6>&1
+fi
+exec 5>./config.log
+
+echo "\
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+" 1>&5
+
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Also quote any args containing shell metacharacters.
+ac_configure_args=
+for ac_arg
+do
+ case "$ac_arg" in
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c) ;;
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;;
+ *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*)
+ ac_configure_args="$ac_configure_args '$ac_arg'" ;;
+ *) ac_configure_args="$ac_configure_args $ac_arg" ;;
+ esac
+done
+
+# NLS nuisances.
+# Only set these to C if already set. These must not be set unconditionally
+# because not all systems understand e.g. LANG=C (notably SCO).
+# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'!
+# Non-C LC_CTYPE values break the ctype check.
+if test "${LANG+set}" = set; then LANG=C; export LANG; fi
+if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi
+if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi
+if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -rf conftest* confdefs.h
+# AIX cpp loses on an empty file, so make sure it contains at least a newline.
+echo > confdefs.h
+
+# A filename unique to this package, relative to the directory that
+# configure is in, which we can look for to find out if srcdir is correct.
+ac_unique_file=refcard.tex
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+ ac_srcdir_defaulted=yes
+ # Try the directory containing this script, then its parent.
+ ac_prog=$0
+ ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'`
+ test "x$ac_confdir" = "x$ac_prog" && ac_confdir=.
+ srcdir=$ac_confdir
+ if test ! -r $srcdir/$ac_unique_file; then
+ srcdir=..
+ fi
+else
+ ac_srcdir_defaulted=no
+fi
+if test ! -r $srcdir/$ac_unique_file; then
+ if test "$ac_srcdir_defaulted" = yes; then
+ { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; }
+ else
+ { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; }
+ fi
+fi
+srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'`
+
+# Prefer explicitly selected file to automatically selected ones.
+if test -z "$CONFIG_SITE"; then
+ if test "x$prefix" != xNONE; then
+ CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site"
+ else
+ CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
+ fi
+fi
+for ac_site_file in $CONFIG_SITE; do
+ if test -r "$ac_site_file"; then
+ echo "loading site script $ac_site_file"
+ . "$ac_site_file"
+ fi
+done
+
+if test -r "$cache_file"; then
+ echo "loading cache $cache_file"
+ . $cache_file
+else
+ echo "creating cache $cache_file"
+ > $cache_file
+fi
+
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+ac_exeext=
+ac_objext=o
+if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then
+ # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu.
+ if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then
+ ac_n= ac_c='
+' ac_t=' '
+ else
+ ac_n=-n ac_c= ac_t=
+ fi
+else
+ ac_n= ac_c='\c' ac_t=
+fi
+
+
+ac_aux_dir=
+for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do
+ if test -f $ac_dir/install-sh; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install-sh -c"
+ break
+ elif test -f $ac_dir/install.sh; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install.sh -c"
+ break
+ fi
+done
+if test -z "$ac_aux_dir"; then
+ { echo "configure: error: can not find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." 1>&2; exit 1; }
+fi
+ac_config_guess=$ac_aux_dir/config.guess
+ac_config_sub=$ac_aux_dir/config.sub
+ac_configure=$ac_aux_dir/configure # This should be Cygnus configure.
+
+# Find a good install program. We prefer a C program (faster),
+# so one script is as good as another. But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# ./install, which can be erroneously created by make from ./install.sh.
+echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6
+echo "configure:556: checking for a BSD compatible install" >&5
+if test -z "$INSTALL"; then
+if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ IFS="${IFS= }"; ac_save_IFS="$IFS"; IFS=":"
+ for ac_dir in $PATH; do
+ # Account for people who put trailing slashes in PATH elements.
+ case "$ac_dir/" in
+ /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;;
+ *)
+ # OSF1 and SCO ODT 3.0 have their own names for install.
+ # Don't use installbsd from OSF since it installs stuff as root
+ # by default.
+ for ac_prog in ginstall scoinst install; do
+ if test -f $ac_dir/$ac_prog; then
+ if test $ac_prog = install &&
+ grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then
+ # AIX install. It has an incompatible calling convention.
+ :
+ else
+ ac_cv_path_install="$ac_dir/$ac_prog -c"
+ break 2
+ fi
+ fi
+ done
+ ;;
+ esac
+ done
+ IFS="$ac_save_IFS"
+
+fi
+ if test "${ac_cv_path_install+set}" = set; then
+ INSTALL="$ac_cv_path_install"
+ else
+ # As a last resort, use the slow shell script. We don't cache a
+ # path for INSTALL within a source directory, because that will
+ # break other packages using the cache if that directory is
+ # removed, or if the path is relative.
+ INSTALL="$ac_install_sh"
+ fi
+fi
+echo "$ac_t""$INSTALL" 1>&6
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+trap '' 1 2 15
+cat > confcache <<\EOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs. It is not useful on other systems.
+# If it contains results you don't want to keep, you may remove or edit it.
+#
+# By default, configure uses ./config.cache as the cache file,
+# creating it if it does not exist already. You can give configure
+# the --cache-file=FILE option to use a different cache file; that is
+# what configure does when it calls configure scripts in
+# subdirectories, so they share the cache.
+# Giving --cache-file=/dev/null disables caching, for debugging configure.
+# config.status only pays attention to the cache file if you give it the
+# --recheck option to rerun configure.
+#
+EOF
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, don't put newlines in cache variables' values.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(set) 2>&1 |
+ case `(ac_space=' '; set) 2>&1 | grep ac_space` in
+ *ac_space=\ *)
+ # `set' does not quote correctly, so add quotes (double-quote substitution
+ # turns \\\\ into \\, and sed turns \\ into \).
+ sed -n \
+ -e "s/'/'\\\\''/g" \
+ -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p"
+ ;;
+ *)
+ # `set' quotes correctly as required by POSIX, so do not add quotes.
+ sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p'
+ ;;
+ esac >> confcache
+if cmp -s $cache_file confcache; then
+ :
+else
+ if test -w $cache_file; then
+ echo "updating cache $cache_file"
+ cat confcache > $cache_file
+ else
+ echo "not updating unwritable cache $cache_file"
+ fi
+fi
+rm -f confcache
+
+trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+# Any assignment to VPATH causes Sun make to only execute
+# the first set of double-colon rules, so remove it if not needed.
+# If there is a colon in the path, we need to keep it.
+if test "x$srcdir" = x.; then
+ ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d'
+fi
+
+trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15
+
+# Transform confdefs.h into DEFS.
+# Protect against shell expansion while executing Makefile rules.
+# Protect against Makefile macro expansion.
+cat > conftest.defs <<\EOF
+s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%-D\1=\2%g
+s%[ `~#$^&*(){}\\|;'"<>?]%\\&%g
+s%\[%\\&%g
+s%\]%\\&%g
+s%\$%$$%g
+EOF
+DEFS=`sed -f conftest.defs confdefs.h | tr '\012' ' '`
+rm -f conftest.defs
+
+
+# Without the "./", some shells look in PATH for config.status.
+: ${CONFIG_STATUS=./config.status}
+
+echo creating $CONFIG_STATUS
+rm -f $CONFIG_STATUS
+cat > $CONFIG_STATUS <<EOF
+#! /bin/sh
+# Generated automatically by configure.
+# Run this file to recreate the current configuration.
+# This directory was configured as follows,
+# on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+#
+# $0 $ac_configure_args
+#
+# Compiler output produced by configure, useful for debugging
+# configure, is in ./config.log if it exists.
+
+ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]"
+for ac_option
+do
+ case "\$ac_option" in
+ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+ echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion"
+ exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;;
+ -version | --version | --versio | --versi | --vers | --ver | --ve | --v)
+ echo "$CONFIG_STATUS generated by autoconf version 2.12.2"
+ exit 0 ;;
+ -help | --help | --hel | --he | --h)
+ echo "\$ac_cs_usage"; exit 0 ;;
+ *) echo "\$ac_cs_usage"; exit 1 ;;
+ esac
+done
+
+ac_given_srcdir=$srcdir
+ac_given_INSTALL="$INSTALL"
+
+trap 'rm -fr `echo "Makefile" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15
+EOF
+cat >> $CONFIG_STATUS <<EOF
+
+# Protect against being on the right side of a sed subst in config.status.
+sed 's/%@/@@/; s/@%/@@/; s/%g\$/@g/; /@g\$/s/[\\\\&%]/\\\\&/g;
+ s/@@/%@/; s/@@/@%/; s/@g\$/%g/' > conftest.subs <<\\CEOF
+$ac_vpsub
+$extrasub
+s%@SHELL@%$SHELL%g
+s%@CFLAGS@%$CFLAGS%g
+s%@CPPFLAGS@%$CPPFLAGS%g
+s%@CXXFLAGS@%$CXXFLAGS%g
+s%@DEFS@%$DEFS%g
+s%@LDFLAGS@%$LDFLAGS%g
+s%@LIBS@%$LIBS%g
+s%@exec_prefix@%$exec_prefix%g
+s%@prefix@%$prefix%g
+s%@program_transform_name@%$program_transform_name%g
+s%@bindir@%$bindir%g
+s%@sbindir@%$sbindir%g
+s%@libexecdir@%$libexecdir%g
+s%@datadir@%$datadir%g
+s%@sysconfdir@%$sysconfdir%g
+s%@sharedstatedir@%$sharedstatedir%g
+s%@localstatedir@%$localstatedir%g
+s%@libdir@%$libdir%g
+s%@includedir@%$includedir%g
+s%@oldincludedir@%$oldincludedir%g
+s%@infodir@%$infodir%g
+s%@mandir@%$mandir%g
+s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g
+s%@INSTALL_DATA@%$INSTALL_DATA%g
+
+CEOF
+EOF
+
+cat >> $CONFIG_STATUS <<\EOF
+
+# Split the substitutions into bite-sized pieces for seds with
+# small command number limits, like on Digital OSF/1 and HP-UX.
+ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script.
+ac_file=1 # Number of current file.
+ac_beg=1 # First line for current file.
+ac_end=$ac_max_sed_cmds # Line after last line for current file.
+ac_more_lines=:
+ac_sed_cmds=""
+while $ac_more_lines; do
+ if test $ac_beg -gt 1; then
+ sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file
+ else
+ sed "${ac_end}q" conftest.subs > conftest.s$ac_file
+ fi
+ if test ! -s conftest.s$ac_file; then
+ ac_more_lines=false
+ rm -f conftest.s$ac_file
+ else
+ if test -z "$ac_sed_cmds"; then
+ ac_sed_cmds="sed -f conftest.s$ac_file"
+ else
+ ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file"
+ fi
+ ac_file=`expr $ac_file + 1`
+ ac_beg=$ac_end
+ ac_end=`expr $ac_end + $ac_max_sed_cmds`
+ fi
+done
+if test -z "$ac_sed_cmds"; then
+ ac_sed_cmds=cat
+fi
+EOF
+
+cat >> $CONFIG_STATUS <<EOF
+
+CONFIG_FILES=\${CONFIG_FILES-"Makefile"}
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then
+ # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+ case "$ac_file" in
+ *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'`
+ ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
+ *) ac_file_in="${ac_file}.in" ;;
+ esac
+
+ # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories.
+
+ # Remove last slash and all that follows it. Not all systems have dirname.
+ ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
+ if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
+ # The file is in a subdirectory.
+ test ! -d "$ac_dir" && mkdir "$ac_dir"
+ ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`"
+ # A "../" for each directory in $ac_dir_suffix.
+ ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'`
+ else
+ ac_dir_suffix= ac_dots=
+ fi
+
+ case "$ac_given_srcdir" in
+ .) srcdir=.
+ if test -z "$ac_dots"; then top_srcdir=.
+ else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;;
+ /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;;
+ *) # Relative path.
+ srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix"
+ top_srcdir="$ac_dots$ac_given_srcdir" ;;
+ esac
+
+ case "$ac_given_INSTALL" in
+ [/$]*) INSTALL="$ac_given_INSTALL" ;;
+ *) INSTALL="$ac_dots$ac_given_INSTALL" ;;
+ esac
+
+ echo creating "$ac_file"
+ rm -f "$ac_file"
+ configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure."
+ case "$ac_file" in
+ *Makefile*) ac_comsub="1i\\
+# $configure_input" ;;
+ *) ac_comsub= ;;
+ esac
+
+ ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"`
+ sed -e "$ac_comsub
+s%@configure_input@%$configure_input%g
+s%@srcdir@%$srcdir%g
+s%@top_srcdir@%$top_srcdir%g
+s%@INSTALL@%$INSTALL%g
+" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file
+fi; done
+rm -f conftest.s*
+
+EOF
+cat >> $CONFIG_STATUS <<EOF
+
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+
+exit 0
+EOF
+chmod +x $CONFIG_STATUS
+rm -fr confdefs* $ac_clean_files
+test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1
+
diff --git a/gdb/doc/configure.in b/gdb/doc/configure.in
new file mode 100644
index 00000000000..460efc2b466
--- /dev/null
+++ b/gdb/doc/configure.in
@@ -0,0 +1,4 @@
+AC_PREREQ(2.12.1)
+AC_INIT(refcard.tex)
+AC_PROG_INSTALL
+AC_OUTPUT(Makefile)
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
new file mode 100644
index 00000000000..fc920bb0c57
--- /dev/null
+++ b/gdb/doc/gdb.texinfo
@@ -0,0 +1,10316 @@
+\input texinfo @c -*-texinfo-*-
+@c Copyright 1988-1999
+@c 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 !!set GDB manual's edition---not the same as GDB version!
+@set EDITION Seventh
+
+@c !!set GDB manual's revision date
+@set DATE February 1999
+
+@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: (gdb). The @sc{gnu} debugger.
+END-INFO-DIR-ENTRY
+@end format
+@end ifinfo
+@c
+@c
+@ifinfo
+This file documents the @sc{gnu} debugger @value{GDBN}.
+
+
+This is the @value{EDITION} Edition, @value{DATE},
+of @cite{Debugging with @value{GDBN}: the @sc{gnu} Source-Level Debugger}
+for @value{GDBN} Version @value{GDBVN}.
+
+Copyright (C) 1988-1999 Free Software Foundation, Inc.
+
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+
+@ignore
+Permission is granted to process this file through TeX and print the
+results, provided the printed document carries copying permission
+notice identical to this one except for the removal of this paragraph
+(this paragraph not being relevant to the printed manual).
+
+@end ignore
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided 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 @sc{gnu} Source-Level Debugger
+@ifclear GENERIC
+@subtitle (@value{TARGET})
+@end ifclear
+@sp 1
+@ifclear HPPA
+@subtitle @value{EDITION} Edition, for @value{GDBN} version @value{GDBVN}
+@subtitle @value{DATE}
+@author Richard M. Stallman and Roland H. Pesch
+@end ifclear
+@ifset HPPA
+@subtitle Edition @value{EDITION}, for @value{HPVER} (based on @value{GDBN} @value{GDBVN})
+@subtitle @value{DATE}
+@author Richard M. Stallman and Roland H. Pesch (modified by HP)
+@end ifset
+@page
+@ifclear HPPA
+@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
+}
+@end tex
+@end ifclear
+@ifset HPPA
+@tex
+{\parskip=0pt
+\hfill {\it Debugging with @value{GDBN}}\par
+\hfill \TeX{}info \texinfoversion\par
+}
+@end tex
+@end ifset
+
+@vskip 0pt plus 1filll
+Copyright @copyright{} 1988-1999 Free Software Foundation, Inc.
+@sp 2
+@ifclear HPPA
+Published by the Free Software Foundation @*
+59 Temple Place - Suite 330, @*
+Boston, MA 02111-1307 USA @*
+Printed copies are available for $20 each. @*
+ISBN 1-882114-11-6 @*
+@end ifclear
+
+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, Summary, (dir), (dir)
+@top Debugging with @value{GDBN}
+
+This file describes @value{GDBN}, the @sc{gnu} symbolic debugger.
+
+This is the @value{EDITION} Edition, @value{DATE}, for @value{GDBN} Version
+@value{GDBVN}.
+
+Copyright (C) 1988-1999 Free Software Foundation, Inc.
+@menu
+* Summary:: Summary of @value{GDBN}
+@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
+
+* 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 @sc{gnu} Emacs
+@end ifclear
+
+* GDB Bugs:: Reporting bugs in @value{GDBN}
+
+@ifclear PRECONFIGURED
+@ifclear HPPA
+* Formatting Documentation:: How to format and print @value{GDBN} documentation
+@end ifclear
+
+@end ifclear
+
+* Command Line Editing:: Command Line Editing
+* Using History Interactively:: Using History Interactively
+* Installing GDB:: Installing GDB
+* Index:: Index
+
+ --- The Detailed Node Listing ---
+
+Summary of @value{GDBN}
+
+* Free Software:: Freely redistributable software
+* Contributors:: Contributors to GDB
+
+Getting In and Out of @value{GDBN}
+
+* Invoking GDB:: How to start @value{GDBN}
+* Quitting GDB:: How to quit @value{GDBN}
+* Shell Commands:: How to use shell commands inside @value{GDBN}
+
+Invoking @value{GDBN}
+
+* File Options:: Choosing files
+* Mode Options:: Choosing modes
+
+@value{GDBN} Commands
+
+* Command Syntax:: How to give commands to @value{GDBN}
+* Completion:: Command completion
+* Help:: How to ask @value{GDBN} for help
+
+Running Programs Under @value{GDBN}
+
+* Compilation:: Compiling for debugging
+* Starting:: Starting your program
+@ifclear BARETARGET
+* Arguments:: Your program's arguments
+* Environment:: Your program's environment
+@end ifclear
+
+* 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
+@ifclear HPPA
+* Process Information:: Additional process information
+@end ifclear
+
+* Threads:: Debugging programs with multiple threads
+* Processes:: Debugging programs with multiple processes
+
+Stopping and Continuing
+
+* Breakpoints:: Breakpoints, watchpoints, and catchpoints
+* Continuing and Stepping:: Resuming execution
+@ifset POSIX
+* Signals:: Signals
+@end ifset
+@ifclear BARETARGET
+* Thread Stops:: Stopping and starting multi-thread programs
+@end ifclear
+
+Breakpoints and watchpoints
+
+* Set Breaks:: Setting breakpoints
+* Set Watchpoints:: Setting watchpoints
+* Set Catchpoints:: Setting catchpoints
+* Delete Breaks:: Deleting breakpoints
+* Disabling:: Disabling breakpoints
+* Conditions:: Break conditions
+* Break Commands:: Breakpoint command lists
+@ifclear CONLY
+* Breakpoint Menus:: Breakpoint menus
+@end ifclear
+
+Examining the Stack
+
+* Frames:: Stack frames
+* Backtrace:: Backtraces
+* Selection:: Selecting a frame
+* Frame Info:: Information on a frame
+* Alpha/MIPS Stack:: Alpha and MIPS machines and the function stack
+
+Examining Source Files
+
+* List:: Printing source lines
+@ifclear DOSHOST
+* Search:: Searching source files
+@end ifclear
+* Source Path:: Specifying source directories
+* Machine Code:: Source and machine code
+
+Examining Data
+
+* 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
+
+Using @value{GDBN} with Different Languages
+
+* Setting:: Switching between source languages
+* Show:: Displaying the language
+@ifset MOD2
+* Checks:: Type and range checks
+@end ifset
+
+* Support:: Supported languages
+
+Switching between source languages
+
+* Filenames:: Filename extensions and languages.
+* Manually:: Setting the working language manually
+* Automatically:: Having @value{GDBN} infer the source language
+
+@ifset MOD2
+Type and range checking
+
+* Type Checking:: An overview of type checking
+* Range Checking:: An overview of range checking
+@end ifset
+
+Supported languages
+
+@ifset MOD2
+* C:: C and C++
+
+C Language Support
+
+* C Operators:: C operators
+
+C Language Support
+@end ifset
+
+* 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:: @value{GDBN} features for C++
+
+@ifset MOD2
+Modula-2
+
+* 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 ifset
+
+Altering Execution
+
+* 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
+
+@value{GDBN} Files
+
+* Files:: Commands to specify files
+* Symbol Errors:: Errors reading symbol files
+
+Specifying a Debugging Target
+
+* Active Targets:: Active targets
+* Target Commands:: Commands for managing targets
+@ifclear HPPA
+* Byte Order:: Choosing target byte order
+* Remote:: Remote debugging
+
+Remote debugging
+@end ifclear
+
+@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:: The UDI protocol for AMD29K
+* EB29K Remote:: The EBMON protocol for AMD29K
+@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
+
+Controlling @value{GDBN}
+
+* Prompt:: Prompt
+* Editing:: Command editing
+* History:: Command history
+* Screen Size:: Screen size
+* Numbers:: Numbers
+* Messages/Warnings:: Optional warnings and messages
+
+Canned Sequences of Commands
+
+* Define:: User-defined commands
+* Hooks:: User-defined command hooks
+* Command Files:: Command files
+* Output:: Commands for controlled output
+
+Reporting Bugs in @value{GDBN}
+
+* Bug Criteria:: Have you found a bug?
+* Bug Reporting:: How to report bugs
+
+Installing @value{GDBN}
+
+* Separate Objdir:: Compiling @value{GDBN} in another directory
+* Config Names:: Specifying names for hosts and targets
+* Configure Options:: Summary of options for configure
+@end menu
+
+@end ifinfo
+
+@node Summary, Sample Session, Top, Top
+@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
+You can use @value{GDBN} to debug programs written in C or C++.
+@c "MOD2" used as a "miscellaneous languages" flag here.
+@c This is acceptable while there is no real doc for Chill and Pascal.
+@ifclear MOD2
+For more information, see @ref{Support,,Supported languages}.
+@end ifclear
+@ifset MOD2
+For more information, see @ref{C,,C and C++}.
+
+Support for Modula-2 and Chill is partial. For information on Modula-2,
+see @ref{Modula-2,,Modula-2}. There is no further documentation on Chill yet.
+
+Debugging Pascal programs which use sets, subranges, file variables, or nested
+functions does not currently work. @value{GDBN} does not support
+entering expressions, printing values, or similar features using Pascal syntax.
+@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, or
+similar features using Fortran syntax. It may be necessary to refer to
+some variables with a trailing underscore.
+@end ifset
+@end ifclear
+
+@ifset HPPA
+This version of the manual documents HP Wildebeest (WDB) Version 0.75,
+implemented on HP 9000 systems running Release 10.20, 10.30, or 11.0 of
+the HP-UX operating system. HP WDB 0.75 can be used to debug code
+generated by the HP ANSI C and HP ANSI C++ compilers as well as the
+@sc{gnu} C and C++ compilers. It does not support the debugging of
+Fortran, Modula-2, or Chill programs.
+@end ifset
+
+@menu
+* Free Software:: Freely redistributable software
+* Contributors:: Contributors to GDB
+@end menu
+
+@node Free Software, Contributors, Summary, Summary
+@unnumberedsec Free software
+
+@value{GDBN} is @dfn{free software}, protected by the @sc{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, , Free Software, Summary
+@unnumberedsec Contributors to GDB
+
+Richard Stallman was the original author of GDB, and of many other
+@sc{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 @value{GDBN} 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 many labors as thankless, we
+particularly thank those who shepherded @value{GDBN} through major
+releases:
+Jim Blandy (release 4.18);
+Jason Molenda (release 4.17);
+Stan Shebs (release 4.14);
+Fred Fish (releases 4.16, 4.15, 4.13, 4.12, 4.11, 4.10, and 4.9);
+Stu Grossman and John Gilmore (releases 4.8, 4.7, 4.6, 4.5, and 4.4);
+John Gilmore (releases 4.3, 4.2, 4.1, 4.0, and 3.9);
+Jim Kingdon (releases 3.5, 3.4, and 3.3);
+and Randy Smith (releases 3.2, 3.1, and 3.0).
+
+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 @sc{gnu} C++ support in GDB,
+with significant additional contributions from Per Bothner. James
+Clark wrote the @sc{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
+
+@value{GDBN} 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.
+
+Brent Benson of Harris Computer Systems contributed DWARF 2 support.
+
+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.
+Jeff Law contributed HP PA and SOM support.
+Keith Packard contributed NS32K support.
+Doug Rabson contributed Acorn Risc Machine support.
+Bob Rusk contributed Harris Nighthawk CX-UX 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.
+
+Andreas Schwab contributed M68K Linux support.
+
+Rich Schaefer and Peter Schauer helped with support of SunOS shared
+libraries.
+
+Jay Fenlason and Roland McGrath ensured that @value{GDBN} and GAS agree
+about several machine instruction sets.
+
+Patrick Duval, Ted Goldstein, Vikram Koka and Glenn Engel helped develop
+remote debugging. Intel Corporation, Wind River Systems, AMD, and ARM
+contributed remote debugging modules for the i960, VxWorks, A29K UDI,
+and RDI targets, respectively.
+
+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 H8/300, H8/500, and
+Super-H processors.
+
+NEC sponsored the support for the v850, Vr4xxx, and Vr5xxx processors.
+
+Mitsubishi sponsored the support for D10V, D30V, and M32R/D processors.
+
+Toshiba sponsored the support for the TX39 Mips processor.
+
+Matsushita sponsored the support for the MN10200 and MN10300 processors.
+
+Fujitsu sponsored the support for SPARClite and FR30 processors
+
+Kung Hsu, Jeff Law, and Rick Sladkey added support for hardware
+watchpoints.
+
+Michael Snyder added support for tracepoints.
+
+Stu Grossman wrote gdbserver.
+
+Jim Kingdon, Peter Schauer, Ian Taylor, and Stu Grossman made
+nearly innumerable bug fixes and cleanups throughout GDB.
+
+The following people at the Hewlett-Packard Company contributed
+support for the PA-RISC 2.0 architecture, HP-UX 10.20, 10.30, and 11.0
+(narrow mode), HP's implementation of kernel threads, HP's aC++
+compiler, and the terminal user interface: Ben Krepp, Richard Title,
+John Bishop, Susan Macchia, Kathy Mann, Satish Pai, India Paul, Steve
+Rehrauer, and Elena Zannoni. Kim Haase provided HP-specific
+information in this manual.
+
+Cygnus Solutions has sponsored GDB maintenance and much of its
+development since 1991. Cygnus engineers who have worked on GDB
+fulltime include Mark Alexander, Jim Blandy, Per Bothner, Edith Epstein,
+Chris Faylor, Fred Fish, Martin Hunt, Jim Ingham, John Gilmore, Stu
+Grossman, Kung Hsu, Jim Kingdon, John Metzler, Fernando Nasser, Geoffrey
+Noer, Dawn Perchik, Rich Pixley, Zdenek Radouch, Keith Seitz, Stan
+Shebs, David Taylor, and Elena Zannoni. In addition, Dave Brolley, Ian
+Carmichael, Steve Chamberlain, Nick Clifton, JT Conklin, Stan Cox, DJ
+Delorie, Ulrich Drepper, Frank Eigler, Doug Evans, Sean Fagan, David
+Henkel-Wallace, Richard Henderson, Jeff Holcomb, Jeff Law, Jim Lemke,
+Tom Lord, Bob Manson, Michael Meissner, Jason Merrill, Catherine Moore,
+Drew Moseley, Ken Raeburn, Gavin Romig-Koch, Rob Savoye, Jamie Smith,
+Mike Stump, Ian Taylor, Angela Thomas, Michael Tiemann, Tom Tromey, Ron
+Unrau, Jim Wilson, and David Zuhn have made contributions both large
+and small.
+
+
+@ifclear BARETARGET
+@node Sample Session, Invocation, Summary, Top
+@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 @sc{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.
+
+@ifclear HPPA
+@smallexample
+$ @b{@value{GDBP} m4}
+@c FIXME: this falsifies the exact text played out, to permit smallbook
+@c FIXME... format to come out better.
+@value{GDBN} 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 @value{GDBN}; type "show warranty"
+ for details.
+
+@value{GDBN} @value{GDBVN}, Copyright 1999 Free Software Foundation, Inc...
+(@value{GDBP})
+@end smallexample
+@end ifclear
+@ifset HPPA
+@smallexample
+$ @b{@value{GDBP} m4}
+Wildebeest 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 Wildebeest; type "show warranty"
+for details.
+
+Hewlett-Packard Wildebeest 0.75 (based on GDB 4.16)
+(built for PA-RISC 1.1 or 2.0, HP-UX 10.20)
+Copyright 1996, 1997 Free Software Foundation, Inc.
+(@value{GDBP})
+@end smallexample
+@end ifset
+
+@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 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 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, Commands, Sample Session, Top
+@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 are:
+@itemize @bullet
+@item
+type @samp{@value{GDBP}} to start GDB.
+@item
+type @kbd{quit} or @kbd{C-d} to exit.
+@end itemize
+
+@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, Quitting GDB, Invocation, Invocation
+@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).
+
+@ifclear HPPA
+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
+@end ifclear
+
+You can run @code{gdb} without printing the front material, which describes
+@value{GDBN}'s non-warranty, by specifying @code{-silent}:
+
+@smallexample
+@value{GDBP} -silent
+@end smallexample
+
+@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:: The UDI protocol for AMD29K
+* EB29K Remote:: The EBMON protocol for AMD29K
+@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 SPARCLET
+* Sparclet Remote:: @value{GDBN} and Sparclet 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
+@ifclear HPPA
+@include remote.texi
+@end ifclear
+@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
+@ifclear HPPA
+@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 is @file{./fred.syms}.
+Future @value{GDBN} debugging sessions notice the presence of this file,
+and can quickly map in symbol information from it, rather than reading
+the symbol table from the executable program.
+
+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
+@end ifclear
+
+@ifclear HPPA
+@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 ifclear
+@end table
+
+@ifclear BARETARGET
+@ifclear HPPA
+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
+@end ifclear
+
+@node Mode Options, , File Options, Invoking GDB
+@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{.gdbinit}, or @file{gdb.ini} on PCs). 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.
+
+@ifclear DOSHOST
+@item -fullname
+@itemx -f
+@sc{gnu} 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
+@ifclear HPPA
+@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.
+@end ifclear
+
+@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
+
+@ifset HPPA
+@item -tui
+Use a Terminal User Interface. For information, use your Web browser to
+read the file @file{TUI.html}, which is usually installed in the
+directory @code{/opt/langtools/wdb/doc} on HP-UX systems. Do not use
+this option if you run @value{GDBN} from Emacs (see @pxref{Emacs, ,Using
+@value{GDBN} under @sc{gnu} Emacs}).
+
+@item -xdb
+Run in XDB compatibility mode, allowing the use of certain XDB commands.
+For information, see the file @file{xdb_trans.html}, which is usually
+installed in the directory @code{/opt/langtools/wdb/doc} on HP-UX
+systems.
+@end ifset
+@end table
+
+@node Quitting GDB, Shell Commands, Invoking GDB, Invocation
+@section Quitting @value{GDBN}
+@cindex exiting @value{GDBN}
+@cindex leaving @value{GDBN}
+
+@table @code
+@kindex quit @r{[}@var{expression}@r{]}
+@kindex q
+@item quit
+To exit @value{GDBN}, use the @code{quit} command (abbreviated @code{q}), or
+type an end-of-file character (usually @kbd{C-d}). If you do not supply
+@var{expression}, @value{GDBN} will terminate normally; otherwise it will
+terminate using the result of @var{expression} as the error code.
+@end table
+
+@cindex interrupt
+An interrupt (often @kbd{C-c}) does not exit from @value{GDBN}, but rather
+terminates the action of any @value{GDBN} command that is in progress and
+returns 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, , Quitting GDB, Invocation
+@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
+@kindex shell
+@cindex shell escape
+@item shell @var{command string}
+Invoke a 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
+@kindex make
+@cindex calling make
+@item make @var{make-args}
+Execute the @code{make} program with the specified
+arguments. This is equivalent to @samp{shell make @var{make-args}}.
+@end table
+
+@node Commands, Running, Invocation, Top
+@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, Completion, Commands, Commands
+@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 whose 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, Help, Command Syntax, Commands
+@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} fills in the
+word, and waits 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} sounds a bell. You can either supply more
+characters and try again, or just press @key{TAB} a second time;
+@value{GDBN} displays 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 displays 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 requires using
+quotes. When this happens, @value{GDBN} inserts 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.
+
+For more information about overloaded functions, @pxref{Cplus
+expressions, ,C++ expressions}. You can use the command @code{set
+overload-resolution off} to disable overload resolution;
+@pxref{Debugging C plus plus, ,@value{GDBN} features for C++}.
+@end ifclear
+
+
+@node Help, , Completion, Commands
+@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
+@kindex h
+@item help
+@itemx 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} displays a
+short paragraph on how to use that command.
+
+@kindex complete
+@item complete @var{args}
+The @code{complete @var{args}} command lists all the possible completions
+for the beginning of a command. Use @var{args} to specify the beginning of the
+command you want completed. For example:
+
+@smallexample
+complete i
+@end smallexample
+
+@noindent results in:
+
+@smallexample
+@group
+info
+inspect
+ignore
+@end group
+@end smallexample
+
+@noindent This is intended for use by @sc{gnu} Emacs.
+@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
+@kindex info
+@kindex i
+@item info
+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 set
+@item set
+You can assign the result of an expression to an environment variable with
+@code{set}. For example, you can set the @value{GDBN} prompt to a $-sign with
+@code{set prompt $}.
+
+@kindex show
+@item show
+In contrast to @code{info}, @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 @sc{gnu} ``NO WARRANTY'' statement.
+@end table
+
+@node Running, Stopping, Commands, Top
+@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 @value{GDBN} 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
+@end ifclear
+
+* 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
+@ifclear HPPA
+* Process Information:: Additional process information
+@end ifclear
+
+* Threads:: Debugging programs with multiple threads
+* Processes:: Debugging programs with multiple processes
+@end menu
+
+@node Compilation, Starting, Running, Running
+@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.
+
+@ifclear HPPA
+@value{NGCC}, the @sc{gnu} C compiler, supports @samp{-g} with or without
+@end ifclear
+@ifset HPPA
+The HP ANSI C and C++ compilers, as well as @value{NGCC}, the @sc{gnu} C
+compiler, support @samp{-g} with or without
+@end ifset
+@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 shows 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} never sees 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 to us as a bug (including a test case!).
+
+Older versions of the @sc{gnu} C compiler permitted a variant option
+@w{@samp{-gg}} for debugging information. @value{GDBN} no longer supports this
+format; if your @sc{gnu} C compiler has this option, do not use it.
+
+@need 2000
+@node Starting, Arguments, Compilation, Running
+@section Starting your program
+@cindex starting
+@cindex running
+
+@table @code
+@kindex run
+@item run
+@itemx r
+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 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 affect
+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} discards its symbol
+table, and reads it again. When it does this, @value{GDBN} tries to retain
+your current breakpoints.
+
+@ifclear BARETARGET
+@node Arguments, Environment, Starting, Running
+@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} uses. 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} executes 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.
+
+@kindex show args
+@item show args
+Show the arguments to give your program when it is started.
+@end table
+
+@node Environment, Working Directory, Arguments, Running
+@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
+@kindex path
+@item path @var{directory}
+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 is 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.
+
+@kindex show paths
+@item show paths
+Display the list of search paths for executables (the @code{PATH}
+environment variable).
+
+@kindex show environment
+@item show environment @r{[}@var{varname}@r{]}
+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}.
+
+@kindex set environment
+@item set environment @var{varname} @r{[}=@r{]} @var{value}
+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.)
+
+@kindex unset environment
+@item unset environment @var{varname}
+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 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, Input/Output, Environment, Running
+@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
+@kindex cd
+@item cd @var{directory}
+Set the @value{GDBN} working directory to @var{directory}.
+
+@kindex pwd
+@item pwd
+Print the @value{GDBN} working directory.
+@end table
+
+@node Input/Output, Attach, Working Directory, Running
+@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
+@kindex info terminal
+@item 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, Kill Process, Input/Output, Running
+@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} shows 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} does 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 you use @code{attach}, the debugger finds the program running in
+the process first by looking in the current working directory, then (if
+the program is not found) by using the source file search path
+(@pxref{Source Path, ,Specifying source directories}). You can also use
+the @code{file} command to load the program. @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
+@ifclear HPPA
+processes with @code{run}. You can insert breakpoints; you can step and
+@end ifclear
+@ifset HPPA
+processes with @code{run}. You can insert breakpoints (except in shared
+libraries); you can step and
+@end ifset
+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
+@kindex detach
+@item 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} does 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, @value{GDBN} asks
+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}).
+
+@ifset HPPA
+@node Kill Process, Threads, Attach, Running
+@section Killing the child process
+@end ifset
+@ifclear HPPA
+@node Kill Process, Process Information, Attach, Running
+@section Killing the child process
+@end ifclear
+
+@table @code
+@kindex kill
+@item 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.
+
+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} notices that the file has changed, and
+reads the symbol table again (while trying to preserve your current
+breakpoint settings).
+
+@ifclear HPPA
+@node Process Information, Threads, Kill Process, Running
+@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.
+@code{info proc} works only on SVR4 systems that support @code{procfs}.
+
+@table @code
+@kindex info proc
+@item info proc
+Summarize available information about the process.
+
+@kindex info proc mappings
+@item 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.
+
+@kindex info proc times
+@item info proc times
+Starting time, user CPU time, and system CPU time for your program and
+its children.
+
+@kindex info proc id
+@item 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.
+
+@kindex info proc status
+@item 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
+
+@ifset HPPA
+@node Threads, Processes, Kill Process, Running
+@section Debugging programs with multiple threads
+@end ifset
+@ifclear HPPA
+@node Threads, Processes, Process Information, Running
+@section Debugging programs with multiple threads
+@end ifclear
+
+@cindex threads of execution
+@cindex multiple threads
+@cindex switching threads
+In some operating systems, such as HP-UX and Solaris, a single program
+may have more than one @dfn{thread} of execution. The precise semantics
+of threads differ from one operating system to another, but in general
+the threads of a single program are akin to multiple processes---except
+that they share one address space (that is, they can all examine and
+modify the same variables). On the other hand, each thread has its own
+registers and execution stack, and perhaps private memory.
+
+@value{GDBN} provides these facilities for debugging multi-thread
+programs:
+
+@itemize @bullet
+@item automatic notification of new threads
+@item @samp{thread @var{threadno}}, a command to switch among threads
+@item @samp{info threads}, a command to inquire about existing threads
+@item @samp{thread apply [@var{threadno}] [@var{all}] @var{args}},
+a command to apply a command to a list of threads
+@item thread-specific breakpoints
+@end itemize
+
+@ifclear HPPA
+@quotation
+@emph{Warning:} These facilities are not yet available on every
+@value{GDBN} configuration where the operating system supports threads.
+If your @value{GDBN} does not support threads, these commands have no
+effect. For example, a system without thread support shows no output
+from @samp{info threads}, and always rejects the @code{thread} command,
+like this:
+
+@smallexample
+(@value{GDBP}) info threads
+(@value{GDBP}) thread 1
+Thread ID 1 not known. Use the "info threads" command to
+see the IDs of currently known threads.
+@end smallexample
+@c FIXME to implementors: how hard would it be to say "sorry, this GDB
+@c doesn't support threads"?
+@end quotation
+@end ifclear
+
+@cindex focus of debugging
+@cindex current thread
+The @value{GDBN} thread debugging facility allows you to observe all
+threads while your program runs---but whenever @value{GDBN} takes
+control, one thread in particular is always the focus of debugging.
+This thread is called the @dfn{current thread}. Debugging commands show
+program information from the perspective of the current thread.
+
+@ifclear HPPA
+@kindex New @var{systag}
+@cindex thread identifier (system)
+@c FIXME-implementors!! It would be more helpful if the [New...] message
+@c included GDB's numeric thread handle, so you could just go to that
+@c thread without first checking `info threads'.
+Whenever @value{GDBN} detects a new thread in your program, it displays
+the target system's identification for the thread with a message in the
+form @samp{[New @var{systag}]}. @var{systag} is a thread identifier
+whose form varies depending on the particular system. For example, on
+LynxOS, you might see
+
+@example
+[New process 35 thread 27]
+@end example
+
+@noindent
+when @value{GDBN} notices a new thread. In contrast, on an SGI system,
+the @var{systag} is simply something like @samp{process 368}, with no
+further qualifier.
+
+@c FIXME!! (1) Does the [New...] message appear even for the very first
+@c thread of a program, or does it only appear for the
+@c second---i.e., when it becomes obvious we have a multithread
+@c program?
+@c (2) *Is* there necessarily a first thread always? Or do some
+@c multithread systems permit starting a program with multiple
+@c threads ab initio?
+
+@cindex thread number
+@cindex thread identifier (GDB)
+For debugging purposes, @value{GDBN} associates its own thread
+number---always a single integer---with each thread in your program.
+
+@table @code
+@kindex info threads
+@item info threads
+Display a summary of all threads currently in your
+program. @value{GDBN} displays for each thread (in this order):
+
+@enumerate
+@item the thread number assigned by @value{GDBN}
+
+@item the target system's thread identifier (@var{systag})
+
+@item the current stack frame summary for that thread
+@end enumerate
+
+@noindent
+An asterisk @samp{*} to the left of the @value{GDBN} thread number
+indicates the current thread.
+
+For example,
+@end table
+@c end table here to get a little more width for example
+
+@smallexample
+(@value{GDBP}) info threads
+ 3 process 35 thread 27 0x34e5 in sigpause ()
+ 2 process 35 thread 23 0x34e5 in sigpause ()
+* 1 process 35 thread 13 main (argc=1, argv=0x7ffffff8)
+ at threadtest.c:68
+@end smallexample
+@end ifclear
+@ifset HPPA
+
+@cindex thread number
+@cindex thread identifier (GDB)
+For debugging purposes, @value{GDBN} associates its own thread
+number---a small integer assigned in thread-creation order---with each
+thread in your program.
+
+@kindex New @var{systag}
+@cindex thread identifier (system)
+@c FIXME-implementors!! It would be more helpful if the [New...] message
+@c included GDB's numeric thread handle, so you could just go to that
+@c thread without first checking `info threads'.
+Whenever @value{GDBN} detects a new thread in your program, it displays
+both @value{GDBN}'s thread number and the target system's identification for the thread with a message in the
+form @samp{[New @var{systag}]}. @var{systag} is a thread identifier
+whose form varies depending on the particular system. For example, on
+HP-UX, you see
+
+@example
+[New thread 2 (system thread 26594)]
+@end example
+
+@noindent
+when @value{GDBN} notices a new thread.
+
+@table @code
+@kindex info threads
+@item info threads
+Display a summary of all threads currently in your
+program. @value{GDBN} displays for each thread (in this order):
+
+@enumerate
+@item the thread number assigned by @value{GDBN}
+
+@item the target system's thread identifier (@var{systag})
+
+@item the current stack frame summary for that thread
+@end enumerate
+
+@noindent
+An asterisk @samp{*} to the left of the @value{GDBN} thread number
+indicates the current thread.
+
+For example,
+@end table
+@c end table here to get a little more width for example
+
+@example
+(@value{GDBP}) info threads
+ * 3 system thread 26607 worker (wptr=0x7b09c318 "@@") at quicksort.c:137
+ 2 system thread 26606 0x7b0030d8 in __ksleep () from /usr/lib/libc.2
+ 1 system thread 27905 0x7b003498 in _brk () from /usr/lib/libc.2
+@end example
+@end ifset
+
+@table @code
+@kindex thread @var{threadno}
+@item thread @var{threadno}
+Make thread number @var{threadno} the current thread. The command
+argument @var{threadno} is the internal @value{GDBN} thread number, as
+shown in the first field of the @samp{info threads} display.
+@value{GDBN} responds by displaying the system identifier of the thread
+you selected, and its current stack frame summary:
+
+@smallexample
+@c FIXME!! This example made up; find a @value{GDBN} w/threads and get real one
+(@value{GDBP}) thread 2
+@ifclear HPPA
+[Switching to process 35 thread 23]
+@end ifclear
+@ifset HPPA
+[Switching to thread 2 (system thread 26594)]
+@end ifset
+0x34e5 in sigpause ()
+@end smallexample
+
+@noindent
+As with the @samp{[New @dots{}]} message, the form of the text after
+@samp{Switching to} depends on your system's conventions for identifying
+threads.
+
+@kindex thread apply
+@item thread apply [@var{threadno}] [@var{all}] @var{args}
+The @code{thread apply} command allows you to apply a command to one or
+more threads. Specify the numbers of the threads that you want affected
+with the command argument @var{threadno}. @var{threadno} is the internal
+@value{GDBN} thread number, as shown in the first field of the @samp{info
+threads} display. To apply a command to all threads, use
+@code{thread apply all} @var{args}.
+@end table
+
+@cindex automatic thread selection
+@cindex switching threads automatically
+@cindex threads, automatic switching
+Whenever @value{GDBN} stops your program, due to a breakpoint or a
+signal, it automatically selects the thread where that breakpoint or
+signal happened. @value{GDBN} alerts you to the context switch with a
+message of the form @samp{[Switching to @var{systag}]} to identify the
+thread.
+
+@xref{Thread Stops,,Stopping and starting multi-thread programs}, for
+more information about how @value{GDBN} behaves when you stop and start
+programs with multiple threads.
+
+@xref{Set Watchpoints,,Setting watchpoints}, for information about
+watchpoints in programs with multiple threads.
+@end ifclear
+
+@ifclear HPPA
+@node Processes, , Threads, Running
+@section Debugging programs with multiple processes
+
+@cindex fork, debugging programs which call
+@cindex multiple processes
+@cindex processes, multiple
+@value{GDBN} has no special support for debugging programs which create
+additional processes using the @code{fork} function. When a program
+forks, @value{GDBN} will continue to debug the parent process and the
+child process will run unimpeded. If you have set a breakpoint in any
+code which the child then executes, the child will get a @code{SIGTRAP}
+signal which (unless it catches the signal) will cause it to terminate.
+
+However, if you want to debug the child process there is a workaround
+which isn't too painful. Put a call to @code{sleep} in the code which
+the child process executes after the fork. It may be useful to sleep
+only if a certain environment variable is set, or a certain file exists,
+so that the delay need not occur when you don't want to run @value{GDBN}
+on the child. While the child is sleeping, use the @code{ps} program to
+get its process ID. Then tell @value{GDBN} (a new invocation of
+@value{GDBN} if you are also debugging the parent process) to attach to
+the child process (see @ref{Attach}). From that point on you can debug
+the child process just like any other process which you attached to.
+@end ifclear
+@ifset HPPA
+@node Processes, , Threads, Running
+@section Debugging programs with multiple processes
+
+@cindex fork, debugging programs which call
+@cindex multiple processes
+@cindex processes, multiple
+
+@value{GDBN} provides support for debugging programs that create
+additional processes using the @code{fork} or @code{vfork} function.
+
+By default, when a program forks, @value{GDBN} will continue to debug
+the parent process and the child process will run unimpeded.
+
+If you want to follow the child process instead of the parent process,
+use the command @w{@code{set follow-fork-mode}}.
+
+@table @code
+@kindex set follow-fork-mode
+@item set follow-fork-mode @var{mode}
+Set the debugger response to a program call of @code{fork} or
+@code{vfork}. A call to @code{fork} or @code{vfork} creates a new
+process. The @var{mode} can be:
+
+@table @code
+@item parent
+The original process is debugged after a fork. The child process runs
+unimpeded.
+
+@item child
+The new process is debugged after a fork. The parent process runs
+unimpeded.
+
+@item ask
+The debugger will ask for one of the above choices.
+@end table
+
+@item show follow-fork-mode
+Display the current debugger response to a fork or vfork call.
+@end table
+
+If you ask to debug a child process and a @code{vfork} is followed by an
+@code{exec}, @value{GDBN} executes the new target up to the first
+breakpoint in the new target. If you have a breakpoint set on
+@code{main} in your original program, the breakpoint will also be set on
+the child process's @code{main}.
+
+When a child process is spawned by @code{vfork}, you cannot debug the
+child or parent until an @code{exec} call completes.
+
+If you issue a @code{run} command to @value{GDBN} after an @code{exec}
+call executes, the new target restarts. To restart the parent process,
+use the @code{file} command with the parent executable name as its
+argument.
+
+You can use the @code{catch} command to make @value{GDBN} stop whenever
+a @code{fork}, @code{vfork}, or @code{exec} call is made. @xref{Set
+Catchpoints, ,Setting catchpoints}.
+@end ifset
+
+@node Stopping, Stack, Running, Top
+@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
+@kindex info program
+@item 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
+* Breakpoints:: Breakpoints, watchpoints, and catchpoints
+* Continuing and Stepping:: Resuming execution
+@ifset POSIX
+* Signals:: Signals
+@end ifset
+
+@ifclear BARETARGET
+* Thread Stops:: Stopping and starting multi-thread programs
+@end ifclear
+
+@end menu
+
+@node Breakpoints, Continuing and Stepping, Stopping, Stopping
+@section Breakpoints, watchpoints, and catchpoints
+
+@cindex breakpoints
+A @dfn{breakpoint} makes your program stop whenever a certain point in
+the program is reached. For each breakpoint, you can add conditions to
+control in finer detail whether your program stops. 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.
+
+In HP-UX, SunOS 4.x, SVR4, and Alpha OSF/1 configurations, you can set
+breakpoints in shared libraries before the executable is run. There is
+a minor limitation on HP-UX systems: you must wait until the executable
+is run in order to set breakpoints in shared library routines that are
+not called directly by the program (for example, routines that are
+arguments in a @code{pthread_create} call).
+
+@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 catchpoints
+@cindex breakpoint on events
+A @dfn{catchpoint} is another special breakpoint that stops your program
+when a certain kind of event occurs, such as the throwing of a C++
+exception or the loading of a library. As with watchpoints, you use a
+different command to set a catchpoint (@pxref{Set Catchpoints, ,Setting
+catchpoints}), but aside from that, you can manage a catchpoint like any
+other breakpoint. (To stop when your program receives a signal, use the
+@code{handle} command; @pxref{Signals, ,Signals}.)
+
+@cindex breakpoint numbers
+@cindex numbers for breakpoints
+@value{GDBN} assigns a number to each breakpoint, watchpoint, or
+catchpoint 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
+* Set Catchpoints:: Setting catchpoints
+* Delete Breaks:: Deleting breakpoints
+* Disabling:: Disabling breakpoints
+* Conditions:: Break conditions
+* Break Commands:: Breakpoint command lists
+@ifclear CONLY
+* Breakpoint Menus:: Breakpoint menus
+@end ifclear
+
+@c @ifclear BARETARGET
+@c * Error in Breakpoints:: ``Cannot insert breakpoints''
+@c @end ifclear
+@end menu
+
+@node Set Breaks, Set Watchpoints, Breakpoints, Breakpoints
+@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 breakpoints 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 stops 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 makes your program 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} stops
+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.
+
+@kindex tbreak
+@item tbreak @var{args}
+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 deleted after the first time your
+program stops there. @xref{Disabling, ,Disabling breakpoints}.
+
+@ifclear HPPA
+@kindex hbreak
+@item hbreak @var{args}
+Set a hardware-assisted breakpoint. @var{args} are the same as for the
+@code{break} command and the breakpoint is set in the same way, but the
+breakpoint requires hardware support and some target hardware may not
+have this support. The main purpose of this is EPROM/ROM code
+debugging, so you can set a breakpoint at an instruction without
+changing the instruction. This can be used with the new trap-generation
+provided by SPARClite DSU. DSU will generate traps when a program accesses
+some data or instruction address that is assigned to the debug registers.
+However the hardware breakpoint registers can only take two data breakpoints,
+and @value{GDBN} will reject this command if more than two are used.
+Delete or disable unused hardware breakpoints before setting
+new ones. @xref{Conditions, ,Break conditions}.
+
+@kindex thbreak
+@item thbreak @var{args}
+Set a hardware-assisted breakpoint enabled only for one stop. @var{args}
+are the same as for the @code{hbreak} command and the breakpoint is set in
+the same way. However, like the @code{tbreak} command,
+the breakpoint is automatically deleted after the
+first time your program stops there. Also, like the @code{hbreak}
+command, the breakpoint requires hardware support and some target hardware
+may not have this support. @xref{Disabling, ,Disabling breakpoints}.
+Also @xref{Conditions, ,Break conditions}.
+@end ifclear
+
+@kindex rbreak
+@cindex regular expression
+@item rbreak @var{regex}
+@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. You can
+delete them, disable them, or make them conditional the same way as any
+other breakpoint.
+
+@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, watchpoints, and catchpoints set and
+not deleted, with the following columns for each breakpoint:
+
+@table @emph
+@item Breakpoint Numbers
+@item Type
+Breakpoint, watchpoint, or catchpoint.
+@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}).
+
+@noindent
+@code{info break} displays a count of the number of times the breakpoint
+has been hit. This is especially useful in conjunction with the
+@code{ignore} command. You can ignore a large number of breakpoint
+hits, look at the breakpoint info to see how many times the breakpoint
+was hit, and then run again, ignoring one less than that number. This
+will get you quickly to the last hit of that breakpoint.
+@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.
+
+@ifset HPPA
+@item shlib events
+Shared library events.
+@end ifset
+@end table
+@end table
+
+
+@node Set Watchpoints, Set Catchpoints, Set Breaks, Breakpoints
+@subsection Setting watchpoints
+
+@cindex setting watchpoints
+@cindex software watchpoints
+@cindex hardware 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.
+
+Depending on your system, watchpoints may be implemented in software or
+hardware. GDB does software watchpointing by single-stepping your
+program and testing the variable's value each time, which is hundreds of
+times slower than normal execution. (But this may still be worth it, to
+catch errors where you have no clue what part of your program is the
+culprit.)
+
+On some systems, such as HP-UX and Linux, GDB includes support for
+hardware watchpoints, which do not slow down the running of your
+program.
+
+@table @code
+@kindex watch
+@item watch @var{expr}
+Set a watchpoint for an expression. @value{GDBN} will break when @var{expr}
+is written into by the program and its value changes.
+
+@kindex rwatch
+@item rwatch @var{expr}
+Set a watchpoint that will break when watch @var{expr} is read by the program.
+If you use both watchpoints, both must be set with the @code{rwatch}
+command.
+
+@kindex awatch
+@item awatch @var{expr}
+Set a watchpoint that will break when @var{args} is read and written into
+by the program. If you use both watchpoints, both must be set with the
+@code{awatch} command.
+
+@kindex info watchpoints
+@item info watchpoints
+This command prints a list of watchpoints, breakpoints, and catchpoints;
+it is the same as @code{info break}.
+@end table
+
+@value{GDBN} sets a @dfn{hardware watchpoint} if possible. Hardware
+watchpoints execute very quickly, and the debugger reports a change in
+value at the exact instruction where the change occurs. If @value{GDBN}
+cannot set a hardware watchpoint, it sets a software watchpoint, which
+executes more slowly and reports the change in value at the next
+statement, not the instruction, after the change occurs.
+
+When you issue the @code{watch} command, @value{GDBN} reports
+
+@example
+Hardware watchpoint @var{num}: @var{expr}
+@end example
+
+@noindent
+if it was able to set a hardware watchpoint.
+
+The SPARClite DSU will generate traps when a program accesses
+some data or instruction address that is assigned to the debug registers.
+For the data addresses, DSU facilitates the @code{watch} command.
+However the hardware breakpoint registers can only take two data watchpoints,
+and both watchpoints must be the same kind. For example, you can set two
+watchpoints with @code{watch} commands, two with @code{rwatch}
+commands, @strong{or} two with @code{awatch} commands, but you cannot set one
+watchpoint with one command and the other with a different command.
+@value{GDBN} will reject the command if you try to mix watchpoints.
+Delete or disable unused watchpoint commands before setting new ones.
+
+If you call a function interactively using @code{print} or @code{call},
+any watchpoints you have set will be inactive until GDB reaches another
+kind of breakpoint or the call completes.
+
+@ifclear BARETARGET
+@quotation
+@cindex watchpoints and threads
+@cindex threads and watchpoints
+@ifclear HPPA
+@emph{Warning:} In multi-thread programs, watchpoints have only limited
+usefulness. With the current watchpoint implementation, @value{GDBN}
+can only watch the value of an expression @emph{in a single thread}. If
+you are confident that the expression can only change due to the current
+thread's activity (and if you are also confident that no other thread
+can become current), then you can use watchpoints as usual. However,
+@value{GDBN} may not notice when a non-current thread's activity changes
+the expression.
+@end ifclear
+@ifset HPPA
+@emph{Warning:} In multi-thread programs, software watchpoints have only
+limited usefulness. If @value{GDBN} creates a software watchpoint, it
+can only watch the value of an expression @emph{in a single thread}. If
+you are confident that the expression can only change due to the current
+thread's activity (and if you are also confident that no other thread
+can become current), then you can use software watchpoints as usual.
+However, @value{GDBN} may not notice when a non-current thread's
+activity changes the expression. (Hardware watchpoints, in contrast,
+watch an expression in all threads.)
+@end ifset
+@end quotation
+@end ifclear
+
+@node Set Catchpoints, Delete Breaks, Set Watchpoints, Breakpoints
+@subsection Setting catchpoints
+@cindex catchpoints
+@cindex exception handlers
+@cindex event handling
+
+You can use @dfn{catchpoints} to cause the debugger to stop for certain
+kinds of program events, such as C++ exceptions or the loading of a
+shared library. Use the @code{catch} command to set a catchpoint.
+
+@table @code
+@kindex catch
+@item catch @var{event}
+Stop when @var{event} occurs. @var{event} can be any of the following:
+@table @code
+@item throw
+@kindex catch throw
+The throwing of a C++ exception.
+
+@item catch
+@kindex catch catch
+The catching of a C++ exception.
+
+@item exec
+@kindex catch exec
+A call to @code{exec}. This is currently only available for HP-UX.
+
+@item fork
+@kindex catch fork
+A call to @code{fork}. This is currently only available for HP-UX.
+
+@item vfork
+@kindex catch vfork
+A call to @code{vfork}. This is currently only available for HP-UX.
+
+@item load
+@itemx load @var{libname}
+@kindex catch load
+The dynamic loading of any shared library, or the loading of the library
+@var{libname}. This is currently only available for HP-UX.
+
+@item unload
+@itemx unload @var{libname}
+@kindex catch unload
+The unloading of any dynamically loaded shared library, or the unloading
+of the library @var{libname}. This is currently only available for HP-UX.
+@end table
+
+@item tcatch @var{event}
+Set a catchpoint that is enabled only for one stop. The catchpoint is
+automatically deleted after the first time the event is caught.
+
+@end table
+
+Use the @code{info break} command to list the current catchpoints.
+
+There are currently some limitations to C++ exception handling
+(@code{catch throw} and @code{catch catch}) in @value{GDBN}:
+
+@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 either to abort or to
+simply continue running until it hits a breakpoint, catches a signal
+that @value{GDBN} is listening for, or exits. This is the case even if
+you set a catchpoint for the exception; catchpoints on exceptions are
+disabled within interactive calls.
+
+@item
+You cannot raise an exception interactively.
+
+@item
+You cannot install an exception handler interactively.
+@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 @sc{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.
+
+
+@node Delete Breaks, Disabling, Set Catchpoints, Breakpoints
+@subsection Deleting breakpoints
+
+@cindex clearing breakpoints, watchpoints, catchpoints
+@cindex deleting breakpoints, watchpoints, catchpoints
+It is often necessary to eliminate a breakpoint, watchpoint, or
+catchpoint 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, watchpoints, or catchpoints 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
+@kindex clear
+@item 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.
+
+@cindex delete breakpoints
+@kindex delete
+@kindex d
+@item delete @r{[}breakpoints@r{]} @r{[}@var{bnums}@dots{}@r{]}
+Delete the breakpoints, watchpoints, or catchpoints 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, Conditions, Delete Breaks, Breakpoints
+@subsection Disabling breakpoints
+
+@kindex disable breakpoints
+@kindex enable breakpoints
+Rather than deleting a breakpoint, watchpoint, or catchpoint, 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, watchpoints, and catchpoints 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, watchpoints, and
+catchpoints if you do not know which numbers to use.
+
+A breakpoint, watchpoint, or catchpoint can have any of four different
+states of enablement:
+
+@itemize @bullet
+@item
+Enabled. The breakpoint stops 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 stops your program, but then becomes
+disabled. A breakpoint set with the @code{tbreak} command starts out in
+this state.
+@item
+Enabled for deletion. The breakpoint stops your program, but
+immediately after it does so it is deleted permanently.
+@end itemize
+
+You can use the following commands to enable or disable breakpoints,
+watchpoints, and catchpoints:
+
+@table @code
+@kindex disable breakpoints
+@kindex disable
+@kindex dis
+@item disable @r{[}breakpoints@r{]} @r{[}@var{bnums}@dots{}@r{]}
+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}.
+
+@kindex enable breakpoints
+@kindex enable
+@item enable @r{[}breakpoints@r{]} @r{[}@var{bnums}@dots{}@r{]}
+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. @value{GDBN} disables any
+of these breakpoints immediately after stopping your program.
+
+@item enable @r{[}breakpoints@r{]} delete @var{bnums}@dots{}
+Enable the specified breakpoints to work once, then die. @value{GDBN}
+deletes any of these breakpoints as soon as your program stops there.
+@end table
+
+Except 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 does not change the state of your other
+breakpoints; see @ref{Continuing and Stepping, ,Continuing and
+stepping}.)
+
+@node Conditions, Break Commands, Disabling, Breakpoints
+@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.
+@ifclear HPPA
+@c The watch command now seems to recognize the if keyword.
+@c catch doesn't, though.
+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.
+@end ifclear
+@ifset HPPA
+You can also use the @code{if} keyword with the @code{watch} command.
+The @code{catch} command does not recognize the @code{if} keyword;
+@code{condition} is the only way to impose a further condition on a
+catchpoint.
+@end ifset
+
+@table @code
+@kindex condition
+@item condition @var{bnum} @var{expression}
+Specify @var{expression} as the break condition for breakpoint,
+watchpoint, or catchpoint number @var{bnum}. After you set a condition,
+breakpoint @var{bnum} stops 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 does not stop the next @var{n} times
+your program reaches it.
+
+@table @code
+@kindex ignore
+@item ignore @var{bnum} @var{count}
+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 does 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,
+@value{GDBN} resumes checking the condition.
+
+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
+
+Ignore counts apply to breakpoints, watchpoints, and catchpoints.
+
+
+@node Break Commands, Breakpoint Menus, Conditions, Breakpoints
+@subsection Breakpoint command lists
+
+@cindex breakpoint commands
+You can give any breakpoint (or watchpoint or catchpoint) 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
+@kindex commands
+@kindex end
+@item commands @r{[}@var{bnum}@r{]}
+@itemx @dots{} @var{command-list} @dots{}
+@itemx 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, watchpoint, or catchpoint 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
+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, , Break Commands, Breakpoints
+@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 is 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
+@group
+(@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 group
+@end smallexample
+@end ifclear
+
+@c @ifclear BARETARGET
+@c @node Error in Breakpoints
+@c @subsection ``Cannot insert breakpoints''
+@c
+@c FIXME!! 14/6/95 Is there a real example of this? Let's use it.
+@c
+@c Under some operating systems, breakpoints cannot be used in a program if
+@c any other process is running that program. In this situation,
+@c attempting to run or continue a program with a breakpoint causes
+@c @value{GDBN} to stop the other process.
+@c
+@c When this happens, you have three ways to proceed:
+@c
+@c @enumerate
+@c @item
+@c Remove or disable the breakpoints, then continue.
+@c
+@c @item
+@c Suspend @value{GDBN}, and copy the file containing your program to a new
+@c name. Resume @value{GDBN} and use the @code{exec-file} command to specify
+@c that @value{GDBN} should run your program under that name.
+@c Then start your program again.
+@c
+@c @item
+@c Relink your program so that the text segment is nonsharable, using the
+@c linker option @samp{-N}. The operating system limitation may not apply
+@c to nonsharable executables.
+@c @end enumerate
+@c @end ifclear
+
+@node Continuing and Stepping, Signals, Breakpoints, Stopping
+@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
+@kindex continue
+@kindex c
+@kindex fg
+@item continue @r{[}@var{ignore-count}@r{]}
+@itemx c @r{[}@var{ignore-count}@r{]}
+@itemx fg @r{[}@var{ignore-count}@r{]}
+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
+(@pxref{Breakpoints, ,Breakpoints; watchpoints; and catchpoints}) 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
+@kindex step
+@kindex s
+@item step
+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
+@c "without debugging information" is imprecise; actually "without line
+@c numbers in the debugging information". (gcc -g1 has debugging info but
+@c not line numbers). But it seems complex to try to make that
+@c distinction here.
+@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. Likewise, it will not step into a function which
+is compiled without debugging information. To step through functions
+without debugging information, use the @code{stepi} command, described
+below.
+@end quotation
+
+The @code{step} command now only stops at the first instruction of a
+source line. This prevents the multiple stops that used to occur in
+switch statements, for loops, etc. @code{step} continues to stop if a
+function that has debugging information is called within the line.
+
+Also, the @code{step} command now only enters a subroutine if there is line
+number information for the subroutine. Otherwise it acts like the
+@code{next} command. This avoids problems when using @code{cc -gl}
+on MIPS machines. Previously, @code{step} entered subroutines if there
+was any debugging information about the routine.
+
+@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.
+
+@kindex next
+@kindex n
+@item next @r{[}@var{count}@r{]}
+Continue to the next source line in the current (innermost) stack frame.
+This is similar to @code{step}, but function calls that appear within the line
+of code are executed without stopping. Execution stops when control
+reaches a different line of code at the original stack level that was
+executing when you gave the @code{next} command. This command is abbreviated
+@code{n}.
+
+An argument @var{count} is a repeat count, as for @code{step}.
+
+
+@c FIX ME!! Do we delete this, or is there a way it fits in with
+@c the following paragraph? --- Vctoria
+@c
+@c @code{next} within a function that lacks debugging information acts like
+@c @code{step}, but any function calls appearing within the code of the
+@c function are executed without stopping.
+
+The @code{next} command now only stops at the first instruction of a
+source line. This prevents the multiple stops that used to occur in
+switch statements, for loops, etc.
+
+@kindex finish
+@item 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}).
+
+@kindex until
+@kindex u
+@item until
+@itemx 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} makes your program continue execution until it
+exits the loop. In contrast, a @code{next} command at the end of a loop
+simply steps back to the beginning of the loop, which forces 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.
+
+@kindex stepi
+@kindex si
+@item stepi
+@itemx 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 makes @value{GDBN} automatically display the next
+instruction to be executed, each time your program stops. @xref{Auto
+Display,, Automatic display}.
+
+An argument is a repeat count, as in @code{step}.
+
+@need 750
+@kindex nexti
+@kindex ni
+@item nexti
+@itemx 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, Thread Stops, Continuing and Stepping, Stopping
+@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
+@kindex info signals
+@item 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.
+
+@code{info handle} is the new alias for @code{info signals}.
+
+@kindex handle
+@item handle @var{signal} @var{keywords}@dots{}
+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
+can handle the signal, or else it may terminate 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 sees 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 your
+program sees that signal when you continue.
+
+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
+
+@ifclear BARETARGET
+@node Thread Stops, , Signals, Stopping
+@section Stopping and starting multi-thread programs
+
+When your program has multiple threads (@pxref{Threads,, Debugging
+programs with multiple threads}), you can choose whether to set
+breakpoints on all threads, or on a particular thread.
+
+@table @code
+@cindex breakpoints and threads
+@cindex thread breakpoints
+@kindex break @dots{} thread @var{threadno}
+@item break @var{linespec} thread @var{threadno}
+@itemx break @var{linespec} thread @var{threadno} if @dots{}
+@var{linespec} specifies source lines; there are several ways of
+writing them, but the effect is always to specify some source line.
+
+Use the qualifier @samp{thread @var{threadno}} with a breakpoint command
+to specify that you only want @value{GDBN} to stop the program when a
+particular thread reaches this breakpoint. @var{threadno} is one of the
+numeric thread identifiers assigned by @value{GDBN}, shown in the first
+column of the @samp{info threads} display.
+
+If you do not specify @samp{thread @var{threadno}} when you set a
+breakpoint, the breakpoint applies to @emph{all} threads of your
+program.
+
+You can use the @code{thread} qualifier on conditional breakpoints as
+well; in this case, place @samp{thread @var{threadno}} before the
+breakpoint condition, like this:
+
+@smallexample
+(gdb) break frik.c:13 thread 28 if bartab > lim
+@end smallexample
+
+@end table
+
+@cindex stopped threads
+@cindex threads, stopped
+Whenever your program stops under @value{GDBN} for any reason,
+@emph{all} threads of execution stop, not just the current thread. This
+allows you to examine the overall state of the program, including
+switching between threads, without worrying that things may change
+underfoot.
+
+@cindex continuing threads
+@cindex threads, continuing
+Conversely, whenever you restart the program, @emph{all} threads start
+executing. @emph{This is true even when single-stepping} with commands
+like @code{step} or @code{next}.
+
+In particular, @value{GDBN} cannot single-step all threads in lockstep.
+Since thread scheduling is up to your debugging target's operating
+system (not controlled by @value{GDBN}), other threads may
+execute more than one statement while the current thread completes a
+single step. Moreover, in general other threads stop in the middle of a
+statement, rather than at a clean statement boundary, when the program
+stops.
+
+You might even find your program stopped in another thread after
+continuing or even single-stepping. This happens whenever some other
+thread runs into a breakpoint, a signal, or an exception before the
+first thread completes whatever you requested.
+
+On some OSes, you can lock the OS scheduler and thus allow only a single
+thread to run.
+
+@table @code
+@item set scheduler-locking @var{mode}
+Set the scheduler locking mode. If it is @code{off}, then there is no
+locking and any thread may run at any time. If @code{on}, then only the
+current thread may run when the inferior is resumed. The @code{step}
+mode optimizes for single-stepping. It stops other threads from
+``seizing the prompt'' by preempting the current thread while you are
+stepping. Other threads will only rarely (or never) get a chance to run
+when you step. They are more likely to run when you ``next'' over a
+function call, and they are completely free to run when you use commands
+like ``continue'', ``until'', or ``finish''. However, unless another
+thread hits a breakpoint during its timeslice, they will never steal the
+GDB prompt away from the thread that you are debugging.
+
+@item show scheduler-locking
+Display the current scheduler locking mode.
+@end table
+
+@end ifclear
+
+
+@node Stack, Source, Stopping, Top
+@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, information about the call
+is generated.
+That information includes the location of the call in your program,
+the arguments of the call,
+and the local variables of the function being called.
+The information is saved in a block of data called a @dfn{stack frame}.
+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. @xref{Selection, ,Selecting a frame}.
+
+When your program stops, @value{GDBN} automatically selects the
+currently executing frame and describes it briefly, similar to the
+@code{frame} command (@pxref{Frame Info, ,Information about a frame}).
+
+@menu
+* Frames:: Stack frames
+* Backtrace:: Backtraces
+* Selection:: Selecting a frame
+* Frame Info:: Information on a frame
+* Alpha/MIPS Stack:: Alpha and MIPS machines and the function stack
+
+@end menu
+
+@node Frames, Backtrace, Stack, Stack
+@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 byte 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} generates 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} nevertheless regards 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.
+
+@table @code
+@kindex frame
+@item frame @var{args}
+The @code{frame} command allows you to move from one stack frame to another,
+and to print the stack frame you select. @var{args} may be either the
+address of the frame or the stack frame number. Without an argument,
+@code{frame} prints the current stack frame.
+
+@kindex select-frame
+@item select-frame
+The @code{select-frame} command allows you to move from one stack frame
+to another without printing the frame. This is the silent version of
+@code{frame}.
+@end table
+
+@node Backtrace, Selection, Frames, Stack
+@section Backtraces
+
+@cindex backtraces
+@cindex tracebacks
+@cindex stack traces
+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
+@kindex backtrace
+@kindex bt
+@item backtrace
+@itemx 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, Frame Info, Backtrace, Stack
+@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
+@kindex frame
+@kindex f
+@item frame @var{n}
+@itemx f @var{n}
+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.
+
+@ifclear H8EXCLUSIVE
+@ifclear HPPA
+On the SPARC architecture, @code{frame} needs two addresses to
+select an arbitrary frame: a frame pointer and a stack pointer.
+
+On the MIPS and Alpha architecture, it needs two addresses: a stack
+pointer and a program counter.
+
+On the 29k architecture, it needs three addresses: a register stack
+pointer, a program counter, and a memory stack pointer.
+@c note to future updaters: this is conditioned on a flag
+@c SETUP_ARBITRARY_FRAME in the tm-*.h files. The above is up to date
+@c as of 27 Jan 1994.
+@end ifclear
+@end ifclear
+
+@kindex up
+@item up @var{n}
+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.
+
+@kindex down
+@kindex do
+@item down @var{n}
+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.
+
+@need 1000
+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
+prints ten lines centered on the point of execution in the frame.
+@xref{List, ,Printing source lines}.
+
+@table @code
+@kindex down-silently
+@kindex up-silently
+@item up-silently @var{n}
+@itemx down-silently @var{n}
+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, Alpha/MIPS Stack, Selection, Stack
+@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}.
+
+@kindex info frame
+@kindex info f
+@item info frame
+@itemx info f
+This command prints a verbose description of the selected stack frame,
+including:
+
+@itemize @bullet
+@item
+the address of the frame
+@item
+the address of the next frame down (called by this frame)
+@item
+the address of the next frame up (caller of this frame)
+@item
+the language in which the source code corresponding to this frame is written
+@item
+the address of the frame's arguments
+@item
+the program counter saved in it (the address of execution in the caller frame)
+@item
+which registers were saved in the frame
+@end itemize
+
+@noindent 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. This requires the same kind of address (more than one for some
+architectures) that you specify in the @code{frame} command.
+@xref{Selection, ,Selecting a frame}.
+
+@kindex info args
+@item 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
+@ifclear HPPA
+@kindex info catch
+@cindex catch exceptions
+@cindex exception handlers
+@item 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 @code{up},
+@code{down}, or @code{frame} commands); then type @code{info catch}.
+@xref{Set Catchpoints, , Setting catchpoints}.
+@end ifclear
+@end ifclear
+@end table
+
+@node Alpha/MIPS Stack, , Frame Info, Stack
+@section MIPS/Alpha machines and the function stack
+
+@cindex stack on Alpha
+@cindex stack on MIPS
+@cindex Alpha stack
+@cindex MIPS stack
+Alpha- and 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:
+
+@table @code
+@cindex @code{heuristic-fence-post} (Alpha,MIPS)
+@item set heuristic-fence-post @var{limit}
+Restrict @value{GDBN} to examining at most @var{limit} bytes in its search
+for the beginning of a function. A value of @var{0} (the default)
+means there is no limit. However, except for @var{0}, the larger the
+limit the more bytes @code{heuristic-fence-post} must search and
+therefore the longer it takes to run.
+
+@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 Alpha or MIPS processors.
+
+
+@node Source, Data, Stack, Top
+@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 @sc{gnu} Emacs interface, you may prefer
+to use
+Emacs facilities to view source; @pxref{Emacs, ,Using @value{GDBN} under @sc{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, Search, Source, Source
+@section Printing source lines
+
+@kindex list
+@kindex l
+To print lines from a source file, use the @code{list} command
+(abbreviated @code{l}). By default, ten lines are printed.
+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
+@kindex set listsize
+@item set listsize @var{count}
+Make the @code{list} command display @var{count} source lines (unless
+the @code{list} argument explicitly specifies some other number).
+
+@kindex show listsize
+@item show listsize
+Display the number of lines that @code{list} prints.
+@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}
+Specifies the line that begins the body of the function @var{function}.
+For example: in C, this is the line with the open brace.
+
+@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, Source Path, List, Source
+@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
+@kindex search
+@kindex forward-search
+@item forward-search @var{regexp}
+@itemx search @var{regexp}
+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 the
+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, Machine Code, Search, Source
+@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} looks in the current directory as a
+last resort.
+
+Whenever you reset or rearrange the source path, @value{GDBN} clears out
+any information it has cached about where source files are found and where
+each line is in the file.
+
+@kindex directory
+@kindex dir
+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{}
+@item dir @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 @value{GDBN} searches it 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, , Source Path, Source
+@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. When run under @sc{gnu} Emacs
+mode, the @code{info line} command now causes the arrow to point to the
+line specified. Also, @code{info line} prints addresses in symbolic form as
+well as hex.
+
+@table @code
+@kindex info line
+@item info line @var{linespec}
+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
+@cindex assembly instructions
+@cindex instructions, assembly
+@cindex machine instructions
+@cindex listing machine instructions
+@item 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; @value{GDBN} dumps the function
+surrounding this value. Two arguments specify a range of addresses
+(first inclusive, second exclusive) to dump.
+@end table
+
+@ifclear H8EXCLUSIVE
+The following example shows the disassembly of a range of addresses of
+HP PA-RISC 2.0 code:
+
+@smallexample
+(@value{GDBP}) disas 0x32c4 0x32e4
+Dump of assembler code from 0x32c4 to 0x32e4:
+0x32c4 <main+204>: addil 0,dp
+0x32c8 <main+208>: ldw 0x22c(sr0,r1),r26
+0x32cc <main+212>: ldil 0x3000,r31
+0x32d0 <main+216>: ble 0x3f8(sr4,r31)
+0x32d4 <main+220>: ldo 0(r31),rp
+0x32d8 <main+224>: addil -0x800,dp
+0x32dc <main+228>: ldo 0x588(r1),r26
+0x32e0 <main+232>: ldil 0x3000,r31
+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
+
+Some architectures have more than one commonly-used set of instruction
+mnemonics or other syntax.
+
+@table @code
+@kindex set assembly-language
+@cindex assembly instructions
+@cindex instructions, assembly
+@cindex machine instructions
+@cindex listing machine instructions
+@item set assembly-language @var{instruction-set}
+Select the instruction set to use when disassembling the
+program via the @code{disassemble} or @code{x/i} commands.
+
+Currently this command is only defined for the Intel x86 family. You
+can set @var{instruction-set} to either @code{i386} or @code{i8086}.
+The default is @code{i386}.
+@end table
+
+
+@node Data, Languages, Source, Top
+@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, Variables, Data, Data
+@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.
+
+@value{GDBN} now supports array constants in expressions input by
+the user. The syntax is @var{@{element, element@dots{}@}}. For example,
+you can now use the command @code{print @{1, 2, 3@}} to build up an array in
+memory that is malloc'd in the target program.
+
+@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 in order 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 common
+to 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}.
+
+@cindex @{@var{type}@}
+@cindex type casting memory
+@cindex memory, viewing as typed object
+@cindex casts, to view memory
+@item @{@var{type}@} @var{addr}
+Refers to an object of type @var{type} stored at address @var{addr} in
+memory. @var{addr} may be any expression whose value is an integer or
+pointer (but parentheses are required around 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, Arrays, Expressions, Data
+@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 be either:
+
+@itemize @bullet
+@item
+global (or file-static)
+@end itemize
+
+@noindent or
+
+@itemize @bullet
+@item
+visible according to the scope rules of the
+programming language from the point of execution in that frame
+@end itemize
+
+@noindent 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.
+
+This may also happen when the compiler does significant optimizations.
+To be sure of always seeing accurate values, turn off all optimization
+when compiling.
+
+@node Arrays, Output Formats, Variables, Data
+@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
+and be 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.
+
+Another way to create an artificial array is to use a cast.
+This re-interprets a value as if it were an array.
+The value need not be in memory:
+@example
+(@value{GDBP}) p/x (short[2])0x12345678
+$1 = @{0x1234, 0x5678@}
+@end example
+
+As a convenience, if you leave the array length out (as in
+@samp{(@var{type})[])@var{value}}) gdb calculates the size to fill
+the value (as @samp{sizeof(@var{value})/sizeof(@var{type})}:
+@example
+(@value{GDBP}) p/x (short[])0x12345678
+$2 = @{0x1234, 0x5678@}
+@end example
+
+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, Memory, Arrays, Data
+@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
+@cindex unknown address, locating
+Print as an address, both absolute in hexadecimal and as an offset from
+the nearest preceding symbol. You can use this format 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, Auto Display, Output Formats, Data
+@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},
+@samp{s} (null-terminated string), or @samp{i} (machine instruction).
+The default is @samp{x} (hexadecimal) initially.
+The default changes each time you use 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 works. The output
+specifications @samp{4xw} and @samp{4wx} mean exactly the same thing.
+(However, the count @var{n} must come first; @samp{wx4} does 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, Print Settings, Memory, Data
+@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} prints 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
+@kindex display
+@item display @var{exp}
+Add the expression @var{exp} to the list of expressions to display
+each time your program stops. @xref{Expressions, ,Expressions}.
+
+@code{display} does 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
+@kindex delete display
+@kindex undisplay
+@item undisplay @var{dnums}@dots{}
+@itemx delete display @var{dnums}@dots{}
+Remove item numbers @var{dnums} from the list of expressions to display.
+
+@code{undisplay} does not repeat if you press @key{RET} after using it.
+(Otherwise you would just get the error @samp{No display number @dots{}}.)
+
+@kindex disable display
+@item disable display @var{dnums}@dots{}
+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.
+
+@kindex enable display
+@item enable display @var{dnums}@dots{}
+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.
+
+@kindex info display
+@item 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}, @value{GDBN} displays this argument while your program
+continues to stop inside that function. When it stops elsewhere---where
+there is no variable @code{last_char}---the display is disabled
+automatically. The next time your program stops where @code{last_char}
+is meaningful, you can enable the display expression once again.
+
+@node Print Settings, Value History, Auto Display, Data
+@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
+@kindex set print address
+@item set print address
+@itemx set print address on
+@value{GDBN} prints 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 @code{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.
+
+@kindex show print address
+@item 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 clarify. One way to do this is with
+@code{info line}, for example @samp{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
+@kindex set print symbol-filename
+@item set print symbol-filename on
+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.
+
+@kindex show print symbol-filename
+@item 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
+
+Another situation where it is helpful to show symbol filenames and line
+numbers is when disassembling code; @value{GDBN} shows you the line
+number and source file that corresponds to each instruction.
+
+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
+@kindex set print max-symbolic-offset
+@item set print max-symbolic-offset @var{max-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 tells @value{GDBN}
+to always print the symbolic form of an address if any symbol precedes it.
+
+@kindex show print max-symbolic-offset
+@item show print max-symbolic-offset
+Ask how large the maximum offset is that @value{GDBN} prints in a
+symbolic address.
+@end table
+
+@cindex wild pointer, interpreting
+@cindex pointer, finding referent
+If you have a pointer and you are not sure where it points, try
+@samp{set print symbol-filename on}. Then you can determine the name
+and source file location of the variable where it points, using
+@samp{p/a @var{pointer}}. This interprets the address in symbolic form.
+For example, here @value{GDBN} shows that a variable @code{ptt} points
+at another variable @code{t}, defined in @file{hi2.c}:
+
+@example
+(@value{GDBP}) set print symbol-filename on
+(@value{GDBP}) p/a ptt
+$4 = 0xe008 <t in hi2.c>
+@end example
+
+@quotation
+@emph{Warning:} For pointers that point to a local variable, @samp{p/a}
+does not show the symbol name and filename of the referent, even with
+the appropriate @code{set print} options turned on.
+@end quotation
+
+Other settings control how different kinds of objects are printed:
+
+@table @code
+@kindex set print array
+@item set print array
+@itemx set print array on
+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.
+
+@kindex show print array
+@item show print array
+Show whether compressed or pretty format is selected for displaying
+arrays.
+
+@kindex set print elements
+@item set print elements @var{number-of-elements}
+Set a limit on how many elements of an array @value{GDBN} will print.
+If @value{GDBN} is printing a large array, it stops 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 @var{number-of-elements} to zero means that the printing is unlimited.
+
+@kindex show print elements
+@item show print elements
+Display the number of elements of a large array that @value{GDBN} will print.
+If the number is 0, then the printing is unlimited.
+
+@kindex set print null-stop
+@item set print null-stop
+Cause @value{GDBN} to stop printing the characters of an array when the first
+@sc{NULL} is encountered. This is useful when large arrays actually
+contain only short strings.
+
+@kindex set print pretty
+@item set print pretty on
+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.
+
+@kindex show print pretty
+@item show print pretty
+Show which format @value{GDBN} is using to print structures.
+
+@kindex set print sevenbit-strings
+@item set print sevenbit-strings on
+Print using only seven-bit characters; if this option is set,
+@value{GDBN} displays any eight-bit characters (in strings or
+character values) using the notation @code{\}@var{nnn}. This setting is
+best if you are working in English (@sc{ascii}) and you use the
+high-order bit of characters as a marker or ``meta'' bit.
+
+@item set print sevenbit-strings off
+Print full eight-bit characters. This allows the use of more
+international character sets, and is the default.
+
+@kindex show print sevenbit-strings
+@item show print sevenbit-strings
+Show whether or not @value{GDBN} is printing only seven-bit characters.
+
+@kindex set print union
+@item set print union on
+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.
+
+@kindex show print union
+@item 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
+@cindex demangling
+@kindex set print demangle
+@item set print demangle
+@itemx 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 @samp{on}.
+
+@kindex show print demangle
+@item show print demangle
+Show whether C++ names are printed in mangled or demangled form.
+
+@kindex set print asm-demangle
+@item set print asm-demangle
+@itemx 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.
+
+@kindex show print asm-demangle
+@item show print asm-demangle
+Show whether C++ names in assembly listings are printed in mangled
+or demangled form.
+
+@kindex set demangle-style
+@cindex C++ symbol decoding style
+@cindex symbol decoding style, C++
+@item set demangle-style @var{style}
+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 @sc{gnu} C++ compiler (@code{g++}) encoding algorithm.
+@ifclear HPPA
+This is the default.
+@end ifclear
+
+@item hp
+Decode based on the HP ANSI C++ (@code{aCC}) 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
+If you omit @var{style}, you will see a list of possible formats.
+
+@kindex show demangle-style
+@item show demangle-style
+Display the encoding style currently in use for decoding C++ symbols.
+
+@kindex set print object
+@item set print object
+@itemx set print object on
+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.
+
+@kindex show print object
+@item show print object
+Show whether actual, or declared, object types are displayed.
+
+@kindex set print static-members
+@item set print static-members
+@itemx set print static-members on
+Print static members when displaying a C++ object. The default is on.
+
+@item set print static-members off
+Do not print static members when displaying a C++ object.
+
+@kindex show print static-members
+@item show print static-members
+Show whether C++ static members are printed, or not.
+
+@c These don't work with HP ANSI C++ yet.
+@kindex set print vtbl
+@item set print vtbl
+@itemx set print vtbl on
+Pretty print C++ virtual function tables. The default is off.
+@ifset HPPA
+(The @code{vtbl} commands do not work on programs compiled with the HP
+ANSI C++ compiler (@code{aCC}).)
+@end ifset
+
+@item set print vtbl off
+Do not pretty print C++ virtual function tables.
+
+@kindex show print vtbl
+@item show print vtbl
+Show whether C++ virtual function tables are pretty printed, or not.
+@end table
+@end ifclear
+
+@node Value History, Convenience Vars, Print Settings, Data
+@section Value history
+
+@cindex value history
+Values printed by the @code{print} command are saved in the @value{GDBN}
+@dfn{value history}. This allows you to 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, @code{show values +} 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, Registers, Value History, Data
+@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
+@kindex show convenience
+@item 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
+@end example
+
+@noindent Repeat that command by typing @key{RET}.
+
+Some convenience variables are created automatically by @value{GDBN} and given
+values likely to be useful.
+
+@table @code
+@kindex $_
+@item $_
+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{$__}.
+
+@kindex $__
+@item $__
+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.
+
+@item $_exitcode
+@kindex $_exitcode
+The variable @code{$_exitcode} is automatically set to the exit code when
+the program being debugged terminates.
+@end table
+
+@ifset HPPA
+If you refer to a function or variable name that begins with a dollar
+sign, @value{GDBN} searches for a user or system name first, before it
+searches for a convenience variable.
+@end ifset
+
+@node Registers, Floating Point Hardware, Convenience Vars, Data
+@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
+@kindex info registers
+@item info registers
+Print the names and values of all registers except floating-point
+registers (in the selected stack frame).
+
+@kindex info all-registers
+@cindex floating point registers
+@item info all-registers
+Print the names and values of all registers, including floating-point
+registers.
+
+@item info registers @var{regname} @dots{}
+Print the @dfn{relativized} value of each specified register @var{regname}.
+As discussed in detail below, register values are normally relative to
+the selected stack frame. @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 makes no difference.
+
+@ifset AMD29K
+@table @code
+@kindex set rstack_high_address
+@cindex AMD 29K register stack
+@cindex register stack, AMD29K
+@item set rstack_high_address @var{address}
+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 probably want to precede with @samp{0x} to specify in
+hexadecimal.
+
+@kindex show rstack_high_address
+@item 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, , Registers, Data
+@section Floating point hardware
+@cindex floating point
+
+Depending on the configuration, @value{GDBN} may be able to give
+you more information about the status of the floating point hardware.
+
+@table @code
+@kindex info float
+@item info float
+Display hardware-dependent information about the floating
+point unit. The exact contents and layout vary depending on the
+floating point chip. Currently, @samp{info float} is supported on
+the ARM and x86 machines.
+@end table
+@end ifclear
+
+@ifclear CONLY
+@node Languages, Symbols, Data, Top
+@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 appear as
+@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 is called the @dfn{working
+language}.
+
+@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, Show, Languages, Languages
+@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. The working language is
+used to determine how expressions you type are interpreted, how values
+are printed, etc.
+
+In addition to the working language, every source file that
+@value{GDBN} knows about has its own working language. For some object
+file formats, the compiler might indicate which language a particular
+source file is in. However, most of the time @value{GDBN} infers the
+language from the name of the file. The language of a source file
+controls whether C++ names are demangled---this way @code{backtrace} can
+show each frame appropriately for its own language. There is no way to
+set the language of a source file from within @value{GDBN}.
+
+This is most commonly a problem when you use a program, such
+as @code{cfront} or @code{f2c}, that generates C but is written in
+another language. In that case, make the
+program use @code{#line} directives in its C output; that way
+@value{GDBN} will know the correct language of the source code of the original
+program, and will display that source code, not the generated C code.
+
+@menu
+* Filenames:: Filename extensions and languages.
+* Manually:: Setting the working language manually
+* Automatically:: Having @value{GDBN} infer the source language
+@end menu
+
+@node Filenames, Manually, Setting, Setting
+@subsection List of filename extensions and languages
+
+If a source file name ends in one of the following extensions, then
+@value{GDBN} infers that its language is the one indicated.
+
+@table @file
+
+@item .c
+C source file
+
+@item .C
+@itemx .cc
+@itemx .cp
+@itemx .cpp
+@itemx .cxx
+@itemx .c++
+C++ source file
+
+@item .f
+@itemx .F
+Fortran source file
+
+@ifclear HPPA
+@item .ch
+@itemx .c186
+@itemx .c286
+CHILL source file.
+@end ifclear
+
+@ifset MOD2
+@item .mod
+Modula-2 source file
+@end ifset
+
+@item .s
+@itemx .S
+Assembler source file. This actually behaves almost like C, but
+@value{GDBN} does not skip over function prologues when stepping.
+@end table
+
+In addition, you may set the language associated with a filename
+extension. @xref{Show, , Displaying the language}.
+
+@node Manually, Automatically, Filenames, Setting
+@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}.
+
+@ifclear MOD2
+Setting the language manually prevents @value{GDBN} from updating the
+working language automatically. For example, if you used the @code{c}
+setting to debug a C++ program, names might not be demangled properly,
+overload resolution would not work, user-defined operators might not be
+interpreted correctly, and so on.
+@end ifclear
+@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, , Manually, Setting
+@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 working language. That is, 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.
+
+@ifset MOD2
+@node Show, Checks, Setting, Languages
+@section Displaying the language
+@end ifset
+@ifclear MOD2
+@node Show, Support, Setting, Languages
+@section Displaying the language
+@end ifclear
+
+The following commands 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
+Display the source language for this frame. This language becomes the
+working language if you use an identifier from this frame.
+@xref{Frame Info, ,Information about a frame}, to identify the other
+information listed here.
+
+@item info source
+Display the source language of this source file.
+@xref{Symbols, ,Examining the Symbol Table}, to identify the other
+information listed here.
+@end table
+
+In unusual circumstances, you may have source files with extensions
+not in the standard list. You can then set the extension associated
+with a language explicitly:
+
+@kindex set extension-language
+@kindex info extensions
+@table @code
+@item set extension-language @var{.ext} @var{language}
+Set source files with extension @var{.ext} to be assumed to be in
+the source language @var{language}.
+
+@item info extensions
+List all the filename extensions and the associated languages.
+@end table
+
+@ifset MOD2
+@node Checks, Support, Show, Languages
+@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} does 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, Range Checking, Checks, Checks
+@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,
+
+@smallexample
+1 + 2 @result{} 3
+@exdent but
+@error{} 1 + 2.3
+@end smallexample
+
+The second example fails because the @code{CARDINAL} 1 is not
+type-compatible with the @code{REAL} 2.3.
+
+For the 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 to 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 if you turn type checking off, there may be other reasons
+related to type that 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, , Type Checking, Checks
+@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
+
+@ifset MOD2
+@node Support, , Checks, Languages
+@section Supported languages
+@end ifset
+@ifclear MOD2
+@node Support, , Show, Languages
+@section Supported languages
+@end ifclear
+
+@ifset MOD2
+@value{GDBN} supports C, C++, Fortran, Chill, assembly, and Modula-2.
+@end ifset
+@ifclear MOD2
+@value{GDBN} supports C, C++, Fortran, Chill, and assembly.
+@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 accepts, 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, Modula-2, , Support
+@subsection C and C++
+@cindex C and C++
+@cindex expressions in C or C++
+@end ifset
+
+Since C and C++ are so closely related, many features of @value{GDBN} apply
+to both languages. Whenever this is the case, we discuss those languages
+together.
+
+@ifclear MOD2
+@c Cancel this below, under same condition, at end of this chapter!
+@raisesections
+@end ifclear
+
+@ifclear HPPA
+@cindex C++
+@kindex g++
+@cindex @sc{gnu} C++
+The C++ debugging facilities are jointly implemented by the C++
+compiler and @value{GDBN}. Therefore, to debug your C++ code
+effectively, you must compile your C++ programs with a supported
+C++ compiler, such as @sc{gnu} @code{g++}, or the HP ANSI C++
+compiler (@code{aCC}).
+
+For best results when using @sc{gnu} C++, use the stabs debugging
+format. You can select that format explicitly with the @code{g++}
+command-line options @samp{-gstabs} or @samp{-gstabs+}. See
+@ref{Debugging Options,,Options for Debugging Your Program or @sc{gnu}
+CC, gcc.info, Using @sc{gnu} CC}, for more information.
+@end ifclear
+@ifset HPPA
+@cindex C++
+@kindex g++
+@cindex @sc{gnu} C++
+You can use @value{GDBN} to debug C programs compiled with either the HP
+C compiler (@code{cc}) or the GNU C compiler (@code{gcc}), and to debug
+programs compiled with either the HP ANSI C++ compiler (@code{aCC}) or
+the @sc{gnu} C++ compiler (@code{g++}).
+
+If you compile with the @sc{gnu} C++ compiler, use the stabs debugging
+format for best results when debugging. You can select that format
+explicitly with the @code{g++} command-line options @samp{-gstabs} or
+@samp{-gstabs+}. See @ref{Debugging Options,,Options for Debugging Your
+Program or @sc{gnu} CC, gcc.info, Using @sc{gnu} CC}, for more
+information.
+@end ifset
+@end ifclear
+
+@ifset CONLY
+@node C, Symbols, Data, Top
+@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 debugging. This also permits @value{GDBN} to
+output values in a manner consistent with C conventions.
+
+@menu
+* C Operators:: C operators
+@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:: @value{GDBN} features for C++
+@end menu
+@end ifclear
+
+@ifclear CONLY
+@cindex C and C++ operators
+@node C Operators, C Constants, , C
+@subsubsection C and C++ operators
+@end ifclear
+@ifset CONLY
+@cindex C operators
+@node C Operators, C Constants, C, C
+@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
+@ifclear HPPA
+@emph{Integral types} include @code{int} with any of its storage-class
+specifiers; @code{char}; and @code{enum}.
+@end ifclear
+@ifset HPPA
+@emph{Integral types} include @code{int} with any of its storage-class
+specifiers; @code{char}; @code{enum}; and, for C++, @code{bool}.
+@end ifset
+
+@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.
+
+@ifset HPPA
+@item .*@r{, }->*
+Dereferences of pointers to members.
+@end ifset
+
+@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
+
+@ifset HPPA
+If an operator is redefined in the user code, @value{GDBN} usually
+attempts to invoke the redefined version instead of using the operator's
+predefined meaning.
+@end ifset
+
+@ifclear CONLY
+@menu
+* C Constants::
+@end menu
+
+@ifset MOD2
+@node C Constants, Cplus expressions, C Operators, C
+@subsubsection C and C++ constants
+@end ifset
+@ifclear MOD2
+@node C Constants, Cplus expressions, C Operators, Support
+@subsubsection C and C++ constants
+@end ifclear
+
+@cindex 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, Debugging C, C Operators, C
+@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} (i.e. 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
+@menu
+* Cplus expressions::
+* C Defaults::
+@ifset MOD2
+* C Checks::
+@end ifset
+
+* Debugging C::
+@end menu
+
+@ifset MOD2
+@node Cplus expressions, C Defaults, C Constants, C
+@subsubsection C++ expressions
+@end ifset
+@ifclear MOD2
+@node Cplus expressions, C Defaults, C Constants, Support
+@subsubsection C++ expressions
+@end ifclear
+
+@cindex expressions in C++
+@value{GDBN} expression handling can interpret most C++ expressions.
+
+@ifclear HPPA
+@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++
+@c FIXME!! GDB may eventually be able to debug C++ using DWARF; check
+@c periodically whether this has happened...
+@quotation
+@emph{Warning:} @value{GDBN} can only debug C++ code if you use the
+proper compiler. Typically, C++ debugging depends on the use of
+additional debugging information in the symbol table, and thus requires
+special support. In particular, if your compiler generates a.out, MIPS
+@sc{ecoff}, RS/6000 @sc{xcoff}, or @sc{elf} with stabs extensions to the
+symbol table, these facilities are all available. (With @sc{gnu} CC,
+you can use the @samp{-gstabs} option to request stabs debugging
+extensions explicitly.) Where the object code format is standard
+@sc{coff} or @sc{dwarf} in @sc{elf}, on the other hand, most of the C++
+support in @value{GDBN} does @emph{not} work.
+@end quotation
+@end ifclear
+
+@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++.
+
+@ifclear HPPA
+@cindex call overloaded functions
+@cindex type conversions in C++
+@item
+You can call overloaded functions; @value{GDBN} resolves 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} does not perform conversions requiring constructors or
+user-defined type operators.
+@end ifclear
+@ifset HPPA
+@cindex call overloaded functions
+@cindex overloaded functions
+@cindex type conversions in C++
+@item
+You can call overloaded functions; @value{GDBN} resolves the function
+call to the right definition, with some restrictions. GDB does not
+perform overload resolution involving user-defined type conversions,
+calls to constructors, or instantiations of templates that do not exist
+in the program. It also cannot handle ellipsis argument lists or
+default arguments.
+
+It does perform integral conversions and promotions, floating-point
+promotions, arithmetic conversions, pointer conversions, conversions of
+class objects to base classes, and standard conversions such as those of
+functions or arrays to pointers; it requires an exact match on the
+number of function arguments.
+
+Overload resolution is always performed, unless you have specified
+@code{set overload-resolution off}. @xref{Debugging C plus plus,
+,@value{GDBN} features for C++}.
+
+You must specify@code{set overload-resolution off} in order to use an
+explicit function signature to call an overloaded function, as in
+@smallexample
+p 'foo(char,int)'('x', 13)
+@end smallexample
+The @value{GDBN} command-completion facility can simplify this;
+@pxref{Completion, ,Command completion}.
+
+@end ifset
+
+@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
+
+@ifset HPPA
+In addition, @value{GDBN} supports calling virtual functions correctly,
+printing out virtual bases of objects, calling functions in a base
+subobject, casting objects, and invoking user-defined operators.
+@end ifset
+
+@ifset MOD2
+@node C Defaults, C Checks, Cplus expressions, C
+@subsubsection C and C++ defaults
+@end ifset
+@ifclear MOD2
+@node C Defaults, Debugging C, Cplus expressions, Support
+@subsubsection C and C++ defaults
+@end ifclear
+@cindex C and C++ defaults
+
+@ifclear HPPA
+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}
+selects the working language.
+@end ifclear
+
+If you allow @value{GDBN} to set the language automatically, it
+recognizes source files whose names end with @file{.c}, @file{.C}, or
+@file{.cc}, etc, and when @value{GDBN} enters code compiled from one of
+these files, it sets the working language to C or C++.
+@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. roland 16jul93.
+@node C Checks, Debugging C, C Defaults, C Constants
+@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}
+considers two variables type equivalent if:
+
+@itemize @bullet
+@item
+The two variables are structured and have the same structure, union, or
+enumerated tag.
+
+@item
+The 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
+@ifset MOD2
+@node Debugging C, Debugging C plus plus, C Checks, C
+@subsubsection @value{GDBN} and C
+@end ifset
+@ifclear MOD2
+@node Debugging C, Debugging C plus plus, C Defaults, Support
+@subsubsection @value{GDBN} and C
+@end ifclear
+@end ifclear
+@ifset CONLY
+@node Debugging C, , C Constants, 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
+is also printed.
+Otherwise, it appears 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
+@menu
+* Debugging C plus plus::
+@end menu
+
+@ifset MOD2
+@node Debugging C plus plus, , Debugging C, C
+@subsubsection @value{GDBN} features for C++
+@end ifset
+@ifclear MOD2
+@node Debugging C plus plus, , Debugging C, Support
+@subsubsection @value{GDBN} features for C++
+@end ifclear
+
+@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 throw
+@itemx catch catch
+Debug C++ exception handling using these commands. @xref{Set
+Catchpoints, , Setting catchpoints}.
+
+@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}.
+@ifset HPPA
+(The @code{vtbl} commands do not work on programs compiled with the HP
+ANSI C++ compiler (@code{aCC}).)
+
+@kindex set overload-resolution
+@cindex overloaded functions
+@item set overload-resolution on
+Enable overload resolution for C++ expression evaluation. The default
+is on. For overloaded functions, @value{GDBN} evaluates the arguments
+and searches for a function whose signature matches the argument types,
+using the standard C++ conversion rules (@pxref{Cplus expressions, ,C++
+expressions} for details). If it cannot find a match, it emits a
+message.
+
+@item set overload-resolution off
+Disable overload resolution for C++ expression evaluation. For
+overloaded functions that are not class member functions, @value{GDBN}
+chooses the first function of the specified name that it finds in the
+symbol table, whether or not its arguments are of the correct type. For
+overloaded functions that are class member functions, @value{GDBN}
+searches for a function whose signature @emph{exactly} matches the
+argument types.
+@end ifset
+
+@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, ,C , Support
+@subsection Modula-2
+@cindex Modula-2
+
+The extensions made to @value{GDBN} to support Modula-2 only support
+output from the @sc{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 is most likely
+to give 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, Built-In Func/Proc, Modula-2, Modula-2
+@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}
+treats 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, M2 Constants, M2 Operators, Modula-2
+@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} treats the use of procedures @code{INCL} and @code{EXCL} as
+an error.
+@end quotation
+
+@cindex Modula-2 constants
+@node M2 Constants, M2 Defaults, Built-In Func/Proc, Modula-2
+@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, Deviations, M2 Constants, Modula-2
+@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} sets the
+working language to Modula-2. @xref{Automatically, ,Having @value{GDBN} set
+the language automatically}, for further details.
+
+@node Deviations, M2 Checks, M2 Defaults, Modula-2
+@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} prints 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, M2 Scope, Deviations, Modula-2
+@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
+@sc{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, GDB/M2, M2 Checks, Modula-2
+@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} searches 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, , M2 Scope, Modula-2
+@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, Altering, Languages, Top
+@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}).
+
+@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
+@kindex info address
+@item info address @var{symbol}
+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.
+
+@kindex whatis
+@item whatis @var{exp}
+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.
+
+@kindex ptype
+@item ptype @var{typename}
+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.
+
+@kindex info types
+@item info types @var{regexp}
+@itemx 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.
+
+@kindex info source
+@item 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.
+
+@kindex info sources
+@item 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.
+
+@kindex info functions
+@item 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}.
+
+@kindex info variables
+@item 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.
+@kindex info methods
+@item info methods
+@itemx info methods @var{regexp}
+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
+
+@ifclear HPPA
+@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.
+
+@kindex show symbol-reloading
+@item show symbol-reloading
+Show the current @code{on} or @code{off} setting.
+@end table
+@end ifclear
+
+@ifset HPPA
+@kindex set opaque-type-resolution
+@item set opaque-type-resolution on
+Tell @value{GDBN} to resolve opaque types. An opaque type is a type
+declared as a pointer to a @code{struct}, @code{class}, or
+@code{union}---for example, @code{struct MyType *}---that is used in one
+source file although the full declaration of @code{struct MyType} is in
+another source file. The default is on.
+
+A change in the setting of this subcommand will not take effect until
+the next time symbols for a file are loaded.
+
+@item set opaque-type-resolution off
+Tell @value{GDBN} not to resolve opaque types. In this case, the type
+is printed as follows:
+@smallexample
+@{<no data fields>@}
+@end smallexample
+
+@kindex show opaque-type-resolution
+@item show opaque-type-resolution
+Show whether opaque types are resolved or not.
+@end ifset
+
+@kindex maint print symbols
+@cindex symbol dump
+@kindex maint print psymbols
+@cindex partial symbol dump
+@item maint print symbols @var{filename}
+@itemx maint print psymbols @var{filename}
+@itemx maint print msymbols @var{filename}
+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, GDB Files, Symbols, Top
+@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.
+
+@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, Jumping, Altering, Altering
+@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.
+
+@ifclear HPPA
+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
+@end ifclear
+@ifset HPPA
+Because the @code{set} command has many subcommands that can conflict
+with the names of program variables, it is a good idea to use the
+@code{set variable} command instead of just @code{set}. For example, if
+your program has a variable @code{g}, you run into problems if you try
+to set a new value with just @samp{set g=4}, because @value{GDBN} has
+the command @code{set gnutarget}, abbreviated @code{set g}:
+
+@example
+@group
+(@value{GDBP}) whatis g
+type = double
+(@value{GDBP}) p g
+$1 = 1
+(@value{GDBP}) set g=4
+(gdb) p g
+$2 = 1
+(@value{GDBP}) r
+The program being debugged has been started already.
+Start it from the beginning? (y or n) y
+Starting program: /home/smith/cc_progs/a.out
+"/home/smith/cc_progs/a.out": can't open to read symbols: Invalid bfd target.
+(@value{GDBP}) show g
+The current BFD target is "=4".
+@end group
+@end example
+
+@noindent
+The program variable @code{g} did not change, and you silently set the
+@code{gnutarget} to an invalid value. In order to set the variable
+@code{g}, use
+
+@example
+(@value{GDBP}) set var g=4
+@end example
+@end ifset
+
+@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 /doc@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, Signaling, Assignment, Altering
+@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
+@kindex jump
+@item jump @var{linespec}
+Resume execution at line @var{linespec}. Execution stops again
+immediately if there is a breakpoint there. @xref{List, ,Printing
+source lines}, for a description of the different forms of
+@var{linespec}. It is common practice to use the @code{tbreak} command
+in conjunction with @code{jump}. @xref{Set Breaks, ,Setting
+breakpoints}.
+
+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
+
+@ifclear HPPA
+@c Doesn't work on HP-UX; have to set $pcoqh and $pcoqt.
+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 of where it
+@emph{will} run when you continue. For example,
+
+@example
+set $pc = 0x485
+@end example
+
+@noindent
+makes the next @code{continue} command or stepping command execute at
+address @code{0x485}, rather than at the address where your program stopped.
+@xref{Continuing and Stepping, ,Continuing and stepping}.
+@end ifclear
+
+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, Returning, Jumping, Altering
+@section Giving your program a signal
+
+@table @code
+@kindex signal
+@item signal @var{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, Calling, Signaling, Altering
+@section Returning from a function
+
+@table @code
+@cindex returning from a function
+@kindex return
+@item return
+@itemx return @var{expression}
+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, Patching, Returning, Altering
+@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. If the result is not void, it
+is printed and saved in the value history.
+
+@ifclear HPPA
+For the A29K, a user-controlled variable @code{call_scratch_address},
+specifies the location of a scratch area to be used when @value{GDBN}
+calls a function in the target. This is necessary because the usual
+method of putting the scratch area on the stack does not work in systems
+that have separate instruction and data spaces.
+@end ifclear
+
+@node Patching, , Calling, Altering
+@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
+@kindex set write
+@item set write on
+@itemx set write off
+If you specify @samp{set write on}, @value{GDBN} opens executable
+@ifclear BARETARGET
+and core
+@end ifclear
+files for both reading and writing; if you specify @samp{set write
+off} (the default), @value{GDBN} opens 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
+are opened for writing as well as reading.
+@end table
+
+@node GDB Files, Targets, Altering, Top
+@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, Symbol Errors, GDB Files, GDB Files
+@section Commands to specify files
+@cindex symbol table
+
+@ifclear BARETARGET
+@cindex core dump file
+You may want to specify executable and core dump file names.
+The usual way to do this is at start-up time, using the arguments to
+@value{GDBN}'s start-up commands (@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
+@cindex executable file
+@kindex file
+@item file @var{filename}
+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.
+
+@ifclear HPPA
+On systems with memory-mapped files, an auxiliary file
+@file{@var{filename}.syms} may hold symbol table information for
+@var{filename}. If so, @value{GDBN} maps in the symbol table from
+@file{@var{filename}.syms}, starting up more quickly. See the
+descriptions of the file 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}, described below),
+for more information.
+@end ifclear
+
+@item file
+@code{file} with no argument makes @value{GDBN} discard any information it
+has on both executable file and the symbol table.
+
+@kindex exec-file
+@item exec-file @r{[} @var{filename} @r{]}
+Specify that the program to be run (but not the symbol table) is found
+in @var{filename}. @value{GDBN} searches the environment variable @code{PATH}
+if necessary to locate your program. Omitting @var{filename} means to
+discard information on the executable file.
+
+@kindex symbol-file
+@item symbol-file @r{[} @var{filename} @r{]}
+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} does not repeat if you press @key{RET} again after
+executing it once.
+
+When @value{GDBN} is configured for a particular environment, it
+understands debugging information in whatever format is the standard
+generated for that environment; you may use either a @sc{gnu} compiler, or
+other compilers that adhere to the local conventions.
+@ifclear HPPA
+Best results are usually obtained from @sc{gnu} compilers; for example,
+using @code{@value{GCC}} you can generate debugging information for
+optimized code.
+@end ifclear
+
+For most kinds of object files, with the exception of old SVR3 systems
+using COFF, 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}.)
+
+@ifclear HPPA
+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. Note that ``stabs-in-COFF''
+still does the two-stage strategy, since the debug info is actually
+in stabs format.
+
+@kindex readnow
+@cindex reading symbols immediately
+@cindex symbols, reading immediately
+@kindex mapped
+@cindex memory-mapped symbol file
+@cindex saving symbol table
+@item symbol-file @var{filename} @r{[} -readnow @r{]} @r{[} -mapped @r{]}
+@itemx file @var{filename} @r{[} -readnow @r{]} @r{[} -mapped @r{]}
+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.
+@end ifclear
+
+@ifclear BARETARGET
+@ifclear HPPA
+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 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} always attempts 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.
+@end ifclear
+
+@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.
+
+@kindex core
+@kindex core-file
+@item core-file @r{[} @var{filename} @r{]}
+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
+
+@ifclear BARETARGET
+@ifclear HPPA
+@kindex add-symbol-file
+@cindex dynamic linking
+@item add-symbol-file @var{filename} @var{address}
+@itemx add-symbol-file @var{filename} @var{address} @r{[} -readnow @r{]} @r{[} -mapped @r{]}
+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} does 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}.
+
+@kindex add-shared-symbol-file
+@item add-shared-symbol-file
+The @code{add-shared-symbol-file} command can be used only under Harris' CXUX
+operating system for the Motorola 88k. @value{GDBN} automatically looks for
+shared libraries, however if @value{GDBN} does not find yours, you can run
+@code{add-shared-symbol-file}. It takes no arguments.
+@end ifclear
+@end ifclear
+
+@ifclear HPPA
+@kindex section
+@item section
+The @code{section} command changes the base address of section SECTION of
+the exec file to ADDR. This can be used if the exec file does not contain
+section addresses, (such as in the a.out format), or when the addresses
+specified in the file itself are wrong. Each section must be changed
+separately. The ``info files'' command lists all the sections and their
+addresses.
+@end ifclear
+
+@kindex info files
+@kindex info target
+@item info files
+@itemx 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 target} 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 file
+name and remembers it that way.
+
+@ifclear BARETARGET
+@cindex shared libraries
+@ifclear HPPA
+@c added HP-UX -- Kim (HP writer)
+@value{GDBN} supports HP-UX, SunOS, SVr4, Irix 5, and IBM RS/6000 shared
+libraries.
+@end ifclear
+@ifset HPPA
+@value{GDBN} supports HP-UX shared libraries.
+@end ifset
+@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} does not understand
+references to a function in a shared library, however---unless you are
+debugging a core file).
+@ifset HPPA
+If the program loads a library explicitly, @value{GDBN} automatically
+loads the symbols at the time of the @code{shl_load} call.
+@end ifset
+@c FIXME: some @value{GDBN} release may permit some refs to undef
+@c FIXME...symbols---eg in a break cmd---assuming they are from a shared
+@c FIXME...lib; check this from time to time when updating manual
+
+@table @code
+@kindex info sharedlibrary
+@kindex info share
+@item info share
+@itemx info sharedlibrary
+Print the names of the shared libraries which are currently loaded.
+
+@kindex sharedlibrary
+@kindex share
+@item sharedlibrary @var{regex}
+@itemx share @var{regex}
+
+Load shared object library symbols for files matching a
+Unix regular expression.
+As with files loaded automatically, it only loads 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
+
+@ifset HPPA
+@value{GDBN} detects the loading of a shared library and automatically
+reads in symbols from the newly loaded library, up to a threshold that
+is initially set but that you can modify if you wish.
+
+Beyond that threshold, symbols from shared libraries must be explicitly
+loaded. To load these symbols, use the command @code{sharedlibrary}
+@var{filename}. The base address of the shared library is determined
+automatically by @value{GDBN} and need not be specified.
+
+To display or set the threshold, use the commands:
+
+@table @code
+@kindex set auto-solib-add
+@item set auto-solib-add @var{threshold}
+Set the autoloading size threshold, in megabytes. If @var{threshold} is
+nonzero, symbols from all shared object libraries will be loaded
+automatically when the inferior begins execution or when the dynamic
+linker informs @value{GDBN} that a new library has been loaded, until
+the symbol table of the program and libraries exceeds this threshold.
+Otherwise, symbols must be loaded manually, using the
+@code{sharedlibrary} command. The default threshold is 100 megabytes.
+
+@kindex show auto-solib-add
+@item show auto-solib-add
+Display the current autoloading size threshold, in megabytes.
+@end table
+@end ifset
+
+@end ifclear
+
+@node Symbol Errors, , Files, GDB Files
+@section Errors reading symbol files
+
+While reading a symbol file, @value{GDBN} occasionally encounters 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 has 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
+usually allows you to debug your program, though certain symbols
+are not 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, Controlling GDB, GDB Files, Top
+@chapter Specifying a Debugging Target
+@cindex debugging target
+@kindex target
+
+A @dfn{target} is the execution environment occupied by your program.
+@ifclear HPPA
+@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
+@end ifclear
+@ifset HPPA
+On HP-UX systems, @value{GDBN} has been configured to support debugging
+of processes running on the PA-RISC architecture. This means that the
+only possible targets are:
+
+@itemize @bullet
+@item
+An executable that has been compiled and linked to run on HP-UX
+
+@item
+A live HP-UX process, either started by @value{GDBN} (with the
+@code{run} command) or started outside of @value{GDBN} and attached to
+(with the @code{attach} command)
+
+@item
+A core file generated by an HP-UX process that previously aborted
+execution
+@end itemize
+
+@value{GDBN} on HP-UX has not been configured to support remote
+debugging, or to support programs running on other platforms. You
+@end ifset
+@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
+@ifset REMOTESTUB
+* Byte Order:: Choosing target byte order
+* Remote:: Remote debugging
+@end ifset
+
+@end menu
+
+@node Active Targets, Target Commands, Targets, 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 uses 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, Byte Order, Active Targets, Targets
+@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 does not repeat if you press @key{RET} again
+after executing the command.
+
+@kindex help target
+@item 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.
+
+@kindex set gnutarget
+@item set gnutarget @var{args}
+@value{GDBN} uses its own library BFD to read your files. @value{GDBN}
+knows whether it is reading an @dfn{executable},
+a @dfn{core}, or a @dfn{.o} file; however, you can specify the file format
+with the @code{set gnutarget} command. Unlike most @code{target} commands,
+with @code{gnutarget} the @code{target} refers to a program, not a machine.
+
+@emph{Warning:} To specify a file format with @code{set gnutarget},
+you must know the actual BFD name.
+
+@noindent @xref{Files, , Commands to specify files}.
+
+@kindex show gnutarget
+@item show gnutarget
+Use the @code{show gnutarget} command to display what file format
+@code{gnutarget} is set to read. If you have not set @code{gnutarget},
+@value{GDBN} will determine the file format for each file automatically,
+and @code{show gnutarget} displays @samp{The current BDF target is "auto"}.
+@end table
+
+@ifclear HPPA
+Here are some common targets (available, or not, depending on the GDB
+configuration):
+@end ifclear
+@ifset HPPA
+These are the valid targets on HP-UX systems:
+@end ifset
+
+@table @code
+@kindex target exec
+@item target exec @var{program}
+An executable file. @samp{target exec @var{program}} is the same as
+@samp{exec-file @var{program}}.
+
+@ifclear BARETARGET
+@kindex target core
+@item target core @var{filename}
+A core dump file. @samp{target core @var{filename}} is the same as
+@samp{core-file @var{filename}}.
+@end ifclear
+
+@kindex target remote
+@item target remote @var{dev}
+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}. @code{target remote}
+now supports the @code{load} command. This is only useful if you have
+some other way of getting the stub to the target system, and you can put
+it somewhere in memory where it won't get clobbered by the download.
+
+@ifclear HPPA
+@kindex target sim
+@item target sim
+CPU simulator. @xref{Simulator,,Simulated CPU Target}.
+@end ifclear
+@end table
+
+The following targets are all CPU-specific, and only available for
+specific configurations.
+@c should organize by CPU
+
+@table @code
+
+@kindex target abug
+@item target abug @var{dev}
+ABug ROM monitor for M68K.
+
+@kindex target adapt
+@item target adapt @var{dev}
+Adapt monitor for A29K.
+
+@kindex target amd-eb
+@item target amd-eb @var{dev} @var{speed} @var{PROG}
+@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, ,The EBMON protocol for AMD29K}.
+
+@kindex target array
+@item target array @var{dev}
+Array Tech LSI33K RAID controller board.
+
+@kindex target bug
+@item target bug @var{dev}
+BUG monitor, running on a MVME187 (m88k) board.
+
+@kindex target cpu32bug
+@item target cpu32bug @var{dev}
+CPU32BUG monitor, running on a CPU32 (M68K) board.
+
+@kindex target dbug
+@item target dbug @var{dev}
+dBUG ROM monitor for Motorola ColdFire.
+
+@kindex target ddb
+@item target ddb @var{dev}
+NEC's DDB monitor for Mips Vr4300.
+
+@kindex target dink32
+@item target dink32 @var{dev}
+DINK32 ROM monitor for PowerPC.
+
+@kindex target e7000
+@item target e7000 @var{dev}
+E7000 emulator for Hitachi H8 and SH.
+
+@kindex target es1800
+@item target es1800 @var{dev}
+ES-1800 emulator for M68K.
+
+@kindex target est
+@item target est @var{dev}
+EST-300 ICE monitor, running on a CPU32 (M68K) board.
+
+@kindex target hms
+@item target hms @var{dev}
+A Hitachi SH, H8/300, or H8/500 board, attached via serial line to your host.
+@ifclear H8EXCLUSIVE
+Use special commands @code{device} and @code{speed} to control the serial
+line and the communications speed used.
+@xref{Hitachi Remote,,@value{GDBN} and Hitachi Microprocessors}.
+
+@kindex target lsi
+@item target lsi @var{dev}
+LSI ROM monitor for Mips.
+
+@kindex target m32r
+@item target m32r @var{dev}
+Mitsubishi M32R/D ROM monitor.
+
+@kindex target mips
+@item target mips @var{dev}
+IDT/SIM ROM monitor for Mips.
+
+@kindex target mon960
+@item target mon960 @var{dev}
+MON960 monitor for Intel i960.
+
+@kindex target nindy
+@item target nindy @var{devicename}
+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)}.
+
+@kindex target nrom
+@item target nrom @var{dev}
+NetROM ROM emulator. This target only supports downloading.
+
+@kindex target op50n
+@item target op50n @var{dev}
+OP50N monitor, running on an OKI HPPA board.
+
+@kindex target pmon
+@item target pmon @var{dev}
+PMON ROM monitor for Mips.
+
+@kindex target ppcbug
+@item target ppcbug @var{dev}
+@kindex target ppcbug1
+@item target ppcbug1 @var{dev}
+PPCBUG ROM monitor for PowerPC.
+
+@kindex target r3900
+@item target r3900 @var{dev}
+Densan DVE-R3900 ROM monitor for Toshiba R3900 Mips.
+
+@kindex target rdi
+@item target rdi @var{dev}
+ARM Angel monitor, via RDI library interface.
+
+@kindex target rdp
+@item target rdp @var{dev}
+ARM Demon monitor.
+
+@kindex target rom68k
+@item target rom68k @var{dev}
+ROM 68K monitor, running on an M68K IDP board.
+
+@kindex target rombug
+@item target rombug @var{dev}
+ROMBUG ROM monitor for OS/9000.
+
+@kindex target sds
+@item target sds @var{dev}
+SDS monitor, running on a PowerPC board (such as Motorola's ADS).
+
+@kindex target sparclite
+@item target sparclite @var{dev}
+Fujitsu sparclite boards, used only for the purpose of loading.
+You must use an additional command to debug the program.
+For example: target remote @var{dev} using @value{GDBN} standard
+remote protocol.
+
+@kindex target sh3
+@kindex target sh3e
+@item target sh3 @var{dev}
+@item target sh3e @var{dev}
+Hitachi SH-3 and SH-3E target systems.
+
+@kindex target st2000
+@item target st2000 @var{dev} @var{speed}
+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}.
+
+@kindex target udi
+@item target udi @var{keyword}
+Remote AMD29K target, using the AMD UDI protocol. The @var{keyword}
+argument specifies which 29K board or simulator to use. @xref{UDI29K
+Remote,,The UDI protocol for AMD29K}.
+
+@kindex target vxworks
+@item target vxworks @var{machinename}
+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}.
+
+@kindex target w89k
+@item target w89k @var{dev}
+W89K monitor, running on a Winbond HPPA board.
+
+@end ifclear
+@end table
+
+@ifset GENERIC
+Different targets are available on different configurations of @value{GDBN};
+your configuration may have more or fewer targets.
+@end ifset
+
+Many remote targets require you to download the executable's code
+once you've successfully established a connection.
+
+@table @code
+
+@kindex load @var{filename}
+@item load @var{filename}
+@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, you can specify the load address when you
+link the program; for other formats, like a.out, the object file format
+specifies a fixed address.
+@c FIXME! This would be a good place for an xref to the GNU linker doc.
+
+@ifset VXWORKS
+On VxWorks, @code{load} links @var{filename} dynamically 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}
+downloads @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} does not repeat if you press @key{RET} again after using it.
+@end table
+
+@ifset REMOTESTUB
+@node Byte Order, Remote, Target Commands, Targets
+@section Choosing target byte order
+@cindex choosing target byte order
+@cindex target byte order
+@kindex set endian big
+@kindex set endian little
+@kindex set endian auto
+@kindex show endian
+
+Some types of processors, such as the MIPS, PowerPC, and Hitachi SH,
+offer the ability to run either big-endian or little-endian byte
+orders. Usually the executable or symbol will include a bit to
+designate the endian-ness, and you will not need to worry about
+which to use. However, you may still find it useful to adjust
+GDB's idea of processor endian-ness manually.
+
+@table @code
+@kindex set endian big
+@item set endian big
+Instruct @value{GDBN} to assume the target is big-endian.
+
+@kindex set endian little
+@item set endian little
+Instruct @value{GDBN} to assume the target is little-endian.
+
+@kindex set endian auto
+@item set endian auto
+Instruct @value{GDBN} to use the byte order associated with the
+executable.
+
+@item show endian
+Display @value{GDBN}'s current idea of the target byte order.
+
+@end table
+
+Note that these commands merely adjust interpretation of symbolic
+data on the host, and that they have absolutely no effect on the
+target system.
+
+@node Remote, , Byte Order, Targets
+@section Remote debugging
+@cindex remote debugging
+
+If you are trying to debug a program running on a machine that cannot run
+@value{GDBN} 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 @value{GDBN} have special serial or TCP/IP interfaces
+to make this work with particular debugging targets. In addition,
+@value{GDBN} comes with a generic serial protocol (specific to @value{GDBN},
+but not specific to any particular target system) which you can use if you
+write the remote stubs---the code that runs on the remote system to
+communicate with @value{GDBN}.
+
+Other remote targets may be available in your
+configuration of @value{GDBN}; use @code{help target} to list them.
+@end ifset
+
+@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:: The UDI protocol for AMD29K
+* EB29K Remote:: The EBMON protocol for AMD29K
+@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 SPARCLET
+* Sparclet Remote:: @value{GDBN} and Sparclet 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, Editing, Controlling GDB, Controlling GDB
+@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.
+
+@emph{Note:} @code{set prompt} no longer adds a space for you after the
+prompt you set. This allows you to set a prompt which ends in a space
+or a prompt that does not.
+
+@table @code
+@kindex set prompt
+@item set prompt @var{newprompt}
+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, History, Prompt, Controlling GDB
+@section Command editing
+@cindex readline
+@cindex command line editing
+
+@value{GDBN} reads its input commands via the @dfn{readline} interface. This
+@sc{gnu} library provides consistent behavior for programs which provide a
+command line interface to the user. Advantages are @sc{gnu} Emacs-style
+or @dfn{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, Screen Size, Editing, Controlling GDB
+@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
+@kindex GDBHISTFILE
+@item set history filename @var{fname}
+Set the name of the @value{GDBN} command history file to @var{fname}.
+This is the file where @value{GDBN} reads an initial command history
+list, and where it writes the command history from this session when it
+exits. You can access this list 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} keeps 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 do 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 @sc{gnu} 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, Numbers, History, Controlling GDB
+@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
+@kindex set height
+@kindex set width
+@kindex show width
+@kindex show height
+@item set height @var{lpp}
+@itemx show height
+@itemx set width @var{cpl}
+@itemx show width
+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} does 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, Messages/Warnings, Screen Size, Controlling GDB
+@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 input-radix
+@item set input-radix @var{base}
+Set the default base for numeric input. 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
+
+@smallexample
+set radix 012
+set radix 10.
+set radix 0xa
+@end smallexample
+
+@noindent
+sets the base to decimal. On the other hand, @samp{set radix 10}
+leaves the radix unchanged no matter what it was.
+
+@kindex set output-radix
+@item set output-radix @var{base}
+Set the default base for numeric 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.
+
+@kindex show input-radix
+@item show input-radix
+Display the current default base for numeric input.
+
+@kindex show output-radix
+@item show output-radix
+Display the current default base for numeric display.
+@end table
+
+@node Messages/Warnings, , Numbers, Controlling GDB
+@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.
+This makes @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).
+
+@kindex show confirm
+@item show confirm
+Displays state of confirmation requests.
+@end table
+
+@node Sequences, Emacs, Controlling GDB, Top
+@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, Hooks, Sequences, Sequences
+@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. User commands may accept up to 10 arguments separated by whitespace.
+Arguments are accessed within the user command via @var{$arg0@dots{}$arg9}.
+A trivial example:
+
+@smallexample
+define adder
+ print $arg0 + $arg1 + $arg2
+@end smallexample
+
+@noindent To execute the command use:
+
+@smallexample
+adder 1 2 3
+@end smallexample
+
+@noindent This defines the command @code{adder}, which prints the sum of
+its three arguments. Note the arguments are text substitutions, so they may
+reference variables, use complex expressions, or even perform inferior
+functions calls.
+
+@table @code
+@kindex define
+@item define @var{commandname}
+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}.
+
+@kindex if
+@kindex else
+@item if
+Takes a single argument, which is an expression to evaluate.
+It is followed by a series of commands that are executed
+only if the expression is true (nonzero).
+There can then optionally be a line @code{else}, followed
+by a series of commands that are only executed if the expression
+was false. The end of the list is marked by a line containing @code{end}.
+
+@kindex while
+@item while
+The syntax is similar to @code{if}: the command takes a single argument,
+which is an expression to evaluate, and must be followed by the commands to
+execute, one per line, terminated by an @code{end}.
+The commands are executed repeatedly as long as the expression
+evaluates to true.
+
+@kindex document
+@item document @var{commandname}
+Document the user-defined command @var{commandname}, so that it can be
+accessed by @code{help}. 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} displays the documentation you have written.
+
+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.
+
+@kindex help user-defined
+@item help user-defined
+List all user-defined commands, with the first line of the documentation
+(if any) for each.
+
+@kindex show user
+@item show user
+@itemx show user @var{commandname}
+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
+
+When user-defined commands are executed, the
+commands of the definition are not printed. An error in any command
+stops execution of the user-defined command.
+
+If used interactively, commands that would ask for confirmation 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, Command Files, Define, Sequences
+@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
+get a warning from the @code{define} command.
+
+@node Command Files, Output, Hooks, Sequences
+@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{.gdbinit}
+When you start @value{GDBN}, it automatically executes commands from its
+@dfn{init files}. These are files named @file{.gdbinit} on Unix, or
+@file{gdb.ini} on DOS/Windows. @value{GDBN} reads the init file (if
+any) in your home directory, then processes command line options and
+operands, and then reads the init file (if any) in the current working
+directory. This is so the init file in your home directory can set
+options (such as @code{set complaints}) which affect the processing of
+the command line options and operands. 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 @value{GDBN} 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:
+
+@kindex .vxgdbinit
+@itemize @bullet
+@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
+@kindex source
+@item source @var{filename}
+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, , Command Files, Sequences
+@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
+@kindex echo
+@item echo @var{text}
+@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 is 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
+
+@kindex output
+@item output @var{expression}
+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.
+
+@kindex printf
+@item printf @var{string}, @var{expressions}@dots{}
+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, GDB Bugs, Sequences, Top
+@chapter Using @value{GDBN} under @sc{gnu} Emacs
+
+@cindex Emacs
+@cindex @sc{gnu} Emacs
+A special interface allows you to use @sc{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.
+@ifset HPPA
+(Do not use the @code{-tui} option to run @value{GDBN} from Emacs.)
+@end ifset
+
+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 have no reason to use them from Emacs.
+
+@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 does 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 proceeds 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 an absolute file 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) makes 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 @sc{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 &} indicates that you
+wish special formatting, and also acts 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 recreates
+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 cease
+to correspond properly with the code.
+
+@c The following dropped because Epoch is nonstandard. Reactivate
+@c if/when v19 does something similar. ---doc@cygnus.com 19dec1990
+@ignore
+@kindex Emacs Epoch environment
+@kindex Epoch
+@kindex inspect
+
+Version 18 of @sc{gnu} 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
+
+@node GDB Bugs
+@c links whacked to pacify makeinfo
+@c , Command Line Editing, Emacs, Top
+@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, Bug Reporting, GDB Bugs, GDB Bugs
+@section Have you found a bug?
+@cindex bug criteria
+
+If you are not sure whether you have found a bug, here are some guidelines:
+
+@itemize @bullet
+@cindex fatal signal
+@cindex debugger crash
+@cindex crash of debugger
+@item
+If the debugger gets a fatal signal, for any input whatever, that is a
+@value{GDBN} bug. Reliable debuggers never crash.
+
+@cindex error on valid input
+@item
+If @value{GDBN} produces an error message for valid input, that is a
+bug. (Note that if you're cross debugging, the problem may also be
+somewhere in the connection to the target.)
+
+@cindex invalid input
+@item
+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, , Bug Criteria, GDB Bugs
+@section How to report bugs
+@cindex bug reports
+@cindex @value{GDBN} bugs, reporting
+
+@ifclear HPPA
+A number of companies and individuals offer support for @sc{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 @sc{gnu} Emacs
+distribution.
+@c should add a web page ref...
+
+In any event, we also recommend that you send bug reports for
+@value{GDBN} to this addresses:
+
+@example
+bug-gdb@@prep.ai.mit.edu
+@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
+@sc{gnu} Debugger Bugs
+Free Software Foundation Inc.
+59 Temple Place - Suite 330
+Boston, MA 02111-1307
+USA
+@end example
+@end ifclear
+
+@ifset HPPA
+If you obtained HP GDB as part of your HP ANSI C or HP ANSI C++ compiler
+kit, report problems to your HP Support Representative.
+
+If you obtained HP GDB from the Hewlett-Packard Web site, report
+problems by electronic mail to @code{wdb-www@@ch.hp.com}.
+@end ifset
+
+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. It may be that the bug has been reported previously, but neither
+you nor we can know that unless your bug report is complete and
+self-contained.
+
+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.
+
+@ifclear HPPA
+@item
+What compiler (and its version) was used to compile @value{GDBN}---e.g.
+``@value{GCC}--2.8.1''.
+@end ifclear
+
+@item
+What compiler (and its version) was used to compile the program you are
+debugging---e.g. ``@value{GCC}--2.8.1'', or ``HP92453-01 A.10.32.03 HP
+C Compiler''. For GCC, you can say @code{gcc --version} to get this
+information; for other compilers, see the documentation for those
+compilers.
+
+@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. 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.
+
+@ifclear HPPA
+@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 ifclear
+@end itemize
+
+Here are some things that are not necessary:
+
+@itemize @bullet
+@item
+A description of the envelope of the bug.
+
+Often people who encounter a bug spend a lot of time investigating
+which changes to the input file will make the bug go away and which
+changes will not affect it.
+
+This is often time consuming and not very useful, because the way we
+will find the bug is by running a single example under the debugger
+with breakpoints, not by pure deduction from a series of examples.
+We recommend that you save your time for something else.
+
+Of course, if you can find a simpler example to report @emph{instead}
+of the original one, that is a convenience for us. Errors in the
+output will be easier to spot, running under the debugger will take
+less time, and so on.
+
+However, simplification is not vital; if you do not want to do this,
+report the bug anyway and send us the entire test case you used.
+
+@item
+A patch for the bug.
+
+A patch for the bug does help us if it is a good one. But do not omit
+the necessary information, such as the test case, on the assumption that
+a patch is all we need. We might see problems with your patch and decide
+to fix the problem another way, or we might not understand it at all.
+
+Sometimes with 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
+
+
+@ifclear PRECONFIGURED
+@ifclear HPPA
+@node Formatting Documentation
+@c links whacked to pacify makeinfo
+@c , Installing GDB, Renamed Commands, Top
+@appendix Formatting Documentation
+
+@cindex @value{GDBN} reference card
+@cindex reference card
+The @value{GDBN} 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 @value{GDBN} reference card is designed to print in @dfn{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 @value{GDBN} 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.
+
+@value{GDBN} 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-@value{GDBVN}/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 @sc{gnu}
+Emacs or the standalone @code{info} program, available as part of the
+@sc{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
+@value{GDBN} 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 either read or
+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 type:
+
+@example
+make gdb.dvi
+@end example
+
+Then give @file{gdb.dvi} to your @sc{dvi} printing program.
+@end ifclear
+
+@node Installing GDB, Index, Using History Interactively, Top
+@appendix Installing @value{GDBN}
+@cindex configuring @value{GDBN}
+@cindex installation
+
+@ifset HPPA
+If you obtain @value{GDBN} (HP WDB 0.75) as part of your HP ANSI C or
+HP ANSI C++ Developer's Kit at HP-UX Release 11.0, you do not have to
+take any special action to build or install @value{GDBN}.
+
+If you obtain @value{GDBN} (HP WDB 0.75) from an HP web site, you may
+download either a @code{swinstall}-able package or a source tree, or
+both.
+
+Most customers will want to install the @value{GDBN} binary that is part
+of the @code{swinstall}-able package. To do so, use a command of the
+form
+
+@smallexample
+/usr/sbin/swinstall -s @var{package-name} WDB
+@end smallexample
+
+Alternatively, it is possible to build @value{GDBN} from the source
+distribution. Sophisticated customers who want to modify the debugger
+sources to tailor @value{GDBN} to their their needs may wish to do this.
+The source distribution consists of a @code{tar}'ed source tree rooted
+at @file{gdb-4.16/...}. The instructions that follow describe how to
+build a @file{gdb} executable from this source tree. HP believes that
+these instructions apply to the WDB source tree that it distributes.
+However, HP does not explicitly support building a @file{gdb} for any
+non-HP platform from the WDB source tree. It may work, but HP has not
+tested it for any platforms other than those described in the WDB 0.75
+Release Notes.
+@end ifset
+
+@value{GDBN} comes with a @code{configure} script that automates the process
+of preparing @value{GDBN} 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 @value{GDBN} 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 @value{GDBN} distribution includes all the source code you need for
+@value{GDBN} in a single directory, whose name is usually composed by
+appending the version number to @samp{gdb}.
+
+For example, the @value{GDBN} 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 @value{GDBN} and all its supporting libraries
+
+@item gdb-@value{GDBVN}/gdb
+the source specific to @value{GDBN} itself
+
+@item gdb-@value{GDBVN}/bfd
+source for the Binary File Descriptor library
+
+@item gdb-@value{GDBVN}/include
+@sc{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 @sc{gnu} command-line interface
+
+@item gdb-@value{GDBVN}/glob
+source for the @sc{gnu} filename pattern-matching subroutine
+
+@item gdb-@value{GDBVN}/mmalloc
+source for the @sc{gnu} memory-mapped malloc package
+@end table
+
+The simplest way to configure and build @value{GDBN} 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 @value{GDBN} 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 @value{GDBN} 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.
+
+@need 750
+@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 @value{GDBN} 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 @value{GDBN} uses the shell to start your program---some systems refuse to
+let @value{GDBN} debug child processes whose programs are not readable.
+
+@menu
+* Separate Objdir:: Compiling @value{GDBN} in another directory
+* Config Names:: Specifying names for hosts and targets
+* Configure Options:: Summary of options for configure
+@end menu
+
+@node Separate Objdir, Config Names, Installing GDB, Installing GDB
+@section Compiling @value{GDBN} in another directory
+
+If you want to run @value{GDBN} 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 (@sc{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 is assumed.)
+
+For example, with version @value{GDBVN}, you can build @value{GDBN} 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 @value{GDBN} itself in
+@file{gdb-sun4/gdb}.
+
+One popular reason to build several @value{GDBN} configurations in separate
+directories is to configure @value{GDBN} for cross-compiling (where
+@value{GDBN} runs on one machine---the @dfn{host}---while debugging
+programs that run on another machine---the @dfn{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{dirname}/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, Configure Options, Separate Objdir, Installing GDB
+@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 @value{GDBN} 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 i386-linux
+i386-pc-linux-gnu
+% sh config.sub alpha-linux
+alpha-unknown-linux-gnu
+% sh config.sub hp9k700
+hppa1.1-hp-hpux
+% sh config.sub sun4
+sparc-sun-sunos4.1.1
+% sh config.sub sun3
+m68k-sun-sunos4.1.1
+% sh config.sub i986v
+Invalid configuration `i986v': machine `i986v' not recognized
+@end smallexample
+
+@noindent
+@code{config.sub} is also distributed in the @value{GDBN} source
+directory (@file{gdb-@value{GDBVN}}, for version @value{GDBVN}).
+
+@node Configure Options, , Config Names, Installing GDB
+@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}.
+
+@example
+configure @r{[}--help@r{]}
+ @r{[}--prefix=@var{dir}@r{]}
+ @r{[}--exec-prefix=@var{dir}@r{]}
+ @r{[}--srcdir=@var{dirname}@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 --exec-prefix=@var{dir}
+Configure the source to install programs under directory
+@file{@var{dir}}.
+
+@c avoid splitting the warning from the explanation:
+@need 2000
+@item --srcdir=@var{dirname}
+@strong{Warning: using this option requires @sc{gnu} @code{make}, or another
+@code{make} that implements the @code{VPATH} feature.}@*
+Use this option to make configurations in directories separate from the
+@value{GDBN} 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{dirname}. @code{configure} creates directories under
+the working directory in parallel to the source directories below
+@var{dirname}.
+
+@item --norecursion
+Configure only the directory level where @code{configure} is executed; do not
+propagate configuration to subdirectories.
+
+@item --target=@var{target}
+Configure @value{GDBN} for cross-debugging programs running on the specified
+@var{target}. Without this option, @value{GDBN} is configured to debug
+programs that run on the same machine (@var{host}) as @value{GDBN} itself.
+
+There is no convenient way to generate a list of all available targets.
+
+@item @var{host} @dots{}
+Configure @value{GDBN} to run on the specified @var{host}.
+
+There is no convenient way to generate a list of all available hosts.
+@end table
+
+There are many other options available as well, but they are generally
+needed for special purposes only.
+@end ifclear
+
+
+@node Index, , Installing GDB, Top
+@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: doc@cygnus.com, 1991.
+@end tex
+
+@contents
+@bye
diff --git a/gdb/doc/gdbint.texinfo b/gdb/doc/gdbint.texinfo
new file mode 100644
index 00000000000..99f081dcda4
--- /dev/null
+++ b/gdb/doc/gdbint.texinfo
@@ -0,0 +1,2711 @@
+\input texinfo
+@setfilename gdbint.info
+
+@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-1999 Free Software Foundation, Inc.
+Contributed by Cygnus Solutions. Written by John Gilmore.
+Second Edition by Stan Shebs.
+
+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{GDB Internals}
+@subtitle{A guide to the internals of the GNU debugger}
+@author John Gilmore
+@author Cygnus Solutions
+@author Second Edition:
+@author Stan Shebs
+@author Cygnus Solutions
+@page
+@tex
+\def\$#1${{#1}} % Kluge: collect RCS revision info without $...$
+\xdef\manvers{\$Revision$} % For use in headers, footers too
+{\parskip=0pt
+\hfill Cygnus Solutions\par
+\hfill \manvers\par
+\hfill \TeX{}info \texinfoversion\par
+}
+@end tex
+
+@vskip 0pt plus 1filll
+Copyright @copyright{} 1990-1999 Free Software Foundation, Inc.
+
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+
+@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
+includes description of GDB's key algorithms and operations, as well
+as the mechanisms that adapt GDB to specific hosts and targets.
+
+@menu
+* Requirements::
+* Overall Structure::
+* Algorithms::
+* User Interface::
+* Symbol Handling::
+* Language Support::
+* Host Definition::
+* Target Architecture Definition::
+* Target Vector Definition::
+* Native Debugging::
+* Support Libraries::
+* Coding::
+* Porting GDB::
+* Hints::
+@end menu
+
+@node Requirements
+
+@chapter Requirements
+
+Before diving into the internals, you should understand the formal
+requirements and other expectations for GDB. Although some of these may
+seem obvious, there have been proposals for GDB that have run counter to
+these requirements.
+
+First of all, GDB is a debugger. It's not designed to be a front panel
+for embedded systems. It's not a text editor. It's not a shell. It's
+not a programming environment.
+
+GDB is an interactive tool. Although a batch mode is available, GDB's
+primary role is to interact with a human programmer.
+
+GDB should be responsive to the user. A programmer hot on the trail of
+a nasty bug, and operating under a looming deadline, is going to be very
+impatient of everything, including the response time to debugger
+commands.
+
+GDB should be relatively permissive, such as for expressions. While the
+compiler should be picky (or have the option to be made picky), since
+source code lives for a long time usually, the programmer doing
+debugging shouldn't be spending time figuring out to mollify the
+debugger.
+
+GDB will be called upon to deal with really large programs. Executable
+sizes of 50 to 100 megabytes occur regularly, and we've heard reports of
+programs approaching 1 gigabyte in size.
+
+GDB should be able to run everywhere. No other debugger is available
+for even half as many configurations as GDB supports.
+
+
+@node Overall Structure
+
+@chapter Overall Structure
+
+GDB consists of three major subsystems: user interface, symbol handling
+(the ``symbol side''), and target system handling (the ``target side'').
+
+Ther user interface consists of several actual interfaces, plus
+supporting code.
+
+The symbol side consists of object file readers, debugging info
+interpreters, symbol table management, source language expression
+parsing, type and value printing.
+
+The target side consists of execution control, stack frame analysis, and
+physical target manipulation.
+
+The target side/symbol side division is not formal, and there are a
+number of exceptions. For instance, core file support involves symbolic
+elements (the basic core file reader is in BFD) and target elements (it
+supplies the contents of memory and the values of registers). Instead,
+this division is useful for understanding how the minor subsystems
+should fit together.
+
+@section The Symbol Side
+
+The symbolic side of GDB can be thought of as ``everything you can do in
+GDB without having a live program running''. For instance, you can look
+at the types of variables, and evaluate many kinds of expressions.
+
+@section The Target Side
+
+The target side of GDB is the ``bits and bytes manipulator''. Although
+it may make reference to symbolic info here and there, most of the
+target side will run with only a stripped executable available -- or
+even no executable at all, in remote debugging cases.
+
+Operations such as disassembly, stack frame crawls, and register
+display, are able to work with no symbolic info at all. In some cases,
+such as disassembly, GDB will use symbolic info to present addresses
+relative to symbols rather than as raw numbers, but it will work either
+way.
+
+@section Configurations
+
+@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.
+
+
+@node Algorithms
+
+@chapter Algorithms
+
+GDB uses a number of debugging-specific algorithms. They are often not
+very complicated, but get lost in the thicket of special cases and
+real-world issues. This chapter describes the basic algorithms and
+mentions some of the specific target definitions that they use.
+
+@section Frames
+
+A frame is a construct that GDB uses to keep track of calling and called
+functions.
+
+@code{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.)
+
+Given a GDB frame, define @code{FRAME_CHAIN} to 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.
+
+@section Breakpoint Handling
+
+In general, a breakpoint is a user-designated location in the program
+where the user wants to regain control if program execution ever reaches
+that location.
+
+There are two main ways to implement breakpoints; either as ``hardware''
+breakpoints or as ``software'' breakpoints.
+
+Hardware breakpoints are sometimes available as a builtin debugging
+features with some chips. Typically these work by having dedicated
+register into which the breakpoint address may be stored. If the PC
+ever matches a value in a breakpoint registers, the CPU raises an
+exception and reports it to GDB. Another possibility is when an
+emulator is in use; many emulators include circuitry that watches the
+address lines coming out from the processor, and force it to stop if the
+address matches a breakpoint's address. A third possibility is that the
+target already has the ability to do breakpoints somehow; for instance,
+a ROM monitor may do its own software breakpoints. So although these
+are not literally ``hardware breakpoints'', from GDB's point of view
+they work the same; GDB need not do nothing more than set the breakpoint
+and wait for something to happen.
+
+Since they depend on hardware resources, hardware breakpoints may be
+limited in number; when the user asks for more, GDB will start trying to
+set software breakpoints.
+
+Software breakpoints require GDB to do somewhat more work. The basic
+theory is that GDB will replace a program instruction a trap, illegal
+divide, or some other instruction that will cause an exception, and then
+when it's encountered, GDB will take the exception and stop the program.
+When the user says to continue, GDB will restore the original
+instruction, single-step, re-insert the trap, and continue on.
+
+Since it literally overwrites the program being tested, the program area
+must be writeable, so this technique won't work on programs in ROM. It
+can also distort the behavior of programs that examine themselves,
+although the situation would be highly unusual.
+
+Also, the software breakpoint instruction should be the smallest size of
+instruction, so it doesn't overwrite an instruction that might be a jump
+target, and cause disaster when the program jumps into the middle of the
+breakpoint instruction. (Strictly speaking, the breakpoint must be no
+larger than the smallest interval between instructions that may be jump
+targets; perhaps there is an architecture where only even-numbered
+instructions may jumped to.) Note that it's possible for an instruction
+set not to have any instructions usable for a software breakpoint,
+although in practice only the ARC has failed to define such an
+instruction.
+
+The basic definition of the software breakpoint is the macro
+@code{BREAKPOINT}.
+
+Basic breakpoint object handling is in @file{breakpoint.c}. However,
+much of the interesting breakpoint action is in @file{infrun.c}.
+
+@section Single Stepping
+
+@section Signal Handling
+
+@section Thread Handling
+
+@section Inferior Function Calls
+
+@section 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-@var{xyz}.h} file. Look in @file{tm-sun4os4.h} and
+@file{sparc-tdep.c} for examples of how to do this.
+
+@node User Interface
+
+@chapter User Interface
+
+GDB has several user interfaces. Although the command-line interface
+is the most common and most familiar, there are others.
+
+@section Command Interpreter
+
+The command interpreter in GDB is fairly simple. It is designed to
+allow for the set of commands to be augmented dynamically, and also
+has a recursive subcommand capability, where the first argument to
+a command may itself direct a lookup on a different command list.
+
+For instance, the @code{set} command just starts a lookup on the
+@code{setlist} command list, while @code{set thread} recurses
+to the @code{set_thread_cmd_list}.
+
+To add commands in general, use @code{add_cmd}. @code{add_com} adds to
+the main command list, and should be used for those commands. The usual
+place to add commands is in the @code{_initialize_@var{xyz}} routines at the
+ends of most source files.
+
+@section Console Printing
+
+@section TUI
+
+@section libgdb
+
+@code{libgdb} was an abortive project of years ago. The theory was to
+provide an API to GDB's functionality.
+
+@node Symbol Handling
+
+@chapter Symbol Handling
+
+Symbols are a key part of GDB's operation. Symbols include variables,
+functions, and types.
+
+@section 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 @code{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 code in @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{xyz}_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{xyz}_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{xyz}_symfile_init}, but it can call
+@code{error} if it detects an unavoidable problem.
+
+@item @var{xyz}_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{xyz}_symfile_init}, if a new
+symbol table is being read, or may be called alone if all symbols are
+simply being discarded.
+
+@item @var{xyz}_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{xyz}_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{xyz}_symfile_read is called, these psymtabs will contain a pointer
+to a function @code{@var{xyz}_psymtab_to_symtab}, which can be called
+from any point in the GDB symbol-handling code.
+
+@table @code
+@item @var{xyz}_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
+
+@section 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.
+@c (@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.
+
+@section 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.
+
+@section Object File Formats
+
+@subsection a.out
+
+The @file{a.out} format is the original file format for Unix. It
+consists of three sections: text, data, and bss, which are for program
+code, initialized data, and uninitialized data, respectively.
+
+The @file{a.out} format is so simple that it doesn't have any reserved
+place for debugging information. (Hey, the original Unix hackers used
+@file{adb}, which is a machine-language debugger.) The only debugging
+format for @file{a.out} is stabs, which is encoded as a set of normal
+symbols with distinctive attributes.
+
+The basic @file{a.out} reader is in @file{dbxread.c}.
+
+@subsection COFF
+
+The COFF format was introduced with System V Release 3 (SVR3) Unix.
+COFF files may have multiple sections, each prefixed by a header. The
+number of sections is limited.
+
+The COFF specification includes support for debugging. Although this
+was a step forward, the debugging information was woefully limited. For
+instance, it was not possible to represent code that came from an
+included file.
+
+The COFF reader is in @file{coffread.c}.
+
+@subsection ECOFF
+
+ECOFF is an extended COFF originally introduced for Mips and Alpha
+workstations.
+
+The basic ECOFF reader is in @file{mipsread.c}.
+
+@subsection XCOFF
+
+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, see @xref{Top,,,stabs,The Stabs Debugging Format}.
+
+The shared library scheme has a 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).
+
+@subsection PE
+
+Windows 95 and NT use the PE (Portable Executable) format for their
+executables. PE is basically COFF with additional headers.
+
+While BFD includes special PE support, GDB needs only the basic
+COFF reader.
+
+@subsection ELF
+
+The ELF format came with System V Release 4 (SVR4) Unix. ELF is similar
+to COFF in being organized into a number of sections, but it removes
+many of COFF's limitations.
+
+The basic ELF reader is in @file{elfread.c}.
+
+@subsection SOM
+
+SOM is HP's object file and debug format (not to be confused with IBM's
+SOM, which is a cross-language ABI).
+
+The SOM reader is in @file{hpread.c}.
+
+@subsection Other File Formats
+
+Other file formats that have been supported by GDB include Netware
+Loadable Modules (@file{nlmread.c}.
+
+@section Debugging File Formats
+
+This section describes characteristics of debugging information that
+are independent of the object file format.
+
+@subsection stabs
+
+@code{stabs} started out as special symbols within the @code{a.out}
+format. Since then, it has been encapsulated into other file
+formats, such as COFF and ELF.
+
+While @file{dbxread.c} does some of the basic stab processing,
+including for encapsulated versions, @file{stabsread.c} does
+the real work.
+
+@subsection COFF
+
+The basic COFF definition includes debugging information. The level
+of support is minimal and non-extensible, and is not often used.
+
+@subsection Mips debug (Third Eye)
+
+ECOFF includes a definition of a special debug format.
+
+The file @file{mdebugread.c} implements reading for this format.
+
+@subsection DWARF 1
+
+DWARF 1 is a debugging format that was originally designed to be
+used with ELF in SVR4 systems.
+
+@c CHILL_PRODUCER
+@c GCC_PRODUCER
+@c GPLUS_PRODUCER
+@c LCC_PRODUCER
+@c If defined, these are the producer strings in a DWARF 1 file. All of
+@c these have reasonable defaults already.
+
+The DWARF 1 reader is in @file{dwarfread.c}.
+
+@subsection DWARF 2
+
+DWARF 2 is an improved but incompatible version of DWARF 1.
+
+The DWARF 2 reader is in @file{dwarf2read.c}.
+
+@subsection SOM
+
+Like COFF, the SOM definition includes debugging information.
+
+@section Adding a New Symbol Reader to GDB
+
+If you are using an existing object file format (a.out, COFF, ELF, etc),
+there is probably little to be done.
+
+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.
+
+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/libxyz.h}, which is included by GDB.
+
+
+@node Language Support
+
+@chapter Language Support
+
+GDB's language support is mainly driven by the symbol reader, although
+it is possible for the user to set the source language manually.
+
+GDB chooses the source language by looking at the extension of the file
+recorded in the debug info; @code{.c} means C, @code{.f} means Fortran,
+etc. It may also use a special-purpose language identifier if the debug
+format supports it, such as DWARF.
+
+@section 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 Host Definition
+
+@chapter Host Definition
+
+With the advent of autoconf, it's rarely necessary to have host
+definition machinery anymore.
+
+@section Adding a New Host
+
+Most of GDB's host configuration support happens via autoconf. It
+should be rare to need new host-specific definitions. GDB still uses
+the host-specific definitions and files listed below, but these mostly
+exist for historical reasons, and should eventually disappear.
+
+Several files control GDB's configuration for host systems:
+
+@table @file
+
+@item gdb/config/@var{arch}/@var{xyz}.mh
+Specifies Makefile fragments needed when hosting on machine @var{xyz}.
+In particular, this lists the required machine-dependent object files,
+by defining @samp{XDEPFILES=@dots{}}. Also specifies the header file
+which describes host @var{xyz}, by defining @code{XM_FILE=
+xm-@var{xyz}.h}. You can also define @code{CC}, @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{xyz}.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.
+
+@item gdb/@var{xyz}-xdep.c
+Contains any miscellaneous C code required for this machine as a host.
+On most machines it doesn't exist at all. If it does exist, put
+@file{@var{xyz}-xdep.o} into the @code{XDEPFILES} line in
+@file{gdb/config/@var{arch}/@var{xyz}.mh}.
+
+@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{xyz}.h} file. If these routines work for
+the @var{xyz} 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{xyz}-xdep.c}, and put @code{@var{xyz}-xdep.o}
+into @code{XDEPFILES}.
+
+@table @file
+
+@item ser-unix.c
+This contains serial line support for Unix systems. This is always
+included, via the makefile variable @code{SER_HARDWIRE}; override this
+variable in the @file{.mh} file to avoid it.
+
+@item ser-go32.c
+This contains serial line support for 32-bit programs running under DOS,
+using the GO32 execution environment.
+
+@item ser-tcp.c
+This contains generic TCP support using sockets.
+
+@end table
+
+@section 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 (or if the meaning is not
+documented here, then one of the source files where they are used is
+indicated) are:
+
+@table @code
+
+@item GDBINIT_FILENAME
+The default name of GDB's initialization file (normally @file{.gdbinit}).
+
+@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
+Define this if your system does not have a @code{<sys/file.h>}.
+
+@item SIGWINCH_HANDLER
+If your host defines @code{SIGWINCH}, you can define this to be the name
+of a function to be called if @code{SIGWINCH} is received.
+
+@item SIGWINCH_HANDLER_BODY
+Define this to expand into code that will define the function named by
+the expansion of @code{SIGWINCH_HANDLER}.
+
+@item ALIGN_STACK_ON_STARTUP
+Define this if your system is of a sort that will crash in
+@code{tgetent} if the stack happens not to be longword-aligned when
+@code{main} is called. This is a rare situation, but is known to occur
+on several different types of systems.
+
+@item CRLF_SOURCE_FILES
+Define this if host files use @code{\r\n} rather than @code{\n} as a
+line terminator. This will cause source file listings to omit @code{\r}
+characters when printing and it will allow \r\n line endings of files
+which are "sourced" by gdb. It must be possible to open files in binary
+mode using @code{O_BINARY} or, for fopen, @code{"rb"}.
+
+@item DEFAULT_PROMPT
+The default value of the prompt string (normally @code{"(gdb) "}).
+
+@item DEV_TTY
+The name of the generic TTY device, defaults to @code{"/dev/tty"}.
+
+@item FCLOSE_PROVIDED
+Define this if the system declares @code{fclose} in the headers included
+in @code{defs.h}. This isn't needed unless your compiler is unusually
+anal.
+
+@item FOPEN_RB
+Define this if binary files are opened the same way as text files.
+
+@item GETENV_PROVIDED
+Define this if the system declares @code{getenv} in its headers included
+in @code{defs.h}. This isn't needed unless your compiler is unusually
+anal.
+
+@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_SIGSETMASK
+Define this if the host system has job control, but does not define
+@code{sigsetmask()}. Currently, this is only true of the RS/6000.
+
+@item HAVE_TERMIO
+Define this if the host system has @code{termio.h}.
+
+@item HOST_BYTE_ORDER
+The ordering of bytes in the host. This must be defined to be either
+@code{BIG_ENDIAN} or @code{LITTLE_ENDIAN}.
+
+@item INT_MAX
+@item INT_MIN
+@item LONG_MAX
+@item UINT_MAX
+@item ULONG_MAX
+Values for host-side constants.
+
+@item ISATTY
+Substitute for isatty, if not available.
+
+@item LONGEST
+This is the longest integer type available on the host. If not defined,
+it will default to @code{long long} or @code{long}, depending on
+@code{CC_HAS_LONG_LONG}.
+
+@item CC_HAS_LONG_LONG
+Define this if the host C compiler supports ``long long''. This is set
+by the configure script.
+
+@item PRINTF_HAS_LONG_LONG
+Define this if the host can handle printing of long long integers via
+the printf format directive ``ll''. This is set by the configure script.
+
+@item HAVE_LONG_DOUBLE
+Define this if the host C compiler supports ``long double''. This is
+set by the configure script.
+
+@item PRINTF_HAS_LONG_DOUBLE
+Define this if the host can handle printing of long double float-point
+numbers via the printf format directive ``Lg''. This is set by the
+configure script.
+
+@item SCANF_HAS_LONG_DOUBLE
+Define this if the host can handle the parsing of long double
+float-point numbers via the scanf format directive directive
+``Lg''. This is set by the configure script.
+
+@item LSEEK_NOT_LINEAR
+Define this if @code{lseek (n)} does not necessarily move to byte number
+@code{n} in the file. This is only used when reading source files. It
+is normally faster to define @code{CRLF_SOURCE_FILES} when possible.
+
+@item L_SET
+This macro is used as the argument to lseek (or, most commonly,
+bfd_seek). FIXME, should be replaced by SEEK_SET instead, which is the
+POSIX equivalent.
+
+@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 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 NEED_POSIX_SETPGID
+Define this to use the POSIX version of @code{setpgid} to determine
+whether job control is available.
+
+@item NORETURN
+If defined, this should be one or more tokens, such as @code{volatile},
+that can be used in both the declaration and definition of functions to
+indicate that they never return. The default is already set correctly
+if compiling with GCC. This will almost never need to be defined.
+
+@item ATTR_NORETURN
+If defined, this should be one or more tokens, such as
+@code{__attribute__ ((noreturn))}, that can be used in the declarations
+of functions to indicate that they never return. The default is already
+set correctly if compiling with GCC. This will almost never need to be
+defined.
+
+@item USE_MMALLOC
+GDB will use the @code{mmalloc} library for memory allocation for symbol
+reading if this symbol is defined. Be careful defining it since there
+are 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{USE_MMALLOC}, you will also have to set @code{MMALLOC} in the
+Makefile, to point to the mmalloc library. This define is set when you
+configure with --with-mmalloc.
+
+@item NO_MMCHECK
+Define this if you are using @code{mmalloc}, but don't want the overhead
+of checking the heap with @code{mmcheck}. Note that on some systems,
+the C runtime makes calls to malloc prior to calling @code{main}, and if
+@code{free} is ever called with these pointers after calling
+@code{mmcheck} to enable checking, a memory corruption abort is certain
+to occur. These systems can still use mmalloc, but must define
+NO_MMCHECK.
+
+@item MMCHECK_FORCE
+Define this to 1 if the C runtime allocates memory prior to
+@code{mmcheck} being called, but that memory is never freed so we don't
+have to worry about it triggering a memory corruption abort. The
+default is 0, which means that @code{mmcheck} will only install the heap
+checking functions if there has not yet been any memory allocation
+calls, and if it fails to install the functions, gdb will issue a
+warning. This is currently defined if you configure using
+--with-mmalloc.
+
+@item NO_SIGINTERRUPT
+Define this to indicate that siginterrupt() is not available.
+
+@item R_OK
+Define if this is not in a system .h file.
+
+@item SEEK_CUR
+@item SEEK_SET
+Define these to appropriate value for the system lseek(), if not already
+defined.
+
+@item STOP_SIGNAL
+This is the signal for stopping GDB. Defaults to SIGTSTP. (Only
+redefined for the Convex.)
+
+@item USE_O_NOCTTY
+Define this if the interior's tty should be opened with the O_NOCTTY
+flag. (FIXME: This should be a native-only flag, but @file{inflow.c} is
+always linked in.)
+
+@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 lint
+Define this to help placate lint in some situations.
+
+@item volatile
+Define this to override the defaults of @code{__volatile__} or
+@code{/**/}.
+
+@end table
+
+
+@node Target Architecture Definition
+
+@chapter Target Architecture Definition
+
+GDB's target architecture defines what sort of machine-language programs
+GDB can work with, and how it works with them.
+
+At present, the target architecture definition consists of a number of C
+macros.
+
+@section Registers and Memory
+
+GDB's model of the target machine is rather simple. GDB assumes the
+machine includes a bank of registers and a block of memory. Each
+register may have a different size.
+
+GDB does not have a magical way to match up with the compiler's idea of
+which registers are which; however, it is critical that they do match up
+accurately. The only way to make this work is to get accurate
+information about the order that the compiler uses, and to reflect that
+in the @code{REGISTER_NAME} and related macros.
+
+GDB can handle big-endian, little-endian, and bi-endian architectures.
+
+@section Frame Interpretation
+
+@section Inferior Call Setup
+
+@section Compiler Characteristics
+
+@section Target Conditionals
+
+This section describes the macros that you can use to define the target
+machine.
+
+@table @code
+
+@item ADDITIONAL_OPTIONS
+@item ADDITIONAL_OPTION_CASES
+@item ADDITIONAL_OPTION_HANDLER
+@item ADDITIONAL_OPTION_HELP
+These are a set of macros that allow the addition of additional command
+line options to GDB. They are currently used only for the unsupported
+i960 Nindy target, and should not be used in any other configuration.
+
+@item ADDR_BITS_REMOVE (addr)
+If a raw machine address includes any bits that are not really part of
+the address, then define this macro to expand into an expression that
+zeros those bits in @var{addr}. For example, the two low-order bits of
+a Motorola 88K address may be used by some kernels for their own
+purposes, since addresses must always be 4-byte aligned, and so are of
+no use for addressing. Those bits should be filtered out with an
+expression such as @code{((addr) & ~3)}.
+
+@item BEFORE_MAIN_LOOP_HOOK
+Define this to expand into any code that you want to execute before the
+main loop starts. Although this is not, strictly speaking, a target
+conditional, that is how it is currently being used. Note that if a
+configuration were to define it one way for a host and a different way
+for the target, GDB will probably not compile, let alone run correctly.
+This is currently used only for the unsupported i960 Nindy target, and
+should not be used in any other configuration.
+
+@item BELIEVE_PCC_PROMOTION
+Define if the compiler promotes a short or char parameter to an int, but
+still reports the parameter as its original type, rather than the
+promoted type.
+
+@item BELIEVE_PCC_PROMOTION_TYPE
+Define this if GDB should believe the type of a short argument when
+compiled by pcc, but look within a full int space to get its value.
+Only defined for Sun-3 at present.
+
+@item BITS_BIG_ENDIAN
+Define this if the numbering of bits in the targets does *not* match the
+endianness of the target byte order. A value of 1 means that the bits
+are numbered in a big-endian order, 0 means little-endian.
+
+@item BREAKPOINT
+This is the character array initializer for the bit pattern to put into
+memory where a breakpoint is set. Although it's common to use a trap
+instruction for a breakpoint, it's not required; for instance, the bit
+pattern could be an invalid instruction. The breakpoint must be no
+longer than the shortest instruction of the architecture.
+
+@item BIG_BREAKPOINT
+@item LITTLE_BREAKPOINT
+Similar to BREAKPOINT, but used for bi-endian targets.
+
+@item REMOTE_BREAKPOINT
+@item LITTLE_REMOTE_BREAKPOINT
+@item BIG_REMOTE_BREAKPOINT
+Similar to BREAKPOINT, but used for remote targets.
+
+@item BREAKPOINT_FROM_PC (pcptr, lenptr)
+
+Use the program counter to determine the contents and size of a
+breakpoint instruction. It returns a pointer to a string of bytes that
+encode a breakpoint instruction, stores the length of the string to
+*lenptr, and adjusts pc (if necessary) to point to the actual memory
+location where the breakpoint should be inserted.
+
+Although it is common to use a trap instruction for a breakpoint, it's
+not required; for instance, the bit pattern could be an invalid
+instruction. The breakpoint must be no longer than the shortest
+instruction of the architecture.
+
+Replaces all the other BREAKPOINTs.
+
+@item CALL_DUMMY
+valops.c
+@item CALL_DUMMY_LOCATION
+inferior.h
+@item CALL_DUMMY_STACK_ADJUST
+valops.c
+
+@item CANNOT_FETCH_REGISTER (regno)
+A C expression that should be nonzero if @var{regno} cannot be fetched
+from an inferior process. This is only relevant if
+@code{FETCH_INFERIOR_REGISTERS} is not defined.
+
+@item CANNOT_STORE_REGISTER (regno)
+A C expression that should be nonzero if @var{regno} should not be
+written to the target. This is often the case for program counters,
+status words, and other special registers. If this is not defined, GDB
+will assume that all registers may be written.
+
+@item DO_DEFERRED_STORES
+@item CLEAR_DEFERRED_STORES
+Define this to execute any deferred stores of registers into the inferior,
+and to cancel any deferred stores.
+
+Currently only implemented correctly for native Sparc configurations?
+
+@item CPLUS_MARKER
+Define this to expand into the character that G++ uses to distinguish
+compiler-generated identifiers from programmer-specified identifiers.
+By default, this expands into @code{'$'}. Most System V targets should
+define this to @code{'.'}.
+
+@item DBX_PARM_SYMBOL_CLASS
+Hook for the @code{SYMBOL_CLASS} of a parameter when decoding DBX symbol
+information. In the i960, parameters can be stored as locals or as
+args, depending on the type of the debug record.
+
+@item DECR_PC_AFTER_BREAK
+Define this to be the amount by which to decrement the PC after the
+program encounters a breakpoint. This is often the number of bytes in
+BREAKPOINT, though not always. For most targets this value will be 0.
+
+@item DECR_PC_AFTER_HW_BREAK
+Similarly, for hardware breakpoints.
+
+@item DISABLE_UNSETTABLE_BREAK addr
+If defined, this should evaluate to 1 if @var{addr} is in a shared
+library in which breakpoints cannot be set and so should be disabled.
+
+@item DO_REGISTERS_INFO
+If defined, use this to print the value of a register or all registers.
+
+@item END_OF_TEXT_DEFAULT
+This is an expression that should designate the end of the text section
+(? FIXME ?)
+
+@item EXTRACT_RETURN_VALUE(type,regbuf,valbuf)
+Define this to extract a function's return value of type @var{type} from
+the raw register state @var{regbuf} and copy that, in virtual format,
+into @var{valbuf}.
+
+@item EXTRACT_STRUCT_VALUE_ADDRESS(regbuf)
+Define this to extract from an array @var{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).
+
+@item FLOAT_INFO
+If defined, then the `info float' command will print information about
+the processor's floating point unit.
+
+@item FP_REGNUM
+The number of the frame pointer register.
+
+@item FRAMELESS_FUNCTION_INVOCATION(fi, frameless)
+Define this to set the variable @var{frameless} to 1 if the function
+invocation represented by @var{fi} does not have a stack frame
+associated with it. Otherwise set it to 0.
+
+@item FRAME_ARGS_ADDRESS_CORRECT
+stack.c
+
+@item FRAME_CHAIN(frame)
+Given @var{frame}, return a pointer to the calling frame.
+
+@item FRAME_CHAIN_COMBINE(chain,frame)
+Define this to take the frame chain pointer and the frame's nominal
+address and produce the nominal address of the caller's frame.
+Presently only defined for HP PA.
+
+@item FRAME_CHAIN_VALID(chain,thisframe)
+
+Define this to be an expression that returns zero if the given frame is
+an outermost frame, with no caller, and nonzero otherwise. Three common
+definitions are available. @code{default_frame_chain_valid} (the
+default) is nonzero if the chain pointer is nonzero and given frame's PC
+is not inside the startup file (such as @file{crt0.o}).
+@code{alternate_frame_chain_valid} is nonzero if the chain pointer is
+nonzero and the given frame's PC is not in @code{main()} or a known
+entry point function (such as @code{_start()}).
+
+@item FRAME_INIT_SAVED_REGS(frame)
+See @file{frame.h}. Determines the address of all registers in the
+current stack frame storing each in @code{frame->saved_regs}. Space for
+@code{frame->saved_regs} shall be allocated by
+@code{FRAME_INIT_SAVED_REGS} using either
+@code{frame_saved_regs_zalloc} or @code{frame_obstack_alloc}.
+
+@var{FRAME_FIND_SAVED_REGS} and @var{EXTRA_FRAME_INFO} are deprecated.
+
+@item FRAME_NUM_ARGS (val, fi)
+For the frame described by @var{fi}, set @var{val} to the number of arguments
+that are being passed.
+
+@item FRAME_SAVED_PC(frame)
+Given @var{frame}, return the pc saved there. That is, the return
+address.
+
+@item FUNCTION_EPILOGUE_SIZE
+For some COFF targets, the @code{x_sym.x_misc.x_fsize} field of the
+function end symbol is 0. For such targets, you must define
+@code{FUNCTION_EPILOGUE_SIZE} to expand into the standard size of a
+function's epilogue.
+
+@item GCC_COMPILED_FLAG_SYMBOL
+@item GCC2_COMPILED_FLAG_SYMBOL
+If defined, these are the names of the symbols that GDB will look for to
+detect that GCC compiled the file. The default symbols are
+@code{gcc_compiled.} and @code{gcc2_compiled.}, respectively. (Currently
+only defined for the Delta 68.)
+
+@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
+@item GDB_TARGET_IS_SUN3
+@item GDB_TARGET_IS_SUN386
+Kludges that should go away.
+
+@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
+Define this if you need to supply your own definition for the function
+@code{get_saved_register}. Currently this is only done for the a29k.
+
+@item HAVE_REGISTER_WINDOWS
+Define this if the target has register windows.
+@item REGISTER_IN_WINDOW_P (regnum)
+Define this to be an expression that is 1 if the given register is in
+the window.
+
+@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_FLOAT
+Define this if the target system uses IEEE-format floating point numbers.
+
+@item INIT_EXTRA_FRAME_INFO (fromleaf, frame)
+If additional information about the frame is required this should be
+stored in @code{frame->extra_info}. Space for @code{frame->extra_info}
+is allocated using @code{frame_obstack_alloc}.
+
+@item INIT_FRAME_PC (fromleaf, prev)
+This is a C statement that sets the pc of the frame pointed to by
+@var{prev}. [By default...]
+
+@item INNER_THAN (lhs,rhs)
+Returns non-zero if stack address @var{lhs} is inner than (nearer to the
+stack top) stack address @var{rhs}. Define this as @code{lhs < rhs} if
+the target's stack grows downward in memory, or @code{lhs > rsh} if the
+stack grows upward.
+
+@item IN_SIGTRAMP (pc, name)
+Define this to return true if the given @var{pc} and/or @var{name}
+indicates that the current function is a sigtramp.
+
+@item SIGTRAMP_START (pc)
+@item SIGTRAMP_END (pc)
+Define these to be the start and end address of the sigtramp for the
+given @var{pc}. On machines where the address is just a compile time
+constant, the macro expansion will typically just ignore the supplied
+@var{pc}.
+
+@item IN_SOLIB_CALL_TRAMPOLINE pc name
+Define this to evaluate to nonzero if the program is stopped in the
+trampoline that connects to a shared library.
+
+@item IN_SOLIB_RETURN_TRAMPOLINE pc name
+Define this to evaluate to nonzero if the program is stopped in the
+trampoline that returns from a shared library.
+
+@item IS_TRAPPED_INTERNALVAR (name)
+This is an ugly hook to allow the specification of special actions that
+should occur as a side-effect of setting the value of a variable
+internal to GDB. Currently only used by the h8500. Note that this
+could be either a host or target conditional.
+
+@item NEED_TEXT_START_END
+Define this if GDB should determine the start and end addresses of the
+text section. (Seems dubious.)
+
+@item NO_HIF_SUPPORT
+(Specific to the a29k.)
+
+@item SOFTWARE_SINGLE_STEP_P
+Define this as 1 if the target does not have a hardware single-step
+mechanism. The macro @code{SOFTWARE_SINGLE_STEP} must also be defined.
+
+@item SOFTWARE_SINGLE_STEP(signal,insert_breapoints_p)
+A function that inserts or removes (dependant on
+@var{insert_breapoints_p}) breakpoints at each possible destinations of
+the next instruction. See @code{sparc-tdep.c} and @code{rs6000-tdep.c}
+for examples.
+
+@item PCC_SOL_BROKEN
+(Used only in the Convex target.)
+
+@item PC_IN_CALL_DUMMY
+inferior.h
+
+@item PC_LOAD_SEGMENT
+If defined, print information about the load segment for the program
+counter. (Defined only for the RS/6000.)
+
+@item PC_REGNUM
+If the program counter is kept in a register, then define this macro to
+be the number of that register. This need be defined only if
+@code{TARGET_WRITE_PC} is not defined.
+
+@item NPC_REGNUM
+The number of the ``next program counter'' register, if defined.
+
+@item NNPC_REGNUM
+The number of the ``next next program counter'' register, if defined.
+Currently, this is only defined for the Motorola 88K.
+
+@item PRINT_REGISTER_HOOK (regno)
+If defined, this must be a function that prints the contents of the
+given register to standard output.
+
+@item PRINT_TYPELESS_INTEGER
+This is an obscure substitute for @code{print_longest} that seems to
+have been defined for the Convex target.
+
+@item PROCESS_LINENUMBER_HOOK
+A hook defined for XCOFF reading.
+
+@item PROLOGUE_FIRSTLINE_OVERLAP
+(Only used in unsupported Convex configuration.)
+
+@item PS_REGNUM
+If defined, this is the number of the processor status register. (This
+definition is only used in generic code when parsing "$ps".)
+
+@item POP_FRAME
+Used in @samp{call_function_by_hand} to remove an artificial stack
+frame.
+
+@item PUSH_ARGUMENTS (nargs, args, sp, struct_return, struct_addr)
+Define this to push arguments onto the stack for inferior function call.
+
+@item PUSH_DUMMY_FRAME
+Used in @samp{call_function_by_hand} to create an artificial stack frame.
+
+@item REGISTER_BYTES
+The total amount of space needed to store GDB's copy of the machine's
+register state.
+
+@item REGISTER_NAME(i)
+Return the name of register @var{i} as a string. May return @var{NULL}
+or @var{NUL} to indicate that register @var{i} is not valid.
+
+@item REG_STRUCT_HAS_ADDR (gcc_p, type)
+Define this to return 1 if the given type will be passed by pointer
+rather than directly.
+
+@item SDB_REG_TO_REGNUM
+Define this to convert sdb register numbers into GDB regnums. If not
+defined, no conversion will be done.
+
+@item SHIFT_INST_REGS
+(Only used for m88k targets.)
+
+@item SKIP_PROLOGUE (pc)
+A C statement that advances the @var{pc} across any function entry
+prologue instructions so as to reach ``real'' code.
+
+@item SKIP_PROLOGUE_FRAMELESS_P
+A C statement that should behave similarly, but that can stop as soon as
+the function is known to have a frame. If not defined,
+@code{SKIP_PROLOGUE} will be used instead.
+
+@item SKIP_TRAMPOLINE_CODE (pc)
+If the target machine has trampoline code that sits between callers and
+the functions being called, then define this macro to return a new PC
+that is at the start of the real function.
+
+@item SP_REGNUM
+Define this to be the number of the register that serves as the stack
+pointer.
+
+@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 (addr)
+Define this to adjust the address to the alignment required for the
+processor's stack.
+
+@item STEP_SKIPS_DELAY (addr)
+Define this to return true if the address is of an instruction with a
+delay slot. If a breakpoint has been placed in the instruction's delay
+slot, GDB will single-step over that instruction before resuming
+normally. Currently only defined for the Mips.
+
+@item STORE_RETURN_VALUE (type, valbuf)
+A C expression that stores a function return value of type @var{type},
+where @var{valbuf} is the address of the value to be stored.
+
+@item SUN_FIXED_LBRAC_BUG
+(Used only for Sun-3 and Sun-4 targets.)
+
+@item SYMBOL_RELOADING_DEFAULT
+The default value of the `symbol-reloading' variable. (Never defined in
+current sources.)
+
+@item TARGET_BYTE_ORDER_DEFAULT
+The ordering of bytes in the target. This must be either
+@code{BIG_ENDIAN} or @code{LITTLE_ENDIAN}. This macro replaces
+@var{TARGET_BYTE_ORDER} which is deprecated.
+
+@item TARGET_BYTE_ORDER_SELECTABLE_P
+Non-zero if the target has both @code{BIG_ENDIAN} and
+@code{LITTLE_ENDIAN} variants. This macro replaces
+@var{TARGET_BYTE_ORDER_SELECTABLE} which is deprecated.
+
+@item TARGET_CHAR_BIT
+Number of bits in a char; defaults to 8.
+
+@item TARGET_COMPLEX_BIT
+Number of bits in a complex number; defaults to @code{2 * TARGET_FLOAT_BIT}.
+
+@item TARGET_DOUBLE_BIT
+Number of bits in a double float; defaults to @code{8 * TARGET_CHAR_BIT}.
+
+@item TARGET_DOUBLE_COMPLEX_BIT
+Number of bits in a double complex; defaults to @code{2 * TARGET_DOUBLE_BIT}.
+
+@item TARGET_FLOAT_BIT
+Number of bits in a float; defaults to @code{4 * TARGET_CHAR_BIT}.
+
+@item TARGET_INT_BIT
+Number of bits in an integer; defaults to @code{4 * TARGET_CHAR_BIT}.
+
+@item TARGET_LONG_BIT
+Number of bits in a long integer; defaults to @code{4 * TARGET_CHAR_BIT}.
+
+@item TARGET_LONG_DOUBLE_BIT
+Number of bits in a long double float;
+defaults to @code{2 * TARGET_DOUBLE_BIT}.
+
+@item TARGET_LONG_LONG_BIT
+Number of bits in a long long integer; defaults to @code{2 * TARGET_LONG_BIT}.
+
+@item TARGET_PTR_BIT
+Number of bits in a pointer; defaults to @code{TARGET_INT_BIT}.
+
+@item TARGET_SHORT_BIT
+Number of bits in a short integer; defaults to @code{2 * TARGET_CHAR_BIT}.
+
+@item TARGET_READ_PC
+@item TARGET_WRITE_PC (val, pid)
+@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_VIRTUAL_FRAME_POINTER(pc,regp,offsetp)
+Returns a @code{(register, offset)} pair representing the virtual
+frame pointer in use at the code address @code{"pc"}. If virtual
+frame pointers are not used, a default definition simply returns
+@code{FP_REGNUM}, with an offset of zero.
+
+@item USE_STRUCT_CONVENTION (gcc_p, type)
+If defined, this must be an expression that is nonzero if a value of the
+given @var{type} being returned from a function must have space
+allocated for it on the stack. @var{gcc_p} is true if the function
+being considered is known to have been compiled by GCC; this is helpful
+for systems where GCC is known to use different calling convention than
+other compilers.
+
+@item VARIABLES_INSIDE_BLOCK (desc, gcc_p)
+For dbx-style debugging information, if the compiler puts variable
+declarations inside LBRAC/RBRAC blocks, this should be defined to be
+nonzero. @var{desc} is the value of @code{n_desc} from the
+@code{N_RBRAC} symbol, and @var{gcc_p} is true if GDB has noticed the
+presence of either the @code{GCC_COMPILED_SYMBOL} or the
+@code{GCC2_COMPILED_SYMBOL}. By default, this is 0.
+
+@item OS9K_VARIABLES_INSIDE_BLOCK (desc, gcc_p)
+Similarly, for OS/9000. Defaults to 1.
+
+@end table
+
+Motorola M68K target conditionals.
+
+@table @code
+
+@item BPT_VECTOR
+Define this to be the 4-bit location of the breakpoint trap vector. If
+not defined, it will default to @code{0xf}.
+
+@item REMOTE_BPT_VECTOR
+Defaults to @code{1}.
+
+@end table
+
+@section Adding a New Target
+
+The following files define a target to GDB:
+
+@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}, but
+these are now deprecated and may go away in future versions of GDB.
+
+@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.
+
+@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. This is vastly preferable, since it is easier to understand
+and debug.
+
+@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{ttt}.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
+
+If you are adding a new operating system for an existing CPU chip, add a
+@file{config/tm-@var{os}.h} file that describes the operating system
+facilities that are unusual (extra symbol table info; the breakpoint
+instruction needed; etc). Then write a @file{@var{arch}/tm-@var{os}.h}
+that just @code{#include}s @file{tm-@var{arch}.h} and
+@file{config/tm-@var{os}.h}.
+
+
+@node Target Vector Definition
+
+@chapter Target Vector Definition
+
+The target vector defines the interface between GDB's abstract handling
+of target systems, and the nitty-gritty code that actually exercises
+control over a process or a serial port. GDB includes some 30-40
+different target vectors; however, each configuration of GDB includes
+only a few of them.
+
+@section File Targets
+
+Both executables and core files have target vectors.
+
+@section Standard Protocol and 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.
+
+@section ROM Monitor Interface
+
+@section Custom Protocols
+
+@section Transport Layer
+
+@section Builtin Simulator
+
+
+@node Native Debugging
+
+@chapter Native Debugging
+
+Several files control GDB's configuration for native support:
+
+@table @file
+
+@item gdb/config/@var{arch}/@var{xyz}.mh
+Specifies Makefile fragments needed when hosting @emph{or native} on
+machine @var{xyz}. 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{xyz}, by defining @samp{NAT_FILE= nm-@var{xyz}.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{xyz}.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.
+
+@item gdb/@var{xyz}-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
+
+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{xyz}.h} file. If these routines work for
+the @var{xyz} 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{xyz}-nat.c}, and put @code{@var{xyz}-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.
+
+@end table
+
+@section Native core file Support
+
+@table @file
+
+@item core-aout.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{core-aout.c}, and should
+just provide @code{fetch_core_registers} in @code{@var{xyz}-nat.c} (or
+@code{REGISTER_U_ADDR} in @code{nm-@var{xyz}.h}).
+
+@item core-aout.c::register_addr()
+If your @code{nm-@var{xyz}.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{core-aout.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{xyz}-nat.c} file, and be sure @code{@var{xyz}-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{core-aout.c}; if not, it's in your @file{@var{xyz}-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.
+
+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.
+
+@section ptrace
+
+@section /proc
+
+@section win32
+
+@section shared libraries
+
+@section 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 CHILD_PREPARE_TO_STORE
+If the machine stores all registers at once in the child process, then
+define this to ensure that all values are correct. This usually entails
+a read from the child.
+
+[Note that this is incorrectly defined in @file{xm-@var{system}.h} files
+currently.]
+
+@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 FILES_INFO_HOOK
+(Only defined for Convex.)
+
+@item FP0_REGNUM
+This macro is normally defined to be the number of the first floating
+point register, if the machine has such registers. As such, it would
+appear only in target-specific code. However, /proc support uses this
+to decide whether floats are in use on this target.
+
+@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 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 ONE_PROCESS_WRITETEXT
+Define this to be able to, when a breakpoint insertion fails, warn the
+user that another process may be running with the same executable.
+
+@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''.
+
+@item SHELL_COMMAND_CONCAT
+If defined, is a string to prefix on the shell command used to start the
+inferior.
+
+@item SHELL_FILE
+If defined, this is the name of the shell to use to run the inferior.
+Defaults to @code{"/bin/sh"}.
+
+@item SOLIB_ADD (filename, from_tty, targ)
+Define this to expand into an expression that will cause the symbols in
+@var{filename} to be added to GDB's symbol table.
+
+@item SOLIB_CREATE_INFERIOR_HOOK
+Define this to expand into any shared-library-relocation code that you
+want to be run just after the child process has been forked.
+
+@item START_INFERIOR_TRAPS_EXPECTED
+When starting an inferior, GDB normally expects to trap twice; once when
+the shell execs, and once when the program itself execs. If the actual
+number of traps is something other than 2, then define this macro to
+expand into the number expected.
+
+@item SVR4_SHARED_LIBS
+Define this to indicate that SVR4-style shared libraries are in use.
+
+@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.
+
+@item CLEAR_SOLIB
+objfiles.c
+
+@item DEBUG_PTRACE
+Define this to debug ptrace calls.
+
+@end table
+
+
+@node Support Libraries
+
+@chapter Support Libraries
+
+@section BFD
+
+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
+
+@section opcodes
+
+The opcodes library provides GDB's disassembler. (It's a separate
+library because it's also used in binutils, for @file{objdump}).
+
+@section readline
+
+@section mmalloc
+
+@section libiberty
+
+@section gnu-regex
+
+Regex conditionals.
+
+@table @code
+
+@item C_ALLOCA
+
+@item NFAILURES
+
+@item RE_NREGS
+
+@item SIGN_EXTEND_CHAR
+
+@item SWITCH_ENUM_BUG
+
+@item SYNTAX_TABLE
+
+@item Sword
+
+@item sparc
+
+@end table
+
+@section include
+
+@node Coding
+
+@chapter Coding
+
+This chapter covers topics that are lower-level than the major
+algorithms of GDB.
+
+@section 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).
+
+@section 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.
+
+@section GDB Coding Standards
+
+GDB follows the GNU coding standards, as described in
+@file{etc/standards.texi}. This file is also available for anonymous
+FTP from GNU archive sites. GDB takes a strict interpretation of the
+standard; in general, when the GNU standard recommends a practice but
+does not require it, GDB requires it.
+
+GDB follows an additional set of coding standards specific to GDB,
+as described in the following sections.
+
+You can configure with @samp{--enable-build-warnings} to get GCC to
+check on a number of these rules. GDB sources ought not to engender any
+complaints, unless they are caused by bogus host systems. (The exact
+set of enabled warnings is currently @samp{-Wall -Wpointer-arith
+-Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations}.
+
+@subsection Formatting
+
+The standard GNU recommendations for formatting must be followed
+strictly.
+
+Note that while in a definition, the function's name must be in column
+zero; in a function declaration, the name must be on the same line as
+the return type.
+
+In addition, there must be a space between a function or macro name and
+the opening parenthesis of its argument list (except for macro
+definitions, as required by C). There must not be a space after an open
+paren/bracket or before a close paren/bracket.
+
+While additional whitespace is generally helpful for reading, do not use
+more than one blank line to separate blocks, and avoid adding whitespace
+after the end of a program line (as of 1/99, some 600 lines had whitespace
+after the semicolon). Excess whitespace causes difficulties for diff and
+patch.
+
+@subsection Comments
+
+The standard GNU requirements on comments must be followed strictly.
+
+Block comments must appear in the following form, with no `/*'- or
+'*/'-only lines, and no leading `*':
+
+@example @code
+/* 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. */
+@end example
+
+(Note that this format is encouraged by Emacs; tabbing for a multi-line
+comment works correctly, and M-Q fills the block consistently.)
+
+Put a blank line between the block comments preceding function or
+variable definitions, and the definition itself.
+
+In general, put function-body comments on lines by themselves, rather
+than trying to fit them into the 20 characters left at the end of a
+line, since either the comment or the code will inevitably get longer
+than will fit, and then somebody will have to move it anyhow.
+
+@subsection C Usage
+
+Code must not 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.
+
+Use functions freely. There are only a handful of compute-bound areas
+in GDB that might be affected by the overhead of a function call, mainly
+in symbol reading. Most of GDB's performance is limited by the target
+interface (whether serial line or system call).
+
+However, use functions with moderation. A thousand one-line functions
+are just as hard to understand as a single thousand-line function.
+
+@subsection Function Prototypes
+
+Prototypes must be used to @emph{declare} functions but never to
+@emph{define} them. Prototypes for GDB functions must include both the
+argument type and name, with the name matching that used in the actual
+function definition.
+
+For the sake of compatibility with pre-ANSI compilers, define prototypes
+with the @code{PARAMS} macro:
+
+@example @code
+extern int memory_remove_breakpoint PARAMS ((CORE_ADDR addr,
+ char *contents_cache));
+@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
+extern 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, except for @code{_initialize_*}
+functions, which must be external so that @file{init.c} construction
+works, but shouldn't be visible to random source files.
+
+All static functions must be declared in a block near the top of the
+source file.
+
+@subsection 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.
+
+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}.
+
+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.
+
+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.
+
+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.
+
+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.
+
+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.
+
+
+@node Porting GDB
+
+@chapter Porting GDB
+
+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{xyz} (e.g.
+@samp{sun4}), and its full three-part configuration name is
+@code{@var{arch}-@var{xvend}-@var{xos}} (e.g. @samp{sparc-sun-sunos4}).
+In particular:
+
+In the top level directory, edit @file{config.sub} and add @var{arch},
+@var{xvend}, and @var{xos} to the lists of supported architectures,
+vendors, and operating systems near the bottom of the file. Also, add
+@var{xyz} as an alias that maps to
+@code{@var{arch}-@var{xvend}-@var{xos}}. You can test your changes by
+running
+
+@example
+./config.sub @var{xyz}
+@end example
+@noindent
+and
+@example
+./config.sub @code{@var{arch}-@var{xvend}-@var{xos}}
+@end example
+@noindent
+which should both respond with @code{@var{arch}-@var{xvend}-@var{xos}}
+and no error messages.
+
+You need to port BFD, if that hasn't been done already. Porting BFD is
+beyond the scope of this manual.
+
+To configure GDB itself, edit @file{gdb/configure.host} to recognize
+your system and set @code{gdb_host} to @var{xyz}, and (unless your
+desired target is already available) also edit @file{gdb/configure.tgt},
+setting @code{gdb_target} to something appropriate (for instance,
+@var{xyz}).
+
+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.
+
+@section 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.gz
+@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
+been configured, you can just do @code{make gdb.tar.gz} 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 Hints
+
+@chapter Hints
+
+Check the @file{README} file, it often has useful information that does not
+appear anywhere else in the directory.
+
+@menu
+* Getting Started:: Getting started working on GDB
+* Debugging GDB:: Debugging GDB with itself
+@end menu
+
+@node Getting Started,,, Hints
+
+@section Getting Started
+
+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.
+
+This manual, the GDB Internals manual, has information which applies
+generally to many parts of GDB.
+
+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. 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 documents all the available macros.
+@c (@pxref{Host Conditionals}, @pxref{Target
+@c Conditionals}, @pxref{Native Conditionals}, and @pxref{Obsolete
+@c Conditionals})
+
+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.
+
+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.
+
+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.
+
+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}.
+
+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.
+
+@node Debugging GDB,,,Hints
+
+@section 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.
+
+@section 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 GDB maintainers will only install ``cleanly designed'' patches. You
+may not always agree on what is clean design.
+@c @pxref{Coding Style}, @pxref{Clean Design}.
+
+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.
+
+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 directly to the GDB maintainers at
+@code{gdb-patches@@cygnus.com}.
+
+@section 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!
+
+@item PYRAMID_CONTROL_FRAME_DEBUGGING
+pyr-xdep.c
+@item PYRAMID_CORE
+pyr-xdep.c
+@item PYRAMID_PTRACE
+pyr-xdep.c
+
+@item REG_STACK_SEGMENT
+exec.c
+
+@end table
+
+
+@contents
+@bye
diff --git a/gdb/doc/libgdb.texinfo b/gdb/doc/libgdb.texinfo
new file mode 100644
index 00000000000..4fadcb2c9b5
--- /dev/null
+++ b/gdb/doc/libgdb.texinfo
@@ -0,0 +1,878 @@
+\input texinfo @c -*-texinfo-*-
+@c %**start of header
+@setfilename libgdb.info
+@settitle Libgdb
+@setchapternewpage off
+@c %**end of header
+
+@ifinfo
+This file documents libgdb, the GNU symbolic debugger in a library.
+
+This is Edition 0.3, Oct 1993, of @cite{Libgdb}.
+Copyright 1993 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.
+
+@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
+
+@c This title page illustrates only one of the
+@c two methods of forming a title page.
+
+@titlepage
+@title Libgdb
+@subtitle Version 0.3
+@subtitle Oct 1993
+@author Thomas Lord
+
+@c The following two commands
+@c start the copyright page.
+@page
+@vskip 0pt plus 1filll
+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.
+
+Copyright @copyright{} 1993 Cygnus Support
+@end titlepage
+
+@ifinfo
+@node Top, Overview, (dir), (dir)
+
+This info file documents libgdb: an API for GDB, the GNU symbolic debugger.
+
+@menu
+* Overview:: The basics of libgdb and this document.
+* Interpreter:: Libgdb is an Interpreter-Based Server.
+* Top Level:: You Provide the Top Level for the Libgdb
+ Command Interpreter .
+* I/O:: How the Server's I/O Can be Used.
+* Invoking:: Invoking the Interpreter, Executing
+ Commands.
+* Defining Commands:: How New Commands are Created.
+* Variables:: How Builtin Variables are Defined.
+* Asynchronous:: Scheduling Asynchronous Computations.
+* Commands:: Debugger Commands for Libgdb Applications
+@end menu
+
+@end ifinfo
+@node Overview, Interpreter, top, top
+@comment node-name, next, previous, up
+@chapter Overview
+@cindex overview
+@cindex definitions
+
+@heading Function and Purpose
+
+Libgdb is a package which provides an API to the functionality of GDB,
+the GNU symbolic debugger. It is specifically intended to support the
+development of a symbolic debugger with a graphic interface.
+
+
+@heading This Document
+
+This document is a specification of the libgdb API. It is written in
+the form of a programmer's manual. So the goal of this document is to
+explain what functions make up the API, and how they can be used in a
+running application.
+
+
+@heading Terminology
+
+In this document, @dfn{libgdb} refers to a library containing the
+functions defined herein, @dfn{application} refers to any program built
+with that library.
+
+
+@heading Dependencies
+
+Programs which are linked with libgdb must be linked with libbfd,
+libopcodes, libiberty, and libmmalloc.
+
+@heading Acknowledgments
+
+Essential contributions to this design were made by Stu Grossman, Jim
+Kingdon, and Rich Pixley.
+
+@node Interpreter, Top Level, Overview, Top
+@comment node-name, next, previous, up
+@chapter Libgdb is an Interpreter Based Server
+@cindex interpreter
+@cindex server
+
+To understand libgdb, it is necessary to understand how the library is
+structured. Historically, GDB is written as a small interpreter for a
+simple command language. The commands of the language perform useful
+debugging functions.
+
+Libgdb is built from GDB by turning the interpreter into a debugging
+server. The server reads debugging commands from any source and
+interprets them, directing the output arbitrarily.
+
+In addition to changing GDB from a tty-based program to a server, a
+number of new GDB commands have been added to make the server more
+useful for a program with a graphic interface.
+
+Finally, libgdb includes provisions for asynchronous processing within
+the application.
+
+Most operations that can be carried out with libgdb involve the GDB
+command interpreter. The usual mode of operation is that the operation
+is expressed as a string of GDB commands, which the interpreter is then
+invoked to carry out. The output from commands executed in this manner
+can be redirected in a variety of useful ways for further processing by
+the application.
+
+The command interpreter provides an extensive system of hooks so an
+application can monitor any aspect of the debugging library's state. An
+application can set its own breakpoints and attach commands and
+conditions to those. It is possible to attach hooks to any debugger
+command; the hooks are invoked whenever that command is about to be
+invoked. By means of these, the displays of a graphical interface can
+be kept fully up to date at all times.
+
+We show you how to define new primitives in the command language. By
+defining new primitives and using them in breakpoint scripts and command
+hooks, an application can schedule the execution of arbitrary C-code at
+almost any point of interest in the operation of libgdb.
+
+We show you how to define new GDB convenience variables for which your
+code computes a value on demand. Referring to such variables in a
+breakpoint condition is a convenient way to conditionalize breakpoints
+in novel ways.
+
+To summarize: in libgdb, the gdb command language is turned into a
+debugging server. The server takes commands as input, and the server's
+output is redirectable. An application uses libgdb by formatting
+debugging commands and invoking the interpreter. The application might
+maintain breakpoints, watchpoints and many kinds of hooks. An application
+can define new primitives for the interpreter.
+
+@node Top Level, I/O, Interpreter, Top
+@chapter You Provide the Top Level for the Libgdb Command Interpreter
+@cindex {top level}
+
+When you use libgdb, your code is providing a @dfn{top level} for the
+command language interpreter. The top level is significant because it
+provides commands for the the interpreter to execute. In addition, the
+top level is responsible for handling some kinds of errors, and
+performing certain cleanup operations on behalf of the interpreter.
+
+@heading Initialization
+
+Before calling any other libgdb functions, call this:
+
+@deftypefun void gdb_init (void)
+Perform one-time initialization for libgdb.
+@end deftypefun
+
+An application may wish to evaluate specific gdb commands as part of its
+own initialization. The details of how this can be accomplished are
+explained below.
+
+@heading The Top-Level Loop
+
+There is a strong presumption in libgdb that the application has
+the form of a loop. Here is what such a loop might look like:
+
+@example
+while (gdb_still_going ())
+ @{
+ if (!GDB_TOP_LEVEL ())
+ @{
+ char * command;
+ gdb_start_top_loop ();
+ command = process_events ();
+ gdb_execute_command (command);
+ gdb_finish_top_loop ();
+ @}
+ @}
+@end example
+
+The function @code{gdb_still_going} returns 1 until the gdb command
+`quit' is run.
+
+The macro @code{GDB_TOP_LEVEL} invokes setjmp to set the top level error
+handler. When a command results in an error, the interpreter exits with
+a longjmp. There is nothing special libgdb requires of the top level
+error handler other than it be present and that it restart the top level
+loop. Errors are explained in detail in a later chapter.
+
+Each time through the top level loop two important things happen: a
+debugger command is constructed on the basis of user input, and the
+interpreter is invoked to execute that command. In the sample code, the
+call to the imaginary function @code{process_events} represents the
+point at which a graphical interface should read input events until
+ready to execute a debugger command. The call to
+@code{gdb_execute_command} invokes the command interpreter (what happens
+to the output from the command will be explained later).
+
+Libgdb manages some resources using the top-level loop. The primary
+reason for this is error-handling: even if a command terminates with an
+error, it may already have allocated resources which need to be freed.
+The freeing of such resources takes place at the top-level, regardless
+of how the the command exits. The calls to @code{gdb_start_top_loop}
+and @code{gdb_finish_top_loop} let libgdb know when it is safe to
+perform operations associated with these resources.
+
+@heading Breakpoint Commands
+
+Breakpoint commands are scripts of GDB operations associated with
+particular breakpoints. When a breakpoint is reached, its associated
+commands are executed.
+
+Breakpoint commands are invoked by the libgdb function
+@code{gdb_finish_top_loop}.
+
+Notice that if control returns to the top-level error handler, the
+execution of breakpoint commands is bypassed. This can happen as a
+result of errors during either @code{gdb_execute_command} or
+@code{gdb_finish_top_loop}.
+
+@heading Application Initialization
+
+Sometimes it is inconvenient to execute commands via a command loop for
+example, the commands an application uses to initialize itself. An
+alternative to @code{execute_command} is @code{execute_catching_errors}.
+When @code{execute_catching_errors} is used, no top level error handler
+need be in effect, and it is not necessary to call
+@code{gdb_start_top_loop} or @code{gdb_finish_top_loop}.
+
+
+@heading Cleanup
+
+The debugger command ``quit'' performs all necessary cleanup for libgdb.
+After it has done so, it changes the return value of
+@code{gdb_still_going} to 0 and returns to the top level error handler.
+
+
+@node I/O, Invoking, Top Level, Top
+@comment node-name, next, previous, up
+@chapter How the Server's I/O Can be Used
+@cindex I/O
+
+In the last chapter it was pointed out that a libgdb application is
+responsible for providing commands for the interpreter to execute.
+However some commands require further input (for example, the ``quit''
+command might ask for confirmation). Almost all commands produce output
+of some kind. The purpose of this section is to explain how libgdb
+performs its I/O, and how an application can take advantage of
+this.
+
+
+@heading I/O Vectors
+
+Libgdb has no fixed strategy for I/O. Instead, all operations are
+performed by functions called via structures of function pointers.
+Applications supply theses structures and can change them at any
+time.
+
+@deftp Type {struct gdb_input_vector}
+@deftpx Type {struct gdb_output_vector}
+These structures contain a set of function pointers. Each function
+determines how a particular type of i/o is performed. The details of
+these strucutres are explained below.
+
+The application allocates these structures, initializes them to all bits
+zero, fills in the function pointers, and then registers names for them
+them with libgdb.
+@end deftp
+
+@deftypefun void gdb_name_input_vector (@var{name}, @var{vec})
+@deftypefunx void gdb_remove_input_vector (@var{name}, @var{vec})
+@deftypefunx void gdb_name_output_vector (@var{name}, @var{vec})
+@deftypefunx void gdb_remove_input_vector (@var{name}, @var{vec})
+@example
+ char * @var{name};
+ struct gdb_output_vector * @var{vec};
+@end example
+These functions are used to give and remove names to i/o vectors. Note
+that if a name is used twice, the most recent definition applies.
+@end deftypefun
+
+
+
+@subheading Output
+
+An output vector is a structure with at least these fields:
+
+@example
+struct gdb_output_vector
+@{
+ /* output */
+ void (*put_string) (struct gdb_output_vector *, char * str);
+@}
+@end example
+
+Use the function @code{memset} or something equivalent to initialize an
+output vector to all bits zero. Then fill in the function pointer with
+your function.
+
+A debugger command can produce three kinds of output: error messages
+(such as when trying to delete a non-existent breakpoint), informational
+messages (such as the notification printed when a breakpoint is hit),
+and the output specifically requested by a command (for example, the
+value printed by the ``print'' command). At any given time, then,
+libgdb has three output vectors. These are called the @dfn{error},
+@dfn{info}, @dfn{value} vector respectively.
+
+@subheading Input
+
+@example
+struct gdb_input_vector
+@{
+ int (*query) (struct gdb_input_vector *,
+ char * prompt,
+ int quit_allowed);
+ int * (*selection) (struct gdb_input_vector *,
+ char * prompt,
+ char ** choices);
+ char * (*read_string) (struct gdb_input_vector *,
+ char * prompt);
+ char ** (*read_strings) (struct gdb_input_vector *,
+ char * prompt);
+@}
+@end example
+
+Use the function @code{memset} or something equivalent to initialize an
+input vector to all bits zero. Then fill in the function pointers with
+your functions.
+
+There are four kinds of input requests explicitly made by libgdb.
+
+A @dfn{query} is a yes or no question. The user can respond to a query
+with an affirmative or negative answer, or by telling gdb to abort the
+command (in some cases an abort is not permitted). Query should return
+'y' or 'n' or 0 to abort.
+
+A @dfn{selection} is a list of options from which the user selects a subset.
+Selections should return a NULL terminated array of integers, which are
+indexes into the array of choices. It can return NULL instead to abort
+the command. The array returned by this function will be passed to
+@code{free} by libgdb.
+
+A @dfn{read_string} asks the user to supply an arbitrary string. It may
+return NULL to abort the command. The string returned by @code{read_string}
+should be allocated by @code{malloc}; it will be freed by libgdb.
+
+A @dfn{read_strings} asks the user to supply multiple lines of input
+(for example, the body of a command created using `define'). It, too,
+may return NULL to abort. The array and the strings returned by this
+function will be freed by libgdb.
+
+@heading I/O Redirection from the Application Top-Level
+
+@deftypefun struct gdb_io_vecs gdb_set_io (struct gdb_io_vecs *)
+@example
+
+struct gdb_io_vecs
+@{
+ struct gdb_input_vector * input;
+ struct gdb_output_vector * error;
+ struct gdb_output_vector * info;
+ struct gdb_output_vector * value;
+@}
+@end example
+
+This establishes a new set of i/o vectors, and returns the old setting.
+Any of the pointers in this structure may be NULL, indicating that the
+current value should be used.
+
+This function is useful for setting up i/o vectors before any libgdb
+commands have been invoked (hence before any input or output has taken
+place).
+@end deftypefun
+
+It is explained in a later chapter how to redirect output temporarily.
+(@xref{Invoking}.)
+
+@heading I/O Redirection in Debugger Commands
+
+A libgdb application creates input and output vectors and assigns them names.
+Which input and output vectors are used by libgdb is established by
+executing these debugger commands:
+
+@defun {set input-vector} name
+@defunx {set error-output-vector} name
+@defunx {set info-output-vector} name
+@defunx {set value-output-vector} name
+Choose an I/O vector by name.
+@end defun
+
+
+A few debugger commands are for use only within commands defined using
+the debugger command `define' (they have no effect at other times).
+These commands exist so that an application can maintain hooks which
+redirect output without affecting the global I/O vectors.
+
+@defun with-input-vector name
+@defunx with-error-output-vector name
+@defunx with-info-output-vector name
+@defunx with-value-output-vector name
+Set an I/O vector, but only temporarily. The setting has effect only
+within the command definition in which it occurs.
+@end defun
+
+
+@heading Initial Conditions
+
+When libgdb is initialized, a set of default I/O vectors is put in
+place. The default vectors are called @code{default-input-vector},
+@code{default-output-vector}, &c.
+
+The default query function always returns `y'. Other input functions
+always abort. The default output functions discard output silently.
+
+
+@node Invoking, Defining Commands, I/O, Top
+@chapter Invoking the Interpreter, Executing Commands
+@cindex {executing commands}
+@cindex {invoking the interpreter}
+
+This section introduces the libgdb functions which invoke the command
+interpreter.
+
+@deftypefun void gdb_execute_command (@var{command})
+@example
+char * @var{command};
+@end example
+Interpret the argument debugger command. An error handler must be set
+when this function is called. (@xref{Top Level}.)
+@end deftypefun
+
+It is possible to override the current I/O vectors for the duration of a
+single command:
+
+@deftypefun void gdb_execute_with_io (@var{command}, @var{vecs})
+@example
+char * @var{command};
+struct gdb_io_vecs * @var{vecs};
+
+struct gdb_io_vecs
+@{
+ struct gdb_input_vector * input;
+ struct gdb_output_vector * error;
+ struct gdb_output_vector * info;
+ struct gdb_output_vector * value;
+@}
+@end example
+
+Execute @var{command}, temporarily using the i/o vectors in @var{vecs}.
+
+Any of the vectors may be NULL, indicating that the current value should
+be used. An error handler must be in place when this function is used.
+@end deftypefun
+
+@deftypefun {struct gdb_str_output} gdb_execute_for_strings (@var{cmd})
+@example
+char * cmd;
+@end example
+@deftypefunx {struct gdb_str_output} gdb_execute_for_strings2 (@var{cmd}, @var{input})
+@example
+char * cmd;
+struct gdb_input_vector * input;
+@end example
+@page
+@example
+struct gdb_str_output
+@{
+ char * error;
+ char * info;
+ char * value;
+@};
+@end example
+
+Execute @var{cmd}, collecting its output as strings. If no error
+occurs, all three strings will be present in the structure, the
+empty-string rather than NULL standing for no output of a particular
+kind.
+
+If the command aborts with an error, then the @code{value} field will be
+NULL, though the other two strings will be present.
+
+In all cases, the strings returned are allocated by malloc and should be
+freed by the caller.
+
+The first form listed uses the current input vector, but overrides the
+current output vector. The second form additionally allows the input
+vector to be overridden.
+
+This function does not require that an error handler be installed.
+@end deftypefun
+
+@deftypefun void execute_catching_errors (@var{command})
+@example
+char * @var{command};
+@end example
+Like @code{execute_command} except that no error handler is required.
+@end deftypefun
+
+@deftypefun void execute_with_text (@var{command}, @var{text})
+@example
+char * @var{command};
+char ** @var{text};
+@end example
+Like @code{execute_catching_errors}, except that the input vector is
+overridden. The new input vector handles only calls to @code{query} (by
+returning 'y') and calls to @code{read_strings} by returning a copy of
+@var{text} and the strings it points to.
+
+This form of execute_command is useful for commands like @code{define},
+@code{document}, and @code{commands}.
+@end deftypefun
+
+
+
+@node Defining Commands, Variables, Invoking, Top
+@comment node-name, next, previous, up
+@chapter How New Commands are Created
+@cindex {commands, defining}
+
+Applications are, of course, free to take advantage of the existing GDB
+macro definition capability (the @code{define} and @code{document}
+functions).
+
+In addition, an application can add new primitives to the GDB command
+language.
+
+@deftypefun void gdb_define_app_command (@var{name}, @var{fn}, @var{doc})
+@example
+char * @var{name};
+gdb_cmd_fn @var{fn};
+char * @var{doc};
+
+typedef void (*gdb_cmd_fn) (char * args);
+@end example
+
+Create a new command call @var{name}. The new command is in the
+@code{application} help class. When invoked, the command-line arguments
+to the command are passed as a single string.
+
+Calling this function twice with the same name replaces an earlier
+definition, but application commands can not replace builtin commands of
+the same name.
+
+The documentation string of the command is set to a copy the string
+@var{doc}.
+@end deftypefun
+
+@node Variables, Asynchronous, Defining Commands, Top
+@comment node-name, next, previous, up
+@chapter How Builtin Variables are Defined
+@cindex {variables, defining}
+
+Convenience variables provide a way for values maintained by libgdb to
+be referenced in expressions (e.g. @code{$bpnum}). Libgdb includes a
+means by which the application can define new, integer valued
+convenience variables:
+@page
+@deftypefun void gdb_define_int_var (@var{name}, @var{fn}, @var{fn_arg})
+@example
+char * @var{name};
+int (*@var{fn}) (void *);
+void * @var{fn_arg};
+@end example
+This function defines (or undefines) a convenience variable called @var{name}.
+If @var{fn} is NULL, the variable becomes undefined. Otherwise,
+@var{fn} is a function which, when passed @var{fn_arg} returns the value
+of the newly defined variable.
+
+No libgdb functions should be called by @var{fn}.
+@end deftypefun
+
+One use for this function is to create breakpoint conditions computed in
+novel ways. This is done by defining a convenience variable and
+referring to that variable in a breakpoint condition expression.
+
+
+@node Asynchronous, Commands, Variables, Top
+@chapter Scheduling Asynchronous Computations
+@cindex asynchronous
+
+
+A running libgdb function can take a long time. Libgdb includes a hook
+so that an application can run intermittently during long debugger
+operations.
+
+@deftypefun void gdb_set_poll_fn (@var{fn}, @var{fn_arg})
+@example
+void (*@var{fn})(void * fn_arg, int (*gdb_poll)());
+void * @var{fn_arg};
+@end example
+Arrange to call @var{fn} periodically during lengthy debugger operations.
+If @var{fn} is NULL, polling is turned off. @var{fn} should take two
+arguments: an opaque pointer passed as @var{fn_arg} to
+@code{gdb_set_poll_fn}, and a function pointer. The function pointer
+passed to @var{fn} is provided by libgdb and points to a function that
+returns 0 when the poll function should return. That is, when
+@code{(*gdb_poll)()} returns 0, libgdb is ready to continue @var{fn}
+should return quickly.
+
+It is possible that @code{(*gdb_poll)()} will return 0 the first time it
+is called, so it is reasonable for an application to do minimal processing
+before checking whether to return.
+
+No libgdb functions should be called from an application's poll function,
+with one exception: @code{gdb_request_quit}.
+@end deftypefun
+
+
+@deftypefun void gdb_request_quit (void)
+This function, if called from a poll function, requests that the
+currently executing libgdb command be interrupted as soon as possible,
+and that control be returned to the top-level via an error.
+
+The quit is not immediate. It will not occur until at least after the
+application's poll function returns.
+@end deftypefun
+
+@node Commands, Top, Asynchronous, Top
+@comment node-name, next, previous, up
+@chapter Debugger Commands for Libgdb Applications
+
+The debugger commands available to libgdb applications are the same commands
+available interactively via GDB. This section is an overview of the
+commands newly created as part of libgdb.
+
+This section is not by any means a complete reference to the GDB command
+language. See the GDB manual for such a reference.
+
+@menu
+* Command Hooks:: Setting Hooks to Execute With Debugger Commands.
+* View Commands:: View Commands Mirror Show Commands
+* Breakpoints:: The Application Can Have Its Own Breakpoints
+@end menu
+
+@node Command Hooks, View Commands, Commands, Commands
+@comment node-name, next, previous, up
+@section Setting Hooks to Execute With Debugger Commands.
+
+Debugger commands support hooks. A command hook is executed just before
+the interpreter invokes the hooked command.
+
+There are two hooks allowed for every command. By convention, one hook
+is for use by users, the other is for use by the application.
+
+A user hook is created for a command XYZZY by using
+@code{define-command} to create a command called @code{hook-XYZZY}.
+
+An application hook is created for a command XYZZY by using
+@code{define-command} to create a command called @code{apphook-XYZZY}.
+
+Application hooks are useful for interfaces which wish to continuously
+monitor certain aspects of debugger state. The application can set a
+hook on all commands that might modify the watched state. When the hook
+is executed, it can use i/o redirection to notify parts of the
+application that previous data may be out of date. After the top-level loop
+resumes, the application can recompute any values that may have changed.
+(@xref{I/O}.)
+
+@node View Commands, Breakpoints, Command Hooks, Commands
+@comment node-name, next, previous, up
+@section View Commands Mirror Show Commands
+
+The GDB command language contains many @code{set} and @code{show}
+commands. These commands are used to modify or examine parameters to
+the debugger.
+
+It is difficult to get the current state of a parameter from the
+@code{show} command because @code{show} is very verbose.
+
+@example
+(gdb) show check type
+Type checking is "auto; currently off".
+(gdb) show width
+Number of characters gdb thinks are in a line is 80.
+@end example
+
+For every @code{show} command, libgdb includes a @code{view} command.
+@code{view} is like @code{show} without the verbose commentary:
+
+@example
+(gdb) view check type
+auto; currently off
+(gdb) view width
+80
+@end example
+
+(The precise format of the ouput from @code{view} is subject to change.
+In particular, @code{view} may one-day print values which can be used as
+arguments to the corresponding @code{set} command.)
+
+@node Breakpoints, Structured Output, View Commands, Commands
+@comment node-name, next, previous, up
+@section The Application Can Have Its Own Breakpoints
+
+The GDB breakpoint commands were written with a strong presumption that
+all breakpoints are managed by a human user. Therefore, the command
+language contains commands like `delete' which affect all breakpoints
+without discrimination.
+
+In libgdb, there is added support for breakpoints and watchpoints which
+are set by the application and which should not be affected by ordinary,
+indiscriminate commands. These are called @dfn{protected} breakpoints.
+
+@deffn {Debugger Command} break-protected ...
+@deffnx {Debugger Command} watch-protected ...
+These work like @code{break} and @code{watch} except that the resulting
+breakpoint is given a negative number. Negative numbered breakpoints do
+not appear in the output of @code{info breakpoints} but do in that of
+@code{info all-breakpoints}. Negative numbered breakpoints are not
+affected by commands which ordinarily affect `all' breakpoints (e.g.
+@code{delete} with no arguments).
+
+Note that libgdb itself creates protected breakpoints, so programs
+should not rely on being able to allocate particular protected
+breakpoint numbers for themselves.
+@end deffn
+
+More than one breakpoint may be set at a given location. Libgdb adds
+the concept of @dfn{priority} to breakpoints. A priority is an integer,
+assigned to each breakpoint. When a breakpoint is reached, the
+conditions of all breakpoints at the same location are evaluated in
+order of ascending priority. When breakpoint commands are executed,
+they are also executed in ascending priority (until all have been
+executed, an error occurs, or one set of commands continues the
+target).
+
+@deffn {Debugger Command} priority n bplist
+Set the priority for breakpoints @var{bplist} to @var{n}.
+By default, breakpoints are assigned a priority of zero.
+@end deffn
+
+@node Structured Output, Commands, Breakpoints, Commands
+@comment node-name, next, previous, up
+@section Structured Output, The @code{Explain} Command
+
+(This section may be subject to considerable revision.)
+
+When GDB prints a the value of an expression, the printed representation
+contains information that can be usefully fed back into future commands
+and expressions. For example,
+
+@example
+(gdb) print foo
+$16 = @{v = 0x38ae0, v_length = 40@}
+@end example
+
+On the basis of this output, a user knows, for example, that
+@code{$16.v} refers to a pointer valued @code{0x38ae0}
+
+A new output command helps to make information like this available to
+the application.
+
+@deffn {Debugger Command} explain expression
+@deffnx {Debugger Command} explain /format expression
+Print the value of @var{expression} in the manner of the @code{print}
+command, but embed that output in a list syntax containing information
+about the structure of the output.
+@end deffn
+
+As an example, @code{explain argv} might produce this output:
+
+@example
+(exp-attribute
+ ((expression "$19")
+ (type "char **")
+ (address "48560")
+ (deref-expression "*$19"))
+ "$19 = 0x3800\n")
+@end example
+
+The syntax of output from @code{explain} is:
+
+@example
+<explanation> := <quoted-string>
+ | (exp-concat <explanation> <explanation>*)
+ | (exp-attribute <property-list> <explanation>)
+
+<property-list> := ( <property-pair>* )
+
+<property-pair> := ( <property-name> <quoted-string> )
+@end example
+
+The string-concatenation of all of the @code{<quoted-string>} (except
+those in property lists) yields the output generated by the equivalent
+@code{print} command. Quoted strings may contain quotes and backslashes
+if they are escaped by backslash. "\n" in a quoted string stands for
+newline; unescaped newlines do not occur within the strings output by
+@code{explain}.
+
+Property names are made up of alphabetic characters, dashes, and
+underscores.
+
+The set of properties is open-ended. As GDB acquires support for new
+source languages and other new capabilities, new property types may be
+added to the output of this command. Future commands may offer
+applications some selectivity concerning which properties are reported.
+
+The initial set of properties defined includes:
+
+@itemize @bullet
+@item @code{expression}
+
+This is an expression, such as @code{$42} or @code{$42.x}. The
+expression can be used to refer to the value printed in the attributed
+part of the string.
+
+@item @code{type}
+
+This is a user-readable name for the type of the attributed value.
+
+@item @code{address}
+
+If the value is stored in a target register, this is a register number.
+If the value is stored in a GDB convenience variable, this is an integer
+that is unique among all the convenience variables. Otherwise, this is
+the address in the target where the value is stored.
+
+@item @code{deref-expression}
+
+If the attributed value is a pointer type, this is an expression that
+refers to the dereferenced value.
+@end itemize
+
+Here is a larger example, using the same object passed to @code{print}
+in an earlier example of this section.
+
+@example
+(gdb) explain foo
+(exp-attribute
+ ( (expression "$16")
+ (type "struct bytecode_vector")
+ (address 14336) )
+ (exp-concat
+ "$16 = @{"
+ (exp-attribute
+ ( (expression "$16.v")
+ (type "char *")
+ (address 14336)
+ (deref-expression "*$16.v") )
+ "v = 0x38ae0")
+ (exp-attribute
+ ( (expression "$16.v_length")
+ (type "int")
+ (address 14340) )
+ ", v_length = 40")
+ "@}\n"))
+@end example
+
+It is undefined how libgdb will indent these lines of output or
+where newlines will be included.
+
+@bye
diff --git a/gdb/doc/lpsrc.sed b/gdb/doc/lpsrc.sed
new file mode 100644
index 00000000000..1c7af4aaf48
--- /dev/null
+++ b/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/gdb/doc/psrc.sed b/gdb/doc/psrc.sed
new file mode 100644
index 00000000000..9bb557eae21
--- /dev/null
+++ b/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/gdb/doc/refcard.tex b/gdb/doc/refcard.tex
new file mode 100644
index 00000000000..d2b72de04d2
--- /dev/null
+++ b/gdb/doc/refcard.tex
@@ -0,0 +1,645 @@
+%%%%%%%%%%%%%%%% gdb-refcard.tex %%%%%%%%%%%%%%%%
+
+%This file is TeX source for a reference card describing GDB, the GNU debugger.
+%Copyright (C) 1991, 1992, 1993, 1998 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 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 can find a copy of the GNU General Public License at the URL
+%http://www.gnu.org/copyleft/gpl.html; or write to the Free Software
+%Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+%
+%You can contact the maintainer at: doc@cygnus.com
+%
+% Documentation Department
+% Cygnus Solutions
+% 1325 Chesapeake Terrace
+% Sunnyvale, CA 94089 USA
+%
+% +1 800 CYGNUS-1
+%
+%
+%
+% 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 env&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 1998 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 event}&break at {\it event}, which may be {\tt catch}, {\tt throw},
+{\tt exec}, {\tt fork}, {\tt vfork}, {\tt load}, or {\tt unload}.\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
+\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 conv&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 complaint {\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, '92, '93, '98 Free Software Foundation, Inc.}
+\centerline{Roland H. Pesch}
+\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. Improvements can be sent to bug-gdb@gnu.org.}
+
+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/gdb/doc/remote.texi b/gdb/doc/remote.texi
new file mode 100644
index 00000000000..816b65837de
--- /dev/null
+++ b/gdb/doc/remote.texi
@@ -0,0 +1,1708 @@
+@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 i386-stub.c
+@kindex i386-stub.c
+@cindex Intel
+@cindex i386
+For Intel 386 and compatible architectures.
+
+@item m68k-stub.c
+@kindex m68k-stub.c
+@cindex Motorola 680x0
+@cindex m680x0
+For Motorola 680x0 architectures.
+
+@item sh-stub.c
+@kindex sh-stub.c
+@cindex Hitachi
+@cindex SH
+For Hitachi SH architectures.
+
+@item sparc-stub.c
+@kindex sparc-stub.c
+@cindex Sparc
+For @sc{sparc} architectures.
+
+@item sparcl-stub.c
+@kindex sparcl-stub.c
+@cindex Fujitsu
+@cindex SparcLite
+For Fujitsu @sc{sparclite} 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
+@ifset GDBSERVE
+* NetWare:: Using the `gdbserve.nlm' 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 transfers 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 gets 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.
+
+First of all you need to tell the stub how to communicate with the
+serial port.
+
+@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.
+@end table
+
+@cindex control C, and remote debugging
+@cindex interrupting remote targets
+If you want @value{GDBN} to be able to stop your program while it is
+running, you need to use an interrupt-driven serial driver, and arrange
+for it to stop when it receives a @code{^C} (@samp{\003}, the control-C
+character). That is the character which @value{GDBN} uses to tell the
+remote system to stop.
+
+Getting the debugging target to return the proper status to @value{GDBN}
+probably requires changes to the standard stub; one quick and dirty way
+is to just execute a breakpoint instruction (the ``dirty'' part is that
+@value{GDBN} reports a @code{SIGTRAP} instead of a @code{SIGINT}).
+
+Other routines you need to supply are:
+
+@table @code
+@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,
+and so on) 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 interrup themselves without
+help from @code{exceptionHandler}.
+
+@item void flush_i_cache()
+@kindex flush_i_cache
+(sparc and sparclite only) 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 varies 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 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 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 some of the commands currently supported (for a complete list of
+commands, look in @file{gdb/remote.c.}):
+
+@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}.
+
+@need 500
+@item c
+@itemx c@var{addr}
+Resume execution at the current address (or at @var{addr} if supplied).
+
+@need 500
+@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.
+
+@item T
+Allows the remote stub to send only the registers that @value{GDBN} needs
+to make a quick decision about single-stepping or conditional breakpoints.
+This eliminates the need to fetch the entire register set for each instruction
+being stepped through.
+
+@value{GDBN} now implements a write-through cache for registers and only
+re-reads the registers if the target has run.
+@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} shows 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
+@value{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 @value{GDBN}, so you may be able to get
+started more quickly on a new system by using @code{gdbserver}.
+Finally, if you develop code for real-time systems, you may find that
+the tradeoffs involved in real-time operation make it more convenient to
+do as much development work as possible on another system, for example
+by cross-compiling. You can use @code{gdbserver} to make a similar
+choice for debugging.
+
+@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 machine,
+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{GDBN};
+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 (for example, @code{23} is
+reserved for @code{telnet}).@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 @value{GDBN} host machine,
+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 @w{@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 descriptor 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 @w{@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
+
+@ifset GDBSERVE
+@node NetWare
+@subsubsection Using the @code{gdbserve.nlm} program
+
+@kindex gdbserve.nlm
+@code{gdbserve.nlm} is a control program for NetWare systems, which
+allows you to connect your program with a remote @value{GDBN} via
+@code{target remote}.
+
+@value{GDBN} and @code{gdbserve.nlm} communicate via a serial line,
+using the standard @value{GDBN} remote serial protocol.
+
+@table @emph
+@item On the target machine,
+you need to have a copy of the program you want to debug.
+@code{gdbserve.nlm} 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{GDBN}; the name of your program; and the arguments for your
+program. The syntax is:
+
+@smallexample
+load gdbserve [ BOARD=@var{board} ] [ PORT=@var{port} ]
+ [ BAUD=@var{baud} ] @var{program} [ @var{args} @dots{} ]
+@end smallexample
+
+@var{board} and @var{port} specify the serial line; @var{baud} specifies
+the baud rate used by the connection. @var{port} and @var{node} default
+to 0, @var{baud} defaults to 9600 bps.
+
+For example, to debug Emacs with the argument @samp{foo.txt}and
+communicate with @value{GDBN} over serial port number 2 or board 1
+using a 19200 bps connection:
+
+@smallexample
+load gdbserve BOARD=1 PORT=2 BAUD=19200 emacs foo.txt
+@end smallexample
+
+@item On the @value{GDBN} host machine,
+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 @w{@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{gdbserve.nlm}. Its
+argument is a device name (usually a serial device, like
+@file{/dev/ttyb}). For example:
+
+@smallexample
+(@value{GDBP}) target remote /dev/ttyb
+@end smallexample
+
+@noindent
+communications with the server via serial line @file{/dev/ttyb}.
+@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 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 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? ---doc@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... ---doc@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} keeps
+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} does @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
+
+@need 500
+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). ---doc@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} reads 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 gets 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.)
+
+@table @code
+@item VxWorks-timeout @var{args}
+@kindex vxworks-timeout
+All VxWorks-based targets now support the option @code{vxworks-timeout}.
+This option is set by the user, and @var{args} represents the number of
+seconds @value{GDBN} waits for responses to rpc's. You might use this if
+your VxWorks target is a slow software simulator or is on the far side
+of a thin network line.
+@end table
+
+The following information on connecting to VxWorks was current when
+this manual was produced; newer releases of VxWorks may use revised
+procedures.
+
+@kindex INCLUDE_RDB
+To use @value{GDBN} with VxWorks, you must rebuild your VxWorks kernel
+to include the remote debugging interface routines in the VxWorks
+library @file{rdb.a}. To do this, define @code{INCLUDE_RDB} in the
+VxWorks configuration file @file{configAll.h} and rebuild your VxWorks
+kernel. The resulting kernel contains @file{rdb.a}, and spawns 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 @file{rdb.a} 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
+
+@need 750
+@value{GDBN} displays messages like these:
+
+@smallexample
+Attaching remote machine across net...
+Connected to tt.
+@end smallexample
+
+@need 1000
+@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
+v
+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 makes @value{GDBN} 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. Running tasks are suspended at
+the time of attachment.
+@end ifset
+
+@ifset SPARCLET
+@node Sparclet Remote
+@subsection @value{GDBN} and Sparclet
+@cindex Sparclet
+
+@value{GDBN} enables developers to debug tasks running on
+Sparclet targets from a Unix host.
+@value{GDBN} uses code that runs on
+both the Unix host and on the Sparclet target. The program
+@code{gdb} is installed and executed on the Unix host.
+
+@table @code
+@item timeout @var{args}
+@kindex remotetimeout
+@value{GDBN} now supports the option @code{remotetimeout}.
+This option is set by the user, and @var{args} represents the number of
+seconds @value{GDBN} waits for responses.
+@end table
+
+@kindex Compiling
+When compiling for debugging, include the options "-g" to get debug
+information and "-Ttext" to relocate the program to where you wish to
+load it on the target. You may also want to add the options "-n" or
+"-N" in order to reduce the size of the sections.
+
+@example
+sparclet-aout-gcc prog.c -Ttext 0x12010000 -g -o prog -N
+@end example
+
+You can use objdump to verify that the addresses are what you intended.
+
+@example
+sparclet-aout-objdump --headers --syms prog
+@end example
+
+@kindex Running
+Once you have 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{sparclet-aout-gdb}, depending on your installation).
+
+@value{GDBN} comes up showing the prompt:
+
+@example
+(gdbslet)
+@end example
+
+@menu
+* Sparclet File:: Setting the file to debug
+* Sparclet Connection:: Connecting to Sparclet
+* Sparclet Download:: Sparclet download
+* Sparclet Execution:: Running and debugging
+@end menu
+
+@node Sparclet File
+@subsubsection Setting file to debug
+
+The @value{GDBN} command @code{file} lets you choose with program to debug.
+
+@example
+(gdbslet) file prog
+@end example
+
+@need 1000
+@value{GDBN} then attempts to read the symbol table of @file{prog}.
+@value{GDBN} locates
+the file by searching the directories listed in the command search
+path.
+If the file was compiled with debug information (option "-g"), source
+files will be searched as well.
+@value{GDBN} locates
+the source files by searching the directories listed in the directory search
+path (@pxref{Environment, ,Your program's environment}).
+If it fails
+to find a file, it displays a message such as:
+
+@example
+prog: No such file or directory.
+@end example
+
+When this happens, add the appropriate directories to the search paths with
+the @value{GDBN} commands @code{path} and @code{dir}, and execute the
+@code{target} command again.
+
+@node Sparclet Connection
+@subsubsection Connecting to Sparclet
+
+The @value{GDBN} command @code{target} lets you connect to a Sparclet target.
+To connect to a target on serial port ``@code{ttya}'', type:
+
+@example
+(gdbslet) target sparclet /dev/ttya
+Remote target sparclet connected to /dev/ttya
+main () at ../prog.c:3
+@end example
+
+@need 750
+@value{GDBN} displays messages like these:
+
+@smallexample
+Connected to ttya.
+@end smallexample
+
+@node Sparclet Download
+@subsubsection Sparclet download
+
+@cindex download to Sparclet
+Once connected to the Sparclet target,
+you can use the @value{GDBN}
+@code{load} command to download the file from the host to the target.
+The file name and load offset should be given as arguments to the @code{load}
+command.
+Since the file format is aout, the program must be loaded to the starting
+address. You can use objdump to find out what this value is. The load
+offset is an offset which is added to the VMA (virtual memory address)
+of each of the file's sections.
+For instance, if the program
+@file{prog} was linked to text address 0x1201000, with data at 0x12010160
+and bss at 0x12010170, in @value{GDBN}, type:
+
+@example
+(gdbslet) load prog 0x12010000
+Loading section .text, size 0xdb0 vma 0x12010000
+@end example
+
+If the code is loaded at a different address then what the program was linked
+to, you may need to use the @code{section} and @code{add-symbol-file} commands
+to tell @value{GDBN} where to map the symbol table.
+
+@node Sparclet Execution
+@subsubsection Running and debugging
+
+@cindex running and debugging Sparclet programs
+You can now begin debugging the task using @value{GDBN}'s execution control
+commands, @code{b}, @code{step}, @code{run}, etc. See the @value{GDBN}
+manual for the list of commands.
+
+@example
+(gdbslet) b main
+Breakpoint 1 at 0x12010000: file prog.c, line 3.
+(gdbslet) run
+Starting program: prog
+Breakpoint 1, main (argc=1, argv=0xeffff21c) at prog.c:3
+3 char *symarg = 0;
+(gdbslet) step
+4 char *execarg = "hello!";
+(gdbslet)
+@end example
+
+@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, or @samp{target e7000}, the in-circuit
+emulator for the Hitachi SH and the Hitachi 300H. (@samp{target hms} 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).
+
+@ifclear H8EXCLUSIVE
+@c this is only for Unix hosts, not of interest to Hitachi
+@item
+what speed to use over the serial device.
+@end ifclear
+@end enumerate
+
+@menu
+* Hitachi Boards:: Connecting to Hitachi boards.
+* Hitachi ICE:: Using the E7000 In-Circuit Emulator.
+* Hitachi Special:: Special @value{GDBN} commands for Hitachi micros.
+@end menu
+
+@node Hitachi Boards
+@subsubsection Connecting to Hitachi boards
+
+@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
+C:\H8300\TEST> asynctsr 2
+C:\H8300\TEST> mode com2:9600,n,8,1,p
+
+Resident portion of MODE loaded
+
+COM2: 9600, n, 8, 1, p
+
+@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} sees the effect of a @sc{reset} on the
+development board as a ``normal exit'' of your program.
+@end ifset
+
+@node Hitachi ICE
+@subsubsection Using the E7000 in-circuit emulator
+
+@kindex target e7000
+You can use the E7000 in-circuit emulator to develop code for either the
+Hitachi SH or the H8/300H. Use one of these forms of the @samp{target
+e7000} command to connect @value{GDBN} to your E7000:
+
+@table @code
+@item target e7000 @var{port} @var{speed}
+Use this form if your E7000 is connected to a serial port. The
+@var{port} argument identifies what serial port to use (for example,
+@samp{com2}). The third argument is the line speed in bits per second
+(for example, @samp{9600}).
+
+@item target e7000 @var{hostname}
+If your E7000 is installed as a host on a TCP/IP network, you can just
+specify its hostname; @value{GDBN} uses @code{telnet} to connect.
+@end table
+
+@node Hitachi Special
+@subsubsection Special @value{GDBN} commands for Hitachi micros
+
+Some @value{GDBN} commands are available only on the H8/300 or the
+H8/500 configurations:
+
+@table @code
+@kindex set machine
+@kindex show machine
+@item set machine h8300
+@itemx set machine h8300h
+Condition @value{GDBN} for one of the two variants of the H8/300
+architecture with @samp{set machine}. You can use @samp{show machine}
+to check which variant is currently in effect.
+
+@kindex set memory @var{mod}
+@cindex memory models, H8/500
+@item set memory @var{mod}
+@itemx show memory
+Specify which H8/500 memory model (@var{mod}) you are using with
+@samp{set memory}; check which memory model is in effect with @samp{show
+memory}. The accepted values for @var{mod} are @code{small},
+@code{big}, @code{medium}, and @code{compact}.
+@end table
+
+@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}.
+
+@need 1000
+Use these @value{GDBN} commands to specify the connection to your target board:
+
+@table @code
+@item target mips @var{port}
+@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.
+
+For example, this sequence connects to the target board through a serial
+port, and loads and runs a program called @var{prog} through the
+debugger:
+
+@example
+host$ @value{GDBP} @var{prog}
+GDB is free software and @dots{}
+(gdb) target mips /dev/ttyb
+(gdb) load @var{prog}
+(gdb) run
+@end example
+
+@item target mips @var{hostname}:@var{portnumber}
+On some @value{GDBN} host configurations, you can specify a TCP
+connection (for instance, to a serial line managed by a terminal
+concentrator) instead of a serial port, using the syntax
+@samp{@var{hostname}:@var{portnumber}}.
+
+@item target pmon @var{port}
+@kindex target pmon @var{port}
+
+@item target ddb @var{port}
+@kindex target ddb @var{port}
+
+@item target lsi @var{port}
+@kindex target lsi @var{port}
+
+@end table
+
+
+@noindent
+@value{GDBN} also supports these special commands for MIPS targets:
+
+@table @code
+@item set processor @var{args}
+@itemx show processor
+@kindex set processor @var{args}
+@kindex show processor
+Use the @code{set processor} command to set the type of MIPS
+processor when you want to access processor-type-specific registers.
+For example, @code{set processor @var{r3041}} tells @value{GDBN}
+to use the CPO registers appropriate for the 3041 chip.
+Use the @code{show processor} command to see what MIPS processor @value{GDBN}
+is using. Use the @code{info reg} command to see what registers
+@value{GDBN} is using.
+
+@item set mipsfpu double
+@itemx set mipsfpu single
+@itemx set mipsfpu none
+@itemx show mipsfpu
+@kindex set mipsfpu
+@kindex show mipsfpu
+@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 none} (if you
+need this, you may wish to put the command 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. If you are using a floating point coprocessor
+with only single precision floating point support, as on the @sc{r4650}
+processor, use the command @samp{set mipsfpu single}. The default
+double precision floating point coprocessor may be selected using
+@samp{set mipsfpu double}.
+
+In previous versions the only choices were double precision or no
+floating point, so @samp{set mipsfpu on} will select double precision
+and @samp{set mipsfpu off} will select no floating point.
+
+As usual, you can inquire about the @code{mipsfpu} variable with
+@samp{show mipsfpu}.
+
+@item set remotedebug @var{n}
+@itemx show remotedebug
+@kindex set remotedebug
+@kindex show remotedebug
+@cindex @code{remotedebug}, MIPS protocol
+@cindex MIPS @code{remotedebug} 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 @code{1} using
+@samp{set remotedebug 1}, every packet is displayed. If you set it
+to @code{2}, every character is displayed. You can check the current value
+at any time with the command @samp{show remotedebug}.
+
+@item set timeout @var{seconds}
+@itemx set retransmit-timeout @var{seconds}
+@itemx show timeout
+@itemx show retransmit-timeout
+@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}.)
+
+The timeout set by @code{set timeout} does not apply when @value{GDBN}
+is waiting for your program to stop. In that case, @value{GDBN} waits
+forever because it has no way of knowing how long the program is going
+to run before stopping.
+@end table
+@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, simulators are available for ARM, D10V, D30V, FR30, H8/300,
+H8/500, i960, M32R, MIPS, MN10200, MN10300, PowerPC, SH, Sparc, V850,
+W65, and Z8000.
+@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 @var{args}
+@kindex sim
+@kindex target sim
+Debug programs on a simulated CPU. If the simulator supports setup
+options, specify them via @var{args}.
+@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}), the Z8000 simulator 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 suspends only after at least 5000
+simulated clock ticks.
+@end ifset
+
+@c need to add much more detail about sims!
diff --git a/gdb/doc/stabs.texinfo b/gdb/doc/stabs.texinfo
new file mode 100644
index 00000000000..a4f0bc93989
--- /dev/null
+++ b/gdb/doc/stabs.texinfo
@@ -0,0 +1,4019 @@
+\input texinfo
+@setfilename stabs.info
+
+@c @finalout
+
+@ifinfo
+@format
+START-INFO-DIR-ENTRY
+* Stabs: (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, 93, 94, 95, 97, 1998 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$} % 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, 93, 94, 95, 97, 1998 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:: Stabs specific to C++
+* 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
+* Stab Sections:: In some object file formats, stabs are
+ in sections.
+* 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
+Peter Kessler 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.
+
+@c FIXME: Need to document all OS9000 stuff in GDB; see all references
+@c to os9k_stabs in stabsread.c.
+
+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 explicitly 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; it can
+contain a pair of colons (@pxref{Nested Symbols}). @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. Also, the Lucid
+compiler will repeat @samp{@var{type-number}=} more than once if it
+wants to define several type numbers at once.
+
+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}.
+
+A @var{type-number} is often a single number. The GNU and Sun tools
+additionally permit a @var{type-number} to be a pair
+(@var{file-number},@var{filetype-number}) (the parentheses appear in the
+string, and serve to distinguish the two cases). The @var{file-number}
+is a number starting with 1 which is incremented for each seperate
+source file in the compilation (e.g., in C, each header file gets a
+different number). The @var{filetype-number} is a number starting with
+1 which is incremented for each new type defined in the file.
+(Separating the file number and the type number permits the
+@code{N_BINCL} optimization to succeed more often; see @ref{Include
+Files}).
+
+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 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.
+
+@item s@var{size}
+Size in bits of a variable of this type. This is fully supported by GDB
+4.11 and later.
+
+@item S
+Indicate that this type is a string instead of an array of characters,
+or a bitstring instead of a set. It doesn't change the layout of the
+data being represented, but does enable the debugger to know which type
+it is.
+@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 (or assemblers or linkers, I'm not sure which)
+cretinously limit the strings to about 80 characters, so compilers which
+must work with such systems need to split the @code{.stabs} directive
+into several @code{.stabs} directives. Each stab duplicates every field
+except the string field. The string field of every stab except the last
+is marked as continued with a backslash at the end (in the assembly code
+this may be written as a double backslash, depending on the assembler).
+Removing the backslashes and concatenating the string fields of each
+stab produces the original, long string. Just to be incompatible (or so
+they don't have to worry about what the assembler does with
+backslashes), AIX can use @samp{?} instead of backslash.
+
+@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::
+* Alternate Entry Points:: Entering procedures except at the beginning.
+@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. I'm not sure how XCOFF handles this.
+
+@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
+
+@findex C_FILE
+Instead of @code{N_SO} symbols, XCOFF uses a @code{.file} assembler
+directive which assembles to a @code{C_FILE} symbol; explaining this in
+detail is outside the scope of this document.
+
+@c FIXME: Exactly when should the empty N_SO be used? Why?
+If it is useful to indicate the end of a source file, this is done with
+an @code{N_SO} symbol with an empty string for the name. The value is
+the address of the end of the text section for the file. For some
+systems, there is no indication of the end of a source file, and you
+just need to figure it ended when you see an @code{N_SO} for a different
+source file, or a symbol ending in @code{.o} (which at least some
+linkers insert to mark the start of a new @code{.o} file).
+
+@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 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. @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 GNU linker and the Sun (both SunOS4 and Solaris) linker are the only
+ones which supports this feature.
+
+A linker which supports this feature will set the value of a
+@code{N_BINCL} symbol to the total of all the characters in the stabs
+strings included in the header file, omitting any file numbers. The
+value of an @code{N_EXCL} symbol is the same as the value of the
+@code{N_BINCL} symbol it replaces. This information can be used to
+match up @code{N_EXCL} and @code{N_BINCL} symbols which have the same
+filename. The @code{N_EINCL} value, and the values of the other and
+description fields for all three, appear to always be zero.
+
+@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 stabs in sections (@pxref{Stab Sections}), 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. On systems where non-stab symbols have
+leading underscores, the stabs will lack underscores and the debugger
+needs to know about the leading underscore to match up the stab and the
+non-stab symbol. 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).
+
+@findex C_FUN
+A function is represented by an @samp{F} symbol descriptor for a global
+(extern) function, and @samp{f} for a static (local) function. For
+a.out, the value of the symbol is the address of the start of the
+function; 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, or just absolute. See @ref{ELF Linker
+Relocation} for more information on linker relocation of stabs in ELF
+files. For XCOFF, the stab uses the @code{C_FUN} storage class and the
+value of the stab is meaningless; the address of the function can be
+found from the csect symbol (XTY_LD/XMC_PR).
+
+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.
+
+If functions can appear in different sections, then the debugger may not
+be able to find the end of a function. Recent versions of GCC will mark
+the end of a function with an @code{N_FUN} symbol with an empty string
+for the name. The value is the address of the end of the current
+function. Without such a symbol, there is no indication of the address
+of the end of a function, and you must assume that it ended at the
+starting address of the next function or at the end of the text section
+for the program.
+
+@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
+@c For GCC 2.5.8 or so stabs-in-coff, these are absolute instead of
+@c function relative (as documented below). But GDB has never been able
+@c to deal with that (it had wanted them to be relative to the file, but
+@c I just fixed that (between GDB 4.12 and 4.13)), so it is function
+@c relative just like ELF and SOM and the below documentation.
+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 stabs in sections (@pxref{Stab Sections}), 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.
+
+@findex .bb
+@findex .be
+@findex C_BLOCK
+For XCOFF, block scope is indicated with @code{C_BLOCK} symbols. If the
+name of the symbol is @samp{.bb}, then it is the beginning of the block;
+if the name of the symbol is @samp{.be}; it is the end of the block.
+
+@node Alternate Entry Points
+@section Alternate Entry Points
+
+@findex N_ENTRY
+@findex C_ENTRY
+Some languages, like Fortran, have the ability to enter procedures at
+some place other than the beginning. One can declare an alternate entry
+point. The @code{N_ENTRY} stab is for this; however, the Sun FORTRAN
+compiler doesn't use it. According to AIX documentation, only the name
+of a @code{C_ENTRY} stab is significant; the address of the alternate
+entry point comes from the corresponding external symbol. A previous
+revision of this document said that the value of an @code{N_ENTRY} stab
+was the address of the alternate entry point, but I don't know the
+source for that information.
+
+@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, for stack variables
+@findex C_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, or
+@code{C_LSYM} for XCOFF.
+
+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
+@findex C_GSYM
+@c FIXME: verify for sure that it really is C_GSYM on XCOFF
+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 (C_GSYM for XCOFF). 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.
+
+Some compilers, like GCC, output @code{N_GSYM} stabs only once, where
+the variable is defined. Other compilers, like SunOS4 /bin/cc, output a
+@code{N_GSYM} stab for each compilation unit which references the
+variable.
+
+@node Register Variables
+@section Register Variables
+
+@findex N_RSYM
+@findex C_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}
+(@code{C_RSYM} for XCOFF), 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. One exception: in XCOFF, IBM's
+xlc compiler always uses @samp{V}, and whether it is file scope or not
+is distinguished by whether the stab is located within a function.
+
+@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
+
+@findex C_STSYM
+@findex C_BSTAT
+@findex C_ESTAT
+In XCOFF files, the stab type need not indicate the section;
+@code{C_STSYM} can be used for all statics. Also, each static variable
+is enclosed in a static block. A @code{C_BSTAT} (emitted with a
+@samp{.bs} assembler directive) symbol begins the static block; its
+value is the symbol number of the csect symbol whose value is the
+address of the static block, its section is the section of the variables
+in that static block, and its name is @samp{.bs}. A @code{C_ESTAT}
+(emitted with a @samp{.es} assembler directive) symbol ends the static
+block; its name is @samp{.es} and its value and section are ignored.
+
+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{ELF Linker Relocation}.
+
+@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
+@findex C_PSYM
+Parameters passed on the stack use the symbol descriptor @samp{p} and
+the @code{N_PSYM} symbol type (or @code{C_PSYM} for XCOFF). 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 in XCOFF and @code{N_RSYM}
+is used otherwise. 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.
+
+If a parameter is passed as one type and converted to a smaller type by
+the prologue (for example, the parameter is declared as a @code{float},
+but the calling conventions specify that it is passed as a
+@code{double}), then GCC2 (sometimes) uses a pair of symbols. The first
+symbol uses symbol descriptor @samp{p} and the type which is passed.
+The second symbol has the type and location which the parameter actually
+has after the prologue. For example, suppose the following C code
+appears with no prototypes involved:
+
+@example
+void
+subr (f)
+ float f;
+@{
+@end example
+
+if @code{f} is passed as a double at stack offset 8, and the prologue
+converts it to a float in register number 0, then the stabs look like:
+
+@example
+.stabs "f:p13",160,0,3,8 # @r{160 is @code{N_PSYM}, here 13 is @code{double}}
+.stabs "f:r12",64,0,3,0 # @r{64 is @code{N_RSYM}, here 12 is @code{float}}
+@end example
+
+In both stabs 3 is the line number where @code{f} is declared
+(@pxref{Line Numbers}).
+
+@findex N_LSYM, for parameter
+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 or GDB). 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. GDB and GCC assume that zero is false,
+one is true, and other values have unspecified meaning. I hope this
+agrees with how the IBM tools use the type.
+
+@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?).
+
+@item -31
+@code{long long}, 64 bit signed integral type.
+
+@item -32
+@code{unsigned long long}, 64 bit unsigned integral type.
+
+@item -33
+@code{logical*8}, 64 bit unsigned integral type.
+
+@item -34
+@code{integer*8}, 64 bit signed integral type.
+@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}.
+
+In CHILL, if it is a bitstring instead of a set, also use the @samp{S}
+type attribute (@pxref{String Field}).
+
+@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{:}.
+If the name contains @samp{::} between a @samp{<} and @samp{>} pair (for
+C++ templates), such a @samp{::} does not end the name---only a single
+@samp{:} ends the name; see @ref{Nested Symbols}.
+
+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
+
+Languages, such as CHILL which have a string type which is basically
+just an array of characters use the @samp{S} type attribute
+(@pxref{String Field}).
+
+@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{;}. The fact that @var{value} is
+specified as an integer can cause problems if the value is large. GCC
+2.5.2 tries to output it in octal in that case with a leading zero,
+which is probably a good thing, although GDB 4.11 supports octal only in
+cases where decimal is perfectly good. Negative decimal values are
+supported by both GDB and dbx.
+
+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). Type attributes can be used to specify an enumeration type of
+another size for debuggers which support them; see @ref{String Field}.
+
+Enumeration types are unusual in that they define symbols for the
+enumeration values (@code{first}, @code{second}, and @code{third} in the
+above example), and even though these symbols are visible in the file as
+a whole (rather than being in a more local namespace like structure
+member names), they are defined in the type definition for the
+enumeration type rather than each having their own symbol. In order to
+be fast, GDB will only get symbols from such types (in its initial scan
+of the stabs) if the type is the first thing defined after a @samp{T} or
+@samp{t} symbol descriptor (the above example fulfills this
+requirement). If the type does not have a name, the compiler should
+emit it in a nameless stab (@pxref{String Field}); GCC does this.
+
+@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.
+
+If a field is a static member (this is a C++ feature in which a single
+variable appears to be a field of every structure of a given type) it
+still starts out with the field name, a colon, and the type, but then
+instead of a comma, bit position, comma, and bit size, there is a colon
+followed by the name of the variable which each such field refers to.
+
+If the structure has methods (a C++ feature), they follow the non-method
+fields; see @ref{Cplusplus}.
+
+@node Typedefs
+@section Giving a Type a Name
+
+@findex N_LSYM, for types
+@findex C_DECL, for types
+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). (The Sun
+documentation mentions using @code{N_GSYM} in some cases).
+
+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::
+* Stab Section Transformations:: For some object file formats,
+ 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 Stab Section Transformations
+@subsection Transformations of Stabs in separate sections
+
+For object file formats using stabs in separate sections (@pxref{Stab
+Sections}), 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{ELF Linker Relocation}). 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
+* Class Names:: C++ class names are both tags and typedefs.
+* Nested Symbols:: C++ symbol names can be within other types.
+* Basic Cplusplus Types::
+* Simple Classes::
+* Class Instance::
+* Methods:: Method definition
+* Method Type Descriptor:: The @samp{#} type descriptor
+* Member Type Descriptor:: The @samp{@@} type descriptor
+* Protections::
+* Method Modifiers::
+* Virtual Methods::
+* Inheritence::
+* Virtual Base Classes::
+* Static Members::
+@end menu
+
+@node Class Names
+@section C++ Class Names
+
+In C++, a class name which is declared with @code{class}, @code{struct},
+or @code{union}, is not only a tag, as in C, but also a type name. Thus
+there should be stabs with both @samp{t} and @samp{T} symbol descriptors
+(@pxref{Typedefs}).
+
+To save space, there is a special abbreviation for this case. If the
+@samp{T} symbol descriptor is followed by @samp{t}, then the stab
+defines both a type name and a tag.
+
+For example, the C++ code
+
+@example
+struct foo @{int x;@};
+@end example
+
+can be represented as either
+
+@example
+.stabs "foo:T19=s4x:1,0,32;;",128,0,0,0 # @r{128 is N_LSYM}
+.stabs "foo:t19",128,0,0,0
+@end example
+
+or
+
+@example
+.stabs "foo:Tt19=s4x:1,0,32;;",128,0,0,0
+@end example
+
+@node Nested Symbols
+@section Defining a Symbol Within Another Type
+
+In C++, a symbol (such as a type name) can be defined within another type.
+@c FIXME: Needs example.
+
+In stabs, this is sometimes represented by making the name of a symbol
+which contains @samp{::}. Such a pair of colons does not end the name
+of the symbol, the way a single colon would (@pxref{String Field}). I'm
+not sure how consistently used or well thought out this mechanism is.
+So that a pair of colons in this position always has this meaning,
+@samp{:} cannot be used as a symbol descriptor.
+
+For example, if the string for a stab is @samp{foo::bar::baz:t5=*6},
+then @code{foo::bar::baz} is the name of the symbol, @samp{t} is the
+symbol descriptor, and @samp{5=*6} is the type information.
+
+@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 of the method.
+Normally this will be a type declared using the @samp{#} type
+descriptor; see @ref{Method Type Descriptor}; static member functions
+are declared using the @samp{f} type descriptor instead; see
+@ref{Function Types}.
+
+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 Method Type Descriptor
+@section The @samp{#} Type Descriptor
+
+This is used to describe a class method. This is a function which takes
+an extra argument as its first argument, for the @code{this} pointer.
+
+If the @samp{#} is immediately followed by another @samp{#}, the second
+one will be followed by the return type and a semicolon. The class and
+argument types are not specified, and must be determined by demangling
+the name of the method if it is available.
+
+Otherwise, the single @samp{#} is followed by the class type, a comma,
+the return type, a comma, and zero or more parameter types separated by
+commas. The list of arguments is terminated by a semicolon. In the
+debugging output generated by gcc, a final argument type of @code{void}
+indicates a method which does not take a variable number of arguments.
+If the final argument type of @code{void} does not appear, the method
+was declared with an ellipsis.
+
+Note that although such a type will normally be used to describe fields
+in structures, unions, or classes, for at least some versions of the
+compiler it can also be used in other contexts.
+
+@node Member Type Descriptor
+@section The @samp{@@} Type Descriptor
+
+The @samp{@@} type descriptor is for a 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.
+
+@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.
+
+If the character following the @samp{@var{field-name}:} part of the
+string is @samp{/}, then the next character is the visibility. @samp{0}
+means private, @samp{1} means protected, and @samp{2} means public.
+Debuggers should ignore visibility characters they do not recognize, and
+assume a reasonable default (such as public) (GDB 4.11 does not, but
+this should be fixed in the next GDB release). If no visibility is
+specified the field is public. The visibility @samp{9} means that the
+field has been optimized out and is public (there is no way to specify
+an optimized out field with a private or protected visibility).
+Visibility @samp{9} is not supported by GDB 4.11; this should be fixed
+in the next GDB release.
+
+The following C++ source:
+
+@example
+class vis @{
+private:
+ int priv;
+protected:
+ char prot;
+public:
+ float pub;
+@};
+@end example
+
+@noindent
+generates the following stab:
+
+@example
+# @r{128 is N_LSYM}
+.stabs "vis:T19=s12priv:/01,0,32;prot:/12,32,8;pub:12,64,32;;",128,0,0,0
+@end example
+
+@samp{vis:T19=s12} indicates that type number 19 is a 12 byte structure
+named @code{vis} The @code{priv} field has public visibility
+(@samp{/0}), type int (@samp{1}), and offset and size @samp{,0,32;}.
+The @code{prot} field has protected visibility (@samp{/1}), type char
+(@samp{2}) and offset and size @samp{,32,8;}. The @code{pub} field has
+type float (@samp{12}), and offset and size @samp{,64,32;}.
+
+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: a virtual character, a
+visibilty character, a number, a comma, another number, and a
+semi-colon.
+
+The virtual character is @samp{1} if the base class is virtual and
+@samp{0} if not. The visibility character is @samp{2} if the derivation
+is public, @samp{1} if it is protected, and @samp{0} if it is private.
+Debuggers should ignore virtual or visibility characters they do not
+recognize, and assume a reasonable default (such as public and
+non-virtual) (GDB 4.11 does not, but this should be fixed in the next
+GDB release).
+
+The number following the virtual and visibility characters 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
+a.out files, in numeric order. This does not apply to XCOFF, but
+it does apply to stabs in sections (@pxref{Stab Sections}). 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
+@itemx 0x15 N_SETA | N_EXT
+Absolute set element
+
+@item 0x16 N_SETT
+@itemx 0x17 N_SETT | N_EXT
+Text segment set element
+
+@item 0x18 N_SETD
+@itemx 0x19 N_SETD | N_EXT
+Data segment set element
+
+@item 0x1a N_SETB
+@itemx 0x1b N_SETB | N_EXT
+BSS segment set element
+
+@item 0x1c N_SETV
+@itemx 0x1d N_SETV | N_EXT
+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{Alternate Entry Points}.
+
+@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 :
+C++ nested symbol; see @xref{Nested Symbols}
+
+@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 s
+Local variable (OS9000).
+
+@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{Method Type Descriptor}.
+
+@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{Member Type Descriptor}.
+
+@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}. Const and volatile
+qualfied type (OS9000).
+
+@item B
+Volatile-qualified type; see @ref{Miscellaneous Types}.
+
+@item c
+Complex builtin type (AIX); see @ref{Builtin Type Descriptors}.
+Const-qualified type (OS9000).
+
+@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 (AIX); see @ref{Cross-References}. Volatile-qualified
+type (OS9000).
+
+@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 Y
+Used by IBM's xlC C++ compiler (for structures, I think).
+
+@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 covers certain
+stabs which are not yet described in 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.
+
+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_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
+
+See @cite{Dbx and Dbxtool Interfaces}, 2nd edition, by Sun, 1988, for
+more information.
+
+@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_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.)
+@end itemize
+
+@node Stab Sections
+@appendix Using Stabs in Their Own Sections
+
+Many object file formats allow tools to create object files with custom
+sections containing any arbitrary data. For any such object file
+format, stabs can be embedded in special sections. This is how stabs
+are used with ELF and SOM, and aside from ECOFF and XCOFF, is how stabs
+are used with COFF.
+
+@menu
+* Stab Section Basics:: How to embed stabs in sections
+* ELF Linker Relocation:: Sun ELF hacks
+@end menu
+
+@node Stab Section Basics
+@appendixsec How to Embed Stabs in Sections
+
+The assembler creates 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 depends on the object file format.
+For ELF, it 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. For SOM, it is always big-endian (is this true??? FIXME). For
+COFF, it matches the byte order of the COFF headers. The meaning of the
+fields is the same as for a.out (@pxref{Symbol Table Format}), except
+that the @code{n_strx} field is relative to the strings for the current
+compilation unit (which can be found using the synthetic N_UNDF stab
+described below), rather than the entire string table.
+
+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.
+This may eventually be used to hold overflows from the count in
+the @code{n_desc} field.
+
+@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. SOM and COFF have no way of linking the sections together
+or marking them as string tables.
+
+For COFF, the @code{.stab} and @code{.stabstr} sections may be simply
+concatenated by the linker. GDB then uses the @code{n_desc} fields to
+figure out the extent of the original sections. Similarly, the
+@code{n_value} fields of the header symbols are added together in order
+to get the actual position of the strings in a desired @code{.stabstr}
+section. Although this design obviates any need for the linker to
+relocate or otherwise manipulate @code{.stab} and @code{.stabstr}
+sections, it also requires some care to ensure that the offsets are
+calculated correctly. For instance, if the linker were to pad in
+between the @code{.stabstr} sections before concatenating, then the
+offsets to strings in the middle of the executable's @code{.stabstr}
+section would be wrong.
+
+The GNU linker is able to optimize stabs information by merging
+duplicate strings and removing duplicate header file information
+(@pxref{Include Files}). When some versions of the GNU linker optimize
+stabs in sections, they remove the leading @code{N_UNDF} symbol and
+arranges for all the @code{n_strx} fields to be relative to the start of
+the @code{.stabstr} section.
+
+@node ELF Linker Relocation
+@appendixsec Having the Linker Relocate Stabs in ELF
+
+This section describes some Sun hacks for Stabs in ELF; it does not
+apply to COFF or SOM.
+
+To keep linking fast, you don't want the linker to have to relocate very
+many stabs. Making sure this is done for @code{N_SLINE},
+@code{N_RBRAC}, and @code{N_LBRAC} stabs is the most important thing
+(see the descriptions of those stabs for more information). But Sun's
+stabs in ELF has taken this further, to make all addresses in the
+@code{n_value} field (functions and static variables) relative to the
+source file. For the @code{N_SO} symbol itself, Sun simply omits the
+address. 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{Stab Section Transformations}. GCC does not provide these symbols;
+it instead relies on the stabs getting relocated. 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. With
+the Sun compiler 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.
+
+Finding the correct @code{Bbss.bss}, etc., symbol is difficult, because
+the linker simply concatenates the @code{.stab} sections from each
+@file{.o} file without including any information about which part of a
+@code{.stab} section comes from which @file{.o} file. The way GDB does
+this is to look for an ELF @code{STT_FILE} symbol which has the same
+name as the last component of the file name from the @code{N_SO} symbol
+in the stabs (for example, if the file name is @file{../../gdb/main.c},
+it looks for an ELF @code{STT_FILE} symbol named @code{main.c}). This
+loses if different files have the same name (they could be in different
+directories, a library could have been copied from one system to
+another, etc.). It would be much cleaner to have the @code{Bbss.bss}
+symbols in the stabs themselves. Having the linker relocate them there
+is no more work than having the linker relocate ELF symbols, and it
+solves the problem of having to associate the ELF and stab symbols.
+However, no one has yet designed or implemented such a scheme.
+
+@node Symbol Types Index
+@unnumbered Symbol Types Index
+
+@printindex fn
+
+@contents
+@bye
diff --git a/gdb/dpx2-nat.c b/gdb/dpx2-nat.c
new file mode 100644
index 00000000000..21dc1357174
--- /dev/null
+++ b/gdb/dpx2-nat.c
@@ -0,0 +1,83 @@
+/* DPX2 host interface.
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "gdbcore.h"
+
+#include "gdb_string.h"
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/dir.h>
+#include <signal.h>
+#include <sys/user.h>
+#include <sys/reg.h>
+#include <sys/utsname.h>
+
+
+/* this table must line up with REGISTER_NAMES in tm-68k.h */
+/* symbols like 'A0' come from <sys/reg.h> */
+static int regmap[] =
+{
+ R0, R1, R2, R3, R4, R5, R6, R7,
+ A0, A1, A2, A3, A4, A5, A6, SP,
+ PS, PC,
+ FP0, FP1, FP2, FP3, FP4, FP5, FP6, FP7,
+ FP_CR, FP_SR, FP_IAR
+};
+
+/* blockend is the value of u.u_ar0, and points to the
+ * place where D0 is stored
+ */
+
+int
+dpx2_register_u_addr (blockend, regnum)
+ int blockend;
+ int regnum;
+{
+ if (regnum < FP0_REGNUM)
+ return (blockend + 4 * regmap[regnum]);
+ else
+ return (int) &(((struct user *)0)->u_fpstate[regmap[regnum]]);
+}
+
+/* This is the amount to subtract from u.u_ar0
+ to get the offset in the core file of the register values.
+ Unfortunately this is not provided in the system header files.
+ To make matters worse, this value also differs between
+ the dpx/2200 and dpx/2300 models and nlist is not available on the dpx2.
+ We use utsname() to decide on which model we are running.
+ FIXME: This breaks cross examination of core files (it would not be hard
+ to check whether u.u_ar0 is between 0x7fff5000 and 0x7fffc000 and if so
+ use 0x7fff5000 and if not use 0x7fffc000. FIXME). */
+
+#define KERNEL_U_ADDR_200 0x7fff5000
+#define KERNEL_U_ADDR_300 0x7fffc000
+
+CORE_ADDR kernel_u_addr;
+
+void
+_initialize_dpx2_nat ()
+{
+ struct utsname uts;
+
+ if (uname (&uts) == 0 && strcmp (uts.machine, "DPX/2200") == 0)
+ kernel_u_addr = KERNEL_U_ADDR_200;
+ else
+ kernel_u_addr = KERNEL_U_ADDR_300;
+}
diff --git a/gdb/dsrec.c b/gdb/dsrec.c
new file mode 100644
index 00000000000..06c2929df53
--- /dev/null
+++ b/gdb/dsrec.c
@@ -0,0 +1,312 @@
+/* S-record download support for GDB, the GNU debugger.
+ Copyright 1995, 1996, 1997 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "serial.h"
+#include "srec.h"
+#include <time.h>
+
+int (*ui_load_progress_hook) PARAMS ((char *, unsigned long));
+extern void report_transfer_performance PARAMS ((unsigned long, time_t, time_t));
+
+extern int remote_debug;
+
+static int make_srec PARAMS ((char *srec, CORE_ADDR targ_addr, bfd *abfd,
+ asection *sect, int sectoff, int *maxrecsize,
+ int flags));
+
+/* Download an executable by converting it to S records. DESC is a
+ serial_t to send the data to. FILE is the name of the file to be
+ loaded. LOAD_OFFSET is the offset into memory to load data into.
+ It is usually specified by the user and is useful with the a.out
+ file format. MAXRECSIZE is the length in chars of the largest
+ S-record the host can accomodate. This is measured from the
+ starting `S' to the last char of the checksum. FLAGS is various
+ random flags, and HASHMARK is non-zero to cause a `#' to be
+ printed out for each record loaded. WAITACK, if non-NULL, is a
+ function that waits for an acknowledgement after each S-record,
+ and returns non-zero if the ack is read correctly. */
+
+void
+load_srec (desc, file, load_offset, maxrecsize, flags, hashmark, waitack)
+ serial_t desc;
+ const char *file;
+ bfd_vma load_offset;
+ int maxrecsize;
+ int flags;
+ int hashmark;
+ int (*waitack) PARAMS ((void));
+{
+ bfd *abfd;
+ asection *s;
+ char *srec;
+ int i;
+ int reclen;
+ time_t start_time, end_time;
+ unsigned long data_count = 0;
+
+ srec = (char *) alloca (maxrecsize + 1);
+
+ abfd = bfd_openr (file, 0);
+ if (!abfd)
+ {
+ printf_filtered ("Unable to open file %s\n", file);
+ return;
+ }
+
+ if (bfd_check_format (abfd, bfd_object) == 0)
+ {
+ printf_filtered ("File is not an object file\n");
+ return;
+ }
+
+ start_time = time (NULL);
+
+ /* Write a type 0 header record. no data for a type 0, and there
+ is no data, so len is 0. */
+
+ reclen = maxrecsize;
+ make_srec (srec, 0, NULL, (asection *)1, 0, &reclen, flags);
+ if (remote_debug)
+ {
+ srec[reclen] = '\0';
+ puts_debug ("sent -->", srec, "<--");
+ }
+ SERIAL_WRITE (desc, srec, reclen);
+
+ for (s = abfd->sections; s; s = s->next)
+ if (s->flags & SEC_LOAD)
+ {
+ int numbytes;
+ bfd_vma addr = bfd_get_section_vma (abfd, s) + load_offset;
+ bfd_size_type size = bfd_get_section_size_before_reloc (s);
+ char * section_name = (char *)bfd_get_section_name (abfd, s);
+ printf_filtered ("%s\t: 0x%08x .. 0x%08x ",
+ section_name, (int) addr, (int) addr + size);
+ gdb_flush (gdb_stdout);
+
+ data_count += size;
+
+ for (i = 0; i < size; i += numbytes)
+ {
+ reclen = maxrecsize;
+ numbytes = make_srec (srec, (CORE_ADDR) (addr + i), abfd, s,
+ i, &reclen, flags);
+
+ if (remote_debug)
+ {
+ srec[reclen] = '\0';
+ puts_debug ("sent -->", srec, "<--");
+ }
+
+ /* Repeatedly send the S-record until a good
+ acknowledgement is sent back. */
+ do
+ {
+ SERIAL_WRITE (desc, srec, reclen);
+ if (ui_load_progress_hook)
+ if (ui_load_progress_hook (section_name, (unsigned long) i))
+ error ("Canceled the download");
+ }
+ while (waitack != NULL && !waitack ());
+
+ if (hashmark)
+ {
+ putchar_unfiltered ('#');
+ gdb_flush (gdb_stdout);
+ }
+ } /* Per-packet (or S-record) loop */
+
+ if (ui_load_progress_hook)
+ if (ui_load_progress_hook (section_name, (unsigned long) i))
+ error ("Canceled the download");
+ putchar_unfiltered ('\n');
+ }
+
+ if (hashmark)
+ putchar_unfiltered ('\n');
+
+ end_time = time (NULL);
+
+ /* Write a terminator record. */
+
+ reclen = maxrecsize;
+ make_srec (srec, abfd->start_address, NULL, NULL, 0, &reclen, flags);
+
+ if (remote_debug)
+ {
+ srec[reclen] = '\0';
+ puts_debug ("sent -->", srec, "<--");
+ }
+
+ SERIAL_WRITE (desc, srec, reclen);
+
+ /* Some monitors need these to wake up properly. (Which ones? -sts) */
+ SERIAL_WRITE (desc, "\r\r", 2);
+ if (remote_debug)
+ puts_debug ("sent -->", "\r\r", "<---");
+
+ SERIAL_FLUSH_INPUT (desc);
+
+ report_transfer_performance (data_count, start_time, end_time);
+}
+
+/*
+ * make_srec -- make an srecord. This writes each line, one at a
+ * time, each with it's own header and trailer line.
+ * An srecord looks like this:
+ *
+ * byte count-+ address
+ * start ---+ | | data +- checksum
+ * | | | |
+ * S01000006F6B692D746573742E73726563E4
+ * S315000448600000000000000000FC00005900000000E9
+ * S31A0004000023C1400037DE00F023604000377B009020825000348D
+ * S30B0004485A0000000000004E
+ * S70500040000F6
+ *
+ * S<type><length><address><data><checksum>
+ *
+ * Where
+ * - 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.
+ * - 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
+ *
+ * - address
+ * is the start address of the data following, or in the case of
+ * a termination record, the start address of the image
+ * - data
+ * is the data.
+ * - checksum
+ * is the sum of all the raw byte data in the record, from the length
+ * upwards, modulo 256 and subtracted from 255.
+ *
+ * This routine returns the length of the S-record.
+ *
+ */
+
+static int
+make_srec (srec, targ_addr, abfd, sect, sectoff, maxrecsize, flags)
+ char *srec;
+ CORE_ADDR targ_addr;
+ bfd *abfd;
+ asection *sect;
+ int sectoff;
+ int *maxrecsize;
+ int flags;
+{
+ unsigned char checksum;
+ int tmp;
+ const static char hextab[] = "0123456789ABCDEF";
+ const static char data_code_table[] = "123";
+ const static char term_code_table[] = "987";
+ const static char header_code_table[] = "000";
+ const static char *formats[] = { "S%c%02X%04X",
+ "S%c%02X%06X",
+ "S%c%02X%08X" };
+ char const *code_table;
+ int addr_size;
+ int payload_size;
+ char *binbuf;
+ char *p;
+
+ if (sect)
+ {
+ tmp = flags; /* Data or header record */
+ code_table = abfd ? data_code_table : header_code_table;
+ binbuf = alloca (*maxrecsize/2);
+ }
+ else
+ {
+ tmp = flags >> SREC_TERM_SHIFT; /* Term record */
+ code_table = term_code_table;
+ }
+
+ if ((tmp & SREC_2_BYTE_ADDR) && (targ_addr <= 0xffff))
+ addr_size = 2;
+ else if ((tmp & SREC_3_BYTE_ADDR) && (targ_addr <= 0xffffff))
+ addr_size = 3;
+ else if (tmp & SREC_4_BYTE_ADDR)
+ addr_size = 4;
+ else
+ fatal ("make_srec: Bad address (0x%x), or bad flags (0x%x).",
+ targ_addr, flags);
+
+ /* Now that we know the address size, we can figure out how much
+ data this record can hold. */
+
+ if (sect && abfd)
+ {
+ payload_size = (*maxrecsize - (1 + 1 + 2 + addr_size * 2 + 2)) / 2;
+ payload_size = min (payload_size, sect->_raw_size - sectoff);
+
+ bfd_get_section_contents (abfd, sect, binbuf, sectoff, payload_size);
+ }
+ else
+ payload_size = 0; /* Term or header packets have no payload */
+
+ /* Output the header. */
+
+ sprintf (srec, formats[addr_size - 2], code_table[addr_size - 2],
+ addr_size + payload_size + 1, (int)targ_addr);
+
+ /* Note that the checksum is calculated on the raw data, not the
+ hexified data. It includes the length, address and the data
+ portions of the packet. */
+
+ checksum = 0;
+
+ checksum += (payload_size + addr_size + 1 /* Packet length */
+ + (targ_addr & 0xff) /* Address... */
+ + ((targ_addr >> 8) & 0xff)
+ + ((targ_addr >> 16) & 0xff)
+ + ((targ_addr >> 24) & 0xff));
+
+ p = srec + 1 + 1 + 2 + addr_size * 2;
+
+ /* Build the Srecord. */
+ for (tmp = 0; tmp < payload_size; tmp++)
+ {
+ unsigned char k;
+
+ k = binbuf[tmp];
+ *p++ = hextab [k >> 4];
+ *p++ = hextab [k & 0xf];
+ checksum += k;
+ }
+
+ checksum = ~checksum;
+
+ *p++ = hextab[checksum >> 4];
+ *p++ = hextab[checksum & 0xf];
+ *p++ = '\r';
+
+ *maxrecsize = p - srec;
+ return payload_size;
+}
diff --git a/gdb/dst.h b/gdb/dst.h
new file mode 100644
index 00000000000..252a3a86b8b
--- /dev/null
+++ b/gdb/dst.h
@@ -0,0 +1,1659 @@
+/* <apollo/dst.h> */
+/* Apollo object module DST (debug symbol table) description */
+
+#ifndef apollo_dst_h
+#define apollo_dst_h
+
+#if defined(apollo) && !defined(__GNUC__)
+#define ALIGNED1 __attribute( (aligned(1)) )
+#else
+/* Remove attribute directives from non-Apollo code: */
+#define ALIGNED1 /* nil */
+#endif
+
+
+
+/* Identification of this version of the debug symbol table. Producers of the
+ debug symbol table must write these values into the version number field of
+ the compilation unit record in .blocks .
+*/
+#define dst_version_major 1
+#define dst_version_minor 3
+
+
+/*
+** Enumeration of debug record types appearing in .blocks and .symbols ...
+*/
+typedef enum
+ {
+ dst_typ_pad, /* 0 */
+ dst_typ_comp_unit, /* 1 */
+ dst_typ_section_tab, /* 2 */
+ dst_typ_file_tab, /* 3 */
+ dst_typ_block, /* 4 */
+ dst_typ_5,
+ dst_typ_var,
+ dst_typ_pointer, /* 7 */
+ dst_typ_array, /* 8 */
+ dst_typ_subrange, /* 9 */
+ dst_typ_set, /* 10 */
+ dst_typ_implicit_enum, /* 11 */
+ dst_typ_explicit_enum, /* 12 */
+ dst_typ_short_rec, /* 13 */
+ dst_typ_old_record,
+ dst_typ_short_union, /* 15 */
+ dst_typ_old_union,
+ dst_typ_file, /* 17 */
+ dst_typ_offset, /* 18 */
+ dst_typ_alias, /* 19 */
+ dst_typ_signature, /* 20 */
+ dst_typ_21,
+ dst_typ_old_label, /* 22 */
+ dst_typ_scope, /* 23 */
+ dst_typ_end_scope, /* 24 */
+ dst_typ_25,
+ dst_typ_26,
+ dst_typ_string_tab, /* 27 */
+ dst_typ_global_name_tab, /* 28 */
+ dst_typ_forward, /* 29 */
+ dst_typ_aux_size, /* 30 */
+ dst_typ_aux_align, /* 31 */
+ dst_typ_aux_field_size, /* 32 */
+ dst_typ_aux_field_off, /* 33 */
+ dst_typ_aux_field_align, /* 34 */
+ dst_typ_aux_qual, /* 35 */
+ dst_typ_aux_var_bound, /* 36 */
+ dst_typ_extension, /* 37 */
+ dst_typ_string, /* 38 */
+ dst_typ_old_entry,
+ dst_typ_const, /* 40 */
+ dst_typ_reference, /* 41 */
+ dst_typ_record, /* 42 */
+ dst_typ_union, /* 43 */
+ dst_typ_aux_type_deriv, /* 44 */
+ dst_typ_locpool, /* 45 */
+ dst_typ_variable, /* 46 */
+ dst_typ_label, /* 47 */
+ dst_typ_entry, /* 48 */
+ dst_typ_aux_lifetime, /* 49 */
+ dst_typ_aux_ptr_base, /* 50 */
+ dst_typ_aux_src_range, /* 51 */
+ dst_typ_aux_reg_val, /* 52 */
+ dst_typ_aux_unit_names, /* 53 */
+ dst_typ_aux_sect_info, /* 54 */
+ dst_typ_END_OF_ENUM
+ }
+ dst_rec_type_t;
+
+
+/*
+** Dummy bounds for variably dimensioned arrays:
+*/
+#define dst_dummy_array_size 100
+
+
+/*
+** Reference to another item in the symbol table.
+**
+** The value of a dst_rel_offset_t is the relative offset from the start of the
+** referencing record to the start of the referenced record, string, etc.
+**
+** The value of a NIL dst_rel_offset_t is zero.
+*/
+
+typedef long dst_rel_offset_t ALIGNED1;
+
+
+/* FIXME: Here and many places we make assumptions about sizes of host
+ data types, structure layout, etc. Only needs to be fixed if we care
+ about cross-debugging, though. */
+
+/*
+** Section-relative reference.
+**
+** The section index field is an index into the local compilation unit's
+** section table (see dst_rec_section_tab_t)--NOT into the object module
+** section table!
+**
+** The sect_offset field is the offset in bytes into the section.
+**
+** A NIL dst_sect_ref_t has a sect_index field of zero. Indexes originate
+** at one.
+*/
+
+typedef struct
+ {
+ unsigned short sect_index;
+ unsigned long sect_offset ALIGNED1;
+ }
+ dst_sect_ref_t;
+
+#define dst_sect_index_nil 0
+#define dst_sect_index_origin 1
+
+
+/*
+** Source location descriptor.
+**
+** The file_index field is an index into the local compilation unit's
+** file table (see dst_rec_file_tab_t).
+**
+** A NIL dst_src_loc_t has a file_index field of zero. Indexes originate
+** at one.
+*/
+
+typedef struct
+ {
+ boolean reserved : 1; /* reserved for future use */
+ int file_index : 11; /* index into .blocks source file list */
+ int line_number : 20; /* source line number */
+ }
+ dst_src_loc_t;
+
+#define dst_file_index_nil 0
+#define dst_file_index_origin 1
+
+
+/*
+** Standard (primitive) type codes.
+*/
+
+typedef enum
+ {
+ dst_non_std_type,
+ dst_int8_type, /* 8 bit integer */
+ dst_int16_type, /* 16 bit integer */
+ dst_int32_type, /* 32 bit integer */
+ dst_uint8_type, /* 8 bit unsigned integer */
+ dst_uint16_type, /* 16 bit unsigned integer */
+ dst_uint32_type, /* 32 bit unsigned integer */
+ dst_real32_type, /* single precision ieee floatining point */
+ dst_real64_type, /* double precision ieee floatining point */
+ dst_complex_type, /* single precision complex */
+ dst_dcomplex_type, /* double precision complex */
+ dst_bool8_type, /* boolean =logical*1 */
+ dst_bool16_type, /* boolean =logical*2 */
+ dst_bool32_type, /* boolean =logical*4 */
+ dst_char_type, /* 8 bit ascii character */
+ dst_string_type, /* string of 8 bit ascii characters */
+ dst_ptr_type, /* univ_pointer */
+ dst_set_type, /* generic 256 bit set */
+ dst_proc_type, /* generic procedure (signature not specified) */
+ dst_func_type, /* generic function (signature not specified) */
+ dst_void_type, /* c void type */
+ dst_uchar_type, /* c unsigned char */
+ dst_std_type_END_OF_ENUM
+ }
+ dst_std_type_t;
+
+
+/*
+** General data type descriptor
+**
+** If the user_defined_type bit is clear, then the type is a standard type, and
+** the remaining bits contain the dst_std_type_t of the type. If the bit is
+** set, then the type is defined in a separate dst record, which is referenced
+** by the remaining bits as a dst_rel_offset_t.
+*/
+
+typedef union
+ {
+ struct
+ {
+ boolean user_defined_type : 1; /* tag field */
+ int must_be_zero : 23; /* 23 bits of pad */
+ dst_std_type_t dtc : 8; /* 8 bit primitive data */
+ }
+ std_type;
+
+ struct
+ {
+ boolean user_defined_type : 1; /* tag field */
+ int doffset : 31; /* offset to type record */
+ }
+ user_type;
+ }
+ dst_type_t ALIGNED1;
+
+/* The user_type.doffset field is a 31-bit signed value. Some versions of C
+ do not support signed bit fields. The following macro will extract that
+ field as a signed value:
+*/
+#define dst_user_type_offset(type_rec) \
+ ( ((int) ((type_rec).user_type.doffset << 1)) >> 1 )
+
+
+/*================================================*/
+/*========== RECORDS IN .blocks SECTION ==========*/
+/*================================================*/
+
+/*-----------------------
+ COMPILATION UNIT record
+ -----------------------
+ This must be the first record in each .blocks section.
+ Provides a set of information describing the output of a single compilation
+ and pointers to additional information for the compilation unit.
+*/
+
+typedef enum
+ {
+ dst_pc_code_locs, /* ranges in loc strings are pc ranges */
+ dst_comp_unit_END_OF_ENUM
+ }
+ dst_comp_unit_flag_t;
+
+typedef enum
+ {
+ dst_lang_unk, /* unknown language */
+ dst_lang_pas, /* Pascal */
+ dst_lang_ftn, /* FORTRAN */
+ dst_lang_c, /* C */
+ dst_lang_mod2, /* Modula-2 */
+ dst_lang_asm_m68k, /* 68K assembly language */
+ dst_lang_asm_a88k, /* AT assembly language */
+ dst_lang_ada, /* Ada */
+ dst_lang_cxx, /* C++ */
+ dst_lang_END_OF_ENUM
+ }
+ dst_lang_type_t;
+
+typedef struct
+ {
+ struct
+ {
+ unsigned char major_part; /* = dst_version_major */
+ unsigned char minor_part; /* = dst_version_minor */
+ }
+ version; /* version of dst */
+ unsigned short flags; /* mask of dst_comp_unit_flag_t */
+ unsigned short lang_type; /* source language */
+ unsigned short number_of_blocks; /* number of blocks records */
+ dst_rel_offset_t root_block_offset; /* offset to root block (module?) */
+ dst_rel_offset_t section_table /* offset to section table record */;
+ dst_rel_offset_t file_table; /* offset to file table record */
+ unsigned long data_size; /* total size of .blocks data */
+ }
+ dst_rec_comp_unit_t ALIGNED1;
+
+
+/*--------------------
+ SECTION TABLE record
+ --------------------
+ There must be one section table associated with each compilation unit.
+ Other debug records refer to sections via their index in this table. The
+ section base addresses in the table are virtual addresses of the sections,
+ relocated by the linker.
+*/
+
+typedef struct
+ {
+ unsigned short number_of_sections; /* size of array: */
+ unsigned long section_base[dst_dummy_array_size] ALIGNED1;
+ }
+ dst_rec_section_tab_t ALIGNED1;
+
+
+/*-----------------
+ FILE TABLE record
+ -----------------
+ There must be one file table associated with each compilation unit describing
+ the source (and include) files used by each compilation unit. Other debug
+ records refer to files via their index in this table. The first entry is the
+ primary source file.
+*/
+
+typedef struct
+ {
+ long dtm; /* time last modified (time_$clock_t) */
+ dst_rel_offset_t noffset; /* offset to name string for source file */
+ }
+ dst_file_desc_t;
+
+typedef struct
+ {
+ unsigned short number_of_files; /* size of array: */
+ dst_file_desc_t files[dst_dummy_array_size] ALIGNED1;
+ }
+ dst_rec_file_tab_t ALIGNED1;
+
+
+/*-----------------
+ NAME TABLE record
+ -----------------
+ A name table record may appear as an auxiliary record to the file table,
+ providing additional qualification of the file indexes for languages that
+ need it (i.e. Ada). Name table entries parallel file table entries of the
+ same file index.
+*/
+
+typedef struct
+ {
+ unsigned short number_of_names; /* size of array: */
+ dst_rel_offset_t names[dst_dummy_array_size] ALIGNED1;
+ }
+ dst_rec_name_tab_t ALIGNED1;
+
+
+/*--------------
+ BLOCK record
+ --------------
+ Describes a lexical program block--a procedure, function, module, etc.
+*/
+
+/* Block types. These may be used in any way desired by the compiler writers.
+ The debugger uses them only to give a description to the user of the type of
+ a block. The debugger makes no other assumptions about the meaning of any
+ of these. For example, the fact that a block is executable (e.g., program)
+ or not (e.g., module) is expressed in block attributes (see below), not
+ guessed at from the block type.
+*/
+typedef enum
+ {
+ dst_block_module, /* some pascal = modula = ada types */
+ dst_block_program,
+ dst_block_procedure,
+ dst_block_function, /* C function */
+ dst_block_subroutine, /* some fortran block types */
+ dst_block_block_data,
+ dst_block_stmt_function,
+ dst_block_package, /* a few particular to Ada */
+ dst_block_package_body,
+ dst_block_subunit,
+ dst_block_task,
+ dst_block_file, /* a C outer scope? */
+ dst_block_class, /* C++ or Simula */
+ dst_block_END_OF_ENUM
+ }
+ dst_block_type_t;
+
+/* Block attributes. This is the information used by the debugger to represent
+ the semantics of blocks.
+*/
+typedef enum
+ {
+ dst_block_main_entry, /* the block's entry point is a main entry into
+ the compilation unit */
+ dst_block_executable, /* the block has an entry point */
+ dst_block_attr_END_OF_ENUM
+ }
+ dst_block_attr_t;
+
+/* Code range. Each block has associated with it one or more code ranges. An
+ individual code range is identified by a range of source (possibly nil) and
+ a range of executable code. For example, a block which has its executable
+ code spread over multiple sections will have one code range per section.
+*/
+typedef struct
+ {
+ unsigned long code_size; /* size of executable code (in bytes ) */
+ dst_sect_ref_t code_start; /* starting address of executable code */
+ dst_sect_ref_t lines_start; /* start of line number tables */
+ }
+ dst_code_range_t;
+
+typedef struct
+ {
+ dst_block_type_t block_type : 8;
+ unsigned short flags : 8; /* mask of dst_block_attr_t flags */
+ dst_rel_offset_t sibling_block_off; /* offset to next sibling block */
+ dst_rel_offset_t child_block_off; /* offset to first contained block */
+ dst_rel_offset_t noffset; /* offset to block name string */
+ dst_sect_ref_t symbols_start; /* start of debug symbols */
+ unsigned short n_of_code_ranges; /* size of array... */
+ dst_code_range_t code_ranges[dst_dummy_array_size] ALIGNED1;
+ }
+ dst_rec_block_t ALIGNED1;
+
+
+/*--------------------------
+ AUX SECT INFO TABLE record
+ --------------------------
+ Appears as an auxiliary to a block record. Expands code range information
+ by providing references into additional, language-dependent sections for
+ information related to specific code ranges of the block. Sect info table
+ entries parallel code range array entries of the same index.
+*/
+
+typedef struct
+ {
+ unsigned char tag; /* currently can only be zero */
+ unsigned char number_of_refs; /* size of array: */
+ dst_sect_ref_t refs[dst_dummy_array_size] ALIGNED1;
+ }
+ dst_rec_sect_info_tab_t ALIGNED1;
+
+/*=================================================*/
+/*========== RECORDS IN .symbols SECTION ==========*/
+/*=================================================*/
+
+/*-----------------
+ CONSTANT record
+ -----------------
+ Describes a symbolic constant.
+*/
+
+typedef struct
+ {
+ float r; /* real part */
+ float i; /* imaginary part */
+ }
+ dst_complex_t;
+
+typedef struct
+ {
+ double dr; /* real part */
+ double di; /* imaginary part */
+ }
+ dst_double_complex_t;
+
+/* The following record provides a way of describing constant values with
+ non-standard type and no limit on size.
+*/
+typedef union
+ {
+ char char_data[dst_dummy_array_size];
+ short int_data [dst_dummy_array_size];
+ long long_data[dst_dummy_array_size];
+ }
+ dst_big_kon_t;
+
+/* Representation of the value of a general constant.
+*/
+typedef struct
+ {
+ unsigned short length; /* size of constant value (bytes) */
+
+ union
+ {
+ unsigned short kon_int8;
+ short kon_int16;
+ long kon_int32 ALIGNED1;
+ float kon_real ALIGNED1;
+ double kon_dbl ALIGNED1;
+ dst_complex_t kon_cplx ALIGNED1;
+ dst_double_complex_t kon_dcplx ALIGNED1;
+ char kon_char;
+ dst_big_kon_t kon ALIGNED1;
+ }
+ val; /* value data of constant */
+ }
+ dst_const_t ALIGNED1;
+
+typedef struct
+ {
+ dst_rel_offset_t noffset; /* offset to name string */
+ dst_src_loc_t src_loc; /* file/line of const definition */
+ dst_type_t type_desc; /* type of this (manifest) constant */
+ dst_const_t value;
+ }
+ dst_rec_const_t ALIGNED1;
+
+/*----------------
+ VARIABLE record
+ ----------------
+ Describes a program variable.
+*/
+
+/* Variable attributes. These define certain variable semantics to the
+ debugger.
+*/
+typedef enum
+ {
+ dst_var_attr_read_only, /* is read-only (a program literal) */
+ dst_var_attr_volatile, /* same as compiler's VOLATILE attribute */
+ dst_var_attr_global, /* is a global definition or reference */
+ dst_var_attr_compiler_gen, /* is compiler-generated */
+ dst_var_attr_static, /* has static location */
+ dst_var_attr_END_OF_ENUM
+ }
+ dst_var_attr_t;
+
+typedef struct
+ {
+ dst_rel_offset_t noffset; /* offset to name string */
+ dst_rel_offset_t loffset; /* offset to loc string */
+ dst_src_loc_t src_loc; /* file/line of variable definition */
+ dst_type_t type_desc; /* type descriptor */
+ unsigned short attributes; /* mask of dst_var_attr_t flags */
+ }
+ dst_rec_variable_t ALIGNED1;
+
+
+/*----------------
+ old VAR record
+ -----------------
+ Used by older compilers to describe a variable
+*/
+
+typedef enum
+ {
+ dst_var_loc_unknown, /* Actually defined as "unknown" */
+ dst_var_loc_abs, /* Absolute address */
+ dst_var_loc_sect_off, /* Absolute address as a section offset */
+ dst_var_loc_ind_sect_off, /* An indexed section offset ???? */
+ dst_var_loc_reg, /* register */
+ dst_var_loc_reg_rel, /* register relative - usually fp */
+ dst_var_loc_ind_reg_rel, /* Indexed register relative */
+ dst_var_loc_ftn_ptr_based, /* Fortran pointer based */
+ dst_var_loc_pc_rel, /* PC relative. Really. */
+ dst_var_loc_external, /* External */
+ dst_var_loc_END_OF_ENUM
+ }
+ dst_var_loc_t;
+
+/* Locations come in two versions. The sort, and the long. The difference
+ * between the short and the long is the addition of a statement number
+ * field to the start andend of the range of the long, and and unkown
+ * purpose field in the middle. Also, loc_type and loc_index aren't
+ * bitfields in the long version.
+ */
+
+typedef struct
+ {
+ unsigned short loc_type : 4;
+ unsigned short loc_index : 12;
+ long location;
+ short start_line; /* start_line and end_line? */
+ short end_line; /* I'm guessing here. */
+ } dst_var_loc_short_t;
+
+typedef struct
+ {
+ unsigned short loc_type;
+ unsigned short loc_index;
+ long location;
+ short unknown; /* Always 0003 or 3b3c. Why? */
+ short start_statement;
+ short start_line;
+ short end_statement;
+ short end_line;
+ } dst_var_loc_long_t;
+
+
+typedef struct
+ {
+ dst_rel_offset_t noffset; /* offset to name string */
+ dst_src_loc_t src_loc; /* file/line of description */
+ dst_type_t type_desc; /* Type description */
+ unsigned short attributes; /* mask of dst_var_attr_t flags */
+ unsigned short no_of_locs : 15;/* Number of locations */
+ unsigned short short_locs : 1; /* True if short locations. */
+ union
+ {
+ dst_var_loc_short_t shorts[dst_dummy_array_size];
+ dst_var_loc_long_t longs[dst_dummy_array_size];
+ } locs;
+ } dst_rec_var_t;
+
+/*----------------
+ old LABEL record
+ -----------------
+ Used by older compilers to describe a label
+*/
+
+typedef struct
+ {
+ dst_rel_offset_t noffset; /* offset to name string */
+ dst_src_loc_t src_loc; /* file/line of description */
+ char location[12]; /* location string */
+ }
+ dst_rec_old_label_t ALIGNED1;
+
+/*----------------
+ POINTER record
+ ----------------
+ Describes a pointer type.
+*/
+
+typedef struct
+ {
+ dst_rel_offset_t noffset; /* offset to the name string for this type */
+ dst_src_loc_t src_loc; /* file/line of definition */
+ dst_type_t type_desc; /* base type of this pointer */
+ }
+ dst_rec_pointer_t ALIGNED1;
+
+
+/*-------------
+ ARRAY record
+ -------------
+ Describes an array type.
+
+ Multidimensional arrays are described with a number of dst_rec_array_t
+ records, one per array dimension, each linked to the next through the
+ elem_type_desc.doffset field. Each record must have its multi_dim flag
+ set.
+
+ If column_major is true (as with FORTRAN arrays) then the last array bound in
+ the declaration is the first array index in memory, which is the opposite of
+ the usual case (as with Pascal and C arrays).
+
+ Variable array bounds are described by auxiliary records; if aux_var_bound
+ records are present, the lo_bound and hi_bound fields of this record are
+ ignored by the debugger.
+
+ span_comp identifies one of the language-dependent ways in which the distance
+ between successive array elements (span) is calculated.
+ dst_use_span_field -- the span is the value of span field.
+ dst_compute_from_prev -- the span is the size of the previous dimension.
+ dst_compute_from_next -- the span is the size of the next dimension.
+ In the latter two cases, the span field contains an amount of padding to add
+ to the size of the appropriate dimension to calculate the span.
+*/
+
+typedef enum
+ {
+ dst_use_span_field,
+ dst_compute_from_prev,
+ dst_compute_from_next,
+ dst_span_comp_END_OF_ENUM
+ }
+ dst_span_comp_t;
+
+typedef struct
+ {
+ dst_rel_offset_t noffset; /* offset to name string */
+ dst_src_loc_t src_loc; /* file/line of definition */
+ dst_type_t elem_type_desc; /* array element type */
+ dst_type_t indx_type_desc; /* array index type */
+ long lo_bound; /* lower bound of index */
+ long hi_bound; /* upper bound of index */
+ unsigned long span; /* see above */
+ unsigned long size; /* total array size (bytes) */
+ boolean multi_dim : 1;
+ boolean is_packed : 1; /* true if packed array */
+ boolean is_signed : 1; /* true if packed elements are signed */
+ dst_span_comp_t span_comp : 2; /* how to compute span */
+ boolean column_major : 1;
+ unsigned short reserved : 2; /* must be zero */
+ unsigned short elem_size : 8; /* element size if packed (bits) */
+ }
+ dst_rec_array_t ALIGNED1;
+
+
+/*-----------------
+ SUBRANGE record
+ -----------------
+ Describes a subrange type.
+*/
+
+/* Variable subrange bounds are described by auxiliary records; if aux_var_bound
+ records are present, the lo_bound and hi_bound fields of this record are
+ ignored by the debugger.
+*/
+
+typedef struct
+ {
+ dst_rel_offset_t noffset; /* offset to name string */
+ dst_src_loc_t src_loc; /* file/line of subrange definition */
+ dst_type_t type_desc; /* parent type */
+ long lo_bound; /* lower bound of subrange */
+ long hi_bound; /* upper bound of subrange */
+ unsigned short size; /* storage size (bytes) */
+ }
+ dst_rec_subrange_t ALIGNED1;
+
+
+/*---------------
+ STRING record
+ ---------------
+ Describes a string type.
+*/
+
+/* Variable subrange bounds are described by auxiliary records; if aux_var_bound
+ records are present, the lo_bound and hi_bound fields of this record are
+ ignored by the debugger.
+*/
+
+typedef struct
+ {
+ dst_rel_offset_t noffset; /* offset to name string */
+ dst_src_loc_t src_loc; /* file/line of string definition */
+ dst_type_t elem_type_desc; /* element type */
+ dst_type_t indx_type_desc; /* index type */
+ long lo_bound; /* lower bound */
+ long hi_bound; /* upper bound */
+ unsigned long size; /* total string size (bytes) if fixed */
+ }
+ dst_rec_string_t ALIGNED1;
+
+
+/*---------------
+ SET record
+ ---------------
+ Describes a set type.
+*/
+
+typedef struct
+ {
+ dst_rel_offset_t noffset; /* offset to name string */
+ dst_src_loc_t src_loc; /* file/line of definition */
+ dst_type_t type_desc; /* element type */
+ unsigned short nbits; /* number of bits in set */
+ unsigned short size; /* storage size (bytes) */
+ }
+ dst_rec_set_t ALIGNED1;
+
+
+/*-----------------------------
+ IMPLICIT ENUMERATION record
+ -----------------------------
+ Describes an enumeration type with implicit element values = 0, 1, 2, ...
+ (Pascal-style).
+*/
+
+typedef struct
+ {
+ dst_rel_offset_t noffset; /* offset to name string */
+ dst_src_loc_t src_loc; /* file/line of definition */
+ unsigned short nelems; /* number of elements in enumeration */
+ unsigned short size; /* storage size (bytes) */
+ /* offsets to name strings of elements 0, 1, 2, ... */
+ dst_rel_offset_t elem_noffsets[dst_dummy_array_size];
+ }
+ dst_rec_implicit_enum_t ALIGNED1;
+
+
+/*-----------------------------
+ EXPLICIT ENUMERATION record
+ -----------------------------
+ Describes an enumeration type with explicitly assigned element values
+ (C-style).
+*/
+
+typedef struct
+ {
+ dst_rel_offset_t noffset; /* offset to element name string */
+ long value; /* element value */
+ }
+ dst_enum_elem_t;
+
+typedef struct
+ {
+ dst_rel_offset_t noffset; /* offset to name string */
+ dst_src_loc_t src_loc; /* file/line of definition */
+ unsigned short nelems; /* number of elements in enumeration */
+ unsigned short size; /* storage size (bytes) */
+ /* name/value pairs, one describing each enumeration value: */
+ dst_enum_elem_t elems[dst_dummy_array_size];
+ }
+ dst_rec_explicit_enum_t ALIGNED1;
+
+
+/*-----------------------
+ RECORD / UNION record
+ -----------------------
+ Describes a record (struct) or union.
+
+ If the record is larger than 2**16 bytes then an attached aux record
+ specifies its size. Also, if the record is stored in short form then
+ attached records specify field offsets larger than 2**16 bytes.
+
+ Whether the fields[] array or sfields[] array is used is selected by
+ the dst_rec_type_t of the overall dst record.
+*/
+
+/*
+ Record field descriptor, short form. This form handles only fields which
+ are an even number of bytes long, located some number of bytes from the
+ start of the record.
+*/
+typedef struct
+ {
+ dst_rel_offset_t noffset; /* offset to field name string */
+ dst_type_t type_desc; /* field type */
+ unsigned short foffset; /* field offset from start of record (bytes) */
+ }
+ dst_short_field_t ALIGNED1;
+
+typedef struct
+ {
+ dst_rel_offset_t noffset; /* offset to name string */
+ dst_type_t type_desc; /* field type */
+ unsigned short foffset; /* byte offset */
+ unsigned short is_packed : 1; /* True if field is packed */
+ unsigned short bit_offset : 6; /* Bit offset */
+ unsigned short size : 6; /* Size in bits */
+ unsigned short sign : 1; /* True if signed */
+ unsigned short pad : 2; /* Padding. Must be 0 */
+ }
+ dst_old_field_t ALIGNED1;
+
+/* Tag enumeration for long record field descriptor:
+*/
+typedef enum
+ {
+ dst_field_byte,
+ dst_field_bit,
+ dst_field_loc,
+ dst_field_END_OF_ENUM
+ }
+ dst_field_format_t;
+
+/*
+ Record field descriptor, long form. The format of the field information
+ is identified by the format_tag, which contains one of the above values.
+ The field_byte variant is equivalent to the short form of field descriptor.
+ The field_bit variant handles fields which are any number of bits long,
+ located some number of bits from the start of the record. The field_loc
+ variant allows the location of the field to be described by a general loc
+ string.
+*/
+typedef struct
+ {
+ dst_rel_offset_t noffset; /* offset to name of field */
+ dst_type_t type_desc; /* type of field */
+ union
+ {
+ struct {
+ dst_field_format_t format_tag: 2; /* dst_field_byte */
+ unsigned long offset: 30; /* offset of field in bytes */
+ }
+ field_byte ALIGNED1;
+ struct {
+ dst_field_format_t format_tag: 2; /* dst_field_bit */
+ unsigned long nbits: 6; /* bit size of field */
+ unsigned long is_signed: 1; /* signed/unsigned attribute */
+ unsigned long bit_offset: 3; /* bit offset from byte boundary */
+ int pad: 4; /* must be zero */
+ unsigned short byte_offset; /* offset of byte boundary */
+ }
+ field_bit ALIGNED1;
+ struct {
+ dst_field_format_t format_tag: 2; /* dst_field_loc */
+ int loffset: 30; /* dst_rel_offset_t to loc string */
+ }
+ field_loc ALIGNED1;
+ }
+ f ALIGNED1;
+ }
+ dst_field_t;
+
+/* The field_loc.loffset field is a 30-bit signed value. Some versions of C do
+ not support signed bit fields. The following macro will extract that field
+ as a signed value:
+*/
+#define dst_field_loffset(field_rec) \
+ ( ((int) ((field_rec).f.field_loc.loffset << 2)) >> 2 )
+
+
+typedef struct
+ {
+ dst_rel_offset_t noffset; /* offset to record name string */
+ dst_src_loc_t src_loc; /* file/line where this record is defined */
+ unsigned short size; /* storage size (bytes) */
+ unsigned short nfields; /* number of fields in this record */
+ union
+ {
+ dst_field_t fields[dst_dummy_array_size];
+ dst_short_field_t sfields[dst_dummy_array_size];
+ dst_old_field_t ofields[dst_dummy_array_size];
+ }
+ f; /* array of fields */
+ }
+ dst_rec_record_t ALIGNED1;
+
+
+/*-------------
+ FILE record
+ -------------
+ Describes a file type.
+*/
+
+typedef struct
+ {
+ dst_rel_offset_t noffset; /* offset to name string */
+ dst_src_loc_t src_loc; /* file/line where type was defined */
+ dst_type_t type_desc; /* file element type */
+ }
+ dst_rec_file_t ALIGNED1;
+
+
+/*---------------
+ OFFSET record
+ ---------------
+ Describes a Pascal offset type.
+ (This type, an undocumented Domain Pascal extension, is currently not
+ supported by the debugger)
+*/
+
+typedef struct
+ {
+ dst_rel_offset_t noffset; /* offset to the name string */
+ dst_src_loc_t src_loc; /* file/line of definition */
+ dst_type_t area_type_desc; /* area type */
+ dst_type_t base_type_desc; /* base type */
+ long lo_bound; /* low bound of the offset range */
+ long hi_bound; /* high bound of the offset range */
+ long bias; /* bias */
+ unsigned short scale; /* scale factor */
+ unsigned short size; /* storage size (bytes) */
+ }
+ dst_rec_offset_t ALIGNED1;
+
+
+/*--------------
+ ALIAS record
+ --------------
+ Describes a type alias (e.g., typedef).
+*/
+
+typedef struct
+ {
+ dst_rel_offset_t noffset; /* offset to name string */
+ dst_src_loc_t src_loc; /* file/line of definition */
+ dst_type_t type_desc; /* parent type */
+ }
+ dst_rec_alias_t ALIGNED1;
+
+
+/*------------------
+ SIGNATURE record
+ ------------------
+ Describes a procedure/function type.
+*/
+
+/* Enumeration of argument semantics. Note that most are mutually
+ exclusive.
+*/
+typedef enum
+ {
+ dst_arg_attr_val, /* passed by value */
+ dst_arg_attr_ref, /* passed by reference */
+ dst_arg_attr_name, /* passed by name */
+ dst_arg_attr_in, /* readable in the callee */
+ dst_arg_attr_out, /* writable in the callee */
+ dst_arg_attr_hidden, /* not visible in the caller */
+ dst_arg_attr_END_OF_ENUM
+ }
+ dst_arg_attr_t;
+
+/* Argument descriptor. Actually points to a variable record for most of the
+ information.
+*/
+typedef struct
+ {
+ dst_rel_offset_t var_offset; /* offset to variable record */
+ unsigned short attributes; /* a mask of dst_arg_attr_t flags */
+ }
+ dst_arg_t ALIGNED1;
+
+typedef struct
+ {
+ dst_rel_offset_t noffset; /* offset to name string */
+ dst_src_loc_t src_loc; /* file/line of function definition */
+ dst_rel_offset_t result; /* offset to function result variable record */
+ unsigned short nargs; /* number of arguments */
+ dst_arg_t args[dst_dummy_array_size];
+ }
+ dst_rec_signature_t ALIGNED1;
+
+/*--------------
+ SCOPE record
+ --------------
+ Obsolete. Use the new ENTRY type instead.
+ Old compilers may put this in as the first entry in a function,
+ terminated by an end of scope entry.
+*/
+
+typedef struct
+ {
+ dst_rel_offset_t noffset; /* Name offset */
+ dst_src_loc_t start_line; /* Starting line */
+ dst_src_loc_t end_line; /* Ending line */
+ }
+ dst_rec_scope_t ALIGNED1;
+
+/*--------------
+ ENTRY record
+ --------------
+ Describes a procedure/function entry point. An entry record is to a
+ signature record roughly as a variable record is to a type descriptor record.
+
+ The entry_number field is keyed to the entry numbers in .lines -- the
+ debugger locates the code location of an entry by searching the line
+ number table for an entry numbered with the value of entry_number. The
+ main entry is numbered zero.
+*/
+
+typedef struct
+ {
+ dst_rel_offset_t noffset; /* offset to entry name string */
+ dst_rel_offset_t loffset; /* where to jump to call this entry */
+ dst_src_loc_t src_loc; /* file/line of definition */
+ dst_rel_offset_t sig_desc; /* offset to signature descriptor */
+ unsigned int entry_number: 8;
+ int pad: 8; /* must be zero */
+ }
+ dst_rec_entry_t ALIGNED1;
+
+/*-----------------------
+ Old format ENTRY record
+ -----------------------
+ Supposedly obsolete but still used by some compilers.
+ */
+
+typedef struct
+ {
+ dst_rel_offset_t noffset; /* Offset to entry name string */
+ dst_src_loc_t src_loc; /* Location in source */
+ dst_rel_offset_t sig_desc; /* Signature description */
+ char unknown[36];
+ }
+ dst_rec_old_entry_t ALIGNED1;
+
+/*--------------
+ LABEL record
+ --------------
+ Describes a program label.
+*/
+
+typedef struct
+ {
+ dst_rel_offset_t noffset; /* offset to label string */
+ dst_rel_offset_t loffset; /* offset to loc string */
+ dst_src_loc_t src_loc; /* file/line of definition */
+ }
+ dst_rec_label_t ALIGNED1;
+
+
+/*-----------------------
+ AUXILIARY SIZE record
+ -----------------------
+ May appear in the auxiliary record list of any type or variable record to
+ modify the default size of the type or variable.
+*/
+
+typedef struct
+ {
+ unsigned long size; /* size (bytes) */
+ }
+ dst_rec_aux_size_t ALIGNED1;
+
+
+/*-----------------------
+ AUXILIARY ALIGN record
+ -----------------------
+ May appear in the auxiliary record list of any type or variable record to
+ modify the default alignment of the type or variable.
+*/
+
+typedef struct
+ {
+ unsigned short alignment; /* # of low order zero bits */
+ }
+ dst_rec_aux_align_t ALIGNED1;
+
+
+/*-----------------------------
+ AUXILIARY FIELD SIZE record
+ -----------------------------
+ May appear in the auxiliary record list of any RECORD/UNION record to
+ modify the default size of a field.
+*/
+
+typedef struct
+ {
+ unsigned short field_no; /* field number */
+ unsigned long size; /* size (bits) */
+ }
+ dst_rec_aux_field_size_t ALIGNED1;
+
+
+
+/*-----------------------------
+ AUXILIARY FIELD OFFSET record
+ -----------------------------
+ May appear in the auxiliary record list of any RECORD/UNION record to
+ specify a field offset larger than 2**16.
+*/
+
+typedef struct
+ {
+ unsigned short field_no; /* field number */
+ unsigned long foffset; /* offset */
+ }
+ dst_rec_aux_field_off_t ALIGNED1;
+
+
+/*-----------------------------
+ AUXILIARY FIELD ALIGN record
+ -----------------------------
+ May appear in the auxiliary record list of any RECORD/UNION record to
+ modify the default alignment of a field.
+*/
+
+typedef struct
+ {
+ unsigned short field_no; /* field number */
+ unsigned short alignment; /* number of low order zero bits */
+ }
+ dst_rec_aux_field_align_t ALIGNED1;
+
+
+/*----------------------------
+ AUXILIARY VAR BOUND record
+ ----------------------------
+ May appear in the auxiliary record list of any ARRAY, SUBRANGE or STRING
+ record to describe a variable bound for the range of the type.
+*/
+
+typedef enum
+ {
+ dst_low_bound, /* the low bound is variable */
+ dst_high_bound, /* the high bound is variable */
+ dst_var_bound_END_OF_ENUM
+ }
+ dst_var_bound_t;
+
+typedef struct
+ {
+ unsigned short which; /* which bound */
+ dst_rel_offset_t voffset ALIGNED1; /* variable that defines bound */
+ }
+ dst_rec_aux_var_bound_t ALIGNED1;
+
+
+/*----------------------------------
+ AUXILIARY TYPE DERIVATION record
+ ----------------------------------
+ May appear in the auxiliary record list of any RECORD/UNION record to denote
+ class inheritance of that type from a parent type.
+
+ Inheritance implies that it is possible to convert the inheritor type to the
+ inherited type, retaining those fields which were inherited. To allow this,
+ orig_field_no, a field number into the record type, is provided. If
+ orig_is_pointer is false, then the start of the inherited record is located
+ at the location of the field indexed by orig_field_no. If orig_is_pointer
+ is true, then it is located at the address contained in the field indexed
+ by orig_field_no (assumed to be a pointer).
+*/
+
+typedef struct
+ {
+ dst_type_t parent_type; /* reference to inherited type */
+ unsigned short orig_field_no;
+ boolean orig_is_pointer: 1;
+ int unused: 15; /* must be zero */
+ }
+ dst_rec_aux_type_deriv_t ALIGNED1;
+
+
+/*------------------------------------
+ AUXILIARY VARIABLE LIFETIME record
+ ------------------------------------
+ May appear in the auxiliary record list of a VARIABLE record to add location
+ information for an additional variable lifetime.
+*/
+
+typedef struct
+ {
+ dst_rel_offset_t loffset;
+ }
+ dst_rec_aux_lifetime_t ALIGNED1;
+
+
+/*-------------------------------
+ AUXILIARY POINTER BASE record
+ -------------------------------
+ May appear in the auxiliary record list of a VARIABLE record to provide a
+ pointer base to substitute for references to any such bases in the location
+ string of the variable. A pointer base is another VARIABLE record. When
+ the variable is evaluated by the debugger, it uses the current value of the
+ pointer base variable in computing its location.
+
+ This is useful for representing FORTRAN pointer-based variables.
+*/
+
+typedef struct
+ {
+ dst_rel_offset_t voffset;
+ }
+ dst_rec_aux_ptr_base_t ALIGNED1;
+
+
+/*---------------------------------
+ AUXILIARY REGISTER VALUE record
+ ---------------------------------
+ May appear in the auxiliary record list of an ENTRY record to specify
+ a register that must be set to a specific value before jumping to the entry
+ point in a debugger "call". The debugger must set the debuggee register,
+ specified by the register code, to the value of the *address* to which the
+ location string resolves. If the address is register-relative, then the
+ call cannot be made unless the current stack frame is the lexical parent
+ of the entry. An example of this is when a (Pascal) nested procedure
+ contains references to its parent's variables, which it accesses through
+ a static link register. The static link register must be set to some
+ address relative to the parent's stack base register.
+*/
+
+typedef struct
+ {
+ unsigned short reg; /* identifies register to set (isp enum) */
+ dst_rel_offset_t loffset; /* references a location string */
+ }
+ dst_rec_aux_reg_val_t ALIGNED1;
+
+
+/*==========================================================*/
+/*========== RECORDS USED IN .blocks AND .symbols ==========*/
+/*==========================================================*/
+
+/*---------------------
+ STRING TABLE record
+ ---------------------
+ A string table record contains any number of null-terminated, variable length
+ strings. The length field gives the size in bytes of the text field, which
+ can be any size.
+
+ The global name table shares this format. This record appears in the
+ .blocks section. Each string in the table identifies a global defined in
+ the current compilation unit.
+
+ The loc pool record shares this format as well. Loc strings are described
+ elsewhere.
+*/
+
+typedef struct
+ {
+ unsigned long length;
+ char text[dst_dummy_array_size];
+ }
+ dst_rec_string_tab_t ALIGNED1;
+
+
+/*-----------------------
+ AUXILIARY QUAL record
+ -----------------------
+ May appear in the auxiliary record list of any BLOCK, VARIABLE, or type record
+ to provide it with a fully-qualified, language-dependent name.
+*/
+
+typedef struct
+ {
+ dst_rel_offset_t lang_qual_name;
+ }
+ dst_rec_aux_qual_t ALIGNED1;
+
+
+/*----------------
+ FORWARD record
+ ----------------
+ Reference to a record somewhere else. This allows identical definitions in
+ different scopes to share data.
+*/
+
+typedef struct
+ {
+ dst_rel_offset_t rec_off;
+ }
+ dst_rec_forward_t ALIGNED1;
+
+
+/*-------------------------------
+ AUXILIARY SOURCE RANGE record
+ -------------------------------
+ May appear in the auxiliary record list of any BLOCK record to specify a
+ range of source lines over which the block is active.
+*/
+
+typedef struct
+ {
+ dst_src_loc_t first_line; /* first source line */
+ dst_src_loc_t last_line; /* last source line */
+ }
+ dst_rec_aux_src_range_t ALIGNED1;
+
+
+/*------------------
+ EXTENSION record
+ ------------------
+ Provision for "foreign" records, such as might be generated by a non-Apollo
+ compiler. Apollo software will ignore these.
+*/
+
+typedef struct
+ {
+ unsigned short rec_size; /* record size (bytes) */
+ unsigned short ext_type; /* defined by whoever generates it */
+ unsigned short ext_data; /* place-holder for arbitrary amount of data */
+ }
+ dst_rec_extension_t ALIGNED1;
+
+
+/*
+** DEBUG SYMBOL record -- The wrapper for all .blocks and .symbols records.
+**
+** This record ties together all previous .blocks and .symbols records
+** together in a union with a common header. The rec_type field of the
+** header identifies the record type. The rec_flags field currently only
+** defines auxiliary record lists.
+**
+** If a record carries with it a non-null auxiliary record list, its
+** dst_flag_has_aux_recs flag is set, and each of the records that follow
+** it are treated as its auxiliary records, until the end of the compilation
+** unit or scope is reached, or until an auxiliary record with its
+** dst_flag_last_aux_rec flag set is reached.
+*/
+
+typedef enum
+ {
+ dst_flag_has_aux_recs,
+ dst_flag_last_aux_rec,
+ dst_rec_flag_END_OF_ENUM
+ }
+ dst_rec_flags_t;
+
+typedef struct
+ {
+ dst_rec_type_t rec_type : 8; /* record type */
+ int rec_flags: 8; /* mask of dst_rec_flags_t */
+ union /* switched on rec_type field above */
+ {
+ /* dst_typ_pad requires no additional fields */
+ dst_rec_comp_unit_t comp_unit_;
+ dst_rec_section_tab_t section_tab_;
+ dst_rec_file_tab_t file_tab_;
+ dst_rec_block_t block_;
+ dst_rec_var_t var_;
+ dst_rec_pointer_t pointer_;
+ dst_rec_array_t array_;
+ dst_rec_subrange_t subrange_;
+ dst_rec_set_t set_;
+ dst_rec_implicit_enum_t implicit_enum_;
+ dst_rec_explicit_enum_t explicit_enum_;
+ /* dst_typ_short_{rec,union} are represented by 'rec' (below) */
+ dst_rec_file_t file_;
+ dst_rec_offset_t offset_;
+ dst_rec_alias_t alias_;
+ dst_rec_signature_t signature_;
+ dst_rec_old_label_t old_label_;
+ dst_rec_scope_t scope_;
+ /* dst_typ_end_scope requires no additional fields */
+ dst_rec_string_tab_t string_tab_;
+ /* dst_typ_global_name_tab is represented by 'string_tab' (above) */
+ dst_rec_forward_t forward_;
+ dst_rec_aux_size_t aux_size_;
+ dst_rec_aux_align_t aux_align_;
+ dst_rec_aux_field_size_t aux_field_size_;
+ dst_rec_aux_field_off_t aux_field_off_;
+ dst_rec_aux_field_align_t aux_field_align_;
+ dst_rec_aux_qual_t aux_qual_;
+ dst_rec_aux_var_bound_t aux_var_bound_;
+ dst_rec_extension_t extension_;
+ dst_rec_string_t string_;
+ dst_rec_const_t const_;
+ /* dst_typ_reference is represented by 'pointer' (above) */
+ dst_rec_record_t record_;
+ /* dst_typ_union is represented by 'record' (above) */
+ dst_rec_aux_type_deriv_t aux_type_deriv_;
+ /* dst_typ_locpool is represented by 'string_tab' (above) */
+ dst_rec_variable_t variable_;
+ dst_rec_label_t label_;
+ dst_rec_entry_t entry_;
+ dst_rec_aux_lifetime_t aux_lifetime_;
+ dst_rec_aux_ptr_base_t aux_ptr_base_;
+ dst_rec_aux_src_range_t aux_src_range_;
+ dst_rec_aux_reg_val_t aux_reg_val_;
+ dst_rec_name_tab_t aux_unit_names_;
+ dst_rec_sect_info_tab_t aux_sect_info_;
+ }
+ rec_data ALIGNED1;
+ }
+ dst_rec_t, *dst_rec_ptr_t;
+
+
+/*===============================================*/
+/*========== .lines SECTION DEFINITIONS =========*/
+/*===============================================*/
+/*
+ The .lines section contains a sequence of line number tables. There is no
+ record structure within the section. The start of the table for a routine
+ is pointed to by the block record, and the end of the table is signaled by
+ an escape code.
+
+ A line number table is a sequence of bytes. The default entry contains a line
+ number delta (-7..+7) in the high 4 bits and a pc delta (0..15) in the low 4
+ bits. Special cases, including when one or both of the values is too large
+ to fit in 4 bits and other special cases are handled through escape entries.
+ Escape entries are identified by the value 0x8 in the high 4 bits. The low 4
+ bits are occupied by a function code. Some escape entries are followed by
+ additional arguments, which may be bytes, words, or longwords. This data is
+ not aligned.
+
+ The initial PC offset, file number and line number are zero. Normally, the
+ table begins with a dst_ln_file escape which establishes the initial file
+ and line number. All PC deltas are unsigned (thus the table is ordered by
+ increasing PC); line number deltas are signed. The table ends with a
+ dst_ln_end escape, which is followed by a final table entry whose PC delta
+ gives the code size of the last statement.
+
+ Escape Semantic
+ --------- ------------------------------------------------------------
+ file Changes file state. The current source file remains constant
+ until another file escape. Though the line number state is
+ also updated by a file escape, a file escape does NOT
+ constitute a line table entry.
+
+ statement Alters the statement number of the next table entry. By
+ default, all table entries refer to the first statement on a
+ line. Statement number one is the second statement, and so on.
+
+ entry Identifies the next table entry as the position of an entry
+ point for the current block. The PC position should follow
+ any procedure prologue code. An argument specifies the entry
+ number, which is keyed to the entry number of the corresponding
+ .symbols ENTRY record.
+
+ exit Identifies the next table entry as the last position within
+ the current block before a procedure epiloge and subsequent
+ procedure exit.
+
+ gap By default, the executable code corresponding to a table entry
+ is assumed to extend to the beginning of the next table entry.
+ If this is not the case--there is a "hole" in the table--then
+ a gap escape should follow the first table entry to specify
+ where the code for that entry ends.
+*/
+
+#define dst_ln_escape_flag -8
+
+/*
+ Escape function codes:
+*/
+typedef enum
+ {
+ dst_ln_pad, /* pad byte */
+ dst_ln_file, /* file escape. Next 4 bytes are a dst_src_loc_t */
+ dst_ln_dln1_dpc1, /* 1 byte line delta, 1 byte pc delta */
+ dst_ln_dln2_dpc2, /* 2 bytes line delta, 2 bytes pc delta */
+ dst_ln_ln4_pc4, /* 4 bytes ABSOLUTE line number, 4 bytes ABSOLUTE pc */
+ dst_ln_dln1_dpc0, /* 1 byte line delta, pc delta = 0 */
+ dst_ln_ln_off_1, /* statement escape, stmt # = 1 (2nd stmt on line) */
+ dst_ln_ln_off, /* statement escape, stmt # = next byte */
+ dst_ln_entry, /* entry escape, next byte is entry number */
+ dst_ln_exit, /* exit escape */
+ dst_ln_stmt_end, /* gap escape, 4 bytes pc delta */
+ dst_ln_escape_11, /* reserved */
+ dst_ln_escape_12, /* reserved */
+ dst_ln_escape_13, /* reserved */
+ dst_ln_nxt_byte, /* next byte contains the real escape code */
+ dst_ln_end, /* end escape, final entry follows */
+ dst_ln_escape_END_OF_ENUM
+ }
+ dst_ln_escape_t;
+
+/*
+ Line number table entry
+*/
+typedef union
+ {
+ struct
+ {
+ unsigned int ln_delta : 4; /* 4 bit line number delta */
+ unsigned int pc_delta : 4; /* 4 bit pc delta */
+ }
+ delta;
+
+ struct
+ {
+ unsigned int esc_flag : 4; /* alias for ln_delta */
+ dst_ln_escape_t esc_code : 4; /* escape function code */
+ }
+ esc;
+
+ char sdata; /* signed data byte */
+ unsigned char udata; /* unsigned data byte */
+ }
+ dst_ln_entry_t,
+ *dst_ln_entry_ptr_t,
+ dst_ln_table_t[dst_dummy_array_size];
+
+/* The following macro will extract the ln_delta field as a signed value:
+*/
+#define dst_ln_ln_delta(ln_rec) \
+ ( ((short) ((ln_rec).delta.ln_delta << 12)) >> 12 )
+
+
+
+
+typedef struct dst_sec_struct {
+ char *buffer;
+ long position;
+ long size;
+ long base;
+} dst_sec;
+
+
+/* Macros for access to the data */
+
+#define DST_comp_unit(x) ((x)->rec_data.comp_unit_)
+#define DST_section_tab(x) ((x)->rec_data.section_tab_)
+#define DST_file_tab(x) ((x)->rec_data.file_tab_)
+#define DST_block(x) ((x)->rec_data.block_)
+#define DST_var(x) ((x)->rec_data.var_)
+#define DST_pointer(x) ((x)->rec_data.pointer_)
+#define DST_array(x) ((x)->rec_data.array_)
+#define DST_subrange(x) ((x)->rec_data.subrange_)
+#define DST_set(x) ((x)->rec_data.set_)
+#define DST_implicit_enum(x) ((x)->rec_data.implicit_enum_)
+#define DST_explicit_enum(x) ((x)->rec_data.explicit_enum_)
+#define DST_short_rec(x) ((x)->rec_data.record_)
+#define DST_short_union(x) ((x)->rec_data.record_)
+#define DST_file(x) ((x)->rec_data.file_)
+#define DST_offset(x) ((x)->rec_data.offset_)
+#define DST_alias(x) ((x)->rec_data.alias_)
+#define DST_signature(x) ((x)->rec_data.signature_)
+#define DST_old_label(x) ((x)->rec_data.old_label_)
+#define DST_scope(x) ((x)->rec_data.scope_)
+#define DST_string_tab(x) ((x)->rec_data.string_tab_)
+#define DST_global_name_tab(x) ((x)->rec_data.string_tab_)
+#define DST_forward(x) ((x)->rec_data.forward_)
+#define DST_aux_size(x) ((x)->rec_data.aux_size_)
+#define DST_aux_align(x) ((x)->rec_data.aux_align_)
+#define DST_aux_field_size(x) ((x)->rec_data.aux_field_size_)
+#define DST_aux_field_off(x) ((x)->rec_data.aux_field_off_)
+#define DST_aux_field_align(x) ((x)->rec_data.aux_field_align_)
+#define DST_aux_qual(x) ((x)->rec_data.aux_qual_)
+#define DST_aux_var_bound(x) ((x)->rec_data.aux_var_bound_)
+#define DST_extension(x) ((x)->rec_data.extension_)
+#define DST_string(x) ((x)->rec_data.string_)
+#define DST_const(x) ((x)->rec_data.const_)
+#define DST_reference(x) ((x)->rec_data.pointer_)
+#define DST_record(x) ((x)->rec_data.record_)
+#define DST_union(x) ((x)->rec_data.record_)
+#define DST_aux_type_deriv(x) ((x)->rec_data.aux_type_deriv_)
+#define DST_locpool(x) ((x)->rec_data.string_tab_)
+#define DST_variable(x) ((x)->rec_data.variable_)
+#define DST_label(x) ((x)->rec_data.label_)
+#define DST_entry(x) ((x)->rec_data.entry_)
+#define DST_aux_lifetime(x) ((x)->rec_data.aux_lifetime_)
+#define DST_aux_ptr_base(x) ((x)->rec_data.aux_ptr_base_)
+#define DST_aux_src_range(x) ((x)->rec_data.aux_src_range_)
+#define DST_aux_reg_val(x) ((x)->rec_data.aux_reg_val_)
+#define DST_aux_unit_names(x) ((x)->rec_data.aux_unit_names_)
+#define DST_aux_sect_info(x) ((x)->rec_data.aux_sect_info_)
+
+
+/*
+ * Type codes for loc strings. I'm not entirely certain about all of
+ * these, but they seem to work.
+ * troy@cbme.unsw.EDU.AU
+ * If you find a variable whose location can't be decoded, you should
+ * find out it's code using "dstdump -s filename". It will record an
+ * entry for the variable, and give a text representation of what
+ * the locstring means. Before that explaination there will be a
+ * number. In the LOCSTRING table, that number will appear before
+ * the start of the location string. Location string codes are
+ * five bit codes with a 3 bit argument. Check the high 5 bits of
+ * the one byte code, and figure out where it goes in here.
+ * Then figure out exactly what the meaning is and code it in
+ * dstread.c
+ *
+ * Note that ranged locs mean that the variable is in different locations
+ * depending on the current PC. We ignore these because (a) gcc can't handle
+ * them, and (b), If you don't use high levels of optimisation they won't
+ * occur.
+ */
+typedef enum
+{
+ dst_lsc_end, /* End of string */
+ dst_lsc_indirect, /* Indirect through previous. Arg == 6 */
+ /* Or register ax (x=arg) */
+ dst_lsc_dreg, /* register dx (x=arg) */
+ dst_lsc_03,
+ dst_lsc_section, /* Section (arg+1) */
+ dst_lsc_05,
+ dst_lsc_06,
+ dst_lsc_add, /* Add (arg+1)*2 */
+ dst_lsc_sub, /* Subtract (arg+1)*2 */
+ dst_lsc_09,
+ dst_lsc_0a,
+ dst_lsc_sec_byte, /* Section of next byte+1 */
+ dst_lsc_add_byte, /* Add next byte (arg == 5) or next word
+ * (arg == 6)
+ */
+ dst_lsc_sub_byte, /* Subtract next byte. (arg == 1) or next
+ * word (arg == 6 ?)
+ */
+ dst_lsc_sbreg, /* Stack base register (frame pointer). Arg==0*/
+ dst_lsc_0f,
+ dst_lsc_ranged, /* location is pc dependent */
+ dst_lsc_11,
+ dst_lsc_12,
+ dst_lsc_13,
+ dst_lsc_14,
+ dst_lsc_15,
+ dst_lsc_16,
+ dst_lsc_17,
+ dst_lsc_18,
+ dst_lsc_19,
+ dst_lsc_1a,
+ dst_lsc_1b,
+ dst_lsc_1c,
+ dst_lsc_1d,
+ dst_lsc_1e,
+ dst_lsc_1f
+} dst_loc_string_code_t;
+
+/* If the following occurs after an addition/subtraction, that addition
+ * or subtraction should be multiplied by 256. It's a complete byte, not
+ * a code.
+ */
+
+#define dst_multiply_256 ((char) 0x73)
+
+typedef struct
+{
+ char code : 5;
+ char arg : 3;
+} dst_loc_header_t ALIGNED1;
+
+typedef union
+{
+ dst_loc_header_t header;
+ char data;
+} dst_loc_entry_t ALIGNED1;
+
+#undef ALIGNED1
+#endif /* apollo_dst_h */
diff --git a/gdb/dstread.c b/gdb/dstread.c
new file mode 100644
index 00000000000..d23f9f6ed41
--- /dev/null
+++ b/gdb/dstread.c
@@ -0,0 +1,1665 @@
+/* Read apollo DST symbol tables and convert to internal format, for GDB.
+ Contributed by Troy Rollo, University of NSW (troy@cbme.unsw.edu.au).
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 "obstack.h"
+
+#include "gdb_string.h"
+
+#include "dst.h"
+
+CORE_ADDR cur_src_start_addr, cur_src_end_addr;
+dst_sec blocks_info, lines_info, symbols_info;
+
+/* 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;
+
+static int
+init_dst_sections PARAMS ((int));
+
+static void
+read_dst_symtab PARAMS ((struct objfile *));
+
+static void
+find_dst_sections PARAMS ((bfd *, sec_ptr, PTR));
+
+static void
+dst_symfile_init PARAMS ((struct objfile *));
+
+static void
+dst_new_init PARAMS ((struct objfile *));
+
+static void
+dst_symfile_read PARAMS ((struct objfile *, struct section_offsets *, int));
+
+static void
+dst_symfile_finish PARAMS ((struct objfile *));
+
+static void
+dst_end_symtab PARAMS ((struct objfile *));
+
+static void
+complete_symtab PARAMS ((char *, CORE_ADDR, unsigned int));
+
+static void
+dst_start_symtab PARAMS ((void));
+
+static void
+dst_record_line PARAMS ((int, CORE_ADDR));
+
+/* Manage the vector of line numbers. */
+/* FIXME: Use record_line instead. */
+
+static void
+dst_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.
+ It indicates the start of data for one original source file. */
+/* FIXME: use start_symtab, like coffread.c now does. */
+
+static void
+dst_start_symtab ()
+{
+ /* 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. */
+/* FIXME: Use end_symtab, like coffread.c now does. */
+
+static void
+dst_end_symtab (objfile)
+ struct objfile *objfile;
+{
+ register struct symtab *symtab;
+ register struct blockvector *blockvector;
+ register struct linetable *lv;
+
+ /* Create the blockvector that points to all the file's blocks. */
+
+ blockvector = make_blockvector (objfile);
+
+ /* Now create the symtab object for this source file. */
+ symtab = allocate_symtab (last_source_file, objfile);
+
+ /* Fill in its components. */
+ symtab->blockvector = blockvector;
+ symtab->free_code = free_linetable;
+ symtab->free_ptr = 0;
+ symtab->filename = last_source_file;
+ symtab->dirname = NULL;
+ symtab->debugformat = obsavestring ("Apollo DST", 10,
+ &objfile -> symbol_obstack);
+ lv = line_vector;
+ lv->nitems = line_vector_index;
+ symtab->linetable = (struct linetable *)
+ xrealloc ((char *) lv, (sizeof (struct linetable)
+ + lv->nitems * sizeof (struct linetable_entry)));
+
+ free_named_symtabs (symtab->filename);
+
+ /* Reinitialize for beginning of new file. */
+ line_vector = 0;
+ line_vector_length = -1;
+ last_source_file = NULL;
+}
+
+/* dst_symfile_init ()
+ is the dst-specific initialization routine for reading symbols.
+
+ We will only be called if this is a DST or DST-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 void
+dst_symfile_init (objfile)
+ struct objfile *objfile;
+{
+ asection *section;
+ bfd *abfd = objfile->obfd;
+
+ init_entry_point_info (objfile);
+
+}
+
+/* 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_dst_sections (abfd, asect, vpinfo)
+ bfd *abfd;
+ sec_ptr asect;
+ PTR vpinfo;
+{
+ int size, count;
+ long base;
+ file_ptr offset, maxoff;
+ dst_sec *section;
+
+/* WARNING WILL ROBINSON! ACCESSING BFD-PRIVATE DATA HERE! FIXME! */
+ size = asect->_raw_size;
+ offset = asect->filepos;
+ base = asect->vma;
+/* End of warning */
+
+ section = NULL;
+ if (!strcmp(asect->name, ".blocks"))
+ section = &blocks_info;
+ else if (!strcmp(asect->name, ".lines"))
+ section = &lines_info;
+ else if (!strcmp(asect->name, ".symbols"))
+ section = &symbols_info;
+ if (!section)
+ return;
+ section->size = size;
+ section->position = offset;
+ section->base = base;
+}
+
+
+/* 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 dst_symfile_init. */
+/* FIXME! Addr and Mainline are not used yet -- this will not work for
+ shared libraries or add_file! */
+
+/* ARGSUSED */
+static void
+dst_symfile_read (objfile, section_offsets, mainline)
+ struct objfile *objfile;
+ struct section_offsets *section_offsets;
+ int mainline;
+{
+ bfd *abfd = objfile->obfd;
+ char *name = bfd_get_filename (abfd);
+ int desc;
+ register int val;
+ int num_symbols;
+ int symtab_offset;
+ int stringtab_offset;
+
+ symfile_bfd = abfd; /* Kludge for swap routines */
+
+/* WARNING WILL ROBINSON! ACCESSING BFD-PRIVATE DATA HERE! FIXME! */
+ desc = fileno ((FILE *)(abfd->iostream)); /* File descriptor */
+
+ /* Read the line number table, all at once. */
+ bfd_map_over_sections (abfd, find_dst_sections, (PTR)NULL);
+
+ val = init_dst_sections (desc);
+ if (val < 0)
+ error ("\"%s\": error reading debugging symbol tables\n", 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_dst_symtab (objfile);
+
+ /* Sort symbols alphabetically within each block. */
+
+ {
+ struct symtab *s;
+ for (s = objfile -> symtabs; s != NULL; s = s -> next)
+ {
+ sort_symtab_syms (s);
+ }
+ }
+
+ /* Install any minimal symbols that have been collected as the current
+ minimal symbols for this objfile. */
+
+ install_minimal_symbols (objfile);
+}
+
+static void
+dst_new_init (ignore)
+ struct objfile *ignore;
+{
+ /* Nothin' to do */
+}
+
+/* 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
+dst_symfile_finish (objfile)
+ struct objfile *objfile;
+{
+ /* Nothing to do */
+}
+
+
+/* Get the next line number from the DST. Returns 0 when we hit an
+ * end directive or cannot continue for any other reason.
+ *
+ * Note that ordinary pc deltas are multiplied by two. Apparently
+ * this is what was really intended.
+ */
+static int
+get_dst_line(buffer, pc)
+ signed char **buffer;
+ long *pc;
+{
+ static last_pc = 0;
+ static long last_line = 0;
+ static int last_file = 0;
+ dst_ln_entry_ptr_t entry;
+ int size;
+ dst_src_loc_t *src_loc;
+
+ if (*pc != -1)
+ {
+ last_pc = *pc;
+ *pc = -1;
+ }
+ entry = (dst_ln_entry_ptr_t) *buffer;
+
+ while (dst_ln_ln_delta(*entry) == dst_ln_escape_flag)
+ {
+ switch(entry->esc.esc_code)
+ {
+ case dst_ln_pad:
+ size = 1; /* pad byte */
+ break;
+ case dst_ln_file:
+ /* file escape. Next 4 bytes are a dst_src_loc_t */
+ size = 5;
+ src_loc = (dst_src_loc_t *) (*buffer + 1);
+ last_line = src_loc->line_number;
+ last_file = src_loc->file_index;
+ break;
+ case dst_ln_dln1_dpc1:
+ /* 1 byte line delta, 1 byte pc delta */
+ last_line += (*buffer)[1];
+ last_pc += 2 * (unsigned char) (*buffer)[2];
+ dst_record_line(last_line, last_pc);
+ size = 3;
+ break;
+ case dst_ln_dln2_dpc2:
+ /* 2 bytes line delta, 2 bytes pc delta */
+ last_line += *(short *) (*buffer + 1);
+ last_pc += 2 * (*(short *) (*buffer + 3));
+ size = 5;
+ dst_record_line(last_line, last_pc);
+ break;
+ case dst_ln_ln4_pc4:
+ /* 4 bytes ABSOLUTE line number, 4 bytes ABSOLUTE pc */
+ last_line = *(unsigned long *) (*buffer + 1);
+ last_pc = *(unsigned long *) (*buffer + 5);
+ size = 9;
+ dst_record_line(last_line, last_pc);
+ break;
+ case dst_ln_dln1_dpc0:
+ /* 1 byte line delta, pc delta = 0 */
+ size = 2;
+ last_line+= (*buffer)[1];
+ break;
+ case dst_ln_ln_off_1:
+ /* statement escape, stmt # = 1 (2nd stmt on line) */
+ size = 1;
+ break;
+ case dst_ln_ln_off:
+ /* statement escape, stmt # = next byte */
+ size = 2;
+ break;
+ case dst_ln_entry:
+ /* entry escape, next byte is entry number */
+ size = 2;
+ break;
+ case dst_ln_exit:
+ /* exit escape */
+ size = 1;
+ break;
+ case dst_ln_stmt_end:
+ /* gap escape, 4 bytes pc delta */
+ size = 5;
+ /* last_pc += 2 * (*(long *) (*buffer + 1)); */
+ /* Apparently this isn't supposed to actually modify
+ * the pc value. Totally weird.
+ */
+ break;
+ case dst_ln_escape_11:
+ case dst_ln_escape_12:
+ case dst_ln_escape_13:
+ size = 1;
+ break;
+ case dst_ln_nxt_byte:
+ /* This shouldn't happen. If it does, we're SOL */
+ return 0;
+ break;
+ case dst_ln_end:
+ /* end escape, final entry follows */
+ return 0;
+ }
+ *buffer += (size < 0) ? -size : size;
+ entry = (dst_ln_entry_ptr_t) *buffer;
+ }
+ last_line += dst_ln_ln_delta(*entry);
+ last_pc += entry->delta.pc_delta * 2;
+ (*buffer)++;
+ dst_record_line(last_line, last_pc);
+ return 1;
+}
+
+static void
+enter_all_lines(buffer, address)
+ char *buffer;
+ long address;
+{
+ if (buffer)
+ while (get_dst_line(&buffer, &address));
+}
+
+static int
+get_dst_entry(buffer, ret_entry)
+ char *buffer;
+ dst_rec_ptr_t *ret_entry;
+{
+ int size;
+ dst_rec_ptr_t entry;
+ static int last_type;
+ int ar_size;
+ static unsigned lu3;
+
+ entry = (dst_rec_ptr_t) buffer;
+ switch(entry->rec_type)
+ {
+ case dst_typ_pad:
+ size = 0;
+ break;
+ case dst_typ_comp_unit:
+ size = sizeof(DST_comp_unit(entry));
+ break;
+ case dst_typ_section_tab:
+ size = sizeof(DST_section_tab(entry))
+ + ((int) DST_section_tab(entry).number_of_sections
+ - dst_dummy_array_size) * sizeof(long);
+ break;
+ case dst_typ_file_tab:
+ size = sizeof(DST_file_tab(entry))
+ + ((int) DST_file_tab(entry).number_of_files
+ - dst_dummy_array_size) * sizeof(dst_file_desc_t);
+ break;
+ case dst_typ_block:
+ size = sizeof(DST_block(entry))
+ + ((int) DST_block(entry).n_of_code_ranges
+ - dst_dummy_array_size) * sizeof(dst_code_range_t);
+ break;
+ case dst_typ_5:
+ size = -1;
+ break;
+ case dst_typ_var:
+ size = sizeof(DST_var(entry)) -
+ sizeof(dst_var_loc_long_t) * dst_dummy_array_size +
+ DST_var(entry).no_of_locs *
+ ( DST_var(entry).short_locs ?
+ sizeof(dst_var_loc_short_t):
+ sizeof(dst_var_loc_long_t));
+ break;
+ case dst_typ_pointer:
+ size = sizeof(DST_pointer(entry));
+ break;
+ case dst_typ_array:
+ size = sizeof(DST_array(entry));
+ break;
+ case dst_typ_subrange:
+ size = sizeof(DST_subrange(entry));
+ break;
+ case dst_typ_set:
+ size = sizeof(DST_set(entry));
+ break;
+ case dst_typ_implicit_enum:
+ size = sizeof(DST_implicit_enum(entry))
+ + ((int) DST_implicit_enum(entry).nelems
+ - dst_dummy_array_size) * sizeof(dst_rel_offset_t);
+ break;
+ case dst_typ_explicit_enum:
+ size = sizeof(DST_explicit_enum(entry))
+ + ((int) DST_explicit_enum(entry).nelems
+ - dst_dummy_array_size) * sizeof(dst_enum_elem_t);
+ break;
+ case dst_typ_short_rec:
+ size = sizeof(DST_short_rec(entry))
+ + DST_short_rec(entry).nfields * sizeof(dst_short_field_t)
+ - dst_dummy_array_size * sizeof(dst_field_t);
+ break;
+ case dst_typ_short_union:
+ size = sizeof(DST_short_union(entry))
+ + DST_short_union(entry).nfields * sizeof(dst_short_field_t)
+ - dst_dummy_array_size * sizeof(dst_field_t);
+ break;
+ case dst_typ_file:
+ size = sizeof(DST_file(entry));
+ break;
+ case dst_typ_offset:
+ size = sizeof(DST_offset(entry));
+ break;
+ case dst_typ_alias:
+ size = sizeof(DST_alias(entry));
+ break;
+ case dst_typ_signature:
+ size = sizeof(DST_signature(entry)) +
+ ((int) DST_signature(entry).nargs -
+ dst_dummy_array_size) * sizeof(dst_arg_t);
+ break;
+ case dst_typ_21:
+ size = -1;
+ break;
+ case dst_typ_old_label:
+ size = sizeof(DST_old_label(entry));
+ break;
+ case dst_typ_scope:
+ size = sizeof(DST_scope(entry));
+ break;
+ case dst_typ_end_scope:
+ size = 0;
+ break;
+ case dst_typ_25:
+ case dst_typ_26:
+ size = -1;
+ break;
+ case dst_typ_string_tab:
+ case dst_typ_global_name_tab:
+ size = sizeof(DST_string_tab(entry))
+ + DST_string_tab(entry).length
+ - dst_dummy_array_size;
+ break;
+ case dst_typ_forward:
+ size = sizeof(DST_forward(entry));
+ get_dst_entry((char *) entry + DST_forward(entry).rec_off, &entry);
+ break;
+ case dst_typ_aux_size:
+ size = sizeof(DST_aux_size(entry));
+ break;
+ case dst_typ_aux_align:
+ size = sizeof(DST_aux_align(entry));
+ break;
+ case dst_typ_aux_field_size:
+ size = sizeof(DST_aux_field_size(entry));
+ break;
+ case dst_typ_aux_field_off:
+ size = sizeof(DST_aux_field_off(entry));
+ break;
+ case dst_typ_aux_field_align:
+ size = sizeof(DST_aux_field_align(entry));
+ break;
+ case dst_typ_aux_qual:
+ size = sizeof(DST_aux_qual(entry));
+ break;
+ case dst_typ_aux_var_bound:
+ size = sizeof(DST_aux_var_bound(entry));
+ break;
+ case dst_typ_extension:
+ size = DST_extension(entry).rec_size;
+ break;
+ case dst_typ_string:
+ size = sizeof(DST_string(entry));
+ break;
+ case dst_typ_old_entry:
+ size = 48; /* Obsolete entry type */
+ break;
+ case dst_typ_const:
+ size = sizeof(DST_const(entry))
+ + DST_const(entry).value.length
+ - sizeof(DST_const(entry).value.val);
+ break;
+ case dst_typ_reference:
+ size = sizeof(DST_reference(entry));
+ break;
+ case dst_typ_old_record:
+ case dst_typ_old_union:
+ case dst_typ_record:
+ case dst_typ_union:
+ size = sizeof(DST_record(entry))
+ + ((int) DST_record(entry).nfields
+ - dst_dummy_array_size) * sizeof(dst_field_t);
+ break;
+ case dst_typ_aux_type_deriv:
+ size = sizeof(DST_aux_type_deriv(entry));
+ break;
+ case dst_typ_locpool:
+ size = sizeof(DST_locpool(entry))
+ + ((int) DST_locpool(entry).length -
+ dst_dummy_array_size);
+ break;
+ case dst_typ_variable:
+ size = sizeof(DST_variable(entry));
+ break;
+ case dst_typ_label:
+ size = sizeof(DST_label(entry));
+ break;
+ case dst_typ_entry:
+ size = sizeof(DST_entry(entry));
+ break;
+ case dst_typ_aux_lifetime:
+ size = sizeof(DST_aux_lifetime(entry));
+ break;
+ case dst_typ_aux_ptr_base:
+ size = sizeof(DST_aux_ptr_base(entry));
+ break;
+ case dst_typ_aux_src_range:
+ size = sizeof(DST_aux_src_range(entry));
+ break;
+ case dst_typ_aux_reg_val:
+ size = sizeof(DST_aux_reg_val(entry));
+ break;
+ case dst_typ_aux_unit_names:
+ size = sizeof(DST_aux_unit_names(entry))
+ + ((int) DST_aux_unit_names(entry).number_of_names
+ - dst_dummy_array_size) * sizeof(dst_rel_offset_t);
+ break;
+ case dst_typ_aux_sect_info:
+ size = sizeof(DST_aux_sect_info(entry))
+ + ((int) DST_aux_sect_info(entry).number_of_refs
+ - dst_dummy_array_size) * sizeof(dst_sect_ref_t);
+ break;
+ default:
+ size = -1;
+ break;
+ }
+ if (size == -1)
+ {
+ fprintf_unfiltered(gdb_stderr, "Warning: unexpected DST entry type (%d) found\nLast valid entry was of type: %d\n",
+ (int) entry->rec_type,
+ last_type);
+ fprintf_unfiltered(gdb_stderr, "Last unknown_3 value: %d\n", lu3);
+ size = 0;
+ }
+ else
+ last_type = entry->rec_type;
+ if (size & 1) /* Align on a word boundary */
+ size++;
+ size += 2;
+ *ret_entry = entry;
+ return size;
+}
+
+static int next_dst_entry(buffer, entry, table)
+ char **buffer;
+ dst_rec_ptr_t *entry;
+ dst_sec *table;
+{
+ if (*buffer - table->buffer >= table->size)
+ {
+ *entry = NULL;
+ return 0;
+ }
+ *buffer += get_dst_entry(*buffer, entry);
+ return 1;
+}
+
+#define NEXT_BLK(a, b) next_dst_entry(a, b, &blocks_info)
+#define NEXT_SYM(a, b) next_dst_entry(a, b, &symbols_info)
+#define DST_OFFSET(a, b) ((char *) (a) + (b))
+
+static dst_rec_ptr_t section_table = NULL;
+
+char *
+get_sec_ref(ref)
+ dst_sect_ref_t *ref;
+{
+ dst_sec *section = NULL;
+ long offset;
+
+ if (!section_table || !ref->sect_index)
+ return NULL;
+ offset = DST_section_tab(section_table).section_base[ref->sect_index-1]
+ + ref->sect_offset;
+ if (offset >= blocks_info.base &&
+ offset < blocks_info.base + blocks_info.size)
+ section = &blocks_info;
+ else if (offset >= symbols_info.base &&
+ offset < symbols_info.base + symbols_info.size)
+ section = &symbols_info;
+ else if (offset >= lines_info.base &&
+ offset < lines_info.base + lines_info.size)
+ section = &lines_info;
+ if (!section)
+ return NULL;
+ return section->buffer + (offset - section->base);
+}
+
+CORE_ADDR
+dst_get_addr(int section, long offset)
+{
+ if (!section_table || !section)
+ return 0;
+ return DST_section_tab(section_table).section_base[section-1] + offset;
+}
+
+CORE_ADDR
+dst_sym_addr(ref)
+ dst_sect_ref_t *ref;
+{
+ if (!section_table || !ref->sect_index)
+ return 0;
+ return DST_section_tab(section_table).section_base[ref->sect_index-1]
+ + ref->sect_offset;
+}
+
+static struct type *
+create_new_type(objfile)
+ struct objfile *objfile;
+{
+ struct type *type;
+
+ type = (struct type *)
+ obstack_alloc (&objfile->symbol_obstack, sizeof (struct type));
+ memset(type, 0, sizeof(struct type));
+ return type;
+}
+
+static struct symbol *
+create_new_symbol(objfile, name)
+ struct objfile *objfile;
+ char *name;
+{
+ struct symbol *sym = (struct symbol *)
+ obstack_alloc (&objfile->symbol_obstack, sizeof (struct symbol));
+ memset (sym, 0, sizeof (struct symbol));
+ SYMBOL_NAME (sym) = obsavestring (name, strlen (name),
+ &objfile->symbol_obstack);
+ SYMBOL_VALUE (sym) = 0;
+ SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
+
+ SYMBOL_CLASS (sym) = LOC_BLOCK;
+ return sym;
+};
+
+static struct type *
+decode_dst_type PARAMS ((struct objfile *, dst_rec_ptr_t));
+
+static struct type *
+decode_type_desc(objfile, type_desc, base)
+ struct objfile *objfile;
+ dst_type_t *type_desc;
+ dst_rec_ptr_t base;
+{
+ struct type *type;
+ dst_rec_ptr_t entry;
+ if (type_desc->std_type.user_defined_type)
+ {
+ entry = (dst_rec_ptr_t) DST_OFFSET(base,
+ dst_user_type_offset(*type_desc));
+ type = decode_dst_type(objfile, entry);
+ }
+ else
+ {
+ switch(type_desc->std_type.dtc)
+ {
+ case dst_int8_type:
+ type = builtin_type_signed_char;
+ break;
+ case dst_int16_type:
+ type = builtin_type_short;
+ break;
+ case dst_int32_type:
+ type = builtin_type_long;
+ break;
+ case dst_uint8_type:
+ type = builtin_type_unsigned_char;
+ break;
+ case dst_uint16_type:
+ type = builtin_type_unsigned_short;
+ break;
+ case dst_uint32_type:
+ type = builtin_type_unsigned_long;
+ break;
+ case dst_real32_type:
+ type = builtin_type_float;
+ break;
+ case dst_real64_type:
+ type = builtin_type_double;
+ break;
+ case dst_complex_type:
+ type = builtin_type_complex;
+ break;
+ case dst_dcomplex_type:
+ type = builtin_type_double_complex;
+ break;
+ case dst_bool8_type:
+ type = builtin_type_char;
+ break;
+ case dst_bool16_type:
+ type = builtin_type_short;
+ break;
+ case dst_bool32_type:
+ type = builtin_type_long;
+ break;
+ case dst_char_type:
+ type = builtin_type_char;
+ break;
+ /* The next few are more complex. I will take care
+ * of them properly at a later point.
+ */
+ case dst_string_type:
+ type = builtin_type_void;
+ break;
+ case dst_ptr_type:
+ type = builtin_type_void;
+ break;
+ case dst_set_type:
+ type = builtin_type_void;
+ break;
+ case dst_proc_type:
+ type = builtin_type_void;
+ break;
+ case dst_func_type:
+ type = builtin_type_void;
+ break;
+ /* Back tto some ordinary ones */
+ case dst_void_type:
+ type = builtin_type_void;
+ break;
+ case dst_uchar_type:
+ type = builtin_type_unsigned_char;
+ break;
+ default:
+ type = builtin_type_void;
+ break;
+ }
+ }
+ return type;
+}
+
+struct structure_list
+ {
+ struct structure_list *next;
+ struct type *type;
+ };
+
+static struct structure_list *struct_list = NULL;
+
+static struct type *
+find_dst_structure(name)
+ char *name;
+{
+ struct structure_list *element;
+
+ for (element = struct_list; element; element = element->next)
+ if (!strcmp(name, TYPE_NAME(element->type)))
+ return element->type;
+ return NULL;
+}
+
+
+static struct type *
+decode_dst_structure(objfile, entry, code, version)
+ struct objfile *objfile;
+ dst_rec_ptr_t entry;
+ int code;
+ int version;
+{
+ struct type *type, *child_type;
+ char *struct_name;
+ char *name, *field_name;
+ int i;
+ int fieldoffset, fieldsize;
+ dst_type_t type_desc;
+ struct structure_list *element;
+
+ struct_name = DST_OFFSET(entry, DST_record(entry).noffset);
+ name = concat( (code == TYPE_CODE_UNION)?"union ":"struct ",
+ struct_name, NULL);
+ type = find_dst_structure(name);
+ if (type)
+ {
+ free((PTR) name);
+ return type;
+ }
+ type = create_new_type(objfile);
+ TYPE_NAME(type) = obstack_copy0 (&objfile->symbol_obstack,
+ name, strlen(name));
+ free((PTR) name);
+ TYPE_CODE(type) = code;
+ TYPE_LENGTH(type) = DST_record(entry).size;
+ TYPE_NFIELDS(type) = DST_record(entry).nfields;
+ TYPE_FIELDS(type) = (struct field *)
+ obstack_alloc (&objfile->symbol_obstack, sizeof (struct field) *
+ DST_record(entry).nfields);
+ fieldoffset = fieldsize = 0;
+ INIT_CPLUS_SPECIFIC(type);
+ element = (struct structure_list *)
+ xmalloc(sizeof(struct structure_list));
+ element->type = type;
+ element->next = struct_list;
+ struct_list = element;
+ for (i = 0; i < DST_record(entry).nfields; i++)
+ {
+ switch (version)
+ {
+ case 2:
+ field_name = DST_OFFSET(entry,
+ DST_record(entry).f.ofields[i].noffset);
+ fieldoffset = DST_record(entry).f.ofields[i].foffset*8 +
+ DST_record(entry).f.ofields[i].bit_offset;
+ fieldsize = DST_record(entry).f.ofields[i].size;
+ type_desc = DST_record(entry).f.ofields[i].type_desc;
+ break;
+ case 1:
+ field_name = DST_OFFSET(entry,
+ DST_record(entry).f.fields[i].noffset);
+ type_desc = DST_record(entry).f.fields[i].type_desc;
+ switch(DST_record(entry).f.fields[i].f.field_loc.format_tag)
+ {
+ case dst_field_byte:
+ fieldoffset = DST_record(entry).f.
+ fields[i].f.field_byte.offset * 8;
+ fieldsize = -1;
+ break;
+ case dst_field_bit:
+ fieldoffset = DST_record(entry).f.
+ fields[i].f.field_bit.byte_offset * 8 +
+ DST_record(entry).f.
+ fields[i].f.field_bit.bit_offset;
+ fieldsize = DST_record(entry).f.
+ fields[i].f.field_bit.nbits;
+ break;
+ case dst_field_loc:
+ fieldoffset += fieldsize;
+ fieldsize = -1;
+ break;
+ }
+ break;
+ case 0:
+ field_name = DST_OFFSET(entry,
+ DST_record(entry).f.sfields[i].noffset);
+ fieldoffset = DST_record(entry).f.sfields[i].foffset;
+ type_desc = DST_record(entry).f.sfields[i].type_desc;
+ if (i < DST_record(entry).nfields - 1)
+ fieldsize = DST_record(entry).f.sfields[i+1].foffset;
+ else
+ fieldsize = DST_record(entry).size;
+ fieldsize -= fieldoffset;
+ fieldoffset *= 8;
+ fieldsize *= 8;
+ }
+ TYPE_FIELDS(type)[i].name =
+ obstack_copy0 (&objfile->symbol_obstack,
+ field_name, strlen(field_name));
+ TYPE_FIELDS(type)[i].type = decode_type_desc(objfile,
+ &type_desc,
+ entry);
+ if (fieldsize == -1)
+ fieldsize = TYPE_LENGTH(TYPE_FIELDS(type)[i].type) *
+ 8;
+ TYPE_FIELDS(type)[i].bitsize = fieldsize;
+ TYPE_FIELDS(type)[i].bitpos = fieldoffset;
+ }
+ return type;
+}
+
+static struct type *
+decode_dst_type(objfile, entry)
+ struct objfile *objfile;
+ dst_rec_ptr_t entry;
+{
+ struct type *child_type, *type, *range_type, *index_type;
+
+ switch(entry->rec_type)
+ {
+ case dst_typ_var:
+ return decode_type_desc(objfile,
+ &DST_var(entry).type_desc,
+ entry);
+ break;
+ case dst_typ_variable:
+ return decode_type_desc(objfile,
+ &DST_variable(entry).type_desc,
+ entry);
+ break;
+ case dst_typ_short_rec:
+ return decode_dst_structure(objfile, entry, TYPE_CODE_STRUCT,0);
+ case dst_typ_short_union:
+ return decode_dst_structure(objfile, entry, TYPE_CODE_UNION, 0);
+ case dst_typ_union:
+ return decode_dst_structure(objfile, entry, TYPE_CODE_UNION, 1);
+ case dst_typ_record:
+ return decode_dst_structure(objfile, entry, TYPE_CODE_STRUCT,1);
+ case dst_typ_old_union:
+ return decode_dst_structure(objfile, entry, TYPE_CODE_UNION, 2);
+ case dst_typ_old_record:
+ return decode_dst_structure(objfile, entry, TYPE_CODE_STRUCT,2);
+ case dst_typ_pointer:
+ return make_pointer_type(
+ decode_type_desc(objfile,
+ &DST_pointer(entry).type_desc,
+ entry),
+ NULL);
+ case dst_typ_array:
+ child_type = decode_type_desc(objfile,
+ &DST_pointer(entry).type_desc,
+ entry);
+ index_type = lookup_fundamental_type(objfile,
+ FT_INTEGER);
+ range_type = create_range_type ((struct type *) NULL,
+ index_type, DST_array(entry).lo_bound,
+ DST_array(entry).hi_bound);
+ return create_array_type ((struct type *) NULL, child_type,
+ range_type);
+ case dst_typ_alias:
+ return decode_type_desc(objfile,
+ &DST_alias(entry).type_desc,
+ entry);
+ default:
+ return builtin_type_int;
+ }
+}
+
+struct symbol_list {
+ struct symbol_list *next;
+ struct symbol *symbol;
+};
+
+static struct symbol_list *dst_global_symbols = NULL;
+static int total_globals = 0;
+
+static void
+decode_dst_locstring(locstr, sym)
+ char *locstr;
+ struct symbol *sym;
+{
+ dst_loc_entry_t *entry, *next_entry;
+ CORE_ADDR temp;
+ int count = 0;
+
+ while(1)
+ {
+ if (count++ == 100)
+ {
+ fprintf_unfiltered(gdb_stderr, "Error reading locstring\n");
+ break;
+ }
+ entry = (dst_loc_entry_t *) locstr;
+ next_entry = (dst_loc_entry_t *) (locstr + 1);
+ switch (entry->header.code)
+ {
+ case dst_lsc_end: /* End of string */
+ return;
+ case dst_lsc_indirect:/* Indirect through previous. Arg == 6 */
+ /* Or register ax x == arg */
+ if (entry->header.arg < 6)
+ {
+ SYMBOL_CLASS(sym) = LOC_REGISTER;
+ SYMBOL_VALUE(sym) = entry->header.arg + 8;
+ }
+ /* We predict indirects */
+ locstr++;
+ break;
+ case dst_lsc_dreg:
+ SYMBOL_CLASS(sym) = LOC_REGISTER;
+ SYMBOL_VALUE(sym) = entry->header.arg;
+ locstr++;
+ break;
+ case dst_lsc_section:/* Section (arg+1) */
+ SYMBOL_VALUE(sym) = dst_get_addr(entry->header.arg+1, 0);
+ locstr++;
+ break;
+ case dst_lsc_sec_byte: /* Section (next_byte+1) */
+ SYMBOL_VALUE(sym) = dst_get_addr(locstr[1]+1, 0);
+ locstr+=2;
+ break;
+ case dst_lsc_add: /* Add (arg+1)*2 */
+ case dst_lsc_sub: /* Subtract (arg+1)*2 */
+ temp = (entry->header.arg + 1) * 2;
+ locstr++;
+ if (*locstr == dst_multiply_256)
+ {
+ temp <<= 8;
+ locstr++;
+ }
+ switch(entry->header.code)
+ {
+ case dst_lsc_add:
+ if (SYMBOL_CLASS(sym) == LOC_LOCAL)
+ SYMBOL_CLASS(sym) = LOC_ARG;
+ SYMBOL_VALUE(sym) += temp;
+ break;
+ case dst_lsc_sub:
+ SYMBOL_VALUE(sym) -= temp;
+ break;
+ }
+ break;
+ case dst_lsc_add_byte:
+ case dst_lsc_sub_byte:
+ switch (entry->header.arg & 0x03)
+ {
+ case 1:
+ temp = (unsigned char) locstr[1];
+ locstr += 2;
+ break;
+ case 2:
+ temp = * (unsigned short *) (locstr + 1);
+ locstr += 3;
+ break;
+ case 3:
+ temp = * (unsigned long *) (locstr + 1);
+ locstr += 5;
+ break;
+ }
+ if (*locstr == dst_multiply_256)
+ {
+ temp <<= 8;
+ locstr++;
+ }
+ switch(entry->header.code)
+ {
+ case dst_lsc_add_byte:
+ if (SYMBOL_CLASS(sym) == LOC_LOCAL)
+ SYMBOL_CLASS(sym) = LOC_ARG;
+ SYMBOL_VALUE(sym) += temp;
+ break;
+ case dst_lsc_sub_byte:
+ SYMBOL_VALUE(sym) -= temp;
+ break;
+ }
+ break;
+ case dst_lsc_sbreg: /* Stack base register (frame pointer). Arg==0*/
+ if (next_entry->header.code != dst_lsc_indirect)
+ {
+ SYMBOL_VALUE(sym) = 0;
+ SYMBOL_CLASS(sym) = LOC_STATIC;
+ return;
+ }
+ SYMBOL_VALUE(sym) = 0;
+ SYMBOL_CLASS(sym) = LOC_LOCAL;
+ locstr++;
+ break;
+ default:
+ SYMBOL_VALUE(sym) = 0;
+ SYMBOL_CLASS(sym) = LOC_STATIC;
+ return;
+ }
+ }
+}
+
+static struct symbol_list *
+process_dst_symbols(objfile, entry, name, nsyms_ret)
+ struct objfile *objfile;
+ dst_rec_ptr_t entry;
+ char *name;
+ int *nsyms_ret;
+{
+ struct symbol_list *list = NULL, *element;
+ struct symbol *sym;
+ char *symname;
+ int nsyms = 0;
+ char *location;
+ long line;
+ dst_type_t symtype;
+ struct type *type;
+ dst_var_attr_t attr;
+ dst_var_loc_t loc_type;
+ unsigned loc_index;
+ long loc_value;
+
+ if (!entry)
+ {
+ *nsyms_ret = 0;
+ return NULL;
+ }
+ location = (char *) entry;
+ while (NEXT_SYM(&location, &entry) &&
+ entry->rec_type != dst_typ_end_scope)
+ {
+ if (entry->rec_type == dst_typ_var)
+ {
+ if (DST_var(entry).short_locs)
+ {
+ loc_type = DST_var(entry).locs.shorts[0].loc_type;
+ loc_index = DST_var(entry).locs.shorts[0].loc_index;
+ loc_value = DST_var(entry).locs.shorts[0].location;
+ }
+ else
+ {
+ loc_type = DST_var(entry).locs.longs[0].loc_type;
+ loc_index = DST_var(entry).locs.longs[0].loc_index;
+ loc_value = DST_var(entry).locs.longs[0].location;
+ }
+ if (loc_type == dst_var_loc_external)
+ continue;
+ symname = DST_OFFSET(entry, DST_var(entry).noffset);
+ line = DST_var(entry).src_loc.line_number;
+ symtype = DST_var(entry).type_desc;
+ attr = DST_var(entry).attributes;
+ }
+ else if (entry->rec_type == dst_typ_variable)
+ {
+ symname = DST_OFFSET(entry,
+ DST_variable(entry).noffset);
+ line = DST_variable(entry).src_loc.line_number;
+ symtype = DST_variable(entry).type_desc;
+ attr = DST_variable(entry).attributes;
+ }
+ else
+ {
+ continue;
+ }
+ if (symname && name && !strcmp(symname, name))
+ /* It's the function return value */
+ continue;
+ sym = create_new_symbol(objfile, symname);
+
+ if ((attr & (1<<dst_var_attr_global)) ||
+ (attr & (1<<dst_var_attr_static)))
+ SYMBOL_CLASS(sym) = LOC_STATIC;
+ else
+ SYMBOL_CLASS(sym) = LOC_LOCAL;
+ SYMBOL_LINE(sym) = line;
+ SYMBOL_TYPE(sym) = decode_type_desc(objfile, &symtype,
+ entry);
+ SYMBOL_VALUE(sym) = 0;
+ switch (entry->rec_type)
+ {
+ case dst_typ_var:
+ switch(loc_type)
+ {
+ case dst_var_loc_abs:
+ SYMBOL_VALUE_ADDRESS(sym) = loc_value;
+ break;
+ case dst_var_loc_sect_off:
+ case dst_var_loc_ind_sect_off: /* What is this? */
+ SYMBOL_VALUE_ADDRESS(sym) = dst_get_addr(
+ loc_index,
+ loc_value);
+ break;
+ case dst_var_loc_ind_reg_rel: /* What is this? */
+ case dst_var_loc_reg_rel:
+ /* If it isn't fp relative, specify the
+ * register it's relative to.
+ */
+ if (loc_index)
+ {
+ sym->aux_value.basereg = loc_index;
+ }
+ SYMBOL_VALUE(sym) = loc_value;
+ if (loc_value > 0 &&
+ SYMBOL_CLASS(sym) == LOC_BASEREG)
+ SYMBOL_CLASS(sym) = LOC_BASEREG_ARG;
+ break;
+ case dst_var_loc_reg:
+ SYMBOL_VALUE(sym) = loc_index;
+ SYMBOL_CLASS(sym) = LOC_REGISTER;
+ break;
+ }
+ break;
+ case dst_typ_variable:
+ /* External variable..... don't try to interpret
+ * its nonexistant locstring.
+ */
+ if (DST_variable(entry).loffset == -1)
+ continue;
+ decode_dst_locstring(DST_OFFSET(entry,
+ DST_variable(entry).loffset),
+ sym);
+ }
+ element = (struct symbol_list *)
+ xmalloc(sizeof(struct symbol_list));
+
+ if (attr & (1<<dst_var_attr_global))
+ {
+ element->next = dst_global_symbols;
+ dst_global_symbols = element;
+ total_globals++;
+ }
+ else
+ {
+ element->next = list;
+ list = element;
+ nsyms++;
+ }
+ element->symbol = sym;
+ }
+ *nsyms_ret = nsyms;
+ return list;
+}
+
+
+static struct symbol *
+process_dst_function(objfile, entry, name, address)
+ struct objfile *objfile;
+ dst_rec_ptr_t entry;
+ char *name;
+ CORE_ADDR address;
+{
+ struct symbol *sym;
+ struct type *type, *ftype;
+ dst_rec_ptr_t sym_entry, typ_entry;
+ char *location;
+ struct symbol_list *element;
+
+ type = builtin_type_int;
+ sym = create_new_symbol(objfile, name);
+ SYMBOL_CLASS(sym) = LOC_BLOCK;
+
+ if (entry)
+ {
+ location = (char *) entry;
+ do
+ {
+ NEXT_SYM(&location, &sym_entry);
+ } while (sym_entry && sym_entry->rec_type != dst_typ_signature);
+
+ if (sym_entry)
+ {
+ SYMBOL_LINE(sym) =
+ DST_signature(sym_entry).src_loc.line_number;
+ if (DST_signature(sym_entry).result)
+ {
+ typ_entry = (dst_rec_ptr_t)
+ DST_OFFSET(sym_entry,
+ DST_signature(sym_entry).result);
+ type = decode_dst_type(objfile, typ_entry);
+ }
+ }
+ }
+
+ if (!type->function_type)
+ {
+ ftype = create_new_type(objfile);
+ type->function_type = ftype;
+ ftype->target_type = type;
+ ftype->code = TYPE_CODE_FUNC;
+ }
+ SYMBOL_TYPE(sym) = type->function_type;
+
+ /* Now add ourselves to the global symbols list */
+ element = (struct symbol_list *)
+ xmalloc(sizeof(struct symbol_list));
+
+ element->next = dst_global_symbols;
+ dst_global_symbols = element;
+ total_globals++;
+ element->symbol = sym;
+
+ return sym;
+}
+
+static struct block *
+process_dst_block(objfile, entry)
+ struct objfile *objfile;
+ dst_rec_ptr_t entry;
+{
+ struct block *block;
+ struct symbol *function = NULL;
+ CORE_ADDR address;
+ long size;
+ char *name;
+ dst_rec_ptr_t child_entry, symbol_entry;
+ struct block *child_block;
+ int total_symbols = 0;
+ char fake_name[20];
+ static long fake_seq = 0;
+ struct symbol_list *symlist, *nextsym;
+ int symnum;
+
+ if (DST_block(entry).noffset)
+ name = DST_OFFSET(entry, DST_block(entry).noffset);
+ else
+ name = NULL;
+ if (DST_block(entry).n_of_code_ranges)
+ {
+ address = dst_sym_addr(
+ &DST_block(entry).code_ranges[0].code_start);
+ size = DST_block(entry).code_ranges[0].code_size;
+ }
+ else
+ {
+ address = -1;
+ size = 0;
+ }
+ symbol_entry = (dst_rec_ptr_t) get_sec_ref(&DST_block(entry).symbols_start);
+ switch(DST_block(entry).block_type)
+ {
+ /* These are all really functions. Even the "program" type.
+ * This is because the Apollo OS was written in Pascal, and
+ * in Pascal, the main procedure is described as the Program.
+ * Cute, huh?
+ */
+ case dst_block_procedure:
+ case dst_block_function:
+ case dst_block_subroutine:
+ case dst_block_program:
+ prim_record_minimal_symbol(name, address, mst_text, objfile);
+ function = process_dst_function(
+ objfile,
+ symbol_entry,
+ name,
+ address);
+ enter_all_lines(get_sec_ref(&DST_block(entry).code_ranges[0].lines_start), address);
+ break;
+ case dst_block_block_data:
+ break;
+
+ default:
+ /* GDB has to call it something, and the module name
+ * won't cut it
+ */
+ sprintf(fake_name, "block_%08lx", fake_seq++);
+ function = process_dst_function(
+ objfile, NULL, fake_name, address);
+ break;
+ }
+ symlist = process_dst_symbols(objfile, symbol_entry,
+ name, &total_symbols);
+ block = (struct block *)
+ obstack_alloc (&objfile->symbol_obstack,
+ sizeof (struct block) +
+ (total_symbols - 1) * sizeof (struct symbol *));
+
+ symnum = 0;
+ while (symlist)
+ {
+ nextsym = symlist->next;
+
+ block->sym[symnum] = symlist->symbol;
+
+ free((PTR) symlist);
+ symlist = nextsym;
+ symnum++;
+ }
+ BLOCK_NSYMS (block) = total_symbols;
+ BLOCK_START (block) = address;
+ BLOCK_END (block) = address + size;
+ BLOCK_SUPERBLOCK (block) = 0;
+ if (function)
+ {
+ SYMBOL_BLOCK_VALUE (function) = block;
+ BLOCK_FUNCTION (block) = function;
+ }
+ else
+ BLOCK_FUNCTION (block) = 0;
+
+ if (DST_block(entry).child_block_off)
+ {
+ child_entry = (dst_rec_ptr_t) DST_OFFSET(entry,
+ DST_block(entry).child_block_off);
+ while (child_entry)
+ {
+ child_block = process_dst_block(objfile, child_entry);
+ if (child_block)
+ {
+ if (BLOCK_START(child_block) <
+ BLOCK_START(block) ||
+ BLOCK_START(block) == -1)
+ BLOCK_START(block) =
+ BLOCK_START(child_block);
+ if (BLOCK_END(child_block) >
+ BLOCK_END(block) ||
+ BLOCK_END(block) == -1)
+ BLOCK_END(block) =
+ BLOCK_END(child_block);
+ BLOCK_SUPERBLOCK (child_block) = block;
+ }
+ if (DST_block(child_entry).sibling_block_off)
+ child_entry = (dst_rec_ptr_t) DST_OFFSET(
+ child_entry,
+ DST_block(child_entry).sibling_block_off);
+ else
+ child_entry = NULL;
+ }
+ }
+ record_pending_block (objfile, block, NULL);
+ return block;
+}
+
+
+static void
+read_dst_symtab (objfile)
+ struct objfile *objfile;
+{
+ char *buffer;
+ dst_rec_ptr_t entry, file_table, root_block;
+ char *source_file;
+ struct block *block, *global_block;
+ int symnum;
+ struct symbol_list *nextsym;
+ int module_num = 0;
+ struct structure_list *element;
+
+ current_objfile = objfile;
+ buffer = blocks_info.buffer;
+ while (NEXT_BLK(&buffer, &entry))
+ {
+ if (entry->rec_type == dst_typ_comp_unit)
+ {
+ file_table = (dst_rec_ptr_t) DST_OFFSET(entry,
+ DST_comp_unit(entry).file_table);
+ section_table = (dst_rec_ptr_t) DST_OFFSET(entry,
+ DST_comp_unit(entry).section_table);
+ root_block = (dst_rec_ptr_t) DST_OFFSET(entry,
+ DST_comp_unit(entry).root_block_offset);
+ source_file = DST_OFFSET(file_table,
+ DST_file_tab(file_table).files[0].noffset);
+ /* Point buffer to the start of the next comp_unit */
+ buffer = DST_OFFSET(entry,
+ DST_comp_unit(entry).data_size);
+ dst_start_symtab();
+
+ block = process_dst_block(objfile, root_block);
+
+ global_block = (struct block *)
+ obstack_alloc (&objfile->symbol_obstack,
+ sizeof (struct block) +
+ (total_globals - 1) *
+ sizeof (struct symbol *));
+ BLOCK_NSYMS(global_block) = total_globals;
+ for (symnum = 0; symnum < total_globals; symnum++)
+ {
+ nextsym = dst_global_symbols->next;
+
+ global_block->sym[symnum] =
+ dst_global_symbols->symbol;
+
+ free((PTR) dst_global_symbols);
+ dst_global_symbols = nextsym;
+ }
+ dst_global_symbols = NULL;
+ total_globals = 0;
+ BLOCK_FUNCTION(global_block) = 0;
+ BLOCK_START(global_block) = BLOCK_START(block);
+ BLOCK_END(global_block) = BLOCK_END(block);
+ BLOCK_SUPERBLOCK(global_block) = 0;
+ BLOCK_SUPERBLOCK(block) = global_block;
+ record_pending_block (objfile, global_block, NULL);
+
+ complete_symtab(source_file,
+ BLOCK_START(block),
+ BLOCK_END(block) - BLOCK_START(block));
+ module_num++;
+ dst_end_symtab(objfile);
+ }
+ }
+ if (module_num)
+ prim_record_minimal_symbol("<end_of_program>",
+ BLOCK_END(block), mst_text, objfile);
+ /* One more faked symbol to make sure nothing can ever run off the
+ * end of the symbol table. This one represents the end of the
+ * text space. It used to be (CORE_ADDR) -1 (effectively the highest
+ * int possible), but some parts of gdb treated it as a signed
+ * number and failed comparisons. We could equally use 7fffffff,
+ * but no functions are ever mapped to an address higher than
+ * 40000000
+ */
+ prim_record_minimal_symbol("<end_of_text>",
+ (CORE_ADDR) 0x40000000,
+ mst_text, objfile);
+ while (struct_list)
+ {
+ element = struct_list;
+ struct_list = element->next;
+ free((PTR) element);
+ }
+}
+
+
+/* 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_one_section(chan, secinfo)
+ int chan;
+ dst_sec *secinfo;
+{
+ if (secinfo->size == 0
+ || lseek(chan, secinfo->position, 0) == -1
+ || (secinfo->buffer = xmalloc(secinfo->size)) == NULL
+ || myread(chan, secinfo->buffer, secinfo->size) == -1)
+ return 0;
+ else
+ return 1;
+}
+
+static int
+init_dst_sections (chan)
+ int chan;
+{
+
+ if (!init_one_section(chan, &blocks_info) ||
+ !init_one_section(chan, &lines_info) ||
+ !init_one_section(chan, &symbols_info))
+ return -1;
+ else
+ return 0;
+}
+
+/* Fake up support for relocating symbol addresses. FIXME. */
+
+struct section_offsets dst_symfile_faker = {0};
+
+struct section_offsets *
+dst_symfile_offsets (objfile, addr)
+ struct objfile *objfile;
+ CORE_ADDR addr;
+{
+ objfile->num_sections = 1;
+ return &dst_symfile_faker;
+}
+
+/* Register our ability to parse symbols for DST BFD files */
+
+static struct sym_fns dst_sym_fns =
+{
+ /* FIXME: Can this be integrated with coffread.c? If not, should it be
+ a separate flavour like ecoff? */
+ (enum bfd_flavour)-2,
+
+ dst_new_init, /* sym_new_init: init anything gbl to entire symtab */
+ dst_symfile_init, /* sym_init: read initial info, setup for sym_read() */
+ dst_symfile_read, /* sym_read: read a symbol file into symtab */
+ dst_symfile_finish, /* sym_finish: finished with file, cleanup */
+ dst_symfile_offsets, /* sym_offsets: xlate external to internal form */
+ NULL /* next: pointer to next struct sym_fns */
+};
+
+void
+_initialize_dstread ()
+{
+ add_symtab_fns(&dst_sym_fns);
+}
diff --git a/gdb/dve3900-rom.c b/gdb/dve3900-rom.c
new file mode 100644
index 00000000000..c76da776d60
--- /dev/null
+++ b/gdb/dve3900-rom.c
@@ -0,0 +1,962 @@
+/* Remote debugging interface for Densan DVE-R3900 ROM monitor for
+ GDB, the GNU debugger.
+ Copyright 1997 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "gdbcore.h"
+#include "target.h"
+#include "monitor.h"
+#include "serial.h"
+#include "inferior.h"
+#include "command.h"
+#include "gdb_string.h"
+#include <time.h>
+
+/* Type of function passed to bfd_map_over_sections. */
+
+typedef void (*section_map_func) PARAMS ((bfd *abfd, asection *sect, PTR obj));
+
+/* Packet escape character used by Densan monitor. */
+
+#define PESC 0xdc
+
+/* Maximum packet size. This is actually smaller than necessary
+ just to be safe. */
+
+#define MAXPSIZE 1024
+
+/* External functions. */
+
+extern void report_transfer_performance PARAMS ((unsigned long,
+ time_t, time_t));
+
+/* Certain registers are "bitmapped", in that the monitor can only display
+ them or let the user modify them as a series of named bitfields.
+ This structure describes a field in a bitmapped register. */
+
+struct bit_field
+{
+ char *prefix; /* string appearing before the value */
+ char *suffix; /* string appearing after the value */
+ char *user_name; /* name used by human when entering field value */
+ int length; /* number of bits in the field */
+ int start; /* starting (least significant) bit number of field */
+};
+
+/* Local functions for register manipulation. */
+
+static void r3900_supply_register PARAMS ((char *regname, int regnamelen,
+ char *val, int vallen));
+static void fetch_bad_vaddr PARAMS ((void));
+static unsigned long fetch_fields PARAMS ((struct bit_field *bf));
+static void fetch_bitmapped_register PARAMS ((int regno,
+ struct bit_field *bf));
+static void r3900_fetch_registers PARAMS ((int regno));
+static void store_bitmapped_register PARAMS ((int regno,
+ struct bit_field *bf));
+static void r3900_store_registers PARAMS ((int regno));
+
+/* Local functions for fast binary loading. */
+
+static void write_long PARAMS ((char *buf, long n));
+static void write_long_le PARAMS ((char *buf, long n));
+static int debug_readchar PARAMS ((int hex));
+static void debug_write PARAMS ((unsigned char *buf, int buflen));
+static void ignore_packet PARAMS ((void));
+static void send_packet PARAMS ((char type, unsigned char *buf, int buflen,
+ int seq));
+static void process_read_request PARAMS ((unsigned char *buf, int buflen));
+static void count_section PARAMS ((bfd *abfd, asection *s,
+ unsigned int *section_count));
+static void load_section PARAMS ((bfd *abfd, asection *s,
+ unsigned int *data_count));
+static void r3900_load PARAMS ((char *filename, int from_tty));
+
+/* Miscellaneous local functions. */
+
+static void r3900_open PARAMS ((char *args, int from_tty));
+
+
+/* Pointers to static functions in monitor.c for fetching and storing
+ registers. We can't use these function in certain cases where the Densan
+ monitor acts perversely: for registers that it displays in bit-map
+ format, and those that can't be modified at all. In those cases
+ we have to use our own functions to fetch and store their values. */
+
+static void (*orig_monitor_fetch_registers) PARAMS ((int regno));
+static void (*orig_monitor_store_registers) PARAMS ((int regno));
+
+/* Pointer to static function in monitor. for loading programs.
+ We use this function for loading S-records via the serial link. */
+
+static void (*orig_monitor_load) PARAMS ((char *file, int from_tty));
+
+/* This flag is set if a fast ethernet download should be used. */
+
+static int ethernet = 0;
+
+/* This array of registers needs to match the indexes used by GDB. The
+ whole reason this exists is because the various ROM monitors use
+ different names than GDB does, and don't support all the registers
+ either. */
+
+static char *r3900_regnames[NUM_REGS] =
+{
+ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
+ "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
+ "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
+ "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
+
+ "S", /* PS_REGNUM */
+ "l", /* LO_REGNUM */
+ "h", /* HI_REGNUM */
+ "B", /* BADVADDR_REGNUM */
+ "Pcause", /* CAUSE_REGNUM */
+ "p" /* PC_REGNUM */
+};
+
+
+/* Table of register names produced by monitor's register dump command. */
+
+static struct reg_entry
+{
+ char *name;
+ int regno;
+} reg_table[] =
+{
+ { "r0_zero", 0 }, { "r1_at", 1 }, { "r2_v0", 2 }, { "r3_v1", 3 },
+ { "r4_a0", 4 }, { "r5_a1", 5 }, { "r6_a2", 6 }, { "r7_a3", 7 },
+ { "r8_t0", 8 }, { "r9_t1", 9 }, { "r10_t2", 10 }, { "r11_t3", 11 },
+ { "r12_t4", 12 }, { "r13_t5", 13 }, { "r14_t6", 14 }, { "r15_t7", 15 },
+ { "r16_s0", 16 }, { "r17_s1", 17 }, { "r18_s2", 18 }, { "r19_s3", 19 },
+ { "r20_s4", 20 }, { "r21_s5", 21 }, { "r22_s6", 22 }, { "r23_s7", 23 },
+ { "r24_t8", 24 }, { "r25_t9", 25 }, { "r26_k0", 26 }, { "r27_k1", 27 },
+ { "r28_gp", 28 }, { "r29_sp", 29 }, { "r30_fp", 30 }, { "r31_ra", 31 },
+ { "HI", HI_REGNUM },
+ { "LO", LO_REGNUM },
+ { "PC", PC_REGNUM },
+ { "BadV", BADVADDR_REGNUM },
+ { NULL, 0 }
+};
+
+
+/* The monitor displays the cache register along with the status register,
+ as if they were a single register. So when we want to fetch the
+ status register, parse but otherwise ignore the fields of the
+ cache register that the monitor displays. Register fields that should
+ be ignored have a length of zero in the tables below. */
+
+static struct bit_field status_fields [] =
+{
+ /* Status register portion */
+ { "SR[<CU=", " ", "cu", 4, 28 },
+ { "RE=", " ", "re", 1, 25 },
+ { "BEV=", " ", "bev", 1, 22 },
+ { "TS=", " ", "ts", 1, 21 },
+ { "Nmi=", " ", "nmi", 1, 20 },
+ { "INT=", " ", "int", 6, 10 },
+ { "SW=", ">]", "sw", 2, 8 },
+ { "[<KUO=", " ", "kuo", 1, 5 },
+ { "IEO=", " ", "ieo", 1, 4 },
+ { "KUP=", " ", "kup", 1, 3 },
+ { "IEP=", " ", "iep", 1, 2 },
+ { "KUC=", " ", "kuc", 1, 1 },
+ { "IEC=", ">]", "iec", 1, 0 },
+
+ /* Cache register portion (dummy for parsing only) */
+ { "CR[<IalO="," ", "ialo", 0, 13 },
+ { "DalO=", " ", "dalo", 0, 12 },
+ { "IalP=", " ", "ialp", 0, 11 },
+ { "DalP=", " ", "dalp", 0, 10 },
+ { "IalC=", " ", "ialc", 0, 9 },
+ { "DalC=", ">] ", "dalc", 0, 8 },
+
+ { NULL, NULL, 0, 0 } /* end of table marker */
+};
+
+
+#if 0 /* FIXME: Enable when we add support for modifying cache register. */
+static struct bit_field cache_fields [] =
+{
+ /* Status register portion (dummy for parsing only) */
+ { "SR[<CU=", " ", "cu", 0, 28 },
+ { "RE=", " ", "re", 0, 25 },
+ { "BEV=", " ", "bev", 0, 22 },
+ { "TS=", " ", "ts", 0, 21 },
+ { "Nmi=", " ", "nmi", 0, 20 },
+ { "INT=", " ", "int", 0, 10 },
+ { "SW=", ">]", "sw", 0, 8 },
+ { "[<KUO=", " ", "kuo", 0, 5 },
+ { "IEO=", " ", "ieo", 0, 4 },
+ { "KUP=", " ", "kup", 0, 3 },
+ { "IEP=", " ", "iep", 0, 2 },
+ { "KUC=", " ", "kuc", 0, 1 },
+ { "IEC=", ">]", "iec", 0, 0 },
+
+ /* Cache register portion */
+ { "CR[<IalO="," ", "ialo", 1, 13 },
+ { "DalO=", " ", "dalo", 1, 12 },
+ { "IalP=", " ", "ialp", 1, 11 },
+ { "DalP=", " ", "dalp", 1, 10 },
+ { "IalC=", " ", "ialc", 1, 9 },
+ { "DalC=", ">] ", "dalc", 1, 8 },
+
+ { NULL, NULL, NULL, 0, 0 } /* end of table marker */
+};
+#endif
+
+
+static struct bit_field cause_fields[] =
+{
+ { "<BD=", " ", "bd", 1, 31 },
+ { "CE=", " ", "ce", 2, 28 },
+ { "IP=", " ", "ip", 6, 10 },
+ { "SW=", " ", "sw", 2, 8 },
+ { "EC=", ">]" , "ec", 5, 2 },
+
+ { NULL, NULL, NULL, 0, 0 } /* end of table marker */
+};
+
+
+/* The monitor prints register values in the form
+
+ regname = xxxx xxxx
+
+ We look up the register name in a table, and remove the embedded space in
+ the hex value before passing it to monitor_supply_register. */
+
+static void
+r3900_supply_register (regname, regnamelen, val, vallen)
+ char *regname;
+ int regnamelen;
+ char *val;
+ int vallen;
+{
+ int regno = -1;
+ int i;
+ char valbuf[10];
+ char *p;
+
+ /* Perform some sanity checks on the register name and value. */
+ if (regnamelen < 2 || regnamelen > 7 || vallen != 9)
+ return;
+
+ /* Look up the register name. */
+ for (i = 0; reg_table[i].name != NULL; i++)
+ {
+ int rlen = strlen (reg_table[i].name);
+ if (rlen == regnamelen && strncmp (regname, reg_table[i].name, rlen) == 0)
+ {
+ regno = reg_table[i].regno;
+ break;
+ }
+ }
+ if (regno == -1)
+ return;
+
+ /* Copy the hex value to a buffer and eliminate the embedded space. */
+ for (i = 0, p = valbuf; i < vallen; i++)
+ if (val[i] != ' ')
+ *p++ = val[i];
+ *p = '\0';
+
+ monitor_supply_register (regno, valbuf);
+}
+
+
+/* Fetch the BadVaddr register. Unlike the other registers, this
+ one can't be modified, and the monitor won't even prompt to let
+ you modify it. */
+
+static void
+fetch_bad_vaddr()
+{
+ char buf[20];
+
+ monitor_printf ("xB\r");
+ monitor_expect ("BadV=", NULL, 0);
+ monitor_expect_prompt (buf, sizeof(buf));
+ monitor_supply_register (BADVADDR_REGNUM, buf);
+}
+
+
+/* Read a series of bit fields from the monitor, and return their
+ combined binary value. */
+
+static unsigned long
+fetch_fields (bf)
+ struct bit_field *bf;
+{
+ char buf[20];
+ unsigned long val = 0;
+ unsigned long bits;
+
+ for ( ; bf->prefix != NULL; bf++)
+ {
+ monitor_expect (bf->prefix, NULL, 0); /* get prefix */
+ monitor_expect (bf->suffix, buf, sizeof (buf)); /* hex value, suffix */
+ if (bf->length != 0)
+ {
+ bits = strtoul (buf, NULL, 16); /* get field value */
+ bits &= ((1 << bf->length) - 1); /* mask out useless bits */
+ val |= bits << bf->start; /* insert into register */
+ }
+
+ }
+
+ return val;
+}
+
+
+static void
+fetch_bitmapped_register (regno, bf)
+ int regno;
+ struct bit_field *bf;
+{
+ unsigned long val;
+ unsigned char regbuf[MAX_REGISTER_RAW_SIZE];
+
+ monitor_printf ("x%s\r", r3900_regnames[regno]);
+ val = fetch_fields (bf);
+ monitor_printf (".\r");
+ monitor_expect_prompt (NULL, 0);
+
+ /* supply register stores in target byte order, so swap here */
+
+ store_unsigned_integer (regbuf, REGISTER_RAW_SIZE (regno), val);
+ supply_register (regno, regbuf);
+
+}
+
+
+/* Fetch all registers (if regno is -1), or one register from the
+ monitor. For most registers, we can use the generic monitor_
+ monitor_fetch_registers function. But others are displayed in
+ a very unusual fashion by the monitor, and must be handled specially. */
+
+static void
+r3900_fetch_registers (regno)
+ int regno;
+{
+ switch (regno)
+ {
+ case BADVADDR_REGNUM:
+ fetch_bad_vaddr ();
+ return;
+ case PS_REGNUM:
+ fetch_bitmapped_register (PS_REGNUM, status_fields);
+ return;
+ case CAUSE_REGNUM:
+ fetch_bitmapped_register (CAUSE_REGNUM, cause_fields);
+ return;
+ default:
+ orig_monitor_fetch_registers (regno);
+ }
+}
+
+
+/* Write the new value of the bitmapped register to the monitor. */
+
+static void
+store_bitmapped_register (regno, bf)
+ int regno;
+ struct bit_field *bf;
+{
+ unsigned long oldval, newval;
+
+ /* Fetch the current value of the register. */
+ monitor_printf ("x%s\r", r3900_regnames[regno]);
+ oldval = fetch_fields (bf);
+ newval = read_register (regno);
+
+ /* To save time, write just the fields that have changed. */
+ for ( ; bf->prefix != NULL; bf++)
+ {
+ if (bf->length != 0)
+ {
+ unsigned long oldbits, newbits, mask;
+
+ mask = (1 << bf->length) - 1;
+ oldbits = (oldval >> bf->start) & mask;
+ newbits = (newval >> bf->start) & mask;
+ if (oldbits != newbits)
+ monitor_printf ("%s %x ", bf->user_name, newbits);
+ }
+ }
+
+ monitor_printf (".\r");
+ monitor_expect_prompt (NULL, 0);
+}
+
+
+static void
+r3900_store_registers (regno)
+ int regno;
+{
+ switch (regno)
+ {
+ case PS_REGNUM:
+ store_bitmapped_register (PS_REGNUM, status_fields);
+ return;
+ case CAUSE_REGNUM:
+ store_bitmapped_register (CAUSE_REGNUM, cause_fields);
+ return;
+ default:
+ orig_monitor_store_registers (regno);
+ }
+}
+
+
+/* Write a 4-byte integer to the buffer in big-endian order. */
+
+static void
+write_long (buf, n)
+ char *buf;
+ long n;
+{
+ buf[0] = (n >> 24) & 0xff;
+ buf[1] = (n >> 16) & 0xff;
+ buf[2] = (n >> 8) & 0xff;
+ buf[3] = n & 0xff;
+}
+
+
+/* Write a 4-byte integer to the buffer in little-endian order. */
+
+static void
+write_long_le (buf, n)
+ char *buf;
+ long n;
+{
+ buf[0] = n & 0xff;
+ buf[1] = (n >> 8) & 0xff;
+ buf[2] = (n >> 16) & 0xff;
+ buf[3] = (n >> 24) & 0xff;
+}
+
+
+/* Read a character from the monitor. If remote debugging is on,
+ print the received character. If HEX is non-zero, print the
+ character in hexadecimal; otherwise, print it in ASCII. */
+
+static int
+debug_readchar (hex)
+ int hex;
+{
+ char buf [10];
+ int c = monitor_readchar ();
+
+ if (remote_debug > 0)
+ {
+ if (hex)
+ sprintf (buf, "[%02x]", c & 0xff);
+ else if (c == '\0')
+ strcpy (buf, "\\0");
+ else
+ {
+ buf[0] = c;
+ buf[1] = '\0';
+ }
+ puts_debug ("Read -->", buf, "<--");
+ }
+ return c;
+}
+
+
+/* Send a buffer of characters to the monitor. If remote debugging is on,
+ print the sent buffer in hex. */
+
+static void
+debug_write (buf, buflen)
+ unsigned char *buf;
+ int buflen;
+{
+ char s[10];
+
+ monitor_write (buf, buflen);
+
+ if (remote_debug > 0)
+ {
+ while (buflen-- > 0)
+ {
+ sprintf (s, "[%02x]", *buf & 0xff);
+ puts_debug ("Sent -->", s, "<--");
+ buf++;
+ }
+ }
+}
+
+
+/* Ignore a packet sent to us by the monitor. It send packets
+ when its console is in "communications interface" mode. A packet
+ is of this form:
+
+ start of packet flag (one byte: 0xdc)
+ packet type (one byte)
+ length (low byte)
+ length (high byte)
+ data (length bytes)
+
+ The last two bytes of the data field are a checksum, but we don't
+ bother to verify it.
+*/
+
+static void
+ignore_packet ()
+{
+ int c;
+ int len;
+
+ /* Ignore lots of trash (messages about section addresses, for example)
+ until we see the start of a packet. */
+ for (len = 0; len < 256; len++)
+ {
+ c = debug_readchar (0);
+ if (c == PESC)
+ break;
+ }
+ if (len == 8)
+ error ("Packet header byte not found; %02x seen instead.", c);
+
+ /* Read the packet type and length. */
+ c = debug_readchar (1); /* type */
+
+ c = debug_readchar (1); /* low byte of length */
+ len = c & 0xff;
+
+ c = debug_readchar (1); /* high byte of length */
+ len += (c & 0xff) << 8;
+
+ /* Ignore the rest of the packet. */
+ while (len-- > 0)
+ c = debug_readchar (1);
+}
+
+
+/* Encapsulate some data into a packet and send it to the monitor.
+
+ The 'p' packet is a special case. This is a packet we send
+ in response to a read ('r') packet from the monitor. This function
+ appends a one-byte sequence number to the data field of such a packet.
+*/
+
+static void
+send_packet (type, buf, buflen, seq)
+ char type;
+ unsigned char *buf;
+ int buflen, seq;
+{
+ unsigned char hdr[4];
+ int len = buflen;
+ int sum, i;
+
+ /* If this is a 'p' packet, add one byte for a sequence number. */
+ if (type == 'p')
+ len++;
+
+ /* If the buffer has a non-zero length, add two bytes for a checksum. */
+ if (len > 0)
+ len += 2;
+
+ /* Write the packet header. */
+ hdr[0] = PESC;
+ hdr[1] = type;
+ hdr[2] = len & 0xff;
+ hdr[3] = (len >> 8) & 0xff;
+ debug_write (hdr, sizeof (hdr));
+
+ if (len)
+ {
+ /* Write the packet data. */
+ debug_write (buf, buflen);
+
+ /* Write the sequence number if this is a 'p' packet. */
+ if (type == 'p')
+ {
+ hdr[0] = seq;
+ debug_write (hdr, 1);
+ }
+
+ /* Write the checksum. */
+ sum = 0;
+ for (i = 0; i < buflen; i++)
+ {
+ int tmp = (buf[i] & 0xff);
+ if (i & 1)
+ sum += tmp;
+ else
+ sum += tmp << 8;
+ }
+ if (type == 'p')
+ {
+ if (buflen & 1)
+ sum += (seq & 0xff);
+ else
+ sum += (seq & 0xff) << 8;
+ }
+ sum = (sum & 0xffff) + ((sum >> 16) & 0xffff);
+ sum += (sum >> 16) & 1;
+ sum = ~sum;
+
+ hdr[0] = (sum >> 8) & 0xff;
+ hdr[1] = sum & 0xff;
+ debug_write (hdr, 2);
+ }
+}
+
+
+/* Respond to an expected read request from the monitor by sending
+ data in chunks. Handle all acknowledgements and handshaking packets.
+
+ The monitor expects a response consisting of a one or more 'p' packets,
+ each followed by a portion of the data requested. The 'p' packet
+ contains only a four-byte integer, the value of which is the number
+ of bytes of data we are about to send. Following the 'p' packet,
+ the monitor expects the data bytes themselves in raw, unpacketized,
+ form, without even a checksum.
+ */
+
+static void
+process_read_request (buf, buflen)
+ unsigned char *buf;
+ int buflen;
+{
+ unsigned char len[4];
+ int i, chunk;
+ unsigned char seq;
+
+ /* Discard the read request. FIXME: we have to hope it's for
+ the exact number of bytes we want to send; should check for this. */
+ ignore_packet ();
+
+ for (i = chunk = 0, seq = 0; i < buflen; i += chunk, seq++)
+ {
+ /* Don't send more than MAXPSIZE bytes at a time. */
+ chunk = buflen - i;
+ if (chunk > MAXPSIZE)
+ chunk = MAXPSIZE;
+
+ /* Write a packet containing the number of bytes we are sending. */
+ write_long_le (len, chunk);
+ send_packet ('p', len, sizeof (len), seq);
+
+ /* Write the data in raw form following the packet. */
+ debug_write (&buf[i], chunk);
+
+ /* Discard the ACK packet. */
+ ignore_packet ();
+ }
+
+ /* Send an "end of data" packet. */
+ send_packet ('e', "", 0, 0);
+}
+
+
+/* Count loadable sections (helper function for r3900_load). */
+
+static void
+count_section (abfd, s, section_count)
+ bfd *abfd;
+ asection *s;
+ unsigned int *section_count;
+{
+ if (s->flags & SEC_LOAD && bfd_section_size (abfd, s) != 0)
+ (*section_count)++;
+}
+
+
+/* Load a single BFD section (helper function for r3900_load).
+
+ WARNING: this code is filled with assumptions about how
+ the Densan monitor loads programs. The monitor issues
+ packets containing read requests, but rather than respond
+ to them in an general way, we expect them to following
+ a certain pattern.
+
+ For example, we know that the monitor will start loading by
+ issuing an 8-byte read request for the binary file header.
+ We know this is coming and ignore the actual contents
+ of the read request packet.
+*/
+
+static void
+load_section (abfd, s, data_count)
+ bfd *abfd;
+ asection *s;
+ unsigned int *data_count;
+{
+ if (s->flags & SEC_LOAD)
+ {
+ bfd_size_type section_size = bfd_section_size (abfd, s);
+ bfd_vma section_base = bfd_section_lma (abfd, s);
+ unsigned char *buffer;
+ unsigned char header[8];
+
+ /* Don't output zero-length sections. */
+ if (section_size == 0)
+ return;
+ if (data_count)
+ *data_count += section_size;
+
+ /* Print some fluff about the section being loaded. */
+ printf_filtered ("Loading section %s, size 0x%lx lma ",
+ bfd_section_name (abfd, s), (long)section_size);
+ print_address_numeric (section_base, 1, gdb_stdout);
+ printf_filtered ("\n");
+ gdb_flush (gdb_stdout);
+
+ /* Write the section header (location and size). */
+ write_long (&header[0], (long)section_base);
+ write_long (&header[4], (long)section_size);
+ process_read_request (header, sizeof (header));
+
+ /* Read the section contents into a buffer, write it out,
+ then free the buffer. */
+ buffer = (unsigned char *) xmalloc (section_size);
+ bfd_get_section_contents (abfd, s, buffer, 0, section_size);
+ process_read_request (buffer, section_size);
+ free (buffer);
+ }
+}
+
+
+/* When the ethernet is used as the console port on the Densan board,
+ we can use the "Rm" command to do a fast binary load. The format
+ of the download data is:
+
+ number of sections (4 bytes)
+ starting address (4 bytes)
+ repeat for each section:
+ location address (4 bytes)
+ section size (4 bytes)
+ binary data
+
+ The 4-byte fields are all in big-endian order.
+
+ Using this command is tricky because we have to put the monitor
+ into a special funky "communications interface" mode, in which
+ it sends and receives packets of data along with the normal prompt.
+ */
+
+static void
+r3900_load (filename, from_tty)
+ char *filename;
+ int from_tty;
+{
+ bfd *abfd;
+ unsigned int data_count = 0;
+ time_t start_time, end_time; /* for timing of download */
+ int section_count = 0;
+ unsigned char buffer[8];
+
+ /* If we are not using the ethernet, use the normal monitor load,
+ which sends S-records over the serial link. */
+ if (!ethernet)
+ {
+ orig_monitor_load (filename, from_tty);
+ return;
+ }
+
+ /* Open the file. */
+ if (filename == NULL || filename[0] == 0)
+ filename = get_exec_file (1);
+ abfd = bfd_openr (filename, 0);
+ if (!abfd)
+ error ("Unable to open file %s\n", filename);
+ if (bfd_check_format (abfd, bfd_object) == 0)
+ error ("File is not an object file\n");
+
+ /* Output the "vconsi" command to get the monitor in the communication
+ state where it will accept a load command. This will cause
+ the monitor to emit a packet before each prompt, so ignore the packet. */
+ monitor_printf ("vconsi\r");
+ ignore_packet ();
+ monitor_expect_prompt (NULL, 0);
+
+ /* Output the "Rm" (load) command and respond to the subsequent "open"
+ packet by sending an ACK packet. */
+ monitor_printf ("Rm\r");
+ ignore_packet ();
+ send_packet ('a', "", 0, 0);
+
+ /* Output the fast load header (number of sections and starting address). */
+ bfd_map_over_sections ((bfd *) abfd, (section_map_func) count_section,
+ &section_count);
+ write_long (&buffer[0], (long)section_count);
+ if (exec_bfd)
+ write_long (&buffer[4], (long)bfd_get_start_address (exec_bfd));
+ else
+ write_long (&buffer[4], 0);
+ process_read_request (buffer, sizeof (buffer));
+
+ /* Output the section data. */
+ start_time = time (NULL);
+ bfd_map_over_sections (abfd, (section_map_func) load_section, &data_count);
+ end_time = time (NULL);
+
+ /* Acknowledge the close packet and put the monitor back into
+ "normal" mode so it won't send packets any more. */
+ ignore_packet ();
+ send_packet ('a', "", 0, 0);
+ monitor_expect_prompt (NULL, 0);
+ monitor_printf ("vconsx\r");
+ monitor_expect_prompt (NULL, 0);
+
+ /* Print start address and download performance information. */
+ printf_filtered ("Start address 0x%lx\n", (long)bfd_get_start_address (abfd));
+ report_transfer_performance (data_count, start_time, end_time);
+
+ /* Finally, make the PC point at the start address */
+ if (exec_bfd)
+ write_pc (bfd_get_start_address (exec_bfd));
+
+ inferior_pid = 0; /* No process now */
+
+ /* This is necessary because many things were based on the PC at the
+ time that we attached to the monitor, which is no longer valid
+ now that we have loaded new code (and just changed the PC).
+ Another way to do this might be to call normal_stop, except that
+ the stack may not be valid, and things would get horribly
+ confused... */
+ clear_symtab_users ();
+}
+
+
+/* Commands to send to the monitor when first connecting:
+ * The bare carriage return forces a prompt from the monitor
+ (monitor doesn't prompt immediately after a reset).
+ * The "vconsx" switches the monitor back to interactive mode
+ in case an aborted download had left it in packet mode.
+ * The "Xtr" command causes subsequent "t" (trace) commands to display
+ the general registers only.
+ * The "Xxr" command does the same thing for the "x" (examine
+ registers) command.
+ * The "bx" command clears all breakpoints.
+*/
+
+static char *r3900_inits[] = {"\r", "vconsx\r", "Xtr\r", "Xxr\r", "bx\r", NULL};
+static char *dummy_inits[] = { NULL };
+
+static struct target_ops r3900_ops;
+static struct monitor_ops r3900_cmds;
+
+static void
+r3900_open (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ char buf[64];
+ int i;
+
+ monitor_open (args, &r3900_cmds, from_tty);
+
+ /* We have to handle sending the init strings ourselves, because
+ the first two strings we send (carriage returns) may not be echoed
+ by the monitor, but the rest will be. */
+ monitor_printf_noecho ("\r\r");
+ for (i = 0; r3900_inits[i] != NULL; i++)
+ {
+ monitor_printf (r3900_inits[i]);
+ monitor_expect_prompt (NULL, 0);
+ }
+
+ /* Attempt to determine whether the console device is ethernet or serial.
+ This will tell us which kind of load to use (S-records over a serial
+ link, or the Densan fast binary multi-section format over the net). */
+
+ ethernet = 0;
+ monitor_printf ("v\r");
+ if (monitor_expect ("console device :", NULL, 0) != -1)
+ if (monitor_expect ("\n", buf, sizeof (buf)) != -1)
+ if (strstr (buf, "ethernet") != NULL)
+ ethernet = 1;
+ monitor_expect_prompt (NULL, 0);
+}
+
+void
+_initialize_r3900_rom ()
+{
+ r3900_cmds.flags = MO_NO_ECHO_ON_OPEN |
+ MO_ADDR_BITS_REMOVE |
+ MO_CLR_BREAK_USES_ADDR |
+ MO_GETMEM_READ_SINGLE |
+ MO_PRINT_PROGRAM_OUTPUT;
+
+ r3900_cmds.init = dummy_inits;
+ r3900_cmds.cont = "g\r";
+ r3900_cmds.step = "t\r";
+ r3900_cmds.set_break = "b %A\r"; /* COREADDR */
+ r3900_cmds.clr_break = "b %A,0\r"; /* COREADDR */
+ r3900_cmds.fill = "fx %A s %x %x\r"; /* COREADDR, len, val */
+
+ r3900_cmds.setmem.cmdb = "sx %A %x\r"; /* COREADDR, val */
+ r3900_cmds.setmem.cmdw = "sh %A %x\r"; /* COREADDR, val */
+ r3900_cmds.setmem.cmdl = "sw %A %x\r"; /* COREADDR, val */
+
+ r3900_cmds.getmem.cmdb = "sx %A\r"; /* COREADDR */
+ r3900_cmds.getmem.cmdw = "sh %A\r"; /* COREADDR */
+ r3900_cmds.getmem.cmdl = "sw %A\r"; /* COREADDR */
+ r3900_cmds.getmem.resp_delim = " : ";
+ r3900_cmds.getmem.term = " ";
+ r3900_cmds.getmem.term_cmd = ".\r";
+
+ r3900_cmds.setreg.cmd = "x%s %x\r"; /* regname, val */
+
+ r3900_cmds.getreg.cmd = "x%s\r"; /* regname */
+ r3900_cmds.getreg.resp_delim = "=";
+ r3900_cmds.getreg.term = " ";
+ r3900_cmds.getreg.term_cmd = ".\r";
+
+ r3900_cmds.dump_registers = "x\r";
+ r3900_cmds.register_pattern =
+ "\\([a-zA-Z0-9_]+\\) *=\\([0-9a-f]+ [0-9a-f]+\\b\\)";
+ r3900_cmds.supply_register = r3900_supply_register;
+ /* S-record download, via "keyboard port". */
+ r3900_cmds.load = "r0\r";
+ r3900_cmds.prompt = "#";
+ r3900_cmds.line_term = "\r";
+ r3900_cmds.target = &r3900_ops;
+ r3900_cmds.stopbits = SERIAL_1_STOPBITS;
+ r3900_cmds.regnames = r3900_regnames;
+ r3900_cmds.magic = MONITOR_OPS_MAGIC;
+
+ init_monitor_ops (&r3900_ops);
+
+ r3900_ops.to_shortname = "r3900";
+ r3900_ops.to_longname = "R3900 monitor";
+ r3900_ops.to_doc = "Debug using the DVE R3900 monitor.\n\
+Specify the serial device it is connected to (e.g. /dev/ttya).";
+ r3900_ops.to_open = r3900_open;
+
+ /* Override the functions to fetch and store registers. But save the
+ addresses of the default functions, because we will use those functions
+ for "normal" registers. */
+
+ orig_monitor_fetch_registers = r3900_ops.to_fetch_registers;
+ orig_monitor_store_registers = r3900_ops.to_store_registers;
+ r3900_ops.to_fetch_registers = r3900_fetch_registers;
+ r3900_ops.to_store_registers = r3900_store_registers;
+
+ /* Override the load function, but save the address of the default
+ function to use when loading S-records over a serial link. */
+ orig_monitor_load = r3900_ops.to_load;
+ r3900_ops.to_load = r3900_load;
+
+ add_target (&r3900_ops);
+}
diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
new file mode 100644
index 00000000000..cf5206631ec
--- /dev/null
+++ b/gdb/dwarf2read.c
@@ -0,0 +1,5865 @@
+/* DWARF 2 debugging format support for GDB.
+ Copyright 1994, 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
+
+ Adapted by Gary Funck (gary@intrepid.com), Intrepid Technology,
+ Inc. with support from Florida State University (under contract
+ with the Ada Joint Program Office), and Silicon Graphics, Inc.
+ Initial contribution by Brent Benson, Harris Computer Systems, Inc.,
+ based on Fred Fish's (Cygnus Support) implementation of DWARF 1
+ support in dwarfread.c
+
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "bfd.h"
+#include "elf-bfd.h"
+#include "symtab.h"
+#include "gdbtypes.h"
+#include "symfile.h"
+#include "objfiles.h"
+#include "elf/dwarf2.h"
+#include "buildsym.h"
+#include "demangle.h"
+#include "expression.h"
+#include "language.h"
+#include "complaints.h"
+
+#include <fcntl.h>
+#include "gdb_string.h"
+#include <sys/types.h>
+
+/* .debug_info header for a compilation unit
+ Because of alignment constraints, this structure has padding and cannot
+ be mapped directly onto the beginning of the .debug_info section. */
+typedef struct comp_unit_header
+ {
+ unsigned int length; /* length of the .debug_info
+ contribution */
+ unsigned short version; /* version number -- 2 for DWARF
+ version 2 */
+ unsigned int abbrev_offset; /* offset into .debug_abbrev section */
+ unsigned char addr_size; /* byte size of an address -- 4 */
+ }
+_COMP_UNIT_HEADER;
+#define _ACTUAL_COMP_UNIT_HEADER_SIZE 11
+
+/* .debug_pubnames header
+ Because of alignment constraints, this structure has padding and cannot
+ be mapped directly onto the beginning of the .debug_info section. */
+typedef struct pubnames_header
+ {
+ unsigned int length; /* length of the .debug_pubnames
+ contribution */
+ unsigned char version; /* version number -- 2 for DWARF
+ version 2 */
+ unsigned int info_offset; /* offset into .debug_info section */
+ unsigned int info_size; /* byte size of .debug_info section
+ portion */
+ }
+_PUBNAMES_HEADER;
+#define _ACTUAL_PUBNAMES_HEADER_SIZE 13
+
+/* .debug_pubnames header
+ Because of alignment constraints, this structure has padding and cannot
+ be mapped directly onto the beginning of the .debug_info section. */
+typedef struct aranges_header
+ {
+ unsigned int length; /* byte len of the .debug_aranges
+ contribution */
+ unsigned short version; /* version number -- 2 for DWARF
+ version 2 */
+ unsigned int info_offset; /* offset into .debug_info section */
+ unsigned char addr_size; /* byte size of an address */
+ unsigned char seg_size; /* byte size of segment descriptor */
+ }
+_ARANGES_HEADER;
+#define _ACTUAL_ARANGES_HEADER_SIZE 12
+
+/* .debug_line statement program prologue
+ Because of alignment constraints, this structure has padding and cannot
+ be mapped directly onto the beginning of the .debug_info section. */
+typedef struct statement_prologue
+ {
+ unsigned int total_length; /* byte length of the statement
+ information */
+ unsigned short version; /* version number -- 2 for DWARF
+ version 2 */
+ unsigned int prologue_length; /* # bytes between prologue &
+ stmt program */
+ unsigned char minimum_instruction_length; /* byte size of
+ smallest instr */
+ unsigned char default_is_stmt; /* initial value of is_stmt
+ register */
+ char line_base;
+ unsigned char line_range;
+ unsigned char opcode_base; /* number assigned to first special
+ opcode */
+ unsigned char *standard_opcode_lengths;
+ }
+_STATEMENT_PROLOGUE;
+
+/* offsets and sizes of debugging sections */
+
+static file_ptr dwarf_info_offset;
+static file_ptr dwarf_abbrev_offset;
+static file_ptr dwarf_line_offset;
+static file_ptr dwarf_pubnames_offset;
+static file_ptr dwarf_aranges_offset;
+static file_ptr dwarf_loc_offset;
+static file_ptr dwarf_macinfo_offset;
+static file_ptr dwarf_str_offset;
+
+static unsigned int dwarf_info_size;
+static unsigned int dwarf_abbrev_size;
+static unsigned int dwarf_line_size;
+static unsigned int dwarf_pubnames_size;
+static unsigned int dwarf_aranges_size;
+static unsigned int dwarf_loc_size;
+static unsigned int dwarf_macinfo_size;
+static unsigned int dwarf_str_size;
+
+/* names of the debugging sections */
+
+#define INFO_SECTION ".debug_info"
+#define ABBREV_SECTION ".debug_abbrev"
+#define LINE_SECTION ".debug_line"
+#define PUBNAMES_SECTION ".debug_pubnames"
+#define ARANGES_SECTION ".debug_aranges"
+#define LOC_SECTION ".debug_loc"
+#define MACINFO_SECTION ".debug_macinfo"
+#define STR_SECTION ".debug_str"
+
+/* local data types */
+
+/* The data in a compilation unit header looks like this. */
+struct comp_unit_head
+ {
+ unsigned int length;
+ short version;
+ unsigned int abbrev_offset;
+ unsigned char addr_size;
+ };
+
+/* The data in the .debug_line statement prologue looks like this. */
+struct line_head
+ {
+ unsigned int total_length;
+ unsigned short version;
+ unsigned int prologue_length;
+ unsigned char minimum_instruction_length;
+ unsigned char default_is_stmt;
+ int line_base;
+ unsigned char line_range;
+ unsigned char opcode_base;
+ unsigned char *standard_opcode_lengths;
+ };
+
+/* When we construct a partial symbol table entry we only
+ need this much information. */
+struct partial_die_info
+ {
+ enum dwarf_tag tag;
+ unsigned char has_children;
+ unsigned char is_external;
+ unsigned char is_declaration;
+ unsigned char has_type;
+ unsigned int offset;
+ unsigned int abbrev;
+ char *name;
+ CORE_ADDR lowpc;
+ CORE_ADDR highpc;
+ struct dwarf_block *locdesc;
+ unsigned int language;
+ char *sibling;
+ };
+
+/* This data structure holds the information of an abbrev. */
+struct abbrev_info
+ {
+ unsigned int number; /* number identifying abbrev */
+ enum dwarf_tag tag; /* dwarf tag */
+ int has_children; /* boolean */
+ unsigned int num_attrs; /* number of attributes */
+ struct attr_abbrev *attrs; /* an array of attribute descriptions */
+ struct abbrev_info *next; /* next in chain */
+ };
+
+struct attr_abbrev
+ {
+ enum dwarf_attribute name;
+ enum dwarf_form form;
+ };
+
+/* This data structure holds a complete die structure. */
+struct die_info
+ {
+ enum dwarf_tag tag; /* Tag indicating type of die */
+ unsigned short has_children; /* Does the die have children */
+ unsigned int abbrev; /* Abbrev number */
+ unsigned int offset; /* Offset in .debug_info section */
+ unsigned int num_attrs; /* Number of attributes */
+ struct attribute *attrs; /* An array of attributes */
+ struct die_info *next_ref; /* Next die in ref hash table */
+ struct die_info *next; /* Next die in linked list */
+ struct type *type; /* Cached type information */
+ };
+
+/* Attributes have a name and a value */
+struct attribute
+ {
+ enum dwarf_attribute name;
+ enum dwarf_form form;
+ union
+ {
+ char *str;
+ struct dwarf_block *blk;
+ unsigned int unsnd;
+ int snd;
+ CORE_ADDR addr;
+ }
+ u;
+ };
+
+/* Get at parts of an attribute structure */
+
+#define DW_STRING(attr) ((attr)->u.str)
+#define DW_UNSND(attr) ((attr)->u.unsnd)
+#define DW_BLOCK(attr) ((attr)->u.blk)
+#define DW_SND(attr) ((attr)->u.snd)
+#define DW_ADDR(attr) ((attr)->u.addr)
+
+/* Blocks are a bunch of untyped bytes. */
+struct dwarf_block
+ {
+ unsigned int size;
+ char *data;
+ };
+
+/* We only hold one compilation unit's abbrevs in
+ memory at any one time. */
+#ifndef ABBREV_HASH_SIZE
+#define ABBREV_HASH_SIZE 121
+#endif
+#ifndef ATTR_ALLOC_CHUNK
+#define ATTR_ALLOC_CHUNK 4
+#endif
+
+static struct abbrev_info *dwarf2_abbrevs[ABBREV_HASH_SIZE];
+
+/* A hash table of die offsets for following references. */
+#ifndef REF_HASH_SIZE
+#define REF_HASH_SIZE 1021
+#endif
+
+static struct die_info *die_ref_table[REF_HASH_SIZE];
+
+/* Obstack for allocating temporary storage used during symbol reading. */
+static struct obstack dwarf2_tmp_obstack;
+
+/* Offset to the first byte of the current compilation unit header,
+ for resolving relative reference dies. */
+static unsigned int cu_header_offset;
+
+/* Allocate fields for structs, unions and enums in this size. */
+#ifndef DW_FIELD_ALLOC_CHUNK
+#define DW_FIELD_ALLOC_CHUNK 4
+#endif
+
+/* The language we are debugging. */
+static enum language cu_language;
+static const struct language_defn *cu_language_defn;
+
+/* Actually data from the sections. */
+static char *dwarf_info_buffer;
+static char *dwarf_abbrev_buffer;
+static char *dwarf_line_buffer;
+
+/* A zeroed version of a partial die for initialization purposes. */
+static struct partial_die_info zeroed_partial_die;
+
+/* 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. */
+static struct pending **list_in_scope = &file_symbols;
+
+/* FIXME: The following variables pass additional information from
+ decode_locdesc to the caller. */
+static int optimized_out; /* Kludge to identify optimized out variables */
+static int isreg; /* Kludge to identify register variables */
+static int offreg; /* Kludge to identify basereg references */
+static int basereg; /* Which base register is it relative to? */
+static int islocal; /* Kludge to identify local variables */
+
+/* DW_AT_frame_base values for the current function.
+ frame_base_reg is -1 if DW_AT_frame_base is missing, otherwise it
+ contains the register number for the frame register.
+ frame_base_offset is the offset from the frame register to the
+ virtual stack frame. */
+static int frame_base_reg;
+static CORE_ADDR frame_base_offset;
+
+/* 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 */
+
+/* We put a pointer to this structure in the read_symtab_private field
+ of the psymtab.
+ The complete dwarf information for an objfile is kept in the
+ psymbol_obstack, so that absolute die references can be handled.
+ Most of the information in this structure is related to an entire
+ object file and could be passed via the sym_private field of the objfile.
+ It is however conceivable that dwarf2 might not be the only type
+ of symbols read from an object file. */
+
+struct dwarf2_pinfo
+{
+ /* Pointer to start of dwarf info buffer for the objfile. */
+
+ char *dwarf_info_buffer;
+
+ /* Offset in dwarf_info_buffer for this compilation unit. */
+
+ unsigned long dwarf_info_offset;
+
+ /* Pointer to start of dwarf abbreviation buffer for the objfile. */
+
+ char *dwarf_abbrev_buffer;
+
+ /* Size of dwarf abbreviation section for the objfile. */
+
+ unsigned int dwarf_abbrev_size;
+
+ /* Pointer to start of dwarf line buffer for the objfile. */
+
+ char *dwarf_line_buffer;
+};
+
+#define PST_PRIVATE(p) ((struct dwarf2_pinfo *)(p)->read_symtab_private)
+#define DWARF_INFO_BUFFER(p) (PST_PRIVATE(p)->dwarf_info_buffer)
+#define DWARF_INFO_OFFSET(p) (PST_PRIVATE(p)->dwarf_info_offset)
+#define DWARF_ABBREV_BUFFER(p) (PST_PRIVATE(p)->dwarf_abbrev_buffer)
+#define DWARF_ABBREV_SIZE(p) (PST_PRIVATE(p)->dwarf_abbrev_size)
+#define DWARF_LINE_BUFFER(p) (PST_PRIVATE(p)->dwarf_line_buffer)
+
+/* 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 */
+
+/* FIXME: We might want to set this from BFD via bfd_arch_bits_per_byte,
+ but this would require a corresponding change in unpack_field_as_long
+ and friends. */
+static int bits_per_byte = 8;
+
+/* The routines that read and process dies 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. */
+struct field_info
+{
+ /* List of data member and baseclasses fields. */
+ struct nextfield
+ {
+ struct nextfield *next;
+ int accessibility;
+ int virtuality;
+ struct field field;
+ } *fields;
+
+ /* Number of fields. */
+ int nfields;
+
+ /* Number of baseclasses. */
+ int nbaseclasses;
+
+ /* Set if the accesibility of one of the fields is not public. */
+ int non_public_fields;
+
+ /* Member function fields array, entries are allocated in the order they
+ are encountered in the object file. */
+ struct nextfnfield
+ {
+ struct nextfnfield *next;
+ struct fn_field fnfield;
+ } *fnfields;
+
+ /* Member function fieldlist array, contains name of possibly overloaded
+ member function, number of overloaded member functions and a pointer
+ to the head of the member function field chain. */
+ struct fnfieldlist
+ {
+ char *name;
+ int length;
+ struct nextfnfield *head;
+ } *fnfieldlists;
+
+ /* Number of entries in the fnfieldlists array. */
+ int nfnfields;
+};
+
+/* FIXME: Kludge to mark a varargs function type for C++ member function
+ argument processing. */
+#define TYPE_FLAG_VARARGS (1 << 10)
+
+/* Dwarf2 has no clean way to discern C++ static and non-static member
+ functions. G++ helps GDB by marking the first parameter for non-static
+ member functions (which is the this pointer) as artificial.
+ We pass this information between dwarf2_add_member_fn and
+ read_subroutine_type via TYPE_FIELD_ARTIFICIAL. */
+#define TYPE_FIELD_ARTIFICIAL TYPE_FIELD_BITPOS
+
+/* Various complaints about symbol reading that don't abort the process */
+
+static struct complaint dwarf2_const_ignored =
+{
+ "type qualifier 'const' ignored", 0, 0
+};
+static struct complaint dwarf2_volatile_ignored =
+{
+ "type qualifier 'volatile' ignored", 0, 0
+};
+static struct complaint dwarf2_non_const_array_bound_ignored =
+{
+ "non-constant array bounds form '%s' ignored", 0, 0
+};
+static struct complaint dwarf2_missing_line_number_section =
+{
+ "missing .debug_line section", 0, 0
+};
+static struct complaint dwarf2_mangled_line_number_section =
+{
+ "mangled .debug_line section", 0, 0
+};
+static struct complaint dwarf2_unsupported_die_ref_attr =
+{
+ "unsupported die ref attribute form: '%s'", 0, 0
+};
+static struct complaint dwarf2_unsupported_stack_op =
+{
+ "unsupported stack op: '%s'", 0, 0
+};
+static struct complaint dwarf2_unsupported_tag =
+{
+ "unsupported tag: '%s'", 0, 0
+};
+static struct complaint dwarf2_unsupported_at_encoding =
+{
+ "unsupported DW_AT_encoding: '%s'", 0, 0
+};
+static struct complaint dwarf2_unsupported_at_frame_base =
+{
+ "unsupported DW_AT_frame_base for function '%s'", 0, 0
+};
+static struct complaint dwarf2_unexpected_tag =
+{
+ "unexepected tag in read_type_die: '%s'", 0, 0
+};
+static struct complaint dwarf2_missing_at_frame_base =
+{
+ "DW_AT_frame_base missing for DW_OP_fbreg", 0, 0
+};
+static struct complaint dwarf2_bad_static_member_name =
+{
+ "unrecognized static data member name '%s'", 0, 0
+};
+static struct complaint dwarf2_unsupported_accessibility =
+{
+ "unsupported accessibility %d", 0, 0
+};
+static struct complaint dwarf2_bad_member_name_complaint =
+{
+ "cannot extract member name from '%s'", 0, 0
+};
+static struct complaint dwarf2_missing_member_fn_type_complaint =
+{
+ "member function type missing for '%s'", 0, 0
+};
+static struct complaint dwarf2_vtbl_not_found_complaint =
+{
+ "virtual function table pointer not found when defining class '%s'", 0, 0
+};
+static struct complaint dwarf2_absolute_sibling_complaint =
+{
+ "ignoring absolute DW_AT_sibling", 0, 0
+};
+static struct complaint dwarf2_const_value_length_mismatch =
+{
+ "const value length mismatch for '%s', got %d, expected %d", 0, 0
+};
+static struct complaint dwarf2_unsupported_const_value_attr =
+{
+ "unsupported const value attribute form: '%s'", 0, 0
+};
+
+/* Remember the addr_size read from the dwarf.
+ If a target expects to link compilation units with differing address
+ sizes, gdb needs to be sure that the appropriate size is here for
+ whatever scope is currently getting read. */
+static int address_size;
+
+/* Some elf32 object file formats while linked for a 32 bit address
+ space contain debug information that has assumed 64 bit
+ addresses. Eg 64 bit MIPS target produced by GCC/GAS/LD where the
+ symbol table contains 32bit address values while its .debug_info
+ section contains 64 bit address values.
+ ADDRESS_SIGNIFICANT_SIZE specifies the number significant bits in
+ the ADDRESS_SIZE bytes read from the file */
+static int address_significant_size;
+
+/* Externals references. */
+extern int info_verbose; /* From main.c; nonzero => verbose */
+
+/* local function prototypes */
+
+static void dwarf2_locate_sections PARAMS ((bfd *, asection *, PTR));
+
+#if 0
+static void dwarf2_build_psymtabs_easy PARAMS ((struct objfile *,
+ struct section_offsets *,
+ int));
+#endif
+
+static void dwarf2_build_psymtabs_hard PARAMS ((struct objfile *,
+ struct section_offsets *,
+ int));
+
+static char *scan_partial_symbols PARAMS ((char *, struct objfile *,
+ CORE_ADDR *, CORE_ADDR *));
+
+static void add_partial_symbol PARAMS ((struct partial_die_info *,
+ struct objfile *));
+
+static void dwarf2_psymtab_to_symtab PARAMS ((struct partial_symtab *));
+
+static void psymtab_to_symtab_1 PARAMS ((struct partial_symtab *));
+
+static char *dwarf2_read_section PARAMS ((struct objfile *, file_ptr,
+ unsigned int));
+
+static void dwarf2_read_abbrevs PARAMS ((bfd *, unsigned int));
+
+static void dwarf2_empty_abbrev_table PARAMS ((PTR));
+
+static struct abbrev_info *dwarf2_lookup_abbrev PARAMS ((unsigned int));
+
+static char *read_partial_die PARAMS ((struct partial_die_info *,
+ bfd *, char *, int *));
+
+static char *read_full_die PARAMS ((struct die_info **, bfd *, char *));
+
+static char *read_attribute PARAMS ((struct attribute *, struct attr_abbrev *,
+ bfd *, char *));
+
+static unsigned int read_1_byte PARAMS ((bfd *, char *));
+
+static int read_1_signed_byte PARAMS ((bfd *, char *));
+
+static unsigned int read_2_bytes PARAMS ((bfd *, char *));
+
+static unsigned int read_4_bytes PARAMS ((bfd *, char *));
+
+static unsigned int read_8_bytes PARAMS ((bfd *, char *));
+
+static CORE_ADDR read_address PARAMS ((bfd *, char *));
+
+static char *read_n_bytes PARAMS ((bfd *, char *, unsigned int));
+
+static char *read_string PARAMS ((bfd *, char *, unsigned int *));
+
+static unsigned int read_unsigned_leb128 PARAMS ((bfd *, char *,
+ unsigned int *));
+
+static int read_signed_leb128 PARAMS ((bfd *, char *, unsigned int *));
+
+static void set_cu_language PARAMS ((unsigned int));
+
+static struct attribute *dwarf_attr PARAMS ((struct die_info *,
+ unsigned int));
+
+static void dwarf_decode_lines PARAMS ((unsigned int, char *, bfd *));
+
+static void dwarf2_start_subfile PARAMS ((char *, char *));
+
+static struct symbol *new_symbol PARAMS ((struct die_info *, struct type *,
+ struct objfile *));
+
+static void dwarf2_const_value PARAMS ((struct attribute *, struct symbol *,
+ struct objfile *));
+
+static struct type *die_type PARAMS ((struct die_info *, struct objfile *));
+
+static struct type *die_containing_type PARAMS ((struct die_info *,
+ struct objfile *));
+
+#if 0
+static struct type *type_at_offset PARAMS ((unsigned int, struct objfile *));
+#endif
+
+static struct type *tag_type_to_type PARAMS ((struct die_info *,
+ struct objfile *));
+
+static void read_type_die PARAMS ((struct die_info *, struct objfile *));
+
+static void read_typedef PARAMS ((struct die_info *, struct objfile *));
+
+static void read_base_type PARAMS ((struct die_info *, struct objfile *));
+
+static void read_file_scope PARAMS ((struct die_info *, struct objfile *));
+
+static void read_func_scope PARAMS ((struct die_info *, struct objfile *));
+
+static void read_lexical_block_scope PARAMS ((struct die_info *,
+ struct objfile *));
+
+static int dwarf2_get_pc_bounds PARAMS ((struct die_info *,
+ CORE_ADDR *, CORE_ADDR *,
+ struct objfile *));
+
+static void dwarf2_add_field PARAMS ((struct field_info *, struct die_info *,
+ struct objfile *));
+
+static void dwarf2_attach_fields_to_type PARAMS ((struct field_info *,
+ struct type *,
+ struct objfile *));
+
+static char *skip_member_fn_name PARAMS ((char *));
+
+static void dwarf2_add_member_fn PARAMS ((struct field_info *,
+ struct die_info *, struct type *,
+ struct objfile *objfile));
+
+static void dwarf2_attach_fn_fields_to_type PARAMS ((struct field_info *,
+ struct type *,
+ struct objfile *));
+
+static void read_structure_scope PARAMS ((struct die_info *, struct objfile *));
+
+static void read_common_block PARAMS ((struct die_info *, struct objfile *));
+
+static void read_enumeration PARAMS ((struct die_info *, struct objfile *));
+
+static struct type *dwarf_base_type PARAMS ((int, int, struct objfile *));
+
+static CORE_ADDR decode_locdesc PARAMS ((struct dwarf_block *,
+ struct objfile *));
+
+static void read_array_type PARAMS ((struct die_info *, struct objfile *));
+
+static void read_tag_pointer_type PARAMS ((struct die_info *,
+ struct objfile *));
+
+static void read_tag_ptr_to_member_type PARAMS ((struct die_info *,
+ struct objfile *));
+
+static void read_tag_reference_type PARAMS ((struct die_info *,
+ struct objfile *));
+
+static void read_tag_const_type PARAMS ((struct die_info *, struct objfile *));
+
+static void read_tag_volatile_type PARAMS ((struct die_info *,
+ struct objfile *));
+
+static void read_tag_string_type PARAMS ((struct die_info *,
+ struct objfile *));
+
+static void read_subroutine_type PARAMS ((struct die_info *,
+ struct objfile *));
+
+struct die_info *read_comp_unit PARAMS ((char *, bfd *));
+
+static void free_die_list PARAMS ((struct die_info *));
+
+static void process_die PARAMS ((struct die_info *, struct objfile *));
+
+static char *dwarf2_linkage_name PARAMS ((struct die_info *));
+
+static char *dwarf_tag_name PARAMS ((unsigned int));
+
+static char *dwarf_attr_name PARAMS ((unsigned int));
+
+static char *dwarf_form_name PARAMS ((unsigned int));
+
+static char *dwarf_stack_op_name PARAMS ((unsigned int));
+
+static char *dwarf_bool_name PARAMS ((unsigned int));
+
+static char *dwarf_type_encoding_name PARAMS ((unsigned int));
+
+#if 0
+static char *dwarf_cfi_name PARAMS ((unsigned int));
+
+struct die_info *copy_die PARAMS ((struct die_info *));
+#endif
+
+struct die_info *sibling_die PARAMS ((struct die_info *));
+
+void dump_die PARAMS ((struct die_info *));
+
+void dump_die_list PARAMS ((struct die_info *));
+
+void store_in_ref_table PARAMS ((unsigned int, struct die_info *));
+
+static void dwarf2_empty_die_ref_table PARAMS ((void));
+
+static unsigned int dwarf2_get_ref_die_offset PARAMS ((struct attribute *));
+
+struct die_info *follow_die_ref PARAMS ((unsigned int));
+
+static struct type *dwarf2_fundamental_type PARAMS ((struct objfile *, int));
+
+/* memory allocation interface */
+
+static void dwarf2_free_tmp_obstack PARAMS ((PTR));
+
+static struct dwarf_block *dwarf_alloc_block PARAMS ((void));
+
+static struct abbrev_info *dwarf_alloc_abbrev PARAMS ((void));
+
+static struct die_info *dwarf_alloc_die PARAMS ((void));
+
+/* Try to locate the sections we need for DWARF 2 debugging
+ information and return true if we have enough to do something. */
+
+int
+dwarf2_has_info (abfd)
+ bfd *abfd;
+{
+ dwarf_info_offset = dwarf_abbrev_offset = dwarf_line_offset = 0;
+ bfd_map_over_sections (abfd, dwarf2_locate_sections, NULL);
+ if (dwarf_info_offset && dwarf_abbrev_offset)
+ {
+ return 1;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+/* This function is mapped across the sections and remembers the
+ offset and size of each of the debugging sections we are interested
+ in. */
+
+static void
+dwarf2_locate_sections (ignore_abfd, sectp, ignore_ptr)
+ bfd *ignore_abfd;
+ asection *sectp;
+ PTR ignore_ptr;
+{
+ if (STREQ (sectp->name, INFO_SECTION))
+ {
+ dwarf_info_offset = sectp->filepos;
+ dwarf_info_size = bfd_get_section_size_before_reloc (sectp);
+ }
+ else if (STREQ (sectp->name, ABBREV_SECTION))
+ {
+ dwarf_abbrev_offset = sectp->filepos;
+ dwarf_abbrev_size = bfd_get_section_size_before_reloc (sectp);
+ }
+ else if (STREQ (sectp->name, LINE_SECTION))
+ {
+ dwarf_line_offset = sectp->filepos;
+ dwarf_line_size = bfd_get_section_size_before_reloc (sectp);
+ }
+ else if (STREQ (sectp->name, PUBNAMES_SECTION))
+ {
+ dwarf_pubnames_offset = sectp->filepos;
+ dwarf_pubnames_size = bfd_get_section_size_before_reloc (sectp);
+ }
+ else if (STREQ (sectp->name, ARANGES_SECTION))
+ {
+ dwarf_aranges_offset = sectp->filepos;
+ dwarf_aranges_size = bfd_get_section_size_before_reloc (sectp);
+ }
+ else if (STREQ (sectp->name, LOC_SECTION))
+ {
+ dwarf_loc_offset = sectp->filepos;
+ dwarf_loc_size = bfd_get_section_size_before_reloc (sectp);
+ }
+ else if (STREQ (sectp->name, MACINFO_SECTION))
+ {
+ dwarf_macinfo_offset = sectp->filepos;
+ dwarf_macinfo_size = bfd_get_section_size_before_reloc (sectp);
+ }
+ else if (STREQ (sectp->name, STR_SECTION))
+ {
+ dwarf_str_offset = sectp->filepos;
+ dwarf_str_size = bfd_get_section_size_before_reloc (sectp);
+ }
+}
+
+/* Build a partial symbol table. */
+
+void
+dwarf2_build_psymtabs (objfile, section_offsets, mainline)
+ struct objfile *objfile;
+ struct section_offsets *section_offsets;
+ int mainline;
+{
+
+ /* We definitely need the .debug_info and .debug_abbrev sections */
+
+ dwarf_info_buffer = dwarf2_read_section (objfile,
+ dwarf_info_offset,
+ dwarf_info_size);
+ dwarf_abbrev_buffer = dwarf2_read_section (objfile,
+ dwarf_abbrev_offset,
+ dwarf_abbrev_size);
+ dwarf_line_buffer = dwarf2_read_section (objfile,
+ dwarf_line_offset,
+ dwarf_line_size);
+
+ if (mainline || objfile->global_psymbols.size == 0 ||
+ objfile->static_psymbols.size == 0)
+ {
+ init_psymbol_list (objfile, 1024);
+ }
+
+#if 0
+ if (dwarf_aranges_offset && dwarf_pubnames_offset)
+ {
+ /* Things are significanlty easier if we have .debug_aranges and
+ .debug_pubnames sections */
+
+ dwarf2_build_psymtabs_easy (objfile, section_offsets, mainline);
+ }
+ else
+#endif
+ /* only test this case for now */
+ {
+ /* In this case we have to work a bit harder */
+ dwarf2_build_psymtabs_hard (objfile, section_offsets, mainline);
+ }
+}
+
+#if 0
+/* Build the partial symbol table from the information in the
+ .debug_pubnames and .debug_aranges sections. */
+
+static void
+dwarf2_build_psymtabs_easy (objfile, section_offsets, mainline)
+ struct objfile *objfile;
+ struct section_offsets *section_offsets;
+ int mainline;
+{
+ bfd *abfd = objfile->obfd;
+ char *aranges_buffer, *pubnames_buffer;
+ char *aranges_ptr, *pubnames_ptr;
+ unsigned int entry_length, version, info_offset, info_size;
+
+ pubnames_buffer = dwarf2_read_section (objfile,
+ dwarf_pubnames_offset,
+ dwarf_pubnames_size);
+ pubnames_ptr = pubnames_buffer;
+ while ((pubnames_ptr - pubnames_buffer) < dwarf_pubnames_size)
+ {
+ entry_length = read_4_bytes (abfd, pubnames_ptr);
+ pubnames_ptr += 4;
+ version = read_1_byte (abfd, pubnames_ptr);
+ pubnames_ptr += 1;
+ info_offset = read_4_bytes (abfd, pubnames_ptr);
+ pubnames_ptr += 4;
+ info_size = read_4_bytes (abfd, pubnames_ptr);
+ pubnames_ptr += 4;
+ }
+
+ aranges_buffer = dwarf2_read_section (objfile,
+ dwarf_aranges_offset,
+ dwarf_aranges_size);
+
+}
+#endif
+
+/* Build the partial symbol table by doing a quick pass through the
+ .debug_info and .debug_abbrev sections. */
+
+static void
+dwarf2_build_psymtabs_hard (objfile, section_offsets, mainline)
+ struct objfile *objfile;
+ struct section_offsets *section_offsets;
+ int mainline;
+{
+ /* Instead of reading this into a big buffer, we should probably use
+ mmap() on architectures that support it. (FIXME) */
+ bfd *abfd = objfile->obfd;
+ char *info_ptr, *abbrev_ptr;
+ char *beg_of_comp_unit;
+ struct comp_unit_head cu_header;
+ struct partial_die_info comp_unit_die;
+ struct partial_symtab *pst;
+ struct cleanup *back_to;
+ int comp_unit_has_pc_info;
+ CORE_ADDR lowpc, highpc;
+
+ /* Number of bytes of any addresses that are signficant */
+ address_significant_size = get_elf_backend_data (abfd)->s->arch_size / 8;
+
+ info_ptr = dwarf_info_buffer;
+ abbrev_ptr = dwarf_abbrev_buffer;
+
+ obstack_init (&dwarf2_tmp_obstack);
+ back_to = make_cleanup (dwarf2_free_tmp_obstack, NULL);
+
+ while ((unsigned int) (info_ptr - dwarf_info_buffer)
+ + ((info_ptr - dwarf_info_buffer) % 4) < dwarf_info_size)
+ {
+ beg_of_comp_unit = info_ptr;
+ cu_header.length = read_4_bytes (abfd, info_ptr);
+ info_ptr += 4;
+ cu_header.version = read_2_bytes (abfd, info_ptr);
+ info_ptr += 2;
+ cu_header.abbrev_offset = read_4_bytes (abfd, info_ptr);
+ info_ptr += 4;
+ cu_header.addr_size = read_1_byte (abfd, info_ptr);
+ info_ptr += 1;
+ address_size = cu_header.addr_size;
+
+ if (cu_header.version != 2)
+ {
+ error ("Dwarf Error: wrong version in compilation unit header.");
+ return;
+ }
+ if (cu_header.abbrev_offset >= dwarf_abbrev_size)
+ {
+ error ("Dwarf Error: bad offset (0x%lx) in compilation unit header (offset 0x%lx + 6).",
+ (long) cu_header.abbrev_offset,
+ (long) (beg_of_comp_unit - dwarf_info_buffer));
+ return;
+ }
+ if (beg_of_comp_unit + cu_header.length + 4
+ > dwarf_info_buffer + dwarf_info_size)
+ {
+ error ("Dwarf Error: bad length (0x%lx) in compilation unit header (offset 0x%lx + 0).",
+ (long) cu_header.length,
+ (long) (beg_of_comp_unit - dwarf_info_buffer));
+ return;
+ }
+ if (address_size < address_significant_size)
+ {
+ error ("Dwarf Error: bad address size (%ld) in compilation unit header (offset 0x%lx + 11).",
+ (long) cu_header.addr_size,
+ (long) (beg_of_comp_unit - dwarf_info_buffer));
+ }
+
+ /* Read the abbrevs for this compilation unit into a table */
+ dwarf2_read_abbrevs (abfd, cu_header.abbrev_offset);
+ make_cleanup (dwarf2_empty_abbrev_table, NULL);
+
+ /* Read the compilation unit die */
+ info_ptr = read_partial_die (&comp_unit_die, abfd,
+ info_ptr, &comp_unit_has_pc_info);
+
+ /* Set the language we're debugging */
+ set_cu_language (comp_unit_die.language);
+
+ /* Allocate a new partial symbol table structure */
+ pst = start_psymtab_common (objfile, section_offsets,
+ comp_unit_die.name ? comp_unit_die.name : "",
+ comp_unit_die.lowpc,
+ objfile->global_psymbols.next,
+ objfile->static_psymbols.next);
+
+ pst->read_symtab_private = (char *)
+ obstack_alloc (&objfile->psymbol_obstack, sizeof (struct dwarf2_pinfo));
+ cu_header_offset = beg_of_comp_unit - dwarf_info_buffer;
+ DWARF_INFO_BUFFER(pst) = dwarf_info_buffer;
+ DWARF_INFO_OFFSET(pst) = beg_of_comp_unit - dwarf_info_buffer;
+ DWARF_ABBREV_BUFFER(pst) = dwarf_abbrev_buffer;
+ DWARF_ABBREV_SIZE(pst) = dwarf_abbrev_size;
+ DWARF_LINE_BUFFER(pst) = dwarf_line_buffer;
+ baseaddr = ANOFFSET (section_offsets, 0);
+
+ /* Store the function that reads in the rest of the symbol table */
+ pst->read_symtab = dwarf2_psymtab_to_symtab;
+
+ /* Check if comp unit has_children.
+ If so, read the rest of the partial symbols from this comp unit.
+ If not, there's no more debug_info for this comp unit. */
+ if (comp_unit_die.has_children)
+ {
+ info_ptr = scan_partial_symbols (info_ptr, objfile, &lowpc, &highpc);
+
+ /* If the compilation unit didn't have an explicit address range,
+ then use the information extracted from its child dies. */
+ if (!comp_unit_has_pc_info)
+ {
+ comp_unit_die.lowpc = lowpc;
+ comp_unit_die.highpc = highpc;
+ }
+ }
+ pst->textlow = comp_unit_die.lowpc + baseaddr;
+ pst->texthigh = comp_unit_die.highpc + baseaddr;
+
+ 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);
+
+ info_ptr = beg_of_comp_unit + cu_header.length + 4;
+ }
+ do_cleanups (back_to);
+}
+
+/* Read in all interesting dies to the end of the compilation unit. */
+
+static char *
+scan_partial_symbols (info_ptr, objfile, lowpc, highpc)
+ char *info_ptr;
+ struct objfile *objfile;
+ CORE_ADDR *lowpc;
+ CORE_ADDR *highpc;
+{
+ bfd *abfd = objfile->obfd;
+ struct partial_die_info pdi;
+
+ /* This function is called after we've read in the comp_unit_die in
+ order to read its children. We start the nesting level at 1 since
+ we have pushed 1 level down in order to read the comp unit's children.
+ The comp unit itself is at level 0, so we stop reading when we pop
+ back to that level. */
+
+ int nesting_level = 1;
+ int has_pc_info;
+
+ *lowpc = ((CORE_ADDR) -1);
+ *highpc = ((CORE_ADDR) 0);
+
+ while (nesting_level)
+ {
+ info_ptr = read_partial_die (&pdi, abfd, info_ptr, &has_pc_info);
+
+ if (pdi.name)
+ {
+ switch (pdi.tag)
+ {
+ case DW_TAG_subprogram:
+ if (has_pc_info)
+ {
+ if (pdi.lowpc < *lowpc)
+ {
+ *lowpc = pdi.lowpc;
+ }
+ if (pdi.highpc > *highpc)
+ {
+ *highpc = pdi.highpc;
+ }
+ if ((pdi.is_external || nesting_level == 1)
+ && !pdi.is_declaration)
+ {
+ add_partial_symbol (&pdi, objfile);
+ }
+ }
+ break;
+ case DW_TAG_variable:
+ case DW_TAG_typedef:
+ case DW_TAG_class_type:
+ case DW_TAG_structure_type:
+ case DW_TAG_union_type:
+ case DW_TAG_enumeration_type:
+ if ((pdi.is_external || nesting_level == 1)
+ && !pdi.is_declaration)
+ {
+ add_partial_symbol (&pdi, objfile);
+ }
+ break;
+ case DW_TAG_enumerator:
+ /* File scope enumerators are added to the partial symbol
+ table. */
+ if (nesting_level == 2)
+ add_partial_symbol (&pdi, objfile);
+ break;
+ case DW_TAG_base_type:
+ /* File scope base type definitions are added to the partial
+ symbol table. */
+ if (nesting_level == 1)
+ add_partial_symbol (&pdi, objfile);
+ break;
+ default:
+ break;
+ }
+ }
+
+ /* If the die has a sibling, skip to the sibling.
+ Do not skip enumeration types, we want to record their
+ enumerators. */
+ if (pdi.sibling && pdi.tag != DW_TAG_enumeration_type)
+ {
+ info_ptr = pdi.sibling;
+ }
+ else if (pdi.has_children)
+ {
+ /* Die has children, but the optional DW_AT_sibling attribute
+ is missing. */
+ nesting_level++;
+ }
+
+ if (pdi.tag == 0)
+ {
+ nesting_level--;
+ }
+ }
+
+ /* If we didn't find a lowpc, set it to highpc to avoid complaints
+ from `maint check'. */
+ if (*lowpc == ((CORE_ADDR) -1))
+ *lowpc = *highpc;
+ return info_ptr;
+}
+
+static void
+add_partial_symbol (pdi, objfile)
+ struct partial_die_info *pdi;
+ struct objfile *objfile;
+{
+ CORE_ADDR addr = 0;
+
+ switch (pdi->tag)
+ {
+ case DW_TAG_subprogram:
+ if (pdi->is_external)
+ {
+ /*prim_record_minimal_symbol (pdi->name, pdi->lowpc + baseaddr,
+ mst_text, objfile);*/
+ add_psymbol_to_list (pdi->name, strlen (pdi->name),
+ VAR_NAMESPACE, LOC_BLOCK,
+ &objfile->global_psymbols,
+ 0, pdi->lowpc + baseaddr, cu_language, objfile);
+ }
+ else
+ {
+ /*prim_record_minimal_symbol (pdi->name, pdi->lowpc + baseaddr,
+ mst_file_text, objfile);*/
+ add_psymbol_to_list (pdi->name, strlen (pdi->name),
+ VAR_NAMESPACE, LOC_BLOCK,
+ &objfile->static_psymbols,
+ 0, pdi->lowpc + baseaddr, cu_language, objfile);
+ }
+ break;
+ case DW_TAG_variable:
+ if (pdi->is_external)
+ {
+ /* Global Variable.
+ Don't enter into the minimal symbol tables as there is
+ a minimal symbol table entry from the ELF symbols already.
+ Enter into partial symbol table if it has a location
+ descriptor or a type.
+ If the location descriptor is missing, new_symbol will create
+ a LOC_UNRESOLVED symbol, the address of the variable will then
+ be determined from the minimal symbol table whenever the variable
+ is referenced.
+ The address for the partial symbol table entry is not
+ used by GDB, but it comes in handy for debugging partial symbol
+ table building. */
+
+ if (pdi->locdesc)
+ addr = decode_locdesc (pdi->locdesc, objfile);
+ if (pdi->locdesc || pdi->has_type)
+ add_psymbol_to_list (pdi->name, strlen (pdi->name),
+ VAR_NAMESPACE, LOC_STATIC,
+ &objfile->global_psymbols,
+ 0, addr + baseaddr, cu_language, objfile);
+ }
+ else
+ {
+ /* Static Variable. Skip symbols without location descriptors. */
+ if (pdi->locdesc == NULL)
+ return;
+ addr = decode_locdesc (pdi->locdesc, objfile);
+ /*prim_record_minimal_symbol (pdi->name, addr + baseaddr,
+ mst_file_data, objfile);*/
+ add_psymbol_to_list (pdi->name, strlen (pdi->name),
+ VAR_NAMESPACE, LOC_STATIC,
+ &objfile->static_psymbols,
+ 0, addr + baseaddr, cu_language, objfile);
+ }
+ break;
+ case DW_TAG_typedef:
+ case DW_TAG_base_type:
+ add_psymbol_to_list (pdi->name, strlen (pdi->name),
+ VAR_NAMESPACE, LOC_TYPEDEF,
+ &objfile->static_psymbols,
+ 0, (CORE_ADDR) 0, cu_language, objfile);
+ break;
+ case DW_TAG_class_type:
+ case DW_TAG_structure_type:
+ case DW_TAG_union_type:
+ case DW_TAG_enumeration_type:
+ /* Skip aggregate types without children, these are external
+ references. */
+ if (pdi->has_children == 0)
+ return;
+ add_psymbol_to_list (pdi->name, strlen (pdi->name),
+ STRUCT_NAMESPACE, LOC_TYPEDEF,
+ &objfile->static_psymbols,
+ 0, (CORE_ADDR) 0, cu_language, objfile);
+
+ if (cu_language == language_cplus)
+ {
+ /* For C++, these implicitly act as typedefs as well. */
+ add_psymbol_to_list (pdi->name, strlen (pdi->name),
+ VAR_NAMESPACE, LOC_TYPEDEF,
+ &objfile->static_psymbols,
+ 0, (CORE_ADDR) 0, cu_language, objfile);
+ }
+ break;
+ case DW_TAG_enumerator:
+ add_psymbol_to_list (pdi->name, strlen (pdi->name),
+ VAR_NAMESPACE, LOC_CONST,
+ &objfile->static_psymbols,
+ 0, (CORE_ADDR) 0, cu_language, objfile);
+ break;
+ default:
+ break;
+ }
+}
+
+/* Expand this partial symbol table into a full symbol table. */
+
+static void
+dwarf2_psymtab_to_symtab (pst)
+ struct partial_symtab *pst;
+{
+ /* FIXME: This is barely more than a stub. */
+ if (pst != NULL)
+ {
+ if (pst->readin)
+ {
+ warning ("bug: psymtab for %s is already read in.", pst->filename);
+ }
+ else
+ {
+ if (info_verbose)
+ {
+ printf_filtered ("Reading in symbols for %s...", pst->filename);
+ gdb_flush (gdb_stdout);
+ }
+
+ psymtab_to_symtab_1 (pst);
+
+ /* Finish up the debug error message. */
+ if (info_verbose)
+ printf_filtered ("done.\n");
+ }
+ }
+}
+
+static void
+psymtab_to_symtab_1 (pst)
+ struct partial_symtab *pst;
+{
+ struct objfile *objfile = pst->objfile;
+ bfd *abfd = objfile->obfd;
+ struct comp_unit_head cu_header;
+ struct die_info *dies;
+ unsigned long offset;
+ CORE_ADDR lowpc, highpc;
+ struct die_info *child_die;
+ char *info_ptr;
+ struct symtab *symtab;
+ struct cleanup *back_to;
+
+ /* Set local variables from the partial symbol table info. */
+ offset = DWARF_INFO_OFFSET(pst);
+ dwarf_info_buffer = DWARF_INFO_BUFFER(pst);
+ dwarf_abbrev_buffer = DWARF_ABBREV_BUFFER(pst);
+ dwarf_abbrev_size = DWARF_ABBREV_SIZE(pst);
+ dwarf_line_buffer = DWARF_LINE_BUFFER(pst);
+ baseaddr = ANOFFSET (pst->section_offsets, 0);
+ cu_header_offset = offset;
+ info_ptr = dwarf_info_buffer + offset;
+
+ obstack_init (&dwarf2_tmp_obstack);
+ back_to = make_cleanup (dwarf2_free_tmp_obstack, NULL);
+
+ buildsym_init ();
+ make_cleanup ((make_cleanup_func) really_free_pendings, NULL);
+
+ /* read in the comp_unit header */
+ cu_header.length = read_4_bytes (abfd, info_ptr);
+ info_ptr += 4;
+ cu_header.version = read_2_bytes (abfd, info_ptr);
+ info_ptr += 2;
+ cu_header.abbrev_offset = read_4_bytes (abfd, info_ptr);
+ info_ptr += 4;
+ cu_header.addr_size = read_1_byte (abfd, info_ptr);
+ info_ptr += 1;
+
+ /* Read the abbrevs for this compilation unit */
+ dwarf2_read_abbrevs (abfd, cu_header.abbrev_offset);
+ make_cleanup (dwarf2_empty_abbrev_table, NULL);
+
+ dies = read_comp_unit (info_ptr, abfd);
+
+ make_cleanup ((make_cleanup_func) free_die_list, dies);
+
+ /* Do line number decoding in read_file_scope () */
+ process_die (dies, objfile);
+
+ if (!dwarf2_get_pc_bounds (dies, &lowpc, &highpc, objfile))
+ {
+ /* Some compilers don't define a DW_AT_high_pc attribute for
+ the compilation unit. If the DW_AT_high_pc is missing,
+ synthesize it, by scanning the DIE's below the compilation unit. */
+ highpc = 0;
+ if (dies->has_children)
+ {
+ child_die = dies->next;
+ while (child_die && child_die->tag)
+ {
+ if (child_die->tag == DW_TAG_subprogram)
+ {
+ CORE_ADDR low, high;
+
+ if (dwarf2_get_pc_bounds (child_die, &low, &high, objfile))
+ {
+ highpc = max (highpc, high);
+ }
+ }
+ child_die = sibling_die (child_die);
+ }
+ }
+ }
+ symtab = end_symtab (highpc + baseaddr, objfile, 0);
+
+ /* Set symtab language to language from DW_AT_language.
+ If the compilation is from a C file generated by language preprocessors,
+ do not set the language if it was already deduced by start_subfile. */
+ if (symtab != NULL
+ && !(cu_language == language_c && symtab->language != language_c))
+ {
+ symtab->language = cu_language;
+ }
+ pst->symtab = symtab;
+ pst->readin = 1;
+ sort_symtab_syms (pst->symtab);
+
+ do_cleanups (back_to);
+}
+
+/* Process a die and its children. */
+
+static void
+process_die (die, objfile)
+ struct die_info *die;
+ struct objfile *objfile;
+{
+ switch (die->tag)
+ {
+ case DW_TAG_padding:
+ break;
+ case DW_TAG_compile_unit:
+ read_file_scope (die, objfile);
+ break;
+ case DW_TAG_subprogram:
+ read_subroutine_type (die, objfile);
+ read_func_scope (die, objfile);
+ break;
+ case DW_TAG_inlined_subroutine:
+ /* FIXME: These are ignored for now.
+ They could be used to set breakpoints on all inlined instances
+ of a function and make GDB `next' properly over inlined functions. */
+ break;
+ case DW_TAG_lexical_block:
+ read_lexical_block_scope (die, objfile);
+ break;
+ case DW_TAG_class_type:
+ case DW_TAG_structure_type:
+ case DW_TAG_union_type:
+ read_structure_scope (die, objfile);
+ break;
+ case DW_TAG_enumeration_type:
+ read_enumeration (die, objfile);
+ break;
+ case DW_TAG_subroutine_type:
+ read_subroutine_type (die, objfile);
+ break;
+ case DW_TAG_array_type:
+ read_array_type (die, objfile);
+ break;
+ case DW_TAG_pointer_type:
+ read_tag_pointer_type (die, objfile);
+ break;
+ case DW_TAG_ptr_to_member_type:
+ read_tag_ptr_to_member_type (die, objfile);
+ break;
+ case DW_TAG_reference_type:
+ read_tag_reference_type (die, objfile);
+ break;
+ case DW_TAG_string_type:
+ read_tag_string_type (die, objfile);
+ break;
+ case DW_TAG_base_type:
+ read_base_type (die, objfile);
+ if (dwarf_attr (die, DW_AT_name))
+ {
+ /* Add a typedef symbol for the base type definition. */
+ new_symbol (die, die->type, objfile);
+ }
+ break;
+ case DW_TAG_common_block:
+ read_common_block (die, objfile);
+ break;
+ case DW_TAG_common_inclusion:
+ break;
+ default:
+ new_symbol (die, NULL, objfile);
+ break;
+ }
+}
+
+static void
+read_file_scope (die, objfile)
+ struct die_info *die;
+ struct objfile *objfile;
+{
+ unsigned int line_offset = 0;
+ CORE_ADDR lowpc = ((CORE_ADDR) -1);
+ CORE_ADDR highpc = ((CORE_ADDR) 0);
+ struct attribute *attr;
+ char *name = "<unknown>";
+ char *comp_dir = NULL;
+ struct die_info *child_die;
+ bfd *abfd = objfile->obfd;
+
+ if (!dwarf2_get_pc_bounds (die, &lowpc, &highpc, objfile))
+ {
+ if (die->has_children)
+ {
+ child_die = die->next;
+ while (child_die && child_die->tag)
+ {
+ if (child_die->tag == DW_TAG_subprogram)
+ {
+ CORE_ADDR low, high;
+
+ if (dwarf2_get_pc_bounds (child_die, &low, &high, objfile))
+ {
+ lowpc = min (lowpc, low);
+ highpc = max (highpc, high);
+ }
+ }
+ child_die = sibling_die (child_die);
+ }
+ }
+ }
+
+ /* If we didn't find a lowpc, set it to highpc to avoid complaints
+ from finish_block. */
+ if (lowpc == ((CORE_ADDR) -1))
+ lowpc = highpc;
+ lowpc += baseaddr;
+ highpc += baseaddr;
+
+ attr = dwarf_attr (die, DW_AT_name);
+ if (attr)
+ {
+ name = DW_STRING (attr);
+ }
+ attr = dwarf_attr (die, DW_AT_comp_dir);
+ if (attr)
+ {
+ comp_dir = DW_STRING (attr);
+ if (comp_dir)
+ {
+ /* Irix 6.2 native cc prepends <machine>.: to the compilation
+ directory, get rid of it. */
+ char *cp = strchr (comp_dir, ':');
+
+ if (cp && cp != comp_dir && cp[-1] == '.' && cp[1] == '/')
+ comp_dir = cp + 1;
+ }
+ }
+
+ if (objfile->ei.entry_point >= lowpc &&
+ objfile->ei.entry_point < highpc)
+ {
+ objfile->ei.entry_file_lowpc = lowpc;
+ objfile->ei.entry_file_highpc = highpc;
+ }
+
+ attr = dwarf_attr (die, DW_AT_language);
+ if (attr)
+ {
+ set_cu_language (DW_UNSND (attr));
+ }
+
+ /* We assume that we're processing GCC output. */
+ processing_gcc_compilation = 2;
+#if 0
+ /* FIXME:Do something here. */
+ if (dip->at_producer != NULL)
+ {
+ handle_producer (dip->at_producer);
+ }
+#endif
+
+ /* The compilation unit may be in a different language or objfile,
+ zero out all remembered fundamental types. */
+ memset (ftypes, 0, FT_NUM_MEMBERS * sizeof (struct type *));
+
+ start_symtab (name, comp_dir, lowpc);
+ record_debugformat ("DWARF 2");
+
+ /* Decode line number information if present. */
+ attr = dwarf_attr (die, DW_AT_stmt_list);
+ if (attr)
+ {
+ line_offset = DW_UNSND (attr);
+ dwarf_decode_lines (line_offset, comp_dir, abfd);
+ }
+
+ /* Process all dies in compilation unit. */
+ if (die->has_children)
+ {
+ child_die = die->next;
+ while (child_die && child_die->tag)
+ {
+ process_die (child_die, objfile);
+ child_die = sibling_die (child_die);
+ }
+ }
+}
+
+static void
+read_func_scope (die, objfile)
+ struct die_info *die;
+ struct objfile *objfile;
+{
+ register struct context_stack *new;
+ CORE_ADDR lowpc;
+ CORE_ADDR highpc;
+ struct die_info *child_die;
+ struct attribute *attr;
+ char *name;
+
+ name = dwarf2_linkage_name (die);
+
+ /* Ignore functions with missing or empty names and functions with
+ missing or invalid low and high pc attributes. */
+ if (name == NULL || !dwarf2_get_pc_bounds (die, &lowpc, &highpc, objfile))
+ return;
+
+ lowpc += baseaddr;
+ highpc += baseaddr;
+
+ if (objfile->ei.entry_point >= lowpc &&
+ objfile->ei.entry_point < highpc)
+ {
+ objfile->ei.entry_func_lowpc = lowpc;
+ objfile->ei.entry_func_highpc = highpc;
+ }
+
+ if (STREQ (name, "main")) /* FIXME: hardwired name */
+ {
+ objfile->ei.main_func_lowpc = lowpc;
+ objfile->ei.main_func_highpc = highpc;
+ }
+
+ /* Decode DW_AT_frame_base location descriptor if present, keep result
+ for DW_OP_fbreg operands in decode_locdesc. */
+ frame_base_reg = -1;
+ frame_base_offset = 0;
+ attr = dwarf_attr (die, DW_AT_frame_base);
+ if (attr)
+ {
+ CORE_ADDR addr = decode_locdesc (DW_BLOCK (attr), objfile);
+ if (isreg)
+ frame_base_reg = addr;
+ else if (offreg)
+ {
+ frame_base_reg = basereg;
+ frame_base_offset = addr;
+ }
+ else
+ complain (&dwarf2_unsupported_at_frame_base, name);
+ }
+
+ new = push_context (0, lowpc);
+ new->name = new_symbol (die, die->type, objfile);
+ list_in_scope = &local_symbols;
+
+ if (die->has_children)
+ {
+ child_die = die->next;
+ while (child_die && child_die->tag)
+ {
+ process_die (child_die, objfile);
+ child_die = sibling_die (child_die);
+ }
+ }
+
+ new = pop_context ();
+ /* Make a block for the local symbols within. */
+ finish_block (new->name, &local_symbols, new->old_blocks,
+ lowpc, highpc, objfile);
+ list_in_scope = &file_symbols;
+}
+
+/* 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 (die, objfile)
+ struct die_info *die;
+ struct objfile *objfile;
+{
+ register struct context_stack *new;
+ CORE_ADDR lowpc, highpc;
+ struct die_info *child_die;
+
+ /* Ignore blocks with missing or invalid low and high pc attributes. */
+ if (!dwarf2_get_pc_bounds (die, &lowpc, &highpc, objfile))
+ return;
+ lowpc += baseaddr;
+ highpc += baseaddr;
+
+ push_context (0, lowpc);
+ if (die->has_children)
+ {
+ child_die = die->next;
+ while (child_die && child_die->tag)
+ {
+ process_die (child_die, objfile);
+ child_die = sibling_die (child_die);
+ }
+ }
+ new = pop_context ();
+
+ if (local_symbols != NULL)
+ {
+ finish_block (0, &local_symbols, new->old_blocks, new->start_addr,
+ highpc, objfile);
+ }
+ local_symbols = new->locals;
+}
+
+/* Get low and high pc attributes from a die.
+ Return 1 if the attributes are present and valid, otherwise, return 0. */
+
+static int
+dwarf2_get_pc_bounds (die, lowpc, highpc, objfile)
+ struct die_info *die;
+ CORE_ADDR *lowpc;
+ CORE_ADDR *highpc;
+ struct objfile *objfile;
+{
+ struct attribute *attr;
+ CORE_ADDR low;
+ CORE_ADDR high;
+
+ attr = dwarf_attr (die, DW_AT_low_pc);
+ if (attr)
+ low = DW_ADDR (attr);
+ else
+ return 0;
+ attr = dwarf_attr (die, DW_AT_high_pc);
+ if (attr)
+ high = DW_ADDR (attr);
+ else
+ return 0;
+
+ if (high < low)
+ return 0;
+
+ /* When using the GNU linker, .gnu.linkonce. sections are used to
+ eliminate duplicate copies of functions and vtables and such.
+ The linker will arbitrarily choose one and discard the others.
+ The AT_*_pc values for such functions refer to local labels in
+ these sections. If the section from that file was discarded, the
+ labels are not in the output, so the relocs get a value of 0.
+ If this is a discarded function, mark the pc bounds as invalid,
+ so that GDB will ignore it. */
+ if (low == 0 && (bfd_get_file_flags (objfile->obfd) & HAS_RELOC) == 0)
+ return 0;
+
+ *lowpc = low;
+ *highpc = high;
+ return 1;
+}
+
+/* Add an aggregate field to the field list. */
+
+static void
+dwarf2_add_field (fip, die, objfile)
+ struct field_info *fip;
+ struct die_info *die;
+ struct objfile *objfile;
+{
+ struct nextfield *new_field;
+ struct attribute *attr;
+ struct field *fp;
+ char *fieldname = "";
+
+ /* Allocate a new field list entry and link it in. */
+ new_field = (struct nextfield *) xmalloc (sizeof (struct nextfield));
+ make_cleanup (free, new_field);
+ memset (new_field, 0, sizeof (struct nextfield));
+ new_field->next = fip->fields;
+ fip->fields = new_field;
+ fip->nfields++;
+
+ /* Handle accessibility and virtuality of field.
+ The default accessibility for members is public, the default
+ accessibility for inheritance is private. */
+ if (die->tag != DW_TAG_inheritance)
+ new_field->accessibility = DW_ACCESS_public;
+ else
+ new_field->accessibility = DW_ACCESS_private;
+ new_field->virtuality = DW_VIRTUALITY_none;
+
+ attr = dwarf_attr (die, DW_AT_accessibility);
+ if (attr)
+ new_field->accessibility = DW_UNSND (attr);
+ if (new_field->accessibility != DW_ACCESS_public)
+ fip->non_public_fields = 1;
+ attr = dwarf_attr (die, DW_AT_virtuality);
+ if (attr)
+ new_field->virtuality = DW_UNSND (attr);
+
+ fp = &new_field->field;
+ if (die->tag == DW_TAG_member)
+ {
+ /* Get type of field. */
+ fp->type = die_type (die, objfile);
+
+ /* Get bit size of field (zero if none). */
+ attr = dwarf_attr (die, DW_AT_bit_size);
+ if (attr)
+ {
+ FIELD_BITSIZE (*fp) = DW_UNSND (attr);
+ }
+ else
+ {
+ FIELD_BITSIZE (*fp) = 0;
+ }
+
+ /* Get bit offset of field. */
+ attr = dwarf_attr (die, DW_AT_data_member_location);
+ if (attr)
+ {
+ FIELD_BITPOS (*fp) =
+ decode_locdesc (DW_BLOCK (attr), objfile) * bits_per_byte;
+ }
+ else
+ FIELD_BITPOS (*fp) = 0;
+ attr = dwarf_attr (die, DW_AT_bit_offset);
+ if (attr)
+ {
+ if (BITS_BIG_ENDIAN)
+ {
+ /* For big endian bits, the DW_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. */
+ FIELD_BITPOS (*fp) += DW_UNSND (attr);
+ }
+ else
+ {
+ /* For little endian bits, 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. */
+ int anonymous_size;
+ int bit_offset = DW_UNSND (attr);
+
+ attr = dwarf_attr (die, DW_AT_byte_size);
+ if (attr)
+ {
+ /* The size of the anonymous object containing
+ the bit field is explicit, so use the
+ indicated size (in bytes). */
+ anonymous_size = DW_UNSND (attr);
+ }
+ else
+ {
+ /* The size of the anonymous object containing
+ the bit field must be inferred from the type
+ attribute of the data member containing the
+ bit field. */
+ anonymous_size = TYPE_LENGTH (fp->type);
+ }
+ FIELD_BITPOS (*fp) += anonymous_size * bits_per_byte
+ - bit_offset - FIELD_BITSIZE (*fp);
+ }
+ }
+
+ /* Get name of field. */
+ attr = dwarf_attr (die, DW_AT_name);
+ if (attr && DW_STRING (attr))
+ fieldname = DW_STRING (attr);
+ fp->name = obsavestring (fieldname, strlen (fieldname),
+ &objfile->type_obstack);
+
+ /* Change accessibility for artificial fields (e.g. virtual table
+ pointer or virtual base class pointer) to private. */
+ if (dwarf_attr (die, DW_AT_artificial))
+ {
+ new_field->accessibility = DW_ACCESS_private;
+ fip->non_public_fields = 1;
+ }
+ }
+ else if (die->tag == DW_TAG_variable)
+ {
+ char *physname;
+ char *cp;
+
+ /* C++ static member.
+ Get physical name, extract field name from physical name. */
+ physname = dwarf2_linkage_name (die);
+ if (physname == NULL)
+ return;
+
+ cp = physname;
+ while (*cp && !is_cplus_marker (*cp))
+ cp++;
+ if (*cp)
+ fieldname = cp + 1;
+ if (*fieldname == '\0')
+ {
+ complain (&dwarf2_bad_static_member_name, physname);
+ }
+
+ SET_FIELD_PHYSNAME (*fp, obsavestring (physname, strlen (physname),
+ &objfile->type_obstack));
+ FIELD_TYPE (*fp) = die_type (die, objfile);
+ FIELD_NAME (*fp) = obsavestring (fieldname, strlen (fieldname),
+ &objfile->type_obstack);
+ }
+ else if (die->tag == DW_TAG_inheritance)
+ {
+ /* C++ base class field. */
+ attr = dwarf_attr (die, DW_AT_data_member_location);
+ if (attr)
+ FIELD_BITPOS (*fp) = decode_locdesc (DW_BLOCK (attr), objfile) * bits_per_byte;
+ FIELD_BITSIZE (*fp) = 0;
+ FIELD_TYPE (*fp) = die_type (die, objfile);
+ FIELD_NAME (*fp) = type_name_no_tag (fp->type);
+ fip->nbaseclasses++;
+ }
+}
+
+/* Create the vector of fields, and attach it to the type. */
+
+static void
+dwarf2_attach_fields_to_type (fip, type, objfile)
+ struct field_info *fip;
+ struct type *type;
+ struct objfile *objfile;
+{
+ int nfields = fip->nfields;
+
+ /* Record the field count, allocate space for the array of fields,
+ and create blank accessibility 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 (fip->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);
+
+ TYPE_FIELD_IGNORE_BITS (type) =
+ (B_TYPE *) TYPE_ALLOC (type, B_BYTES (nfields));
+ B_CLRALL (TYPE_FIELD_IGNORE_BITS (type), nfields);
+ }
+
+ /* If the type has baseclasses, allocate and clear a bit vector for
+ TYPE_FIELD_VIRTUAL_BITS. */
+ if (fip->nbaseclasses)
+ {
+ int num_bytes = B_BYTES (fip->nbaseclasses);
+ char *pointer;
+
+ ALLOCATE_CPLUS_STRUCT_TYPE (type);
+ pointer = (char *) TYPE_ALLOC (type, num_bytes);
+ TYPE_FIELD_VIRTUAL_BITS (type) = (B_TYPE *) pointer;
+ B_CLRALL (TYPE_FIELD_VIRTUAL_BITS (type), fip->nbaseclasses);
+ TYPE_N_BASECLASSES (type) = fip->nbaseclasses;
+ }
+
+ /* 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->fields->field;
+ switch (fip->fields->accessibility)
+ {
+ case DW_ACCESS_private:
+ SET_TYPE_FIELD_PRIVATE (type, nfields);
+ break;
+
+ case DW_ACCESS_protected:
+ SET_TYPE_FIELD_PROTECTED (type, nfields);
+ break;
+
+ case DW_ACCESS_public:
+ break;
+
+ default:
+ /* Unknown accessibility. Complain and treat it as public. */
+ {
+ complain (&dwarf2_unsupported_accessibility,
+ fip->fields->accessibility);
+ }
+ break;
+ }
+ if (nfields < fip->nbaseclasses)
+ {
+ switch (fip->fields->virtuality)
+ {
+ case DW_VIRTUALITY_virtual:
+ case DW_VIRTUALITY_pure_virtual:
+ SET_TYPE_FIELD_VIRTUAL (type, nfields);
+ break;
+ }
+ }
+ fip->fields = fip->fields->next;
+ }
+}
+
+/* Skip to the end of a member function name in a mangled name. */
+
+static char *
+skip_member_fn_name (physname)
+ char *physname;
+{
+ char *endname = physname;
+
+ /* Skip over leading underscores. */
+ while (*endname == '_')
+ endname++;
+
+ /* Find two succesive underscores. */
+ do
+ endname = strchr (endname, '_');
+ while (endname != NULL && *++endname != '_');
+
+ if (endname == NULL)
+ {
+ complain (&dwarf2_bad_member_name_complaint, physname);
+ endname = physname;
+ }
+ else
+ {
+ /* Take care of trailing underscores. */
+ if (endname[1] != '_')
+ endname--;
+ }
+ return endname;
+}
+
+/* Add a member function to the proper fieldlist. */
+
+static void
+dwarf2_add_member_fn (fip, die, type, objfile)
+ struct field_info *fip;
+ struct die_info *die;
+ struct type *type;
+ struct objfile *objfile;
+{
+ struct attribute *attr;
+ struct fnfieldlist *flp;
+ int i;
+ struct fn_field *fnp;
+ char *fieldname;
+ char *physname;
+ struct nextfnfield *new_fnfield;
+
+ /* Extract member function name from mangled name. */
+ physname = dwarf2_linkage_name (die);
+ if (physname == NULL)
+ return;
+ if ((physname[0] == '_' && physname[1] == '_'
+ && strchr ("0123456789Qt", physname[2]))
+ || DESTRUCTOR_PREFIX_P (physname))
+ {
+ /* Constructor and destructor field names are set to the name
+ of the class, but without template parameter lists.
+ The name might be missing for anonymous aggregates. */
+ if (TYPE_TAG_NAME (type))
+ {
+ char *p = strchr (TYPE_TAG_NAME (type), '<');
+
+ if (p == NULL)
+ fieldname = TYPE_TAG_NAME (type);
+ else
+ fieldname = obsavestring (TYPE_TAG_NAME (type),
+ p - TYPE_TAG_NAME (type),
+ &objfile->type_obstack);
+ }
+ else
+ {
+ char *anon_name = "";
+ fieldname = obsavestring (anon_name, strlen (anon_name),
+ &objfile->type_obstack);
+ }
+ }
+ else
+ {
+ char *endname = skip_member_fn_name (physname);
+
+ /* Ignore member function if we were unable not extract the member
+ function name. */
+ if (endname == physname)
+ return;
+ fieldname = obsavestring (physname, endname - physname,
+ &objfile->type_obstack);
+ }
+
+ /* Look up member function name in fieldlist. */
+ for (i = 0; i < fip->nfnfields; i++)
+ {
+ if (STREQ (fip->fnfieldlists[i].name, fieldname))
+ break;
+ }
+
+ /* Create new list element if necessary. */
+ if (i < fip->nfnfields)
+ flp = &fip->fnfieldlists[i];
+ else
+ {
+ if ((fip->nfnfields % DW_FIELD_ALLOC_CHUNK) == 0)
+ {
+ fip->fnfieldlists = (struct fnfieldlist *)
+ xrealloc (fip->fnfieldlists,
+ (fip->nfnfields + DW_FIELD_ALLOC_CHUNK)
+ * sizeof (struct fnfieldlist));
+ if (fip->nfnfields == 0)
+ make_cleanup ((make_cleanup_func) free_current_contents,
+ &fip->fnfieldlists);
+ }
+ flp = &fip->fnfieldlists[fip->nfnfields];
+ flp->name = fieldname;
+ flp->length = 0;
+ flp->head = NULL;
+ fip->nfnfields++;
+ }
+
+ /* Create a new member function field and chain it to the field list
+ entry. */
+ new_fnfield = (struct nextfnfield *) xmalloc (sizeof (struct nextfnfield));
+ make_cleanup (free, new_fnfield);
+ memset (new_fnfield, 0, sizeof (struct nextfnfield));
+ new_fnfield->next = flp->head;
+ flp->head = new_fnfield;
+ flp->length++;
+
+ /* Fill in the member function field info. */
+ fnp = &new_fnfield->fnfield;
+ fnp->physname = obsavestring (physname, strlen (physname),
+ &objfile->type_obstack);
+ fnp->type = alloc_type (objfile);
+ if (die->type && TYPE_CODE (die->type) == TYPE_CODE_FUNC)
+ {
+ struct type *return_type = TYPE_TARGET_TYPE (die->type);
+ struct type **arg_types;
+ int nparams = TYPE_NFIELDS (die->type);
+ int iparams;
+
+ /* Copy argument types from the subroutine type. */
+ arg_types = (struct type **)
+ TYPE_ALLOC (fnp->type, (nparams + 1) * sizeof (struct type *));
+ for (iparams = 0; iparams < nparams; iparams++)
+ arg_types[iparams] = TYPE_FIELD_TYPE (die->type, iparams);
+
+ /* Set last entry in argument type vector. */
+ if (TYPE_FLAGS (die->type) & TYPE_FLAG_VARARGS)
+ arg_types[nparams] = NULL;
+ else
+ arg_types[nparams] = dwarf2_fundamental_type (objfile, FT_VOID);
+
+ smash_to_method_type (fnp->type, type, return_type, arg_types);
+
+ /* Handle static member functions.
+ Dwarf2 has no clean way to discern C++ static and non-static
+ member functions. G++ helps GDB by marking the first
+ parameter for non-static member functions (which is the
+ this pointer) as artificial. We obtain this information
+ from read_subroutine_type via TYPE_FIELD_ARTIFICIAL. */
+ if (nparams == 0 || TYPE_FIELD_ARTIFICIAL (die->type, 0) == 0)
+ fnp->voffset = VOFFSET_STATIC;
+ }
+ else
+ complain (&dwarf2_missing_member_fn_type_complaint, physname);
+
+ /* Get fcontext from DW_AT_containing_type if present. */
+ if (dwarf_attr (die, DW_AT_containing_type) != NULL)
+ fnp->fcontext = die_containing_type (die, objfile);
+
+ /* dwarf2 doesn't have stubbed physical names, so the setting of is_const
+ and is_volatile is irrelevant, as it is needed by gdb_mangle_name only. */
+
+ /* Get accessibility. */
+ attr = dwarf_attr (die, DW_AT_accessibility);
+ if (attr)
+ {
+ switch (DW_UNSND (attr))
+ {
+ case DW_ACCESS_private:
+ fnp->is_private = 1;
+ break;
+ case DW_ACCESS_protected:
+ fnp->is_protected = 1;
+ break;
+ }
+ }
+
+ /* Get index in virtual function table if it is a virtual member function. */
+ attr = dwarf_attr (die, DW_AT_vtable_elem_location);
+ if (attr)
+ fnp->voffset = decode_locdesc (DW_BLOCK (attr), objfile) + 2;
+}
+
+/* Create the vector of member function fields, and attach it to the type. */
+
+static void
+dwarf2_attach_fn_fields_to_type (fip, type, objfile)
+ struct field_info *fip;
+ struct type *type;
+ struct objfile *objfile;
+{
+ struct fnfieldlist *flp;
+ int total_length = 0;
+ int i;
+
+ ALLOCATE_CPLUS_STRUCT_TYPE (type);
+ TYPE_FN_FIELDLISTS (type) = (struct fn_fieldlist *)
+ TYPE_ALLOC (type, sizeof (struct fn_fieldlist) * fip->nfnfields);
+
+ for (i = 0, flp = fip->fnfieldlists; i < fip->nfnfields; i++, flp++)
+ {
+ struct nextfnfield *nfp = flp->head;
+ struct fn_fieldlist *fn_flp = &TYPE_FN_FIELDLIST (type, i);
+ int k;
+
+ TYPE_FN_FIELDLIST_NAME (type, i) = flp->name;
+ TYPE_FN_FIELDLIST_LENGTH (type, i) = flp->length;
+ fn_flp->fn_fields = (struct fn_field *)
+ TYPE_ALLOC (type, sizeof (struct fn_field) * flp->length);
+ for (k = flp->length; (k--, nfp); nfp = nfp->next)
+ fn_flp->fn_fields[k] = nfp->fnfield;
+
+ total_length += flp->length;
+ }
+
+ TYPE_NFN_FIELDS (type) = fip->nfnfields;
+ TYPE_NFN_FIELDS_TOTAL (type) = total_length;
+}
+
+/* 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.
+
+ NOTE: 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 (die, objfile)
+ struct die_info *die;
+ struct objfile *objfile;
+{
+ struct type *type;
+ struct attribute *attr;
+
+ type = alloc_type (objfile);
+
+ INIT_CPLUS_SPECIFIC (type);
+ attr = dwarf_attr (die, DW_AT_name);
+ if (attr && DW_STRING (attr))
+ {
+ TYPE_TAG_NAME (type) = obsavestring (DW_STRING (attr),
+ strlen (DW_STRING (attr)),
+ &objfile->type_obstack);
+ }
+
+ if (die->tag == DW_TAG_structure_type)
+ {
+ TYPE_CODE (type) = TYPE_CODE_STRUCT;
+ }
+ else if (die->tag == DW_TAG_union_type)
+ {
+ TYPE_CODE (type) = TYPE_CODE_UNION;
+ }
+ else
+ {
+ /* FIXME: TYPE_CODE_CLASS is currently defined to TYPE_CODE_STRUCT
+ in gdbtypes.h. */
+ TYPE_CODE (type) = TYPE_CODE_CLASS;
+ }
+
+ attr = dwarf_attr (die, DW_AT_byte_size);
+ if (attr)
+ {
+ TYPE_LENGTH (type) = DW_UNSND (attr);
+ }
+ else
+ {
+ TYPE_LENGTH (type) = 0;
+ }
+
+ /* We need to add the type field to the die immediately so we don't
+ infinitely recurse when dealing with pointers to the structure
+ type within the structure itself. */
+ die->type = type;
+
+ if (die->has_children)
+ {
+ struct field_info fi;
+ struct die_info *child_die;
+ struct cleanup *back_to = make_cleanup (null_cleanup, NULL);
+
+ memset (&fi, 0, sizeof (struct field_info));
+
+ child_die = die->next;
+
+ while (child_die && child_die->tag)
+ {
+ if (child_die->tag == DW_TAG_member)
+ {
+ dwarf2_add_field (&fi, child_die, objfile);
+ }
+ else if (child_die->tag == DW_TAG_variable)
+ {
+ /* C++ static member. */
+ dwarf2_add_field (&fi, child_die, objfile);
+ }
+ else if (child_die->tag == DW_TAG_subprogram)
+ {
+ /* C++ member function. */
+ process_die (child_die, objfile);
+ dwarf2_add_member_fn (&fi, child_die, type, objfile);
+ }
+ else if (child_die->tag == DW_TAG_inheritance)
+ {
+ /* C++ base class field. */
+ dwarf2_add_field (&fi, child_die, objfile);
+ }
+ else
+ {
+ process_die (child_die, objfile);
+ }
+ child_die = sibling_die (child_die);
+ }
+
+ /* Attach fields and member functions to the type. */
+ if (fi.nfields)
+ dwarf2_attach_fields_to_type (&fi, type, objfile);
+ if (fi.nfnfields)
+ {
+ dwarf2_attach_fn_fields_to_type (&fi, type, objfile);
+
+ /* Get the type which refers to the base class (possibly this
+ class itself) which contains the vtable pointer for the current
+ class from the DW_AT_containing_type attribute. */
+
+ if (dwarf_attr (die, DW_AT_containing_type) != NULL)
+ {
+ struct type *t = die_containing_type (die, objfile);
+
+ TYPE_VPTR_BASETYPE (type) = t;
+ if (type == t)
+ {
+ static const char vptr_name[] = { '_','v','p','t','r','\0' };
+ int i;
+
+ /* Our own class provides vtbl ptr. */
+ for (i = TYPE_NFIELDS (t) - 1;
+ i >= TYPE_N_BASECLASSES (t);
+ --i)
+ {
+ char *fieldname = TYPE_FIELD_NAME (t, i);
+
+ if (STREQN (fieldname, vptr_name, strlen (vptr_name) - 1)
+ && is_cplus_marker (fieldname[strlen (vptr_name)]))
+ {
+ TYPE_VPTR_FIELDNO (type) = i;
+ break;
+ }
+ }
+
+ /* Complain if virtual function table field not found. */
+ if (i < TYPE_N_BASECLASSES (t))
+ complain (&dwarf2_vtbl_not_found_complaint,
+ TYPE_TAG_NAME (type) ? TYPE_TAG_NAME (type) : "");
+ }
+ else
+ {
+ TYPE_VPTR_FIELDNO (type) = TYPE_VPTR_FIELDNO (t);
+ }
+ }
+ }
+
+ new_symbol (die, type, objfile);
+
+ do_cleanups (back_to);
+ }
+ else
+ {
+ /* No children, must be stub. */
+ TYPE_FLAGS (type) |= TYPE_FLAG_STUB;
+ }
+
+ die->type = type;
+}
+
+/* Given a pointer to a die which begins an enumeration, process all
+ the dies that define the members of the enumeration.
+
+ This will be much nicer in draft 6 of the DWARF spec when our
+ members will be dies instead squished into the DW_AT_element_list
+ attribute.
+
+ NOTE: We reverse the order of the element list. */
+
+static void
+read_enumeration (die, objfile)
+ struct die_info *die;
+ struct objfile *objfile;
+{
+ struct die_info *child_die;
+ struct type *type;
+ struct field *fields;
+ struct attribute *attr;
+ struct symbol *sym;
+ int num_fields;
+ int unsigned_enum = 1;
+
+ type = alloc_type (objfile);
+
+ TYPE_CODE (type) = TYPE_CODE_ENUM;
+ attr = dwarf_attr (die, DW_AT_name);
+ if (attr && DW_STRING (attr))
+ {
+ TYPE_TAG_NAME (type) = obsavestring (DW_STRING (attr),
+ strlen (DW_STRING (attr)),
+ &objfile->type_obstack);
+ }
+
+ attr = dwarf_attr (die, DW_AT_byte_size);
+ if (attr)
+ {
+ TYPE_LENGTH (type) = DW_UNSND (attr);
+ }
+ else
+ {
+ TYPE_LENGTH (type) = 0;
+ }
+
+ num_fields = 0;
+ fields = NULL;
+ if (die->has_children)
+ {
+ child_die = die->next;
+ while (child_die && child_die->tag)
+ {
+ if (child_die->tag != DW_TAG_enumerator)
+ {
+ process_die (child_die, objfile);
+ }
+ else
+ {
+ attr = dwarf_attr (child_die, DW_AT_name);
+ if (attr)
+ {
+ sym = new_symbol (child_die, type, objfile);
+ if (SYMBOL_VALUE (sym) < 0)
+ unsigned_enum = 0;
+
+ if ((num_fields % DW_FIELD_ALLOC_CHUNK) == 0)
+ {
+ fields = (struct field *)
+ xrealloc (fields,
+ (num_fields + DW_FIELD_ALLOC_CHUNK)
+ * sizeof (struct field));
+ }
+
+ FIELD_NAME (fields[num_fields]) = SYMBOL_NAME (sym);
+ FIELD_TYPE (fields[num_fields]) = NULL;
+ FIELD_BITPOS (fields[num_fields]) = SYMBOL_VALUE (sym);
+ FIELD_BITSIZE (fields[num_fields]) = 0;
+
+ num_fields++;
+ }
+ }
+
+ child_die = sibling_die (child_die);
+ }
+
+ if (num_fields)
+ {
+ TYPE_NFIELDS (type) = num_fields;
+ TYPE_FIELDS (type) = (struct field *)
+ TYPE_ALLOC (type, sizeof (struct field) * num_fields);
+ memcpy (TYPE_FIELDS (type), fields,
+ sizeof (struct field) * num_fields);
+ free (fields);
+ }
+ if (unsigned_enum)
+ TYPE_FLAGS (type) |= TYPE_FLAG_UNSIGNED;
+ }
+ die->type = type;
+ new_symbol (die, type, objfile);
+}
+
+/* Extract all information from a DW_TAG_array_type DIE and put it in
+ the DIE's type field. For now, this only handles one dimensional
+ arrays. */
+
+static void
+read_array_type (die, objfile)
+ struct die_info *die;
+ struct objfile *objfile;
+{
+ struct die_info *child_die;
+ struct type *type = NULL;
+ struct type *element_type, *range_type, *index_type;
+ struct type **range_types = NULL;
+ struct attribute *attr;
+ int ndim = 0;
+ struct cleanup *back_to;
+
+ /* Return if we've already decoded this type. */
+ if (die->type)
+ {
+ return;
+ }
+
+ element_type = die_type (die, objfile);
+
+ /* Irix 6.2 native cc creates array types without children for
+ arrays with unspecified length. */
+ if (die->has_children == 0)
+ {
+ index_type = dwarf2_fundamental_type (objfile, FT_INTEGER);
+ range_type = create_range_type (NULL, index_type, 0, -1);
+ die->type = create_array_type (NULL, element_type, range_type);
+ return;
+ }
+
+ back_to = make_cleanup (null_cleanup, NULL);
+ child_die = die->next;
+ while (child_die && child_die->tag)
+ {
+ if (child_die->tag == DW_TAG_subrange_type)
+ {
+ unsigned int low, high;
+
+ /* Default bounds to an array with unspecified length. */
+ low = 0;
+ high = -1;
+ if (cu_language == language_fortran)
+ {
+ /* FORTRAN implies a lower bound of 1, if not given. */
+ low = 1;
+ }
+
+ index_type = die_type (child_die, objfile);
+ attr = dwarf_attr (child_die, DW_AT_lower_bound);
+ if (attr)
+ {
+ if (attr->form == DW_FORM_sdata)
+ {
+ low = DW_SND (attr);
+ }
+ else if (attr->form == DW_FORM_udata
+ || attr->form == DW_FORM_data1
+ || attr->form == DW_FORM_data2
+ || attr->form == DW_FORM_data4)
+ {
+ low = DW_UNSND (attr);
+ }
+ else
+ {
+ complain (&dwarf2_non_const_array_bound_ignored,
+ dwarf_form_name (attr->form));
+#ifdef FORTRAN_HACK
+ die->type = lookup_pointer_type (element_type);
+ return;
+#else
+ low = 0;
+#endif
+ }
+ }
+ attr = dwarf_attr (child_die, DW_AT_upper_bound);
+ if (attr)
+ {
+ if (attr->form == DW_FORM_sdata)
+ {
+ high = DW_SND (attr);
+ }
+ else if (attr->form == DW_FORM_udata
+ || attr->form == DW_FORM_data1
+ || attr->form == DW_FORM_data2
+ || attr->form == DW_FORM_data4)
+ {
+ high = DW_UNSND (attr);
+ }
+ else if (attr->form == DW_FORM_block1)
+ {
+ /* GCC encodes arrays with unspecified or dynamic length
+ with a DW_FORM_block1 attribute.
+ FIXME: GDB does not yet know how to handle dynamic
+ arrays properly, treat them as arrays with unspecified
+ length for now. */
+ high = -1;
+ }
+ else
+ {
+ complain (&dwarf2_non_const_array_bound_ignored,
+ dwarf_form_name (attr->form));
+#ifdef FORTRAN_HACK
+ die->type = lookup_pointer_type (element_type);
+ return;
+#else
+ high = 1;
+#endif
+ }
+ }
+
+ /* Create a range type and save it for array type creation. */
+ if ((ndim % DW_FIELD_ALLOC_CHUNK) == 0)
+ {
+ range_types = (struct type **)
+ xrealloc (range_types, (ndim + DW_FIELD_ALLOC_CHUNK)
+ * sizeof (struct type *));
+ if (ndim == 0)
+ make_cleanup ((make_cleanup_func) free_current_contents,
+ &range_types);
+ }
+ range_types[ndim++] = create_range_type (NULL, index_type, low, high);
+ }
+ child_die = sibling_die (child_die);
+ }
+
+ /* Dwarf2 dimensions are output from left to right, create the
+ necessary array types in backwards order. */
+ type = element_type;
+ while (ndim-- > 0)
+ type = create_array_type (NULL, type, range_types[ndim]);
+
+ do_cleanups (back_to);
+
+ /* Install the type in the die. */
+ die->type = type;
+}
+
+/* First cut: install each common block member as a global variable. */
+
+static void
+read_common_block (die, objfile)
+ struct die_info *die;
+ struct objfile *objfile;
+{
+ struct die_info *child_die;
+ struct attribute *attr;
+ struct symbol *sym;
+ CORE_ADDR base = (CORE_ADDR) 0;
+
+ attr = dwarf_attr (die, DW_AT_location);
+ if (attr)
+ {
+ base = decode_locdesc (DW_BLOCK (attr), objfile);
+ }
+ if (die->has_children)
+ {
+ child_die = die->next;
+ while (child_die && child_die->tag)
+ {
+ sym = new_symbol (child_die, NULL, objfile);
+ attr = dwarf_attr (child_die, DW_AT_data_member_location);
+ if (attr)
+ {
+ SYMBOL_VALUE_ADDRESS (sym) =
+ base + decode_locdesc (DW_BLOCK (attr), objfile);
+ add_symbol_to_list (sym, &global_symbols);
+ }
+ child_die = sibling_die (child_die);
+ }
+ }
+}
+
+/* Extract all information from a DW_TAG_pointer_type DIE and add to
+ the user defined type vector. */
+
+static void
+read_tag_pointer_type (die, objfile)
+ struct die_info *die;
+ struct objfile *objfile;
+{
+ struct type *type;
+ struct attribute *attr;
+
+ if (die->type)
+ {
+ return;
+ }
+
+ type = lookup_pointer_type (die_type (die, objfile));
+ attr = dwarf_attr (die, DW_AT_byte_size);
+ if (attr)
+ {
+ TYPE_LENGTH (type) = DW_UNSND (attr);
+ }
+ else
+ {
+ TYPE_LENGTH (type) = address_size;
+ }
+ die->type = type;
+}
+
+/* Extract all information from a DW_TAG_ptr_to_member_type DIE and add to
+ the user defined type vector. */
+
+static void
+read_tag_ptr_to_member_type (die, objfile)
+ struct die_info *die;
+ struct objfile *objfile;
+{
+ struct type *type;
+ struct type *to_type;
+ struct type *domain;
+
+ if (die->type)
+ {
+ return;
+ }
+
+ type = alloc_type (objfile);
+ to_type = die_type (die, objfile);
+ domain = die_containing_type (die, objfile);
+ smash_to_member_type (type, domain, to_type);
+
+ die->type = type;
+}
+
+/* Extract all information from a DW_TAG_reference_type DIE and add to
+ the user defined type vector. */
+
+static void
+read_tag_reference_type (die, objfile)
+ struct die_info *die;
+ struct objfile *objfile;
+{
+ struct type *type;
+ struct attribute *attr;
+
+ if (die->type)
+ {
+ return;
+ }
+
+ type = lookup_reference_type (die_type (die, objfile));
+ attr = dwarf_attr (die, DW_AT_byte_size);
+ if (attr)
+ {
+ TYPE_LENGTH (type) = DW_UNSND (attr);
+ }
+ else
+ {
+ TYPE_LENGTH (type) = address_size;
+ }
+ die->type = type;
+}
+
+static void
+read_tag_const_type (die, objfile)
+ struct die_info *die;
+ struct objfile *objfile;
+{
+ if (die->type)
+ {
+ return;
+ }
+
+ complain (&dwarf2_const_ignored);
+ die->type = die_type (die, objfile);
+}
+
+static void
+read_tag_volatile_type (die, objfile)
+ struct die_info *die;
+ struct objfile *objfile;
+{
+ if (die->type)
+ {
+ return;
+ }
+
+ complain (&dwarf2_volatile_ignored);
+ die->type = die_type (die, objfile);
+}
+
+/* Extract all information from a DW_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 (die, objfile)
+ struct die_info *die;
+ struct objfile *objfile;
+{
+ struct type *type, *range_type, *index_type, *char_type;
+ struct attribute *attr;
+ unsigned int length;
+
+ if (die->type)
+ {
+ return;
+ }
+
+ attr = dwarf_attr (die, DW_AT_string_length);
+ if (attr)
+ {
+ length = DW_UNSND (attr);
+ }
+ else
+ {
+ length = 1;
+ }
+ index_type = dwarf2_fundamental_type (objfile, FT_INTEGER);
+ range_type = create_range_type (NULL, index_type, 1, length);
+ char_type = dwarf2_fundamental_type (objfile, FT_CHAR);
+ type = create_string_type (char_type, range_type);
+ die->type = type;
+}
+
+/* Handle DIES due to C code like:
+
+ struct foo
+ {
+ int (*funcp)(int a, long l);
+ int b;
+ };
+
+ ('funcp' generates a DW_TAG_subroutine_type DIE)
+*/
+
+static void
+read_subroutine_type (die, objfile)
+ struct die_info *die;
+ struct objfile *objfile;
+{
+ struct type *type; /* Type that this function returns */
+ struct type *ftype; /* Function that returns above type */
+ struct attribute *attr;
+
+ /* Decode the type that this subroutine returns */
+ if (die->type)
+ {
+ return;
+ }
+ type = die_type (die, objfile);
+ ftype = lookup_function_type (type);
+
+ /* All functions in C++ have prototypes. */
+ attr = dwarf_attr (die, DW_AT_prototyped);
+ if ((attr && (DW_UNSND (attr) != 0))
+ || cu_language == language_cplus)
+ TYPE_FLAGS (ftype) |= TYPE_FLAG_PROTOTYPED;
+
+ if (die->has_children)
+ {
+ struct die_info *child_die;
+ int nparams = 0;
+ int iparams = 0;
+
+ /* Count the number of parameters.
+ FIXME: GDB currently ignores vararg functions, but knows about
+ vararg member functions. */
+ child_die = die->next;
+ while (child_die && child_die->tag)
+ {
+ if (child_die->tag == DW_TAG_formal_parameter)
+ nparams++;
+ else if (child_die->tag == DW_TAG_unspecified_parameters)
+ TYPE_FLAGS (ftype) |= TYPE_FLAG_VARARGS;
+ child_die = sibling_die (child_die);
+ }
+
+ /* Allocate storage for parameters and fill them in. */
+ TYPE_NFIELDS (ftype) = nparams;
+ TYPE_FIELDS (ftype) = (struct field *)
+ TYPE_ALLOC (ftype, nparams * sizeof (struct field));
+
+ child_die = die->next;
+ while (child_die && child_die->tag)
+ {
+ if (child_die->tag == DW_TAG_formal_parameter)
+ {
+ /* Dwarf2 has no clean way to discern C++ static and non-static
+ member functions. G++ helps GDB by marking the first
+ parameter for non-static member functions (which is the
+ this pointer) as artificial. We pass this information
+ to dwarf2_add_member_fn via TYPE_FIELD_ARTIFICIAL. */
+ attr = dwarf_attr (child_die, DW_AT_artificial);
+ if (attr)
+ TYPE_FIELD_ARTIFICIAL (ftype, iparams) = DW_UNSND (attr);
+ else
+ TYPE_FIELD_ARTIFICIAL (ftype, iparams) = 0;
+ TYPE_FIELD_TYPE (ftype, iparams) = die_type (child_die, objfile);
+ iparams++;
+ }
+ child_die = sibling_die (child_die);
+ }
+ }
+
+ die->type = ftype;
+}
+
+static void
+read_typedef (die, objfile)
+ struct die_info *die;
+ struct objfile *objfile;
+{
+ struct type *type;
+
+ if (!die->type)
+ {
+ struct attribute *attr;
+ struct type *xtype;
+
+ xtype = die_type (die, objfile);
+
+ type = alloc_type (objfile);
+ TYPE_CODE (type) = TYPE_CODE_TYPEDEF;
+ TYPE_FLAGS (type) |= TYPE_FLAG_TARGET_STUB;
+ TYPE_TARGET_TYPE (type) = xtype;
+ attr = dwarf_attr (die, DW_AT_name);
+ if (attr && DW_STRING (attr))
+ TYPE_NAME (type) = obsavestring (DW_STRING (attr),
+ strlen (DW_STRING (attr)),
+ &objfile->type_obstack);
+
+ die->type = type;
+ }
+}
+
+/* Find a representation of a given base type and install
+ it in the TYPE field of the die. */
+
+static void
+read_base_type (die, objfile)
+ struct die_info *die;
+ struct objfile *objfile;
+{
+ struct type *type;
+ struct attribute *attr;
+ int encoding = 0, size = 0;
+
+ /* If we've already decoded this die, this is a no-op. */
+ if (die->type)
+ {
+ return;
+ }
+
+ attr = dwarf_attr (die, DW_AT_encoding);
+ if (attr)
+ {
+ encoding = DW_UNSND (attr);
+ }
+ attr = dwarf_attr (die, DW_AT_byte_size);
+ if (attr)
+ {
+ size = DW_UNSND (attr);
+ }
+ attr = dwarf_attr (die, DW_AT_name);
+ if (attr && DW_STRING (attr))
+ {
+ enum type_code code = TYPE_CODE_INT;
+ int is_unsigned = 0;
+
+ switch (encoding)
+ {
+ case DW_ATE_address:
+ /* Turn DW_ATE_address into a void * pointer. */
+ code = TYPE_CODE_PTR;
+ is_unsigned = 1;
+ break;
+ case DW_ATE_boolean:
+ code = TYPE_CODE_BOOL;
+ is_unsigned = 1;
+ break;
+ case DW_ATE_complex_float:
+ code = TYPE_CODE_COMPLEX;
+ break;
+ case DW_ATE_float:
+ code = TYPE_CODE_FLT;
+ break;
+ case DW_ATE_signed:
+ case DW_ATE_signed_char:
+ break;
+ case DW_ATE_unsigned:
+ case DW_ATE_unsigned_char:
+ is_unsigned = 1;
+ break;
+ default:
+ complain (&dwarf2_unsupported_at_encoding,
+ dwarf_type_encoding_name (encoding));
+ break;
+ }
+ type = init_type (code, size, is_unsigned, DW_STRING (attr), objfile);
+ if (encoding == DW_ATE_address)
+ TYPE_TARGET_TYPE (type) = dwarf2_fundamental_type (objfile, FT_VOID);
+ }
+ else
+ {
+ type = dwarf_base_type (encoding, size, objfile);
+ }
+ die->type = type;
+}
+
+/* Read a whole compilation unit into a linked list of dies. */
+
+struct die_info *
+read_comp_unit (info_ptr, abfd)
+ char *info_ptr;
+ bfd *abfd;
+{
+ struct die_info *first_die, *last_die, *die;
+ char *cur_ptr;
+ int nesting_level;
+
+ /* Reset die reference table, we are building a new one now. */
+ dwarf2_empty_die_ref_table ();
+
+ cur_ptr = info_ptr;
+ nesting_level = 0;
+ first_die = last_die = NULL;
+ do
+ {
+ cur_ptr = read_full_die (&die, abfd, cur_ptr);
+ if (die->has_children)
+ {
+ nesting_level++;
+ }
+ if (die->tag == 0)
+ {
+ nesting_level--;
+ }
+
+ die->next = NULL;
+
+ /* Enter die in reference hash table */
+ store_in_ref_table (die->offset, die);
+
+ if (!first_die)
+ {
+ first_die = last_die = die;
+ }
+ else
+ {
+ last_die->next = die;
+ last_die = die;
+ }
+ }
+ while (nesting_level > 0);
+ return first_die;
+}
+
+/* Free a linked list of dies. */
+
+static void
+free_die_list (dies)
+ struct die_info *dies;
+{
+ struct die_info *die, *next;
+
+ die = dies;
+ while (die)
+ {
+ next = die->next;
+ free (die->attrs);
+ free (die);
+ die = next;
+ }
+}
+
+/* Read the contents of the section at OFFSET and of size SIZE from the
+ object file specified by OBJFILE into the psymbol_obstack and return it. */
+
+static char *
+dwarf2_read_section (objfile, offset, size)
+ struct objfile *objfile;
+ file_ptr offset;
+ unsigned int size;
+{
+ bfd *abfd = objfile->obfd;
+ char *buf;
+
+ if (size == 0)
+ return NULL;
+
+ buf = (char *) obstack_alloc (&objfile->psymbol_obstack, size);
+ if ((bfd_seek (abfd, offset, SEEK_SET) != 0) ||
+ (bfd_read (buf, size, 1, abfd) != size))
+ {
+ buf = NULL;
+ error ("Dwarf Error: Can't read DWARF data from '%s'",
+ bfd_get_filename (abfd));
+ }
+ return buf;
+}
+
+/* In DWARF version 2, the description of the debugging information is
+ stored in a separate .debug_abbrev section. Before we read any
+ dies from a section we read in all abbreviations and install them
+ in a hash table. */
+
+static void
+dwarf2_read_abbrevs (abfd, offset)
+ bfd * abfd;
+ unsigned int offset;
+{
+ char *abbrev_ptr;
+ struct abbrev_info *cur_abbrev;
+ unsigned int abbrev_number, bytes_read, abbrev_name;
+ unsigned int abbrev_form, hash_number;
+
+ /* empty the table */
+ dwarf2_empty_abbrev_table (NULL);
+
+ abbrev_ptr = dwarf_abbrev_buffer + offset;
+ abbrev_number = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read);
+ abbrev_ptr += bytes_read;
+
+ /* loop until we reach an abbrev number of 0 */
+ while (abbrev_number)
+ {
+ cur_abbrev = dwarf_alloc_abbrev ();
+
+ /* read in abbrev header */
+ cur_abbrev->number = abbrev_number;
+ cur_abbrev->tag = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read);
+ abbrev_ptr += bytes_read;
+ cur_abbrev->has_children = read_1_byte (abfd, abbrev_ptr);
+ abbrev_ptr += 1;
+
+ /* now read in declarations */
+ abbrev_name = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read);
+ abbrev_ptr += bytes_read;
+ abbrev_form = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read);
+ abbrev_ptr += bytes_read;
+ while (abbrev_name)
+ {
+ if ((cur_abbrev->num_attrs % ATTR_ALLOC_CHUNK) == 0)
+ {
+ cur_abbrev->attrs = (struct attr_abbrev *)
+ xrealloc (cur_abbrev->attrs,
+ (cur_abbrev->num_attrs + ATTR_ALLOC_CHUNK)
+ * sizeof (struct attr_abbrev));
+ }
+ cur_abbrev->attrs[cur_abbrev->num_attrs].name = abbrev_name;
+ cur_abbrev->attrs[cur_abbrev->num_attrs++].form = abbrev_form;
+ abbrev_name = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read);
+ abbrev_ptr += bytes_read;
+ abbrev_form = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read);
+ abbrev_ptr += bytes_read;
+ }
+
+ hash_number = abbrev_number % ABBREV_HASH_SIZE;
+ cur_abbrev->next = dwarf2_abbrevs[hash_number];
+ dwarf2_abbrevs[hash_number] = cur_abbrev;
+
+ /* Get next abbreviation.
+ Under Irix6 the abbreviations for a compilation unit are not
+ always properly terminated with an abbrev number of 0.
+ Exit loop if we encounter an abbreviation which we have
+ already read (which means we are about to read the abbreviations
+ for the next compile unit) or if the end of the abbreviation
+ table is reached. */
+ if ((unsigned int) (abbrev_ptr - dwarf_abbrev_buffer)
+ >= dwarf_abbrev_size)
+ break;
+ abbrev_number = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read);
+ abbrev_ptr += bytes_read;
+ if (dwarf2_lookup_abbrev (abbrev_number) != NULL)
+ break;
+ }
+}
+
+/* Empty the abbrev table for a new compilation unit. */
+
+/* ARGSUSED */
+static void
+dwarf2_empty_abbrev_table (ignore)
+ PTR ignore;
+{
+ int i;
+ struct abbrev_info *abbrev, *next;
+
+ for (i = 0; i < ABBREV_HASH_SIZE; ++i)
+ {
+ next = NULL;
+ abbrev = dwarf2_abbrevs[i];
+ while (abbrev)
+ {
+ next = abbrev->next;
+ free (abbrev->attrs);
+ free (abbrev);
+ abbrev = next;
+ }
+ dwarf2_abbrevs[i] = NULL;
+ }
+}
+
+/* Lookup an abbrev_info structure in the abbrev hash table. */
+
+static struct abbrev_info *
+dwarf2_lookup_abbrev (number)
+ unsigned int number;
+{
+ unsigned int hash_number;
+ struct abbrev_info *abbrev;
+
+ hash_number = number % ABBREV_HASH_SIZE;
+ abbrev = dwarf2_abbrevs[hash_number];
+
+ while (abbrev)
+ {
+ if (abbrev->number == number)
+ return abbrev;
+ else
+ abbrev = abbrev->next;
+ }
+ return NULL;
+}
+
+/* Read a minimal amount of information into the minimal die structure. */
+
+static char *
+read_partial_die (part_die, abfd, info_ptr, has_pc_info)
+ struct partial_die_info *part_die;
+ bfd * abfd;
+ char *info_ptr;
+ int *has_pc_info;
+{
+ unsigned int abbrev_number, bytes_read, i;
+ struct abbrev_info *abbrev;
+ struct attribute attr;
+ struct attribute spec_attr;
+ int found_spec_attr = 0;
+ int has_low_pc_attr = 0;
+ int has_high_pc_attr = 0;
+
+ *part_die = zeroed_partial_die;
+ *has_pc_info = 0;
+ abbrev_number = read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
+ info_ptr += bytes_read;
+ if (!abbrev_number)
+ return info_ptr;
+
+ abbrev = dwarf2_lookup_abbrev (abbrev_number);
+ if (!abbrev)
+ {
+ error ("Dwarf Error: Could not find abbrev number %d.", abbrev_number);
+ }
+ part_die->offset = info_ptr - dwarf_info_buffer;
+ part_die->tag = abbrev->tag;
+ part_die->has_children = abbrev->has_children;
+ part_die->abbrev = abbrev_number;
+
+ for (i = 0; i < abbrev->num_attrs; ++i)
+ {
+ info_ptr = read_attribute (&attr, &abbrev->attrs[i], abfd, info_ptr);
+
+ /* Store the data if it is of an attribute we want to keep in a
+ partial symbol table. */
+ switch (attr.name)
+ {
+ case DW_AT_name:
+
+ /* Prefer DW_AT_MIPS_linkage_name over DW_AT_name. */
+ if (part_die->name == NULL)
+ part_die->name = DW_STRING (&attr);
+ break;
+ case DW_AT_MIPS_linkage_name:
+ part_die->name = DW_STRING (&attr);
+ break;
+ case DW_AT_low_pc:
+ has_low_pc_attr = 1;
+ part_die->lowpc = DW_ADDR (&attr);
+ break;
+ case DW_AT_high_pc:
+ has_high_pc_attr = 1;
+ part_die->highpc = DW_ADDR (&attr);
+ break;
+ case DW_AT_location:
+ part_die->locdesc = DW_BLOCK (&attr);
+ break;
+ case DW_AT_language:
+ part_die->language = DW_UNSND (&attr);
+ break;
+ case DW_AT_external:
+ part_die->is_external = DW_UNSND (&attr);
+ break;
+ case DW_AT_declaration:
+ part_die->is_declaration = DW_UNSND (&attr);
+ break;
+ case DW_AT_type:
+ part_die->has_type = 1;
+ break;
+ case DW_AT_abstract_origin:
+ case DW_AT_specification:
+ found_spec_attr = 1;
+ spec_attr = attr;
+ break;
+ case DW_AT_sibling:
+ /* Ignore absolute siblings, they might point outside of
+ the current compile unit. */
+ if (attr.form == DW_FORM_ref_addr)
+ complain(&dwarf2_absolute_sibling_complaint);
+ else
+ part_die->sibling =
+ dwarf_info_buffer + dwarf2_get_ref_die_offset (&attr);
+ break;
+ default:
+ break;
+ }
+ }
+
+ /* If we found a reference attribute and the die has no name, try
+ to find a name in the referred to die. */
+
+ if (found_spec_attr && part_die->name == NULL)
+ {
+ struct partial_die_info spec_die;
+ char *spec_ptr;
+ int dummy;
+
+ spec_ptr = dwarf_info_buffer + dwarf2_get_ref_die_offset (&spec_attr);
+ read_partial_die (&spec_die, abfd, spec_ptr, &dummy);
+ if (spec_die.name)
+ {
+ part_die->name = spec_die.name;
+
+ /* Copy DW_AT_external attribute if it is set. */
+ if (spec_die.is_external)
+ part_die->is_external = spec_die.is_external;
+ }
+ }
+
+ /* When using the GNU linker, .gnu.linkonce. sections are used to
+ eliminate duplicate copies of functions and vtables and such.
+ The linker will arbitrarily choose one and discard the others.
+ The AT_*_pc values for such functions refer to local labels in
+ these sections. If the section from that file was discarded, the
+ labels are not in the output, so the relocs get a value of 0.
+ If this is a discarded function, mark the pc bounds as invalid,
+ so that GDB will ignore it. */
+ if (has_low_pc_attr && has_high_pc_attr
+ && part_die->lowpc < part_die->highpc
+ && (part_die->lowpc != 0
+ || (bfd_get_file_flags (abfd) & HAS_RELOC)))
+ *has_pc_info = 1;
+ return info_ptr;
+}
+
+/* Read the die from the .debug_info section buffer. And set diep to
+ point to a newly allocated die with its information. */
+
+static char *
+read_full_die (diep, abfd, info_ptr)
+ struct die_info **diep;
+ bfd *abfd;
+ char *info_ptr;
+{
+ unsigned int abbrev_number, bytes_read, i, offset;
+ struct abbrev_info *abbrev;
+ struct die_info *die;
+
+ offset = info_ptr - dwarf_info_buffer;
+ abbrev_number = read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
+ info_ptr += bytes_read;
+ if (!abbrev_number)
+ {
+ die = dwarf_alloc_die ();
+ die->tag = 0;
+ die->abbrev = abbrev_number;
+ die->type = NULL;
+ *diep = die;
+ return info_ptr;
+ }
+
+ abbrev = dwarf2_lookup_abbrev (abbrev_number);
+ if (!abbrev)
+ {
+ error ("Dwarf Error: could not find abbrev number %d.", abbrev_number);
+ }
+ die = dwarf_alloc_die ();
+ die->offset = offset;
+ die->tag = abbrev->tag;
+ die->has_children = abbrev->has_children;
+ die->abbrev = abbrev_number;
+ die->type = NULL;
+
+ die->num_attrs = abbrev->num_attrs;
+ die->attrs = (struct attribute *)
+ xmalloc (die->num_attrs * sizeof (struct attribute));
+
+ for (i = 0; i < abbrev->num_attrs; ++i)
+ {
+ info_ptr = read_attribute (&die->attrs[i], &abbrev->attrs[i],
+ abfd, info_ptr);
+ }
+
+ *diep = die;
+ return info_ptr;
+}
+
+/* Read an attribute described by an abbreviated attribute. */
+
+static char *
+read_attribute (attr, abbrev, abfd, info_ptr)
+ struct attribute *attr;
+ struct attr_abbrev *abbrev;
+ bfd *abfd;
+ char *info_ptr;
+{
+ unsigned int bytes_read;
+ struct dwarf_block *blk;
+
+ attr->name = abbrev->name;
+ attr->form = abbrev->form;
+ switch (abbrev->form)
+ {
+ case DW_FORM_addr:
+ case DW_FORM_ref_addr:
+ DW_ADDR (attr) = read_address (abfd, info_ptr);
+ info_ptr += address_size;
+ break;
+ case DW_FORM_block2:
+ blk = dwarf_alloc_block ();
+ blk->size = read_2_bytes (abfd, info_ptr);
+ info_ptr += 2;
+ blk->data = read_n_bytes (abfd, info_ptr, blk->size);
+ info_ptr += blk->size;
+ DW_BLOCK (attr) = blk;
+ break;
+ case DW_FORM_block4:
+ blk = dwarf_alloc_block ();
+ blk->size = read_4_bytes (abfd, info_ptr);
+ info_ptr += 4;
+ blk->data = read_n_bytes (abfd, info_ptr, blk->size);
+ info_ptr += blk->size;
+ DW_BLOCK (attr) = blk;
+ break;
+ case DW_FORM_data2:
+ DW_UNSND (attr) = read_2_bytes (abfd, info_ptr);
+ info_ptr += 2;
+ break;
+ case DW_FORM_data4:
+ DW_UNSND (attr) = read_4_bytes (abfd, info_ptr);
+ info_ptr += 4;
+ break;
+ case DW_FORM_data8:
+ DW_UNSND (attr) = read_8_bytes (abfd, info_ptr);
+ info_ptr += 8;
+ break;
+ case DW_FORM_string:
+ DW_STRING (attr) = read_string (abfd, info_ptr, &bytes_read);
+ info_ptr += bytes_read;
+ break;
+ case DW_FORM_block:
+ blk = dwarf_alloc_block ();
+ blk->size = read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
+ info_ptr += bytes_read;
+ blk->data = read_n_bytes (abfd, info_ptr, blk->size);
+ info_ptr += blk->size;
+ DW_BLOCK (attr) = blk;
+ break;
+ case DW_FORM_block1:
+ blk = dwarf_alloc_block ();
+ blk->size = read_1_byte (abfd, info_ptr);
+ info_ptr += 1;
+ blk->data = read_n_bytes (abfd, info_ptr, blk->size);
+ info_ptr += blk->size;
+ DW_BLOCK (attr) = blk;
+ break;
+ case DW_FORM_data1:
+ DW_UNSND (attr) = read_1_byte (abfd, info_ptr);
+ info_ptr += 1;
+ break;
+ case DW_FORM_flag:
+ DW_UNSND (attr) = read_1_byte (abfd, info_ptr);
+ info_ptr += 1;
+ break;
+ case DW_FORM_sdata:
+ DW_SND (attr) = read_signed_leb128 (abfd, info_ptr, &bytes_read);
+ info_ptr += bytes_read;
+ break;
+ case DW_FORM_udata:
+ DW_UNSND (attr) = read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
+ info_ptr += bytes_read;
+ break;
+ case DW_FORM_ref1:
+ DW_UNSND (attr) = read_1_byte (abfd, info_ptr);
+ info_ptr += 1;
+ break;
+ case DW_FORM_ref2:
+ DW_UNSND (attr) = read_2_bytes (abfd, info_ptr);
+ info_ptr += 2;
+ break;
+ case DW_FORM_ref4:
+ DW_UNSND (attr) = read_4_bytes (abfd, info_ptr);
+ info_ptr += 4;
+ break;
+ case DW_FORM_ref_udata:
+ DW_UNSND (attr) = read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
+ info_ptr += bytes_read;
+ break;
+ case DW_FORM_strp:
+ case DW_FORM_indirect:
+ default:
+ error ("Dwarf Error: Cannot handle %s in DWARF reader.",
+ dwarf_form_name (abbrev->form));
+ }
+ return info_ptr;
+}
+
+/* read dwarf information from a buffer */
+
+static unsigned int
+read_1_byte (abfd, buf)
+ bfd *abfd;
+ char *buf;
+{
+ return bfd_get_8 (abfd, (bfd_byte *) buf);
+}
+
+static int
+read_1_signed_byte (abfd, buf)
+ bfd *abfd;
+ char *buf;
+{
+ return bfd_get_signed_8 (abfd, (bfd_byte *) buf);
+}
+
+static unsigned int
+read_2_bytes (abfd, buf)
+ bfd *abfd;
+ char *buf;
+{
+ return bfd_get_16 (abfd, (bfd_byte *) buf);
+}
+
+static int
+read_2_signed_bytes (abfd, buf)
+ bfd *abfd;
+ char *buf;
+{
+ return bfd_get_signed_16 (abfd, (bfd_byte *) buf);
+}
+
+static unsigned int
+read_4_bytes (abfd, buf)
+ bfd *abfd;
+ char *buf;
+{
+ return bfd_get_32 (abfd, (bfd_byte *) buf);
+}
+
+static int
+read_4_signed_bytes (abfd, buf)
+ bfd *abfd;
+ char *buf;
+{
+ return bfd_get_signed_32 (abfd, (bfd_byte *) buf);
+}
+
+static unsigned int
+read_8_bytes (abfd, buf)
+ bfd *abfd;
+ char *buf;
+{
+ return bfd_get_64 (abfd, (bfd_byte *) buf);
+}
+
+static CORE_ADDR
+read_address (abfd, buf)
+ bfd *abfd;
+ char *buf;
+{
+ CORE_ADDR retval = 0;
+
+ switch (address_size)
+ {
+ case 4:
+ retval = bfd_get_32 (abfd, (bfd_byte *) buf);
+ break;
+ case 8:
+ retval = bfd_get_64 (abfd, (bfd_byte *) buf);
+ break;
+ default:
+ /* *THE* alternative is 8, right? */
+ abort ();
+ }
+ /* If the address being read is larger than the address that is
+ applicable for the object file format then mask it down to the
+ correct size. Take care to avoid unnecessary shift or shift
+ overflow */
+ if (address_size > address_significant_size
+ && address_significant_size < sizeof (CORE_ADDR))
+ {
+ CORE_ADDR mask = ((CORE_ADDR) 0) - 1;
+ retval &= ~(mask << (address_significant_size * 8));
+ }
+ return retval;
+}
+
+static char *
+read_n_bytes (abfd, buf, size)
+ bfd * abfd;
+ char *buf;
+ unsigned int size;
+{
+ /* If the size of a host char is 8 bits, we can return a pointer
+ to the buffer, otherwise we have to copy the data to a buffer
+ allocated on the temporary obstack. */
+#if HOST_CHAR_BIT == 8
+ return buf;
+#else
+ char *ret;
+ unsigned int i;
+
+ ret = obstack_alloc (&dwarf2_tmp_obstack, size);
+ for (i = 0; i < size; ++i)
+ {
+ ret[i] = bfd_get_8 (abfd, (bfd_byte *) buf);
+ buf++;
+ }
+ return ret;
+#endif
+}
+
+static char *
+read_string (abfd, buf, bytes_read_ptr)
+ bfd *abfd;
+ char *buf;
+ unsigned int *bytes_read_ptr;
+{
+ /* If the size of a host char is 8 bits, we can return a pointer
+ to the string, otherwise we have to copy the string to a buffer
+ allocated on the temporary obstack. */
+#if HOST_CHAR_BIT == 8
+ if (*buf == '\0')
+ {
+ *bytes_read_ptr = 1;
+ return NULL;
+ }
+ *bytes_read_ptr = strlen (buf) + 1;
+ return buf;
+#else
+ int byte;
+ unsigned int i = 0;
+
+ while ((byte = bfd_get_8 (abfd, (bfd_byte *) buf)) != 0)
+ {
+ obstack_1grow (&dwarf2_tmp_obstack, byte);
+ i++;
+ buf++;
+ }
+ if (i == 0)
+ {
+ *bytes_read_ptr = 1;
+ return NULL;
+ }
+ obstack_1grow (&dwarf2_tmp_obstack, '\0');
+ *bytes_read_ptr = i + 1;
+ return obstack_finish (&dwarf2_tmp_obstack);
+#endif
+}
+
+static unsigned int
+read_unsigned_leb128 (abfd, buf, bytes_read_ptr)
+ bfd *abfd;
+ char *buf;
+ unsigned int *bytes_read_ptr;
+{
+ unsigned int result, num_read;
+ int i, shift;
+ unsigned char byte;
+
+ result = 0;
+ shift = 0;
+ num_read = 0;
+ i = 0;
+ while (1)
+ {
+ byte = bfd_get_8 (abfd, (bfd_byte *) buf);
+ buf++;
+ num_read++;
+ result |= ((byte & 127) << shift);
+ if ((byte & 128) == 0)
+ {
+ break;
+ }
+ shift += 7;
+ }
+ *bytes_read_ptr = num_read;
+ return result;
+}
+
+static int
+read_signed_leb128 (abfd, buf, bytes_read_ptr)
+ bfd *abfd;
+ char *buf;
+ unsigned int *bytes_read_ptr;
+{
+ int result;
+ int i, shift, size, num_read;
+ unsigned char byte;
+
+ result = 0;
+ shift = 0;
+ size = 32;
+ num_read = 0;
+ i = 0;
+ while (1)
+ {
+ byte = bfd_get_8 (abfd, (bfd_byte *) buf);
+ buf++;
+ num_read++;
+ result |= ((byte & 127) << shift);
+ shift += 7;
+ if ((byte & 128) == 0)
+ {
+ break;
+ }
+ }
+ if ((shift < size) && (byte & 0x40))
+ {
+ result |= -(1 << shift);
+ }
+ *bytes_read_ptr = num_read;
+ return result;
+}
+
+static void
+set_cu_language (lang)
+ unsigned int lang;
+{
+ switch (lang)
+ {
+ case DW_LANG_C89:
+ case DW_LANG_C:
+ cu_language = language_c;
+ break;
+ case DW_LANG_C_plus_plus:
+ cu_language = language_cplus;
+ break;
+ case DW_LANG_Fortran77:
+ case DW_LANG_Fortran90:
+ cu_language = language_fortran;
+ break;
+ case DW_LANG_Mips_Assembler:
+ cu_language = language_asm;
+ break;
+ case DW_LANG_Ada83:
+ case DW_LANG_Cobol74:
+ case DW_LANG_Cobol85:
+ case DW_LANG_Pascal83:
+ case DW_LANG_Modula2:
+ default:
+ cu_language = language_unknown;
+ break;
+ }
+ cu_language_defn = language_def (cu_language);
+}
+
+/* Return the named attribute or NULL if not there. */
+
+static struct attribute *
+dwarf_attr (die, name)
+ struct die_info *die;
+ unsigned int name;
+{
+ unsigned int i;
+ struct attribute *spec = NULL;
+
+ for (i = 0; i < die->num_attrs; ++i)
+ {
+ if (die->attrs[i].name == name)
+ {
+ return &die->attrs[i];
+ }
+ if (die->attrs[i].name == DW_AT_specification
+ || die->attrs[i].name == DW_AT_abstract_origin)
+ spec = &die->attrs[i];
+ }
+ if (spec)
+ {
+ struct die_info *ref_die =
+ follow_die_ref (dwarf2_get_ref_die_offset (spec));
+
+ if (ref_die)
+ return dwarf_attr (ref_die, name);
+ }
+
+ return NULL;
+}
+
+/* Decode the line number information for the compilation unit whose
+ line number info is at OFFSET in the .debug_line section.
+ The compilation directory of the file is passed in COMP_DIR. */
+
+struct filenames
+{
+ unsigned int num_files;
+ struct fileinfo
+ {
+ char *name;
+ unsigned int dir;
+ unsigned int time;
+ unsigned int size;
+ }
+ *files;
+};
+
+struct directories
+{
+ unsigned int num_dirs;
+ char **dirs;
+};
+
+static void
+dwarf_decode_lines (offset, comp_dir, abfd)
+ unsigned int offset;
+ char *comp_dir;
+ bfd *abfd;
+{
+ char *line_ptr;
+ char *line_end;
+ struct line_head lh;
+ struct cleanup *back_to;
+ unsigned int i, bytes_read;
+ char *cur_file, *cur_dir;
+ unsigned char op_code, extended_op, adj_opcode;
+
+#define FILE_ALLOC_CHUNK 5
+#define DIR_ALLOC_CHUNK 5
+
+ struct filenames files;
+ struct directories dirs;
+
+ if (dwarf_line_buffer == NULL)
+ {
+ complain (&dwarf2_missing_line_number_section);
+ return;
+ }
+
+ files.num_files = 0;
+ files.files = NULL;
+
+ dirs.num_dirs = 0;
+ dirs.dirs = NULL;
+
+ line_ptr = dwarf_line_buffer + offset;
+
+ /* read in the prologue */
+ lh.total_length = read_4_bytes (abfd, line_ptr);
+ line_ptr += 4;
+ line_end = line_ptr + lh.total_length;
+ lh.version = read_2_bytes (abfd, line_ptr);
+ line_ptr += 2;
+ lh.prologue_length = read_4_bytes (abfd, line_ptr);
+ line_ptr += 4;
+ lh.minimum_instruction_length = read_1_byte (abfd, line_ptr);
+ line_ptr += 1;
+ lh.default_is_stmt = read_1_byte (abfd, line_ptr);
+ line_ptr += 1;
+ lh.line_base = read_1_signed_byte (abfd, line_ptr);
+ line_ptr += 1;
+ lh.line_range = read_1_byte (abfd, line_ptr);
+ line_ptr += 1;
+ lh.opcode_base = read_1_byte (abfd, line_ptr);
+ line_ptr += 1;
+ lh.standard_opcode_lengths = (unsigned char *)
+ xmalloc (lh.opcode_base * sizeof (unsigned char));
+ back_to = make_cleanup ((make_cleanup_func) free_current_contents,
+ &lh.standard_opcode_lengths);
+
+ lh.standard_opcode_lengths[0] = 1;
+ for (i = 1; i < lh.opcode_base; ++i)
+ {
+ lh.standard_opcode_lengths[i] = read_1_byte (abfd, line_ptr);
+ line_ptr += 1;
+ }
+
+ /* Read directory table */
+ while ((cur_dir = read_string (abfd, line_ptr, &bytes_read)) != NULL)
+ {
+ line_ptr += bytes_read;
+ if ((dirs.num_dirs % DIR_ALLOC_CHUNK) == 0)
+ {
+ dirs.dirs = (char **)
+ xrealloc (dirs.dirs,
+ (dirs.num_dirs + DIR_ALLOC_CHUNK) * sizeof (char *));
+ if (dirs.num_dirs == 0)
+ make_cleanup ((make_cleanup_func) free_current_contents, &dirs.dirs);
+ }
+ dirs.dirs[dirs.num_dirs++] = cur_dir;
+ }
+ line_ptr += bytes_read;
+
+ /* Read file name table */
+ while ((cur_file = read_string (abfd, line_ptr, &bytes_read)) != NULL)
+ {
+ line_ptr += bytes_read;
+ if ((files.num_files % FILE_ALLOC_CHUNK) == 0)
+ {
+ files.files = (struct fileinfo *)
+ xrealloc (files.files,
+ (files.num_files + FILE_ALLOC_CHUNK)
+ * sizeof (struct fileinfo));
+ if (files.num_files == 0)
+ make_cleanup ((make_cleanup_func) free_current_contents,
+ &files.files);
+ }
+ files.files[files.num_files].name = cur_file;
+ files.files[files.num_files].dir =
+ read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
+ line_ptr += bytes_read;
+ files.files[files.num_files].time =
+ read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
+ line_ptr += bytes_read;
+ files.files[files.num_files].size =
+ read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
+ line_ptr += bytes_read;
+ files.num_files++;
+ }
+ line_ptr += bytes_read;
+
+ /* Read the statement sequences until there's nothing left. */
+ while (line_ptr < line_end)
+ {
+ /* state machine registers */
+ CORE_ADDR address = 0;
+ unsigned int file = 1;
+ unsigned int line = 1;
+ unsigned int column = 0;
+ int is_stmt = lh.default_is_stmt;
+ int basic_block = 0;
+ int end_sequence = 0;
+
+ /* Start a subfile for the current file of the state machine. */
+ if (files.num_files >= file)
+ {
+ /* The file and directory tables are 0 based, the references
+ are 1 based. */
+ dwarf2_start_subfile (files.files[file - 1].name,
+ (files.files[file - 1].dir
+ ? dirs.dirs[files.files[file - 1].dir - 1]
+ : comp_dir));
+ }
+
+ /* Decode the table. */
+ while (! end_sequence)
+ {
+ op_code = read_1_byte (abfd, line_ptr);
+ line_ptr += 1;
+ switch (op_code)
+ {
+ case DW_LNS_extended_op:
+ line_ptr += 1; /* ignore length */
+ extended_op = read_1_byte (abfd, line_ptr);
+ line_ptr += 1;
+ switch (extended_op)
+ {
+ case DW_LNE_end_sequence:
+ end_sequence = 1;
+ record_line (current_subfile, line, address);
+ break;
+ case DW_LNE_set_address:
+ address = read_address (abfd, line_ptr) + baseaddr;
+ line_ptr += address_size;
+ break;
+ case DW_LNE_define_file:
+ cur_file = read_string (abfd, line_ptr, &bytes_read);
+ line_ptr += bytes_read;
+ if ((files.num_files % FILE_ALLOC_CHUNK) == 0)
+ {
+ files.files = (struct fileinfo *)
+ xrealloc (files.files,
+ (files.num_files + FILE_ALLOC_CHUNK)
+ * sizeof (struct fileinfo));
+ if (files.num_files == 0)
+ make_cleanup ((make_cleanup_func) free_current_contents,
+ &files.files);
+ }
+ files.files[files.num_files].name = cur_file;
+ files.files[files.num_files].dir =
+ read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
+ line_ptr += bytes_read;
+ files.files[files.num_files].time =
+ read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
+ line_ptr += bytes_read;
+ files.files[files.num_files].size =
+ read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
+ line_ptr += bytes_read;
+ files.num_files++;
+ break;
+ default:
+ complain (&dwarf2_mangled_line_number_section);
+ goto done;
+ }
+ break;
+ case DW_LNS_copy:
+ record_line (current_subfile, line, address);
+ basic_block = 0;
+ break;
+ case DW_LNS_advance_pc:
+ address += lh.minimum_instruction_length
+ * read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
+ line_ptr += bytes_read;
+ break;
+ case DW_LNS_advance_line:
+ line += read_signed_leb128 (abfd, line_ptr, &bytes_read);
+ line_ptr += bytes_read;
+ break;
+ case DW_LNS_set_file:
+ /* The file and directory tables are 0 based, the references
+ are 1 based. */
+ file = read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
+ line_ptr += bytes_read;
+ dwarf2_start_subfile
+ (files.files[file - 1].name,
+ (files.files[file - 1].dir
+ ? dirs.dirs[files.files[file - 1].dir - 1]
+ : comp_dir));
+ break;
+ case DW_LNS_set_column:
+ column = read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
+ line_ptr += bytes_read;
+ break;
+ case DW_LNS_negate_stmt:
+ is_stmt = (!is_stmt);
+ break;
+ case DW_LNS_set_basic_block:
+ basic_block = 1;
+ break;
+ case DW_LNS_const_add_pc:
+ address += (255 - lh.opcode_base) / lh.line_range;
+ break;
+ case DW_LNS_fixed_advance_pc:
+ address += read_2_bytes (abfd, line_ptr);
+ line_ptr += 2;
+ break;
+ default: /* special operand */
+ adj_opcode = op_code - lh.opcode_base;
+ address += (adj_opcode / lh.line_range)
+ * lh.minimum_instruction_length;
+ line += lh.line_base + (adj_opcode % lh.line_range);
+ /* append row to matrix using current values */
+ record_line (current_subfile, line, address);
+ basic_block = 1;
+ }
+ }
+ }
+done:
+ do_cleanups (back_to);
+}
+
+/* Start a subfile for DWARF. FILENAME is the name of the file and
+ DIRNAME the name of the source directory which contains FILENAME
+ or NULL if not known.
+ This routine tries to keep line numbers from identical absolute and
+ relative file names in a common subfile.
+
+ Using the `list' example from the GDB testsuite, which resides in
+ /srcdir and compiling it with Irix6.2 cc in /compdir using a filename
+ of /srcdir/list0.c yields the following debugging information for list0.c:
+
+ DW_AT_name: /srcdir/list0.c
+ DW_AT_comp_dir: /compdir
+ files.files[0].name: list0.h
+ files.files[0].dir: /srcdir
+ files.files[1].name: list0.c
+ files.files[1].dir: /srcdir
+
+ The line number information for list0.c has to end up in a single
+ subfile, so that `break /srcdir/list0.c:1' works as expected. */
+
+static void
+dwarf2_start_subfile (filename, dirname)
+ char *filename;
+ char *dirname;
+{
+ /* If the filename isn't absolute, try to match an existing subfile
+ with the full pathname. */
+
+ if (*filename != '/' && dirname != NULL)
+ {
+ struct subfile *subfile;
+ char *fullname = concat (dirname, "/", filename, NULL);
+
+ for (subfile = subfiles; subfile; subfile = subfile->next)
+ {
+ if (STREQ (subfile->name, fullname))
+ {
+ current_subfile = subfile;
+ free (fullname);
+ return;
+ }
+ }
+ free (fullname);
+ }
+ start_subfile (filename, dirname);
+}
+
+/* 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.
+ If TYPE is NULL, determine symbol type from the die, otherwise
+ used the passed type.
+ */
+
+static struct symbol *
+new_symbol (die, type, objfile)
+ struct die_info *die;
+ struct type *type;
+ struct objfile *objfile;
+{
+ struct symbol *sym = NULL;
+ char *name;
+ struct attribute *attr = NULL;
+ struct attribute *attr2 = NULL;
+ CORE_ADDR addr;
+
+ name = dwarf2_linkage_name (die);
+ if (name)
+ {
+ sym = (struct symbol *) obstack_alloc (&objfile->symbol_obstack,
+ sizeof (struct symbol));
+ OBJSTAT (objfile, n_syms++);
+ memset (sym, 0, sizeof (struct symbol));
+ SYMBOL_NAME (sym) = obsavestring (name, strlen (name),
+ &objfile->symbol_obstack);
+
+ /* Default assumptions.
+ Use the passed type or decode it from the die. */
+ SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
+ SYMBOL_CLASS (sym) = LOC_STATIC;
+ if (type != NULL)
+ SYMBOL_TYPE (sym) = type;
+ else
+ SYMBOL_TYPE (sym) = die_type (die, objfile);
+ attr = dwarf_attr (die, DW_AT_decl_line);
+ if (attr)
+ {
+ SYMBOL_LINE (sym) = DW_UNSND (attr);
+ }
+
+ /* 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 (die->tag)
+ {
+ case DW_TAG_label:
+ attr = dwarf_attr (die, DW_AT_low_pc);
+ if (attr)
+ {
+ SYMBOL_VALUE_ADDRESS (sym) = DW_ADDR (attr) + baseaddr;
+ }
+ SYMBOL_CLASS (sym) = LOC_LABEL;
+ break;
+ case DW_TAG_subprogram:
+ /* SYMBOL_BLOCK_VALUE (sym) will be filled in later by
+ finish_block. */
+ SYMBOL_CLASS (sym) = LOC_BLOCK;
+ attr2 = dwarf_attr (die, DW_AT_external);
+ if (attr2 && (DW_UNSND (attr2) != 0))
+ {
+ add_symbol_to_list (sym, &global_symbols);
+ }
+ else
+ {
+ add_symbol_to_list (sym, list_in_scope);
+ }
+ break;
+ case DW_TAG_variable:
+ /* Compilation with minimal debug info may result in variables
+ with missing type entries. Change the misleading `void' type
+ to something sensible. */
+ if (TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_VOID)
+ SYMBOL_TYPE (sym) = init_type (TYPE_CODE_INT,
+ TARGET_INT_BIT / HOST_CHAR_BIT, 0,
+ "<variable, no debug info>",
+ objfile);
+ attr = dwarf_attr (die, DW_AT_const_value);
+ if (attr)
+ {
+ dwarf2_const_value (attr, sym, objfile);
+ attr2 = dwarf_attr (die, DW_AT_external);
+ if (attr2 && (DW_UNSND (attr2) != 0))
+ add_symbol_to_list (sym, &global_symbols);
+ else
+ add_symbol_to_list (sym, list_in_scope);
+ break;
+ }
+ attr = dwarf_attr (die, DW_AT_location);
+ if (attr)
+ {
+ attr2 = dwarf_attr (die, DW_AT_external);
+ if (attr2 && (DW_UNSND (attr2) != 0))
+ {
+ SYMBOL_VALUE_ADDRESS (sym) =
+ decode_locdesc (DW_BLOCK (attr), objfile);
+ add_symbol_to_list (sym, &global_symbols);
+
+ /* In shared libraries the address of the variable
+ in the location descriptor might still be relocatable,
+ so its value could be zero.
+ Enter the symbol as a LOC_UNRESOLVED symbol, if its
+ value is zero, the address of the variable will then
+ be determined from the minimal symbol table whenever
+ the variable is referenced. */
+ if (SYMBOL_VALUE_ADDRESS (sym))
+ {
+ SYMBOL_VALUE_ADDRESS (sym) += baseaddr;
+ SYMBOL_CLASS (sym) = LOC_STATIC;
+ }
+ else
+ SYMBOL_CLASS (sym) = LOC_UNRESOLVED;
+ }
+ else
+ {
+ SYMBOL_VALUE (sym) = addr =
+ decode_locdesc (DW_BLOCK (attr), objfile);
+ add_symbol_to_list (sym, list_in_scope);
+ if (optimized_out)
+ {
+ SYMBOL_CLASS (sym) = LOC_OPTIMIZED_OUT;
+ }
+ else if (isreg)
+ {
+ SYMBOL_CLASS (sym) = LOC_REGISTER;
+ }
+ else if (offreg)
+ {
+ SYMBOL_CLASS (sym) = LOC_BASEREG;
+ SYMBOL_BASEREG (sym) = basereg;
+ }
+ else if (islocal)
+ {
+ SYMBOL_CLASS (sym) = LOC_LOCAL;
+ }
+ else
+ {
+ SYMBOL_CLASS (sym) = LOC_STATIC;
+ SYMBOL_VALUE_ADDRESS (sym) = addr + baseaddr;
+ }
+ }
+ }
+ else
+ {
+ /* We do not know the address of this symbol.
+ If it is an external symbol and we have type information
+ for it, enter the symbol as a LOC_UNRESOLVED symbol.
+ The address of the variable will then be determined from
+ the minimal symbol table whenever the variable is
+ referenced. */
+ attr2 = dwarf_attr (die, DW_AT_external);
+ if (attr2 && (DW_UNSND (attr2) != 0)
+ && dwarf_attr (die, DW_AT_type) != NULL)
+ {
+ SYMBOL_CLASS (sym) = LOC_UNRESOLVED;
+ add_symbol_to_list (sym, &global_symbols);
+ }
+ }
+ break;
+ case DW_TAG_formal_parameter:
+ attr = dwarf_attr (die, DW_AT_location);
+ if (attr)
+ {
+ SYMBOL_VALUE (sym) = decode_locdesc (DW_BLOCK (attr), objfile);
+ 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;
+ }
+ }
+ attr = dwarf_attr (die, DW_AT_const_value);
+ if (attr)
+ {
+ dwarf2_const_value (attr, sym, objfile);
+ }
+ add_symbol_to_list (sym, list_in_scope);
+ break;
+ case DW_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 DW_TAG_class_type:
+ case DW_TAG_structure_type:
+ case DW_TAG_union_type:
+ case DW_TAG_enumeration_type:
+ SYMBOL_CLASS (sym) = LOC_TYPEDEF;
+ SYMBOL_NAMESPACE (sym) = STRUCT_NAMESPACE;
+ add_symbol_to_list (sym, list_in_scope);
+
+ /* The semantics of C++ state that "struct foo { ... }" also
+ defines a typedef for "foo". Synthesize a typedef symbol so
+ that "ptype foo" works as expected. */
+ if (cu_language == language_cplus)
+ {
+ struct symbol *typedef_sym = (struct symbol *)
+ obstack_alloc (&objfile->symbol_obstack,
+ sizeof (struct symbol));
+ *typedef_sym = *sym;
+ SYMBOL_NAMESPACE (typedef_sym) = VAR_NAMESPACE;
+ if (TYPE_NAME (SYMBOL_TYPE (sym)) == 0)
+ TYPE_NAME (SYMBOL_TYPE (sym)) =
+ obsavestring (SYMBOL_NAME (sym),
+ strlen (SYMBOL_NAME (sym)),
+ &objfile->type_obstack);
+ add_symbol_to_list (typedef_sym, list_in_scope);
+ }
+ break;
+ case DW_TAG_typedef:
+ case DW_TAG_base_type:
+ SYMBOL_CLASS (sym) = LOC_TYPEDEF;
+ SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
+ add_symbol_to_list (sym, list_in_scope);
+ break;
+ case DW_TAG_enumerator:
+ attr = dwarf_attr (die, DW_AT_const_value);
+ if (attr)
+ {
+ dwarf2_const_value (attr, sym, objfile);
+ }
+ 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. */
+ complain (&dwarf2_unsupported_tag, dwarf_tag_name (die->tag));
+ break;
+ }
+ }
+ return (sym);
+}
+
+/* Copy constant value from an attribute to a symbol. */
+
+static void
+dwarf2_const_value (attr, sym, objfile)
+ struct attribute *attr;
+ struct symbol *sym;
+ struct objfile *objfile;
+{
+ struct dwarf_block *blk;
+
+ switch (attr->form)
+ {
+ case DW_FORM_addr:
+ if (TYPE_LENGTH (SYMBOL_TYPE (sym)) != (unsigned int) address_size)
+ complain (&dwarf2_const_value_length_mismatch, SYMBOL_NAME (sym),
+ address_size, TYPE_LENGTH (SYMBOL_TYPE (sym)));
+ SYMBOL_VALUE_BYTES (sym) = (char *)
+ obstack_alloc (&objfile->symbol_obstack, address_size);
+ store_address (SYMBOL_VALUE_BYTES (sym), address_size, DW_ADDR (attr));
+ SYMBOL_CLASS (sym) = LOC_CONST_BYTES;
+ break;
+ case DW_FORM_block1:
+ case DW_FORM_block2:
+ case DW_FORM_block4:
+ case DW_FORM_block:
+ blk = DW_BLOCK (attr);
+ if (TYPE_LENGTH (SYMBOL_TYPE (sym)) != blk->size)
+ complain (&dwarf2_const_value_length_mismatch, SYMBOL_NAME (sym),
+ blk->size, TYPE_LENGTH (SYMBOL_TYPE (sym)));
+ SYMBOL_VALUE_BYTES (sym) = (char *)
+ obstack_alloc (&objfile->symbol_obstack, blk->size);
+ memcpy (SYMBOL_VALUE_BYTES (sym), blk->data, blk->size);
+ SYMBOL_CLASS (sym) = LOC_CONST_BYTES;
+ break;
+ case DW_FORM_data2:
+ case DW_FORM_data4:
+ case DW_FORM_data8:
+ case DW_FORM_data1:
+ case DW_FORM_sdata:
+ case DW_FORM_udata:
+ SYMBOL_VALUE (sym) = DW_UNSND (attr);
+ SYMBOL_CLASS (sym) = LOC_CONST;
+ break;
+ default:
+ complain (&dwarf2_unsupported_const_value_attr,
+ dwarf_form_name (attr->form));
+ SYMBOL_VALUE (sym) = 0;
+ SYMBOL_CLASS (sym) = LOC_CONST;
+ break;
+ }
+}
+
+/* Return the type of the die in question using its DW_AT_type attribute. */
+
+static struct type *
+die_type (die, objfile)
+ struct die_info *die;
+ struct objfile *objfile;
+{
+ struct type *type;
+ struct attribute *type_attr;
+ struct die_info *type_die;
+ unsigned int ref;
+
+ type_attr = dwarf_attr (die, DW_AT_type);
+ if (!type_attr)
+ {
+ /* A missing DW_AT_type represents a void type. */
+ return dwarf2_fundamental_type (objfile, FT_VOID);
+ }
+ else
+ {
+ ref = dwarf2_get_ref_die_offset (type_attr);
+ type_die = follow_die_ref (ref);
+ if (!type_die)
+ {
+ error ("Dwarf Error: Cannot find referent at offset %d.", ref);
+ return NULL;
+ }
+ }
+ type = tag_type_to_type (type_die, objfile);
+ if (!type)
+ {
+ dump_die (type_die);
+ error ("Dwarf Error: Problem turning type die at offset into gdb type.");
+ }
+ return type;
+}
+
+/* Return the containing type of the die in question using its
+ DW_AT_containing_type attribute. */
+
+static struct type *
+die_containing_type (die, objfile)
+ struct die_info *die;
+ struct objfile *objfile;
+{
+ struct type *type = NULL;
+ struct attribute *type_attr;
+ struct die_info *type_die = NULL;
+ unsigned int ref;
+
+ type_attr = dwarf_attr (die, DW_AT_containing_type);
+ if (type_attr)
+ {
+ ref = dwarf2_get_ref_die_offset (type_attr);
+ type_die = follow_die_ref (ref);
+ if (!type_die)
+ {
+ error ("Dwarf Error: Cannot find referent at offset %d.", ref);
+ return NULL;
+ }
+ type = tag_type_to_type (type_die, objfile);
+ }
+ if (!type)
+ {
+ if (type_die)
+ dump_die (type_die);
+ error ("Dwarf Error: Problem turning containing type into gdb type.");
+ }
+ return type;
+}
+
+#if 0
+static struct type *
+type_at_offset (offset, objfile)
+ unsigned int offset;
+ struct objfile *objfile;
+{
+ struct die_info *die;
+ struct type *type;
+
+ die = follow_die_ref (offset);
+ if (!die)
+ {
+ error ("Dwarf Error: Cannot find type referent at offset %d.", offset);
+ return NULL;
+ }
+ type = tag_type_to_type (die, objfile);
+ return type;
+}
+#endif
+
+static struct type *
+tag_type_to_type (die, objfile)
+ struct die_info *die;
+ struct objfile *objfile;
+{
+ if (die->type)
+ {
+ return die->type;
+ }
+ else
+ {
+ read_type_die (die, objfile);
+ if (!die->type)
+ {
+ dump_die (die);
+ error ("Dwarf Error: Cannot find type of die.");
+ }
+ return die->type;
+ }
+}
+
+static void
+read_type_die (die, objfile)
+ struct die_info *die;
+ struct objfile *objfile;
+{
+ switch (die->tag)
+ {
+ case DW_TAG_class_type:
+ case DW_TAG_structure_type:
+ case DW_TAG_union_type:
+ read_structure_scope (die, objfile);
+ break;
+ case DW_TAG_enumeration_type:
+ read_enumeration (die, objfile);
+ break;
+ case DW_TAG_subprogram:
+ case DW_TAG_subroutine_type:
+ read_subroutine_type (die, objfile);
+ break;
+ case DW_TAG_array_type:
+ read_array_type (die, objfile);
+ break;
+ case DW_TAG_pointer_type:
+ read_tag_pointer_type (die, objfile);
+ break;
+ case DW_TAG_ptr_to_member_type:
+ read_tag_ptr_to_member_type (die, objfile);
+ break;
+ case DW_TAG_reference_type:
+ read_tag_reference_type (die, objfile);
+ break;
+ case DW_TAG_const_type:
+ read_tag_const_type (die, objfile);
+ break;
+ case DW_TAG_volatile_type:
+ read_tag_volatile_type (die, objfile);
+ break;
+ case DW_TAG_string_type:
+ read_tag_string_type (die, objfile);
+ break;
+ case DW_TAG_typedef:
+ read_typedef (die, objfile);
+ break;
+ case DW_TAG_base_type:
+ read_base_type (die, objfile);
+ break;
+ default:
+ complain (&dwarf2_unexpected_tag, dwarf_tag_name (die->tag));
+ break;
+ }
+}
+
+static struct type *
+dwarf_base_type (encoding, size, objfile)
+ int encoding;
+ int size;
+ struct objfile *objfile;
+{
+ /* FIXME - this should not produce a new (struct type *)
+ every time. It should cache base types. */
+ struct type *type;
+ switch (encoding)
+ {
+ case DW_ATE_address:
+ type = dwarf2_fundamental_type (objfile, FT_VOID);
+ return type;
+ case DW_ATE_boolean:
+ type = dwarf2_fundamental_type (objfile, FT_BOOLEAN);
+ return type;
+ case DW_ATE_complex_float:
+ if (size == 16)
+ {
+ type = dwarf2_fundamental_type (objfile, FT_DBL_PREC_COMPLEX);
+ }
+ else
+ {
+ type = dwarf2_fundamental_type (objfile, FT_COMPLEX);
+ }
+ return type;
+ case DW_ATE_float:
+ if (size == 8)
+ {
+ type = dwarf2_fundamental_type (objfile, FT_DBL_PREC_FLOAT);
+ }
+ else
+ {
+ type = dwarf2_fundamental_type (objfile, FT_FLOAT);
+ }
+ return type;
+ case DW_ATE_signed:
+ switch (size)
+ {
+ case 1:
+ type = dwarf2_fundamental_type (objfile, FT_SIGNED_CHAR);
+ break;
+ case 2:
+ type = dwarf2_fundamental_type (objfile, FT_SIGNED_SHORT);
+ break;
+ default:
+ case 4:
+ type = dwarf2_fundamental_type (objfile, FT_SIGNED_INTEGER);
+ break;
+ }
+ return type;
+ case DW_ATE_signed_char:
+ type = dwarf2_fundamental_type (objfile, FT_SIGNED_CHAR);
+ return type;
+ case DW_ATE_unsigned:
+ switch (size)
+ {
+ case 1:
+ type = dwarf2_fundamental_type (objfile, FT_UNSIGNED_CHAR);
+ break;
+ case 2:
+ type = dwarf2_fundamental_type (objfile, FT_UNSIGNED_SHORT);
+ break;
+ default:
+ case 4:
+ type = dwarf2_fundamental_type (objfile, FT_UNSIGNED_INTEGER);
+ break;
+ }
+ return type;
+ case DW_ATE_unsigned_char:
+ type = dwarf2_fundamental_type (objfile, FT_UNSIGNED_CHAR);
+ return type;
+ default:
+ type = dwarf2_fundamental_type (objfile, FT_SIGNED_INTEGER);
+ return type;
+ }
+}
+
+#if 0
+struct die_info *
+copy_die (old_die)
+ struct die_info *old_die;
+{
+ struct die_info *new_die;
+ int i, num_attrs;
+
+ new_die = (struct die_info *) xmalloc (sizeof (struct die_info));
+ memset (new_die, 0, sizeof (struct die_info));
+
+ new_die->tag = old_die->tag;
+ new_die->has_children = old_die->has_children;
+ new_die->abbrev = old_die->abbrev;
+ new_die->offset = old_die->offset;
+ new_die->type = NULL;
+
+ num_attrs = old_die->num_attrs;
+ new_die->num_attrs = num_attrs;
+ new_die->attrs = (struct attribute *)
+ xmalloc (num_attrs * sizeof (struct attribute));
+
+ for (i = 0; i < old_die->num_attrs; ++i)
+ {
+ new_die->attrs[i].name = old_die->attrs[i].name;
+ new_die->attrs[i].form = old_die->attrs[i].form;
+ new_die->attrs[i].u.addr = old_die->attrs[i].u.addr;
+ }
+
+ new_die->next = NULL;
+ return new_die;
+}
+#endif
+
+/* Return sibling of die, NULL if no sibling. */
+
+struct die_info *
+sibling_die (die)
+ struct die_info *die;
+{
+ int nesting_level = 0;
+
+ if (!die->has_children)
+ {
+ if (die->next && (die->next->tag == 0))
+ {
+ return NULL;
+ }
+ else
+ {
+ return die->next;
+ }
+ }
+ else
+ {
+ do
+ {
+ if (die->has_children)
+ {
+ nesting_level++;
+ }
+ if (die->tag == 0)
+ {
+ nesting_level--;
+ }
+ die = die->next;
+ }
+ while (nesting_level);
+ if (die && (die->tag == 0))
+ {
+ return NULL;
+ }
+ else
+ {
+ return die;
+ }
+ }
+}
+
+/* Get linkage name of a die, return NULL if not found. */
+
+static char *
+dwarf2_linkage_name (die)
+ struct die_info *die;
+{
+ struct attribute *attr;
+
+ attr = dwarf_attr (die, DW_AT_MIPS_linkage_name);
+ if (attr && DW_STRING (attr))
+ return DW_STRING (attr);
+ attr = dwarf_attr (die, DW_AT_name);
+ if (attr && DW_STRING (attr))
+ return DW_STRING (attr);
+ return NULL;
+}
+
+/* Convert a DIE tag into its string name. */
+
+static char *
+dwarf_tag_name (tag)
+ register unsigned tag;
+{
+ switch (tag)
+ {
+ case DW_TAG_padding:
+ return "DW_TAG_padding";
+ case DW_TAG_array_type:
+ return "DW_TAG_array_type";
+ case DW_TAG_class_type:
+ return "DW_TAG_class_type";
+ case DW_TAG_entry_point:
+ return "DW_TAG_entry_point";
+ case DW_TAG_enumeration_type:
+ return "DW_TAG_enumeration_type";
+ case DW_TAG_formal_parameter:
+ return "DW_TAG_formal_parameter";
+ case DW_TAG_imported_declaration:
+ return "DW_TAG_imported_declaration";
+ case DW_TAG_label:
+ return "DW_TAG_label";
+ case DW_TAG_lexical_block:
+ return "DW_TAG_lexical_block";
+ case DW_TAG_member:
+ return "DW_TAG_member";
+ case DW_TAG_pointer_type:
+ return "DW_TAG_pointer_type";
+ case DW_TAG_reference_type:
+ return "DW_TAG_reference_type";
+ case DW_TAG_compile_unit:
+ return "DW_TAG_compile_unit";
+ case DW_TAG_string_type:
+ return "DW_TAG_string_type";
+ case DW_TAG_structure_type:
+ return "DW_TAG_structure_type";
+ case DW_TAG_subroutine_type:
+ return "DW_TAG_subroutine_type";
+ case DW_TAG_typedef:
+ return "DW_TAG_typedef";
+ case DW_TAG_union_type:
+ return "DW_TAG_union_type";
+ case DW_TAG_unspecified_parameters:
+ return "DW_TAG_unspecified_parameters";
+ case DW_TAG_variant:
+ return "DW_TAG_variant";
+ case DW_TAG_common_block:
+ return "DW_TAG_common_block";
+ case DW_TAG_common_inclusion:
+ return "DW_TAG_common_inclusion";
+ case DW_TAG_inheritance:
+ return "DW_TAG_inheritance";
+ case DW_TAG_inlined_subroutine:
+ return "DW_TAG_inlined_subroutine";
+ case DW_TAG_module:
+ return "DW_TAG_module";
+ case DW_TAG_ptr_to_member_type:
+ return "DW_TAG_ptr_to_member_type";
+ case DW_TAG_set_type:
+ return "DW_TAG_set_type";
+ case DW_TAG_subrange_type:
+ return "DW_TAG_subrange_type";
+ case DW_TAG_with_stmt:
+ return "DW_TAG_with_stmt";
+ case DW_TAG_access_declaration:
+ return "DW_TAG_access_declaration";
+ case DW_TAG_base_type:
+ return "DW_TAG_base_type";
+ case DW_TAG_catch_block:
+ return "DW_TAG_catch_block";
+ case DW_TAG_const_type:
+ return "DW_TAG_const_type";
+ case DW_TAG_constant:
+ return "DW_TAG_constant";
+ case DW_TAG_enumerator:
+ return "DW_TAG_enumerator";
+ case DW_TAG_file_type:
+ return "DW_TAG_file_type";
+ case DW_TAG_friend:
+ return "DW_TAG_friend";
+ case DW_TAG_namelist:
+ return "DW_TAG_namelist";
+ case DW_TAG_namelist_item:
+ return "DW_TAG_namelist_item";
+ case DW_TAG_packed_type:
+ return "DW_TAG_packed_type";
+ case DW_TAG_subprogram:
+ return "DW_TAG_subprogram";
+ case DW_TAG_template_type_param:
+ return "DW_TAG_template_type_param";
+ case DW_TAG_template_value_param:
+ return "DW_TAG_template_value_param";
+ case DW_TAG_thrown_type:
+ return "DW_TAG_thrown_type";
+ case DW_TAG_try_block:
+ return "DW_TAG_try_block";
+ case DW_TAG_variant_part:
+ return "DW_TAG_variant_part";
+ case DW_TAG_variable:
+ return "DW_TAG_variable";
+ case DW_TAG_volatile_type:
+ return "DW_TAG_volatile_type";
+ case DW_TAG_MIPS_loop:
+ return "DW_TAG_MIPS_loop";
+ case DW_TAG_format_label:
+ return "DW_TAG_format_label";
+ case DW_TAG_function_template:
+ return "DW_TAG_function_template";
+ case DW_TAG_class_template:
+ return "DW_TAG_class_template";
+ default:
+ return "DW_TAG_<unknown>";
+ }
+}
+
+/* Convert a DWARF attribute code into its string name. */
+
+static char *
+dwarf_attr_name (attr)
+ register unsigned attr;
+{
+ switch (attr)
+ {
+ case DW_AT_sibling:
+ return "DW_AT_sibling";
+ case DW_AT_location:
+ return "DW_AT_location";
+ case DW_AT_name:
+ return "DW_AT_name";
+ case DW_AT_ordering:
+ return "DW_AT_ordering";
+ case DW_AT_subscr_data:
+ return "DW_AT_subscr_data";
+ case DW_AT_byte_size:
+ return "DW_AT_byte_size";
+ case DW_AT_bit_offset:
+ return "DW_AT_bit_offset";
+ case DW_AT_bit_size:
+ return "DW_AT_bit_size";
+ case DW_AT_element_list:
+ return "DW_AT_element_list";
+ case DW_AT_stmt_list:
+ return "DW_AT_stmt_list";
+ case DW_AT_low_pc:
+ return "DW_AT_low_pc";
+ case DW_AT_high_pc:
+ return "DW_AT_high_pc";
+ case DW_AT_language:
+ return "DW_AT_language";
+ case DW_AT_member:
+ return "DW_AT_member";
+ case DW_AT_discr:
+ return "DW_AT_discr";
+ case DW_AT_discr_value:
+ return "DW_AT_discr_value";
+ case DW_AT_visibility:
+ return "DW_AT_visibility";
+ case DW_AT_import:
+ return "DW_AT_import";
+ case DW_AT_string_length:
+ return "DW_AT_string_length";
+ case DW_AT_common_reference:
+ return "DW_AT_common_reference";
+ case DW_AT_comp_dir:
+ return "DW_AT_comp_dir";
+ case DW_AT_const_value:
+ return "DW_AT_const_value";
+ case DW_AT_containing_type:
+ return "DW_AT_containing_type";
+ case DW_AT_default_value:
+ return "DW_AT_default_value";
+ case DW_AT_inline:
+ return "DW_AT_inline";
+ case DW_AT_is_optional:
+ return "DW_AT_is_optional";
+ case DW_AT_lower_bound:
+ return "DW_AT_lower_bound";
+ case DW_AT_producer:
+ return "DW_AT_producer";
+ case DW_AT_prototyped:
+ return "DW_AT_prototyped";
+ case DW_AT_return_addr:
+ return "DW_AT_return_addr";
+ case DW_AT_start_scope:
+ return "DW_AT_start_scope";
+ case DW_AT_stride_size:
+ return "DW_AT_stride_size";
+ case DW_AT_upper_bound:
+ return "DW_AT_upper_bound";
+ case DW_AT_abstract_origin:
+ return "DW_AT_abstract_origin";
+ case DW_AT_accessibility:
+ return "DW_AT_accessibility";
+ case DW_AT_address_class:
+ return "DW_AT_address_class";
+ case DW_AT_artificial:
+ return "DW_AT_artificial";
+ case DW_AT_base_types:
+ return "DW_AT_base_types";
+ case DW_AT_calling_convention:
+ return "DW_AT_calling_convention";
+ case DW_AT_count:
+ return "DW_AT_count";
+ case DW_AT_data_member_location:
+ return "DW_AT_data_member_location";
+ case DW_AT_decl_column:
+ return "DW_AT_decl_column";
+ case DW_AT_decl_file:
+ return "DW_AT_decl_file";
+ case DW_AT_decl_line:
+ return "DW_AT_decl_line";
+ case DW_AT_declaration:
+ return "DW_AT_declaration";
+ case DW_AT_discr_list:
+ return "DW_AT_discr_list";
+ case DW_AT_encoding:
+ return "DW_AT_encoding";
+ case DW_AT_external:
+ return "DW_AT_external";
+ case DW_AT_frame_base:
+ return "DW_AT_frame_base";
+ case DW_AT_friend:
+ return "DW_AT_friend";
+ case DW_AT_identifier_case:
+ return "DW_AT_identifier_case";
+ case DW_AT_macro_info:
+ return "DW_AT_macro_info";
+ case DW_AT_namelist_items:
+ return "DW_AT_namelist_items";
+ case DW_AT_priority:
+ return "DW_AT_priority";
+ case DW_AT_segment:
+ return "DW_AT_segment";
+ case DW_AT_specification:
+ return "DW_AT_specification";
+ case DW_AT_static_link:
+ return "DW_AT_static_link";
+ case DW_AT_type:
+ return "DW_AT_type";
+ case DW_AT_use_location:
+ return "DW_AT_use_location";
+ case DW_AT_variable_parameter:
+ return "DW_AT_variable_parameter";
+ case DW_AT_virtuality:
+ return "DW_AT_virtuality";
+ case DW_AT_vtable_elem_location:
+ return "DW_AT_vtable_elem_location";
+
+#ifdef MIPS
+ case DW_AT_MIPS_fde:
+ return "DW_AT_MIPS_fde";
+ case DW_AT_MIPS_loop_begin:
+ return "DW_AT_MIPS_loop_begin";
+ case DW_AT_MIPS_tail_loop_begin:
+ return "DW_AT_MIPS_tail_loop_begin";
+ case DW_AT_MIPS_epilog_begin:
+ return "DW_AT_MIPS_epilog_begin";
+ case DW_AT_MIPS_loop_unroll_factor:
+ return "DW_AT_MIPS_loop_unroll_factor";
+ case DW_AT_MIPS_software_pipeline_depth:
+ return "DW_AT_MIPS_software_pipeline_depth";
+ case DW_AT_MIPS_linkage_name:
+ return "DW_AT_MIPS_linkage_name";
+#endif
+
+ case DW_AT_sf_names:
+ return "DW_AT_sf_names";
+ case DW_AT_src_info:
+ return "DW_AT_src_info";
+ case DW_AT_mac_info:
+ return "DW_AT_mac_info";
+ case DW_AT_src_coords:
+ return "DW_AT_src_coords";
+ case DW_AT_body_begin:
+ return "DW_AT_body_begin";
+ case DW_AT_body_end:
+ return "DW_AT_body_end";
+ default:
+ return "DW_AT_<unknown>";
+ }
+}
+
+/* Convert a DWARF value form code into its string name. */
+
+static char *
+dwarf_form_name (form)
+ register unsigned form;
+{
+ switch (form)
+ {
+ case DW_FORM_addr:
+ return "DW_FORM_addr";
+ case DW_FORM_block2:
+ return "DW_FORM_block2";
+ case DW_FORM_block4:
+ return "DW_FORM_block4";
+ case DW_FORM_data2:
+ return "DW_FORM_data2";
+ case DW_FORM_data4:
+ return "DW_FORM_data4";
+ case DW_FORM_data8:
+ return "DW_FORM_data8";
+ case DW_FORM_string:
+ return "DW_FORM_string";
+ case DW_FORM_block:
+ return "DW_FORM_block";
+ case DW_FORM_block1:
+ return "DW_FORM_block1";
+ case DW_FORM_data1:
+ return "DW_FORM_data1";
+ case DW_FORM_flag:
+ return "DW_FORM_flag";
+ case DW_FORM_sdata:
+ return "DW_FORM_sdata";
+ case DW_FORM_strp:
+ return "DW_FORM_strp";
+ case DW_FORM_udata:
+ return "DW_FORM_udata";
+ case DW_FORM_ref_addr:
+ return "DW_FORM_ref_addr";
+ case DW_FORM_ref1:
+ return "DW_FORM_ref1";
+ case DW_FORM_ref2:
+ return "DW_FORM_ref2";
+ case DW_FORM_ref4:
+ return "DW_FORM_ref4";
+ case DW_FORM_ref8:
+ return "DW_FORM_ref8";
+ case DW_FORM_ref_udata:
+ return "DW_FORM_ref_udata";
+ case DW_FORM_indirect:
+ return "DW_FORM_indirect";
+ default:
+ return "DW_FORM_<unknown>";
+ }
+}
+
+/* Convert a DWARF stack opcode into its string name. */
+
+static char *
+dwarf_stack_op_name (op)
+ register unsigned op;
+{
+ switch (op)
+ {
+ case DW_OP_addr:
+ return "DW_OP_addr";
+ case DW_OP_deref:
+ return "DW_OP_deref";
+ case DW_OP_const1u:
+ return "DW_OP_const1u";
+ case DW_OP_const1s:
+ return "DW_OP_const1s";
+ case DW_OP_const2u:
+ return "DW_OP_const2u";
+ case DW_OP_const2s:
+ return "DW_OP_const2s";
+ case DW_OP_const4u:
+ return "DW_OP_const4u";
+ case DW_OP_const4s:
+ return "DW_OP_const4s";
+ case DW_OP_const8u:
+ return "DW_OP_const8u";
+ case DW_OP_const8s:
+ return "DW_OP_const8s";
+ case DW_OP_constu:
+ return "DW_OP_constu";
+ case DW_OP_consts:
+ return "DW_OP_consts";
+ case DW_OP_dup:
+ return "DW_OP_dup";
+ case DW_OP_drop:
+ return "DW_OP_drop";
+ case DW_OP_over:
+ return "DW_OP_over";
+ case DW_OP_pick:
+ return "DW_OP_pick";
+ case DW_OP_swap:
+ return "DW_OP_swap";
+ case DW_OP_rot:
+ return "DW_OP_rot";
+ case DW_OP_xderef:
+ return "DW_OP_xderef";
+ case DW_OP_abs:
+ return "DW_OP_abs";
+ case DW_OP_and:
+ return "DW_OP_and";
+ case DW_OP_div:
+ return "DW_OP_div";
+ case DW_OP_minus:
+ return "DW_OP_minus";
+ case DW_OP_mod:
+ return "DW_OP_mod";
+ case DW_OP_mul:
+ return "DW_OP_mul";
+ case DW_OP_neg:
+ return "DW_OP_neg";
+ case DW_OP_not:
+ return "DW_OP_not";
+ case DW_OP_or:
+ return "DW_OP_or";
+ case DW_OP_plus:
+ return "DW_OP_plus";
+ case DW_OP_plus_uconst:
+ return "DW_OP_plus_uconst";
+ case DW_OP_shl:
+ return "DW_OP_shl";
+ case DW_OP_shr:
+ return "DW_OP_shr";
+ case DW_OP_shra:
+ return "DW_OP_shra";
+ case DW_OP_xor:
+ return "DW_OP_xor";
+ case DW_OP_bra:
+ return "DW_OP_bra";
+ case DW_OP_eq:
+ return "DW_OP_eq";
+ case DW_OP_ge:
+ return "DW_OP_ge";
+ case DW_OP_gt:
+ return "DW_OP_gt";
+ case DW_OP_le:
+ return "DW_OP_le";
+ case DW_OP_lt:
+ return "DW_OP_lt";
+ case DW_OP_ne:
+ return "DW_OP_ne";
+ case DW_OP_skip:
+ return "DW_OP_skip";
+ case DW_OP_lit0:
+ return "DW_OP_lit0";
+ case DW_OP_lit1:
+ return "DW_OP_lit1";
+ case DW_OP_lit2:
+ return "DW_OP_lit2";
+ case DW_OP_lit3:
+ return "DW_OP_lit3";
+ case DW_OP_lit4:
+ return "DW_OP_lit4";
+ case DW_OP_lit5:
+ return "DW_OP_lit5";
+ case DW_OP_lit6:
+ return "DW_OP_lit6";
+ case DW_OP_lit7:
+ return "DW_OP_lit7";
+ case DW_OP_lit8:
+ return "DW_OP_lit8";
+ case DW_OP_lit9:
+ return "DW_OP_lit9";
+ case DW_OP_lit10:
+ return "DW_OP_lit10";
+ case DW_OP_lit11:
+ return "DW_OP_lit11";
+ case DW_OP_lit12:
+ return "DW_OP_lit12";
+ case DW_OP_lit13:
+ return "DW_OP_lit13";
+ case DW_OP_lit14:
+ return "DW_OP_lit14";
+ case DW_OP_lit15:
+ return "DW_OP_lit15";
+ case DW_OP_lit16:
+ return "DW_OP_lit16";
+ case DW_OP_lit17:
+ return "DW_OP_lit17";
+ case DW_OP_lit18:
+ return "DW_OP_lit18";
+ case DW_OP_lit19:
+ return "DW_OP_lit19";
+ case DW_OP_lit20:
+ return "DW_OP_lit20";
+ case DW_OP_lit21:
+ return "DW_OP_lit21";
+ case DW_OP_lit22:
+ return "DW_OP_lit22";
+ case DW_OP_lit23:
+ return "DW_OP_lit23";
+ case DW_OP_lit24:
+ return "DW_OP_lit24";
+ case DW_OP_lit25:
+ return "DW_OP_lit25";
+ case DW_OP_lit26:
+ return "DW_OP_lit26";
+ case DW_OP_lit27:
+ return "DW_OP_lit27";
+ case DW_OP_lit28:
+ return "DW_OP_lit28";
+ case DW_OP_lit29:
+ return "DW_OP_lit29";
+ case DW_OP_lit30:
+ return "DW_OP_lit30";
+ case DW_OP_lit31:
+ return "DW_OP_lit31";
+ case DW_OP_reg0:
+ return "DW_OP_reg0";
+ case DW_OP_reg1:
+ return "DW_OP_reg1";
+ case DW_OP_reg2:
+ return "DW_OP_reg2";
+ case DW_OP_reg3:
+ return "DW_OP_reg3";
+ case DW_OP_reg4:
+ return "DW_OP_reg4";
+ case DW_OP_reg5:
+ return "DW_OP_reg5";
+ case DW_OP_reg6:
+ return "DW_OP_reg6";
+ case DW_OP_reg7:
+ return "DW_OP_reg7";
+ case DW_OP_reg8:
+ return "DW_OP_reg8";
+ case DW_OP_reg9:
+ return "DW_OP_reg9";
+ case DW_OP_reg10:
+ return "DW_OP_reg10";
+ case DW_OP_reg11:
+ return "DW_OP_reg11";
+ case DW_OP_reg12:
+ return "DW_OP_reg12";
+ case DW_OP_reg13:
+ return "DW_OP_reg13";
+ case DW_OP_reg14:
+ return "DW_OP_reg14";
+ case DW_OP_reg15:
+ return "DW_OP_reg15";
+ case DW_OP_reg16:
+ return "DW_OP_reg16";
+ case DW_OP_reg17:
+ return "DW_OP_reg17";
+ case DW_OP_reg18:
+ return "DW_OP_reg18";
+ case DW_OP_reg19:
+ return "DW_OP_reg19";
+ case DW_OP_reg20:
+ return "DW_OP_reg20";
+ case DW_OP_reg21:
+ return "DW_OP_reg21";
+ case DW_OP_reg22:
+ return "DW_OP_reg22";
+ case DW_OP_reg23:
+ return "DW_OP_reg23";
+ case DW_OP_reg24:
+ return "DW_OP_reg24";
+ case DW_OP_reg25:
+ return "DW_OP_reg25";
+ case DW_OP_reg26:
+ return "DW_OP_reg26";
+ case DW_OP_reg27:
+ return "DW_OP_reg27";
+ case DW_OP_reg28:
+ return "DW_OP_reg28";
+ case DW_OP_reg29:
+ return "DW_OP_reg29";
+ case DW_OP_reg30:
+ return "DW_OP_reg30";
+ case DW_OP_reg31:
+ return "DW_OP_reg31";
+ case DW_OP_breg0:
+ return "DW_OP_breg0";
+ case DW_OP_breg1:
+ return "DW_OP_breg1";
+ case DW_OP_breg2:
+ return "DW_OP_breg2";
+ case DW_OP_breg3:
+ return "DW_OP_breg3";
+ case DW_OP_breg4:
+ return "DW_OP_breg4";
+ case DW_OP_breg5:
+ return "DW_OP_breg5";
+ case DW_OP_breg6:
+ return "DW_OP_breg6";
+ case DW_OP_breg7:
+ return "DW_OP_breg7";
+ case DW_OP_breg8:
+ return "DW_OP_breg8";
+ case DW_OP_breg9:
+ return "DW_OP_breg9";
+ case DW_OP_breg10:
+ return "DW_OP_breg10";
+ case DW_OP_breg11:
+ return "DW_OP_breg11";
+ case DW_OP_breg12:
+ return "DW_OP_breg12";
+ case DW_OP_breg13:
+ return "DW_OP_breg13";
+ case DW_OP_breg14:
+ return "DW_OP_breg14";
+ case DW_OP_breg15:
+ return "DW_OP_breg15";
+ case DW_OP_breg16:
+ return "DW_OP_breg16";
+ case DW_OP_breg17:
+ return "DW_OP_breg17";
+ case DW_OP_breg18:
+ return "DW_OP_breg18";
+ case DW_OP_breg19:
+ return "DW_OP_breg19";
+ case DW_OP_breg20:
+ return "DW_OP_breg20";
+ case DW_OP_breg21:
+ return "DW_OP_breg21";
+ case DW_OP_breg22:
+ return "DW_OP_breg22";
+ case DW_OP_breg23:
+ return "DW_OP_breg23";
+ case DW_OP_breg24:
+ return "DW_OP_breg24";
+ case DW_OP_breg25:
+ return "DW_OP_breg25";
+ case DW_OP_breg26:
+ return "DW_OP_breg26";
+ case DW_OP_breg27:
+ return "DW_OP_breg27";
+ case DW_OP_breg28:
+ return "DW_OP_breg28";
+ case DW_OP_breg29:
+ return "DW_OP_breg29";
+ case DW_OP_breg30:
+ return "DW_OP_breg30";
+ case DW_OP_breg31:
+ return "DW_OP_breg31";
+ case DW_OP_regx:
+ return "DW_OP_regx";
+ case DW_OP_fbreg:
+ return "DW_OP_fbreg";
+ case DW_OP_bregx:
+ return "DW_OP_bregx";
+ case DW_OP_piece:
+ return "DW_OP_piece";
+ case DW_OP_deref_size:
+ return "DW_OP_deref_size";
+ case DW_OP_xderef_size:
+ return "DW_OP_xderef_size";
+ case DW_OP_nop:
+ return "DW_OP_nop";
+ default:
+ return "OP_<unknown>";
+ }
+}
+
+static char *
+dwarf_bool_name (mybool)
+ unsigned mybool;
+{
+ if (mybool)
+ return "TRUE";
+ else
+ return "FALSE";
+}
+
+/* Convert a DWARF type code into its string name. */
+
+static char *
+dwarf_type_encoding_name (enc)
+ register unsigned enc;
+{
+ switch (enc)
+ {
+ case DW_ATE_address:
+ return "DW_ATE_address";
+ case DW_ATE_boolean:
+ return "DW_ATE_boolean";
+ case DW_ATE_complex_float:
+ return "DW_ATE_complex_float";
+ case DW_ATE_float:
+ return "DW_ATE_float";
+ case DW_ATE_signed:
+ return "DW_ATE_signed";
+ case DW_ATE_signed_char:
+ return "DW_ATE_signed_char";
+ case DW_ATE_unsigned:
+ return "DW_ATE_unsigned";
+ case DW_ATE_unsigned_char:
+ return "DW_ATE_unsigned_char";
+ default:
+ return "DW_ATE_<unknown>";
+ }
+}
+
+/* Convert a DWARF call frame info operation to its string name. */
+
+#if 0
+static char *
+dwarf_cfi_name (cfi_opc)
+ register unsigned cfi_opc;
+{
+ switch (cfi_opc)
+ {
+ case DW_CFA_advance_loc:
+ return "DW_CFA_advance_loc";
+ case DW_CFA_offset:
+ return "DW_CFA_offset";
+ case DW_CFA_restore:
+ return "DW_CFA_restore";
+ case DW_CFA_nop:
+ return "DW_CFA_nop";
+ case DW_CFA_set_loc:
+ return "DW_CFA_set_loc";
+ case DW_CFA_advance_loc1:
+ return "DW_CFA_advance_loc1";
+ case DW_CFA_advance_loc2:
+ return "DW_CFA_advance_loc2";
+ case DW_CFA_advance_loc4:
+ return "DW_CFA_advance_loc4";
+ case DW_CFA_offset_extended:
+ return "DW_CFA_offset_extended";
+ case DW_CFA_restore_extended:
+ return "DW_CFA_restore_extended";
+ case DW_CFA_undefined:
+ return "DW_CFA_undefined";
+ case DW_CFA_same_value:
+ return "DW_CFA_same_value";
+ case DW_CFA_register:
+ return "DW_CFA_register";
+ case DW_CFA_remember_state:
+ return "DW_CFA_remember_state";
+ case DW_CFA_restore_state:
+ return "DW_CFA_restore_state";
+ case DW_CFA_def_cfa:
+ return "DW_CFA_def_cfa";
+ case DW_CFA_def_cfa_register:
+ return "DW_CFA_def_cfa_register";
+ case DW_CFA_def_cfa_offset:
+ return "DW_CFA_def_cfa_offset";
+ /* SGI/MIPS specific */
+ case DW_CFA_MIPS_advance_loc8:
+ return "DW_CFA_MIPS_advance_loc8";
+ default:
+ return "DW_CFA_<unknown>";
+ }
+}
+#endif
+
+void
+dump_die (die)
+ struct die_info *die;
+{
+ unsigned int i;
+
+ fprintf (stderr, "Die: %s (abbrev = %d, offset = %d)\n",
+ dwarf_tag_name (die->tag), die->abbrev, die->offset);
+ fprintf (stderr, "\thas children: %s\n",
+ dwarf_bool_name (die->has_children));
+
+ fprintf (stderr, "\tattributes:\n");
+ for (i = 0; i < die->num_attrs; ++i)
+ {
+ fprintf (stderr, "\t\t%s (%s) ",
+ dwarf_attr_name (die->attrs[i].name),
+ dwarf_form_name (die->attrs[i].form));
+ switch (die->attrs[i].form)
+ {
+ case DW_FORM_ref_addr:
+ case DW_FORM_addr:
+ fprintf (stderr, "address: ");
+ print_address_numeric (DW_ADDR (&die->attrs[i]), 1, gdb_stderr);
+ break;
+ case DW_FORM_block2:
+ case DW_FORM_block4:
+ case DW_FORM_block:
+ case DW_FORM_block1:
+ fprintf (stderr, "block: size %d", DW_BLOCK (&die->attrs[i])->size);
+ break;
+ case DW_FORM_data1:
+ case DW_FORM_data2:
+ case DW_FORM_data4:
+ case DW_FORM_ref1:
+ case DW_FORM_ref2:
+ case DW_FORM_ref4:
+ case DW_FORM_udata:
+ case DW_FORM_sdata:
+ fprintf (stderr, "constant: %d", DW_UNSND (&die->attrs[i]));
+ break;
+ case DW_FORM_string:
+ fprintf (stderr, "string: \"%s\"",
+ DW_STRING (&die->attrs[i])
+ ? DW_STRING (&die->attrs[i]) : "");
+ break;
+ case DW_FORM_flag:
+ if (DW_UNSND (&die->attrs[i]))
+ fprintf (stderr, "flag: TRUE");
+ else
+ fprintf (stderr, "flag: FALSE");
+ break;
+ case DW_FORM_strp: /* we do not support separate string
+ section yet */
+ case DW_FORM_indirect: /* we do not handle indirect yet */
+ case DW_FORM_data8: /* we do not have 64 bit quantities */
+ default:
+ fprintf (stderr, "unsupported attribute form: %d.",
+ die->attrs[i].form);
+ }
+ fprintf (stderr, "\n");
+ }
+}
+
+void
+dump_die_list (die)
+ struct die_info *die;
+{
+ while (die)
+ {
+ dump_die (die);
+ die = die->next;
+ }
+}
+
+void
+store_in_ref_table (offset, die)
+ unsigned int offset;
+ struct die_info *die;
+{
+ int h;
+ struct die_info *old;
+
+ h = (offset % REF_HASH_SIZE);
+ old = die_ref_table[h];
+ die->next_ref = old;
+ die_ref_table[h] = die;
+}
+
+
+static void
+dwarf2_empty_die_ref_table ()
+{
+ memset (die_ref_table, 0, sizeof (die_ref_table));
+}
+
+static unsigned int
+dwarf2_get_ref_die_offset (attr)
+ struct attribute *attr;
+{
+ unsigned int result = 0;
+
+ switch (attr->form)
+ {
+ case DW_FORM_ref_addr:
+ result = DW_ADDR (attr);
+ break;
+ case DW_FORM_ref1:
+ case DW_FORM_ref2:
+ case DW_FORM_ref4:
+ case DW_FORM_ref_udata:
+ result = cu_header_offset + DW_UNSND (attr);
+ break;
+ default:
+ complain (&dwarf2_unsupported_die_ref_attr, dwarf_form_name (attr->form));
+ }
+ return result;
+}
+
+struct die_info *
+follow_die_ref (offset)
+ unsigned int offset;
+{
+ struct die_info *die;
+ int h;
+
+ h = (offset % REF_HASH_SIZE);
+ die = die_ref_table[h];
+ while (die)
+ {
+ if (die->offset == offset)
+ {
+ return die;
+ }
+ die = die->next_ref;
+ }
+ return NULL;
+}
+
+static struct type *
+dwarf2_fundamental_type (objfile, typeid)
+ struct objfile *objfile;
+ int typeid;
+{
+ if (typeid < 0 || typeid >= FT_NUM_MEMBERS)
+ {
+ error ("Dwarf 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]);
+}
+
+/* Decode simple location descriptions.
+ Given a pointer to a dwarf block that defines a location, compute
+ the location and return the value.
+
+ FIXME: This is a kludge until we figure out a better
+ way to handle the location descriptions.
+ Gdb's design does not mesh well with the DWARF2 notion of a location
+ computing interpreter, which is a shame because the flexibility goes unused.
+ FIXME: Implement more operations as necessary.
+
+ A location description containing no operations indicates that the
+ object is optimized out. The global optimized_out flag is set for
+ those, the return value is meaningless.
+
+ When the result is a register number, the global isreg flag is set,
+ otherwise it is cleared.
+
+ When the result is a base register offset, the global offreg flag is set
+ and the register number is returned in basereg, otherwise it is cleared.
+
+ When the DW_OP_fbreg operation is encountered without a corresponding
+ DW_AT_frame_base attribute, the global islocal flag is set.
+ Hopefully the machine dependent code knows how to set up a virtual
+ frame pointer for the local references.
+
+ Note that stack[0] is unused except as a default error return.
+ Note that stack overflow is not yet handled. */
+
+static CORE_ADDR
+decode_locdesc (blk, objfile)
+ struct dwarf_block *blk;
+ struct objfile *objfile;
+{
+ int i;
+ int size = blk->size;
+ char *data = blk->data;
+ CORE_ADDR stack[64];
+ int stacki;
+ unsigned int bytes_read, unsnd;
+ unsigned char op;
+
+ i = 0;
+ stacki = 0;
+ stack[stacki] = 0;
+ isreg = 0;
+ offreg = 0;
+ islocal = 0;
+ optimized_out = 1;
+
+ while (i < size)
+ {
+ optimized_out = 0;
+ op = data[i++];
+ switch (op)
+ {
+ case DW_OP_reg0:
+ case DW_OP_reg1:
+ case DW_OP_reg2:
+ case DW_OP_reg3:
+ case DW_OP_reg4:
+ case DW_OP_reg5:
+ case DW_OP_reg6:
+ case DW_OP_reg7:
+ case DW_OP_reg8:
+ case DW_OP_reg9:
+ case DW_OP_reg10:
+ case DW_OP_reg11:
+ case DW_OP_reg12:
+ case DW_OP_reg13:
+ case DW_OP_reg14:
+ case DW_OP_reg15:
+ case DW_OP_reg16:
+ case DW_OP_reg17:
+ case DW_OP_reg18:
+ case DW_OP_reg19:
+ case DW_OP_reg20:
+ case DW_OP_reg21:
+ case DW_OP_reg22:
+ case DW_OP_reg23:
+ case DW_OP_reg24:
+ case DW_OP_reg25:
+ case DW_OP_reg26:
+ case DW_OP_reg27:
+ case DW_OP_reg28:
+ case DW_OP_reg29:
+ case DW_OP_reg30:
+ case DW_OP_reg31:
+ isreg = 1;
+ stack[++stacki] = op - DW_OP_reg0;
+ break;
+
+ case DW_OP_regx:
+ isreg = 1;
+ unsnd = read_unsigned_leb128 (NULL, (data + i), &bytes_read);
+ i += bytes_read;
+#if defined(HARRIS_TARGET) && defined(_M88K)
+ /* The Harris 88110 gdb ports have long kept their special reg
+ numbers between their gp-regs and their x-regs. This is
+ not how our dwarf is generated. Punt. */
+ unsnd += 6;
+#endif
+ stack[++stacki] = unsnd;
+ break;
+
+ case DW_OP_breg0:
+ case DW_OP_breg1:
+ case DW_OP_breg2:
+ case DW_OP_breg3:
+ case DW_OP_breg4:
+ case DW_OP_breg5:
+ case DW_OP_breg6:
+ case DW_OP_breg7:
+ case DW_OP_breg8:
+ case DW_OP_breg9:
+ case DW_OP_breg10:
+ case DW_OP_breg11:
+ case DW_OP_breg12:
+ case DW_OP_breg13:
+ case DW_OP_breg14:
+ case DW_OP_breg15:
+ case DW_OP_breg16:
+ case DW_OP_breg17:
+ case DW_OP_breg18:
+ case DW_OP_breg19:
+ case DW_OP_breg20:
+ case DW_OP_breg21:
+ case DW_OP_breg22:
+ case DW_OP_breg23:
+ case DW_OP_breg24:
+ case DW_OP_breg25:
+ case DW_OP_breg26:
+ case DW_OP_breg27:
+ case DW_OP_breg28:
+ case DW_OP_breg29:
+ case DW_OP_breg30:
+ case DW_OP_breg31:
+ offreg = 1;
+ basereg = op - DW_OP_breg0;
+ stack[++stacki] = read_signed_leb128 (NULL, (data + i), &bytes_read);
+ i += bytes_read;
+ break;
+
+ case DW_OP_fbreg:
+ stack[++stacki] = read_signed_leb128 (NULL, (data + i), &bytes_read);
+ i += bytes_read;
+ if (frame_base_reg >= 0)
+ {
+ offreg = 1;
+ basereg = frame_base_reg;
+ stack[stacki] += frame_base_offset;
+ }
+ else
+ {
+ complain (&dwarf2_missing_at_frame_base);
+ islocal = 1;
+ }
+ break;
+
+ case DW_OP_addr:
+ stack[++stacki] = read_address (objfile->obfd, &data[i]);
+ i += address_size;
+ break;
+
+ case DW_OP_const1u:
+ stack[++stacki] = read_1_byte (objfile->obfd, &data[i]);
+ i += 1;
+ break;
+
+ case DW_OP_const1s:
+ stack[++stacki] = read_1_signed_byte (objfile->obfd, &data[i]);
+ i += 1;
+ break;
+
+ case DW_OP_const2u:
+ stack[++stacki] = read_2_bytes (objfile->obfd, &data[i]);
+ i += 2;
+ break;
+
+ case DW_OP_const2s:
+ stack[++stacki] = read_2_signed_bytes (objfile->obfd, &data[i]);
+ i += 2;
+ break;
+
+ case DW_OP_const4u:
+ stack[++stacki] = read_4_bytes (objfile->obfd, &data[i]);
+ i += 4;
+ break;
+
+ case DW_OP_const4s:
+ stack[++stacki] = read_4_signed_bytes (objfile->obfd, &data[i]);
+ i += 4;
+ break;
+
+ case DW_OP_constu:
+ stack[++stacki] = read_unsigned_leb128 (NULL, (data + i),
+ &bytes_read);
+ i += bytes_read;
+ break;
+
+ case DW_OP_consts:
+ stack[++stacki] = read_signed_leb128 (NULL, (data + i), &bytes_read);
+ i += bytes_read;
+ break;
+
+ case DW_OP_plus:
+ stack[stacki - 1] += stack[stacki];
+ stacki--;
+ break;
+
+ case DW_OP_plus_uconst:
+ stack[stacki] += read_unsigned_leb128 (NULL, (data + i), &bytes_read);
+ i += bytes_read;
+ break;
+
+ case DW_OP_minus:
+ stack[stacki - 1] = stack[stacki] - stack[stacki - 1];
+ stacki--;
+ break;
+
+ default:
+ complain (&dwarf2_unsupported_stack_op, dwarf_stack_op_name(op));
+ return (stack[stacki]);
+ }
+ }
+ return (stack[stacki]);
+}
+
+/* memory allocation interface */
+
+/* ARGSUSED */
+static void
+dwarf2_free_tmp_obstack (ignore)
+ PTR ignore;
+{
+ obstack_free (&dwarf2_tmp_obstack, NULL);
+}
+
+static struct dwarf_block *
+dwarf_alloc_block ()
+{
+ struct dwarf_block *blk;
+
+ blk = (struct dwarf_block *)
+ obstack_alloc (&dwarf2_tmp_obstack, sizeof (struct dwarf_block));
+ return (blk);
+}
+
+static struct abbrev_info *
+dwarf_alloc_abbrev ()
+{
+ struct abbrev_info *abbrev;
+
+ abbrev = (struct abbrev_info *) xmalloc (sizeof (struct abbrev_info));
+ memset (abbrev, 0, sizeof (struct abbrev_info));
+ return (abbrev);
+}
+
+static struct die_info *
+dwarf_alloc_die ()
+{
+ struct die_info *die;
+
+ die = (struct die_info *) xmalloc (sizeof (struct die_info));
+ memset (die, 0, sizeof (struct die_info));
+ return (die);
+}
diff --git a/gdb/dwarfread.c b/gdb/dwarfread.c
new file mode 100644
index 00000000000..9de03123d7d
--- /dev/null
+++ b/gdb/dwarfread.c
@@ -0,0 +1,3915 @@
+/* DWARF debugging format support for GDB.
+ Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996, 1998
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 "symtab.h"
+#include "gdbtypes.h"
+#include "symfile.h"
+#include "objfiles.h"
+#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 "gdb_string.h"
+
+/* 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
+};
+
+struct complaint missing_at_name =
+{
+ "DIE @ 0x%x, AT_name tag missing", 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
+
+/* Provide a default mapping from a DWARF register number to a gdb REGNUM. */
+#ifndef DWARF_REG_TO_REGNUM
+#define DWARF_REG_TO_REGNUM(num) (num)
+#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;
+ CORE_ADDR at_low_pc;
+ CORE_ADDR 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;
+
+ /* Kludge to identify register variables */
+
+ unsigned int isreg;
+
+ /* Kludge to identify optimized out variables */
+
+ unsigned int optimized_out;
+
+ /* Kludge to identify basereg references.
+ Nonzero if we have an offset relative to a basereg. */
+
+ unsigned int offreg;
+
+ /* Kludge to identify which base register is it relative to. */
+
+ unsigned int basereg;
+};
+
+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 */
+
+/* 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;
+
+/* We put a pointer to this structure in the read_symtab_private field
+ of the psymtab. */
+
+struct dwfinfo {
+ /* Always the absolute file offset to the start of the ".debug"
+ section for the file containing the DIE's being accessed. */
+ file_ptr dbfoff;
+ /* Relative offset from the start of the ".debug" section 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. */
+ int dbroff;
+ /* The size of the chunk of DIE's being examined, in bytes. */
+ int dblength;
+ /* 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. */
+ file_ptr lnfoff;
+};
+
+#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 void
+free_utypes PARAMS ((PTR));
+
+static int
+attribute_size PARAMS ((unsigned int));
+
+static CORE_ADDR
+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
+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 ((struct dieinfo *));
+
+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_FORTRAN77:
+ case LANG_FORTRAN90:
+ cu_language = language_fortran;
+ break;
+ case LANG_ADA83:
+ case LANG_COBOL74:
+ case LANG_COBOL85:
+ 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, SEEK_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
+
+ free_utypes -- free the utypes array and reset pointer & count
+
+SYNOPSIS
+
+ static void free_utypes (PTR dummy)
+
+DESCRIPTION
+
+ Called via do_cleanups to free the utypes array, reset the pointer to NULL,
+ and set numutypes back to zero. This ensures that the utypes does not get
+ referenced after being freed.
+ */
+
+static void
+free_utypes (dummy)
+ PTR dummy;
+{
+ free (utypes);
+ utypes = NULL;
+ numutypes = 0;
+}
+
+
+/*
+
+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_VOID);
+ }
+ 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;
+ int anonymous_size;
+
+ 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);
+ FIELD_TYPE (list->field) = decode_die_type (&mbr);
+ FIELD_BITPOS (list->field) = 8 * locval (&mbr);
+ /* Handle bit fields. */
+ FIELD_BITSIZE (list->field) = 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. */
+ FIELD_BITPOS (list->field) += 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);
+ }
+ FIELD_BITPOS (list->field) +=
+ anonymous_size * 8 - mbr.at_bit_offset - mbr.at_bit_size;
+ }
+ }
+ 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: Possably a poor assumption */
+ TYPE_LENGTH (utype) = TARGET_PTR_BIT / TARGET_CHAR_BIT ;
+ 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_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;
+ int unsigned_enum = 1;
+
+ 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;
+ FIELD_TYPE (list->field) = NULL;
+ FIELD_BITSIZE (list->field) = 0;
+ FIELD_BITPOS (list->field) =
+ 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) = FIELD_BITPOS (list->field);
+ if (SYMBOL_VALUE (sym) < 0)
+ unsigned_enum = 0;
+ 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)
+ {
+ if (unsigned_enum)
+ TYPE_FLAGS (type) |= TYPE_FLAG_UNSIGNED;
+ 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;
+
+ /* AT_name is absent if the function is described with an
+ AT_abstract_origin tag.
+ Ignore the function description for now to avoid GDB core dumps.
+ FIXME: Add code to handle AT_abstract_origin tags properly. */
+ if (dip -> at_name == NULL)
+ {
+ complain (&missing_at_name, DIE_ID);
+ return;
+ }
+
+ 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. */
+
+ if (STREQN (producer, GCC_PRODUCER, strlen (GCC_PRODUCER)))
+ {
+ char version = producer[strlen (GCC_PRODUCER)];
+ processing_gcc_compilation = (version == '2' ? 2 : 1);
+ }
+ else
+ {
+ processing_gcc_compilation =
+ STREQN (producer, GPLUS_PRODUCER, strlen (GPLUS_PRODUCER))
+ || STREQN (producer, CHILL_PRODUCER, strlen (CHILL_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, NULL);
+ 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);
+ record_debugformat ("DWARF 1");
+ decode_line_numbers (lnbase);
+ process_dies (thisdie + dip -> die_length, enddie, objfile);
+
+ symtab = end_symtab (dip -> at_high_pc, objfile, 0);
+ if (symtab != NULL)
+ {
+ symtab -> language = cu_language;
+ }
+ do_cleanups (back_to);
+}
+
+/*
+
+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;
+ }
+#ifdef SMASH_TEXT_ADDRESS
+ /* I think that these are always text, not data, addresses. */
+ SMASH_TEXT_ADDRESS (di.at_low_pc);
+ SMASH_TEXT_ADDRESS (di.at_high_pc);
+#endif
+ switch (di.die_tag)
+ {
+ case TAG_compile_unit:
+ /* Skip Tag_compile_unit if we are already inside a compilation
+ unit, we are unable to handle nested compilation units
+ properly (FIXME). */
+ if (current_subfile == NULL)
+ read_file_scope (&di, thisdie, nextdie, objfile);
+ else
+ nextdie = thisdie + di.die_length;
+ 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 (struct dieinfo *dip)
+
+DESCRIPTION
+
+ Given pointer to a string of bytes that define a location, compute
+ the location and return the value.
+ A location description containing no atoms indicates that the
+ object is optimized out. The optimized_out flag is set for those,
+ the return value is meaningless.
+
+ 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 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 (dip)
+ struct dieinfo *dip;
+{
+ unsigned short nbytes;
+ unsigned short locsize;
+ auto long stack[64];
+ int stacki;
+ char *loc;
+ char *end;
+ int loc_atom_code;
+ int loc_value_size;
+
+ loc = dip -> at_location;
+ 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;
+ dip -> isreg = 0;
+ dip -> offreg = 0;
+ dip -> optimized_out = 1;
+ loc_value_size = TARGET_FT_LONG_SIZE (current_objfile);
+ while (loc < end)
+ {
+ dip -> optimized_out = 0;
+ 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]
+ = DWARF_REG_TO_REGNUM (target_to_host (loc, loc_value_size,
+ GET_UNSIGNED,
+ current_objfile));
+ loc += loc_value_size;
+ dip -> 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. */
+ dip -> offreg = 1;
+ dip -> 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, SEEK_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), SEEK_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), SEEK_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 (" ", gdb_stdout);
+ wrap_here ("");
+ fputs_filtered ("and ", gdb_stdout);
+ wrap_here ("");
+ printf_filtered ("%s...",
+ pst -> dependencies[i] -> filename);
+ wrap_here ("");
+ gdb_flush (gdb_stdout); /* Flush output */
+ }
+ psymtab_to_symtab_1 (pst -> dependencies[i]);
+ }
+ }
+ if (DBLENGTH (pst)) /* Otherwise it's a dummy */
+ {
+ buildsym_init ();
+ old_chain = make_cleanup ((make_cleanup_func)
+ really_free_pendings, 0);
+ read_ofile_symtab (pst);
+ if (info_verbose)
+ {
+ printf_filtered ("%d DIE's, sorting...", diecount);
+ wrap_here ("");
+ gdb_flush (gdb_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);
+ gdb_flush (gdb_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");
+ gdb_flush (gdb_stdout);
+ }
+ }
+ }
+ }
+}
+
+/*
+
+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, 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,
+ 0, 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, 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,
+ 0, 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, 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, 0, cu_language, objfile);
+ break;
+ case TAG_class_type:
+ case TAG_structure_type:
+ case TAG_union_type:
+ case TAG_enumeration_type:
+ /* Do not add opaque aggregate definitions to the psymtab. */
+ if (!dip -> has_at_byte_size)
+ break;
+ add_psymbol_to_list (dip -> at_name, strlen (dip -> at_name),
+ STRUCT_NAMESPACE, LOC_TYPEDEF,
+ &objfile -> static_psymbols,
+ 0, 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, 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));
+ OBJSTAT (objfile, n_syms++);
+ 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_ADDRESS (sym) = dip -> at_low_pc;
+ SYMBOL_CLASS (sym) = LOC_LABEL;
+ break;
+ case TAG_global_subroutine:
+ case TAG_subroutine:
+ SYMBOL_VALUE_ADDRESS (sym) = dip -> at_low_pc;
+ SYMBOL_TYPE (sym) = lookup_function_type (SYMBOL_TYPE (sym));
+ if (dip -> at_prototyped)
+ TYPE_FLAGS (SYMBOL_TYPE (sym)) |= TYPE_FLAG_PROTOTYPED;
+ 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_ADDRESS (sym) = locval (dip);
+ 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)
+ {
+ int loc = locval (dip);
+ if (dip -> optimized_out)
+ {
+ SYMBOL_CLASS (sym) = LOC_OPTIMIZED_OUT;
+ }
+ else if (dip -> isreg)
+ {
+ SYMBOL_CLASS (sym) = LOC_REGISTER;
+ }
+ else if (dip -> offreg)
+ {
+ SYMBOL_CLASS (sym) = LOC_BASEREG;
+ SYMBOL_BASEREG (sym) = dip -> basereg;
+ }
+ else
+ {
+ SYMBOL_CLASS (sym) = LOC_STATIC;
+ SYMBOL_VALUE (sym) += baseaddr;
+ }
+ if (SYMBOL_CLASS (sym) == LOC_STATIC)
+ {
+ /* LOC_STATIC address class MUST use SYMBOL_VALUE_ADDRESS,
+ which may store to a bigger location than SYMBOL_VALUE. */
+ SYMBOL_VALUE_ADDRESS (sym) = loc;
+ }
+ else
+ {
+ SYMBOL_VALUE (sym) = loc;
+ }
+ add_symbol_to_list (sym, list_in_scope);
+ }
+ break;
+ case TAG_formal_parameter:
+ if (dip -> at_location != NULL)
+ {
+ SYMBOL_VALUE (sym) = locval (dip);
+ }
+ add_symbol_to_list (sym, list_in_scope);
+ if (dip -> isreg)
+ {
+ SYMBOL_CLASS (sym) = LOC_REGPARM;
+ }
+ else if (dip -> offreg)
+ {
+ SYMBOL_CLASS (sym) = LOC_BASEREG_ARG;
+ SYMBOL_BASEREG (sym) = dip -> 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));
+ OBJSTAT (objfile, n_syms++);
+ 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.
+
+ FIXME: Would a 32 bit target ever need an 8 byte result?
+
+ */
+
+static CORE_ADDR
+target_to_host (from, nbytes, signextend, objfile)
+ char *from;
+ int nbytes;
+ int signextend; /* FIXME: Unused */
+ struct objfile *objfile;
+{
+ CORE_ADDR 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/gdb/elfread.c b/gdb/elfread.c
new file mode 100644
index 00000000000..417039e044d
--- /dev/null
+++ b/gdb/elfread.c
@@ -0,0 +1,849 @@
+/* Read ELF (Executable and Linking Format) object files for GDB.
+ Copyright 1991, 92, 93, 94, 95, 96, 1998 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "bfd.h"
+#include "gdb_string.h"
+#include "elf-bfd.h"
+#include "elf/mips.h"
+#include "symtab.h"
+#include "symfile.h"
+#include "objfiles.h"
+#include "buildsym.h"
+#include "stabsread.h"
+#include "gdb-stabs.h"
+#include "complaints.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 */
+ asection *mdebugsect; /* Section pointer for .mdebug 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 *, int));
+
+static void
+free_elfinfo PARAMS ((void *));
+
+static struct minimal_symbol *
+record_minimal_symbol_and_info PARAMS ((char *, CORE_ADDR,
+ enum minimal_symbol_type, char *,
+ asection *bfd_section,
+ 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;
+ }
+ else if (STREQ (sectp -> name, ".mdebug"))
+ {
+ ei -> mdebugsect = 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 struct minimal_symbol *
+record_minimal_symbol_and_info (name, address, ms_type, info, bfd_section,
+ objfile)
+ char *name;
+ CORE_ADDR address;
+ enum minimal_symbol_type ms_type;
+ char *info; /* FIXME, is this really char *? */
+ asection *bfd_section;
+ 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;
+#ifdef SMASH_TEXT_ADDRESS
+ SMASH_TEXT_ADDRESS (address);
+#endif
+ 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;
+ }
+
+ return prim_record_minimal_symbol_and_info
+ (name, address, ms_type, info, section, bfd_section, objfile);
+}
+
+/*
+
+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, int dynamic)
+
+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, dynamic)
+ bfd *abfd;
+ CORE_ADDR addr;
+ struct objfile *objfile;
+ int dynamic;
+{
+ long storage_needed;
+ asymbol *sym;
+ asymbol **symbol_table;
+ long number_of_symbols;
+ long 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;
+#ifdef SOFUN_ADDRESS_MAYBE_MISSING
+ /* Name of filesym, as saved on the symbol_obstack. */
+ char *filesymname = obsavestring ("", 0, &objfile->symbol_obstack);
+#endif
+ struct dbx_symfile_info *dbx = objfile->sym_stab_info;
+ unsigned long size;
+ int stripped = (bfd_get_symcount (abfd) == 0);
+
+ if (dynamic)
+ {
+ storage_needed = bfd_get_dynamic_symtab_upper_bound (abfd);
+
+ /* Nothing to be done if there is no dynamic symtab. */
+ if (storage_needed < 0)
+ return;
+ }
+ else
+ {
+ storage_needed = bfd_get_symtab_upper_bound (abfd);
+ if (storage_needed < 0)
+ error ("Can't read symbols from %s: %s", bfd_get_filename (abfd),
+ bfd_errmsg (bfd_get_error ()));
+ }
+ if (storage_needed > 0)
+ {
+ symbol_table = (asymbol **) xmalloc (storage_needed);
+ back_to = make_cleanup (free, symbol_table);
+ if (dynamic)
+ number_of_symbols = bfd_canonicalize_dynamic_symtab (abfd,
+ symbol_table);
+ else
+ number_of_symbols = bfd_canonicalize_symtab (abfd, symbol_table);
+ if (number_of_symbols < 0)
+ error ("Can't read symbols from %s: %s", bfd_get_filename (abfd),
+ bfd_errmsg (bfd_get_error ()));
+ 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 (dynamic
+ && sym -> section == &bfd_und_section
+ && (sym -> flags & BSF_FUNCTION))
+ {
+ struct minimal_symbol *msym;
+
+ /* Symbol is a reference to a function defined in
+ a shared library.
+ If its value is non zero then it is usually the address
+ of the corresponding entry in the procedure linkage table,
+ relative to the base address.
+ If its value is zero then the dynamic linker has to resolve
+ the symbol. We are unable to find any meaningful address
+ for this symbol in the executable file, so we skip it. */
+ symaddr = sym -> value;
+ if (symaddr == 0)
+ continue;
+ symaddr += addr;
+ msym = record_minimal_symbol_and_info
+ ((char *) sym -> name, symaddr,
+ mst_solib_trampoline, NULL, sym -> section, objfile);
+#ifdef SOFUN_ADDRESS_MAYBE_MISSING
+ if (msym != NULL)
+ msym->filename = filesymname;
+#endif
+ continue;
+ }
+
+ /* If it is a nonstripped executable, do not enter dynamic
+ symbols, as the dynamic symbol table is usually a subset
+ of the main symbol table. */
+ if (dynamic && !stripped)
+ 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;
+#ifdef SOFUN_ADDRESS_MAYBE_MISSING
+ filesymname =
+ obsavestring ((char *)filesym->name, strlen (filesym->name),
+ &objfile->symbol_obstack);
+#endif
+ }
+ else if (sym -> flags & (BSF_GLOBAL | BSF_LOCAL | BSF_WEAK))
+ {
+ struct minimal_symbol *msym;
+
+ /* 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)
+ {
+ /* This is a hack to get the minimal symbol type
+ right for Irix 5, which has absolute adresses
+ with special section indices for dynamic symbols. */
+ unsigned short shndx =
+ ((elf_symbol_type *) sym)->internal_elf_sym.st_shndx;
+
+ switch (shndx)
+ {
+ case SHN_MIPS_TEXT:
+ ms_type = mst_text;
+ break;
+ case SHN_MIPS_DATA:
+ ms_type = mst_data;
+ break;
+ case SHN_MIPS_ACOMMON:
+ ms_type = mst_bss;
+ break;
+ default:
+ ms_type = mst_abs;
+ }
+
+ /* If it is an Irix dynamic symbol, skip section name
+ symbols, relocate all others. */
+ if (ms_type != mst_abs)
+ {
+ if (sym->name[0] == '.')
+ continue;
+ symaddr += addr;
+ }
+ }
+ 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')
+ || ((sym -> flags & BSF_LOCAL)
+ && 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;
+#ifdef HARRIS_TARGET
+ else if (sym->name[0] == '.' && sym->name[1] == '.')
+ {
+ /* Looks like a Harris compiler generated label for the
+ purpose of marking instructions that are relevant to
+ DWARF dies. The assembler can't get rid of these
+ because they are relocatable addresses that the
+ linker needs to resolve. */
+ continue;
+ }
+#endif
+ 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;
+ msym = record_minimal_symbol_and_info
+ ((char *) sym -> name, symaddr,
+ ms_type, (PTR) size, sym -> section, objfile);
+#ifdef SOFUN_ADDRESS_MAYBE_MISSING
+ if (msym != NULL)
+ msym->filename = filesymname;
+#endif
+#ifdef ELF_MAKE_MSYMBOL_SPECIAL
+ ELF_MAKE_MSYMBOL_SPECIAL(sym,msym);
+#endif
+ }
+ }
+ 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;
+ mdebug_build_psymtabs() handles ECOFF debugging information.
+
+ 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 ((make_cleanup_func) discard_minimal_symbols, 0);
+
+ memset ((char *) &ei, 0, sizeof (ei));
+
+ /* Allocate struct to keep track of the symfile */
+ objfile->sym_stab_info = (struct dbx_symfile_info *)
+ 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, 0);
+
+ /* Add the dynamic symbols. */
+
+ elf_symtab_read (abfd, offset, objfile, 1);
+
+ /* Now process debugging information, which is contained in
+ special ELF sections. */
+
+ /* If we are reinitializing, or if we have never loaded syms yet,
+ set table to empty. MAINLINE is cleared so that *_read_psymtab
+ functions do not all also re-initialize the psymbol table. */
+ if (mainline)
+ {
+ init_psymbol_list (objfile, 0);
+ mainline = 0;
+ }
+
+ /* We first have to find them... */
+ bfd_map_over_sections (abfd, elf_locate_sections, (PTR) &ei);
+
+ /* ELF debugging information is inserted into the psymtab in the
+ order of least informative first - most informative last. Since
+ the psymtab table is searched `most recent insertion first' this
+ increases the probability that more detailed debug information
+ for a section is found.
+
+ For instance, an object file might contain both .mdebug (XCOFF)
+ and .debug_info (DWARF2) sections then .mdebug is inserted first
+ (searched last) and DWARF2 is inserted last (searched first). If
+ we don't do this then the XCOFF info is found first - for code in
+ an included file XCOFF info is useless. */
+
+ if (ei.mdebugsect)
+ {
+ const struct ecoff_debug_swap *swap;
+
+ /* .mdebug section, presumably holding ECOFF debugging
+ information. */
+ swap = get_elf_backend_data (abfd)->elf_backend_ecoff_debug_swap;
+ if (swap)
+ elfmdebug_build_psymtabs (objfile, swap, ei.mdebugsect,
+ section_offsets);
+ }
+ if (ei.stabsect)
+ {
+ asection *str_sect;
+
+ /* Stab sections have an associated string table that looks like
+ a separate section. */
+ str_sect = bfd_get_section_by_name (abfd, ".stabstr");
+
+ /* FIXME should probably warn about a stab section without a stabstr. */
+ if (str_sect)
+ elfstab_build_psymtabs (objfile,
+ section_offsets,
+ mainline,
+ ei.stabsect->filepos,
+ bfd_section_size (abfd, ei.stabsect),
+ str_sect->filepos,
+ bfd_section_size (abfd, str_sect));
+ }
+ if (dwarf2_has_info (abfd))
+ {
+ /* DWARF 2 sections */
+ dwarf2_build_psymtabs (objfile, section_offsets, mainline);
+ }
+ else if (ei.dboffset && ei.lnoffset)
+ {
+ /* DWARF sections */
+ dwarf_build_psymtabs (objfile,
+ section_offsets, mainline,
+ ei.dboffset, ei.dbsize,
+ ei.lnoffset, ei.lnsize);
+ }
+
+ /* 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 = 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 (objfile)
+ struct objfile *objfile;
+{
+ /* ELF objects may be reordered, so set OBJF_REORDERED. If we
+ find this causes a significant slowdown in gdb then we could
+ set it in the debug symbol readers only when necessary. */
+ objfile->flags |= OBJF_REORDERED;
+}
+
+/* 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 = 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. */
+
+static struct sym_fns elf_sym_fns =
+{
+ bfd_target_elf_flavour,
+ 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 */
+ default_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/gdb/environ.c b/gdb/environ.c
new file mode 100644
index 00000000000..77296bef2a4
--- /dev/null
+++ b/gdb/environ.c
@@ -0,0 +1,194 @@
+/* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define min(a, b) ((a) < (b) ? (a) : (b))
+#define max(a, b) ((a) > (b) ? (a) : (b))
+
+#include "defs.h"
+#include "environ.h"
+#include "gdb_string.h"
+#include "gdbcore.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;
+
+ if (environ == NULL)
+ return;
+
+ 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;
+
+ /* This used to handle setting the PATH and GNUTARGET variables
+ specially. The latter has been replaced by "set gnutarget"
+ (which has worked since GDB 4.11). The former affects searching
+ the PATH to find SHELL, and searching the PATH to find the
+ argument of "symbol-file" or "exec-file". Maybe we should have
+ some kind of "set exec-path" for that. But in any event, having
+ "set env" affect anything besides the inferior is a bad idea.
+ What if we want to change the environment we pass to the program
+ without afecting GDB's behavior? */
+
+ 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/gdb/environ.h b/gdb/environ.h
new file mode 100644
index 00000000000..87a538a1b47
--- /dev/null
+++ b/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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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/gdb/eval.c b/gdb/eval.c
new file mode 100644
index 00000000000..d3c34657396
--- /dev/null
+++ b/gdb/eval.c
@@ -0,0 +1,1989 @@
+/* Evaluate expressions for GDB.
+ Copyright 1986, 87, 89, 91, 92, 93, 94, 95, 96, 97, 1998
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "gdb_string.h"
+#include "symtab.h"
+#include "gdbtypes.h"
+#include "value.h"
+#include "expression.h"
+#include "target.h"
+#include "frame.h"
+#include "demangle.h"
+#include "language.h" /* For CAST_IS_CONVERSION */
+#include "f-lang.h" /* for array bound stuff */
+
+/* Defined in symtab.c */
+extern int hp_som_som_object_present;
+
+/* This is defined in valops.c */
+extern int overload_resolution;
+
+
+/* Prototypes for local functions. */
+
+static value_ptr evaluate_subexp_for_sizeof PARAMS ((struct expression *,
+ int *));
+
+static value_ptr evaluate_subexp_for_address PARAMS ((struct expression *,
+ int *, enum noside));
+
+static value_ptr evaluate_subexp PARAMS ((struct type *, struct expression *,
+ int *, enum noside));
+
+static char *get_label PARAMS ((struct expression *, int *));
+
+static value_ptr
+evaluate_struct_tuple PARAMS ((value_ptr, struct expression *, int *,
+ enum noside, int));
+
+static LONGEST
+init_array_element PARAMS ((value_ptr, value_ptr, struct expression *,
+ int *, enum noside, LONGEST, LONGEST));
+
+#ifdef __GNUC__
+inline
+#endif
+static value_ptr
+evaluate_subexp (expect_type, exp, pos, noside)
+ struct type *expect_type;
+ register struct expression *exp;
+ register int *pos;
+ enum noside noside;
+{
+ return (*exp->language_defn->evaluate_exp) (expect_type, exp, pos, noside);
+}
+
+/* Parse the string EXP as a C expression, evaluate it,
+ and return the result as a number. */
+
+CORE_ADDR
+parse_and_eval_address (exp)
+ char *exp;
+{
+ struct expression *expr = parse_expression (exp);
+ register CORE_ADDR addr;
+ register struct cleanup *old_chain =
+ make_cleanup ((make_cleanup_func) free_current_contents, &expr);
+
+ addr = value_as_pointer (evaluate_expression (expr));
+ do_cleanups (old_chain);
+ return addr;
+}
+
+/* Like parse_and_eval_address but takes a pointer to a char * variable
+ and advanced that variable across the characters parsed. */
+
+CORE_ADDR
+parse_and_eval_address_1 (expptr)
+ char **expptr;
+{
+ struct expression *expr = parse_exp_1 (expptr, (struct block *)0, 0);
+ register CORE_ADDR addr;
+ register struct cleanup *old_chain =
+ make_cleanup ((make_cleanup_func) free_current_contents, &expr);
+
+ addr = value_as_pointer (evaluate_expression (expr));
+ do_cleanups (old_chain);
+ return addr;
+}
+
+value_ptr
+parse_and_eval (exp)
+ char *exp;
+{
+ struct expression *expr = parse_expression (exp);
+ register value_ptr val;
+ register struct cleanup *old_chain
+ = make_cleanup ((make_cleanup_func) free_current_contents, &expr);
+
+ val = evaluate_expression (expr);
+ do_cleanups (old_chain);
+ return val;
+}
+
+/* Parse up to a comma (or to a closeparen)
+ in the string EXPP as an expression, evaluate it, and return the value.
+ EXPP is advanced to point to the comma. */
+
+value_ptr
+parse_to_comma_and_eval (expp)
+ char **expp;
+{
+ struct expression *expr = parse_exp_1 (expp, (struct block *) 0, 1);
+ register value_ptr val;
+ register struct cleanup *old_chain
+ = make_cleanup ((make_cleanup_func) free_current_contents, &expr);
+
+ val = evaluate_expression (expr);
+ do_cleanups (old_chain);
+ return val;
+}
+
+/* Evaluate an expression in internal prefix form
+ such as is constructed by parse.y.
+
+ See expression.h for info on the format of an expression. */
+
+value_ptr
+evaluate_expression (exp)
+ struct expression *exp;
+{
+ int pc = 0;
+ return evaluate_subexp (NULL_TYPE, exp, &pc, EVAL_NORMAL);
+}
+
+/* Evaluate an expression, avoiding all memory references
+ and getting a value whose type alone is correct. */
+
+value_ptr
+evaluate_type (exp)
+ struct expression *exp;
+{
+ int pc = 0;
+ return evaluate_subexp (NULL_TYPE, exp, &pc, EVAL_AVOID_SIDE_EFFECTS);
+}
+
+/* If the next expression is an OP_LABELED, skips past it,
+ returning the label. Otherwise, does nothing and returns NULL. */
+
+static char*
+get_label (exp, pos)
+ register struct expression *exp;
+ int *pos;
+{
+ if (exp->elts[*pos].opcode == OP_LABELED)
+ {
+ int pc = (*pos)++;
+ char *name = &exp->elts[pc + 2].string;
+ int tem = longest_to_int (exp->elts[pc + 1].longconst);
+ (*pos) += 3 + BYTES_TO_EXP_ELEM (tem + 1);
+ return name;
+ }
+ else
+ return NULL;
+}
+
+/* This function evaluates tupes (in Chill) or brace-initializers
+ (in C/C++) for structure types. */
+
+static value_ptr
+evaluate_struct_tuple (struct_val, exp, pos, noside, nargs)
+ value_ptr struct_val;
+ register struct expression *exp;
+ register int *pos;
+ enum noside noside;
+ int nargs;
+{
+ struct type *struct_type = check_typedef (VALUE_TYPE (struct_val));
+ struct type *substruct_type = struct_type;
+ struct type *field_type;
+ int fieldno = -1;
+ int variantno = -1;
+ int subfieldno = -1;
+ while (--nargs >= 0)
+ {
+ int pc = *pos;
+ value_ptr val = NULL;
+ int nlabels = 0;
+ int bitpos, bitsize;
+ char *addr;
+
+ /* Skip past the labels, and count them. */
+ while (get_label (exp, pos) != NULL)
+ nlabels++;
+
+ do
+ {
+ char *label = get_label (exp, &pc);
+ if (label)
+ {
+ for (fieldno = 0; fieldno < TYPE_NFIELDS (struct_type);
+ fieldno++)
+ {
+ char *field_name = TYPE_FIELD_NAME (struct_type, fieldno);
+ if (field_name != NULL && STREQ (field_name, label))
+ {
+ variantno = -1;
+ subfieldno = fieldno;
+ substruct_type = struct_type;
+ goto found;
+ }
+ }
+ for (fieldno = 0; fieldno < TYPE_NFIELDS (struct_type);
+ fieldno++)
+ {
+ char *field_name = TYPE_FIELD_NAME (struct_type, fieldno);
+ field_type = TYPE_FIELD_TYPE (struct_type, fieldno);
+ if ((field_name == 0 || *field_name == '\0')
+ && TYPE_CODE (field_type) == TYPE_CODE_UNION)
+ {
+ variantno = 0;
+ for (; variantno < TYPE_NFIELDS (field_type);
+ variantno++)
+ {
+ substruct_type
+ = TYPE_FIELD_TYPE (field_type, variantno);
+ if (TYPE_CODE (substruct_type) == TYPE_CODE_STRUCT)
+ {
+ for (subfieldno = 0;
+ subfieldno < TYPE_NFIELDS (substruct_type);
+ subfieldno++)
+ {
+ if (STREQ (TYPE_FIELD_NAME (substruct_type,
+ subfieldno),
+ label))
+ {
+ goto found;
+ }
+ }
+ }
+ }
+ }
+ }
+ error ("there is no field named %s", label);
+ found:
+ ;
+ }
+ else
+ {
+ /* Unlabelled tuple element - go to next field. */
+ if (variantno >= 0)
+ {
+ subfieldno++;
+ if (subfieldno >= TYPE_NFIELDS (substruct_type))
+ {
+ variantno = -1;
+ substruct_type = struct_type;
+ }
+ }
+ if (variantno < 0)
+ {
+ fieldno++;
+ subfieldno = fieldno;
+ if (fieldno >= TYPE_NFIELDS (struct_type))
+ error ("too many initializers");
+ field_type = TYPE_FIELD_TYPE (struct_type, fieldno);
+ if (TYPE_CODE (field_type) == TYPE_CODE_UNION
+ && TYPE_FIELD_NAME (struct_type, fieldno)[0] == '0')
+ error ("don't know which variant you want to set");
+ }
+ }
+
+ /* Here, struct_type is the type of the inner struct,
+ while substruct_type is the type of the inner struct.
+ These are the same for normal structures, but a variant struct
+ contains anonymous union fields that contain substruct fields.
+ The value fieldno is the index of the top-level (normal or
+ anonymous union) field in struct_field, while the value
+ subfieldno is the index of the actual real (named inner) field
+ in substruct_type. */
+
+ field_type = TYPE_FIELD_TYPE (substruct_type, subfieldno);
+ if (val == 0)
+ val = evaluate_subexp (field_type, exp, pos, noside);
+
+ /* Now actually set the field in struct_val. */
+
+ /* Assign val to field fieldno. */
+ if (VALUE_TYPE (val) != field_type)
+ val = value_cast (field_type, val);
+
+ bitsize = TYPE_FIELD_BITSIZE (substruct_type, subfieldno);
+ bitpos = TYPE_FIELD_BITPOS (struct_type, fieldno);
+ if (variantno >= 0)
+ bitpos += TYPE_FIELD_BITPOS (substruct_type, subfieldno);
+ addr = VALUE_CONTENTS (struct_val) + bitpos / 8;
+ if (bitsize)
+ modify_field (addr, value_as_long (val),
+ bitpos % 8, bitsize);
+ else
+ memcpy (addr, VALUE_CONTENTS (val),
+ TYPE_LENGTH (VALUE_TYPE (val)));
+ } while (--nlabels > 0);
+ }
+ return struct_val;
+}
+
+/* Recursive helper function for setting elements of array tuples for Chill.
+ The target is ARRAY (which has bounds LOW_BOUND to HIGH_BOUND);
+ the element value is ELEMENT;
+ EXP, POS and NOSIDE are as usual.
+ Evaluates index expresions and sets the specified element(s) of
+ ARRAY to ELEMENT.
+ Returns last index value. */
+
+static LONGEST
+init_array_element (array, element, exp, pos, noside, low_bound, high_bound)
+ value_ptr array, element;
+ register struct expression *exp;
+ register int *pos;
+ enum noside noside;
+ LONGEST low_bound, high_bound;
+{
+ LONGEST index;
+ int element_size = TYPE_LENGTH (VALUE_TYPE (element));
+ if (exp->elts[*pos].opcode == BINOP_COMMA)
+ {
+ (*pos)++;
+ init_array_element (array, element, exp, pos, noside,
+ low_bound, high_bound);
+ return init_array_element (array, element,
+ exp, pos, noside, low_bound, high_bound);
+ }
+ else if (exp->elts[*pos].opcode == BINOP_RANGE)
+ {
+ LONGEST low, high;
+ (*pos)++;
+ low = value_as_long (evaluate_subexp (NULL_TYPE, exp, pos, noside));
+ high = value_as_long (evaluate_subexp (NULL_TYPE, exp, pos, noside));
+ if (low < low_bound || high > high_bound)
+ error ("tuple range index out of range");
+ for (index = low ; index <= high; index++)
+ {
+ memcpy (VALUE_CONTENTS_RAW (array)
+ + (index - low_bound) * element_size,
+ VALUE_CONTENTS (element), element_size);
+ }
+ }
+ else
+ {
+ index = value_as_long (evaluate_subexp (NULL_TYPE, exp, pos, noside));
+ if (index < low_bound || index > high_bound)
+ error ("tuple index out of range");
+ memcpy (VALUE_CONTENTS_RAW (array) + (index - low_bound) * element_size,
+ VALUE_CONTENTS (element), element_size);
+ }
+ return index;
+}
+
+value_ptr
+evaluate_subexp_standard (expect_type, exp, pos, noside)
+ struct type *expect_type;
+ register struct expression *exp;
+ register int *pos;
+ enum noside noside;
+{
+ enum exp_opcode op;
+ int tem, tem2, tem3;
+ register int pc, pc2 = 0, oldpos;
+ register value_ptr arg1 = NULL, arg2 = NULL, arg3;
+ struct type *type;
+ int nargs;
+ value_ptr *argvec;
+ int upper, lower, retcode;
+ int code;
+ int ix;
+ long mem_offset;
+ struct symbol * sym;
+ struct type ** arg_types;
+ int save_pos1;
+
+ /* This expect_type crap should not be used for C. C expressions do
+ not have any notion of expected types, never has and (goddess
+ willing) never will. The C++ code uses it for some twisted
+ purpose (I haven't investigated but I suspect it just the usual
+ combination of Stroustrup figuring out some crazy language
+ feature and Tiemann figuring out some crazier way to try to
+ implement it). CHILL has the tuple stuff; I don't know enough
+ about CHILL to know whether expected types is the way to do it.
+ FORTRAN I don't know. */
+ if (exp->language_defn->la_language != language_cplus
+ && exp->language_defn->la_language != language_chill)
+ expect_type = NULL_TYPE;
+
+ pc = (*pos)++;
+ op = exp->elts[pc].opcode;
+
+ switch (op)
+ {
+ case OP_SCOPE:
+ 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_longest (exp->elts[pc + 1].type,
+ exp->elts[pc + 2].longconst);
+
+ case OP_DOUBLE:
+ (*pos) += 3;
+ return value_from_double (exp->elts[pc + 1].type,
+ exp->elts[pc + 2].doubleconst);
+
+ case OP_VAR_VALUE:
+ (*pos) += 3;
+ if (noside == EVAL_SKIP)
+ goto nosideret;
+ if (noside == EVAL_AVOID_SIDE_EFFECTS)
+ {
+ struct symbol * sym = exp->elts[pc + 2].symbol;
+ enum lval_type lv;
+
+ switch (SYMBOL_CLASS (sym))
+ {
+ case LOC_CONST:
+ case LOC_LABEL:
+ case LOC_CONST_BYTES:
+ lv = not_lval;
+ break;
+
+ case LOC_REGISTER:
+ case LOC_REGPARM:
+ lv = lval_register;
+ break;
+
+ default:
+ lv = lval_memory;
+ break;
+ }
+
+ return value_zero (SYMBOL_TYPE (sym), lv);
+ }
+ else
+ return value_of_variable (exp->elts[pc + 2].symbol,
+ exp->elts[pc + 1].block);
+
+ case OP_LAST:
+ (*pos) += 2;
+ return
+ access_value_history (longest_to_int (exp->elts[pc + 1].longconst));
+
+ case OP_REGISTER:
+ {
+ int regno = longest_to_int (exp->elts[pc + 1].longconst);
+ value_ptr val = value_of_register (regno);
+
+ (*pos) += 2;
+ if (val == NULL)
+ error ("Value of register %s not available.", REGISTER_NAME (regno));
+ else
+ return val;
+ }
+ case OP_BOOL:
+ (*pos) += 2;
+ return value_from_longest (LA_BOOL_TYPE,
+ exp->elts[pc + 1].longconst);
+
+ case OP_INTERNALVAR:
+ (*pos) += 2;
+ return value_of_internalvar (exp->elts[pc + 1].internalvar);
+
+ case OP_STRING:
+ 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:
+ tem = longest_to_int (exp->elts[pc + 1].longconst);
+ (*pos)
+ += 3 + BYTES_TO_EXP_ELEM ((tem + HOST_CHAR_BIT - 1) / HOST_CHAR_BIT);
+ if (noside == EVAL_SKIP)
+ goto nosideret;
+ return value_bitstring (&exp->elts[pc + 2].string, tem);
+ 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;
+ type = expect_type ? check_typedef (expect_type) : NULL_TYPE;
+
+ if (expect_type != NULL_TYPE && noside != EVAL_SKIP
+ && TYPE_CODE (type) == TYPE_CODE_STRUCT)
+ {
+ value_ptr rec = allocate_value (expect_type);
+ memset (VALUE_CONTENTS_RAW (rec), '\0', TYPE_LENGTH (type));
+ return evaluate_struct_tuple (rec, exp, pos, noside, nargs);
+ }
+
+ if (expect_type != NULL_TYPE && noside != EVAL_SKIP
+ && TYPE_CODE (type) == TYPE_CODE_ARRAY)
+ {
+ struct type *range_type = TYPE_FIELD_TYPE (type, 0);
+ struct type *element_type = TYPE_TARGET_TYPE (type);
+ value_ptr array = allocate_value (expect_type);
+ int element_size = TYPE_LENGTH (check_typedef (element_type));
+ LONGEST low_bound, high_bound, index;
+ if (get_discrete_bounds (range_type, &low_bound, &high_bound) < 0)
+ {
+ low_bound = 0;
+ high_bound = (TYPE_LENGTH (type) / element_size) - 1;
+ }
+ index = low_bound;
+ memset (VALUE_CONTENTS_RAW (array), 0, TYPE_LENGTH (expect_type));
+ for (tem = nargs; --nargs >= 0; )
+ {
+ value_ptr element;
+ int index_pc = 0;
+ if (exp->elts[*pos].opcode == BINOP_RANGE)
+ {
+ index_pc = ++(*pos);
+ evaluate_subexp (NULL_TYPE, exp, pos, EVAL_SKIP);
+ }
+ element = evaluate_subexp (element_type, exp, pos, noside);
+ if (VALUE_TYPE (element) != element_type)
+ element = value_cast (element_type, element);
+ if (index_pc)
+ {
+ int continue_pc = *pos;
+ *pos = index_pc;
+ index = init_array_element (array, element, exp, pos, noside,
+ low_bound, high_bound);
+ *pos = continue_pc;
+ }
+ else
+ {
+ if (index > high_bound)
+ /* to avoid memory corruption */
+ error ("Too many array elements");
+ memcpy (VALUE_CONTENTS_RAW (array)
+ + (index - low_bound) * element_size,
+ VALUE_CONTENTS (element),
+ element_size);
+ }
+ index++;
+ }
+ return array;
+ }
+
+ if (expect_type != NULL_TYPE && noside != EVAL_SKIP
+ && TYPE_CODE (type) == TYPE_CODE_SET)
+ {
+ value_ptr set = allocate_value (expect_type);
+ char *valaddr = VALUE_CONTENTS_RAW (set);
+ struct type *element_type = TYPE_INDEX_TYPE (type);
+ struct type *check_type = element_type;
+ LONGEST low_bound, high_bound;
+
+ /* get targettype of elementtype */
+ while (TYPE_CODE (check_type) == TYPE_CODE_RANGE ||
+ TYPE_CODE (check_type) == TYPE_CODE_TYPEDEF)
+ check_type = TYPE_TARGET_TYPE (check_type);
+
+ if (get_discrete_bounds (element_type, &low_bound, &high_bound) < 0)
+ error ("(power)set type with unknown size");
+ memset (valaddr, '\0', TYPE_LENGTH (type));
+ for (tem = 0; tem < nargs; tem++)
+ {
+ LONGEST range_low, range_high;
+ struct type *range_low_type, *range_high_type;
+ value_ptr elem_val;
+ if (exp->elts[*pos].opcode == BINOP_RANGE)
+ {
+ (*pos)++;
+ elem_val = evaluate_subexp (element_type, exp, pos, noside);
+ range_low_type = VALUE_TYPE (elem_val);
+ range_low = value_as_long (elem_val);
+ elem_val = evaluate_subexp (element_type, exp, pos, noside);
+ range_high_type = VALUE_TYPE (elem_val);
+ range_high = value_as_long (elem_val);
+ }
+ else
+ {
+ elem_val = evaluate_subexp (element_type, exp, pos, noside);
+ range_low_type = range_high_type = VALUE_TYPE (elem_val);
+ range_low = range_high = value_as_long (elem_val);
+ }
+ /* check types of elements to avoid mixture of elements from
+ different types. Also check if type of element is "compatible"
+ with element type of powerset */
+ if (TYPE_CODE (range_low_type) == TYPE_CODE_RANGE)
+ range_low_type = TYPE_TARGET_TYPE (range_low_type);
+ if (TYPE_CODE (range_high_type) == TYPE_CODE_RANGE)
+ range_high_type = TYPE_TARGET_TYPE (range_high_type);
+ if ((TYPE_CODE (range_low_type) != TYPE_CODE (range_high_type)) ||
+ (TYPE_CODE (range_low_type) == TYPE_CODE_ENUM &&
+ (range_low_type != range_high_type)))
+ /* different element modes */
+ error ("POWERSET tuple elements of different mode");
+ if ((TYPE_CODE (check_type) != TYPE_CODE (range_low_type)) ||
+ (TYPE_CODE (check_type) == TYPE_CODE_ENUM &&
+ range_low_type != check_type))
+ error ("incompatible POWERSET tuple elements");
+ if (range_low > range_high)
+ {
+ warning ("empty POWERSET tuple range");
+ continue;
+ }
+ if (range_low < low_bound || range_high > high_bound)
+ error ("POWERSET tuple element out of range");
+ range_low -= low_bound;
+ range_high -= low_bound;
+ for ( ; range_low <= range_high; range_low++)
+ {
+ int bit_index = (unsigned) range_low % TARGET_CHAR_BIT;
+ if (BITS_BIG_ENDIAN)
+ bit_index = TARGET_CHAR_BIT - 1 - bit_index;
+ valaddr [(unsigned) range_low / TARGET_CHAR_BIT]
+ |= 1 << bit_index;
+ }
+ }
+ return set;
+ }
+
+ argvec = (value_ptr *) alloca (sizeof (value_ptr) * 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_array (tem2, tem3, argvec);
+
+ case TERNOP_SLICE:
+ {
+ value_ptr array = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+ int lowbound
+ = value_as_long (evaluate_subexp (NULL_TYPE, exp, pos, noside));
+ int upper
+ = value_as_long (evaluate_subexp (NULL_TYPE, exp, pos, noside));
+ if (noside == EVAL_SKIP)
+ goto nosideret;
+ return value_slice (array, lowbound, upper - lowbound + 1);
+ }
+
+ case TERNOP_SLICE_COUNT:
+ {
+ value_ptr array = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+ int lowbound
+ = value_as_long (evaluate_subexp (NULL_TYPE, exp, pos, noside));
+ int length
+ = value_as_long (evaluate_subexp (NULL_TYPE, exp, pos, noside));
+ return value_slice (array, lowbound, length);
+ }
+
+ case TERNOP_COND:
+ /* Skip third and second args to evaluate the first one. */
+ arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+ if (value_logical_not (arg1))
+ {
+ evaluate_subexp (NULL_TYPE, exp, pos, EVAL_SKIP);
+ return evaluate_subexp (NULL_TYPE, exp, pos, noside);
+ }
+ else
+ {
+ arg2 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+ evaluate_subexp (NULL_TYPE, exp, pos, EVAL_SKIP);
+ return arg2;
+ }
+
+ case OP_FUNCALL:
+ (*pos) += 2;
+ op = exp->elts[*pos].opcode;
+ nargs = longest_to_int (exp->elts[pc + 1].longconst);
+ /* Allocate arg vector, including space for the function to be
+ called in argvec[0] and a terminating NULL */
+ argvec = (value_ptr *) alloca (sizeof (value_ptr) * (nargs + 3));
+ if (op == STRUCTOP_MEMBER || op == STRUCTOP_MPTR)
+ {
+ LONGEST fnptr;
+
+ /* 1997-08-01 Currently we do not support function invocation
+ via pointers-to-methods with HP aCC. Pointer does not point
+ to the function, but possibly to some thunk. */
+ if (hp_som_som_object_present)
+ {
+ error ("Not implemented: function invocation through pointer to method with HP aCC");
+ }
+
+ nargs++;
+ /* First, evaluate the structure into arg2 */
+ pc2 = (*pos)++;
+
+ if (noside == EVAL_SKIP)
+ goto nosideret;
+
+ if (op == STRUCTOP_MEMBER)
+ {
+ arg2 = evaluate_subexp_for_address (exp, pos, noside);
+ }
+ else
+ {
+ arg2 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+ }
+
+ /* If the function is a virtual function, then the
+ aggregate value (providing the structure) plays
+ its part by providing the vtable. Otherwise,
+ it is just along for the ride: call the function
+ directly. */
+
+ arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+
+ fnptr = 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));
+ 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 ((int) TYPE_FN_FIELD_VOFFSET (f, j) == fnoffset)
+ {
+ value_ptr 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", fnoffset);
+ }
+ else
+ {
+ VALUE_TYPE (arg1) = lookup_pointer_type (TYPE_TARGET_TYPE (VALUE_TYPE (arg1)));
+ }
+ got_it:
+
+ /* Now, say which argument to start evaluating from */
+ tem = 2;
+ }
+ else if (op == STRUCTOP_STRUCT || op == STRUCTOP_PTR)
+ {
+ /* Hair for method invocations */
+ int tem2;
+
+ nargs++;
+ /* First, evaluate the structure into arg2 */
+ pc2 = (*pos)++;
+ 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 (NULL_TYPE, exp, pos, noside);
+ }
+ /* Now, say which argument to start evaluating from */
+ tem = 2;
+ }
+ else
+ {
+ /* Non-method function call */
+ save_pos1 = *pos;
+ argvec[0] = evaluate_subexp_with_coercion (exp, pos, noside);
+ tem = 1;
+ type = VALUE_TYPE (argvec[0]);
+ if (type && TYPE_CODE (type) == TYPE_CODE_PTR)
+ type = TYPE_TARGET_TYPE (type);
+ if (type && TYPE_CODE (type) == TYPE_CODE_FUNC)
+ {
+ for (; tem <= nargs && tem <= TYPE_NFIELDS (type); tem++)
+ {
+ /* pai: FIXME This seems to be coercing arguments before
+ * overload resolution has been done! */
+ argvec[tem] = evaluate_subexp (TYPE_FIELD_TYPE (type, tem-1),
+ exp, pos, noside);
+ }
+ }
+ }
+
+ /* Evaluate arguments */
+ for (; tem <= nargs; tem++)
+ {
+ /* Ensure that array expressions are coerced into pointer objects. */
+ argvec[tem] = evaluate_subexp_with_coercion (exp, pos, noside);
+ }
+
+ /* signal end of arglist */
+ argvec[tem] = 0;
+
+ if (op == STRUCTOP_STRUCT || op == STRUCTOP_PTR)
+ {
+ int static_memfuncp;
+ value_ptr temp = arg2;
+ char tstr[256];
+ struct fn_field * fns_ptr;
+ int num_fns;
+ struct type * basetype;
+ int boffset;
+
+ /* Method invocation : stuff "this" as first parameter */
+ /* pai: this used to have lookup_pointer_type for some reason,
+ * but temp is already a pointer to the object */
+ argvec[1] = value_from_longest (VALUE_TYPE (temp),
+ VALUE_ADDRESS (temp)+VALUE_OFFSET (temp));
+ /* Name of method from expression */
+ strcpy(tstr, &exp->elts[pc2+2].string);
+
+ if (overload_resolution && (exp->language_defn->la_language == language_cplus))
+ {
+ /* Language is C++, do some overload resolution before evaluation */
+ value_ptr valp = NULL;
+
+ /* Prepare list of argument types for overload resolution */
+ arg_types = (struct type **) xmalloc (nargs * (sizeof (struct type *)));
+ for (ix=1; ix <= nargs; ix++)
+ arg_types[ix-1] = VALUE_TYPE (argvec[ix]);
+
+ (void) find_overload_match (arg_types, nargs, tstr,
+ 1 /* method */, 0 /* strict match */,
+ arg2 /* the object */, NULL,
+ &valp, NULL, &static_memfuncp);
+
+
+ argvec[1] = arg2; /* the ``this'' pointer */
+ argvec[0] = valp; /* use the method found after overload resolution */
+ }
+ else /* Non-C++ case -- or no overload resolution */
+ {
+ temp = arg2;
+ argvec[0] = value_struct_elt (&temp, argvec+1, tstr,
+ &static_memfuncp,
+ op == STRUCTOP_STRUCT
+ ? "structure" : "structure pointer");
+ argvec[1] = arg2; /* the ``this'' pointer */
+ }
+
+ if (static_memfuncp)
+ {
+ argvec[1] = argvec[0];
+ nargs--;
+ argvec++;
+ }
+ }
+ else if (op == STRUCTOP_MEMBER || op == STRUCTOP_MPTR)
+ {
+ argvec[1] = arg2;
+ argvec[0] = arg1;
+ }
+ else
+ {
+ /* Non-member function being called */
+
+ if (overload_resolution && (exp->language_defn->la_language == language_cplus))
+ {
+ /* Language is C++, do some overload resolution before evaluation */
+ struct symbol * symp;
+
+ /* Prepare list of argument types for overload resolution */
+ arg_types = (struct type **) xmalloc (nargs * (sizeof (struct type *)));
+ for (ix=1; ix <= nargs; ix++)
+ arg_types[ix-1] = VALUE_TYPE (argvec[ix]);
+
+ (void) find_overload_match (arg_types, nargs, NULL /* no need for name */,
+ 0 /* not method */, 0 /* strict match */,
+ NULL, exp->elts[5].symbol /* the function */,
+ NULL, &symp, NULL);
+
+ /* Now fix the expression being evaluated */
+ exp->elts[5].symbol = symp;
+ argvec[0] = evaluate_subexp_with_coercion (exp, &save_pos1, noside);
+ }
+ else
+ {
+ /* Not C++, or no overload resolution allowed */
+ /* nothing to be done; argvec already correctly set up */
+ }
+ }
+
+ do_call_it:
+
+ if (noside == EVAL_SKIP)
+ goto nosideret;
+ if (noside == EVAL_AVOID_SIDE_EFFECTS)
+ {
+ /* If the return type doesn't look like a function type, call an
+ error. This can happen if somebody tries to turn a variable into
+ a function call. This is here because people often want to
+ call, eg, strcmp, which gdb doesn't know is a function. If
+ gdb isn't asked for it's opinion (ie. through "whatis"),
+ it won't offer it. */
+
+ struct type *ftype =
+ TYPE_TARGET_TYPE (VALUE_TYPE (argvec[0]));
+
+ if (ftype)
+ return allocate_value (TYPE_TARGET_TYPE (VALUE_TYPE (argvec[0])));
+ else
+ error ("Expression of type other than \"Function returning ...\" used as function");
+ }
+ if (argvec[0] == NULL)
+ error ("Cannot evaluate function -- may be inlined");
+ return call_function_by_hand (argvec[0], nargs, argvec + 1);
+ /* pai: FIXME save value from call_function_by_hand, then adjust pc by adjust_fn_pc if +ve */
+
+ case OP_F77_UNDETERMINED_ARGLIST:
+
+ /* Remember that in F77, functions, substring ops and
+ array subscript operations cannot be disambiguated
+ at parse time. We have made all array subscript operations,
+ substring operations as well as function calls come here
+ and we now have to discover what the heck this thing actually was.
+ If it is a function, we process just as if we got an OP_FUNCALL. */
+
+ nargs = longest_to_int (exp->elts[pc+1].longconst);
+ (*pos) += 2;
+
+ /* First determine the type code we are dealing with. */
+ arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+ type = check_typedef (VALUE_TYPE (arg1));
+ code = TYPE_CODE (type);
+
+ switch (code)
+ {
+ case TYPE_CODE_ARRAY:
+ goto multi_f77_subscript;
+
+ case TYPE_CODE_STRING:
+ goto op_f77_substr;
+
+ case TYPE_CODE_PTR:
+ case TYPE_CODE_FUNC:
+ /* It's a function call. */
+ /* Allocate arg vector, including space for the function to be
+ called in argvec[0] and a terminating NULL */
+ argvec = (value_ptr *) alloca (sizeof (value_ptr) * (nargs + 2));
+ argvec[0] = arg1;
+ tem = 1;
+ for (; tem <= nargs; tem++)
+ argvec[tem] = evaluate_subexp_with_coercion (exp, pos, noside);
+ argvec[tem] = 0; /* signal end of arglist */
+ goto do_call_it;
+
+ default:
+ error ("Cannot perform substring on this type");
+ }
+
+ op_f77_substr:
+ /* We have a substring operation on our hands here,
+ let us get the string we will be dealing with */
+
+ /* Now evaluate the 'from' and 'to' */
+
+ arg2 = evaluate_subexp_with_coercion (exp, pos, noside);
+
+ if (nargs < 2)
+ return value_subscript (arg1, arg2);
+
+ arg3 = evaluate_subexp_with_coercion (exp, pos, noside);
+
+ if (noside == EVAL_SKIP)
+ goto nosideret;
+
+ tem2 = value_as_long (arg2);
+ tem3 = value_as_long (arg3);
+
+ return value_slice (arg1, tem2, tem3 - tem2 + 1);
+
+ case OP_COMPLEX:
+ /* We have a complex number, There should be 2 floating
+ point numbers that compose it */
+ arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+ arg2 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+
+ return value_literal_complex (arg1, arg2, builtin_type_f_complex_s16);
+
+ case STRUCTOP_STRUCT:
+ 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
+ {
+ value_ptr temp = arg1;
+ return value_struct_elt (&temp, NULL, &exp->elts[pc + 2].string,
+ NULL, "structure");
+ }
+
+ case STRUCTOP_PTR:
+ 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
+ {
+ value_ptr temp = arg1;
+ return value_struct_elt (&temp, NULL, &exp->elts[pc + 2].string,
+ NULL, "structure pointer");
+ }
+
+ case STRUCTOP_MEMBER:
+ arg1 = evaluate_subexp_for_address (exp, pos, noside);
+ arg2 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+
+ /* With HP aCC, pointers to methods do not point to the function code */
+ if (hp_som_som_object_present &&
+ (TYPE_CODE (VALUE_TYPE (arg2)) == TYPE_CODE_PTR) &&
+ (TYPE_CODE (TYPE_TARGET_TYPE (VALUE_TYPE (arg2))) == TYPE_CODE_METHOD))
+ error ("Pointers to methods not supported with HP aCC"); /* 1997-08-19 */
+
+ mem_offset = value_as_long (arg2);
+ goto handle_pointer_to_member;
+
+ case STRUCTOP_MPTR:
+ arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+ arg2 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+
+ /* With HP aCC, pointers to methods do not point to the function code */
+ if (hp_som_som_object_present &&
+ (TYPE_CODE (VALUE_TYPE (arg2)) == TYPE_CODE_PTR) &&
+ (TYPE_CODE (TYPE_TARGET_TYPE (VALUE_TYPE (arg2))) == TYPE_CODE_METHOD))
+ error ("Pointers to methods not supported with HP aCC"); /* 1997-08-19 */
+
+ mem_offset = value_as_long (arg2);
+
+handle_pointer_to_member:
+ /* HP aCC generates offsets that have bit #29 set; turn it off to get
+ a real offset to the member. */
+ if (hp_som_som_object_present)
+ {
+ if (!mem_offset) /* no bias -> really null */
+ error ("Attempted dereference of null pointer-to-member");
+ mem_offset &= ~0x20000000;
+ }
+ if (noside == EVAL_SKIP)
+ goto nosideret;
+ type = check_typedef (VALUE_TYPE (arg2));
+ if (TYPE_CODE (type) != TYPE_CODE_PTR)
+ goto bad_pointer_to_member;
+ type = check_typedef (TYPE_TARGET_TYPE (type));
+ 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. */
+ 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) + mem_offset);
+ return value_ind (arg3);
+bad_pointer_to_member:
+ error("non-pointer-to-member value used in pointer-to-member construct");
+
+ 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;
+ if (binop_user_defined_p (op, arg1, arg2))
+ return value_x_binop (arg1, arg2, op, OP_NULL, noside);
+ else
+ return value_concat (arg1, arg2);
+
+ case BINOP_ASSIGN:
+ arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+ arg2 = evaluate_subexp (VALUE_TYPE (arg1), exp, pos, noside);
+
+ /* Do special stuff for HP aCC pointers to members */
+ if (hp_som_som_object_present)
+ {
+ /* 1997-08-19 Can't assign HP aCC pointers to methods. No details of
+ the implementation yet; but the pointer appears to point to a code
+ sequence (thunk) in memory -- in any case it is *not* the address
+ of the function as it would be in a naive implementation. */
+ if ((TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_PTR) &&
+ (TYPE_CODE (TYPE_TARGET_TYPE (VALUE_TYPE (arg1))) == TYPE_CODE_METHOD))
+ error ("Assignment to pointers to methods not implemented with HP aCC");
+
+ /* HP aCC pointers to data members require a constant bias */
+ if ((TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_PTR) &&
+ (TYPE_CODE (TYPE_TARGET_TYPE (VALUE_TYPE (arg1))) == TYPE_CODE_MEMBER))
+ {
+ unsigned int * ptr = (unsigned int *) VALUE_CONTENTS (arg2); /* forces evaluation */
+ *ptr |= 0x20000000; /* set 29th bit */
+ }
+ }
+
+ 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, OP_NULL, noside);
+ else
+ return value_assign (arg1, arg2);
+
+ case BINOP_ASSIGN_MODIFY:
+ (*pos) += 2;
+ arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+ arg2 = evaluate_subexp (VALUE_TYPE (arg1), exp, pos, noside);
+ if (noside == EVAL_SKIP || noside == EVAL_AVOID_SIDE_EFFECTS)
+ return arg1;
+ op = exp->elts[pc + 1].opcode;
+ if (binop_user_defined_p (op, arg1, arg2))
+ return value_x_binop (arg1, arg2, BINOP_ASSIGN_MODIFY, op, noside);
+ else if (op == BINOP_ADD)
+ arg2 = value_add (arg1, arg2);
+ else if (op == BINOP_SUB)
+ arg2 = value_sub (arg1, arg2);
+ else
+ arg2 = value_binop (arg1, arg2, op);
+ return value_assign (arg1, arg2);
+
+ case BINOP_ADD:
+ arg1 = evaluate_subexp_with_coercion (exp, pos, noside);
+ arg2 = evaluate_subexp_with_coercion (exp, pos, noside);
+ if (noside == EVAL_SKIP)
+ goto nosideret;
+ if (binop_user_defined_p (op, arg1, arg2))
+ return value_x_binop (arg1, arg2, op, OP_NULL, noside);
+ else
+ return value_add (arg1, arg2);
+
+ case BINOP_SUB:
+ arg1 = evaluate_subexp_with_coercion (exp, pos, noside);
+ arg2 = evaluate_subexp_with_coercion (exp, pos, noside);
+ if (noside == EVAL_SKIP)
+ goto nosideret;
+ if (binop_user_defined_p (op, arg1, arg2))
+ return value_x_binop (arg1, arg2, op, OP_NULL, noside);
+ 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_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, OP_NULL, noside);
+ else
+ if (noside == EVAL_AVOID_SIDE_EFFECTS
+ && (op == BINOP_DIV || op == BINOP_REM || op == BINOP_MOD))
+ return value_zero (VALUE_TYPE (arg1), not_lval);
+ else
+ return value_binop (arg1, arg2, op);
+
+ case BINOP_RANGE:
+ arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+ arg2 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+ if (noside == EVAL_SKIP)
+ goto nosideret;
+ error ("':' operator used in invalid context");
+
+ case BINOP_SUBSCRIPT:
+ arg1 = evaluate_subexp_with_coercion (exp, pos, noside);
+ arg2 = evaluate_subexp_with_coercion (exp, pos, noside);
+ if (noside == EVAL_SKIP)
+ goto nosideret;
+ if (binop_user_defined_p (op, arg1, arg2))
+ return value_x_binop (arg1, arg2, op, OP_NULL, noside);
+ else
+ {
+ /* If the user attempts to subscript something that is not an
+ array or pointer type (like a plain int variable for example),
+ then report this as an error. */
+
+ COERCE_REF (arg1);
+ type = check_typedef (VALUE_TYPE (arg1));
+ if (TYPE_CODE (type) != TYPE_CODE_ARRAY
+ && TYPE_CODE (type) != TYPE_CODE_PTR)
+ {
+ if (TYPE_NAME (type))
+ error ("cannot subscript something of type `%s'",
+ TYPE_NAME (type));
+ else
+ error ("cannot subscript requested type");
+ }
+
+ if (noside == EVAL_AVOID_SIDE_EFFECTS)
+ return value_zero (TYPE_TARGET_TYPE (type), VALUE_LVAL (arg1));
+ else
+ return value_subscript (arg1, arg2);
+ }
+
+ case BINOP_IN:
+ arg1 = evaluate_subexp_with_coercion (exp, pos, noside);
+ arg2 = evaluate_subexp_with_coercion (exp, pos, noside);
+ if (noside == EVAL_SKIP)
+ goto nosideret;
+ return value_in (arg1, arg2);
+
+ 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 (check_typedef (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, noside);
+ }
+ else
+ {
+ arg1 = value_subscript (arg1, arg2);
+ }
+ }
+ return (arg1);
+
+ multi_f77_subscript:
+ {
+ int subscript_array[MAX_FORTRAN_DIMS+1]; /* 1-based array of
+ subscripts, max == 7 */
+ int array_size_array[MAX_FORTRAN_DIMS+1];
+ int ndimensions=1,i;
+ struct type *tmp_type;
+ int offset_item; /* The array offset where the item lives */
+
+ if (nargs > MAX_FORTRAN_DIMS)
+ error ("Too many subscripts for F77 (%d Max)", MAX_FORTRAN_DIMS);
+
+ tmp_type = check_typedef (VALUE_TYPE (arg1));
+ ndimensions = calc_f77_array_dims (type);
+
+ if (nargs != ndimensions)
+ error ("Wrong number of subscripts");
+
+ /* Now that we know we have a legal array subscript expression
+ let us actually find out where this element exists in the array. */
+
+ offset_item = 0;
+ for (i = 1; i <= nargs; i++)
+ {
+ /* Evaluate each subscript, It must be a legal integer in F77 */
+ arg2 = evaluate_subexp_with_coercion (exp, pos, noside);
+
+ /* Fill in the subscript and array size arrays */
+
+ subscript_array[i] = value_as_long (arg2);
+
+ retcode = f77_get_dynamic_upperbound (tmp_type, &upper);
+ if (retcode == BOUND_FETCH_ERROR)
+ error ("Cannot obtain dynamic upper bound");
+
+ retcode = f77_get_dynamic_lowerbound (tmp_type, &lower);
+ if (retcode == BOUND_FETCH_ERROR)
+ error("Cannot obtain dynamic lower bound");
+
+ array_size_array[i] = upper - lower + 1;
+
+ /* Zero-normalize subscripts so that offsetting will work. */
+
+ subscript_array[i] -= lower;
+
+ /* If we are at the bottom of a multidimensional
+ array type then keep a ptr to the last ARRAY
+ type around for use when calling value_subscript()
+ below. This is done because we pretend to value_subscript
+ that we actually have a one-dimensional array
+ of base element type that we apply a simple
+ offset to. */
+
+ if (i < nargs)
+ tmp_type = check_typedef (TYPE_TARGET_TYPE (tmp_type));
+ }
+
+ /* Now let us calculate the offset for this item */
+
+ offset_item = subscript_array[ndimensions];
+
+ for (i = ndimensions - 1; i >= 1; i--)
+ offset_item =
+ array_size_array[i] * offset_item + subscript_array[i];
+
+ /* Construct a value node with the value of the offset */
+
+ arg2 = value_from_longest (builtin_type_f_integer, offset_item);
+
+ /* Let us now play a dirty trick: we will take arg1
+ which is a value node pointing to the topmost level
+ of the multidimensional array-set and pretend
+ that it is actually a array of the final element
+ type, this will ensure that value_subscript()
+ returns the correct type value */
+
+ VALUE_TYPE (arg1) = tmp_type;
+ return value_ind (value_add (value_coerce_array (arg1), arg2));
+ }
+
+ case BINOP_LOGICAL_AND:
+ arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+ if (noside == EVAL_SKIP)
+ {
+ arg2 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+ goto nosideret;
+ }
+
+ oldpos = *pos;
+ arg2 = evaluate_subexp (NULL_TYPE, exp, pos, EVAL_AVOID_SIDE_EFFECTS);
+ *pos = oldpos;
+
+ if (binop_user_defined_p (op, arg1, arg2))
+ {
+ arg2 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+ return value_x_binop (arg1, arg2, op, OP_NULL, noside);
+ }
+ else
+ {
+ tem = value_logical_not (arg1);
+ arg2 = evaluate_subexp (NULL_TYPE, exp, pos,
+ (tem ? EVAL_SKIP : noside));
+ return value_from_longest (LA_BOOL_TYPE,
+ (LONGEST) (!tem && !value_logical_not (arg2)));
+ }
+
+ case BINOP_LOGICAL_OR:
+ arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+ if (noside == EVAL_SKIP)
+ {
+ arg2 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+ goto nosideret;
+ }
+
+ oldpos = *pos;
+ arg2 = evaluate_subexp (NULL_TYPE, exp, pos, EVAL_AVOID_SIDE_EFFECTS);
+ *pos = oldpos;
+
+ if (binop_user_defined_p (op, arg1, arg2))
+ {
+ arg2 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+ return value_x_binop (arg1, arg2, op, OP_NULL, noside);
+ }
+ else
+ {
+ tem = value_logical_not (arg1);
+ arg2 = evaluate_subexp (NULL_TYPE, exp, pos,
+ (!tem ? EVAL_SKIP : noside));
+ return value_from_longest (LA_BOOL_TYPE,
+ (LONGEST) (!tem || !value_logical_not (arg2)));
+ }
+
+ case BINOP_EQUAL:
+ arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+ arg2 = evaluate_subexp (VALUE_TYPE (arg1), exp, pos, noside);
+ if (noside == EVAL_SKIP)
+ goto nosideret;
+ if (binop_user_defined_p (op, arg1, arg2))
+ {
+ return value_x_binop (arg1, arg2, op, OP_NULL, noside);
+ }
+ else
+ {
+ tem = value_equal (arg1, arg2);
+ return value_from_longest (LA_BOOL_TYPE, (LONGEST) tem);
+ }
+
+ case BINOP_NOTEQUAL:
+ arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+ arg2 = evaluate_subexp (VALUE_TYPE (arg1), exp, pos, noside);
+ if (noside == EVAL_SKIP)
+ goto nosideret;
+ if (binop_user_defined_p (op, arg1, arg2))
+ {
+ return value_x_binop (arg1, arg2, op, OP_NULL, noside);
+ }
+ else
+ {
+ tem = value_equal (arg1, arg2);
+ return value_from_longest (LA_BOOL_TYPE, (LONGEST) ! tem);
+ }
+
+ case BINOP_LESS:
+ arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+ arg2 = evaluate_subexp (VALUE_TYPE (arg1), exp, pos, noside);
+ if (noside == EVAL_SKIP)
+ goto nosideret;
+ if (binop_user_defined_p (op, arg1, arg2))
+ {
+ return value_x_binop (arg1, arg2, op, OP_NULL, noside);
+ }
+ else
+ {
+ tem = value_less (arg1, arg2);
+ return value_from_longest (LA_BOOL_TYPE, (LONGEST) tem);
+ }
+
+ case BINOP_GTR:
+ arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+ arg2 = evaluate_subexp (VALUE_TYPE (arg1), exp, pos, noside);
+ if (noside == EVAL_SKIP)
+ goto nosideret;
+ if (binop_user_defined_p (op, arg1, arg2))
+ {
+ return value_x_binop (arg1, arg2, op, OP_NULL, noside);
+ }
+ else
+ {
+ tem = value_less (arg2, arg1);
+ return value_from_longest (LA_BOOL_TYPE, (LONGEST) tem);
+ }
+
+ case BINOP_GEQ:
+ arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+ arg2 = evaluate_subexp (VALUE_TYPE (arg1), exp, pos, noside);
+ if (noside == EVAL_SKIP)
+ goto nosideret;
+ if (binop_user_defined_p (op, arg1, arg2))
+ {
+ return value_x_binop (arg1, arg2, op, OP_NULL, noside);
+ }
+ else
+ {
+ tem = value_less (arg2, arg1) || value_equal (arg1, arg2);
+ return value_from_longest (LA_BOOL_TYPE, (LONGEST) tem);
+ }
+
+ case BINOP_LEQ:
+ arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+ arg2 = evaluate_subexp (VALUE_TYPE (arg1), exp, pos, noside);
+ if (noside == EVAL_SKIP)
+ goto nosideret;
+ if (binop_user_defined_p (op, arg1, arg2))
+ {
+ return value_x_binop (arg1, arg2, op, OP_NULL, noside);
+ }
+ else
+ {
+ tem = value_less (arg1, arg2) || value_equal (arg1, arg2);
+ return value_from_longest (LA_BOOL_TYPE, (LONGEST) tem);
+ }
+
+ case BINOP_REPEAT:
+ arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+ arg2 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+ if (noside == EVAL_SKIP)
+ goto nosideret;
+ type = check_typedef (VALUE_TYPE (arg2));
+ if (TYPE_CODE (type) != TYPE_CODE_INT)
+ error ("Non-integral right operand for \"@\" operator.");
+ if (noside == EVAL_AVOID_SIDE_EFFECTS)
+ {
+ return allocate_repeat_value (VALUE_TYPE (arg1),
+ longest_to_int (value_as_long (arg2)));
+ }
+ else
+ return value_repeat (arg1, longest_to_int (value_as_long (arg2)));
+
+ case BINOP_COMMA:
+ evaluate_subexp (NULL_TYPE, exp, pos, noside);
+ return evaluate_subexp (NULL_TYPE, exp, pos, noside);
+
+ case UNOP_NEG:
+ arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+ if (noside == EVAL_SKIP)
+ goto nosideret;
+ if (unop_user_defined_p (op, arg1))
+ return value_x_unop (arg1, op, noside);
+ else
+ return value_neg (arg1);
+
+ 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 (UNOP_COMPLEMENT, arg1))
+ return value_x_unop (arg1, UNOP_COMPLEMENT, noside);
+ else
+ return value_complement (arg1);
+
+ 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, noside);
+ else
+ return value_from_longest (LA_BOOL_TYPE,
+ (LONGEST) value_logical_not (arg1));
+
+ case UNOP_IND:
+ if (expect_type && TYPE_CODE (expect_type) == TYPE_CODE_PTR)
+ expect_type = TYPE_TARGET_TYPE (check_typedef (expect_type));
+ arg1 = evaluate_subexp (expect_type, exp, pos, noside);
+ if ((TYPE_TARGET_TYPE (VALUE_TYPE (arg1))) &&
+ ((TYPE_CODE (TYPE_TARGET_TYPE (VALUE_TYPE (arg1))) == TYPE_CODE_METHOD) ||
+ (TYPE_CODE (TYPE_TARGET_TYPE (VALUE_TYPE (arg1))) == TYPE_CODE_MEMBER)))
+ error ("Attempt to dereference pointer to member without an object");
+ if (noside == EVAL_SKIP)
+ goto nosideret;
+ if (unop_user_defined_p (op, arg1))
+ return value_x_unop (arg1, op, noside);
+ else if (noside == EVAL_AVOID_SIDE_EFFECTS)
+ {
+ type = check_typedef (VALUE_TYPE (arg1));
+ if (TYPE_CODE (type) == TYPE_CODE_PTR
+ || TYPE_CODE (type) == TYPE_CODE_REF
+ /* In C you can dereference an array to get the 1st elt. */
+ || TYPE_CODE (type) == TYPE_CODE_ARRAY
+ )
+ return value_zero (TYPE_TARGET_TYPE (type),
+ lval_memory);
+ else if (TYPE_CODE (type) == TYPE_CODE_INT)
+ /* GDB allows dereferencing an int. */
+ return value_zero (builtin_type_int, lval_memory);
+ else
+ error ("Attempt to take contents of a non-pointer value.");
+ }
+ return value_ind (arg1);
+
+ case UNOP_ADDR:
+ /* C++: check for and handle pointer to members. */
+
+ op = exp->elts[*pos].opcode;
+
+ if (noside == EVAL_SKIP)
+ {
+ if (op == OP_SCOPE)
+ {
+ 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;
+ }
+ else
+ {
+ value_ptr retvalp = evaluate_subexp_for_address (exp, pos, noside);
+ /* If HP aCC object, use bias for pointers to members */
+ if (hp_som_som_object_present &&
+ (TYPE_CODE (VALUE_TYPE (retvalp)) == TYPE_CODE_PTR) &&
+ (TYPE_CODE (TYPE_TARGET_TYPE (VALUE_TYPE (retvalp))) == TYPE_CODE_MEMBER))
+ {
+ unsigned int * ptr = (unsigned int *) VALUE_CONTENTS (retvalp); /* forces evaluation */
+ *ptr |= 0x20000000; /* set 29th bit */
+ }
+ return retvalp;
+ }
+
+ case UNOP_SIZEOF:
+ if (noside == EVAL_SKIP)
+ {
+ evaluate_subexp (NULL_TYPE, exp, pos, EVAL_SKIP);
+ goto nosideret;
+ }
+ return evaluate_subexp_for_sizeof (exp, pos);
+
+ case UNOP_CAST:
+ (*pos) += 2;
+ type = exp->elts[pc + 1].type;
+ arg1 = evaluate_subexp (type, exp, pos, noside);
+ if (noside == EVAL_SKIP)
+ goto nosideret;
+ if (type != VALUE_TYPE (arg1))
+ arg1 = value_cast (type, arg1);
+ return arg1;
+
+ case UNOP_MEMVAL:
+ (*pos) += 2;
+ arg1 = evaluate_subexp (expect_type, exp, pos, noside);
+ if (noside == EVAL_SKIP)
+ goto nosideret;
+ if (noside == EVAL_AVOID_SIDE_EFFECTS)
+ return value_zero (exp->elts[pc + 1].type, lval_memory);
+ else
+ return value_at_lazy (exp->elts[pc + 1].type,
+ value_as_pointer (arg1),
+ NULL);
+
+ case UNOP_PREINCREMENT:
+ arg1 = evaluate_subexp (expect_type, exp, pos, noside);
+ if (noside == EVAL_SKIP || noside == EVAL_AVOID_SIDE_EFFECTS)
+ return arg1;
+ else if (unop_user_defined_p (op, arg1))
+ {
+ return value_x_unop (arg1, op, noside);
+ }
+ else
+ {
+ arg2 = value_add (arg1, value_from_longest (builtin_type_char,
+ (LONGEST) 1));
+ return value_assign (arg1, arg2);
+ }
+
+ case UNOP_PREDECREMENT:
+ arg1 = evaluate_subexp (expect_type, exp, pos, noside);
+ if (noside == EVAL_SKIP || noside == EVAL_AVOID_SIDE_EFFECTS)
+ return arg1;
+ else if (unop_user_defined_p (op, arg1))
+ {
+ return value_x_unop (arg1, op, noside);
+ }
+ else
+ {
+ arg2 = value_sub (arg1, value_from_longest (builtin_type_char,
+ (LONGEST) 1));
+ return value_assign (arg1, arg2);
+ }
+
+ case UNOP_POSTINCREMENT:
+ arg1 = evaluate_subexp (expect_type, exp, pos, noside);
+ if (noside == EVAL_SKIP || noside == EVAL_AVOID_SIDE_EFFECTS)
+ return arg1;
+ else if (unop_user_defined_p (op, arg1))
+ {
+ return value_x_unop (arg1, op, noside);
+ }
+ else
+ {
+ arg2 = value_add (arg1, value_from_longest (builtin_type_char,
+ (LONGEST) 1));
+ value_assign (arg1, arg2);
+ return arg1;
+ }
+
+ case UNOP_POSTDECREMENT:
+ arg1 = evaluate_subexp (expect_type, exp, pos, noside);
+ if (noside == EVAL_SKIP || noside == EVAL_AVOID_SIDE_EFFECTS)
+ return arg1;
+ else if (unop_user_defined_p (op, arg1))
+ {
+ return value_x_unop (arg1, op, noside);
+ }
+ else
+ {
+ arg2 = value_sub (arg1, value_from_longest (builtin_type_char,
+ (LONGEST) 1));
+ value_assign (arg1, arg2);
+ return arg1;
+ }
+
+ case OP_THIS:
+ (*pos) += 1;
+ return value_of_this (1);
+
+ case OP_TYPE:
+ error ("Attempt to use a type name as an expression");
+
+ default:
+ /* 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 evaluate that kind of expression");
+ }
+
+ nosideret:
+ return value_from_longest (builtin_type_long, (LONGEST) 1);
+}
+
+/* Evaluate a subexpression of EXP, at index *POS,
+ and return the address of that subexpression.
+ Advance *POS over the subexpression.
+ If the subexpression isn't an lvalue, get an error.
+ NOSIDE may be EVAL_AVOID_SIDE_EFFECTS;
+ then only the type of the result need be correct. */
+
+static value_ptr
+evaluate_subexp_for_address (exp, pos, noside)
+ register struct expression *exp;
+ register int *pos;
+ enum noside noside;
+{
+ enum exp_opcode op;
+ register int pc;
+ struct symbol *var;
+
+ pc = (*pos);
+ op = exp->elts[pc].opcode;
+
+ switch (op)
+ {
+ case UNOP_IND:
+ (*pos)++;
+ return evaluate_subexp (NULL_TYPE, exp, pos, noside);
+
+ case UNOP_MEMVAL:
+ (*pos) += 3;
+ return value_cast (lookup_pointer_type (exp->elts[pc + 1].type),
+ evaluate_subexp (NULL_TYPE, exp, pos, noside));
+
+ case OP_VAR_VALUE:
+ 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 (var));
+ enum address_class sym_class = SYMBOL_CLASS (var);
+
+ if (sym_class == LOC_CONST
+ || sym_class == LOC_CONST_BYTES
+ || sym_class == LOC_REGISTER
+ || sym_class == LOC_REGPARM)
+ error ("Attempt to take address of register or constant.");
+
+ return
+ value_zero (type, not_lval);
+ }
+ else
+ return
+ locate_var_value
+ (var,
+ block_innermost_frame (exp->elts[pc + 1].block));
+
+ default:
+ default_case:
+ if (noside == EVAL_AVOID_SIDE_EFFECTS)
+ {
+ value_ptr x = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+ if (VALUE_LVAL (x) == lval_memory)
+ 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 (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 (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.
+
+ */
+
+value_ptr
+evaluate_subexp_with_coercion (exp, pos, noside)
+ register struct expression *exp;
+ register int *pos;
+ enum noside noside;
+{
+ register enum exp_opcode op;
+ register int pc;
+ register value_ptr val;
+ struct symbol *var;
+
+ pc = (*pos);
+ op = exp->elts[pc].opcode;
+
+ switch (op)
+ {
+ case OP_VAR_VALUE:
+ var = exp->elts[pc + 2].symbol;
+ if (TYPE_CODE (check_typedef (SYMBOL_TYPE (var))) == TYPE_CODE_ARRAY
+ && CAST_IS_CONVERSION)
+ {
+ (*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 */
+
+ default:
+ return evaluate_subexp (NULL_TYPE, exp, pos, noside);
+ }
+}
+
+/* Evaluate a subexpression of EXP, at index *POS,
+ and return a value for the size of that subexpression.
+ Advance *POS over the subexpression. */
+
+static value_ptr
+evaluate_subexp_for_sizeof (exp, pos)
+ register struct expression *exp;
+ register int *pos;
+{
+ enum exp_opcode op;
+ register int pc;
+ struct type *type;
+ value_ptr val;
+
+ pc = (*pos);
+ op = exp->elts[pc].opcode;
+
+ switch (op)
+ {
+ /* This case is handled specially
+ so that we avoid creating a value for the result type.
+ If the result type is very big, it's desirable not to
+ create a value unnecessarily. */
+ case UNOP_IND:
+ (*pos)++;
+ val = evaluate_subexp (NULL_TYPE, exp, pos, EVAL_AVOID_SIDE_EFFECTS);
+ type = check_typedef (VALUE_TYPE (val));
+ if (TYPE_CODE (type) != TYPE_CODE_PTR
+ && TYPE_CODE (type) != TYPE_CODE_REF
+ && TYPE_CODE (type) != TYPE_CODE_ARRAY)
+ error ("Attempt to take contents of a non-pointer value.");
+ type = check_typedef (TYPE_TARGET_TYPE (type));
+ return value_from_longest (builtin_type_int, (LONGEST)
+ TYPE_LENGTH (type));
+
+ case UNOP_MEMVAL:
+ (*pos) += 3;
+ type = check_typedef (exp->elts[pc + 1].type);
+ return value_from_longest (builtin_type_int,
+ (LONGEST) TYPE_LENGTH (type));
+
+ case OP_VAR_VALUE:
+ (*pos) += 4;
+ type = check_typedef (SYMBOL_TYPE (exp->elts[pc + 2].symbol));
+ return
+ value_from_longest (builtin_type_int, (LONGEST) TYPE_LENGTH (type));
+
+ default:
+ 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;
+}
+
+int
+calc_f77_array_dims (array_type)
+ struct type *array_type;
+{
+ int ndimen = 1;
+ struct type *tmp_type;
+
+ if ((TYPE_CODE(array_type) != TYPE_CODE_ARRAY))
+ error ("Can't get dimensions for a non-array type");
+
+ tmp_type = array_type;
+
+ while ((tmp_type = TYPE_TARGET_TYPE (tmp_type)))
+ {
+ if (TYPE_CODE (tmp_type) == TYPE_CODE_ARRAY)
+ ++ndimen;
+ }
+ return ndimen;
+}
diff --git a/gdb/exc_request.defs b/gdb/exc_request.defs
new file mode 100644
index 00000000000..9b5ed2ee421
--- /dev/null
+++ b/gdb/exc_request.defs
@@ -0,0 +1,51 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1993,1991,1990,1989,1988,1987 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+
+/*
+ * Abstract:
+ * MiG definitions file for Mach exception interface (request half).
+ */
+
+subsystem exc 2400;
+
+#include <mach/std_types.defs>
+
+#ifdef USERPREFIX
+userprefix USERPREFIX;
+#endif
+
+#ifdef SERVERPREFIX
+serverprefix SERVERPREFIX;
+#endif
+
+simpleroutine exception_raise_request (
+ exception_port : mach_port_t;
+ replyport reply : mach_port_send_once_t;
+ thread : mach_port_t;
+ task : mach_port_t;
+ exception : integer_t;
+ code : integer_t;
+ subcode : integer_t);
diff --git a/gdb/exec.c b/gdb/exec.c
new file mode 100644
index 00000000000..87aed010f01
--- /dev/null
+++ b/gdb/exec.c
@@ -0,0 +1,762 @@
+/* Work with executable files, for GDB.
+ Copyright 1988, 1989, 1991, 1992, 1993, 1994, 1997, 1998
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "frame.h"
+#include "inferior.h"
+#include "target.h"
+#include "gdbcmd.h"
+#include "language.h"
+#include "symfile.h"
+#include "objfiles.h"
+
+#ifdef USG
+#include <sys/types.h>
+#endif
+
+#include <fcntl.h>
+#include "gdb_string.h"
+
+#include "gdbcore.h"
+
+#include <ctype.h>
+#include "gdb_stat.h"
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
+
+#include "xcoffsolib.h"
+
+struct vmap *map_vmap PARAMS ((bfd *, bfd *));
+
+void (*file_changed_hook) PARAMS ((char *));
+
+/* 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 *));
+
+static void bfdsec_to_vmap PARAMS ((bfd *, sec_ptr, PTR));
+
+static int ignore PARAMS ((CORE_ADDR, char *));
+
+static void init_exec_ops PARAMS ((void));
+
+void _initialize_exec PARAMS ((void));
+
+extern int info_verbose;
+
+/* The target vector for executable files. */
+
+struct target_ops exec_ops;
+
+/* 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 */
+
+#ifndef NEED_TEXT_START_END
+#define NEED_TEXT_START_END (0)
+#endif
+CORE_ADDR text_start = 0;
+CORE_ADDR text_end = 0;
+
+struct vmap *vmap;
+
+/* ARGSUSED */
+static void
+exec_close (quitting)
+ int quitting;
+{
+ int need_symtab_cleanup = 0;
+ struct vmap *vp, *nxt;
+
+ for (nxt = vmap; nxt != NULL; )
+ {
+ vp = nxt;
+ nxt = vp->nxt;
+
+ /* if there is an objfile associated with this bfd,
+ free_objfile() will do proper cleanup of objfile *and* bfd. */
+
+ if (vp->objfile)
+ {
+ free_objfile (vp->objfile);
+ need_symtab_cleanup = 1;
+ }
+ else if (vp->bfd != exec_bfd)
+ /* FIXME-leak: We should be freeing vp->name too, I think. */
+ if (!bfd_close (vp->bfd))
+ warning ("cannot close \"%s\": %s",
+ vp->name, bfd_errmsg (bfd_get_error ()));
+
+ /* FIXME: This routine is #if 0'd in symfile.c. What should we
+ be doing here? Should we just free everything in
+ vp->objfile->symtabs? Should free_objfile do that?
+ FIXME-as-well: free_objfile already free'd vp->name, so it isn't
+ valid here. */
+ free_named_symtabs (vp->name);
+ free (vp);
+ }
+
+ vmap = NULL;
+
+ if (exec_bfd)
+ {
+ char *name = bfd_get_filename (exec_bfd);
+
+ if (!bfd_close (exec_bfd))
+ warning ("cannot close \"%s\": %s",
+ name, bfd_errmsg (bfd_get_error ()));
+ 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.
+
+ This function is intended to be behave essentially the same
+ as exec_file_command, except that the latter will detect when
+ a target is being debugged, and will ask the user whether it
+ should be shut down first. (If the answer is "no", then the
+ new file is ignored.)
+
+ This file is used by exec_file_command, to do the work of opening
+ and processing the exec file after any prompting has happened.
+
+ And, it is used by child_attach, when the attach command was
+ given a pid but not a exec pathname, and the attach command could
+ figure out the pathname from the pid. (In this case, we shouldn't
+ ask the user whether the current target should be shut down --
+ we're supplying the exec pathname late for good reason.) */
+
+void
+exec_file_attach (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ char **argv;
+ char *filename;
+
+ /* 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. */
+
+ argv = buildargv (args);
+ if (argv == NULL)
+ nomem (0);
+
+ make_cleanup ((make_cleanup_func) 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 defined(__GO32__) || defined(_WIN32)
+ if (scratch_chan < 0)
+ {
+ char *exename = alloca (strlen (filename) + 5);
+ strcat (strcpy (exename, filename), ".exe");
+ scratch_chan = openp (getenv ("PATH"), 1, exename, write_files ?
+ O_RDWR|O_BINARY : O_RDONLY|O_BINARY, 0, &scratch_pathname);
+ }
+#endif
+ if (scratch_chan < 0)
+ perror_with_name (filename);
+ exec_bfd = bfd_fdopenr (scratch_pathname, gnutarget, scratch_chan);
+
+ if (!exec_bfd)
+ error ("\"%s\": could not open as an executable file: %s",
+ scratch_pathname, bfd_errmsg (bfd_get_error ()));
+
+ /* At this point, scratch_pathname and exec_bfd->name both point to the
+ same malloc'd string. However exec_close() will attempt to free it
+ via the exec_bfd->name pointer, so we need to make another copy and
+ leave exec_bfd as the new owner of the original copy. */
+ scratch_pathname = strdup (scratch_pathname);
+ make_cleanup (free, scratch_pathname);
+
+ if (!bfd_check_format (exec_bfd, bfd_object))
+ {
+ /* Make sure to close exec_bfd, or else "run" might try to use
+ it. */
+ exec_close (0);
+ error ("\"%s\": not in executable format: %s",
+ scratch_pathname, bfd_errmsg (bfd_get_error ()));
+ }
+
+ /* FIXME - This should only be run for RS6000, but the ifdef is a poor
+ way to accomplish. */
+#ifdef IBM6000_TARGET
+ /* Setup initial vmap. */
+
+ map_vmap (exec_bfd, 0);
+ if (vmap == NULL)
+ {
+ /* Make sure to close exec_bfd, or else "run" might try to use
+ it. */
+ exec_close (0);
+ error ("\"%s\": can't find the file sections: %s",
+ scratch_pathname, bfd_errmsg (bfd_get_error ()));
+ }
+#endif /* IBM6000_TARGET */
+
+ if (build_section_table (exec_bfd, &exec_ops.to_sections,
+ &exec_ops.to_sections_end))
+ {
+ /* Make sure to close exec_bfd, or else "run" might try to use
+ it. */
+ exec_close (0);
+ error ("\"%s\": can't find the file sections: %s",
+ scratch_pathname, bfd_errmsg (bfd_get_error ()));
+ }
+
+ /* text_end is sometimes used for where to put call dummies. A
+ few ports use these for other purposes too. */
+ if (NEED_TEXT_START_END)
+ {
+ 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. */
+ /* FIXME: The comment above does not match the code. The
+ code checks for sections with are either code *or*
+ readonly. */
+ 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->the_bfd_section)
+ & (SEC_CODE | SEC_READONLY))
+ {
+ if (text_start > p->addr)
+ text_start = p->addr;
+ if (text_end < p->endaddr)
+ text_end = p->endaddr;
+ }
+ }
+
+ validate_files ();
+
+ set_gdbarch_from_file (exec_bfd);
+
+ 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_unfiltered ("No executable file now.\n");
+}
+
+/* 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);
+
+ exec_file_attach (args, from_tty);
+}
+
+/* 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);
+ if (file_changed_hook)
+ file_changed_hook (arg);
+}
+
+
+/* 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);
+ if (!(aflag & SEC_ALLOC))
+ return;
+ if (0 == bfd_section_size (abfd, asect))
+ return;
+ (*table_pp)->bfd = abfd;
+ (*table_pp)->the_bfd_section = 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;
+}
+
+static void
+bfdsec_to_vmap(abfd, sect, arg3)
+ bfd *abfd;
+ sec_ptr sect;
+ PTR arg3;
+{
+ struct vmap_and_bfd *vmap_bfd = (struct vmap_and_bfd *) arg3;
+ struct vmap *vp;
+
+ vp = vmap_bfd->pvmap;
+
+ if ((bfd_get_section_flags (abfd, sect) & SEC_LOAD) == 0)
+ return;
+
+ if (STREQ (bfd_section_name (abfd, sect), ".text"))
+ {
+ vp->tstart = bfd_section_vma (abfd, sect);
+ vp->tend = vp->tstart + bfd_section_size (abfd, sect);
+ vp->tvma = bfd_section_vma (abfd, sect);
+ vp->toffs = sect->filepos;
+ }
+ else if (STREQ (bfd_section_name (abfd, sect), ".data"))
+ {
+ vp->dstart = bfd_section_vma (abfd, sect);
+ vp->dend = vp->dstart + bfd_section_size (abfd, sect);
+ vp->dvma = bfd_section_vma (abfd, sect);
+ }
+ /* Silently ignore other types of sections. (FIXME?) */
+}
+
+/* Make a vmap for ABFD which might be a member of the archive ARCH.
+ Return the new vmap. */
+
+struct vmap *
+map_vmap (abfd, arch)
+ bfd *abfd;
+ bfd *arch;
+{
+ struct vmap_and_bfd vmap_bfd;
+ struct vmap *vp, **vpp;
+
+ vp = (struct vmap *) xmalloc (sizeof (*vp));
+ memset ((char *) vp, '\0', sizeof (*vp));
+ vp->nxt = 0;
+ vp->bfd = abfd;
+ vp->name = bfd_get_filename (arch ? arch : abfd);
+ vp->member = arch ? bfd_get_filename (abfd) : "";
+
+ vmap_bfd.pbfd = arch;
+ vmap_bfd.pvmap = vp;
+ bfd_map_over_sections (abfd, bfdsec_to_vmap, &vmap_bfd);
+
+ /* Find the end of the list and append. */
+ for (vpp = &vmap; *vpp; vpp = &(*vpp)->nxt)
+ ;
+ *vpp = vp;
+
+ return vp;
+}
+
+/* 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));
+ asection *section;
+
+ if (len <= 0)
+ abort();
+
+ if (overlay_debugging)
+ {
+ section = find_pc_overlay (memaddr);
+ if (pc_in_unmapped_range (memaddr, section))
+ memaddr = overlay_mapped_address (memaddr, section);
+ }
+
+ memend = memaddr + len;
+ xfer_fn = write ? bfd_set_section_contents : bfd_get_section_contents;
+ nextsectaddr = memend;
+
+#if 0 /* Stu's implementation */
+/* If a section has been specified, try to use it. Note that we cannot use the
+ specified section directly. This is because it usually comes from the
+ symbol file, which may be different from the exec or core file. Instead, we
+ have to lookup the specified section by name in the bfd associated with
+ to_sections. */
+
+ if (target_memory_bfd_section)
+ {
+ asection *s;
+ bfd *abfd;
+ asection *target_section;
+ bfd *target_bfd;
+
+ s = target_memory_bfd_section;
+ abfd = s->owner;
+
+ target_bfd = target->to_sections->bfd;
+ target_section = bfd_get_section_by_name (target_bfd, bfd_section_name (abfd, s));
+
+ if (target_section)
+ {
+ bfd_vma sec_addr;
+ bfd_size_type sec_size;
+
+ sec_addr = bfd_section_vma (target_bfd, target_section);
+ sec_size = target_section->_raw_size;
+
+ /* Make sure the requested memory starts inside the section. */
+
+ if (memaddr >= sec_addr
+ && memaddr < sec_addr + sec_size)
+ {
+ /* Cut back length in case request overflows the end of the section. */
+ len = min (len, sec_addr + sec_size - memaddr);
+
+ res = xfer_fn (target_bfd, target_section, myaddr, memaddr - sec_addr, len);
+
+ return res ? len : 0;
+ }
+ }
+ }
+#endif /* 0, Stu's implementation */
+ for (p = target->to_sections; p < target->to_sections_end; p++)
+ {
+ if (overlay_debugging && section && p->the_bfd_section &&
+ strcmp (section->name, p->the_bfd_section->name) != 0)
+ continue; /* not the section we need */
+ if (memaddr >= p->addr)
+ if (memend <= p->endaddr)
+ {
+ /* Entire transfer is within this section. */
+ res = xfer_fn (p->bfd, p->the_bfd_section, myaddr,
+ memaddr - p->addr, len);
+ return (res != 0) ? len : 0;
+ }
+ else if (memaddr >= p->endaddr)
+ {
+ /* 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->the_bfd_section, myaddr,
+ memaddr - p->addr, len);
+ return (res != 0) ? len : 0;
+ }
+ else
+ nextsectaddr = min (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));
+ if (abfd == exec_bfd)
+ {
+ printf_filtered ("\tEntry point: ");
+ print_address_numeric (bfd_get_start_address (abfd), 1, gdb_stdout);
+ printf_filtered ("\n");
+ }
+ for (p = t->to_sections; p < t->to_sections_end; p++)
+ {
+ /* FIXME-32x64 need a print_address_numeric with field width */
+ 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->the_bfd_section->filepos, "08l"));
+ printf_filtered (" is %s", bfd_section_name (p->bfd, p->the_bfd_section));
+ 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);
+
+ if (vmap)
+ {
+ struct vmap *vp;
+
+ printf_unfiltered ("\tMapping info for file `%s'.\n", vmap->name);
+ printf_unfiltered ("\t %8.8s %8.8s %8.8s %8.8s %8.8s %s\n",
+ "tstart", "tend", "dstart", "dend", "section",
+ "file(member)");
+
+ for (vp = vmap; vp; vp = vp->nxt)
+ printf_unfiltered ("\t0x%8.8x 0x%8.8x 0x%8.8x 0x%8.8x %s%s%s%s\n",
+ vp->tstart, vp->tend, vp->dstart, vp->dend, vp->name,
+ *vp->member ? "(" : "", vp->member,
+ *vp->member ? ")" : "");
+ }
+}
+
+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->the_bfd_section), seclen)
+ && bfd_section_name (exec_bfd, p->the_bfd_section)[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;
+}
+
+/* Fill in the exec file target vector. Very few entries need to be
+ defined. */
+
+void
+init_exec_ops ()
+{
+ exec_ops.to_shortname = "exec";
+ exec_ops.to_longname = "Local exec file";
+ exec_ops.to_doc = "Use an executable file as a target.\n\
+Specify the filename of the executable file.";
+ exec_ops.to_open = exec_file_command;
+ exec_ops.to_close = exec_close;
+ exec_ops.to_attach = find_default_attach;
+ exec_ops.to_require_attach = find_default_require_attach;
+ exec_ops.to_require_detach = find_default_require_detach;
+ exec_ops.to_xfer_memory = xfer_memory;
+ exec_ops.to_files_info = exec_files_info;
+ exec_ops.to_insert_breakpoint = ignore;
+ exec_ops.to_remove_breakpoint = ignore;
+ exec_ops.to_create_inferior = find_default_create_inferior;
+ exec_ops.to_clone_and_follow_inferior = find_default_clone_and_follow_inferior;
+ exec_ops.to_stratum = file_stratum;
+ exec_ops.to_has_memory = 1;
+ exec_ops.to_magic = OPS_MAGIC;
+}
+
+void
+_initialize_exec ()
+{
+ struct cmd_list_element *c;
+
+ init_exec_ops ();
+
+ if (!dbx_commands)
+ {
+ 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/gdb/expprint.c b/gdb/expprint.c
new file mode 100644
index 00000000000..939919a425a
--- /dev/null
+++ b/gdb/expprint.c
@@ -0,0 +1,903 @@
+/* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "symtab.h"
+#include "gdbtypes.h"
+#include "expression.h"
+#include "value.h"
+#include "language.h"
+#include "parser-defs.h"
+
+#ifdef HAVE_CTYPE_H
+#include <ctype.h>
+#endif
+
+/* Prototypes for local functions */
+
+static void
+print_subexp PARAMS ((struct expression *, int *, GDB_FILE *, enum precedence));
+
+void
+print_expression (exp, stream)
+ struct expression *exp;
+ GDB_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;
+ GDB_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_ptr 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",
+ REGISTER_NAME (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_NAME:
+ case OP_EXPRSTRING:
+ nargs = longest_to_int (exp -> elts[pc + 1].longconst);
+ (*pos) += 3 + BYTES_TO_EXP_ELEM (nargs + 1);
+ fputs_filtered (&exp->elts[pc + 2].string, 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, 1, 0);
+ return;
+
+ case OP_BITSTRING:
+ nargs = longest_to_int (exp -> elts[pc + 1].longconst);
+ (*pos)
+ += 3 + BYTES_TO_EXP_ELEM ((nargs + HOST_CHAR_BIT - 1) / HOST_CHAR_BIT);
+ fprintf_unfiltered (stream, "B'<unimplemented>'");
+ return;
+
+ 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, 1, 0);
+ (*pos) = pc;
+ }
+ else
+ {
+ int is_chill = exp->language_defn->la_language == language_chill;
+ fputs_filtered (is_chill ? " [" : " {", stream);
+ for (tem = 0; tem < nargs; tem++)
+ {
+ if (tem != 0)
+ {
+ fputs_filtered (", ", stream);
+ }
+ print_subexp (exp, pos, stream, PREC_ABOVE_COMMA);
+ }
+ fputs_filtered (is_chill ? "]" : "}", stream);
+ }
+ return;
+
+ case OP_LABELED:
+ tem = longest_to_int (exp->elts[pc + 1].longconst);
+ (*pos) += 3 + BYTES_TO_EXP_ELEM (tem + 1);
+
+ if (exp->language_defn->la_language == language_chill)
+ {
+ fputs_filtered (".", stream);
+ fputs_filtered (&exp->elts[pc + 2].string, stream);
+ fputs_filtered (exp->elts[*pos].opcode == OP_LABELED ? ", "
+ : ": ",
+ stream);
+ }
+ else
+ {
+ /* Gcc support both these syntaxes. Unsure which is preferred. */
+#if 1
+ fputs_filtered (&exp->elts[pc + 2].string, stream);
+ fputs_filtered (": ", stream);
+#else
+ fputs_filtered (".", stream);
+ fputs_filtered (&exp->elts[pc + 2].string, stream);
+ fputs_filtered ("=", stream);
+#endif
+ }
+ print_subexp (exp, pos, stream, PREC_SUFFIX);
+ 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 TERNOP_SLICE:
+ case TERNOP_SLICE_COUNT:
+ print_subexp (exp, pos, stream, PREC_SUFFIX);
+ fputs_filtered ("(", stream);
+ print_subexp (exp, pos, stream, PREC_ABOVE_COMMA);
+ fputs_filtered (opcode == TERNOP_SLICE ? " : " : " UP ", stream);
+ print_subexp (exp, pos, stream, PREC_ABOVE_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,
+ NULL);
+ 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_unfiltered (stream, " [");
+ for (tem = 0; tem < nargs; tem++)
+ {
+ if (tem != 0)
+ fprintf_unfiltered (stream, ", ");
+ print_subexp (exp, pos, stream, PREC_ABOVE_COMMA);
+ }
+ fprintf_unfiltered (stream, "]");
+ return;
+
+ case BINOP_VAL:
+ (*pos)+=2;
+ fprintf_unfiltered(stream,"VAL(");
+ type_print(exp->elts[pc+1].type,"",stream,0);
+ fprintf_unfiltered(stream,",");
+ print_subexp(exp,pos,stream,PREC_PREFIX);
+ fprintf_unfiltered(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");
+ }
+
+ /* Note that PREC_BUILTIN will always emit parentheses. */
+ if ((int) myprec < (int) prec)
+ fputs_filtered ("(", stream);
+ if ((int) opcode > (int) BINOP_END)
+ {
+ if (assoc)
+ {
+ /* Unary postfix operator. */
+ print_subexp (exp, pos, stream, PREC_SUFFIX);
+ fputs_filtered (op_str, stream);
+ }
+ else
+ {
+ /* Unary prefix operator. */
+ fputs_filtered (op_str, stream);
+ if (myprec == PREC_BUILTIN_FUNCTION)
+ fputs_filtered ("(", stream);
+ print_subexp (exp, pos, stream, PREC_PREFIX);
+ if (myprec == PREC_BUILTIN_FUNCTION)
+ fputs_filtered (")", stream);
+ }
+ }
+ 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);
+}
+
+/* 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 MAINTENANCE_CMDS
+
+/* Support for dumping the raw data from expressions in a human readable
+ form. */
+
+static char * op_name PARAMS ((int opcode));
+
+static char *
+op_name (opcode)
+ int opcode;
+{
+ switch (opcode)
+ {
+ default:
+ {
+ static char buf[30];
+
+ sprintf (buf, "<unknown %d>", opcode);
+ return buf;
+ }
+ case OP_NULL: return "OP_NULL";
+ case BINOP_ADD: return "BINOP_ADD";
+ case BINOP_SUB: return "BINOP_SUB";
+ case BINOP_MUL: return "BINOP_MUL";
+ case BINOP_DIV: return "BINOP_DIV";
+ case BINOP_REM: return "BINOP_REM";
+ case BINOP_MOD: return "BINOP_MOD";
+ case BINOP_LSH: return "BINOP_LSH";
+ case BINOP_RSH: return "BINOP_RSH";
+ case BINOP_LOGICAL_AND: return "BINOP_LOGICAL_AND";
+ case BINOP_LOGICAL_OR: return "BINOP_LOGICAL_OR";
+ case BINOP_BITWISE_AND: return "BINOP_BITWISE_AND";
+ case BINOP_BITWISE_IOR: return "BINOP_BITWISE_IOR";
+ case BINOP_BITWISE_XOR: return "BINOP_BITWISE_XOR";
+ case BINOP_EQUAL: return "BINOP_EQUAL";
+ case BINOP_NOTEQUAL: return "BINOP_NOTEQUAL";
+ case BINOP_LESS: return "BINOP_LESS";
+ case BINOP_GTR: return "BINOP_GTR";
+ case BINOP_LEQ: return "BINOP_LEQ";
+ case BINOP_GEQ: return "BINOP_GEQ";
+ case BINOP_REPEAT: return "BINOP_REPEAT";
+ case BINOP_ASSIGN: return "BINOP_ASSIGN";
+ case BINOP_COMMA: return "BINOP_COMMA";
+ case BINOP_SUBSCRIPT: return "BINOP_SUBSCRIPT";
+ case MULTI_SUBSCRIPT: return "MULTI_SUBSCRIPT";
+ case BINOP_EXP: return "BINOP_EXP";
+ case BINOP_MIN: return "BINOP_MIN";
+ case BINOP_MAX: return "BINOP_MAX";
+ case BINOP_SCOPE: return "BINOP_SCOPE";
+ case STRUCTOP_MEMBER: return "STRUCTOP_MEMBER";
+ case STRUCTOP_MPTR: return "STRUCTOP_MPTR";
+ case BINOP_INTDIV: return "BINOP_INTDIV";
+ case BINOP_ASSIGN_MODIFY: return "BINOP_ASSIGN_MODIFY";
+ case BINOP_VAL: return "BINOP_VAL";
+ case BINOP_INCL: return "BINOP_INCL";
+ case BINOP_EXCL: return "BINOP_EXCL";
+ case BINOP_CONCAT: return "BINOP_CONCAT";
+ case BINOP_RANGE: return "BINOP_RANGE";
+ case BINOP_END: return "BINOP_END";
+ case TERNOP_COND: return "TERNOP_COND";
+ case TERNOP_SLICE: return "TERNOP_SLICE";
+ case TERNOP_SLICE_COUNT: return "TERNOP_SLICE_COUNT";
+ case OP_LONG: return "OP_LONG";
+ case OP_DOUBLE: return "OP_DOUBLE";
+ case OP_VAR_VALUE: return "OP_VAR_VALUE";
+ case OP_LAST: return "OP_LAST";
+ case OP_REGISTER: return "OP_REGISTER";
+ case OP_INTERNALVAR: return "OP_INTERNALVAR";
+ case OP_FUNCALL: return "OP_FUNCALL";
+ case OP_STRING: return "OP_STRING";
+ case OP_BITSTRING: return "OP_BITSTRING";
+ case OP_ARRAY: return "OP_ARRAY";
+ case UNOP_CAST: return "UNOP_CAST";
+ case UNOP_MEMVAL: return "UNOP_MEMVAL";
+ case UNOP_NEG: return "UNOP_NEG";
+ case UNOP_LOGICAL_NOT: return "UNOP_LOGICAL_NOT";
+ case UNOP_COMPLEMENT: return "UNOP_COMPLEMENT";
+ case UNOP_IND: return "UNOP_IND";
+ case UNOP_ADDR: return "UNOP_ADDR";
+ case UNOP_PREINCREMENT: return "UNOP_PREINCREMENT";
+ case UNOP_POSTINCREMENT: return "UNOP_POSTINCREMENT";
+ case UNOP_PREDECREMENT: return "UNOP_PREDECREMENT";
+ case UNOP_POSTDECREMENT: return "UNOP_POSTDECREMENT";
+ case UNOP_SIZEOF: return "UNOP_SIZEOF";
+ case UNOP_LOWER: return "UNOP_LOWER";
+ case UNOP_UPPER: return "UNOP_UPPER";
+ case UNOP_LENGTH: return "UNOP_LENGTH";
+ case UNOP_PLUS: return "UNOP_PLUS";
+ case UNOP_CAP: return "UNOP_CAP";
+ case UNOP_CHR: return "UNOP_CHR";
+ case UNOP_ORD: return "UNOP_ORD";
+ case UNOP_ABS: return "UNOP_ABS";
+ case UNOP_FLOAT: return "UNOP_FLOAT";
+ case UNOP_HIGH: return "UNOP_HIGH";
+ case UNOP_MAX: return "UNOP_MAX";
+ case UNOP_MIN: return "UNOP_MIN";
+ case UNOP_ODD: return "UNOP_ODD";
+ case UNOP_TRUNC: return "UNOP_TRUNC";
+ case OP_BOOL: return "OP_BOOL";
+ case OP_M2_STRING: return "OP_M2_STRING";
+ case STRUCTOP_STRUCT: return "STRUCTOP_STRUCT";
+ case STRUCTOP_PTR: return "STRUCTOP_PTR";
+ case OP_THIS: return "OP_THIS";
+ case OP_SCOPE: return "OP_SCOPE";
+ case OP_TYPE: return "OP_TYPE";
+ case OP_LABELED: return "OP_LABELED";
+ }
+}
+
+void
+dump_prefix_expression (exp, stream, note)
+ struct expression *exp;
+ GDB_FILE *stream;
+ char *note;
+{
+ int elt;
+ char *opcode_name;
+ char *eltscan;
+ int eltsize;
+
+ fprintf_filtered (stream, "Dump of expression @ ");
+ gdb_print_address (exp, stream);
+ fprintf_filtered (stream, ", %s:\nExpression: `", note);
+ if (exp->elts[0].opcode != OP_TYPE)
+ print_expression (exp, stream);
+ else
+ fprintf_filtered (stream, "Type printing not yet supported....");
+ fprintf_filtered (stream, "'\n\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);
+ opcode_name = op_name (exp -> elts[elt].opcode);
+
+ fprintf_filtered (stream, "%20s ", opcode_name);
+ print_longest (stream, 'd', 0, exp -> elts[elt].longconst);
+ fprintf_filtered (stream, " ");
+
+ 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");
+ }
+}
+
+static int dump_subexp PARAMS ((struct expression *exp, GDB_FILE *stream, int elt));
+
+static int
+dump_subexp (exp, stream, elt)
+ struct expression *exp;
+ GDB_FILE *stream;
+ int elt;
+{
+ static int indent = 0;
+ int i;
+
+ fprintf_filtered (stream, "\n");
+ fprintf_filtered (stream, "\t%5d ", elt);
+
+ for (i = 1; i <= indent; i++)
+ fprintf_filtered (stream, " ");
+ indent += 2;
+
+ fprintf_filtered (stream, "%-20s ", op_name (exp->elts[elt].opcode));
+
+ switch (exp -> elts[elt++].opcode)
+ {
+ case TERNOP_COND:
+ case TERNOP_SLICE:
+ case TERNOP_SLICE_COUNT:
+ elt = dump_subexp (exp, stream, elt);
+ case BINOP_ADD:
+ case BINOP_SUB:
+ case BINOP_MUL:
+ case BINOP_DIV:
+ case BINOP_REM:
+ case BINOP_MOD:
+ case BINOP_LSH:
+ case BINOP_RSH:
+ case BINOP_LOGICAL_AND:
+ case BINOP_LOGICAL_OR:
+ case BINOP_BITWISE_AND:
+ case BINOP_BITWISE_IOR:
+ case BINOP_BITWISE_XOR:
+ case BINOP_EQUAL:
+ case BINOP_NOTEQUAL:
+ case BINOP_LESS:
+ case BINOP_GTR:
+ case BINOP_LEQ:
+ case BINOP_GEQ:
+ case BINOP_REPEAT:
+ case BINOP_ASSIGN:
+ case BINOP_COMMA:
+ case BINOP_SUBSCRIPT:
+ case BINOP_EXP:
+ case BINOP_MIN:
+ case BINOP_MAX:
+ case BINOP_SCOPE:
+ case BINOP_INTDIV:
+ case BINOP_ASSIGN_MODIFY:
+ case BINOP_VAL:
+ case BINOP_INCL:
+ case BINOP_EXCL:
+ case BINOP_CONCAT:
+ case BINOP_IN:
+ case BINOP_RANGE:
+ case BINOP_END:
+ elt = dump_subexp (exp, stream, elt);
+ case UNOP_NEG:
+ case UNOP_LOGICAL_NOT:
+ case UNOP_COMPLEMENT:
+ case UNOP_IND:
+ case UNOP_ADDR:
+ case UNOP_PREINCREMENT:
+ case UNOP_POSTINCREMENT:
+ case UNOP_PREDECREMENT:
+ case UNOP_POSTDECREMENT:
+ case UNOP_SIZEOF:
+ case UNOP_PLUS:
+ case UNOP_CAP:
+ case UNOP_CHR:
+ case UNOP_ORD:
+ case UNOP_ABS:
+ case UNOP_FLOAT:
+ case UNOP_HIGH:
+ case UNOP_MAX:
+ case UNOP_MIN:
+ case UNOP_ODD:
+ case UNOP_TRUNC:
+ case UNOP_LOWER:
+ case UNOP_UPPER:
+ case UNOP_LENGTH:
+ case UNOP_CARD:
+ case UNOP_CHMAX:
+ case UNOP_CHMIN:
+ elt = dump_subexp (exp, stream, elt);
+ break;
+ case OP_LONG:
+ fprintf_filtered (stream, "Type @0x%x (", exp->elts[elt].type);
+ type_print (exp->elts[elt].type, NULL, stream, 0);
+ fprintf_filtered (stream, "), value %ld (0x%lx)",
+ (long)exp->elts[elt+1].longconst,
+ (long)exp->elts[elt+1].longconst);
+ elt += 3;
+ break;
+ case OP_DOUBLE:
+ fprintf_filtered (stream, "Type @0x%x (", exp->elts[elt].type);
+ type_print (exp->elts[elt].type, NULL, stream, 0);
+ fprintf_filtered (stream, "), value %g",
+ (double)exp->elts[elt+1].doubleconst);
+ elt += 3;
+ break;
+ case OP_VAR_VALUE:
+ fprintf_filtered (stream, "Block @0x%x, symbol @0x%x (%s)",
+ exp->elts[elt].block,
+ exp->elts[elt+1].symbol,
+ SYMBOL_NAME (exp->elts[elt+1].symbol));
+ elt += 3;
+ break;
+ case OP_LAST:
+ fprintf_filtered (stream, "History element %ld",
+ (long)exp->elts[elt].longconst);
+ elt += 2;
+ break;
+ case OP_REGISTER:
+ fprintf_filtered (stream, "Register %ld",
+ (long)exp->elts[elt].longconst);
+ elt += 2;
+ break;
+ case OP_INTERNALVAR:
+ fprintf_filtered (stream, "Internal var @0x%x (%s)",
+ exp->elts[elt].internalvar,
+ exp->elts[elt].internalvar->name);
+ elt += 2;
+ break;
+ case OP_FUNCALL:
+ {
+ int nargs;
+
+ nargs = longest_to_int (exp->elts[elt].longconst);
+
+ fprintf_filtered (stream, "Number of args: %d", nargs);
+ elt += 2;
+
+ for (i = 1; i <= nargs + 1; i++)
+ elt = dump_subexp (exp, stream, elt);
+ }
+ break;
+ case OP_ARRAY:
+ {
+ int lower, upper;
+ int i;
+
+ lower = longest_to_int (exp->elts[elt].longconst);
+ upper = longest_to_int (exp->elts[elt + 1].longconst);
+
+ fprintf_filtered (stream, "Bounds [%d:%d]", lower, upper);
+ elt += 3;
+
+ for (i = 1; i <= upper - lower + 1; i++)
+ elt = dump_subexp (exp, stream, elt);
+ }
+ break;
+ case UNOP_MEMVAL:
+ case UNOP_CAST:
+ fprintf_filtered (stream, "Type @0x%x (",
+ exp->elts[elt].type);
+ type_print (exp->elts[elt].type, NULL, stream, 0);
+ fprintf_filtered (stream, ")");
+ elt = dump_subexp (exp, stream, elt + 2);
+ break;
+ case OP_TYPE:
+ fprintf_filtered (stream, "Type @0x%x (",
+ exp->elts[elt].type);
+ type_print (exp->elts[elt].type, NULL, stream, 0);
+ fprintf_filtered (stream, ")");
+ elt += 2;
+ break;
+ case STRUCTOP_STRUCT:
+ case STRUCTOP_PTR:
+ {
+ char *elem_name;
+ int len;
+
+ len = longest_to_int (exp->elts[elt].longconst);
+ elem_name = &exp->elts[elt + 1].string;
+
+ fprintf_filtered (stream, "Element name: `%.*s'", len, elem_name);
+ elt = dump_subexp (exp, stream, elt + 3 + BYTES_TO_EXP_ELEM (len + 1));
+ }
+ break;
+ case OP_SCOPE:
+ {
+ char *elem_name;
+ int len;
+
+ fprintf_filtered (stream, "Type @0x%x (", exp->elts[elt].type);
+ type_print (exp->elts[elt].type, NULL, stream, 0);
+ fprintf_filtered (stream, ") ");
+
+ len = longest_to_int (exp->elts[elt + 1].longconst);
+ elem_name = &exp->elts[elt + 2].string;
+
+ fprintf_filtered (stream, "Field name: `%.*s'", len, elem_name);
+ elt += 4 + BYTES_TO_EXP_ELEM (len + 1);
+ }
+ break;
+ default:
+ case OP_NULL:
+ case STRUCTOP_MEMBER:
+ case STRUCTOP_MPTR:
+ case MULTI_SUBSCRIPT:
+ case OP_F77_UNDETERMINED_ARGLIST:
+ case OP_COMPLEX:
+ case OP_STRING:
+ case OP_BITSTRING:
+ case OP_BOOL:
+ case OP_M2_STRING:
+ case OP_THIS:
+ case OP_LABELED:
+ case OP_NAME:
+ case OP_EXPRSTRING:
+ fprintf_filtered (stream, "Unknown format");
+ }
+
+ indent -= 2;
+
+ return elt;
+}
+
+void
+dump_postfix_expression (exp, stream, note)
+ struct expression *exp;
+ GDB_FILE *stream;
+ char *note;
+{
+ int elt;
+
+ fprintf_filtered (stream, "Dump of expression @ ");
+ gdb_print_address (exp, stream);
+ fprintf_filtered (stream, ", %s:\nExpression: `", note);
+ if (exp->elts[0].opcode != OP_TYPE)
+ print_expression (exp, stream);
+ else
+ fputs_filtered ("Type printing not yet supported....", stream);
+ fprintf_filtered (stream, "'\n\tLanguage %s, %d elements, %d bytes each.\n",
+ exp->language_defn->la_name, exp -> nelts,
+ sizeof (union exp_element));
+ fputs_filtered ("\n", stream);
+
+ for (elt = 0; elt < exp -> nelts;)
+ elt = dump_subexp (exp, stream, elt);
+ fputs_filtered ("\n", stream);
+}
+
+#endif /* MAINTENANCE_CMDS */
diff --git a/gdb/expression.h b/gdb/expression.h
new file mode 100644
index 00000000000..310b2e297ac
--- /dev/null
+++ b/gdb/expression.h
@@ -0,0 +1,382 @@
+/* Definitions for expressions stored in reversed prefix form, for GDB.
+ Copyright 1986, 1989, 1992, 1994 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#if !defined (EXPRESSION_H)
+#define EXPRESSION_H 1
+
+
+#include "symtab.h" /* Needed for "struct block" type. */
+
+
+/* Definitions for saved C expressions. */
+
+/* An expression is represented as a vector of union exp_element's.
+ Each exp_element is an opcode, except that some opcodes cause
+ the following exp_element to be treated as a long or double constant
+ or as a variable. The opcodes are obeyed, using a stack for temporaries.
+ The value is left on the temporary stack at the end. */
+
+/* When it is necessary to include a string,
+ it can occupy as many exp_elements as it needs.
+ We find the length of the string using strlen,
+ divide to find out how many exp_elements are used up,
+ and skip that many. Strings, like numbers, are indicated
+ by the preceding opcode. */
+
+enum exp_opcode
+{
+ /* 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, /* + */
+ BINOP_SUB, /* - */
+ BINOP_MUL, /* * */
+ BINOP_DIV, /* / */
+ BINOP_REM, /* % */
+ BINOP_MOD, /* mod (Knuth 1.2.4) */
+ BINOP_LSH, /* << */
+ BINOP_RSH, /* >> */
+ BINOP_LOGICAL_AND, /* && */
+ BINOP_LOGICAL_OR, /* || */
+ BINOP_BITWISE_AND, /* & */
+ BINOP_BITWISE_IOR, /* | */
+ BINOP_BITWISE_XOR, /* ^ */
+ BINOP_EQUAL, /* == */
+ BINOP_NOTEQUAL, /* != */
+ BINOP_LESS, /* < */
+ BINOP_GTR, /* > */
+ BINOP_LEQ, /* <= */
+ BINOP_GEQ, /* >= */
+ BINOP_REPEAT, /* @ */
+ BINOP_ASSIGN, /* = */
+ BINOP_COMMA, /* , */
+ BINOP_SUBSCRIPT, /* x[y] */
+ BINOP_EXP, /* Exponentiation */
+
+ /* C++. */
+
+ BINOP_MIN, /* <? */
+ BINOP_MAX, /* >? */
+ BINOP_SCOPE, /* :: */
+
+ /* STRUCTOP_MEMBER is used for pointer-to-member constructs.
+ X . * Y translates into X STRUCTOP_MEMBER Y. */
+ STRUCTOP_MEMBER,
+
+ /* STRUCTOP_MPTR is used for pointer-to-member constructs
+ when X is a pointer instead of an aggregate. */
+ STRUCTOP_MPTR,
+
+ /* end of C++. */
+
+ /* For Modula-2 integer division DIV */
+ BINOP_INTDIV,
+
+ BINOP_ASSIGN_MODIFY, /* +=, -=, *=, and so on.
+ The following exp_element is another opcode,
+ a BINOP_, saying how to modify.
+ Then comes another BINOP_ASSIGN_MODIFY,
+ making three exp_elements in total. */
+
+ /* 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,
+
+ /* For Chill and Pascal. */
+ BINOP_IN, /* Returns 1 iff ARG1 IN ARG2. */
+
+ /* This is the "colon operator" used various places in Chill. */
+ BINOP_RANGE,
+
+ /* This must be the highest BINOP_ value, for expprint.c. */
+ BINOP_END,
+
+ /* Operates on three values computed by following subexpressions. */
+ TERNOP_COND, /* ?: */
+
+ /* A sub-string/sub-array. Chill syntax: OP1(OP2:OP3).
+ Return elements OP2 through OP3 of OP1. */
+ TERNOP_SLICE,
+
+ /* A sub-string/sub-array. Chill syntax: OP1(OP2 UP OP3).
+ Return OP3 elements of OP1, starting with element OP2. */
+ TERNOP_SLICE_COUNT,
+
+ /* 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. */
+
+ /* OP_LONG is followed by a type pointer in the next exp_element
+ and the long constant value in the following exp_element.
+ Then comes another OP_LONG.
+ Thus, the operation occupies four exp_elements. */
+ OP_LONG,
+
+ /* OP_DOUBLE is similar but takes a DOUBLEST constant instead of a long. */
+ OP_DOUBLE,
+
+ /* 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.
+ With another OP_LAST at the end, this makes three exp_elements. */
+ OP_LAST,
+
+ /* OP_REGISTER is followed by an integer in the next exp_element.
+ This is the number of a register to fetch (as an int).
+ With another OP_REGISTER at the end, this makes three exp_elements. */
+ OP_REGISTER,
+
+ /* OP_INTERNALVAR is followed by an internalvar ptr in the next exp_element.
+ With another OP_INTERNALVAR at the end, this makes three exp_elements. */
+ OP_INTERNALVAR,
+
+ /* OP_FUNCALL is followed by an integer in the next exp_element.
+ The integer is the number of args to the function call.
+ That many plus one values from following subexpressions
+ are used, the first one being the function.
+ The integer is followed by a repeat of OP_FUNCALL,
+ making three exp_elements. */
+ OP_FUNCALL,
+
+ /* This is EXACTLY like OP_FUNCALL but is semantically different.
+ In F77, array subscript expressions, substring expressions
+ and function calls are all exactly the same syntactically. They may
+ only be dismabiguated at runtime. Thus this operator, which
+ indicates that we have found something of the form <name> ( <stuff> ) */
+ OP_F77_UNDETERMINED_ARGLIST,
+
+ /* The following OP is a special one, it introduces a F77 complex
+ literal. It is followed by exactly two args that are doubles. */
+ OP_COMPLEX,
+
+ /* OP_STRING represents a string constant.
+ Its format is the same as that of a STRUCTOP, but the string
+ data is just made into a string constant when the operation
+ is executed. */
+ OP_STRING,
+
+ /* 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.
+ It casts the value of the following subexpression. */
+ UNOP_CAST,
+
+ /* UNOP_MEMVAL is followed by a type pointer in the next exp_element
+ With another UNOP_MEMVAL at the end, this makes three exp_elements.
+ It casts the contents of the word addressed by the value of the
+ following subexpression. */
+ UNOP_MEMVAL,
+
+ /* UNOP_... operate on one value from a following subexpression
+ and replace it with a result. They take no immediate arguments. */
+
+ UNOP_NEG, /* Unary - */
+ UNOP_LOGICAL_NOT, /* Unary ! */
+ UNOP_COMPLEMENT, /* Unary ~ */
+ UNOP_IND, /* Unary * */
+ UNOP_ADDR, /* Unary & */
+ UNOP_PREINCREMENT, /* ++ before an expression */
+ UNOP_POSTINCREMENT, /* ++ after an expression */
+ UNOP_PREDECREMENT, /* -- before an expression */
+ UNOP_POSTDECREMENT, /* -- after an expression */
+ UNOP_SIZEOF, /* Unary sizeof (followed by expression) */
+
+ 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,
+
+ /* Chill builtin functions. */
+ UNOP_LOWER, UNOP_UPPER, UNOP_LENGTH, UNOP_CARD, UNOP_CHMAX, UNOP_CHMIN,
+
+ 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).
+ STRUCTOP_STRUCT is used for "." and STRUCTOP_PTR for "->".
+ They differ only in the error message given in case the value is
+ not suitable or the structure component specified is not found.
+
+ The length of the string follows 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,
+
+ /* C++ */
+ /* OP_THIS is just a placeholder for the class instance variable.
+ It just comes in a tight (OP_THIS, OP_THIS) pair. */
+ OP_THIS,
+
+ /* OP_SCOPE surrounds a type name and a field name. The type
+ name is encoded as one element, but the field name stays as
+ a string, which, of course, is variable length. */
+ OP_SCOPE,
+
+ /* Used to represent named structure field values in brace initializers
+ (or tuples as they are called in Chill).
+ The gcc C syntax is NAME:VALUE or .NAME=VALUE, the Chill syntax is
+ .NAME:VALUE. Multiple labels (as in the Chill syntax
+ .NAME1,.NAME2:VALUE) is represented as if it were
+ .NAME1:(.NAME2:VALUE) (though that is not valid Chill syntax).
+
+ The NAME is represented as for STRUCTOP_STRUCT; VALUE follows. */
+ OP_LABELED,
+
+ /* 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,
+
+ /* An un-looked-up identifier. */
+ OP_NAME,
+
+ /* An unparsed expression. Used for Scheme (for now at least) */
+ OP_EXPRSTRING
+};
+
+union exp_element
+{
+ enum exp_opcode opcode;
+ struct symbol *symbol;
+ LONGEST longconst;
+ DOUBLEST 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];
+};
+
+/* 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 eval.c */
+
+/* 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). */
+};
+
+extern struct value* evaluate_subexp_standard
+PARAMS ((struct type *, struct expression *, int*, enum noside));
+
+/* From expprint.c */
+
+extern void print_expression PARAMS ((struct expression *, GDB_FILE *));
+
+extern char *op_string PARAMS ((enum exp_opcode));
+
+#ifdef MAINTENANCE_CMDS
+extern void dump_prefix_expression PARAMS ((struct expression *,
+ GDB_FILE *,
+ char *));
+extern void dump_postfix_expression PARAMS ((struct expression *,
+ GDB_FILE *,
+ char *));
+#endif /* MAINTENANCE_CMDS */
+
+#endif /* !defined (EXPRESSION_H) */
diff --git a/gdb/f-exp.y b/gdb/f-exp.y
new file mode 100644
index 00000000000..4a1f747605c
--- /dev/null
+++ b/gdb/f-exp.y
@@ -0,0 +1,1174 @@
+/* YACC parser for Fortran expressions, for GDB.
+ Copyright 1986, 1989, 1990, 1991, 1993, 1994
+ Free Software Foundation, Inc.
+ Contributed by Motorola. Adapted from the C parser by Farooq Butt
+ (fmbutt@engage.sps.mot.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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* This was blantantly ripped off the C expression parser, please
+ be aware of that as you look at its basic structure -FMB */
+
+/* Parse a F77 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 "gdb_string.h"
+#include "expression.h"
+#include "value.h"
+#include "parser-defs.h"
+#include "language.h"
+#include "f-lang.h"
+#include "bfd.h" /* Required by objfiles.h. */
+#include "symfile.h" /* Required by objfiles.h. */
+#include "objfiles.h" /* For have_full_symbols and have_partial_symbols */
+
+/* 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 f_maxdepth
+#define yyparse f_parse
+#define yylex f_lex
+#define yyerror f_error
+#define yylval f_lval
+#define yychar f_char
+#define yydebug f_debug
+#define yypact f_pact
+#define yyr1 f_r1
+#define yyr2 f_r2
+#define yydef f_def
+#define yychk f_chk
+#define yypgo f_pgo
+#define yyact f_act
+#define yyexca f_exca
+#define yyerrflag f_errflag
+#define yynerrs f_nerrs
+#define yyps f_ps
+#define yypv f_pv
+#define yys f_s
+#define yy_yys f_yys
+#define yystate f_state
+#define yytmp f_tmp
+#define yyv f_v
+#define yy_yyv f_yyv
+#define yyval f_val
+#define yylloc f_lloc
+#define yyreds f_reds /* With YYDEBUG defined */
+#define yytoks f_toks /* With YYDEBUG defined */
+#define yylhs f_yylhs
+#define yylen f_yylen
+#define yydefred f_yydefred
+#define yydgoto f_yydgoto
+#define yysindex f_yysindex
+#define yyrindex f_yyrindex
+#define yygindex f_yygindex
+#define yytable f_yytable
+#define yycheck f_yycheck
+
+#ifndef YYDEBUG
+#define YYDEBUG 1 /* Default to no yydebug support */
+#endif
+
+int yyparse PARAMS ((void));
+
+static int yylex PARAMS ((void));
+
+void yyerror PARAMS ((char *));
+
+static void growbuf_by_size PARAMS ((int));
+
+static int match_string_literal PARAMS ((void));
+
+%}
+
+/* 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;
+ DOUBLEST 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 type_exp 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
+
+%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_LITERAL
+%token <lval> BOOLEAN_LITERAL
+%token <ssym> NAME
+%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 SIZEOF
+%token ERROR
+
+/* Special type cases, put in to allow the parser to distinguish different
+ legal basetypes. */
+%token INT_KEYWORD INT_S2_KEYWORD LOGICAL_S1_KEYWORD LOGICAL_S2_KEYWORD
+%token LOGICAL_KEYWORD REAL_KEYWORD REAL_S8_KEYWORD REAL_S16_KEYWORD
+%token COMPLEX_S8_KEYWORD COMPLEX_S16_KEYWORD COMPLEX_S32_KEYWORD
+%token BOOL_AND BOOL_OR BOOL_NOT
+%token <lval> CHARACTER
+
+%token <voidval> VARIABLE
+
+%token <opcode> ASSIGN_MODIFY
+
+%left ','
+%left ABOVE_COMMA
+%right '=' ASSIGN_MODIFY
+%right '?'
+%left BOOL_OR
+%right BOOL_NOT
+%left BOOL_AND
+%left '|'
+%left '^'
+%left '&'
+%left EQUAL NOTEQUAL
+%left LESSTHAN GREATERTHAN LEQ GEQ
+%left LSH RSH
+%left '@'
+%left '+' '-'
+%left '*' '/' '%'
+%right UNARY
+%right '('
+
+
+%%
+
+start : exp
+ | type_exp
+ ;
+
+type_exp: type
+ { write_exp_elt_opcode(OP_TYPE);
+ write_exp_elt_type($1);
+ write_exp_elt_opcode(OP_TYPE); }
+ ;
+
+exp : '(' exp ')'
+ { }
+ ;
+
+/* 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 : BOOL_NOT exp %prec UNARY
+ { write_exp_elt_opcode (UNOP_LOGICAL_NOT); }
+ ;
+
+exp : '~' exp %prec UNARY
+ { write_exp_elt_opcode (UNOP_COMPLEMENT); }
+ ;
+
+exp : SIZEOF exp %prec UNARY
+ { write_exp_elt_opcode (UNOP_SIZEOF); }
+ ;
+
+/* No more explicit array operators, we treat everything in F77 as
+ a function call. The disambiguation as to whether we are
+ doing a subscript operation or a function call is done
+ later in eval.c. */
+
+exp : exp '('
+ { start_arglist (); }
+ arglist ')'
+ { write_exp_elt_opcode (OP_F77_UNDETERMINED_ARGLIST);
+ write_exp_elt_longcst ((LONGEST) end_arglist ());
+ write_exp_elt_opcode (OP_F77_UNDETERMINED_ARGLIST); }
+ ;
+
+arglist :
+ ;
+
+arglist : exp
+ { arglist_len = 1; }
+ ;
+
+arglist : substring
+ { arglist_len = 2;}
+
+arglist : arglist ',' exp %prec ABOVE_COMMA
+ { arglist_len++; }
+ ;
+
+substring: exp ':' exp %prec ABOVE_COMMA
+ { }
+ ;
+
+
+complexnum: exp ',' exp
+ { }
+ ;
+
+exp : '(' complexnum ')'
+ { write_exp_elt_opcode(OP_COMPLEX); }
+ ;
+
+exp : '(' type ')' exp %prec UNARY
+ { write_exp_elt_opcode (UNOP_CAST);
+ write_exp_elt_type ($2);
+ write_exp_elt_opcode (UNOP_CAST); }
+ ;
+
+/* 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 LESSTHAN exp
+ { write_exp_elt_opcode (BINOP_LESS); }
+ ;
+
+exp : exp GREATERTHAN 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 BOOL_AND exp
+ { write_exp_elt_opcode (BINOP_LOGICAL_AND); }
+ ;
+
+
+exp : exp BOOL_OR exp
+ { write_exp_elt_opcode (BINOP_LOGICAL_OR); }
+ ;
+
+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_f_real_s8);
+ write_exp_elt_dblcst ($1);
+ write_exp_elt_opcode (OP_DOUBLE); }
+ ;
+
+exp : variable
+ ;
+
+exp : VARIABLE
+ ;
+
+exp : SIZEOF '(' type ')' %prec UNARY
+ { write_exp_elt_opcode (OP_LONG);
+ write_exp_elt_type (builtin_type_f_integer);
+ CHECK_TYPEDEF ($3);
+ write_exp_elt_longcst ((LONGEST) TYPE_LENGTH ($3));
+ write_exp_elt_opcode (OP_LONG); }
+ ;
+
+exp : BOOLEAN_LITERAL
+ { write_exp_elt_opcode (OP_BOOL);
+ write_exp_elt_longcst ((LONGEST) $1);
+ write_exp_elt_opcode (OP_BOOL);
+ }
+ ;
+
+exp : STRING_LITERAL
+ {
+ write_exp_elt_opcode (OP_STRING);
+ write_exp_string ($1);
+ write_exp_elt_opcode (OP_STRING);
+ }
+ ;
+
+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);
+ break;
+ }
+ else
+ {
+ struct minimal_symbol *msymbol;
+ register char *arg = copy_name ($1.stoken);
+
+ msymbol =
+ lookup_minimal_symbol (arg, NULL, NULL);
+ if (msymbol != NULL)
+ {
+ write_exp_msymbol (msymbol,
+ lookup_function_type (builtin_type_int),
+ builtin_type_int);
+ }
+ 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));
+ }
+ }
+ ;
+
+
+type : ptype
+ ;
+
+ptype : typebase
+ | typebase abs_decl
+ {
+ /* This is where the interesting stuff happens. */
+ int done = 0;
+ int array_size;
+ struct type *follow_type = $1;
+ 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_f_integer, 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;
+ }
+ $$ = follow_type;
+ }
+ ;
+
+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 func_mod
+ { push_type (tp_function); }
+ | func_mod
+ { push_type (tp_function); }
+ ;
+
+func_mod: '(' ')'
+ { $$ = 0; }
+ | '(' nonempty_typelist ')'
+ { free ((PTR)$2); $$ = 0; }
+ ;
+
+typebase /* Implements (approximately): (type-qualifier)* type-specifier */
+ : TYPENAME
+ { $$ = $1.type; }
+ | INT_KEYWORD
+ { $$ = builtin_type_f_integer; }
+ | INT_S2_KEYWORD
+ { $$ = builtin_type_f_integer_s2; }
+ | CHARACTER
+ { $$ = builtin_type_f_character; }
+ | LOGICAL_KEYWORD
+ { $$ = builtin_type_f_logical;}
+ | LOGICAL_S2_KEYWORD
+ { $$ = builtin_type_f_logical_s2;}
+ | LOGICAL_S1_KEYWORD
+ { $$ = builtin_type_f_logical_s1;}
+ | REAL_KEYWORD
+ { $$ = builtin_type_f_real;}
+ | REAL_S8_KEYWORD
+ { $$ = builtin_type_f_real_s8;}
+ | REAL_S16_KEYWORD
+ { $$ = builtin_type_f_real_s16;}
+ | COMPLEX_S8_KEYWORD
+ { $$ = builtin_type_f_complex_s8;}
+ | COMPLEX_S16_KEYWORD
+ { $$ = builtin_type_f_complex_s16;}
+ | COMPLEX_S32_KEYWORD
+ { $$ = builtin_type_f_complex_s32;}
+ ;
+
+typename: TYPENAME
+ ;
+
+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; }
+ | TYPENAME
+ { $$ = $1.stoken; }
+ | NAME_OR_INT
+ { $$ = $1.stoken; }
+ ;
+
+name_not_typename : NAME
+/* 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;
+ register int c;
+ register int base = input_radix;
+ int unsigned_p = 0;
+ int long_p = 0;
+ ULONGEST 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. */
+ /* [dD] is not understood as an exponent by atof, change it to 'e'. */
+ char *tmp, *tmp2;
+
+ tmp = strsave (p);
+ for (tmp2 = tmp; *tmp2; ++tmp2)
+ if (*tmp2 == 'd' || *tmp2 == 'D')
+ *tmp2 = 'e';
+ putithere->dval = atof (tmp);
+ free (tmp);
+ 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 = ((ULONGEST)1) << (TARGET_LONG_BIT-1);
+ unsigned_type = builtin_type_unsigned_long;
+ signed_type = builtin_type_long;
+ }
+ else
+ {
+ high_bit = ((ULONGEST)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 dot_ops[] =
+{
+ { ".and.", BOOL_AND, BINOP_END },
+ { ".AND.", BOOL_AND, BINOP_END },
+ { ".or.", BOOL_OR, BINOP_END },
+ { ".OR.", BOOL_OR, BINOP_END },
+ { ".not.", BOOL_NOT, BINOP_END },
+ { ".NOT.", BOOL_NOT, BINOP_END },
+ { ".eq.", EQUAL, BINOP_END },
+ { ".EQ.", EQUAL, BINOP_END },
+ { ".eqv.", EQUAL, BINOP_END },
+ { ".NEQV.", NOTEQUAL, BINOP_END },
+ { ".neqv.", NOTEQUAL, BINOP_END },
+ { ".EQV.", EQUAL, BINOP_END },
+ { ".ne.", NOTEQUAL, BINOP_END },
+ { ".NE.", NOTEQUAL, BINOP_END },
+ { ".le.", LEQ, BINOP_END },
+ { ".LE.", LEQ, BINOP_END },
+ { ".ge.", GEQ, BINOP_END },
+ { ".GE.", GEQ, BINOP_END },
+ { ".gt.", GREATERTHAN, BINOP_END },
+ { ".GT.", GREATERTHAN, BINOP_END },
+ { ".lt.", LESSTHAN, BINOP_END },
+ { ".LT.", LESSTHAN, BINOP_END },
+ { NULL, 0, 0 }
+};
+
+struct f77_boolean_val
+{
+ char *name;
+ int value;
+};
+
+static const struct f77_boolean_val boolean_values[] =
+{
+ { ".true.", 1 },
+ { ".TRUE.", 1 },
+ { ".false.", 0 },
+ { ".FALSE.", 0 },
+ { NULL, 0 }
+};
+
+static const struct token f77_keywords[] =
+{
+ { "complex_16", COMPLEX_S16_KEYWORD, BINOP_END },
+ { "complex_32", COMPLEX_S32_KEYWORD, BINOP_END },
+ { "character", CHARACTER, BINOP_END },
+ { "integer_2", INT_S2_KEYWORD, BINOP_END },
+ { "logical_1", LOGICAL_S1_KEYWORD, BINOP_END },
+ { "logical_2", LOGICAL_S2_KEYWORD, BINOP_END },
+ { "complex_8", COMPLEX_S8_KEYWORD, BINOP_END },
+ { "integer", INT_KEYWORD, BINOP_END },
+ { "logical", LOGICAL_KEYWORD, BINOP_END },
+ { "real_16", REAL_S16_KEYWORD, BINOP_END },
+ { "complex", COMPLEX_S8_KEYWORD, BINOP_END },
+ { "sizeof", SIZEOF, BINOP_END },
+ { "real_8", REAL_S8_KEYWORD, BINOP_END },
+ { "real", REAL_KEYWORD, BINOP_END },
+ { NULL, 0, 0 }
+};
+
+/* Implementation of a dynamically expandable buffer for processing input
+ characters acquired through lexptr and building a value to return in
+ yylval. Ripped off from ch-exp.y */
+
+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);
+}
+
+/* Blatantly ripped off from ch-exp.y. This routine recognizes F77
+ string-literals.
+
+ Recognize a string literal. A string literal is a nonzero sequence
+ of characters enclosed in matching single 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 */
+ return 0;
+ else
+ {
+ tempbuf[tempbufindex] = '\0';
+ yylval.sval.ptr = tempbuf;
+ yylval.sval.length = tempbufindex;
+ lexptr = ++tokptr;
+ return STRING_LITERAL;
+ }
+}
+
+/* Read one token, getting characters through lexptr. */
+
+static int
+yylex ()
+{
+ int c;
+ int namelen;
+ unsigned int i,token;
+ char *tokstart;
+
+ retry:
+
+ tokstart = lexptr;
+
+ /* First of all, let us make sure we are not dealing with the
+ special tokens .true. and .false. which evaluate to 1 and 0. */
+
+ if (*lexptr == '.')
+ {
+ for (i = 0; boolean_values[i].name != NULL; i++)
+ {
+ if STREQN (tokstart, boolean_values[i].name,
+ strlen (boolean_values[i].name))
+ {
+ lexptr += strlen (boolean_values[i].name);
+ yylval.lval = boolean_values[i].value;
+ return BOOLEAN_LITERAL;
+ }
+ }
+ }
+
+ /* See if it is a special .foo. operator */
+
+ for (i = 0; dot_ops[i].operator != NULL; i++)
+ if (STREQN (tokstart, dot_ops[i].operator, strlen (dot_ops[i].operator)))
+ {
+ lexptr += strlen (dot_ops[i].operator);
+ yylval.opcode = dot_ops[i].opcode;
+ return dot_ops[i].token;
+ }
+
+ switch (c = *tokstart)
+ {
+ case 0:
+ return 0;
+
+ case ' ':
+ case '\t':
+ case '\n':
+ lexptr++;
+ goto retry;
+
+ case '\'':
+ token = match_string_literal ();
+ if (token != 0)
+ return (token);
+ break;
+
+ 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, got_d = 0, toktype;
+ register char *p = tokstart;
+ int hex = input_radix > 10;
+
+ if (c == '0' && (p[1] == 'x' || p[1] == 'X'))
+ {
+ p += 2;
+ hex = 1;
+ }
+ else if (c == '0' && (p[1]=='t' || p[1]=='T' || p[1]=='d' || p[1]=='D'))
+ {
+ p += 2;
+ hex = 0;
+ }
+
+ for (;; ++p)
+ {
+ if (!hex && !got_e && (*p == 'e' || *p == 'E'))
+ got_dot = got_e = 1;
+ else if (!hex && !got_d && (*p == 'd' || *p == 'D'))
+ got_dot = got_d = 1;
+ else if (!hex && !got_dot && *p == '.')
+ got_dot = 1;
+ else if (((got_e && (p[-1] == 'e' || p[-1] == 'E'))
+ || (got_d && (p[-1] == 'd' || p[-1] == 'D')))
+ && (*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|got_d,
+ &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;
+ }
+
+ 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);
+
+ 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;
+
+ /* Catch specific keywords. */
+
+ for (i = 0; f77_keywords[i].operator != NULL; i++)
+ if (STREQN(tokstart, f77_keywords[i].operator,
+ strlen(f77_keywords[i].operator)))
+ {
+ /* lexptr += strlen(f77_keywords[i].operator); */
+ yylval.opcode = f77_keywords[i].opcode;
+ return f77_keywords[i].token;
+ }
+
+ yylval.sval.ptr = tokstart;
+ yylval.sval.length = namelen;
+
+ if (*tokstart == '$')
+ {
+ write_dollar_variable (yylval.sval);
+ return VARIABLE;
+ }
+
+ /* 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 : NULL,
+ NULL);
+ if (sym && SYMBOL_CLASS (sym) == LOC_TYPEDEF)
+ {
+ yylval.tsym.type = SYMBOL_TYPE (sym);
+ return TYPENAME;
+ }
+ if ((yylval.tsym.type = lookup_primitive_typename (tmp)) != 0)
+ return TYPENAME;
+
+ /* Input names that aren't symbols but ARE valid hex numbers,
+ when the input radix permits them, can be names or numbers
+ depending on the parse. Note we support radixes > 16 here. */
+ if (!sym
+ && ((tokstart[0] >= 'a' && tokstart[0] < 'a' + input_radix - 10)
+ || (tokstart[0] >= 'A' && tokstart[0] < 'A' + input_radix - 10)))
+ {
+ YYSTYPE newlval; /* Its value is ignored. */
+ hextype = parse_number (tokstart, namelen, 0, &newlval);
+ if (hextype == INT)
+ {
+ yylval.ssym.sym = sym;
+ yylval.ssym.is_a_field_of_this = is_a_field_of_this;
+ return NAME_OR_INT;
+ }
+ }
+
+ /* 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 ("A %s in expression, near `%s'.", (msg ? msg : "error"), lexptr);
+}
diff --git a/gdb/f-lang.c b/gdb/f-lang.c
new file mode 100644
index 00000000000..4ee66d58c3f
--- /dev/null
+++ b/gdb/f-lang.c
@@ -0,0 +1,973 @@
+/* Fortran language support routines for GDB, the GNU debugger.
+ Copyright 1993, 1994, 1996 Free Software Foundation, Inc.
+ Contributed by Motorola. Adapted from the C parser by Farooq Butt
+ (fmbutt@engage.sps.mot.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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "gdb_string.h"
+#include "symtab.h"
+#include "gdbtypes.h"
+#include "expression.h"
+#include "parser-defs.h"
+#include "language.h"
+#include "f-lang.h"
+
+/* The built-in types of F77. FIXME: integer*4 is missing, plain
+ logical is missing (builtin_type_logical is logical*4). */
+
+struct type *builtin_type_f_character;
+struct type *builtin_type_f_logical;
+struct type *builtin_type_f_logical_s1;
+struct type *builtin_type_f_logical_s2;
+struct type *builtin_type_f_integer;
+struct type *builtin_type_f_integer_s2;
+struct type *builtin_type_f_real;
+struct type *builtin_type_f_real_s8;
+struct type *builtin_type_f_real_s16;
+struct type *builtin_type_f_complex_s8;
+struct type *builtin_type_f_complex_s16;
+struct type *builtin_type_f_complex_s32;
+struct type *builtin_type_f_void;
+
+/* Following is dubious stuff that had been in the xcoff reader. */
+
+struct saved_fcn
+{
+ long line_offset; /* Line offset for function */
+ struct saved_fcn *next;
+};
+
+
+struct saved_bf_symnum
+{
+ long symnum_fcn; /* Symnum of function (i.e. .function directive) */
+ long symnum_bf; /* Symnum of .bf for this function */
+ struct saved_bf_symnum *next;
+};
+
+typedef struct saved_fcn SAVED_FUNCTION, *SAVED_FUNCTION_PTR;
+typedef struct saved_bf_symnum SAVED_BF, *SAVED_BF_PTR;
+
+/* Local functions */
+
+#if 0
+static void clear_function_list PARAMS ((void));
+static long get_bf_for_fcn PARAMS ((long));
+static void clear_bf_list PARAMS ((void));
+static void patch_all_commons_by_name PARAMS ((char *, CORE_ADDR, int));
+static SAVED_F77_COMMON_PTR find_first_common_named PARAMS ((char *));
+static void add_common_entry PARAMS ((struct symbol *));
+static void add_common_block PARAMS ((char *, CORE_ADDR, int, char *));
+static SAVED_FUNCTION *allocate_saved_function_node PARAMS ((void));
+static SAVED_BF_PTR allocate_saved_bf_node PARAMS ((void));
+static COMMON_ENTRY_PTR allocate_common_entry_node PARAMS ((void));
+static SAVED_F77_COMMON_PTR allocate_saved_f77_common_node PARAMS ((void));
+static void patch_common_entries PARAMS ((SAVED_F77_COMMON_PTR, CORE_ADDR, int));
+#endif
+
+static struct type *f_create_fundamental_type PARAMS ((struct objfile *, int));
+static void f_printstr PARAMS ((GDB_FILE *stream, char *string, unsigned int length, int width, int force_ellipses));
+static void f_printchar PARAMS ((int c, GDB_FILE *stream));
+static void f_emit_char PARAMS ((int c, GDB_FILE *stream, int quoter));
+
+/* 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 F77 version. */
+
+static void
+f_emit_char (c, stream, quoter)
+ register int c;
+ GDB_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 F77version. */
+
+static void
+f_printchar (c, stream)
+ int c;
+ GDB_FILE *stream;
+{
+ fputs_filtered ("'", stream);
+ LA_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 F77 version. */
+
+static void
+f_printstr (stream, string, length, width, force_ellipses)
+ GDB_FILE *stream;
+ char *string;
+ unsigned int length;
+ int width;
+ 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 ("''", gdb_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;
+ }
+ f_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;
+ }
+ LA_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 F77 programmer. */
+
+static struct type *
+f_create_fundamental_type (objfile, typeid)
+ struct objfile *objfile;
+ int typeid;
+{
+ register struct type *type = NULL;
+
+ switch (typeid)
+ {
+ 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, "character", objfile);
+ break;
+ case FT_SIGNED_CHAR:
+ type = init_type (TYPE_CODE_INT,
+ TARGET_CHAR_BIT / TARGET_CHAR_BIT,
+ 0, "integer*1", objfile);
+ break;
+ case FT_UNSIGNED_CHAR:
+ type = init_type (TYPE_CODE_BOOL,
+ TARGET_CHAR_BIT / TARGET_CHAR_BIT,
+ TYPE_FLAG_UNSIGNED, "logical*1", objfile);
+ break;
+ case FT_SHORT:
+ type = init_type (TYPE_CODE_INT,
+ TARGET_SHORT_BIT / TARGET_CHAR_BIT,
+ 0, "integer*2", objfile);
+ break;
+ case FT_SIGNED_SHORT:
+ type = init_type (TYPE_CODE_INT,
+ TARGET_SHORT_BIT / TARGET_CHAR_BIT,
+ 0, "short", objfile); /* FIXME-fnf */
+ break;
+ case FT_UNSIGNED_SHORT:
+ type = init_type (TYPE_CODE_BOOL,
+ TARGET_SHORT_BIT / TARGET_CHAR_BIT,
+ TYPE_FLAG_UNSIGNED, "logical*2", objfile);
+ break;
+ case FT_INTEGER:
+ type = init_type (TYPE_CODE_INT,
+ TARGET_INT_BIT / TARGET_CHAR_BIT,
+ 0, "integer*4", objfile);
+ break;
+ case FT_SIGNED_INTEGER:
+ type = init_type (TYPE_CODE_INT,
+ TARGET_INT_BIT / TARGET_CHAR_BIT,
+ 0, "integer", objfile); /* FIXME -fnf */
+ break;
+ case FT_UNSIGNED_INTEGER:
+ type = init_type (TYPE_CODE_BOOL,
+ TARGET_INT_BIT / TARGET_CHAR_BIT,
+ TYPE_FLAG_UNSIGNED, "logical*4", 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,
+ 0, "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,
+ 0, "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, "real", objfile);
+ break;
+ case FT_DBL_PREC_FLOAT:
+ type = init_type (TYPE_CODE_FLT,
+ TARGET_DOUBLE_BIT / TARGET_CHAR_BIT,
+ 0, "real*8", 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, "real*16", objfile);
+ break;
+ case FT_COMPLEX:
+ type = init_type (TYPE_CODE_COMPLEX,
+ 2 * TARGET_FLOAT_BIT / TARGET_CHAR_BIT,
+ 0, "complex*8", objfile);
+ TYPE_TARGET_TYPE (type) = builtin_type_f_real;
+ break;
+ case FT_DBL_PREC_COMPLEX:
+ type = init_type (TYPE_CODE_COMPLEX,
+ 2 * TARGET_DOUBLE_BIT / TARGET_CHAR_BIT,
+ 0, "complex*16", objfile);
+ TYPE_TARGET_TYPE (type) = builtin_type_f_real_s8;
+ break;
+ case FT_EXT_PREC_COMPLEX:
+ type = init_type (TYPE_CODE_COMPLEX,
+ 2 * TARGET_LONG_DOUBLE_BIT / TARGET_CHAR_BIT,
+ 0, "complex*32", objfile);
+ TYPE_TARGET_TYPE (type) = builtin_type_f_real_s16;
+ break;
+ 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 F77 fundamental type %d", typeid);
+ break;
+ }
+ return (type);
+}
+
+
+/* Table of operators and their precedences for printing expressions. */
+
+static const struct op_print f_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 },
+ { ".EQ.", BINOP_EQUAL, PREC_EQUAL, 0 },
+ { ".NE.", BINOP_NOTEQUAL, PREC_EQUAL, 0 },
+ { ".LE.", BINOP_LEQ, PREC_ORDER, 0 },
+ { ".GE.", BINOP_GEQ, PREC_ORDER, 0 },
+ { ".GT.", BINOP_GTR, PREC_ORDER, 0 },
+ { ".LT.", BINOP_LESS, PREC_ORDER, 0 },
+ { "**", UNOP_IND, PREC_PREFIX, 0 },
+ { "@", BINOP_REPEAT, PREC_REPEAT, 0 },
+ { NULL, 0, 0, 0 }
+};
+
+struct type ** CONST_PTR (f_builtin_types[]) =
+{
+ &builtin_type_f_character,
+ &builtin_type_f_logical,
+ &builtin_type_f_logical_s1,
+ &builtin_type_f_logical_s2,
+ &builtin_type_f_integer,
+ &builtin_type_f_integer_s2,
+ &builtin_type_f_real,
+ &builtin_type_f_real_s8,
+ &builtin_type_f_real_s16,
+ &builtin_type_f_complex_s8,
+ &builtin_type_f_complex_s16,
+#if 0
+ &builtin_type_f_complex_s32,
+#endif
+ &builtin_type_f_void,
+ 0
+};
+
+/* This is declared in c-lang.h but it is silly to import that file for what
+ is already just a hack. */
+extern int
+c_value_print PARAMS ((struct value *, GDB_FILE *, int, enum val_prettyprint));
+
+const struct language_defn f_language_defn = {
+ "fortran",
+ language_fortran,
+ f_builtin_types,
+ range_check_on,
+ type_check_on,
+ f_parse, /* parser */
+ f_error, /* parser error function */
+ evaluate_subexp_standard,
+ f_printchar, /* Print character constant */
+ f_printstr, /* function to print string constant */
+ f_emit_char, /* Function to print a single character */
+ f_create_fundamental_type, /* Create fundamental type in this language */
+ f_print_type, /* Print a type using appropriate syntax */
+ f_val_print, /* Print a value using appropriate syntax */
+ c_value_print, /* FIXME */
+ {"", "", "", ""}, /* Binary format info */
+ {"0%o", "0", "o", ""}, /* Octal format info */
+ {"%d", "", "d", ""}, /* Decimal format info */
+ {"0x%x", "0x", "x", ""}, /* Hex format info */
+ f_op_print_tab, /* expression operators for printing */
+ 0, /* arrays are first-class (not c-style) */
+ 1, /* String lower bound */
+ &builtin_type_f_character, /* Type of string elements */
+ LANG_MAGIC
+ };
+
+void
+_initialize_f_language ()
+{
+ builtin_type_f_void =
+ init_type (TYPE_CODE_VOID, 1,
+ 0,
+ "VOID", (struct objfile *) NULL);
+
+ builtin_type_f_character =
+ init_type (TYPE_CODE_INT, TARGET_CHAR_BIT / TARGET_CHAR_BIT,
+ 0,
+ "character", (struct objfile *) NULL);
+
+ builtin_type_f_logical_s1 =
+ init_type (TYPE_CODE_BOOL, TARGET_CHAR_BIT / TARGET_CHAR_BIT,
+ TYPE_FLAG_UNSIGNED,
+ "logical*1", (struct objfile *) NULL);
+
+ builtin_type_f_integer_s2 =
+ init_type (TYPE_CODE_INT, TARGET_SHORT_BIT / TARGET_CHAR_BIT,
+ 0,
+ "integer*2", (struct objfile *) NULL);
+
+ builtin_type_f_logical_s2 =
+ init_type (TYPE_CODE_BOOL, TARGET_SHORT_BIT / TARGET_CHAR_BIT,
+ TYPE_FLAG_UNSIGNED,
+ "logical*2", (struct objfile *) NULL);
+
+ builtin_type_f_integer =
+ init_type (TYPE_CODE_INT, TARGET_INT_BIT / TARGET_CHAR_BIT,
+ 0,
+ "integer", (struct objfile *) NULL);
+
+ builtin_type_f_logical =
+ init_type (TYPE_CODE_BOOL, TARGET_INT_BIT / TARGET_CHAR_BIT,
+ TYPE_FLAG_UNSIGNED,
+ "logical*4", (struct objfile *) NULL);
+
+ builtin_type_f_real =
+ init_type (TYPE_CODE_FLT, TARGET_FLOAT_BIT / TARGET_CHAR_BIT,
+ 0,
+ "real", (struct objfile *) NULL);
+
+ builtin_type_f_real_s8 =
+ init_type (TYPE_CODE_FLT, TARGET_DOUBLE_BIT / TARGET_CHAR_BIT,
+ 0,
+ "real*8", (struct objfile *) NULL);
+
+ builtin_type_f_real_s16 =
+ init_type (TYPE_CODE_FLT, TARGET_LONG_DOUBLE_BIT / TARGET_CHAR_BIT,
+ 0,
+ "real*16", (struct objfile *) NULL);
+
+ builtin_type_f_complex_s8 =
+ init_type (TYPE_CODE_COMPLEX, 2 * TARGET_FLOAT_BIT / TARGET_CHAR_BIT,
+ 0,
+ "complex*8", (struct objfile *) NULL);
+ TYPE_TARGET_TYPE (builtin_type_f_complex_s8) = builtin_type_f_real;
+
+ builtin_type_f_complex_s16 =
+ init_type (TYPE_CODE_COMPLEX, 2 * TARGET_DOUBLE_BIT / TARGET_CHAR_BIT,
+ 0,
+ "complex*16", (struct objfile *) NULL);
+ TYPE_TARGET_TYPE (builtin_type_f_complex_s16) = builtin_type_f_real_s8;
+
+ /* We have a new size == 4 double floats for the
+ complex*32 data type */
+
+ builtin_type_f_complex_s32 =
+ init_type (TYPE_CODE_COMPLEX, 2 * TARGET_LONG_DOUBLE_BIT / TARGET_CHAR_BIT,
+ 0,
+ "complex*32", (struct objfile *) NULL);
+ TYPE_TARGET_TYPE (builtin_type_f_complex_s32) = builtin_type_f_real_s16;
+
+ builtin_type_string =
+ init_type (TYPE_CODE_STRING, TARGET_CHAR_BIT / TARGET_CHAR_BIT,
+ 0,
+ "character string", (struct objfile *) NULL);
+
+ add_language (&f_language_defn);
+}
+
+#if 0
+static SAVED_BF_PTR
+allocate_saved_bf_node()
+{
+ SAVED_BF_PTR new;
+
+ new = (SAVED_BF_PTR) xmalloc (sizeof (SAVED_BF));
+ return(new);
+}
+
+static SAVED_FUNCTION *
+allocate_saved_function_node()
+{
+ SAVED_FUNCTION *new;
+
+ new = (SAVED_FUNCTION *) xmalloc (sizeof (SAVED_FUNCTION));
+ return(new);
+}
+
+static SAVED_F77_COMMON_PTR allocate_saved_f77_common_node()
+{
+ SAVED_F77_COMMON_PTR new;
+
+ new = (SAVED_F77_COMMON_PTR) xmalloc (sizeof (SAVED_F77_COMMON));
+ return(new);
+}
+
+static COMMON_ENTRY_PTR allocate_common_entry_node()
+{
+ COMMON_ENTRY_PTR new;
+
+ new = (COMMON_ENTRY_PTR) xmalloc (sizeof (COMMON_ENTRY));
+ return(new);
+}
+#endif
+
+SAVED_F77_COMMON_PTR head_common_list=NULL; /* Ptr to 1st saved COMMON */
+SAVED_F77_COMMON_PTR tail_common_list=NULL; /* Ptr to last saved COMMON */
+SAVED_F77_COMMON_PTR current_common=NULL; /* Ptr to current COMMON */
+
+#if 0
+static SAVED_BF_PTR saved_bf_list=NULL; /* Ptr to (.bf,function)
+ list*/
+static SAVED_BF_PTR saved_bf_list_end=NULL; /* Ptr to above list's end */
+static SAVED_BF_PTR current_head_bf_list=NULL; /* Current head of above list
+ */
+
+static SAVED_BF_PTR tmp_bf_ptr; /* Generic temporary for use
+ in macros */
+
+/* The following function simply enters a given common block onto
+ the global common block chain */
+
+static void
+add_common_block(name,offset,secnum,func_stab)
+ char *name;
+ CORE_ADDR offset;
+ int secnum;
+ char *func_stab;
+{
+ SAVED_F77_COMMON_PTR tmp;
+ char *c,*local_copy_func_stab;
+
+ /* If the COMMON block we are trying to add has a blank
+ name (i.e. "#BLNK_COM") then we set it to __BLANK
+ because the darn "#" character makes GDB's input
+ parser have fits. */
+
+
+ if (STREQ(name,BLANK_COMMON_NAME_ORIGINAL) ||
+ STREQ(name,BLANK_COMMON_NAME_MF77))
+ {
+
+ free(name);
+ name = alloca(strlen(BLANK_COMMON_NAME_LOCAL) + 1);
+ strcpy(name,BLANK_COMMON_NAME_LOCAL);
+ }
+
+ tmp = allocate_saved_f77_common_node();
+
+ local_copy_func_stab = xmalloc (strlen(func_stab) + 1);
+ strcpy(local_copy_func_stab,func_stab);
+
+ tmp->name = xmalloc(strlen(name) + 1);
+
+ /* local_copy_func_stab is a stabstring, let us first extract the
+ function name from the stab by NULLing out the ':' character. */
+
+
+ c = NULL;
+ c = strchr(local_copy_func_stab,':');
+
+ if (c)
+ *c = '\0';
+ else
+ error("Malformed function STAB found in add_common_block()");
+
+
+ tmp->owning_function = xmalloc (strlen(local_copy_func_stab) + 1);
+
+ strcpy(tmp->owning_function,local_copy_func_stab);
+
+ strcpy(tmp->name,name);
+ tmp->offset = offset;
+ tmp->next = NULL;
+ tmp->entries = NULL;
+ tmp->secnum = secnum;
+
+ current_common = tmp;
+
+ if (head_common_list == NULL)
+ {
+ head_common_list = tail_common_list = tmp;
+ }
+ else
+ {
+ tail_common_list->next = tmp;
+ tail_common_list = tmp;
+ }
+}
+#endif
+
+/* The following function simply enters a given common entry onto
+ the "current_common" block that has been saved away. */
+
+#if 0
+static void
+add_common_entry(entry_sym_ptr)
+ struct symbol *entry_sym_ptr;
+{
+ COMMON_ENTRY_PTR tmp;
+
+
+
+ /* The order of this list is important, since
+ we expect the entries to appear in decl.
+ order when we later issue "info common" calls */
+
+ tmp = allocate_common_entry_node();
+
+ tmp->next = NULL;
+ tmp->symbol = entry_sym_ptr;
+
+ if (current_common == NULL)
+ error("Attempt to add COMMON entry with no block open!");
+ else
+ {
+ if (current_common->entries == NULL)
+ {
+ current_common->entries = tmp;
+ current_common->end_of_entries = tmp;
+ }
+ else
+ {
+ current_common->end_of_entries->next = tmp;
+ current_common->end_of_entries = tmp;
+ }
+ }
+}
+#endif
+
+/* This routine finds the first encountred COMMON block named "name" */
+
+#if 0
+static SAVED_F77_COMMON_PTR
+find_first_common_named(name)
+ char *name;
+{
+
+ SAVED_F77_COMMON_PTR tmp;
+
+ tmp = head_common_list;
+
+ while (tmp != NULL)
+ {
+ if (STREQ(tmp->name,name))
+ return(tmp);
+ else
+ tmp = tmp->next;
+ }
+ return(NULL);
+}
+#endif
+
+/* This routine finds the first encountred COMMON block named "name"
+ that belongs to function funcname */
+
+SAVED_F77_COMMON_PTR find_common_for_function(name, funcname)
+ char *name;
+ char *funcname;
+{
+
+ SAVED_F77_COMMON_PTR tmp;
+
+ tmp = head_common_list;
+
+ while (tmp != NULL)
+ {
+ if (STREQ(tmp->name,name) && STREQ(tmp->owning_function,funcname))
+ return(tmp);
+ else
+ tmp = tmp->next;
+ }
+ return(NULL);
+}
+
+
+#if 0
+
+/* The following function is called to patch up the offsets
+ for the statics contained in the COMMON block named
+ "name." */
+
+static void
+patch_common_entries (blk, offset, secnum)
+ SAVED_F77_COMMON_PTR blk;
+ CORE_ADDR offset;
+ int secnum;
+{
+ COMMON_ENTRY_PTR entry;
+
+ blk->offset = offset; /* Keep this around for future use. */
+
+ entry = blk->entries;
+
+ while (entry != NULL)
+ {
+ SYMBOL_VALUE (entry->symbol) += offset;
+ SYMBOL_SECTION (entry->symbol) = secnum;
+
+ entry = entry->next;
+ }
+ blk->secnum = secnum;
+}
+
+/* Patch all commons named "name" that need patching.Since COMMON
+ blocks occur with relative infrequency, we simply do a linear scan on
+ the name. Eventually, the best way to do this will be a
+ hashed-lookup. Secnum is the section number for the .bss section
+ (which is where common data lives). */
+
+static void
+patch_all_commons_by_name (name, offset, secnum)
+ char *name;
+ CORE_ADDR offset;
+ int secnum;
+{
+
+ SAVED_F77_COMMON_PTR tmp;
+
+ /* For blank common blocks, change the canonical reprsentation
+ of a blank name */
+
+ if ((STREQ(name,BLANK_COMMON_NAME_ORIGINAL)) ||
+ (STREQ(name,BLANK_COMMON_NAME_MF77)))
+ {
+ free(name);
+ name = alloca(strlen(BLANK_COMMON_NAME_LOCAL) + 1);
+ strcpy(name,BLANK_COMMON_NAME_LOCAL);
+ }
+
+ tmp = head_common_list;
+
+ while (tmp != NULL)
+ {
+ if (COMMON_NEEDS_PATCHING(tmp))
+ if (STREQ(tmp->name,name))
+ patch_common_entries(tmp,offset,secnum);
+
+ tmp = tmp->next;
+ }
+}
+#endif
+
+/* This macro adds the symbol-number for the start of the function
+ (the symbol number of the .bf) referenced by symnum_fcn to a
+ list. This list, in reality should be a FIFO queue but since
+ #line pragmas sometimes cause line ranges to get messed up
+ we simply create a linear list. This list can then be searched
+ first by a queueing algorithm and upon failure fall back to
+ a linear scan. */
+
+#if 0
+#define ADD_BF_SYMNUM(bf_sym,fcn_sym) \
+ \
+ if (saved_bf_list == NULL) \
+{ \
+ tmp_bf_ptr = allocate_saved_bf_node(); \
+ \
+ tmp_bf_ptr->symnum_bf = (bf_sym); \
+ tmp_bf_ptr->symnum_fcn = (fcn_sym); \
+ tmp_bf_ptr->next = NULL; \
+ \
+ current_head_bf_list = saved_bf_list = tmp_bf_ptr; \
+ saved_bf_list_end = tmp_bf_ptr; \
+ } \
+else \
+{ \
+ tmp_bf_ptr = allocate_saved_bf_node(); \
+ \
+ tmp_bf_ptr->symnum_bf = (bf_sym); \
+ tmp_bf_ptr->symnum_fcn = (fcn_sym); \
+ tmp_bf_ptr->next = NULL; \
+ \
+ saved_bf_list_end->next = tmp_bf_ptr; \
+ saved_bf_list_end = tmp_bf_ptr; \
+ }
+#endif
+
+/* This function frees the entire (.bf,function) list */
+
+#if 0
+static void
+ clear_bf_list()
+{
+
+ SAVED_BF_PTR tmp = saved_bf_list;
+ SAVED_BF_PTR next = NULL;
+
+ while (tmp != NULL)
+ {
+ next = tmp->next;
+ free(tmp);
+ tmp=next;
+ }
+ saved_bf_list = NULL;
+}
+#endif
+
+int global_remote_debug;
+
+#if 0
+
+static long
+get_bf_for_fcn (the_function)
+ long the_function;
+{
+ SAVED_BF_PTR tmp;
+ int nprobes = 0;
+
+ /* First use a simple queuing algorithm (i.e. look and see if the
+ item at the head of the queue is the one you want) */
+
+ if (saved_bf_list == NULL)
+ fatal ("cannot get .bf node off empty list");
+
+ if (current_head_bf_list != NULL)
+ if (current_head_bf_list->symnum_fcn == the_function)
+ {
+ if (global_remote_debug)
+ fprintf(stderr,"*");
+
+ tmp = current_head_bf_list;
+ current_head_bf_list = current_head_bf_list->next;
+ return(tmp->symnum_bf);
+ }
+
+ /* If the above did not work (probably because #line directives were
+ used in the sourcefile and they messed up our internal tables) we now do
+ the ugly linear scan */
+
+ if (global_remote_debug)
+ fprintf(stderr,"\ndefaulting to linear scan\n");
+
+ nprobes = 0;
+ tmp = saved_bf_list;
+ while (tmp != NULL)
+ {
+ nprobes++;
+ if (tmp->symnum_fcn == the_function)
+ {
+ if (global_remote_debug)
+ fprintf(stderr,"Found in %d probes\n",nprobes);
+ current_head_bf_list = tmp->next;
+ return(tmp->symnum_bf);
+ }
+ tmp= tmp->next;
+ }
+
+ return(-1);
+}
+
+static SAVED_FUNCTION_PTR saved_function_list=NULL;
+static SAVED_FUNCTION_PTR saved_function_list_end=NULL;
+
+static void
+clear_function_list()
+{
+ SAVED_FUNCTION_PTR tmp = saved_function_list;
+ SAVED_FUNCTION_PTR next = NULL;
+
+ while (tmp != NULL)
+ {
+ next = tmp->next;
+ free(tmp);
+ tmp = next;
+ }
+
+ saved_function_list = NULL;
+}
+#endif
+
diff --git a/gdb/f-lang.h b/gdb/f-lang.h
new file mode 100644
index 00000000000..c6b8f028a23
--- /dev/null
+++ b/gdb/f-lang.h
@@ -0,0 +1,96 @@
+/* Fortran language support definitions for GDB, the GNU debugger.
+ Copyright 1992, 1993, 1994 Free Software Foundation, Inc.
+ Contributed by Motorola. Adapted from the C definitions by Farooq Butt
+ (fmbutt@engage.sps.mot.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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+extern int f_parse PARAMS ((void));
+
+extern void f_error PARAMS ((char *)); /* Defined in f-exp.y */
+
+extern void f_print_type PARAMS ((struct type *, char *,
+ GDB_FILE *, int, int));
+
+extern int f_val_print PARAMS ((struct type *, char *, int,
+ CORE_ADDR, GDB_FILE *,
+ int, int, int, enum val_prettyprint));
+
+/* Language-specific data structures */
+
+struct common_entry
+{
+ struct symbol *symbol; /* The symbol node corresponding
+ to this component */
+ struct common_entry *next; /* The next component */
+};
+
+struct saved_f77_common
+{
+ char *name; /* Name of COMMON */
+ char *owning_function; /* Name of parent function */
+ int secnum; /* Section # of .bss */
+ CORE_ADDR offset; /* Offset from .bss for
+ this block */
+ struct common_entry *entries; /* List of block's components */
+ struct common_entry *end_of_entries; /* ptr. to end of components */
+ struct saved_f77_common *next; /* Next saved COMMON block */
+};
+
+typedef struct saved_f77_common SAVED_F77_COMMON, *SAVED_F77_COMMON_PTR;
+
+typedef struct common_entry COMMON_ENTRY, *COMMON_ENTRY_PTR;
+
+extern SAVED_F77_COMMON_PTR head_common_list; /* Ptr to 1st saved COMMON */
+extern SAVED_F77_COMMON_PTR tail_common_list; /* Ptr to last saved COMMON */
+extern SAVED_F77_COMMON_PTR current_common; /* Ptr to current COMMON */
+
+extern SAVED_F77_COMMON_PTR find_common_for_function PARAMS ((char *, char *));
+
+#define UNINITIALIZED_SECNUM -1
+#define COMMON_NEEDS_PATCHING(blk) ((blk)->secnum == UNINITIALIZED_SECNUM)
+
+#define BLANK_COMMON_NAME_ORIGINAL "#BLNK_COM" /* XLF assigned */
+#define BLANK_COMMON_NAME_MF77 "__BLNK__" /* MF77 assigned */
+#define BLANK_COMMON_NAME_LOCAL "__BLANK" /* Local GDB */
+
+#define BOUND_FETCH_OK 1
+#define BOUND_FETCH_ERROR -999
+
+/* When reasonable array bounds cannot be fetched, such as when
+you ask to 'mt print symbols' and there is no stack frame and
+therefore no way of knowing the bounds of stack-based arrays,
+we have to assign default bounds, these are as good as any... */
+
+#define DEFAULT_UPPER_BOUND 999999
+#define DEFAULT_LOWER_BOUND -999999
+
+extern char *real_main_name; /* Name of main function */
+extern int real_main_c_value; /* C_value field of main function */
+
+extern int f77_get_dynamic_upperbound PARAMS ((struct type *, int *));
+
+extern int f77_get_dynamic_lowerbound PARAMS ((struct type *, int *));
+
+extern void f77_get_dynamic_array_length PARAMS ((struct type *));
+
+extern int calc_f77_array_dims PARAMS ((struct type *));
+
+#define DEFAULT_DOTMAIN_NAME_IN_MF77 ".MAIN_"
+#define DEFAULT_MAIN_NAME_IN_MF77 "MAIN_"
+#define DEFAULT_DOTMAIN_NAME_IN_XLF_BUGGY ".main "
+#define DEFAULT_DOTMAIN_NAME_IN_XLF ".main"
diff --git a/gdb/f-typeprint.c b/gdb/f-typeprint.c
new file mode 100644
index 00000000000..09bb3ebd095
--- /dev/null
+++ b/gdb/f-typeprint.c
@@ -0,0 +1,458 @@
+/* Support for printing Fortran types for GDB, the GNU debugger.
+ Copyright 1986, 1988, 1989, 1991, 1993, 1994 Free Software Foundation, Inc.
+ Contributed by Motorola. Adapted from the C version by Farooq Butt
+ (fmbutt@engage.sps.mot.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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "obstack.h"
+#include "bfd.h"
+#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 "f-lang.h"
+#include "typeprint.h"
+#include "frame.h" /* ??? */
+
+#include "gdb_string.h"
+#include <errno.h>
+
+#if 0 /* Currently unused */
+static void f_type_print_args PARAMS ((struct type *, GDB_FILE *));
+#endif
+
+static void print_equivalent_f77_float_type PARAMS ((struct type *,
+ GDB_FILE *));
+
+static void f_type_print_varspec_suffix PARAMS ((struct type *, GDB_FILE *,
+ int, int, int));
+
+void f_type_print_varspec_prefix PARAMS ((struct type *, GDB_FILE *,
+ int, int));
+
+void f_type_print_base PARAMS ((struct type *, GDB_FILE *, int, int));
+
+
+/* LEVEL is the depth to indent lines by. */
+
+void
+f_print_type (type, varstring, stream, show, level)
+ struct type *type;
+ char *varstring;
+ GDB_FILE *stream;
+ int show;
+ int level;
+{
+ register enum type_code code;
+ int demangled_args;
+
+ f_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);
+ f_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] == ')';
+ f_type_print_varspec_suffix (type, stream, show, 0, demangled_args);
+}
+
+/* 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
+f_type_print_varspec_prefix (type, stream, show, passed_a_ptr)
+ struct type *type;
+ GDB_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:
+ f_type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0, 1);
+ break;
+
+ case TYPE_CODE_FUNC:
+ f_type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0, 0);
+ if (passed_a_ptr)
+ fprintf_filtered (stream, "(");
+ break;
+
+ case TYPE_CODE_ARRAY:
+ f_type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0, 0);
+ 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:
+ case TYPE_CODE_METHOD:
+ case TYPE_CODE_MEMBER:
+ case TYPE_CODE_REF:
+ case TYPE_CODE_COMPLEX:
+ case TYPE_CODE_TYPEDEF:
+ /* These types need no prefix. They are listed here so that
+ gcc -Wall will reveal any types that haven't been handled. */
+ break;
+ }
+}
+
+#if 0 /* Currently unused */
+
+static void
+f_type_print_args (type, stream)
+ struct type *type;
+ GDB_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++)
+ {
+ f_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, ")");
+}
+
+#endif /* 0 */
+
+/* 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
+f_type_print_varspec_suffix (type, stream, show, passed_a_ptr, demangled_args)
+ struct type *type;
+ GDB_FILE *stream;
+ int show;
+ int passed_a_ptr;
+ int demangled_args;
+{
+ int upper_bound, lower_bound;
+ int lower_bound_was_default = 0;
+ static int arrayprint_recurse_level = 0;
+ int retcode;
+
+ if (type == 0)
+ return;
+
+ if (TYPE_NAME (type) && show <= 0)
+ return;
+
+ QUIT;
+
+ switch (TYPE_CODE (type))
+ {
+ case TYPE_CODE_ARRAY:
+ arrayprint_recurse_level++;
+
+ if (arrayprint_recurse_level == 1)
+ fprintf_filtered(stream,"(");
+
+ if (TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_ARRAY)
+ f_type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, 0, 0, 0);
+
+ retcode = f77_get_dynamic_lowerbound (type,&lower_bound);
+
+ lower_bound_was_default = 0;
+
+ if (retcode == BOUND_FETCH_ERROR)
+ fprintf_filtered (stream,"???");
+ else
+ if (lower_bound == 1) /* The default */
+ lower_bound_was_default = 1;
+ else
+ fprintf_filtered (stream,"%d",lower_bound);
+
+ if (lower_bound_was_default)
+ lower_bound_was_default = 0;
+ else
+ fprintf_filtered(stream,":");
+
+ /* Make sure that, if we have an assumed size array, we
+ print out a warning and print the upperbound as '*' */
+
+ if (TYPE_ARRAY_UPPER_BOUND_TYPE(type) == BOUND_CANNOT_BE_DETERMINED)
+ fprintf_filtered (stream, "*");
+ else
+ {
+ retcode = f77_get_dynamic_upperbound(type,&upper_bound);
+
+ if (retcode == BOUND_FETCH_ERROR)
+ fprintf_filtered(stream,"???");
+ else
+ fprintf_filtered(stream,"%d",upper_bound);
+ }
+
+ if (TYPE_CODE (TYPE_TARGET_TYPE (type)) != TYPE_CODE_ARRAY)
+ f_type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, 0, 0, 0);
+ if (arrayprint_recurse_level == 1)
+ fprintf_filtered (stream, ")");
+ else
+ fprintf_filtered(stream,",");
+ arrayprint_recurse_level--;
+ break;
+
+ case TYPE_CODE_PTR:
+ case TYPE_CODE_REF:
+ f_type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, 0, 1, 0);
+ fprintf_filtered(stream,")");
+ break;
+
+ case TYPE_CODE_FUNC:
+ f_type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, 0,
+ passed_a_ptr, 0);
+ if (passed_a_ptr)
+ fprintf_filtered (stream, ")");
+
+ fprintf_filtered (stream, "()");
+ break;
+
+ case TYPE_CODE_UNDEF:
+ case TYPE_CODE_STRUCT:
+ case TYPE_CODE_UNION:
+ case TYPE_CODE_ENUM:
+ case TYPE_CODE_INT:
+ case TYPE_CODE_FLT:
+ case TYPE_CODE_VOID:
+ case TYPE_CODE_ERROR:
+ case TYPE_CODE_CHAR:
+ case TYPE_CODE_BOOL:
+ case TYPE_CODE_SET:
+ case TYPE_CODE_RANGE:
+ case TYPE_CODE_STRING:
+ case TYPE_CODE_BITSTRING:
+ case TYPE_CODE_METHOD:
+ case TYPE_CODE_MEMBER:
+ case TYPE_CODE_COMPLEX:
+ case TYPE_CODE_TYPEDEF:
+ /* These types do not need a suffix. They are listed so that
+ gcc -Wall will report types that may not have been considered. */
+ break;
+ }
+}
+
+static void
+print_equivalent_f77_float_type (type, stream)
+ struct type *type;
+ GDB_FILE *stream;
+{
+ /* Override type name "float" and make it the
+ appropriate real. XLC stupidly outputs -12 as a type
+ for real when it really should be outputting -18 */
+
+ fprintf_filtered (stream, "real*%d", TYPE_LENGTH (type));
+}
+
+/* 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. */
+
+void
+f_type_print_base (type, stream, show, level)
+ struct type *type;
+ GDB_FILE *stream;
+ int show;
+ int level;
+{
+ int retcode;
+ int upper_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))
+ {
+ if (TYPE_CODE (type) == TYPE_CODE_FLT)
+ print_equivalent_f77_float_type (type, stream);
+ else
+ fputs_filtered (TYPE_NAME (type), stream);
+ return;
+ }
+
+ if (TYPE_CODE (type) != TYPE_CODE_TYPEDEF)
+ CHECK_TYPEDEF (type);
+
+ switch (TYPE_CODE (type))
+ {
+ case TYPE_CODE_TYPEDEF:
+ f_type_print_base (TYPE_TARGET_TYPE (type), stream, 0, level);
+ break;
+
+ case TYPE_CODE_ARRAY:
+ case TYPE_CODE_FUNC:
+ f_type_print_base (TYPE_TARGET_TYPE (type), stream, show, level);
+ break;
+
+ case TYPE_CODE_PTR:
+ fprintf_filtered (stream, "PTR TO -> ( ");
+ f_type_print_base (TYPE_TARGET_TYPE (type), stream, 0, level);
+ 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;
+
+ case TYPE_CODE_CHAR:
+ /* Override name "char" and make it "character" */
+ fprintf_filtered (stream, "character");
+ break;
+
+ case TYPE_CODE_INT:
+ /* There may be some character types that attempt to come
+ through as TYPE_CODE_INT since dbxstclass.h is so
+ C-oriented, we must change these to "character" from "char". */
+
+ if (STREQ (TYPE_NAME (type), "char"))
+ fprintf_filtered (stream, "character");
+ else
+ goto default_case;
+ break;
+
+ case TYPE_CODE_COMPLEX:
+ fprintf_filtered (stream, "complex*%d", TYPE_LENGTH (type));
+ break;
+
+ case TYPE_CODE_FLT:
+ print_equivalent_f77_float_type (type, stream);
+ break;
+
+ case TYPE_CODE_STRING:
+ /* Strings may have dynamic upperbounds (lengths) like arrays. */
+
+ if (TYPE_ARRAY_UPPER_BOUND_TYPE (type) == BOUND_CANNOT_BE_DETERMINED)
+ fprintf_filtered (stream, "character*(*)");
+ else
+ {
+ retcode = f77_get_dynamic_upperbound (type, &upper_bound);
+
+ if (retcode == BOUND_FETCH_ERROR)
+ fprintf_filtered (stream, "character*???");
+ else
+ fprintf_filtered (stream, "character*%d", upper_bound);
+ }
+ break;
+
+ default_case:
+ 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 ("Invalid type code (%d) in symbol table.", TYPE_CODE (type));
+ break;
+ }
+}
diff --git a/gdb/f-valprint.c b/gdb/f-valprint.c
new file mode 100644
index 00000000000..bb0b1d0efb1
--- /dev/null
+++ b/gdb/f-valprint.c
@@ -0,0 +1,767 @@
+/* Support for printing Fortran values for GDB, the GNU debugger.
+ Copyright 1993, 1994, 1995 Free Software Foundation, Inc.
+ Contributed by Motorola. Adapted from the C definitions by Farooq Butt
+ (fmbutt@engage.sps.mot.com), additionally worked over by Stan Shebs.
+
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "gdb_string.h"
+#include "symtab.h"
+#include "gdbtypes.h"
+#include "expression.h"
+#include "value.h"
+#include "demangle.h"
+#include "valprint.h"
+#include "language.h"
+#include "f-lang.h"
+#include "frame.h"
+#include "gdbcore.h"
+#include "command.h"
+
+#if 0
+static int there_is_a_visible_common_named PARAMS ((char *));
+#endif
+
+static void info_common_command PARAMS ((char *, int));
+static void list_all_visible_commons PARAMS ((char *));
+static void f77_print_array PARAMS ((struct type *, char *, CORE_ADDR,
+ GDB_FILE *, int, int, int,
+ enum val_prettyprint));
+static void f77_print_array_1 PARAMS ((int, int, struct type *, char *,
+ CORE_ADDR, GDB_FILE *, int, int, int,
+ enum val_prettyprint));
+static void f77_create_arrayprint_offset_tbl PARAMS ((struct type *,
+ GDB_FILE *));
+static void f77_get_dynamic_length_of_aggregate PARAMS ((struct type *));
+
+int f77_array_offset_tbl[MAX_FORTRAN_DIMS+1][2];
+
+/* Array which holds offsets to be applied to get a row's elements
+ for a given array. Array also holds the size of each subarray. */
+
+/* The following macro gives us the size of the nth dimension, Where
+ n is 1 based. */
+
+#define F77_DIM_SIZE(n) (f77_array_offset_tbl[n][1])
+
+/* The following gives us the offset for row n where n is 1-based. */
+
+#define F77_DIM_OFFSET(n) (f77_array_offset_tbl[n][0])
+
+int
+f77_get_dynamic_lowerbound (type, lower_bound)
+ struct type *type;
+ int *lower_bound;
+{
+ CORE_ADDR current_frame_addr;
+ CORE_ADDR ptr_to_lower_bound;
+
+ switch (TYPE_ARRAY_LOWER_BOUND_TYPE (type))
+ {
+ case BOUND_BY_VALUE_ON_STACK:
+ current_frame_addr = selected_frame->frame;
+ if (current_frame_addr > 0)
+ {
+ *lower_bound =
+ read_memory_integer (current_frame_addr +
+ TYPE_ARRAY_LOWER_BOUND_VALUE (type),
+ 4);
+ }
+ else
+ {
+ *lower_bound = DEFAULT_LOWER_BOUND;
+ return BOUND_FETCH_ERROR;
+ }
+ break;
+
+ case BOUND_SIMPLE:
+ *lower_bound = TYPE_ARRAY_LOWER_BOUND_VALUE (type);
+ break;
+
+ case BOUND_CANNOT_BE_DETERMINED:
+ error ("Lower bound may not be '*' in F77");
+ break;
+
+ case BOUND_BY_REF_ON_STACK:
+ current_frame_addr = selected_frame->frame;
+ if (current_frame_addr > 0)
+ {
+ ptr_to_lower_bound =
+ read_memory_integer (current_frame_addr +
+ TYPE_ARRAY_LOWER_BOUND_VALUE (type),
+ 4);
+ *lower_bound = read_memory_integer (ptr_to_lower_bound, 4);
+ }
+ else
+ {
+ *lower_bound = DEFAULT_LOWER_BOUND;
+ return BOUND_FETCH_ERROR;
+ }
+ break;
+
+ case BOUND_BY_REF_IN_REG:
+ case BOUND_BY_VALUE_IN_REG:
+ default:
+ error ("??? unhandled dynamic array bound type ???");
+ break;
+ }
+ return BOUND_FETCH_OK;
+}
+
+int
+f77_get_dynamic_upperbound (type, upper_bound)
+ struct type *type;
+ int *upper_bound;
+{
+ CORE_ADDR current_frame_addr = 0;
+ CORE_ADDR ptr_to_upper_bound;
+
+ switch (TYPE_ARRAY_UPPER_BOUND_TYPE (type))
+ {
+ case BOUND_BY_VALUE_ON_STACK:
+ current_frame_addr = selected_frame->frame;
+ if (current_frame_addr > 0)
+ {
+ *upper_bound =
+ read_memory_integer (current_frame_addr +
+ TYPE_ARRAY_UPPER_BOUND_VALUE (type),
+ 4);
+ }
+ else
+ {
+ *upper_bound = DEFAULT_UPPER_BOUND;
+ return BOUND_FETCH_ERROR;
+ }
+ break;
+
+ case BOUND_SIMPLE:
+ *upper_bound = TYPE_ARRAY_UPPER_BOUND_VALUE (type);
+ break;
+
+ case BOUND_CANNOT_BE_DETERMINED:
+ /* we have an assumed size array on our hands. Assume that
+ upper_bound == lower_bound so that we show at least
+ 1 element.If the user wants to see more elements, let
+ him manually ask for 'em and we'll subscript the
+ array and show him */
+ f77_get_dynamic_lowerbound (type, upper_bound);
+ break;
+
+ case BOUND_BY_REF_ON_STACK:
+ current_frame_addr = selected_frame->frame;
+ if (current_frame_addr > 0)
+ {
+ ptr_to_upper_bound =
+ read_memory_integer (current_frame_addr +
+ TYPE_ARRAY_UPPER_BOUND_VALUE (type),
+ 4);
+ *upper_bound = read_memory_integer(ptr_to_upper_bound, 4);
+ }
+ else
+ {
+ *upper_bound = DEFAULT_UPPER_BOUND;
+ return BOUND_FETCH_ERROR;
+ }
+ break;
+
+ case BOUND_BY_REF_IN_REG:
+ case BOUND_BY_VALUE_IN_REG:
+ default:
+ error ("??? unhandled dynamic array bound type ???");
+ break;
+ }
+ return BOUND_FETCH_OK;
+}
+
+/* Obtain F77 adjustable array dimensions */
+
+static void
+f77_get_dynamic_length_of_aggregate (type)
+ struct type *type;
+{
+ int upper_bound = -1;
+ int lower_bound = 1;
+ int retcode;
+
+ /* Recursively go all the way down into a possibly multi-dimensional
+ F77 array and get the bounds. For simple arrays, this is pretty
+ easy but when the bounds are dynamic, we must be very careful
+ to add up all the lengths correctly. Not doing this right
+ will lead to horrendous-looking arrays in parameter lists.
+
+ This function also works for strings which behave very
+ similarly to arrays. */
+
+ if (TYPE_CODE(TYPE_TARGET_TYPE (type)) == TYPE_CODE_ARRAY
+ || TYPE_CODE(TYPE_TARGET_TYPE (type)) == TYPE_CODE_STRING)
+ f77_get_dynamic_length_of_aggregate (TYPE_TARGET_TYPE (type));
+
+ /* Recursion ends here, start setting up lengths. */
+ retcode = f77_get_dynamic_lowerbound (type, &lower_bound);
+ if (retcode == BOUND_FETCH_ERROR)
+ error ("Cannot obtain valid array lower bound");
+
+ retcode = f77_get_dynamic_upperbound (type, &upper_bound);
+ if (retcode == BOUND_FETCH_ERROR)
+ error ("Cannot obtain valid array upper bound");
+
+ /* Patch in a valid length value. */
+
+ TYPE_LENGTH (type) =
+ (upper_bound - lower_bound + 1) * TYPE_LENGTH (check_typedef (TYPE_TARGET_TYPE (type)));
+}
+
+/* Function that sets up the array offset,size table for the array
+ type "type". */
+
+static void
+f77_create_arrayprint_offset_tbl (type, stream)
+ struct type *type;
+ GDB_FILE *stream;
+{
+ struct type *tmp_type;
+ int eltlen;
+ int ndimen = 1;
+ int upper, lower, retcode;
+
+ tmp_type = type;
+
+ while ((TYPE_CODE (tmp_type) == TYPE_CODE_ARRAY))
+ {
+ if (TYPE_ARRAY_UPPER_BOUND_TYPE (tmp_type) == BOUND_CANNOT_BE_DETERMINED)
+ fprintf_filtered (stream, "<assumed size array> ");
+
+ retcode = f77_get_dynamic_upperbound (tmp_type, &upper);
+ if (retcode == BOUND_FETCH_ERROR)
+ error ("Cannot obtain dynamic upper bound");
+
+ retcode = f77_get_dynamic_lowerbound(tmp_type,&lower);
+ if (retcode == BOUND_FETCH_ERROR)
+ error("Cannot obtain dynamic lower bound");
+
+ F77_DIM_SIZE (ndimen) = upper - lower + 1;
+
+ tmp_type = TYPE_TARGET_TYPE (tmp_type);
+ ndimen++;
+ }
+
+ /* Now we multiply eltlen by all the offsets, so that later we
+ can print out array elements correctly. Up till now we
+ know an offset to apply to get the item but we also
+ have to know how much to add to get to the next item */
+
+ ndimen--;
+ eltlen = TYPE_LENGTH (tmp_type);
+ F77_DIM_OFFSET (ndimen) = eltlen;
+ while (--ndimen > 0)
+ {
+ eltlen *= F77_DIM_SIZE (ndimen + 1);
+ F77_DIM_OFFSET (ndimen) = eltlen;
+ }
+}
+
+/* Actual function which prints out F77 arrays, Valaddr == address in
+ the superior. Address == the address in the inferior. */
+
+static void
+f77_print_array_1 (nss, ndimensions, type, valaddr, address,
+ stream, format, deref_ref, recurse, pretty)
+ int nss;
+ int ndimensions;
+ struct type *type;
+ char *valaddr;
+ CORE_ADDR address;
+ GDB_FILE *stream;
+ int format;
+ int deref_ref;
+ int recurse;
+ enum val_prettyprint pretty;
+{
+ int i;
+
+ if (nss != ndimensions)
+ {
+ for (i = 0; i< F77_DIM_SIZE(nss); i++)
+ {
+ fprintf_filtered (stream, "( ");
+ f77_print_array_1 (nss + 1, ndimensions, TYPE_TARGET_TYPE (type),
+ valaddr + i * F77_DIM_OFFSET (nss),
+ address + i * F77_DIM_OFFSET (nss),
+ stream, format, deref_ref, recurse, pretty);
+ fprintf_filtered (stream, ") ");
+ }
+ }
+ else
+ {
+ for (i = 0; (i < F77_DIM_SIZE (nss) && i < print_max); i++)
+ {
+ val_print (TYPE_TARGET_TYPE (type),
+ valaddr + i * F77_DIM_OFFSET (ndimensions),
+ 0,
+ address + i * F77_DIM_OFFSET (ndimensions),
+ stream, format, deref_ref, recurse, pretty);
+
+ if (i != (F77_DIM_SIZE (nss) - 1))
+ fprintf_filtered (stream, ", ");
+
+ if (i == print_max - 1)
+ fprintf_filtered (stream, "...");
+ }
+ }
+}
+
+/* This function gets called to print an F77 array, we set up some
+ stuff and then immediately call f77_print_array_1() */
+
+static void
+f77_print_array (type, valaddr, address, stream, format, deref_ref, recurse,
+ pretty)
+ struct type *type;
+ char *valaddr;
+ CORE_ADDR address;
+ GDB_FILE *stream;
+ int format;
+ int deref_ref;
+ int recurse;
+ enum val_prettyprint pretty;
+{
+ int ndimensions;
+
+ ndimensions = calc_f77_array_dims (type);
+
+ if (ndimensions > MAX_FORTRAN_DIMS || ndimensions < 0)
+ error ("Type node corrupt! F77 arrays cannot have %d subscripts (%d Max)",
+ ndimensions, MAX_FORTRAN_DIMS);
+
+ /* Since F77 arrays are stored column-major, we set up an
+ offset table to get at the various row's elements. The
+ offset table contains entries for both offset and subarray size. */
+
+ f77_create_arrayprint_offset_tbl (type, stream);
+
+ f77_print_array_1 (1, ndimensions, type, valaddr, address, stream, format,
+ deref_ref, recurse, pretty);
+}
+
+
+/* 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
+f_val_print (type, valaddr, embedded_offset, address, stream, format, deref_ref, recurse,
+ pretty)
+ struct type *type;
+ char *valaddr;
+ int embedded_offset;
+ CORE_ADDR address;
+ GDB_FILE *stream;
+ int format;
+ int deref_ref;
+ int recurse;
+ enum val_prettyprint pretty;
+{
+ register unsigned int i = 0; /* Number of characters printed */
+ struct type *elttype;
+ LONGEST val;
+ CORE_ADDR addr;
+
+ CHECK_TYPEDEF (type);
+ switch (TYPE_CODE (type))
+ {
+ case TYPE_CODE_STRING:
+ f77_get_dynamic_length_of_aggregate (type);
+ LA_PRINT_STRING (stream, valaddr, TYPE_LENGTH (type), 1, 0);
+ break;
+
+ case TYPE_CODE_ARRAY:
+ fprintf_filtered (stream, "(");
+ f77_print_array (type, valaddr, address, stream, format,
+ deref_ref, recurse, pretty);
+ fprintf_filtered (stream, ")");
+ break;
+#if 0
+ /* Array of unspecified length: treat like pointer to first elt. */
+ valaddr = (char *) &address;
+ /* FALL THROUGH */
+#endif
+ case TYPE_CODE_PTR:
+ if (format && format != 's')
+ {
+ print_scalar_formatted (valaddr, type, format, 0, stream);
+ break;
+ }
+ else
+ {
+ addr = unpack_pointer (type, valaddr);
+ elttype = check_typedef (TYPE_TARGET_TYPE (type));
+
+ if (TYPE_CODE (elttype) == TYPE_CODE_FUNC)
+ {
+ /* Try to print what function it points to. */
+ print_address_demangle (addr, stream, demangle);
+ /* Return value is irrelevant except for string pointers. */
+ return 0;
+ }
+
+ if (addressprint && format != 's')
+ fprintf_filtered (stream, "0x%x", addr);
+
+ /* For a pointer to char or unsigned char, also print the string
+ pointed to, unless pointer is null. */
+ if (TYPE_LENGTH (elttype) == 1
+ && TYPE_CODE (elttype) == TYPE_CODE_INT
+ && (format == 0 || format == 's')
+ && addr != 0)
+ i = val_print_string (addr, -1, TYPE_LENGTH (elttype), 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_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_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_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_BOOL:
+ format = format ? format : output_format;
+ if (format)
+ print_scalar_formatted (valaddr, type, format, 0, stream);
+ else
+ {
+ val = 0;
+ switch (TYPE_LENGTH(type))
+ {
+ case 1:
+ val = unpack_long (builtin_type_f_logical_s1, valaddr);
+ break ;
+
+ case 2:
+ val = unpack_long (builtin_type_f_logical_s2, valaddr);
+ break ;
+
+ case 4:
+ val = unpack_long (builtin_type_f_logical, valaddr);
+ break ;
+
+ default:
+ error ("Logicals of length %d bytes not supported",
+ TYPE_LENGTH (type));
+
+ }
+
+ if (val == 0)
+ fprintf_filtered (stream, ".FALSE.");
+ else
+ if (val == 1)
+ fprintf_filtered (stream, ".TRUE.");
+ else
+ /* Not a legitimate logical type, print as an integer. */
+ {
+ /* Bash the type code temporarily. */
+ TYPE_CODE (type) = TYPE_CODE_INT;
+ f_val_print (type, valaddr, 0, address, stream, format,
+ deref_ref, recurse, pretty);
+ /* Restore the type code so later uses work as intended. */
+ TYPE_CODE (type) = TYPE_CODE_BOOL;
+ }
+ }
+ break;
+
+ case TYPE_CODE_COMPLEX:
+ switch (TYPE_LENGTH (type))
+ {
+ case 8: type = builtin_type_f_real; break;
+ case 16: type = builtin_type_f_real_s8; break;
+ case 32: type = builtin_type_f_real_s16; break;
+ default:
+ error ("Cannot print out complex*%d variables", TYPE_LENGTH(type));
+ }
+ fputs_filtered ("(", stream);
+ print_floating (valaddr, type, stream);
+ fputs_filtered (",", stream);
+ print_floating (valaddr, type, stream);
+ fputs_filtered (")", stream);
+ 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 F77 type code %d in symbol table.", TYPE_CODE (type));
+ }
+ gdb_flush (stream);
+ return 0;
+}
+
+static void
+list_all_visible_commons (funname)
+ char *funname;
+{
+ SAVED_F77_COMMON_PTR tmp;
+
+ tmp = head_common_list;
+
+ printf_filtered ("All COMMON blocks visible at this level:\n\n");
+
+ while (tmp != NULL)
+ {
+ if (STREQ(tmp->owning_function,funname))
+ printf_filtered ("%s\n", tmp->name);
+
+ tmp = tmp->next;
+ }
+}
+
+/* This function is used to print out the values in a given COMMON
+ block. It will always use the most local common block of the
+ given name */
+
+static void
+info_common_command (comname, from_tty)
+ char *comname;
+ int from_tty;
+{
+ SAVED_F77_COMMON_PTR the_common;
+ COMMON_ENTRY_PTR entry;
+ struct frame_info *fi;
+ register char *funname = 0;
+ struct symbol *func;
+
+ /* We have been told to display the contents of F77 COMMON
+ block supposedly visible in this function. Let us
+ first make sure that it is visible and if so, let
+ us display its contents */
+
+ fi = selected_frame;
+
+ if (fi == NULL)
+ error ("No frame selected");
+
+ /* The following is generally ripped off from stack.c's routine
+ print_frame_info() */
+
+ 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 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.
+ FIXME: (Not necessarily true. What about text labels) */
+
+ struct minimal_symbol *msymbol = lookup_minimal_symbol_by_pc (fi->pc);
+
+ if (msymbol != NULL
+ && (SYMBOL_VALUE_ADDRESS (msymbol)
+ > BLOCK_START (SYMBOL_BLOCK_VALUE (func))))
+ funname = SYMBOL_NAME (msymbol);
+ else
+ funname = SYMBOL_NAME (func);
+ }
+ else
+ {
+ register struct minimal_symbol *msymbol =
+ lookup_minimal_symbol_by_pc (fi->pc);
+
+ if (msymbol != NULL)
+ funname = SYMBOL_NAME (msymbol);
+ }
+
+ /* If comname is NULL, we assume the user wishes to see the
+ which COMMON blocks are visible here and then return */
+
+ if (comname == 0)
+ {
+ list_all_visible_commons (funname);
+ return;
+ }
+
+ the_common = find_common_for_function (comname,funname);
+
+ if (the_common)
+ {
+ if (STREQ(comname,BLANK_COMMON_NAME_LOCAL))
+ printf_filtered ("Contents of blank COMMON block:\n");
+ else
+ printf_filtered ("Contents of F77 COMMON block '%s':\n",comname);
+
+ printf_filtered ("\n");
+ entry = the_common->entries;
+
+ while (entry != NULL)
+ {
+ printf_filtered ("%s = ",SYMBOL_NAME(entry->symbol));
+ print_variable_value (entry->symbol, fi, gdb_stdout);
+ printf_filtered ("\n");
+ entry = entry->next;
+ }
+ }
+ else
+ printf_filtered ("Cannot locate the common block %s in function '%s'\n",
+ comname, funname);
+}
+
+/* This function is used to determine whether there is a
+ F77 common block visible at the current scope called 'comname'. */
+
+#if 0
+static int
+there_is_a_visible_common_named (comname)
+ char *comname;
+{
+ SAVED_F77_COMMON_PTR the_common;
+ struct frame_info *fi;
+ register char *funname = 0;
+ struct symbol *func;
+
+ if (comname == NULL)
+ error ("Cannot deal with NULL common name!");
+
+ fi = selected_frame;
+
+ if (fi == NULL)
+ error ("No frame selected");
+
+ /* The following is generally ripped off from stack.c's routine
+ print_frame_info() */
+
+ 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 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.
+ FIXME: (Not necessarily true. What about text labels) */
+
+ struct minimal_symbol *msymbol = lookup_minimal_symbol_by_pc (fi->pc);
+
+ if (msymbol != NULL
+ && (SYMBOL_VALUE_ADDRESS (msymbol)
+ > BLOCK_START (SYMBOL_BLOCK_VALUE (func))))
+ funname = SYMBOL_NAME (msymbol);
+ else
+ funname = SYMBOL_NAME (func);
+ }
+ else
+ {
+ register struct minimal_symbol *msymbol =
+ lookup_minimal_symbol_by_pc (fi->pc);
+
+ if (msymbol != NULL)
+ funname = SYMBOL_NAME (msymbol);
+ }
+
+ the_common = find_common_for_function (comname, funname);
+
+ return (the_common ? 1 : 0);
+}
+#endif
+
+void
+_initialize_f_valprint ()
+{
+ add_info ("common", info_common_command,
+ "Print out the values contained in a Fortran COMMON block.");
+ if (xdb_commands)
+ add_com("lc", class_info, info_common_command,
+ "Print out the values contained in a Fortran COMMON block.");
+}
diff --git a/gdb/findvar.c b/gdb/findvar.c
new file mode 100644
index 00000000000..5bfecc22a7e
--- /dev/null
+++ b/gdb/findvar.c
@@ -0,0 +1,1630 @@
+/* Find a variable's value in memory, for GDB, the GNU debugger.
+ Copyright 1986, 87, 89, 91, 94, 95, 96, 1998
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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"
+#include "gdb_string.h"
+#include "floatformat.h"
+#include "symfile.h" /* for overlay functions */
+
+/* This is used to indicate that we don't know the format of the floating point
+ number. Typically, this is useful for native ports, where the actual format
+ is irrelevant, since no conversions will be taking place. */
+
+const struct floatformat floatformat_unknown;
+
+/* Registers we shouldn't try to store. */
+#if !defined (CANNOT_STORE_REGISTER)
+#define CANNOT_STORE_REGISTER(regno) 0
+#endif
+
+static void write_register_gen PARAMS ((int, char *));
+
+/* 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 > (int) 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;
+ /* Do the sign extension once at the start. */
+ retval = ((LONGEST)*p ^ 0x80) - 0x80;
+ for (++p; p < endaddr; ++p)
+ retval = (retval << 8) | *p;
+ }
+ else
+ {
+ p = endaddr - 1;
+ /* Do the sign extension once at the start. */
+ retval = ((LONGEST)*p ^ 0x80) - 0x80;
+ for (--p; p >= startaddr; --p)
+ retval = (retval << 8) | *p;
+ }
+ return retval;
+}
+
+ULONGEST
+extract_unsigned_integer (addr, len)
+ PTR addr;
+ int len;
+{
+ ULONGEST retval;
+ unsigned char *p;
+ unsigned char *startaddr = (unsigned char *)addr;
+ unsigned char *endaddr = startaddr + len;
+
+ if (len > (int) sizeof (ULONGEST))
+ error ("\
+That operation is not available on integers of more than %d bytes.",
+ sizeof (ULONGEST));
+
+ /* 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)
+ retval = (retval << 8) | *p;
+ }
+ else
+ {
+ for (p = endaddr - 1; p >= startaddr; --p)
+ retval = (retval << 8) | *p;
+ }
+ return retval;
+}
+
+/* Sometimes a long long unsigned integer can be extracted as a
+ LONGEST value. This is done so that we can print these values
+ better. If this integer can be converted to a LONGEST, this
+ function returns 1 and sets *PVAL. Otherwise it returns 0. */
+
+int
+extract_long_unsigned_integer (addr, orig_len, pval)
+ PTR addr;
+ int orig_len;
+ LONGEST *pval;
+{
+ char *p, *first_addr;
+ int len;
+
+ len = orig_len;
+ if (TARGET_BYTE_ORDER == BIG_ENDIAN)
+ {
+ for (p = (char *) addr;
+ len > (int) sizeof (LONGEST) && p < (char *) addr + orig_len;
+ p++)
+ {
+ if (*p == 0)
+ len--;
+ else
+ break;
+ }
+ first_addr = p;
+ }
+ else
+ {
+ first_addr = (char *) addr;
+ for (p = (char *) addr + orig_len - 1;
+ len > (int) sizeof (LONGEST) && p >= (char *) addr;
+ p--)
+ {
+ if (*p == 0)
+ len--;
+ else
+ break;
+ }
+ }
+
+ if (len <= (int) sizeof (LONGEST))
+ {
+ *pval = (LONGEST) extract_unsigned_integer (first_addr,
+ sizeof (LONGEST));
+ return 1;
+ }
+
+ return 0;
+}
+
+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 (CORE_ADDR)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)
+ {
+ *p = val & 0xff;
+ val >>= 8;
+ }
+ }
+ else
+ {
+ for (p = startaddr; p < endaddr; ++p)
+ {
+ *p = val & 0xff;
+ val >>= 8;
+ }
+ }
+}
+
+void
+store_unsigned_integer (addr, len, val)
+ PTR addr;
+ int len;
+ ULONGEST 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)
+ {
+ *p = val & 0xff;
+ val >>= 8;
+ }
+ }
+ else
+ {
+ for (p = startaddr; p < endaddr; ++p)
+ {
+ *p = val & 0xff;
+ val >>= 8;
+ }
+ }
+}
+
+/* Store the literal address "val" into
+ gdb-local memory pointed to by "addr"
+ for "len" bytes. */
+void
+store_address (addr, len, val)
+ PTR addr;
+ int len;
+ LONGEST val;
+{
+ if( TARGET_BYTE_ORDER == BIG_ENDIAN
+ && len != sizeof( LONGEST )) {
+ /* On big-endian machines (e.g., HPPA 2.0, narrow mode)
+ * just letting this fall through to the call below will
+ * lead to the wrong bits being stored.
+ *
+ * Only the simplest case is fixed here, the others just
+ * get the old behavior.
+ */
+ if( (len == sizeof( CORE_ADDR ))
+ && (sizeof( LONGEST ) == 2 * sizeof( CORE_ADDR ))) {
+ /* Watch out! The high bits are garbage! */
+ CORE_ADDR coerce[2];
+ *(LONGEST*)&coerce = val;
+
+ store_unsigned_integer (addr, len, coerce[1] ); /* BIG_ENDIAN code! */
+ return;
+ }
+ }
+ store_unsigned_integer (addr, len, val);
+}
+
+/* Swap LEN bytes at BUFFER between target and host byte-order. */
+#define SWAP_FLOATING(buffer,len) \
+ do \
+ { \
+ if (TARGET_BYTE_ORDER != HOST_BYTE_ORDER) \
+ { \
+ char tmp; \
+ char *p = (char *)(buffer); \
+ char *q = ((char *)(buffer)) + len - 1; \
+ for (; p < q; p++, q--) \
+ { \
+ tmp = *q; \
+ *q = *p; \
+ *p = tmp; \
+ } \
+ } \
+ } \
+ while (0)
+
+/* Extract a floating-point number from a target-order byte-stream at ADDR.
+ Returns the value as type DOUBLEST.
+
+ If the host and target formats agree, we just copy the raw data into the
+ appropriate type of variable and return, letting the host increase precision
+ as necessary. Otherwise, we call the conversion routine and let it do the
+ dirty work. */
+
+DOUBLEST
+extract_floating (addr, len)
+ PTR addr;
+ int len;
+{
+ DOUBLEST dretval;
+
+ if (len == sizeof (float))
+ {
+ if (HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT)
+ {
+ float retval;
+
+ memcpy (&retval, addr, sizeof (retval));
+ return retval;
+ }
+ else
+ floatformat_to_doublest (TARGET_FLOAT_FORMAT, addr, &dretval);
+ }
+ else if (len == sizeof (double))
+ {
+ if (HOST_DOUBLE_FORMAT == TARGET_DOUBLE_FORMAT)
+ {
+ double retval;
+
+ memcpy (&retval, addr, sizeof (retval));
+ return retval;
+ }
+ else
+ floatformat_to_doublest (TARGET_DOUBLE_FORMAT, addr, &dretval);
+ }
+ else if (len == sizeof (DOUBLEST))
+ {
+ if (HOST_LONG_DOUBLE_FORMAT == TARGET_LONG_DOUBLE_FORMAT)
+ {
+ DOUBLEST retval;
+
+ memcpy (&retval, addr, sizeof (retval));
+ return retval;
+ }
+ else
+ floatformat_to_doublest (TARGET_LONG_DOUBLE_FORMAT, addr, &dretval);
+ }
+ else
+ {
+ error ("Can't deal with a floating point number of %d bytes.", len);
+ }
+
+ return dretval;
+}
+
+void
+store_floating (addr, len, val)
+ PTR addr;
+ int len;
+ DOUBLEST val;
+{
+ if (len == sizeof (float))
+ {
+ if (HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT)
+ {
+ float floatval = val;
+
+ memcpy (addr, &floatval, sizeof (floatval));
+ }
+ else
+ floatformat_from_doublest (TARGET_FLOAT_FORMAT, &val, addr);
+ }
+ else if (len == sizeof (double))
+ {
+ if (HOST_DOUBLE_FORMAT == TARGET_DOUBLE_FORMAT)
+ {
+ double doubleval = val;
+
+ memcpy (addr, &doubleval, sizeof (doubleval));
+ }
+ else
+ floatformat_from_doublest (TARGET_DOUBLE_FORMAT, &val, addr);
+ }
+ else if (len == sizeof (DOUBLEST))
+ {
+ if (HOST_LONG_DOUBLE_FORMAT == TARGET_LONG_DOUBLE_FORMAT)
+ memcpy (addr, &val, sizeof (val));
+ else
+ floatformat_from_doublest (TARGET_LONG_DOUBLE_FORMAT, &val, addr);
+ }
+ else
+ {
+ error ("Can't deal with a floating point number of %d bytes.", len);
+ }
+}
+
+#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)
+ struct frame_info *frame;
+ int regnum;
+{
+ register struct frame_info *frame1 = NULL;
+ register CORE_ADDR addr = 0;
+
+ if (frame == NULL) /* 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;
+
+ FRAME_INIT_SAVED_REGS (frame1);
+ return frame1->saved_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;
+ FRAME_INIT_SAVED_REGS (frame1);
+ if (frame1->saved_regs[regnum])
+ addr = frame1->saved_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;
+ struct frame_info *frame;
+ int regnum;
+ enum lval_type *lval;
+{
+ CORE_ADDR addr;
+
+ if (!target_has_registers)
+ error ("No registers.");
+
+ /* 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), (LONGEST)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 input 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_for_frame (regnum, myaddr, frame)
+ int regnum;
+ char *myaddr;
+ struct frame_info *frame;
+{
+ int optim;
+ if (regnum == FP_REGNUM && frame)
+ {
+ /* Put it back in target format. */
+ store_address (myaddr, REGISTER_RAW_SIZE(FP_REGNUM),
+ (LONGEST)FRAME_FP(frame));
+
+ return 0;
+ }
+
+ get_saved_register (myaddr, &optim, (CORE_ADDR *) NULL, frame,
+ regnum, (enum lval_type *)NULL);
+
+ if (register_valid [regnum] < 0)
+ return 1; /* register value not available */
+
+ return optim;
+}
+
+/* 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;
+{
+ return read_relative_register_raw_bytes_for_frame (regnum, myaddr,
+ selected_frame);
+}
+
+/* Return a `value' with the contents of register REGNUM
+ in its virtual format, with the type specified by
+ REGISTER_VIRTUAL_TYPE.
+
+ NOTE: returns NULL if register value is not available.
+ Caller will check return value or die! */
+
+value_ptr
+value_of_register (regnum)
+ int regnum;
+{
+ CORE_ADDR addr;
+ int optim;
+ register value_ptr reg_val;
+ char raw_buffer[MAX_REGISTER_RAW_SIZE];
+ enum lval_type lval;
+
+ get_saved_register (raw_buffer, &optim, &addr,
+ selected_frame, regnum, &lval);
+
+ if (register_valid[regnum] < 0)
+ return NULL; /* register value not available */
+
+ reg_val = allocate_value (REGISTER_VIRTUAL_TYPE (regnum));
+
+ /* Convert raw data to virtual format if necessary. */
+
+#ifdef REGISTER_CONVERTIBLE
+ if (REGISTER_CONVERTIBLE (regnum))
+ {
+ REGISTER_CONVERT_TO_VIRTUAL (regnum, REGISTER_VIRTUAL_TYPE (regnum),
+ raw_buffer, VALUE_CONTENTS_RAW (reg_val));
+ }
+ else
+#endif
+ if (REGISTER_RAW_SIZE (regnum) == REGISTER_VIRTUAL_SIZE (regnum))
+ memcpy (VALUE_CONTENTS_RAW (reg_val), raw_buffer,
+ REGISTER_RAW_SIZE (regnum));
+ else
+ fatal ("Register \"%s\" (%d) has conflicting raw (%d) and virtual (%d) size",
+ REGISTER_NAME (regnum), regnum,
+ REGISTER_RAW_SIZE (regnum), REGISTER_VIRTUAL_SIZE (regnum));
+ VALUE_LVAL (reg_val) = lval;
+ VALUE_ADDRESS (reg_val) = addr;
+ VALUE_REGNO (reg_val) = regnum;
+ VALUE_OPTIMIZED_OUT (reg_val) = optim;
+ return reg_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,
+ -1 if register value not available. */
+SIGNED char register_valid[NUM_REGS];
+
+/* The thread/process associated with the current set of registers. For now,
+ -1 is special, and means `no current process'. */
+int registers_pid = -1;
+
+/* Indicate that registers may have changed, so invalidate the cache. */
+
+void
+registers_changed ()
+{
+ int i;
+ int numregs = ARCH_NUM_REGS;
+
+ registers_pid = -1;
+
+ /* Force cleanup of any alloca areas if using C alloca instead of
+ a builtin alloca. This particular call is used to clean up
+ areas allocated by low level target code which may build up
+ during lengthy interactions between gdb and the target before
+ gdb gives control to the user (ie watchpoints). */
+ alloca (0);
+
+ for (i = 0; i < numregs; i++)
+ register_valid[i] = 0;
+
+ if (registers_changed_hook)
+ registers_changed_hook ();
+}
+
+/* Indicate that all registers have been fetched, so mark them all valid. */
+void
+registers_fetched ()
+{
+ int i;
+ int numregs = ARCH_NUM_REGS;
+ for (i = 0; i < numregs; i++)
+ register_valid[i] = 1;
+}
+
+/* read_register_bytes and write_register_bytes are generally a *BAD* idea.
+ They are inefficient because they need to check for partial updates, which
+ can only be done by scanning through all of the registers and seeing if the
+ bytes that are being read/written fall inside of an invalid register. [The
+ main reason this is necessary is that register sizes can vary, so a simple
+ index won't suffice.] It is far better to call read_register_gen if you
+ want to get at the raw register contents, as it only takes a regno as an
+ argument, and therefore can't do a partial register update. It would also
+ be good to have a write_register_gen for similar reasons.
+
+ Prior to the recent fixes to check for partial updates, both read and
+ write_register_bytes always checked to see if any registers were stale, and
+ then called target_fetch_registers (-1) to update the whole set. This
+ caused really slowed things down for remote targets. */
+
+/* Copy INLEN bytes of consecutive data from registers
+ starting with the INREGBYTE'th byte of register data
+ into memory at MYADDR. */
+
+void
+read_register_bytes (inregbyte, myaddr, inlen)
+ int inregbyte;
+ char *myaddr;
+ int inlen;
+{
+ int inregend = inregbyte + inlen;
+ int regno;
+
+ if (registers_pid != inferior_pid)
+ {
+ registers_changed ();
+ registers_pid = inferior_pid;
+ }
+
+ /* See if we are trying to read bytes from out-of-date registers. If so,
+ update just those registers. */
+
+ for (regno = 0; regno < NUM_REGS; regno++)
+ {
+ int regstart, regend;
+ int startin, endin;
+
+ if (register_valid[regno])
+ continue;
+
+ if (REGISTER_NAME (regno) == NULL || *REGISTER_NAME (regno) == '\0')
+ continue;
+
+ regstart = REGISTER_BYTE (regno);
+ regend = regstart + REGISTER_RAW_SIZE (regno);
+
+ startin = regstart >= inregbyte && regstart < inregend;
+ endin = regend > inregbyte && regend <= inregend;
+
+ if (!startin && !endin)
+ continue;
+
+ /* We've found an invalid register where at least one byte will be read.
+ Update it from the target. */
+
+ target_fetch_registers (regno);
+
+ if (!register_valid[regno])
+ error ("read_register_bytes: Couldn't update register %d.", regno);
+ }
+
+ if (myaddr != NULL)
+ memcpy (myaddr, &registers[inregbyte], inlen);
+}
+
+/* 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 (registers_pid != inferior_pid)
+ {
+ registers_changed ();
+ registers_pid = inferior_pid;
+ }
+
+ if (!register_valid[regno])
+ target_fetch_registers (regno);
+ memcpy (myaddr, &registers[REGISTER_BYTE (regno)],
+ REGISTER_RAW_SIZE (regno));
+}
+
+/* Write register REGNO at MYADDR to the target. MYADDR points at
+ REGISTER_RAW_BYTES(REGNO), which must be in target byte-order. */
+
+static void
+write_register_gen (regno, myaddr)
+ int regno;
+ char *myaddr;
+{
+ 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;
+
+ if (registers_pid != inferior_pid)
+ {
+ registers_changed ();
+ registers_pid = inferior_pid;
+ }
+
+ size = REGISTER_RAW_SIZE(regno);
+
+ /* 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]
+ && memcmp (&registers[REGISTER_BYTE (regno)], myaddr, size) == 0)
+ return;
+
+ target_prepare_to_store ();
+
+ memcpy (&registers[REGISTER_BYTE (regno)], myaddr, size);
+
+ register_valid [regno] = 1;
+
+ target_store_registers (regno);
+}
+
+/* Copy INLEN bytes of consecutive data from memory at MYADDR
+ into registers starting with the MYREGSTART'th byte of register data. */
+
+void
+write_register_bytes (myregstart, myaddr, inlen)
+ int myregstart;
+ char *myaddr;
+ int inlen;
+{
+ int myregend = myregstart + inlen;
+ int regno;
+
+ target_prepare_to_store ();
+
+ /* Scan through the registers updating any that are covered by the range
+ myregstart<=>myregend using write_register_gen, which does nice things
+ like handling threads, and avoiding updates when the new and old contents
+ are the same. */
+
+ for (regno = 0; regno < NUM_REGS; regno++)
+ {
+ int regstart, regend;
+ int startin, endin;
+ char regbuf[MAX_REGISTER_RAW_SIZE];
+
+ regstart = REGISTER_BYTE (regno);
+ regend = regstart + REGISTER_RAW_SIZE (regno);
+
+ startin = regstart >= myregstart && regstart < myregend;
+ endin = regend > myregstart && regend <= myregend;
+
+ if (!startin && !endin)
+ continue; /* Register is completely out of range */
+
+ if (startin && endin) /* register is completely in range */
+ {
+ write_register_gen (regno, myaddr + (regstart - myregstart));
+ continue;
+ }
+
+ /* We may be doing a partial update of an invalid register. Update it
+ from the target before scribbling on it. */
+ read_register_gen (regno, regbuf);
+
+ if (startin)
+ memcpy (registers + regstart,
+ myaddr + regstart - myregstart,
+ myregend - regstart);
+ else /* endin */
+ memcpy (registers + myregstart,
+ myaddr,
+ regend - myregstart);
+ target_store_registers (regno);
+ }
+}
+
+/* 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 (registers_pid != inferior_pid)
+ {
+ registers_changed ();
+ registers_pid = inferior_pid;
+ }
+
+ if (!register_valid[regno])
+ target_fetch_registers (regno);
+
+ return (CORE_ADDR)extract_address (&registers[REGISTER_BYTE (regno)],
+ REGISTER_RAW_SIZE(regno));
+}
+
+CORE_ADDR
+read_register_pid (regno, pid)
+ int regno, pid;
+{
+ int save_pid;
+ CORE_ADDR retval;
+
+ if (pid == inferior_pid)
+ return read_register (regno);
+
+ save_pid = inferior_pid;
+
+ inferior_pid = pid;
+
+ retval = read_register (regno);
+
+ inferior_pid = save_pid;
+
+ return retval;
+}
+
+/* Store VALUE, into the raw contents of register number REGNO.
+ This should probably write a LONGEST rather than a CORE_ADDR */
+
+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;
+
+ if (registers_pid != inferior_pid)
+ {
+ registers_changed ();
+ registers_pid = inferior_pid;
+ }
+
+ 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]
+ && 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);
+}
+
+void
+write_register_pid (regno, val, pid)
+ int regno;
+ CORE_ADDR val;
+ int pid;
+{
+ int save_pid;
+
+ if (pid == inferior_pid)
+ {
+ write_register (regno, val);
+ return;
+ }
+
+ save_pid = inferior_pid;
+
+ inferior_pid = pid;
+
+ write_register (regno, val);
+
+ inferior_pid = save_pid;
+}
+
+/* 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.
+
+ If VAL is a NULL pointer, then it's probably an unsupported register. We
+ just set it's value to all zeros. We might want to record this fact, and
+ report it to the users of read_register and friends.
+*/
+
+void
+supply_register (regno, val)
+ int regno;
+ char *val;
+{
+#if 1
+ if (registers_pid != inferior_pid)
+ {
+ registers_changed ();
+ registers_pid = inferior_pid;
+ }
+#endif
+
+ register_valid[regno] = 1;
+ if (val)
+ memcpy (&registers[REGISTER_BYTE (regno)], val, REGISTER_RAW_SIZE (regno));
+ else
+ memset (&registers[REGISTER_BYTE (regno)], '\000', 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
+}
+
+
+/* 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_pid (pid)
+ int pid;
+{
+ int saved_inferior_pid;
+ CORE_ADDR pc_val;
+
+ /* In case pid != inferior_pid. */
+ saved_inferior_pid = inferior_pid;
+ inferior_pid = pid;
+
+#ifdef TARGET_READ_PC
+ pc_val = TARGET_READ_PC (pid);
+#else
+ pc_val = ADDR_BITS_REMOVE ((CORE_ADDR) read_register_pid (PC_REGNUM, pid));
+#endif
+
+ inferior_pid = saved_inferior_pid;
+ return pc_val;
+}
+
+CORE_ADDR
+read_pc ()
+{
+ return read_pc_pid (inferior_pid);
+}
+
+void
+write_pc_pid (pc, pid)
+ CORE_ADDR pc;
+ int pid;
+{
+ int saved_inferior_pid;
+
+ /* In case pid != inferior_pid. */
+ saved_inferior_pid = inferior_pid;
+ inferior_pid = pid;
+
+#ifdef TARGET_WRITE_PC
+ TARGET_WRITE_PC (pc, pid);
+#else
+ write_register_pid (PC_REGNUM, pc, pid);
+#ifdef NPC_REGNUM
+ write_register_pid (NPC_REGNUM, pc + 4, pid);
+#ifdef NNPC_REGNUM
+ write_register_pid (NNPC_REGNUM, pc + 8, pid);
+#endif
+#endif
+#endif
+
+ inferior_pid = saved_inferior_pid;
+}
+
+void
+write_pc (pc)
+ CORE_ADDR pc;
+{
+ write_pc_pid (pc, inferior_pid);
+}
+
+/* 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
+}
+
+/* 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:
+ case LOC_THREAD_LOCAL_STATIC:
+ return 1;
+
+ case LOC_UNDEF:
+ case LOC_CONST:
+ case LOC_STATIC:
+ case LOC_INDIRECT:
+ 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_UNRESOLVED:
+ case LOC_OPTIMIZED_OUT:
+ return 0;
+ }
+ return 1;
+}
+
+/* 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_ptr
+read_var_value (var, frame)
+ register struct symbol *var;
+ struct frame_info *frame;
+{
+ register value_ptr v;
+ 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. */
+ VALUE_BFD_SECTION (v) = SYMBOL_BFD_SECTION (var);
+
+ len = TYPE_LENGTH (type);
+
+ if (frame == NULL) 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. */
+ if (overlay_debugging)
+ store_address (VALUE_CONTENTS_RAW (v), len,
+ (LONGEST)symbol_overlayed_address (SYMBOL_VALUE_ADDRESS (var),
+ SYMBOL_BFD_SECTION (var)));
+ else
+ store_address (VALUE_CONTENTS_RAW (v), len,
+ (LONGEST)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:
+ if (overlay_debugging)
+ addr = symbol_overlayed_address (SYMBOL_VALUE_ADDRESS (var),
+ SYMBOL_BFD_SECTION (var));
+ else
+ addr = SYMBOL_VALUE_ADDRESS (var);
+ break;
+
+ case LOC_INDIRECT:
+ /* The import slot does not have a real address in it from the
+ dynamic loader (dld.sl on HP-UX), if the target hasn't begun
+ execution yet, so check for that. */
+ if (!target_has_execution)
+ error ("\
+Attempt to access variable defined in different shared object or load module when\n\
+addresses have not been bound by the dynamic loader. Try again when executable is running.");
+
+ addr = SYMBOL_VALUE_ADDRESS (var);
+ addr = read_memory_unsigned_integer
+ (addr, TARGET_PTR_BIT / TARGET_CHAR_BIT);
+ break;
+
+ case LOC_ARG:
+ if (frame == NULL)
+ return 0;
+ addr = FRAME_ARGS_ADDRESS (frame);
+ if (!addr)
+ return 0;
+ addr += SYMBOL_VALUE (var);
+ break;
+
+ case LOC_REF_ARG:
+ if (frame == NULL)
+ return 0;
+ addr = FRAME_ARGS_ADDRESS (frame);
+ 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:
+ if (frame == NULL)
+ return 0;
+ addr = FRAME_LOCALS_ADDRESS (frame);
+ 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_THREAD_LOCAL_STATIC:
+ {
+ 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:
+ if (overlay_debugging)
+ VALUE_ADDRESS (v) = symbol_overlayed_address
+ (BLOCK_START (SYMBOL_BLOCK_VALUE (var)), SYMBOL_BFD_SECTION (var));
+ else
+ VALUE_ADDRESS (v) = BLOCK_START (SYMBOL_BLOCK_VALUE (var));
+ return v;
+
+ case LOC_REGISTER:
+ case LOC_REGPARM:
+ case LOC_REGPARM_ADDR:
+ {
+ struct block *b;
+ int regno = SYMBOL_VALUE (var);
+ value_ptr regval;
+
+ if (frame == NULL)
+ return 0;
+ b = get_frame_block (frame);
+
+ if (SYMBOL_CLASS (var) == LOC_REGPARM_ADDR)
+ {
+ regval = value_from_register (lookup_pointer_type (type),
+ regno,
+ frame);
+
+ if (regval == NULL)
+ error ("Value of register variable not available.");
+
+ addr = value_as_pointer (regval);
+ VALUE_LVAL (v) = lval_memory;
+ }
+ else
+ {
+ regval = value_from_register (type, regno, frame);
+
+ if (regval == NULL)
+ error ("Value of register variable not available.");
+ return regval;
+ }
+ }
+ break;
+
+ case LOC_UNRESOLVED:
+ {
+ struct minimal_symbol *msym;
+
+ msym = lookup_minimal_symbol (SYMBOL_NAME (var), NULL, NULL);
+ if (msym == NULL)
+ return 0;
+ if (overlay_debugging)
+ addr = symbol_overlayed_address (SYMBOL_VALUE_ADDRESS (msym),
+ SYMBOL_BFD_SECTION (msym));
+ else
+ addr = SYMBOL_VALUE_ADDRESS (msym);
+ }
+ 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.
+
+ NOTE: returns NULL if register value is not available.
+ Caller will check return value or die! */
+
+value_ptr
+value_from_register (type, regnum, frame)
+ struct type *type;
+ int regnum;
+ struct frame_info *frame;
+{
+ char raw_buffer [MAX_REGISTER_RAW_SIZE];
+ CORE_ADDR addr;
+ int optim;
+ value_ptr v = allocate_value (type);
+ char *value_bytes = 0;
+ int value_bytes_copied = 0;
+ int num_storage_locs;
+ enum lval_type lval;
+ int len;
+
+ CHECK_TYPEDEF (type);
+ len = TYPE_LENGTH (type);
+
+ 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 (register_valid[page_regnum] == -1)
+ return NULL; /* register value not available */
+
+ 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 (register_valid[regnum] == -1)
+ return NULL; /* register value not available */
+
+ 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 (register_valid[local_regnum] == -1)
+ return NULL; /* register value not available */
+
+ 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);
+
+ if (register_valid[regnum] == -1)
+ return NULL; /* register value not available */
+
+ VALUE_OPTIMIZED_OUT (v) = optim;
+ VALUE_LVAL (v) = lval;
+ VALUE_ADDRESS (v) = addr;
+
+ /* Convert raw data to virtual format if necessary. */
+
+#ifdef REGISTER_CONVERTIBLE
+ if (REGISTER_CONVERTIBLE (regnum))
+ {
+ REGISTER_CONVERT_TO_VIRTUAL (regnum, type,
+ raw_buffer, VALUE_CONTENTS_RAW (v));
+ }
+ else
+#endif
+ {
+ /* Raw and virtual formats are the same for this register. */
+
+ if (TARGET_BYTE_ORDER == BIG_ENDIAN && len < REGISTER_RAW_SIZE (regnum))
+ {
+ /* Big-endian, and we want less than full size. */
+ VALUE_OFFSET (v) = REGISTER_RAW_SIZE (regnum) - len;
+ }
+
+ memcpy (VALUE_CONTENTS_RAW (v), raw_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_ptr
+locate_var_value (var, frame)
+ register struct symbol *var;
+ struct frame_info *frame;
+{
+ CORE_ADDR addr = 0;
+ struct type *type = SYMBOL_TYPE (var);
+ value_ptr 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)
+ {
+ value_ptr val;
+
+ addr = VALUE_ADDRESS (lazy_value);
+ val = value_from_longest (lookup_pointer_type (type), (LONGEST) addr);
+ VALUE_BFD_SECTION (val) = VALUE_BFD_SECTION (lazy_value);
+ return val;
+ }
+
+ /* 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/gdb/fork-child.c b/gdb/fork-child.c
new file mode 100644
index 00000000000..f3504bc6409
--- /dev/null
+++ b/gdb/fork-child.c
@@ -0,0 +1,616 @@
+/* Fork a Unix child process, and set up to debug it, for GDB.
+ Copyright 1990, 1991, 1992, 1993, 1994, 1996 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "gdb_string.h"
+#include "frame.h" /* required by inferior.h */
+#include "inferior.h"
+#include "target.h"
+#include "wait.h"
+#include "gdbcore.h"
+#include "terminal.h"
+#include "gdbthread.h"
+
+#include <signal.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#define DEBUGGING 0
+
+/* This just gets used as a default if we can't find SHELL */
+#ifndef SHELL_FILE
+#define SHELL_FILE "/bin/sh"
+#endif
+
+extern char **environ;
+
+/* This function breaks up an argument string into an argument
+ * vector suitable for passing to execvp().
+ * E.g., on "run a b c d" this routine would get as input
+ * the string "a b c d", and as output it would fill in argv with
+ * the four arguments "a", "b", "c", "d".
+ */
+static void
+breakup_args (
+ scratch,
+ argv)
+ char *scratch;
+ char **argv;
+{
+ char *cp = scratch;
+
+#if DEBUGGING
+ printf ("breakup_args: input = %s\n", scratch);
+#endif
+ for (;;)
+ {
+
+ /* Scan past leading separators */
+ while (*cp == ' ' || *cp == '\t' || *cp == '\n')
+ {
+ cp++;
+ }
+
+ /* Break if at end of string */
+ if (*cp == '\0')
+ break;
+
+ /* Take an arg */
+ *argv++ = cp;
+
+ /* Scan for next arg separator */
+ cp = strchr (cp, ' ');
+ if (cp == NULL)
+ cp = strchr (cp, '\t');
+ if (cp == NULL)
+ cp = strchr (cp, '\n');
+
+ /* No separators => end of string => break */
+ if (cp == NULL)
+ break;
+
+ /* Replace the separator with a terminator */
+ *cp++ = '\0';
+ }
+
+ /* execv requires a null-terminated arg vector */
+ *argv = NULL;
+
+}
+
+
+/* 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. SHELL_FILE is the shell file,
+ or NULL if we should pick one. Errors reported with error(). */
+
+void
+fork_inferior (exec_file, allargs, env, traceme_fun, init_trace_fun,
+ pre_trace_fun, shell_file)
+ char *exec_file;
+ char *allargs;
+ char **env;
+ void (*traceme_fun) PARAMS ((void));
+ void (*init_trace_fun) PARAMS ((int));
+ void (*pre_trace_fun) PARAMS ((void));
+ char *shell_file;
+{
+ int pid;
+ char *shell_command;
+ static char default_shell_file[] = SHELL_FILE;
+ int len;
+ /* 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;
+ int shell = 0;
+ char **argv;
+ char *tryname;
+
+ /* 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);
+
+ /* STARTUP_WITH_SHELL is defined in inferior.h.
+ * If 0, we'll just do a fork/exec, no shell, so don't
+ * bother figuring out what shell.
+ */
+ if (STARTUP_WITH_SHELL)
+ {
+ /* Figure out what shell to start up the user program under. */
+ if (shell_file == NULL)
+ shell_file = getenv ("SHELL");
+ if (shell_file == NULL)
+ shell_file = default_shell_file;
+ shell = 1;
+ }
+
+#if DEBUGGING
+ printf ("shell is %s\n", shell_file);
+#endif
+
+ /* 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
+
+ if (!shell)
+ {
+ /* We're going to call execvp. Create argv */
+ /* Largest case: every other character is a separate arg */
+#if DEBUGGING
+ printf ("allocating argv, length = %d\n",
+ (
+ (strlen (allargs) + 1) / (unsigned) 2
+ + 2
+ ) * sizeof (*argv)
+ );
+#endif
+ argv = (char **) xmalloc (((strlen (allargs) + 1) / (unsigned) 2 + 2) * sizeof (*argv));
+ argv[0] = exec_file;
+ breakup_args (allargs, &argv[1]);
+
+ }
+ else
+ {
+
+ /* We're going to call a shell */
+
+ /* Now add exec_file, quoting as necessary. */
+
+ char *p;
+ int need_to_quote;
+
+ strcat (shell_command, "exec ");
+
+ /* 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. */
+
+ gdb_flush (gdb_stdout);
+ gdb_flush (gdb_stderr);
+
+ /* If there's any initialization of the target layers that must happen
+ to prepare to handle the child we're about fork, do it now...
+ */
+ if (pre_trace_fun != NULL)
+ (*pre_trace_fun) ();
+
+#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");
+
+ /* 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) ();
+ /* The call above set this process (the "child") as debuggable
+ * by the original gdb process (the "parent"). Since processes
+ * (unlike people) can have only one parent, if you are
+ * debugging gdb itself (and your debugger is thus _already_ the
+ * controller/parent for this child), code from here on out
+ * is undebuggable. Indeed, you probably got an error message
+ * saying "not parent". Sorry--you'll have to use print statements!
+ */
+
+ /* 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;
+
+ /* If we decided above to start up with a shell,
+ * we exec the shell,
+ * "-c" says to interpret the next arg as a shell command
+ * to execute, and this command is "exec <target-program> <args>".
+ * "-f" means "fast startup" to the c-shell, which means
+ * don't do .cshrc file. Doing .cshrc may cause fork/exec
+ * events which will confuse debugger start-up code.
+ */
+ if (shell)
+ {
+#if 0
+
+ /* HP change is problematic. The -f option has different meanings
+ for different shells. It is particularly inappropriate for
+ bourne shells. */
+ execlp (shell_file, shell_file, "-f", "-c", shell_command, (char *) 0);
+#else
+ execlp (shell_file, shell_file, "-c", shell_command, (char *) 0);
+#endif
+
+
+ /* If we get here, it's an error */
+ fprintf_unfiltered (gdb_stderr, "Cannot exec %s: %s.\n", shell_file,
+ safe_strerror (errno));
+ gdb_flush (gdb_stderr);
+ _exit (0177);
+ }
+ else
+ {
+ /* Otherwise, we directly exec the target program with execvp. */
+ int i;
+ char *errstring;
+#if DEBUGGING
+ printf ("about to exec target, exec_file = %s\n", exec_file);
+ i = 0;
+ while (argv[i] != NULL)
+ {
+ printf ("strlen(argv[%d]) is %d\n", i, strlen (argv[i]));
+ printf ("argv[%d] is %s\n", i, argv[i]);
+ i++;
+ }
+#endif
+ execvp (exec_file, argv);
+
+ /* If we get here, it's an error */
+ errstring = safe_strerror (errno);
+ fprintf_unfiltered (gdb_stderr, "Cannot exec %s ", exec_file);
+
+ i = 1;
+ while (argv[i] != NULL)
+ {
+ if (i != 1)
+ fprintf_unfiltered (gdb_stderr, " ");
+ fprintf_unfiltered (gdb_stderr, "%s", argv[i]);
+ i++;
+ }
+ fprintf_unfiltered (gdb_stderr, ".\n");
+ /* This extra info seems to be useless
+ fprintf_unfiltered (gdb_stderr, "Got error %s.\n", errstring);
+ */
+ gdb_flush (gdb_stderr);
+ _exit (0177);
+ }
+ }
+
+ /* Restore our environment in case a vforked child clob'd it. */
+ environ = save_our_env;
+
+ init_thread_list ();
+
+ inferior_pid = pid; /* Needed for wait_for_inferior stuff below */
+
+ /* Now that we have a child process, make it our target, and
+ initialize anything target-vector-specific that needs initializing. */
+
+ (*init_trace_fun) (pid);
+
+ /* 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. */
+
+ /* Allow target dependant code to play with the new process. This might be
+ used to have target-specific code initialize a variable in the new process
+ prior to executing the first instruction. */
+ TARGET_CREATE_INFERIOR_HOOK (pid);
+
+#ifdef SOLIB_CREATE_INFERIOR_HOOK
+ SOLIB_CREATE_INFERIOR_HOOK (pid);
+#endif
+}
+
+/* An inferior Unix process CHILD_PID has been created by a call to
+ fork() (or variants like vfork). It is presently stopped, and waiting
+ to be resumed. clone_and_follow_inferior will fork the debugger,
+ and that clone will "follow" (attach to) CHILD_PID. The original copy
+ of the debugger will not touch CHILD_PID again.
+
+ Also, the original debugger will set FOLLOWED_CHILD FALSE, while the
+ clone will set it TRUE.
+ */
+void
+clone_and_follow_inferior (child_pid, followed_child)
+ int child_pid;
+ int *followed_child;
+{
+ extern int auto_solib_add;
+
+ int debugger_pid;
+ int status;
+ char pid_spelling[100]; /* Arbitrary but sufficient length. */
+
+ /* This semaphore is used to coordinate the two debuggers' handoff
+ of CHILD_PID. The original debugger will detach from CHILD_PID,
+ and then the clone debugger will attach to it. (It must be done
+ this way because on some targets, only one process at a time can
+ trace another. Thus, the original debugger must relinquish its
+ tracing rights before the clone can pick them up.)
+ */
+#define SEM_TALK (1)
+#define SEM_LISTEN (0)
+ int handoff_semaphore[2]; /* Original "talks" to [1], clone "listens" to [0] */
+ int talk_value = 99;
+ int listen_value;
+
+ /* Set debug_fork then attach to the child while it sleeps, to debug. */
+ static int debug_fork = 0;
+
+ /* 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. */
+
+ gdb_flush (gdb_stdout);
+ gdb_flush (gdb_stderr);
+
+ /* Open the semaphore pipes.
+ */
+ status = pipe (handoff_semaphore);
+ if (status < 0)
+ error ("error getting pipe for handoff semaphore");
+
+ /* Clone the debugger. */
+#if defined(USG) && !defined(HAVE_VFORK)
+ debugger_pid = fork ();
+#else
+ if (debug_fork)
+ debugger_pid = fork ();
+ else
+ debugger_pid = vfork ();
+#endif
+
+ if (debugger_pid < 0)
+ perror_with_name ("fork");
+
+ /* Are we the original debugger? If so, we must relinquish all claims
+ to CHILD_PID. */
+ if (debugger_pid != 0)
+ {
+ char signal_spelling[100];/* Arbitrary but sufficient length */
+
+ /* Detach from CHILD_PID. Deliver a "stop" signal when we do, though,
+ so that it remains stopped until the clone debugger can attach
+ to it.
+ */
+ detach_breakpoints (child_pid);
+
+ sprintf (signal_spelling, "%d", target_signal_to_host (TARGET_SIGNAL_STOP));
+ target_require_detach (child_pid, signal_spelling, 1);
+
+ /* Notify the clone debugger that it should attach to CHILD_PID. */
+ write (handoff_semaphore[SEM_TALK], &talk_value, sizeof (talk_value));
+
+ *followed_child = 0;
+ }
+
+ /* We're the child. */
+ else
+ {
+ if (debug_fork)
+ sleep (debug_fork);
+
+ /* The child (i.e., the cloned debugger) must now attach to
+ CHILD_PID. inferior_pid is presently set to the parent process
+ of the fork, while CHILD_PID should be the child process of the
+ fork.
+
+ Wait until the original debugger relinquishes control of CHILD_PID,
+ though.
+ */
+ read (handoff_semaphore[SEM_LISTEN], &listen_value, sizeof (listen_value));
+
+ /* Note that we DON'T want to actually detach from inferior_pid,
+ because that would allow it to run free. The original
+ debugger wants to retain control of the process. So, we
+ just reset inferior_pid to CHILD_PID, and then ensure that all
+ breakpoints are really set in CHILD_PID.
+ */
+ target_mourn_inferior ();
+
+ /* Ask the tty subsystem to switch to the one we specified earlier
+ (or to share the current terminal, if none was specified). */
+
+ new_tty ();
+
+ dont_repeat ();
+ sprintf (pid_spelling, "%d", child_pid);
+ target_require_attach (pid_spelling, 1);
+
+ /* Perform any necessary cleanup, after attachment. (This form
+ of attaching can behave differently on some targets than the
+ standard method, where a process formerly not under debugger
+ control was suddenly attached to..)
+ */
+ target_post_follow_inferior_by_clone ();
+
+ *followed_child = 1;
+ }
+
+ /* Discard the handoff sempahore. */
+ (void) close (handoff_semaphore[SEM_LISTEN]);
+ (void) close (handoff_semaphore[SEM_TALK]);
+}
+
+/* Accept NTRAPS traps from the inferior. */
+
+void
+startup_inferior (ntraps)
+ int ntraps;
+{
+ int pending_execs = ntraps;
+ int terminal_initted;
+
+ /* 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. */
+
+ clear_proceed_status ();
+
+ init_wait_for_inferior ();
+
+ terminal_initted = 0;
+
+ if (STARTUP_WITH_SHELL)
+ inferior_ignoring_startup_exec_events = ntraps;
+ else
+ inferior_ignoring_startup_exec_events = 0;
+ inferior_ignoring_leading_exec_events =
+ target_reported_exec_events_per_exec_call () - 1;
+
+#ifdef STARTUP_INFERIOR
+ STARTUP_INFERIOR (pending_execs);
+#else
+ while (1)
+ {
+ stop_soon_quietly = 1; /* Make wait_for_inferior be quiet */
+ wait_for_inferior ();
+ if (stop_signal != TARGET_SIGNAL_TRAP)
+ {
+ /* 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;
+ }
+
+ pending_execs = pending_execs - 1;
+ if (0 == pending_execs)
+ break;
+
+ resume (0, TARGET_SIGNAL_0); /* Just make it go on */
+ }
+ }
+#endif /* STARTUP_INFERIOR */
+ stop_soon_quietly = 0;
+}
diff --git a/gdb/fr30-tdep.c b/gdb/fr30-tdep.c
new file mode 100644
index 00000000000..0d442dafa4d
--- /dev/null
+++ b/gdb/fr30-tdep.c
@@ -0,0 +1,552 @@
+/* Target-dependent code for the Fujitsu FR30.
+ Copyright 1999, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "frame.h"
+#include "inferior.h"
+#include "obstack.h"
+#include "target.h"
+#include "value.h"
+#include "bfd.h"
+#include "gdb_string.h"
+#include "gdbcore.h"
+#include "symfile.h"
+
+/* Function: pop_frame
+ This routine gets called when either the user uses the `return'
+ command, or the call dummy breakpoint gets hit. */
+
+void
+fr30_pop_frame ()
+{
+ struct frame_info *frame = get_current_frame();
+ int regnum;
+ CORE_ADDR sp = read_register(SP_REGNUM);
+
+ if (PC_IN_CALL_DUMMY(frame->pc, frame->frame, frame->frame))
+ generic_pop_dummy_frame ();
+ else
+ {
+ write_register (PC_REGNUM, FRAME_SAVED_PC (frame));
+
+ for (regnum = 0; regnum < NUM_REGS; regnum++)
+ if (frame->fsr.regs[regnum] != 0) {
+ write_register (regnum,
+ read_memory_unsigned_integer (frame->fsr.regs[regnum],
+ REGISTER_RAW_SIZE(regnum)));
+ }
+ write_register (SP_REGNUM, sp + frame->framesize);
+ }
+ flush_cached_frames ();
+}
+
+/* Function: skip_prologue
+ Return the address of the first code past the prologue of the function. */
+
+CORE_ADDR
+fr30_skip_prologue(CORE_ADDR pc)
+{
+ CORE_ADDR func_addr, func_end;
+
+ /* See what the symbol table says */
+
+ if (find_pc_partial_function (pc, NULL, &func_addr, &func_end))
+ {
+ struct symtab_and_line sal;
+
+ sal = find_pc_line (func_addr, 0);
+
+ if (sal.line != 0 && sal.end < func_end) {
+ return sal.end;
+ }
+ }
+
+/* Either we didn't find the start of this function (nothing we can do),
+ or there's no line info, or the line after the prologue is after
+ the end of the function (there probably isn't a prologue). */
+
+ return pc;
+}
+
+
+/* Function: push_arguments
+ Setup arguments and RP for a call to the target. First four args
+ go in FIRST_ARGREG -> LAST_ARGREG, subsequent args go on stack...
+ Structs are passed by reference. XXX not right now Z.R.
+ 64 bit quantities (doubles and long longs) may be split between
+ the regs and the stack.
+ When calling a function that returns a struct, a pointer to the struct
+ is passed in as a secret first argument (always in FIRST_ARGREG).
+
+ Stack space for the args has NOT been allocated: that job is up to us.
+*/
+
+CORE_ADDR
+fr30_push_arguments(nargs, args, sp, struct_return, struct_addr)
+ int nargs;
+ value_ptr * args;
+ CORE_ADDR sp;
+ int struct_return;
+ CORE_ADDR struct_addr;
+{
+ int argreg;
+ int argnum;
+ int stack_offset;
+ struct stack_arg {
+ char *val;
+ int len;
+ int offset;
+ };
+ struct stack_arg *stack_args =
+ (struct stack_arg*)alloca (nargs * sizeof (struct stack_arg));
+ int nstack_args = 0;
+
+ argreg = FIRST_ARGREG;
+
+ /* the struct_return pointer occupies the first parameter-passing reg */
+ if (struct_return)
+ write_register (argreg++, struct_addr);
+
+ stack_offset = 0;
+
+ /* Process args from left to right. Store as many as allowed in
+ registers, save the rest to be pushed on the stack */
+ for(argnum = 0; argnum < nargs; argnum++)
+ {
+ char * val;
+ value_ptr arg = args[argnum];
+ struct type * arg_type = check_typedef (VALUE_TYPE (arg));
+ struct type * target_type = TYPE_TARGET_TYPE (arg_type);
+ int len = TYPE_LENGTH (arg_type);
+ enum type_code typecode = TYPE_CODE (arg_type);
+ CORE_ADDR regval;
+ int newarg;
+
+ val = (char *) VALUE_CONTENTS (arg);
+
+ {
+ /* Copy the argument to general registers or the stack in
+ register-sized pieces. Large arguments are split between
+ registers and stack. */
+ while (len > 0)
+ {
+ if (argreg <= LAST_ARGREG)
+ {
+ int partial_len = len < REGISTER_SIZE ? len : REGISTER_SIZE;
+ regval = extract_address (val, partial_len);
+
+ /* It's a simple argument being passed in a general
+ register. */
+ write_register (argreg, regval);
+ argreg++;
+ len -= partial_len;
+ val += partial_len;
+ }
+ else
+ {
+ /* keep for later pushing */
+ stack_args[nstack_args].val = val;
+ stack_args[nstack_args++].len = len;
+ break;
+ }
+ }
+ }
+ }
+ /* now do the real stack pushing, process args right to left */
+ while(nstack_args--)
+ {
+ sp -= stack_args[nstack_args].len;
+ write_memory(sp, stack_args[nstack_args].val,
+ stack_args[nstack_args].len);
+ }
+
+ /* Return adjusted stack pointer. */
+ return sp;
+}
+
+_initialize_fr30_tdep()
+{
+ extern int print_insn_fr30(bfd_vma, disassemble_info *);
+
+ tm_print_insn = print_insn_fr30;
+}
+
+/* Function: check_prologue_cache
+ Check if prologue for this frame's PC has already been scanned.
+ If it has, copy the relevant information about that prologue and
+ return non-zero. Otherwise do not copy anything and return zero.
+
+ The information saved in the cache includes:
+ * the frame register number;
+ * the size of the stack frame;
+ * the offsets of saved regs (relative to the old SP); and
+ * the offset from the stack pointer to the frame pointer
+
+ The cache contains only one entry, since this is adequate
+ for the typical sequence of prologue scan requests we get.
+ When performing a backtrace, GDB will usually ask to scan
+ the same function twice in a row (once to get the frame chain,
+ and once to fill in the extra frame information).
+*/
+
+static struct frame_info prologue_cache;
+
+static int
+check_prologue_cache (fi)
+ struct frame_info * fi;
+{
+ int i;
+
+ if (fi->pc == prologue_cache.pc)
+ {
+ fi->framereg = prologue_cache.framereg;
+ fi->framesize = prologue_cache.framesize;
+ fi->frameoffset = prologue_cache.frameoffset;
+ for (i = 0; i <= NUM_REGS; i++)
+ fi->fsr.regs[i] = prologue_cache.fsr.regs[i];
+ return 1;
+ }
+ else
+ return 0;
+}
+
+
+/* Function: save_prologue_cache
+ Copy the prologue information from fi to the prologue cache.
+*/
+
+static void
+save_prologue_cache (fi)
+ struct frame_info * fi;
+{
+ int i;
+
+ prologue_cache.pc = fi->pc;
+ prologue_cache.framereg = fi->framereg;
+ prologue_cache.framesize = fi->framesize;
+ prologue_cache.frameoffset = fi->frameoffset;
+
+ for (i = 0; i <= NUM_REGS; i++) {
+ prologue_cache.fsr.regs[i] = fi->fsr.regs[i];
+ }
+}
+
+
+/* Function: scan_prologue
+ Scan the prologue of the function that contains PC, and record what
+ we find in PI. PI->fsr must be zeroed by the called. Returns the
+ pc after the prologue. Note that the addresses saved in pi->fsr
+ are actually just frame relative (negative offsets from the frame
+ pointer). This is because we don't know the actual value of the
+ frame pointer yet. In some circumstances, the frame pointer can't
+ be determined till after we have scanned the prologue. */
+
+static void
+fr30_scan_prologue (fi)
+ struct frame_info * fi;
+{
+ int sp_offset, fp_offset;
+ CORE_ADDR prologue_start, prologue_end, current_pc;
+
+ /* Check if this function is already in the cache of frame information. */
+ if (check_prologue_cache (fi))
+ return;
+
+ /* Assume there is no frame until proven otherwise. */
+ fi->framereg = SP_REGNUM;
+ fi->framesize = 0;
+ fi->frameoffset = 0;
+
+ /* Find the function prologue. If we can't find the function in
+ the symbol table, peek in the stack frame to find the PC. */
+ if (find_pc_partial_function (fi->pc, NULL, &prologue_start, &prologue_end))
+ {
+ /* Assume the prologue is everything between the first instruction
+ in the function and the first source line. */
+ struct symtab_and_line sal = find_pc_line (prologue_start, 0);
+
+ if (sal.line == 0) /* no line info, use current PC */
+ prologue_end = fi->pc;
+ else if (sal.end < prologue_end) /* next line begins after fn end */
+ prologue_end = sal.end; /* (probably means no prologue) */
+ }
+ else
+ {
+ /* XXX Z.R. What now??? The following is entirely bogus */
+ prologue_start = (read_memory_integer (fi->frame, 4) & 0x03fffffc) - 12;
+ prologue_end = prologue_start + 40;
+ }
+
+ /* Now search the prologue looking for instructions that set up the
+ frame pointer, adjust the stack pointer, and save registers. */
+
+ sp_offset = fp_offset = 0;
+ for (current_pc = prologue_start; current_pc < prologue_end; current_pc += 2)
+ {
+ unsigned int insn;
+
+ insn = read_memory_unsigned_integer (current_pc, 2);
+
+ if ((insn & 0xfe00) == 0x8e00) /* stm0 or stm1 */
+ {
+ int reg, mask = insn & 0xff;
+
+ /* scan in one sweep - create virtual 16-bit mask from either insn's mask */
+ if((insn & 0x0100) == 0)
+ {
+ mask <<= 8; /* stm0 - move to upper byte in virtual mask */
+ }
+
+ /* Calculate offsets of saved registers (to be turned later into addresses). */
+ for (reg = R4_REGNUM; reg <= R11_REGNUM; reg++)
+ if (mask & (1 << (15 - reg)))
+ {
+ sp_offset -= 4;
+ fi->fsr.regs[reg] = sp_offset;
+ }
+ }
+ else if((insn & 0xfff0) == 0x1700) /* st rx,@-r15 */
+ {
+ int reg = insn & 0xf;
+
+ sp_offset -= 4;
+ fi->fsr.regs[reg] = sp_offset;
+ }
+ else if((insn & 0xff00) == 0x0f00) /* enter */
+ {
+ fp_offset = fi->fsr.regs[FP_REGNUM] = sp_offset - 4;
+ sp_offset -= 4 * (insn & 0xff);
+ fi->framereg = FP_REGNUM;
+ }
+ else if(insn == 0x1781) /* st rp,@-sp */
+ {
+ sp_offset -= 4;
+ fi->fsr.regs[RP_REGNUM] = sp_offset;
+ }
+ else if(insn == 0x170e) /* st fp,@-sp */
+ {
+ sp_offset -= 4;
+ fi->fsr.regs[FP_REGNUM] = sp_offset;
+ }
+ else if(insn == 0x8bfe) /* mov sp,fp */
+ {
+ fi->framereg = FP_REGNUM;
+ }
+ else if((insn & 0xff00) == 0xa300) /* addsp xx */
+ {
+ sp_offset += 4 * (signed char)(insn & 0xff);
+ }
+ else if((insn & 0xff0f) == 0x9b00 && /* ldi:20 xx,r0 */
+ read_memory_unsigned_integer(current_pc+4, 2)
+ == 0xac0f) /* sub r0,sp */
+ {
+ /* large stack adjustment */
+ sp_offset -= (((insn & 0xf0) << 12) | read_memory_unsigned_integer(current_pc+2, 2));
+ current_pc += 4;
+ }
+ else if(insn == 0x9f80 && /* ldi:32 xx,r0 */
+ read_memory_unsigned_integer(current_pc+6, 2)
+ == 0xac0f) /* sub r0,sp */
+ {
+ /* large stack adjustment */
+ sp_offset -=
+ (read_memory_unsigned_integer(current_pc+2, 2) << 16 |
+ read_memory_unsigned_integer(current_pc+4, 2));
+ current_pc += 6;
+ }
+ }
+
+ /* The frame size is just the negative of the offset (from the original SP)
+ of the last thing thing we pushed on the stack. The frame offset is
+ [new FP] - [new SP]. */
+ fi->framesize = -sp_offset;
+ fi->frameoffset = fp_offset - sp_offset;
+
+ save_prologue_cache (fi);
+}
+
+/* Function: init_extra_frame_info
+ Setup the frame's frame pointer, pc, and frame addresses for saved
+ registers. Most of the work is done in scan_prologue().
+
+ Note that when we are called for the last frame (currently active frame),
+ that fi->pc and fi->frame will already be setup. However, fi->frame will
+ be valid only if this routine uses FP. For previous frames, fi-frame will
+ always be correct (since that is derived from fr30_frame_chain ()).
+
+ We can be called with the PC in the call dummy under two circumstances.
+ First, during normal backtracing, second, while figuring out the frame
+ pointer just prior to calling the target function (see run_stack_dummy). */
+
+void
+fr30_init_extra_frame_info (fi)
+ struct frame_info * fi;
+{
+ int reg;
+
+ if (fi->next)
+ fi->pc = FRAME_SAVED_PC (fi->next);
+
+ memset (fi->fsr.regs, '\000', sizeof fi->fsr.regs);
+
+ if (PC_IN_CALL_DUMMY (fi->pc, fi->frame, fi->frame))
+ {
+ /* We need to setup fi->frame here because run_stack_dummy gets it wrong
+ by assuming it's always FP. */
+ fi->frame = generic_read_register_dummy (fi->pc, fi->frame, SP_REGNUM);
+ fi->framesize = 0;
+ fi->frameoffset = 0;
+ return;
+ }
+ fr30_scan_prologue (fi);
+
+ if (!fi->next) /* this is the innermost frame? */
+ fi->frame = read_register (fi->framereg);
+ else /* not the innermost frame */
+ /* If we have an FP, the callee saved it. */
+ if (fi->framereg == FP_REGNUM)
+ if (fi->next->fsr.regs[fi->framereg] != 0)
+ fi->frame = read_memory_integer (fi->next->fsr.regs[fi->framereg],
+ 4);
+ /* Calculate actual addresses of saved registers using offsets determined
+ by fr30_scan_prologue. */
+ for (reg = 0; reg < NUM_REGS; reg++)
+ if (fi->fsr.regs[reg] != 0) {
+ fi->fsr.regs[reg] += fi->frame + fi->framesize - fi->frameoffset;
+ }
+}
+
+/* Function: find_callers_reg
+ Find REGNUM on the stack. Otherwise, it's in an active register.
+ One thing we might want to do here is to check REGNUM against the
+ clobber mask, and somehow flag it as invalid if it isn't saved on
+ the stack somewhere. This would provide a graceful failure mode
+ when trying to get the value of caller-saves registers for an inner
+ frame. */
+
+CORE_ADDR
+fr30_find_callers_reg (fi, regnum)
+ struct frame_info *fi;
+ int regnum;
+{
+ for (; fi; fi = fi->next)
+ if (PC_IN_CALL_DUMMY (fi->pc, fi->frame, fi->frame))
+ return generic_read_register_dummy (fi->pc, fi->frame, regnum);
+ else if (fi->fsr.regs[regnum] != 0)
+ return read_memory_unsigned_integer (fi->fsr.regs[regnum],
+ REGISTER_RAW_SIZE(regnum));
+
+ return read_register (regnum);
+}
+
+
+/* Function: frame_chain
+ Figure out the frame prior to FI. Unfortunately, this involves
+ scanning the prologue of the caller, which will also be done
+ shortly by fr30_init_extra_frame_info. For the dummy frame, we
+ just return the stack pointer that was in use at the time the
+ function call was made. */
+
+
+CORE_ADDR
+fr30_frame_chain (fi)
+ struct frame_info * fi;
+{
+ CORE_ADDR fn_start, callers_pc, fp;
+ struct frame_info caller_fi;
+ int framereg;
+
+ /* is this a dummy frame? */
+ if (PC_IN_CALL_DUMMY (fi->pc, fi->frame, fi->frame))
+ return fi->frame; /* dummy frame same as caller's frame */
+
+ /* is caller-of-this a dummy frame? */
+ callers_pc = FRAME_SAVED_PC(fi); /* find out who called us: */
+ fp = fr30_find_callers_reg (fi, FP_REGNUM);
+ if (PC_IN_CALL_DUMMY (callers_pc, fp, fp))
+ return fp; /* dummy frame's frame may bear no relation to ours */
+
+ if (find_pc_partial_function (fi->pc, 0, &fn_start, 0))
+ if (fn_start == entry_point_address ())
+ return 0; /* in _start fn, don't chain further */
+
+ framereg = fi->framereg;
+
+ /* If the caller is the startup code, we're at the end of the chain. */
+ if (find_pc_partial_function (callers_pc, 0, &fn_start, 0))
+ if (fn_start == entry_point_address ())
+ return 0;
+
+ memset (& caller_fi, 0, sizeof (caller_fi));
+ caller_fi.pc = callers_pc;
+ fr30_scan_prologue (& caller_fi);
+ framereg = caller_fi.framereg;
+
+ /* If the caller used a frame register, return its value.
+ Otherwise, return the caller's stack pointer. */
+ if (framereg == FP_REGNUM)
+ return fr30_find_callers_reg (fi, framereg);
+ else
+ return fi->frame + fi->framesize;
+}
+
+/* Function: frame_saved_pc
+ Find the caller of this frame. We do this by seeing if RP_REGNUM
+ is saved in the stack anywhere, otherwise we get it from the
+ registers. If the inner frame is a dummy frame, return its PC
+ instead of RP, because that's where "caller" of the dummy-frame
+ will be found. */
+
+CORE_ADDR
+fr30_frame_saved_pc (fi)
+ struct frame_info *fi;
+{
+ if (PC_IN_CALL_DUMMY(fi->pc, fi->frame, fi->frame))
+ return generic_read_register_dummy(fi->pc, fi->frame, PC_REGNUM);
+ else
+ return fr30_find_callers_reg (fi, RP_REGNUM);
+}
+
+/* Function: fix_call_dummy
+ Pokes the callee function's address into the CALL_DUMMY assembly stub.
+ Assumes that the CALL_DUMMY looks like this:
+ jarl <offset24>, r31
+ trap
+ */
+
+int
+fr30_fix_call_dummy (dummy, sp, fun, nargs, args, type, gcc_p)
+ char *dummy;
+ CORE_ADDR sp;
+ CORE_ADDR fun;
+ int nargs;
+ value_ptr *args;
+ struct type *type;
+ int gcc_p;
+{
+ long offset24;
+
+ offset24 = (long) fun - (long) entry_point_address ();
+ offset24 &= 0x3fffff;
+ offset24 |= 0xff800000; /* jarl <offset24>, r31 */
+
+ store_unsigned_integer ((unsigned int *)&dummy[2], 2, offset24 & 0xffff);
+ store_unsigned_integer ((unsigned int *)&dummy[0], 2, offset24 >> 16);
+ return 0;
+}
diff --git a/gdb/frame.h b/gdb/frame.h
new file mode 100644
index 00000000000..6836c6ce1b4
--- /dev/null
+++ b/gdb/frame.h
@@ -0,0 +1,264 @@
+/* Definitions for dealing with stack frames, for GDB, the GNU debugger.
+ Copyright 1986, 1989, 1991, 1992, 1999 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#if !defined (FRAME_H)
+#define FRAME_H 1
+
+/* Describe the saved registers of a frame. */
+
+#if defined (EXTRA_FRAME_INFO) || defined (FRAME_FIND_SAVED_REGS)
+/* XXXX - deprecated */
+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];
+ };
+#endif
+
+/* 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. */
+ CORE_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;
+
+ /* 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. */
+ /* Allocated by frame_saved_regs_zalloc () which is called /
+ initialized by FRAME_INIT_SAVED_REGS(). */
+ CORE_ADDR *saved_regs; /*NUM_REGS*/
+
+#ifdef EXTRA_FRAME_INFO
+ /* XXXX - deprecated */
+ /* Anything extra for this structure that may have been defined
+ in the machine dependent files. */
+ EXTRA_FRAME_INFO
+#endif
+
+ /* Anything extra for this structure that may have been defined
+ in the machine dependent files. */
+ /* Allocated by frame_obstack_alloc () which is called /
+ initialized by INIT_EXTRA_FRAME_INFO */
+ struct frame_extra_info *extra_info;
+
+ /* Pointers to the next and previous frame_info's in the frame cache. */
+ struct frame_info *next, *prev;
+ };
+
+/* Allocate additional space for appendices to a struct frame_info. */
+
+#ifndef SIZEOF_FRAME_SAVED_REGS
+#define SIZEOF_FRAME_SAVED_REGS (sizeof (CORE_ADDR) * (NUM_REGS))
+#endif
+extern void *frame_obstack_alloc PARAMS ((unsigned long size));
+extern void frame_saved_regs_zalloc PARAMS ((struct frame_info *));
+
+/* Dummy frame. This saves the processor state just prior to setting up the
+ inferior function call. On most targets, the registers are saved on the
+ target stack, but that really slows down function calls. */
+
+struct dummy_frame
+{
+ struct dummy_frame *next;
+
+ CORE_ADDR pc;
+ CORE_ADDR fp;
+ CORE_ADDR sp;
+ char regs[REGISTER_BYTES];
+};
+
+/* Return the frame address from FR. 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(fi) ((fi)->frame)
+
+/* 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.
+
+ XXXX - both default and alternate frame_chain_valid functions are
+ deprecated. New code should use generic dummy frames. */
+
+extern int default_frame_chain_valid PARAMS ((CORE_ADDR, struct frame_info *));
+extern int alternate_frame_chain_valid PARAMS ((CORE_ADDR, struct frame_info *));
+extern int nonnull_frame_chain_valid PARAMS ((CORE_ADDR, struct frame_info *));
+extern int generic_frame_chain_valid PARAMS ((CORE_ADDR, struct frame_info *));
+
+#if !defined (FRAME_CHAIN_VALID)
+#if !defined (FRAME_CHAIN_VALID_ALTERNATE)
+#define FRAME_CHAIN_VALID(chain, thisframe) default_frame_chain_valid (chain, thisframe)
+#else
+/* 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) alternate_frame_chain_valid (chain,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 struct frame_info *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 ((struct frame_info *));
+
+extern struct frame_info *create_new_frame PARAMS ((CORE_ADDR, CORE_ADDR));
+
+extern void flush_cached_frames PARAMS ((void));
+
+extern void reinit_frame_cache PARAMS ((void));
+
+
+#ifdef FRAME_FIND_SAVED_REGS
+/* XXX - deprecated */
+#define FRAME_INIT_SAVED_REGS(FI) get_frame_saved_regs (FI, NULL)
+extern void get_frame_saved_regs PARAMS ((struct frame_info *,
+ struct frame_saved_regs *));
+#endif
+
+extern void set_current_frame PARAMS ((struct frame_info *));
+
+extern struct frame_info *get_prev_frame PARAMS ((struct frame_info *));
+
+extern struct frame_info *get_current_frame PARAMS ((void));
+
+extern struct frame_info *get_next_frame PARAMS ((struct frame_info *));
+
+extern struct block *get_frame_block PARAMS ((struct frame_info *));
+
+extern struct block *get_current_block PARAMS ((void));
+
+extern struct block *get_selected_block PARAMS ((void));
+
+extern struct symbol *get_frame_function PARAMS ((struct frame_info *));
+
+extern CORE_ADDR get_frame_pc PARAMS ((struct frame_info *));
+
+extern CORE_ADDR get_pc_function_start PARAMS ((CORE_ADDR));
+
+extern struct block * block_for_pc PARAMS ((CORE_ADDR));
+
+extern struct block * block_for_pc_sect PARAMS ((CORE_ADDR, asection *));
+
+extern int frameless_look_for_prologue PARAMS ((struct frame_info *));
+
+extern void print_frame_args PARAMS ((struct symbol *, struct frame_info *,
+ int, GDB_FILE *));
+
+extern struct frame_info *find_relative_frame PARAMS ((struct frame_info *, int*));
+
+extern void print_stack_frame PARAMS ((struct frame_info *, int, int));
+
+extern void print_only_stack_frame PARAMS ((struct frame_info *, int, int));
+
+extern void show_stack_frame PARAMS ((struct frame_info *));
+
+extern void select_frame PARAMS ((struct frame_info *, int));
+
+extern void record_selected_frame PARAMS ((CORE_ADDR *, int *));
+
+extern void select_and_print_frame PARAMS ((struct frame_info *, int));
+
+extern void print_frame_info PARAMS ((struct frame_info *, int, int, int));
+
+extern void show_frame_info PARAMS ((struct frame_info *, int, int, int));
+
+extern CORE_ADDR find_saved_register PARAMS ((struct frame_info *, int));
+
+extern struct frame_info *block_innermost_frame PARAMS ((struct block *));
+
+extern struct frame_info *find_frame_addr_in_frame_chain PARAMS ((CORE_ADDR));
+
+extern CORE_ADDR sigtramp_saved_pc PARAMS ((struct frame_info *));
+
+extern CORE_ADDR generic_read_register_dummy PARAMS ((CORE_ADDR pc,
+ CORE_ADDR fp,
+ int));
+extern void generic_push_dummy_frame PARAMS ((void));
+extern void generic_pop_current_frame PARAMS ((void (*) (struct frame_info *)));
+extern void generic_pop_dummy_frame PARAMS ((void));
+
+extern int generic_pc_in_call_dummy PARAMS ((CORE_ADDR pc,
+ CORE_ADDR fp));
+extern char * generic_find_dummy_frame PARAMS ((CORE_ADDR pc,
+ CORE_ADDR fp));
+
+#ifdef __GNUC__
+/* Some native compilers, even ones that are supposed to be ANSI and for which __STDC__
+ is true, complain about forward decls of enums. */
+enum lval_type;
+extern void generic_get_saved_register PARAMS ((char *, int *, CORE_ADDR *, struct frame_info *, int, enum lval_type *));
+#endif
+
+#endif /* !defined (FRAME_H) */
diff --git a/gdb/gdb-stabs.h b/gdb/gdb-stabs.h
new file mode 100644
index 00000000000..1ad782abdca
--- /dev/null
+++ b/gdb/gdb-stabs.h
@@ -0,0 +1,92 @@
+/* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 {
+ CORE_ADDR text_addr; /* Start of text section */
+ int text_size; /* Size of text section */
+ 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. */
+
+ /* See stabsread.h for the use of the following. */
+ struct header_file *header_files;
+ int n_header_files;
+ int n_allocated_header_files;
+
+ /* Pointers to BFD sections. These are used to speed up the building of
+ minimal symbols. */
+ asection *text_section;
+ asection *data_section;
+ asection *bss_section;
+};
+
+#define DBX_SYMFILE_INFO(o) ((o)->sym_stab_info)
+#define DBX_TEXT_ADDR(o) (DBX_SYMFILE_INFO(o)->text_addr)
+#define DBX_TEXT_SIZE(o) (DBX_SYMFILE_INFO(o)->text_size)
+#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)
+#define DBX_TEXT_SECTION(o) (DBX_SYMFILE_INFO(o)->text_section)
+#define DBX_DATA_SECTION(o) (DBX_SYMFILE_INFO(o)->data_section)
+#define DBX_BSS_SECTION(o) (DBX_SYMFILE_INFO(o)->bss_section)
+
+#endif /* GDBSTABS_H */
diff --git a/gdb/gdb.1 b/gdb/gdb.1
new file mode 100644
index 00000000000..2430b18c6ca
--- /dev/null
+++ b/gdb/gdb.1
@@ -0,0 +1,375 @@
+.\" Copyright (c) 1991 Free Software Foundation
+.\" See section COPYING for conditions for redistribution
+.\" $Id$
+.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
+.B \-write
+Enable writing into executable and core files.
+
+.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/gdb/gdb.gdb b/gdb/gdb.gdb
new file mode 100644
index 00000000000..437784102c1
--- /dev/null
+++ b/gdb/gdb.gdb
@@ -0,0 +1,35 @@
+# Examples of using gdb's command language to print out various gdb data
+# structures.
+
+define list-objfiles
+ set $obj = object_files
+ printf "objfile bfd msyms name\n"
+ while $obj != 0
+ printf "0x%-8x 0x%-8x %6d %s\n", $obj, $obj->obfd, \
+ $obj->minimal_symbol_count, $obj->name
+ set var $obj = $obj->next
+ end
+end
+document list-objfiles
+Print a table of the current objfiles.
+end
+
+define print-values
+ printf "Location Offset Size Lazy Contents0-3 Lval\n"
+ set $val = $arg0
+ while $val != 0
+ printf "%8x %6d %10d %4d %12x ", $val->location.address, \
+ $val->offset, \
+ $val->type->length, $val->lazy, $val->aligner.contents[0]
+ output $val->lval
+ printf "\n"
+ set $val = $val->next
+ end
+end
+document print-values
+Print a list of values.
+Takes one argument, the value to print, and prints all the values which
+are chained through the next field. Thus the most recently created values
+will be listed first. The "Contents0-3" field gives the first "int"
+of the VALUE_CONTENTS; not the entire contents.
+end
diff --git a/gdb/gdb_stat.h b/gdb/gdb_stat.h
new file mode 100644
index 00000000000..b871b292a53
--- /dev/null
+++ b/gdb/gdb_stat.h
@@ -0,0 +1,68 @@
+/* Portable <sys/stat.h>
+ Copyright 1995 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#if !defined(GDB_STAT_H)
+#define GDB_STAT_H
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#ifdef STAT_MACROS_BROKEN
+#undef S_ISBLK
+#undef S_ISCHR
+#undef S_ISDIR
+#undef S_ISREG
+#undef S_ISFIFO
+#undef S_ISLNK
+#undef S_ISSOCK
+#undef S_ISMPB
+#undef S_ISMPC
+#undef S_ISNWK
+#endif
+
+#if !defined(S_ISBLK) && defined(S_IFBLK)
+#define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK)
+#endif
+#if !defined(S_ISCHR) && defined(S_IFCHR)
+#define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR)
+#endif
+#if !defined(S_ISDIR) && defined(S_IFDIR)
+#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
+#endif
+#if !defined(S_ISREG) && defined(S_IFREG)
+#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
+#endif
+#if !defined(S_ISFIFO) && defined(S_IFIFO)
+#define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO)
+#endif
+#if !defined(S_ISLNK) && defined(S_IFLNK)
+#define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
+#endif
+#if !defined(S_ISSOCK) && defined(S_IFSOCK)
+#define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)
+#endif
+#if !defined(S_ISMPB) && defined(S_IFMPB) /* V7 */
+#define S_ISMPB(m) (((m) & S_IFMT) == S_IFMPB)
+#define S_ISMPC(m) (((m) & S_IFMT) == S_IFMPC)
+#endif
+#if !defined(S_ISNWK) && defined(S_IFNWK) /* HP/UX */
+#define S_ISNWK(m) (((m) & S_IFMT) == S_IFNWK)
+#endif
+
+#endif /* !defined(GDB_STAT_H) */
diff --git a/gdb/gdb_string.h b/gdb/gdb_string.h
new file mode 100644
index 00000000000..944eec14ad9
--- /dev/null
+++ b/gdb/gdb_string.h
@@ -0,0 +1,68 @@
+/* Portable <string.h>
+ Copyright 1995, 1998 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#if !defined(GDB_STRING_H)
+#define GDB_STRING_H
+
+#ifdef STDC_HEADERS
+#include <string.h>
+#else
+# ifdef HAVE_STRING_H
+# include <string.h>
+# else
+# include <strings.h>
+# endif
+
+#ifndef strchr
+extern char *strchr PARAMS ((const char *, int)); /* X3.159-1989 4.11.5.2 */
+#endif
+
+#ifndef strrchr
+extern char *strrchr PARAMS ((const char *, int)); /* X3.159-1989 4.11.5.5 */
+#endif
+
+#ifndef strstr
+extern char *strstr PARAMS ((const char *, const char *)); /* X3.159-1989 4.11.5.7 */
+#endif
+
+#ifndef strtok
+extern char *strtok PARAMS ((char *, const char *)); /* X3.159-1989 4.11.5.8 */
+#endif
+
+# ifdef HAVE_MEMORY_H
+# include <memory.h>
+# else
+extern void *memset();
+extern void *memcpy();
+extern void *memmove();
+extern int memcmp();
+# endif
+#endif /* STDC_HEADERS */
+
+#ifdef NEED_DECLARATION_STRERROR
+#ifndef strerror
+extern char *strerror PARAMS ((int)); /* X3.159-1989 4.11.6.2 */
+#endif
+#endif
+
+#ifdef NEED_DECLARATION_STRDUP
+extern char *strdup (); /* full prototype collides w/ some OSes (AIX 3.2.5) */
+#endif
+
+#endif /* !defined(GDB_STRING_H) */
diff --git a/gdb/gdba.el b/gdb/gdba.el
new file mode 100644
index 00000000000..0f715864228
--- /dev/null
+++ b/gdb/gdba.el
@@ -0,0 +1,2607 @@
+(defmacro gud (form)
+ (` (save-excursion (set-buffer "*gud-a.out*") (, form))))
+
+(defun dbug (foo &optional fun)
+ (save-excursion
+ (set-buffer (get-buffer-create "*trace*"))
+ (goto-char (point-max))
+ (insert "***" (symbol-name foo) "\n")
+ (if fun
+ (funcall fun))))
+
+
+;;; gud.el --- Grand Unified Debugger mode for gdb, sdb, dbx, or xdb
+;;; under Emacs
+
+;; Author: Eric S. Raymond <esr@snark.thyrsus.com>
+;; Maintainer: FSF
+;; Version: 1.3
+;; Keywords: unix, tools
+
+;; Copyright (C) 1992, 1993 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; if not, write to the Free Software
+;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+
+;; The ancestral gdb.el was by W. Schelter <wfs@rascal.ics.utexas.edu>
+;; It was later rewritten by rms. Some ideas were due to Masanobu.
+;; Grand Unification (sdb/dbx support) by Eric S. Raymond <esr@thyrsus.com>
+;; The overloading code was then rewritten by Barry Warsaw <bwarsaw@cen.com>,
+;; who also hacked the mode to use comint.el. Shane Hartman <shane@spr.com>
+;; added support for xdb (HPUX debugger).
+
+;; Cygnus Support added support for gdb's --annotate=2.
+
+;;; Code:
+
+(require 'comint)
+(require 'etags)
+
+;; ======================================================================
+;; GUD commands must be visible in C buffers visited by GUD
+
+(defvar gud-key-prefix "\C-x\C-a"
+ "Prefix of all GUD commands valid in C buffers.")
+
+(global-set-key (concat gud-key-prefix "\C-l") 'gud-refresh)
+(global-set-key "\C-x " 'gud-break) ;; backward compatibility hack
+
+;; ======================================================================
+;; the overloading mechanism
+
+(defun gud-overload-functions (gud-overload-alist)
+ "Overload functions defined in GUD-OVERLOAD-ALIST.
+This association list has elements of the form
+ (ORIGINAL-FUNCTION-NAME OVERLOAD-FUNCTION)"
+ (mapcar
+ (function (lambda (p) (fset (car p) (symbol-function (cdr p)))))
+ gud-overload-alist))
+
+(defun gud-massage-args (file args)
+ (error "GUD not properly entered."))
+
+(defun gud-marker-filter (str)
+ (error "GUD not properly entered."))
+
+(defun gud-find-file (f)
+ (error "GUD not properly entered."))
+
+;; ======================================================================
+;; command definition
+
+;; This macro is used below to define some basic debugger interface commands.
+;; Of course you may use `gud-def' with any other debugger command, including
+;; user defined ones.
+
+;; A macro call like (gud-def FUNC NAME KEY DOC) expands to a form
+;; which defines FUNC to send the command NAME to the debugger, gives
+;; it the docstring DOC, and binds that function to KEY in the GUD
+;; major mode. The function is also bound in the global keymap with the
+;; GUD prefix.
+
+(defmacro gud-def (func cmd key &optional doc)
+ "Define FUNC to be a command sending STR and bound to KEY, with
+optional doc string DOC. Certain %-escapes in the string arguments
+are interpreted specially if present. These are:
+
+ %f name (without directory) of current source file.
+ %d directory of current source file.
+ %l number of current source line
+ %e text of the C lvalue or function-call expression surrounding point.
+ %a text of the hexadecimal address surrounding point
+ %p prefix argument to the command (if any) as a number
+
+ The `current' source file is the file of the current buffer (if
+we're in a C file) or the source file current at the last break or
+step (if we're in the GUD buffer).
+ The `current' line is that of the current buffer (if we're in a
+source file) or the source line number at the last break or step (if
+we're in the GUD buffer)."
+ (list 'progn
+ (list 'defun func '(arg)
+ (or doc "")
+ '(interactive "p")
+ (list 'gud-call cmd 'arg))
+ (if key
+ (list 'define-key
+ '(current-local-map)
+ (concat "\C-c" key)
+ (list 'quote func)))
+ (if key
+ (list 'global-set-key
+ (list 'concat 'gud-key-prefix key)
+ (list 'quote func)))))
+
+;; Where gud-display-frame should put the debugging arrow. This is
+;; set by the marker-filter, which scans the debugger's output for
+;; indications of the current program counter.
+(defvar gud-last-frame nil)
+
+;; Used by gud-refresh, which should cause gud-display-frame to redisplay
+;; the last frame, even if it's been called before and gud-last-frame has
+;; been set to nil.
+(defvar gud-last-last-frame nil)
+
+;; All debugger-specific information is collected here.
+;; Here's how it works, in case you ever need to add a debugger to the mode.
+;;
+;; Each entry must define the following at startup:
+;;
+;;<name>
+;; comint-prompt-regexp
+;; gud-<name>-massage-args
+;; gud-<name>-marker-filter
+;; gud-<name>-find-file
+;;
+;; The job of the massage-args method is to modify the given list of
+;; debugger arguments before running the debugger.
+;;
+;; The job of the marker-filter method is to detect file/line markers in
+;; strings and set the global gud-last-frame to indicate what display
+;; action (if any) should be triggered by the marker. Note that only
+;; whatever the method *returns* is displayed in the buffer; thus, you
+;; can filter the debugger's output, interpreting some and passing on
+;; the rest.
+;;
+;; The job of the find-file method is to visit and return the buffer indicated
+;; by the car of gud-tag-frame. This may be a file name, a tag name, or
+;; something else.
+
+;; ======================================================================
+;; gdb functions
+
+;;; History of argument lists passed to gdb.
+(defvar gud-gdb-history nil)
+
+(defun gud-gdb-massage-args (file args)
+ (cons "--annotate=2" (cons file args)))
+
+
+;;
+;; In this world, there are gdb instance objects (of unspecified
+;; representation) and buffers associated with those objects.
+;;
+
+;;
+;; gdb-instance objects
+;;
+
+(defun make-gdb-instance (proc)
+ "Create a gdb instance object from a gdb process."
+ (setq last-proc proc)
+ (let ((instance (cons 'gdb-instance proc)))
+ (save-excursion
+ (set-buffer (process-buffer proc))
+ (setq gdb-buffer-instance instance)
+ (progn
+ (mapcar 'make-variable-buffer-local gdb-instance-variables)
+ (setq gdb-buffer-type 'gud)
+ ;; If we're taking over the buffer of another process,
+ ;; take over it's ancillery buffers as well.
+ ;;
+ (let ((dead (or old-gdb-buffer-instance)))
+ (mapcar
+ (function
+ (lambda (b)
+ (progn
+ (set-buffer b)
+ (if (eq dead gdb-buffer-instance)
+ (setq gdb-buffer-instance instance)))))
+ (buffer-list)))))
+ instance))
+
+(defun gdb-instance-process (inst) (cdr inst))
+
+;;; The list of instance variables is built up by the expansions of
+;;; DEF-GDB-VARIABLE
+;;;
+(defvar gdb-instance-variables '()
+ "A list of variables that are local to the gud buffer associated
+with a gdb instance.")
+
+(defmacro def-gdb-variable
+ (name accessor setter &optional default doc)
+ (`
+ (progn
+ (defvar (, name) (, default) (, (or doc "undocumented")))
+ (if (not (memq '(, name) gdb-instance-variables))
+ (setq gdb-instance-variables
+ (cons '(, name) gdb-instance-variables)))
+ (, (and accessor
+ (`
+ (defun (, accessor) (instance)
+ (let
+ ((buffer (gdb-get-instance-buffer instance 'gud)))
+ (and buffer
+ (save-excursion
+ (set-buffer buffer)
+ (, name))))))))
+ (, (and setter
+ (`
+ (defun (, setter) (instance val)
+ (let
+ ((buffer (gdb-get-instance-buffer instance 'gud)))
+ (and buffer
+ (save-excursion
+ (set-buffer buffer)
+ (setq (, name) val)))))))))))
+
+(defmacro def-gdb-var (root-symbol &optional default doc)
+ (let* ((root (symbol-name root-symbol))
+ (accessor (intern (concat "gdb-instance-" root)))
+ (setter (intern (concat "set-gdb-instance-" root)))
+ (var-name (intern (concat "gdb-" root))))
+ (` (def-gdb-variable
+ (, var-name) (, accessor) (, setter)
+ (, default) (, doc)))))
+
+(def-gdb-var buffer-instance nil
+ "In an instance buffer, the buffer's instance.")
+
+(def-gdb-var buffer-type nil
+ "One of the symbols bound in gdb-instance-buffer-rules")
+
+(def-gdb-var burst ""
+ "A string of characters from gdb that have not yet been processed.")
+
+(def-gdb-var input-queue ()
+ "A list of high priority gdb command objects.")
+
+(def-gdb-var idle-input-queue ()
+ "A list of low priority gdb command objects.")
+
+(def-gdb-var prompting nil
+ "True when gdb is idle with no pending input.")
+
+(def-gdb-var output-sink 'user
+ "The disposition of the output of the current gdb command.
+Possible values are these symbols:
+
+ user -- gdb output should be copied to the gud buffer
+ for the user to see.
+
+ inferior -- gdb output should be copied to the inferior-io buffer
+
+ pre-emacs -- output should be ignored util the post-prompt
+ annotation is received. Then the output-sink
+ becomes:...
+ emacs -- output should be collected in the partial-output-buffer
+ for subsequent processing by a command. This is the
+ disposition of output generated by commands that
+ gud mode sends to gdb on its own behalf.
+ post-emacs -- ignore input until the prompt annotation is
+ received, then go to USER disposition.
+")
+
+(def-gdb-var current-item nil
+ "The most recent command item sent to gdb.")
+
+(def-gdb-var pending-triggers '()
+ "A list of trigger functions that have run later than their output
+handlers.")
+
+(defun in-gdb-instance-context (instance form)
+ "Funcall `form' in the gud buffer of `instance'"
+ (save-excursion
+ (set-buffer (gdb-get-instance-buffer instance 'gud))
+ (funcall form)))
+
+;; end of instance vars
+
+;;
+;; finding instances
+;;
+
+(defun gdb-proc->instance (proc)
+ (save-excursion
+ (set-buffer (process-buffer proc))
+ gdb-buffer-instance))
+
+(defun gdb-mru-instance-buffer ()
+ "Return the most recently used (non-auxiliary) gdb gud buffer."
+ (save-excursion
+ (gdb-goto-first-gdb-instance (buffer-list))))
+
+(defun gdb-goto-first-gdb-instance (blist)
+ "Use gdb-mru-instance-buffer -- not this."
+ (and blist
+ (progn
+ (set-buffer (car blist))
+ (or (and gdb-buffer-instance
+ (eq gdb-buffer-type 'gud)
+ (car blist))
+ (gdb-goto-first-gdb-instance (cdr blist))))))
+
+(defun buffer-gdb-instance (buf)
+ (save-excursion
+ (set-buffer buf)
+ gdb-buffer-instance))
+
+(defun gdb-needed-default-instance ()
+ "Return the most recently used gdb instance or signal an error."
+ (let ((buffer (gdb-mru-instance-buffer)))
+ (or (and buffer (buffer-gdb-instance buffer))
+ (error "No instance of gdb found."))))
+
+(defun gdb-instance-target-string (instance)
+ "The apparent name of the program being debugged by a gdb instance.
+For sure this the root string used in smashing together the gud
+buffer's name, even if that doesn't happen to be the name of a
+program."
+ (in-gdb-instance-context
+ instance
+ (function (lambda () gud-target-name))))
+
+
+
+;;
+;; Instance Buffers.
+;;
+
+;; More than one buffer can be associated with a gdb instance.
+;;
+;; Each buffer has a TYPE -- a symbol that identifies the function
+;; of that particular buffer.
+;;
+;; The usual gud interaction buffer is given the type `gud' and
+;; is constructed specially.
+;;
+;; Others are constructed by gdb-get-create-instance-buffer and
+;; named according to the rules set forth in the gdb-instance-buffer-rules-assoc
+
+(defun gdb-get-instance-buffer (instance key)
+ "Return the instance buffer for `instance' tagged with type `key'.
+The key should be one of the cars in `gdb-instance-buffer-rules-assoc'."
+ (save-excursion
+ (gdb-look-for-tagged-buffer instance key (buffer-list))))
+
+(defun gdb-get-create-instance-buffer (instance key)
+ "Create a new gdb instance buffer of the type specified by `key'.
+The key should be one of the cars in `gdb-instance-buffer-rules-assoc'."
+ (or (gdb-get-instance-buffer instance key)
+ (let* ((rules (assoc key gdb-instance-buffer-rules-assoc))
+ (name (funcall (gdb-rules-name-maker rules) instance))
+ (new (get-buffer-create name)))
+ (save-excursion
+ (set-buffer new)
+ (make-variable-buffer-local 'gdb-buffer-type)
+ (setq gdb-buffer-type key)
+ (make-variable-buffer-local 'gdb-buffer-instance)
+ (setq gdb-buffer-instance instance)
+ (if (cdr (cdr rules))
+ (funcall (car (cdr (cdr rules)))))
+ new))))
+
+(defun gdb-rules-name-maker (rules) (car (cdr rules)))
+
+(defun gdb-look-for-tagged-buffer (instance key bufs)
+ (let ((retval nil))
+ (while (and (not retval) bufs)
+ (set-buffer (car bufs))
+ (if (and (eq gdb-buffer-instance instance)
+ (eq gdb-buffer-type key))
+ (setq retval (car bufs)))
+ (setq bufs (cdr bufs))
+ )
+ retval))
+
+(defun gdb-instance-buffer-p (buf)
+ (save-excursion
+ (set-buffer buf)
+ (and gdb-buffer-type
+ (not (eq gdb-buffer-type 'gud)))))
+
+;;
+;; This assoc maps buffer type symbols to rules. Each rule is a list of
+;; at least one and possible more functions. The functions have these
+;; roles in defining a buffer type:
+;;
+;; NAME - take an instance, return a name for this type buffer for that
+;; instance.
+;; The remaining function(s) are optional:
+;;
+;; MODE - called in new new buffer with no arguments, should establish
+;; the proper mode for the buffer.
+;;
+
+(defvar gdb-instance-buffer-rules-assoc '())
+
+(defun gdb-set-instance-buffer-rules (buffer-type &rest rules)
+ (let ((binding (assoc buffer-type gdb-instance-buffer-rules-assoc)))
+ (if binding
+ (setcdr binding rules)
+ (setq gdb-instance-buffer-rules-assoc
+ (cons (cons buffer-type rules)
+ gdb-instance-buffer-rules-assoc)))))
+
+(gdb-set-instance-buffer-rules 'gud 'error) ; gud buffers are an exception to the rules
+
+;;
+;; partial-output buffers
+;;
+;; These accumulate output from a command executed on
+;; behalf of emacs (rather than the user).
+;;
+
+(gdb-set-instance-buffer-rules 'gdb-partial-output-buffer
+ 'gdb-partial-output-name)
+
+(defun gdb-partial-output-name (instance)
+ (concat "*partial-output-"
+ (gdb-instance-target-string instance)
+ "*"))
+
+
+(gdb-set-instance-buffer-rules 'gdb-inferior-io
+ 'gdb-inferior-io-name
+ 'gud-inferior-io-mode)
+
+(defun gdb-inferior-io-name (instance)
+ (concat "*input/output of "
+ (gdb-instance-target-string instance)
+ "*"))
+
+(defvar gdb-inferior-io-mode-map (copy-keymap comint-mode-map))
+(define-key comint-mode-map "\C-c\C-c" 'gdb-inferior-io-interrupt)
+(define-key comint-mode-map "\C-c\C-z" 'gdb-inferior-io-stop)
+(define-key comint-mode-map "\C-c\C-\\" 'gdb-inferior-io-quit)
+(define-key comint-mode-map "\C-c\C-d" 'gdb-inferior-io-eof)
+
+(defun gud-inferior-io-mode ()
+ "Major mode for gud inferior-io.
+
+\\{comint-mode-map}"
+ ;; We want to use comint because it has various nifty and familiar
+ ;; features. We don't need a process, but comint wants one, so create
+ ;; a dummy one.
+ (make-comint (substring (buffer-name) 1 (- (length (buffer-name)) 1))
+ "/bin/cat")
+ (setq major-mode 'gud-inferior-io-mode)
+ (setq mode-name "Debuggee I/O")
+ (setq comint-input-sender 'gud-inferior-io-sender)
+)
+
+(defun gud-inferior-io-sender (proc string)
+ (save-excursion
+ (set-buffer (process-buffer proc))
+ (let ((instance gdb-buffer-instance))
+ (set-buffer (gdb-get-instance-buffer instance 'gud))
+ (let ((gud-proc (get-buffer-process (current-buffer))))
+ (process-send-string gud-proc string)
+ (process-send-string gud-proc "\n")
+ ))
+ ))
+
+(defun gdb-inferior-io-interrupt (instance)
+ "Interrupt the program being debugged."
+ (interactive (list (gdb-needed-default-instance)))
+ (interrupt-process
+ (get-buffer-process (gdb-get-instance-buffer instance 'gud)) comint-ptyp))
+
+(defun gdb-inferior-io-quit (instance)
+ "Send quit signal to the program being debugged."
+ (interactive (list (gdb-needed-default-instance)))
+ (quit-process
+ (get-buffer-process (gdb-get-instance-buffer instance 'gud)) comint-ptyp))
+
+(defun gdb-inferior-io-stop (instance)
+ "Stop the program being debugged."
+ (interactive (list (gdb-needed-default-instance)))
+ (stop-process
+ (get-buffer-process (gdb-get-instance-buffer instance 'gud)) comint-ptyp))
+
+(defun gdb-inferior-io-eof (instance)
+ "Send end-of-file to the program being debugged."
+ (interactive (list (gdb-needed-default-instance)))
+ (process-send-eof
+ (get-buffer-process (gdb-get-instance-buffer instance 'gud))))
+
+
+;;
+;; gdb communications
+;;
+
+;; INPUT: things sent to gdb
+;;
+;; Each instance has a high and low priority
+;; input queue. Low priority input is sent only
+;; when the high priority queue is idle.
+;;
+;; The queues are lists. Each element is either
+;; a string (indicating user or user-like input)
+;; or a list of the form:
+;;
+;; (INPUT-STRING HANDLER-FN)
+;;
+;;
+;; The handler function will be called from the
+;; partial-output buffer when the command completes.
+;; This is the way to write commands which
+;; invoke gdb commands autonomously.
+;;
+;; These lists are consumed tail first.
+;;
+
+(defun gdb-send (proc string)
+ "A comint send filter for gdb.
+This filter may simply queue output for a later time."
+ (let ((instance (gdb-proc->instance proc)))
+ (gdb-instance-enqueue-input instance (concat string "\n"))))
+
+;; Note: Stuff enqueued here will be sent to the next prompt, even if it
+;; is a query, or other non-top-level prompt. To guarantee stuff will get
+;; sent to the top-level prompt, currently it must be put in the idle queue.
+;; ^^^^^^^^^
+;; [This should encourage gud extentions that invoke gdb commands to let
+;; the user go first; it is not a bug. -t]
+;;
+
+(defun gdb-instance-enqueue-input (instance item)
+ (if (gdb-instance-prompting instance)
+ (progn
+ (gdb-send-item instance item)
+ (set-gdb-instance-prompting instance nil))
+ (set-gdb-instance-input-queue
+ instance
+ (cons item (gdb-instance-input-queue instance)))))
+
+(defun gdb-instance-dequeue-input (instance)
+ (let ((queue (gdb-instance-input-queue instance)))
+ (and queue
+ (if (not (cdr queue))
+ (let ((answer (car queue)))
+ (set-gdb-instance-input-queue instance '())
+ answer)
+ (gdb-take-last-elt queue)))))
+
+(defun gdb-instance-enqueue-idle-input (instance item)
+ (if (and (gdb-instance-prompting instance)
+ (not (gdb-instance-input-queue instance)))
+ (progn
+ (gdb-send-item instance item)
+ (set-gdb-instance-prompting instance nil))
+ (set-gdb-instance-idle-input-queue
+ instance
+ (cons item (gdb-instance-idle-input-queue instance)))))
+
+(defun gdb-instance-dequeue-idle-input (instance)
+ (let ((queue (gdb-instance-idle-input-queue instance)))
+ (and queue
+ (if (not (cdr queue))
+ (let ((answer (car queue)))
+ (set-gdb-instance-idle-input-queue instance '())
+ answer)
+ (gdb-take-last-elt queue)))))
+
+; Don't use this in general.
+(defun gdb-take-last-elt (l)
+ (if (cdr (cdr l))
+ (gdb-take-last-elt (cdr l))
+ (let ((answer (car (cdr l))))
+ (setcdr l '())
+ answer)))
+
+
+;;
+;; output -- things gdb prints to emacs
+;;
+;; GDB output is a stream interrupted by annotations.
+;; Annotations can be recognized by their beginning
+;; with \C-j\C-z\C-z<tag><opt>\C-j
+;;
+;; The tag is a string obeying symbol syntax.
+;;
+;; The optional part `<opt>' can be either the empty string
+;; or a space followed by more data relating to the annotation.
+;; For example, the SOURCE annotation is followed by a filename,
+;; line number and various useless goo. This data must not include
+;; any newlines.
+;;
+
+
+(defun gud-gdb-marker-filter (string)
+ "A gud marker filter for gdb."
+ ;; Bogons don't tell us the process except through scoping crud.
+ (let ((instance (gdb-proc->instance proc)))
+ (gdb-output-burst instance string)))
+
+(defvar gdb-annotation-rules
+ '(("frames-invalid" gdb-invalidate-frames)
+ ("breakpoints-invalid" gdb-invalidate-breakpoints)
+ ("pre-prompt" gdb-pre-prompt)
+ ("prompt" gdb-prompt)
+ ("commands" gdb-subprompt)
+ ("overload-choice" gdb-subprompt)
+ ("query" gdb-subprompt)
+ ("prompt-for-continue" gdb-subprompt)
+ ("post-prompt" gdb-post-prompt)
+ ("source" gdb-source)
+ ("starting" gdb-starting)
+ ("exited" gdb-stopping)
+ ("signalled" gdb-stopping)
+ ("signal" gdb-stopping)
+ ("breakpoint" gdb-stopping)
+ ("watchpoint" gdb-stopping)
+ ("stopped" gdb-stopped)
+ )
+ "An assoc mapping annotation tags to functions which process them.")
+
+
+(defun gdb-ignore-annotation (instance args)
+ nil)
+
+(defconst gdb-source-spec-regexp
+ "\\(.*\\):\\([0-9]*\\):[0-9]*:[a-z]*:0x[a-f0-9]*")
+
+;; Do not use this except as an annotation handler."
+(defun gdb-source (instance args)
+ (string-match gdb-source-spec-regexp args)
+ ;; Extract the frame position from the marker.
+ (setq gud-last-frame
+ (cons
+ (substring args (match-beginning 1) (match-end 1))
+ (string-to-int (substring args
+ (match-beginning 2)
+ (match-end 2))))))
+
+;; An annotation handler for `prompt'.
+;; This sends the next command (if any) to gdb.
+(defun gdb-prompt (instance ignored)
+ (let ((sink (gdb-instance-output-sink instance)))
+ (cond
+ ((eq sink 'user) t)
+ ((eq sink 'post-emacs)
+ (set-gdb-instance-output-sink instance 'user))
+ (t
+ (set-gdb-instance-output-sink instance 'user)
+ (error "Phase error in gdb-prompt (got %s)" sink))))
+ (let ((highest (gdb-instance-dequeue-input instance)))
+ (if highest
+ (gdb-send-item instance highest)
+ (let ((lowest (gdb-instance-dequeue-idle-input instance)))
+ (if lowest
+ (gdb-send-item instance lowest)
+ (progn
+ (set-gdb-instance-prompting instance t)
+ (gud-display-frame)))))))
+
+;; An annotation handler for non-top-level prompts.
+(defun gdb-subprompt (instance ignored)
+ (let ((highest (gdb-instance-dequeue-input instance)))
+ (if highest
+ (gdb-send-item instance highest)
+ (set-gdb-instance-prompting instance t))))
+
+(defun gdb-send-item (instance item)
+ (set-gdb-instance-current-item instance item)
+ (if (stringp item)
+ (progn
+ (set-gdb-instance-output-sink instance 'user)
+ (process-send-string (gdb-instance-process instance)
+ item))
+ (progn
+ (gdb-clear-partial-output instance)
+ (set-gdb-instance-output-sink instance 'pre-emacs)
+ (process-send-string (gdb-instance-process instance)
+ (car item)))))
+
+;; An annotation handler for `pre-prompt'.
+;; This terminates the collection of output from a previous
+;; command if that happens to be in effect.
+(defun gdb-pre-prompt (instance ignored)
+ (let ((sink (gdb-instance-output-sink instance)))
+ (cond
+ ((eq sink 'user) t)
+ ((eq sink 'emacs)
+ (set-gdb-instance-output-sink instance 'post-emacs)
+ (let ((handler
+ (car (cdr (gdb-instance-current-item instance)))))
+ (save-excursion
+ (set-buffer (gdb-get-create-instance-buffer
+ instance 'gdb-partial-output-buffer))
+ (funcall handler))))
+ (t
+ (set-gdb-instance-output-sink instance 'user)
+ (error "Output sink phase error 1.")))))
+
+;; An annotation handler for `starting'. This says that I/O for the subprocess
+;; is now the program being debugged, not GDB.
+(defun gdb-starting (instance ignored)
+ (let ((sink (gdb-instance-output-sink instance)))
+ (cond
+ ((eq sink 'user)
+ (set-gdb-instance-output-sink instance 'inferior)
+ ;; FIXME: need to send queued input
+ )
+ (t (error "Unexpected `starting' annotation")))))
+
+;; An annotation handler for `exited' and other annotations which say that
+;; I/O for the subprocess is now GDB, not the program being debugged.
+(defun gdb-stopping (instance ignored)
+ (let ((sink (gdb-instance-output-sink instance)))
+ (cond
+ ((eq sink 'inferior)
+ (set-gdb-instance-output-sink instance 'user)
+ )
+ (t (error "Unexpected stopping annotation")))))
+
+;; An annotation handler for `stopped'. It is just like gdb-stopping, except
+;; that if we already set the output sink to 'user in gdb-stopping, that is
+;; fine.
+(defun gdb-stopped (instance ignored)
+ (let ((sink (gdb-instance-output-sink instance)))
+ (cond
+ ((eq sink 'inferior)
+ (set-gdb-instance-output-sink instance 'user)
+ )
+ ((eq sink 'user)
+ t)
+ (t (error "Unexpected stopping annotation")))))
+
+;; An annotation handler for `post-prompt'.
+;; This begins the collection of output from the current
+;; command if that happens to be appropriate."
+(defun gdb-post-prompt (instance ignored)
+ (gdb-invalidate-registers instance ignored)
+ (let ((sink (gdb-instance-output-sink instance)))
+ (cond
+ ((eq sink 'user) t)
+ ((eq sink 'pre-emacs)
+ (set-gdb-instance-output-sink instance 'emacs))
+
+ (t
+ (set-gdb-instance-output-sink instance 'user)
+ (error "Output sink phase error 3.")))))
+
+;; Handle a burst of output from a gdb instance.
+;; This function is (indirectly) used as a gud-marker-filter.
+;; It must return output (if any) to be insterted in the gud
+;; buffer.
+
+(defun gdb-output-burst (instance string)
+ "Handle a burst of output from a gdb instance.
+This function is (indirectly) used as a gud-marker-filter.
+It must return output (if any) to be insterted in the gud
+buffer."
+
+ (save-match-data
+ (let (
+ ;; Recall the left over burst from last time
+ (burst (concat (gdb-instance-burst instance) string))
+ ;; Start accumulating output for the gud buffer
+ (output ""))
+
+ ;; Process all the complete markers in this chunk.
+
+ (while (string-match "\n\032\032\\(.*\\)\n" burst)
+ (let ((annotation (substring burst
+ (match-beginning 1)
+ (match-end 1))))
+
+ ;; Stuff prior to the match is just ordinary output.
+ ;; It is either concatenated to OUTPUT or directed
+ ;; elsewhere.
+ (setq output
+ (gdb-concat-output
+ instance
+ output
+ (substring burst 0 (match-beginning 0))))
+
+ ;; Take that stuff off the burst.
+ (setq burst (substring burst (match-end 0)))
+
+ ;; Parse the tag from the annotation, and maybe its arguments.
+ (string-match "\\(\\S-*\\) ?\\(.*\\)" annotation)
+ (let* ((annotation-type (substring annotation
+ (match-beginning 1)
+ (match-end 1)))
+ (annotation-arguments (substring annotation
+ (match-beginning 2)
+ (match-end 2)))
+ (annotation-rule (assoc annotation-type
+ gdb-annotation-rules)))
+ ;; Call the handler for this annotation.
+ (if annotation-rule
+ (funcall (car (cdr annotation-rule))
+ instance
+ annotation-arguments)
+ ;; Else the annotation is not recognized. Ignore it silently,
+ ;; so that GDB can add new annotations without causing
+ ;; us to blow up.
+ ))))
+
+
+ ;; Does the remaining text end in a partial line?
+ ;; If it does, then keep part of the burst until we get more.
+ (if (string-match "\n\\'\\|\n\032\\'\\|\n\032\032.*\\'"
+ burst)
+ (progn
+ ;; Everything before the potential marker start can be output.
+ (setq output
+ (gdb-concat-output
+ instance
+ output
+ (substring burst 0 (match-beginning 0))))
+
+ ;; Everything after, we save, to combine with later input.
+ (setq burst (substring burst (match-beginning 0))))
+
+ ;; In case we know the burst contains no partial annotations:
+ (progn
+ (setq output (gdb-concat-output instance output burst))
+ (setq burst "")))
+
+ ;; Save the remaining burst for the next call to this function.
+ (set-gdb-instance-burst instance burst)
+ output)))
+
+(defun gdb-concat-output (instance so-far new)
+ (let ((sink (gdb-instance-output-sink instance)))
+ (cond
+ ((eq sink 'user) (concat so-far new))
+ ((or (eq sink 'pre-emacs) (eq sink 'post-emacs)) so-far)
+ ((eq sink 'emacs)
+ (gdb-append-to-partial-output instance new)
+ so-far)
+ ((eq sink 'inferior)
+ (gdb-append-to-inferior-io instance new)
+ so-far)
+ (t (error "Bogon output sink %S" sink)))))
+
+(defun gdb-append-to-partial-output (instance string)
+ (save-excursion
+ (set-buffer
+ (gdb-get-create-instance-buffer
+ instance 'gdb-partial-output-buffer))
+ (goto-char (point-max))
+ (insert string)))
+
+(defun gdb-clear-partial-output (instance)
+ (save-excursion
+ (set-buffer
+ (gdb-get-create-instance-buffer
+ instance 'gdb-partial-output-buffer))
+ (delete-region (point-min) (point-max))))
+
+(defun gdb-append-to-inferior-io (instance string)
+ (save-excursion
+ (set-buffer
+ (gdb-get-create-instance-buffer
+ instance 'gdb-inferior-io))
+ (goto-char (point-max))
+ (insert-before-markers string))
+ (gud-display-buffer
+ (gdb-get-create-instance-buffer instance
+ 'gdb-inferior-io)))
+
+(defun gdb-clear-inferior-io (instance)
+ (save-excursion
+ (set-buffer
+ (gdb-get-create-instance-buffer
+ instance 'gdb-inferior-io))
+ (delete-region (point-min) (point-max))))
+
+
+
+;; One trick is to have a command who's output is always available in
+;; a buffer of it's own, and is always up to date. We build several
+;; buffers of this type.
+;;
+;; There are two aspects to this: gdb has to tell us when the output
+;; for that command might have changed, and we have to be able to run
+;; the command behind the user's back.
+;;
+;; The idle input queue and the output phasing associated with
+;; the instance variable `(gdb-instance-output-sink instance)' help
+;; us to run commands behind the user's back.
+;;
+;; Below is the code for specificly managing buffers of output from one
+;; command.
+;;
+
+
+;; The trigger function is suitable for use in the assoc GDB-ANNOTATION-RULES
+;; It adds an idle input for the command we are tracking. It should be the
+;; annotation rule binding of whatever gdb sends to tell us this command
+;; might have changed it's output.
+;;
+;; NAME is the fucntion name. DEMAND-PREDICATE tests if output is really needed.
+;; GDB-COMMAND is a string of such. OUTPUT-HANDLER is the function bound to the
+;; input in the input queue (see comment about ``gdb communications'' above).
+(defmacro def-gdb-auto-update-trigger (name demand-predicate gdb-command output-handler)
+ (`
+ (defun (, name) (instance &optional ignored)
+ (if (and ((, demand-predicate) instance)
+ (not (member '(, name)
+ (gdb-instance-pending-triggers instance))))
+ (progn
+ (gdb-instance-enqueue-idle-input
+ instance
+ (list (, gdb-command) '(, output-handler)))
+ (set-gdb-instance-pending-triggers
+ instance
+ (cons '(, name)
+ (gdb-instance-pending-triggers instance))))))))
+
+(defmacro def-gdb-auto-update-handler (name trigger buf-key)
+ (`
+ (defun (, name) ()
+ (set-gdb-instance-pending-triggers
+ instance
+ (delq '(, trigger)
+ (gdb-instance-pending-triggers instance)))
+ (let ((buf (gdb-get-instance-buffer instance
+ '(, buf-key))))
+ (and buf
+ (save-excursion
+ (set-buffer buf)
+ (let ((p (point))
+ (buffer-read-only nil))
+ (delete-region (point-min) (point-max))
+ (insert-buffer (gdb-get-create-instance-buffer
+ instance
+ 'gdb-partial-output-buffer))
+ (goto-char p))))))))
+
+(defmacro def-gdb-auto-updated-buffer
+ (buffer-key trigger-name gdb-command output-handler-name)
+ (`
+ (progn
+ (def-gdb-auto-update-trigger (, trigger-name)
+ ;; The demand predicate:
+ (lambda (instance)
+ (gdb-get-instance-buffer instance '(, buffer-key)))
+ (, gdb-command)
+ (, output-handler-name))
+ (def-gdb-auto-update-handler (, output-handler-name)
+ (, trigger-name) (, buffer-key)))))
+
+
+
+;;
+;; Breakpoint buffers
+;;
+;; These display the output of `info breakpoints'.
+;;
+
+
+(gdb-set-instance-buffer-rules 'gdb-breakpoints-buffer
+ 'gdb-breakpoints-buffer-name
+ 'gud-breakpoints-mode)
+
+(def-gdb-auto-updated-buffer gdb-breakpoints-buffer
+ ;; This defines the auto update rule for buffers of type
+ ;; `gdb-breakpoints-buffer'.
+ ;;
+ ;; It defines a function to serve as the annotation handler that
+ ;; handles the `foo-invalidated' message. That function is called:
+ gdb-invalidate-breakpoints
+
+ ;; To update the buffer, this command is sent to gdb.
+ "server info breakpoints\n"
+
+ ;; This also defines a function to be the handler for the output
+ ;; from the command above. That function will copy the output into
+ ;; the appropriately typed buffer. That function will be called:
+ gdb-info-breakpoints-handler)
+
+(defun gdb-breakpoints-buffer-name (instance)
+ (save-excursion
+ (set-buffer (process-buffer (gdb-instance-process instance)))
+ (concat "*breakpoints of " (gdb-instance-target-string instance) "*")))
+
+(defun gud-display-breakpoints-buffer (instance)
+ (interactive (list (gdb-needed-default-instance)))
+ (gud-display-buffer
+ (gdb-get-create-instance-buffer instance
+ 'gdb-breakpoints-buffer)))
+
+(defun gud-frame-breakpoints-buffer (instance)
+ (interactive (list (gdb-needed-default-instance)))
+ (gud-frame-buffer
+ (gdb-get-create-instance-buffer instance
+ 'gdb-breakpoints-buffer)))
+
+(defvar gud-breakpoints-mode-map nil)
+(setq gud-breakpoints-mode-map (make-keymap))
+(suppress-keymap gud-breakpoints-mode-map)
+(define-key gud-breakpoints-mode-map " " 'gud-toggle-bp-this-line)
+(define-key gud-breakpoints-mode-map "d" 'gud-delete-bp-this-line)
+
+(defun gud-breakpoints-mode ()
+ "Major mode for gud breakpoints.
+
+\\{gud-breakpoints-mode-map}"
+ (setq major-mode 'gud-breakpoints-mode)
+ (setq mode-name "Breakpoints")
+ (use-local-map gud-breakpoints-mode-map)
+ (setq buffer-read-only t)
+ (gdb-invalidate-breakpoints gdb-buffer-instance))
+
+(defun gud-toggle-bp-this-line ()
+ (interactive)
+ (save-excursion
+ (beginning-of-line 1)
+ (if (not (looking-at "\\([0-9]*\\)\\s-*\\S-*\\s-*\\S-*\\s-*\\(.\\)"))
+ (error "Not recognized as breakpoint line (demo foo).")
+ (gdb-instance-enqueue-idle-input
+ gdb-buffer-instance
+ (list
+ (concat
+ (if (eq ?y (char-after (match-beginning 2)))
+ "server disable "
+ "server enable ")
+ (buffer-substring (match-beginning 0)
+ (match-end 1))
+ "\n")
+ '(lambda () nil)))
+ )))
+
+(defun gud-delete-bp-this-line ()
+ (interactive)
+ (save-excursion
+ (beginning-of-line 1)
+ (if (not (looking-at "\\([0-9]*\\)\\s-*\\S-*\\s-*\\S-*\\s-*\\(.\\)"))
+ (error "Not recognized as breakpoint line (demo foo).")
+ (gdb-instance-enqueue-idle-input
+ gdb-buffer-instance
+ (list
+ (concat
+ "server delete "
+ (buffer-substring (match-beginning 0)
+ (match-end 1))
+ "\n")
+ '(lambda () nil)))
+ )))
+
+
+
+
+;;
+;; Frames buffers. These display a perpetually correct bactracktrace
+;; (from the command `where').
+;;
+;; Alas, if your stack is deep, they are costly.
+;;
+
+(gdb-set-instance-buffer-rules 'gdb-stack-buffer
+ 'gdb-stack-buffer-name
+ 'gud-frames-mode)
+
+(def-gdb-auto-updated-buffer gdb-stack-buffer
+ gdb-invalidate-frames
+ "server where\n"
+ gdb-info-frames-handler)
+
+(defun gdb-stack-buffer-name (instance)
+ (save-excursion
+ (set-buffer (process-buffer (gdb-instance-process instance)))
+ (concat "*stack frames of "
+ (gdb-instance-target-string instance) "*")))
+
+(defun gud-display-stack-buffer (instance)
+ (interactive (list (gdb-needed-default-instance)))
+ (gud-display-buffer
+ (gdb-get-create-instance-buffer instance
+ 'gdb-stack-buffer)))
+
+(defun gud-frame-stack-buffer (instance)
+ (interactive (list (gdb-needed-default-instance)))
+ (gud-frame-buffer
+ (gdb-get-create-instance-buffer instance
+ 'gdb-stack-buffer)))
+
+(defvar gud-frames-mode-map nil)
+(setq gud-frames-mode-map (make-keymap))
+(suppress-keymap gud-frames-mode-map)
+(define-key gud-frames-mode-map [mouse-2]
+ 'gud-frames-select-by-mouse)
+
+(defun gud-frames-mode ()
+ "Major mode for gud frames.
+
+\\{gud-frames-mode-map}"
+ (setq major-mode 'gud-frames-mode)
+ (setq mode-name "Frames")
+ (setq buffer-read-only t)
+ (use-local-map gud-frames-mode-map)
+ (gdb-invalidate-frames gdb-buffer-instance))
+
+(defun gud-get-frame-number ()
+ (save-excursion
+ (let* ((pos (re-search-backward "^#\\([0-9]*\\)" nil t))
+ (n (or (and pos
+ (string-to-int
+ (buffer-substring (match-beginning 1)
+ (match-end 1))))
+ 0)))
+ n)))
+
+(defun gud-frames-select-by-mouse (e)
+ (interactive "e")
+ (let (selection)
+ (save-excursion
+ (set-buffer (window-buffer (posn-window (event-end e))))
+ (save-excursion
+ (goto-char (posn-point (event-end e)))
+ (setq selection (gud-get-frame-number))))
+ (select-window (posn-window (event-end e)))
+ (save-excursion
+ (set-buffer (gdb-get-instance-buffer (gdb-needed-default-instance) 'gud))
+ (gud-call "fr %p" selection)
+ (gud-display-frame))))
+
+
+;;
+;; Registers buffers
+;;
+
+(def-gdb-auto-updated-buffer gdb-registers-buffer
+ gdb-invalidate-registers
+ "server info registers\n"
+ gdb-info-registers-handler)
+
+(gdb-set-instance-buffer-rules 'gdb-registers-buffer
+ 'gdb-registers-buffer-name
+ 'gud-registers-mode)
+
+(defvar gud-registers-mode-map nil)
+(setq gud-registers-mode-map (make-keymap))
+(suppress-keymap gud-registers-mode-map)
+
+(defun gud-registers-mode ()
+ "Major mode for gud registers.
+
+\\{gud-registers-mode-map}"
+ (setq major-mode 'gud-registers-mode)
+ (setq mode-name "Registers")
+ (setq buffer-read-only t)
+ (use-local-map gud-registers-mode-map)
+ (gdb-invalidate-registers gdb-buffer-instance))
+
+(defun gdb-registers-buffer-name (instance)
+ (save-excursion
+ (set-buffer (process-buffer (gdb-instance-process instance)))
+ (concat "*registers of " (gdb-instance-target-string instance) "*")))
+
+(defun gud-display-registers-buffer (instance)
+ (interactive (list (gdb-needed-default-instance)))
+ (gud-display-buffer
+ (gdb-get-create-instance-buffer instance
+ 'gdb-registers-buffer)))
+
+(defun gud-frame-registers-buffer (instance)
+ (interactive (list (gdb-needed-default-instance)))
+ (gud-frame-buffer
+ (gdb-get-create-instance-buffer instance
+ 'gdb-registers-buffer)))
+
+
+
+;;;; Menu windows:
+
+
+;; MENU-LIST is ((option option option...) (option option ...)...)
+;;
+(defun gud-display-menu (menu-list)
+ (setq fill-column (min 120 (- (window-width)
+ (min 8 (window-width)))))
+ (while menu-list
+ (mapcar (function (lambda (x) (insert (symbol-name x) " "))) (car menu-list))
+ (fill-paragraph nil)
+ (insert "\n\n")
+ (setq menu-list (cdr menu-list)))
+ (goto-char (point-min))
+ (while (re-search-forward "\\([^ \n]+\\)\\(\n\\| \\)" nil t)
+ (put-text-property (match-beginning 1) (match-end 1)
+ 'mouse-face 'highlight))
+ (goto-char (point-min)))
+
+(defun gud-goto-menu (menu)
+ (setq gud-menu-position menu)
+ (let ((buffer-read-only nil))
+ (delete-region (point-min) (point-max))
+ (gud-display-menu menu)))
+
+(defun gud-menu-pick (event)
+ "Choose an item from a gdb command menu."
+ (interactive "e")
+ (let (choice)
+ (save-excursion
+ (set-buffer (window-buffer (posn-window (event-start event))))
+ (goto-char (posn-point (event-start event)))
+ (let (beg end)
+ (skip-chars-forward "^ \t\n")
+ (setq end (point))
+ (skip-chars-backward "^ \t\n")
+ (setq beg (point))
+ (setq choice (buffer-substring beg end))
+ (message choice)
+ (gud-invoke-menu (intern choice))))))
+
+(defun gud-invoke-menu (symbol)
+ (let ((meaning (assoc symbol gud-menu-rules)))
+ (cond
+ ((and (consp meaning)
+ (consp (car (cdr meaning))))
+ (gud-goto-menu (car (cdr meaning))))
+ (meaning (call-interactively (car (cdr meaning)))))))
+
+
+
+(gdb-set-instance-buffer-rules 'gdb-command-buffer
+ 'gdb-command-buffer-name
+ 'gud-command-mode)
+
+(defvar gud-command-mode-map nil)
+(setq gud-command-mode-map (make-keymap))
+(suppress-keymap gud-command-mode-map)
+(define-key gud-command-mode-map [mouse-2] 'gud-menu-pick)
+
+(defun gud-command-mode ()
+ "Major mode for gud menu.
+
+\\{gud-command-mode-map}" (interactive) (setq major-mode 'gud-command-mode)
+ (setq mode-name "Menu") (setq buffer-read-only t) (use-local-map
+ gud-command-mode-map) (make-variable-buffer-local 'gud-menu-position)
+ (if (not gud-menu-position) (gud-goto-menu gud-running-menu)))
+
+(defun gdb-command-buffer-name (instance)
+ (save-excursion
+ (set-buffer (process-buffer (gdb-instance-process instance)))
+ (concat "*menu of " (gdb-instance-target-string instance) "*")))
+
+(defun gud-display-command-buffer (instance)
+ (interactive (list (gdb-needed-default-instance)))
+ (gud-display-buffer
+ (gdb-get-create-instance-buffer instance
+ 'gdb-command-buffer)
+ 6))
+
+(defun gud-frame-command-buffer (instance)
+ (interactive (list (gdb-needed-default-instance)))
+ (gud-frame-buffer
+ (gdb-get-create-instance-buffer instance
+ 'gdb-command-buffer)))
+
+(defvar gud-selected-menu-titles ())
+(setq gud-selected-menu-titles
+ '(RUNNING STACK DATA BREAKPOINTS FILES))
+
+(setq gud-running-menu
+ (list
+ '(RUNNING stack breakpoints files)
+ '(target run next step continue finish stepi kill help-running)))
+
+(setq gud-stack-menu
+ (list
+ '(running STACK breakpoints files)
+ '(up down frame backtrace return help-stack)))
+
+(setq gud-data-menu
+ (list
+ '(running stack DATA breakpoints files)
+ '(whatis ptype print set display undisplay disassemble help-data)))
+
+(setq gud-breakpoints-menu
+ (list
+ '(running stack BREAKPOINTS files)
+ '(awatch rwatch watch break delete enable disable condition ignore help-breakpoints)))
+
+(setq gud-files-menu
+ (list
+ '(running stack breakpoints FILES)
+ '(file core-file help-files)
+ '(exec-file load symbol-file add-symbol-file sharedlibrary)))
+
+(setq gud-menu-rules
+ (list
+ (list 'running gud-running-menu)
+ (list 'RUNNING gud-running-menu)
+ (list 'stack gud-stack-menu)
+ (list 'STACK gud-stack-menu)
+ (list 'data gud-data-menu)
+ (list 'DATA gud-data-menu)
+ (list 'breakpoints gud-breakpoints-menu)
+ (list 'BREAKPOINTS gud-breakpoints-menu)
+ (list 'files gud-files-menu)
+ (list 'FILES gud-files-menu)
+
+ (list 'target 'gud-target)
+ (list 'kill 'gud-kill)
+ (list 'stepi 'gud-stepi)
+ (list 'step 'gud-step)
+ (list 'next 'gud-next)
+ (list 'finish 'gud-finish)
+ (list 'continue 'gud-cont)
+ (list 'run 'gud-run)
+
+ (list 'backtrace 'gud-backtrace)
+ (list 'frame 'gud-frame)
+ (list 'down 'gud-down)
+ (list 'up 'gud-up)
+ (list 'return 'gud-return)
+
+ (list 'file 'gud-file)
+ (list 'core-file 'gud-core-file)
+ (list 'cd 'gud-cd)
+
+ (list 'exec-file 'gud-exec-file)
+ (list 'load 'gud-load)
+ (list 'symbol-file 'gud-symbol-file)
+ (list 'add-symbol-file 'gud-add-symbol-file)
+ (list 'sharedlibrary 'gud-sharedlibrary)
+ ))
+
+
+
+
+(defun gdb-call-showing-gud (instance command)
+ (gud-display-gud-buffer instance)
+ (comint-input-sender (gdb-instance-process instance) command))
+
+(defvar gud-target-history ())
+
+(defun gud-temp-buffer-show (buf)
+ (let ((ow (selected-window)))
+ (unwind-protect
+ (progn
+ (pop-to-buffer buf)
+
+ ;; This insertion works around a bug in emacs.
+ ;; The bug is that all the empty space after a
+ ;; highlighted word that terminates a buffer
+ ;; gets highlighted. That's really ugly, so
+ ;; make sure a highlighted word can't ever
+ ;; terminate the buffer.
+ (goto-char (point-max))
+ (insert "\n")
+ (goto-char (point-min))
+
+ (if (< (window-height) 10)
+ (enlarge-window (- 10 (window-height)))))
+ (select-window ow))))
+
+(defun gud-target (instance command)
+ (interactive
+ (let* ((instance (gdb-needed-default-instance))
+ (temp-buffer-show-function (function gud-temp-buffer-show))
+ (target-name (completing-read (format "Target type: ")
+ '(("remote")
+ ("core")
+ ("child")
+ ("exec"))
+ nil
+ t
+ nil
+ 'gud-target-history)))
+ (list instance
+ (cond
+ ((equal target-name "child") "run")
+
+ ((equal target-name "core")
+ (concat "target core "
+ (read-file-name "core file: "
+ nil
+ "core"
+ t)))
+
+ ((equal target-name "exec")
+ (concat "target exec "
+ (read-file-name "exec file: "
+ nil
+ "a.out"
+ t)))
+
+ ((equal target-name "remote")
+ (concat "target remote "
+ (read-file-name "serial line for remote: "
+ "/dev/"
+ "ttya"
+ t)))
+
+ (t "echo No such target command!")))))
+
+ (gud-display-gud-buffer instance)
+ (apply comint-input-sender
+ (list (gdb-instance-process instance) command)))
+
+(defun gud-backtrace ()
+ (interactive)
+ (let ((instance (gdb-needed-default-instance)))
+ (gud-display-gud-buffer instance)
+ (apply comint-input-sender
+ (list (gdb-instance-process instance)
+ "backtrace"))))
+
+(defun gud-frame ()
+ (interactive)
+ (let ((instance (gdb-needed-default-instance)))
+ (apply comint-input-sender
+ (list (gdb-instance-process instance)
+ "frame"))))
+
+(defun gud-return (instance command)
+ (interactive
+ (let ((temp-buffer-show-function (function gud-temp-buffer-show)))
+ (list (gdb-needed-default-instance)
+ (concat "return " (read-string "Expression to return: ")))))
+ (gud-display-gud-buffer instance)
+ (apply comint-input-sender
+ (list (gdb-instance-process instance) command)))
+
+
+(defun gud-file (instance command)
+ (interactive
+ (let ((temp-buffer-show-function (function gud-temp-buffer-show)))
+ (list (gdb-needed-default-instance)
+ (concat "file " (read-file-name "Executable to debug: "
+ nil
+ "a.out"
+ t)))))
+ (gud-display-gud-buffer instance)
+ (apply comint-input-sender
+ (list (gdb-instance-process instance) command)))
+
+(defun gud-core-file (instance command)
+ (interactive
+ (let ((temp-buffer-show-function (function gud-temp-buffer-show)))
+ (list (gdb-needed-default-instance)
+ (concat "core " (read-file-name "Core file to debug: "
+ nil
+ "core-file"
+ t)))))
+ (gud-display-gud-buffer instance)
+ (apply comint-input-sender
+ (list (gdb-instance-process instance) command)))
+
+(defun gud-cd (dir)
+ (interactive "FChange GDB's default directory: ")
+ (let ((instance (gdb-needed-default-instance)))
+ (save-excursion
+ (set-buffer (gdb-get-instance-buffer instance 'gud))
+ (cd dir))
+ (gud-display-gud-buffer instance)
+ (apply comint-input-sender
+ (list (gdb-instance-process instance)
+ (concat "cd " dir)))))
+
+
+(defun gud-exec-file (instance command)
+ (interactive
+ (let ((temp-buffer-show-function (function gud-temp-buffer-show)))
+ (list (gdb-needed-default-instance)
+ (concat "exec-file " (read-file-name "Init memory from executable: "
+ nil
+ "a.out"
+ t)))))
+ (gud-display-gud-buffer instance)
+ (apply comint-input-sender
+ (list (gdb-instance-process instance) command)))
+
+(defun gud-load (instance command)
+ (interactive
+ (let ((temp-buffer-show-function (function gud-temp-buffer-show)))
+ (list (gdb-needed-default-instance)
+ (concat "load " (read-file-name "Dynamicly load from file: "
+ nil
+ "a.out"
+ t)))))
+ (gud-display-gud-buffer instance)
+ (apply comint-input-sender
+ (list (gdb-instance-process instance) command)))
+
+(defun gud-symbol-file (instance command)
+ (interactive
+ (let ((temp-buffer-show-function (function gud-temp-buffer-show)))
+ (list (gdb-needed-default-instance)
+ (concat "symbol-file " (read-file-name "Read symbol table from file: "
+ nil
+ "a.out"
+ t)))))
+ (gud-display-gud-buffer instance)
+ (apply comint-input-sender
+ (list (gdb-instance-process instance) command)))
+
+
+(defun gud-add-symbol-file (instance command)
+ (interactive
+ (let ((temp-buffer-show-function (function gud-temp-buffer-show)))
+ (list (gdb-needed-default-instance)
+ (concat "add-symbol-file "
+ (read-file-name "Add symbols from file: "
+ nil
+ "a.out"
+ t)))))
+ (gud-display-gud-buffer instance)
+ (apply comint-input-sender
+ (list (gdb-instance-process instance) command)))
+
+
+(defun gud-sharedlibrary (instance command)
+ (interactive
+ (let ((temp-buffer-show-function (function gud-temp-buffer-show)))
+ (list (gdb-needed-default-instance)
+ (concat "sharedlibrary "
+ (read-string "Load symbols for files matching regexp: ")))))
+ (gud-display-gud-buffer instance)
+ (apply comint-input-sender
+ (list (gdb-instance-process instance) command)))
+
+
+
+
+
+;;;; Window management
+
+
+;;; FIXME: This should only return true for buffers in the current instance
+(defun gud-protected-buffer-p (buffer)
+ "Is BUFFER a buffer which we want to leave displayed?"
+ (save-excursion
+ (set-buffer buffer)
+ (or gdb-buffer-type
+ overlay-arrow-position)))
+
+;;; The way we abuse the dedicated-p flag is pretty gross, but seems
+;;; to do the right thing. Seeing as there is no way for Lisp code to
+;;; get at the use_time field of a window, I'm not sure there exists a
+;;; more elegant solution without writing C code.
+
+(defun gud-display-buffer (buf &optional size)
+ (let ((must-split nil)
+ (answer nil))
+ (unwind-protect
+ (progn
+ (walk-windows
+ '(lambda (win)
+ (if (gud-protected-buffer-p (window-buffer win))
+ (set-window-dedicated-p win t))))
+ (setq answer (get-buffer-window buf))
+ (if (not answer)
+ (let ((window (get-lru-window)))
+ (if window
+ (progn
+ (set-window-buffer window buf)
+ (setq answer window))
+ (setq must-split t)))))
+ (walk-windows
+ '(lambda (win)
+ (if (gud-protected-buffer-p (window-buffer win))
+ (set-window-dedicated-p win nil)))))
+ (if must-split
+ (let* ((largest (get-largest-window))
+ (cur-size (window-height largest))
+ (new-size (and size (< size cur-size) (- cur-size size))))
+ (setq answer (split-window largest new-size))
+ (set-window-buffer answer buf)))
+ answer))
+
+(defun existing-source-window (buffer)
+ (catch 'found
+ (save-excursion
+ (walk-windows
+ (function
+ (lambda (win)
+ (if (and overlay-arrow-position
+ (eq (window-buffer win)
+ (marker-buffer overlay-arrow-position)))
+ (progn
+ (set-window-buffer win buffer)
+ (throw 'found win))))))
+ nil)))
+
+(defun gud-display-source-buffer (buffer)
+ (or (existing-source-window buffer)
+ (gud-display-buffer buffer)))
+
+(defun gud-frame-buffer (buf)
+ (save-excursion
+ (set-buffer buf)
+ (make-frame)))
+
+
+
+;;; Shared keymap initialization:
+
+(defun make-windows-menu (map)
+ (define-key map [menu-bar displays]
+ (cons "GDB-Windows" (make-sparse-keymap "GDB-Windows")))
+ (define-key map [menu-bar displays gdb]
+ '("Gdb" . gud-display-gud-buffer))
+ (define-key map [menu-bar displays registers]
+ '("Registers" . gud-display-registers-buffer))
+ (define-key map [menu-bar displays frames]
+ '("Stack" . gud-display-stack-buffer))
+ (define-key map [menu-bar displays breakpoints]
+ '("Breakpoints" . gud-display-breakpoints-buffer))
+ (define-key map [menu-bar displays commands]
+ '("Commands" . gud-display-command-buffer)))
+
+(defun gud-display-gud-buffer (instance)
+ (interactive (list (gdb-needed-default-instance)))
+ (gud-display-buffer
+ (gdb-get-create-instance-buffer instance 'gud)))
+
+(make-windows-menu gud-breakpoints-mode-map)
+(make-windows-menu gud-frames-mode-map)
+(make-windows-menu gud-registers-mode-map)
+
+
+
+(defun make-frames-menu (map)
+ (define-key map [menu-bar frames]
+ (cons "GDB-Frames" (make-sparse-keymap "GDB-Frames")))
+ (define-key map [menu-bar frames gdb]
+ '("Gdb" . gud-frame-gud-buffer))
+ (define-key map [menu-bar frames registers]
+ '("Registers" . gud-frame-registers-buffer))
+ (define-key map [menu-bar frames frames]
+ '("Stack" . gud-frame-stack-buffer))
+ (define-key map [menu-bar frames breakpoints]
+ '("Breakpoints" . gud-frame-breakpoints-buffer))
+ (define-key map [menu-bar displays commands]
+ '("Commands" . gud-display-command-buffer)))
+
+(defun gud-frame-gud-buffer (instance)
+ (interactive (list (gdb-needed-default-instance)))
+ (gud-frame-buffer
+ (gdb-get-create-instance-buffer instance 'gud)))
+
+(make-frames-menu gud-breakpoints-mode-map)
+(make-frames-menu gud-frames-mode-map)
+(make-frames-menu gud-registers-mode-map)
+
+
+(defun gud-gdb-find-file (f)
+ (find-file-noselect f))
+
+;;;###autoload
+(defun gdb (command-line)
+ "Run gdb on program FILE in buffer *gud-FILE*.
+The directory containing FILE becomes the initial working directory
+and source-file directory for your debugger."
+ (interactive
+ (list (read-from-minibuffer "Run gdb (like this): "
+ (if (consp gud-gdb-history)
+ (car gud-gdb-history)
+ "gdb ")
+ nil nil
+ '(gud-gdb-history . 1))))
+ (gud-overload-functions
+ '((gud-massage-args . gud-gdb-massage-args)
+ (gud-marker-filter . gud-gdb-marker-filter)
+ (gud-find-file . gud-gdb-find-file)
+ ))
+
+ (let* ((words (gud-chop-words command-line))
+ (program (car words))
+ (file-word (let ((w (cdr words)))
+ (while (and w (= ?- (aref (car w) 0)))
+ (setq w (cdr w)))
+ (car w)))
+ (args (delq file-word (cdr words)))
+ (file (expand-file-name file-word))
+ (filepart (file-name-nondirectory file))
+ (buffer-name (concat "*gud-" filepart "*")))
+ (setq gdb-first-time (not (get-buffer-process buffer-name))))
+
+ (gud-common-init command-line)
+
+ (gud-def gud-break "break %f:%l" "\C-b" "Set breakpoint at current line.")
+ (gud-def gud-tbreak "tbreak %f:%l" "\C-t" "Set breakpoint at current line.")
+ (gud-def gud-remove "clear %l" "\C-d" "Remove breakpoint at current line")
+ (gud-def gud-kill "kill" nil "Kill the program.")
+ (gud-def gud-run "run" nil "Run the program.")
+ (gud-def gud-stepi "stepi %p" "\C-i" "Step one instruction with display.")
+ (gud-def gud-step "step %p" "\C-s" "Step one source line with display.")
+ (gud-def gud-next "next %p" "\C-n" "Step one line (skip functions).")
+ (gud-def gud-finish "finish" "\C-f" "Finish executing current function.")
+ (gud-def gud-cont "cont" "\C-r" "Continue with display.")
+ (gud-def gud-up "up %p" "<" "Up N stack frames (numeric arg).")
+ (gud-def gud-down "down %p" ">" "Down N stack frames (numeric arg).")
+ (gud-def gud-print "print %e" "\C-p" "Evaluate C expression at point.")
+
+ (setq comint-prompt-regexp "^(.*gdb[+]?) *")
+ (setq comint-input-sender 'gdb-send)
+ (run-hooks 'gdb-mode-hook)
+ (let ((instance
+ (make-gdb-instance (get-buffer-process (current-buffer)))
+ ))
+ (if gdb-first-time (gdb-clear-inferior-io instance)))
+ )
+
+
+;; ======================================================================
+;; sdb functions
+
+;;; History of argument lists passed to sdb.
+(defvar gud-sdb-history nil)
+
+(defvar gud-sdb-needs-tags (not (file-exists-p "/var"))
+ "If nil, we're on a System V Release 4 and don't need the tags hack.")
+
+(defvar gud-sdb-lastfile nil)
+
+(defun gud-sdb-massage-args (file args)
+ (cons file args))
+
+(defun gud-sdb-marker-filter (string)
+ (cond
+ ;; System V Release 3.2 uses this format
+ ((string-match "\\(^0x\\w* in \\|^\\|\n\\)\\([^:\n]*\\):\\([0-9]*\\):.*\n"
+ string)
+ (setq gud-last-frame
+ (cons
+ (substring string (match-beginning 2) (match-end 2))
+ (string-to-int
+ (substring string (match-beginning 3) (match-end 3))))))
+ ;; System V Release 4.0
+ ((string-match "^\\(BREAKPOINT\\|STEPPED\\) process [0-9]+ function [^ ]+ in \\(.+\\)\n"
+ string)
+ (setq gud-sdb-lastfile
+ (substring string (match-beginning 2) (match-end 2))))
+ ((and gud-sdb-lastfile (string-match "^\\([0-9]+\\):" string))
+ (setq gud-last-frame
+ (cons
+ gud-sdb-lastfile
+ (string-to-int
+ (substring string (match-beginning 1) (match-end 1))))))
+ (t
+ (setq gud-sdb-lastfile nil)))
+ string)
+
+(defun gud-sdb-find-file (f)
+ (if gud-sdb-needs-tags
+ (find-tag-noselect f)
+ (find-file-noselect f)))
+
+;;;###autoload
+(defun sdb (command-line)
+ "Run sdb on program FILE in buffer *gud-FILE*.
+The directory containing FILE becomes the initial working directory
+and source-file directory for your debugger."
+ (interactive
+ (list (read-from-minibuffer "Run sdb (like this): "
+ (if (consp gud-sdb-history)
+ (car gud-sdb-history)
+ "sdb ")
+ nil nil
+ '(gud-sdb-history . 1))))
+ (if (and gud-sdb-needs-tags
+ (not (and (boundp 'tags-file-name) (file-exists-p tags-file-name))))
+ (error "The sdb support requires a valid tags table to work."))
+ (gud-overload-functions '((gud-massage-args . gud-sdb-massage-args)
+ (gud-marker-filter . gud-sdb-marker-filter)
+ (gud-find-file . gud-sdb-find-file)
+ ))
+
+ (gud-common-init command-line)
+
+ (gud-def gud-break "%l b" "\C-b" "Set breakpoint at current line.")
+ (gud-def gud-tbreak "%l c" "\C-t" "Set temporary breakpoint at current line.")
+ (gud-def gud-remove "%l d" "\C-d" "Remove breakpoint at current line")
+ (gud-def gud-step "s %p" "\C-s" "Step one source line with display.")
+ (gud-def gud-stepi "i %p" "\C-i" "Step one instruction with display.")
+ (gud-def gud-next "S %p" "\C-n" "Step one line (skip functions).")
+ (gud-def gud-cont "c" "\C-r" "Continue with display.")
+ (gud-def gud-print "%e/" "\C-p" "Evaluate C expression at point.")
+
+ (setq comint-prompt-regexp "\\(^\\|\n\\)\\*")
+ (run-hooks 'sdb-mode-hook)
+ )
+
+;; ======================================================================
+;; dbx functions
+
+;;; History of argument lists passed to dbx.
+(defvar gud-dbx-history nil)
+
+(defun gud-dbx-massage-args (file args)
+ (cons file args))
+
+(defun gud-dbx-marker-filter (string)
+ (if (or (string-match
+ "stopped in .* at line \\([0-9]*\\) in file \"\\([^\"]*\\)\""
+ string)
+ (string-match
+ "signal .* in .* at line \\([0-9]*\\) in file \"\\([^\"]*\\)\""
+ string))
+ (setq gud-last-frame
+ (cons
+ (substring string (match-beginning 2) (match-end 2))
+ (string-to-int
+ (substring string (match-beginning 1) (match-end 1))))))
+ string)
+
+(defun gud-dbx-find-file (f)
+ (find-file-noselect f))
+
+;;;###autoload
+(defun dbx (command-line)
+ "Run dbx on program FILE in buffer *gud-FILE*.
+The directory containing FILE becomes the initial working directory
+and source-file directory for your debugger."
+ (interactive
+ (list (read-from-minibuffer "Run dbx (like this): "
+ (if (consp gud-dbx-history)
+ (car gud-dbx-history)
+ "dbx ")
+ nil nil
+ '(gud-dbx-history . 1))))
+ (gud-overload-functions '((gud-massage-args . gud-dbx-massage-args)
+ (gud-marker-filter . gud-dbx-marker-filter)
+ (gud-find-file . gud-dbx-find-file)
+ ))
+
+ (gud-common-init command-line)
+
+ (gud-def gud-break "file \"%d%f\"\nstop at %l"
+ "\C-b" "Set breakpoint at current line.")
+;; (gud-def gud-break "stop at \"%f\":%l"
+;; "\C-b" "Set breakpoint at current line.")
+ (gud-def gud-remove "clear %l" "\C-d" "Remove breakpoint at current line")
+ (gud-def gud-step "step %p" "\C-s" "Step one line with display.")
+ (gud-def gud-stepi "stepi %p" "\C-i" "Step one instruction with display.")
+ (gud-def gud-next "next %p" "\C-n" "Step one line (skip functions).")
+ (gud-def gud-cont "cont" "\C-r" "Continue with display.")
+ (gud-def gud-up "up %p" "<" "Up (numeric arg) stack frames.")
+ (gud-def gud-down "down %p" ">" "Down (numeric arg) stack frames.")
+ (gud-def gud-print "print %e" "\C-p" "Evaluate C expression at point.")
+
+ (setq comint-prompt-regexp "^[^)]*dbx) *")
+ (run-hooks 'dbx-mode-hook)
+ )
+
+;; ======================================================================
+;; xdb (HP PARISC debugger) functions
+
+;;; History of argument lists passed to xdb.
+(defvar gud-xdb-history nil)
+
+(defvar gud-xdb-directories nil
+ "*A list of directories that xdb should search for source code.
+If nil, only source files in the program directory
+will be known to xdb.
+
+The file names should be absolute, or relative to the directory
+containing the executable being debugged.")
+
+(defun gud-xdb-massage-args (file args)
+ (nconc (let ((directories gud-xdb-directories)
+ (result nil))
+ (while directories
+ (setq result (cons (car directories) (cons "-d" result)))
+ (setq directories (cdr directories)))
+ (nreverse (cons file result)))
+ args))
+
+(defun gud-xdb-file-name (f)
+ "Transform a relative pathname to a full pathname in xdb mode"
+ (let ((result nil))
+ (if (file-exists-p f)
+ (setq result (expand-file-name f))
+ (let ((directories gud-xdb-directories))
+ (while directories
+ (let ((path (concat (car directories) "/" f)))
+ (if (file-exists-p path)
+ (setq result (expand-file-name path)
+ directories nil)))
+ (setq directories (cdr directories)))))
+ result))
+
+;; xdb does not print the lines all at once, so we have to accumulate them
+(defvar gud-xdb-accumulation "")
+
+(defun gud-xdb-marker-filter (string)
+ (let (result)
+ (if (or (string-match comint-prompt-regexp string)
+ (string-match ".*\012" string))
+ (setq result (concat gud-xdb-accumulation string)
+ gud-xdb-accumulation "")
+ (setq gud-xdb-accumulation (concat gud-xdb-accumulation string)))
+ (if result
+ (if (or (string-match "\\([^\n \t:]+\\): [^:]+: \\([0-9]+\\):" result)
+ (string-match "[^: \t]+:[ \t]+\\([^:]+\\): [^:]+: \\([0-9]+\\):"
+ result))
+ (let ((line (string-to-int
+ (substring result (match-beginning 2) (match-end 2))))
+ (file (gud-xdb-file-name
+ (substring result (match-beginning 1) (match-end 1)))))
+ (if file
+ (setq gud-last-frame (cons file line))))))
+ (or result "")))
+
+(defun gud-xdb-find-file (f)
+ (let ((realf (gud-xdb-file-name f)))
+ (if realf (find-file-noselect realf))))
+
+;;;###autoload
+(defun xdb (command-line)
+ "Run xdb on program FILE in buffer *gud-FILE*.
+The directory containing FILE becomes the initial working directory
+and source-file directory for your debugger.
+
+You can set the variable 'gud-xdb-directories' to a list of program source
+directories if your program contains sources from more than one directory."
+ (interactive
+ (list (read-from-minibuffer "Run xdb (like this): "
+ (if (consp gud-xdb-history)
+ (car gud-xdb-history)
+ "xdb ")
+ nil nil
+ '(gud-xdb-history . 1))))
+ (gud-overload-functions '((gud-massage-args . gud-xdb-massage-args)
+ (gud-marker-filter . gud-xdb-marker-filter)
+ (gud-find-file . gud-xdb-find-file)))
+
+ (gud-common-init command-line)
+
+ (gud-def gud-break "b %f:%l" "\C-b" "Set breakpoint at current line.")
+ (gud-def gud-tbreak "b %f:%l\\t" "\C-t"
+ "Set temporary breakpoint at current line.")
+ (gud-def gud-remove "db" "\C-d" "Remove breakpoint at current line")
+ (gud-def gud-step "s %p" "\C-s" "Step one line with display.")
+ (gud-def gud-next "S %p" "\C-n" "Step one line (skip functions).")
+ (gud-def gud-cont "c" "\C-r" "Continue with display.")
+ (gud-def gud-up "up %p" "<" "Up (numeric arg) stack frames.")
+ (gud-def gud-down "down %p" ">" "Down (numeric arg) stack frames.")
+ (gud-def gud-finish "bu\\t" "\C-f" "Finish executing current function.")
+ (gud-def gud-print "p %e" "\C-p" "Evaluate C expression at point.")
+
+ (setq comint-prompt-regexp "^>")
+ (make-local-variable 'gud-xdb-accumulation)
+ (setq gud-xdb-accumulation "")
+ (run-hooks 'xdb-mode-hook))
+
+;; ======================================================================
+;; perldb functions
+
+;;; History of argument lists passed to perldb.
+(defvar gud-perldb-history nil)
+
+(defun gud-perldb-massage-args (file args)
+ (cons "-d" (cons file (cons "-emacs" args))))
+
+;; There's no guarantee that Emacs will hand the filter the entire
+;; marker at once; it could be broken up across several strings. We
+;; might even receive a big chunk with several markers in it. If we
+;; receive a chunk of text which looks like it might contain the
+;; beginning of a marker, we save it here between calls to the
+;; filter.
+(defvar gud-perldb-marker-acc "")
+
+(defun gud-perldb-marker-filter (string)
+ (save-match-data
+ (setq gud-perldb-marker-acc (concat gud-perldb-marker-acc string))
+ (let ((output ""))
+
+ ;; Process all the complete markers in this chunk.
+ (while (string-match "^\032\032\\([^:\n]*\\):\\([0-9]*\\):.*\n"
+ gud-perldb-marker-acc)
+ (setq
+
+ ;; Extract the frame position from the marker.
+ gud-last-frame
+ (cons (substring gud-perldb-marker-acc (match-beginning 1) (match-end 1))
+ (string-to-int (substring gud-perldb-marker-acc
+ (match-beginning 2)
+ (match-end 2))))
+
+ ;; Append any text before the marker to the output we're going
+ ;; to return - we don't include the marker in this text.
+ output (concat output
+ (substring gud-perldb-marker-acc 0 (match-beginning 0)))
+
+ ;; Set the accumulator to the remaining text.
+ gud-perldb-marker-acc (substring gud-perldb-marker-acc (match-end 0))))
+
+ ;; Does the remaining text look like it might end with the
+ ;; beginning of another marker? If it does, then keep it in
+ ;; gud-perldb-marker-acc until we receive the rest of it. Since we
+ ;; know the full marker regexp above failed, it's pretty simple to
+ ;; test for marker starts.
+ (if (string-match "^\032.*\\'" gud-perldb-marker-acc)
+ (progn
+ ;; Everything before the potential marker start can be output.
+ (setq output (concat output (substring gud-perldb-marker-acc
+ 0 (match-beginning 0))))
+
+ ;; Everything after, we save, to combine with later input.
+ (setq gud-perldb-marker-acc
+ (substring gud-perldb-marker-acc (match-beginning 0))))
+
+ (setq output (concat output gud-perldb-marker-acc)
+ gud-perldb-marker-acc ""))
+
+ output)))
+
+(defun gud-perldb-find-file (f)
+ (find-file-noselect f))
+
+;;;###autoload
+(defun perldb (command-line)
+ "Run perldb on program FILE in buffer *gud-FILE*.
+The directory containing FILE becomes the initial working directory
+and source-file directory for your debugger."
+ (interactive
+ (list (read-from-minibuffer "Run perldb (like this): "
+ (if (consp gud-perldb-history)
+ (car gud-perldb-history)
+ "perl ")
+ nil nil
+ '(gud-perldb-history . 1))))
+ (gud-overload-functions '((gud-massage-args . gud-perldb-massage-args)
+ (gud-marker-filter . gud-perldb-marker-filter)
+ (gud-find-file . gud-perldb-find-file)
+ ))
+
+ (gud-common-init command-line)
+
+ (gud-def gud-break "b %l" "\C-b" "Set breakpoint at current line.")
+ (gud-def gud-remove "d %l" "\C-d" "Remove breakpoint at current line")
+ (gud-def gud-step "s" "\C-s" "Step one source line with display.")
+ (gud-def gud-next "n" "\C-n" "Step one line (skip functions).")
+ (gud-def gud-cont "c" "\C-r" "Continue with display.")
+; (gud-def gud-finish "finish" "\C-f" "Finish executing current function.")
+; (gud-def gud-up "up %p" "<" "Up N stack frames (numeric arg).")
+; (gud-def gud-down "down %p" ">" "Down N stack frames (numeric arg).")
+ (gud-def gud-print "%e" "\C-p" "Evaluate perl expression at point.")
+
+ (setq comint-prompt-regexp "^ DB<[0-9]+> ")
+ (run-hooks 'perldb-mode-hook)
+ )
+
+;;
+;; End of debugger-specific information
+;;
+
+
+;;; When we send a command to the debugger via gud-call, it's annoying
+;;; to see the command and the new prompt inserted into the debugger's
+;;; buffer; we have other ways of knowing the command has completed.
+;;;
+;;; If the buffer looks like this:
+;;; --------------------
+;;; (gdb) set args foo bar
+;;; (gdb) -!-
+;;; --------------------
+;;; (the -!- marks the location of point), and we type `C-x SPC' in a
+;;; source file to set a breakpoint, we want the buffer to end up like
+;;; this:
+;;; --------------------
+;;; (gdb) set args foo bar
+;;; Breakpoint 1 at 0x92: file make-docfile.c, line 49.
+;;; (gdb) -!-
+;;; --------------------
+;;; Essentially, the old prompt is deleted, and the command's output
+;;; and the new prompt take its place.
+;;;
+;;; Not echoing the command is easy enough; you send it directly using
+;;; comint-input-sender, and it never enters the buffer. However,
+;;; getting rid of the old prompt is trickier; you don't want to do it
+;;; when you send the command, since that will result in an annoying
+;;; flicker as the prompt is deleted, redisplay occurs while Emacs
+;;; waits for a response from the debugger, and the new prompt is
+;;; inserted. Instead, we'll wait until we actually get some output
+;;; from the subprocess before we delete the prompt. If the command
+;;; produced no output other than a new prompt, that prompt will most
+;;; likely be in the first chunk of output received, so we will delete
+;;; the prompt and then replace it with an identical one. If the
+;;; command produces output, the prompt is moving anyway, so the
+;;; flicker won't be annoying.
+;;;
+;;; So - when we want to delete the prompt upon receipt of the next
+;;; chunk of debugger output, we position gud-delete-prompt-marker at
+;;; the start of the prompt; the process filter will notice this, and
+;;; delete all text between it and the process output marker. If
+;;; gud-delete-prompt-marker points nowhere, we leave the current
+;;; prompt alone.
+(defvar gud-delete-prompt-marker nil)
+
+
+(defvar gdbish-comint-mode-map (copy-keymap comint-mode-map))
+(define-key gdbish-comint-mode-map "\C-c\M-\C-r" 'gud-display-registers-buffer)
+(define-key gdbish-comint-mode-map "\C-c\M-\C-f" 'gud-display-stack-buffer)
+(define-key gdbish-comint-mode-map "\C-c\M-\C-b" 'gud-display-breakpoints-buffer)
+
+(make-windows-menu gdbish-comint-mode-map)
+(make-frames-menu gdbish-comint-mode-map)
+
+(defun gud-mode ()
+ "Major mode for interacting with an inferior debugger process.
+
+ You start it up with one of the commands M-x gdb, M-x sdb, M-x dbx,
+or M-x xdb. Each entry point finishes by executing a hook; `gdb-mode-hook',
+`sdb-mode-hook', `dbx-mode-hook' or `xdb-mode-hook' respectively.
+
+After startup, the following commands are available in both the GUD
+interaction buffer and any source buffer GUD visits due to a breakpoint stop
+or step operation:
+
+\\[gud-break] sets a breakpoint at the current file and line. In the
+GUD buffer, the current file and line are those of the last breakpoint or
+step. In a source buffer, they are the buffer's file and current line.
+
+\\[gud-remove] removes breakpoints on the current file and line.
+
+\\[gud-refresh] displays in the source window the last line referred to
+in the gud buffer.
+
+\\[gud-step], \\[gud-next], and \\[gud-stepi] do a step-one-line,
+step-one-line (not entering function calls), and step-one-instruction
+and then update the source window with the current file and position.
+\\[gud-cont] continues execution.
+
+\\[gud-print] tries to find the largest C lvalue or function-call expression
+around point, and sends it to the debugger for value display.
+
+The above commands are common to all supported debuggers except xdb which
+does not support stepping instructions.
+
+Under gdb, sdb and xdb, \\[gud-tbreak] behaves exactly like \\[gud-break],
+except that the breakpoint is temporary; that is, it is removed when
+execution stops on it.
+
+Under gdb, dbx, and xdb, \\[gud-up] pops up through an enclosing stack
+frame. \\[gud-down] drops back down through one.
+
+If you are using gdb or xdb, \\[gud-finish] runs execution to the return from
+the current function and stops.
+
+All the keystrokes above are accessible in the GUD buffer
+with the prefix C-c, and in all buffers through the prefix C-x C-a.
+
+All pre-defined functions for which the concept make sense repeat
+themselves the appropriate number of times if you give a prefix
+argument.
+
+You may use the `gud-def' macro in the initialization hook to define other
+commands.
+
+Other commands for interacting with the debugger process are inherited from
+comint mode, which see."
+ (interactive)
+ (comint-mode)
+ (setq major-mode 'gud-mode)
+ (setq mode-name "Debugger")
+ (setq mode-line-process '(": %s"))
+ (use-local-map (copy-keymap gdbish-comint-mode-map))
+ (setq gud-last-frame nil)
+ (make-local-variable 'comint-prompt-regexp)
+ (make-local-variable 'gud-delete-prompt-marker)
+ (setq gud-delete-prompt-marker (make-marker))
+ (run-hooks 'gud-mode-hook)
+)
+
+(defvar gud-comint-buffer nil)
+
+;; Chop STRING into words separated by SPC or TAB and return a list of them.
+(defun gud-chop-words (string)
+ (let ((i 0) (beg 0)
+ (len (length string))
+ (words nil))
+ (while (< i len)
+ (if (memq (aref string i) '(?\t ? ))
+ (progn
+ (setq words (cons (substring string beg i) words)
+ beg (1+ i))
+ (while (and (< beg len) (memq (aref string beg) '(?\t ? )))
+ (setq beg (1+ beg)))
+ (setq i (1+ beg)))
+ (setq i (1+ i))))
+ (if (< beg len)
+ (setq words (cons (substring string beg) words)))
+ (nreverse words)))
+
+(defvar gud-target-name "--unknown--"
+ "The apparent name of the program being debugged in a gud buffer.
+For sure this the root string used in smashing together the gud
+buffer's name, even if that doesn't happen to be the name of a
+program.")
+
+;; Perform initializations common to all debuggers.
+(defun gud-common-init (command-line)
+ (let* ((words (gud-chop-words command-line))
+ (program (car words))
+ (file-word (let ((w (cdr words)))
+ (while (and w (= ?- (aref (car w) 0)))
+ (setq w (cdr w)))
+ (car w)))
+ (args (delq file-word (cdr words)))
+ (file (expand-file-name file-word))
+ (filepart (file-name-nondirectory file))
+ (buffer-name (concat "*gud-" filepart "*")))
+ (switch-to-buffer buffer-name)
+ (setq default-directory (file-name-directory file))
+ (or (bolp) (newline))
+ (insert "Current directory is " default-directory "\n")
+ (let ((old-instance gdb-buffer-instance))
+ (apply 'make-comint (concat "gud-" filepart) program nil
+ (gud-massage-args file args))
+ (gud-mode)
+ (make-variable-buffer-local 'old-gdb-buffer-instance)
+ (setq old-gdb-buffer-instance old-instance))
+ (make-variable-buffer-local 'gud-target-name)
+ (setq gud-target-name filepart))
+ (set-process-filter (get-buffer-process (current-buffer)) 'gud-filter)
+ (set-process-sentinel (get-buffer-process (current-buffer)) 'gud-sentinel)
+ (gud-set-buffer)
+ )
+
+(defun gud-set-buffer ()
+ (cond ((eq major-mode 'gud-mode)
+ (setq gud-comint-buffer (current-buffer)))))
+
+;; These functions are responsible for inserting output from your debugger
+;; into the buffer. The hard work is done by the method that is
+;; the value of gud-marker-filter.
+
+(defun gud-filter (proc string)
+ ;; Here's where the actual buffer insertion is done
+ (let ((inhibit-quit t))
+ (save-excursion
+ (set-buffer (process-buffer proc))
+ (let (moving output-after-point)
+ (save-excursion
+ (goto-char (process-mark proc))
+ ;; If we have been so requested, delete the debugger prompt.
+ (if (marker-buffer gud-delete-prompt-marker)
+ (progn
+ (delete-region (point) gud-delete-prompt-marker)
+ (set-marker gud-delete-prompt-marker nil)))
+ (insert-before-markers (gud-marker-filter string))
+ (setq moving (= (point) (process-mark proc)))
+ (setq output-after-point (< (point) (process-mark proc)))
+ ;; Check for a filename-and-line number.
+ ;; Don't display the specified file
+ ;; unless (1) point is at or after the position where output appears
+ ;; and (2) this buffer is on the screen.
+ (if (and gud-last-frame
+ (not output-after-point)
+ (get-buffer-window (current-buffer)))
+ (gud-display-frame)))
+ (if moving (goto-char (process-mark proc)))))))
+
+(defun gud-proc-died (proc)
+ ;; Stop displaying an arrow in a source file.
+ (setq overlay-arrow-position nil)
+
+ ;; Kill the dummy process, so that C-x C-c won't worry about it.
+ (save-excursion
+ (set-buffer (process-buffer proc))
+ (kill-process
+ (get-buffer-process
+ (gdb-get-instance-buffer gdb-buffer-instance 'gdb-inferior-io))))
+ )
+
+(defun gud-sentinel (proc msg)
+ (cond ((null (buffer-name (process-buffer proc)))
+ ;; buffer killed
+ (gud-proc-died proc)
+ (set-process-buffer proc nil))
+ ((memq (process-status proc) '(signal exit))
+ (gud-proc-died proc)
+
+ ;; Fix the mode line.
+ (setq mode-line-process
+ (concat ": "
+ (symbol-name (process-status proc))))
+ (let* ((obuf (current-buffer)))
+ ;; save-excursion isn't the right thing if
+ ;; process-buffer is current-buffer
+ (unwind-protect
+ (progn
+ ;; Write something in *compilation* and hack its mode line,
+ (set-buffer (process-buffer proc))
+ ;; Force mode line redisplay soon
+ (set-buffer-modified-p (buffer-modified-p))
+ (if (eobp)
+ (insert ?\n mode-name " " msg)
+ (save-excursion
+ (goto-char (point-max))
+ (insert ?\n mode-name " " msg)))
+ ;; If buffer and mode line will show that the process
+ ;; is dead, we can delete it now. Otherwise it
+ ;; will stay around until M-x list-processes.
+ (delete-process proc))
+ ;; Restore old buffer, but don't restore old point
+ ;; if obuf is the gud buffer.
+ (set-buffer obuf))))))
+
+(defun gud-display-frame ()
+ "Find and obey the last filename-and-line marker from the debugger.
+Obeying it means displaying in another window the specified file and line."
+ (interactive)
+ (if gud-last-frame
+ (progn
+; (gud-set-buffer)
+ (gud-display-line (car gud-last-frame) (cdr gud-last-frame))
+ (setq gud-last-last-frame gud-last-frame
+ gud-last-frame nil))))
+
+;; Make sure the file named TRUE-FILE is in a buffer that appears on the screen
+;; and that its line LINE is visible.
+;; Put the overlay-arrow on the line LINE in that buffer.
+;; Most of the trickiness in here comes from wanting to preserve the current
+;; region-restriction if that's possible. We use an explicit display-buffer
+;; to get around the fact that this is called inside a save-excursion.
+
+(defun gud-display-line (true-file line)
+ (let* ((buffer (gud-find-file true-file))
+ (window (gud-display-source-buffer buffer))
+ (pos))
+ (if (not window)
+ (error "foo bar baz"))
+;;; (if (equal buffer (current-buffer))
+;;; nil
+;;; (setq buffer-read-only nil))
+ (save-excursion
+;;; (setq buffer-read-only t)
+ (set-buffer buffer)
+ (save-restriction
+ (widen)
+ (goto-line line)
+ (setq pos (point))
+ (setq overlay-arrow-string "=>")
+ (or overlay-arrow-position
+ (setq overlay-arrow-position (make-marker)))
+ (set-marker overlay-arrow-position (point) (current-buffer)))
+ (cond ((or (< pos (point-min)) (> pos (point-max)))
+ (widen)
+ (goto-char pos))))
+ (set-window-point window overlay-arrow-position)))
+
+;;; The gud-call function must do the right thing whether its invoking
+;;; keystroke is from the GUD buffer itself (via major-mode binding)
+;;; or a C buffer. In the former case, we want to supply data from
+;;; gud-last-frame. Here's how we do it:
+
+(defun gud-format-command (str arg)
+ (let ((insource (not (eq (current-buffer) gud-comint-buffer))))
+ (if (string-match "\\(.*\\)%f\\(.*\\)" str)
+ (setq str (concat
+ (substring str (match-beginning 1) (match-end 1))
+ (file-name-nondirectory (if insource
+ (buffer-file-name)
+ (car gud-last-frame)))
+ (substring str (match-beginning 2) (match-end 2)))))
+ (if (string-match "\\(.*\\)%d\\(.*\\)" str)
+ (setq str (concat
+ (substring str (match-beginning 1) (match-end 1))
+ (file-name-directory (if insource
+ (buffer-file-name)
+ (car gud-last-frame)))
+ (substring str (match-beginning 2) (match-end 2)))))
+ (if (string-match "\\(.*\\)%l\\(.*\\)" str)
+ (setq str (concat
+ (substring str (match-beginning 1) (match-end 1))
+ (if insource
+ (save-excursion
+ (beginning-of-line)
+ (save-restriction (widen)
+ (1+ (count-lines 1 (point)))))
+ (cdr gud-last-frame))
+ (substring str (match-beginning 2) (match-end 2)))))
+ (if (string-match "\\(.*\\)%e\\(.*\\)" str)
+ (setq str (concat
+ (substring str (match-beginning 1) (match-end 1))
+ (find-c-expr)
+ (substring str (match-beginning 2) (match-end 2)))))
+ (if (string-match "\\(.*\\)%a\\(.*\\)" str)
+ (setq str (concat
+ (substring str (match-beginning 1) (match-end 1))
+ (gud-read-address)
+ (substring str (match-beginning 2) (match-end 2)))))
+ (if (string-match "\\(.*\\)%p\\(.*\\)" str)
+ (setq str (concat
+ (substring str (match-beginning 1) (match-end 1))
+ (if arg (int-to-string arg) "")
+ (substring str (match-beginning 2) (match-end 2)))))
+ )
+ str
+ )
+
+(defun gud-read-address ()
+ "Return a string containing the core-address found in the buffer at point."
+ (save-excursion
+ (let ((pt (point)) found begin)
+ (setq found (if (search-backward "0x" (- pt 7) t) (point)))
+ (cond
+ (found (forward-char 2)
+ (buffer-substring found
+ (progn (re-search-forward "[^0-9a-f]")
+ (forward-char -1)
+ (point))))
+ (t (setq begin (progn (re-search-backward "[^0-9]")
+ (forward-char 1)
+ (point)))
+ (forward-char 1)
+ (re-search-forward "[^0-9]")
+ (forward-char -1)
+ (buffer-substring begin (point)))))))
+
+(defun gud-call (fmt &optional arg)
+ (let ((msg (gud-format-command fmt arg)))
+ (message "Command: %s" msg)
+ (sit-for 0)
+ (gud-basic-call msg)))
+
+(defun gud-basic-call (command)
+ "Invoke the debugger COMMAND displaying source in other window."
+ (interactive)
+ (gud-set-buffer)
+ (let ((proc (get-buffer-process gud-comint-buffer)))
+
+ ;; Arrange for the current prompt to get deleted.
+ (save-excursion
+ (set-buffer gud-comint-buffer)
+ (goto-char (process-mark proc))
+ (beginning-of-line)
+ (if (looking-at comint-prompt-regexp)
+ (set-marker gud-delete-prompt-marker (point)))
+ (apply comint-input-sender (list proc command)))))
+
+(defun gud-refresh (&optional arg)
+ "Fix up a possibly garbled display, and redraw the arrow."
+ (interactive "P")
+ (recenter arg)
+ (or gud-last-frame (setq gud-last-frame gud-last-last-frame))
+ (gud-display-frame))
+
+;;; Code for parsing expressions out of C code. The single entry point is
+;;; find-c-expr, which tries to return an lvalue expression from around point.
+;;;
+;;; The rest of this file is a hacked version of gdbsrc.el by
+;;; Debby Ayers <ayers@asc.slb.com>,
+;;; Rich Schaefer <schaefer@asc.slb.com> Schlumberger, Austin, Tx.
+
+(defun find-c-expr ()
+ "Returns the C expr that surrounds point."
+ (interactive)
+ (save-excursion
+ (let ((p) (expr) (test-expr))
+ (setq p (point))
+ (setq expr (expr-cur))
+ (setq test-expr (expr-prev))
+ (while (expr-compound test-expr expr)
+ (setq expr (cons (car test-expr) (cdr expr)))
+ (goto-char (car expr))
+ (setq test-expr (expr-prev)))
+ (goto-char p)
+ (setq test-expr (expr-next))
+ (while (expr-compound expr test-expr)
+ (setq expr (cons (car expr) (cdr test-expr)))
+ (setq test-expr (expr-next))
+ )
+ (buffer-substring (car expr) (cdr expr)))))
+
+(defun expr-cur ()
+ "Returns the expr that point is in; point is set to beginning of expr.
+The expr is represented as a cons cell, where the car specifies the point in
+the current buffer that marks the beginning of the expr and the cdr specifies
+the character after the end of the expr."
+ (let ((p (point)) (begin) (end))
+ (expr-backward-sexp)
+ (setq begin (point))
+ (expr-forward-sexp)
+ (setq end (point))
+ (if (>= p end)
+ (progn
+ (setq begin p)
+ (goto-char p)
+ (expr-forward-sexp)
+ (setq end (point))
+ )
+ )
+ (goto-char begin)
+ (cons begin end)))
+
+(defun expr-backward-sexp ()
+ "Version of `backward-sexp' that catches errors."
+ (condition-case nil
+ (backward-sexp)
+ (error t)))
+
+(defun expr-forward-sexp ()
+ "Version of `forward-sexp' that catches errors."
+ (condition-case nil
+ (forward-sexp)
+ (error t)))
+
+(defun expr-prev ()
+ "Returns the previous expr, point is set to beginning of that expr.
+The expr is represented as a cons cell, where the car specifies the point in
+the current buffer that marks the beginning of the expr and the cdr specifies
+the character after the end of the expr"
+ (let ((begin) (end))
+ (expr-backward-sexp)
+ (setq begin (point))
+ (expr-forward-sexp)
+ (setq end (point))
+ (goto-char begin)
+ (cons begin end)))
+
+(defun expr-next ()
+ "Returns the following expr, point is set to beginning of that expr.
+The expr is represented as a cons cell, where the car specifies the point in
+the current buffer that marks the beginning of the expr and the cdr specifies
+the character after the end of the expr."
+ (let ((begin) (end))
+ (expr-forward-sexp)
+ (expr-forward-sexp)
+ (setq end (point))
+ (expr-backward-sexp)
+ (setq begin (point))
+ (cons begin end)))
+
+(defun expr-compound-sep (span-start span-end)
+ "Returns '.' for '->' & '.', returns ' ' for white space,
+returns '?' for other punctuation."
+ (let ((result ? )
+ (syntax))
+ (while (< span-start span-end)
+ (setq syntax (char-syntax (char-after span-start)))
+ (cond
+ ((= syntax ? ) t)
+ ((= syntax ?.) (setq syntax (char-after span-start))
+ (cond
+ ((= syntax ?.) (setq result ?.))
+ ((and (= syntax ?-) (= (char-after (+ span-start 1)) ?>))
+ (setq result ?.)
+ (setq span-start (+ span-start 1)))
+ (t (setq span-start span-end)
+ (setq result ??)))))
+ (setq span-start (+ span-start 1)))
+ result))
+
+(defun expr-compound (first second)
+ "Non-nil if concatenating FIRST and SECOND makes a single C token.
+The two exprs are represented as a cons cells, where the car
+specifies the point in the current buffer that marks the beginning of the
+expr and the cdr specifies the character after the end of the expr.
+Link exprs of the form:
+ Expr -> Expr
+ Expr . Expr
+ Expr (Expr)
+ Expr [Expr]
+ (Expr) Expr
+ [Expr] Expr"
+ (let ((span-start (cdr first))
+ (span-end (car second))
+ (syntax))
+ (setq syntax (expr-compound-sep span-start span-end))
+ (cond
+ ((= (car first) (car second)) nil)
+ ((= (cdr first) (cdr second)) nil)
+ ((= syntax ?.) t)
+ ((= syntax ? )
+ (setq span-start (char-after (- span-start 1)))
+ (setq span-end (char-after span-end))
+ (cond
+ ((= span-start ?) ) t )
+ ((= span-start ?] ) t )
+ ((= span-end ?( ) t )
+ ((= span-end ?[ ) t )
+ (t nil))
+ )
+ (t nil))))
+
+(provide 'gud)
+
+;;; gud.el ends here
diff --git a/gdb/gdbarch.c b/gdb/gdbarch.c
new file mode 100644
index 00000000000..154fa8f9982
--- /dev/null
+++ b/gdb/gdbarch.c
@@ -0,0 +1,360 @@
+/* Semi-dynamic architecture support for GDB, the GNU debugger.
+ Copyright 1998, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "bfd.h"
+#include "gdbcmd.h"
+
+
+
+/* Non-zero if we want to trace architecture code. */
+
+#ifndef GDBARCH_DEBUG
+#define GDBARCH_DEBUG 0
+#endif
+int gdbarch_debug = GDBARCH_DEBUG;
+
+
+/* Functions to manipulate the endianness of the target. */
+
+#ifdef TARGET_BYTE_ORDER_SELECTABLE
+/* compat - Catch old targets that expect a selectable byte-order to
+ default to BIG_ENDIAN */
+#ifndef TARGET_BYTE_ORDER_DEFAULT
+#define TARGET_BYTE_ORDER_DEFAULT BIG_ENDIAN
+#endif
+#endif
+#ifndef TARGET_BYTE_ORDER_DEFAULT
+/* compat - Catch old non byte-order selectable targets that do not
+ define TARGET_BYTE_ORDER_DEFAULT and instead expect
+ TARGET_BYTE_ORDER to be used as the default. For targets that
+ defined neither TARGET_BYTE_ORDER nor TARGET_BYTE_ORDER_DEFAULT the
+ below will get a strange compiler warning. */
+#define TARGET_BYTE_ORDER_DEFAULT TARGET_BYTE_ORDER
+#endif
+int target_byte_order = TARGET_BYTE_ORDER_DEFAULT;
+int target_byte_order_auto = 1;
+
+/* Chain containing the \"set endian\" commands. */
+static struct cmd_list_element *endianlist = NULL;
+
+/* Called by ``show endian''. */
+static void show_endian PARAMS ((char *, int));
+static void
+show_endian (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ char *msg =
+ (TARGET_BYTE_ORDER_AUTO
+ ? "The target endianness is set automatically (currently %s endian)\n"
+ : "The target is assumed to be %s endian\n");
+ printf_unfiltered (msg, (TARGET_BYTE_ORDER == BIG_ENDIAN ? "big" : "little"));
+}
+
+/* Called if the user enters ``set endian'' without an argument. */
+static void set_endian PARAMS ((char *, int));
+static void
+set_endian (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ printf_unfiltered ("\"set endian\" must be followed by \"auto\", \"big\" or \"little\".\n");
+ show_endian (args, from_tty);
+}
+
+/* Called by ``set endian big''. */
+static void set_endian_big PARAMS ((char *, int));
+static void
+set_endian_big (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ if (TARGET_BYTE_ORDER_SELECTABLE_P)
+ {
+ target_byte_order = BIG_ENDIAN;
+ target_byte_order_auto = 0;
+ }
+ else
+ {
+ printf_unfiltered ("Byte order is not selectable.");
+ show_endian (args, from_tty);
+ }
+}
+
+/* Called by ``set endian little''. */
+static void set_endian_little PARAMS ((char *, int));
+static void
+set_endian_little (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ if (TARGET_BYTE_ORDER_SELECTABLE_P)
+ {
+ target_byte_order = LITTLE_ENDIAN;
+ target_byte_order_auto = 0;
+ }
+ else
+ {
+ printf_unfiltered ("Byte order is not selectable.");
+ show_endian (args, from_tty);
+ }
+}
+
+/* Called by ``set endian auto''. */
+static void set_endian_auto PARAMS ((char *, int));
+static void
+set_endian_auto (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ if (TARGET_BYTE_ORDER_SELECTABLE_P)
+ {
+ target_byte_order_auto = 1;
+ }
+ else
+ {
+ printf_unfiltered ("Byte order is not selectable.");
+ show_endian (args, from_tty);
+ }
+}
+
+/* Set the endianness from a BFD. */
+static void set_endian_from_file PARAMS ((bfd *));
+static void
+set_endian_from_file (abfd)
+ bfd *abfd;
+{
+ if (TARGET_BYTE_ORDER_SELECTABLE_P)
+ {
+ int want;
+
+ if (bfd_big_endian (abfd))
+ want = BIG_ENDIAN;
+ else
+ want = LITTLE_ENDIAN;
+ if (TARGET_BYTE_ORDER_AUTO)
+ target_byte_order = want;
+ else if (TARGET_BYTE_ORDER != want)
+ warning ("%s endian file does not match %s endian target.",
+ want == BIG_ENDIAN ? "big" : "little",
+ TARGET_BYTE_ORDER == BIG_ENDIAN ? "big" : "little");
+ }
+ else
+ {
+ if (bfd_big_endian (abfd)
+ ? TARGET_BYTE_ORDER != BIG_ENDIAN
+ : TARGET_BYTE_ORDER == BIG_ENDIAN)
+ warning ("%s endian file does not match %s endian target.",
+ bfd_big_endian (abfd) ? "big" : "little",
+ TARGET_BYTE_ORDER == BIG_ENDIAN ? "big" : "little");
+ }
+}
+
+
+
+/* Functions to manipulate the architecture of the target */
+
+int target_architecture_auto = 1;
+extern const struct bfd_arch_info bfd_default_arch_struct;
+const struct bfd_arch_info *target_architecture = &bfd_default_arch_struct;
+int (*target_architecture_hook) PARAMS ((const struct bfd_arch_info *ap));
+
+/* Do the real work of changing the current architecture */
+static void
+set_arch (arch)
+ const struct bfd_arch_info *arch;
+{
+ /* FIXME: Is it compatible with gdb? */
+ /* Check with the target on the setting */
+ if (target_architecture_hook != NULL
+ && !target_architecture_hook (arch))
+ printf_unfiltered ("Target does not support `%s' architecture.\n",
+ arch->printable_name);
+ else
+ {
+ target_architecture_auto = 0;
+ target_architecture = arch;
+ }
+}
+
+/* Called if the user enters ``show architecture'' without an argument. */
+static void show_architecture PARAMS ((char *, int));
+static void
+show_architecture (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ const char *arch;
+ arch = TARGET_ARCHITECTURE->printable_name;
+ if (target_architecture_auto)
+ printf_filtered ("The target architecture is set automatically (currently %s)\n", arch);
+ else
+ printf_filtered ("The target architecture is assumed to be %s\n", arch);
+}
+
+/* Called if the user enters ``set architecture'' with or without an
+ argument. */
+static void set_architecture PARAMS ((char *, int));
+static void
+set_architecture (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ if (args == NULL)
+ {
+ printf_unfiltered ("\"set architecture\" must be followed by \"auto\" or an architecture name.\n");
+ }
+ else if (strcmp (args, "auto") == 0)
+ {
+ target_architecture_auto = 1;
+ }
+ else
+ {
+ const struct bfd_arch_info *arch = bfd_scan_arch (args);
+ if (arch != NULL)
+ set_arch (arch);
+ else
+ printf_unfiltered ("Architecture `%s' not reconized.\n", args);
+ }
+}
+
+/* Called if the user enters ``info architecture'' without an argument. */
+static void info_architecture PARAMS ((char *, int));
+static void
+info_architecture (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ enum bfd_architecture a;
+ printf_filtered ("Available architectures are:\n");
+ for (a = bfd_arch_obscure + 1; a < bfd_arch_last; a++)
+ {
+ const struct bfd_arch_info *ap = bfd_lookup_arch (a, 0);
+ if (ap != NULL)
+ {
+ do
+ {
+ printf_filtered (" %s", ap->printable_name);
+ ap = ap->next;
+ }
+ while (ap != NULL);
+ printf_filtered ("\n");
+ }
+ }
+}
+
+/* Set the architecture from arch/machine */
+void
+set_architecture_from_arch_mach (arch, mach)
+ enum bfd_architecture arch;
+ unsigned long mach;
+{
+ const struct bfd_arch_info *wanted = bfd_lookup_arch (arch, mach);
+ if (wanted != NULL)
+ set_arch (wanted);
+ else
+ fatal ("hardwired architecture/machine not reconized");
+}
+
+/* Set the architecture from a BFD */
+static void set_architecture_from_file PARAMS ((bfd *));
+static void
+set_architecture_from_file (abfd)
+ bfd *abfd;
+{
+ const struct bfd_arch_info *wanted = bfd_get_arch_info (abfd);
+ if (target_architecture_auto)
+ {
+ if (target_architecture_hook != NULL
+ && !target_architecture_hook (wanted))
+ warning ("Target may not support %s architecture",
+ wanted->printable_name);
+ target_architecture = wanted;
+ }
+ else if (wanted != target_architecture)
+ {
+ warning ("%s architecture file may be incompatible with %s target.",
+ wanted->printable_name,
+ target_architecture->printable_name);
+ }
+}
+
+
+
+/* Disassembler */
+
+/* Pointer to the target-dependent disassembly function. */
+int (*tm_print_insn) PARAMS ((bfd_vma, disassemble_info *));
+disassemble_info tm_print_insn_info;
+
+
+
+/* Set the dynamic target-system-dependant parameters (architecture,
+ byte-order) using information found in the BFD */
+
+void
+set_gdbarch_from_file (abfd)
+ bfd *abfd;
+{
+ set_architecture_from_file (abfd);
+ set_endian_from_file (abfd);
+}
+
+
+extern void _initialize_gdbarch PARAMS ((void));
+void
+_initialize_gdbarch ()
+{
+ add_prefix_cmd ("endian", class_support, set_endian,
+ "Set endianness of target.",
+ &endianlist, "set endian ", 0, &setlist);
+ add_cmd ("big", class_support, set_endian_big,
+ "Set target as being big endian.", &endianlist);
+ add_cmd ("little", class_support, set_endian_little,
+ "Set target as being little endian.", &endianlist);
+ add_cmd ("auto", class_support, set_endian_auto,
+ "Select target endianness automatically.", &endianlist);
+ add_cmd ("endian", class_support, show_endian,
+ "Show endianness of target.", &showlist);
+
+ add_cmd ("architecture", class_support, set_architecture,
+ "Set architecture of target.", &setlist);
+ add_alias_cmd ("processor", "architecture", class_support, 1, &setlist);
+ add_cmd ("architecture", class_support, show_architecture,
+ "Show architecture of target.", &showlist);
+ add_cmd ("architecture", class_support, info_architecture,
+ "List supported target architectures", &infolist);
+
+ INIT_DISASSEMBLE_INFO_NO_ARCH (tm_print_insn_info, gdb_stdout, (fprintf_ftype)fprintf_filtered);
+ tm_print_insn_info.flavour = bfd_target_unknown_flavour;
+ tm_print_insn_info.read_memory_func = dis_asm_read_memory;
+ tm_print_insn_info.memory_error_func = dis_asm_memory_error;
+ tm_print_insn_info.print_address_func = dis_asm_print_address;
+
+#ifdef MAINTENANCE_CMDS
+ add_show_from_set (add_set_cmd ("archdebug",
+ class_maintenance,
+ var_zinteger,
+ (char *)&gdbarch_debug,
+ "Set architecture debugging.\n\
+When non-zero, architecture debugging is enabled.", &setlist),
+ &showlist);
+#endif
+}
diff --git a/gdb/gdbarch.h b/gdb/gdbarch.h
new file mode 100644
index 00000000000..098db4c2860
--- /dev/null
+++ b/gdb/gdbarch.h
@@ -0,0 +1,118 @@
+/* Architecture commands for GDB, the GNU debugger.
+ Copyright 1998, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef GDBARCH_H
+#define GDBARCH_H
+
+
+/* The target-system-dependant byte order is dynamic */
+
+/* TARGET_BYTE_ORDER_SELECTABLE_P determines if the target endianness
+ is selectable at runtime. The user can use the `set endian'
+ command to change it. TARGET_BYTE_ORDER_AUTO is nonzero when
+ target_byte_order should be auto-detected (from the program image
+ say). */
+
+#ifndef TARGET_BYTE_ORDER_SELECTABLE_P
+/* compat - Catch old targets that define TARGET_BYTE_ORDER_SLECTABLE
+ when they should have defined TARGET_BYTE_ORDER_SELECTABLE_P 1 */
+#ifdef TARGET_BYTE_ORDER_SELECTABLE
+#define TARGET_BYTE_ORDER_SELECTABLE_P 1
+#else
+#define TARGET_BYTE_ORDER_SELECTABLE_P 0
+#endif
+#endif
+
+extern int target_byte_order;
+#ifdef TARGET_BYTE_ORDER_SELECTABLE
+/* compat - Catch old targets that define TARGET_BYTE_ORDER_SELECTABLE
+ and expect defs.h to re-define TARGET_BYTE_ORDER. */
+#undef TARGET_BYTE_ORDER
+#endif
+#ifndef TARGET_BYTE_ORDER
+#define TARGET_BYTE_ORDER (target_byte_order + 0)
+#endif
+
+extern int target_byte_order_auto;
+#ifndef TARGET_BYTE_ORDER_AUTO
+#define TARGET_BYTE_ORDER_AUTO (target_byte_order_auto + 0)
+#endif
+
+
+
+/* The target-system-dependant BFD architecture is dynamic */
+
+extern int target_architecture_auto;
+#ifndef TARGET_ARCHITECTURE_AUTO
+#define TARGET_ARCHITECTURE_AUTO (target_architecture_auto + 0)
+#endif
+
+extern const struct bfd_arch_info *target_architecture;
+#ifndef TARGET_ARCHITECTURE
+#define TARGET_ARCHITECTURE (target_architecture + 0)
+#endif
+
+/* Notify the target dependant backend of a change to the selected
+ architecture. A zero return status indicates that the target did
+ not like the change. */
+
+extern int (*target_architecture_hook) PARAMS ((const struct bfd_arch_info *));
+
+
+
+/* The target-system-dependant disassembler is semi-dynamic */
+
+#include "dis-asm.h" /* Get defs for disassemble_info */
+
+extern int dis_asm_read_memory PARAMS ((bfd_vma memaddr, bfd_byte *myaddr,
+ int len, disassemble_info *info));
+
+extern void dis_asm_memory_error PARAMS ((int status, bfd_vma memaddr,
+ disassemble_info *info));
+
+extern void dis_asm_print_address PARAMS ((bfd_vma addr,
+ disassemble_info *info));
+
+extern int (*tm_print_insn) PARAMS ((bfd_vma, disassemble_info*));
+extern disassemble_info tm_print_insn_info;
+#ifndef TARGET_PRINT_INSN
+#define TARGET_PRINT_INSN(vma, info) (*tm_print_insn) (vma, info)
+#endif
+#ifndef TARGET_PRINT_INSN_INFO
+#define TARGET_PRINT_INSN_INFO (&tm_print_insn_info)
+#endif
+
+
+
+/* Set the dynamic target-system-dependant parameters (architecture,
+ byte-order, ...) using information found in the BFD */
+
+extern void set_gdbarch_from_file PARAMS ((bfd *));
+
+
+/* Explicitly set the dynamic target-system-dependant parameters based
+ on bfd_architecture and machine. */
+
+extern void set_architecture_from_arch_mach PARAMS ((enum bfd_architecture, unsigned long));
+
+
+/* gdbarch trace variable */
+extern int gdbarch_debug;
+
+#endif
diff --git a/gdb/gdbcmd.h b/gdb/gdbcmd.h
new file mode 100644
index 00000000000..65b3b7a941c
--- /dev/null
+++ b/gdb/gdbcmd.h
@@ -0,0 +1,114 @@
+/* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 toggle subcommands. */
+
+extern struct cmd_list_element *togglelist;
+
+/* Chain containing all defined stop subcommands. */
+
+extern struct cmd_list_element *stoplist;
+
+/* 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));
+
+enum command_control_type
+execute_control_command PARAMS ((struct command_line *));
+
+void print_command_line PARAMS ((struct command_line *, unsigned int));
+
+extern char **noop_completer PARAMS ((char *, char *));
+
+extern char **filename_completer PARAMS ((char *, char *));
+
+#endif /* !defined (GDBCMD_H) */
diff --git a/gdb/gdbcore.h b/gdb/gdbcore.h
new file mode 100644
index 00000000000..6501e3098b9
--- /dev/null
+++ b/gdb/gdbcore.h
@@ -0,0 +1,169 @@
+/* Machine independent variables that describe the core file under GDB.
+ Copyright 1986, 1987, 1989, 1990, 1992, 1995 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Interface routines for core, executable, etc. */
+
+#if !defined (GDBCORE_H)
+#define GDBCORE_H 1
+
+#include "bfd.h"
+
+/* 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));
+
+extern void read_memory_section PARAMS ((CORE_ADDR memaddr, char *myaddr,
+ int len, asection *bfd_section));
+
+/* 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 ULONGEST read_memory_unsigned_integer PARAMS ((CORE_ADDR memaddr, int len));
+
+/* Read a null-terminated string from the debuggee's memory, given address,
+ * a buffer into which to place the string, and the maximum available space */
+extern void read_memory_string PARAMS ((CORE_ADDR, char *, int));
+
+/* This takes a char *, not void *. This is probably right, because
+ passing in an int * or whatever is wrong with respect to
+ byteswapping, alignment, different sizes for host vs. target types,
+ etc. */
+
+extern void write_memory PARAMS ((CORE_ADDR memaddr, char *myaddr, int len));
+
+extern void generic_search PARAMS ((int len, char *data, char *mask,
+ CORE_ADDR startaddr, int increment,
+ CORE_ADDR lorange, CORE_ADDR hirange,
+ CORE_ADDR *addr_found, char *data_found));
+
+/* Hook for `exec_file_command' command to call. */
+
+extern void (*exec_file_display_hook) PARAMS ((char *filename));
+
+/* Hook for "file_command", which is more useful than above
+ (because it is invoked AFTER symbols are read, not before) */
+
+extern void (*file_changed_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_attach PARAMS ((char *filename, int from_tty));
+
+extern void exec_file_command PARAMS ((char *filename, int from_tty));
+
+extern void validate_files PARAMS ((void));
+
+extern CORE_ADDR register_addr PARAMS ((int regno, CORE_ADDR blockend));
+
+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;
+
+/* The current default bfd target. */
+
+extern char *gnutarget;
+
+extern void set_gnutarget PARAMS ((char *));
+
+/* Structure to keep track of core register reading functions for
+ various core file types. */
+
+struct core_fns {
+
+ /* BFD flavour that we handle. Note that bfd_target_unknown_flavour matches
+ anything, and if there is no better match, this function will be called
+ as the default. */
+
+ enum bfd_flavour core_flavour;
+
+ /* 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 (*core_read_registers) PARAMS ((char *core_reg_sect, unsigned core_reg_size,
+ int which, CORE_ADDR reg_addr));
+
+ /* Finds the next struct core_fns. They are allocated and initialized
+ in whatever module implements the functions pointed to; an
+ initializer calls add_core_fns to add them to the global chain. */
+
+ struct core_fns *next;
+
+};
+
+extern void add_core_fns PARAMS ((struct core_fns *cf));
+
+#endif /* !defined (GDBCORE_H) */
diff --git a/gdb/gdbinit.in b/gdb/gdbinit.in
new file mode 100644
index 00000000000..af97d2cae3d
--- /dev/null
+++ b/gdb/gdbinit.in
@@ -0,0 +1,18 @@
+echo Setting up the environment for debugging gdb.\n
+
+set complaints 1
+
+b fatal
+
+b info_command
+commands
+ silent
+ return
+end
+
+dir @srcdir@
+dir .
+dir @srcdir@/../mmalloc
+dir @srcdir@/../libiberty
+dir @srcdir@/../bfd
+set prompt (top-gdb)
diff --git a/gdb/gdbserver/Makefile.in b/gdb/gdbserver/Makefile.in
new file mode 100644
index 00000000000..b016e134c5f
--- /dev/null
+++ b/gdb/gdbserver/Makefile.in
@@ -0,0 +1,241 @@
+#Copyright 1989, 90, 91, 92, 93, 94, 95, 96, 1997
+#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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+prefix = /usr/local
+
+program_transform_name =
+exec_prefix = $(prefix)
+bindir = $(exec_prefix)/bin
+libdir = $(exec_prefix)/lib
+tooldir = $(libdir)/$(target_alias)
+
+datadir = $(prefix)/share
+mandir = $(prefix)/man
+man1dir = $(mandir)/man1
+man2dir = $(mandir)/man2
+man3dir = $(mandir)/man3
+man4dir = $(mandir)/man4
+man5dir = $(mandir)/man5
+man6dir = $(mandir)/man6
+man7dir = $(mandir)/man7
+man8dir = $(mandir)/man8
+man9dir = $(mandir)/man9
+infodir = $(prefix)/info
+includedir = $(prefix)/include
+
+SHELL = /bin/sh
+
+INSTALL = `cd $(srcdir)/../..;pwd`/install-sh -c
+INSTALL_PROGRAM = $(INSTALL)
+INSTALL_DATA = $(INSTALL)
+
+AR = ar
+AR_FLAGS = qv
+RANLIB = ranlib
+
+# 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
+# will be incorrectly compiled. The "fixincludes" script in the gcc
+# distribution will fix your include files up.
+#CC=cc
+#CC=gcc -traditional
+GCC=gcc
+
+# Directory containing source files. Don't clean up the spacing,
+# this exact string is matched for by the "configure" script.
+srcdir = .
+
+# It is also possible that you will need to add -I/usr/include/sys to the
+# CFLAGS section if your system doesn't have fcntl.h in /usr/include (which
+# is where it should be according to Posix).
+
+# 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}
+
+# Where is the "include" directory? Traditionally ../include or ./include
+INCLUDE_DIR = ${srcdir}/../../include
+INCLUDE_DEP = $$(INCLUDE_DIR)
+
+# Where are the BFD library?
+BFD_DIR = ../../bfd
+BFD = $(BFD_DIR)/libbfd.a
+BFD_SRC = $(srcdir)/$(BFD_DIR)
+BFD_CFLAGS = -I$(BFD_DIR) -I$(BFD_SRC)
+
+# Where is the source dir for the READLINE library? Traditionally in .. or .
+# (For the binary library built from it, we use ${READLINE_DIR}${subdir}.)
+READLINE_DIR = ${srcdir}/../readline
+READLINE_DEP = $$(READLINE_DIR)
+
+# All the includes used for CFLAGS and for lint.
+# -I. for config files.
+# -I${srcdir} possibly for regex.h also.
+# -I${srcdir}/config for more generic config files.
+INCLUDE_CFLAGS = -I. -I${srcdir} -I${srcdir}/.. -I${srcdir}/../config -I$(INCLUDE_DIR)
+
+# M{H,T}_CFLAGS, if defined, has host- and target-dependent CFLAGS
+# from the config/ directory.
+GLOBAL_CFLAGS = ${MT_CFLAGS} ${MH_CFLAGS}
+#PROFILE_CFLAGS = -pg
+
+# CFLAGS is specifically reserved for setting from the command line
+# when running make. I.E. "make CFLAGS=-Wmissing-prototypes".
+CFLAGS = -g
+# INTERNAL_CFLAGS is the aggregate of all other *CFLAGS macros.
+INTERNAL_CFLAGS = ${CFLAGS} ${GLOBAL_CFLAGS} ${PROFILE_CFLAGS} \
+ ${BFD_CFLAGS} ${INCLUDE_CFLAGS}
+
+# LDFLAGS is specifically reserved for setting from the command line
+# when running make.
+
+# Perhaps should come from parent Makefile
+VERSION = gdbserver-4.12.3
+DIST=gdb
+
+LINT=/usr/5bin/lint
+LINTFLAGS= $(BFD_CFLAGS)
+
+# Host and target-dependent makefile fragments come in here.
+####
+# End of host and target-dependent makefile fragments
+
+# All source files that go into linking GDB remote server.
+
+SFILES = $(srcdir)/low-lynx.c $(srcdir)/low-sparc.c $(srcdir)/low-sun3.c \
+ $(srcdir)/low-hppabsd.c \
+ $(srcdir)/utils.c $(srcdir)/server.c $(srcdir)/remote-utils.c
+
+DEPFILES = $(GDBSERVER_DEPFILES)
+
+SOURCES = $(SFILES) $(ALLDEPFILES)
+TAGFILES = $(SOURCES) ${HFILES} ${ALLPARAM} ${POSSLIBS}
+
+OBS = utils.o $(GDBSERVER_DEPFILES) server.o remote-utils.o
+
+# Prevent Sun make from putting in the machine type. Setting
+# TARGET_ARCH to nothing works for SunOS 3, 4.0, but not for 4.1.
+.c.o:
+ ${CC} -c ${INTERNAL_CFLAGS} $<
+
+all: gdbserver gdbreplay
+
+# Traditionally "install" depends on "all". But it may be useful
+# not to; for example, if the user has made some trivial change to a
+# source file and doesn't care about rebuilding or just wants to save the
+# time it takes for make to check that all is up to date.
+# install-only is intended to address that need.
+install: all install-only
+install-only:
+ n=`echo gdbserver | sed '$(program_transform_name)'`; \
+ if [ x$$n = x ]; then n=gdbserver; else true; fi; \
+ $(INSTALL_PROGRAM) gdbserver $(bindir)/$$n; \
+ $(INSTALL_DATA) $(srcdir)/gdbserver.1 $(man1dir)/$$n.1
+
+uninstall: force
+ n=`echo gdbserver | sed '$(program_transform_name)'`; \
+ if [ x$$n = x ]; then n=gdbserver; else true; fi; \
+ rm -f $(bindir)/$$n $(man1dir)/$$n.1
+
+installcheck:
+check:
+info dvi:
+install-info:
+clean-info:
+
+gdbserver: $(OBS) ${ADD_DEPS} ${CDEPS}
+ rm -f gdbserver
+ ${CC-LD} $(GLOBAL_CFLAGS) $(LDFLAGS) -o gdbserver $(OBS) \
+ $(GDBSERVER_LIBS) $(XM_CLIBS)
+
+gdbreplay: gdbreplay.o
+ rm -f gdbreplay
+ ${CC-LD} $(GLOBAL_CFLAGS) $(LDFLAGS) -o gdbreplay gdbreplay.o \
+ $(XM_CLIBS)
+
+config.status:
+ @echo "You must configure gdbserver. Look at the README file for details."
+ @false
+
+# Put the proper machine-specific files first, so M-. on a machine
+# specific routine gets the one for the correct machine.
+# The xyzzy stuff below deals with empty DEPFILES
+TAGS: ${TAGFILES}
+ etags `find ${srcdir}/../config -name $(TM_FILE) -print` \
+ `find ${srcdir}/../config -name ${XM_FILE} -print` \
+ `find ${srcdir}/../config -name ${NAT_FILE} -print` \
+ `for i in yzzy ${DEPFILES}; do \
+ if [ x$$i != xyzzy ]; then \
+ echo ${srcdir}/$$i | sed -e 's/\.o$$/\.c/' ; \
+ fi; \
+ done` \
+ ${TAGFILES}
+tags: TAGS
+
+clean:
+ rm -f *.o ${ADD_FILES} *~
+ rm -f gdbserver core make.log
+
+distclean: clean
+ rm -f nm.h tm.h xm.h config.status
+ rm -f Makefile
+
+maintainer-clean realclean: clean
+ rm -f nm.h tm.h xm.h config.status
+ rm -f Makefile
+
+STAGESTUFF=${OBS} ${TSOBS} ${NTSOBS} ${ADD_FILES} init.c init.o version.c gdb
+
+Makefile: $(srcdir)/Makefile.in $(host_makefile_frag) $(target_makefile_frag)
+ $(SHELL) ./config.status
+
+force:
+
+version.c: Makefile
+ echo 'char *version = "$(VERSION)";' >version.c
+
+# GNU Make has an annoying habit of putting *all* the Makefile variables
+# into the environment, unless you include this target as a circumvention.
+# Rumor is that this will be fixed (and this target can be removed)
+# in GNU Make 4.0.
+.NOEXPORT:
+
+# GNU Make 3.63 has a different problem: it keeps tacking command line
+# overrides onto the definition of $(MAKE). This variable setting
+# will remove them.
+MAKEOVERRIDES=
+
+## This is ugly, but I don't want GNU make to put these variables in
+## the environment. Older makes will see this as a set of targets
+## with no dependencies and no actions.
+unexport CHILLFLAGS CHILL_LIB CHILL_FOR_TARGET :
+
+server.o : ${srcdir}/server.c ${srcdir}/server.h
+remote-utils.o : ${srcdir}/remote-utils.c ${srcdir}/server.h
+low-linux.o : ${srcdir}/low-linux.c ${srcdir}/server.h
+low-lynx.o : ${srcdir}/low-lynx.c ${srcdir}/server.h
+low-sim.o : ${srcdir}/low-sim.c ${srcdir}/server.h
+low-sparc.o : $(srcdir)/low-sparc.c $(srcdir)/server.h
+low-sun3.o : $(srcdir)/low-sun3.c $(srcdir)/server.h
+low-hppabsd.o : $(srcdir)/low-hppabsd.c $(srcdir)/server.h
+utils.o : ${srcdir}/utils.c ${srcdir}/server.h
+
+# This is the end of "Makefile.in".
diff --git a/gdb/gdbserver/README b/gdb/gdbserver/README
new file mode 100644
index 00000000000..2281bf686c1
--- /dev/null
+++ b/gdb/gdbserver/README
@@ -0,0 +1,127 @@
+ README for GDBserver & GDBreplay
+ by Stu Grossman and Fred Fish
+
+Introduction:
+
+This is GDBserver, a remote server for Un*x-like systems. It can be used to
+control the execution of a program on a target system from a GDB on a different
+host. GDB and GDBserver communicate using the standard remote serial protocol
+implemented in remote.c, and various *-stub.c files. They communicate via
+either a serial line or a TCP connection.
+
+Usage (server (target) side):
+
+First, you need to have a copy of the program you want to debug put onto
+the target system. The program can be stripped to save space if needed, as
+GDBserver doesn't care about symbols. All symbol handling is taken care of by
+the GDB running on the host system.
+
+To use the server, you log on to the target system, and run the `gdbserver'
+program. You must tell it (a) how to communicate with GDB, (b) the name of
+your program, and (c) its arguments. The general syntax is:
+
+ target> gdbserver COMM PROGRAM [ARGS ...]
+
+For example, using a serial port, you might say:
+
+ target> gdbserver /dev/com1 emacs foo.txt
+
+This tells gdbserver to debug emacs with an argument of foo.txt, and to
+communicate with GDB via /dev/com1. Gdbserver now waits patiently for the
+host GDB to communicate with it.
+
+To use a TCP connection, you could say:
+
+ target> gdbserver host:2345 emacs foo.txt
+
+This says pretty much the same thing as the last example, except that we are
+going to communicate with the host GDB via TCP. The `host:2345' argument means
+that we are expecting to see a TCP connection from `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 existing TCP
+ports on the target system. This same port number must be used in the host
+GDBs `target remote' command, which will be described shortly. Note that if
+you chose a port number that conflicts with another service, gdbserver will
+print an error message and exit.
+
+Usage (host side):
+
+You need an unstripped copy of the target program on your host system, since
+GDB needs to examine it's symbol tables and such. Start up GDB as you normally
+would, with the target program as the first argument. (You may need to use the
+--baud option if the serial line is running at anything except 9600 baud.)
+Ie: `gdb TARGET-PROG', or `gdb --baud BAUD TARGET-PROG'. After that, the only
+new command you need to know about is `target remote'. It's argument is either
+a device name (usually a serial device, like `/dev/ttyb'), or a HOST:PORT
+descriptor. 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', where
+you previously started up gdbserver with the same port number. Note that for
+TCP connections, you must start up gdbserver prior to using the `target remote'
+command, otherwise you may get an error that looks something like
+`Connection refused'.
+
+Building:
+
+Configuring gdbserver you should specify the same machine for host and
+target (which are the machine that gdbserver is going to run on. This
+is not the same as the machine that gdb is going to run on; building
+gdbserver automatically as part of building a whole tree of tools does
+not currently work if cross-compilation is involved (we don't get the
+right CC in the Makefile, to start with)).
+
+gdbserver should work on sparc-sun-sunos4* or Lynx. The following
+instructions pertain to Lynx. To build the server for Lynx, make a
+new copy of the distribution onto a disk that is NFS shared with the
+Lynx system. Lets say that's in a directory called xyzzy. Then,
+follow these steps under the host system:
+
+ 1) cd xyzzy/gdb/gdbserver
+ 2) ../../configure i386-none-lynx
+
+When that completes, do the following on the Lynx system:
+
+ 3) cd xyzzy/gdb/gdbserver
+ 4) make CC=gcc
+
+It should build with only a minor complaint about NULL being redefined. That's
+a LynxOS problem, and can be ignored.
+
+It's also possible that you may have a cross-compiler to Lynx. In that case,
+you can skip the stuff about NFS. You would replace steps 3 & 4 with:
+
+ make CC=lynx-target-compiler...
+
+Using GDBreplay:
+
+A special hacked down version of gdbserver can be used to replay remote
+debug log files created by gdb. Before using the gdb "target" command to
+initiate a remote debug session, use "set remotelogfile <filename>" to tell
+gdb that you want to make a recording of the serial or tcp session. Note
+that when replaying the session, gdb communicates with gdbreplay via tcp,
+regardless of whether the original session was via a serial link or tcp.
+
+Once you are done with the remote debug session, start gdbreplay and
+tell it the name of the log file and the host and port number that gdb
+should connect to (typically the same as the host running gdb):
+
+ $ gdbreplay logfile host:port
+
+Then start gdb (preferably in a different screen or window) and use the
+"target" command to connect to gdbreplay:
+
+ (gdb) target remote host:port
+
+Repeat the same sequence of user commands to gdb that you gave in the
+original debug session. Gdb should not be able to tell that it is talking
+to gdbreplay rather than a real target, all other things being equal. Note
+that gdbreplay echos the command lines to stderr, as well as the contents of
+the packets it sends and receives. The last command echoed by gdbreplay is
+the next command that needs to be typed to gdb to continue the session in
+sync with the original session.
diff --git a/gdb/gdbserver/configure.in b/gdb/gdbserver/configure.in
new file mode 100644
index 00000000000..1bbb73c489d
--- /dev/null
+++ b/gdb/gdbserver/configure.in
@@ -0,0 +1,100 @@
+srcname="Remote GDB server"
+srctrigger=server.c
+gdb_serial_driver=../ser-unix.c
+
+# per-host:
+
+. ${srcdir}/../configure.host
+
+echo "gdbserver/configure.in: host is $host, target is $target"
+
+if [ ! -f ${srcdir}/../config/${gdb_host_cpu}/${gdb_host}.mh ]; then
+ echo '***' "GDB remote does not support host ${host}" 1>&2
+ exit 1
+fi
+
+# We really shouldn't depend on there being a space after XM_FILE= ...
+hostfile=`awk '$1 == "XM_FILE=" { print $2 }' <${srcdir}/../config/${gdb_host_cpu}/${gdb_host}.mh`
+
+# per-target:
+
+. ${srcdir}/../configure.tgt
+
+echo "gdbserver/configure.in: host_cpu is $host_cpu, target_cpu is $target_cpu"
+
+if [ ! -f ${srcdir}/../config/${gdb_target_cpu}/${gdb_target}.mt ]; then
+ echo '***' "GDB remote does not support target ${target}" 1>&2
+ exit 1
+fi
+
+if [ -z "${removing}" ] ; then
+ cat ${srcdir}/../config/${gdb_host_cpu}/${gdb_host}.mh ${srcdir}/../config/${gdb_target_cpu}/${gdb_target}.mt | awk '$1 == "#msg" {
+ print substr($0,6)}'
+fi
+
+# We really shouldn't depend on there being a space after TM_FILE= ...
+targetfile=`awk '$1 == "TM_FILE=" { print $2 }' <${srcdir}/../config/${gdb_target_cpu}/${gdb_target}.mt`
+
+if [ "${target}" = "${host}" ] ; then
+ nativefile=`awk '$1 == "NAT_FILE=" { print $2 }' <${srcdir}/../config/${gdb_host_cpu}/${gdb_host}.mh`
+fi
+
+host_makefile_frag=../config/${gdb_host_cpu}/${gdb_host}.mh
+target_makefile_frag=../config/${gdb_target_cpu}/${gdb_target}.mt
+
+# If hostfile (XM_FILE) and/or targetfile (TM_FILE) and/or nativefile
+# (NAT_FILE) is not set in the ?config/* file, we don't make the
+# corresponding links. But we have to remove the xm.h files and tm.h
+# files anyway, e.g. when switching from "configure host" to
+# "configure none".
+
+files=
+links=
+rm -f xm.h
+rm -f ser-hardwire.c
+if [ "${hostfile}" != "" ]; then
+ if [ -f ${srcdir}/../config/${hostfile} ]; then
+ files="${files} ../config/${hostfile}"
+ else
+ files="${files} ../config/${gdb_host_cpu}/${hostfile}"
+ fi
+ links="${links} xm.h"
+
+# files="${files} ${gdb_serial_driver}"
+# links="${links} ser-hardwire.c"
+fi
+rm -f tm.h
+if [ "${targetfile}" != "" ]; then
+ if [ -f ${srcdir}/../config/${targetfile} ]; then
+ files="${files} ../config/${targetfile}"
+ else
+ files="${files} ../config/${gdb_target_cpu}/${targetfile}"
+ fi
+ links="${links} tm.h"
+fi
+rm -f nm.h
+if [ "${nativefile}" != "" ]; then
+ if [ -f ${srcdir}/../config/${nativefile} ]; then
+ files="${files} ../config/${nativefile}"
+ else
+ files="${files} ../config/${gdb_host_cpu}/${nativefile}"
+ fi
+ links="${links} nm.h"
+# temporary scaffolding until all hosts have the host/target/native
+# split in place.
+else
+ files="${files} ../config/nm-empty.h"
+ links="${links} nm.h"
+fi
+
+if [ ${target_cpu} = "sparclite" ]; then
+ configdirs="${configdirs} sparclite"
+fi
+
+# post-target:
+
+if [ "${nativefile}" = "" ] ; then
+ sed -e '/^NATDEPFILES= /s//# NATDEPFILES= /' \
+ < Makefile > Makefile.tem
+ mv -f Makefile.tem Makefile
+fi
diff --git a/gdb/gdbserver/gdbreplay.c b/gdb/gdbserver/gdbreplay.c
new file mode 100644
index 00000000000..ebe06bad8f2
--- /dev/null
+++ b/gdb/gdbserver/gdbreplay.c
@@ -0,0 +1,318 @@
+/* Replay a remote debug session logfile for GDB.
+ Copyright (C) 1996 Free Software Foundation, Inc.
+ Written by Fred Fish (fnf@cygnus.com) from pieces of gdbserver.
+
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include <stdio.h>
+#include <sys/file.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <netdb.h>
+#include <netinet/tcp.h>
+#include <signal.h>
+#include <ctype.h>
+#include <fcntl.h>
+
+/* Sort of a hack... */
+#define EOL (EOF - 1)
+
+static int remote_desc;
+
+/* 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;
+
+ err = (errno < sys_nerr) ? sys_errlist[errno] : "unknown error";
+ combined = (char *) alloca (strlen (err) + strlen (string) + 3);
+ strcpy (combined, string);
+ strcat (combined, ": ");
+ strcat (combined, err);
+ fprintf (stderr, "\n%s.\n", combined);
+ fflush (stderr);
+ exit (1);
+}
+
+static void
+sync_error (fp, desc, expect, got)
+ FILE *fp;
+ char *desc;
+ int expect;
+ int got;
+{
+ fprintf (stderr, "\n%s\n", desc);
+ fprintf (stderr, "At logfile offset %ld, expected '0x%x' got '0x%x'\n",
+ ftell (fp), expect, got);
+ fflush (stderr);
+ exit (1);
+}
+
+void
+remote_close()
+{
+ close (remote_desc);
+}
+
+/* Open a connection to a remote debugger.
+ NAME is the filename used for communication. */
+
+void
+remote_open (name)
+ char *name;
+{
+ extern char *strchr ();
+
+ if (!strchr (name, ':'))
+ {
+ fprintf (stderr, "%s: Must specify tcp connection as host:addr\n", name);
+ fflush (stderr);
+ exit (1);
+ }
+ else
+ {
+ char *port_str;
+ int port;
+ struct sockaddr_in sockaddr;
+ int tmp;
+ struct protoent *protoent;
+ int tmp_desc;
+
+ port_str = strchr (name, ':');
+
+ port = atoi (port_str + 1);
+
+ tmp_desc = socket (PF_INET, SOCK_STREAM, 0);
+ if (tmp_desc < 0)
+ perror_with_name ("Can't open socket");
+
+ /* Allow rapid reuse of this port. */
+ tmp = 1;
+ setsockopt (tmp_desc, SOL_SOCKET, SO_REUSEADDR, (char *)&tmp,
+ sizeof(tmp));
+
+ sockaddr.sin_family = PF_INET;
+ sockaddr.sin_port = htons(port);
+ sockaddr.sin_addr.s_addr = INADDR_ANY;
+
+ if (bind (tmp_desc, (struct sockaddr *)&sockaddr, sizeof (sockaddr))
+ || listen (tmp_desc, 1))
+ perror_with_name ("Can't bind address");
+
+ tmp = sizeof (sockaddr);
+ remote_desc = accept (tmp_desc, (struct sockaddr *)&sockaddr, &tmp);
+ if (remote_desc == -1)
+ perror_with_name ("Accept failed");
+
+ protoent = getprotobyname ("tcp");
+ if (!protoent)
+ perror_with_name ("getprotobyname");
+
+ /* Enable TCP keep alive process. */
+ tmp = 1;
+ setsockopt (tmp_desc, SOL_SOCKET, SO_KEEPALIVE, (char *)&tmp, sizeof(tmp));
+
+ /* Tell TCP not to delay small packets. This greatly speeds up
+ interactive response. */
+ tmp = 1;
+ setsockopt (remote_desc, protoent->p_proto, TCP_NODELAY,
+ (char *)&tmp, sizeof(tmp));
+
+ close (tmp_desc); /* No longer need this */
+
+ signal (SIGPIPE, SIG_IGN); /* If we don't do this, then gdbreplay simply
+ exits when the remote side dies. */
+ }
+
+ fcntl (remote_desc, F_SETFL, FASYNC);
+
+ fprintf (stderr, "Replay logfile using %s\n", name);
+ fflush (stderr);
+}
+
+static int tohex (ch)
+ int ch;
+{
+ if (ch >= '0' && ch <= '9')
+ {
+ return (ch - '0');
+ }
+ if (ch >= 'A' && ch <= 'F')
+ {
+ return (ch - 'A' + 10);
+ }
+ if (ch >= 'a' && ch <= 'f')
+ {
+ return (ch - 'a' + 10);
+ }
+ fprintf (stderr, "\nInvalid hex digit '%c'\n", ch);
+ fflush (stderr);
+ exit (1);
+}
+
+static int
+logchar (fp)
+ FILE *fp;
+{
+ int ch;
+ int ch2;
+
+ ch = fgetc (fp);
+ fputc (ch, stdout);
+ fflush (stdout);
+ switch (ch)
+ {
+ case '\n':
+ ch = EOL;
+ break;
+ case '\\':
+ ch = fgetc (fp);
+ fputc (ch, stdout);
+ fflush (stdout);
+ switch (ch)
+ {
+ case '\\': break;
+ case 'b': ch = '\b'; break;
+ case 'f': ch = '\f'; break;
+ case 'n': ch = '\n'; break;
+ case 'r': ch = '\r'; break;
+ case 't': ch = '\t'; break;
+ case 'v': ch = '\v'; break;
+ case 'x':
+ ch2 = fgetc (fp);
+ fputc (ch2, stdout);
+ fflush (stdout);
+ ch = tohex (ch2) << 4;
+ ch2 = fgetc (fp);
+ fputc (ch2, stdout);
+ fflush (stdout);
+ ch |= tohex (ch2);
+ break;
+ default:
+ /* Treat any other char as just itself */
+ break;
+ }
+ default:
+ break;
+ }
+ return (ch);
+}
+
+/* Accept input from gdb and match with chars from fp (after skipping one
+ blank) up until a \n is read from fp (which is not matched) */
+
+void
+expect (fp)
+ FILE *fp;
+{
+ int fromlog;
+ unsigned char fromgdb;
+
+ if ((fromlog = logchar (fp)) != ' ')
+ {
+ sync_error (fp, "Sync error during gdb read of leading blank", ' ',
+ fromlog);
+ }
+ do
+ {
+ fromlog = logchar (fp);
+ if (fromlog == EOL)
+ {
+ break;
+ }
+ read (remote_desc, &fromgdb, 1);
+ } while (fromlog == fromgdb);
+ if (fromlog != EOL)
+ {
+ sync_error (fp, "Sync error during read of gdb packet", fromlog,
+ fromgdb);
+ }
+}
+
+/* Play data back to gdb from fp (after skipping leading blank) up until a
+ \n is read from fp (which is discarded and not sent to gdb). */
+
+void
+play (fp)
+ FILE *fp;
+{
+ int fromlog;
+ char ch;
+
+ if ((fromlog = logchar (fp)) != ' ')
+ {
+ sync_error (fp, "Sync error skipping blank during write to gdb", ' ',
+ fromlog);
+ }
+ while ((fromlog = logchar (fp)) != EOL)
+ {
+ ch = fromlog;
+ write (remote_desc, &ch, 1);
+ }
+}
+
+int
+main (argc, argv)
+ int argc;
+ char *argv[];
+{
+ FILE *fp;
+ int ch;
+
+ if (argc < 3)
+ {
+ fprintf (stderr, "Usage: gdbreplay <logfile> <host:port>\n");
+ fflush (stderr);
+ exit (1);
+ }
+ fp = fopen (argv[1], "r");
+ if (fp == NULL)
+ {
+ perror_with_name (argv[1]);
+ }
+ remote_open (argv[2]);
+ while ((ch = logchar (fp)) != EOF)
+ {
+ switch (ch)
+ {
+ case 'w':
+ /* data sent from gdb to gdbreplay, accept and match it */
+ expect (fp);
+ break;
+ case 'r':
+ /* data sent from gdbreplay to gdb, play it */
+ play (fp);
+ break;
+ case 'c':
+ /* Command executed by gdb */
+ while ((ch = logchar (fp)) != EOL);
+ break;
+ }
+ }
+ remote_close ();
+ exit (0);
+}
+
diff --git a/gdb/gdbserver/gdbserver.1 b/gdb/gdbserver/gdbserver.1
new file mode 100644
index 00000000000..9d3fdcd8011
--- /dev/null
+++ b/gdb/gdbserver/gdbserver.1
@@ -0,0 +1,103 @@
+.\" Copyright (c) 1993 Free Software Foundation
+.\" See section COPYING for conditions for redistribution
+.TH gdbserver 1 "2 November 1993" "Cygnus Support" "GNU Development Tools"
+.SH NAME
+gdbserver \- Remote Server for the GNU Debugger
+.SH SYNOPSIS
+.na
+.TP
+.B gdbserver
+.RB tty
+.RB prog
+.RB "[\|" args... "\|]"
+.ad b
+.SH DESCRIPTION
+GDBSERVER is a program that allows you to run GDB on a different machine
+than the one which is running the program being debugged.
+
+Usage (server (target) side):
+
+First, you need to have a copy of the program you want to debug put onto
+the target system. The program can be stripped to save space if needed, as
+GDBserver doesn't care about symbols. All symbol handling is taken care of by
+the GDB running on the host system.
+
+To use the server, you log on to the target system, and run the `gdbserver'
+program. You must tell it (a) how to communicate with GDB, (b) the name of
+your program, and (c) its arguments. The general syntax is:
+
+ target> gdbserver COMM PROGRAM [ARGS ...]
+
+For example, using a serial port, you might say:
+
+ target> gdbserver /dev/com1 emacs foo.txt
+
+This tells gdbserver to debug emacs with an argument of foo.txt, and to
+communicate with GDB via /dev/com1. Gdbserver now waits patiently for the
+host GDB to communicate with it.
+
+To use a TCP connection, you could say:
+
+ target> gdbserver host:2345 emacs foo.txt
+
+This says pretty much the same thing as the last example, except that we are
+going to communicate with the host GDB via TCP. The `host:2345' argument means
+that we are expecting to see a TCP connection from `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 existing TCP
+ports on the target system. This same port number must be used in the host
+GDBs `target remote' command, which will be described shortly. Note that if
+you chose a port number that conflicts with another service, gdbserver will
+print an error message and exit.
+
+Usage (host side):
+
+You need an unstripped copy of the target program on your host system, since
+GDB needs to examine it's symbol tables and such. Start up GDB as you normally
+would, with the target program as the first argument. (You may need to use the
+--baud option if the serial line is running at anything except 9600 baud.)
+Ie: `gdb TARGET-PROG', or `gdb --baud BAUD TARGET-PROG'. After that, the only
+new command you need to know about is `target remote'. It's argument is either
+a device name (usually a serial device, like `/dev/ttyb'), or a HOST:PORT
+descriptor. 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', where
+you previously started up gdbserver with the same port number. Note that for
+TCP connections, you must start up gdbserver prior to using the `target remote'
+command, otherwise you may get an error that looks something like
+`Connection refused'.
+.SH OPTIONS
+You have to supply the name of the program to debug
+and the tty to communicate on; the remote GDB will do everything else.
+Any remaining arguments will be passed to the program verbatim.
+.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) 1993 Free Software Foundation, Inc.
+.PP
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+.PP
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided that the
+entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+.PP
+Permission is granted to copy and distribute translations of this
+manual into another language, under the above conditions for modified
+versions, except that this permission notice may be included in
+translations approved by the Free Software Foundation instead of in
+the original English.
diff --git a/gdb/gdbserver/low-hppabsd.c b/gdb/gdbserver/low-hppabsd.c
new file mode 100644
index 00000000000..c784d0c61ac
--- /dev/null
+++ b/gdb/gdbserver/low-hppabsd.c
@@ -0,0 +1,379 @@
+/* Low level interface to ptrace, for the remote server for GDB.
+ Copyright (C) 1995 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include <sys/wait.h>
+#include "frame.h"
+#include "inferior.h"
+
+#include <stdio.h>
+#include <sys/param.h>
+#include <sys/dir.h>
+#include <sys/user.h>
+#include <signal.h>
+#include <sys/ioctl.h>
+#include <sgtty.h>
+#include <fcntl.h>
+
+/***************Begin MY defs*********************/
+int quit_flag = 0;
+char registers[REGISTER_BYTES];
+
+/* Index within `registers' of the first byte of the space for
+ register N. */
+
+
+char buf2[MAX_REGISTER_RAW_SIZE];
+/***************End MY defs*********************/
+
+#include <sys/ptrace.h>
+#include <machine/reg.h>
+
+extern char **environ;
+extern int errno;
+extern int inferior_pid;
+void quit (), perror_with_name ();
+int query ();
+
+/* Start an inferior process and returns its pid.
+ ALLARGS is a vector of program-name and args.
+ ENV is the environment vector to pass. */
+
+int
+create_inferior (program, allargs)
+ char *program;
+ char **allargs;
+{
+ int pid;
+
+ pid = fork ();
+ if (pid < 0)
+ perror_with_name ("fork");
+
+ if (pid == 0)
+ {
+ ptrace (PT_TRACE_ME, 0, 0, 0, 0);
+
+ execv (program, allargs);
+
+ fprintf (stderr, "Cannot exec %s: %s.\n", program,
+ errno < sys_nerr ? sys_errlist[errno] : "unknown error");
+ fflush (stderr);
+ _exit (0177);
+ }
+
+ return pid;
+}
+
+/* Kill the inferior process. Make us have no inferior. */
+
+void
+kill_inferior ()
+{
+ if (inferior_pid == 0)
+ return;
+ ptrace (8, inferior_pid, 0, 0, 0);
+ wait (0);
+ /*************inferior_died ();****VK**************/
+}
+
+/* Return nonzero if the given thread is still alive. */
+int
+mythread_alive (pid)
+ int pid;
+{
+ return 1;
+}
+
+/* Wait for process, returns status */
+
+unsigned char
+mywait (status)
+ char *status;
+{
+ int pid;
+ union wait w;
+
+ pid = wait (&w);
+ if (pid != inferior_pid)
+ perror_with_name ("wait");
+
+ if (WIFEXITED (w))
+ {
+ fprintf (stderr, "\nChild exited with retcode = %x \n", WEXITSTATUS (w));
+ *status = 'W';
+ return ((unsigned char) WEXITSTATUS (w));
+ }
+ else if (!WIFSTOPPED (w))
+ {
+ fprintf (stderr, "\nChild terminated with signal = %x \n", WTERMSIG (w));
+ *status = 'X';
+ return ((unsigned char) WTERMSIG (w));
+ }
+
+ fetch_inferior_registers (0);
+
+ *status = 'T';
+ return ((unsigned char) WSTOPSIG (w));
+}
+
+/* Resume execution of the inferior process.
+ If STEP is nonzero, single-step it.
+ If SIGNAL is nonzero, give it that signal. */
+
+void
+myresume (step, signal)
+ int step;
+ int signal;
+{
+ errno = 0;
+ ptrace (step ? PT_STEP : PT_CONTINUE, inferior_pid, 1, signal, 0);
+ if (errno)
+ perror_with_name ("ptrace");
+}
+
+
+#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
+
+CORE_ADDR
+register_addr (regno, blockend)
+ int regno;
+ CORE_ADDR blockend;
+{
+ CORE_ADDR addr;
+
+ if (regno < 0 || regno >= ARCH_NUM_REGS)
+ error ("Invalid register number %d.", regno);
+
+ REGISTER_U_ADDR (addr, blockend, regno);
+
+ return addr;
+}
+
+/* Fetch one register. */
+
+static void
+fetch_register (regno)
+ int regno;
+{
+ register unsigned int regaddr;
+ char buf[MAX_REGISTER_RAW_SIZE];
+ register int i;
+
+ /* Offset of registers within the u area. */
+ unsigned int offset;
+
+ offset = U_REGS_OFFSET;
+
+ regaddr = register_addr (regno, offset);
+ for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (int))
+ {
+ errno = 0;
+ *(int *) &registers[ regno * 4 + i] = ptrace (PT_RUREGS, inferior_pid,
+ (PTRACE_ARG3_TYPE) regaddr, 0, 0);
+ regaddr += sizeof (int);
+ if (errno != 0)
+ {
+ /* Warning, not error, in case we are attached; sometimes the
+ kernel doesn't let us at the registers. */
+ char *err = strerror (errno);
+ char *msg = alloca (strlen (err) + 128);
+ sprintf (msg, "reading register %d: %s", regno, err);
+ error (msg);
+ goto error_exit;
+ }
+ }
+ error_exit:;
+}
+
+/* Fetch all registers, or just one, from the child process. */
+
+void
+fetch_inferior_registers (regno)
+ int regno;
+{
+ if (regno == -1 || regno == 0)
+ for (regno = 0; regno < NUM_REGS; regno++)
+ fetch_register (regno);
+ else
+ fetch_register (regno);
+}
+
+/* Store our register values back into the inferior.
+ If REGNO is -1, do this for all registers.
+ Otherwise, REGNO specifies which register (so we can save time). */
+
+void
+store_inferior_registers (regno)
+ int regno;
+{
+ register unsigned int regaddr;
+ char buf[80];
+ extern char registers[];
+ register int i;
+ unsigned int offset = U_REGS_OFFSET;
+ int scratch;
+
+ if (regno >= 0)
+ {
+ if (CANNOT_STORE_REGISTER (regno))
+ return;
+ regaddr = register_addr (regno, offset);
+ errno = 0;
+ if (regno == PCOQ_HEAD_REGNUM || regno == PCOQ_TAIL_REGNUM)
+ {
+ scratch = *(int *) &registers[REGISTER_BYTE (regno)] | 0x3;
+ ptrace (PT_WUREGS, inferior_pid, (PTRACE_ARG3_TYPE) regaddr,
+ scratch, 0);
+ if (errno != 0)
+ {
+ /* Error, even if attached. Failing to write these two
+ registers is pretty serious. */
+ sprintf (buf, "writing register number %d", regno);
+ perror_with_name (buf);
+ }
+ }
+ else
+ for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof(int))
+ {
+ errno = 0;
+ ptrace (PT_WUREGS, inferior_pid, (PTRACE_ARG3_TYPE) regaddr,
+ *(int *) &registers[REGISTER_BYTE (regno) + i], 0);
+ if (errno != 0)
+ {
+ /* Warning, not error, in case we are attached; sometimes the
+ kernel doesn't let us at the registers. */
+ char *err = strerror (errno);
+ char *msg = alloca (strlen (err) + 128);
+ sprintf (msg, "writing register %d: %s",
+ regno, err);
+ error (msg);
+ return;
+ }
+ regaddr += sizeof(int);
+ }
+ }
+ else
+ for (regno = 0; regno < NUM_REGS; regno++)
+ store_inferior_registers (regno);
+}
+
+/* NOTE! I tried using PTRACE_READDATA, etc., to read and write memory
+ in the NEW_SUN_PTRACE case.
+ It ought to be straightforward. But it appears that writing did
+ not write the data that I specified. I cannot understand where
+ it got the data that it actually did write. */
+
+/* Copy LEN bytes from inferior's memory starting at MEMADDR
+ to debugger memory starting at MYADDR. */
+
+read_inferior_memory (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+{
+ register int i;
+ /* Round starting address down to longword boundary. */
+ register CORE_ADDR addr = memaddr & -sizeof (int);
+ /* Round ending address up; get number of longwords that makes. */
+ register int count
+ = (((memaddr + len) - addr) + sizeof (int) - 1) / sizeof (int);
+ /* Allocate buffer of that many longwords. */
+ register int *buffer = (int *) alloca (count * sizeof (int));
+
+ /* Read all the longwords */
+ for (i = 0; i < count; i++, addr += sizeof (int))
+ {
+ buffer[i] = ptrace (1, inferior_pid, addr, 0, 0);
+ }
+
+ /* Copy appropriate bytes out of the buffer. */
+ memcpy (myaddr, (char *) buffer + (memaddr & (sizeof (int) - 1)), len);
+}
+
+/* Copy LEN bytes of data from debugger memory at MYADDR
+ to inferior's memory at MEMADDR.
+ On failure (cannot write the inferior)
+ returns the value of errno. */
+
+int
+write_inferior_memory (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+{
+ register int i;
+ /* Round starting address down to longword boundary. */
+ register CORE_ADDR addr = memaddr & -sizeof (int);
+ /* Round ending address up; get number of longwords that makes. */
+ register int count
+ = (((memaddr + len) - addr) + sizeof (int) - 1) / sizeof (int);
+ /* Allocate buffer of that many longwords. */
+ register int *buffer = (int *) alloca (count * sizeof (int));
+ extern int errno;
+
+ /* Fill start and end extra bytes of buffer with existing memory data. */
+
+ buffer[0] = ptrace (1, inferior_pid, addr, 0, 0);
+
+ if (count > 1)
+ {
+ buffer[count - 1]
+ = ptrace (1, inferior_pid,
+ addr + (count - 1) * sizeof (int), 0, 0);
+ }
+
+ /* Copy data to be written over corresponding part of buffer */
+
+ memcpy ((char *) buffer + (memaddr & (sizeof (int) - 1)), myaddr, len);
+
+ /* Write the entire buffer. */
+
+ for (i = 0; i < count; i++, addr += sizeof (int))
+ {
+ errno = 0;
+ ptrace (4, inferior_pid, addr, buffer[i], 0);
+ if (errno)
+ return errno;
+ }
+
+ return 0;
+}
+
+void
+initialize ()
+{
+ inferior_pid = 0;
+}
+
+int
+have_inferior_p ()
+{
+ return inferior_pid != 0;
+}
diff --git a/gdb/gdbserver/low-linux.c b/gdb/gdbserver/low-linux.c
new file mode 100644
index 00000000000..106021057a3
--- /dev/null
+++ b/gdb/gdbserver/low-linux.c
@@ -0,0 +1,451 @@
+/* Low level interface to ptrace, for the remote server for GDB.
+ Copyright (C) 1995, 1996 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include <sys/wait.h>
+#include "frame.h"
+#include "inferior.h"
+
+#include <stdio.h>
+#include <sys/param.h>
+#include <sys/dir.h>
+#include <sys/user.h>
+#include <signal.h>
+#include <sys/ioctl.h>
+#if 0
+#include <sgtty.h>
+#endif
+#include <fcntl.h>
+
+/***************Begin MY defs*********************/
+int quit_flag = 0;
+char registers[REGISTER_BYTES];
+
+/* Index within `registers' of the first byte of the space for
+ register N. */
+
+
+char buf2[MAX_REGISTER_RAW_SIZE];
+/***************End MY defs*********************/
+
+#include <sys/ptrace.h>
+
+#if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 1)
+#include <sys/reg.h>
+#endif
+
+extern char **environ;
+extern int errno;
+extern int inferior_pid;
+void quit (), perror_with_name ();
+int query ();
+
+/* Start an inferior process and returns its pid.
+ ALLARGS is a vector of program-name and args.
+ ENV is the environment vector to pass. */
+
+int
+create_inferior (program, allargs)
+ char *program;
+ char **allargs;
+{
+ int pid;
+
+ pid = fork ();
+ if (pid < 0)
+ perror_with_name ("fork");
+
+ if (pid == 0)
+ {
+ ptrace (PTRACE_TRACEME, 0, 0, 0);
+
+ execv (program, allargs);
+
+ fprintf (stderr, "Cannot exec %s: %s.\n", program,
+ errno < sys_nerr ? sys_errlist[errno] : "unknown error");
+ fflush (stderr);
+ _exit (0177);
+ }
+
+ return pid;
+}
+
+/* Kill the inferior process. Make us have no inferior. */
+
+void
+kill_inferior ()
+{
+ if (inferior_pid == 0)
+ return;
+ ptrace (PTRACE_KILL, inferior_pid, 0, 0);
+ wait (0);
+ /*************inferior_died ();****VK**************/
+}
+
+/* Return nonzero if the given thread is still alive. */
+int
+mythread_alive (pid)
+ int pid;
+{
+ return 1;
+}
+
+/* Wait for process, returns status */
+
+unsigned char
+mywait (status)
+ char *status;
+{
+ int pid;
+ union wait w;
+
+ pid = wait (&w);
+ if (pid != inferior_pid)
+ perror_with_name ("wait");
+
+ if (WIFEXITED (w))
+ {
+ fprintf (stderr, "\nChild exited with retcode = %x \n", WEXITSTATUS (w));
+ *status = 'W';
+ return ((unsigned char) WEXITSTATUS (w));
+ }
+ else if (!WIFSTOPPED (w))
+ {
+ fprintf (stderr, "\nChild terminated with signal = %x \n", WTERMSIG (w));
+ *status = 'X';
+ return ((unsigned char) WTERMSIG (w));
+ }
+
+ fetch_inferior_registers (0);
+
+ *status = 'T';
+ return ((unsigned char) WSTOPSIG (w));
+}
+
+/* Resume execution of the inferior process.
+ If STEP is nonzero, single-step it.
+ If SIGNAL is nonzero, give it that signal. */
+
+void
+myresume (step, signal)
+ int step;
+ int signal;
+{
+ errno = 0;
+ ptrace (step ? PTRACE_SINGLESTEP : PTRACE_CONT, inferior_pid, 1, signal);
+ if (errno)
+ perror_with_name ("ptrace");
+}
+
+
+#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
+
+#ifndef TARGET_M68K
+/* this table must line up with REGISTER_NAMES in tm-i386v.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,
+};
+
+int
+i386_register_u_addr (blockend, regnum)
+ int blockend;
+ int 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]);
+
+}
+#else /* TARGET_M68K */
+/* This table must line up with REGISTER_NAMES in tm-m68k.h */
+static int regmap[] =
+{
+#ifdef PT_D0
+ PT_D0, PT_D1, PT_D2, PT_D3, PT_D4, PT_D5, PT_D6, PT_D7,
+ PT_A0, PT_A1, PT_A2, PT_A3, PT_A4, PT_A5, PT_A6, PT_USP,
+ PT_SR, PT_PC,
+#else
+ 14, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 15,
+ 17, 18,
+#endif
+#ifdef PT_FP0
+ PT_FP0, PT_FP1, PT_FP2, PT_FP3, PT_FP4, PT_FP5, PT_FP6, PT_FP7,
+ PT_FPCR, PT_FPSR, PT_FPIAR
+#else
+ 21, 24, 27, 30, 33, 36, 39, 42, 45, 46, 47
+#endif
+};
+
+/* BLOCKEND is the value of u.u_ar0, and points to the place where GS
+ is stored. */
+
+int
+m68k_linux_register_u_addr (blockend, regnum)
+ int blockend;
+ int regnum;
+{
+ return (blockend + 4 * regmap[regnum]);
+}
+#endif
+
+CORE_ADDR
+register_addr (regno, blockend)
+ int regno;
+ CORE_ADDR blockend;
+{
+ CORE_ADDR addr;
+
+ if (regno < 0 || regno >= ARCH_NUM_REGS)
+ error ("Invalid register number %d.", regno);
+
+ REGISTER_U_ADDR (addr, blockend, regno);
+
+ return addr;
+}
+
+/* Fetch one register. */
+
+static void
+fetch_register (regno)
+ int regno;
+{
+ register unsigned int regaddr;
+ register int i;
+
+ /* Offset of registers within the u area. */
+ unsigned int offset;
+
+ offset = U_REGS_OFFSET;
+
+ regaddr = register_addr (regno, offset);
+ for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (int))
+ {
+ errno = 0;
+ *(int *) &registers[ regno * 4 + i] = ptrace (PTRACE_PEEKUSR, inferior_pid,
+ (PTRACE_ARG3_TYPE) regaddr, 0);
+ regaddr += sizeof (int);
+ if (errno != 0)
+ {
+ /* Warning, not error, in case we are attached; sometimes the
+ kernel doesn't let us at the registers. */
+ char *err = strerror (errno);
+ char *msg = alloca (strlen (err) + 128);
+ sprintf (msg, "reading register %d: %s", regno, err);
+ error (msg);
+ goto error_exit;
+ }
+ }
+ error_exit:;
+}
+
+/* Fetch all registers, or just one, from the child process. */
+
+void
+fetch_inferior_registers (regno)
+ int regno;
+{
+ if (regno == -1 || regno == 0)
+ for (regno = 0; regno < NUM_REGS-NUM_FREGS; regno++)
+ fetch_register (regno);
+ else
+ fetch_register (regno);
+}
+
+/* Store our register values back into the inferior.
+ If REGNO is -1, do this for all registers.
+ Otherwise, REGNO specifies which register (so we can save time). */
+
+void
+store_inferior_registers (regno)
+ int regno;
+{
+ register unsigned int regaddr;
+ register int i;
+ unsigned int offset = U_REGS_OFFSET;
+
+ if (regno >= 0)
+ {
+#if 0
+ if (CANNOT_STORE_REGISTER (regno))
+ return;
+#endif
+ regaddr = register_addr (regno, offset);
+ errno = 0;
+#if 0
+ if (regno == PCOQ_HEAD_REGNUM || regno == PCOQ_TAIL_REGNUM)
+ {
+ scratch = *(int *) &registers[REGISTER_BYTE (regno)] | 0x3;
+ ptrace (PT_WUREGS, inferior_pid, (PTRACE_ARG3_TYPE) regaddr,
+ scratch, 0);
+ if (errno != 0)
+ {
+ /* Error, even if attached. Failing to write these two
+ registers is pretty serious. */
+ sprintf (buf, "writing register number %d", regno);
+ perror_with_name (buf);
+ }
+ }
+ else
+#endif
+ for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof(int))
+ {
+ errno = 0;
+ ptrace (PTRACE_POKEUSR, inferior_pid, (PTRACE_ARG3_TYPE) regaddr,
+ *(int *) &registers[REGISTER_BYTE (regno) + i]);
+ if (errno != 0)
+ {
+ /* Warning, not error, in case we are attached; sometimes the
+ kernel doesn't let us at the registers. */
+ char *err = strerror (errno);
+ char *msg = alloca (strlen (err) + 128);
+ sprintf (msg, "writing register %d: %s",
+ regno, err);
+ error (msg);
+ return;
+ }
+ regaddr += sizeof(int);
+ }
+ }
+ else
+ for (regno = 0; regno < NUM_REGS-NUM_FREGS; regno++)
+ store_inferior_registers (regno);
+}
+
+/* NOTE! I tried using PTRACE_READDATA, etc., to read and write memory
+ in the NEW_SUN_PTRACE case.
+ It ought to be straightforward. But it appears that writing did
+ not write the data that I specified. I cannot understand where
+ it got the data that it actually did write. */
+
+/* Copy LEN bytes from inferior's memory starting at MEMADDR
+ to debugger memory starting at MYADDR. */
+
+void
+read_inferior_memory (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+{
+ register int i;
+ /* Round starting address down to longword boundary. */
+ register CORE_ADDR addr = memaddr & -sizeof (int);
+ /* Round ending address up; get number of longwords that makes. */
+ register int count
+ = (((memaddr + len) - addr) + sizeof (int) - 1) / sizeof (int);
+ /* Allocate buffer of that many longwords. */
+ register int *buffer = (int *) alloca (count * sizeof (int));
+
+ /* Read all the longwords */
+ for (i = 0; i < count; i++, addr += sizeof (int))
+ {
+ buffer[i] = ptrace (PTRACE_PEEKTEXT, inferior_pid, addr, 0);
+ }
+
+ /* Copy appropriate bytes out of the buffer. */
+ memcpy (myaddr, (char *) buffer + (memaddr & (sizeof (int) - 1)), len);
+}
+
+/* Copy LEN bytes of data from debugger memory at MYADDR
+ to inferior's memory at MEMADDR.
+ On failure (cannot write the inferior)
+ returns the value of errno. */
+
+int
+write_inferior_memory (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+{
+ register int i;
+ /* Round starting address down to longword boundary. */
+ register CORE_ADDR addr = memaddr & -sizeof (int);
+ /* Round ending address up; get number of longwords that makes. */
+ register int count
+ = (((memaddr + len) - addr) + sizeof (int) - 1) / sizeof (int);
+ /* Allocate buffer of that many longwords. */
+ register int *buffer = (int *) alloca (count * sizeof (int));
+ extern int errno;
+
+ /* Fill start and end extra bytes of buffer with existing memory data. */
+
+ buffer[0] = ptrace (PTRACE_PEEKTEXT, inferior_pid, addr, 0);
+
+ if (count > 1)
+ {
+ buffer[count - 1]
+ = ptrace (PTRACE_PEEKTEXT, inferior_pid,
+ addr + (count - 1) * sizeof (int), 0);
+ }
+
+ /* Copy data to be written over corresponding part of buffer */
+
+ memcpy ((char *) buffer + (memaddr & (sizeof (int) - 1)), myaddr, len);
+
+ /* Write the entire buffer. */
+
+ for (i = 0; i < count; i++, addr += sizeof (int))
+ {
+ errno = 0;
+ ptrace (PTRACE_POKETEXT, inferior_pid, addr, buffer[i]);
+ if (errno)
+ return errno;
+ }
+
+ return 0;
+}
+
+void
+initialize ()
+{
+ inferior_pid = 0;
+}
+
+int
+have_inferior_p ()
+{
+ return inferior_pid != 0;
+}
diff --git a/gdb/gdbserver/low-lynx.c b/gdb/gdbserver/low-lynx.c
new file mode 100644
index 00000000000..3444f7a116e
--- /dev/null
+++ b/gdb/gdbserver/low-lynx.c
@@ -0,0 +1,746 @@
+/* Low level interface to ptrace, for the remote server for GDB.
+ Copyright (C) 1986, 1987, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "server.h"
+#include "frame.h"
+#include "inferior.h"
+
+#include <stdio.h>
+#include <sys/param.h>
+#include <sys/dir.h>
+#define LYNXOS
+#include <sys/mem.h>
+#include <sys/signal.h>
+#include <sys/file.h>
+#include <sys/kernel.h>
+#ifndef __LYNXOS
+#define __LYNXOS
+#endif
+#include <sys/itimer.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <sys/proc.h>
+#include <signal.h>
+#include <sys/ioctl.h>
+#include <sgtty.h>
+#include <fcntl.h>
+#include <sys/wait.h>
+#include <sys/fpp.h>
+
+char registers[REGISTER_BYTES];
+
+#include <sys/ptrace.h>
+
+/* Start an inferior process and returns its pid.
+ ALLARGS is a vector of program-name and args. */
+
+int
+create_inferior (program, allargs)
+ char *program;
+ char **allargs;
+{
+ int pid;
+
+ pid = fork ();
+ if (pid < 0)
+ perror_with_name ("fork");
+
+ if (pid == 0)
+ {
+ int pgrp;
+
+ /* Switch child to it's own process group so that signals won't
+ directly affect gdbserver. */
+
+ pgrp = getpid();
+ setpgrp(0, pgrp);
+ ioctl (0, TIOCSPGRP, &pgrp);
+
+ ptrace (PTRACE_TRACEME, 0, (PTRACE_ARG3_TYPE)0, 0);
+
+ execv (program, allargs);
+
+ fprintf (stderr, "GDBserver (process %d): Cannot exec %s: %s.\n",
+ getpid(), program,
+ errno < sys_nerr ? sys_errlist[errno] : "unknown error");
+ fflush (stderr);
+ _exit (0177);
+ }
+
+ return pid;
+}
+
+/* Kill the inferior process. Make us have no inferior. */
+
+void
+kill_inferior ()
+{
+ if (inferior_pid == 0)
+ return;
+ ptrace (PTRACE_KILL, inferior_pid, 0, 0);
+ wait (0);
+
+ inferior_pid = 0;
+}
+
+/* Return nonzero if the given thread is still alive. */
+int
+mythread_alive (pid)
+ int pid;
+{
+ /* Arggh. Apparently pthread_kill only works for threads within
+ the process that calls pthread_kill.
+
+ We want to avoid the lynx signal extensions as they simply don't
+ map well to the generic gdb interface we want to keep.
+
+ All we want to do is determine if a particular thread is alive;
+ it appears as if we can just make a harmless thread specific
+ ptrace call to do that. */
+ return (ptrace (PTRACE_THREADUSER,
+ BUILDPID (PIDGET (inferior_pid), pid), 0, 0) != -1);
+}
+
+/* Wait for process, returns status */
+
+unsigned char
+mywait (status)
+ char *status;
+{
+ int pid;
+ union wait w;
+
+ while (1)
+ {
+ enable_async_io();
+
+ pid = wait (&w);
+
+ disable_async_io();
+
+ if (pid != PIDGET(inferior_pid))
+ perror_with_name ("wait");
+
+ thread_from_wait = w.w_tid;
+ inferior_pid = BUILDPID (inferior_pid, w.w_tid);
+
+ if (WIFSTOPPED(w)
+ && WSTOPSIG(w) == SIGTRAP)
+ {
+ int realsig;
+
+ realsig = ptrace (PTRACE_GETTRACESIG, inferior_pid,
+ (PTRACE_ARG3_TYPE)0, 0);
+
+ if (realsig == SIGNEWTHREAD)
+ {
+ /* It's a new thread notification. Nothing to do here since
+ the machine independent code in wait_for_inferior will
+ add the thread to the thread list and restart the thread
+ when pid != inferior_pid and pid is not in the thread list.
+ We don't even want to muck with realsig -- the code in
+ wait_for_inferior expects SIGTRAP. */
+ ;
+ }
+ }
+ break;
+ }
+
+ if (WIFEXITED (w))
+ {
+ *status = 'W';
+ return ((unsigned char) WEXITSTATUS (w));
+ }
+ else if (!WIFSTOPPED (w))
+ {
+ *status = 'X';
+ return ((unsigned char) WTERMSIG (w));
+ }
+
+ fetch_inferior_registers (0);
+
+ *status = 'T';
+ return ((unsigned char) WSTOPSIG (w));
+}
+
+/* Resume execution of the inferior process.
+ If STEP is nonzero, single-step it.
+ If SIGNAL is nonzero, give it that signal. */
+
+void
+myresume (step, signal)
+ int step;
+ int signal;
+{
+ errno = 0;
+ ptrace (step ? PTRACE_SINGLESTEP_ONE : PTRACE_CONT,
+ BUILDPID (inferior_pid, cont_thread == -1 ? 0 : cont_thread),
+ 1, signal);
+ if (errno)
+ perror_with_name ("ptrace");
+}
+
+#undef offsetof
+#define offsetof(TYPE, MEMBER) ((unsigned long) &((TYPE *)0)->MEMBER)
+
+/* Mapping between GDB register #s and offsets into econtext. Must be
+ consistent with REGISTER_NAMES macro in various tmXXX.h files. */
+
+#define X(ENTRY)(offsetof(struct econtext, ENTRY))
+
+#ifdef I386
+/* Mappings from tm-i386v.h */
+
+static int regmap[] =
+{
+ X(eax),
+ X(ecx),
+ X(edx),
+ X(ebx),
+ X(esp), /* sp */
+ X(ebp), /* fp */
+ X(esi),
+ X(edi),
+ X(eip), /* pc */
+ X(flags), /* ps */
+ X(cs),
+ X(ss),
+ X(ds),
+ X(es),
+ X(ecode), /* Lynx doesn't give us either fs or gs, so */
+ X(fault), /* we just substitute these two in the hopes
+ that they are useful. */
+};
+#endif
+
+#ifdef M68K
+/* Mappings from tm-m68k.h */
+
+static int regmap[] =
+{
+ X(regs[0]), /* d0 */
+ X(regs[1]), /* d1 */
+ X(regs[2]), /* d2 */
+ X(regs[3]), /* d3 */
+ X(regs[4]), /* d4 */
+ X(regs[5]), /* d5 */
+ X(regs[6]), /* d6 */
+ X(regs[7]), /* d7 */
+ X(regs[8]), /* a0 */
+ X(regs[9]), /* a1 */
+ X(regs[10]), /* a2 */
+ X(regs[11]), /* a3 */
+ X(regs[12]), /* a4 */
+ X(regs[13]), /* a5 */
+ X(regs[14]), /* fp */
+ 0, /* sp */
+ X(status), /* ps */
+ X(pc),
+
+ X(fregs[0*3]), /* fp0 */
+ X(fregs[1*3]), /* fp1 */
+ X(fregs[2*3]), /* fp2 */
+ X(fregs[3*3]), /* fp3 */
+ X(fregs[4*3]), /* fp4 */
+ X(fregs[5*3]), /* fp5 */
+ X(fregs[6*3]), /* fp6 */
+ X(fregs[7*3]), /* fp7 */
+
+ X(fcregs[0]), /* fpcontrol */
+ X(fcregs[1]), /* fpstatus */
+ X(fcregs[2]), /* fpiaddr */
+ X(ssw), /* fpcode */
+ X(fault), /* fpflags */
+};
+#endif
+
+#ifdef SPARC
+/* Mappings from tm-sparc.h */
+
+#define FX(ENTRY)(offsetof(struct fcontext, ENTRY))
+
+static int regmap[] =
+{
+ -1, /* g0 */
+ X(g1),
+ X(g2),
+ X(g3),
+ X(g4),
+ -1, /* g5->g7 aren't saved by Lynx */
+ -1,
+ -1,
+
+ X(o[0]),
+ X(o[1]),
+ X(o[2]),
+ X(o[3]),
+ X(o[4]),
+ X(o[5]),
+ X(o[6]), /* sp */
+ X(o[7]), /* ra */
+
+ -1,-1,-1,-1,-1,-1,-1,-1, /* l0 -> l7 */
+
+ -1,-1,-1,-1,-1,-1,-1,-1, /* i0 -> i7 */
+
+ FX(f.fregs[0]), /* f0 */
+ FX(f.fregs[1]),
+ FX(f.fregs[2]),
+ FX(f.fregs[3]),
+ FX(f.fregs[4]),
+ FX(f.fregs[5]),
+ FX(f.fregs[6]),
+ FX(f.fregs[7]),
+ FX(f.fregs[8]),
+ FX(f.fregs[9]),
+ FX(f.fregs[10]),
+ FX(f.fregs[11]),
+ FX(f.fregs[12]),
+ FX(f.fregs[13]),
+ FX(f.fregs[14]),
+ FX(f.fregs[15]),
+ FX(f.fregs[16]),
+ FX(f.fregs[17]),
+ FX(f.fregs[18]),
+ FX(f.fregs[19]),
+ FX(f.fregs[20]),
+ FX(f.fregs[21]),
+ FX(f.fregs[22]),
+ FX(f.fregs[23]),
+ FX(f.fregs[24]),
+ FX(f.fregs[25]),
+ FX(f.fregs[26]),
+ FX(f.fregs[27]),
+ FX(f.fregs[28]),
+ FX(f.fregs[29]),
+ FX(f.fregs[30]),
+ FX(f.fregs[31]),
+
+ X(y),
+ X(psr),
+ X(wim),
+ X(tbr),
+ X(pc),
+ X(npc),
+ FX(fsr), /* fpsr */
+ -1, /* cpsr */
+};
+#endif
+
+#ifdef SPARC
+
+/* This routine handles some oddball cases for Sparc registers and LynxOS.
+ In partucular, it causes refs to G0, g5->7, and all fp regs to return zero.
+ It also handles knows where to find the I & L regs on the stack. */
+
+void
+fetch_inferior_registers (regno)
+ int regno;
+{
+#if 0
+ int whatregs = 0;
+
+#define WHATREGS_FLOAT 1
+#define WHATREGS_GEN 2
+#define WHATREGS_STACK 4
+
+ if (regno == -1)
+ whatregs = WHATREGS_FLOAT | WHATREGS_GEN | WHATREGS_STACK;
+ else if (regno >= L0_REGNUM && regno <= I7_REGNUM)
+ whatregs = WHATREGS_STACK;
+ else if (regno >= FP0_REGNUM && regno < FP0_REGNUM + 32)
+ whatregs = WHATREGS_FLOAT;
+ else
+ whatregs = WHATREGS_GEN;
+
+ if (whatregs & WHATREGS_GEN)
+ {
+ struct econtext ec; /* general regs */
+ char buf[MAX_REGISTER_RAW_SIZE];
+ int retval;
+ int i;
+
+ errno = 0;
+ retval = ptrace (PTRACE_GETREGS,
+ BUILDPID (inferior_pid, general_thread),
+ (PTRACE_ARG3_TYPE) &ec,
+ 0);
+ if (errno)
+ perror_with_name ("Sparc fetch_inferior_registers(ptrace)");
+
+ memset (buf, 0, REGISTER_RAW_SIZE (G0_REGNUM));
+ supply_register (G0_REGNUM, buf);
+ supply_register (TBR_REGNUM, (char *)&ec.tbr);
+
+ memcpy (&registers[REGISTER_BYTE (G1_REGNUM)], &ec.g1,
+ 4 * REGISTER_RAW_SIZE (G1_REGNUM));
+ for (i = G1_REGNUM; i <= G1_REGNUM + 3; i++)
+ register_valid[i] = 1;
+
+ supply_register (PS_REGNUM, (char *)&ec.psr);
+ supply_register (Y_REGNUM, (char *)&ec.y);
+ supply_register (PC_REGNUM, (char *)&ec.pc);
+ supply_register (NPC_REGNUM, (char *)&ec.npc);
+ supply_register (WIM_REGNUM, (char *)&ec.wim);
+
+ memcpy (&registers[REGISTER_BYTE (O0_REGNUM)], ec.o,
+ 8 * REGISTER_RAW_SIZE (O0_REGNUM));
+ for (i = O0_REGNUM; i <= O0_REGNUM + 7; i++)
+ register_valid[i] = 1;
+ }
+
+ if (whatregs & WHATREGS_STACK)
+ {
+ CORE_ADDR sp;
+ int i;
+
+ sp = read_register (SP_REGNUM);
+
+ target_xfer_memory (sp + FRAME_SAVED_I0,
+ &registers[REGISTER_BYTE(I0_REGNUM)],
+ 8 * REGISTER_RAW_SIZE (I0_REGNUM), 0);
+ for (i = I0_REGNUM; i <= I7_REGNUM; i++)
+ register_valid[i] = 1;
+
+ target_xfer_memory (sp + FRAME_SAVED_L0,
+ &registers[REGISTER_BYTE(L0_REGNUM)],
+ 8 * REGISTER_RAW_SIZE (L0_REGNUM), 0);
+ for (i = L0_REGNUM; i <= L0_REGNUM + 7; i++)
+ register_valid[i] = 1;
+ }
+
+ if (whatregs & WHATREGS_FLOAT)
+ {
+ struct fcontext fc; /* fp regs */
+ int retval;
+ int i;
+
+ errno = 0;
+ retval = ptrace (PTRACE_GETFPREGS, BUILDPID (inferior_pid, general_thread), (PTRACE_ARG3_TYPE) &fc,
+ 0);
+ if (errno)
+ perror_with_name ("Sparc fetch_inferior_registers(ptrace)");
+
+ memcpy (&registers[REGISTER_BYTE (FP0_REGNUM)], fc.f.fregs,
+ 32 * REGISTER_RAW_SIZE (FP0_REGNUM));
+ for (i = FP0_REGNUM; i <= FP0_REGNUM + 31; i++)
+ register_valid[i] = 1;
+
+ supply_register (FPS_REGNUM, (char *)&fc.fsr);
+ }
+#endif
+}
+
+/* This routine handles storing of the I & L regs for the Sparc. The trick
+ here is that they actually live on the stack. The really tricky part is
+ that when changing the stack pointer, the I & L regs must be written to
+ where the new SP points, otherwise the regs will be incorrect when the
+ process is started up again. We assume that the I & L regs are valid at
+ this point. */
+
+void
+store_inferior_registers (regno)
+ int regno;
+{
+#if 0
+ int whatregs = 0;
+
+ if (regno == -1)
+ whatregs = WHATREGS_FLOAT | WHATREGS_GEN | WHATREGS_STACK;
+ else if (regno >= L0_REGNUM && regno <= I7_REGNUM)
+ whatregs = WHATREGS_STACK;
+ else if (regno >= FP0_REGNUM && regno < FP0_REGNUM + 32)
+ whatregs = WHATREGS_FLOAT;
+ else if (regno == SP_REGNUM)
+ whatregs = WHATREGS_STACK | WHATREGS_GEN;
+ else
+ whatregs = WHATREGS_GEN;
+
+ if (whatregs & WHATREGS_GEN)
+ {
+ struct econtext ec; /* general regs */
+ int retval;
+
+ ec.tbr = read_register (TBR_REGNUM);
+ memcpy (&ec.g1, &registers[REGISTER_BYTE (G1_REGNUM)],
+ 4 * REGISTER_RAW_SIZE (G1_REGNUM));
+
+ ec.psr = read_register (PS_REGNUM);
+ ec.y = read_register (Y_REGNUM);
+ ec.pc = read_register (PC_REGNUM);
+ ec.npc = read_register (NPC_REGNUM);
+ ec.wim = read_register (WIM_REGNUM);
+
+ memcpy (ec.o, &registers[REGISTER_BYTE (O0_REGNUM)],
+ 8 * REGISTER_RAW_SIZE (O0_REGNUM));
+
+ errno = 0;
+ retval = ptrace (PTRACE_SETREGS, BUILDPID (inferior_pid, general_thread), (PTRACE_ARG3_TYPE) &ec,
+ 0);
+ if (errno)
+ perror_with_name ("Sparc fetch_inferior_registers(ptrace)");
+ }
+
+ if (whatregs & WHATREGS_STACK)
+ {
+ int regoffset;
+ CORE_ADDR sp;
+
+ sp = read_register (SP_REGNUM);
+
+ if (regno == -1 || regno == SP_REGNUM)
+ {
+ if (!register_valid[L0_REGNUM+5])
+ abort();
+ target_xfer_memory (sp + FRAME_SAVED_I0,
+ &registers[REGISTER_BYTE (I0_REGNUM)],
+ 8 * REGISTER_RAW_SIZE (I0_REGNUM), 1);
+
+ target_xfer_memory (sp + FRAME_SAVED_L0,
+ &registers[REGISTER_BYTE (L0_REGNUM)],
+ 8 * REGISTER_RAW_SIZE (L0_REGNUM), 1);
+ }
+ else if (regno >= L0_REGNUM && regno <= I7_REGNUM)
+ {
+ if (!register_valid[regno])
+ abort();
+ if (regno >= L0_REGNUM && regno <= L0_REGNUM + 7)
+ regoffset = REGISTER_BYTE (regno) - REGISTER_BYTE (L0_REGNUM)
+ + FRAME_SAVED_L0;
+ else
+ regoffset = REGISTER_BYTE (regno) - REGISTER_BYTE (I0_REGNUM)
+ + FRAME_SAVED_I0;
+ target_xfer_memory (sp + regoffset, &registers[REGISTER_BYTE (regno)],
+ REGISTER_RAW_SIZE (regno), 1);
+ }
+ }
+
+ if (whatregs & WHATREGS_FLOAT)
+ {
+ struct fcontext fc; /* fp regs */
+ int retval;
+
+/* We read fcontext first so that we can get good values for fq_t... */
+ errno = 0;
+ retval = ptrace (PTRACE_GETFPREGS, BUILDPID (inferior_pid, general_thread), (PTRACE_ARG3_TYPE) &fc,
+ 0);
+ if (errno)
+ perror_with_name ("Sparc fetch_inferior_registers(ptrace)");
+
+ memcpy (fc.f.fregs, &registers[REGISTER_BYTE (FP0_REGNUM)],
+ 32 * REGISTER_RAW_SIZE (FP0_REGNUM));
+
+ fc.fsr = read_register (FPS_REGNUM);
+
+ errno = 0;
+ retval = ptrace (PTRACE_SETFPREGS, BUILDPID (inferior_pid, general_thread), (PTRACE_ARG3_TYPE) &fc,
+ 0);
+ if (errno)
+ perror_with_name ("Sparc fetch_inferior_registers(ptrace)");
+ }
+#endif
+}
+#endif /* SPARC */
+
+#ifndef SPARC
+
+/* Return the offset relative to the start of the per-thread data to the
+ saved context block. */
+
+static unsigned long
+lynx_registers_addr()
+{
+ CORE_ADDR stblock;
+ int ecpoff = offsetof(st_t, ecp);
+ CORE_ADDR ecp;
+
+ errno = 0;
+ stblock = (CORE_ADDR) ptrace (PTRACE_THREADUSER, BUILDPID (inferior_pid, general_thread),
+ (PTRACE_ARG3_TYPE)0, 0);
+ if (errno)
+ perror_with_name ("PTRACE_THREADUSER");
+
+ ecp = (CORE_ADDR) ptrace (PTRACE_PEEKTHREAD, BUILDPID (inferior_pid, general_thread),
+ (PTRACE_ARG3_TYPE)ecpoff, 0);
+ if (errno)
+ perror_with_name ("lynx_registers_addr(PTRACE_PEEKTHREAD)");
+
+ return ecp - stblock;
+}
+
+/* Fetch one or more registers from the inferior. REGNO == -1 to get
+ them all. We actually fetch more than requested, when convenient,
+ marking them as valid so we won't fetch them again. */
+
+void
+fetch_inferior_registers (ignored)
+ int ignored;
+{
+ int regno;
+ unsigned long reg;
+ unsigned long ecp;
+
+ ecp = lynx_registers_addr();
+
+ for (regno = 0; regno < NUM_REGS; regno++)
+ {
+ int ptrace_fun = PTRACE_PEEKTHREAD;
+
+#ifdef PTRACE_PEEKUSP
+ ptrace_fun = regno == SP_REGNUM ? PTRACE_PEEKUSP : PTRACE_PEEKTHREAD;
+#endif
+
+ errno = 0;
+ reg = ptrace (ptrace_fun, BUILDPID (inferior_pid, general_thread),
+ (PTRACE_ARG3_TYPE) (ecp + regmap[regno]), 0);
+ if (errno)
+ perror_with_name ("fetch_inferior_registers(PTRACE_PEEKTHREAD)");
+
+ *(unsigned long *)&registers[REGISTER_BYTE (regno)] = reg;
+ }
+}
+
+/* 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 (ignored)
+ int ignored;
+{
+ int regno;
+ unsigned long reg;
+ unsigned long ecp;
+
+ ecp = lynx_registers_addr();
+
+ for (regno = 0; regno < NUM_REGS; regno++)
+ {
+ int ptrace_fun = PTRACE_POKEUSER;
+
+#ifdef PTRACE_POKEUSP
+ ptrace_fun = regno == SP_REGNUM ? PTRACE_POKEUSP : PTRACE_POKEUSER;
+#endif
+
+ reg = *(unsigned long *)&registers[REGISTER_BYTE (regno)];
+
+ errno = 0;
+ ptrace (ptrace_fun, BUILDPID (inferior_pid, general_thread),
+ (PTRACE_ARG3_TYPE) (ecp + regmap[regno]), reg);
+ if (errno)
+ perror_with_name ("PTRACE_POKEUSER");
+ }
+}
+
+#endif /* ! SPARC */
+
+/* NOTE! I tried using PTRACE_READDATA, etc., to read and write memory
+ in the NEW_SUN_PTRACE case.
+ It ought to be straightforward. But it appears that writing did
+ not write the data that I specified. I cannot understand where
+ it got the data that it actually did write. */
+
+/* Copy LEN bytes from inferior's memory starting at MEMADDR
+ to debugger memory starting at MYADDR. */
+
+void
+read_inferior_memory (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+{
+ register int i;
+ /* Round starting address down to longword boundary. */
+ register CORE_ADDR addr = memaddr & -sizeof (int);
+ /* Round ending address up; get number of longwords that makes. */
+ register int count
+ = (((memaddr + len) - addr) + sizeof (int) - 1) / sizeof (int);
+ /* Allocate buffer of that many longwords. */
+ register int *buffer = (int *) alloca (count * sizeof (int));
+
+ /* Read all the longwords */
+ for (i = 0; i < count; i++, addr += sizeof (int))
+ {
+ buffer[i] = ptrace (PTRACE_PEEKTEXT, BUILDPID (inferior_pid, general_thread), addr, 0);
+ }
+
+ /* Copy appropriate bytes out of the buffer. */
+ memcpy (myaddr, (char *) buffer + (memaddr & (sizeof (int) - 1)), len);
+}
+
+/* Copy LEN bytes of data from debugger memory at MYADDR
+ to inferior's memory at MEMADDR.
+ On failure (cannot write the inferior)
+ returns the value of errno. */
+
+int
+write_inferior_memory (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+{
+ register int i;
+ /* Round starting address down to longword boundary. */
+ register CORE_ADDR addr = memaddr & -sizeof (int);
+ /* Round ending address up; get number of longwords that makes. */
+ register int count
+ = (((memaddr + len) - addr) + sizeof (int) - 1) / sizeof (int);
+ /* Allocate buffer of that many longwords. */
+ register int *buffer = (int *) alloca (count * sizeof (int));
+ extern int errno;
+
+ /* Fill start and end extra bytes of buffer with existing memory data. */
+
+ buffer[0] = ptrace (PTRACE_PEEKTEXT, BUILDPID (inferior_pid, general_thread), addr, 0);
+
+ if (count > 1)
+ {
+ buffer[count - 1]
+ = ptrace (PTRACE_PEEKTEXT, BUILDPID (inferior_pid, general_thread),
+ addr + (count - 1) * sizeof (int), 0);
+ }
+
+ /* Copy data to be written over corresponding part of buffer */
+
+ memcpy ((char *) buffer + (memaddr & (sizeof (int) - 1)), myaddr, len);
+
+ /* Write the entire buffer. */
+
+ for (i = 0; i < count; i++, addr += sizeof (int))
+ {
+ while (1)
+ {
+ errno = 0;
+ ptrace (PTRACE_POKETEXT, BUILDPID (inferior_pid, general_thread), addr, buffer[i]);
+ if (errno)
+ {
+ fprintf(stderr, "\
+ptrace (PTRACE_POKETEXT): errno=%d, pid=0x%x, addr=0x%x, buffer[i] = 0x%x\n",
+ errno, BUILDPID (inferior_pid, general_thread),
+ addr, buffer[i]);
+ fprintf(stderr, "Sleeping for 1 second\n");
+ sleep(1);
+ }
+ else
+ break;
+ }
+ }
+
+ return 0;
+}
diff --git a/gdb/gdbserver/low-sim.c b/gdb/gdbserver/low-sim.c
new file mode 100644
index 00000000000..8ad6e91d461
--- /dev/null
+++ b/gdb/gdbserver/low-sim.c
@@ -0,0 +1,289 @@
+/* Low level interface to simulators, for the remote server for GDB.
+ Copyright (C) 1995, 1996 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "bfd.h"
+#include "server.h"
+#include "callback.h" /* GDB simulator callback interface */
+#include "remote-sim.h" /* GDB simulator interface */
+
+extern int remote_debug;
+
+extern host_callback default_callback; /* in sim/common/callback.c */
+
+char registers[REGISTER_BYTES] __attribute__ ((aligned));
+
+int target_byte_order; /* used by simulator */
+
+/* We record the result of sim_open so we can pass it
+ back to the other sim_foo routines. */
+static SIM_DESC gdbsim_desc = 0;
+
+/* This version of "load" should be usable for any simulator that
+ does not support loading itself. */
+
+static void
+generic_load (loadfile_bfd)
+ bfd *loadfile_bfd;
+{
+ asection *s;
+
+ 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;
+ bfd_vma lma; /* use load address, not virtual address */
+
+ buffer = xmalloc (size);
+ lma = s->lma;
+
+ /* Is this really necessary? I guess it gives the user something
+ to look at during a long download. */
+ printf ("Loading section %s, size 0x%lx lma 0x%lx\n",
+ bfd_get_section_name (loadfile_bfd, s),
+ (unsigned long) size,
+ (unsigned long) lma); /* chops high 32 bits. FIXME!! */
+
+ bfd_get_section_contents (loadfile_bfd, s, buffer, 0, size);
+
+ write_inferior_memory (lma, buffer, size);
+ free (buffer);
+ }
+ }
+ }
+
+ printf ("Start address 0x%lx\n",
+ (unsigned long)loadfile_bfd->start_address);
+
+ /* We were doing this in remote-mips.c, I suspect it is right
+ for other targets too. */
+ /* write_pc (loadfile_bfd->start_address); */ /* FIXME!! */
+}
+
+int
+create_inferior (program, argv)
+ char *program;
+ char **argv;
+{
+ bfd *abfd;
+ int pid = 0;
+#ifdef TARGET_BYTE_ORDER_SELECTABLE
+ char **new_argv;
+ int nargs;
+#endif
+
+ abfd = bfd_openr (program, 0);
+ if (!abfd)
+ {
+ fprintf (stderr, "gdbserver: can't open %s: %s\n",
+ program, bfd_errmsg (bfd_get_error ()));
+ exit (1);
+ }
+
+ if (!bfd_check_format (abfd, bfd_object))
+ {
+ fprintf (stderr, "gdbserver: unknown load format for %s: %s\n",
+ program, bfd_errmsg (bfd_get_error ()));
+ exit (1);
+ }
+
+#ifdef TARGET_BYTE_ORDER_SELECTABLE
+ /* Add "-E big" or "-E little" to the argument list depending on the
+ endianness of the program to be loaded. */
+ for (nargs = 0; argv[nargs] != NULL; nargs++) /* count the args */
+ ;
+ new_argv = alloca (sizeof (char *) * (nargs + 3)); /* allocate new args */
+ for (nargs = 0; argv[nargs] != NULL; nargs++) /* copy old to new */
+ new_argv[nargs] = argv[nargs];
+ new_argv[nargs] = "-E";
+ new_argv[nargs + 1] = bfd_big_endian (abfd) ? "big" : "little";
+ new_argv[nargs + 2] = NULL;
+ argv = new_argv;
+#endif
+
+ /* Create an instance of the simulator. */
+ default_callback.init (&default_callback);
+ gdbsim_desc = sim_open (SIM_OPEN_STANDALONE, &default_callback, abfd, argv);
+ if (gdbsim_desc == 0)
+ exit (1);
+
+ /* Load the program into the simulator. */
+ if (abfd)
+ if (sim_load (gdbsim_desc, program, NULL, 0) == SIM_RC_FAIL)
+ generic_load (abfd);
+
+ /* Create an inferior process in the simulator. This initializes SP. */
+ sim_create_inferior (gdbsim_desc, abfd, argv, /* env */ NULL);
+ sim_resume (gdbsim_desc, 1, 0); /* execute one instr */
+ return pid;
+}
+
+/* Kill the inferior process. Make us have no inferior. */
+
+void
+kill_inferior ()
+{
+ sim_close (gdbsim_desc, 0);
+ default_callback.shutdown (&default_callback);
+}
+
+/* Fetch one register. */
+
+static void
+fetch_register (regno)
+ int regno;
+{
+ sim_fetch_register (gdbsim_desc, regno, &registers[REGISTER_BYTE (regno)],
+ REGISTER_RAW_SIZE (regno));
+}
+
+/* Fetch all registers, or just one, from the child process. */
+
+void
+fetch_inferior_registers (regno)
+ int regno;
+{
+ if (regno == -1 || regno == 0)
+ for (regno = 0; regno < NUM_REGS/*-NUM_FREGS*/; regno++)
+ fetch_register (regno);
+ else
+ fetch_register (regno);
+}
+
+/* Store our register values back into the inferior.
+ If REGNO is -1, do this for all registers.
+ Otherwise, REGNO specifies which register (so we can save time). */
+
+void
+store_inferior_registers (regno)
+ int regno;
+{
+ if (regno == -1)
+ {
+ for (regno = 0; regno < NUM_REGS; regno++)
+ store_inferior_registers (regno);
+ }
+ else
+ sim_store_register (gdbsim_desc, regno, &registers[REGISTER_BYTE (regno)],
+ REGISTER_RAW_SIZE (regno));
+}
+
+/* Return nonzero if the given thread is still alive. */
+int
+mythread_alive (pid)
+ int pid;
+{
+ return 1;
+}
+
+/* Wait for process, returns status */
+
+unsigned char
+mywait (status)
+ char *status;
+{
+ int sigrc;
+ enum sim_stop reason;
+
+ sim_stop_reason (gdbsim_desc, &reason, &sigrc);
+ switch (reason)
+ {
+ case sim_exited:
+ if (remote_debug)
+ printf ("\nChild exited with retcode = %x \n", sigrc);
+ *status = 'W';
+ return sigrc;
+
+#if 0
+ case sim_stopped:
+ if (remote_debug)
+ printf ("\nChild terminated with signal = %x \n", sigrc);
+ *status = 'X';
+ return sigrc;
+#endif
+
+ default: /* should this be sim_signalled or sim_stopped? FIXME!! */
+ if (remote_debug)
+ printf ("\nChild received signal = %x \n", sigrc);
+ fetch_inferior_registers (0);
+ *status = 'T';
+ return (unsigned char) sigrc;
+ }
+}
+
+/* Resume execution of the inferior process.
+ If STEP is nonzero, single-step it.
+ If SIGNAL is nonzero, give it that signal. */
+
+void
+myresume (step, signo)
+ int step;
+ int signo;
+{
+ /* Should be using target_signal_to_host() or signal numbers in target.h
+ to convert GDB signal number to target signal number. */
+ sim_resume (gdbsim_desc, step, signo);
+}
+
+/* Copy LEN bytes from inferior's memory starting at MEMADDR
+ to debugger memory starting at MYADDR. */
+
+void
+read_inferior_memory (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+{
+ sim_read (gdbsim_desc, memaddr, myaddr, len);
+}
+
+/* Copy LEN bytes of data from debugger memory at MYADDR
+ to inferior's memory at MEMADDR.
+ On failure (cannot write the inferior)
+ returns the value of errno. */
+
+int
+write_inferior_memory (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+{
+ sim_write (gdbsim_desc, memaddr, myaddr, len); /* should check for error. FIXME!! */
+ return 0;
+}
+
+#if 0
+void
+initialize ()
+{
+ inferior_pid = 0;
+}
+
+int
+have_inferior_p ()
+{
+ return inferior_pid != 0;
+}
+#endif
diff --git a/gdb/gdbserver/low-sparc.c b/gdb/gdbserver/low-sparc.c
new file mode 100644
index 00000000000..ddffaec5927
--- /dev/null
+++ b/gdb/gdbserver/low-sparc.c
@@ -0,0 +1,334 @@
+/* Low level interface to ptrace, for the remote server for GDB.
+ Copyright (C) 1986, 1987, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include <sys/wait.h>
+#include "frame.h"
+#include "inferior.h"
+/***************************
+#include "initialize.h"
+****************************/
+
+#include <stdio.h>
+#include <sys/param.h>
+#include <sys/dir.h>
+#include <sys/user.h>
+#include <signal.h>
+#include <sys/ioctl.h>
+#include <sgtty.h>
+#include <fcntl.h>
+
+/***************Begin MY defs*********************/
+int quit_flag = 0;
+char registers[REGISTER_BYTES];
+
+/* Index within `registers' of the first byte of the space for
+ register N. */
+
+
+char buf2[MAX_REGISTER_RAW_SIZE];
+/***************End MY defs*********************/
+
+#include <sys/ptrace.h>
+#include <sys/reg.h>
+
+extern int sys_nerr;
+extern char **sys_errlist;
+extern char **environ;
+extern int errno;
+extern int inferior_pid;
+void quit (), perror_with_name ();
+int query ();
+
+/* Start an inferior process and returns its pid.
+ ALLARGS is a vector of program-name and args.
+ ENV is the environment vector to pass. */
+
+int
+create_inferior (program, allargs)
+ char *program;
+ char **allargs;
+{
+ int pid;
+
+ pid = fork ();
+ if (pid < 0)
+ perror_with_name ("fork");
+
+ if (pid == 0)
+ {
+ ptrace (PTRACE_TRACEME);
+
+ execv (program, allargs);
+
+ fprintf (stderr, "Cannot exec %s: %s.\n", program,
+ errno < sys_nerr ? sys_errlist[errno] : "unknown error");
+ fflush (stderr);
+ _exit (0177);
+ }
+
+ return pid;
+}
+
+/* Kill the inferior process. Make us have no inferior. */
+
+void
+kill_inferior ()
+{
+ if (inferior_pid == 0)
+ return;
+ ptrace (8, inferior_pid, 0, 0);
+ wait (0);
+ /*************inferior_died ();****VK**************/
+}
+
+/* Return nonzero if the given thread is still alive. */
+int
+mythread_alive (pid)
+ int pid;
+{
+ return 1;
+}
+
+/* Wait for process, returns status */
+
+unsigned char
+mywait (status)
+ char *status;
+{
+ int pid;
+ union wait w;
+
+ pid = wait (&w);
+ if (pid != inferior_pid)
+ perror_with_name ("wait");
+
+ if (WIFEXITED (w))
+ {
+ fprintf (stderr, "\nChild exited with retcode = %x \n", WEXITSTATUS (w));
+ *status = 'W';
+ return ((unsigned char) WEXITSTATUS (w));
+ }
+ else if (!WIFSTOPPED (w))
+ {
+ fprintf (stderr, "\nChild terminated with signal = %x \n", WTERMSIG (w));
+ *status = 'X';
+ return ((unsigned char) WTERMSIG (w));
+ }
+
+ fetch_inferior_registers (0);
+
+ *status = 'T';
+ return ((unsigned char) WSTOPSIG (w));
+}
+
+/* Resume execution of the inferior process.
+ If STEP is nonzero, single-step it.
+ If SIGNAL is nonzero, give it that signal. */
+
+void
+myresume (step, signal)
+ int step;
+ int signal;
+{
+ errno = 0;
+ ptrace (step ? PTRACE_SINGLESTEP : PTRACE_CONT, inferior_pid, 1, signal);
+ if (errno)
+ perror_with_name ("ptrace");
+}
+
+/* Fetch one or more registers from the inferior. REGNO == -1 to get
+ them all. We actually fetch more than requested, when convenient,
+ marking them as valid so we won't fetch them again. */
+
+void
+fetch_inferior_registers (ignored)
+ int ignored;
+{
+ struct regs inferior_registers;
+ struct fp_status inferior_fp_registers;
+ int i;
+
+ /* Global and Out regs are fetched directly, as well as the control
+ registers. If we're getting one of the in or local regs,
+ and the stack pointer has not yet been fetched,
+ we have to do that first, since they're found in memory relative
+ to the stack pointer. */
+
+ if (ptrace (PTRACE_GETREGS, inferior_pid,
+ (PTRACE_ARG3_TYPE) &inferior_registers, 0))
+ perror("ptrace_getregs");
+
+ registers[REGISTER_BYTE (0)] = 0;
+ memcpy (&registers[REGISTER_BYTE (1)], &inferior_registers.r_g1,
+ 15 * REGISTER_RAW_SIZE (G0_REGNUM));
+ *(int *)&registers[REGISTER_BYTE (PS_REGNUM)] = inferior_registers.r_ps;
+ *(int *)&registers[REGISTER_BYTE (PC_REGNUM)] = inferior_registers.r_pc;
+ *(int *)&registers[REGISTER_BYTE (NPC_REGNUM)] = inferior_registers.r_npc;
+ *(int *)&registers[REGISTER_BYTE (Y_REGNUM)] = inferior_registers.r_y;
+
+ /* Floating point registers */
+
+ if (ptrace (PTRACE_GETFPREGS, inferior_pid,
+ (PTRACE_ARG3_TYPE) &inferior_fp_registers,
+ 0))
+ perror("ptrace_getfpregs");
+ memcpy (&registers[REGISTER_BYTE (FP0_REGNUM)], &inferior_fp_registers,
+ sizeof inferior_fp_registers.fpu_fr);
+
+ /* These regs are saved on the stack by the kernel. Only read them
+ all (16 ptrace calls!) if we really need them. */
+
+ read_inferior_memory (*(CORE_ADDR*)&registers[REGISTER_BYTE (SP_REGNUM)],
+ &registers[REGISTER_BYTE (L0_REGNUM)],
+ 16*REGISTER_RAW_SIZE (L0_REGNUM));
+}
+
+/* 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 (ignored)
+ int ignored;
+{
+ struct regs inferior_registers;
+ struct fp_status inferior_fp_registers;
+ CORE_ADDR sp = *(CORE_ADDR *)&registers[REGISTER_BYTE (SP_REGNUM)];
+
+ write_inferior_memory (sp, &registers[REGISTER_BYTE (L0_REGNUM)],
+ 16*REGISTER_RAW_SIZE (L0_REGNUM));
+
+ memcpy (&inferior_registers.r_g1, &registers[REGISTER_BYTE (G1_REGNUM)],
+ 15 * REGISTER_RAW_SIZE (G1_REGNUM));
+
+ inferior_registers.r_ps =
+ *(int *)&registers[REGISTER_BYTE (PS_REGNUM)];
+ inferior_registers.r_pc =
+ *(int *)&registers[REGISTER_BYTE (PC_REGNUM)];
+ inferior_registers.r_npc =
+ *(int *)&registers[REGISTER_BYTE (NPC_REGNUM)];
+ inferior_registers.r_y =
+ *(int *)&registers[REGISTER_BYTE (Y_REGNUM)];
+
+ if (ptrace (PTRACE_SETREGS, inferior_pid,
+ (PTRACE_ARG3_TYPE) &inferior_registers, 0))
+ perror("ptrace_setregs");
+
+ memcpy (&inferior_fp_registers, &registers[REGISTER_BYTE (FP0_REGNUM)],
+ sizeof inferior_fp_registers.fpu_fr);
+
+ if (ptrace (PTRACE_SETFPREGS, inferior_pid,
+ (PTRACE_ARG3_TYPE) &inferior_fp_registers, 0))
+ perror("ptrace_setfpregs");
+}
+
+/* NOTE! I tried using PTRACE_READDATA, etc., to read and write memory
+ in the NEW_SUN_PTRACE case.
+ It ought to be straightforward. But it appears that writing did
+ not write the data that I specified. I cannot understand where
+ it got the data that it actually did write. */
+
+/* Copy LEN bytes from inferior's memory starting at MEMADDR
+ to debugger memory starting at MYADDR. */
+
+read_inferior_memory (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+{
+ register int i;
+ /* Round starting address down to longword boundary. */
+ register CORE_ADDR addr = memaddr & -sizeof (int);
+ /* Round ending address up; get number of longwords that makes. */
+ register int count
+ = (((memaddr + len) - addr) + sizeof (int) - 1) / sizeof (int);
+ /* Allocate buffer of that many longwords. */
+ register int *buffer = (int *) alloca (count * sizeof (int));
+
+ /* Read all the longwords */
+ for (i = 0; i < count; i++, addr += sizeof (int))
+ {
+ buffer[i] = ptrace (1, inferior_pid, addr, 0);
+ }
+
+ /* Copy appropriate bytes out of the buffer. */
+ memcpy (myaddr, (char *) buffer + (memaddr & (sizeof (int) - 1)), len);
+}
+
+/* Copy LEN bytes of data from debugger memory at MYADDR
+ to inferior's memory at MEMADDR.
+ On failure (cannot write the inferior)
+ returns the value of errno. */
+
+int
+write_inferior_memory (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+{
+ register int i;
+ /* Round starting address down to longword boundary. */
+ register CORE_ADDR addr = memaddr & -sizeof (int);
+ /* Round ending address up; get number of longwords that makes. */
+ register int count
+ = (((memaddr + len) - addr) + sizeof (int) - 1) / sizeof (int);
+ /* Allocate buffer of that many longwords. */
+ register int *buffer = (int *) alloca (count * sizeof (int));
+ extern int errno;
+
+ /* Fill start and end extra bytes of buffer with existing memory data. */
+
+ buffer[0] = ptrace (1, inferior_pid, addr, 0);
+
+ if (count > 1)
+ {
+ buffer[count - 1]
+ = ptrace (1, inferior_pid,
+ addr + (count - 1) * sizeof (int), 0);
+ }
+
+ /* Copy data to be written over corresponding part of buffer */
+
+ bcopy (myaddr, (char *) buffer + (memaddr & (sizeof (int) - 1)), len);
+
+ /* Write the entire buffer. */
+
+ for (i = 0; i < count; i++, addr += sizeof (int))
+ {
+ errno = 0;
+ ptrace (4, inferior_pid, addr, buffer[i]);
+ if (errno)
+ return errno;
+ }
+
+ return 0;
+}
+
+void
+initialize ()
+{
+ inferior_pid = 0;
+}
+
+int
+have_inferior_p ()
+{
+ return inferior_pid != 0;
+}
diff --git a/gdb/gdbserver/low-sun3.c b/gdb/gdbserver/low-sun3.c
new file mode 100644
index 00000000000..c84b79f2f68
--- /dev/null
+++ b/gdb/gdbserver/low-sun3.c
@@ -0,0 +1,313 @@
+/* Low level interface to ptrace, for the remote server for GDB.
+ Copyright (C) 1986, 1987, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "<sys/wait.h>"
+#include "frame.h"
+#include "inferior.h"
+
+#include <stdio.h>
+#include <sys/param.h>
+#include <sys/dir.h>
+#include <sys/user.h>
+#include <signal.h>
+#include <sys/ioctl.h>
+#include <sgtty.h>
+#include <fcntl.h>
+
+/***************Begin MY defs*********************/
+int quit_flag = 0;
+char registers[REGISTER_BYTES];
+
+/* Index within `registers' of the first byte of the space for
+ register N. */
+
+
+char buf2[MAX_REGISTER_RAW_SIZE];
+/***************End MY defs*********************/
+
+#include <sys/ptrace.h>
+#include <machine/reg.h>
+
+extern int sys_nerr;
+extern char **sys_errlist;
+extern char **environ;
+extern int errno;
+extern int inferior_pid;
+void quit (), perror_with_name ();
+int query ();
+
+/* Start an inferior process and returns its pid.
+ ALLARGS is a vector of program-name and args.
+ ENV is the environment vector to pass. */
+
+int
+create_inferior (program, allargs)
+ char *program;
+ char **allargs;
+{
+ int pid;
+
+ pid = fork ();
+ if (pid < 0)
+ perror_with_name ("fork");
+
+ if (pid == 0)
+ {
+ ptrace (PTRACE_TRACEME);
+
+ execv (program, allargs);
+
+ fprintf (stderr, "Cannot exec %s: %s.\n", program,
+ errno < sys_nerr ? sys_errlist[errno] : "unknown error");
+ fflush (stderr);
+ _exit (0177);
+ }
+
+ return pid;
+}
+
+/* Kill the inferior process. Make us have no inferior. */
+
+void
+kill_inferior ()
+{
+ if (inferior_pid == 0)
+ return;
+ ptrace (8, inferior_pid, 0, 0);
+ wait (0);
+ /*************inferior_died ();****VK**************/
+}
+
+/* Return nonzero if the given thread is still alive. */
+int
+mythread_alive (pid)
+ int pid;
+{
+ return 1;
+}
+
+/* Wait for process, returns status */
+
+unsigned char
+mywait (status)
+ char *status;
+{
+ int pid;
+ union wait w;
+
+ pid = wait (&w);
+ if (pid != inferior_pid)
+ perror_with_name ("wait");
+
+ if (WIFEXITED (w))
+ {
+ fprintf (stderr, "\nChild exited with retcode = %x \n", WEXITSTATUS (w));
+ *status = 'W';
+ return ((unsigned char) WEXITSTATUS (w));
+ }
+ else if (!WIFSTOPPED (w))
+ {
+ fprintf (stderr, "\nChild terminated with signal = %x \n", WTERMSIG (w));
+ *status = 'X';
+ return ((unsigned char) WTERMSIG (w));
+ }
+
+ fetch_inferior_registers (0);
+
+ *status = 'T';
+ return ((unsigned char) WSTOPSIG (w));
+}
+
+/* Resume execution of the inferior process.
+ If STEP is nonzero, single-step it.
+ If SIGNAL is nonzero, give it that signal. */
+
+void
+myresume (step, signal)
+ int step;
+ int signal;
+{
+ errno = 0;
+ ptrace (step ? PTRACE_SINGLESTEP : PTRACE_CONT, inferior_pid, 1, signal);
+ if (errno)
+ perror_with_name ("ptrace");
+}
+
+/* Fetch one or more registers from the inferior. REGNO == -1 to get
+ them all. We actually fetch more than requested, when convenient,
+ marking them as valid so we won't fetch them again. */
+
+void
+fetch_inferior_registers (ignored)
+ int ignored;
+{
+ struct regs inferior_registers;
+ struct fp_status inferior_fp_registers;
+
+ ptrace (PTRACE_GETREGS, inferior_pid,
+ (PTRACE_ARG3_TYPE) &inferior_registers);
+#ifdef FP0_REGNUM
+ ptrace (PTRACE_GETFPREGS, inferior_pid,
+ (PTRACE_ARG3_TYPE) &inferior_fp_registers);
+#endif
+
+ memcpy (registers, &inferior_registers, 16 * 4);
+#ifdef FP0_REGNUM
+ memcpy (&registers[REGISTER_BYTE (FP0_REGNUM)], &inferior_fp_registers,
+ sizeof inferior_fp_registers.fps_regs);
+#endif
+ *(int *)&registers[REGISTER_BYTE (PS_REGNUM)] = inferior_registers.r_ps;
+ *(int *)&registers[REGISTER_BYTE (PC_REGNUM)] = inferior_registers.r_pc;
+#ifdef FP0_REGNUM
+ memcpy
+ (&registers[REGISTER_BYTE (FPC_REGNUM)],
+ &inferior_fp_registers.fps_control,
+ sizeof inferior_fp_registers - sizeof inferior_fp_registers.fps_regs);
+#endif
+}
+
+/* Store our register values back into the inferior.
+ If REGNO is -1, do this for all registers.
+ Otherwise, REGNO specifies which register (so we can save time). */
+
+void
+store_inferior_registers (ignored)
+ int ignored;
+{
+ struct regs inferior_registers;
+ struct fp_status inferior_fp_registers;
+
+ memcpy (&inferior_registers, registers, 16 * 4);
+#ifdef FP0_REGNUM
+ memcpy (&inferior_fp_registers,
+ &registers[REGISTER_BYTE (FP0_REGNUM)],
+ sizeof inferior_fp_registers.fps_regs);
+#endif
+ inferior_registers.r_ps = *(int *)&registers[REGISTER_BYTE (PS_REGNUM)];
+ inferior_registers.r_pc = *(int *)&registers[REGISTER_BYTE (PC_REGNUM)];
+
+#ifdef FP0_REGNUM
+ memcpy (&inferior_fp_registers.fps_control,
+ &registers[REGISTER_BYTE (FPC_REGNUM)],
+ (sizeof inferior_fp_registers
+ - sizeof inferior_fp_registers.fps_regs));
+#endif
+
+ ptrace (PTRACE_SETREGS, inferior_pid,
+ (PTRACE_ARG3_TYPE) &inferior_registers);
+#if FP0_REGNUM
+ ptrace (PTRACE_SETFPREGS, inferior_pid,
+ (PTRACE_ARG3_TYPE) &inferior_fp_registers);
+#endif
+}
+
+/* NOTE! I tried using PTRACE_READDATA, etc., to read and write memory
+ in the NEW_SUN_PTRACE case.
+ It ought to be straightforward. But it appears that writing did
+ not write the data that I specified. I cannot understand where
+ it got the data that it actually did write. */
+
+/* Copy LEN bytes from inferior's memory starting at MEMADDR
+ to debugger memory starting at MYADDR. */
+
+read_inferior_memory (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+{
+ register int i;
+ /* Round starting address down to longword boundary. */
+ register CORE_ADDR addr = memaddr & -sizeof (int);
+ /* Round ending address up; get number of longwords that makes. */
+ register int count
+ = (((memaddr + len) - addr) + sizeof (int) - 1) / sizeof (int);
+ /* Allocate buffer of that many longwords. */
+ register int *buffer = (int *) alloca (count * sizeof (int));
+
+ /* Read all the longwords */
+ for (i = 0; i < count; i++, addr += sizeof (int))
+ {
+ buffer[i] = ptrace (1, inferior_pid, addr, 0);
+ }
+
+ /* Copy appropriate bytes out of the buffer. */
+ memcpy (myaddr, (char *) buffer + (memaddr & (sizeof (int) - 1)), len);
+}
+
+/* Copy LEN bytes of data from debugger memory at MYADDR
+ to inferior's memory at MEMADDR.
+ On failure (cannot write the inferior)
+ returns the value of errno. */
+
+int
+write_inferior_memory (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+{
+ register int i;
+ /* Round starting address down to longword boundary. */
+ register CORE_ADDR addr = memaddr & -sizeof (int);
+ /* Round ending address up; get number of longwords that makes. */
+ register int count
+ = (((memaddr + len) - addr) + sizeof (int) - 1) / sizeof (int);
+ /* Allocate buffer of that many longwords. */
+ register int *buffer = (int *) alloca (count * sizeof (int));
+ extern int errno;
+
+ /* Fill start and end extra bytes of buffer with existing memory data. */
+
+ buffer[0] = ptrace (1, inferior_pid, addr, 0);
+
+ if (count > 1)
+ {
+ buffer[count - 1]
+ = ptrace (1, inferior_pid,
+ addr + (count - 1) * sizeof (int), 0);
+ }
+
+ /* Copy data to be written over corresponding part of buffer */
+
+ memcpy ((char *) buffer + (memaddr & (sizeof (int) - 1)), myaddr, 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;
+}
+
+void
+initialize ()
+{
+ inferior_pid = 0;
+}
+
+int
+have_inferior_p ()
+{
+ return inferior_pid != 0;
+}
diff --git a/gdb/gdbserver/remote-utils.c b/gdb/gdbserver/remote-utils.c
new file mode 100644
index 00000000000..0a7e0fbc797
--- /dev/null
+++ b/gdb/gdbserver/remote-utils.c
@@ -0,0 +1,545 @@
+/* Remote utility routines for the remote server for GDB.
+ Copyright (C) 1986, 1989, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "server.h"
+#include "terminal.h"
+#include <stdio.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/file.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <netdb.h>
+#include <netinet/tcp.h>
+#include <sys/ioctl.h>
+#include <signal.h>
+#include <fcntl.h>
+
+int remote_debug = 0;
+
+static int remote_desc;
+
+/* Open a connection to a remote debugger.
+ NAME is the filename used for communication. */
+
+void
+remote_open (name)
+ char *name;
+{
+ int save_fcntl_flags;
+
+ if (!strchr (name, ':'))
+ {
+ remote_desc = open (name, O_RDWR);
+ if (remote_desc < 0)
+ perror_with_name ("Could not open remote device");
+
+#ifdef HAVE_TERMIOS
+ {
+ struct termios termios;
+ tcgetattr(remote_desc, &termios);
+
+ termios.c_iflag = 0;
+ termios.c_oflag = 0;
+ termios.c_lflag = 0;
+ termios.c_cflag &= ~(CSIZE|PARENB);
+ termios.c_cflag |= CLOCAL | CS8;
+ termios.c_cc[VMIN] = 0;
+ termios.c_cc[VTIME] = 0;
+
+ tcsetattr(remote_desc, TCSANOW, &termios);
+ }
+#endif
+
+#ifdef HAVE_TERMIO
+ {
+ struct termio termio;
+ ioctl (remote_desc, TCGETA, &termio);
+
+ termio.c_iflag = 0;
+ termio.c_oflag = 0;
+ termio.c_lflag = 0;
+ termio.c_cflag &= ~(CSIZE|PARENB);
+ termio.c_cflag |= CLOCAL | CS8;
+ termio.c_cc[VMIN] = 0;
+ termio.c_cc[VTIME] = 0;
+
+ ioctl (remote_desc, TCSETA, &termio);
+ }
+#endif
+
+#ifdef HAVE_SGTTY
+ {
+ struct sgttyb sg;
+
+ ioctl (remote_desc, TIOCGETP, &sg);
+ sg.sg_flags = RAW;
+ ioctl (remote_desc, TIOCSETP, &sg);
+ }
+#endif
+
+
+ }
+ else
+ {
+ char *port_str;
+ int port;
+ struct sockaddr_in sockaddr;
+ int tmp;
+ struct protoent *protoent;
+ int tmp_desc;
+
+ port_str = strchr (name, ':');
+
+ port = atoi (port_str + 1);
+
+ tmp_desc = socket (PF_INET, SOCK_STREAM, 0);
+ if (tmp_desc < 0)
+ perror_with_name ("Can't open socket");
+
+ /* Allow rapid reuse of this port. */
+ tmp = 1;
+ setsockopt (tmp_desc, SOL_SOCKET, SO_REUSEADDR, (char *)&tmp,
+ sizeof(tmp));
+
+ sockaddr.sin_family = PF_INET;
+ sockaddr.sin_port = htons(port);
+ sockaddr.sin_addr.s_addr = INADDR_ANY;
+
+ if (bind (tmp_desc, (struct sockaddr *)&sockaddr, sizeof (sockaddr))
+ || listen (tmp_desc, 1))
+ perror_with_name ("Can't bind address");
+
+ tmp = sizeof (sockaddr);
+ remote_desc = accept (tmp_desc, (struct sockaddr *)&sockaddr, &tmp);
+ if (remote_desc == -1)
+ perror_with_name ("Accept failed");
+
+ protoent = getprotobyname ("tcp");
+ if (!protoent)
+ perror_with_name ("getprotobyname");
+
+ /* Enable TCP keep alive process. */
+ tmp = 1;
+ setsockopt (tmp_desc, SOL_SOCKET, SO_KEEPALIVE, (char *)&tmp, sizeof(tmp));
+
+ /* Tell TCP not to delay small packets. This greatly speeds up
+ interactive response. */
+ tmp = 1;
+ setsockopt (remote_desc, protoent->p_proto, TCP_NODELAY,
+ (char *)&tmp, sizeof(tmp));
+
+ close (tmp_desc); /* No longer need this */
+
+ signal (SIGPIPE, SIG_IGN); /* If we don't do this, then gdbserver simply
+ exits when the remote side dies. */
+ }
+
+#if defined(F_SETFL) && defined (FASYNC)
+ save_fcntl_flags = fcntl (remote_desc, F_GETFL, 0);
+ fcntl (remote_desc, F_SETFL, save_fcntl_flags | FASYNC);
+ disable_async_io ();
+#endif /* FASYNC */
+ fprintf (stderr, "Remote debugging using %s\n", name);
+}
+
+void
+remote_close()
+{
+ close (remote_desc);
+}
+
+/* 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");
+}
+
+/* Convert number NIB to a hex digit. */
+
+static int
+tohex (nib)
+ int nib;
+{
+ if (nib < 10)
+ return '0' + nib;
+ else
+ return 'a' + nib - 10;
+}
+
+/* Send a packet to the remote machine, with error checking.
+ The data of the packet is in BUF. Returns >= 0 on success, -1 otherwise. */
+
+int
+putpkt (buf)
+ char *buf;
+{
+ int i;
+ unsigned char csum = 0;
+ char buf2[2000];
+ char buf3[1];
+ int cnt = strlen (buf);
+ char *p;
+
+ /* Copy the packet into buffer BUF2, encapsulating it
+ and giving it a checksum. */
+
+ p = buf2;
+ *p++ = '$';
+
+ for (i = 0; i < cnt; i++)
+ {
+ csum += buf[i];
+ *p++ = buf[i];
+ }
+ *p++ = '#';
+ *p++ = tohex ((csum >> 4) & 0xf);
+ *p++ = tohex (csum & 0xf);
+
+ *p = '\0';
+
+ /* Send it over and over until we get a positive ack. */
+
+ do
+ {
+ int cc;
+
+ if (write (remote_desc, buf2, p - buf2) != p - buf2)
+ {
+ perror ("putpkt(write)");
+ return -1;
+ }
+
+ if (remote_debug)
+ printf ("putpkt (\"%s\"); [looking for ack]\n", buf2);
+ cc = read (remote_desc, buf3, 1);
+ if (remote_debug)
+ printf ("[received '%c' (0x%x)]\n", buf3[0], buf3[0]);
+ if (cc <= 0)
+ {
+ if (cc == 0)
+ fprintf (stderr, "putpkt(read): Got EOF\n");
+ else
+ perror ("putpkt(read)");
+
+ return -1;
+ }
+ }
+ while (buf3[0] != '+');
+
+ return 1; /* Success! */
+}
+
+/* Come here when we get an input interrupt from the remote side. This
+ interrupt should only be active while we are waiting for the child to do
+ something. About the only thing that should come through is a ^C, which
+ will cause us to send a SIGINT to the child. */
+
+static void
+input_interrupt()
+{
+ int cc;
+ char c;
+
+ cc = read (remote_desc, &c, 1);
+
+ if (cc != 1 || c != '\003')
+ {
+ fprintf(stderr, "input_interrupt, cc = %d c = %d\n", cc, c);
+ return;
+ }
+
+ kill (inferior_pid, SIGINT);
+}
+
+void
+enable_async_io()
+{
+ signal (SIGIO, input_interrupt);
+}
+
+void
+disable_async_io()
+{
+ signal (SIGIO, SIG_IGN);
+}
+
+/* Returns next char from remote GDB. -1 if error. */
+
+static int
+readchar ()
+{
+ static char buf[BUFSIZ];
+ static int bufcnt = 0;
+ static char *bufp;
+
+ if (bufcnt-- > 0)
+ return *bufp++ & 0x7f;
+
+ bufcnt = read (remote_desc, buf, sizeof (buf));
+
+ if (bufcnt <= 0)
+ {
+ if (bufcnt == 0)
+ fprintf (stderr, "readchar: Got EOF\n");
+ else
+ perror ("readchar");
+
+ return -1;
+ }
+
+ bufp = buf;
+ bufcnt--;
+ return *bufp++ & 0x7f;
+}
+
+/* Read a packet from the remote machine, with error checking,
+ and store it in BUF. Returns length of packet, or negative if error. */
+
+int
+getpkt (buf)
+ char *buf;
+{
+ char *bp;
+ unsigned char csum, c1, c2;
+ int c;
+
+ while (1)
+ {
+ csum = 0;
+
+ while (1)
+ {
+ c = readchar ();
+ if (c == '$')
+ break;
+ if (remote_debug)
+ printf ("[getpkt: discarding char '%c']\n", c);
+ if (c < 0)
+ return -1;
+ }
+
+ bp = buf;
+ while (1)
+ {
+ c = readchar ();
+ if (c < 0)
+ return -1;
+ if (c == '#')
+ break;
+ *bp++ = c;
+ csum += c;
+ }
+ *bp = 0;
+
+ c1 = fromhex (readchar ());
+ c2 = fromhex (readchar ());
+
+ if (csum == (c1 << 4) + c2)
+ break;
+
+ fprintf (stderr, "Bad checksum, sentsum=0x%x, csum=0x%x, buf=%s\n",
+ (c1 << 4) + c2, csum, buf);
+ write (remote_desc, "-", 1);
+ }
+
+ if (remote_debug)
+ printf ("getpkt (\"%s\"); [sending ack] \n", buf);
+
+ write (remote_desc, "+", 1);
+
+ if (remote_debug)
+ printf ("[sent ack]\n");
+ return bp - buf;
+}
+
+void
+write_ok (buf)
+ char *buf;
+{
+ buf[0] = 'O';
+ buf[1] = 'K';
+ buf[2] = '\0';
+}
+
+void
+write_enn (buf)
+ char *buf;
+{
+ buf[0] = 'E';
+ buf[1] = 'N';
+ buf[2] = 'N';
+ buf[3] = '\0';
+}
+
+void
+convert_int_to_ascii (from, to, n)
+ char *from, *to;
+ int n;
+{
+ int nib;
+ char ch;
+ while (n--)
+ {
+ ch = *from++;
+ nib = ((ch & 0xf0) >> 4) & 0x0f;
+ *to++ = tohex (nib);
+ nib = ch & 0x0f;
+ *to++ = tohex (nib);
+ }
+ *to++ = 0;
+}
+
+
+void
+convert_ascii_to_int (from, to, n)
+ char *from, *to;
+ int n;
+{
+ int nib1, nib2;
+ while (n--)
+ {
+ nib1 = fromhex (*from++);
+ nib2 = fromhex (*from++);
+ *to++ = (((nib1 & 0x0f) << 4) & 0xf0) | (nib2 & 0x0f);
+ }
+}
+
+static char *
+outreg(regno, buf)
+ int regno;
+ char *buf;
+{
+ extern char registers[];
+ int regsize = REGISTER_RAW_SIZE (regno);
+
+ *buf++ = tohex (regno >> 4);
+ *buf++ = tohex (regno & 0xf);
+ *buf++ = ':';
+ convert_int_to_ascii (&registers[REGISTER_BYTE (regno)], buf, regsize);
+ buf += 2 * regsize;
+ *buf++ = ';';
+
+ return buf;
+}
+
+void
+prepare_resume_reply (buf, status, signo)
+ char *buf;
+ char status;
+ unsigned char signo;
+{
+ int nib;
+
+ *buf++ = status;
+
+ /* FIXME! Should be converting this signal number (numbered
+ according to the signal numbering of the system we are running on)
+ to the signal numbers used by the gdb protocol (see enum target_signal
+ in gdb/target.h). */
+ nib = ((signo & 0xf0) >> 4);
+ *buf++ = tohex (nib);
+ nib = signo & 0x0f;
+ *buf++ = tohex (nib);
+
+ if (status == 'T')
+ {
+ buf = outreg (PC_REGNUM, buf);
+ buf = outreg (FP_REGNUM, buf);
+ buf = outreg (SP_REGNUM, buf);
+#ifdef NPC_REGNUM
+ buf = outreg (NPC_REGNUM, buf);
+#endif
+#ifdef O7_REGNUM
+ buf = outreg (O7_REGNUM, buf);
+#endif
+
+ /* If the debugger hasn't used any thread features, don't burden it with
+ threads. If we didn't check this, GDB 4.13 and older would choke. */
+ if (cont_thread != 0)
+ {
+ if (old_thread_from_wait != thread_from_wait)
+ {
+ sprintf (buf, "thread:%x;", thread_from_wait);
+ buf += strlen (buf);
+ old_thread_from_wait = thread_from_wait;
+ }
+ }
+ }
+ /* For W and X, we're done. */
+ *buf++ = 0;
+}
+
+void
+decode_m_packet (from, mem_addr_ptr, len_ptr)
+ char *from;
+ CORE_ADDR *mem_addr_ptr;
+ unsigned int *len_ptr;
+{
+ int i = 0, j = 0;
+ char ch;
+ *mem_addr_ptr = *len_ptr = 0;
+
+ while ((ch = from[i++]) != ',')
+ {
+ *mem_addr_ptr = *mem_addr_ptr << 4;
+ *mem_addr_ptr |= fromhex (ch) & 0x0f;
+ }
+
+ for (j = 0; j < 4; j++)
+ {
+ if ((ch = from[i++]) == 0)
+ break;
+ *len_ptr = *len_ptr << 4;
+ *len_ptr |= fromhex (ch) & 0x0f;
+ }
+}
+
+void
+decode_M_packet (from, mem_addr_ptr, len_ptr, to)
+ char *from, *to;
+ CORE_ADDR *mem_addr_ptr;
+ unsigned int *len_ptr;
+{
+ int i = 0;
+ char ch;
+ *mem_addr_ptr = *len_ptr = 0;
+
+ while ((ch = from[i++]) != ',')
+ {
+ *mem_addr_ptr = *mem_addr_ptr << 4;
+ *mem_addr_ptr |= fromhex (ch) & 0x0f;
+ }
+
+ while ((ch = from[i++]) != ':')
+ {
+ *len_ptr = *len_ptr << 4;
+ *len_ptr |= fromhex (ch) & 0x0f;
+ }
+
+ convert_ascii_to_int (&from[i++], to, *len_ptr);
+}
diff --git a/gdb/gdbserver/server.c b/gdb/gdbserver/server.c
new file mode 100644
index 00000000000..cdec0f8a931
--- /dev/null
+++ b/gdb/gdbserver/server.c
@@ -0,0 +1,258 @@
+/* Main code for remote server for GDB.
+ Copyright (C) 1989, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "server.h"
+
+int cont_thread;
+int general_thread;
+int thread_from_wait;
+int old_thread_from_wait;
+int extended_protocol;
+jmp_buf toplevel;
+int inferior_pid;
+
+static unsigned char
+start_inferior (argv, statusptr)
+ char *argv[];
+ char *statusptr;
+{
+ inferior_pid = create_inferior (argv[0], argv);
+ fprintf (stderr, "Process %s created; pid = %d\n", argv[0], inferior_pid);
+
+ /* Wait till we are at 1st instruction in program, return signal number. */
+ return mywait (statusptr);
+}
+
+extern int remote_debug;
+
+int
+main (argc, argv)
+ int argc;
+ char *argv[];
+{
+ char ch, status, own_buf[2000], mem_buf[2000];
+ int i = 0;
+ unsigned char signal;
+ unsigned int len;
+ CORE_ADDR mem_addr;
+
+ if (setjmp(toplevel))
+ {
+ fprintf(stderr, "Exiting\n");
+ exit(1);
+ }
+
+ if (argc < 3)
+ error("Usage: gdbserver tty prog [args ...]");
+
+ /* Wait till we are at first instruction in program. */
+ signal = start_inferior (&argv[2], &status);
+
+ /* We are now stopped at the first instruction of the target process */
+
+ while (1)
+ {
+ remote_open (argv[1]);
+
+restart:
+ setjmp(toplevel);
+ while (getpkt (own_buf) > 0)
+ {
+ unsigned char sig;
+ i = 0;
+ ch = own_buf[i++];
+ switch (ch)
+ {
+ case 'd':
+ remote_debug = !remote_debug;
+ break;
+ case '!':
+ extended_protocol = 1;
+ prepare_resume_reply (own_buf, status, signal);
+ break;
+ case '?':
+ prepare_resume_reply (own_buf, status, signal);
+ break;
+ case 'H':
+ switch (own_buf[1])
+ {
+ case 'g':
+ general_thread = strtol (&own_buf[2], NULL, 16);
+ write_ok (own_buf);
+ fetch_inferior_registers (0);
+ break;
+ case 'c':
+ cont_thread = strtol (&own_buf[2], NULL, 16);
+ write_ok (own_buf);
+ break;
+ default:
+ /* Silently ignore it so that gdb can extend the protocol
+ without compatibility headaches. */
+ own_buf[0] = '\0';
+ break;
+ }
+ break;
+ case 'g':
+ convert_int_to_ascii (registers, own_buf, REGISTER_BYTES);
+ break;
+ case 'G':
+ convert_ascii_to_int (&own_buf[1], registers, REGISTER_BYTES);
+ store_inferior_registers (-1);
+ write_ok (own_buf);
+ break;
+ case 'm':
+ decode_m_packet (&own_buf[1], &mem_addr, &len);
+ read_inferior_memory (mem_addr, mem_buf, len);
+ convert_int_to_ascii (mem_buf, own_buf, len);
+ break;
+ case 'M':
+ decode_M_packet (&own_buf[1], &mem_addr, &len, mem_buf);
+ if (write_inferior_memory (mem_addr, mem_buf, len) == 0)
+ write_ok (own_buf);
+ else
+ write_enn (own_buf);
+ break;
+ case 'C':
+ convert_ascii_to_int (own_buf + 1, &sig, 1);
+ myresume (0, sig);
+ signal = mywait (&status);
+ prepare_resume_reply (own_buf, status, signal);
+ break;
+ case 'S':
+ convert_ascii_to_int (own_buf + 1, &sig, 1);
+ myresume (1, sig);
+ signal = mywait (&status);
+ prepare_resume_reply (own_buf, status, signal);
+ break;
+ case 'c':
+ myresume (0, 0);
+ signal = mywait (&status);
+ prepare_resume_reply (own_buf, status, signal);
+ break;
+ case 's':
+ myresume (1, 0);
+ signal = mywait (&status);
+ prepare_resume_reply (own_buf, status, signal);
+ break;
+ case 'k':
+ fprintf (stderr, "Killing inferior\n");
+ kill_inferior ();
+ /* When using the extended protocol, we start up a new
+ debugging session. The traditional protocol will
+ exit instead. */
+ if (extended_protocol)
+ {
+ write_ok (own_buf);
+ fprintf (stderr, "GDBserver restarting\n");
+
+ /* Wait till we are at 1st instruction in prog. */
+ signal = start_inferior (&argv[2], &status);
+ goto restart;
+ break;
+ }
+ else
+ {
+ exit (0);
+ break;
+ }
+ case 'T':
+ if (mythread_alive (strtol (&own_buf[1], NULL, 16)))
+ write_ok (own_buf);
+ else
+ write_enn (own_buf);
+ break;
+ case 'R':
+ /* Restarting the inferior is only supported in the
+ extended protocol. */
+ if (extended_protocol)
+ {
+ kill_inferior ();
+ write_ok (own_buf);
+ fprintf (stderr, "GDBserver restarting\n");
+
+ /* Wait till we are at 1st instruction in prog. */
+ signal = start_inferior (&argv[2], &status);
+ goto restart;
+ break;
+ }
+ else
+ {
+ /* It is a request we don't understand. Respond with an
+ empty packet so that gdb knows that we don't support this
+ request. */
+ own_buf[0] = '\0';
+ break;
+ }
+ default:
+ /* It is a request we don't understand. Respond with an
+ empty packet so that gdb knows that we don't support this
+ request. */
+ own_buf[0] = '\0';
+ break;
+ }
+
+ putpkt (own_buf);
+
+ if (status == 'W')
+ fprintf (stderr,
+ "\nChild exited with status %d\n", sig);
+ if (status == 'X')
+ fprintf (stderr, "\nChild terminated with signal = 0x%x\n", sig);
+ if (status == 'W' || status == 'X')
+ {
+ if (extended_protocol)
+ {
+ fprintf (stderr, "Killing inferior\n");
+ kill_inferior ();
+ write_ok (own_buf);
+ fprintf (stderr, "GDBserver restarting\n");
+
+ /* Wait till we are at 1st instruction in prog. */
+ signal = start_inferior (&argv[2], &status);
+ goto restart;
+ break;
+ }
+ else
+ {
+ fprintf (stderr, "GDBserver exiting\n");
+ exit (0);
+ }
+ }
+ }
+
+ /* We come here when getpkt fails.
+
+ For the extended remote protocol we exit (and this is the only
+ way we gracefully exit!).
+
+ For the traditional remote protocol close the connection,
+ and re-open it at the top of the loop. */
+ if (extended_protocol)
+ {
+ remote_close ();
+ exit (0);
+ }
+ else
+ {
+ fprintf (stderr, "Remote side has terminated connection. GDBserver will reopen the connection.\n");
+
+ remote_close ();
+ }
+ }
+}
diff --git a/gdb/gdbserver/server.h b/gdb/gdbserver/server.h
new file mode 100644
index 00000000000..e23c773a60b
--- /dev/null
+++ b/gdb/gdbserver/server.h
@@ -0,0 +1,72 @@
+/* Common definitions for remote server for GDB.
+ Copyright (C) 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include <setjmp.h>
+
+/* Target-specific functions */
+
+int create_inferior PARAMS ((char *program, char **allargs));
+void kill_inferior PARAMS ((void));
+void fetch_inferior_registers PARAMS ((int regno));
+void store_inferior_registers PARAMS ((int regno));
+int mythread_alive PARAMS ((int pid));
+void myresume PARAMS ((int step, int signo));
+unsigned char mywait PARAMS ((char *status));
+void read_inferior_memory PARAMS ((CORE_ADDR memaddr, char *myaddr, int len));
+int write_inferior_memory PARAMS ((CORE_ADDR memaddr, char *myaddr, int len));
+int create_inferior ();
+
+/* Target-specific variables */
+
+extern char registers[];
+
+/* Public variables in server.c */
+
+extern int cont_thread;
+extern int general_thread;
+extern int thread_from_wait;
+extern int old_thread_from_wait;
+
+extern jmp_buf toplevel;
+extern int inferior_pid;
+
+/* Functions from remote-utils.c */
+
+int putpkt PARAMS ((char *buf));
+int getpkt PARAMS ((char *buf));
+void remote_open PARAMS ((char *name));
+void remote_close PARAMS ((void));
+void write_ok PARAMS ((char *buf));
+void write_enn PARAMS ((char *buf));
+void enable_async_io PARAMS ((void));
+void disable_async_io PARAMS ((void));
+void convert_ascii_to_int PARAMS ((char *from, char *to, int n));
+void convert_int_to_ascii PARAMS ((char *from, char *to, int n));
+void prepare_resume_reply PARAMS ((char *buf, char status, unsigned char sig));
+
+void decode_m_packet PARAMS ((char *from, CORE_ADDR *mem_addr_ptr,
+ unsigned int *len_ptr));
+void decode_M_packet PARAMS ((char *from, CORE_ADDR *mem_addr_ptr,
+ unsigned int *len_ptr, char *to));
+
+
+/* Functions from utils.c */
+
+void perror_with_name PARAMS ((char *string));
diff --git a/gdb/gdbserver/utils.c b/gdb/gdbserver/utils.c
new file mode 100644
index 00000000000..63d522c95a9
--- /dev/null
+++ b/gdb/gdbserver/utils.c
@@ -0,0 +1,114 @@
+/* General utility routines for the remote server for GDB.
+ Copyright (C) 1986, 1989, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "server.h"
+#include <stdio.h>
+#include <string.h>
+
+/* Generally useful subroutines used throughout the program. */
+
+/* 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 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. */
+
+#ifdef ANSI_PROTOTYPES
+NORETURN void
+error (const char *string, ...)
+#else
+void
+error (va_alist)
+ va_dcl
+#endif
+{
+ extern jmp_buf toplevel;
+ va_list args;
+#ifdef ANSI_PROTOTYPES
+ va_start (args, string);
+#else
+ va_start (args);
+#endif
+ fflush (stdout);
+#ifdef ANSI_PROTOTYPES
+ vfprintf (stderr, string, args);
+#else
+ {
+ char *string1;
+
+ string1 = va_arg (args, char *);
+ vfprintf (stderr, string1, args);
+ }
+#endif
+ fprintf (stderr, "\n");
+ longjmp(toplevel, 1);
+}
+
+/* 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. */
+
+/* VARARGS */
+NORETURN void
+#ifdef ANSI_PROTOTYPES
+fatal (char *string, ...)
+#else
+fatal (va_alist)
+ va_dcl
+#endif
+{
+ va_list args;
+#ifdef ANSI_PROTOTYPES
+ va_start (args, string);
+#else
+ char *string;
+ va_start (args);
+ string = va_arg (args, char *);
+#endif
+ fprintf (stderr, "gdb: ");
+ vfprintf (stderr, string, args);
+ fprintf (stderr, "\n");
+ va_end (args);
+ exit (1);
+}
diff --git a/gdb/gdbthread.h b/gdb/gdbthread.h
new file mode 100644
index 00000000000..653dd65c16a
--- /dev/null
+++ b/gdb/gdbthread.h
@@ -0,0 +1,121 @@
+/* Multi-process/thread control defs for GDB, the GNU debugger.
+ Copyright 1987, 88, 89, 90, 91, 92, 1993, 1998
+
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef GDBTHREAD_H
+#define GDBTHREAD_H
+
+/* For bpstat */
+#include "breakpoint.h"
+
+extern void init_thread_list PARAMS ((void));
+
+extern void add_thread PARAMS ((int pid));
+
+extern void delete_thread PARAMS ((int));
+
+extern int thread_id_to_pid PARAMS ((int));
+
+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));
+
+extern void load_infrun_state PARAMS ((int, CORE_ADDR *, CORE_ADDR *, char **,
+ int *, struct breakpoint **,
+ struct breakpoint **, CORE_ADDR *,
+ CORE_ADDR *, CORE_ADDR *, int *, int *,
+ int *, bpstat *, int *));
+
+extern void save_infrun_state PARAMS ((int, CORE_ADDR, CORE_ADDR, char *,
+ int, struct breakpoint *,
+ struct breakpoint *, CORE_ADDR,
+ CORE_ADDR, CORE_ADDR, int, int,
+ int, bpstat, int));
+
+/* Commands with a prefix of `thread'. */
+extern struct cmd_list_element *thread_cmd_list;
+
+/* Support for external (remote) systems with threads (processes) */
+/* For example real time operating systems */
+
+#define OPAQUETHREADBYTES 8
+/* a 64 bit opaque identifier */
+typedef unsigned char threadref[OPAQUETHREADBYTES] ;
+/* WARNING: This threadref data structure comes from the remote O.S., libstub
+ protocol encoding, and remote.c. it is not particularly changable */
+
+/* Right now, the internal structure is int. We want it to be bigger.
+ Plan to fix this.
+ */
+typedef int gdb_threadref ; /* internal GDB thread reference */
+
+/* gdb_ext_thread_info is an internal GDB data structure which is
+ equivalint to the reply of the remote threadinfo packet */
+
+struct gdb_ext_thread_info
+{
+ threadref threadid ; /* External form of thread reference */
+ int active ; /* Has state interesting to GDB? , regs, stack */
+ char display[256] ; /* Brief state display, name, blocked/syspended */
+ char shortname[32] ; /* To be used to name threads */
+ char more_display[256] ; /* Long info, statistics, queue depth, whatever */
+} ;
+
+/* The volume of remote transfers can be limited by submitting
+ a mask containing bits specifying the desired information.
+ Use a union of these values as the 'selection' parameter to
+ get_thread_info. FIXME: Make these TAG names more thread specific.
+ */
+#define TAG_THREADID 1
+#define TAG_EXISTS 2
+#define TAG_DISPLAY 4
+#define TAG_THREADNAME 8
+#define TAG_MOREDISPLAY 16
+
+/* Always initialize an instance of this structure using run time assignments */
+/* Because we are likely to add entrtries to it. */
+/* Alternatly, WE COULD ADD THESE TO THE TARGET VECTOR */
+
+struct target_thread_vector
+{
+ int (*find_new_threads)PARAMS((void)) ;
+ int (*get_thread_info) PARAMS((
+ gdb_threadref * ref,
+ int selection,
+ struct gdb_ext_thread_info * info
+ )) ;
+ /* to_thread_alive - Already in the target vector */
+ /* to_switch_thread - Done via select frame */
+} ;
+
+extern void bind_target_thread_vector PARAMS((struct target_thread_vector * vec)) ;
+
+extern struct target_thread_vector * unbind_target_thread_vector PARAMS ((void)) ;
+
+extern int target_get_thread_info PARAMS((
+ gdb_threadref * ref,
+ int selection,
+ struct gdb_ext_thread_info * info)) ;
+
+
+#endif /* GDBTHREAD_H */
diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c
new file mode 100644
index 00000000000..03934623d19
--- /dev/null
+++ b/gdb/gdbtypes.c
@@ -0,0 +1,2905 @@
+/* Support routines for manipulating internal types for GDB.
+ Copyright (C) 1992, 93, 94, 95, 96, 1998 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "gdb_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"
+#include "gdbcmd.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;
+struct type *builtin_type_int8;
+struct type *builtin_type_uint8;
+struct type *builtin_type_int16;
+struct type *builtin_type_uint16;
+struct type *builtin_type_int32;
+struct type *builtin_type_uint32;
+struct type *builtin_type_int64;
+struct type *builtin_type_uint64;
+struct type *builtin_type_bool;
+
+int opaque_type_resolution = 1;
+
+
+struct extra { char str[128]; int len; }; /* maximum extention is 128! FIXME */
+
+static void add_name PARAMS ((struct extra *, char *));
+static void add_mangled_type PARAMS ((struct extra *, struct type *));
+#if 0
+static void cfront_mangle_name PARAMS ((struct type *, int, int));
+#endif
+static void print_bit_vector PARAMS ((B_TYPE *, int));
+static void print_arg_types PARAMS ((struct type **, int));
+static void dump_fn_fieldlists PARAMS ((struct type *, int));
+static void print_cplus_stuff PARAMS ((struct type *, int));
+
+/* 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));
+ OBJSTAT (objfile, n_types++);
+ }
+ 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;
+ TYPE_CV_TYPE (type) = type; /* chain back to itself */
+
+ 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;
+
+ 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_LENGTH (ntype) = 1;
+ TYPE_CODE (ntype) = TYPE_CODE_FUNC;
+
+ 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);
+}
+
+
+/* Make a "c-v" variant of a type -- a type that is identical to the
+ one supplied except that it may have const or volatile attributes
+ CNST is a flag for setting the const attribute
+ VOLTL is a flag for setting the volatile attribute
+ TYPE is the base type whose variant we are creating.
+ 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_cv_type (cnst, voltl, type, typeptr)
+ int cnst;
+ int voltl;
+ struct type *type;
+ struct type **typeptr;
+{
+ register struct type *ntype; /* New type */
+ register struct type *tmp_type = type; /* tmp type */
+ struct objfile *objfile;
+
+ ntype = TYPE_CV_TYPE (type);
+
+ while (ntype != type)
+ {
+ if ((TYPE_CONST (ntype) == cnst) &&
+ (TYPE_VOLATILE (ntype) == voltl))
+ {
+ if (typeptr == 0)
+ return ntype;
+ else if (*typeptr == 0)
+ {
+ *typeptr = ntype; /* Tracking alloc, and we have new type. */
+ return ntype;
+ }
+ }
+ tmp_type = ntype;
+ ntype = TYPE_CV_TYPE (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;
+ }
+
+ /* Copy original type */
+ memcpy ((char *) ntype, (char *) type, sizeof (struct type));
+ /* But zero out fields that shouldn't be copied */
+ TYPE_POINTER_TYPE (ntype) = (struct type *) 0; /* Need new pointer kind */
+ TYPE_REFERENCE_TYPE (ntype) = (struct type *) 0; /* Need new referene kind */
+ /* Note: TYPE_TARGET_TYPE can be left as is */
+
+ /* Set flags appropriately */
+ if (cnst)
+ TYPE_FLAGS (ntype) |= TYPE_FLAG_CONST;
+ else
+ TYPE_FLAGS (ntype) &= ~TYPE_FLAG_CONST;
+
+ if (voltl)
+ TYPE_FLAGS (ntype) |= TYPE_FLAG_VOLATILE;
+ else
+ TYPE_FLAGS (ntype) &= ~TYPE_FLAG_VOLATILE;
+
+ /* Fix the chain of cv variants */
+ TYPE_CV_TYPE (ntype) = type;
+ TYPE_CV_TYPE (tmp_type) = ntype;
+
+ return ntype;
+}
+
+
+
+
+/* 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;
+ if (TYPE_FLAGS (index_type) & TYPE_FLAG_STUB)
+ TYPE_FLAGS (result_type) |= TYPE_FLAG_TARGET_STUB;
+ else
+ TYPE_LENGTH (result_type) = TYPE_LENGTH (check_typedef (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 */
+
+ if(low_bound >= 0)
+ TYPE_FLAGS (result_type) |= TYPE_FLAG_UNSIGNED;
+
+ return (result_type);
+}
+
+/* Set *LOWP and *HIGHP to the lower and upper bounds of discrete type TYPE.
+ Return 1 of type is a range type, 0 if it is discrete (and bounds
+ will fit in LONGEST), or -1 otherwise. */
+
+int
+get_discrete_bounds (type, lowp, highp)
+ struct type *type;
+ LONGEST *lowp, *highp;
+{
+ CHECK_TYPEDEF (type);
+ switch (TYPE_CODE (type))
+ {
+ case TYPE_CODE_RANGE:
+ *lowp = TYPE_LOW_BOUND (type);
+ *highp = TYPE_HIGH_BOUND (type);
+ return 1;
+ case TYPE_CODE_ENUM:
+ if (TYPE_NFIELDS (type) > 0)
+ {
+ /* The enums may not be sorted by value, so search all
+ entries */
+ int i;
+
+ *lowp = *highp = TYPE_FIELD_BITPOS (type, 0);
+ for (i = 0; i < TYPE_NFIELDS (type); i++)
+ {
+ if (TYPE_FIELD_BITPOS (type, i) < *lowp)
+ *lowp = TYPE_FIELD_BITPOS (type, i);
+ if (TYPE_FIELD_BITPOS (type, i) > *highp)
+ *highp = TYPE_FIELD_BITPOS (type, i);
+ }
+
+ /* Set unsigned indicator if warranted. */
+ if(*lowp >= 0)
+ {
+ TYPE_FLAGS (type) |= TYPE_FLAG_UNSIGNED;
+ }
+ }
+ else
+ {
+ *lowp = 0;
+ *highp = -1;
+ }
+ return 0;
+ case TYPE_CODE_BOOL:
+ *lowp = 0;
+ *highp = 1;
+ return 0;
+ case TYPE_CODE_INT:
+ if (TYPE_LENGTH (type) > sizeof (LONGEST)) /* Too big */
+ return -1;
+ if (!TYPE_UNSIGNED (type))
+ {
+ *lowp = - (1 << (TYPE_LENGTH (type) * TARGET_CHAR_BIT - 1));
+ *highp = -*lowp - 1;
+ return 0;
+ }
+ /* ... fall through for unsigned ints ... */
+ case TYPE_CODE_CHAR:
+ *lowp = 0;
+ /* This round-about calculation is to avoid shifting by
+ TYPE_LENGTH (type) * TARGET_CHAR_BIT, which will not work
+ if TYPE_LENGTH (type) == sizeof (LONGEST). */
+ *highp = 1 << (TYPE_LENGTH (type) * TARGET_CHAR_BIT - 1);
+ *highp = (*highp - 1) | *highp;
+ return 0;
+ default:
+ return -1;
+ }
+}
+
+/* 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;
+{
+ LONGEST low_bound, high_bound;
+
+ 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;
+ if (get_discrete_bounds (range_type, &low_bound, &high_bound) < 0)
+ low_bound = high_bound = 0;
+ CHECK_TYPEDEF (element_type);
+ 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;
+
+ /* TYPE_FLAG_TARGET_STUB will take care of zero length arrays */
+ if (TYPE_LENGTH (result_type) == 0)
+ TYPE_FLAGS (result_type) |= TYPE_FLAG_TARGET_STUB;
+
+ 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,
+ *current_language->string_char_type,
+ range_type);
+ TYPE_CODE (result_type) = TYPE_CODE_STRING;
+ return (result_type);
+}
+
+struct type *
+create_set_type (result_type, domain_type)
+ struct type *result_type;
+ struct type *domain_type;
+{
+ LONGEST low_bound, high_bound, bit_length;
+ if (result_type == NULL)
+ {
+ result_type = alloc_type (TYPE_OBJFILE (domain_type));
+ }
+ TYPE_CODE (result_type) = TYPE_CODE_SET;
+ TYPE_NFIELDS (result_type) = 1;
+ TYPE_FIELDS (result_type) = (struct field *)
+ TYPE_ALLOC (result_type, 1 * sizeof (struct field));
+ memset (TYPE_FIELDS (result_type), 0, sizeof (struct field));
+
+ if (! (TYPE_FLAGS (domain_type) & TYPE_FLAG_STUB))
+ {
+ if (get_discrete_bounds (domain_type, &low_bound, &high_bound) < 0)
+ low_bound = high_bound = 0;
+ bit_length = high_bound - low_bound + 1;
+ TYPE_LENGTH (result_type)
+ = (bit_length + TARGET_CHAR_BIT - 1) / TARGET_CHAR_BIT;
+ }
+ TYPE_FIELD_TYPE (result_type, 0) = domain_type;
+
+ if(low_bound >= 0)
+ TYPE_FLAGS (result_type) |= TYPE_FLAG_UNSIGNED;
+
+ 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;
+ struct type * t;
+
+ sym = lookup_symbol (name, block, STRUCT_NAMESPACE, 0,
+ (struct symtab **) NULL);
+
+ if (sym == NULL)
+ error ("No union type named %s.", name);
+
+ t = SYMBOL_TYPE(sym);
+
+ if (TYPE_CODE (t) == TYPE_CODE_UNION)
+ return (t);
+
+ /* C++ unions may come out with TYPE_CODE_CLASS, but we look at
+ * a further "declared_type" field to discover it is really a union.
+ */
+ if (HAVE_CPLUS_STRUCT (t))
+ if (TYPE_DECLARED_TYPE(t) == DECLARED_TYPE_UNION)
+ return (t);
+
+ /* If we get here, it's not a union */
+ error ("This context has class, struct or enum %s, not a union.", name);
+}
+
+
+/* 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;
+
+ for (;;)
+ {
+ CHECK_TYPEDEF (type);
+ if (TYPE_CODE (type) != TYPE_CODE_PTR
+ && TYPE_CODE (type) != TYPE_CODE_REF)
+ break;
+ type = TYPE_TARGET_TYPE (type);
+ }
+
+ if (TYPE_CODE (type) != TYPE_CODE_STRUCT &&
+ TYPE_CODE (type) != TYPE_CODE_UNION)
+ {
+ target_terminal_ours ();
+ gdb_flush (gdb_stdout);
+ fprintf_unfiltered (gdb_stderr, "Type ");
+ type_print (type, "", gdb_stderr, -1);
+ error (" is not a structure or union 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 ();
+ gdb_flush (gdb_stdout);
+ fprintf_unfiltered (gdb_stderr, "Type ");
+ type_print (type, "", gdb_stderr, -1);
+ fprintf_unfiltered (gdb_stderr, " has no component named ");
+ fputs_filtered (name, gdb_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_TYPEDEF (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;
+ }
+ }
+ }
+}
+
+/* Find the method and field indices for the destructor in class type T.
+ Return 1 if the destructor was found, otherwise, return 0. */
+
+int
+get_destructor_fn_field (t, method_indexp, field_indexp)
+ struct type *t;
+ int *method_indexp;
+ int *field_indexp;
+{
+ int i;
+
+ for (i = 0; i < TYPE_NFN_FIELDS (t); i++)
+ {
+ int j;
+ struct fn_field *f = TYPE_FN_FIELDLIST1 (t, i);
+
+ for (j = 0; j < TYPE_FN_FIELDLIST_LENGTH (t, i); j++)
+ {
+ if (DESTRUCTOR_PREFIX_P (TYPE_FN_FIELD_PHYSNAME (f, j)))
+ {
+ *method_indexp = i;
+ *field_indexp = j;
+ return 1;
+ }
+ }
+ }
+ return 0;
+}
+
+/* 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. There used to be a comment (but
+ not any code) that if we don't find a full definition, we'd set a flag
+ so we don't spend time in the future checking the same type. That would
+ be a mistake, though--we might load in more symbols which contain a
+ full definition for the type.
+
+ 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};
+
+struct type *
+check_typedef (type)
+ register struct type *type;
+{
+ struct type *orig_type = type;
+ while (TYPE_CODE (type) == TYPE_CODE_TYPEDEF)
+ {
+ if (!TYPE_TARGET_TYPE (type))
+ {
+ char* name;
+ struct symbol *sym;
+
+ /* It is dangerous to call lookup_symbol if we are currently
+ reading a symtab. Infinite recursion is one danger. */
+ if (currently_reading_symtab)
+ return type;
+
+ 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). */
+ if (name == NULL)
+ {
+ complain (&stub_noname_complaint);
+ return type;
+ }
+ sym = lookup_symbol (name, 0, STRUCT_NAMESPACE, 0,
+ (struct symtab **) NULL);
+ if (sym)
+ TYPE_TARGET_TYPE (type) = SYMBOL_TYPE (sym);
+ else
+ TYPE_TARGET_TYPE (type) = alloc_type (NULL); /* TYPE_CODE_UNDEF */
+ }
+ type = TYPE_TARGET_TYPE (type);
+ }
+
+ /* If this is a struct/class/union with no fields, then check whether a
+ full definition exists somewhere else. This is for systems where a
+ type definition with no fields is issued for such types, instead of
+ identifying them as stub types in the first place */
+
+ if (TYPE_IS_OPAQUE (type) && opaque_type_resolution && !currently_reading_symtab)
+ {
+ char * name = type_name_no_tag (type);
+ struct type * newtype;
+ if (name == NULL)
+ {
+ complain (&stub_noname_complaint);
+ return type;
+ }
+ newtype = lookup_transparent_type (name);
+ if (newtype)
+ {
+ memcpy ((char *) type, (char *) newtype, sizeof (struct type));
+ }
+ }
+ /* Otherwise, rely on the stub flag being set for opaque/stubbed types */
+ else if ((TYPE_FLAGS(type) & TYPE_FLAG_STUB) && ! currently_reading_symtab)
+ {
+ 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 type;
+ }
+ sym = lookup_symbol (name, 0, STRUCT_NAMESPACE, 0, (struct symtab **) NULL);
+ if (sym)
+ {
+ memcpy ((char *)type, (char *)SYMBOL_TYPE(sym), sizeof (struct type));
+ }
+ }
+
+ if (TYPE_FLAGS (type) & TYPE_FLAG_TARGET_STUB)
+ {
+ struct type *range_type;
+ struct type *target_type = check_typedef (TYPE_TARGET_TYPE (type));
+
+ if (TYPE_FLAGS (target_type) & (TYPE_FLAG_STUB | TYPE_FLAG_TARGET_STUB))
+ { }
+ else if (TYPE_CODE (type) == TYPE_CODE_ARRAY
+ && TYPE_NFIELDS (type) == 1
+ && (TYPE_CODE (range_type = TYPE_FIELD_TYPE (type, 0))
+ == TYPE_CODE_RANGE))
+ {
+ /* Now recompute the length of the array type, based on its
+ number of elements and the target type's length. */
+ TYPE_LENGTH (type) =
+ ((TYPE_FIELD_BITPOS (range_type, 1)
+ - TYPE_FIELD_BITPOS (range_type, 0)
+ + 1)
+ * TYPE_LENGTH (target_type));
+ TYPE_FLAGS (type) &= ~TYPE_FLAG_TARGET_STUB;
+ }
+ else if (TYPE_CODE (type) == TYPE_CODE_RANGE)
+ {
+ TYPE_LENGTH (type) = TYPE_LENGTH (target_type);
+ TYPE_FLAGS (type) &= ~TYPE_FLAG_TARGET_STUB;
+ }
+ }
+ /* Cache TYPE_LENGTH for future use. */
+ TYPE_LENGTH (orig_type) = TYPE_LENGTH (type);
+ return type;
+}
+
+/* New code added to support parsing of Cfront stabs strings */
+#include <ctype.h>
+#define INIT_EXTRA { pextras->len=0; pextras->str[0]='\0'; }
+#define ADD_EXTRA(c) { pextras->str[pextras->len++]=c; }
+
+static void
+add_name(pextras,n)
+ struct extra * pextras;
+ char * n;
+{
+ int nlen;
+
+ if ((nlen = (n ? strlen(n) : 0))==0)
+ return;
+ sprintf(pextras->str+pextras->len,"%d%s",nlen,n);
+ pextras->len=strlen(pextras->str);
+}
+
+static void
+add_mangled_type(pextras,t)
+ struct extra * pextras;
+ struct type * t;
+{
+ enum type_code tcode;
+ int tlen, tflags;
+ char * tname;
+
+ tcode = TYPE_CODE(t);
+ tlen = TYPE_LENGTH(t);
+ tflags = TYPE_FLAGS(t);
+ tname = TYPE_NAME(t);
+ /* args of "..." seem to get mangled as "e" */
+
+ switch (tcode)
+ {
+ case TYPE_CODE_INT:
+ if (tflags==1)
+ ADD_EXTRA('U');
+ switch (tlen)
+ {
+ case 1:
+ ADD_EXTRA('c');
+ break;
+ case 2:
+ ADD_EXTRA('s');
+ break;
+ case 4:
+ {
+ char* pname;
+ if ((pname=strrchr(tname,'l'),pname) && !strcmp(pname,"long"))
+ ADD_EXTRA('l')
+ else
+ ADD_EXTRA('i')
+ }
+ break;
+ default:
+ {
+
+ static struct complaint msg = {"Bad int type code length x%x\n",0,0};
+
+ complain (&msg, tlen);
+
+ }
+ }
+ break;
+ case TYPE_CODE_FLT:
+ switch (tlen)
+ {
+ case 4:
+ ADD_EXTRA('f');
+ break;
+ case 8:
+ ADD_EXTRA('d');
+ break;
+ case 16:
+ ADD_EXTRA('r');
+ break;
+ default:
+ {
+ static struct complaint msg = {"Bad float type code length x%x\n",0,0};
+ complain (&msg, tlen);
+ }
+ }
+ break;
+ case TYPE_CODE_REF:
+ ADD_EXTRA('R');
+ /* followed by what it's a ref to */
+ break;
+ case TYPE_CODE_PTR:
+ ADD_EXTRA('P');
+ /* followed by what it's a ptr to */
+ break;
+ case TYPE_CODE_TYPEDEF:
+ {
+ static struct complaint msg = {"Typedefs in overloaded functions not yet supported\n",0,0};
+ complain (&msg);
+ }
+ /* followed by type bytes & name */
+ break;
+ case TYPE_CODE_FUNC:
+ ADD_EXTRA('F');
+ /* followed by func's arg '_' & ret types */
+ break;
+ case TYPE_CODE_VOID:
+ ADD_EXTRA('v');
+ break;
+ case TYPE_CODE_METHOD:
+ ADD_EXTRA('M');
+ /* followed by name of class and func's arg '_' & ret types */
+ add_name(pextras,tname);
+ ADD_EXTRA('F'); /* then mangle function */
+ break;
+ case TYPE_CODE_STRUCT: /* C struct */
+ case TYPE_CODE_UNION: /* C union */
+ case TYPE_CODE_ENUM: /* Enumeration type */
+ /* followed by name of type */
+ add_name(pextras,tname);
+ break;
+
+ /* errors possible types/not supported */
+ case TYPE_CODE_CHAR:
+ case TYPE_CODE_ARRAY: /* Array type */
+ case TYPE_CODE_MEMBER: /* Member type */
+ case TYPE_CODE_BOOL:
+ case TYPE_CODE_COMPLEX: /* Complex float */
+ case TYPE_CODE_UNDEF:
+ case TYPE_CODE_SET: /* Pascal sets */
+ case TYPE_CODE_RANGE:
+ case TYPE_CODE_STRING:
+ case TYPE_CODE_BITSTRING:
+ case TYPE_CODE_ERROR:
+ default:
+ {
+ static struct complaint msg = {"Unknown type code x%x\n",0,0};
+ complain (&msg, tcode);
+ }
+ }
+ if (t->target_type)
+ add_mangled_type(pextras,t->target_type);
+}
+
+#if 0
+void
+cfront_mangle_name(type, i, j)
+ struct type *type;
+ int i;
+ int j;
+{
+ struct fn_field *f;
+ char *mangled_name = gdb_mangle_name (type, i, j);
+
+ f = TYPE_FN_FIELDLIST1 (type, i); /* moved from below */
+
+ /* kludge to support cfront methods - gdb expects to find "F" for
+ ARM_mangled names, so when we mangle, we have to add it here */
+ if (ARM_DEMANGLING)
+ {
+ int k;
+ char * arm_mangled_name;
+ 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);
+
+ struct type *ftype = TYPE_FN_FIELD_TYPE (f, j);
+ int nargs = TYPE_NFIELDS(ftype); /* number of args */
+ struct extra extras, * pextras = &extras;
+ INIT_EXTRA
+
+ if (TYPE_FN_FIELD_STATIC_P (f, j)) /* j for sublist within this list */
+ ADD_EXTRA('S')
+ ADD_EXTRA('F')
+ /* add args here! */
+ if (nargs <= 1) /* no args besides this */
+ ADD_EXTRA('v')
+ else {
+ for (k=1; k<nargs; k++)
+ {
+ struct type * t;
+ t = TYPE_FIELD_TYPE(ftype,k);
+ add_mangled_type(pextras,t);
+ }
+ }
+ ADD_EXTRA('\0')
+ printf("add_mangled_type: %s\n",extras.str); /* FIXME */
+ arm_mangled_name = malloc(strlen(mangled_name)+extras.len);
+ sprintf(arm_mangled_name,"%s%s",mangled_name,extras.str);
+ free(mangled_name);
+ mangled_name = arm_mangled_name;
+ }
+}
+#endif /* 0 */
+
+#undef ADD_EXTRA
+/* End of new code added to support parsing of Cfront stabs strings */
+
+/* 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, method_id, signature_id)
+ struct type *type;
+ int method_id;
+ int signature_id;
+{
+ struct fn_field *f;
+ char *mangled_name = gdb_mangle_name (type, method_id, signature_id);
+ 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;
+
+ /* Make sure we got back a function string that we can use. */
+ if (demangled_name)
+ p = strchr (demangled_name, '(');
+
+ if (demangled_name == NULL || p == NULL)
+ error ("Internal: Cannot demangle mangled name `%s'.", mangled_name);
+
+ /* Now, read in the parameters that define this type. */
+ p += 1;
+ argtypetext = p;
+ 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;
+ /* FIXME: This is wrong for static member functions. */
+ argtypes[0] = lookup_pointer_type (type);
+ argcount = 1;
+
+ if (*p != ')') /* () means no args, skip while */
+ {
+ depth = 0;
+ while (*p)
+ {
+ if (depth <= 0 && (*p == ',' || *p == ')'))
+ {
+ /* Avoid parsing of ellipsis, they will be handled below. */
+ if (strncmp (argtypetext, "...", p - argtypetext) != 0)
+ {
+ 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, method_id);
+
+ TYPE_FN_FIELD_PHYSNAME (f, signature_id) = mangled_name;
+
+ /* Now update the old "stub" type into a real type. */
+ mtype = TYPE_FN_FIELD_TYPE (f, signature_id);
+ TYPE_DOMAIN_TYPE (mtype) = type;
+ TYPE_ARG_TYPES (mtype) = argtypes;
+ TYPE_FLAGS (mtype) &= ~TYPE_FLAG_STUB;
+ TYPE_FN_FIELD_STUB (f, signature_id) = 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);
+ OBJSTAT (objfile, n_types += FT_NUM_MEMBERS);
+ }
+
+ /* 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);
+}
+
+int
+can_dereference (t)
+ struct type *t;
+{
+ /* FIXME: Should we return true for references as well as pointers? */
+ CHECK_TYPEDEF (t);
+ return
+ (t != NULL
+ && TYPE_CODE (t) == TYPE_CODE_PTR
+ && TYPE_CODE (TYPE_TARGET_TYPE (t)) != TYPE_CODE_VOID);
+}
+
+/* Chill varying string and arrays are represented as follows:
+
+ struct { int __var_length; ELEMENT_TYPE[MAX_SIZE] __var_data};
+
+ Return true if TYPE is such a Chill varying type. */
+
+int
+chill_varying_type (type)
+ struct type *type;
+{
+ if (TYPE_CODE (type) != TYPE_CODE_STRUCT
+ || TYPE_NFIELDS (type) != 2
+ || strcmp (TYPE_FIELD_NAME (type, 0), "__var_length") != 0)
+ return 0;
+ return 1;
+}
+
+/* Check whether BASE is an ancestor or base class or DCLASS
+ Return 1 if so, and 0 if not.
+ Note: callers may want to check for identity of the types before
+ calling this function -- identical types are considered to satisfy
+ the ancestor relationship even if they're identical */
+
+int
+is_ancestor (base, dclass)
+ struct type * base;
+ struct type * dclass;
+{
+ int i;
+
+ CHECK_TYPEDEF (base);
+ CHECK_TYPEDEF (dclass);
+
+ if (base == dclass)
+ return 1;
+
+ for (i = 0; i < TYPE_N_BASECLASSES (dclass); i++)
+ if (is_ancestor (base, TYPE_BASECLASS (dclass, i)))
+ return 1;
+
+ return 0;
+}
+
+
+
+/* See whether DCLASS has a virtual table. This routine is aimed at
+ the HP/Taligent ANSI C++ runtime model, and may not work with other
+ runtime models. Return 1 => Yes, 0 => No. */
+
+int
+has_vtable (dclass)
+ struct type * dclass;
+{
+ /* In the HP ANSI C++ runtime model, a class has a vtable only if it
+ has virtual functions or virtual bases. */
+
+ register int i;
+
+ if (TYPE_CODE(dclass) != TYPE_CODE_CLASS)
+ return 0;
+
+ /* First check for the presence of virtual bases */
+ if (TYPE_FIELD_VIRTUAL_BITS(dclass))
+ for (i=0; i < TYPE_N_BASECLASSES(dclass); i++)
+ if (B_TST(TYPE_FIELD_VIRTUAL_BITS(dclass), i))
+ return 1;
+
+ /* Next check for virtual functions */
+ if (TYPE_FN_FIELDLISTS(dclass))
+ for (i=0; i < TYPE_NFN_FIELDS(dclass); i++)
+ if (TYPE_FN_FIELD_VIRTUAL_P(TYPE_FN_FIELDLIST1(dclass, i), 0))
+ return 1;
+
+ /* Recurse on non-virtual bases to see if any of them needs a vtable */
+ if (TYPE_FIELD_VIRTUAL_BITS(dclass))
+ for (i=0; i < TYPE_N_BASECLASSES(dclass); i++)
+ if ((!B_TST (TYPE_FIELD_VIRTUAL_BITS(dclass), i)) &&
+ (has_vtable (TYPE_FIELD_TYPE(dclass, i))))
+ return 1;
+
+ /* Well, maybe we don't need a virtual table */
+ return 0;
+}
+
+/* Return a pointer to the "primary base class" of DCLASS.
+
+ A NULL return indicates that DCLASS has no primary base, or that it
+ couldn't be found (insufficient information).
+
+ This routine is aimed at the HP/Taligent ANSI C++ runtime model,
+ and may not work with other runtime models. */
+
+struct type *
+primary_base_class (dclass)
+ struct type * dclass;
+{
+ /* In HP ANSI C++'s runtime model, a "primary base class" of a class
+ is the first directly inherited, non-virtual base class that
+ requires a virtual table */
+
+ register int i;
+
+ if (TYPE_CODE(dclass) != TYPE_CODE_CLASS)
+ return NULL;
+
+ for (i=0; i < TYPE_N_BASECLASSES(dclass); i++)
+ if (!TYPE_FIELD_VIRTUAL(dclass, i) &&
+ has_vtable(TYPE_FIELD_TYPE(dclass, i)))
+ return TYPE_FIELD_TYPE(dclass, i);
+
+ return NULL;
+}
+
+/* Global manipulated by virtual_base_list[_aux]() */
+
+static struct vbase * current_vbase_list = NULL;
+
+/* Return a pointer to a null-terminated list of struct vbase
+ items. The vbasetype pointer of each item in the list points to the
+ type information for a virtual base of the argument DCLASS.
+
+ Helper function for virtual_base_list().
+ Note: the list goes backward, right-to-left. virtual_base_list()
+ copies the items out in reverse order. */
+
+struct vbase *
+virtual_base_list_aux (dclass)
+ struct type * dclass;
+{
+ struct vbase * tmp_vbase;
+ register int i;
+
+ if (TYPE_CODE(dclass) != TYPE_CODE_CLASS)
+ return NULL;
+
+ for (i = 0; i < TYPE_N_BASECLASSES (dclass); i++)
+ {
+ /* Recurse on this ancestor, first */
+ virtual_base_list_aux(TYPE_FIELD_TYPE(dclass, i));
+
+ /* If this current base is itself virtual, add it to the list */
+ if (BASETYPE_VIA_VIRTUAL(dclass, i))
+ {
+ struct type * basetype = TYPE_FIELD_TYPE (dclass, i);
+
+ /* Check if base already recorded */
+ tmp_vbase = current_vbase_list;
+ while (tmp_vbase)
+ {
+ if (tmp_vbase->vbasetype == basetype)
+ break; /* found it */
+ tmp_vbase = tmp_vbase->next;
+ }
+
+ if (!tmp_vbase) /* normal exit from loop */
+ {
+ /* Allocate new item for this virtual base */
+ tmp_vbase = (struct vbase *) xmalloc (sizeof (struct vbase));
+
+ /* Stick it on at the end of the list */
+ tmp_vbase->vbasetype = basetype;
+ tmp_vbase->next = current_vbase_list;
+ current_vbase_list = tmp_vbase;
+ }
+ } /* if virtual */
+ } /* for loop over bases */
+}
+
+
+/* Compute the list of virtual bases in the right order. Virtual
+ bases are laid out in the object's memory area in order of their
+ occurrence in a depth-first, left-to-right search through the
+ ancestors.
+
+ Argument DCLASS is the type whose virtual bases are required.
+ Return value is the address of a null-terminated array of pointers
+ to struct type items.
+
+ This routine is aimed at the HP/Taligent ANSI C++ runtime model,
+ and may not work with other runtime models.
+
+ This routine merely hands off the argument to virtual_base_list_aux()
+ and then copies the result into an array to save space. */
+
+struct type **
+virtual_base_list (dclass)
+ struct type * dclass;
+{
+ register struct vbase * tmp_vbase;
+ register struct vbase * tmp_vbase_2;
+ register int i;
+ int count;
+ struct type ** vbase_array;
+
+ current_vbase_list = NULL;
+ virtual_base_list_aux(dclass);
+
+ for (i=0, tmp_vbase = current_vbase_list; tmp_vbase != NULL; i++, tmp_vbase = tmp_vbase->next)
+ /* no body */ ;
+
+ count = i;
+
+ vbase_array = (struct type **) xmalloc((count + 1) * sizeof (struct type *));
+
+ for (i=count -1, tmp_vbase = current_vbase_list; i >= 0; i--, tmp_vbase = tmp_vbase->next)
+ vbase_array[i] = tmp_vbase->vbasetype;
+
+ /* Get rid of constructed chain */
+ tmp_vbase_2 = tmp_vbase = current_vbase_list;
+ while (tmp_vbase)
+ {
+ tmp_vbase = tmp_vbase->next;
+ free(tmp_vbase_2);
+ tmp_vbase_2 = tmp_vbase;
+ }
+
+ vbase_array[count] = NULL;
+ return vbase_array;
+}
+
+/* Return the length of the virtual base list of the type DCLASS. */
+
+int
+virtual_base_list_length (dclass)
+ struct type * dclass;
+{
+ register int i;
+ register struct vbase * tmp_vbase;
+
+ current_vbase_list = NULL;
+ virtual_base_list_aux(dclass);
+
+ for (i=0, tmp_vbase = current_vbase_list; tmp_vbase != NULL; i++, tmp_vbase = tmp_vbase->next)
+ /* no body */ ;
+ return i;
+}
+
+/* Return the number of elements of the virtual base list of the type
+ DCLASS, ignoring those appearing in the primary base (and its
+ primary base, recursively). */
+
+int
+virtual_base_list_length_skip_primaries (dclass)
+ struct type * dclass;
+{
+ register int i;
+ register struct vbase * tmp_vbase;
+ struct type * primary;
+
+ primary = TYPE_RUNTIME_PTR (dclass) ? TYPE_PRIMARY_BASE (dclass) : NULL;
+
+ if (!primary)
+ return virtual_base_list_length (dclass);
+
+ current_vbase_list = NULL;
+ virtual_base_list_aux(dclass);
+
+ for (i=0, tmp_vbase = current_vbase_list; tmp_vbase != NULL; tmp_vbase = tmp_vbase->next)
+ {
+ if (virtual_base_index (tmp_vbase->vbasetype, primary) >= 0)
+ continue;
+ i++;
+ }
+ return i;
+}
+
+
+/* Return the index (position) of type BASE, which is a virtual base
+ class of DCLASS, in the latter's virtual base list. A return of -1
+ indicates "not found" or a problem. */
+
+int
+virtual_base_index(base, dclass)
+ struct type * base;
+ struct type * dclass;
+{
+ register struct type * vbase;
+ register int i;
+
+ if ((TYPE_CODE(dclass) != TYPE_CODE_CLASS) ||
+ (TYPE_CODE(base) != TYPE_CODE_CLASS))
+ return -1;
+
+ i = 0;
+ vbase = TYPE_VIRTUAL_BASE_LIST(dclass)[0];
+ while (vbase)
+ {
+ if (vbase == base)
+ break;
+ vbase = TYPE_VIRTUAL_BASE_LIST(dclass)[++i];
+ }
+
+ return vbase ? i : -1;
+}
+
+
+
+/* Return the index (position) of type BASE, which is a virtual base
+ class of DCLASS, in the latter's virtual base list. Skip over all
+ bases that may appear in the virtual base list of the primary base
+ class of DCLASS (recursively). A return of -1 indicates "not
+ found" or a problem. */
+
+int
+virtual_base_index_skip_primaries(base, dclass)
+ struct type * base;
+ struct type * dclass;
+{
+ register struct type * vbase;
+ register int i, j;
+ struct type * primary;
+
+ if ((TYPE_CODE(dclass) != TYPE_CODE_CLASS) ||
+ (TYPE_CODE(base) != TYPE_CODE_CLASS))
+ return -1;
+
+ primary = TYPE_RUNTIME_PTR(dclass) ? TYPE_PRIMARY_BASE(dclass) : NULL;
+
+ j = -1;
+ i = 0;
+ vbase = TYPE_VIRTUAL_BASE_LIST(dclass)[0];
+ while (vbase)
+ {
+ if (!primary || (virtual_base_index_skip_primaries(vbase, primary) < 0))
+ j++;
+ if (vbase == base)
+ break;
+ vbase = TYPE_VIRTUAL_BASE_LIST(dclass)[++i];
+ }
+
+ return vbase ? j : -1;
+}
+
+/* Return position of a derived class DCLASS in the list of
+ * primary bases starting with the remotest ancestor.
+ * Position returned is 0-based. */
+
+int
+class_index_in_primary_list (dclass)
+ struct type * dclass;
+{
+ struct type * pbc; /* primary base class */
+
+ /* Simply recurse on primary base */
+ pbc = TYPE_PRIMARY_BASE (dclass);
+ if (pbc)
+ return 1 + class_index_in_primary_list (pbc);
+ else
+ return 0;
+}
+
+/* Return a count of the number of virtual functions a type has.
+ * This includes all the virtual functions it inherits from its
+ * base classes too.
+ */
+
+/* pai: FIXME This doesn't do the right thing: count redefined virtual
+ * functions only once (latest redefinition)
+ */
+
+int
+count_virtual_fns (dclass)
+ struct type * dclass;
+{
+ int base; /* index for base classes */
+ int fn, oi; /* function and overloaded instance indices */
+
+ int vfuncs; /* count to return */
+
+ /* recurse on bases that can share virtual table */
+ struct type * pbc = primary_base_class (dclass);
+ if (pbc)
+ vfuncs = count_virtual_fns (pbc);
+
+ for (fn = 0; fn < TYPE_NFN_FIELDS (dclass); fn++)
+ for (oi = 0; oi < TYPE_FN_FIELDLIST_LENGTH (dclass, fn); oi++)
+ if (TYPE_FN_FIELD_VIRTUAL_P (TYPE_FN_FIELDLIST1 (dclass, fn), oi))
+ vfuncs++;
+
+ return vfuncs;
+}
+
+
+
+/* Functions for overload resolution begin here */
+
+/* Compare two badness vectors A and B and return the result.
+ * 0 => A and B are identical
+ * 1 => A and B are incomparable
+ * 2 => A is better than B
+ * 3 => A is worse than B */
+
+int
+compare_badness (a, b)
+ struct badness_vector * a;
+ struct badness_vector * b;
+{
+ int i;
+ int tmp;
+ short found_pos = 0; /* any positives in c? */
+ short found_neg = 0; /* any negatives in c? */
+
+ /* differing lengths => incomparable */
+ if (a->length != b->length)
+ return 1;
+
+ /* Subtract b from a */
+ for (i=0; i < a->length; i++)
+ {
+ tmp = a->rank[i] - b->rank[i];
+ if (tmp > 0)
+ found_pos = 1;
+ else if (tmp < 0)
+ found_neg = 1;
+ }
+
+ if (found_pos)
+ {
+ if (found_neg)
+ return 1; /* incomparable */
+ else
+ return 3; /* A > B */
+ }
+ else /* no positives */
+ {
+ if (found_neg)
+ return 2; /* A < B */
+ else
+ return 0; /* A == B */
+ }
+}
+
+/* Rank a function by comparing its parameter types (PARMS, length NPARMS),
+ * to the types of an argument list (ARGS, length NARGS).
+ * Return a pointer to a badness vector. This has NARGS + 1 entries. */
+
+struct badness_vector *
+rank_function (parms, nparms, args, nargs)
+ struct type ** parms;
+ int nparms;
+ struct type ** args;
+ int nargs;
+{
+ int i;
+ struct badness_vector * bv;
+ int min_len = nparms < nargs ? nparms : nargs;
+
+ bv = xmalloc (sizeof (struct badness_vector));
+ bv->length = nargs + 1; /* add 1 for the length-match rank */
+ bv->rank = xmalloc ((nargs + 1) * sizeof (int));
+
+ /* First compare the lengths of the supplied lists.
+ * If there is a mismatch, set it to a high value. */
+
+ /* pai/1997-06-03 FIXME: when we have debug info about default
+ * arguments and ellipsis parameter lists, we should consider those
+ * and rank the length-match more finely. */
+
+ LENGTH_MATCH (bv) = (nargs != nparms) ? LENGTH_MISMATCH_BADNESS : 0;
+
+ /* Now rank all the parameters of the candidate function */
+ for (i=1; i <= min_len; i++)
+ bv->rank[i] = rank_one_type (parms[i-1], args[i-1]);
+
+ /* If more arguments than parameters, add dummy entries */
+ for (i = min_len +1; i <= nargs; i++)
+ bv->rank[i] = TOO_FEW_PARAMS_BADNESS;
+
+ return bv;
+}
+
+/* Compare one type (PARM) for compatibility with another (ARG).
+ * PARM is intended to be the parameter type of a function; and
+ * ARG is the supplied argument's type. This function tests if
+ * the latter can be converted to the former.
+ *
+ * Return 0 if they are identical types;
+ * Otherwise, return an integer which corresponds to how compatible
+ * PARM is to ARG. The higher the return value, the worse the match.
+ * Generally the "bad" conversions are all uniformly assigned a 100 */
+
+int
+rank_one_type (parm, arg)
+ struct type * parm;
+ struct type * arg;
+{
+ /* Identical type pointers */
+ /* However, this still doesn't catch all cases of same type for arg
+ * and param. The reason is that builtin types are different from
+ * the same ones constructed from the object. */
+ if (parm == arg)
+ return 0;
+
+ /* Resolve typedefs */
+ if (TYPE_CODE (parm) == TYPE_CODE_TYPEDEF)
+ parm = check_typedef (parm);
+ if (TYPE_CODE (arg) == TYPE_CODE_TYPEDEF)
+ arg = check_typedef (arg);
+
+ /* Check if identical after resolving typedefs */
+ if (parm == arg)
+ return 0;
+
+#if 0
+ /* Debugging only */
+ printf("------ Arg is %s [%d], parm is %s [%d]\n",
+ TYPE_NAME (arg), TYPE_CODE (arg), TYPE_NAME (parm), TYPE_CODE (parm));
+#endif
+
+ /* x -> y means arg of type x being supplied for parameter of type y */
+
+ switch (TYPE_CODE (parm))
+ {
+ case TYPE_CODE_PTR:
+ switch (TYPE_CODE (arg))
+ {
+ case TYPE_CODE_PTR:
+ if (TYPE_CODE (TYPE_TARGET_TYPE (parm)) == TYPE_CODE_VOID)
+ return VOID_PTR_CONVERSION_BADNESS;
+ else
+ return rank_one_type (TYPE_TARGET_TYPE (parm), TYPE_TARGET_TYPE (arg));
+ case TYPE_CODE_ARRAY:
+ return rank_one_type (TYPE_TARGET_TYPE (parm), TYPE_TARGET_TYPE (arg));
+ case TYPE_CODE_FUNC:
+ return rank_one_type (TYPE_TARGET_TYPE (parm), arg);
+ case TYPE_CODE_INT:
+ case TYPE_CODE_ENUM:
+ case TYPE_CODE_CHAR:
+ case TYPE_CODE_RANGE:
+ case TYPE_CODE_BOOL:
+ return POINTER_CONVERSION_BADNESS;
+ default:
+ return INCOMPATIBLE_TYPE_BADNESS;
+ }
+ case TYPE_CODE_ARRAY:
+ switch (TYPE_CODE (arg))
+ {
+ case TYPE_CODE_PTR:
+ case TYPE_CODE_ARRAY:
+ return rank_one_type (TYPE_TARGET_TYPE (parm), TYPE_TARGET_TYPE (arg));
+ default:
+ return INCOMPATIBLE_TYPE_BADNESS;
+ }
+ case TYPE_CODE_FUNC:
+ switch (TYPE_CODE (arg))
+ {
+ case TYPE_CODE_PTR: /* funcptr -> func */
+ return rank_one_type (parm, TYPE_TARGET_TYPE (arg));
+ default:
+ return INCOMPATIBLE_TYPE_BADNESS;
+ }
+ case TYPE_CODE_INT:
+ switch (TYPE_CODE (arg))
+ {
+ case TYPE_CODE_INT:
+ if (TYPE_LENGTH (arg) == TYPE_LENGTH (parm))
+ {
+ /* Deal with signed, unsigned, and plain chars and
+ signed and unsigned ints */
+ if (TYPE_NOSIGN (parm))
+ {
+ /* This case only for character types */
+ if (TYPE_NOSIGN (arg)) /* plain char -> plain char */
+ return 0;
+ else
+ return INTEGER_COERCION_BADNESS; /* signed/unsigned char -> plain char */
+ }
+ else if (TYPE_UNSIGNED (parm))
+ {
+ if (TYPE_UNSIGNED (arg))
+ {
+ if (!strcmp (TYPE_NAME (parm), TYPE_NAME (arg)))
+ return 0; /* unsigned int -> unsigned int, or unsigned long -> unsigned long */
+ else if (!strcmp (TYPE_NAME (arg), "int") && !strcmp (TYPE_NAME (parm), "long"))
+ return INTEGER_PROMOTION_BADNESS; /* unsigned int -> unsigned long */
+ else
+ return INTEGER_COERCION_BADNESS; /* unsigned long -> unsigned int */
+ }
+ else
+ {
+ if (!strcmp (TYPE_NAME (arg), "long") && !strcmp (TYPE_NAME (parm), "int"))
+ return INTEGER_COERCION_BADNESS; /* signed long -> unsigned int */
+ else
+ return INTEGER_CONVERSION_BADNESS; /* signed int/long -> unsigned int/long */
+ }
+ }
+ else if (!TYPE_NOSIGN (arg) && !TYPE_UNSIGNED (arg))
+ {
+ if (!strcmp (TYPE_NAME (parm), TYPE_NAME (arg)))
+ return 0;
+ else if (!strcmp (TYPE_NAME (arg), "int") && !strcmp (TYPE_NAME (parm), "long"))
+ return INTEGER_PROMOTION_BADNESS;
+ else
+ return INTEGER_COERCION_BADNESS;
+ }
+ else
+ return INTEGER_COERCION_BADNESS;
+ }
+ else if (TYPE_LENGTH (arg) < TYPE_LENGTH (parm))
+ return INTEGER_PROMOTION_BADNESS;
+ else
+ return INTEGER_COERCION_BADNESS;
+ case TYPE_CODE_ENUM:
+ case TYPE_CODE_CHAR:
+ case TYPE_CODE_RANGE:
+ case TYPE_CODE_BOOL:
+ return INTEGER_PROMOTION_BADNESS;
+ case TYPE_CODE_FLT:
+ return INT_FLOAT_CONVERSION_BADNESS;
+ case TYPE_CODE_PTR:
+ return NS_POINTER_CONVERSION_BADNESS;
+ default:
+ return INCOMPATIBLE_TYPE_BADNESS;
+ }
+ break;
+ case TYPE_CODE_ENUM:
+ switch (TYPE_CODE (arg))
+ {
+ case TYPE_CODE_INT:
+ case TYPE_CODE_CHAR:
+ case TYPE_CODE_RANGE:
+ case TYPE_CODE_BOOL:
+ case TYPE_CODE_ENUM:
+ return INTEGER_COERCION_BADNESS;
+ case TYPE_CODE_FLT:
+ return INT_FLOAT_CONVERSION_BADNESS;
+ default:
+ return INCOMPATIBLE_TYPE_BADNESS;
+ }
+ break;
+ case TYPE_CODE_CHAR:
+ switch (TYPE_CODE (arg))
+ {
+ case TYPE_CODE_RANGE:
+ case TYPE_CODE_BOOL:
+ case TYPE_CODE_ENUM:
+ return INTEGER_COERCION_BADNESS;
+ case TYPE_CODE_FLT:
+ return INT_FLOAT_CONVERSION_BADNESS;
+ case TYPE_CODE_INT:
+ if (TYPE_LENGTH (arg) > TYPE_LENGTH (parm))
+ return INTEGER_COERCION_BADNESS;
+ else if (TYPE_LENGTH (arg) < TYPE_LENGTH (parm))
+ return INTEGER_PROMOTION_BADNESS;
+ /* >>> !! else fall through !! <<< */
+ case TYPE_CODE_CHAR:
+ /* Deal with signed, unsigned, and plain chars for C++
+ and with int cases falling through from previous case */
+ if (TYPE_NOSIGN (parm))
+ {
+ if (TYPE_NOSIGN (arg))
+ return 0;
+ else
+ return INTEGER_COERCION_BADNESS;
+ }
+ else if (TYPE_UNSIGNED (parm))
+ {
+ if (TYPE_UNSIGNED (arg))
+ return 0;
+ else
+ return INTEGER_PROMOTION_BADNESS;
+ }
+ else if (!TYPE_NOSIGN (arg) && !TYPE_UNSIGNED (arg))
+ return 0;
+ else
+ return INTEGER_COERCION_BADNESS;
+ default:
+ return INCOMPATIBLE_TYPE_BADNESS;
+ }
+ break;
+ case TYPE_CODE_RANGE:
+ switch (TYPE_CODE (arg))
+ {
+ case TYPE_CODE_INT:
+ case TYPE_CODE_CHAR:
+ case TYPE_CODE_RANGE:
+ case TYPE_CODE_BOOL:
+ case TYPE_CODE_ENUM:
+ return INTEGER_COERCION_BADNESS;
+ case TYPE_CODE_FLT:
+ return INT_FLOAT_CONVERSION_BADNESS;
+ default:
+ return INCOMPATIBLE_TYPE_BADNESS;
+ }
+ break;
+ case TYPE_CODE_BOOL:
+ switch (TYPE_CODE (arg))
+ {
+ case TYPE_CODE_INT:
+ case TYPE_CODE_CHAR:
+ case TYPE_CODE_RANGE:
+ case TYPE_CODE_ENUM:
+ case TYPE_CODE_FLT:
+ case TYPE_CODE_PTR:
+ return BOOLEAN_CONVERSION_BADNESS;
+ case TYPE_CODE_BOOL:
+ return 0;
+ default:
+ return INCOMPATIBLE_TYPE_BADNESS;
+ }
+ break;
+ case TYPE_CODE_FLT:
+ switch (TYPE_CODE (arg))
+ {
+ case TYPE_CODE_FLT:
+ if (TYPE_LENGTH (arg) < TYPE_LENGTH (parm))
+ return FLOAT_PROMOTION_BADNESS;
+ else if (TYPE_LENGTH (arg) == TYPE_LENGTH (parm))
+ return 0;
+ else
+ return FLOAT_CONVERSION_BADNESS;
+ case TYPE_CODE_INT:
+ case TYPE_CODE_BOOL:
+ case TYPE_CODE_ENUM:
+ case TYPE_CODE_RANGE:
+ case TYPE_CODE_CHAR:
+ return INT_FLOAT_CONVERSION_BADNESS;
+ default:
+ return INCOMPATIBLE_TYPE_BADNESS;
+ }
+ break;
+ case TYPE_CODE_COMPLEX:
+ switch (TYPE_CODE (arg))
+ { /* Strictly not needed for C++, but... */
+ case TYPE_CODE_FLT:
+ return FLOAT_PROMOTION_BADNESS;
+ case TYPE_CODE_COMPLEX:
+ return 0;
+ default:
+ return INCOMPATIBLE_TYPE_BADNESS;
+ }
+ break;
+ case TYPE_CODE_STRUCT:
+ /* currently same as TYPE_CODE_CLASS */
+ switch (TYPE_CODE (arg))
+ {
+ case TYPE_CODE_STRUCT:
+ /* Check for derivation */
+ if (is_ancestor (parm, arg))
+ return BASE_CONVERSION_BADNESS;
+ /* else fall through */
+ default:
+ return INCOMPATIBLE_TYPE_BADNESS;
+ }
+ break;
+ case TYPE_CODE_UNION:
+ switch (TYPE_CODE (arg))
+ {
+ case TYPE_CODE_UNION:
+ default:
+ return INCOMPATIBLE_TYPE_BADNESS;
+ }
+ break;
+ case TYPE_CODE_MEMBER:
+ switch (TYPE_CODE (arg))
+ {
+ default:
+ return INCOMPATIBLE_TYPE_BADNESS;
+ }
+ break;
+ case TYPE_CODE_METHOD:
+ switch (TYPE_CODE (arg))
+ {
+
+ default:
+ return INCOMPATIBLE_TYPE_BADNESS;
+ }
+ break;
+ case TYPE_CODE_REF:
+ switch (TYPE_CODE (arg))
+ {
+
+ default:
+ return INCOMPATIBLE_TYPE_BADNESS;
+ }
+
+ break;
+ case TYPE_CODE_SET:
+ switch (TYPE_CODE (arg))
+ {
+ /* Not in C++ */
+ case TYPE_CODE_SET:
+ return rank_one_type (TYPE_FIELD_TYPE (parm, 0), TYPE_FIELD_TYPE (arg, 0));
+ default:
+ return INCOMPATIBLE_TYPE_BADNESS;
+ }
+ break;
+ case TYPE_CODE_VOID:
+ default:
+ return INCOMPATIBLE_TYPE_BADNESS;
+ } /* switch (TYPE_CODE (arg)) */
+}
+
+
+/* End of functions for overload resolution */
+
+
+
+#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 ");
+ gdb_print_address (TYPE_FN_FIELDLISTS (type), gdb_stdout);
+ printf_filtered ("\n");
+ 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' (",
+ method_idx,
+ TYPE_FN_FIELDLIST_NAME (type, method_idx));
+ gdb_print_address (TYPE_FN_FIELDLIST_NAME (type, method_idx),
+ gdb_stdout);
+ printf_filtered (") length %d\n",
+ 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' (",
+ overload_idx,
+ TYPE_FN_FIELD_PHYSNAME (f, overload_idx));
+ gdb_print_address (TYPE_FN_FIELD_PHYSNAME (f, overload_idx),
+ gdb_stdout);
+ printf_filtered (")\n");
+ printfi_filtered (spaces + 8, "type ");
+ gdb_print_address (TYPE_FN_FIELD_TYPE (f, overload_idx), gdb_stdout);
+ printf_filtered ("\n");
+
+ recursive_dump_type (TYPE_FN_FIELD_TYPE (f, overload_idx),
+ spaces + 8 + 2);
+
+ printfi_filtered (spaces + 8, "args ");
+ gdb_print_address (TYPE_FN_FIELD_ARGS (f, overload_idx), gdb_stdout);
+ printf_filtered ("\n");
+
+ print_arg_types (TYPE_FN_FIELD_ARGS (f, overload_idx), spaces);
+ printfi_filtered (spaces + 8, "fcontext ");
+ gdb_print_address (TYPE_FN_FIELD_FCONTEXT (f, overload_idx),
+ gdb_stdout);
+ printf_filtered ("\n");
+
+ 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 *",
+ TYPE_N_BASECLASSES (type));
+ gdb_print_address (TYPE_FIELD_VIRTUAL_BITS (type), gdb_stdout);
+ printf_filtered (")");
+
+ 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 *",
+ TYPE_NFIELDS (type));
+ gdb_print_address (TYPE_FIELD_PRIVATE_BITS (type), gdb_stdout);
+ printf_filtered (")");
+ 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 *",
+ TYPE_NFIELDS (type));
+ gdb_print_address (TYPE_FIELD_PROTECTED_BITS (type), gdb_stdout);
+ printf_filtered (")");
+ 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);
+ }
+}
+
+static struct obstack dont_print_type_obstack;
+
+void
+recursive_dump_type (type, spaces)
+ struct type *type;
+ int spaces;
+{
+ int idx;
+
+ if (spaces == 0)
+ obstack_begin (&dont_print_type_obstack, 0);
+
+ if (TYPE_NFIELDS (type) > 0
+ || (TYPE_CPLUS_SPECIFIC (type) && TYPE_NFN_FIELDS (type) > 0))
+ {
+ struct type **first_dont_print
+ = (struct type **)obstack_base (&dont_print_type_obstack);
+
+ int i = (struct type **)obstack_next_free (&dont_print_type_obstack)
+ - first_dont_print;
+
+ while (--i >= 0)
+ {
+ if (type == first_dont_print[i])
+ {
+ printfi_filtered (spaces, "type node ");
+ gdb_print_address (type, gdb_stdout);
+ printf_filtered (" <same as already seen type>\n");
+ return;
+ }
+ }
+
+ obstack_ptr_grow (&dont_print_type_obstack, type);
+ }
+
+ printfi_filtered (spaces, "type node ");
+ gdb_print_address (type, gdb_stdout);
+ printf_filtered ("\n");
+ printfi_filtered (spaces, "name '%s' (",
+ TYPE_NAME (type) ? TYPE_NAME (type) : "<NULL>");
+ gdb_print_address (TYPE_NAME (type), gdb_stdout);
+ printf_filtered (")\n");
+ if (TYPE_TAG_NAME (type) != NULL)
+ {
+ printfi_filtered (spaces, "tagname '%s' (",
+ TYPE_TAG_NAME (type));
+ gdb_print_address (TYPE_TAG_NAME (type), gdb_stdout);
+ printf_filtered (")\n");
+ }
+ 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;
+ case TYPE_CODE_TYPEDEF:
+ printf_filtered ("(TYPE_CODE_TYPEDEF)");
+ break;
+ default:
+ printf_filtered ("(UNKNOWN TYPE CODE)");
+ break;
+ }
+ puts_filtered ("\n");
+ printfi_filtered (spaces, "length %d\n", TYPE_LENGTH (type));
+ printfi_filtered (spaces, "objfile ");
+ gdb_print_address (TYPE_OBJFILE (type), gdb_stdout);
+ printf_filtered ("\n");
+ printfi_filtered (spaces, "target_type ");
+ gdb_print_address (TYPE_TARGET_TYPE (type), gdb_stdout);
+ printf_filtered ("\n");
+ if (TYPE_TARGET_TYPE (type) != NULL)
+ {
+ recursive_dump_type (TYPE_TARGET_TYPE (type), spaces + 2);
+ }
+ printfi_filtered (spaces, "pointer_type ");
+ gdb_print_address (TYPE_POINTER_TYPE (type), gdb_stdout);
+ printf_filtered ("\n");
+ printfi_filtered (spaces, "reference_type ");
+ gdb_print_address (TYPE_REFERENCE_TYPE (type), gdb_stdout);
+ printf_filtered ("\n");
+ 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_STUB)
+ {
+ puts_filtered (" TYPE_FLAG_STUB");
+ }
+ puts_filtered ("\n");
+ printfi_filtered (spaces, "nfields %d ", TYPE_NFIELDS (type));
+ gdb_print_address (TYPE_FIELDS (type), gdb_stdout);
+ puts_filtered ("\n");
+ for (idx = 0; idx < TYPE_NFIELDS (type); idx++)
+ {
+ printfi_filtered (spaces + 2,
+ "[%d] bitpos %d bitsize %d type ",
+ idx, TYPE_FIELD_BITPOS (type, idx),
+ TYPE_FIELD_BITSIZE (type, idx));
+ gdb_print_address (TYPE_FIELD_TYPE (type, idx), gdb_stdout);
+ printf_filtered (" name '%s' (",
+ TYPE_FIELD_NAME (type, idx) != NULL
+ ? TYPE_FIELD_NAME (type, idx)
+ : "<NULL>");
+ gdb_print_address (TYPE_FIELD_NAME (type, idx), gdb_stdout);
+ printf_filtered (")\n");
+ if (TYPE_FIELD_TYPE (type, idx) != NULL)
+ {
+ recursive_dump_type (TYPE_FIELD_TYPE (type, idx), spaces + 4);
+ }
+ }
+ printfi_filtered (spaces, "vptr_basetype ");
+ gdb_print_address (TYPE_VPTR_BASETYPE (type), gdb_stdout);
+ puts_filtered ("\n");
+ 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 ");
+ gdb_print_address (TYPE_ARG_TYPES (type), gdb_stdout);
+ puts_filtered ("\n");
+ print_arg_types (TYPE_ARG_TYPES (type), spaces);
+ break;
+
+ case TYPE_CODE_STRUCT:
+ printfi_filtered (spaces, "cplus_stuff ");
+ gdb_print_address (TYPE_CPLUS_SPECIFIC (type), gdb_stdout);
+ puts_filtered ("\n");
+ 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 ");
+ gdb_print_address (TYPE_CPLUS_SPECIFIC (type), gdb_stdout);
+ if (TYPE_CPLUS_SPECIFIC (type) != NULL)
+ {
+ printf_filtered (" (unknown data form)");
+ }
+ printf_filtered ("\n");
+ break;
+
+ }
+ if (spaces == 0)
+ obstack_free (&dont_print_type_obstack, NULL);
+}
+
+#endif /* MAINTENANCE_CMDS */
+
+
+static void build_gdbtypes PARAMS ((void));
+static void
+build_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);
+ TYPE_FLAGS (builtin_type_char) |= TYPE_FLAG_NOSIGN;
+
+ builtin_type_signed_char =
+ init_type (TYPE_CODE_INT, TARGET_CHAR_BIT / TARGET_CHAR_BIT,
+ 0,
+ "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_COMPLEX, 2 * TARGET_FLOAT_BIT / TARGET_CHAR_BIT,
+ 0,
+ "complex", (struct objfile *) NULL);
+ TYPE_TARGET_TYPE (builtin_type_complex) = builtin_type_float;
+ builtin_type_double_complex =
+ init_type (TYPE_CODE_COMPLEX, 2 * TARGET_DOUBLE_BIT / TARGET_CHAR_BIT,
+ 0,
+ "double complex", (struct objfile *) NULL);
+ TYPE_TARGET_TYPE (builtin_type_double_complex) = builtin_type_double;
+ builtin_type_string =
+ init_type (TYPE_CODE_STRING, TARGET_CHAR_BIT / TARGET_CHAR_BIT,
+ 0,
+ "string", (struct objfile *) NULL);
+ builtin_type_int8 =
+ init_type (TYPE_CODE_INT, 8 / 8,
+ 0,
+ "int8_t", (struct objfile *) NULL);
+ builtin_type_uint8 =
+ init_type (TYPE_CODE_INT, 8 / 8,
+ TYPE_FLAG_UNSIGNED,
+ "uint8_t", (struct objfile *) NULL);
+ builtin_type_int16 =
+ init_type (TYPE_CODE_INT, 16 / 8,
+ 0,
+ "int16_t", (struct objfile *) NULL);
+ builtin_type_uint16 =
+ init_type (TYPE_CODE_INT, 16 / 8,
+ TYPE_FLAG_UNSIGNED,
+ "uint16_t", (struct objfile *) NULL);
+ builtin_type_int32 =
+ init_type (TYPE_CODE_INT, 32 / 8,
+ 0,
+ "int32_t", (struct objfile *) NULL);
+ builtin_type_uint32 =
+ init_type (TYPE_CODE_INT, 32 / 8,
+ TYPE_FLAG_UNSIGNED,
+ "uint32_t", (struct objfile *) NULL);
+ builtin_type_int64 =
+ init_type (TYPE_CODE_INT, 64 / 8,
+ 0,
+ "int64_t", (struct objfile *) NULL);
+ builtin_type_uint64 =
+ init_type (TYPE_CODE_INT, 64 / 8,
+ TYPE_FLAG_UNSIGNED,
+ "uint64_t", (struct objfile *) NULL);
+ builtin_type_bool =
+ init_type (TYPE_CODE_BOOL, TARGET_CHAR_BIT / TARGET_CHAR_BIT,
+ 0,
+ "bool", (struct objfile *) NULL);
+
+ /* Add user knob for controlling resolution of opaque types */
+ add_show_from_set
+ (add_set_cmd ("opaque-type-resolution", class_support, var_boolean, (char *)&opaque_type_resolution,
+ "Set resolution of opaque struct/class/union types (if set before loading symbols).",
+ &setlist),
+ &showlist);
+ opaque_type_resolution = 1;
+
+}
+
+
+extern void _initialize_gdbtypes PARAMS ((void));
+void
+_initialize_gdbtypes ()
+{
+ build_gdbtypes ();
+}
diff --git a/gdb/gdbtypes.h b/gdb/gdbtypes.h
new file mode 100644
index 00000000000..107eb46eb30
--- /dev/null
+++ b/gdb/gdbtypes.h
@@ -0,0 +1,1135 @@
+/* Internal type definitions for GDB.
+ Copyright (C) 1992, 1993, 1994, 1996, 1998, 1999
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#if !defined (GDBTYPES_H)
+#define GDBTYPES_H 1
+
+/* Codes for `fundamental types'. This is a monstrosity based on the
+ bogus notion that there are certain compiler-independent
+ `fundamental types'. None of these is well-defined (how big is
+ FT_SHORT? Does it depend on the language? How does the
+ language-specific code know which type to correlate to FT_SHORT?) */
+
+#define FT_VOID 0
+#define FT_BOOLEAN 1
+#define FT_CHAR 2 /* we use this for not-unsigned C/C++ chars */
+#define FT_SIGNED_CHAR 3 /* we use this for C++ signed chars */
+#define FT_UNSIGNED_CHAR 4 /* we use this for C/C++ unsigned chars */
+#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_TEMPLATE_ARG 28
+
+#define FT_NUM_MEMBERS 29 /* 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. Beware, there are parts
+ of GDB which bogusly assume that TYPE_CODE_FLT can mean complex. */
+ TYPE_CODE_FLT,
+
+ /* Void type. The length field specifies the length (probably always
+ one) which is used in pointer arithmetic involving pointers to
+ this type, but actually dereferencing such a pointer is invalid;
+ a void type has no length and no actual representation in memory
+ or registers. A pointer to a void type is a generic pointer. */
+ TYPE_CODE_VOID,
+
+ TYPE_CODE_SET, /* Pascal sets */
+ TYPE_CODE_RANGE, /* Range (integers within spec'd bounds) */
+
+ /* A string type which is like an array of character but prints
+ differently (at least for CHILL). It does not contain a length
+ field as Pascal strings (for many Pascals, anyway) do; if we want
+ to deal with such strings, we should use a new type code. */
+ TYPE_CODE_STRING,
+
+ /* String of bits; like TYPE_CODE_SET but prints differently (at least
+ for CHILL). */
+ TYPE_CODE_BITSTRING,
+
+ /* 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 */
+
+ TYPE_CODE_CHAR, /* *real* character type */
+
+ /* Boolean type. 0 is false, 1 is true, and other values are non-boolean
+ (e.g. FORTRAN "logical" used as unsigned int). */
+ TYPE_CODE_BOOL,
+
+ /* Fortran */
+ TYPE_CODE_COMPLEX, /* Complex float */
+
+ TYPE_CODE_TYPEDEF,
+ TYPE_CODE_TEMPLATE, /* C++ template */
+ TYPE_CODE_TEMPLATE_ARG /* C++ template arg */
+
+};
+
+/* For now allow source to use TYPE_CODE_CLASS for C++ classes, as an
+ alias for TYPE_CODE_STRUCT. This is for DWARF, which has a distinct
+ "class" attribute. Perhaps we should actually have a separate TYPE_CODE
+ so that we can print "class" or "struct" depending on what the debug
+ info said. It's not clear we should bother. */
+
+#define TYPE_CODE_CLASS TYPE_CODE_STRUCT
+
+/* Some bits for the type's flags word. */
+
+/* Unsigned integer type. If this is not set for a TYPE_CODE_INT, the
+ type is signed (unless TYPE_FLAG_NOSIGN (below) is set). */
+
+#define TYPE_FLAG_UNSIGNED (1 << 0)
+
+/* No sign for this type. In C++, "char", "signed char", and "unsigned
+ char" are distinct types; so we need an extra flag to indicate the
+ absence ofa sign! */
+
+#define TYPE_FLAG_NOSIGN (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)
+
+/* The target type of this type is a stub type, and this type needs to
+ be updated if it gets un-stubbed in check_typedef.
+ Used for arrays and ranges, in which TYPE_LENGTH of the array/range
+ gets set based on the TYPE_LENGTH of the target type.
+ Also, set for TYPE_CODE_TYPEDEF. */
+
+#define TYPE_FLAG_TARGET_STUB (1 << 3)
+
+/* Static type. If this is set, the corresponding type had
+ * a static modifier.
+ * Note: This may be unnecessary, since static data members
+ * are indicated by other means (bitpos == -1)
+ */
+
+#define TYPE_FLAG_STATIC (1 << 4)
+
+/* Constant type. If this is set, the corresponding type has a
+ * const modifier.
+ */
+
+#define TYPE_FLAG_CONST (1 << 5)
+
+/* Volatile type. If this is set, the corresponding type has a
+ * volatile modifier.
+ */
+
+#define TYPE_FLAG_VOLATILE (1 << 6)
+
+
+/* This is a function type which appears to have a prototype. We need this
+ for function calls in order to tell us if it's necessary to coerce the args,
+ or to just do the standard conversions. This is used with a short field. */
+
+#define TYPE_FLAG_PROTOTYPED (1 << 7)
+
+/* This flag is used to indicate that processing for this type
+ is incomplete.
+
+ (Mostly intended for HP platforms, where class methods, for
+ instance, can be encountered before their classes in the debug
+ info; the incomplete type has to be marked so that the class and
+ the method can be assigned correct types.) */
+
+#define TYPE_FLAG_INCOMPLETE (1 << 8)
+
+
+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 of storage for a value of this type. Various places pass
+ this to memcpy and such, meaning it must be in units of
+ HOST_CHAR_BIT. Various other places expect they can calculate
+ addresses by adding it and such, meaning it must be in units of
+ TARGET_CHAR_BIT. For some DSP targets, in which HOST_CHAR_BIT
+ will (presumably) be 8 and TARGET_CHAR_BIT will be (say) 32, this
+ is a problem. One fix would be to make this field in bits
+ (requiring that it always be a multiple of HOST_CHAR_BIT and
+ TARGET_CHAR_BIT)--the other choice would be to make it
+ consistently in units of HOST_CHAR_BIT. */
+
+ unsigned length;
+
+ /* FIXME, these should probably be restricted to a Fortran-specific
+ field in some fashion. */
+#define BOUND_CANNOT_BE_DETERMINED 5
+#define BOUND_BY_REF_ON_STACK 4
+#define BOUND_BY_VALUE_ON_STACK 3
+#define BOUND_BY_REF_IN_REG 2
+#define BOUND_BY_VALUE_IN_REG 1
+#define BOUND_SIMPLE 0
+ int upper_bound_type;
+ int lower_bound_type;
+
+ /* 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.
+ For a complex type, describes the type of each coordinate.
+ 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;
+
+ /* C-v variant chain. This points to a type that
+ differs from this one only in a const or volatile
+ attribute (or both). The various c-v variants
+ are chained together in a ring. */
+ struct type *cv_type;
+
+ /* Flags about this type. */
+
+ int 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 a function type, a "field" for each parameter type.
+ 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
+ {
+
+
+
+ union field_location
+ {
+ /* Position of this field, counting in bits from start of
+ containing structure.
+ 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.
+ 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;
+
+ /* For a static field, if TYPE_FIELD_STATIC_HAS_ADDR then physaddr
+ is the location (in the target) of the static field.
+ Otherwise, physname is the mangled label of the static field. */
+
+ CORE_ADDR physaddr;
+ char* physname;
+ } loc;
+
+ /* 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.
+ A value of -1 or -2 indicates a static field; -1 means the location
+ is specified by the label loc.physname; -2 means that loc.physaddr
+ specifies the actual address. */
+
+ int bitsize;
+
+ /* In a struct or union 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 (TYPE_CODE_STRUCT), VPTR_BASETYPE
+ is the base class which defined the virtual function table pointer.
+
+ For types that are pointer to member types (TYPE_CODE_MEMBER),
+ VPTR_BASETYPE is the type that this pointer is a member of.
+
+ For method types (TYPE_CODE_METHOD), VPTR_BASETYPE is the aggregate
+ type that contains the method.
+
+ 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.
+ Contains the type of each argument, ending with a void type
+ after the last argument for normal member functions or a NULL
+ pointer after the last argument for functions with variable
+ arguments. */
+
+ 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, not including the
+ methods that it derives from. */
+
+ short nfn_fields_total;
+
+ /* The "declared_type" field contains a code saying how the
+ user really declared this type, e.g., "class s", "union s",
+ "struct s".
+ The 3 above things come out from the C++ compiler looking like classes,
+ but we keep track of the real declaration so we can give
+ the correct information on "ptype". (Note: TEMPLATE may not
+ belong in this list...) */
+
+#define DECLARED_TYPE_CLASS 0
+#define DECLARED_TYPE_UNION 1
+#define DECLARED_TYPE_STRUCT 2
+#define DECLARED_TYPE_TEMPLATE 3
+ short declared_type; /* One of the above codes */
+
+ /* 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 with fields to be ignored, either this is optimized out
+ or this field has length 0 */
+
+ B_TYPE *ignore_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 function type for the method.
+ (This comment used to say "The return value of the method",
+ but that's wrong. The function type
+ is expected here, i.e. something with TYPE_CODE_FUNC,
+ and *not* the return-value type). */
+
+ 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. Should not contain
+ a `this' pointer for static member functions. */
+
+ 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;
+ unsigned int is_public : 1;
+ unsigned int is_abstract : 1;
+ unsigned int is_static : 1;
+ unsigned int is_final : 1;
+ unsigned int is_synchronized : 1;
+ unsigned int is_native : 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;
+
+ /* C++ method that is inlined */
+ unsigned int is_inlined : 1;
+
+ /* Unused. */
+ unsigned int dummy : 4;
+
+ /* Index into that baseclass's virtual function table,
+ minus 2; else if static: VOFFSET_STATIC; else: 0. */
+
+ unsigned int voffset : 16;
+
+# define VOFFSET_STATIC 1
+
+ } *fn_fields;
+
+ } *fn_fieldlists;
+
+ /* If this "struct type" describes a template, then it
+ * has arguments. "template_args" points to an array of
+ * template arg descriptors, of length "ntemplate_args".
+ * The only real information in each of these template arg descriptors
+ * is a name. "type" will typically just point to a "struct type" with
+ * the placeholder TYPE_CODE_TEMPLATE_ARG type.
+ */
+ short ntemplate_args;
+ struct template_arg
+ {
+ char *name;
+ struct type *type;
+ } *template_args;
+
+ /* If this "struct type" describes a template, it has a list
+ * of instantiations. "instantiations" is a pointer to an array
+ * of type's, one representing each instantiation. There
+ * are "ninstantiations" elements in this array.
+ */
+ short ninstantiations;
+ struct type **instantiations;
+
+ /* The following points to information relevant to the runtime model
+ * of the compiler.
+ * Currently being used only for HP's ANSI C++ compiler.
+ * (This type may have to be changed/enhanced for other compilers.)
+ *
+ * RUNTIME_PTR is NULL if there is no runtime information (currently
+ * this means the type was not compiled by HP aCC).
+ *
+ * Fields in structure pointed to:
+ * ->HAS_VTABLE : 0 => no virtual table, 1 => vtable present
+ *
+ * ->PRIMARY_BASE points to the first non-virtual base class that has
+ * a virtual table.
+ *
+ * ->VIRTUAL_BASE_LIST points to a list of struct type * pointers that
+ * point to the type information for all virtual bases among this type's
+ * ancestors.
+ */
+ struct runtime_info {
+ short has_vtable;
+ struct type * primary_base;
+ struct type ** virtual_base_list;
+ } * runtime_ptr;
+
+ /* Pointer to information about enclosing scope, if this is a
+ * local type. If it is not a local type, this is NULL
+ */
+ struct local_type_info {
+ char * file;
+ int line;
+ } * localtype_ptr;
+};
+
+/* Struct used in computing virtual base list */
+struct vbase
+{
+ struct type * vbasetype; /* pointer to virtual base */
+ struct vbase * next; /* next in chain */
+};
+
+/* Struct used for ranking a function for overload resolution */
+struct badness_vector {
+ int length;
+ int * rank;
+};
+
+/* 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_CV_TYPE(thistype) (thistype)->cv_type
+/* Note that if thistype is a TYPEDEF type, you have to call check_typedef.
+ But check_typedef does set the TYPE_LENGTH of the TYPEDEF type,
+ so you only have to call check_typedef once. Since allocate_value
+ calls check_typedef, TYPE_LENGTH (VALUE_TYPE (X)) is safe. */
+#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_NOSIGN(thistype) ((thistype)->flags & TYPE_FLAG_NOSIGN)
+#define TYPE_CONST(thistype) ((thistype)->flags & TYPE_FLAG_CONST)
+#define TYPE_VOLATILE(thistype) ((thistype)->flags & TYPE_FLAG_VOLATILE)
+#define TYPE_INCOMPLETE(thistype) ((thistype)->flags & TYPE_FLAG_INCOMPLETE)
+/* Note that TYPE_CODE can be TYPE_CODE_TYPEDEF, so if you wan the real
+ type, you need to do TYPE_CODE (check_type (this_type)). */
+#define TYPE_CODE(thistype) (thistype)->code
+#define TYPE_NFIELDS(thistype) (thistype)->nfields
+#define TYPE_FIELDS(thistype) (thistype)->fields
+#define TYPE_TEMPLATE_ARGS(thistype) TYPE_CPLUS_SPECIFIC(thistype)->template_args
+#define TYPE_INSTANTIATIONS(thistype) TYPE_CPLUS_SPECIFIC(thistype)->instantiations
+
+#define TYPE_INDEX_TYPE(type) TYPE_FIELD_TYPE (type, 0)
+#define TYPE_LOW_BOUND(range_type) TYPE_FIELD_BITPOS (range_type, 0)
+#define TYPE_HIGH_BOUND(range_type) TYPE_FIELD_BITPOS (range_type, 1)
+
+/* Moto-specific stuff for FORTRAN arrays */
+
+#define TYPE_ARRAY_UPPER_BOUND_TYPE(thistype) (thistype)->upper_bound_type
+#define TYPE_ARRAY_LOWER_BOUND_TYPE(thistype) (thistype)->lower_bound_type
+
+#define TYPE_ARRAY_UPPER_BOUND_VALUE(arraytype) \
+ (TYPE_FIELD_BITPOS((TYPE_FIELD_TYPE((arraytype),0)),1))
+
+#define TYPE_ARRAY_LOWER_BOUND_VALUE(arraytype) \
+ (TYPE_FIELD_BITPOS((TYPE_FIELD_TYPE((arraytype),0)),0))
+
+/* 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_NTEMPLATE_ARGS(thistype) TYPE_CPLUS_SPECIFIC(thistype)->ntemplate_args
+#define TYPE_NINSTANTIATIONS(thistype) TYPE_CPLUS_SPECIFIC(thistype)->ninstantiations
+#define TYPE_DECLARED_TYPE(thistype) TYPE_CPLUS_SPECIFIC(thistype)->declared_type
+#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) TYPE_FIELD_BITPOS(thistype,index)
+#define BASETYPE_VIA_PUBLIC(thistype, index) \
+ ((!TYPE_FIELD_PRIVATE(thistype, index)) && (!TYPE_FIELD_PROTECTED(thistype, index)))
+
+#define BASETYPE_VIA_VIRTUAL(thistype, index) \
+ (TYPE_CPLUS_SPECIFIC(thistype)->virtual_field_bits == NULL ? 0 \
+ : B_TST(TYPE_CPLUS_SPECIFIC(thistype)->virtual_field_bits, (index)))
+
+#define FIELD_TYPE(thisfld) ((thisfld).type)
+#define FIELD_NAME(thisfld) ((thisfld).name)
+#define FIELD_BITPOS(thisfld) ((thisfld).loc.bitpos)
+#define FIELD_BITSIZE(thisfld) ((thisfld).bitsize)
+#define FIELD_PHYSNAME(thisfld) ((thisfld).loc.physname)
+#define FIELD_PHYSADDR(thisfld) ((thisfld).loc.physaddr)
+#define SET_FIELD_PHYSNAME(thisfld, name) \
+ ((thisfld).bitsize = -1, FIELD_PHYSNAME(thisfld) = (name))
+#define SET_FIELD_PHYSADDR(thisfld, name) \
+ ((thisfld).bitsize = -2, FIELD_PHYSADDR(thisfld) = (name))
+#define TYPE_FIELD(thistype, n) (thistype)->fields[n]
+#define TYPE_FIELD_TYPE(thistype, n) FIELD_TYPE(TYPE_FIELD(thistype, n))
+#define TYPE_FIELD_NAME(thistype, n) FIELD_NAME(TYPE_FIELD(thistype, n))
+#define TYPE_FIELD_BITPOS(thistype, n) FIELD_BITPOS(TYPE_FIELD(thistype,n))
+#define TYPE_FIELD_BITSIZE(thistype, n) FIELD_BITSIZE(TYPE_FIELD(thistype,n))
+#define TYPE_FIELD_PACKED(thistype, n) (FIELD_BITSIZE(TYPE_FIELD(thistype,n))!=0)
+#define TYPE_TEMPLATE_ARG(thistype, n) TYPE_CPLUS_SPECIFIC(thistype)->template_args[n]
+#define TYPE_INSTANTIATION(thistype, n) TYPE_CPLUS_SPECIFIC(thistype)->instantiations[n]
+
+#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_IGNORE_BITS(thistype) \
+ TYPE_CPLUS_SPECIFIC(thistype)->ignore_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_IGNORE(thistype, n) \
+ B_SET (TYPE_CPLUS_SPECIFIC(thistype)->ignore_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_IGNORE(thistype, n) \
+ (TYPE_CPLUS_SPECIFIC(thistype)->ignore_field_bits == NULL ? 0 \
+ : B_TST(TYPE_CPLUS_SPECIFIC(thistype)->ignore_field_bits, (n)))
+#define TYPE_FIELD_VIRTUAL(thistype, n) \
+ (TYPE_CPLUS_SPECIFIC(thistype)->virtual_field_bits == NULL ? 0 \
+ : B_TST(TYPE_CPLUS_SPECIFIC(thistype)->virtual_field_bits, (n)))
+
+#define TYPE_FIELD_STATIC(thistype, n) ((thistype)->fields[n].bitsize < 0)
+#define TYPE_FIELD_STATIC_HAS_ADDR(thistype, n) ((thistype)->fields[n].bitsize == -2)
+#define TYPE_FIELD_STATIC_PHYSNAME(thistype, n) FIELD_PHYSNAME(TYPE_FIELD(thistype, n))
+#define TYPE_FIELD_STATIC_PHYSADDR(thistype, n) FIELD_PHYSADDR(TYPE_FIELD(thistype, n))
+
+#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_PUBLIC(thisfn, n) ((thisfn)[n].is_public)
+#define TYPE_FN_FIELD_STATIC(thisfn, n) ((thisfn)[n].is_static)
+#define TYPE_FN_FIELD_FINAL(thisfn, n) ((thisfn)[n].is_final)
+#define TYPE_FN_FIELD_SYNCHRONIZED(thisfn, n) ((thisfn)[n].is_synchronized)
+#define TYPE_FN_FIELD_NATIVE(thisfn, n) ((thisfn)[n].is_native)
+#define TYPE_FN_FIELD_ABSTRACT(thisfn, n) ((thisfn)[n].is_abstract)
+#define TYPE_FN_FIELD_STUB(thisfn, n) ((thisfn)[n].is_stub)
+#define TYPE_FN_FIELD_INLINED(thisfn, n) ((thisfn)[n].is_inlined)
+#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)
+
+#define TYPE_RUNTIME_PTR(thistype) (TYPE_CPLUS_SPECIFIC(thistype)->runtime_ptr)
+#define TYPE_VTABLE(thistype) (TYPE_RUNTIME_PTR(thistype)->has_vtable)
+#define TYPE_HAS_VTABLE(thistype) (TYPE_RUNTIME_PTR(thistype) && TYPE_VTABLE(thistype))
+#define TYPE_PRIMARY_BASE(thistype) (TYPE_RUNTIME_PTR(thistype)->primary_base)
+#define TYPE_VIRTUAL_BASE_LIST(thistype) (TYPE_RUNTIME_PTR(thistype)->virtual_base_list)
+
+#define TYPE_LOCALTYPE_PTR(thistype) (TYPE_CPLUS_SPECIFIC(thistype)->localtype_ptr)
+#define TYPE_LOCALTYPE_FILE(thistype) (TYPE_CPLUS_SPECIFIC(thistype)->localtype_ptr->file)
+#define TYPE_LOCALTYPE_LINE(thistype) (TYPE_CPLUS_SPECIFIC(thistype)->localtype_ptr->line)
+
+#define TYPE_IS_OPAQUE(thistype) (((TYPE_CODE (thistype) == TYPE_CODE_STRUCT) || \
+ (TYPE_CODE (thistype) == TYPE_CODE_UNION)) && \
+ (TYPE_NFIELDS (thistype) == 0) && \
+ (TYPE_CPLUS_SPECIFIC (thistype) && (TYPE_NFN_FIELDS (thistype) == 0)))
+
+
+
+/* Implicit sizes */
+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;
+extern struct type *builtin_type_bool;
+
+/* Explicit sizes - see <intypes.h> for naming schema */
+extern struct type *builtin_type_int8;
+extern struct type *builtin_type_uint8;
+extern struct type *builtin_type_int16;
+extern struct type *builtin_type_uint16;
+extern struct type *builtin_type_int32;
+extern struct type *builtin_type_uint32;
+extern struct type *builtin_type_int64;
+extern struct type *builtin_type_uint64;
+
+/* 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;
+
+/* Fortran (F77) types */
+
+extern struct type *builtin_type_f_character;
+extern struct type *builtin_type_f_integer;
+extern struct type *builtin_type_f_logical;
+extern struct type *builtin_type_f_logical_s1;
+extern struct type *builtin_type_f_logical_s2;
+extern struct type *builtin_type_f_integer;
+extern struct type *builtin_type_f_integer_s2;
+extern struct type *builtin_type_f_real;
+extern struct type *builtin_type_f_real_s8;
+extern struct type *builtin_type_f_real_s16;
+extern struct type *builtin_type_f_complex_s8;
+extern struct type *builtin_type_f_complex_s16;
+extern struct type *builtin_type_f_complex_s32;
+extern struct type *builtin_type_f_void;
+
+/* RTTI for C++ */
+/* extern struct type *builtin_type_cxx_typeinfo; */
+
+/* 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 *
+make_cv_type PARAMS ((int, int, 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 *create_set_type PARAMS ((struct type *, struct type *));
+
+extern int chill_varying_type PARAMS ((struct type*));
+
+extern struct type *
+lookup_unsigned_typename PARAMS ((char *));
+
+extern struct type *
+lookup_signed_typename PARAMS ((char *));
+
+extern struct type *
+check_typedef PARAMS ((struct type *));
+
+#define CHECK_TYPEDEF(TYPE) (TYPE) = check_typedef (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 *));
+
+extern int get_destructor_fn_field PARAMS ((struct type *, int *, int *));
+
+extern int get_discrete_bounds PARAMS ((struct type*, LONGEST*, LONGEST*));
+
+extern int
+is_ancestor PARAMS ((struct type *, struct type *));
+
+extern int
+has_vtable PARAMS ((struct type *));
+
+extern struct type *
+primary_base_class PARAMS ((struct type *));
+
+extern struct type **
+virtual_base_list PARAMS ((struct type *));
+
+extern int
+virtual_base_list_length PARAMS ((struct type *));
+extern int
+virtual_base_list_length_skip_primaries PARAMS ((struct type *));
+
+extern int
+virtual_base_index PARAMS ((struct type *, struct type *));
+extern int
+virtual_base_index_skip_primaries PARAMS ((struct type *, struct type *));
+
+
+extern int
+class_index_in_primary_list PARAMS ((struct type *));
+
+extern int
+count_virtual_fns PARAMS ((struct type*));
+
+/* Constants for HP/Taligent ANSI C++ runtime model */
+
+/* Where virtual function entries begin in the
+ * virtual table, in the non-RRBC vtable format.
+ * First 4 are the metavtable pointer, top offset,
+ * typeinfo pointer, and dup base info pointer */
+#define HP_ACC_VFUNC_START 4
+
+/* (Negative) Offset where virtual base offset entries begin
+ * in the virtual table. Skips over metavtable pointer and
+ * the self-offset entry.
+ * NOTE: NEGATE THIS BEFORE USING! The virtual base offsets
+ * appear before the address point of the vtable (the slot
+ * pointed to by the object's vtable pointer), i.e. at lower
+ * addresses than the vtable pointer. */
+#define HP_ACC_VBASE_START 2
+
+/* (Positive) Offset where the pointer to the typeinfo
+ * object is present in the virtual table */
+#define HP_ACC_TYPEINFO_OFFSET 2
+
+/* (Positive) Offset where the ``top offset'' entry of
+ * the virtual table is */
+#define HP_ACC_TOP_OFFSET_OFFSET 1
+
+/* Overload resolution */
+
+#define LENGTH_MATCH(bv) ((bv)->rank[0])
+
+/* Badness if parameter list length doesn't match arg list length */
+#define LENGTH_MISMATCH_BADNESS 100
+/* Dummy badness value for nonexistent parameter positions */
+#define TOO_FEW_PARAMS_BADNESS 100
+/* Badness if no conversion among types */
+#define INCOMPATIBLE_TYPE_BADNESS 100
+/* Badness of coercing large integer to smaller size */
+#define INTEGER_COERCION_BADNESS 100
+/* Badness of coercing large floating type to smaller size */
+#define FLOAT_COERCION_BADNESS 100
+
+/* Badness of integral promotion */
+#define INTEGER_PROMOTION_BADNESS 1
+/* Badness of floating promotion */
+#define FLOAT_PROMOTION_BADNESS 1
+/* Badness of integral conversion */
+#define INTEGER_CONVERSION_BADNESS 2
+/* Badness of floating conversion */
+#define FLOAT_CONVERSION_BADNESS 2
+/* Badness of integer<->floating conversions */
+#define INT_FLOAT_CONVERSION_BADNESS 2
+/* Badness of converting to a boolean */
+#define BOOLEAN_CONVERSION_BADNESS 2
+/* Badness of pointer conversion */
+#define POINTER_CONVERSION_BADNESS 2
+/* Badness of conversion of pointer to void pointer */
+#define VOID_PTR_CONVERSION_BADNESS 2
+/* Badness of convering derived to base class */
+#define BASE_CONVERSION_BADNESS 2
+
+/* Non-standard conversions allowed by the debugger */
+/* Converting a pointer to an int is usually OK */
+#define NS_POINTER_CONVERSION_BADNESS 10
+
+
+extern int
+compare_badness PARAMS ((struct badness_vector *, struct badness_vector *));
+
+extern struct badness_vector *
+rank_function PARAMS ((struct type **, int, struct type **, int));
+
+extern int
+rank_one_type PARAMS ((struct type *, 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, GDB_FILE *));
+
+extern int can_dereference PARAMS ((struct type *));
+
+#if MAINTENANCE_CMDS
+extern void maintenance_print_type PARAMS ((char *, int));
+#endif
+
+/* typeprint.c */
+
+extern void print_type_scalar PARAMS ((struct type *, LONGEST, GDB_FILE *));
+
+#endif /* GDBTYPES_H */
diff --git a/gdb/gnu-nat.c b/gdb/gnu-nat.c
new file mode 100644
index 00000000000..156d981f68f
--- /dev/null
+++ b/gdb/gnu-nat.c
@@ -0,0 +1,3201 @@
+/* Interface GDB to the GNU Hurd
+ Copyright (C) 1992, 1995, 1996, 1997 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ Written by Miles Bader <miles@gnu.ai.mit.edu>
+
+ Some code and ideas from m3-nat.c by Jukka Virtanen <jtv@hut.fi>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include <stdio.h>
+#include <errno.h>
+#include <signal.h>
+#include <assert.h>
+#include <setjmp.h>
+#include <limits.h>
+#include <sys/ptrace.h>
+
+/* We include this because we don't need the access macros and they conflict
+ with gdb's definitions (ick). This is very non standard! */
+#include <waitflags.h>
+
+#include <mach.h>
+#include <mach/message.h>
+#include <mach/notify.h>
+#include <mach_error.h>
+#include <mach/exception.h>
+#include <mach/vm_attributes.h>
+
+#include <hurd/process.h>
+#include <hurd/process_request.h>
+#include <hurd/msg.h>
+#include <hurd/msg_request.h>
+#include <hurd/signal.h>
+#include <hurd/interrupt.h>
+#include <hurd/sigpreempt.h>
+
+#include <portinfo.h>
+
+#include "defs.h"
+#include "inferior.h"
+#include "symtab.h"
+#include "value.h"
+#include "language.h"
+#include "target.h"
+#include "wait.h"
+#include "gdbcmd.h"
+#include "gdbcore.h"
+
+#include "gnu-nat.h"
+
+#include "exc_request_S.h"
+#include "notify_S.h"
+#include "process_reply_S.h"
+#include "msg_reply_S.h"
+#include "exc_request_U.h"
+#include "msg_U.h"
+
+static process_t proc_server = MACH_PORT_NULL;
+
+/* If we've sent a proc_wait_request to the proc server, the pid of the
+ process we asked about. We can only ever have one outstanding. */
+int proc_wait_pid = 0;
+
+/* The number of wait requests we've sent, and expect replies from. */
+int proc_waits_pending = 0;
+
+int gnu_debug_flag = 0;
+
+/* Forward decls */
+
+extern struct target_ops gnu_ops;
+extern char *strerror();
+
+int inf_update_procs (struct inf *inf);
+struct inf *make_inf ();
+void inf_clear_wait (struct inf *inf);
+void inf_cleanup (struct inf *inf);
+void inf_startup (struct inf *inf, int pid);
+int inf_update_suspends (struct inf *inf);
+void inf_set_pid (struct inf *inf, pid_t pid);
+void inf_validate_procs (struct inf *inf);
+void inf_steal_exc_ports (struct inf *inf);
+void inf_restore_exc_ports (struct inf *inf);
+struct proc *inf_tid_to_proc (struct inf *inf, int tid);
+inline void inf_set_threads_resume_sc (struct inf *inf,
+ struct proc *run_thread,
+ int run_others);
+inline int inf_set_threads_resume_sc_for_signal_thread (struct inf *inf);
+inline void inf_suspend (struct inf *inf);
+inline void inf_resume (struct inf *inf);
+void inf_set_step_thread (struct inf *inf, struct proc *proc);
+void inf_detach (struct inf *inf);
+void inf_attach (struct inf *inf, int pid);
+void inf_signal (struct inf *inf, enum target_signal sig);
+
+#define inf_debug(_inf, msg, args...) \
+ do { struct inf *__inf = (_inf); \
+ debug ("{inf %d %p}: " msg, __inf->pid, __inf , ##args); } while (0)
+
+void proc_abort (struct proc *proc, int force);
+thread_state_t proc_get_state (struct proc *proc, int force);
+struct proc *make_proc (struct inf *inf, mach_port_t port, int tid);
+struct proc *_proc_free (struct proc *proc);
+int proc_update_sc (struct proc *proc);
+error_t proc_get_exception_port (struct proc *proc, mach_port_t *port);
+error_t proc_set_exception_port (struct proc *proc, mach_port_t port);
+static mach_port_t _proc_get_exc_port (struct proc *proc);
+void proc_steal_exc_port (struct proc *proc, mach_port_t exc_port);
+void proc_restore_exc_port (struct proc *proc);
+int proc_trace (struct proc *proc, int set);
+char *proc_string (struct proc *proc);
+
+/* Evaluate RPC_EXPR in a scope with the variables MSGPORT and REFPORT bound
+ to INF's msg port and task port respectively. If it has no msg port,
+ EIEIO is returned. INF must refer to a running process! */
+#define INF_MSGPORT_RPC(inf, rpc_expr) \
+ HURD_MSGPORT_RPC (proc_getmsgport (proc_server, inf->pid, &msgport), \
+ (refport = inf->task->port, 0), 0, \
+ msgport ? (rpc_expr) : EIEIO)
+
+/* Like INF_MSGPORT_RPC, but will also resume the signal thread to ensure
+ there's someone around to deal with the RPC (and resuspend things
+ afterwards). This effects INF's threads' resume_sc count. */
+#define INF_RESUME_MSGPORT_RPC(inf, rpc_expr) \
+ (inf_set_threads_resume_sc_for_signal_thread (inf) \
+ ? ({ error_t __e; \
+ inf_resume (inf); \
+ __e = INF_MSGPORT_RPC (inf, rpc_expr); \
+ inf_suspend (inf); \
+ __e; }) \
+ : EIEIO)
+
+#define MIG_SERVER_DIED EMIG_SERVER_DIED /* XXX */
+
+/* The state passed by an exception message. */
+struct exc_state
+{
+ int exception; /* The exception code */
+ int code, subcode;
+ mach_port_t handler; /* The real exception port to handle this. */
+ mach_port_t reply; /* The reply port from the exception call. */
+};
+
+/* The results of the last wait an inf did. */
+struct inf_wait
+{
+ struct target_waitstatus status; /* The status returned to gdb. */
+ struct exc_state exc; /* The exception that caused us to return. */
+ struct proc *thread; /* The thread in question. */
+ int suppress; /* Something trivial happened. */
+};
+
+/* The state of an inferior. */
+struct inf
+{
+ /* Fields describing the current inferior. */
+
+ struct proc *task; /* The mach task. */
+ struct proc *threads; /* A linked list of all threads in TASK. */
+
+ /* True if THREADS needn't be validated by querying the task. We assume that
+ we and the task in question are the only ones frobbing the thread list,
+ so as long as we don't let any code run, we don't have to worry about
+ THREADS changing. */
+ int threads_up_to_date;
+
+ pid_t pid; /* The real system PID. */
+
+ struct inf_wait wait; /* What to return from target_wait. */
+
+ /* One thread proc in INF may be in `single-stepping mode'. This is it. */
+ struct proc *step_thread;
+
+ /* The thread we think is the signal thread. */
+ struct proc *signal_thread;
+
+ mach_port_t event_port; /* Where we receive various msgs. */
+
+ /* True if we think at least one thread in the inferior could currently be
+ running. */
+ int running : 1;
+
+ /* True if the process has stopped (in the proc server sense). Note that
+ since a proc server `stop' leaves the signal thread running, the inf can
+ be RUNNING && STOPPED... */
+ int stopped : 1;
+
+ /* True if the inferior is traced. */
+ int traced : 1;
+
+ /* True if we shouldn't try waiting for the inferior, usually because we
+ can't for some reason. */
+ int no_wait : 1;
+
+ /* When starting a new inferior, we don't try to validate threads until all
+ the proper execs have been done. This is a count of how many execs we
+ expect to happen. */
+ unsigned pending_execs;
+
+ /* Fields describing global state */
+
+ /* The task suspend count used when gdb has control. This is normally 1 to
+ make things easier for us, but sometimes (like when attaching to vital
+ system servers) it may be desirable to let the task continue to run
+ (pausing individual threads as necessary). */
+ int pause_sc;
+
+ /* The task suspend count left when detaching from a task. */
+ int detach_sc;
+
+ /* The initial values used for the run_sc and pause_sc of newly discovered
+ threads -- see the definition of those fields in struct proc. */
+ int default_thread_run_sc;
+ int default_thread_pause_sc;
+ int default_thread_detach_sc;
+
+ /* True if the process should be traced when started/attached. Newly
+ started processes *must* be traced at first to exec them properly, but
+ if this is false, tracing is turned off as soon it has done so. */
+ int want_signals;
+
+ /* True if exceptions from the inferior process should be trapped. This
+ must be on to use breakpoints. */
+ int want_exceptions;
+};
+
+
+int __proc_pid (struct proc *proc)
+{
+ return proc->inf->pid;
+}
+
+/* Update PROC's real suspend count to match it's desired one. Returns true
+ if we think PROC is now in a runnable state. */
+int
+proc_update_sc (struct proc *proc)
+{
+ int running;
+ int err = 0;
+ int delta = proc->sc - proc->cur_sc;
+
+ if (delta)
+ proc_debug (proc, "sc: %d --> %d", proc->cur_sc, proc->sc);
+
+ if (proc->sc == 0 && proc->state_changed)
+ /* Since PROC may start running, we must write back any state changes. */
+ {
+ assert (proc_is_thread (proc));
+ proc_debug (proc, "storing back changed thread state");
+ err = thread_set_state (proc->port, THREAD_STATE_FLAVOR,
+ (thread_state_t)&proc->state, THREAD_STATE_SIZE);
+ if (! err)
+ proc->state_changed = 0;
+ }
+
+ if (delta > 0)
+ while (delta-- > 0 && !err)
+ if (proc_is_task (proc))
+ err = task_suspend (proc->port);
+ else
+ err = thread_suspend (proc->port);
+ else
+ while (delta++ < 0 && !err)
+ if (proc_is_task (proc))
+ err = task_resume (proc->port);
+ else
+ err = thread_resume (proc->port);
+
+ if (! err)
+ proc->cur_sc = proc->sc;
+
+ /* If we got an error, then the task/thread has disappeared. */
+ running = !err && proc->sc == 0;
+
+ proc_debug (proc, "is %s", err ? "dead" : running ? "running" : "suspended");
+ if (err)
+ proc_debug (proc, "err = %s", strerror (err));
+
+ if (running)
+ {
+ proc->aborted = 0;
+ proc->state_valid = proc->state_changed = 0;
+ proc->fetched_regs = 0;
+ }
+
+ return running;
+}
+
+/* Thread_abort is called on PROC if needed. PROC must be a thread proc.
+ If PROC is deemed `precious', then nothing is done unless FORCE is true.
+ In particular, a thread is precious if it's running (in which case forcing
+ it includes suspending it first), or if it has an exception pending. */
+void
+proc_abort (struct proc *proc, int force)
+{
+ assert (proc_is_thread (proc));
+
+ if (! proc->aborted)
+ {
+ struct inf *inf = proc->inf;
+ int running = (proc->cur_sc == 0 && inf->task->cur_sc == 0);
+
+ if (running && force)
+ {
+ proc->sc = 1;
+ inf_update_suspends (proc->inf);
+ running = 0;
+ warning ("Stopped %s.", proc_string (proc));
+ }
+ else if (proc == inf->wait.thread && inf->wait.exc.reply && !force)
+ /* An exception is pending on PROC, which don't mess with. */
+ running = 1;
+
+ if (! running)
+ /* We only abort the thread if it's not actually running. */
+ {
+ thread_abort (proc->port);
+ proc_debug (proc, "aborted");
+ proc->aborted = 1;
+ }
+ else
+ proc_debug (proc, "not aborting");
+ }
+}
+
+/* Make sure that the state field in PROC is up to date, and return a pointer
+ to it, or 0 if something is wrong. If WILL_MODIFY is true, makes sure
+ that the thread is stopped and aborted first, and sets the state_changed
+ field in PROC to true. */
+thread_state_t
+proc_get_state (struct proc *proc, int will_modify)
+{
+ int was_aborted = proc->aborted;
+
+ proc_debug (proc, "updating state info%s",
+ will_modify ? " (with intention to modify)" : "");
+
+ proc_abort (proc, will_modify);
+
+ if (! was_aborted && proc->aborted)
+ /* PROC's state may have changed since we last fetched it. */
+ proc->state_valid = 0;
+
+ if (! proc->state_valid)
+ {
+ mach_msg_type_number_t state_size = THREAD_STATE_SIZE;
+ error_t err =
+ thread_get_state (proc->port, THREAD_STATE_FLAVOR,
+ (thread_state_t)&proc->state, &state_size);
+ proc_debug (proc, "getting thread state");
+ proc->state_valid = !err;
+ }
+
+ if (proc->state_valid)
+ {
+ if (will_modify)
+ proc->state_changed = 1;
+ return (thread_state_t)&proc->state;
+ }
+ else
+ return 0;
+}
+
+/* Set PORT to PROC's exception port. */
+error_t
+proc_get_exception_port (struct proc *proc, mach_port_t *port)
+{
+ if (proc_is_task (proc))
+ return task_get_exception_port (proc->port, port);
+ else
+ return thread_get_exception_port (proc->port, port);
+}
+
+/* Set PROC's exception port to PORT. */
+error_t
+proc_set_exception_port (struct proc *proc, mach_port_t port)
+{
+ proc_debug (proc, "setting exception port: %d", port);
+ if (proc_is_task (proc))
+ return task_set_exception_port (proc->port, port);
+ else
+ return thread_set_exception_port (proc->port, port);
+}
+
+/* Get PROC's exception port, cleaning up a bit if proc has died. */
+static mach_port_t
+_proc_get_exc_port (struct proc *proc)
+{
+ mach_port_t exc_port;
+ error_t err = proc_get_exception_port (proc, &exc_port);
+
+ if (err)
+ /* PROC must be dead. */
+ {
+ if (proc->exc_port)
+ mach_port_deallocate (mach_task_self (), proc->exc_port);
+ proc->exc_port = MACH_PORT_NULL;
+ if (proc->saved_exc_port)
+ mach_port_deallocate (mach_task_self (), proc->saved_exc_port);
+ proc->saved_exc_port = MACH_PORT_NULL;
+ }
+
+ return exc_port;
+}
+
+/* Replace PROC's exception port with EXC_PORT, unless it's already been
+ done. Stash away any existing exception port so we can restore it later. */
+void
+proc_steal_exc_port (struct proc *proc, mach_port_t exc_port)
+{
+ mach_port_t cur_exc_port = _proc_get_exc_port (proc);
+
+ if (cur_exc_port)
+ {
+ error_t err;
+
+ proc_debug (proc, "inserting exception port: %d", exc_port);
+
+ if (cur_exc_port != exc_port)
+ /* Put in our exception port. */
+ err = proc_set_exception_port (proc, exc_port);
+
+ if (err || cur_exc_port == proc->exc_port)
+ /* We previously set the exception port, and it's still set. So we
+ just keep the old saved port which is what the proc set. */
+ {
+ if (cur_exc_port)
+ mach_port_deallocate (mach_task_self (), cur_exc_port);
+ }
+ else
+ /* Keep a copy of PROC's old exception port so it can be restored. */
+ {
+ if (proc->saved_exc_port)
+ mach_port_deallocate (mach_task_self (), proc->saved_exc_port);
+ proc->saved_exc_port = cur_exc_port;
+ }
+
+ proc_debug (proc, "saved exception port: %d", proc->saved_exc_port);
+
+ if (!err)
+ proc->exc_port = exc_port;
+ else
+ warning ("Error setting exception port for %s: %s",
+ proc_string (proc), strerror (err));
+ }
+}
+
+/* If we previously replaced PROC's exception port, put back what we
+ found there at the time, unless *our* exception port has since been
+ overwritten, in which case who knows what's going on. */
+void
+proc_restore_exc_port (struct proc *proc)
+{
+ mach_port_t cur_exc_port = _proc_get_exc_port (proc);
+
+ if (cur_exc_port)
+ {
+ error_t err = 0;
+
+ proc_debug (proc, "restoring real exception port");
+
+ if (proc->exc_port == cur_exc_port)
+ /* Our's is still there. */
+ err = proc_set_exception_port (proc, proc->saved_exc_port);
+
+ if (proc->saved_exc_port)
+ mach_port_deallocate (mach_task_self (), proc->saved_exc_port);
+ proc->saved_exc_port = MACH_PORT_NULL;
+
+ if (!err)
+ proc->exc_port = MACH_PORT_NULL;
+ else
+ warning ("Error setting exception port for %s: %s",
+ proc_string (proc), strerror (err));
+ }
+}
+
+/* Turns hardware tracing in PROC on or off when SET is true or false,
+ respectively. Returns true on success. */
+int
+proc_trace (struct proc *proc, int set)
+{
+ thread_state_t state = proc_get_state (proc, 1);
+
+ if (! state)
+ return 0; /* the thread must be dead. */
+
+ proc_debug (proc, "tracing %s", set ? "on" : "off");
+
+ if (set)
+ {
+ /* XXX We don't get the exception unless the thread has its own
+ exception port???? */
+ if (proc->exc_port == MACH_PORT_NULL)
+ proc_steal_exc_port (proc, proc->inf->event_port);
+ THREAD_STATE_SET_TRACED (state);
+ }
+ else
+ THREAD_STATE_CLEAR_TRACED (state);
+
+ return 1;
+}
+
+/* A variable from which to assign new TIDs. */
+static int next_thread_id = 1;
+
+/* Returns a new proc structure with the given fields. Also adds a
+ notification for PORT becoming dead to be sent to INF's notify port. */
+struct proc *
+make_proc (struct inf *inf, mach_port_t port, int tid)
+{
+ error_t err;
+ mach_port_t prev_port = MACH_PORT_NULL;
+ struct proc *proc = malloc (sizeof (struct proc));
+
+ proc->port = port;
+ proc->tid = tid;
+ proc->inf = inf;
+ proc->next = 0;
+ proc->saved_exc_port = MACH_PORT_NULL;
+ proc->exc_port = MACH_PORT_NULL;
+
+ proc->sc = 0;
+ proc->cur_sc = 0;
+
+ /* Note that these are all the values for threads; the task simply uses the
+ corresponding field in INF directly. */
+ proc->run_sc = inf->default_thread_run_sc;
+ proc->pause_sc = inf->default_thread_pause_sc;
+ proc->detach_sc = inf->default_thread_detach_sc;
+ proc->resume_sc = proc->run_sc;
+
+ proc->aborted = 0;
+ proc->dead = 0;
+ proc->state_valid = 0;
+ proc->state_changed = 0;
+
+ proc_debug (proc, "is new");
+
+ /* Get notified when things die. */
+ err =
+ mach_port_request_notification (mach_task_self(), port,
+ MACH_NOTIFY_DEAD_NAME, 1,
+ inf->event_port,
+ MACH_MSG_TYPE_MAKE_SEND_ONCE,
+ &prev_port);
+ if (err)
+ warning ("Couldn't request notification for port %d: %s",
+ port, strerror (err));
+ else
+ {
+ proc_debug (proc, "notifications to: %d", inf->event_port);
+ if (prev_port != MACH_PORT_NULL)
+ mach_port_deallocate (mach_task_self (), prev_port);
+ }
+
+ if (inf->want_exceptions)
+ if (proc_is_task (proc))
+ /* Make the task exception port point to us. */
+ proc_steal_exc_port (proc, inf->event_port);
+ else
+ /* Just clear thread exception ports -- they default to the task one. */
+ proc_steal_exc_port (proc, MACH_PORT_NULL);
+
+ return proc;
+}
+
+/* Frees PROC and any resources it uses, and returns the value of PROC's
+ next field. */
+struct proc *
+_proc_free (struct proc *proc)
+{
+ struct inf *inf = proc->inf;
+ struct proc *next = proc->next;
+
+ proc_debug (proc, "freeing...");
+
+ if (proc == inf->step_thread)
+ /* Turn off single stepping. */
+ inf_set_step_thread (inf, 0);
+ if (proc == inf->wait.thread)
+ inf_clear_wait (inf);
+ if (proc == inf->signal_thread)
+ inf->signal_thread = 0;
+
+ if (proc->port != MACH_PORT_NULL)
+ {
+ if (proc->exc_port != MACH_PORT_NULL)
+ /* Restore the original exception port. */
+ proc_restore_exc_port (proc);
+ if (proc->cur_sc != 0)
+ /* Resume the thread/task. */
+ {
+ proc->sc = 0;
+ proc_update_sc (proc);
+ }
+ mach_port_deallocate (mach_task_self (), proc->port);
+ }
+
+ free (proc);
+ return next;
+}
+
+struct inf *make_inf ()
+{
+ struct inf *inf = malloc (sizeof (struct inf));
+
+ if (!inf)
+ return 0;
+
+ inf->task = 0;
+ inf->threads = 0;
+ inf->threads_up_to_date = 0;
+ inf->pid = 0;
+ inf->wait.status.kind = TARGET_WAITKIND_SPURIOUS;
+ inf->wait.thread = 0;
+ inf->wait.exc.handler = MACH_PORT_NULL;
+ inf->wait.exc.reply = MACH_PORT_NULL;
+ inf->step_thread = 0;
+ inf->signal_thread = 0;
+ inf->event_port = MACH_PORT_NULL;
+ inf->stopped = 0;
+ inf->running = 0;
+ inf->traced = 0;
+ inf->no_wait = 0;
+ inf->pending_execs = 0;
+ inf->pause_sc = 1;
+ inf->detach_sc = 0;
+ inf->default_thread_run_sc = 0;
+ inf->default_thread_pause_sc = 0;
+ inf->default_thread_detach_sc = 0;
+ inf->want_signals = 1; /* By default */
+ inf->want_exceptions = 1; /* By default */
+
+ return inf;
+}
+
+/* clear INF's target wait status. */
+void
+inf_clear_wait (struct inf *inf)
+{
+ inf_debug (inf, "clearing wait");
+ inf->wait.status.kind = TARGET_WAITKIND_SPURIOUS;
+ inf->wait.thread = 0;
+ inf->wait.suppress = 0;
+ if (inf->wait.exc.handler != MACH_PORT_NULL)
+ {
+ mach_port_deallocate (mach_task_self (), inf->wait.exc.handler);
+ inf->wait.exc.handler = MACH_PORT_NULL;
+ }
+ if (inf->wait.exc.reply != MACH_PORT_NULL)
+ {
+ mach_port_deallocate (mach_task_self (), inf->wait.exc.reply);
+ inf->wait.exc.reply = MACH_PORT_NULL;
+ }
+}
+
+void
+inf_cleanup (struct inf *inf)
+{
+ inf_debug (inf, "cleanup");
+
+ inf_clear_wait (inf);
+
+ inf_set_pid (inf, -1);
+ inf->pid = 0;
+ inf->traced = 0;
+ inf->no_wait = 0;
+ inf->stopped = 0;
+ inf->running = 0;
+ inf->pending_execs = 0;
+
+ if (inf->event_port)
+ {
+ mach_port_destroy (mach_task_self (), inf->event_port);
+ inf->event_port = MACH_PORT_NULL;
+ }
+}
+
+void
+inf_startup (struct inf *inf, int pid)
+{
+ error_t err;
+
+ inf_debug (inf, "startup: pid = %d", pid);
+
+ inf_cleanup (inf);
+
+ /* Make the port on which we receive all events. */
+ err = mach_port_allocate (mach_task_self (),
+ MACH_PORT_RIGHT_RECEIVE, &inf->event_port);
+ if (err)
+ error ("Error allocating event port: %s", strerror (err));
+
+ /* Make a send right for it, so we can easily copy it for other people. */
+ mach_port_insert_right (mach_task_self (), inf->event_port,
+ inf->event_port, MACH_MSG_TYPE_MAKE_SEND);
+ inf_set_pid (inf, pid);
+}
+
+/* close current process, if any, and attach INF to process PORT */
+void
+inf_set_pid (struct inf *inf, pid_t pid)
+{
+ task_t task_port;
+ struct proc *task = inf->task;
+
+ inf_debug (inf, "setting pid: %d", pid);
+
+ if (pid < 0)
+ task_port = MACH_PORT_NULL;
+ else
+ {
+ error_t err = proc_pid2task (proc_server, pid, &task_port);
+ if (err)
+ error ("Error getting task for pid %d: %s", pid, strerror (err));
+ }
+
+ inf_debug (inf, "setting task: %d", task_port);
+
+ if (inf->pause_sc)
+ task_suspend (task_port);
+
+ if (task && task->port != task_port)
+ {
+ inf->task = 0;
+ inf_validate_procs (inf); /* Trash all the threads. */
+ _proc_free (task); /* And the task. */
+ }
+
+ if (task_port != MACH_PORT_NULL)
+ {
+ inf->task = make_proc (inf, task_port, PROC_TID_TASK);
+ inf->threads_up_to_date = 0;
+ }
+
+ if (inf->task)
+ {
+ inf->pid = pid;
+ if (inf->pause_sc)
+ inf->task->sc = inf->task->cur_sc = 1; /* Reflect task_suspend above */
+ }
+ else
+ inf->pid = -1;
+}
+
+/* Validates INF's stopped field from the actual proc server state. */
+static void
+inf_validate_stopped (struct inf *inf)
+{
+ char *noise;
+ mach_msg_type_number_t noise_len = 0;
+ struct procinfo *pi;
+ mach_msg_type_number_t pi_len = 0;
+ int info_flags = 0;
+ error_t err =
+ proc_getprocinfo (proc_server, inf->pid, &info_flags,
+ (procinfo_t *)&pi, &pi_len, &noise, &noise_len);
+
+ if (! err)
+ {
+ inf->stopped = !!(pi->state & PI_STOPPED);
+ vm_deallocate (mach_task_self (), (vm_address_t)pi, pi_len);
+ if (noise_len > 0)
+ vm_deallocate (mach_task_self (), (vm_address_t)noise, noise_len);
+ }
+}
+
+/* Validates INF's task suspend count. If it's higher than we expect, verify
+ with the user before `stealing' the extra count. */
+static void
+inf_validate_task_sc (struct inf *inf)
+{
+ struct task_basic_info info;
+ mach_msg_type_number_t info_len = TASK_BASIC_INFO_COUNT;
+ error_t err =
+ task_info (inf->task->port, TASK_BASIC_INFO, (task_info_t)&info, &info_len);
+
+ if (err)
+ inf->task->dead = 1; /* oh well */
+ else if (inf->task->cur_sc < info.suspend_count)
+ {
+ int abort;
+
+ target_terminal_ours (); /* Allow I/O. */
+ abort =
+ !query ("Pid %d has an additional task suspend count of %d; clear it? ",
+ inf->pid, info.suspend_count - inf->task->cur_sc);
+ target_terminal_inferior (); /* Give it back to the child. */
+
+ if (abort)
+ error ("Additional task suspend count left untouched.");
+
+ inf->task->cur_sc = info.suspend_count;
+ }
+}
+
+/* Turns tracing for INF on or off, depending on ON, unless it already is.
+ If INF is running, the resume_sc count of INF's threads will be modified,
+ and the signal thread will briefly be run to change the trace state. */
+void
+inf_set_traced (struct inf *inf, int on)
+{
+ if (on != inf->traced)
+ if (inf->task && !inf->task->dead)
+ /* Make it take effect immediately. */
+ {
+ sigset_t mask = on ? ~(sigset_t)0 : 0;
+ error_t err =
+ INF_RESUME_MSGPORT_RPC (inf, msg_set_init_int (msgport, refport,
+ INIT_TRACEMASK, mask));
+ if (err == EIEIO)
+ {
+ if (on)
+ warning ("Can't modify tracing state for pid %d: No signal thread",
+ inf->pid);
+ inf->traced = on;
+ }
+ else if (err)
+ warning ("Can't modify tracing state for pid %d: %s",
+ inf->pid, strerror (err));
+ else
+ inf->traced = on;
+ }
+ else
+ inf->traced = on;
+}
+
+/* Makes all the real suspend count deltas of all the procs in INF match the
+ desired values. Careful to always do thread/task suspend counts in the
+ safe order. Returns true if at least one thread is thought to be running.*/
+int
+inf_update_suspends (struct inf *inf)
+{
+ struct proc *task = inf->task;
+ /* We don't have to update INF->threads even though we're iterating over it
+ because we'll change a thread only if it already has an existing proc
+ entry. */
+
+ inf_debug (inf, "updating suspend counts");
+
+ if (task)
+ {
+ struct proc *thread;
+ int task_running = (task->sc == 0), thread_running = 0;
+
+ if (task->sc > task->cur_sc)
+ /* The task is becoming _more_ suspended; do before any threads. */
+ task_running = proc_update_sc (task);
+
+ if (inf->pending_execs)
+ /* When we're waiting for an exec, things may be happening behind our
+ back, so be conservative. */
+ thread_running = 1;
+
+ /* Do all the thread suspend counts. */
+ for (thread = inf->threads; thread; thread = thread->next)
+ thread_running |= proc_update_sc (thread);
+
+ if (task->sc != task->cur_sc)
+ /* We didn't do the task first, because we wanted to wait for the
+ threads; do it now. */
+ task_running = proc_update_sc (task);
+
+ inf_debug (inf, "%srunning...",
+ (thread_running && task_running) ? "" : "not ");
+
+ inf->running = thread_running && task_running;
+
+ /* Once any thread has executed some code, we can't depend on the
+ threads list any more. */
+ if (inf->running)
+ inf->threads_up_to_date = 0;
+
+ return inf->running;
+ }
+
+ return 0;
+}
+
+/* Converts a GDB pid to a struct proc. */
+struct proc *
+inf_tid_to_thread (struct inf *inf, int tid)
+{
+ struct proc *thread = inf->threads;
+
+ while (thread)
+ if (thread->tid == tid)
+ return thread;
+ else
+ thread = thread->next;
+ return 0;
+}
+
+/* Converts a thread port to a struct proc. */
+struct proc *
+inf_port_to_thread (struct inf *inf, mach_port_t port)
+{
+ struct proc *thread = inf->threads;
+ while (thread)
+ if (thread->port == port)
+ return thread;
+ else
+ thread = thread->next;
+ return 0;
+}
+
+/* Make INF's list of threads be consistent with reality of TASK. */
+void
+inf_validate_procs (struct inf *inf)
+{
+ int i;
+ thread_array_t threads;
+ unsigned num_threads;
+ struct proc *task = inf->task;
+
+ /* If no threads are currently running, this function will guarantee that
+ things are up to date. The exception is if there are zero threads --
+ then it is almost certainly in an odd state, and probably some outside
+ agent will create threads. */
+ inf->threads_up_to_date = inf->threads ? !inf->running : 0;
+
+ if (task)
+ {
+ error_t err = task_threads (task->port, &threads, &num_threads);
+ inf_debug (inf, "fetching threads");
+ if (err)
+ /* TASK must be dead. */
+ {
+ task->dead = 1;
+ task = 0;
+ }
+ }
+
+ if (!task)
+ {
+ num_threads = 0;
+ inf_debug (inf, "no task");
+ }
+
+ {
+ unsigned search_start = 0; /* Make things normally linear. */
+ /* Which thread in PROCS corresponds to each task thread, & the task. */
+ struct proc *matched[num_threads + 1];
+ /* The last thread in INF->threads, so we can add to the end. */
+ struct proc *last = 0;
+ /* The current thread we're considering. */
+ struct proc *thread = inf->threads;
+
+ bzero (matched, sizeof (matched));
+
+ while (thread)
+ {
+ unsigned left;
+
+ for (i = search_start, left = num_threads; left; i++, left--)
+ {
+ if (i >= num_threads)
+ i -= num_threads; /* I wrapped around. */
+ if (thread->port == threads[i])
+ /* We already know about this thread. */
+ {
+ matched[i] = thread;
+ last = thread;
+ thread = thread->next;
+ search_start++;
+ break;
+ }
+ }
+
+ if (! left)
+ {
+ proc_debug (thread, "died!");
+ thread->port = MACH_PORT_NULL;
+ thread = _proc_free (thread); /* THREAD is dead. */
+ (last ? last->next : inf->threads) = thread;
+ }
+ }
+
+ for (i = 0; i < num_threads; i++)
+ if (matched[i])
+ /* Throw away the duplicate send right. */
+ mach_port_deallocate (mach_task_self (), threads[i]);
+ else
+ /* THREADS[I] is a thread we don't know about yet! */
+ {
+ thread = make_proc (inf, threads[i], next_thread_id++);
+ (last ? last->next : inf->threads) = thread;
+ last = thread;
+ proc_debug (thread, "new thread: %d", threads[i]);
+ add_thread (thread->tid); /* Tell GDB's generic thread code. */
+ }
+
+ vm_deallocate(mach_task_self(),
+ (vm_address_t)threads, (num_threads * sizeof(thread_t)));
+ }
+}
+
+/* Makes sure that INF's thread list is synced with the actual process. */
+inline int
+inf_update_procs (struct inf *inf)
+{
+ if (! inf->task)
+ return 0;
+ if (! inf->threads_up_to_date)
+ inf_validate_procs (inf);
+ return !!inf->task;
+}
+
+/* Sets the resume_sc of each thread in inf. That of RUN_THREAD is set to 0,
+ and others are set to their run_sc if RUN_OTHERS is true, and otherwise
+ their pause_sc. */
+inline void
+inf_set_threads_resume_sc (struct inf *inf,
+ struct proc *run_thread, int run_others)
+{
+ struct proc *thread;
+ inf_update_procs (inf);
+ for (thread = inf->threads; thread; thread = thread->next)
+ if (thread == run_thread)
+ thread->resume_sc = 0;
+ else if (run_others)
+ thread->resume_sc = thread->run_sc;
+ else
+ thread->resume_sc = thread->pause_sc;
+}
+
+/* Cause INF to continue execution immediately; individual threads may still
+ be suspended (but their suspend counts will be updated). */
+inline void
+inf_resume (struct inf *inf)
+{
+ struct proc *thread;
+
+ inf_update_procs (inf);
+
+ for (thread = inf->threads; thread; thread = thread->next)
+ thread->sc = thread->resume_sc;
+
+ if (inf->task)
+ {
+ if (! inf->pending_execs)
+ /* Try to make sure our task count is correct -- in the case where
+ we're waiting for an exec though, things are too volatile, so just
+ assume things will be reasonable (which they usually will be). */
+ inf_validate_task_sc (inf);
+ inf->task->sc = 0;
+ }
+
+ inf_update_suspends (inf);
+}
+
+/* Cause INF to stop execution immediately; individual threads may still
+ be running. */
+inline void
+inf_suspend (struct inf *inf)
+{
+ struct proc *thread;
+
+ inf_update_procs (inf);
+
+ for (thread = inf->threads; thread; thread = thread->next)
+ thread->sc = thread->pause_sc;
+
+ if (inf->task)
+ inf->task->sc = inf->pause_sc;
+
+ inf_update_suspends (inf);
+}
+
+/* INF has one thread PROC that is in single-stepping mode. This function
+ changes it to be PROC, changing any old step_thread to be a normal one. A
+ PROC of 0 clears any existing value. */
+void
+inf_set_step_thread (struct inf *inf, struct proc *thread)
+{
+ assert (!thread || proc_is_thread (thread));
+
+ if (thread)
+ inf_debug (inf, "setting step thread: %d/%d", inf->pid, thread->tid);
+ else
+ inf_debug (inf, "clearing step thread");
+
+ if (inf->step_thread != thread)
+ {
+ if (inf->step_thread && inf->step_thread->port != MACH_PORT_NULL)
+ if (! proc_trace (inf->step_thread, 0))
+ return;
+ if (thread && proc_trace (thread, 1))
+ inf->step_thread = thread;
+ else
+ inf->step_thread = 0;
+ }
+}
+
+/* Set up the thread resume_sc's so that only the signal thread is running
+ (plus whatever other thread are set to always run). Returns true if we
+ did so, or false if we can't find a signal thread. */
+inline int
+inf_set_threads_resume_sc_for_signal_thread (struct inf *inf)
+{
+ if (inf->signal_thread)
+ {
+ inf_set_threads_resume_sc (inf, inf->signal_thread, 0);
+ return 1;
+ }
+ else
+ return 0;
+}
+
+static void
+inf_update_signal_thread (struct inf *inf)
+{
+ /* XXX for now we assume that if there's a msgport, the 2nd thread is
+ the signal thread. */
+ inf->signal_thread = inf->threads ? inf->threads->next : 0;
+}
+
+/* Detachs from INF's inferior task, letting it run once again... */
+void
+inf_detach (struct inf *inf)
+{
+ struct proc *task = inf->task;
+
+ inf_debug (inf, "detaching...");
+
+ inf_clear_wait (inf);
+ inf_set_step_thread (inf, 0);
+
+ if (task)
+ {
+ struct proc *thread;
+
+ inf_set_traced (inf, 0);
+ if (inf->stopped)
+ inf_signal (inf, TARGET_SIGNAL_0);
+
+ proc_restore_exc_port (task);
+ task->sc = inf->detach_sc;
+
+ for (thread = inf->threads; thread; thread = thread->next)
+ {
+ proc_restore_exc_port (thread);
+ thread->sc = thread->detach_sc;
+ }
+
+ inf_update_suspends (inf);
+ }
+
+ inf_cleanup (inf);
+}
+
+/* Attaches INF to the process with process id PID, returning it in a suspended
+ state suitable for debugging. */
+void
+inf_attach (struct inf *inf, int pid)
+{
+ inf_debug (inf, "attaching: %d", pid);
+
+ if (inf->pid)
+ inf_detach (inf);
+
+ inf_startup (inf, pid);
+}
+
+/* Makes sure that we've got our exception ports entrenched in the process. */
+void inf_steal_exc_ports (struct inf *inf)
+{
+ struct proc *thread;
+
+ inf_debug (inf, "stealing exception ports");
+
+ inf_set_step_thread (inf, 0); /* The step thread is special. */
+
+ proc_steal_exc_port (inf->task, inf->event_port);
+ for (thread = inf->threads; thread; thread = thread->next)
+ proc_steal_exc_port (thread, MACH_PORT_NULL);
+}
+
+/* Makes sure the process has its own exception ports. */
+void inf_restore_exc_ports (struct inf *inf)
+{
+ struct proc *thread;
+
+ inf_debug (inf, "restoring exception ports");
+
+ inf_set_step_thread (inf, 0); /* The step thread is special. */
+
+ proc_restore_exc_port (inf->task);
+ for (thread = inf->threads; thread; thread = thread->next)
+ proc_restore_exc_port (thread);
+}
+
+/* Deliver signal SIG to INF. If INF is stopped, delivering a signal, even
+ signal 0, will continue it. INF is assumed to be in a paused state, and
+ the resume_sc's of INF's threads may be affected. */
+void
+inf_signal (struct inf *inf, enum target_signal sig)
+{
+ error_t err = 0;
+ int host_sig = target_signal_to_host (sig);
+
+#define NAME target_signal_to_name (sig)
+
+ if (host_sig >= _NSIG)
+ /* A mach exception. Exceptions are encoded in the signal space by
+ putting them after _NSIG; this assumes they're positive (and not
+ extremely large)! */
+ {
+ struct inf_wait *w = &inf->wait;
+ if (w->status.kind == TARGET_WAITKIND_STOPPED
+ && w->status.value.sig == sig
+ && w->thread && !w->thread->aborted)
+ /* We're passing through the last exception we received. This is
+ kind of bogus, because exceptions are per-thread whereas gdb
+ treats signals as per-process. We just forward the exception to
+ the correct handler, even it's not for the same thread as TID --
+ i.e., we pretend it's global. */
+ {
+ struct exc_state *e = &w->exc;
+ inf_debug (inf, "passing through exception:"
+ " task = %d, thread = %d, exc = %d"
+ ", code = %d, subcode = %d",
+ w->thread->port, inf->task->port,
+ e->exception, e->code, e->subcode);
+ err =
+ exception_raise_request (e->handler,
+ e->reply, MACH_MSG_TYPE_MOVE_SEND_ONCE,
+ w->thread->port, inf->task->port,
+ e->exception, e->code, e->subcode);
+ }
+ else
+ error ("Can't forward spontaneous exception (%s).", NAME);
+ }
+ else
+ /* A Unix signal. */
+ if (inf->stopped)
+ /* The process is stopped and expecting a signal. Just send off a
+ request and let it get handled when we resume everything. */
+ {
+ inf_debug (inf, "sending %s to stopped process", NAME);
+ err =
+ INF_MSGPORT_RPC (inf,
+ msg_sig_post_untraced_request (msgport,
+ inf->event_port,
+ MACH_MSG_TYPE_MAKE_SEND_ONCE,
+ host_sig, 0,
+ refport));
+ if (! err)
+ /* Posting an untraced signal automatically continues it.
+ We clear this here rather than when we get the reply
+ because we'd rather assume it's not stopped when it
+ actually is, than the reverse. */
+ inf->stopped = 0;
+ }
+ else
+ /* It's not expecting it. We have to let just the signal thread
+ run, and wait for it to get into a reasonable state before we
+ can continue the rest of the process. When we finally resume the
+ process the signal we request will be the very first thing that
+ happens. */
+ {
+ inf_debug (inf, "sending %s to unstopped process (so resuming signal thread)", NAME);
+ err =
+ INF_RESUME_MSGPORT_RPC (inf, msg_sig_post_untraced (msgport,
+ host_sig, 0, refport));
+ }
+
+ if (err == EIEIO)
+ /* Can't do too much... */
+ warning ("Can't deliver signal %s: No signal thread.", NAME);
+ else if (err)
+ warning ("Delivering signal %s: %s", NAME, strerror (err));
+
+#undef NAME
+}
+
+/* The inferior used for all gdb target ops. */
+struct inf *current_inferior = 0;
+
+/* The inferior being waited for by gnu_wait. Since GDB is decidely not
+ multi-threaded, we don't bother to lock this. */
+struct inf *waiting_inf;
+
+/* Wait for something to happen in the inferior, returning what in STATUS. */
+static int
+gnu_wait (int tid, struct target_waitstatus *status)
+{
+ struct msg {
+ mach_msg_header_t hdr;
+ mach_msg_type_t type;
+ int data[8000];
+ } msg;
+ error_t err;
+ struct proc *thread;
+ struct inf *inf = current_inferior;
+
+ assert (inf->task);
+
+ if (!inf->threads && !inf->pending_execs)
+ /* No threads! Assume that maybe some outside agency is frobbing our
+ task, and really look for new threads. If we can't find any, just tell
+ the user to try again later. */
+ {
+ inf_validate_procs (inf);
+ if (!inf->threads && !inf->task->dead)
+ error ("There are no threads; try again later.");
+ }
+
+ waiting_inf = inf;
+
+ inf_debug (inf, "waiting for: %d", tid);
+
+ rewait:
+ if (proc_wait_pid != inf->pid && !inf->no_wait)
+ /* Always get information on events from the proc server. */
+ {
+ inf_debug (inf, "requesting wait on pid %d", inf->pid);
+
+ if (proc_wait_pid)
+ /* The proc server is single-threaded, and only allows a single
+ outstanding wait request, so we have to cancel the previous one. */
+ {
+ inf_debug (inf, "cancelling previous wait on pid %d", proc_wait_pid);
+ interrupt_operation (proc_server, 0);
+ }
+
+ err =
+ proc_wait_request (proc_server, inf->event_port, inf->pid, WUNTRACED);
+ if (err)
+ warning ("wait request failed: %s", strerror (err));
+ else
+ {
+ inf_debug (inf, "waits pending: %d", proc_waits_pending);
+ proc_wait_pid = inf->pid;
+ /* Even if proc_waits_pending was > 0 before, we still won't get
+ any other replies, because it was either from a different INF,
+ or a different process attached to INF -- and the event port,
+ which is the wait reply port, changes when you switch processes.*/
+ proc_waits_pending = 1;
+ }
+ }
+
+ inf_clear_wait (inf);
+
+ /* What can happen? (1) Dead name notification; (2) Exceptions arrive;
+ (3) wait reply from the proc server. */
+
+ inf_debug (inf, "waiting for an event...");
+ err = mach_msg (&msg.hdr, MACH_RCV_MSG | MACH_RCV_INTERRUPT,
+ 0, sizeof (struct msg), inf->event_port,
+ MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
+
+ /* Re-suspend the task. */
+ inf_suspend (inf);
+
+ if (!inf->task && inf->pending_execs)
+ /* When doing an exec, it's possible that the old task wasn't reused
+ (e.g., setuid execs). So if the task seems to have disappeared,
+ attempt to refetch it, as the pid should still be the same. */
+ inf_set_pid (inf, inf->pid);
+
+ if (err == EMACH_RCV_INTERRUPTED)
+ inf_debug (inf, "interrupted");
+ else if (err)
+ error ("Couldn't wait for an event: %s", strerror (err));
+ else
+ {
+ struct {
+ mach_msg_header_t hdr;
+ mach_msg_type_t err_type;
+ kern_return_t err;
+ char noise[200];
+ } reply;
+
+ inf_debug (inf, "event: msgid = %d", msg.hdr.msgh_id);
+
+ /* Handle what we got. */
+ if (! notify_server (&msg.hdr, &reply.hdr)
+ && ! exc_server (&msg.hdr, &reply.hdr)
+ && ! process_reply_server (&msg.hdr, &reply.hdr)
+ && ! msg_reply_server (&msg.hdr, &reply.hdr))
+ /* Whatever it is, it's something strange. */
+ error ("Got a strange event, msg id = %d.", msg.hdr.msgh_id);
+
+ if (reply.err)
+ error ("Handling event, msgid = %d: %s",
+ msg.hdr.msgh_id, strerror (reply.err));
+ }
+
+ if (inf->pending_execs)
+ /* We're waiting for the inferior to finish execing. */
+ {
+ struct inf_wait *w = &inf->wait;
+ enum target_waitkind kind = w->status.kind;
+
+ if (kind == TARGET_WAITKIND_SPURIOUS)
+ /* Since gdb is actually counting the number of times the inferior
+ stops, expecting one stop per exec, we only return major events
+ while execing. */
+ {
+ w->suppress = 1;
+ inf_debug (inf, "pending_execs = %d, ignoring minor event",
+ inf->pending_execs);
+ }
+ else if (kind == TARGET_WAITKIND_STOPPED
+ && w->status.value.sig == TARGET_SIGNAL_TRAP)
+ /* Ah hah! A SIGTRAP from the inferior while starting up probably
+ means we've succesfully completed an exec! */
+ {
+ if (--inf->pending_execs == 0)
+ /* We're done! */
+ {
+#if 0 /* do we need this? */
+ prune_threads (1); /* Get rid of the old shell threads */
+ renumber_threads (0); /* Give our threads reasonable names. */
+#endif
+ }
+ inf_debug (inf, "pending exec completed, pending_execs => %d",
+ inf->pending_execs);
+ }
+ else if (kind == TARGET_WAITKIND_STOPPED)
+ /* It's possible that this signal is because of a crashed process
+ being handled by the hurd crash server; in this case, the process
+ will have an extra task suspend, which we need to know about.
+ Since the code in inf_resume that normally checks for this is
+ disabled while INF->pending_execs, we do the check here instead. */
+ inf_validate_task_sc (inf);
+ }
+
+ if (inf->wait.suppress)
+ /* Some totally spurious event happened that we don't consider
+ worth returning to gdb. Just keep waiting. */
+ {
+ inf_debug (inf, "suppressing return, rewaiting...");
+ inf_resume (inf);
+ goto rewait;
+ }
+
+ /* Pass back out our results. */
+ bcopy (&inf->wait.status, status, sizeof (*status));
+
+ thread = inf->wait.thread;
+ if (thread)
+ tid = thread->tid;
+ else
+ thread = inf_tid_to_thread (inf, tid);
+
+ if (!thread || thread->port == MACH_PORT_NULL)
+ /* TID is dead; try and find a new thread. */
+ if (inf_update_procs (inf) && inf->threads)
+ tid = inf->threads->tid; /* The first available thread. */
+ else
+ tid = inferior_pid; /* let wait_for_inferior handle exit case */
+
+ if (thread && tid >= 0 && status->kind != TARGET_WAITKIND_SPURIOUS
+ && inf->pause_sc == 0 && thread->pause_sc == 0)
+ /* If something actually happened to THREAD, make sure we suspend it. */
+ {
+ thread->sc = 1;
+ inf_update_suspends (inf);
+ }
+
+ inf_debug (inf, "returning tid = %d, status = %s (%d)", tid,
+ status->kind == TARGET_WAITKIND_EXITED ? "EXITED"
+ : status->kind == TARGET_WAITKIND_STOPPED ? "STOPPED"
+ : status->kind == TARGET_WAITKIND_SIGNALLED ? "SIGNALLED"
+ : status->kind == TARGET_WAITKIND_LOADED ? "LOADED"
+ : status->kind == TARGET_WAITKIND_SPURIOUS ? "SPURIOUS"
+ : "?",
+ status->value.integer);
+
+ return tid;
+}
+
+/* The rpc handler called by exc_server. */
+error_t
+S_exception_raise_request (mach_port_t port, mach_port_t reply_port,
+ thread_t thread_port, task_t task_port,
+ int exception, int code, int subcode)
+{
+ struct inf *inf = waiting_inf;
+ struct proc *thread = inf_port_to_thread (inf, thread_port);
+
+ inf_debug (waiting_inf,
+ "thread = %d, task = %d, exc = %d, code = %d, subcode = %d",
+ thread_port, task_port, exception, code);
+
+ if (!thread)
+ /* We don't know about thread? */
+ {
+ inf_update_procs (inf);
+ thread = inf_port_to_thread (inf, thread_port);
+ if (!thread)
+ /* Give up, the generating thread is gone. */
+ return 0;
+ }
+
+ mach_port_deallocate (mach_task_self (), thread_port);
+ mach_port_deallocate (mach_task_self (), task_port);
+
+ if (! thread->aborted)
+ /* THREAD hasn't been aborted since this exception happened (abortion
+ clears any exception state), so it must be real. */
+ {
+ /* Store away the details; this will destroy any previous info. */
+ inf->wait.thread = thread;
+
+ inf->wait.status.kind = TARGET_WAITKIND_STOPPED;
+
+ if (exception == EXC_BREAKPOINT)
+ /* GDB likes to get SIGTRAP for breakpoints. */
+ {
+ inf->wait.status.value.sig = TARGET_SIGNAL_TRAP;
+ mach_port_deallocate (mach_task_self (), reply_port);
+ }
+ else
+ /* Record the exception so that we can forward it later. */
+ {
+ if (thread->exc_port == port)
+ {
+ inf_debug (waiting_inf, "Handler is thread exeption port <%d>",
+ thread->saved_exc_port);
+ inf->wait.exc.handler = thread->saved_exc_port;
+ }
+ else
+ {
+ inf_debug (waiting_inf, "Handler is task exeption port <%d>",
+ inf->task->saved_exc_port);
+ inf->wait.exc.handler = inf->task->saved_exc_port;
+ assert (inf->task->exc_port == port);
+ }
+ if (inf->wait.exc.handler != MACH_PORT_NULL)
+ /* Add a reference to the exception handler. */
+ mach_port_mod_refs (mach_task_self (),
+ inf->wait.exc.handler, MACH_PORT_RIGHT_SEND,
+ 1);
+
+ inf->wait.exc.exception = exception;
+ inf->wait.exc.code = code;
+ inf->wait.exc.subcode = subcode;
+ inf->wait.exc.reply = reply_port;
+
+ /* Exceptions are encoded in the signal space by putting them after
+ _NSIG; this assumes they're positive (and not extremely large)! */
+ inf->wait.status.value.sig =
+ target_signal_from_host (_NSIG + exception);
+ }
+ }
+ else
+ /* A supppressed exception, which ignore. */
+ {
+ inf->wait.suppress = 1;
+ mach_port_deallocate (mach_task_self (), reply_port);
+ }
+
+ return 0;
+}
+
+/* Fill in INF's wait field after a task has died without giving us more
+ detailed information. */
+void
+inf_task_died_status (struct inf *inf)
+{
+ warning ("Pid %d died with unknown exit status, using SIGKILL.", inf->pid);
+ inf->wait.status.kind = TARGET_WAITKIND_SIGNALLED;
+ inf->wait.status.value.sig = TARGET_SIGNAL_KILL;
+}
+
+/* Notify server routines. The only real one is dead name notification. */
+error_t
+do_mach_notify_dead_name (mach_port_t notify, mach_port_t dead_port)
+{
+ struct inf *inf = waiting_inf;
+
+ inf_debug (waiting_inf, "port = %d", dead_port);
+
+ if (inf->task && inf->task->port == dead_port)
+ {
+ proc_debug (inf->task, "is dead");
+ inf->task->port = MACH_PORT_NULL;
+ if (proc_wait_pid == inf->pid)
+ /* We have a wait outstanding on the process, which will return more
+ detailed information, so delay until we get that. */
+ inf->wait.suppress = 1;
+ else
+ /* We never waited for the process (maybe it wasn't a child), so just
+ pretend it got a SIGKILL. */
+ inf_task_died_status (inf);
+ }
+ else
+ {
+ struct proc *thread = inf_port_to_thread (inf, dead_port);
+ if (thread)
+ {
+ proc_debug (thread, "is dead");
+ thread->port = MACH_PORT_NULL;
+ }
+ }
+
+ mach_port_deallocate (mach_task_self (), dead_port);
+ inf->threads_up_to_date = 0; /* Just in case */
+
+ return 0;
+}
+
+static error_t
+ill_rpc (char *fun)
+{
+ warning ("illegal rpc: %s", fun);
+ return 0;
+}
+
+error_t
+do_mach_notify_no_senders (mach_port_t notify, mach_port_mscount_t count)
+{
+ return ill_rpc (__FUNCTION__);
+}
+
+error_t
+do_mach_notify_port_deleted (mach_port_t notify, mach_port_t name)
+{
+ return ill_rpc (__FUNCTION__);
+}
+
+error_t
+do_mach_notify_msg_accepted (mach_port_t notify, mach_port_t name)
+{
+ return ill_rpc (__FUNCTION__);
+}
+
+error_t
+do_mach_notify_port_destroyed (mach_port_t notify, mach_port_t name)
+{
+ return ill_rpc (__FUNCTION__);
+}
+
+error_t
+do_mach_notify_send_once (mach_port_t notify)
+{
+ return ill_rpc (__FUNCTION__);
+}
+
+/* Process_reply server routines. We only use process_wait_reply. */
+
+error_t
+S_proc_wait_reply (mach_port_t reply, error_t err,
+ int status, int sigcode, rusage_t rusage, pid_t pid)
+{
+ struct inf *inf = waiting_inf;
+
+ inf_debug (inf, "err = %s, pid = %d, status = 0x%x, sigcode = %d",
+ err ? strerror (err) : "0", pid, status, sigcode);
+
+ if (err && proc_wait_pid && (!inf->task || !inf->task->port))
+ /* Ack. The task has died, but the task-died notification code didn't
+ tell anyone because it thought a more detailed reply from the
+ procserver was forthcoming. However, we now learn that won't
+ happen... So we have to act like the task just died, and this time,
+ tell the world. */
+ inf_task_died_status (inf);
+
+ if (--proc_waits_pending == 0)
+ /* PROC_WAIT_PID represents the most recent wait. We will always get
+ replies in order because the proc server is single threaded. */
+ proc_wait_pid = 0;
+
+ inf_debug (inf, "waits pending now: %d", proc_waits_pending);
+
+ if (err)
+ {
+ if (err != EINTR)
+ {
+ warning ("Can't wait for pid %d: %s", inf->pid, strerror (err));
+ inf->no_wait = 1;
+
+ /* Since we can't see the inferior's signals, don't trap them. */
+ inf_set_traced (inf, 0);
+ }
+ }
+ else if (pid == inf->pid)
+ {
+ store_waitstatus (&inf->wait.status, status);
+ if (inf->wait.status.kind == TARGET_WAITKIND_STOPPED)
+ /* The process has sent us a signal, and stopped itself in a sane
+ state pending our actions. */
+ {
+ inf_debug (inf, "process has stopped itself");
+ inf->stopped = 1;
+ }
+ }
+ else
+ inf->wait.suppress = 1; /* Something odd happened. Ignore. */
+
+ return 0;
+}
+
+error_t
+S_proc_setmsgport_reply (mach_port_t reply, error_t err,
+ mach_port_t old_msg_port)
+{
+ return ill_rpc (__FUNCTION__);
+}
+
+error_t
+S_proc_getmsgport_reply (mach_port_t reply, error_t err, mach_port_t msg_port)
+{
+ return ill_rpc (__FUNCTION__);
+}
+
+/* Msg_reply server routines. We only use msg_sig_post_untraced_reply. */
+
+error_t
+S_msg_sig_post_untraced_reply (mach_port_t reply, error_t err)
+{
+ struct inf *inf = waiting_inf;
+
+ if (err == EBUSY)
+ /* EBUSY is what we get when the crash server has grabbed control of the
+ process and doesn't like what signal we tried to send it. Just act
+ like the process stopped (using a signal of 0 should mean that the
+ *next* time the user continues, it will pass signal 0, which the crash
+ server should like). */
+ {
+ inf->wait.status.kind = TARGET_WAITKIND_STOPPED;
+ inf->wait.status.value.sig = TARGET_SIGNAL_0;
+ }
+ else if (err)
+ warning ("Signal delivery failed: %s", strerror (err));
+
+ if (err)
+ /* We only get this reply when we've posted a signal to a process which we
+ thought was stopped, and which we expected to continue after the signal.
+ Given that the signal has failed for some reason, it's reasonable to
+ assume it's still stopped. */
+ inf->stopped = 1;
+ else
+ inf->wait.suppress = 1;
+
+ return 0;
+}
+
+error_t
+S_msg_sig_post_reply (mach_port_t reply, error_t err)
+{
+ return ill_rpc (__FUNCTION__);
+}
+
+/* Returns the number of messages queued for the receive right PORT. */
+static mach_port_msgcount_t
+port_msgs_queued (mach_port_t port)
+{
+ struct mach_port_status status;
+ error_t err =
+ mach_port_get_receive_status (mach_task_self (), port, &status);
+
+ if (err)
+ return 0;
+ else
+ return status.mps_msgcount;
+}
+
+/* Resume execution of the inferior process.
+
+ If STEP is nonzero, single-step it.
+ If SIGNAL is nonzero, give it that signal.
+
+ TID STEP:
+ -1 true Single step the current thread allowing other threads to run.
+ -1 false Continue the current thread allowing other threads to run.
+ X true Single step the given thread, don't allow any others to run.
+ X false Continue the given thread, do not allow any others to run.
+ (Where X, of course, is anything except -1)
+
+ Note that a resume may not `take' if there are pending exceptions/&c
+ still unprocessed from the last resume we did (any given resume may result
+ in multiple events returned by wait).
+*/
+static void
+gnu_resume (int tid, int step, enum target_signal sig)
+{
+ struct proc *step_thread = 0;
+ struct inf *inf = current_inferior;
+
+ inf_debug (inf, "tid = %d, step = %d, sig = %d", tid, step, sig);
+
+ if (sig != TARGET_SIGNAL_0 || inf->stopped)
+ inf_signal (inf, sig);
+ else if (inf->wait.exc.reply != MACH_PORT_NULL)
+ /* We received an exception to which we have chosen not to forward, so
+ abort the faulting thread, which will perhaps retake it. */
+ {
+ proc_abort (inf->wait.thread, 1);
+ warning ("Aborting %s with unforwarded exception %s.",
+ proc_string (inf->wait.thread),
+ target_signal_to_name (inf->wait.status.value.sig));
+ }
+
+ if (port_msgs_queued (inf->event_port))
+ /* If there are still messages in our event queue, don't bother resuming
+ the process, as we're just going to stop it right away anyway. */
+ return;
+
+ inf_update_procs (inf);
+
+ if (tid < 0)
+ /* Allow all threads to run, except perhaps single-stepping one. */
+ {
+ inf_debug (inf, "running all threads; tid = %d", inferior_pid);
+ tid = inferior_pid; /* What to step. */
+ inf_set_threads_resume_sc (inf, 0, 1);
+ }
+ else
+ /* Just allow a single thread to run. */
+ {
+ struct proc *thread = inf_tid_to_thread (inf, tid);
+ if (! thread)
+ error ("Can't run single thread id %d: no such thread!");
+ inf_debug (inf, "running one thread: %d/%d", inf->pid, thread->tid);
+ inf_set_threads_resume_sc (inf, thread, 0);
+ }
+
+ if (step)
+ {
+ step_thread = inf_tid_to_thread (inf, tid);
+ if (! step_thread)
+ warning ("Can't step thread id %d: no such thread.", tid);
+ else
+ inf_debug (inf, "stepping thread: %d/%d", inf->pid, step_thread->tid);
+ }
+ if (step_thread != inf->step_thread)
+ inf_set_step_thread (inf, step_thread);
+
+ inf_debug (inf, "here we go...");
+ inf_resume (inf);
+}
+
+static void
+gnu_kill_inferior ()
+{
+ struct proc *task = current_inferior->task;
+ if (task)
+ {
+ proc_debug (task, "terminating...");
+ task_terminate (task->port);
+ inf_set_pid (current_inferior, -1);
+ }
+ target_mourn_inferior ();
+}
+
+/* Clean up after the inferior dies. */
+
+static void
+gnu_mourn_inferior ()
+{
+ inf_debug (current_inferior, "rip");
+ inf_detach (current_inferior);
+ unpush_target (&gnu_ops);
+ generic_mourn_inferior ();
+}
+
+/* Fork an inferior process, and start debugging it. */
+
+/* Set INFERIOR_PID to the first thread available in the child, if any. */
+static int
+inf_pick_first_thread ()
+{
+ if (current_inferior->task && current_inferior->threads)
+ /* The first thread. */
+ return current_inferior->threads->tid;
+ else
+ /* What may be the next thread. */
+ return next_thread_id;
+}
+
+static struct inf *
+cur_inf ()
+{
+ if (! current_inferior)
+ current_inferior = make_inf ();
+ return current_inferior;
+}
+
+static void
+gnu_create_inferior (exec_file, allargs, env)
+ char *exec_file;
+ char *allargs;
+ char **env;
+{
+ struct inf *inf = cur_inf ();
+
+ void trace_me ()
+ {
+ /* We're in the child; make this process stop as soon as it execs. */
+ inf_debug (inf, "tracing self");
+ if (ptrace (PTRACE_TRACEME) != 0)
+ error ("ptrace (PTRACE_TRACEME) failed!");
+ }
+ int attach_to_child (int pid)
+ {
+ /* Attach to the now stopped child, which is actually a shell... */
+ inf_debug (inf, "attaching to child: %d", pid);
+
+ inf_attach (inf, pid);
+
+ attach_flag = 0;
+ push_target (&gnu_ops);
+
+ inf->pending_execs = 2;
+ inf->traced = 1;
+
+ /* Now let the child run again, knowing that it will stop immediately
+ because of the ptrace. */
+ inf_resume (inf);
+ inferior_pid = inf_pick_first_thread ();
+
+ startup_inferior (inf->pending_execs);
+
+ return inferior_pid;
+ }
+
+ inf_debug (inf, "creating inferior");
+
+ fork_inferior (exec_file, allargs, env, trace_me, attach_to_child, NULL, NULL);
+
+ inf_update_signal_thread (inf);
+ inf_set_traced (inf, inf->want_signals);
+
+ /* Execing the process will have trashed our exception ports; steal them
+ back (or make sure they're restored if the user wants that). */
+ if (inf->want_exceptions)
+ inf_steal_exc_ports (inf);
+ else
+ inf_restore_exc_ports (inf);
+
+ /* Here we go! */
+ proceed ((CORE_ADDR) -1, 0, 0);
+}
+
+/* Mark our target-struct as eligible for stray "run" and "attach"
+ commands. */
+static int
+gnu_can_run ()
+{
+ return 1;
+}
+
+#ifdef ATTACH_DETACH
+
+/* Attach to process PID, then initialize for debugging it
+ and wait for the trace-trap that results from attaching. */
+static void
+gnu_attach (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ int pid;
+ char *exec_file;
+ struct inf *inf = cur_inf ();
+
+ if (!args)
+ error_no_arg ("PID to attach");
+
+ 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_unfiltered ("Attaching to program `%s', pid %d\n",
+ exec_file, pid);
+ else
+ printf_unfiltered ("Attaching to pid %d\n", pid);
+
+ gdb_flush (gdb_stdout);
+ }
+
+ inf_debug (inf, "attaching to pid: %d", pid);
+
+ inf_attach (inf, pid);
+ inf_update_procs (inf);
+
+ inferior_pid = inf_pick_first_thread ();
+
+ attach_flag = 1;
+ push_target (&gnu_ops);
+
+ inf_update_signal_thread (inf);
+ inf_set_traced (inf, inf->want_signals);
+
+ /* If the process was stopped before we attached, make it continue the next
+ time the user does a continue. */
+ inf_validate_stopped (inf);
+
+#if 0 /* Do we need this? */
+ renumber_threads (0); /* Give our threads reasonable names. */
+#endif
+}
+
+/* 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 fork. */
+static void
+gnu_detach (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ if (from_tty)
+ {
+ char *exec_file = get_exec_file (0);
+ if (exec_file)
+ printf_unfiltered ("Detaching from program `%s' pid %d\n",
+ exec_file, current_inferior->pid);
+ else
+ printf_unfiltered ("Detaching from pid %d\n", current_inferior->pid);
+ gdb_flush (gdb_stdout);
+ }
+
+ inf_detach (current_inferior);
+
+ inferior_pid = 0;
+
+ unpush_target (&gnu_ops); /* Pop out of handling an inferior */
+}
+#endif /* ATTACH_DETACH */
+
+static void
+gnu_terminal_init_inferior ()
+{
+ assert (current_inferior);
+ terminal_init_inferior_with_pgrp (current_inferior->pid);
+}
+
+/* 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
+gnu_prepare_to_store ()
+{
+#ifdef CHILD_PREPARE_TO_STORE
+ CHILD_PREPARE_TO_STORE ();
+#endif
+}
+
+static void
+gnu_open (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ error ("Use the \"run\" command to start a Unix child process.");
+}
+
+static void
+gnu_stop ()
+{
+ error ("to_stop target function not implemented");
+}
+
+static void
+gnu_pid_to_exec_file ()
+{
+ error ("to_pid_to_exec_file target function not implemented");
+}
+
+
+static int
+gnu_thread_alive (int tid)
+{
+ inf_update_procs (current_inferior);
+ return !!inf_tid_to_thread (current_inferior, tid);
+}
+
+/*
+ * Read inferior task's LEN bytes from ADDR and copy it to MYADDR
+ * in gdb's address space.
+ *
+ * Return 0 on failure; number of bytes read otherwise.
+ */
+int
+gnu_read_inferior (task, addr, myaddr, length)
+ task_t task;
+ CORE_ADDR addr;
+ char *myaddr;
+ int length;
+{
+ error_t err;
+ vm_address_t low_address = (vm_address_t) trunc_page (addr);
+ vm_size_t aligned_length =
+ (vm_size_t) round_page (addr+length) - low_address;
+ pointer_t copied;
+ int copy_count;
+
+ /* Get memory from inferior with page aligned addresses */
+ err = vm_read (task, low_address, aligned_length, &copied, &copy_count);
+ if (err)
+ return 0;
+
+ err = hurd_safe_copyin (myaddr, (void*)addr - low_address + copied, length);
+ if (err)
+ {
+ warning ("Read from inferior faulted: %s", strerror (err));
+ length = 0;
+ }
+
+ err = vm_deallocate (mach_task_self (), copied, copy_count);
+ if (err)
+ warning ("gnu_read_inferior vm_deallocate failed: %s", strerror (err));
+
+ return length;
+}
+
+#define CHK_GOTO_OUT(str,ret) \
+ do if (ret != KERN_SUCCESS) { errstr = #str; goto out; } while(0)
+
+struct vm_region_list {
+ struct vm_region_list *next;
+ vm_prot_t protection;
+ vm_address_t start;
+ vm_size_t length;
+};
+
+struct obstack region_obstack;
+
+/*
+ * Write gdb's LEN bytes from MYADDR and copy it to ADDR
+ * in inferior task's address space.
+ */
+int
+gnu_write_inferior (task, addr, myaddr, length)
+ task_t task;
+ CORE_ADDR addr;
+ char *myaddr;
+ int length;
+{
+ error_t err = 0;
+ vm_address_t low_address = (vm_address_t) trunc_page (addr);
+ vm_size_t aligned_length =
+ (vm_size_t) round_page (addr+length) - low_address;
+ pointer_t copied;
+ int copy_count;
+ int deallocate = 0;
+
+ char *errstr = "Bug in gnu_write_inferior";
+
+ struct vm_region_list *region_element;
+ struct vm_region_list *region_head = (struct vm_region_list *)NULL;
+
+ /* Get memory from inferior with page aligned addresses */
+ err = vm_read (task,
+ low_address,
+ aligned_length,
+ &copied,
+ &copy_count);
+ CHK_GOTO_OUT ("gnu_write_inferior vm_read failed", err);
+
+ deallocate++;
+
+ err = hurd_safe_copyout ((void*)addr - low_address + copied, myaddr, length);
+ CHK_GOTO_OUT ("Write to inferior faulted", err);
+
+ obstack_init (&region_obstack);
+
+ /* Do writes atomically.
+ * First check for holes and unwritable memory.
+ */
+ {
+ vm_size_t remaining_length = aligned_length;
+ vm_address_t region_address = low_address;
+
+ struct vm_region_list *scan;
+
+ while(region_address < low_address + aligned_length)
+ {
+ vm_prot_t protection;
+ vm_prot_t max_protection;
+ vm_inherit_t inheritance;
+ boolean_t shared;
+ mach_port_t object_name;
+ vm_offset_t offset;
+ vm_size_t region_length = remaining_length;
+ vm_address_t old_address = region_address;
+
+ err = vm_region (task,
+ &region_address,
+ &region_length,
+ &protection,
+ &max_protection,
+ &inheritance,
+ &shared,
+ &object_name,
+ &offset);
+ CHK_GOTO_OUT ("vm_region failed", err);
+
+ /* Check for holes in memory */
+ if (old_address != region_address)
+ {
+ warning ("No memory at 0x%x. Nothing written",
+ old_address);
+ err = KERN_SUCCESS;
+ length = 0;
+ goto out;
+ }
+
+ if (!(max_protection & VM_PROT_WRITE))
+ {
+ warning ("Memory at address 0x%x is unwritable. Nothing written",
+ old_address);
+ err = KERN_SUCCESS;
+ length = 0;
+ goto out;
+ }
+
+ /* Chain the regions for later use */
+ region_element =
+ (struct vm_region_list *)
+ obstack_alloc (&region_obstack, sizeof (struct vm_region_list));
+
+ region_element->protection = protection;
+ region_element->start = region_address;
+ region_element->length = region_length;
+
+ /* Chain the regions along with protections */
+ region_element->next = region_head;
+ region_head = region_element;
+
+ region_address += region_length;
+ remaining_length = remaining_length - region_length;
+ }
+
+ /* If things fail after this, we give up.
+ * Somebody is messing up inferior_task's mappings.
+ */
+
+ /* Enable writes to the chained vm regions */
+ for (scan = region_head; scan; scan = scan->next)
+ {
+ boolean_t protection_changed = FALSE;
+
+ if (!(scan->protection & VM_PROT_WRITE))
+ {
+ err = vm_protect (task,
+ scan->start,
+ scan->length,
+ FALSE,
+ scan->protection | VM_PROT_WRITE);
+ CHK_GOTO_OUT ("vm_protect: enable write failed", err);
+ }
+ }
+
+ err = vm_write (task,
+ low_address,
+ copied,
+ aligned_length);
+ CHK_GOTO_OUT ("vm_write failed", err);
+
+ /* Set up the original region protections, if they were changed */
+ for (scan = region_head; scan; scan = scan->next)
+ {
+ boolean_t protection_changed = FALSE;
+
+ if (!(scan->protection & VM_PROT_WRITE))
+ {
+ err = vm_protect (task,
+ scan->start,
+ scan->length,
+ FALSE,
+ scan->protection);
+ CHK_GOTO_OUT ("vm_protect: enable write failed", err);
+ }
+ }
+ }
+
+ out:
+ if (deallocate)
+ {
+ obstack_free (&region_obstack, 0);
+
+ (void) vm_deallocate (mach_task_self (),
+ copied,
+ copy_count);
+ }
+
+ if (err != KERN_SUCCESS)
+ {
+ warning ("%s: %s", errstr, mach_error_string (err));
+ return 0;
+ }
+
+ return length;
+}
+
+/* Return 0 on failure, number of bytes handled otherwise. */
+static int
+gnu_xfer_memory (memaddr, myaddr, len, write, target)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+ int write;
+ struct target_ops *target; /* IGNORED */
+{
+ int result;
+ task_t task =
+ current_inferior
+ ? (current_inferior->task ? current_inferior->task->port : 0)
+ : 0;
+
+ if (task == MACH_PORT_NULL)
+ return 0;
+ else
+ {
+ inf_debug (current_inferior, "%s %p[%d] %s %p",
+ write ? "writing" : "reading", memaddr, len,
+ write ? "<--" : "-->", myaddr);
+ if (write)
+ return gnu_write_inferior (task, memaddr, myaddr, len);
+ else
+ return gnu_read_inferior (task, memaddr, myaddr, len);
+ }
+}
+
+extern void gnu_store_registers (int regno);
+extern void gnu_fetch_registers (int regno);
+
+struct target_ops gnu_ops ;
+
+static void
+init_gnu_ops(void)
+{
+ gnu_ops.to_shortname = "GNU"; /* to_shortname */
+ gnu_ops.to_longname = "GNU Hurd process"; /* to_longname */
+ gnu_ops.to_doc = "GNU Hurd process"; /* to_doc */
+ gnu_ops.to_open = gnu_open; /* to_open */
+ gnu_ops.to_close = 0; /* to_close */
+ gnu_ops.to_attach = gnu_attach; /* to_attach */
+ gnu_ops.to_post_attach = NULL;
+ gnu_ops.to_require_attach = NULL; /* to_require_attach */
+ gnu_ops.to_detach = gnu_detach; /* to_detach */
+ gnu_ops.to_require_detach = NULL; /* to_require_detach */
+ gnu_ops.to_resume = gnu_resume; /* to_resume */
+ gnu_ops.to_wait = gnu_wait; /* to_wait */
+ gnu_ops.to_post_wait = NULL; /* to_post_wait */
+ gnu_ops.to_fetch_registers = gnu_fetch_registers; /* to_fetch_registers */
+ gnu_ops.to_store_registers = gnu_store_registers; /* to_store_registers */
+ gnu_ops.to_prepare_to_store = gnu_prepare_to_store; /* to_prepare_to_store */
+ gnu_ops.to_xfer_memory = gnu_xfer_memory; /* to_xfer_memory */
+ gnu_ops.to_files_info = 0; /* to_files_info */
+ gnu_ops.to_insert_breakpoint = memory_insert_breakpoint;
+ gnu_ops.to_remove_breakpoint = memory_remove_breakpoint;
+ gnu_ops.to_terminal_init = gnu_terminal_init_inferior;
+ gnu_ops.to_terminal_inferior = terminal_inferior;
+ gnu_ops.to_terminal_ours_for_output = terminal_ours_for_output;
+ gnu_ops.to_terminal_ours = terminal_ours;
+ gnu_ops.to_terminal_info = child_terminal_info;
+ gnu_ops.to_kill = gnu_kill_inferior; /* to_kill */
+ gnu_ops.to_load = 0; /* to_load */
+ gnu_ops.to_lookup_symbol = 0; /* to_lookup_symbol */
+ gnu_ops.to_create_inferior = gnu_create_inferior; /* to_create_inferior */
+ gnu_ops.to_post_startup_inferior = NULL; /* to_post_startup_inferior */
+ gnu_ops.to_acknowledge_created_inferior = NULL; /* to_acknowledge_created_inferior */
+ gnu_ops.to_clone_and_follow_inferior = NULL; /* to_clone_and_follow_inferior */
+ gnu_ops.to_post_follow_inferior_by_clone = NULL; /* to_post_follow_inferior_by_clone */
+ gnu_ops.to_insert_fork_catchpoint = NULL;
+ gnu_ops.to_remove_fork_catchpoint = NULL;
+ gnu_ops.to_insert_vfork_catchpoint = NULL;
+ gnu_ops.to_remove_vfork_catchpoint = NULL;
+ gnu_ops.to_has_forked = NULL; /* to_has_forked */
+ gnu_ops.to_has_vforked = NULL; /* to_has_vforked */
+ gnu_ops.to_can_follow_vfork_prior_to_exec = NULL;
+ gnu_ops.to_post_follow_vfork = NULL; /* to_post_follow_vfork */
+ gnu_ops.to_insert_exec_catchpoint = NULL;
+ gnu_ops.to_remove_exec_catchpoint = NULL;
+ gnu_ops.to_has_execd = NULL;
+ gnu_ops.to_reported_exec_events_per_exec_call = NULL;
+ gnu_ops.to_has_exited = NULL;
+ gnu_ops.to_mourn_inferior = gnu_mourn_inferior; /* to_mourn_inferior */
+ gnu_ops.to_can_run = gnu_can_run; /* to_can_run */
+ gnu_ops.to_notice_signals = 0; /* to_notice_signals */
+ gnu_ops.to_thread_alive = gnu_thread_alive;/* to_thread_alive */
+ gnu_ops.to_stop = gnu_stop; /* to_stop */
+ gnu_ops.to_pid_to_exec_file = gnu_pid_to_exec_file; /* to_pid_to_exec_file */
+ gnu_ops.to_core_file_to_sym_file = NULL;
+ gnu_ops.to_stratum = process_stratum; /* to_stratum */
+ gnu_ops.DONT_USE = 0; /* to_next */
+ gnu_ops.to_has_all_memory = 1; /* to_has_all_memory */
+ gnu_ops.to_has_memory = 1; /* to_has_memory */
+ gnu_ops.to_has_stack = 1; /* to_has_stack */
+ gnu_ops.to_has_registers = 1; /* to_has_registers */
+ gnu_ops.to_has_execution = 1; /* to_has_execution */
+ gnu_ops.to_sections = 0; /* sections */
+ gnu_ops.to_sections_end = 0; /* sections_end */
+ gnu_ops.to_magic = OPS_MAGIC ; /* to_magic */
+} /* init_gnu_ops */
+
+/* Return printable description of proc. */
+char *proc_string (struct proc *proc)
+{
+ static char tid_str[80];
+ if (proc_is_task (proc))
+ sprintf (tid_str, "process %d", proc->inf->pid);
+ else
+ sprintf (tid_str, "thread %d.%d",
+ proc->inf->pid, pid_to_thread_id (proc->tid));
+ return tid_str;
+}
+
+char *
+gnu_target_pid_to_str (int tid)
+{
+ struct inf *inf = current_inferior;
+ struct proc *thread = inf_tid_to_thread (inf, tid);
+
+ if (thread)
+ return proc_string (thread);
+ else
+ {
+ static char tid_str[80];
+ sprintf (tid_str, "bogus thread id %d", tid);
+ return tid_str;
+ }
+}
+
+/* User task commands. */
+
+struct cmd_list_element *set_task_cmd_list = 0;
+struct cmd_list_element *show_task_cmd_list = 0;
+/* User thread commands. */
+
+/* Commands with a prefix of `set/show thread'. */
+extern struct cmd_list_element *thread_cmd_list;
+struct cmd_list_element *set_thread_cmd_list = NULL;
+struct cmd_list_element *show_thread_cmd_list = NULL;
+
+/* Commands with a prefix of `set/show thread default'. */
+struct cmd_list_element *set_thread_default_cmd_list = NULL;
+struct cmd_list_element *show_thread_default_cmd_list = NULL;
+
+static void
+set_thread_cmd (char *args, int from_tty)
+{
+ printf_unfiltered ("\"set thread\" must be followed by the name of a thread
+property, or \"default\".\n");
+}
+
+static void
+show_thread_cmd (char *args, int from_tty)
+{
+ printf_unfiltered ("\"show thread\" must be followed by the name of a thread property, or \"default\".\n");
+}
+
+static void
+set_thread_default_cmd (char *args, int from_tty)
+{
+ printf_unfiltered ("\"set thread default\" must be followed by the name of a thread property.\n");
+}
+
+static void
+show_thread_default_cmd (char *args, int from_tty)
+{
+ printf_unfiltered ("\"show thread default\" must be followed by the name of a thread property.\n");
+}
+
+static int
+parse_int_arg (char *args, char *cmd_prefix)
+{
+ if (args)
+ {
+ char *arg_end;
+ int val = strtoul (args, &arg_end, 10);
+ if (*args && *arg_end == '\0')
+ return val;
+ }
+ error ("Illegal argument for \"%s\" command, should be an integer.", cmd_prefix);
+}
+
+static int
+_parse_bool_arg (char *args, char *t_val, char *f_val, char *cmd_prefix)
+{
+ if (!args || strcmp (args, t_val) == 0)
+ return 1;
+ else if (strcmp (args, f_val) == 0)
+ return 0;
+ else
+ error ("Illegal argument for \"%s\" command, should be \"%s\" or \"%s\".",
+ cmd_prefix, t_val, f_val);
+}
+
+#define parse_bool_arg(args, cmd_prefix) \
+ _parse_bool_arg (args, "on", "off", cmd_prefix)
+
+static void
+check_empty (char *args, char *cmd_prefix)
+{
+ if (args)
+ error ("Garbage after \"%s\" command: `%s'", cmd_prefix, args);
+}
+
+/* Returns the alive thread named by INFERIOR_PID, or signals an error. */
+static struct proc *
+cur_thread ()
+{
+ struct inf *inf = cur_inf ();
+ struct proc *thread = inf_tid_to_thread (inf, inferior_pid);
+ if (!thread)
+ error ("No current thread.");
+ return thread;
+}
+
+/* Returns the current inferior, but signals an error if it has no task. */
+static struct inf *
+active_inf ()
+{
+ struct inf *inf = cur_inf ();
+ if (! inf->task)
+ error ("No current process.");
+ return inf;
+}
+
+static void
+set_task_pause_cmd (char *args, int from_tty)
+{
+ struct inf *inf = cur_inf ();
+ int old_sc = inf->pause_sc;
+
+ inf->pause_sc = parse_bool_arg (args, "set task pause");
+
+ if (old_sc == 0 && inf->pause_sc != 0)
+ /* If the task is currently unsuspended, immediately suspend it,
+ otherwise wait until the next time it gets control. */
+ inf_suspend (inf);
+}
+
+static void
+show_task_pause_cmd (char *args, int from_tty)
+{
+ struct inf *inf = cur_inf ();
+ check_empty (args, "show task pause");
+ printf_unfiltered ("The inferior task %s suspended while gdb has control.\n",
+ inf->task
+ ? (inf->pause_sc == 0 ? "isn't" : "is")
+ : (inf->pause_sc == 0 ? "won't be" : "will be"));
+}
+
+static void
+set_task_detach_sc_cmd (char *args, int from_tty)
+{
+ cur_inf ()->detach_sc = parse_int_arg (args, "set task detach-suspend-count");
+}
+
+static void
+show_task_detach_sc_cmd (char *args, int from_tty)
+{
+ check_empty (args, "show task detach-suspend-count");
+ printf_unfiltered ("The inferior task will be left with a suspend count of %d when detaching.\n",
+ cur_inf ()->detach_sc);
+}
+
+static void
+set_thread_default_pause_cmd (char *args, int from_tty)
+{
+ struct inf *inf = cur_inf ();
+ inf->default_thread_pause_sc =
+ parse_bool_arg (args, "set thread default pause") ? 0 : 1;
+}
+
+static void
+show_thread_default_pause_cmd (char *args, int from_tty)
+{
+ struct inf *inf = cur_inf ();
+ int sc = inf->default_thread_pause_sc;
+ check_empty (args, "show thread default pause");
+ printf_unfiltered ("New threads %s suspended while gdb has control%s.\n",
+ sc ? "are" : "aren't",
+ !sc && inf->pause_sc ? " (but the task is)" : "");
+}
+
+static void
+set_thread_default_run_cmd (char *args, int from_tty)
+{
+ struct inf *inf = cur_inf ();
+ inf->default_thread_run_sc =
+ parse_bool_arg (args, "set thread default run") ? 0 : 1;
+}
+
+static void
+show_thread_default_run_cmd (char *args, int from_tty)
+{
+ struct inf *inf = cur_inf ();
+ check_empty (args, "show thread default run");
+ printf_unfiltered ("New threads %s allowed to run.\n",
+ inf->default_thread_run_sc == 0 ? "are" : "aren't");
+}
+
+static void
+set_thread_default_detach_sc_cmd (char *args, int from_tty)
+{
+ cur_inf ()->default_thread_detach_sc =
+ parse_int_arg (args, "set thread default detach-suspend-count");
+}
+
+static void
+show_thread_default_detach_sc_cmd (char *args, int from_tty)
+{
+ check_empty (args, "show thread default detach-suspend-count");
+ printf_unfiltered ("New threads will get a detach-suspend-count of %d.\n",
+ cur_inf ()->default_thread_detach_sc);
+}
+
+/* Steal a send right called NAME in the inferior task, and make it PROC's
+ saved exception port. */
+static void
+steal_exc_port (struct proc *proc, mach_port_t name)
+{
+ error_t err;
+ mach_port_t port;
+ mach_msg_type_name_t port_type;
+
+ if (!proc || !proc->inf->task)
+ error ("No inferior task.");
+
+ err = mach_port_extract_right (proc->inf->task->port,
+ name, MACH_MSG_TYPE_COPY_SEND,
+ &port, &port_type);
+ if (err)
+ error ("Couldn't extract send right %d from inferior: %s",
+ name, strerror (err));
+
+ if (proc->saved_exc_port)
+ /* Get rid of our reference to the old one. */
+ mach_port_deallocate (mach_task_self (), proc->saved_exc_port);
+
+ proc->saved_exc_port = port;
+
+ if (! proc->exc_port)
+ /* If PROC is a thread, we may not have set its exception port before.
+ We can't use proc_steal_exc_port because it also sets saved_exc_port. */
+ {
+ proc->exc_port = proc->inf->event_port;
+ err = proc_set_exception_port (proc, proc->exc_port);
+ error ("Can't set exception port for %s: %s",
+ proc_string (proc), strerror (err));
+ }
+}
+
+static void
+set_task_exc_port_cmd (char *args, int from_tty)
+{
+ struct inf *inf = cur_inf ();
+ if (!args)
+ error ("No argument to \"set task exception-port\" command.");
+ steal_exc_port (inf->task, parse_and_eval_address (args));
+}
+
+static void
+set_stopped_cmd (char *args, int from_tty)
+{
+ cur_inf ()->stopped = _parse_bool_arg (args, "yes", "no", "set stopped");
+}
+
+static void
+show_stopped_cmd (char *args, int from_tty)
+{
+ struct inf *inf = active_inf ();
+ check_empty (args, "show stopped");
+ printf_unfiltered ("The inferior process %s stopped.\n",
+ inf->stopped ? "is" : "isn't");
+}
+
+static void
+set_sig_thread_cmd (char *args, int from_tty)
+{
+ int tid;
+ struct inf *inf = cur_inf ();
+
+ if (!args || (! isdigit (*args) && strcmp (args, "none") != 0))
+ error ("Illegal argument to \"set signal-thread\" command.\n"
+ "Should be an integer thread ID, or `none'.");
+
+ if (strcmp (args, "none") == 0)
+ inf->signal_thread = 0;
+ else
+ {
+ int tid = thread_id_to_pid (atoi (args));
+ if (tid < 0)
+ error ("Thread ID %s not known. Use the \"info threads\" command to\n"
+ "see the IDs of currently known threads.", args);
+ inf->signal_thread = inf_tid_to_thread (inf, tid);
+ }
+}
+
+static void
+show_sig_thread_cmd (char *args, int from_tty)
+{
+ struct inf *inf = active_inf ();
+ check_empty (args, "show signal-thread");
+ if (inf->signal_thread)
+ printf_unfiltered ("The signal thread is %s.\n",
+ proc_string (inf->signal_thread));
+ else
+ printf_unfiltered ("There is no signal thread.\n");
+}
+
+static void
+set_signals_cmd (char *args, int from_tty)
+{
+ int trace;
+ struct inf *inf = cur_inf ();
+
+ inf->want_signals = parse_bool_arg (args, "set signals");
+
+ if (inf->task && inf->want_signals != inf->traced)
+ /* Make this take effect immediately in a running process. */
+ inf_set_traced (inf, inf->want_signals);
+}
+
+static void
+show_signals_cmd (char *args, int from_tty)
+{
+ struct inf *inf = cur_inf ();
+ check_empty (args, "show signals");
+ printf_unfiltered ("The inferior process's signals %s intercepted.\n",
+ inf->task
+ ? (inf->traced ? "are" : "aren't")
+ : (inf->want_signals ? "will be" : "won't be"));
+}
+
+static void
+set_exceptions_cmd (char *args, int from_tty)
+{
+ struct inf *inf = cur_inf ();
+ int val = parse_bool_arg (args, "set exceptions");
+
+ if (inf->task && inf->want_exceptions != val)
+ /* Make this take effect immediately in a running process. */
+ /* XXX */;
+
+ inf->want_exceptions = val;
+}
+
+static void
+show_exceptions_cmd (char *args, int from_tty)
+{
+ struct inf *inf = cur_inf ();
+ check_empty (args, "show exceptions");
+ printf_unfiltered ("Exceptions in the inferior %s trapped.\n",
+ inf->task
+ ? (inf->want_exceptions ? "are" : "aren't")
+ : (inf->want_exceptions ? "will be" : "won't be"));
+}
+
+static void
+set_task_cmd (char *args, int from_tty)
+{
+ printf_unfiltered ("\"set task\" must be followed by the name of a task property.\n");
+}
+
+static void
+show_task_cmd (char *args, int from_tty)
+{
+ struct inf *inf = cur_inf ();
+
+ check_empty (args, "show task");
+
+ show_signals_cmd (0, from_tty);
+ show_exceptions_cmd (0, from_tty);
+ show_task_pause_cmd (0, from_tty);
+
+ if (inf->pause_sc == 0)
+ show_thread_default_pause_cmd (0, from_tty);
+ show_thread_default_run_cmd (0, from_tty);
+
+ if (inf->task)
+ {
+ show_stopped_cmd (0, from_tty);
+ show_sig_thread_cmd (0, from_tty);
+ }
+
+ if (inf->detach_sc != 0)
+ show_task_detach_sc_cmd (0, from_tty);
+ if (inf->default_thread_detach_sc != 0)
+ show_thread_default_detach_sc_cmd (0, from_tty);
+}
+
+static void
+set_noninvasive_cmd (char *args, int from_tty)
+{
+ /* Invert the sense of the arg for each component. */
+ char *inv_args = parse_bool_arg (args, "set noninvasive") ? "off" : "on";
+
+ set_task_pause_cmd (inv_args, from_tty);
+ set_signals_cmd (inv_args, from_tty);
+ set_exceptions_cmd (inv_args, from_tty);
+}
+
+static void
+info_port_rights (char *args, mach_port_type_t only)
+{
+ struct inf *inf = active_inf ();
+ value_ptr vmark = value_mark ();
+
+ if (args)
+ /* Explicit list of port rights. */
+ {
+ while (*args)
+ {
+ value_ptr val = parse_to_comma_and_eval (&args);
+ long right = value_as_long (val);
+ error_t err =
+ print_port_info (right, 0, inf->task->port, PORTINFO_DETAILS,
+ stdout);
+ if (err)
+ error ("%ld: %s.", right, strerror (err));
+ }
+ }
+ else
+ /* Print all of them. */
+ {
+ error_t err =
+ print_task_ports_info (inf->task->port, only, PORTINFO_DETAILS,
+ stdout);
+ if (err)
+ error ("%s.", strerror (err));
+ }
+
+ value_free_to_mark (vmark);
+}
+
+static void
+info_send_rights_cmd (char *args, int from_tty)
+{
+ info_port_rights (args, MACH_PORT_TYPE_SEND);
+}
+static void
+info_recv_rights_cmd (char *args, int from_tty)
+{
+ info_port_rights (args, MACH_PORT_TYPE_RECEIVE);
+}
+static void
+info_port_sets_cmd (char *args, int from_tty)
+{
+ info_port_rights (args, MACH_PORT_TYPE_PORT_SET);
+}
+static void
+info_dead_names_cmd (char *args, int from_tty)
+{
+ info_port_rights (args, MACH_PORT_TYPE_DEAD_NAME);
+}
+static void
+info_port_rights_cmd (char *args, int from_tty)
+{
+ info_port_rights (args, ~0);
+}
+
+static void add_task_commands ()
+{
+ add_cmd ("pause", class_run, set_thread_default_pause_cmd,
+ "Set whether the new threads are suspended while gdb has control.\n"
+ "This property normally has no effect because the whole task is\n"
+ "suspended, however, that may be disabled with \"set task pause off\".\n"
+ "The default value is \"off\".",
+ &set_thread_default_cmd_list);
+ add_cmd ("pause", no_class, show_thread_default_pause_cmd,
+ "Show whether new threads are suspended while gdb has control.",
+ &show_thread_default_cmd_list);
+ add_cmd ("run", class_run, set_thread_default_run_cmd,
+ "Set whether new threads are allowed to run (once gdb has noticed them).",
+ &set_thread_default_cmd_list);
+ add_cmd ("run", no_class, show_thread_default_run_cmd,
+ "Show whether new threads are allowed to run (once gdb has noticed
+them).",
+ &show_thread_default_cmd_list);
+ add_cmd ("detach-suspend-count", class_run, set_thread_default_detach_sc_cmd,
+ "Set the default detach-suspend-count value for new threads.",
+ &set_thread_default_cmd_list);
+ add_cmd ("detach-suspend-count", no_class, show_thread_default_detach_sc_cmd,
+ "Show the default detach-suspend-count value for new threads.",
+ &show_thread_default_cmd_list);
+
+ add_cmd ("signals", class_run, set_signals_cmd,
+ "Set whether the inferior process's signals will be intercepted.\n"
+ "Mach exceptions (such as breakpoint traps) are not affected.",
+ &setlist);
+ add_alias_cmd ("sigs", "signals", class_run, 1, &setlist);
+ add_cmd ("signals", no_class, show_signals_cmd,
+ "Show whether the inferior process's signals will be intercepted.",
+ &showlist);
+ add_alias_cmd ("sigs", "signals", no_class, 1, &showlist);
+
+ add_cmd ("signal-thread", class_run, set_sig_thread_cmd,
+ "Set the thread that gdb thinks is the libc signal thread.\n"
+ "This thread is run when delivering a signal to a non-stopped process.",
+ &setlist);
+ add_alias_cmd ("sigthread", "signal-thread", class_run, 1, &setlist);
+ add_cmd ("signal-thread", no_class, show_sig_thread_cmd,
+ "Set the thread that gdb thinks is the libc signal thread.",
+ &showlist);
+ add_alias_cmd ("sigthread", "signal-thread", no_class, 1, &showlist);
+
+ add_cmd ("stopped", class_run, set_stopped_cmd,
+ "Set whether gdb thinks the inferior process is stopped as with SIGSTOP.\n"
+ "Stopped process will be continued by sending them a signal.",
+ &setlist);
+ add_cmd ("stopped", no_class, show_signals_cmd,
+ "Show whether gdb thinks the inferior process is stopped as with SIGSTOP.",
+ &showlist);
+
+ add_cmd ("exceptions", class_run, set_exceptions_cmd,
+ "Set whether exceptions in the inferior process will be trapped.\n"
+ "When exceptions are turned off, neither breakpoints nor single-stepping\n"
+ "will work.",
+ &setlist);
+ /* Allow `set exc' despite conflict with `set exception-port'. */
+ add_alias_cmd ("exc", "exceptions", class_run, 1, &setlist);
+ add_cmd ("exceptions", no_class, show_exceptions_cmd,
+ "Show whether exceptions in the inferior process will be trapped.",
+ &showlist);
+
+ add_prefix_cmd ("task", no_class, set_task_cmd,
+ "Command prefix for setting task attributes.",
+ &set_task_cmd_list, "set task ", 0, &setlist);
+ add_prefix_cmd ("task", no_class, show_task_cmd,
+ "Command prefix for showing task attributes.",
+ &show_task_cmd_list, "show task ", 0, &showlist);
+
+ add_cmd ("pause", class_run, set_task_pause_cmd,
+ "Set whether the task is suspended while gdb has control.\n"
+ "A value of \"on\" takes effect immediately, otherwise nothing\n"
+ "happens until the next time the program is continued.\n"
+ "When setting this to \"off\", \"set thread default pause on\"\n"
+ "can be used to pause individual threads by default instead.",
+ &set_task_cmd_list);
+ add_cmd ("pause", no_class, show_task_pause_cmd,
+ "Show whether the task is suspended while gdb has control.",
+ &show_task_cmd_list);
+ add_cmd ("detach-suspend-count", class_run, set_task_detach_sc_cmd,
+ "Set the suspend count will leave on the thread when detaching.",
+ &set_task_cmd_list);
+ add_cmd ("detach-suspend-count", no_class, show_task_detach_sc_cmd,
+ "Show the suspend count will leave on the thread when detaching.",
+ &show_task_cmd_list);
+
+ add_cmd ("exception-port", no_class, set_task_exc_port_cmd,
+ "Set the task exception port to which we forward exceptions.\n"
+ "The argument should be the value of the send right in the task.",
+ &set_task_cmd_list);
+ add_alias_cmd ("excp", "exception-port", no_class, 1, &set_task_cmd_list);
+ add_alias_cmd ("exc-port", "exception-port", no_class, 1, &set_task_cmd_list);
+
+ /* A convenient way of turning on all options require to noninvasively
+ debug running tasks. */
+ add_cmd ("noninvasive", no_class, set_noninvasive_cmd,
+ "Set task options so that we interfere as little as possible.\n"
+ "This is the same as setting `task pause', `exceptions', and"
+ "`signals' to the opposite value.",
+ &setlist);
+
+ /* Commands to show information about the task's ports. */
+ add_cmd ("send-rights", class_info, info_send_rights_cmd,
+ "Show information about the task's send rights",
+ &infolist);
+ add_cmd ("receive-rights", class_info, info_recv_rights_cmd,
+ "Show information about the task's receive rights",
+ &infolist);
+ add_cmd ("port-rights", class_info, info_send_rights_cmd,
+ "Show information about the task's port rights",
+ &infolist);
+ add_cmd ("port-sets", class_info, info_port_sets_cmd,
+ "Show information about the task's port sets",
+ &infolist);
+ add_cmd ("dead-names", class_info, info_dead_names_cmd,
+ "Show information about the task's dead names",
+ &infolist);
+ add_info_alias ("ports", "port-rights", 1);
+ add_info_alias ("port", "port-rights", 1);
+ add_info_alias ("psets", "port-sets", 1);
+}
+
+
+static void
+set_thread_pause_cmd (char *args, int from_tty)
+{
+ struct proc *thread = cur_thread ();
+ int old_sc = thread->pause_sc;
+ thread->pause_sc = parse_bool_arg (args, "set thread pause");
+ if (old_sc == 0 && thread->pause_sc != 0 && thread->inf->pause_sc == 0)
+ /* If the task is currently unsuspended, immediately suspend it,
+ otherwise wait until the next time it gets control. */
+ inf_suspend (thread->inf);
+}
+
+static void
+show_thread_pause_cmd (char *args, int from_tty)
+{
+ struct proc *thread = cur_thread ();
+ int sc = thread->pause_sc;
+ check_empty (args, "show task pause");
+ printf_unfiltered ("Thread %s %s suspended while gdb has control%s.\n",
+ proc_string (thread),
+ sc ? "is" : "isn't",
+ !sc && thread->inf->pause_sc ? " (but the task is)" : "");
+}
+
+static void
+set_thread_run_cmd (char *args, int from_tty)
+{
+ struct proc *thread = cur_thread ();
+ thread->run_sc = parse_bool_arg (args, "set thread run") ? 0 : 1;
+}
+
+static void
+show_thread_run_cmd (char *args, int from_tty)
+{
+ struct proc *thread = cur_thread ();
+ check_empty (args, "show thread run");
+ printf_unfiltered ("Thread %s %s allowed to run.",
+ proc_string (thread),
+ thread->run_sc == 0 ? "is" : "isn't");
+}
+
+static void
+set_thread_detach_sc_cmd (char *args, int from_tty)
+{
+ cur_thread ()->detach_sc = parse_int_arg (args, "set thread detach-suspend-count");
+}
+
+static void
+show_thread_detach_sc_cmd (char *args, int from_tty)
+{
+ struct proc *thread = cur_thread ();
+ check_empty (args, "show thread detach-suspend-count");
+ printf_unfiltered ("Thread %s will be left with a suspend count of %d when detaching.\n",
+ proc_string (thread),
+ thread->detach_sc);
+}
+
+static void
+set_thread_exc_port_cmd (char *args, int from_tty)
+{
+ struct proc *thread = cur_thread ();
+ if (!args)
+ error ("No argument to \"set thread exception-port\" command.");
+ steal_exc_port (thread, parse_and_eval_address (args));
+}
+
+#if 0
+static void
+show_thread_cmd (char *args, int from_tty)
+{
+ struct proc *thread = cur_thread ();
+ check_empty (args, "show thread");
+ show_thread_run_cmd (0, from_tty);
+ show_thread_pause_cmd (0, from_tty);
+ if (thread->detach_sc != 0)
+ show_thread_detach_sc_cmd (0, from_tty);
+}
+#endif
+
+static void
+thread_takeover_sc_cmd (char *args, int from_tty)
+{
+ struct proc *thread = cur_thread ();
+ thread_basic_info_data_t _info;
+ thread_basic_info_t info = &_info;
+ mach_msg_type_number_t info_len = THREAD_BASIC_INFO_COUNT;
+ error_t err =
+ thread_info (thread->port, THREAD_BASIC_INFO, (int *)&info, &info_len);
+ if (err)
+ error ("%s.", strerror (err));
+ thread->sc = info->suspend_count;
+ if (from_tty)
+ printf_unfiltered ("Suspend count was %d.\n", thread->sc);
+ if (info != &_info)
+ vm_deallocate (mach_task_self (), (vm_address_t)info, info_len * sizeof (int));
+}
+
+add_thread_commands ()
+{
+ add_prefix_cmd ("thread", no_class, set_thread_cmd,
+ "Command prefix for setting thread properties.",
+ &set_thread_cmd_list, "set thread ", 0, &setlist);
+ add_prefix_cmd ("default", no_class, show_thread_cmd,
+ "Command prefix for setting default thread properties.",
+ &set_thread_default_cmd_list, "set thread default ", 0,
+ &set_thread_cmd_list);
+ add_prefix_cmd ("thread", no_class, set_thread_default_cmd,
+ "Command prefix for showing thread properties.",
+ &show_thread_cmd_list, "show thread ", 0, &showlist);
+ add_prefix_cmd ("default", no_class, show_thread_default_cmd,
+ "Command prefix for showing default thread properties.",
+ &show_thread_default_cmd_list, "show thread default ", 0,
+ &show_thread_cmd_list);
+
+ add_cmd ("pause", class_run, set_thread_pause_cmd,
+ "Set whether the current thread is suspended while gdb has control.\n"
+ "A value of \"on\" takes effect immediately, otherwise nothing\n"
+ "happens until the next time the program is continued. This\n"
+ "property normally has no effect because the whole task is suspended,\n"
+ "however, that may be disabled with \"set task pause off\".\n"
+ "The default value is \"off\".",
+ &set_thread_cmd_list);
+ add_cmd ("pause", no_class, show_thread_pause_cmd,
+ "Show whether the current thread is suspended while gdb has control.",
+ &show_thread_cmd_list);
+
+ add_cmd ("run", class_run, set_thread_run_cmd,
+ "Set whether the current thread is allowed to run.",
+ &set_thread_cmd_list);
+ add_cmd ("run", no_class, show_thread_run_cmd,
+ "Show whether the current thread is allowed to run.",
+ &show_thread_cmd_list);
+
+ add_cmd ("detach-suspend-count", class_run, set_thread_detach_sc_cmd,
+ "Set the suspend count will leave on the thread when detaching.\n"
+ "Note that this is relative to suspend count when gdb noticed the thread;\n"
+ "use the `thread takeover-suspend-count' to force it to an absolute value.",
+ &set_thread_cmd_list);
+ add_cmd ("detach-suspend-count", no_class, show_thread_detach_sc_cmd,
+ "Show the suspend count will leave on the thread when detaching."
+ "Note that this is relative to suspend count when gdb noticed the thread;\n"
+ "use the `thread takeover-suspend-count' to force it to an absolute value.",
+ &show_thread_cmd_list);
+
+ add_cmd ("exception-port", no_class, set_thread_exc_port_cmd,
+ "Set the exception port to which we forward exceptions for the\n"
+ "current thread, overriding the task exception port.\n"
+ "The argument should be the value of the send right in the task.",
+ &set_thread_cmd_list);
+ add_alias_cmd ("excp", "exception-port", no_class, 1, &set_thread_cmd_list);
+ add_alias_cmd ("exc-port", "exception-port", no_class, 1, &set_thread_cmd_list);
+
+ add_cmd ("takeover-suspend-count", no_class, thread_takeover_sc_cmd,
+ "Force the threads absolute suspend-count to be gdb's.\n"
+ "Prior to giving this command, gdb's thread suspend-counts are relative to\n"
+ "the thread's initial suspend-count when gdb notices the threads.",
+ &thread_cmd_list);
+}
+
+void
+_initialize_gnu_nat ()
+{
+ proc_server = getproc ();
+ init_gnu_ops() ;
+ add_target (&gnu_ops);
+ add_task_commands ();
+ add_thread_commands ();
+
+#if MAINTENANCE_CMDS
+ add_set_cmd ("gnu-debug", class_maintenance,
+ var_boolean, (char *)&gnu_debug_flag,
+ "Set debugging output for the gnu backend.", &maintenancelist);
+#endif
+}
+
+#ifdef FLUSH_INFERIOR_CACHE
+
+/* When over-writing code on some machines the I-Cache must be flushed
+ explicitly, because it is not kept coherent by the lazy hardware.
+ This definitely includes breakpoints, for instance, or else we
+ end up looping in mysterious Bpt traps */
+
+void
+flush_inferior_icache(pc, amount)
+ CORE_ADDR pc;
+{
+ vm_machine_attribute_val_t flush = MATTR_VAL_ICACHE_FLUSH;
+ error_t ret;
+
+ ret = vm_machine_attribute (current_inferior->task->port,
+ pc,
+ amount,
+ MATTR_CACHE,
+ &flush);
+ if (ret != KERN_SUCCESS)
+ warning ("Error flushing inferior's cache : %s", strerror (ret));
+}
+#endif FLUSH_INFERIOR_CACHE
diff --git a/gdb/gnu-nat.h b/gdb/gnu-nat.h
new file mode 100644
index 00000000000..d238dc04a95
--- /dev/null
+++ b/gdb/gnu-nat.h
@@ -0,0 +1,93 @@
+/* Common things used by the various *gnu-nat.c files
+ Copyright (C) 1995, 1996 Free Software Foundation, Inc.
+
+Written by Miles Bader <miles@gnu.ai.mit.edu>
+
+The GNU Hurd is free software; you can redistribute 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.
+
+The GNU Hurd is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef __GNU_NAT_H__
+#define __GNU_NAT_H__
+
+#include <unistd.h>
+#include <mach.h>
+
+struct inf;
+
+extern struct inf *current_inferior;
+
+/* Converts a GDB pid to a struct proc. */
+struct proc *inf_tid_to_thread (struct inf *inf, int tid);
+
+/* A proc is either a thread, or the task (there can only be one task proc
+ because it always has the same TID, PROC_TID_TASK). */
+struct proc
+{
+ thread_t port; /* The task or thread port. */
+ int tid; /* The GDB pid (actually a thread id). */
+ int num; /* An id number for threads, to print. */
+
+ mach_port_t saved_exc_port; /* The task/thread's real exception port. */
+ mach_port_t exc_port; /* Our replacement, which for. */
+
+ int sc; /* Desired suspend count. */
+ int cur_sc; /* Implemented suspend count. */
+ int run_sc; /* Default sc when the program is running. */
+ int pause_sc; /* Default sc when gdb has control. */
+ int resume_sc; /* Sc resulting from the last resume. */
+ int detach_sc; /* SC to leave around when detaching
+ from program. */
+
+ thread_state_data_t state; /* Registers, &c. */
+ int state_valid : 1; /* True if STATE is up to date. */
+ int state_changed : 1;
+
+ int aborted : 1; /* True if thread_abort has been called. */
+ int dead : 1; /* We happen to know it's actually dead. */
+
+ /* Bit mask of registers fetched by gdb. This is used when we re-fetch
+ STATE after aborting the thread, to detect that gdb may have out-of-date
+ information. */
+ unsigned long fetched_regs;
+
+ struct inf *inf; /* Where we come from. */
+
+ struct proc *next;
+};
+
+/* The task has a thread entry with this TID. */
+#define PROC_TID_TASK (-1)
+
+#define proc_is_task(proc) ((proc)->tid == PROC_TID_TASK)
+#define proc_is_thread(proc) ((proc)->tid != PROC_TID_TASK)
+
+extern int __proc_pid (struct proc *proc);
+
+extern thread_state_t proc_get_state (struct proc *proc, int will_modify);
+
+#define proc_debug(_proc, msg, args...) \
+ do { struct proc *__proc = (_proc); \
+ debug ("{proc %d/%d %p}: " msg, \
+ __proc_pid (__proc), __proc->tid, __proc , ##args); } while (0)
+
+#if MAINTENANCE_CMDS
+extern int gnu_debug_flag;
+#define debug(msg, args...) \
+ do { if (gnu_debug_flag) \
+ fprintf (stderr, "%s: " msg "\r\n", __FUNCTION__ , ##args); } while (0)
+#else
+#define debug(msg, args...) (void)0
+#endif
+
+#endif /* __GNU_NAT_H__ */
diff --git a/gdb/gnu-regex.c b/gdb/gnu-regex.c
new file mode 100644
index 00000000000..84db70f7952
--- /dev/null
+++ b/gdb/gnu-regex.c
@@ -0,0 +1,5797 @@
+/* Extended regular expression matching and search library,
+ version 0.12.
+ (Implements POSIX draft P1003.2/D11.2, except for some of the
+ internationalization features.)
+ Copyright (C) 1993, 94, 95, 96, 97, 98 Free Software Foundation, Inc.
+
+ NOTE: The canonical source of this file is maintained with the
+ GNU C Library. Bugs can be reported to bug-glibc@prep.ai.mit.edu.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 2, or (at your option) any
+ later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* AIX requires this to be the first thing in the file. */
+#if defined _AIX && !defined REGEX_MALLOC
+ #pragma alloca
+#endif
+
+#undef _GNU_SOURCE
+#define _GNU_SOURCE
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#ifndef PARAMS
+# if defined __GNUC__ || (defined __STDC__ && __STDC__)
+# define PARAMS(args) args
+# else
+# define PARAMS(args) ()
+# endif /* GCC. */
+#endif /* Not PARAMS. */
+
+#if defined STDC_HEADERS && !defined emacs
+# include <stddef.h>
+#else
+/* We need this for `gnu-regex.h', and perhaps for the Emacs include files. */
+# include <sys/types.h>
+#endif
+
+/* For platform which support the ISO C amendement 1 functionality we
+ support user defined character classes. */
+#if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)
+ /* Solaris 2.5 has a bug: <wchar.h> must be included before <wctype.h>. */
+# include <wchar.h>
+# include <wctype.h>
+#endif
+
+/* This is for other GNU distributions with internationalized messages. */
+/* CYGNUS LOCAL: ../intl will handle this for us */
+#ifdef ENABLE_NLS
+# include <libintl.h>
+#else
+# define gettext(msgid) (msgid)
+#endif
+
+#ifndef gettext_noop
+/* This define is so xgettext can find the internationalizable
+ strings. */
+# define gettext_noop(String) String
+#endif
+
+/* The `emacs' switch turns on certain matching commands
+ that make sense only in Emacs. */
+#ifdef emacs
+
+# include "lisp.h"
+# include "buffer.h"
+# include "syntax.h"
+
+#else /* not emacs */
+
+/* If we are not linking with Emacs proper,
+ we can't use the relocating allocator
+ even if config.h says that we can. */
+# undef REL_ALLOC
+
+# if defined STDC_HEADERS || defined _LIBC
+# include <stdlib.h>
+# else
+char *malloc ();
+char *realloc ();
+# endif
+
+/* When used in Emacs's lib-src, we need to get bzero and bcopy somehow.
+ If nothing else has been done, use the method below. */
+# ifdef INHIBIT_STRING_HEADER
+# if !(defined HAVE_BZERO && defined HAVE_BCOPY)
+# if !defined bzero && !defined bcopy
+# undef INHIBIT_STRING_HEADER
+# endif
+# endif
+# endif
+
+/* This is the normal way of making sure we have a bcopy and a bzero.
+ This is used in most programs--a few other programs avoid this
+ by defining INHIBIT_STRING_HEADER. */
+# ifndef INHIBIT_STRING_HEADER
+# if defined HAVE_STRING_H || defined STDC_HEADERS || defined _LIBC
+# include <string.h>
+# ifndef bzero
+# ifndef _LIBC
+# define bzero(s, n) (memset (s, '\0', n), (s))
+# else
+# define bzero(s, n) __bzero (s, n)
+# endif
+# endif
+# else
+# include <strings.h>
+# ifndef memcmp
+# define memcmp(s1, s2, n) bcmp (s1, s2, n)
+# endif
+# ifndef memcpy
+# define memcpy(d, s, n) (bcopy (s, d, n), (d))
+# endif
+# endif
+# endif
+
+/* Define the syntax stuff for \<, \>, etc. */
+
+/* This must be nonzero for the wordchar and notwordchar pattern
+ commands in re_match_2. */
+# ifndef Sword
+# define Sword 1
+# endif
+
+# ifdef SWITCH_ENUM_BUG
+# define SWITCH_ENUM_CAST(x) ((int)(x))
+# else
+# define SWITCH_ENUM_CAST(x) (x)
+# endif
+
+/* How many characters in the character set. */
+# define CHAR_SET_SIZE 256
+
+/* GDB LOCAL: define _REGEX_RE_COMP to get BSD style re_comp and re_exec */
+#ifndef _REGEX_RE_COMP
+#define _REGEX_RE_COMP
+#endif
+
+# ifdef SYNTAX_TABLE
+
+extern char *re_syntax_table;
+
+# else /* not SYNTAX_TABLE */
+
+static char re_syntax_table[CHAR_SET_SIZE];
+
+static void
+init_syntax_once ()
+{
+ register int c;
+ static int done = 0;
+
+ if (done)
+ return;
+
+ bzero (re_syntax_table, sizeof re_syntax_table);
+
+ for (c = 'a'; c <= 'z'; c++)
+ re_syntax_table[c] = Sword;
+
+ for (c = 'A'; c <= 'Z'; c++)
+ re_syntax_table[c] = Sword;
+
+ for (c = '0'; c <= '9'; c++)
+ re_syntax_table[c] = Sword;
+
+ re_syntax_table['_'] = Sword;
+
+ done = 1;
+}
+
+# endif /* not SYNTAX_TABLE */
+
+# define SYNTAX(c) re_syntax_table[c]
+
+#endif /* not emacs */
+
+/* Get the interface, including the syntax bits. */
+/* CYGNUS LOCAL: call it gnu-regex.h, not regex.h, to avoid name conflicts */
+#include "gnu-regex.h"
+
+/* isalpha etc. are used for the character classes. */
+#include <ctype.h>
+
+/* Jim Meyering writes:
+
+ "... Some ctype macros are valid only for character codes that
+ isascii says are ASCII (SGI's IRIX-4.0.5 is one such system --when
+ using /bin/cc or gcc but without giving an ansi option). So, all
+ ctype uses should be through macros like ISPRINT... If
+ STDC_HEADERS is defined, then autoconf has verified that the ctype
+ macros don't need to be guarded with references to isascii. ...
+ Defining isascii to 1 should let any compiler worth its salt
+ eliminate the && through constant folding."
+ Solaris defines some of these symbols so we must undefine them first. */
+
+#undef ISASCII
+#if defined STDC_HEADERS || (!defined isascii && !defined HAVE_ISASCII)
+# define ISASCII(c) 1
+#else
+# define ISASCII(c) isascii(c)
+#endif
+
+#ifdef isblank
+# define ISBLANK(c) (ISASCII (c) && isblank (c))
+#else
+# define ISBLANK(c) ((c) == ' ' || (c) == '\t')
+#endif
+#ifdef isgraph
+# define ISGRAPH(c) (ISASCII (c) && isgraph (c))
+#else
+# define ISGRAPH(c) (ISASCII (c) && isprint (c) && !isspace (c))
+#endif
+
+#undef ISPRINT
+#define ISPRINT(c) (ISASCII (c) && isprint (c))
+#define ISDIGIT(c) (ISASCII (c) && isdigit (c))
+#define ISALNUM(c) (ISASCII (c) && isalnum (c))
+#define ISALPHA(c) (ISASCII (c) && isalpha (c))
+#define ISCNTRL(c) (ISASCII (c) && iscntrl (c))
+#define ISLOWER(c) (ISASCII (c) && islower (c))
+#define ISPUNCT(c) (ISASCII (c) && ispunct (c))
+#define ISSPACE(c) (ISASCII (c) && isspace (c))
+#define ISUPPER(c) (ISASCII (c) && isupper (c))
+#define ISXDIGIT(c) (ISASCII (c) && isxdigit (c))
+
+#ifndef NULL
+# define NULL (void *)0
+#endif
+
+/* We remove any previous definition of `SIGN_EXTEND_CHAR',
+ since ours (we hope) works properly with all combinations of
+ machines, compilers, `char' and `unsigned char' argument types.
+ (Per Bothner suggested the basic approach.) */
+#undef SIGN_EXTEND_CHAR
+#if __STDC__
+# define SIGN_EXTEND_CHAR(c) ((signed char) (c))
+#else /* not __STDC__ */
+/* As in Harbison and Steele. */
+# define SIGN_EXTEND_CHAR(c) ((((unsigned char) (c)) ^ 128) - 128)
+#endif
+
+/* Should we use malloc or alloca? If REGEX_MALLOC is not defined, we
+ use `alloca' instead of `malloc'. This is because using malloc in
+ re_search* or re_match* could cause memory leaks when C-g is used in
+ Emacs; also, malloc is slower and causes storage fragmentation. On
+ the other hand, malloc is more portable, and easier to debug.
+
+ Because we sometimes use alloca, some routines have to be macros,
+ not functions -- `alloca'-allocated space disappears at the end of the
+ function it is called in. */
+
+#ifdef REGEX_MALLOC
+
+# define REGEX_ALLOCATE malloc
+# define REGEX_REALLOCATE(source, osize, nsize) realloc (source, nsize)
+# define REGEX_FREE free
+
+#else /* not REGEX_MALLOC */
+
+/* Emacs already defines alloca, sometimes. */
+# ifndef alloca
+
+/* Make alloca work the best possible way. */
+# ifdef __GNUC__
+# define alloca __builtin_alloca
+# else /* not __GNUC__ */
+# if HAVE_ALLOCA_H
+# include <alloca.h>
+# endif /* HAVE_ALLOCA_H */
+# endif /* not __GNUC__ */
+
+# endif /* not alloca */
+
+# define REGEX_ALLOCATE alloca
+
+/* Assumes a `char *destination' variable. */
+# define REGEX_REALLOCATE(source, osize, nsize) \
+ (destination = (char *) alloca (nsize), \
+ memcpy (destination, source, osize))
+
+/* No need to do anything to free, after alloca. */
+# define REGEX_FREE(arg) ((void)0) /* Do nothing! But inhibit gcc warning. */
+
+#endif /* not REGEX_MALLOC */
+
+/* Define how to allocate the failure stack. */
+
+#if defined REL_ALLOC && defined REGEX_MALLOC
+
+# define REGEX_ALLOCATE_STACK(size) \
+ r_alloc (&failure_stack_ptr, (size))
+# define REGEX_REALLOCATE_STACK(source, osize, nsize) \
+ r_re_alloc (&failure_stack_ptr, (nsize))
+# define REGEX_FREE_STACK(ptr) \
+ r_alloc_free (&failure_stack_ptr)
+
+#else /* not using relocating allocator */
+
+# ifdef REGEX_MALLOC
+
+# define REGEX_ALLOCATE_STACK malloc
+# define REGEX_REALLOCATE_STACK(source, osize, nsize) realloc (source, nsize)
+# define REGEX_FREE_STACK free
+
+# else /* not REGEX_MALLOC */
+
+# define REGEX_ALLOCATE_STACK alloca
+
+# define REGEX_REALLOCATE_STACK(source, osize, nsize) \
+ REGEX_REALLOCATE (source, osize, nsize)
+/* No need to explicitly free anything. */
+# define REGEX_FREE_STACK(arg)
+
+# endif /* not REGEX_MALLOC */
+#endif /* not using relocating allocator */
+
+
+/* True if `size1' is non-NULL and PTR is pointing anywhere inside
+ `string1' or just past its end. This works if PTR is NULL, which is
+ a good thing. */
+#define FIRST_STRING_P(ptr) \
+ (size1 && string1 <= (ptr) && (ptr) <= string1 + size1)
+
+/* (Re)Allocate N items of type T using malloc, or fail. */
+#define TALLOC(n, t) ((t *) malloc ((n) * sizeof (t)))
+#define RETALLOC(addr, n, t) ((addr) = (t *) realloc (addr, (n) * sizeof (t)))
+#define RETALLOC_IF(addr, n, t) \
+ if (addr) RETALLOC((addr), (n), t); else (addr) = TALLOC ((n), t)
+#define REGEX_TALLOC(n, t) ((t *) REGEX_ALLOCATE ((n) * sizeof (t)))
+
+#define BYTEWIDTH 8 /* In bits. */
+
+#define STREQ(s1, s2) ((strcmp (s1, s2) == 0))
+
+#undef MAX
+#undef MIN
+#define MAX(a, b) ((a) > (b) ? (a) : (b))
+#define MIN(a, b) ((a) < (b) ? (a) : (b))
+
+typedef char boolean;
+#define false 0
+#define true 1
+
+static int re_match_2_internal PARAMS ((struct re_pattern_buffer *bufp,
+ const char *string1, int size1,
+ const char *string2, int size2,
+ int pos,
+ struct re_registers *regs,
+ int stop));
+
+/* These are the command codes that appear in compiled regular
+ expressions. Some opcodes are followed by argument bytes. A
+ command code can specify any interpretation whatsoever for its
+ arguments. Zero bytes may appear in the compiled regular expression. */
+
+typedef enum
+{
+ no_op = 0,
+
+ /* Succeed right away--no more backtracking. */
+ succeed,
+
+ /* Followed by one byte giving n, then by n literal bytes. */
+ exactn,
+
+ /* Matches any (more or less) character. */
+ anychar,
+
+ /* Matches any one char belonging to specified set. First
+ following byte is number of bitmap bytes. Then come bytes
+ for a bitmap saying which chars are in. Bits in each byte
+ are ordered low-bit-first. A character is in the set if its
+ bit is 1. A character too large to have a bit in the map is
+ automatically not in the set. */
+ charset,
+
+ /* Same parameters as charset, but match any character that is
+ not one of those specified. */
+ charset_not,
+
+ /* Start remembering the text that is matched, for storing in a
+ register. Followed by one byte with the register number, in
+ the range 0 to one less than the pattern buffer's re_nsub
+ field. Then followed by one byte with the number of groups
+ inner to this one. (This last has to be part of the
+ start_memory only because we need it in the on_failure_jump
+ of re_match_2.) */
+ start_memory,
+
+ /* Stop remembering the text that is matched and store it in a
+ memory register. Followed by one byte with the register
+ number, in the range 0 to one less than `re_nsub' in the
+ pattern buffer, and one byte with the number of inner groups,
+ just like `start_memory'. (We need the number of inner
+ groups here because we don't have any easy way of finding the
+ corresponding start_memory when we're at a stop_memory.) */
+ stop_memory,
+
+ /* Match a duplicate of something remembered. Followed by one
+ byte containing the register number. */
+ duplicate,
+
+ /* Fail unless at beginning of line. */
+ begline,
+
+ /* Fail unless at end of line. */
+ endline,
+
+ /* Succeeds if at beginning of buffer (if emacs) or at beginning
+ of string to be matched (if not). */
+ begbuf,
+
+ /* Analogously, for end of buffer/string. */
+ endbuf,
+
+ /* Followed by two byte relative address to which to jump. */
+ jump,
+
+ /* Same as jump, but marks the end of an alternative. */
+ jump_past_alt,
+
+ /* Followed by two-byte relative address of place to resume at
+ in case of failure. */
+ on_failure_jump,
+
+ /* Like on_failure_jump, but pushes a placeholder instead of the
+ current string position when executed. */
+ on_failure_keep_string_jump,
+
+ /* Throw away latest failure point and then jump to following
+ two-byte relative address. */
+ pop_failure_jump,
+
+ /* Change to pop_failure_jump if know won't have to backtrack to
+ match; otherwise change to jump. This is used to jump
+ back to the beginning of a repeat. If what follows this jump
+ clearly won't match what the repeat does, such that we can be
+ sure that there is no use backtracking out of repetitions
+ already matched, then we change it to a pop_failure_jump.
+ Followed by two-byte address. */
+ maybe_pop_jump,
+
+ /* Jump to following two-byte address, and push a dummy failure
+ point. This failure point will be thrown away if an attempt
+ is made to use it for a failure. A `+' construct makes this
+ before the first repeat. Also used as an intermediary kind
+ of jump when compiling an alternative. */
+ dummy_failure_jump,
+
+ /* Push a dummy failure point and continue. Used at the end of
+ alternatives. */
+ push_dummy_failure,
+
+ /* Followed by two-byte relative address and two-byte number n.
+ After matching N times, jump to the address upon failure. */
+ succeed_n,
+
+ /* Followed by two-byte relative address, and two-byte number n.
+ Jump to the address N times, then fail. */
+ jump_n,
+
+ /* Set the following two-byte relative address to the
+ subsequent two-byte number. The address *includes* the two
+ bytes of number. */
+ set_number_at,
+
+ wordchar, /* Matches any word-constituent character. */
+ notwordchar, /* Matches any char that is not a word-constituent. */
+
+ wordbeg, /* Succeeds if at word beginning. */
+ wordend, /* Succeeds if at word end. */
+
+ wordbound, /* Succeeds if at a word boundary. */
+ notwordbound /* Succeeds if not at a word boundary. */
+
+#ifdef emacs
+ ,before_dot, /* Succeeds if before point. */
+ at_dot, /* Succeeds if at point. */
+ after_dot, /* Succeeds if after point. */
+
+ /* Matches any character whose syntax is specified. Followed by
+ a byte which contains a syntax code, e.g., Sword. */
+ syntaxspec,
+
+ /* Matches any character whose syntax is not that specified. */
+ notsyntaxspec
+#endif /* emacs */
+} re_opcode_t;
+
+/* Common operations on the compiled pattern. */
+
+/* Store NUMBER in two contiguous bytes starting at DESTINATION. */
+
+#define STORE_NUMBER(destination, number) \
+ do { \
+ (destination)[0] = (number) & 0377; \
+ (destination)[1] = (number) >> 8; \
+ } while (0)
+
+/* Same as STORE_NUMBER, except increment DESTINATION to
+ the byte after where the number is stored. Therefore, DESTINATION
+ must be an lvalue. */
+
+#define STORE_NUMBER_AND_INCR(destination, number) \
+ do { \
+ STORE_NUMBER (destination, number); \
+ (destination) += 2; \
+ } while (0)
+
+/* Put into DESTINATION a number stored in two contiguous bytes starting
+ at SOURCE. */
+
+#define EXTRACT_NUMBER(destination, source) \
+ do { \
+ (destination) = *(source) & 0377; \
+ (destination) += SIGN_EXTEND_CHAR (*((source) + 1)) << 8; \
+ } while (0)
+
+#ifdef DEBUG
+static void extract_number _RE_ARGS ((int *dest, unsigned char *source));
+static void
+extract_number (dest, source)
+ int *dest;
+ unsigned char *source;
+{
+ int temp = SIGN_EXTEND_CHAR (*(source + 1));
+ *dest = *source & 0377;
+ *dest += temp << 8;
+}
+
+# ifndef EXTRACT_MACROS /* To debug the macros. */
+# undef EXTRACT_NUMBER
+# define EXTRACT_NUMBER(dest, src) extract_number (&dest, src)
+# endif /* not EXTRACT_MACROS */
+
+#endif /* DEBUG */
+
+/* Same as EXTRACT_NUMBER, except increment SOURCE to after the number.
+ SOURCE must be an lvalue. */
+
+#define EXTRACT_NUMBER_AND_INCR(destination, source) \
+ do { \
+ EXTRACT_NUMBER (destination, source); \
+ (source) += 2; \
+ } while (0)
+
+#ifdef DEBUG
+static void extract_number_and_incr _RE_ARGS ((int *destination,
+ unsigned char **source));
+static void
+extract_number_and_incr (destination, source)
+ int *destination;
+ unsigned char **source;
+{
+ extract_number (destination, *source);
+ *source += 2;
+}
+
+# ifndef EXTRACT_MACROS
+# undef EXTRACT_NUMBER_AND_INCR
+# define EXTRACT_NUMBER_AND_INCR(dest, src) \
+ extract_number_and_incr (&dest, &src)
+# endif /* not EXTRACT_MACROS */
+
+#endif /* DEBUG */
+
+/* If DEBUG is defined, Regex prints many voluminous messages about what
+ it is doing (if the variable `debug' is nonzero). If linked with the
+ main program in `iregex.c', you can enter patterns and strings
+ interactively. And if linked with the main program in `main.c' and
+ the other test files, you can run the already-written tests. */
+
+#ifdef DEBUG
+
+/* We use standard I/O for debugging. */
+# include <stdio.h>
+
+/* It is useful to test things that ``must'' be true when debugging. */
+# include <assert.h>
+
+static int debug = 0;
+
+# define DEBUG_STATEMENT(e) e
+# define DEBUG_PRINT1(x) if (debug) printf (x)
+# define DEBUG_PRINT2(x1, x2) if (debug) printf (x1, x2)
+# define DEBUG_PRINT3(x1, x2, x3) if (debug) printf (x1, x2, x3)
+# define DEBUG_PRINT4(x1, x2, x3, x4) if (debug) printf (x1, x2, x3, x4)
+# define DEBUG_PRINT_COMPILED_PATTERN(p, s, e) \
+ if (debug) print_partial_compiled_pattern (s, e)
+# define DEBUG_PRINT_DOUBLE_STRING(w, s1, sz1, s2, sz2) \
+ if (debug) print_double_string (w, s1, sz1, s2, sz2)
+
+
+/* Print the fastmap in human-readable form. */
+
+void
+print_fastmap (fastmap)
+ char *fastmap;
+{
+ unsigned was_a_range = 0;
+ unsigned i = 0;
+
+ while (i < (1 << BYTEWIDTH))
+ {
+ if (fastmap[i++])
+ {
+ was_a_range = 0;
+ putchar (i - 1);
+ while (i < (1 << BYTEWIDTH) && fastmap[i])
+ {
+ was_a_range = 1;
+ i++;
+ }
+ if (was_a_range)
+ {
+ printf ("-");
+ putchar (i - 1);
+ }
+ }
+ }
+ putchar ('\n');
+}
+
+
+/* Print a compiled pattern string in human-readable form, starting at
+ the START pointer into it and ending just before the pointer END. */
+
+void
+print_partial_compiled_pattern (start, end)
+ unsigned char *start;
+ unsigned char *end;
+{
+ int mcnt, mcnt2;
+ unsigned char *p1;
+ unsigned char *p = start;
+ unsigned char *pend = end;
+
+ if (start == NULL)
+ {
+ printf ("(null)\n");
+ return;
+ }
+
+ /* Loop over pattern commands. */
+ while (p < pend)
+ {
+ printf ("%d:\t", p - start);
+
+ switch ((re_opcode_t) *p++)
+ {
+ case no_op:
+ printf ("/no_op");
+ break;
+
+ case exactn:
+ mcnt = *p++;
+ printf ("/exactn/%d", mcnt);
+ do
+ {
+ putchar ('/');
+ putchar (*p++);
+ }
+ while (--mcnt);
+ break;
+
+ case start_memory:
+ mcnt = *p++;
+ printf ("/start_memory/%d/%d", mcnt, *p++);
+ break;
+
+ case stop_memory:
+ mcnt = *p++;
+ printf ("/stop_memory/%d/%d", mcnt, *p++);
+ break;
+
+ case duplicate:
+ printf ("/duplicate/%d", *p++);
+ break;
+
+ case anychar:
+ printf ("/anychar");
+ break;
+
+ case charset:
+ case charset_not:
+ {
+ register int c, last = -100;
+ register int in_range = 0;
+
+ printf ("/charset [%s",
+ (re_opcode_t) *(p - 1) == charset_not ? "^" : "");
+
+ assert (p + *p < pend);
+
+ for (c = 0; c < 256; c++)
+ if (c / 8 < *p
+ && (p[1 + (c/8)] & (1 << (c % 8))))
+ {
+ /* Are we starting a range? */
+ if (last + 1 == c && ! in_range)
+ {
+ putchar ('-');
+ in_range = 1;
+ }
+ /* Have we broken a range? */
+ else if (last + 1 != c && in_range)
+ {
+ putchar (last);
+ in_range = 0;
+ }
+
+ if (! in_range)
+ putchar (c);
+
+ last = c;
+ }
+
+ if (in_range)
+ putchar (last);
+
+ putchar (']');
+
+ p += 1 + *p;
+ }
+ break;
+
+ case begline:
+ printf ("/begline");
+ break;
+
+ case endline:
+ printf ("/endline");
+ break;
+
+ case on_failure_jump:
+ extract_number_and_incr (&mcnt, &p);
+ printf ("/on_failure_jump to %d", p + mcnt - start);
+ break;
+
+ case on_failure_keep_string_jump:
+ extract_number_and_incr (&mcnt, &p);
+ printf ("/on_failure_keep_string_jump to %d", p + mcnt - start);
+ break;
+
+ case dummy_failure_jump:
+ extract_number_and_incr (&mcnt, &p);
+ printf ("/dummy_failure_jump to %d", p + mcnt - start);
+ break;
+
+ case push_dummy_failure:
+ printf ("/push_dummy_failure");
+ break;
+
+ case maybe_pop_jump:
+ extract_number_and_incr (&mcnt, &p);
+ printf ("/maybe_pop_jump to %d", p + mcnt - start);
+ break;
+
+ case pop_failure_jump:
+ extract_number_and_incr (&mcnt, &p);
+ printf ("/pop_failure_jump to %d", p + mcnt - start);
+ break;
+
+ case jump_past_alt:
+ extract_number_and_incr (&mcnt, &p);
+ printf ("/jump_past_alt to %d", p + mcnt - start);
+ break;
+
+ case jump:
+ extract_number_and_incr (&mcnt, &p);
+ printf ("/jump to %d", p + mcnt - start);
+ break;
+
+ case succeed_n:
+ extract_number_and_incr (&mcnt, &p);
+ p1 = p + mcnt;
+ extract_number_and_incr (&mcnt2, &p);
+ printf ("/succeed_n to %d, %d times", p1 - start, mcnt2);
+ break;
+
+ case jump_n:
+ extract_number_and_incr (&mcnt, &p);
+ p1 = p + mcnt;
+ extract_number_and_incr (&mcnt2, &p);
+ printf ("/jump_n to %d, %d times", p1 - start, mcnt2);
+ break;
+
+ case set_number_at:
+ extract_number_and_incr (&mcnt, &p);
+ p1 = p + mcnt;
+ extract_number_and_incr (&mcnt2, &p);
+ printf ("/set_number_at location %d to %d", p1 - start, mcnt2);
+ break;
+
+ case wordbound:
+ printf ("/wordbound");
+ break;
+
+ case notwordbound:
+ printf ("/notwordbound");
+ break;
+
+ case wordbeg:
+ printf ("/wordbeg");
+ break;
+
+ case wordend:
+ printf ("/wordend");
+
+# ifdef emacs
+ case before_dot:
+ printf ("/before_dot");
+ break;
+
+ case at_dot:
+ printf ("/at_dot");
+ break;
+
+ case after_dot:
+ printf ("/after_dot");
+ break;
+
+ case syntaxspec:
+ printf ("/syntaxspec");
+ mcnt = *p++;
+ printf ("/%d", mcnt);
+ break;
+
+ case notsyntaxspec:
+ printf ("/notsyntaxspec");
+ mcnt = *p++;
+ printf ("/%d", mcnt);
+ break;
+# endif /* emacs */
+
+ case wordchar:
+ printf ("/wordchar");
+ break;
+
+ case notwordchar:
+ printf ("/notwordchar");
+ break;
+
+ case begbuf:
+ printf ("/begbuf");
+ break;
+
+ case endbuf:
+ printf ("/endbuf");
+ break;
+
+ default:
+ printf ("?%d", *(p-1));
+ }
+
+ putchar ('\n');
+ }
+
+ printf ("%d:\tend of pattern.\n", p - start);
+}
+
+
+void
+print_compiled_pattern (bufp)
+ struct re_pattern_buffer *bufp;
+{
+ unsigned char *buffer = bufp->buffer;
+
+ print_partial_compiled_pattern (buffer, buffer + bufp->used);
+ printf ("%ld bytes used/%ld bytes allocated.\n",
+ bufp->used, bufp->allocated);
+
+ if (bufp->fastmap_accurate && bufp->fastmap)
+ {
+ printf ("fastmap: ");
+ print_fastmap (bufp->fastmap);
+ }
+
+ printf ("re_nsub: %d\t", bufp->re_nsub);
+ printf ("regs_alloc: %d\t", bufp->regs_allocated);
+ printf ("can_be_null: %d\t", bufp->can_be_null);
+ printf ("newline_anchor: %d\n", bufp->newline_anchor);
+ printf ("no_sub: %d\t", bufp->no_sub);
+ printf ("not_bol: %d\t", bufp->not_bol);
+ printf ("not_eol: %d\t", bufp->not_eol);
+ printf ("syntax: %lx\n", bufp->syntax);
+ /* Perhaps we should print the translate table? */
+}
+
+
+void
+print_double_string (where, string1, size1, string2, size2)
+ const char *where;
+ const char *string1;
+ const char *string2;
+ int size1;
+ int size2;
+{
+ int this_char;
+
+ if (where == NULL)
+ printf ("(null)");
+ else
+ {
+ if (FIRST_STRING_P (where))
+ {
+ for (this_char = where - string1; this_char < size1; this_char++)
+ putchar (string1[this_char]);
+
+ where = string2;
+ }
+
+ for (this_char = where - string2; this_char < size2; this_char++)
+ putchar (string2[this_char]);
+ }
+}
+
+void
+printchar (c)
+ int c;
+{
+ putc (c, stderr);
+}
+
+#else /* not DEBUG */
+
+# undef assert
+# define assert(e)
+
+# define DEBUG_STATEMENT(e)
+# define DEBUG_PRINT1(x)
+# define DEBUG_PRINT2(x1, x2)
+# define DEBUG_PRINT3(x1, x2, x3)
+# define DEBUG_PRINT4(x1, x2, x3, x4)
+# define DEBUG_PRINT_COMPILED_PATTERN(p, s, e)
+# define DEBUG_PRINT_DOUBLE_STRING(w, s1, sz1, s2, sz2)
+
+#endif /* not DEBUG */
+
+/* Set by `re_set_syntax' to the current regexp syntax to recognize. Can
+ also be assigned to arbitrarily: each pattern buffer stores its own
+ syntax, so it can be changed between regex compilations. */
+/* This has no initializer because initialized variables in Emacs
+ become read-only after dumping. */
+reg_syntax_t re_syntax_options;
+
+
+/* Specify the precise syntax of regexps for compilation. This provides
+ for compatibility for various utilities which historically have
+ different, incompatible syntaxes.
+
+ The argument SYNTAX is a bit mask comprised of the various bits
+ defined in gnu-regex.h. We return the old syntax. */
+
+reg_syntax_t
+re_set_syntax (syntax)
+ reg_syntax_t syntax;
+{
+ reg_syntax_t ret = re_syntax_options;
+
+ re_syntax_options = syntax;
+#ifdef DEBUG
+ if (syntax & RE_DEBUG)
+ debug = 1;
+ else if (debug) /* was on but now is not */
+ debug = 0;
+#endif /* DEBUG */
+ return ret;
+}
+#ifdef _LIBC
+weak_alias (__re_set_syntax, re_set_syntax)
+#endif
+
+/* This table gives an error message for each of the error codes listed
+ in gnu-regex.h. Obviously the order here has to be same as there.
+ POSIX doesn't require that we do anything for REG_NOERROR,
+ but why not be nice? */
+
+static const char *re_error_msgid[] =
+ {
+ gettext_noop ("Success"), /* REG_NOERROR */
+ gettext_noop ("No match"), /* REG_NOMATCH */
+ gettext_noop ("Invalid regular expression"), /* REG_BADPAT */
+ gettext_noop ("Invalid collation character"), /* REG_ECOLLATE */
+ gettext_noop ("Invalid character class name"), /* REG_ECTYPE */
+ gettext_noop ("Trailing backslash"), /* REG_EESCAPE */
+ gettext_noop ("Invalid back reference"), /* REG_ESUBREG */
+ gettext_noop ("Unmatched [ or [^"), /* REG_EBRACK */
+ gettext_noop ("Unmatched ( or \\("), /* REG_EPAREN */
+ gettext_noop ("Unmatched \\{"), /* REG_EBRACE */
+ gettext_noop ("Invalid content of \\{\\}"), /* REG_BADBR */
+ gettext_noop ("Invalid range end"), /* REG_ERANGE */
+ gettext_noop ("Memory exhausted"), /* REG_ESPACE */
+ gettext_noop ("Invalid preceding regular expression"), /* REG_BADRPT */
+ gettext_noop ("Premature end of regular expression"), /* REG_EEND */
+ gettext_noop ("Regular expression too big"), /* REG_ESIZE */
+ gettext_noop ("Unmatched ) or \\)"), /* REG_ERPAREN */
+ };
+
+/* Avoiding alloca during matching, to placate r_alloc. */
+
+/* Define MATCH_MAY_ALLOCATE unless we need to make sure that the
+ searching and matching functions should not call alloca. On some
+ systems, alloca is implemented in terms of malloc, and if we're
+ using the relocating allocator routines, then malloc could cause a
+ relocation, which might (if the strings being searched are in the
+ ralloc heap) shift the data out from underneath the regexp
+ routines.
+
+ Here's another reason to avoid allocation: Emacs
+ processes input from X in a signal handler; processing X input may
+ call malloc; if input arrives while a matching routine is calling
+ malloc, then we're scrod. But Emacs can't just block input while
+ calling matching routines; then we don't notice interrupts when
+ they come in. So, Emacs blocks input around all regexp calls
+ except the matching calls, which it leaves unprotected, in the
+ faith that they will not malloc. */
+
+/* Normally, this is fine. */
+#define MATCH_MAY_ALLOCATE
+
+/* When using GNU C, we are not REALLY using the C alloca, no matter
+ what config.h may say. So don't take precautions for it. */
+#ifdef __GNUC__
+# undef C_ALLOCA
+#endif
+
+/* The match routines may not allocate if (1) they would do it with malloc
+ and (2) it's not safe for them to use malloc.
+ Note that if REL_ALLOC is defined, matching would not use malloc for the
+ failure stack, but we would still use it for the register vectors;
+ so REL_ALLOC should not affect this. */
+#if (defined C_ALLOCA || defined REGEX_MALLOC) && defined emacs
+# undef MATCH_MAY_ALLOCATE
+#endif
+
+
+/* Failure stack declarations and macros; both re_compile_fastmap and
+ re_match_2 use a failure stack. These have to be macros because of
+ REGEX_ALLOCATE_STACK. */
+
+
+/* Number of failure points for which to initially allocate space
+ when matching. If this number is exceeded, we allocate more
+ space, so it is not a hard limit. */
+#ifndef INIT_FAILURE_ALLOC
+# define INIT_FAILURE_ALLOC 5
+#endif
+
+/* Roughly the maximum number of failure points on the stack. Would be
+ exactly that if always used MAX_FAILURE_ITEMS items each time we failed.
+ This is a variable only so users of regex can assign to it; we never
+ change it ourselves. */
+
+#ifdef INT_IS_16BIT
+
+# if defined MATCH_MAY_ALLOCATE
+/* 4400 was enough to cause a crash on Alpha OSF/1,
+ whose default stack limit is 2mb. */
+long int re_max_failures = 4000;
+# else
+long int re_max_failures = 2000;
+# endif
+
+union fail_stack_elt
+{
+ unsigned char *pointer;
+ long int integer;
+};
+
+typedef union fail_stack_elt fail_stack_elt_t;
+
+typedef struct
+{
+ fail_stack_elt_t *stack;
+ unsigned long int size;
+ unsigned long int avail; /* Offset of next open position. */
+} fail_stack_type;
+
+#else /* not INT_IS_16BIT */
+
+# if defined MATCH_MAY_ALLOCATE
+/* 4400 was enough to cause a crash on Alpha OSF/1,
+ whose default stack limit is 2mb. */
+int re_max_failures = 20000;
+# else
+int re_max_failures = 2000;
+# endif
+
+union fail_stack_elt
+{
+ unsigned char *pointer;
+ int integer;
+};
+
+typedef union fail_stack_elt fail_stack_elt_t;
+
+typedef struct
+{
+ fail_stack_elt_t *stack;
+ unsigned size;
+ unsigned avail; /* Offset of next open position. */
+} fail_stack_type;
+
+#endif /* INT_IS_16BIT */
+
+#define FAIL_STACK_EMPTY() (fail_stack.avail == 0)
+#define FAIL_STACK_PTR_EMPTY() (fail_stack_ptr->avail == 0)
+#define FAIL_STACK_FULL() (fail_stack.avail == fail_stack.size)
+
+
+/* Define macros to initialize and free the failure stack.
+ Do `return -2' if the alloc fails. */
+
+#ifdef MATCH_MAY_ALLOCATE
+# define INIT_FAIL_STACK() \
+ do { \
+ fail_stack.stack = (fail_stack_elt_t *) \
+ REGEX_ALLOCATE_STACK (INIT_FAILURE_ALLOC * sizeof (fail_stack_elt_t)); \
+ \
+ if (fail_stack.stack == NULL) \
+ return -2; \
+ \
+ fail_stack.size = INIT_FAILURE_ALLOC; \
+ fail_stack.avail = 0; \
+ } while (0)
+
+# define RESET_FAIL_STACK() REGEX_FREE_STACK (fail_stack.stack)
+#else
+# define INIT_FAIL_STACK() \
+ do { \
+ fail_stack.avail = 0; \
+ } while (0)
+
+# define RESET_FAIL_STACK()
+#endif
+
+
+/* Double the size of FAIL_STACK, up to approximately `re_max_failures' items.
+
+ Return 1 if succeeds, and 0 if either ran out of memory
+ allocating space for it or it was already too large.
+
+ REGEX_REALLOCATE_STACK requires `destination' be declared. */
+
+#define DOUBLE_FAIL_STACK(fail_stack) \
+ ((fail_stack).size > (unsigned) (re_max_failures * MAX_FAILURE_ITEMS) \
+ ? 0 \
+ : ((fail_stack).stack = (fail_stack_elt_t *) \
+ REGEX_REALLOCATE_STACK ((fail_stack).stack, \
+ (fail_stack).size * sizeof (fail_stack_elt_t), \
+ ((fail_stack).size << 1) * sizeof (fail_stack_elt_t)), \
+ \
+ (fail_stack).stack == NULL \
+ ? 0 \
+ : ((fail_stack).size <<= 1, \
+ 1)))
+
+
+/* Push pointer POINTER on FAIL_STACK.
+ Return 1 if was able to do so and 0 if ran out of memory allocating
+ space to do so. */
+#define PUSH_PATTERN_OP(POINTER, FAIL_STACK) \
+ ((FAIL_STACK_FULL () \
+ && !DOUBLE_FAIL_STACK (FAIL_STACK)) \
+ ? 0 \
+ : ((FAIL_STACK).stack[(FAIL_STACK).avail++].pointer = POINTER, \
+ 1))
+
+/* Push a pointer value onto the failure stack.
+ Assumes the variable `fail_stack'. Probably should only
+ be called from within `PUSH_FAILURE_POINT'. */
+#define PUSH_FAILURE_POINTER(item) \
+ fail_stack.stack[fail_stack.avail++].pointer = (unsigned char *) (item)
+
+/* This pushes an integer-valued item onto the failure stack.
+ Assumes the variable `fail_stack'. Probably should only
+ be called from within `PUSH_FAILURE_POINT'. */
+#define PUSH_FAILURE_INT(item) \
+ fail_stack.stack[fail_stack.avail++].integer = (item)
+
+/* Push a fail_stack_elt_t value onto the failure stack.
+ Assumes the variable `fail_stack'. Probably should only
+ be called from within `PUSH_FAILURE_POINT'. */
+#define PUSH_FAILURE_ELT(item) \
+ fail_stack.stack[fail_stack.avail++] = (item)
+
+/* These three POP... operations complement the three PUSH... operations.
+ All assume that `fail_stack' is nonempty. */
+#define POP_FAILURE_POINTER() fail_stack.stack[--fail_stack.avail].pointer
+#define POP_FAILURE_INT() fail_stack.stack[--fail_stack.avail].integer
+#define POP_FAILURE_ELT() fail_stack.stack[--fail_stack.avail]
+
+/* Used to omit pushing failure point id's when we're not debugging. */
+#ifdef DEBUG
+# define DEBUG_PUSH PUSH_FAILURE_INT
+# define DEBUG_POP(item_addr) *(item_addr) = POP_FAILURE_INT ()
+#else
+# define DEBUG_PUSH(item)
+# define DEBUG_POP(item_addr)
+#endif
+
+
+/* Push the information about the state we will need
+ if we ever fail back to it.
+
+ Requires variables fail_stack, regstart, regend, reg_info, and
+ num_regs_pushed be declared. DOUBLE_FAIL_STACK requires `destination'
+ be declared.
+
+ Does `return FAILURE_CODE' if runs out of memory. */
+
+#define PUSH_FAILURE_POINT(pattern_place, string_place, failure_code) \
+ do { \
+ char *destination; \
+ /* Must be int, so when we don't save any registers, the arithmetic \
+ of 0 + -1 isn't done as unsigned. */ \
+ /* Can't be int, since there is not a shred of a guarantee that int \
+ is wide enough to hold a value of something to which pointer can \
+ be assigned */ \
+ active_reg_t this_reg; \
+ \
+ DEBUG_STATEMENT (failure_id++); \
+ DEBUG_STATEMENT (nfailure_points_pushed++); \
+ DEBUG_PRINT2 ("\nPUSH_FAILURE_POINT #%u:\n", failure_id); \
+ DEBUG_PRINT2 (" Before push, next avail: %d\n", (fail_stack).avail);\
+ DEBUG_PRINT2 (" size: %d\n", (fail_stack).size);\
+ \
+ DEBUG_PRINT2 (" slots needed: %ld\n", NUM_FAILURE_ITEMS); \
+ DEBUG_PRINT2 (" available: %d\n", REMAINING_AVAIL_SLOTS); \
+ \
+ /* Ensure we have enough space allocated for what we will push. */ \
+ while (REMAINING_AVAIL_SLOTS < NUM_FAILURE_ITEMS) \
+ { \
+ if (!DOUBLE_FAIL_STACK (fail_stack)) \
+ return failure_code; \
+ \
+ DEBUG_PRINT2 ("\n Doubled stack; size now: %d\n", \
+ (fail_stack).size); \
+ DEBUG_PRINT2 (" slots available: %d\n", REMAINING_AVAIL_SLOTS);\
+ } \
+ \
+ /* Push the info, starting with the registers. */ \
+ DEBUG_PRINT1 ("\n"); \
+ \
+ if (1) \
+ for (this_reg = lowest_active_reg; this_reg <= highest_active_reg; \
+ this_reg++) \
+ { \
+ DEBUG_PRINT2 (" Pushing reg: %lu\n", this_reg); \
+ DEBUG_STATEMENT (num_regs_pushed++); \
+ \
+ DEBUG_PRINT2 (" start: %p\n", regstart[this_reg]); \
+ PUSH_FAILURE_POINTER (regstart[this_reg]); \
+ \
+ DEBUG_PRINT2 (" end: %p\n", regend[this_reg]); \
+ PUSH_FAILURE_POINTER (regend[this_reg]); \
+ \
+ DEBUG_PRINT2 (" info: %p\n ", \
+ reg_info[this_reg].word.pointer); \
+ DEBUG_PRINT2 (" match_null=%d", \
+ REG_MATCH_NULL_STRING_P (reg_info[this_reg])); \
+ DEBUG_PRINT2 (" active=%d", IS_ACTIVE (reg_info[this_reg])); \
+ DEBUG_PRINT2 (" matched_something=%d", \
+ MATCHED_SOMETHING (reg_info[this_reg])); \
+ DEBUG_PRINT2 (" ever_matched=%d", \
+ EVER_MATCHED_SOMETHING (reg_info[this_reg])); \
+ DEBUG_PRINT1 ("\n"); \
+ PUSH_FAILURE_ELT (reg_info[this_reg].word); \
+ } \
+ \
+ DEBUG_PRINT2 (" Pushing low active reg: %ld\n", lowest_active_reg);\
+ PUSH_FAILURE_INT (lowest_active_reg); \
+ \
+ DEBUG_PRINT2 (" Pushing high active reg: %ld\n", highest_active_reg);\
+ PUSH_FAILURE_INT (highest_active_reg); \
+ \
+ DEBUG_PRINT2 (" Pushing pattern %p:\n", pattern_place); \
+ DEBUG_PRINT_COMPILED_PATTERN (bufp, pattern_place, pend); \
+ PUSH_FAILURE_POINTER (pattern_place); \
+ \
+ DEBUG_PRINT2 (" Pushing string %p: `", string_place); \
+ DEBUG_PRINT_DOUBLE_STRING (string_place, string1, size1, string2, \
+ size2); \
+ DEBUG_PRINT1 ("'\n"); \
+ PUSH_FAILURE_POINTER (string_place); \
+ \
+ DEBUG_PRINT2 (" Pushing failure id: %u\n", failure_id); \
+ DEBUG_PUSH (failure_id); \
+ } while (0)
+
+/* This is the number of items that are pushed and popped on the stack
+ for each register. */
+#define NUM_REG_ITEMS 3
+
+/* Individual items aside from the registers. */
+#ifdef DEBUG
+# define NUM_NONREG_ITEMS 5 /* Includes failure point id. */
+#else
+# define NUM_NONREG_ITEMS 4
+#endif
+
+/* We push at most this many items on the stack. */
+/* We used to use (num_regs - 1), which is the number of registers
+ this regexp will save; but that was changed to 5
+ to avoid stack overflow for a regexp with lots of parens. */
+#define MAX_FAILURE_ITEMS (5 * NUM_REG_ITEMS + NUM_NONREG_ITEMS)
+
+/* We actually push this many items. */
+#define NUM_FAILURE_ITEMS \
+ (((0 \
+ ? 0 : highest_active_reg - lowest_active_reg + 1) \
+ * NUM_REG_ITEMS) \
+ + NUM_NONREG_ITEMS)
+
+/* How many items can still be added to the stack without overflowing it. */
+#define REMAINING_AVAIL_SLOTS ((fail_stack).size - (fail_stack).avail)
+
+
+/* Pops what PUSH_FAIL_STACK pushes.
+
+ We restore into the parameters, all of which should be lvalues:
+ STR -- the saved data position.
+ PAT -- the saved pattern position.
+ LOW_REG, HIGH_REG -- the highest and lowest active registers.
+ REGSTART, REGEND -- arrays of string positions.
+ REG_INFO -- array of information about each subexpression.
+
+ Also assumes the variables `fail_stack' and (if debugging), `bufp',
+ `pend', `string1', `size1', `string2', and `size2'. */
+
+#define POP_FAILURE_POINT(str, pat, low_reg, high_reg, regstart, regend, reg_info)\
+{ \
+ DEBUG_STATEMENT (unsigned failure_id;) \
+ active_reg_t this_reg; \
+ const unsigned char *string_temp; \
+ \
+ assert (!FAIL_STACK_EMPTY ()); \
+ \
+ /* Remove failure points and point to how many regs pushed. */ \
+ DEBUG_PRINT1 ("POP_FAILURE_POINT:\n"); \
+ DEBUG_PRINT2 (" Before pop, next avail: %d\n", fail_stack.avail); \
+ DEBUG_PRINT2 (" size: %d\n", fail_stack.size); \
+ \
+ assert (fail_stack.avail >= NUM_NONREG_ITEMS); \
+ \
+ DEBUG_POP (&failure_id); \
+ DEBUG_PRINT2 (" Popping failure id: %u\n", failure_id); \
+ \
+ /* If the saved string location is NULL, it came from an \
+ on_failure_keep_string_jump opcode, and we want to throw away the \
+ saved NULL, thus retaining our current position in the string. */ \
+ string_temp = POP_FAILURE_POINTER (); \
+ if (string_temp != NULL) \
+ str = (const char *) string_temp; \
+ \
+ DEBUG_PRINT2 (" Popping string %p: `", str); \
+ DEBUG_PRINT_DOUBLE_STRING (str, string1, size1, string2, size2); \
+ DEBUG_PRINT1 ("'\n"); \
+ \
+ pat = (unsigned char *) POP_FAILURE_POINTER (); \
+ DEBUG_PRINT2 (" Popping pattern %p:\n", pat); \
+ DEBUG_PRINT_COMPILED_PATTERN (bufp, pat, pend); \
+ \
+ /* Restore register info. */ \
+ high_reg = (active_reg_t) POP_FAILURE_INT (); \
+ DEBUG_PRINT2 (" Popping high active reg: %ld\n", high_reg); \
+ \
+ low_reg = (active_reg_t) POP_FAILURE_INT (); \
+ DEBUG_PRINT2 (" Popping low active reg: %ld\n", low_reg); \
+ \
+ if (1) \
+ for (this_reg = high_reg; this_reg >= low_reg; this_reg--) \
+ { \
+ DEBUG_PRINT2 (" Popping reg: %ld\n", this_reg); \
+ \
+ reg_info[this_reg].word = POP_FAILURE_ELT (); \
+ DEBUG_PRINT2 (" info: %p\n", \
+ reg_info[this_reg].word.pointer); \
+ \
+ regend[this_reg] = (const char *) POP_FAILURE_POINTER (); \
+ DEBUG_PRINT2 (" end: %p\n", regend[this_reg]); \
+ \
+ regstart[this_reg] = (const char *) POP_FAILURE_POINTER (); \
+ DEBUG_PRINT2 (" start: %p\n", regstart[this_reg]); \
+ } \
+ else \
+ { \
+ for (this_reg = highest_active_reg; this_reg > high_reg; this_reg--) \
+ { \
+ reg_info[this_reg].word.integer = 0; \
+ regend[this_reg] = 0; \
+ regstart[this_reg] = 0; \
+ } \
+ highest_active_reg = high_reg; \
+ } \
+ \
+ set_regs_matched_done = 0; \
+ DEBUG_STATEMENT (nfailure_points_popped++); \
+} /* POP_FAILURE_POINT */
+
+
+
+/* Structure for per-register (a.k.a. per-group) information.
+ Other register information, such as the
+ starting and ending positions (which are addresses), and the list of
+ inner groups (which is a bits list) are maintained in separate
+ variables.
+
+ We are making a (strictly speaking) nonportable assumption here: that
+ the compiler will pack our bit fields into something that fits into
+ the type of `word', i.e., is something that fits into one item on the
+ failure stack. */
+
+
+/* Declarations and macros for re_match_2. */
+
+typedef union
+{
+ fail_stack_elt_t word;
+ struct
+ {
+ /* This field is one if this group can match the empty string,
+ zero if not. If not yet determined, `MATCH_NULL_UNSET_VALUE'. */
+#define MATCH_NULL_UNSET_VALUE 3
+ unsigned match_null_string_p : 2;
+ unsigned is_active : 1;
+ unsigned matched_something : 1;
+ unsigned ever_matched_something : 1;
+ } bits;
+} register_info_type;
+
+#define REG_MATCH_NULL_STRING_P(R) ((R).bits.match_null_string_p)
+#define IS_ACTIVE(R) ((R).bits.is_active)
+#define MATCHED_SOMETHING(R) ((R).bits.matched_something)
+#define EVER_MATCHED_SOMETHING(R) ((R).bits.ever_matched_something)
+
+
+/* Call this when have matched a real character; it sets `matched' flags
+ for the subexpressions which we are currently inside. Also records
+ that those subexprs have matched. */
+#define SET_REGS_MATCHED() \
+ do \
+ { \
+ if (!set_regs_matched_done) \
+ { \
+ active_reg_t r; \
+ set_regs_matched_done = 1; \
+ for (r = lowest_active_reg; r <= highest_active_reg; r++) \
+ { \
+ MATCHED_SOMETHING (reg_info[r]) \
+ = EVER_MATCHED_SOMETHING (reg_info[r]) \
+ = 1; \
+ } \
+ } \
+ } \
+ while (0)
+
+/* Registers are set to a sentinel when they haven't yet matched. */
+static char reg_unset_dummy;
+#define REG_UNSET_VALUE (&reg_unset_dummy)
+#define REG_UNSET(e) ((e) == REG_UNSET_VALUE)
+
+/* Subroutine declarations and macros for regex_compile. */
+
+static reg_errcode_t regex_compile _RE_ARGS ((const char *pattern, size_t size,
+ reg_syntax_t syntax,
+ struct re_pattern_buffer *bufp));
+static void store_op1 _RE_ARGS ((re_opcode_t op, unsigned char *loc, int arg));
+static void store_op2 _RE_ARGS ((re_opcode_t op, unsigned char *loc,
+ int arg1, int arg2));
+static void insert_op1 _RE_ARGS ((re_opcode_t op, unsigned char *loc,
+ int arg, unsigned char *end));
+static void insert_op2 _RE_ARGS ((re_opcode_t op, unsigned char *loc,
+ int arg1, int arg2, unsigned char *end));
+static boolean at_begline_loc_p _RE_ARGS ((const char *pattern, const char *p,
+ reg_syntax_t syntax));
+static boolean at_endline_loc_p _RE_ARGS ((const char *p, const char *pend,
+ reg_syntax_t syntax));
+static reg_errcode_t compile_range _RE_ARGS ((const char **p_ptr,
+ const char *pend,
+ char *translate,
+ reg_syntax_t syntax,
+ unsigned char *b));
+
+/* Fetch the next character in the uncompiled pattern---translating it
+ if necessary. Also cast from a signed character in the constant
+ string passed to us by the user to an unsigned char that we can use
+ as an array index (in, e.g., `translate'). */
+#ifndef PATFETCH
+# define PATFETCH(c) \
+ do {if (p == pend) return REG_EEND; \
+ c = (unsigned char) *p++; \
+ if (translate) c = (unsigned char) translate[c]; \
+ } while (0)
+#endif
+
+/* Fetch the next character in the uncompiled pattern, with no
+ translation. */
+#define PATFETCH_RAW(c) \
+ do {if (p == pend) return REG_EEND; \
+ c = (unsigned char) *p++; \
+ } while (0)
+
+/* Go backwards one character in the pattern. */
+#define PATUNFETCH p--
+
+
+/* If `translate' is non-null, return translate[D], else just D. We
+ cast the subscript to translate because some data is declared as
+ `char *', to avoid warnings when a string constant is passed. But
+ when we use a character as a subscript we must make it unsigned. */
+#ifndef TRANSLATE
+# define TRANSLATE(d) \
+ (translate ? (char) translate[(unsigned char) (d)] : (d))
+#endif
+
+
+/* Macros for outputting the compiled pattern into `buffer'. */
+
+/* If the buffer isn't allocated when it comes in, use this. */
+#define INIT_BUF_SIZE 32
+
+/* Make sure we have at least N more bytes of space in buffer. */
+#define GET_BUFFER_SPACE(n) \
+ while ((unsigned long) (b - bufp->buffer + (n)) > bufp->allocated) \
+ EXTEND_BUFFER ()
+
+/* Make sure we have one more byte of buffer space and then add C to it. */
+#define BUF_PUSH(c) \
+ do { \
+ GET_BUFFER_SPACE (1); \
+ *b++ = (unsigned char) (c); \
+ } while (0)
+
+
+/* Ensure we have two more bytes of buffer space and then append C1 and C2. */
+#define BUF_PUSH_2(c1, c2) \
+ do { \
+ GET_BUFFER_SPACE (2); \
+ *b++ = (unsigned char) (c1); \
+ *b++ = (unsigned char) (c2); \
+ } while (0)
+
+
+/* As with BUF_PUSH_2, except for three bytes. */
+#define BUF_PUSH_3(c1, c2, c3) \
+ do { \
+ GET_BUFFER_SPACE (3); \
+ *b++ = (unsigned char) (c1); \
+ *b++ = (unsigned char) (c2); \
+ *b++ = (unsigned char) (c3); \
+ } while (0)
+
+
+/* Store a jump with opcode OP at LOC to location TO. We store a
+ relative address offset by the three bytes the jump itself occupies. */
+#define STORE_JUMP(op, loc, to) \
+ store_op1 (op, loc, (int) ((to) - (loc) - 3))
+
+/* Likewise, for a two-argument jump. */
+#define STORE_JUMP2(op, loc, to, arg) \
+ store_op2 (op, loc, (int) ((to) - (loc) - 3), arg)
+
+/* Like `STORE_JUMP', but for inserting. Assume `b' is the buffer end. */
+#define INSERT_JUMP(op, loc, to) \
+ insert_op1 (op, loc, (int) ((to) - (loc) - 3), b)
+
+/* Like `STORE_JUMP2', but for inserting. Assume `b' is the buffer end. */
+#define INSERT_JUMP2(op, loc, to, arg) \
+ insert_op2 (op, loc, (int) ((to) - (loc) - 3), arg, b)
+
+
+/* This is not an arbitrary limit: the arguments which represent offsets
+ into the pattern are two bytes long. So if 2^16 bytes turns out to
+ be too small, many things would have to change. */
+/* Any other compiler which, like MSC, has allocation limit below 2^16
+ bytes will have to use approach similar to what was done below for
+ MSC and drop MAX_BUF_SIZE a bit. Otherwise you may end up
+ reallocating to 0 bytes. Such thing is not going to work too well.
+ You have been warned!! */
+#if defined _MSC_VER && !defined WIN32
+/* Microsoft C 16-bit versions limit malloc to approx 65512 bytes.
+ The REALLOC define eliminates a flurry of conversion warnings,
+ but is not required. */
+# define MAX_BUF_SIZE 65500L
+# define REALLOC(p,s) realloc ((p), (size_t) (s))
+#else
+# define MAX_BUF_SIZE (1L << 16)
+# define REALLOC(p,s) realloc ((p), (s))
+#endif
+
+/* Extend the buffer by twice its current size via realloc and
+ reset the pointers that pointed into the old block to point to the
+ correct places in the new one. If extending the buffer results in it
+ being larger than MAX_BUF_SIZE, then flag memory exhausted. */
+#define EXTEND_BUFFER() \
+ do { \
+ unsigned char *old_buffer = bufp->buffer; \
+ if (bufp->allocated == MAX_BUF_SIZE) \
+ return REG_ESIZE; \
+ bufp->allocated <<= 1; \
+ if (bufp->allocated > MAX_BUF_SIZE) \
+ bufp->allocated = MAX_BUF_SIZE; \
+ bufp->buffer = (unsigned char *) REALLOC (bufp->buffer, bufp->allocated);\
+ if (bufp->buffer == NULL) \
+ return REG_ESPACE; \
+ /* If the buffer moved, move all the pointers into it. */ \
+ if (old_buffer != bufp->buffer) \
+ { \
+ b = (b - old_buffer) + bufp->buffer; \
+ begalt = (begalt - old_buffer) + bufp->buffer; \
+ if (fixup_alt_jump) \
+ fixup_alt_jump = (fixup_alt_jump - old_buffer) + bufp->buffer;\
+ if (laststart) \
+ laststart = (laststart - old_buffer) + bufp->buffer; \
+ if (pending_exact) \
+ pending_exact = (pending_exact - old_buffer) + bufp->buffer; \
+ } \
+ } while (0)
+
+
+/* Since we have one byte reserved for the register number argument to
+ {start,stop}_memory, the maximum number of groups we can report
+ things about is what fits in that byte. */
+#define MAX_REGNUM 255
+
+/* But patterns can have more than `MAX_REGNUM' registers. We just
+ ignore the excess. */
+typedef unsigned regnum_t;
+
+
+/* Macros for the compile stack. */
+
+/* Since offsets can go either forwards or backwards, this type needs to
+ be able to hold values from -(MAX_BUF_SIZE - 1) to MAX_BUF_SIZE - 1. */
+/* int may be not enough when sizeof(int) == 2. */
+typedef long pattern_offset_t;
+
+typedef struct
+{
+ pattern_offset_t begalt_offset;
+ pattern_offset_t fixup_alt_jump;
+ pattern_offset_t inner_group_offset;
+ pattern_offset_t laststart_offset;
+ regnum_t regnum;
+} compile_stack_elt_t;
+
+
+typedef struct
+{
+ compile_stack_elt_t *stack;
+ unsigned size;
+ unsigned avail; /* Offset of next open position. */
+} compile_stack_type;
+
+
+#define INIT_COMPILE_STACK_SIZE 32
+
+#define COMPILE_STACK_EMPTY (compile_stack.avail == 0)
+#define COMPILE_STACK_FULL (compile_stack.avail == compile_stack.size)
+
+/* The next available element. */
+#define COMPILE_STACK_TOP (compile_stack.stack[compile_stack.avail])
+
+
+/* Set the bit for character C in a list. */
+#define SET_LIST_BIT(c) \
+ (b[((unsigned char) (c)) / BYTEWIDTH] \
+ |= 1 << (((unsigned char) c) % BYTEWIDTH))
+
+
+/* Get the next unsigned number in the uncompiled pattern. */
+#define GET_UNSIGNED_NUMBER(num) \
+ { if (p != pend) \
+ { \
+ PATFETCH (c); \
+ while (ISDIGIT (c)) \
+ { \
+ if (num < 0) \
+ num = 0; \
+ num = num * 10 + c - '0'; \
+ if (p == pend) \
+ break; \
+ PATFETCH (c); \
+ } \
+ } \
+ }
+
+#if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)
+/* The GNU C library provides support for user-defined character classes
+ and the functions from ISO C amendement 1. */
+# ifdef CHARCLASS_NAME_MAX
+# define CHAR_CLASS_MAX_LENGTH CHARCLASS_NAME_MAX
+# else
+/* This shouldn't happen but some implementation might still have this
+ problem. Use a reasonable default value. */
+# define CHAR_CLASS_MAX_LENGTH 256
+# endif
+
+# ifdef _LIBC
+# define IS_CHAR_CLASS(string) __wctype (string)
+# else
+# define IS_CHAR_CLASS(string) wctype (string)
+# endif
+#else
+# define CHAR_CLASS_MAX_LENGTH 6 /* Namely, `xdigit'. */
+
+# define IS_CHAR_CLASS(string) \
+ (STREQ (string, "alpha") || STREQ (string, "upper") \
+ || STREQ (string, "lower") || STREQ (string, "digit") \
+ || STREQ (string, "alnum") || STREQ (string, "xdigit") \
+ || STREQ (string, "space") || STREQ (string, "print") \
+ || STREQ (string, "punct") || STREQ (string, "graph") \
+ || STREQ (string, "cntrl") || STREQ (string, "blank"))
+#endif
+
+#ifndef MATCH_MAY_ALLOCATE
+
+/* If we cannot allocate large objects within re_match_2_internal,
+ we make the fail stack and register vectors global.
+ The fail stack, we grow to the maximum size when a regexp
+ is compiled.
+ The register vectors, we adjust in size each time we
+ compile a regexp, according to the number of registers it needs. */
+
+static fail_stack_type fail_stack;
+
+/* Size with which the following vectors are currently allocated.
+ That is so we can make them bigger as needed,
+ but never make them smaller. */
+static int regs_allocated_size;
+
+static const char ** regstart, ** regend;
+static const char ** old_regstart, ** old_regend;
+static const char **best_regstart, **best_regend;
+static register_info_type *reg_info;
+static const char **reg_dummy;
+static register_info_type *reg_info_dummy;
+
+/* Make the register vectors big enough for NUM_REGS registers,
+ but don't make them smaller. */
+
+static
+regex_grow_registers (num_regs)
+ int num_regs;
+{
+ if (num_regs > regs_allocated_size)
+ {
+ RETALLOC_IF (regstart, num_regs, const char *);
+ RETALLOC_IF (regend, num_regs, const char *);
+ RETALLOC_IF (old_regstart, num_regs, const char *);
+ RETALLOC_IF (old_regend, num_regs, const char *);
+ RETALLOC_IF (best_regstart, num_regs, const char *);
+ RETALLOC_IF (best_regend, num_regs, const char *);
+ RETALLOC_IF (reg_info, num_regs, register_info_type);
+ RETALLOC_IF (reg_dummy, num_regs, const char *);
+ RETALLOC_IF (reg_info_dummy, num_regs, register_info_type);
+
+ regs_allocated_size = num_regs;
+ }
+}
+
+#endif /* not MATCH_MAY_ALLOCATE */
+
+static boolean group_in_compile_stack _RE_ARGS ((compile_stack_type
+ compile_stack,
+ regnum_t regnum));
+
+/* `regex_compile' compiles PATTERN (of length SIZE) according to SYNTAX.
+ Returns one of error codes defined in `gnu-regex.h', or zero for success.
+
+ Assumes the `allocated' (and perhaps `buffer') and `translate'
+ fields are set in BUFP on entry.
+
+ If it succeeds, results are put in BUFP (if it returns an error, the
+ contents of BUFP are undefined):
+ `buffer' is the compiled pattern;
+ `syntax' is set to SYNTAX;
+ `used' is set to the length of the compiled pattern;
+ `fastmap_accurate' is zero;
+ `re_nsub' is the number of subexpressions in PATTERN;
+ `not_bol' and `not_eol' are zero;
+
+ The `fastmap' and `newline_anchor' fields are neither
+ examined nor set. */
+
+/* Return, freeing storage we allocated. */
+#define FREE_STACK_RETURN(value) \
+ return (free (compile_stack.stack), value)
+
+static reg_errcode_t
+regex_compile (pattern, size, syntax, bufp)
+ const char *pattern;
+ size_t size;
+ reg_syntax_t syntax;
+ struct re_pattern_buffer *bufp;
+{
+ /* We fetch characters from PATTERN here. Even though PATTERN is
+ `char *' (i.e., signed), we declare these variables as unsigned, so
+ they can be reliably used as array indices. */
+ register unsigned char c, c1;
+
+ /* A random temporary spot in PATTERN. */
+ const char *p1;
+
+ /* Points to the end of the buffer, where we should append. */
+ register unsigned char *b;
+
+ /* Keeps track of unclosed groups. */
+ compile_stack_type compile_stack;
+
+ /* Points to the current (ending) position in the pattern. */
+ const char *p = pattern;
+ const char *pend = pattern + size;
+
+ /* How to translate the characters in the pattern. */
+ RE_TRANSLATE_TYPE translate = bufp->translate;
+
+ /* Address of the count-byte of the most recently inserted `exactn'
+ command. This makes it possible to tell if a new exact-match
+ character can be added to that command or if the character requires
+ a new `exactn' command. */
+ unsigned char *pending_exact = 0;
+
+ /* Address of start of the most recently finished expression.
+ This tells, e.g., postfix * where to find the start of its
+ operand. Reset at the beginning of groups and alternatives. */
+ unsigned char *laststart = 0;
+
+ /* Address of beginning of regexp, or inside of last group. */
+ unsigned char *begalt;
+
+ /* Place in the uncompiled pattern (i.e., the {) to
+ which to go back if the interval is invalid. */
+ const char *beg_interval;
+
+ /* Address of the place where a forward jump should go to the end of
+ the containing expression. Each alternative of an `or' -- except the
+ last -- ends with a forward jump of this sort. */
+ unsigned char *fixup_alt_jump = 0;
+
+ /* Counts open-groups as they are encountered. Remembered for the
+ matching close-group on the compile stack, so the same register
+ number is put in the stop_memory as the start_memory. */
+ regnum_t regnum = 0;
+
+#ifdef DEBUG
+ DEBUG_PRINT1 ("\nCompiling pattern: ");
+ if (debug)
+ {
+ unsigned debug_count;
+
+ for (debug_count = 0; debug_count < size; debug_count++)
+ putchar (pattern[debug_count]);
+ putchar ('\n');
+ }
+#endif /* DEBUG */
+
+ /* Initialize the compile stack. */
+ compile_stack.stack = TALLOC (INIT_COMPILE_STACK_SIZE, compile_stack_elt_t);
+ if (compile_stack.stack == NULL)
+ return REG_ESPACE;
+
+ compile_stack.size = INIT_COMPILE_STACK_SIZE;
+ compile_stack.avail = 0;
+
+ /* Initialize the pattern buffer. */
+ bufp->syntax = syntax;
+ bufp->fastmap_accurate = 0;
+ bufp->not_bol = bufp->not_eol = 0;
+
+ /* Set `used' to zero, so that if we return an error, the pattern
+ printer (for debugging) will think there's no pattern. We reset it
+ at the end. */
+ bufp->used = 0;
+
+ /* Always count groups, whether or not bufp->no_sub is set. */
+ bufp->re_nsub = 0;
+
+#if !defined emacs && !defined SYNTAX_TABLE
+ /* Initialize the syntax table. */
+ init_syntax_once ();
+#endif
+
+ if (bufp->allocated == 0)
+ {
+ if (bufp->buffer)
+ { /* If zero allocated, but buffer is non-null, try to realloc
+ enough space. This loses if buffer's address is bogus, but
+ that is the user's responsibility. */
+ RETALLOC (bufp->buffer, INIT_BUF_SIZE, unsigned char);
+ }
+ else
+ { /* Caller did not allocate a buffer. Do it for them. */
+ bufp->buffer = TALLOC (INIT_BUF_SIZE, unsigned char);
+ }
+ if (!bufp->buffer) FREE_STACK_RETURN (REG_ESPACE);
+
+ bufp->allocated = INIT_BUF_SIZE;
+ }
+
+ begalt = b = bufp->buffer;
+
+ /* Loop through the uncompiled pattern until we're at the end. */
+ while (p != pend)
+ {
+ PATFETCH (c);
+
+ switch (c)
+ {
+ case '^':
+ {
+ if ( /* If at start of pattern, it's an operator. */
+ p == pattern + 1
+ /* If context independent, it's an operator. */
+ || syntax & RE_CONTEXT_INDEP_ANCHORS
+ /* Otherwise, depends on what's come before. */
+ || at_begline_loc_p (pattern, p, syntax))
+ BUF_PUSH (begline);
+ else
+ goto normal_char;
+ }
+ break;
+
+
+ case '$':
+ {
+ if ( /* If at end of pattern, it's an operator. */
+ p == pend
+ /* If context independent, it's an operator. */
+ || syntax & RE_CONTEXT_INDEP_ANCHORS
+ /* Otherwise, depends on what's next. */
+ || at_endline_loc_p (p, pend, syntax))
+ BUF_PUSH (endline);
+ else
+ goto normal_char;
+ }
+ break;
+
+
+ case '+':
+ case '?':
+ if ((syntax & RE_BK_PLUS_QM)
+ || (syntax & RE_LIMITED_OPS))
+ goto normal_char;
+ handle_plus:
+ case '*':
+ /* If there is no previous pattern... */
+ if (!laststart)
+ {
+ if (syntax & RE_CONTEXT_INVALID_OPS)
+ FREE_STACK_RETURN (REG_BADRPT);
+ else if (!(syntax & RE_CONTEXT_INDEP_OPS))
+ goto normal_char;
+ }
+
+ {
+ /* Are we optimizing this jump? */
+ boolean keep_string_p = false;
+
+ /* 1 means zero (many) matches is allowed. */
+ char zero_times_ok = 0, many_times_ok = 0;
+
+ /* If there is a sequence of repetition chars, collapse it
+ down to just one (the right one). We can't combine
+ interval operators with these because of, e.g., `a{2}*',
+ which should only match an even number of `a's. */
+
+ for (;;)
+ {
+ zero_times_ok |= c != '+';
+ many_times_ok |= c != '?';
+
+ if (p == pend)
+ break;
+
+ PATFETCH (c);
+
+ if (c == '*'
+ || (!(syntax & RE_BK_PLUS_QM) && (c == '+' || c == '?')))
+ ;
+
+ else if (syntax & RE_BK_PLUS_QM && c == '\\')
+ {
+ if (p == pend) FREE_STACK_RETURN (REG_EESCAPE);
+
+ PATFETCH (c1);
+ if (!(c1 == '+' || c1 == '?'))
+ {
+ PATUNFETCH;
+ PATUNFETCH;
+ break;
+ }
+
+ c = c1;
+ }
+ else
+ {
+ PATUNFETCH;
+ break;
+ }
+
+ /* If we get here, we found another repeat character. */
+ }
+
+ /* Star, etc. applied to an empty pattern is equivalent
+ to an empty pattern. */
+ if (!laststart)
+ break;
+
+ /* Now we know whether or not zero matches is allowed
+ and also whether or not two or more matches is allowed. */
+ if (many_times_ok)
+ { /* More than one repetition is allowed, so put in at the
+ end a backward relative jump from `b' to before the next
+ jump we're going to put in below (which jumps from
+ laststart to after this jump).
+
+ But if we are at the `*' in the exact sequence `.*\n',
+ insert an unconditional jump backwards to the .,
+ instead of the beginning of the loop. This way we only
+ push a failure point once, instead of every time
+ through the loop. */
+ assert (p - 1 > pattern);
+
+ /* Allocate the space for the jump. */
+ GET_BUFFER_SPACE (3);
+
+ /* We know we are not at the first character of the pattern,
+ because laststart was nonzero. And we've already
+ incremented `p', by the way, to be the character after
+ the `*'. Do we have to do something analogous here
+ for null bytes, because of RE_DOT_NOT_NULL? */
+ if (TRANSLATE (*(p - 2)) == TRANSLATE ('.')
+ && zero_times_ok
+ && p < pend && TRANSLATE (*p) == TRANSLATE ('\n')
+ && !(syntax & RE_DOT_NEWLINE))
+ { /* We have .*\n. */
+ STORE_JUMP (jump, b, laststart);
+ keep_string_p = true;
+ }
+ else
+ /* Anything else. */
+ STORE_JUMP (maybe_pop_jump, b, laststart - 3);
+
+ /* We've added more stuff to the buffer. */
+ b += 3;
+ }
+
+ /* On failure, jump from laststart to b + 3, which will be the
+ end of the buffer after this jump is inserted. */
+ GET_BUFFER_SPACE (3);
+ INSERT_JUMP (keep_string_p ? on_failure_keep_string_jump
+ : on_failure_jump,
+ laststart, b + 3);
+ pending_exact = 0;
+ b += 3;
+
+ if (!zero_times_ok)
+ {
+ /* At least one repetition is required, so insert a
+ `dummy_failure_jump' before the initial
+ `on_failure_jump' instruction of the loop. This
+ effects a skip over that instruction the first time
+ we hit that loop. */
+ GET_BUFFER_SPACE (3);
+ INSERT_JUMP (dummy_failure_jump, laststart, laststart + 6);
+ b += 3;
+ }
+ }
+ break;
+
+
+ case '.':
+ laststart = b;
+ BUF_PUSH (anychar);
+ break;
+
+
+ case '[':
+ {
+ boolean had_char_class = false;
+
+ if (p == pend) FREE_STACK_RETURN (REG_EBRACK);
+
+ /* Ensure that we have enough space to push a charset: the
+ opcode, the length count, and the bitset; 34 bytes in all. */
+ GET_BUFFER_SPACE (34);
+
+ laststart = b;
+
+ /* We test `*p == '^' twice, instead of using an if
+ statement, so we only need one BUF_PUSH. */
+ BUF_PUSH (*p == '^' ? charset_not : charset);
+ if (*p == '^')
+ p++;
+
+ /* Remember the first position in the bracket expression. */
+ p1 = p;
+
+ /* Push the number of bytes in the bitmap. */
+ BUF_PUSH ((1 << BYTEWIDTH) / BYTEWIDTH);
+
+ /* Clear the whole map. */
+ bzero (b, (1 << BYTEWIDTH) / BYTEWIDTH);
+
+ /* charset_not matches newline according to a syntax bit. */
+ if ((re_opcode_t) b[-2] == charset_not
+ && (syntax & RE_HAT_LISTS_NOT_NEWLINE))
+ SET_LIST_BIT ('\n');
+
+ /* Read in characters and ranges, setting map bits. */
+ for (;;)
+ {
+ if (p == pend) FREE_STACK_RETURN (REG_EBRACK);
+
+ PATFETCH (c);
+
+ /* \ might escape characters inside [...] and [^...]. */
+ if ((syntax & RE_BACKSLASH_ESCAPE_IN_LISTS) && c == '\\')
+ {
+ if (p == pend) FREE_STACK_RETURN (REG_EESCAPE);
+
+ PATFETCH (c1);
+ SET_LIST_BIT (c1);
+ continue;
+ }
+
+ /* Could be the end of the bracket expression. If it's
+ not (i.e., when the bracket expression is `[]' so
+ far), the ']' character bit gets set way below. */
+ if (c == ']' && p != p1 + 1)
+ break;
+
+ /* Look ahead to see if it's a range when the last thing
+ was a character class. */
+ if (had_char_class && c == '-' && *p != ']')
+ FREE_STACK_RETURN (REG_ERANGE);
+
+ /* Look ahead to see if it's a range when the last thing
+ was a character: if this is a hyphen not at the
+ beginning or the end of a list, then it's the range
+ operator. */
+ if (c == '-'
+ && !(p - 2 >= pattern && p[-2] == '[')
+ && !(p - 3 >= pattern && p[-3] == '[' && p[-2] == '^')
+ && *p != ']')
+ {
+ reg_errcode_t ret
+ = compile_range (&p, pend, translate, syntax, b);
+ if (ret != REG_NOERROR) FREE_STACK_RETURN (ret);
+ }
+
+ else if (p[0] == '-' && p[1] != ']')
+ { /* This handles ranges made up of characters only. */
+ reg_errcode_t ret;
+
+ /* Move past the `-'. */
+ PATFETCH (c1);
+
+ ret = compile_range (&p, pend, translate, syntax, b);
+ if (ret != REG_NOERROR) FREE_STACK_RETURN (ret);
+ }
+
+ /* See if we're at the beginning of a possible character
+ class. */
+
+ else if (syntax & RE_CHAR_CLASSES && c == '[' && *p == ':')
+ { /* Leave room for the null. */
+ char str[CHAR_CLASS_MAX_LENGTH + 1];
+
+ PATFETCH (c);
+ c1 = 0;
+
+ /* If pattern is `[[:'. */
+ if (p == pend) FREE_STACK_RETURN (REG_EBRACK);
+
+ for (;;)
+ {
+ PATFETCH (c);
+ if ((c == ':' && *p == ']') || p == pend
+ || c1 == CHAR_CLASS_MAX_LENGTH)
+ break;
+ str[c1++] = c;
+ }
+ str[c1] = '\0';
+
+ /* If isn't a word bracketed by `[:' and `:]':
+ undo the ending character, the letters, and leave
+ the leading `:' and `[' (but set bits for them). */
+ if (c == ':' && *p == ']')
+ {
+/* CYGNUS LOCAL: Skip this code if we don't have btowc(). btowc() is */
+/* defined in the 1994 Amendment 1 to ISO C and may not be present on */
+/* systems where we have wchar.h and wctype.h. */
+#if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H && defined HAVE_BTOWC)
+ boolean is_lower = STREQ (str, "lower");
+ boolean is_upper = STREQ (str, "upper");
+ wctype_t wt;
+ int ch;
+
+ wt = IS_CHAR_CLASS (str);
+ if (wt == 0)
+ FREE_STACK_RETURN (REG_ECTYPE);
+
+ /* Throw away the ] at the end of the character
+ class. */
+ PATFETCH (c);
+
+ if (p == pend) FREE_STACK_RETURN (REG_EBRACK);
+
+ for (ch = 0; ch < 1 << BYTEWIDTH; ++ch)
+ {
+# ifdef _LIBC
+ if (__iswctype (__btowc (ch), wt))
+ SET_LIST_BIT (ch);
+#else
+ if (iswctype (btowc (ch), wt))
+ SET_LIST_BIT (ch);
+#endif
+
+ if (translate && (is_upper || is_lower)
+ && (ISUPPER (ch) || ISLOWER (ch)))
+ SET_LIST_BIT (ch);
+ }
+
+ had_char_class = true;
+#else
+ int ch;
+ boolean is_alnum = STREQ (str, "alnum");
+ boolean is_alpha = STREQ (str, "alpha");
+ boolean is_blank = STREQ (str, "blank");
+ boolean is_cntrl = STREQ (str, "cntrl");
+ boolean is_digit = STREQ (str, "digit");
+ boolean is_graph = STREQ (str, "graph");
+ boolean is_lower = STREQ (str, "lower");
+ boolean is_print = STREQ (str, "print");
+ boolean is_punct = STREQ (str, "punct");
+ boolean is_space = STREQ (str, "space");
+ boolean is_upper = STREQ (str, "upper");
+ boolean is_xdigit = STREQ (str, "xdigit");
+
+ if (!IS_CHAR_CLASS (str))
+ FREE_STACK_RETURN (REG_ECTYPE);
+
+ /* Throw away the ] at the end of the character
+ class. */
+ PATFETCH (c);
+
+ if (p == pend) FREE_STACK_RETURN (REG_EBRACK);
+
+ for (ch = 0; ch < 1 << BYTEWIDTH; ch++)
+ {
+ /* This was split into 3 if's to
+ avoid an arbitrary limit in some compiler. */
+ if ( (is_alnum && ISALNUM (ch))
+ || (is_alpha && ISALPHA (ch))
+ || (is_blank && ISBLANK (ch))
+ || (is_cntrl && ISCNTRL (ch)))
+ SET_LIST_BIT (ch);
+ if ( (is_digit && ISDIGIT (ch))
+ || (is_graph && ISGRAPH (ch))
+ || (is_lower && ISLOWER (ch))
+ || (is_print && ISPRINT (ch)))
+ SET_LIST_BIT (ch);
+ if ( (is_punct && ISPUNCT (ch))
+ || (is_space && ISSPACE (ch))
+ || (is_upper && ISUPPER (ch))
+ || (is_xdigit && ISXDIGIT (ch)))
+ SET_LIST_BIT (ch);
+ if ( translate && (is_upper || is_lower)
+ && (ISUPPER (ch) || ISLOWER (ch)))
+ SET_LIST_BIT (ch);
+ }
+ had_char_class = true;
+#endif /* libc || wctype.h */
+ }
+ else
+ {
+ c1++;
+ while (c1--)
+ PATUNFETCH;
+ SET_LIST_BIT ('[');
+ SET_LIST_BIT (':');
+ had_char_class = false;
+ }
+ }
+ else
+ {
+ had_char_class = false;
+ SET_LIST_BIT (c);
+ }
+ }
+
+ /* Discard any (non)matching list bytes that are all 0 at the
+ end of the map. Decrease the map-length byte too. */
+ while ((int) b[-1] > 0 && b[b[-1] - 1] == 0)
+ b[-1]--;
+ b += b[-1];
+ }
+ break;
+
+
+ case '(':
+ if (syntax & RE_NO_BK_PARENS)
+ goto handle_open;
+ else
+ goto normal_char;
+
+
+ case ')':
+ if (syntax & RE_NO_BK_PARENS)
+ goto handle_close;
+ else
+ goto normal_char;
+
+
+ case '\n':
+ if (syntax & RE_NEWLINE_ALT)
+ goto handle_alt;
+ else
+ goto normal_char;
+
+
+ case '|':
+ if (syntax & RE_NO_BK_VBAR)
+ goto handle_alt;
+ else
+ goto normal_char;
+
+
+ case '{':
+ if (syntax & RE_INTERVALS && syntax & RE_NO_BK_BRACES)
+ goto handle_interval;
+ else
+ goto normal_char;
+
+
+ case '\\':
+ if (p == pend) FREE_STACK_RETURN (REG_EESCAPE);
+
+ /* Do not translate the character after the \, so that we can
+ distinguish, e.g., \B from \b, even if we normally would
+ translate, e.g., B to b. */
+ PATFETCH_RAW (c);
+
+ switch (c)
+ {
+ case '(':
+ if (syntax & RE_NO_BK_PARENS)
+ goto normal_backslash;
+
+ handle_open:
+ bufp->re_nsub++;
+ regnum++;
+
+ if (COMPILE_STACK_FULL)
+ {
+ RETALLOC (compile_stack.stack, compile_stack.size << 1,
+ compile_stack_elt_t);
+ if (compile_stack.stack == NULL) return REG_ESPACE;
+
+ compile_stack.size <<= 1;
+ }
+
+ /* These are the values to restore when we hit end of this
+ group. They are all relative offsets, so that if the
+ whole pattern moves because of realloc, they will still
+ be valid. */
+ COMPILE_STACK_TOP.begalt_offset = begalt - bufp->buffer;
+ COMPILE_STACK_TOP.fixup_alt_jump
+ = fixup_alt_jump ? fixup_alt_jump - bufp->buffer + 1 : 0;
+ COMPILE_STACK_TOP.laststart_offset = b - bufp->buffer;
+ COMPILE_STACK_TOP.regnum = regnum;
+
+ /* We will eventually replace the 0 with the number of
+ groups inner to this one. But do not push a
+ start_memory for groups beyond the last one we can
+ represent in the compiled pattern. */
+ if (regnum <= MAX_REGNUM)
+ {
+ COMPILE_STACK_TOP.inner_group_offset = b - bufp->buffer + 2;
+ BUF_PUSH_3 (start_memory, regnum, 0);
+ }
+
+ compile_stack.avail++;
+
+ fixup_alt_jump = 0;
+ laststart = 0;
+ begalt = b;
+ /* If we've reached MAX_REGNUM groups, then this open
+ won't actually generate any code, so we'll have to
+ clear pending_exact explicitly. */
+ pending_exact = 0;
+ break;
+
+
+ case ')':
+ if (syntax & RE_NO_BK_PARENS) goto normal_backslash;
+
+ if (COMPILE_STACK_EMPTY)
+ {
+ if (syntax & RE_UNMATCHED_RIGHT_PAREN_ORD)
+ goto normal_backslash;
+ else
+ FREE_STACK_RETURN (REG_ERPAREN);
+ }
+
+ handle_close:
+ if (fixup_alt_jump)
+ { /* Push a dummy failure point at the end of the
+ alternative for a possible future
+ `pop_failure_jump' to pop. See comments at
+ `push_dummy_failure' in `re_match_2'. */
+ BUF_PUSH (push_dummy_failure);
+
+ /* We allocated space for this jump when we assigned
+ to `fixup_alt_jump', in the `handle_alt' case below. */
+ STORE_JUMP (jump_past_alt, fixup_alt_jump, b - 1);
+ }
+
+ /* See similar code for backslashed left paren above. */
+ if (COMPILE_STACK_EMPTY)
+ {
+ if (syntax & RE_UNMATCHED_RIGHT_PAREN_ORD)
+ goto normal_char;
+ else
+ FREE_STACK_RETURN (REG_ERPAREN);
+ }
+
+ /* Since we just checked for an empty stack above, this
+ ``can't happen''. */
+ assert (compile_stack.avail != 0);
+ {
+ /* We don't just want to restore into `regnum', because
+ later groups should continue to be numbered higher,
+ as in `(ab)c(de)' -- the second group is #2. */
+ regnum_t this_group_regnum;
+
+ compile_stack.avail--;
+ begalt = bufp->buffer + COMPILE_STACK_TOP.begalt_offset;
+ fixup_alt_jump
+ = COMPILE_STACK_TOP.fixup_alt_jump
+ ? bufp->buffer + COMPILE_STACK_TOP.fixup_alt_jump - 1
+ : 0;
+ laststart = bufp->buffer + COMPILE_STACK_TOP.laststart_offset;
+ this_group_regnum = COMPILE_STACK_TOP.regnum;
+ /* If we've reached MAX_REGNUM groups, then this open
+ won't actually generate any code, so we'll have to
+ clear pending_exact explicitly. */
+ pending_exact = 0;
+
+ /* We're at the end of the group, so now we know how many
+ groups were inside this one. */
+ if (this_group_regnum <= MAX_REGNUM)
+ {
+ unsigned char *inner_group_loc
+ = bufp->buffer + COMPILE_STACK_TOP.inner_group_offset;
+
+ *inner_group_loc = regnum - this_group_regnum;
+ BUF_PUSH_3 (stop_memory, this_group_regnum,
+ regnum - this_group_regnum);
+ }
+ }
+ break;
+
+
+ case '|': /* `\|'. */
+ if (syntax & RE_LIMITED_OPS || syntax & RE_NO_BK_VBAR)
+ goto normal_backslash;
+ handle_alt:
+ if (syntax & RE_LIMITED_OPS)
+ goto normal_char;
+
+ /* Insert before the previous alternative a jump which
+ jumps to this alternative if the former fails. */
+ GET_BUFFER_SPACE (3);
+ INSERT_JUMP (on_failure_jump, begalt, b + 6);
+ pending_exact = 0;
+ b += 3;
+
+ /* The alternative before this one has a jump after it
+ which gets executed if it gets matched. Adjust that
+ jump so it will jump to this alternative's analogous
+ jump (put in below, which in turn will jump to the next
+ (if any) alternative's such jump, etc.). The last such
+ jump jumps to the correct final destination. A picture:
+ _____ _____
+ | | | |
+ | v | v
+ a | b | c
+
+ If we are at `b', then fixup_alt_jump right now points to a
+ three-byte space after `a'. We'll put in the jump, set
+ fixup_alt_jump to right after `b', and leave behind three
+ bytes which we'll fill in when we get to after `c'. */
+
+ if (fixup_alt_jump)
+ STORE_JUMP (jump_past_alt, fixup_alt_jump, b);
+
+ /* Mark and leave space for a jump after this alternative,
+ to be filled in later either by next alternative or
+ when know we're at the end of a series of alternatives. */
+ fixup_alt_jump = b;
+ GET_BUFFER_SPACE (3);
+ b += 3;
+
+ laststart = 0;
+ begalt = b;
+ break;
+
+
+ case '{':
+ /* If \{ is a literal. */
+ if (!(syntax & RE_INTERVALS)
+ /* If we're at `\{' and it's not the open-interval
+ operator. */
+ || ((syntax & RE_INTERVALS) && (syntax & RE_NO_BK_BRACES))
+ || (p - 2 == pattern && p == pend))
+ goto normal_backslash;
+
+ handle_interval:
+ {
+ /* If got here, then the syntax allows intervals. */
+
+ /* At least (most) this many matches must be made. */
+ int lower_bound = -1, upper_bound = -1;
+
+ beg_interval = p - 1;
+
+ if (p == pend)
+ {
+ if (syntax & RE_NO_BK_BRACES)
+ goto unfetch_interval;
+ else
+ FREE_STACK_RETURN (REG_EBRACE);
+ }
+
+ GET_UNSIGNED_NUMBER (lower_bound);
+
+ if (c == ',')
+ {
+ GET_UNSIGNED_NUMBER (upper_bound);
+ if (upper_bound < 0) upper_bound = RE_DUP_MAX;
+ }
+ else
+ /* Interval such as `{1}' => match exactly once. */
+ upper_bound = lower_bound;
+
+ if (lower_bound < 0 || upper_bound > RE_DUP_MAX
+ || lower_bound > upper_bound)
+ {
+ if (syntax & RE_NO_BK_BRACES)
+ goto unfetch_interval;
+ else
+ FREE_STACK_RETURN (REG_BADBR);
+ }
+
+ if (!(syntax & RE_NO_BK_BRACES))
+ {
+ if (c != '\\') FREE_STACK_RETURN (REG_EBRACE);
+
+ PATFETCH (c);
+ }
+
+ if (c != '}')
+ {
+ if (syntax & RE_NO_BK_BRACES)
+ goto unfetch_interval;
+ else
+ FREE_STACK_RETURN (REG_BADBR);
+ }
+
+ /* We just parsed a valid interval. */
+
+ /* If it's invalid to have no preceding re. */
+ if (!laststart)
+ {
+ if (syntax & RE_CONTEXT_INVALID_OPS)
+ FREE_STACK_RETURN (REG_BADRPT);
+ else if (syntax & RE_CONTEXT_INDEP_OPS)
+ laststart = b;
+ else
+ goto unfetch_interval;
+ }
+
+ /* If the upper bound is zero, don't want to succeed at
+ all; jump from `laststart' to `b + 3', which will be
+ the end of the buffer after we insert the jump. */
+ if (upper_bound == 0)
+ {
+ GET_BUFFER_SPACE (3);
+ INSERT_JUMP (jump, laststart, b + 3);
+ b += 3;
+ }
+
+ /* Otherwise, we have a nontrivial interval. When
+ we're all done, the pattern will look like:
+ set_number_at <jump count> <upper bound>
+ set_number_at <succeed_n count> <lower bound>
+ succeed_n <after jump addr> <succeed_n count>
+ <body of loop>
+ jump_n <succeed_n addr> <jump count>
+ (The upper bound and `jump_n' are omitted if
+ `upper_bound' is 1, though.) */
+ else
+ { /* If the upper bound is > 1, we need to insert
+ more at the end of the loop. */
+ unsigned nbytes = 10 + (upper_bound > 1) * 10;
+
+ GET_BUFFER_SPACE (nbytes);
+
+ /* Initialize lower bound of the `succeed_n', even
+ though it will be set during matching by its
+ attendant `set_number_at' (inserted next),
+ because `re_compile_fastmap' needs to know.
+ Jump to the `jump_n' we might insert below. */
+ INSERT_JUMP2 (succeed_n, laststart,
+ b + 5 + (upper_bound > 1) * 5,
+ lower_bound);
+ b += 5;
+
+ /* Code to initialize the lower bound. Insert
+ before the `succeed_n'. The `5' is the last two
+ bytes of this `set_number_at', plus 3 bytes of
+ the following `succeed_n'. */
+ insert_op2 (set_number_at, laststart, 5, lower_bound, b);
+ b += 5;
+
+ if (upper_bound > 1)
+ { /* More than one repetition is allowed, so
+ append a backward jump to the `succeed_n'
+ that starts this interval.
+
+ When we've reached this during matching,
+ we'll have matched the interval once, so
+ jump back only `upper_bound - 1' times. */
+ STORE_JUMP2 (jump_n, b, laststart + 5,
+ upper_bound - 1);
+ b += 5;
+
+ /* The location we want to set is the second
+ parameter of the `jump_n'; that is `b-2' as
+ an absolute address. `laststart' will be
+ the `set_number_at' we're about to insert;
+ `laststart+3' the number to set, the source
+ for the relative address. But we are
+ inserting into the middle of the pattern --
+ so everything is getting moved up by 5.
+ Conclusion: (b - 2) - (laststart + 3) + 5,
+ i.e., b - laststart.
+
+ We insert this at the beginning of the loop
+ so that if we fail during matching, we'll
+ reinitialize the bounds. */
+ insert_op2 (set_number_at, laststart, b - laststart,
+ upper_bound - 1, b);
+ b += 5;
+ }
+ }
+ pending_exact = 0;
+ beg_interval = NULL;
+ }
+ break;
+
+ unfetch_interval:
+ /* If an invalid interval, match the characters as literals. */
+ assert (beg_interval);
+ p = beg_interval;
+ beg_interval = NULL;
+
+ /* normal_char and normal_backslash need `c'. */
+ PATFETCH (c);
+
+ if (!(syntax & RE_NO_BK_BRACES))
+ {
+ if (p > pattern && p[-1] == '\\')
+ goto normal_backslash;
+ }
+ goto normal_char;
+
+#ifdef emacs
+ /* There is no way to specify the before_dot and after_dot
+ operators. rms says this is ok. --karl */
+ case '=':
+ BUF_PUSH (at_dot);
+ break;
+
+ case 's':
+ laststart = b;
+ PATFETCH (c);
+ BUF_PUSH_2 (syntaxspec, syntax_spec_code[c]);
+ break;
+
+ case 'S':
+ laststart = b;
+ PATFETCH (c);
+ BUF_PUSH_2 (notsyntaxspec, syntax_spec_code[c]);
+ break;
+#endif /* emacs */
+
+
+ case 'w':
+ if (syntax & RE_NO_GNU_OPS)
+ goto normal_char;
+ laststart = b;
+ BUF_PUSH (wordchar);
+ break;
+
+
+ case 'W':
+ if (syntax & RE_NO_GNU_OPS)
+ goto normal_char;
+ laststart = b;
+ BUF_PUSH (notwordchar);
+ break;
+
+
+ case '<':
+ if (syntax & RE_NO_GNU_OPS)
+ goto normal_char;
+ BUF_PUSH (wordbeg);
+ break;
+
+ case '>':
+ if (syntax & RE_NO_GNU_OPS)
+ goto normal_char;
+ BUF_PUSH (wordend);
+ break;
+
+ case 'b':
+ if (syntax & RE_NO_GNU_OPS)
+ goto normal_char;
+ BUF_PUSH (wordbound);
+ break;
+
+ case 'B':
+ if (syntax & RE_NO_GNU_OPS)
+ goto normal_char;
+ BUF_PUSH (notwordbound);
+ break;
+
+ case '`':
+ if (syntax & RE_NO_GNU_OPS)
+ goto normal_char;
+ BUF_PUSH (begbuf);
+ break;
+
+ case '\'':
+ if (syntax & RE_NO_GNU_OPS)
+ goto normal_char;
+ BUF_PUSH (endbuf);
+ break;
+
+ case '1': case '2': case '3': case '4': case '5':
+ case '6': case '7': case '8': case '9':
+ if (syntax & RE_NO_BK_REFS)
+ goto normal_char;
+
+ c1 = c - '0';
+
+ if (c1 > regnum)
+ FREE_STACK_RETURN (REG_ESUBREG);
+
+ /* Can't back reference to a subexpression if inside of it. */
+ if (group_in_compile_stack (compile_stack, (regnum_t) c1))
+ goto normal_char;
+
+ laststart = b;
+ BUF_PUSH_2 (duplicate, c1);
+ break;
+
+
+ case '+':
+ case '?':
+ if (syntax & RE_BK_PLUS_QM)
+ goto handle_plus;
+ else
+ goto normal_backslash;
+
+ default:
+ normal_backslash:
+ /* You might think it would be useful for \ to mean
+ not to translate; but if we don't translate it
+ it will never match anything. */
+ c = TRANSLATE (c);
+ goto normal_char;
+ }
+ break;
+
+
+ default:
+ /* Expects the character in `c'. */
+ normal_char:
+ /* If no exactn currently being built. */
+ if (!pending_exact
+
+ /* If last exactn not at current position. */
+ || pending_exact + *pending_exact + 1 != b
+
+ /* We have only one byte following the exactn for the count. */
+ || *pending_exact == (1 << BYTEWIDTH) - 1
+
+ /* If followed by a repetition operator. */
+ || *p == '*' || *p == '^'
+ || ((syntax & RE_BK_PLUS_QM)
+ ? *p == '\\' && (p[1] == '+' || p[1] == '?')
+ : (*p == '+' || *p == '?'))
+ || ((syntax & RE_INTERVALS)
+ && ((syntax & RE_NO_BK_BRACES)
+ ? *p == '{'
+ : (p[0] == '\\' && p[1] == '{'))))
+ {
+ /* Start building a new exactn. */
+
+ laststart = b;
+
+ BUF_PUSH_2 (exactn, 0);
+ pending_exact = b - 1;
+ }
+
+ BUF_PUSH (c);
+ (*pending_exact)++;
+ break;
+ } /* switch (c) */
+ } /* while p != pend */
+
+
+ /* Through the pattern now. */
+
+ if (fixup_alt_jump)
+ STORE_JUMP (jump_past_alt, fixup_alt_jump, b);
+
+ if (!COMPILE_STACK_EMPTY)
+ FREE_STACK_RETURN (REG_EPAREN);
+
+ /* If we don't want backtracking, force success
+ the first time we reach the end of the compiled pattern. */
+ if (syntax & RE_NO_POSIX_BACKTRACKING)
+ BUF_PUSH (succeed);
+
+ free (compile_stack.stack);
+
+ /* We have succeeded; set the length of the buffer. */
+ bufp->used = b - bufp->buffer;
+
+#ifdef DEBUG
+ if (debug)
+ {
+ DEBUG_PRINT1 ("\nCompiled pattern: \n");
+ print_compiled_pattern (bufp);
+ }
+#endif /* DEBUG */
+
+#ifndef MATCH_MAY_ALLOCATE
+ /* Initialize the failure stack to the largest possible stack. This
+ isn't necessary unless we're trying to avoid calling alloca in
+ the search and match routines. */
+ {
+ int num_regs = bufp->re_nsub + 1;
+
+ /* Since DOUBLE_FAIL_STACK refuses to double only if the current size
+ is strictly greater than re_max_failures, the largest possible stack
+ is 2 * re_max_failures failure points. */
+ if (fail_stack.size < (2 * re_max_failures * MAX_FAILURE_ITEMS))
+ {
+ fail_stack.size = (2 * re_max_failures * MAX_FAILURE_ITEMS);
+
+# ifdef emacs
+ if (! fail_stack.stack)
+ fail_stack.stack
+ = (fail_stack_elt_t *) xmalloc (fail_stack.size
+ * sizeof (fail_stack_elt_t));
+ else
+ fail_stack.stack
+ = (fail_stack_elt_t *) xrealloc (fail_stack.stack,
+ (fail_stack.size
+ * sizeof (fail_stack_elt_t)));
+# else /* not emacs */
+ if (! fail_stack.stack)
+ fail_stack.stack
+ = (fail_stack_elt_t *) malloc (fail_stack.size
+ * sizeof (fail_stack_elt_t));
+ else
+ fail_stack.stack
+ = (fail_stack_elt_t *) realloc (fail_stack.stack,
+ (fail_stack.size
+ * sizeof (fail_stack_elt_t)));
+# endif /* not emacs */
+ }
+
+ regex_grow_registers (num_regs);
+ }
+#endif /* not MATCH_MAY_ALLOCATE */
+
+ return REG_NOERROR;
+} /* regex_compile */
+
+/* Subroutines for `regex_compile'. */
+
+/* Store OP at LOC followed by two-byte integer parameter ARG. */
+
+static void
+store_op1 (op, loc, arg)
+ re_opcode_t op;
+ unsigned char *loc;
+ int arg;
+{
+ *loc = (unsigned char) op;
+ STORE_NUMBER (loc + 1, arg);
+}
+
+
+/* Like `store_op1', but for two two-byte parameters ARG1 and ARG2. */
+
+static void
+store_op2 (op, loc, arg1, arg2)
+ re_opcode_t op;
+ unsigned char *loc;
+ int arg1, arg2;
+{
+ *loc = (unsigned char) op;
+ STORE_NUMBER (loc + 1, arg1);
+ STORE_NUMBER (loc + 3, arg2);
+}
+
+
+/* Copy the bytes from LOC to END to open up three bytes of space at LOC
+ for OP followed by two-byte integer parameter ARG. */
+
+static void
+insert_op1 (op, loc, arg, end)
+ re_opcode_t op;
+ unsigned char *loc;
+ int arg;
+ unsigned char *end;
+{
+ register unsigned char *pfrom = end;
+ register unsigned char *pto = end + 3;
+
+ while (pfrom != loc)
+ *--pto = *--pfrom;
+
+ store_op1 (op, loc, arg);
+}
+
+
+/* Like `insert_op1', but for two two-byte parameters ARG1 and ARG2. */
+
+static void
+insert_op2 (op, loc, arg1, arg2, end)
+ re_opcode_t op;
+ unsigned char *loc;
+ int arg1, arg2;
+ unsigned char *end;
+{
+ register unsigned char *pfrom = end;
+ register unsigned char *pto = end + 5;
+
+ while (pfrom != loc)
+ *--pto = *--pfrom;
+
+ store_op2 (op, loc, arg1, arg2);
+}
+
+
+/* P points to just after a ^ in PATTERN. Return true if that ^ comes
+ after an alternative or a begin-subexpression. We assume there is at
+ least one character before the ^. */
+
+static boolean
+at_begline_loc_p (pattern, p, syntax)
+ const char *pattern, *p;
+ reg_syntax_t syntax;
+{
+ const char *prev = p - 2;
+ boolean prev_prev_backslash = prev > pattern && prev[-1] == '\\';
+
+ return
+ /* After a subexpression? */
+ (*prev == '(' && (syntax & RE_NO_BK_PARENS || prev_prev_backslash))
+ /* After an alternative? */
+ || (*prev == '|' && (syntax & RE_NO_BK_VBAR || prev_prev_backslash));
+}
+
+
+/* The dual of at_begline_loc_p. This one is for $. We assume there is
+ at least one character after the $, i.e., `P < PEND'. */
+
+static boolean
+at_endline_loc_p (p, pend, syntax)
+ const char *p, *pend;
+ reg_syntax_t syntax;
+{
+ const char *next = p;
+ boolean next_backslash = *next == '\\';
+ const char *next_next = p + 1 < pend ? p + 1 : 0;
+
+ return
+ /* Before a subexpression? */
+ (syntax & RE_NO_BK_PARENS ? *next == ')'
+ : next_backslash && next_next && *next_next == ')')
+ /* Before an alternative? */
+ || (syntax & RE_NO_BK_VBAR ? *next == '|'
+ : next_backslash && next_next && *next_next == '|');
+}
+
+
+/* Returns true if REGNUM is in one of COMPILE_STACK's elements and
+ false if it's not. */
+
+static boolean
+group_in_compile_stack (compile_stack, regnum)
+ compile_stack_type compile_stack;
+ regnum_t regnum;
+{
+ int this_element;
+
+ for (this_element = compile_stack.avail - 1;
+ this_element >= 0;
+ this_element--)
+ if (compile_stack.stack[this_element].regnum == regnum)
+ return true;
+
+ return false;
+}
+
+
+/* Read the ending character of a range (in a bracket expression) from the
+ uncompiled pattern *P_PTR (which ends at PEND). We assume the
+ starting character is in `P[-2]'. (`P[-1]' is the character `-'.)
+ Then we set the translation of all bits between the starting and
+ ending characters (inclusive) in the compiled pattern B.
+
+ Return an error code.
+
+ We use these short variable names so we can use the same macros as
+ `regex_compile' itself. */
+
+static reg_errcode_t
+compile_range (p_ptr, pend, translate, syntax, b)
+ const char **p_ptr, *pend;
+ RE_TRANSLATE_TYPE translate;
+ reg_syntax_t syntax;
+ unsigned char *b;
+{
+ unsigned this_char;
+
+ const char *p = *p_ptr;
+ unsigned int range_start, range_end;
+
+ if (p == pend)
+ return REG_ERANGE;
+
+ /* Even though the pattern is a signed `char *', we need to fetch
+ with unsigned char *'s; if the high bit of the pattern character
+ is set, the range endpoints will be negative if we fetch using a
+ signed char *.
+
+ We also want to fetch the endpoints without translating them; the
+ appropriate translation is done in the bit-setting loop below. */
+ /* The SVR4 compiler on the 3B2 had trouble with unsigned const char *. */
+ range_start = ((const unsigned char *) p)[-2];
+ range_end = ((const unsigned char *) p)[0];
+
+ /* Have to increment the pointer into the pattern string, so the
+ caller isn't still at the ending character. */
+ (*p_ptr)++;
+
+ /* If the start is after the end, the range is empty. */
+ if (range_start > range_end)
+ return syntax & RE_NO_EMPTY_RANGES ? REG_ERANGE : REG_NOERROR;
+
+ /* Here we see why `this_char' has to be larger than an `unsigned
+ char' -- the range is inclusive, so if `range_end' == 0xff
+ (assuming 8-bit characters), we would otherwise go into an infinite
+ loop, since all characters <= 0xff. */
+ for (this_char = range_start; this_char <= range_end; this_char++)
+ {
+ SET_LIST_BIT (TRANSLATE (this_char));
+ }
+
+ return REG_NOERROR;
+}
+
+/* re_compile_fastmap computes a ``fastmap'' for the compiled pattern in
+ BUFP. A fastmap records which of the (1 << BYTEWIDTH) possible
+ characters can start a string that matches the pattern. This fastmap
+ is used by re_search to skip quickly over impossible starting points.
+
+ The caller must supply the address of a (1 << BYTEWIDTH)-byte data
+ area as BUFP->fastmap.
+
+ We set the `fastmap', `fastmap_accurate', and `can_be_null' fields in
+ the pattern buffer.
+
+ Returns 0 if we succeed, -2 if an internal error. */
+
+int
+re_compile_fastmap (bufp)
+ struct re_pattern_buffer *bufp;
+{
+ int j, k;
+#ifdef MATCH_MAY_ALLOCATE
+ fail_stack_type fail_stack;
+#endif
+#ifndef REGEX_MALLOC
+ char *destination;
+#endif
+
+ register char *fastmap = bufp->fastmap;
+ unsigned char *pattern = bufp->buffer;
+ unsigned char *p = pattern;
+ register unsigned char *pend = pattern + bufp->used;
+
+#ifdef REL_ALLOC
+ /* This holds the pointer to the failure stack, when
+ it is allocated relocatably. */
+ fail_stack_elt_t *failure_stack_ptr;
+#endif
+
+ /* Assume that each path through the pattern can be null until
+ proven otherwise. We set this false at the bottom of switch
+ statement, to which we get only if a particular path doesn't
+ match the empty string. */
+ boolean path_can_be_null = true;
+
+ /* We aren't doing a `succeed_n' to begin with. */
+ boolean succeed_n_p = false;
+
+ assert (fastmap != NULL && p != NULL);
+
+ INIT_FAIL_STACK ();
+ bzero (fastmap, 1 << BYTEWIDTH); /* Assume nothing's valid. */
+ bufp->fastmap_accurate = 1; /* It will be when we're done. */
+ bufp->can_be_null = 0;
+
+ while (1)
+ {
+ if (p == pend || *p == succeed)
+ {
+ /* We have reached the (effective) end of pattern. */
+ if (!FAIL_STACK_EMPTY ())
+ {
+ bufp->can_be_null |= path_can_be_null;
+
+ /* Reset for next path. */
+ path_can_be_null = true;
+
+ p = fail_stack.stack[--fail_stack.avail].pointer;
+
+ continue;
+ }
+ else
+ break;
+ }
+
+ /* We should never be about to go beyond the end of the pattern. */
+ assert (p < pend);
+
+ switch (SWITCH_ENUM_CAST ((re_opcode_t) *p++))
+ {
+
+ /* I guess the idea here is to simply not bother with a fastmap
+ if a backreference is used, since it's too hard to figure out
+ the fastmap for the corresponding group. Setting
+ `can_be_null' stops `re_search_2' from using the fastmap, so
+ that is all we do. */
+ case duplicate:
+ bufp->can_be_null = 1;
+ goto done;
+
+
+ /* Following are the cases which match a character. These end
+ with `break'. */
+
+ case exactn:
+ fastmap[p[1]] = 1;
+ break;
+
+
+ case charset:
+ for (j = *p++ * BYTEWIDTH - 1; j >= 0; j--)
+ if (p[j / BYTEWIDTH] & (1 << (j % BYTEWIDTH)))
+ fastmap[j] = 1;
+ break;
+
+
+ case charset_not:
+ /* Chars beyond end of map must be allowed. */
+ for (j = *p * BYTEWIDTH; j < (1 << BYTEWIDTH); j++)
+ fastmap[j] = 1;
+
+ for (j = *p++ * BYTEWIDTH - 1; j >= 0; j--)
+ if (!(p[j / BYTEWIDTH] & (1 << (j % BYTEWIDTH))))
+ fastmap[j] = 1;
+ break;
+
+
+ case wordchar:
+ for (j = 0; j < (1 << BYTEWIDTH); j++)
+ if (SYNTAX (j) == Sword)
+ fastmap[j] = 1;
+ break;
+
+
+ case notwordchar:
+ for (j = 0; j < (1 << BYTEWIDTH); j++)
+ if (SYNTAX (j) != Sword)
+ fastmap[j] = 1;
+ break;
+
+
+ case anychar:
+ {
+ int fastmap_newline = fastmap['\n'];
+
+ /* `.' matches anything ... */
+ for (j = 0; j < (1 << BYTEWIDTH); j++)
+ fastmap[j] = 1;
+
+ /* ... except perhaps newline. */
+ if (!(bufp->syntax & RE_DOT_NEWLINE))
+ fastmap['\n'] = fastmap_newline;
+
+ /* Return if we have already set `can_be_null'; if we have,
+ then the fastmap is irrelevant. Something's wrong here. */
+ else if (bufp->can_be_null)
+ goto done;
+
+ /* Otherwise, have to check alternative paths. */
+ break;
+ }
+
+#ifdef emacs
+ case syntaxspec:
+ k = *p++;
+ for (j = 0; j < (1 << BYTEWIDTH); j++)
+ if (SYNTAX (j) == (enum syntaxcode) k)
+ fastmap[j] = 1;
+ break;
+
+
+ case notsyntaxspec:
+ k = *p++;
+ for (j = 0; j < (1 << BYTEWIDTH); j++)
+ if (SYNTAX (j) != (enum syntaxcode) k)
+ fastmap[j] = 1;
+ break;
+
+
+ /* All cases after this match the empty string. These end with
+ `continue'. */
+
+
+ case before_dot:
+ case at_dot:
+ case after_dot:
+ continue;
+#endif /* emacs */
+
+
+ case no_op:
+ case begline:
+ case endline:
+ case begbuf:
+ case endbuf:
+ case wordbound:
+ case notwordbound:
+ case wordbeg:
+ case wordend:
+ case push_dummy_failure:
+ continue;
+
+
+ case jump_n:
+ case pop_failure_jump:
+ case maybe_pop_jump:
+ case jump:
+ case jump_past_alt:
+ case dummy_failure_jump:
+ EXTRACT_NUMBER_AND_INCR (j, p);
+ p += j;
+ if (j > 0)
+ continue;
+
+ /* Jump backward implies we just went through the body of a
+ loop and matched nothing. Opcode jumped to should be
+ `on_failure_jump' or `succeed_n'. Just treat it like an
+ ordinary jump. For a * loop, it has pushed its failure
+ point already; if so, discard that as redundant. */
+ if ((re_opcode_t) *p != on_failure_jump
+ && (re_opcode_t) *p != succeed_n)
+ continue;
+
+ p++;
+ EXTRACT_NUMBER_AND_INCR (j, p);
+ p += j;
+
+ /* If what's on the stack is where we are now, pop it. */
+ if (!FAIL_STACK_EMPTY ()
+ && fail_stack.stack[fail_stack.avail - 1].pointer == p)
+ fail_stack.avail--;
+
+ continue;
+
+
+ case on_failure_jump:
+ case on_failure_keep_string_jump:
+ handle_on_failure_jump:
+ EXTRACT_NUMBER_AND_INCR (j, p);
+
+ /* For some patterns, e.g., `(a?)?', `p+j' here points to the
+ end of the pattern. We don't want to push such a point,
+ since when we restore it above, entering the switch will
+ increment `p' past the end of the pattern. We don't need
+ to push such a point since we obviously won't find any more
+ fastmap entries beyond `pend'. Such a pattern can match
+ the null string, though. */
+ if (p + j < pend)
+ {
+ if (!PUSH_PATTERN_OP (p + j, fail_stack))
+ {
+ RESET_FAIL_STACK ();
+ return -2;
+ }
+ }
+ else
+ bufp->can_be_null = 1;
+
+ if (succeed_n_p)
+ {
+ EXTRACT_NUMBER_AND_INCR (k, p); /* Skip the n. */
+ succeed_n_p = false;
+ }
+
+ continue;
+
+
+ case succeed_n:
+ /* Get to the number of times to succeed. */
+ p += 2;
+
+ /* Increment p past the n for when k != 0. */
+ EXTRACT_NUMBER_AND_INCR (k, p);
+ if (k == 0)
+ {
+ p -= 4;
+ succeed_n_p = true; /* Spaghetti code alert. */
+ goto handle_on_failure_jump;
+ }
+ continue;
+
+
+ case set_number_at:
+ p += 4;
+ continue;
+
+
+ case start_memory:
+ case stop_memory:
+ p += 2;
+ continue;
+
+
+ default:
+ abort (); /* We have listed all the cases. */
+ } /* switch *p++ */
+
+ /* Getting here means we have found the possible starting
+ characters for one path of the pattern -- and that the empty
+ string does not match. We need not follow this path further.
+ Instead, look at the next alternative (remembered on the
+ stack), or quit if no more. The test at the top of the loop
+ does these things. */
+ path_can_be_null = false;
+ p = pend;
+ } /* while p */
+
+ /* Set `can_be_null' for the last path (also the first path, if the
+ pattern is empty). */
+ bufp->can_be_null |= path_can_be_null;
+
+ done:
+ RESET_FAIL_STACK ();
+ return 0;
+} /* re_compile_fastmap */
+#ifdef _LIBC
+weak_alias (__re_compile_fastmap, re_compile_fastmap)
+#endif
+
+/* Set REGS to hold NUM_REGS registers, storing them in STARTS and
+ ENDS. Subsequent matches using PATTERN_BUFFER and REGS will use
+ this memory for recording register information. STARTS and ENDS
+ must be allocated using the malloc library routine, and must each
+ be at least NUM_REGS * sizeof (regoff_t) bytes long.
+
+ If NUM_REGS == 0, then subsequent matches should allocate their own
+ register data.
+
+ Unless this function is called, the first search or match using
+ PATTERN_BUFFER will allocate its own register data, without
+ freeing the old data. */
+
+void
+re_set_registers (bufp, regs, num_regs, starts, ends)
+ struct re_pattern_buffer *bufp;
+ struct re_registers *regs;
+ unsigned num_regs;
+ regoff_t *starts, *ends;
+{
+ if (num_regs)
+ {
+ bufp->regs_allocated = REGS_REALLOCATE;
+ regs->num_regs = num_regs;
+ regs->start = starts;
+ regs->end = ends;
+ }
+ else
+ {
+ bufp->regs_allocated = REGS_UNALLOCATED;
+ regs->num_regs = 0;
+ regs->start = regs->end = (regoff_t *) 0;
+ }
+}
+#ifdef _LIBC
+weak_alias (__re_set_registers, re_set_registers)
+#endif
+
+/* Searching routines. */
+
+/* Like re_search_2, below, but only one string is specified, and
+ doesn't let you say where to stop matching. */
+
+int
+re_search (bufp, string, size, startpos, range, regs)
+ struct re_pattern_buffer *bufp;
+ const char *string;
+ int size, startpos, range;
+ struct re_registers *regs;
+{
+ return re_search_2 (bufp, NULL, 0, string, size, startpos, range,
+ regs, size);
+}
+#ifdef _LIBC
+weak_alias (__re_search, re_search)
+#endif
+
+
+/* Using the compiled pattern in BUFP->buffer, first tries to match the
+ virtual concatenation of STRING1 and STRING2, starting first at index
+ STARTPOS, then at STARTPOS + 1, and so on.
+
+ STRING1 and STRING2 have length SIZE1 and SIZE2, respectively.
+
+ RANGE is how far to scan while trying to match. RANGE = 0 means try
+ only at STARTPOS; in general, the last start tried is STARTPOS +
+ RANGE.
+
+ In REGS, return the indices of the virtual concatenation of STRING1
+ and STRING2 that matched the entire BUFP->buffer and its contained
+ subexpressions.
+
+ Do not consider matching one past the index STOP in the virtual
+ concatenation of STRING1 and STRING2.
+
+ We return either the position in the strings at which the match was
+ found, -1 if no match, or -2 if error (such as failure
+ stack overflow). */
+
+int
+re_search_2 (bufp, string1, size1, string2, size2, startpos, range, regs, stop)
+ struct re_pattern_buffer *bufp;
+ const char *string1, *string2;
+ int size1, size2;
+ int startpos;
+ int range;
+ struct re_registers *regs;
+ int stop;
+{
+ int val;
+ register char *fastmap = bufp->fastmap;
+ register RE_TRANSLATE_TYPE translate = bufp->translate;
+ int total_size = size1 + size2;
+ int endpos = startpos + range;
+
+ /* Check for out-of-range STARTPOS. */
+ if (startpos < 0 || startpos > total_size)
+ return -1;
+
+ /* Fix up RANGE if it might eventually take us outside
+ the virtual concatenation of STRING1 and STRING2.
+ Make sure we won't move STARTPOS below 0 or above TOTAL_SIZE. */
+ if (endpos < 0)
+ range = 0 - startpos;
+ else if (endpos > total_size)
+ range = total_size - startpos;
+
+ /* If the search isn't to be a backwards one, don't waste time in a
+ search for a pattern that must be anchored. */
+ if (bufp->used > 0 && (re_opcode_t) bufp->buffer[0] == begbuf && range > 0)
+ {
+ if (startpos > 0)
+ return -1;
+ else
+ range = 1;
+ }
+
+#ifdef emacs
+ /* In a forward search for something that starts with \=.
+ don't keep searching past point. */
+ if (bufp->used > 0 && (re_opcode_t) bufp->buffer[0] == at_dot && range > 0)
+ {
+ range = PT - startpos;
+ if (range <= 0)
+ return -1;
+ }
+#endif /* emacs */
+
+ /* Update the fastmap now if not correct already. */
+ if (fastmap && !bufp->fastmap_accurate)
+ if (re_compile_fastmap (bufp) == -2)
+ return -2;
+
+ /* Loop through the string, looking for a place to start matching. */
+ for (;;)
+ {
+ /* If a fastmap is supplied, skip quickly over characters that
+ cannot be the start of a match. If the pattern can match the
+ null string, however, we don't need to skip characters; we want
+ the first null string. */
+ if (fastmap && startpos < total_size && !bufp->can_be_null)
+ {
+ if (range > 0) /* Searching forwards. */
+ {
+ register const char *d;
+ register int lim = 0;
+ int irange = range;
+
+ if (startpos < size1 && startpos + range >= size1)
+ lim = range - (size1 - startpos);
+
+ d = (startpos >= size1 ? string2 - size1 : string1) + startpos;
+
+ /* Written out as an if-else to avoid testing `translate'
+ inside the loop. */
+ if (translate)
+ while (range > lim
+ && !fastmap[(unsigned char)
+ translate[(unsigned char) *d++]])
+ range--;
+ else
+ while (range > lim && !fastmap[(unsigned char) *d++])
+ range--;
+
+ startpos += irange - range;
+ }
+ else /* Searching backwards. */
+ {
+ register char c = (size1 == 0 || startpos >= size1
+ ? string2[startpos - size1]
+ : string1[startpos]);
+
+ if (!fastmap[(unsigned char) TRANSLATE (c)])
+ goto advance;
+ }
+ }
+
+ /* If can't match the null string, and that's all we have left, fail. */
+ if (range >= 0 && startpos == total_size && fastmap
+ && !bufp->can_be_null)
+ return -1;
+
+ val = re_match_2_internal (bufp, string1, size1, string2, size2,
+ startpos, regs, stop);
+#ifndef REGEX_MALLOC
+# ifdef C_ALLOCA
+ alloca (0);
+# endif
+#endif
+
+ if (val >= 0)
+ return startpos;
+
+ if (val == -2)
+ return -2;
+
+ advance:
+ if (!range)
+ break;
+ else if (range > 0)
+ {
+ range--;
+ startpos++;
+ }
+ else
+ {
+ range++;
+ startpos--;
+ }
+ }
+ return -1;
+} /* re_search_2 */
+#ifdef _LIBC
+weak_alias (__re_search_2, re_search_2)
+#endif
+
+/* This converts PTR, a pointer into one of the search strings `string1'
+ and `string2' into an offset from the beginning of that string. */
+#define POINTER_TO_OFFSET(ptr) \
+ (FIRST_STRING_P (ptr) \
+ ? ((regoff_t) ((ptr) - string1)) \
+ : ((regoff_t) ((ptr) - string2 + size1)))
+
+/* Macros for dealing with the split strings in re_match_2. */
+
+#define MATCHING_IN_FIRST_STRING (dend == end_match_1)
+
+/* Call before fetching a character with *d. This switches over to
+ string2 if necessary. */
+#define PREFETCH() \
+ while (d == dend) \
+ { \
+ /* End of string2 => fail. */ \
+ if (dend == end_match_2) \
+ goto fail; \
+ /* End of string1 => advance to string2. */ \
+ d = string2; \
+ dend = end_match_2; \
+ }
+
+
+/* Test if at very beginning or at very end of the virtual concatenation
+ of `string1' and `string2'. If only one string, it's `string2'. */
+#define AT_STRINGS_BEG(d) ((d) == (size1 ? string1 : string2) || !size2)
+#define AT_STRINGS_END(d) ((d) == end2)
+
+
+/* Test if D points to a character which is word-constituent. We have
+ two special cases to check for: if past the end of string1, look at
+ the first character in string2; and if before the beginning of
+ string2, look at the last character in string1. */
+#define WORDCHAR_P(d) \
+ (SYNTAX ((d) == end1 ? *string2 \
+ : (d) == string2 - 1 ? *(end1 - 1) : *(d)) \
+ == Sword)
+
+/* Disabled due to a compiler bug -- see comment at case wordbound */
+#if 0
+/* Test if the character before D and the one at D differ with respect
+ to being word-constituent. */
+#define AT_WORD_BOUNDARY(d) \
+ (AT_STRINGS_BEG (d) || AT_STRINGS_END (d) \
+ || WORDCHAR_P (d - 1) != WORDCHAR_P (d))
+#endif
+
+/* Free everything we malloc. */
+#ifdef MATCH_MAY_ALLOCATE
+# define FREE_VAR(var) if (var) REGEX_FREE (var); var = NULL
+# define FREE_VARIABLES() \
+ do { \
+ REGEX_FREE_STACK (fail_stack.stack); \
+ FREE_VAR (regstart); \
+ FREE_VAR (regend); \
+ FREE_VAR (old_regstart); \
+ FREE_VAR (old_regend); \
+ FREE_VAR (best_regstart); \
+ FREE_VAR (best_regend); \
+ FREE_VAR (reg_info); \
+ FREE_VAR (reg_dummy); \
+ FREE_VAR (reg_info_dummy); \
+ } while (0)
+#else
+# define FREE_VARIABLES() ((void)0) /* Do nothing! But inhibit gcc warning. */
+#endif /* not MATCH_MAY_ALLOCATE */
+
+/* These values must meet several constraints. They must not be valid
+ register values; since we have a limit of 255 registers (because
+ we use only one byte in the pattern for the register number), we can
+ use numbers larger than 255. They must differ by 1, because of
+ NUM_FAILURE_ITEMS above. And the value for the lowest register must
+ be larger than the value for the highest register, so we do not try
+ to actually save any registers when none are active. */
+#define NO_HIGHEST_ACTIVE_REG (1 << BYTEWIDTH)
+#define NO_LOWEST_ACTIVE_REG (NO_HIGHEST_ACTIVE_REG + 1)
+
+/* Matching routines. */
+
+#ifndef emacs /* Emacs never uses this. */
+/* re_match is like re_match_2 except it takes only a single string. */
+
+int
+re_match (bufp, string, size, pos, regs)
+ struct re_pattern_buffer *bufp;
+ const char *string;
+ int size, pos;
+ struct re_registers *regs;
+{
+ int result = re_match_2_internal (bufp, NULL, 0, string, size,
+ pos, regs, size);
+# ifndef REGEX_MALLOC
+# ifdef C_ALLOCA
+ alloca (0);
+# endif
+# endif
+ return result;
+}
+# ifdef _LIBC
+weak_alias (__re_match, re_match)
+# endif
+#endif /* not emacs */
+
+static boolean group_match_null_string_p _RE_ARGS ((unsigned char **p,
+ unsigned char *end,
+ register_info_type *reg_info));
+static boolean alt_match_null_string_p _RE_ARGS ((unsigned char *p,
+ unsigned char *end,
+ register_info_type *reg_info));
+static boolean common_op_match_null_string_p _RE_ARGS ((unsigned char **p,
+ unsigned char *end,
+ register_info_type *reg_info));
+static int bcmp_translate _RE_ARGS ((const char *s1, const char *s2,
+ int len, char *translate));
+
+/* re_match_2 matches the compiled pattern in BUFP against the
+ the (virtual) concatenation of STRING1 and STRING2 (of length SIZE1
+ and SIZE2, respectively). We start matching at POS, and stop
+ matching at STOP.
+
+ If REGS is non-null and the `no_sub' field of BUFP is nonzero, we
+ store offsets for the substring each group matched in REGS. See the
+ documentation for exactly how many groups we fill.
+
+ We return -1 if no match, -2 if an internal error (such as the
+ failure stack overflowing). Otherwise, we return the length of the
+ matched substring. */
+
+int
+re_match_2 (bufp, string1, size1, string2, size2, pos, regs, stop)
+ struct re_pattern_buffer *bufp;
+ const char *string1, *string2;
+ int size1, size2;
+ int pos;
+ struct re_registers *regs;
+ int stop;
+{
+ int result = re_match_2_internal (bufp, string1, size1, string2, size2,
+ pos, regs, stop);
+#ifndef REGEX_MALLOC
+# ifdef C_ALLOCA
+ alloca (0);
+# endif
+#endif
+ return result;
+}
+#ifdef _LIBC
+weak_alias (__re_match_2, re_match_2)
+#endif
+
+/* This is a separate function so that we can force an alloca cleanup
+ afterwards. */
+static int
+re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop)
+ struct re_pattern_buffer *bufp;
+ const char *string1, *string2;
+ int size1, size2;
+ int pos;
+ struct re_registers *regs;
+ int stop;
+{
+ /* General temporaries. */
+ int mcnt;
+ unsigned char *p1;
+
+ /* Just past the end of the corresponding string. */
+ const char *end1, *end2;
+
+ /* Pointers into string1 and string2, just past the last characters in
+ each to consider matching. */
+ const char *end_match_1, *end_match_2;
+
+ /* Where we are in the data, and the end of the current string. */
+ const char *d, *dend;
+
+ /* Where we are in the pattern, and the end of the pattern. */
+ unsigned char *p = bufp->buffer;
+ register unsigned char *pend = p + bufp->used;
+
+ /* Mark the opcode just after a start_memory, so we can test for an
+ empty subpattern when we get to the stop_memory. */
+ unsigned char *just_past_start_mem = 0;
+
+ /* We use this to map every character in the string. */
+ RE_TRANSLATE_TYPE translate = bufp->translate;
+
+ /* Failure point stack. Each place that can handle a failure further
+ down the line pushes a failure point on this stack. It consists of
+ restart, regend, and reg_info for all registers corresponding to
+ the subexpressions we're currently inside, plus the number of such
+ registers, and, finally, two char *'s. The first char * is where
+ to resume scanning the pattern; the second one is where to resume
+ scanning the strings. If the latter is zero, the failure point is
+ a ``dummy''; if a failure happens and the failure point is a dummy,
+ it gets discarded and the next next one is tried. */
+#ifdef MATCH_MAY_ALLOCATE /* otherwise, this is global. */
+ fail_stack_type fail_stack;
+#endif
+#ifdef DEBUG
+ static unsigned failure_id = 0;
+ unsigned nfailure_points_pushed = 0, nfailure_points_popped = 0;
+#endif
+
+#ifdef REL_ALLOC
+ /* This holds the pointer to the failure stack, when
+ it is allocated relocatably. */
+ fail_stack_elt_t *failure_stack_ptr;
+#endif
+
+ /* We fill all the registers internally, independent of what we
+ return, for use in backreferences. The number here includes
+ an element for register zero. */
+ size_t num_regs = bufp->re_nsub + 1;
+
+ /* The currently active registers. */
+ active_reg_t lowest_active_reg = NO_LOWEST_ACTIVE_REG;
+ active_reg_t highest_active_reg = NO_HIGHEST_ACTIVE_REG;
+
+ /* Information on the contents of registers. These are pointers into
+ the input strings; they record just what was matched (on this
+ attempt) by a subexpression part of the pattern, that is, the
+ regnum-th regstart pointer points to where in the pattern we began
+ matching and the regnum-th regend points to right after where we
+ stopped matching the regnum-th subexpression. (The zeroth register
+ keeps track of what the whole pattern matches.) */
+#ifdef MATCH_MAY_ALLOCATE /* otherwise, these are global. */
+ const char **regstart, **regend;
+#endif
+
+ /* If a group that's operated upon by a repetition operator fails to
+ match anything, then the register for its start will need to be
+ restored because it will have been set to wherever in the string we
+ are when we last see its open-group operator. Similarly for a
+ register's end. */
+#ifdef MATCH_MAY_ALLOCATE /* otherwise, these are global. */
+ const char **old_regstart, **old_regend;
+#endif
+
+ /* The is_active field of reg_info helps us keep track of which (possibly
+ nested) subexpressions we are currently in. The matched_something
+ field of reg_info[reg_num] helps us tell whether or not we have
+ matched any of the pattern so far this time through the reg_num-th
+ subexpression. These two fields get reset each time through any
+ loop their register is in. */
+#ifdef MATCH_MAY_ALLOCATE /* otherwise, this is global. */
+ register_info_type *reg_info;
+#endif
+
+ /* The following record the register info as found in the above
+ variables when we find a match better than any we've seen before.
+ This happens as we backtrack through the failure points, which in
+ turn happens only if we have not yet matched the entire string. */
+ unsigned best_regs_set = false;
+#ifdef MATCH_MAY_ALLOCATE /* otherwise, these are global. */
+ const char **best_regstart, **best_regend;
+#endif
+
+ /* Logically, this is `best_regend[0]'. But we don't want to have to
+ allocate space for that if we're not allocating space for anything
+ else (see below). Also, we never need info about register 0 for
+ any of the other register vectors, and it seems rather a kludge to
+ treat `best_regend' differently than the rest. So we keep track of
+ the end of the best match so far in a separate variable. We
+ initialize this to NULL so that when we backtrack the first time
+ and need to test it, it's not garbage. */
+ const char *match_end = NULL;
+
+ /* This helps SET_REGS_MATCHED avoid doing redundant work. */
+ int set_regs_matched_done = 0;
+
+ /* Used when we pop values we don't care about. */
+#ifdef MATCH_MAY_ALLOCATE /* otherwise, these are global. */
+ const char **reg_dummy;
+ register_info_type *reg_info_dummy;
+#endif
+
+#ifdef DEBUG
+ /* Counts the total number of registers pushed. */
+ unsigned num_regs_pushed = 0;
+#endif
+
+ DEBUG_PRINT1 ("\n\nEntering re_match_2.\n");
+
+ INIT_FAIL_STACK ();
+
+#ifdef MATCH_MAY_ALLOCATE
+ /* Do not bother to initialize all the register variables if there are
+ no groups in the pattern, as it takes a fair amount of time. If
+ there are groups, we include space for register 0 (the whole
+ pattern), even though we never use it, since it simplifies the
+ array indexing. We should fix this. */
+ if (bufp->re_nsub)
+ {
+ regstart = REGEX_TALLOC (num_regs, const char *);
+ regend = REGEX_TALLOC (num_regs, const char *);
+ old_regstart = REGEX_TALLOC (num_regs, const char *);
+ old_regend = REGEX_TALLOC (num_regs, const char *);
+ best_regstart = REGEX_TALLOC (num_regs, const char *);
+ best_regend = REGEX_TALLOC (num_regs, const char *);
+ reg_info = REGEX_TALLOC (num_regs, register_info_type);
+ reg_dummy = REGEX_TALLOC (num_regs, const char *);
+ reg_info_dummy = REGEX_TALLOC (num_regs, register_info_type);
+
+ if (!(regstart && regend && old_regstart && old_regend && reg_info
+ && best_regstart && best_regend && reg_dummy && reg_info_dummy))
+ {
+ FREE_VARIABLES ();
+ return -2;
+ }
+ }
+ else
+ {
+ /* We must initialize all our variables to NULL, so that
+ `FREE_VARIABLES' doesn't try to free them. */
+ regstart = regend = old_regstart = old_regend = best_regstart
+ = best_regend = reg_dummy = NULL;
+ reg_info = reg_info_dummy = (register_info_type *) NULL;
+ }
+#endif /* MATCH_MAY_ALLOCATE */
+
+ /* The starting position is bogus. */
+ if (pos < 0 || pos > size1 + size2)
+ {
+ FREE_VARIABLES ();
+ return -1;
+ }
+
+ /* Initialize subexpression text positions to -1 to mark ones that no
+ start_memory/stop_memory has been seen for. Also initialize the
+ register information struct. */
+ for (mcnt = 1; (unsigned) mcnt < num_regs; mcnt++)
+ {
+ regstart[mcnt] = regend[mcnt]
+ = old_regstart[mcnt] = old_regend[mcnt] = REG_UNSET_VALUE;
+
+ REG_MATCH_NULL_STRING_P (reg_info[mcnt]) = MATCH_NULL_UNSET_VALUE;
+ IS_ACTIVE (reg_info[mcnt]) = 0;
+ MATCHED_SOMETHING (reg_info[mcnt]) = 0;
+ EVER_MATCHED_SOMETHING (reg_info[mcnt]) = 0;
+ }
+
+ /* We move `string1' into `string2' if the latter's empty -- but not if
+ `string1' is null. */
+ if (size2 == 0 && string1 != NULL)
+ {
+ string2 = string1;
+ size2 = size1;
+ string1 = 0;
+ size1 = 0;
+ }
+ end1 = string1 + size1;
+ end2 = string2 + size2;
+
+ /* Compute where to stop matching, within the two strings. */
+ if (stop <= size1)
+ {
+ end_match_1 = string1 + stop;
+ end_match_2 = string2;
+ }
+ else
+ {
+ end_match_1 = end1;
+ end_match_2 = string2 + stop - size1;
+ }
+
+ /* `p' scans through the pattern as `d' scans through the data.
+ `dend' is the end of the input string that `d' points within. `d'
+ is advanced into the following input string whenever necessary, but
+ this happens before fetching; therefore, at the beginning of the
+ loop, `d' can be pointing at the end of a string, but it cannot
+ equal `string2'. */
+ if (size1 > 0 && pos <= size1)
+ {
+ d = string1 + pos;
+ dend = end_match_1;
+ }
+ else
+ {
+ d = string2 + pos - size1;
+ dend = end_match_2;
+ }
+
+ DEBUG_PRINT1 ("The compiled pattern is:\n");
+ DEBUG_PRINT_COMPILED_PATTERN (bufp, p, pend);
+ DEBUG_PRINT1 ("The string to match is: `");
+ DEBUG_PRINT_DOUBLE_STRING (d, string1, size1, string2, size2);
+ DEBUG_PRINT1 ("'\n");
+
+ /* This loops over pattern commands. It exits by returning from the
+ function if the match is complete, or it drops through if the match
+ fails at this starting point in the input data. */
+ for (;;)
+ {
+#ifdef _LIBC
+ DEBUG_PRINT2 ("\n%p: ", p);
+#else
+ DEBUG_PRINT2 ("\n0x%x: ", p);
+#endif
+
+ if (p == pend)
+ { /* End of pattern means we might have succeeded. */
+ DEBUG_PRINT1 ("end of pattern ... ");
+
+ /* If we haven't matched the entire string, and we want the
+ longest match, try backtracking. */
+ if (d != end_match_2)
+ {
+ /* 1 if this match ends in the same string (string1 or string2)
+ as the best previous match. */
+ boolean same_str_p = (FIRST_STRING_P (match_end)
+ == MATCHING_IN_FIRST_STRING);
+ /* 1 if this match is the best seen so far. */
+ boolean best_match_p;
+
+ /* AIX compiler got confused when this was combined
+ with the previous declaration. */
+ if (same_str_p)
+ best_match_p = d > match_end;
+ else
+ best_match_p = !MATCHING_IN_FIRST_STRING;
+
+ DEBUG_PRINT1 ("backtracking.\n");
+
+ if (!FAIL_STACK_EMPTY ())
+ { /* More failure points to try. */
+
+ /* If exceeds best match so far, save it. */
+ if (!best_regs_set || best_match_p)
+ {
+ best_regs_set = true;
+ match_end = d;
+
+ DEBUG_PRINT1 ("\nSAVING match as best so far.\n");
+
+ for (mcnt = 1; (unsigned) mcnt < num_regs; mcnt++)
+ {
+ best_regstart[mcnt] = regstart[mcnt];
+ best_regend[mcnt] = regend[mcnt];
+ }
+ }
+ goto fail;
+ }
+
+ /* If no failure points, don't restore garbage. And if
+ last match is real best match, don't restore second
+ best one. */
+ else if (best_regs_set && !best_match_p)
+ {
+ restore_best_regs:
+ /* Restore best match. It may happen that `dend ==
+ end_match_1' while the restored d is in string2.
+ For example, the pattern `x.*y.*z' against the
+ strings `x-' and `y-z-', if the two strings are
+ not consecutive in memory. */
+ DEBUG_PRINT1 ("Restoring best registers.\n");
+
+ d = match_end;
+ dend = ((d >= string1 && d <= end1)
+ ? end_match_1 : end_match_2);
+
+ for (mcnt = 1; (unsigned) mcnt < num_regs; mcnt++)
+ {
+ regstart[mcnt] = best_regstart[mcnt];
+ regend[mcnt] = best_regend[mcnt];
+ }
+ }
+ } /* d != end_match_2 */
+
+ succeed_label:
+ DEBUG_PRINT1 ("Accepting match.\n");
+
+ /* If caller wants register contents data back, do it. */
+ if (regs && !bufp->no_sub)
+ {
+ /* Have the register data arrays been allocated? */
+ if (bufp->regs_allocated == REGS_UNALLOCATED)
+ { /* No. So allocate them with malloc. We need one
+ extra element beyond `num_regs' for the `-1' marker
+ GNU code uses. */
+ regs->num_regs = MAX (RE_NREGS, num_regs + 1);
+ regs->start = TALLOC (regs->num_regs, regoff_t);
+ regs->end = TALLOC (regs->num_regs, regoff_t);
+ if (regs->start == NULL || regs->end == NULL)
+ {
+ FREE_VARIABLES ();
+ return -2;
+ }
+ bufp->regs_allocated = REGS_REALLOCATE;
+ }
+ else if (bufp->regs_allocated == REGS_REALLOCATE)
+ { /* Yes. If we need more elements than were already
+ allocated, reallocate them. If we need fewer, just
+ leave it alone. */
+ if (regs->num_regs < num_regs + 1)
+ {
+ regs->num_regs = num_regs + 1;
+ RETALLOC (regs->start, regs->num_regs, regoff_t);
+ RETALLOC (regs->end, regs->num_regs, regoff_t);
+ if (regs->start == NULL || regs->end == NULL)
+ {
+ FREE_VARIABLES ();
+ return -2;
+ }
+ }
+ }
+ else
+ {
+ /* These braces fend off a "empty body in an else-statement"
+ warning under GCC when assert expands to nothing. */
+ assert (bufp->regs_allocated == REGS_FIXED);
+ }
+
+ /* Convert the pointer data in `regstart' and `regend' to
+ indices. Register zero has to be set differently,
+ since we haven't kept track of any info for it. */
+ if (regs->num_regs > 0)
+ {
+ regs->start[0] = pos;
+ regs->end[0] = (MATCHING_IN_FIRST_STRING
+ ? ((regoff_t) (d - string1))
+ : ((regoff_t) (d - string2 + size1)));
+ }
+
+ /* Go through the first `min (num_regs, regs->num_regs)'
+ registers, since that is all we initialized. */
+ for (mcnt = 1; (unsigned) mcnt < MIN (num_regs, regs->num_regs);
+ mcnt++)
+ {
+ if (REG_UNSET (regstart[mcnt]) || REG_UNSET (regend[mcnt]))
+ regs->start[mcnt] = regs->end[mcnt] = -1;
+ else
+ {
+ regs->start[mcnt]
+ = (regoff_t) POINTER_TO_OFFSET (regstart[mcnt]);
+ regs->end[mcnt]
+ = (regoff_t) POINTER_TO_OFFSET (regend[mcnt]);
+ }
+ }
+
+ /* If the regs structure we return has more elements than
+ were in the pattern, set the extra elements to -1. If
+ we (re)allocated the registers, this is the case,
+ because we always allocate enough to have at least one
+ -1 at the end. */
+ for (mcnt = num_regs; (unsigned) mcnt < regs->num_regs; mcnt++)
+ regs->start[mcnt] = regs->end[mcnt] = -1;
+ } /* regs && !bufp->no_sub */
+
+ DEBUG_PRINT4 ("%u failure points pushed, %u popped (%u remain).\n",
+ nfailure_points_pushed, nfailure_points_popped,
+ nfailure_points_pushed - nfailure_points_popped);
+ DEBUG_PRINT2 ("%u registers pushed.\n", num_regs_pushed);
+
+ mcnt = d - pos - (MATCHING_IN_FIRST_STRING
+ ? string1
+ : string2 - size1);
+
+ DEBUG_PRINT2 ("Returning %d from re_match_2.\n", mcnt);
+
+ FREE_VARIABLES ();
+ return mcnt;
+ }
+
+ /* Otherwise match next pattern command. */
+ switch (SWITCH_ENUM_CAST ((re_opcode_t) *p++))
+ {
+ /* Ignore these. Used to ignore the n of succeed_n's which
+ currently have n == 0. */
+ case no_op:
+ DEBUG_PRINT1 ("EXECUTING no_op.\n");
+ break;
+
+ case succeed:
+ DEBUG_PRINT1 ("EXECUTING succeed.\n");
+ goto succeed_label;
+
+ /* Match the next n pattern characters exactly. The following
+ byte in the pattern defines n, and the n bytes after that
+ are the characters to match. */
+ case exactn:
+ mcnt = *p++;
+ DEBUG_PRINT2 ("EXECUTING exactn %d.\n", mcnt);
+
+ /* This is written out as an if-else so we don't waste time
+ testing `translate' inside the loop. */
+ if (translate)
+ {
+ do
+ {
+ PREFETCH ();
+ if ((unsigned char) translate[(unsigned char) *d++]
+ != (unsigned char) *p++)
+ goto fail;
+ }
+ while (--mcnt);
+ }
+ else
+ {
+ do
+ {
+ PREFETCH ();
+ if (*d++ != (char) *p++) goto fail;
+ }
+ while (--mcnt);
+ }
+ SET_REGS_MATCHED ();
+ break;
+
+
+ /* Match any character except possibly a newline or a null. */
+ case anychar:
+ DEBUG_PRINT1 ("EXECUTING anychar.\n");
+
+ PREFETCH ();
+
+ if ((!(bufp->syntax & RE_DOT_NEWLINE) && TRANSLATE (*d) == '\n')
+ || (bufp->syntax & RE_DOT_NOT_NULL && TRANSLATE (*d) == '\000'))
+ goto fail;
+
+ SET_REGS_MATCHED ();
+ DEBUG_PRINT2 (" Matched `%d'.\n", *d);
+ d++;
+ break;
+
+
+ case charset:
+ case charset_not:
+ {
+ register unsigned char c;
+ boolean not = (re_opcode_t) *(p - 1) == charset_not;
+
+ DEBUG_PRINT2 ("EXECUTING charset%s.\n", not ? "_not" : "");
+
+ PREFETCH ();
+ c = TRANSLATE (*d); /* The character to match. */
+
+ /* Cast to `unsigned' instead of `unsigned char' in case the
+ bit list is a full 32 bytes long. */
+ if (c < (unsigned) (*p * BYTEWIDTH)
+ && p[1 + c / BYTEWIDTH] & (1 << (c % BYTEWIDTH)))
+ not = !not;
+
+ p += 1 + *p;
+
+ if (!not) goto fail;
+
+ SET_REGS_MATCHED ();
+ d++;
+ break;
+ }
+
+
+ /* The beginning of a group is represented by start_memory.
+ The arguments are the register number in the next byte, and the
+ number of groups inner to this one in the next. The text
+ matched within the group is recorded (in the internal
+ registers data structure) under the register number. */
+ case start_memory:
+ DEBUG_PRINT3 ("EXECUTING start_memory %d (%d):\n", *p, p[1]);
+
+ /* Find out if this group can match the empty string. */
+ p1 = p; /* To send to group_match_null_string_p. */
+
+ if (REG_MATCH_NULL_STRING_P (reg_info[*p]) == MATCH_NULL_UNSET_VALUE)
+ REG_MATCH_NULL_STRING_P (reg_info[*p])
+ = group_match_null_string_p (&p1, pend, reg_info);
+
+ /* Save the position in the string where we were the last time
+ we were at this open-group operator in case the group is
+ operated upon by a repetition operator, e.g., with `(a*)*b'
+ against `ab'; then we want to ignore where we are now in
+ the string in case this attempt to match fails. */
+ old_regstart[*p] = REG_MATCH_NULL_STRING_P (reg_info[*p])
+ ? REG_UNSET (regstart[*p]) ? d : regstart[*p]
+ : regstart[*p];
+ DEBUG_PRINT2 (" old_regstart: %d\n",
+ POINTER_TO_OFFSET (old_regstart[*p]));
+
+ regstart[*p] = d;
+ DEBUG_PRINT2 (" regstart: %d\n", POINTER_TO_OFFSET (regstart[*p]));
+
+ IS_ACTIVE (reg_info[*p]) = 1;
+ MATCHED_SOMETHING (reg_info[*p]) = 0;
+
+ /* Clear this whenever we change the register activity status. */
+ set_regs_matched_done = 0;
+
+ /* This is the new highest active register. */
+ highest_active_reg = *p;
+
+ /* If nothing was active before, this is the new lowest active
+ register. */
+ if (lowest_active_reg == NO_LOWEST_ACTIVE_REG)
+ lowest_active_reg = *p;
+
+ /* Move past the register number and inner group count. */
+ p += 2;
+ just_past_start_mem = p;
+
+ break;
+
+
+ /* The stop_memory opcode represents the end of a group. Its
+ arguments are the same as start_memory's: the register
+ number, and the number of inner groups. */
+ case stop_memory:
+ DEBUG_PRINT3 ("EXECUTING stop_memory %d (%d):\n", *p, p[1]);
+
+ /* We need to save the string position the last time we were at
+ this close-group operator in case the group is operated
+ upon by a repetition operator, e.g., with `((a*)*(b*)*)*'
+ against `aba'; then we want to ignore where we are now in
+ the string in case this attempt to match fails. */
+ old_regend[*p] = REG_MATCH_NULL_STRING_P (reg_info[*p])
+ ? REG_UNSET (regend[*p]) ? d : regend[*p]
+ : regend[*p];
+ DEBUG_PRINT2 (" old_regend: %d\n",
+ POINTER_TO_OFFSET (old_regend[*p]));
+
+ regend[*p] = d;
+ DEBUG_PRINT2 (" regend: %d\n", POINTER_TO_OFFSET (regend[*p]));
+
+ /* This register isn't active anymore. */
+ IS_ACTIVE (reg_info[*p]) = 0;
+
+ /* Clear this whenever we change the register activity status. */
+ set_regs_matched_done = 0;
+
+ /* If this was the only register active, nothing is active
+ anymore. */
+ if (lowest_active_reg == highest_active_reg)
+ {
+ lowest_active_reg = NO_LOWEST_ACTIVE_REG;
+ highest_active_reg = NO_HIGHEST_ACTIVE_REG;
+ }
+ else
+ { /* We must scan for the new highest active register, since
+ it isn't necessarily one less than now: consider
+ (a(b)c(d(e)f)g). When group 3 ends, after the f), the
+ new highest active register is 1. */
+ unsigned char r = *p - 1;
+ while (r > 0 && !IS_ACTIVE (reg_info[r]))
+ r--;
+
+ /* If we end up at register zero, that means that we saved
+ the registers as the result of an `on_failure_jump', not
+ a `start_memory', and we jumped to past the innermost
+ `stop_memory'. For example, in ((.)*) we save
+ registers 1 and 2 as a result of the *, but when we pop
+ back to the second ), we are at the stop_memory 1.
+ Thus, nothing is active. */
+ if (r == 0)
+ {
+ lowest_active_reg = NO_LOWEST_ACTIVE_REG;
+ highest_active_reg = NO_HIGHEST_ACTIVE_REG;
+ }
+ else
+ highest_active_reg = r;
+ }
+
+ /* If just failed to match something this time around with a
+ group that's operated on by a repetition operator, try to
+ force exit from the ``loop'', and restore the register
+ information for this group that we had before trying this
+ last match. */
+ if ((!MATCHED_SOMETHING (reg_info[*p])
+ || just_past_start_mem == p - 1)
+ && (p + 2) < pend)
+ {
+ boolean is_a_jump_n = false;
+
+ p1 = p + 2;
+ mcnt = 0;
+ switch ((re_opcode_t) *p1++)
+ {
+ case jump_n:
+ is_a_jump_n = true;
+ case pop_failure_jump:
+ case maybe_pop_jump:
+ case jump:
+ case dummy_failure_jump:
+ EXTRACT_NUMBER_AND_INCR (mcnt, p1);
+ if (is_a_jump_n)
+ p1 += 2;
+ break;
+
+ default:
+ /* do nothing */ ;
+ }
+ p1 += mcnt;
+
+ /* If the next operation is a jump backwards in the pattern
+ to an on_failure_jump right before the start_memory
+ corresponding to this stop_memory, exit from the loop
+ by forcing a failure after pushing on the stack the
+ on_failure_jump's jump in the pattern, and d. */
+ if (mcnt < 0 && (re_opcode_t) *p1 == on_failure_jump
+ && (re_opcode_t) p1[3] == start_memory && p1[4] == *p)
+ {
+ /* If this group ever matched anything, then restore
+ what its registers were before trying this last
+ failed match, e.g., with `(a*)*b' against `ab' for
+ regstart[1], and, e.g., with `((a*)*(b*)*)*'
+ against `aba' for regend[3].
+
+ Also restore the registers for inner groups for,
+ e.g., `((a*)(b*))*' against `aba' (register 3 would
+ otherwise get trashed). */
+
+ if (EVER_MATCHED_SOMETHING (reg_info[*p]))
+ {
+ unsigned r;
+
+ EVER_MATCHED_SOMETHING (reg_info[*p]) = 0;
+
+ /* Restore this and inner groups' (if any) registers. */
+ for (r = *p; r < (unsigned) *p + (unsigned) *(p + 1);
+ r++)
+ {
+ regstart[r] = old_regstart[r];
+
+ /* xx why this test? */
+ if (old_regend[r] >= regstart[r])
+ regend[r] = old_regend[r];
+ }
+ }
+ p1++;
+ EXTRACT_NUMBER_AND_INCR (mcnt, p1);
+ PUSH_FAILURE_POINT (p1 + mcnt, d, -2);
+
+ goto fail;
+ }
+ }
+
+ /* Move past the register number and the inner group count. */
+ p += 2;
+ break;
+
+
+ /* \<digit> has been turned into a `duplicate' command which is
+ followed by the numeric value of <digit> as the register number. */
+ case duplicate:
+ {
+ register const char *d2, *dend2;
+ int regno = *p++; /* Get which register to match against. */
+ DEBUG_PRINT2 ("EXECUTING duplicate %d.\n", regno);
+
+ /* Can't back reference a group which we've never matched. */
+ if (REG_UNSET (regstart[regno]) || REG_UNSET (regend[regno]))
+ goto fail;
+
+ /* Where in input to try to start matching. */
+ d2 = regstart[regno];
+
+ /* Where to stop matching; if both the place to start and
+ the place to stop matching are in the same string, then
+ set to the place to stop, otherwise, for now have to use
+ the end of the first string. */
+
+ dend2 = ((FIRST_STRING_P (regstart[regno])
+ == FIRST_STRING_P (regend[regno]))
+ ? regend[regno] : end_match_1);
+ for (;;)
+ {
+ /* If necessary, advance to next segment in register
+ contents. */
+ while (d2 == dend2)
+ {
+ if (dend2 == end_match_2) break;
+ if (dend2 == regend[regno]) break;
+
+ /* End of string1 => advance to string2. */
+ d2 = string2;
+ dend2 = regend[regno];
+ }
+ /* At end of register contents => success */
+ if (d2 == dend2) break;
+
+ /* If necessary, advance to next segment in data. */
+ PREFETCH ();
+
+ /* How many characters left in this segment to match. */
+ mcnt = dend - d;
+
+ /* Want how many consecutive characters we can match in
+ one shot, so, if necessary, adjust the count. */
+ if (mcnt > dend2 - d2)
+ mcnt = dend2 - d2;
+
+ /* Compare that many; failure if mismatch, else move
+ past them. */
+ if (translate
+ ? bcmp_translate (d, d2, mcnt, translate)
+ : memcmp (d, d2, mcnt))
+ goto fail;
+ d += mcnt, d2 += mcnt;
+
+ /* Do this because we've match some characters. */
+ SET_REGS_MATCHED ();
+ }
+ }
+ break;
+
+
+ /* begline matches the empty string at the beginning of the string
+ (unless `not_bol' is set in `bufp'), and, if
+ `newline_anchor' is set, after newlines. */
+ case begline:
+ DEBUG_PRINT1 ("EXECUTING begline.\n");
+
+ if (AT_STRINGS_BEG (d))
+ {
+ if (!bufp->not_bol) break;
+ }
+ else if (d[-1] == '\n' && bufp->newline_anchor)
+ {
+ break;
+ }
+ /* In all other cases, we fail. */
+ goto fail;
+
+
+ /* endline is the dual of begline. */
+ case endline:
+ DEBUG_PRINT1 ("EXECUTING endline.\n");
+
+ if (AT_STRINGS_END (d))
+ {
+ if (!bufp->not_eol) break;
+ }
+
+ /* We have to ``prefetch'' the next character. */
+ else if ((d == end1 ? *string2 : *d) == '\n'
+ && bufp->newline_anchor)
+ {
+ break;
+ }
+ goto fail;
+
+
+ /* Match at the very beginning of the data. */
+ case begbuf:
+ DEBUG_PRINT1 ("EXECUTING begbuf.\n");
+ if (AT_STRINGS_BEG (d))
+ break;
+ goto fail;
+
+
+ /* Match at the very end of the data. */
+ case endbuf:
+ DEBUG_PRINT1 ("EXECUTING endbuf.\n");
+ if (AT_STRINGS_END (d))
+ break;
+ goto fail;
+
+
+ /* on_failure_keep_string_jump is used to optimize `.*\n'. It
+ pushes NULL as the value for the string on the stack. Then
+ `pop_failure_point' will keep the current value for the
+ string, instead of restoring it. To see why, consider
+ matching `foo\nbar' against `.*\n'. The .* matches the foo;
+ then the . fails against the \n. But the next thing we want
+ to do is match the \n against the \n; if we restored the
+ string value, we would be back at the foo.
+
+ Because this is used only in specific cases, we don't need to
+ check all the things that `on_failure_jump' does, to make
+ sure the right things get saved on the stack. Hence we don't
+ share its code. The only reason to push anything on the
+ stack at all is that otherwise we would have to change
+ `anychar's code to do something besides goto fail in this
+ case; that seems worse than this. */
+ case on_failure_keep_string_jump:
+ DEBUG_PRINT1 ("EXECUTING on_failure_keep_string_jump");
+
+ EXTRACT_NUMBER_AND_INCR (mcnt, p);
+#ifdef _LIBC
+ DEBUG_PRINT3 (" %d (to %p):\n", mcnt, p + mcnt);
+#else
+ DEBUG_PRINT3 (" %d (to 0x%x):\n", mcnt, p + mcnt);
+#endif
+
+ PUSH_FAILURE_POINT (p + mcnt, NULL, -2);
+ break;
+
+
+ /* Uses of on_failure_jump:
+
+ Each alternative starts with an on_failure_jump that points
+ to the beginning of the next alternative. Each alternative
+ except the last ends with a jump that in effect jumps past
+ the rest of the alternatives. (They really jump to the
+ ending jump of the following alternative, because tensioning
+ these jumps is a hassle.)
+
+ Repeats start with an on_failure_jump that points past both
+ the repetition text and either the following jump or
+ pop_failure_jump back to this on_failure_jump. */
+ case on_failure_jump:
+ on_failure:
+ DEBUG_PRINT1 ("EXECUTING on_failure_jump");
+
+ EXTRACT_NUMBER_AND_INCR (mcnt, p);
+#ifdef _LIBC
+ DEBUG_PRINT3 (" %d (to %p)", mcnt, p + mcnt);
+#else
+ DEBUG_PRINT3 (" %d (to 0x%x)", mcnt, p + mcnt);
+#endif
+
+ /* If this on_failure_jump comes right before a group (i.e.,
+ the original * applied to a group), save the information
+ for that group and all inner ones, so that if we fail back
+ to this point, the group's information will be correct.
+ For example, in \(a*\)*\1, we need the preceding group,
+ and in \(zz\(a*\)b*\)\2, we need the inner group. */
+
+ /* We can't use `p' to check ahead because we push
+ a failure point to `p + mcnt' after we do this. */
+ p1 = p;
+
+ /* We need to skip no_op's before we look for the
+ start_memory in case this on_failure_jump is happening as
+ the result of a completed succeed_n, as in \(a\)\{1,3\}b\1
+ against aba. */
+ while (p1 < pend && (re_opcode_t) *p1 == no_op)
+ p1++;
+
+ if (p1 < pend && (re_opcode_t) *p1 == start_memory)
+ {
+ /* We have a new highest active register now. This will
+ get reset at the start_memory we are about to get to,
+ but we will have saved all the registers relevant to
+ this repetition op, as described above. */
+ highest_active_reg = *(p1 + 1) + *(p1 + 2);
+ if (lowest_active_reg == NO_LOWEST_ACTIVE_REG)
+ lowest_active_reg = *(p1 + 1);
+ }
+
+ DEBUG_PRINT1 (":\n");
+ PUSH_FAILURE_POINT (p + mcnt, d, -2);
+ break;
+
+
+ /* A smart repeat ends with `maybe_pop_jump'.
+ We change it to either `pop_failure_jump' or `jump'. */
+ case maybe_pop_jump:
+ EXTRACT_NUMBER_AND_INCR (mcnt, p);
+ DEBUG_PRINT2 ("EXECUTING maybe_pop_jump %d.\n", mcnt);
+ {
+ register unsigned char *p2 = p;
+
+ /* Compare the beginning of the repeat with what in the
+ pattern follows its end. If we can establish that there
+ is nothing that they would both match, i.e., that we
+ would have to backtrack because of (as in, e.g., `a*a')
+ then we can change to pop_failure_jump, because we'll
+ never have to backtrack.
+
+ This is not true in the case of alternatives: in
+ `(a|ab)*' we do need to backtrack to the `ab' alternative
+ (e.g., if the string was `ab'). But instead of trying to
+ detect that here, the alternative has put on a dummy
+ failure point which is what we will end up popping. */
+
+ /* Skip over open/close-group commands.
+ If what follows this loop is a ...+ construct,
+ look at what begins its body, since we will have to
+ match at least one of that. */
+ while (1)
+ {
+ if (p2 + 2 < pend
+ && ((re_opcode_t) *p2 == stop_memory
+ || (re_opcode_t) *p2 == start_memory))
+ p2 += 3;
+ else if (p2 + 6 < pend
+ && (re_opcode_t) *p2 == dummy_failure_jump)
+ p2 += 6;
+ else
+ break;
+ }
+
+ p1 = p + mcnt;
+ /* p1[0] ... p1[2] are the `on_failure_jump' corresponding
+ to the `maybe_finalize_jump' of this case. Examine what
+ follows. */
+
+ /* If we're at the end of the pattern, we can change. */
+ if (p2 == pend)
+ {
+ /* Consider what happens when matching ":\(.*\)"
+ against ":/". I don't really understand this code
+ yet. */
+ p[-3] = (unsigned char) pop_failure_jump;
+ DEBUG_PRINT1
+ (" End of pattern: change to `pop_failure_jump'.\n");
+ }
+
+ else if ((re_opcode_t) *p2 == exactn
+ || (bufp->newline_anchor && (re_opcode_t) *p2 == endline))
+ {
+ register unsigned char c
+ = *p2 == (unsigned char) endline ? '\n' : p2[2];
+
+ if ((re_opcode_t) p1[3] == exactn && p1[5] != c)
+ {
+ p[-3] = (unsigned char) pop_failure_jump;
+ DEBUG_PRINT3 (" %c != %c => pop_failure_jump.\n",
+ c, p1[5]);
+ }
+
+ else if ((re_opcode_t) p1[3] == charset
+ || (re_opcode_t) p1[3] == charset_not)
+ {
+ int not = (re_opcode_t) p1[3] == charset_not;
+
+ if (c < (unsigned char) (p1[4] * BYTEWIDTH)
+ && p1[5 + c / BYTEWIDTH] & (1 << (c % BYTEWIDTH)))
+ not = !not;
+
+ /* `not' is equal to 1 if c would match, which means
+ that we can't change to pop_failure_jump. */
+ if (!not)
+ {
+ p[-3] = (unsigned char) pop_failure_jump;
+ DEBUG_PRINT1 (" No match => pop_failure_jump.\n");
+ }
+ }
+ }
+ else if ((re_opcode_t) *p2 == charset)
+ {
+#ifdef DEBUG
+ register unsigned char c
+ = *p2 == (unsigned char) endline ? '\n' : p2[2];
+#endif
+
+#if 0
+ if ((re_opcode_t) p1[3] == exactn
+ && ! ((int) p2[1] * BYTEWIDTH > (int) p1[5]
+ && (p2[2 + p1[5] / BYTEWIDTH]
+ & (1 << (p1[5] % BYTEWIDTH)))))
+#else
+ if ((re_opcode_t) p1[3] == exactn
+ && ! ((int) p2[1] * BYTEWIDTH > (int) p1[4]
+ && (p2[2 + p1[4] / BYTEWIDTH]
+ & (1 << (p1[4] % BYTEWIDTH)))))
+#endif
+ {
+ p[-3] = (unsigned char) pop_failure_jump;
+ DEBUG_PRINT3 (" %c != %c => pop_failure_jump.\n",
+ c, p1[5]);
+ }
+
+ else if ((re_opcode_t) p1[3] == charset_not)
+ {
+ int idx;
+ /* We win if the charset_not inside the loop
+ lists every character listed in the charset after. */
+ for (idx = 0; idx < (int) p2[1]; idx++)
+ if (! (p2[2 + idx] == 0
+ || (idx < (int) p1[4]
+ && ((p2[2 + idx] & ~ p1[5 + idx]) == 0))))
+ break;
+
+ if (idx == p2[1])
+ {
+ p[-3] = (unsigned char) pop_failure_jump;
+ DEBUG_PRINT1 (" No match => pop_failure_jump.\n");
+ }
+ }
+ else if ((re_opcode_t) p1[3] == charset)
+ {
+ int idx;
+ /* We win if the charset inside the loop
+ has no overlap with the one after the loop. */
+ for (idx = 0;
+ idx < (int) p2[1] && idx < (int) p1[4];
+ idx++)
+ if ((p2[2 + idx] & p1[5 + idx]) != 0)
+ break;
+
+ if (idx == p2[1] || idx == p1[4])
+ {
+ p[-3] = (unsigned char) pop_failure_jump;
+ DEBUG_PRINT1 (" No match => pop_failure_jump.\n");
+ }
+ }
+ }
+ }
+ p -= 2; /* Point at relative address again. */
+ if ((re_opcode_t) p[-1] != pop_failure_jump)
+ {
+ p[-1] = (unsigned char) jump;
+ DEBUG_PRINT1 (" Match => jump.\n");
+ goto unconditional_jump;
+ }
+ /* Note fall through. */
+
+
+ /* The end of a simple repeat has a pop_failure_jump back to
+ its matching on_failure_jump, where the latter will push a
+ failure point. The pop_failure_jump takes off failure
+ points put on by this pop_failure_jump's matching
+ on_failure_jump; we got through the pattern to here from the
+ matching on_failure_jump, so didn't fail. */
+ case pop_failure_jump:
+ {
+ /* We need to pass separate storage for the lowest and
+ highest registers, even though we don't care about the
+ actual values. Otherwise, we will restore only one
+ register from the stack, since lowest will == highest in
+ `pop_failure_point'. */
+ active_reg_t dummy_low_reg, dummy_high_reg;
+ unsigned char *pdummy;
+ const char *sdummy;
+
+ DEBUG_PRINT1 ("EXECUTING pop_failure_jump.\n");
+ POP_FAILURE_POINT (sdummy, pdummy,
+ dummy_low_reg, dummy_high_reg,
+ reg_dummy, reg_dummy, reg_info_dummy);
+ }
+ /* Note fall through. */
+
+ unconditional_jump:
+#ifdef _LIBC
+ DEBUG_PRINT2 ("\n%p: ", p);
+#else
+ DEBUG_PRINT2 ("\n0x%x: ", p);
+#endif
+ /* Note fall through. */
+
+ /* Unconditionally jump (without popping any failure points). */
+ case jump:
+ EXTRACT_NUMBER_AND_INCR (mcnt, p); /* Get the amount to jump. */
+ DEBUG_PRINT2 ("EXECUTING jump %d ", mcnt);
+ p += mcnt; /* Do the jump. */
+#ifdef _LIBC
+ DEBUG_PRINT2 ("(to %p).\n", p);
+#else
+ DEBUG_PRINT2 ("(to 0x%x).\n", p);
+#endif
+ break;
+
+
+ /* We need this opcode so we can detect where alternatives end
+ in `group_match_null_string_p' et al. */
+ case jump_past_alt:
+ DEBUG_PRINT1 ("EXECUTING jump_past_alt.\n");
+ goto unconditional_jump;
+
+
+ /* Normally, the on_failure_jump pushes a failure point, which
+ then gets popped at pop_failure_jump. We will end up at
+ pop_failure_jump, also, and with a pattern of, say, `a+', we
+ are skipping over the on_failure_jump, so we have to push
+ something meaningless for pop_failure_jump to pop. */
+ case dummy_failure_jump:
+ DEBUG_PRINT1 ("EXECUTING dummy_failure_jump.\n");
+ /* It doesn't matter what we push for the string here. What
+ the code at `fail' tests is the value for the pattern. */
+ PUSH_FAILURE_POINT (NULL, NULL, -2);
+ goto unconditional_jump;
+
+
+ /* At the end of an alternative, we need to push a dummy failure
+ point in case we are followed by a `pop_failure_jump', because
+ we don't want the failure point for the alternative to be
+ popped. For example, matching `(a|ab)*' against `aab'
+ requires that we match the `ab' alternative. */
+ case push_dummy_failure:
+ DEBUG_PRINT1 ("EXECUTING push_dummy_failure.\n");
+ /* See comments just above at `dummy_failure_jump' about the
+ two zeroes. */
+ PUSH_FAILURE_POINT (NULL, NULL, -2);
+ break;
+
+ /* Have to succeed matching what follows at least n times.
+ After that, handle like `on_failure_jump'. */
+ case succeed_n:
+ EXTRACT_NUMBER (mcnt, p + 2);
+ DEBUG_PRINT2 ("EXECUTING succeed_n %d.\n", mcnt);
+
+ assert (mcnt >= 0);
+ /* Originally, this is how many times we HAVE to succeed. */
+ if (mcnt > 0)
+ {
+ mcnt--;
+ p += 2;
+ STORE_NUMBER_AND_INCR (p, mcnt);
+#ifdef _LIBC
+ DEBUG_PRINT3 (" Setting %p to %d.\n", p - 2, mcnt);
+#else
+ DEBUG_PRINT3 (" Setting 0x%x to %d.\n", p - 2, mcnt);
+#endif
+ }
+ else if (mcnt == 0)
+ {
+#ifdef _LIBC
+ DEBUG_PRINT2 (" Setting two bytes from %p to no_op.\n", p+2);
+#else
+ DEBUG_PRINT2 (" Setting two bytes from 0x%x to no_op.\n", p+2);
+#endif
+ p[2] = (unsigned char) no_op;
+ p[3] = (unsigned char) no_op;
+ goto on_failure;
+ }
+ break;
+
+ case jump_n:
+ EXTRACT_NUMBER (mcnt, p + 2);
+ DEBUG_PRINT2 ("EXECUTING jump_n %d.\n", mcnt);
+
+ /* Originally, this is how many times we CAN jump. */
+ if (mcnt)
+ {
+ mcnt--;
+ STORE_NUMBER (p + 2, mcnt);
+#ifdef _LIBC
+ DEBUG_PRINT3 (" Setting %p to %d.\n", p + 2, mcnt);
+#else
+ DEBUG_PRINT3 (" Setting 0x%x to %d.\n", p + 2, mcnt);
+#endif
+ goto unconditional_jump;
+ }
+ /* If don't have to jump any more, skip over the rest of command. */
+ else
+ p += 4;
+ break;
+
+ case set_number_at:
+ {
+ DEBUG_PRINT1 ("EXECUTING set_number_at.\n");
+
+ EXTRACT_NUMBER_AND_INCR (mcnt, p);
+ p1 = p + mcnt;
+ EXTRACT_NUMBER_AND_INCR (mcnt, p);
+#ifdef _LIBC
+ DEBUG_PRINT3 (" Setting %p to %d.\n", p1, mcnt);
+#else
+ DEBUG_PRINT3 (" Setting 0x%x to %d.\n", p1, mcnt);
+#endif
+ STORE_NUMBER (p1, mcnt);
+ break;
+ }
+
+#if 0
+ /* The DEC Alpha C compiler 3.x generates incorrect code for the
+ test WORDCHAR_P (d - 1) != WORDCHAR_P (d) in the expansion of
+ AT_WORD_BOUNDARY, so this code is disabled. Expanding the
+ macro and introducing temporary variables works around the bug. */
+
+ case wordbound:
+ DEBUG_PRINT1 ("EXECUTING wordbound.\n");
+ if (AT_WORD_BOUNDARY (d))
+ break;
+ goto fail;
+
+ case notwordbound:
+ DEBUG_PRINT1 ("EXECUTING notwordbound.\n");
+ if (AT_WORD_BOUNDARY (d))
+ goto fail;
+ break;
+#else
+ case wordbound:
+ {
+ boolean prevchar, thischar;
+
+ DEBUG_PRINT1 ("EXECUTING wordbound.\n");
+ if (AT_STRINGS_BEG (d) || AT_STRINGS_END (d))
+ break;
+
+ prevchar = WORDCHAR_P (d - 1);
+ thischar = WORDCHAR_P (d);
+ if (prevchar != thischar)
+ break;
+ goto fail;
+ }
+
+ case notwordbound:
+ {
+ boolean prevchar, thischar;
+
+ DEBUG_PRINT1 ("EXECUTING notwordbound.\n");
+ if (AT_STRINGS_BEG (d) || AT_STRINGS_END (d))
+ goto fail;
+
+ prevchar = WORDCHAR_P (d - 1);
+ thischar = WORDCHAR_P (d);
+ if (prevchar != thischar)
+ goto fail;
+ break;
+ }
+#endif
+
+ case wordbeg:
+ DEBUG_PRINT1 ("EXECUTING wordbeg.\n");
+ if (WORDCHAR_P (d) && (AT_STRINGS_BEG (d) || !WORDCHAR_P (d - 1)))
+ break;
+ goto fail;
+
+ case wordend:
+ DEBUG_PRINT1 ("EXECUTING wordend.\n");
+ if (!AT_STRINGS_BEG (d) && WORDCHAR_P (d - 1)
+ && (!WORDCHAR_P (d) || AT_STRINGS_END (d)))
+ break;
+ goto fail;
+
+#ifdef emacs
+ case before_dot:
+ DEBUG_PRINT1 ("EXECUTING before_dot.\n");
+ if (PTR_CHAR_POS ((unsigned char *) d) >= point)
+ goto fail;
+ break;
+
+ case at_dot:
+ DEBUG_PRINT1 ("EXECUTING at_dot.\n");
+ if (PTR_CHAR_POS ((unsigned char *) d) != point)
+ goto fail;
+ break;
+
+ case after_dot:
+ DEBUG_PRINT1 ("EXECUTING after_dot.\n");
+ if (PTR_CHAR_POS ((unsigned char *) d) <= point)
+ goto fail;
+ break;
+
+ case syntaxspec:
+ DEBUG_PRINT2 ("EXECUTING syntaxspec %d.\n", mcnt);
+ mcnt = *p++;
+ goto matchsyntax;
+
+ case wordchar:
+ DEBUG_PRINT1 ("EXECUTING Emacs wordchar.\n");
+ mcnt = (int) Sword;
+ matchsyntax:
+ PREFETCH ();
+ /* Can't use *d++ here; SYNTAX may be an unsafe macro. */
+ d++;
+ if (SYNTAX (d[-1]) != (enum syntaxcode) mcnt)
+ goto fail;
+ SET_REGS_MATCHED ();
+ break;
+
+ case notsyntaxspec:
+ DEBUG_PRINT2 ("EXECUTING notsyntaxspec %d.\n", mcnt);
+ mcnt = *p++;
+ goto matchnotsyntax;
+
+ case notwordchar:
+ DEBUG_PRINT1 ("EXECUTING Emacs notwordchar.\n");
+ mcnt = (int) Sword;
+ matchnotsyntax:
+ PREFETCH ();
+ /* Can't use *d++ here; SYNTAX may be an unsafe macro. */
+ d++;
+ if (SYNTAX (d[-1]) == (enum syntaxcode) mcnt)
+ goto fail;
+ SET_REGS_MATCHED ();
+ break;
+
+#else /* not emacs */
+ case wordchar:
+ DEBUG_PRINT1 ("EXECUTING non-Emacs wordchar.\n");
+ PREFETCH ();
+ if (!WORDCHAR_P (d))
+ goto fail;
+ SET_REGS_MATCHED ();
+ d++;
+ break;
+
+ case notwordchar:
+ DEBUG_PRINT1 ("EXECUTING non-Emacs notwordchar.\n");
+ PREFETCH ();
+ if (WORDCHAR_P (d))
+ goto fail;
+ SET_REGS_MATCHED ();
+ d++;
+ break;
+#endif /* not emacs */
+
+ default:
+ abort ();
+ }
+ continue; /* Successfully executed one pattern command; keep going. */
+
+
+ /* We goto here if a matching operation fails. */
+ fail:
+ if (!FAIL_STACK_EMPTY ())
+ { /* A restart point is known. Restore to that state. */
+ DEBUG_PRINT1 ("\nFAIL:\n");
+ POP_FAILURE_POINT (d, p,
+ lowest_active_reg, highest_active_reg,
+ regstart, regend, reg_info);
+
+ /* If this failure point is a dummy, try the next one. */
+ if (!p)
+ goto fail;
+
+ /* If we failed to the end of the pattern, don't examine *p. */
+ assert (p <= pend);
+ if (p < pend)
+ {
+ boolean is_a_jump_n = false;
+
+ /* If failed to a backwards jump that's part of a repetition
+ loop, need to pop this failure point and use the next one. */
+ switch ((re_opcode_t) *p)
+ {
+ case jump_n:
+ is_a_jump_n = true;
+ case maybe_pop_jump:
+ case pop_failure_jump:
+ case jump:
+ p1 = p + 1;
+ EXTRACT_NUMBER_AND_INCR (mcnt, p1);
+ p1 += mcnt;
+
+ if ((is_a_jump_n && (re_opcode_t) *p1 == succeed_n)
+ || (!is_a_jump_n
+ && (re_opcode_t) *p1 == on_failure_jump))
+ goto fail;
+ break;
+ default:
+ /* do nothing */ ;
+ }
+ }
+
+ if (d >= string1 && d <= end1)
+ dend = end_match_1;
+ }
+ else
+ break; /* Matching at this starting point really fails. */
+ } /* for (;;) */
+
+ if (best_regs_set)
+ goto restore_best_regs;
+
+ FREE_VARIABLES ();
+
+ return -1; /* Failure to match. */
+} /* re_match_2 */
+
+/* Subroutine definitions for re_match_2. */
+
+
+/* We are passed P pointing to a register number after a start_memory.
+
+ Return true if the pattern up to the corresponding stop_memory can
+ match the empty string, and false otherwise.
+
+ If we find the matching stop_memory, sets P to point to one past its number.
+ Otherwise, sets P to an undefined byte less than or equal to END.
+
+ We don't handle duplicates properly (yet). */
+
+static boolean
+group_match_null_string_p (p, end, reg_info)
+ unsigned char **p, *end;
+ register_info_type *reg_info;
+{
+ int mcnt;
+ /* Point to after the args to the start_memory. */
+ unsigned char *p1 = *p + 2;
+
+ while (p1 < end)
+ {
+ /* Skip over opcodes that can match nothing, and return true or
+ false, as appropriate, when we get to one that can't, or to the
+ matching stop_memory. */
+
+ switch ((re_opcode_t) *p1)
+ {
+ /* Could be either a loop or a series of alternatives. */
+ case on_failure_jump:
+ p1++;
+ EXTRACT_NUMBER_AND_INCR (mcnt, p1);
+
+ /* If the next operation is not a jump backwards in the
+ pattern. */
+
+ if (mcnt >= 0)
+ {
+ /* Go through the on_failure_jumps of the alternatives,
+ seeing if any of the alternatives cannot match nothing.
+ The last alternative starts with only a jump,
+ whereas the rest start with on_failure_jump and end
+ with a jump, e.g., here is the pattern for `a|b|c':
+
+ /on_failure_jump/0/6/exactn/1/a/jump_past_alt/0/6
+ /on_failure_jump/0/6/exactn/1/b/jump_past_alt/0/3
+ /exactn/1/c
+
+ So, we have to first go through the first (n-1)
+ alternatives and then deal with the last one separately. */
+
+
+ /* Deal with the first (n-1) alternatives, which start
+ with an on_failure_jump (see above) that jumps to right
+ past a jump_past_alt. */
+
+ while ((re_opcode_t) p1[mcnt-3] == jump_past_alt)
+ {
+ /* `mcnt' holds how many bytes long the alternative
+ is, including the ending `jump_past_alt' and
+ its number. */
+
+ if (!alt_match_null_string_p (p1, p1 + mcnt - 3,
+ reg_info))
+ return false;
+
+ /* Move to right after this alternative, including the
+ jump_past_alt. */
+ p1 += mcnt;
+
+ /* Break if it's the beginning of an n-th alternative
+ that doesn't begin with an on_failure_jump. */
+ if ((re_opcode_t) *p1 != on_failure_jump)
+ break;
+
+ /* Still have to check that it's not an n-th
+ alternative that starts with an on_failure_jump. */
+ p1++;
+ EXTRACT_NUMBER_AND_INCR (mcnt, p1);
+ if ((re_opcode_t) p1[mcnt-3] != jump_past_alt)
+ {
+ /* Get to the beginning of the n-th alternative. */
+ p1 -= 3;
+ break;
+ }
+ }
+
+ /* Deal with the last alternative: go back and get number
+ of the `jump_past_alt' just before it. `mcnt' contains
+ the length of the alternative. */
+ EXTRACT_NUMBER (mcnt, p1 - 2);
+
+ if (!alt_match_null_string_p (p1, p1 + mcnt, reg_info))
+ return false;
+
+ p1 += mcnt; /* Get past the n-th alternative. */
+ } /* if mcnt > 0 */
+ break;
+
+
+ case stop_memory:
+ assert (p1[1] == **p);
+ *p = p1 + 2;
+ return true;
+
+
+ default:
+ if (!common_op_match_null_string_p (&p1, end, reg_info))
+ return false;
+ }
+ } /* while p1 < end */
+
+ return false;
+} /* group_match_null_string_p */
+
+
+/* Similar to group_match_null_string_p, but doesn't deal with alternatives:
+ It expects P to be the first byte of a single alternative and END one
+ byte past the last. The alternative can contain groups. */
+
+static boolean
+alt_match_null_string_p (p, end, reg_info)
+ unsigned char *p, *end;
+ register_info_type *reg_info;
+{
+ int mcnt;
+ unsigned char *p1 = p;
+
+ while (p1 < end)
+ {
+ /* Skip over opcodes that can match nothing, and break when we get
+ to one that can't. */
+
+ switch ((re_opcode_t) *p1)
+ {
+ /* It's a loop. */
+ case on_failure_jump:
+ p1++;
+ EXTRACT_NUMBER_AND_INCR (mcnt, p1);
+ p1 += mcnt;
+ break;
+
+ default:
+ if (!common_op_match_null_string_p (&p1, end, reg_info))
+ return false;
+ }
+ } /* while p1 < end */
+
+ return true;
+} /* alt_match_null_string_p */
+
+
+/* Deals with the ops common to group_match_null_string_p and
+ alt_match_null_string_p.
+
+ Sets P to one after the op and its arguments, if any. */
+
+static boolean
+common_op_match_null_string_p (p, end, reg_info)
+ unsigned char **p, *end;
+ register_info_type *reg_info;
+{
+ int mcnt;
+ boolean ret;
+ int reg_no;
+ unsigned char *p1 = *p;
+
+ switch ((re_opcode_t) *p1++)
+ {
+ case no_op:
+ case begline:
+ case endline:
+ case begbuf:
+ case endbuf:
+ case wordbeg:
+ case wordend:
+ case wordbound:
+ case notwordbound:
+#ifdef emacs
+ case before_dot:
+ case at_dot:
+ case after_dot:
+#endif
+ break;
+
+ case start_memory:
+ reg_no = *p1;
+ assert (reg_no > 0 && reg_no <= MAX_REGNUM);
+ ret = group_match_null_string_p (&p1, end, reg_info);
+
+ /* Have to set this here in case we're checking a group which
+ contains a group and a back reference to it. */
+
+ if (REG_MATCH_NULL_STRING_P (reg_info[reg_no]) == MATCH_NULL_UNSET_VALUE)
+ REG_MATCH_NULL_STRING_P (reg_info[reg_no]) = ret;
+
+ if (!ret)
+ return false;
+ break;
+
+ /* If this is an optimized succeed_n for zero times, make the jump. */
+ case jump:
+ EXTRACT_NUMBER_AND_INCR (mcnt, p1);
+ if (mcnt >= 0)
+ p1 += mcnt;
+ else
+ return false;
+ break;
+
+ case succeed_n:
+ /* Get to the number of times to succeed. */
+ p1 += 2;
+ EXTRACT_NUMBER_AND_INCR (mcnt, p1);
+
+ if (mcnt == 0)
+ {
+ p1 -= 4;
+ EXTRACT_NUMBER_AND_INCR (mcnt, p1);
+ p1 += mcnt;
+ }
+ else
+ return false;
+ break;
+
+ case duplicate:
+ if (!REG_MATCH_NULL_STRING_P (reg_info[*p1]))
+ return false;
+ break;
+
+ case set_number_at:
+ p1 += 4;
+
+ default:
+ /* All other opcodes mean we cannot match the empty string. */
+ return false;
+ }
+
+ *p = p1;
+ return true;
+} /* common_op_match_null_string_p */
+
+
+/* Return zero if TRANSLATE[S1] and TRANSLATE[S2] are identical for LEN
+ bytes; nonzero otherwise. */
+
+static int
+bcmp_translate (s1, s2, len, translate)
+ const char *s1, *s2;
+ register int len;
+ RE_TRANSLATE_TYPE translate;
+{
+ register const unsigned char *p1 = (const unsigned char *) s1;
+ register const unsigned char *p2 = (const unsigned char *) s2;
+ while (len)
+ {
+ if (translate[*p1++] != translate[*p2++]) return 1;
+ len--;
+ }
+ return 0;
+}
+
+/* Entry points for GNU code. */
+
+/* re_compile_pattern is the GNU regular expression compiler: it
+ compiles PATTERN (of length SIZE) and puts the result in BUFP.
+ Returns 0 if the pattern was valid, otherwise an error string.
+
+ Assumes the `allocated' (and perhaps `buffer') and `translate' fields
+ are set in BUFP on entry.
+
+ We call regex_compile to do the actual compilation. */
+
+const char *
+re_compile_pattern (pattern, length, bufp)
+ const char *pattern;
+ size_t length;
+ struct re_pattern_buffer *bufp;
+{
+ reg_errcode_t ret;
+
+ /* GNU code is written to assume at least RE_NREGS registers will be set
+ (and at least one extra will be -1). */
+ bufp->regs_allocated = REGS_UNALLOCATED;
+
+ /* And GNU code determines whether or not to get register information
+ by passing null for the REGS argument to re_match, etc., not by
+ setting no_sub. */
+ bufp->no_sub = 0;
+
+ /* Match anchors at newline. */
+ bufp->newline_anchor = 1;
+
+ ret = regex_compile (pattern, length, re_syntax_options, bufp);
+
+ if (!ret)
+ return NULL;
+ return gettext (re_error_msgid[(int) ret]);
+}
+#ifdef _LIBC
+weak_alias (__re_compile_pattern, re_compile_pattern)
+#endif
+
+/* Entry points compatible with 4.2 BSD regex library. We don't define
+ them unless specifically requested. */
+
+#if defined _REGEX_RE_COMP || defined _LIBC
+
+/* BSD has one and only one pattern buffer. */
+static struct re_pattern_buffer re_comp_buf;
+
+char *
+#ifdef _LIBC
+/* Make these definitions weak in libc, so POSIX programs can redefine
+ these names if they don't use our functions, and still use
+ regcomp/regexec below without link errors. */
+weak_function
+#endif
+re_comp (s)
+ const char *s;
+{
+ reg_errcode_t ret;
+
+ if (!s)
+ {
+ if (!re_comp_buf.buffer)
+ return gettext ("No previous regular expression");
+ return 0;
+ }
+
+ if (!re_comp_buf.buffer)
+ {
+ re_comp_buf.buffer = (unsigned char *) malloc (200);
+ if (re_comp_buf.buffer == NULL)
+ return (char *) gettext (re_error_msgid[(int) REG_ESPACE]);
+ re_comp_buf.allocated = 200;
+
+ re_comp_buf.fastmap = (char *) malloc (1 << BYTEWIDTH);
+ if (re_comp_buf.fastmap == NULL)
+ return (char *) gettext (re_error_msgid[(int) REG_ESPACE]);
+ }
+
+ /* Since `re_exec' always passes NULL for the `regs' argument, we
+ don't need to initialize the pattern buffer fields which affect it. */
+
+ /* Match anchors at newlines. */
+ re_comp_buf.newline_anchor = 1;
+
+ ret = regex_compile (s, strlen (s), re_syntax_options, &re_comp_buf);
+
+ if (!ret)
+ return NULL;
+
+ /* Yes, we're discarding `const' here if !HAVE_LIBINTL. */
+ return (char *) gettext (re_error_msgid[(int) ret]);
+}
+
+
+int
+#ifdef _LIBC
+weak_function
+#endif
+re_exec (s)
+ const char *s;
+{
+ const int len = strlen (s);
+ return
+ 0 <= re_search (&re_comp_buf, s, len, 0, len, (struct re_registers *) 0);
+}
+
+#endif /* _REGEX_RE_COMP */
+
+/* POSIX.2 functions. Don't define these for Emacs. */
+
+#ifndef emacs
+
+/* regcomp takes a regular expression as a string and compiles it.
+
+ PREG is a regex_t *. We do not expect any fields to be initialized,
+ since POSIX says we shouldn't. Thus, we set
+
+ `buffer' to the compiled pattern;
+ `used' to the length of the compiled pattern;
+ `syntax' to RE_SYNTAX_POSIX_EXTENDED if the
+ REG_EXTENDED bit in CFLAGS is set; otherwise, to
+ RE_SYNTAX_POSIX_BASIC;
+ `newline_anchor' to REG_NEWLINE being set in CFLAGS;
+ `fastmap' and `fastmap_accurate' to zero;
+ `re_nsub' to the number of subexpressions in PATTERN.
+
+ PATTERN is the address of the pattern string.
+
+ CFLAGS is a series of bits which affect compilation.
+
+ If REG_EXTENDED is set, we use POSIX extended syntax; otherwise, we
+ use POSIX basic syntax.
+
+ If REG_NEWLINE is set, then . and [^...] don't match newline.
+ Also, regexec will try a match beginning after every newline.
+
+ If REG_ICASE is set, then we considers upper- and lowercase
+ versions of letters to be equivalent when matching.
+
+ If REG_NOSUB is set, then when PREG is passed to regexec, that
+ routine will report only success or failure, and nothing about the
+ registers.
+
+ It returns 0 if it succeeds, nonzero if it doesn't. (See gnu-regex.h for
+ the return codes and their meanings.) */
+
+int
+regcomp (preg, pattern, cflags)
+ regex_t *preg;
+ const char *pattern;
+ int cflags;
+{
+ reg_errcode_t ret;
+ reg_syntax_t syntax
+ = (cflags & REG_EXTENDED) ?
+ RE_SYNTAX_POSIX_EXTENDED : RE_SYNTAX_POSIX_BASIC;
+
+ /* regex_compile will allocate the space for the compiled pattern. */
+ preg->buffer = 0;
+ preg->allocated = 0;
+ preg->used = 0;
+
+ /* Don't bother to use a fastmap when searching. This simplifies the
+ REG_NEWLINE case: if we used a fastmap, we'd have to put all the
+ characters after newlines into the fastmap. This way, we just try
+ every character. */
+ preg->fastmap = 0;
+
+ if (cflags & REG_ICASE)
+ {
+ unsigned i;
+
+ preg->translate
+ = (RE_TRANSLATE_TYPE) malloc (CHAR_SET_SIZE
+ * sizeof (*(RE_TRANSLATE_TYPE)0));
+ if (preg->translate == NULL)
+ return (int) REG_ESPACE;
+
+ /* Map uppercase characters to corresponding lowercase ones. */
+ for (i = 0; i < CHAR_SET_SIZE; i++)
+ preg->translate[i] = ISUPPER (i) ? tolower (i) : i;
+ }
+ else
+ preg->translate = NULL;
+
+ /* If REG_NEWLINE is set, newlines are treated differently. */
+ if (cflags & REG_NEWLINE)
+ { /* REG_NEWLINE implies neither . nor [^...] match newline. */
+ syntax &= ~RE_DOT_NEWLINE;
+ syntax |= RE_HAT_LISTS_NOT_NEWLINE;
+ /* It also changes the matching behavior. */
+ preg->newline_anchor = 1;
+ }
+ else
+ preg->newline_anchor = 0;
+
+ preg->no_sub = !!(cflags & REG_NOSUB);
+
+ /* POSIX says a null character in the pattern terminates it, so we
+ can use strlen here in compiling the pattern. */
+ ret = regex_compile (pattern, strlen (pattern), syntax, preg);
+
+ /* POSIX doesn't distinguish between an unmatched open-group and an
+ unmatched close-group: both are REG_EPAREN. */
+ if (ret == REG_ERPAREN) ret = REG_EPAREN;
+
+ return (int) ret;
+}
+#ifdef _LIBC
+weak_alias (__regcomp, regcomp)
+#endif
+
+
+/* regexec searches for a given pattern, specified by PREG, in the
+ string STRING.
+
+ If NMATCH is zero or REG_NOSUB was set in the cflags argument to
+ `regcomp', we ignore PMATCH. Otherwise, we assume PMATCH has at
+ least NMATCH elements, and we set them to the offsets of the
+ corresponding matched substrings.
+
+ EFLAGS specifies `execution flags' which affect matching: if
+ REG_NOTBOL is set, then ^ does not match at the beginning of the
+ string; if REG_NOTEOL is set, then $ does not match at the end.
+
+ We return 0 if we find a match and REG_NOMATCH if not. */
+
+int
+regexec (preg, string, nmatch, pmatch, eflags)
+ const regex_t *preg;
+ const char *string;
+ size_t nmatch;
+ regmatch_t pmatch[];
+ int eflags;
+{
+ int ret;
+ struct re_registers regs;
+ regex_t private_preg;
+ int len = strlen (string);
+ boolean want_reg_info = !preg->no_sub && nmatch > 0;
+
+ private_preg = *preg;
+
+ private_preg.not_bol = !!(eflags & REG_NOTBOL);
+ private_preg.not_eol = !!(eflags & REG_NOTEOL);
+
+ /* The user has told us exactly how many registers to return
+ information about, via `nmatch'. We have to pass that on to the
+ matching routines. */
+ private_preg.regs_allocated = REGS_FIXED;
+
+ if (want_reg_info)
+ {
+ regs.num_regs = nmatch;
+ regs.start = TALLOC (nmatch, regoff_t);
+ regs.end = TALLOC (nmatch, regoff_t);
+ if (regs.start == NULL || regs.end == NULL)
+ return (int) REG_NOMATCH;
+ }
+
+ /* Perform the searching operation. */
+ ret = re_search (&private_preg, string, len,
+ /* start: */ 0, /* range: */ len,
+ want_reg_info ? &regs : (struct re_registers *) 0);
+
+ /* Copy the register information to the POSIX structure. */
+ if (want_reg_info)
+ {
+ if (ret >= 0)
+ {
+ unsigned r;
+
+ for (r = 0; r < nmatch; r++)
+ {
+ pmatch[r].rm_so = regs.start[r];
+ pmatch[r].rm_eo = regs.end[r];
+ }
+ }
+
+ /* If we needed the temporary register info, free the space now. */
+ free (regs.start);
+ free (regs.end);
+ }
+
+ /* We want zero return to mean success, unlike `re_search'. */
+ return ret >= 0 ? (int) REG_NOERROR : (int) REG_NOMATCH;
+}
+#ifdef _LIBC
+weak_alias (__regexec, regexec)
+#endif
+
+
+/* Returns a message corresponding to an error code, ERRCODE, returned
+ from either regcomp or regexec. We don't use PREG here. */
+
+size_t
+__regerror (errcode, preg, errbuf, errbuf_size)
+ int errcode;
+ const regex_t *preg;
+ char *errbuf;
+ size_t errbuf_size;
+{
+ const char *msg;
+ size_t msg_size;
+
+ if (errcode < 0
+ || errcode >= (int) (sizeof (re_error_msgid)
+ / sizeof (re_error_msgid[0])))
+ /* Only error codes returned by the rest of the code should be passed
+ to this routine. If we are given anything else, or if other regex
+ code generates an invalid error code, then the program has a bug.
+ Dump core so we can fix it. */
+ abort ();
+
+ msg = gettext (re_error_msgid[errcode]);
+
+ msg_size = strlen (msg) + 1; /* Includes the null. */
+
+ if (errbuf_size != 0)
+ {
+ if (msg_size > errbuf_size)
+ {
+#if defined HAVE_MEMPCPY || defined _LIBC
+ *((char *) __mempcpy (errbuf, msg, errbuf_size - 1)) = '\0';
+#else
+ memcpy (errbuf, msg, errbuf_size - 1);
+ errbuf[errbuf_size - 1] = 0;
+#endif
+ }
+ else
+ memcpy (errbuf, msg, msg_size);
+ }
+
+ return msg_size;
+}
+#ifdef _LIBC
+weak_alias (__regerror, regerror)
+#endif
+
+
+/* Free dynamically allocated space used by PREG. */
+
+void
+regfree (preg)
+ regex_t *preg;
+{
+ if (preg->buffer != NULL)
+ free (preg->buffer);
+ preg->buffer = NULL;
+
+ preg->allocated = 0;
+ preg->used = 0;
+
+ if (preg->fastmap != NULL)
+ free (preg->fastmap);
+ preg->fastmap = NULL;
+ preg->fastmap_accurate = 0;
+
+ if (preg->translate != NULL)
+ free (preg->translate);
+ preg->translate = NULL;
+}
+#ifdef _LIBC
+weak_alias (__regfree, regfree)
+#endif
+
+#endif /* not emacs */
diff --git a/gdb/gnu-regex.h b/gdb/gnu-regex.h
new file mode 100644
index 00000000000..9153ea1b07d
--- /dev/null
+++ b/gdb/gnu-regex.h
@@ -0,0 +1,576 @@
+/* Definitions for data structures and routines for the regular
+ expression library, version 0.12.
+ Copyright (C) 1985,89,90,91,92,93,95,96,97,98 Free Software Foundation, Inc.
+
+ NOTE: The canonical source of this file is maintained with the
+ GNU C Library. Bugs can be reported to bug-glibc@prep.ai.mit.edu.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 2, or (at your option) any
+ later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef _REGEX_H
+#define _REGEX_H 1
+
+/* Allow the use in C++ code. */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* POSIX says that <sys/types.h> must be included (by the caller) before
+ <regex.h>. */
+
+#if !defined _POSIX_C_SOURCE && !defined _POSIX_SOURCE && defined VMS
+/* VMS doesn't have `size_t' in <sys/types.h>, even though POSIX says it
+ should be there. */
+# include <stddef.h>
+#endif
+
+/* GDB LOCAL: define _REGEX_RE_COMP to get BSD style re_comp and re_exec */
+#ifndef _REGEX_RE_COMP
+#define _REGEX_RE_COMP
+#endif
+
+/* The following two types have to be signed and unsigned integer type
+ wide enough to hold a value of a pointer. For most ANSI compilers
+ ptrdiff_t and size_t should be likely OK. Still size of these two
+ types is 2 for Microsoft C. Ugh... */
+typedef long int s_reg_t;
+typedef unsigned long int active_reg_t;
+
+/* The following bits are used to determine the regexp syntax we
+ recognize. The set/not-set meanings are chosen so that Emacs syntax
+ remains the value 0. The bits are given in alphabetical order, and
+ the definitions shifted by one from the previous bit; thus, when we
+ add or remove a bit, only one other definition need change. */
+typedef unsigned long int reg_syntax_t;
+
+/* If this bit is not set, then \ inside a bracket expression is literal.
+ If set, then such a \ quotes the following character. */
+#define RE_BACKSLASH_ESCAPE_IN_LISTS ((unsigned long int) 1)
+
+/* If this bit is not set, then + and ? are operators, and \+ and \? are
+ literals.
+ If set, then \+ and \? are operators and + and ? are literals. */
+#define RE_BK_PLUS_QM (RE_BACKSLASH_ESCAPE_IN_LISTS << 1)
+
+/* If this bit is set, then character classes are supported. They are:
+ [:alpha:], [:upper:], [:lower:], [:digit:], [:alnum:], [:xdigit:],
+ [:space:], [:print:], [:punct:], [:graph:], and [:cntrl:].
+ If not set, then character classes are not supported. */
+#define RE_CHAR_CLASSES (RE_BK_PLUS_QM << 1)
+
+/* If this bit is set, then ^ and $ are always anchors (outside bracket
+ expressions, of course).
+ If this bit is not set, then it depends:
+ ^ is an anchor if it is at the beginning of a regular
+ expression or after an open-group or an alternation operator;
+ $ is an anchor if it is at the end of a regular expression, or
+ before a close-group or an alternation operator.
+
+ This bit could be (re)combined with RE_CONTEXT_INDEP_OPS, because
+ POSIX draft 11.2 says that * etc. in leading positions is undefined.
+ We already implemented a previous draft which made those constructs
+ invalid, though, so we haven't changed the code back. */
+#define RE_CONTEXT_INDEP_ANCHORS (RE_CHAR_CLASSES << 1)
+
+/* If this bit is set, then special characters are always special
+ regardless of where they are in the pattern.
+ If this bit is not set, then special characters are special only in
+ some contexts; otherwise they are ordinary. Specifically,
+ * + ? and intervals are only special when not after the beginning,
+ open-group, or alternation operator. */
+#define RE_CONTEXT_INDEP_OPS (RE_CONTEXT_INDEP_ANCHORS << 1)
+
+/* If this bit is set, then *, +, ?, and { cannot be first in an re or
+ immediately after an alternation or begin-group operator. */
+#define RE_CONTEXT_INVALID_OPS (RE_CONTEXT_INDEP_OPS << 1)
+
+/* If this bit is set, then . matches newline.
+ If not set, then it doesn't. */
+#define RE_DOT_NEWLINE (RE_CONTEXT_INVALID_OPS << 1)
+
+/* If this bit is set, then . doesn't match NUL.
+ If not set, then it does. */
+#define RE_DOT_NOT_NULL (RE_DOT_NEWLINE << 1)
+
+/* If this bit is set, nonmatching lists [^...] do not match newline.
+ If not set, they do. */
+#define RE_HAT_LISTS_NOT_NEWLINE (RE_DOT_NOT_NULL << 1)
+
+/* If this bit is set, either \{...\} or {...} defines an
+ interval, depending on RE_NO_BK_BRACES.
+ If not set, \{, \}, {, and } are literals. */
+#define RE_INTERVALS (RE_HAT_LISTS_NOT_NEWLINE << 1)
+
+/* If this bit is set, +, ? and | aren't recognized as operators.
+ If not set, they are. */
+#define RE_LIMITED_OPS (RE_INTERVALS << 1)
+
+/* If this bit is set, newline is an alternation operator.
+ If not set, newline is literal. */
+#define RE_NEWLINE_ALT (RE_LIMITED_OPS << 1)
+
+/* If this bit is set, then `{...}' defines an interval, and \{ and \}
+ are literals.
+ If not set, then `\{...\}' defines an interval. */
+#define RE_NO_BK_BRACES (RE_NEWLINE_ALT << 1)
+
+/* If this bit is set, (...) defines a group, and \( and \) are literals.
+ If not set, \(...\) defines a group, and ( and ) are literals. */
+#define RE_NO_BK_PARENS (RE_NO_BK_BRACES << 1)
+
+/* If this bit is set, then \<digit> matches <digit>.
+ If not set, then \<digit> is a back-reference. */
+#define RE_NO_BK_REFS (RE_NO_BK_PARENS << 1)
+
+/* If this bit is set, then | is an alternation operator, and \| is literal.
+ If not set, then \| is an alternation operator, and | is literal. */
+#define RE_NO_BK_VBAR (RE_NO_BK_REFS << 1)
+
+/* If this bit is set, then an ending range point collating higher
+ than the starting range point, as in [z-a], is invalid.
+ If not set, then when ending range point collates higher than the
+ starting range point, the range is ignored. */
+#define RE_NO_EMPTY_RANGES (RE_NO_BK_VBAR << 1)
+
+/* If this bit is set, then an unmatched ) is ordinary.
+ If not set, then an unmatched ) is invalid. */
+#define RE_UNMATCHED_RIGHT_PAREN_ORD (RE_NO_EMPTY_RANGES << 1)
+
+/* If this bit is set, succeed as soon as we match the whole pattern,
+ without further backtracking. */
+#define RE_NO_POSIX_BACKTRACKING (RE_UNMATCHED_RIGHT_PAREN_ORD << 1)
+
+/* If this bit is set, do not process the GNU regex operators.
+ If not set, then the GNU regex operators are recognized. */
+#define RE_NO_GNU_OPS (RE_NO_POSIX_BACKTRACKING << 1)
+
+/* If this bit is set, turn on internal regex debugging.
+ If not set, and debugging was on, turn it off.
+ This only works if regex.c is compiled -DDEBUG.
+ We define this bit always, so that all that's needed to turn on
+ debugging is to recompile regex.c; the calling code can always have
+ this bit set, and it won't affect anything in the normal case. */
+#define RE_DEBUG (RE_NO_GNU_OPS << 1)
+
+/* This global variable defines the particular regexp syntax to use (for
+ some interfaces). When a regexp is compiled, the syntax used is
+ stored in the pattern buffer, so changing this does not affect
+ already-compiled regexps. */
+extern reg_syntax_t re_syntax_options;
+
+/* Define combinations of the above bits for the standard possibilities.
+ (The [[[ comments delimit what gets put into the Texinfo file, so
+ don't delete them!) */
+/* [[[begin syntaxes]]] */
+#define RE_SYNTAX_EMACS 0
+
+#define RE_SYNTAX_AWK \
+ (RE_BACKSLASH_ESCAPE_IN_LISTS | RE_DOT_NOT_NULL \
+ | RE_NO_BK_PARENS | RE_NO_BK_REFS \
+ | RE_NO_BK_VBAR | RE_NO_EMPTY_RANGES \
+ | RE_DOT_NEWLINE | RE_CONTEXT_INDEP_ANCHORS \
+ | RE_UNMATCHED_RIGHT_PAREN_ORD | RE_NO_GNU_OPS)
+
+#define RE_SYNTAX_GNU_AWK \
+ ((RE_SYNTAX_POSIX_EXTENDED | RE_BACKSLASH_ESCAPE_IN_LISTS | RE_DEBUG) \
+ & ~(RE_DOT_NOT_NULL | RE_INTERVALS | RE_CONTEXT_INDEP_OPS))
+
+#define RE_SYNTAX_POSIX_AWK \
+ (RE_SYNTAX_POSIX_EXTENDED | RE_BACKSLASH_ESCAPE_IN_LISTS \
+ | RE_INTERVALS | RE_NO_GNU_OPS)
+
+#define RE_SYNTAX_GREP \
+ (RE_BK_PLUS_QM | RE_CHAR_CLASSES \
+ | RE_HAT_LISTS_NOT_NEWLINE | RE_INTERVALS \
+ | RE_NEWLINE_ALT)
+
+#define RE_SYNTAX_EGREP \
+ (RE_CHAR_CLASSES | RE_CONTEXT_INDEP_ANCHORS \
+ | RE_CONTEXT_INDEP_OPS | RE_HAT_LISTS_NOT_NEWLINE \
+ | RE_NEWLINE_ALT | RE_NO_BK_PARENS \
+ | RE_NO_BK_VBAR)
+
+#define RE_SYNTAX_POSIX_EGREP \
+ (RE_SYNTAX_EGREP | RE_INTERVALS | RE_NO_BK_BRACES)
+
+/* P1003.2/D11.2, section 4.20.7.1, lines 5078ff. */
+#define RE_SYNTAX_ED RE_SYNTAX_POSIX_BASIC
+
+#define RE_SYNTAX_SED RE_SYNTAX_POSIX_BASIC
+
+/* Syntax bits common to both basic and extended POSIX regex syntax. */
+#define _RE_SYNTAX_POSIX_COMMON \
+ (RE_CHAR_CLASSES | RE_DOT_NEWLINE | RE_DOT_NOT_NULL \
+ | RE_INTERVALS | RE_NO_EMPTY_RANGES)
+
+#define RE_SYNTAX_POSIX_BASIC \
+ (_RE_SYNTAX_POSIX_COMMON | RE_BK_PLUS_QM)
+
+/* Differs from ..._POSIX_BASIC only in that RE_BK_PLUS_QM becomes
+ RE_LIMITED_OPS, i.e., \? \+ \| are not recognized. Actually, this
+ isn't minimal, since other operators, such as \`, aren't disabled. */
+#define RE_SYNTAX_POSIX_MINIMAL_BASIC \
+ (_RE_SYNTAX_POSIX_COMMON | RE_LIMITED_OPS)
+
+#define RE_SYNTAX_POSIX_EXTENDED \
+ (_RE_SYNTAX_POSIX_COMMON | RE_CONTEXT_INDEP_ANCHORS \
+ | RE_CONTEXT_INDEP_OPS | RE_NO_BK_BRACES \
+ | RE_NO_BK_PARENS | RE_NO_BK_VBAR \
+ | RE_UNMATCHED_RIGHT_PAREN_ORD)
+
+/* Differs from ..._POSIX_EXTENDED in that RE_CONTEXT_INVALID_OPS
+ replaces RE_CONTEXT_INDEP_OPS and RE_NO_BK_REFS is added. */
+#define RE_SYNTAX_POSIX_MINIMAL_EXTENDED \
+ (_RE_SYNTAX_POSIX_COMMON | RE_CONTEXT_INDEP_ANCHORS \
+ | RE_CONTEXT_INVALID_OPS | RE_NO_BK_BRACES \
+ | RE_NO_BK_PARENS | RE_NO_BK_REFS \
+ | RE_NO_BK_VBAR | RE_UNMATCHED_RIGHT_PAREN_ORD)
+/* [[[end syntaxes]]] */
+
+/* Maximum number of duplicates an interval can allow. Some systems
+ (erroneously) define this in other header files, but we want our
+ value, so remove any previous define. */
+#ifdef RE_DUP_MAX
+# undef RE_DUP_MAX
+#endif
+/* If sizeof(int) == 2, then ((1 << 15) - 1) overflows. */
+#define RE_DUP_MAX (0x7fff)
+
+
+/* POSIX `cflags' bits (i.e., information for `regcomp'). */
+
+/* If this bit is set, then use extended regular expression syntax.
+ If not set, then use basic regular expression syntax. */
+#define REG_EXTENDED 1
+
+/* If this bit is set, then ignore case when matching.
+ If not set, then case is significant. */
+#define REG_ICASE (REG_EXTENDED << 1)
+
+/* If this bit is set, then anchors do not match at newline
+ characters in the string.
+ If not set, then anchors do match at newlines. */
+#define REG_NEWLINE (REG_ICASE << 1)
+
+/* If this bit is set, then report only success or fail in regexec.
+ If not set, then returns differ between not matching and errors. */
+#define REG_NOSUB (REG_NEWLINE << 1)
+
+
+/* POSIX `eflags' bits (i.e., information for regexec). */
+
+/* If this bit is set, then the beginning-of-line operator doesn't match
+ the beginning of the string (presumably because it's not the
+ beginning of a line).
+ If not set, then the beginning-of-line operator does match the
+ beginning of the string. */
+#define REG_NOTBOL 1
+
+/* Like REG_NOTBOL, except for the end-of-line. */
+#define REG_NOTEOL (1 << 1)
+
+
+/* If any error codes are removed, changed, or added, update the
+ `re_error_msg' table in regex.c. */
+typedef enum
+{
+#if (_XOPEN_SOURCE - 0) == 500
+ REG_NOSYS = -1, /* This will never happen for this implementation. */
+#endif
+
+ REG_NOERROR = 0, /* Success. */
+ REG_NOMATCH, /* Didn't find a match (for regexec). */
+
+ /* POSIX regcomp return error codes. (In the order listed in the
+ standard.) */
+ REG_BADPAT, /* Invalid pattern. */
+ REG_ECOLLATE, /* Not implemented. */
+ REG_ECTYPE, /* Invalid character class name. */
+ REG_EESCAPE, /* Trailing backslash. */
+ REG_ESUBREG, /* Invalid back reference. */
+ REG_EBRACK, /* Unmatched left bracket. */
+ REG_EPAREN, /* Parenthesis imbalance. */
+ REG_EBRACE, /* Unmatched \{. */
+ REG_BADBR, /* Invalid contents of \{\}. */
+ REG_ERANGE, /* Invalid range end. */
+ REG_ESPACE, /* Ran out of memory. */
+ REG_BADRPT, /* No preceding re for repetition op. */
+
+ /* Error codes we've added. */
+ REG_EEND, /* Premature end. */
+ REG_ESIZE, /* Compiled pattern bigger than 2^16 bytes. */
+ REG_ERPAREN /* Unmatched ) or \); not returned from regcomp. */
+} reg_errcode_t;
+
+/* This data structure represents a compiled pattern. Before calling
+ the pattern compiler, the fields `buffer', `allocated', `fastmap',
+ `translate', and `no_sub' can be set. After the pattern has been
+ compiled, the `re_nsub' field is available. All other fields are
+ private to the regex routines. */
+
+#ifndef RE_TRANSLATE_TYPE
+# define RE_TRANSLATE_TYPE char *
+#endif
+
+struct re_pattern_buffer
+{
+/* [[[begin pattern_buffer]]] */
+ /* Space that holds the compiled pattern. It is declared as
+ `unsigned char *' because its elements are
+ sometimes used as array indexes. */
+ unsigned char *buffer;
+
+ /* Number of bytes to which `buffer' points. */
+ unsigned long int allocated;
+
+ /* Number of bytes actually used in `buffer'. */
+ unsigned long int used;
+
+ /* Syntax setting with which the pattern was compiled. */
+ reg_syntax_t syntax;
+
+ /* Pointer to a fastmap, if any, otherwise zero. re_search uses
+ the fastmap, if there is one, to skip over impossible
+ starting points for matches. */
+ char *fastmap;
+
+ /* Either a translate table to apply to all characters before
+ comparing them, or zero for no translation. The translation
+ is applied to a pattern when it is compiled and to a string
+ when it is matched. */
+ RE_TRANSLATE_TYPE translate;
+
+ /* Number of subexpressions found by the compiler. */
+ size_t re_nsub;
+
+ /* Zero if this pattern cannot match the empty string, one else.
+ Well, in truth it's used only in `re_search_2', to see
+ whether or not we should use the fastmap, so we don't set
+ this absolutely perfectly; see `re_compile_fastmap' (the
+ `duplicate' case). */
+ unsigned can_be_null : 1;
+
+ /* If REGS_UNALLOCATED, allocate space in the `regs' structure
+ for `max (RE_NREGS, re_nsub + 1)' groups.
+ If REGS_REALLOCATE, reallocate space if necessary.
+ If REGS_FIXED, use what's there. */
+#define REGS_UNALLOCATED 0
+#define REGS_REALLOCATE 1
+#define REGS_FIXED 2
+ unsigned regs_allocated : 2;
+
+ /* Set to zero when `regex_compile' compiles a pattern; set to one
+ by `re_compile_fastmap' if it updates the fastmap. */
+ unsigned fastmap_accurate : 1;
+
+ /* If set, `re_match_2' does not return information about
+ subexpressions. */
+ unsigned no_sub : 1;
+
+ /* If set, a beginning-of-line anchor doesn't match at the
+ beginning of the string. */
+ unsigned not_bol : 1;
+
+ /* Similarly for an end-of-line anchor. */
+ unsigned not_eol : 1;
+
+ /* If true, an anchor at a newline matches. */
+ unsigned newline_anchor : 1;
+
+/* [[[end pattern_buffer]]] */
+};
+
+typedef struct re_pattern_buffer regex_t;
+
+/* Type for byte offsets within the string. POSIX mandates this. */
+typedef int regoff_t;
+
+
+/* This is the structure we store register match data in. See
+ regex.texinfo for a full description of what registers match. */
+struct re_registers
+{
+ unsigned num_regs;
+ regoff_t *start;
+ regoff_t *end;
+};
+
+
+/* If `regs_allocated' is REGS_UNALLOCATED in the pattern buffer,
+ `re_match_2' returns information about at least this many registers
+ the first time a `regs' structure is passed. */
+#ifndef RE_NREGS
+# define RE_NREGS 30
+#endif
+
+
+/* POSIX specification for registers. Aside from the different names than
+ `re_registers', POSIX uses an array of structures, instead of a
+ structure of arrays. */
+typedef struct
+{
+ regoff_t rm_so; /* Byte offset from string's start to substring's start. */
+ regoff_t rm_eo; /* Byte offset from string's start to substring's end. */
+} regmatch_t;
+
+/* Declarations for routines. */
+
+/* To avoid duplicating every routine declaration -- once with a
+ prototype (if we are ANSI), and once without (if we aren't) -- we
+ use the following macro to declare argument types. This
+ unfortunately clutters up the declarations a bit, but I think it's
+ worth it. */
+
+#if __STDC__
+
+# define _RE_ARGS(args) args
+
+#else /* not __STDC__ */
+
+# define _RE_ARGS(args) ()
+
+#endif /* not __STDC__ */
+
+/* Sets the current default syntax to SYNTAX, and return the old syntax.
+ You can also simply assign to the `re_syntax_options' variable. */
+extern reg_syntax_t __re_set_syntax _RE_ARGS ((reg_syntax_t syntax));
+extern reg_syntax_t re_set_syntax _RE_ARGS ((reg_syntax_t syntax));
+
+/* Compile the regular expression PATTERN, with length LENGTH
+ and syntax given by the global `re_syntax_options', into the buffer
+ BUFFER. Return NULL if successful, and an error string if not. */
+extern const char *__re_compile_pattern
+ _RE_ARGS ((const char *pattern, size_t length,
+ struct re_pattern_buffer *buffer));
+extern const char *re_compile_pattern
+ _RE_ARGS ((const char *pattern, size_t length,
+ struct re_pattern_buffer *buffer));
+
+
+/* Compile a fastmap for the compiled pattern in BUFFER; used to
+ accelerate searches. Return 0 if successful and -2 if was an
+ internal error. */
+extern int __re_compile_fastmap _RE_ARGS ((struct re_pattern_buffer *buffer));
+extern int re_compile_fastmap _RE_ARGS ((struct re_pattern_buffer *buffer));
+
+
+/* Search in the string STRING (with length LENGTH) for the pattern
+ compiled into BUFFER. Start searching at position START, for RANGE
+ characters. Return the starting position of the match, -1 for no
+ match, or -2 for an internal error. Also return register
+ information in REGS (if REGS and BUFFER->no_sub are nonzero). */
+extern int __re_search
+ _RE_ARGS ((struct re_pattern_buffer *buffer, const char *string,
+ int length, int start, int range, struct re_registers *regs));
+extern int re_search
+ _RE_ARGS ((struct re_pattern_buffer *buffer, const char *string,
+ int length, int start, int range, struct re_registers *regs));
+
+
+/* Like `re_search', but search in the concatenation of STRING1 and
+ STRING2. Also, stop searching at index START + STOP. */
+extern int __re_search_2
+ _RE_ARGS ((struct re_pattern_buffer *buffer, const char *string1,
+ int length1, const char *string2, int length2,
+ int start, int range, struct re_registers *regs, int stop));
+extern int re_search_2
+ _RE_ARGS ((struct re_pattern_buffer *buffer, const char *string1,
+ int length1, const char *string2, int length2,
+ int start, int range, struct re_registers *regs, int stop));
+
+
+/* Like `re_search', but return how many characters in STRING the regexp
+ in BUFFER matched, starting at position START. */
+extern int __re_match
+ _RE_ARGS ((struct re_pattern_buffer *buffer, const char *string,
+ int length, int start, struct re_registers *regs));
+extern int re_match
+ _RE_ARGS ((struct re_pattern_buffer *buffer, const char *string,
+ int length, int start, struct re_registers *regs));
+
+
+/* Relates to `re_match' as `re_search_2' relates to `re_search'. */
+extern int __re_match_2
+ _RE_ARGS ((struct re_pattern_buffer *buffer, const char *string1,
+ int length1, const char *string2, int length2,
+ int start, struct re_registers *regs, int stop));
+extern int re_match_2
+ _RE_ARGS ((struct re_pattern_buffer *buffer, const char *string1,
+ int length1, const char *string2, int length2,
+ int start, struct re_registers *regs, int stop));
+
+
+/* Set REGS to hold NUM_REGS registers, storing them in STARTS and
+ ENDS. Subsequent matches using BUFFER and REGS will use this memory
+ for recording register information. STARTS and ENDS must be
+ allocated with malloc, and must each be at least `NUM_REGS * sizeof
+ (regoff_t)' bytes long.
+
+ If NUM_REGS == 0, then subsequent matches should allocate their own
+ register data.
+
+ Unless this function is called, the first search or match using
+ PATTERN_BUFFER will allocate its own register data, without
+ freeing the old data. */
+extern void __re_set_registers
+ _RE_ARGS ((struct re_pattern_buffer *buffer, struct re_registers *regs,
+ unsigned num_regs, regoff_t *starts, regoff_t *ends));
+extern void re_set_registers
+ _RE_ARGS ((struct re_pattern_buffer *buffer, struct re_registers *regs,
+ unsigned num_regs, regoff_t *starts, regoff_t *ends));
+
+#ifdef _REGEX_RE_COMP
+# ifndef _CRAY
+/* 4.2 bsd compatibility. */
+extern char *re_comp _RE_ARGS ((const char *));
+extern int re_exec _RE_ARGS ((const char *));
+# endif
+#endif
+
+/* POSIX compatibility. */
+extern int __regcomp _RE_ARGS ((regex_t *__preg, const char *__pattern,
+ int __cflags));
+extern int regcomp _RE_ARGS ((regex_t *__preg, const char *__pattern,
+ int __cflags));
+
+extern int __regexec _RE_ARGS ((const regex_t *__preg,
+ const char *__string, size_t __nmatch,
+ regmatch_t __pmatch[], int __eflags));
+extern int regexec _RE_ARGS ((const regex_t *__preg,
+ const char *__string, size_t __nmatch,
+ regmatch_t __pmatch[], int __eflags));
+
+extern size_t __regerror _RE_ARGS ((int __errcode, const regex_t *__preg,
+ char *__errbuf, size_t __errbuf_size));
+extern size_t regerror _RE_ARGS ((int __errcode, const regex_t *__preg,
+ char *__errbuf, size_t __errbuf_size));
+
+extern void __regfree _RE_ARGS ((regex_t *__preg));
+extern void regfree _RE_ARGS ((regex_t *__preg));
+
+
+#ifdef __cplusplus
+}
+#endif /* C++ */
+
+#endif /* regex.h */
+
+/*
+Local variables:
+make-backup-files: t
+version-control: t
+trim-versions-without-asking: nil
+End:
+*/
diff --git a/gdb/gould-tdep.c b/gdb/gould-tdep.c
new file mode 100644
index 00000000000..1916cc2ac69
--- /dev/null
+++ b/gdb/gould-tdep.c
@@ -0,0 +1,310 @@
+/* OBSOLETE /* GOULD RISC target-dependent code for GDB, the GNU debugger. */
+/* OBSOLETE Copyright 1986, 1987, 1989, 1991 Free Software Foundation, Inc. */
+/* OBSOLETE */
+/* OBSOLETE This file is part of GDB. */
+/* OBSOLETE */
+/* OBSOLETE This program is free software; you can redistribute it and/or modify */
+/* OBSOLETE it under the terms of the GNU General Public License as published by */
+/* OBSOLETE the Free Software Foundation; either version 2 of the License, or */
+/* OBSOLETE (at your option) any later version. */
+/* OBSOLETE */
+/* OBSOLETE This program is distributed in the hope that it will be useful, */
+/* OBSOLETE but WITHOUT ANY WARRANTY; without even the implied warranty of */
+/* OBSOLETE MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
+/* OBSOLETE GNU General Public License for more details. */
+/* OBSOLETE */
+/* OBSOLETE You should have received a copy of the GNU General Public License */
+/* OBSOLETE along with this program; if not, write to the Free Software */
+/* OBSOLETE Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *x/ */
+/* OBSOLETE */
+/* OBSOLETE #include "defs.h" */
+/* OBSOLETE #include "symtab.h" */
+/* OBSOLETE #include "frame.h" */
+/* OBSOLETE #include "gdbcore.h" */
+/* OBSOLETE #if defined GOULD_PN */
+/* OBSOLETE #include "opcode/pn.h" */
+/* OBSOLETE #else */
+/* OBSOLETE #include "opcode/np1.h" */
+/* OBSOLETE #endif */
+/* OBSOLETE */
+/* OBSOLETE /* GOULD RISC instructions are never longer than this many bytes. *x/ */
+/* OBSOLETE #define MAXLEN 4 */
+/* OBSOLETE */
+/* OBSOLETE /* Number of elements in the opcode table. *x/ */
+/* OBSOLETE #define NOPCODES (sizeof gld_opcodes / sizeof gld_opcodes[0]) */
+/* OBSOLETE */
+/* OBSOLETE int */
+/* OBSOLETE gould_frame_chain_valid (chain, fi) */
+/* OBSOLETE CORE_ADDR chain; */
+/* OBSOLETE struct frame_info *fi; /* not used here *x/ */
+/* OBSOLETE { */
+/* OBSOLETE return (chain != 0 && chain != (thisframe)->frame); */
+/* OBSOLETE } */
+/* OBSOLETE */
+/* OBSOLETE /* Both gcc and cc return small structs in registers (i.e. in GDB */
+/* OBSOLETE terminology, small structs don't use the struct return convention). *x/ */
+/* OBSOLETE int */
+/* OBSOLETE gould_use_struct_convention (gcc_p, type) */
+/* OBSOLETE int gcc_p; */
+/* OBSOLETE struct type *type; */
+/* OBSOLETE { */
+/* OBSOLETE return (TYPE_LENGTH(type) > 8); */
+/* OBSOLETE } */
+/* OBSOLETE */
+/* OBSOLETE */
+/* OBSOLETE */
+/* OBSOLETE /* Print the GOULD instruction at address MEMADDR in debugged memory, */
+/* OBSOLETE on STREAM. Returns length of the instruction, in bytes. *x/ */
+/* OBSOLETE */
+/* OBSOLETE int */
+/* OBSOLETE gould_print_insn (memaddr, stream) */
+/* OBSOLETE CORE_ADDR memaddr; */
+/* OBSOLETE FILE *stream; */
+/* OBSOLETE { */
+/* OBSOLETE unsigned char buffer[MAXLEN]; */
+/* OBSOLETE register int i; */
+/* OBSOLETE register char *d; */
+/* OBSOLETE register int bestmask; */
+/* OBSOLETE unsigned best; */
+/* OBSOLETE int temp, index, bestlen; */
+/* OBSOLETE */
+/* OBSOLETE read_memory (memaddr, buffer, MAXLEN); */
+/* OBSOLETE */
+/* OBSOLETE bestmask = 0; */
+/* OBSOLETE index = -1; */
+/* OBSOLETE best = 0xffffffff; */
+/* OBSOLETE for (i = 0; i < NOPCODES; i++) */
+/* OBSOLETE { */
+/* OBSOLETE register unsigned int opcode = gld_opcodes[i].opcode; */
+/* OBSOLETE register unsigned int mask = gld_opcodes[i].mask; */
+/* OBSOLETE register unsigned int len = gld_opcodes[i].length; */
+/* OBSOLETE register unsigned int test; */
+/* OBSOLETE */
+/* OBSOLETE /* Get possible opcode bytes into integer *x/ */
+/* OBSOLETE test = buffer[0] << 24; */
+/* OBSOLETE test |= buffer[1] << 16; */
+/* OBSOLETE test |= buffer[2] << 8; */
+/* OBSOLETE test |= buffer[3]; */
+/* OBSOLETE */
+/* OBSOLETE /* Mask with opcode and see if match *x/ */
+/* OBSOLETE if ((opcode & mask) == (test & mask)) */
+/* OBSOLETE { */
+/* OBSOLETE /* See if second or third match *x/ */
+/* OBSOLETE if (index >= 0) */
+/* OBSOLETE { */
+/* OBSOLETE /* Take new one if it looks good *x/ */
+/* OBSOLETE if (bestlen == MAXLEN && len == MAXLEN) */
+/* OBSOLETE { */
+/* OBSOLETE /* See if lower bits matched *x/ */
+/* OBSOLETE if (((bestmask & 3) == 0) && */
+/* OBSOLETE ((mask & 3) != 0)) */
+/* OBSOLETE { */
+/* OBSOLETE bestmask = mask; */
+/* OBSOLETE bestlen = len; */
+/* OBSOLETE best = test; */
+/* OBSOLETE index = i; */
+/* OBSOLETE } */
+/* OBSOLETE } */
+/* OBSOLETE } */
+/* OBSOLETE else */
+/* OBSOLETE { */
+/* OBSOLETE /* First match, save it *x/ */
+/* OBSOLETE bestmask = mask; */
+/* OBSOLETE bestlen = len; */
+/* OBSOLETE best = test; */
+/* OBSOLETE index = i; */
+/* OBSOLETE } */
+/* OBSOLETE } */
+/* OBSOLETE } */
+/* OBSOLETE */
+/* OBSOLETE /* Handle undefined instructions. *x/ */
+/* OBSOLETE if (index < 0) */
+/* OBSOLETE { */
+/* OBSOLETE fprintf (stream, "undefined 0%o",(buffer[0]<<8)+buffer[1]); */
+/* OBSOLETE return 2; */
+/* OBSOLETE } */
+/* OBSOLETE */
+/* OBSOLETE /* Print instruction name *x/ */
+/* OBSOLETE fprintf (stream, "%-12s", gld_opcodes[index].name); */
+/* OBSOLETE */
+/* OBSOLETE /* Adjust if short instruction *x/ */
+/* OBSOLETE if (gld_opcodes[index].length < 4) */
+/* OBSOLETE { */
+/* OBSOLETE best >>= 16; */
+/* OBSOLETE i = 0; */
+/* OBSOLETE } */
+/* OBSOLETE else */
+/* OBSOLETE { */
+/* OBSOLETE i = 16; */
+/* OBSOLETE } */
+/* OBSOLETE */
+/* OBSOLETE /* Dump out instruction arguments *x/ */
+/* OBSOLETE for (d = gld_opcodes[index].args; *d; ++d) */
+/* OBSOLETE { */
+/* OBSOLETE switch (*d) */
+/* OBSOLETE { */
+/* OBSOLETE case 'f': */
+/* OBSOLETE fprintf (stream, "%d", (best >> (7 + i)) & 7); */
+/* OBSOLETE break; */
+/* OBSOLETE case 'r': */
+/* OBSOLETE fprintf (stream, "r%d", (best >> (7 + i)) & 7); */
+/* OBSOLETE break; */
+/* OBSOLETE case 'R': */
+/* OBSOLETE fprintf (stream, "r%d", (best >> (4 + i)) & 7); */
+/* OBSOLETE break; */
+/* OBSOLETE case 'b': */
+/* OBSOLETE fprintf (stream, "b%d", (best >> (7 + i)) & 7); */
+/* OBSOLETE break; */
+/* OBSOLETE case 'B': */
+/* OBSOLETE fprintf (stream, "b%d", (best >> (4 + i)) & 7); */
+/* OBSOLETE break; */
+/* OBSOLETE case 'v': */
+/* OBSOLETE fprintf (stream, "b%d", (best >> (7 + i)) & 7); */
+/* OBSOLETE break; */
+/* OBSOLETE case 'V': */
+/* OBSOLETE fprintf (stream, "b%d", (best >> (4 + i)) & 7); */
+/* OBSOLETE break; */
+/* OBSOLETE case 'X': */
+/* OBSOLETE temp = (best >> 20) & 7; */
+/* OBSOLETE if (temp) */
+/* OBSOLETE fprintf (stream, "r%d", temp); */
+/* OBSOLETE else */
+/* OBSOLETE putc ('0', stream); */
+/* OBSOLETE break; */
+/* OBSOLETE case 'A': */
+/* OBSOLETE temp = (best >> 16) & 7; */
+/* OBSOLETE if (temp) */
+/* OBSOLETE fprintf (stream, "(b%d)", temp); */
+/* OBSOLETE break; */
+/* OBSOLETE case 'S': */
+/* OBSOLETE fprintf (stream, "#%d", best & 0x1f); */
+/* OBSOLETE break; */
+/* OBSOLETE case 'I': */
+/* OBSOLETE fprintf (stream, "#%x", best & 0xffff); */
+/* OBSOLETE break; */
+/* OBSOLETE case 'O': */
+/* OBSOLETE fprintf (stream, "%x", best & 0xffff); */
+/* OBSOLETE break; */
+/* OBSOLETE case 'h': */
+/* OBSOLETE fprintf (stream, "%d", best & 0xfffe); */
+/* OBSOLETE break; */
+/* OBSOLETE case 'd': */
+/* OBSOLETE fprintf (stream, "%d", best & 0xfffc); */
+/* OBSOLETE break; */
+/* OBSOLETE case 'T': */
+/* OBSOLETE fprintf (stream, "%d", (best >> 8) & 0xff); */
+/* OBSOLETE break; */
+/* OBSOLETE case 'N': */
+/* OBSOLETE fprintf (stream, "%d", best & 0xff); */
+/* OBSOLETE break; */
+/* OBSOLETE default: */
+/* OBSOLETE putc (*d, stream); */
+/* OBSOLETE break; */
+/* OBSOLETE } */
+/* OBSOLETE } */
+/* OBSOLETE */
+/* OBSOLETE /* Return length of instruction *x/ */
+/* OBSOLETE return (gld_opcodes[index].length); */
+/* OBSOLETE } */
+/* OBSOLETE */
+/* OBSOLETE /* */
+/* OBSOLETE * Find the number of arguments to a function. */
+/* OBSOLETE *x/ */
+/* OBSOLETE findarg(frame) */
+/* OBSOLETE struct frame_info *frame; */
+/* OBSOLETE { */
+/* OBSOLETE register struct symbol *func; */
+/* OBSOLETE register unsigned pc; */
+/* OBSOLETE */
+/* OBSOLETE #ifdef notdef */
+/* OBSOLETE /* find starting address of frame function *x/ */
+/* OBSOLETE pc = get_pc_function_start (frame->pc); */
+/* OBSOLETE */
+/* OBSOLETE /* find function symbol info *x/ */
+/* OBSOLETE func = find_pc_function (pc); */
+/* OBSOLETE */
+/* OBSOLETE /* call blockframe code to look for match *x/ */
+/* OBSOLETE if (func != NULL) */
+/* OBSOLETE return (func->value.block->nsyms / sizeof(int)); */
+/* OBSOLETE #endif */
+/* OBSOLETE */
+/* OBSOLETE return (-1); */
+/* OBSOLETE } */
+/* OBSOLETE */
+/* OBSOLETE /* */
+/* OBSOLETE * In the case of the NPL, the frame's norminal address is Br2 and the */
+/* OBSOLETE * previous routines frame is up the stack X bytes. Finding out what */
+/* OBSOLETE * 'X' is can be tricky. */
+/* OBSOLETE * */
+/* OBSOLETE * 1.) stored in the code function header xA(Br1). */
+/* OBSOLETE * 2.) must be careful of recurssion. */
+/* OBSOLETE *x/ */
+/* OBSOLETE CORE_ADDR */
+/* OBSOLETE findframe(thisframe) */
+/* OBSOLETE struct frame_info *thisframe; */
+/* OBSOLETE { */
+/* OBSOLETE register CORE_ADDR pointer; */
+/* OBSOLETE CORE_ADDR framechain(); */
+/* OBSOLETE #if 0 */
+/* OBSOLETE struct frame_info *frame; */
+/* OBSOLETE */
+/* OBSOLETE /* Setup toplevel frame structure *x/ */
+/* OBSOLETE frame->pc = read_pc(); */
+/* OBSOLETE frame->next_frame = 0; */
+/* OBSOLETE frame->frame = read_register (SP_REGNUM); /* Br2 *x/ */
+/* OBSOLETE */
+/* OBSOLETE /* Search for this frame (start at current Br2) *x/ */
+/* OBSOLETE do */
+/* OBSOLETE { */
+/* OBSOLETE pointer = framechain(frame); */
+/* OBSOLETE frame->next_frame = frame->frame; */
+/* OBSOLETE frame->frame = pointer; */
+/* OBSOLETE frame->pc = FRAME_SAVED_PC(frame); */
+/* OBSOLETE } */
+/* OBSOLETE while (frame->next_frame != thisframe); */
+/* OBSOLETE #endif */
+/* OBSOLETE */
+/* OBSOLETE pointer = framechain (thisframe); */
+/* OBSOLETE */
+/* OBSOLETE /* stop gap for now, end at __base3 *x/ */
+/* OBSOLETE if (thisframe->pc == 0) */
+/* OBSOLETE return 0; */
+/* OBSOLETE */
+/* OBSOLETE return pointer; */
+/* OBSOLETE } */
+/* OBSOLETE */
+/* OBSOLETE /* */
+/* OBSOLETE * Gdb front-end and internal framechain routine. */
+/* OBSOLETE * Go back up stack one level. Tricky... */
+/* OBSOLETE *x/ */
+/* OBSOLETE CORE_ADDR */
+/* OBSOLETE framechain(frame) */
+/* OBSOLETE register struct frame_info *frame; */
+/* OBSOLETE { */
+/* OBSOLETE register CORE_ADDR func, prevsp; */
+/* OBSOLETE register unsigned value; */
+/* OBSOLETE */
+/* OBSOLETE /* Get real function start address from internal frame address *x/ */
+/* OBSOLETE func = get_pc_function_start(frame->pc); */
+/* OBSOLETE */
+/* OBSOLETE /* If no stack given, read register Br1 "(sp)" *x/ */
+/* OBSOLETE if (!frame->frame) */
+/* OBSOLETE prevsp = read_register (SP_REGNUM); */
+/* OBSOLETE else */
+/* OBSOLETE prevsp = frame->frame; */
+/* OBSOLETE */
+/* OBSOLETE /* Check function header, case #2 *x/ */
+/* OBSOLETE value = read_memory_integer (func, 4); */
+/* OBSOLETE if (value) */
+/* OBSOLETE { */
+/* OBSOLETE /* 32bit call push value stored in function header *x/ */
+/* OBSOLETE prevsp += value; */
+/* OBSOLETE } */
+/* OBSOLETE else */
+/* OBSOLETE { */
+/* OBSOLETE /* read half-word from suabr at start of function *x/ */
+/* OBSOLETE prevsp += read_memory_integer (func + 10, 2); */
+/* OBSOLETE } */
+/* OBSOLETE */
+/* OBSOLETE return (prevsp); */
+/* OBSOLETE } */
diff --git a/gdb/gould-xdep.c b/gdb/gould-xdep.c
new file mode 100644
index 00000000000..904758fa8b4
--- /dev/null
+++ b/gdb/gould-xdep.c
@@ -0,0 +1,130 @@
+/* OBSOLETE /* Low level interface to ptrace, for GDB when running under Unix. */
+/* OBSOLETE Copyright (C) 1986, 1987, 1989, 1991 Free Software Foundation, Inc. */
+/* OBSOLETE */
+/* OBSOLETE This file is part of GDB. */
+/* OBSOLETE */
+/* OBSOLETE This program is free software; you can redistribute it and/or modify */
+/* OBSOLETE it under the terms of the GNU General Public License as published by */
+/* OBSOLETE the Free Software Foundation; either version 2 of the License, or */
+/* OBSOLETE (at your option) any later version. */
+/* OBSOLETE */
+/* OBSOLETE This program is distributed in the hope that it will be useful, */
+/* OBSOLETE but WITHOUT ANY WARRANTY; without even the implied warranty of */
+/* OBSOLETE MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
+/* OBSOLETE GNU General Public License for more details. */
+/* OBSOLETE */
+/* OBSOLETE You should have received a copy of the GNU General Public License */
+/* OBSOLETE along with this program; if not, write to the Free Software */
+/* OBSOLETE Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *x/ */
+/* OBSOLETE */
+/* OBSOLETE #include "defs.h" */
+/* OBSOLETE #include "frame.h" */
+/* OBSOLETE #include "inferior.h" */
+/* OBSOLETE */
+/* OBSOLETE #include <sys/param.h> */
+/* OBSOLETE #include <sys/dir.h> */
+/* OBSOLETE #include <signal.h> */
+/* OBSOLETE #include <sys/user.h> */
+/* OBSOLETE #include <sys/ioctl.h> */
+/* OBSOLETE #include <fcntl.h> */
+/* OBSOLETE */
+/* OBSOLETE #include "gdbcore.h" */
+/* OBSOLETE */
+/* OBSOLETE #include <sys/file.h> */
+/* OBSOLETE #include "gdb_stat.h" */
+/* OBSOLETE */
+/* OBSOLETE */
+/* OBSOLETE /* Work with core dump and executable files, for GDB. */
+/* OBSOLETE This code would be in corefile.c if it weren't machine-dependent. *x/ */
+/* OBSOLETE */
+/* OBSOLETE void */
+/* OBSOLETE core_file_command (filename, from_tty) */
+/* OBSOLETE char *filename; */
+/* OBSOLETE int from_tty; */
+/* OBSOLETE { */
+/* OBSOLETE int val; */
+/* OBSOLETE extern char registers[]; */
+/* OBSOLETE */
+/* OBSOLETE /* Discard all vestiges of any previous core file */
+/* OBSOLETE and mark data and stack spaces as empty. *x/ */
+/* OBSOLETE */
+/* OBSOLETE if (corefile) */
+/* OBSOLETE free (corefile); */
+/* OBSOLETE corefile = 0; */
+/* OBSOLETE */
+/* OBSOLETE if (corechan >= 0) */
+/* OBSOLETE close (corechan); */
+/* OBSOLETE corechan = -1; */
+/* OBSOLETE */
+/* OBSOLETE data_start = 0; */
+/* OBSOLETE data_end = 0; */
+/* OBSOLETE stack_start = STACK_END_ADDR; */
+/* OBSOLETE stack_end = STACK_END_ADDR; */
+/* OBSOLETE */
+/* OBSOLETE /* Now, if a new core file was specified, open it and digest it. *x/ */
+/* OBSOLETE */
+/* OBSOLETE if (filename) */
+/* OBSOLETE { */
+/* OBSOLETE filename = tilde_expand (filename); */
+/* OBSOLETE make_cleanup (free, filename); */
+/* OBSOLETE */
+/* OBSOLETE if (have_inferior_p ()) */
+/* OBSOLETE error ("To look at a core file, you must kill the program with \"kill\"."); */
+/* OBSOLETE corechan = open (filename, O_RDONLY, 0); */
+/* OBSOLETE if (corechan < 0) */
+/* OBSOLETE perror_with_name (filename); */
+/* OBSOLETE /* 4.2-style (and perhaps also sysV-style) core dump file. *x/ */
+/* OBSOLETE { */
+/* OBSOLETE struct user u; */
+/* OBSOLETE int reg_offset; */
+/* OBSOLETE */
+/* OBSOLETE val = myread (corechan, &u, sizeof u); */
+/* OBSOLETE if (val < 0) */
+/* OBSOLETE perror_with_name (filename); */
+/* OBSOLETE data_start = exec_data_start; */
+/* OBSOLETE */
+/* OBSOLETE data_end = data_start + NBPG * u.u_dsize; */
+/* OBSOLETE stack_start = stack_end - NBPG * u.u_ssize; */
+/* OBSOLETE data_offset = NBPG * UPAGES; */
+/* OBSOLETE stack_offset = NBPG * (UPAGES + u.u_dsize); */
+/* OBSOLETE reg_offset = (int) u.u_ar0 - KERNEL_U_ADDR; */
+/* OBSOLETE */
+/* OBSOLETE /* I don't know where to find this info. */
+/* OBSOLETE So, for now, mark it as not available. *x/ */
+/* OBSOLETE core_aouthdr.a_magic = 0; */
+/* OBSOLETE */
+/* OBSOLETE /* Read the register values out of the core file and store */
+/* OBSOLETE them where `read_register' will find them. *x/ */
+/* OBSOLETE */
+/* OBSOLETE { */
+/* OBSOLETE register int regno; */
+/* OBSOLETE */
+/* OBSOLETE for (regno = 0; regno < NUM_REGS; regno++) */
+/* OBSOLETE { */
+/* OBSOLETE char buf[MAX_REGISTER_RAW_SIZE]; */
+/* OBSOLETE */
+/* OBSOLETE val = lseek (corechan, register_addr (regno, reg_offset), 0); */
+/* OBSOLETE if (val < 0) */
+/* OBSOLETE perror_with_name (filename); */
+/* OBSOLETE */
+/* OBSOLETE val = myread (corechan, buf, sizeof buf); */
+/* OBSOLETE if (val < 0) */
+/* OBSOLETE perror_with_name (filename); */
+/* OBSOLETE supply_register (regno, buf); */
+/* OBSOLETE } */
+/* OBSOLETE } */
+/* OBSOLETE } */
+/* OBSOLETE if (filename[0] == '/') */
+/* OBSOLETE corefile = savestring (filename, strlen (filename)); */
+/* OBSOLETE else */
+/* OBSOLETE { */
+/* OBSOLETE corefile = concat (current_directory, "/", filename, NULL); */
+/* OBSOLETE } */
+/* OBSOLETE */
+/* OBSOLETE flush_cached_frames (); */
+/* OBSOLETE select_frame (get_current_frame (), 0); */
+/* OBSOLETE validate_files (); */
+/* OBSOLETE } */
+/* OBSOLETE else if (from_tty) */
+/* OBSOLETE printf ("No core file now.\n"); */
+/* OBSOLETE } */
diff --git a/gdb/h8300-tdep.c b/gdb/h8300-tdep.c
new file mode 100644
index 00000000000..3fbe9e1bb28
--- /dev/null
+++ b/gdb/h8300-tdep.c
@@ -0,0 +1,921 @@
+/* Target-machine dependent code for Hitachi H8/300, for GDB.
+ Copyright (C) 1988, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/*
+ Contributed by Steve Chamberlain
+ sac@cygnus.com
+ */
+
+#include "defs.h"
+#include "frame.h"
+#include "obstack.h"
+#include "symtab.h"
+#include "dis-asm.h"
+#include "gdbcmd.h"
+#include "gdbtypes.h"
+#include "gdbcore.h"
+#include "gdb_string.h"
+#include "value.h"
+
+extern int h8300hmode, h8300smode;
+
+#undef NUM_REGS
+#define NUM_REGS 11
+
+#define UNSIGNED_SHORT(X) ((X) & 0xffff)
+
+#define IS_PUSH(x) ((x & 0xfff0)==0x6df0)
+#define IS_PUSH_FP(x) (x == 0x6df6)
+#define IS_MOVE_FP(x) (x == 0x0d76 || x == 0x0ff6)
+#define IS_MOV_SP_FP(x) (x == 0x0d76 || x == 0x0ff6)
+#define IS_SUB2_SP(x) (x==0x1b87)
+#define IS_SUB4_SP(x) (x==0x1b97)
+#define IS_SUBL_SP(x) (x==0x7a37)
+#define IS_MOVK_R5(x) (x==0x7905)
+#define IS_SUB_R5SP(x) (x==0x1957)
+
+
+/* The register names change depending on whether the h8300h processor
+ type is selected. */
+
+static char *original_register_names[] = REGISTER_NAMES;
+
+static char *h8300h_register_names[] =
+ {"er0", "er1", "er2", "er3", "er4", "er5", "er6",
+ "sp", "ccr","pc","cycles","tick","inst" };
+
+char **h8300_register_names = original_register_names;
+
+
+/* Local function declarations. */
+
+static CORE_ADDR examine_prologue ();
+static void set_machine_hook PARAMS ((char *filename));
+
+void h8300_frame_find_saved_regs ();
+
+CORE_ADDR
+h8300_skip_prologue (start_pc)
+ CORE_ADDR start_pc;
+{
+ short int w;
+ int adjust = 0;
+
+ /* Skip past all push and stm insns. */
+ while (1)
+ {
+ w = read_memory_unsigned_integer (start_pc, 2);
+ /* First look for push insns. */
+ if (w == 0x0100 || w == 0x0110 || w == 0x0120 || w == 0x0130)
+ {
+ w = read_memory_unsigned_integer (start_pc + 2, 2);
+ adjust = 2;
+ }
+
+ if (IS_PUSH (w))
+ {
+ start_pc += 2 + adjust;
+ w = read_memory_unsigned_integer (start_pc, 2);
+ continue;
+ }
+ adjust = 0;
+ break;
+ }
+
+ /* Skip past a move to FP, either word or long sized */
+ w = read_memory_unsigned_integer (start_pc, 2);
+ if (w == 0x0100)
+ {
+ w = read_memory_unsigned_integer (start_pc + 2, 2);
+ adjust += 2;
+ }
+
+ if (IS_MOVE_FP (w))
+ {
+ start_pc += 2 + adjust;
+ w = read_memory_unsigned_integer (start_pc, 2);
+ }
+
+ /* Check for loading either a word constant into r5;
+ long versions are handled by the SUBL_SP below. */
+ if (IS_MOVK_R5 (w))
+ {
+ start_pc += 2;
+ w = read_memory_unsigned_integer (start_pc, 2);
+ }
+
+ /* Now check for subtracting r5 from sp, word sized only. */
+ if (IS_SUB_R5SP (w))
+ {
+ start_pc += 2 + adjust;
+ w = read_memory_unsigned_integer (start_pc, 2);
+ }
+
+ /* Check for subs #2 and subs #4. */
+ while (IS_SUB2_SP (w) || IS_SUB4_SP (w))
+ {
+ start_pc += 2 + adjust;
+ w = read_memory_unsigned_integer (start_pc, 2);
+ }
+
+ /* Check for a 32bit subtract. */
+ if (IS_SUBL_SP (w))
+ start_pc += 6 + adjust;
+
+ return start_pc;
+}
+
+int
+gdb_print_insn_h8300 (memaddr, info)
+ bfd_vma memaddr;
+ disassemble_info *info;
+{
+ if (h8300smode)
+ return print_insn_h8300s (memaddr, info);
+ else if (h8300hmode)
+ return print_insn_h8300h (memaddr, info);
+ else
+ return print_insn_h8300 (memaddr, info);
+}
+
+/* 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
+ INIT_EXTRA_FRAME_INFO and INIT_FRAME_PC will be called for the new frame.
+
+ For us, the frame address is its stack pointer value, so we look up
+ the function prologue to determine the caller's sp value, and return it. */
+
+CORE_ADDR
+h8300_frame_chain (thisframe)
+ struct frame_info *thisframe;
+{
+ if (PC_IN_CALL_DUMMY(thisframe->pc, thisframe->frame, thisframe->frame))
+ { /* initialize the from_pc now */
+ thisframe->from_pc = generic_read_register_dummy (thisframe->pc,
+ thisframe->frame,
+ PC_REGNUM);
+ return thisframe->frame;
+ }
+ h8300_frame_find_saved_regs (thisframe, (struct frame_saved_regs *) 0);
+ return thisframe->fsr->regs[SP_REGNUM];
+}
+
+/* Put here the code to store, into a struct frame_saved_regs,
+ the addresses of the saved registers of frame described by FRAME_INFO.
+ This includes special registers such as pc and fp saved in special
+ ways in the stack frame. sp is even more special:
+ the address we return for it IS the sp for the next frame.
+
+ We cache the result of doing this in the frame_obstack, since it is
+ fairly expensive. */
+
+void
+h8300_frame_find_saved_regs (fi, fsr)
+ struct frame_info *fi;
+ struct frame_saved_regs *fsr;
+{
+ register struct frame_saved_regs *cache_fsr;
+ CORE_ADDR ip;
+ struct symtab_and_line sal;
+ CORE_ADDR limit;
+
+ if (!fi->fsr)
+ {
+ cache_fsr = (struct frame_saved_regs *)
+ frame_obstack_alloc (sizeof (struct frame_saved_regs));
+ memset (cache_fsr, '\0', sizeof (struct frame_saved_regs));
+
+ fi->fsr = cache_fsr;
+
+ if (PC_IN_CALL_DUMMY(fi->pc, fi->frame, fi->frame))
+ { /* no more to do. */
+ if (fsr)
+ *fsr = *fi->fsr;
+ return;
+ }
+ /* Find the start and end of the function prologue. If the PC
+ is in the function prologue, we only consider the part that
+ has executed already. */
+
+ ip = get_pc_function_start (fi->pc);
+ sal = find_pc_line (ip, 0);
+ limit = (sal.end && sal.end < fi->pc) ? sal.end : fi->pc;
+
+ /* This will fill in fields in *fi as well as in cache_fsr. */
+ examine_prologue (ip, limit, fi->frame, cache_fsr, fi);
+ }
+
+ if (fsr)
+ *fsr = *fi->fsr;
+}
+
+/* Fetch the instruction at ADDR, returning 0 if ADDR is beyond LIM or
+ is not the address of a valid instruction, the address of the next
+ instruction beyond ADDR otherwise. *PWORD1 receives the first word
+ of the instruction.*/
+
+CORE_ADDR
+NEXT_PROLOGUE_INSN (addr, lim, pword1)
+ CORE_ADDR addr;
+ CORE_ADDR lim;
+ INSN_WORD *pword1;
+{
+ char buf[2];
+ if (addr < lim + 8)
+ {
+ read_memory (addr, buf, 2);
+ *pword1 = extract_signed_integer (buf, 2);
+
+ return addr + 2;
+ }
+ return 0;
+}
+
+/* Examine the prologue of a function. `ip' points to the first instruction.
+ `limit' is the limit of the prologue (e.g. the addr of the first
+ linenumber, or perhaps the program counter if we're stepping through).
+ `frame_sp' is the stack pointer value in use in this frame.
+ `fsr' is a pointer to a frame_saved_regs structure into which we put
+ info about the registers saved by this frame.
+ `fi' is a struct frame_info pointer; we fill in various fields in it
+ to reflect the offsets of the arg pointer and the locals pointer. */
+
+static CORE_ADDR
+examine_prologue (ip, limit, after_prolog_fp, fsr, fi)
+ register CORE_ADDR ip;
+ register CORE_ADDR limit;
+ CORE_ADDR after_prolog_fp;
+ struct frame_saved_regs *fsr;
+ struct frame_info *fi;
+{
+ register CORE_ADDR next_ip;
+ int r;
+ int have_fp = 0;
+ INSN_WORD insn_word;
+ /* Number of things pushed onto stack, starts at 2/4, 'cause the
+ PC is already there */
+ unsigned int reg_save_depth = h8300hmode ? 4 : 2;
+
+ unsigned int auto_depth = 0; /* Number of bytes of autos */
+
+ char in_frame[11]; /* One for each reg */
+
+ int adjust = 0;
+
+ memset (in_frame, 1, 11);
+ for (r = 0; r < 8; r++)
+ {
+ fsr->regs[r] = 0;
+ }
+ if (after_prolog_fp == 0)
+ {
+ after_prolog_fp = read_register (SP_REGNUM);
+ }
+
+ /* If the PC isn't valid, quit now. */
+ if (ip == 0 || ip & (h8300hmode ? ~0xffffff : ~0xffff))
+ return 0;
+
+ next_ip = NEXT_PROLOGUE_INSN (ip, limit, &insn_word);
+
+ if (insn_word == 0x0100)
+ {
+ insn_word = read_memory_unsigned_integer (ip + 2, 2);
+ adjust = 2;
+ }
+
+ /* Skip over any fp push instructions */
+ fsr->regs[6] = after_prolog_fp;
+ while (next_ip && IS_PUSH_FP (insn_word))
+ {
+ ip = next_ip + adjust;
+
+ in_frame[insn_word & 0x7] = reg_save_depth;
+ next_ip = NEXT_PROLOGUE_INSN (ip, limit, &insn_word);
+ reg_save_depth += 2 + adjust;
+ }
+
+ /* Is this a move into the fp */
+ if (next_ip && IS_MOV_SP_FP (insn_word))
+ {
+ ip = next_ip;
+ next_ip = NEXT_PROLOGUE_INSN (ip, limit, &insn_word);
+ have_fp = 1;
+ }
+
+ /* Skip over any stack adjustment, happens either with a number of
+ sub#2,sp or a mov #x,r5 sub r5,sp */
+
+ if (next_ip && (IS_SUB2_SP (insn_word) || IS_SUB4_SP (insn_word)))
+ {
+ while (next_ip && (IS_SUB2_SP (insn_word) || IS_SUB4_SP (insn_word)))
+ {
+ auto_depth += IS_SUB2_SP (insn_word) ? 2 : 4;
+ ip = next_ip;
+ next_ip = NEXT_PROLOGUE_INSN (ip, limit, &insn_word);
+ }
+ }
+ else
+ {
+ if (next_ip && IS_MOVK_R5 (insn_word))
+ {
+ ip = next_ip;
+ next_ip = NEXT_PROLOGUE_INSN (ip, limit, &insn_word);
+ auto_depth += insn_word;
+
+ next_ip = NEXT_PROLOGUE_INSN (next_ip, limit, &insn_word);
+ auto_depth += insn_word;
+ }
+ if (next_ip && IS_SUBL_SP (insn_word))
+ {
+ ip = next_ip;
+ auto_depth += read_memory_unsigned_integer (ip, 4);
+ ip += 4;
+
+ next_ip = NEXT_PROLOGUE_INSN (ip, limit, &insn_word);
+ }
+ }
+
+ /* Now examine the push insns to determine where everything lives
+ on the stack. */
+ while (1)
+ {
+ adjust = 0;
+ if (!next_ip)
+ break;
+
+ if (insn_word == 0x0100)
+ {
+ ip = next_ip;
+ next_ip = NEXT_PROLOGUE_INSN (ip, limit, &insn_word);
+ adjust = 2;
+ }
+
+ if (IS_PUSH (insn_word))
+ {
+ ip = next_ip;
+ next_ip = NEXT_PROLOGUE_INSN (ip, limit, &insn_word);
+ fsr->regs[r] = after_prolog_fp + auto_depth;
+ auto_depth += 2 + adjust;
+ continue;
+ }
+
+ /* Now check for push multiple insns. */
+ if (insn_word == 0x0110 || insn_word == 0x0120 || insn_word == 0x0130)
+ {
+ int count = ((insn_word >> 4) & 0xf) + 1;
+ int start, i;
+
+ ip = next_ip;
+ next_ip = NEXT_PROLOGUE_INSN (ip, limit, &insn_word);
+ start = insn_word & 0x7;
+
+ for (i = start; i <= start + count; i++)
+ {
+ fsr->regs[i] = after_prolog_fp + auto_depth;
+ auto_depth += 4;
+ }
+ }
+ break;
+ }
+
+ /* The args are always reffed based from the stack pointer */
+ fi->args_pointer = after_prolog_fp;
+ /* Locals are always reffed based from the fp */
+ fi->locals_pointer = after_prolog_fp;
+ /* The PC is at a known place */
+ fi->from_pc = read_memory_unsigned_integer (after_prolog_fp + BINWORD, BINWORD);
+
+ /* Rememeber any others too */
+ in_frame[PC_REGNUM] = 0;
+
+ if (have_fp)
+ /* We keep the old FP in the SP spot */
+ fsr->regs[SP_REGNUM] = read_memory_unsigned_integer (fsr->regs[6], BINWORD);
+ else
+ fsr->regs[SP_REGNUM] = after_prolog_fp + auto_depth;
+
+ return (ip);
+}
+
+void
+h8300_init_extra_frame_info (fromleaf, fi)
+ int fromleaf;
+ struct frame_info *fi;
+{
+ fi->fsr = 0; /* Not yet allocated */
+ fi->args_pointer = 0; /* Unknown */
+ fi->locals_pointer = 0; /* Unknown */
+ fi->from_pc = 0;
+ if (PC_IN_CALL_DUMMY(fi->pc, fi->frame, fi->frame))
+ { /* anything special to do? */
+ return;
+ }
+}
+
+/* Return the saved PC from this frame.
+
+ If the frame has a memory copy of SRP_REGNUM, use that. If not,
+ just use the register SRP_REGNUM itself. */
+
+CORE_ADDR
+h8300_frame_saved_pc (frame)
+ struct frame_info *frame;
+{
+ if (PC_IN_CALL_DUMMY(frame->pc, frame->frame, frame->frame))
+ return generic_read_register_dummy (frame->pc, frame->frame, PC_REGNUM);
+ else
+ return frame->from_pc;
+}
+
+CORE_ADDR
+frame_locals_address (fi)
+ struct frame_info *fi;
+{
+ if (PC_IN_CALL_DUMMY(fi->pc, fi->frame, fi->frame))
+ return (CORE_ADDR) 0; /* Not sure what else to do... */
+ if (!fi->locals_pointer)
+ {
+ struct frame_saved_regs ignore;
+
+ get_frame_saved_regs (fi, &ignore);
+
+ }
+ return fi->locals_pointer;
+}
+
+/* Return the address of the argument block for the frame
+ described by FI. Returns 0 if the address is unknown. */
+
+CORE_ADDR
+frame_args_address (fi)
+ struct frame_info *fi;
+{
+ if (PC_IN_CALL_DUMMY(fi->pc, fi->frame, fi->frame))
+ return (CORE_ADDR) 0; /* Not sure what else to do... */
+ if (!fi->args_pointer)
+ {
+ struct frame_saved_regs ignore;
+
+ get_frame_saved_regs (fi, &ignore);
+
+ }
+
+ return fi->args_pointer;
+}
+
+/* Function: push_arguments
+ Setup the function arguments for calling a function in the inferior.
+
+ On the Hitachi H8/300 architecture, there are three registers (R0 to R2)
+ which are dedicated for passing function arguments. Up to the first
+ three arguments (depending on size) may go into these registers.
+ The rest go on the stack.
+
+ Arguments that are smaller than WORDSIZE bytes will still take up a
+ whole register or a whole WORDSIZE word on the stack, and will be
+ right-justified in the register or the stack word. This includes
+ chars and small aggregate types. Note that WORDSIZE depends on the
+ cpu type.
+
+ Arguments that are larger than WORDSIZE bytes will be split between
+ two or more registers as available, but will NOT be split between a
+ register and the stack.
+
+ An exceptional case exists for struct arguments (and possibly other
+ aggregates such as arrays) -- if the size is larger than WORDSIZE
+ bytes but not a multiple of WORDSIZE bytes. In this case the
+ argument is never split between the registers and the stack, but
+ instead is copied in its entirety onto the stack, AND also copied
+ into as many registers as there is room for. In other words, space
+ in registers permitting, two copies of the same argument are passed
+ in. As far as I can tell, only the one on the stack is used,
+ although that may be a function of the level of compiler
+ optimization. I suspect this is a compiler bug. Arguments of
+ these odd sizes are left-justified within the word (as opposed to
+ arguments smaller than WORDSIZE bytes, which are right-justified).
+
+ If the function is to return an aggregate type such as a struct,
+ the caller must allocate space into which the callee will copy the
+ return value. In this case, a pointer to the return value location
+ is passed into the callee in register R0, which displaces one of
+ the other arguments passed in via registers R0 to R2. */
+
+CORE_ADDR
+h8300_push_arguments(nargs, args, sp, struct_return, struct_addr)
+ int nargs;
+ struct value **args;
+ CORE_ADDR sp;
+ unsigned char struct_return;
+ CORE_ADDR struct_addr;
+{
+ int stack_align, stack_alloc, stack_offset;
+ int wordsize;
+ int argreg;
+ int argnum;
+ struct type *type;
+ CORE_ADDR regval;
+ char *val;
+ char valbuf[4];
+ int len;
+
+ if (h8300hmode || h8300smode)
+ {
+ stack_align = 3;
+ wordsize = 4;
+ }
+ else
+ {
+ stack_align = 1;
+ wordsize = 2;
+ }
+
+ /* first force sp to a n-byte alignment */
+ sp = sp & ~stack_align;
+
+ /* Now make sure there's space on the stack */
+ for (argnum = 0, stack_alloc = 0;
+ argnum < nargs; argnum++)
+ stack_alloc += ((TYPE_LENGTH(VALUE_TYPE(args[argnum])) + stack_align)
+ & ~stack_align);
+ sp -= stack_alloc; /* make room on stack for args */
+ /* we may over-allocate a little here, but that won't hurt anything */
+
+ argreg = ARG0_REGNUM;
+ if (struct_return) /* "struct return" pointer takes up one argreg */
+ {
+ write_register (argreg++, struct_addr);
+ }
+
+ /* Now load as many as possible of the first arguments into
+ registers, and push the rest onto the stack. There are 3N bytes
+ in three registers available. Loop thru args from first to last. */
+
+ for (argnum = 0, stack_offset = 0; argnum < nargs; argnum++)
+ {
+ type = VALUE_TYPE (args[argnum]);
+ len = TYPE_LENGTH (type);
+ memset(valbuf, 0, sizeof(valbuf));
+ if (len < wordsize)
+ {
+ /* the purpose of this is to right-justify the value within the word */
+ memcpy(valbuf + (wordsize - len),
+ (char *) VALUE_CONTENTS (args[argnum]), len);
+ val = valbuf;
+ }
+ else
+ val = (char *) VALUE_CONTENTS (args[argnum]);
+
+ if (len > (ARGLAST_REGNUM+1 - argreg) * REGISTER_RAW_SIZE(ARG0_REGNUM) ||
+ (len > wordsize && (len & stack_align) != 0))
+ { /* passed on the stack */
+ write_memory (sp + stack_offset, val,
+ len < wordsize ? wordsize : len);
+ stack_offset += (len + stack_align) & ~stack_align;
+ }
+ /* NOTE WELL!!!!! This is not an "else if" clause!!!
+ That's because some *&^%$ things get passed on the stack
+ AND in the registers! */
+ if (len <= (ARGLAST_REGNUM+1 - argreg) * REGISTER_RAW_SIZE(ARG0_REGNUM))
+ while (len > 0)
+ { /* there's room in registers */
+ regval = extract_address (val, wordsize);
+ write_register (argreg, regval);
+ len -= wordsize;
+ val += wordsize;
+ argreg++;
+ }
+ }
+ return sp;
+}
+
+/* Function: push_return_address
+ Setup the return address for a dummy frame, as called by
+ call_function_by_hand. Only necessary when you are using an
+ empty CALL_DUMMY, ie. the target will not actually be executing
+ a JSR/BSR instruction. */
+
+CORE_ADDR
+h8300_push_return_address (pc, sp)
+ CORE_ADDR pc;
+ CORE_ADDR sp;
+{
+ unsigned char buf[4];
+ int wordsize;
+
+ if (h8300hmode || h8300smode)
+ wordsize = 4;
+ else
+ wordsize = 2;
+
+ sp -= wordsize;
+ store_unsigned_integer (buf, wordsize, CALL_DUMMY_ADDRESS ());
+ write_memory (sp, buf, wordsize);
+ return sp;
+}
+
+/* Function: pop_frame
+ Restore the machine to the state it had before the current frame
+ was created. Usually used either by the "RETURN" command, or by
+ call_function_by_hand after the dummy_frame is finished. */
+
+void
+h8300_pop_frame ()
+{
+ unsigned regnum;
+ struct frame_saved_regs fsr;
+ struct frame_info *frame = get_current_frame ();
+
+ if (PC_IN_CALL_DUMMY(frame->pc, frame->frame, frame->frame))
+ {
+ generic_pop_dummy_frame();
+ }
+ else
+ {
+ get_frame_saved_regs (frame, &fsr);
+
+ for (regnum = 0; regnum < 8; regnum++)
+ {
+ /* Don't forget SP_REGNUM is a frame_saved_regs struct is the
+ actual value we want, not the address of the value we want. */
+ if (fsr.regs[regnum] && regnum != SP_REGNUM)
+ write_register (regnum,
+ read_memory_integer(fsr.regs[regnum], BINWORD));
+ else if (fsr.regs[regnum] && regnum == SP_REGNUM)
+ write_register (regnum, frame->frame + 2 * BINWORD);
+ }
+
+ /* Don't forget the update the PC too! */
+ write_pc (frame->from_pc);
+ }
+ flush_cached_frames ();
+}
+
+/* Function: extract_return_value
+ Figure out where in REGBUF the called function has left its return value.
+ Copy that into VALBUF. Be sure to account for CPU type. */
+
+void
+h8300_extract_return_value (type, regbuf, valbuf)
+ struct type *type;
+ char *regbuf;
+ char *valbuf;
+{
+ int wordsize, len;
+
+ if (h8300smode || h8300hmode)
+ wordsize = 4;
+ else
+ wordsize = 2;
+
+ len = TYPE_LENGTH(type);
+
+ switch (len) {
+ case 1: /* (char) */
+ case 2: /* (short), (int) */
+ memcpy (valbuf, regbuf + REGISTER_BYTE(0) + (wordsize - len), len);
+ break;
+ case 4: /* (long), (float) */
+ if (h8300smode || h8300hmode)
+ {
+ memcpy (valbuf, regbuf + REGISTER_BYTE(0), 4);
+ }
+ else
+ {
+ memcpy (valbuf, regbuf + REGISTER_BYTE(0), 2);
+ memcpy (valbuf+2, regbuf + REGISTER_BYTE(1), 2);
+ }
+ break;
+ case 8: /* (double) (doesn't seem to happen, which is good,
+ because this almost certainly isn't right. */
+ error ("I don't know how a double is returned.");
+ break;
+ }
+}
+
+/* Function: store_return_value
+ Place the appropriate value in the appropriate registers.
+ Primarily used by the RETURN command. */
+
+void
+h8300_store_return_value (type, valbuf)
+ struct type *type;
+ char *valbuf;
+{
+ int wordsize, len, regval;
+
+ if (h8300hmode || h8300smode)
+ wordsize = 4;
+ else
+ wordsize = 2;
+
+ len = TYPE_LENGTH(type);
+ switch (len) {
+ case 1: /* char */
+ case 2: /* short, int */
+ regval = extract_address(valbuf, len);
+ write_register (0, regval);
+ break;
+ case 4: /* long, float */
+ regval = extract_address(valbuf, len);
+ if (h8300smode || h8300hmode)
+ {
+ write_register (0, regval);
+ }
+ else
+ {
+ write_register (0, regval >> 16);
+ write_register (1, regval & 0xffff);
+ }
+ break;
+ case 8: /* presumeably double, but doesn't seem to happen */
+ error ("I don't know how to return a double.");
+ break;
+ }
+}
+
+/* Function: get_saved_register
+ Just call the generic_get_saved_register function. */
+
+void
+get_saved_register (raw_buffer, optimized, addrp, frame, regnum, lval)
+ char *raw_buffer;
+ int *optimized;
+ CORE_ADDR *addrp;
+ struct frame_info *frame;
+ int regnum;
+ enum lval_type *lval;
+{
+ generic_get_saved_register (raw_buffer, optimized, addrp,
+ frame, regnum, lval);
+}
+
+struct cmd_list_element *setmemorylist;
+
+static void
+set_register_names ()
+{
+ if (h8300hmode != 0)
+ h8300_register_names = h8300h_register_names;
+ else
+ h8300_register_names = original_register_names;
+}
+
+static void
+h8300_command(args, from_tty)
+{
+ extern int h8300hmode;
+ h8300hmode = 0;
+ h8300smode = 0;
+ set_register_names ();
+}
+
+static void
+h8300h_command(args, from_tty)
+{
+ extern int h8300hmode;
+ h8300hmode = 1;
+ h8300smode = 0;
+ set_register_names ();
+}
+
+static void
+h8300s_command(args, from_tty)
+{
+ extern int h8300smode;
+ extern int h8300hmode;
+ h8300smode = 1;
+ h8300hmode = 1;
+ set_register_names ();
+}
+
+
+static void
+set_machine (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ printf_unfiltered ("\"set machine\" must be followed by h8300, h8300h");
+ printf_unfiltered ("or h8300s");
+ help_list (setmemorylist, "set memory ", -1, gdb_stdout);
+}
+
+/* set_machine_hook is called as the exec file is being opened, but
+ before the symbol file is opened. This allows us to set the
+ h8300hmode flag based on the machine type specified in the exec
+ file. This in turn will cause subsequently defined pointer types
+ to be 16 or 32 bits as appropriate for the machine. */
+
+static void
+set_machine_hook (filename)
+ char *filename;
+{
+ if (bfd_get_mach (exec_bfd) == bfd_mach_h8300s)
+ {
+ h8300smode = 1;
+ h8300hmode = 1;
+ }
+ else
+ if (bfd_get_mach (exec_bfd) == bfd_mach_h8300h)
+ {
+ h8300smode = 0;
+ h8300hmode = 1;
+ }
+ else
+ {
+ h8300smode = 0;
+ h8300hmode = 0;
+ }
+ set_register_names ();
+}
+
+void
+_initialize_h8300m ()
+{
+ add_prefix_cmd ("machine", no_class, set_machine,
+ "set the machine type",
+ &setmemorylist, "set machine ", 0,
+ &setlist);
+
+ add_cmd ("h8300", class_support, h8300_command,
+ "Set machine to be H8/300.", &setmemorylist);
+
+ add_cmd ("h8300h", class_support, h8300h_command,
+ "Set machine to be H8/300H.", &setmemorylist);
+
+ add_cmd ("h8300s", class_support, h8300s_command,
+ "Set machine to be H8/300S.", &setmemorylist);
+
+ /* Add a hook to set the machine type when we're loading a file. */
+
+ specify_exec_file_hook(set_machine_hook);
+}
+
+
+
+void
+print_register_hook (regno)
+{
+ if (regno == 8)
+ {
+ /* CCR register */
+ int C, Z, N, V;
+ unsigned char b[4];
+ unsigned char l;
+ read_relative_register_raw_bytes (regno, b);
+ l = b[REGISTER_VIRTUAL_SIZE(8) -1];
+ printf_unfiltered ("\t");
+ printf_unfiltered ("I-%d - ", (l & 0x80) != 0);
+ printf_unfiltered ("H-%d - ", (l & 0x20) != 0);
+ N = (l & 0x8) != 0;
+ Z = (l & 0x4) != 0;
+ V = (l & 0x2) != 0;
+ C = (l & 0x1) != 0;
+ printf_unfiltered ("N-%d ", N);
+ printf_unfiltered ("Z-%d ", Z);
+ printf_unfiltered ("V-%d ", V);
+ printf_unfiltered ("C-%d ", C);
+ if ((C | Z) == 0)
+ printf_unfiltered ("u> ");
+ if ((C | Z) == 1)
+ printf_unfiltered ("u<= ");
+ if ((C == 0))
+ printf_unfiltered ("u>= ");
+ if (C == 1)
+ printf_unfiltered ("u< ");
+ if (Z == 0)
+ printf_unfiltered ("!= ");
+ if (Z == 1)
+ printf_unfiltered ("== ");
+ if ((N ^ V) == 0)
+ printf_unfiltered (">= ");
+ if ((N ^ V) == 1)
+ printf_unfiltered ("< ");
+ if ((Z | (N ^ V)) == 0)
+ printf_unfiltered ("> ");
+ if ((Z | (N ^ V)) == 1)
+ printf_unfiltered ("<= ");
+ }
+}
+
+void
+_initialize_h8300_tdep ()
+{
+ tm_print_insn = gdb_print_insn_h8300;
+}
diff --git a/gdb/h8500-tdep.c b/gdb/h8500-tdep.c
new file mode 100644
index 00000000000..49fab2d54e5
--- /dev/null
+++ b/gdb/h8500-tdep.c
@@ -0,0 +1,653 @@
+/* Target-dependent code for Hitachi H8/500, for GDB.
+ Copyright 1993, 1994, 1995 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/*
+ Contributed by Steve Chamberlain
+ sac@cygnus.com
+ */
+
+#include "defs.h"
+#include "frame.h"
+#include "obstack.h"
+#include "symtab.h"
+#include "gdbtypes.h"
+#include "gdbcmd.h"
+#include "value.h"
+#include "dis-asm.h"
+#include "gdbcore.h"
+
+#define UNSIGNED_SHORT(X) ((X) & 0xffff)
+
+static int code_size = 2;
+
+static int data_size = 2;
+
+/* Shape of an H8/500 frame :
+
+ arg-n
+ ..
+ arg-2
+ arg-1
+ return address <2 or 4 bytes>
+ old fp <2 bytes>
+ auto-n
+ ..
+ auto-1
+ saved registers
+
+*/
+
+/* an easy to debug H8 stack frame looks like:
+0x6df6 push r6
+0x0d76 mov.w r7,r6
+0x6dfn push reg
+0x7905 nnnn mov.w #n,r5 or 0x1b87 subs #2,sp
+0x1957 sub.w r5,sp
+
+ */
+
+#define IS_PUSH(x) (((x) & 0xff00)==0x6d00)
+#define IS_LINK_8(x) ((x) == 0x17)
+#define IS_LINK_16(x) ((x) == 0x1f)
+#define IS_MOVE_FP(x) ((x) == 0x0d76)
+#define IS_MOV_SP_FP(x) ((x) == 0x0d76)
+#define IS_SUB2_SP(x) ((x) == 0x1b87)
+#define IS_MOVK_R5(x) ((x) == 0x7905)
+#define IS_SUB_R5SP(x) ((x) == 0x1957)
+
+#define LINK_8 0x17
+#define LINK_16 0x1f
+
+int minimum_mode = 1;
+
+CORE_ADDR
+h8500_skip_prologue (start_pc)
+ CORE_ADDR start_pc;
+{
+ short int w;
+
+ w = read_memory_integer (start_pc, 1);
+ if (w == LINK_8)
+ {
+ start_pc += 2;
+ w = read_memory_integer (start_pc, 1);
+ }
+
+ if (w == LINK_16)
+ {
+ start_pc += 3;
+ w = read_memory_integer (start_pc, 2);
+ }
+
+ return start_pc;
+}
+
+CORE_ADDR
+h8500_addr_bits_remove (addr)
+ CORE_ADDR addr;
+{
+ return ((addr) & 0xffffff);
+}
+
+/* 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
+ INIT_EXTRA_FRAME_INFO and INIT_FRAME_PC will be called for the new frame.
+
+ For us, the frame address is its stack pointer value, so we look up
+ the function prologue to determine the caller's sp value, and return it. */
+
+CORE_ADDR
+h8500_frame_chain (thisframe)
+ struct frame_info *thisframe;
+{
+ if (!inside_entry_file (thisframe->pc))
+ return (read_memory_integer (FRAME_FP (thisframe), PTR_SIZE));
+ else
+ return 0;
+}
+
+/* Fetch the instruction at ADDR, returning 0 if ADDR is beyond LIM or
+ is not the address of a valid instruction, the address of the next
+ instruction beyond ADDR otherwise. *PWORD1 receives the first word
+ of the instruction.*/
+
+CORE_ADDR
+NEXT_PROLOGUE_INSN (addr, lim, pword1)
+ CORE_ADDR addr;
+ CORE_ADDR lim;
+ char *pword1;
+{
+ if (addr < lim + 8)
+ {
+ read_memory (addr, pword1, 1);
+ read_memory (addr, pword1 + 1, 1);
+ return 1;
+ }
+ return 0;
+}
+
+/* Examine the prologue of a function. `ip' points to the first
+ instruction. `limit' is the limit of the prologue (e.g. the addr
+ of the first linenumber, or perhaps the program counter if we're
+ stepping through). `frame_sp' is the stack pointer value in use in
+ this frame. `fsr' is a pointer to a frame_saved_regs structure
+ into which we put info about the registers saved by this frame.
+ `fi' is a struct frame_info pointer; we fill in various fields in
+ it to reflect the offsets of the arg pointer and the locals
+ pointer. */
+
+/* Return the saved PC from this frame. */
+
+CORE_ADDR
+frame_saved_pc (frame)
+ struct frame_info *frame;
+{
+ return read_memory_integer (FRAME_FP (frame) + 2, PTR_SIZE);
+}
+
+void
+h8500_pop_frame ()
+{
+ unsigned regnum;
+ struct frame_saved_regs fsr;
+ struct frame_info *frame = get_current_frame ();
+
+ get_frame_saved_regs (frame, &fsr);
+
+ for (regnum = 0; regnum < 8; regnum++)
+ {
+ if (fsr.regs[regnum])
+ write_register (regnum, read_memory_short (fsr.regs[regnum]));
+
+ flush_cached_frames ();
+ }
+}
+
+void
+print_register_hook (regno)
+ int regno;
+{
+ if (regno == CCR_REGNUM)
+ {
+ /* CCR register */
+
+ int C, Z, N, V;
+ unsigned char b[2];
+ unsigned char l;
+
+ read_relative_register_raw_bytes (regno, b);
+ l = b[1];
+ printf_unfiltered ("\t");
+ printf_unfiltered ("I-%d - ", (l & 0x80) != 0);
+ N = (l & 0x8) != 0;
+ Z = (l & 0x4) != 0;
+ V = (l & 0x2) != 0;
+ C = (l & 0x1) != 0;
+ printf_unfiltered ("N-%d ", N);
+ printf_unfiltered ("Z-%d ", Z);
+ printf_unfiltered ("V-%d ", V);
+ printf_unfiltered ("C-%d ", C);
+ if ((C | Z) == 0)
+ printf_unfiltered ("u> ");
+ if ((C | Z) == 1)
+ printf_unfiltered ("u<= ");
+ if ((C == 0))
+ printf_unfiltered ("u>= ");
+ if (C == 1)
+ printf_unfiltered ("u< ");
+ if (Z == 0)
+ printf_unfiltered ("!= ");
+ if (Z == 1)
+ printf_unfiltered ("== ");
+ if ((N ^ V) == 0)
+ printf_unfiltered (">= ");
+ if ((N ^ V) == 1)
+ printf_unfiltered ("< ");
+ if ((Z | (N ^ V)) == 0)
+ printf_unfiltered ("> ");
+ if ((Z | (N ^ V)) == 1)
+ printf_unfiltered ("<= ");
+ }
+}
+
+int
+h8500_register_size (regno)
+ int regno;
+{
+ switch (regno)
+ {
+ case SEG_C_REGNUM:
+ case SEG_D_REGNUM:
+ case SEG_E_REGNUM:
+ case SEG_T_REGNUM:
+ return 1;
+ case R0_REGNUM:
+ case R1_REGNUM:
+ case R2_REGNUM:
+ case R3_REGNUM:
+ case R4_REGNUM:
+ case R5_REGNUM:
+ case R6_REGNUM:
+ case R7_REGNUM:
+ case CCR_REGNUM:
+ return 2;
+
+ case PR0_REGNUM:
+ case PR1_REGNUM:
+ case PR2_REGNUM:
+ case PR3_REGNUM:
+ case PR4_REGNUM:
+ case PR5_REGNUM:
+ case PR6_REGNUM:
+ case PR7_REGNUM:
+ case PC_REGNUM:
+ return 4;
+ default:
+ abort ();
+ }
+}
+
+struct type *
+h8500_register_virtual_type (regno)
+ int regno;
+{
+ switch (regno)
+ {
+ case SEG_C_REGNUM:
+ case SEG_E_REGNUM:
+ case SEG_D_REGNUM:
+ case SEG_T_REGNUM:
+ return builtin_type_unsigned_char;
+ case R0_REGNUM:
+ case R1_REGNUM:
+ case R2_REGNUM:
+ case R3_REGNUM:
+ case R4_REGNUM:
+ case R5_REGNUM:
+ case R6_REGNUM:
+ case R7_REGNUM:
+ case CCR_REGNUM:
+ return builtin_type_unsigned_short;
+ case PR0_REGNUM:
+ case PR1_REGNUM:
+ case PR2_REGNUM:
+ case PR3_REGNUM:
+ case PR4_REGNUM:
+ case PR5_REGNUM:
+ case PR6_REGNUM:
+ case PR7_REGNUM:
+ case PC_REGNUM:
+ return builtin_type_unsigned_long;
+ default:
+ abort ();
+ }
+}
+
+/* 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. */
+
+void
+frame_find_saved_regs (frame_info, frame_saved_regs)
+ struct frame_info *frame_info;
+ struct frame_saved_regs *frame_saved_regs;
+{
+ register int regnum;
+ register int regmask;
+ register CORE_ADDR next_addr;
+ register CORE_ADDR pc;
+ unsigned char thebyte;
+
+ memset (frame_saved_regs, '\0', sizeof *frame_saved_regs);
+
+ if ((frame_info)->pc >= (frame_info)->frame - CALL_DUMMY_LENGTH - FP_REGNUM * 4 - 4
+ && (frame_info)->pc <= (frame_info)->frame)
+ {
+ next_addr = (frame_info)->frame;
+ pc = (frame_info)->frame - CALL_DUMMY_LENGTH - FP_REGNUM * 4 - 4;
+ }
+ else
+ {
+ pc = get_pc_function_start ((frame_info)->pc);
+ /* Verify we have a link a6 instruction next;
+ if not we lose. If we win, find the address above the saved
+ regs using the amount of storage from the link instruction.
+ */
+
+ thebyte = read_memory_integer (pc, 1);
+ if (0x1f == thebyte)
+ next_addr = (frame_info)->frame + read_memory_integer (pc += 1, 2), pc += 2;
+ else if (0x17 == thebyte)
+ next_addr = (frame_info)->frame + read_memory_integer (pc += 1, 1), pc += 1;
+ else
+ goto lose;
+#if 0
+ /* FIXME steve */
+ /* If have an add:g.waddal #-n, sp next, adjust next_addr. */
+ if ((0x0c0177777 & read_memory_integer (pc, 2)) == 0157774)
+ next_addr += read_memory_integer (pc += 2, 4), pc += 4;
+#endif
+ }
+
+ thebyte = read_memory_integer (pc, 1);
+ if (thebyte == 0x12)
+ {
+ /* Got stm */
+ pc++;
+ regmask = read_memory_integer (pc, 1);
+ pc++;
+ for (regnum = 0; regnum < 8; regnum++, regmask >>= 1)
+ {
+ if (regmask & 1)
+ {
+ (frame_saved_regs)->regs[regnum] = (next_addr += 2) - 2;
+ }
+ }
+ thebyte = read_memory_integer (pc, 1);
+ }
+ /* Maybe got a load of pushes */
+ while (thebyte == 0xbf)
+ {
+ pc++;
+ regnum = read_memory_integer (pc, 1) & 0x7;
+ pc++;
+ (frame_saved_regs)->regs[regnum] = (next_addr += 2) - 2;
+ thebyte = read_memory_integer (pc, 1);
+ }
+
+lose:;
+
+ /* Remember the address of the frame pointer */
+ (frame_saved_regs)->regs[FP_REGNUM] = (frame_info)->frame;
+
+ /* This is where the old sp is hidden */
+ (frame_saved_regs)->regs[SP_REGNUM] = (frame_info)->frame;
+
+ /* And the PC - remember the pushed FP is always two bytes long */
+ (frame_saved_regs)->regs[PC_REGNUM] = (frame_info)->frame + 2;
+}
+
+CORE_ADDR
+saved_pc_after_call ()
+{
+ int x;
+ int a = read_register (SP_REGNUM);
+
+ x = read_memory_integer (a, code_size);
+ if (code_size == 2)
+ {
+ /* Stick current code segement onto top */
+ x &= 0xffff;
+ x |= read_register (SEG_C_REGNUM) << 16;
+ }
+ x &= 0xffffff;
+ return x;
+}
+
+void
+h8500_set_pointer_size (newsize)
+ int newsize;
+{
+ static int oldsize = 0;
+
+ if (oldsize != newsize)
+ {
+ printf_unfiltered ("pointer size set to %d bits\n", newsize);
+ oldsize = newsize;
+ if (newsize == 32)
+ {
+ minimum_mode = 0;
+ }
+ else
+ {
+ minimum_mode = 1;
+ }
+ _initialize_gdbtypes ();
+ }
+}
+
+static void
+big_command ()
+{
+ h8500_set_pointer_size (32);
+ code_size = 4;
+ data_size = 4;
+}
+
+static void
+medium_command ()
+{
+ h8500_set_pointer_size (32);
+ code_size = 4;
+ data_size = 2;
+}
+
+static void
+compact_command ()
+{
+ h8500_set_pointer_size (32);
+ code_size = 2;
+ data_size = 4;
+}
+
+static void
+small_command ()
+{
+ h8500_set_pointer_size (16);
+ code_size = 2;
+ data_size = 2;
+}
+
+static struct cmd_list_element *setmemorylist;
+
+static void
+set_memory (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ printf_unfiltered ("\"set memory\" must be followed by the name of a memory subcommand.\n");
+ help_list (setmemorylist, "set memory ", -1, gdb_stdout);
+}
+
+/* See if variable name is ppc or pr[0-7] */
+
+int
+h8500_is_trapped_internalvar (name)
+ char *name;
+{
+ if (name[0] != 'p')
+ return 0;
+
+ if (strcmp (name + 1, "pc") == 0)
+ return 1;
+
+ if (name[1] == 'r'
+ && name[2] >= '0'
+ && name[2] <= '7'
+ && name[3] == '\000')
+ return 1;
+ else
+ return 0;
+}
+
+value_ptr
+h8500_value_of_trapped_internalvar (var)
+ struct internalvar *var;
+{
+ LONGEST regval;
+ unsigned char regbuf[4];
+ int page_regnum, regnum;
+
+ regnum = var->name[2] == 'c' ? PC_REGNUM : var->name[2] - '0';
+
+ switch (var->name[2])
+ {
+ case 'c':
+ page_regnum = SEG_C_REGNUM;
+ break;
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ page_regnum = SEG_D_REGNUM;
+ break;
+ case '4':
+ case '5':
+ page_regnum = SEG_E_REGNUM;
+ break;
+ case '6':
+ case '7':
+ page_regnum = SEG_T_REGNUM;
+ break;
+ }
+
+ get_saved_register (regbuf, NULL, NULL, selected_frame, page_regnum, NULL);
+ regval = regbuf[0] << 16;
+
+ get_saved_register (regbuf, NULL, NULL, selected_frame, regnum, NULL);
+ regval |= regbuf[0] << 8 | regbuf[1]; /* XXX host/target byte order */
+
+ free (var->value); /* Free up old value */
+
+ var->value = value_from_longest (builtin_type_unsigned_long, regval);
+ release_value (var->value); /* Unchain new value */
+
+ VALUE_LVAL (var->value) = lval_internalvar;
+ VALUE_INTERNALVAR (var->value) = var;
+ return var->value;
+}
+
+void
+h8500_set_trapped_internalvar (var, newval, bitpos, bitsize, offset)
+ struct internalvar *var;
+ int offset, bitpos, bitsize;
+ value_ptr newval;
+{
+ char *page_regnum, *regnum;
+ char expression[100];
+ unsigned new_regval;
+ struct type *type;
+ enum type_code newval_type_code;
+
+ type = check_typedef (VALUE_TYPE (newval));
+ newval_type_code = TYPE_CODE (type);
+
+ if ((newval_type_code != TYPE_CODE_INT
+ && newval_type_code != TYPE_CODE_PTR)
+ || TYPE_LENGTH (type) != sizeof (new_regval))
+ error ("Illegal type (%s) for assignment to $%s\n",
+ TYPE_NAME (VALUE_TYPE (newval)), var->name);
+
+ new_regval = *(long *) VALUE_CONTENTS_RAW (newval);
+
+ regnum = var->name + 1;
+
+ switch (var->name[2])
+ {
+ case 'c':
+ page_regnum = "cp";
+ break;
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ page_regnum = "dp";
+ break;
+ case '4':
+ case '5':
+ page_regnum = "ep";
+ break;
+ case '6':
+ case '7':
+ page_regnum = "tp";
+ break;
+ }
+
+ sprintf (expression, "$%s=%d", page_regnum, new_regval >> 16);
+ parse_and_eval (expression);
+
+ sprintf (expression, "$%s=%d", regnum, new_regval & 0xffff);
+ parse_and_eval (expression);
+}
+
+CORE_ADDR
+h8500_read_sp ()
+{
+ return read_register (PR7_REGNUM);
+}
+
+void
+h8500_write_sp (v)
+ CORE_ADDR v;
+{
+ write_register (PR7_REGNUM, v);
+}
+
+CORE_ADDR
+h8500_read_pc (pid)
+ int pid;
+{
+ return read_register (PC_REGNUM);
+}
+
+void
+h8500_write_pc (v, pid)
+ CORE_ADDR v;
+ int pid;
+{
+ write_register (PC_REGNUM, v);
+}
+
+CORE_ADDR
+h8500_read_fp ()
+{
+ return read_register (PR6_REGNUM);
+}
+
+void
+h8500_write_fp (v)
+ CORE_ADDR v;
+{
+ write_register (PR6_REGNUM, v);
+}
+
+void
+_initialize_h8500_tdep ()
+{
+ tm_print_insn = print_insn_h8500;
+
+ add_prefix_cmd ("memory", no_class, set_memory,
+ "set the memory model", &setmemorylist, "set memory ", 0,
+ &setlist);
+
+ add_cmd ("small", class_support, small_command,
+ "Set small memory model. (16 bit code, 16 bit data)", &setmemorylist);
+
+ add_cmd ("big", class_support, big_command,
+ "Set big memory model. (32 bit code, 32 bit data)", &setmemorylist);
+
+ add_cmd ("medium", class_support, medium_command,
+ "Set medium memory model. (32 bit code, 16 bit data)", &setmemorylist);
+
+ add_cmd ("compact", class_support, compact_command,
+ "Set compact memory model. (16 bit code, 32 bit data)", &setmemorylist);
+
+}
diff --git a/gdb/hp-psymtab-read.c b/gdb/hp-psymtab-read.c
new file mode 100644
index 00000000000..5926ada3f3e
--- /dev/null
+++ b/gdb/hp-psymtab-read.c
@@ -0,0 +1,2381 @@
+/* Read hp debug symbols and convert to internal format, for GDB.
+ Copyright 1993, 1996, 1998, 1999 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Written by the Center for Software Science at the University of Utah
+ and by Cygnus Support. */
+
+/* Common include file for hp_symtab_read.c and hp_psymtab_read.c.
+ This has nested includes of a bunch of stuff. */
+#include "hpread.h"
+#include "demangle.h"
+
+/* To generate dumping code, uncomment this define. The dumping
+ itself is controlled by routine-local statics called "dumping". */
+/* #define DUMPING 1 */
+
+/* To use the quick look-up tables, uncomment this define. */
+#define QUICK_LOOK_UP 1
+
+/* To call PXDB to process un-processed files, uncomment this define. */
+#define USE_PXDB 1
+
+/* Forward procedure declarations */
+
+void hpread_symfile_init
+ PARAMS ((struct objfile *));
+
+void
+do_pxdb PARAMS ((bfd *));
+
+void hpread_build_psymtabs
+ PARAMS ((struct objfile *, struct section_offsets *, int));
+
+void hpread_symfile_finish
+ PARAMS ((struct objfile *));
+
+static union dnttentry *hpread_get_gntt
+ PARAMS ((int, struct objfile *));
+
+static unsigned long hpread_get_textlow
+ PARAMS ((int, int, struct objfile *, int));
+
+static struct partial_symtab *hpread_start_psymtab
+ PARAMS ((struct objfile *, struct section_offsets *, char *, CORE_ADDR, int,
+ struct partial_symbol **, struct partial_symbol **));
+
+static struct partial_symtab *hpread_end_psymtab
+ PARAMS ((struct partial_symtab *, char **, int, int, CORE_ADDR,
+ struct partial_symtab **, int));
+
+/* End of forward routine declarations */
+
+#ifdef USE_PXDB
+
+/* NOTE use of system files! May not be portable. */
+
+#define PXDB_SVR4 "/opt/langtools/bin/pxdb"
+#define PXDB_BSD "/usr/bin/pxdb"
+
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+/* check for the existance of a file, given its full pathname */
+int
+file_exists (filename)
+ char *filename;
+{
+ if (filename)
+ return (access (filename, F_OK) == 0);
+ return 0;
+}
+
+
+/* Translate from the "hp_language" enumeration in hp-symtab.h
+ used in the debug info to gdb's generic enumeration in defs.h. */
+static enum language
+trans_lang (in_lang)
+ enum hp_language in_lang;
+{
+ if (in_lang == HP_LANGUAGE_C)
+ return language_c;
+
+ else if (in_lang == HP_LANGUAGE_CPLUSPLUS)
+ return language_cplus;
+
+ else if (in_lang == HP_LANGUAGE_F77)
+ return language_fortran;
+
+ else
+ return language_unknown;
+}
+
+static char main_string[] = "main";
+
+/* Call PXDB to process our file.
+
+ Approach copied from DDE's "dbgk_run_pxdb". Note: we
+ don't check for BSD location of pxdb, nor for existance
+ of pxdb itself, etc.
+
+ NOTE: uses system function and string functions directly.
+
+ Return value: 1 if ok, 0 if not */
+int
+hpread_call_pxdb (file_name)
+ char *file_name;
+{
+ char *p;
+ int status;
+ int retval;
+
+ if (file_exists (PXDB_SVR4))
+ {
+ p = malloc (strlen (PXDB_SVR4) + strlen (file_name) + 2);
+ strcpy (p, PXDB_SVR4);
+ strcat (p, " ");
+ strcat (p, file_name);
+
+ warning ("File not processed by pxdb--about to process now.\n");
+ status = system (p);
+
+ retval = (status == 0);
+ }
+ else
+ {
+ warning ("pxdb not found at standard location: /opt/langtools/bin\ngdb will not be able to debug %s.\nPlease install pxdb at the above location and then restart gdb.\nYou can also run pxdb on %s with the command\n\"pxdb %s\" and then restart gdb.", file_name, file_name, file_name);
+
+ retval = 0;
+ }
+ return retval;
+} /* hpread_call_pxdb */
+
+
+/* Return 1 if the file turns out to need pre-processing
+ by PXDB, and we have thus called PXDB to do this processing
+ and the file therefore needs to be re-loaded. Otherwise
+ return 0. */
+int
+hpread_pxdb_needed (sym_bfd)
+ bfd *sym_bfd;
+{
+ asection *pinfo_section, *debug_section, *header_section;
+ unsigned int do_pxdb;
+ char *buf;
+ bfd_size_type header_section_size;
+
+ unsigned long tmp;
+ unsigned int pxdbed;
+
+ header_section = bfd_get_section_by_name (sym_bfd, "$HEADER$");
+ if (!header_section)
+ {
+ return 0; /* No header at all, can't recover... */
+ }
+
+ debug_section = bfd_get_section_by_name (sym_bfd, "$DEBUG$");
+ pinfo_section = bfd_get_section_by_name (sym_bfd, "$PINFO$");
+
+ if (pinfo_section && !debug_section)
+ {
+ /* Debug info with DOC, has different header format.
+ this only happens if the file was pxdbed and compiled optimized
+ otherwise the PINFO section is not there. */
+ header_section_size = bfd_section_size (objfile->obfd, header_section);
+
+ if (header_section_size == (bfd_size_type) sizeof (DOC_info_PXDB_header))
+ {
+ buf = alloca (sizeof (DOC_info_PXDB_header));
+
+ if (!bfd_get_section_contents (sym_bfd,
+ header_section,
+ buf, 0,
+ header_section_size))
+ error ("bfd_get_section_contents\n");
+
+ tmp = bfd_get_32 (sym_bfd, (bfd_byte *) (buf + sizeof (int) * 4));
+ pxdbed = (tmp >> 31) & 0x1;
+
+ if (!pxdbed)
+ error ("file debug header info invalid\n");
+ do_pxdb = 0;
+ }
+
+ else
+ error ("invalid $HEADER$ size in executable \n");
+ }
+
+ else
+ {
+
+ /* this can be three different cases:
+ 1. pxdbed and not doc
+ - DEBUG and HEADER sections are there
+ - header is PXDB_header type
+ - pxdbed flag is set to 1
+
+ 2. not pxdbed and doc
+ - DEBUG and HEADER sections are there
+ - header is DOC_info_header type
+ - pxdbed flag is set to 0
+
+ 3. not pxdbed and not doc
+ - DEBUG and HEADER sections are there
+ - header is XDB_header type
+ - pxdbed flag is set to 0
+
+ NOTE: the pxdbed flag is meaningful also in the not
+ already pxdb processed version of the header,
+ because in case on non-already processed by pxdb files
+ that same bit in the header would be always zero.
+ Why? Because the bit is the leftmost bit of a word
+ which contains a 'length' which is always a positive value
+ so that bit is never set to 1 (otherwise it would be negative)
+
+ Given the above, we have two choices : either we ignore the
+ size of the header itself and just look at the pxdbed field,
+ or we check the size and then we (for safety and paranoia related
+ issues) check the bit.
+ The first solution is used by DDE, the second by PXDB itself.
+ I am using the second one here, because I already wrote it,
+ and it is the end of a long day.
+ Also, using the first approach would still involve size issues
+ because we need to read in the contents of the header section, and
+ give the correct amount of stuff we want to read to the
+ get_bfd_section_contents function. */
+
+ /* decide which case depending on the size of the header section.
+ The size is as defined in hp-symtab.h */
+
+ header_section_size = bfd_section_size (objfile->obfd, header_section);
+
+ if (header_section_size == (bfd_size_type) sizeof (PXDB_header)) /* pxdb and not doc */
+ {
+
+ buf = alloca (sizeof (PXDB_header));
+ if (!bfd_get_section_contents (sym_bfd,
+ header_section,
+ buf, 0,
+ header_section_size))
+ error ("bfd_get_section_contents\n");
+
+ tmp = bfd_get_32 (sym_bfd, (bfd_byte *) (buf + sizeof (int) * 3));
+ pxdbed = (tmp >> 31) & 0x1;
+
+ if (pxdbed)
+ do_pxdb = 0;
+ else
+ error ("file debug header invalid\n");
+ }
+ else /*not pxdbed and doc OR not pxdbed and non doc */
+ do_pxdb = 1;
+ }
+
+ if (do_pxdb)
+ {
+ return 1;
+ }
+ else
+ {
+ return 0;
+ }
+} /* hpread_pxdb_needed */
+
+#endif
+
+/* Check whether the file needs to be preprocessed by pxdb.
+ If so, call pxdb. */
+
+void
+do_pxdb (sym_bfd)
+ bfd *sym_bfd;
+{
+ /* The following code is HP-specific. The "right" way of
+ doing this is unknown, but we bet would involve a target-
+ specific pre-file-load check using a generic mechanism. */
+
+ /* This code will not be executed if the file is not in SOM
+ format (i.e. if compiled with gcc) */
+ if (hpread_pxdb_needed (sym_bfd))
+ {
+ /*This file has not been pre-processed. Preprocess now */
+
+ if (hpread_call_pxdb (sym_bfd->filename))
+ {
+ /* The call above has changed the on-disk file,
+ we can close the file anyway, because the
+ symbols will be reread in when the target is run */
+ bfd_close (sym_bfd);
+ }
+ }
+}
+
+
+
+#ifdef QUICK_LOOK_UP
+
+/* Code to handle quick lookup-tables follows. */
+
+
+/* Some useful macros */
+#define VALID_FILE(i) ((i) < pxdb_header_p->fd_entries)
+#define VALID_MODULE(i) ((i) < pxdb_header_p->md_entries)
+#define VALID_PROC(i) ((i) < pxdb_header_p->pd_entries)
+#define VALID_CLASS(i) ((i) < pxdb_header_p->cd_entries)
+
+#define FILE_START(i) (qFD[i].adrStart)
+#define MODULE_START(i) (qMD[i].adrStart)
+#define PROC_START(i) (qPD[i].adrStart)
+
+#define FILE_END(i) (qFD[i].adrEnd)
+#define MODULE_END(i) (qMD[i].adrEnd)
+#define PROC_END(i) (qPD[i].adrEnd)
+
+#define FILE_ISYM(i) (qFD[i].isym)
+#define MODULE_ISYM(i) (qMD[i].isym)
+#define PROC_ISYM(i) (qPD[i].isym)
+
+#define VALID_CURR_FILE (curr_fd < pxdb_header_p->fd_entries)
+#define VALID_CURR_MODULE (curr_md < pxdb_header_p->md_entries)
+#define VALID_CURR_PROC (curr_pd < pxdb_header_p->pd_entries)
+#define VALID_CURR_CLASS (curr_cd < pxdb_header_p->cd_entries)
+
+#define CURR_FILE_START (qFD[curr_fd].adrStart)
+#define CURR_MODULE_START (qMD[curr_md].adrStart)
+#define CURR_PROC_START (qPD[curr_pd].adrStart)
+
+#define CURR_FILE_END (qFD[curr_fd].adrEnd)
+#define CURR_MODULE_END (qMD[curr_md].adrEnd)
+#define CURR_PROC_END (qPD[curr_pd].adrEnd)
+
+#define CURR_FILE_ISYM (qFD[curr_fd].isym)
+#define CURR_MODULE_ISYM (qMD[curr_md].isym)
+#define CURR_PROC_ISYM (qPD[curr_pd].isym)
+
+#define TELL_OBJFILE \
+ do { \
+ if( !told_objfile ) { \
+ told_objfile = 1; \
+ warning ("\nIn object file \"%s\":\n", \
+ objfile->name); \
+ } \
+ } while (0)
+
+
+
+/* Keeping track of the start/end symbol table (LNTT) indices of
+ psymtabs created so far */
+
+typedef struct
+ {
+ int start;
+ int end;
+ }
+pst_syms_struct;
+
+static pst_syms_struct *pst_syms_array = 0;
+
+static pst_syms_count = 0;
+static pst_syms_size = 0;
+
+/* used by the TELL_OBJFILE macro */
+static boolean told_objfile = 0;
+
+/* Set up psymtab symbol index stuff */
+static void
+init_pst_syms ()
+{
+ pst_syms_count = 0;
+ pst_syms_size = 20;
+ pst_syms_array = (pst_syms_struct *) xmalloc (20 * sizeof (pst_syms_struct));
+}
+
+/* Clean up psymtab symbol index stuff */
+static void
+clear_pst_syms ()
+{
+ pst_syms_count = 0;
+ pst_syms_size = 0;
+ free (pst_syms_array);
+ pst_syms_array = 0;
+}
+
+/* Add information about latest psymtab to symbol index table */
+static void
+record_pst_syms (start_sym, end_sym)
+ int start_sym;
+ int end_sym;
+{
+ if (++pst_syms_count > pst_syms_size)
+ {
+ pst_syms_array = (pst_syms_struct *) xrealloc (pst_syms_array,
+ 2 * pst_syms_size * sizeof (pst_syms_struct));
+ pst_syms_size *= 2;
+ }
+ pst_syms_array[pst_syms_count - 1].start = start_sym;
+ pst_syms_array[pst_syms_count - 1].end = end_sym;
+}
+
+/* Find a suitable symbol table index which can serve as the upper
+ bound of a psymtab that starts at INDEX
+
+ This scans backwards in the psymtab symbol index table to find a
+ "hole" in which the given index can fit. This is a heuristic!!
+ We don't search the entire table to check for multiple holes,
+ we don't care about overlaps, etc.
+
+ Return 0 => not found */
+static int
+find_next_pst_start (index)
+ int index;
+{
+ int i;
+
+ for (i = pst_syms_count - 1; i >= 0; i--)
+ if (pst_syms_array[i].end <= index)
+ return (i == pst_syms_count - 1) ? 0 : pst_syms_array[i + 1].start - 1;
+
+ if (pst_syms_array[0].start > index)
+ return pst_syms_array[0].start - 1;
+
+ return 0;
+}
+
+
+
+/* Utility functions to find the ending symbol index for a psymtab */
+
+/* Find the next file entry that begins beyond INDEX, and return
+ its starting symbol index - 1.
+ QFD is the file table, CURR_FD is the file entry from where to start,
+ PXDB_HEADER_P as in hpread_quick_traverse (to allow macros to work).
+
+ Return 0 => not found */
+static int
+find_next_file_isym (index, qFD, curr_fd, pxdb_header_p)
+ int index;
+ quick_file_entry *qFD;
+ int curr_fd;
+ PXDB_header_ptr pxdb_header_p;
+{
+ while (VALID_CURR_FILE)
+ {
+ if (CURR_FILE_ISYM >= index)
+ return CURR_FILE_ISYM - 1;
+ curr_fd++;
+ }
+ return 0;
+}
+
+/* Find the next procedure entry that begins beyond INDEX, and return
+ its starting symbol index - 1.
+ QPD is the procedure table, CURR_PD is the proc entry from where to start,
+ PXDB_HEADER_P as in hpread_quick_traverse (to allow macros to work).
+
+ Return 0 => not found */
+static int
+find_next_proc_isym (index, qPD, curr_pd, pxdb_header_p)
+ int index;
+ quick_procedure_entry *qPD;
+ int curr_pd;
+ PXDB_header_ptr pxdb_header_p;
+{
+ while (VALID_CURR_PROC)
+ {
+ if (CURR_PROC_ISYM >= index)
+ return CURR_PROC_ISYM - 1;
+ curr_pd++;
+ }
+ return 0;
+}
+
+/* Find the next module entry that begins beyond INDEX, and return
+ its starting symbol index - 1.
+ QMD is the module table, CURR_MD is the modue entry from where to start,
+ PXDB_HEADER_P as in hpread_quick_traverse (to allow macros to work).
+
+ Return 0 => not found */
+static int
+find_next_module_isym (index, qMD, curr_md, pxdb_header_p)
+ int index;
+ quick_module_entry *qMD;
+ int curr_md;
+ PXDB_header_ptr pxdb_header_p;
+{
+ while (VALID_CURR_MODULE)
+ {
+ if (CURR_MODULE_ISYM >= index)
+ return CURR_MODULE_ISYM - 1;
+ curr_md++;
+ }
+ return 0;
+}
+
+/* Scan and record partial symbols for all functions starting from index
+ pointed to by CURR_PD_P, and between code addresses START_ADR and END_ADR.
+ Other parameters are explained in comments below. */
+
+/* This used to be inline in hpread_quick_traverse, but now that we do essentially the
+ same thing for two different cases (modules and module-less files), it's better
+ organized in a separate routine, although it does take lots of arguments. pai/1997-10-08 */
+
+static int
+scan_procs (curr_pd_p, qPD, max_procs, start_adr, end_adr, pst, vt_bits, objfile, section_offsets)
+ int *curr_pd_p; /* pointer to current proc index */
+ quick_procedure_entry *qPD; /* the procedure quick lookup table */
+ int max_procs; /* number of entries in proc. table */
+ CORE_ADDR start_adr; /* beginning of code range for current psymtab */
+ CORE_ADDR end_adr; /* end of code range for current psymtab */
+ struct partial_symtab *pst; /* current psymtab */
+ char *vt_bits; /* strings table of SOM debug space */
+ struct objfile *objfile; /* current object file */
+ struct section_offsets *section_offsets; /* not really used for HP-UX currently */
+{
+ union dnttentry *dn_bufp;
+ int symbol_count = 0; /* Total number of symbols in this psymtab */
+ int curr_pd = *curr_pd_p; /* Convenience variable -- avoid dereferencing pointer all the time */
+
+#ifdef DUMPING
+ /* Turn this on for lots of debugging information in this routine */
+ static int dumping = 0;
+#endif
+
+#ifdef DUMPING
+ if (dumping)
+ {
+ printf ("Scan_procs called, addresses %x to %x, proc %x\n", start_adr, end_adr, curr_pd);
+ }
+#endif
+
+ while ((CURR_PROC_START <= end_adr) && (curr_pd < max_procs))
+ {
+
+ char *rtn_name; /* mangled name */
+ char *rtn_dem_name; /* qualified demangled name */
+ char *class_name;
+ int class;
+
+ if ((trans_lang ((enum hp_language) qPD[curr_pd].language) == language_cplus) &&
+ vt_bits[(long) qPD[curr_pd].sbAlias]) /* not a null string */
+ {
+ /* Get mangled name for the procedure, and demangle it */
+ rtn_name = &vt_bits[(long) qPD[curr_pd].sbAlias];
+ rtn_dem_name = cplus_demangle (rtn_name, DMGL_ANSI | DMGL_PARAMS);
+ }
+ else
+ {
+ rtn_name = &vt_bits[(long) qPD[curr_pd].sbProc];
+ rtn_dem_name = NULL;
+ }
+
+ /* Hack to get around HP C/C++ compilers' insistence on providing
+ "_MAIN_" as an alternate name for "main" */
+ if ((strcmp (rtn_name, "_MAIN_") == 0) &&
+ (strcmp (&vt_bits[(long) qPD[curr_pd].sbProc], "main") == 0))
+ rtn_dem_name = rtn_name = main_string;
+
+#ifdef DUMPING
+ if (dumping)
+ {
+ printf ("..add %s (demangled %s), index %x to this psymtab\n", rtn_name, rtn_dem_name, curr_pd);
+ }
+#endif
+
+ /* Check for module-spanning routines. */
+ if (CURR_PROC_END > end_adr)
+ {
+ TELL_OBJFILE;
+ warning ("Procedure \"%s\" [0x%x] spans file or module boundaries.", rtn_name, curr_pd);
+ }
+
+ /* Add this routine symbol to the list in the objfile.
+ Unfortunately we have to go to the LNTT to determine the
+ correct list to put it on. An alternative (which the
+ code used to do) would be to not check and always throw
+ it on the "static" list. But if we go that route, then
+ symbol_lookup() needs to be tweaked a bit to account
+ for the fact that the function might not be found on
+ the correct list in the psymtab. - RT */
+ dn_bufp = hpread_get_lntt (qPD[curr_pd].isym, objfile);
+ if (dn_bufp->dfunc.global)
+ add_psymbol_with_dem_name_to_list (rtn_name,
+ strlen (rtn_name),
+ rtn_dem_name,
+ strlen (rtn_dem_name),
+ VAR_NAMESPACE,
+ LOC_BLOCK, /* "I am a routine" */
+ &objfile->global_psymbols,
+ (qPD[curr_pd].adrStart + /* Starting address of rtn */
+ ANOFFSET (section_offsets, SECT_OFF_TEXT)),
+ 0, /* core addr?? */
+ trans_lang ((enum hp_language) qPD[curr_pd].language),
+ objfile);
+ else
+ add_psymbol_with_dem_name_to_list (rtn_name,
+ strlen (rtn_name),
+ rtn_dem_name,
+ strlen (rtn_dem_name),
+ VAR_NAMESPACE,
+ LOC_BLOCK, /* "I am a routine" */
+ &objfile->static_psymbols,
+ (qPD[curr_pd].adrStart + /* Starting address of rtn */
+ ANOFFSET (section_offsets, SECT_OFF_TEXT)),
+ 0, /* core addr?? */
+ trans_lang ((enum hp_language) qPD[curr_pd].language),
+ objfile);
+
+ symbol_count++;
+ *curr_pd_p = ++curr_pd; /* bump up count & reflect in caller */
+ } /* loop over procedures */
+
+#ifdef DUMPING
+ if (dumping)
+ {
+ if (symbol_count == 0)
+ printf ("Scan_procs: no symbols found!\n");
+ }
+#endif
+
+ return symbol_count;
+}
+
+
+/* Traverse the quick look-up tables, building a set of psymtabs.
+
+ This constructs a psymtab for modules and files in the quick lookup
+ tables.
+
+ Mostly, modules correspond to compilation units, so we try to
+ create psymtabs that correspond to modules; however, in some cases
+ a file can result in a compiled object which does not have a module
+ entry for it, so in such cases we create a psymtab for the file. */
+
+int
+hpread_quick_traverse (objfile, section_offsets, gntt_bits, vt_bits, pxdb_header_p)
+ struct objfile *objfile; /* The object file descriptor */
+ struct section_offsets *section_offsets; /* ?? Null for HP */
+ char *gntt_bits; /* GNTT entries, loaded in from the file */
+ char *vt_bits; /* VT (string) entries ditto. */
+ PXDB_header_ptr pxdb_header_p; /* Pointer to pxdb header ditto */
+{
+ struct partial_symtab *pst;
+
+ char *addr;
+
+ quick_procedure_entry *qPD;
+ quick_file_entry *qFD;
+ quick_module_entry *qMD;
+ quick_class_entry *qCD;
+
+ int idx;
+ int i;
+ CORE_ADDR start_adr; /* current psymtab's starting code addr */
+ CORE_ADDR end_adr; /* current psymtab's ending code addr */
+ CORE_ADDR next_mod_adr; /* next module's starting code addr */
+ int curr_pd; /* current procedure */
+ int curr_fd; /* current file */
+ int curr_md; /* current module */
+ int start_sym; /* current psymtab's starting symbol index */
+ int end_sym; /* current psymtab's ending symbol index */
+ int max_LNTT_sym_index;
+ int syms_in_pst;
+ B_TYPE *class_entered;
+
+ struct partial_symbol **global_syms; /* We'll be filling in the "global" */
+ struct partial_symbol **static_syms; /* and "static" tables in the objfile
+ as we go, so we need a pair of
+ current pointers. */
+
+#ifdef DUMPING
+ /* Turn this on for lots of debugging information in this routine.
+ You get a blow-by-blow account of quick lookup table reading */
+ static int dumping = 0;
+#endif
+
+ pst = (struct partial_symtab *) 0;
+
+ /* Clear out some globals */
+ init_pst_syms ();
+ told_objfile = 0;
+
+ /* Demangling style -- if EDG style already set, don't change it,
+ as HP style causes some problems with the KAI EDG compiler */
+ if (current_demangling_style != edg_demangling)
+ {
+ /* Otherwise, ensure that we are using HP style demangling */
+ set_demangling_style (HP_DEMANGLING_STYLE_STRING);
+ }
+
+ /* First we need to find the starting points of the quick
+ look-up tables in the GNTT. */
+
+ addr = gntt_bits;
+
+ qPD = (quick_procedure_entry_ptr) addr;
+ addr += pxdb_header_p->pd_entries * sizeof (quick_procedure_entry);
+
+#ifdef DUMPING
+ if (dumping)
+ {
+ printf ("\n Printing routines as we see them\n");
+ for (i = 0; VALID_PROC (i); i++)
+ {
+ idx = (long) qPD[i].sbProc;
+ printf ("%s %x..%x\n", &vt_bits[idx],
+ (int) PROC_START (i),
+ (int) PROC_END (i));
+ }
+ }
+#endif
+
+ qFD = (quick_file_entry_ptr) addr;
+ addr += pxdb_header_p->fd_entries * sizeof (quick_file_entry);
+
+#ifdef DUMPING
+ if (dumping)
+ {
+ printf ("\n Printing files as we see them\n");
+ for (i = 0; VALID_FILE (i); i++)
+ {
+ idx = (long) qFD[i].sbFile;
+ printf ("%s %x..%x\n", &vt_bits[idx],
+ (int) FILE_START (i),
+ (int) FILE_END (i));
+ }
+ }
+#endif
+
+ qMD = (quick_module_entry_ptr) addr;
+ addr += pxdb_header_p->md_entries * sizeof (quick_module_entry);
+
+#ifdef DUMPING
+ if (dumping)
+ {
+ printf ("\n Printing modules as we see them\n");
+ for (i = 0; i < pxdb_header_p->md_entries; i++)
+ {
+ idx = (long) qMD[i].sbMod;
+ printf ("%s\n", &vt_bits[idx]);
+ }
+ }
+#endif
+
+ qCD = (quick_class_entry_ptr) addr;
+ addr += pxdb_header_p->cd_entries * sizeof (quick_class_entry);
+
+#ifdef DUMPING
+ if (dumping)
+ {
+ printf ("\n Printing classes as we see them\n");
+ for (i = 0; VALID_CLASS (i); i++)
+ {
+ idx = (long) qCD[i].sbClass;
+ printf ("%s\n", &vt_bits[idx]);
+ }
+
+ printf ("\n Done with dump, on to build!\n");
+ }
+#endif
+
+ /* We need this index only while hp-symtab-read.c expects
+ a byte offset to the end of the LNTT entries for a given
+ psymtab. Thus the need for it should go away someday.
+
+ When it goes away, then we won't have any need to load the
+ LNTT from the objfile at psymtab-time, and start-up will be
+ faster. To make that work, we'll need some way to create
+ a null pst for the "globals" pseudo-module. */
+ max_LNTT_sym_index = LNTT_SYMCOUNT (objfile);
+
+ /* Scan the module descriptors and make a psymtab for each.
+
+ We know the MDs, FDs and the PDs are in order by starting
+ address. We use that fact to traverse all three arrays in
+ parallel, knowing when the next PD is in a new file
+ and we need to create a new psymtab. */
+ curr_pd = 0; /* Current procedure entry */
+ curr_fd = 0; /* Current file entry */
+ curr_md = 0; /* Current module entry */
+
+ start_adr = 0; /* Current psymtab code range */
+ end_adr = 0;
+
+ start_sym = 0; /* Current psymtab symbol range */
+ end_sym = 0;
+
+ syms_in_pst = 0; /* Symbol count for psymtab */
+
+ /* Psts actually just have pointers into the objfile's
+ symbol table, not their own symbol tables. */
+ global_syms = objfile->global_psymbols.list;
+ static_syms = objfile->static_psymbols.list;
+
+
+ /* First skip over pseudo-entries with address 0. These represent inlined
+ routines and abstract (uninstantiated) template routines.
+ FIXME: These should be read in and available -- even if we can't set
+ breakpoints, etc., there's some information that can be presented
+ to the user. pai/1997-10-08 */
+
+ while (VALID_CURR_PROC && (CURR_PROC_START == 0))
+ curr_pd++;
+
+ /* Loop over files, modules, and procedures in code address order. Each
+ time we enter an iteration of this loop, curr_pd points to the first
+ unprocessed procedure, curr_fd points to the first unprocessed file, and
+ curr_md to the first unprocessed module. Each iteration of this loop
+ updates these as required -- any or all of them may be bumpd up
+ each time around. When we exit this loop, we are done with all files
+ and modules in the tables -- there may still be some procedures, however.
+
+ Note: This code used to loop only over module entries, under the assumption
+ that files can occur via inclusions and are thus unreliable, while a
+ compiled object always corresponds to a module. With CTTI in the HP aCC
+ compiler, it turns out that compiled objects may have only files and no
+ modules; so we have to loop over files and modules, creating psymtabs for
+ either as appropriate. Unfortunately there are some problems (notably:
+ 1. the lack of "SRC_FILE_END" entries in the LNTT, 2. the lack of pointers
+ to the ending symbol indices of a module or a file) which make it quite hard
+ to do this correctly. Currently it uses a bunch of heuristics to start and
+ end psymtabs; they seem to work well with most objects generated by aCC, but
+ who knows when that will change... */
+
+ while (VALID_CURR_FILE || VALID_CURR_MODULE)
+ {
+
+ char *mod_name_string;
+ char *full_name_string;
+
+ /* First check for modules like "version.c", which have no code
+ in them but still have qMD entries. They also have no qFD or
+ qPD entries. Their start address is -1 and their end address
+ is 0. */
+ if (VALID_CURR_MODULE && (CURR_MODULE_START == -1) && (CURR_MODULE_END == 0))
+ {
+
+ mod_name_string = &vt_bits[(long) qMD[curr_md].sbMod];
+
+#ifdef DUMPING
+ if (dumping)
+ printf ("Module with data only %s\n", mod_name_string);
+#endif
+
+ /* We'll skip the rest (it makes error-checking easier), and
+ just make an empty pst. Right now empty psts are not put
+ in the pst chain, so all this is for naught, but later it
+ might help. */
+
+ pst = hpread_start_psymtab (objfile,
+ section_offsets, /* ?? */
+ mod_name_string,
+ CURR_MODULE_START, /* Low text address: bogus! */
+ (CURR_MODULE_ISYM * sizeof (struct dntt_type_block)),
+ /* ldsymoff */
+ global_syms,
+ static_syms);
+
+ pst = hpread_end_psymtab (pst,
+ NULL, /* psymtab_include_list */
+ 0, /* includes_used */
+ end_sym * sizeof (struct dntt_type_block),
+ /* byte index in LNTT of end
+ = capping symbol offset
+ = LDSYMOFF of nextfile */
+ 0, /* text high */
+ NULL, /* dependency_list */
+ 0); /* dependencies_used */
+
+ global_syms = objfile->global_psymbols.next;
+ static_syms = objfile->static_psymbols.next;
+
+ curr_md++;
+ }
+ else if (VALID_CURR_MODULE &&
+ ((CURR_MODULE_START == 0) || (CURR_MODULE_START == -1) ||
+ (CURR_MODULE_END == 0) || (CURR_MODULE_END == -1)))
+ {
+ TELL_OBJFILE;
+ warning ("Module \"%s\" [0x%x] has non-standard addresses. It starts at 0x%x, ends at 0x%x, and will be skipped.",
+ mod_name_string, curr_md, start_adr, end_adr);
+ /* On to next module */
+ curr_md++;
+ }
+ else
+ {
+ /* First check if we are looking at a file with code in it
+ that does not overlap the current module's code range */
+
+ if (VALID_CURR_FILE ? (VALID_CURR_MODULE ? (CURR_FILE_END < CURR_MODULE_START) : 1) : 0)
+ {
+
+ /* Looking at file not corresponding to any module,
+ create a psymtab for it */
+ full_name_string = &vt_bits[(long) qFD[curr_fd].sbFile];
+ start_adr = CURR_FILE_START;
+ end_adr = CURR_FILE_END;
+ start_sym = CURR_FILE_ISYM;
+
+ /* Check if there are any procedures not handled until now, that
+ begin before the start address of this file, and if so, adjust
+ this module's start address to include them. This handles routines that
+ are in between file or module ranges for some reason (probably
+ indicates a compiler bug */
+
+ if (CURR_PROC_START < start_adr)
+ {
+ TELL_OBJFILE;
+ warning ("Found procedure \"%s\" [0x%x] that is not in any file or module.",
+ &vt_bits[(long) qPD[curr_pd].sbProc], curr_pd);
+ start_adr = CURR_PROC_START;
+ if (CURR_PROC_ISYM < start_sym)
+ start_sym = CURR_PROC_ISYM;
+ }
+
+ /* Sometimes (compiler bug -- COBOL) the module end address is higher
+ than the start address of the next module, so check for that and
+ adjust accordingly */
+
+ if (VALID_FILE (curr_fd + 1) && (FILE_START (curr_fd + 1) <= end_adr))
+ {
+ TELL_OBJFILE;
+ warning ("File \"%s\" [0x%x] has ending address after starting address of next file; adjusting ending address down.",
+ full_name_string, curr_fd);
+ end_adr = FILE_START (curr_fd + 1) - 1; /* Is -4 (or -8 for 64-bit) better? */
+ }
+ if (VALID_MODULE (curr_md) && (CURR_MODULE_START <= end_adr))
+ {
+ TELL_OBJFILE;
+ warning ("File \"%s\" [0x%x] has ending address after starting address of next module; adjusting ending address down.",
+ full_name_string, curr_fd);
+ end_adr = CURR_MODULE_START - 1; /* Is -4 (or -8 for 64-bit) better? */
+ }
+
+
+#ifdef DUMPING
+ if (dumping)
+ {
+ printf ("Make new psymtab for file %s (%x to %x).\n",
+ full_name_string, start_adr, end_adr);
+ }
+#endif
+ /* Create the basic psymtab, connecting it in the list
+ for this objfile and pointing its symbol entries
+ to the current end of the symbol areas in the objfile.
+
+ The "ldsymoff" parameter is the byte offset in the LNTT
+ of the first symbol in this file. Some day we should
+ turn this into an index (fix in hp-symtab-read.c as well).
+ And it's not even the right byte offset, as we're using
+ the size of a union! FIXME! */
+ pst = hpread_start_psymtab (objfile,
+ section_offsets, /* ?? */
+ full_name_string,
+ start_adr, /* Low text address */
+ (start_sym * sizeof (struct dntt_type_block)),
+ /* ldsymoff */
+ global_syms,
+ static_syms);
+
+ /* Set up to only enter each class referenced in this module once. */
+ class_entered = malloc (B_BYTES (pxdb_header_p->cd_entries));
+ B_CLRALL (class_entered, pxdb_header_p->cd_entries);
+
+ /* Scan the procedure descriptors for procedures in the current
+ file, based on the starting addresses. */
+
+ syms_in_pst = scan_procs (&curr_pd, qPD, pxdb_header_p->pd_entries,
+ start_adr, end_adr,
+ pst, vt_bits, objfile, section_offsets);
+
+ /* Get ending symbol offset */
+
+ end_sym = 0;
+ /* First check for starting index before previous psymtab */
+ if (pst_syms_count && start_sym < pst_syms_array[pst_syms_count - 1].end)
+ {
+ end_sym = find_next_pst_start (start_sym);
+ }
+ /* Look for next start index of a file or module, or procedure */
+ if (!end_sym)
+ {
+ int next_file_isym = find_next_file_isym (start_sym, qFD, curr_fd + 1, pxdb_header_p);
+ int next_module_isym = find_next_module_isym (start_sym, qMD, curr_md, pxdb_header_p);
+ int next_proc_isym = find_next_proc_isym (start_sym, qPD, curr_pd, pxdb_header_p);
+
+ if (next_file_isym && next_module_isym)
+ {
+ /* pick lower of next file or module start index */
+ end_sym = min (next_file_isym, next_module_isym);
+ }
+ else
+ {
+ /* one of them is zero, pick the other */
+ end_sym = max (next_file_isym, next_module_isym);
+ }
+
+ /* As a precaution, check next procedure index too */
+ if (!end_sym)
+ end_sym = next_proc_isym;
+ else
+ end_sym = min (end_sym, next_proc_isym);
+ }
+
+ /* Couldn't find procedure, file, or module, use globals as default */
+ if (!end_sym)
+ end_sym = pxdb_header_p->globals;
+
+#ifdef DUMPING
+ if (dumping)
+ {
+ printf ("File psymtab indices: %x to %x\n", start_sym, end_sym);
+ }
+#endif
+
+ pst = hpread_end_psymtab (pst,
+ NULL, /* psymtab_include_list */
+ 0, /* includes_used */
+ end_sym * sizeof (struct dntt_type_block),
+ /* byte index in LNTT of end
+ = capping symbol offset
+ = LDSYMOFF of nextfile */
+ end_adr, /* text high */
+ NULL, /* dependency_list */
+ 0); /* dependencies_used */
+
+ record_pst_syms (start_sym, end_sym);
+
+ if (NULL == pst)
+ warning ("No symbols in psymtab for file \"%s\" [0x%x].", full_name_string, curr_fd);
+
+#ifdef DUMPING
+ if (dumping)
+ {
+ printf ("Made new psymtab for file %s (%x to %x), sym %x to %x.\n",
+ full_name_string, start_adr, end_adr, CURR_FILE_ISYM, end_sym);
+ }
+#endif
+ /* Prepare for the next psymtab. */
+ global_syms = objfile->global_psymbols.next;
+ static_syms = objfile->static_psymbols.next;
+ free (class_entered);
+
+ curr_fd++;
+ } /* Psymtab for file */
+ else
+ {
+ /* We have a module for which we create a psymtab */
+
+ mod_name_string = &vt_bits[(long) qMD[curr_md].sbMod];
+
+ /* We will include the code ranges of any files that happen to
+ overlap with this module */
+
+ /* So, first pick the lower of the file's and module's start addresses */
+ start_adr = CURR_MODULE_START;
+ if (VALID_CURR_FILE)
+ {
+ if (CURR_FILE_START < CURR_MODULE_START)
+ {
+ TELL_OBJFILE;
+ warning ("File \"%s\" [0x%x] crosses beginning of module \"%s\".",
+ &vt_bits[(long) qFD[curr_fd].sbFile],
+ curr_fd, mod_name_string);
+
+ start_adr = CURR_FILE_START;
+ }
+ }
+
+ /* Also pick the lower of the file's and the module's start symbol indices */
+ start_sym = CURR_MODULE_ISYM;
+ if (VALID_CURR_FILE && (CURR_FILE_ISYM < CURR_MODULE_ISYM))
+ start_sym = CURR_FILE_ISYM;
+
+ /* For the end address, we scan through the files till we find one
+ that overlaps the current module but ends beyond it; if no such file exists we
+ simply use the module's start address.
+ (Note, if file entries themselves overlap
+ we take the longest overlapping extension beyond the end of the module...)
+ We assume that modules never overlap. */
+
+ end_adr = CURR_MODULE_END;
+
+ if (VALID_CURR_FILE)
+ {
+ while (VALID_CURR_FILE && (CURR_FILE_START < end_adr))
+ {
+
+#ifdef DUMPING
+ if (dumping)
+ printf ("Maybe skipping file %s which overlaps with module %s\n",
+ &vt_bits[(long) qFD[curr_fd].sbFile], mod_name_string);
+#endif
+ if (CURR_FILE_END > end_adr)
+ {
+ TELL_OBJFILE;
+ warning ("File \"%s\" [0x%x] crosses end of module \"%s\".",
+ &vt_bits[(long) qFD[curr_fd].sbFile],
+ curr_fd, mod_name_string);
+ end_adr = CURR_FILE_END;
+ }
+ curr_fd++;
+ }
+ curr_fd--; /* back up after going too far */
+ }
+
+ /* Sometimes (compiler bug -- COBOL) the module end address is higher
+ than the start address of the next module, so check for that and
+ adjust accordingly */
+
+ if (VALID_MODULE (curr_md + 1) && (MODULE_START (curr_md + 1) <= end_adr))
+ {
+ TELL_OBJFILE;
+ warning ("Module \"%s\" [0x%x] has ending address after starting address of next module; adjusting ending address down.",
+ mod_name_string, curr_md);
+ end_adr = MODULE_START (curr_md + 1) - 1; /* Is -4 (or -8 for 64-bit) better? */
+ }
+ if (VALID_FILE (curr_fd + 1) && (FILE_START (curr_fd + 1) <= end_adr))
+ {
+ TELL_OBJFILE;
+ warning ("Module \"%s\" [0x%x] has ending address after starting address of next file; adjusting ending address down.",
+ mod_name_string, curr_md);
+ end_adr = FILE_START (curr_fd + 1) - 1; /* Is -4 (or -8 for 64-bit) better? */
+ }
+
+ /* Use one file to get the full name for the module. This
+ situation can arise if there is executable code in a #include
+ file. Each file with code in it gets a qFD. Files which don't
+ contribute code don't get a qFD, even if they include files
+ which do, e.g.:
+
+ body.c: rtn.h:
+ int x; int main() {
+ #include "rtn.h" return x;
+ }
+
+ There will a qFD for "rtn.h",and a qMD for "body.c",
+ but no qMD for "rtn.h" or qFD for "body.c"!
+
+ We pick the name of the last file to overlap with this
+ module. C convention is to put include files first. In a
+ perfect world, we could check names and use the file whose full
+ path name ends with the module name. */
+
+ if (VALID_CURR_FILE)
+ full_name_string = &vt_bits[(long) qFD[curr_fd].sbFile];
+ else
+ full_name_string = mod_name_string;
+
+ /* Check if there are any procedures not handled until now, that
+ begin before the start address we have now, and if so, adjust
+ this psymtab's start address to include them. This handles routines that
+ are in between file or module ranges for some reason (probably
+ indicates a compiler bug */
+
+ if (CURR_PROC_START < start_adr)
+ {
+ TELL_OBJFILE;
+ warning ("Found procedure \"%s\" [0x%x] that is not in any file or module.",
+ &vt_bits[(long) qPD[curr_pd].sbProc], curr_pd);
+ start_adr = CURR_PROC_START;
+ if (CURR_PROC_ISYM < start_sym)
+ start_sym = CURR_PROC_ISYM;
+ }
+
+#ifdef DUMPING
+ if (dumping)
+ {
+ printf ("Make new psymtab for module %s (%x to %x), using file %s\n",
+ mod_name_string, start_adr, end_adr, full_name_string);
+ }
+#endif
+ /* Create the basic psymtab, connecting it in the list
+ for this objfile and pointing its symbol entries
+ to the current end of the symbol areas in the objfile.
+
+ The "ldsymoff" parameter is the byte offset in the LNTT
+ of the first symbol in this file. Some day we should
+ turn this into an index (fix in hp-symtab-read.c as well).
+ And it's not even the right byte offset, as we're using
+ the size of a union! FIXME! */
+ pst = hpread_start_psymtab (objfile,
+ section_offsets, /* ?? */
+ full_name_string,
+ start_adr, /* Low text address */
+ (start_sym * sizeof (struct dntt_type_block)),
+ /* ldsymoff */
+ global_syms,
+ static_syms);
+
+ /* Set up to only enter each class referenced in this module once. */
+ class_entered = malloc (B_BYTES (pxdb_header_p->cd_entries));
+ B_CLRALL (class_entered, pxdb_header_p->cd_entries);
+
+ /* Scan the procedure descriptors for procedures in the current
+ module, based on the starting addresses. */
+
+ syms_in_pst = scan_procs (&curr_pd, qPD, pxdb_header_p->pd_entries,
+ start_adr, end_adr,
+ pst, vt_bits, objfile, section_offsets);
+
+ /* Get ending symbol offset */
+
+ end_sym = 0;
+ /* First check for starting index before previous psymtab */
+ if (pst_syms_count && start_sym < pst_syms_array[pst_syms_count - 1].end)
+ {
+ end_sym = find_next_pst_start (start_sym);
+ }
+ /* Look for next start index of a file or module, or procedure */
+ if (!end_sym)
+ {
+ int next_file_isym = find_next_file_isym (start_sym, qFD, curr_fd + 1, pxdb_header_p);
+ int next_module_isym = find_next_module_isym (start_sym, qMD, curr_md + 1, pxdb_header_p);
+ int next_proc_isym = find_next_proc_isym (start_sym, qPD, curr_pd, pxdb_header_p);
+
+ if (next_file_isym && next_module_isym)
+ {
+ /* pick lower of next file or module start index */
+ end_sym = min (next_file_isym, next_module_isym);
+ }
+ else
+ {
+ /* one of them is zero, pick the other */
+ end_sym = max (next_file_isym, next_module_isym);
+ }
+
+ /* As a precaution, check next procedure index too */
+ if (!end_sym)
+ end_sym = next_proc_isym;
+ else
+ end_sym = min (end_sym, next_proc_isym);
+ }
+
+ /* Couldn't find procedure, file, or module, use globals as default */
+ if (!end_sym)
+ end_sym = pxdb_header_p->globals;
+
+#ifdef DUMPING
+ if (dumping)
+ {
+ printf ("Module psymtab indices: %x to %x\n", start_sym, end_sym);
+ }
+#endif
+
+ pst = hpread_end_psymtab (pst,
+ NULL, /* psymtab_include_list */
+ 0, /* includes_used */
+ end_sym * sizeof (struct dntt_type_block),
+ /* byte index in LNTT of end
+ = capping symbol offset
+ = LDSYMOFF of nextfile */
+ end_adr, /* text high */
+ NULL, /* dependency_list */
+ 0); /* dependencies_used */
+
+ record_pst_syms (start_sym, end_sym);
+
+ if (NULL == pst)
+ warning ("No symbols in psymtab for module \"%s\" [0x%x].", mod_name_string, curr_md);
+
+#ifdef DUMPING
+ if (dumping)
+ {
+ printf ("Made new psymtab for module %s (%x to %x), sym %x to %x.\n",
+ mod_name_string, start_adr, end_adr, CURR_MODULE_ISYM, end_sym);
+ }
+#endif
+
+ /* Prepare for the next psymtab. */
+ global_syms = objfile->global_psymbols.next;
+ static_syms = objfile->static_psymbols.next;
+ free (class_entered);
+
+ curr_md++;
+ curr_fd++;
+ } /* psymtab for module */
+ } /* psymtab for non-bogus file or module */
+ } /* End of while loop over all files & modules */
+
+ /* There may be some routines after all files and modules -- these will get
+ inserted in a separate new module of their own */
+ if (VALID_CURR_PROC)
+ {
+ start_adr = CURR_PROC_START;
+ end_adr = qPD[pxdb_header_p->pd_entries - 1].adrEnd;
+ TELL_OBJFILE;
+ warning ("Found functions beyond end of all files and modules [0x%x].", curr_pd);
+#ifdef DUMPING
+ if (dumping)
+ {
+ printf ("Orphan functions at end, PD %d and beyond (%x to %x)\n",
+ curr_pd, start_adr, end_adr);
+ }
+#endif
+ pst = hpread_start_psymtab (objfile,
+ section_offsets, /* ?? */
+ "orphans",
+ start_adr, /* Low text address */
+ (CURR_PROC_ISYM * sizeof (struct dntt_type_block)),
+ /* ldsymoff */
+ global_syms,
+ static_syms);
+
+ scan_procs (&curr_pd, qPD, pxdb_header_p->pd_entries,
+ start_adr, end_adr,
+ pst, vt_bits, objfile, section_offsets);
+
+ pst = hpread_end_psymtab (pst,
+ NULL, /* psymtab_include_list */
+ 0, /* includes_used */
+ pxdb_header_p->globals * sizeof (struct dntt_type_block),
+ /* byte index in LNTT of end
+ = capping symbol offset
+ = LDSYMOFF of nextfile */
+ end_adr, /* text high */
+ NULL, /* dependency_list */
+ 0); /* dependencies_used */
+ }
+
+
+#ifdef NEVER_NEVER
+ /* Now build psts for non-module things (in the tail of
+ the LNTT, after the last END MODULE entry).
+
+ If null psts were kept on the chain, this would be
+ a solution. FIXME */
+ pst = hpread_start_psymtab (objfile,
+ section_offsets,
+ "globals",
+ 0,
+ (pxdb_header_p->globals
+ * sizeof (struct dntt_type_block)),
+ objfile->global_psymbols.next,
+ objfile->static_psymbols.next);
+ hpread_end_psymtab (pst,
+ NULL, 0,
+ (max_LNTT_sym_index * sizeof (struct dntt_type_block)),
+ 0,
+ NULL, 0);
+#endif
+
+ clear_pst_syms ();
+
+ return 1;
+
+} /* End of hpread_quick_traverse. */
+
+
+/* Get appropriate header, based on pxdb type.
+ Return value: 1 if ok, 0 if not */
+int
+hpread_get_header (objfile, pxdb_header_p)
+ struct objfile *objfile;
+ PXDB_header_ptr pxdb_header_p;
+{
+ asection *pinfo_section, *debug_section, *header_section;
+
+#ifdef DUMPING
+ /* Turn on for debugging information */
+ static int dumping = 0;
+#endif
+
+ header_section = bfd_get_section_by_name (objfile->obfd, "$HEADER$");
+ if (!header_section)
+ {
+ /* We don't have either PINFO or DEBUG sections. But
+ stuff like "libc.sl" has no debug info. There's no
+ need to warn the user of this, as it may be ok. The
+ caller will figure it out and issue any needed
+ messages. */
+#ifdef DUMPING
+ if (dumping)
+ printf ("==No debug info at all for %s.\n", objfile->name);
+#endif
+
+ return 0;
+ }
+
+ /* We would like either a $DEBUG$ or $PINFO$ section.
+ Once we know which, we can understand the header
+ data (which we have defined to suit the more common
+ $DEBUG$ case). */
+ debug_section = bfd_get_section_by_name (objfile->obfd, "$DEBUG$");
+ pinfo_section = bfd_get_section_by_name (objfile->obfd, "$PINFO$");
+ if (debug_section)
+ {
+ /* The expected case: normal pxdb header. */
+ bfd_get_section_contents (objfile->obfd, header_section,
+ pxdb_header_p, 0, sizeof (PXDB_header));
+
+ if (!pxdb_header_p->pxdbed)
+ {
+ /* This shouldn't happen if we check in "symfile.c". */
+ return 0;
+ } /* DEBUG section */
+ }
+
+ else if (pinfo_section)
+ {
+ /* The DOC case; we need to translate this into a
+ regular header. */
+ DOC_info_PXDB_header doc_header;
+
+#ifdef DUMPING
+ if (dumping)
+ {
+ printf ("==OOps, PINFO, let's try to handle this, %s.\n", objfile->name);
+ }
+#endif
+
+ bfd_get_section_contents (objfile->obfd,
+ header_section,
+ &doc_header, 0,
+ sizeof (DOC_info_PXDB_header));
+
+ if (!doc_header.pxdbed)
+ {
+ /* This shouldn't happen if we check in "symfile.c". */
+ warning ("File \"%s\" not processed by pxdb!", objfile->name);
+ return 0;
+ }
+
+ /* Copy relevent fields to standard header passed in. */
+ pxdb_header_p->pd_entries = doc_header.pd_entries;
+ pxdb_header_p->fd_entries = doc_header.fd_entries;
+ pxdb_header_p->md_entries = doc_header.md_entries;
+ pxdb_header_p->pxdbed = doc_header.pxdbed;
+ pxdb_header_p->bighdr = doc_header.bighdr;
+ pxdb_header_p->sa_header = doc_header.sa_header;
+ pxdb_header_p->inlined = doc_header.inlined;
+ pxdb_header_p->globals = doc_header.globals;
+ pxdb_header_p->time = doc_header.time;
+ pxdb_header_p->pg_entries = doc_header.pg_entries;
+ pxdb_header_p->functions = doc_header.functions;
+ pxdb_header_p->files = doc_header.files;
+ pxdb_header_p->cd_entries = doc_header.cd_entries;
+ pxdb_header_p->aa_entries = doc_header.aa_entries;
+ pxdb_header_p->oi_entries = doc_header.oi_entries;
+ pxdb_header_p->version = doc_header.version;
+ } /* PINFO section */
+
+ else
+ {
+#ifdef DUMPING
+ if (dumping)
+ printf ("==No debug info at all for %s.\n", objfile->name);
+#endif
+
+ return 0;
+
+ }
+
+ return 1;
+} /* End of hpread_get_header */
+#endif /* QUICK_LOOK_UP */
+
+
+/* Initialization for reading native HP C debug symbols from OBJFILE.
+
+ Its only purpose in life is to set up the symbol reader's private
+ per-objfile data structures, and read in the raw contents of the debug
+ sections (attaching pointers to the debug info into the private data
+ structures).
+
+ 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. Note we may
+ be called on a file without native HP C debugging symbols.
+
+ FIXME, there should be a cleaner peephole into the BFD environment
+ here. */
+void
+hpread_symfile_init (objfile)
+ struct objfile *objfile;
+{
+ asection *vt_section, *slt_section, *lntt_section, *gntt_section;
+
+ /* Allocate struct to keep track of the symfile */
+ objfile->sym_private = (PTR)
+ xmmalloc (objfile->md, sizeof (struct hpread_symfile_info));
+ memset (objfile->sym_private, 0, sizeof (struct hpread_symfile_info));
+
+ /* We haven't read in any types yet. */
+ TYPE_VECTOR (objfile) = 0;
+
+ /* Read in data from the $GNTT$ subspace. */
+ gntt_section = bfd_get_section_by_name (objfile->obfd, "$GNTT$");
+ if (!gntt_section)
+ return;
+
+ GNTT (objfile)
+ = obstack_alloc (&objfile->symbol_obstack,
+ bfd_section_size (objfile->obfd, gntt_section));
+
+ bfd_get_section_contents (objfile->obfd, gntt_section, GNTT (objfile),
+ 0, bfd_section_size (objfile->obfd, gntt_section));
+
+ GNTT_SYMCOUNT (objfile)
+ = bfd_section_size (objfile->obfd, gntt_section)
+ / sizeof (struct dntt_type_block);
+
+ /* Read in data from the $LNTT$ subspace. Also keep track of the number
+ of LNTT symbols.
+
+ FIXME: this could be moved into the psymtab-to-symtab expansion
+ code, and save startup time. At the moment this data is
+ still used, though. We'd need a way to tell hp-symtab-read.c
+ whether or not to load the LNTT. */
+ lntt_section = bfd_get_section_by_name (objfile->obfd, "$LNTT$");
+ if (!lntt_section)
+ return;
+
+ LNTT (objfile)
+ = obstack_alloc (&objfile->symbol_obstack,
+ bfd_section_size (objfile->obfd, lntt_section));
+
+ bfd_get_section_contents (objfile->obfd, lntt_section, LNTT (objfile),
+ 0, bfd_section_size (objfile->obfd, lntt_section));
+
+ LNTT_SYMCOUNT (objfile)
+ = bfd_section_size (objfile->obfd, lntt_section)
+ / sizeof (struct dntt_type_block);
+
+ /* Read in data from the $SLT$ subspace. $SLT$ contains information
+ on source line numbers. */
+ slt_section = bfd_get_section_by_name (objfile->obfd, "$SLT$");
+ if (!slt_section)
+ return;
+
+ SLT (objfile) =
+ obstack_alloc (&objfile->symbol_obstack,
+ bfd_section_size (objfile->obfd, slt_section));
+
+ bfd_get_section_contents (objfile->obfd, slt_section, SLT (objfile),
+ 0, bfd_section_size (objfile->obfd, slt_section));
+
+ /* Read in data from the $VT$ subspace. $VT$ contains things like
+ names and constants. Keep track of the number of symbols in the VT. */
+ vt_section = bfd_get_section_by_name (objfile->obfd, "$VT$");
+ if (!vt_section)
+ return;
+
+ VT_SIZE (objfile) = bfd_section_size (objfile->obfd, vt_section);
+
+ VT (objfile) =
+ (char *) obstack_alloc (&objfile->symbol_obstack,
+ VT_SIZE (objfile));
+
+ bfd_get_section_contents (objfile->obfd, vt_section, VT (objfile),
+ 0, VT_SIZE (objfile));
+}
+
+/* Scan and build partial symbols for a symbol file.
+
+ The minimal symbol table (either SOM or HP a.out) has already been
+ read in; all we need to do is setup partial symbols based on the
+ native debugging information.
+
+ Note that the minimal table is produced by the linker, and has
+ only global routines in it; the psymtab is based on compiler-
+ generated debug information and has non-global
+ routines in it as well as files and class information.
+
+ We assume hpread_symfile_init has been called to initialize the
+ symbol reader's private data structures.
+
+ 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). */
+void
+hpread_build_psymtabs (objfile, section_offsets, mainline)
+ struct objfile *objfile;
+ struct section_offsets *section_offsets;
+ int mainline;
+{
+
+#ifdef DUMPING
+ /* Turn this on to get debugging output. */
+ static int dumping = 0;
+#endif
+
+ char *namestring;
+ int past_first_source_file = 0;
+ struct cleanup *old_chain;
+
+ int hp_symnum, symcount, i;
+ int scan_start = 0;
+
+ union dnttentry *dn_bufp;
+ unsigned long valu;
+ char *p;
+ int texthigh = 0;
+ int have_name = 0;
+
+ /* 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;
+
+ /* Just in case the stabs reader left turds lying around. */
+ free_pending_blocks ();
+ make_cleanup ((make_cleanup_func) really_free_pendings, 0);
+
+ pst = (struct partial_symtab *) 0;
+
+ /* We shouldn't use alloca, instead use malloc/free. Doing so avoids
+ a number of problems with cross compilation and creating useless holes
+ in the stack when we have to allocate new entries. FIXME. */
+
+ 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 ((make_cleanup_func) free_objfile, objfile);
+
+ last_source_file = 0;
+
+#ifdef QUICK_LOOK_UP
+ {
+ /* Begin code for new-style loading of quick look-up tables. */
+
+ /* elz: this checks whether the file has beeen processed by pxdb.
+ If not we would like to try to read the psymbols in
+ anyway, but it turns out to be not so easy. So this could
+ actually be commented out, but I leave it in, just in case
+ we decide to add support for non-pxdb-ed stuff in the future. */
+ PXDB_header pxdb_header;
+ int found_modules_in_program;
+
+ if (hpread_get_header (objfile, &pxdb_header))
+ {
+ /* Build a minimal table. No types, no global variables,
+ no include files.... */
+#ifdef DUMPING
+ if (dumping)
+ printf ("\nNew method for %s\n", objfile->name);
+#endif
+
+ /* elz: quick_traverse returns true if it found
+ some modules in the main source file, other
+ than those in end.c
+ In C and C++, all the files have MODULES entries
+ in the LNTT, and the quick table traverse is all
+ based on finding these MODULES entries. Without
+ those it cannot work.
+ It happens that F77 programs don't have MODULES
+ so the quick traverse gets confused. F90 programs
+ have modules, and the quick method still works.
+ So, if modules (other than those in end.c) are
+ not found we give up on the quick table stuff,
+ and fall back on the slower method */
+ found_modules_in_program = hpread_quick_traverse (objfile,
+ section_offsets,
+ GNTT (objfile),
+ VT (objfile),
+ &pxdb_header);
+
+ discard_cleanups (old_chain);
+
+ /* Set up to scan the global section of the LNTT.
+
+ This field is not always correct: if there are
+ no globals, it will point to the last record in
+ the regular LNTT, which is usually an END MODULE.
+
+ Since it might happen that there could be a file
+ with just one global record, there's no way to
+ tell other than by looking at the record, so that's
+ done below. */
+ if (found_modules_in_program)
+ scan_start = pxdb_header.globals;
+ }
+#ifdef DUMPING
+ else
+ {
+ if (dumping)
+ printf ("\nGoing on to old method for %s\n", objfile->name);
+ }
+#endif
+ }
+#endif /* QUICK_LOOK_UP */
+
+ /* Make two passes, one over the GNTT symbols, the other for the
+ LNTT symbols.
+
+ JB comment: above isn't true--they only make one pass, over
+ the LNTT. */
+ for (i = 0; i < 1; i++)
+ {
+ int within_function = 0;
+
+ if (i)
+ symcount = GNTT_SYMCOUNT (objfile);
+ else
+ symcount = LNTT_SYMCOUNT (objfile);
+
+
+ for (hp_symnum = scan_start; hp_symnum < symcount; hp_symnum++)
+ {
+ QUIT;
+ if (i)
+ dn_bufp = hpread_get_gntt (hp_symnum, objfile);
+ else
+ dn_bufp = hpread_get_lntt (hp_symnum, objfile);
+
+ if (dn_bufp->dblock.extension)
+ continue;
+
+ /* Only handle things which are necessary for minimal symbols.
+ everything else is ignored. */
+ switch (dn_bufp->dblock.kind)
+ {
+ case DNTT_TYPE_SRCFILE:
+ {
+#ifdef QUICK_LOOK_UP
+ if (scan_start == hp_symnum
+ && symcount == hp_symnum + 1)
+ {
+ /* If there are NO globals in an executable,
+ PXDB's index to the globals will point to
+ the last record in the file, which
+ could be this record. (this happened for F77 libraries)
+ ignore it and be done! */
+ continue;
+ }
+#endif /* QUICK_LOOK_UP */
+
+ /* A source file of some kind. Note this may simply
+ be an included file. */
+ SET_NAMESTRING (dn_bufp, &namestring, objfile);
+
+ /* Check if this is the source file we are already working
+ with. */
+ if (pst && !strcmp (namestring, pst->filename))
+ continue;
+
+ /* Check if this is an include file, if so check if we have
+ already seen it. Add it to the include list */
+ p = strrchr (namestring, '.');
+ if (!strcmp (p, ".h"))
+ {
+ int j, found;
+
+ found = 0;
+ for (j = 0; j < includes_used; j++)
+ if (!strcmp (namestring, psymtab_include_list[j]))
+ {
+ found = 1;
+ break;
+ }
+ if (found)
+ continue;
+
+ /* Add it to the list of includes seen so far and
+ allocate more include space if necessary. */
+ 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;
+ }
+
+ if (pst)
+ {
+ if (!have_name)
+ {
+ pst->filename = (char *)
+ obstack_alloc (&pst->objfile->psymbol_obstack,
+ strlen (namestring) + 1);
+ strcpy (pst->filename, namestring);
+ have_name = 1;
+ continue;
+ }
+ continue;
+ }
+
+ /* This is a bonafide new source file.
+ End the current partial symtab and start a new one. */
+
+ if (pst && past_first_source_file)
+ {
+ hpread_end_psymtab (pst, psymtab_include_list,
+ includes_used,
+ (hp_symnum
+ * sizeof (struct dntt_type_block)),
+ texthigh,
+ dependency_list, dependencies_used);
+ pst = (struct partial_symtab *) 0;
+ includes_used = 0;
+ dependencies_used = 0;
+ }
+ else
+ past_first_source_file = 1;
+
+ valu = hpread_get_textlow (i, hp_symnum, objfile, symcount);
+ valu += ANOFFSET (section_offsets, SECT_OFF_TEXT);
+ pst = hpread_start_psymtab (objfile, section_offsets,
+ namestring, valu,
+ (hp_symnum
+ * sizeof (struct dntt_type_block)),
+ objfile->global_psymbols.next,
+ objfile->static_psymbols.next);
+ texthigh = valu;
+ have_name = 1;
+ continue;
+ }
+
+ case DNTT_TYPE_MODULE:
+ /* A source file. It's still unclear to me what the
+ real difference between a DNTT_TYPE_SRCFILE and DNTT_TYPE_MODULE
+ is supposed to be. */
+
+ /* First end the previous psymtab */
+ if (pst)
+ {
+ hpread_end_psymtab (pst, psymtab_include_list, includes_used,
+ ((hp_symnum - 1)
+ * sizeof (struct dntt_type_block)),
+ texthigh,
+ dependency_list, dependencies_used);
+ pst = (struct partial_symtab *) 0;
+ includes_used = 0;
+ dependencies_used = 0;
+ have_name = 0;
+ }
+
+ /* Now begin a new module and a new psymtab for it */
+ SET_NAMESTRING (dn_bufp, &namestring, objfile);
+ valu = hpread_get_textlow (i, hp_symnum, objfile, symcount);
+ valu += ANOFFSET (section_offsets, SECT_OFF_TEXT);
+ if (!pst)
+ {
+ pst = hpread_start_psymtab (objfile, section_offsets,
+ namestring, valu,
+ (hp_symnum
+ * sizeof (struct dntt_type_block)),
+ objfile->global_psymbols.next,
+ objfile->static_psymbols.next);
+ texthigh = valu;
+ have_name = 0;
+ }
+ continue;
+
+ case DNTT_TYPE_FUNCTION:
+ case DNTT_TYPE_ENTRY:
+ /* The beginning of a function. DNTT_TYPE_ENTRY may also denote
+ a secondary entry point. */
+ valu = dn_bufp->dfunc.hiaddr + ANOFFSET (section_offsets,
+ SECT_OFF_TEXT);
+ if (valu > texthigh)
+ texthigh = valu;
+ valu = dn_bufp->dfunc.lowaddr +
+ ANOFFSET (section_offsets, SECT_OFF_TEXT);
+ SET_NAMESTRING (dn_bufp, &namestring, objfile);
+ if (dn_bufp->dfunc.global)
+ add_psymbol_to_list (namestring, strlen (namestring),
+ VAR_NAMESPACE, LOC_BLOCK,
+ &objfile->global_psymbols, valu,
+ 0, language_unknown, objfile);
+ else
+ add_psymbol_to_list (namestring, strlen (namestring),
+ VAR_NAMESPACE, LOC_BLOCK,
+ &objfile->static_psymbols, valu,
+ 0, language_unknown, objfile);
+ within_function = 1;
+ continue;
+
+ case DNTT_TYPE_DOC_FUNCTION:
+ valu = dn_bufp->ddocfunc.hiaddr + ANOFFSET (section_offsets,
+ SECT_OFF_TEXT);
+ if (valu > texthigh)
+ texthigh = valu;
+ valu = dn_bufp->ddocfunc.lowaddr +
+ ANOFFSET (section_offsets, SECT_OFF_TEXT);
+ SET_NAMESTRING (dn_bufp, &namestring, objfile);
+ if (dn_bufp->ddocfunc.global)
+ add_psymbol_to_list (namestring, strlen (namestring),
+ VAR_NAMESPACE, LOC_BLOCK,
+ &objfile->global_psymbols, valu,
+ 0, language_unknown, objfile);
+ else
+ add_psymbol_to_list (namestring, strlen (namestring),
+ VAR_NAMESPACE, LOC_BLOCK,
+ &objfile->static_psymbols, valu,
+ 0, language_unknown, objfile);
+ within_function = 1;
+ continue;
+
+ case DNTT_TYPE_BEGIN:
+ case DNTT_TYPE_END:
+ /* We don't check MODULE end here, because there can be
+ symbols beyond the module end which properly belong to the
+ current psymtab -- so we wait till the next MODULE start */
+
+
+#ifdef QUICK_LOOK_UP
+ if (scan_start == hp_symnum
+ && symcount == hp_symnum + 1)
+ {
+ /* If there are NO globals in an executable,
+ PXDB's index to the globals will point to
+ the last record in the file, which is
+ probably an END MODULE, i.e. this record.
+ ignore it and be done! */
+ continue;
+ }
+#endif /* QUICK_LOOK_UP */
+
+ /* Scope block begin/end. We only care about function
+ and file blocks right now. */
+
+ if ((dn_bufp->dend.endkind == DNTT_TYPE_FUNCTION) ||
+ (dn_bufp->dend.endkind == DNTT_TYPE_DOC_FUNCTION))
+ within_function = 0;
+ continue;
+
+ case DNTT_TYPE_SVAR:
+ case DNTT_TYPE_DVAR:
+ case DNTT_TYPE_TYPEDEF:
+ case DNTT_TYPE_TAGDEF:
+ {
+ /* Variables, typedefs an the like. */
+ enum address_class storage;
+ namespace_enum namespace;
+
+ /* Don't add locals to the partial symbol table. */
+ if (within_function
+ && (dn_bufp->dblock.kind == DNTT_TYPE_SVAR
+ || dn_bufp->dblock.kind == DNTT_TYPE_DVAR))
+ continue;
+
+ /* TAGDEFs go into the structure namespace. */
+ if (dn_bufp->dblock.kind == DNTT_TYPE_TAGDEF)
+ namespace = STRUCT_NAMESPACE;
+ else
+ namespace = VAR_NAMESPACE;
+
+ /* What kind of "storage" does this use? */
+ if (dn_bufp->dblock.kind == DNTT_TYPE_SVAR)
+ storage = LOC_STATIC;
+ else if (dn_bufp->dblock.kind == DNTT_TYPE_DVAR
+ && dn_bufp->ddvar.regvar)
+ storage = LOC_REGISTER;
+ else if (dn_bufp->dblock.kind == DNTT_TYPE_DVAR)
+ storage = LOC_LOCAL;
+ else
+ storage = LOC_UNDEF;
+
+ SET_NAMESTRING (dn_bufp, &namestring, objfile);
+ if (!pst)
+ {
+ pst = hpread_start_psymtab (objfile, section_offsets,
+ "globals", 0,
+ (hp_symnum
+ * sizeof (struct dntt_type_block)),
+ objfile->global_psymbols.next,
+ objfile->static_psymbols.next);
+ }
+
+ /* Compute address of the data symbol */
+ valu = dn_bufp->dsvar.location;
+ /* Relocate in case it's in a shared library */
+ if (storage == LOC_STATIC)
+ valu += ANOFFSET (section_offsets, SECT_OFF_DATA);
+
+ /* Luckily, dvar, svar, typedef, and tagdef all
+ have their "global" bit in the same place, so it works
+ (though it's bad programming practice) to reference
+ "dsvar.global" even though we may be looking at
+ any of the above four types. */
+ if (dn_bufp->dsvar.global)
+ {
+ add_psymbol_to_list (namestring, strlen (namestring),
+ namespace, storage,
+ &objfile->global_psymbols,
+ valu,
+ 0, language_unknown, objfile);
+ }
+ else
+ {
+ add_psymbol_to_list (namestring, strlen (namestring),
+ namespace, storage,
+ &objfile->static_psymbols,
+ valu,
+ 0, language_unknown, objfile);
+ }
+
+ /* For TAGDEF's, the above code added the tagname to the
+ struct namespace. This will cause tag "t" to be found
+ on a reference of the form "(struct t) x". But for
+ C++ classes, "t" will also be a typename, which we
+ want to find on a reference of the form "ptype t".
+ Therefore, we also add "t" to the var namespace.
+ Do the same for enum's due to the way aCC generates
+ debug info for these (see more extended comment
+ in hp-symtab-read.c).
+ We do the same for templates, so that "ptype t"
+ where "t" is a template also works. */
+ if (dn_bufp->dblock.kind == DNTT_TYPE_TAGDEF &&
+ dn_bufp->dtype.type.dnttp.index < LNTT_SYMCOUNT (objfile))
+ {
+ int global = dn_bufp->dtag.global;
+ /* Look ahead to see if it's a C++ class */
+ dn_bufp = hpread_get_lntt (dn_bufp->dtype.type.dnttp.index, objfile);
+ if (dn_bufp->dblock.kind == DNTT_TYPE_CLASS ||
+ dn_bufp->dblock.kind == DNTT_TYPE_ENUM ||
+ dn_bufp->dblock.kind == DNTT_TYPE_TEMPLATE)
+ {
+ if (global)
+ {
+ add_psymbol_to_list (namestring, strlen (namestring),
+ VAR_NAMESPACE, storage,
+ &objfile->global_psymbols,
+ dn_bufp->dsvar.location,
+ 0, language_unknown, objfile);
+ }
+ else
+ {
+ add_psymbol_to_list (namestring, strlen (namestring),
+ VAR_NAMESPACE, storage,
+ &objfile->static_psymbols,
+ dn_bufp->dsvar.location,
+ 0, language_unknown, objfile);
+ }
+ }
+ }
+ }
+ continue;
+
+ case DNTT_TYPE_MEMENUM:
+ case DNTT_TYPE_CONST:
+ /* Constants and members of enumerated types. */
+ SET_NAMESTRING (dn_bufp, &namestring, objfile);
+ if (!pst)
+ {
+ pst = hpread_start_psymtab (objfile, section_offsets,
+ "globals", 0,
+ (hp_symnum
+ * sizeof (struct dntt_type_block)),
+ objfile->global_psymbols.next,
+ objfile->static_psymbols.next);
+ }
+ if (dn_bufp->dconst.global)
+ add_psymbol_to_list (namestring, strlen (namestring),
+ VAR_NAMESPACE, LOC_CONST,
+ &objfile->global_psymbols, 0,
+ 0, language_unknown, objfile);
+ else
+ add_psymbol_to_list (namestring, strlen (namestring),
+ VAR_NAMESPACE, LOC_CONST,
+ &objfile->static_psymbols, 0,
+ 0, language_unknown, objfile);
+ continue;
+ default:
+ continue;
+ }
+ }
+ }
+
+ /* End any pending partial symbol table. */
+ if (pst)
+ {
+ hpread_end_psymtab (pst, psymtab_include_list, includes_used,
+ hp_symnum * sizeof (struct dntt_type_block),
+ 0, dependency_list, dependencies_used);
+ }
+
+ discard_cleanups (old_chain);
+}
+
+/* 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. */
+
+void
+hpread_symfile_finish (objfile)
+ struct objfile *objfile;
+{
+ if (objfile->sym_private != NULL)
+ {
+ mfree (objfile->md, objfile->sym_private);
+ }
+}
+
+
+/* The remaining functions are all for internal use only. */
+
+/* Various small functions to get entries in the debug symbol sections. */
+
+union dnttentry *
+hpread_get_lntt (index, objfile)
+ int index;
+ struct objfile *objfile;
+{
+ return (union dnttentry *)
+ &(LNTT (objfile)[(index * sizeof (struct dntt_type_block))]);
+}
+
+static union dnttentry *
+hpread_get_gntt (index, objfile)
+ int index;
+ struct objfile *objfile;
+{
+ return (union dnttentry *)
+ &(GNTT (objfile)[(index * sizeof (struct dntt_type_block))]);
+}
+
+union sltentry *
+hpread_get_slt (index, objfile)
+ int index;
+ struct objfile *objfile;
+{
+ return (union sltentry *) &(SLT (objfile)[index * sizeof (union sltentry)]);
+}
+
+/* Get the low address associated with some symbol (typically the start
+ of a particular source file or module). Since that information is not
+ stored as part of the DNTT_TYPE_MODULE or DNTT_TYPE_SRCFILE symbol we must infer it from
+ the existance of DNTT_TYPE_FUNCTION symbols. */
+
+static unsigned long
+hpread_get_textlow (global, index, objfile, symcount)
+ int global;
+ int index;
+ struct objfile *objfile;
+ int symcount;
+{
+ union dnttentry *dn_bufp;
+ struct minimal_symbol *msymbol;
+
+ /* Look for a DNTT_TYPE_FUNCTION symbol. */
+ if (index < symcount) /* symcount is the number of symbols in */
+ { /* the dbinfo, LNTT table */
+ do
+ {
+ if (global)
+ dn_bufp = hpread_get_gntt (index++, objfile);
+ else
+ dn_bufp = hpread_get_lntt (index++, objfile);
+ }
+ while (dn_bufp->dblock.kind != DNTT_TYPE_FUNCTION
+ && dn_bufp->dblock.kind != DNTT_TYPE_DOC_FUNCTION
+ && dn_bufp->dblock.kind != DNTT_TYPE_END
+ && index < symcount);
+ }
+
+ /* Avoid going past a DNTT_TYPE_END when looking for a DNTT_TYPE_FUNCTION. This
+ might happen when a sourcefile has no functions. */
+ if (dn_bufp->dblock.kind == DNTT_TYPE_END)
+ return 0;
+
+ /* Avoid going past the end of the LNTT file */
+ if (index == symcount)
+ return 0;
+
+ /* The minimal symbols are typically more accurate for some reason. */
+ if (dn_bufp->dblock.kind == DNTT_TYPE_FUNCTION)
+ msymbol = lookup_minimal_symbol (dn_bufp->dfunc.name + VT (objfile), NULL,
+ objfile);
+ else /* must be a DNTT_TYPE_DOC_FUNCTION */
+ msymbol = lookup_minimal_symbol (dn_bufp->ddocfunc.name + VT (objfile), NULL,
+ objfile);
+
+ if (msymbol)
+ return SYMBOL_VALUE_ADDRESS (msymbol);
+ else
+ return dn_bufp->dfunc.lowaddr;
+}
+
+/* Allocate and partially fill a partial symtab. It will be
+ completely filled at the end of the symbol list.
+
+ SYMFILE_NAME is the name of the symbol-file we are reading from, and ADDR
+ is the address relative to which its symbols are (incremental) or 0
+ (normal). */
+
+static struct partial_symtab *
+hpread_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;
+{
+ int offset = ANOFFSET (section_offsets, SECT_OFF_TEXT);
+ extern void hpread_psymtab_to_symtab ();
+ struct partial_symtab *result =
+ start_psymtab_common (objfile, section_offsets,
+ filename, textlow, global_syms, static_syms);
+
+ result->textlow += offset;
+ result->read_symtab_private = (char *)
+ obstack_alloc (&objfile->psymbol_obstack, sizeof (struct symloc));
+ LDSYMOFF (result) = ldsymoff;
+ result->read_symtab = hpread_psymtab_to_symtab;
+
+ return result;
+}
+
+
+/* Close off the current usage of PST.
+ Returns PST or NULL if the partial symtab was empty and thrown away.
+
+ capping_symbol_offset --Byte index in LNTT or GNTT of the
+ last symbol processed during the build
+ of the previous pst.
+
+ FIXME: List variables and peculiarities of same. */
+
+static struct partial_symtab *
+hpread_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;
+{
+ int i;
+ struct objfile *objfile = pst->objfile;
+ int offset = ANOFFSET (pst->section_offsets, SECT_OFF_TEXT);
+
+#ifdef DUMPING
+ /* Turn on to see what kind of a psymtab we've built. */
+ static int dumping = 0;
+#endif
+
+ if (capping_symbol_offset != -1)
+ LDSYMLEN (pst) = capping_symbol_offset - LDSYMOFF (pst);
+ else
+ LDSYMLEN (pst) = 0;
+ pst->texthigh = capping_text + offset;
+
+ 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);
+
+#ifdef DUMPING
+ if (dumping)
+ {
+ printf ("\nPst %s, LDSYMOFF %x (%x), LDSYMLEN %x (%x), globals %d, statics %d\n",
+ pst->filename,
+ LDSYMOFF (pst),
+ LDSYMOFF (pst) / sizeof (struct dntt_type_block),
+ LDSYMLEN (pst),
+ LDSYMLEN (pst) / sizeof (struct dntt_type_block),
+ pst->n_global_syms, pst->n_static_syms);
+ }
+#endif
+
+ 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.
+ Empty psymtabs happen as a result of header files which don't have
+ any symbols in them. There can be a lot of them. But this check
+ is wrong, in that a psymtab with N_SLINE entries but nothing else
+ is not empty, but we don't realize that. Fixing that without slowing
+ things down might be tricky.
+ It's also wrong if we're using the quick look-up tables, as
+ we can get empty psymtabs from modules with no routines in
+ them. */
+
+ discard_psymtab (pst);
+
+ /* Indicate that psymtab was thrown away. */
+ pst = (struct partial_symtab *) NULL;
+
+ }
+ return pst;
+}
+
+
+/* End of hp-psymtab-read.c */
+
+/* Set indentation to 4 spaces for Emacs; this file is
+ mostly non-GNU-ish in its style :-( */
+#if 0
+***Local Variables:
+***c - basic - offset:4
+*** End:
+#endif
+
+
diff --git a/gdb/hp-symtab-read.c b/gdb/hp-symtab-read.c
new file mode 100644
index 00000000000..90d4a10c6bc
--- /dev/null
+++ b/gdb/hp-symtab-read.c
@@ -0,0 +1,3988 @@
+/* Read hp debug symbols and convert to internal format, for GDB.
+ Copyright 1993, 1996 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Written by the Center for Software Science at the University of Utah
+ and by Cygnus Support. */
+
+/* Common include for hp-symtab-read.c and hp-psymtab-read.c.
+ * Note this has nested includes for a bunch of stuff.
+ */
+#include "defs.h"
+#include "symtab.h"
+#include "gdbtypes.h"
+#include "hpread.h"
+#include "demangle.h"
+#include "complaints.h"
+
+
+
+
+static struct complaint hpread_unhandled_end_common_complaint =
+{
+ "unhandled symbol in hp-symtab-read.c: DNTT_TYPE_COMMON/DNTT_TYPE_END.\n", 0, 0
+};
+
+static struct complaint hpread_unhandled_type_complaint =
+{
+ "hpread_type_translate: unhandled type code.", 0, 0
+};
+
+static struct complaint hpread_struct_complaint =
+{
+ "hpread_read_struct_type: expected SVAR type...", 0, 0
+};
+
+static struct complaint hpread_array_complaint =
+{
+ "error in hpread_array_type.", 0, 0
+};
+
+static struct complaint hpread_type_lookup_complaint =
+{
+ "error in hpread_type_lookup().", 0, 0
+};
+
+
+static struct complaint hpread_unexpected_end_complaint =
+{
+ "internal error in hp-symtab-read.c: Unexpected DNTT_TYPE_END kind.", 0, 0
+};
+
+static struct complaint hpread_tagdef_complaint =
+{
+ "error processing class tagdef", 0, 0
+};
+
+static struct complaint hpread_unhandled_common_complaint =
+{
+ "unhandled symbol in hp-symtab-read.c: DNTT_TYPE_COMMON.", 0, 0
+};
+
+static struct complaint hpread_unhandled_blockdata_complaint =
+{
+ "unhandled symbol in hp-symtab-read.c: DNTT_TYPE_BLOCKDATA.", 0, 0
+};
+
+
+/* Forward procedure declarations */
+
+static unsigned long hpread_get_scope_start
+ PARAMS ((sltpointer, struct objfile *));
+
+static unsigned long hpread_get_line
+ PARAMS ((sltpointer, struct objfile *));
+
+static CORE_ADDR hpread_get_location
+ PARAMS ((sltpointer, struct objfile *));
+
+static void hpread_psymtab_to_symtab_1
+ PARAMS ((struct partial_symtab *));
+
+void hpread_psymtab_to_symtab
+ PARAMS ((struct partial_symtab *));
+
+static struct symtab *hpread_expand_symtab
+ PARAMS ((struct objfile *, int, int, CORE_ADDR, int,
+ struct section_offsets *, char *));
+
+static int hpread_type_translate
+ PARAMS ((dnttpointer));
+
+static struct type **hpread_lookup_type
+ PARAMS ((dnttpointer, struct objfile *));
+
+static struct type *hpread_alloc_type
+ PARAMS ((dnttpointer, struct objfile *));
+
+static struct type *hpread_read_enum_type
+ PARAMS ((dnttpointer, union dnttentry *, struct objfile *));
+
+static struct type *hpread_read_function_type
+ PARAMS ((dnttpointer, union dnttentry *, struct objfile *, int));
+
+static struct type *hpread_read_doc_function_type
+ PARAMS ((dnttpointer, union dnttentry *, struct objfile *, int));
+
+static struct type *hpread_read_struct_type
+ PARAMS ((dnttpointer, union dnttentry *, struct objfile *));
+
+static struct type *hpread_get_nth_template_arg
+ PARAMS ((struct objfile *, int));
+
+static struct type * hpread_read_templ_arg_type
+ PARAMS ((dnttpointer, union dnttentry *, struct objfile *, char *));
+
+static struct type *hpread_read_set_type
+ PARAMS ((dnttpointer, union dnttentry *, struct objfile *));
+
+static struct type * hpread_read_array_type
+ PARAMS ((dnttpointer, union dnttentry *dn_bufp, struct objfile *objfile));
+
+static struct type *hpread_read_subrange_type
+ PARAMS ((dnttpointer, union dnttentry *, struct objfile *));
+
+static struct type * hpread_type_lookup
+ PARAMS ((dnttpointer, struct objfile *));
+
+static sltpointer hpread_record_lines
+ PARAMS ((struct subfile *, sltpointer, sltpointer,
+ struct objfile *, CORE_ADDR));
+
+static void hpread_process_one_debug_symbol
+ PARAMS ((union dnttentry *, char *, struct section_offsets *,
+ struct objfile *, CORE_ADDR, int, char *, int, int * ));
+
+static int hpread_get_scope_depth
+ PARAMS ((union dnttentry *, struct objfile *, int));
+
+static void fix_static_member_physnames
+ PARAMS ((struct type *, char *, struct objfile *));
+
+static void fixup_class_method_type
+ PARAMS ((struct type *, struct type *, struct objfile *));
+
+static void hpread_adjust_bitoffsets PARAMS ((struct type *, int));
+
+static dnttpointer hpread_get_next_skip_over_anon_unions
+ PARAMS ((int, dnttpointer, union dnttentry **, struct objfile *));
+
+/* Global to indicate presence of HP-compiled objects,
+ in particular, SOM executable file with SOM debug info
+ Defined in symtab.c, used in hppa-tdep.c. */
+extern int hp_som_som_object_present;
+
+/* Static used to indicate a class type that requires a
+ fix-up of one of its method types */
+static struct type * fixup_class = NULL;
+
+/* Static used to indicate the method type that is to be
+ used to fix-up the type for fixup_class */
+static struct type * fixup_method = NULL;
+
+
+
+/* Get the nesting depth for the source line identified by INDEX. */
+
+static unsigned long
+hpread_get_scope_start (index, objfile)
+ sltpointer index;
+ struct objfile *objfile;
+{
+ union sltentry *sl_bufp;
+
+ sl_bufp = hpread_get_slt (index, objfile);
+ return sl_bufp->sspec.backptr.dnttp.index;
+}
+
+/* Get the source line number the the line identified by INDEX. */
+
+static unsigned long
+hpread_get_line (index, objfile)
+ sltpointer index;
+ struct objfile *objfile;
+{
+ union sltentry *sl_bufp;
+
+ sl_bufp = hpread_get_slt (index, objfile);
+ return sl_bufp->snorm.line;
+}
+
+/* Find the code address associated with a given sltpointer */
+
+static CORE_ADDR
+hpread_get_location (index, objfile)
+ sltpointer index;
+ struct objfile *objfile;
+{
+ union sltentry *sl_bufp;
+ int i;
+
+ /* code location of special sltentrys is determined from context */
+ sl_bufp = hpread_get_slt (index, objfile);
+
+ if (sl_bufp->snorm.sltdesc == SLT_END)
+ {
+ /* find previous normal sltentry and get address */
+ for (i = 0; ((sl_bufp->snorm.sltdesc != SLT_NORMAL) &&
+ (sl_bufp->snorm.sltdesc != SLT_NORMAL_OFFSET) &&
+ (sl_bufp->snorm.sltdesc != SLT_EXIT)); i++)
+ sl_bufp = hpread_get_slt (index - i, objfile);
+ if (sl_bufp->snorm.sltdesc == SLT_NORMAL_OFFSET)
+ return sl_bufp->snormoff.address;
+ else
+ return sl_bufp->snorm.address;
+ }
+
+ /* find next normal sltentry and get address */
+ for (i = 0; ((sl_bufp->snorm.sltdesc != SLT_NORMAL) &&
+ (sl_bufp->snorm.sltdesc != SLT_NORMAL_OFFSET) &&
+ (sl_bufp->snorm.sltdesc != SLT_EXIT)); i++)
+ sl_bufp = hpread_get_slt (index + i, objfile);
+ if (sl_bufp->snorm.sltdesc == SLT_NORMAL_OFFSET)
+ return sl_bufp->snormoff.address;
+ else
+ return sl_bufp->snorm.address;
+}
+
+
+/* Return 1 if an HP debug symbol of type KIND has a name associated with
+ * it, else return 0. (This function is not currently used, but I'll
+ * leave it here in case it proves useful later on. - RT).
+ */
+
+int
+hpread_has_name (kind)
+ enum dntt_entry_type kind;
+{
+ switch (kind)
+ {
+ case DNTT_TYPE_SRCFILE:
+ case DNTT_TYPE_MODULE:
+ case DNTT_TYPE_FUNCTION:
+ case DNTT_TYPE_DOC_FUNCTION:
+ case DNTT_TYPE_ENTRY:
+ case DNTT_TYPE_IMPORT:
+ case DNTT_TYPE_LABEL:
+ case DNTT_TYPE_FPARAM:
+ case DNTT_TYPE_SVAR:
+ case DNTT_TYPE_DVAR:
+ case DNTT_TYPE_CONST:
+ case DNTT_TYPE_TYPEDEF:
+ case DNTT_TYPE_TAGDEF:
+ case DNTT_TYPE_MEMENUM:
+ case DNTT_TYPE_FIELD:
+ case DNTT_TYPE_SA:
+ case DNTT_TYPE_BLOCKDATA:
+ case DNTT_TYPE_MEMFUNC:
+ case DNTT_TYPE_DOC_MEMFUNC:
+ return 1;
+
+ case DNTT_TYPE_BEGIN:
+ case DNTT_TYPE_END:
+ case DNTT_TYPE_POINTER:
+ case DNTT_TYPE_ENUM:
+ case DNTT_TYPE_SET:
+ case DNTT_TYPE_ARRAY:
+ case DNTT_TYPE_STRUCT:
+ case DNTT_TYPE_UNION:
+ case DNTT_TYPE_VARIANT:
+ case DNTT_TYPE_FILE:
+ case DNTT_TYPE_FUNCTYPE:
+ case DNTT_TYPE_SUBRANGE:
+ case DNTT_TYPE_WITH:
+ case DNTT_TYPE_COMMON:
+ case DNTT_TYPE_COBSTRUCT:
+ case DNTT_TYPE_XREF:
+ case DNTT_TYPE_MACRO:
+ case DNTT_TYPE_CLASS_SCOPE:
+ case DNTT_TYPE_REFERENCE:
+ case DNTT_TYPE_PTRMEM:
+ case DNTT_TYPE_PTRMEMFUNC:
+ case DNTT_TYPE_CLASS:
+ case DNTT_TYPE_GENFIELD:
+ case DNTT_TYPE_VFUNC:
+ case DNTT_TYPE_MEMACCESS:
+ case DNTT_TYPE_INHERITANCE:
+ case DNTT_TYPE_FRIEND_CLASS:
+ case DNTT_TYPE_FRIEND_FUNC:
+ case DNTT_TYPE_MODIFIER:
+ case DNTT_TYPE_OBJECT_ID:
+ case DNTT_TYPE_TEMPLATE:
+ case DNTT_TYPE_TEMPLATE_ARG:
+ case DNTT_TYPE_FUNC_TEMPLATE:
+ case DNTT_TYPE_LINK:
+ /* DNTT_TYPE_DYN_ARRAY_DESC ? */
+ /* DNTT_TYPE_DESC_SUBRANGE ? */
+ /* DNTT_TYPE_BEGIN_EXT ? */
+ /* DNTT_TYPE_INLN ? */
+ /* DNTT_TYPE_INLN_LIST ? */
+ /* DNTT_TYPE_ALIAS ? */
+ default:
+ return 0;
+ }
+}
+
+/* Do the dirty work of reading in the full symbol from a partial symbol
+ table. */
+
+static void
+hpread_psymtab_to_symtab_1 (pst)
+ struct partial_symtab *pst;
+{
+ struct cleanup *old_chain;
+ int i;
+
+ /* Get out quick if passed junk. */
+ if (!pst)
+ return;
+
+ /* Complain if we've already read in this symbol table. */
+ 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 (" ", gdb_stdout);
+ wrap_here ("");
+ fputs_filtered ("and ", gdb_stdout);
+ wrap_here ("");
+ printf_filtered ("%s...", pst->dependencies[i]->filename);
+ wrap_here (""); /* Flush output */
+ gdb_flush (gdb_stdout);
+ }
+ hpread_psymtab_to_symtab_1 (pst->dependencies[i]);
+ }
+
+ /* If it's real... */
+ if (LDSYMLEN (pst))
+ {
+ /* Init stuff necessary for reading in symbols */
+ buildsym_init ();
+ old_chain = make_cleanup (really_free_pendings, 0);
+
+ pst->symtab =
+ hpread_expand_symtab (pst->objfile, LDSYMOFF (pst), LDSYMLEN (pst),
+ pst->textlow, pst->texthigh - pst->textlow,
+ pst->section_offsets, pst->filename);
+ 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. */
+
+void
+hpread_psymtab_to_symtab (pst)
+ struct partial_symtab *pst;
+{
+ /* Get out quick if given junk. */
+ if (!pst)
+ return;
+
+ /* Sanity check. */
+ if (pst->readin)
+ {
+ fprintf (stderr, "Psymtab for %s already read in. Shouldn't happen.\n",
+ pst->filename);
+ return;
+ }
+
+ /* elz: setting the flag to indicate that the code of the target
+ was compiled using an HP compiler (aCC, cc)
+ the processing_acc_compilation variable is declared in the
+ file buildsym.h, the HP_COMPILED_TARGET is defined to be equal
+ to 3 in the file tm_hppa.h*/
+
+ processing_gcc_compilation = 0;
+
+ 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);
+ gdb_flush (gdb_stdout);
+ }
+
+ hpread_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.
+
+ DESC is the file descriptor for the file, positioned at the
+ beginning of the symtab
+ SYM_OFFSET is the offset within the file of
+ the beginning of the symbols we want to read
+ SYM_SIZE is the size of the symbol info to read in.
+ TEXT_OFFSET is the beginning of the text segment we are reading symbols for
+ TEXT_SIZE is the size of the text segment read in.
+ SECTION_OFFSETS are the relocation offsets which get added to each symbol. */
+
+static struct symtab *
+hpread_expand_symtab (objfile, sym_offset, sym_size, text_offset, text_size,
+ section_offsets, filename)
+ struct objfile *objfile;
+ int sym_offset;
+ int sym_size;
+ CORE_ADDR text_offset;
+ int text_size;
+ struct section_offsets *section_offsets;
+ char *filename;
+{
+ char *namestring;
+ union dnttentry *dn_bufp;
+ unsigned max_symnum;
+ int at_module_boundary = 0;
+ /* 1 => at end, -1 => at beginning */
+
+ int sym_index = sym_offset / sizeof (struct dntt_type_block);
+
+ current_objfile = objfile;
+ subfile_stack = 0;
+
+ last_source_file = 0;
+
+ /* Demangling style -- if EDG style already set, don't change it,
+ as HP style causes some problems with the KAI EDG compiler */
+ if (current_demangling_style != edg_demangling) {
+ /* Otherwise, ensure that we are using HP style demangling */
+ set_demangling_style (HP_DEMANGLING_STYLE_STRING);
+ }
+
+ dn_bufp = hpread_get_lntt (sym_index, objfile);
+ if (!((dn_bufp->dblock.kind == (unsigned char) DNTT_TYPE_SRCFILE) ||
+ (dn_bufp->dblock.kind == (unsigned char) DNTT_TYPE_MODULE)))
+ {
+ start_symtab ("globals", NULL, 0);
+ record_debugformat ("HP");
+ }
+
+ /* The psymtab builder (hp-psymtab-read.c) is the one that
+ * determined the "sym_size" argument (i.e. how many DNTT symbols
+ * are in this symtab), which we use to compute "max_symnum"
+ * (point in DNTT to which we read).
+ *
+ * Perhaps this should be changed so that
+ * process_one_debug_symbol() "knows" when
+ * to stop reading (based on reading from the MODULE to the matching
+ * END), and take out this reliance on a #-syms being passed in...
+ * (I'm worried about the reliability of this number). But I'll
+ * leave it as-is, for now. - RT
+ *
+ * The change above has been made. I've left the "for" loop control
+ * in to prepare for backing this out again. -JB
+ */
+ max_symnum = sym_size / sizeof (struct dntt_type_block);
+ /* No reason to multiply on pst side and divide on sym side... FIXME */
+
+ /* Read in and process each debug symbol within the specified range.
+ */
+ for (symnum = 0;
+ symnum < max_symnum;
+ symnum++)
+ {
+ QUIT; /* Allow this to be interruptable */
+ dn_bufp = hpread_get_lntt (sym_index + symnum, objfile);
+
+ if (dn_bufp->dblock.extension)
+ continue;
+
+ /* Yow! We call SET_NAMESTRING on things without names! */
+ SET_NAMESTRING (dn_bufp, &namestring, objfile);
+
+ hpread_process_one_debug_symbol (dn_bufp, namestring, section_offsets,
+ objfile, text_offset, text_size,
+ filename, symnum + sym_index,
+ &at_module_boundary
+ );
+
+ /* OLD COMMENTS: This routine is only called for psts. All psts
+ * correspond to MODULES. If we ever do lazy-reading of globals
+ * from the LNTT, then there will be a pst which ends when the
+ * LNTT ends, and not at an END MODULE entry. Then we'll have
+ * to re-visit this break.
+
+ if( at_end_of_module )
+ break;
+
+ */
+
+ /* We no longer break out of the loop when we reach the end of a
+ module. The reason is that with CTTI, the compiler can generate
+ function symbols (for template function instantiations) which are not
+ in any module; typically they show up beyond a module's end, and
+ before the next module's start. We include them in the current
+ module. However, we still don't trust the MAX_SYMNUM value from
+ the psymtab, so we break out if we enter a new module. */
+
+ if (at_module_boundary == -1)
+ break;
+ }
+
+ current_objfile = NULL;
+ hp_som_som_object_present = 1; /* Indicate we've processed an HP SOM SOM file */
+
+ return end_symtab (text_offset + text_size, objfile, 0);
+}
+
+
+
+
+/* Convert basic types from HP debug format into GDB internal format. */
+
+static int
+hpread_type_translate (typep)
+ dnttpointer typep;
+{
+ if (!typep.dntti.immediate) {
+ error ("error in hpread_type_translate\n.");
+ return;
+ }
+
+ switch (typep.dntti.type)
+ {
+ case HP_TYPE_BOOLEAN:
+ case HP_TYPE_BOOLEAN_S300_COMPAT:
+ case HP_TYPE_BOOLEAN_VAX_COMPAT:
+ return FT_BOOLEAN;
+ case HP_TYPE_CHAR: /* C signed char, C++ plain char */
+
+ case HP_TYPE_WIDE_CHAR:
+ return FT_CHAR;
+ case HP_TYPE_INT:
+ if (typep.dntti.bitlength <= 8)
+ return FT_SIGNED_CHAR; /* C++ signed char */
+ if (typep.dntti.bitlength <= 16)
+ return FT_SHORT;
+ if (typep.dntti.bitlength <= 32)
+ return FT_INTEGER;
+ return FT_LONG_LONG;
+ case HP_TYPE_LONG:
+ if (typep.dntti.bitlength <= 8)
+ return FT_SIGNED_CHAR; /* C++ signed char. */
+ return FT_LONG;
+ case HP_TYPE_UNSIGNED_LONG:
+ if (typep.dntti.bitlength <= 8)
+ return FT_UNSIGNED_CHAR; /* C/C++ unsigned char */
+ if (typep.dntti.bitlength <= 16)
+ return FT_UNSIGNED_SHORT;
+ if (typep.dntti.bitlength <= 32)
+ return FT_UNSIGNED_LONG;
+ return FT_UNSIGNED_LONG_LONG;
+ case HP_TYPE_UNSIGNED_INT:
+ if (typep.dntti.bitlength <= 8)
+ return FT_UNSIGNED_CHAR;
+ if (typep.dntti.bitlength <= 16)
+ return FT_UNSIGNED_SHORT;
+ if (typep.dntti.bitlength <= 32)
+ return FT_UNSIGNED_INTEGER;
+ return FT_UNSIGNED_LONG_LONG;
+ case HP_TYPE_REAL:
+ case HP_TYPE_REAL_3000:
+ case HP_TYPE_DOUBLE:
+ if (typep.dntti.bitlength == 64)
+ return FT_DBL_PREC_FLOAT;
+ if (typep.dntti.bitlength == 128)
+ return FT_EXT_PREC_FLOAT;
+ return FT_FLOAT;
+ case HP_TYPE_COMPLEX:
+ case HP_TYPE_COMPLEXS3000:
+ if (typep.dntti.bitlength == 128)
+ return FT_DBL_PREC_COMPLEX;
+ if (typep.dntti.bitlength == 192)
+ return FT_EXT_PREC_COMPLEX;
+ return FT_COMPLEX;
+ case HP_TYPE_VOID:
+ return FT_VOID;
+ case HP_TYPE_STRING200:
+ case HP_TYPE_LONGSTRING200:
+ case HP_TYPE_FTN_STRING_SPEC:
+ case HP_TYPE_MOD_STRING_SPEC:
+ case HP_TYPE_MOD_STRING_3000:
+ case HP_TYPE_FTN_STRING_S300_COMPAT:
+ case HP_TYPE_FTN_STRING_VAX_COMPAT:
+ return FT_STRING;
+ case HP_TYPE_TEMPLATE_ARG:
+ return FT_TEMPLATE_ARG;
+ case HP_TYPE_TEXT:
+ case HP_TYPE_FLABEL:
+ case HP_TYPE_PACKED_DECIMAL:
+ case HP_TYPE_ANYPOINTER:
+ case HP_TYPE_GLOBAL_ANYPOINTER:
+ case HP_TYPE_LOCAL_ANYPOINTER:
+ default:
+ warning ("hpread_type_translate: unhandled type code.\n");
+ return FT_VOID;
+ }
+}
+
+/* Given a position in the DNTT, return a pointer to the
+ * already-built "struct type" (if any), for the type defined
+ * at that position.
+ */
+
+static struct type **
+hpread_lookup_type (hp_type, objfile)
+ dnttpointer hp_type;
+ struct objfile *objfile;
+{
+ unsigned old_len;
+ int index = hp_type.dnttp.index;
+ int size_changed = 0;
+
+ /* The immediate flag indicates this doesn't actually point to
+ * a type DNTT.
+ */
+ if (hp_type.dntti.immediate)
+ return NULL;
+
+ /* For each objfile, we maintain a "type vector".
+ * This an array of "struct type *"'s with one pointer per DNTT index.
+ * Given a DNTT index, we look in this array to see if we have
+ * already processed this DNTT and if it is a type definition.
+ * If so, then we can locate a pointer to the already-built
+ * "struct type", and not build it again.
+ *
+ * The need for this arises because our DNTT-walking code wanders
+ * around. In particular, it will encounter the same type multiple
+ * times (once for each object of that type). We don't want to
+ * built multiple "struct type"'s for the same thing.
+ *
+ * Having said this, I should point out that this type-vector is
+ * an expensive way to keep track of this. If most DNTT entries are
+ * 3 words, the type-vector will be 1/3 the size of the DNTT itself.
+ * Alternative solutions:
+ * - Keep a compressed or hashed table. Less memory, but more expensive
+ * to search and update.
+ * - (Suggested by JB): Overwrite the DNTT entry itself
+ * with the info. Create a new type code "ALREADY_BUILT", and modify
+ * the DNTT to have that type code and point to the already-built entry.
+ * -RT
+ */
+
+ if (index < LNTT_SYMCOUNT (objfile))
+ {
+ if (index >= TYPE_VECTOR_LENGTH (objfile))
+ {
+ old_len = TYPE_VECTOR_LENGTH (objfile);
+
+ /* See if we need to allocate a type-vector. */
+ if (old_len == 0)
+ {
+ TYPE_VECTOR_LENGTH(objfile) = LNTT_SYMCOUNT (objfile) + GNTT_SYMCOUNT (objfile);
+ TYPE_VECTOR (objfile) = (struct type **)
+ xmmalloc (objfile->md, TYPE_VECTOR_LENGTH (objfile) * sizeof (struct type *));
+ memset (&TYPE_VECTOR (objfile)[old_len], 0,
+ (TYPE_VECTOR_LENGTH (objfile) - old_len) *
+ sizeof (struct type *));
+ }
+
+ /* See if we need to resize type-vector. With my change to
+ * initially allocate a correct-size type-vector, this code
+ * should no longer trigger.
+ */
+ while (index >= TYPE_VECTOR_LENGTH (objfile)) {
+ TYPE_VECTOR_LENGTH (objfile) *= 2;
+ size_changed = 1;
+ }
+ if (size_changed) {
+ TYPE_VECTOR (objfile) = (struct type **)
+ xmrealloc (objfile -> md,
+ (char *) TYPE_VECTOR (objfile),
+ (TYPE_VECTOR_LENGTH (objfile) * sizeof (struct type *)));
+
+ memset (&TYPE_VECTOR (objfile)[old_len], 0,
+ (TYPE_VECTOR_LENGTH (objfile) - old_len) *
+ sizeof (struct type *));
+ }
+
+ }
+ return &TYPE_VECTOR (objfile)[index];
+ }
+ else
+ return NULL;
+}
+
+/* Possibly allocate a GDB internal type so we can internalize HP_TYPE.
+ Note we'll just return the address of a GDB internal type if we already
+ have it lying around. */
+
+static struct type *
+hpread_alloc_type (hp_type, objfile)
+ dnttpointer hp_type;
+ struct objfile *objfile;
+{
+ struct type **type_addr;
+
+ type_addr = hpread_lookup_type (hp_type, objfile);
+ if (*type_addr == 0) {
+ *type_addr = alloc_type (objfile);
+
+ /* A hack - if we really are a C++ class symbol, then this default
+ * will get overriden later on.
+ */
+ TYPE_CPLUS_SPECIFIC (*type_addr)
+ = (struct cplus_struct_type *) &cplus_struct_default;
+ }
+
+ return *type_addr;
+}
+
+/* Read a native enumerated type and return it in GDB internal form. */
+
+static struct type *
+hpread_read_enum_type (hp_type, dn_bufp, objfile)
+ dnttpointer hp_type;
+ union dnttentry *dn_bufp;
+ struct objfile *objfile;
+{
+ struct type *type;
+ struct pending **symlist, *osyms, *syms;
+ struct pending *local_list = NULL;
+ int o_nsyms, nsyms = 0;
+ dnttpointer mem;
+ union dnttentry *memp;
+ char *name;
+ long n;
+ struct symbol *sym;
+
+ /* Allocate a GDB type. If we've already read in this enum type,
+ * it'll return the already built GDB type, so stop here.
+ * (Note: I added this check, to conform with what's done for
+ * struct, union, class.
+ * I assume this is OK. - RT)
+ */
+ type = hpread_alloc_type (hp_type, objfile);
+ if (TYPE_CODE (type) == TYPE_CODE_ENUM)
+ return type;
+
+ /* HP C supports "sized enums", where a specifier such as "short" or
+ "char" can be used to get enums of different sizes. So don't assume
+ an enum is always 4 bytes long. pai/1997-08-21 */
+ TYPE_LENGTH (type) = dn_bufp->denum.bitlength / 8;
+
+ symlist = &file_symbols;
+ osyms = *symlist;
+ o_nsyms = osyms ? osyms->nsyms : 0;
+
+ /* Get a name for each member and add it to our list of members.
+ * The list of "mem" SOM records we are walking should all be
+ * SOM type DNTT_TYPE_MEMENUM (not checked).
+ */
+ mem = dn_bufp->denum.firstmem;
+ while (mem.word && mem.word != DNTTNIL)
+ {
+ memp = hpread_get_lntt (mem.dnttp.index, objfile);
+
+ name = VT (objfile) + memp->dmember.name;
+ sym = (struct symbol *) obstack_alloc (&objfile->symbol_obstack,
+ sizeof (struct symbol));
+ memset (sym, 0, sizeof (struct symbol));
+ SYMBOL_NAME (sym) = obsavestring (name, strlen (name),
+ &objfile->symbol_obstack);
+ SYMBOL_CLASS (sym) = LOC_CONST;
+ SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
+ SYMBOL_VALUE (sym) = memp->dmember.value;
+ add_symbol_to_list (sym, symlist);
+ nsyms++;
+ mem = memp->dmember.nextmem;
+ }
+
+ /* Now that we know more about the enum, fill in more info. */
+ TYPE_CODE (type) = TYPE_CODE_ENUM;
+ TYPE_FLAGS (type) &= ~TYPE_FLAG_STUB;
+ TYPE_NFIELDS (type) = nsyms;
+ TYPE_FIELDS (type) = (struct field *)
+ obstack_alloc (&objfile->type_obstack, sizeof (struct field) * nsyms);
+
+ /* Find the symbols for the members 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_BITPOS (type, n) = SYMBOL_VALUE (xsym);
+ TYPE_FIELD_BITSIZE (type, n) = 0;
+ }
+ if (syms == osyms)
+ break;
+ }
+
+ return type;
+}
+
+/* Read and internalize a native function debug symbol. */
+
+static struct type *
+hpread_read_function_type (hp_type, dn_bufp, objfile, newblock)
+ dnttpointer hp_type;
+ union dnttentry *dn_bufp;
+ struct objfile *objfile;
+ int newblock;
+{
+ struct type *type, *type1;
+ struct pending *syms;
+ struct pending *local_list = NULL;
+ int nsyms = 0;
+ dnttpointer param;
+ union dnttentry *paramp;
+ char *name;
+ long n;
+ struct symbol *sym;
+ int record_args = 1;
+
+ /* See if we've already read in this type. */
+ type = hpread_alloc_type (hp_type, objfile);
+ if (TYPE_CODE (type) == TYPE_CODE_FUNC)
+ {
+ record_args = 0; /* already read in, don't modify type */
+ }
+ else
+ {
+ /* Nope, so read it in and store it away. */
+ if (dn_bufp->dblock.kind == DNTT_TYPE_FUNCTION ||
+ dn_bufp->dblock.kind == DNTT_TYPE_MEMFUNC)
+ type1 = lookup_function_type (hpread_type_lookup (dn_bufp->dfunc.retval,
+ objfile));
+ else if (dn_bufp->dblock.kind == DNTT_TYPE_FUNCTYPE)
+ type1 = lookup_function_type (hpread_type_lookup (dn_bufp->dfunctype.retval,
+ objfile));
+ else /* expect DNTT_TYPE_FUNC_TEMPLATE */
+ type1 = lookup_function_type (hpread_type_lookup (dn_bufp->dfunc_template.retval,
+ objfile));
+ memcpy ((char *) type, (char *) type1, sizeof (struct type));
+
+ /* Mark it -- in the middle of processing */
+ TYPE_FLAGS (type) |= TYPE_FLAG_INCOMPLETE;
+ }
+
+ /* Now examine each parameter noting its type, location, and a
+ wealth of other information. */
+ if (dn_bufp->dblock.kind == DNTT_TYPE_FUNCTION ||
+ dn_bufp->dblock.kind == DNTT_TYPE_MEMFUNC)
+ param = dn_bufp->dfunc.firstparam;
+ else if (dn_bufp->dblock.kind == DNTT_TYPE_FUNCTYPE)
+ param = dn_bufp->dfunctype.firstparam;
+ else /* expect DNTT_TYPE_FUNC_TEMPLATE */
+ param = dn_bufp->dfunc_template.firstparam;
+ while (param.word && param.word != DNTTNIL)
+ {
+ paramp = hpread_get_lntt (param.dnttp.index, objfile);
+ nsyms++;
+ param = paramp->dfparam.nextparam;
+
+ /* Get the name. */
+ name = VT (objfile) + paramp->dfparam.name;
+ sym = (struct symbol *) obstack_alloc (&objfile->symbol_obstack,
+ sizeof (struct symbol));
+ (void) memset (sym, 0, sizeof (struct symbol));
+ SYMBOL_NAME (sym) = obsavestring (name, strlen (name),
+ &objfile->symbol_obstack);
+
+ /* Figure out where it lives. */
+ if (paramp->dfparam.regparam)
+ SYMBOL_CLASS (sym) = LOC_REGPARM;
+ else if (paramp->dfparam.indirect)
+ SYMBOL_CLASS (sym) = LOC_REF_ARG;
+ else
+ SYMBOL_CLASS (sym) = LOC_ARG;
+ SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
+ if (paramp->dfparam.copyparam)
+ {
+ SYMBOL_VALUE (sym) = paramp->dfparam.location ;
+#ifdef HPREAD_ADJUST_STACK_ADDRESS
+ SYMBOL_VALUE (sym)
+ += HPREAD_ADJUST_STACK_ADDRESS (CURRENT_FUNCTION_VALUE (objfile));
+#endif
+ /* This is likely a pass-by-invisible reference parameter,
+ Hack on the symbol class to make GDB happy. */
+ /* ??rehrauer: This appears to be broken w/r/t to passing
+ C values of type float and struct. Perhaps this ought
+ to be highighted as a special case, but for now, just
+ allowing these to be LOC_ARGs seems to work fine.
+ */
+#if 0
+ SYMBOL_CLASS (sym) = LOC_REGPARM_ADDR;
+#endif
+ }
+ else
+ SYMBOL_VALUE (sym) = paramp->dfparam.location;
+
+ /* Get its type. */
+ SYMBOL_TYPE (sym) = hpread_type_lookup (paramp->dfparam.type, objfile);
+ /* Add it to the symbol list. */
+ /* Note 1 (RT) At the moment, add_symbol_to_list() is also being
+ * called on FPARAM symbols from the process_one_debug_symbol()
+ * level... so parameters are getting added twice! (this shows
+ * up in the symbol dump you get from "maint print symbols ...").
+ * Note 2 (RT) I took out the processing of FPARAM from the
+ * process_one_debug_symbol() level, so at the moment parameters are only
+ * being processed here. This seems to have no ill effect.
+ */
+ /* Note 3 (pai/1997-08-11) I removed the add_symbol_to_list() which put
+ each fparam on the local_symbols list from here. Now we use the
+ local_list to which fparams are added below, and set the param_symbols
+ global to point to that at the end of this routine. */
+ /* elz: I added this new list of symbols which is local to the function.
+ this list is the one which is actually used to build the type for the
+ function rather than the gloabal list pointed to by symlist.
+ Using a global list to keep track of the parameters is wrong, because
+ this function is called recursively if one parameter happend to be
+ a function itself with more parameters in it. Adding parameters to the
+ same global symbol list would not work!
+ Actually it did work in case of cc compiled programs where you do
+ not check the parameter lists of the arguments. */
+ add_symbol_to_list (sym, &local_list);
+
+ }
+
+ /* If type was read in earlier, don't bother with modifying
+ the type struct */
+ if (!record_args)
+ goto finish;
+
+ /* Note how many parameters we found. */
+ TYPE_NFIELDS (type) = nsyms;
+ TYPE_FIELDS (type) = (struct field *)
+ obstack_alloc (&objfile->type_obstack,
+ sizeof (struct field) * nsyms);
+
+ /* Find the symbols for the parameters and
+ use them to fill parameter-type information into the function-type.
+ The parameter symbols can be found in the local_list that we just put them on. */
+ /* Note that we preserve the order of the parameters, so
+ that in something like "enum {FOO, LAST_THING=FOO}" we print
+ FOO, not LAST_THING. */
+
+ /* get the parameters types from the local list not the global list
+ so that the type can be correctly constructed for functions which
+ have function as parameters */
+ for (syms = local_list, n = 0; syms; syms = syms->next)
+ {
+ int j = 0;
+ for (j=0; j < syms->nsyms; j++, n++)
+ {
+ struct symbol *xsym = syms->symbol[j];
+ TYPE_FIELD_NAME (type, n) = SYMBOL_NAME (xsym);
+ TYPE_FIELD_TYPE (type, n) = SYMBOL_TYPE (xsym);
+ TYPE_FIELD_BITPOS (type, n) = n;
+ TYPE_FIELD_BITSIZE (type, n) = 0;
+ }
+ }
+ /* Mark it as having been processed */
+ TYPE_FLAGS (type) &= ~(TYPE_FLAG_INCOMPLETE);
+
+ /* Check whether we need to fix-up a class type with this function's type */
+ if (fixup_class && (fixup_method == type))
+ {
+ fixup_class_method_type (fixup_class, fixup_method, objfile);
+ fixup_class = NULL;
+ fixup_method = NULL;
+ }
+
+ /* Set the param list of this level of the context stack
+ to our local list. Do this only if this function was
+ called for creating a new block, and not if it was called
+ simply to get the function type. This prevents recursive
+ invocations from trashing param_symbols. */
+finish:
+ if (newblock)
+ param_symbols = local_list;
+
+ return type;
+}
+
+
+/* Read and internalize a native DOC function debug symbol. */
+/* This is almost identical to hpread_read_function_type(), except
+ * for references to dn_bufp->ddocfunc instead of db_bufp->dfunc.
+ * Since debug information for DOC functions is more likely to be
+ * volatile, please leave it this way.
+ */
+static struct type *
+hpread_read_doc_function_type (hp_type, dn_bufp, objfile, newblock)
+ dnttpointer hp_type;
+ union dnttentry *dn_bufp;
+ struct objfile *objfile;
+ int newblock;
+{
+ struct type *type, *type1;
+ struct pending *syms;
+ struct pending *local_list = NULL;
+ int nsyms = 0;
+ dnttpointer param;
+ union dnttentry *paramp;
+ char *name;
+ long n;
+ struct symbol *sym;
+ int record_args = 1;
+
+ /* See if we've already read in this type. */
+ type = hpread_alloc_type (hp_type, objfile);
+ if (TYPE_CODE (type) == TYPE_CODE_FUNC)
+ {
+ record_args = 0; /* already read in, don't modify type */
+ }
+ else
+ {
+ /* Nope, so read it in and store it away. */
+ if (dn_bufp->dblock.kind == DNTT_TYPE_DOC_FUNCTION ||
+ dn_bufp->dblock.kind == DNTT_TYPE_DOC_MEMFUNC)
+ type1 = lookup_function_type (hpread_type_lookup (dn_bufp->ddocfunc.retval,
+ objfile));
+ memcpy ((char *) type, (char *) type1, sizeof (struct type));
+
+ /* Mark it -- in the middle of processing */
+ TYPE_FLAGS (type) |= TYPE_FLAG_INCOMPLETE;
+ }
+
+ /* Now examine each parameter noting its type, location, and a
+ wealth of other information. */
+ if (dn_bufp->dblock.kind == DNTT_TYPE_DOC_FUNCTION ||
+ dn_bufp->dblock.kind == DNTT_TYPE_DOC_MEMFUNC)
+ param = dn_bufp->ddocfunc.firstparam;
+ while (param.word && param.word != DNTTNIL)
+ {
+ paramp = hpread_get_lntt (param.dnttp.index, objfile);
+ nsyms++;
+ param = paramp->dfparam.nextparam;
+
+ /* Get the name. */
+ name = VT (objfile) + paramp->dfparam.name;
+ sym = (struct symbol *) obstack_alloc (&objfile->symbol_obstack,
+ sizeof (struct symbol));
+ (void) memset (sym, 0, sizeof (struct symbol));
+ SYMBOL_NAME (sym) = name;
+
+ /* Figure out where it lives. */
+ if (paramp->dfparam.regparam)
+ SYMBOL_CLASS (sym) = LOC_REGPARM;
+ else if (paramp->dfparam.indirect)
+ SYMBOL_CLASS (sym) = LOC_REF_ARG;
+ else
+ SYMBOL_CLASS (sym) = LOC_ARG;
+ SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
+ if (paramp->dfparam.copyparam)
+ {
+ SYMBOL_VALUE (sym) = paramp->dfparam.location ;
+#ifdef HPREAD_ADJUST_STACK_ADDRESS
+ SYMBOL_VALUE (sym)
+ += HPREAD_ADJUST_STACK_ADDRESS (CURRENT_FUNCTION_VALUE (objfile));
+#endif
+ /* This is likely a pass-by-invisible reference parameter,
+ Hack on the symbol class to make GDB happy. */
+ /* ??rehrauer: This appears to be broken w/r/t to passing
+ C values of type float and struct. Perhaps this ought
+ to be highighted as a special case, but for now, just
+ allowing these to be LOC_ARGs seems to work fine.
+ */
+#if 0
+ SYMBOL_CLASS (sym) = LOC_REGPARM_ADDR;
+#endif
+ }
+ else
+ SYMBOL_VALUE (sym) = paramp->dfparam.location;
+
+ /* Get its type. */
+ SYMBOL_TYPE (sym) = hpread_type_lookup (paramp->dfparam.type, objfile);
+ /* Add it to the symbol list. */
+ /* Note 1 (RT) At the moment, add_symbol_to_list() is also being
+ * called on FPARAM symbols from the process_one_debug_symbol()
+ * level... so parameters are getting added twice! (this shows
+ * up in the symbol dump you get from "maint print symbols ...").
+ * Note 2 (RT) I took out the processing of FPARAM from the
+ * process_one_debug_symbol() level, so at the moment parameters are only
+ * being processed here. This seems to have no ill effect.
+ */
+ /* Note 3 (pai/1997-08-11) I removed the add_symbol_to_list() which put
+ each fparam on the local_symbols list from here. Now we use the
+ local_list to which fparams are added below, and set the param_symbols
+ global to point to that at the end of this routine. */
+
+ /* elz: I added this new list of symbols which is local to the function.
+ this list is the one which is actually used to build the type for the
+ function rather than the gloabal list pointed to by symlist.
+ Using a global list to keep track of the parameters is wrong, because
+ this function is called recursively if one parameter happend to be
+ a function itself with more parameters in it. Adding parameters to the
+ same global symbol list would not work!
+ Actually it did work in case of cc compiled programs where you do not check the
+ parameter lists of the arguments. */
+ add_symbol_to_list (sym, &local_list);
+ }
+
+ /* If type was read in earlier, don't bother with modifying
+ the type struct */
+ if (!record_args)
+ goto finish;
+
+ /* Note how many parameters we found. */
+ TYPE_NFIELDS (type) = nsyms;
+ TYPE_FIELDS (type) = (struct field *)
+ obstack_alloc (&objfile->type_obstack,
+ sizeof (struct field) * nsyms);
+
+ /* Find the symbols for the parameters and
+ use them to fill parameter-type information into the function-type.
+ The parameter symbols can be found in the local_list that we just put them on. */
+ /* Note that we preserve the order of the parameters, so
+ that in something like "enum {FOO, LAST_THING=FOO}" we print
+ FOO, not LAST_THING. */
+
+ /* get the parameters types from the local list not the global list
+ so that the type can be correctly constructed for functions which
+ have function as parameters
+ */
+ for (syms = local_list, n = 0; syms; syms = syms->next)
+ {
+ int j = 0;
+ for (j = 0; j < syms->nsyms; j++, n++)
+ {
+ struct symbol *xsym = syms->symbol[j];
+ TYPE_FIELD_NAME (type, n) = SYMBOL_NAME (xsym);
+ TYPE_FIELD_TYPE (type, n) = SYMBOL_TYPE (xsym);
+ TYPE_FIELD_BITPOS (type, n) = n;
+ TYPE_FIELD_BITSIZE (type, n) = 0;
+ }
+ }
+
+ /* Mark it as having been processed */
+ TYPE_FLAGS (type) &= ~(TYPE_FLAG_INCOMPLETE);
+
+ /* Check whether we need to fix-up a class type with this function's type */
+ if (fixup_class && (fixup_method == type))
+ {
+ fixup_class_method_type (fixup_class, fixup_method, objfile);
+ fixup_class = NULL;
+ fixup_method = NULL;
+ }
+
+ /* Set the param list of this level of the context stack
+ to our local list. Do this only if this function was
+ called for creating a new block, and not if it was called
+ simply to get the function type. This prevents recursive
+ invocations from trashing param_symbols. */
+finish:
+ if (newblock)
+ param_symbols = local_list;
+
+ return type;
+}
+
+
+
+/* A file-level variable which keeps track of the current-template
+ * being processed. Set in hpread_read_struct_type() while processing
+ * a template type. Referred to in hpread_get_nth_templ_arg().
+ * Yes, this is a kludge, but it arises from the kludge that already
+ * exists in symtab.h, namely the fact that they encode
+ * "template argument n" with fundamental type FT_TEMPLATE_ARG and
+ * bitlength n. This means that deep in processing fundamental types
+ * I need to ask the question "what template am I in the middle of?".
+ * The alternative to stuffing a global would be to pass an argument
+ * down the chain of calls just for this purpose.
+ *
+ * There may be problems handling nested templates... tough.
+ */
+static struct type * current_template = NULL;
+
+/* Read in and internalize a structure definition.
+ * This same routine is called for struct, union, and class types.
+ * Also called for templates, since they build a very similar
+ * type entry as for class types.
+ */
+
+static struct type *
+hpread_read_struct_type (hp_type, dn_bufp, objfile)
+ dnttpointer hp_type;
+ union dnttentry *dn_bufp;
+ struct objfile *objfile;
+{
+ /* The data members get linked together into a list of struct nextfield's */
+ struct nextfield
+ {
+ struct nextfield *next;
+ struct field field;
+ unsigned char attributes; /* store visibility and virtuality info */
+# define ATTR_VIRTUAL 1
+# define ATTR_PRIVATE 2
+# define ATTR_PROTECT 3
+ };
+
+
+ /* The methods get linked together into a list of struct next_fn_field's */
+ struct next_fn_field
+ {
+ struct next_fn_field *next;
+ struct fn_fieldlist field;
+ struct fn_field fn_field;
+ int num_fn_fields;
+ };
+
+ /* The template args get linked together into a list of struct next_template's */
+ struct next_template
+ {
+ struct next_template *next;
+ struct template_arg arg;
+ };
+
+ /* The template instantiations get linked together into a list of these... */
+ struct next_instantiation
+ {
+ struct next_instantiation * next;
+ struct type * t;
+ };
+
+ struct type *type;
+ struct type *baseclass;
+ struct type *memtype;
+ struct nextfield *list = 0, *tmp_list = 0;
+ struct next_fn_field *fn_list = 0;
+ struct next_fn_field *fn_p;
+ struct next_template *t_new, *t_list = 0;
+ struct nextfield *new;
+ struct next_fn_field *fn_new;
+ struct next_instantiation *i_new, *i_list = 0;
+ int n, nfields = 0, n_fn_fields = 0, n_fn_fields_total = 0;
+ int n_base_classes = 0, n_templ_args = 0;
+ int ninstantiations = 0;
+ dnttpointer field, fn_field, parent;
+ union dnttentry *fieldp, *fn_fieldp, *parentp;
+ int i;
+ int static_member = 0;
+ int const_member = 0;
+ int volatile_member = 0;
+ unsigned long vtbl_offset;
+ int need_bitvectors = 0;
+ char * method_name = NULL;
+ char * method_alias = NULL;
+
+
+ /* Is it something we've already dealt with? */
+ type = hpread_alloc_type (hp_type, objfile);
+ if ((TYPE_CODE (type) == TYPE_CODE_STRUCT) ||
+ (TYPE_CODE (type) == TYPE_CODE_UNION) ||
+ (TYPE_CODE (type) == TYPE_CODE_CLASS) ||
+ (TYPE_CODE (type) == TYPE_CODE_TEMPLATE))
+ return type;
+
+ /* Get the basic type correct. */
+ if (dn_bufp->dblock.kind == DNTT_TYPE_STRUCT)
+ {
+ TYPE_CODE (type) = TYPE_CODE_STRUCT;
+ TYPE_LENGTH (type) = dn_bufp->dstruct.bitlength / 8;
+ }
+ else if (dn_bufp->dblock.kind == DNTT_TYPE_UNION)
+ {
+ TYPE_CODE (type) = TYPE_CODE_UNION;
+ TYPE_LENGTH (type) = dn_bufp->dunion.bitlength / 8;
+ }
+ else if (dn_bufp->dblock.kind == DNTT_TYPE_CLASS)
+ {
+ TYPE_CODE (type) = TYPE_CODE_CLASS;
+ TYPE_LENGTH (type) = dn_bufp->dclass.bitlength / 8;
+
+ /* Overrides the TYPE_CPLUS_SPECIFIC(type) with allocated memory
+ * rather than &cplus_struct_default.
+ */
+ allocate_cplus_struct_type(type);
+
+ /* Fill in declared-type.
+ * (The C++ compiler will emit TYPE_CODE_CLASS
+ * for all 3 of "class", "struct"
+ * "union", and we have to look at the "class_decl" field if we
+ * want to know how it was really declared)
+ */
+ /* (0==class, 1==union, 2==struct) */
+ TYPE_DECLARED_TYPE(type) = dn_bufp->dclass.class_decl;
+ }
+ else if (dn_bufp->dblock.kind == DNTT_TYPE_TEMPLATE)
+ {
+ /* Get the basic type correct. */
+ TYPE_CODE (type) = TYPE_CODE_TEMPLATE;
+ allocate_cplus_struct_type(type);
+ TYPE_DECLARED_TYPE(type) = DECLARED_TYPE_TEMPLATE;
+ }
+ else
+ return type;
+
+
+ TYPE_FLAGS (type) &= ~TYPE_FLAG_STUB;
+
+ /* For classes, read the parent list.
+ * Question (RT): Do we need to do this for templates also?
+ */
+ if (dn_bufp->dblock.kind == DNTT_TYPE_CLASS) {
+
+ /* First read the parent-list (classes from which we derive fields) */
+ parent = dn_bufp->dclass.parentlist;
+ while (parent.word && parent.word != DNTTNIL) {
+ parentp = hpread_get_lntt (parent.dnttp.index, objfile);
+
+ /* "parentp" should point to a DNTT_TYPE_INHERITANCE record */
+
+ /* Get space to record the next field/data-member. */
+ new = (struct nextfield *) alloca (sizeof (struct nextfield));
+ new->next = list;
+ list = new;
+
+ FIELD_BITSIZE (list->field) = 0;
+
+ /* The "classname" field is actually a DNTT pointer to the base class */
+ baseclass = hpread_type_lookup (parentp->dinheritance.classname,
+ objfile);
+ FIELD_TYPE (list->field) = baseclass;
+
+ list->field.name = type_name_no_tag(FIELD_TYPE (list->field));
+
+ list->attributes = 0;
+
+ /* Check for virtuality of base, and set the
+ * offset of the base subobject within the object.
+ * (Offset set to -1 for virtual bases (for now).)
+ */
+ if (parentp->dinheritance.Virtual)
+ {
+ B_SET(&(list->attributes), ATTR_VIRTUAL);
+ parentp->dinheritance.offset = -1;
+ }
+ else
+ FIELD_BITPOS (list->field) = parentp->dinheritance.offset;
+
+ /* Check visibility */
+ switch (parentp->dinheritance.visibility)
+ {
+ case 1:
+ B_SET(&(list->attributes), ATTR_PROTECT);
+ break;
+ case 2:
+ B_SET(&(list->attributes), ATTR_PRIVATE);
+ break;
+ }
+
+ n_base_classes++;
+ nfields++;
+
+ parent = parentp->dinheritance.next;
+ }
+ }
+
+ /* For templates, read the template argument list.
+ * This must be done before processing the member list, because
+ * the member list may refer back to this. E.g.:
+ * template <class T1, class T2> class q2 {
+ * public:
+ * T1 a;
+ * T2 b;
+ * };
+ * We need to read the argument list "T1", "T2" first.
+ */
+ if (dn_bufp->dblock.kind == DNTT_TYPE_TEMPLATE) {
+ /* Kludge alert: This stuffs a global "current_template" which
+ * is referred to by hpread_get_nth_templ_arg(). The global
+ * is cleared at the end of this routine.
+ */
+ current_template = type;
+
+ /* Read in the argument list */
+ field = dn_bufp->dtemplate.arglist;
+ while (field.word && field.word != DNTTNIL) {
+ /* Get this template argument*/
+ fieldp = hpread_get_lntt (field.dnttp.index, objfile);
+ if (fieldp->dblock.kind != DNTT_TYPE_TEMPLATE_ARG)
+ {
+ warning ("Invalid debug info: Template argument entry is of wrong kind");
+ break;
+ }
+ /* Bump the count */
+ n_templ_args++;
+ /* Allocate and fill in a struct next_template */
+ t_new = (struct next_template *) alloca (sizeof (struct next_template));
+ t_new->next = t_list;
+ t_list = t_new;
+ t_list->arg.name = VT (objfile) + fieldp->dtempl_arg.name;
+ t_list->arg.type = hpread_read_templ_arg_type(field, fieldp,
+ objfile, t_list->arg.name);
+ /* Walk to the next template argument */
+ field = fieldp->dtempl_arg.nextarg;
+ }
+ }
+
+ TYPE_NTEMPLATE_ARGS(type) = n_templ_args;
+
+ if (n_templ_args > 0)
+ TYPE_TEMPLATE_ARGS(type) = (struct template_arg *)
+ obstack_alloc (&objfile->type_obstack, sizeof (struct template_arg) * n_templ_args);
+ for (n = n_templ_args; t_list; t_list = t_list->next)
+ {
+ n -= 1;
+ TYPE_TEMPLATE_ARG(type, n) = t_list->arg;
+ }
+
+ /* Next read in and internalize all the fields/members. */
+ if (dn_bufp->dblock.kind == DNTT_TYPE_STRUCT)
+ field = dn_bufp->dstruct.firstfield;
+ else if (dn_bufp->dblock.kind == DNTT_TYPE_UNION)
+ field = dn_bufp->dunion.firstfield;
+ else if (dn_bufp->dblock.kind == DNTT_TYPE_CLASS)
+ field = dn_bufp->dclass.memberlist;
+ else if (dn_bufp->dblock.kind == DNTT_TYPE_TEMPLATE)
+ field = dn_bufp->dtemplate.memberlist;
+ else
+ field.word = DNTTNIL;
+
+ while (field.word && field.word != DNTTNIL)
+ {
+ fieldp = hpread_get_lntt (field.dnttp.index, objfile);
+
+ /* At this point "fieldp" may point to either a DNTT_TYPE_FIELD
+ * or a DNTT_TYPE_GENFIELD record.
+ */
+ vtbl_offset = 0;
+ static_member = 0;
+ const_member = 0;
+ volatile_member = 0;
+
+ if (fieldp->dblock.kind == DNTT_TYPE_GENFIELD) {
+
+ /* The type will be GENFIELD if the field is a method or
+ * a static member (or some other cases -- see below)
+ */
+
+ /* Follow a link to get to the record for the field. */
+ fn_field = fieldp->dgenfield.field;
+ fn_fieldp = hpread_get_lntt(fn_field.dnttp.index, objfile);
+
+ /* Virtual funcs are indicated by a VFUNC which points to the
+ * real entry
+ */
+ if (fn_fieldp->dblock.kind == DNTT_TYPE_VFUNC) {
+ vtbl_offset = fn_fieldp->dvfunc.vtbl_offset;
+ fn_field = fn_fieldp->dvfunc.funcptr;
+ fn_fieldp = hpread_get_lntt(fn_field.dnttp.index, objfile);
+ }
+
+ /* A function's entry may be preceded by a modifier which
+ * labels it static/constant/volatile.
+ */
+ if (fn_fieldp->dblock.kind == DNTT_TYPE_MODIFIER) {
+ static_member = fn_fieldp->dmodifier.m_static;
+ const_member = fn_fieldp->dmodifier.m_const;
+ volatile_member = fn_fieldp->dmodifier.m_volatile;
+ fn_field = fn_fieldp->dmodifier.type;
+ fn_fieldp = hpread_get_lntt(fn_field.dnttp.index, objfile);
+ }
+
+ /* Check whether we have a method */
+ if ((fn_fieldp->dblock.kind == DNTT_TYPE_MEMFUNC) ||
+ (fn_fieldp->dblock.kind == DNTT_TYPE_FUNCTION) ||
+ (fn_fieldp->dblock.kind == DNTT_TYPE_DOC_MEMFUNC) ||
+ (fn_fieldp->dblock.kind == DNTT_TYPE_DOC_FUNCTION)) {
+ /* Method found */
+
+ short ix = 0;
+
+ /* Look up function type of method */
+ memtype = hpread_type_lookup (fn_field, objfile);
+
+ /* Methods can be seen before classes in the SOM records.
+ If we are processing this class because it's a parameter of a
+ method, at this point the method's type is actually incomplete;
+ we'll have to fix it up later; mark the class for this. */
+
+ if (TYPE_INCOMPLETE (memtype))
+ {
+ TYPE_FLAGS (type) |= TYPE_FLAG_INCOMPLETE;
+ if (fixup_class)
+ warning ("Two classes to fix up for method?? Type information may be incorrect for some classes.");
+ if (fixup_method)
+ warning ("Two methods to be fixed up at once?? Type information may be incorrect for some classes.");
+ fixup_class = type; /* remember this class has to be fixed up */
+ fixup_method = memtype; /* remember the method type to be used in fixup */
+ }
+
+ /* HP aCC generates operator names without the "operator" keyword, and
+ generates null strings as names for operators that are
+ user-defined type conversions to basic types (e.g. operator int ()).
+ So try to reconstruct name as best as possible. */
+
+ method_name = (char *) (VT (objfile) + fn_fieldp->dfunc.name);
+ method_alias = (char *) (VT (objfile) + fn_fieldp->dfunc.alias);
+
+ if (!method_name || /* no name */
+ !*method_name || /* or null name */
+ cplus_mangle_opname (method_name, DMGL_ANSI)) /* or name is an operator like "<" */
+ {
+ char * tmp_name = cplus_demangle (method_alias, DMGL_ANSI);
+ char * op_string = strstr (tmp_name, "operator");
+ method_name = xmalloc (strlen (op_string) + 1); /* don't overwrite VT! */
+ strcpy (method_name, op_string);
+ }
+
+ /* First check if a method of the same name has already been seen. */
+ fn_p = fn_list;
+ while (fn_p)
+ {
+ if (STREQ (fn_p->field.name, method_name))
+ break;
+ fn_p = fn_p->next;
+ }
+
+ /* If no such method was found, allocate a new entry in the list */
+ if (!fn_p)
+ {
+ /* Get space to record this member function */
+ /* Note: alloca used; this will disappear on routine exit */
+ fn_new = (struct next_fn_field *) alloca (sizeof (struct next_fn_field));
+ fn_new->next = fn_list;
+ fn_list = fn_new;
+
+ /* Fill in the fields of the struct nextfield */
+
+ /* Record the (unmangled) method name */
+ fn_list->field.name = method_name;
+ /* Initial space for overloaded methods */
+ /* Note: xmalloc is used; this will persist after this routine exits */
+ fn_list->field.fn_fields = (struct fn_field *) xmalloc (5 * (sizeof (struct fn_field)));
+ fn_list->field.length = 1; /* Init # of overloaded instances */
+ fn_list->num_fn_fields = 5; /* # of entries for which space allocated */
+ fn_p = fn_list;
+ ix = 0; /* array index for fn_field */
+ /* Bump the total count of the distinctly named methods */
+ n_fn_fields++;
+ }
+ else /* Another overloaded instance of an already seen method name */
+ {
+ if (++(fn_p->field.length) > fn_p->num_fn_fields)
+ {
+ /* Increase space allocated for overloaded instances */
+ fn_p->field.fn_fields
+ = (struct fn_field *) xrealloc (fn_p->field.fn_fields,
+ (fn_p->num_fn_fields + 5) * sizeof (struct fn_field));
+ fn_p->num_fn_fields += 5;
+ }
+ ix = fn_p->field.length -1; /* array index for fn_field */
+ }
+
+ /* "physname" is intended to be the name of this overloaded instance. */
+ if ((fn_fieldp->dfunc.language == HP_LANGUAGE_CPLUSPLUS) &&
+ method_alias &&
+ *method_alias) /* not a null string */
+ fn_p->field.fn_fields[ix].physname = method_alias;
+ else
+ fn_p->field.fn_fields[ix].physname = method_name;
+ /* What's expected here is the function type */
+ /* But mark it as NULL if the method was incompletely processed
+ We'll fix this up later when the method is fully processed */
+ if (TYPE_INCOMPLETE (memtype))
+ {
+ fn_p->field.fn_fields[ix].type = NULL;
+ fn_p->field.fn_fields[ix].args = NULL;
+ }
+ else
+ {
+ fn_p->field.fn_fields[ix].type = memtype;
+
+ /* The argument list */
+ fn_p->field.fn_fields[ix].type->type_specific.arg_types =
+ (struct type **) obstack_alloc(&objfile->type_obstack,
+ sizeof(struct type *) * (memtype->nfields + 1));
+ for (i = 0; i < memtype->nfields; i++)
+ fn_p->field.fn_fields[ix].type->type_specific.arg_types[i] = memtype->fields[i].type;
+ /* void termination */
+ fn_p->field.fn_fields[ix].type->type_specific.arg_types[memtype->nfields] = builtin_type_void;
+
+ /* pai: It's not clear why this args field has to be set. Perhaps
+ * it should be eliminated entirely. */
+ fn_p->field.fn_fields[ix].args =
+ (struct type **) obstack_alloc(&objfile->type_obstack,
+ sizeof(struct type *) * (memtype->nfields + 1));
+ for (i = 0; i < memtype->nfields; i++)
+ fn_p->field.fn_fields[ix].args[i] = memtype->fields[i].type;
+ /* null-terminated, unlike arg_types above e*/
+ fn_p->field.fn_fields[ix].args[memtype->nfields] = NULL;
+ }
+ /* For virtual functions, fill in the voffset field with the
+ * virtual table offset. (This is just copied over from the
+ * SOM record; not sure if it is what GDB expects here...).
+ * But if the function is a static method, set it to 1.
+ *
+ * Note that we have to add 1 because 1 indicates a static
+ * method, and 0 indicates a non-static, non-virtual method */
+
+ if (static_member)
+ fn_p->field.fn_fields[ix].voffset = VOFFSET_STATIC;
+ else
+ fn_p->field.fn_fields[ix].voffset = vtbl_offset ? vtbl_offset + 1 : 0;
+
+ /* Also fill in the fcontext field with the current
+ * class. (The latter isn't quite right: should be the baseclass
+ * that defines the virtual function... Note we do have
+ * a variable "baseclass" that we could stuff into the fcontext
+ * field, but "baseclass" isn't necessarily right either,
+ * since the virtual function could have been defined more
+ * than one level up).
+ */
+
+ if (vtbl_offset != 0)
+ fn_p->field.fn_fields[ix].fcontext = type;
+ else
+ fn_p->field.fn_fields[ix].fcontext = NULL;
+
+ /* Other random fields pertaining to this method */
+ fn_p->field.fn_fields[ix].is_const = const_member;
+ fn_p->field.fn_fields[ix].is_volatile = volatile_member; /* ?? */
+ switch (fieldp->dgenfield.visibility) {
+ case 1:
+ fn_p->field.fn_fields[ix].is_protected = 1;
+ fn_p->field.fn_fields[ix].is_private = 0;
+ break;
+ case 2:
+ fn_p->field.fn_fields[ix].is_protected = 0;
+ fn_p->field.fn_fields[ix].is_private = 1;
+ break;
+ default: /* public */
+ fn_p->field.fn_fields[ix].is_protected = 0;
+ fn_p->field.fn_fields[ix].is_private = 0;
+ }
+ fn_p->field.fn_fields[ix].is_stub = 0;
+
+ /* HP aCC emits both MEMFUNC and FUNCTION entries for a method;
+ if the class points to the FUNCTION, there is usually separate
+ code for the method; but if we have a MEMFUNC, the method has
+ been inlined (and there is usually no FUNCTION entry)
+ FIXME Not sure if this test is accurate. pai/1997-08-22 */
+ if ((fn_fieldp->dblock.kind == DNTT_TYPE_MEMFUNC) ||
+ (fn_fieldp->dblock.kind == DNTT_TYPE_DOC_MEMFUNC))
+ fn_p->field.fn_fields[ix].is_inlined = 1;
+ else
+ fn_p->field.fn_fields[ix].is_inlined = 0;
+
+ fn_p->field.fn_fields[ix].dummy = 0;
+
+ /* Bump the total count of the member functions */
+ n_fn_fields_total++;
+
+ } else if (fn_fieldp->dblock.kind == DNTT_TYPE_SVAR) {
+ /* This case is for static data members of classes */
+
+ /* pai:: FIXME -- check that "staticmem" bit is set */
+
+ /* Get space to record this static member */
+ new = (struct nextfield *) alloca (sizeof (struct nextfield));
+ new->next = list;
+ list = new;
+
+ list->field.name = VT (objfile) + fn_fieldp->dsvar.name;
+ FIELD_BITSIZE (list->field) = -1; /* indicates static member */
+ SET_FIELD_PHYSNAME (list->field, 0); /* initialize to empty */
+ memtype = hpread_type_lookup (fn_fieldp->dsvar.type, objfile);
+
+ FIELD_TYPE (list->field) = memtype;
+ list->attributes = 0;
+ switch (fieldp->dgenfield.visibility) {
+ case 1:
+ B_SET(&(list->attributes), ATTR_PROTECT);
+ break;
+ case 2:
+ B_SET(&(list->attributes), ATTR_PRIVATE);
+ break;
+ }
+ nfields++;
+ }
+
+ else if (fn_fieldp->dblock.kind == DNTT_TYPE_FIELD)
+ {
+ /* FIELDs follow GENFIELDs for fields of anonymous unions.
+ Code below is replicated from the case for FIELDs further
+ below, except that fieldp is replaced by fn_fieldp */
+ if (!fn_fieldp->dfield.a_union)
+ warning ("Debug info inconsistent: FIELD of anonymous union doesn't have a_union bit set");
+ /* Get space to record the next field/data-member. */
+ new = (struct nextfield *) alloca (sizeof (struct nextfield));
+ new->next = list;
+ list = new;
+
+ list->field.name = VT (objfile) + fn_fieldp->dfield.name;
+ FIELD_BITPOS (list->field) = fn_fieldp->dfield.bitoffset;
+ if (fn_fieldp->dfield.bitlength % 8)
+ list->field.bitsize = fn_fieldp->dfield.bitlength;
+ else
+ list->field.bitsize = 0;
+
+ memtype = hpread_type_lookup (fn_fieldp->dfield.type, objfile);
+ list->field.type = memtype;
+ list->attributes = 0;
+ switch (fn_fieldp->dfield.visibility) {
+ case 1:
+ B_SET(&(list->attributes), ATTR_PROTECT);
+ break;
+ case 2:
+ B_SET(&(list->attributes), ATTR_PRIVATE);
+ break;
+ }
+ nfields++;
+ }
+ else if (fn_fieldp->dblock.kind == DNTT_TYPE_SVAR)
+ {
+ /* Field of anonymous union; union is not inside a class */
+ if (!fn_fieldp->dsvar.a_union)
+ warning ("Debug info inconsistent: SVAR field in anonymous union doesn't have a_union bit set");
+ /* Get space to record the next field/data-member. */
+ new = (struct nextfield *) alloca (sizeof (struct nextfield));
+ new->next = list;
+ list = new;
+
+ list->field.name = VT (objfile) + fn_fieldp->dsvar.name;
+ FIELD_BITPOS (list->field) = 0; /* FIXME is this always true? */
+ FIELD_BITSIZE (list->field) = 0; /* use length from type */
+ memtype = hpread_type_lookup (fn_fieldp->dsvar.type, objfile);
+ list->field.type = memtype;
+ list->attributes = 0;
+ /* No info to set visibility -- always public */
+ nfields++;
+ }
+ else if (fn_fieldp->dblock.kind == DNTT_TYPE_DVAR)
+ {
+ /* Field of anonymous union; union is not inside a class */
+ if (!fn_fieldp->ddvar.a_union)
+ warning ("Debug info inconsistent: DVAR field in anonymous union doesn't have a_union bit set");
+ /* Get space to record the next field/data-member. */
+ new = (struct nextfield *) alloca (sizeof (struct nextfield));
+ new->next = list;
+ list = new;
+
+ list->field.name = VT (objfile) + fn_fieldp->ddvar.name;
+ FIELD_BITPOS (list->field) = 0; /* FIXME is this always true? */
+ FIELD_BITSIZE (list->field) = 0; /* use length from type */
+ memtype = hpread_type_lookup (fn_fieldp->ddvar.type, objfile);
+ list->field.type = memtype;
+ list->attributes = 0;
+ /* No info to set visibility -- always public */
+ nfields++;
+ }
+ else { /* Not a method, nor a static data member, nor an anon union field */
+
+ /* This case is for miscellaneous type entries (local enums,
+ local function templates, etc.) that can be present
+ inside a class. */
+
+ /* Enums -- will be handled by other code that takes care
+ of DNTT_TYPE_ENUM; here we see only DNTT_TYPE_MEMENUM so
+ it's not clear we could have handled them here at all. */
+ /* FUNC_TEMPLATE: is handled by other code (??). */
+ /* MEMACCESS: modified access for inherited member. Not
+ sure what to do with this, ignoriing it at present. */
+
+ /* What other entries can appear following a GENFIELD which
+ we do not handle above? (MODIFIER, VFUNC handled above.) */
+
+ if ((fn_fieldp->dblock.kind != DNTT_TYPE_MEMACCESS) &&
+ (fn_fieldp->dblock.kind != DNTT_TYPE_MEMENUM) &&
+ (fn_fieldp->dblock.kind != DNTT_TYPE_FUNC_TEMPLATE))
+ warning ("Internal error: Unexpected debug record kind %d found following DNTT_GENFIELD",
+ fn_fieldp->dblock.kind);
+ }
+ /* walk to the next FIELD or GENFIELD */
+ field = fieldp->dgenfield.nextfield;
+
+ }
+ else if (fieldp->dblock.kind == DNTT_TYPE_FIELD) {
+
+ /* Ordinary structure/union/class field */
+ struct type * anon_union_type;
+
+ /* Get space to record the next field/data-member. */
+ new = (struct nextfield *) alloca (sizeof (struct nextfield));
+ new->next = list;
+ list = new;
+
+ list->field.name = VT (objfile) + fieldp->dfield.name;
+
+
+ /* A FIELD by itself (without a GENFIELD) can also be a static member */
+ if (fieldp->dfield.staticmem)
+ {
+ FIELD_BITPOS (list->field) = -1;
+ FIELD_BITSIZE (list->field) = 0;
+ }
+ else /* Non-static data member */
+ {
+ FIELD_BITPOS (list->field) = fieldp->dfield.bitoffset;
+ if (fieldp->dfield.bitlength % 8)
+ FIELD_BITSIZE (list->field) = fieldp->dfield.bitlength;
+ else
+ FIELD_BITSIZE (list->field) = 0;
+ }
+
+ memtype = hpread_type_lookup (fieldp->dfield.type, objfile);
+ FIELD_TYPE (list->field) = memtype;
+ list->attributes = 0;
+ switch (fieldp->dfield.visibility) {
+ case 1:
+ B_SET(&(list->attributes), ATTR_PROTECT);
+ break;
+ case 2:
+ B_SET(&(list->attributes), ATTR_PRIVATE);
+ break;
+ }
+ nfields++;
+
+
+ /* Note 1: First, we have to check if the current field is an anonymous
+ union. If it is, then *its* fields are threaded along in the
+ nextfield chain. :-( This was supposed to help debuggers, but is
+ really just a nuisance since we deal with anonymous unions anyway by
+ checking that the name is null. So anyway, we skip over the fields
+ of the anonymous union. pai/1997-08-22 */
+ /* Note 2: In addition, the bitoffsets for the fields of the anon union
+ are relative to the enclosing struct, *NOT* relative to the anon
+ union! This is an even bigger nuisance -- we have to go in and munge
+ the anon union's type information appropriately. pai/1997-08-22 */
+
+ /* Both tasks noted above are done by a separate function. This takes us
+ to the next FIELD or GENFIELD, skipping anon unions, and recursively
+ processing intermediate types. */
+ field = hpread_get_next_skip_over_anon_unions (1, field, &fieldp, objfile);
+
+ } else {
+ /* neither field nor genfield ?? is this possible?? */
+ /* pai:: FIXME walk to the next -- how? */
+ warning ("Internal error: unexpected DNTT kind %d encountered as field of struct");
+ warning ("Skipping remaining fields of struct");
+ break; /* get out of loop of fields */
+ }
+ }
+
+ /* If it's a template, read in the instantiation list */
+ if (dn_bufp->dblock.kind == DNTT_TYPE_TEMPLATE) {
+ ninstantiations = 0;
+ field = dn_bufp->dtemplate.expansions;
+ while (field.word && field.word != DNTTNIL) {
+ fieldp = hpread_get_lntt (field.dnttp.index, objfile);
+
+ /* The expansions or nextexp should point to a tagdef */
+ if (fieldp->dblock.kind != DNTT_TYPE_TAGDEF)
+ break;
+
+ i_new = (struct next_instantiation *) alloca (sizeof (struct next_instantiation));
+ i_new->next = i_list;
+ i_list = i_new;
+ i_list->t = hpread_type_lookup (field, objfile);
+ ninstantiations++;
+
+ /* And the "type" field of that should point to a class */
+ field = fieldp->dtag.type;
+ fieldp = hpread_get_lntt (field.dnttp.index, objfile);
+ if (fieldp->dblock.kind != DNTT_TYPE_CLASS)
+ break;
+
+ /* Get the next expansion */
+ field = fieldp->dclass.nextexp;
+ }
+ }
+ TYPE_NINSTANTIATIONS(type) = ninstantiations;
+ if (ninstantiations > 0)
+ TYPE_INSTANTIATIONS(type) = (struct type **)
+ obstack_alloc (&objfile->type_obstack, sizeof (struct type *) * ninstantiations);
+ for (n = ninstantiations; i_list; i_list = i_list->next)
+ {
+ n -= 1;
+ TYPE_INSTANTIATION(type, n) = i_list->t;
+ }
+
+
+ /* Copy the field-list to GDB's symbol table */
+ TYPE_NFIELDS (type) = nfields;
+ TYPE_N_BASECLASSES (type) = n_base_classes;
+ TYPE_FIELDS (type) = (struct field *)
+ obstack_alloc (&objfile->type_obstack, sizeof (struct field) * nfields);
+ /* Copy the saved-up fields into the field vector. */
+ for (n = nfields, tmp_list = list; tmp_list; tmp_list = tmp_list->next)
+ {
+ n -= 1;
+ TYPE_FIELD (type, n) = tmp_list->field;
+ }
+
+ /* Copy the "function-field-list" (i.e., the list of member
+ * functions in the class) to GDB's symbol table
+ */
+ TYPE_NFN_FIELDS (type) = n_fn_fields;
+ TYPE_NFN_FIELDS_TOTAL (type) = n_fn_fields_total;
+ TYPE_FN_FIELDLISTS(type) = (struct fn_fieldlist *)
+ obstack_alloc (&objfile->type_obstack, sizeof (struct fn_fieldlist) * n_fn_fields);
+ for (n = n_fn_fields; fn_list; fn_list = fn_list->next)
+ {
+ n -= 1;
+ TYPE_FN_FIELDLIST(type, n) = fn_list->field;
+ }
+
+ /* pai:: FIXME -- perhaps each bitvector should be created individually */
+ for (n = nfields, tmp_list = list; tmp_list; tmp_list = tmp_list->next)
+ {
+ n -= 1;
+ if (tmp_list->attributes)
+ {
+ need_bitvectors = 1;
+ break;
+ }
+ }
+
+ if (need_bitvectors)
+ {
+ /* pai:: this step probably redundant */
+ ALLOCATE_CPLUS_STRUCT_TYPE (type);
+
+ TYPE_FIELD_VIRTUAL_BITS (type) =
+ (B_TYPE *) TYPE_ALLOC (type, B_BYTES (nfields));
+ B_CLRALL (TYPE_FIELD_VIRTUAL_BITS (type), nfields);
+
+ 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);
+
+ /* this field vector isn't actually used with HP aCC */
+ TYPE_FIELD_IGNORE_BITS (type) =
+ (B_TYPE *) TYPE_ALLOC (type, B_BYTES (nfields));
+ B_CLRALL (TYPE_FIELD_IGNORE_BITS (type), nfields);
+
+ while (nfields-- > 0)
+ {
+ if (B_TST(&(list->attributes),ATTR_VIRTUAL))
+ SET_TYPE_FIELD_VIRTUAL (type, nfields);
+ if (B_TST(&(list->attributes),ATTR_PRIVATE))
+ SET_TYPE_FIELD_PRIVATE (type, nfields);
+ if (B_TST(&(list->attributes),ATTR_PROTECT))
+ SET_TYPE_FIELD_PROTECTED (type, nfields);
+
+ list = list->next;
+ }
+ }
+ else
+ {
+ TYPE_FIELD_VIRTUAL_BITS(type) = NULL;
+ TYPE_FIELD_PROTECTED_BITS(type) = NULL;
+ TYPE_FIELD_PRIVATE_BITS(type) = NULL;
+ }
+
+ if (has_vtable(type))
+ {
+ /* Allocate space for class runtime information */
+ TYPE_RUNTIME_PTR(type) = (struct runtime_info *) xmalloc (sizeof(struct runtime_info));
+ /* Set flag for vtable */
+ TYPE_VTABLE(type) = 1;
+ /* The first non-virtual base class with a vtable. */
+ TYPE_PRIMARY_BASE(type) = primary_base_class(type);
+ /* The virtual base list. */
+ TYPE_VIRTUAL_BASE_LIST(type) = virtual_base_list(type);
+ }
+ else
+ TYPE_RUNTIME_PTR(type) = NULL;
+
+ /* If this is a local type (C++ - declared inside a function), record file name & line # */
+ if (hpread_get_scope_depth (dn_bufp, objfile, 1 /* no need for real depth */))
+ {
+ TYPE_LOCALTYPE_PTR (type) = (struct local_type_info *) xmalloc (sizeof (struct local_type_info));
+ TYPE_LOCALTYPE_FILE (type) = (char *) xmalloc (strlen (current_subfile->name) + 1);
+ strcpy (TYPE_LOCALTYPE_FILE (type), current_subfile->name);
+ if (current_subfile->line_vector && (current_subfile->line_vector->nitems > 0))
+ TYPE_LOCALTYPE_LINE (type) = current_subfile->line_vector->item[current_subfile->line_vector->nitems - 1].line;
+ else
+ TYPE_LOCALTYPE_LINE (type) = 0;
+ }
+ else
+ TYPE_LOCALTYPE_PTR (type) = NULL;
+
+ /* Clear the global saying what template we are in the middle of processing */
+ current_template = NULL;
+
+ return type;
+}
+
+/* Adjust the physnames for each static member of a struct
+ or class type to be something like "A::x"; then various
+ other pieces of code that do a lookup_symbol on the phyname
+ work correctly.
+ TYPE is a pointer to the struct/class type
+ NAME is a char * (string) which is the class/struct name
+ Void return */
+
+static void
+fix_static_member_physnames (type, class_name, objfile)
+ struct type * type;
+ char * class_name;
+ struct objfile * objfile;
+{
+ int i;
+
+ /* We fix the member names only for classes or structs */
+ if (TYPE_CODE (type) != TYPE_CODE_STRUCT)
+ return;
+
+ for (i=0; i < TYPE_NFIELDS (type); i++)
+ if (TYPE_FIELD_STATIC (type, i))
+ {
+ if (TYPE_FIELD_STATIC_PHYSNAME (type, i))
+ return; /* physnames are already set */
+
+ SET_FIELD_PHYSNAME (type->fields[i],
+ obstack_alloc (&objfile->type_obstack,
+ strlen (class_name) + strlen (TYPE_FIELD_NAME (type, i)) + 3));
+ strcpy (TYPE_FIELD_STATIC_PHYSNAME (type, i), class_name);
+ strcat (TYPE_FIELD_STATIC_PHYSNAME (type, i), "::");
+ strcat (TYPE_FIELD_STATIC_PHYSNAME (type, i), TYPE_FIELD_NAME (type, i));
+ }
+}
+
+/* Fix-up the type structure for a CLASS so that the type entry
+ * for a method (previously marked with a null type in hpread_read_struct_type()
+ * is set correctly to METHOD.
+ * OBJFILE is as for other such functions.
+ * Void return. */
+
+static void
+fixup_class_method_type (class, method, objfile)
+ struct type * class;
+ struct type * method;
+ struct objfile * objfile;
+{
+ int i, j, k;
+
+ if (!class || !method || !objfile)
+ return;
+
+ /* Only for types that have methods */
+ if ((TYPE_CODE (class) != TYPE_CODE_CLASS) &&
+ (TYPE_CODE (class) != TYPE_CODE_UNION))
+ return;
+
+ /* Loop over all methods and find the one marked with a NULL type */
+ for (i = 0; i < TYPE_NFN_FIELDS (class); i++)
+ for (j = 0; j < TYPE_FN_FIELDLIST_LENGTH (class, i); j++)
+ if (TYPE_FN_FIELD_TYPE (TYPE_FN_FIELDLIST1 (class, i), j) == NULL)
+ {
+ /* Set the method type */
+ TYPE_FN_FIELD_TYPE (TYPE_FN_FIELDLIST1 (class, i), j) = method;
+ /* The argument list */
+ (TYPE_FN_FIELD_TYPE (TYPE_FN_FIELDLIST1 (class, i), j))->type_specific.arg_types
+ = (struct type **) obstack_alloc(&objfile->type_obstack,
+ sizeof(struct type *) * (method->nfields + 1));
+ for (k = 0; k < method->nfields; k++)
+ (TYPE_FN_FIELD_TYPE (TYPE_FN_FIELDLIST1 (class, i), j))->type_specific.arg_types[k] = method->fields[k].type;
+ /* void termination */
+ (TYPE_FN_FIELD_TYPE (TYPE_FN_FIELDLIST1 (class, i), j))->type_specific.arg_types[method->nfields] = builtin_type_void;
+
+ /* pai: It's not clear why this args field has to be set. Perhaps
+ * it should be eliminated entirely. */
+ (TYPE_FN_FIELD (TYPE_FN_FIELDLIST1 (class, i), j)).args
+ = (struct type **) obstack_alloc(&objfile->type_obstack,
+ sizeof(struct type *) * (method->nfields + 1));
+ for (k = 0; k < method->nfields; k++)
+ (TYPE_FN_FIELD (TYPE_FN_FIELDLIST1 (class, i), j)).args[k] = method->fields[k].type;
+ /* null-terminated, unlike arg_types above */
+ (TYPE_FN_FIELD (TYPE_FN_FIELDLIST1 (class, i), j)).args[method->nfields] = NULL;
+
+ /* Break out of both loops -- only one method to fix up in a class */
+ goto finish;
+ }
+
+finish:
+ TYPE_FLAGS (class) &= ~TYPE_FLAG_INCOMPLETE;
+}
+
+
+/* If we're in the middle of processing a template, get a pointer
+ * to the Nth template argument.
+ * An example may make this clearer:
+ * template <class T1, class T2> class q2 {
+ * public:
+ * T1 a;
+ * T2 b;
+ * };
+ * The type for "a" will be "first template arg" and
+ * the type for "b" will be "second template arg".
+ * We need to look these up in order to fill in "a" and "b"'s type.
+ * This is called from hpread_type_lookup().
+ */
+static struct type *
+hpread_get_nth_template_arg(objfile, n)
+ struct objfile *objfile;
+ int n;
+{
+ if (current_template != NULL)
+ return TYPE_TEMPLATE_ARG(current_template, n).type;
+ else
+ return lookup_fundamental_type (objfile, FT_TEMPLATE_ARG);
+}
+
+/* Read in and internalize a TEMPL_ARG (template arg) symbol. */
+
+static struct type *
+hpread_read_templ_arg_type (hp_type, dn_bufp, objfile, name)
+ dnttpointer hp_type;
+ union dnttentry *dn_bufp;
+ struct objfile *objfile;
+ char * name;
+{
+ struct type *type;
+
+ /* See if it's something we've already deal with. */
+ type = hpread_alloc_type (hp_type, objfile);
+ if (TYPE_CODE (type) == TYPE_CODE_TEMPLATE_ARG)
+ return type;
+
+ /* Nope. Fill in the appropriate fields. */
+ TYPE_CODE (type) = TYPE_CODE_TEMPLATE_ARG;
+ TYPE_LENGTH (type) = 0;
+ TYPE_NFIELDS (type) = 0;
+ TYPE_NAME (type) = name;
+ return type;
+}
+
+/* Read in and internalize a set debug symbol. */
+
+static struct type *
+hpread_read_set_type (hp_type, dn_bufp, objfile)
+ dnttpointer hp_type;
+ union dnttentry *dn_bufp;
+ struct objfile *objfile;
+{
+ struct type *type;
+
+ /* See if it's something we've already deal with. */
+ type = hpread_alloc_type (hp_type, objfile);
+ if (TYPE_CODE (type) == TYPE_CODE_SET)
+ return type;
+
+ /* Nope. Fill in the appropriate fields. */
+ TYPE_CODE (type) = TYPE_CODE_SET;
+ TYPE_LENGTH (type) = dn_bufp->dset.bitlength / 8;
+ TYPE_NFIELDS (type) = 0;
+ TYPE_TARGET_TYPE (type) = hpread_type_lookup (dn_bufp->dset.subtype,
+ objfile);
+ return type;
+}
+
+/* Read in and internalize an array debug symbol. */
+
+static struct type *
+hpread_read_array_type (hp_type, dn_bufp, objfile)
+ dnttpointer hp_type;
+ union dnttentry *dn_bufp;
+ struct objfile *objfile;
+{
+ struct type *type;
+
+ /* Allocate an array type symbol.
+ * Why no check for already-read here, like in the other
+ * hpread_read_xxx_type routines? Because it kept us
+ * from properly determining the size of the array!
+ */
+ type = hpread_alloc_type (hp_type, objfile);
+
+ TYPE_CODE (type) = TYPE_CODE_ARRAY;
+
+ /* Although the hp-symtab.h does not *require* this to be the case,
+ * GDB is assuming that "arrayisbytes" and "elemisbytes" be consistent.
+ * I.e., express both array-length and element-length in bits,
+ * or express both array-length and element-length in bytes.
+ */
+ if (!((dn_bufp->darray.arrayisbytes && dn_bufp->darray.elemisbytes) ||
+ (!dn_bufp->darray.arrayisbytes && !dn_bufp->darray.elemisbytes))) {
+ warning ("error in hpread_array_type.\n");
+ return;
+ } else if (dn_bufp->darray.arraylength == 0x7fffffff) {
+ /* The HP debug format represents char foo[]; as an array with
+ * length 0x7fffffff. Internally GDB wants to represent this
+ * as an array of length zero.
+ */
+ TYPE_LENGTH (type) = 0;
+ } else if (dn_bufp->darray.arrayisbytes)
+ TYPE_LENGTH (type) = dn_bufp->darray.arraylength;
+ else /* arraylength is in bits */
+ TYPE_LENGTH (type) = dn_bufp->darray.arraylength / 8;
+
+ TYPE_TARGET_TYPE (type) = hpread_type_lookup (dn_bufp->darray.elemtype,
+ objfile);
+
+ /* The one "field" is used to store the subscript type */
+ /* Since C and C++ multi-dimensional arrays are simply represented
+ * as: array of array of ..., we only need one subscript-type
+ * per array. This subscript type is typically a subrange of integer.
+ * If this gets extended to support languages like Pascal, then
+ * we need to fix this to represent multi-dimensional arrays properly.
+ */
+ TYPE_NFIELDS (type) = 1;
+ TYPE_FIELDS (type) = (struct field *)
+ obstack_alloc (&objfile->type_obstack, sizeof (struct field));
+ TYPE_FIELD_TYPE (type, 0) = hpread_type_lookup (dn_bufp->darray.indextype,
+ objfile);
+ return type;
+}
+
+/* Read in and internalize a subrange debug symbol. */
+static struct type *
+hpread_read_subrange_type (hp_type, dn_bufp, objfile)
+ dnttpointer hp_type;
+ union dnttentry *dn_bufp;
+ struct objfile *objfile;
+{
+ struct type *type;
+
+ /* Is it something we've already dealt with. */
+ type = hpread_alloc_type (hp_type, objfile);
+ if (TYPE_CODE (type) == TYPE_CODE_RANGE)
+ return type;
+
+ /* Nope, internalize it. */
+ TYPE_CODE (type) = TYPE_CODE_RANGE;
+ TYPE_LENGTH (type) = dn_bufp->dsubr.bitlength / 8;
+ TYPE_NFIELDS (type) = 2;
+ TYPE_FIELDS (type)
+ = (struct field *) obstack_alloc (&objfile->type_obstack,
+ 2 * sizeof (struct field));
+
+ if (dn_bufp->dsubr.dyn_low)
+ TYPE_FIELD_BITPOS (type, 0) = 0;
+ else
+ TYPE_FIELD_BITPOS (type, 0) = dn_bufp->dsubr.lowbound;
+
+ if (dn_bufp->dsubr.dyn_high)
+ TYPE_FIELD_BITPOS (type, 1) = -1;
+ else
+ TYPE_FIELD_BITPOS (type, 1) = dn_bufp->dsubr.highbound;
+ TYPE_TARGET_TYPE (type) = hpread_type_lookup (dn_bufp->dsubr.subtype,
+ objfile);
+ return type;
+}
+
+/* struct type * hpread_type_lookup(hp_type, objfile)
+ * Arguments:
+ * hp_type: A pointer into the DNTT specifying what type we
+ * are about to "look up"., or else [for fundamental types
+ * like int, float, ...] an "immediate" structure describing
+ * the type.
+ * objfile: ?
+ * Return value: A pointer to a "struct type" (representation of a
+ * type in GDB's internal symbol table - see gdbtypes.h)
+ * Routine description:
+ * There are a variety of places when scanning the DNTT when we
+ * need to interpret a "type" field. The simplest and most basic
+ * example is when we're processing the symbol table record
+ * for a data symbol (a SVAR or DVAR record). That has
+ * a "type" field specifying the type of the data symbol. That
+ * "type" field is either an "immediate" type specification (for the
+ * fundamental types) or a DNTT pointer (for more complicated types).
+ * For the more complicated types, we may or may not have already
+ * processed the pointed-to type. (Multiple data symbols can of course
+ * share the same type).
+ * The job of hpread_type_lookup() is to process this "type" field.
+ * Most of the real work is done in subroutines. Here we interpret
+ * the immediate flag. If not immediate, chase the DNTT pointer to
+ * find our way to the SOM record describing the type, switch on
+ * the SOM kind, and then call an appropriate subroutine depending
+ * on what kind of type we are constructing. (e.g., an array type,
+ * a struct/class type, etc).
+ */
+static struct type *
+hpread_type_lookup (hp_type, objfile)
+ dnttpointer hp_type;
+ struct objfile *objfile;
+{
+ union dnttentry *dn_bufp;
+ struct type * tmp_type;
+
+ /* First see if it's a simple builtin type. */
+ if (hp_type.dntti.immediate)
+ /* If this is a template argument, the argument number is
+ * encoded in the bitlength. All other cases, just return
+ * GDB's representation of this fundamental type.
+ */
+ if (hp_type.dntti.type == HP_TYPE_TEMPLATE_ARG)
+ return hpread_get_nth_template_arg(objfile, hp_type.dntti.bitlength);
+ else
+ return lookup_fundamental_type (objfile, hpread_type_translate (hp_type));
+
+ /* Not a builtin type. We'll have to read it in. */
+ if (hp_type.dnttp.index < LNTT_SYMCOUNT (objfile))
+ dn_bufp = hpread_get_lntt (hp_type.dnttp.index, objfile);
+ else
+ /* This is a fancy way of returning NULL */
+ return lookup_fundamental_type (objfile, FT_VOID);
+
+ switch (dn_bufp->dblock.kind)
+ {
+ case DNTT_TYPE_SRCFILE:
+ case DNTT_TYPE_MODULE:
+ case DNTT_TYPE_ENTRY:
+ case DNTT_TYPE_BEGIN:
+ case DNTT_TYPE_END:
+ case DNTT_TYPE_IMPORT:
+ case DNTT_TYPE_LABEL:
+ case DNTT_TYPE_FPARAM:
+ case DNTT_TYPE_SVAR:
+ case DNTT_TYPE_DVAR:
+ case DNTT_TYPE_CONST:
+ case DNTT_TYPE_MEMENUM:
+ case DNTT_TYPE_VARIANT:
+ case DNTT_TYPE_FILE:
+ case DNTT_TYPE_WITH:
+ case DNTT_TYPE_COMMON:
+ case DNTT_TYPE_COBSTRUCT:
+ case DNTT_TYPE_XREF:
+ case DNTT_TYPE_SA:
+ case DNTT_TYPE_MACRO:
+ case DNTT_TYPE_BLOCKDATA:
+ case DNTT_TYPE_CLASS_SCOPE:
+ case DNTT_TYPE_MEMACCESS:
+ case DNTT_TYPE_INHERITANCE:
+ case DNTT_TYPE_OBJECT_ID:
+ case DNTT_TYPE_FRIEND_CLASS:
+ case DNTT_TYPE_FRIEND_FUNC:
+ /* These are not types - something went wrong. */
+ /* This is a fancy way of returning NULL */
+ return lookup_fundamental_type (objfile, FT_VOID);
+
+ case DNTT_TYPE_FUNCTION:
+ /* We wind up here when dealing with class member functions
+ * (called from hpread_read_struct_type(), i.e. when processing
+ * the class definition itself).
+ */
+ return hpread_read_function_type (hp_type, dn_bufp, objfile, 0);
+
+ case DNTT_TYPE_DOC_FUNCTION:
+ return hpread_read_doc_function_type (hp_type, dn_bufp, objfile, 0);
+
+ case DNTT_TYPE_TYPEDEF:
+ {
+ /* A typedef - chase it down by making a recursive call */
+ struct type *structtype = hpread_type_lookup (dn_bufp->dtype.type,
+ objfile);
+
+ /* The following came from the base hpread.c that we inherited.
+ * It is WRONG so I have commented it out. - RT
+ *...
+
+ char *suffix;
+ suffix = VT (objfile) + dn_bufp->dtype.name;
+ TYPE_NAME (structtype) = suffix;
+
+ * ... further explanation ....
+ *
+ * What we have here is a typedef pointing to a typedef.
+ * E.g.,
+ * typedef int foo;
+ * typedef foo fum;
+ *
+ * What we desire to build is (these are pictures
+ * of "struct type"'s):
+ *
+ * +---------+ +----------+ +------------+
+ * | typedef | | typedef | | fund. type |
+ * | type| -> | type| -> | |
+ * | "fum" | | "foo" | | "int" |
+ * +---------+ +----------+ +------------+
+ *
+ * What this commented-out code is doing is smashing the
+ * name of pointed-to-type to be the same as the pointed-from
+ * type. So we wind up with something like:
+ *
+ * +---------+ +----------+ +------------+
+ * | typedef | | typedef | | fund. type |
+ * | type| -> | type| -> | |
+ * | "fum" | | "fum" | | "fum" |
+ * +---------+ +----------+ +------------+
+ *
+ */
+
+ return structtype;
+ }
+
+ case DNTT_TYPE_TAGDEF:
+ {
+ /* Just a little different from above. We have to tack on
+ * an identifier of some kind (struct, union, enum, class, etc).
+ */
+ struct type *structtype = hpread_type_lookup (dn_bufp->dtype.type,
+ objfile);
+ char *prefix, *suffix;
+ suffix = VT (objfile) + dn_bufp->dtype.name;
+
+ /* Lookup the next type in the list. It should be a structure,
+ * union, class, enum, or template type.
+ * We will need to attach that to our name.
+ */
+ if (dn_bufp->dtype.type.dnttp.index < LNTT_SYMCOUNT (objfile))
+ dn_bufp = hpread_get_lntt (dn_bufp->dtype.type.dnttp.index, objfile);
+ else {
+ complain (&hpread_type_lookup_complaint);
+ return;
+ }
+
+ if (dn_bufp->dblock.kind == DNTT_TYPE_STRUCT) {
+ prefix = "struct ";
+ } else if (dn_bufp->dblock.kind == DNTT_TYPE_UNION) {
+ prefix = "union ";
+ } else if (dn_bufp->dblock.kind == DNTT_TYPE_CLASS) {
+ /* Further field for CLASS saying how it was really declared */
+ /* 0==class, 1==union, 2==struct */
+ if (dn_bufp->dclass.class_decl == 0)
+ prefix = "class ";
+ else if (dn_bufp->dclass.class_decl == 1)
+ prefix = "union ";
+ else if (dn_bufp->dclass.class_decl == 2)
+ prefix = "struct ";
+ else
+ prefix = "";
+ } else if (dn_bufp->dblock.kind == DNTT_TYPE_ENUM) {
+ prefix = "enum ";
+ } else if (dn_bufp->dblock.kind == DNTT_TYPE_TEMPLATE) {
+ prefix = "template ";
+ } else {
+ prefix = "";
+ }
+
+ /* Build the correct name. */
+ structtype->name
+ = (char *) obstack_alloc (&objfile->type_obstack,
+ strlen (prefix) + strlen (suffix) + 1);
+ TYPE_NAME (structtype) = strcpy (TYPE_NAME (structtype), prefix);
+ TYPE_NAME (structtype) = strcat (TYPE_NAME (structtype), suffix);
+ TYPE_TAG_NAME (structtype) = suffix;
+
+ /* For classes/structs, we have to set the static member "physnames"
+ to point to strings like "Class::Member" */
+ if (TYPE_CODE (structtype) == TYPE_CODE_STRUCT)
+ fix_static_member_physnames (structtype, suffix, objfile);
+
+ return structtype;
+ }
+
+ case DNTT_TYPE_POINTER:
+ /* Pointer type - call a routine in gdbtypes.c that constructs
+ * the appropriate GDB type.
+ */
+ return make_pointer_type (
+ hpread_type_lookup (dn_bufp->dptr.pointsto,
+ objfile),
+ NULL);
+
+ case DNTT_TYPE_REFERENCE:
+ /* C++ reference type - call a routine in gdbtypes.c that constructs
+ * the appropriate GDB type.
+ */
+ return make_reference_type (
+ hpread_type_lookup (dn_bufp->dreference.pointsto,
+ objfile),
+ NULL);
+
+ case DNTT_TYPE_ENUM:
+ return hpread_read_enum_type (hp_type, dn_bufp, objfile);
+ case DNTT_TYPE_SET:
+ return hpread_read_set_type (hp_type, dn_bufp, objfile);
+ case DNTT_TYPE_SUBRANGE:
+ return hpread_read_subrange_type (hp_type, dn_bufp, objfile);
+ case DNTT_TYPE_ARRAY:
+ return hpread_read_array_type (hp_type, dn_bufp, objfile);
+ case DNTT_TYPE_STRUCT:
+ case DNTT_TYPE_UNION:
+ return hpread_read_struct_type (hp_type, dn_bufp, objfile);
+ case DNTT_TYPE_FIELD:
+ return hpread_type_lookup (dn_bufp->dfield.type, objfile);
+
+ case DNTT_TYPE_FUNCTYPE:
+ /* Here we want to read the function SOMs and return a
+ * type for it. We get here, for instance, when processing
+ * pointer-to-function type.
+ */
+ return hpread_read_function_type (hp_type, dn_bufp, objfile, 0);
+
+ case DNTT_TYPE_PTRMEM:
+ /* Declares a C++ pointer-to-data-member type.
+ * The "pointsto" field defines the class,
+ * while the "memtype" field defines the pointed-to-type.
+ */
+ {
+ struct type * ptrmemtype;
+ struct type * class_type;
+ struct type * memtype;
+ memtype = hpread_type_lookup (dn_bufp->dptrmem.memtype,
+ objfile),
+ class_type = hpread_type_lookup (dn_bufp->dptrmem.pointsto,
+ objfile),
+ ptrmemtype = alloc_type(objfile);
+ smash_to_member_type(ptrmemtype, class_type, memtype);
+ return make_pointer_type(ptrmemtype, NULL);
+ }
+ break;
+
+ case DNTT_TYPE_PTRMEMFUNC:
+ /* Defines a C++ pointer-to-function-member type.
+ * The "pointsto" field defines the class,
+ * while the "memtype" field defines the pointed-to-type.
+ */
+ {
+ struct type * ptrmemtype;
+ struct type * class_type;
+ struct type * functype;
+ struct type * retvaltype;
+ int nargs;
+ int i;
+ struct type ** args_type;
+ class_type = hpread_type_lookup (dn_bufp->dptrmem.pointsto,
+ objfile);
+ functype = hpread_type_lookup (dn_bufp->dptrmem.memtype,
+ objfile);
+ retvaltype = TYPE_TARGET_TYPE (functype);
+ nargs = TYPE_NFIELDS (functype);
+ args_type = (struct type **) xmalloc ((nargs+1) * sizeof (struct type *));
+ for (i = 0; i < nargs; i++) {
+ args_type[i] = TYPE_FIELD_TYPE (functype, i);
+ }
+ args_type[nargs] = NULL;
+ ptrmemtype = alloc_type(objfile);
+ smash_to_method_type(ptrmemtype, class_type, retvaltype, args_type);
+ return make_pointer_type(ptrmemtype, NULL);
+ }
+ break;
+
+ case DNTT_TYPE_CLASS:
+ return hpread_read_struct_type (hp_type, dn_bufp, objfile);
+
+ case DNTT_TYPE_GENFIELD:
+ /* Chase pointer from GENFIELD to FIELD, and make recursive
+ * call on that.
+ */
+ return hpread_type_lookup (dn_bufp->dgenfield.field, objfile);
+
+ case DNTT_TYPE_VFUNC:
+ /* C++ virtual function.
+ * We get here in the course of processing a class type which
+ * contains virtual functions. Just go through another level
+ * of indirection to get to the pointed-to function SOM.
+ */
+ return hpread_type_lookup (dn_bufp->dvfunc.funcptr, objfile);
+
+ case DNTT_TYPE_MODIFIER:
+ /* Check the modifiers and then just make a recursive call on
+ * the "type" pointed to by the modifier DNTT.
+ *
+ * pai:: FIXME -- do we ever want to handle "m_duplicate" and
+ * "m_void" modifiers? Is static_flag really needed here?
+ * (m_static used for methods of classes, elsewhere).
+ */
+ tmp_type = make_cv_type (dn_bufp->dmodifier.m_const,
+ dn_bufp->dmodifier.m_volatile,
+ hpread_type_lookup (dn_bufp->dmodifier.type, objfile),
+ 0);
+ return tmp_type;
+
+
+ case DNTT_TYPE_MEMFUNC:
+ /* Member function. Treat like a function.
+ * I think we get here in the course of processing a
+ * pointer-to-member-function type...
+ */
+ return hpread_read_function_type (hp_type, dn_bufp, objfile, 0);
+
+ case DNTT_TYPE_DOC_MEMFUNC:
+ return hpread_read_doc_function_type (hp_type, dn_bufp, objfile, 0);
+
+ case DNTT_TYPE_TEMPLATE:
+ /* Template - sort of the header for a template definition,
+ * which like a class, points to a member list and also points
+ * to a TEMPLATE_ARG list of type-arguments.
+ */
+ return hpread_read_struct_type (hp_type, dn_bufp, objfile);
+
+ case DNTT_TYPE_TEMPLATE_ARG:
+ {
+ char * name;
+ /* The TEMPLATE record points to an argument list of
+ * TEMPLATE_ARG records, each of which describes one
+ * of the type-arguments.
+ */
+ name = VT (objfile) + dn_bufp->dtempl_arg.name;
+ return hpread_read_templ_arg_type (hp_type, dn_bufp, objfile, name);
+ }
+
+ case DNTT_TYPE_FUNC_TEMPLATE:
+ /* We wind up here when processing a TEMPLATE type,
+ * if the template has member function(s).
+ * Treat it like a FUNCTION.
+ */
+ return hpread_read_function_type (hp_type, dn_bufp, objfile, 0);
+
+ case DNTT_TYPE_LINK:
+ /* The LINK record is used to link up templates with instantiations.
+ * There is no type associated with the LINK record per se.
+ */
+ return lookup_fundamental_type (objfile, FT_VOID);
+
+ /* Also not yet handled... */
+ /* case DNTT_TYPE_DYN_ARRAY_DESC: */
+ /* case DNTT_TYPE_DESC_SUBRANGE: */
+ /* case DNTT_TYPE_BEGIN_EXT: */
+ /* case DNTT_TYPE_INLN: */
+ /* case DNTT_TYPE_INLN_LIST: */
+ /* case DNTT_TYPE_ALIAS: */
+ default:
+ /* A fancy way of returning NULL */
+ return lookup_fundamental_type (objfile, FT_VOID);
+ }
+}
+
+static sltpointer
+hpread_record_lines (subfile, s_idx, e_idx, objfile, offset)
+ struct subfile *subfile;
+ sltpointer s_idx, e_idx;
+ struct objfile *objfile;
+ CORE_ADDR offset;
+{
+ union sltentry *sl_bufp;
+
+ while (s_idx <= e_idx)
+ {
+ sl_bufp = hpread_get_slt (s_idx, objfile);
+ /* Only record "normal" entries in the SLT. */
+ if (sl_bufp->snorm.sltdesc == SLT_NORMAL
+ || sl_bufp->snorm.sltdesc == SLT_EXIT)
+ record_line (subfile, sl_bufp->snorm.line,
+ sl_bufp->snorm.address + offset);
+ else if (sl_bufp->snorm.sltdesc == SLT_NORMAL_OFFSET)
+ record_line (subfile, sl_bufp->snormoff.line,
+ sl_bufp->snormoff.address + offset);
+ s_idx++;
+ }
+ return e_idx;
+}
+
+/* Given a function "f" which is a member of a class, find
+ * the classname that it is a member of. Used to construct
+ * the name (e.g., "c::f") which GDB will put in the
+ * "demangled name" field of the function's symbol.
+ * Called from hpread_process_one_debug_symbol()
+ * If "f" is not a member function, return NULL.
+ */
+char * class_of (functype)
+struct type * functype;
+{
+ struct type * first_param_type;
+ char * first_param_name;
+ struct type * pointed_to_type;
+ char * class_name;
+
+ /* Check that the function has a first argument "this",
+ * and that "this" is a pointer to a class. If not,
+ * functype is not a member function, so return NULL.
+ */
+ if (TYPE_NFIELDS(functype) == 0)
+ return NULL;
+ first_param_name = TYPE_FIELD_NAME (functype, 0);
+ if (first_param_name == NULL)
+ return NULL; /* paranoia */
+ if (strcmp(first_param_name, "this"))
+ return NULL;
+ first_param_type = TYPE_FIELD_TYPE (functype, 0);
+ if (first_param_type == NULL)
+ return NULL; /* paranoia */
+ if (TYPE_CODE(first_param_type) != TYPE_CODE_PTR)
+ return NULL;
+
+ /* Get the thing that "this" points to, check that
+ * it's a class, and get its class name.
+ */
+ pointed_to_type = TYPE_TARGET_TYPE(first_param_type);
+ if (pointed_to_type == NULL)
+ return NULL; /* paranoia */
+ if (TYPE_CODE(pointed_to_type) != TYPE_CODE_CLASS)
+ return NULL;
+ class_name = TYPE_NAME(pointed_to_type);
+ if (class_name == NULL)
+ return NULL; /* paranoia */
+
+ /* The class name may be of the form "class c", in which case
+ * we want to strip off the leading "class ".
+ */
+ if (strncmp(class_name, "class ", 6) == 0)
+ class_name += 6;
+
+ return class_name;
+}
+
+/* Internalize one native debug symbol.
+ * Called in a loop from hpread_expand_symtab().
+ * Arguments:
+ * dn_bufp:
+ * name:
+ * section_offsets:
+ * objfile:
+ * text_offset:
+ * text_size:
+ * filename:
+ * index: Index of this symbol
+ * at_module_boundary_p Pointer to boolean flag to control caller's loop.
+ */
+
+static void
+hpread_process_one_debug_symbol (dn_bufp, name, section_offsets, objfile,
+ text_offset, text_size, filename,
+ index, at_module_boundary_p
+ )
+ union dnttentry *dn_bufp;
+ char *name;
+ struct section_offsets *section_offsets;
+ struct objfile *objfile;
+ CORE_ADDR text_offset;
+ int text_size;
+ char *filename;
+ int index;
+ int *at_module_boundary_p;
+{
+ unsigned long desc;
+ int type;
+ CORE_ADDR valu;
+ int offset = ANOFFSET (section_offsets, SECT_OFF_TEXT);
+ int data_offset = ANOFFSET (section_offsets, SECT_OFF_DATA);
+ union dnttentry *dn_temp;
+ dnttpointer hp_type;
+ struct symbol *sym;
+ struct context_stack *new;
+ char * class_scope_name;
+ extern int is_in_import_list (); /* in somread.c */
+
+ /* Allocate one GDB debug symbol and fill in some default values. */
+ sym = (struct symbol *) obstack_alloc (&objfile->symbol_obstack,
+ sizeof (struct symbol));
+ memset (sym, 0, sizeof (struct symbol));
+ SYMBOL_NAME (sym) = obsavestring (name, strlen (name), &objfile->symbol_obstack);
+ SYMBOL_LANGUAGE (sym) = language_auto;
+ SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
+ SYMBOL_LINE (sym) = 0;
+ SYMBOL_VALUE (sym) = 0;
+ SYMBOL_CLASS (sym) = LOC_TYPEDEF;
+
+ /* Just a trick in case the SOM debug symbol is a type definition.
+ * There are routines that are set up to build a GDB type symbol, given
+ * a SOM dnttpointer. So we set up a dummy SOM dnttpointer "hp_type".
+ * This allows us to call those same routines.
+ */
+ hp_type.dnttp.extension = 1;
+ hp_type.dnttp.immediate = 0;
+ hp_type.dnttp.global = 0;
+ hp_type.dnttp.index = index;
+
+ /* This "type" is the type of SOM record.
+ * Switch on SOM type.
+ */
+ type = dn_bufp->dblock.kind;
+ switch (type)
+ {
+ case DNTT_TYPE_SRCFILE:
+ /* This type of symbol indicates from which source file or
+ * include file any following data comes. It may indicate:
+ *
+ * o The start of an entirely new source file (and thus
+ * a new module)
+ *
+ * o The start of a different source file due to #include
+ *
+ * o The end of an include file and the return to the original
+ * file. Thus if "foo.c" includes "bar.h", we see first
+ * a SRCFILE for foo.c, then one for bar.h, and then one for
+ * foo.c again.
+ *
+ * If it indicates the start of a new module then we must
+ * finish the symbol table of the previous module
+ * (if any) and start accumulating a new symbol table.
+ */
+
+ valu = text_offset;
+ if (!last_source_file ) {
+ /*
+ * A note on "last_source_file": this is a char* pointing
+ * to the actual file name. "start_symtab" sets it,
+ * "end_symtab" clears it.
+ *
+ * So if "last_source_file" is NULL, then either this is
+ * the first record we are looking at, or a previous call
+ * to "end_symtab()" was made to close out the previous
+ * module. Since we're now quitting the scan loop when we
+ * see a MODULE END record, we should never get here, except
+ * in the case that we're not using the quick look-up tables
+ * and have to use the old system as a fall-back.
+ */
+ start_symtab (name, NULL, valu);
+ record_debugformat ("HP");
+ SL_INDEX (objfile) = dn_bufp->dsfile.address;
+ }
+
+ else {
+ /* Either a new include file, or a SRCFILE record
+ * saying we are back in the main source (or out of
+ * a nested include file) again.
+ */
+ SL_INDEX (objfile) = hpread_record_lines (current_subfile,
+ SL_INDEX (objfile),
+ dn_bufp->dsfile.address,
+ objfile, offset);
+ }
+
+ /* A note on "start_subfile". This routine will check
+ * the name we pass it and look for an existing subfile
+ * of that name. There's thus only one sub-file for the
+ * actual source (e.g. for "foo.c" in foo.c), despite the
+ * fact that we'll see lots of SRCFILE entries for foo.c
+ * inside foo.c.
+ */
+ start_subfile (name, NULL);
+ break;
+
+ case DNTT_TYPE_MODULE:
+ /*
+ * We no longer ignore DNTT_TYPE_MODULE symbols. The module
+ * represents the meaningful semantic structure of a compilation
+ * unit. We expect to start the psymtab-to-symtab expansion
+ * looking at a MODULE entry, and to end it at the corresponding
+ * END MODULE entry.
+ *
+ *--Begin outdated comments
+ *
+ * This record signifies the start of a new source module
+ * In C/C++ there is no explicit "module" construct in the language,
+ * but each compilation unit is implicitly a module and they
+ * do emit the DNTT_TYPE_MODULE records.
+ * The end of the module is marked by a matching DNTT_TYPE_END record.
+ *
+ * The reason GDB gets away with ignoring the DNTT_TYPE_MODULE record
+ * is it notices the DNTT_TYPE_END record for the previous
+ * module (see comments under DNTT_TYPE_END case), and then treats
+ * the next DNTT_TYPE_SRCFILE record as if it were the module-start record.
+ * (i.e., it makes a start_symtab() call).
+ * This scheme seems a little convoluted, but I'll leave it
+ * alone on the principle "if it ain't broke don't fix
+ * it". (RT).
+ *
+ *-- End outdated comments
+ */
+
+ valu = text_offset;
+ if (!last_source_file )
+ {
+ /* Start of a new module. We know this because "last_source_file"
+ * is NULL, which can only happen the first time or if we just
+ * made a call to end_symtab() to close out the previous module.
+ */
+ start_symtab (name, NULL, valu);
+ SL_INDEX (objfile) = dn_bufp->dmodule.address;
+ }
+ else
+ {
+ /* This really shouldn't happen if we're using the quick
+ * look-up tables, as it would mean we'd scanned past an
+ * END MODULE entry. But if we're not using the tables,
+ * we started the module on the SRCFILE entry, so it's ok.
+ * For now, accept this.
+ */
+ /* warning( "Error expanding psymtab, missed module end, found entry for %s",
+ * name );
+ */
+ *at_module_boundary_p = -1;
+ }
+
+ start_subfile (name, NULL);
+ break;
+
+ case DNTT_TYPE_FUNCTION:
+ case DNTT_TYPE_ENTRY:
+ /* A function or secondary entry point. */
+ valu = dn_bufp->dfunc.lowaddr + offset;
+
+ /* Record lines up to this point. */
+ SL_INDEX (objfile) = hpread_record_lines (current_subfile,
+ SL_INDEX (objfile),
+ dn_bufp->dfunc.address,
+ objfile, offset);
+
+ WITHIN_FUNCTION (objfile) = 1;
+ CURRENT_FUNCTION_VALUE (objfile) = valu;
+
+ /* Stack must be empty now. */
+ if (context_stack_depth != 0)
+ complain (&lbrac_unmatched_complaint, (char *) symnum);
+ new = push_context (0, valu);
+
+ /* Built a type for the function. This includes processing
+ * the symbol records for the function parameters.
+ */
+ SYMBOL_CLASS (sym) = LOC_BLOCK;
+ SYMBOL_TYPE (sym) = hpread_read_function_type (hp_type, dn_bufp, objfile, 1);
+
+ /* The "SYMBOL_NAME" field is expected to be the mangled name
+ * (if any), which we get from the "alias" field of the SOM record
+ * if that exists.
+ */
+ if ((dn_bufp->dfunc.language == HP_LANGUAGE_CPLUSPLUS) &&
+ dn_bufp->dfunc.alias && /* has an alias */
+ *(char *)(VT (objfile) + dn_bufp->dfunc.alias)) /* not a null string */
+ SYMBOL_NAME (sym) = VT (objfile) + dn_bufp->dfunc.alias;
+ else
+ SYMBOL_NAME (sym) = VT (objfile) + dn_bufp->dfunc.name;
+
+ /* Special hack to get around HP compilers' insistence on
+ * reporting "main" as "_MAIN_" for C/C++ */
+ if ((strcmp (SYMBOL_NAME (sym), "_MAIN_") == 0) &&
+ (strcmp (VT (objfile) + dn_bufp->dfunc.name, "main") == 0))
+ SYMBOL_NAME (sym) = VT (objfile) + dn_bufp->dfunc.name;
+
+ /* The SYMBOL_CPLUS_DEMANGLED_NAME field is expected to
+ * be the demangled name.
+ */
+ if (dn_bufp->dfunc.language == HP_LANGUAGE_CPLUSPLUS)
+ {
+ /* SYMBOL_INIT_DEMANGLED_NAME is a macro which winds up
+ * calling the demangler in libiberty (cplus_demangle()) to
+ * do the job. This generally does the job, even though
+ * it's intended for the GNU compiler and not the aCC compiler
+ * Note that SYMBOL_INIT_DEMANGLED_NAME calls the
+ * demangler with arguments DMGL_PARAMS | DMGL_ANSI.
+ * Generally, we don't want params when we display
+ * a demangled name, but when I took out the DMGL_PARAMS,
+ * some things broke, so I'm leaving it in here, and
+ * working around the issue in stack.c. - RT
+ */
+ SYMBOL_INIT_DEMANGLED_NAME (sym, &objfile->symbol_obstack);
+ if ((SYMBOL_NAME (sym) == VT (objfile) + dn_bufp->dfunc.alias) &&
+ (!SYMBOL_CPLUS_DEMANGLED_NAME(sym))) {
+
+ /* Well, the symbol name is mangled, but the
+ * demangler in libiberty failed so the demangled
+ * field is still NULL. Try to
+ * do the job ourselves based on the "name" field
+ * in the SOM record. A complication here is that
+ * the name field contains only the function name
+ * (like "f"), whereas we want the class qualification
+ * (as in "c::f"). Try to reconstruct that.
+ */
+ char * basename;
+ char * classname;
+ char * dem_name;
+ basename = VT (objfile) + dn_bufp->dfunc.name;
+ classname = class_of(SYMBOL_TYPE(sym));
+ if (classname) {
+ dem_name = xmalloc(strlen(basename)+strlen(classname)+3);
+ strcpy(dem_name, classname);
+ strcat(dem_name, "::");
+ strcat(dem_name, basename);
+ SYMBOL_CPLUS_DEMANGLED_NAME(sym) = dem_name;
+ SYMBOL_LANGUAGE (sym) = language_cplus;
+ }
+ }
+ }
+
+ /* Add the function symbol to the list of symbols in this blockvector */
+ if (dn_bufp->dfunc.global)
+ add_symbol_to_list (sym, &global_symbols);
+ else
+ add_symbol_to_list (sym, &file_symbols);
+ new->name = sym;
+
+ /* Search forward to the next BEGIN and also read
+ * in the line info up to that point.
+ * Not sure why this is needed.
+ * In HP FORTRAN this code is harmful since there
+ * may not be a BEGIN after the FUNCTION.
+ * So I made it C/C++ specific. - RT
+ */
+ if (dn_bufp->dfunc.language == HP_LANGUAGE_C ||
+ dn_bufp->dfunc.language == HP_LANGUAGE_CPLUSPLUS) {
+ while (dn_bufp->dblock.kind != DNTT_TYPE_BEGIN)
+ {
+ dn_bufp = hpread_get_lntt (++index, objfile);
+ if (dn_bufp->dblock.extension)
+ continue;
+ }
+ SL_INDEX (objfile) = hpread_record_lines (current_subfile,
+ SL_INDEX (objfile),
+ dn_bufp->dbegin.address,
+ objfile, offset);
+ SYMBOL_LINE (sym) = hpread_get_line (dn_bufp->dbegin.address, objfile);
+ }
+ record_line (current_subfile, SYMBOL_LINE (sym), valu);
+ break;
+
+ case DNTT_TYPE_DOC_FUNCTION:
+ valu = dn_bufp->ddocfunc.lowaddr + offset;
+
+ /* Record lines up to this point. */
+ SL_INDEX (objfile) = hpread_record_lines (current_subfile,
+ SL_INDEX (objfile),
+ dn_bufp->ddocfunc.address,
+ objfile, offset);
+
+ WITHIN_FUNCTION (objfile) = 1;
+ CURRENT_FUNCTION_VALUE (objfile) = valu;
+ /* Stack must be empty now. */
+ if (context_stack_depth != 0)
+ complain (&lbrac_unmatched_complaint, (char *) symnum);
+ new = push_context (0, valu);
+
+ /* Built a type for the function. This includes processing
+ * the symbol records for the function parameters.
+ */
+ SYMBOL_CLASS (sym) = LOC_BLOCK;
+ SYMBOL_TYPE (sym) = hpread_read_doc_function_type (hp_type, dn_bufp, objfile, 1);
+
+ /* The "SYMBOL_NAME" field is expected to be the mangled name
+ * (if any), which we get from the "alias" field of the SOM record
+ * if that exists.
+ */
+ if ((dn_bufp->ddocfunc.language == HP_LANGUAGE_CPLUSPLUS) &&
+ dn_bufp->ddocfunc.alias && /* has an alias */
+ *(char *)(VT (objfile) + dn_bufp->ddocfunc.alias)) /* not a null string */
+ SYMBOL_NAME (sym) = VT (objfile) + dn_bufp->ddocfunc.alias;
+ else
+ SYMBOL_NAME (sym) = VT (objfile) + dn_bufp->ddocfunc.name;
+
+ /* Special hack to get around HP compilers' insistence on
+ * reporting "main" as "_MAIN_" for C/C++ */
+ if ((strcmp (SYMBOL_NAME (sym), "_MAIN_") == 0) &&
+ (strcmp (VT (objfile) + dn_bufp->ddocfunc.name, "main") == 0))
+ SYMBOL_NAME (sym) = VT (objfile) + dn_bufp->ddocfunc.name;
+
+ if (dn_bufp->ddocfunc.language == HP_LANGUAGE_CPLUSPLUS) {
+
+ /* SYMBOL_INIT_DEMANGLED_NAME is a macro which winds up
+ * calling the demangler in libiberty (cplus_demangle()) to
+ * do the job. This generally does the job, even though
+ * it's intended for the GNU compiler and not the aCC compiler
+ * Note that SYMBOL_INIT_DEMANGLED_NAME calls the
+ * demangler with arguments DMGL_PARAMS | DMGL_ANSI.
+ * Generally, we don't want params when we display
+ * a demangled name, but when I took out the DMGL_PARAMS,
+ * some things broke, so I'm leaving it in here, and
+ * working around the issue in stack.c. - RT
+ */
+ SYMBOL_INIT_DEMANGLED_NAME (sym, &objfile->symbol_obstack);
+
+ if ((SYMBOL_NAME (sym) == VT (objfile) + dn_bufp->ddocfunc.alias) &&
+ (!SYMBOL_CPLUS_DEMANGLED_NAME(sym))) {
+
+ /* Well, the symbol name is mangled, but the
+ * demangler in libiberty failed so the demangled
+ * field is still NULL. Try to
+ * do the job ourselves based on the "name" field
+ * in the SOM record. A complication here is that
+ * the name field contains only the function name
+ * (like "f"), whereas we want the class qualification
+ * (as in "c::f"). Try to reconstruct that.
+ */
+ char * basename;
+ char * classname;
+ char * dem_name;
+ basename = VT (objfile) + dn_bufp->ddocfunc.name;
+ classname = class_of(SYMBOL_TYPE(sym));
+ if (classname) {
+ dem_name = xmalloc(strlen(basename)+strlen(classname)+3);
+ strcpy(dem_name, classname);
+ strcat(dem_name, "::");
+ strcat(dem_name, basename);
+ SYMBOL_CPLUS_DEMANGLED_NAME(sym) = dem_name;
+ SYMBOL_LANGUAGE (sym) = language_cplus;
+ }
+ }
+ }
+
+ /* Add the function symbol to the list of symbols in this blockvector */
+ if (dn_bufp->ddocfunc.global)
+ add_symbol_to_list (sym, &global_symbols);
+ else
+ add_symbol_to_list (sym, &file_symbols);
+ new->name = sym;
+
+ /* Search forward to the next BEGIN and also read
+ * in the line info up to that point.
+ * Not sure why this is needed.
+ * In HP FORTRAN this code is harmful since there
+ * may not be a BEGIN after the FUNCTION.
+ * So I made it C/C++ specific. - RT
+ */
+ if (dn_bufp->ddocfunc.language == HP_LANGUAGE_C ||
+ dn_bufp->ddocfunc.language == HP_LANGUAGE_CPLUSPLUS) {
+ while (dn_bufp->dblock.kind != DNTT_TYPE_BEGIN)
+ {
+ dn_bufp = hpread_get_lntt (++index, objfile);
+ if (dn_bufp->dblock.extension)
+ continue;
+ }
+ SL_INDEX (objfile) = hpread_record_lines (current_subfile,
+ SL_INDEX (objfile),
+ dn_bufp->dbegin.address,
+ objfile, offset);
+ SYMBOL_LINE (sym) = hpread_get_line (dn_bufp->dbegin.address, objfile);
+ }
+ record_line (current_subfile, SYMBOL_LINE (sym), valu);
+ break;
+
+ case DNTT_TYPE_BEGIN:
+ /* Begin a new scope. */
+ if (context_stack_depth == 1 /* this means we're at function level */ &&
+ context_stack[0].name != NULL /* this means it's a function */ &&
+ context_stack[0].depth == 0 /* this means it's the first BEGIN
+ we've seen after the FUNCTION */
+ )
+ {
+ /* This is the first BEGIN after a FUNCTION.
+ * We ignore this one, since HP compilers always insert
+ * at least one BEGIN, i.e. it's:
+ *
+ * FUNCTION
+ * argument symbols
+ * BEGIN
+ * local symbols
+ * (possibly nested BEGIN ... END's if there are inner { } blocks)
+ * END
+ * END
+ *
+ * By ignoring this first BEGIN, the local symbols get treated
+ * as belonging to the function scope, and "print func::local_sym"
+ * works (which is what we want).
+ */
+
+ /* All we do here is increase the depth count associated with
+ * the FUNCTION entry in the context stack. This ensures that
+ * the next BEGIN we see (if any), representing a real nested { }
+ * block, will get processed.
+ */
+
+ context_stack[0].depth++;
+
+ } else {
+
+ /* Record lines up to this SLT pointer. */
+ SL_INDEX (objfile) = hpread_record_lines (current_subfile,
+ SL_INDEX (objfile),
+ dn_bufp->dbegin.address,
+ objfile, offset);
+ /* Calculate start address of new scope */
+ valu = hpread_get_location (dn_bufp->dbegin.address, objfile);
+ valu += offset; /* Relocate for dynamic loading */
+ /* We use the scope start DNTT index as nesting depth identifier! */
+ desc = hpread_get_scope_start (dn_bufp->dbegin.address, objfile);
+ new = push_context (desc, valu);
+ }
+ break;
+
+ case DNTT_TYPE_END:
+ /* End a scope. */
+
+ /* Valid end kinds are:
+ * MODULE
+ * FUNCTION
+ * WITH
+ * COMMON
+ * BEGIN
+ * CLASS_SCOPE
+ */
+
+ SL_INDEX (objfile) = hpread_record_lines (current_subfile,
+ SL_INDEX (objfile),
+ dn_bufp->dend.address,
+ objfile, offset);
+ switch (dn_bufp->dend.endkind)
+ {
+ case DNTT_TYPE_MODULE:
+ /* Ending a module ends the symbol table for that module.
+ * Calling end_symtab() has the side effect of clearing the
+ * last_source_file pointer, which in turn signals
+ * process_one_debug_symbol() to treat the next DNTT_TYPE_SRCFILE
+ * record as a module-begin.
+ */
+ valu = text_offset + text_size + offset;
+
+ /* Tell our caller that we're done with expanding the
+ * debug information for a module.
+ */
+ *at_module_boundary_p = 1;
+
+ /* Don't do this, as our caller will do it!
+ *
+ * (void) end_symtab (valu, objfile, 0);
+ */
+ break;
+
+ case DNTT_TYPE_FUNCTION:
+ /* Ending a function, well, ends the function's scope. */
+ dn_temp = hpread_get_lntt (dn_bufp->dend.beginscope.dnttp.index,
+ objfile);
+ valu = dn_temp->dfunc.hiaddr + offset;
+ /* Insert func params into local list */
+ merge_symbol_lists (&param_symbols, &local_symbols);
+ 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);
+ WITHIN_FUNCTION (objfile) = 0; /* This may have to change for Pascal */
+ local_symbols = new->locals;
+ param_symbols = new->params;
+ break;
+
+ case DNTT_TYPE_BEGIN:
+ if (context_stack_depth == 1 &&
+ context_stack[0].name != NULL &&
+ context_stack[0].depth == 1)
+ {
+ /* This is the END corresponding to the
+ * BEGIN which we ignored - see DNTT_TYPE_BEGIN case above.
+ */
+ context_stack[0].depth--;
+ } else {
+ /* Ending a local scope. */
+ valu = hpread_get_location (dn_bufp->dend.address, objfile);
+ /* Why in the hell is this needed? */
+ valu += offset + 9; /* Relocate for dynamic loading */
+ new = pop_context ();
+ desc = dn_bufp->dend.beginscope.dnttp.index;
+ if (desc != new->depth)
+ complain (&lbrac_mismatch_complaint, (char *) symnum);
+
+ /* Make a block for the local symbols within. */
+ finish_block (new->name, &local_symbols, new->old_blocks,
+ new->start_addr, valu, objfile);
+ local_symbols = new->locals;
+ param_symbols = new->params;
+ }
+ break;
+
+ case DNTT_TYPE_WITH:
+ /* Since we ignore the DNTT_TYPE_WITH that starts the scope,
+ * we can ignore the DNTT_TYPE_END that ends it.
+ */
+ break;
+
+ case DNTT_TYPE_COMMON:
+ /* End a FORTRAN common block. We don't currently handle these */
+ complain (&hpread_unhandled_end_common_complaint);
+ break;
+
+ case DNTT_TYPE_CLASS_SCOPE:
+
+ /* pai: FIXME Not handling nested classes for now -- must
+ * maintain a stack */
+ class_scope_name = NULL;
+
+#if 0
+ /* End a class scope */
+ valu = hpread_get_location (dn_bufp->dend.address, objfile);
+ /* Why in the hell is this needed? */
+ valu += offset + 9; /* Relocate for dynamic loading */
+ new = pop_context ();
+ desc = dn_bufp->dend.beginscope.dnttp.index;
+ if (desc != new->depth)
+ complain (&lbrac_mismatch_complaint, (char *) symnum);
+ /* Make a block for the local symbols within. */
+ finish_block (new->name, &local_symbols, new->old_blocks,
+ new->start_addr, valu, objfile);
+ local_symbols = new->locals;
+ param_symbols = new->params;
+#endif
+ break;
+
+ default:
+ complain (&hpread_unexpected_end_complaint);
+ break;
+ }
+ break;
+
+ /* DNTT_TYPE_IMPORT is not handled */
+
+ case DNTT_TYPE_LABEL:
+ SYMBOL_NAMESPACE (sym) = LABEL_NAMESPACE;
+ break;
+
+ case DNTT_TYPE_FPARAM:
+ /* Function parameters. */
+ /* Note 1: This code was present in the 4.16 sources, and then
+ removed, because fparams are handled in
+ hpread_read_function_type(). However, while fparam symbols
+ are indeed handled twice, this code here cannot be removed
+ because then they don't get added to the local symbol list of
+ the function's code block, which leads to a failure to look
+ up locals, "this"-relative member names, etc. So I've put
+ this code back in. pai/1997-07-21 */
+ /* Note 2: To fix a defect, we stopped adding FPARAMS to local_symbols
+ in hpread_read_function_type(), so FPARAMS had to be handled
+ here. I changed the location to be the appropriate argument
+ kinds rather than LOC_LOCAL. pai/1997-08-08 */
+ /* Note 3: Well, the fix in Note 2 above broke argument printing
+ in traceback frames, and further it makes assumptions about the
+ order of the FPARAM entries from HP compilers (cc and aCC in particular
+ generate them in reverse orders -- fixing one breaks for the other).
+ So I've added code in hpread_read_function_type() to add fparams
+ to a param_symbols list for the current context level. These are
+ then merged into local_symbols when a function end is reached.
+ pai/1997-08-11 */
+
+ break; /* do nothing; handled in hpread_read_function_type() */
+
+#if 0 /* Old code */
+ if (dn_bufp->dfparam.regparam)
+ SYMBOL_CLASS (sym) = LOC_REGISTER;
+ else if (dn_bufp->dfparam.indirect)
+ SYMBOL_CLASS (sym) = LOC_REF_ARG;
+ else
+ SYMBOL_CLASS (sym) = LOC_ARG;
+ SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
+ if (dn_bufp->dfparam.copyparam)
+ {
+ SYMBOL_VALUE (sym) = dn_bufp->dfparam.location;
+#ifdef HPREAD_ADJUST_STACK_ADDRESS
+ SYMBOL_VALUE (sym)
+ += HPREAD_ADJUST_STACK_ADDRESS (CURRENT_FUNCTION_VALUE (objfile));
+#endif
+ }
+ else
+ SYMBOL_VALUE (sym) = dn_bufp->dfparam.location;
+ SYMBOL_TYPE (sym) = hpread_type_lookup (dn_bufp->dfparam.type, objfile);
+ add_symbol_to_list (sym, &fparam_symbols);
+ break;
+#endif
+
+ case DNTT_TYPE_SVAR:
+ /* Static variables. */
+ SYMBOL_CLASS (sym) = LOC_STATIC;
+
+ /* Note: There is a case that arises with globals in shared
+ * libraries where we need to set the address to LOC_INDIRECT.
+ * This case is if you have a global "g" in one library, and
+ * it is referenced "extern <type> g;" in another library.
+ * If we're processing the symbols for the referencing library,
+ * we'll see a global "g", but in this case the address given
+ * in the symbol table contains a pointer to the real "g".
+ * We use the storage class LOC_INDIRECT to indicate this. RT
+ */
+ if (is_in_import_list (SYMBOL_NAME(sym), objfile))
+ SYMBOL_CLASS (sym) = LOC_INDIRECT;
+
+ SYMBOL_VALUE_ADDRESS (sym) = dn_bufp->dsvar.location + data_offset;
+ SYMBOL_TYPE (sym) = hpread_type_lookup (dn_bufp->dsvar.type, objfile);
+
+ if (dn_bufp->dsvar.global)
+ add_symbol_to_list (sym, &global_symbols);
+
+ else if (WITHIN_FUNCTION (objfile))
+ add_symbol_to_list (sym, &local_symbols);
+
+ else
+ add_symbol_to_list (sym, &file_symbols);
+
+ if (dn_bufp->dsvar.thread_specific)
+ {
+ /* Thread-local variable.
+ */
+ SYMBOL_CLASS (sym) = LOC_THREAD_LOCAL_STATIC;
+ SYMBOL_BASEREG (sym) = CR27_REGNUM;
+
+ if( objfile->flags & OBJF_SHARED ) {
+ /*
+ * This variable is not only thread local but
+ * in a shared library.
+ *
+ * Alas, the shared lib structures are private
+ * to "somsolib.c". But C lets us point to one.
+ */
+ struct so_list *so;
+
+ if( objfile->obj_private == NULL )
+ error( "Internal error in reading shared library information." );
+
+ so = ((obj_private_data_t *)(objfile->obj_private))->so_info;
+ if( so == NULL )
+ error( "Internal error in reading shared library information." );
+
+ /* Thread-locals in shared libraries do NOT have the
+ * standard offset ("data_offset"), so we re-calculate
+ * where to look for this variable, using a call-back
+ * to interpret the private shared-library data.
+ */
+ SYMBOL_VALUE_ADDRESS(sym) = dn_bufp->dsvar.location +
+ so_lib_thread_start_addr( so );
+ }
+ }
+ break;
+
+ case DNTT_TYPE_DVAR:
+ /* Dynamic variables. */
+ if (dn_bufp->ddvar.regvar)
+ SYMBOL_CLASS (sym) = LOC_REGISTER;
+ else
+ SYMBOL_CLASS (sym) = LOC_LOCAL;
+
+ SYMBOL_VALUE (sym) = dn_bufp->ddvar.location;
+#ifdef HPREAD_ADJUST_STACK_ADDRESS
+ SYMBOL_VALUE (sym)
+ += HPREAD_ADJUST_STACK_ADDRESS (CURRENT_FUNCTION_VALUE (objfile));
+#endif
+ SYMBOL_TYPE (sym) = hpread_type_lookup (dn_bufp->ddvar.type, objfile);
+ if (dn_bufp->ddvar.global)
+ add_symbol_to_list (sym, &global_symbols);
+ else if (WITHIN_FUNCTION (objfile))
+ add_symbol_to_list (sym, &local_symbols);
+ else
+ add_symbol_to_list (sym, &file_symbols);
+ break;
+
+ case DNTT_TYPE_CONST:
+ /* A constant (pascal?). */
+ SYMBOL_CLASS (sym) = LOC_CONST;
+ SYMBOL_VALUE (sym) = dn_bufp->dconst.location;
+ SYMBOL_TYPE (sym) = hpread_type_lookup (dn_bufp->dconst.type, objfile);
+ if (dn_bufp->dconst.global)
+ add_symbol_to_list (sym, &global_symbols);
+ else if (WITHIN_FUNCTION (objfile))
+ add_symbol_to_list (sym, &local_symbols);
+ else
+ add_symbol_to_list (sym, &file_symbols);
+ break;
+
+ case DNTT_TYPE_TYPEDEF:
+ /* A typedef. We do want to process these, since a name is
+ * added to the namespace for the typedef'ed name.
+ */
+ SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
+ SYMBOL_TYPE (sym) = hpread_type_lookup (dn_bufp->dtype.type, objfile);
+ if (dn_bufp->dtype.global)
+ add_symbol_to_list (sym, &global_symbols);
+ else if (WITHIN_FUNCTION (objfile))
+ add_symbol_to_list (sym, &local_symbols);
+ else
+ add_symbol_to_list (sym, &file_symbols);
+ break;
+
+ case DNTT_TYPE_TAGDEF:
+ {
+ int global = dn_bufp->dtag.global;
+ /* Structure, union, enum, template, or class tag definition */
+ /* We do want to process these, since a name is
+ * added to the namespace for the tag name (and if C++ class,
+ * for the typename also).
+ */
+ SYMBOL_NAMESPACE (sym) = STRUCT_NAMESPACE;
+
+ /* The tag contains in its "type" field a pointer to the
+ * DNTT_TYPE_STRUCT, DNTT_TYPE_UNION, DNTT_TYPE_ENUM,
+ * DNTT_TYPE_CLASS or DNTT_TYPE_TEMPLATE
+ * record that actually defines the type.
+ */
+ SYMBOL_TYPE (sym) = hpread_type_lookup (dn_bufp->dtype.type, objfile);
+ TYPE_NAME (sym->type) = SYMBOL_NAME (sym);
+ TYPE_TAG_NAME (sym->type) = SYMBOL_NAME (sym);
+ if (dn_bufp->dtag.global)
+ add_symbol_to_list (sym, &global_symbols);
+ else if (WITHIN_FUNCTION (objfile))
+ add_symbol_to_list (sym, &local_symbols);
+ else
+ add_symbol_to_list (sym, &file_symbols);
+
+ /* If this is a C++ class, then we additionally
+ * need to define a typedef for the
+ * class type. E.g., so that the name "c" becomes visible as
+ * a type name when the user says "class c { ... }".
+ * In order to figure this out, we need to chase down the "type"
+ * field to get to the DNTT_TYPE_CLASS record.
+ *
+ * We also add the typename for ENUM. Though this isn't
+ * strictly correct, it is necessary because of the debug info
+ * generated by the aCC compiler, in which we cannot
+ * distinguish between:
+ * enum e { ... };
+ * and
+ * typedef enum { ... } e;
+ * I.e., the compiler emits the same debug info for the above
+ * two cases, in both cases "e" appearing as a tagdef.
+ * Therefore go ahead and generate the typename so that
+ * "ptype e" will work in the above cases.
+ *
+ * We also add the typename for TEMPLATE, so as to allow "ptype t"
+ * when "t" is a template name.
+ */
+ if (dn_bufp->dtype.type.dnttp.index < LNTT_SYMCOUNT (objfile))
+ dn_bufp = hpread_get_lntt (dn_bufp->dtag.type.dnttp.index, objfile);
+ else {
+ complain (&hpread_tagdef_complaint);
+ return;
+ }
+ if (dn_bufp->dblock.kind == DNTT_TYPE_CLASS ||
+ dn_bufp->dblock.kind == DNTT_TYPE_ENUM ||
+ dn_bufp->dblock.kind == DNTT_TYPE_TEMPLATE) {
+ struct symbol *newsym;
+
+ newsym = (struct symbol *) obstack_alloc (&objfile->symbol_obstack,
+ sizeof (struct symbol));
+ memset (newsym, 0, sizeof (struct symbol));
+ SYMBOL_NAME (newsym) = name;
+ SYMBOL_LANGUAGE (newsym) = language_auto;
+ SYMBOL_NAMESPACE (newsym) = VAR_NAMESPACE;
+ SYMBOL_LINE (newsym) = 0;
+ SYMBOL_VALUE (newsym) = 0;
+ SYMBOL_CLASS (newsym) = LOC_TYPEDEF;
+ SYMBOL_TYPE (newsym) = sym->type;
+ if (global)
+ add_symbol_to_list (newsym, &global_symbols);
+ else if (WITHIN_FUNCTION (objfile))
+ add_symbol_to_list (newsym, &local_symbols);
+ else
+ add_symbol_to_list (newsym, &file_symbols);
+ }
+ }
+ break;
+
+ case DNTT_TYPE_POINTER:
+ /* Declares a pointer type. Should not be necessary to do anything
+ * with the type at this level; these are processed
+ * at the hpread_type_lookup() level.
+ */
+ break;
+
+ case DNTT_TYPE_ENUM:
+ /* Declares an enum type. Should not be necessary to do anything
+ * with the type at this level; these are processed
+ * at the hpread_type_lookup() level.
+ */
+ break;
+
+ case DNTT_TYPE_MEMENUM:
+ /* Member of enum */
+ /* Ignored at this level, but hpread_read_enum_type() will take
+ * care of walking the list of enumeration members.
+ */
+ break;
+
+ case DNTT_TYPE_SET:
+ /* Declares a set type. Should not be necessary to do anything
+ * with the type at this level; these are processed
+ * at the hpread_type_lookup() level.
+ */
+ break;
+
+ case DNTT_TYPE_SUBRANGE:
+ /* Declares a subrange type. Should not be necessary to do anything
+ * with the type at this level; these are processed
+ * at the hpread_type_lookup() level.
+ */
+ break;
+
+ case DNTT_TYPE_ARRAY:
+ /* Declares an array type. Should not be necessary to do anything
+ * with the type at this level; these are processed
+ * at the hpread_type_lookup() level.
+ */
+ break;
+
+ case DNTT_TYPE_STRUCT:
+ case DNTT_TYPE_UNION:
+ /* Declares an struct/union type.
+ * Should not be necessary to do anything
+ * with the type at this level; these are processed
+ * at the hpread_type_lookup() level.
+ */
+ break;
+
+ case DNTT_TYPE_FIELD:
+ /* Structure/union/class field */
+ /* Ignored at this level, but hpread_read_struct_type() will take
+ * care of walking the list of structure/union/class members.
+ */
+ break;
+
+ /* DNTT_TYPE_VARIANT is not handled by GDB */
+
+ /* DNTT_TYPE_FILE is not handled by GDB */
+
+ case DNTT_TYPE_FUNCTYPE:
+ /* Function type */
+ /* Ignored at this level, handled within hpread_type_lookup() */
+ break;
+
+ case DNTT_TYPE_WITH:
+ /* This is emitted within methods to indicate "with <class>"
+ * scoping rules (i.e., indicate that the class data members
+ * are directly visible).
+ * However, since GDB already infers this by looking at the
+ * "this" argument, interpreting the DNTT_TYPE_WITH
+ * symbol record is unnecessary.
+ */
+ break;
+
+ case DNTT_TYPE_COMMON:
+ /* FORTRAN common. Not yet handled. */
+ complain (&hpread_unhandled_common_complaint);
+ break;
+
+ /* DNTT_TYPE_COBSTRUCT is not handled by GDB. */
+ /* DNTT_TYPE_XREF is not handled by GDB. */
+ /* DNTT_TYPE_SA is not handled by GDB. */
+ /* DNTT_TYPE_MACRO is not handled by GDB */
+
+ case DNTT_TYPE_BLOCKDATA:
+ /* Not sure what this is - part of FORTRAN support maybe?
+ * Anyway, not yet handled.
+ */
+ complain (&hpread_unhandled_blockdata_complaint);
+ break;
+
+ case DNTT_TYPE_CLASS_SCOPE:
+
+
+
+ /* The compiler brackets member functions with a CLASS_SCOPE/END
+ * pair of records, presumably to put them in a different scope
+ * from the module scope where they are normally defined.
+ * E.g., in the situation:
+ * void f() { ... }
+ * void c::f() { ...}
+ * The member function "c::f" will be bracketed by a CLASS_SCOPE/END.
+ * This causes "break f" at the module level to pick the
+ * the file-level function f(), not the member function
+ * (which needs to be referenced via "break c::f").
+ *
+ * Here we record the class name to generate the demangled names of
+ * member functions later.
+ *
+ * FIXME Not being used now for anything -- cplus_demangle seems
+ * enough for getting the class-qualified names of functions. We
+ * may need this for handling nested classes and types. */
+
+ /* pai: FIXME Not handling nested classes for now -- need to
+ * maintain a stack */
+
+ dn_temp = hpread_get_lntt (dn_bufp->dclass_scope.type.dnttp.index, objfile);
+ if (dn_temp->dblock.kind == DNTT_TYPE_TAGDEF)
+ class_scope_name = VT (objfile) + dn_temp->dtag.name;
+ else
+ class_scope_name = NULL;
+
+#if 0
+
+ /* Begin a new scope. */
+ SL_INDEX (objfile) = hpread_record_lines (current_subfile,
+ SL_INDEX (objfile),
+ dn_bufp->dclass_scope.address,
+ objfile, offset);
+ valu = hpread_get_location (dn_bufp->dclass_scope.address, objfile);
+ valu += offset; /* Relocate for dynamic loading */
+ desc = hpread_get_scope_start (dn_bufp->dclass_scope.address, objfile);
+ /* We use the scope start DNTT index as the nesting depth identifier! */
+ new = push_context (desc, valu);
+#endif
+ break;
+
+ case DNTT_TYPE_REFERENCE:
+ /* Declares a C++ reference type. Should not be necessary to do anything
+ * with the type at this level; these are processed
+ * at the hpread_type_lookup() level.
+ */
+ break;
+
+ case DNTT_TYPE_PTRMEM:
+ /* Declares a C++ pointer-to-data-member type. This does not
+ * need to be handled at this level; being a type description it
+ * is instead handled at the hpread_type_lookup() level.
+ */
+ break;
+
+ case DNTT_TYPE_PTRMEMFUNC:
+ /* Declares a C++ pointer-to-function-member type. This does not
+ * need to be handled at this level; being a type description it
+ * is instead handled at the hpread_type_lookup() level.
+ */
+ break;
+
+ case DNTT_TYPE_CLASS:
+ /* Declares a class type.
+ * Should not be necessary to do anything
+ * with the type at this level; these are processed
+ * at the hpread_type_lookup() level.
+ */
+ break;
+
+ case DNTT_TYPE_GENFIELD:
+ /* I believe this is used for class member functions */
+ /* Ignored at this level, but hpread_read_struct_type() will take
+ * care of walking the list of class members.
+ */
+ break;
+
+ case DNTT_TYPE_VFUNC:
+ /* Virtual function */
+ /* This does not have to be handled at this level; handled in
+ * the course of processing class symbols.
+ */
+ break;
+
+ case DNTT_TYPE_MEMACCESS:
+ /* DDE ignores this symbol table record.
+ * It has something to do with "modified access" to class members.
+ * I'll assume we can safely ignore it too.
+ */
+ break;
+
+ case DNTT_TYPE_INHERITANCE:
+ /* These don't have to be handled here, since they are handled
+ * within hpread_read_struct_type() in the process of constructing
+ * a class type.
+ */
+ break;
+
+ case DNTT_TYPE_FRIEND_CLASS:
+ case DNTT_TYPE_FRIEND_FUNC:
+ /* These can safely be ignored, as GDB doesn't need this
+ * info. DDE only uses it in "describe". We may later want
+ * to extend GDB's "ptype" to give this info, but for now
+ * it seems safe enough to ignore it.
+ */
+ break;
+
+ case DNTT_TYPE_MODIFIER:
+ /* Intended to supply "modified access" to a type */
+ /* From the way DDE handles this, it looks like it always
+ * modifies a type. Therefore it is safe to ignore it at this
+ * level, and handle it in hpread_type_lookup().
+ */
+ break;
+
+ case DNTT_TYPE_OBJECT_ID:
+ /* Just ignore this - that's all DDE does */
+ break;
+
+ case DNTT_TYPE_MEMFUNC:
+ /* Member function */
+ /* This does not have to be handled at this level; handled in
+ * the course of processing class symbols.
+ */
+ break;
+
+ case DNTT_TYPE_DOC_MEMFUNC:
+ /* Member function */
+ /* This does not have to be handled at this level; handled in
+ * the course of processing class symbols.
+ */
+ break;
+
+ case DNTT_TYPE_TEMPLATE:
+ /* Template - sort of the header for a template definition,
+ * which like a class, points to a member list and also points
+ * to a TEMPLATE_ARG list of type-arguments.
+ * We do not need to process TEMPLATE records at this level though.
+ */
+ break;
+
+ case DNTT_TYPE_TEMPLATE_ARG:
+ /* The TEMPLATE record points to an argument list of
+ * TEMPLATE_ARG records, each of which describes one
+ * of the type-arguments.
+ * We do not need to process TEMPLATE_ARG records at this level though.
+ */
+ break;
+
+ case DNTT_TYPE_FUNC_TEMPLATE:
+ /* This will get emitted for member functions of templates.
+ * But we don't need to process this record at this level though,
+ * we will process it in the course of processing a TEMPLATE
+ * record.
+ */
+ break;
+
+ case DNTT_TYPE_LINK:
+ /* The LINK record is used to link up templates with instantiations. */
+ /* It is not clear why this is needed, and furthermore aCC does
+ * not appear to generate this, so I think we can safely ignore it. - RT
+ */
+ break;
+
+ /* DNTT_TYPE_DYN_ARRAY_DESC is not handled by GDB */
+ /* DNTT_TYPE_DESC_SUBRANGE is not handled by GDB */
+ /* DNTT_TYPE_BEGIN_EXT is not handled by GDB */
+ /* DNTT_TYPE_INLN is not handled by GDB */
+ /* DNTT_TYPE_INLN_LIST is not handled by GDB */
+ /* DNTT_TYPE_ALIAS is not handled by GDB */
+
+ default:
+ break;
+ }
+}
+
+/* Get nesting depth for a DNTT entry.
+ * DN_BUFP points to a DNTT entry.
+ * OBJFILE is the object file.
+ * REPORT_NESTED is a flag; if 0, real nesting depth is
+ * reported, if it is 1, the function simply returns a
+ * non-zero value if the nesting depth is anything > 0.
+ *
+ * Return value is an integer. 0 => not a local type / name
+ * positive return => type or name is local to some
+ * block or function.
+ */
+
+
+/* elz: ATTENTION: FIXME: NOTE: WARNING!!!!
+ this function now returns 0 right away. It was taking too much time
+ at start up. Now, though, the local types are not handled correctly.
+*/
+
+
+static int
+hpread_get_scope_depth (dn_bufp, objfile, report_nested)
+ union dnttentry * dn_bufp;
+ struct objfile * objfile;
+ int report_nested;
+{
+ register int index;
+ register union dnttentry * dn_tmp;
+ register short depth = 0;
+/****************************/
+ return 0;
+/****************************/
+
+ index = (((char *) dn_bufp) - LNTT (objfile)) / (sizeof (struct dntt_type_block));
+
+ while (--index >= 0)
+ {
+ dn_tmp = hpread_get_lntt (index, objfile);
+ switch (dn_tmp->dblock.kind)
+ {
+ case DNTT_TYPE_MODULE:
+ return depth;
+ case DNTT_TYPE_END:
+ /* index is signed int; dnttp.index is 29-bit unsigned int! */
+ index = (int) dn_tmp->dend.beginscope.dnttp.index;
+ break;
+ case DNTT_TYPE_BEGIN:
+ case DNTT_TYPE_FUNCTION:
+ case DNTT_TYPE_DOC_FUNCTION:
+ case DNTT_TYPE_WITH:
+ case DNTT_TYPE_COMMON:
+ case DNTT_TYPE_CLASS_SCOPE:
+ depth++;
+ if (report_nested)
+ return 1;
+ break;
+ default:
+ break;
+ }
+ }
+ return depth;
+}
+
+/* Adjust the bitoffsets for all fields of an anonymous union of
+ type TYPE by negative BITS. This handles HP aCC's hideous habit
+ of giving members of anonymous unions bit offsets relative to the
+ enclosing structure instead of relative to the union itself. */
+
+static void
+hpread_adjust_bitoffsets (type, bits)
+ struct type * type;
+ int bits;
+{
+ register int i;
+
+ /* This is done only for unions; caller had better check that
+ it is an anonymous one. */
+ if (TYPE_CODE (type) != TYPE_CODE_UNION)
+ return;
+
+ /* Adjust each field; since this is a union, there are no base
+ classes. Also no static membes. Also, no need for recursion as
+ the members of this union if themeselves structs or unions, have
+ the correct bitoffsets; if an anonymous union is a member of this
+ anonymous union, the code in hpread_read_struct_type() will
+ adjust for that. */
+
+ for (i = 0; i < TYPE_NFIELDS (type); i++)
+ TYPE_FIELD_BITPOS (type, i) -= bits;
+}
+
+/* Because of quirks in HP compilers' treatment of anonymous unions inside
+ classes, we have to chase through a chain of threaded FIELD entries.
+ If we encounter an anonymous union in the chain, we must recursively skip over
+ that too.
+
+ This function does a "next" in the chain of FIELD entries, but transparently
+ skips over anonymous unions' fields (recursively).
+
+ Inputs are the number of times to do "next" at the top level, the dnttpointer
+ (FIELD) and entry pointer (FIELDP) for the dntt record corresponding to it,
+ and the ubiquitous objfile parameter. (Note: FIELDP is a **.) Return value
+ is a dnttpointer for the new field after all the skipped ones */
+
+static dnttpointer
+hpread_get_next_skip_over_anon_unions (skip_fields, field, fieldp, objfile)
+ int skip_fields;
+ dnttpointer field;
+ union dnttentry ** fieldp;
+ struct objfile * objfile;
+{
+ struct type * anon_type;
+ register int i;
+ int bitoffset;
+ char * name;
+
+ for (i=0; i < skip_fields; i++)
+ {
+ /* Get type of item we're looking at now; recursively processes the types
+ of these intermediate items we skip over, so they aren't lost. */
+ anon_type = hpread_type_lookup ((*fieldp)->dfield.type, objfile);
+ anon_type = CHECK_TYPEDEF (anon_type);
+ bitoffset = (*fieldp)->dfield.bitoffset;
+ name = VT (objfile) + (*fieldp)->dfield.name;
+ /* First skip over one item to avoid stack death on recursion */
+ field = (*fieldp)->dfield.nextfield;
+ *fieldp = hpread_get_lntt (field.dnttp.index, objfile);
+ /* Do we have another anonymous union? If so, adjust the bitoffsets
+ of its members and skip over its members. */
+ if ((TYPE_CODE (anon_type) == TYPE_CODE_UNION) &&
+ (!name || STREQ (name, "")))
+ {
+ hpread_adjust_bitoffsets (anon_type, bitoffset);
+ field = hpread_get_next_skip_over_anon_unions (TYPE_NFIELDS (anon_type), field, fieldp, objfile);
+ }
+ }
+ return field;
+}
+
+
diff --git a/gdb/hp300ux-nat.c b/gdb/hp300ux-nat.c
new file mode 100644
index 00000000000..38f68e1bdb7
--- /dev/null
+++ b/gdb/hp300ux-nat.c
@@ -0,0 +1,221 @@
+/* HP/UX native interface for HP 300's, for GDB when running under 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "frame.h"
+#include "inferior.h"
+
+/* Defining this means some system include files define some extra stuff. */
+#define WOPR
+#include <sys/param.h>
+#include <signal.h>
+#include <sys/user.h>
+#include <fcntl.h>
+
+#include <sys/ptrace.h>
+#include <sys/reg.h>
+#include <sys/trap.h>
+
+#include <sys/file.h>
+
+static void
+fetch_inferior_register PARAMS ((int, unsigned int));
+
+static void
+store_inferior_register_1 PARAMS ((int, unsigned int, int));
+
+static void
+store_inferior_register PARAMS ((int, unsigned int));
+
+/* Get kernel_u_addr using HPUX-style nlist(). */
+CORE_ADDR kernel_u_addr;
+
+struct hpnlist {
+ char * n_name;
+ long n_value;
+ unsigned char n_type;
+ unsigned char n_length;
+ short n_almod;
+ short n_unused;
+};
+static struct hpnlist nl[] = {{ "_u", -1, }, { (char *) 0, }};
+
+/* read the value of the u area from the hp-ux kernel */
+void
+_initialize_hp300ux_nat ()
+{
+#ifndef HPUX_VERSION_5
+ nlist ("/hp-ux", nl);
+ kernel_u_addr = nl[0].n_value;
+#else /* HPUX version 5. */
+ kernel_u_addr = (CORE_ADDR) 0x0097900;
+#endif
+}
+
+#define INFERIOR_AR0(u) \
+ ((ptrace \
+ (PT_RUAREA, inferior_pid, \
+ (PTRACE_ARG3_TYPE) ((char *) &u.u_ar0 - (char *) &u), 0, 0)) \
+ - kernel_u_addr)
+
+static void
+fetch_inferior_register (regno, regaddr)
+ register int regno;
+ register unsigned int regaddr;
+{
+#ifndef HPUX_VERSION_5
+ if (regno == PS_REGNUM)
+ {
+ union { int i; short s[2]; } ps_val;
+ int regval;
+
+ ps_val.i = (ptrace (PT_RUAREA, inferior_pid, (PTRACE_ARG3_TYPE) regaddr,
+ 0, 0));
+ regval = ps_val.s[0];
+ supply_register (regno, (char *)&regval);
+ }
+ else
+#endif /* not HPUX_VERSION_5 */
+ {
+ char buf[MAX_REGISTER_RAW_SIZE];
+ register int i;
+
+ for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (int))
+ {
+ *(int *) &buf[i] = ptrace (PT_RUAREA, inferior_pid,
+ (PTRACE_ARG3_TYPE) regaddr, 0, 0);
+ regaddr += sizeof (int);
+ }
+ supply_register (regno, buf);
+ }
+ return;
+}
+
+static void
+store_inferior_register_1 (regno, regaddr, val)
+ int regno;
+ unsigned int regaddr;
+ int val;
+{
+ errno = 0;
+ ptrace (PT_WUAREA, inferior_pid, (PTRACE_ARG3_TYPE) regaddr, val, 0);
+#if 0
+ /* HP-UX randomly sets errno to non-zero for regno == 25.
+ However, the value is correctly written, so ignore errno. */
+ if (errno != 0)
+ {
+ char string_buf[64];
+
+ sprintf (string_buf, "writing register number %d", regno);
+ perror_with_name (string_buf);
+ }
+#endif
+ return;
+}
+
+static void
+store_inferior_register (regno, regaddr)
+ register int regno;
+ register unsigned int regaddr;
+{
+#ifndef HPUX_VERSION_5
+ if (regno == PS_REGNUM)
+ {
+ union { int i; short s[2]; } ps_val;
+
+ ps_val.i = (ptrace (PT_RUAREA, inferior_pid, (PTRACE_ARG3_TYPE) regaddr,
+ 0, 0));
+ ps_val.s[0] = (read_register (regno));
+ store_inferior_register_1 (regno, regaddr, ps_val.i);
+ }
+ else
+#endif /* not HPUX_VERSION_5 */
+ {
+ register int i;
+ extern char registers[];
+
+ for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (int))
+ {
+ store_inferior_register_1
+ (regno, regaddr,
+ (*(int *) &registers[(REGISTER_BYTE (regno)) + i]));
+ regaddr += sizeof (int);
+ }
+ }
+ return;
+}
+
+void
+fetch_inferior_registers (regno)
+ int regno;
+{
+ struct user u;
+ register unsigned int ar0_offset;
+
+ ar0_offset = (INFERIOR_AR0 (u));
+ if (regno == -1)
+ {
+ for (regno = 0; (regno < FP0_REGNUM); regno++)
+ fetch_inferior_register (regno, (REGISTER_ADDR (ar0_offset, regno)));
+ for (; (regno < NUM_REGS); regno++)
+ fetch_inferior_register (regno, (FP_REGISTER_ADDR (u, regno)));
+ }
+ else
+ fetch_inferior_register (regno,
+ (regno < FP0_REGNUM
+ ? REGISTER_ADDR (ar0_offset, regno)
+ : FP_REGISTER_ADDR (u, regno)));
+}
+
+/* Store our register values back into the inferior.
+ If REGNO is -1, do this for all registers.
+ Otherwise, REGNO specifies which register (so we can save time). */
+
+void
+store_inferior_registers (regno)
+ register int regno;
+{
+ struct user u;
+ register unsigned int ar0_offset;
+
+ if (regno >= FP0_REGNUM)
+ {
+ store_inferior_register (regno, (FP_REGISTER_ADDR (u, regno)));
+ return;
+ }
+
+ ar0_offset = (INFERIOR_AR0 (u));
+ if (regno >= 0)
+ {
+ store_inferior_register (regno, (REGISTER_ADDR (ar0_offset, regno)));
+ return;
+ }
+
+ for (regno = 0; (regno < FP0_REGNUM); regno++)
+ store_inferior_register (regno, (REGISTER_ADDR (ar0_offset, regno)));
+ for (; (regno < NUM_REGS); regno++)
+ store_inferior_register (regno, (FP_REGISTER_ADDR (u, regno)));
+ return;
+}
+
+int
+getpagesize ()
+{
+ return 4096;
+}
diff --git a/gdb/hppa-tdep.c b/gdb/hppa-tdep.c
new file mode 100644
index 00000000000..d9117508112
--- /dev/null
+++ b/gdb/hppa-tdep.c
@@ -0,0 +1,4445 @@
+/* Target-dependent code for the HP PA architecture, for GDB.
+ Copyright 1986, 87, 89, 90, 91, 92, 93, 94, 95, 96, 1999
+ Free Software Foundation, Inc.
+
+ Contributed by the Center for Software Science at the
+ University of Utah (pa-gdb-bugs@cs.utah.edu).
+
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "frame.h"
+#include "bfd.h"
+#include "inferior.h"
+#include "value.h"
+
+/* For argument passing to the inferior */
+#include "symtab.h"
+
+#ifdef USG
+#include <sys/types.h>
+#endif
+
+#include <dl.h>
+#include <sys/param.h>
+#include <signal.h>
+
+#include <sys/ptrace.h>
+#include <machine/save_state.h>
+
+#ifdef COFF_ENCAPSULATE
+#include "a.out.encap.h"
+#else
+#endif
+
+/*#include <sys/user.h> After a.out.h */
+#include <sys/file.h>
+#include "gdb_stat.h"
+#include "wait.h"
+
+#include "gdbcore.h"
+#include "gdbcmd.h"
+#include "target.h"
+#include "symfile.h"
+#include "objfiles.h"
+
+/* To support asking "What CPU is this?" */
+#include <unistd.h>
+
+/* To support detection of the pseudo-initial frame
+ that threads have. */
+#define THREAD_INITIAL_FRAME_SYMBOL "__pthread_exit"
+#define THREAD_INITIAL_FRAME_SYM_LEN sizeof(THREAD_INITIAL_FRAME_SYMBOL)
+
+static int extract_5_load PARAMS ((unsigned int));
+
+static unsigned extract_5R_store PARAMS ((unsigned int));
+
+static unsigned extract_5r_store PARAMS ((unsigned int));
+
+static void find_dummy_frame_regs PARAMS ((struct frame_info *,
+ struct frame_saved_regs *));
+
+static int find_proc_framesize PARAMS ((CORE_ADDR));
+
+static int find_return_regnum PARAMS ((CORE_ADDR));
+
+struct unwind_table_entry *find_unwind_entry PARAMS ((CORE_ADDR));
+
+static int extract_17 PARAMS ((unsigned int));
+
+static unsigned deposit_21 PARAMS ((unsigned int, unsigned int));
+
+static int extract_21 PARAMS ((unsigned));
+
+static unsigned deposit_14 PARAMS ((int, unsigned int));
+
+static int extract_14 PARAMS ((unsigned));
+
+static void unwind_command PARAMS ((char *, int));
+
+static int low_sign_extend PARAMS ((unsigned int, unsigned int));
+
+static int sign_extend PARAMS ((unsigned int, unsigned int));
+
+static int restore_pc_queue PARAMS ((struct frame_saved_regs *));
+
+static int hppa_alignof PARAMS ((struct type *));
+
+/* To support multi-threading and stepping. */
+int hppa_prepare_to_proceed PARAMS (());
+
+static int prologue_inst_adjust_sp PARAMS ((unsigned long));
+
+static int is_branch PARAMS ((unsigned long));
+
+static int inst_saves_gr PARAMS ((unsigned long));
+
+static int inst_saves_fr PARAMS ((unsigned long));
+
+static int pc_in_interrupt_handler PARAMS ((CORE_ADDR));
+
+static int pc_in_linker_stub PARAMS ((CORE_ADDR));
+
+static int compare_unwind_entries PARAMS ((const void *, const void *));
+
+static void read_unwind_info PARAMS ((struct objfile *));
+
+static void internalize_unwinds PARAMS ((struct objfile *,
+ struct unwind_table_entry *,
+ asection *, unsigned int,
+ unsigned int, CORE_ADDR));
+static void pa_print_registers PARAMS ((char *, int, int));
+static void pa_strcat_registers PARAMS ((char *, int, int, GDB_FILE *));
+static void pa_register_look_aside PARAMS ((char *, int, long *));
+static void pa_print_fp_reg PARAMS ((int));
+static void pa_strcat_fp_reg PARAMS ((int, GDB_FILE *, enum precision_type));
+
+typedef struct {
+ struct minimal_symbol * msym;
+ CORE_ADDR solib_handle;
+} args_for_find_stub;
+
+static CORE_ADDR cover_find_stub_with_shl_get PARAMS ((args_for_find_stub *));
+
+static int is_pa_2 = 0; /* False */
+
+/* This is declared in symtab.c; set to 1 in hp-symtab-read.c */
+extern int hp_som_som_object_present;
+
+/* In breakpoint.c */
+extern int exception_catchpoints_are_fragile;
+
+/* This is defined in valops.c. */
+extern value_ptr
+find_function_in_inferior PARAMS((char *));
+
+/* Should call_function allocate stack space for a struct return? */
+int
+hppa_use_struct_convention (gcc_p, type)
+ int gcc_p;
+ struct type *type;
+{
+ return (TYPE_LENGTH (type) > 8);
+}
+
+
+/* Routines to extract various sized constants out of hppa
+ instructions. */
+
+/* This assumes that no garbage lies outside of the lower bits of
+ value. */
+
+static int
+sign_extend (val, bits)
+ unsigned val, bits;
+{
+ return (int)(val >> (bits - 1) ? (-1 << bits) | val : val);
+}
+
+/* For many immediate values the sign bit is the low bit! */
+
+static int
+low_sign_extend (val, bits)
+ unsigned val, bits;
+{
+ return (int)((val & 0x1 ? (-1 << (bits - 1)) : 0) | val >> 1);
+}
+
+/* extract the immediate field from a ld{bhw}s instruction */
+
+#if 0
+
+unsigned
+get_field (val, from, to)
+ unsigned val, from, to;
+{
+ val = val >> 31 - to;
+ return val & ((1 << 32 - from) - 1);
+}
+
+unsigned
+set_field (val, from, to, new_val)
+ unsigned *val, from, to;
+{
+ unsigned mask = ~((1 << (to - from + 1)) << (31 - from));
+ return *val = *val & mask | (new_val << (31 - from));
+}
+
+/* extract a 3-bit space register number from a be, ble, mtsp or mfsp */
+
+int
+extract_3 (word)
+ unsigned word;
+{
+ return GET_FIELD (word, 18, 18) << 2 | GET_FIELD (word, 16, 17);
+}
+
+#endif
+
+static int
+extract_5_load (word)
+ unsigned word;
+{
+ return low_sign_extend (word >> 16 & MASK_5, 5);
+}
+
+#if 0
+
+/* extract the immediate field from a st{bhw}s instruction */
+
+int
+extract_5_store (word)
+ unsigned word;
+{
+ return low_sign_extend (word & MASK_5, 5);
+}
+
+#endif /* 0 */
+
+/* extract the immediate field from a break instruction */
+
+static unsigned
+extract_5r_store (word)
+ unsigned word;
+{
+ return (word & MASK_5);
+}
+
+/* extract the immediate field from a {sr}sm instruction */
+
+static unsigned
+extract_5R_store (word)
+ unsigned word;
+{
+ return (word >> 16 & MASK_5);
+}
+
+/* extract an 11 bit immediate field */
+
+#if 0
+
+int
+extract_11 (word)
+ unsigned word;
+{
+ return low_sign_extend (word & MASK_11, 11);
+}
+
+#endif
+
+/* extract a 14 bit immediate field */
+
+static int
+extract_14 (word)
+ unsigned word;
+{
+ return low_sign_extend (word & MASK_14, 14);
+}
+
+/* deposit a 14 bit constant in a word */
+
+static unsigned
+deposit_14 (opnd, word)
+ int opnd;
+ unsigned word;
+{
+ unsigned sign = (opnd < 0 ? 1 : 0);
+
+ return word | ((unsigned)opnd << 1 & MASK_14) | sign;
+}
+
+/* extract a 21 bit constant */
+
+static int
+extract_21 (word)
+ unsigned word;
+{
+ int val;
+
+ word &= MASK_21;
+ word <<= 11;
+ val = GET_FIELD (word, 20, 20);
+ val <<= 11;
+ val |= GET_FIELD (word, 9, 19);
+ val <<= 2;
+ val |= GET_FIELD (word, 5, 6);
+ val <<= 5;
+ val |= GET_FIELD (word, 0, 4);
+ val <<= 2;
+ val |= GET_FIELD (word, 7, 8);
+ return sign_extend (val, 21) << 11;
+}
+
+/* deposit a 21 bit constant in a word. Although 21 bit constants are
+ usually the top 21 bits of a 32 bit constant, we assume that only
+ the low 21 bits of opnd are relevant */
+
+static unsigned
+deposit_21 (opnd, word)
+ unsigned opnd, word;
+{
+ unsigned val = 0;
+
+ val |= GET_FIELD (opnd, 11 + 14, 11 + 18);
+ val <<= 2;
+ val |= GET_FIELD (opnd, 11 + 12, 11 + 13);
+ val <<= 2;
+ val |= GET_FIELD (opnd, 11 + 19, 11 + 20);
+ val <<= 11;
+ val |= GET_FIELD (opnd, 11 + 1, 11 + 11);
+ val <<= 1;
+ val |= GET_FIELD (opnd, 11 + 0, 11 + 0);
+ return word | val;
+}
+
+/* extract a 12 bit constant from branch instructions */
+
+#if 0
+
+int
+extract_12 (word)
+ unsigned word;
+{
+ return sign_extend (GET_FIELD (word, 19, 28) |
+ GET_FIELD (word, 29, 29) << 10 |
+ (word & 0x1) << 11, 12) << 2;
+}
+
+/* Deposit a 17 bit constant in an instruction (like bl). */
+
+unsigned int
+deposit_17 (opnd, word)
+ unsigned opnd, word;
+{
+ word |= GET_FIELD (opnd, 15 + 0, 15 + 0); /* w */
+ word |= GET_FIELD (opnd, 15 + 1, 15 + 5) << 16; /* w1 */
+ word |= GET_FIELD (opnd, 15 + 6, 15 + 6) << 2; /* w2[10] */
+ word |= GET_FIELD (opnd, 15 + 7, 15 + 16) << 3; /* w2[0..9] */
+
+ return word;
+}
+
+#endif
+
+/* extract a 17 bit constant from branch instructions, returning the
+ 19 bit signed value. */
+
+static int
+extract_17 (word)
+ unsigned word;
+{
+ return sign_extend (GET_FIELD (word, 19, 28) |
+ GET_FIELD (word, 29, 29) << 10 |
+ GET_FIELD (word, 11, 15) << 11 |
+ (word & 0x1) << 16, 17) << 2;
+}
+
+
+/* Compare the start address for two unwind entries returning 1 if
+ the first address is larger than the second, -1 if the second is
+ larger than the first, and zero if they are equal. */
+
+static int
+compare_unwind_entries (arg1, arg2)
+ const void *arg1;
+ const void *arg2;
+{
+ const struct unwind_table_entry *a = arg1;
+ const struct unwind_table_entry *b = arg2;
+
+ if (a->region_start > b->region_start)
+ return 1;
+ else if (a->region_start < b->region_start)
+ return -1;
+ else
+ return 0;
+}
+
+static void
+internalize_unwinds (objfile, table, section, entries, size, text_offset)
+ struct objfile *objfile;
+ struct unwind_table_entry *table;
+ asection *section;
+ unsigned int entries, size;
+ CORE_ADDR text_offset;
+{
+ /* We will read the unwind entries into temporary memory, then
+ fill in the actual unwind table. */
+ if (size > 0)
+ {
+ unsigned long tmp;
+ unsigned i;
+ char *buf = alloca (size);
+
+ bfd_get_section_contents (objfile->obfd, section, buf, 0, size);
+
+ /* Now internalize the information being careful to handle host/target
+ endian issues. */
+ for (i = 0; i < entries; i++)
+ {
+ table[i].region_start = bfd_get_32 (objfile->obfd,
+ (bfd_byte *)buf);
+ table[i].region_start += text_offset;
+ buf += 4;
+ table[i].region_end = bfd_get_32 (objfile->obfd, (bfd_byte *)buf);
+ table[i].region_end += text_offset;
+ buf += 4;
+ tmp = bfd_get_32 (objfile->obfd, (bfd_byte *)buf);
+ buf += 4;
+ table[i].Cannot_unwind = (tmp >> 31) & 0x1;
+ table[i].Millicode = (tmp >> 30) & 0x1;
+ table[i].Millicode_save_sr0 = (tmp >> 29) & 0x1;
+ table[i].Region_description = (tmp >> 27) & 0x3;
+ table[i].reserved1 = (tmp >> 26) & 0x1;
+ table[i].Entry_SR = (tmp >> 25) & 0x1;
+ table[i].Entry_FR = (tmp >> 21) & 0xf;
+ table[i].Entry_GR = (tmp >> 16) & 0x1f;
+ table[i].Args_stored = (tmp >> 15) & 0x1;
+ table[i].Variable_Frame = (tmp >> 14) & 0x1;
+ table[i].Separate_Package_Body = (tmp >> 13) & 0x1;
+ table[i].Frame_Extension_Millicode = (tmp >> 12) & 0x1;
+ table[i].Stack_Overflow_Check = (tmp >> 11) & 0x1;
+ table[i].Two_Instruction_SP_Increment = (tmp >> 10) & 0x1;
+ table[i].Ada_Region = (tmp >> 9) & 0x1;
+ table[i].cxx_info = (tmp >> 8) & 0x1;
+ table[i].cxx_try_catch = (tmp >> 7) & 0x1;
+ table[i].sched_entry_seq = (tmp >> 6) & 0x1;
+ table[i].reserved2 = (tmp >> 5) & 0x1;
+ table[i].Save_SP = (tmp >> 4) & 0x1;
+ table[i].Save_RP = (tmp >> 3) & 0x1;
+ table[i].Save_MRP_in_frame = (tmp >> 2) & 0x1;
+ table[i].extn_ptr_defined = (tmp >> 1) & 0x1;
+ table[i].Cleanup_defined = tmp & 0x1;
+ tmp = bfd_get_32 (objfile->obfd, (bfd_byte *)buf);
+ buf += 4;
+ table[i].MPE_XL_interrupt_marker = (tmp >> 31) & 0x1;
+ table[i].HP_UX_interrupt_marker = (tmp >> 30) & 0x1;
+ table[i].Large_frame = (tmp >> 29) & 0x1;
+ table[i].Pseudo_SP_Set = (tmp >> 28) & 0x1;
+ table[i].reserved4 = (tmp >> 27) & 0x1;
+ table[i].Total_frame_size = tmp & 0x7ffffff;
+
+ /* Stub unwinds are handled elsewhere. */
+ table[i].stub_unwind.stub_type = 0;
+ table[i].stub_unwind.padding = 0;
+ }
+ }
+}
+
+/* Read in the backtrace information stored in the `$UNWIND_START$' section of
+ the object file. This info is used mainly by find_unwind_entry() to find
+ out the stack frame size and frame pointer used by procedures. We put
+ everything on the psymbol obstack in the objfile so that it automatically
+ gets freed when the objfile is destroyed. */
+
+static void
+read_unwind_info (objfile)
+ struct objfile *objfile;
+{
+ asection *unwind_sec, *elf_unwind_sec, *stub_unwind_sec;
+ unsigned unwind_size, elf_unwind_size, stub_unwind_size, total_size;
+ unsigned index, unwind_entries, elf_unwind_entries;
+ unsigned stub_entries, total_entries;
+ CORE_ADDR text_offset;
+ struct obj_unwind_info *ui;
+ obj_private_data_t *obj_private;
+
+ text_offset = ANOFFSET (objfile->section_offsets, 0);
+ ui = (struct obj_unwind_info *)obstack_alloc (&objfile->psymbol_obstack,
+ sizeof (struct obj_unwind_info));
+
+ ui->table = NULL;
+ ui->cache = NULL;
+ ui->last = -1;
+
+ /* Get hooks to all unwind sections. Note there is no linker-stub unwind
+ section in ELF at the moment. */
+ unwind_sec = bfd_get_section_by_name (objfile->obfd, "$UNWIND_START$");
+ elf_unwind_sec = bfd_get_section_by_name (objfile->obfd, ".PARISC.unwind");
+ stub_unwind_sec = bfd_get_section_by_name (objfile->obfd, "$UNWIND_END$");
+
+ /* Get sizes and unwind counts for all sections. */
+ if (unwind_sec)
+ {
+ unwind_size = bfd_section_size (objfile->obfd, unwind_sec);
+ unwind_entries = unwind_size / UNWIND_ENTRY_SIZE;
+ }
+ else
+ {
+ unwind_size = 0;
+ unwind_entries = 0;
+ }
+
+ if (elf_unwind_sec)
+ {
+ elf_unwind_size = bfd_section_size (objfile->obfd, elf_unwind_sec); /* purecov: deadcode */
+ elf_unwind_entries = elf_unwind_size / UNWIND_ENTRY_SIZE; /* purecov: deadcode */
+ }
+ else
+ {
+ elf_unwind_size = 0;
+ elf_unwind_entries = 0;
+ }
+
+ if (stub_unwind_sec)
+ {
+ stub_unwind_size = bfd_section_size (objfile->obfd, stub_unwind_sec);
+ stub_entries = stub_unwind_size / STUB_UNWIND_ENTRY_SIZE;
+ }
+ else
+ {
+ stub_unwind_size = 0;
+ stub_entries = 0;
+ }
+
+ /* Compute total number of unwind entries and their total size. */
+ total_entries = unwind_entries + elf_unwind_entries + stub_entries;
+ total_size = total_entries * sizeof (struct unwind_table_entry);
+
+ /* Allocate memory for the unwind table. */
+ ui->table = (struct unwind_table_entry *)
+ obstack_alloc (&objfile->psymbol_obstack, total_size);
+ ui->last = total_entries - 1;
+
+ /* Internalize the standard unwind entries. */
+ index = 0;
+ internalize_unwinds (objfile, &ui->table[index], unwind_sec,
+ unwind_entries, unwind_size, text_offset);
+ index += unwind_entries;
+ internalize_unwinds (objfile, &ui->table[index], elf_unwind_sec,
+ elf_unwind_entries, elf_unwind_size, text_offset);
+ index += elf_unwind_entries;
+
+ /* Now internalize the stub unwind entries. */
+ if (stub_unwind_size > 0)
+ {
+ unsigned int i;
+ char *buf = alloca (stub_unwind_size);
+
+ /* Read in the stub unwind entries. */
+ bfd_get_section_contents (objfile->obfd, stub_unwind_sec, buf,
+ 0, stub_unwind_size);
+
+ /* Now convert them into regular unwind entries. */
+ for (i = 0; i < stub_entries; i++, index++)
+ {
+ /* Clear out the next unwind entry. */
+ memset (&ui->table[index], 0, sizeof (struct unwind_table_entry));
+
+ /* Convert offset & size into region_start and region_end.
+ Stuff away the stub type into "reserved" fields. */
+ ui->table[index].region_start = bfd_get_32 (objfile->obfd,
+ (bfd_byte *) buf);
+ ui->table[index].region_start += text_offset;
+ buf += 4;
+ ui->table[index].stub_unwind.stub_type = bfd_get_8 (objfile->obfd,
+ (bfd_byte *) buf);
+ buf += 2;
+ ui->table[index].region_end
+ = ui->table[index].region_start + 4 *
+ (bfd_get_16 (objfile->obfd, (bfd_byte *) buf) - 1);
+ buf += 2;
+ }
+
+ }
+
+ /* Unwind table needs to be kept sorted. */
+ qsort (ui->table, total_entries, sizeof (struct unwind_table_entry),
+ compare_unwind_entries);
+
+ /* Keep a pointer to the unwind information. */
+ if(objfile->obj_private == NULL)
+ {
+ obj_private = (obj_private_data_t *)
+ obstack_alloc(&objfile->psymbol_obstack,
+ sizeof(obj_private_data_t));
+ obj_private->unwind_info = NULL;
+ obj_private->so_info = NULL;
+
+ objfile->obj_private = (PTR) obj_private;
+ }
+ obj_private = (obj_private_data_t *)objfile->obj_private;
+ obj_private->unwind_info = ui;
+}
+
+/* Lookup the unwind (stack backtrace) info for the given PC. We search all
+ of the objfiles seeking the unwind table entry for this PC. Each objfile
+ contains a sorted list of struct unwind_table_entry. Since we do a binary
+ search of the unwind tables, we depend upon them to be sorted. */
+
+struct unwind_table_entry *
+find_unwind_entry(pc)
+ CORE_ADDR pc;
+{
+ int first, middle, last;
+ struct objfile *objfile;
+
+ /* A function at address 0? Not in HP-UX! */
+ if (pc == (CORE_ADDR) 0)
+ return NULL;
+
+ ALL_OBJFILES (objfile)
+ {
+ struct obj_unwind_info *ui;
+ ui = NULL;
+ if (objfile->obj_private)
+ ui = ((obj_private_data_t *)(objfile->obj_private))->unwind_info;
+
+ if (!ui)
+ {
+ read_unwind_info (objfile);
+ if (objfile->obj_private == NULL)
+ error ("Internal error reading unwind information."); /* purecov: deadcode */
+ ui = ((obj_private_data_t *)(objfile->obj_private))->unwind_info;
+ }
+
+ /* First, check the cache */
+
+ if (ui->cache
+ && pc >= ui->cache->region_start
+ && pc <= ui->cache->region_end)
+ return ui->cache;
+
+ /* Not in the cache, do a binary search */
+
+ first = 0;
+ last = ui->last;
+
+ while (first <= last)
+ {
+ middle = (first + last) / 2;
+ if (pc >= ui->table[middle].region_start
+ && pc <= ui->table[middle].region_end)
+ {
+ ui->cache = &ui->table[middle];
+ return &ui->table[middle];
+ }
+
+ if (pc < ui->table[middle].region_start)
+ last = middle - 1;
+ else
+ first = middle + 1;
+ }
+ } /* ALL_OBJFILES() */
+ return NULL;
+}
+
+/* Return the adjustment necessary to make for addresses on the stack
+ as presented by hpread.c.
+
+ This is necessary because of the stack direction on the PA and the
+ bizarre way in which someone (?) decided they wanted to handle
+ frame pointerless code in GDB. */
+int
+hpread_adjust_stack_address (func_addr)
+ CORE_ADDR func_addr;
+{
+ struct unwind_table_entry *u;
+
+ u = find_unwind_entry (func_addr);
+ if (!u)
+ return 0;
+ else
+ return u->Total_frame_size << 3;
+}
+
+/* Called to determine if PC is in an interrupt handler of some
+ kind. */
+
+static int
+pc_in_interrupt_handler (pc)
+ CORE_ADDR pc;
+{
+ struct unwind_table_entry *u;
+ struct minimal_symbol *msym_us;
+
+ u = find_unwind_entry (pc);
+ if (!u)
+ return 0;
+
+ /* Oh joys. HPUX sets the interrupt bit for _sigreturn even though
+ its frame isn't a pure interrupt frame. Deal with this. */
+ msym_us = lookup_minimal_symbol_by_pc (pc);
+
+ return u->HP_UX_interrupt_marker && !IN_SIGTRAMP (pc, SYMBOL_NAME (msym_us));
+}
+
+/* Called when no unwind descriptor was found for PC. Returns 1 if it
+ appears that PC is in a linker stub. */
+
+static int
+pc_in_linker_stub (pc)
+ CORE_ADDR pc;
+{
+ int found_magic_instruction = 0;
+ int i;
+ char buf[4];
+
+ /* If unable to read memory, assume pc is not in a linker stub. */
+ if (target_read_memory (pc, buf, 4) != 0)
+ return 0;
+
+ /* We are looking for something like
+
+ ; $$dyncall jams RP into this special spot in the frame (RP')
+ ; before calling the "call stub"
+ ldw -18(sp),rp
+
+ ldsid (rp),r1 ; Get space associated with RP into r1
+ mtsp r1,sp ; Move it into space register 0
+ be,n 0(sr0),rp) ; back to your regularly scheduled program */
+
+ /* Maximum known linker stub size is 4 instructions. Search forward
+ from the given PC, then backward. */
+ for (i = 0; i < 4; i++)
+ {
+ /* If we hit something with an unwind, stop searching this direction. */
+
+ if (find_unwind_entry (pc + i * 4) != 0)
+ break;
+
+ /* Check for ldsid (rp),r1 which is the magic instruction for a
+ return from a cross-space function call. */
+ if (read_memory_integer (pc + i * 4, 4) == 0x004010a1)
+ {
+ found_magic_instruction = 1;
+ break;
+ }
+ /* Add code to handle long call/branch and argument relocation stubs
+ here. */
+ }
+
+ if (found_magic_instruction != 0)
+ return 1;
+
+ /* Now look backward. */
+ for (i = 0; i < 4; i++)
+ {
+ /* If we hit something with an unwind, stop searching this direction. */
+
+ if (find_unwind_entry (pc - i * 4) != 0)
+ break;
+
+ /* Check for ldsid (rp),r1 which is the magic instruction for a
+ return from a cross-space function call. */
+ if (read_memory_integer (pc - i * 4, 4) == 0x004010a1)
+ {
+ found_magic_instruction = 1;
+ break;
+ }
+ /* Add code to handle long call/branch and argument relocation stubs
+ here. */
+ }
+ return found_magic_instruction;
+}
+
+static int
+find_return_regnum(pc)
+ CORE_ADDR pc;
+{
+ struct unwind_table_entry *u;
+
+ u = find_unwind_entry (pc);
+
+ if (!u)
+ return RP_REGNUM;
+
+ if (u->Millicode)
+ return 31;
+
+ return RP_REGNUM;
+}
+
+/* Return size of frame, or -1 if we should use a frame pointer. */
+static int
+find_proc_framesize (pc)
+ CORE_ADDR pc;
+{
+ struct unwind_table_entry *u;
+ struct minimal_symbol *msym_us;
+
+ /* This may indicate a bug in our callers... */
+ if (pc == (CORE_ADDR)0)
+ return -1;
+
+ u = find_unwind_entry (pc);
+
+ if (!u)
+ {
+ if (pc_in_linker_stub (pc))
+ /* Linker stubs have a zero size frame. */
+ return 0;
+ else
+ return -1;
+ }
+
+ msym_us = lookup_minimal_symbol_by_pc (pc);
+
+ /* If Save_SP is set, and we're not in an interrupt or signal caller,
+ then we have a frame pointer. Use it. */
+ if (u->Save_SP && !pc_in_interrupt_handler (pc)
+ && !IN_SIGTRAMP (pc, SYMBOL_NAME (msym_us)))
+ return -1;
+
+ return u->Total_frame_size << 3;
+}
+
+/* Return offset from sp at which rp is saved, or 0 if not saved. */
+static int rp_saved PARAMS ((CORE_ADDR));
+
+static int
+rp_saved (pc)
+ CORE_ADDR pc;
+{
+ struct unwind_table_entry *u;
+
+ /* A function at, and thus a return PC from, address 0? Not in HP-UX! */
+ if (pc == (CORE_ADDR) 0)
+ return 0;
+
+ u = find_unwind_entry (pc);
+
+ if (!u)
+ {
+ if (pc_in_linker_stub (pc))
+ /* This is the so-called RP'. */
+ return -24;
+ else
+ return 0;
+ }
+
+ if (u->Save_RP)
+ return -20;
+ else if (u->stub_unwind.stub_type != 0)
+ {
+ switch (u->stub_unwind.stub_type)
+ {
+ case EXPORT:
+ case IMPORT:
+ return -24;
+ case PARAMETER_RELOCATION:
+ return -8;
+ default:
+ return 0;
+ }
+ }
+ else
+ return 0;
+}
+
+int
+frameless_function_invocation (frame)
+ struct frame_info *frame;
+{
+ struct unwind_table_entry *u;
+
+ u = find_unwind_entry (frame->pc);
+
+ if (u == 0)
+ return 0;
+
+ return (u->Total_frame_size == 0 && u->stub_unwind.stub_type == 0);
+}
+
+CORE_ADDR
+saved_pc_after_call (frame)
+ struct frame_info *frame;
+{
+ int ret_regnum;
+ CORE_ADDR pc;
+ struct unwind_table_entry *u;
+
+ ret_regnum = find_return_regnum (get_frame_pc (frame));
+ pc = read_register (ret_regnum) & ~0x3;
+
+ /* If PC is in a linker stub, then we need to dig the address
+ the stub will return to out of the stack. */
+ u = find_unwind_entry (pc);
+ if (u && u->stub_unwind.stub_type != 0)
+ return FRAME_SAVED_PC (frame);
+ else
+ return pc;
+}
+
+CORE_ADDR
+hppa_frame_saved_pc (frame)
+ struct frame_info *frame;
+{
+ CORE_ADDR pc = get_frame_pc (frame);
+ struct unwind_table_entry *u;
+ CORE_ADDR old_pc;
+ int spun_around_loop = 0;
+ int rp_offset = 0;
+
+ /* BSD, HPUX & OSF1 all lay out the hardware state in the same manner
+ at the base of the frame in an interrupt handler. Registers within
+ are saved in the exact same order as GDB numbers registers. How
+ convienent. */
+ if (pc_in_interrupt_handler (pc))
+ return read_memory_integer (frame->frame + PC_REGNUM * 4, 4) & ~0x3;
+
+#ifdef FRAME_SAVED_PC_IN_SIGTRAMP
+ /* Deal with signal handler caller frames too. */
+ if (frame->signal_handler_caller)
+ {
+ CORE_ADDR rp;
+ FRAME_SAVED_PC_IN_SIGTRAMP (frame, &rp);
+ return rp & ~0x3;
+ }
+#endif
+
+ if (frameless_function_invocation (frame))
+ {
+ int ret_regnum;
+
+ ret_regnum = find_return_regnum (pc);
+
+ /* If the next frame is an interrupt frame or a signal
+ handler caller, then we need to look in the saved
+ register area to get the return pointer (the values
+ in the registers may not correspond to anything useful). */
+ if (frame->next
+ && (frame->next->signal_handler_caller
+ || pc_in_interrupt_handler (frame->next->pc)))
+ {
+ struct frame_saved_regs saved_regs;
+
+ get_frame_saved_regs (frame->next, &saved_regs);
+ if (read_memory_integer (saved_regs.regs[FLAGS_REGNUM], 4) & 0x2)
+ {
+ pc = read_memory_integer (saved_regs.regs[31], 4) & ~0x3;
+
+ /* Syscalls are really two frames. The syscall stub itself
+ with a return pointer in %rp and the kernel call with
+ a return pointer in %r31. We return the %rp variant
+ if %r31 is the same as frame->pc. */
+ if (pc == frame->pc)
+ pc = read_memory_integer (saved_regs.regs[RP_REGNUM], 4) & ~0x3;
+ }
+ else
+ pc = read_memory_integer (saved_regs.regs[RP_REGNUM], 4) & ~0x3;
+ }
+ else
+ pc = read_register (ret_regnum) & ~0x3;
+ }
+ else
+ {
+ spun_around_loop = 0;
+ old_pc = pc;
+
+restart:
+ rp_offset = rp_saved (pc);
+
+ /* Similar to code in frameless function case. If the next
+ frame is a signal or interrupt handler, then dig the right
+ information out of the saved register info. */
+ if (rp_offset == 0
+ && frame->next
+ && (frame->next->signal_handler_caller
+ || pc_in_interrupt_handler (frame->next->pc)))
+ {
+ struct frame_saved_regs saved_regs;
+
+ get_frame_saved_regs (frame->next, &saved_regs);
+ if (read_memory_integer (saved_regs.regs[FLAGS_REGNUM], 4) & 0x2)
+ {
+ pc = read_memory_integer (saved_regs.regs[31], 4) & ~0x3;
+
+ /* Syscalls are really two frames. The syscall stub itself
+ with a return pointer in %rp and the kernel call with
+ a return pointer in %r31. We return the %rp variant
+ if %r31 is the same as frame->pc. */
+ if (pc == frame->pc)
+ pc = read_memory_integer (saved_regs.regs[RP_REGNUM], 4) & ~0x3;
+ }
+ else
+ pc = read_memory_integer (saved_regs.regs[RP_REGNUM], 4) & ~0x3;
+ }
+ else if (rp_offset == 0)
+ {
+ old_pc = pc;
+ pc = read_register (RP_REGNUM) & ~0x3;
+ }
+ else
+ {
+ old_pc = pc;
+ pc = read_memory_integer (frame->frame + rp_offset, 4) & ~0x3;
+ }
+ }
+
+ /* If PC is inside a linker stub, then dig out the address the stub
+ will return to.
+
+ Don't do this for long branch stubs. Why? For some unknown reason
+ _start is marked as a long branch stub in hpux10. */
+ u = find_unwind_entry (pc);
+ if (u && u->stub_unwind.stub_type != 0
+ && u->stub_unwind.stub_type != LONG_BRANCH)
+ {
+ unsigned int insn;
+
+ /* If this is a dynamic executable, and we're in a signal handler,
+ then the call chain will eventually point us into the stub for
+ _sigreturn. Unlike most cases, we'll be pointed to the branch
+ to the real sigreturn rather than the code after the real branch!.
+
+ Else, try to dig the address the stub will return to in the normal
+ fashion. */
+ insn = read_memory_integer (pc, 4);
+ if ((insn & 0xfc00e000) == 0xe8000000)
+ return (pc + extract_17 (insn) + 8) & ~0x3;
+ else
+ {
+ if (old_pc == pc)
+ spun_around_loop++;
+
+ if (spun_around_loop > 1)
+ {
+ /* We're just about to go around the loop again with
+ no more hope of success. Die. */
+ error("Unable to find return pc for this frame");
+ }
+ else
+ goto restart;
+ }
+ }
+
+ return pc;
+}
+
+/* We need to correct the PC and the FP for the outermost frame when we are
+ in a system call. */
+
+void
+init_extra_frame_info (fromleaf, frame)
+ int fromleaf;
+ struct frame_info *frame;
+{
+ int flags;
+ int framesize;
+
+ if (frame->next && !fromleaf)
+ return;
+
+ /* If the next frame represents a frameless function invocation
+ then we have to do some adjustments that are normally done by
+ FRAME_CHAIN. (FRAME_CHAIN is not called in this case.) */
+ if (fromleaf)
+ {
+ /* Find the framesize of *this* frame without peeking at the PC
+ in the current frame structure (it isn't set yet). */
+ framesize = find_proc_framesize (FRAME_SAVED_PC (get_next_frame (frame)));
+
+ /* Now adjust our base frame accordingly. If we have a frame pointer
+ use it, else subtract the size of this frame from the current
+ frame. (we always want frame->frame to point at the lowest address
+ in the frame). */
+ if (framesize == -1)
+ frame->frame = TARGET_READ_FP ();
+ else
+ frame->frame -= framesize;
+ return;
+ }
+
+ flags = read_register (FLAGS_REGNUM);
+ if (flags & 2) /* In system call? */
+ frame->pc = read_register (31) & ~0x3;
+
+ /* The outermost frame is always derived from PC-framesize
+
+ One might think frameless innermost frames should have
+ a frame->frame that is the same as the parent's frame->frame.
+ That is wrong; frame->frame in that case should be the *high*
+ address of the parent's frame. It's complicated as hell to
+ explain, but the parent *always* creates some stack space for
+ the child. So the child actually does have a frame of some
+ sorts, and its base is the high address in its parent's frame. */
+ framesize = find_proc_framesize(frame->pc);
+ if (framesize == -1)
+ frame->frame = TARGET_READ_FP ();
+ else
+ frame->frame = read_register (SP_REGNUM) - framesize;
+}
+
+/* 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
+ INIT_EXTRA_FRAME_INFO and INIT_FRAME_PC will be called for the new frame.
+
+ This may involve searching through prologues for several functions
+ at boundaries where GCC calls HP C code, or where code which has
+ a frame pointer calls code without a frame pointer. */
+
+CORE_ADDR
+frame_chain (frame)
+ struct frame_info *frame;
+{
+ int my_framesize, caller_framesize;
+ struct unwind_table_entry *u;
+ CORE_ADDR frame_base;
+ struct frame_info *tmp_frame;
+
+ CORE_ADDR caller_pc;
+
+ struct minimal_symbol *min_frame_symbol;
+ struct symbol *frame_symbol;
+ char *frame_symbol_name;
+
+ /* If this is a threaded application, and we see the
+ routine "__pthread_exit", treat it as the stack root
+ for this thread. */
+ min_frame_symbol = lookup_minimal_symbol_by_pc (frame->pc);
+ frame_symbol = find_pc_function(frame->pc);
+
+ if ((min_frame_symbol != 0) /* && (frame_symbol == 0) */)
+ {
+ /* The test above for "no user function name" would defend
+ against the slim likelihood that a user might define a
+ routine named "__pthread_exit" and then try to debug it.
+
+ If it weren't commented out, and you tried to debug the
+ pthread library itself, you'd get errors.
+
+ So for today, we don't make that check. */
+ frame_symbol_name = SYMBOL_NAME(min_frame_symbol);
+ if (frame_symbol_name != 0) {
+ if (0 == strncmp(frame_symbol_name,
+ THREAD_INITIAL_FRAME_SYMBOL,
+ THREAD_INITIAL_FRAME_SYM_LEN)) {
+ /* Pretend we've reached the bottom of the stack. */
+ return (CORE_ADDR) 0;
+ }
+ }
+ } /* End of hacky code for threads. */
+
+ /* Handle HPUX, BSD, and OSF1 style interrupt frames first. These
+ are easy; at *sp we have a full save state strucutre which we can
+ pull the old stack pointer from. Also see frame_saved_pc for
+ code to dig a saved PC out of the save state structure. */
+ if (pc_in_interrupt_handler (frame->pc))
+ frame_base = read_memory_integer (frame->frame + SP_REGNUM * 4, 4);
+#ifdef FRAME_BASE_BEFORE_SIGTRAMP
+ else if (frame->signal_handler_caller)
+ {
+ FRAME_BASE_BEFORE_SIGTRAMP (frame, &frame_base);
+ }
+#endif
+ else
+ frame_base = frame->frame;
+
+ /* Get frame sizes for the current frame and the frame of the
+ caller. */
+ my_framesize = find_proc_framesize (frame->pc);
+ caller_pc = FRAME_SAVED_PC(frame);
+
+ /* If we can't determine the caller's PC, then it's not likely we can
+ really determine anything meaningful about its frame. We'll consider
+ this to be stack bottom. */
+ if (caller_pc == (CORE_ADDR) 0)
+ return (CORE_ADDR) 0;
+
+ caller_framesize = find_proc_framesize (FRAME_SAVED_PC(frame));
+
+ /* If caller does not have a frame pointer, then its frame
+ can be found at current_frame - caller_framesize. */
+ if (caller_framesize != -1)
+ {
+ return frame_base - caller_framesize;
+ }
+ /* Both caller and callee have frame pointers and are GCC compiled
+ (SAVE_SP bit in unwind descriptor is on for both functions.
+ The previous frame pointer is found at the top of the current frame. */
+ if (caller_framesize == -1 && my_framesize == -1)
+ {
+ return read_memory_integer (frame_base, 4);
+ }
+ /* Caller has a frame pointer, but callee does not. This is a little
+ more difficult as GCC and HP C lay out locals and callee register save
+ areas very differently.
+
+ The previous frame pointer could be in a register, or in one of
+ several areas on the stack.
+
+ Walk from the current frame to the innermost frame examining
+ unwind descriptors to determine if %r3 ever gets saved into the
+ stack. If so return whatever value got saved into the stack.
+ If it was never saved in the stack, then the value in %r3 is still
+ valid, so use it.
+
+ We use information from unwind descriptors to determine if %r3
+ is saved into the stack (Entry_GR field has this information). */
+
+ tmp_frame = frame;
+ while (tmp_frame)
+ {
+ u = find_unwind_entry (tmp_frame->pc);
+
+ if (!u)
+ {
+ /* We could find this information by examining prologues. I don't
+ think anyone has actually written any tools (not even "strip")
+ which leave them out of an executable, so maybe this is a moot
+ point. */
+ /* ??rehrauer: Actually, it's quite possible to stepi your way into
+ code that doesn't have unwind entries. For example, stepping into
+ the dynamic linker will give you a PC that has none. Thus, I've
+ disabled this warning. */
+#if 0
+ warning ("Unable to find unwind for PC 0x%x -- Help!", tmp_frame->pc);
+#endif
+ return (CORE_ADDR) 0;
+ }
+
+ /* Entry_GR specifies the number of callee-saved general registers
+ saved in the stack. It starts at %r3, so %r3 would be 1. */
+ if (u->Entry_GR >= 1 || u->Save_SP
+ || tmp_frame->signal_handler_caller
+ || pc_in_interrupt_handler (tmp_frame->pc))
+ break;
+ else
+ tmp_frame = tmp_frame->next;
+ }
+
+ if (tmp_frame)
+ {
+ /* We may have walked down the chain into a function with a frame
+ pointer. */
+ if (u->Save_SP
+ && !tmp_frame->signal_handler_caller
+ && !pc_in_interrupt_handler (tmp_frame->pc))
+ {
+ return read_memory_integer (tmp_frame->frame, 4);
+ }
+ /* %r3 was saved somewhere in the stack. Dig it out. */
+ else
+ {
+ struct frame_saved_regs saved_regs;
+
+ /* Sick.
+
+ For optimization purposes many kernels don't have the
+ callee saved registers into the save_state structure upon
+ entry into the kernel for a syscall; the optimization
+ is usually turned off if the process is being traced so
+ that the debugger can get full register state for the
+ process.
+
+ This scheme works well except for two cases:
+
+ * Attaching to a process when the process is in the
+ kernel performing a system call (debugger can't get
+ full register state for the inferior process since
+ the process wasn't being traced when it entered the
+ system call).
+
+ * Register state is not complete if the system call
+ causes the process to core dump.
+
+
+ The following heinous code is an attempt to deal with
+ the lack of register state in a core dump. It will
+ fail miserably if the function which performs the
+ system call has a variable sized stack frame. */
+
+ get_frame_saved_regs (tmp_frame, &saved_regs);
+
+ /* Abominable hack. */
+ if (current_target.to_has_execution == 0
+ && ((saved_regs.regs[FLAGS_REGNUM]
+ && (read_memory_integer (saved_regs.regs[FLAGS_REGNUM], 4)
+ & 0x2))
+ || (saved_regs.regs[FLAGS_REGNUM] == 0
+ && read_register (FLAGS_REGNUM) & 0x2)))
+ {
+ u = find_unwind_entry (FRAME_SAVED_PC (frame));
+ if (!u)
+ {
+ return read_memory_integer (saved_regs.regs[FP_REGNUM], 4);
+ }
+ else
+ {
+ return frame_base - (u->Total_frame_size << 3);
+ }
+ }
+
+ return read_memory_integer (saved_regs.regs[FP_REGNUM], 4);
+ }
+ }
+ else
+ {
+ struct frame_saved_regs saved_regs;
+
+ /* Get the innermost frame. */
+ tmp_frame = frame;
+ while (tmp_frame->next != NULL)
+ tmp_frame = tmp_frame->next;
+
+ get_frame_saved_regs (tmp_frame, &saved_regs);
+ /* Abominable hack. See above. */
+ if (current_target.to_has_execution == 0
+ && ((saved_regs.regs[FLAGS_REGNUM]
+ && (read_memory_integer (saved_regs.regs[FLAGS_REGNUM], 4)
+ & 0x2))
+ || (saved_regs.regs[FLAGS_REGNUM] == 0
+ && read_register (FLAGS_REGNUM) & 0x2)))
+ {
+ u = find_unwind_entry (FRAME_SAVED_PC (frame));
+ if (!u)
+ {
+ return read_memory_integer (saved_regs.regs[FP_REGNUM], 4);
+ }
+ else
+ {
+ return frame_base - (u->Total_frame_size << 3);
+ }
+ }
+
+ /* The value in %r3 was never saved into the stack (thus %r3 still
+ holds the value of the previous frame pointer). */
+ return TARGET_READ_FP ();
+ }
+}
+
+
+/* To see if a frame chain is valid, see if the caller looks like it
+ was compiled with gcc. */
+
+int
+hppa_frame_chain_valid (chain, thisframe)
+ CORE_ADDR chain;
+ struct frame_info *thisframe;
+{
+ struct minimal_symbol *msym_us;
+ struct minimal_symbol *msym_start;
+ struct unwind_table_entry *u, *next_u = NULL;
+ struct frame_info *next;
+
+ if (!chain)
+ return 0;
+
+ u = find_unwind_entry (thisframe->pc);
+
+ if (u == NULL)
+ return 1;
+
+ /* We can't just check that the same of msym_us is "_start", because
+ someone idiotically decided that they were going to make a Ltext_end
+ symbol with the same address. This Ltext_end symbol is totally
+ indistinguishable (as nearly as I can tell) from the symbol for a function
+ which is (legitimately, since it is in the user's namespace)
+ named Ltext_end, so we can't just ignore it. */
+ msym_us = lookup_minimal_symbol_by_pc (FRAME_SAVED_PC (thisframe));
+ msym_start = lookup_minimal_symbol ("_start", NULL, NULL);
+ if (msym_us
+ && msym_start
+ && SYMBOL_VALUE_ADDRESS (msym_us) == SYMBOL_VALUE_ADDRESS (msym_start))
+ return 0;
+
+ /* Grrrr. Some new idiot decided that they don't want _start for the
+ PRO configurations; $START$ calls main directly.... Deal with it. */
+ msym_start = lookup_minimal_symbol ("$START$", NULL, NULL);
+ if (msym_us
+ && msym_start
+ && SYMBOL_VALUE_ADDRESS (msym_us) == SYMBOL_VALUE_ADDRESS (msym_start))
+ return 0;
+
+ next = get_next_frame (thisframe);
+ if (next)
+ next_u = find_unwind_entry (next->pc);
+
+ /* If this frame does not save SP, has no stack, isn't a stub,
+ and doesn't "call" an interrupt routine or signal handler caller,
+ then its not valid. */
+ if (u->Save_SP || u->Total_frame_size || u->stub_unwind.stub_type != 0
+ || (thisframe->next && thisframe->next->signal_handler_caller)
+ || (next_u && next_u->HP_UX_interrupt_marker))
+ return 1;
+
+ if (pc_in_linker_stub (thisframe->pc))
+ return 1;
+
+ return 0;
+}
+
+/*
+ These functions deal with saving and restoring register state
+ around a function call in the inferior. They keep the stack
+ double-word aligned; eventually, on an hp700, the stack will have
+ to be aligned to a 64-byte boundary. */
+
+void
+push_dummy_frame (inf_status)
+ struct inferior_status *inf_status;
+{
+ CORE_ADDR sp, pc, pcspace;
+ register int regnum;
+ int int_buffer;
+ double freg_buffer;
+
+ /* Oh, what a hack. If we're trying to perform an inferior call
+ while the inferior is asleep, we have to make sure to clear
+ the "in system call" bit in the flag register (the call will
+ start after the syscall returns, so we're no longer in the system
+ call!) This state is kept in "inf_status", change it there.
+
+ We also need a number of horrid hacks to deal with lossage in the
+ PC queue registers (apparently they're not valid when the in syscall
+ bit is set). */
+ pc = target_read_pc (inferior_pid);
+ int_buffer = read_register (FLAGS_REGNUM);
+ if (int_buffer & 0x2)
+ {
+ unsigned int sid;
+ int_buffer &= ~0x2;
+ memcpy (inf_status->registers, &int_buffer, 4);
+ memcpy (inf_status->registers + REGISTER_BYTE (PCOQ_HEAD_REGNUM), &pc, 4);
+ pc += 4;
+ memcpy (inf_status->registers + REGISTER_BYTE (PCOQ_TAIL_REGNUM), &pc, 4);
+ pc -= 4;
+ sid = (pc >> 30) & 0x3;
+ if (sid == 0)
+ pcspace = read_register (SR4_REGNUM);
+ else
+ pcspace = read_register (SR4_REGNUM + 4 + sid);
+ memcpy (inf_status->registers + REGISTER_BYTE (PCSQ_HEAD_REGNUM),
+ &pcspace, 4);
+ memcpy (inf_status->registers + REGISTER_BYTE (PCSQ_TAIL_REGNUM),
+ &pcspace, 4);
+ }
+ else
+ pcspace = read_register (PCSQ_HEAD_REGNUM);
+
+ /* Space for "arguments"; the RP goes in here. */
+ sp = read_register (SP_REGNUM) + 48;
+ int_buffer = read_register (RP_REGNUM) | 0x3;
+ write_memory (sp - 20, (char *)&int_buffer, 4);
+
+ int_buffer = TARGET_READ_FP ();
+ write_memory (sp, (char *)&int_buffer, 4);
+
+ write_register (FP_REGNUM, sp);
+
+ sp += 8;
+
+ for (regnum = 1; regnum < 32; regnum++)
+ if (regnum != RP_REGNUM && regnum != FP_REGNUM)
+ sp = push_word (sp, read_register (regnum));
+
+ sp += 4;
+
+ for (regnum = FP0_REGNUM; regnum < NUM_REGS; regnum++)
+ {
+ read_register_bytes (REGISTER_BYTE (regnum), (char *)&freg_buffer, 8);
+ sp = push_bytes (sp, (char *)&freg_buffer, 8);
+ }
+ sp = push_word (sp, read_register (IPSW_REGNUM));
+ sp = push_word (sp, read_register (SAR_REGNUM));
+ sp = push_word (sp, pc);
+ sp = push_word (sp, pcspace);
+ sp = push_word (sp, pc + 4);
+ sp = push_word (sp, pcspace);
+ write_register (SP_REGNUM, sp);
+}
+
+static void
+find_dummy_frame_regs (frame, frame_saved_regs)
+ struct frame_info *frame;
+ struct frame_saved_regs *frame_saved_regs;
+{
+ CORE_ADDR fp = frame->frame;
+ int i;
+
+ frame_saved_regs->regs[RP_REGNUM] = (fp - 20) & ~0x3;
+ frame_saved_regs->regs[FP_REGNUM] = fp;
+ frame_saved_regs->regs[1] = fp + 8;
+
+ for (fp += 12, i = 3; i < 32; i++)
+ {
+ if (i != FP_REGNUM)
+ {
+ frame_saved_regs->regs[i] = fp;
+ fp += 4;
+ }
+ }
+
+ fp += 4;
+ for (i = FP0_REGNUM; i < NUM_REGS; i++, fp += 8)
+ frame_saved_regs->regs[i] = fp;
+
+ frame_saved_regs->regs[IPSW_REGNUM] = fp;
+ frame_saved_regs->regs[SAR_REGNUM] = fp + 4;
+ frame_saved_regs->regs[PCOQ_HEAD_REGNUM] = fp + 8;
+ frame_saved_regs->regs[PCSQ_HEAD_REGNUM] = fp + 12;
+ frame_saved_regs->regs[PCOQ_TAIL_REGNUM] = fp + 16;
+ frame_saved_regs->regs[PCSQ_TAIL_REGNUM] = fp + 20;
+}
+
+void
+hppa_pop_frame ()
+{
+ register struct frame_info *frame = get_current_frame ();
+ register CORE_ADDR fp, npc, target_pc;
+ register int regnum;
+ struct frame_saved_regs fsr;
+ double freg_buffer;
+
+ fp = FRAME_FP (frame);
+ get_frame_saved_regs (frame, &fsr);
+
+#ifndef NO_PC_SPACE_QUEUE_RESTORE
+ if (fsr.regs[IPSW_REGNUM]) /* Restoring a call dummy frame */
+ restore_pc_queue (&fsr);
+#endif
+
+ for (regnum = 31; regnum > 0; regnum--)
+ if (fsr.regs[regnum])
+ write_register (regnum, read_memory_integer (fsr.regs[regnum], 4));
+
+ for (regnum = NUM_REGS - 1; regnum >= FP0_REGNUM ; regnum--)
+ if (fsr.regs[regnum])
+ {
+ read_memory (fsr.regs[regnum], (char *)&freg_buffer, 8);
+ write_register_bytes (REGISTER_BYTE (regnum), (char *)&freg_buffer, 8);
+ }
+
+ if (fsr.regs[IPSW_REGNUM])
+ write_register (IPSW_REGNUM,
+ read_memory_integer (fsr.regs[IPSW_REGNUM], 4));
+
+ if (fsr.regs[SAR_REGNUM])
+ write_register (SAR_REGNUM,
+ read_memory_integer (fsr.regs[SAR_REGNUM], 4));
+
+ /* If the PC was explicitly saved, then just restore it. */
+ if (fsr.regs[PCOQ_TAIL_REGNUM])
+ {
+ npc = read_memory_integer (fsr.regs[PCOQ_TAIL_REGNUM], 4);
+ write_register (PCOQ_TAIL_REGNUM, npc);
+ }
+ /* Else use the value in %rp to set the new PC. */
+ else
+ {
+ npc = read_register (RP_REGNUM);
+ write_pc (npc);
+ }
+
+ write_register (FP_REGNUM, read_memory_integer (fp, 4));
+
+ if (fsr.regs[IPSW_REGNUM]) /* call dummy */
+ write_register (SP_REGNUM, fp - 48);
+ else
+ write_register (SP_REGNUM, fp);
+
+ /* The PC we just restored may be inside a return trampoline. If so
+ we want to restart the inferior and run it through the trampoline.
+
+ Do this by setting a momentary breakpoint at the location the
+ trampoline returns to.
+
+ Don't skip through the trampoline if we're popping a dummy frame. */
+ target_pc = SKIP_TRAMPOLINE_CODE (npc & ~0x3) & ~0x3;
+ if (target_pc && !fsr.regs[IPSW_REGNUM])
+ {
+ struct symtab_and_line sal;
+ struct breakpoint *breakpoint;
+ struct cleanup *old_chain;
+
+ /* Set up our breakpoint. Set it to be silent as the MI code
+ for "return_command" will print the frame we returned to. */
+ sal = find_pc_line (target_pc, 0);
+ sal.pc = target_pc;
+ breakpoint = set_momentary_breakpoint (sal, NULL, bp_finish);
+ breakpoint->silent = 1;
+
+ /* So we can clean things up. */
+ old_chain = make_cleanup ((make_cleanup_func) delete_breakpoint, breakpoint);
+
+ /* Start up the inferior. */
+ clear_proceed_status ();
+ proceed_to_finish = 1;
+ proceed ((CORE_ADDR) -1, TARGET_SIGNAL_DEFAULT, 0);
+
+ /* Perform our cleanups. */
+ do_cleanups (old_chain);
+ }
+ flush_cached_frames ();
+}
+
+/* After returning to a dummy on the stack, restore the instruction
+ queue space registers. */
+
+static int
+restore_pc_queue (fsr)
+ struct frame_saved_regs *fsr;
+{
+ CORE_ADDR pc = read_pc ();
+ CORE_ADDR new_pc = read_memory_integer (fsr->regs[PCOQ_HEAD_REGNUM], 4);
+ struct target_waitstatus w;
+ int insn_count;
+
+ /* Advance past break instruction in the call dummy. */
+ write_register (PCOQ_HEAD_REGNUM, pc + 4);
+ write_register (PCOQ_TAIL_REGNUM, pc + 8);
+
+ /* HPUX doesn't let us set the space registers or the space
+ registers of the PC queue through ptrace. Boo, hiss.
+ Conveniently, the call dummy has this sequence of instructions
+ after the break:
+ mtsp r21, sr0
+ ble,n 0(sr0, r22)
+
+ So, load up the registers and single step until we are in the
+ right place. */
+
+ write_register (21, read_memory_integer (fsr->regs[PCSQ_HEAD_REGNUM], 4));
+ write_register (22, new_pc);
+
+ for (insn_count = 0; insn_count < 3; insn_count++)
+ {
+ /* FIXME: What if the inferior gets a signal right now? Want to
+ merge this into wait_for_inferior (as a special kind of
+ watchpoint? By setting a breakpoint at the end? Is there
+ any other choice? Is there *any* way to do this stuff with
+ ptrace() or some equivalent?). */
+ resume (1, 0);
+ target_wait (inferior_pid, &w);
+
+ if (w.kind == TARGET_WAITKIND_SIGNALLED)
+ {
+ stop_signal = w.value.sig;
+ terminal_ours_for_output ();
+ printf_unfiltered ("\nProgram terminated with signal %s, %s.\n",
+ target_signal_to_name (stop_signal),
+ target_signal_to_string (stop_signal));
+ gdb_flush (gdb_stdout);
+ return 0;
+ }
+ }
+ target_terminal_ours ();
+ target_fetch_registers (-1);
+ return 1;
+}
+
+#if 0
+CORE_ADDR
+hppa_push_arguments (nargs, args, sp, struct_return, struct_addr)
+ int nargs;
+ value_ptr *args;
+ CORE_ADDR sp;
+ int struct_return;
+ CORE_ADDR struct_addr;
+{
+ /* array of arguments' offsets */
+ int *offset = (int *)alloca(nargs * sizeof (int));
+ int cum = 0;
+ int i, alignment;
+
+ for (i = 0; i < nargs; i++)
+ {
+ int x = 0;
+ /* cum is the sum of the lengths in bytes of
+ the arguments seen so far */
+ cum += TYPE_LENGTH (VALUE_TYPE (args[i]));
+
+ /* value must go at proper alignment. Assume alignment is a
+ power of two. */
+ alignment = hppa_alignof (VALUE_TYPE (args[i]));
+
+ if (cum % alignment)
+ cum = (cum + alignment) & -alignment;
+ offset[i] = -cum;
+
+ }
+ sp += max ((cum + 7) & -8, 16);
+
+ for (i = 0; i < nargs; i++)
+ write_memory (sp + offset[i], VALUE_CONTENTS (args[i]),
+ TYPE_LENGTH (VALUE_TYPE (args[i])));
+
+ if (struct_return)
+ write_register (28, struct_addr);
+ return sp + 32;
+}
+#endif
+
+/* elz: I am rewriting this function, because the one above is a very
+ obscure piece of code.
+ This function pushes the arguments on the stack. The stack grows up
+ on the PA.
+ Each argument goes in one (or more) word (4 bytes) on the stack.
+ The first four words for the args must be allocated, even if they
+ are not used.
+ The 'topmost' arg is arg0, the 'bottom-most' is arg3. (if you think of
+ them as 1 word long).
+ Below these there can be any number of arguments, as needed by the function.
+ If an arg is bigger than one word, it will be written on the stack
+ occupying as many words as needed. Args that are bigger than 64bits
+ are not copied on the stack, a pointer is passed instead.
+
+ On top of the arg0 word there are other 8 words (32bytes) which are used
+ for other purposes */
+
+CORE_ADDR
+hppa_push_arguments (nargs, args, sp, struct_return, struct_addr)
+ int nargs;
+ value_ptr *args;
+ CORE_ADDR sp;
+ int struct_return;
+ CORE_ADDR struct_addr;
+{
+ /* array of arguments' offsets */
+ int *offset = (int *)alloca(nargs * sizeof (int));
+ /* array of arguments' lengths: real lengths in bytes, not aligned to word size */
+ int *lengths = (int *)alloca(nargs * sizeof (int));
+
+ int bytes_reserved; /* this is the number of bytes on the stack occupied by an
+ argument. This will be always a multiple of 4 */
+
+ int cum_bytes_reserved = 0; /* this is the total number of bytes reserved by the args
+ seen so far. It is a multiple of 4 always */
+ int cum_bytes_aligned = 0; /* same as above, but aligned on 8 bytes */
+ int i;
+
+ /* When an arg does not occupy a whole word, for instance in bitfields:
+ if the arg is x bits (0<x<32), it must be written
+ starting from the (x-1)-th position down until the 0-th position.
+ It is enough to align it to the word. */
+ /* if an arg occupies 8 bytes, it must be aligned on the 64-bits
+ high order word in odd arg word. */
+ /* if an arg is larger than 64 bits, we need to pass a pointer to it, and
+ copy the actual value on the stack, so that the callee can play with it.
+ This is taken care of in valops.c in the call_function_by_hand function.
+ The argument that is received in this function here has already be converted
+ to a pointer to whatever is needed, so that it just can be pushed
+ as a word argument */
+
+ for (i = 0; i < nargs; i++)
+ {
+
+ lengths[i] = TYPE_LENGTH (VALUE_TYPE (args[i]));
+
+ if (lengths[i] % 4)
+ bytes_reserved = (lengths[i] / 4) * 4 + 4;
+ else
+ bytes_reserved = lengths[i];
+
+ offset[i] = cum_bytes_reserved + lengths[i];
+
+ if ((bytes_reserved == 8) && (offset[i] % 8)) /* if 64-bit arg is not 64 bit aligned */
+ {
+ int new_offset=0;
+ /* bytes_reserved is already aligned to the word, so we put it at one word
+ more down the stack. This will leave one empty word on the
+ stack, and one unused register. This is OK, see the calling
+ convention doc */
+ /* the offset may have to be moved to the corresponding position
+ one word down the stack, to maintain
+ alignment. */
+ new_offset = (offset[i] / 8) * 8 + 8;
+ if ((new_offset - offset[i]) >=4)
+ {
+ bytes_reserved += 4;
+ offset[i] += 4;
+ }
+ }
+
+ cum_bytes_reserved += bytes_reserved;
+
+ }
+
+ /* now move up the sp to reserve at least 4 words required for the args,
+ or more than this if needed */
+ /* wee also need to keep the sp aligned to 8 bytes */
+ cum_bytes_aligned = STACK_ALIGN (cum_bytes_reserved);
+ sp += max (cum_bytes_aligned, 16);
+
+ /* now write each of the args at the proper offset down the stack */
+ for (i = 0; i < nargs; i++)
+ write_memory (sp - offset[i], VALUE_CONTENTS (args[i]), lengths[i]);
+
+
+ /* if a structure has to be returned, set up register 28 to hold its address */
+ if (struct_return)
+ write_register (28, struct_addr);
+
+ /* the stack will have other 8 words on top of the args */
+ return sp + 32;
+}
+
+
+/* elz: this function returns a value which is built looking at the given address.
+ It is called from call_function_by_hand, in case we need to return a
+ value which is larger than 64 bits, and it is stored in the stack rather than
+ in the registers r28 and r29 or fr4.
+ This function does the same stuff as value_being_returned in values.c, but
+ gets the value from the stack rather than from the buffer where all the
+ registers were saved when the function called completed. */
+value_ptr
+hppa_value_returned_from_stack (valtype , addr)
+ register struct type *valtype;
+ CORE_ADDR addr;
+{
+ register value_ptr val;
+
+ val = allocate_value (valtype);
+ CHECK_TYPEDEF (valtype);
+ target_read_memory(addr, VALUE_CONTENTS_RAW (val), TYPE_LENGTH (valtype));
+
+ return val;
+}
+
+
+
+/* elz: Used to lookup a symbol in the shared libraries.
+ This function calls shl_findsym, indirectly through a
+ call to __d_shl_get. __d_shl_get is in end.c, which is always
+ linked in by the hp compilers/linkers.
+ The call to shl_findsym cannot be made directly because it needs
+ to be active in target address space.
+ inputs: - minimal symbol pointer for the function we want to look up
+ - address in target space of the descriptor for the library
+ where we want to look the symbol up.
+ This address is retrieved using the
+ som_solib_get_solib_by_pc function (somsolib.c).
+ output: - real address in the library of the function.
+ note: the handle can be null, in which case shl_findsym will look for
+ the symbol in all the loaded shared libraries.
+ files to look at if you need reference on this stuff:
+ dld.c, dld_shl_findsym.c
+ end.c
+ man entry for shl_findsym */
+
+CORE_ADDR
+find_stub_with_shl_get(function, handle)
+ struct minimal_symbol *function;
+ CORE_ADDR handle;
+{
+ struct symbol *get_sym, *symbol2;
+ struct minimal_symbol *buff_minsym, *msymbol;
+ struct type *ftype;
+ value_ptr *args;
+ value_ptr funcval, val;
+
+ int x, namelen, err_value, tmp = -1;
+ CORE_ADDR endo_buff_addr, value_return_addr, errno_return_addr;
+ CORE_ADDR stub_addr;
+
+
+ args = (value_ptr *) alloca (sizeof (value_ptr) * 8); /* 6 for the arguments and one null one??? */
+ funcval = find_function_in_inferior("__d_shl_get");
+ get_sym = lookup_symbol("__d_shl_get", NULL, VAR_NAMESPACE, NULL, NULL);
+ buff_minsym = lookup_minimal_symbol("__buffer", NULL, NULL);
+ msymbol = lookup_minimal_symbol ("__shldp", NULL, NULL);
+ symbol2 = lookup_symbol("__shldp", NULL, VAR_NAMESPACE, NULL, NULL);
+ endo_buff_addr = SYMBOL_VALUE_ADDRESS (buff_minsym);
+ namelen = strlen(SYMBOL_NAME(function));
+ value_return_addr = endo_buff_addr + namelen;
+ ftype = check_typedef(SYMBOL_TYPE(get_sym));
+
+ /* do alignment */
+ if ((x=value_return_addr % 64) !=0)
+ value_return_addr = value_return_addr + 64 - x;
+
+ errno_return_addr = value_return_addr + 64;
+
+
+ /* set up stuff needed by __d_shl_get in buffer in end.o */
+
+ target_write_memory(endo_buff_addr, SYMBOL_NAME(function), namelen);
+
+ target_write_memory(value_return_addr, (char *) &tmp, 4);
+
+ target_write_memory(errno_return_addr, (char *) &tmp, 4);
+
+ target_write_memory(SYMBOL_VALUE_ADDRESS(msymbol),
+ (char *)&handle, 4);
+
+ /* now prepare the arguments for the call */
+
+ args[0] = value_from_longest (TYPE_FIELD_TYPE(ftype, 0), 12);
+ args[1] = value_from_longest (TYPE_FIELD_TYPE(ftype, 1), SYMBOL_VALUE_ADDRESS(msymbol));
+ args[2] = value_from_longest (TYPE_FIELD_TYPE(ftype, 2), endo_buff_addr);
+ args[3] = value_from_longest (TYPE_FIELD_TYPE(ftype, 3), TYPE_PROCEDURE);
+ args[4] = value_from_longest (TYPE_FIELD_TYPE(ftype, 4), value_return_addr);
+ args[5] = value_from_longest (TYPE_FIELD_TYPE(ftype, 5), errno_return_addr);
+
+ /* now call the function */
+
+ val = call_function_by_hand(funcval, 6, args);
+
+ /* now get the results */
+
+ target_read_memory(errno_return_addr, (char *) &err_value, sizeof(err_value));
+
+ target_read_memory(value_return_addr, (char *) &stub_addr, sizeof(stub_addr));
+ if (stub_addr <= 0)
+ error("call to __d_shl_get failed, error code is %d", err_value); /* purecov: deadcode */
+
+ return(stub_addr);
+}
+
+/* Cover routine for find_stub_with_shl_get to pass to catch_errors */
+static CORE_ADDR
+cover_find_stub_with_shl_get (args)
+ args_for_find_stub * args;
+{
+ return find_stub_with_shl_get (args->msym, args->solib_handle);
+}
+
+
+/* Insert the specified number of args and function address
+ into a call sequence of the above form stored at DUMMYNAME.
+
+ On the hppa we need to call the stack dummy through $$dyncall.
+ Therefore our version of FIX_CALL_DUMMY takes an extra argument,
+ real_pc, which is the location where gdb should start up the
+ inferior to do the function call. */
+
+CORE_ADDR
+hppa_fix_call_dummy (dummy, pc, fun, nargs, args, type, gcc_p)
+ char *dummy;
+ CORE_ADDR pc;
+ CORE_ADDR fun;
+ int nargs;
+ value_ptr *args;
+ struct type *type;
+ int gcc_p;
+{
+ CORE_ADDR dyncall_addr;
+ struct minimal_symbol *msymbol;
+ struct minimal_symbol *trampoline;
+ int flags = read_register (FLAGS_REGNUM);
+ struct unwind_table_entry *u;
+ CORE_ADDR new_stub=0;
+ CORE_ADDR solib_handle=0;
+
+ trampoline = NULL;
+ msymbol = lookup_minimal_symbol ("$$dyncall", NULL, NULL);
+ if (msymbol == NULL)
+ error ("Can't find an address for $$dyncall trampoline"); /* purecov: deadcode */
+
+ dyncall_addr = SYMBOL_VALUE_ADDRESS (msymbol);
+
+ /* FUN could be a procedure label, in which case we have to get
+ its real address and the value of its GOT/DP. */
+ if (fun & 0x2)
+ {
+ /* Get the GOT/DP value for the target function. It's
+ at *(fun+4). Note the call dummy is *NOT* allowed to
+ trash %r19 before calling the target function. */
+ write_register (19, read_memory_integer ((fun & ~0x3) + 4, 4));
+
+ /* Now get the real address for the function we are calling, it's
+ at *fun. */
+ fun = (CORE_ADDR) read_memory_integer (fun & ~0x3, 4);
+ }
+ else
+ {
+
+#ifndef GDB_TARGET_IS_PA_ELF
+ /* FUN could be either an export stub, or the real address of a
+ function in a shared library. We must call an import stub
+ rather than the export stub or real function for lazy binding
+ to work correctly. */
+
+ /* elz: let's see if fun is in a shared library */
+ solib_handle = som_solib_get_solib_by_pc(fun);
+
+ /* elz: for 10.30 and 11.00 the calls via __d_plt_call cannot be made
+ via import stubs, only via plables, so this code here becomes useless.
+ On 10.20, the plables mechanism works too, so we just ignore this import
+ stub stuff */
+#if 0
+ if (solib_handle)
+ {
+ struct objfile *objfile;
+ struct minimal_symbol *funsymbol, *stub_symbol;
+ CORE_ADDR newfun = 0;
+
+ funsymbol = lookup_minimal_symbol_by_pc (fun);
+ if (!funsymbol)
+ error ("Unable to find minimal symbol for target fucntion.\n");
+
+ /* Search all the object files for an import symbol with the
+ right name. */
+ ALL_OBJFILES (objfile)
+ {
+ stub_symbol = lookup_minimal_symbol (SYMBOL_NAME (funsymbol),
+ NULL, objfile);
+ /* Found a symbol with the right name. */
+ if (stub_symbol)
+ {
+ struct unwind_table_entry *u;
+ /* It must be a shared library trampoline. */
+ if (MSYMBOL_TYPE (stub_symbol) != mst_solib_trampoline)
+ continue;
+
+ /* It must also be an import stub. */
+ u = find_unwind_entry (SYMBOL_VALUE (stub_symbol));
+ if (!u || u->stub_unwind.stub_type != IMPORT)
+ continue;
+
+ /* OK. Looks like the correct import stub. */
+ newfun = SYMBOL_VALUE (stub_symbol);
+ fun = newfun;
+ }
+ }
+ if (newfun == 0)
+ write_register (19, som_solib_get_got_by_pc (fun));
+ }
+#endif /* end of if 0 */
+#endif
+ }
+
+ /* If we are calling an import stub (eg calling into a dynamic library)
+ then have sr4export call the magic __d_plt_call routine which is linked
+ in from end.o. (You can't use _sr4export to call the import stub as
+ the value in sp-24 will get fried and you end up returning to the
+ wrong location. You can't call the import stub directly as the code
+ to bind the PLT entry to a function can't return to a stack address.) */
+
+ /* elz:
+ There does not have to be an import stub to call a routine in a
+ different load module (note: a "load module" is an a.out or a shared
+ library). If you call a routine indirectly, going through $$dyncall (or
+ $$dyncall_external), you won't go through an import stub. Import stubs
+ are only used for direct calls to an imported routine.
+
+ What you (wdb) need is to go through $$dyncall with a proper plabel for
+ the imported routine. shl_findsym() returns you the address of a plabel
+ suitable for use in making an indirect call through, e.g., through
+ $$dyncall.
+ This is taken care below with the call to find_stub_.... */
+#if 0
+ /* elz: this check here is not necessary if we are going to call stuff through
+ plabels only, we just now check whether the function we call is in a shlib */
+ u = find_unwind_entry (fun);
+
+ if (u && u->stub_unwind.stub_type == IMPORT ||
+ (!(u && u->stub_unwind.stub_type == IMPORT) && solib_handle))
+#endif /* 0 */
+ if (solib_handle)
+ {
+ CORE_ADDR new_fun;
+
+ /* Prefer __gcc_plt_call over the HP supplied routine because
+ __gcc_plt_call works for any number of arguments. */
+ trampoline = lookup_minimal_symbol ("__gcc_plt_call", NULL, NULL);
+ if (trampoline == NULL)
+ trampoline = lookup_minimal_symbol ("__d_plt_call", NULL, NULL);
+
+ if (trampoline == NULL)
+ {
+ error ("Can't find an address for __d_plt_call or __gcc_plt_call trampoline\nSuggest linking executable with -g (links in /opt/langtools/lib/end.o)");
+ }
+ /* This is where sr4export will jump to. */
+ new_fun = SYMBOL_VALUE_ADDRESS (trampoline);
+
+ if (strcmp (SYMBOL_NAME (trampoline), "__d_plt_call") == 0)
+ {
+ /* if the function is in a shared library, but we have no import sub for
+ it, we need to get the plabel from a call to __d_shl_get, which is a
+ function in end.o. To call this function we need to set up various things */
+
+ /* actually now we just use the plabel any time we make the call,
+ because on 10.30 and 11.00 this is the only acceptable way. This also
+ works fine for 10.20 */
+ /* if (!(u && u->stub_unwind.stub_type == IMPORT) && solib_handle) */
+ {
+ struct minimal_symbol *fmsymbol = lookup_minimal_symbol_by_pc(fun);
+
+ new_stub = find_stub_with_shl_get(fmsymbol, solib_handle);
+
+ if (new_stub == NULL)
+ error("Can't find an import stub for %s", SYMBOL_NAME(fmsymbol)); /* purecov: deadcode */
+ }
+
+ /* We have to store the address of the stub in __shlib_funcptr. */
+ msymbol = lookup_minimal_symbol ("__shlib_funcptr", NULL,
+ (struct objfile *)NULL);
+ if (msymbol == NULL)
+ error ("Can't find an address for __shlib_funcptr"); /* purecov: deadcode */
+
+ /* if (new_stub != NULL) */
+ target_write_memory (SYMBOL_VALUE_ADDRESS (msymbol), (char *)&new_stub, 4);
+ /* this is no longer used */
+ /* else
+ target_write_memory (SYMBOL_VALUE_ADDRESS (msymbol), (char *)&fun, 4); */
+
+ /* We want sr4export to call __d_plt_call, so we claim it is
+ the final target. Clear trampoline. */
+ fun = new_fun;
+ trampoline = NULL;
+ }
+ }
+
+ /* Store upper 21 bits of function address into ldil. fun will either be
+ the final target (most cases) or __d_plt_call when calling into a shared
+ library and __gcc_plt_call is not available. */
+ store_unsigned_integer
+ (&dummy[FUNC_LDIL_OFFSET],
+ INSTRUCTION_SIZE,
+ deposit_21 (fun >> 11,
+ extract_unsigned_integer (&dummy[FUNC_LDIL_OFFSET],
+ INSTRUCTION_SIZE)));
+
+ /* Store lower 11 bits of function address into ldo */
+ store_unsigned_integer
+ (&dummy[FUNC_LDO_OFFSET],
+ INSTRUCTION_SIZE,
+ deposit_14 (fun & MASK_11,
+ extract_unsigned_integer (&dummy[FUNC_LDO_OFFSET],
+ INSTRUCTION_SIZE)));
+#ifdef SR4EXPORT_LDIL_OFFSET
+
+ {
+ CORE_ADDR trampoline_addr;
+
+ /* We may still need sr4export's address too. */
+
+ if (trampoline == NULL)
+ {
+ msymbol = lookup_minimal_symbol ("_sr4export", NULL, NULL);
+ if (msymbol == NULL)
+ error ("Can't find an address for _sr4export trampoline"); /* purecov: deadcode */
+
+ trampoline_addr = SYMBOL_VALUE_ADDRESS (msymbol);
+ }
+ else
+ trampoline_addr = SYMBOL_VALUE_ADDRESS (trampoline);
+
+
+ /* Store upper 21 bits of trampoline's address into ldil */
+ store_unsigned_integer
+ (&dummy[SR4EXPORT_LDIL_OFFSET],
+ INSTRUCTION_SIZE,
+ deposit_21 (trampoline_addr >> 11,
+ extract_unsigned_integer (&dummy[SR4EXPORT_LDIL_OFFSET],
+ INSTRUCTION_SIZE)));
+
+ /* Store lower 11 bits of trampoline's address into ldo */
+ store_unsigned_integer
+ (&dummy[SR4EXPORT_LDO_OFFSET],
+ INSTRUCTION_SIZE,
+ deposit_14 (trampoline_addr & MASK_11,
+ extract_unsigned_integer (&dummy[SR4EXPORT_LDO_OFFSET],
+ INSTRUCTION_SIZE)));
+ }
+#endif
+
+ write_register (22, pc);
+
+ /* If we are in a syscall, then we should call the stack dummy
+ directly. $$dyncall is not needed as the kernel sets up the
+ space id registers properly based on the value in %r31. In
+ fact calling $$dyncall will not work because the value in %r22
+ will be clobbered on the syscall exit path.
+
+ Similarly if the current PC is in a shared library. Note however,
+ this scheme won't work if the shared library isn't mapped into
+ the same space as the stack. */
+ if (flags & 2)
+ return pc;
+#ifndef GDB_TARGET_IS_PA_ELF
+ else if (som_solib_get_got_by_pc (target_read_pc (inferior_pid)))
+ return pc;
+#endif
+ else
+ return dyncall_addr;
+
+}
+
+
+
+
+/* If the pid is in a syscall, then the FP register is not readable.
+ We'll return zero in that case, rather than attempting to read it
+ and cause a warning. */
+CORE_ADDR
+target_read_fp (pid)
+ int pid;
+{
+ int flags = read_register (FLAGS_REGNUM);
+
+ if (flags & 2) {
+ return (CORE_ADDR) 0;
+ }
+
+ /* This is the only site that may directly read_register () the FP
+ register. All others must use TARGET_READ_FP (). */
+ return read_register (FP_REGNUM);
+}
+
+
+/* Get the PC from %r31 if currently in a syscall. Also mask out privilege
+ bits. */
+
+CORE_ADDR
+target_read_pc (pid)
+ int pid;
+{
+ int flags = read_register_pid (FLAGS_REGNUM, pid);
+
+ /* The following test does not belong here. It is OS-specific, and belongs
+ in native code. */
+ /* Test SS_INSYSCALL */
+ if (flags & 2)
+ return read_register_pid (31, pid) & ~0x3;
+
+ return read_register_pid (PC_REGNUM, pid) & ~0x3;
+}
+
+/* Write out the PC. If currently in a syscall, then also write the new
+ PC value into %r31. */
+
+void
+target_write_pc (v, pid)
+ CORE_ADDR v;
+ int pid;
+{
+ int flags = read_register_pid (FLAGS_REGNUM, pid);
+
+ /* The following test does not belong here. It is OS-specific, and belongs
+ in native code. */
+ /* If in a syscall, then set %r31. Also make sure to get the
+ privilege bits set correctly. */
+ /* Test SS_INSYSCALL */
+ if (flags & 2)
+ write_register_pid (31, v | 0x3, pid);
+
+ write_register_pid (PC_REGNUM, v, pid);
+ write_register_pid (NPC_REGNUM, v + 4, pid);
+}
+
+/* return the alignment of a type in bytes. Structures have the maximum
+ alignment required by their fields. */
+
+static int
+hppa_alignof (type)
+ struct type *type;
+{
+ int max_align, align, i;
+ CHECK_TYPEDEF (type);
+ switch (TYPE_CODE (type))
+ {
+ case TYPE_CODE_PTR:
+ case TYPE_CODE_INT:
+ case TYPE_CODE_FLT:
+ return TYPE_LENGTH (type);
+ case TYPE_CODE_ARRAY:
+ return hppa_alignof (TYPE_FIELD_TYPE (type, 0));
+ case TYPE_CODE_STRUCT:
+ case TYPE_CODE_UNION:
+ max_align = 1;
+ for (i = 0; i < TYPE_NFIELDS (type); i++)
+ {
+ /* Bit fields have no real alignment. */
+ /* if (!TYPE_FIELD_BITPOS (type, i)) */
+ if (!TYPE_FIELD_BITSIZE (type, i)) /* elz: this should be bitsize */
+ {
+ align = hppa_alignof (TYPE_FIELD_TYPE (type, i));
+ max_align = max (max_align, align);
+ }
+ }
+ return max_align;
+ default:
+ return 4;
+ }
+}
+
+/* Print the register regnum, or all registers if regnum is -1 */
+
+void
+pa_do_registers_info (regnum, fpregs)
+ int regnum;
+ int fpregs;
+{
+ char raw_regs [REGISTER_BYTES];
+ int i;
+
+ /* Make a copy of gdb's save area (may cause actual
+ reads from the target). */
+ for (i = 0; i < NUM_REGS; i++)
+ read_relative_register_raw_bytes (i, raw_regs + REGISTER_BYTE (i));
+
+ if (regnum == -1)
+ pa_print_registers (raw_regs, regnum, fpregs);
+ else if (regnum < FP4_REGNUM) {
+ long reg_val[2];
+
+ /* Why is the value not passed through "extract_signed_integer"
+ as in "pa_print_registers" below? */
+ pa_register_look_aside(raw_regs, regnum, &reg_val[0]);
+
+ if(!is_pa_2) {
+ printf_unfiltered ("%s %x\n", REGISTER_NAME (regnum), reg_val[1]);
+ }
+ else {
+ /* Fancy % formats to prevent leading zeros. */
+ if(reg_val[0] == 0)
+ printf_unfiltered("%s %x\n", REGISTER_NAME (regnum), reg_val[1]);
+ else
+ printf_unfiltered("%s %x%8.8x\n", REGISTER_NAME (regnum),
+ reg_val[0], reg_val[1]);
+ }
+ }
+ else
+ /* Note that real floating point values only start at
+ FP4_REGNUM. FP0 and up are just status and error
+ registers, which have integral (bit) values. */
+ pa_print_fp_reg (regnum);
+}
+
+/********** new function ********************/
+void
+pa_do_strcat_registers_info (regnum, fpregs, stream, precision)
+ int regnum;
+ int fpregs;
+ GDB_FILE *stream;
+ enum precision_type precision;
+{
+ char raw_regs [REGISTER_BYTES];
+ int i;
+
+ /* Make a copy of gdb's save area (may cause actual
+ reads from the target). */
+ for (i = 0; i < NUM_REGS; i++)
+ read_relative_register_raw_bytes (i, raw_regs + REGISTER_BYTE (i));
+
+ if (regnum == -1)
+ pa_strcat_registers (raw_regs, regnum, fpregs, stream);
+
+ else if (regnum < FP4_REGNUM) {
+ long reg_val[2];
+
+ /* Why is the value not passed through "extract_signed_integer"
+ as in "pa_print_registers" below? */
+ pa_register_look_aside(raw_regs, regnum, &reg_val[0]);
+
+ if(!is_pa_2) {
+ fprintf_unfiltered (stream, "%s %x", REGISTER_NAME (regnum), reg_val[1]);
+ }
+ else {
+ /* Fancy % formats to prevent leading zeros. */
+ if(reg_val[0] == 0)
+ fprintf_unfiltered(stream, "%s %x", REGISTER_NAME (regnum),
+ reg_val[1]);
+ else
+ fprintf_unfiltered(stream, "%s %x%8.8x", REGISTER_NAME (regnum),
+ reg_val[0], reg_val[1]);
+ }
+ }
+ else
+ /* Note that real floating point values only start at
+ FP4_REGNUM. FP0 and up are just status and error
+ registers, which have integral (bit) values. */
+ pa_strcat_fp_reg (regnum, stream, precision);
+}
+
+/* If this is a PA2.0 machine, fetch the real 64-bit register
+ value. Otherwise use the info from gdb's saved register area.
+
+ Note that reg_val is really expected to be an array of longs,
+ with two elements. */
+static void
+pa_register_look_aside(raw_regs, regnum, raw_val)
+ char *raw_regs;
+ int regnum;
+ long *raw_val;
+{
+ static int know_which = 0; /* False */
+
+ int regaddr;
+ unsigned int offset;
+ register int i;
+ int start;
+
+
+ char buf[MAX_REGISTER_RAW_SIZE];
+ long long reg_val;
+
+ if(!know_which) {
+ if(CPU_PA_RISC2_0 == sysconf(_SC_CPU_VERSION)) {
+ is_pa_2 = (1==1);
+ }
+
+ know_which = 1; /* True */
+ }
+
+ raw_val[0] = 0;
+ raw_val[1] = 0;
+
+ if(!is_pa_2) {
+ raw_val[1] = *(long *)(raw_regs + REGISTER_BYTE(regnum));
+ return;
+ }
+
+ /* Code below copied from hppah-nat.c, with fixes for wide
+ registers, using different area of save_state, etc. */
+ if (regnum == FLAGS_REGNUM || regnum >= FP0_REGNUM ||
+ !HAVE_STRUCT_SAVE_STATE_T || !HAVE_STRUCT_MEMBER_SS_WIDE) {
+ /* Use narrow regs area of save_state and default macro. */
+ offset = U_REGS_OFFSET;
+ regaddr = register_addr(regnum, offset);
+ start = 1;
+ }
+ else {
+ /* Use wide regs area, and calculate registers as 8 bytes wide.
+
+ We'd like to do this, but current version of "C" doesn't
+ permit "offsetof":
+
+ offset = offsetof(save_state_t, ss_wide);
+
+ Note that to avoid "C" doing typed pointer arithmetic, we
+ have to cast away the type in our offset calculation:
+ otherwise we get an offset of 1! */
+
+ /* #if the following code out so that this file can still be
+ compiled on older HPUX boxes (< 10.20) which don't have
+ this structure/structure member. */
+#if HAVE_STRUCT_SAVE_STATE_T == 1 && HAVE_STRUCT_MEMBER_SS_WIDE == 1
+ save_state_t temp;
+
+ offset = ((int) &temp.ss_wide) - ((int) &temp);
+ regaddr = offset + regnum * 8;
+ start = 0;
+#endif
+ }
+
+ for(i = start; i < 2; i++)
+ {
+ errno = 0;
+ raw_val[i] = call_ptrace (PT_RUREGS, inferior_pid,
+ (PTRACE_ARG3_TYPE) regaddr, 0);
+ if (errno != 0)
+ {
+ /* Warning, not error, in case we are attached; sometimes the
+ kernel doesn't let us at the registers. */
+ char *err = safe_strerror (errno);
+ char *msg = alloca (strlen (err) + 128);
+ sprintf (msg, "reading register %s: %s", REGISTER_NAME (regnum), err);
+ warning (msg);
+ goto error_exit;
+ }
+
+ regaddr += sizeof (long);
+ }
+
+ if (regnum == PCOQ_HEAD_REGNUM || regnum == PCOQ_TAIL_REGNUM)
+ raw_val[1] &= ~0x3; /* I think we're masking out space bits */
+
+error_exit:
+ ;
+}
+
+/* "Info all-reg" command */
+
+static void
+pa_print_registers (raw_regs, regnum, fpregs)
+ char *raw_regs;
+ int regnum;
+ int fpregs;
+{
+ int i,j;
+ long raw_val[2]; /* Alas, we are compiled so that "long long" is 32 bits */
+ long long_val;
+
+ for (i = 0; i < 18; i++)
+ {
+ for (j = 0; j < 4; j++)
+ {
+ /* Q: Why is the value passed through "extract_signed_integer",
+ while above, in "pa_do_registers_info" it isn't?
+ A: ? */
+ pa_register_look_aside(raw_regs, i+(j*18), &raw_val[0]);
+
+ /* Even fancier % formats to prevent leading zeros
+ and still maintain the output in columns. */
+ if(!is_pa_2) {
+ /* Being big-endian, on this machine the low bits
+ (the ones we want to look at) are in the second longword. */
+ long_val = extract_signed_integer (&raw_val[1], 4);
+ printf_filtered ("%8.8s: %8x ",
+ REGISTER_NAME (i+(j*18)), long_val);
+ }
+ else {
+ /* raw_val = extract_signed_integer(&raw_val, 8); */
+ if(raw_val[0] == 0)
+ printf_filtered("%8.8s: %8x ",
+ REGISTER_NAME (i+(j*18)), raw_val[1]);
+ else
+ printf_filtered("%8.8s: %8x%8.8x ", REGISTER_NAME (i+(j*18)),
+ raw_val[0], raw_val[1]);
+ }
+ }
+ printf_unfiltered ("\n");
+ }
+
+ if (fpregs)
+ for (i = FP4_REGNUM; i < NUM_REGS; i++) /* FP4_REGNUM == 72 */
+ pa_print_fp_reg (i);
+}
+
+/************* new function ******************/
+static void
+pa_strcat_registers (raw_regs, regnum, fpregs, stream)
+ char *raw_regs;
+ int regnum;
+ int fpregs;
+ GDB_FILE *stream;
+{
+ int i,j;
+ long raw_val[2]; /* Alas, we are compiled so that "long long" is 32 bits */
+ long long_val;
+ enum precision_type precision;
+
+ precision = unspecified_precision;
+
+ for (i = 0; i < 18; i++)
+ {
+ for (j = 0; j < 4; j++)
+ {
+ /* Q: Why is the value passed through "extract_signed_integer",
+ while above, in "pa_do_registers_info" it isn't?
+ A: ? */
+ pa_register_look_aside(raw_regs, i+(j*18), &raw_val[0]);
+
+ /* Even fancier % formats to prevent leading zeros
+ and still maintain the output in columns. */
+ if(!is_pa_2) {
+ /* Being big-endian, on this machine the low bits
+ (the ones we want to look at) are in the second longword. */
+ long_val = extract_signed_integer(&raw_val[1], 4);
+ fprintf_filtered (stream, "%8.8s: %8x ", REGISTER_NAME (i+(j*18)), long_val);
+ }
+ else {
+ /* raw_val = extract_signed_integer(&raw_val, 8); */
+ if(raw_val[0] == 0)
+ fprintf_filtered(stream, "%8.8s: %8x ", REGISTER_NAME (i+(j*18)),
+ raw_val[1]);
+ else
+ fprintf_filtered(stream, "%8.8s: %8x%8.8x ", REGISTER_NAME (i+(j*18)),
+ raw_val[0], raw_val[1]);
+ }
+ }
+ fprintf_unfiltered (stream, "\n");
+ }
+
+ if (fpregs)
+ for (i = FP4_REGNUM; i < NUM_REGS; i++) /* FP4_REGNUM == 72 */
+ pa_strcat_fp_reg (i, stream, precision);
+}
+
+static void
+pa_print_fp_reg (i)
+ int i;
+{
+ char raw_buffer[MAX_REGISTER_RAW_SIZE];
+ char virtual_buffer[MAX_REGISTER_VIRTUAL_SIZE];
+
+ /* Get 32bits of data. */
+ read_relative_register_raw_bytes (i, raw_buffer);
+
+ /* Put it in the buffer. No conversions are ever necessary. */
+ memcpy (virtual_buffer, raw_buffer, REGISTER_RAW_SIZE (i));
+
+ fputs_filtered (REGISTER_NAME (i), gdb_stdout);
+ print_spaces_filtered (8 - strlen (REGISTER_NAME (i)), gdb_stdout);
+ fputs_filtered ("(single precision) ", gdb_stdout);
+
+ val_print (REGISTER_VIRTUAL_TYPE (i), virtual_buffer, 0, 0, gdb_stdout, 0,
+ 1, 0, Val_pretty_default);
+ printf_filtered ("\n");
+
+ /* If "i" is even, then this register can also be a double-precision
+ FP register. Dump it out as such. */
+ if ((i % 2) == 0)
+ {
+ /* Get the data in raw format for the 2nd half. */
+ read_relative_register_raw_bytes (i + 1, raw_buffer);
+
+ /* Copy it into the appropriate part of the virtual buffer. */
+ memcpy (virtual_buffer + REGISTER_RAW_SIZE (i), raw_buffer,
+ REGISTER_RAW_SIZE (i));
+
+ /* Dump it as a double. */
+ fputs_filtered (REGISTER_NAME (i), gdb_stdout);
+ print_spaces_filtered (8 - strlen (REGISTER_NAME (i)), gdb_stdout);
+ fputs_filtered ("(double precision) ", gdb_stdout);
+
+ val_print (builtin_type_double, virtual_buffer, 0, 0, gdb_stdout, 0,
+ 1, 0, Val_pretty_default);
+ printf_filtered ("\n");
+ }
+}
+
+/*************** new function ***********************/
+static void
+pa_strcat_fp_reg (i, stream, precision)
+ int i;
+ GDB_FILE *stream;
+ enum precision_type precision;
+{
+ char raw_buffer[MAX_REGISTER_RAW_SIZE];
+ char virtual_buffer[MAX_REGISTER_VIRTUAL_SIZE];
+
+ fputs_filtered (REGISTER_NAME (i), stream);
+ print_spaces_filtered (8 - strlen (REGISTER_NAME (i)), stream);
+
+ /* Get 32bits of data. */
+ read_relative_register_raw_bytes (i, raw_buffer);
+
+ /* Put it in the buffer. No conversions are ever necessary. */
+ memcpy (virtual_buffer, raw_buffer, REGISTER_RAW_SIZE (i));
+
+ if (precision == double_precision && (i % 2) == 0)
+ {
+
+ char raw_buf[MAX_REGISTER_RAW_SIZE];
+
+ /* Get the data in raw format for the 2nd half. */
+ read_relative_register_raw_bytes (i + 1, raw_buf);
+
+ /* Copy it into the appropriate part of the virtual buffer. */
+ memcpy (virtual_buffer + REGISTER_RAW_SIZE(i), raw_buf, REGISTER_RAW_SIZE (i));
+
+ val_print (builtin_type_double, virtual_buffer, 0, 0 , stream, 0,
+ 1, 0, Val_pretty_default);
+
+ }
+ else {
+ val_print (REGISTER_VIRTUAL_TYPE (i), virtual_buffer, 0, 0, stream, 0,
+ 1, 0, Val_pretty_default);
+ }
+
+}
+
+/* Return one if PC is in the call path of a trampoline, else return zero.
+
+ Note we return one for *any* call trampoline (long-call, arg-reloc), not
+ just shared library trampolines (import, export). */
+
+int
+in_solib_call_trampoline (pc, name)
+ CORE_ADDR pc;
+ char *name;
+{
+ struct minimal_symbol *minsym;
+ struct unwind_table_entry *u;
+ static CORE_ADDR dyncall = 0;
+ static CORE_ADDR sr4export = 0;
+
+/* FIXME XXX - dyncall and sr4export must be initialized whenever we get a
+ new exec file */
+
+ /* First see if PC is in one of the two C-library trampolines. */
+ if (!dyncall)
+ {
+ minsym = lookup_minimal_symbol ("$$dyncall", NULL, NULL);
+ if (minsym)
+ dyncall = SYMBOL_VALUE_ADDRESS (minsym);
+ else
+ dyncall = -1;
+ }
+
+ if (!sr4export)
+ {
+ minsym = lookup_minimal_symbol ("_sr4export", NULL, NULL);
+ if (minsym)
+ sr4export = SYMBOL_VALUE_ADDRESS (minsym);
+ else
+ sr4export = -1;
+ }
+
+ if (pc == dyncall || pc == sr4export)
+ return 1;
+
+ /* Get the unwind descriptor corresponding to PC, return zero
+ if no unwind was found. */
+ u = find_unwind_entry (pc);
+ if (!u)
+ return 0;
+
+ /* If this isn't a linker stub, then return now. */
+ if (u->stub_unwind.stub_type == 0)
+ return 0;
+
+ /* By definition a long-branch stub is a call stub. */
+ if (u->stub_unwind.stub_type == LONG_BRANCH)
+ return 1;
+
+ /* The call and return path execute the same instructions within
+ an IMPORT stub! So an IMPORT stub is both a call and return
+ trampoline. */
+ if (u->stub_unwind.stub_type == IMPORT)
+ return 1;
+
+ /* Parameter relocation stubs always have a call path and may have a
+ return path. */
+ if (u->stub_unwind.stub_type == PARAMETER_RELOCATION
+ || u->stub_unwind.stub_type == EXPORT)
+ {
+ CORE_ADDR addr;
+
+ /* Search forward from the current PC until we hit a branch
+ or the end of the stub. */
+ for (addr = pc; addr <= u->region_end; addr += 4)
+ {
+ unsigned long insn;
+
+ insn = read_memory_integer (addr, 4);
+
+ /* Does it look like a bl? If so then it's the call path, if
+ we find a bv or be first, then we're on the return path. */
+ if ((insn & 0xfc00e000) == 0xe8000000)
+ return 1;
+ else if ((insn & 0xfc00e001) == 0xe800c000
+ || (insn & 0xfc000000) == 0xe0000000)
+ return 0;
+ }
+
+ /* Should never happen. */
+ warning ("Unable to find branch in parameter relocation stub.\n"); /* purecov: deadcode */
+ return 0; /* purecov: deadcode */
+ }
+
+ /* Unknown stub type. For now, just return zero. */
+ return 0; /* purecov: deadcode */
+}
+
+/* Return one if PC is in the return path of a trampoline, else return zero.
+
+ Note we return one for *any* call trampoline (long-call, arg-reloc), not
+ just shared library trampolines (import, export). */
+
+int
+in_solib_return_trampoline (pc, name)
+ CORE_ADDR pc;
+ char *name;
+{
+ struct unwind_table_entry *u;
+
+ /* Get the unwind descriptor corresponding to PC, return zero
+ if no unwind was found. */
+ u = find_unwind_entry (pc);
+ if (!u)
+ return 0;
+
+ /* If this isn't a linker stub or it's just a long branch stub, then
+ return zero. */
+ if (u->stub_unwind.stub_type == 0 || u->stub_unwind.stub_type == LONG_BRANCH)
+ return 0;
+
+ /* The call and return path execute the same instructions within
+ an IMPORT stub! So an IMPORT stub is both a call and return
+ trampoline. */
+ if (u->stub_unwind.stub_type == IMPORT)
+ return 1;
+
+ /* Parameter relocation stubs always have a call path and may have a
+ return path. */
+ if (u->stub_unwind.stub_type == PARAMETER_RELOCATION
+ || u->stub_unwind.stub_type == EXPORT)
+ {
+ CORE_ADDR addr;
+
+ /* Search forward from the current PC until we hit a branch
+ or the end of the stub. */
+ for (addr = pc; addr <= u->region_end; addr += 4)
+ {
+ unsigned long insn;
+
+ insn = read_memory_integer (addr, 4);
+
+ /* Does it look like a bl? If so then it's the call path, if
+ we find a bv or be first, then we're on the return path. */
+ if ((insn & 0xfc00e000) == 0xe8000000)
+ return 0;
+ else if ((insn & 0xfc00e001) == 0xe800c000
+ || (insn & 0xfc000000) == 0xe0000000)
+ return 1;
+ }
+
+ /* Should never happen. */
+ warning ("Unable to find branch in parameter relocation stub.\n"); /* purecov: deadcode */
+ return 0; /* purecov: deadcode */
+ }
+
+ /* Unknown stub type. For now, just return zero. */
+ return 0; /* purecov: deadcode */
+
+}
+
+/* Figure out if PC is in a trampoline, and if so find out where
+ the trampoline will jump to. If not in a trampoline, return zero.
+
+ Simple code examination probably is not a good idea since the code
+ sequences in trampolines can also appear in user code.
+
+ We use unwinds and information from the minimal symbol table to
+ determine when we're in a trampoline. This won't work for ELF
+ (yet) since it doesn't create stub unwind entries. Whether or
+ not ELF will create stub unwinds or normal unwinds for linker
+ stubs is still being debated.
+
+ This should handle simple calls through dyncall or sr4export,
+ long calls, argument relocation stubs, and dyncall/sr4export
+ calling an argument relocation stub. It even handles some stubs
+ used in dynamic executables. */
+
+# if 0
+CORE_ADDR
+skip_trampoline_code (pc, name)
+ CORE_ADDR pc;
+ char *name;
+{
+ return find_solib_trampoline_target(pc);
+}
+
+#endif
+
+CORE_ADDR
+skip_trampoline_code (pc, name)
+ CORE_ADDR pc;
+ char *name;
+{
+ long orig_pc = pc;
+ long prev_inst, curr_inst, loc;
+ static CORE_ADDR dyncall = 0;
+ static CORE_ADDR dyncall_external = 0;
+ static CORE_ADDR sr4export = 0;
+ struct minimal_symbol *msym;
+ struct unwind_table_entry *u;
+
+
+/* FIXME XXX - dyncall and sr4export must be initialized whenever we get a
+ new exec file */
+
+ if (!dyncall)
+ {
+ msym = lookup_minimal_symbol ("$$dyncall", NULL, NULL);
+ if (msym)
+ dyncall = SYMBOL_VALUE_ADDRESS (msym);
+ else
+ dyncall = -1;
+ }
+
+ if (!dyncall_external)
+ {
+ msym = lookup_minimal_symbol ("$$dyncall_external", NULL, NULL);
+ if (msym)
+ dyncall_external = SYMBOL_VALUE_ADDRESS (msym);
+ else
+ dyncall_external = -1;
+ }
+
+ if (!sr4export)
+ {
+ msym = lookup_minimal_symbol ("_sr4export", NULL, NULL);
+ if (msym)
+ sr4export = SYMBOL_VALUE_ADDRESS (msym);
+ else
+ sr4export = -1;
+ }
+
+ /* Addresses passed to dyncall may *NOT* be the actual address
+ of the function. So we may have to do something special. */
+ if (pc == dyncall)
+ {
+ pc = (CORE_ADDR) read_register (22);
+
+ /* If bit 30 (counting from the left) is on, then pc is the address of
+ the PLT entry for this function, not the address of the function
+ itself. Bit 31 has meaning too, but only for MPE. */
+ if (pc & 0x2)
+ pc = (CORE_ADDR) read_memory_integer (pc & ~0x3, 4);
+ }
+ if (pc == dyncall_external)
+ {
+ pc = (CORE_ADDR) read_register (22);
+ pc = (CORE_ADDR) read_memory_integer (pc & ~0x3, 4);
+ }
+ else if (pc == sr4export)
+ pc = (CORE_ADDR) (read_register (22));
+
+ /* Get the unwind descriptor corresponding to PC, return zero
+ if no unwind was found. */
+ u = find_unwind_entry (pc);
+ if (!u)
+ return 0;
+
+ /* If this isn't a linker stub, then return now. */
+ /* elz: attention here! (FIXME) because of a compiler/linker
+ error, some stubs which should have a non zero stub_unwind.stub_type
+ have unfortunately a value of zero. So this function would return here
+ as if we were not in a trampoline. To fix this, we go look at the partial
+ symbol information, which reports this guy as a stub.
+ (FIXME): Unfortunately, we are not that lucky: it turns out that the
+ partial symbol information is also wrong sometimes. This is because
+ when it is entered (somread.c::som_symtab_read()) it can happen that
+ if the type of the symbol (from the som) is Entry, and the symbol is
+ in a shared library, then it can also be a trampoline. This would
+ be OK, except that I believe the way they decide if we are ina shared library
+ does not work. SOOOO..., even if we have a regular function w/o trampolines
+ its minimal symbol can be assigned type mst_solib_trampoline.
+ Also, if we find that the symbol is a real stub, then we fix the unwind
+ descriptor, and define the stub type to be EXPORT.
+ Hopefully this is correct most of the times. */
+ if (u->stub_unwind.stub_type == 0)
+ {
+
+/* elz: NOTE (FIXME!) once the problem with the unwind information is fixed
+ we can delete all the code which appears between the lines */
+/*--------------------------------------------------------------------------*/
+ msym = lookup_minimal_symbol_by_pc (pc);
+
+ if (msym == NULL || MSYMBOL_TYPE (msym) != mst_solib_trampoline)
+ return orig_pc == pc ? 0 : pc & ~0x3;
+
+ else if (msym != NULL && MSYMBOL_TYPE (msym) == mst_solib_trampoline)
+ {
+ struct objfile *objfile;
+ struct minimal_symbol *msymbol;
+ int function_found = 0;
+
+ /* go look if there is another minimal symbol with the same name as
+ this one, but with type mst_text. This would happen if the msym
+ is an actual trampoline, in which case there would be another
+ symbol with the same name corresponding to the real function */
+
+ ALL_MSYMBOLS (objfile, msymbol)
+ {
+ if (MSYMBOL_TYPE (msymbol) == mst_text
+ && STREQ (SYMBOL_NAME (msymbol) , SYMBOL_NAME (msym)))
+ {
+ function_found = 1;
+ break;
+ }
+ }
+
+ if (function_found)
+ /* the type of msym is correct (mst_solib_trampoline), but
+ the unwind info is wrong, so set it to the correct value */
+ u->stub_unwind.stub_type = EXPORT;
+ else
+ /* the stub type info in the unwind is correct (this is not a
+ trampoline), but the msym type information is wrong, it
+ should be mst_text. So we need to fix the msym, and also
+ get out of this function */
+ {
+ MSYMBOL_TYPE (msym) = mst_text;
+ return orig_pc == pc ? 0 : pc & ~0x3;
+ }
+ }
+
+/*--------------------------------------------------------------------------*/
+ }
+
+ /* It's a stub. Search for a branch and figure out where it goes.
+ Note we have to handle multi insn branch sequences like ldil;ble.
+ Most (all?) other branches can be determined by examining the contents
+ of certain registers and the stack. */
+
+ loc = pc;
+ curr_inst = 0;
+ prev_inst = 0;
+ while (1)
+ {
+ /* Make sure we haven't walked outside the range of this stub. */
+ if (u != find_unwind_entry (loc))
+ {
+ warning ("Unable to find branch in linker stub");
+ return orig_pc == pc ? 0 : pc & ~0x3;
+ }
+
+ prev_inst = curr_inst;
+ curr_inst = read_memory_integer (loc, 4);
+
+ /* Does it look like a branch external using %r1? Then it's the
+ branch from the stub to the actual function. */
+ if ((curr_inst & 0xffe0e000) == 0xe0202000)
+ {
+ /* Yup. See if the previous instruction loaded
+ a value into %r1. If so compute and return the jump address. */
+ if ((prev_inst & 0xffe00000) == 0x20200000)
+ return (extract_21 (prev_inst) + extract_17 (curr_inst)) & ~0x3;
+ else
+ {
+ warning ("Unable to find ldil X,%%r1 before ble Y(%%sr4,%%r1).");
+ return orig_pc == pc ? 0 : pc & ~0x3;
+ }
+ }
+
+ /* Does it look like a be 0(sr0,%r21)? OR
+ Does it look like a be, n 0(sr0,%r21)? OR
+ Does it look like a bve (r21)? (this is on PA2.0)
+ Does it look like a bve, n(r21)? (this is also on PA2.0)
+ That's the branch from an
+ import stub to an export stub.
+
+ It is impossible to determine the target of the branch via
+ simple examination of instructions and/or data (consider
+ that the address in the plabel may be the address of the
+ bind-on-reference routine in the dynamic loader).
+
+ So we have try an alternative approach.
+
+ Get the name of the symbol at our current location; it should
+ be a stub symbol with the same name as the symbol in the
+ shared library.
+
+ Then lookup a minimal symbol with the same name; we should
+ get the minimal symbol for the target routine in the shared
+ library as those take precedence of import/export stubs. */
+ if ((curr_inst == 0xe2a00000) ||
+ (curr_inst == 0xe2a00002) ||
+ (curr_inst == 0xeaa0d000) ||
+ (curr_inst == 0xeaa0d002))
+ {
+ struct minimal_symbol *stubsym, *libsym;
+
+ stubsym = lookup_minimal_symbol_by_pc (loc);
+ if (stubsym == NULL)
+ {
+ warning ("Unable to find symbol for 0x%x", loc);
+ return orig_pc == pc ? 0 : pc & ~0x3;
+ }
+
+ libsym = lookup_minimal_symbol (SYMBOL_NAME (stubsym), NULL, NULL);
+ if (libsym == NULL)
+ {
+ warning ("Unable to find library symbol for %s\n",
+ SYMBOL_NAME (stubsym));
+ return orig_pc == pc ? 0 : pc & ~0x3;
+ }
+
+ return SYMBOL_VALUE (libsym);
+ }
+
+ /* Does it look like bl X,%rp or bl X,%r0? Another way to do a
+ branch from the stub to the actual function. */
+ /*elz*/
+ else if ((curr_inst & 0xffe0e000) == 0xe8400000
+ || (curr_inst & 0xffe0e000) == 0xe8000000
+ || (curr_inst & 0xffe0e000) == 0xe800A000)
+ return (loc + extract_17 (curr_inst) + 8) & ~0x3;
+
+ /* Does it look like bv (rp)? Note this depends on the
+ current stack pointer being the same as the stack
+ pointer in the stub itself! This is a branch on from the
+ stub back to the original caller. */
+ /*else if ((curr_inst & 0xffe0e000) == 0xe840c000)*/
+ else if ((curr_inst & 0xffe0f000) == 0xe840c000)
+ {
+ /* Yup. See if the previous instruction loaded
+ rp from sp - 8. */
+ if (prev_inst == 0x4bc23ff1)
+ return (read_memory_integer
+ (read_register (SP_REGNUM) - 8, 4)) & ~0x3;
+ else
+ {
+ warning ("Unable to find restore of %%rp before bv (%%rp).");
+ return orig_pc == pc ? 0 : pc & ~0x3;
+ }
+ }
+
+ /* elz: added this case to capture the new instruction
+ at the end of the return part of an export stub used by
+ the PA2.0: BVE, n (rp) */
+ else if ((curr_inst & 0xffe0f000) == 0xe840d000)
+ {
+ return (read_memory_integer
+ (read_register (SP_REGNUM) - 24, 4)) & ~0x3;
+ }
+
+ /* What about be,n 0(sr0,%rp)? It's just another way we return to
+ the original caller from the stub. Used in dynamic executables. */
+ else if (curr_inst == 0xe0400002)
+ {
+ /* The value we jump to is sitting in sp - 24. But that's
+ loaded several instructions before the be instruction.
+ I guess we could check for the previous instruction being
+ mtsp %r1,%sr0 if we want to do sanity checking. */
+ return (read_memory_integer
+ (read_register (SP_REGNUM) - 24, 4)) & ~0x3;
+ }
+
+ /* Haven't found the branch yet, but we're still in the stub.
+ Keep looking. */
+ loc += 4;
+ }
+}
+
+
+/* For the given instruction (INST), return any adjustment it makes
+ to the stack pointer or zero for no adjustment.
+
+ This only handles instructions commonly found in prologues. */
+
+static int
+prologue_inst_adjust_sp (inst)
+ unsigned long inst;
+{
+ /* This must persist across calls. */
+ static int save_high21;
+
+ /* The most common way to perform a stack adjustment ldo X(sp),sp */
+ if ((inst & 0xffffc000) == 0x37de0000)
+ return extract_14 (inst);
+
+ /* stwm X,D(sp) */
+ if ((inst & 0xffe00000) == 0x6fc00000)
+ return extract_14 (inst);
+
+ /* addil high21,%r1; ldo low11,(%r1),%r30)
+ save high bits in save_high21 for later use. */
+ if ((inst & 0xffe00000) == 0x28200000)
+ {
+ save_high21 = extract_21 (inst);
+ return 0;
+ }
+
+ if ((inst & 0xffff0000) == 0x343e0000)
+ return save_high21 + extract_14 (inst);
+
+ /* fstws as used by the HP compilers. */
+ if ((inst & 0xffffffe0) == 0x2fd01220)
+ return extract_5_load (inst);
+
+ /* No adjustment. */
+ return 0;
+}
+
+/* Return nonzero if INST is a branch of some kind, else return zero. */
+
+static int
+is_branch (inst)
+ unsigned long inst;
+{
+ switch (inst >> 26)
+ {
+ case 0x20:
+ case 0x21:
+ case 0x22:
+ case 0x23:
+ case 0x28:
+ case 0x29:
+ case 0x2a:
+ case 0x2b:
+ case 0x30:
+ case 0x31:
+ case 0x32:
+ case 0x33:
+ case 0x38:
+ case 0x39:
+ case 0x3a:
+ return 1;
+
+ default:
+ return 0;
+ }
+}
+
+/* Return the register number for a GR which is saved by INST or
+ zero it INST does not save a GR. */
+
+static int
+inst_saves_gr (inst)
+ unsigned long inst;
+{
+ /* Does it look like a stw? */
+ if ((inst >> 26) == 0x1a)
+ return extract_5R_store (inst);
+
+ /* Does it look like a stwm? GCC & HPC may use this in prologues. */
+ if ((inst >> 26) == 0x1b)
+ return extract_5R_store (inst);
+
+ /* Does it look like sth or stb? HPC versions 9.0 and later use these
+ too. */
+ if ((inst >> 26) == 0x19 || (inst >> 26) == 0x18)
+ return extract_5R_store (inst);
+
+ return 0;
+}
+
+/* Return the register number for a FR which is saved by INST or
+ zero it INST does not save a FR.
+
+ Note we only care about full 64bit register stores (that's the only
+ kind of stores the prologue will use).
+
+ FIXME: What about argument stores with the HP compiler in ANSI mode? */
+
+static int
+inst_saves_fr (inst)
+ unsigned long inst;
+{
+ /* is this an FSTDS ?*/
+ if ((inst & 0xfc00dfc0) == 0x2c001200)
+ return extract_5r_store (inst);
+ /* is this an FSTWS ?*/
+ if ((inst & 0xfc00df80) == 0x24001200)
+ return extract_5r_store (inst);
+ return 0;
+}
+
+/* Advance PC across any function entry prologue instructions
+ to reach some "real" code.
+
+ Use information in the unwind table to determine what exactly should
+ be in the prologue. */
+
+
+CORE_ADDR
+skip_prologue_hard_way (pc)
+ CORE_ADDR pc;
+{
+ char buf[4];
+ CORE_ADDR orig_pc = pc;
+ unsigned long inst, stack_remaining, save_gr, save_fr, save_rp, save_sp;
+ unsigned long args_stored, status, i, restart_gr, restart_fr;
+ struct unwind_table_entry *u;
+
+ restart_gr = 0;
+ restart_fr = 0;
+
+restart:
+ u = find_unwind_entry (pc);
+ if (!u)
+ return pc;
+
+ /* If we are not at the beginning of a function, then return now. */
+ if ((pc & ~0x3) != u->region_start)
+ return pc;
+
+ /* This is how much of a frame adjustment we need to account for. */
+ stack_remaining = u->Total_frame_size << 3;
+
+ /* Magic register saves we want to know about. */
+ save_rp = u->Save_RP;
+ save_sp = u->Save_SP;
+
+ /* An indication that args may be stored into the stack. Unfortunately
+ the HPUX compilers tend to set this in cases where no args were
+ stored too!. */
+ args_stored = 1;
+
+ /* Turn the Entry_GR field into a bitmask. */
+ save_gr = 0;
+ for (i = 3; i < u->Entry_GR + 3; i++)
+ {
+ /* Frame pointer gets saved into a special location. */
+ if (u->Save_SP && i == FP_REGNUM)
+ continue;
+
+ save_gr |= (1 << i);
+ }
+ save_gr &= ~restart_gr;
+
+ /* Turn the Entry_FR field into a bitmask too. */
+ save_fr = 0;
+ for (i = 12; i < u->Entry_FR + 12; i++)
+ save_fr |= (1 << i);
+ save_fr &= ~restart_fr;
+
+ /* Loop until we find everything of interest or hit a branch.
+
+ For unoptimized GCC code and for any HP CC code this will never ever
+ examine any user instructions.
+
+ For optimzied GCC code we're faced with problems. GCC will schedule
+ its prologue and make prologue instructions available for delay slot
+ filling. The end result is user code gets mixed in with the prologue
+ and a prologue instruction may be in the delay slot of the first branch
+ or call.
+
+ Some unexpected things are expected with debugging optimized code, so
+ we allow this routine to walk past user instructions in optimized
+ GCC code. */
+ while (save_gr || save_fr || save_rp || save_sp || stack_remaining > 0
+ || args_stored)
+ {
+ unsigned int reg_num;
+ unsigned long old_stack_remaining, old_save_gr, old_save_fr;
+ unsigned long old_save_rp, old_save_sp, next_inst;
+
+ /* Save copies of all the triggers so we can compare them later
+ (only for HPC). */
+ old_save_gr = save_gr;
+ old_save_fr = save_fr;
+ old_save_rp = save_rp;
+ old_save_sp = save_sp;
+ old_stack_remaining = stack_remaining;
+
+ status = target_read_memory (pc, buf, 4);
+ inst = extract_unsigned_integer (buf, 4);
+
+ /* Yow! */
+ if (status != 0)
+ return pc;
+
+ /* Note the interesting effects of this instruction. */
+ stack_remaining -= prologue_inst_adjust_sp (inst);
+
+ /* There is only one instruction used for saving RP into the stack. */
+ if (inst == 0x6bc23fd9)
+ save_rp = 0;
+
+ /* This is the only way we save SP into the stack. At this time
+ the HP compilers never bother to save SP into the stack. */
+ if ((inst & 0xffffc000) == 0x6fc10000)
+ save_sp = 0;
+
+ /* Account for general and floating-point register saves. */
+ reg_num = inst_saves_gr (inst);
+ save_gr &= ~(1 << reg_num);
+
+ /* Ugh. Also account for argument stores into the stack.
+ Unfortunately args_stored only tells us that some arguments
+ where stored into the stack. Not how many or what kind!
+
+ This is a kludge as on the HP compiler sets this bit and it
+ never does prologue scheduling. So once we see one, skip past
+ all of them. We have similar code for the fp arg stores below.
+
+ FIXME. Can still die if we have a mix of GR and FR argument
+ stores! */
+ if (reg_num >= 23 && reg_num <= 26)
+ {
+ while (reg_num >= 23 && reg_num <= 26)
+ {
+ pc += 4;
+ status = target_read_memory (pc, buf, 4);
+ inst = extract_unsigned_integer (buf, 4);
+ if (status != 0)
+ return pc;
+ reg_num = inst_saves_gr (inst);
+ }
+ args_stored = 0;
+ continue;
+ }
+
+ reg_num = inst_saves_fr (inst);
+ save_fr &= ~(1 << reg_num);
+
+ status = target_read_memory (pc + 4, buf, 4);
+ next_inst = extract_unsigned_integer (buf, 4);
+
+ /* Yow! */
+ if (status != 0)
+ return pc;
+
+ /* We've got to be read to handle the ldo before the fp register
+ save. */
+ if ((inst & 0xfc000000) == 0x34000000
+ && inst_saves_fr (next_inst) >= 4
+ && inst_saves_fr (next_inst) <= 7)
+ {
+ /* So we drop into the code below in a reasonable state. */
+ reg_num = inst_saves_fr (next_inst);
+ pc -= 4;
+ }
+
+ /* Ugh. Also account for argument stores into the stack.
+ This is a kludge as on the HP compiler sets this bit and it
+ never does prologue scheduling. So once we see one, skip past
+ all of them. */
+ if (reg_num >= 4 && reg_num <= 7)
+ {
+ while (reg_num >= 4 && reg_num <= 7)
+ {
+ pc += 8;
+ status = target_read_memory (pc, buf, 4);
+ inst = extract_unsigned_integer (buf, 4);
+ if (status != 0)
+ return pc;
+ if ((inst & 0xfc000000) != 0x34000000)
+ break;
+ status = target_read_memory (pc + 4, buf, 4);
+ next_inst = extract_unsigned_integer (buf, 4);
+ if (status != 0)
+ return pc;
+ reg_num = inst_saves_fr (next_inst);
+ }
+ args_stored = 0;
+ continue;
+ }
+
+ /* Quit if we hit any kind of branch. This can happen if a prologue
+ instruction is in the delay slot of the first call/branch. */
+ if (is_branch (inst))
+ break;
+
+ /* What a crock. The HP compilers set args_stored even if no
+ arguments were stored into the stack (boo hiss). This could
+ cause this code to then skip a bunch of user insns (up to the
+ first branch).
+
+ To combat this we try to identify when args_stored was bogusly
+ set and clear it. We only do this when args_stored is nonzero,
+ all other resources are accounted for, and nothing changed on
+ this pass. */
+ if (args_stored
+ && ! (save_gr || save_fr || save_rp || save_sp || stack_remaining > 0)
+ && old_save_gr == save_gr && old_save_fr == save_fr
+ && old_save_rp == save_rp && old_save_sp == save_sp
+ && old_stack_remaining == stack_remaining)
+ break;
+
+ /* Bump the PC. */
+ pc += 4;
+ }
+
+ /* We've got a tenative location for the end of the prologue. However
+ because of limitations in the unwind descriptor mechanism we may
+ have went too far into user code looking for the save of a register
+ that does not exist. So, if there registers we expected to be saved
+ but never were, mask them out and restart.
+
+ This should only happen in optimized code, and should be very rare. */
+ if (save_gr || (save_fr && ! (restart_fr || restart_gr)))
+ {
+ pc = orig_pc;
+ restart_gr = save_gr;
+ restart_fr = save_fr;
+ goto restart;
+ }
+
+ return pc;
+}
+
+
+
+
+
+/* return 0 if we cannot determine the end of the prologue,
+ return the new pc value if we know where the prologue ends */
+
+static CORE_ADDR
+after_prologue (pc)
+ CORE_ADDR pc;
+{
+ struct symtab_and_line sal;
+ CORE_ADDR func_addr, func_end;
+ struct symbol *f;
+
+ if (!find_pc_partial_function (pc, NULL, &func_addr, &func_end))
+ return 0; /* Unknown */
+
+ f = find_pc_function (pc);
+ if (!f)
+ return 0; /* no debug info, do it the hard way! */
+
+ sal = find_pc_line (func_addr, 0);
+
+ if (sal.end < func_end)
+ {
+ /* this happens when the function has no prologue, because the way
+ find_pc_line works: elz. Note: this may not be a very good
+ way to decide whether a function has a prologue or not, but
+ it is the best I can do with the info available
+ Also, this will work for functions like: int f()
+ {
+ return 2;
+ }
+ I.e. the bp will be inserted at the first open brace.
+ For functions where the body is only one line written like this:
+ int f()
+ { return 2; }
+ this will make the breakpoint to be at the last brace, after the body
+ has been executed already. What's the point of stepping through a function
+ without any variables anyway?? */
+
+ if ((SYMBOL_LINE(f) > 0) && (SYMBOL_LINE(f) < sal.line))
+ return pc; /*no adjusment will be made*/
+ else
+ return sal.end; /* this is the end of the prologue */
+ }
+ /* The line after the prologue is after the end of the function. In this
+ case, put the end of the prologue is the beginning of the function. */
+ /* This should happen only when the function is prologueless and has no
+ code in it. For instance void dumb(){} Note: this kind of function
+ is used quite a lot in the test system */
+
+ else return pc; /* no adjustment will be made */
+}
+
+/* To skip prologues, I use this predicate. Returns either PC itself
+ if the code at PC does not look like a function prologue; otherwise
+ returns an address that (if we're lucky) follows the prologue. If
+ LENIENT, then we must skip everything which is involved in setting
+ up the frame (it's OK to skip more, just so long as we don't skip
+ anything which might clobber the registers which are being saved.
+ Currently we must not skip more on the alpha, but we might the lenient
+ stuff some day. */
+
+CORE_ADDR
+skip_prologue (pc)
+ CORE_ADDR pc;
+{
+ unsigned long inst;
+ int offset;
+ CORE_ADDR post_prologue_pc;
+ char buf[4];
+
+#ifdef GDB_TARGET_HAS_SHARED_LIBS
+ /* Silently return the unaltered pc upon memory errors.
+ This could happen on OSF/1 if decode_line_1 tries to skip the
+ prologue for quickstarted shared library functions when the
+ shared library is not yet mapped in.
+ Reading target memory is slow over serial lines, so we perform
+ this check only if the target has shared libraries. */
+ if (target_read_memory (pc, buf, 4))
+ return pc;
+#endif
+
+ /* See if we can determine the end of the prologue via the symbol table.
+ If so, then return either PC, or the PC after the prologue, whichever
+ is greater. */
+
+ post_prologue_pc = after_prologue (pc);
+
+ if (post_prologue_pc != 0)
+ return max (pc, post_prologue_pc);
+
+
+ /* Can't determine prologue from the symbol table, (this can happen if there
+ is no debug information) so we need to fall back on the old code, which
+ looks at the instructions */
+ /* FIXME (elz) !!!!: this may create a problem if, once the bp is hit, the user says
+ where: the backtrace info is not right: this is because the point at which we
+ break is at the very first instruction of the function. At this time the stuff that
+ needs to be saved on the stack, has not been saved yet, so the backtrace
+ cannot know all it needs to know. This will need to be fixed in the
+ actual backtrace code. (Note: this is what DDE does) */
+
+ else
+
+ return (skip_prologue_hard_way(pc));
+
+#if 0
+/* elz: I am keeping this code around just in case, but remember, all the
+ instructions are for alpha: you should change all to the hppa instructions */
+
+ /* Can't determine prologue from the symbol table, need to examine
+ instructions. */
+
+ /* Skip the typical prologue instructions. These are the stack adjustment
+ instruction and the instructions that save registers on the stack
+ or in the gcc frame. */
+ for (offset = 0; offset < 100; offset += 4)
+ {
+ int status;
+
+ status = read_memory_nobpt (pc + offset, buf, 4);
+ if (status)
+ memory_error (status, pc + offset);
+ inst = extract_unsigned_integer (buf, 4);
+
+ /* The alpha has no delay slots. But let's keep the lenient stuff,
+ we might need it for something else in the future. */
+ if (lenient && 0)
+ continue;
+
+ if ((inst & 0xffff0000) == 0x27bb0000) /* ldah $gp,n($t12) */
+ continue;
+ if ((inst & 0xffff0000) == 0x23bd0000) /* lda $gp,n($gp) */
+ continue;
+ if ((inst & 0xffff0000) == 0x23de0000) /* lda $sp,n($sp) */
+ continue;
+ else if ((inst & 0xfc1f0000) == 0xb41e0000
+ && (inst & 0xffff0000) != 0xb7fe0000)
+ continue; /* stq reg,n($sp) */
+ /* reg != $zero */
+ else if ((inst & 0xfc1f0000) == 0x9c1e0000
+ && (inst & 0xffff0000) != 0x9ffe0000)
+ continue; /* stt reg,n($sp) */
+ /* reg != $zero */
+ else if (inst == 0x47de040f) /* bis sp,sp,fp */
+ continue;
+ else
+ break;
+ }
+ return pc + offset;
+#endif /* 0 */
+}
+
+/* Put here the code to store, into a struct frame_saved_regs,
+ the addresses of the saved registers of frame described by FRAME_INFO.
+ This includes special registers such as pc and fp saved in special
+ ways in the stack frame. sp is even more special:
+ the address we return for it IS the sp for the next frame. */
+
+void
+hppa_frame_find_saved_regs (frame_info, frame_saved_regs)
+ struct frame_info *frame_info;
+ struct frame_saved_regs *frame_saved_regs;
+{
+ CORE_ADDR pc;
+ struct unwind_table_entry *u;
+ unsigned long inst, stack_remaining, save_gr, save_fr, save_rp, save_sp;
+ int status, i, reg;
+ char buf[4];
+ int fp_loc = -1;
+
+ /* Zero out everything. */
+ memset (frame_saved_regs, '\0', sizeof (struct frame_saved_regs));
+
+ /* Call dummy frames always look the same, so there's no need to
+ examine the dummy code to determine locations of saved registers;
+ instead, let find_dummy_frame_regs fill in the correct offsets
+ for the saved registers. */
+ if ((frame_info->pc >= frame_info->frame
+ && frame_info->pc <= (frame_info->frame + CALL_DUMMY_LENGTH
+ + 32 * 4 + (NUM_REGS - FP0_REGNUM) * 8
+ + 6 * 4)))
+ find_dummy_frame_regs (frame_info, frame_saved_regs);
+
+ /* Interrupt handlers are special too. They lay out the register
+ state in the exact same order as the register numbers in GDB. */
+ if (pc_in_interrupt_handler (frame_info->pc))
+ {
+ for (i = 0; i < NUM_REGS; i++)
+ {
+ /* SP is a little special. */
+ if (i == SP_REGNUM)
+ frame_saved_regs->regs[SP_REGNUM]
+ = read_memory_integer (frame_info->frame + SP_REGNUM * 4, 4);
+ else
+ frame_saved_regs->regs[i] = frame_info->frame + i * 4;
+ }
+ return;
+ }
+
+#ifdef FRAME_FIND_SAVED_REGS_IN_SIGTRAMP
+ /* Handle signal handler callers. */
+ if (frame_info->signal_handler_caller)
+ {
+ FRAME_FIND_SAVED_REGS_IN_SIGTRAMP (frame_info, frame_saved_regs);
+ return;
+ }
+#endif
+
+ /* Get the starting address of the function referred to by the PC
+ saved in frame. */
+ pc = get_pc_function_start (frame_info->pc);
+
+ /* Yow! */
+ u = find_unwind_entry (pc);
+ if (!u)
+ return;
+
+ /* This is how much of a frame adjustment we need to account for. */
+ stack_remaining = u->Total_frame_size << 3;
+
+ /* Magic register saves we want to know about. */
+ save_rp = u->Save_RP;
+ save_sp = u->Save_SP;
+
+ /* Turn the Entry_GR field into a bitmask. */
+ save_gr = 0;
+ for (i = 3; i < u->Entry_GR + 3; i++)
+ {
+ /* Frame pointer gets saved into a special location. */
+ if (u->Save_SP && i == FP_REGNUM)
+ continue;
+
+ save_gr |= (1 << i);
+ }
+
+ /* Turn the Entry_FR field into a bitmask too. */
+ save_fr = 0;
+ for (i = 12; i < u->Entry_FR + 12; i++)
+ save_fr |= (1 << i);
+
+ /* The frame always represents the value of %sp at entry to the
+ current function (and is thus equivalent to the "saved" stack
+ pointer. */
+ frame_saved_regs->regs[SP_REGNUM] = frame_info->frame;
+
+ /* Loop until we find everything of interest or hit a branch.
+
+ For unoptimized GCC code and for any HP CC code this will never ever
+ examine any user instructions.
+
+ For optimzied GCC code we're faced with problems. GCC will schedule
+ its prologue and make prologue instructions available for delay slot
+ filling. The end result is user code gets mixed in with the prologue
+ and a prologue instruction may be in the delay slot of the first branch
+ or call.
+
+ Some unexpected things are expected with debugging optimized code, so
+ we allow this routine to walk past user instructions in optimized
+ GCC code. */
+ while (save_gr || save_fr || save_rp || save_sp || stack_remaining > 0)
+ {
+ status = target_read_memory (pc, buf, 4);
+ inst = extract_unsigned_integer (buf, 4);
+
+ /* Yow! */
+ if (status != 0)
+ return;
+
+ /* Note the interesting effects of this instruction. */
+ stack_remaining -= prologue_inst_adjust_sp (inst);
+
+ /* There is only one instruction used for saving RP into the stack. */
+ if (inst == 0x6bc23fd9)
+ {
+ save_rp = 0;
+ frame_saved_regs->regs[RP_REGNUM] = frame_info->frame - 20;
+ }
+
+ /* Just note that we found the save of SP into the stack. The
+ value for frame_saved_regs was computed above. */
+ if ((inst & 0xffffc000) == 0x6fc10000)
+ save_sp = 0;
+
+ /* Account for general and floating-point register saves. */
+ reg = inst_saves_gr (inst);
+ if (reg >= 3 && reg <= 18
+ && (!u->Save_SP || reg != FP_REGNUM))
+ {
+ save_gr &= ~(1 << reg);
+
+ /* stwm with a positive displacement is a *post modify*. */
+ if ((inst >> 26) == 0x1b
+ && extract_14 (inst) >= 0)
+ frame_saved_regs->regs[reg] = frame_info->frame;
+ else
+ {
+ /* Handle code with and without frame pointers. */
+ if (u->Save_SP)
+ frame_saved_regs->regs[reg]
+ = frame_info->frame + extract_14 (inst);
+ else
+ frame_saved_regs->regs[reg]
+ = frame_info->frame + (u->Total_frame_size << 3)
+ + extract_14 (inst);
+ }
+ }
+
+
+ /* GCC handles callee saved FP regs a little differently.
+
+ It emits an instruction to put the value of the start of
+ the FP store area into %r1. It then uses fstds,ma with
+ a basereg of %r1 for the stores.
+
+ HP CC emits them at the current stack pointer modifying
+ the stack pointer as it stores each register. */
+
+ /* ldo X(%r3),%r1 or ldo X(%r30),%r1. */
+ if ((inst & 0xffffc000) == 0x34610000
+ || (inst & 0xffffc000) == 0x37c10000)
+ fp_loc = extract_14 (inst);
+
+ reg = inst_saves_fr (inst);
+ if (reg >= 12 && reg <= 21)
+ {
+ /* Note +4 braindamage below is necessary because the FP status
+ registers are internally 8 registers rather than the expected
+ 4 registers. */
+ save_fr &= ~(1 << reg);
+ if (fp_loc == -1)
+ {
+ /* 1st HP CC FP register store. After this instruction
+ we've set enough state that the GCC and HPCC code are
+ both handled in the same manner. */
+ frame_saved_regs->regs[reg + FP4_REGNUM + 4] = frame_info->frame;
+ fp_loc = 8;
+ }
+ else
+ {
+ frame_saved_regs->regs[reg + FP0_REGNUM + 4]
+ = frame_info->frame + fp_loc;
+ fp_loc += 8;
+ }
+ }
+
+ /* Quit if we hit any kind of branch. This can happen if a prologue
+ instruction is in the delay slot of the first call/branch. */
+ if (is_branch (inst))
+ break;
+
+ /* Bump the PC. */
+ pc += 4;
+ }
+}
+
+
+/* Exception handling support for the HP-UX ANSI C++ compiler.
+ The compiler (aCC) provides a callback for exception events;
+ GDB can set a breakpoint on this callback and find out what
+ exception event has occurred. */
+
+/* The name of the hook to be set to point to the callback function */
+static char HP_ACC_EH_notify_hook[] = "__eh_notify_hook";
+/* The name of the function to be used to set the hook value */
+static char HP_ACC_EH_set_hook_value[] = "__eh_set_hook_value";
+/* The name of the callback function in end.o */
+static char HP_ACC_EH_notify_callback[] = "__d_eh_notify_callback";
+/* Name of function in end.o on which a break is set (called by above) */
+static char HP_ACC_EH_break[] = "__d_eh_break";
+/* Name of flag (in end.o) that enables catching throws */
+static char HP_ACC_EH_catch_throw[] = "__d_eh_catch_throw";
+/* Name of flag (in end.o) that enables catching catching */
+static char HP_ACC_EH_catch_catch[] = "__d_eh_catch_catch";
+/* The enum used by aCC */
+typedef enum {
+ __EH_NOTIFY_THROW,
+ __EH_NOTIFY_CATCH
+} __eh_notification;
+
+/* Is exception-handling support available with this executable? */
+static int hp_cxx_exception_support = 0;
+/* Has the initialize function been run? */
+int hp_cxx_exception_support_initialized = 0;
+/* Similar to above, but imported from breakpoint.c -- non-target-specific */
+extern int exception_support_initialized;
+/* Address of __eh_notify_hook */
+static CORE_ADDR eh_notify_hook_addr = NULL;
+/* Address of __d_eh_notify_callback */
+static CORE_ADDR eh_notify_callback_addr = NULL;
+/* Address of __d_eh_break */
+static CORE_ADDR eh_break_addr = NULL;
+/* Address of __d_eh_catch_catch */
+static CORE_ADDR eh_catch_catch_addr = NULL;
+/* Address of __d_eh_catch_throw */
+static CORE_ADDR eh_catch_throw_addr = NULL;
+/* Sal for __d_eh_break */
+static struct symtab_and_line * break_callback_sal = NULL;
+
+/* Code in end.c expects __d_pid to be set in the inferior,
+ otherwise __d_eh_notify_callback doesn't bother to call
+ __d_eh_break! So we poke the pid into this symbol
+ ourselves.
+ 0 => success
+ 1 => failure */
+int
+setup_d_pid_in_inferior ()
+{
+ CORE_ADDR anaddr;
+ struct minimal_symbol * msymbol;
+ char buf[4]; /* FIXME 32x64? */
+
+ /* Slam the pid of the process into __d_pid; failing is only a warning! */
+ msymbol = lookup_minimal_symbol ("__d_pid", NULL, symfile_objfile);
+ if (msymbol == NULL)
+ {
+ warning ("Unable to find __d_pid symbol in object file.");
+ warning ("Suggest linking executable with -g (links in /opt/langtools/lib/end.o).");
+ return 1;
+ }
+
+ anaddr = SYMBOL_VALUE_ADDRESS (msymbol);
+ store_unsigned_integer (buf, 4, inferior_pid); /* FIXME 32x64? */
+ if (target_write_memory (anaddr, buf, 4)) /* FIXME 32x64? */
+ {
+ warning ("Unable to write __d_pid");
+ warning ("Suggest linking executable with -g (links in /opt/langtools/lib/end.o).");
+ return 1;
+ }
+ return 0;
+}
+
+/* Initialize exception catchpoint support by looking for the
+ necessary hooks/callbacks in end.o, etc., and set the hook value to
+ point to the required debug function
+
+ Return 0 => failure
+ 1 => success */
+
+static int
+initialize_hp_cxx_exception_support ()
+{
+ struct symtabs_and_lines sals;
+ struct cleanup * old_chain;
+ struct cleanup * canonical_strings_chain = NULL;
+ int i;
+ char * addr_start;
+ char * addr_end = NULL;
+ char ** canonical = (char **) NULL;
+ int thread = -1;
+ struct symbol * sym = NULL;
+ struct minimal_symbol * msym = NULL;
+ struct objfile * objfile;
+ asection *shlib_info;
+
+ /* Detect and disallow recursion. On HP-UX with aCC, infinite
+ recursion is a possibility because finding the hook for exception
+ callbacks involves making a call in the inferior, which means
+ re-inserting breakpoints which can re-invoke this code */
+
+ static int recurse = 0;
+ if (recurse > 0)
+ {
+ hp_cxx_exception_support_initialized = 0;
+ exception_support_initialized = 0;
+ return 0;
+ }
+
+ hp_cxx_exception_support = 0;
+
+ /* First check if we have seen any HP compiled objects; if not,
+ it is very unlikely that HP's idiosyncratic callback mechanism
+ for exception handling debug support will be available!
+ This will percolate back up to breakpoint.c, where our callers
+ will decide to try the g++ exception-handling support instead. */
+ if (!hp_som_som_object_present)
+ return 0;
+
+ /* We have a SOM executable with SOM debug info; find the hooks */
+
+ /* First look for the notify hook provided by aCC runtime libs */
+ /* If we find this symbol, we conclude that the executable must
+ have HP aCC exception support built in. If this symbol is not
+ found, even though we're a HP SOM-SOM file, we may have been
+ built with some other compiler (not aCC). This results percolates
+ back up to our callers in breakpoint.c which can decide to
+ try the g++ style of exception support instead.
+ If this symbol is found but the other symbols we require are
+ not found, there is something weird going on, and g++ support
+ should *not* be tried as an alternative.
+
+ ASSUMPTION: Only HP aCC code will have __eh_notify_hook defined.
+ ASSUMPTION: HP aCC and g++ modules cannot be linked together. */
+
+ /* libCsup has this hook; it'll usually be non-debuggable */
+ msym = lookup_minimal_symbol (HP_ACC_EH_notify_hook, NULL, NULL);
+ if (msym)
+ {
+ eh_notify_hook_addr = SYMBOL_VALUE_ADDRESS (msym);
+ hp_cxx_exception_support = 1;
+ }
+ else
+ {
+ warning ("Unable to find exception callback hook (%s).", HP_ACC_EH_notify_hook);
+ warning ("Executable may not have been compiled debuggable with HP aCC.");
+ warning ("GDB will be unable to intercept exception events.");
+ eh_notify_hook_addr = 0;
+ hp_cxx_exception_support = 0;
+ return 0;
+ }
+
+#if 0 /* DEBUGGING */
+ printf ("Hook addr found is %lx\n", eh_notify_hook_addr);
+#endif
+
+ /* Next look for the notify callback routine in end.o */
+ /* This is always available in the SOM symbol dictionary if end.o is linked in */
+ msym = lookup_minimal_symbol (HP_ACC_EH_notify_callback, NULL, NULL);
+ if (msym)
+ {
+ eh_notify_callback_addr = SYMBOL_VALUE_ADDRESS (msym);
+ hp_cxx_exception_support = 1;
+ }
+ else
+ {
+ warning ("Unable to find exception callback routine (%s).", HP_ACC_EH_notify_callback);
+ warning ("Suggest linking executable with -g (links in /opt/langtools/lib/end.o).");
+ warning ("GDB will be unable to intercept exception events.");
+ eh_notify_callback_addr = 0;
+ return 0;
+ }
+
+ /* Check whether the executable is dynamically linked or archive bound */
+ /* With an archive-bound executable we can use the raw addresses we find
+ for the callback function, etc. without modification. For an executable
+ with shared libraries, we have to do more work to find the plabel, which
+ can be the target of a call through $$dyncall from the aCC runtime support
+ library (libCsup) which is linked shared by default by aCC. */
+ /* This test below was copied from somsolib.c/somread.c. It may not be a very
+ reliable one to test that an executable is linked shared. pai/1997-07-18 */
+ shlib_info = bfd_get_section_by_name (symfile_objfile->obfd, "$SHLIB_INFO$");
+ if (shlib_info && (bfd_section_size (symfile_objfile->obfd, shlib_info) != 0))
+ {
+ /* The minsym we have has the local code address, but that's not the
+ plabel that can be used by an inter-load-module call. */
+ /* Find solib handle for main image (which has end.o), and use that
+ and the min sym as arguments to __d_shl_get() (which does the equivalent
+ of shl_findsym()) to find the plabel. */
+
+ args_for_find_stub args;
+ static char message[] = "Error while finding exception callback hook:\n";
+
+ args.solib_handle = som_solib_get_solib_by_pc (eh_notify_callback_addr);
+ args.msym = msym;
+
+ recurse++;
+ eh_notify_callback_addr = catch_errors ((int (*) PARAMS ((char *))) cover_find_stub_with_shl_get,
+ (char *) &args,
+ message, RETURN_MASK_ALL);
+ recurse--;
+
+#if 0 /* DEBUGGING */
+ printf ("found plabel for eh notify callback: %x\n", eh_notify_callback_addr);
+#endif
+
+ exception_catchpoints_are_fragile = 1;
+
+ if (!eh_notify_callback_addr)
+ {
+ /* We can get here either if there is no plabel in the export list
+ for the main image, or if something strange happened (??) */
+ warning ("Couldn't find a plabel (indirect function label) for the exception callback.");
+ warning ("GDB will not be able to intercept exception events.");
+ return 0;
+ }
+ }
+ else
+ exception_catchpoints_are_fragile = 0;
+
+#if 0 /* DEBUGGING */
+ printf ("Cb addr found is %lx\n", eh_notify_callback_addr);
+#endif
+
+ /* Now, look for the breakpointable routine in end.o */
+ /* This should also be available in the SOM symbol dict. if end.o linked in */
+ msym = lookup_minimal_symbol (HP_ACC_EH_break, NULL, NULL);
+ if (msym)
+ {
+ eh_break_addr = SYMBOL_VALUE_ADDRESS (msym);
+ hp_cxx_exception_support = 1;
+ }
+ else
+ {
+ warning ("Unable to find exception callback routine to set breakpoint (%s).", HP_ACC_EH_break);
+ warning ("Suggest linking executable with -g (link in /opt/langtools/lib/end.o).");
+ warning ("GDB will be unable to intercept exception events.");
+ eh_break_addr = 0;
+ return 0;
+ }
+
+#if 0 /* DEBUGGING */
+ printf ("break addr found is %lx\n", eh_break_addr);
+#endif
+
+ /* Next look for the catch enable flag provided in end.o */
+ sym = lookup_symbol (HP_ACC_EH_catch_catch, (struct block *) NULL,
+ VAR_NAMESPACE, 0, (struct symtab **) NULL);
+ if (sym) /* sometimes present in debug info */
+ {
+ eh_catch_catch_addr = SYMBOL_VALUE_ADDRESS (sym);
+ hp_cxx_exception_support = 1;
+ }
+ else /* otherwise look in SOM symbol dict. */
+ {
+ msym = lookup_minimal_symbol (HP_ACC_EH_catch_catch, NULL, NULL);
+ if (msym)
+ {
+ eh_catch_catch_addr = SYMBOL_VALUE_ADDRESS (msym);
+ hp_cxx_exception_support = 1;
+ }
+ else
+ {
+ warning ("Unable to enable interception of exception catches.");
+ warning ("Executable may not have been compiled debuggable with HP aCC.");
+ warning ("Suggest linking executable with -g (link in /opt/langtools/lib/end.o).");
+ return 0;
+ }
+ }
+
+#if 0 /* DEBUGGING */
+ printf ("catch catch addr found is %lx\n", eh_catch_catch_addr);
+#endif
+
+ /* Next look for the catch enable flag provided end.o */
+ sym = lookup_symbol (HP_ACC_EH_catch_catch, (struct block *) NULL,
+ VAR_NAMESPACE, 0, (struct symtab **) NULL);
+ if (sym) /* sometimes present in debug info */
+ {
+ eh_catch_throw_addr = SYMBOL_VALUE_ADDRESS (sym);
+ hp_cxx_exception_support = 1;
+ }
+ else /* otherwise look in SOM symbol dict. */
+ {
+ msym = lookup_minimal_symbol (HP_ACC_EH_catch_throw, NULL, NULL);
+ if (msym)
+ {
+ eh_catch_throw_addr = SYMBOL_VALUE_ADDRESS (msym);
+ hp_cxx_exception_support = 1;
+ }
+ else
+ {
+ warning ("Unable to enable interception of exception throws.");
+ warning ("Executable may not have been compiled debuggable with HP aCC.");
+ warning ("Suggest linking executable with -g (link in /opt/langtools/lib/end.o).");
+ return 0;
+ }
+ }
+
+#if 0 /* DEBUGGING */
+ printf ("catch throw addr found is %lx\n", eh_catch_throw_addr);
+#endif
+
+ /* Set the flags */
+ hp_cxx_exception_support = 2; /* everything worked so far */
+ hp_cxx_exception_support_initialized = 1;
+ exception_support_initialized = 1;
+
+ return 1;
+}
+
+/* Target operation for enabling or disabling interception of
+ exception events.
+ KIND is either EX_EVENT_THROW or EX_EVENT_CATCH
+ ENABLE is either 0 (disable) or 1 (enable).
+ Return value is NULL if no support found;
+ -1 if something went wrong,
+ or a pointer to a symtab/line struct if the breakpointable
+ address was found. */
+
+struct symtab_and_line *
+child_enable_exception_callback (kind, enable)
+ enum exception_event_kind kind;
+ int enable;
+{
+ char buf[4];
+
+ if (!exception_support_initialized || !hp_cxx_exception_support_initialized)
+ if (!initialize_hp_cxx_exception_support ())
+ return NULL;
+
+ switch (hp_cxx_exception_support)
+ {
+ case 0:
+ /* Assuming no HP support at all */
+ return NULL;
+ case 1:
+ /* HP support should be present, but something went wrong */
+ return (struct symtab_and_line *) -1; /* yuck! */
+ /* there may be other cases in the future */
+ }
+
+ /* Set the EH hook to point to the callback routine */
+ store_unsigned_integer (buf, 4, enable ? eh_notify_callback_addr : 0); /* FIXME 32x64 problem */
+ /* pai: (temp) FIXME should there be a pack operation first? */
+ if (target_write_memory (eh_notify_hook_addr, buf, 4)) /* FIXME 32x64 problem */
+ {
+ warning ("Could not write to target memory for exception event callback.");
+ warning ("Interception of exception events may not work.");
+ return (struct symtab_and_line *) -1;
+ }
+ if (enable)
+ {
+ /* Ensure that __d_pid is set up correctly -- end.c code checks this. :-(*/
+ if (inferior_pid > 0)
+ {
+ if (setup_d_pid_in_inferior ())
+ return (struct symtab_and_line *) -1;
+ }
+ else
+ {
+ warning ("Internal error: Invalid inferior pid? Cannot intercept exception events."); /* purecov: deadcode */
+ return (struct symtab_and_line *) -1; /* purecov: deadcode */
+ }
+ }
+
+ switch (kind)
+ {
+ case EX_EVENT_THROW:
+ store_unsigned_integer (buf, 4, enable ? 1 : 0);
+ if (target_write_memory (eh_catch_throw_addr, buf, 4)) /* FIXME 32x64? */
+ {
+ warning ("Couldn't enable exception throw interception.");
+ return (struct symtab_and_line *) -1;
+ }
+ break;
+ case EX_EVENT_CATCH:
+ store_unsigned_integer (buf, 4, enable ? 1 : 0);
+ if (target_write_memory (eh_catch_catch_addr, buf, 4)) /* FIXME 32x64? */
+ {
+ warning ("Couldn't enable exception catch interception.");
+ return (struct symtab_and_line *) -1;
+ }
+ break;
+ default: /* purecov: deadcode */
+ error ("Request to enable unknown or unsupported exception event."); /* purecov: deadcode */
+ }
+
+ /* Copy break address into new sal struct, malloc'ing if needed. */
+ if (!break_callback_sal)
+ {
+ break_callback_sal = (struct symtab_and_line *) xmalloc (sizeof (struct symtab_and_line));
+ }
+ INIT_SAL(break_callback_sal);
+ break_callback_sal->symtab = NULL;
+ break_callback_sal->pc = eh_break_addr;
+ break_callback_sal->line = 0;
+ break_callback_sal->end = eh_break_addr;
+
+ return break_callback_sal;
+}
+
+/* Record some information about the current exception event */
+static struct exception_event_record current_ex_event;
+/* Convenience struct */
+static struct symtab_and_line null_symtab_and_line = { NULL, 0, 0, 0 };
+
+/* Report current exception event. Returns a pointer to a record
+ that describes the kind of the event, where it was thrown from,
+ and where it will be caught. More information may be reported
+ in the future */
+struct exception_event_record *
+child_get_current_exception_event ()
+{
+ CORE_ADDR event_kind;
+ CORE_ADDR throw_addr;
+ CORE_ADDR catch_addr;
+ struct frame_info *fi, *curr_frame;
+ int level = 1;
+
+ curr_frame = get_current_frame();
+ if (!curr_frame)
+ return (struct exception_event_record *) NULL;
+
+ /* Go up one frame to __d_eh_notify_callback, because at the
+ point when this code is executed, there's garbage in the
+ arguments of __d_eh_break. */
+ fi = find_relative_frame (curr_frame, &level);
+ if (level != 0)
+ return (struct exception_event_record *) NULL;
+
+ select_frame (fi, -1);
+
+ /* Read in the arguments */
+ /* __d_eh_notify_callback() is called with 3 arguments:
+ 1. event kind catch or throw
+ 2. the target address if known
+ 3. a flag -- not sure what this is. pai/1997-07-17 */
+ event_kind = read_register (ARG0_REGNUM);
+ catch_addr = read_register (ARG1_REGNUM);
+
+ /* Now go down to a user frame */
+ /* For a throw, __d_eh_break is called by
+ __d_eh_notify_callback which is called by
+ __notify_throw which is called
+ from user code.
+ For a catch, __d_eh_break is called by
+ __d_eh_notify_callback which is called by
+ <stackwalking stuff> which is called by
+ __throw__<stuff> or __rethrow_<stuff> which is called
+ from user code. */
+ /* FIXME: Don't use such magic numbers; search for the frames */
+ level = (event_kind == EX_EVENT_THROW) ? 3 : 4;
+ fi = find_relative_frame (curr_frame, &level);
+ if (level != 0)
+ return (struct exception_event_record *) NULL;
+
+ select_frame (fi, -1);
+ throw_addr = fi->pc;
+
+ /* Go back to original (top) frame */
+ select_frame (curr_frame, -1);
+
+ current_ex_event.kind = (enum exception_event_kind) event_kind;
+ current_ex_event.throw_sal = find_pc_line (throw_addr, 1);
+ current_ex_event.catch_sal = find_pc_line (catch_addr, 1);
+
+ return &current_ex_event;
+}
+
+
+#ifdef MAINTENANCE_CMDS
+
+static void
+unwind_command (exp, from_tty)
+ char *exp;
+ int from_tty;
+{
+ CORE_ADDR address;
+ struct unwind_table_entry *u;
+
+ /* If we have an expression, evaluate it and use it as the address. */
+
+ if (exp != 0 && *exp != 0)
+ address = parse_and_eval_address (exp);
+ else
+ return;
+
+ u = find_unwind_entry (address);
+
+ if (!u)
+ {
+ printf_unfiltered ("Can't find unwind table entry for %s\n", exp);
+ return;
+ }
+
+ printf_unfiltered ("unwind_table_entry (0x%x):\n", u);
+
+ printf_unfiltered ("\tregion_start = ");
+ print_address (u->region_start, gdb_stdout);
+
+ printf_unfiltered ("\n\tregion_end = ");
+ print_address (u->region_end, gdb_stdout);
+
+#ifdef __STDC__
+#define pif(FLD) if (u->FLD) printf_unfiltered (" "#FLD);
+#else
+#define pif(FLD) if (u->FLD) printf_unfiltered (" FLD");
+#endif
+
+ printf_unfiltered ("\n\tflags =");
+ pif (Cannot_unwind);
+ pif (Millicode);
+ pif (Millicode_save_sr0);
+ pif (Entry_SR);
+ pif (Args_stored);
+ pif (Variable_Frame);
+ pif (Separate_Package_Body);
+ pif (Frame_Extension_Millicode);
+ pif (Stack_Overflow_Check);
+ pif (Two_Instruction_SP_Increment);
+ pif (Ada_Region);
+ pif (Save_SP);
+ pif (Save_RP);
+ pif (Save_MRP_in_frame);
+ pif (extn_ptr_defined);
+ pif (Cleanup_defined);
+ pif (MPE_XL_interrupt_marker);
+ pif (HP_UX_interrupt_marker);
+ pif (Large_frame);
+
+ putchar_unfiltered ('\n');
+
+#ifdef __STDC__
+#define pin(FLD) printf_unfiltered ("\t"#FLD" = 0x%x\n", u->FLD);
+#else
+#define pin(FLD) printf_unfiltered ("\tFLD = 0x%x\n", u->FLD);
+#endif
+
+ pin (Region_description);
+ pin (Entry_FR);
+ pin (Entry_GR);
+ pin (Total_frame_size);
+}
+#endif /* MAINTENANCE_CMDS */
+
+#ifdef PREPARE_TO_PROCEED
+
+/* If the user has switched threads, and there is a breakpoint
+ at the old thread's pc location, then switch to that thread
+ and return TRUE, else return FALSE and don't do a thread
+ switch (or rather, don't seem to have done a thread switch).
+
+ Ptrace-based gdb will always return FALSE to the thread-switch
+ query, and thus also to PREPARE_TO_PROCEED.
+
+ The important thing is whether there is a BPT instruction,
+ not how many user breakpoints there are. So we have to worry
+ about things like these:
+
+ o Non-bp stop -- NO
+
+ o User hits bp, no switch -- NO
+
+ o User hits bp, switches threads -- YES
+
+ o User hits bp, deletes bp, switches threads -- NO
+
+ o User hits bp, deletes one of two or more bps
+ at that PC, user switches threads -- YES
+
+ o Plus, since we're buffering events, the user may have hit a
+ breakpoint, deleted the breakpoint and then gotten another
+ hit on that same breakpoint on another thread which
+ actually hit before the delete. (FIXME in breakpoint.c
+ so that "dead" breakpoints are ignored?) -- NO
+
+ For these reasons, we have to violate information hiding and
+ call "breakpoint_here_p". If core gdb thinks there is a bpt
+ here, that's what counts, as core gdb is the one which is
+ putting the BPT instruction in and taking it out. */
+int
+hppa_prepare_to_proceed()
+{
+ pid_t old_thread;
+ pid_t current_thread;
+
+ old_thread = hppa_switched_threads(inferior_pid);
+ if (old_thread != 0)
+ {
+ /* Switched over from "old_thread". Try to do
+ as little work as possible, 'cause mostly
+ we're going to switch back. */
+ CORE_ADDR new_pc;
+ CORE_ADDR old_pc = read_pc();
+
+ /* Yuk, shouldn't use global to specify current
+ thread. But that's how gdb does it. */
+ current_thread = inferior_pid;
+ inferior_pid = old_thread;
+
+ new_pc = read_pc();
+ if (new_pc != old_pc /* If at same pc, no need */
+ && breakpoint_here_p (new_pc))
+ {
+ /* User hasn't deleted the BP.
+ Return TRUE, finishing switch to "old_thread". */
+ flush_cached_frames ();
+ registers_changed ();
+#if 0
+ printf("---> PREPARE_TO_PROCEED (was %d, now %d)!\n",
+ current_thread, inferior_pid);
+#endif
+
+ return 1;
+ }
+
+ /* Otherwise switch back to the user-chosen thread. */
+ inferior_pid = current_thread;
+ new_pc = read_pc(); /* Re-prime register cache */
+ }
+
+ return 0;
+}
+#endif /* PREPARE_TO_PROCEED */
+
+void
+_initialize_hppa_tdep ()
+{
+ tm_print_insn = print_insn_hppa;
+
+#ifdef MAINTENANCE_CMDS
+ add_cmd ("unwind", class_maintenance, unwind_command,
+ "Print unwind table entry at given address.",
+ &maintenanceprintlist);
+#endif /* MAINTENANCE_CMDS */
+}
diff --git a/gdb/hppab-nat.c b/gdb/hppab-nat.c
new file mode 100644
index 00000000000..52ce1fdc4a5
--- /dev/null
+++ b/gdb/hppab-nat.c
@@ -0,0 +1,215 @@
+/* Machine-dependent hooks for the unix child process stratum. This
+ code is for the HP PA-RISC cpu.
+
+ Copyright 1986, 1987, 1989, 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
+
+ Contributed by the Center for Software Science at the
+ University of Utah (pa-gdb-bugs@cs.utah.edu).
+
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "inferior.h"
+#include "target.h"
+#include <sys/ptrace.h>
+
+/* Use an extra level of indirection for ptrace calls.
+ This lets us breakpoint usefully on call_ptrace. It also
+ allows us to pass an extra argument to ptrace without
+ using an ANSI-C specific macro. */
+
+#define ptrace call_ptrace
+
+#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
+
+/* Fetch one register. */
+
+static void
+fetch_register (regno)
+ int regno;
+{
+ register unsigned int regaddr;
+ char buf[MAX_REGISTER_RAW_SIZE];
+ register int i;
+
+ /* Offset of registers within the u area. */
+ unsigned int offset;
+
+ offset = U_REGS_OFFSET;
+
+ regaddr = register_addr (regno, offset);
+ for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (int))
+ {
+ errno = 0;
+ *(int *) &buf[i] = ptrace (PT_RUREGS, inferior_pid,
+ (PTRACE_ARG3_TYPE) regaddr, 0);
+ regaddr += sizeof (int);
+ if (errno != 0)
+ {
+ /* Warning, not error, in case we are attached; sometimes the
+ kernel doesn't let us at the registers. */
+ char *err = safe_strerror (errno);
+ char *msg = alloca (strlen (err) + 128);
+ sprintf (msg, "reading register %s: %s", REGISTER_NAME (regno), err);
+ warning (msg);
+ goto error_exit;
+ }
+ }
+ supply_register (regno, buf);
+ error_exit:;
+}
+
+/* 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);
+}
+
+/* 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];
+ extern char registers[];
+ register int i;
+ unsigned int offset = U_REGS_OFFSET;
+ int scratch;
+
+ if (regno >= 0)
+ {
+ if (CANNOT_STORE_REGISTER (regno))
+ return;
+ regaddr = register_addr (regno, offset);
+ errno = 0;
+ if (regno == PCOQ_HEAD_REGNUM || regno == PCOQ_TAIL_REGNUM)
+ {
+ scratch = *(int *) &registers[REGISTER_BYTE (regno)] | 0x3;
+ ptrace (PT_WUREGS, inferior_pid, (PTRACE_ARG3_TYPE) regaddr,
+ scratch);
+ if (errno != 0)
+ {
+ /* Error, even if attached. Failing to write these two
+ registers is pretty serious. */
+ sprintf (buf, "writing register number %d", regno);
+ perror_with_name (buf);
+ }
+ }
+ else
+ for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof(int))
+ {
+ errno = 0;
+ ptrace (PT_WUREGS, inferior_pid, (PTRACE_ARG3_TYPE) regaddr,
+ *(int *) &registers[REGISTER_BYTE (regno) + i]);
+ if (errno != 0)
+ {
+ /* Warning, not error, in case we are attached; sometimes the
+ kernel doesn't let us at the registers. */
+ char *err = safe_strerror (errno);
+ char *msg = alloca (strlen (err) + 128);
+ sprintf (msg, "writing register %s: %s",
+ REGISTER_NAME (regno), err);
+ warning (msg);
+ return;
+ }
+ regaddr += sizeof(int);
+ }
+ }
+ else
+ for (regno = 0; regno < NUM_REGS; regno++)
+ store_inferior_registers (regno);
+}
+
+/* PT_PROT is specific to the PA BSD kernel and isn't documented
+ anywhere (except here).
+
+ PT_PROT allows one to enable/disable the data memory break bit
+ for pages of memory in an inferior process. This bit is used
+ to cause "Data memory break traps" to occur when the appropriate
+ page is written to.
+
+ The arguments are as follows:
+
+ PT_PROT -- The ptrace action to perform.
+
+ INFERIOR_PID -- The pid of the process who's page table entries
+ will be modified.
+
+ PT_ARGS -- The *address* of a 3 word block of memory which has
+ additional information:
+
+ word 0 -- The start address to watch. This should be a page-aligned
+ address.
+
+ word 1 -- The ending address to watch. Again, this should be a
+ page aligned address.
+
+ word 2 -- Nonzero to enable the data memory break bit on the
+ given address range or zero to disable the data memory break
+ bit on the given address range.
+
+ This call may fail if the given addresses are not valid in the inferior
+ process. This most often happens when restarting a program which
+ as watchpoints inserted on heap or stack memory. */
+
+#define PT_PROT 21
+
+int
+hppa_set_watchpoint (addr, len, flag)
+ int addr, len, flag;
+{
+ int pt_args[3];
+ pt_args[0] = addr;
+ pt_args[1] = addr + len;
+ pt_args[2] = flag;
+
+ /* Mask off the lower 12 bits since we want to work on a page basis. */
+ pt_args[0] >>= 12;
+ pt_args[1] >>= 12;
+
+ /* Rounding adjustments. */
+ pt_args[1] -= pt_args[0];
+ pt_args[1]++;
+
+ /* Put the lower 12 bits back as zero. */
+ pt_args[0] <<= 12;
+ pt_args[1] <<= 12;
+
+ /* Do it. */
+ return ptrace (PT_PROT, inferior_pid, (PTRACE_ARG3_TYPE) pt_args, 0);
+}
diff --git a/gdb/hppah-nat.c b/gdb/hppah-nat.c
new file mode 100644
index 00000000000..ac7f69f0a34
--- /dev/null
+++ b/gdb/hppah-nat.c
@@ -0,0 +1,1059 @@
+/* Native support code for HPUX PA-RISC.
+ Copyright 1986, 1987, 1989, 1990, 1991, 1992, 1993, 1998
+ Free Software Foundation, Inc.
+
+ Contributed by the Center for Software Science at the
+ University of Utah (pa-gdb-bugs@cs.utah.edu).
+
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+
+#include "defs.h"
+#include "inferior.h"
+#include "target.h"
+#include <sys/ptrace.h>
+#include "gdbcore.h"
+#include <wait.h>
+#include <signal.h>
+
+extern CORE_ADDR text_end;
+
+static void fetch_register PARAMS ((int));
+
+void
+fetch_inferior_registers (regno)
+ int regno;
+{
+ if (regno == -1)
+ for (regno = 0; regno < NUM_REGS; regno++)
+ fetch_register (regno);
+ else
+ fetch_register (regno);
+}
+
+/* Store our register values back into the inferior.
+ If REGNO is -1, do this for all registers.
+ Otherwise, REGNO specifies which register (so we can save time). */
+
+void
+store_inferior_registers (regno)
+ int regno;
+{
+ register unsigned int regaddr;
+ char buf[80];
+ extern char registers[];
+ register int i;
+ unsigned int offset = U_REGS_OFFSET;
+ int scratch;
+
+ if (regno >= 0)
+ {
+ if (CANNOT_STORE_REGISTER (regno))
+ return;
+ regaddr = register_addr (regno, offset);
+ errno = 0;
+ if (regno == PCOQ_HEAD_REGNUM || regno == PCOQ_TAIL_REGNUM)
+ {
+ scratch = *(int *) &registers[REGISTER_BYTE (regno)] | 0x3;
+ call_ptrace (PT_WUREGS, inferior_pid, (PTRACE_ARG3_TYPE) regaddr,
+ scratch);
+ if (errno != 0)
+ {
+ /* Error, even if attached. Failing to write these two
+ registers is pretty serious. */
+ sprintf (buf, "writing register number %d", regno);
+ perror_with_name (buf);
+ }
+ }
+ else
+ for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof(int))
+ {
+ errno = 0;
+ call_ptrace (PT_WUREGS, inferior_pid, (PTRACE_ARG3_TYPE) regaddr,
+ *(int *) &registers[REGISTER_BYTE (regno) + i]);
+ if (errno != 0)
+ {
+ /* Warning, not error, in case we are attached; sometimes the
+ kernel doesn't let us at the registers. */
+ char *err = safe_strerror (errno);
+ char *msg = alloca (strlen (err) + 128);
+ sprintf (msg, "writing register %s: %s",
+ REGISTER_NAME (regno), err);
+ warning (msg);
+ return;
+ }
+ regaddr += sizeof(int);
+ }
+ }
+ else
+ for (regno = 0; regno < NUM_REGS; regno++)
+ store_inferior_registers (regno);
+}
+
+/* Fetch one register. */
+
+static void
+fetch_register (regno)
+ int regno;
+{
+ register unsigned int regaddr;
+ char buf[MAX_REGISTER_RAW_SIZE];
+ register int i;
+
+ /* Offset of registers within the u area. */
+ unsigned int offset;
+
+ offset = U_REGS_OFFSET;
+
+ regaddr = register_addr (regno, offset);
+ for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (int))
+ {
+ errno = 0;
+ *(int *) &buf[i] = call_ptrace (PT_RUREGS, inferior_pid,
+ (PTRACE_ARG3_TYPE) regaddr, 0);
+ regaddr += sizeof (int);
+ if (errno != 0)
+ {
+ /* Warning, not error, in case we are attached; sometimes the
+ * kernel doesn't let us at the registers.
+ */
+ char *err = safe_strerror (errno);
+ char *msg = alloca (strlen (err) + 128);
+ sprintf (msg, "reading register %s: %s", REGISTER_NAME (regno), err);
+ warning (msg);
+ goto error_exit;
+ }
+ }
+ if (regno == PCOQ_HEAD_REGNUM || regno == PCOQ_TAIL_REGNUM)
+ buf[3] &= ~0x3;
+ supply_register (regno, buf);
+ error_exit:;
+}
+
+/* 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 (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. */
+ /* Note (RT) - This code formerly used alloca, which I have
+ * replaced with xmalloc and a matching free() at the end.
+ * The problem with alloca() is that there is no guarantee of
+ * when it'll be freed, and we were seeing cases of memory
+ * leaks on:
+ * (gdb) watch x
+ * (gdb) cont
+ * where the piled-up alloca's for the child_xfer_memory buffers
+ * were not getting freed.
+ */
+ register int *buffer = (int *) xmalloc (count * sizeof (int));
+
+ if (write)
+ {
+ /* Fill start and end extra bytes of buffer with existing memory data. */
+
+ if (addr != memaddr || len < (int)sizeof (int)) {
+ /* Need part of initial word -- fetch it. */
+ buffer[0] = call_ptrace (addr < text_end ? PT_RIUSER : PT_RDUSER,
+ inferior_pid, (PTRACE_ARG3_TYPE) addr, 0);
+ }
+
+ if (count > 1) /* FIXME, avoid if even boundary */
+ {
+ buffer[count - 1]
+ = call_ptrace (addr < text_end ? PT_RIUSER : PT_RDUSER, inferior_pid,
+ (PTRACE_ARG3_TYPE) (addr + (count - 1) * sizeof (int)),
+ 0);
+ }
+
+ /* Copy data to be written over corresponding part of buffer */
+
+ memcpy ((char *) buffer + (memaddr & (sizeof (int) - 1)), myaddr, len);
+
+ /* Write the entire buffer. */
+
+ for (i = 0; i < count; i++, addr += sizeof (int))
+ {
+ int pt_status;
+ int pt_request;
+ /* The HP-UX kernel crashes if you use PT_WDUSER to write into the text
+ segment. FIXME -- does it work to write into the data segment using
+ WIUSER, or do these idiots really expect us to figure out which segment
+ the address is in, so we can use a separate system call for it??! */
+ errno = 0;
+ pt_request = (addr < text_end) ? PT_WIUSER : PT_WDUSER;
+ pt_status = call_ptrace (pt_request,
+ inferior_pid,
+ (PTRACE_ARG3_TYPE) addr,
+ buffer[i]);
+
+ /* Did we fail? Might we've guessed wrong about which
+ segment this address resides in? Try the other request,
+ and see if that works...
+ */
+ if ((pt_status == -1) && errno) {
+ errno = 0;
+ pt_request = (pt_request == PT_WIUSER) ? PT_WDUSER : PT_WIUSER;
+ pt_status = call_ptrace (pt_request,
+ inferior_pid,
+ (PTRACE_ARG3_TYPE) addr,
+ buffer[i]);
+
+ /* No, we still fail. Okay, time to punt. */
+ if ((pt_status == -1) && errno)
+ {
+ free(buffer);
+ return 0;
+ }
+ }
+ }
+ }
+ else
+ {
+ /* Read all the longwords */
+ for (i = 0; i < count; i++, addr += sizeof (int))
+ {
+ errno = 0;
+ buffer[i] = call_ptrace (addr < text_end ? PT_RIUSER : PT_RDUSER,
+ inferior_pid, (PTRACE_ARG3_TYPE) addr, 0);
+ if (errno) {
+ free(buffer);
+ return 0;
+ }
+ QUIT;
+ }
+
+ /* Copy appropriate bytes out of the buffer. */
+ memcpy (myaddr, (char *) buffer + (memaddr & (sizeof (int) - 1)), len);
+ }
+ free(buffer);
+ return len;
+}
+
+
+void
+child_post_follow_inferior_by_clone ()
+{
+ int status;
+
+ /* This function is used when following both the parent and child
+ of a fork. In this case, the debugger clones itself. The original
+ debugger follows the parent, the clone follows the child. The
+ original detaches from the child, delivering a SIGSTOP to it to
+ keep it from running away until the clone can attach itself.
+
+ At this point, the clone has attached to the child. Because of
+ the SIGSTOP, we must now deliver a SIGCONT to the child, or it
+ won't behave properly. */
+ status = kill (inferior_pid, SIGCONT);
+}
+
+
+void
+child_post_follow_vfork (parent_pid, followed_parent, child_pid, followed_child)
+ int parent_pid;
+ int followed_parent;
+ int child_pid;
+ int followed_child;
+{
+
+ /* Are we a debugger that followed the parent of a vfork? If so,
+ then recall that the child's vfork event was delivered to us
+ first. And, that the parent was suspended by the OS until the
+ child's exec or exit events were received.
+
+ Upon receiving that child vfork, then, we were forced to remove
+ all breakpoints in the child and continue it so that it could
+ reach the exec or exit point.
+
+ But also recall that the parent and child of a vfork share the
+ same address space. Thus, removing bp's in the child also
+ removed them from the parent.
+
+ Now that the child has safely exec'd or exited, we must restore
+ the parent's breakpoints before we continue it. Else, we may
+ cause it run past expected stopping points. */
+ if (followed_parent)
+ {
+ reattach_breakpoints (parent_pid);
+ }
+
+ /* Are we a debugger that followed the child of a vfork? If so,
+ then recall that we don't actually acquire control of the child
+ until after it has exec'd or exited.
+ */
+ if (followed_child)
+ {
+ /* If the child has exited, then there's nothing for us to do.
+ In the case of an exec event, we'll let that be handled by
+ the normal mechanism that notices and handles exec events, in
+ resume(). */
+
+ }
+}
+
+/* Format a process id, given a pid. Be sure to terminate
+ * this with a null--it's going to be printed via a "%s".
+ */
+char *
+hppa_pid_to_str( pid )
+ pid_t pid;
+{
+ static char buf[30]; /* Static because address returned */
+
+ sprintf( buf, "process %d\0\0\0\0", pid );
+ /* Extra NULLs for paranoia's sake */
+
+ return buf;
+}
+
+/* Format a thread id, given a tid. Be sure to terminate
+ * this with a null--it's going to be printed via a "%s".
+ *
+ * Note: This is a core-gdb tid, not the actual system tid.
+ * See infttrace.c for details.
+ */
+char *
+hppa_tid_to_str( tid )
+ pid_t tid;
+{
+ static char buf[30]; /* Static because address returned */
+
+ sprintf( buf, "system thread %d\0\0\0\0", tid );
+ /* Extra NULLs for paranoia's sake */
+
+ return buf;
+}
+
+#if !defined (GDB_NATIVE_HPUX_11)
+
+/* The following code is a substitute for the infttrace.c versions used
+ with ttrace() in HPUX 11. */
+
+/* This value is an arbitrary integer. */
+#define PT_VERSION 123456
+
+/* This semaphore is used to coordinate the child and parent processes
+ after a fork(), and before an exec() by the child. See
+ parent_attach_all for details. */
+
+typedef struct {
+ int parent_channel[2]; /* Parent "talks" to [1], child "listens" to [0] */
+ int child_channel[2]; /* Child "talks" to [1], parent "listens" to [0] */
+} startup_semaphore_t;
+
+#define SEM_TALK (1)
+#define SEM_LISTEN (0)
+
+static startup_semaphore_t startup_semaphore;
+
+extern int parent_attach_all PARAMS ((int, PTRACE_ARG3_TYPE, int));
+
+#ifdef PT_SETTRC
+/* This function causes the caller's process to be traced by its
+ parent. This is intended to be called after GDB forks itself,
+ and before the child execs the target.
+
+ Note that HP-UX ptrace is rather funky in how this is done.
+ If the parent wants to get the initial exec event of a child,
+ it must set the ptrace event mask of the child to include execs.
+ (The child cannot do this itself.) This must be done after the
+ child is forked, but before it execs.
+
+ To coordinate the parent and child, we implement a semaphore using
+ pipes. After SETTRC'ing itself, the child tells the parent that
+ it is now traceable by the parent, and waits for the parent's
+ acknowledgement. The parent can then set the child's event mask,
+ and notify the child that it can now exec.
+
+ (The acknowledgement by parent happens as a result of a call to
+ child_acknowledge_created_inferior.) */
+
+int
+parent_attach_all (pid, addr, data)
+ int pid;
+ PTRACE_ARG3_TYPE addr;
+ int data;
+{
+ int pt_status = 0;
+
+ /* We need a memory home for a constant. */
+ int tc_magic_child = PT_VERSION;
+ int tc_magic_parent = 0;
+
+ /* The remainder of this function is only useful for HPUX 10.0 and
+ later, as it depends upon the ability to request notification
+ of specific kinds of events by the kernel. */
+#if defined(PT_SET_EVENT_MASK)
+
+ /* Notify the parent that we're potentially ready to exec(). */
+ write (startup_semaphore.child_channel[SEM_TALK],
+ &tc_magic_child,
+ sizeof (tc_magic_child));
+
+ /* Wait for acknowledgement from the parent. */
+ read (startup_semaphore.parent_channel[SEM_LISTEN],
+ &tc_magic_parent,
+ sizeof (tc_magic_parent));
+ if (tc_magic_child != tc_magic_parent)
+ warning ("mismatched semaphore magic");
+
+ /* Discard our copy of the semaphore. */
+ (void) close (startup_semaphore.parent_channel[SEM_LISTEN]);
+ (void) close (startup_semaphore.parent_channel[SEM_TALK]);
+ (void) close (startup_semaphore.child_channel[SEM_LISTEN]);
+ (void) close (startup_semaphore.child_channel[SEM_TALK]);
+#endif
+
+ return 0;
+}
+#endif
+
+int
+hppa_require_attach (pid)
+ int pid;
+{
+ int pt_status;
+ CORE_ADDR pc;
+ CORE_ADDR pc_addr;
+ unsigned int regs_offset;
+
+ /* Are we already attached? There appears to be no explicit way to
+ answer this via ptrace, so we try something which should be
+ innocuous if we are attached. If that fails, then we assume
+ we're not attached, and so attempt to make it so. */
+
+ errno = 0;
+ regs_offset = U_REGS_OFFSET;
+ pc_addr = register_addr (PC_REGNUM, regs_offset);
+ pc = call_ptrace (PT_READ_U, pid, (PTRACE_ARG3_TYPE) pc_addr, 0);
+
+ if (errno)
+ {
+ errno = 0;
+ pt_status = call_ptrace (PT_ATTACH, pid, (PTRACE_ARG3_TYPE) 0, 0);
+
+ if (errno)
+ return -1;
+
+ /* Now we really are attached. */
+ errno = 0;
+ }
+ attach_flag = 1;
+ return pid;
+}
+
+int
+hppa_require_detach (pid, signal)
+ int pid;
+ int signal;
+{
+ errno = 0;
+ call_ptrace (PT_DETACH, pid, (PTRACE_ARG3_TYPE) 1, signal);
+ errno = 0; /* Ignore any errors. */
+ return pid;
+}
+
+/* Since ptrace doesn't support memory page-protection events, which
+ are used to implement "hardware" watchpoints on HP-UX, these are
+ dummy versions, which perform no useful work. */
+
+void
+hppa_enable_page_protection_events (pid)
+ int pid;
+{
+}
+
+void
+hppa_disable_page_protection_events (pid)
+ int pid;
+{
+}
+
+int
+hppa_insert_hw_watchpoint (pid, start, len, type)
+ int pid;
+ CORE_ADDR start;
+ LONGEST len;
+ int type;
+{
+ error ("Hardware watchpoints not implemented on this platform.");
+}
+
+int
+hppa_remove_hw_watchpoint (pid, start, len, type)
+ int pid;
+ CORE_ADDR start;
+ LONGEST len;
+ enum bptype type;
+{
+ error ("Hardware watchpoints not implemented on this platform.");
+}
+
+int
+hppa_can_use_hw_watchpoint (type, cnt, ot)
+ enum bptype type;
+ int cnt;
+ enum bptype ot;
+{
+ return 0;
+}
+
+int
+hppa_range_profitable_for_hw_watchpoint (pid, start, len)
+ int pid;
+ CORE_ADDR start;
+ LONGEST len;
+{
+ error ("Hardware watchpoints not implemented on this platform.");
+}
+
+char *
+hppa_pid_or_tid_to_str (id)
+ pid_t id;
+{
+ /* In the ptrace world, there are only processes. */
+ return hppa_pid_to_str (id);
+}
+
+/* This function has no meaning in a non-threaded world. Thus, we
+ return 0 (FALSE). See the use of "hppa_prepare_to_proceed" in
+ hppa-tdep.c. */
+
+pid_t
+hppa_switched_threads (pid)
+ pid_t pid;
+{
+ return (pid_t) 0;
+}
+
+void
+hppa_ensure_vforking_parent_remains_stopped (pid)
+ int pid;
+{
+ /* This assumes that the vforked parent is presently stopped, and
+ that the vforked child has just delivered its first exec event.
+ Calling kill() this way will cause the SIGTRAP to be delivered as
+ soon as the parent is resumed, which happens as soon as the
+ vforked child is resumed. See wait_for_inferior for the use of
+ this function. */
+ kill (pid, SIGTRAP);
+}
+
+int
+hppa_resume_execd_vforking_child_to_get_parent_vfork ()
+{
+ return 1; /* Yes, the child must be resumed. */
+}
+
+void
+require_notification_of_events (pid)
+ int pid;
+{
+#if defined(PT_SET_EVENT_MASK)
+ int pt_status;
+ ptrace_event_t ptrace_events;
+
+ /* Instruct the kernel as to the set of events we wish to be
+ informed of. (This support does not exist before HPUX 10.0.
+ We'll assume if PT_SET_EVENT_MASK has not been defined by
+ <sys/ptrace.h>, then we're being built on pre-10.0.)
+ */
+ memset (&ptrace_events, 0, sizeof (ptrace_events));
+
+ /* Note: By default, all signals are visible to us. If we wish
+ the kernel to keep certain signals hidden from us, we do it
+ by calling sigdelset (ptrace_events.pe_signals, signal) for
+ each such signal here, before doing PT_SET_EVENT_MASK.
+ */
+ sigemptyset (&ptrace_events.pe_signals);
+
+ ptrace_events.pe_set_event = 0;
+
+ ptrace_events.pe_set_event |= PTRACE_SIGNAL;
+ ptrace_events.pe_set_event |= PTRACE_EXEC;
+ ptrace_events.pe_set_event |= PTRACE_FORK;
+ ptrace_events.pe_set_event |= PTRACE_VFORK;
+ /* ??rehrauer: Add this one when we're prepared to catch it...
+ ptrace_events.pe_set_event |= PTRACE_EXIT;
+ */
+
+ errno = 0;
+ pt_status = call_ptrace (PT_SET_EVENT_MASK,
+ pid,
+ (PTRACE_ARG3_TYPE) &ptrace_events,
+ sizeof (ptrace_events));
+ if (errno)
+ perror_with_name ("ptrace");
+ if (pt_status < 0)
+ return;
+#endif
+}
+
+void
+require_notification_of_exec_events (pid)
+ int pid;
+{
+#if defined(PT_SET_EVENT_MASK)
+ int pt_status;
+ ptrace_event_t ptrace_events;
+
+ /* Instruct the kernel as to the set of events we wish to be
+ informed of. (This support does not exist before HPUX 10.0.
+ We'll assume if PT_SET_EVENT_MASK has not been defined by
+ <sys/ptrace.h>, then we're being built on pre-10.0.)
+ */
+ memset (&ptrace_events, 0, sizeof (ptrace_events));
+
+ /* Note: By default, all signals are visible to us. If we wish
+ the kernel to keep certain signals hidden from us, we do it
+ by calling sigdelset (ptrace_events.pe_signals, signal) for
+ each such signal here, before doing PT_SET_EVENT_MASK.
+ */
+ sigemptyset (&ptrace_events.pe_signals);
+
+ ptrace_events.pe_set_event = 0;
+
+ ptrace_events.pe_set_event |= PTRACE_EXEC;
+ /* ??rehrauer: Add this one when we're prepared to catch it...
+ ptrace_events.pe_set_event |= PTRACE_EXIT;
+ */
+
+ errno = 0;
+ pt_status = call_ptrace (PT_SET_EVENT_MASK,
+ pid,
+ (PTRACE_ARG3_TYPE) &ptrace_events,
+ sizeof (ptrace_events));
+ if (errno)
+ perror_with_name ("ptrace");
+ if (pt_status < 0)
+ return;
+#endif
+}
+
+/* This function is called by the parent process, with pid being the
+ ID of the child process, after the debugger has forked. */
+
+void
+child_acknowledge_created_inferior (pid)
+ int pid;
+{
+ /* We need a memory home for a constant. */
+ int tc_magic_parent = PT_VERSION;
+ int tc_magic_child = 0;
+
+ /* Wait for the child to tell us that it has forked. */
+ read (startup_semaphore.child_channel[SEM_LISTEN],
+ &tc_magic_child,
+ sizeof(tc_magic_child));
+
+ /* Notify the child that it can exec.
+
+ In the infttrace.c variant of this function, we set the child's
+ event mask after the fork but before the exec. In the ptrace
+ world, it seems we can't set the event mask until after the exec. */
+
+ write (startup_semaphore.parent_channel[SEM_TALK],
+ &tc_magic_parent,
+ sizeof (tc_magic_parent));
+
+ /* We'd better pause a bit before trying to set the event mask,
+ though, to ensure that the exec has happened. We don't want to
+ wait() on the child, because that'll screw up the upper layers
+ of gdb's execution control that expect to see the exec event.
+
+ After an exec, the child is no longer executing gdb code. Hence,
+ we can't have yet another synchronization via the pipes. We'll
+ just sleep for a second, and hope that's enough delay... */
+
+ sleep (1);
+
+ /* Instruct the kernel as to the set of events we wish to be
+ informed of. */
+
+ require_notification_of_exec_events (pid);
+
+ /* Discard our copy of the semaphore. */
+ (void) close (startup_semaphore.parent_channel[SEM_LISTEN]);
+ (void) close (startup_semaphore.parent_channel[SEM_TALK]);
+ (void) close (startup_semaphore.child_channel[SEM_LISTEN]);
+ (void) close (startup_semaphore.child_channel[SEM_TALK]);
+}
+
+void
+child_post_startup_inferior (pid)
+ int pid;
+
+{
+ require_notification_of_events (pid);
+}
+
+void
+child_post_attach (pid)
+ int pid;
+{
+ require_notification_of_events (pid);
+}
+
+int
+child_insert_fork_catchpoint (pid)
+ int pid;
+{
+ /* This request is only available on HPUX 10.0 and later. */
+#if !defined(PT_SET_EVENT_MASK)
+ error ("Unable to catch forks prior to HPUX 10.0");
+#else
+ /* Enable reporting of fork events from the kernel. */
+ /* ??rehrauer: For the moment, we're always enabling these events,
+ and just ignoring them if there's no catchpoint to catch them.
+ */
+ return 0;
+#endif
+}
+
+int
+child_remove_fork_catchpoint (pid)
+ int pid;
+{
+ /* This request is only available on HPUX 10.0 and later. */
+#if !defined(PT_SET_EVENT_MASK)
+ error ("Unable to catch forks prior to HPUX 10.0");
+#else
+ /* Disable reporting of fork events from the kernel. */
+ /* ??rehrauer: For the moment, we're always enabling these events,
+ and just ignoring them if there's no catchpoint to catch them. */
+ return 0;
+#endif
+}
+
+int
+child_insert_vfork_catchpoint (pid)
+ int pid;
+{
+ /* This request is only available on HPUX 10.0 and later. */
+#if !defined(PT_SET_EVENT_MASK)
+ error ("Unable to catch vforks prior to HPUX 10.0");
+#else
+ /* Enable reporting of vfork events from the kernel. */
+ /* ??rehrauer: For the moment, we're always enabling these events,
+ and just ignoring them if there's no catchpoint to catch them. */
+ return 0;
+#endif
+}
+
+int
+child_remove_vfork_catchpoint (pid)
+ int pid;
+{
+ /* This request is only available on HPUX 10.0 and later. */
+#if !defined(PT_SET_EVENT_MASK)
+ error ("Unable to catch vforks prior to HPUX 10.0");
+#else
+ /* Disable reporting of vfork events from the kernel. */
+ /* ??rehrauer: For the moment, we're always enabling these events,
+ and just ignoring them if there's no catchpoint to catch them. */
+ return 0;
+#endif
+}
+
+int
+child_has_forked (pid, childpid)
+ int pid;
+ int * childpid;
+{
+ /* This request is only available on HPUX 10.0 and later. */
+#if !defined(PT_GET_PROCESS_STATE)
+ *childpid = 0;
+ return 0;
+#else
+ int pt_status;
+ ptrace_state_t ptrace_state;
+
+ errno = 0;
+ pt_status = call_ptrace (PT_GET_PROCESS_STATE,
+ pid,
+ (PTRACE_ARG3_TYPE) &ptrace_state,
+ sizeof (ptrace_state));
+ if (errno)
+ perror_with_name ("ptrace");
+ if (pt_status < 0)
+ return 0;
+
+ if (ptrace_state.pe_report_event & PTRACE_FORK)
+ {
+ *childpid = ptrace_state.pe_other_pid;
+ return 1;
+ }
+
+ return 0;
+#endif
+}
+
+int
+child_has_vforked (pid, childpid)
+ int pid;
+ int * childpid;
+{
+ /* This request is only available on HPUX 10.0 and later. */
+#if !defined(PT_GET_PROCESS_STATE)
+ *childpid = 0;
+ return 0;
+
+#else
+ int pt_status;
+ ptrace_state_t ptrace_state;
+
+ errno = 0;
+ pt_status = call_ptrace (PT_GET_PROCESS_STATE,
+ pid,
+ (PTRACE_ARG3_TYPE) &ptrace_state,
+ sizeof (ptrace_state));
+ if (errno)
+ perror_with_name ("ptrace");
+ if (pt_status < 0)
+ return 0;
+
+ if (ptrace_state.pe_report_event & PTRACE_VFORK)
+ {
+ *childpid = ptrace_state.pe_other_pid;
+ return 1;
+ }
+
+ return 0;
+#endif
+}
+
+int
+child_can_follow_vfork_prior_to_exec ()
+{
+ /* ptrace doesn't allow this. */
+ return 0;
+}
+
+int
+child_insert_exec_catchpoint (pid)
+ int pid;
+{
+ /* This request is only available on HPUX 10.0 and later.
+ */
+#if !defined(PT_SET_EVENT_MASK)
+ error ("Unable to catch execs prior to HPUX 10.0");
+
+#else
+ /* Enable reporting of exec events from the kernel. */
+ /* ??rehrauer: For the moment, we're always enabling these events,
+ and just ignoring them if there's no catchpoint to catch them.
+ */
+ return 0;
+#endif
+}
+
+int
+child_remove_exec_catchpoint (pid)
+ int pid;
+{
+ /* This request is only available on HPUX 10.0 and later.
+ */
+#if !defined(PT_SET_EVENT_MASK)
+ error ("Unable to catch execs prior to HPUX 10.0");
+
+#else
+ /* Disable reporting of exec events from the kernel. */
+ /* ??rehrauer: For the moment, we're always enabling these events,
+ and just ignoring them if there's no catchpoint to catch them.
+ */
+ return 0;
+#endif
+}
+
+int
+child_has_execd (pid, execd_pathname)
+ int pid;
+ char ** execd_pathname;
+{
+
+ /* This request is only available on HPUX 10.0 and later.
+ */
+#if !defined(PT_GET_PROCESS_STATE)
+ *execd_pathname = NULL;
+ return 0;
+
+#else
+ int pt_status;
+ ptrace_state_t ptrace_state;
+
+ errno = 0;
+ pt_status = call_ptrace (PT_GET_PROCESS_STATE,
+ pid,
+ (PTRACE_ARG3_TYPE) &ptrace_state,
+ sizeof (ptrace_state));
+ if (errno)
+ perror_with_name ("ptrace");
+ if (pt_status < 0)
+ return 0;
+
+ if (ptrace_state.pe_report_event & PTRACE_EXEC)
+ {
+ char * exec_file = target_pid_to_exec_file (pid);
+ *execd_pathname = savestring (exec_file, strlen (exec_file));
+ return 1;
+ }
+
+ return 0;
+#endif
+}
+
+int
+child_reported_exec_events_per_exec_call ()
+{
+ return 2; /* ptrace reports the event twice per call. */
+}
+
+int
+child_has_syscall_event (pid, kind, syscall_id)
+ int pid;
+ enum target_waitkind *kind;
+ int *syscall_id;
+{
+ /* This request is only available on HPUX 10.30 and later, via
+ the ttrace interface. */
+
+ *kind = TARGET_WAITKIND_SPURIOUS;
+ *syscall_id = -1;
+ return 0;
+}
+
+char *
+child_pid_to_exec_file (pid)
+ int pid;
+{
+ static char exec_file_buffer[1024];
+ int pt_status;
+ CORE_ADDR top_of_stack;
+ char four_chars[4];
+ int name_index;
+ int i;
+ int saved_inferior_pid;
+ boolean done;
+
+#ifdef PT_GET_PROCESS_PATHNAME
+ /* As of 10.x HP-UX, there's an explicit request to get the pathname. */
+ pt_status = call_ptrace (PT_GET_PROCESS_PATHNAME,
+ pid,
+ (PTRACE_ARG3_TYPE) exec_file_buffer,
+ sizeof (exec_file_buffer) - 1);
+ if (pt_status == 0)
+ return exec_file_buffer;
+#endif
+
+ /* It appears that this request is broken prior to 10.30.
+ If it fails, try a really, truly amazingly gross hack
+ that DDE uses, of pawing through the process' data
+ segment to find the pathname. */
+
+ top_of_stack = 0x7b03a000;
+ name_index = 0;
+ done = 0;
+
+ /* On the chance that pid != inferior_pid, set inferior_pid
+ to pid, so that (grrrr!) implicit uses of inferior_pid get
+ the right id. */
+
+ saved_inferior_pid = inferior_pid;
+ inferior_pid = pid;
+
+ /* Try to grab a null-terminated string. */
+ while (! done)
+ {
+ if (target_read_memory (top_of_stack, four_chars, 4) != 0)
+ {
+ inferior_pid = saved_inferior_pid;
+ return NULL;
+ }
+ for (i = 0; i < 4; i++)
+ {
+ exec_file_buffer[name_index++] = four_chars[i];
+ done = (four_chars[i] == '\0');
+ if (done)
+ break;
+ }
+ top_of_stack += 4;
+ }
+
+ if (exec_file_buffer[0] == '\0')
+ {
+ inferior_pid = saved_inferior_pid;
+ return NULL;
+ }
+
+ inferior_pid = saved_inferior_pid;
+ return exec_file_buffer;
+}
+
+void
+pre_fork_inferior ()
+{
+ int status;
+
+ status = pipe (startup_semaphore.parent_channel);
+ if (status < 0)
+ {
+ warning ("error getting parent pipe for startup semaphore");
+ return;
+ }
+
+ status = pipe (startup_semaphore.child_channel);
+ if (status < 0)
+ {
+ warning ("error getting child pipe for startup semaphore");
+ return;
+ }
+}
+
+
+/* Check to see if the given thread is alive.
+
+ This is a no-op, as ptrace doesn't support threads, so we just
+ return "TRUE". */
+
+int
+child_thread_alive (pid)
+ int pid;
+{
+ return 1;
+}
+
+#endif /* ! GDB_NATIVE_HPUX_11 */
diff --git a/gdb/hppam3-nat.c b/gdb/hppam3-nat.c
new file mode 100644
index 00000000000..95a66b05fef
--- /dev/null
+++ b/gdb/hppam3-nat.c
@@ -0,0 +1,141 @@
+/* Low level interface to HP800 running mach 4.0.
+ Copyright (C) 1995 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "inferior.h"
+#include "floatformat.h"
+
+#include <stdio.h>
+
+#include <mach.h>
+#include <mach/message.h>
+#include <mach/exception.h>
+#include <mach_error.h>
+
+#include <target.h>
+
+/*
+ * Fetch inferiors registers for gdb.
+ * REGNO specifies which (as gdb views it) register, -1 for all.
+ */
+
+void
+fetch_inferior_registers (regno)
+ int regno;
+{
+ kern_return_t ret;
+ thread_state_data_t state;
+ unsigned int stateCnt = TRACE_FLAVOR_SIZE;
+ int index;
+
+ if (! MACH_PORT_VALID (current_thread))
+ error ("fetch inferior registers: Invalid thread");
+
+ if (must_suspend_thread)
+ setup_thread (current_thread, 1);
+
+ ret = thread_get_state (current_thread,
+ TRACE_FLAVOR,
+ state,
+ &stateCnt);
+
+ if (ret != KERN_SUCCESS)
+ warning ("fetch_inferior_registers: %s ",
+ mach_error_string (ret));
+ else
+ {
+ for (index = 0; index < NUM_REGS; index++)
+ supply_register (index,(void*)&state[index]);
+ }
+
+ if (must_suspend_thread)
+ setup_thread (current_thread, 0);
+}
+
+/* Store our register values back into the inferior.
+ * If REGNO is -1, do this for all registers.
+ * Otherwise, REGNO specifies which register
+ *
+ * On mach3 all registers are always saved in one call.
+ */
+void
+store_inferior_registers (regno)
+ int regno;
+{
+ kern_return_t ret;
+ thread_state_data_t state;
+ unsigned int stateCnt = TRACE_FLAVOR_SIZE;
+ register int index;
+
+ if (! MACH_PORT_VALID (current_thread))
+ error ("store inferior registers: Invalid thread");
+
+ if (must_suspend_thread)
+ setup_thread (current_thread, 1);
+
+ /* Fetch the state of the current thread */
+ ret = thread_get_state (current_thread,
+ TRACE_FLAVOR,
+ state,
+ &stateCnt);
+
+ if (ret != KERN_SUCCESS)
+ {
+ warning ("store_inferior_registers (get): %s",
+ mach_error_string (ret));
+ if (must_suspend_thread)
+ setup_thread (current_thread, 0);
+ return;
+ }
+
+
+ /* move gdb's registers to thread's state
+ *
+ * Since we save all registers anyway, save the ones
+ * that gdb thinks are valid (e.g. ignore the regno
+ * parameter)
+ */
+ if (regno > 0 && regno < NUM_REGS )
+ {
+ memcpy(&state[regno], &registers[REGISTER_BYTE (regno)],
+ REGISTER_RAW_SIZE(regno));
+ }
+ else
+ {
+ for (index = 0; index < NUM_REGS; index++)
+ memcpy(&state[index], &registers[REGISTER_BYTE (index)],
+ REGISTER_RAW_SIZE(index));
+/* state[index] = registers[REGISTER_BYTE (index)];*/
+
+ }
+
+ /* Write gdb's current view of register to the thread
+ */
+ ret = thread_set_state (current_thread,
+ TRACE_FLAVOR,
+ state,
+ TRACE_FLAVOR_SIZE);
+
+ if (ret != KERN_SUCCESS)
+ warning ("store_inferior_registers (set): %s",
+ mach_error_string (ret));
+
+ if (must_suspend_thread)
+ setup_thread (current_thread, 0);
+}
diff --git a/gdb/hpread.c b/gdb/hpread.c
new file mode 100644
index 00000000000..0b464ec3a3c
--- /dev/null
+++ b/gdb/hpread.c
@@ -0,0 +1,2050 @@
+/* Read hp debug symbols and convert to internal format, for GDB.
+ Copyright 1993, 1996 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Written by the Center for Software Science at the University of Utah
+ and by Cygnus Support. */
+
+#include "defs.h"
+#include "bfd.h"
+#include "gdb_string.h"
+#include "hp-symtab.h"
+#include "syms.h"
+#include "symtab.h"
+#include "symfile.h"
+#include "objfiles.h"
+#include "buildsym.h"
+#include "complaints.h"
+#include "gdb-stabs.h"
+#include "gdbtypes.h"
+#include "demangle.h"
+
+/* Private information attached to an objfile which we use to find
+ and internalize the HP C debug symbols within that objfile. */
+
+struct hpread_symfile_info
+{
+ /* The contents of each of the debug sections (there are 4 of them). */
+ char *gntt;
+ char *lntt;
+ char *slt;
+ char *vt;
+
+ /* We keep the size of the $VT$ section for range checking. */
+ unsigned int vt_size;
+
+ /* Some routines still need to know the number of symbols in the
+ main debug sections ($LNTT$ and $GNTT$). */
+ unsigned int lntt_symcount;
+ unsigned int gntt_symcount;
+
+ /* To keep track of all the types we've processed. */
+ struct type **type_vector;
+ int type_vector_length;
+
+ /* Keeps track of the beginning of a range of source lines. */
+ sltpointer sl_index;
+
+ /* Some state variables we'll need. */
+ int within_function;
+
+ /* Keep track of the current function's address. We may need to look
+ up something based on this address. */
+ unsigned int current_function_value;
+};
+
+/* Accessor macros to get at the fields. */
+#define HPUX_SYMFILE_INFO(o) \
+ ((struct hpread_symfile_info *)((o)->sym_private))
+#define GNTT(o) (HPUX_SYMFILE_INFO(o)->gntt)
+#define LNTT(o) (HPUX_SYMFILE_INFO(o)->lntt)
+#define SLT(o) (HPUX_SYMFILE_INFO(o)->slt)
+#define VT(o) (HPUX_SYMFILE_INFO(o)->vt)
+#define VT_SIZE(o) (HPUX_SYMFILE_INFO(o)->vt_size)
+#define LNTT_SYMCOUNT(o) (HPUX_SYMFILE_INFO(o)->lntt_symcount)
+#define GNTT_SYMCOUNT(o) (HPUX_SYMFILE_INFO(o)->gntt_symcount)
+#define TYPE_VECTOR(o) (HPUX_SYMFILE_INFO(o)->type_vector)
+#define TYPE_VECTOR_LENGTH(o) (HPUX_SYMFILE_INFO(o)->type_vector_length)
+#define SL_INDEX(o) (HPUX_SYMFILE_INFO(o)->sl_index)
+#define WITHIN_FUNCTION(o) (HPUX_SYMFILE_INFO(o)->within_function)
+#define CURRENT_FUNCTION_VALUE(o) (HPUX_SYMFILE_INFO(o)->current_function_value)
+
+/* Given the native debug symbol SYM, set NAMEP to the name associated
+ with the debug symbol. Note we may be called with a debug symbol which
+ has no associated name, in that case we return an empty string.
+
+ Also note we "know" that the name for any symbol is always in the
+ same place. Hence we don't have to conditionalize on the symbol type. */
+#define SET_NAMESTRING(SYM, NAMEP, OBJFILE) \
+ if (! hpread_has_name ((SYM)->dblock.kind)) \
+ *NAMEP = ""; \
+ else if (((unsigned)(SYM)->dsfile.name) >= VT_SIZE (OBJFILE)) \
+ { \
+ complain (&string_table_offset_complaint, (char *) symnum); \
+ *NAMEP = ""; \
+ } \
+ else \
+ *NAMEP = (SYM)->dsfile.name + VT (OBJFILE)
+
+/* We put a pointer to this structure in the read_symtab_private field
+ of the psymtab. */
+
+struct symloc
+{
+ /* The offset within the file symbol table of first local symbol for
+ this file. */
+
+ int ldsymoff;
+
+ /* 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). 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. */
+
+ int ldsymlen;
+};
+
+#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))
+
+/* FIXME: Shouldn't this stuff be in a .h file somewhere? */
+/* Nonzero means give verbose info on gdb action. */
+extern int info_verbose;
+
+/* Complaints about the symbols we have encountered. */
+extern struct complaint string_table_offset_complaint;
+extern struct complaint lbrac_unmatched_complaint;
+extern struct complaint lbrac_mismatch_complaint;
+
+
+void hpread_symfile_init PARAMS ((struct objfile *));
+
+static struct type *
+hpread_read_array_type PARAMS ((dnttpointer, union dnttentry *, struct objfile *));
+
+static struct type *hpread_alloc_type
+ PARAMS ((dnttpointer, struct objfile *));
+
+static struct type **hpread_lookup_type
+ PARAMS ((dnttpointer, struct objfile *));
+
+static struct type *hpread_read_enum_type
+ PARAMS ((dnttpointer, union dnttentry *, struct objfile *));
+
+static struct type *hpread_read_set_type
+ PARAMS ((dnttpointer, union dnttentry *, struct objfile *));
+
+static struct type *hpread_read_subrange_type
+ PARAMS ((dnttpointer, union dnttentry *, struct objfile *));
+
+static struct type *hpread_read_struct_type
+ PARAMS ((dnttpointer, union dnttentry *, struct objfile *));
+
+void hpread_build_psymtabs
+ PARAMS ((struct objfile *, struct section_offsets *, int));
+
+void hpread_symfile_finish PARAMS ((struct objfile *));
+
+static struct partial_symtab *hpread_start_psymtab
+ PARAMS ((struct objfile *, struct section_offsets *, char *, CORE_ADDR, int,
+ struct partial_symbol **, struct partial_symbol **));
+
+static struct partial_symtab *hpread_end_psymtab
+ PARAMS ((struct partial_symtab *, char **, int, int, CORE_ADDR,
+ struct partial_symtab **, int));
+
+static struct symtab *hpread_expand_symtab
+ PARAMS ((struct objfile *, int, int, CORE_ADDR, int,
+ struct section_offsets *, char *));
+
+static void hpread_process_one_debug_symbol
+ PARAMS ((union dnttentry *, char *, struct section_offsets *,
+ struct objfile *, CORE_ADDR, int, char *, int));
+
+static sltpointer hpread_record_lines
+ PARAMS ((struct subfile *, sltpointer, sltpointer,
+ struct objfile *, CORE_ADDR));
+
+static struct type *hpread_read_function_type
+ PARAMS ((dnttpointer, union dnttentry *, struct objfile *));
+
+static struct type * hpread_type_lookup
+ PARAMS ((dnttpointer, struct objfile *));
+
+static unsigned long hpread_get_depth
+ PARAMS ((sltpointer, struct objfile *));
+
+static unsigned long hpread_get_line
+ PARAMS ((sltpointer, struct objfile *));
+
+static CORE_ADDR hpread_get_location
+ PARAMS ((sltpointer, struct objfile *));
+
+static int hpread_type_translate PARAMS ((dnttpointer));
+static unsigned long hpread_get_textlow PARAMS ((int, int, struct objfile *));
+static union dnttentry *hpread_get_gntt PARAMS ((int, struct objfile *));
+static union dnttentry *hpread_get_lntt PARAMS ((int, struct objfile *));
+static union sltentry *hpread_get_slt PARAMS ((int, struct objfile *));
+static void hpread_psymtab_to_symtab PARAMS ((struct partial_symtab *));
+static void hpread_psymtab_to_symtab_1 PARAMS ((struct partial_symtab *));
+static int hpread_has_name PARAMS ((enum dntt_entry_type));
+
+
+/* Initialization for reading native HP C debug symbols from OBJFILE.
+
+ It's only purpose in life is to set up the symbol reader's private
+ per-objfile data structures, and read in the raw contents of the debug
+ sections (attaching pointers to the debug info into the private data
+ structures).
+
+ 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. Note we may
+ be called on a file without native HP C debugging symbols.
+ FIXME, there should be a cleaner peephole into the BFD environment here. */
+
+void
+hpread_symfile_init (objfile)
+ struct objfile *objfile;
+{
+ asection *vt_section, *slt_section, *lntt_section, *gntt_section;
+
+ /* Allocate struct to keep track of the symfile */
+ objfile->sym_private = (PTR)
+ xmmalloc (objfile->md, sizeof (struct hpread_symfile_info));
+ memset (objfile->sym_private, 0, sizeof (struct hpread_symfile_info));
+
+ /* We haven't read in any types yet. */
+ TYPE_VECTOR (objfile) = 0;
+
+ /* Read in data from the $GNTT$ subspace. */
+ gntt_section = bfd_get_section_by_name (objfile->obfd, "$GNTT$");
+ if (!gntt_section)
+ return;
+
+ GNTT (objfile)
+ = obstack_alloc (&objfile->symbol_obstack,
+ bfd_section_size (objfile->obfd, gntt_section));
+
+ bfd_get_section_contents (objfile->obfd, gntt_section, GNTT (objfile),
+ 0, bfd_section_size (objfile->obfd, gntt_section));
+
+ GNTT_SYMCOUNT (objfile)
+ = bfd_section_size (objfile->obfd, gntt_section)
+ / sizeof (struct dntt_type_block);
+
+ /* Read in data from the $LNTT$ subspace. Also keep track of the number
+ of LNTT symbols. */
+ lntt_section = bfd_get_section_by_name (objfile->obfd, "$LNTT$");
+ if (!lntt_section)
+ return;
+
+ LNTT (objfile)
+ = obstack_alloc (&objfile->symbol_obstack,
+ bfd_section_size (objfile->obfd, lntt_section));
+
+ bfd_get_section_contents (objfile->obfd, lntt_section, LNTT (objfile),
+ 0, bfd_section_size (objfile->obfd, lntt_section));
+
+ LNTT_SYMCOUNT (objfile)
+ = bfd_section_size (objfile->obfd, lntt_section)
+ / sizeof (struct dntt_type_block);
+
+ /* Read in data from the $SLT$ subspace. $SLT$ contains information
+ on source line numbers. */
+ slt_section = bfd_get_section_by_name (objfile->obfd, "$SLT$");
+ if (!slt_section)
+ return;
+
+ SLT (objfile) =
+ obstack_alloc (&objfile->symbol_obstack,
+ bfd_section_size (objfile->obfd, slt_section));
+
+ bfd_get_section_contents (objfile->obfd, slt_section, SLT (objfile),
+ 0, bfd_section_size (objfile->obfd, slt_section));
+
+ /* Read in data from the $VT$ subspace. $VT$ contains things like
+ names and constants. Keep track of the number of symbols in the VT. */
+ vt_section = bfd_get_section_by_name (objfile->obfd, "$VT$");
+ if (!vt_section)
+ return;
+
+ VT_SIZE (objfile) = bfd_section_size (objfile->obfd, vt_section);
+
+ VT (objfile) =
+ (char *) obstack_alloc (&objfile->symbol_obstack,
+ VT_SIZE (objfile));
+
+ bfd_get_section_contents (objfile->obfd, vt_section, VT (objfile),
+ 0, VT_SIZE (objfile));
+}
+
+/* Scan and build partial symbols for a symbol file.
+
+ The minimal symbol table (either SOM or HP a.out) has already been
+ read in; all we need to do is setup partial symbols based on the
+ native debugging information.
+
+ We assume hpread_symfile_init has been called to initialize the
+ symbol reader's private data structures.
+
+ 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). */
+
+void
+hpread_build_psymtabs (objfile, section_offsets, mainline)
+ struct objfile *objfile;
+ struct section_offsets *section_offsets;
+ int mainline;
+{
+ char *namestring;
+ int past_first_source_file = 0;
+ struct cleanup *old_chain;
+
+ int hp_symnum, symcount, i;
+
+ union dnttentry *dn_bufp;
+ unsigned long valu;
+ char *p;
+ int texthigh = 0;
+ int have_name = 0;
+
+ /* 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;
+
+ /* Just in case the stabs reader left turds lying around. */
+ free_pending_blocks ();
+ make_cleanup (really_free_pendings, 0);
+
+ pst = (struct partial_symtab *) 0;
+
+ /* We shouldn't use alloca, instead use malloc/free. Doing so avoids
+ a number of problems with cross compilation and creating useless holes
+ in the stack when we have to allocate new entries. FIXME. */
+
+ 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_objfile, objfile);
+
+ last_source_file = 0;
+
+ /* Make two passes, one ofr the GNTT symbols, the other for the
+ LNTT symbols. */
+ for (i = 0; i < 1; i++)
+ {
+ int within_function = 0;
+
+ if (i)
+ symcount = GNTT_SYMCOUNT (objfile);
+ else
+ symcount = LNTT_SYMCOUNT (objfile);
+
+ for (hp_symnum = 0; hp_symnum < symcount; hp_symnum++)
+ {
+ QUIT;
+ if (i)
+ dn_bufp = hpread_get_gntt (hp_symnum, objfile);
+ else
+ dn_bufp = hpread_get_lntt (hp_symnum, objfile);
+
+ if (dn_bufp->dblock.extension)
+ continue;
+
+ /* Only handle things which are necessary for minimal symbols.
+ everything else is ignored. */
+ switch (dn_bufp->dblock.kind)
+ {
+ case DNTT_TYPE_SRCFILE:
+ {
+ /* A source file of some kind. Note this may simply
+ be an included file. */
+ SET_NAMESTRING (dn_bufp, &namestring, objfile);
+
+ /* Check if this is the source file we are already working
+ with. */
+ if (pst && !strcmp (namestring, pst->filename))
+ continue;
+
+ /* Check if this is an include file, if so check if we have
+ already seen it. Add it to the include list */
+ p = strrchr (namestring, '.');
+ if (!strcmp (p, ".h"))
+ {
+ int j, found;
+
+ found = 0;
+ for (j = 0; j < includes_used; j++)
+ if (!strcmp (namestring, psymtab_include_list[j]))
+ {
+ found = 1;
+ break;
+ }
+ if (found)
+ continue;
+
+ /* Add it to the list of includes seen so far and
+ allocate more include space if necessary. */
+ 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;
+ }
+
+
+ if (pst)
+ {
+ if (!have_name)
+ {
+ pst->filename = (char *)
+ obstack_alloc (&pst->objfile->psymbol_obstack,
+ strlen (namestring) + 1);
+ strcpy (pst->filename, namestring);
+ have_name = 1;
+ continue;
+ }
+ continue;
+ }
+
+ /* This is a bonafide new source file.
+ End the current partial symtab and start a new one. */
+
+ if (pst && past_first_source_file)
+ {
+ hpread_end_psymtab (pst, psymtab_include_list,
+ includes_used,
+ (hp_symnum
+ * sizeof (struct dntt_type_block)),
+ texthigh,
+ dependency_list, dependencies_used);
+ pst = (struct partial_symtab *) 0;
+ includes_used = 0;
+ dependencies_used = 0;
+ }
+ else
+ past_first_source_file = 1;
+
+ valu = hpread_get_textlow (i, hp_symnum, objfile);
+ valu += ANOFFSET (section_offsets, SECT_OFF_TEXT);
+ pst = hpread_start_psymtab (objfile, section_offsets,
+ namestring, valu,
+ (hp_symnum
+ * sizeof (struct dntt_type_block)),
+ objfile->global_psymbols.next,
+ objfile->static_psymbols.next);
+ texthigh = valu;
+ have_name = 1;
+ continue;
+ }
+
+ case DNTT_TYPE_MODULE:
+ /* A source file. It's still unclear to me what the
+ real difference between a DNTT_TYPE_SRCFILE and DNTT_TYPE_MODULE
+ is supposed to be. */
+ SET_NAMESTRING (dn_bufp, &namestring, objfile);
+ valu = hpread_get_textlow (i, hp_symnum, objfile);
+ valu += ANOFFSET (section_offsets, SECT_OFF_TEXT);
+ if (!pst)
+ {
+ pst = hpread_start_psymtab (objfile, section_offsets,
+ namestring, valu,
+ (hp_symnum
+ * sizeof (struct dntt_type_block)),
+ objfile->global_psymbols.next,
+ objfile->static_psymbols.next);
+ texthigh = valu;
+ have_name = 0;
+ }
+ continue;
+ case DNTT_TYPE_FUNCTION:
+ case DNTT_TYPE_ENTRY:
+ /* The beginning of a function. DNTT_TYPE_ENTRY may also denote
+ a secondary entry point. */
+ valu = dn_bufp->dfunc.hiaddr + ANOFFSET (section_offsets,
+ SECT_OFF_TEXT);
+ if (valu > texthigh)
+ texthigh = valu;
+ valu = dn_bufp->dfunc.lowaddr +
+ ANOFFSET (section_offsets, SECT_OFF_TEXT);
+ SET_NAMESTRING (dn_bufp, &namestring, objfile);
+ add_psymbol_to_list (namestring, strlen (namestring),
+ VAR_NAMESPACE, LOC_BLOCK,
+ &objfile->static_psymbols, valu,
+ 0, language_unknown, objfile);
+ within_function = 1;
+ continue;
+ case DNTT_TYPE_BEGIN:
+ case DNTT_TYPE_END:
+ /* Scope block begin/end. We only care about function
+ and file blocks right now. */
+ if (dn_bufp->dend.endkind == DNTT_TYPE_MODULE)
+ {
+ hpread_end_psymtab (pst, psymtab_include_list, includes_used,
+ (hp_symnum
+ * sizeof (struct dntt_type_block)),
+ texthigh,
+ dependency_list, dependencies_used);
+ pst = (struct partial_symtab *) 0;
+ includes_used = 0;
+ dependencies_used = 0;
+ have_name = 0;
+ }
+ if (dn_bufp->dend.endkind == DNTT_TYPE_FUNCTION)
+ within_function = 0;
+ continue;
+ case DNTT_TYPE_SVAR:
+ case DNTT_TYPE_DVAR:
+ case DNTT_TYPE_TYPEDEF:
+ case DNTT_TYPE_TAGDEF:
+ {
+ /* Variables, typedefs an the like. */
+ enum address_class storage;
+ namespace_enum namespace;
+
+ /* Don't add locals to the partial symbol table. */
+ if (within_function
+ && (dn_bufp->dblock.kind == DNTT_TYPE_SVAR
+ || dn_bufp->dblock.kind == DNTT_TYPE_DVAR))
+ continue;
+
+ /* TAGDEFs go into the structure namespace. */
+ if (dn_bufp->dblock.kind == DNTT_TYPE_TAGDEF)
+ namespace = STRUCT_NAMESPACE;
+ else
+ namespace = VAR_NAMESPACE;
+
+ /* What kind of "storage" does this use? */
+ if (dn_bufp->dblock.kind == DNTT_TYPE_SVAR)
+ storage = LOC_STATIC;
+ else if (dn_bufp->dblock.kind == DNTT_TYPE_DVAR
+ && dn_bufp->ddvar.regvar)
+ storage = LOC_REGISTER;
+ else if (dn_bufp->dblock.kind == DNTT_TYPE_DVAR)
+ storage = LOC_LOCAL;
+ else
+ storage = LOC_UNDEF;
+
+ SET_NAMESTRING (dn_bufp, &namestring, objfile);
+ if (!pst)
+ {
+ pst = hpread_start_psymtab (objfile, section_offsets,
+ "globals", 0,
+ (hp_symnum
+ * sizeof (struct dntt_type_block)),
+ objfile->global_psymbols.next,
+ objfile->static_psymbols.next);
+ }
+ if (dn_bufp->dsvar.global)
+ {
+ add_psymbol_to_list (namestring, strlen (namestring),
+ namespace, storage,
+ &objfile->global_psymbols,
+ dn_bufp->dsvar.location,
+ 0, language_unknown, objfile);
+ }
+ else
+ {
+ add_psymbol_to_list (namestring, strlen (namestring),
+ namespace, storage,
+ &objfile->static_psymbols,
+ dn_bufp->dsvar.location,
+ 0, language_unknown, objfile);
+ }
+ continue;
+ }
+ case DNTT_TYPE_MEMENUM:
+ case DNTT_TYPE_CONST:
+ /* Constants and members of enumerated types. */
+ SET_NAMESTRING (dn_bufp, &namestring, objfile);
+ if (!pst)
+ {
+ pst = hpread_start_psymtab (objfile, section_offsets,
+ "globals", 0,
+ (hp_symnum
+ * sizeof (struct dntt_type_block)),
+ objfile->global_psymbols.next,
+ objfile->static_psymbols.next);
+ }
+ add_psymbol_to_list (namestring, strlen (namestring),
+ VAR_NAMESPACE, LOC_CONST,
+ &objfile->static_psymbols, 0,
+ 0, language_unknown, objfile);
+ continue;
+ default:
+ continue;
+ }
+ }
+ }
+
+ /* End any pending partial symbol table. */
+ if (pst)
+ {
+ hpread_end_psymtab (pst, psymtab_include_list, includes_used,
+ hp_symnum * sizeof (struct dntt_type_block),
+ 0, dependency_list, dependencies_used);
+ }
+
+ discard_cleanups (old_chain);
+}
+
+/* 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. */
+
+void
+hpread_symfile_finish (objfile)
+ struct objfile *objfile;
+{
+ if (objfile->sym_private != NULL)
+ {
+ mfree (objfile->md, objfile->sym_private);
+ }
+}
+
+
+/* The remaining functions are all for internal use only. */
+
+/* Various small functions to get entries in the debug symbol sections. */
+
+static union dnttentry *
+hpread_get_lntt (index, objfile)
+ int index;
+ struct objfile *objfile;
+{
+ return (union dnttentry *)
+ &(LNTT (objfile)[(index * sizeof (struct dntt_type_block))]);
+}
+
+static union dnttentry *
+hpread_get_gntt (index, objfile)
+ int index;
+ struct objfile *objfile;
+{
+ return (union dnttentry *)
+ &(GNTT (objfile)[(index * sizeof (struct dntt_type_block))]);
+}
+
+static union sltentry *
+hpread_get_slt (index, objfile)
+ int index;
+ struct objfile *objfile;
+{
+ return (union sltentry *)&(SLT (objfile)[index * sizeof (union sltentry)]);
+}
+
+/* Get the low address associated with some symbol (typically the start
+ of a particular source file or module). Since that information is not
+ stored as part of the DNTT_TYPE_MODULE or DNTT_TYPE_SRCFILE symbol we must infer it from
+ the existance of DNTT_TYPE_FUNCTION symbols. */
+
+static unsigned long
+hpread_get_textlow (global, index, objfile)
+ int global;
+ int index;
+ struct objfile *objfile;
+{
+ union dnttentry *dn_bufp;
+ struct minimal_symbol *msymbol;
+
+ /* Look for a DNTT_TYPE_FUNCTION symbol. */
+ do
+ {
+ if (global)
+ dn_bufp = hpread_get_gntt (index++, objfile);
+ else
+ dn_bufp = hpread_get_lntt (index++, objfile);
+ } while (dn_bufp->dblock.kind != DNTT_TYPE_FUNCTION
+ && dn_bufp->dblock.kind != DNTT_TYPE_END);
+
+ /* Avoid going past a DNTT_TYPE_END when looking for a DNTT_TYPE_FUNCTION. This
+ might happen when a sourcefile has no functions. */
+ if (dn_bufp->dblock.kind == DNTT_TYPE_END)
+ return 0;
+
+ /* The minimal symbols are typically more accurate for some reason. */
+ msymbol = lookup_minimal_symbol (dn_bufp->dfunc.name + VT (objfile), NULL,
+ objfile);
+ if (msymbol)
+ return SYMBOL_VALUE_ADDRESS (msymbol);
+ else
+ return dn_bufp->dfunc.lowaddr;
+}
+
+/* Get the nesting depth for the source line identified by INDEX. */
+
+static unsigned long
+hpread_get_depth (index, objfile)
+ sltpointer index;
+ struct objfile *objfile;
+{
+ union sltentry *sl_bufp;
+
+ sl_bufp = hpread_get_slt (index, objfile);
+ return sl_bufp->sspec.backptr.dnttp.index;
+}
+
+/* Get the source line number the the line identified by INDEX. */
+
+static unsigned long
+hpread_get_line (index, objfile)
+ sltpointer index;
+ struct objfile *objfile;
+{
+ union sltentry *sl_bufp;
+
+ sl_bufp = hpread_get_slt (index, objfile);
+ return sl_bufp->snorm.line;
+}
+
+static CORE_ADDR
+hpread_get_location (index, objfile)
+ sltpointer index;
+ struct objfile *objfile;
+{
+ union sltentry *sl_bufp;
+ int i;
+
+ /* code location of special sltentrys is determined from context */
+ sl_bufp = hpread_get_slt (index, objfile);
+
+ if (sl_bufp->snorm.sltdesc == SLT_END)
+ {
+ /* find previous normal sltentry and get address */
+ for (i = 0; ((sl_bufp->snorm.sltdesc != SLT_NORMAL) &&
+ (sl_bufp->snorm.sltdesc != SLT_EXIT)); i++)
+ sl_bufp = hpread_get_slt (index - i, objfile);
+ return sl_bufp->snorm.address;
+ }
+
+ /* find next normal sltentry and get address */
+ for (i = 0; ((sl_bufp->snorm.sltdesc != SLT_NORMAL) &&
+ (sl_bufp->snorm.sltdesc != SLT_EXIT)); i++)
+ sl_bufp = hpread_get_slt (index + i, objfile);
+ return sl_bufp->snorm.address;
+}
+
+
+/* Return 1 if an HP debug symbol of type KIND has a name associated with
+ it, else return 0. */
+
+static int
+hpread_has_name (kind)
+ enum dntt_entry_type kind;
+{
+ switch (kind)
+ {
+ case DNTT_TYPE_SRCFILE:
+ case DNTT_TYPE_MODULE:
+ case DNTT_TYPE_FUNCTION:
+ case DNTT_TYPE_ENTRY:
+ case DNTT_TYPE_IMPORT:
+ case DNTT_TYPE_LABEL:
+ case DNTT_TYPE_FPARAM:
+ case DNTT_TYPE_SVAR:
+ case DNTT_TYPE_DVAR:
+ case DNTT_TYPE_CONST:
+ case DNTT_TYPE_TYPEDEF:
+ case DNTT_TYPE_TAGDEF:
+ case DNTT_TYPE_MEMENUM:
+ case DNTT_TYPE_FIELD:
+ case DNTT_TYPE_SA:
+ return 1;
+
+ case DNTT_TYPE_BEGIN:
+ case DNTT_TYPE_END:
+ case DNTT_TYPE_WITH:
+ case DNTT_TYPE_COMMON:
+ case DNTT_TYPE_POINTER:
+ case DNTT_TYPE_ENUM:
+ case DNTT_TYPE_SET:
+ case DNTT_TYPE_SUBRANGE:
+ case DNTT_TYPE_ARRAY:
+ case DNTT_TYPE_STRUCT:
+ case DNTT_TYPE_UNION:
+ case DNTT_TYPE_VARIANT:
+ case DNTT_TYPE_FILE:
+ case DNTT_TYPE_FUNCTYPE:
+ case DNTT_TYPE_COBSTRUCT:
+ case DNTT_TYPE_XREF:
+ case DNTT_TYPE_MACRO:
+ default:
+ return 0;
+ }
+}
+
+/* Allocate and partially fill a partial symtab. It will be
+ completely filled at the end of the symbol list.
+
+ SYMFILE_NAME is the name of the symbol-file we are reading from, and ADDR
+ is the address relative to which its symbols are (incremental) or 0
+ (normal). */
+
+static struct partial_symtab *
+hpread_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 = hpread_psymtab_to_symtab;
+
+ 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. */
+
+static struct partial_symtab *
+hpread_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;
+{
+ int i;
+ struct objfile *objfile = pst -> objfile;
+
+ if (capping_symbol_offset != -1)
+ LDSYMLEN(pst) = capping_symbol_offset - LDSYMOFF(pst);
+ pst->texthigh = capping_text;
+
+ 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. */
+ /* Empty psymtabs happen as a result of header files which don't have
+ any symbols in them. There can be a lot of them. But this check
+ is wrong, in that a psymtab with N_SLINE entries but nothing else
+ is not empty, but we don't realize that. Fixing that without slowing
+ things down might be tricky. */
+
+ discard_psymtab (pst);
+
+ /* Indicate that psymtab was thrown away. */
+ pst = (struct partial_symtab *)NULL;
+ }
+ return pst;
+}
+
+/* Do the dirty work of reading in the full symbol from a partial symbol
+ table. */
+
+static void
+hpread_psymtab_to_symtab_1 (pst)
+ struct partial_symtab *pst;
+{
+ struct cleanup *old_chain;
+ int i;
+
+ /* Get out quick if passed junk. */
+ if (!pst)
+ return;
+
+ /* Complain if we've already read in this symbol table. */
+ 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 (" ", gdb_stdout);
+ wrap_here ("");
+ fputs_filtered ("and ", gdb_stdout);
+ wrap_here ("");
+ printf_filtered ("%s...", pst->dependencies[i]->filename);
+ wrap_here (""); /* Flush output */
+ gdb_flush (gdb_stdout);
+ }
+ hpread_psymtab_to_symtab_1 (pst->dependencies[i]);
+ }
+
+ /* If it's real... */
+ if (LDSYMLEN (pst))
+ {
+ /* Init stuff necessary for reading in symbols */
+ buildsym_init ();
+ old_chain = make_cleanup (really_free_pendings, 0);
+
+ pst->symtab =
+ hpread_expand_symtab (pst->objfile, LDSYMOFF (pst), LDSYMLEN (pst),
+ pst->textlow, pst->texthigh - pst->textlow,
+ pst->section_offsets, pst->filename);
+ 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
+hpread_psymtab_to_symtab (pst)
+ struct partial_symtab *pst;
+{
+ /* Get out quick if given junk. */
+ if (!pst)
+ return;
+
+ /* Sanity check. */
+ 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);
+ gdb_flush (gdb_stdout);
+ }
+
+ hpread_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.
+
+ DESC is the file descriptor for the file, positioned at the
+ beginning of the symtab
+ SYM_OFFSET is the offset within the file of
+ the beginning of the symbols we want to read
+ SYM_SIZE is the size of the symbol info to read in.
+ TEXT_OFFSET is the beginning of the text segment we are reading symbols for
+ TEXT_SIZE is the size of the text segment read in.
+ SECTION_OFFSETS are the relocation offsets which get added to each symbol. */
+
+static struct symtab *
+hpread_expand_symtab (objfile, sym_offset, sym_size, text_offset, text_size,
+ section_offsets, filename)
+ struct objfile *objfile;
+ int sym_offset;
+ int sym_size;
+ CORE_ADDR text_offset;
+ int text_size;
+ struct section_offsets *section_offsets;
+ char *filename;
+{
+ char *namestring;
+ union dnttentry *dn_bufp;
+ unsigned max_symnum;
+
+ int sym_index = sym_offset / sizeof (struct dntt_type_block);
+
+ current_objfile = objfile;
+ subfile_stack = 0;
+
+ last_source_file = 0;
+
+ dn_bufp = hpread_get_lntt (sym_index, objfile);
+ if (!((dn_bufp->dblock.kind == (unsigned char) DNTT_TYPE_SRCFILE) ||
+ (dn_bufp->dblock.kind == (unsigned char) DNTT_TYPE_MODULE)))
+ {
+ start_symtab ("globals", NULL, 0);
+ record_debugformat ("HP");
+ }
+
+ max_symnum = sym_size / sizeof (struct dntt_type_block);
+
+ /* Read in and process each debug symbol within the specified range. */
+ for (symnum = 0;
+ symnum < max_symnum;
+ symnum++)
+ {
+ QUIT; /* Allow this to be interruptable */
+ dn_bufp = hpread_get_lntt (sym_index + symnum, objfile);
+
+ if (dn_bufp->dblock.extension)
+ continue;
+
+ /* Yow! We call SET_NAMESTRING on things without names! */
+ SET_NAMESTRING (dn_bufp, &namestring, objfile);
+
+ hpread_process_one_debug_symbol (dn_bufp, namestring, section_offsets,
+ objfile, text_offset, text_size,
+ filename, symnum + sym_index);
+ }
+
+ current_objfile = NULL;
+
+ return end_symtab (text_offset + text_size, objfile, 0);
+}
+
+
+/* Convert basic types from HP debug format into GDB internal format. */
+
+static int
+hpread_type_translate (typep)
+ dnttpointer typep;
+{
+ if (!typep.dntti.immediate)
+ abort ();
+
+ switch (typep.dntti.type)
+ {
+ case HP_TYPE_BOOLEAN:
+ case HP_TYPE_BOOLEAN_S300_COMPAT:
+ case HP_TYPE_BOOLEAN_VAX_COMPAT:
+ return FT_BOOLEAN;
+ /* Ugh. No way to distinguish between signed and unsigned chars. */
+ case HP_TYPE_CHAR:
+ case HP_TYPE_WIDE_CHAR:
+ return FT_CHAR;
+ case HP_TYPE_INT:
+ if (typep.dntti.bitlength <= 8)
+ return FT_CHAR;
+ if (typep.dntti.bitlength <= 16)
+ return FT_SHORT;
+ if (typep.dntti.bitlength <= 32)
+ return FT_INTEGER;
+ return FT_LONG_LONG;
+ case HP_TYPE_LONG:
+ return FT_LONG;
+ case HP_TYPE_UNSIGNED_LONG:
+ if (typep.dntti.bitlength <= 8)
+ return FT_UNSIGNED_CHAR;
+ if (typep.dntti.bitlength <= 16)
+ return FT_UNSIGNED_SHORT;
+ if (typep.dntti.bitlength <= 32)
+ return FT_UNSIGNED_LONG;
+ return FT_UNSIGNED_LONG_LONG;
+ case HP_TYPE_UNSIGNED_INT:
+ if (typep.dntti.bitlength <= 8)
+ return FT_UNSIGNED_CHAR;
+ if (typep.dntti.bitlength <= 16)
+ return FT_UNSIGNED_SHORT;
+ if (typep.dntti.bitlength <= 32)
+ return FT_UNSIGNED_INTEGER;
+ return FT_UNSIGNED_LONG_LONG;
+ case HP_TYPE_REAL:
+ case HP_TYPE_REAL_3000:
+ case HP_TYPE_DOUBLE:
+ if (typep.dntti.bitlength == 64)
+ return FT_DBL_PREC_FLOAT;
+ if (typep.dntti.bitlength == 128)
+ return FT_EXT_PREC_FLOAT;
+ return FT_FLOAT;
+ case HP_TYPE_COMPLEX:
+ case HP_TYPE_COMPLEXS3000:
+ if (typep.dntti.bitlength == 128)
+ return FT_DBL_PREC_COMPLEX;
+ if (typep.dntti.bitlength == 192)
+ return FT_EXT_PREC_COMPLEX;
+ return FT_COMPLEX;
+ case HP_TYPE_STRING200:
+ case HP_TYPE_LONGSTRING200:
+ case HP_TYPE_FTN_STRING_SPEC:
+ case HP_TYPE_MOD_STRING_SPEC:
+ case HP_TYPE_MOD_STRING_3000:
+ case HP_TYPE_FTN_STRING_S300_COMPAT:
+ case HP_TYPE_FTN_STRING_VAX_COMPAT:
+ return FT_STRING;
+ default:
+ abort ();
+ }
+}
+
+/* Return the type associated with the index found in HP_TYPE. */
+
+static struct type **
+hpread_lookup_type (hp_type, objfile)
+ dnttpointer hp_type;
+ struct objfile *objfile;
+{
+ unsigned old_len;
+ int index = hp_type.dnttp.index;
+
+ if (hp_type.dntti.immediate)
+ return NULL;
+
+ if (index < LNTT_SYMCOUNT (objfile))
+ {
+ if (index >= TYPE_VECTOR_LENGTH (objfile))
+ {
+ old_len = TYPE_VECTOR_LENGTH (objfile);
+ if (old_len == 0)
+ {
+ TYPE_VECTOR_LENGTH (objfile) = 100;
+ TYPE_VECTOR (objfile) = (struct type **)
+ xmmalloc (objfile -> md,
+ TYPE_VECTOR_LENGTH (objfile) * sizeof (struct type *));
+ }
+ while (index >= TYPE_VECTOR_LENGTH (objfile))
+ TYPE_VECTOR_LENGTH (objfile) *= 2;
+ TYPE_VECTOR (objfile) = (struct type **)
+ xmrealloc (objfile -> md,
+ (char *) TYPE_VECTOR (objfile),
+ (TYPE_VECTOR_LENGTH (objfile) * sizeof (struct type *)));
+ memset (&TYPE_VECTOR (objfile)[old_len], 0,
+ (TYPE_VECTOR_LENGTH (objfile) - old_len) *
+ sizeof (struct type *));
+ }
+ return &TYPE_VECTOR (objfile)[index];
+ }
+ else
+ return NULL;
+}
+
+/* Possibly allocate a GDB internal type so we can internalize HP_TYPE.
+ Note we'll just return the address of a GDB internal type if we already
+ have it lying around. */
+
+static struct type *
+hpread_alloc_type (hp_type, objfile)
+ dnttpointer hp_type;
+ struct objfile *objfile;
+{
+ struct type **type_addr;
+
+ type_addr = hpread_lookup_type (hp_type, objfile);
+ if (*type_addr == 0)
+ *type_addr = alloc_type (objfile);
+
+ TYPE_CPLUS_SPECIFIC (*type_addr)
+ = (struct cplus_struct_type *) &cplus_struct_default;
+ return *type_addr;
+}
+
+/* Read a native enumerated type and return it in GDB internal form. */
+
+static struct type *
+hpread_read_enum_type (hp_type, dn_bufp, objfile)
+ dnttpointer hp_type;
+ union dnttentry *dn_bufp;
+ struct objfile *objfile;
+{
+ struct type *type;
+ struct pending **symlist, *osyms, *syms;
+ int o_nsyms, nsyms = 0;
+ dnttpointer mem;
+ union dnttentry *memp;
+ char *name;
+ long n;
+ struct symbol *sym;
+
+ type = hpread_alloc_type (hp_type, objfile);
+ TYPE_LENGTH (type) = 4;
+
+ symlist = &file_symbols;
+ osyms = *symlist;
+ o_nsyms = osyms ? osyms->nsyms : 0;
+
+ /* Get a name for each member and add it to our list of members. */
+ mem = dn_bufp->denum.firstmem;
+ while (mem.dnttp.extension && mem.word != DNTTNIL)
+ {
+ memp = hpread_get_lntt (mem.dnttp.index, objfile);
+
+ name = VT (objfile) + memp->dmember.name;
+ sym = (struct symbol *) obstack_alloc (&objfile->symbol_obstack,
+ sizeof (struct symbol));
+ memset (sym, 0, sizeof (struct symbol));
+ SYMBOL_NAME (sym) = obsavestring (name, strlen (name),
+ &objfile->symbol_obstack);
+ SYMBOL_CLASS (sym) = LOC_CONST;
+ SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
+ SYMBOL_VALUE (sym) = memp->dmember.value;
+ add_symbol_to_list (sym, symlist);
+ nsyms++;
+ mem = memp->dmember.nextmem;
+ }
+
+ /* Now that we know more about the enum, fill in more info. */
+ TYPE_CODE (type) = TYPE_CODE_ENUM;
+ TYPE_FLAGS (type) &= ~TYPE_FLAG_STUB;
+ TYPE_NFIELDS (type) = nsyms;
+ TYPE_FIELDS (type) = (struct field *)
+ obstack_alloc (&objfile->type_obstack, sizeof (struct field) * nsyms);
+
+ /* Find the symbols for the members 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_BITPOS (type, n) = SYMBOL_VALUE (xsym);
+ TYPE_FIELD_BITSIZE (type, n) = 0;
+ }
+ if (syms == osyms)
+ break;
+ }
+
+ return type;
+}
+
+/* Read and internalize a native function debug symbol. */
+
+static struct type *
+hpread_read_function_type (hp_type, dn_bufp, objfile)
+ dnttpointer hp_type;
+ union dnttentry *dn_bufp;
+ struct objfile *objfile;
+{
+ struct type *type, *type1;
+ struct pending **symlist, *osyms, *syms;
+ int o_nsyms, nsyms = 0;
+ dnttpointer param;
+ union dnttentry *paramp;
+ char *name;
+ long n;
+ struct symbol *sym;
+
+ param = dn_bufp->dfunc.firstparam;
+
+ /* See if we've already read in this type. */
+ type = hpread_alloc_type (hp_type, objfile);
+ if (TYPE_CODE (type) == TYPE_CODE_FUNC)
+ return type;
+
+ /* Nope, so read it in and store it away. */
+ type1 = lookup_function_type (hpread_type_lookup (dn_bufp->dfunc.retval,
+ objfile));
+ memcpy ((char *) type, (char *) type1, sizeof (struct type));
+
+ symlist = &local_symbols;
+ osyms = *symlist;
+ o_nsyms = osyms ? osyms->nsyms : 0;
+
+ /* Now examine each parameter noting its type, location, and a
+ wealth of other information. */
+ while (param.word && param.word != DNTTNIL)
+ {
+ paramp = hpread_get_lntt (param.dnttp.index, objfile);
+ nsyms++;
+ param = paramp->dfparam.nextparam;
+
+ /* Get the name. */
+ name = VT (objfile) + paramp->dfparam.name;
+ sym = (struct symbol *) obstack_alloc (&objfile->symbol_obstack,
+ sizeof (struct symbol));
+ (void) memset (sym, 0, sizeof (struct symbol));
+ SYMBOL_NAME (sym) = obsavestring (name, strlen (name),
+ &objfile->symbol_obstack);
+
+ /* Figure out where it lives. */
+ if (paramp->dfparam.regparam)
+ SYMBOL_CLASS (sym) = LOC_REGPARM;
+ else if (paramp->dfparam.indirect)
+ SYMBOL_CLASS (sym) = LOC_REF_ARG;
+ else
+ SYMBOL_CLASS (sym) = LOC_ARG;
+ SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
+ if (paramp->dfparam.copyparam)
+ {
+ SYMBOL_VALUE (sym) = paramp->dfparam.location ;
+#ifdef HPREAD_ADJUST_STACK_ADDRESS
+ SYMBOL_VALUE (sym)
+ += HPREAD_ADJUST_STACK_ADDRESS (CURRENT_FUNCTION_VALUE (objfile));
+#endif
+ /* This is likely a pass-by-invisible reference parameter,
+ Hack on the symbol class to make GDB happy. */
+ SYMBOL_CLASS (sym) = LOC_REGPARM_ADDR;
+ }
+ else
+ SYMBOL_VALUE (sym) = paramp->dfparam.location;
+
+ /* Get its type. */
+ SYMBOL_TYPE (sym) = hpread_type_lookup (paramp->dfparam.type, objfile);
+
+ /* Add it to the list. */
+ add_symbol_to_list (sym, symlist);
+ }
+
+ /* Note how many parameters we found. */
+ TYPE_NFIELDS (type) = nsyms;
+ TYPE_FIELDS (type) = (struct field *)
+ obstack_alloc (&objfile->type_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 parameters, 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];
+ TYPE_FIELD_NAME (type, n) = SYMBOL_NAME (xsym);
+ TYPE_FIELD_TYPE (type, n) = SYMBOL_TYPE (xsym);
+ TYPE_FIELD_BITPOS (type, n) = n;
+ TYPE_FIELD_BITSIZE (type, n) = 0;
+ }
+ if (syms == osyms)
+ break;
+ }
+ return type;
+}
+
+/* Read in and internalize a structure definition. */
+
+static struct type *
+hpread_read_struct_type (hp_type, dn_bufp, objfile)
+ dnttpointer hp_type;
+ union dnttentry *dn_bufp;
+ struct objfile *objfile;
+{
+ struct nextfield
+ {
+ struct nextfield *next;
+ struct field field;
+ };
+
+ struct type *type;
+ struct nextfield *list = 0;
+ struct nextfield *new;
+ int n, nfields = 0;
+ dnttpointer field;
+ union dnttentry *fieldp;
+
+ /* Is it something we've already dealt with? */
+ type = hpread_alloc_type (hp_type, objfile);
+ if ((TYPE_CODE (type) == TYPE_CODE_STRUCT) ||
+ (TYPE_CODE (type) == TYPE_CODE_UNION))
+ return type;
+
+ /* Get the basic type correct. */
+ if (dn_bufp->dblock.kind == DNTT_TYPE_STRUCT)
+ {
+ TYPE_CODE (type) = TYPE_CODE_STRUCT;
+ TYPE_LENGTH (type) = dn_bufp->dstruct.bitlength / 8;
+ }
+ else if (dn_bufp->dblock.kind == DNTT_TYPE_UNION)
+ {
+ TYPE_CODE (type) = TYPE_CODE_UNION;
+ TYPE_LENGTH (type) = dn_bufp->dunion.bitlength / 8;
+ }
+ else
+ return type;
+
+
+ TYPE_FLAGS (type) &= ~TYPE_FLAG_STUB;
+
+ /* Read in and internalize all the fields. */
+ field = dn_bufp->dstruct.firstfield;
+ while (field.word != DNTTNIL && field.dnttp.extension)
+ {
+ fieldp = hpread_get_lntt (field.dnttp.index, objfile);
+
+ /* Get space to record the next field's data. */
+ new = (struct nextfield *) alloca (sizeof (struct nextfield));
+ new->next = list;
+ list = new;
+
+ list->field.name = VT (objfile) + fieldp->dfield.name;
+ FIELD_BITPOS (list->field) = fieldp->dfield.bitoffset;
+ if (fieldp->dfield.bitlength % 8)
+ FIELD_BITSIZE (list->field) = fieldp->dfield.bitlength;
+ else
+ FIELD_BITSIZE (list->field) = 0;
+ nfields++;
+ field = fieldp->dfield.nextfield;
+ FIELD_TYPE (list->field) = hpread_type_lookup (fieldp->dfield.type,
+ objfile);
+ }
+
+ TYPE_NFIELDS (type) = nfields;
+ TYPE_FIELDS (type) = (struct field *)
+ obstack_alloc (&objfile->type_obstack, sizeof (struct field) * nfields);
+
+ /* Copy the saved-up fields into the field vector. */
+ for (n = nfields; list; list = list->next)
+ {
+ n -= 1;
+ TYPE_FIELD (type, n) = list->field;
+ }
+ return type;
+}
+
+/* Read in and internalize a set debug symbol. */
+
+static struct type *
+hpread_read_set_type (hp_type, dn_bufp, objfile)
+ dnttpointer hp_type;
+ union dnttentry *dn_bufp;
+ struct objfile *objfile;
+{
+ struct type *type;
+
+ /* See if it's something we've already deal with. */
+ type = hpread_alloc_type (hp_type, objfile);
+ if (TYPE_CODE (type) == TYPE_CODE_SET)
+ return type;
+
+ /* Nope. Fill in the appropriate fields. */
+ TYPE_CODE (type) = TYPE_CODE_SET;
+ TYPE_LENGTH (type) = dn_bufp->dset.bitlength / 8;
+ TYPE_NFIELDS (type) = 0;
+ TYPE_TARGET_TYPE (type) = hpread_type_lookup (dn_bufp->dset.subtype,
+ objfile);
+ return type;
+}
+
+/* Read in and internalize an array debug symbol. */
+
+static struct type *
+hpread_read_array_type (hp_type, dn_bufp, objfile)
+ dnttpointer hp_type;
+ union dnttentry *dn_bufp;
+ struct objfile *objfile;
+{
+ struct type *type;
+ union dnttentry save;
+ save = *dn_bufp;
+
+ /* Why no check here? Because it kept us from properly determining
+ the size of the array! */
+ type = hpread_alloc_type (hp_type, objfile);
+
+ TYPE_CODE (type) = TYPE_CODE_ARRAY;
+
+ /* values are not normalized. */
+ if (!((dn_bufp->darray.arrayisbytes && dn_bufp->darray.elemisbytes)
+ || (!dn_bufp->darray.arrayisbytes && !dn_bufp->darray.elemisbytes)))
+ abort ();
+ else if (dn_bufp->darray.arraylength == 0x7fffffff)
+ {
+ /* The HP debug format represents char foo[]; as an array with
+ length 0x7fffffff. Internally GDB wants to represent this
+ as an array of length zero. */
+ TYPE_LENGTH (type) = 0;
+ }
+ else
+ TYPE_LENGTH (type) = dn_bufp->darray.arraylength / 8;
+
+ TYPE_NFIELDS (type) = 1;
+ TYPE_TARGET_TYPE (type) = hpread_type_lookup (dn_bufp->darray.elemtype,
+ objfile);
+ dn_bufp = &save;
+ TYPE_FIELDS (type) = (struct field *)
+ obstack_alloc (&objfile->type_obstack, sizeof (struct field));
+ TYPE_FIELD_TYPE (type, 0) = hpread_type_lookup (dn_bufp->darray.indextype,
+ objfile);
+ return type;
+}
+
+/* Read in and internalize a subrange debug symbol. */
+static struct type *
+hpread_read_subrange_type (hp_type, dn_bufp, objfile)
+ dnttpointer hp_type;
+ union dnttentry *dn_bufp;
+ struct objfile *objfile;
+{
+ struct type *type;
+
+ /* Is it something we've already dealt with. */
+ type = hpread_alloc_type (hp_type, objfile);
+ if (TYPE_CODE (type) == TYPE_CODE_RANGE)
+ return type;
+
+ /* Nope, internalize it. */
+ TYPE_CODE (type) = TYPE_CODE_RANGE;
+ TYPE_LENGTH (type) = dn_bufp->dsubr.bitlength / 8;
+ TYPE_NFIELDS (type) = 2;
+ TYPE_FIELDS (type)
+ = (struct field *) obstack_alloc (&objfile->type_obstack,
+ 2 * sizeof (struct field));
+
+ if (dn_bufp->dsubr.dyn_low)
+ TYPE_FIELD_BITPOS (type, 0) = 0;
+ else
+ TYPE_FIELD_BITPOS (type, 0) = dn_bufp->dsubr.lowbound;
+
+ if (dn_bufp->dsubr.dyn_high)
+ TYPE_FIELD_BITPOS (type, 1) = -1;
+ else
+ TYPE_FIELD_BITPOS (type, 1) = dn_bufp->dsubr.highbound;
+ TYPE_TARGET_TYPE (type) = hpread_type_lookup (dn_bufp->dsubr.subtype,
+ objfile);
+ return type;
+}
+
+static struct type *
+hpread_type_lookup (hp_type, objfile)
+ dnttpointer hp_type;
+ struct objfile *objfile;
+{
+ union dnttentry *dn_bufp;
+
+ /* First see if it's a simple builtin type. */
+ if (hp_type.dntti.immediate)
+ return lookup_fundamental_type (objfile, hpread_type_translate (hp_type));
+
+ /* Not a builtin type. We'll have to read it in. */
+ if (hp_type.dnttp.index < LNTT_SYMCOUNT (objfile))
+ dn_bufp = hpread_get_lntt (hp_type.dnttp.index, objfile);
+ else
+ return lookup_fundamental_type (objfile, FT_VOID);
+
+ switch (dn_bufp->dblock.kind)
+ {
+ case DNTT_TYPE_SRCFILE:
+ case DNTT_TYPE_MODULE:
+ case DNTT_TYPE_FUNCTION:
+ case DNTT_TYPE_ENTRY:
+ case DNTT_TYPE_BEGIN:
+ case DNTT_TYPE_END:
+ case DNTT_TYPE_IMPORT:
+ case DNTT_TYPE_LABEL:
+ case DNTT_TYPE_WITH:
+ case DNTT_TYPE_COMMON:
+ case DNTT_TYPE_FPARAM:
+ case DNTT_TYPE_SVAR:
+ case DNTT_TYPE_DVAR:
+ case DNTT_TYPE_CONST:
+ /* Opps. Something went very wrong. */
+ return lookup_fundamental_type (objfile, FT_VOID);
+
+ case DNTT_TYPE_TYPEDEF:
+ {
+ struct type *structtype = hpread_type_lookup (dn_bufp->dtype.type,
+ objfile);
+ char *suffix;
+ suffix = VT (objfile) + dn_bufp->dtype.name;
+
+ TYPE_CPLUS_SPECIFIC (structtype)
+ = (struct cplus_struct_type *) &cplus_struct_default;
+ TYPE_NAME (structtype) = suffix;
+ return structtype;
+ }
+
+ case DNTT_TYPE_TAGDEF:
+ {
+ /* Just a little different from above. We have to tack on
+ an identifier of some kind (struct, union, enum, etc). */
+ struct type *structtype = hpread_type_lookup (dn_bufp->dtype.type,
+ objfile);
+ char *prefix, *suffix;
+ suffix = VT (objfile) + dn_bufp->dtype.name;
+
+ /* Lookup the next type in the list. It should be a structure,
+ union, or enum type. We will need to attach that to our name. */
+ if (dn_bufp->dtype.type.dnttp.index < LNTT_SYMCOUNT (objfile))
+ dn_bufp = hpread_get_lntt (dn_bufp->dtype.type.dnttp.index, objfile);
+ else
+ abort ();
+
+ if (dn_bufp->dblock.kind == DNTT_TYPE_STRUCT)
+ prefix = "struct ";
+ else if (dn_bufp->dblock.kind == DNTT_TYPE_UNION)
+ prefix = "union ";
+ else
+ prefix = "enum ";
+
+ /* Build the correct name. */
+ structtype->name
+ = (char *) obstack_alloc (&objfile->type_obstack,
+ strlen (prefix) + strlen (suffix) + 1);
+ TYPE_NAME (structtype) = strcpy (TYPE_NAME (structtype), prefix);
+ TYPE_NAME (structtype) = strcat (TYPE_NAME (structtype), suffix);
+ TYPE_TAG_NAME (structtype) = suffix;
+
+ TYPE_CPLUS_SPECIFIC (structtype)
+ = (struct cplus_struct_type *) &cplus_struct_default;
+
+ return structtype;
+ }
+ case DNTT_TYPE_POINTER:
+ return lookup_pointer_type (hpread_type_lookup (dn_bufp->dptr.pointsto,
+ objfile));
+ case DNTT_TYPE_ENUM:
+ return hpread_read_enum_type (hp_type, dn_bufp, objfile);
+ case DNTT_TYPE_MEMENUM:
+ return lookup_fundamental_type (objfile, FT_VOID);
+ case DNTT_TYPE_SET:
+ return hpread_read_set_type (hp_type, dn_bufp, objfile);
+ case DNTT_TYPE_SUBRANGE:
+ return hpread_read_subrange_type (hp_type, dn_bufp, objfile);
+ case DNTT_TYPE_ARRAY:
+ return hpread_read_array_type (hp_type, dn_bufp, objfile);
+ case DNTT_TYPE_STRUCT:
+ case DNTT_TYPE_UNION:
+ return hpread_read_struct_type (hp_type, dn_bufp, objfile);
+ case DNTT_TYPE_FIELD:
+ return hpread_type_lookup (dn_bufp->dfield.type, objfile);
+ case DNTT_TYPE_VARIANT:
+ case DNTT_TYPE_FILE:
+ return lookup_fundamental_type (objfile, FT_VOID);
+ case DNTT_TYPE_FUNCTYPE:
+ return lookup_function_type (hpread_type_lookup (dn_bufp->dfunctype.retval,
+ objfile));
+ case DNTT_TYPE_COBSTRUCT:
+ case DNTT_TYPE_XREF:
+ case DNTT_TYPE_SA:
+ case DNTT_TYPE_MACRO:
+ default:
+ return lookup_fundamental_type (objfile, FT_VOID);
+ }
+}
+
+static sltpointer
+hpread_record_lines (subfile, s_idx, e_idx, objfile, offset)
+ struct subfile *subfile;
+ sltpointer s_idx, e_idx;
+ struct objfile *objfile;
+ CORE_ADDR offset;
+{
+ union sltentry *sl_bufp;
+
+ while (s_idx <= e_idx)
+ {
+ sl_bufp = hpread_get_slt (s_idx, objfile);
+ /* Only record "normal" entries in the SLT. */
+ if (sl_bufp->snorm.sltdesc == SLT_NORMAL
+ || sl_bufp->snorm.sltdesc == SLT_EXIT)
+ record_line (subfile, sl_bufp->snorm.line,
+ sl_bufp->snorm.address + offset);
+ s_idx++;
+ }
+ return e_idx;
+}
+
+/* Internalize one native debug symbol. */
+
+static void
+hpread_process_one_debug_symbol (dn_bufp, name, section_offsets, objfile,
+ text_offset, text_size, filename, index)
+ union dnttentry *dn_bufp;
+ char *name;
+ struct section_offsets *section_offsets;
+ struct objfile *objfile;
+ CORE_ADDR text_offset;
+ int text_size;
+ char *filename;
+ int index;
+{
+ unsigned long desc;
+ int type;
+ CORE_ADDR valu;
+ int offset = ANOFFSET (section_offsets, SECT_OFF_TEXT);
+ union dnttentry *dn_temp;
+ dnttpointer hp_type;
+ struct symbol *sym;
+ struct context_stack *new;
+
+ /* Allocate one GDB debug symbol and fill in some default values. */
+ sym = (struct symbol *) obstack_alloc (&objfile->symbol_obstack,
+ sizeof (struct symbol));
+ memset (sym, 0, sizeof (struct symbol));
+ SYMBOL_NAME (sym) = obsavestring (name, strlen (name), &objfile->symbol_obstack);
+ SYMBOL_LANGUAGE (sym) = language_auto;
+ SYMBOL_INIT_DEMANGLED_NAME (sym, &objfile->symbol_obstack);
+ SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
+ SYMBOL_LINE (sym) = 0;
+ SYMBOL_VALUE (sym) = 0;
+ SYMBOL_CLASS (sym) = LOC_TYPEDEF;
+
+ hp_type.dnttp.extension = 1;
+ hp_type.dnttp.immediate = 0;
+ hp_type.dnttp.global = 0;
+ hp_type.dnttp.index = index;
+
+ type = dn_bufp->dblock.kind;
+
+ switch (type)
+ {
+ case DNTT_TYPE_SRCFILE:
+ /* This type of symbol indicates from which source file or include file
+ the following data comes. If there are no modules it also may
+ indicate the start of a new source file, in which case we must
+ finish the symbol table of the previous source file
+ (if any) and start accumulating a new symbol table. */
+
+ valu = text_offset;
+ if (!last_source_file)
+ {
+ start_symtab (name, NULL, valu);
+ record_debugformat ("HP");
+ SL_INDEX (objfile) = dn_bufp->dsfile.address;
+ }
+ else
+ {
+ SL_INDEX (objfile) = hpread_record_lines (current_subfile,
+ SL_INDEX (objfile),
+ dn_bufp->dsfile.address,
+ objfile, offset);
+ }
+ start_subfile (name, NULL);
+ break;
+
+ case DNTT_TYPE_MODULE:
+ /* No need to do anything with these DNTT_TYPE_MODULE symbols anymore. */
+ break;
+
+ case DNTT_TYPE_FUNCTION:
+ case DNTT_TYPE_ENTRY:
+ /* A function or secondary entry point. */
+ valu = dn_bufp->dfunc.lowaddr + offset;
+ SL_INDEX (objfile) = hpread_record_lines (current_subfile,
+ SL_INDEX (objfile),
+ dn_bufp->dfunc.address,
+ objfile, offset);
+
+ WITHIN_FUNCTION (objfile) = 1;
+ CURRENT_FUNCTION_VALUE (objfile) = valu;
+
+ /* Stack must be empty now. */
+ if (context_stack_depth != 0)
+ complain (&lbrac_unmatched_complaint, (char *) symnum);
+ new = push_context (0, valu);
+
+ SYMBOL_CLASS (sym) = LOC_BLOCK;
+ SYMBOL_TYPE (sym) = hpread_read_function_type (hp_type, dn_bufp, objfile);
+ if (dn_bufp->dfunc.global)
+ add_symbol_to_list (sym, &global_symbols);
+ else
+ add_symbol_to_list (sym, &file_symbols);
+ new->name = sym;
+
+ /* Search forward to the next scope beginning. */
+ while (dn_bufp->dblock.kind != DNTT_TYPE_BEGIN)
+ {
+ dn_bufp = hpread_get_lntt (++index, objfile);
+ if (dn_bufp->dblock.extension)
+ continue;
+ }
+ SL_INDEX (objfile) = hpread_record_lines (current_subfile,
+ SL_INDEX (objfile),
+ dn_bufp->dbegin.address,
+ objfile, offset);
+ SYMBOL_LINE (sym) = hpread_get_line (dn_bufp->dbegin.address, objfile);
+ record_line (current_subfile, SYMBOL_LINE (sym), valu);
+ break;
+
+ case DNTT_TYPE_BEGIN:
+ /* Begin a new scope. */
+ SL_INDEX (objfile) = hpread_record_lines (current_subfile,
+ SL_INDEX (objfile),
+ dn_bufp->dbegin.address,
+ objfile, offset);
+ valu = hpread_get_location (dn_bufp->dbegin.address, objfile);
+ valu += offset; /* Relocate for dynamic loading */
+ desc = hpread_get_depth (dn_bufp->dbegin.address, objfile);
+ new = push_context (desc, valu);
+ break;
+
+ case DNTT_TYPE_END:
+ /* End a scope. */
+ SL_INDEX (objfile) = hpread_record_lines (current_subfile,
+ SL_INDEX (objfile),
+ dn_bufp->dend.address + 1,
+ objfile, offset);
+ switch (dn_bufp->dend.endkind)
+ {
+ case DNTT_TYPE_MODULE:
+ /* Ending a module ends the symbol table for that module. */
+ valu = text_offset + text_size + offset;
+ (void) end_symtab (valu, objfile, 0);
+ break;
+
+ case DNTT_TYPE_FUNCTION:
+ /* Ending a function, well, ends the function's scope. */
+ dn_temp = hpread_get_lntt (dn_bufp->dend.beginscope.dnttp.index,
+ objfile);
+ valu = dn_temp->dfunc.hiaddr + offset;
+ 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);
+ WITHIN_FUNCTION (objfile) = 0;
+ break;
+ case DNTT_TYPE_BEGIN:
+ /* Just ending a local scope. */
+ valu = hpread_get_location (dn_bufp->dend.address, objfile);
+ /* Why in the hell is this needed? */
+ valu += offset + 9; /* Relocate for dynamic loading */
+ new = pop_context ();
+ desc = dn_bufp->dend.beginscope.dnttp.index;
+ if (desc != new->depth)
+ complain (&lbrac_mismatch_complaint, (char *) symnum);
+ /* Make a block for the local symbols within. */
+ finish_block (new->name, &local_symbols, new->old_blocks,
+ new->start_addr, valu, objfile);
+ local_symbols = new->locals;
+ break;
+ }
+ break;
+ case DNTT_TYPE_LABEL:
+ SYMBOL_NAMESPACE (sym) = LABEL_NAMESPACE;
+ break;
+ case DNTT_TYPE_FPARAM:
+ /* Function parameters. */
+ if (dn_bufp->dfparam.regparam)
+ SYMBOL_CLASS (sym) = LOC_REGISTER;
+ else
+ SYMBOL_CLASS (sym) = LOC_LOCAL;
+ if (dn_bufp->dfparam.copyparam)
+ {
+ SYMBOL_VALUE (sym) = dn_bufp->dfparam.location;
+#ifdef HPREAD_ADJUST_STACK_ADDRESS
+ SYMBOL_VALUE (sym)
+ += HPREAD_ADJUST_STACK_ADDRESS (CURRENT_FUNCTION_VALUE (objfile));
+#endif
+ }
+ else
+ SYMBOL_VALUE (sym) = dn_bufp->dfparam.location;
+ SYMBOL_TYPE (sym) = hpread_type_lookup (dn_bufp->dfparam.type, objfile);
+ add_symbol_to_list (sym, &local_symbols);
+ break;
+ case DNTT_TYPE_SVAR:
+ /* Static variables. */
+ SYMBOL_CLASS (sym) = LOC_STATIC;
+ SYMBOL_VALUE_ADDRESS (sym) = dn_bufp->dsvar.location;
+ SYMBOL_TYPE (sym) = hpread_type_lookup (dn_bufp->dsvar.type, objfile);
+ if (dn_bufp->dsvar.global)
+ add_symbol_to_list (sym, &global_symbols);
+ else if (WITHIN_FUNCTION (objfile))
+ add_symbol_to_list (sym, &local_symbols);
+ else
+ add_symbol_to_list (sym, &file_symbols);
+ break;
+ case DNTT_TYPE_DVAR:
+ /* Dynamic variables. */
+ if (dn_bufp->ddvar.regvar)
+ SYMBOL_CLASS (sym) = LOC_REGISTER;
+ else
+ SYMBOL_CLASS (sym) = LOC_LOCAL;
+ SYMBOL_VALUE (sym) = dn_bufp->ddvar.location;
+#ifdef HPREAD_ADJUST_STACK_ADDRESS
+ SYMBOL_VALUE (sym)
+ += HPREAD_ADJUST_STACK_ADDRESS (CURRENT_FUNCTION_VALUE (objfile));
+#endif
+ SYMBOL_TYPE (sym) = hpread_type_lookup (dn_bufp->ddvar.type, objfile);
+ if (dn_bufp->ddvar.global)
+ add_symbol_to_list (sym, &global_symbols);
+ else if (WITHIN_FUNCTION (objfile))
+ add_symbol_to_list (sym, &local_symbols);
+ else
+ add_symbol_to_list (sym, &file_symbols);
+ break;
+ case DNTT_TYPE_CONST:
+ /* A constant (pascal?). */
+ SYMBOL_CLASS (sym) = LOC_CONST;
+ SYMBOL_VALUE (sym) = dn_bufp->dconst.location;
+ SYMBOL_TYPE (sym) = hpread_type_lookup (dn_bufp->dconst.type, objfile);
+ if (dn_bufp->dconst.global)
+ add_symbol_to_list (sym, &global_symbols);
+ else if (WITHIN_FUNCTION (objfile))
+ add_symbol_to_list (sym, &local_symbols);
+ else
+ add_symbol_to_list (sym, &file_symbols);
+ break;
+ case DNTT_TYPE_TYPEDEF:
+ SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
+ SYMBOL_TYPE (sym) = hpread_type_lookup (dn_bufp->dtype.type, objfile);
+ if (dn_bufp->dtype.global)
+ add_symbol_to_list (sym, &global_symbols);
+ else if (WITHIN_FUNCTION (objfile))
+ add_symbol_to_list (sym, &local_symbols);
+ else
+ add_symbol_to_list (sym, &file_symbols);
+ break;
+ case DNTT_TYPE_TAGDEF:
+ SYMBOL_NAMESPACE (sym) = STRUCT_NAMESPACE;
+ SYMBOL_TYPE (sym) = hpread_type_lookup (dn_bufp->dtype.type, objfile);
+ TYPE_NAME (sym->type) = SYMBOL_NAME (sym);
+ TYPE_TAG_NAME (sym->type) = SYMBOL_NAME (sym);
+ if (dn_bufp->dtype.global)
+ add_symbol_to_list (sym, &global_symbols);
+ else if (WITHIN_FUNCTION (objfile))
+ add_symbol_to_list (sym, &local_symbols);
+ else
+ add_symbol_to_list (sym, &file_symbols);
+ break;
+ case DNTT_TYPE_POINTER:
+ SYMBOL_TYPE (sym) = lookup_pointer_type (hpread_type_lookup
+ (dn_bufp->dptr.pointsto,
+ objfile));
+ add_symbol_to_list (sym, &file_symbols);
+ break;
+ case DNTT_TYPE_ENUM:
+ SYMBOL_NAMESPACE (sym) = STRUCT_NAMESPACE;
+ SYMBOL_TYPE (sym) = hpread_read_enum_type (hp_type, dn_bufp, objfile);
+ add_symbol_to_list (sym, &file_symbols);
+ break;
+ case DNTT_TYPE_MEMENUM:
+ break;
+ case DNTT_TYPE_SET:
+ SYMBOL_TYPE (sym) = hpread_read_set_type (hp_type, dn_bufp, objfile);
+ add_symbol_to_list (sym, &file_symbols);
+ break;
+ case DNTT_TYPE_SUBRANGE:
+ SYMBOL_TYPE (sym) = hpread_read_subrange_type (hp_type, dn_bufp,
+ objfile);
+ add_symbol_to_list (sym, &file_symbols);
+ break;
+ case DNTT_TYPE_ARRAY:
+ SYMBOL_TYPE (sym) = hpread_read_array_type (hp_type, dn_bufp, objfile);
+ add_symbol_to_list (sym, &file_symbols);
+ break;
+ case DNTT_TYPE_STRUCT:
+ case DNTT_TYPE_UNION:
+ SYMBOL_NAMESPACE (sym) = STRUCT_NAMESPACE;
+ SYMBOL_TYPE (sym) = hpread_read_struct_type (hp_type, dn_bufp, objfile);
+ add_symbol_to_list (sym, &file_symbols);
+ break;
+ default:
+ break;
+ }
+}
diff --git a/gdb/hpread.h b/gdb/hpread.h
new file mode 100644
index 00000000000..7864dd65150
--- /dev/null
+++ b/gdb/hpread.h
@@ -0,0 +1,150 @@
+/* hpread.h
+ * Common include file for:
+ * hp_symtab_read.c
+ * hp_psymtab_read.c
+ */
+
+/* Copyright 1993, 1996 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Written by the Center for Software Science at the University of Utah
+ and by Cygnus Support. */
+
+#include "defs.h"
+#include "bfd.h"
+#include "gdb_string.h"
+#include "hp-symtab.h"
+#include "syms.h"
+#include "symtab.h"
+#include "symfile.h"
+#include "objfiles.h"
+#include "buildsym.h"
+#include "complaints.h"
+#include "gdb-stabs.h"
+#include "gdbtypes.h"
+#include "demangle.h"
+
+/* Private information attached to an objfile which we use to find
+ and internalize the HP C debug symbols within that objfile. */
+
+struct hpread_symfile_info
+{
+ /* The contents of each of the debug sections (there are 4 of them). */
+ char *gntt;
+ char *lntt;
+ char *slt;
+ char *vt;
+
+ /* We keep the size of the $VT$ section for range checking. */
+ unsigned int vt_size;
+
+ /* Some routines still need to know the number of symbols in the
+ main debug sections ($LNTT$ and $GNTT$). */
+ unsigned int lntt_symcount;
+ unsigned int gntt_symcount;
+
+ /* To keep track of all the types we've processed. */
+ struct type **type_vector;
+ int type_vector_length;
+
+ /* Keeps track of the beginning of a range of source lines. */
+ sltpointer sl_index;
+
+ /* Some state variables we'll need. */
+ int within_function;
+
+ /* Keep track of the current function's address. We may need to look
+ up something based on this address. */
+ unsigned int current_function_value;
+};
+
+/* Accessor macros to get at the fields. */
+#define HPUX_SYMFILE_INFO(o) \
+ ((struct hpread_symfile_info *)((o)->sym_private))
+#define GNTT(o) (HPUX_SYMFILE_INFO(o)->gntt)
+#define LNTT(o) (HPUX_SYMFILE_INFO(o)->lntt)
+#define SLT(o) (HPUX_SYMFILE_INFO(o)->slt)
+#define VT(o) (HPUX_SYMFILE_INFO(o)->vt)
+#define VT_SIZE(o) (HPUX_SYMFILE_INFO(o)->vt_size)
+#define LNTT_SYMCOUNT(o) (HPUX_SYMFILE_INFO(o)->lntt_symcount)
+#define GNTT_SYMCOUNT(o) (HPUX_SYMFILE_INFO(o)->gntt_symcount)
+#define TYPE_VECTOR(o) (HPUX_SYMFILE_INFO(o)->type_vector)
+#define TYPE_VECTOR_LENGTH(o) (HPUX_SYMFILE_INFO(o)->type_vector_length)
+#define SL_INDEX(o) (HPUX_SYMFILE_INFO(o)->sl_index)
+#define WITHIN_FUNCTION(o) (HPUX_SYMFILE_INFO(o)->within_function)
+#define CURRENT_FUNCTION_VALUE(o) (HPUX_SYMFILE_INFO(o)->current_function_value)
+
+/* Given the native debug symbol SYM, set NAMEP to the name associated
+ with the debug symbol. Note we may be called with a debug symbol which
+ has no associated name, in that case we return an empty string.
+
+ Also note we "know" that the name for any symbol is always in the
+ same place. Hence we don't have to conditionalize on the symbol type. */
+#define SET_NAMESTRING(SYM, NAMEP, OBJFILE) \
+ if (! hpread_has_name ((SYM)->dblock.kind)) \
+ *NAMEP = ""; \
+ else if (((unsigned)(SYM)->dsfile.name) >= VT_SIZE (OBJFILE)) \
+ { \
+ complain (&string_table_offset_complaint, (char *) symnum); \
+ *NAMEP = ""; \
+ } \
+ else \
+ *NAMEP = (SYM)->dsfile.name + VT (OBJFILE)
+
+/* We put a pointer to this structure in the read_symtab_private field
+ of the psymtab. */
+
+struct symloc
+{
+ /* The offset within the file symbol table of first local symbol for
+ this file. */
+
+ int ldsymoff;
+
+ /* 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). 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. */
+
+ int ldsymlen;
+};
+
+#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))
+
+/* FIXME: Shouldn't this stuff be in a .h file somewhere? */
+/* Nonzero means give verbose info on gdb action. */
+extern int info_verbose;
+
+/* Complaints about the symbols we have encountered. */
+extern struct complaint string_table_offset_complaint;
+extern struct complaint lbrac_unmatched_complaint;
+extern struct complaint lbrac_mismatch_complaint;
+
+extern union sltentry *hpread_get_slt
+ PARAMS ((int, struct objfile *));
+
+extern union dnttentry *hpread_get_lntt
+ PARAMS ((int, struct objfile *));
+
+int hpread_has_name
+ PARAMS ((enum dntt_entry_type));
+
+/* end of hpread.h */
diff --git a/gdb/hpux-thread.c b/gdb/hpux-thread.c
new file mode 100644
index 00000000000..36421f390ab
--- /dev/null
+++ b/gdb/hpux-thread.c
@@ -0,0 +1,641 @@
+/* Low level interface for debugging HPUX/DCE threads for GDB, the GNU debugger.
+ Copyright 1996, 1999 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* This module implements a sort of half target that sits between the
+ machine-independent parts of GDB and the ptrace interface (infptrace.c) to
+ provide access to the HPUX user-mode thread implementation.
+
+ HPUX threads are true user-mode threads, which are invoked via the cma_*
+ and pthread_* (DCE and Posix respectivly) interfaces. These are mostly
+ implemented in user-space, with all thread context kept in various
+ structures that live in the user's heap. For the most part, the kernel has
+ no knowlege of these threads.
+
+ */
+
+#include "defs.h"
+
+#define _CMA_NOWRAPPERS_
+
+#include <cma_tcb_defs.h>
+#include <cma_deb_core.h>
+#include "gdbthread.h"
+#include "target.h"
+#include "inferior.h"
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include "gdbcore.h"
+
+extern int child_suppress_run;
+extern struct target_ops child_ops; /* target vector for inftarg.c */
+
+extern void _initialize_hpux_thread PARAMS ((void));
+
+struct string_map
+{
+ int num;
+ char *str;
+};
+
+static int hpux_thread_active = 0;
+
+static int main_pid; /* Real process ID */
+
+static CORE_ADDR P_cma__g_known_threads;
+static CORE_ADDR P_cma__g_current_thread;
+
+static struct cleanup * save_inferior_pid PARAMS ((void));
+
+static void restore_inferior_pid PARAMS ((int pid));
+
+static void hpux_thread_resume PARAMS ((int pid, int step,
+ enum target_signal signo));
+
+static void init_hpux_thread_ops PARAMS ((void));
+
+static struct target_ops hpux_thread_ops;
+
+/*
+
+LOCAL FUNCTION
+
+ save_inferior_pid - Save inferior_pid on the cleanup list
+ restore_inferior_pid - Restore inferior_pid from the cleanup list
+
+SYNOPSIS
+
+ struct cleanup *save_inferior_pid ()
+ void restore_inferior_pid (int pid)
+
+DESCRIPTION
+
+ These two functions act in unison to restore inferior_pid in
+ case of an error.
+
+NOTES
+
+ inferior_pid is a global variable that needs to be changed by many of
+ these routines before calling functions in procfs.c. In order to
+ guarantee that inferior_pid gets restored (in case of errors), you
+ need to call save_inferior_pid before changing it. At the end of the
+ function, you should invoke do_cleanups to restore it.
+
+ */
+
+
+static struct cleanup *
+save_inferior_pid ()
+{
+ return make_cleanup (restore_inferior_pid, inferior_pid);
+}
+
+static void
+restore_inferior_pid (pid)
+ int pid;
+{
+ inferior_pid = pid;
+}
+
+static int find_active_thread PARAMS ((void));
+
+static int cached_thread;
+static int cached_active_thread;
+static cma__t_int_tcb cached_tcb;
+
+static int
+find_active_thread ()
+{
+ static cma__t_int_tcb tcb;
+ CORE_ADDR tcb_ptr;
+
+ if (cached_active_thread != 0)
+ return cached_active_thread;
+
+ read_memory ((CORE_ADDR)P_cma__g_current_thread,
+ (char *)&tcb_ptr,
+ sizeof tcb_ptr);
+
+ read_memory (tcb_ptr, (char *)&tcb, sizeof tcb);
+
+ return (cma_thread_get_unique (&tcb.prolog.client_thread) << 16) | main_pid;
+}
+
+static cma__t_int_tcb * find_tcb PARAMS ((int thread));
+
+static cma__t_int_tcb *
+find_tcb (thread)
+ int thread;
+{
+ cma__t_known_object queue_header;
+ cma__t_queue *queue_ptr;
+
+ if (thread == cached_thread)
+ return &cached_tcb;
+
+ read_memory ((CORE_ADDR)P_cma__g_known_threads,
+ (char *)&queue_header,
+ sizeof queue_header);
+
+ for (queue_ptr = queue_header.queue.flink;
+ queue_ptr != (cma__t_queue *)P_cma__g_known_threads;
+ queue_ptr = cached_tcb.threads.flink)
+ {
+ cma__t_int_tcb *tcb_ptr;
+
+ tcb_ptr = cma__base (queue_ptr, threads, cma__t_int_tcb);
+
+ read_memory ((CORE_ADDR)tcb_ptr, (char *)&cached_tcb, sizeof cached_tcb);
+
+ if (cached_tcb.header.type == cma__c_obj_tcb)
+ if (cma_thread_get_unique (&cached_tcb.prolog.client_thread) == thread >> 16)
+ {
+ cached_thread = thread;
+ return &cached_tcb;
+ }
+ }
+
+ error ("Can't find TCB %d,%d", thread >> 16, thread & 0xffff);
+ return NULL;
+}
+
+/* Most target vector functions from here on actually just pass through to
+ inftarg.c, as they don't need to do anything specific for threads. */
+
+/* ARGSUSED */
+static void
+hpux_thread_open (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ child_ops.to_open (arg, from_tty);
+}
+
+/* Attach to process PID, then initialize for debugging it
+ and wait for the trace-trap that results from attaching. */
+
+static void
+hpux_thread_attach (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ child_ops.to_attach (args, from_tty);
+
+ /* XXX - might want to iterate over all the threads and register them. */
+}
+
+/* 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
+hpux_thread_detach (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ child_ops.to_detach (args, from_tty);
+}
+
+/* Resume execution of process PID. If STEP is nozero, then
+ just single step it. If SIGNAL is nonzero, restart it with that
+ signal activated. We may have to convert pid from a thread-id to an LWP id
+ for procfs. */
+
+static void
+hpux_thread_resume (pid, step, signo)
+ int pid;
+ int step;
+ enum target_signal signo;
+{
+ struct cleanup *old_chain;
+
+ old_chain = save_inferior_pid ();
+
+ pid = inferior_pid = main_pid;
+
+#if 0
+ if (pid != -1)
+ {
+ pid = thread_to_lwp (pid, -2);
+ if (pid == -2) /* Inactive thread */
+ error ("This version of Solaris can't start inactive threads.");
+ }
+#endif
+
+ child_ops.to_resume (pid, step, signo);
+
+ cached_thread = 0;
+ cached_active_thread = 0;
+
+ do_cleanups (old_chain);
+}
+
+/* Wait for any threads to stop. We may have to convert PID from a thread id
+ to a LWP id, and vice versa on the way out. */
+
+static int
+hpux_thread_wait (pid, ourstatus)
+ int pid;
+ struct target_waitstatus *ourstatus;
+{
+ int rtnval;
+ struct cleanup *old_chain;
+
+ old_chain = save_inferior_pid ();
+
+ inferior_pid = main_pid;
+
+ if (pid != -1)
+ pid = main_pid;
+
+ rtnval = child_ops.to_wait (pid, ourstatus);
+
+ rtnval = find_active_thread ();
+
+ do_cleanups (old_chain);
+
+ return rtnval;
+}
+
+static char regmap[NUM_REGS] =
+{
+ -2, -1, -1, 0, 4, 8, 12, 16, 20, 24, /* flags, r1 -> r9 */
+ 28, 32, 36, 40, 44, 48, 52, 56, 60, -1, /* r10 -> r19 */
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* r20 -> r29 */
+
+ /* r30, r31, sar, pcoqh, pcsqh, pcoqt, pcsqt, eiem, iir, isr */
+ -2, -1, -1, -2, -1, -1, -1, -1, -1, -1,
+
+ /* ior, ipsw, goto, sr4, sr0, sr1, sr2, sr3, sr5, sr6 */
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+
+ /* sr7, cr0, cr8, cr9, ccr, cr12, cr13, cr24, cr25, cr26 */
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+
+ -1, -1, -1, -1, /* mpsfu_high, mpsfu_low, mpsfu_ovflo, pad */
+ 144, -1, -1, -1, -1, -1, -1, -1, /* fpsr, fpe1 -> fpe7 */
+ -1, -1, -1, -1, -1, -1, -1, -1, /* fr4 -> fr7 */
+ -1, -1, -1, -1, -1, -1, -1, -1, /* fr8 -> fr11 */
+ 136, -1, 128, -1, 120, -1, 112, -1, /* fr12 -> fr15 */
+ 104, -1, 96, -1, 88, -1, 80, -1, /* fr16 -> fr19 */
+ 72, -1, 64, -1, -1, -1, -1, -1, /* fr20 -> fr23 */
+ -1, -1, -1, -1, -1, -1, -1, -1, /* fr24 -> fr27 */
+ -1, -1, -1, -1, -1, -1, -1, -1, /* fr28 -> fr31 */
+};
+
+static void
+hpux_thread_fetch_registers (regno)
+ int regno;
+{
+ cma__t_int_tcb tcb, *tcb_ptr;
+ struct cleanup *old_chain;
+ int i;
+ int first_regno, last_regno;
+
+ tcb_ptr = find_tcb (inferior_pid);
+
+ old_chain = save_inferior_pid ();
+
+ inferior_pid = main_pid;
+
+ if (tcb_ptr->state == cma__c_state_running)
+ {
+ child_ops.to_fetch_registers (regno);
+
+ do_cleanups (old_chain);
+
+ return;
+ }
+
+ if (regno == -1)
+ {
+ first_regno = 0;
+ last_regno = NUM_REGS - 1;
+ }
+ else
+ {
+ first_regno = regno;
+ last_regno = regno;
+ }
+
+ for (regno = first_regno; regno <= last_regno; regno++)
+ {
+ if (regmap[regno] == -1)
+ child_ops.to_fetch_registers (regno);
+ else
+ {
+ unsigned char buf[MAX_REGISTER_RAW_SIZE];
+ CORE_ADDR sp;
+
+ sp = (CORE_ADDR)tcb_ptr->static_ctx.sp - 160;
+
+ if (regno == FLAGS_REGNUM)
+ /* Flags must be 0 to avoid bogus value for SS_INSYSCALL */
+ memset (buf, '\000', REGISTER_RAW_SIZE (regno));
+ else if (regno == SP_REGNUM)
+ store_address (buf, sizeof sp, sp);
+ else if (regno == PC_REGNUM)
+ read_memory (sp - 20, buf, REGISTER_RAW_SIZE (regno));
+ else
+ read_memory (sp + regmap[regno], buf, REGISTER_RAW_SIZE (regno));
+
+ supply_register (regno, buf);
+ }
+ }
+
+ do_cleanups (old_chain);
+}
+
+static void
+hpux_thread_store_registers (regno)
+ int regno;
+{
+ cma__t_int_tcb tcb, *tcb_ptr;
+ struct cleanup *old_chain;
+ int i;
+ int first_regno, last_regno;
+
+ tcb_ptr = find_tcb (inferior_pid);
+
+ old_chain = save_inferior_pid ();
+
+ inferior_pid = main_pid;
+
+ if (tcb_ptr->state == cma__c_state_running)
+ {
+ child_ops.to_store_registers (regno);
+
+ do_cleanups (old_chain);
+
+ return;
+ }
+
+ if (regno == -1)
+ {
+ first_regno = 0;
+ last_regno = NUM_REGS - 1;
+ }
+ else
+ {
+ first_regno = regno;
+ last_regno = regno;
+ }
+
+ for (regno = first_regno; regno <= last_regno; regno++)
+ {
+ if (regmap[regno] == -1)
+ child_ops.to_store_registers (regno);
+ else
+ {
+ unsigned char buf[MAX_REGISTER_RAW_SIZE];
+ CORE_ADDR sp;
+
+ sp = (CORE_ADDR)tcb_ptr->static_ctx.sp - 160;
+
+ if (regno == FLAGS_REGNUM)
+ child_ops.to_store_registers (regno); /* Let lower layer handle this... */
+ else if (regno == SP_REGNUM)
+ {
+ write_memory ((CORE_ADDR)&tcb_ptr->static_ctx.sp,
+ registers + REGISTER_BYTE (regno),
+ REGISTER_RAW_SIZE (regno));
+ tcb_ptr->static_ctx.sp = (cma__t_hppa_regs *)
+ (extract_address (registers + REGISTER_BYTE (regno), REGISTER_RAW_SIZE (regno)) + 160);
+ }
+ else if (regno == PC_REGNUM)
+ write_memory (sp - 20,
+ registers + REGISTER_BYTE (regno),
+ REGISTER_RAW_SIZE (regno));
+ else
+ write_memory (sp + regmap[regno],
+ registers + REGISTER_BYTE (regno),
+ REGISTER_RAW_SIZE (regno));
+ }
+ }
+
+ do_cleanups (old_chain);
+}
+
+/* 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
+hpux_thread_prepare_to_store ()
+{
+ child_ops.to_prepare_to_store ();
+}
+
+static int
+hpux_thread_xfer_memory (memaddr, myaddr, len, dowrite, target)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+ int dowrite;
+ struct target_ops *target; /* ignored */
+{
+ int retval;
+ struct cleanup *old_chain;
+
+ old_chain = save_inferior_pid ();
+
+ inferior_pid = main_pid;
+
+ retval = child_ops.to_xfer_memory (memaddr, myaddr, len, dowrite, target);
+
+ do_cleanups (old_chain);
+
+ return retval;
+}
+
+/* Print status information about what we're accessing. */
+
+static void
+hpux_thread_files_info (ignore)
+ struct target_ops *ignore;
+{
+ child_ops.to_files_info (ignore);
+}
+
+static void
+hpux_thread_kill_inferior ()
+{
+ child_ops.to_kill ();
+}
+
+static void
+hpux_thread_notice_signals (pid)
+ int pid;
+{
+ child_ops.to_notice_signals (pid);
+}
+
+/* Fork an inferior process, and start debugging it with /proc. */
+
+static void
+hpux_thread_create_inferior (exec_file, allargs, env)
+ char *exec_file;
+ char *allargs;
+ char **env;
+{
+ child_ops.to_create_inferior (exec_file, allargs, env);
+
+ if (hpux_thread_active)
+ {
+ main_pid = inferior_pid;
+
+ push_target (&hpux_thread_ops);
+
+ inferior_pid = find_active_thread ();
+
+ add_thread (inferior_pid);
+ }
+}
+
+/* This routine is called whenever a new symbol table is read in, or when all
+ symbol tables are removed. libthread_db can only be initialized when it
+ finds the right variables in libthread.so. Since it's a shared library,
+ those variables don't show up until the library gets mapped and the symbol
+ table is read in. */
+
+void
+hpux_thread_new_objfile (objfile)
+ struct objfile *objfile;
+{
+ struct minimal_symbol *ms;
+
+ if (!objfile)
+ {
+ hpux_thread_active = 0;
+
+ return;
+ }
+
+ ms = lookup_minimal_symbol ("cma__g_known_threads", NULL, objfile);
+
+ if (!ms)
+ return;
+
+ P_cma__g_known_threads = SYMBOL_VALUE_ADDRESS (ms);
+
+ ms = lookup_minimal_symbol ("cma__g_current_thread", NULL, objfile);
+
+ if (!ms)
+ return;
+
+ P_cma__g_current_thread = SYMBOL_VALUE_ADDRESS (ms);
+
+ hpux_thread_active = 1;
+}
+
+/* Clean up after the inferior dies. */
+
+static void
+hpux_thread_mourn_inferior ()
+{
+ child_ops.to_mourn_inferior ();
+}
+
+/* Mark our target-struct as eligible for stray "run" and "attach" commands. */
+
+static int
+hpux_thread_can_run ()
+{
+ return child_suppress_run;
+}
+
+static int
+hpux_thread_alive (pid)
+ int pid;
+{
+ return 1;
+}
+
+static void
+hpux_thread_stop ()
+{
+ child_ops.to_stop ();
+}
+
+/* Convert a pid to printable form. */
+
+char *
+hpux_pid_to_str (pid)
+ int pid;
+{
+ static char buf[100];
+
+ sprintf (buf, "Thread %d", pid >> 16);
+
+ return buf;
+}
+
+static void
+init_hpux_thread_ops ()
+{
+ hpux_thread_ops.to_shortname = "hpux-threads";
+ hpux_thread_ops.to_longname = "HPUX threads and pthread.";
+ hpux_thread_ops.to_doc = "HPUX threads and pthread support.";
+ hpux_thread_ops.to_open = hpux_thread_open;
+ hpux_thread_ops.to_attach = hpux_thread_attach;
+ hpux_thread_ops.to_detach = hpux_thread_detach;
+ hpux_thread_ops.to_resume = hpux_thread_resume;
+ hpux_thread_ops.to_wait = hpux_thread_wait;
+ hpux_thread_ops.to_fetch_registers = hpux_thread_fetch_registers;
+ hpux_thread_ops.to_store_registers = hpux_thread_store_registers;
+ hpux_thread_ops.to_prepare_to_store = hpux_thread_prepare_to_store;
+ hpux_thread_ops.to_xfer_memory = hpux_thread_xfer_memory;
+ hpux_thread_ops.to_files_info = hpux_thread_files_info;
+ hpux_thread_ops.to_insert_breakpoint = memory_insert_breakpoint;
+ hpux_thread_ops.to_remove_breakpoint = memory_remove_breakpoint;
+ hpux_thread_ops.to_terminal_init = terminal_init_inferior;
+ hpux_thread_ops.to_terminal_inferior = terminal_inferior;
+ hpux_thread_ops.to_terminal_ours_for_output = terminal_ours_for_output;
+ hpux_thread_ops.to_terminal_ours = terminal_ours;
+ hpux_thread_ops.to_terminal_info = child_terminal_info;
+ hpux_thread_ops.to_kill = hpux_thread_kill_inferior;
+ hpux_thread_ops.to_create_inferior = hpux_thread_create_inferior;
+ hpux_thread_ops.to_mourn_inferior = hpux_thread_mourn_inferior;
+ hpux_thread_ops.to_can_run = hpux_thread_can_run;
+ hpux_thread_ops.to_notice_signals = hpux_thread_notice_signals;
+ hpux_thread_ops.to_thread_alive = hpux_thread_thread_alive;
+ hpux_thread_ops.to_stop = hpux_thread_stop;
+ hpux_thread_ops.to_stratum = process_stratum;
+ hpux_thread_ops.to_has_all_memory = 1;
+ hpux_thread_ops.to_has_memory = 1;
+ hpux_thread_ops.to_has_stack = 1;
+ hpux_thread_ops.to_has_registers = 1;
+ hpux_thread_ops.to_has_execution = 1;
+ hpux_thread_ops.to_magic = OPS_MAGIC;
+}
+
+void
+_initialize_hpux_thread ()
+{
+ init_hpux_thread_ops ();
+ add_target (&hpux_thread_ops);
+
+ child_suppress_run = 1;
+}
diff --git a/gdb/i386-stub.c b/gdb/i386-stub.c
new file mode 100644
index 00000000000..768f00c3c8e
--- /dev/null
+++ b/gdb/i386-stub.c
@@ -0,0 +1,927 @@
+/****************************************************************************
+
+ THIS SOFTWARE IS NOT COPYRIGHTED
+
+ HP offers the following for use in the public domain. HP makes no
+ warranty with regard to the software or it's performance and the
+ user accepts the software "AS IS" with all faults.
+
+ HP DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD
+ TO THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+
+****************************************************************************/
+
+/****************************************************************************
+ * Header: remcom.c,v 1.34 91/03/09 12:29:49 glenne Exp $
+ *
+ * Module name: remcom.c $
+ * Revision: 1.34 $
+ * Date: 91/03/09 12:29:49 $
+ * Contributor: Lake Stevens Instrument Division$
+ *
+ * Description: low level support for gdb debugger. $
+ *
+ * Considerations: only works on target hardware $
+ *
+ * Written by: Glenn Engel $
+ * ModuleState: Experimental $
+ *
+ * NOTES: See Below $
+ *
+ * Modified for 386 by Jim Kingdon, Cygnus Support.
+ *
+ * To enable debugger support, two things need to happen. One, a
+ * call to set_debug_traps() is necessary in order to allow any breakpoints
+ * or error conditions to be properly intercepted and reported to gdb.
+ * Two, a breakpoint needs to be generated to begin communication. This
+ * is most easily accomplished by a call to breakpoint(). Breakpoint()
+ * simulates a breakpoint by executing a trap #1.
+ *
+ * The external function exceptionHandler() is
+ * used to attach a specific handler to a specific 386 vector number.
+ * It should use the same privilege level it runs at. It should
+ * install it as an interrupt gate so that interrupts are masked
+ * while the handler runs.
+ * Also, need to assign exceptionHook and oldExceptionHook.
+ *
+ * Because gdb will sometimes write to the stack area to execute function
+ * calls, this program cannot rely on using the supervisor stack so it
+ * uses it's own stack area reserved in the int array remcomStack.
+ *
+ *************
+ *
+ * The following gdb commands are supported:
+ *
+ * command function Return value
+ *
+ * g return the value of the CPU registers hex data or ENN
+ * G set the value of the CPU registers OK or ENN
+ *
+ * mAA..AA,LLLL Read LLLL bytes at address AA..AA hex data or ENN
+ * MAA..AA,LLLL: Write LLLL bytes at address AA.AA OK or ENN
+ *
+ * c Resume at current address SNN ( signal NN)
+ * cAA..AA Continue at address AA..AA SNN
+ *
+ * s Step one instruction SNN
+ * sAA..AA Step one instruction from AA..AA SNN
+ *
+ * k kill
+ *
+ * ? What was the last sigval ? SNN (signal NN)
+ *
+ * All commands and responses are sent with a packet which includes a
+ * checksum. A packet consists of
+ *
+ * $<packet info>#<checksum>.
+ *
+ * where
+ * <packet info> :: <characters representing the command or response>
+ * <checksum> :: < two hex digits computed as modulo 256 sum of <packetinfo>>
+ *
+ * When a packet is received, it is first acknowledged with either '+' or '-'.
+ * '+' indicates a successful transfer. '-' indicates a failed transfer.
+ *
+ * Example:
+ *
+ * Host: Reply:
+ * $m0,10#2a +$00010203040506070809101112131415#42
+ *
+ ****************************************************************************/
+
+#include <stdio.h>
+#include <string.h>
+
+/************************************************************************
+ *
+ * external low-level support routines
+ */
+typedef void (*ExceptionHook)(int); /* pointer to function with int parm */
+typedef void (*Function)(); /* pointer to a function */
+
+extern void putDebugChar(); /* write a single character */
+extern int getDebugChar(); /* read and return a single char */
+
+extern Function exceptionHandler(); /* assign an exception handler */
+extern ExceptionHook exceptionHook; /* hook variable for errors/exceptions */
+
+/************************************************************************/
+/* BUFMAX defines the maximum number of characters in inbound/outbound buffers*/
+/* at least NUMREGBYTES*2 are needed for register packets */
+#define BUFMAX 400
+
+static char initialized; /* boolean flag. != 0 means we've been initialized */
+
+int remote_debug;
+/* debug > 0 prints ill-formed commands in valid packets & checksum errors */
+
+void waitabit();
+
+static const char hexchars[]="0123456789abcdef";
+
+/* Number of registers. */
+#define NUMREGS 16
+
+/* Number of bytes of registers. */
+#define NUMREGBYTES (NUMREGS * 4)
+
+enum regnames {EAX, ECX, EDX, EBX, ESP, EBP, ESI, EDI,
+ PC /* also known as eip */,
+ PS /* also known as eflags */,
+ CS, SS, DS, ES, FS, GS};
+
+/*
+ * these should not be static cuz they can be used outside this module
+ */
+int registers[NUMREGS];
+
+#define STACKSIZE 10000
+int remcomStack[STACKSIZE/sizeof(int)];
+static int* stackPtr = &remcomStack[STACKSIZE/sizeof(int) - 1];
+
+/*
+ * In many cases, the system will want to continue exception processing
+ * when a continue command is given.
+ * oldExceptionHook is a function to invoke in this case.
+ */
+
+static ExceptionHook oldExceptionHook;
+
+/*************************** ASSEMBLY CODE MACROS *************************/
+/* */
+
+extern void
+return_to_prog ();
+
+/* Restore the program's registers (including the stack pointer, which
+ means we get the right stack and don't have to worry about popping our
+ return address and any stack frames and so on) and return. */
+asm(".text");
+asm(".globl _return_to_prog");
+asm("_return_to_prog:");
+asm(" movw _registers+44, %ss");
+asm(" movl _registers+16, %esp");
+asm(" movl _registers+4, %ecx");
+asm(" movl _registers+8, %edx");
+asm(" movl _registers+12, %ebx");
+asm(" movl _registers+20, %ebp");
+asm(" movl _registers+24, %esi");
+asm(" movl _registers+28, %edi");
+asm(" movw _registers+48, %ds");
+asm(" movw _registers+52, %es");
+asm(" movw _registers+56, %fs");
+asm(" movw _registers+60, %gs");
+asm(" movl _registers+36, %eax");
+asm(" pushl %eax"); /* saved eflags */
+asm(" movl _registers+40, %eax");
+asm(" pushl %eax"); /* saved cs */
+asm(" movl _registers+32, %eax");
+asm(" pushl %eax"); /* saved eip */
+asm(" movl _registers, %eax");
+/* use iret to restore pc and flags together so
+ that trace flag works right. */
+asm(" iret");
+
+#define BREAKPOINT() asm(" int $3");
+
+/* Put the error code here just in case the user cares. */
+int gdb_i386errcode;
+/* Likewise, the vector number here (since GDB only gets the signal
+ number through the usual means, and that's not very specific). */
+int gdb_i386vector = -1;
+
+/* GDB stores segment registers in 32-bit words (that's just the way
+ m-i386v.h is written). So zero the appropriate areas in registers. */
+#define SAVE_REGISTERS1() \
+ asm ("movl %eax, _registers"); \
+ asm ("movl %ecx, _registers+4"); \
+ asm ("movl %edx, _registers+8"); \
+ asm ("movl %ebx, _registers+12"); \
+ asm ("movl %ebp, _registers+20"); \
+ asm ("movl %esi, _registers+24"); \
+ asm ("movl %edi, _registers+28"); \
+ asm ("movw $0, %ax"); \
+ asm ("movw %ds, _registers+48"); \
+ asm ("movw %ax, _registers+50"); \
+ asm ("movw %es, _registers+52"); \
+ asm ("movw %ax, _registers+54"); \
+ asm ("movw %fs, _registers+56"); \
+ asm ("movw %ax, _registers+58"); \
+ asm ("movw %gs, _registers+60"); \
+ asm ("movw %ax, _registers+62");
+#define SAVE_ERRCODE() \
+ asm ("popl %ebx"); \
+ asm ("movl %ebx, _gdb_i386errcode");
+#define SAVE_REGISTERS2() \
+ asm ("popl %ebx"); /* old eip */ \
+ asm ("movl %ebx, _registers+32"); \
+ asm ("popl %ebx"); /* old cs */ \
+ asm ("movl %ebx, _registers+40"); \
+ asm ("movw %ax, _registers+42"); \
+ asm ("popl %ebx"); /* old eflags */ \
+ asm ("movl %ebx, _registers+36"); \
+ /* Now that we've done the pops, we can save the stack pointer."); */ \
+ asm ("movw %ss, _registers+44"); \
+ asm ("movw %ax, _registers+46"); \
+ asm ("movl %esp, _registers+16");
+
+/* See if mem_fault_routine is set, if so just IRET to that address. */
+#define CHECK_FAULT() \
+ asm ("cmpl $0, _mem_fault_routine"); \
+ asm ("jne mem_fault");
+
+asm (".text");
+asm ("mem_fault:");
+/* OK to clobber temp registers; we're just going to end up in set_mem_err. */
+/* Pop error code from the stack and save it. */
+asm (" popl %eax");
+asm (" movl %eax, _gdb_i386errcode");
+
+asm (" popl %eax"); /* eip */
+/* We don't want to return there, we want to return to the function
+ pointed to by mem_fault_routine instead. */
+asm (" movl _mem_fault_routine, %eax");
+asm (" popl %ecx"); /* cs (low 16 bits; junk in hi 16 bits). */
+asm (" popl %edx"); /* eflags */
+
+/* Remove this stack frame; when we do the iret, we will be going to
+ the start of a function, so we want the stack to look just like it
+ would after a "call" instruction. */
+asm (" leave");
+
+/* Push the stuff that iret wants. */
+asm (" pushl %edx"); /* eflags */
+asm (" pushl %ecx"); /* cs */
+asm (" pushl %eax"); /* eip */
+
+/* Zero mem_fault_routine. */
+asm (" movl $0, %eax");
+asm (" movl %eax, _mem_fault_routine");
+
+asm ("iret");
+
+#define CALL_HOOK() asm("call _remcomHandler");
+
+/* This function is called when a i386 exception occurs. It saves
+ * all the cpu regs in the _registers array, munges the stack a bit,
+ * and invokes an exception handler (remcom_handler).
+ *
+ * stack on entry: stack on exit:
+ * old eflags vector number
+ * old cs (zero-filled to 32 bits)
+ * old eip
+ *
+ */
+extern void _catchException3();
+asm(".text");
+asm(".globl __catchException3");
+asm("__catchException3:");
+SAVE_REGISTERS1();
+SAVE_REGISTERS2();
+asm ("pushl $3");
+CALL_HOOK();
+
+/* Same thing for exception 1. */
+extern void _catchException1();
+asm(".text");
+asm(".globl __catchException1");
+asm("__catchException1:");
+SAVE_REGISTERS1();
+SAVE_REGISTERS2();
+asm ("pushl $1");
+CALL_HOOK();
+
+/* Same thing for exception 0. */
+extern void _catchException0();
+asm(".text");
+asm(".globl __catchException0");
+asm("__catchException0:");
+SAVE_REGISTERS1();
+SAVE_REGISTERS2();
+asm ("pushl $0");
+CALL_HOOK();
+
+/* Same thing for exception 4. */
+extern void _catchException4();
+asm(".text");
+asm(".globl __catchException4");
+asm("__catchException4:");
+SAVE_REGISTERS1();
+SAVE_REGISTERS2();
+asm ("pushl $4");
+CALL_HOOK();
+
+/* Same thing for exception 5. */
+extern void _catchException5();
+asm(".text");
+asm(".globl __catchException5");
+asm("__catchException5:");
+SAVE_REGISTERS1();
+SAVE_REGISTERS2();
+asm ("pushl $5");
+CALL_HOOK();
+
+/* Same thing for exception 6. */
+extern void _catchException6();
+asm(".text");
+asm(".globl __catchException6");
+asm("__catchException6:");
+SAVE_REGISTERS1();
+SAVE_REGISTERS2();
+asm ("pushl $6");
+CALL_HOOK();
+
+/* Same thing for exception 7. */
+extern void _catchException7();
+asm(".text");
+asm(".globl __catchException7");
+asm("__catchException7:");
+SAVE_REGISTERS1();
+SAVE_REGISTERS2();
+asm ("pushl $7");
+CALL_HOOK();
+
+/* Same thing for exception 8. */
+extern void _catchException8();
+asm(".text");
+asm(".globl __catchException8");
+asm("__catchException8:");
+SAVE_REGISTERS1();
+SAVE_ERRCODE();
+SAVE_REGISTERS2();
+asm ("pushl $8");
+CALL_HOOK();
+
+/* Same thing for exception 9. */
+extern void _catchException9();
+asm(".text");
+asm(".globl __catchException9");
+asm("__catchException9:");
+SAVE_REGISTERS1();
+SAVE_REGISTERS2();
+asm ("pushl $9");
+CALL_HOOK();
+
+/* Same thing for exception 10. */
+extern void _catchException10();
+asm(".text");
+asm(".globl __catchException10");
+asm("__catchException10:");
+SAVE_REGISTERS1();
+SAVE_ERRCODE();
+SAVE_REGISTERS2();
+asm ("pushl $10");
+CALL_HOOK();
+
+/* Same thing for exception 12. */
+extern void _catchException12();
+asm(".text");
+asm(".globl __catchException12");
+asm("__catchException12:");
+SAVE_REGISTERS1();
+SAVE_ERRCODE();
+SAVE_REGISTERS2();
+asm ("pushl $12");
+CALL_HOOK();
+
+/* Same thing for exception 16. */
+extern void _catchException16();
+asm(".text");
+asm(".globl __catchException16");
+asm("__catchException16:");
+SAVE_REGISTERS1();
+SAVE_REGISTERS2();
+asm ("pushl $16");
+CALL_HOOK();
+
+/* For 13, 11, and 14 we have to deal with the CHECK_FAULT stuff. */
+
+/* Same thing for exception 13. */
+extern void _catchException13 ();
+asm (".text");
+asm (".globl __catchException13");
+asm ("__catchException13:");
+CHECK_FAULT();
+SAVE_REGISTERS1();
+SAVE_ERRCODE();
+SAVE_REGISTERS2();
+asm ("pushl $13");
+CALL_HOOK();
+
+/* Same thing for exception 11. */
+extern void _catchException11 ();
+asm (".text");
+asm (".globl __catchException11");
+asm ("__catchException11:");
+CHECK_FAULT();
+SAVE_REGISTERS1();
+SAVE_ERRCODE();
+SAVE_REGISTERS2();
+asm ("pushl $11");
+CALL_HOOK();
+
+/* Same thing for exception 14. */
+extern void _catchException14 ();
+asm (".text");
+asm (".globl __catchException14");
+asm ("__catchException14:");
+CHECK_FAULT();
+SAVE_REGISTERS1();
+SAVE_ERRCODE();
+SAVE_REGISTERS2();
+asm ("pushl $14");
+CALL_HOOK();
+
+/*
+ * remcomHandler is a front end for handle_exception. It moves the
+ * stack pointer into an area reserved for debugger use.
+ */
+asm("_remcomHandler:");
+asm(" popl %eax"); /* pop off return address */
+asm(" popl %eax"); /* get the exception number */
+asm(" movl _stackPtr, %esp"); /* move to remcom stack area */
+asm(" pushl %eax"); /* push exception onto stack */
+asm(" call _handle_exception"); /* this never returns */
+
+void _returnFromException()
+{
+ return_to_prog ();
+}
+
+int hex(ch)
+char ch;
+{
+ if ((ch >= 'a') && (ch <= 'f')) return (ch-'a'+10);
+ if ((ch >= '0') && (ch <= '9')) return (ch-'0');
+ if ((ch >= 'A') && (ch <= 'F')) return (ch-'A'+10);
+ return (-1);
+}
+
+
+/* scan for the sequence $<data>#<checksum> */
+void getpacket(buffer)
+char * buffer;
+{
+ unsigned char checksum;
+ unsigned char xmitcsum;
+ int i;
+ int count;
+ char ch;
+
+ do {
+ /* wait around for the start character, ignore all other characters */
+ while ((ch = (getDebugChar() & 0x7f)) != '$');
+ checksum = 0;
+ xmitcsum = -1;
+
+ count = 0;
+
+ /* now, read until a # or end of buffer is found */
+ while (count < BUFMAX) {
+ ch = getDebugChar() & 0x7f;
+ if (ch == '#') break;
+ checksum = checksum + ch;
+ buffer[count] = ch;
+ count = count + 1;
+ }
+ buffer[count] = 0;
+
+ if (ch == '#') {
+ xmitcsum = hex(getDebugChar() & 0x7f) << 4;
+ xmitcsum += hex(getDebugChar() & 0x7f);
+ if ((remote_debug ) && (checksum != xmitcsum)) {
+ fprintf (stderr ,"bad checksum. My count = 0x%x, sent=0x%x. buf=%s\n",
+ checksum,xmitcsum,buffer);
+ }
+
+ if (checksum != xmitcsum) putDebugChar('-'); /* failed checksum */
+ else {
+ putDebugChar('+'); /* successful transfer */
+ /* if a sequence char is present, reply the sequence ID */
+ if (buffer[2] == ':') {
+ putDebugChar( buffer[0] );
+ putDebugChar( buffer[1] );
+ /* remove sequence chars from buffer */
+ count = strlen(buffer);
+ for (i=3; i <= count; i++) buffer[i-3] = buffer[i];
+ }
+ }
+ }
+ } while (checksum != xmitcsum);
+
+}
+
+/* send the packet in buffer. */
+
+
+void putpacket(buffer)
+char * buffer;
+{
+ unsigned char checksum;
+ int count;
+ char ch;
+
+ /* $<packet info>#<checksum>. */
+ do {
+ putDebugChar('$');
+ checksum = 0;
+ count = 0;
+
+ while (ch=buffer[count]) {
+ putDebugChar(ch);
+ checksum += ch;
+ count += 1;
+ }
+
+ putDebugChar('#');
+ putDebugChar(hexchars[checksum >> 4]);
+ putDebugChar(hexchars[checksum % 16]);
+
+ } while ((getDebugChar() & 0x7f) != '+');
+
+}
+
+char remcomInBuffer[BUFMAX];
+char remcomOutBuffer[BUFMAX];
+static short error;
+
+
+void debug_error(format, parm)
+char * format;
+char * parm;
+{
+ if (remote_debug) fprintf (stderr,format,parm);
+}
+
+/* Address of a routine to RTE to if we get a memory fault. */
+static void (*volatile mem_fault_routine)() = NULL;
+
+/* Indicate to caller of mem2hex or hex2mem that there has been an
+ error. */
+static volatile int mem_err = 0;
+
+void
+set_mem_err ()
+{
+ mem_err = 1;
+}
+
+/* These are separate functions so that they are so short and sweet
+ that the compiler won't save any registers (if there is a fault
+ to mem_fault, they won't get restored, so there better not be any
+ saved). */
+int
+get_char (addr)
+ char *addr;
+{
+ return *addr;
+}
+
+void
+set_char (addr, val)
+ char *addr;
+ int val;
+{
+ *addr = val;
+}
+
+/* convert the memory pointed to by mem into hex, placing result in buf */
+/* return a pointer to the last char put in buf (null) */
+/* If MAY_FAULT is non-zero, then we should set mem_err in response to
+ a fault; if zero treat a fault like any other fault in the stub. */
+char* mem2hex(mem, buf, count, may_fault)
+char* mem;
+char* buf;
+int count;
+int may_fault;
+{
+ int i;
+ unsigned char ch;
+
+ if (may_fault)
+ mem_fault_routine = set_mem_err;
+ for (i=0;i<count;i++) {
+ ch = get_char (mem++);
+ if (may_fault && mem_err)
+ return (buf);
+ *buf++ = hexchars[ch >> 4];
+ *buf++ = hexchars[ch % 16];
+ }
+ *buf = 0;
+ if (may_fault)
+ mem_fault_routine = NULL;
+ return(buf);
+}
+
+/* convert the hex array pointed to by buf into binary to be placed in mem */
+/* return a pointer to the character AFTER the last byte written */
+char* hex2mem(buf, mem, count, may_fault)
+char* buf;
+char* mem;
+int count;
+int may_fault;
+{
+ int i;
+ unsigned char ch;
+
+ if (may_fault)
+ mem_fault_routine = set_mem_err;
+ for (i=0;i<count;i++) {
+ ch = hex(*buf++) << 4;
+ ch = ch + hex(*buf++);
+ set_char (mem++, ch);
+ if (may_fault && mem_err)
+ return (mem);
+ }
+ if (may_fault)
+ mem_fault_routine = NULL;
+ return(mem);
+}
+
+/* this function takes the 386 exception vector and attempts to
+ translate this number into a unix compatible signal value */
+int computeSignal( exceptionVector )
+int exceptionVector;
+{
+ int sigval;
+ switch (exceptionVector) {
+ case 0 : sigval = 8; break; /* divide by zero */
+ case 1 : sigval = 5; break; /* debug exception */
+ case 3 : sigval = 5; break; /* breakpoint */
+ case 4 : sigval = 16; break; /* into instruction (overflow) */
+ case 5 : sigval = 16; break; /* bound instruction */
+ case 6 : sigval = 4; break; /* Invalid opcode */
+ case 7 : sigval = 8; break; /* coprocessor not available */
+ case 8 : sigval = 7; break; /* double fault */
+ case 9 : sigval = 11; break; /* coprocessor segment overrun */
+ case 10 : sigval = 11; break; /* Invalid TSS */
+ case 11 : sigval = 11; break; /* Segment not present */
+ case 12 : sigval = 11; break; /* stack exception */
+ case 13 : sigval = 11; break; /* general protection */
+ case 14 : sigval = 11; break; /* page fault */
+ case 16 : sigval = 7; break; /* coprocessor error */
+ default:
+ sigval = 7; /* "software generated"*/
+ }
+ return (sigval);
+}
+
+/**********************************************/
+/* WHILE WE FIND NICE HEX CHARS, BUILD AN INT */
+/* RETURN NUMBER OF CHARS PROCESSED */
+/**********************************************/
+int hexToInt(char **ptr, int *intValue)
+{
+ int numChars = 0;
+ int hexValue;
+
+ *intValue = 0;
+
+ while (**ptr)
+ {
+ hexValue = hex(**ptr);
+ if (hexValue >=0)
+ {
+ *intValue = (*intValue <<4) | hexValue;
+ numChars ++;
+ }
+ else
+ break;
+
+ (*ptr)++;
+ }
+
+ return (numChars);
+}
+
+/*
+ * This function does all command procesing for interfacing to gdb.
+ */
+void handle_exception(int exceptionVector)
+{
+ int sigval;
+ int addr, length;
+ char * ptr;
+ int newPC;
+
+ gdb_i386vector = exceptionVector;
+
+ if (remote_debug) printf("vector=%d, sr=0x%x, pc=0x%x\n",
+ exceptionVector,
+ registers[ PS ],
+ registers[ PC ]);
+
+ /* reply to host that an exception has occurred */
+ sigval = computeSignal( exceptionVector );
+ remcomOutBuffer[0] = 'S';
+ remcomOutBuffer[1] = hexchars[sigval >> 4];
+ remcomOutBuffer[2] = hexchars[sigval % 16];
+ remcomOutBuffer[3] = 0;
+
+ putpacket(remcomOutBuffer);
+
+ while (1==1) {
+ error = 0;
+ remcomOutBuffer[0] = 0;
+ getpacket(remcomInBuffer);
+ switch (remcomInBuffer[0]) {
+ case '?' : remcomOutBuffer[0] = 'S';
+ remcomOutBuffer[1] = hexchars[sigval >> 4];
+ remcomOutBuffer[2] = hexchars[sigval % 16];
+ remcomOutBuffer[3] = 0;
+ break;
+ case 'd' : remote_debug = !(remote_debug); /* toggle debug flag */
+ break;
+ case 'g' : /* return the value of the CPU registers */
+ mem2hex((char*) registers, remcomOutBuffer, NUMREGBYTES, 0);
+ break;
+ case 'G' : /* set the value of the CPU registers - return OK */
+ hex2mem(&remcomInBuffer[1], (char*) registers, NUMREGBYTES, 0);
+ strcpy(remcomOutBuffer,"OK");
+ break;
+ case 'P' : /* set the value of a single CPU register - return OK */
+ {
+ int regno;
+
+ ptr = &remcomInBuffer[1];
+ if (hexToInt (&ptr, &regno) && *ptr++ == '=')
+ if (regno >= 0 && regno < NUMREGS)
+ {
+ hex2mem (ptr, (char *)&registers[regno], 4, 0);
+ strcpy(remcomOutBuffer,"OK");
+ break;
+ }
+
+ strcpy (remcomOutBuffer, "E01");
+ break;
+ }
+
+ /* mAA..AA,LLLL Read LLLL bytes at address AA..AA */
+ case 'm' :
+ /* TRY TO READ %x,%x. IF SUCCEED, SET PTR = 0 */
+ ptr = &remcomInBuffer[1];
+ if (hexToInt(&ptr,&addr))
+ if (*(ptr++) == ',')
+ if (hexToInt(&ptr,&length))
+ {
+ ptr = 0;
+ mem_err = 0;
+ mem2hex((char*) addr, remcomOutBuffer, length, 1);
+ if (mem_err) {
+ strcpy (remcomOutBuffer, "E03");
+ debug_error ("memory fault");
+ }
+ }
+
+ if (ptr)
+ {
+ strcpy(remcomOutBuffer,"E01");
+ debug_error("malformed read memory command: %s",remcomInBuffer);
+ }
+ break;
+
+ /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
+ case 'M' :
+ /* TRY TO READ '%x,%x:'. IF SUCCEED, SET PTR = 0 */
+ ptr = &remcomInBuffer[1];
+ if (hexToInt(&ptr,&addr))
+ if (*(ptr++) == ',')
+ if (hexToInt(&ptr,&length))
+ if (*(ptr++) == ':')
+ {
+ mem_err = 0;
+ hex2mem(ptr, (char*) addr, length, 1);
+
+ if (mem_err) {
+ strcpy (remcomOutBuffer, "E03");
+ debug_error ("memory fault");
+ } else {
+ strcpy(remcomOutBuffer,"OK");
+ }
+
+ ptr = 0;
+ }
+ if (ptr)
+ {
+ strcpy(remcomOutBuffer,"E02");
+ debug_error("malformed write memory command: %s",remcomInBuffer);
+ }
+ break;
+
+ /* cAA..AA Continue at address AA..AA(optional) */
+ /* sAA..AA Step one instruction from AA..AA(optional) */
+ case 'c' :
+ case 's' :
+ /* try to read optional parameter, pc unchanged if no parm */
+ ptr = &remcomInBuffer[1];
+ if (hexToInt(&ptr,&addr))
+ registers[ PC ] = addr;
+
+ newPC = registers[ PC];
+
+ /* clear the trace bit */
+ registers[ PS ] &= 0xfffffeff;
+
+ /* set the trace bit if we're stepping */
+ if (remcomInBuffer[0] == 's') registers[ PS ] |= 0x100;
+
+ /*
+ * If we found a match for the PC AND we are not returning
+ * as a result of a breakpoint (33),
+ * trace exception (9), nmi (31), jmp to
+ * the old exception handler as if this code never ran.
+ */
+#if 0
+ /* Don't really think we need this, except maybe for protection
+ exceptions. */
+ /*
+ * invoke the previous handler.
+ */
+ if (oldExceptionHook)
+ (*oldExceptionHook) (frame->exceptionVector);
+ newPC = registers[ PC ]; /* pc may have changed */
+#endif /* 0 */
+
+ _returnFromException(); /* this is a jump */
+
+ break;
+
+ /* kill the program */
+ case 'k' : /* do nothing */
+#if 0
+ /* Huh? This doesn't look like "nothing".
+ m68k-stub.c and sparc-stub.c don't have it. */
+ BREAKPOINT();
+#endif
+ break;
+ } /* switch */
+
+ /* reply to the request */
+ putpacket(remcomOutBuffer);
+ }
+}
+
+/* this function is used to set up exception handlers for tracing and
+ breakpoints */
+void set_debug_traps()
+{
+extern void remcomHandler();
+int exception;
+
+ stackPtr = &remcomStack[STACKSIZE/sizeof(int) - 1];
+
+ exceptionHandler (0, _catchException0);
+ exceptionHandler (1, _catchException1);
+ exceptionHandler (3, _catchException3);
+ exceptionHandler (4, _catchException4);
+ exceptionHandler (5, _catchException5);
+ exceptionHandler (6, _catchException6);
+ exceptionHandler (7, _catchException7);
+ exceptionHandler (8, _catchException8);
+ exceptionHandler (9, _catchException9);
+ exceptionHandler (10, _catchException10);
+ exceptionHandler (11, _catchException11);
+ exceptionHandler (12, _catchException12);
+ exceptionHandler (13, _catchException13);
+ exceptionHandler (14, _catchException14);
+ exceptionHandler (16, _catchException16);
+
+ if (exceptionHook != remcomHandler)
+ {
+ oldExceptionHook = exceptionHook;
+ exceptionHook = remcomHandler;
+ }
+
+ /* In case GDB is started before us, ack any packets (presumably
+ "$?#xx") sitting there. */
+ putDebugChar ('+');
+
+ initialized = 1;
+
+}
+
+/* This function will generate a breakpoint exception. It is used at the
+ beginning of a program to sync up with a debugger and can be used
+ otherwise as a quick means to stop program execution and "break" into
+ the debugger. */
+
+void breakpoint()
+{
+ if (initialized)
+#if 0
+ handle_exception(3);
+#else
+ BREAKPOINT();
+#endif
+ waitabit();
+}
+
+int waitlimit = 1000000;
+
+void
+waitabit()
+{
+ int i;
+ for (i = 0; i < waitlimit; i++) ;
+}
diff --git a/gdb/i386-tdep.c b/gdb/i386-tdep.c
new file mode 100644
index 00000000000..1daa81d6aee
--- /dev/null
+++ b/gdb/i386-tdep.c
@@ -0,0 +1,794 @@
+/* Intel 386 target-dependent stuff.
+ Copyright (C) 1988, 1989, 1991, 1994, 1995, 1996, 1998
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "gdb_string.h"
+#include "frame.h"
+#include "inferior.h"
+#include "gdbcore.h"
+#include "target.h"
+#include "floatformat.h"
+#include "symtab.h"
+#include "gdbcmd.h"
+#include "command.h"
+
+static long i386_get_frame_setup PARAMS ((CORE_ADDR));
+
+static void i386_follow_jump PARAMS ((void));
+
+static void codestream_read PARAMS ((unsigned char *, int));
+
+static void codestream_seek PARAMS ((CORE_ADDR));
+
+static unsigned char codestream_fill PARAMS ((int));
+
+CORE_ADDR skip_trampoline_code PARAMS ((CORE_ADDR, char *));
+
+static int gdb_print_insn_i386 (bfd_vma, disassemble_info *);
+
+void _initialize_i386_tdep PARAMS ((void));
+
+/* This is the variable the is set with "set disassembly-flavor",
+ and its legitimate values. */
+static char att_flavor[] = "att";
+static char intel_flavor[] = "intel";
+static char *valid_flavors[] = {
+ att_flavor,
+ intel_flavor,
+ NULL
+};
+static char *disassembly_flavor = att_flavor;
+
+/* 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)
+ CORE_ADDR 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)
+ CORE_ADDR 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 == 0x68 || op == 0x6a)
+ {
+ /*
+ * this function may start with
+ *
+ * pushl constant
+ * call _probe
+ * addl $4, %esp
+ * followed by
+ * pushl %ebp
+ * etc.
+ */
+ int pos;
+ unsigned char buf[8];
+
+ /* Skip past the pushl instruction; it has either a one-byte
+ or a four-byte operand, depending on the opcode. */
+ pos = codestream_tell ();
+ if (op == 0x68)
+ pos += 4;
+ else
+ pos += 1;
+ codestream_seek (pos);
+
+ /* Read the following 8 bytes, which should be "call _probe" (6 bytes)
+ followed by "addl $4,%esp" (2 bytes). */
+ codestream_read (buf, sizeof (buf));
+ if (buf[0] == 0xe8 && buf[6] == 0xc4 && buf[7] == 0x4)
+ pos += sizeof (buf);
+ 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 = -1;
+ unsigned char op;
+ CORE_ADDR dummy_bottom;
+ CORE_ADDR adr;
+ CORE_ADDR pc;
+ 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;
+ }
+
+ pc = get_pc_function_start (fip->pc);
+ if (pc != 0)
+ locals = i386_get_frame_setup (pc);
+
+ if (locals >= 0)
+ {
+ adr = fip->frame - 4 - locals;
+ for (i = 0; i < 8; i++)
+ {
+ op = codestream_get ();
+ if (op < 0x50 || op > 0x57)
+ break;
+#ifdef I386_REGNO_TO_SYMMETRY
+ /* Dynix uses different internal numbering. Ick. */
+ fsrp->regs[I386_REGNO_TO_SYMMETRY(op - 0x50)] = adr;
+#else
+ fsrp->regs[op - 0x50] = adr;
+#endif
+ 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;
+ static unsigned char pic_pat[6] = { 0xe8, 0, 0, 0, 0, /* call 0x0 */
+ 0x5b, /* popl %ebx */
+ };
+ CORE_ADDR pos;
+
+ 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 ();
+ }
+
+ /* The native cc on SVR4 in -K PIC mode inserts the following code to get
+ the address of the global offset table (GOT) into register %ebx.
+ call 0x0
+ popl %ebx
+ movl %ebx,x(%ebp) (optional)
+ addl y,%ebx
+ This code is with the rest of the prologue (at the end of the
+ function), so we have to skip it to get to the first real
+ instruction at the start of the function. */
+
+ pos = codestream_tell ();
+ for (i = 0; i < 6; i++)
+ {
+ op = codestream_get ();
+ if (pic_pat [i] != op)
+ break;
+ }
+ if (i == 6)
+ {
+ unsigned char buf[4];
+ long delta = 6;
+
+ op = codestream_get ();
+ if (op == 0x89) /* movl %ebx, x(%ebp) */
+ {
+ op = codestream_get ();
+ if (op == 0x5d) /* one byte offset from %ebp */
+ {
+ delta += 3;
+ codestream_read (buf, 1);
+ }
+ else if (op == 0x9d) /* four byte offset from %ebp */
+ {
+ delta += 6;
+ codestream_read (buf, 4);
+ }
+ else /* unexpected instruction */
+ delta = -1;
+ op = codestream_get ();
+ }
+ /* addl y,%ebx */
+ if (delta > 0 && op == 0x81 && codestream_get () == 0xc3)
+ {
+ pos += delta + 6;
+ }
+ }
+ codestream_seek (pos);
+
+ 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 ()
+{
+ struct frame_info *frame = get_current_frame ();
+ CORE_ADDR fp;
+ int regnum;
+ struct frame_saved_regs fsr;
+ char regbuf[MAX_REGISTER_RAW_SIZE];
+
+ fp = FRAME_FP (frame);
+ get_frame_saved_regs (frame, &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 ();
+}
+
+#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 */
+
+void
+i386_extract_return_value(type, regbuf, valbuf)
+ struct type *type;
+ char regbuf[REGISTER_BYTES];
+ char *valbuf;
+{
+/* On AIX, floating point values are returned in floating point registers. */
+#ifdef I386_AIX_TARGET
+ if (TYPE_CODE_FLT == TYPE_CODE(type))
+ {
+ double d;
+ /* 387 %st(0), gcc uses this */
+ floatformat_to_double (&floatformat_i387_ext,
+ &regbuf[REGISTER_BYTE(FP0_REGNUM)],
+ &d);
+ store_floating (valbuf, TYPE_LENGTH (type), d);
+ }
+ else
+#endif /* I386_AIX_TARGET */
+ {
+ memcpy (valbuf, regbuf, TYPE_LENGTH (type));
+ }
+}
+
+#ifdef I386V4_SIGTRAMP_SAVED_PC
+/* Get saved user PC for sigtramp from the pushed ucontext on the stack
+ for all three variants of SVR4 sigtramps. */
+
+CORE_ADDR
+i386v4_sigtramp_saved_pc (frame)
+ struct frame_info *frame;
+{
+ CORE_ADDR saved_pc_offset = 4;
+ char *name = NULL;
+
+ find_pc_partial_function (frame->pc, &name, NULL, NULL);
+ if (name)
+ {
+ if (STREQ (name, "_sigreturn"))
+ saved_pc_offset = 132 + 14 * 4;
+ else if (STREQ (name, "_sigacthandler"))
+ saved_pc_offset = 80 + 14 * 4;
+ else if (STREQ (name, "sigvechandler"))
+ saved_pc_offset = 120 + 14 * 4;
+ }
+
+ if (frame->next)
+ return read_memory_integer (frame->next->frame + saved_pc_offset, 4);
+ return read_memory_integer (read_register (SP_REGNUM) + saved_pc_offset, 4);
+}
+#endif /* I386V4_SIGTRAMP_SAVED_PC */
+
+#ifdef STATIC_TRANSFORM_NAME
+/* SunPRO encodes the static variables. This is not related to C++ mangling,
+ it is done for C too. */
+
+char *
+sunpro_static_transform_name (name)
+ char *name;
+{
+ char *p;
+ if (IS_STATIC_TRANSFORM_NAME (name))
+ {
+ /* For file-local statics there will be a period, a bunch
+ of junk (the contents of which match a string given in the
+ N_OPT), a period and the name. For function-local statics
+ there will be a bunch of junk (which seems to change the
+ second character from 'A' to 'B'), a period, the name of the
+ function, and the name. So just skip everything before the
+ last period. */
+ p = strrchr (name, '.');
+ if (p != NULL)
+ name = p + 1;
+ }
+ return name;
+}
+#endif /* STATIC_TRANSFORM_NAME */
+
+
+
+/* Stuff for WIN32 PE style DLL's but is pretty generic really. */
+
+CORE_ADDR
+skip_trampoline_code (pc, name)
+ CORE_ADDR pc;
+ char *name;
+{
+ if (pc && read_memory_unsigned_integer (pc, 2) == 0x25ff) /* jmp *(dest) */
+ {
+ unsigned long indirect = read_memory_unsigned_integer (pc+2, 4);
+ struct minimal_symbol *indsym =
+ indirect ? lookup_minimal_symbol_by_pc (indirect) : 0;
+ char *symname = indsym ? SYMBOL_NAME(indsym) : 0;
+
+ if (symname)
+ {
+ if (strncmp (symname,"__imp_", 6) == 0
+ || strncmp (symname,"_imp_", 5) == 0)
+ return name ? 1 : read_memory_unsigned_integer (indirect, 4);
+ }
+ }
+ return 0; /* not a trampoline */
+}
+
+static int
+gdb_print_insn_i386 (memaddr, info)
+ bfd_vma memaddr;
+ disassemble_info * info;
+{
+ if (disassembly_flavor == att_flavor)
+ return print_insn_i386_att (memaddr, info);
+ else if (disassembly_flavor == intel_flavor)
+ return print_insn_i386_intel (memaddr, info);
+}
+
+void
+_initialize_i386_tdep ()
+{
+ tm_print_insn = gdb_print_insn_i386;
+ tm_print_insn_info.mach = bfd_lookup_arch (bfd_arch_i386, 0)->mach;
+
+ /* Add the variable that controls the disassembly flavor */
+ add_show_from_set(
+ add_set_enum_cmd ("disassembly-flavor", no_class,
+ valid_flavors,
+ (char *) &disassembly_flavor,
+ "Set the disassembly flavor, the valid values are \"att\" and \"intel\", \
+and the default value is \"att\".",
+ &setlist),
+ &showlist);
+
+
+}
diff --git a/gdb/i386aix-nat.c b/gdb/i386aix-nat.c
new file mode 100644
index 00000000000..20e656e704c
--- /dev/null
+++ b/gdb/i386aix-nat.c
@@ -0,0 +1,362 @@
+/* Intel 386 native support.
+ Copyright (C) 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "frame.h"
+#include "inferior.h"
+#include "language.h"
+#include "gdbcore.h"
+
+#ifdef USG
+#include <sys/types.h>
+#endif
+
+#include <sys/param.h>
+#include <sys/dir.h>
+#include <signal.h>
+#include <sys/user.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+
+#include <sys/file.h>
+#include "gdb_stat.h"
+
+#include <stddef.h>
+#include <sys/ptrace.h>
+
+/* Does AIX define this in <errno.h>? */
+extern int errno;
+
+#ifdef HAVE_SYS_REG_H
+#include <sys/reg.h>
+#endif
+
+#include "floatformat.h"
+
+#include "target.h"
+
+static void fetch_core_registers PARAMS ((char *, unsigned, int, CORE_ADDR));
+
+
+/* this table must line up with REGISTER_NAMES in tm-i386v.h */
+/* symbols like 'EAX' come from <sys/reg.h> */
+static int regmap[] =
+{
+ EAX, ECX, EDX, EBX,
+ USP, 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
+ */
+
+int
+i386_register_u_addr (blockend, regnum)
+ int blockend;
+ int 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]);
+
+}
+
+/* The code below only work on the aix ps/2 (i386-ibm-aix) -
+ * mtranle@paris - Sat Apr 11 10:34:12 1992
+ */
+
+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_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_unfiltered ("u: ");
+ print_387_status_word (status);
+ }
+
+ if (ep->status != 0)
+ {
+ if (bothstatus)
+ printf_unfiltered ("e: ");
+ print_387_status_word (ep->status);
+ }
+
+ print_387_control_word (ep->control);
+ printf_unfiltered ("last exception: ");
+ printf_unfiltered ("opcode %s; ", local_hex_string(ep->opcode));
+ printf_unfiltered ("pc %s:", local_hex_string(ep->code_seg));
+ printf_unfiltered ("%s; ", local_hex_string(ep->eip));
+ printf_unfiltered ("operand %s", local_hex_string(ep->operand_seg));
+ printf_unfiltered (":%s\n", local_hex_string(ep->operand));
+
+ top = ((ep->status >> 11) & 7);
+
+ printf_unfiltered ("regno tag msb lsb value\n");
+ for (fpreg = 7; fpreg >= 0; fpreg--)
+ {
+ double val;
+
+ printf_unfiltered ("%s %d: ", fpreg == top ? "=>" : " ", fpreg);
+
+ switch ((ep->tag >> ((7 - fpreg) * 2)) & 3)
+ {
+ case 0: printf_unfiltered ("valid "); break;
+ case 1: printf_unfiltered ("zero "); break;
+ case 2: printf_unfiltered ("trap "); break;
+ case 3: printf_unfiltered ("empty "); break;
+ }
+ for (i = 9; i >= 0; i--)
+ printf_unfiltered ("%02x", ep->regs[fpreg][i]);
+
+ i387_to_double ((char *)ep->regs[fpreg], (char *)&val);
+ printf_unfiltered (" %#g\n", val);
+ }
+}
+
+static struct env387 core_env387;
+
+void
+i386_float_info ()
+{
+ struct env387 fps;
+ int fpsaved = 0;
+ /* We need to reverse the order of the registers. Apparently AIX stores
+ the highest-numbered ones first. */
+ struct env387 fps_fixed;
+ int i;
+
+ if (inferior_pid)
+ {
+ char buf[10];
+ unsigned short status;
+
+ ptrace (PT_READ_FPR, inferior_pid, buf, offsetof(struct env387, status));
+ memcpy (&status, buf, sizeof (status));
+ fpsaved = status;
+ }
+ else
+ {
+ if ((fpsaved = core_env387.status) != 0)
+ memcpy(&fps, &core_env387, sizeof(fps));
+ }
+
+ if (fpsaved == 0)
+ {
+ printf_unfiltered ("no floating point status saved\n");
+ return;
+ }
+
+ if (inferior_pid)
+ {
+ int offset;
+ for (offset = 0; offset < sizeof(fps); offset += 10)
+ {
+ char buf[10];
+ ptrace (PT_READ_FPR, inferior_pid, buf, offset);
+ memcpy ((char *)&fps.control + offset, buf,
+ MIN(10, sizeof(fps) - offset));
+ }
+ }
+ fps_fixed = fps;
+ for (i = 0; i < 8; ++i)
+ memcpy (fps_fixed.regs[i], fps.regs[7 - i], 10);
+ print_387_status (0, &fps_fixed);
+}
+
+/* Fetch one register. */
+static void
+fetch_register (regno)
+ int regno;
+{
+ char buf[MAX_REGISTER_RAW_SIZE];
+ if (regno < FP0_REGNUM)
+ *(int *)buf = ptrace (PT_READ_GPR, inferior_pid,
+ PT_REG(regmap[regno]), 0, 0);
+ else
+ ptrace (PT_READ_FPR, inferior_pid, buf,
+ (regno - FP0_REGNUM)*10 + offsetof(struct env387, regs));
+ supply_register (regno, buf);
+}
+
+void
+fetch_inferior_registers (regno)
+ int regno;
+{
+ if (regno < 0)
+ for (regno = 0; regno < NUM_REGS; regno++)
+ fetch_register (regno);
+ else
+ fetch_register (regno);
+}
+
+/* store one register */
+static void
+store_register (regno)
+ int regno;
+{
+ char buf[80];
+ extern char registers[];
+ errno = 0;
+ if (regno < FP0_REGNUM)
+ ptrace (PT_WRITE_GPR, inferior_pid, PT_REG(regmap[regno]),
+ *(int *) &registers[REGISTER_BYTE (regno)], 0);
+ else
+ ptrace (PT_WRITE_FPR, inferior_pid, &registers[REGISTER_BYTE (regno)],
+ (regno - FP0_REGNUM)*10 + offsetof(struct env387, regs));
+
+ if (errno != 0)
+ {
+ sprintf (buf, "writing register number %d", regno);
+ perror_with_name (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). */
+void
+store_inferior_registers (regno)
+ int regno;
+{
+ if (regno < 0)
+ for (regno = 0; regno < NUM_REGS; regno++)
+ store_register (regno);
+ else
+ store_register (regno);
+}
+
+#ifndef CD_AX /* defined in sys/i386/coredump.h */
+# define CD_AX 0
+# define CD_BX 1
+# define CD_CX 2
+# define CD_DX 3
+# define CD_SI 4
+# define CD_DI 5
+# define CD_BP 6
+# define CD_SP 7
+# define CD_FL 8
+# define CD_IP 9
+# define CD_CS 10
+# define CD_DS 11
+# define CD_ES 12
+# define CD_FS 13
+# define CD_GS 14
+# define CD_SS 15
+#endif
+
+/*
+ * The order here in core_regmap[] has to be the same as in
+ * regmap[] above.
+ */
+static int core_regmap[] =
+{
+ CD_AX, CD_CX, CD_DX, CD_BX,
+ CD_SP, CD_BP, CD_SI, CD_DI,
+ CD_IP, CD_FL, CD_CS, CD_SS,
+ CD_DS, CD_ES, CD_FS, CD_GS,
+};
+
+static void
+fetch_core_registers (core_reg_sect, core_reg_size, which, reg_addr)
+ char *core_reg_sect;
+ unsigned core_reg_size;
+ int which;
+ CORE_ADDR reg_addr; /* ignored */
+{
+
+ if (which == 0)
+ {
+ /* Integer registers */
+
+#define cd_regs(n) ((int *)core_reg_sect)[n]
+#define regs(n) *((int *) &registers[REGISTER_BYTE (n)])
+
+ int i;
+ for (i = 0; i < FP0_REGNUM; i++)
+ regs(i) = cd_regs(core_regmap[i]);
+ }
+ else if (which == 2)
+ {
+ /* Floating point registers */
+
+ if (core_reg_size >= sizeof (core_env387))
+ memcpy (&core_env387, core_reg_sect, core_reg_size);
+ else
+ fprintf_unfiltered (gdb_stderr, "Couldn't read float regs from core file\n");
+ }
+}
+
+
+/* Register that we are able to handle i386aix core file formats.
+ FIXME: is this really bfd_target_unknown_flavour? */
+
+static struct core_fns i386aix_core_fns =
+{
+ bfd_target_unknown_flavour,
+ fetch_core_registers,
+ NULL
+};
+
+void
+_initialize_core_i386aix ()
+{
+ add_core_fns (&i386aix_core_fns);
+}
diff --git a/gdb/i386b-nat.c b/gdb/i386b-nat.c
new file mode 100644
index 00000000000..e784773f083
--- /dev/null
+++ b/gdb/i386b-nat.c
@@ -0,0 +1,285 @@
+/* Native-dependent code for BSD Unix running on i386's, for GDB.
+ Copyright 1988, 1989, 1991, 1992, 1994, 1996 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+
+#ifdef FETCH_INFERIOR_REGISTERS
+#include <sys/types.h>
+#include <sys/ptrace.h>
+#include <machine/reg.h>
+#include <machine/frame.h>
+#include "inferior.h"
+
+void
+fetch_inferior_registers(regno)
+ int regno;
+{
+ struct reg inferior_registers;
+
+ ptrace (PT_GETREGS, inferior_pid, (PTRACE_ARG3_TYPE) &inferior_registers, 0);
+ memcpy (&registers[REGISTER_BYTE (0)], &inferior_registers, 4*NUM_REGS);
+ registers_fetched ();
+}
+
+void
+store_inferior_registers(regno)
+ int regno;
+{
+ struct reg inferior_registers;
+
+ memcpy (&inferior_registers, &registers[REGISTER_BYTE (0)], 4*NUM_REGS);
+ ptrace (PT_SETREGS, inferior_pid, (PTRACE_ARG3_TYPE) &inferior_registers, 0);
+}
+
+struct md_core {
+ struct reg intreg;
+ struct fpreg freg;
+};
+
+void
+fetch_core_registers (core_reg_sect, core_reg_size, which, ignore)
+ char *core_reg_sect;
+ unsigned core_reg_size;
+ int which;
+ CORE_ADDR ignore;
+{
+ struct md_core *core_reg = (struct md_core *)core_reg_sect;
+
+ /* integer registers */
+ memcpy(&registers[REGISTER_BYTE (0)], &core_reg->intreg,
+ sizeof(struct reg));
+ /* floating point registers */
+ /* XXX */
+}
+
+#else
+
+#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
+};
+#else /* No sEAX */
+
+/* FreeBSD has decided to collapse the s* and t* symbols. So if the s*
+ ones aren't around, use the t* ones for sregmap too. */
+
+static int sregmap[] =
+{
+ tEAX, tECX, tEDX, tEBX,
+ tESP, tEBP, tESI, tEDI,
+ tEIP, tEFLAGS, tCS, tSS
+};
+#endif /* No sEAX */
+
+/* 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. */
+
+ if (blockend < 0x1fcc)
+ return (blockend + 4 * tregmap[regnum]);
+ else
+ return (blockend + 4 * sregmap[regnum]);
+}
+
+#endif /* !FETCH_INFERIOR_REGISTERS */
+
+#ifdef FLOAT_INFO
+#include "expression.h"
+#include "language.h" /* for local_hex_string */
+#include "floatformat.h"
+
+#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 "gdb_stat.h"
+#include <sys/ptrace.h>
+
+extern void print_387_control_word (); /* i387-tdep.h */
+extern void print_387_status_word ();
+
+#define fpstate save87
+#define U_FPSTATE(u) u.u_pcb.pcb_savefpu
+
+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 void
+print_387_status (status, ep)
+ unsigned short status;
+ struct env387 *ep;
+{
+ int i;
+ int bothstatus;
+ int top;
+ int fpreg;
+
+ bothstatus = ((status != 0) && (ep->status != 0));
+ if (status != 0)
+ {
+ if (bothstatus)
+ printf_unfiltered ("u: ");
+ print_387_status_word ((unsigned int)status);
+ }
+
+ if (ep->status != 0)
+ {
+ if (bothstatus)
+ printf_unfiltered ("e: ");
+ print_387_status_word ((unsigned int)ep->status);
+ }
+
+ print_387_control_word ((unsigned int)ep->control);
+ printf_unfiltered ("last exception: ");
+ printf_unfiltered ("opcode %s; ", local_hex_string(ep->opcode));
+ printf_unfiltered ("pc %s:", local_hex_string(ep->code_seg));
+ printf_unfiltered ("%s; ", local_hex_string(ep->eip));
+ printf_unfiltered ("operand %s", local_hex_string(ep->operand_seg));
+ printf_unfiltered (":%s\n", local_hex_string(ep->operand));
+
+ top = (ep->status >> 11) & 7;
+
+ printf_unfiltered ("regno tag msb lsb value\n");
+ for (fpreg = 7; fpreg >= 0; fpreg--)
+ {
+ double val;
+
+ printf_unfiltered ("%s %d: ", fpreg == top ? "=>" : " ", fpreg);
+
+ switch ((ep->tag >> (fpreg * 2)) & 3)
+ {
+ case 0: printf_unfiltered ("valid "); break;
+ case 1: printf_unfiltered ("zero "); break;
+ case 2: printf_unfiltered ("trap "); break;
+ case 3: printf_unfiltered ("empty "); break;
+ }
+ for (i = 9; i >= 0; i--)
+ printf_unfiltered ("%02x", ep->regs[fpreg][i]);
+
+ floatformat_to_double(&floatformat_i387_ext, (char *) ep->regs[fpreg],
+ &val);
+ printf_unfiltered (" %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);
+}
+
+int
+kernel_u_size ()
+{
+ return (sizeof (struct user));
+}
+
+#endif
diff --git a/gdb/i386gnu-nat.c b/gdb/i386gnu-nat.c
new file mode 100644
index 00000000000..6ed92c167f5
--- /dev/null
+++ b/gdb/i386gnu-nat.c
@@ -0,0 +1,357 @@
+/* Low level interface to I386 running the GNU Hurd
+ Copyright (C) 1992, 1995, 1996 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "inferior.h"
+#include "floatformat.h"
+
+#include <stdio.h>
+#include <errno.h>
+
+#include <mach.h>
+#include <mach/message.h>
+#include <mach/exception.h>
+#include <mach_error.h>
+
+#include "gnu-nat.h"
+
+/* Hmmm... Should this not be here?
+ * Now for i386_float_info() target_has_execution
+ */
+#include <target.h>
+
+/* @@@ Should move print_387_status() to i387-tdep.c */
+extern void print_387_control_word (); /* i387-tdep.h */
+extern void print_387_status_word ();
+
+/* Find offsets to thread states at compile time.
+ * If your compiler does not grok this, calculate offsets
+ * offsets yourself and use them (or get a compatible compiler :-)
+ */
+
+#define REG_OFFSET(reg) (int)(&((struct i386_thread_state *)0)->reg)
+
+/* at reg_offset[i] is the offset to the i386_thread_state
+ * location where the gdb registers[i] is stored.
+ */
+
+static int reg_offset[] =
+{
+ REG_OFFSET(eax), REG_OFFSET(ecx), REG_OFFSET(edx), REG_OFFSET(ebx),
+ REG_OFFSET(uesp), REG_OFFSET(ebp), REG_OFFSET(esi), REG_OFFSET(edi),
+ REG_OFFSET(eip), REG_OFFSET(efl), REG_OFFSET(cs), REG_OFFSET(ss),
+ REG_OFFSET(ds), REG_OFFSET(es), REG_OFFSET(fs), REG_OFFSET(gs)
+};
+
+#define REG_ADDR(state,regnum) ((char *)(state)+reg_offset[regnum])
+
+/* Fetch COUNT contiguous registers from thread STATE starting from REGNUM
+ * Caller knows that the regs handled in one transaction are of same size.
+ */
+#define FETCH_REGS(state, regnum, count) \
+ memcpy (&registers[REGISTER_BYTE (regnum)], \
+ REG_ADDR (state, regnum), \
+ count * REGISTER_RAW_SIZE (regnum))
+
+/* Store COUNT contiguous registers to thread STATE starting from REGNUM */
+#define STORE_REGS(state, regnum, count) \
+ memcpy (REG_ADDR (state, regnum), \
+ &registers[REGISTER_BYTE (regnum)], \
+ count * REGISTER_RAW_SIZE (regnum))
+
+/*
+ * Fetch inferiors registers for gdb.
+ * REG specifies which (as gdb views it) register, -1 for all.
+ */
+void
+gnu_fetch_registers (int reg)
+{
+ struct proc *thread;
+ thread_state_t state;
+
+ inf_update_procs (current_inferior); /* Make sure we know about new threads. */
+
+ thread = inf_tid_to_thread (current_inferior, inferior_pid);
+ if (! thread)
+ error ("fetch inferior registers: %d: Invalid thread", inferior_pid);
+
+ state = proc_get_state (thread, 0);
+
+ if (! state)
+ warning ("Couldn't fetch register %s from %s (invalid thread).",
+ REGISTER_NAME (reg), proc_string (thread));
+ else if (reg >= 0)
+ {
+ proc_debug (thread, "fetching register: %s", REGISTER_NAME (reg));
+ supply_register (reg, REG_ADDR(state, reg));
+ thread->fetched_regs |= (1 << reg);
+ }
+ else
+ {
+ proc_debug (thread, "fetching all registers");
+ for (reg = 0; reg < NUM_REGS; reg++)
+ supply_register (reg, REG_ADDR(state, reg));
+ thread->fetched_regs = ~0;
+ }
+}
+
+/* Store our register values back into the inferior.
+ * If REG is -1, do this for all registers.
+ * Otherwise, REG specifies which register
+ *
+ * On mach3 all registers are always saved in one call.
+ */
+void
+gnu_store_registers (reg)
+ int reg;
+{
+ struct proc *thread;
+ int was_aborted, was_valid;
+ thread_state_t state;
+ thread_state_data_t old_state;
+
+ inf_update_procs (current_inferior); /* Make sure we know about new threads. */
+
+ thread = inf_tid_to_thread (current_inferior, inferior_pid);
+ if (! thread)
+ error ("store inferior registers: %d: Invalid thread", inferior_pid);
+
+ proc_debug (thread, "storing register %s.", REGISTER_NAME (reg));
+
+ was_aborted = thread->aborted;
+ was_valid = thread->state_valid;
+ if (! was_aborted && was_valid)
+ bcopy (&thread->state, &old_state, sizeof (old_state));
+
+ state = proc_get_state (thread, 1);
+
+ if (! state)
+ warning ("Couldn't store register %s from %s (invalid thread).",
+ REGISTER_NAME (reg), proc_string (thread));
+ else
+ {
+ if (! was_aborted && was_valid)
+ /* See which registers have changed after aborting the thread. */
+ {
+ int check_reg;
+ for (check_reg = 0; check_reg < NUM_REGS; check_reg++)
+ if ((thread->fetched_regs & (1 << check_reg))
+ && bcmp (REG_ADDR (&old_state, check_reg),
+ REG_ADDR (state, check_reg),
+ REGISTER_RAW_SIZE (check_reg)))
+ /* Register CHECK_REG has changed! Ack! */
+ {
+ warning ("Register %s changed after thread was aborted.",
+ REGISTER_NAME (check_reg));
+ if (reg >= 0 && reg != check_reg)
+ /* Update gdb's copy of the register. */
+ supply_register (check_reg, REG_ADDR (state, check_reg));
+ else
+ warning ("... also writing this register! Suspicious...");
+ }
+ }
+
+ if (reg >= 0)
+ {
+ proc_debug (thread, "storing register: %s", REGISTER_NAME (reg));
+ STORE_REGS (state, reg, 1);
+ }
+ else
+ {
+ proc_debug (thread, "storing all registers");
+ for (reg = 0; reg < NUM_REGS; reg++)
+ STORE_REGS (state, reg, 1);
+ }
+ }
+}
+
+/* jtv@hut.fi: I copied and modified this 387 code from
+ * gdb/i386-xdep.c. Modifications for Mach 3.0.
+ *
+ * i387 status dumper. See also i387-tdep.c
+ */
+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];
+};
+/* This routine is machine independent?
+ * Should move it to i387-tdep.c but you need to export struct env387
+ */
+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_unfiltered ("u: ");
+ print_387_status_word (status);
+ }
+
+ if (ep->status != 0)
+ {
+ if (bothstatus)
+ printf_unfiltered ("e: ");
+ print_387_status_word (ep->status);
+ }
+
+ print_387_control_word (ep->control);
+ printf_unfiltered ("last exception: ");
+ printf_unfiltered ("opcode %s; ", local_hex_string(ep->opcode));
+ printf_unfiltered ("pc %s:", local_hex_string(ep->code_seg));
+ printf_unfiltered ("%s; ", local_hex_string(ep->eip));
+ printf_unfiltered ("operand %s", local_hex_string(ep->operand_seg));
+ printf_unfiltered (":%s\n", local_hex_string(ep->operand));
+
+ top = (ep->status >> 11) & 7;
+
+ printf_unfiltered ("regno tag msb lsb value\n");
+ for (fpreg = 7; fpreg >= 0; fpreg--)
+ {
+ double val;
+
+ printf_unfiltered ("%s %d: ", fpreg == top ? "=>" : " ", fpreg);
+
+ switch ((ep->tag >> (fpreg * 2)) & 3)
+ {
+ case 0: printf_unfiltered ("valid "); break;
+ case 1: printf_unfiltered ("zero "); break;
+ case 2: printf_unfiltered ("trap "); break;
+ case 3: printf_unfiltered ("empty "); break;
+ }
+ for (i = 9; i >= 0; i--)
+ printf_unfiltered ("%02x", ep->regs[fpreg][i]);
+
+ floatformat_to_double (&floatformat_i387_ext, (char *)ep->regs[fpreg],
+ &val);
+ printf_unfiltered (" %g\n", val);
+ }
+ if (ep->r0)
+ printf_unfiltered ("warning: reserved0 is %s\n", local_hex_string(ep->r0));
+ if (ep->r1)
+ printf_unfiltered ("warning: reserved1 is %s\n", local_hex_string(ep->r1));
+ if (ep->r2)
+ printf_unfiltered ("warning: reserved2 is %s\n", local_hex_string(ep->r2));
+ if (ep->r3)
+ printf_unfiltered ("warning: reserved3 is %s\n", local_hex_string(ep->r3));
+}
+
+/*
+ * values that go into fp_kind (from <i386/fpreg.h>)
+ */
+#define FP_NO 0 /* no fp chip, no emulator (no fp support) */
+#define FP_SW 1 /* no fp chip, using software emulator */
+#define FP_HW 2 /* chip present bit */
+#define FP_287 2 /* 80287 chip present */
+#define FP_387 3 /* 80387 chip present */
+
+typedef struct fpstate {
+#if 1
+ unsigned char state[FP_STATE_BYTES]; /* "hardware" state */
+#else
+ struct env387 state; /* Actually this */
+#endif
+ int status; /* Duplicate status */
+} *fpstate_t;
+
+/* Mach 3 specific routines.
+ */
+static int
+get_i387_state (fstate)
+ struct fpstate *fstate;
+{
+ error_t err;
+ thread_state_data_t state;
+ unsigned int fsCnt = i386_FLOAT_STATE_COUNT;
+ struct i386_float_state *fsp;
+ struct proc *thread = inf_tid_to_thread (current_inferior, inferior_pid);
+
+ if (!thread)
+ error ("get_i387_state: Invalid thread");
+
+ proc_abort (thread, 0); /* Make sure THREAD's in a reasonable state. */
+
+ err = thread_get_state (thread->port, i386_FLOAT_STATE, state, &fsCnt);
+ if (err)
+ {
+ warning ("Can not get live floating point state: %s",
+ mach_error_string (err));
+ return 0;
+ }
+
+ fsp = (struct i386_float_state *)state;
+ /* The 387 chip (also 486 counts) or a software emulator? */
+ if (!fsp->initialized || (fsp->fpkind != FP_387 && fsp->fpkind != FP_SW))
+ return 0;
+
+ /* Clear the target then copy thread's float state there.
+ Make a copy of the status word, for some reason?
+ */
+ memset (fstate, 0, sizeof (struct fpstate));
+
+ fstate->status = fsp->exc_status;
+
+ memcpy (fstate->state, (char *)&fsp->hw_state, FP_STATE_BYTES);
+
+ return 1;
+}
+
+/*
+ * This is called by "info float" command
+ */
+void
+i386_mach3_float_info()
+{
+ char buf [sizeof (struct fpstate) + 2 * sizeof (int)];
+ int valid = 0;
+ fpstate_t fps;
+
+ if (target_has_execution)
+ valid = get_i387_state (buf);
+
+ if (!valid)
+ {
+ warning ("no floating point status saved");
+ return;
+ }
+
+ fps = (fpstate_t) buf;
+
+ print_387_status (fps->status, (struct env387 *)fps->state);
+}
diff --git a/gdb/i386ly-tdep.c b/gdb/i386ly-tdep.c
new file mode 100644
index 00000000000..101f4edd8c6
--- /dev/null
+++ b/gdb/i386ly-tdep.c
@@ -0,0 +1,43 @@
+/* Target-dependent code for Intel 386 running LynxOS.
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "inferior.h"
+#include "target.h"
+#include "gdbcore.h"
+
+/* Return the PC of the caller from the call frame. Assumes the subr prologue
+ has already been executed, and the frame pointer setup. If this is the
+ outermost frame, we check to see if we are in a system call by examining the
+ previous instruction. If so, then the return PC is actually at SP+4 because
+ system calls use a different calling sequence. */
+
+CORE_ADDR
+i386lynx_saved_pc_after_call (frame)
+ struct frame_info *frame;
+{
+ char opcode[7];
+ static const unsigned char call_inst[] = {0x9a, 0, 0, 0, 0, 8, 0}; /* lcall 0x8,0x0 */
+
+ read_memory (frame->pc - 7, opcode, 7);
+ if (memcmp (opcode, call_inst, 7) == 0)
+ return read_memory_integer (read_register (SP_REGNUM) + 4, 4);
+
+ return read_memory_integer (read_register (SP_REGNUM), 4);
+}
diff --git a/gdb/i386m3-nat.c b/gdb/i386m3-nat.c
new file mode 100644
index 00000000000..c0257b18584
--- /dev/null
+++ b/gdb/i386m3-nat.c
@@ -0,0 +1,421 @@
+/* Low level interface to I386 running mach 3.0.
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "inferior.h"
+#include "floatformat.h"
+
+#include <stdio.h>
+
+#include <mach.h>
+#include <mach/message.h>
+#include <mach/exception.h>
+#include <mach_error.h>
+
+/* Hmmm... Should this not be here?
+ * Now for i386_float_info() target_has_execution
+ */
+#include <target.h>
+
+/* This mess is duplicated in bfd/i386mach3.h
+ *
+ * This is an ugly way to hack around the incorrect
+ * definition of UPAGES in i386/machparam.h.
+ *
+ * The definition should specify the size reserved
+ * for "struct user" in core files in PAGES,
+ * but instead it gives it in 512-byte core-clicks
+ * for i386 and i860.
+ */
+#include <sys/param.h>
+#if UPAGES == 16
+#define UAREA_SIZE ctob(UPAGES)
+#elif UPAGES == 2
+#define UAREA_SIZE (NBPG*UPAGES)
+#else
+FIXME!! UPAGES is neither 2 nor 16
+#endif
+
+/* @@@ Should move print_387_status() to i387-tdep.c */
+extern void print_387_control_word (); /* i387-tdep.h */
+extern void print_387_status_word ();
+
+#define private static
+
+
+/* Find offsets to thread states at compile time.
+ * If your compiler does not grok this, calculate offsets
+ * offsets yourself and use them (or get a compatible compiler :-)
+ */
+
+#define REG_OFFSET(reg) (int)(&((struct i386_thread_state *)0)->reg)
+
+/* at reg_offset[i] is the offset to the i386_thread_state
+ * location where the gdb registers[i] is stored.
+ */
+
+static int reg_offset[] =
+{
+ REG_OFFSET(eax), REG_OFFSET(ecx), REG_OFFSET(edx), REG_OFFSET(ebx),
+ REG_OFFSET(uesp), REG_OFFSET(ebp), REG_OFFSET(esi), REG_OFFSET(edi),
+ REG_OFFSET(eip), REG_OFFSET(efl), REG_OFFSET(cs), REG_OFFSET(ss),
+ REG_OFFSET(ds), REG_OFFSET(es), REG_OFFSET(fs), REG_OFFSET(gs)
+};
+
+#define REG_ADDRESS(state,regnum) ((char *)(state)+reg_offset[regnum])
+
+/* Fetch COUNT contiguous registers from thread STATE starting from REGNUM
+ * Caller knows that the regs handled in one transaction are of same size.
+ */
+#define FETCH_REGS(state, regnum, count) \
+ memcpy (&registers[REGISTER_BYTE (regnum)], \
+ REG_ADDRESS (state, regnum), \
+ count*REGISTER_SIZE)
+
+/* Store COUNT contiguous registers to thread STATE starting from REGNUM */
+#define STORE_REGS(state, regnum, count) \
+ memcpy (REG_ADDRESS (state, regnum), \
+ &registers[REGISTER_BYTE (regnum)], \
+ count*REGISTER_SIZE)
+
+/*
+ * Fetch inferiors registers for gdb.
+ * REGNO specifies which (as gdb views it) register, -1 for all.
+ */
+
+void
+fetch_inferior_registers (regno)
+ int regno;
+{
+ kern_return_t ret;
+ thread_state_data_t state;
+ unsigned int stateCnt = i386_THREAD_STATE_COUNT;
+ int index;
+
+ if (! MACH_PORT_VALID (current_thread))
+ error ("fetch inferior registers: Invalid thread");
+
+ if (must_suspend_thread)
+ setup_thread (current_thread, 1);
+
+ ret = thread_get_state (current_thread,
+ i386_THREAD_STATE,
+ state,
+ &stateCnt);
+
+ if (ret != KERN_SUCCESS)
+ warning ("fetch_inferior_registers: %s ",
+ mach_error_string (ret));
+#if 0
+ /* It may be more effective to store validate all of them,
+ * since we fetched them all anyway
+ */
+ else if (regno != -1)
+ supply_register (regno, (char *)state+reg_offset[regno]);
+#endif
+ else
+ {
+ for (index = 0; index < NUM_REGS; index++)
+ supply_register (index, (char *)state+reg_offset[index]);
+ }
+
+ if (must_suspend_thread)
+ setup_thread (current_thread, 0);
+}
+
+/* Store our register values back into the inferior.
+ * If REGNO is -1, do this for all registers.
+ * Otherwise, REGNO specifies which register
+ *
+ * On mach3 all registers are always saved in one call.
+ */
+void
+store_inferior_registers (regno)
+ int regno;
+{
+ kern_return_t ret;
+ thread_state_data_t state;
+ unsigned int stateCnt = i386_THREAD_STATE_COUNT;
+ register int index;
+
+ if (! MACH_PORT_VALID (current_thread))
+ error ("store inferior registers: Invalid thread");
+
+ if (must_suspend_thread)
+ setup_thread (current_thread, 1);
+
+ /* Fetch the state of the current thread */
+ ret = thread_get_state (current_thread,
+ i386_THREAD_STATE,
+ state,
+ &stateCnt);
+
+ if (ret != KERN_SUCCESS)
+ {
+ warning ("store_inferior_registers (get): %s",
+ mach_error_string (ret));
+ if (must_suspend_thread)
+ setup_thread (current_thread, 0);
+ return;
+ }
+
+ /* move gdb's registers to thread's state
+ *
+ * Since we save all registers anyway, save the ones
+ * that gdb thinks are valid (e.g. ignore the regno
+ * parameter)
+ */
+#if 0
+ if (regno != -1)
+ STORE_REGS (state, regno, 1);
+ else
+#endif
+ {
+ for (index = 0; index < NUM_REGS; index++)
+ STORE_REGS (state, index, 1);
+ }
+
+ /* Write gdb's current view of register to the thread
+ */
+ ret = thread_set_state (current_thread,
+ i386_THREAD_STATE,
+ state,
+ i386_THREAD_STATE_COUNT);
+
+ if (ret != KERN_SUCCESS)
+ warning ("store_inferior_registers (set): %s",
+ mach_error_string (ret));
+
+ if (must_suspend_thread)
+ setup_thread (current_thread, 0);
+}
+
+
+
+/* Return the address in the core dump or inferior of register REGNO.
+ * BLOCKEND should be the address of the end of the UPAGES area read
+ * in memory, but it's not?
+ *
+ * Currently our UX server dumps the whole thread state to the
+ * core file. If your UX does something else, adapt the routine
+ * below to return the offset to the given register.
+ *
+ * Called by core-aout.c(fetch_core_registers)
+ */
+
+CORE_ADDR
+register_addr (regno, blockend)
+ int regno;
+ CORE_ADDR blockend;
+{
+ CORE_ADDR addr;
+
+ if (regno < 0 || regno >= NUM_REGS)
+ error ("Invalid register number %d.", regno);
+
+ /* UAREA_SIZE == 8 kB in i386 */
+ addr = (unsigned int)REG_ADDRESS (UAREA_SIZE - sizeof(struct i386_thread_state), regno);
+
+ return addr;
+}
+
+/* jtv@hut.fi: I copied and modified this 387 code from
+ * gdb/i386-xdep.c. Modifications for Mach 3.0.
+ *
+ * i387 status dumper. See also i387-tdep.c
+ */
+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];
+};
+/* This routine is machine independent?
+ * Should move it to i387-tdep.c but you need to export struct env387
+ */
+private
+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_unfiltered ("u: ");
+ print_387_status_word (status);
+ }
+
+ if (ep->status != 0)
+ {
+ if (bothstatus)
+ printf_unfiltered ("e: ");
+ print_387_status_word (ep->status);
+ }
+
+ print_387_control_word (ep->control);
+ printf_unfiltered ("last exception: ");
+ printf_unfiltered ("opcode %s; ", local_hex_string(ep->opcode));
+ printf_unfiltered ("pc %s:", local_hex_string(ep->code_seg));
+ printf_unfiltered ("%s; ", local_hex_string(ep->eip));
+ printf_unfiltered ("operand %s", local_hex_string(ep->operand_seg));
+ printf_unfiltered (":%s\n", local_hex_string(ep->operand));
+
+ top = (ep->status >> 11) & 7;
+
+ printf_unfiltered ("regno tag msb lsb value\n");
+ for (fpreg = 7; fpreg >= 0; fpreg--)
+ {
+ double val;
+
+ printf_unfiltered ("%s %d: ", fpreg == top ? "=>" : " ", fpreg);
+
+ switch ((ep->tag >> (fpreg * 2)) & 3)
+ {
+ case 0: printf_unfiltered ("valid "); break;
+ case 1: printf_unfiltered ("zero "); break;
+ case 2: printf_unfiltered ("trap "); break;
+ case 3: printf_unfiltered ("empty "); break;
+ }
+ for (i = 9; i >= 0; i--)
+ printf_unfiltered ("%02x", ep->regs[fpreg][i]);
+
+ floatformat_to_double (&floatformat_i387_ext, (char *)ep->regs[fpreg],
+ &val);
+ printf_unfiltered (" %g\n", val);
+ }
+ if (ep->r0)
+ printf_unfiltered ("warning: reserved0 is %s\n", local_hex_string(ep->r0));
+ if (ep->r1)
+ printf_unfiltered ("warning: reserved1 is %s\n", local_hex_string(ep->r1));
+ if (ep->r2)
+ printf_unfiltered ("warning: reserved2 is %s\n", local_hex_string(ep->r2));
+ if (ep->r3)
+ printf_unfiltered ("warning: reserved3 is %s\n", local_hex_string(ep->r3));
+}
+
+/*
+ * values that go into fp_kind (from <i386/fpreg.h>)
+ */
+#define FP_NO 0 /* no fp chip, no emulator (no fp support) */
+#define FP_SW 1 /* no fp chip, using software emulator */
+#define FP_HW 2 /* chip present bit */
+#define FP_287 2 /* 80287 chip present */
+#define FP_387 3 /* 80387 chip present */
+
+typedef struct fpstate {
+#if 1
+ unsigned char state[FP_STATE_BYTES]; /* "hardware" state */
+#else
+ struct env387 state; /* Actually this */
+#endif
+ int status; /* Duplicate status */
+} *fpstate_t;
+
+/* Mach 3 specific routines.
+ */
+private boolean_t
+get_i387_state (fstate)
+ struct fpstate *fstate;
+{
+ kern_return_t ret;
+ thread_state_data_t state;
+ unsigned int fsCnt = i386_FLOAT_STATE_COUNT;
+ struct i386_float_state *fsp;
+
+ ret = thread_get_state (current_thread,
+ i386_FLOAT_STATE,
+ state,
+ &fsCnt);
+
+ if (ret != KERN_SUCCESS)
+ {
+ warning ("Can not get live floating point state: %s",
+ mach_error_string (ret));
+ return FALSE;
+ }
+
+ fsp = (struct i386_float_state *)state;
+ /* The 387 chip (also 486 counts) or a software emulator? */
+ if (!fsp->initialized || (fsp->fpkind != FP_387 && fsp->fpkind != FP_SW))
+ return FALSE;
+
+ /* Clear the target then copy thread's float state there.
+ Make a copy of the status word, for some reason?
+ */
+ memset (fstate, 0, sizeof (struct fpstate));
+
+ fstate->status = fsp->exc_status;
+
+ memcpy (fstate->state, (char *)&fsp->hw_state, FP_STATE_BYTES);
+
+ return TRUE;
+}
+
+private boolean_t
+get_i387_core_state (fstate)
+ struct fpstate *fstate;
+{
+ /* Not implemented yet. Core files do not contain float state. */
+ return FALSE;
+}
+
+/*
+ * This is called by "info float" command
+ */
+void
+i386_mach3_float_info()
+{
+ char buf [sizeof (struct fpstate) + 2 * sizeof (int)];
+ boolean_t valid = FALSE;
+ fpstate_t fps;
+
+ if (target_has_execution)
+ valid = get_i387_state (buf);
+#if 0
+ else if (WE HAVE CORE FILE) /* @@@@ Core files not supported */
+ valid = get_i387_core_state (buf);
+#endif
+
+ if (!valid)
+ {
+ warning ("no floating point status saved");
+ return;
+ }
+
+ fps = (fpstate_t) buf;
+
+ print_387_status (fps->status, (struct env387 *)fps->state);
+}
diff --git a/gdb/i386mach-nat.c b/gdb/i386mach-nat.c
new file mode 100644
index 00000000000..f843d7f95a3
--- /dev/null
+++ b/gdb/i386mach-nat.c
@@ -0,0 +1,163 @@
+/* Native dependent code for Mach 386's for GDB, the GNU debugger.
+ Copyright (C) 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "frame.h"
+#include "inferior.h"
+#include "gdbcore.h"
+
+#include <sys/param.h>
+#include <sys/dir.h>
+#include <sys/user.h>
+#include <signal.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+
+#include <sys/ptrace.h>
+#include <machine/reg.h>
+
+#include <sys/file.h>
+#include "gdb_stat.h"
+#include <sys/core.h>
+
+static void fetch_core_registers PARAMS ((char *, unsigned, int, CORE_ADDR));
+
+void
+fetch_inferior_registers (regno)
+ int regno; /* Original value discarded */
+{
+ struct regs inferior_registers;
+ struct fp_state inferior_fp_registers;
+ extern char registers[];
+
+ registers_fetched ();
+
+ ptrace (PTRACE_GETREGS, inferior_pid,
+ (PTRACE_ARG3_TYPE) &inferior_registers);
+ ptrace (PTRACE_GETFPREGS, inferior_pid,
+ (PTRACE_ARG3_TYPE) &inferior_fp_registers);
+
+ memcpy (registers, &inferior_registers, sizeof inferior_registers);
+
+ memcpy (&registers[REGISTER_BYTE (FP0_REGNUM)],
+ inferior_fp_registers.f_st,
+ sizeof inferior_fp_registers.f_st);
+ memcpy (&registers[REGISTER_BYTE (FPC_REGNUM)],
+ &inferior_fp_registers.f_ctrl,
+ sizeof inferior_fp_registers - sizeof inferior_fp_registers.f_st);
+}
+
+/* Store our register values back into the inferior.
+ If REGNO is -1, do this for all registers.
+ Otherwise, REGNO specifies which register (so we can save time). */
+
+void
+store_inferior_registers (regno)
+ int regno;
+{
+ struct regs inferior_registers;
+ struct fp_state inferior_fp_registers;
+ extern char registers[];
+
+ memcpy (&inferior_registers, registers, 20 * 4);
+
+ memcpy (inferior_fp_registers.f_st,&registers[REGISTER_BYTE (FP0_REGNUM)],
+ sizeof inferior_fp_registers.f_st);
+ memcpy (&inferior_fp_registers.f_ctrl,
+ &registers[REGISTER_BYTE (FPC_REGNUM)],
+ sizeof inferior_fp_registers - sizeof inferior_fp_registers.f_st);
+
+#ifdef PTRACE_FP_BUG
+ if (regno == FP_REGNUM || regno == -1)
+ /* Storing the frame pointer requires a gross hack, in which an
+ instruction that moves eax into ebp gets single-stepped. */
+ {
+ int stack = inferior_registers.r_reg[SP_REGNUM];
+ int stuff = ptrace (PTRACE_PEEKDATA, inferior_pid,
+ (PTRACE_ARG3_TYPE) stack);
+ int reg = inferior_registers.r_reg[EAX];
+ inferior_registers.r_reg[EAX] =
+ inferior_registers.r_reg[FP_REGNUM];
+ ptrace (PTRACE_SETREGS, inferior_pid,
+ (PTRACE_ARG3_TYPE) &inferior_registers);
+ ptrace (PTRACE_POKEDATA, inferior_pid, (PTRACE_ARG3_TYPE) stack, 0xc589);
+ ptrace (PTRACE_SINGLESTEP, inferior_pid, (PTRACE_ARG3_TYPE) stack, 0);
+ wait (0);
+ ptrace (PTRACE_POKEDATA, inferior_pid, (PTRACE_ARG3_TYPE) stack, stuff);
+ inferior_registers.r_reg[EAX] = reg;
+ }
+#endif
+ ptrace (PTRACE_SETREGS, inferior_pid,
+ (PTRACE_ARG3_TYPE) &inferior_registers);
+ ptrace (PTRACE_SETFPREGS, inferior_pid,
+ (PTRACE_ARG3_TYPE) &inferior_fp_registers);
+}
+
+
+
+/* Work with core files, for GDB. */
+
+static void
+fetch_core_registers (core_reg_sect, core_reg_size, which, reg_addr)
+ char *core_reg_sect;
+ unsigned core_reg_size;
+ int which;
+ CORE_ADDR reg_addr; /* Unused in this version */
+{
+ int val;
+ extern char registers[];
+
+ switch (which) {
+ case 0:
+ case 1:
+ memcpy (registers, core_reg_sect, core_reg_size);
+ break;
+
+ case 2:
+#ifdef FP0_REGNUM
+ memcpy (&registers[REGISTER_BYTE (FP0_REGNUM)],
+ core_reg_sect,
+ core_reg_size); /* FIXME, probably bogus */
+#endif
+#ifdef FPC_REGNUM
+ memcpy (&registers[REGISTER_BYTE (FPC_REGNUM)],
+ &corestr.c_fpu.f_fpstatus.f_ctrl,
+ sizeof corestr.c_fpu.f_fpstatus -
+ sizeof corestr.c_fpu.f_fpstatus.f_st);
+#endif
+ break;
+ }
+}
+
+
+/* Register that we are able to handle i386mach core file formats.
+ FIXME: is this really bfd_target_unknown_flavour? */
+
+static struct core_fns i386mach_core_fns =
+{
+ bfd_target_unknown_flavour,
+ fetch_core_registers,
+ NULL
+};
+
+void
+_initialize_core_i386mach ()
+{
+ add_core_fns (&i386mach_core_fns);
+}
diff --git a/gdb/i386v-nat.c b/gdb/i386v-nat.c
new file mode 100644
index 00000000000..5618687a689
--- /dev/null
+++ b/gdb/i386v-nat.c
@@ -0,0 +1,392 @@
+/* Intel 386 native support for SYSV systems (pre-SVR4).
+ Copyright (C) 1988, 89, 91, 92, 94, 96, 1998 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+
+#ifdef HAVE_PTRACE_H
+# include <ptrace.h>
+#else
+# ifdef HAVE_SYS_PTRACE_H
+# include <sys/ptrace.h>
+# endif
+#endif
+
+#include "frame.h"
+#include "inferior.h"
+#include "language.h"
+#include "gdbcore.h"
+
+#ifdef USG
+#include <sys/types.h>
+#endif
+
+#include <sys/param.h>
+#include <sys/dir.h>
+#include <signal.h>
+#include <sys/user.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+
+
+/* FIXME: The following used to be just "#include <sys/debugreg.h>", but
+ * the the Linux 2.1.x kernel and glibc 2.0.x are not in sync; including
+ * <sys/debugreg.h> will result in an error. With luck, these losers
+ * will get their act together and we can trash this hack in the near future.
+ * --jsm 1998-10-21
+ */
+
+#ifdef TARGET_HAS_HARDWARE_WATCHPOINTS
+# ifdef HAVE_ASM_DEBUGREG_H
+# include <asm/debugreg.h>
+# else
+# include <sys/debugreg.h>
+# endif
+#endif
+
+#include <sys/file.h>
+#include "gdb_stat.h"
+
+#ifdef HAVE_SYS_REG_H
+#include <sys/reg.h>
+#endif
+
+#include "floatformat.h"
+
+#include "target.h"
+
+
+/* this table must line up with REGISTER_NAMES in tm-i386v.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
+ */
+
+int
+i386_register_u_addr (blockend, regnum)
+ int blockend;
+ int regnum;
+{
+ struct user u;
+ int fpstate;
+ int ubase;
+
+ ubase = blockend;
+ /* FIXME: Should have better way to test floating point range */
+ if (regnum >= FP0_REGNUM && regnum <= (FP0_REGNUM + 7))
+ {
+#ifdef KSTKSZ /* SCO, and others? */
+ ubase += 4 * (SS + 1) - KSTKSZ;
+ fpstate = ubase + ((char *)&u.u_fps.u_fpstate - (char *)&u);
+ return (fpstate + 0x1c + 10 * (regnum - FP0_REGNUM));
+#else
+ fpstate = ubase + ((char *)&u.i387.st_space - (char *)&u);
+ return (fpstate + 10 * (regnum - FP0_REGNUM));
+#endif
+ }
+ else
+ {
+ return (ubase + 4 * regmap[regnum]);
+ }
+
+}
+
+int
+kernel_u_size ()
+{
+ return (sizeof (struct user));
+}
+
+#ifdef TARGET_HAS_HARDWARE_WATCHPOINTS
+
+#if !defined (offsetof)
+#define offsetof(TYPE, MEMBER) ((unsigned long) &((TYPE *)0)->MEMBER)
+#endif
+
+/* Record the value of the debug control register. */
+static int debug_control_mirror;
+
+/* Record which address associates with which register. */
+static CORE_ADDR address_lookup[DR_LASTADDR - DR_FIRSTADDR + 1];
+
+static int
+i386_insert_aligned_watchpoint PARAMS ((int, CORE_ADDR, CORE_ADDR, int,
+ int));
+
+static int
+i386_insert_nonaligned_watchpoint PARAMS ((int, CORE_ADDR, CORE_ADDR, int,
+ int));
+
+/* Insert a watchpoint. */
+
+int
+i386_insert_watchpoint (pid, addr, len, rw)
+ int pid;
+ CORE_ADDR addr;
+ int len;
+ int rw;
+{
+ return i386_insert_aligned_watchpoint (pid, addr, addr, len, rw);
+}
+
+static int
+i386_insert_aligned_watchpoint (pid, waddr, addr, len, rw)
+ int pid;
+ CORE_ADDR waddr;
+ CORE_ADDR addr;
+ int len;
+ int rw;
+{
+ int i;
+ int read_write_bits, len_bits;
+ int free_debug_register;
+ int register_number;
+
+ /* Look for a free debug register. */
+ for (i = DR_FIRSTADDR; i <= DR_LASTADDR; i++)
+ {
+ if (address_lookup[i - DR_FIRSTADDR] == 0)
+ break;
+ }
+
+ /* No more debug registers! */
+ if (i > DR_LASTADDR)
+ return -1;
+
+ read_write_bits = (rw & 1) ? DR_RW_READ : DR_RW_WRITE;
+
+ if (len == 1)
+ len_bits = DR_LEN_1;
+ else if (len == 2)
+ {
+ if (addr % 2)
+ return i386_insert_nonaligned_watchpoint (pid, waddr, addr, len, rw);
+ len_bits = DR_LEN_2;
+ }
+
+ else if (len == 4)
+ {
+ if (addr % 4)
+ return i386_insert_nonaligned_watchpoint (pid, waddr, addr, len, rw);
+ len_bits = DR_LEN_4;
+ }
+ else
+ return i386_insert_nonaligned_watchpoint (pid, waddr, addr, len, rw);
+
+ free_debug_register = i;
+ register_number = free_debug_register - DR_FIRSTADDR;
+ debug_control_mirror |=
+ ((read_write_bits | len_bits)
+ << (DR_CONTROL_SHIFT + DR_CONTROL_SIZE * register_number));
+ debug_control_mirror |=
+ (1 << (DR_LOCAL_ENABLE_SHIFT + DR_ENABLE_SIZE * register_number));
+ debug_control_mirror |= DR_LOCAL_SLOWDOWN;
+ debug_control_mirror &= ~DR_CONTROL_RESERVED;
+
+ ptrace (6, pid, offsetof (struct user, u_debugreg[DR_CONTROL]),
+ debug_control_mirror);
+ ptrace (6, pid, offsetof (struct user, u_debugreg[free_debug_register]),
+ addr);
+
+ /* Record where we came from. */
+ address_lookup[register_number] = addr;
+ return 0;
+}
+
+static int
+i386_insert_nonaligned_watchpoint (pid, waddr, addr, len, rw)
+ int pid;
+ CORE_ADDR waddr;
+ CORE_ADDR addr;
+ int len;
+ int rw;
+{
+ int align;
+ int size;
+ int rv;
+
+ static int size_try_array[16] = {
+ 1, 1, 1, 1, /* trying size one */
+ 2, 1, 2, 1, /* trying size two */
+ 2, 1, 2, 1, /* trying size three */
+ 4, 1, 2, 1 /* trying size four */
+ };
+
+ rv = 0;
+ while (len > 0)
+ {
+ align = addr % 4;
+ /* Four is the maximum length for 386. */
+ size = (len > 4) ? 3 : len - 1;
+ size = size_try_array[size * 4 + align];
+
+ rv = i386_insert_aligned_watchpoint (pid, waddr, addr, size, rw);
+ if (rv)
+ {
+ i386_remove_watchpoint (pid, waddr, size);
+ return rv;
+ }
+ addr += size;
+ len -= size;
+ }
+ return rv;
+}
+
+/* Remove a watchpoint. */
+
+int
+i386_remove_watchpoint (pid, addr, len)
+ int pid;
+ CORE_ADDR addr;
+ int len;
+{
+ int i;
+ int register_number;
+
+ for (i = DR_FIRSTADDR; i <= DR_LASTADDR; i++)
+ {
+ register_number = i - DR_FIRSTADDR;
+ if (address_lookup[register_number] == addr)
+ {
+ debug_control_mirror &=
+ ~(1 << (DR_LOCAL_ENABLE_SHIFT + DR_ENABLE_SIZE * register_number));
+ address_lookup[register_number] = 0;
+ }
+ }
+ ptrace (6, pid, offsetof (struct user, u_debugreg[DR_CONTROL]),
+ debug_control_mirror);
+ ptrace (6, pid, offsetof (struct user, u_debugreg[DR_STATUS]), 0);
+
+ return 0;
+}
+
+/* Check if stopped by a watchpoint. */
+
+CORE_ADDR
+i386_stopped_by_watchpoint (pid)
+ int pid;
+{
+ int i;
+ int status;
+
+ status = ptrace (3, pid, offsetof (struct user, u_debugreg[DR_STATUS]), 0);
+ ptrace (6, pid, offsetof (struct user, u_debugreg[DR_STATUS]), 0);
+
+ for (i = DR_FIRSTADDR; i <= DR_LASTADDR; i++)
+ {
+ if (status & (1 << (i - DR_FIRSTADDR)))
+ return address_lookup[i - DR_FIRSTADDR];
+ }
+
+ return 0;
+}
+
+#endif /* TARGET_HAS_HARDWARE_WATCHPOINTS */
+
+#if 0
+/* using FLOAT_INFO as is would be a problem. FLOAT_INFO is called
+ via a command xxx and eventually calls ptrace without ever having
+ traversed the target vector. This would be terribly impolite
+ behaviour for a sun4 hosted remote gdb.
+
+ A fix might be to move this code into the "info registers" command.
+ rich@cygnus.com 15 Sept 92. */
+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 = 0;
+ unsigned int rounded_addr;
+ unsigned int rounded_size;
+ extern int corechan;
+ int skip;
+
+ uaddr = (char *)&u.u_fpvalid - (char *)&u;
+ if (target_has_execution)
+ {
+ unsigned int data;
+ unsigned int mask;
+
+ rounded_addr = uaddr & -sizeof (int);
+ data = ptrace (3, inferior_pid, (PTRACE_ARG3_TYPE) rounded_addr, 0);
+ mask = 0xff << ((uaddr - rounded_addr) * 8);
+
+ fpvalid = ((data & mask) != 0);
+ }
+#if 0
+ else
+ {
+ if (lseek (corechan, uaddr, 0) < 0)
+ perror ("seek on core file");
+ if (myread (corechan, &fpvalid, 1) < 0)
+ perror ("read on core file");
+
+ }
+#endif /* no core support yet */
+
+ if (fpvalid == 0)
+ {
+ printf_unfiltered ("no floating point status saved\n");
+ return;
+ }
+
+ uaddr = (char *)&U_FPSTATE(u) - (char *)&u;
+ if (target_has_execution)
+ {
+ 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, (PTRACE_ARG3_TYPE) rounded_addr, 0);
+ rounded_addr += sizeof (int);
+ }
+ }
+#if 0
+ 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;
+ }
+#endif /* 0 */
+
+ fpstatep = (struct fpstate *)(buf + skip);
+ print_387_status (fpstatep->status, (struct env387 *)fpstatep->state);
+}
+
+#endif /* never */
diff --git a/gdb/i386v4-nat.c b/gdb/i386v4-nat.c
new file mode 100644
index 00000000000..ea84c651c46
--- /dev/null
+++ b/gdb/i386v4-nat.c
@@ -0,0 +1,172 @@
+/* Native-dependent code for SVR4 Unix running on i386's, for GDB.
+ Copyright 1988, 1989, 1991, 1992, 1996, 1998 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "value.h"
+
+#ifdef HAVE_SYS_REG_H
+#include <sys/reg.h>
+#endif
+
+
+#ifdef HAVE_SYS_PROCFS_H
+
+#include <sys/procfs.h>
+
+/* The /proc interface divides the target machine's register set up into
+ two different sets, the general register set (gregset) and the floating
+ point register set (fpregset). For each set, there is an ioctl to get
+ the current register set and another ioctl to set the current values.
+
+ The actual structure passed through the ioctl interface is, of course,
+ naturally machine dependent, and is different for each set of registers.
+ For the i386 for example, the general register set is typically defined
+ by:
+
+ typedef int gregset_t[19]; (in <sys/regset.h>)
+
+ #define GS 0 (in <sys/reg.h>)
+ #define FS 1
+ ...
+ #define UESP 17
+ #define SS 18
+
+ and the floating point set by:
+
+ typedef struct fpregset
+ {
+ union
+ {
+ struct fpchip_state // fp extension state //
+ {
+ int state[27]; // 287/387 saved state //
+ int status; // status word saved at exception //
+ } fpchip_state;
+ struct fp_emul_space // for emulators //
+ {
+ char fp_emul[246];
+ char fp_epad[2];
+ } fp_emul_space;
+ int f_fpregs[62]; // union of the above //
+ } fp_reg_set;
+ long f_wregs[33]; // saved weitek state //
+ } fpregset_t;
+
+ These routines provide the packing and unpacking of gregset_t and
+ fpregset_t formatted data.
+
+ */
+
+#ifdef HAVE_GREGSET_T
+
+/* This is a duplicate of the table in i386-xdep.c. */
+
+static int regmap[] =
+{
+ EAX, ECX, EDX, EBX,
+ UESP, EBP, ESI, EDI,
+ EIP, EFL, CS, SS,
+ DS, ES, FS, GS,
+};
+
+/* Prototypes for local functions */
+
+void fill_gregset PARAMS ((gregset_t *, int));
+
+void supply_gregset PARAMS ((gregset_t *));
+
+void supply_fpregset PARAMS ((fpregset_t *));
+
+void fill_fpregset PARAMS ((fpregset_t *, int));
+
+
+/* FIXME: These routine absolutely depends upon (NUM_REGS - NUM_FREGS)
+ being less than or equal to the number of registers that can be stored
+ in a gregset_t. Note that with the current scheme there will typically
+ be more registers actually stored in a gregset_t that what we know
+ about. This is bogus and should be fixed. */
+
+/* Given a pointer to a general register set in /proc format (gregset_t *),
+ unpack the register contents and supply them as gdb's idea of the current
+ register values. */
+
+void
+supply_gregset (gregsetp)
+ gregset_t *gregsetp;
+{
+ register int regi;
+ register greg_t *regp = (greg_t *) gregsetp;
+ extern int regmap[];
+
+ for (regi = 0 ; regi < (NUM_REGS - NUM_FREGS) ; regi++)
+ {
+ supply_register (regi, (char *) (regp + regmap[regi]));
+ }
+}
+
+void
+fill_gregset (gregsetp, regno)
+ gregset_t *gregsetp;
+ int regno;
+{
+ int regi;
+ register greg_t *regp = (greg_t *) gregsetp;
+ extern char registers[];
+ extern int regmap[];
+
+ for (regi = 0 ; regi < (NUM_REGS - NUM_FREGS) ; regi++)
+ {
+ if ((regno == -1) || (regno == regi))
+ {
+ *(regp + regmap[regi]) = *(int *) &registers[REGISTER_BYTE (regi)];
+ }
+ }
+}
+
+#endif /* HAVE_GREGSET_T */
+
+#if defined (FP0_REGNUM) && defined (HAVE_FPREGSET_T)
+
+/* Given a pointer to a floating point register set in /proc format
+ (fpregset_t *), unpack the register contents and supply them as gdb's
+ idea of the current floating point register values. */
+
+void
+supply_fpregset (fpregsetp)
+ fpregset_t *fpregsetp;
+{
+ /* FIXME: see m68k-tdep.c for an example, for the m68k. */
+}
+
+/* Given a pointer to a floating point register set in /proc format
+ (fpregset_t *), update the register specified by REGNO from gdb's idea
+ of the current floating point register set. If REGNO is -1, update
+ them all. */
+
+void
+fill_fpregset (fpregsetp, regno)
+ fpregset_t *fpregsetp;
+ int regno;
+{
+ /* FIXME: see m68k-tdep.c for an example, for the m68k. */
+}
+
+#endif /* defined (FP0_REGNUM) && defined (HAVE_FPREGSET_T) */
+
+#endif /* HAVE_SYS_PROCFS_H */
diff --git a/gdb/i387-tdep.c b/gdb/i387-tdep.c
new file mode 100644
index 00000000000..869ab9a33b8
--- /dev/null
+++ b/gdb/i387-tdep.c
@@ -0,0 +1,111 @@
+/* Intel 387 floating point stuff.
+ Copyright (C) 1988, 1989, 1991, 1998 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "frame.h"
+#include "inferior.h"
+#include "language.h"
+#include "gdbcore.h"
+#include "floatformat.h"
+
+void i387_to_double PARAMS ((char *, char *));
+
+void double_to_i387 PARAMS ((char *, char *));
+
+/* FIXME: Eliminate these routines when we have the time to change all
+ the callers. */
+
+void
+i387_to_double (from, to)
+ char *from;
+ char *to;
+{
+ floatformat_to_double (&floatformat_i387_ext, from, (double *)to);
+}
+
+void
+double_to_i387 (from, to)
+ char *from;
+ char *to;
+{
+ floatformat_from_double (&floatformat_i387_ext, (double *)from, to);
+}
+
+void
+print_387_control_word (control)
+ unsigned int control;
+{
+ printf_unfiltered ("control %s: ", local_hex_string(control));
+ printf_unfiltered ("compute to ");
+ switch ((control >> 8) & 3)
+ {
+ case 0: printf_unfiltered ("24 bits; "); break;
+ case 1: printf_unfiltered ("(bad); "); break;
+ case 2: printf_unfiltered ("53 bits; "); break;
+ case 3: printf_unfiltered ("64 bits; "); break;
+ }
+ printf_unfiltered ("round ");
+ switch ((control >> 10) & 3)
+ {
+ case 0: printf_unfiltered ("NEAREST; "); break;
+ case 1: printf_unfiltered ("DOWN; "); break;
+ case 2: printf_unfiltered ("UP; "); break;
+ case 3: printf_unfiltered ("CHOP; "); break;
+ }
+ if (control & 0x3f)
+ {
+ printf_unfiltered ("mask:");
+ if (control & 0x0001) printf_unfiltered (" INVALID");
+ if (control & 0x0002) printf_unfiltered (" DENORM");
+ if (control & 0x0004) printf_unfiltered (" DIVZ");
+ if (control & 0x0008) printf_unfiltered (" OVERF");
+ if (control & 0x0010) printf_unfiltered (" UNDERF");
+ if (control & 0x0020) printf_unfiltered (" LOS");
+ printf_unfiltered (";");
+ }
+ printf_unfiltered ("\n");
+ if (control & 0xe080) warning ("reserved bits on: %s\n",
+ local_hex_string(control & 0xe080));
+}
+
+void
+print_387_status_word (status)
+ unsigned int status;
+{
+ printf_unfiltered ("status %s: ", local_hex_string (status));
+ if (status & 0xff)
+ {
+ printf_unfiltered ("exceptions:");
+ if (status & 0x0001) printf_unfiltered (" INVALID");
+ if (status & 0x0002) printf_unfiltered (" DENORM");
+ if (status & 0x0004) printf_unfiltered (" DIVZ");
+ if (status & 0x0008) printf_unfiltered (" OVERF");
+ if (status & 0x0010) printf_unfiltered (" UNDERF");
+ if (status & 0x0020) printf_unfiltered (" LOS");
+ if (status & 0x0040) printf_unfiltered (" FPSTACK");
+ printf_unfiltered ("; ");
+ }
+ printf_unfiltered ("flags: %d%d%d%d; ",
+ (status & 0x4000) != 0,
+ (status & 0x0400) != 0,
+ (status & 0x0200) != 0,
+ (status & 0x0100) != 0);
+
+ printf_unfiltered ("top %d\n", (status >> 11) & 7);
+}
diff --git a/gdb/i960-tdep.c b/gdb/i960-tdep.c
new file mode 100644
index 00000000000..e33415d7399
--- /dev/null
+++ b/gdb/i960-tdep.c
@@ -0,0 +1,838 @@
+/* Target-machine dependent code for the Intel 960
+ Copyright 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+ Contributed by Intel Corporation.
+ examine_prologue and other parts contributed by Wind River Systems.
+
+This file is part of GDB.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "symtab.h"
+#include "value.h"
+#include "frame.h"
+#include "floatformat.h"
+#include "target.h"
+#include "gdbcore.h"
+
+static CORE_ADDR next_insn PARAMS ((CORE_ADDR memaddr,
+ unsigned int *pword1,
+ unsigned int *pword2));
+
+/* Does the specified function use the "struct returning" convention
+ or the "value returning" convention? The "value returning" convention
+ almost invariably returns the entire value in registers. The
+ "struct returning" convention often returns the entire value in
+ memory, and passes a pointer (out of or into the function) saying
+ where the value (is or should go).
+
+ Since this sometimes depends on whether it was compiled with GCC,
+ this is also an argument. This is used in call_function to build a
+ stack, and in value_being_returned to print return values.
+
+ On i960, a structure is returned in registers g0-g3, if it will fit.
+ If it's more than 16 bytes long, g13 pointed to it on entry. */
+
+int
+i960_use_struct_convention (gcc_p, type)
+ int gcc_p;
+ struct type *type;
+{
+ return (TYPE_LENGTH (type) > 16);
+}
+
+/* gdb960 is always running on a non-960 host. Check its characteristics.
+ This routine must be called as part of gdb initialization. */
+
+static void
+check_host()
+{
+ int i;
+
+ static struct typestruct {
+ int hostsize; /* Size of type on host */
+ int i960size; /* Size of type on i960 */
+ char *typename; /* Name of type, for error msg */
+ } types[] = {
+ { sizeof(short), 2, "short" },
+ { sizeof(int), 4, "int" },
+ { sizeof(long), 4, "long" },
+ { sizeof(float), 4, "float" },
+ { sizeof(double), 8, "double" },
+ { sizeof(char *), 4, "pointer" },
+ };
+#define TYPELEN (sizeof(types) / sizeof(struct typestruct))
+
+ /* Make sure that host type sizes are same as i960
+ */
+ for ( i = 0; i < TYPELEN; i++ ){
+ if ( types[i].hostsize != types[i].i960size ){
+ printf_unfiltered("sizeof(%s) != %d: PROCEED AT YOUR OWN RISK!\n",
+ types[i].typename, types[i].i960size );
+ }
+
+ }
+}
+
+/* Examine an i960 function prologue, recording the addresses at which
+ registers are saved explicitly by the prologue code, and returning
+ the address of the first instruction after the prologue (but not
+ after the instruction at address LIMIT, as explained below).
+
+ LIMIT places an upper bound on addresses of the instructions to be
+ examined. If the prologue code scan reaches LIMIT, the scan is
+ aborted and LIMIT is returned. This is used, when examining the
+ prologue for the current frame, to keep examine_prologue () from
+ claiming that a given register has been saved when in fact the
+ instruction that saves it has not yet been executed. LIMIT is used
+ at other times to stop the scan when we hit code after the true
+ function prologue (e.g. for the first source line) which might
+ otherwise be mistaken for function prologue.
+
+ The format of the function prologue matched by this routine is
+ derived from examination of the source to gcc960 1.21, particularly
+ the routine i960_function_prologue (). A "regular expression" for
+ the function prologue is given below:
+
+ (lda LRn, g14
+ mov g14, g[0-7]
+ (mov 0, g14) | (lda 0, g14))?
+
+ (mov[qtl]? g[0-15], r[4-15])*
+ ((addo [1-31], sp, sp) | (lda n(sp), sp))?
+ (st[qtl]? g[0-15], n(fp))*
+
+ (cmpobne 0, g14, LFn
+ mov sp, g14
+ lda 0x30(sp), sp
+ LFn: stq g0, (g14)
+ stq g4, 0x10(g14)
+ stq g8, 0x20(g14))?
+
+ (st g14, n(fp))?
+ (mov g13,r[4-15])?
+*/
+
+/* Macros for extracting fields from i960 instructions. */
+
+#define BITMASK(pos, width) (((0x1 << (width)) - 1) << (pos))
+#define EXTRACT_FIELD(val, pos, width) ((val) >> (pos) & BITMASK (0, width))
+
+#define REG_SRC1(insn) EXTRACT_FIELD (insn, 0, 5)
+#define REG_SRC2(insn) EXTRACT_FIELD (insn, 14, 5)
+#define REG_SRCDST(insn) EXTRACT_FIELD (insn, 19, 5)
+#define MEM_SRCDST(insn) EXTRACT_FIELD (insn, 19, 5)
+#define MEMA_OFFSET(insn) EXTRACT_FIELD (insn, 0, 12)
+
+/* Fetch the instruction at ADDR, returning 0 if ADDR is beyond LIM or
+ is not the address of a valid instruction, the address of the next
+ instruction beyond ADDR otherwise. *PWORD1 receives the first word
+ of the instruction, and (for two-word instructions), *PWORD2 receives
+ the second. */
+
+#define NEXT_PROLOGUE_INSN(addr, lim, pword1, pword2) \
+ (((addr) < (lim)) ? next_insn (addr, pword1, pword2) : 0)
+
+static CORE_ADDR
+examine_prologue (ip, limit, frame_addr, fsr)
+ register CORE_ADDR ip;
+ register CORE_ADDR limit;
+ CORE_ADDR frame_addr;
+ struct frame_saved_regs *fsr;
+{
+ register CORE_ADDR next_ip;
+ register int src, dst;
+ register unsigned int *pcode;
+ unsigned int insn1, insn2;
+ int size;
+ int within_leaf_prologue;
+ CORE_ADDR save_addr;
+ static unsigned int varargs_prologue_code [] =
+ {
+ 0x3507a00c, /* cmpobne 0x0, g14, LFn */
+ 0x5cf01601, /* mov sp, g14 */
+ 0x8c086030, /* lda 0x30(sp), sp */
+ 0xb2879000, /* LFn: stq g0, (g14) */
+ 0xb2a7a010, /* stq g4, 0x10(g14) */
+ 0xb2c7a020 /* stq g8, 0x20(g14) */
+ };
+
+ /* Accept a leaf procedure prologue code fragment if present.
+ Note that ip might point to either the leaf or non-leaf
+ entry point; we look for the non-leaf entry point first: */
+
+ within_leaf_prologue = 0;
+ if ((next_ip = NEXT_PROLOGUE_INSN (ip, limit, &insn1, &insn2))
+ && ((insn1 & 0xfffff000) == 0x8cf00000 /* lda LRx, g14 (MEMA) */
+ || (insn1 & 0xfffffc60) == 0x8cf03000)) /* lda LRx, g14 (MEMB) */
+ {
+ within_leaf_prologue = 1;
+ next_ip = NEXT_PROLOGUE_INSN (next_ip, limit, &insn1, &insn2);
+ }
+
+ /* Now look for the prologue code at a leaf entry point: */
+
+ if (next_ip
+ && (insn1 & 0xff87ffff) == 0x5c80161e /* mov g14, gx */
+ && REG_SRCDST (insn1) <= G0_REGNUM + 7)
+ {
+ within_leaf_prologue = 1;
+ if ((next_ip = NEXT_PROLOGUE_INSN (next_ip, limit, &insn1, &insn2))
+ && (insn1 == 0x8cf00000 /* lda 0, g14 */
+ || insn1 == 0x5cf01e00)) /* mov 0, g14 */
+ {
+ ip = next_ip;
+ next_ip = NEXT_PROLOGUE_INSN (ip, limit, &insn1, &insn2);
+ within_leaf_prologue = 0;
+ }
+ }
+
+ /* If something that looks like the beginning of a leaf prologue
+ has been seen, but the remainder of the prologue is missing, bail.
+ We don't know what we've got. */
+
+ if (within_leaf_prologue)
+ return (ip);
+
+ /* Accept zero or more instances of "mov[qtl]? gx, ry", where y >= 4.
+ This may cause us to mistake the moving of a register
+ parameter to a local register for the saving of a callee-saved
+ register, but that can't be helped, since with the
+ "-fcall-saved" flag, any register can be made callee-saved. */
+
+ while (next_ip
+ && (insn1 & 0xfc802fb0) == 0x5c000610
+ && (dst = REG_SRCDST (insn1)) >= (R0_REGNUM + 4))
+ {
+ src = REG_SRC1 (insn1);
+ size = EXTRACT_FIELD (insn1, 24, 2) + 1;
+ save_addr = frame_addr + ((dst - R0_REGNUM) * 4);
+ while (size--)
+ {
+ fsr->regs[src++] = save_addr;
+ save_addr += 4;
+ }
+ ip = next_ip;
+ next_ip = NEXT_PROLOGUE_INSN (ip, limit, &insn1, &insn2);
+ }
+
+ /* Accept an optional "addo n, sp, sp" or "lda n(sp), sp". */
+
+ if (next_ip &&
+ ((insn1 & 0xffffffe0) == 0x59084800 /* addo n, sp, sp */
+ || (insn1 & 0xfffff000) == 0x8c086000 /* lda n(sp), sp (MEMA) */
+ || (insn1 & 0xfffffc60) == 0x8c087400)) /* lda n(sp), sp (MEMB) */
+ {
+ ip = next_ip;
+ next_ip = NEXT_PROLOGUE_INSN (ip, limit, &insn1, &insn2);
+ }
+
+ /* Accept zero or more instances of "st[qtl]? gx, n(fp)".
+ This may cause us to mistake the copying of a register
+ parameter to the frame for the saving of a callee-saved
+ register, but that can't be helped, since with the
+ "-fcall-saved" flag, any register can be made callee-saved.
+ We can, however, refuse to accept a save of register g14,
+ since that is matched explicitly below. */
+
+ while (next_ip &&
+ ((insn1 & 0xf787f000) == 0x9287e000 /* stl? gx, n(fp) (MEMA) */
+ || (insn1 & 0xf787fc60) == 0x9287f400 /* stl? gx, n(fp) (MEMB) */
+ || (insn1 & 0xef87f000) == 0xa287e000 /* st[tq] gx, n(fp) (MEMA) */
+ || (insn1 & 0xef87fc60) == 0xa287f400) /* st[tq] gx, n(fp) (MEMB) */
+ && ((src = MEM_SRCDST (insn1)) != G14_REGNUM))
+ {
+ save_addr = frame_addr + ((insn1 & BITMASK (12, 1))
+ ? insn2 : MEMA_OFFSET (insn1));
+ size = (insn1 & BITMASK (29, 1)) ? ((insn1 & BITMASK (28, 1)) ? 4 : 3)
+ : ((insn1 & BITMASK (27, 1)) ? 2 : 1);
+ while (size--)
+ {
+ fsr->regs[src++] = save_addr;
+ save_addr += 4;
+ }
+ ip = next_ip;
+ next_ip = NEXT_PROLOGUE_INSN (ip, limit, &insn1, &insn2);
+ }
+
+ /* Accept the varargs prologue code if present. */
+
+ size = sizeof (varargs_prologue_code) / sizeof (int);
+ pcode = varargs_prologue_code;
+ while (size-- && next_ip && *pcode++ == insn1)
+ {
+ ip = next_ip;
+ next_ip = NEXT_PROLOGUE_INSN (ip, limit, &insn1, &insn2);
+ }
+
+ /* Accept an optional "st g14, n(fp)". */
+
+ if (next_ip &&
+ ((insn1 & 0xfffff000) == 0x92f7e000 /* st g14, n(fp) (MEMA) */
+ || (insn1 & 0xfffffc60) == 0x92f7f400)) /* st g14, n(fp) (MEMB) */
+ {
+ fsr->regs[G14_REGNUM] = frame_addr + ((insn1 & BITMASK (12, 1))
+ ? insn2 : MEMA_OFFSET (insn1));
+ ip = next_ip;
+ next_ip = NEXT_PROLOGUE_INSN (ip, limit, &insn1, &insn2);
+ }
+
+ /* Accept zero or one instance of "mov g13, ry", where y >= 4.
+ This is saving the address where a struct should be returned. */
+
+ if (next_ip
+ && (insn1 & 0xff802fbf) == 0x5c00061d
+ && (dst = REG_SRCDST (insn1)) >= (R0_REGNUM + 4))
+ {
+ save_addr = frame_addr + ((dst - R0_REGNUM) * 4);
+ fsr->regs[G0_REGNUM+13] = save_addr;
+ ip = next_ip;
+#if 0 /* We'll need this once there is a subsequent instruction examined. */
+ next_ip = NEXT_PROLOGUE_INSN (ip, limit, &insn1, &insn2);
+#endif
+ }
+
+ return (ip);
+}
+
+/* Given an ip value corresponding to the start of a function,
+ return the ip of the first instruction after the function
+ prologue. */
+
+CORE_ADDR
+skip_prologue (ip)
+ CORE_ADDR (ip);
+{
+ struct frame_saved_regs saved_regs_dummy;
+ struct symtab_and_line sal;
+ CORE_ADDR limit;
+
+ sal = find_pc_line (ip, 0);
+ limit = (sal.end) ? sal.end : 0xffffffff;
+
+ return (examine_prologue (ip, limit, (CORE_ADDR) 0, &saved_regs_dummy));
+}
+
+/* Put here the code to store, into a struct frame_saved_regs,
+ the addresses of the saved registers of frame described by FRAME_INFO.
+ This includes special registers such as pc and fp saved in special
+ ways in the stack frame. sp is even more special:
+ the address we return for it IS the sp for the next frame.
+
+ We cache the result of doing this in the frame_obstack, since it is
+ fairly expensive. */
+
+void
+frame_find_saved_regs (fi, fsr)
+ struct frame_info *fi;
+ struct frame_saved_regs *fsr;
+{
+ register CORE_ADDR next_addr;
+ register CORE_ADDR *saved_regs;
+ register int regnum;
+ register struct frame_saved_regs *cache_fsr;
+ CORE_ADDR ip;
+ struct symtab_and_line sal;
+ CORE_ADDR limit;
+
+ if (!fi->fsr)
+ {
+ cache_fsr = (struct frame_saved_regs *)
+ frame_obstack_alloc (sizeof (struct frame_saved_regs));
+ memset (cache_fsr, '\0', sizeof (struct frame_saved_regs));
+ fi->fsr = cache_fsr;
+
+ /* Find the start and end of the function prologue. If the PC
+ is in the function prologue, we only consider the part that
+ has executed already. */
+
+ ip = get_pc_function_start (fi->pc);
+ sal = find_pc_line (ip, 0);
+ limit = (sal.end && sal.end < fi->pc) ? sal.end: fi->pc;
+
+ examine_prologue (ip, limit, fi->frame, cache_fsr);
+
+ /* Record the addresses at which the local registers are saved.
+ Strictly speaking, we should only do this for non-leaf procedures,
+ but no one will ever look at these values if it is a leaf procedure,
+ since local registers are always caller-saved. */
+
+ next_addr = (CORE_ADDR) fi->frame;
+ saved_regs = cache_fsr->regs;
+ for (regnum = R0_REGNUM; regnum <= R15_REGNUM; regnum++)
+ {
+ *saved_regs++ = next_addr;
+ next_addr += 4;
+ }
+
+ cache_fsr->regs[FP_REGNUM] = cache_fsr->regs[PFP_REGNUM];
+ }
+
+ *fsr = *fi->fsr;
+
+ /* Fetch the value of the sp from memory every time, since it
+ is conceivable that it has changed since the cache was flushed.
+ This unfortunately undoes much of the savings from caching the
+ saved register values. I suggest adding an argument to
+ get_frame_saved_regs () specifying the register number we're
+ interested in (or -1 for all registers). This would be passed
+ through to FRAME_FIND_SAVED_REGS (), permitting more efficient
+ computation of saved register addresses (e.g., on the i960,
+ we don't have to examine the prologue to find local registers).
+ -- markf@wrs.com
+ FIXME, we don't need to refetch this, since the cache is cleared
+ every time the child process is restarted. If GDB itself
+ modifies SP, it has to clear the cache by hand (does it?). -gnu */
+
+ fsr->regs[SP_REGNUM] = read_memory_integer (fsr->regs[SP_REGNUM], 4);
+}
+
+/* Return the address of the argument block for the frame
+ described by FI. Returns 0 if the address is unknown. */
+
+CORE_ADDR
+frame_args_address (fi, must_be_correct)
+ struct frame_info *fi;
+{
+ struct frame_saved_regs fsr;
+ CORE_ADDR ap;
+
+ /* If g14 was saved in the frame by the function prologue code, return
+ the saved value. If the frame is current and we are being sloppy,
+ return the value of g14. Otherwise, return zero. */
+
+ get_frame_saved_regs (fi, &fsr);
+ if (fsr.regs[G14_REGNUM])
+ ap = read_memory_integer (fsr.regs[G14_REGNUM],4);
+ else
+ {
+ if (must_be_correct)
+ return 0; /* Don't cache this result */
+ if (get_next_frame (fi))
+ ap = 0;
+ else
+ ap = read_register (G14_REGNUM);
+ if (ap == 0)
+ ap = fi->frame;
+ }
+ fi->arg_pointer = ap; /* Cache it for next time */
+ return ap;
+}
+
+/* Return the address of the return struct for the frame
+ described by FI. Returns 0 if the address is unknown. */
+
+CORE_ADDR
+frame_struct_result_address (fi)
+ struct frame_info *fi;
+{
+ struct frame_saved_regs fsr;
+ CORE_ADDR ap;
+
+ /* If the frame is non-current, check to see if g14 was saved in the
+ frame by the function prologue code; return the saved value if so,
+ zero otherwise. If the frame is current, return the value of g14.
+
+ FIXME, shouldn't this use the saved value as long as we are past
+ the function prologue, and only use the current value if we have
+ no saved value and are at TOS? -- gnu@cygnus.com */
+
+ if (get_next_frame (fi))
+ {
+ get_frame_saved_regs (fi, &fsr);
+ if (fsr.regs[G13_REGNUM])
+ ap = read_memory_integer (fsr.regs[G13_REGNUM],4);
+ else
+ ap = 0;
+ }
+ else
+ ap = read_register (G13_REGNUM);
+
+ return ap;
+}
+
+/* Return address to which the currently executing leafproc will return,
+ or 0 if ip is not in a leafproc (or if we can't tell if it is).
+
+ Do this by finding the starting address of the routine in which ip lies.
+ If the instruction there is "mov g14, gx" (where x is in [0,7]), this
+ is a leafproc and the return address is in register gx. Well, this is
+ true unless the return address points at a RET instruction in the current
+ procedure, which indicates that we have a 'dual entry' routine that
+ has been entered through the CALL entry point. */
+
+CORE_ADDR
+leafproc_return (ip)
+ CORE_ADDR ip; /* ip from currently executing function */
+{
+ register struct minimal_symbol *msymbol;
+ char *p;
+ int dst;
+ unsigned int insn1, insn2;
+ CORE_ADDR return_addr;
+
+ if ((msymbol = lookup_minimal_symbol_by_pc (ip)) != NULL)
+ {
+ if ((p = strchr(SYMBOL_NAME (msymbol), '.')) && STREQ (p, ".lf"))
+ {
+ if (next_insn (SYMBOL_VALUE_ADDRESS (msymbol), &insn1, &insn2)
+ && (insn1 & 0xff87ffff) == 0x5c80161e /* mov g14, gx */
+ && (dst = REG_SRCDST (insn1)) <= G0_REGNUM + 7)
+ {
+ /* Get the return address. If the "mov g14, gx"
+ instruction hasn't been executed yet, read
+ the return address from g14; otherwise, read it
+ from the register into which g14 was moved. */
+
+ return_addr =
+ read_register ((ip == SYMBOL_VALUE_ADDRESS (msymbol))
+ ? G14_REGNUM : dst);
+
+ /* We know we are in a leaf procedure, but we don't know
+ whether the caller actually did a "bal" to the ".lf"
+ entry point, or a normal "call" to the non-leaf entry
+ point one instruction before. In the latter case, the
+ return address will be the address of a "ret"
+ instruction within the procedure itself. We test for
+ this below. */
+
+ if (!next_insn (return_addr, &insn1, &insn2)
+ || (insn1 & 0xff000000) != 0xa000000 /* ret */
+ || lookup_minimal_symbol_by_pc (return_addr) != msymbol)
+ return (return_addr);
+ }
+ }
+ }
+
+ return (0);
+}
+
+/* Immediately after a function call, return the saved pc.
+ Can't go through the frames for this because on some machines
+ the new frame is not set up until the new function executes
+ some instructions.
+ On the i960, the frame *is* set up immediately after the call,
+ unless the function is a leaf procedure. */
+
+CORE_ADDR
+saved_pc_after_call (frame)
+ struct frame_info *frame;
+{
+ CORE_ADDR saved_pc;
+
+ saved_pc = leafproc_return (get_frame_pc (frame));
+ if (!saved_pc)
+ saved_pc = FRAME_SAVED_PC (frame);
+
+ return saved_pc;
+}
+
+/* Discard from the stack the innermost frame,
+ restoring all saved registers. */
+
+void
+pop_frame ()
+{
+ register struct frame_info *current_fi, *prev_fi;
+ register int i;
+ CORE_ADDR save_addr;
+ CORE_ADDR leaf_return_addr;
+ struct frame_saved_regs fsr;
+ char local_regs_buf[16 * 4];
+
+ current_fi = get_current_frame ();
+
+ /* First, undo what the hardware does when we return.
+ If this is a non-leaf procedure, restore local registers from
+ the save area in the calling frame. Otherwise, load the return
+ address obtained from leafproc_return () into the rip. */
+
+ leaf_return_addr = leafproc_return (current_fi->pc);
+ if (!leaf_return_addr)
+ {
+ /* Non-leaf procedure. Restore local registers, incl IP. */
+ prev_fi = get_prev_frame (current_fi);
+ read_memory (prev_fi->frame, local_regs_buf, sizeof (local_regs_buf));
+ write_register_bytes (REGISTER_BYTE (R0_REGNUM), local_regs_buf,
+ sizeof (local_regs_buf));
+
+ /* Restore frame pointer. */
+ write_register (FP_REGNUM, prev_fi->frame);
+ }
+ else
+ {
+ /* Leaf procedure. Just restore the return address into the IP. */
+ write_register (RIP_REGNUM, leaf_return_addr);
+ }
+
+ /* Now restore any global regs that the current function had saved. */
+ get_frame_saved_regs (current_fi, &fsr);
+ for (i = G0_REGNUM; i < G14_REGNUM; i++)
+ {
+ if (save_addr = fsr.regs[i])
+ write_register (i, read_memory_integer (save_addr, 4));
+ }
+
+ /* Flush the frame cache, create a frame for the new innermost frame,
+ and make it the current frame. */
+
+ flush_cached_frames ();
+}
+
+/* Given a 960 stop code (fault or trace), return the signal which
+ corresponds. */
+
+enum target_signal
+i960_fault_to_signal (fault)
+ int fault;
+{
+ switch (fault)
+ {
+ case 0: return TARGET_SIGNAL_BUS; /* parallel fault */
+ case 1: return TARGET_SIGNAL_UNKNOWN;
+ case 2: return TARGET_SIGNAL_ILL; /* operation fault */
+ case 3: return TARGET_SIGNAL_FPE; /* arithmetic fault */
+ case 4: return TARGET_SIGNAL_FPE; /* floating point fault */
+
+ /* constraint fault. This appears not to distinguish between
+ a range constraint fault (which should be SIGFPE) and a privileged
+ fault (which should be SIGILL). */
+ case 5: return TARGET_SIGNAL_ILL;
+
+ case 6: return TARGET_SIGNAL_SEGV; /* virtual memory fault */
+
+ /* protection fault. This is for an out-of-range argument to
+ "calls". I guess it also could be SIGILL. */
+ case 7: return TARGET_SIGNAL_SEGV;
+
+ case 8: return TARGET_SIGNAL_BUS; /* machine fault */
+ case 9: return TARGET_SIGNAL_BUS; /* structural fault */
+ case 0xa: return TARGET_SIGNAL_ILL; /* type fault */
+ case 0xb: return TARGET_SIGNAL_UNKNOWN; /* reserved fault */
+ case 0xc: return TARGET_SIGNAL_BUS; /* process fault */
+ case 0xd: return TARGET_SIGNAL_SEGV; /* descriptor fault */
+ case 0xe: return TARGET_SIGNAL_BUS; /* event fault */
+ case 0xf: return TARGET_SIGNAL_UNKNOWN; /* reserved fault */
+ case 0x10: return TARGET_SIGNAL_TRAP; /* single-step trace */
+ case 0x11: return TARGET_SIGNAL_TRAP; /* branch trace */
+ case 0x12: return TARGET_SIGNAL_TRAP; /* call trace */
+ case 0x13: return TARGET_SIGNAL_TRAP; /* return trace */
+ case 0x14: return TARGET_SIGNAL_TRAP; /* pre-return trace */
+ case 0x15: return TARGET_SIGNAL_TRAP; /* supervisor call trace */
+ case 0x16: return TARGET_SIGNAL_TRAP; /* breakpoint trace */
+ default: return TARGET_SIGNAL_UNKNOWN;
+ }
+}
+
+/****************************************/
+/* MEM format */
+/****************************************/
+
+struct tabent {
+ char *name;
+ char numops;
+};
+
+static int /* returns instruction length: 4 or 8 */
+mem( memaddr, word1, word2, noprint )
+ unsigned long memaddr;
+ unsigned long word1, word2;
+ int noprint; /* If TRUE, return instruction length, but
+ don't output any text. */
+{
+ int i, j;
+ int len;
+ int mode;
+ int offset;
+ const char *reg1, *reg2, *reg3;
+
+ /* This lookup table is too sparse to make it worth typing in, but not
+ * so large as to make a sparse array necessary. We allocate the
+ * table at runtime, initialize all entries to empty, and copy the
+ * real ones in from an initialization table.
+ *
+ * NOTE: In this table, the meaning of 'numops' is:
+ * 1: single operand
+ * 2: 2 operands, load instruction
+ * -2: 2 operands, store instruction
+ */
+ static struct tabent *mem_tab = NULL;
+/* Opcodes of 0x8X, 9X, aX, bX, and cX must be in the table. */
+#define MEM_MIN 0x80
+#define MEM_MAX 0xcf
+#define MEM_SIZ ((MEM_MAX-MEM_MIN+1) * sizeof(struct tabent))
+
+ static struct { int opcode; char *name; char numops; } mem_init[] = {
+ 0x80, "ldob", 2,
+ 0x82, "stob", -2,
+ 0x84, "bx", 1,
+ 0x85, "balx", 2,
+ 0x86, "callx", 1,
+ 0x88, "ldos", 2,
+ 0x8a, "stos", -2,
+ 0x8c, "lda", 2,
+ 0x90, "ld", 2,
+ 0x92, "st", -2,
+ 0x98, "ldl", 2,
+ 0x9a, "stl", -2,
+ 0xa0, "ldt", 2,
+ 0xa2, "stt", -2,
+ 0xb0, "ldq", 2,
+ 0xb2, "stq", -2,
+ 0xc0, "ldib", 2,
+ 0xc2, "stib", -2,
+ 0xc8, "ldis", 2,
+ 0xca, "stis", -2,
+ 0, NULL, 0
+ };
+
+ if ( mem_tab == NULL ){
+ mem_tab = (struct tabent *) xmalloc( MEM_SIZ );
+ memset( mem_tab, '\0', MEM_SIZ );
+ for ( i = 0; mem_init[i].opcode != 0; i++ ){
+ j = mem_init[i].opcode - MEM_MIN;
+ mem_tab[j].name = mem_init[i].name;
+ mem_tab[j].numops = mem_init[i].numops;
+ }
+ }
+
+ i = ((word1 >> 24) & 0xff) - MEM_MIN;
+ mode = (word1 >> 10) & 0xf;
+
+ if ( (mem_tab[i].name != NULL) /* Valid instruction */
+ && ((mode == 5) || (mode >=12)) ){ /* With 32-bit displacement */
+ len = 8;
+ } else {
+ len = 4;
+ }
+
+ if ( noprint ){
+ return len;
+ }
+ abort ();
+}
+
+/* Read the i960 instruction at 'memaddr' and return the address of
+ the next instruction after that, or 0 if 'memaddr' is not the
+ address of a valid instruction. The first word of the instruction
+ is stored at 'pword1', and the second word, if any, is stored at
+ 'pword2'. */
+
+static CORE_ADDR
+next_insn (memaddr, pword1, pword2)
+ unsigned int *pword1, *pword2;
+ CORE_ADDR memaddr;
+{
+ int len;
+ char buf[8];
+
+ /* Read the two (potential) words of the instruction at once,
+ to eliminate the overhead of two calls to read_memory ().
+ FIXME: Loses if the first one is readable but the second is not
+ (e.g. last word of the segment). */
+
+ read_memory (memaddr, buf, 8);
+ *pword1 = extract_unsigned_integer (buf, 4);
+ *pword2 = extract_unsigned_integer (buf + 4, 4);
+
+ /* Divide instruction set into classes based on high 4 bits of opcode*/
+
+ switch ((*pword1 >> 28) & 0xf)
+ {
+ case 0x0:
+ case 0x1: /* ctrl */
+
+ case 0x2:
+ case 0x3: /* cobr */
+
+ case 0x5:
+ case 0x6:
+ case 0x7: /* reg */
+ len = 4;
+ break;
+
+ case 0x8:
+ case 0x9:
+ case 0xa:
+ case 0xb:
+ case 0xc:
+ len = mem (memaddr, *pword1, *pword2, 1);
+ break;
+
+ default: /* invalid instruction */
+ len = 0;
+ break;
+ }
+
+ if (len)
+ return memaddr + len;
+ else
+ return 0;
+}
+
+/* 'start_frame' is a variable in the MON960 runtime startup routine
+ that contains the frame pointer of the 'start' routine (the routine
+ that calls 'main'). By reading its contents out of remote memory,
+ we can tell where the frame chain ends: backtraces should halt before
+ they display this frame. */
+
+int
+mon960_frame_chain_valid (chain, curframe)
+ CORE_ADDR chain;
+ struct frame_info *curframe;
+{
+ struct symbol *sym;
+ struct minimal_symbol *msymbol;
+
+ /* crtmon960.o is an assembler module that is assumed to be linked
+ * first in an i80960 executable. It contains the true entry point;
+ * it performs startup up initialization and then calls 'main'.
+ *
+ * 'sf' is the name of a variable in crtmon960.o that is set
+ * during startup to the address of the first frame.
+ *
+ * 'a' is the address of that variable in 80960 memory.
+ */
+ static char sf[] = "start_frame";
+ CORE_ADDR a;
+
+
+ chain &= ~0x3f; /* Zero low 6 bits because previous frame pointers
+ contain return status info in them. */
+ if ( chain == 0 ){
+ return 0;
+ }
+
+ sym = lookup_symbol(sf, 0, VAR_NAMESPACE, (int *)NULL,
+ (struct symtab **)NULL);
+ if ( sym != 0 ){
+ a = SYMBOL_VALUE (sym);
+ } else {
+ msymbol = lookup_minimal_symbol (sf, NULL, NULL);
+ if (msymbol == NULL)
+ return 0;
+ a = SYMBOL_VALUE_ADDRESS (msymbol);
+ }
+
+ return ( chain != read_memory_integer(a,4) );
+}
+
+void
+_initialize_i960_tdep ()
+{
+ check_host ();
+
+ tm_print_insn = print_insn_i960;
+}
diff --git a/gdb/infcmd.c b/gdb/infcmd.c
new file mode 100644
index 00000000000..4add1f043cb
--- /dev/null
+++ b/gdb/infcmd.c
@@ -0,0 +1,1553 @@
+/* Memory-access and commands for "inferior" process, for GDB.
+ Copyright 1986, 87, 88, 89, 91, 92, 95, 96, 1998
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include <signal.h>
+#include "gdb_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"
+#include "language.h"
+#include "symfile.h"
+#include "objfiles.h"
+
+/* Functions exported for general use: */
+
+void nofp_registers_info PARAMS ((char *, int));
+
+void all_registers_info PARAMS ((char *, int));
+
+void registers_info PARAMS ((char *, int));
+
+/* Local functions: */
+
+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));
+
+#if !defined (DO_REGISTERS_INFO)
+static void do_registers_info PARAMS ((int, int));
+#endif
+
+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 *));
+
+void nexti_command PARAMS ((char *, int));
+
+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));
+
+void _initialize_infcmd PARAMS ((void));
+
+#define GO_USAGE "Usage: go <location>\n"
+
+#ifdef CALL_DUMMY_BREAKPOINT_OFFSET
+static void breakpoint_auto_delete_contents PARAMS ((PTR));
+#endif
+
+#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). */
+
+enum target_signal stop_signal;
+
+/* Address at which inferior stopped. */
+
+CORE_ADDR stop_pc;
+
+/* 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. */
+
+CORE_ADDR step_frame_address;
+
+/* Our notion of the current stack pointer. */
+
+CORE_ADDR step_sp;
+
+/* 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 ();
+
+ if (inferior_pid != 0 && target_has_execution)
+ {
+ if (
+ !query ("The program being debugged has been started already.\n\
+Start it from the beginning? "))
+ error ("Program not restarted.");
+ target_kill ();
+#if defined(SOLIB_RESTART)
+ SOLIB_RESTART ();
+#endif
+ init_wait_for_inferior ();
+ }
+
+ clear_breakpoint_hit_counts ();
+
+ exec_file = (char *) get_exec_file (0);
+
+ /* Purge old solib objfiles. */
+ objfile_purge_solibs ();
+
+ do_run_cleanups (NULL);
+
+ /* 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 ();
+
+ /* We keep symbols from add-symbol-file, on the grounds that the
+ user might want to add some symbols before running the program
+ (right?). But sometimes (dynamic loading where the user manually
+ introduces the new symbols with add-symbol-file), the code which
+ the symbols describe does not persist between runs. Currently
+ the user has to manually nuke all symbols between runs if they
+ want them to go away (PR 2207). This is probably reasonable. */
+
+ 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");
+ gdb_flush (gdb_stdout);
+ }
+
+ target_create_inferior (exec_file, inferior_args,
+ environ_vector (inferior_environ));
+}
+
+
+static void
+run_no_args_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ execute_command("set args", from_tty);
+ run_command((char *)NULL, from_tty);
+}
+
+
+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, TARGET_SIGNAL_DEFAULT, 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 */
+void
+stepi_command (count_string, from_tty)
+ char *count_string;
+ int from_tty;
+{
+ step_1 (0, 1, count_string);
+}
+
+/* ARGSUSED */
+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;
+ struct frame_info *frame;
+ 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 ((make_cleanup_func) disable_longjmp_breakpoint,
+ 0);
+ }
+
+ for (; count > 0; count--)
+ {
+ clear_proceed_status ();
+
+ frame = get_current_frame ();
+ if (!frame) /* Avoid coredump here. Why tho? */
+ error ("No current frame");
+ step_frame_address = FRAME_FP (frame);
+ step_sp = read_sp ();
+
+ 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);
+ }
+ }
+ 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, TARGET_SIGNAL_DEFAULT, 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 */
+ }
+ }
+
+ if (sfn != NULL)
+ {
+ fixup_symbol_section (sfn, 0);
+ if (section_is_overlay (SYMBOL_BFD_SECTION (sfn)) &&
+ !section_is_mapped (SYMBOL_BFD_SECTION (sfn)))
+ {
+ if (!query ("WARNING!!! Destination is in unmapped overlay! Jump anyway? "))
+ {
+ error ("Not confirmed.");
+ /* NOTREACHED */
+ }
+ }
+ }
+
+
+ addr = sal.pc;
+
+ if (from_tty)
+ {
+ printf_filtered ("Continuing at ");
+ print_address_numeric (addr, 1, gdb_stdout);
+ printf_filtered (".\n");
+ }
+
+ clear_proceed_status ();
+ proceed (addr, TARGET_SIGNAL_0, 0);
+}
+
+
+/* Go to line or address in current procedure */
+static void
+go_command(line_no, from_tty)
+ char *line_no;
+ int from_tty;
+{
+ if (line_no == (char *)NULL || !*line_no)
+ printf_filtered(GO_USAGE);
+ else
+ {
+ tbreak_command(line_no, from_tty);
+ jump_command(line_no, from_tty);
+ }
+}
+
+
+/* Continue program giving it specified signal. */
+
+static void
+signal_command (signum_exp, from_tty)
+ char *signum_exp;
+ int from_tty;
+{
+ enum target_signal oursig;
+
+ 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. */
+ oursig = target_signal_from_name (signum_exp);
+
+ if (oursig == TARGET_SIGNAL_UNKNOWN)
+ {
+ /* No, try numeric. */
+ int num = parse_and_eval_address (signum_exp);
+
+ if (num == 0)
+ oursig = TARGET_SIGNAL_0;
+ else
+ oursig = target_signal_from_command (num);
+ }
+
+ if (from_tty)
+ {
+ if (oursig == TARGET_SIGNAL_0)
+ printf_filtered ("Continuing with no signal.\n");
+ else
+ printf_filtered ("Continuing with signal %s.\n",
+ target_signal_to_name (oursig));
+ }
+
+ clear_proceed_status ();
+ /* "signal 0" should not get stuck if we are stopped at a breakpoint.
+ FIXME: Neither should "signal foo" but when I tried passing
+ (CORE_ADDR)-1 unconditionally I got a testsuite failure which I haven't
+ tried to track down yet. */
+ proceed (oursig == TARGET_SIGNAL_0 ? (CORE_ADDR) -1 : stop_pc, oursig, 0);
+}
+
+/* Call breakpoint_auto_delete on the current contents of the bpstat
+ pointed to by arg (which is really a bpstat *). */
+
+#ifdef CALL_DUMMY_BREAKPOINT_OFFSET
+
+static void
+breakpoint_auto_delete_contents (arg)
+ PTR arg;
+{
+ breakpoint_auto_delete (*(bpstat *)arg);
+}
+
+#endif /* CALL_DUMMY_BREAKPOINT_OFFSET */
+
+/* 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;
+
+ INIT_SAL (&sal); /* initialize to zeroes */
+#if CALL_DUMMY_LOCATION != AT_ENTRY_POINT
+ sal.pc = addr - CALL_DUMMY_START_OFFSET + CALL_DUMMY_BREAKPOINT_OFFSET;
+#else
+ sal.pc = CALL_DUMMY_ADDRESS ();
+#endif
+ sal.section = find_pc_overlay (sal.pc);
+
+ /* 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 = del;
+
+ /* 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. */
+
+ disable_watchpoints_before_interactive_call_start ();
+ proceed_to_finish = 1; /* We want stop_registers, please... */
+ proceed (addr, TARGET_SIGNAL_0, 0);
+ enable_watchpoints_after_interactive_call_stop ();
+
+ 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. This may involve changes to wait_for_inferior and the
+ proceed status code. */
+
+/* ARGSUSED */
+static void
+until_next_command (from_tty)
+ int from_tty;
+{
+ struct frame_info *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_sp = read_sp ();
+
+ step_multi = 0; /* Only one call to proceed */
+
+ proceed ((CORE_ADDR) -1, TARGET_SIGNAL_DEFAULT, 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 struct frame_info *frame;
+ 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 ();
+
+ sal = find_pc_line (frame->pc, 0);
+ sal.pc = frame->pc;
+
+ breakpoint = set_momentary_breakpoint (sal, frame, bp_finish);
+
+ old_chain = make_cleanup ((make_cleanup_func) delete_breakpoint, breakpoint);
+
+ /* Find the function we will return from. */
+
+ function = find_pc_function (selected_frame->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, TARGET_SIGNAL_DEFAULT, 0);
+
+ /* Did we stop at our breakpoint? */
+ if (bpstat_find_breakpoint(stop_bpstat, breakpoint) != NULL
+ && function != 0)
+ {
+ struct type *value_type;
+ register value_ptr val;
+ CORE_ADDR funcaddr;
+ int struct_return;
+
+ 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));
+
+ struct_return = using_struct_return (value_of_variable (function, NULL),
+
+ funcaddr,
+ check_typedef (value_type),
+ BLOCK_GCC_COMPILED (SYMBOL_BLOCK_VALUE (function)));
+
+ if (!struct_return)
+ {
+ val = value_being_returned (value_type, stop_registers, struct_return);
+ printf_filtered ("Value returned is $%d = ", record_latest_value (val));
+ value_print (val, gdb_stdout, 0, Val_no_prettyprint);
+ printf_filtered ("\n");
+ }
+ else
+ {
+ /* elz: we cannot determine the contents of the structure because
+ it is on the stack, and we don't know where, since we did not
+ initiate the call, as opposed to the call_function_by_hand case */
+#ifdef VALUE_RETURNED_FROM_STACK
+ val = 0;
+ printf_filtered ("Value returned has type: %s.",
+ TYPE_NAME (value_type));
+ printf_filtered (" Cannot determine contents\n");
+#else
+ val = value_being_returned (value_type, stop_registers,
+ struct_return);
+ printf_filtered ("Value returned is $%d = ",
+ record_latest_value (val));
+ value_print (val, gdb_stdout, 0, Val_no_prettyprint);
+ printf_filtered ("\n");
+#endif
+
+ }
+ }
+ 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 ");
+ printf_filtered ("since been deleted.\n");
+ }
+ else
+ printf_filtered ("It stopped at breakpoint %d.\n", num);
+ num = bpstat_num (&bs);
+ }
+ }
+ else if (stop_signal != TARGET_SIGNAL_0)
+ {
+ printf_filtered ("It stopped with signal %s, %s.\n",
+ target_signal_to_name (stop_signal),
+ target_signal_to_string (stop_signal));
+ }
+
+ if (!from_tty)
+ {
+ printf_filtered ("Type \"info stack\" or \"info registers\" ");
+ printf_filtered ("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 ");
+ printf_filtered ("\"%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;
+ char *env;
+ dont_repeat ();
+ env = get_in_environ (inferior_environ, path_var_name);
+ /* Can be null if path is not set */
+ if (!env)
+ env = "";
+ exec_path = strsave (env);
+ 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);
+}
+
+
+#ifdef REGISTER_NAMES
+char *gdb_register_names[] = REGISTER_NAMES;
+#endif
+/* 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;
+ int numregs = ARCH_NUM_REGS;
+
+ for (i = 0; i < numregs; 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;
+ }
+
+ /* If the register name is empty, it is undefined for this
+ processor, so don't display anything. */
+ if (REGISTER_NAME (i) == NULL || *(REGISTER_NAME (i)) == '\0')
+ continue;
+
+ fputs_filtered (REGISTER_NAME (i), gdb_stdout);
+ print_spaces_filtered (15 - strlen (REGISTER_NAME (i)), gdb_stdout);
+
+ /* Get the data in raw format. */
+ if (read_relative_register_raw_bytes (i, raw_buffer))
+ {
+ printf_filtered ("*value not available*\n");
+ continue;
+ }
+
+ /* Convert raw data to virtual format if necessary. */
+#ifdef REGISTER_CONVERTIBLE
+ if (REGISTER_CONVERTIBLE (i))
+ {
+ REGISTER_CONVERT_TO_VIRTUAL (i, REGISTER_VIRTUAL_TYPE (i),
+ raw_buffer, virtual_buffer);
+ }
+ else
+#endif
+ memcpy (virtual_buffer, raw_buffer,
+ REGISTER_VIRTUAL_SIZE (i));
+
+ /* If virtual format is floating, print it that way, and in raw hex. */
+ if (TYPE_CODE (REGISTER_VIRTUAL_TYPE (i)) == TYPE_CODE_FLT)
+ {
+ register int j;
+
+#ifdef INVALID_FLOAT
+ if (INVALID_FLOAT (virtual_buffer, REGISTER_VIRTUAL_SIZE (i)))
+ printf_filtered ("<invalid float>");
+ else
+#endif
+ val_print (REGISTER_VIRTUAL_TYPE (i), virtual_buffer, 0, 0,
+ gdb_stdout, 0, 1, 0, Val_pretty_default);
+
+ printf_filtered ("\t(raw 0x");
+ for (j = 0; j < REGISTER_RAW_SIZE (i); j++)
+ {
+ register int idx = TARGET_BYTE_ORDER == BIG_ENDIAN ? j
+ : REGISTER_RAW_SIZE (i) - 1 - j;
+ printf_filtered ("%02x", (unsigned char)raw_buffer[idx]);
+ }
+ 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) > (int) 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), virtual_buffer, 0, 0,
+ gdb_stdout, 'x', 1, 0, Val_pretty_default);
+ printf_filtered ("\t");
+ val_print (REGISTER_VIRTUAL_TYPE (i), virtual_buffer, 0, 0,
+ gdb_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. */
+
+extern int target_map_name_to_register PARAMS ((char *, int));
+
+void
+registers_info (addr_exp, fpregs)
+ char *addr_exp;
+ int fpregs;
+{
+ int regnum, numregs;
+ register char *end;
+
+ if (!target_has_registers)
+ error ("The program has no registers now.");
+ if (selected_frame == NULL)
+ error ("No selected frame.");
+
+ 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;
+ numregs = ARCH_NUM_REGS;
+
+ regnum = target_map_name_to_register (addr_exp, end - addr_exp);
+ if (regnum >= 0)
+ goto found;
+
+ regnum = numregs;
+
+ if (*addr_exp >= '0' && *addr_exp <= '9')
+ regnum = atoi (addr_exp); /* Take a number */
+ if (regnum >= numregs) /* 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');
+}
+
+void
+all_registers_info (addr_exp, from_tty)
+ char *addr_exp;
+ int from_tty;
+{
+ registers_info (addr_exp, 1);
+}
+
+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;
+{
+#ifdef SOLIB_ADD
+ extern int auto_solib_add;
+#endif
+
+ char * exec_file;
+ char * full_exec_path = NULL;
+
+ 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;
+
+ /* No traps are generated when attaching to inferior under Mach 3
+ or GNU hurd. */
+#ifndef ATTACH_NO_WAIT
+ wait_for_inferior ();
+#endif
+
+ /*
+ * If no exec file is yet known, try to determine it from the
+ * process itself.
+ */
+ exec_file = (char *) get_exec_file (0);
+ if (! exec_file) {
+ exec_file = target_pid_to_exec_file (inferior_pid);
+ if (exec_file) {
+ /* It's possible we don't have a full path, but rather just a
+ filename. Some targets, such as HP-UX, don't provide the
+ full path, sigh.
+
+ Attempt to qualify the filename against the source path.
+ (If that fails, we'll just fall back on the original
+ filename. Not much more we can do...)
+ */
+ if (!source_full_path_of (exec_file, &full_exec_path))
+ full_exec_path = savestring (exec_file, strlen (exec_file));
+
+ exec_file_attach (full_exec_path, from_tty);
+ symbol_file_command (full_exec_path, from_tty);
+ }
+ }
+
+#ifdef SOLIB_ADD
+ if (auto_solib_add)
+ {
+ /* Add shared library symbols from the newly attached process, if any. */
+ SOLIB_ADD ((char *)0, from_tty, &current_target);
+ re_enable_breakpoints_in_shlibs ();
+ }
+#endif
+
+ /* Take any necessary post-attaching actions for this platform.
+ */
+ target_post_attach (inferior_pid);
+
+ 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);
+#if defined(SOLIB_RESTART)
+ SOLIB_RESTART ();
+#endif
+}
+
+/* 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 ");
+ printf_filtered ("an unset subcommand.\n");
+ help_list (unsetlist, "unset ", -1, gdb_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 argument list 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\" with a process id, the debugger finds the\n\
+program running in the process, looking first in the current working\n\
+directory, or (if not found there) using the source file search path\n\
+(see the \"directory\" command). You can also use the \"file\" command\n\
+to specify the program, 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\n\
+you 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 specified by the argument.\n\
+An argument of \"0\" means continue program without giving it a signal.");
+
+ 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);
+ if (xdb_commands)
+ add_com_alias("S", "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 ("go", class_run, go_command,
+ "Usage: go <location>\n\
+Continue program being debugged, stopping at specified line or \n\
+address.\n\
+Give as argument either LINENUM or *ADDR, where ADDR is an \n\
+expression for an address to start at.\n\
+This command is a combination of tbreak and jump.");
+ if (xdb_commands)
+ add_com_alias("g", "g", class_run, 1);
+
+ 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);
+ if (xdb_commands)
+ add_com ("R", class_run, run_no_args_command,
+ "Start debugged program with no arguments.");
+
+ 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.");
+
+ if (xdb_commands)
+ add_com("lr", class_info, 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/gdb/inferior.h b/gdb/inferior.h
new file mode 100644
index 00000000000..fa59c2a5ff7
--- /dev/null
+++ b/gdb/inferior.h
@@ -0,0 +1,473 @@
+/* Variables that describe the inferior process running under GDB:
+ Where it is, why it stopped, and how to step it.
+ Copyright 1986, 1989, 1992, 1996, 1998 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#if !defined (INFERIOR_H)
+#define INFERIOR_H 1
+
+/* For bpstat. */
+#include "breakpoint.h"
+
+/* For enum target_signal. */
+#include "target.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
+ {
+ enum target_signal stop_signal;
+ CORE_ADDR stop_pc;
+ 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;
+ CORE_ADDR step_frame_address;
+ int step_over_calls;
+ CORE_ADDR step_resume_break_address;
+ int stop_after_trap;
+ int stop_soon_quietly;
+ CORE_ADDR selected_frame_address;
+ 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 selected_level;
+ int breakpoint_proceeded;
+ int restore_stack_info;
+ int proceed_to_finish;
+ };
+
+/* This macro gives the number of registers actually in use by the
+ inferior. This may be less than the total number of registers,
+ perhaps depending on the actual CPU in use or program being run. */
+
+#ifndef ARCH_NUM_REGS
+#define ARCH_NUM_REGS NUM_REGS
+#endif
+
+extern void save_inferior_status PARAMS ((struct inferior_status *, int));
+
+extern void restore_inferior_status PARAMS ((struct inferior_status *));
+
+extern void set_sigint_trap PARAMS ((void));
+
+extern void clear_sigint_trap PARAMS ((void));
+
+extern void set_sigio_trap PARAMS ((void));
+
+extern void clear_sigio_trap PARAMS ((void));
+
+/* 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;
+
+/* This is only valid when inferior_pid is non-zero.
+
+ If this is 0, then exec events should be noticed and responded to
+ by the debugger (i.e., be reported to the user).
+
+ If this is > 0, then that many subsequent exec events should be
+ ignored (i.e., not be reported to the user).
+ */
+extern int inferior_ignoring_startup_exec_events;
+
+/* This is only valid when inferior_ignoring_startup_exec_events is
+ zero.
+
+ Some targets (stupidly) report more than one exec event per actual
+ call to an event() system call. If only the last such exec event
+ need actually be noticed and responded to by the debugger (i.e.,
+ be reported to the user), then this is the number of "leading"
+ exec events which should be ignored.
+ */
+extern int inferior_ignoring_leading_exec_events;
+
+/* Inferior environment. */
+
+extern struct environ *inferior_environ;
+
+/* 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.
+ -1 if register value is not available. */
+
+extern SIGNED char register_valid[NUM_REGS];
+
+extern void clear_proceed_status PARAMS ((void));
+
+extern void proceed PARAMS ((CORE_ADDR, enum target_signal, 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 CORE_ADDR read_pc_pid PARAMS ((int));
+
+extern void write_pc PARAMS ((CORE_ADDR));
+
+extern void write_pc_pid PARAMS ((CORE_ADDR, int));
+
+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, enum target_signal));
+
+/* 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));
+
+extern void terminal_init_inferior_with_pgrp PARAMS ((int pgrp));
+
+/* From infptrace.c or infttrace.c */
+
+extern int attach PARAMS ((int));
+
+#if !defined(REQUIRE_ATTACH)
+#define REQUIRE_ATTACH attach
+#endif
+
+#if !defined(REQUIRE_DETACH)
+#define REQUIRE_DETACH(pid,siggnal) detach (siggnal)
+#endif
+
+extern void detach PARAMS ((int));
+
+int ptrace_wait PARAMS ((int, int *));
+
+extern void child_resume PARAMS ((int, int, enum target_signal));
+
+#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));
+
+extern void pre_fork_inferior PARAMS ((void));
+
+/* From procfs.c */
+
+extern int proc_iterate_over_mappings PARAMS ((int (*)(int, CORE_ADDR)));
+
+extern int procfs_first_available PARAMS ((void));
+
+extern int procfs_get_pid_fd PARAMS ((int));
+
+/* From fork-child.c */
+
+extern void fork_inferior PARAMS ((char *, char *, char **,
+ void (*)(void),
+ void (*)(int),
+ void (*)(void),
+ char *));
+
+
+extern void
+clone_and_follow_inferior PARAMS ((int, int *));
+
+extern void startup_inferior PARAMS ((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 enum target_signal stop_signal;
+
+/* Address at which inferior stopped. */
+
+extern CORE_ADDR stop_pc;
+
+/* 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 CORE_ADDR step_frame_address;
+
+/* Our notion of the current stack pointer. */
+
+extern CORE_ADDR step_sp;
+
+/* 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) \
+ && (pc) < SIGTRAMP_END(pc) \
+ )
+#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) \
+ (INNER_THAN ((sp), (pc)) && (frame_address != 0) && INNER_THAN ((pc), (frame_address)))
+#endif /* On stack. */
+
+#if CALL_DUMMY_LOCATION == AT_ENTRY_POINT
+#define PC_IN_CALL_DUMMY(pc, sp, frame_address) \
+ ((pc) >= CALL_DUMMY_ADDRESS () \
+ && (pc) <= (CALL_DUMMY_ADDRESS () + DECR_PC_AFTER_BREAK))
+#endif /* At entry point. */
+#endif /* No PC_IN_CALL_DUMMY. */
+
+/* It's often not enough for our clients to know whether the PC is merely
+ somewhere within the call dummy. They may need to know whether the
+ call dummy has actually completed. (For example, wait_for_inferior
+ wants to know when it should truly stop because the call dummy has
+ completed. If we're single-stepping because of slow watchpoints,
+ then we may find ourselves stopped at the entry of the call dummy,
+ and want to continue stepping until we reach the end.)
+
+ Note that this macro is intended for targets (like HP-UX) which
+ require more than a single breakpoint in their call dummies, and
+ therefore cannot use the CALL_DUMMY_BREAKPOINT_OFFSET mechanism.
+
+ If a target does define CALL_DUMMY_BREAKPOINT_OFFSET, then this
+ default implementation of CALL_DUMMY_HAS_COMPLETED is sufficient.
+ Else, a target may wish to supply an implementation that works in
+ the presense of multiple breakpoints in its call dummy.
+ */
+#if !defined(CALL_DUMMY_HAS_COMPLETED)
+#define CALL_DUMMY_HAS_COMPLETED(pc, sp, frame_address) \
+ PC_IN_CALL_DUMMY((pc), (sp), (frame_address))
+#endif
+
+/* If STARTUP_WITH_SHELL is set, GDB's "run"
+ will attempts to start up the debugee under a shell.
+ This is in order for argument-expansion to occur. E.g.,
+ (gdb) run *
+ The "*" gets expanded by the shell into a list of files.
+ While this is a nice feature, it turns out to interact badly
+ with some of the catch-fork/catch-exec features we have added.
+ In particular, if the shell does any fork/exec's before
+ the exec of the target program, that can confuse GDB.
+ To disable this feature, set STARTUP_WITH_SHELL to 0.
+ To enable this feature, set STARTUP_WITH_SHELL to 1.
+ The catch-exec traps expected during start-up will
+ be 1 if target is not started up with a shell, 2 if it is.
+ - RT
+ If you disable this, you need to decrement
+ START_INFERIOR_TRAPS_EXPECTED in tm.h. */
+#define STARTUP_WITH_SHELL 1
+#if !defined(START_INFERIOR_TRAPS_EXPECTED)
+#define START_INFERIOR_TRAPS_EXPECTED 2
+#endif
+#endif /* !defined (INFERIOR_H) */
diff --git a/gdb/inflow.c b/gdb/inflow.c
new file mode 100644
index 00000000000..90336751622
--- /dev/null
+++ b/gdb/inflow.c
@@ -0,0 +1,751 @@
+/* Low level interface to ptrace, for GDB when running under Unix.
+ Copyright 1986-87, 1989, 1991-92, 1995, 1998 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 "gdbthread.h"
+
+#include "gdb_string.h"
+#include <signal.h>
+#include <fcntl.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#ifdef HAVE_TERMIOS
+#define PROCESS_GROUP_TYPE pid_t
+#endif
+
+#ifdef HAVE_TERMIO
+#define PROCESS_GROUP_TYPE int
+#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 */
+
+#if defined (SIGIO) && defined (FASYNC) && defined (FD_SET) && defined (F_SETOWN)
+static void
+handle_sigio PARAMS ((int));
+#endif
+
+static void
+pass_signal PARAMS ((int));
+
+static void
+kill_command PARAMS ((char *, int));
+
+static void
+terminal_ours_1 PARAMS ((int));
+
+/* 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
+ (). */
+
+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_TERMIO
+ our_process_group = getpgrp ();
+#endif
+#ifdef HAVE_SGTTY
+ ioctl (0, TIOCGPGRP, &our_process_group);
+#endif
+ }
+ }
+
+ return gdb_has_a_terminal_flag == yes;
+ default:
+ /* "Can't happen". */
+ return 0;
+ }
+}
+
+/* Macro for printing errors from ioctl operations */
+
+#define OOPSY(what) \
+ if (result == -1) \
+ fprintf_unfiltered(gdb_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_with_pgrp (pgrp)
+ int pgrp;
+{
+ 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 = pgrp;
+#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;
+ }
+}
+
+void
+terminal_init_inferior ()
+{
+#ifdef PROCESS_GROUP_TYPE
+ /* This is for Lynx, and should be cleaned up by having Lynx be a separate
+ debugging target with a version of target_terminal_init_inferior which
+ passes in the process group to a generic routine which does all the work
+ (and the non-threaded child_terminal_init_inferior can just pass in
+ inferior_pid to the same routine). */
+ /* We assume INFERIOR_PID is also the child's process group. */
+ terminal_init_inferior_with_pgrp (PIDGET (inferior_pid));
+#endif /* PROCESS_GROUP_TYPE */
+}
+
+/* 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);
+#ifdef SIGQUIT
+ sigquit_ours = (void (*) ()) signal (SIGQUIT, SIG_IGN);
+#endif
+ }
+
+ /* 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_TERMIO
+ inferior_process_group = getpgrp ();
+#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.
+ FIXME-maybe: However, query() expects non-raw mode and doesn't
+ use readline. Maybe query should use readline (on the other hand,
+ this only matters for HAVE_SGTTY, not termio or termios, I think). */
+
+ /* 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_unfiltered (gdb_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);
+#ifdef SIGQUIT
+ signal (SIGQUIT, sigquit_ours);
+#endif
+ }
+
+#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__) && !defined(_WIN32)
+#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 && !win32*/
+}
+
+/* Kill the inferior process. Make us have no inferior. */
+
+/* ARGSUSED */
+static void
+kill_command (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ /* FIXME: This should not really be inferior_pid (or target_has_execution).
+ It should be a distinct flag that indicates that a target is active, cuz
+ some targets don't have processes! */
+
+ 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", target_longname);
+ if (selected_frame == NULL)
+ fputs_filtered ("No selected stack frame.\n", gdb_stdout);
+ else
+ print_stack_frame (selected_frame, selected_frame_level, 1);
+ }
+}
+
+/* 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;
+{
+#ifndef _WIN32
+ kill (PIDGET (inferior_pid), SIGINT);
+#endif
+}
+
+static void (*osig)();
+
+void
+set_sigint_trap()
+{
+ if (attach_flag || inferior_thisrun_terminal)
+ {
+ osig = (void (*) ()) signal (SIGINT, pass_signal);
+ }
+}
+
+void
+clear_sigint_trap()
+{
+ if (attach_flag || inferior_thisrun_terminal)
+ {
+ signal (SIGINT, osig);
+ }
+}
+
+#if defined (SIGIO) && defined (FASYNC) && defined (FD_SET) && defined (F_SETOWN)
+static void (*old_sigio) ();
+
+static void
+handle_sigio (signo)
+ int signo;
+{
+ int numfds;
+ fd_set readfds;
+
+ signal (SIGIO, handle_sigio);
+
+ FD_ZERO (&readfds);
+ FD_SET (target_activity_fd, &readfds);
+ numfds = select (target_activity_fd + 1, &readfds, NULL, NULL, NULL);
+ if (numfds >= 0 && FD_ISSET (target_activity_fd, &readfds))
+ {
+#ifndef _WIN32
+ if ((*target_activity_function) ())
+ kill (inferior_pid, SIGINT);
+#endif
+ }
+}
+
+static int old_fcntl_flags;
+
+void
+set_sigio_trap ()
+{
+ if (target_activity_function)
+ {
+ old_sigio = (void (*) ()) signal (SIGIO, handle_sigio);
+ fcntl (target_activity_fd, F_SETOWN, getpid());
+ old_fcntl_flags = fcntl (target_activity_fd, F_GETFL, 0);
+ fcntl (target_activity_fd, F_SETFL, old_fcntl_flags | FASYNC);
+ }
+}
+
+void
+clear_sigio_trap ()
+{
+ if (target_activity_function)
+ {
+ signal (SIGIO, old_sigio);
+ fcntl (target_activity_fd, F_SETFL, old_fcntl_flags);
+ }
+}
+#else /* No SIGIO. */
+void
+set_sigio_trap ()
+{
+ if (target_activity_function)
+ abort ();
+}
+
+void
+clear_sigio_trap ()
+{
+ if (target_activity_function)
+ abort ();
+}
+#endif /* No SIGIO. */
+
+
+/* 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) && defined (HAVE_SETPGID))
+ /* 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
+#ifdef _SC_JOB_CONTROL
+ job_control = sysconf (_SC_JOB_CONTROL);
+#else
+ job_control = 0; /* have to assume the worst */
+#endif /* _SC_JOB_CONTROL */
+#endif /* _POSIX_JOB_CONTROL */
+#endif /* HAVE_TERMIOS */
+
+#ifdef HAVE_SGTTY
+#ifdef TIOCGPGRP
+ job_control = 1;
+#else
+ job_control = 0;
+#endif /* TIOCGPGRP */
+#endif /* sgtty */
+}
diff --git a/gdb/infptrace.c b/gdb/infptrace.c
new file mode 100644
index 00000000000..1db7223ea3b
--- /dev/null
+++ b/gdb/infptrace.c
@@ -0,0 +1,638 @@
+/* Low level Unix child interface to ptrace, for GDB when running under Unix.
+ Copyright 1988, 89, 90, 91, 92, 93, 94, 95, 96, 1998
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "frame.h"
+#include "inferior.h"
+#include "target.h"
+#include "gdb_string.h"
+#include "wait.h"
+#include "command.h"
+
+#ifdef USG
+#include <sys/types.h>
+#endif
+
+#include <sys/param.h>
+#include <sys/dir.h>
+#include <signal.h>
+#include <sys/ioctl.h>
+
+#ifdef HAVE_PTRACE_H
+# include <ptrace.h>
+#else
+# ifdef HAVE_SYS_PTRACE_H
+# include <sys/ptrace.h>
+# endif
+#endif
+
+#if !defined (PT_READ_I)
+#define PT_READ_I 1 /* Read word from text space */
+#endif
+#if !defined (PT_READ_D)
+#define PT_READ_D 2 /* Read word from data space */
+#endif
+#if !defined (PT_READ_U)
+#define PT_READ_U 3 /* Read word from kernel user struct */
+#endif
+#if !defined (PT_WRITE_I)
+#define PT_WRITE_I 4 /* Write word to text space */
+#endif
+#if !defined (PT_WRITE_D)
+#define PT_WRITE_D 5 /* Write word to data space */
+#endif
+#if !defined (PT_WRITE_U)
+#define PT_WRITE_U 6 /* Write word to kernel user struct */
+#endif
+#if !defined (PT_CONTINUE)
+#define PT_CONTINUE 7 /* Continue after signal */
+#endif
+#if !defined (PT_STEP)
+#define PT_STEP 9 /* Set flag for single stepping */
+#endif
+#if !defined (PT_KILL)
+#define PT_KILL 8 /* Send child a SIGKILL signal */
+#endif
+
+#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 "gdb_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 */
+
+#if !defined (CHILD_XFER_MEMORY)
+static void udot_info PARAMS ((char *, int));
+#endif
+
+#if !defined (FETCH_INFERIOR_REGISTERS)
+static void fetch_register PARAMS ((int));
+static void store_register PARAMS ((int));
+#endif
+
+void _initialize_kernel_u_addr PARAMS ((void));
+void _initialize_infptrace PARAMS ((void));
+
+
+/* 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;
+{
+ int pt_status = 0;
+
+#if 0
+ int saved_errno;
+
+ printf ("call_ptrace(request=%d, pid=%d, addr=0x%x, data=0x%x)",
+ request, pid, addr, data);
+#endif
+#if defined(PT_SETTRC)
+ /* If the parent can be told to attach to us, try to do it. */
+ if (request == PT_SETTRC) {
+ errno = 0;
+ pt_status = ptrace (PT_SETTRC, 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 (errno) perror_with_name ("ptrace");
+#if 0
+ printf (" = %d\n", pt_status);
+#endif
+ if (pt_status < 0)
+ return pt_status;
+ else
+ return parent_attach_all (pid, addr, data);
+ }
+#endif
+
+#if defined(PT_CONTIN1)
+ /* On HPUX, PT_CONTIN1 is a form of continue that preserves pending
+ signals. If it's available, use it. */
+ if (request == PT_CONTINUE)
+ request = PT_CONTIN1;
+#endif
+
+#if defined(PT_SINGLE1)
+ /* On HPUX, PT_SINGLE1 is a form of step that preserves pending
+ signals. If it's available, use it. */
+ if (request == PT_STEP)
+ request = PT_SINGLE1;
+#endif
+
+#if 0
+ saved_errno = errno;
+ errno = 0;
+#endif
+ pt_status = 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 0
+ if (errno)
+ printf (" [errno = %d]", errno);
+
+ errno = saved_errno;
+ printf (" = 0x%x\n", pt_status);
+#endif
+ return pt_status;
+}
+
+
+#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
+
+/* Wait for a process to finish, possibly running a target-specific
+ hook before returning. */
+
+int
+ptrace_wait (pid, status)
+ int pid;
+ int *status;
+{
+ int wstate;
+
+ wstate = wait (status);
+ target_post_wait (wstate, *status);
+ return wstate;
+}
+
+void
+kill_inferior ()
+{
+ int status;
+
+ if (inferior_pid == 0)
+ return;
+
+ /* This once used to call "kill" to kill the inferior just in case
+ the inferior was still running. As others have noted in the past
+ (kingdon) there shouldn't be any way to get here if the inferior
+ is still running -- else there's a major problem elsewere in gdb
+ and it needs to be fixed.
+
+ The kill call causes problems under hpux10, so it's been removed;
+ if this causes problems we'll deal with them as they arise. */
+ ptrace (PT_KILL, inferior_pid, (PTRACE_ARG3_TYPE) 0, 0);
+ ptrace_wait (0, &status);
+ target_mourn_inferior ();
+}
+
+#ifndef CHILD_RESUME
+
+/* 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;
+ enum target_signal signal;
+{
+ errno = 0;
+
+ if (pid == -1)
+ /* Resume all threads. */
+ /* I think this only gets used in the non-threaded case, where "resume
+ all threads" and "resume inferior_pid" are the same. */
+ 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)
+ {
+ if (SOFTWARE_SINGLE_STEP_P)
+ abort(); /* Make sure this doesn't happen. */
+ else
+ ptrace (PT_STEP, pid, (PTRACE_ARG3_TYPE) 1,
+ target_signal_to_host (signal));
+ }
+ else
+ ptrace (PT_CONTINUE, pid, (PTRACE_ARG3_TYPE) 1,
+ target_signal_to_host (signal));
+
+ if (errno)
+ perror_with_name ("ptrace");
+}
+#endif /* CHILD_RESUME */
+
+
+#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
+
+/* 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) && !defined (FETCH_INFERIOR_REGISTERS)
+/* Get kernel_u_addr using BSD-style nlist(). */
+CORE_ADDR kernel_u_addr;
+#endif /* KERNEL_U_ADDR_BSD. */
+
+void
+_initialize_kernel_u_addr ()
+{
+#if defined (KERNEL_U_ADDR_BSD) && !defined (FETCH_INFERIOR_REGISTERS)
+ 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 (FETCH_INFERIOR_REGISTERS)
+
+#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;
+{
+ /* This isn't really an address. But ptrace thinks of it as one. */
+ CORE_ADDR regaddr;
+ char mess[128]; /* For messages */
+ register int i;
+ unsigned int offset; /* Offset of registers within the u area. */
+ char buf[MAX_REGISTER_RAW_SIZE];
+
+ 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)", REGISTER_NAME (regno), regno);
+ perror_with_name (mess);
+ }
+ }
+ supply_register (regno, buf);
+}
+
+
+/* Fetch register values from the inferior.
+ If REGNO is negative, do this for all registers.
+ Otherwise, REGNO specifies which register (so we can save time). */
+
+void
+fetch_inferior_registers (regno)
+ int regno;
+{
+ if (regno >= 0)
+ {
+ fetch_register (regno);
+ }
+ else
+ {
+ for (regno = 0; regno < ARCH_NUM_REGS; regno++)
+ {
+ fetch_register (regno);
+ }
+ }
+}
+
+/* Registers we shouldn't try to store. */
+#if !defined (CANNOT_STORE_REGISTER)
+#define CANNOT_STORE_REGISTER(regno) 0
+#endif
+
+/* Store one register. */
+
+static void
+store_register (regno)
+ int regno;
+{
+ /* This isn't really an address. But ptrace thinks of it as one. */
+ CORE_ADDR regaddr;
+ char mess[128]; /* For messages */
+ register int i;
+ unsigned int offset; /* Offset of registers within the u area. */
+
+ if (CANNOT_STORE_REGISTER (regno))
+ {
+ 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 (PT_WRITE_U, inferior_pid, (PTRACE_ARG3_TYPE) regaddr,
+ *(PTRACE_XFER_TYPE *) &registers[REGISTER_BYTE (regno) + i]);
+ regaddr += sizeof (PTRACE_XFER_TYPE);
+ if (errno != 0)
+ {
+ sprintf (mess, "writing register %s (#%d)", REGISTER_NAME (regno), regno);
+ perror_with_name (mess);
+ }
+ }
+}
+
+/* Store our register values back into the inferior.
+ If REGNO is negative, do this for all registers.
+ Otherwise, REGNO specifies which register (so we can save time). */
+
+void
+store_inferior_registers (regno)
+ int regno;
+{
+ if (regno >= 0)
+ {
+ store_register (regno);
+ }
+ else
+ {
+ for (regno = 0; regno < ARCH_NUM_REGS; regno++)
+ {
+ store_register (regno);
+ }
+ }
+}
+#endif /* !defined (FETCH_INFERIOR_REGISTERS). */
+
+
+#if !defined (CHILD_XFER_MEMORY)
+/* 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;
+ }
+#ifdef CLEAR_INSN_CACHE
+ CLEAR_INSN_CACHE();
+#endif
+ }
+ 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;
+}
+
+
+static void
+udot_info (dummy1, dummy2)
+ char *dummy1;
+ int dummy2;
+{
+#if defined (KERNEL_U_SIZE)
+ int udot_off; /* Offset into user struct */
+ int udot_val; /* Value from user struct at udot_off */
+ char mess[128]; /* For messages */
+#endif
+
+ if (!target_has_execution)
+ {
+ error ("The program is not being run.");
+ }
+
+#if !defined (KERNEL_U_SIZE)
+
+ /* Adding support for this command is easy. Typically you just add a
+ routine, called "kernel_u_size" that returns the size of the user
+ struct, to the appropriate *-nat.c file and then add to the native
+ config file "#define KERNEL_U_SIZE kernel_u_size()" */
+ error ("Don't know how large ``struct user'' is in this version of gdb.");
+
+#else
+
+ for (udot_off = 0; udot_off < KERNEL_U_SIZE; udot_off += sizeof (udot_val))
+ {
+ if ((udot_off % 24) == 0)
+ {
+ if (udot_off > 0)
+ {
+ printf_filtered ("\n");
+ }
+ printf_filtered ("%04x:", udot_off);
+ }
+ udot_val = ptrace (PT_READ_U, inferior_pid, (PTRACE_ARG3_TYPE) udot_off, 0);
+ if (errno != 0)
+ {
+ sprintf (mess, "\nreading user struct at offset 0x%x", udot_off);
+ perror_with_name (mess);
+ }
+ /* Avoid using nonportable (?) "*" in print specs */
+ printf_filtered (sizeof (int) == 4 ? " 0x%08x" : " 0x%16x", udot_val);
+ }
+ printf_filtered ("\n");
+
+#endif
+}
+#endif /* !defined (CHILD_XFER_MEMORY). */
+
+
+void
+_initialize_infptrace ()
+{
+#if !defined (CHILD_XFER_MEMORY)
+ add_info ("udot", udot_info,
+ "Print contents of kernel ``struct user'' for current child.");
+#endif
+}
diff --git a/gdb/infrun.c b/gdb/infrun.c
new file mode 100644
index 00000000000..5fd8fc107c7
--- /dev/null
+++ b/gdb/infrun.c
@@ -0,0 +1,3775 @@
+/* Target-struct-independent code to start (run) and stop an inferior process.
+ Copyright 1986, 87, 88, 89, 91, 92, 93, 94, 95, 96, 97, 1998
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "gdb_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 "gdbthread.h"
+#include "annotate.h"
+#include "symfile.h" /* for overlay functions */
+
+#include <signal.h>
+
+/* Prototypes for local functions */
+
+static void signals_info PARAMS ((char *, int));
+
+static void handle_command PARAMS ((char *, int));
+
+static void sig_print_info PARAMS ((enum target_signal));
+
+static void sig_print_header PARAMS ((void));
+
+static void resume_cleanups PARAMS ((int));
+
+static int hook_stop_stub PARAMS ((PTR));
+
+static void delete_breakpoint_current_contents PARAMS ((PTR));
+
+int inferior_ignoring_startup_exec_events = 0;
+int inferior_ignoring_leading_exec_events = 0;
+
+#ifdef HPUXHPPA
+/* wait_for_inferior and normal_stop use this to notify the user
+ when the inferior stopped in a different thread than it had been
+ running in. */
+static int switched_from_inferior_pid;
+#endif
+
+/* resume and wait_for_inferior use this to ensure that when
+ stepping over a hit breakpoint in a threaded application
+ only the thread that hit the breakpoint is stepped and the
+ other threads don't continue. This prevents having another
+ thread run past the breakpoint while it is temporarily
+ removed.
+
+ This is not thread-specific, so it isn't saved as part of
+ the infrun state.
+
+ Versions of gdb which don't use the "step == this thread steps
+ and others continue" model but instead use the "step == this
+ thread steps and others wait" shouldn't do this. */
+static int thread_step_needed = 0;
+
+void _initialize_infrun PARAMS ((void));
+
+/* 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
+
+/* Dynamic function trampolines are similar to solib trampolines in that they
+ are between the caller and the callee. The difference is that when you
+ enter a dynamic trampoline, you can't determine the callee's address. Some
+ (usually complex) code needs to run in the dynamic trampoline to figure out
+ the callee's address. This macro is usually called twice. First, when we
+ enter the trampoline (looks like a normal function call at that point). It
+ should return the PC of a point within the trampoline where the callee's
+ address is known. Second, when we hit the breakpoint, this routine returns
+ the callee's address. At that point, things proceed as per a step resume
+ breakpoint. */
+
+#ifndef DYNAMIC_TRAMPOLINE_NEXTPC
+#define DYNAMIC_TRAMPOLINE_NEXTPC(pc) 0
+#endif
+
+/* On SVR4 based systems, determining the callee's address is exceedingly
+ difficult and depends on the implementation of the run time loader.
+ If we are stepping at the source level, we single step until we exit
+ the run time loader code and reach the callee's address. */
+
+#ifndef IN_SOLIB_DYNSYM_RESOLVE_CODE
+#define IN_SOLIB_DYNSYM_RESOLVE_CODE(pc) 0
+#endif
+
+/* For SVR4 shared libraries, each call goes through a small piece of
+ trampoline code in the ".plt" section. IN_SOLIB_CALL_TRAMPOLINE evaluates
+ to nonzero if we are current stopped in one of these. */
+
+#ifndef IN_SOLIB_CALL_TRAMPOLINE
+#define IN_SOLIB_CALL_TRAMPOLINE(pc,name) 0
+#endif
+
+/* In some shared library schemes, the return path from a shared library
+ call may need to go through a trampoline too. */
+
+#ifndef IN_SOLIB_RETURN_TRAMPOLINE
+#define IN_SOLIB_RETURN_TRAMPOLINE(pc,name) 0
+#endif
+
+/* This function returns TRUE if pc is the address of an instruction
+ that lies within the dynamic linker (such as the event hook, or the
+ dld itself).
+
+ This function must be used only when a dynamic linker event has
+ been caught, and the inferior is being stepped out of the hook, or
+ undefined results are guaranteed. */
+
+#ifndef SOLIB_IN_DYNAMIC_LINKER
+#define SOLIB_IN_DYNAMIC_LINKER(pid,pc) 0
+#endif
+
+/* On MIPS16, a function that returns a floating point value may call
+ a library helper function to copy the return value to a floating point
+ register. The IGNORE_HELPER_CALL macro returns non-zero if we
+ should ignore (i.e. step over) this function call. */
+#ifndef IGNORE_HELPER_CALL
+#define IGNORE_HELPER_CALL(pc) 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;
+
+#ifdef SOLIB_ADD
+/* Nonzero if we want to give control to the user when we're notified
+ of shared library events by the dynamic linker. */
+static int stop_on_solib_events;
+#endif
+
+#ifdef HP_OS_BUG
+/* 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;
+#endif
+
+/* 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;
+
+static struct breakpoint *step_resume_breakpoint = NULL;
+static struct breakpoint *through_sigtramp_breakpoint = NULL;
+
+/* On some platforms (e.g., HP-UX), hardware watchpoints have bad
+ interactions with an inferior that is running a kernel function
+ (aka, a system call or "syscall"). wait_for_inferior therefore
+ may have a need to know when the inferior is in a syscall. This
+ is a count of the number of inferior threads which are known to
+ currently be running in a syscall. */
+static int number_of_threads_in_syscalls;
+
+/* This is used to remember when a fork, vfork or exec event
+ was caught by a catchpoint, and thus the event is to be
+ followed at the next resume of the inferior, and not
+ immediately. */
+static struct
+ {
+ enum target_waitkind kind;
+ struct
+ {
+ int parent_pid;
+ int saw_parent_fork;
+ int child_pid;
+ int saw_child_fork;
+ int saw_child_exec;
+ }
+ fork_event;
+ char *execd_pathname;
+ }
+pending_follow;
+
+/* Some platforms don't allow us to do anything meaningful with a
+ vforked child until it has exec'd. Vforked processes on such
+ platforms can only be followed after they've exec'd.
+
+ When this is set to 0, a vfork can be immediately followed,
+ and an exec can be followed merely as an exec. When this is
+ set to 1, a vfork event has been seen, but cannot be followed
+ until the exec is seen.
+
+ (In the latter case, inferior_pid is still the parent of the
+ vfork, and pending_follow.fork_event.child_pid is the child. The
+ appropriate process is followed, according to the setting of
+ follow-fork-mode.) */
+static int follow_vfork_when_exec;
+
+static char *follow_fork_mode_kind_names[] =
+{
+/* ??rehrauer: The "both" option is broken, by what may be a 10.20
+ kernel problem. It's also not terribly useful without a GUI to
+ help the user drive two debuggers. So for now, I'm disabling
+ the "both" option.
+ "parent", "child", "both", "ask" };
+ */
+ "parent", "child", "ask"};
+
+static char *follow_fork_mode_string = NULL;
+
+
+#if defined(HPUXHPPA)
+static void
+follow_inferior_fork (parent_pid, child_pid, has_forked, has_vforked)
+ int parent_pid;
+ int child_pid;
+ int has_forked;
+ int has_vforked;
+{
+ int followed_parent = 0;
+ int followed_child = 0;
+ int ima_clone = 0;
+
+ /* Which process did the user want us to follow? */
+ char *follow_mode =
+ savestring (follow_fork_mode_string, strlen (follow_fork_mode_string));
+
+ /* Or, did the user not know, and want us to ask? */
+ if (STREQ (follow_fork_mode_string, "ask"))
+ {
+ char requested_mode[100];
+
+ free (follow_mode);
+ error ("\"ask\" mode NYI");
+ follow_mode = savestring (requested_mode, strlen (requested_mode));
+ }
+
+ /* If we're to be following the parent, then detach from child_pid.
+ We're already following the parent, so need do nothing explicit
+ for it. */
+ if (STREQ (follow_mode, "parent"))
+ {
+ followed_parent = 1;
+
+ /* We're already attached to the parent, by default. */
+
+ /* Before detaching from the child, remove all breakpoints from
+ it. (This won't actually modify the breakpoint list, but will
+ physically remove the breakpoints from the child.) */
+ if (!has_vforked || !follow_vfork_when_exec)
+ {
+ detach_breakpoints (child_pid);
+ SOLIB_REMOVE_INFERIOR_HOOK (child_pid);
+ }
+
+ /* Detach from the child. */
+ dont_repeat ();
+
+ target_require_detach (child_pid, "", 1);
+ }
+
+ /* If we're to be following the child, then attach to it, detach
+ from inferior_pid, and set inferior_pid to child_pid. */
+ else if (STREQ (follow_mode, "child"))
+ {
+ char child_pid_spelling[100]; /* Arbitrary length. */
+
+ followed_child = 1;
+
+ /* Before detaching from the parent, detach all breakpoints from
+ the child. But only if we're forking, or if we follow vforks
+ as soon as they happen. (If we're following vforks only when
+ the child has exec'd, then it's very wrong to try to write
+ back the "shadow contents" of inserted breakpoints now -- they
+ belong to the child's pre-exec'd a.out.) */
+ if (!has_vforked || !follow_vfork_when_exec)
+ {
+ detach_breakpoints (child_pid);
+ }
+
+ /* Before detaching from the parent, remove all breakpoints from it. */
+ remove_breakpoints ();
+
+ /* Also reset the solib inferior hook from the parent. */
+ SOLIB_REMOVE_INFERIOR_HOOK (inferior_pid);
+
+ /* Detach from the parent. */
+ dont_repeat ();
+ target_detach (NULL, 1);
+
+ /* Attach to the child. */
+ inferior_pid = child_pid;
+ sprintf (child_pid_spelling, "%d", child_pid);
+ dont_repeat ();
+
+ target_require_attach (child_pid_spelling, 1);
+
+ /* Was there a step_resume breakpoint? (There was if the user
+ did a "next" at the fork() call.) If so, explicitly reset its
+ thread number.
+
+ step_resumes are a form of bp that are made to be per-thread.
+ Since we created the step_resume bp when the parent process
+ was being debugged, and now are switching to the child process,
+ from the breakpoint package's viewpoint, that's a switch of
+ "threads". We must update the bp's notion of which thread
+ it is for, or it'll be ignored when it triggers... */
+ if (step_resume_breakpoint &&
+ (!has_vforked || !follow_vfork_when_exec))
+ breakpoint_re_set_thread (step_resume_breakpoint);
+
+ /* Reinsert all breakpoints in the child. (The user may've set
+ breakpoints after catching the fork, in which case those
+ actually didn't get set in the child, but only in the parent.) */
+ if (!has_vforked || !follow_vfork_when_exec)
+ {
+ breakpoint_re_set ();
+ insert_breakpoints ();
+ }
+ }
+
+ /* If we're to be following both parent and child, then fork ourselves,
+ and attach the debugger clone to the child. */
+ else if (STREQ (follow_mode, "both"))
+ {
+ char pid_suffix[100]; /* Arbitrary length. */
+
+ /* Clone ourselves to follow the child. This is the end of our
+ involvement with child_pid; our clone will take it from here... */
+ dont_repeat ();
+ target_clone_and_follow_inferior (child_pid, &followed_child);
+ followed_parent = !followed_child;
+
+ /* We continue to follow the parent. To help distinguish the two
+ debuggers, though, both we and our clone will reset our prompts. */
+ sprintf (pid_suffix, "[%d] ", inferior_pid);
+ set_prompt (strcat (get_prompt (), pid_suffix));
+ }
+
+ /* The parent and child of a vfork share the same address space.
+ Also, on some targets the order in which vfork and exec events
+ are received for parent in child requires some delicate handling
+ of the events.
+
+ For instance, on ptrace-based HPUX we receive the child's vfork
+ event first, at which time the parent has been suspended by the
+ OS and is essentially untouchable until the child's exit or second
+ exec event arrives. At that time, the parent's vfork event is
+ delivered to us, and that's when we see and decide how to follow
+ the vfork. But to get to that point, we must continue the child
+ until it execs or exits. To do that smoothly, all breakpoints
+ must be removed from the child, in case there are any set between
+ the vfork() and exec() calls. But removing them from the child
+ also removes them from the parent, due to the shared-address-space
+ nature of a vfork'd parent and child. On HPUX, therefore, we must
+ take care to restore the bp's to the parent before we continue it.
+ Else, it's likely that we may not stop in the expected place. (The
+ worst scenario is when the user tries to step over a vfork() call;
+ the step-resume bp must be restored for the step to properly stop
+ in the parent after the call completes!)
+
+ Sequence of events, as reported to gdb from HPUX:
+
+ Parent Child Action for gdb to take
+ -------------------------------------------------------
+ 1 VFORK Continue child
+ 2 EXEC
+ 3 EXEC or EXIT
+ 4 VFORK */
+ if (has_vforked)
+ {
+ target_post_follow_vfork (parent_pid,
+ followed_parent,
+ child_pid,
+ followed_child);
+ }
+
+ pending_follow.fork_event.saw_parent_fork = 0;
+ pending_follow.fork_event.saw_child_fork = 0;
+
+ free (follow_mode);
+}
+
+static void
+follow_fork (parent_pid, child_pid)
+ int parent_pid;
+ int child_pid;
+{
+ follow_inferior_fork (parent_pid, child_pid, 1, 0);
+}
+
+
+/* Forward declaration. */
+static void follow_exec PARAMS ((int, char *));
+
+static void
+follow_vfork (parent_pid, child_pid)
+ int parent_pid;
+ int child_pid;
+{
+ follow_inferior_fork (parent_pid, child_pid, 0, 1);
+
+ /* Did we follow the child? Had it exec'd before we saw the parent vfork? */
+ if (pending_follow.fork_event.saw_child_exec && (inferior_pid == child_pid))
+ {
+ pending_follow.fork_event.saw_child_exec = 0;
+ pending_follow.kind = TARGET_WAITKIND_SPURIOUS;
+ follow_exec (inferior_pid, pending_follow.execd_pathname);
+ free (pending_follow.execd_pathname);
+ }
+}
+#endif /* HPUXHPPA */
+
+static void
+follow_exec (pid, execd_pathname)
+ int pid;
+ char *execd_pathname;
+{
+#ifdef HPUXHPPA
+ int saved_pid = pid;
+ extern struct target_ops child_ops;
+
+ /* Did this exec() follow a vfork()? If so, we must follow the
+ vfork now too. Do it before following the exec. */
+ if (follow_vfork_when_exec &&
+ (pending_follow.kind == TARGET_WAITKIND_VFORKED))
+ {
+ pending_follow.kind = TARGET_WAITKIND_SPURIOUS;
+ follow_vfork (inferior_pid, pending_follow.fork_event.child_pid);
+ follow_vfork_when_exec = 0;
+ saved_pid = inferior_pid;
+
+ /* Did we follow the parent? If so, we're done. If we followed
+ the child then we must also follow its exec(). */
+ if (inferior_pid == pending_follow.fork_event.parent_pid)
+ return;
+ }
+
+ /* This is an exec event that we actually wish to pay attention to.
+ Refresh our symbol table to the newly exec'd program, remove any
+ momentary bp's, etc.
+
+ If there are breakpoints, they aren't really inserted now,
+ since the exec() transformed our inferior into a fresh set
+ of instructions.
+
+ We want to preserve symbolic breakpoints on the list, since
+ we have hopes that they can be reset after the new a.out's
+ symbol table is read.
+
+ However, any "raw" breakpoints must be removed from the list
+ (e.g., the solib bp's), since their address is probably invalid
+ now.
+
+ And, we DON'T want to call delete_breakpoints() here, since
+ that may write the bp's "shadow contents" (the instruction
+ value that was overwritten witha TRAP instruction). Since
+ we now have a new a.out, those shadow contents aren't valid. */
+ update_breakpoints_after_exec ();
+
+ /* If there was one, it's gone now. We cannot truly step-to-next
+ statement through an exec(). */
+ step_resume_breakpoint = NULL;
+ step_range_start = 0;
+ step_range_end = 0;
+
+ /* If there was one, it's gone now. */
+ through_sigtramp_breakpoint = NULL;
+
+ /* What is this a.out's name? */
+ printf_unfiltered ("Executing new program: %s\n", execd_pathname);
+
+ /* We've followed the inferior through an exec. Therefore, the
+ inferior has essentially been killed & reborn. */
+ gdb_flush (gdb_stdout);
+ target_mourn_inferior ();
+ inferior_pid = saved_pid; /* Because mourn_inferior resets inferior_pid. */
+ push_target (&child_ops);
+
+ /* That a.out is now the one to use. */
+ exec_file_attach (execd_pathname, 0);
+
+ /* And also is where symbols can be found. */
+ symbol_file_command (execd_pathname, 0);
+
+ /* Reset the shared library package. This ensures that we get
+ a shlib event when the child reaches "_start", at which point
+ the dld will have had a chance to initialize the child. */
+ SOLIB_RESTART ();
+ SOLIB_CREATE_INFERIOR_HOOK (inferior_pid);
+
+ /* Reinsert all breakpoints. (Those which were symbolic have
+ been reset to the proper address in the new a.out, thanks
+ to symbol_file_command...) */
+ insert_breakpoints ();
+
+ /* The next resume of this inferior should bring it to the shlib
+ startup breakpoints. (If the user had also set bp's on
+ "main" from the old (parent) process, then they'll auto-
+ matically get reset there in the new process.) */
+#endif
+}
+
+/* Non-zero if we just simulating a single-step. This is needed
+ because we cannot remove the breakpoints in the inferior process
+ until after the `wait' in `wait_for_inferior'. */
+static int singlestep_breakpoints_inserted_p = 0;
+
+
+/* Things to clean up if we QUIT out of resume (). */
+/* ARGSUSED */
+static void
+resume_cleanups (arg)
+ int arg;
+{
+ normal_stop ();
+}
+
+static char schedlock_off[] = "off";
+static char schedlock_on[] = "on";
+static char schedlock_step[] = "step";
+static char *scheduler_mode = schedlock_off;
+static char *scheduler_enums[] =
+{schedlock_off, schedlock_on, schedlock_step};
+
+static void
+set_schedlock_func (args, from_tty, c)
+ char *args;
+ int from_tty;
+ struct cmd_list_element *c;
+{
+ if (c->type == set_cmd)
+ if (!target_can_lock_scheduler)
+ {
+ scheduler_mode = schedlock_off;
+ error ("Target '%s' cannot support this command.",
+ target_shortname);
+ }
+}
+
+
+/* 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;
+ enum target_signal sig;
+{
+ int should_resume = 1;
+ struct cleanup *old_cleanups = make_cleanup ((make_cleanup_func)
+ 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
+
+ if (SOFTWARE_SINGLE_STEP_P && step)
+ {
+ /* Do it the hard way, w/temp breakpoints */
+ SOFTWARE_SINGLE_STEP (sig, 1 /*insert-breakpoints*/ );
+ /* ...and don't ask hardware to do it. */
+ step = 0;
+ /* and do not pull these breakpoints until after a `wait' in
+ `wait_for_inferior' */
+ singlestep_breakpoints_inserted_p = 1;
+ }
+
+ /* Handle any optimized stores to the inferior NOW... */
+#ifdef DO_DEFERRED_STORES
+ DO_DEFERRED_STORES;
+#endif
+
+#ifdef HPUXHPPA
+ /* If there were any forks/vforks/execs that were caught and are
+ now to be followed, then do so. */
+ switch (pending_follow.kind)
+ {
+ case (TARGET_WAITKIND_FORKED):
+ pending_follow.kind = TARGET_WAITKIND_SPURIOUS;
+ follow_fork (inferior_pid, pending_follow.fork_event.child_pid);
+ break;
+
+ case (TARGET_WAITKIND_VFORKED):
+ {
+ int saw_child_exec = pending_follow.fork_event.saw_child_exec;
+
+ pending_follow.kind = TARGET_WAITKIND_SPURIOUS;
+ follow_vfork (inferior_pid, pending_follow.fork_event.child_pid);
+
+ /* Did we follow the child, but not yet see the child's exec event?
+ If so, then it actually ought to be waiting for us; we respond to
+ parent vfork events. We don't actually want to resume the child
+ in this situation; we want to just get its exec event. */
+ if (!saw_child_exec &&
+ (inferior_pid == pending_follow.fork_event.child_pid))
+ should_resume = 0;
+ }
+ break;
+
+ case (TARGET_WAITKIND_EXECD):
+ /* If we saw a vfork event but couldn't follow it until we saw
+ an exec, then now might be the time! */
+ pending_follow.kind = TARGET_WAITKIND_SPURIOUS;
+ /* follow_exec is called as soon as the exec event is seen. */
+ break;
+
+ default:
+ break;
+ }
+#endif /* HPUXHPPA */
+
+ /* Install inferior's terminal modes. */
+ target_terminal_inferior ();
+
+ if (should_resume)
+ {
+#ifdef HPUXHPPA
+ if (thread_step_needed)
+ {
+ /* We stopped on a BPT instruction;
+ don't continue other threads and
+ just step this thread. */
+ thread_step_needed = 0;
+
+ if (!breakpoint_here_p (read_pc ()))
+ {
+ /* Breakpoint deleted: ok to do regular resume
+ where all the threads either step or continue. */
+ target_resume (-1, step, sig);
+ }
+ else
+ {
+ if (!step)
+ {
+ warning ("Internal error, changing continue to step.");
+ remove_breakpoints ();
+ breakpoints_inserted = 0;
+ trap_expected = 1;
+ step = 1;
+ }
+
+ target_resume (inferior_pid, step, sig);
+ }
+ }
+ else
+#endif /* HPUXHPPA */
+ {
+ /* Vanilla resume. */
+
+ if ((scheduler_mode == schedlock_on) ||
+ (scheduler_mode == schedlock_step && step != 0))
+ target_resume (inferior_pid, step, sig);
+ else
+ 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;
+ enum target_signal 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 (and report a second
+ hit at this breakpoint). */
+
+ if (read_pc () == stop_pc && breakpoint_here_p (read_pc ()))
+ oneproc = 1;
+
+#ifndef STEP_SKIPS_DELAY
+#define STEP_SKIPS_DELAY(pc) (0)
+#define STEP_SKIPS_DELAY_P (0)
+#endif
+ /* Check breakpoint_here_p first, because breakpoint_here_p is fast
+ (it just checks internal GDB data structures) and STEP_SKIPS_DELAY
+ is slow (it needs to read memory from the target). */
+ if (STEP_SKIPS_DELAY_P
+ && breakpoint_here_p (read_pc () + 4)
+ && STEP_SKIPS_DELAY (read_pc ()))
+ oneproc = 1;
+ }
+ else
+ {
+ write_pc (addr);
+
+ /* New address; we don't need to single-step a thread
+ over a breakpoint we just hit, 'cause we aren't
+ continuing from there.
+
+ It's not worth worrying about the case where a user
+ asks for a "jump" at the current PC--if they get the
+ hiccup of re-hiting a hit breakpoint, what else do
+ they expect? */
+ thread_step_needed = 0;
+ }
+
+#ifdef PREPARE_TO_PROCEED
+ /* In a multi-threaded task we may select another thread
+ and then continue or step.
+
+ But if the old thread was stopped at a breakpoint, it
+ will immediately cause another breakpoint stop without
+ any execution (i.e. it will report a breakpoint hit
+ incorrectly). So we must step over it first.
+
+ PREPARE_TO_PROCEED checks the current thread against the thread
+ that reported the most recent event. If a step-over is required
+ it returns TRUE and sets the current thread to the old thread. */
+ if (PREPARE_TO_PROCEED () && breakpoint_here_p (read_pc ()))
+ {
+ oneproc = 1;
+ thread_step_needed = 1;
+ }
+
+#endif /* PREPARE_TO_PROCEED */
+
+#ifdef HP_OS_BUG
+ 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;
+ }
+#endif /* HP_OS_BUG */
+
+ 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 != TARGET_SIGNAL_DEFAULT)
+ stop_signal = siggnal;
+ /* If this signal should not be seen by program,
+ give it zero. Used for debugging signals. */
+ else if (!signal_program[stop_signal])
+ stop_signal = TARGET_SIGNAL_0;
+
+ annotate_starting ();
+
+ /* Make sure that output from GDB appears before output from the
+ inferior. */
+ gdb_flush (gdb_stdout);
+
+ /* 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_func_start;
+static char *prev_func_name;
+
+
+/* Start remote-debugging of a machine over a serial link. */
+
+void
+start_remote ()
+{
+ init_thread_list ();
+ init_wait_for_inferior ();
+ 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_func_start = 0;
+ prev_func_name = NULL;
+
+#ifdef HP_OS_BUG
+ trap_expected_after_continue = 0;
+#endif
+ breakpoints_inserted = 0;
+ breakpoint_init_inferior (inf_starting);
+
+ /* Don't confuse first call to proceed(). */
+ stop_signal = TARGET_SIGNAL_0;
+
+ /* The first resume is not following a fork/vfork/exec. */
+ pending_follow.kind = TARGET_WAITKIND_SPURIOUS; /* I.e., none. */
+ pending_follow.fork_event.saw_parent_fork = 0;
+ pending_follow.fork_event.saw_child_fork = 0;
+ pending_follow.fork_event.saw_child_exec = 0;
+
+ /* See wait_for_inferior's handling of SYSCALL_ENTRY/RETURN events. */
+ number_of_threads_in_syscalls = 0;
+
+ clear_proceed_status ();
+}
+
+static void
+delete_breakpoint_current_contents (arg)
+ PTR arg;
+{
+ struct breakpoint **breakpointp = (struct breakpoint **) arg;
+ if (*breakpointp != NULL)
+ {
+ delete_breakpoint (*breakpointp);
+ *breakpointp = NULL;
+ }
+}
+
+/* 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;
+ struct target_waitstatus w;
+ int another_trap;
+ int random_signal = 0;
+ CORE_ADDR stop_func_start;
+ CORE_ADDR stop_func_end;
+ char *stop_func_name;
+#if 0
+ CORE_ADDR prologue_pc = 0;
+#endif
+ CORE_ADDR tmp;
+ struct symtab_and_line sal;
+ int remove_breakpoints_on_following_step = 0;
+ int current_line;
+ struct symtab *current_symtab;
+ int handling_longjmp = 0; /* FIXME */
+ int pid;
+ int saved_inferior_pid;
+ int update_step_sp = 0;
+ int stepping_through_solib_after_catch = 0;
+ bpstat stepping_through_solib_catchpoints = NULL;
+ int enable_hw_watchpoints_after_wait = 0;
+ int stepping_through_sigtramp = 0;
+ int new_thread_event;
+
+#ifdef HAVE_NONSTEPPABLE_WATCHPOINT
+ int stepped_after_stopped_by_watchpoint;
+#endif
+
+ old_cleanups = make_cleanup (delete_breakpoint_current_contents,
+ &step_resume_breakpoint);
+ make_cleanup (delete_breakpoint_current_contents,
+ &through_sigtramp_breakpoint);
+ sal = find_pc_line (prev_pc, 0);
+ current_line = sal.line;
+ current_symtab = sal.symtab;
+
+ /* Are we stepping? */
+#define CURRENTLY_STEPPING() \
+ ((through_sigtramp_breakpoint == NULL \
+ && !handling_longjmp \
+ && ((step_range_end && step_resume_breakpoint == NULL) \
+ || trap_expected)) \
+ || stepping_through_solib_after_catch \
+ || bpstat_should_step ())
+ ;
+ thread_step_needed = 0;
+
+#ifdef HPUXHPPA
+ /* We'll update this if & when we switch to a new thread. */
+ switched_from_inferior_pid = inferior_pid;
+#endif
+
+ while (1)
+ {
+ extern int overlay_cache_invalid; /* declared in symfile.h */
+
+ overlay_cache_invalid = 1;
+
+ /* We have to invalidate the registers BEFORE calling target_wait because
+ they can be loaded from the target while in target_wait. This makes
+ remote debugging a bit more efficient for those targets that provide
+ critical registers as part of their normal status mechanism. */
+
+ registers_changed ();
+
+ if (target_wait_hook)
+ pid = target_wait_hook (-1, &w);
+ else
+ pid = target_wait (-1, &w);
+
+ /* Since we've done a wait, we have a new event. Don't carry
+ over any expectations about needing to step over a
+ breakpoint. */
+ thread_step_needed = 0;
+
+ /* See comments where a TARGET_WAITKIND_SYSCALL_RETURN event is
+ serviced in this loop, below. */
+ if (enable_hw_watchpoints_after_wait)
+ {
+ TARGET_ENABLE_HW_WATCHPOINTS (inferior_pid);
+ enable_hw_watchpoints_after_wait = 0;
+ }
+
+
+#ifdef HAVE_NONSTEPPABLE_WATCHPOINT
+ stepped_after_stopped_by_watchpoint = 0;
+#endif
+
+ /* Gross.
+
+ We goto this label from elsewhere in wait_for_inferior when we want
+ to continue the main loop without calling "wait" and trashing the
+ waitstatus contained in W. */
+ have_waited:
+
+ flush_cached_frames ();
+
+ /* If it's a new process, add it to the thread database */
+
+ new_thread_event = ((pid != inferior_pid) && !in_thread_list (pid));
+
+ if (w.kind != TARGET_WAITKIND_EXITED
+ && w.kind != TARGET_WAITKIND_SIGNALLED
+ && new_thread_event)
+ {
+ add_thread (pid);
+
+
+#ifdef HPUXHPPA
+ fprintf_unfiltered (gdb_stderr, "[New %s]\n",
+ target_pid_or_tid_to_str (pid));
+
+#else
+ printf_filtered ("[New %s]\n", target_pid_to_str (pid));
+#endif
+
+#if 0
+ /* NOTE: This block is ONLY meant to be invoked in case of a
+ "thread creation event"! If it is invoked for any other
+ sort of event (such as a new thread landing on a breakpoint),
+ the event will be discarded, which is almost certainly
+ a bad thing!
+
+ To avoid this, the low-level module (eg. target_wait)
+ should call in_thread_list and add_thread, so that the
+ new thread is known by the time we get here. */
+
+ /* We may want to consider not doing a resume here in order
+ to give the user a chance to play with the new thread.
+ It might be good to make that a user-settable option. */
+
+ /* At this point, all threads are stopped (happens
+ automatically in either the OS or the native code).
+ Therefore we need to continue all threads in order to
+ make progress. */
+
+ target_resume (-1, 0, TARGET_SIGNAL_0);
+ continue;
+#endif
+ }
+
+ switch (w.kind)
+ {
+ case TARGET_WAITKIND_LOADED:
+ /* Ignore gracefully during startup of the inferior, as it
+ might be the shell which has just loaded some objects,
+ otherwise add the symbols for the newly loaded objects. */
+#ifdef SOLIB_ADD
+ if (!stop_soon_quietly)
+ {
+ extern int auto_solib_add;
+
+ /* Remove breakpoints, SOLIB_ADD might adjust
+ breakpoint addresses via breakpoint_re_set. */
+ if (breakpoints_inserted)
+ remove_breakpoints ();
+
+ /* Check for any newly added shared libraries if we're
+ supposed to be adding them automatically. */
+ if (auto_solib_add)
+ {
+ /* Switch terminal for any messages produced by
+ breakpoint_re_set. */
+ target_terminal_ours_for_output ();
+ SOLIB_ADD (NULL, 0, NULL);
+ target_terminal_inferior ();
+ }
+
+ /* Reinsert breakpoints and continue. */
+ if (breakpoints_inserted)
+ insert_breakpoints ();
+ }
+#endif
+ resume (0, TARGET_SIGNAL_0);
+ continue;
+
+ case TARGET_WAITKIND_SPURIOUS:
+ resume (0, TARGET_SIGNAL_0);
+ continue;
+
+ case TARGET_WAITKIND_EXITED:
+ target_terminal_ours (); /* Must do this before mourn anyway */
+ annotate_exited (w.value.integer);
+ if (w.value.integer)
+ printf_filtered ("\nProgram exited with code 0%o.\n",
+ (unsigned int) w.value.integer);
+ else
+ printf_filtered ("\nProgram exited normally.\n");
+
+ /* Record the exit code in the convenience variable $_exitcode, so
+ that the user can inspect this again later. */
+ set_internalvar (lookup_internalvar ("_exitcode"),
+ value_from_longest (builtin_type_int,
+ (LONGEST) w.value.integer));
+ gdb_flush (gdb_stdout);
+ target_mourn_inferior ();
+ singlestep_breakpoints_inserted_p = 0; /*SOFTWARE_SINGLE_STEP_P*/
+ stop_print_frame = 0;
+ goto stop_stepping;
+
+ case TARGET_WAITKIND_SIGNALLED:
+ stop_print_frame = 0;
+ stop_signal = w.value.sig;
+ target_terminal_ours (); /* Must do this before mourn anyway */
+ annotate_signalled ();
+
+ /* This looks pretty bogus to me. Doesn't TARGET_WAITKIND_SIGNALLED
+ mean it is already dead? This has been here since GDB 2.8, so
+ perhaps it means rms didn't understand unix waitstatuses?
+ For the moment I'm just kludging around this in remote.c
+ rather than trying to change it here --kingdon, 5 Dec 1994. */
+ target_kill (); /* kill mourns as well */
+
+ printf_filtered ("\nProgram terminated with signal ");
+ annotate_signal_name ();
+ printf_filtered ("%s", target_signal_to_name (stop_signal));
+ annotate_signal_name_end ();
+ printf_filtered (", ");
+ annotate_signal_string ();
+ printf_filtered ("%s", target_signal_to_string (stop_signal));
+ annotate_signal_string_end ();
+ printf_filtered (".\n");
+
+ printf_filtered ("The program no longer exists.\n");
+ gdb_flush (gdb_stdout);
+ singlestep_breakpoints_inserted_p = 0; /*SOFTWARE_SINGLE_STEP_P*/
+ goto stop_stepping;
+
+ /* The following are the only cases in which we keep going;
+ the above cases end in a continue or goto. */
+ case TARGET_WAITKIND_FORKED:
+ stop_signal = TARGET_SIGNAL_TRAP;
+ pending_follow.kind = w.kind;
+
+ /* Ignore fork events reported for the parent; we're only
+ interested in reacting to forks of the child. Note that
+ we expect the child's fork event to be available if we
+ waited for it now. */
+ if (inferior_pid == pid)
+ {
+ pending_follow.fork_event.saw_parent_fork = 1;
+ pending_follow.fork_event.parent_pid = pid;
+ pending_follow.fork_event.child_pid = w.value.related_pid;
+ continue;
+ }
+ else
+ {
+ pending_follow.fork_event.saw_child_fork = 1;
+ pending_follow.fork_event.child_pid = pid;
+ pending_follow.fork_event.parent_pid = w.value.related_pid;
+ }
+
+ stop_pc = read_pc_pid (pid);
+ saved_inferior_pid = inferior_pid;
+ inferior_pid = pid;
+ stop_bpstat = bpstat_stop_status
+ (&stop_pc,
+#if DECR_PC_AFTER_BREAK
+ (prev_pc != stop_pc - DECR_PC_AFTER_BREAK
+ && CURRENTLY_STEPPING ())
+#else /* DECR_PC_AFTER_BREAK zero */
+ 0
+#endif /* DECR_PC_AFTER_BREAK zero */
+ );
+ random_signal = !bpstat_explains_signal (stop_bpstat);
+ inferior_pid = saved_inferior_pid;
+ goto process_event_stop_test;
+
+ /* If this a platform which doesn't allow a debugger to touch a
+ vfork'd inferior until after it exec's, then we'd best keep
+ our fingers entirely off the inferior, other than continuing
+ it. This has the unfortunate side-effect that catchpoints
+ of vforks will be ignored. But since the platform doesn't
+ allow the inferior be touched at vfork time, there's really
+ little choice. */
+ case TARGET_WAITKIND_VFORKED:
+ stop_signal = TARGET_SIGNAL_TRAP;
+ pending_follow.kind = w.kind;
+
+ /* Is this a vfork of the parent? If so, then give any
+ vfork catchpoints a chance to trigger now. (It's
+ dangerous to do so if the child canot be touched until
+ it execs, and the child has not yet exec'd. We probably
+ should warn the user to that effect when the catchpoint
+ triggers...) */
+ if (pid == inferior_pid)
+ {
+ pending_follow.fork_event.saw_parent_fork = 1;
+ pending_follow.fork_event.parent_pid = pid;
+ pending_follow.fork_event.child_pid = w.value.related_pid;
+ }
+
+ /* If we've seen the child's vfork event but cannot really touch
+ the child until it execs, then we must continue the child now.
+ Else, give any vfork catchpoints a chance to trigger now. */
+ else
+ {
+ pending_follow.fork_event.saw_child_fork = 1;
+ pending_follow.fork_event.child_pid = pid;
+ pending_follow.fork_event.parent_pid = w.value.related_pid;
+ target_post_startup_inferior (pending_follow.fork_event.child_pid);
+ follow_vfork_when_exec = !target_can_follow_vfork_prior_to_exec ();
+ if (follow_vfork_when_exec)
+ {
+ target_resume (pid, 0, TARGET_SIGNAL_0);
+ continue;
+ }
+ }
+
+ stop_pc = read_pc ();
+ stop_bpstat = bpstat_stop_status
+ (&stop_pc,
+#if DECR_PC_AFTER_BREAK
+ (prev_pc != stop_pc - DECR_PC_AFTER_BREAK
+ && CURRENTLY_STEPPING ())
+#else /* DECR_PC_AFTER_BREAK zero */
+ 0
+#endif /* DECR_PC_AFTER_BREAK zero */
+ );
+ random_signal = !bpstat_explains_signal (stop_bpstat);
+ goto process_event_stop_test;
+
+ case TARGET_WAITKIND_EXECD:
+ stop_signal = TARGET_SIGNAL_TRAP;
+
+ /* Is this a target which reports multiple exec events per actual
+ call to exec()? (HP-UX using ptrace does, for example.) If so,
+ ignore all but the last one. Just resume the exec'r, and wait
+ for the next exec event. */
+ if (inferior_ignoring_leading_exec_events)
+ {
+ inferior_ignoring_leading_exec_events--;
+ if (pending_follow.kind == TARGET_WAITKIND_VFORKED)
+ ENSURE_VFORKING_PARENT_REMAINS_STOPPED (pending_follow.fork_event.parent_pid);
+ target_resume (pid, 0, TARGET_SIGNAL_0);
+ continue;
+ }
+ inferior_ignoring_leading_exec_events =
+ target_reported_exec_events_per_exec_call () - 1;
+
+ pending_follow.execd_pathname = savestring (w.value.execd_pathname,
+ strlen (w.value.execd_pathname));
+
+ /* Did inferior_pid exec, or did a (possibly not-yet-followed)
+ child of a vfork exec?
+
+ ??rehrauer: This is unabashedly an HP-UX specific thing. On
+ HP-UX, events associated with a vforking inferior come in
+ threes: a vfork event for the child (always first), followed
+ a vfork event for the parent and an exec event for the child.
+ The latter two can come in either order.
+
+ If we get the parent vfork event first, life's good: We follow
+ either the parent or child, and then the child's exec event is
+ a "don't care".
+
+ But if we get the child's exec event first, then we delay
+ responding to it until we handle the parent's vfork. Because,
+ otherwise we can't satisfy a "catch vfork". */
+ if (pending_follow.kind == TARGET_WAITKIND_VFORKED)
+ {
+ pending_follow.fork_event.saw_child_exec = 1;
+
+ /* On some targets, the child must be resumed before
+ the parent vfork event is delivered. A single-step
+ suffices. */
+ if (RESUME_EXECD_VFORKING_CHILD_TO_GET_PARENT_VFORK ())
+ target_resume (pid, 1, TARGET_SIGNAL_0);
+ /* We expect the parent vfork event to be available now. */
+ continue;
+ }
+
+ /* This causes the eventpoints and symbol table to be reset. Must
+ do this now, before trying to determine whether to stop. */
+ follow_exec (inferior_pid, pending_follow.execd_pathname);
+ free (pending_follow.execd_pathname);
+
+ stop_pc = read_pc_pid (pid);
+ saved_inferior_pid = inferior_pid;
+ inferior_pid = pid;
+ stop_bpstat = bpstat_stop_status
+ (&stop_pc,
+#if DECR_PC_AFTER_BREAK
+ (prev_pc != stop_pc - DECR_PC_AFTER_BREAK
+ && CURRENTLY_STEPPING ())
+#else /* DECR_PC_AFTER_BREAK zero */
+ 0
+#endif /* DECR_PC_AFTER_BREAK zero */
+ );
+ random_signal = !bpstat_explains_signal (stop_bpstat);
+ inferior_pid = saved_inferior_pid;
+ goto process_event_stop_test;
+
+ /* These syscall events are returned on HP-UX, as part of its
+ implementation of page-protection-based "hardware" watchpoints.
+ HP-UX has unfortunate interactions between page-protections and
+ some system calls. Our solution is to disable hardware watches
+ when a system call is entered, and reenable them when the syscall
+ completes. The downside of this is that we may miss the precise
+ point at which a watched piece of memory is modified. "Oh well."
+
+ Note that we may have multiple threads running, which may each
+ enter syscalls at roughly the same time. Since we don't have a
+ good notion currently of whether a watched piece of memory is
+ thread-private, we'd best not have any page-protections active
+ when any thread is in a syscall. Thus, we only want to reenable
+ hardware watches when no threads are in a syscall.
+
+ Also, be careful not to try to gather much state about a thread
+ that's in a syscall. It's frequently a losing proposition. */
+ case TARGET_WAITKIND_SYSCALL_ENTRY:
+ number_of_threads_in_syscalls++;
+ if (number_of_threads_in_syscalls == 1)
+ {
+ TARGET_DISABLE_HW_WATCHPOINTS (inferior_pid);
+ }
+ resume (0, TARGET_SIGNAL_0);
+ continue;
+
+ /* Before examining the threads further, step this thread to
+ get it entirely out of the syscall. (We get notice of the
+ event when the thread is just on the verge of exiting a
+ syscall. Stepping one instruction seems to get it back
+ into user code.)
+
+ Note that although the logical place to reenable h/w watches
+ is here, we cannot. We cannot reenable them before stepping
+ the thread (this causes the next wait on the thread to hang).
+
+ Nor can we enable them after stepping until we've done a wait.
+ Thus, we simply set the flag enable_hw_watchpoints_after_wait
+ here, which will be serviced immediately after the target
+ is waited on. */
+ case TARGET_WAITKIND_SYSCALL_RETURN:
+ target_resume (pid, 1, TARGET_SIGNAL_0);
+
+ if (number_of_threads_in_syscalls > 0)
+ {
+ number_of_threads_in_syscalls--;
+ enable_hw_watchpoints_after_wait =
+ (number_of_threads_in_syscalls == 0);
+ }
+ continue;
+
+ case TARGET_WAITKIND_STOPPED:
+ stop_signal = w.value.sig;
+ break;
+ }
+
+ /* We may want to consider not doing a resume here in order to give
+ the user a chance to play with the new thread. It might be good
+ to make that a user-settable option. */
+
+ /* At this point, all threads are stopped (happens automatically in
+ either the OS or the native code). Therefore we need to continue
+ all threads in order to make progress. */
+ if (new_thread_event)
+ {
+ target_resume (-1, 0, TARGET_SIGNAL_0);
+ continue;
+ }
+
+ stop_pc = read_pc_pid (pid);
+
+ /* See if a thread hit a thread-specific breakpoint that was meant for
+ another thread. If so, then step that thread past the breakpoint,
+ and continue it. */
+
+ if (stop_signal == TARGET_SIGNAL_TRAP)
+ {
+ if (SOFTWARE_SINGLE_STEP_P && singlestep_breakpoints_inserted_p)
+ random_signal = 0;
+ else if (breakpoints_inserted
+ && breakpoint_here_p (stop_pc - DECR_PC_AFTER_BREAK))
+ {
+ random_signal = 0;
+ if (!breakpoint_thread_match (stop_pc - DECR_PC_AFTER_BREAK,
+ pid))
+ {
+ int remove_status;
+
+ /* Saw a breakpoint, but it was hit by the wrong thread.
+ Just continue. */
+ write_pc_pid (stop_pc - DECR_PC_AFTER_BREAK, pid);
+
+ remove_status = remove_breakpoints ();
+ /* Did we fail to remove breakpoints? If so, try
+ to set the PC past the bp. (There's at least
+ one situation in which we can fail to remove
+ the bp's: On HP-UX's that use ttrace, we can't
+ change the address space of a vforking child
+ process until the child exits (well, okay, not
+ then either :-) or execs. */
+ if (remove_status != 0)
+ {
+ write_pc_pid (stop_pc - DECR_PC_AFTER_BREAK + 4, pid);
+ }
+ else
+ { /* Single step */
+ target_resume (pid, 1, TARGET_SIGNAL_0);
+ /* FIXME: What if a signal arrives instead of the
+ single-step happening? */
+
+ if (target_wait_hook)
+ target_wait_hook (pid, &w);
+ else
+ target_wait (pid, &w);
+ insert_breakpoints ();
+ }
+
+ /* We need to restart all the threads now. */
+ target_resume (-1, 0, TARGET_SIGNAL_0);
+ continue;
+ }
+ else
+ {
+ /* This breakpoint matches--either it is the right
+ thread or it's a generic breakpoint for all threads.
+ Remember that we'll need to step just _this_ thread
+ on any following user continuation! */
+ thread_step_needed = 1;
+ }
+ }
+ }
+ else
+ random_signal = 1;
+
+ /* See if something interesting happened to the non-current thread. If
+ so, then switch to that thread, and eventually give control back to
+ the user.
+
+ Note that if there's any kind of pending follow (i.e., of a fork,
+ vfork or exec), we don't want to do this now. Rather, we'll let
+ the next resume handle it. */
+ if ((pid != inferior_pid) &&
+ (pending_follow.kind == TARGET_WAITKIND_SPURIOUS))
+ {
+ int printed = 0;
+
+ /* If it's a random signal for a non-current thread, notify user
+ if he's expressed an interest. */
+ if (random_signal
+ && signal_print[stop_signal])
+ {
+/* ??rehrauer: I don't understand the rationale for this code. If the
+ inferior will stop as a result of this signal, then the act of handling
+ the stop ought to print a message that's couches the stoppage in user
+ terms, e.g., "Stopped for breakpoint/watchpoint". If the inferior
+ won't stop as a result of the signal -- i.e., if the signal is merely
+ a side-effect of something GDB's doing "under the covers" for the
+ user, such as stepping threads over a breakpoint they shouldn't stop
+ for -- then the message seems to be a serious annoyance at best.
+
+ For now, remove the message altogether. */
+#if 0
+ printed = 1;
+ target_terminal_ours_for_output ();
+ printf_filtered ("\nProgram received signal %s, %s.\n",
+ target_signal_to_name (stop_signal),
+ target_signal_to_string (stop_signal));
+ gdb_flush (gdb_stdout);
+#endif
+ }
+
+ /* If it's not SIGTRAP and not a signal we want to stop for, then
+ continue the thread. */
+
+ if (stop_signal != TARGET_SIGNAL_TRAP
+ && !signal_stop[stop_signal])
+ {
+ if (printed)
+ target_terminal_inferior ();
+
+ /* Clear the signal if it should not be passed. */
+ if (signal_program[stop_signal] == 0)
+ stop_signal = TARGET_SIGNAL_0;
+
+ target_resume (pid, 0, stop_signal);
+ continue;
+ }
+
+ /* It's a SIGTRAP or a signal we're interested in. Switch threads,
+ and fall into the rest of wait_for_inferior(). */
+
+ /* Save infrun state for the old thread. */
+ save_infrun_state (inferior_pid, prev_pc,
+ prev_func_start, prev_func_name,
+ trap_expected, step_resume_breakpoint,
+ through_sigtramp_breakpoint,
+ step_range_start, step_range_end,
+ step_frame_address, handling_longjmp,
+ another_trap,
+ stepping_through_solib_after_catch,
+ stepping_through_solib_catchpoints,
+ stepping_through_sigtramp);
+
+#ifdef HPUXHPPA
+ switched_from_inferior_pid = inferior_pid;
+#endif
+
+ inferior_pid = pid;
+
+ /* Load infrun state for the new thread. */
+ load_infrun_state (inferior_pid, &prev_pc,
+ &prev_func_start, &prev_func_name,
+ &trap_expected, &step_resume_breakpoint,
+ &through_sigtramp_breakpoint,
+ &step_range_start, &step_range_end,
+ &step_frame_address, &handling_longjmp,
+ &another_trap,
+ &stepping_through_solib_after_catch,
+ &stepping_through_solib_catchpoints,
+ &stepping_through_sigtramp);
+
+ if (context_hook)
+ context_hook (pid_to_thread_id (pid));
+
+ printf_filtered ("[Switching to %s]\n", target_pid_to_str (pid));
+ flush_cached_frames ();
+ }
+
+ if (SOFTWARE_SINGLE_STEP_P && singlestep_breakpoints_inserted_p)
+ {
+ /* Pull the single step breakpoints out of the target. */
+ SOFTWARE_SINGLE_STEP (0, 0);
+ singlestep_breakpoints_inserted_p = 0;
+ }
+
+ /* 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 0 /* XXX DEBUG */
+ printf ("infrun.c:1607: pc = 0x%x\n", read_pc ());
+#endif
+ /* if (INSTRUCTION_NULLIFIED && CURRENTLY_STEPPING ()) */
+ if (INSTRUCTION_NULLIFIED)
+ {
+ struct target_waitstatus tmpstatus;
+#if 0
+ all_registers_info ((char *) 0, 0);
+#endif
+ registers_changed ();
+ target_resume (pid, 1, TARGET_SIGNAL_0);
+
+ /* We may have received a signal that we want to pass to
+ the inferior; therefore, we must not clobber the waitstatus
+ in W. So we call wait ourselves, then continue the loop
+ at the "have_waited" label. */
+ if (target_wait_hook)
+ target_wait_hook (pid, &tmpstatus);
+ else
+ target_wait (pid, &tmpstatus);
+
+ goto have_waited;
+ }
+
+#ifdef HAVE_STEPPABLE_WATCHPOINT
+ /* It may not be necessary to disable the watchpoint to stop over
+ it. For example, the PA can (with some kernel cooperation)
+ single step over a watchpoint without disabling the watchpoint. */
+ if (STOPPED_BY_WATCHPOINT (w))
+ {
+ resume (1, 0);
+ continue;
+ }
+#endif
+
+#ifdef HAVE_NONSTEPPABLE_WATCHPOINT
+ /* It is far more common to need to disable a watchpoint
+ to step the inferior over it. FIXME. What else might
+ a debug register or page protection watchpoint scheme need
+ here? */
+ if (STOPPED_BY_WATCHPOINT (w))
+ {
+/* At this point, we are stopped at an instruction which has attempted to write
+ to a piece of memory under control of a watchpoint. The instruction hasn't
+ actually executed yet. If we were to evaluate the watchpoint expression
+ now, we would get the old value, and therefore no change would seem to have
+ occurred.
+
+ In order to make watchpoints work `right', we really need to complete the
+ memory write, and then evaluate the watchpoint expression. The following
+ code does that by removing the watchpoint (actually, all watchpoints and
+ breakpoints), single-stepping the target, re-inserting watchpoints, and then
+ falling through to let normal single-step processing handle proceed. Since
+ this includes evaluating watchpoints, things will come to a stop in the
+ correct manner. */
+
+ write_pc (stop_pc - DECR_PC_AFTER_BREAK);
+
+ remove_breakpoints ();
+ registers_changed ();
+ target_resume (pid, 1, TARGET_SIGNAL_0); /* Single step */
+
+ if (target_wait_hook)
+ target_wait_hook (pid, &w);
+ else
+ target_wait (pid, &w);
+ insert_breakpoints ();
+
+ /* FIXME-maybe: is this cleaner than setting a flag? Does it
+ handle things like signals arriving and other things happening
+ in combination correctly? */
+ stepped_after_stopped_by_watchpoint = 1;
+ goto have_waited;
+ }
+#endif
+
+#ifdef HAVE_CONTINUABLE_WATCHPOINT
+ /* It may be possible to simply continue after a watchpoint. */
+ STOPPED_BY_WATCHPOINT (w);
+#endif
+
+ stop_func_start = 0;
+ stop_func_end = 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,
+ &stop_func_end);
+ 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 == TARGET_SIGNAL_TRAP
+ || (breakpoints_inserted &&
+ (stop_signal == TARGET_SIGNAL_ILL
+ || stop_signal == TARGET_SIGNAL_EMT
+ ))
+ || stop_soon_quietly)
+ {
+ if (stop_signal == TARGET_SIGNAL_TRAP && 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 through_sigtramp_breakpoint
+ will be set and we should check whether we've hit the
+ step breakpoint. */
+ if (stop_signal == TARGET_SIGNAL_TRAP && trap_expected
+ && through_sigtramp_breakpoint == NULL)
+ bpstat_clear (&stop_bpstat);
+ else
+ {
+ /* See if there is a breakpoint at the current PC. */
+ stop_bpstat = bpstat_stop_status
+ (&stop_pc,
+ (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
+ and 3) we didn't hit a breakpoint in a signal handler
+ without an intervening stop in sigtramp, which is
+ detected by a new stack pointer value below
+ any usual function calling stack adjustments. */
+ (CURRENTLY_STEPPING ()
+ && prev_pc != stop_pc - DECR_PC_AFTER_BREAK
+ && !(step_range_end
+ && INNER_THAN (read_sp (), (step_sp - 16)))) :
+ 0)
+ );
+ /* Following in case break condition called a
+ function. */
+ stop_print_frame = 1;
+ }
+
+ if (stop_signal == TARGET_SIGNAL_TRAP)
+ random_signal
+ = !(bpstat_explains_signal (stop_bpstat)
+ || trap_expected
+#ifndef CALL_DUMMY_BREAKPOINT_OFFSET
+ || PC_IN_CALL_DUMMY (stop_pc, read_sp (),
+ FRAME_FP (get_current_frame ()))
+#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, read_sp (),
+ FRAME_FP (get_current_frame ()))
+#endif /* No CALL_DUMMY_BREAKPOINT_OFFSET. */
+ );
+ if (!random_signal)
+ stop_signal = TARGET_SIGNAL_TRAP;
+ }
+ }
+
+ /* When we reach this point, we've pretty much decided
+ that the reason for stopping must've been a random
+ (unexpected) signal. */
+
+ else
+ random_signal = 1;
+ /* If a fork, vfork or exec event was seen, then there are two
+ possible responses we can make:
+
+ 1. If a catchpoint triggers for the event (random_signal == 0),
+ then we must stop now and issue a prompt. We will resume
+ the inferior when the user tells us to.
+ 2. If no catchpoint triggers for the event (random_signal == 1),
+ then we must resume the inferior now and keep checking.
+
+ In either case, we must take appropriate steps to "follow" the
+ the fork/vfork/exec when the inferior is resumed. For example,
+ if follow-fork-mode is "child", then we must detach from the
+ parent inferior and follow the new child inferior.
+
+ In either case, setting pending_follow causes the next resume()
+ to take the appropriate following action. */
+ process_event_stop_test:
+ if (w.kind == TARGET_WAITKIND_FORKED)
+ {
+ if (random_signal) /* I.e., no catchpoint triggered for this. */
+ {
+ trap_expected = 1;
+ stop_signal = TARGET_SIGNAL_0;
+ goto keep_going;
+ }
+ }
+ else if (w.kind == TARGET_WAITKIND_VFORKED)
+ {
+ if (random_signal) /* I.e., no catchpoint triggered for this. */
+ {
+ stop_signal = TARGET_SIGNAL_0;
+ goto keep_going;
+ }
+ }
+ else if (w.kind == TARGET_WAITKIND_EXECD)
+ {
+ pending_follow.kind = w.kind;
+ if (random_signal) /* I.e., no catchpoint triggered for this. */
+ {
+ trap_expected = 1;
+ stop_signal = TARGET_SIGNAL_0;
+ goto keep_going;
+ }
+ }
+
+ /* 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 (signal_print[stop_signal])
+ {
+ printed = 1;
+ target_terminal_ours_for_output ();
+ annotate_signal ();
+ printf_filtered ("\nProgram received signal ");
+ annotate_signal_name ();
+ printf_filtered ("%s", target_signal_to_name (stop_signal));
+ annotate_signal_name_end ();
+ printf_filtered (", ");
+ annotate_signal_string ();
+ printf_filtered ("%s", target_signal_to_string (stop_signal));
+ annotate_signal_string_end ();
+ printf_filtered (".\n");
+ gdb_flush (gdb_stdout);
+ }
+ if (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 = TARGET_SIGNAL_0;
+
+ /* If we're in the middle of a "next" command, let the code for
+ stepping over a function handle this. pai/1997-09-10
+
+ A previous comment here suggested it was possible to change
+ this to jump to keep_going in all cases. */
+
+ if (step_over_calls > 0)
+ goto step_over_function;
+ else
+ 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;
+ }
+ /* Not sure whether we need to blow this away too, but probably
+ it is like the step-resume breakpoint. */
+ if (through_sigtramp_breakpoint != NULL)
+ {
+ delete_breakpoint (through_sigtramp_breakpoint);
+ through_sigtramp_breakpoint = NULL;
+ }
+
+#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
+ && (INNER_THAN (FRAME_FP (get_current_frame ()),
+ 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)
+ {
+ thread_step_needed = 1;
+ 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 and
+ through_sigtramp_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 and
+ through_sigtramp_breakpoint via the cleanup chain, so
+ no need to worry about it here. */
+
+ goto stop_stepping;
+
+ case BPSTAT_WHAT_STEP_RESUME:
+ /* This proably demands a more elegant solution, but, yeah
+ right...
+
+ This function's use of the simple variable
+ step_resume_breakpoint doesn't seem to accomodate
+ simultaneously active step-resume bp's, although the
+ breakpoint list certainly can.
+
+ If we reach here and step_resume_breakpoint is already
+ NULL, then apparently we have multiple active
+ step-resume bp's. We'll just delete the breakpoint we
+ stopped at, and carry on. */
+ if (step_resume_breakpoint == NULL)
+ {
+ step_resume_breakpoint =
+ bpstat_find_step_resume_breakpoint (stop_bpstat);
+ }
+ delete_breakpoint (step_resume_breakpoint);
+ step_resume_breakpoint = NULL;
+ break;
+
+ case BPSTAT_WHAT_THROUGH_SIGTRAMP:
+ if (through_sigtramp_breakpoint)
+ delete_breakpoint (through_sigtramp_breakpoint);
+ through_sigtramp_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;
+ break;
+
+ case BPSTAT_WHAT_CHECK_SHLIBS:
+ case BPSTAT_WHAT_CHECK_SHLIBS_RESUME_FROM_HOOK:
+#ifdef SOLIB_ADD
+ {
+ extern int auto_solib_add;
+
+ /* Remove breakpoints, we eventually want to step over the
+ shlib event breakpoint, and SOLIB_ADD might adjust
+ breakpoint addresses via breakpoint_re_set. */
+ if (breakpoints_inserted)
+ remove_breakpoints ();
+ breakpoints_inserted = 0;
+
+ /* Check for any newly added shared libraries if we're
+ supposed to be adding them automatically. */
+ if (auto_solib_add)
+ {
+ /* Switch terminal for any messages produced by
+ breakpoint_re_set. */
+ target_terminal_ours_for_output ();
+ SOLIB_ADD (NULL, 0, NULL);
+ target_terminal_inferior ();
+ }
+
+ /* Try to reenable shared library breakpoints, additional
+ code segments in shared libraries might be mapped in now. */
+ re_enable_breakpoints_in_shlibs ();
+
+ /* If requested, stop when the dynamic linker notifies
+ gdb of events. This allows the user to get control
+ and place breakpoints in initializer routines for
+ dynamically loaded objects (among other things). */
+ if (stop_on_solib_events)
+ {
+ stop_print_frame = 0;
+ goto stop_stepping;
+ }
+
+ /* If we stopped due to an explicit catchpoint, then the
+ (see above) call to SOLIB_ADD pulled in any symbols
+ from a newly-loaded library, if appropriate.
+
+ We do want the inferior to stop, but not where it is
+ now, which is in the dynamic linker callback. Rather,
+ we would like it stop in the user's program, just after
+ the call that caused this catchpoint to trigger. That
+ gives the user a more useful vantage from which to
+ examine their program's state. */
+ else if (what.main_action == BPSTAT_WHAT_CHECK_SHLIBS_RESUME_FROM_HOOK)
+ {
+ /* ??rehrauer: If I could figure out how to get the
+ right return PC from here, we could just set a temp
+ breakpoint and resume. I'm not sure we can without
+ cracking open the dld's shared libraries and sniffing
+ their unwind tables and text/data ranges, and that's
+ not a terribly portable notion.
+
+ Until that time, we must step the inferior out of the
+ dld callback, and also out of the dld itself (and any
+ code or stubs in libdld.sl, such as "shl_load" and
+ friends) until we reach non-dld code. At that point,
+ we can stop stepping. */
+ bpstat_get_triggered_catchpoints (stop_bpstat,
+ &stepping_through_solib_catchpoints);
+ stepping_through_solib_after_catch = 1;
+
+ /* Be sure to lift all breakpoints, so the inferior does
+ actually step past this point... */
+ another_trap = 1;
+ break;
+ }
+ else
+ {
+ /* We want to step over this breakpoint, then keep going. */
+ another_trap = 1;
+ break;
+ }
+ }
+#endif
+ break;
+
+ case BPSTAT_WHAT_LAST:
+ /* Not a real code, but listed here to shut up gcc -Wall. */
+
+ case BPSTAT_WHAT_KEEP_CHECKING:
+ break;
+ }
+ }
+
+ /* 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. */
+
+ /* Are we stepping to get the inferior out of the dynamic
+ linker's hook (and possibly the dld itself) after catching
+ a shlib event? */
+ if (stepping_through_solib_after_catch)
+ {
+#if defined(SOLIB_ADD)
+ /* Have we reached our destination? If not, keep going. */
+ if (SOLIB_IN_DYNAMIC_LINKER (pid, stop_pc))
+ {
+ another_trap = 1;
+ goto keep_going;
+ }
+#endif
+ /* Else, stop and report the catchpoint(s) whose triggering
+ caused us to begin stepping. */
+ stepping_through_solib_after_catch = 0;
+ bpstat_clear (&stop_bpstat);
+ stop_bpstat = bpstat_copy (stepping_through_solib_catchpoints);
+ bpstat_clear (&stepping_through_solib_catchpoints);
+ stop_print_frame = 1;
+ goto stop_stepping;
+ }
+
+#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 (CALL_DUMMY_HAS_COMPLETED (stop_pc, read_sp (),
+ FRAME_FP (get_current_frame ()))
+ && !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'm not sure whether this needs to be check_sigtramp2 or
+ whether it could/should be keep_going. */
+ 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.
+
+ Note that step_range_end is the address of the first instruction
+ beyond the step range, and NOT the address of the last instruction
+ within it! */
+ if (stop_pc >= step_range_start
+ && stop_pc < step_range_end
+#if 0
+/* I haven't a clue what might trigger this clause, and it seems wrong
+ anyway, so I've disabled it until someone complains. -Stu 10/24/95 */
+
+ /* 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
+ && FRAME_FP (get_current_frame ())
+ && (INNER_THAN (read_sp (), step_sp)
+ || FRAME_FP (get_current_frame ()) != step_frame_address))
+#endif
+ )
+ {
+ /* 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. */
+
+ /* If we are stepping at the source level and entered the runtime
+ loader dynamic symbol resolution code, we keep on single stepping
+ until we exit the run time loader code and reach the callee's
+ address. */
+ if (step_over_calls < 0 && IN_SOLIB_DYNSYM_RESOLVE_CODE (stop_pc))
+ goto keep_going;
+
+ /* We can't update step_sp every time through the loop, because
+ reading the stack pointer would slow down stepping too much.
+ But we can update it every time we leave the step range. */
+ update_step_sp = 1;
+
+ /* Did we just take a signal? */
+ if (IN_SIGTRAMP (stop_pc, stop_func_name)
+ && !IN_SIGTRAMP (prev_pc, prev_func_name)
+ && INNER_THAN (read_sp (), step_sp))
+ {
+ /* We've just taken a signal; go until we are back to
+ the point where we took it and one more. */
+
+ /* Note: The test above succeeds not only when we stepped
+ into a signal handler, but also when we step past the last
+ statement of a signal handler and end up in the return stub
+ of the signal handler trampoline. To distinguish between
+ these two cases, check that the frame is INNER_THAN the
+ previous one below. pai/1997-09-11 */
+
+
+ {
+ CORE_ADDR current_frame = FRAME_FP (get_current_frame ());
+
+ if (INNER_THAN (current_frame, step_frame_address))
+ {
+ /* We have just taken a signal; go until we are back to
+ the point where we took it and one more. */
+
+ /* This code is needed at least in the following case:
+ The user types "next" and then a signal arrives (before
+ the "next" is done). */
+
+ /* Note that if we are stopped at a breakpoint, then we need
+ the step_resume breakpoint to override any breakpoints at
+ the same location, so that we will still step over the
+ breakpoint even though the signal happened. */
+ struct symtab_and_line sr_sal;
+
+ INIT_SAL (&sr_sal);
+ sr_sal.symtab = NULL;
+ sr_sal.line = 0;
+ sr_sal.pc = prev_pc;
+ /* We could probably be setting the frame to
+ step_frame_address; I don't think anyone thought to
+ try it. */
+ step_resume_breakpoint =
+ set_momentary_breakpoint (sr_sal, NULL, bp_step_resume);
+ if (breakpoints_inserted)
+ insert_breakpoints ();
+ }
+ else
+ {
+ /* We just stepped out of a signal handler and into
+ its calling trampoline.
+
+ Normally, we'd jump to step_over_function from
+ here, but for some reason GDB can't unwind the
+ stack correctly to find the real PC for the point
+ user code where the signal trampoline will return
+ -- FRAME_SAVED_PC fails, at least on HP-UX 10.20.
+ But signal trampolines are pretty small stubs of
+ code, anyway, so it's OK instead to just
+ single-step out. Note: assuming such trampolines
+ don't exhibit recursion on any platform... */
+ find_pc_partial_function (stop_pc, &stop_func_name,
+ &stop_func_start,
+ &stop_func_end);
+ /* Readjust stepping range */
+ step_range_start = stop_func_start;
+ step_range_end = stop_func_end;
+ stepping_through_sigtramp = 1;
+ }
+ }
+
+
+ /* 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 0
+ /* I disabled this test because it was too complicated and slow.
+ The SKIP_PROLOGUE was especially slow, because it caused
+ unnecessary prologue examination on various architectures.
+ The code in the #else clause has been tested on the Sparc,
+ Mips, PA, and Power architectures, so it's pretty likely to
+ be correct. -Stu 10/24/95 */
+
+ /* See if we left the step range due to a subroutine call that
+ we should proceed to the end of. */
+
+ if (stop_func_start)
+ {
+ struct symtab *s;
+
+ /* Do this after the IN_SIGTRAMP check; it might give
+ an error. */
+ prologue_pc = stop_func_start;
+
+ /* Don't skip the prologue if this is assembly source */
+ s = find_pc_symtab (stop_pc);
+ if (s && s->language != language_asm)
+ SKIP_PROLOGUE (prologue_pc);
+ }
+
+ if (!(INNER_THAN (step_sp, read_sp ())) /* don't mistake (sig)return
+ as a call */
+ && ( /* 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
+ || read_sp () != step_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
+
+ /* ...except on the Alpha with -O (and also Irix 5 and
+ perhaps others), 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
+
+ /* ...and if it is a leaf function, the prologue might
+ consist of gp loading only, so the call transfers to
+ the first instruction after the prologue. */
+ || (stop_pc == prologue_pc
+
+ /* Distinguish this from the case where we jump back
+ to the first instruction after the prologue,
+ within a function. */
+ && stop_func_start != prev_func_start)
+
+ /* 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_CALL_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. */
+ ))
+#else
+ /* This test is a much more streamlined, (but hopefully correct)
+ replacement for the code above. It's been tested on the Sparc,
+ Mips, PA, and Power architectures with good results. */
+
+ if (stop_pc == stop_func_start /* Quick test */
+ || (in_prologue (stop_pc, stop_func_start) &&
+ !IN_SOLIB_RETURN_TRAMPOLINE (stop_pc, stop_func_name))
+ || IN_SOLIB_CALL_TRAMPOLINE (stop_pc, stop_func_name)
+ || stop_func_name == 0)
+#endif
+
+ {
+ /* 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 || IGNORE_HELPER_CALL (stop_pc))
+ /* 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;
+ else
+ {
+ tmp = DYNAMIC_TRAMPOLINE_NEXTPC (stop_pc);
+ if (tmp)
+ {
+ struct symtab_and_line xxx;
+ /* Why isn't this s_a_l called "sr_sal", like all of the
+ other s_a_l's where this code is duplicated? */
+ INIT_SAL (&xxx); /* initialize to zeroes */
+ xxx.pc = tmp;
+ xxx.section = find_pc_overlay (xxx.pc);
+ step_resume_breakpoint =
+ set_momentary_breakpoint (xxx, NULL, bp_step_resume);
+ insert_breakpoints ();
+ goto keep_going;
+ }
+ }
+
+ /* 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;
+
+ INIT_SAL (&sr_sal);
+ sr_sal.symtab = NULL;
+ sr_sal.line = 0;
+
+ /* If we came here after encountering a signal in the middle of
+ a "next", use the stashed-away previous frame pc */
+ sr_sal.pc
+ = stopped_by_random_signal
+ ? prev_pc
+ : ADDR_BITS_REMOVE (SAVED_PC_AFTER_CALL (get_current_frame ()));
+
+ step_resume_breakpoint =
+ set_momentary_breakpoint (sr_sal,
+ stopped_by_random_signal ?
+ NULL : get_current_frame (),
+ bp_step_resume);
+
+ /* We've just entered a callee, and we wish to resume until
+ it returns to the caller. Setting a step_resume bp on
+ the return PC will catch a return from the callee.
+
+ However, if the callee is recursing, we want to be
+ careful not to catch returns of those recursive calls,
+ but of THIS instance of the call.
+
+ To do this, we set the step_resume bp's frame to our
+ current caller's frame (step_frame_address, which is
+ set by the "next" or "until" command, before execution
+ begins).
+
+ But ... don't do it if we're single-stepping out of a
+ sigtramp, because the reason we're single-stepping is
+ precisely because unwinding is a problem (HP-UX 10.20,
+ e.g.) and the frame address is likely to be incorrect.
+ No danger of sigtramp recursion. */
+
+ if (stepping_through_sigtramp)
+ {
+ step_resume_breakpoint->frame = (CORE_ADDR) NULL;
+ stepping_through_sigtramp = 0;
+ }
+ else if (!IN_SOLIB_DYNSYM_RESOLVE_CODE (sr_sal.pc))
+ step_resume_breakpoint->frame = step_frame_address;
+
+ 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. */
+ {
+ struct symtab *s;
+
+ s = find_pc_symtab (stop_pc);
+ if (s && s->language != language_asm)
+ 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 (if it is still
+ within the function). 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 && sal.end < stop_func_end)
+ 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;
+
+ INIT_SAL (&sr_sal); /* initialize to zeroes */
+ sr_sal.pc = stop_func_start;
+ sr_sal.section = find_pc_overlay (stop_func_start);
+ /* 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. */
+
+ 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 we're in the return path from a shared library trampoline,
+ we want to proceed through the trampoline when stepping. */
+ if (IN_SOLIB_RETURN_TRAMPOLINE (stop_pc, stop_func_name))
+ {
+ CORE_ADDR tmp;
+
+ /* Determine where this trampoline returns. */
+ tmp = SKIP_TRAMPOLINE_CODE (stop_pc);
+
+ /* Only proceed through if we know where it's going. */
+ if (tmp)
+ {
+ /* And put the step-breakpoint there and go until there. */
+ struct symtab_and_line sr_sal;
+
+ INIT_SAL (&sr_sal); /* initialize to zeroes */
+ sr_sal.pc = tmp;
+ sr_sal.section = find_pc_overlay (sr_sal.pc);
+ /* 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 ();
+
+ /* Restart without fiddling with the step ranges or
+ other state. */
+ goto keep_going;
+ }
+ }
+
+ 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 || current_symtab != sal.symtab))
+ {
+ /* 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.) */
+
+ if (stop_func_end && sal.end >= stop_func_end)
+ {
+ /* If this is the last line of the function, don't keep stepping
+ (it would probably step us out of the function).
+ This is particularly necessary for a one-line function,
+ in which after skipping the prologue we better stop even though
+ we will be in mid-line. */
+ stop_step = 1;
+ break;
+ }
+ step_range_start = sal.pc;
+ step_range_end = sal.end;
+ step_frame_address = FRAME_FP (get_current_frame ());
+ current_line = sal.line;
+ current_symtab = sal.symtab;
+
+ /* In the case where we just stepped out of a function into the middle
+ of a line of the caller, continue stepping, but step_frame_address
+ must be modified to current frame */
+ {
+ CORE_ADDR current_frame = FRAME_FP (get_current_frame ());
+ if (!(INNER_THAN (current_frame, step_frame_address)))
+ step_frame_address = current_frame;
+ }
+
+
+ goto keep_going;
+
+ check_sigtramp2:
+ if (trap_expected
+ && IN_SIGTRAMP (stop_pc, stop_func_name)
+ && !IN_SIGTRAMP (prev_pc, prev_func_name)
+ && INNER_THAN (read_sp (), step_sp))
+ {
+ /* 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;
+
+ INIT_SAL (&sr_sal); /* initialize to zeroes */
+ sr_sal.pc = prev_pc;
+ sr_sal.section = find_pc_overlay (sr_sal.pc);
+ /* We perhaps could set the frame if we kept track of what
+ the frame corresponding to prev_pc was. But we don't,
+ so don't. */
+ through_sigtramp_breakpoint =
+ set_momentary_breakpoint (sr_sal, NULL, bp_through_sigtramp);
+ 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. */
+
+ /* ??rehrauer: ttrace on HP-UX theoretically allows one to debug
+ a vforked child beetween its creation and subsequent exit or
+ call to exec(). However, I had big problems in this rather
+ creaky exec engine, getting that to work. The fundamental
+ problem is that I'm trying to debug two processes via an
+ engine that only understands a single process with possibly
+ multiple threads.
+
+ Hence, this spot is known to have problems when
+ target_can_follow_vfork_prior_to_exec returns 1. */
+
+ /* Save the pc before execution, to compare with pc after stop. */
+ prev_pc = read_pc (); /* Might have been DECR_AFTER_BREAK */
+ prev_func_start = stop_func_start; /* Ok, since if DECR_PC_AFTER
+ BREAK is defined, the
+ original pc would not have
+ been at the start of a
+ function. */
+ prev_func_name = stop_func_name;
+
+ if (update_step_sp)
+ step_sp = read_sp ();
+ update_step_sp = 0;
+
+ /* If we did not do break;, it means we should keep
+ running the inferior and not return to debugger. */
+
+ if (trap_expected && stop_signal != TARGET_SIGNAL_TRAP)
+ {
+ /* 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
+ && through_sigtramp_breakpoint == NULL
+ && remove_breakpoints_on_following_step)
+ {
+ remove_breakpoints_on_following_step = 0;
+ remove_breakpoints ();
+ breakpoints_inserted = 0;
+ }
+ else if (!breakpoints_inserted &&
+ (through_sigtramp_breakpoint != NULL || !another_trap))
+ {
+ breakpoints_failed = insert_breakpoints ();
+ if (breakpoints_failed)
+ break;
+ breakpoints_inserted = 1;
+ }
+
+ trap_expected = another_trap;
+
+ /* Do not deliver SIGNAL_TRAP (except when the user
+ explicitly specifies that such a signal should be
+ delivered to the target program).
+
+ Typically, this would occure when a user is debugging a
+ target monitor on a simulator: the target monitor sets a
+ breakpoint; the simulator encounters this break-point and
+ halts the simulation handing control to GDB; GDB, noteing
+ that the break-point isn't valid, returns control back to
+ the simulator; the simulator then delivers the hardware
+ equivalent of a SIGNAL_TRAP to the program being
+ debugged. */
+
+ if (stop_signal == TARGET_SIGNAL_TRAP
+ && !signal_program[stop_signal])
+ stop_signal = TARGET_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 != TARGET_SIGNAL_CHLD)
+ && !stopped_by_random_signal)
+ SHIFT_INST_REGS ();
+#endif /* SHIFT_INST_REGS */
+
+ resume (CURRENTLY_STEPPING (), stop_signal);
+ }
+ }
+
+stop_stepping:
+ if (target_has_execution)
+ {
+ /* Are we stopping for a vfork event? We only stop when we see
+ the child's event. However, we may not yet have seen the
+ parent's event. And, inferior_pid is still set to the parent's
+ pid, until we resume again and follow either the parent or child.
+
+ To ensure that we can really touch inferior_pid (aka, the
+ parent process) -- which calls to functions like read_pc
+ implicitly do -- wait on the parent if necessary. */
+ if ((pending_follow.kind == TARGET_WAITKIND_VFORKED)
+ && !pending_follow.fork_event.saw_parent_fork)
+ {
+ int parent_pid;
+
+ do
+ {
+ if (target_wait_hook)
+ parent_pid = target_wait_hook (-1, &w);
+ else
+ parent_pid = target_wait (-1, &w);
+ }
+ while (parent_pid != inferior_pid);
+ }
+
+
+ /* 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;
+ }
+ do_cleanups (old_cleanups);
+}
+
+/* This function returns TRUE if ep is an internal breakpoint
+ set to catch generic shared library (aka dynamically-linked
+ library) events. (This is *NOT* the same as a catchpoint for a
+ shlib event. The latter is something a user can set; this is
+ something gdb sets for its own use, and isn't ever shown to a
+ user.) */
+static int
+is_internal_shlib_eventpoint (ep)
+ struct breakpoint *ep;
+{
+ return
+ (ep->type == bp_shlib_event)
+ ;
+}
+
+/* This function returns TRUE if bs indicates that the inferior
+ stopped due to a shared library (aka dynamically-linked library)
+ event. */
+static int
+stopped_for_internal_shlib_event (bs)
+ bpstat bs;
+{
+ /* Note that multiple eventpoints may've caused the stop. Any
+ that are associated with shlib events will be accepted. */
+ for (; bs != NULL; bs = bs->next)
+ {
+ if ((bs->breakpoint_at != NULL)
+ && is_internal_shlib_eventpoint (bs->breakpoint_at))
+ return 1;
+ }
+
+ /* If we get here, then no candidate was found. */
+ return 0;
+}
+
+/* This function returns TRUE if bs indicates that the inferior
+ stopped due to a shared library (aka dynamically-linked library)
+ event caught by a catchpoint.
+
+ If TRUE, cp_p is set to point to the catchpoint.
+
+ Else, the value of cp_p is undefined. */
+static int
+stopped_for_shlib_catchpoint (bs, cp_p)
+ bpstat bs;
+ struct breakpoint **cp_p;
+{
+ /* Note that multiple eventpoints may've caused the stop. Any
+ that are associated with shlib events will be accepted. */
+ *cp_p = NULL;
+
+ for (; bs != NULL; bs = bs->next)
+ {
+ if ((bs->breakpoint_at != NULL)
+ && ep_is_shlib_catchpoint (bs->breakpoint_at))
+ {
+ *cp_p = bs->breakpoint_at;
+ return 1;
+ }
+ }
+
+ /* If we get here, then no candidate was found. */
+ return 0;
+}
+
+
+/* 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 ()
+{
+
+#ifdef HPUXHPPA
+ /* As with the notification of thread events, we want to delay
+ notifying the user that we've switched thread context until
+ the inferior actually stops.
+
+ (Note that there's no point in saying anything if the inferior
+ has exited!) */
+ if ((switched_from_inferior_pid != inferior_pid) &&
+ target_has_execution)
+ {
+ target_terminal_ours_for_output ();
+ printf_filtered ("[Switched to %s]\n",
+ target_pid_or_tid_to_str (inferior_pid));
+ switched_from_inferior_pid = inferior_pid;
+ }
+#endif
+
+ /* 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 ");
+ printf_filtered ("program is no longer writable.\n");
+ printf_filtered ("It might be running in another process.\n");
+ printf_filtered ("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 ();
+
+ /* Don't print a message if in the middle of doing a "step n"
+ operation for n > 1 */
+ if (step_multi && stop_step)
+ goto done;
+
+ target_terminal_ours ();
+
+ /* Did we stop because the user set the stop_on_solib_events
+ variable? (If so, we report this as a generic, "Stopped due
+ to shlib event" message.) */
+ if (stopped_for_internal_shlib_event (stop_bpstat))
+ {
+ printf_filtered ("Stopped due to shared library event\n");
+ }
+
+ /* Look up the hook_stop and run it if it exists. */
+
+ if (stop_command && stop_command->hook)
+ {
+ catch_errors (hook_stop_stub, stop_command->hook,
+ "Error while running hook_stop:\n", RETURN_MASK_ALL);
+ }
+
+ if (!target_has_stack)
+ {
+
+ goto done;
+ }
+
+ /* Select innermost stack frame - i.e., current frame is frame 0,
+ and current location is based on that.
+ Don't do this on return from a stack dummy routine,
+ or if the program has exited. */
+
+ if (!stop_stack_dummy)
+ {
+ select_frame (get_current_frame (), 0);
+
+ /* Print current location without a level number, if
+ we have changed functions or hit a breakpoint.
+ Print source line if we have one.
+ bpstat_print() contains the logic deciding in detail
+ what to print, based on the event(s) that just occurred. */
+
+ if (stop_print_frame)
+ {
+ int bpstat_ret;
+ int source_flag;
+
+ bpstat_ret = bpstat_print (stop_bpstat);
+ /* bpstat_print() returned one of:
+ -1: Didn't print anything
+ 0: Printed preliminary "Breakpoint n, " message, desires
+ location tacked on
+ 1: Printed something, don't tack on location */
+
+ if (bpstat_ret == -1)
+ if (stop_step
+ && step_frame_address == FRAME_FP (get_current_frame ())
+ && step_start_function == find_pc_function (stop_pc))
+ source_flag = -1; /* finished step, just print source line */
+ else
+ source_flag = 1; /* print location and source line */
+ else if (bpstat_ret == 0) /* hit bpt, desire location */
+ source_flag = 1; /* print location and source line */
+ else /* bpstat_ret == 1, hit bpt, do not desire location */
+ source_flag = -1; /* just print source line */
+
+ /* The behavior of this routine with respect to the source
+ flag is:
+ -1: Print only source line
+ 0: Print only location
+ 1: Print location and source line */
+ show_and_print_stack_frame (selected_frame, -1, source_flag);
+
+ /* 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;
+ /* Set stop_pc to what it was before we called the function.
+ Can't rely on restore_inferior_status because that only gets
+ called if we don't stop in the called function. */
+ stop_pc = read_pc ();
+ select_frame (get_current_frame (), 0);
+ }
+
+
+ TUIDO (((TuiOpaqueFuncPtr) tui_vCheckDataValues, selected_frame));
+
+done:
+ annotate_stopped ();
+}
+
+static int
+hook_stop_stub (cmd)
+ PTR cmd;
+{
+ execute_user_command ((struct cmd_list_element *) cmd, 0);
+ return (0);
+}
+
+int
+signal_stop_state (signo)
+ int signo;
+{
+ return signal_stop[signo];
+}
+
+int
+signal_print_state (signo)
+ int signo;
+{
+ return signal_print[signo];
+}
+
+int
+signal_pass_state (signo)
+ int signo;
+{
+ return signal_program[signo];
+}
+
+static void
+sig_print_header ()
+{
+ printf_filtered ("\
+Signal Stop\tPrint\tPass to program\tDescription\n");
+}
+
+static void
+sig_print_info (oursig)
+ enum target_signal oursig;
+{
+ char *name = target_signal_to_name (oursig);
+ int name_padding = 13 - strlen (name);
+ if (name_padding <= 0)
+ name_padding = 0;
+
+ printf_filtered ("%s", name);
+ printf_filtered ("%*.*s ", name_padding, name_padding,
+ " ");
+ printf_filtered ("%s\t", signal_stop[oursig] ? "Yes" : "No");
+ printf_filtered ("%s\t", signal_print[oursig] ? "Yes" : "No");
+ printf_filtered ("%s\t\t", signal_program[oursig] ? "Yes" : "No");
+ printf_filtered ("%s\n", target_signal_to_string (oursig));
+}
+
+/* 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;
+ enum target_signal oursig;
+ 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 = (int) TARGET_SIGNAL_LAST;
+ 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 ((make_cleanup_func) freeargv, (char *) argv);
+
+ /* Walk through the args, looking for signal oursigs, 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)
+ {
+ /* It is numeric. The numeric signal refers to our own
+ internal signal numbering from target.h, not to host/target
+ signal number. This is a feature; users really should be
+ using symbolic names anyway, and the common ones like
+ SIGHUP, SIGINT, SIGALRM, etc. will work right anyway. */
+
+ sigfirst = siglast = (int)
+ target_signal_from_command (atoi (*argv));
+ if ((*argv)[digits] == '-')
+ {
+ siglast = (int)
+ target_signal_from_command (atoi ((*argv) + digits + 1));
+ }
+ if (sigfirst > siglast)
+ {
+ /* Bet he didn't figure we'd think of this case... */
+ signum = sigfirst;
+ sigfirst = siglast;
+ siglast = signum;
+ }
+ }
+ else
+ {
+ oursig = target_signal_from_name (*argv);
+ if (oursig != TARGET_SIGNAL_UNKNOWN)
+ {
+ sigfirst = siglast = (int) oursig;
+ }
+ 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 ((enum target_signal) signum)
+ {
+ case TARGET_SIGNAL_TRAP:
+ case TARGET_SIGNAL_INT:
+ if (!allsigs && !sigs[signum])
+ {
+ if (query ("%s is used by the debugger.\n\
+Are you sure you want to change it? ",
+ target_signal_to_name
+ ((enum target_signal) signum)))
+ {
+ sigs[signum] = 1;
+ }
+ else
+ {
+ printf_unfiltered ("Not confirmed, unchanged.\n");
+ gdb_flush (gdb_stdout);
+ }
+ }
+ break;
+ case TARGET_SIGNAL_0:
+ case TARGET_SIGNAL_DEFAULT:
+ case TARGET_SIGNAL_UNKNOWN:
+ /* Make sure that "all" doesn't print these. */
+ 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);
+}
+
+static void
+xdb_handle_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ char **argv;
+ struct cleanup *old_chain;
+
+ /* Break the command line up into args. */
+
+ argv = buildargv (args);
+ if (argv == NULL)
+ {
+ nomem (0);
+ }
+ old_chain = make_cleanup ((make_cleanup_func) freeargv, (char *) argv);
+ if (argv[1] != (char *) NULL)
+ {
+ char *argBuf;
+ int bufLen;
+
+ bufLen = strlen (argv[0]) + 20;
+ argBuf = (char *) xmalloc (bufLen);
+ if (argBuf)
+ {
+ int validFlag = 1;
+ enum target_signal oursig;
+
+ oursig = target_signal_from_name (argv[0]);
+ memset (argBuf, 0, bufLen);
+ if (strcmp (argv[1], "Q") == 0)
+ sprintf (argBuf, "%s %s", argv[0], "noprint");
+ else
+ {
+ if (strcmp (argv[1], "s") == 0)
+ {
+ if (!signal_stop[oursig])
+ sprintf (argBuf, "%s %s", argv[0], "stop");
+ else
+ sprintf (argBuf, "%s %s", argv[0], "nostop");
+ }
+ else if (strcmp (argv[1], "i") == 0)
+ {
+ if (!signal_program[oursig])
+ sprintf (argBuf, "%s %s", argv[0], "pass");
+ else
+ sprintf (argBuf, "%s %s", argv[0], "nopass");
+ }
+ else if (strcmp (argv[1], "r") == 0)
+ {
+ if (!signal_print[oursig])
+ sprintf (argBuf, "%s %s", argv[0], "print");
+ else
+ sprintf (argBuf, "%s %s", argv[0], "noprint");
+ }
+ else
+ validFlag = 0;
+ }
+ if (validFlag)
+ handle_command (argBuf, from_tty);
+ else
+ printf_filtered ("Invalid signal handling flag.\n");
+ if (argBuf)
+ free (argBuf);
+ }
+ }
+ do_cleanups (old_chain);
+}
+
+/* Print current contents of the tables set by the handle command.
+ It is possible we should just be printing signals actually used
+ by the current target (but for things to work right when switching
+ targets, all signals should be in the signal tables). */
+
+static void
+signals_info (signum_exp, from_tty)
+ char *signum_exp;
+ int from_tty;
+{
+ enum target_signal oursig;
+ sig_print_header ();
+
+ if (signum_exp)
+ {
+ /* First see if this is a symbol name. */
+ oursig = target_signal_from_name (signum_exp);
+ if (oursig == TARGET_SIGNAL_UNKNOWN)
+ {
+ /* No, try numeric. */
+ oursig =
+ target_signal_from_command (parse_and_eval_address (signum_exp));
+ }
+ sig_print_info (oursig);
+ return;
+ }
+
+ printf_filtered ("\n");
+ /* These ugly casts brought to you by the native VAX compiler. */
+ for (oursig = TARGET_SIGNAL_FIRST;
+ (int) oursig < (int) TARGET_SIGNAL_LAST;
+ oursig = (enum target_signal) ((int) oursig + 1))
+ {
+ QUIT;
+
+ if (oursig != TARGET_SIGNAL_UNKNOWN
+ && oursig != TARGET_SIGNAL_DEFAULT
+ && oursig != TARGET_SIGNAL_0)
+ sig_print_info (oursig);
+ }
+
+ 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_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
+{
+ CORE_ADDR frame_address;
+ int level;
+};
+
+static int restore_selected_frame PARAMS ((PTR));
+
+/* 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)
+ PTR args;
+{
+ struct restore_selected_frame_args *fr =
+ (struct restore_selected_frame_args *) args;
+ struct frame_info *frame;
+ int level = fr->level;
+
+ frame = find_relative_frame (get_current_frame (), &level);
+
+ /* If inf_status->selected_frame_address is NULL, there was no
+ previously selected frame. */
+ if (frame == NULL ||
+ /* FRAME_FP (frame) != fr->frame_address || */
+ /* elz: deleted this check as a quick fix to the problem that
+ for function called by hand gdb creates no internal frame
+ structure and the real stack and gdb's idea of stack are
+ different if nested calls by hands are made.
+
+ mvs: this worries me. */
+ level != 0)
+ {
+ warning ("Unable to restore previously selected frame.\n");
+ return 0;
+ }
+
+ select_frame (frame, 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_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
+set_follow_fork_mode_command (arg, from_tty, c)
+ char *arg;
+ int from_tty;
+ struct cmd_list_element *c;
+{
+ if (!STREQ (arg, "parent") &&
+ !STREQ (arg, "child") &&
+ !STREQ (arg, "both") &&
+ !STREQ (arg, "ask"))
+ error ("follow-fork-mode must be one of \"parent\", \"child\", \"both\" or \"ask\".");
+
+ if (follow_fork_mode_string != NULL)
+ free (follow_fork_mode_string);
+ follow_fork_mode_string = savestring (arg, strlen (arg));
+}
+
+
+
+void
+_initialize_infrun ()
+{
+ register int i;
+ register int numsigs;
+ struct cmd_list_element *c;
+
+ add_info ("signals", signals_info,
+ "What debugger does when program gets various signals.\n\
+Specify a signal as argument to print info on that signal only.");
+ add_info_alias ("handle", "signals", 0);
+
+ add_com ("handle", class_run, handle_command,
+ concat ("Specify how to handle a signal.\n\
+Args are signals and actions to apply to those signals.\n\
+Symbolic signals (e.g. SIGSEGV) are recommended but numeric signals\n\
+from 1-15 are allowed for compatibility with old versions of GDB.\n\
+Numeric ranges may be specified with the form LOW-HIGH (e.g. 1-5).\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.", NULL));
+ if (xdb_commands)
+ {
+ add_com ("lz", class_info, signals_info,
+ "What debugger does when program gets various signals.\n\
+Specify a signal as argument to print info on that signal only.");
+ add_com ("z", class_run, xdb_handle_command,
+ concat ("Specify how to handle a signal.\n\
+Args are signals and actions to apply to those signals.\n\
+Symbolic signals (e.g. SIGSEGV) are recommended but numeric signals\n\
+from 1-15 are allowed for compatibility with old versions of GDB.\n\
+Numeric ranges may be specified with the form LOW-HIGH (e.g. 1-5).\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 \"s\" (toggles between stop and nostop), \n\
+\"r\" (toggles between print and noprint), \"i\" (toggles between pass and \
+nopass), \"Q\" (noprint)\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.", NULL));
+ }
+
+ if (!dbx_commands)
+ 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 = (int) TARGET_SIGNAL_LAST;
+ 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[TARGET_SIGNAL_TRAP] = 0;
+ signal_program[TARGET_SIGNAL_INT] = 0;
+
+ /* Signals that are not errors should not normally enter the debugger. */
+ signal_stop[TARGET_SIGNAL_ALRM] = 0;
+ signal_print[TARGET_SIGNAL_ALRM] = 0;
+ signal_stop[TARGET_SIGNAL_VTALRM] = 0;
+ signal_print[TARGET_SIGNAL_VTALRM] = 0;
+ signal_stop[TARGET_SIGNAL_PROF] = 0;
+ signal_print[TARGET_SIGNAL_PROF] = 0;
+ signal_stop[TARGET_SIGNAL_CHLD] = 0;
+ signal_print[TARGET_SIGNAL_CHLD] = 0;
+ signal_stop[TARGET_SIGNAL_IO] = 0;
+ signal_print[TARGET_SIGNAL_IO] = 0;
+ signal_stop[TARGET_SIGNAL_POLL] = 0;
+ signal_print[TARGET_SIGNAL_POLL] = 0;
+ signal_stop[TARGET_SIGNAL_URG] = 0;
+ signal_print[TARGET_SIGNAL_URG] = 0;
+ signal_stop[TARGET_SIGNAL_WINCH] = 0;
+ signal_print[TARGET_SIGNAL_WINCH] = 0;
+
+#ifdef SOLIB_ADD
+ add_show_from_set
+ (add_set_cmd ("stop-on-solib-events", class_support, var_zinteger,
+ (char *) &stop_on_solib_events,
+ "Set stopping for shared library events.\n\
+If nonzero, gdb will give control to the user when the dynamic linker\n\
+notifies gdb of shared library events. The most common event of interest\n\
+to the user would be loading/unloading of a new library.\n",
+ &setlist),
+ &showlist);
+#endif
+
+ c = add_set_enum_cmd ("follow-fork-mode",
+ class_run,
+ follow_fork_mode_kind_names,
+ (char *) &follow_fork_mode_string,
+/* ??rehrauer: The "both" option is broken, by what may be a 10.20
+ kernel problem. It's also not terribly useful without a GUI to
+ help the user drive two debuggers. So for now, I'm disabling
+ the "both" option. */
+/* "Set debugger response to a program call of fork \
+or vfork.\n\
+A fork or vfork creates a new process. follow-fork-mode can be:\n\
+ parent - the original process is debugged after a fork\n\
+ child - the new process is debugged after a fork\n\
+ both - both the parent and child are debugged after a fork\n\
+ ask - the debugger will ask for one of the above choices\n\
+For \"both\", another copy of the debugger will be started to follow\n\
+the new child process. The original debugger will continue to follow\n\
+the original parent process. To distinguish their prompts, the\n\
+debugger copy's prompt will be changed.\n\
+For \"parent\" or \"child\", the unfollowed process will run free.\n\
+By default, the debugger will follow the parent process.",
+*/
+ "Set debugger response to a program call of fork \
+or vfork.\n\
+A fork or vfork creates a new process. follow-fork-mode can be:\n\
+ parent - the original process is debugged after a fork\n\
+ child - the new process is debugged after a fork\n\
+ ask - the debugger will ask for one of the above choices\n\
+For \"parent\" or \"child\", the unfollowed process will run free.\n\
+By default, the debugger will follow the parent process.",
+ &setlist);
+/* c->function.sfunc = ;*/
+ add_show_from_set (c, &showlist);
+
+ set_follow_fork_mode_command ("parent", 0, NULL);
+
+ c = add_set_enum_cmd ("scheduler-locking", class_run,
+ scheduler_enums, /* array of string names */
+ (char *) &scheduler_mode, /* current mode */
+ "Set mode for locking scheduler during execution.\n\
+off == no locking (threads may preempt at any time)\n\
+on == full locking (no thread except the current thread may run)\n\
+step == scheduler locked during every single-step operation.\n\
+ In this mode, no other thread may run during a step command.\n\
+ Other threads may run while stepping over a function call ('next').",
+ &setlist);
+
+ c->function.sfunc = set_schedlock_func; /* traps on target vector */
+ add_show_from_set (c, &showlist);
+}
diff --git a/gdb/inftarg.c b/gdb/inftarg.c
new file mode 100644
index 00000000000..af5cd3d6c0c
--- /dev/null
+++ b/gdb/inftarg.c
@@ -0,0 +1,968 @@
+/* Target-vector operations for controlling Unix child processes, for GDB.
+ Copyright 1990-1996, 1998, 1999 Free Software Foundation, Inc.
+ Contributed by Cygnus Support.
+
+## Contains temporary hacks..
+
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "frame.h" /* required by inferior.h */
+#include "inferior.h"
+#include "target.h"
+#include "gdbcore.h"
+#include "command.h"
+#include "gdb_stat.h"
+#include <signal.h>
+#include <sys/types.h>
+#include <fcntl.h>
+
+#ifdef HAVE_WAIT_H
+# include <wait.h>
+#else
+# ifdef HAVE_SYS_WAIT_H
+# include <sys/wait.h>
+# endif
+#endif
+
+/* "wait.h" fills in the gaps left by <wait.h> */
+#include "wait.h"
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+extern struct symtab_and_line *
+child_enable_exception_callback PARAMS ((enum exception_event_kind, int));
+
+extern struct exception_event_record *
+child_get_current_exception_event PARAMS ((void));
+
+extern void _initialize_inftarg PARAMS ((void));
+
+static void
+child_prepare_to_store PARAMS ((void));
+
+#ifndef CHILD_WAIT
+static int child_wait PARAMS ((int, struct target_waitstatus *));
+#endif /* CHILD_WAIT */
+
+#if !defined(CHILD_POST_WAIT)
+void
+child_post_wait PARAMS ((int, int));
+#endif
+
+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_detach_from_process PARAMS ((int, char *, int, int));
+
+static void
+child_attach PARAMS ((char *, int));
+
+static void
+child_attach_to_process PARAMS ((char *, int, int));
+
+#if !defined(CHILD_POST_ATTACH)
+extern void child_post_attach PARAMS ((int));
+#endif
+
+static void
+child_require_attach PARAMS ((char *, int));
+
+static void
+child_require_detach PARAMS ((int, 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));
+
+static void
+child_stop PARAMS ((void));
+
+#ifndef CHILD_THREAD_ALIVE
+int child_thread_alive PARAMS ((int));
+#endif
+
+static void init_child_ops PARAMS ((void));
+
+extern char **environ;
+
+struct target_ops child_ops;
+
+int child_suppress_run = 0; /* Non-zero if inftarg should pretend not to
+ be a runnable target. Used by targets
+ that can sit atop inftarg, such as HPUX
+ thread support. */
+
+#ifndef CHILD_WAIT
+
+/*##*/
+/* Enable HACK for ttrace work. In
+ * infttrace.c/require_notification_of_events,
+ * this is set to 0 so that the loop in child_wait
+ * won't loop.
+ */
+int not_same_real_pid = 1;
+/*##*/
+
+
+/* Wait for child to do something. Return pid of child, or -1 in case
+ of error; store status through argument pointer OURSTATUS. */
+
+static int
+child_wait (pid, ourstatus)
+ int pid;
+ struct target_waitstatus *ourstatus;
+{
+ int save_errno;
+ int status;
+ char * execd_pathname;
+ int exit_status;
+ int related_pid;
+ int syscall_id;
+ enum target_waitkind kind;
+
+ do {
+ set_sigint_trap(); /* Causes SIGINT to be passed on to the
+ attached process. */
+ set_sigio_trap ();
+
+ pid = ptrace_wait (inferior_pid, &status);
+
+ save_errno = errno;
+
+ clear_sigio_trap ();
+
+ clear_sigint_trap();
+
+ if (pid == -1)
+ {
+ if (save_errno == EINTR)
+ continue;
+
+ fprintf_unfiltered (gdb_stderr, "Child process unexpectedly missing: %s.\n",
+ safe_strerror (save_errno));
+
+ /* Claim it exited with unknown signal. */
+ ourstatus->kind = TARGET_WAITKIND_SIGNALLED;
+ ourstatus->value.sig = TARGET_SIGNAL_UNKNOWN;
+ return -1;
+ }
+
+ /* Did it exit?
+ */
+ if (target_has_exited (pid, status, &exit_status))
+ {
+ /* ??rehrauer: For now, ignore this. */
+ continue;
+ }
+
+ if (!target_thread_alive (pid))
+ {
+ ourstatus->kind = TARGET_WAITKIND_SPURIOUS;
+ return pid;
+ }
+
+ if (target_has_forked (pid, &related_pid)
+ && ((pid == inferior_pid) || (related_pid == inferior_pid)))
+ {
+ ourstatus->kind = TARGET_WAITKIND_FORKED;
+ ourstatus->value.related_pid = related_pid;
+ return pid;
+ }
+
+ if (target_has_vforked (pid, &related_pid)
+ && ((pid == inferior_pid) || (related_pid == inferior_pid)))
+ {
+ ourstatus->kind = TARGET_WAITKIND_VFORKED;
+ ourstatus->value.related_pid = related_pid;
+ return pid;
+ }
+
+ if (target_has_execd (pid, &execd_pathname))
+ {
+ /* Are we ignoring initial exec events? (This is likely because
+ we're in the process of starting up the inferior, and another
+ (older) mechanism handles those.) If so, we'll report this
+ as a regular stop, not an exec.
+ */
+ if (inferior_ignoring_startup_exec_events)
+ {
+ inferior_ignoring_startup_exec_events--;
+ }
+ else
+ {
+ ourstatus->kind = TARGET_WAITKIND_EXECD;
+ ourstatus->value.execd_pathname = execd_pathname;
+ return pid;
+ }
+ }
+
+ /* All we must do with these is communicate their occurrence
+ to wait_for_inferior...
+ */
+ if (target_has_syscall_event (pid, &kind, &syscall_id))
+ {
+ ourstatus->kind = kind;
+ ourstatus->value.syscall_id = syscall_id;
+ return pid;
+ }
+
+/*## } while (pid != inferior_pid); ##*/ /* Some other child died or stopped */
+/* hack for thread testing */
+ } while( (pid != inferior_pid) && not_same_real_pid );
+/*##*/
+
+ store_waitstatus (ourstatus, status);
+ return pid;
+}
+#endif /* CHILD_WAIT */
+
+#if !defined(CHILD_POST_WAIT)
+void
+child_post_wait (pid, wait_status)
+ int pid;
+ int wait_status;
+{
+ /* This version of Unix doesn't require a meaningful "post wait"
+ operation.
+ */
+}
+#endif
+
+
+#ifndef CHILD_THREAD_ALIVE
+
+/* Check to see if the given thread is alive.
+
+ FIXME: Is kill() ever the right way to do this? I doubt it, but
+ for now we're going to try and be compatable with the old thread
+ code. */
+int
+child_thread_alive (pid)
+ int pid;
+{
+ return (kill (pid, 0) != -1);
+}
+
+#endif
+
+static void
+child_attach_to_process (args, from_tty, after_fork)
+ char * args;
+ int from_tty;
+ int after_fork;
+{
+ if (!args)
+ error_no_arg ("process-id to attach");
+
+#ifndef ATTACH_DETACH
+ error ("Can't attach to a process on this machine.");
+#else
+ {
+ char *exec_file;
+ int pid;
+ char *dummy;
+
+ dummy = args;
+ pid = strtol (args, &dummy, 0);
+ /* Some targets don't set errno on errors, grrr! */
+ if ((pid == 0) && (args == dummy))
+ error ("Illegal process-id: %s\n", args);
+
+ if (pid == getpid()) /* Trying to masturbate? */
+ error ("I refuse to debug myself!");
+
+ if (from_tty)
+ {
+ exec_file = (char *) get_exec_file (0);
+
+ if (after_fork)
+ printf_unfiltered ("Attaching after fork to %s\n",
+ target_pid_to_str (pid));
+ else if (exec_file)
+ printf_unfiltered ("Attaching to program: %s, %s\n", exec_file,
+ target_pid_to_str (pid));
+ else
+ printf_unfiltered ("Attaching to %s\n", target_pid_to_str (pid));
+
+ gdb_flush (gdb_stdout);
+ }
+
+ if (!after_fork)
+ attach (pid);
+ else
+ REQUIRE_ATTACH (pid);
+
+ inferior_pid = pid;
+ push_target (&child_ops);
+ }
+#endif /* ATTACH_DETACH */
+}
+
+
+/* Attach to process PID, then initialize for debugging it. */
+
+static void
+child_attach (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ child_attach_to_process (args, from_tty, 0);
+}
+
+#if !defined(CHILD_POST_ATTACH)
+void
+child_post_attach (pid)
+ int pid;
+{
+ /* This version of Unix doesn't require a meaningful "post attach"
+ operation by a debugger. */
+}
+#endif
+
+static void
+child_require_attach (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ child_attach_to_process (args, from_tty, 1);
+}
+
+static void
+child_detach_from_process (pid, args, from_tty, after_fork)
+ int pid;
+ char * args;
+ int from_tty;
+ int after_fork;
+{
+#ifdef ATTACH_DETACH
+ {
+ int siggnal = 0;
+
+ if (from_tty)
+ {
+ char *exec_file = get_exec_file (0);
+ if (exec_file == 0)
+ exec_file = "";
+ if (after_fork)
+ printf_unfiltered ("Detaching after fork from %s\n",
+ target_pid_to_str (pid));
+ else
+ printf_unfiltered ("Detaching from program: %s, %s\n", exec_file,
+ target_pid_to_str (pid));
+ gdb_flush (gdb_stdout);
+ }
+ if (args)
+ siggnal = atoi (args);
+
+ if (!after_fork)
+ detach (siggnal);
+ else
+ REQUIRE_DETACH (pid, siggnal);
+ }
+#else
+ error ("This version of Unix does not support detaching a process.");
+#endif
+}
+
+/* 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;
+{
+ child_detach_from_process (inferior_pid, args, from_tty, 0);
+ inferior_pid = 0;
+ unpush_target (&child_ops);
+}
+
+static void
+child_require_detach (pid, args, from_tty)
+ int pid;
+ char * args;
+ int from_tty;
+{
+ child_detach_from_process (pid, args, from_tty, 1);
+}
+
+
+/* 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_unfiltered ("\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);
+
+ /* On some targets, there must be some explicit synchronization
+ between the parent and child processes after the debugger
+ forks, and before the child execs the debuggee program. This
+ call basically gives permission for the child to exec.
+ */
+
+ target_acknowledge_created_inferior (pid);
+
+ /* START_INFERIOR_TRAPS_EXPECTED is defined in inferior.h,
+ * and will be 1 or 2 depending on whether we're starting
+ * without or with a shell.
+ */
+ startup_inferior (START_INFERIOR_TRAPS_EXPECTED);
+
+ /* On some targets, there must be some explicit actions taken after
+ the inferior has been started up.
+ */
+ target_post_startup_inferior (pid);
+}
+
+/* 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;
+{
+
+#ifdef HPUXHPPA
+ char *tryname;
+ char *shell_file;
+ char *p;
+ char *p1;
+ char *path = getenv ("PATH");
+ int len;
+ struct stat statbuf;
+
+ /* On HP-UX, we have a possible bad interaction between
+ * the start-up-with-shell code and our catch-fork/catch-exec
+ * logic. To avoid the bad interaction, we start up with the
+ * C shell ("csh") and pass it the "-f" flag (fast start-up,
+ * don't run .cshrc code).
+ * See further comments in inferior.h toward the bottom
+ * (STARTUP_WITH_SHELL flag) and in fork-child.c
+ */
+
+ /* Rather than passing in a hard-wired path like "/bin/csh",
+ * we look down the PATH to find csh. I took this code from
+ * procfs.c, which is the file in the Sun-specific part of GDB
+ * analogous to inftarg.c. See procfs.c for more detailed
+ * comments. - RT
+ */
+ shell_file = "csh";
+ if (path == NULL)
+ path = "/bin:/usr/bin";
+ tryname = alloca (strlen (path) + strlen (shell_file) + 2);
+ for (p = path; p != NULL; p = p1 ? p1 + 1: NULL)
+ {
+ p1 = strchr (p, ':');
+ if (p1 != NULL)
+ len = p1 - p;
+ else
+ len = strlen (p);
+ strncpy (tryname, p, len);
+ tryname[len] = '\0';
+ strcat (tryname, "/");
+ strcat (tryname, shell_file);
+ if (access (tryname, X_OK) < 0)
+ continue;
+ if (stat (tryname, &statbuf) < 0)
+ continue;
+ if (!S_ISREG (statbuf.st_mode))
+ /* We certainly need to reject directories. I'm not quite
+ as sure about FIFOs, sockets, etc., but I kind of doubt
+ that people want to exec() these things. */
+ continue;
+ break;
+ }
+ if (p == NULL)
+ /* Not found. I replaced the error() which existed in procfs.c
+ * with simply passing in NULL and hoping fork_inferior()
+ * can deal with it. - RT
+ */
+ /* error ("Can't find shell %s in PATH", shell_file); */
+ shell_file = NULL;
+ else
+ shell_file = tryname;
+
+ fork_inferior (exec_file, allargs, env, ptrace_me, ptrace_him, pre_fork_inferior, NULL);
+#else
+ fork_inferior (exec_file, allargs, env, ptrace_me, ptrace_him, NULL, NULL);
+#endif
+ /* We are at the first instruction we care about. */
+ /* Pedal to the metal... */
+ proceed ((CORE_ADDR) -1, TARGET_SIGNAL_0, 0);
+}
+
+#if !defined(CHILD_POST_STARTUP_INFERIOR)
+void
+child_post_startup_inferior (pid)
+ int pid;
+{
+ /* This version of Unix doesn't require a meaningful "post startup inferior"
+ operation by a debugger.
+ */
+}
+#endif
+
+#if !defined(CHILD_ACKNOWLEDGE_CREATED_INFERIOR)
+void
+child_acknowledge_created_inferior (pid)
+ int pid;
+{
+ /* This version of Unix doesn't require a meaningful "acknowledge created inferior"
+ operation by a debugger.
+ */
+}
+#endif
+
+
+void
+child_clone_and_follow_inferior (child_pid, followed_child)
+ int child_pid;
+ int *followed_child;
+{
+ clone_and_follow_inferior (child_pid, followed_child);
+
+ /* Don't resume CHILD_PID; it's stopped where it ought to be, until
+ the decision gets made elsewhere how to continue it.
+ */
+}
+
+
+#if !defined(CHILD_POST_FOLLOW_INFERIOR_BY_CLONE)
+void
+child_post_follow_inferior_by_clone ()
+{
+ /* This version of Unix doesn't require a meaningful "post follow inferior"
+ operation by a clone debugger.
+ */
+}
+#endif
+
+#if !defined(CHILD_INSERT_FORK_CATCHPOINT)
+int
+child_insert_fork_catchpoint (pid)
+ int pid;
+{
+ /* This version of Unix doesn't support notification of fork events. */
+ return 0;
+}
+#endif
+
+#if !defined(CHILD_REMOVE_FORK_CATCHPOINT)
+int
+child_remove_fork_catchpoint (pid)
+ int pid;
+{
+ /* This version of Unix doesn't support notification of fork events. */
+ return 0;
+}
+#endif
+
+#if !defined(CHILD_INSERT_VFORK_CATCHPOINT)
+int
+child_insert_vfork_catchpoint (pid)
+ int pid;
+{
+ /* This version of Unix doesn't support notification of vfork events. */
+ return 0;
+}
+#endif
+
+#if !defined(CHILD_REMOVE_VFORK_CATCHPOINT)
+int
+child_remove_vfork_catchpoint (pid)
+ int pid;
+{
+ /* This version of Unix doesn't support notification of vfork events. */
+ return 0;
+}
+#endif
+
+#if !defined(CHILD_HAS_FORKED)
+int
+child_has_forked (pid, child_pid)
+ int pid;
+ int *child_pid;
+{
+ /* This version of Unix doesn't support notification of fork events. */
+ return 0;
+}
+#endif
+
+
+#if !defined(CHILD_HAS_VFORKED)
+int
+child_has_vforked (pid, child_pid)
+ int pid;
+ int * child_pid;
+{
+ /* This version of Unix doesn't support notification of vfork events.
+ */
+ return 0;
+}
+#endif
+
+
+#if !defined(CHILD_CAN_FOLLOW_VFORK_PRIOR_TO_EXEC)
+int
+child_can_follow_vfork_prior_to_exec ()
+{
+ /* This version of Unix doesn't support notification of vfork events.
+ However, if it did, it probably wouldn't allow vforks to be followed
+ before the following exec.
+ */
+ return 0;
+}
+#endif
+
+
+#if !defined(CHILD_POST_FOLLOW_VFORK)
+void
+child_post_follow_vfork (parent_pid, followed_parent, child_pid, followed_child)
+ int parent_pid;
+ int followed_parent;
+ int child_pid;
+ int followed_child;
+{
+ /* This version of Unix doesn't require a meaningful "post follow vfork"
+ operation by a clone debugger.
+ */
+}
+#endif
+
+#if !defined(CHILD_INSERT_EXEC_CATCHPOINT)
+int
+child_insert_exec_catchpoint (pid)
+ int pid;
+{
+ /* This version of Unix doesn't support notification of exec events. */
+ return 0;
+}
+#endif
+
+#if !defined(CHILD_REMOVE_EXEC_CATCHPOINT)
+int
+child_remove_exec_catchpoint (pid)
+ int pid;
+{
+ /* This version of Unix doesn't support notification of exec events. */
+ return 0;
+}
+#endif
+
+#if !defined(CHILD_HAS_EXECD)
+int
+child_has_execd (pid, execd_pathname)
+ int pid;
+ char ** execd_pathname;
+{
+ /* This version of Unix doesn't support notification of exec events.
+ */
+ return 0;
+}
+#endif
+
+
+#if !defined(CHILD_REPORTED_EXEC_EVENTS_PER_EXEC_CALL)
+int
+child_reported_exec_events_per_exec_call ()
+{
+ /* This version of Unix doesn't support notification of exec events.
+ */
+ return 1;
+}
+#endif
+
+
+#if !defined(CHILD_HAS_SYSCALL_EVENT)
+int
+child_has_syscall_event (pid, kind, syscall_id)
+ int pid;
+ enum target_waitkind * kind;
+ int * syscall_id;
+{
+ /* This version of Unix doesn't support notification of syscall events.
+ */
+ return 0;
+}
+#endif
+
+
+#if !defined(CHILD_HAS_EXITED)
+int
+child_has_exited (pid, wait_status, exit_status)
+ int pid;
+ int wait_status;
+ int * exit_status;
+{
+ if (WIFEXITED (wait_status))
+ {
+ *exit_status = WEXITSTATUS (wait_status);
+ return 1;
+ }
+
+ if (WIFSIGNALED (wait_status))
+ {
+ *exit_status = 0; /* ?? Don't know what else to say here. */
+ return 1;
+ }
+
+ /* ?? Do we really need to consult the event state, too? Assume the
+ wait_state alone suffices.
+ */
+ return 0;
+}
+#endif
+
+
+static void
+child_mourn_inferior ()
+{
+ /* FIXME: Should be in a header file */
+ extern void proc_remove_foreign PARAMS ((int));
+
+ unpush_target (&child_ops);
+ proc_remove_foreign (inferior_pid);
+ generic_mourn_inferior ();
+}
+
+static int
+child_can_run ()
+{
+ /* This variable is controlled by modules that sit atop inftarg that may layer
+ their own process structure atop that provided here. hpux-thread.c does
+ this because of the Hpux user-mode level thread model. */
+
+ return !child_suppress_run;
+}
+
+/* Send a SIGINT to the process group. This acts just like the user typed a
+ ^C on the controlling terminal.
+
+ XXX - This may not be correct for all systems. Some may want to use
+ killpg() instead of kill (-pgrp). */
+
+static void
+child_stop ()
+{
+ extern pid_t inferior_process_group;
+
+ kill (-inferior_process_group, SIGINT);
+}
+
+#if !defined(CHILD_ENABLE_EXCEPTION_CALLBACK)
+struct symtab_and_line *
+child_enable_exception_callback (kind, enable)
+ enum exception_event_kind kind;
+ int enable;
+{
+ return (struct symtab_and_line *) NULL;
+}
+#endif
+
+#if !defined(CHILD_GET_CURRENT_EXCEPTION_EVENT)
+struct exception_event_record *
+child_get_current_exception_event ()
+{
+ return (struct exception_event_record *) NULL;
+}
+#endif
+
+
+#if !defined(CHILD_PID_TO_EXEC_FILE)
+char *
+child_pid_to_exec_file (pid)
+ int pid;
+{
+ /* This version of Unix doesn't support translation of a process ID
+ to the filename of the executable file.
+ */
+ return NULL;
+}
+#endif
+
+char *
+child_core_file_to_sym_file (core)
+ char * core;
+{
+ /* The target stratum for a running executable need not support
+ this operation.
+ */
+ return NULL;
+}
+
+
+
+static void
+init_child_ops ()
+{
+ child_ops.to_shortname = "child";
+ child_ops.to_longname = "Unix child process";
+ child_ops.to_doc = "Unix child process (started by the \"run\" command).";
+ child_ops.to_open = child_open;
+ child_ops.to_attach = child_attach;
+ child_ops.to_post_attach = child_post_attach;
+ child_ops.to_require_attach = child_require_attach;
+ child_ops.to_detach = child_detach;
+ child_ops.to_require_detach = child_require_detach;
+ child_ops.to_resume = child_resume;
+ child_ops.to_wait = child_wait;
+ child_ops.to_post_wait = child_post_wait;
+ child_ops.to_fetch_registers = fetch_inferior_registers;
+ child_ops.to_store_registers = store_inferior_registers;
+ child_ops.to_prepare_to_store = child_prepare_to_store;
+ child_ops.to_xfer_memory = child_xfer_memory;
+ child_ops.to_files_info = child_files_info;
+ child_ops.to_insert_breakpoint = memory_insert_breakpoint;
+ child_ops.to_remove_breakpoint = memory_remove_breakpoint;
+ child_ops.to_terminal_init = terminal_init_inferior;
+ child_ops.to_terminal_inferior = terminal_inferior;
+ child_ops.to_terminal_ours_for_output = terminal_ours_for_output;
+ child_ops.to_terminal_ours = terminal_ours;
+ child_ops.to_terminal_info = child_terminal_info;
+ child_ops.to_kill = kill_inferior;
+ child_ops.to_create_inferior = child_create_inferior;
+ child_ops.to_post_startup_inferior = child_post_startup_inferior;
+ child_ops.to_acknowledge_created_inferior = child_acknowledge_created_inferior;
+ child_ops.to_clone_and_follow_inferior = child_clone_and_follow_inferior;
+ child_ops.to_post_follow_inferior_by_clone = child_post_follow_inferior_by_clone;
+ child_ops.to_insert_fork_catchpoint = child_insert_fork_catchpoint;
+ child_ops.to_remove_fork_catchpoint = child_remove_fork_catchpoint;
+ child_ops.to_insert_vfork_catchpoint = child_insert_vfork_catchpoint;
+ child_ops.to_remove_vfork_catchpoint = child_remove_vfork_catchpoint;
+ child_ops.to_has_forked = child_has_forked;
+ child_ops.to_has_vforked = child_has_vforked;
+ child_ops.to_can_follow_vfork_prior_to_exec = child_can_follow_vfork_prior_to_exec;
+ child_ops.to_post_follow_vfork = child_post_follow_vfork;
+ child_ops.to_insert_exec_catchpoint = child_insert_exec_catchpoint;
+ child_ops.to_remove_exec_catchpoint = child_remove_exec_catchpoint;
+ child_ops.to_has_execd = child_has_execd;
+ child_ops.to_reported_exec_events_per_exec_call = child_reported_exec_events_per_exec_call;
+ child_ops.to_has_syscall_event = child_has_syscall_event;
+ child_ops.to_has_exited = child_has_exited;
+ child_ops.to_mourn_inferior = child_mourn_inferior;
+ child_ops.to_can_run = child_can_run;
+ child_ops.to_thread_alive = child_thread_alive;
+ child_ops.to_stop = child_stop;
+ child_ops.to_enable_exception_callback = child_enable_exception_callback;
+ child_ops.to_get_current_exception_event = child_get_current_exception_event;
+ child_ops.to_pid_to_exec_file = child_pid_to_exec_file;
+ child_ops.to_core_file_to_sym_file = child_core_file_to_sym_file;
+ child_ops.to_stratum = process_stratum;
+ child_ops.to_has_all_memory = 1;
+ child_ops.to_has_memory = 1;
+ child_ops.to_has_stack = 1;
+ child_ops.to_has_registers = 1;
+ child_ops.to_has_execution = 1;
+ child_ops.to_magic = OPS_MAGIC;
+}
+
+void
+_initialize_inftarg ()
+{
+#ifdef HAVE_OPTIONAL_PROC_FS
+ char procname[32];
+ int fd;
+
+ /* If we have an optional /proc filesystem (e.g. under OSF/1),
+ don't add ptrace support if we can access the running GDB via /proc. */
+#ifndef PROC_NAME_FMT
+#define PROC_NAME_FMT "/proc/%05d"
+#endif
+ sprintf (procname, PROC_NAME_FMT, getpid ());
+ if ((fd = open (procname, O_RDONLY)) >= 0)
+ {
+ close (fd);
+ return;
+ }
+#endif
+
+ init_child_ops ();
+ add_target (&child_ops);
+}
diff --git a/gdb/infttrace.c b/gdb/infttrace.c
new file mode 100644
index 00000000000..61723dff052
--- /dev/null
+++ b/gdb/infttrace.c
@@ -0,0 +1,5674 @@
+/* Low level Unix child interface to ttrace, for GDB when running under HP-UX.
+ Copyright 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "frame.h"
+#include "inferior.h"
+#include "target.h"
+#include "gdb_string.h"
+#include "wait.h"
+#include "command.h"
+
+/* Some hackery to work around a use of the #define name NO_FLAGS
+ * in both gdb and HPUX (bfd.h and /usr/include/machine/vmparam.h).
+ */
+#ifdef NO_FLAGS
+#define INFTTRACE_TEMP_HACK NO_FLAGS
+#undef NO_FLAGS
+#endif
+
+#ifdef USG
+#include <sys/types.h>
+#endif
+
+#include <sys/param.h>
+#include <sys/dir.h>
+#include <signal.h>
+#include <sys/ioctl.h>
+
+#include <sys/ttrace.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <sys/mman.h>
+
+#ifndef NO_PTRACE_H
+#ifdef PTRACE_IN_WRONG_PLACE
+#include <ptrace.h>
+#else
+#include <sys/ptrace.h>
+#endif
+#endif /* NO_PTRACE_H */
+
+/* Second half of the hackery above. Non-ANSI C, so
+ * we can't use "#error", alas.
+ */
+#ifdef NO_FLAGS
+#if (NO_FLAGS != INFTTRACE_TEMP_HACK )
+ /* #error "Hackery to remove warning didn't work right" */
+#else
+ /* Ok, new def'n of NO_FLAGS is same as old one; no action needed. */
+#endif
+#else
+ /* #error "Didn't get expected re-definition of NO_FLAGS" */
+#define NO_FLAGS INFTTRACE_TEMP_HACK
+#endif
+
+#if !defined (PT_SETTRC)
+#define PT_SETTRC 0 /* Make process traceable by parent */
+#endif
+#if !defined (PT_READ_I)
+#define PT_READ_I 1 /* Read word from text space */
+#endif
+#if !defined (PT_READ_D)
+#define PT_READ_D 2 /* Read word from data space */
+#endif
+#if !defined (PT_READ_U)
+#define PT_READ_U 3 /* Read word from kernel user struct */
+#endif
+#if !defined (PT_WRITE_I)
+#define PT_WRITE_I 4 /* Write word to text space */
+#endif
+#if !defined (PT_WRITE_D)
+#define PT_WRITE_D 5 /* Write word to data space */
+#endif
+#if !defined (PT_WRITE_U)
+#define PT_WRITE_U 6 /* Write word to kernel user struct */
+#endif
+#if !defined (PT_CONTINUE)
+#define PT_CONTINUE 7 /* Continue after signal */
+#endif
+#if !defined (PT_STEP)
+#define PT_STEP 9 /* Set flag for single stepping */
+#endif
+#if !defined (PT_KILL)
+#define PT_KILL 8 /* Send child a SIGKILL signal */
+#endif
+
+#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
+
+/* This semaphore is used to coordinate the child and parent processes
+ after a fork(), and before an exec() by the child. See parent_attach_all
+ for details.
+ */
+typedef struct {
+ int parent_channel[2]; /* Parent "talks" to [1], child "listens" to [0] */
+ int child_channel[2]; /* Child "talks" to [1], parent "listens" to [0] */
+} startup_semaphore_t;
+
+#define SEM_TALK (1)
+#define SEM_LISTEN (0)
+
+static startup_semaphore_t startup_semaphore;
+
+/* See can_touch_threads_of_process for details. */
+static int vforking_child_pid = 0;
+static int vfork_in_flight = 0;
+
+/* To support PREPARE_TO_PROCEED (hppa_prepare_to_proceed).
+ */
+static pid_t old_gdb_pid = 0;
+static pid_t reported_pid = 0;
+static int reported_bpt = 0;
+
+/* 1 if ok as results of a ttrace or ttrace_wait call, 0 otherwise.
+ */
+#define TT_OK( _status, _errno ) \
+ (((_status) == 1) && ((_errno) == 0))
+
+#define TTRACE_ARG_TYPE uint64_t
+
+/* When supplied as the "addr" operand, ttrace interprets this
+ to mean, "from the current address".
+ */
+#define TT_USE_CURRENT_PC ((TTRACE_ARG_TYPE) TT_NOPC)
+
+/* When supplied as the "addr", "data" or "addr2" operand for most
+ requests, ttrace interprets this to mean, "pay no heed to this
+ argument".
+ */
+#define TT_NIL ((TTRACE_ARG_TYPE) TT_NULLARG)
+
+/* This is capable of holding the value of a 32-bit register. The
+ value is always left-aligned in the buffer; i.e., [0] contains
+ the most-significant byte of the register's value, and [sizeof(reg)]
+ contains the least-significant value.
+
+ ??rehrauer: Yes, this assumes that an int is 32-bits on HP-UX, and
+ that registers are 32-bits on HP-UX. The latter assumption changes
+ with PA2.0.
+ */
+typedef int register_value_t;
+
+/********************************************************************
+
+ How this works:
+
+ 1. Thread numbers
+
+ The rest of GDB sees threads as being things with different
+ "pid" (process id) values. See "thread.c" for details. The
+ separate threads will be seen and reacted to if infttrace passes
+ back different pid values (for _events_). See wait_for_inferior
+ in inftarg.c.
+
+ So infttrace is going to use thread ids externally, pretending
+ they are process ids, and keep track internally so that it can
+ use the real process id (and thread id) when calling ttrace.
+
+ The data structure that supports this is a linked list of the
+ current threads. Since at some date infttrace will have to
+ deal with multiple processes, each list element records its
+ corresponding pid, rather than having a single global.
+
+ Note that the list is only approximately current; that's ok, as
+ it's up to date when we need it (we hope!). Also, it can contain
+ dead threads, as there's no harm if it does.
+
+ The approach taken here is to bury the translation from external
+ to internal inside "call_ttrace" and a few other places.
+
+ There are some wrinkles:
+
+ o When GDB forks itself to create the debug target process,
+ there's only a pid of 0 around in the child, so the
+ TT_PROC_SETTRC operation uses a more direct call to ttrace;
+ Similiarly, the initial setting of the event mask happens
+ early as well, and so is also special-cased, and an attach
+ uses a real pid;
+
+ o We define an unthreaded application as having a "pseudo"
+ thread;
+
+ o To keep from confusing the rest of GDB, we don't switch
+ the PID for the pseudo thread to a TID. A table will help:
+
+ Rest of GDB sees these PIDs: pid tid1 tid2 tid3 ...
+
+ Our thread list stores: pid pid pid pid ...
+ tid0 tid1 tid2 tid3
+
+ Ttrace sees these TIDS: tid0 tid1 tid2 tid3 ...
+
+ Both pid and tid0 will map to tid0, as there are infttrace.c-internal
+ calls to ttrace using tid0.
+
+ 2. Step and Continue
+
+ Since we're implementing the "stop the world" model, sub-model
+ "other threads run during step", we have some stuff to do:
+
+ o User steps require continuing all threads other than the
+ one the user is stepping;
+
+ o Internal debugger steps (such as over a breakpoint or watchpoint,
+ but not out of a library load thunk) require stepping only
+ the selected thread; this means that we have to report the
+ step finish on that thread, which can lead to complications;
+
+ o When a thread is created, it is created running, rather
+ than stopped--so we have to stop it.
+
+ The OS doesn't guarantee the stopped thread list will be stable,
+ no does it guarantee where on the stopped thread list a thread
+ that is single-stepped will wind up: it's possible that it will
+ be off the list for a while, it's possible the step will complete
+ and it will be re-posted to the end...
+
+ This means we have to scan the stopped thread list, build up
+ a work-list, and then run down the work list; we can't do the
+ step/continue during the scan.
+
+ 3. Buffering events
+
+ Then there's the issue of waiting for an event. We do this by
+ noticing how many events are reported at the end of each wait.
+ From then on, we "fake" all resumes and steps, returning instantly,
+ and don't do another wait. Once all pending events are reported,
+ we can really resume again.
+
+ To keep this hidden, all the routines which know about tids and
+ pids or real events and simulated ones are static (file-local).
+
+ This code can make lots of calls to ttrace, in particular it
+ can spin down the list of thread states more than once. If this
+ becomes a performance hit, the spin could be done once and the
+ various "tsp" blocks saved, keeping all later spins in this
+ process.
+
+ The O/S doesn't promise to keep the list straight, and so we must
+ re-scan a lot. By observation, it looks like a single-step/wait
+ puts the stepped thread at the end of the list but doesn't change
+ it otherwise.
+
+****************************************************************
+*/
+
+/* Uncomment these to turn on various debugging output */
+/* #define THREAD_DEBUG */
+/* #define WAIT_BUFFER_DEBUG */
+/* #define PARANOIA */
+
+
+#define INFTTRACE_ALL_THREADS (-1)
+#define INFTTRACE_STEP (1)
+#define INFTTRACE_CONTINUE (0)
+
+/* FIX: this is used in inftarg.c/child_wait, in a hack.
+ */
+extern int not_same_real_pid;
+
+/* This is used to count buffered events.
+ */
+static unsigned int more_events_left = 0;
+
+/* Process state.
+ */
+typedef enum process_state_enum {
+ STOPPED,
+ FAKE_STEPPING,
+ FAKE_CONTINUE, /* For later use */
+ RUNNING,
+ FORKING,
+ VFORKING
+} process_state_t;
+
+static process_state_t process_state = STOPPED;
+
+/* User-specified stepping modality.
+ */
+typedef enum stepping_mode_enum {
+ DO_DEFAULT, /* ...which is a continue! */
+ DO_STEP,
+ DO_CONTINUE
+} stepping_mode_t;
+
+/* Action to take on an attach, depends on
+ * what kind (user command, fork, vfork).
+ *
+ * At the moment, this is either:
+ *
+ * o continue with a SIGTRAP signal, or
+ *
+ * o leave stopped.
+ */
+typedef enum attach_continue_enum {
+ DO_ATTACH_CONTINUE,
+ DONT_ATTACH_CONTINUE
+} attach_continue_t;
+
+/* This flag is true if we are doing a step-over-bpt
+ * with buffered events. We will have to be sure to
+ * report the right thread, as otherwise the spaghetti
+ * code in "infrun.c/wait_for_inferior" will get
+ * confused.
+ */
+static int doing_fake_step = 0;
+static lwpid_t fake_step_tid = 0;
+
+
+/****************************************************
+ * Thread information structure routines and types. *
+ ****************************************************
+ */
+typedef
+struct thread_info_struct
+{
+ int am_pseudo; /* This is a pseudo-thread for the process. */
+ int pid; /* Process ID */
+ lwpid_t tid; /* Thread ID */
+ int handled; /* 1 if a buffered event was handled. */
+ int seen; /* 1 if this thread was seen on a traverse. */
+ int terminated; /* 1 if thread has terminated. */
+ int have_signal; /* 1 if signal to be sent */
+ enum target_signal signal_value; /* Signal to send */
+ int have_start; /* 1 if alternate starting address */
+ stepping_mode_t stepping_mode; /* Whether to step or continue */
+ CORE_ADDR start; /* Where to start */
+ int have_state; /* 1 if the event state has been set */
+ ttstate_t last_stop_state;/* The most recently-waited event for this thread. */
+ struct thread_info_struct
+ *next; /* All threads are linked via this field. */
+ struct thread_info_struct
+ *next_pseudo; /* All pseudo-threads are linked via this field. */
+} thread_info;
+
+typedef
+struct thread_info_header_struct
+{
+ int count;
+ thread_info *head;
+ thread_info *head_pseudo;
+
+} thread_info_header;
+
+static thread_info_header thread_head = { 0, NULL, NULL };
+static thread_info_header deleted_threads = { 0, NULL, NULL };
+
+static saved_real_pid = 0;
+
+
+/*************************************************
+ * Debugging support functions *
+ *************************************************
+ */
+CORE_ADDR
+get_raw_pc( ttid )
+ lwpid_t ttid;
+{
+ unsigned long pc_val;
+ int offset;
+ int res;
+
+ offset = register_addr( PC_REGNUM, U_REGS_OFFSET );
+ res = read_from_register_save_state(
+ ttid,
+ (TTRACE_ARG_TYPE) offset,
+ (char *) &pc_val,
+ sizeof( pc_val ));
+ if( res <= 0 ) {
+ return (CORE_ADDR) pc_val;
+ }
+ else {
+ return (CORE_ADDR) 0;
+ }
+}
+
+static char *
+get_printable_name_of_stepping_mode( mode )
+ stepping_mode_t mode;
+{
+ switch( mode ) {
+ case DO_DEFAULT: return "DO_DEFAULT";
+ case DO_STEP: return "DO_STEP";
+ case DO_CONTINUE: return "DO_CONTINUE";
+ default: return "?unknown mode?";
+ }
+}
+
+/* This function returns a pointer to a string describing the
+ * ttrace event being reported.
+ */
+char *
+get_printable_name_of_ttrace_event (event)
+ ttevents_t event;
+{
+ /* This enumeration is "gappy", so don't use a table. */
+ switch (event) {
+
+ case TTEVT_NONE:
+ return "TTEVT_NONE";
+ case TTEVT_SIGNAL:
+ return "TTEVT_SIGNAL";
+ case TTEVT_FORK:
+ return "TTEVT_FORK";
+ case TTEVT_EXEC:
+ return "TTEVT_EXEC";
+ case TTEVT_EXIT:
+ return "TTEVT_EXIT";
+ case TTEVT_VFORK:
+ return "TTEVT_VFORK";
+ case TTEVT_SYSCALL_RETURN:
+ return "TTEVT_SYSCALL_RETURN";
+ case TTEVT_LWP_CREATE:
+ return "TTEVT_LWP_CREATE";
+ case TTEVT_LWP_TERMINATE:
+ return "TTEVT_LWP_TERMINATE";
+ case TTEVT_LWP_EXIT:
+ return "TTEVT_LWP_EXIT";
+ case TTEVT_LWP_ABORT_SYSCALL:
+ return "TTEVT_LWP_ABORT_SYSCALL";
+ case TTEVT_SYSCALL_ENTRY:
+ return "TTEVT_SYSCALL_ENTRY";
+ case TTEVT_SYSCALL_RESTART:
+ return "TTEVT_SYSCALL_RESTART";
+ default :
+ return "?new event?";
+ }
+}
+
+
+/* This function translates the ttrace request enumeration into
+ * a character string that is its printable (aka "human readable")
+ * name.
+ */
+char *
+get_printable_name_of_ttrace_request (request)
+ ttreq_t request;
+{
+ if (!IS_TTRACE_REQ (request))
+ return "?bad req?";
+
+ /* This enumeration is "gappy", so don't use a table. */
+ switch (request) {
+ case TT_PROC_SETTRC :
+ return "TT_PROC_SETTRC";
+ case TT_PROC_ATTACH :
+ return "TT_PROC_ATTACH";
+ case TT_PROC_DETACH :
+ return "TT_PROC_DETACH";
+ case TT_PROC_RDTEXT :
+ return "TT_PROC_RDTEXT";
+ case TT_PROC_WRTEXT :
+ return "TT_PROC_WRTEXT";
+ case TT_PROC_RDDATA :
+ return "TT_PROC_RDDATA";
+ case TT_PROC_WRDATA :
+ return "TT_PROC_WRDATA";
+ case TT_PROC_STOP :
+ return "TT_PROC_STOP";
+ case TT_PROC_CONTINUE :
+ return "TT_PROC_CONTINUE";
+ case TT_PROC_GET_PATHNAME :
+ return "TT_PROC_GET_PATHNAME";
+ case TT_PROC_GET_EVENT_MASK :
+ return "TT_PROC_GET_EVENT_MASK";
+ case TT_PROC_SET_EVENT_MASK :
+ return "TT_PROC_SET_EVENT_MASK";
+ case TT_PROC_GET_FIRST_LWP_STATE :
+ return "TT_PROC_GET_FIRST_LWP_STATE";
+ case TT_PROC_GET_NEXT_LWP_STATE :
+ return "TT_PROC_GET_NEXT_LWP_STATE";
+ case TT_PROC_EXIT :
+ return "TT_PROC_EXIT";
+ case TT_PROC_GET_MPROTECT :
+ return "TT_PROC_GET_MPROTECT";
+ case TT_PROC_SET_MPROTECT :
+ return "TT_PROC_SET_MPROTECT";
+ case TT_PROC_SET_SCBM :
+ return "TT_PROC_SET_SCBM";
+ case TT_LWP_STOP :
+ return "TT_LWP_STOP";
+ case TT_LWP_CONTINUE :
+ return "TT_LWP_CONTINUE";
+ case TT_LWP_SINGLE :
+ return "TT_LWP_SINGLE";
+ case TT_LWP_RUREGS :
+ return "TT_LWP_RUREGS";
+ case TT_LWP_WUREGS :
+ return "TT_LWP_WUREGS";
+ case TT_LWP_GET_EVENT_MASK :
+ return "TT_LWP_GET_EVENT_MASK";
+ case TT_LWP_SET_EVENT_MASK :
+ return "TT_LWP_SET_EVENT_MASK";
+ case TT_LWP_GET_STATE :
+ return "TT_LWP_GET_STATE";
+ default :
+ return "?new req?";
+ }
+}
+
+
+/* This function translates the process state enumeration into
+ * a character string that is its printable (aka "human readable")
+ * name.
+ */
+static char *
+get_printable_name_of_process_state (process_state)
+ process_state_t process_state;
+{
+ switch (process_state) {
+ case STOPPED:
+ return "STOPPED";
+ case FAKE_STEPPING:
+ return "FAKE_STEPPING";
+ case RUNNING:
+ return "RUNNING";
+ case FORKING:
+ return "FORKING";
+ case VFORKING:
+ return "VFORKING";
+ default:
+ return "?some unknown state?";
+ }
+}
+
+/* Set a ttrace thread state to a safe, initial state.
+ */
+static void
+clear_ttstate_t (tts)
+ ttstate_t * tts;
+{
+ tts->tts_pid = 0;
+ tts->tts_lwpid = 0;
+ tts->tts_user_tid = 0;
+ tts->tts_event = TTEVT_NONE;
+}
+
+/* Copy ttrace thread state TTS_FROM into TTS_TO.
+ */
+static void
+copy_ttstate_t (tts_to, tts_from)
+ ttstate_t * tts_to;
+ ttstate_t * tts_from;
+{
+ memcpy ((char *) tts_to, (char *) tts_from, sizeof (*tts_to));
+}
+
+/* Are there any live threads we know about?
+ */
+static int
+any_thread_records()
+{
+ return( thread_head.count > 0 );
+}
+
+/* Create, fill in and link in a thread descriptor.
+ */
+static thread_info *
+create_thread_info (pid, tid)
+ int pid;
+ lwpid_t tid;
+{
+ thread_info * new_p;
+ thread_info * p;
+ int thread_count_of_pid;
+
+ new_p = malloc( sizeof( thread_info ));
+ new_p->pid = pid;
+ new_p->tid = tid;
+ new_p->have_signal = 0;
+ new_p->have_start = 0;
+ new_p->have_state = 0;
+ clear_ttstate_t( &new_p->last_stop_state );
+ new_p->am_pseudo = 0;
+ new_p->handled = 0;
+ new_p->seen = 0;
+ new_p->terminated = 0;
+ new_p->next = NULL;
+ new_p->next_pseudo = NULL;
+ new_p->stepping_mode = DO_DEFAULT;
+
+ if( 0 == thread_head.count ) {
+#ifdef THREAD_DEBUG
+ if( debug_on )
+ printf( "First thread, pid %d tid %d!\n", pid, tid );
+#endif
+ saved_real_pid = inferior_pid;
+ }
+ else {
+#ifdef THREAD_DEBUG
+ if( debug_on )
+ printf( "Subsequent thread, pid %d tid %d\n", pid, tid );
+#endif
+ }
+
+ /* Another day, another thread...
+ */
+ thread_head.count++;
+
+ /* The new thread always goes at the head of the list.
+ */
+ new_p->next = thread_head.head;
+ thread_head.head = new_p;
+
+ /* Is this the "pseudo" thread of a process? It is if there's
+ * no other thread for this process on the list. (Note that this
+ * accomodates multiple processes, such as we see even for simple
+ * cases like forking "non-threaded" programs.)
+ */
+ p = thread_head.head;
+ thread_count_of_pid = 0;
+ while (p)
+ {
+ if (p->pid == new_p->pid)
+ thread_count_of_pid++;
+ p = p->next;
+ }
+
+ /* Did we see any other threads for this pid? (Recall that we just
+ * added this thread to the list...)
+ */
+ if (thread_count_of_pid == 1)
+ {
+ new_p->am_pseudo = 1;
+ new_p->next_pseudo = thread_head.head_pseudo;
+ thread_head.head_pseudo = new_p;
+ }
+
+ return new_p;
+}
+
+/* Get rid of our thread info.
+ */
+static void
+clear_thread_info ()
+{
+ thread_info *p;
+ thread_info *q;
+
+#ifdef THREAD_DEBUG
+ if( debug_on )
+ printf( "Clearing all thread info\n" );
+#endif
+
+ p = thread_head.head;
+ while( p ) {
+ q = p;
+ p = p->next;
+ free( q );
+ }
+
+ thread_head.head = NULL;
+ thread_head.head_pseudo = NULL;
+ thread_head.count = 0;
+
+ p = deleted_threads.head;
+ while( p ) {
+ q = p;
+ p = p->next;
+ free( q );
+ }
+
+ deleted_threads.head = NULL;
+ deleted_threads.head_pseudo = NULL;
+ deleted_threads.count = 0;
+
+ /* No threads, so can't have pending events.
+ */
+ more_events_left = 0;
+}
+
+/* Given a tid, find the thread block for it.
+ */
+static thread_info *
+find_thread_info (tid)
+ lwpid_t tid;
+{
+ thread_info *p;
+
+ for( p = thread_head.head; p; p = p->next ) {
+ if( p->tid == tid ) {
+ return p;
+ }
+ }
+
+ for( p = deleted_threads.head; p; p = p->next ) {
+ if( p->tid == tid ) {
+ return p;
+ }
+ }
+
+ return NULL;
+}
+
+/* For any but the pseudo thread, this maps to the
+ * thread ID. For the pseudo thread, if you pass either
+ * the thread id or the PID, you get the pseudo thread ID.
+ *
+ * We have to be prepared for core gdb to ask about
+ * deleted threads. We do the map, but we don't like it.
+ */
+static lwpid_t
+map_from_gdb_tid( gdb_tid )
+ lwpid_t gdb_tid;
+{
+ thread_info *p;
+
+ /* First assume gdb_tid really is a tid, and try to find a
+ * matching entry on the threads list.
+ */
+ for( p = thread_head.head; p; p = p->next ) {
+ if( p->tid == gdb_tid )
+ return gdb_tid;
+ }
+
+ /* It doesn't appear to be a tid; perhaps it's really a pid?
+ * Try to find a "pseudo" thread entry on the threads list.
+ */
+ for (p = thread_head.head_pseudo; p != NULL; p = p->next_pseudo)
+ {
+ if (p->pid == gdb_tid)
+ return p->tid;
+ }
+
+ /* Perhaps it's the tid of a deleted thread we may still
+ * have some knowledge of?
+ */
+ for( p = deleted_threads.head; p; p = p-> next ) {
+ if( p->tid == gdb_tid )
+ return gdb_tid;
+ }
+
+ /* Or perhaps it's the pid of a deleted process we may still
+ * have knowledge of?
+ */
+ for (p = deleted_threads.head_pseudo; p != NULL; p = p->next_pseudo)
+ {
+ if (p->pid == gdb_tid)
+ return p->tid;
+ }
+
+ return 0; /* Error? */
+}
+
+/* Map the other way: from a real tid to the
+ * "pid" known by core gdb. This tid may be
+ * for a thread that just got deleted, so we
+ * also need to consider deleted threads.
+ */
+static lwpid_t
+map_to_gdb_tid( real_tid )
+ lwpid_t real_tid;
+{
+ thread_info *p;
+
+ for( p = thread_head.head; p; p = p->next ) {
+ if( p->tid == real_tid ) {
+ if( p->am_pseudo )
+ return p->pid;
+ else
+ return real_tid;
+ }
+ }
+
+ for( p = deleted_threads.head; p; p = p-> next ) {
+ if( p->tid == real_tid )
+ if( p->am_pseudo )
+ return p->pid; /* Error? */
+ else
+ return real_tid;
+ }
+
+ return 0; /* Error? Never heard of this thread! */
+}
+
+/* Do any threads have saved signals?
+ */
+static int
+saved_signals_exist ()
+{
+ thread_info *p;
+
+ for( p = thread_head.head; p; p = p->next ) {
+ if( p->have_signal ) {
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+/* Is this the tid for the zero-th thread?
+ */
+static int
+is_pseudo_thread (tid)
+ lwpid_t tid;
+{
+ thread_info *p = find_thread_info( tid );
+ if( NULL == p || p->terminated )
+ return 0;
+ else
+ return p->am_pseudo;
+}
+
+/* Is this thread terminated?
+ */
+static int
+is_terminated (tid)
+ lwpid_t tid;
+{
+ thread_info *p = find_thread_info( tid );
+
+ if( NULL != p )
+ return p->terminated;
+
+ return 0;
+}
+
+/* Is this pid a real PID or a TID?
+ */
+static int
+is_process_id (pid)
+ int pid;
+{
+ lwpid_t tid;
+ thread_info * tinfo;
+ pid_t this_pid;
+ int this_pid_count;
+
+ /* What does PID really represent?
+ */
+ tid = map_from_gdb_tid (pid);
+ if (tid <= 0)
+ return 0; /* Actually, is probably an error... */
+
+ tinfo = find_thread_info (tid);
+
+ /* Does it appear to be a true thread?
+ */
+ if (! tinfo->am_pseudo)
+ return 0;
+
+ /* Else, it looks like it may be a process. See if there's any other
+ * threads with the same process ID, though. If there are, then TID
+ * just happens to be the first thread of several for this process.
+ */
+ this_pid = tinfo->pid;
+ this_pid_count = 0;
+ for (tinfo = thread_head.head; tinfo; tinfo = tinfo->next)
+ {
+ if (tinfo->pid == this_pid)
+ this_pid_count++;
+ }
+
+ return (this_pid_count == 1);
+}
+
+
+/* Add a thread to our info. Prevent duplicate entries.
+ */
+static thread_info *
+add_tthread (pid, tid)
+ int pid;
+ lwpid_t tid;
+{
+ thread_info *p;
+
+ p = find_thread_info( tid );
+ if( NULL == p )
+ p = create_thread_info( pid, tid );
+
+ return p;
+}
+
+/* Notice that a thread was deleted.
+ */
+static void
+del_tthread (tid)
+ lwpid_t tid;
+{
+ thread_info *p;
+ thread_info *chase;
+
+ if( thread_head.count <= 0 ) {
+ error( "Internal error in thread database." );
+ return;
+ }
+
+ chase = NULL;
+ for( p = thread_head.head; p; p = p->next ) {
+ if( p->tid == tid ) {
+
+#ifdef THREAD_DEBUG
+ if( debug_on )
+ printf( "Delete here: %d \n", tid );
+#endif
+
+ if( p->am_pseudo ) {
+ /*
+ * Deleting a main thread is ok if we're doing
+ * a parent-follow on a child; this is odd but
+ * not wrong. It apparently _doesn't_ happen
+ * on the child-follow, as we don't just delete
+ * the pseudo while keeping the rest of the
+ * threads around--instead, we clear out the whole
+ * thread list at once.
+ */
+ thread_info *q;
+ thread_info *q_chase;
+
+ q_chase = NULL;
+ for( q = thread_head.head_pseudo; q; q = q -> next ) {
+ if( q == p ) {
+ /* Remove from pseudo list.
+ */
+ if( q_chase == NULL )
+ thread_head.head_pseudo = p->next_pseudo;
+ else
+ q_chase-> next = p->next_pseudo;
+ }
+ else
+ q_chase = q;
+ }
+ }
+
+ /* Remove from live list.
+ */
+ thread_head.count--;
+
+ if( NULL == chase )
+ thread_head.head = p->next;
+ else
+ chase->next = p->next;
+
+ /* Add to deleted thread list.
+ */
+ p->next = deleted_threads.head;
+ deleted_threads.head = p;
+ deleted_threads.count++;
+ if( p->am_pseudo ) {
+ p->next_pseudo = deleted_threads.head_pseudo;
+ deleted_threads.head_pseudo = p;
+ }
+ p->terminated = 1;
+
+ return;
+ }
+
+ else
+ chase = p;
+ }
+}
+
+/* Get the pid for this tid. (Has to be a real TID!).
+ */
+static int
+get_pid_for (tid)
+ lwpid_t tid;
+{
+ thread_info *p;
+
+ for( p = thread_head.head; p; p = p->next ) {
+ if( p->tid == tid ) {
+ return p->pid;
+ }
+ }
+
+ for( p = deleted_threads.head; p; p = p->next ) {
+ if( p->tid == tid ) {
+ return p->pid;
+ }
+ }
+
+ return 0;
+}
+
+/* Note that this thread's current event has been handled.
+ */
+static void
+set_handled( pid, tid )
+ int pid;
+ lwpid_t tid;
+{
+ thread_info *p;
+
+ p = find_thread_info( tid );
+ if( NULL == p )
+ p = add_tthread( pid, tid );
+
+ p->handled = 1;
+}
+
+/* Was this thread's current event handled?
+ */
+static int
+was_handled( tid )
+ lwpid_t tid;
+{
+ thread_info *p;
+
+ p = find_thread_info( tid );
+ if( NULL != p )
+ return p->handled;
+
+ return 0; /* New threads have not been handled */
+}
+
+/* Set this thread to unhandled.
+ */
+static void
+clear_handled( tid )
+ lwpid_t tid;
+{
+ thread_info * p;
+
+#ifdef WAIT_BUFFER_DEBUG
+ if( debug_on )
+ printf( "clear_handled %d\n", (int) tid );
+#endif
+
+ p = find_thread_info (tid);
+ if (p == NULL)
+ error ("Internal error: No thread state to clear?");
+
+ p->handled = 0;
+}
+
+/* Set all threads to unhandled.
+ */
+static void
+clear_all_handled ()
+{
+ thread_info *p;
+
+#ifdef WAIT_BUFFER_DEBUG
+ if( debug_on )
+ printf( "clear_all_handled\n" );
+#endif
+
+ for( p = thread_head.head; p; p = p->next ) {
+ p->handled = 0;
+ }
+
+ for( p = deleted_threads.head; p; p = p->next ) {
+ p->handled = 0;
+ }
+}
+
+/* Set this thread to default stepping mode.
+ */
+static void
+clear_stepping_mode( tid )
+ lwpid_t tid;
+{
+ thread_info * p;
+
+#ifdef WAIT_BUFFER_DEBUG
+ if( debug_on )
+ printf( "clear_stepping_mode %d\n", (int) tid );
+#endif
+
+ p = find_thread_info (tid);
+ if (p == NULL)
+ error ("Internal error: No thread state to clear?");
+
+ p->stepping_mode = DO_DEFAULT;
+}
+
+/* Set all threads to do default continue on resume.
+ */
+static void
+clear_all_stepping_mode ()
+{
+ thread_info *p;
+
+#ifdef WAIT_BUFFER_DEBUG
+ if( debug_on )
+ printf( "clear_all_stepping_mode\n" );
+#endif
+
+ for( p = thread_head.head; p; p = p->next ) {
+ p->stepping_mode = DO_DEFAULT;
+ }
+
+ for( p = deleted_threads.head; p; p = p->next ) {
+ p->stepping_mode = DO_DEFAULT;
+ }
+}
+
+/* Set all threads to unseen on this pass.
+ */
+static void
+set_all_unseen ()
+{
+ thread_info *p;
+
+ for( p = thread_head.head; p; p = p->next ) {
+ p->seen = 0;
+ }
+}
+
+#if (defined( THREAD_DEBUG ) || defined( PARANOIA ))
+/* debugging routine.
+ */
+static void
+print_tthread (p)
+ thread_info * p;
+{
+ printf( " Thread pid %d, tid %d", p->pid, p->tid );
+ if( p->have_state )
+ printf( ", event is %s",
+ get_printable_name_of_ttrace_event( p->last_stop_state.tts_event ));
+
+ if( p->am_pseudo )
+ printf( ", pseudo thread" );
+
+ if( p->have_signal )
+ printf( ", have signal 0x%x", p->signal_value );
+
+ if( p->have_start )
+ printf( ", have start at 0x%x", p->start );
+
+ printf( ", step is %s", get_printable_name_of_stepping_mode( p->stepping_mode ));
+
+ if( p->handled )
+ printf( ", handled" );
+ else
+ printf( ", not handled" );
+
+ if( p->seen )
+ printf( ", seen" );
+ else
+ printf( ", not seen" );
+
+ printf( "\n" );
+}
+
+static void
+print_tthreads ()
+{
+ thread_info *p;
+
+ if( thread_head.count == 0 )
+ printf( "Thread list is empty\n" );
+ else {
+ printf( "Thread list has " );
+ if( thread_head.count == 1 )
+ printf( "1 entry:\n" );
+ else
+ printf( "%d entries:\n", thread_head.count );
+ for( p = thread_head.head; p; p = p->next ) {
+ print_tthread (p);
+ }
+ }
+
+ if( deleted_threads.count == 0 )
+ printf( "Deleted thread list is empty\n" );
+ else {
+ printf( "Deleted thread list has " );
+ if( deleted_threads.count == 1 )
+ printf( "1 entry:\n" );
+ else
+ printf( "%d entries:\n", deleted_threads.count );
+
+ for( p = deleted_threads.head; p; p = p->next ) {
+ print_tthread (p);
+ }
+ }
+}
+#endif
+
+/* Update the thread list based on the "seen" bits.
+ */
+static void
+update_thread_list ()
+{
+ thread_info *p;
+ thread_info *chase;
+
+ chase = NULL;
+ for( p = thread_head.head; p; p = p->next ) {
+ /* Is this an "unseen" thread which really happens to be a process?
+ If so, is it inferior_pid and is a vfork in flight? If yes to
+ all, then DON'T REMOVE IT! We're in the midst of moving a vfork
+ operation, which is a multiple step thing, to the point where we
+ can touch the parent again. We've most likely stopped to examine
+ the child at a late stage in the vfork, and if we're not following
+ the child, we'd best not treat the parent as a dead "thread"...
+ */
+ if( (!p->seen) && p->am_pseudo && vfork_in_flight
+ && (p->pid != vforking_child_pid))
+ p->seen = 1;
+
+ if( !p->seen ) {
+ /* Remove this one
+ */
+
+#ifdef THREAD_DEBUG
+ if( debug_on )
+ printf( "Delete unseen thread: %d \n", p->tid );
+#endif
+ del_tthread( p->tid );
+ }
+ }
+}
+
+
+
+/************************************************
+ * O/S call wrappers *
+ ************************************************
+ */
+
+/* This function simply calls ttrace with the given arguments.
+ * It exists so that all calls to ttrace are isolated. All
+ * parameters should be as specified by "man 2 ttrace".
+ *
+ * No other "raw" calls to ttrace should exist in this module.
+ */
+static int
+call_real_ttrace( request, pid, tid, addr, data, addr2 )
+ ttreq_t request;
+ pid_t pid;
+ lwpid_t tid;
+ TTRACE_ARG_TYPE addr, data, addr2;
+{
+ int tt_status;
+
+ errno = 0;
+ tt_status = ttrace( request, pid, tid, addr, data, addr2 );
+
+#ifdef THREAD_DEBUG
+ if (errno) {
+ /* Don't bother for a known benign error: if you ask for the
+ * first thread state, but there is only one thread and it's
+ * not stopped, ttrace complains.
+ *
+ * We have this inside the #ifdef because our caller will do
+ * this check for real.
+ */
+ if( request != TT_PROC_GET_FIRST_LWP_STATE
+ || errno != EPROTO ) {
+ if( debug_on )
+ printf( "TT fail for %s, with pid %d, tid %d, status %d \n",
+ get_printable_name_of_ttrace_request (request),
+ pid, tid, tt_status );
+ }
+ }
+#endif
+
+#if 0
+ /* ??rehrauer: It would probably be most robust to catch and report
+ * failed requests here. However, some clients of this interface
+ * seem to expect to catch & deal with them, so we'd best not.
+ */
+ if (errno) {
+ strcpy (reason_for_failure, "ttrace (");
+ strcat (reason_for_failure, get_printable_name_of_ttrace_request (request));
+ strcat (reason_for_failure, ")");
+ printf( "ttrace error, errno = %d\n", errno );
+ perror_with_name (reason_for_failure);
+ }
+#endif
+
+ return tt_status;
+}
+
+
+/* This function simply calls ttrace_wait with the given arguments.
+ * It exists so that all calls to ttrace_wait are isolated.
+ *
+ * No "raw" calls to ttrace_wait should exist elsewhere.
+ */
+static int
+call_real_ttrace_wait( pid, tid, option, tsp, tsp_size )
+ int pid;
+ lwpid_t tid;
+ ttwopt_t option;
+ ttstate_t *tsp;
+ size_t tsp_size;
+{
+ int ttw_status;
+ thread_info * tinfo = NULL;
+
+ errno = 0;
+ ttw_status = ttrace_wait (pid, tid, option, tsp, tsp_size);
+
+ if (errno) {
+#ifdef THREAD_DEBUG
+ if( debug_on )
+ printf( "TW fail with pid %d, tid %d \n", pid, tid );
+#endif
+
+ perror_with_name ("ttrace wait");
+ }
+
+ return ttw_status;
+}
+
+
+/* A process may have one or more kernel threads, of which all or
+ none may be stopped. This function returns the ID of the first
+ kernel thread in a stopped state, or 0 if none are stopped.
+
+ This function can be used with get_process_next_stopped_thread_id
+ to iterate over the IDs of all stopped threads of this process.
+ */
+static lwpid_t
+get_process_first_stopped_thread_id (pid, thread_state)
+ int pid;
+ ttstate_t * thread_state;
+{
+ int tt_status;
+
+ tt_status = call_real_ttrace (
+ TT_PROC_GET_FIRST_LWP_STATE,
+ (pid_t) pid,
+ (lwpid_t) TT_NIL,
+ (TTRACE_ARG_TYPE) thread_state,
+ (TTRACE_ARG_TYPE) sizeof (*thread_state),
+ TT_NIL);
+
+ if (errno) {
+ if( errno == EPROTO) {
+ /* This is an error we can handle: there isn't any stopped
+ * thread. This happens when we're re-starting the application
+ * and it has only one thread. GET_NEXT handles the case of
+ * no more stopped threads well; GET_FIRST doesn't. (A ttrace
+ * "feature".)
+ */
+ tt_status = 1;
+ errno = 0;
+ return 0;
+ }
+ else
+ perror_with_name ("ttrace");
+ }
+
+ if( tt_status < 0 )
+ /* Failed somehow.
+ */
+ return 0;
+
+ return thread_state->tts_lwpid;
+}
+
+
+/* This function returns the ID of the "next" kernel thread in a
+ stopped state, or 0 if there are none. "Next" refers to the
+ thread following that of the last successful call to this
+ function or to get_process_first_stopped_thread_id, using
+ the value of thread_state returned by that call.
+
+ This function can be used with get_process_first_stopped_thread_id
+ to iterate over the IDs of all stopped threads of this process.
+ */
+static lwpid_t
+get_process_next_stopped_thread_id (pid, thread_state)
+ int pid;
+ ttstate_t * thread_state;
+{
+ int tt_status;
+
+ tt_status = call_real_ttrace (
+ TT_PROC_GET_NEXT_LWP_STATE,
+ (pid_t) pid,
+ (lwpid_t) TT_NIL,
+ (TTRACE_ARG_TYPE) thread_state,
+ (TTRACE_ARG_TYPE) sizeof (*thread_state),
+ TT_NIL);
+ if (errno)
+ perror_with_name ("ttrace");
+
+ if (tt_status < 0)
+ /* Failed
+ */
+ return 0;
+
+ else if( tt_status == 0 ) {
+ /* End of list, no next state. Don't return the
+ * tts_lwpid, as it's a meaningless "240".
+ *
+ * This is an HPUX "feature".
+ */
+ return 0;
+ }
+
+ return thread_state->tts_lwpid;
+}
+
+/* ??rehrauer: Eventually this function perhaps should be calling
+ pid_to_thread_id. However, that function currently does nothing
+ for HP-UX. Even then, I'm not clear whether that function
+ will return a "kernel" thread ID, or a "user" thread ID. If
+ the former, we can just call it here. If the latter, we must
+ map from the "user" tid to a "kernel" tid.
+
+ NOTE: currently not called.
+ */
+static lwpid_t
+get_active_tid_of_pid (pid)
+ int pid;
+{
+ ttstate_t thread_state;
+
+ return get_process_first_stopped_thread_id (pid, &thread_state);
+}
+
+/* This function returns 1 if tt_request is a ttrace request that
+ * operates upon all threads of a (i.e., the entire) process.
+ */
+int
+is_process_ttrace_request (tt_request)
+ ttreq_t tt_request;
+{
+ return IS_TTRACE_PROCREQ (tt_request);
+}
+
+
+/* This function translates a thread ttrace request into
+ * the equivalent process request for a one-thread process.
+ */
+static ttreq_t
+make_process_version( request )
+ ttreq_t request;
+{
+ if (!IS_TTRACE_REQ (request)) {
+ error( "Internal error, bad ttrace request made\n" );
+ return -1;
+ }
+
+ switch (request) {
+ case TT_LWP_STOP :
+ return TT_PROC_STOP;
+
+ case TT_LWP_CONTINUE :
+ return TT_PROC_CONTINUE;
+
+ case TT_LWP_GET_EVENT_MASK :
+ return TT_PROC_GET_EVENT_MASK;
+
+ case TT_LWP_SET_EVENT_MASK :
+ return TT_PROC_SET_EVENT_MASK;
+
+ case TT_LWP_SINGLE :
+ case TT_LWP_RUREGS :
+ case TT_LWP_WUREGS :
+ case TT_LWP_GET_STATE :
+ return -1; /* No equivalent */
+
+ default :
+ return request;
+ }
+}
+
+
+/* This function translates the "pid" used by the rest of
+ * gdb to a real pid and a tid. It then calls "call_real_ttrace"
+ * with the given arguments.
+ *
+ * In general, other parts of this module should call this
+ * function when they are dealing with external users, who only
+ * have tids to pass (but they call it "pid" for historical
+ * reasons).
+ */
+static int
+call_ttrace( request, gdb_tid, addr, data, addr2 )
+ ttreq_t request;
+ int gdb_tid;
+ TTRACE_ARG_TYPE addr, data, addr2;
+{
+ lwpid_t real_tid;
+ int real_pid;
+ ttreq_t new_request;
+ int tt_status;
+ char reason_for_failure [100]; /* Arbitrary size, should be big enough. */
+
+#ifdef THREAD_DEBUG
+ int is_interesting = 0;
+
+ if( TT_LWP_RUREGS == request ) {
+ is_interesting = 1; /* Adjust code here as desired */
+ }
+
+ if( is_interesting && 0 && debug_on ) {
+ if( !is_process_ttrace_request( request )) {
+ printf( "TT: Thread request, tid is %d", gdb_tid );
+ printf( "== SINGLE at %x", addr );
+ }
+ else {
+ printf( "TT: Process request, tid is %d\n", gdb_tid );
+ printf( "==! SINGLE at %x", addr );
+ }
+ }
+#endif
+
+ /* The initial SETTRC and SET_EVENT_MASK calls (and all others
+ * which happen before any threads get set up) should go
+ * directly to "call_real_ttrace", so they don't happen here.
+ *
+ * But hardware watchpoints do a SET_EVENT_MASK, so we can't
+ * rule them out....
+ */
+#ifdef THREAD_DEBUG
+ if( request == TT_PROC_SETTRC && debug_on )
+ printf( "Unexpected call for TT_PROC_SETTRC\n" );
+#endif
+
+ /* Sometimes we get called with a bogus tid (e.g., if a
+ * thread has terminated, we return 0; inftarg later asks
+ * whether the thread has exited/forked/vforked).
+ */
+ if( gdb_tid == 0 )
+ {
+ errno = ESRCH; /* ttrace's response would probably be "No such process". */
+ return -1;
+ }
+
+ /* All other cases should be able to expect that there are
+ * thread records.
+ */
+ if( !any_thread_records()) {
+#ifdef THREAD_DEBUG
+ if( debug_on )
+ warning ("No thread records for ttrace call");
+#endif
+ errno = ESRCH; /* ttrace's response would be "No such process". */
+ return -1;
+ }
+
+ /* OK, now the task is to translate the incoming tid into
+ * a pid/tid pair.
+ */
+ real_tid = map_from_gdb_tid( gdb_tid );
+ real_pid = get_pid_for( real_tid );
+
+ /* Now check the result. "Real_pid" is NULL if our list
+ * didn't find it. We have some tricks we can play to fix
+ * this, however.
+ */
+ if( 0 == real_pid ) {
+ ttstate_t thread_state;
+
+#ifdef THREAD_DEBUG
+ if( debug_on )
+ printf( "No saved pid for tid %d\n", gdb_tid );
+#endif
+
+ if( is_process_ttrace_request( request )) {
+
+ /* Ok, we couldn't get a tid. Try to translate to
+ * the equivalent process operation. We expect this
+ * NOT to happen, so this is a desparation-type
+ * move. It can happen if there is an internal
+ * error and so no "wait()" call is ever done.
+ */
+ new_request = make_process_version( request );
+ if( new_request == -1 ) {
+
+#ifdef THREAD_DEBUG
+ if( debug_on )
+ printf( "...and couldn't make process version of thread operation\n" );
+#endif
+
+ /* Use hacky saved pid, which won't always be correct
+ * in the multi-process future. Use tid as thread,
+ * probably dooming this to failure. FIX!
+ */
+ if( saved_real_pid != 0 ) {
+#ifdef THREAD_DEBUG
+ if( debug_on )
+ printf( "...using saved pid %d\n", saved_real_pid );
+#endif
+
+ real_pid = saved_real_pid;
+ real_tid = gdb_tid;
+ }
+
+ else
+ error( "Unable to perform thread operation" );
+ }
+
+ else {
+ /* Sucessfully translated this to a process request,
+ * which needs no thread value.
+ */
+ real_pid = gdb_tid;
+ real_tid = 0;
+ request = new_request;
+
+#ifdef THREAD_DEBUG
+ if( debug_on ) {
+ printf( "Translated thread request to process request\n" );
+ if( saved_real_pid == 0 )
+ printf( "...but there's no saved pid\n" );
+
+ else {
+ if( gdb_tid != saved_real_pid )
+ printf( "...but have the wrong pid (%d rather than %d)\n",
+ gdb_tid, saved_real_pid );
+ }
+ }
+#endif
+ } /* Translated to a process request */
+ } /* Is a process request */
+
+ else {
+ /* We have to have a thread. Ooops.
+ */
+ error( "Thread request with no threads (%s)",
+ get_printable_name_of_ttrace_request( request ));
+ }
+ }
+
+ /* Ttrace doesn't like to see tid values on process requests,
+ * even if we have the right one.
+ */
+ if (is_process_ttrace_request (request)) {
+ real_tid = 0;
+ }
+
+#ifdef THREAD_DEBUG
+ if( is_interesting && 0 && debug_on ) {
+ printf( " now tid %d, pid %d\n", real_tid, real_pid );
+ printf( " request is %s\n", get_printable_name_of_ttrace_request (request));
+ }
+#endif
+
+ /* Finally, the (almost) real call.
+ */
+ tt_status = call_real_ttrace (request, real_pid, real_tid, addr, data, addr2);
+
+#ifdef THREAD_DEBUG
+ if(is_interesting && debug_on ) {
+ if( !TT_OK( tt_status, errno )
+ && !(tt_status == 0 & errno == 0))
+ printf( " got error (errno==%d, status==%d)\n", errno, tt_status );
+ }
+#endif
+
+ return tt_status;
+}
+
+
+/* Stop all the threads of a process.
+ *
+ * NOTE: use of TT_PROC_STOP can cause a thread with a real event
+ * to get a TTEVT_NONE event, discarding the old event. Be
+ * very careful, and only call TT_PROC_STOP when you mean it!
+ */
+static void
+stop_all_threads_of_process( real_pid )
+ pid_t real_pid;
+{
+ int ttw_status;
+
+ ttw_status = call_real_ttrace (TT_PROC_STOP,
+ (pid_t) real_pid,
+ (lwpid_t) TT_NIL,
+ (TTRACE_ARG_TYPE) TT_NIL,
+ (TTRACE_ARG_TYPE) TT_NIL,
+ TT_NIL );
+ if (errno)
+ perror_with_name ("ttrace stop of other threads");
+}
+
+
+/* Under some circumstances, it's unsafe to attempt to stop, or even
+ query the state of, a process' threads.
+
+ In ttrace-based HP-UX, an example is a vforking child process. The
+ vforking parent and child are somewhat fragile, w/r/t what we can do
+ what we can do to them with ttrace, until after the child exits or
+ execs, or until the parent's vfork event is delivered. Until that
+ time, we must not try to stop the process' threads, or inquire how
+ many there are, or even alter its data segments, or it typically dies
+ with a SIGILL. Sigh.
+
+ This function returns 1 if this stopped process, and the event that
+ we're told was responsible for its current stopped state, cannot safely
+ have its threads examined.
+ */
+#define CHILD_VFORKED(evt,pid) \
+ (((evt) == TTEVT_VFORK) && ((pid) != inferior_pid))
+#define CHILD_URPED(evt,pid) \
+ ((((evt) == TTEVT_EXEC) || ((evt) == TTEVT_EXIT)) && ((pid) != vforking_child_pid))
+#define PARENT_VFORKED(evt,pid) \
+ (((evt) == TTEVT_VFORK) && ((pid) == inferior_pid))
+
+static int
+can_touch_threads_of_process (pid, stopping_event)
+ int pid;
+ ttevents_t stopping_event;
+{
+ if (CHILD_VFORKED (stopping_event, pid))
+ {
+ vforking_child_pid = pid;
+ vfork_in_flight = 1;
+ }
+
+ else if (vfork_in_flight &&
+ (PARENT_VFORKED (stopping_event, pid) ||
+ CHILD_URPED (stopping_event, pid)))
+ {
+ vfork_in_flight = 0;
+ vforking_child_pid = 0;
+ }
+
+ return ! vfork_in_flight;
+}
+
+
+/* If we can find an as-yet-unhandled thread state of a
+ * stopped thread of this process return 1 and set "tsp".
+ * Return 0 if we can't.
+ *
+ * If this function is used when the threads of PIS haven't
+ * been stopped, undefined behaviour is guaranteed!
+ */
+static int
+select_stopped_thread_of_process (pid, tsp)
+ int pid;
+ ttstate_t * tsp;
+{
+ lwpid_t candidate_tid, tid;
+ ttstate_t candidate_tstate, tstate;
+
+ /* If we're not allowed to touch the process now, then just
+ * return the current value of *TSP.
+ *
+ * This supports "vfork". It's ok, really, to double the
+ * current event (the child EXEC, we hope!).
+ */
+ if (! can_touch_threads_of_process (pid, tsp->tts_event))
+ return 1;
+
+ /* Decide which of (possibly more than one) events to
+ * return as the first one. We scan them all so that
+ * we always return the result of a fake-step first.
+ */
+ candidate_tid = 0;
+ for (tid = get_process_first_stopped_thread_id (pid, &tstate);
+ tid != 0;
+ tid = get_process_next_stopped_thread_id (pid, &tstate))
+ {
+ /* TTEVT_NONE events are uninteresting to our clients. They're
+ * an artifact of our "stop the world" model--the thread is
+ * stopped because we stopped it.
+ */
+ if (tstate.tts_event == TTEVT_NONE) {
+ set_handled( pid, tstate.tts_lwpid );
+ }
+
+ /* Did we just single-step a single thread, without letting any
+ * of the others run? Is this an event for that thread?
+ *
+ * If so, we believe our client would prefer to see this event
+ * over any others. (Typically the client wants to just push
+ * one thread a little farther forward, and then go around
+ * checking for what all threads are doing.)
+ */
+ else if (doing_fake_step && (tstate.tts_lwpid == fake_step_tid))
+ {
+#ifdef WAIT_BUFFER_DEBUG
+ /* It's possible here to see either a SIGTRAP (due to
+ * successful completion of a step) or a SYSCALL_ENTRY
+ * (due to a step completion with active hardware
+ * watchpoints).
+ */
+ if( debug_on )
+ printf( "Ending fake step with tid %d, state %s\n",
+ tstate.tts_lwpid,
+ get_printable_name_of_ttrace_event( tstate.tts_event ));
+#endif
+
+ /* Remember this one, and throw away any previous
+ * candidate.
+ */
+ candidate_tid = tstate.tts_lwpid;
+ candidate_tstate = tstate;
+ }
+
+#ifdef FORGET_DELETED_BPTS
+
+ /* We can't just do this, as if we do, and then wind
+ * up the loop with no unhandled events, we need to
+ * handle that case--the appropriate reaction is to
+ * just continue, but there's no easy way to do that.
+ *
+ * Better to put this in the ttrace_wait call--if, when
+ * we fake a wait, we update our events based on the
+ * breakpoint_here_pc call and find there are no more events,
+ * then we better continue and so on.
+ *
+ * Or we could put it in the next/continue fake.
+ * But it has to go in the buffering code, not in the
+ * real go/wait code.
+ */
+ else if( (TTEVT_SIGNAL == tstate.tts_event)
+ && (5 == tstate.tts_u.tts_signal.tts_signo)
+ && (0 != get_raw_pc( tstate.tts_lwpid ))
+ && ! breakpoint_here_p( get_raw_pc( tstate.tts_lwpid )) ) {
+ /*
+ * If the user deleted a breakpoint while this
+ * breakpoint-hit event was buffered, we can forget
+ * it now.
+ */
+#ifdef WAIT_BUFFER_DEBUG
+ if( debug_on )
+ printf( "Forgetting deleted bp hit for thread %d\n",
+ tstate.tts_lwpid );
+#endif
+
+ set_handled( pid, tstate.tts_lwpid );
+ }
+#endif
+
+ /* Else, is this the first "unhandled" event? If so,
+ * we believe our client wants to see it (if we don't
+ * see a fake-step later on in the scan).
+ */
+ else if( !was_handled( tstate.tts_lwpid ) && candidate_tid == 0 ) {
+ candidate_tid = tstate.tts_lwpid;
+ candidate_tstate = tstate;
+ }
+
+ /* This is either an event that has already been "handled",
+ * and thus we believe is uninteresting to our client, or we
+ * already have a candidate event. Ignore it...
+ */
+ }
+
+ /* What do we report?
+ */
+ if( doing_fake_step ) {
+ if( candidate_tid == fake_step_tid ) {
+ /* Fake step.
+ */
+ tstate = candidate_tstate;
+ }
+ else {
+ warning( "Internal error: fake-step failed to complete." );
+ return 0;
+ }
+ }
+ else if( candidate_tid != 0 ) {
+ /* Found a candidate unhandled event.
+ */
+ tstate = candidate_tstate;
+ }
+ else if( tid != 0 ) {
+ warning( "Internal error in call of ttrace_wait." );
+ return 0;
+ }
+ else {
+ warning ("Internal error: no unhandled thread event to select");
+ return 0;
+ }
+
+ copy_ttstate_t (tsp, &tstate);
+ return 1;
+} /* End of select_stopped_thread_of_process */
+
+#ifdef PARANOIA
+/* Check our internal thread data against the real thing.
+ */
+static void
+check_thread_consistency( real_pid )
+ pid_t real_pid;
+{
+ int tid; /* really lwpid_t */
+ ttstate_t tstate;
+ thread_info *p;
+
+ /* Spin down the O/S list of threads, checking that they
+ * match what we've got.
+ */
+ for (tid = get_process_first_stopped_thread_id( real_pid, &tstate );
+ tid != 0;
+ tid = get_process_next_stopped_thread_id( real_pid, &tstate )) {
+
+ p = find_thread_info( tid );
+
+ if( NULL == p ) {
+ warning( "No internal thread data for thread %d.", tid );
+ continue;
+ }
+
+ if( !p->seen ) {
+ warning( "Inconsistent internal thread data for thread %d.", tid );
+ }
+
+ if( p->terminated ) {
+ warning( "Thread %d is not terminated, internal error.", tid );
+ continue;
+ }
+
+
+#define TT_COMPARE( fld ) \
+ tstate.fld != p->last_stop_state.fld
+
+ if( p->have_state ) {
+ if( TT_COMPARE( tts_pid )
+ || TT_COMPARE( tts_lwpid )
+ || TT_COMPARE( tts_user_tid )
+ || TT_COMPARE( tts_event )
+ || TT_COMPARE( tts_flags )
+ || TT_COMPARE( tts_scno )
+ || TT_COMPARE( tts_scnargs )) {
+ warning( "Internal thread data for thread %d is wrong.", tid );
+ continue;
+ }
+ }
+ }
+}
+#endif /* PARANOIA */
+
+
+/* This function wraps calls to "call_real_ttrace_wait" so
+ * that a actual wait is only done when all pending events
+ * have been reported.
+ *
+ * Note that typically it is called with a pid of "0", i.e.
+ * the "don't care" value.
+ *
+ * Return value is the status of the pseudo wait.
+ */
+static int
+call_ttrace_wait( pid, option, tsp, tsp_size )
+ int pid;
+ ttwopt_t option;
+ ttstate_t *tsp;
+ size_t tsp_size;
+{
+ /* This holds the actual, for-real, true process ID.
+ */
+ static int real_pid;
+
+ /* As an argument to ttrace_wait, zero pid
+ * means "Any process", and zero tid means
+ * "Any thread of the specified process".
+ */
+ int wait_pid = 0;
+ lwpid_t wait_tid = 0;
+ lwpid_t real_tid;
+
+ int ttw_status = 0; /* To be returned */
+
+ thread_info * tinfo = NULL;
+
+ if( pid != 0 ) {
+ /* Unexpected case.
+ */
+#ifdef THREAD_DEBUG
+ if( debug_on )
+ printf( "TW: Pid to wait on is %d\n", pid );
+#endif
+
+ if( !any_thread_records())
+ error( "No thread records for ttrace call w. specific pid" );
+
+ /* OK, now the task is to translate the incoming tid into
+ * a pid/tid pair.
+ */
+ real_tid = map_from_gdb_tid( pid );
+ real_pid = get_pid_for( real_tid );
+#ifdef THREAD_DEBUG
+ if( debug_on )
+ printf( "==TW: real pid %d, real tid %d\n", real_pid, real_tid );
+#endif
+ }
+
+
+ /* Sanity checks and set-up.
+ * Process State
+ *
+ * Stopped Running Fake-step (v)Fork
+ * \________________________________________
+ * |
+ * No buffered events | error wait wait wait
+ * |
+ * Buffered events | debuffer error wait debuffer (?)
+ *
+ */
+ if( more_events_left == 0 ) {
+
+ if( process_state == RUNNING ) {
+ /* OK--normal call of ttrace_wait with no buffered events.
+ */
+ ;
+ }
+ else if( process_state == FAKE_STEPPING ) {
+ /* Ok--call of ttrace_wait to support
+ * fake stepping with no buffered events.
+ *
+ * But we better be fake-stepping!
+ */
+ if( !doing_fake_step ) {
+ warning( "Inconsistent thread state." );
+ }
+ }
+ else if( (process_state == FORKING)
+ || (process_state == VFORKING)) {
+ /* Ok--there are two processes, so waiting
+ * for the second while the first is stopped
+ * is ok. Handled bits stay as they were.
+ */
+ ;
+ }
+ else if( process_state == STOPPED ) {
+ warning( "Process not running at wait call." );
+ }
+ else
+ /* No known state.
+ */
+ warning( "Inconsistent process state." );
+ }
+
+ else {
+ /* More events left
+ */
+ if( process_state == STOPPED ) {
+ /* OK--buffered events being unbuffered.
+ */
+ ;
+ }
+ else if( process_state == RUNNING ) {
+ /* An error--shouldn't have buffered events
+ * when running.
+ */
+ warning( "Trying to continue with buffered events:" );
+ }
+ else if( process_state == FAKE_STEPPING ) {
+ /*
+ * Better be fake-stepping!
+ */
+ if( !doing_fake_step ) {
+ warning( "Losing buffered thread events!\n" );
+ }
+ }
+ else if( (process_state == FORKING)
+ || (process_state == VFORKING)) {
+ /* Ok--there are two processes, so waiting
+ * for the second while the first is stopped
+ * is ok. Handled bits stay as they were.
+ */
+ ;
+ }
+ else
+ warning( "Process in unknown state with buffered events." );
+ }
+
+ /* Sometimes we have to wait for a particular thread
+ * (if we're stepping over a bpt). In that case, we
+ * _know_ it's going to complete the single-step we
+ * asked for (because we're only doing the step under
+ * certain very well-understood circumstances), so it
+ * can't block.
+ */
+ if( doing_fake_step ) {
+ wait_tid = fake_step_tid;
+ wait_pid = get_pid_for( fake_step_tid );
+
+#ifdef WAIT_BUFFER_DEBUG
+ if( debug_on )
+ printf( "Doing a wait after a fake-step for %d, pid %d\n",
+ wait_tid, wait_pid );
+#endif
+ }
+
+ if( more_events_left == 0 /* No buffered events, need real ones. */
+ || process_state != STOPPED ) {
+ /* If there are no buffered events, and so we need
+ * real ones, or if we are FORKING, VFORKING,
+ * FAKE_STEPPING or RUNNING, and thus have to do
+ * a real wait, then do a real wait.
+ */
+
+#ifdef WAIT_BUFFER_DEBUG
+ /* Normal case... */
+ if( debug_on )
+ printf( "TW: do it for real; pid %d, tid %d\n", wait_pid, wait_tid );
+#endif
+
+ /* The actual wait call.
+ */
+ ttw_status = call_real_ttrace_wait( wait_pid, wait_tid, option, tsp, tsp_size);
+
+ /* Note that the routines we'll call will be using "call_real_ttrace",
+ * not "call_ttrace", and thus need the real pid rather than the pseudo-tid
+ * the rest of the world uses (which is actually the tid).
+ */
+ real_pid = tsp->tts_pid;
+
+ /* For most events: Stop the world!
+ *
+ * It's sometimes not safe to stop all threads of a process.
+ * Sometimes it's not even safe to ask for the thread state
+ * of a process!
+ */
+ if (can_touch_threads_of_process (real_pid, tsp->tts_event))
+ {
+ /* If we're really only stepping a single thread, then don't
+ * try to stop all the others -- we only do this single-stepping
+ * business when all others were already stopped...and the stop
+ * would mess up other threads' events.
+ *
+ * Similiarly, if there are other threads with events,
+ * don't do the stop.
+ */
+ if( !doing_fake_step ) {
+ if( more_events_left > 0 )
+ warning( "Internal error in stopping process" );
+
+ stop_all_threads_of_process (real_pid);
+
+ /* At this point, we could scan and update_thread_list(),
+ * and only use the local list for the rest of the
+ * module! We'd get rid of the scans in the various
+ * continue routines (adding one in attach). It'd
+ * be great--UPGRADE ME!
+ */
+ }
+ }
+
+#ifdef PARANOIA
+ else if( debug_on ) {
+ if( more_events_left > 0 )
+ printf( "== Can't stop process; more events!\n" );
+ else
+ printf( "== Can't stop process!\n" );
+ }
+#endif
+
+ process_state = STOPPED;
+
+#ifdef WAIT_BUFFER_DEBUG
+ if( debug_on )
+ printf( "Process set to STOPPED\n" );
+#endif
+ }
+
+ else {
+ /* Fake a call to ttrace_wait. The process must be
+ * STOPPED, as we aren't going to do any wait.
+ */
+#ifdef WAIT_BUFFER_DEBUG
+ if( debug_on )
+ printf( "TW: fake it\n" );
+#endif
+
+ if( process_state != STOPPED ) {
+ warning( "Process not stopped at wait call, in state '%s'.\n",
+ get_printable_name_of_process_state( process_state ));
+ }
+
+ if( doing_fake_step )
+ error( "Internal error in stepping over breakpoint" );
+
+ ttw_status = 0; /* Faking it is always successful! */
+ } /* End of fake or not? if */
+
+ /* Pick an event to pass to our caller. Be paranoid.
+ */
+ if( !select_stopped_thread_of_process( real_pid, tsp ))
+ warning( "Can't find event, using previous event." );
+
+ else if( tsp->tts_event == TTEVT_NONE )
+ warning( "Internal error: no thread has a real event." );
+
+ else if( doing_fake_step ) {
+ if( fake_step_tid != tsp->tts_lwpid )
+ warning( "Internal error in stepping over breakpoint." );
+
+ /* This wait clears the (current) fake-step if there was one.
+ */
+ doing_fake_step = 0;
+ fake_step_tid = 0;
+ }
+
+ /* We now have a correct tsp and ttw_status for the thread
+ * which we want to report. So it's "handled"! This call
+ * will add it to our list if it's not there already.
+ */
+ set_handled( real_pid, tsp->tts_lwpid );
+
+ /* Save a copy of the ttrace state of this thread, in our local
+ thread descriptor.
+
+ This caches the state. The implementation of queries like
+ target_has_execd can then use this cached state, rather than
+ be forced to make an explicit ttrace call to get it.
+
+ (Guard against the condition that this is the first time we've
+ waited on, i.e., seen this thread, and so haven't yet entered
+ it into our list of threads.)
+ */
+ tinfo = find_thread_info (tsp->tts_lwpid);
+ if (tinfo != NULL) {
+ copy_ttstate_t (&tinfo->last_stop_state, tsp);
+ tinfo->have_state = 1;
+ }
+
+ return ttw_status;
+} /* call_ttrace_wait */
+
+#if defined(CHILD_REPORTED_EXEC_EVENTS_PER_EXEC_CALL)
+int
+child_reported_exec_events_per_exec_call ()
+{
+ return 1; /* ttrace reports the event once per call. */
+}
+#endif
+
+
+
+/* Our implementation of hardware watchpoints involves making memory
+ pages write-protected. We must remember a page's original permissions,
+ and we must also know when it is appropriate to restore a page's
+ permissions to its original state.
+
+ We use a "dictionary" of hardware-watched pages to do this. Each
+ hardware-watched page is recorded in the dictionary. Each page's
+ dictionary entry contains the original permissions and a reference
+ count. Pages are hashed into the dictionary by their start address.
+
+ When hardware watchpoint is set on page X for the first time, page X
+ is added to the dictionary with a reference count of 1. If other
+ hardware watchpoints are subsequently set on page X, its reference
+ count is incremented. When hardware watchpoints are removed from
+ page X, its reference count is decremented. If a page's reference
+ count drops to 0, it's permissions are restored and the page's entry
+ is thrown out of the dictionary.
+ */
+typedef struct memory_page {
+ CORE_ADDR page_start;
+ int reference_count;
+ int original_permissions;
+ struct memory_page * next;
+ struct memory_page * previous;
+} memory_page_t;
+
+#define MEMORY_PAGE_DICTIONARY_BUCKET_COUNT 128
+
+static struct {
+ LONGEST page_count;
+ int page_size;
+ int page_protections_allowed;
+ /* These are just the heads of chains of actual page descriptors. */
+ memory_page_t buckets [MEMORY_PAGE_DICTIONARY_BUCKET_COUNT];
+} memory_page_dictionary;
+
+
+static void
+require_memory_page_dictionary ()
+{
+ int i;
+
+ /* Is the memory page dictionary ready for use? If so, we're done. */
+ if (memory_page_dictionary.page_count >= (LONGEST) 0)
+ return;
+
+ /* Else, initialize it. */
+ memory_page_dictionary.page_count = (LONGEST) 0;
+
+ for (i=0; i<MEMORY_PAGE_DICTIONARY_BUCKET_COUNT; i++)
+ {
+ memory_page_dictionary.buckets[i].page_start = (CORE_ADDR) 0;
+ memory_page_dictionary.buckets[i].reference_count = 0;
+ memory_page_dictionary.buckets[i].next = NULL;
+ memory_page_dictionary.buckets[i].previous = NULL;
+ }
+}
+
+
+static void
+retire_memory_page_dictionary ()
+{
+ memory_page_dictionary.page_count = (LONGEST) -1;
+}
+
+
+/* Write-protect the memory page that starts at this address.
+
+ Returns the original permissions of the page.
+ */
+static int
+write_protect_page (pid, page_start)
+ int pid;
+ CORE_ADDR page_start;
+{
+ int tt_status;
+ int original_permissions;
+ int new_permissions;
+
+ tt_status = call_ttrace (TT_PROC_GET_MPROTECT,
+ pid,
+ (TTRACE_ARG_TYPE) page_start,
+ TT_NIL,
+ (TTRACE_ARG_TYPE) &original_permissions);
+ if (errno || (tt_status < 0))
+ {
+ return 0; /* What else can we do? */
+ }
+
+ /* We'll also write-protect the page now, if that's allowed. */
+ if (memory_page_dictionary.page_protections_allowed)
+ {
+ new_permissions = original_permissions & ~PROT_WRITE;
+ tt_status = call_ttrace (TT_PROC_SET_MPROTECT,
+ pid,
+ (TTRACE_ARG_TYPE) page_start,
+ (TTRACE_ARG_TYPE) memory_page_dictionary.page_size,
+ (TTRACE_ARG_TYPE) new_permissions);
+ if (errno || (tt_status < 0))
+ {
+ return 0; /* What else can we do? */
+ }
+ }
+
+ return original_permissions;
+}
+
+
+/* Unwrite-protect the memory page that starts at this address, restoring
+ (what we must assume are) its original permissions.
+ */
+static void
+unwrite_protect_page (pid, page_start, original_permissions)
+ int pid;
+ CORE_ADDR page_start;
+ int original_permissions;
+{
+ int tt_status;
+
+ tt_status = call_ttrace (TT_PROC_SET_MPROTECT,
+ pid,
+ (TTRACE_ARG_TYPE) page_start,
+ (TTRACE_ARG_TYPE) memory_page_dictionary.page_size,
+ (TTRACE_ARG_TYPE) original_permissions);
+ if (errno || (tt_status < 0))
+ {
+ return; /* What else can we do? */
+ }
+}
+
+
+/* Memory page-protections are used to implement "hardware" watchpoints
+ on HP-UX.
+
+ For every memory page that is currently being watched (i.e., that
+ presently should be write-protected), write-protect it.
+ */
+void
+hppa_enable_page_protection_events (pid)
+ int pid;
+{
+ int bucket;
+
+ memory_page_dictionary.page_protections_allowed = 1;
+
+ for (bucket=0; bucket<MEMORY_PAGE_DICTIONARY_BUCKET_COUNT; bucket++)
+ {
+ memory_page_t * page;
+
+ page = memory_page_dictionary.buckets[bucket].next;
+ while (page != NULL)
+ {
+ page->original_permissions = write_protect_page (pid, page->page_start);
+ page = page->next;
+ }
+ }
+}
+
+
+/* Memory page-protections are used to implement "hardware" watchpoints
+ on HP-UX.
+
+ For every memory page that is currently being watched (i.e., that
+ presently is or should be write-protected), un-write-protect it.
+ */
+void
+hppa_disable_page_protection_events (pid)
+ int pid;
+{
+ int bucket;
+
+ for (bucket=0; bucket<MEMORY_PAGE_DICTIONARY_BUCKET_COUNT; bucket++)
+ {
+ memory_page_t * page;
+
+ page = memory_page_dictionary.buckets[bucket].next;
+ while (page != NULL)
+ {
+ unwrite_protect_page (pid, page->page_start, page->original_permissions);
+ page = page->next;
+ }
+ }
+
+ memory_page_dictionary.page_protections_allowed = 0;
+}
+
+/* Count the number of outstanding events. At this
+ * point, we have selected one thread and its event
+ * as the one to be "reported" upwards to core gdb.
+ * That thread is already marked as "handled".
+ *
+ * Note: we could just scan our own thread list. FIXME!
+ */
+static int
+count_unhandled_events( real_pid, real_tid )
+ int real_pid;
+ lwpid_t real_tid;
+{
+ ttstate_t tstate;
+ lwpid_t ttid;
+ int events_left;
+
+ /* Ok, find out how many threads have real events to report.
+ */
+ events_left = 0;
+ ttid = get_process_first_stopped_thread_id( real_pid, &tstate );
+
+#ifdef THREAD_DEBUG
+ if( debug_on ) {
+ if( ttid == 0 )
+ printf( "Process %d has no threads\n", real_pid );
+ else
+ printf( "Process %d has these threads:\n", real_pid );
+ }
+#endif
+
+ while (ttid > 0 ) {
+ if( tstate.tts_event != TTEVT_NONE
+ && !was_handled( ttid )) {
+ /* TTEVT_NONE implies we just stopped it ourselves
+ * because we're the stop-the-world guys, so it's
+ * not an event from our point of view.
+ *
+ * If "was_handled" is true, this is an event we
+ * already handled, so don't count it.
+ *
+ * Note that we don't count the thread with the
+ * currently-reported event, as it's already marked
+ * as handled.
+ */
+ events_left++;
+ }
+
+#if defined( THREAD_DEBUG ) || defined( WAIT_BUFFER_DEBUG )
+ if( debug_on ) {
+ if( ttid == real_tid )
+ printf( "*" ); /* Thread we're reporting */
+ else
+ printf( " " );
+
+ if( tstate.tts_event != TTEVT_NONE )
+ printf( "+" ); /* Thread with a real event */
+ else
+ printf( " " );
+
+ if( was_handled( ttid ))
+ printf( "h" ); /* Thread has been handled */
+ else
+ printf( " " );
+
+ printf( " %d, with event %s", ttid,
+ get_printable_name_of_ttrace_event( tstate.tts_event ));
+
+ if( tstate.tts_event == TTEVT_SIGNAL
+ && 5 == tstate.tts_u.tts_signal.tts_signo ) {
+ CORE_ADDR pc_val;
+
+ pc_val = get_raw_pc( ttid );
+
+ if( pc_val > 0 )
+ printf( " breakpoint at 0x%x\n", pc_val );
+ else
+ printf( " bpt, can't fetch pc.\n" );
+ }
+ else
+ printf( "\n" );
+ }
+#endif
+
+ ttid = get_process_next_stopped_thread_id (real_pid, &tstate);
+ }
+
+#if defined( THREAD_DEBUG ) || defined( WAIT_BUFFER_DEBUG )
+ if( debug_on )
+ if( events_left > 0 )
+ printf( "There are thus %d pending events\n", events_left );
+#endif
+
+ return events_left;
+}
+
+/* This function is provided as a sop to clients that are calling
+ * ptrace_wait to wait for a process to stop. (see the
+ * implementation of child_wait.) Return value is the pid for
+ * the event that ended the wait.
+ *
+ * Note: used by core gdb and so uses the pseudo-pid (really tid).
+ */
+int
+ptrace_wait (pid, status)
+ int pid;
+ int *status;
+{
+ ttstate_t tsp;
+ int ttwait_return;
+ int real_pid;
+ ttstate_t state;
+ lwpid_t real_tid;
+ int return_pid;
+
+ /* The ptrace implementation of this also ignores pid.
+ */
+ *status = 0;
+
+ ttwait_return = call_ttrace_wait( 0, TTRACE_WAITOK, &tsp, sizeof (tsp) );
+ if (ttwait_return < 0)
+ {
+ /* ??rehrauer: It appears that if our inferior exits and we
+ haven't asked for exit events, that we're not getting any
+ indication save a negative return from ttrace_wait and an
+ errno set to ESRCH?
+ */
+ if (errno == ESRCH)
+ {
+ *status = 0; /* WIFEXITED */
+ return inferior_pid;
+ }
+
+ warning( "Call of ttrace_wait returned with errno %d.",
+ errno );
+ *status = ttwait_return;
+ return inferior_pid;
+ }
+
+ real_pid = tsp.tts_pid;
+ real_tid = tsp.tts_lwpid;
+
+ /* One complication is that the "tts_event" structure has
+ * a set of flags, and more than one can be set. So we
+ * either have to force an order (as we do here), or handle
+ * more than one flag at a time.
+ */
+ if (tsp.tts_event & TTEVT_LWP_CREATE) {
+
+ /* Unlike what you might expect, this event is reported in
+ * the _creating_ thread, and the _created_ thread (whose tid
+ * we have) is still running. So we have to stop it. This
+ * has already been done in "call_ttrace_wait", but should we
+ * ever abandon the "stop-the-world" model, here's the command
+ * to use:
+ *
+ * call_ttrace( TT_LWP_STOP, real_tid, TT_NIL, TT_NIL, TT_NIL );
+ *
+ * Note that this would depend on being called _after_ "add_tthread"
+ * below for the tid-to-pid translation to be done in "call_ttrace".
+ */
+
+#ifdef THREAD_DEBUG
+ if( debug_on )
+ printf( "New thread: pid %d, tid %d, creator tid %d\n",
+ real_pid, tsp.tts_u.tts_thread.tts_target_lwpid,
+ real_tid );
+#endif
+
+ /* Now we have to return the tid of the created thread, not
+ * the creating thread, or "wait_for_inferior" won't know we
+ * have a new "process" (thread). Plus we should record it
+ * right, too.
+ */
+ real_tid = tsp.tts_u.tts_thread.tts_target_lwpid;
+
+ add_tthread( real_pid, real_tid );
+ }
+
+ else if( (tsp.tts_event & TTEVT_LWP_TERMINATE )
+ || (tsp.tts_event & TTEVT_LWP_EXIT) ) {
+
+#ifdef THREAD_DEBUG
+ if( debug_on )
+ printf( "Thread dies: %d\n", real_tid );
+#endif
+
+ del_tthread( real_tid );
+ }
+
+ else if (tsp.tts_event & TTEVT_EXEC) {
+
+#ifdef THREAD_DEBUG
+ if( debug_on )
+ printf( "Pid %d has zero'th thread %d; inferior pid is %d\n",
+ real_pid, real_tid, inferior_pid );
+#endif
+
+ add_tthread( real_pid, real_tid );
+ }
+
+#ifdef THREAD_DEBUG
+ else if( debug_on ) {
+ printf( "Process-level event %s, using tid %d\n",
+ get_printable_name_of_ttrace_event( tsp.tts_event ),
+ real_tid );
+
+ /* OK to do this, as "add_tthread" won't add
+ * duplicate entries. Also OK not to do it,
+ * as this event isn't one which can change the
+ * thread state.
+ */
+ add_tthread( real_pid, real_tid );
+ }
+#endif
+
+
+ /* How many events are left to report later?
+ * In a non-stop-the-world model, this isn't needed.
+ *
+ * Note that it's not always safe to query the thread state of a process,
+ * which is what count_unhandled_events does. (If unsafe, we're left with
+ * no other resort than to assume that no more events remain...)
+ */
+ if (can_touch_threads_of_process (real_pid, tsp.tts_event))
+ more_events_left = count_unhandled_events( real_pid, real_tid );
+
+ else {
+ if( more_events_left > 0 )
+ warning( "Vfork or fork causing loss of %d buffered events.",
+ more_events_left );
+
+ more_events_left = 0;
+ }
+
+ /* Attempt to translate the ttrace_wait-returned status into the
+ ptrace equivalent.
+
+ ??rehrauer: This is somewhat fragile. We really ought to rewrite
+ clients that expect to pick apart a ptrace wait status, to use
+ something a little more abstract.
+ */
+ if ( (tsp.tts_event & TTEVT_EXEC)
+ || (tsp.tts_event & TTEVT_FORK)
+ || (tsp.tts_event & TTEVT_VFORK))
+ {
+ /* Forks come in pairs (parent and child), so core gdb
+ * will do two waits. Be ready to notice this.
+ */
+ if (tsp.tts_event & TTEVT_FORK)
+ {
+ process_state = FORKING;
+
+#ifdef WAIT_BUFFER_DEBUG
+ if( debug_on )
+ printf( "Process set to FORKING\n" );
+#endif
+ }
+ else if (tsp.tts_event & TTEVT_VFORK)
+ {
+ process_state = VFORKING;
+
+#ifdef WAIT_BUFFER_DEBUG
+ if( debug_on )
+ printf( "Process set to VFORKING\n" );
+#endif
+ }
+
+ /* Make an exec or fork look like a breakpoint. Definitely a hack,
+ but I don't think non HP-UX-specific clients really carefully
+ inspect the first events they get after inferior startup, so
+ it probably almost doesn't matter what we claim this is.
+ */
+
+#ifdef THREAD_DEBUG
+ if( debug_on )
+ printf( "..a process 'event'\n" );
+#endif
+
+ /* Also make fork and exec events look like bpts, so they can be caught.
+ */
+ *status = 0177 | (_SIGTRAP << 8);
+ }
+
+ /* Special-cases: We ask for syscall entry and exit events to implement
+ "fast" (aka "hardware") watchpoints.
+
+ When we get a syscall entry, we want to disable page-protections,
+ and resume the inferior; this isn't an event we wish for
+ wait_for_inferior to see. Note that we must resume ONLY the
+ thread that reported the syscall entry; we don't want to allow
+ other threads to run with the page protections off, as they might
+ then be able to write to watch memory without it being caught.
+
+ When we get a syscall exit, we want to reenable page-protections,
+ but we don't want to resume the inferior; this is an event we wish
+ wait_for_inferior to see. Make it look like the signal we normally
+ get for a single-step completion. This should cause wait_for_inferior
+ to evaluate whether any watchpoint triggered.
+
+ Or rather, that's what we'd LIKE to do for syscall exit; we can't,
+ due to some HP-UX "features". Some syscalls have problems with
+ write-protections on some pages, and some syscalls seem to have
+ pending writes to those pages at the time we're getting the return
+ event. So, we'll single-step the inferior to get out of the syscall,
+ and then reenable protections.
+
+ Note that we're intentionally allowing the syscall exit case to
+ fall through into the succeeding cases, as sometimes we single-
+ step out of one syscall only to immediately enter another...
+ */
+ else if ((tsp.tts_event & TTEVT_SYSCALL_ENTRY)
+ || (tsp.tts_event & TTEVT_SYSCALL_RETURN))
+ {
+ /* Make a syscall event look like a breakpoint. Same comments
+ as for exec & fork events.
+ */
+#ifdef THREAD_DEBUG
+ if( debug_on )
+ printf( "..a syscall 'event'\n" );
+#endif
+
+ /* Also make syscall events look like bpts, so they can be caught.
+ */
+ *status = 0177 | (_SIGTRAP << 8);
+ }
+
+ else if ((tsp.tts_event & TTEVT_LWP_CREATE)
+ || (tsp.tts_event & TTEVT_LWP_TERMINATE)
+ || (tsp.tts_event & TTEVT_LWP_EXIT))
+ {
+ /* Make a thread event look like a breakpoint. Same comments
+ * as for exec & fork events.
+ */
+#ifdef THREAD_DEBUG
+ if( debug_on )
+ printf( "..a thread 'event'\n" );
+#endif
+
+ /* Also make thread events look like bpts, so they can be caught.
+ */
+ *status = 0177 | (_SIGTRAP << 8);
+ }
+
+ else if ((tsp.tts_event & TTEVT_EXIT))
+ { /* WIFEXITED */
+
+#ifdef THREAD_DEBUG
+ if( debug_on )
+ printf( "..an exit\n" );
+#endif
+
+ /* Prevent rest of gdb from thinking this is
+ * a new thread if for some reason it's never
+ * seen the main thread before.
+ */
+ inferior_pid = map_to_gdb_tid( real_tid ); /* HACK, FIX */
+
+ *status = 0 | (tsp.tts_u.tts_exit.tts_exitcode);
+ }
+
+ else if (tsp.tts_event & TTEVT_SIGNAL)
+ { /* WIFSTOPPED */
+#ifdef THREAD_DEBUG
+ if( debug_on )
+ printf( "..a signal, %d\n", tsp.tts_u.tts_signal.tts_signo );
+#endif
+
+ *status = 0177 | (tsp.tts_u.tts_signal.tts_signo << 8);
+ }
+
+ else
+ { /* !WIFSTOPPED */
+
+ /* This means the process or thread terminated. But we should've
+ caught an explicit exit/termination above. So warn (this is
+ really an internal error) and claim the process or thread
+ terminated with a SIGTRAP.
+ */
+
+ warning ("process_wait: unknown process state");
+
+#ifdef THREAD_DEBUG
+ if( debug_on )
+ printf( "Process-level event %s, using tid %d\n",
+ get_printable_name_of_ttrace_event( tsp.tts_event ),
+ real_tid );
+#endif
+
+ *status = _SIGTRAP;
+ }
+
+ target_post_wait (tsp.tts_pid, *status);
+
+
+#ifdef THREAD_DEBUG
+ if( debug_on )
+ printf( "Done waiting, pid is %d, tid %d\n", real_pid, real_tid );
+#endif
+
+ /* All code external to this module uses the tid, but calls
+ * it "pid". There's some tweaking so that the outside sees
+ * the first thread as having the same number as the starting
+ * pid.
+ */
+ return_pid = map_to_gdb_tid( real_tid );
+
+ /* Remember this for later use in "hppa_prepare_to_proceed".
+ */
+ old_gdb_pid = inferior_pid;
+ reported_pid = return_pid;
+ reported_bpt = ((tsp.tts_event & TTEVT_SIGNAL) && (5 == tsp.tts_u.tts_signal.tts_signo));
+
+ if( real_tid == 0 || return_pid == 0 ) {
+ warning( "Internal error: process-wait failed." );
+ }
+
+ return return_pid;
+}
+
+
+/* This function causes the caller's process to be traced by its
+ parent. This is intended to be called after GDB forks itself,
+ and before the child execs the target. Despite the name, it
+ is called by the child.
+
+ Note that HP-UX ttrace is rather funky in how this is done.
+ If the parent wants to get the initial exec event of a child,
+ it must set the ttrace event mask of the child to include execs.
+ (The child cannot do this itself.) This must be done after the
+ child is forked, but before it execs.
+
+ To coordinate the parent and child, we implement a semaphore using
+ pipes. After SETTRC'ing itself, the child tells the parent that
+ it is now traceable by the parent, and waits for the parent's
+ acknowledgement. The parent can then set the child's event mask,
+ and notify the child that it can now exec.
+
+ (The acknowledgement by parent happens as a result of a call to
+ child_acknowledge_created_inferior.)
+ */
+int
+parent_attach_all ()
+{
+ int tt_status;
+
+ /* We need a memory home for a constant, to pass it to ttrace.
+ The value of the constant is arbitrary, so long as both
+ parent and child use the same value. Might as well use the
+ "magic" constant provided by ttrace...
+ */
+ uint64_t tc_magic_child = TT_VERSION;
+ uint64_t tc_magic_parent = 0;
+
+ tt_status = call_real_ttrace (
+ TT_PROC_SETTRC,
+ (int) TT_NIL,
+ (lwpid_t) TT_NIL,
+ TT_NIL,
+ (TTRACE_ARG_TYPE) TT_VERSION,
+ TT_NIL );
+
+ if (tt_status < 0)
+ return tt_status;
+
+ /* Notify the parent that we're potentially ready to exec(). */
+ write (startup_semaphore.child_channel[SEM_TALK],
+ &tc_magic_child,
+ sizeof (tc_magic_child));
+
+ /* Wait for acknowledgement from the parent. */
+ read (startup_semaphore.parent_channel[SEM_LISTEN],
+ &tc_magic_parent,
+ sizeof (tc_magic_parent));
+
+ if (tc_magic_child != tc_magic_parent)
+ warning ("mismatched semaphore magic");
+
+ /* Discard our copy of the semaphore. */
+ (void) close (startup_semaphore.parent_channel[SEM_LISTEN]);
+ (void) close (startup_semaphore.parent_channel[SEM_TALK]);
+ (void) close (startup_semaphore.child_channel[SEM_LISTEN]);
+ (void) close (startup_semaphore.child_channel[SEM_TALK]);
+
+ return tt_status;
+}
+
+/* Despite being file-local, this routine is dealing with
+ * actual process IDs, not thread ids. That's because it's
+ * called before the first "wait" call, and there's no map
+ * yet from tids to pids.
+ *
+ * When it is called, a forked child is running, but waiting on
+ * the semaphore. If you stop the child and re-start it,
+ * things get confused, so don't do that! An attached child is
+ * stopped.
+ *
+ * Since this is called after either attach or run, we
+ * have to be the common part of both.
+ */
+static void
+require_notification_of_events ( real_pid )
+ int real_pid;
+{
+ int tt_status;
+ ttevent_t notifiable_events;
+
+ lwpid_t tid;
+ ttstate_t thread_state;
+
+#ifdef THREAD_DEBUG
+ if( debug_on )
+ printf( "Require notif, pid is %d\n", real_pid );
+#endif
+
+ /* Temporary HACK: tell inftarg.c/child_wait to not
+ * loop until pids are the same.
+ */
+ not_same_real_pid = 0;
+
+ sigemptyset (&notifiable_events.tte_signals);
+ notifiable_events.tte_opts = TTEO_NONE;
+
+ /* This ensures that forked children inherit their parent's
+ * event mask, which we're setting here.
+ *
+ * NOTE: if you debug gdb with itself, then the ultimate
+ * debuggee gets flags set by the outermost gdb, as
+ * a child of a child will still inherit.
+ */
+ notifiable_events.tte_opts |= TTEO_PROC_INHERIT;
+
+ notifiable_events.tte_events = TTEVT_DEFAULT;
+ notifiable_events.tte_events |= TTEVT_SIGNAL;
+ notifiable_events.tte_events |= TTEVT_EXEC;
+ notifiable_events.tte_events |= TTEVT_EXIT;
+ notifiable_events.tte_events |= TTEVT_FORK;
+ notifiable_events.tte_events |= TTEVT_VFORK;
+ notifiable_events.tte_events |= TTEVT_LWP_CREATE;
+ notifiable_events.tte_events |= TTEVT_LWP_EXIT;
+ notifiable_events.tte_events |= TTEVT_LWP_TERMINATE;
+
+ tt_status = call_real_ttrace (
+ TT_PROC_SET_EVENT_MASK,
+ real_pid,
+ (lwpid_t) TT_NIL,
+ (TTRACE_ARG_TYPE) &notifiable_events,
+ (TTRACE_ARG_TYPE) sizeof (notifiable_events),
+ TT_NIL);
+}
+
+static void
+require_notification_of_exec_events ( real_pid )
+ int real_pid;
+{
+ int tt_status;
+ ttevent_t notifiable_events;
+
+ lwpid_t tid;
+ ttstate_t thread_state;
+
+#ifdef THREAD_DEBUG
+ if( debug_on )
+ printf( "Require notif, pid is %d\n", real_pid );
+#endif
+
+ /* Temporary HACK: tell inftarg.c/child_wait to not
+ * loop until pids are the same.
+ */
+ not_same_real_pid = 0;
+
+ sigemptyset (&notifiable_events.tte_signals);
+ notifiable_events.tte_opts = TTEO_NOSTRCCHLD;
+
+ /* This ensures that forked children don't inherit their parent's
+ * event mask, which we're setting here.
+ */
+ notifiable_events.tte_opts &= ~TTEO_PROC_INHERIT;
+
+ notifiable_events.tte_events = TTEVT_DEFAULT;
+ notifiable_events.tte_events |= TTEVT_EXEC;
+ notifiable_events.tte_events |= TTEVT_EXIT;
+
+ tt_status = call_real_ttrace (
+ TT_PROC_SET_EVENT_MASK,
+ real_pid,
+ (lwpid_t) TT_NIL,
+ (TTRACE_ARG_TYPE) &notifiable_events,
+ (TTRACE_ARG_TYPE) sizeof (notifiable_events),
+ TT_NIL);
+}
+
+
+/* This function is called by the parent process, with pid being the
+ * ID of the child process, after the debugger has forked.
+ */
+void
+child_acknowledge_created_inferior (pid)
+ int pid;
+{
+ /* We need a memory home for a constant, to pass it to ttrace.
+ The value of the constant is arbitrary, so long as both
+ parent and child use the same value. Might as well use the
+ "magic" constant provided by ttrace...
+ */
+ uint64_t tc_magic_parent = TT_VERSION;
+ uint64_t tc_magic_child = 0;
+
+ /* Wait for the child to tell us that it has forked. */
+ read (startup_semaphore.child_channel[SEM_LISTEN],
+ &tc_magic_child,
+ sizeof(tc_magic_child));
+
+ /* Clear thread info now. We'd like to do this in
+ * "require...", but that messes up attach.
+ */
+ clear_thread_info();
+
+ /* Tell the "rest of gdb" that the initial thread exists.
+ * This isn't really a hack. Other thread-based versions
+ * of gdb (e.g. gnu-nat.c) seem to do the same thing.
+ *
+ * Q: Why don't we also add this thread to the local
+ * list via "add_tthread"?
+ *
+ * A: Because we don't know the tid, and can't stop the
+ * the process safely to ask what it is. Anyway, we'll
+ * add it when it gets the EXEC event.
+ */
+ add_thread( pid ); /* in thread.c */
+
+ /* We can now set the child's ttrace event mask.
+ */
+ require_notification_of_exec_events (pid);
+
+ /* Tell ourselves that the process is running.
+ */
+ process_state = RUNNING;
+
+ /* Notify the child that it can exec. */
+ write (startup_semaphore.parent_channel[SEM_TALK],
+ &tc_magic_parent,
+ sizeof (tc_magic_parent));
+
+ /* Discard our copy of the semaphore. */
+ (void) close (startup_semaphore.parent_channel[SEM_LISTEN]);
+ (void) close (startup_semaphore.parent_channel[SEM_TALK]);
+ (void) close (startup_semaphore.child_channel[SEM_LISTEN]);
+ (void) close (startup_semaphore.child_channel[SEM_TALK]);
+}
+
+
+/*
+ * arrange for notification of all events by
+ * calling require_notification_of_events.
+ */
+void
+child_post_startup_inferior ( real_pid)
+ int real_pid;
+{
+ require_notification_of_events (real_pid);
+}
+
+/* From here on, we should expect tids rather than pids.
+ */
+static void
+hppa_enable_catch_fork (tid)
+ int tid;
+{
+ int tt_status;
+ ttevent_t ttrace_events;
+
+ /* Get the set of events that are currently enabled.
+ */
+ tt_status = call_ttrace (TT_PROC_GET_EVENT_MASK,
+ tid,
+ (TTRACE_ARG_TYPE) &ttrace_events,
+ (TTRACE_ARG_TYPE) sizeof (ttrace_events),
+ TT_NIL );
+ if (errno)
+ perror_with_name ("ttrace");
+
+ /* Add forks to that set. */
+ ttrace_events.tte_events |= TTEVT_FORK;
+
+#ifdef THREAD_DEBUG
+ if( debug_on )
+ printf( "enable fork, tid is %d\n", tid );
+#endif
+
+ tt_status = call_ttrace (TT_PROC_SET_EVENT_MASK,
+ tid,
+ (TTRACE_ARG_TYPE) &ttrace_events,
+ (TTRACE_ARG_TYPE) sizeof (ttrace_events),
+ TT_NIL);
+ if (errno)
+ perror_with_name ("ttrace");
+}
+
+
+static void
+hppa_disable_catch_fork (tid)
+ int tid;
+{
+ int tt_status;
+ ttevent_t ttrace_events;
+
+ /* Get the set of events that are currently enabled.
+ */
+ tt_status = call_ttrace (TT_PROC_GET_EVENT_MASK,
+ tid,
+ (TTRACE_ARG_TYPE) &ttrace_events,
+ (TTRACE_ARG_TYPE) sizeof (ttrace_events),
+ TT_NIL);
+
+ if (errno)
+ perror_with_name ("ttrace");
+
+ /* Remove forks from that set. */
+ ttrace_events.tte_events &= ~TTEVT_FORK;
+
+#ifdef THREAD_DEBUG
+ if( debug_on )
+ printf("disable fork, tid is %d\n", tid );
+#endif
+
+ tt_status = call_ttrace (TT_PROC_SET_EVENT_MASK,
+ tid,
+ (TTRACE_ARG_TYPE) &ttrace_events,
+ (TTRACE_ARG_TYPE) sizeof (ttrace_events),
+ TT_NIL);
+
+ if (errno)
+ perror_with_name ("ttrace");
+}
+
+
+#if defined(CHILD_INSERT_FORK_CATCHPOINT)
+int
+child_insert_fork_catchpoint (tid)
+ int tid;
+{
+ /* Enable reporting of fork events from the kernel. */
+ /* ??rehrauer: For the moment, we're always enabling these events,
+ and just ignoring them if there's no catchpoint to catch them.
+ */
+ return 0;
+}
+#endif
+
+
+#if defined(CHILD_REMOVE_FORK_CATCHPOINT)
+int
+child_remove_fork_catchpoint (tid)
+ int tid;
+{
+ /* Disable reporting of fork events from the kernel. */
+ /* ??rehrauer: For the moment, we're always enabling these events,
+ and just ignoring them if there's no catchpoint to catch them.
+ */
+ return 0;
+}
+#endif
+
+
+static void
+hppa_enable_catch_vfork (tid)
+ int tid;
+{
+ int tt_status;
+ ttevent_t ttrace_events;
+
+ /* Get the set of events that are currently enabled.
+ */
+ tt_status = call_ttrace (TT_PROC_GET_EVENT_MASK,
+ tid,
+ (TTRACE_ARG_TYPE) &ttrace_events,
+ (TTRACE_ARG_TYPE) sizeof (ttrace_events),
+ TT_NIL);
+
+ if (errno)
+ perror_with_name ("ttrace");
+
+ /* Add vforks to that set. */
+ ttrace_events.tte_events |= TTEVT_VFORK;
+
+#ifdef THREAD_DEBUG
+ if( debug_on )
+ printf("enable vfork, tid is %d\n", tid );
+#endif
+
+ tt_status = call_ttrace (TT_PROC_SET_EVENT_MASK,
+ tid,
+ (TTRACE_ARG_TYPE) &ttrace_events,
+ (TTRACE_ARG_TYPE) sizeof (ttrace_events),
+ TT_NIL);
+
+ if (errno)
+ perror_with_name ("ttrace");
+}
+
+
+static void
+hppa_disable_catch_vfork (tid)
+ int tid;
+{
+ int tt_status;
+ ttevent_t ttrace_events;
+
+ /* Get the set of events that are currently enabled. */
+ tt_status = call_ttrace (TT_PROC_GET_EVENT_MASK,
+ tid,
+ (TTRACE_ARG_TYPE) &ttrace_events,
+ (TTRACE_ARG_TYPE) sizeof (ttrace_events),
+ TT_NIL);
+
+ if (errno)
+ perror_with_name ("ttrace");
+
+ /* Remove vforks from that set. */
+ ttrace_events.tte_events &= ~TTEVT_VFORK;
+
+#ifdef THREAD_DEBUG
+ if( debug_on )
+ printf("disable vfork, tid is %d\n", tid );
+#endif
+ tt_status = call_ttrace (TT_PROC_SET_EVENT_MASK,
+ tid,
+ (TTRACE_ARG_TYPE) &ttrace_events,
+ (TTRACE_ARG_TYPE) sizeof (ttrace_events),
+ TT_NIL);
+
+ if (errno)
+ perror_with_name ("ttrace");
+}
+
+
+#if defined(CHILD_INSERT_VFORK_CATCHPOINT)
+int
+child_insert_vfork_catchpoint (tid)
+ int tid;
+{
+ /* Enable reporting of vfork events from the kernel. */
+ /* ??rehrauer: For the moment, we're always enabling these events,
+ and just ignoring them if there's no catchpoint to catch them.
+ */
+ return 0;
+}
+#endif
+
+
+#if defined(CHILD_REMOVE_VFORK_CATCHPOINT)
+int
+child_remove_vfork_catchpoint (tid)
+ int tid;
+{
+ /* Disable reporting of vfork events from the kernel. */
+ /* ??rehrauer: For the moment, we're always enabling these events,
+ and just ignoring them if there's no catchpoint to catch them.
+ */
+ return 0;
+}
+#endif
+
+#if defined(CHILD_HAS_FORKED)
+
+/* Q: Do we need to map the returned process ID to a thread ID?
+ *
+ * A: I don't think so--here we want a _real_ pid. Any later
+ * operations will call "require_notification_of_events" and
+ * start the mapping.
+ */
+int
+child_has_forked (tid, childpid)
+ int tid;
+ int *childpid;
+{
+ int tt_status;
+ ttstate_t ttrace_state;
+ thread_info * tinfo;
+
+ /* Do we have cached thread state that we can consult? If so, use it. */
+ tinfo = find_thread_info (map_from_gdb_tid (tid));
+ if (tinfo != NULL) {
+ copy_ttstate_t (&ttrace_state, &tinfo->last_stop_state);
+ }
+
+ /* Nope, must read the thread's current state */
+ else
+ {
+ tt_status = call_ttrace (TT_LWP_GET_STATE,
+ tid,
+ (TTRACE_ARG_TYPE) &ttrace_state,
+ (TTRACE_ARG_TYPE) sizeof (ttrace_state),
+ TT_NIL);
+
+ if (errno)
+ perror_with_name ("ttrace");
+
+ if (tt_status < 0)
+ return 0;
+ }
+
+ if (ttrace_state.tts_event & TTEVT_FORK)
+ {
+ *childpid = ttrace_state.tts_u.tts_fork.tts_fpid;
+ return 1;
+ }
+
+ return 0;
+}
+#endif
+
+
+#if defined(CHILD_HAS_VFORKED)
+
+/* See child_has_forked for pid discussion.
+ */
+int
+child_has_vforked (tid, childpid)
+ int tid;
+ int * childpid;
+{
+ int tt_status;
+ ttstate_t ttrace_state;
+ thread_info * tinfo;
+
+ /* Do we have cached thread state that we can consult? If so, use it. */
+ tinfo = find_thread_info (map_from_gdb_tid (tid));
+ if (tinfo != NULL)
+ copy_ttstate_t (&ttrace_state, &tinfo->last_stop_state);
+
+ /* Nope, must read the thread's current state */
+ else
+ {
+ tt_status = call_ttrace (TT_LWP_GET_STATE,
+ tid,
+ (TTRACE_ARG_TYPE) &ttrace_state,
+ (TTRACE_ARG_TYPE) sizeof (ttrace_state),
+ TT_NIL);
+
+ if (errno)
+ perror_with_name ("ttrace");
+
+ if (tt_status < 0)
+ return 0;
+ }
+
+ if (ttrace_state.tts_event & TTEVT_VFORK)
+ {
+ *childpid = ttrace_state.tts_u.tts_fork.tts_fpid;
+ return 1;
+ }
+
+ return 0;
+}
+#endif
+
+
+#if defined(CHILD_CAN_FOLLOW_VFORK_PRIOR_TO_EXEC)
+int
+child_can_follow_vfork_prior_to_exec ()
+{
+ /* ttrace does allow this.
+
+ ??rehrauer: However, I had major-league problems trying to
+ convince wait_for_inferior to handle that case. Perhaps when
+ it is rewritten to grok multiple processes in an explicit way...
+ */
+ return 0;
+}
+#endif
+
+
+#if defined(CHILD_INSERT_EXEC_CATCHPOINT)
+int
+child_insert_exec_catchpoint (tid)
+ int tid;
+{
+ /* Enable reporting of exec events from the kernel. */
+ /* ??rehrauer: For the moment, we're always enabling these events,
+ and just ignoring them if there's no catchpoint to catch them.
+ */
+ return 0;
+}
+#endif
+
+
+#if defined(CHILD_REMOVE_EXEC_CATCHPOINT)
+int
+child_remove_exec_catchpoint (tid)
+ int tid;
+{
+ /* Disable reporting of execevents from the kernel. */
+ /* ??rehrauer: For the moment, we're always enabling these events,
+ and just ignoring them if there's no catchpoint to catch them.
+ */
+ return 0;
+}
+#endif
+
+
+#if defined(CHILD_HAS_EXECD)
+int
+child_has_execd (tid, execd_pathname)
+ int tid;
+ char ** execd_pathname;
+{
+ int tt_status;
+ ttstate_t ttrace_state;
+ thread_info * tinfo;
+
+ /* Do we have cached thread state that we can consult? If so, use it. */
+ tinfo = find_thread_info (map_from_gdb_tid (tid));
+ if (tinfo != NULL)
+ copy_ttstate_t (&ttrace_state, &tinfo->last_stop_state);
+
+ /* Nope, must read the thread's current state */
+ else
+ {
+ tt_status = call_ttrace (TT_LWP_GET_STATE,
+ tid,
+ (TTRACE_ARG_TYPE) &ttrace_state,
+ (TTRACE_ARG_TYPE) sizeof (ttrace_state),
+ TT_NIL);
+
+ if (errno)
+ perror_with_name ("ttrace");
+
+ if (tt_status < 0)
+ return 0;
+ }
+
+ if (ttrace_state.tts_event & TTEVT_EXEC)
+ {
+ /* See child_pid_to_exec_file in this file: this is a macro.
+ */
+ char * exec_file = target_pid_to_exec_file (tid);
+
+ *execd_pathname = savestring (exec_file, strlen (exec_file));
+ return 1;
+ }
+
+ return 0;
+}
+#endif
+
+
+#if defined(CHILD_HAS_SYSCALL_EVENT)
+int
+child_has_syscall_event (pid, kind, syscall_id)
+ int pid;
+ enum target_waitkind * kind;
+ int * syscall_id;
+{
+ int tt_status;
+ ttstate_t ttrace_state;
+ thread_info * tinfo;
+
+ /* Do we have cached thread state that we can consult? If so, use it. */
+ tinfo = find_thread_info (map_from_gdb_tid (pid));
+ if (tinfo != NULL)
+ copy_ttstate_t (&ttrace_state, &tinfo->last_stop_state);
+
+ /* Nope, must read the thread's current state */
+ else
+ {
+ tt_status = call_ttrace (TT_LWP_GET_STATE,
+ pid,
+ (TTRACE_ARG_TYPE) &ttrace_state,
+ (TTRACE_ARG_TYPE) sizeof (ttrace_state),
+ TT_NIL);
+
+ if (errno)
+ perror_with_name ("ttrace");
+
+ if (tt_status < 0)
+ return 0;
+ }
+
+ *kind = TARGET_WAITKIND_SPURIOUS; /* Until proven otherwise... */
+ *syscall_id = -1;
+
+ if (ttrace_state.tts_event & TTEVT_SYSCALL_ENTRY)
+ *kind = TARGET_WAITKIND_SYSCALL_ENTRY;
+ else if (ttrace_state.tts_event & TTEVT_SYSCALL_RETURN)
+ *kind = TARGET_WAITKIND_SYSCALL_RETURN;
+ else
+ return 0;
+
+ *syscall_id = ttrace_state.tts_scno;
+ return 1;
+}
+#endif
+
+
+
+#if defined(CHILD_THREAD_ALIVE)
+
+/* Check to see if the given thread is alive.
+ *
+ * We'll trust the thread list, as the more correct
+ * approach of stopping the process and spinning down
+ * the OS's thread list is _very_ expensive.
+ *
+ * May need a FIXME for that reason.
+ */
+int
+child_thread_alive (gdb_tid)
+ lwpid_t gdb_tid;
+{
+ lwpid_t tid;
+
+ /* This spins down the lists twice.
+ * Possible peformance improvement here!
+ */
+ tid = map_from_gdb_tid( gdb_tid );
+ return !is_terminated( tid );
+}
+
+#endif
+
+
+
+/* This function attempts to read the specified number of bytes from the
+ save_state_t that is our view into the hardware registers, starting at
+ ss_offset, and ending at ss_offset + sizeof_buf - 1
+
+ If this function succeeds, it deposits the fetched bytes into buf,
+ and returns 0.
+
+ If it fails, it returns a negative result. The contents of buf are
+ undefined it this function fails.
+ */
+int
+read_from_register_save_state (tid, ss_offset, buf, sizeof_buf)
+ int tid;
+ TTRACE_ARG_TYPE ss_offset;
+ char * buf;
+ int sizeof_buf;
+{
+ int tt_status;
+ register_value_t register_value = 0;
+
+ tt_status = call_ttrace (TT_LWP_RUREGS,
+ tid,
+ ss_offset,
+ (TTRACE_ARG_TYPE) sizeof_buf,
+ (TTRACE_ARG_TYPE) buf);
+
+ if( tt_status == 1 )
+ /* Map ttrace's version of success to our version.
+ * Sometime ttrace returns 0, but that's ok here.
+ */
+ return 0;
+
+ return tt_status;
+}
+
+
+/* This function attempts to write the specified number of bytes to the
+ save_state_t that is our view into the hardware registers, starting at
+ ss_offset, and ending at ss_offset + sizeof_buf - 1
+
+ If this function succeeds, it deposits the bytes in buf, and returns 0.
+
+ If it fails, it returns a negative result. The contents of the save_state_t
+ are undefined it this function fails.
+ */
+int
+write_to_register_save_state (tid, ss_offset, buf, sizeof_buf)
+ int tid;
+ TTRACE_ARG_TYPE ss_offset;
+ char * buf;
+ int sizeof_buf;
+{
+ int tt_status;
+ register_value_t register_value = 0;
+
+ tt_status = call_ttrace (TT_LWP_WUREGS,
+ tid,
+ ss_offset,
+ (TTRACE_ARG_TYPE) sizeof_buf,
+ (TTRACE_ARG_TYPE) buf);
+ return tt_status;
+}
+
+
+/* This function is a sop to the largeish number of direct calls
+ to call_ptrace that exist in other files. Rather than create
+ functions whose name abstracts away from ptrace, and change all
+ the present callers of call_ptrace, we'll do the expedient (and
+ perhaps only practical) thing.
+
+ Note HP-UX explicitly disallows a mix of ptrace & ttrace on a traced
+ process. Thus, we must translate all ptrace requests into their
+ process-specific, ttrace equivalents.
+ */
+int
+call_ptrace (pt_request, gdb_tid, addr, data)
+ int pt_request;
+ int gdb_tid;
+ PTRACE_ARG3_TYPE addr;
+ int data;
+{
+ ttreq_t tt_request;
+ TTRACE_ARG_TYPE tt_addr = (TTRACE_ARG_TYPE) addr;
+ TTRACE_ARG_TYPE tt_data = (TTRACE_ARG_TYPE) data;
+ TTRACE_ARG_TYPE tt_addr2 = TT_NIL;
+ int tt_status;
+ register_value_t register_value;
+ int read_buf;
+
+ /* Perform the necessary argument translation. Note that some
+ cases are funky enough in the ttrace realm that we handle them
+ very specially.
+ */
+ switch (pt_request) {
+ /* The following cases cannot conveniently be handled conveniently
+ by merely adjusting the ptrace arguments and feeding into the
+ generic call to ttrace at the bottom of this function.
+
+ Note that because all branches of this switch end in "return",
+ there's no need for any "break" statements.
+ */
+ case PT_SETTRC :
+ return parent_attach_all ();
+
+ case PT_RUREGS :
+ tt_status = read_from_register_save_state (gdb_tid,
+ tt_addr,
+ &register_value,
+ sizeof (register_value));
+ if (tt_status < 0)
+ return tt_status;
+ return register_value;
+
+ case PT_WUREGS :
+ register_value = (int) tt_data;
+ tt_status = write_to_register_save_state (gdb_tid,
+ tt_addr,
+ &register_value,
+ sizeof (register_value));
+ return tt_status;
+ break;
+
+ case PT_READ_I :
+ tt_status = call_ttrace (TT_PROC_RDTEXT, /* Implicit 4-byte xfer becomes block-xfer. */
+ gdb_tid,
+ tt_addr,
+ (TTRACE_ARG_TYPE) 4,
+ (TTRACE_ARG_TYPE) &read_buf);
+ if (tt_status < 0)
+ return tt_status;
+ return read_buf;
+
+ case PT_READ_D :
+ tt_status = call_ttrace (TT_PROC_RDDATA, /* Implicit 4-byte xfer becomes block-xfer. */
+ gdb_tid,
+ tt_addr,
+ (TTRACE_ARG_TYPE) 4,
+ (TTRACE_ARG_TYPE) &read_buf);
+ if (tt_status < 0)
+ return tt_status;
+ return read_buf;
+
+ case PT_ATTACH :
+ tt_status = call_real_ttrace (TT_PROC_ATTACH,
+ map_from_gdb_tid (gdb_tid),
+ (lwpid_t) TT_NIL,
+ tt_addr,
+ (TTRACE_ARG_TYPE) TT_VERSION,
+ tt_addr2);
+ if (tt_status < 0)
+ return tt_status;
+ return tt_status;
+
+ /* The following cases are handled by merely adjusting the ptrace
+ arguments and feeding into the generic call to ttrace.
+ */
+ case PT_DETACH :
+ tt_request = TT_PROC_DETACH;
+ break;
+
+ case PT_WRITE_I :
+ tt_request = TT_PROC_WRTEXT; /* Translates 4-byte xfer to block-xfer. */
+ tt_data = 4; /* This many bytes. */
+ tt_addr2 = (TTRACE_ARG_TYPE) &data; /* Address of xfer source. */
+ break;
+
+ case PT_WRITE_D :
+ tt_request = TT_PROC_WRDATA; /* Translates 4-byte xfer to block-xfer. */
+ tt_data = 4; /* This many bytes. */
+ tt_addr2 = (TTRACE_ARG_TYPE) &data; /* Address of xfer source. */
+ break;
+
+ case PT_RDTEXT :
+ tt_request = TT_PROC_RDTEXT;
+ break;
+
+ case PT_RDDATA :
+ tt_request = TT_PROC_RDDATA;
+ break;
+
+ case PT_WRTEXT :
+ tt_request = TT_PROC_WRTEXT;
+ break;
+
+ case PT_WRDATA :
+ tt_request = TT_PROC_WRDATA;
+ break;
+
+ case PT_CONTINUE :
+ tt_request = TT_PROC_CONTINUE;
+ break;
+
+ case PT_STEP :
+ tt_request = TT_LWP_SINGLE; /* Should not be making this request? */
+ break;
+
+ case PT_KILL :
+ tt_request = TT_PROC_EXIT;
+ break;
+
+ case PT_GET_PROCESS_PATHNAME :
+ tt_request = TT_PROC_GET_PATHNAME;
+ break;
+
+ default :
+ tt_request = pt_request; /* Let ttrace be the one to complain. */
+ break;
+ }
+
+ return call_ttrace (tt_request,
+ gdb_tid,
+ tt_addr,
+ tt_data,
+ tt_addr2);
+}
+
+/* Kill that pesky process!
+ */
+void
+kill_inferior ()
+{
+ int tid;
+ int wait_status;
+ thread_info * t;
+ thread_info **paranoia;
+ int para_count, i;
+
+ if (inferior_pid == 0)
+ return;
+
+ /* Walk the list of "threads", some of which are "pseudo threads",
+ aka "processes". For each that is NOT inferior_pid, stop it,
+ and detach it.
+
+ You see, we may not have just a single process to kill. If we're
+ restarting or quitting or detaching just after the inferior has
+ forked, then we've actually two processes to clean up.
+
+ But we can't just call target_mourn_inferior() for each, since that
+ zaps the target vector.
+ */
+
+ paranoia = (thread_info **) malloc( thread_head.count *
+ sizeof(thread_info *));
+ para_count = 0;
+
+ t = thread_head.head;
+ while (t) {
+
+ paranoia[ para_count ] = t;
+ for( i = 0; i < para_count; i++ ){
+ if( t->next == paranoia[i] ) {
+ warning( "Bad data in gdb's thread data; repairing." );
+ t->next = 0;
+ }
+ }
+ para_count++;
+
+ if (t->am_pseudo && (t->pid != inferior_pid))
+ {
+ /* TT_PROC_STOP doesn't require a subsequent ttrace_wait, as it
+ * generates no event.
+ */
+ call_ttrace (TT_PROC_STOP,
+ t->pid,
+ TT_NIL,
+ TT_NIL,
+ TT_NIL);
+
+ call_ttrace (TT_PROC_DETACH,
+ t->pid,
+ TT_NIL,
+ (TTRACE_ARG_TYPE) TARGET_SIGNAL_0,
+ TT_NIL);
+ }
+ t = t->next;
+ }
+
+ free( paranoia );
+
+ call_ttrace (TT_PROC_STOP,
+ inferior_pid,
+ TT_NIL,
+ TT_NIL,
+ TT_NIL);
+ target_mourn_inferior ();
+ clear_thread_info();
+}
+
+
+#ifndef CHILD_RESUME
+
+/* Sanity check a thread about to be continued.
+ */
+static void
+thread_dropping_event_check( p )
+ thread_info *p;
+{
+ if( !p->handled ) {
+ /*
+ * This seems to happen when we "next" over a
+ * "fork()" while following the parent. If it's
+ * the FORK event, that's ok. If it's a SIGNAL
+ * in the unfollowed child, that's ok to--but
+ * how can we know that's what's going on?
+ *
+ * FIXME!
+ */
+ if( p->have_state ) {
+ if( p->last_stop_state.tts_event == TTEVT_FORK ) {
+ /* Ok */
+ ;
+ }
+ else if( p->last_stop_state.tts_event == TTEVT_SIGNAL ) {
+ /* Ok, close eyes and let it happen.
+ */
+ ;
+ }
+ else {
+ /* This shouldn't happen--we're dropping a
+ * real event.
+ */
+ warning( "About to continue process %d, thread %d with unhandled event %s.",
+ p->pid, p->tid,
+ get_printable_name_of_ttrace_event(
+ p->last_stop_state.tts_event ));
+
+#ifdef PARANOIA
+ if( debug_on )
+ print_tthread( p );
+#endif
+ }
+ }
+ else {
+ /* No saved state, have to assume it failed.
+ */
+ warning( "About to continue process %d, thread %d with unhandled event.",
+ p->pid, p->tid );
+#ifdef PARANOIA
+ if( debug_on )
+ print_tthread( p );
+#endif
+ }
+ }
+
+} /* thread_dropping_event_check */
+
+/* Use a loop over the threads to continue all the threads but
+ * the one specified, which is to be stepped.
+ */
+static void
+threads_continue_all_but_one( gdb_tid, signal )
+ lwpid_t gdb_tid;
+ int signal;
+{
+ thread_info *p;
+ int thread_signal;
+ lwpid_t real_tid;
+ lwpid_t scan_tid;
+ ttstate_t state;
+ int real_pid;
+
+#ifdef THREAD_DEBUG
+ if( debug_on )
+ printf( "Using loop over threads to step/resume with signals\n" );
+#endif
+
+ /* First update the thread list.
+ */
+ set_all_unseen();
+ real_tid = map_from_gdb_tid( gdb_tid );
+ real_pid = get_pid_for( real_tid );
+
+ scan_tid = get_process_first_stopped_thread_id( real_pid, &state );
+ while ( 0 != scan_tid ) {
+
+#ifdef THREAD_DEBUG
+ /* FIX: later should check state is stopped;
+ * state.tts_flags & TTS_STATEMASK == TTS_WASSUSPENDED
+ */
+ if( debug_on )
+ if( state.tts_flags & TTS_STATEMASK != TTS_WASSUSPENDED )
+ printf( "About to continue non-stopped thread %d\n", scan_tid );
+#endif
+
+ p = find_thread_info( scan_tid );
+ if( NULL == p ) {
+ add_tthread( real_pid, scan_tid );
+ p = find_thread_info( scan_tid );
+
+ /* This is either a newly-created thread or the
+ * result of a fork; in either case there's no
+ * actual event to worry about.
+ */
+ p->handled = 1;
+
+ if( state.tts_event != TTEVT_NONE ) {
+ /* Oops, do need to worry!
+ */
+ warning( "Unexpected thread with \"%s\" event.",
+ get_printable_name_of_ttrace_event( state.tts_event ));
+ }
+ }
+ else if( scan_tid != p->tid )
+ error( "Bad data in thread database." );
+
+#ifdef THREAD_DEBUG
+ if( debug_on )
+ if( p->terminated )
+ printf( "Why are we continuing a dead thread?\n" );
+#endif
+
+ p->seen = 1;
+
+ scan_tid = get_process_next_stopped_thread_id( real_pid, &state );
+ }
+
+ /* Remove unseen threads.
+ */
+ update_thread_list();
+
+ /* Now run down the thread list and continue or step.
+ */
+ for( p = thread_head.head; p; p = p->next ) {
+
+ /* Sanity check.
+ */
+ thread_dropping_event_check( p );
+
+ /* Pass the correct signals along.
+ */
+ if( p->have_signal ) {
+ thread_signal = p->signal_value;
+ p->have_signal = 0;
+ }
+ else
+ thread_signal = 0;
+
+ if( p->tid != real_tid ) {
+ /*
+ * Not the thread of interest, so continue it
+ * as the user expects.
+ */
+ if( p->stepping_mode == DO_STEP ) {
+ /* Just step this thread.
+ */
+ call_ttrace(
+ TT_LWP_SINGLE,
+ p->tid,
+ TT_USE_CURRENT_PC,
+ (TTRACE_ARG_TYPE) target_signal_to_host( signal ),
+ TT_NIL );
+ }
+ else {
+ /* Regular continue (default case).
+ */
+ call_ttrace(
+ TT_LWP_CONTINUE,
+ p->tid,
+ TT_USE_CURRENT_PC,
+ (TTRACE_ARG_TYPE) target_signal_to_host( thread_signal ),
+ TT_NIL );
+ }
+ }
+ else {
+ /* Step the thread of interest.
+ */
+ call_ttrace(
+ TT_LWP_SINGLE,
+ real_tid,
+ TT_USE_CURRENT_PC,
+ (TTRACE_ARG_TYPE) target_signal_to_host( signal ),
+ TT_NIL );
+ }
+ } /* Loop over threads */
+} /* End threads_continue_all_but_one */
+
+/* Use a loop over the threads to continue all the threads.
+ * This is done when a signal must be sent to any of the threads.
+ */
+static void
+threads_continue_all_with_signals( gdb_tid, signal )
+ lwpid_t gdb_tid;
+ int signal;
+{
+ thread_info *p;
+ int thread_signal;
+ lwpid_t real_tid;
+ lwpid_t scan_tid;
+ ttstate_t state;
+ int real_pid;
+
+#ifdef THREAD_DEBUG
+ if( debug_on )
+ printf( "Using loop over threads to resume with signals\n" );
+#endif
+
+ /* Scan and update thread list.
+ */
+ set_all_unseen();
+ real_tid = map_from_gdb_tid( gdb_tid );
+ real_pid = get_pid_for( real_tid );
+
+ scan_tid = get_process_first_stopped_thread_id( real_pid, &state );
+ while ( 0 != scan_tid ) {
+
+#ifdef THREAD_DEBUG
+ if( debug_on )
+ if( state.tts_flags & TTS_STATEMASK != TTS_WASSUSPENDED )
+ warning( "About to continue non-stopped thread %d\n", scan_tid );
+#endif
+
+ p = find_thread_info( scan_tid );
+ if( NULL == p ) {
+ add_tthread( real_pid, scan_tid );
+ p = find_thread_info( scan_tid );
+
+ /* This is either a newly-created thread or the
+ * result of a fork; in either case there's no
+ * actual event to worry about.
+ */
+ p->handled = 1;
+
+ if( state.tts_event != TTEVT_NONE ) {
+ /* Oops, do need to worry!
+ */
+ warning( "Unexpected thread with \"%s\" event.",
+ get_printable_name_of_ttrace_event( state.tts_event ));
+ }
+ }
+
+#ifdef THREAD_DEBUG
+ if( debug_on )
+ if( p->terminated )
+ printf( "Why are we continuing a dead thread? (1)\n" );
+#endif
+
+ p->seen = 1;
+
+ scan_tid = get_process_next_stopped_thread_id( real_pid, &state );
+ }
+
+ /* Remove unseen threads from our list.
+ */
+ update_thread_list();
+
+ /* Continue the threads.
+ */
+ for( p = thread_head.head; p; p = p->next ) {
+
+ /* Sanity check.
+ */
+ thread_dropping_event_check( p );
+
+ /* Pass the correct signals along.
+ */
+ if( p->tid == real_tid ) {
+ thread_signal = signal;
+ p->have_signal = 0;
+ }
+ else if( p->have_signal ) {
+ thread_signal = p->signal_value;
+ p->have_signal = 0;
+ }
+ else
+ thread_signal = 0;
+
+ if( p->stepping_mode == DO_STEP ) {
+ call_ttrace(
+ TT_LWP_SINGLE,
+ p->tid,
+ TT_USE_CURRENT_PC,
+ (TTRACE_ARG_TYPE) target_signal_to_host( signal ),
+ TT_NIL );
+ }
+ else {
+ /* Continue this thread (default case).
+ */
+ call_ttrace(
+ TT_LWP_CONTINUE,
+ p->tid,
+ TT_USE_CURRENT_PC,
+ (TTRACE_ARG_TYPE) target_signal_to_host( thread_signal ),
+ TT_NIL );
+ }
+ }
+} /* End threads_continue_all_with_signals */
+
+/* Step one thread only.
+ */
+static void
+thread_fake_step( tid, signal )
+ lwpid_t tid;
+ enum target_signal signal;
+{
+ thread_info *p;
+
+#ifdef THREAD_DEBUG
+ if( debug_on ) {
+ printf( "Doing a fake-step over a bpt, etc. for %d\n", tid );
+
+ if( is_terminated( tid ))
+ printf( "Why are we continuing a dead thread? (4)\n" );
+ }
+#endif
+
+ if( doing_fake_step )
+ warning( "Step while step already in progress." );
+
+ /* See if there's a saved signal value for this
+ * thread to be passed on, but no current signal.
+ */
+ p = find_thread_info( tid );
+ if( p != NULL ) {
+ if( p->have_signal && signal == NULL ) {
+ /* Pass on a saved signal.
+ */
+ signal = p->signal_value;
+ }
+
+ p->have_signal = 0;
+ }
+
+ if( !p->handled )
+ warning( "Internal error: continuing unhandled thread." );
+
+ call_ttrace( TT_LWP_SINGLE,
+ tid,
+ TT_USE_CURRENT_PC,
+ (TTRACE_ARG_TYPE) target_signal_to_host (signal),
+ TT_NIL );
+
+ /* Do bookkeeping so "call_ttrace_wait" knows it has to wait
+ * for this thread only, and clear any saved signal info.
+ */
+ doing_fake_step = 1;
+ fake_step_tid = tid;
+
+} /* End thread_fake_step */
+
+/* Continue one thread when a signal must be sent to it.
+ */
+static void
+threads_continue_one_with_signal( gdb_tid, signal )
+ lwpid_t gdb_tid;
+ int signal;
+{
+ thread_info *p;
+ lwpid_t real_tid;
+ int real_pid;
+
+#ifdef THREAD_DEBUG
+ if( debug_on )
+ printf( "Continuing one thread with a signal\n" );
+#endif
+
+ real_tid = map_from_gdb_tid( gdb_tid );
+ real_pid = get_pid_for( real_tid );
+
+ p = find_thread_info( real_tid );
+ if( NULL == p ) {
+ add_tthread( real_pid, real_tid );
+ }
+
+#ifdef THREAD_DEBUG
+ if( debug_on )
+ if( p->terminated )
+ printf( "Why are we continuing a dead thread? (2)\n" );
+#endif
+
+ if( !p->handled )
+ warning( "Internal error: continuing unhandled thread." );
+
+ p->have_signal = 0;
+
+ call_ttrace( TT_LWP_CONTINUE,
+ gdb_tid,
+ TT_USE_CURRENT_PC,
+ (TTRACE_ARG_TYPE) target_signal_to_host( signal ),
+ TT_NIL );
+}
+#endif
+
+#ifndef CHILD_RESUME
+
+/* Resume execution of the inferior process.
+ *
+ * This routine is in charge of setting the "handled" bits.
+ *
+ * If STEP is zero, continue it.
+ * If STEP is nonzero, single-step it.
+ *
+ * If SIGNAL is nonzero, give it that signal.
+ *
+ * If TID is -1, apply to all threads.
+ * If TID is not -1, apply to specified thread.
+ *
+ * STEP
+ * \ !0 0
+ * TID \________________________________________________
+ * |
+ * -1 | Step current Continue all threads
+ * | thread and (but which gets any
+ * | continue others signal?--We look at
+ * | "inferior_pid")
+ * |
+ * N | Step _this_ thread Continue _this_ thread
+ * | and leave others and leave others
+ * | stopped; internally stopped; used only for
+ * | used by gdb, never hardware watchpoints
+ * | a user command. and attach, never a
+ * | user command.
+ */
+void
+child_resume( gdb_tid, step, signal )
+ lwpid_t gdb_tid;
+ int step;
+ enum target_signal signal;
+{
+ int resume_all_threads;
+ lwpid_t tid;
+ process_state_t new_process_state;
+
+ resume_all_threads =
+ (gdb_tid == INFTTRACE_ALL_THREADS) ||
+ (vfork_in_flight);
+
+ if (resume_all_threads) {
+ /* Resume all threads, but first pick a tid value
+ * so we can get the pid when in call_ttrace doing
+ * the map.
+ */
+ if (vfork_in_flight)
+ tid = vforking_child_pid;
+ else
+ tid = map_from_gdb_tid( inferior_pid );
+ }
+ else
+ tid = map_from_gdb_tid( gdb_tid );
+
+#ifdef THREAD_DEBUG
+ if( debug_on ) {
+ if( more_events_left )
+ printf( "More events; " );
+
+ if( signal != 0 )
+ printf( "Sending signal %d; ", signal );
+
+ if( resume_all_threads ) {
+ if( step == 0 )
+ printf( "Continue process %d\n", tid );
+ else
+ printf( "Step/continue thread %d\n", tid );
+ }
+ else {
+ if( step == 0 )
+ printf( "Continue thread %d\n", tid );
+ else
+ printf( "Step just thread %d\n", tid );
+ }
+
+ if( vfork_in_flight )
+ printf( "Vfork in flight\n" );
+ }
+#endif
+
+ if( process_state == RUNNING )
+ warning( "Internal error in resume logic; doing resume or step anyway." );
+
+ if( !step /* Asked to continue... */
+ && resume_all_threads /* whole process.. */
+ && signal != 0 /* with a signal... */
+ && more_events_left > 0 ) { /* but we can't yet--save it! */
+
+ /* Continue with signal means we have to set the pending
+ * signal value for this thread.
+ */
+ thread_info *k;
+
+#ifdef THREAD_DEBUG
+ if( debug_on )
+ printf( "Saving signal %d for thread %d\n", signal, tid );
+#endif
+
+ k = find_thread_info( tid );
+ if( k != NULL ) {
+ k->have_signal = 1;
+ k->signal_value = signal;
+
+#ifdef THREAD_DEBUG
+ if( debug_on )
+ if( k->terminated )
+ printf( "Why are we continuing a dead thread? (3)\n" );
+#endif
+
+ }
+
+#ifdef THREAD_DEBUG
+ else if( debug_on ) {
+ printf( "No thread info for tid %d\n", tid );
+ }
+#endif
+ }
+
+ /* Are we faking this "continue" or "step"?
+ *
+ * We used to do steps by continuing all the threads for
+ * which the events had been handled already. While
+ * conceptually nicer (hides it all in a lower level), this
+ * can lead to starvation and a hang (e.g. all but one thread
+ * are unhandled at a breakpoint just before a "join" operation,
+ * and one thread is in the join, and the user wants to step that
+ * thread).
+ */
+ if( resume_all_threads /* Whole process, therefore user command */
+ && more_events_left > 0 ) { /* But we can't do this yet--fake it! */
+ thread_info *p;
+
+ if( !step ) {
+ /* No need to do any notes on a per-thread
+ * basis--we're done!
+ */
+#ifdef WAIT_BUFFER_DEBUG
+ if( debug_on )
+ printf( "Faking a process resume.\n" );
+#endif
+
+ return;
+ }
+ else {
+
+#ifdef WAIT_BUFFER_DEBUG
+ if( debug_on )
+ printf( "Faking a process step.\n" );
+#endif
+
+ }
+
+ p = find_thread_info( tid );
+ if( p == NULL ) {
+ warning( "No thread information for tid %d, 'next' command ignored.\n", tid );
+ return;
+ }
+ else {
+
+#ifdef THREAD_DEBUG
+ if( debug_on )
+ if( p->terminated )
+ printf( "Why are we continuing a dead thread? (3.5)\n" );
+#endif
+
+ if( p->stepping_mode != DO_DEFAULT ) {
+ warning( "Step or continue command applied to thread which is already stepping or continuing; command ignored." );
+
+ return;
+ }
+
+ if( step )
+ p->stepping_mode = DO_STEP;
+ else
+ p->stepping_mode = DO_CONTINUE;
+
+ return;
+ } /* Have thread info */
+ } /* Must fake step or go */
+
+ /* Execept for fake-steps, from here on we know we are
+ * going to wind up with a running process which will
+ * need a real wait.
+ */
+ new_process_state = RUNNING;
+
+ /* An address of TT_USE_CURRENT_PC tells ttrace 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) {
+ if( resume_all_threads ) {
+ /*
+ * Regular user step: other threads get a "continue".
+ */
+ threads_continue_all_but_one( tid, signal );
+ clear_all_handled();
+ clear_all_stepping_mode();
+ }
+
+ else {
+ /* "Fake step": gdb is stepping one thread over a
+ * breakpoint, watchpoint, or out of a library load
+ * event, etc. The rest just stay where they are.
+ *
+ * Also used when there are pending events: we really
+ * step the current thread, but leave the rest stopped.
+ * Users can't request this, but "wait_for_inferior"
+ * does--a lot!
+ */
+ thread_fake_step( tid, signal );
+
+ /* Clear the "handled" state of this thread, because
+ * we'll soon get a new event for it. Other events
+ * stay as they were.
+ */
+ clear_handled( tid );
+ clear_stepping_mode( tid );
+ new_process_state = FAKE_STEPPING;
+ }
+ }
+
+ else {
+ /* TT_LWP_CONTINUE can pass signals to threads,
+ * TT_PROC_CONTINUE can't. So if there are any
+ * signals to pass, we have to use the (slower)
+ * loop over the stopped threads.
+ *
+ * Equally, if we have to not continue some threads,
+ * due to saved events, we have to use the loop.
+ */
+ if( (signal != 0) || saved_signals_exist()) {
+ if( resume_all_threads ) {
+
+#ifdef THREAD_DEBUG
+ if( debug_on )
+ printf( "Doing a continue by loop of all threads\n" );
+#endif
+
+ threads_continue_all_with_signals( tid, signal );
+
+ clear_all_handled();
+ clear_all_stepping_mode();
+ }
+
+ else {
+#ifdef THREAD_DEBUG
+ printf( "Doing a continue w/signal of just thread %d\n", tid );
+#endif
+
+ threads_continue_one_with_signal( tid, signal );
+
+ /* Clear the "handled" state of this thread, because
+ * we'll soon get a new event for it. Other events
+ * can stay as they were.
+ */
+ clear_handled( tid );
+ clear_stepping_mode( tid );
+ }
+ }
+
+ else {
+ /* No signals to send.
+ */
+ if( resume_all_threads ) {
+#ifdef THREAD_DEBUG
+ if( debug_on )
+ printf( "Doing a continue by process of process %d\n", tid );
+#endif
+
+ if( more_events_left > 0 ) {
+ warning( "Losing buffered events on continue." );
+ more_events_left = 0;
+ }
+
+ call_ttrace( TT_PROC_CONTINUE,
+ tid,
+ TT_NIL,
+ TT_NIL,
+ TT_NIL );
+
+ clear_all_handled();
+ clear_all_stepping_mode();
+ }
+
+ else {
+#ifdef THREAD_DEBUG
+ if( debug_on ) {
+ printf( "Doing a continue of just thread %d\n", tid );
+ if( is_terminated( tid ))
+ printf( "Why are we continuing a dead thread? (5)\n" );
+ }
+#endif
+
+ call_ttrace( TT_LWP_CONTINUE,
+ tid,
+ TT_NIL,
+ TT_NIL,
+ TT_NIL );
+
+ /* Clear the "handled" state of this thread, because
+ * we'll soon get a new event for it. Other events
+ * can stay as they were.
+ */
+ clear_handled( tid );
+ clear_stepping_mode( tid );
+ }
+ }
+ }
+
+ process_state = new_process_state;
+
+#ifdef WAIT_BUFFER_DEBUG
+ if( debug_on )
+ printf( "Process set to %s\n",
+ get_printable_name_of_process_state (process_state) );
+#endif
+
+}
+#endif /* CHILD_RESUME */
+
+
+#ifdef ATTACH_DETACH
+/*
+ * Like it says.
+ *
+ * One worry is that we may not be attaching to "inferior_pid"
+ * and thus may not want to clear out our data. FIXME?
+ *
+ */
+static void
+update_thread_state_after_attach( pid, kind_of_go )
+ int pid;
+ attach_continue_t kind_of_go;
+{
+ int tt_status;
+ ttstate_t thread_state;
+ lwpid_t a_thread;
+ lwpid_t tid;
+
+ /* The process better be stopped.
+ */
+ if( process_state != STOPPED
+ && process_state != VFORKING )
+ warning( "Internal error attaching." );
+
+ /* Clear out old tthread info and start over. This has the
+ * side effect of ensuring that the TRAP is reported as being
+ * in the right thread (re-mapped from tid to pid).
+ *
+ * It's because we need to add the tthread _now_ that we
+ * need to call "clear_thread_info" _now_, and that's why
+ * "require_notification_of_events" doesn't clear the thread
+ * info (it's called later than this routine).
+ */
+ clear_thread_info();
+ a_thread = 0;
+
+ for (tid = get_process_first_stopped_thread_id (pid, &thread_state);
+ tid != 0;
+ tid = get_process_next_stopped_thread_id (pid, &thread_state))
+ {
+ thread_info *p;
+
+ if (a_thread == 0)
+ {
+ a_thread = tid;
+#ifdef THREAD_DEBUG
+ if( debug_on )
+ printf( "Attaching to process %d, thread %d\n",
+ pid, a_thread );
+#endif
+ }
+
+ /* Tell ourselves and the "rest of gdb" that this thread
+ * exists.
+ *
+ * This isn't really a hack. Other thread-based versions
+ * of gdb (e.g. gnu-nat.c) seem to do the same thing.
+ *
+ * We don't need to do mapping here, as we know this
+ * is the first thread and thus gets the real pid
+ * (and is "inferior_pid").
+ *
+ * NOTE: it probably isn't the originating thread,
+ * but that doesn't matter (we hope!).
+ */
+ add_tthread( pid, tid );
+ p = find_thread_info( tid );
+ if( NULL == p ) /* ?We just added it! */
+ error( "Internal error adding a thread on attach." );
+
+ copy_ttstate_t( &p->last_stop_state, thread_state );
+ p->have_state = 1;
+
+ if( DO_ATTACH_CONTINUE == kind_of_go ) {
+ /*
+ * If we are going to CONTINUE afterwards,
+ * raising a SIGTRAP, don't bother trying to
+ * handle this event. But check first!
+ */
+ switch( p->last_stop_state.tts_event ) {
+
+ case TTEVT_NONE:
+ /* Ok to set this handled.
+ */
+ break;
+
+ default:
+ warning( "Internal error; skipping event %s on process %d, thread %d.",
+ get_printable_name_of_ttrace_event(
+ p->last_stop_state.tts_event ),
+ p->pid, p->tid);
+ }
+
+ set_handled( pid, tid );
+
+ }
+ else {
+ /* There will be no "continue" opertion, so the
+ * process remains stopped. Don't set any events
+ * handled except the "gimmies".
+ */
+ switch( p->last_stop_state.tts_event ) {
+
+ case TTEVT_NONE:
+ /* Ok to ignore this.
+ */
+ set_handled( pid, tid );
+ break;
+
+ case TTEVT_EXEC:
+ case TTEVT_FORK:
+ /* Expected "other" FORK or EXEC event from a
+ * fork or vfork.
+ */
+ break;
+
+ default:
+ printf( "Internal error: failed to handle event %s on process %d, thread %d.",
+ get_printable_name_of_ttrace_event(
+ p->last_stop_state.tts_event ),
+ p->pid, p->tid);
+ }
+ }
+
+ add_thread( tid ); /* in thread.c */
+ }
+
+#ifdef PARANOIA
+ if( debug_on )
+ print_tthreads();
+#endif
+
+ /* One mustn't call ttrace_wait() after attaching via ttrace,
+ 'cause the process is stopped already.
+
+ However, the upper layers of gdb's execution control will
+ want to wait after attaching (but not after forks, in
+ which case they will be doing a "target_resume", anticipating
+ a later TTEVT_EXEC or TTEVT_FORK event).
+
+ To make this attach() implementation more compatible with
+ others, we'll make the attached-to process raise a SIGTRAP.
+
+ Issue: this continues only one thread. That could be
+ dangerous if the thread is blocked--the process won't run
+ and no trap will be raised. FIX! (check state.tts_flags?
+ need one that's either TTS_WASRUNNING--but we've stopped
+ it and made it TTS_WASSUSPENDED. Hum...FIXME!)
+ */
+ if( DO_ATTACH_CONTINUE == kind_of_go ) {
+ tt_status = call_real_ttrace(
+ TT_LWP_CONTINUE,
+ pid,
+ a_thread,
+ TT_USE_CURRENT_PC,
+ (TTRACE_ARG_TYPE) target_signal_to_host (TARGET_SIGNAL_TRAP),
+ TT_NIL);
+ if (errno)
+ perror_with_name ("ttrace");
+
+ clear_handled( a_thread ); /* So TRAP will be reported. */
+
+ /* Now running.
+ */
+ process_state = RUNNING;
+ }
+
+ attach_flag = 1;
+}
+#endif /* ATTACH_DETACH */
+
+
+#ifdef ATTACH_DETACH
+/* Start debugging the process whose number is PID.
+ * (A _real_ pid).
+ */
+int
+attach( pid )
+ int pid;
+{
+ int tt_status;
+
+ tt_status = call_real_ttrace (
+ TT_PROC_ATTACH,
+ pid,
+ (lwpid_t) TT_NIL,
+ TT_NIL,
+ (TTRACE_ARG_TYPE) TT_VERSION,
+ TT_NIL);
+ if (errno)
+ perror_with_name ("ttrace attach");
+
+ /* If successful, the process is now stopped.
+ */
+ process_state = STOPPED;
+
+ /* Our caller ("attach_command" in "infcmd.c")
+ * expects to do a "wait_for_inferior" after
+ * the attach, so make sure the inferior is
+ * running when we're done.
+ */
+ update_thread_state_after_attach( pid, DO_ATTACH_CONTINUE );
+
+ return pid;
+}
+
+
+#if defined(CHILD_POST_ATTACH)
+void
+child_post_attach (pid)
+ int pid;
+{
+#ifdef THREAD_DEBUG
+ if( debug_on )
+ printf( "child-post-attach call\n" );
+#endif
+
+ require_notification_of_events (pid);
+}
+#endif
+
+
+/* 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;
+ call_ttrace (TT_PROC_DETACH,
+ inferior_pid,
+ TT_NIL,
+ (TTRACE_ARG_TYPE) signal,
+ TT_NIL);
+ attach_flag = 0;
+
+ clear_thread_info();
+
+ /* Process-state? */
+}
+#endif /* ATTACH_DETACH */
+
+
+/* Default the type of the ttrace transfer to int. */
+#ifndef TTRACE_XFER_TYPE
+#define TTRACE_XFER_TYPE int
+#endif
+
+void
+_initialize_kernel_u_addr ()
+{
+}
+
+#if !defined (CHILD_XFER_MEMORY)
+/* NOTE! I tried using TTRACE_READDATA, etc., to read and write memory
+ in the NEW_SUN_TTRACE 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 (TTRACE_XFER_TYPE);
+ /* Round ending address up; get number of longwords that makes. */
+ register int count
+ = (((memaddr + len) - addr) + sizeof (TTRACE_XFER_TYPE) - 1)
+ / sizeof (TTRACE_XFER_TYPE);
+ /* Allocate buffer of that many longwords. */
+ register TTRACE_XFER_TYPE *buffer
+ = (TTRACE_XFER_TYPE *) alloca (count * sizeof (TTRACE_XFER_TYPE));
+
+ if (write)
+ {
+ /* Fill start and end extra bytes of buffer with existing memory data. */
+
+ if (addr != memaddr || len < (int) sizeof (TTRACE_XFER_TYPE)) {
+ /* Need part of initial word -- fetch it. */
+ buffer[0] = call_ttrace (TT_LWP_RDTEXT,
+ inferior_pid,
+ (TTRACE_ARG_TYPE) addr,
+ TT_NIL,
+ TT_NIL);
+ }
+
+ if (count > 1) /* FIXME, avoid if even boundary */
+ {
+ buffer[count - 1] = call_ttrace (TT_LWP_RDTEXT,
+ inferior_pid,
+ ((TTRACE_ARG_TYPE)
+ (addr + (count - 1) * sizeof (TTRACE_XFER_TYPE))),
+ TT_NIL,
+ TT_NIL);
+ }
+
+ /* Copy data to be written over corresponding part of buffer */
+
+ memcpy ((char *) buffer + (memaddr & (sizeof (TTRACE_XFER_TYPE) - 1)),
+ myaddr,
+ len);
+
+ /* Write the entire buffer. */
+
+ for (i = 0; i < count; i++, addr += sizeof (TTRACE_XFER_TYPE))
+ {
+ errno = 0;
+ call_ttrace (TT_LWP_WRDATA,
+ inferior_pid,
+ (TTRACE_ARG_TYPE) addr,
+ (TTRACE_ARG_TYPE) buffer[i],
+ TT_NIL);
+ if (errno)
+ {
+ /* Using the appropriate one (I or D) is necessary for
+ Gould NP1, at least. */
+ errno = 0;
+ call_ttrace (TT_LWP_WRTEXT,
+ inferior_pid,
+ (TTRACE_ARG_TYPE) addr,
+ (TTRACE_ARG_TYPE) buffer[i],
+ TT_NIL);
+ }
+ if (errno)
+ return 0;
+ }
+ }
+ else
+ {
+ /* Read all the longwords */
+ for (i = 0; i < count; i++, addr += sizeof (TTRACE_XFER_TYPE))
+ {
+ errno = 0;
+ buffer[i] = call_ttrace (TT_LWP_RDTEXT,
+ inferior_pid,
+ (TTRACE_ARG_TYPE) addr,
+ TT_NIL,
+ TT_NIL);
+ if (errno)
+ return 0;
+ QUIT;
+ }
+
+ /* Copy appropriate bytes out of the buffer. */
+ memcpy (myaddr,
+ (char *) buffer + (memaddr & (sizeof (TTRACE_XFER_TYPE) - 1)),
+ len);
+ }
+ return len;
+}
+
+
+static void
+udot_info ()
+{
+ int udot_off; /* Offset into user struct */
+ int udot_val; /* Value from user struct at udot_off */
+ char mess[128]; /* For messages */
+
+ if (!target_has_execution)
+ {
+ error ("The program is not being run.");
+ }
+
+#if !defined (KERNEL_U_SIZE)
+
+ /* Adding support for this command is easy. Typically you just add a
+ routine, called "kernel_u_size" that returns the size of the user
+ struct, to the appropriate *-nat.c file and then add to the native
+ config file "#define KERNEL_U_SIZE kernel_u_size()" */
+ error ("Don't know how large ``struct user'' is in this version of gdb.");
+
+#else
+
+ for (udot_off = 0; udot_off < KERNEL_U_SIZE; udot_off += sizeof (udot_val))
+ {
+ if ((udot_off % 24) == 0)
+ {
+ if (udot_off > 0)
+ {
+ printf_filtered ("\n");
+ }
+ printf_filtered ("%04x:", udot_off);
+ }
+ udot_val = call_ttrace (TT_LWP_RUREGS,
+ inferior_pid,
+ (TTRACE_ARG_TYPE) udot_off,
+ TT_NIL,
+ TT_NIL);
+ if (errno != 0)
+ {
+ sprintf (mess, "\nreading user struct at offset 0x%x", udot_off);
+ perror_with_name (mess);
+ }
+ /* Avoid using nonportable (?) "*" in print specs */
+ printf_filtered (sizeof (int) == 4 ? " 0x%08x" : " 0x%16x", udot_val);
+ }
+ printf_filtered ("\n");
+
+#endif
+}
+#endif /* !defined (CHILD_XFER_MEMORY). */
+
+/* TTrace version of "target_pid_to_exec_file"
+ */
+char *
+child_pid_to_exec_file (tid)
+ int tid;
+{
+ static char exec_file_buffer[1024];
+ int tt_status;
+ CORE_ADDR top_of_stack;
+ char four_chars[4];
+ int name_index;
+ int i;
+ int done;
+ int saved_inferior_pid;
+
+ /* As of 10.x HP-UX, there's an explicit request to get the
+ *pathname.
+ */
+ tt_status = call_ttrace (TT_PROC_GET_PATHNAME,
+ tid,
+ (TTRACE_ARG_TYPE) exec_file_buffer,
+ (TTRACE_ARG_TYPE) sizeof (exec_file_buffer) - 1,
+ TT_NIL);
+ if (tt_status >= 0)
+ return exec_file_buffer;
+
+ /* ??rehrauer: The above request may or may not be broken. It
+ doesn't seem to work when I use it. But, it may be designed
+ to only work immediately after an exec event occurs. (I'm
+ waiting for COSL to explain.)
+
+ In any case, if it fails, try a really, truly amazingly gross
+ hack that DDE uses, of pawing through the process' data
+ segment to find the pathname.
+ */
+ top_of_stack = 0x7b03a000;
+ name_index = 0;
+ done = 0;
+
+ /* On the chance that pid != inferior_pid, set inferior_pid
+ to pid, so that (grrrr!) implicit uses of inferior_pid get
+ the right id.
+ */
+ saved_inferior_pid = inferior_pid;
+ inferior_pid = tid;
+
+ /* Try to grab a null-terminated string. */
+ while (! done) {
+ if (target_read_memory (top_of_stack, four_chars, 4) != 0)
+ {
+ inferior_pid = saved_inferior_pid;
+ return NULL;
+ }
+ for (i = 0; i < 4; i++) {
+ exec_file_buffer[name_index++] = four_chars[i];
+ done = (four_chars[i] == '\0');
+ if (done)
+ break;
+ }
+ top_of_stack += 4;
+ }
+
+ if (exec_file_buffer[0] == '\0')
+ {
+ inferior_pid = saved_inferior_pid;
+ return NULL;
+ }
+
+ inferior_pid = saved_inferior_pid;
+ return exec_file_buffer;
+}
+
+
+void
+pre_fork_inferior ()
+{
+ int status;
+
+ status = pipe (startup_semaphore.parent_channel);
+ if (status < 0) {
+ warning ("error getting parent pipe for startup semaphore");
+ return;
+ }
+
+ status = pipe (startup_semaphore.child_channel);
+ if (status < 0) {
+ warning ("error getting child pipe for startup semaphore");
+ return;
+ }
+}
+
+/* Called via #define REQUIRE_ATTACH from inftarg.c,
+ * ultimately from "follow_inferior_fork" in infrun.c,
+ * itself called from "resume".
+ *
+ * This seems to be intended to attach after a fork or
+ * vfork, while "attach" is used to attach to a pid
+ * given by the user. The check for an existing attach
+ * seems odd--it always fails in our test system.
+ */
+int
+hppa_require_attach (pid)
+ int pid;
+{
+ int tt_status;
+ CORE_ADDR pc;
+ CORE_ADDR pc_addr;
+ unsigned int regs_offset;
+ process_state_t old_process_state = process_state;
+
+ /* Are we already attached? There appears to be no explicit
+ * way to answer this via ttrace, so we try something which
+ * should be innocuous if we are attached. If that fails,
+ * then we assume we're not attached, and so attempt to make
+ * it so.
+ */
+ errno = 0;
+ tt_status = call_real_ttrace (TT_PROC_STOP,
+ pid,
+ (lwpid_t) TT_NIL,
+ (TTRACE_ARG_TYPE) TT_NIL,
+ (TTRACE_ARG_TYPE) TT_NIL,
+ TT_NIL);
+
+ if (errno)
+ {
+ /* No change to process-state!
+ */
+ errno = 0;
+ pid = attach (pid);
+ }
+ else
+ {
+ /* If successful, the process is now stopped. But if
+ * we're VFORKING, the parent is still running, so don't
+ * change the process state.
+ */
+ if( process_state != VFORKING )
+ process_state = STOPPED;
+
+ /* If we were already attached, you'd think that we
+ * would need to start going again--but you'd be wrong,
+ * as the fork-following code is actually in the middle
+ * of the "resume" routine in in "infrun.c" and so
+ * will (almost) immediately do a resume.
+ *
+ * On the other hand, if we are VFORKING, which means
+ * that the child and the parent share a process for a
+ * while, we know that "resume" won't be resuming
+ * until the child EXEC event is seen. But we still
+ * don't want to continue, as the event is already
+ * there waiting.
+ */
+ update_thread_state_after_attach( pid, DONT_ATTACH_CONTINUE );
+ } /* STOP succeeded */
+
+ return pid;
+}
+
+int
+hppa_require_detach (pid, signal)
+ int pid;
+ int signal;
+{
+ int tt_status;
+
+ /* If signal is non-zero, we must pass the signal on to the active
+ thread prior to detaching. We do this by continuing the threads
+ with the signal.
+ */
+ if (signal != 0)
+ {
+ errno = 0;
+ threads_continue_all_with_signals( pid, signal );
+ }
+
+ errno = 0;
+ tt_status = call_ttrace (TT_PROC_DETACH,
+ pid,
+ TT_NIL,
+ TT_NIL,
+ TT_NIL);
+
+ errno = 0; /* Ignore any errors. */
+
+ /* process_state? */
+
+ return pid;
+}
+
+/* Given the starting address of a memory page, hash it to a bucket in
+ the memory page dictionary.
+ */
+static int
+get_dictionary_bucket_of_page (page_start)
+ CORE_ADDR page_start;
+{
+ int hash;
+
+ hash = (page_start / memory_page_dictionary.page_size);
+ hash = hash % MEMORY_PAGE_DICTIONARY_BUCKET_COUNT;
+
+ return hash;
+}
+
+
+/* Given a memory page's starting address, get (i.e., find an existing
+ or create a new) dictionary entry for the page. The page will be
+ write-protected when this function returns, but may have a reference
+ count of 0 (if the page was newly-added to the dictionary).
+ */
+static memory_page_t *
+get_dictionary_entry_of_page (pid, page_start)
+ int pid;
+ CORE_ADDR page_start;
+{
+ int bucket;
+ memory_page_t * page = NULL;
+ memory_page_t * previous_page = NULL;
+
+ /* We're going to be using the dictionary now, than-kew. */
+ require_memory_page_dictionary (pid);
+
+ /* Try to find an existing dictionary entry for this page. Hash
+ on the page's starting address.
+ */
+ bucket = get_dictionary_bucket_of_page (page_start);
+ page = &memory_page_dictionary.buckets[bucket];
+ while (page != NULL)
+ {
+ if (page->page_start == page_start)
+ break;
+ previous_page = page;
+ page = page->next;
+ }
+
+ /* Did we find a dictionary entry for this page? If not, then
+ add it to the dictionary now.
+ */
+ if (page == NULL)
+ {
+ /* Create a new entry. */
+ page = (memory_page_t *) xmalloc (sizeof (memory_page_t));
+ page->page_start = page_start;
+ page->reference_count = 0;
+ page->next = NULL;
+ page->previous = NULL;
+
+ /* We'll write-protect the page now, if that's allowed. */
+ page->original_permissions = write_protect_page (pid, page_start);
+
+ /* Add the new entry to the dictionary. */
+ page->previous = previous_page;
+ previous_page->next = page;
+
+ memory_page_dictionary.page_count++;
+ }
+
+ return page;
+}
+
+
+static void
+remove_dictionary_entry_of_page (pid, page)
+ int pid;
+ memory_page_t * page;
+{
+ /* Restore the page's original permissions. */
+ unwrite_protect_page (pid, page->page_start, page->original_permissions);
+
+ /* Kick the page out of the dictionary. */
+ if (page->previous != NULL)
+ page->previous->next = page->next;
+ if (page->next != NULL)
+ page->next->previous = page->previous;
+
+ /* Just in case someone retains a handle to this after it's freed. */
+ page->page_start = (CORE_ADDR) 0;
+
+ memory_page_dictionary.page_count--;
+
+ free (page);
+}
+
+
+static void
+hppa_enable_syscall_events (pid)
+ int pid;
+{
+ int tt_status;
+ ttevent_t ttrace_events;
+
+ /* Get the set of events that are currently enabled. */
+ tt_status = call_ttrace (TT_PROC_GET_EVENT_MASK,
+ pid,
+ (TTRACE_ARG_TYPE) &ttrace_events,
+ (TTRACE_ARG_TYPE) sizeof (ttrace_events),
+ TT_NIL);
+ if (errno)
+ perror_with_name ("ttrace");
+
+ /* Add syscall events to that set. */
+ ttrace_events.tte_events |= TTEVT_SYSCALL_ENTRY;
+ ttrace_events.tte_events |= TTEVT_SYSCALL_RETURN;
+
+ tt_status = call_ttrace (TT_PROC_SET_EVENT_MASK,
+ pid,
+ (TTRACE_ARG_TYPE) &ttrace_events,
+ (TTRACE_ARG_TYPE) sizeof (ttrace_events),
+ TT_NIL);
+ if (errno)
+ perror_with_name ("ttrace");
+}
+
+
+static void
+hppa_disable_syscall_events (pid)
+ int pid;
+{
+ int tt_status;
+ ttevent_t ttrace_events;
+
+ /* Get the set of events that are currently enabled. */
+ tt_status = call_ttrace (TT_PROC_GET_EVENT_MASK,
+ pid,
+ (TTRACE_ARG_TYPE) &ttrace_events,
+ (TTRACE_ARG_TYPE) sizeof (ttrace_events),
+ TT_NIL);
+ if (errno)
+ perror_with_name ("ttrace");
+
+ /* Remove syscall events from that set. */
+ ttrace_events.tte_events &= ~TTEVT_SYSCALL_ENTRY;
+ ttrace_events.tte_events &= ~TTEVT_SYSCALL_RETURN;
+
+ tt_status = call_ttrace (TT_PROC_SET_EVENT_MASK,
+ pid,
+ (TTRACE_ARG_TYPE) &ttrace_events,
+ (TTRACE_ARG_TYPE) sizeof (ttrace_events),
+ TT_NIL);
+ if (errno)
+ perror_with_name ("ttrace");
+}
+
+
+/* The address range beginning with START and ending with START+LEN-1
+ (inclusive) is to be watched via page-protection by a new watchpoint.
+ Set protection for all pages that overlap that range.
+
+ Note that our caller sets TYPE to:
+ 0 for a bp_hardware_watchpoint,
+ 1 for a bp_read_watchpoint,
+ 2 for a bp_access_watchpoint
+
+ (Yes, this is intentionally (though lord only knows why) different
+ from the TYPE that is passed to hppa_remove_hw_watchpoint.)
+ */
+int
+hppa_insert_hw_watchpoint (pid, start, len, type)
+ int pid;
+ CORE_ADDR start;
+ LONGEST len;
+ int type;
+{
+ CORE_ADDR page_start;
+ int dictionary_was_empty;
+ int page_size;
+ int page_id;
+ LONGEST range_size_in_pages;
+
+ if (type != 0)
+ error ("read or access hardware watchpoints not supported on HP-UX");
+
+ /* Examine all pages in the address range. */
+ require_memory_page_dictionary ();
+
+ dictionary_was_empty = (memory_page_dictionary.page_count == (LONGEST) 0);
+
+ page_size = memory_page_dictionary.page_size;
+ page_start = (start / page_size) * page_size;
+ range_size_in_pages = ((LONGEST) len + (LONGEST) page_size - 1) / (LONGEST) page_size;
+
+ for (page_id=0; page_id < range_size_in_pages; page_id++, page_start+=page_size)
+ {
+ memory_page_t * page;
+
+ /* This gets the page entered into the dictionary if it was
+ not already entered.
+ */
+ page = get_dictionary_entry_of_page (pid, page_start);
+ page->reference_count++;
+ }
+
+ /* Our implementation depends on seeing calls to kernel code, for the
+ following reason. Here we ask to be notified of syscalls.
+
+ When a protected page is accessed by user code, HP-UX raises a SIGBUS.
+ Fine.
+
+ But when kernel code accesses the page, it doesn't give a SIGBUS.
+ Rather, the system call that touched the page fails, with errno=EFAULT.
+ Not good for us.
+
+ We could accomodate this "feature" by asking to be notified of syscall
+ entries & exits; upon getting an entry event, disabling page-protections;
+ upon getting an exit event, reenabling page-protections and then checking
+ if any watchpoints triggered.
+
+ However, this turns out to be a real performance loser. syscalls are
+ usually a frequent occurrence. Having to unprotect-reprotect all watched
+ pages, and also to then read all watched memory locations and compare for
+ triggers, can be quite expensive.
+
+ Instead, we'll only ask to be notified of syscall exits. When we get
+ one, we'll check whether errno is set. If not, or if it's not EFAULT,
+ we can just continue the inferior.
+
+ If errno is set upon syscall exit to EFAULT, we must perform some fairly
+ hackish stuff to determine whether the failure really was due to a
+ page-protect trap on a watched location.
+ */
+ if (dictionary_was_empty)
+ hppa_enable_syscall_events (pid);
+
+ return 1;
+}
+
+
+/* The address range beginning with START and ending with START+LEN-1
+ (inclusive) was being watched via page-protection by a watchpoint
+ which has been removed. Remove protection for all pages that
+ overlap that range, which are not also being watched by other
+ watchpoints.
+ */
+int
+hppa_remove_hw_watchpoint (pid, start, len, type)
+ int pid;
+ CORE_ADDR start;
+ LONGEST len;
+ enum bptype type;
+{
+ CORE_ADDR page_start;
+ int dictionary_is_empty;
+ int page_size;
+ int page_id;
+ LONGEST range_size_in_pages;
+
+ if (type != 0)
+ error ("read or access hardware watchpoints not supported on HP-UX");
+
+ /* Examine all pages in the address range. */
+ require_memory_page_dictionary ();
+
+ page_size = memory_page_dictionary.page_size;
+ page_start = (start / page_size) * page_size;
+ range_size_in_pages = ((LONGEST) len + (LONGEST) page_size - 1) / (LONGEST) page_size;
+
+ for (page_id=0; page_id < range_size_in_pages; page_id++, page_start+=page_size)
+ {
+ memory_page_t * page;
+
+ page = get_dictionary_entry_of_page (pid, page_start);
+ page->reference_count--;
+
+ /* Was this the last reference of this page? If so, then we
+ must scrub the entry from the dictionary, and also restore
+ the page's original permissions.
+ */
+ if (page->reference_count == 0)
+ remove_dictionary_entry_of_page (pid, page);
+ }
+
+ dictionary_is_empty = (memory_page_dictionary.page_count == (LONGEST) 0);
+
+ /* If write protections are currently disallowed, then that implies that
+ wait_for_inferior believes that the inferior is within a system call.
+ Since we want to see both syscall entry and return, it's clearly not
+ good to disable syscall events in this state!
+
+ ??rehrauer: Yeah, it'd be better if we had a specific flag that said,
+ "inferior is between syscall events now". Oh well.
+ */
+ if (dictionary_is_empty && memory_page_dictionary.page_protections_allowed)
+ hppa_disable_syscall_events (pid);
+
+ return 1;
+}
+
+
+/* Could we implement a watchpoint of this type via our available
+ hardware support?
+
+ This query does not consider whether a particular address range
+ could be so watched, but just whether support is generally available
+ for such things. See hppa_range_profitable_for_hw_watchpoint for a
+ query that answers whether a particular range should be watched via
+ hardware support.
+ */
+int
+hppa_can_use_hw_watchpoint (type, cnt, ot)
+ enum bptype type;
+ int cnt;
+ enum bptype ot;
+{
+ return (type == bp_hardware_watchpoint);
+}
+
+
+/* Assuming we could set a hardware watchpoint on this address, do
+ we think it would be profitable ("a good idea") to do so? If not,
+ we can always set a regular (aka single-step & test) watchpoint
+ on the address...
+ */
+int
+hppa_range_profitable_for_hw_watchpoint (pid, start, len)
+ int pid;
+ CORE_ADDR start;
+ LONGEST len;
+{
+ int range_is_stack_based;
+ int range_is_accessible;
+ CORE_ADDR page_start;
+ int page_size;
+ int page;
+ LONGEST range_size_in_pages;
+
+ /* ??rehrauer: For now, say that all addresses are potentially
+ profitable. Possibly later we'll want to test the address
+ for "stackness"?
+ */
+ range_is_stack_based = 0;
+
+ /* If any page in the range is inaccessible, then we cannot
+ really use hardware watchpointing, even though our client
+ thinks we can. In that case, it's actually an error to
+ attempt to use hw watchpoints, so we'll tell our client
+ that the range is "unprofitable", and hope that they listen...
+ */
+ range_is_accessible = 1; /* Until proven otherwise. */
+
+ /* Examine all pages in the address range. */
+ errno = 0;
+ page_size = sysconf (_SC_PAGE_SIZE);
+
+ /* If we can't determine page size, we're hosed. Tell our
+ client it's unprofitable to use hw watchpoints for this
+ range.
+ */
+ if (errno || (page_size <= 0))
+ {
+ errno = 0;
+ return 0;
+ }
+
+ page_start = (start / page_size) * page_size;
+ range_size_in_pages = len / (LONGEST)page_size;
+
+ for (page=0; page < range_size_in_pages; page++, page_start+=page_size)
+ {
+ int tt_status;
+ int page_permissions;
+
+ /* Is this page accessible? */
+ errno = 0;
+ tt_status = call_ttrace (TT_PROC_GET_MPROTECT,
+ pid,
+ (TTRACE_ARG_TYPE) page_start,
+ TT_NIL,
+ (TTRACE_ARG_TYPE) &page_permissions);
+ if (errno || (tt_status < 0))
+ {
+ errno = 0;
+ range_is_accessible = 0;
+ break;
+ }
+
+ /* Yes, go for another... */
+ }
+
+ return (! range_is_stack_based && range_is_accessible);
+}
+
+
+char *
+hppa_pid_or_tid_to_str (id)
+ pid_t id;
+{
+ static char buf[100]; /* Static because address returned. */
+
+ /* Does this appear to be a process? If so, print it that way. */
+ if (is_process_id (id))
+ return hppa_pid_to_str (id);
+
+ /* Else, print both the GDB thread number and the system thread id. */
+ sprintf (buf, "thread %d (", pid_to_thread_id (id));
+ strcat (buf, hppa_tid_to_str (id));
+ strcat (buf, ")\0");
+
+ return buf;
+}
+
+
+/* If the current pid is not the pid this module reported
+ * from "ptrace_wait" with the most recent event, then the
+ * user has switched threads.
+ *
+ * If the last reported event was a breakpoint, then return
+ * the old thread id, else return 0.
+ */
+pid_t
+hppa_switched_threads( gdb_pid )
+ pid_t gdb_pid;
+{
+ if( gdb_pid == old_gdb_pid ) {
+ /*
+ * Core gdb is working with the same pid that it
+ * was before we reported the last event. This
+ * is ok: e.g. we reported hitting a thread-specific
+ * breakpoint, but we were reporting the wrong
+ * thread, so the core just ignored the event.
+ *
+ * No thread switch has happened.
+ */
+ return (pid_t) 0;
+ }
+ else if( gdb_pid == reported_pid ) {
+ /*
+ * Core gdb is working with the pid we reported, so
+ * any continue or step will be able to figure out
+ * that it needs to step over any hit breakpoints
+ * without our (i.e. PREPARE_TO_PROCEED's) help.
+ */
+ return (pid_t) 0;
+ }
+ else if( !reported_bpt ) {
+ /*
+ * The core switched, but we didn't just report a
+ * breakpoint, so there's no just-hit breakpoint
+ * instruction at "reported_pid"'s PC, and thus there
+ * is no need to step over it.
+ */
+ return (pid_t) 0;
+ }
+ else {
+ /* There's been a real switch, and we reported
+ * a hit breakpoint. Let "hppa_prepare_to_proceed"
+ * know, so it can see whether the breakpoint is
+ * still active.
+ */
+ return reported_pid;
+ }
+
+ /* Keep compiler happy with an obvious return at the end.
+ */
+ return (pid_t) 0;
+}
+
+void
+hppa_ensure_vforking_parent_remains_stopped (pid)
+ int pid;
+{
+ /* Nothing to do when using ttrace. Only the ptrace-based implementation
+ must do real work.
+ */
+}
+
+
+int
+hppa_resume_execd_vforking_child_to_get_parent_vfork ()
+{
+ return 0; /* No, the parent vfork is available now. */
+}
+
+
+
+void
+_initialize_infttrace ()
+{
+ /* Initialize the ttrace-based hardware watchpoint implementation. */
+ memory_page_dictionary.page_count = (LONGEST) -1;
+ memory_page_dictionary.page_protections_allowed = 1;
+
+ errno = 0;
+ memory_page_dictionary.page_size = sysconf (_SC_PAGE_SIZE);
+
+ if (errno || (memory_page_dictionary.page_size <= 0))
+ perror_with_name ("sysconf");
+}
+
diff --git a/gdb/irix4-nat.c b/gdb/irix4-nat.c
new file mode 100644
index 00000000000..5a6e1112229
--- /dev/null
+++ b/gdb/irix4-nat.c
@@ -0,0 +1,195 @@
+/* Native support for the SGI Iris running IRIX version 4, for GDB.
+ Copyright 1988, 1989, 1990, 1991, 1992, 1993, 1995
+ Free Software Foundation, Inc.
+ Contributed by Alessandro Forin(af@cs.cmu.edu) at CMU
+ and by Per Bothner(bothner@cs.wisc.edu) at U.Wisconsin.
+ Implemented for Irix 4.x by Garrett A. Wollman.
+
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "inferior.h"
+#include "gdbcore.h"
+
+#include <sys/time.h>
+#include <sys/procfs.h>
+#include <setjmp.h> /* For JB_XXX. */
+
+/* Size of elements in jmpbuf */
+
+#define JB_ELEMENT_SIZE 4
+
+typedef unsigned int greg_t; /* why isn't this defined? */
+
+static void
+fetch_core_registers PARAMS ((char *, unsigned int, int, CORE_ADDR));
+
+/*
+ * See the comment in m68k-tdep.c regarding the utility of these functions.
+ */
+
+void
+supply_gregset (gregsetp)
+ gregset_t *gregsetp;
+{
+ register int regi;
+ register greg_t *regp = (greg_t *)(gregsetp->gp_regs);
+ static char zerobuf[MAX_REGISTER_RAW_SIZE] = {0};
+
+ /* FIXME: somewhere, there should be a #define for the meaning
+ of this magic number 32; we should use that. */
+ for(regi = 0; regi < 32; regi++)
+ supply_register (regi, (char *)(regp + regi));
+
+ supply_register (PC_REGNUM, (char *)&(gregsetp->gp_pc));
+ supply_register (HI_REGNUM, (char *)&(gregsetp->gp_mdhi));
+ supply_register (LO_REGNUM, (char *)&(gregsetp->gp_mdlo));
+ supply_register (CAUSE_REGNUM, (char *)&(gregsetp->gp_cause));
+
+ /* Fill inaccessible registers with zero. */
+ supply_register (BADVADDR_REGNUM, zerobuf);
+}
+
+void
+fill_gregset (gregsetp, regno)
+ gregset_t *gregsetp;
+ int regno;
+{
+ int regi;
+ register greg_t *regp = (greg_t *)(gregsetp->gp_regs);
+
+ /* same FIXME as above wrt 32*/
+ for (regi = 0; regi < 32; regi++)
+ if ((regno == -1) || (regno == regi))
+ *(regp + regi) = *(greg_t *) &registers[REGISTER_BYTE (regi)];
+
+ if ((regno == -1) || (regno == PC_REGNUM))
+ gregsetp->gp_pc = *(greg_t *) &registers[REGISTER_BYTE (PC_REGNUM)];
+
+ if ((regno == -1) || (regno == CAUSE_REGNUM))
+ gregsetp->gp_cause = *(greg_t *) &registers[REGISTER_BYTE (CAUSE_REGNUM)];
+
+ if ((regno == -1) || (regno == HI_REGNUM))
+ gregsetp->gp_mdhi = *(greg_t *) &registers[REGISTER_BYTE (HI_REGNUM)];
+
+ if ((regno == -1) || (regno == LO_REGNUM))
+ gregsetp->gp_mdlo = *(greg_t *) &registers[REGISTER_BYTE (LO_REGNUM)];
+}
+
+/*
+ * Now we do the same thing for floating-point registers.
+ * We don't bother to condition on FP0_REGNUM since any
+ * reasonable MIPS configuration has an R3010 in it.
+ *
+ * Again, see the comments in m68k-tdep.c.
+ */
+
+void
+supply_fpregset (fpregsetp)
+ fpregset_t *fpregsetp;
+{
+ register int regi;
+ static char zerobuf[MAX_REGISTER_RAW_SIZE] = {0};
+
+ for (regi = 0; regi < 32; regi++)
+ supply_register (FP0_REGNUM + regi,
+ (char *)&fpregsetp->fp_r.fp_regs[regi]);
+
+ supply_register (FCRCS_REGNUM, (char *)&fpregsetp->fp_csr);
+
+ /* FIXME: how can we supply FCRIR_REGNUM? SGI doesn't tell us. */
+ supply_register (FCRIR_REGNUM, zerobuf);
+}
+
+void
+fill_fpregset (fpregsetp, regno)
+ fpregset_t *fpregsetp;
+ int regno;
+{
+ int regi;
+ char *from, *to;
+
+ for (regi = FP0_REGNUM; regi < FP0_REGNUM + 32; regi++)
+ {
+ if ((regno == -1) || (regno == regi))
+ {
+ from = (char *) &registers[REGISTER_BYTE (regi)];
+ to = (char *) &(fpregsetp->fp_r.fp_regs[regi - FP0_REGNUM]);
+ memcpy(to, from, REGISTER_RAW_SIZE (regi));
+ }
+ }
+
+ if ((regno == -1) || (regno == FCRCS_REGNUM))
+ fpregsetp->fp_csr = *(unsigned *) &registers[REGISTER_BYTE(FCRCS_REGNUM)];
+}
+
+
+/* Figure out where the longjmp will land.
+ 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 jb_addr;
+
+ jb_addr = read_register (A0_REGNUM);
+
+ 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;
+}
+
+static void
+fetch_core_registers (core_reg_sect, core_reg_size, which, reg_addr)
+ char *core_reg_sect;
+ unsigned core_reg_size;
+ int which; /* Unused */
+ CORE_ADDR reg_addr; /* Unused */
+{
+ if (core_reg_size != REGISTER_BYTES)
+ {
+ warning ("wrong size gregset struct in core file");
+ return;
+ }
+
+ memcpy ((char *)registers, core_reg_sect, core_reg_size);
+}
+
+
+/* Register that we are able to handle irix4 core file formats.
+ FIXME: is this really bfd_target_unknown_flavour? */
+
+static struct core_fns irix4_core_fns =
+{
+ bfd_target_unknown_flavour,
+ fetch_core_registers,
+ NULL
+};
+
+void
+_initialize_core_irix4 ()
+{
+ add_core_fns (&irix4_core_fns);
+}
diff --git a/gdb/irix5-nat.c b/gdb/irix5-nat.c
new file mode 100644
index 00000000000..b3373a99168
--- /dev/null
+++ b/gdb/irix5-nat.c
@@ -0,0 +1,1349 @@
+/* Native support for the SGI Iris running IRIX version 5, for GDB.
+ Copyright 1988, 89, 90, 91, 92, 93, 94, 95, 96, 98, 1999
+ Free Software Foundation, Inc.
+ Contributed by Alessandro Forin(af@cs.cmu.edu) at CMU
+ and by Per Bothner(bothner@cs.wisc.edu) at U.Wisconsin.
+ Implemented for Irix 4.x by Garrett A. Wollman.
+ Modified for Irix 5.x by Ian Lance Taylor.
+
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "inferior.h"
+#include "gdbcore.h"
+#include "target.h"
+
+#include "gdb_string.h"
+#include <sys/time.h>
+#include <sys/procfs.h>
+#include <setjmp.h> /* For JB_XXX. */
+
+static void
+fetch_core_registers PARAMS ((char *, unsigned int, int, CORE_ADDR));
+
+/* Size of elements in jmpbuf */
+
+#define JB_ELEMENT_SIZE 4
+
+/*
+ * See the comment in m68k-tdep.c regarding the utility of these functions.
+ *
+ * These definitions are from the MIPS SVR4 ABI, so they may work for
+ * any MIPS SVR4 target.
+ */
+
+void
+supply_gregset (gregsetp)
+ gregset_t *gregsetp;
+{
+ register int regi;
+ register greg_t *regp = &(*gregsetp)[0];
+ int gregoff = sizeof (greg_t) - MIPS_REGSIZE;
+ static char zerobuf[MAX_REGISTER_RAW_SIZE] = {0};
+
+ for(regi = 0; regi <= CTX_RA; regi++)
+ supply_register (regi, (char *)(regp + regi) + gregoff);
+
+ supply_register (PC_REGNUM, (char *)(regp + CTX_EPC) + gregoff);
+ supply_register (HI_REGNUM, (char *)(regp + CTX_MDHI) + gregoff);
+ supply_register (LO_REGNUM, (char *)(regp + CTX_MDLO) + gregoff);
+ supply_register (CAUSE_REGNUM, (char *)(regp + CTX_CAUSE) + gregoff);
+
+ /* Fill inaccessible registers with zero. */
+ supply_register (BADVADDR_REGNUM, zerobuf);
+}
+
+void
+fill_gregset (gregsetp, regno)
+ gregset_t *gregsetp;
+ int regno;
+{
+ int regi;
+ register greg_t *regp = &(*gregsetp)[0];
+
+ /* Under Irix6, if GDB is built with N32 ABI and is debugging an O32
+ executable, we have to sign extend the registers to 64 bits before
+ filling in the gregset structure. */
+
+ for (regi = 0; regi <= CTX_RA; regi++)
+ if ((regno == -1) || (regno == regi))
+ *(regp + regi) =
+ extract_signed_integer (&registers[REGISTER_BYTE (regi)],
+ REGISTER_RAW_SIZE (regi));
+
+ if ((regno == -1) || (regno == PC_REGNUM))
+ *(regp + CTX_EPC) =
+ extract_signed_integer (&registers[REGISTER_BYTE (PC_REGNUM)],
+ REGISTER_RAW_SIZE (PC_REGNUM));
+
+ if ((regno == -1) || (regno == CAUSE_REGNUM))
+ *(regp + CTX_CAUSE) =
+ extract_signed_integer (&registers[REGISTER_BYTE (CAUSE_REGNUM)],
+ REGISTER_RAW_SIZE (CAUSE_REGNUM));
+
+ if ((regno == -1) || (regno == HI_REGNUM))
+ *(regp + CTX_MDHI) =
+ extract_signed_integer (&registers[REGISTER_BYTE (HI_REGNUM)],
+ REGISTER_RAW_SIZE (HI_REGNUM));
+
+ if ((regno == -1) || (regno == LO_REGNUM))
+ *(regp + CTX_MDLO) =
+ extract_signed_integer (&registers[REGISTER_BYTE (LO_REGNUM)],
+ REGISTER_RAW_SIZE (LO_REGNUM));
+}
+
+/*
+ * Now we do the same thing for floating-point registers.
+ * We don't bother to condition on FP0_REGNUM since any
+ * reasonable MIPS configuration has an R3010 in it.
+ *
+ * Again, see the comments in m68k-tdep.c.
+ */
+
+void
+supply_fpregset (fpregsetp)
+ fpregset_t *fpregsetp;
+{
+ register int regi;
+ static char zerobuf[MAX_REGISTER_RAW_SIZE] = {0};
+
+ /* FIXME, this is wrong for the N32 ABI which has 64 bit FP regs. */
+
+ for (regi = 0; regi < 32; regi++)
+ supply_register (FP0_REGNUM + regi,
+ (char *)&fpregsetp->fp_r.fp_regs[regi]);
+
+ supply_register (FCRCS_REGNUM, (char *)&fpregsetp->fp_csr);
+
+ /* FIXME: how can we supply FCRIR_REGNUM? SGI doesn't tell us. */
+ supply_register (FCRIR_REGNUM, zerobuf);
+}
+
+void
+fill_fpregset (fpregsetp, regno)
+ fpregset_t *fpregsetp;
+ int regno;
+{
+ int regi;
+ char *from, *to;
+
+ /* FIXME, this is wrong for the N32 ABI which has 64 bit FP regs. */
+
+ for (regi = FP0_REGNUM; regi < FP0_REGNUM + 32; regi++)
+ {
+ if ((regno == -1) || (regno == regi))
+ {
+ from = (char *) &registers[REGISTER_BYTE (regi)];
+ to = (char *) &(fpregsetp->fp_r.fp_regs[regi - FP0_REGNUM]);
+ memcpy(to, from, REGISTER_RAW_SIZE (regi));
+ }
+ }
+
+ if ((regno == -1) || (regno == FCRCS_REGNUM))
+ fpregsetp->fp_csr = *(unsigned *) &registers[REGISTER_BYTE(FCRCS_REGNUM)];
+}
+
+
+/* Figure out where the longjmp will land.
+ 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 jb_addr;
+
+ jb_addr = read_register (A0_REGNUM);
+
+ 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;
+}
+
+static void
+fetch_core_registers (core_reg_sect, core_reg_size, which, reg_addr)
+ char *core_reg_sect;
+ unsigned core_reg_size;
+ int which; /* Unused */
+ CORE_ADDR reg_addr; /* Unused */
+{
+ if (core_reg_size == REGISTER_BYTES)
+ {
+ memcpy ((char *)registers, core_reg_sect, core_reg_size);
+ }
+ else if (MIPS_REGSIZE == 4 &&
+ core_reg_size == (2 * MIPS_REGSIZE) * NUM_REGS)
+ {
+ /* This is a core file from a N32 executable, 64 bits are saved
+ for all registers. */
+ char *srcp = core_reg_sect;
+ char *dstp = registers;
+ int regno;
+
+ for (regno = 0; regno < NUM_REGS; regno++)
+ {
+ if (regno >= FP0_REGNUM && regno < (FP0_REGNUM + 32))
+ {
+ /* FIXME, this is wrong, N32 has 64 bit FP regs, but GDB
+ currently assumes that they are 32 bit. */
+ *dstp++ = *srcp++;
+ *dstp++ = *srcp++;
+ *dstp++ = *srcp++;
+ *dstp++ = *srcp++;
+ if (REGISTER_RAW_SIZE(regno) == 4)
+ {
+ /* copying 4 bytes from eight bytes?
+ I don't see how this can be right... */
+ srcp += 4;
+ }
+ else
+ {
+ /* copy all 8 bytes (sizeof(double)) */
+ *dstp++ = *srcp++;
+ *dstp++ = *srcp++;
+ *dstp++ = *srcp++;
+ *dstp++ = *srcp++;
+ }
+ }
+ else
+ {
+ srcp += 4;
+ *dstp++ = *srcp++;
+ *dstp++ = *srcp++;
+ *dstp++ = *srcp++;
+ *dstp++ = *srcp++;
+ }
+ }
+ }
+ else
+ {
+ warning ("wrong size gregset struct in core file");
+ return;
+ }
+
+ registers_fetched ();
+}
+
+/* Irix 5 uses what appears to be a unique form of shared library
+ support. This is a copy of solib.c modified for Irix 5. */
+/* FIXME: Most of this code could be merged with osfsolib.c and solib.c
+ by using next_link_map_member and xfer_link_map_member in solib.c. */
+
+#include <sys/types.h>
+#include <signal.h>
+#include <sys/param.h>
+#include <fcntl.h>
+
+/* <obj.h> includes <sym.h> and <symconst.h>, which causes conflicts
+ with our versions of those files included by tm-mips.h. Prevent
+ <obj.h> from including them with some appropriate defines. */
+#define __SYM_H__
+#define __SYMCONST_H__
+#include <obj.h>
+#ifdef HAVE_OBJLIST_H
+#include <objlist.h>
+#endif
+
+#ifdef NEW_OBJ_INFO_MAGIC
+#define HANDLE_NEW_OBJ_LIST
+#endif
+
+#include "symtab.h"
+#include "bfd.h"
+#include "symfile.h"
+#include "objfiles.h"
+#include "command.h"
+#include "frame.h"
+#include "gnu-regex.h"
+#include "inferior.h"
+#include "language.h"
+#include "gdbcmd.h"
+
+/* The symbol which starts off the list of shared libraries. */
+#define DEBUG_BASE "__rld_obj_head"
+
+/* Irix 6.x introduces a new variant of object lists.
+ To be able to debug O32 executables under Irix 6, we have to handle both
+ variants. */
+
+typedef enum
+{
+ OBJ_LIST_OLD, /* Pre Irix 6.x object list. */
+ OBJ_LIST_32, /* 32 Bit Elf32_Obj_Info. */
+ OBJ_LIST_64 /* 64 Bit Elf64_Obj_Info, FIXME not yet implemented. */
+} obj_list_variant;
+
+/* Define our own link_map structure.
+ This will help to share code with osfsolib.c and solib.c. */
+
+struct link_map {
+ obj_list_variant l_variant; /* which variant of object list */
+ CORE_ADDR l_lladdr; /* addr in inferior list was read from */
+ CORE_ADDR l_next; /* address of next object list entry */
+};
+
+/* Irix 5 shared objects are pre-linked to particular addresses
+ although the dynamic linker may have to relocate them if the
+ address ranges of the libraries used by the main program clash.
+ The offset is the difference between the address where the object
+ is mapped and the binding address of the shared library. */
+#define LM_OFFSET(so) ((so) -> offset)
+/* Loaded address of shared library. */
+#define LM_ADDR(so) ((so) -> lmstart)
+
+char shadow_contents[BREAKPOINT_MAX]; /* Stash old bkpt addr contents */
+
+struct so_list {
+ struct so_list *next; /* next structure in linked list */
+ struct link_map lm;
+ CORE_ADDR offset; /* prelink to load address offset */
+ char *so_name; /* shared object lib name */
+ CORE_ADDR lmstart; /* lower addr bound of mapped object */
+ CORE_ADDR lmend; /* upper addr bound of mapped object */
+ 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 */
+
+/* Local function prototypes */
+
+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 *));
+
+static struct link_map *
+first_link_map_member PARAMS ((void));
+
+static struct link_map *
+next_link_map_member PARAMS ((struct so_list *));
+
+static void
+xfer_link_map_member PARAMS ((struct so_list *, struct link_map *));
+
+static CORE_ADDR
+locate_base PARAMS ((void));
+
+static int
+solib_map_sections PARAMS ((char *));
+
+/*
+
+LOCAL FUNCTION
+
+ solib_map_sections -- open bfd and build sections for shared lib
+
+SYNOPSIS
+
+ static int 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 int
+solib_map_sections (arg)
+ char *arg;
+{
+ struct so_list *so = (struct so_list *) arg; /* catch_errors bogon */
+ 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_get_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_get_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_get_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 offset to get the address to which the
+ object was actually mapped. */
+ p -> addr += LM_OFFSET (so);
+ p -> endaddr += LM_OFFSET (so);
+ so -> lmend = (CORE_ADDR) max (p -> endaddr, so -> lmend);
+ if (STREQ (p -> the_bfd_section -> name, ".text"))
+ {
+ so -> textsection = p;
+ }
+ }
+
+ /* Free the file names, close the file now. */
+ do_cleanups (old_chain);
+
+ return (1);
+}
+
+/*
+
+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.
+
+ Irix 5 is basically like SunOS.
+
+ 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 ()
+{
+ struct minimal_symbol *msymbol;
+ CORE_ADDR address = 0;
+
+ msymbol = lookup_minimal_symbol (DEBUG_BASE, NULL, symfile_objfile);
+ if ((msymbol != NULL) && (SYMBOL_VALUE_ADDRESS (msymbol) != 0))
+ {
+ address = SYMBOL_VALUE_ADDRESS (msymbol);
+ }
+ return (address);
+}
+
+/*
+
+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 link map descriptor.
+*/
+
+static struct link_map *
+first_link_map_member ()
+{
+ struct obj_list *listp;
+ struct obj_list list_old;
+ struct link_map *lm;
+ static struct link_map first_lm;
+ CORE_ADDR lladdr;
+ CORE_ADDR next_lladdr;
+
+ /* 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)
+ return NULL;
+
+ /* Get address of first list entry. */
+ read_memory (debug_base, (char *) &listp, sizeof (struct obj_list *));
+
+ if (listp == NULL)
+ return NULL;
+
+ /* Get first list entry. */
+ lladdr = (CORE_ADDR) listp;
+ read_memory (lladdr, (char *) &list_old, sizeof (struct obj_list));
+
+ /* The first entry in the list is the object file we are debugging,
+ so skip it. */
+ next_lladdr = (CORE_ADDR) list_old.next;
+
+#ifdef HANDLE_NEW_OBJ_LIST
+ if (list_old.data == NEW_OBJ_INFO_MAGIC)
+ {
+ Elf32_Obj_Info list_32;
+
+ read_memory (lladdr, (char *) &list_32, sizeof (Elf32_Obj_Info));
+ if (list_32.oi_size != sizeof (Elf32_Obj_Info))
+ return NULL;
+ next_lladdr = (CORE_ADDR) list_32.oi_next;
+ }
+#endif
+
+ if (next_lladdr == 0)
+ return NULL;
+
+ first_lm.l_lladdr = next_lladdr;
+ lm = &first_lm;
+ return lm;
+}
+
+/*
+
+LOCAL FUNCTION
+
+ next_link_map_member -- locate next member in dynamic linker's map
+
+SYNOPSIS
+
+ static struct link_map *next_link_map_member (so_list_ptr)
+
+DESCRIPTION
+
+ Read in a copy of the next member in the inferior's dynamic
+ link map from the inferior's dynamic linker structures, and return
+ a pointer to the link map descriptor.
+*/
+
+static struct link_map *
+next_link_map_member (so_list_ptr)
+ struct so_list *so_list_ptr;
+{
+ struct link_map *lm = &so_list_ptr -> lm;
+ CORE_ADDR next_lladdr = lm -> l_next;
+ static struct link_map next_lm;
+
+ if (next_lladdr == 0)
+ {
+ /* 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 = 0;
+
+ if (lm -> l_variant == OBJ_LIST_OLD)
+ {
+ struct obj_list list_old;
+
+ status = target_read_memory (lm -> l_lladdr,
+ (char *) &list_old,
+ sizeof (struct obj_list));
+ next_lladdr = (CORE_ADDR) list_old.next;
+ }
+#ifdef HANDLE_NEW_OBJ_LIST
+ else if (lm -> l_variant == OBJ_LIST_32)
+ {
+ Elf32_Obj_Info list_32;
+ status = target_read_memory (lm -> l_lladdr,
+ (char *) &list_32,
+ sizeof (Elf32_Obj_Info));
+ next_lladdr = (CORE_ADDR) list_32.oi_next;
+ }
+#endif
+
+ if (status != 0 || next_lladdr == 0)
+ return NULL;
+ }
+
+ next_lm.l_lladdr = next_lladdr;
+ lm = &next_lm;
+ return lm;
+}
+
+/*
+
+LOCAL FUNCTION
+
+ xfer_link_map_member -- set local variables from dynamic linker's map
+
+SYNOPSIS
+
+ static void xfer_link_map_member (so_list_ptr, lm)
+
+DESCRIPTION
+
+ Read in a copy of the requested member in the inferior's dynamic
+ link map from the inferior's dynamic linker structures, and fill
+ in the necessary so_list_ptr elements.
+*/
+
+static void
+xfer_link_map_member (so_list_ptr, lm)
+ struct so_list *so_list_ptr;
+ struct link_map *lm;
+{
+ struct obj_list list_old;
+ CORE_ADDR lladdr = lm -> l_lladdr;
+ struct link_map *new_lm = &so_list_ptr -> lm;
+ int errcode;
+
+ read_memory (lladdr, (char *) &list_old, sizeof (struct obj_list));
+
+ new_lm -> l_variant = OBJ_LIST_OLD;
+ new_lm -> l_lladdr = lladdr;
+ new_lm -> l_next = (CORE_ADDR) list_old.next;
+
+#ifdef HANDLE_NEW_OBJ_LIST
+ if (list_old.data == NEW_OBJ_INFO_MAGIC)
+ {
+ Elf32_Obj_Info list_32;
+
+ read_memory (lladdr, (char *) &list_32, sizeof (Elf32_Obj_Info));
+ if (list_32.oi_size != sizeof (Elf32_Obj_Info))
+ return;
+ new_lm -> l_variant = OBJ_LIST_32;
+ new_lm -> l_next = (CORE_ADDR) list_32.oi_next;
+
+ target_read_string ((CORE_ADDR) list_32.oi_pathname,
+ &so_list_ptr -> so_name,
+ list_32.oi_pathname_len + 1, &errcode);
+ if (errcode != 0)
+ memory_error (errcode, (CORE_ADDR) list_32.oi_pathname);
+
+ LM_ADDR (so_list_ptr) = (CORE_ADDR) list_32.oi_ehdr;
+ LM_OFFSET (so_list_ptr) =
+ (CORE_ADDR) list_32.oi_ehdr - (CORE_ADDR) list_32.oi_orig_ehdr;
+ }
+ else
+#endif
+ {
+#if defined (_MIPS_SIM_NABI32) && _MIPS_SIM == _MIPS_SIM_NABI32
+ /* If we are compiling GDB under N32 ABI, the alignments in
+ the obj struct are different from the O32 ABI and we will get
+ wrong values when accessing the struct.
+ As a workaround we use fixed values which are good for
+ Irix 6.2. */
+ char buf[432];
+
+ read_memory ((CORE_ADDR) list_old.data, buf, sizeof (buf));
+
+ target_read_string (extract_address (&buf[236], 4),
+ &so_list_ptr -> so_name,
+ INT_MAX, &errcode);
+ if (errcode != 0)
+ memory_error (errcode, extract_address (&buf[236], 4));
+
+ LM_ADDR (so_list_ptr) = extract_address (&buf[196], 4);
+ LM_OFFSET (so_list_ptr) =
+ extract_address (&buf[196], 4) - extract_address (&buf[248], 4);
+#else
+ struct obj obj_old;
+
+ read_memory ((CORE_ADDR) list_old.data, (char *) &obj_old,
+ sizeof (struct obj));
+
+ target_read_string ((CORE_ADDR) obj_old.o_path,
+ &so_list_ptr -> so_name,
+ INT_MAX, &errcode);
+ if (errcode != 0)
+ memory_error (errcode, (CORE_ADDR) obj_old.o_path);
+
+ LM_ADDR (so_list_ptr) = (CORE_ADDR) obj_old.o_praw;
+ LM_OFFSET (so_list_ptr) =
+ (CORE_ADDR) obj_old.o_praw - obj_old.o_base_address;
+#endif
+ }
+
+ catch_errors (solib_map_sections, (char *) so_list_ptr,
+ "Error while mapping shared library sections:\n",
+ RETURN_MASK_ALL);
+}
+
+
+/*
+
+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.
+ */
+
+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;
+ struct link_map *lm = NULL;
+ 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)
+ {
+ /* Find 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. */
+ lm = next_link_map_member (so_list_ptr);
+ so_list_next = so_list_ptr -> next;
+ }
+ if ((so_list_next == NULL) && (lm != NULL))
+ {
+ new = (struct so_list *) xmalloc (sizeof (struct so_list));
+ memset ((char *) new, 0, sizeof (struct so_list));
+ /* 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;
+ xfer_link_map_member (new, lm);
+ }
+ 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 */
+ CORE_ADDR text_addr = 0;
+
+ if (so -> textsection)
+ text_addr = so -> textsection -> addr;
+ else if (so -> abfd != NULL)
+ {
+ asection *lowest_sect;
+
+ /* If we didn't find a mapped non zero sized .text section, set up
+ text_addr so that the relocation in symbol_file_add does no harm. */
+
+ lowest_sect = bfd_get_section_by_name (so -> abfd, ".text");
+ if (lowest_sect == NULL)
+ bfd_map_over_sections (so -> abfd, find_lowest_section,
+ (PTR) &lowest_sect);
+ if (lowest_sect)
+ text_addr = bfd_section_vma (so -> abfd, lowest_sect) + LM_OFFSET (so);
+ }
+
+ so -> objfile = symbol_file_add (so -> so_name, so -> from_tty,
+ text_addr,
+ 0, 0, 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);
+ }
+
+ /* 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)
+ {
+ int update_coreops;
+
+ /* We must update the to_sections field in the core_ops structure
+ here, otherwise we dereference a potential dangling pointer
+ for each call to target_read/write_memory within this routine. */
+ update_coreops = core_ops.to_sections == target->to_sections;
+
+ /* 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);
+
+ /* Update the to_sections field in the core_ops structure
+ if needed. */
+ if (update_coreops)
+ {
+ core_ops.to_sections = target->to_sections;
+ core_ops.to_sections_end = target->to_sections_end;
+ }
+
+ /* 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;
+ }
+ }
+ }
+ }
+
+ /* Now add the symbol files. */
+ 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_unfiltered ("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;
+ }
+ }
+ }
+
+ /* Getting new symbols may change our opinion about what is
+ frameless. */
+ if (so_last)
+ reinit_frame_cache ();
+}
+
+/*
+
+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_unfiltered ("No exec file.\n");
+ return;
+ }
+ while ((so = find_solib (so)) != NULL)
+ {
+ if (so -> so_name[0])
+ {
+ if (!header_done)
+ {
+ printf_unfiltered("%-12s%-12s%-12s%s\n", "From", "To", "Syms Read",
+ "Shared Object Library");
+ header_done++;
+ }
+ printf_unfiltered ("%-12s",
+ local_hex_string_custom ((unsigned long) LM_ADDR (so),
+ "08l"));
+ printf_unfiltered ("%-12s",
+ local_hex_string_custom ((unsigned long) so -> lmend,
+ "08l"));
+ printf_unfiltered ("%-12s", so -> symbols_loaded ? "Yes" : "No");
+ printf_unfiltered ("%s\n", so -> so_name);
+ }
+ }
+ if (so_list_head == NULL)
+ {
+ printf_unfiltered ("No shared libraries loaded at this time.\n");
+ }
+}
+
+/*
+
+GLOBAL FUNCTION
+
+ solib_address -- check to see if an address is in a shared lib
+
+SYNOPSIS
+
+ char *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.
+ */
+
+char *
+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 (so->so_name);
+ }
+ }
+ return (0);
+}
+
+/* Called by free_all_symtabs */
+
+void
+clear_solib()
+{
+ struct so_list *next;
+ char *bfd_filename;
+
+ disable_breakpoints_in_shlibs (1);
+
+ 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);
+ if (!bfd_close (so_list_head -> abfd))
+ warning ("cannot close \"%s\": %s",
+ bfd_filename, bfd_errmsg (bfd_get_error ()));
+ }
+ else
+ /* This happens for the executable on SVR4. */
+ bfd_filename = NULL;
+
+ next = so_list_head -> next;
+ if (bfd_filename)
+ free ((PTR)bfd_filename);
+ free (so_list_head->so_name);
+ 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;
+
+
+ /* 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;
+ }
+
+ /* 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
+
+ This functions inserts a breakpoint at the entry point of the
+ main executable, where all shared libraries are mapped in.
+*/
+
+static int
+enable_break ()
+{
+ if (symfile_objfile != NULL
+ && target_insert_breakpoint (symfile_objfile->ei.entry_point,
+ shadow_contents) == 0)
+ {
+ breakpoint_addr = symfile_objfile->ei.entry_point;
+ return 1;
+ }
+
+ return 0;
+}
+
+/*
+
+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 (!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 = TARGET_SIGNAL_0;
+ do
+ {
+ target_resume (-1, 0, stop_signal);
+ wait_for_inferior ();
+ }
+ while (stop_signal != TARGET_SIGNAL_TRAP);
+
+ /* 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 will call reinit_frame_cache.
+ But we are stopped in the startup code and we might not have symbols
+ for the startup code, so heuristic_proc_start could be called
+ and will put out an annoying warning.
+ Delaying the resetting of stop_soon_quietly until after symbol loading
+ suppresses the warning. */
+ if (auto_solib_add)
+ solib_add ((char *) 0, 0, (struct target_ops *) 0);
+ stop_soon_quietly = 0;
+}
+
+/*
+
+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.");
+
+ add_show_from_set
+ (add_set_cmd ("auto-solib-add", class_support, var_zinteger,
+ (char *) &auto_solib_add,
+ "Set autoloading of shared library symbols.\n\
+If nonzero, symbols from all shared object libraries will be loaded\n\
+automatically when the inferior begins execution or when the dynamic linker\n\
+informs gdb that a new library has been loaded. Otherwise, symbols\n\
+must be loaded manually, using `sharedlibrary'.",
+ &setlist),
+ &showlist);
+}
+
+
+/* Register that we are able to handle irix5 core file formats.
+ This really is bfd_target_unknown_flavour */
+
+static struct core_fns irix5_core_fns =
+{
+ bfd_target_unknown_flavour,
+ fetch_core_registers,
+ NULL
+};
+
+void
+_initialize_core_irix5 ()
+{
+ add_core_fns (&irix5_core_fns);
+}
diff --git a/gdb/isi-xdep.c b/gdb/isi-xdep.c
new file mode 100644
index 00000000000..8773c83ea7a
--- /dev/null
+++ b/gdb/isi-xdep.c
@@ -0,0 +1,20 @@
+/* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include <machine/reg.h>
+int rloc[] = {
+ R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, R13, FP, SP, PS, PC
+};
diff --git a/gdb/jv-exp.y b/gdb/jv-exp.y
new file mode 100644
index 00000000000..d17c4f3a8b9
--- /dev/null
+++ b/gdb/jv-exp.y
@@ -0,0 +1,1466 @@
+/* YACC parser for Java expressions, for GDB.
+ Copyright (C) 1997, 1998, 1999.
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Parse a Java 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. Well, almost always; see ArrayAccess.
+
+ 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 "gdb_string.h"
+#include <ctype.h>
+#include "expression.h"
+#include "value.h"
+#include "parser-defs.h"
+#include "language.h"
+#include "jv-lang.h"
+#include "bfd.h" /* Required by objfiles.h. */
+#include "symfile.h" /* Required by objfiles.h. */
+#include "objfiles.h" /* For have_full_symbols and have_partial_symbols */
+
+/* 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 java_maxdepth
+#define yyparse java_parse
+#define yylex java_lex
+#define yyerror java_error
+#define yylval java_lval
+#define yychar java_char
+#define yydebug java_debug
+#define yypact java_pact
+#define yyr1 java_r1
+#define yyr2 java_r2
+#define yydef java_def
+#define yychk java_chk
+#define yypgo java_pgo
+#define yyact java_act
+#define yyexca java_exca
+#define yyerrflag java_errflag
+#define yynerrs java_nerrs
+#define yyps java_ps
+#define yypv java_pv
+#define yys java_s
+#define yy_yys java_yys
+#define yystate java_state
+#define yytmp java_tmp
+#define yyv java_v
+#define yy_yyv java_yyv
+#define yyval java_val
+#define yylloc java_lloc
+#define yyreds java_reds /* With YYDEBUG defined */
+#define yytoks java_toks /* With YYDEBUG defined */
+#define yylhs java_yylhs
+#define yylen java_yylen
+#define yydefred java_yydefred
+#define yydgoto java_yydgoto
+#define yysindex java_yysindex
+#define yyrindex java_yyrindex
+#define yygindex java_yygindex
+#define yytable java_yytable
+#define yycheck java_yycheck
+
+#ifndef YYDEBUG
+#define YYDEBUG 0 /* Default to no yydebug support */
+#endif
+
+int
+yyparse PARAMS ((void));
+
+static int
+yylex PARAMS ((void));
+
+void
+yyerror PARAMS ((char *));
+
+static struct type * java_type_from_name PARAMS ((struct stoken));
+static void push_expression_name PARAMS ((struct stoken));
+static void push_fieldnames PARAMS ((struct stoken));
+
+static struct expression *copy_exp PARAMS ((struct expression *, int));
+static void insert_exp PARAMS ((int, struct expression *));
+
+%}
+
+/* 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_int;
+ struct {
+ DOUBLEST dval;
+ struct type *type;
+ } typed_val_float;
+ struct symbol *sym;
+ struct type *tval;
+ struct stoken sval;
+ struct ttype tsym;
+ struct symtoken ssym;
+ struct block *bval;
+ enum exp_opcode opcode;
+ struct internalvar *ivar;
+ int *ivec;
+ }
+
+%{
+/* YYSTYPE gets defined by %union */
+static int
+parse_number PARAMS ((char *, int, int, YYSTYPE *));
+%}
+
+%type <lval> rcurly Dims Dims_opt
+%type <tval> ClassOrInterfaceType ClassType /* ReferenceType Type ArrayType */
+%type <tval> IntegralType FloatingPointType NumericType PrimitiveType ArrayType PrimitiveOrArrayType
+
+%token <typed_val_int> INTEGER_LITERAL
+%token <typed_val_float> FLOATING_POINT_LITERAL
+
+%token <sval> IDENTIFIER
+%token <sval> STRING_LITERAL
+%token <lval> BOOLEAN_LITERAL
+%token <tsym> TYPENAME
+%type <sval> Name SimpleName QualifiedName ForcedName
+
+/* 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 <sval> NAME_OR_INT
+
+%token ERROR
+
+/* Special type cases, put in to allow the parser to distinguish different
+ legal basetypes. */
+%token LONG SHORT BYTE INT CHAR BOOLEAN DOUBLE FLOAT
+
+%token VARIABLE
+
+%token <opcode> ASSIGN_MODIFY
+
+%token THIS SUPER NEW
+
+%left ','
+%right '=' ASSIGN_MODIFY
+%right '?'
+%left OROR
+%left ANDAND
+%left '|'
+%left '^'
+%left '&'
+%left EQUAL NOTEQUAL
+%left '<' '>' LEQ GEQ
+%left LSH RSH
+%left '+' '-'
+%left '*' '/' '%'
+%right INCREMENT DECREMENT
+%right '.' '[' '('
+
+
+%%
+
+start : exp1
+ | type_exp
+ ;
+
+type_exp: PrimitiveOrArrayType
+ {
+ write_exp_elt_opcode(OP_TYPE);
+ write_exp_elt_type($1);
+ write_exp_elt_opcode(OP_TYPE);
+ }
+ ;
+
+PrimitiveOrArrayType:
+ PrimitiveType
+ | ArrayType
+ ;
+
+StringLiteral:
+ STRING_LITERAL
+ {
+ write_exp_elt_opcode (OP_STRING);
+ write_exp_string ($1);
+ write_exp_elt_opcode (OP_STRING);
+ }
+;
+
+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); }
+| NAME_OR_INT
+ { YYSTYPE val;
+ parse_number ($1.ptr, $1.length, 0, &val);
+ write_exp_elt_opcode (OP_LONG);
+ write_exp_elt_type (val.typed_val_int.type);
+ write_exp_elt_longcst ((LONGEST)val.typed_val_int.val);
+ write_exp_elt_opcode (OP_LONG);
+ }
+| FLOATING_POINT_LITERAL
+ { write_exp_elt_opcode (OP_DOUBLE);
+ write_exp_elt_type ($1.type);
+ write_exp_elt_dblcst ($1.dval);
+ write_exp_elt_opcode (OP_DOUBLE); }
+| BOOLEAN_LITERAL
+ { write_exp_elt_opcode (OP_LONG);
+ write_exp_elt_type (java_boolean_type);
+ write_exp_elt_longcst ((LONGEST)$1);
+ write_exp_elt_opcode (OP_LONG); }
+| StringLiteral
+ ;
+
+/* UNUSED:
+Type:
+ PrimitiveType
+| ReferenceType
+;
+*/
+
+PrimitiveType:
+ NumericType
+| BOOLEAN
+ { $$ = java_boolean_type; }
+;
+
+NumericType:
+ IntegralType
+| FloatingPointType
+;
+
+IntegralType:
+ BYTE
+ { $$ = java_byte_type; }
+| SHORT
+ { $$ = java_short_type; }
+| INT
+ { $$ = java_int_type; }
+| LONG
+ { $$ = java_long_type; }
+| CHAR
+ { $$ = java_char_type; }
+;
+
+FloatingPointType:
+ FLOAT
+ { $$ = java_float_type; }
+| DOUBLE
+ { $$ = java_double_type; }
+;
+
+/* UNUSED:
+ReferenceType:
+ ClassOrInterfaceType
+| ArrayType
+;
+*/
+
+ClassOrInterfaceType:
+ Name
+ { $$ = java_type_from_name ($1); }
+;
+
+ClassType:
+ ClassOrInterfaceType
+;
+
+ArrayType:
+ PrimitiveType Dims
+ { $$ = java_array_type ($1, $2); }
+| Name Dims
+ { $$ = java_array_type (java_type_from_name ($1), $2); }
+;
+
+Name:
+ IDENTIFIER
+| QualifiedName
+;
+
+ForcedName:
+ SimpleName
+| QualifiedName
+;
+
+SimpleName:
+ IDENTIFIER
+| NAME_OR_INT
+;
+
+QualifiedName:
+ Name '.' SimpleName
+ { $$.length = $1.length + $3.length + 1;
+ if ($1.ptr + $1.length + 1 == $3.ptr
+ && $1.ptr[$1.length] == '.')
+ $$.ptr = $1.ptr; /* Optimization. */
+ else
+ {
+ $$.ptr = (char *) malloc ($$.length + 1);
+ make_cleanup (free, $$.ptr);
+ sprintf ($$.ptr, "%.*s.%.*s",
+ $1.length, $1.ptr, $3.length, $3.ptr);
+ } }
+;
+
+/*
+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 : Expression
+ | exp1 ',' Expression
+ { write_exp_elt_opcode (BINOP_COMMA); }
+ ;
+
+Primary:
+ PrimaryNoNewArray
+| ArrayCreationExpression
+;
+
+PrimaryNoNewArray:
+ Literal
+| THIS
+ { write_exp_elt_opcode (OP_THIS);
+ write_exp_elt_opcode (OP_THIS); }
+| '(' Expression ')'
+| ClassInstanceCreationExpression
+| FieldAccess
+| MethodInvocation
+| ArrayAccess
+| lcurly ArgumentList rcurly
+ { write_exp_elt_opcode (OP_ARRAY);
+ write_exp_elt_longcst ((LONGEST) 0);
+ write_exp_elt_longcst ((LONGEST) $3);
+ write_exp_elt_opcode (OP_ARRAY); }
+;
+
+lcurly:
+ '{'
+ { start_arglist (); }
+;
+
+rcurly:
+ '}'
+ { $$ = end_arglist () - 1; }
+;
+
+ClassInstanceCreationExpression:
+ NEW ClassType '(' ArgumentList_opt ')'
+ { error ("FIXME - ClassInstanceCreationExpression"); }
+;
+
+ArgumentList:
+ Expression
+ { arglist_len = 1; }
+| ArgumentList ',' Expression
+ { arglist_len++; }
+;
+
+ArgumentList_opt:
+ /* EMPTY */
+ { arglist_len = 0; }
+| ArgumentList
+;
+
+ArrayCreationExpression:
+ NEW PrimitiveType DimExprs Dims_opt
+ { error ("FIXME - ArrayCreatiionExpression"); }
+| NEW ClassOrInterfaceType DimExprs Dims_opt
+ { error ("FIXME - ArrayCreatiionExpression"); }
+;
+
+DimExprs:
+ DimExpr
+| DimExprs DimExpr
+;
+
+DimExpr:
+ '[' Expression ']'
+;
+
+Dims:
+ '[' ']'
+ { $$ = 1; }
+| Dims '[' ']'
+ { $$ = $1 + 1; }
+;
+
+Dims_opt:
+ Dims
+| /* EMPTY */
+ { $$ = 0; }
+;
+
+FieldAccess:
+ Primary '.' SimpleName
+ { push_fieldnames ($3); }
+| VARIABLE '.' SimpleName
+ { push_fieldnames ($3); }
+/*| SUPER '.' SimpleName { FIXME } */
+;
+
+MethodInvocation:
+ Name '(' ArgumentList_opt ')'
+ { error ("method invocation not implemented"); }
+| Primary '.' SimpleName '(' ArgumentList_opt ')'
+ { error ("method invocation not implemented"); }
+| SUPER '.' SimpleName '(' ArgumentList_opt ')'
+ { error ("method invocation not implemented"); }
+;
+
+ArrayAccess:
+ Name '[' Expression ']'
+ {
+ /* Emit code for the Name now, then exchange it in the
+ expout array with the Expression's code. We could
+ introduce a OP_SWAP code or a reversed version of
+ BINOP_SUBSCRIPT, but that makes the rest of GDB pay
+ for our parsing kludges. */
+ struct expression *name_expr;
+
+ push_expression_name ($1);
+ name_expr = copy_exp (expout, expout_ptr);
+ expout_ptr -= name_expr->nelts;
+ insert_exp (expout_ptr-length_of_subexp (expout, expout_ptr),
+ name_expr);
+ free (name_expr);
+ write_exp_elt_opcode (BINOP_SUBSCRIPT);
+ }
+| VARIABLE '[' Expression ']'
+ { write_exp_elt_opcode (BINOP_SUBSCRIPT); }
+| PrimaryNoNewArray '[' Expression ']'
+ { write_exp_elt_opcode (BINOP_SUBSCRIPT); }
+;
+
+PostfixExpression:
+ Primary
+| Name
+ { push_expression_name ($1); }
+| VARIABLE
+ /* Already written by write_dollar_variable. */
+| PostIncrementExpression
+| PostDecrementExpression
+;
+
+PostIncrementExpression:
+ PostfixExpression INCREMENT
+ { write_exp_elt_opcode (UNOP_POSTINCREMENT); }
+;
+
+PostDecrementExpression:
+ PostfixExpression DECREMENT
+ { write_exp_elt_opcode (UNOP_POSTDECREMENT); }
+;
+
+UnaryExpression:
+ PreIncrementExpression
+| PreDecrementExpression
+| '+' UnaryExpression
+| '-' UnaryExpression
+ { write_exp_elt_opcode (UNOP_NEG); }
+| '*' UnaryExpression
+ { write_exp_elt_opcode (UNOP_IND); } /*FIXME not in Java */
+| UnaryExpressionNotPlusMinus
+;
+
+PreIncrementExpression:
+ INCREMENT UnaryExpression
+ { write_exp_elt_opcode (UNOP_PREINCREMENT); }
+;
+
+PreDecrementExpression:
+ DECREMENT UnaryExpression
+ { write_exp_elt_opcode (UNOP_PREDECREMENT); }
+;
+
+UnaryExpressionNotPlusMinus:
+ PostfixExpression
+| '~' UnaryExpression
+ { write_exp_elt_opcode (UNOP_COMPLEMENT); }
+| '!' UnaryExpression
+ { write_exp_elt_opcode (UNOP_LOGICAL_NOT); }
+| CastExpression
+ ;
+
+CastExpression:
+ '(' PrimitiveType Dims_opt ')' UnaryExpression
+ { write_exp_elt_opcode (UNOP_CAST);
+ write_exp_elt_type (java_array_type ($2, $3));
+ write_exp_elt_opcode (UNOP_CAST); }
+| '(' Expression ')' UnaryExpressionNotPlusMinus
+ {
+ int exp_size = expout_ptr;
+ int last_exp_size = length_of_subexp(expout, expout_ptr);
+ struct type *type;
+ int i;
+ int base = expout_ptr - last_exp_size - 3;
+ if (base < 0 || expout->elts[base+2].opcode != OP_TYPE)
+ error ("invalid cast expression");
+ type = expout->elts[base+1].type;
+ /* Remove the 'Expression' and slide the
+ UnaryExpressionNotPlusMinus down to replace it. */
+ for (i = 0; i < last_exp_size; i++)
+ expout->elts[base + i] = expout->elts[base + i + 3];
+ expout_ptr -= 3;
+ if (TYPE_CODE (type) == TYPE_CODE_STRUCT)
+ type = lookup_pointer_type (type);
+ write_exp_elt_opcode (UNOP_CAST);
+ write_exp_elt_type (type);
+ write_exp_elt_opcode (UNOP_CAST);
+ }
+| '(' Name Dims ')' UnaryExpressionNotPlusMinus
+ { write_exp_elt_opcode (UNOP_CAST);
+ write_exp_elt_type (java_array_type (java_type_from_name ($2), $3));
+ write_exp_elt_opcode (UNOP_CAST); }
+;
+
+
+MultiplicativeExpression:
+ UnaryExpression
+| MultiplicativeExpression '*' UnaryExpression
+ { write_exp_elt_opcode (BINOP_MUL); }
+| MultiplicativeExpression '/' UnaryExpression
+ { write_exp_elt_opcode (BINOP_DIV); }
+| MultiplicativeExpression '%' UnaryExpression
+ { write_exp_elt_opcode (BINOP_REM); }
+;
+
+AdditiveExpression:
+ MultiplicativeExpression
+| AdditiveExpression '+' MultiplicativeExpression
+ { write_exp_elt_opcode (BINOP_ADD); }
+| AdditiveExpression '-' MultiplicativeExpression
+ { write_exp_elt_opcode (BINOP_SUB); }
+;
+
+ShiftExpression:
+ AdditiveExpression
+| ShiftExpression LSH AdditiveExpression
+ { write_exp_elt_opcode (BINOP_LSH); }
+| ShiftExpression RSH AdditiveExpression
+ { write_exp_elt_opcode (BINOP_RSH); }
+/* | ShiftExpression >>> AdditiveExpression { FIXME } */
+;
+
+RelationalExpression:
+ ShiftExpression
+| RelationalExpression '<' ShiftExpression
+ { write_exp_elt_opcode (BINOP_LESS); }
+| RelationalExpression '>' ShiftExpression
+ { write_exp_elt_opcode (BINOP_GTR); }
+| RelationalExpression LEQ ShiftExpression
+ { write_exp_elt_opcode (BINOP_LEQ); }
+| RelationalExpression GEQ ShiftExpression
+ { write_exp_elt_opcode (BINOP_GEQ); }
+/* | RelationalExpresion INSTANCEOF ReferenceType { FIXME } */
+;
+
+EqualityExpression:
+ RelationalExpression
+| EqualityExpression EQUAL RelationalExpression
+ { write_exp_elt_opcode (BINOP_EQUAL); }
+| EqualityExpression NOTEQUAL RelationalExpression
+ { write_exp_elt_opcode (BINOP_NOTEQUAL); }
+;
+
+AndExpression:
+ EqualityExpression
+| AndExpression '&' EqualityExpression
+ { write_exp_elt_opcode (BINOP_BITWISE_AND); }
+;
+
+ExclusiveOrExpression:
+ AndExpression
+| ExclusiveOrExpression '^' AndExpression
+ { write_exp_elt_opcode (BINOP_BITWISE_XOR); }
+;
+InclusiveOrExpression:
+ ExclusiveOrExpression
+| InclusiveOrExpression '|' ExclusiveOrExpression
+ { write_exp_elt_opcode (BINOP_BITWISE_IOR); }
+;
+
+ConditionalAndExpression:
+ InclusiveOrExpression
+| ConditionalAndExpression ANDAND InclusiveOrExpression
+ { write_exp_elt_opcode (BINOP_LOGICAL_AND); }
+;
+
+ConditionalOrExpression:
+ ConditionalAndExpression
+| ConditionalOrExpression OROR ConditionalAndExpression
+ { write_exp_elt_opcode (BINOP_LOGICAL_OR); }
+;
+
+ConditionalExpression:
+ ConditionalOrExpression
+| ConditionalOrExpression '?' Expression ':' ConditionalExpression
+ { write_exp_elt_opcode (TERNOP_COND); }
+;
+
+AssignmentExpression:
+ ConditionalExpression
+| Assignment
+;
+
+Assignment:
+ LeftHandSide '=' ConditionalExpression
+ { write_exp_elt_opcode (BINOP_ASSIGN); }
+| LeftHandSide ASSIGN_MODIFY ConditionalExpression
+ { write_exp_elt_opcode (BINOP_ASSIGN_MODIFY);
+ write_exp_elt_opcode ($2);
+ write_exp_elt_opcode (BINOP_ASSIGN_MODIFY); }
+;
+
+LeftHandSide:
+ ForcedName
+ { push_expression_name ($1); }
+| VARIABLE
+ /* Already written by write_dollar_variable. */
+| FieldAccess
+| ArrayAccess
+;
+
+
+Expression:
+ AssignmentExpression
+;
+
+%%
+/* 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 ULONGEST n = 0;
+ ULONGEST limit, limit_div_base;
+
+ register int c;
+ register int base = input_radix;
+
+ struct type *type;
+
+ if (parsed_float)
+ {
+ /* It's a float since it contains a point or an exponent. */
+ char c;
+ int num = 0; /* number of tokens scanned by scanf */
+ char saved_char = p[len];
+
+ p[len] = 0; /* null-terminate the token */
+ if (sizeof (putithere->typed_val_float.dval) <= sizeof (float))
+ num = sscanf (p, "%g%c", (float *) &putithere->typed_val_float.dval, &c);
+ else if (sizeof (putithere->typed_val_float.dval) <= sizeof (double))
+ num = sscanf (p, "%lg%c", (double *) &putithere->typed_val_float.dval, &c);
+ else
+ {
+#ifdef SCANF_HAS_LONG_DOUBLE
+ num = sscanf (p, "%Lg%c", &putithere->typed_val_float.dval, &c);
+#else
+ /* Scan it into a double, then assign it to the long double.
+ This at least wins with values representable in the range
+ of doubles. */
+ double temp;
+ num = sscanf (p, "%lg%c", &temp, &c);
+ putithere->typed_val_float.dval = temp;
+#endif
+ }
+ p[len] = saved_char; /* restore the input stream */
+ if (num != 1) /* check scanf found ONLY a float ... */
+ return ERROR;
+ /* See if it has `f' or `d' suffix (float or double). */
+
+ c = tolower (p[len - 1]);
+
+ if (c == 'f' || c == 'F')
+ putithere->typed_val_float.type = builtin_type_float;
+ else if (isdigit (c) || c == '.' || c == 'd' || c == 'D')
+ putithere->typed_val_float.type = builtin_type_double;
+ else
+ return ERROR;
+
+ return FLOATING_POINT_LITERAL;
+ }
+
+ /* 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;
+ }
+
+ c = p[len-1];
+ limit = (ULONGEST)0xffffffff;
+ if (c == 'l' || c == 'L')
+ {
+ type = java_long_type;
+ len--;
+ /* A paranoid calculation of (1<<64)-1. */
+ limit = ((limit << 16) << 16) | limit;
+ }
+ else
+ {
+ type = java_int_type;
+ }
+ limit_div_base = limit / (ULONGEST) base;
+
+ while (--len >= 0)
+ {
+ c = *p++;
+ if (c >= '0' && c <= '9')
+ c -= '0';
+ else if (c >= 'A' && c <= 'Z')
+ c -= 'A' - 10;
+ else if (c >= 'a' && c <= 'z')
+ c -= 'a' - 10;
+ else
+ return ERROR; /* Char not a digit */
+ if (c >= base)
+ return ERROR;
+ if (n > limit_div_base
+ || (n *= base) > limit - c)
+ error ("Numeric constant too large.");
+ n += c;
+ }
+
+ putithere->typed_val_int.val = n;
+ putithere->typed_val_int.type = type;
+ return INTEGER_LITERAL;
+}
+
+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},
+ {"&&", ANDAND, BINOP_END},
+ {"||", OROR, 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);
+ else if (c == '\'')
+ error ("Empty character constant.");
+
+ yylval.typed_val_int.val = c;
+ yylval.typed_val_int.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 INTEGER_LITERAL;
+
+ 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 '}':
+ 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_LITERAL);
+ }
+
+ 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 == '<');
+ )
+ {
+ if (c == '<')
+ {
+ int i = namelen;
+ while (tokstart[++i] && tokstart[i] != '>');
+ if (tokstart[i] == '>')
+ namelen = i;
+ }
+ 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;
+
+ tryname:
+
+ /* Catch specific keywords. Should be done with a data structure. */
+ switch (namelen)
+ {
+ case 7:
+ if (STREQN (tokstart, "boolean", 7))
+ return BOOLEAN;
+ break;
+ case 6:
+ if (STREQN (tokstart, "double", 6))
+ return DOUBLE;
+ break;
+ case 5:
+ if (STREQN (tokstart, "short", 5))
+ return SHORT;
+ if (STREQN (tokstart, "false", 5))
+ {
+ yylval.lval = 0;
+ return BOOLEAN_LITERAL;
+ }
+ if (STREQN (tokstart, "super", 5))
+ return SUPER;
+ if (STREQN (tokstart, "float", 5))
+ return FLOAT;
+ break;
+ case 4:
+ if (STREQN (tokstart, "long", 4))
+ return LONG;
+ if (STREQN (tokstart, "byte", 4))
+ return BYTE;
+ if (STREQN (tokstart, "char", 4))
+ return CHAR;
+ if (STREQN (tokstart, "true", 4))
+ {
+ yylval.lval = 1;
+ return BOOLEAN_LITERAL;
+ }
+ 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;
+ if (STREQN (tokstart, "new", 3))
+ return NEW;
+ break;
+ default:
+ break;
+ }
+
+ yylval.sval.ptr = tokstart;
+ yylval.sval.length = namelen;
+
+ if (*tokstart == '$')
+ {
+ write_dollar_variable (yylval.sval);
+ return VARIABLE;
+ }
+
+ /* 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 (((tokstart[0] >= 'a' && tokstart[0] < 'a' + input_radix - 10) ||
+ (tokstart[0] >= 'A' && tokstart[0] < 'A' + input_radix - 10)))
+ {
+ YYSTYPE newlval; /* Its value is ignored. */
+ int hextype = parse_number (tokstart, namelen, 0, &newlval);
+ if (hextype == INTEGER_LITERAL)
+ return NAME_OR_INT;
+ }
+ return IDENTIFIER;
+}
+
+void
+yyerror (msg)
+ char *msg;
+{
+ error ("A %s in expression, near `%s'.", (msg ? msg : "error"), lexptr);
+}
+
+static struct type *
+java_type_from_name (name)
+ struct stoken name;
+
+{
+ char *tmp = copy_name (name);
+ struct type *typ = java_lookup_class (tmp);
+ if (typ == NULL || TYPE_CODE (typ) != TYPE_CODE_STRUCT)
+ error ("No class named %s.", tmp);
+ return typ;
+}
+
+/* If NAME is a valid variable name in this scope, push it and return 1.
+ Otherwise, return 0. */
+
+static int
+push_variable (name)
+ struct stoken name;
+
+{
+ char *tmp = copy_name (name);
+ int is_a_field_of_this = 0;
+ struct symbol *sym;
+ sym = lookup_symbol (tmp, expression_context_block, VAR_NAMESPACE,
+ &is_a_field_of_this, (struct symtab **) NULL);
+ if (sym && SYMBOL_CLASS (sym) != LOC_TYPEDEF)
+ {
+ 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);
+ return 1;
+ }
+ if (is_a_field_of_this)
+ {
+ /* 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 (name);
+ write_exp_elt_opcode (STRUCTOP_PTR);
+ return 1;
+ }
+ return 0;
+}
+
+/* Assuming a reference expression has been pushed, emit the
+ STRUCTOP_STRUCT ops to access the field named NAME. If NAME is a
+ qualified name (has '.'), generate a field access for each part. */
+
+static void
+push_fieldnames (name)
+ struct stoken name;
+{
+ int i;
+ struct stoken token;
+ token.ptr = name.ptr;
+ for (i = 0; ; i++)
+ {
+ if (i == name.length || name.ptr[i] == '.')
+ {
+ /* token.ptr is start of current field name. */
+ token.length = &name.ptr[i] - token.ptr;
+ write_exp_elt_opcode (STRUCTOP_STRUCT);
+ write_exp_string (token);
+ write_exp_elt_opcode (STRUCTOP_STRUCT);
+ token.ptr += token.length + 1;
+ }
+ if (i >= name.length)
+ break;
+ }
+}
+
+/* Helper routine for push_expression_name.
+ Handle a qualified name, where DOT_INDEX is the index of the first '.' */
+
+static void
+push_qualified_expression_name (name, dot_index)
+ struct stoken name;
+ int dot_index;
+{
+ struct stoken token;
+ char *tmp;
+ struct type *typ;
+
+ token.ptr = name.ptr;
+ token.length = dot_index;
+
+ if (push_variable (token))
+ {
+ token.ptr = name.ptr + dot_index + 1;
+ token.length = name.length - dot_index - 1;
+ push_fieldnames (token);
+ return;
+ }
+
+ token.ptr = name.ptr;
+ for (;;)
+ {
+ token.length = dot_index;
+ tmp = copy_name (token);
+ typ = java_lookup_class (tmp);
+ if (typ != NULL)
+ {
+ if (dot_index == name.length)
+ {
+ write_exp_elt_opcode(OP_TYPE);
+ write_exp_elt_type(typ);
+ write_exp_elt_opcode(OP_TYPE);
+ return;
+ }
+ dot_index++; /* Skip '.' */
+ name.ptr += dot_index;
+ name.length -= dot_index;
+ dot_index = 0;
+ while (dot_index < name.length && name.ptr[dot_index] != '.')
+ dot_index++;
+ token.ptr = name.ptr;
+ token.length = dot_index;
+ write_exp_elt_opcode (OP_SCOPE);
+ write_exp_elt_type (typ);
+ write_exp_string (token);
+ write_exp_elt_opcode (OP_SCOPE);
+ if (dot_index < name.length)
+ {
+ dot_index++;
+ name.ptr += dot_index;
+ name.length -= dot_index;
+ push_fieldnames (name);
+ }
+ return;
+ }
+ else if (dot_index >= name.length)
+ break;
+ dot_index++; /* Skip '.' */
+ while (dot_index < name.length && name.ptr[dot_index] != '.')
+ dot_index++;
+ }
+ error ("unknown type `%.*s'", name.length, name.ptr);
+}
+
+/* Handle Name in an expression (or LHS).
+ Handle VAR, TYPE, TYPE.FIELD1....FIELDN and VAR.FIELD1....FIELDN. */
+
+static void
+push_expression_name (name)
+ struct stoken name;
+{
+ char *tmp;
+ struct type *typ;
+ char *ptr;
+ int i;
+
+ for (i = 0; i < name.length; i++)
+ {
+ if (name.ptr[i] == '.')
+ {
+ /* It's a Qualified Expression Name. */
+ push_qualified_expression_name (name, i);
+ return;
+ }
+ }
+
+ /* It's a Simple Expression Name. */
+
+ if (push_variable (name))
+ return;
+ tmp = copy_name (name);
+ typ = java_lookup_class (tmp);
+ if (typ != NULL)
+ {
+ write_exp_elt_opcode(OP_TYPE);
+ write_exp_elt_type(typ);
+ write_exp_elt_opcode(OP_TYPE);
+ }
+ else
+ {
+ struct minimal_symbol *msymbol;
+
+ msymbol = lookup_minimal_symbol (tmp, NULL, NULL);
+ if (msymbol != NULL)
+ {
+ write_exp_msymbol (msymbol,
+ lookup_function_type (builtin_type_int),
+ builtin_type_int);
+ }
+ 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.", tmp);
+ }
+
+}
+
+
+/* The following two routines, copy_exp and insert_exp, aren't specific to
+ Java, so they could go in parse.c, but their only purpose is to support
+ the parsing kludges we use in this file, so maybe it's best to isolate
+ them here. */
+
+/* Copy the expression whose last element is at index ENDPOS - 1 in EXPR
+ into a freshly malloc'ed struct expression. Its language_defn is set
+ to null. */
+static struct expression *
+copy_exp (expr, endpos)
+ struct expression *expr;
+ int endpos;
+{
+ int len = length_of_subexp (expr, endpos);
+ struct expression *new
+ = (struct expression *) malloc (sizeof (*new) + EXP_ELEM_TO_BYTES (len));
+ new->nelts = len;
+ memcpy (new->elts, expr->elts + endpos - len, EXP_ELEM_TO_BYTES (len));
+ new->language_defn = 0;
+
+ return new;
+}
+
+/* Insert the expression NEW into the current expression (expout) at POS. */
+static void
+insert_exp (pos, new)
+ int pos;
+ struct expression *new;
+{
+ int newlen = new->nelts;
+
+ /* Grow expout if necessary. In this function's only use at present,
+ this should never be necessary. */
+ if (expout_ptr + newlen > expout_size)
+ {
+ expout_size = max (expout_size * 2, expout_ptr + newlen + 10);
+ expout = (struct expression *)
+ realloc ((char *) expout, (sizeof (struct expression)
+ + EXP_ELEM_TO_BYTES (expout_size)));
+ }
+
+ {
+ int i;
+
+ for (i = expout_ptr - 1; i >= pos; i--)
+ expout->elts[i + newlen] = expout->elts[i];
+ }
+
+ memcpy (expout->elts + pos, new->elts, EXP_ELEM_TO_BYTES (newlen));
+ expout_ptr += newlen;
+}
diff --git a/gdb/jv-lang.c b/gdb/jv-lang.c
new file mode 100644
index 00000000000..a98147aaf49
--- /dev/null
+++ b/gdb/jv-lang.c
@@ -0,0 +1,1088 @@
+/* Java language support routines for GDB, the GNU debugger.
+ Copyright 1997, 1998, 1999 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "symtab.h"
+#include "gdbtypes.h"
+#include "expression.h"
+#include "parser-defs.h"
+#include "language.h"
+#include "gdbtypes.h"
+#include "symtab.h"
+#include "symfile.h"
+#include "objfiles.h"
+#include "gdb_string.h"
+#include "value.h"
+#include "c-lang.h"
+#include "jv-lang.h"
+#include "gdbcore.h"
+#include <ctype.h>
+
+struct type *java_int_type;
+struct type *java_byte_type;
+struct type *java_short_type;
+struct type *java_long_type;
+struct type *java_boolean_type;
+struct type *java_char_type;
+struct type *java_float_type;
+struct type *java_double_type;
+struct type *java_void_type;
+
+static int java_demangled_signature_length PARAMS ((char*));
+static void java_demangled_signature_copy PARAMS ((char*, char*));
+
+static void java_emit_char PARAMS ((int c, GDB_FILE *stream, int quoter));
+
+/* This objfile contains symtabs that have been dynamically created
+ to record dynamically loaded Java classes and dynamically
+ compiled java methods. */
+
+static struct objfile *dynamics_objfile = NULL;
+
+static struct type *java_link_class_type PARAMS ((struct type *, value_ptr));
+
+static struct objfile *
+get_dynamics_objfile ()
+{
+ if (dynamics_objfile == NULL)
+ {
+ dynamics_objfile = allocate_objfile (NULL, 0, 0, 0);
+ }
+ return dynamics_objfile;
+}
+
+#if 1
+/* symtab contains classes read from the inferior. */
+
+static struct symtab *class_symtab = NULL;
+
+/* Maximum number of class in class_symtab before relocation is needed. */
+
+static int class_symtab_space;
+
+struct symtab *
+get_java_class_symtab ()
+{
+ if (class_symtab == NULL)
+ {
+ struct objfile *objfile = get_dynamics_objfile();
+ struct blockvector *bv;
+ struct block *bl;
+ class_symtab = allocate_symtab ("<java-classes>", objfile);
+ class_symtab->language = language_java;
+ bv = (struct blockvector *)
+ obstack_alloc (&objfile->symbol_obstack, sizeof (struct blockvector));
+ BLOCKVECTOR_NBLOCKS (bv) = 1;
+ BLOCKVECTOR (class_symtab) = bv;
+
+ /* Allocate dummy STATIC_BLOCK. */
+ bl = (struct block *)
+ obstack_alloc (&objfile->symbol_obstack, sizeof (struct block));
+ BLOCK_NSYMS (bl) = 0;
+ BLOCK_START (bl) = 0;
+ BLOCK_END (bl) = 0;
+ BLOCK_FUNCTION (bl) = NULL;
+ BLOCK_SUPERBLOCK (bl) = NULL;
+ BLOCK_GCC_COMPILED (bl) = 0;
+ BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK) = bl;
+
+ /* Allocate GLOBAL_BLOCK. This has to be relocatable. */
+ class_symtab_space = 128;
+ bl = (struct block *)
+ mmalloc (objfile->md,
+ sizeof (struct block)
+ + ((class_symtab_space - 1) * sizeof (struct symbol *)));
+ *bl = *BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK);
+ BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK) = bl;
+ class_symtab->free_ptr = (char *) bl;
+ }
+ return class_symtab;
+}
+
+static void
+add_class_symtab_symbol (sym)
+ struct symbol *sym;
+{
+ struct symtab *symtab = get_java_class_symtab ();
+ struct blockvector *bv = BLOCKVECTOR (symtab);
+ struct block *bl = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
+ if (BLOCK_NSYMS (bl) >= class_symtab_space)
+ {
+ /* Need to re-allocate. */
+ class_symtab_space *= 2;
+ bl = (struct block *)
+ mrealloc (symtab->objfile->md, bl,
+ sizeof (struct block)
+ + ((class_symtab_space - 1) * sizeof (struct symbol *)));
+ class_symtab->free_ptr = (char *) bl;
+ BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK) = bl;
+ }
+
+ BLOCK_SYM (bl, BLOCK_NSYMS (bl)) = sym;
+ BLOCK_NSYMS (bl) = BLOCK_NSYMS (bl) + 1;
+}
+
+static struct symbol * add_class_symbol PARAMS ((struct type *type, CORE_ADDR addr));
+
+static struct symbol *
+add_class_symbol (type, addr)
+ struct type *type;
+ CORE_ADDR addr;
+{
+ struct symbol *sym;
+ sym = (struct symbol *)
+ obstack_alloc (&dynamics_objfile->symbol_obstack, sizeof (struct symbol));
+ memset (sym, 0, sizeof (struct symbol));
+ SYMBOL_LANGUAGE (sym) = language_java;
+ SYMBOL_NAME (sym) = TYPE_TAG_NAME (type);
+ SYMBOL_CLASS (sym) = LOC_TYPEDEF;
+ /* SYMBOL_VALUE (sym) = valu;*/
+ SYMBOL_TYPE (sym) = type;
+ SYMBOL_NAMESPACE (sym) = STRUCT_NAMESPACE;
+ SYMBOL_VALUE_ADDRESS (sym) = addr;
+ return sym;
+}
+#endif
+
+struct type *
+java_lookup_class (name)
+ char *name;
+{
+ struct symbol *sym;
+ sym = lookup_symbol (name, expression_context_block, STRUCT_NAMESPACE,
+ (int *) 0, (struct symtab **) NULL);
+ if (sym != NULL)
+ return SYMBOL_TYPE (sym);
+#if 0
+ CORE_ADDR addr;
+ if (called from parser)
+ {
+ call lookup_class (or similar) in inferior;
+ if not found:
+ return NULL;
+ addr = found in inferior;
+ }
+ else
+ addr = 0;
+ struct type *type;
+ type = alloc_type (objfile);
+ TYPE_CODE (type) = TYPE_CODE_STRUCT;
+ INIT_CPLUS_SPECIFIC (type);
+ TYPE_TAG_NAME (type) = obsavestring (name, strlen(name), &objfile->type_obstack);
+ TYPE_FLAGS (type) |= TYPE_FLAG_STUB;
+ TYPE ? = addr;
+ return type;
+#else
+ /* FIXME - should search inferior's symbol table. */
+ return NULL;
+#endif
+}
+
+/* Return a nul-terminated string (allocated on OBSTACK) for
+ a name given by NAME (which has type Utf8Const*). */
+
+char *
+get_java_utf8_name (obstack, name)
+ struct obstack *obstack;
+ value_ptr name;
+{
+ char *chrs;
+ value_ptr temp = name;
+ int name_length;
+ CORE_ADDR data_addr;
+ temp = value_struct_elt (&temp, NULL, "length", NULL, "structure");
+ name_length = (int) value_as_long (temp);
+ data_addr = VALUE_ADDRESS (temp) + VALUE_OFFSET (temp)
+ + TYPE_LENGTH (VALUE_TYPE (temp));
+ chrs = obstack_alloc (obstack, name_length+1);
+ chrs [name_length] = '\0';
+ read_memory_section (data_addr, chrs, name_length, NULL);
+ return chrs;
+}
+
+value_ptr
+java_class_from_object (obj_val)
+ value_ptr obj_val;
+{
+ /* This is all rather inefficient, since the offsets of vtable and
+ class are fixed. FIXME */
+ value_ptr vtable_val;
+
+ if (TYPE_CODE (VALUE_TYPE (obj_val)) == TYPE_CODE_PTR
+ && TYPE_LENGTH (TYPE_TARGET_TYPE (VALUE_TYPE (obj_val))) == 0)
+ obj_val = value_at (get_java_object_type (),
+ value_as_pointer (obj_val), NULL);
+
+ vtable_val = value_struct_elt (&obj_val, NULL, "vtable", NULL, "structure");
+ return value_struct_elt (&vtable_val, NULL, "class", NULL, "structure");
+}
+
+/* Check if CLASS_IS_PRIMITIVE(value of clas): */
+int
+java_class_is_primitive (clas)
+ value_ptr clas;
+{
+ value_ptr vtable = value_struct_elt (&clas, NULL, "vtable", NULL, "struct");
+ CORE_ADDR i = value_as_pointer (vtable);
+ return (int) (i & 0x7fffffff) == (int) 0x7fffffff;
+}
+
+/* Read a GCJ Class object, and generated a gdb (TYPE_CODE_STRUCT) type. */
+
+struct type *
+type_from_class (clas)
+ value_ptr clas;
+{
+ struct type *type;
+ char *name;
+ value_ptr temp;
+ struct objfile *objfile;
+ value_ptr utf8_name;
+ char *nptr;
+ CORE_ADDR addr;
+ struct block *bl;
+ int i;
+ int is_array = 0;
+
+ type = check_typedef (VALUE_TYPE (clas));
+ if (TYPE_CODE (type) == TYPE_CODE_PTR)
+ {
+ if (value_logical_not (clas))
+ return NULL;
+ clas = value_ind (clas);
+ }
+ addr = VALUE_ADDRESS (clas) + VALUE_OFFSET (clas);
+
+#if 0
+ get_java_class_symtab ();
+ bl = BLOCKVECTOR_BLOCK (BLOCKVECTOR (class_symtab), GLOBAL_BLOCK);
+ for (i = BLOCK_NSYMS (bl); --i >= 0; )
+ {
+ struct symbol *sym = BLOCK_SYM (bl, i);
+ if (SYMBOL_VALUE_ADDRESS (sym) == addr)
+ return SYMBOL_TYPE (sym);
+ }
+#endif
+
+ objfile = get_dynamics_objfile();
+ if (java_class_is_primitive (clas))
+ {
+ value_ptr sig;
+ temp = clas;
+ sig = value_struct_elt (&temp, NULL, "method_count", NULL, "structure");
+ return java_primitive_type (value_as_long (sig));
+ }
+
+ /* Get Class name. */
+ /* if clasloader non-null, prepend loader address. FIXME */
+ temp = clas;
+ utf8_name = value_struct_elt (&temp, NULL, "name", NULL, "structure");
+ name = get_java_utf8_name (&objfile->type_obstack, utf8_name);
+ for (nptr = name; *nptr != 0; nptr++)
+ {
+ if (*nptr == '/')
+ *nptr = '.';
+ }
+
+ type = java_lookup_class (name);
+ if (type != NULL)
+ return type;
+
+ type = alloc_type (objfile);
+ TYPE_CODE (type) = TYPE_CODE_STRUCT;
+ INIT_CPLUS_SPECIFIC (type);
+
+ if (name[0] == '[')
+ {
+ char *signature = name;
+ int namelen = java_demangled_signature_length (signature);
+ if (namelen > strlen (name))
+ name = obstack_alloc (&objfile->type_obstack, namelen+1);
+ java_demangled_signature_copy (name, signature);
+ name[namelen] = '\0';
+ is_array = 1;
+ temp = clas;
+ /* Set array element type. */
+ temp = value_struct_elt (&temp, NULL, "methods", NULL, "structure");
+ VALUE_TYPE (temp) = lookup_pointer_type (VALUE_TYPE (clas));
+ TYPE_TARGET_TYPE (type) = type_from_class (temp);
+ }
+
+ ALLOCATE_CPLUS_STRUCT_TYPE (type);
+ TYPE_TAG_NAME (type) = name;
+
+ add_class_symtab_symbol (add_class_symbol (type, addr));
+ return java_link_class_type (type, clas);
+}
+
+/* Fill in class TYPE with data from the CLAS value. */
+
+struct type *
+java_link_class_type (type, clas)
+ struct type *type;
+ value_ptr clas;
+{
+ value_ptr temp;
+ char *unqualified_name;
+ char *name = TYPE_TAG_NAME (type);
+ int ninterfaces, nfields, nmethods;
+ int type_is_object = 0;
+ struct fn_field *fn_fields;
+ struct fn_fieldlist *fn_fieldlists;
+ value_ptr fields, field, method, methods;
+ int i, j;
+ struct objfile *objfile = get_dynamics_objfile();
+ struct type *tsuper;
+
+ unqualified_name = strrchr (name, '.');
+ if (unqualified_name == NULL)
+ unqualified_name = name;
+
+ temp = clas;
+ temp = value_struct_elt (&temp, NULL, "superclass", NULL, "structure");
+ if (name != NULL && strcmp (name, "java.lang.Object") == 0)
+ {
+ tsuper = get_java_object_type ();
+ if (tsuper && TYPE_CODE (tsuper) == TYPE_CODE_PTR)
+ tsuper = TYPE_TARGET_TYPE (tsuper);
+ type_is_object = 1;
+ }
+ else
+ tsuper = type_from_class (temp);
+
+#if 1
+ ninterfaces = 0;
+#else
+ temp = clas;
+ ninterfaces = value_as_long (value_struct_elt (&temp, NULL, "interface_len", NULL, "structure"));
+#endif
+ TYPE_N_BASECLASSES (type) = (tsuper == NULL ? 0 : 1) + ninterfaces;
+ temp = clas;
+ nfields = value_as_long (value_struct_elt (&temp, NULL, "field_count", NULL, "structure"));
+ nfields += TYPE_N_BASECLASSES (type);
+ nfields++; /* Add one for dummy "class" field. */
+ 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);
+
+ 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);
+
+ TYPE_FIELD_IGNORE_BITS (type) =
+ (B_TYPE *) TYPE_ALLOC (type, B_BYTES (nfields));
+ B_CLRALL (TYPE_FIELD_IGNORE_BITS (type), nfields);
+
+ TYPE_FIELD_VIRTUAL_BITS (type) = (B_TYPE *)
+ TYPE_ALLOC (type, B_BYTES (TYPE_N_BASECLASSES (type)));
+ B_CLRALL (TYPE_FIELD_VIRTUAL_BITS (type), TYPE_N_BASECLASSES (type));
+
+ if (tsuper != NULL)
+ {
+ TYPE_BASECLASS (type, 0) = tsuper;
+ if (type_is_object)
+ SET_TYPE_FIELD_PRIVATE (type, 0);
+ }
+
+ i = strlen (name);
+ if (i > 2 && name[i-1] == ']' && tsuper != NULL)
+ {
+ /* FIXME */
+ TYPE_LENGTH (type) = TYPE_LENGTH (tsuper) + 4; /* size with "length" */
+ }
+ else
+ {
+ temp = clas;
+ temp = value_struct_elt (&temp, NULL, "size_in_bytes", NULL, "structure");
+ TYPE_LENGTH (type) = value_as_long (temp);
+ }
+
+ fields = NULL;
+ nfields--; /* First set up dummy "class" field. */
+ SET_FIELD_PHYSADDR (TYPE_FIELD (type, nfields),
+ VALUE_ADDRESS (clas) + VALUE_OFFSET (clas));
+ TYPE_FIELD_NAME (type, nfields) = "class";
+ TYPE_FIELD_TYPE (type, nfields) = VALUE_TYPE (clas);
+ SET_TYPE_FIELD_PRIVATE (type, nfields);
+
+ for (i = TYPE_N_BASECLASSES (type); i < nfields; i++)
+ {
+ int accflags;
+ int boffset;
+ if (fields == NULL)
+ {
+ temp = clas;
+ fields = value_struct_elt (&temp, NULL, "fields", NULL, "structure");
+ field = value_ind (fields);
+ }
+ else
+ { /* Re-use field value for next field. */
+ VALUE_ADDRESS (field) += TYPE_LENGTH (VALUE_TYPE (field));
+ VALUE_LAZY (field) = 1;
+ }
+ temp = field;
+ temp = value_struct_elt (&temp, NULL, "name", NULL, "structure");
+ TYPE_FIELD_NAME (type, i) =
+ get_java_utf8_name (&objfile->type_obstack, temp);
+ temp = field;
+ accflags = value_as_long (value_struct_elt (&temp, NULL, "accflags",
+ NULL, "structure"));
+ temp = field;
+ temp = value_struct_elt (&temp, NULL, "info", NULL, "structure");
+ boffset = value_as_long (value_struct_elt (&temp, NULL, "boffset",
+ NULL, "structure"));
+ if (accflags & 0x0001) /* public access */
+ {
+ /* ??? */
+ }
+ if (accflags & 0x0002) /* private access */
+ {
+ SET_TYPE_FIELD_PRIVATE (type, i);
+ }
+ if (accflags & 0x0004) /* protected access */
+ {
+ SET_TYPE_FIELD_PROTECTED (type, i);
+ }
+ if (accflags & 0x0008) /* ACC_STATIC */
+ SET_FIELD_PHYSADDR(TYPE_FIELD(type, i), boffset);
+ else
+ TYPE_FIELD_BITPOS (type, i) = 8 * boffset;
+ if (accflags & 0x8000) /* FIELD_UNRESOLVED_FLAG */
+ {
+ TYPE_FIELD_TYPE (type, i) = get_java_object_type (); /* FIXME */
+ }
+ else
+ {
+ struct type *ftype;
+ temp = field;
+ temp = value_struct_elt (&temp, NULL, "type", NULL, "structure");
+ ftype = type_from_class (temp);
+ if (TYPE_CODE (ftype) == TYPE_CODE_STRUCT)
+ ftype = lookup_pointer_type (ftype);
+ TYPE_FIELD_TYPE (type, i) = ftype;
+ }
+ }
+
+ temp = clas;
+ nmethods = value_as_long (value_struct_elt (&temp, NULL, "method_count",
+ NULL, "structure"));
+ TYPE_NFN_FIELDS_TOTAL (type) = nmethods;
+ j = nmethods * sizeof (struct fn_field);
+ fn_fields = (struct fn_field*)
+ obstack_alloc (&dynamics_objfile->symbol_obstack, j);
+ memset (fn_fields, 0, j);
+ fn_fieldlists = (struct fn_fieldlist*)
+ alloca (nmethods * sizeof (struct fn_fieldlist));
+
+ methods = NULL;
+ for (i = 0; i < nmethods; i++)
+ {
+ char *mname;
+ int k;
+ if (methods == NULL)
+ {
+ temp = clas;
+ methods = value_struct_elt (&temp, NULL, "methods", NULL, "structure");
+ method = value_ind (methods);
+ }
+ else
+ { /* Re-use method value for next method. */
+ VALUE_ADDRESS (method) += TYPE_LENGTH (VALUE_TYPE (method));
+ VALUE_LAZY (method) = 1;
+ }
+
+ /* Get method name. */
+ temp = method;
+ temp = value_struct_elt (&temp, NULL, "name", NULL, "structure");
+ mname = get_java_utf8_name (&objfile->type_obstack, temp);
+ if (strcmp (mname, "<init>") == 0)
+ mname = unqualified_name;
+
+ /* Check for an existing method with the same name.
+ * This makes building the fn_fieldslists an O(nmethods**2)
+ * operation. That could be using hashing, but I doubt it
+ * is worth it. Note that we do maintain the order of methods
+ * in the inferior's Method table (as long as that is grouped
+ * by method name), which I think is desirable. --PB */
+ for (k = 0, j = TYPE_NFN_FIELDS (type); ; )
+ {
+ if (--j < 0)
+ { /* No match - new method name. */
+ j = TYPE_NFN_FIELDS(type)++;
+ fn_fieldlists[j].name = mname;
+ fn_fieldlists[j].length = 1;
+ fn_fieldlists[j].fn_fields = &fn_fields[i];
+ k = i;
+ break;
+ }
+ if (strcmp (mname, fn_fieldlists[j].name) == 0)
+ { /* Found an existing method with the same name. */
+ int l;
+ if (mname != unqualified_name)
+ obstack_free (&objfile->type_obstack, mname);
+ mname = fn_fieldlists[j].name;
+ fn_fieldlists[j].length++;
+ k = i - k; /* Index of new slot. */
+ /* Shift intervening fn_fields (between k and i) down. */
+ for (l = i; l > k; l--) fn_fields[l] = fn_fields[l-1];
+ for (l = TYPE_NFN_FIELDS (type); --l > j; )
+ fn_fieldlists[l].fn_fields++;
+ break;
+ }
+ k += fn_fieldlists[j].length;
+ }
+ fn_fields[k].physname = "";
+ fn_fields[k].is_stub = 1;
+ fn_fields[k].type = make_function_type (java_void_type, NULL); /* FIXME*/
+ TYPE_CODE (fn_fields[k].type) = TYPE_CODE_METHOD;
+ }
+
+ j = TYPE_NFN_FIELDS(type) * sizeof (struct fn_fieldlist);
+ TYPE_FN_FIELDLISTS (type) = (struct fn_fieldlist*)
+ obstack_alloc (&dynamics_objfile->symbol_obstack, j);
+ memcpy (TYPE_FN_FIELDLISTS (type), fn_fieldlists, j);
+
+ return type;
+}
+
+static struct type *java_object_type;
+
+struct type *
+get_java_object_type ()
+{
+ if (java_object_type == NULL)
+ {
+ struct symbol *sym;
+ sym = lookup_symbol ("java.lang.Object", NULL, STRUCT_NAMESPACE,
+ (int *) 0, (struct symtab **) NULL);
+ if (sym == NULL)
+ error ("cannot find java.lang.Object");
+ java_object_type = SYMBOL_TYPE (sym);
+ }
+ return java_object_type;
+}
+
+int
+get_java_object_header_size ()
+{
+ struct type *objtype = get_java_object_type ();
+ if (objtype == NULL)
+ return (2 * TARGET_PTR_BIT / TARGET_CHAR_BIT);
+ else
+ return TYPE_LENGTH (objtype);
+}
+
+int
+is_object_type (type)
+ struct type *type;
+{
+ CHECK_TYPEDEF (type);
+ if (TYPE_CODE (type) == TYPE_CODE_PTR)
+ {
+ struct type *ttype = check_typedef (TYPE_TARGET_TYPE (type));
+ char *name;
+ if (TYPE_CODE (ttype) != TYPE_CODE_STRUCT)
+ return 0;
+ while (TYPE_N_BASECLASSES (ttype) > 0)
+ ttype = TYPE_BASECLASS (ttype, 0);
+ name = TYPE_TAG_NAME (ttype);
+ if (name != NULL && strcmp (name, "java.lang.Object") == 0)
+ return 1;
+ name = TYPE_NFIELDS (ttype) > 0 ? TYPE_FIELD_NAME (ttype, 0) : (char*)0;
+ if (name != NULL && strcmp (name, "vtable") == 0)
+ {
+ if (java_object_type == NULL)
+ java_object_type = type;
+ return 1;
+ }
+ }
+ return 0;
+}
+
+struct type *
+java_primitive_type (signature)
+ int signature;
+{
+ switch (signature)
+ {
+ case 'B': return java_byte_type;
+ case 'S': return java_short_type;
+ case 'I': return java_int_type;
+ case 'J': return java_long_type;
+ case 'Z': return java_boolean_type;
+ case 'C': return java_char_type;
+ case 'F': return java_float_type;
+ case 'D': return java_double_type;
+ case 'V': return java_void_type;
+ }
+ error ("unknown signature '%c' for primitive type", (char) signature);
+}
+
+/* If name[0 .. namelen-1] is the name of a primitive Java type,
+ return that type. Otherwise, return NULL. */
+
+struct type *
+java_primitive_type_from_name (name, namelen)
+ char* name;
+ int namelen;
+{
+ switch (name[0])
+ {
+ case 'b':
+ if (namelen == 4 && memcmp (name, "byte", 4) == 0)
+ return java_byte_type;
+ if (namelen == 7 && memcmp (name, "boolean", 7) == 0)
+ return java_boolean_type;
+ break;
+ case 'c':
+ if (namelen == 4 && memcmp (name, "char", 4) == 0)
+ return java_char_type;
+ case 'd':
+ if (namelen == 6 && memcmp (name, "double", 6) == 0)
+ return java_double_type;
+ break;
+ case 'f':
+ if (namelen == 5 && memcmp (name, "float", 5) == 0)
+ return java_float_type;
+ break;
+ case 'i':
+ if (namelen == 3 && memcmp (name, "int", 3) == 0)
+ return java_int_type;
+ break;
+ case 'l':
+ if (namelen == 4 && memcmp (name, "long", 4) == 0)
+ return java_long_type;
+ break;
+ case 's':
+ if (namelen == 5 && memcmp (name, "short", 5) == 0)
+ return java_short_type;
+ break;
+ case 'v':
+ if (namelen == 4 && memcmp (name, "void", 4) == 0)
+ return java_void_type;
+ break;
+ }
+ return NULL;
+}
+
+/* Return the length (in bytes) of demangled name of the Java type
+ signature string SIGNATURE. */
+
+static int
+java_demangled_signature_length (signature)
+ char *signature;
+{
+ int array = 0;
+ for (; *signature == '['; signature++)
+ array += 2; /* Two chars for "[]". */
+ switch (signature[0])
+ {
+ case 'L':
+ /* Subtract 2 for 'L' and ';'. */
+ return strlen (signature) - 2 + array;
+ default:
+ return strlen (TYPE_NAME (java_primitive_type (signature[0]))) + array;
+ }
+}
+
+/* Demangle the Java type signature SIGNATURE, leaving the result in RESULT. */
+
+static void
+java_demangled_signature_copy (result, signature)
+ char *result;
+ char *signature;
+{
+ int array = 0;
+ char *ptr;
+ int i;
+ while (*signature == '[')
+ {
+ array++;
+ signature++;
+ }
+ switch (signature[0])
+ {
+ case 'L':
+ /* Subtract 2 for 'L' and ';', but add 1 for final nul. */
+ signature++;
+ ptr = result;
+ for ( ; *signature != ';' && *signature != '\0'; signature++)
+ {
+ if (*signature == '/')
+ *ptr++ = '.';
+ else
+ *ptr++ = *signature;
+ }
+ break;
+ default:
+ ptr = TYPE_NAME (java_primitive_type (signature[0]));
+ i = strlen (ptr);
+ strcpy (result, ptr);
+ ptr = result + i;
+ break;
+ }
+ while (--array >= 0)
+ {
+ *ptr++ = '[';
+ *ptr++ = ']';
+ }
+}
+
+/* Return the demangled name of the Java type signature string SIGNATURE,
+ as a freshly allocated copy. */
+
+char *
+java_demangle_type_signature (signature)
+ char *signature;
+{
+ int length = java_demangled_signature_length (signature);
+ char *result = xmalloc (length + 1);
+ java_demangled_signature_copy (result, signature);
+ result[length] = '\0';
+ return result;
+}
+
+struct type *
+java_lookup_type (signature)
+ char *signature;
+{
+ switch (signature[0])
+ {
+ case 'L':
+ case '[':
+ error ("java_lookup_type not fully implemented");
+ default:
+ return java_primitive_type (signature[0]);
+ }
+}
+
+/* Return the type of TYPE followed by DIMS pairs of [ ].
+ If DIMS == 0, TYPE is returned. */
+
+struct type *
+java_array_type (type, dims)
+ struct type *type;
+ int dims;
+{
+ struct type *range_type;
+
+ while (dims-- > 0)
+ {
+ range_type = create_range_type (NULL, builtin_type_int, 0, 0);
+ /* FIXME This is bogus! Java arrays are not gdb arrays! */
+ type = create_array_type (NULL, type, range_type);
+ }
+
+ return type;
+}
+
+/* Create a Java string in the inferior from a (Utf8) literal. */
+
+value_ptr
+java_value_string (ptr, len)
+ char *ptr;
+ int len;
+{
+ error ("not implemented - java_value_string"); /* FIXME */
+}
+
+/* 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
+java_emit_char (c, stream, quoter)
+ int c;
+ GDB_FILE *stream;
+ int quoter;
+{
+ switch (c)
+ {
+ case '\\':
+ case '\'':
+ fprintf_filtered (stream, "\\%c", c);
+ break;
+ case '\b':
+ fputs_filtered ("\\b", stream);
+ break;
+ case '\t':
+ fputs_filtered ("\\t", stream);
+ break;
+ case '\n':
+ fputs_filtered ("\\n", stream);
+ break;
+ case '\f':
+ fputs_filtered ("\\f", stream);
+ break;
+ case '\r':
+ fputs_filtered ("\\r", stream);
+ break;
+ default:
+ if (isprint (c))
+ fputc_filtered (c, stream);
+ else
+ fprintf_filtered (stream, "\\u%.4x", (unsigned int) c);
+ break;
+ }
+}
+
+static value_ptr
+evaluate_subexp_java (expect_type, exp, pos, noside)
+ struct type *expect_type;
+ register struct expression *exp;
+ register int *pos;
+ enum noside noside;
+{
+ int pc = *pos;
+ int i;
+ char *name;
+ enum exp_opcode op = exp->elts[*pos].opcode;
+ value_ptr arg1, arg2;
+ struct type *type;
+ switch (op)
+ {
+ case UNOP_IND:
+ if (noside == EVAL_SKIP)
+ goto standard;
+ (*pos)++;
+ arg1 = evaluate_subexp_java (NULL_TYPE, exp, pos, EVAL_NORMAL);
+ if (is_object_type (VALUE_TYPE (arg1)))
+ {
+ struct type *type;
+
+ type = type_from_class (java_class_from_object (arg1));
+ arg1 = value_cast (lookup_pointer_type (type), arg1);
+ }
+ if (noside == EVAL_SKIP)
+ goto nosideret;
+ return value_ind (arg1);
+
+ case BINOP_SUBSCRIPT:
+ (*pos)++;
+ arg1 = evaluate_subexp_with_coercion (exp, pos, noside);
+ arg2 = evaluate_subexp_with_coercion (exp, pos, noside);
+ if (noside == EVAL_SKIP)
+ goto nosideret;
+ /* If the user attempts to subscript something that is not an
+ array or pointer type (like a plain int variable for example),
+ then report this as an error. */
+
+ COERCE_REF (arg1);
+ type = check_typedef (VALUE_TYPE (arg1));
+ if (TYPE_CODE (type) == TYPE_CODE_PTR)
+ type = check_typedef (TYPE_TARGET_TYPE (type));
+ name = TYPE_NAME (type);
+ if (name == NULL)
+ name = TYPE_TAG_NAME (type);
+ i = name == NULL ? 0 : strlen (name);
+ if (TYPE_CODE (type) == TYPE_CODE_STRUCT
+ && i > 2 && name [i - 1] == ']')
+ {
+ CORE_ADDR address;
+ long length, index;
+ struct type *el_type;
+ char buf4[4];
+
+ value_ptr clas = java_class_from_object(arg1);
+ value_ptr temp = clas;
+ /* Get CLASS_ELEMENT_TYPE of the array type. */
+ temp = value_struct_elt (&temp, NULL, "methods",
+ NULL, "structure");
+ VALUE_TYPE (temp) = VALUE_TYPE (clas);
+ el_type = type_from_class (temp);
+ if (TYPE_CODE (el_type) == TYPE_CODE_STRUCT)
+ el_type = lookup_pointer_type (el_type);
+
+ if (noside == EVAL_AVOID_SIDE_EFFECTS)
+ return value_zero (el_type, VALUE_LVAL (arg1));
+ address = value_as_pointer (arg1);
+ address += JAVA_OBJECT_SIZE;
+ read_memory (address, buf4, 4);
+ length = (long) extract_signed_integer (buf4, 4);
+ index = (long) value_as_long (arg2);
+ if (index >= length || index < 0)
+ error ("array index (%ld) out of bounds (length: %ld)",
+ index, length);
+ address = (address + 4) + index * TYPE_LENGTH (el_type);
+ return value_at (el_type, address, NULL);
+ }
+ else if (TYPE_CODE (type) == TYPE_CODE_ARRAY)
+ {
+ if (noside == EVAL_AVOID_SIDE_EFFECTS)
+ return value_zero (TYPE_TARGET_TYPE (type), VALUE_LVAL (arg1));
+ else
+ return value_subscript (arg1, arg2);
+ }
+ if (name)
+ error ("cannot subscript something of type `%s'", name);
+ else
+ error ("cannot subscript requested type");
+
+ case OP_STRING:
+ (*pos)++;
+ i = longest_to_int (exp->elts[pc + 1].longconst);
+ (*pos) += 3 + BYTES_TO_EXP_ELEM (i + 1);
+ if (noside == EVAL_SKIP)
+ goto nosideret;
+ return java_value_string (&exp->elts[pc + 2].string, i);
+
+ case STRUCTOP_STRUCT:
+ arg1 = evaluate_subexp_standard (expect_type, exp, pos, noside);
+ /* Convert object field (such as TYPE.class) to reference. */
+ if (TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_STRUCT)
+ arg1 = value_addr (arg1);
+ return arg1;
+ default:
+ break;
+ }
+standard:
+ return evaluate_subexp_standard (expect_type, exp, pos, noside);
+ nosideret:
+ return value_from_longest (builtin_type_long, (LONGEST) 1);
+}
+
+static struct type *
+java_create_fundamental_type (objfile, typeid)
+ struct objfile *objfile;
+ int typeid;
+{
+ switch (typeid)
+ {
+ case FT_VOID: return java_void_type;
+ case FT_BOOLEAN: return java_boolean_type;
+ case FT_CHAR: return java_char_type;
+ case FT_FLOAT: return java_float_type;
+ case FT_DBL_PREC_FLOAT: return java_double_type;
+ case FT_BYTE: case FT_SIGNED_CHAR: return java_byte_type;
+ case FT_SHORT: case FT_SIGNED_SHORT: return java_short_type;
+ case FT_INTEGER: case FT_SIGNED_INTEGER: return java_int_type;
+ case FT_LONG: case FT_SIGNED_LONG: return java_long_type;
+ }
+ return c_create_fundamental_type (objfile, typeid);
+}
+
+/* Table mapping opcodes into strings for printing operators
+ and precedences of the operators. */
+
+const struct op_print java_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},
+#if 0
+ {">>>", BINOP_???, PREC_SHIFT, 0},
+#endif
+ {"+", 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},
+ {"-", UNOP_NEG, PREC_PREFIX, 0},
+ {"!", UNOP_LOGICAL_NOT, PREC_PREFIX, 0},
+ {"~", UNOP_COMPLEMENT, PREC_PREFIX, 0},
+ {"*", UNOP_IND, PREC_PREFIX, 0},
+#if 0
+ {"instanceof", ???, ???, 0},
+#endif
+ {"++", UNOP_PREINCREMENT, PREC_PREFIX, 0},
+ {"--", UNOP_PREDECREMENT, PREC_PREFIX, 0},
+ {NULL, 0, 0, 0}
+};
+
+const struct language_defn java_language_defn = {
+ "java", /* Language name */
+ language_java,
+ c_builtin_types,
+ range_check_off,
+ type_check_off,
+ java_parse,
+ java_error,
+ evaluate_subexp_java,
+ c_printchar, /* Print a character constant */
+ c_printstr, /* Function to print string constant */
+ java_emit_char, /* Function to print a single character */
+ java_create_fundamental_type, /* Create fundamental type in this language */
+ java_print_type, /* Print a type using appropriate syntax */
+ java_val_print, /* Print a value using appropriate syntax */
+ java_value_print, /* Print a top-level value */
+ {"", "", "", ""}, /* Binary format info */
+ {"0%lo", "0", "o", ""}, /* Octal format info */
+ {"%ld", "", "d", ""}, /* Decimal format info */
+ {"0x%lx", "0x", "x", ""}, /* Hex format info */
+ java_op_print_tab, /* expression operators for printing */
+ 0, /* not c-style arrays */
+ 0, /* String lower bound */
+ &builtin_type_char, /* Type of string elements */
+ LANG_MAGIC
+};
+
+void
+_initialize_java_language ()
+{
+
+ java_int_type = init_type (TYPE_CODE_INT, 4, 0, "int", NULL);
+ java_short_type = init_type (TYPE_CODE_INT, 2, 0, "short", NULL);
+ java_long_type = init_type (TYPE_CODE_INT, 8, 0, "long", NULL);
+ java_byte_type = init_type (TYPE_CODE_INT, 1, 0, "byte", NULL);
+ java_boolean_type= init_type (TYPE_CODE_BOOL, 1, 0, "boolean", NULL);
+ java_char_type = init_type (TYPE_CODE_CHAR, 2, TYPE_FLAG_UNSIGNED, "char", NULL);
+ java_float_type = init_type (TYPE_CODE_FLT, 4, 0, "float", NULL);
+ java_double_type = init_type (TYPE_CODE_FLT, 8, 0, "double", NULL);
+ java_void_type = init_type (TYPE_CODE_VOID, 1, 0, "void", NULL);
+
+ add_language (&java_language_defn);
+}
+
+/* Cleanup code that should be run on every "run".
+ We should use make_run_cleanup to have this be called.
+ But will that mess up values in value histry? FIXME */
+
+void java_rerun_cleanup ()
+{
+ if (class_symtab != NULL)
+ {
+ free_symtab (class_symtab); /* ??? */
+ class_symtab = NULL;
+ }
+ if (dynamics_objfile != NULL)
+ {
+ free_objfile (dynamics_objfile);
+ dynamics_objfile = NULL;
+ }
+
+ java_object_type = NULL;
+}
diff --git a/gdb/jv-lang.h b/gdb/jv-lang.h
new file mode 100644
index 00000000000..44c44375a46
--- /dev/null
+++ b/gdb/jv-lang.h
@@ -0,0 +1,67 @@
+/* Java language support definitions for GDB, the GNU debugger.
+ Copyright 1997, 1998, 1999 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+extern int
+java_parse PARAMS ((void)); /* Defined in jv-exp.y */
+
+extern void
+java_error PARAMS ((char *)); /* Defined in jv-exp.y */
+
+/* sizeof (struct Object) */
+#define JAVA_OBJECT_SIZE (get_java_object_header_size ())
+
+extern struct type *java_int_type;
+extern struct type *java_byte_type;
+extern struct type *java_short_type;
+extern struct type *java_long_type;
+extern struct type *java_boolean_type;
+extern struct type *java_char_type;
+extern struct type *java_float_type;
+extern struct type *java_double_type;
+extern struct type *java_void_type;
+
+extern int
+java_val_print PARAMS ((struct type *, char *, int, CORE_ADDR, GDB_FILE *, int, int,
+ int, enum val_prettyprint));
+
+extern int
+java_value_print PARAMS ((struct value *, GDB_FILE *, int,
+ enum val_prettyprint));
+
+extern value_ptr java_class_from_object PARAMS ((value_ptr));
+
+extern struct type *type_from_class PARAMS ((struct value *));
+
+extern struct type *java_primitive_type PARAMS ((int signature));
+
+extern struct type *java_primitive_type_from_name PARAMS ((char*, int));
+
+extern struct type *java_array_type PARAMS ((struct type *, int));
+
+extern struct type *get_java_object_type PARAMS ((void));
+extern int get_java_object_header_size PARAMS ((void));
+
+extern struct type *java_lookup_class PARAMS((char *));
+
+extern int is_object_type PARAMS ((struct type*));
+
+extern void /* Defined in jv-typeprint.c */
+java_print_type PARAMS ((struct type *, char *, GDB_FILE *, int, int));
+
+extern char *java_demangle_type_signature PARAMS ((char *));
diff --git a/gdb/jv-typeprint.c b/gdb/jv-typeprint.c
new file mode 100644
index 00000000000..59539a0da9f
--- /dev/null
+++ b/gdb/jv-typeprint.c
@@ -0,0 +1,339 @@
+/* Support for printing Java types for GDB, the GNU debugger.
+ Copyright 1997, 1998, 1999 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+
+#include "defs.h"
+#include "symtab.h"
+#include "gdbtypes.h"
+#include "value.h"
+#include "demangle.h"
+#include "jv-lang.h"
+#include "gdb_string.h"
+#include "typeprint.h"
+
+static void
+java_type_print_derivation_info (stream, type)
+ GDB_FILE *stream;
+ struct type *type;
+{
+ char *name;
+ int i;
+ int n_bases;
+ int prev;
+
+ n_bases = TYPE_N_BASECLASSES (type);
+
+ for (i = 0, prev = 0; i < n_bases; i++)
+ {
+ int kind;
+
+ kind = BASETYPE_VIA_VIRTUAL(type, i) ? 'I' : 'E';
+
+ fputs_filtered (kind == prev ? ", "
+ : kind == 'I' ? " implements "
+ : " extends ",
+ stream);
+ prev = kind;
+ name = type_name_no_tag (TYPE_BASECLASS (type, i));
+
+ fprintf_filtered (stream, "%s", name ? name : "(null)");
+ }
+
+ if (i > 0)
+ fputs_filtered (" ", stream);
+}
+
+/* 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 negative 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 zero means just print the type name or struct tag if there is one.
+ If there is no name, print something sensible but not as concise like
+ "struct {int x; int y;}".
+
+ LEVEL is the number of spaces to indent by.
+ We increase it for some recursive calls. */
+
+void
+java_type_print_base (type, stream, show, level)
+ struct type *type;
+ GDB_FILE *stream;
+ int show;
+ int level;
+{
+ register int i;
+ register int len;
+ char *mangled_name;
+ char *demangled_name;
+ 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;
+ }
+
+ CHECK_TYPEDEF (type);
+
+ switch (TYPE_CODE (type))
+ {
+ case TYPE_CODE_PTR:
+ java_type_print_base (TYPE_TARGET_TYPE (type), stream, show, level);
+ break;
+
+ case TYPE_CODE_STRUCT:
+ if (TYPE_TAG_NAME (type) != NULL && TYPE_TAG_NAME (type)[0] == '[')
+ { /* array type */
+ char *name = java_demangle_type_signature (TYPE_TAG_NAME (type));
+ fputs_filtered (name, stream);
+ free (name);
+ break;
+ }
+
+ if (show >= 0)
+ fprintf_filtered (stream, "class ");
+
+ 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 || TYPE_TAG_NAME (type) == NULL)
+ {
+ java_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");
+
+ /* 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 (STREQN (TYPE_FIELD_NAME (type, i), "_vptr", 5)
+ && is_cplus_marker ((TYPE_FIELD_NAME (type, i))[5]))
+ continue;
+
+ /* Don't print the dummy field "class". */
+ if (STREQN (TYPE_FIELD_NAME (type, i), "class", 5))
+ continue;
+
+ print_spaces_filtered (level + 4, stream);
+
+ if (HAVE_CPLUS_STRUCT (type))
+ if (TYPE_FIELD_PROTECTED (type, i))
+ fprintf_filtered (stream, "protected ");
+ else if (TYPE_FIELD_PRIVATE (type, i))
+ fprintf_filtered (stream, "private ");
+ else
+ fprintf_filtered (stream, "public ");
+
+ if (TYPE_FIELD_STATIC (type, i))
+ fprintf_filtered (stream, "static ");
+
+ java_print_type (TYPE_FIELD_TYPE (type, i),
+ TYPE_FIELD_NAME (type, i),
+ stream, show - 1, level + 4);
+
+ fprintf_filtered (stream, ";\n");
+ }
+
+ /* If there are both fields and methods, put a space between. */
+ len = TYPE_NFN_FIELDS (type);
+ if (len)
+ fprintf_filtered (stream, "\n");
+
+ /* Print out the methods */
+
+ for (i = 0; i < len; i++)
+ {
+ struct fn_field *f;
+ int j;
+ char *method_name;
+ char *name;
+ int is_constructor;
+ int n_overloads;
+
+ f = TYPE_FN_FIELDLIST1 (type, i);
+ n_overloads = TYPE_FN_FIELDLIST_LENGTH (type, i);
+ method_name = TYPE_FN_FIELDLIST_NAME (type, i);
+ name = type_name_no_tag (type);
+ is_constructor = name && STREQ (method_name, name);
+
+ for (j = 0; j < n_overloads; j++)
+ {
+ char *physname;
+ int is_full_physname_constructor;
+
+ physname = TYPE_FN_FIELD_PHYSNAME (f, j);
+
+ is_full_physname_constructor =
+ ((physname[0] == '_' && physname[1] == '_'
+ && strchr ("0123456789Qt", physname[2]))
+ || STREQN (physname, "__ct__", 6)
+ || DESTRUCTOR_PREFIX_P (physname)
+ || STREQN (physname, "__dt__", 6));
+
+ QUIT;
+
+ print_spaces_filtered (level + 4, stream);
+
+ if (TYPE_FN_FIELD_PROTECTED (f, j))
+ fprintf_filtered (stream, "protected ");
+ else if (TYPE_FN_FIELD_PRIVATE (f, j))
+ fprintf_filtered (stream, "private ");
+ else if (TYPE_FN_FIELD_PUBLIC (f, j))
+ fprintf_filtered (stream, "public ");
+
+ if (TYPE_FN_FIELD_ABSTRACT (f, j))
+ fprintf_filtered (stream, "abstract ");
+ if (TYPE_FN_FIELD_STATIC (f, j))
+ fprintf_filtered (stream, "static ");
+ if (TYPE_FN_FIELD_FINAL (f, j))
+ fprintf_filtered (stream, "final ");
+ if (TYPE_FN_FIELD_SYNCHRONIZED (f, j))
+ fprintf_filtered (stream, "synchronized ");
+ if (TYPE_FN_FIELD_NATIVE (f, j))
+ fprintf_filtered (stream, "native ");
+
+ if (TYPE_TARGET_TYPE (TYPE_FN_FIELD_TYPE (f, j)) == 0)
+ {
+ /* Keep GDB from crashing here. */
+ fprintf_filtered (stream, "<undefined type> %s;\n",
+ TYPE_FN_FIELD_PHYSNAME (f, j));
+ break;
+ }
+ else if (!is_constructor && !is_full_physname_constructor)
+ {
+ type_print (TYPE_TARGET_TYPE (TYPE_FN_FIELD_TYPE (f, j)),
+ "", stream, -1);
+ fputs_filtered (" ", stream);
+ }
+
+ if (TYPE_FN_FIELD_STUB (f, j))
+ /* Build something we can demangle. */
+ mangled_name = gdb_mangle_name (type, i, j);
+ else
+ mangled_name = TYPE_FN_FIELD_PHYSNAME (f, j);
+
+ demangled_name =
+ cplus_demangle (mangled_name,
+ DMGL_ANSI | DMGL_PARAMS | DMGL_JAVA);
+
+ if (demangled_name == NULL)
+ demangled_name = strdup (mangled_name);
+
+ {
+ char *demangled_no_class;
+ char *ptr;
+
+ ptr = demangled_no_class = demangled_name;
+
+ while (1)
+ {
+ char c;
+
+ c = *ptr++;
+
+ if (c == 0 || c == '(')
+ break;
+ if (c == '.')
+ demangled_no_class = ptr;
+ }
+
+ fputs_filtered (demangled_no_class, stream);
+ free (demangled_name);
+ }
+
+ if (TYPE_FN_FIELD_STUB (f, j))
+ free (mangled_name);
+
+ fprintf_filtered (stream, ";\n");
+ }
+ }
+
+ fprintfi_filtered (level, stream, "}");
+ }
+ break;
+
+ default:
+ c_type_print_base (type, stream, show, level);
+ }
+}
+
+/* LEVEL is the depth to indent lines by. */
+
+void
+java_print_type (type, varstring, stream, show, level)
+ struct type *type;
+ char *varstring;
+ GDB_FILE *stream;
+ int show;
+ int level;
+{
+ int demangled_args;
+
+ java_type_print_base (type, stream, show, level);
+
+ if (varstring != NULL && *varstring != '\0')
+ {
+ fputs_filtered (" ", stream);
+ 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 = strchr(varstring, '(') != NULL;
+ c_type_print_varspec_suffix (type, stream, show, 0, demangled_args);
+}
diff --git a/gdb/jv-valprint.c b/gdb/jv-valprint.c
new file mode 100644
index 00000000000..6bfae7e3274
--- /dev/null
+++ b/gdb/jv-valprint.c
@@ -0,0 +1,526 @@
+/* Support for printing Java values for GDB, the GNU debugger.
+ Copyright 1997, 1998, 1999 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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"
+#include "jv-lang.h"
+#include "c-lang.h"
+
+int
+java_value_print (val, stream, format, pretty)
+ value_ptr val;
+ GDB_FILE *stream;
+ int format;
+ enum val_prettyprint pretty;
+{
+ struct type *type;
+ CORE_ADDR address;
+ int i;
+ char *name;
+
+ type = VALUE_TYPE (val);
+ address = VALUE_ADDRESS (val) + VALUE_OFFSET (val);
+
+ if (is_object_type (type))
+ {
+ CORE_ADDR obj_addr;
+
+ /* Get the run-time type, and cast the object into that */
+
+ obj_addr = unpack_pointer (type, VALUE_CONTENTS (val));
+
+ if (obj_addr != 0)
+ {
+ type = type_from_class (java_class_from_object (val));
+ type = lookup_pointer_type (type);
+
+ val = value_at (type, address, NULL);
+ }
+ }
+
+ if (TYPE_CODE (type) == TYPE_CODE_PTR && ! value_logical_not (val))
+ type_print (TYPE_TARGET_TYPE (type), "", stream, -1);
+
+ name = TYPE_TAG_NAME (type);
+ if (TYPE_CODE (type) == TYPE_CODE_STRUCT && name != NULL
+ && (i = strlen (name), name[i-1] == ']'))
+ {
+ char buf4[4];
+ long length;
+ unsigned int things_printed = 0;
+ int reps;
+ struct type *el_type = java_primitive_type_from_name (name, i - 2);
+
+ i = 0;
+ read_memory (address + JAVA_OBJECT_SIZE, buf4, 4);
+
+ length = (long) extract_signed_integer (buf4, 4);
+ fprintf_filtered (stream, "{length: %ld", length);
+
+ if (el_type == NULL)
+ {
+ CORE_ADDR element, next_element;
+
+ address += JAVA_OBJECT_SIZE + 4; /* Skip object header and length. */
+
+ while (i < length && things_printed < print_max)
+ {
+ char buf[TARGET_PTR_BIT / HOST_CHAR_BIT];
+
+ fputs_filtered (", ", stream);
+ wrap_here (n_spaces (2));
+
+ if (i > 0)
+ element = next_element;
+ else
+ {
+ read_memory (address, buf, sizeof(buf));
+ address += TARGET_PTR_BIT / HOST_CHAR_BIT;
+ element = extract_address (buf, sizeof(buf));
+ }
+
+ for (reps = 1; i + reps < length; reps++)
+ {
+ read_memory (address, buf, sizeof(buf));
+ address += TARGET_PTR_BIT / HOST_CHAR_BIT;
+ next_element = extract_address (buf, sizeof(buf));
+ if (next_element != element)
+ break;
+ }
+
+ if (reps == 1)
+ fprintf_filtered (stream, "%d: ", i);
+ else
+ fprintf_filtered (stream, "%d..%d: ", i, i + reps - 1);
+
+ if (element == 0)
+ fprintf_filtered (stream, "null");
+ else
+ fprintf_filtered (stream, "@%x", element);
+
+ things_printed++;
+ i += reps;
+ }
+ }
+ else
+ {
+ value_ptr v = allocate_value (el_type);
+ value_ptr next_v = allocate_value (el_type);
+
+ VALUE_ADDRESS (v) = address + JAVA_OBJECT_SIZE + 4;
+ VALUE_ADDRESS (next_v) = VALUE_ADDRESS (v);
+
+ while (i < length && things_printed < print_max)
+ {
+ fputs_filtered (", ", stream);
+ wrap_here (n_spaces (2));
+
+ if (i > 0)
+ {
+ value_ptr tmp;
+
+ tmp = next_v;
+ next_v = v;
+ v = tmp;
+ }
+ else
+ {
+ VALUE_LAZY (v) = 1;
+ VALUE_OFFSET (v) = 0;
+ }
+
+ VALUE_OFFSET (next_v) = VALUE_OFFSET (v);
+
+ for (reps = 1; i + reps < length; reps++)
+ {
+ VALUE_LAZY (next_v) = 1;
+ VALUE_OFFSET (next_v) += TYPE_LENGTH (el_type);
+ if (memcmp (VALUE_CONTENTS (v), VALUE_CONTENTS (next_v),
+ TYPE_LENGTH (el_type)) != 0)
+ break;
+ }
+
+ if (reps == 1)
+ fprintf_filtered (stream, "%d: ", i);
+ else
+ fprintf_filtered (stream, "%d..%d: ", i, i + reps - 1);
+
+ val_print (VALUE_TYPE (v), VALUE_CONTENTS (v), 0, 0,
+ stream, format, 2, 1, pretty);
+
+ things_printed++;
+ i += reps;
+ }
+ }
+
+ if (i < length)
+ fprintf_filtered (stream, "...");
+
+ fprintf_filtered (stream, "}");
+
+ return 0;
+ }
+
+ /* If it's type String, print it */
+
+ if (TYPE_CODE (type) == TYPE_CODE_PTR
+ && TYPE_TARGET_TYPE (type)
+ && TYPE_NAME (TYPE_TARGET_TYPE (type))
+ && strcmp (TYPE_NAME (TYPE_TARGET_TYPE (type)), "java.lang.String") == 0
+ && (format == 0 || format == 's')
+ && address != 0)
+ {
+ value_ptr data_val;
+ CORE_ADDR data;
+ value_ptr boffset_val;
+ unsigned long boffset;
+ value_ptr count_val;
+ unsigned long count;
+ value_ptr mark;
+
+ mark = value_mark (); /* Remember start of new values */
+
+ data_val = value_struct_elt (&val, NULL, "data", NULL, NULL);
+ data = value_as_pointer (data_val);
+
+ boffset_val = value_struct_elt (&val, NULL, "boffset", NULL, NULL);
+ boffset = value_as_pointer (boffset_val);
+
+ count_val = value_struct_elt (&val, NULL, "count", NULL, NULL);
+ count = value_as_pointer (count_val);
+
+ value_free_to_mark (mark); /* Release unnecessary values */
+
+ val_print_string (data + boffset, count, 2, stream);
+
+ return 0;
+ }
+
+ return (val_print (type, VALUE_CONTENTS (val), 0, address,
+ stream, format, 1, 0, pretty));
+}
+
+/* TYPE, VALADDR, ADDRESS, STREAM, RECURSE, and PRETTY have the
+ same meanings as in cp_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
+java_print_value_fields (type, valaddr, address, stream,
+ format, recurse, pretty)
+ struct type *type;
+ char *valaddr;
+ CORE_ADDR address;
+ GDB_FILE *stream;
+ int format;
+ int recurse;
+ enum val_prettyprint pretty;
+{
+ int i, len, n_baseclasses;
+
+ CHECK_TYPEDEF (type);
+
+ fprintf_filtered (stream, "{");
+ len = TYPE_NFIELDS (type);
+ n_baseclasses = TYPE_N_BASECLASSES (type);
+
+ if (n_baseclasses > 0)
+ {
+ int i, n_baseclasses = TYPE_N_BASECLASSES (type);
+
+ for (i = 0; i < n_baseclasses; i++)
+ {
+ int boffset;
+ struct type *baseclass = check_typedef (TYPE_BASECLASS (type, i));
+ char *basename = TYPE_NAME (baseclass);
+ char *base_valaddr;
+
+ if (BASETYPE_VIA_VIRTUAL (type, i))
+ continue;
+
+ if (basename != NULL && strcmp (basename, "java.lang.Object") == 0)
+ continue;
+
+ boffset = 0;
+
+ if (pretty)
+ {
+ fprintf_filtered (stream, "\n");
+ print_spaces_filtered (2 * (recurse+1), 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);
+
+ base_valaddr = valaddr;
+
+ java_print_value_fields (baseclass, base_valaddr, address + boffset,
+ stream, format, recurse+1, pretty);
+ fputs_filtered (", ", stream);
+
+ flush_it:
+ ;
+ }
+
+ }
+
+ 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++)
+ {
+ /* If requested, skip printing of static fields. */
+ if (TYPE_FIELD_STATIC (type, i))
+ {
+ char *name = TYPE_FIELD_NAME (type, i);
+ if (!static_field_print)
+ continue;
+ if (name != NULL && strcmp (name, "class") == 0)
+ 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);
+ if (TYPE_FIELD_STATIC (type, i))
+ fputs_filtered ("static ", 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
+ {
+ annotate_field_begin (TYPE_FIELD_TYPE (type, i));
+
+ if (TYPE_FIELD_STATIC (type, i))
+ fputs_filtered ("static ", stream);
+ fprintf_symbol_filtered (stream, TYPE_FIELD_NAME (type, i),
+ language_cplus,
+ DMGL_PARAMS | DMGL_ANSI);
+ annotate_field_name_end ();
+ fputs_filtered (": ", stream);
+ annotate_field_value ();
+ }
+
+ if (!TYPE_FIELD_STATIC (type, i) && TYPE_FIELD_PACKED (type, i))
+ {
+ value_ptr v;
+
+ /* Bitfields require special handling, especially due to byte
+ order problems. */
+ if (TYPE_FIELD_IGNORE (type, i))
+ {
+ fputs_filtered ("<optimized out or zero length>", stream);
+ }
+ else
+ {
+ v = value_from_longest (TYPE_FIELD_TYPE (type, i),
+ unpack_field_as_long (type, valaddr, i));
+
+ val_print (TYPE_FIELD_TYPE(type, i), VALUE_CONTENTS (v), 0,
+ 0, stream, format, 0, recurse + 1, pretty);
+ }
+ }
+ else
+ {
+ if (TYPE_FIELD_IGNORE (type, i))
+ {
+ fputs_filtered ("<optimized out or zero length>", stream);
+ }
+ else if (TYPE_FIELD_STATIC (type, i))
+ {
+ value_ptr v = value_static_field (type, i);
+ if (v == NULL)
+ fputs_filtered ("<optimized out>", stream);
+ else
+ {
+ struct type *t = check_typedef (VALUE_TYPE (v));
+ if (TYPE_CODE (t) == TYPE_CODE_STRUCT)
+ v = value_addr (v);
+ val_print (VALUE_TYPE (v),
+ VALUE_CONTENTS (v), 0, VALUE_ADDRESS (v),
+ stream, format, 0, recurse+1, pretty);
+ }
+ }
+ else
+ {
+ val_print (TYPE_FIELD_TYPE (type, i),
+ valaddr + TYPE_FIELD_BITPOS (type, i) / 8, 0,
+ address + TYPE_FIELD_BITPOS (type, i) / 8,
+ stream, format, 0, recurse + 1, pretty);
+ }
+ }
+ annotate_field_end ();
+ }
+
+ if (pretty)
+ {
+ fprintf_filtered (stream, "\n");
+ print_spaces_filtered (2 * recurse, stream);
+ }
+ }
+ fprintf_filtered (stream, "}");
+}
+
+/* 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
+java_val_print (type, valaddr, embedded_offset, address, stream, format,
+ deref_ref, recurse, pretty)
+ struct type *type;
+ char *valaddr;
+ CORE_ADDR address;
+ GDB_FILE *stream;
+ int format;
+ int deref_ref;
+ int recurse;
+ enum val_prettyprint pretty;
+{
+ register unsigned int i = 0; /* Number of characters printed */
+ struct type *target_type;
+ CORE_ADDR addr;
+
+ CHECK_TYPEDEF (type);
+ switch (TYPE_CODE (type))
+ {
+ case TYPE_CODE_PTR:
+ if (format && format != 's')
+ {
+ print_scalar_formatted (valaddr, type, format, 0, stream);
+ break;
+ }
+#if 0
+ if (vtblprint && cp_is_vtbl_ptr_type(type))
+ {
+ /* Print the unmangled name if desired. */
+ /* Print vtable entry - we only get here if we ARE using
+ -fvtable_thunks. (Otherwise, look under TYPE_CODE_STRUCT.) */
+ print_address_demangle(extract_address (valaddr, TYPE_LENGTH (type)),
+ stream, demangle);
+ break;
+ }
+#endif
+ addr = unpack_pointer (type, valaddr);
+ if (addr == 0)
+ {
+ fputs_filtered ("null", stream);
+ return i;
+ }
+ target_type = check_typedef (TYPE_TARGET_TYPE (type));
+
+ if (TYPE_CODE (target_type) == 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')
+ {
+ fputs_filtered ("@", stream);
+ print_longest (stream, 'x', 0, (ULONGEST) addr);
+ }
+
+ return i;
+
+ case TYPE_CODE_CHAR:
+ format = format ? format : output_format;
+ if (format)
+ print_scalar_formatted (valaddr, type, format, 0, stream);
+ else
+ LA_PRINT_CHAR ((int) unpack_long (type, valaddr), stream);
+ break;
+
+ case TYPE_CODE_INT:
+ /* Can't just call c_val_print because that print bytes as C chars. */
+ 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_STRUCT:
+ java_print_value_fields (type, valaddr, address, stream, format,
+ recurse, pretty);
+ break;
+
+ default:
+ return c_val_print (type, valaddr, embedded_offset, address, stream,
+ format, deref_ref, recurse, pretty);
+ }
+
+ return 0;
+}
diff --git a/gdb/kdb-start.c b/gdb/kdb-start.c
new file mode 100644
index 00000000000..bec558f635d
--- /dev/null
+++ b/gdb/kdb-start.c
@@ -0,0 +1,35 @@
+/* Main loop for the standalone kernel debugger, for GDB, the GNU Debugger.
+ Copyright 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+
+static char *args[] = {"kdb", "kdb-symbols", 0};
+
+static char *environment[] = {0};
+
+char **environ;
+
+start ()
+{
+ INIT_STACK (kdb_stack_beg, kdb_stack_end);
+
+ environ = environment;
+
+ main (2, args, environment);
+}
diff --git a/gdb/language.c b/gdb/language.c
new file mode 100644
index 00000000000..225d423ec01
--- /dev/null
+++ b/gdb/language.c
@@ -0,0 +1,1451 @@
+/* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 <ctype.h>
+#include "gdb_string.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));
+
+static void
+unk_lang_emit_char PARAMS ((int c, GDB_FILE *stream, int quoter));
+
+static void
+unk_lang_printchar PARAMS ((int c, GDB_FILE *stream));
+
+static void
+unk_lang_printstr PARAMS ((GDB_FILE *stream, char *string, unsigned int length, int width, int force_ellipses));
+
+static struct type *
+unk_lang_create_fundamental_type PARAMS ((struct objfile *, int));
+
+static void
+unk_lang_print_type PARAMS ((struct type *, char *, GDB_FILE *, int, int));
+
+static int
+unk_lang_val_print PARAMS ((struct type *, char *, int, CORE_ADDR, GDB_FILE *,
+ int, int, int, enum val_prettyprint));
+
+static int
+unk_lang_value_print PARAMS ((value_ptr, GDB_FILE *, int, enum val_prettyprint));
+
+/* 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;
+
+ if (!language || !language[0])
+ {
+ printf_unfiltered("The currently understood settings are:\n\n");
+ printf_unfiltered ("local or auto Automatic setting based on source file\n");
+
+ for (i = 0; i < languages_size; ++i)
+ {
+ /* Already dealt with these above. */
+ if (languages[i]->la_language == language_unknown
+ || languages[i]->la_language == language_auto)
+ continue;
+
+ /* FIXME for now assume that the human-readable name is just
+ a capitalization of the internal name. */
+ printf_unfiltered ("%-16s Use the %c%s language\n",
+ languages[i]->la_name,
+ /* Capitalize first letter of language
+ name. */
+ toupper (languages[i]->la_name[0]),
+ languages[i]->la_name + 1);
+ }
+ /* 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_unfiltered(
+"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_unfiltered(
+"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. Returns previous language. */
+
+enum language
+set_language(lang)
+ enum language lang;
+{
+ int i;
+ enum language prev_language;
+
+ prev_language = current_language->la_language;
+
+ for (i = 0; i < languages_size; i++) {
+ if (languages[i]->la_language == lang) {
+ current_language = languages[i];
+ set_type_range ();
+ set_lang_str();
+ break;
+ }
+ }
+
+ return prev_language;
+}
+
+/* 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_unfiltered("Current language: %s\n",language);
+ show_language_command((char *)0, 1);
+
+ if (!quietly)
+ {
+ printf_unfiltered("Type checking: %s\n",type);
+ show_type_command((char *)0, 1);
+ printf_unfiltered("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_ptr v1, v2;
+{
+ int size,uns;
+ struct type *t1 = check_typedef (VALUE_TYPE (v1));
+ struct type *t2 = check_typedef (VALUE_TYPE (v2));
+
+ int l1 = TYPE_LENGTH (t1);
+ int l2 = TYPE_LENGTH (t2);
+
+ switch(current_language->la_language)
+ {
+ case language_c:
+ case language_cplus:
+ if (TYPE_CODE (t1)==TYPE_CODE_FLT)
+ return TYPE_CODE(t2) == TYPE_CODE_FLT && l2 > l1 ?
+ VALUE_TYPE(v2) : VALUE_TYPE(v1);
+ else if (TYPE_CODE(t2)==TYPE_CODE_FLT)
+ return TYPE_CODE(t1)) == TYPE_CODE_FLT && l1 > l2 ?
+ VALUE_TYPE(v1) : VALUE_TYPE(v2);
+ else if (TYPE_UNSIGNED(t1) && l1 > l2)
+ return VALUE_TYPE(v1);
+ else if (TYPE_UNSIGNED(t2) && 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;
+}
+
+#if 0
+/* 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;
+{
+ CHECK_TYPEDEF (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;
+{
+ CHECK_TYPEDEF (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;
+{
+ CHECK_TYPEDEF (type);
+ 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;
+{
+ CHECK_TYPEDEF (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;
+{
+ CHECK_TYPEDEF (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;
+{
+ CHECK_TYPEDEF (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;
+{
+ CHECK_TYPEDEF (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;
+{
+ CHECK_TYPEDEF (type);
+ if (TYPE_CODE (type) == TYPE_CODE_BOOL)
+ return 1;
+ switch(current_language->la_language)
+ {
+ case language_c:
+ case language_cplus:
+ /* Might be more cleanly handled by having a TYPE_CODE_INT_NOT_BOOL
+ for CHILL and such languages, or a TYPE_CODE_INT_OR_BOOL for C. */
+ if (TYPE_CODE (type) == TYPE_CODE_INT)
+ return 1;
+ default:
+ break;
+ }
+ return 0;
+}
+
+/* Returns non-zero if the value is a floating-point type */
+int
+float_type (type)
+ struct type *type;
+{
+ CHECK_TYPEDEF (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;
+{
+ CHECK_TYPEDEF (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);
+ }
+}
+#endif
+
+struct type *
+lang_bool_type ()
+{
+ struct symbol *sym;
+ struct type *type;
+ switch(current_language->la_language)
+ {
+ case language_chill:
+ return builtin_type_chill_bool;
+ case language_fortran:
+ sym = lookup_symbol ("logical", NULL, VAR_NAMESPACE, NULL, NULL);
+ if (sym)
+ {
+ type = SYMBOL_TYPE (sym);
+ if (type && TYPE_CODE (type) == TYPE_CODE_BOOL)
+ return type;
+ }
+ return builtin_type_f_logical_s2;
+ case language_cplus:
+ sym = lookup_symbol ("bool", NULL, VAR_NAMESPACE, NULL, NULL);
+ if (sym)
+ {
+ type = SYMBOL_TYPE (sym);
+ if (type && TYPE_CODE (type) == TYPE_CODE_BOOL)
+ return type;
+ }
+ return builtin_type_bool;
+ default:
+ return builtin_type_int;
+ }
+}
+
+/* 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_ptr val;
+{
+ /* It is possible that we should have some sort of error if a non-boolean
+ value is used in this context. Possibly dependent on some kind of
+ "boolean-checking" option like range checking. But it should probably
+ not depend on the language except insofar as is necessary to identify
+ a "boolean" value (i.e. in C using a float, pointer, etc., as a boolean
+ should be an error, probably). */
+ return !value_logical_not (val);
+}
+
+/* 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_ptr 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 != 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
+#ifdef ANSI_PROTOTYPES
+type_error (char *string, ...)
+#else
+type_error (va_alist)
+ va_dcl
+#endif
+{
+ va_list args;
+#ifdef ANSI_PROTOTYPES
+ va_start (args, string);
+#else
+ char *string;
+ va_start (args);
+ string = va_arg (args, char *);
+#endif
+
+ if (type_check == type_check_warn)
+ fprintf_filtered (gdb_stderr, warning_pre_print);
+ else
+ error_begin ();
+
+ vfprintf_filtered (gdb_stderr, string, args);
+ fprintf_filtered (gdb_stderr, "\n");
+ va_end (args);
+ if (type_check == type_check_on)
+ return_to_top_level (RETURN_ERROR);
+}
+
+void
+#ifdef ANSI_PROTOTYPES
+range_error (char *string, ...)
+#else
+range_error (va_alist)
+ va_dcl
+#endif
+{
+ va_list args;
+#ifdef ANSI_PROTOTYPES
+ va_start (args, string);
+#else
+ char *string;
+ va_start (args);
+ string = va_arg (args, char *);
+#endif
+
+ if (range_check == range_check_warn)
+ fprintf_filtered (gdb_stderr, warning_pre_print);
+ else
+ error_begin ();
+
+ vfprintf_filtered (gdb_stderr, string, args);
+ fprintf_filtered (gdb_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 enum for a given language string. */
+
+enum language
+language_enum (str)
+ char *str;
+{
+ int i;
+
+ for (i = 0; i < languages_size; i++)
+ if (STREQ (languages[i]->la_name, str))
+ return languages[i]->la_language;
+
+ return language_unknown;
+}
+
+/* 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_unfiltered(
+"\"set check\" must be followed by the name of a check subcommand.\n");
+ help_list(setchecklist, "set check ", -1, gdb_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_unfiltered(gdb_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_emit_char (c, stream, quoter)
+ register int c;
+ GDB_FILE *stream;
+ int quoter;
+{
+ error ("internal error - unimplemented function unk_lang_emit_char called.");
+}
+
+static void
+unk_lang_printchar (c, stream)
+ register int c;
+ GDB_FILE *stream;
+{
+ error ("internal error - unimplemented function unk_lang_printchar called.");
+}
+
+static void
+unk_lang_printstr (stream, string, length, width, force_ellipses)
+ GDB_FILE *stream;
+ char *string;
+ unsigned int length;
+ int width;
+ 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.");
+}
+
+static void
+unk_lang_print_type (type, varstring, stream, show, level)
+ struct type *type;
+ char *varstring;
+ GDB_FILE *stream;
+ int show;
+ int level;
+{
+ error ("internal error - unimplemented function unk_lang_print_type called.");
+}
+
+static int
+unk_lang_val_print (type, valaddr, embedded_offset, address, stream, format, deref_ref,
+ recurse, pretty)
+ struct type *type;
+ char *valaddr;
+ int embedded_offset;
+ CORE_ADDR address;
+ GDB_FILE *stream;
+ int format;
+ int deref_ref;
+ int recurse;
+ enum val_prettyprint pretty;
+{
+ error ("internal error - unimplemented function unk_lang_val_print called.");
+}
+
+static int
+unk_lang_value_print (val, stream, format, pretty)
+ value_ptr val;
+ GDB_FILE *stream;
+ int format;
+ enum val_prettyprint pretty;
+{
+ error ("internal error - unimplemented function unk_lang_value_print called.");
+}
+
+static struct type ** CONST_PTR (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,
+ evaluate_subexp_standard,
+ unk_lang_printchar, /* Print character constant */
+ unk_lang_printstr,
+ unk_lang_emit_char,
+ 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 */
+ unk_lang_value_print, /* Print a top-level value */
+ {"", "", "", ""}, /* 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 */
+ 1, /* c-style arrays */
+ 0, /* String lower bound */
+ &builtin_type_char, /* Type of string elements */
+ 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,
+ evaluate_subexp_standard,
+ unk_lang_printchar, /* Print character constant */
+ unk_lang_printstr,
+ unk_lang_emit_char,
+ 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 */
+ unk_lang_value_print, /* Print a top-level value */
+ {"", "", "", ""}, /* 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 */
+ 1, /* c-style arrays */
+ 0, /* String lower bound */
+ &builtin_type_char, /* Type of string elements */
+ 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,
+ evaluate_subexp_standard,
+ unk_lang_printchar, /* Print character constant */
+ unk_lang_printstr,
+ unk_lang_emit_char,
+ 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 */
+ unk_lang_value_print, /* Print a top-level value */
+ {"", "", "", ""}, /* 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 */
+ 1, /* c-style arrays */
+ 0, /* String lower bound */
+ &builtin_type_char, /* Type of string elements */
+ 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/gdb/language.h b/gdb/language.h
new file mode 100644
index 00000000000..e3368691491
--- /dev/null
+++ b/gdb/language.h
@@ -0,0 +1,439 @@
+/* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#if !defined (LANGUAGE_H)
+#define LANGUAGE_H 1
+
+#ifdef __STDC__ /* Forward decls for prototypes */
+struct value;
+struct objfile;
+struct expression;
+/* 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
+#define _LANG_fortran
+
+#define MAX_FORTRAN_DIMS 7 /* Maximum number of F77 array dims */
+
+/* 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. This is a vector ended by a NULL pointer. These
+ types can be specified by name in parsing types in expressions,
+ regardless of whether the program being debugged actually defines
+ such a type. */
+
+ 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 *));
+
+ /* Evaluate an expression. */
+ struct value * (*evaluate_exp) PARAMS ((struct type *, struct expression *,
+ int *, enum noside));
+
+ void (*la_printchar) PARAMS ((int ch, GDB_FILE *stream));
+
+ void (*la_printstr) PARAMS ((GDB_FILE *stream, char *string,
+ unsigned int length, int width,
+ int force_ellipses));
+
+ void (*la_emitchar) PARAMS ((int ch, GDB_FILE *stream, int quoter));
+
+ 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 *, GDB_FILE *, int, int));
+
+ /* Print a value using syntax appropriate for this language. */
+
+ int (*la_val_print) PARAMS ((struct type *, char *, int, CORE_ADDR, GDB_FILE *,
+ int, int, int, enum val_prettyprint));
+
+ /* Print a top-level value using syntax appropriate for this language. */
+
+ int (*la_value_print) PARAMS ((struct value *, GDB_FILE *,
+ int, enum val_prettyprint));
+
+ /* 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;
+
+ /* Zero if the language has first-class arrays. True if there are no
+ array values, and array objects decay to pointers, as in C. */
+
+ char c_style_arrays;
+
+ /* Index to use for extracting the first element of a string. */
+ char string_lower_bound;
+
+ /* Type of elements of strings. */
+ struct type **string_char_type;
+
+ /* 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 enum language
+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. */
+
+#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,offset,addr,stream,fmt,deref,recurse,pretty) \
+ (current_language->la_val_print(type,valaddr,offset,addr,stream,fmt,deref, \
+ recurse,pretty))
+#define LA_VALUE_PRINT(val,stream,fmt,pretty) \
+ (current_language->la_value_print(val,stream,fmt,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, width, force_ellipses) \
+ (current_language->la_printstr(stream, string, length, width, force_ellipses))
+#define LA_EMIT_CHAR(ch, stream, quoter) \
+ (current_language->la_emitchar(ch, stream, quoter))
+
+/* 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 PARAMS ((char *, ...))
+ ATTR_FORMAT(printf, 1, 2);
+
+void
+range_error PARAMS ((char *, ...))
+ ATTR_FORMAT(printf, 1, 2);
+
+/* Data: Does this value represent "truth" to the current language? */
+
+extern int
+value_true PARAMS ((struct value *));
+
+extern struct type * lang_bool_type PARAMS ((void));
+
+/* The type used for Boolean values in the current language. */
+#define LA_BOOL_TYPE lang_bool_type ()
+
+/* 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/gdb/lynx-nat.c b/gdb/lynx-nat.c
new file mode 100644
index 00000000000..f006aa46c9c
--- /dev/null
+++ b/gdb/lynx-nat.c
@@ -0,0 +1,837 @@
+/* Native-dependent code for LynxOS.
+ Copyright 1993, 1994 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "frame.h"
+#include "inferior.h"
+#include "target.h"
+#include "gdbcore.h"
+
+#include <sys/ptrace.h>
+#include <sys/wait.h>
+#include <sys/fpp.h>
+
+static unsigned long registers_addr PARAMS ((int pid));
+static void fetch_core_registers PARAMS ((char *, unsigned, int, CORE_ADDR);
+
+#define X(ENTRY)(offsetof(struct econtext, ENTRY))
+
+#ifdef I386
+/* Mappings from tm-i386v.h */
+
+static int regmap[] =
+{
+ X(eax),
+ X(ecx),
+ X(edx),
+ X(ebx),
+ X(esp), /* sp */
+ X(ebp), /* fp */
+ X(esi),
+ X(edi),
+ X(eip), /* pc */
+ X(flags), /* ps */
+ X(cs),
+ X(ss),
+ X(ds),
+ X(es),
+ X(ecode), /* Lynx doesn't give us either fs or gs, so */
+ X(fault), /* we just substitute these two in the hopes
+ that they are useful. */
+};
+#endif /* I386 */
+
+#ifdef M68K
+/* Mappings from tm-m68k.h */
+
+static int regmap[] =
+{
+ X(regs[0]), /* d0 */
+ X(regs[1]), /* d1 */
+ X(regs[2]), /* d2 */
+ X(regs[3]), /* d3 */
+ X(regs[4]), /* d4 */
+ X(regs[5]), /* d5 */
+ X(regs[6]), /* d6 */
+ X(regs[7]), /* d7 */
+ X(regs[8]), /* a0 */
+ X(regs[9]), /* a1 */
+ X(regs[10]), /* a2 */
+ X(regs[11]), /* a3 */
+ X(regs[12]), /* a4 */
+ X(regs[13]), /* a5 */
+ X(regs[14]), /* fp */
+ offsetof (st_t, usp) - offsetof (st_t, ec), /* sp */
+ X(status), /* ps */
+ X(pc),
+
+ X(fregs[0*3]), /* fp0 */
+ X(fregs[1*3]), /* fp1 */
+ X(fregs[2*3]), /* fp2 */
+ X(fregs[3*3]), /* fp3 */
+ X(fregs[4*3]), /* fp4 */
+ X(fregs[5*3]), /* fp5 */
+ X(fregs[6*3]), /* fp6 */
+ X(fregs[7*3]), /* fp7 */
+
+ X(fcregs[0]), /* fpcontrol */
+ X(fcregs[1]), /* fpstatus */
+ X(fcregs[2]), /* fpiaddr */
+ X(ssw), /* fpcode */
+ X(fault), /* fpflags */
+};
+#endif /* M68K */
+
+#ifdef SPARC
+/* Mappings from tm-sparc.h */
+
+#define FX(ENTRY)(offsetof(struct fcontext, ENTRY))
+
+static int regmap[] =
+{
+ -1, /* g0 */
+ X(g1),
+ X(g2),
+ X(g3),
+ X(g4),
+ -1, /* g5->g7 aren't saved by Lynx */
+ -1,
+ -1,
+
+ X(o[0]),
+ X(o[1]),
+ X(o[2]),
+ X(o[3]),
+ X(o[4]),
+ X(o[5]),
+ X(o[6]), /* sp */
+ X(o[7]), /* ra */
+
+ -1,-1,-1,-1,-1,-1,-1,-1, /* l0 -> l7 */
+
+ -1,-1,-1,-1,-1,-1,-1,-1, /* i0 -> i7 */
+
+ FX(f.fregs[0]), /* f0 */
+ FX(f.fregs[1]),
+ FX(f.fregs[2]),
+ FX(f.fregs[3]),
+ FX(f.fregs[4]),
+ FX(f.fregs[5]),
+ FX(f.fregs[6]),
+ FX(f.fregs[7]),
+ FX(f.fregs[8]),
+ FX(f.fregs[9]),
+ FX(f.fregs[10]),
+ FX(f.fregs[11]),
+ FX(f.fregs[12]),
+ FX(f.fregs[13]),
+ FX(f.fregs[14]),
+ FX(f.fregs[15]),
+ FX(f.fregs[16]),
+ FX(f.fregs[17]),
+ FX(f.fregs[18]),
+ FX(f.fregs[19]),
+ FX(f.fregs[20]),
+ FX(f.fregs[21]),
+ FX(f.fregs[22]),
+ FX(f.fregs[23]),
+ FX(f.fregs[24]),
+ FX(f.fregs[25]),
+ FX(f.fregs[26]),
+ FX(f.fregs[27]),
+ FX(f.fregs[28]),
+ FX(f.fregs[29]),
+ FX(f.fregs[30]),
+ FX(f.fregs[31]),
+
+ X(y),
+ X(psr),
+ X(wim),
+ X(tbr),
+ X(pc),
+ X(npc),
+ FX(fsr), /* fpsr */
+ -1, /* cpsr */
+};
+#endif /* SPARC */
+
+#ifdef rs6000
+
+static int regmap[] =
+{
+ X(iregs[0]), /* r0 */
+ X(iregs[1]),
+ X(iregs[2]),
+ X(iregs[3]),
+ X(iregs[4]),
+ X(iregs[5]),
+ X(iregs[6]),
+ X(iregs[7]),
+ X(iregs[8]),
+ X(iregs[9]),
+ X(iregs[10]),
+ X(iregs[11]),
+ X(iregs[12]),
+ X(iregs[13]),
+ X(iregs[14]),
+ X(iregs[15]),
+ X(iregs[16]),
+ X(iregs[17]),
+ X(iregs[18]),
+ X(iregs[19]),
+ X(iregs[20]),
+ X(iregs[21]),
+ X(iregs[22]),
+ X(iregs[23]),
+ X(iregs[24]),
+ X(iregs[25]),
+ X(iregs[26]),
+ X(iregs[27]),
+ X(iregs[28]),
+ X(iregs[29]),
+ X(iregs[30]),
+ X(iregs[31]),
+
+ X(fregs[0]), /* f0 */
+ X(fregs[1]),
+ X(fregs[2]),
+ X(fregs[3]),
+ X(fregs[4]),
+ X(fregs[5]),
+ X(fregs[6]),
+ X(fregs[7]),
+ X(fregs[8]),
+ X(fregs[9]),
+ X(fregs[10]),
+ X(fregs[11]),
+ X(fregs[12]),
+ X(fregs[13]),
+ X(fregs[14]),
+ X(fregs[15]),
+ X(fregs[16]),
+ X(fregs[17]),
+ X(fregs[18]),
+ X(fregs[19]),
+ X(fregs[20]),
+ X(fregs[21]),
+ X(fregs[22]),
+ X(fregs[23]),
+ X(fregs[24]),
+ X(fregs[25]),
+ X(fregs[26]),
+ X(fregs[27]),
+ X(fregs[28]),
+ X(fregs[29]),
+ X(fregs[30]),
+ X(fregs[31]),
+
+ X(srr0), /* IAR (PC) */
+ X(srr1), /* MSR (PS) */
+ X(cr), /* CR */
+ X(lr), /* LR */
+ X(ctr), /* CTR */
+ X(xer), /* XER */
+ X(mq) /* MQ */
+};
+
+#endif /* rs6000 */
+
+#ifdef SPARC
+
+/* This routine handles some oddball cases for Sparc registers and LynxOS.
+ In partucular, it causes refs to G0, g5->7, and all fp regs to return zero.
+ It also handles knows where to find the I & L regs on the stack. */
+
+void
+fetch_inferior_registers (regno)
+ int regno;
+{
+ int whatregs = 0;
+
+#define WHATREGS_FLOAT 1
+#define WHATREGS_GEN 2
+#define WHATREGS_STACK 4
+
+ if (regno == -1)
+ whatregs = WHATREGS_FLOAT | WHATREGS_GEN | WHATREGS_STACK;
+ else if (regno >= L0_REGNUM && regno <= I7_REGNUM)
+ whatregs = WHATREGS_STACK;
+ else if (regno >= FP0_REGNUM && regno < FP0_REGNUM + 32)
+ whatregs = WHATREGS_FLOAT;
+ else
+ whatregs = WHATREGS_GEN;
+
+ if (whatregs & WHATREGS_GEN)
+ {
+ struct econtext ec; /* general regs */
+ char buf[MAX_REGISTER_RAW_SIZE];
+ int retval;
+ int i;
+
+ errno = 0;
+ retval = ptrace (PTRACE_GETREGS, inferior_pid, (PTRACE_ARG3_TYPE) &ec,
+ 0);
+ if (errno)
+ perror_with_name ("ptrace(PTRACE_GETREGS)");
+
+ memset (buf, 0, REGISTER_RAW_SIZE (G0_REGNUM));
+ supply_register (G0_REGNUM, buf);
+ supply_register (TBR_REGNUM, (char *)&ec.tbr);
+
+ memcpy (&registers[REGISTER_BYTE (G1_REGNUM)], &ec.g1,
+ 4 * REGISTER_RAW_SIZE (G1_REGNUM));
+ for (i = G1_REGNUM; i <= G1_REGNUM + 3; i++)
+ register_valid[i] = 1;
+
+ supply_register (PS_REGNUM, (char *)&ec.psr);
+ supply_register (Y_REGNUM, (char *)&ec.y);
+ supply_register (PC_REGNUM, (char *)&ec.pc);
+ supply_register (NPC_REGNUM, (char *)&ec.npc);
+ supply_register (WIM_REGNUM, (char *)&ec.wim);
+
+ memcpy (&registers[REGISTER_BYTE (O0_REGNUM)], ec.o,
+ 8 * REGISTER_RAW_SIZE (O0_REGNUM));
+ for (i = O0_REGNUM; i <= O0_REGNUM + 7; i++)
+ register_valid[i] = 1;
+ }
+
+ if (whatregs & WHATREGS_STACK)
+ {
+ CORE_ADDR sp;
+ int i;
+
+ sp = read_register (SP_REGNUM);
+
+ target_xfer_memory (sp + FRAME_SAVED_I0,
+ &registers[REGISTER_BYTE(I0_REGNUM)],
+ 8 * REGISTER_RAW_SIZE (I0_REGNUM), 0);
+ for (i = I0_REGNUM; i <= I7_REGNUM; i++)
+ register_valid[i] = 1;
+
+ target_xfer_memory (sp + FRAME_SAVED_L0,
+ &registers[REGISTER_BYTE(L0_REGNUM)],
+ 8 * REGISTER_RAW_SIZE (L0_REGNUM), 0);
+ for (i = L0_REGNUM; i <= L0_REGNUM + 7; i++)
+ register_valid[i] = 1;
+ }
+
+ if (whatregs & WHATREGS_FLOAT)
+ {
+ struct fcontext fc; /* fp regs */
+ int retval;
+ int i;
+
+ errno = 0;
+ retval = ptrace (PTRACE_GETFPREGS, inferior_pid, (PTRACE_ARG3_TYPE) &fc,
+ 0);
+ if (errno)
+ perror_with_name ("ptrace(PTRACE_GETFPREGS)");
+
+ memcpy (&registers[REGISTER_BYTE (FP0_REGNUM)], fc.f.fregs,
+ 32 * REGISTER_RAW_SIZE (FP0_REGNUM));
+ for (i = FP0_REGNUM; i <= FP0_REGNUM + 31; i++)
+ register_valid[i] = 1;
+
+ supply_register (FPS_REGNUM, (char *)&fc.fsr);
+ }
+}
+
+/* This routine handles storing of the I & L regs for the Sparc. The trick
+ here is that they actually live on the stack. The really tricky part is
+ that when changing the stack pointer, the I & L regs must be written to
+ where the new SP points, otherwise the regs will be incorrect when the
+ process is started up again. We assume that the I & L regs are valid at
+ this point. */
+
+void
+store_inferior_registers (regno)
+ int regno;
+{
+ int whatregs = 0;
+
+ if (regno == -1)
+ whatregs = WHATREGS_FLOAT | WHATREGS_GEN | WHATREGS_STACK;
+ else if (regno >= L0_REGNUM && regno <= I7_REGNUM)
+ whatregs = WHATREGS_STACK;
+ else if (regno >= FP0_REGNUM && regno < FP0_REGNUM + 32)
+ whatregs = WHATREGS_FLOAT;
+ else if (regno == SP_REGNUM)
+ whatregs = WHATREGS_STACK | WHATREGS_GEN;
+ else
+ whatregs = WHATREGS_GEN;
+
+ if (whatregs & WHATREGS_GEN)
+ {
+ struct econtext ec; /* general regs */
+ int retval;
+
+ ec.tbr = read_register (TBR_REGNUM);
+ memcpy (&ec.g1, &registers[REGISTER_BYTE (G1_REGNUM)],
+ 4 * REGISTER_RAW_SIZE (G1_REGNUM));
+
+ ec.psr = read_register (PS_REGNUM);
+ ec.y = read_register (Y_REGNUM);
+ ec.pc = read_register (PC_REGNUM);
+ ec.npc = read_register (NPC_REGNUM);
+ ec.wim = read_register (WIM_REGNUM);
+
+ memcpy (ec.o, &registers[REGISTER_BYTE (O0_REGNUM)],
+ 8 * REGISTER_RAW_SIZE (O0_REGNUM));
+
+ errno = 0;
+ retval = ptrace (PTRACE_SETREGS, inferior_pid, (PTRACE_ARG3_TYPE) &ec,
+ 0);
+ if (errno)
+ perror_with_name ("ptrace(PTRACE_SETREGS)");
+ }
+
+ if (whatregs & WHATREGS_STACK)
+ {
+ int regoffset;
+ CORE_ADDR sp;
+
+ sp = read_register (SP_REGNUM);
+
+ if (regno == -1 || regno == SP_REGNUM)
+ {
+ if (!register_valid[L0_REGNUM+5])
+ abort();
+ target_xfer_memory (sp + FRAME_SAVED_I0,
+ &registers[REGISTER_BYTE (I0_REGNUM)],
+ 8 * REGISTER_RAW_SIZE (I0_REGNUM), 1);
+
+ target_xfer_memory (sp + FRAME_SAVED_L0,
+ &registers[REGISTER_BYTE (L0_REGNUM)],
+ 8 * REGISTER_RAW_SIZE (L0_REGNUM), 1);
+ }
+ else if (regno >= L0_REGNUM && regno <= I7_REGNUM)
+ {
+ if (!register_valid[regno])
+ abort();
+ if (regno >= L0_REGNUM && regno <= L0_REGNUM + 7)
+ regoffset = REGISTER_BYTE (regno) - REGISTER_BYTE (L0_REGNUM)
+ + FRAME_SAVED_L0;
+ else
+ regoffset = REGISTER_BYTE (regno) - REGISTER_BYTE (I0_REGNUM)
+ + FRAME_SAVED_I0;
+ target_xfer_memory (sp + regoffset, &registers[REGISTER_BYTE (regno)],
+ REGISTER_RAW_SIZE (regno), 1);
+ }
+ }
+
+ if (whatregs & WHATREGS_FLOAT)
+ {
+ struct fcontext fc; /* fp regs */
+ int retval;
+
+/* We read fcontext first so that we can get good values for fq_t... */
+ errno = 0;
+ retval = ptrace (PTRACE_GETFPREGS, inferior_pid, (PTRACE_ARG3_TYPE) &fc,
+ 0);
+ if (errno)
+ perror_with_name ("ptrace(PTRACE_GETFPREGS)");
+
+ memcpy (fc.f.fregs, &registers[REGISTER_BYTE (FP0_REGNUM)],
+ 32 * REGISTER_RAW_SIZE (FP0_REGNUM));
+
+ fc.fsr = read_register (FPS_REGNUM);
+
+ errno = 0;
+ retval = ptrace (PTRACE_SETFPREGS, inferior_pid, (PTRACE_ARG3_TYPE) &fc,
+ 0);
+ if (errno)
+ perror_with_name ("ptrace(PTRACE_SETFPREGS)");
+ }
+}
+#endif /* SPARC */
+
+#if defined (I386) || defined (M68K) || defined (rs6000)
+
+/* Return the offset relative to the start of the per-thread data to the
+ saved context block. */
+
+static unsigned long
+registers_addr(pid)
+ int pid;
+{
+ CORE_ADDR stblock;
+ int ecpoff = offsetof(st_t, ecp);
+ CORE_ADDR ecp;
+
+ errno = 0;
+ stblock = (CORE_ADDR) ptrace (PTRACE_THREADUSER, pid, (PTRACE_ARG3_TYPE)0,
+ 0);
+ if (errno)
+ perror_with_name ("ptrace(PTRACE_THREADUSER)");
+
+ ecp = (CORE_ADDR) ptrace (PTRACE_PEEKTHREAD, pid, (PTRACE_ARG3_TYPE)ecpoff,
+ 0);
+ if (errno)
+ perror_with_name ("ptrace(PTRACE_PEEKTHREAD)");
+
+ return ecp - stblock;
+}
+
+/* Fetch one or more registers from the inferior. REGNO == -1 to get
+ them all. We actually fetch more than requested, when convenient,
+ marking them as valid so we won't fetch them again. */
+
+void
+fetch_inferior_registers (regno)
+ int regno;
+{
+ int reglo, reghi;
+ int i;
+ unsigned long ecp;
+
+ if (regno == -1)
+ {
+ reglo = 0;
+ reghi = NUM_REGS - 1;
+ }
+ else
+ reglo = reghi = regno;
+
+ ecp = registers_addr (inferior_pid);
+
+ for (regno = reglo; regno <= reghi; regno++)
+ {
+ char buf[MAX_REGISTER_RAW_SIZE];
+ int ptrace_fun = PTRACE_PEEKTHREAD;
+
+#ifdef M68K
+ ptrace_fun = regno == SP_REGNUM ? PTRACE_PEEKUSP : PTRACE_PEEKTHREAD;
+#endif
+
+ for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (int))
+ {
+ unsigned int reg;
+
+ errno = 0;
+ reg = ptrace (ptrace_fun, inferior_pid,
+ (PTRACE_ARG3_TYPE) (ecp + regmap[regno] + i), 0);
+ if (errno)
+ perror_with_name ("ptrace(PTRACE_PEEKUSP)");
+
+ *(int *)&buf[i] = reg;
+ }
+ 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). */
+
+/* Registers we shouldn't try to store. */
+#if !defined (CANNOT_STORE_REGISTER)
+#define CANNOT_STORE_REGISTER(regno) 0
+#endif
+
+void
+store_inferior_registers (regno)
+ int regno;
+{
+ int reglo, reghi;
+ int i;
+ unsigned long ecp;
+
+ if (regno == -1)
+ {
+ reglo = 0;
+ reghi = NUM_REGS - 1;
+ }
+ else
+ reglo = reghi = regno;
+
+ ecp = registers_addr (inferior_pid);
+
+ for (regno = reglo; regno <= reghi; regno++)
+ {
+ int ptrace_fun = PTRACE_POKEUSER;
+
+ if (CANNOT_STORE_REGISTER (regno))
+ continue;
+
+#ifdef M68K
+ ptrace_fun = regno == SP_REGNUM ? PTRACE_POKEUSP : PTRACE_POKEUSER;
+#endif
+
+ for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (int))
+ {
+ unsigned int reg;
+
+ reg = *(unsigned int *)&registers[REGISTER_BYTE (regno) + i];
+
+ errno = 0;
+ ptrace (ptrace_fun, inferior_pid,
+ (PTRACE_ARG3_TYPE) (ecp + regmap[regno] + i), reg);
+ if (errno)
+ perror_with_name ("ptrace(PTRACE_POKEUSP)");
+ }
+ }
+}
+#endif /* defined (I386) || defined (M68K) || defined (rs6000) */
+
+/* Wait for child to do something. Return pid of child, or -1 in case
+ of error; store status through argument pointer OURSTATUS. */
+
+int
+child_wait (pid, ourstatus)
+ int pid;
+ struct target_waitstatus *ourstatus;
+{
+ int save_errno;
+ int thread;
+ union wait status;
+
+ while (1)
+ {
+ int sig;
+
+ set_sigint_trap(); /* Causes SIGINT to be passed on to the
+ attached process. */
+ pid = wait (&status);
+
+ save_errno = errno;
+
+ clear_sigint_trap();
+
+ if (pid == -1)
+ {
+ if (save_errno == EINTR)
+ continue;
+ fprintf_unfiltered (gdb_stderr, "Child process unexpectedly missing: %s.\n",
+ safe_strerror (save_errno));
+ /* Claim it exited with unknown signal. */
+ ourstatus->kind = TARGET_WAITKIND_SIGNALLED;
+ ourstatus->value.sig = TARGET_SIGNAL_UNKNOWN;
+ return -1;
+ }
+
+ if (pid != PIDGET (inferior_pid)) /* Some other process?!? */
+ continue;
+
+ thread = status.w_tid; /* Get thread id from status */
+
+ /* Initial thread value can only be acquired via wait, so we have to
+ resort to this hack. */
+
+ if (TIDGET (inferior_pid) == 0 && thread != 0)
+ {
+ inferior_pid = BUILDPID (inferior_pid, thread);
+ add_thread (inferior_pid);
+ }
+
+ pid = BUILDPID (pid, thread);
+
+ /* We've become a single threaded process again. */
+ if (thread == 0)
+ inferior_pid = pid;
+
+ /* Check for thread creation. */
+ if (WIFSTOPPED(status)
+ && WSTOPSIG(status) == SIGTRAP
+ && !in_thread_list (pid))
+ {
+ int realsig;
+
+ realsig = ptrace (PTRACE_GETTRACESIG, pid, (PTRACE_ARG3_TYPE)0, 0);
+
+ if (realsig == SIGNEWTHREAD)
+ {
+ /* It's a new thread notification. We don't want to much with
+ realsig -- the code in wait_for_inferior expects SIGTRAP. */
+ ourstatus->kind = TARGET_WAITKIND_SPURIOUS;
+ ourstatus->value.sig = TARGET_SIGNAL_0;
+ return pid;
+ }
+ else
+ error ("Signal for unknown thread was not SIGNEWTHREAD");
+ }
+
+ /* Check for thread termination. */
+ else if (WIFSTOPPED(status)
+ && WSTOPSIG(status) == SIGTRAP
+ && in_thread_list (pid))
+ {
+ int realsig;
+
+ realsig = ptrace (PTRACE_GETTRACESIG, pid, (PTRACE_ARG3_TYPE)0, 0);
+
+ if (realsig == SIGTHREADEXIT)
+ {
+ ptrace (PTRACE_CONT, PIDGET (pid), (PTRACE_ARG3_TYPE)0, 0);
+ continue;
+ }
+ }
+
+#ifdef SPARC
+ /* SPARC Lynx uses an byte reversed wait status; we must use the
+ host macros to access it. These lines just a copy of
+ store_waitstatus. We can't use CHILD_SPECIAL_WAITSTATUS
+ because target.c can't include the Lynx <sys/wait.h>. */
+ if (WIFEXITED (status))
+ {
+ ourstatus->kind = TARGET_WAITKIND_EXITED;
+ ourstatus->value.integer = WEXITSTATUS (status);
+ }
+ else if (!WIFSTOPPED (status))
+ {
+ ourstatus->kind = TARGET_WAITKIND_SIGNALLED;
+ ourstatus->value.sig =
+ target_signal_from_host (WTERMSIG (status));
+ }
+ else
+ {
+ ourstatus->kind = TARGET_WAITKIND_STOPPED;
+ ourstatus->value.sig =
+ target_signal_from_host (WSTOPSIG (status));
+ }
+#else
+ store_waitstatus (ourstatus, status.w_status);
+#endif
+
+ return pid;
+ }
+}
+
+/* Return nonzero if the given thread is still alive. */
+int
+child_thread_alive (pid)
+ int pid;
+{
+ /* Arggh. Apparently pthread_kill only works for threads within
+ the process that calls pthread_kill.
+
+ We want to avoid the lynx signal extensions as they simply don't
+ map well to the generic gdb interface we want to keep.
+
+ All we want to do is determine if a particular thread is alive;
+ it appears as if we can just make a harmless thread specific
+ ptrace call to do that. */
+ return (ptrace (PTRACE_THREADUSER, pid, 0, 0) != -1);
+}
+
+/* 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;
+ enum target_signal signal;
+{
+ int func;
+
+ errno = 0;
+
+ /* If pid == -1, then we want to step/continue all threads, else
+ we only want to step/continue a single thread. */
+ if (pid == -1)
+ {
+ pid = inferior_pid;
+ func = step ? PTRACE_SINGLESTEP : PTRACE_CONT;
+ }
+ else
+ func = step ? PTRACE_SINGLESTEP_ONE : PTRACE_CONT_ONE;
+
+
+ /* 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. */
+
+ ptrace (func, pid, (PTRACE_ARG3_TYPE) 1, target_signal_to_host (signal));
+
+ if (errno)
+ perror_with_name ("ptrace");
+}
+
+/* Convert a Lynx process ID to a string. Returns the string in a static
+ buffer. */
+
+char *
+lynx_pid_to_str (pid)
+ int pid;
+{
+ static char buf[40];
+
+ sprintf (buf, "process %d thread %d", PIDGET (pid), TIDGET (pid));
+
+ return buf;
+}
+
+/* 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.
+ */
+
+static void
+fetch_core_registers (core_reg_sect, core_reg_size, which, reg_addr)
+ char *core_reg_sect;
+ unsigned core_reg_size;
+ int which;
+ CORE_ADDR reg_addr;
+{
+ struct st_entry s;
+ unsigned int regno;
+
+ for (regno = 0; regno < NUM_REGS; regno++)
+ if (regmap[regno] != -1)
+ supply_register (regno, core_reg_sect + offsetof (st_t, ec)
+ + regmap[regno]);
+
+#ifdef SPARC
+/* Fetching this register causes all of the I & L regs to be read from the
+ stack and validated. */
+
+ fetch_inferior_registers (I0_REGNUM);
+#endif
+}
+
+
+/* Register that we are able to handle lynx core file formats.
+ FIXME: is this really bfd_target_unknown_flavour? */
+
+static struct core_fns lynx_core_fns =
+{
+ bfd_target_unknown_flavour,
+ fetch_core_registers,
+ NULL
+};
+
+void
+_initialize_core_lynx ()
+{
+ add_core_fns (&lynx_core_fns);
+}
diff --git a/gdb/m2-exp.y b/gdb/m2-exp.y
new file mode 100644
index 00000000000..507e5bc62fd
--- /dev/null
+++ b/gdb/m2-exp.y
@@ -0,0 +1,1094 @@
+/* YACC grammar for Modula-2 expressions, for GDB.
+ Copyright (C) 1986, 1989, 1990, 1991, 1993, 1994, 1995
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 "gdb_string.h"
+#include "expression.h"
+#include "language.h"
+#include "value.h"
+#include "parser-defs.h"
+#include "m2-lang.h"
+#include "bfd.h" /* Required by objfiles.h. */
+#include "symfile.h" /* Required by objfiles.h. */
+#include "objfiles.h" /* For have_full_symbols and have_partial_symbols */
+
+/* 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 */
+#define yylhs m2_yylhs
+#define yylen m2_yylen
+#define yydefred m2_yydefred
+#define yydgoto m2_yydgoto
+#define yysindex m2_yysindex
+#define yyrindex m2_yyrindex
+#define yygindex m2_yygindex
+#define yytable m2_yytable
+#define yycheck m2_yycheck
+
+#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;
+ ULONGEST ulval;
+ DOUBLEST 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 <voidval> 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
+ ;
+
+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
+ ;
+
+/* 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, NULL, NULL);
+ if (msymbol != NULL)
+ {
+ write_exp_msymbol
+ (msymbol,
+ lookup_function_type (builtin_type_int),
+ builtin_type_int);
+ }
+ 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 < (int) (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;
+
+ /* Lookup special keywords */
+ for(i = 0 ; i < (int) (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;
+
+ if (*tokstart == '$')
+ {
+ write_dollar_variable (yylval.sval);
+ 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->aclass)
+ {
+ 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:
+ case LOC_UNRESOLVED:
+ 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;
+{
+ error ("A %s in expression, near `%s'.", (msg ? msg : "error"), lexptr);
+}
diff --git a/gdb/m2-lang.c b/gdb/m2-lang.c
new file mode 100644
index 00000000000..f5f38a9d3ed
--- /dev/null
+++ b/gdb/m2-lang.c
@@ -0,0 +1,472 @@
+/* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "symtab.h"
+#include "gdbtypes.h"
+#include "expression.h"
+#include "parser-defs.h"
+#include "language.h"
+#include "m2-lang.h"
+#include "c-lang.h"
+
+static struct type *m2_create_fundamental_type PARAMS ((struct objfile *, int));
+static void m2_printstr PARAMS ((GDB_FILE *stream, char *string, unsigned int length, int width, int force_ellipses));
+static void m2_printchar PARAMS ((int, GDB_FILE *));
+static void m2_emit_char PARAMS ((int, GDB_FILE *, int));
+
+/* 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
+m2_emit_char (c, stream, quoter)
+ register int c;
+ GDB_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;
+ GDB_FILE *stream;
+{
+ fputs_filtered ("'", stream);
+ LA_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, width, force_ellipses)
+ GDB_FILE *stream;
+ char *string;
+ unsigned int length;
+ int width;
+ 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 ("\"\"", gdb_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;
+ }
+ LA_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,
+ 0, "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,
+ 0, "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,
+ 0, "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,
+ 0, "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,
+ 0, "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_COMPLEX,
+ 2 * TARGET_FLOAT_BIT / TARGET_CHAR_BIT,
+ 0, "complex", objfile);
+ TYPE_TARGET_TYPE (type)
+ = m2_create_fundamental_type (objfile, FT_FLOAT);
+ break;
+ case FT_DBL_PREC_COMPLEX:
+ type = init_type (TYPE_CODE_COMPLEX,
+ 2 * TARGET_DOUBLE_BIT / TARGET_CHAR_BIT,
+ 0, "double complex", objfile);
+ TYPE_TARGET_TYPE (type)
+ = m2_create_fundamental_type (objfile, FT_DBL_PREC_FLOAT);
+ break;
+ case FT_EXT_PREC_COMPLEX:
+ type = init_type (TYPE_CODE_COMPLEX,
+ 2 * TARGET_LONG_DOUBLE_BIT / TARGET_CHAR_BIT,
+ 0, "long double complex", objfile);
+ TYPE_TARGET_TYPE (type)
+ = m2_create_fundamental_type (objfile, FT_EXT_PREC_FLOAT);
+ 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},
+ {"CAP", UNOP_CAP, PREC_BUILTIN_FUNCTION, 0},
+ {"CHR", UNOP_CHR, PREC_BUILTIN_FUNCTION, 0},
+ {"ORD", UNOP_ORD, PREC_BUILTIN_FUNCTION, 0},
+ {"FLOAT",UNOP_FLOAT, PREC_BUILTIN_FUNCTION, 0},
+ {"HIGH", UNOP_HIGH, PREC_BUILTIN_FUNCTION, 0},
+ {"MAX", UNOP_MAX, PREC_BUILTIN_FUNCTION, 0},
+ {"MIN", UNOP_MIN, PREC_BUILTIN_FUNCTION, 0},
+ {"ODD", UNOP_ODD, PREC_BUILTIN_FUNCTION, 0},
+ {"TRUNC", UNOP_TRUNC, PREC_BUILTIN_FUNCTION, 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_PTR (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 */
+ evaluate_subexp_standard,
+ m2_printchar, /* Print character constant */
+ m2_printstr, /* function to print string constant */
+ m2_emit_char, /* Function to print a single character */
+ 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 */
+ c_value_print, /* Print a top-level value */
+ {"", "", "", ""}, /* 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 */
+ 0, /* arrays are first-class (not c-style) */
+ 0, /* String lower bound */
+ &builtin_type_m2_char, /* Type of string elements */
+ 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);
+
+ add_language (&m2_language_defn);
+}
diff --git a/gdb/m2-lang.h b/gdb/m2-lang.h
new file mode 100644
index 00000000000..dc627b7f471
--- /dev/null
+++ b/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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 *, GDB_FILE *, int, int));
+
+extern int
+m2_val_print PARAMS ((struct type *, char *, int, CORE_ADDR, GDB_FILE *, int, int,
+ int, enum val_prettyprint));
diff --git a/gdb/m2-typeprint.c b/gdb/m2-typeprint.c
new file mode 100644
index 00000000000..317f40189ef
--- /dev/null
+++ b/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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 "gdb_string.h"
+#include <errno.h>
+
+void
+m2_print_type (type, varstring, stream, show, level)
+ struct type *type;
+ char *varstring;
+ GDB_FILE *stream;
+ int show;
+ int level;
+{
+ extern void c_print_type PARAMS ((struct type *, char *, GDB_FILE *, int, int));
+
+ c_print_type (type, varstring, stream, show, level); /* FIXME */
+}
diff --git a/gdb/m2-valprint.c b/gdb/m2-valprint.c
new file mode 100644
index 00000000000..12a2f27e173
--- /dev/null
+++ b/gdb/m2-valprint.c
@@ -0,0 +1,47 @@
+/* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "obstack.h"
+#include "symtab.h"
+#include "gdbtypes.h"
+#include "valprint.h"
+#include "m2-lang.h"
+
+/* FIXME: For now, just explicitly declare c_val_print and use it instead */
+
+int
+m2_val_print (type, valaddr, embedded_offset, address,
+ stream, format, deref_ref, recurse, pretty)
+ struct type *type;
+ char *valaddr;
+ int embedded_offset;
+ CORE_ADDR address;
+ GDB_FILE *stream;
+ int format;
+ int deref_ref;
+ int recurse;
+ enum val_prettyprint pretty;
+{
+ extern int
+ c_val_print PARAMS ((struct type *, char *, int, CORE_ADDR,
+ GDB_FILE *, int, int, int, enum val_prettyprint));
+ return (c_val_print (type, valaddr, 0, address, stream, format, deref_ref,
+ recurse, pretty));
+}
diff --git a/gdb/m3-nat.c b/gdb/m3-nat.c
new file mode 100644
index 00000000000..4614f656550
--- /dev/null
+++ b/gdb/m3-nat.c
@@ -0,0 +1,4646 @@
+/* Interface GDB to Mach 3.0 operating systems.
+ (Most) Mach 3.0 related routines live in this file.
+
+ Copyright (C) 1992, 1996, 1999 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/*
+ * Author: Jukka Virtanen <jtv@hut.fi>
+ * Computing Centre
+ * Helsinki University of Technology
+ * Finland
+ *
+ * Thanks to my friends who helped with ideas and testing:
+ *
+ * Johannes Helander, Antti Louko, Tero Mononen,
+ * jvh@cs.hut.fi alo@hut.fi tmo@cs.hut.fi
+ *
+ * Tero Kivinen and Eamonn McManus
+ * kivinen@cs.hut.fi emcmanus@gr.osf.org
+ *
+ */
+
+#include <stdio.h>
+
+#include <mach.h>
+#include <servers/netname.h>
+#include <servers/machid.h>
+#include <mach/message.h>
+#include <mach/notify.h>
+#include <mach_error.h>
+#include <mach/exception.h>
+#include <mach/vm_attributes.h>
+
+#include "defs.h"
+#include "inferior.h"
+#include "symtab.h"
+#include "value.h"
+#include "language.h"
+#include "target.h"
+#include "wait.h"
+#include "gdbcmd.h"
+#include "gdbcore.h"
+
+#if 0
+#include <servers/machid_lib.h>
+#else
+#define MACH_TYPE_TASK 1
+#define MACH_TYPE_THREAD 2
+#endif
+
+/* Included only for signal names and NSIG
+ *
+ * note: There are many problems in signal handling with
+ * gdb in Mach 3.0 in general.
+ */
+#include <signal.h>
+#define SIG_UNKNOWN 0 /* Exception that has no matching unix signal */
+
+#include <cthreads.h>
+
+/* This is what a cproc looks like. This is here partly because
+ cthread_internals.h is not a header we can just #include, partly with
+ an eye towards perhaps getting this to work with cross-debugging
+ someday. Best solution is if CMU publishes a real interface to this
+ stuff. */
+#define CPROC_NEXT_OFFSET 0
+#define CPROC_NEXT_SIZE (TARGET_PTR_BIT / HOST_CHAR_BIT)
+#define CPROC_INCARNATION_OFFSET (CPROC_NEXT_OFFSET + CPROC_NEXT_SIZE)
+#define CPROC_INCARNATION_SIZE (sizeof (cthread_t))
+#define CPROC_LIST_OFFSET (CPROC_INCARNATION_OFFSET + CPROC_INCARNATION_SIZE)
+#define CPROC_LIST_SIZE (TARGET_PTR_BIT / HOST_CHAR_BIT)
+#define CPROC_WAIT_OFFSET (CPROC_LIST_OFFSET + CPROC_LIST_SIZE)
+#define CPROC_WAIT_SIZE (TARGET_PTR_BIT / HOST_CHAR_BIT)
+#define CPROC_REPLY_OFFSET (CPROC_WAIT_OFFSET + CPROC_WAIT_SIZE)
+#define CPROC_REPLY_SIZE (sizeof (mach_port_t))
+#define CPROC_CONTEXT_OFFSET (CPROC_REPLY_OFFSET + CPROC_REPLY_SIZE)
+#define CPROC_CONTEXT_SIZE (TARGET_INT_BIT / HOST_CHAR_BIT)
+#define CPROC_LOCK_OFFSET (CPROC_CONTEXT_OFFSET + CPROC_CONTEXT_SIZE)
+#define CPROC_LOCK_SIZE (sizeof (spin_lock_t))
+#define CPROC_STATE_OFFSET (CPROC_LOCK_OFFSET + CPROC_LOCK_SIZE)
+#define CPROC_STATE_SIZE (TARGET_INT_BIT / HOST_CHAR_BIT)
+#define CPROC_WIRED_OFFSET (CPROC_STATE_OFFSET + CPROC_STATE_SIZE)
+#define CPROC_WIRED_SIZE (sizeof (mach_port_t))
+#define CPROC_BUSY_OFFSET (CPROC_WIRED_OFFSET + CPROC_WIRED_SIZE)
+#define CPROC_BUSY_SIZE (TARGET_INT_BIT / HOST_CHAR_BIT)
+#define CPROC_MSG_OFFSET (CPROC_BUSY_OFFSET + CPROC_BUSY_SIZE)
+#define CPROC_MSG_SIZE (sizeof (mach_msg_header_t))
+#define CPROC_BASE_OFFSET (CPROC_MSG_OFFSET + CPROC_MSG_SIZE)
+#define CPROC_BASE_SIZE (TARGET_INT_BIT / HOST_CHAR_BIT)
+#define CPROC_SIZE_OFFSET (CPROC_BASE_OFFSET + CPROC_BASE_SIZE)
+#define CPROC_SIZE_SIZE (TARGET_INT_BIT / HOST_CHAR_BIT)
+#define CPROC_SIZE (CPROC_SIZE_OFFSET + CPROC_SIZE_SIZE)
+
+/* Values for the state field in the cproc. */
+#define CPROC_RUNNING 0
+#define CPROC_SWITCHING 1
+#define CPROC_BLOCKED 2
+#define CPROC_CONDWAIT 4
+
+/* For cproc and kernel thread mapping */
+typedef struct gdb_thread {
+ mach_port_t name;
+ CORE_ADDR sp;
+ CORE_ADDR pc;
+ CORE_ADDR fp;
+ boolean_t in_emulator;
+ int slotid;
+
+ /* This is for the mthreads list. It points to the cproc list.
+ Perhaps the two lists should be merged (or perhaps it was a mistake
+ to make them both use a struct gdb_thread). */
+ struct gdb_thread *cproc;
+
+ /* These are for the cproc list, which is linked through the next field
+ of the struct gdb_thread. */
+ char raw_cproc[CPROC_SIZE];
+ /* The cthread which is pointed to by the incarnation field from the
+ cproc. This points to the copy we've read into GDB. */
+ cthread_t cthread;
+ /* Point back to the mthreads list. */
+ int reverse_map;
+ struct gdb_thread *next;
+} *gdb_thread_t;
+
+/*
+ * Actions for Mach exceptions.
+ *
+ * sigmap field maps the exception to corresponding Unix signal.
+ *
+ * I do not know how to map the exception to unix signal
+ * if SIG_UNKNOWN is specified.
+ */
+
+struct exception_list {
+ char *name;
+ boolean_t forward;
+ boolean_t print;
+ int sigmap;
+} exception_map[] = {
+ {"not_mach3_exception", FALSE, TRUE, SIG_UNKNOWN},
+ {"EXC_BAD_ACCESS", FALSE, TRUE, SIGSEGV},
+ {"EXC_BAD_INSTRUCTION", FALSE, TRUE, SIGILL},
+ {"EXC_ARITHMETIC", FALSE, TRUE, SIGFPE},
+ {"EXC_EMULATION", FALSE, TRUE, SIGEMT}, /* ??? */
+ {"EXC_SOFTWARE", FALSE, TRUE, SIG_UNKNOWN},
+ {"EXC_BREAKPOINT", FALSE, FALSE, SIGTRAP}
+};
+
+/* Mach exception table size */
+int max_exception = sizeof(exception_map)/sizeof(struct exception_list) - 1;
+
+#define MAX_EXCEPTION max_exception
+
+WAITTYPE wait_status;
+
+/* If you define this, intercepted bsd server calls will be
+ * dumped while waiting the inferior to EXEC the correct
+ * program
+ */
+/* #define DUMP_SYSCALL /* debugging interceptor */
+
+/* xx_debug() outputs messages if this is nonzero.
+ * If > 1, DUMP_SYSCALL will dump message contents.
+ */
+int debug_level = 0;
+
+/* "Temporary" debug stuff */
+void
+xx_debug (fmt, a,b,c)
+char *fmt;
+int a,b,c;
+{
+ if (debug_level)
+ warning (fmt, a, b, c);
+}
+
+/* This is in libmach.a */
+extern mach_port_t name_server_port;
+
+/* Set in catch_exception_raise */
+int stop_exception, stop_code, stop_subcode;
+int stopped_in_exception;
+
+/* Thread that was the active thread when we stopped */
+thread_t stop_thread = MACH_PORT_NULL;
+
+char *hostname = "";
+
+/* Set when task is attached or created */
+boolean_t emulator_present = FALSE;
+
+task_t inferior_task;
+thread_t current_thread;
+
+/* Exception ports for inferior task */
+mach_port_t inferior_exception_port = MACH_PORT_NULL;
+mach_port_t inferior_old_exception_port = MACH_PORT_NULL;
+
+/* task exceptions and notifications */
+mach_port_t inferior_wait_port_set = MACH_PORT_NULL;
+mach_port_t our_notify_port = MACH_PORT_NULL;
+
+/* This is "inferior_wait_port_set" when not single stepping, and
+ * "singlestepped_thread_port" when we are single stepping.
+ *
+ * This is protected by a cleanup function: discard_single_step()
+ */
+mach_port_t currently_waiting_for = MACH_PORT_NULL;
+
+/* A port for external messages to gdb.
+ * External in the meaning that they do not come
+ * from the inferior_task, but rather from external
+ * tasks.
+ *
+ * As a debugging feature:
+ * A debugger debugging another debugger can stop the
+ * inferior debugger by the following command sequence
+ * (without running external programs)
+ *
+ * (top-gdb) set stop_inferior_gdb ()
+ * (top-gdb) continue
+ */
+mach_port_t our_message_port = MACH_PORT_NULL;
+
+/* For single stepping */
+mach_port_t thread_exception_port = MACH_PORT_NULL;
+mach_port_t thread_saved_exception_port = MACH_PORT_NULL;
+mach_port_t singlestepped_thread_port = MACH_PORT_NULL;
+
+/* For machid calls */
+mach_port_t mid_server = MACH_PORT_NULL;
+mach_port_t mid_auth = MACH_PORT_NULL;
+
+/* If gdb thinks the inferior task is not suspended, it
+ * must take suspend/abort the threads when it reads the state.
+ */
+int must_suspend_thread = 0;
+
+/* When single stepping, we switch the port that mach_really_wait() listens to.
+ * This cleanup is a guard to prevent the port set from being left to
+ * the singlestepped_thread_port when error() is called.
+ * This is nonzero only when we are single stepping.
+ */
+#define NULL_CLEANUP (struct cleanup *)0
+struct cleanup *cleanup_step = NULL_CLEANUP;
+
+
+static struct target_ops m3_ops;
+
+static void m3_kill_inferior ();
+
+#if 0
+#define MACH_TYPE_EXCEPTION_PORT -1
+#endif
+
+/* Chain of ports to remember requested notifications. */
+
+struct port_chain {
+ struct port_chain *next;
+ mach_port_t port;
+ int type;
+ int mid; /* Now only valid with MACH_TYPE_THREAD and */
+ /* MACH_TYPE_THREAD */
+};
+typedef struct port_chain *port_chain_t;
+
+/* Room for chain nodes comes from pchain_obstack */
+struct obstack pchain_obstack;
+struct obstack *port_chain_obstack = &pchain_obstack;
+
+/* For thread handling */
+struct obstack Cproc_obstack;
+struct obstack *cproc_obstack = &Cproc_obstack;
+
+/* the list of notified ports */
+port_chain_t notify_chain = (port_chain_t) NULL;
+
+port_chain_t
+port_chain_insert (list, name, type)
+ port_chain_t list;
+ mach_port_t name;
+ int type;
+{
+ kern_return_t ret;
+ port_chain_t new;
+ int mid;
+
+ if (! MACH_PORT_VALID (name))
+ return list;
+
+ if (type == MACH_TYPE_TASK || type == MACH_TYPE_THREAD)
+ {
+ if (! MACH_PORT_VALID (mid_server))
+ {
+ warning ("Machid server port invalid, can not map port 0x%x to MID",
+ name);
+ mid = name;
+ }
+ else
+ {
+ ret = machid_mach_register (mid_server, mid_auth, name, type, &mid);
+
+ if (ret != KERN_SUCCESS)
+ {
+ warning ("Can not map name (0x%x) to MID with machid", name);
+ mid = name;
+ }
+ }
+ }
+ else
+ abort ();
+
+ new = (port_chain_t) obstack_alloc (port_chain_obstack,
+ sizeof (struct port_chain));
+ new->next = list;
+ new->port = name;
+ new->type = type;
+ new->mid = mid;
+
+ return new;
+}
+
+port_chain_t
+port_chain_delete (list, elem)
+ port_chain_t list;
+ mach_port_t elem;
+{
+ if (list)
+ if (list->port == elem)
+ list = list->next;
+ else
+ while (list->next)
+ {
+ if (list->next->port == elem)
+ list->next = list->next->next; /* GCd with obstack_free() */
+ else
+ list = list->next;
+ }
+ return list;
+}
+
+void
+port_chain_destroy (ostack)
+ struct obstack *ostack;
+{
+ obstack_free (ostack, 0);
+ obstack_init (ostack);
+}
+
+port_chain_t
+port_chain_member (list, elem)
+ port_chain_t list;
+ mach_port_t elem;
+{
+ while (list)
+ {
+ if (list->port == elem)
+ return list;
+ list = list->next;
+ }
+ return (port_chain_t) NULL;
+}
+
+int
+map_port_name_to_mid (name, type)
+mach_port_t name;
+int type;
+{
+ port_chain_t elem;
+
+ if (!MACH_PORT_VALID (name))
+ return -1;
+
+ elem = port_chain_member (notify_chain, name);
+
+ if (elem && (elem->type == type))
+ return elem->mid;
+
+ if (elem)
+ return -1;
+
+ if (! MACH_PORT_VALID (mid_server))
+ {
+ warning ("Machid server port invalid, can not map port 0x%x to mid",
+ name);
+ return -1;
+ }
+ else
+ {
+ int mid;
+ kern_return_t ret;
+
+ ret = machid_mach_register (mid_server, mid_auth, name, type, &mid);
+
+ if (ret != KERN_SUCCESS)
+ {
+ warning ("Can not map name (0x%x) to mid with machid", name);
+ return -1;
+ }
+ return mid;
+ }
+}
+
+/* Guard for currently_waiting_for and singlestepped_thread_port */
+static void
+discard_single_step (thread)
+ thread_t thread;
+{
+ currently_waiting_for = inferior_wait_port_set;
+
+ cleanup_step = NULL_CLEANUP;
+ if (MACH_PORT_VALID (thread) && MACH_PORT_VALID (singlestepped_thread_port))
+ setup_single_step (thread, FALSE);
+}
+
+setup_single_step (thread, start_step)
+ thread_t thread;
+ boolean_t start_step;
+{
+ kern_return_t ret;
+
+ if (! MACH_PORT_VALID (thread))
+ error ("Invalid thread supplied to setup_single_step");
+ else
+ {
+ mach_port_t teport;
+
+ /* Get the current thread exception port */
+ ret = thread_get_exception_port (thread, &teport);
+ CHK ("Getting thread's exception port", ret);
+
+ if (start_step)
+ {
+ if (MACH_PORT_VALID (singlestepped_thread_port))
+ {
+ warning ("Singlestepped_thread_port (0x%x) is still valid?",
+ singlestepped_thread_port);
+ singlestepped_thread_port = MACH_PORT_NULL;
+ }
+
+ /* If we are already stepping this thread */
+ if (MACH_PORT_VALID (teport) && teport == thread_exception_port)
+ {
+ ret = mach_port_deallocate (mach_task_self (), teport);
+ CHK ("Could not deallocate thread exception port", ret);
+ }
+ else
+ {
+ ret = thread_set_exception_port (thread, thread_exception_port);
+ CHK ("Setting exception port for thread", ret);
+#if 0
+ /* Insert thread exception port to wait port set */
+ ret = mach_port_move_member (mach_task_self(),
+ thread_exception_port,
+ inferior_wait_port_set);
+ CHK ("Moving thread exception port to inferior_wait_port_set",
+ ret);
+#endif
+ thread_saved_exception_port = teport;
+ }
+
+ thread_trace (thread, TRUE);
+
+ singlestepped_thread_port = thread_exception_port;
+ currently_waiting_for = singlestepped_thread_port;
+ cleanup_step = make_cleanup (discard_single_step, thread);
+ }
+ else
+ {
+ if (! MACH_PORT_VALID (teport))
+ error ("Single stepped thread had an invalid exception port?");
+
+ if (teport != thread_exception_port)
+ error ("Single stepped thread had an unknown exception port?");
+
+ ret = mach_port_deallocate (mach_task_self (), teport);
+ CHK ("Couldn't deallocate thread exception port", ret);
+#if 0
+ /* Remove thread exception port from wait port set */
+ ret = mach_port_move_member (mach_task_self(),
+ thread_exception_port,
+ MACH_PORT_NULL);
+ CHK ("Removing thread exception port from inferior_wait_port_set",
+ ret);
+#endif
+ /* Restore thread's old exception port */
+ ret = thread_set_exception_port (thread,
+ thread_saved_exception_port);
+ CHK ("Restoring stepped thread's exception port", ret);
+
+ if (MACH_PORT_VALID (thread_saved_exception_port))
+ (void) mach_port_deallocate (mach_task_self (),
+ thread_saved_exception_port);
+
+ thread_trace (thread, FALSE);
+
+ singlestepped_thread_port = MACH_PORT_NULL;
+ currently_waiting_for = inferior_wait_port_set;
+ if (cleanup_step)
+ discard_cleanups (cleanup_step);
+ }
+ }
+}
+
+static
+request_notify (name, variant, type)
+ mach_port_t name;
+ mach_msg_id_t variant;
+ int type;
+{
+ kern_return_t ret;
+ mach_port_t previous_port_dummy = MACH_PORT_NULL;
+
+ if (! MACH_PORT_VALID (name))
+ return;
+
+ if (port_chain_member (notify_chain, name))
+ return;
+
+ ret = mach_port_request_notification (mach_task_self(),
+ name,
+ variant,
+ 1,
+ our_notify_port,
+ MACH_MSG_TYPE_MAKE_SEND_ONCE,
+ &previous_port_dummy);
+ CHK ("Serious: request_notify failed", ret);
+
+ (void) mach_port_deallocate (mach_task_self (),
+ previous_port_dummy);
+
+ notify_chain = port_chain_insert (notify_chain, name, type);
+}
+
+reverse_msg_bits(msgp, type)
+ mach_msg_header_t *msgp;
+ int type;
+{
+ int rbits,lbits;
+ rbits = MACH_MSGH_BITS_REMOTE(msgp->msgh_bits);
+ lbits = type;
+ msgp->msgh_bits =
+ (msgp->msgh_bits & ~MACH_MSGH_BITS_PORTS_MASK) |
+ MACH_MSGH_BITS(lbits,rbits);
+}
+
+/* On the third day He said:
+
+ Let this be global
+ and then it was global.
+
+ When creating the inferior fork, the
+ child code in inflow.c sets the name of the
+ bootstrap_port in its address space to this
+ variable.
+
+ The name is transferred to our address space
+ with mach3_read_inferior().
+
+ Thou shalt not do this with
+ task_get_bootstrap_port() in this task, since
+ the name in the inferior task is different than
+ the one we get.
+
+ For blessed are the meek, as they shall inherit
+ the address space.
+ */
+mach_port_t original_server_port_name = MACH_PORT_NULL;
+
+
+/* Called from inferior after FORK but before EXEC */
+static void
+m3_trace_me ()
+{
+ kern_return_t ret;
+
+ /* Get the NAME of the bootstrap port in this task
+ so that GDB can read it */
+ ret = task_get_bootstrap_port (mach_task_self (),
+ &original_server_port_name);
+ if (ret != KERN_SUCCESS)
+ abort ();
+ ret = mach_port_deallocate (mach_task_self (),
+ original_server_port_name);
+ if (ret != KERN_SUCCESS)
+ abort ();
+
+ /* Suspend this task to let the parent change my ports.
+ Resumed by the debugger */
+ ret = task_suspend (mach_task_self ());
+ if (ret != KERN_SUCCESS)
+ abort ();
+}
+
+/*
+ * Intercept system calls to Unix server.
+ * After EXEC_COUNTER calls to exec(), return.
+ *
+ * Pre-assertion: Child is suspended. (Not verified)
+ * Post-condition: Child is suspended after EXEC_COUNTER exec() calls.
+ */
+
+void
+intercept_exec_calls (exec_counter)
+ int exec_counter;
+{
+ int terminal_initted = 0;
+
+ struct syscall_msg_t {
+ mach_msg_header_t header;
+ mach_msg_type_t type;
+ char room[ 2000 ]; /* Enuff space */
+ };
+
+ struct syscall_msg_t syscall_in, syscall_out;
+
+ mach_port_t fake_server;
+ mach_port_t original_server_send;
+ mach_port_t original_exec_reply;
+ mach_port_t exec_reply;
+ mach_port_t exec_reply_send;
+ mach_msg_type_name_t acquired;
+ mach_port_t emulator_server_port_name;
+ struct task_basic_info info;
+ mach_msg_type_number_t info_count;
+
+ kern_return_t ret;
+
+ if (exec_counter <= 0)
+ return; /* We are already set up in the correct program */
+
+ ret = mach_port_allocate(mach_task_self(),
+ MACH_PORT_RIGHT_RECEIVE,
+ &fake_server);
+ CHK("create inferior_fake_server port failed", ret);
+
+ /* Wait for inferior_task to suspend itself */
+ while(1)
+ {
+ info_count = sizeof (info);
+ ret = task_info (inferior_task,
+ TASK_BASIC_INFO,
+ (task_info_t)&info,
+ &info_count);
+ CHK ("Task info", ret);
+
+ if (info.suspend_count)
+ break;
+
+ /* Note that the definition of the parameter was undefined
+ * at the time of this writing, so I just use an `ad hoc' value.
+ */
+ (void) swtch_pri (42); /* Universal Priority Value */
+ }
+
+ /* Read the inferior's bootstrap port name */
+ if (!mach3_read_inferior (&original_server_port_name,
+ &original_server_port_name,
+ sizeof (original_server_port_name)))
+ error ("Can't read inferior task bootstrap port name");
+
+ /* @@ BUG: If more than 1 send right GDB will FAIL!!! */
+ /* Should get refs, and set them back when restoring */
+ /* Steal the original bsd server send right from inferior */
+ ret = mach_port_extract_right (inferior_task,
+ original_server_port_name,
+ MACH_MSG_TYPE_MOVE_SEND,
+ &original_server_send,
+ &acquired);
+ CHK("mach_port_extract_right (bsd server send)",ret);
+
+ if (acquired != MACH_MSG_TYPE_PORT_SEND)
+ error("Incorrect right extracted, send right to bsd server excpected");
+
+ ret = mach_port_insert_right (inferior_task,
+ original_server_port_name,
+ fake_server,
+ MACH_MSG_TYPE_MAKE_SEND);
+ CHK("mach_port_insert_right (fake server send)",ret);
+
+ xx_debug ("inferior task bsd server ports set up \nfs %x, ospn %x, oss %x\n",
+ fake_server,
+ original_server_port_name, original_server_send);
+
+ /* A receive right to the reply generated by unix server exec() request */
+ ret = mach_port_allocate(mach_task_self(),
+ MACH_PORT_RIGHT_RECEIVE,
+ &exec_reply);
+ CHK("create intercepted_reply_port port failed", ret);
+
+ /* Pass this send right to Unix server so it replies to us after exec() */
+ ret = mach_port_extract_right (mach_task_self (),
+ exec_reply,
+ MACH_MSG_TYPE_MAKE_SEND_ONCE,
+ &exec_reply_send,
+ &acquired);
+ CHK("mach_port_extract_right (exec_reply)",ret);
+
+ if (acquired != MACH_MSG_TYPE_PORT_SEND_ONCE)
+ error("Incorrect right extracted, send once excpected for exec reply");
+
+ ret = mach_port_move_member(mach_task_self(),
+ fake_server,
+ inferior_wait_port_set);
+ CHK ("Moving fake syscall port to inferior_wait_port_set", ret);
+
+ xx_debug ("syscall fake server set up, resuming inferior\n");
+
+ ret = task_resume (inferior_task);
+ CHK("task_resume (startup)", ret);
+
+ /* Read requests from the inferior.
+ Pass directly through everything else except exec() calls.
+ */
+ while(exec_counter > 0)
+ {
+ ret = mach_msg (&syscall_in.header, /* header */
+ MACH_RCV_MSG, /* options */
+ 0, /* send size */
+ sizeof (struct syscall_msg_t), /* receive size */
+ inferior_wait_port_set, /* receive_name */
+ MACH_MSG_TIMEOUT_NONE,
+ MACH_PORT_NULL);
+ CHK("mach_msg (intercepted sycall)", ret);
+
+#ifdef DUMP_SYSCALL
+ print_msg (&syscall_in.header);
+#endif
+
+ /* ASSERT : msgh_local_port == fake_server */
+
+ if (notify_server (&syscall_in.header, &syscall_out.header))
+ error ("received a notify while intercepting syscalls");
+
+ if (syscall_in.header.msgh_id == MIG_EXEC_SYSCALL_ID)
+ {
+ xx_debug ("Received EXEC SYSCALL, counter = %d\n", exec_counter);
+ if (exec_counter == 1)
+ {
+ original_exec_reply = syscall_in.header.msgh_remote_port;
+ syscall_in.header.msgh_remote_port = exec_reply_send;
+ }
+
+ 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;
+ }
+
+ exec_counter--;
+ }
+
+ syscall_in.header.msgh_local_port = syscall_in.header.msgh_remote_port;
+ syscall_in.header.msgh_remote_port = original_server_send;
+
+ reverse_msg_bits(&syscall_in.header, MACH_MSG_TYPE_COPY_SEND);
+
+ ret = mach_msg_send (&syscall_in.header);
+ CHK ("Forwarded syscall", ret);
+ }
+
+ ret = mach_port_move_member(mach_task_self(),
+ fake_server,
+ MACH_PORT_NULL);
+ CHK ("Moving fake syscall out of inferior_wait_port_set", ret);
+
+ ret = mach_port_move_member(mach_task_self(),
+ exec_reply,
+ inferior_wait_port_set);
+ CHK ("Moving exec_reply to inferior_wait_port_set", ret);
+
+ ret = mach_msg (&syscall_in.header, /* header */
+ MACH_RCV_MSG, /* options */
+ 0, /* send size */
+ sizeof (struct syscall_msg_t), /* receive size */
+ inferior_wait_port_set, /* receive_name */
+ MACH_MSG_TIMEOUT_NONE,
+ MACH_PORT_NULL);
+ CHK("mach_msg (exec reply)", ret);
+
+ ret = task_suspend (inferior_task);
+ CHK ("Suspending inferior after last exec", ret);
+
+ must_suspend_thread = 0;
+
+ xx_debug ("Received exec reply from bsd server, suspended inferior task\n");
+
+#ifdef DUMP_SYSCALL
+ print_msg (&syscall_in.header);
+#endif
+
+ /* Message should appear as if it came from the unix server */
+ syscall_in.header.msgh_local_port = MACH_PORT_NULL;
+
+ /* and go to the inferior task original reply port */
+ syscall_in.header.msgh_remote_port = original_exec_reply;
+
+ reverse_msg_bits(&syscall_in.header, MACH_MSG_TYPE_MOVE_SEND_ONCE);
+
+ ret = mach_msg_send (&syscall_in.header);
+ CHK ("Forwarding exec reply to inferior", ret);
+
+ /* Garbage collect */
+ ret = mach_port_deallocate (inferior_task,
+ original_server_port_name);
+ CHK ("deallocating fake server send right", ret);
+
+ ret = mach_port_insert_right (inferior_task,
+ original_server_port_name,
+ original_server_send,
+ MACH_MSG_TYPE_MOVE_SEND);
+ CHK ("Restoring the original bsd server send right", ret);
+
+ ret = mach_port_destroy (mach_task_self (),
+ fake_server);
+ fake_server = MACH_PORT_DEAD;
+ CHK("mach_port_destroy (fake_server)", ret);
+
+ ret = mach_port_destroy (mach_task_self (),
+ exec_reply);
+ exec_reply = MACH_PORT_DEAD;
+ CHK("mach_port_destroy (exec_reply)", ret);
+
+ xx_debug ("Done with exec call interception\n");
+}
+
+void
+consume_send_rights (thread_list, thread_count)
+ thread_array_t thread_list;
+ int thread_count;
+{
+ int index;
+
+ if (!thread_count)
+ return;
+
+ for (index = 0; index < thread_count; index++)
+ {
+ /* Since thread kill command kills threads, don't check ret */
+ (void) mach_port_deallocate (mach_task_self (),
+ thread_list [ index ]);
+ }
+}
+
+/* suspend/abort/resume a thread. */
+setup_thread (thread, what)
+ mach_port_t thread;
+ int what;
+{
+ kern_return_t ret;
+
+ if (what)
+ {
+ ret = thread_suspend (thread);
+ CHK ("setup_thread thread_suspend", ret);
+
+ ret = thread_abort (thread);
+ CHK ("setup_thread thread_abort", ret);
+ }
+ else
+ {
+ ret = thread_resume (thread);
+ CHK ("setup_thread thread_resume", ret);
+ }
+}
+
+int
+map_slot_to_mid (slot, threads, thread_count)
+ int slot;
+ thread_array_t threads;
+ int thread_count;
+{
+ kern_return_t ret;
+ int deallocate = 0;
+ int index;
+ int mid;
+
+ if (! threads)
+ {
+ deallocate++;
+ ret = task_threads (inferior_task, &threads, &thread_count);
+ CHK ("Can not select a thread from a dead task", ret);
+ }
+
+ if (slot < 0 || slot >= thread_count)
+ {
+ if (deallocate)
+ {
+ consume_send_rights (threads, thread_count);
+ (void) vm_deallocate (mach_task_self(), (vm_address_t)threads,
+ (thread_count * sizeof(mach_port_t)));
+ }
+ if (slot < 0)
+ error ("invalid slot number");
+ else
+ return -(slot+1);
+ }
+
+ mid = map_port_name_to_mid (threads [slot], MACH_TYPE_THREAD);
+
+ if (deallocate)
+ {
+ consume_send_rights (threads, thread_count);
+ (void) vm_deallocate (mach_task_self(), (vm_address_t)threads,
+ (thread_count * sizeof(mach_port_t)));
+ }
+
+ return mid;
+}
+
+static int
+parse_thread_id (arg, thread_count, slots)
+ char *arg;
+ int thread_count;
+ int slots;
+{
+ kern_return_t ret;
+ int mid;
+ int slot;
+ int index;
+
+ if (arg == 0)
+ return 0;
+
+ while (*arg && (*arg == ' ' || *arg == '\t'))
+ arg++;
+
+ if (! *arg)
+ return 0;
+
+ /* Currently parse MID and @SLOTNUMBER */
+ if (*arg != '@')
+ {
+ mid = atoi (arg);
+ if (mid <= 0)
+ error ("valid thread mid expected");
+ return mid;
+ }
+
+ arg++;
+ slot = atoi (arg);
+
+ if (slot < 0)
+ error ("invalid slot number");
+
+ /* If you want slot numbers to remain slot numbers, set slots.
+ *
+ * Well, since 0 is reserved, return the ordinal number
+ * of the thread rather than the slot number. Awk, this
+ * counts as a kludge.
+ */
+ if (slots)
+ return -(slot+1);
+
+ if (thread_count && slot >= thread_count)
+ return -(slot+1);
+
+ mid = map_slot_to_mid (slot);
+
+ return mid;
+}
+
+/* THREAD_ID 0 is special; it selects the first kernel
+ * thread from the list (i.e. SLOTNUMBER 0)
+ * This is used when starting the program with 'run' or when attaching.
+ *
+ * If FLAG is 0 the context is not changed, and the registers, frame, etc
+ * will continue to describe the old thread.
+ *
+ * If FLAG is nonzero, really select the thread.
+ * If FLAG is 2, the THREAD_ID is a slotnumber instead of a mid.
+ *
+ */
+kern_return_t
+select_thread (task, thread_id, flag)
+ mach_port_t task;
+ int thread_id;
+ int flag;
+{
+ thread_array_t thread_list;
+ int thread_count;
+ kern_return_t ret;
+ int index;
+ thread_t new_thread = MACH_PORT_NULL;
+
+ if (thread_id < 0)
+ error ("Can't select cprocs without kernel thread");
+
+ ret = task_threads (task, &thread_list, &thread_count);
+ if (ret != KERN_SUCCESS)
+ {
+ warning ("Can not select a thread from a dead task");
+ m3_kill_inferior ();
+ return KERN_FAILURE;
+ }
+
+ if (thread_count == 0)
+ {
+ /* The task can not do anything anymore, but it still
+ * exists as a container for memory and ports.
+ */
+ registers_changed ();
+ warning ("Task %d has no threads",
+ map_port_name_to_mid (task, MACH_TYPE_TASK));
+ current_thread = MACH_PORT_NULL;
+ (void) vm_deallocate(mach_task_self(),
+ (vm_address_t) thread_list,
+ (thread_count * sizeof(mach_port_t)));
+ return KERN_FAILURE;
+ }
+
+ if (! thread_id || flag == 2)
+ {
+ /* First thread or a slotnumber */
+ if (! thread_id)
+ new_thread = thread_list[0];
+ else
+ {
+ if (thread_id < thread_count)
+ new_thread = thread_list[ thread_id ];
+ else
+ {
+ (void) vm_deallocate(mach_task_self(),
+ (vm_address_t) thread_list,
+ (thread_count * sizeof(mach_port_t)));
+ error ("No such thread slot number : %d", thread_id);
+ }
+ }
+ }
+ else
+ {
+ for (index = 0; index < thread_count; index++)
+ if (thread_id == map_port_name_to_mid (thread_list [index],
+ MACH_TYPE_THREAD))
+ {
+ new_thread = thread_list [index];
+ index = -1;
+ break;
+ }
+
+ if (index != -1)
+ error ("No thread with mid %d", thread_id);
+ }
+
+ /* Notify when the selected thread dies */
+ request_notify (new_thread, MACH_NOTIFY_DEAD_NAME, MACH_TYPE_THREAD);
+
+ ret = vm_deallocate(mach_task_self(),
+ (vm_address_t) thread_list,
+ (thread_count * sizeof(mach_port_t)));
+ CHK ("vm_deallocate", ret);
+
+ if (! flag)
+ current_thread = new_thread;
+ else
+ {
+#if 0
+ if (MACH_PORT_VALID (current_thread))
+ {
+ /* Store the gdb's view of the thread we are deselecting
+ *
+ * @@ I think gdb updates registers immediately when they are
+ * changed, so don't do this.
+ */
+ ret = thread_abort (current_thread);
+ CHK ("Could not abort system calls when saving state of old thread",
+ ret);
+ target_prepare_to_store ();
+ target_store_registers (-1);
+ }
+#endif
+
+ registers_changed ();
+
+ current_thread = new_thread;
+
+ ret = thread_abort (current_thread);
+ CHK ("Could not abort system calls when selecting a thread", ret);
+
+ stop_pc = read_pc();
+ flush_cached_frames ();
+
+ select_frame (get_current_frame (), 0);
+ }
+
+ return KERN_SUCCESS;
+}
+
+/*
+ * Switch to use thread named NEW_THREAD.
+ * Return it's MID
+ */
+int
+switch_to_thread (new_thread)
+ thread_t new_thread;
+{
+ thread_t saved_thread = current_thread;
+ int mid;
+
+ mid = map_port_name_to_mid (new_thread,
+ MACH_TYPE_THREAD);
+ if (mid == -1)
+ warning ("Can't map thread name 0x%x to mid", new_thread);
+ else if (select_thread (inferior_task, mid, 1) != KERN_SUCCESS)
+ {
+ if (current_thread)
+ current_thread = saved_thread;
+ error ("Could not select thread %d", mid);
+ }
+
+ return mid;
+}
+
+/* Do this in gdb after doing FORK but before STARTUP_INFERIOR.
+ * Note that the registers are not yet valid in the inferior task.
+ */
+static int
+m3_trace_him (pid)
+ int pid;
+{
+ kern_return_t ret;
+
+ push_target (&m3_ops);
+
+ inferior_task = task_by_pid (pid);
+
+ if (! MACH_PORT_VALID (inferior_task))
+ error ("Can not map Unix pid %d to Mach task", pid);
+
+ /* Clean up previous notifications and create new ones */
+ setup_notify_port (1);
+
+ /* When notification appears, the inferior task has died */
+ request_notify (inferior_task, MACH_NOTIFY_DEAD_NAME, MACH_TYPE_TASK);
+
+ emulator_present = have_emulator_p (inferior_task);
+
+ /* By default, select the first thread,
+ * If task has no threads, gives a warning
+ * Does not fetch registers, since they are not yet valid.
+ */
+ select_thread (inferior_task, 0, 0);
+
+ inferior_exception_port = MACH_PORT_NULL;
+
+ setup_exception_port ();
+
+ xx_debug ("Now the debugged task is created\n");
+
+ /* One trap to exec the shell, one to exec the program being debugged. */
+ intercept_exec_calls (2);
+
+ return pid;
+}
+
+setup_exception_port ()
+{
+ kern_return_t ret;
+
+ ret = mach_port_allocate (mach_task_self(),
+ MACH_PORT_RIGHT_RECEIVE,
+ &inferior_exception_port);
+ CHK("mach_port_allocate",ret);
+
+ /* add send right */
+ ret = mach_port_insert_right (mach_task_self (),
+ inferior_exception_port,
+ inferior_exception_port,
+ MACH_MSG_TYPE_MAKE_SEND);
+ CHK("mach_port_insert_right",ret);
+
+ ret = mach_port_move_member (mach_task_self(),
+ inferior_exception_port,
+ inferior_wait_port_set);
+ CHK("mach_port_move_member",ret);
+
+ ret = task_get_special_port (inferior_task,
+ TASK_EXCEPTION_PORT,
+ &inferior_old_exception_port);
+ CHK ("task_get_special_port(old exc)",ret);
+
+ ret = task_set_special_port (inferior_task,
+ TASK_EXCEPTION_PORT,
+ inferior_exception_port);
+ CHK("task_set_special_port",ret);
+
+ ret = mach_port_deallocate (mach_task_self (),
+ inferior_exception_port);
+ CHK("mack_port_deallocate",ret);
+
+#if 0
+ /* When notify appears, the inferior_task's exception
+ * port has been destroyed.
+ *
+ * Not used, since the dead_name_notification already
+ * appears when task dies.
+ *
+ */
+ request_notify (inferior_exception_port,
+ MACH_NOTIFY_NO_SENDERS,
+ MACH_TYPE_EXCEPTION_PORT);
+#endif
+}
+
+/* Nonzero if gdb is waiting for a message */
+int mach_really_waiting;
+
+/* Wait for the inferior to stop for some reason.
+ - Loop on notifications until inferior_task dies.
+ - Loop on exceptions until stopped_in_exception comes true.
+ (e.g. we receive a single step trace trap)
+ - a message arrives to gdb's message port
+
+ There is no other way to exit this loop.
+
+ Returns the inferior_pid for rest of gdb.
+ Side effects: Set *OURSTATUS. */
+int
+mach_really_wait (pid, ourstatus)
+ int pid;
+ struct target_waitstatus *ourstatus;
+{
+ kern_return_t ret;
+ int w;
+
+ struct msg {
+ mach_msg_header_t header;
+ mach_msg_type_t foo;
+ int data[8000];
+ } in_msg, out_msg;
+
+ /* Either notify (death), exception or message can stop the inferior */
+ stopped_in_exception = FALSE;
+
+ while (1)
+ {
+ QUIT;
+
+ stop_exception = stop_code = stop_subcode = -1;
+ stop_thread = MACH_PORT_NULL;
+
+ mach_really_waiting = 1;
+ ret = mach_msg (&in_msg.header, /* header */
+ MACH_RCV_MSG, /* options */
+ 0, /* send size */
+ sizeof (struct msg), /* receive size */
+ currently_waiting_for, /* receive name */
+ MACH_MSG_TIMEOUT_NONE,
+ MACH_PORT_NULL);
+ mach_really_waiting = 0;
+ CHK("mach_msg (receive)", ret);
+
+ /* Check if we received a notify of the childs' death */
+ if (notify_server (&in_msg.header, &out_msg.header))
+ {
+ /* If inferior_task is null then the inferior has
+ gone away and we want to return to command level.
+ Otherwise it was just an informative message and we
+ need to look to see if there are any more. */
+ if (inferior_task != MACH_PORT_NULL)
+ continue;
+ else
+ {
+ /* Collect Unix exit status for gdb */
+
+ wait3(&w, WNOHANG, 0);
+
+ /* This mess is here to check that the rest of
+ * gdb knows that the inferior died. It also
+ * tries to hack around the fact that Mach 3.0 (mk69)
+ * unix server (ux28) does not always know what
+ * has happened to it's children when mach-magic
+ * is applied on them.
+ */
+ if ((!WIFEXITED(w) && WIFSTOPPED(w)) ||
+ (WIFEXITED(w) && WEXITSTATUS(w) > 0377))
+ {
+ WSETEXIT(w, 0);
+ warning ("Using exit value 0 for terminated task");
+ }
+ else if (!WIFEXITED(w))
+ {
+ int sig = WTERMSIG(w);
+
+ /* Signals cause problems. Warn the user. */
+ if (sig != SIGKILL) /* Bad luck if garbage matches this */
+ warning ("The terminating signal stuff may be nonsense");
+ else if (sig > NSIG)
+ {
+ WSETEXIT(w, 0);
+ warning ("Using exit value 0 for terminated task");
+ }
+ }
+ store_waitstatus (ourstatus, w);
+ return inferior_pid;
+ }
+ }
+
+ /* Hmm. Check for exception, as it was not a notification.
+ exc_server() does an upcall to catch_exception_raise()
+ if this rpc is an exception. Further actions are decided
+ there.
+ */
+ if (! exc_server (&in_msg.header, &out_msg.header))
+ {
+
+ /* Not an exception, check for message.
+ *
+ * Messages don't come from the inferior, or if they
+ * do they better be asynchronous or it will hang.
+ */
+ if (gdb_message_server (&in_msg.header))
+ continue;
+
+ error ("Unrecognized message received in mach_really_wait");
+ }
+
+ /* Send the reply of the exception rpc to the suspended task */
+ ret = mach_msg_send (&out_msg.header);
+ CHK ("mach_msg_send (exc reply)", ret);
+
+ if (stopped_in_exception)
+ {
+ /* Get unix state. May be changed in mach3_exception_actions() */
+ wait3(&w, WNOHANG, 0);
+
+ mach3_exception_actions (&w, FALSE, "Task");
+
+ store_waitstatus (ourstatus, w);
+ return inferior_pid;
+ }
+ }
+}
+
+/* Called by macro DO_QUIT() in utils.c(quit).
+ * This is called just before calling error() to return to command level
+ */
+void
+mach3_quit ()
+{
+ int mid;
+ kern_return_t ret;
+
+ if (mach_really_waiting)
+ {
+ ret = task_suspend (inferior_task);
+
+ if (ret != KERN_SUCCESS)
+ {
+ warning ("Could not suspend task for interrupt: %s",
+ mach_error_string (ret));
+ mach_really_waiting = 0;
+ return;
+ }
+ }
+
+ must_suspend_thread = 0;
+ mach_really_waiting = 0;
+
+ mid = map_port_name_to_mid (current_thread, MACH_TYPE_THREAD);
+ if (mid == -1)
+ {
+ warning ("Selecting first existing kernel thread");
+ mid = 0;
+ }
+
+ current_thread = MACH_PORT_NULL; /* Force setup */
+ select_thread (inferior_task, mid, 1);
+
+ return;
+}
+
+#if 0
+/* bogus bogus bogus. It is NOT OK to quit out of target_wait. */
+
+/* If ^C is typed when we are waiting for a message
+ * and your Unix server is able to notice that we
+ * should quit now.
+ *
+ * Called by REQUEST_QUIT() from utils.c(request_quit)
+ */
+void
+mach3_request_quit ()
+{
+ if (mach_really_waiting)
+ immediate_quit = 1;
+}
+#endif
+
+/*
+ * Gdb message server.
+ * Currently implemented is the STOP message, that causes
+ * gdb to return to the command level like ^C had been typed from terminal.
+ */
+int
+gdb_message_server (InP)
+ mach_msg_header_t *InP;
+{
+ kern_return_t ret;
+ int mid;
+
+ if (InP->msgh_local_port == our_message_port)
+ {
+ /* A message coming to our_message_port. Check validity */
+ switch (InP->msgh_id) {
+
+ case GDB_MESSAGE_ID_STOP:
+ ret = task_suspend (inferior_task);
+ if (ret != KERN_SUCCESS)
+ warning ("Could not suspend task for stop message: %s",
+ mach_error_string (ret));
+
+ /* QUIT in mach_really_wait() loop. */
+ request_quit (0);
+ break;
+
+ default:
+ warning ("Invalid message id %d received, ignored.",
+ InP->msgh_id);
+ break;
+ }
+
+ return 1;
+ }
+
+ /* Message not handled by this server */
+ return 0;
+}
+
+/* NOTE: This is not an RPC call. It is a simpleroutine.
+ *
+ * This is not called from this gdb code.
+ *
+ * It may be called by another debugger to cause this
+ * debugger to enter command level:
+ *
+ * (gdb) set stop_inferior_gdb ()
+ * (gdb) continue
+ *
+ * External program "stop-gdb" implements this also.
+ */
+void
+stop_inferior_gdb ()
+{
+ kern_return_t ret;
+
+ /* Code generated by mig, with minor cleanups :-)
+ *
+ * simpleroutine stop_inferior_gdb (our_message_port : mach_port_t);
+ */
+
+ typedef struct {
+ mach_msg_header_t Head;
+ } Request;
+
+ Request Mess;
+
+ register Request *InP = &Mess;
+
+ InP->Head.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, 0);
+
+ /* msgh_size passed as argument */
+ InP->Head.msgh_remote_port = our_message_port;
+ InP->Head.msgh_local_port = MACH_PORT_NULL;
+ InP->Head.msgh_seqno = 0;
+ InP->Head.msgh_id = GDB_MESSAGE_ID_STOP;
+
+ ret = mach_msg (&InP->Head,
+ MACH_SEND_MSG|MACH_MSG_OPTION_NONE,
+ sizeof(Request),
+ 0,
+ MACH_PORT_NULL,
+ MACH_MSG_TIMEOUT_NONE,
+ MACH_PORT_NULL);
+}
+
+#ifdef THREAD_ALLOWED_TO_BREAK
+/*
+ * Return 1 if the MID specifies the thread that caused the
+ * last exception.
+ * Since catch_exception_raise() selects the thread causing
+ * the last exception to current_thread, we just check that
+ * it is selected and the last exception was a breakpoint.
+ */
+int
+mach_thread_for_breakpoint (mid)
+ int mid;
+{
+ int cmid = map_port_name_to_mid (current_thread, MACH_TYPE_THREAD);
+
+ if (mid < 0)
+ {
+ mid = map_slot_to_mid (-(mid+1), 0, 0);
+ if (mid < 0)
+ return 0; /* Don't stop, no such slot */
+ }
+
+ if (! mid || cmid == -1)
+ return 1; /* stop */
+
+ return cmid == mid && stop_exception == EXC_BREAKPOINT;
+}
+#endif /* THREAD_ALLOWED_TO_BREAK */
+
+#ifdef THREAD_PARSE_ID
+/*
+ * Map a thread id string (MID or a @SLOTNUMBER)
+ * to a thread-id.
+ *
+ * 0 matches all threads.
+ * Otherwise the meaning is defined only in this file.
+ * (mach_thread_for_breakpoint uses it)
+ *
+ * @@ This allows non-existent MIDs to be specified.
+ * It now also allows non-existent slots to be
+ * specified. (Slot numbers stored are negative,
+ * and the magnitude is one greater than the actual
+ * slot index. (Since 0 is reserved))
+ */
+int
+mach_thread_parse_id (arg)
+ char *arg;
+{
+ int mid;
+ if (arg == 0)
+ error ("thread id excpected");
+ mid = parse_thread_id (arg, 0, 1);
+
+ return mid;
+}
+#endif /* THREAD_PARSE_ID */
+
+#ifdef THREAD_OUTPUT_ID
+char *
+mach_thread_output_id (mid)
+ int mid;
+{
+ static char foobar [20];
+
+ if (mid > 0)
+ sprintf (foobar, "mid %d", mid);
+ else if (mid < 0)
+ sprintf (foobar, "@%d", -(mid+1));
+ else
+ sprintf (foobar, "*any thread*");
+
+ return foobar;
+}
+#endif /* THREAD_OUTPUT_ID */
+
+/* Called with hook PREPARE_TO_PROCEED() from infrun.c.
+ *
+ * If we have switched threads and stopped at breakpoint return 1 otherwise 0.
+ *
+ * if SELECT_IT is nonzero, reselect the thread that was active when
+ * we stopped at a breakpoint.
+ *
+ */
+
+mach3_prepare_to_proceed (select_it)
+ int select_it;
+{
+ if (stop_thread &&
+ stop_thread != current_thread &&
+ stop_exception == EXC_BREAKPOINT)
+ {
+ int mid;
+
+ if (! select_it)
+ return 1;
+
+ mid = switch_to_thread (stop_thread);
+
+ return 1;
+ }
+
+ return 0;
+}
+
+/* this stuff here is an upcall via libmach/excServer.c
+ and mach_really_wait which does the actual upcall.
+
+ The code will pass the exception to the inferior if:
+
+ - The task that signaled is not the inferior task
+ (e.g. when debugging another debugger)
+
+ - The user has explicitely requested to pass on the exceptions.
+ (e.g to the default unix exception handler, which maps
+ exceptions to signals, or the user has her own exception handler)
+
+ - If the thread that signaled is being single-stepped and it
+ has set it's own exception port and the exception is not
+ EXC_BREAKPOINT. (Maybe this is not desirable?)
+ */
+
+kern_return_t
+catch_exception_raise (port, thread, task, exception, code, subcode)
+ mach_port_t port;
+ thread_t thread;
+ task_t task;
+ int exception, code, subcode;
+{
+ kern_return_t ret;
+ boolean_t signal_thread;
+ int mid = map_port_name_to_mid (thread, MACH_TYPE_THREAD);
+
+ if (! MACH_PORT_VALID (thread))
+ {
+ /* If the exception was sent and thread dies before we
+ receive it, THREAD will be MACH_PORT_DEAD
+ */
+
+ current_thread = thread = MACH_PORT_NULL;
+ error ("Received exception from nonexistent thread");
+ }
+
+ /* Check if the task died in transit.
+ * @@ Isn't the thread also invalid in such case?
+ */
+ if (! MACH_PORT_VALID (task))
+ {
+ current_thread = thread = MACH_PORT_NULL;
+ error ("Received exception from nonexistent task");
+ }
+
+ if (exception < 0 || exception > MAX_EXCEPTION)
+ fatal ("catch_exception_raise: unknown exception code %d thread %d",
+ exception,
+ mid);
+
+ if (! MACH_PORT_VALID (inferior_task))
+ error ("got an exception, but inferior_task is null or dead");
+
+ stop_exception = exception;
+ stop_code = code;
+ stop_subcode = subcode;
+ stop_thread = thread;
+
+ signal_thread = exception != EXC_BREAKPOINT &&
+ port == singlestepped_thread_port &&
+ MACH_PORT_VALID (thread_saved_exception_port);
+
+ /* If it was not our inferior or if we want to forward
+ * the exception to the inferior's handler, do it here
+ *
+ * Note: If you have forwarded EXC_BREAKPOINT I trust you know why.
+ */
+ if (task != inferior_task ||
+ signal_thread ||
+ exception_map [exception].forward)
+ {
+ mach_port_t eport = inferior_old_exception_port;
+
+ if (signal_thread)
+ {
+ /*
+ GDB now forwards the exeption to thread's original handler,
+ since the user propably knows what he is doing.
+ Give a message, though.
+ */
+
+ mach3_exception_actions ((WAITTYPE *)NULL, TRUE, "Thread");
+ eport = thread_saved_exception_port;
+ }
+
+ /* Send the exception to the original handler */
+ ret = exception_raise (eport,
+ thread,
+ task,
+ exception,
+ code,
+ subcode);
+
+ (void) mach_port_deallocate (mach_task_self (), task);
+ (void) mach_port_deallocate (mach_task_self (), thread);
+
+ /* If we come here, we don't want to trace any more, since we
+ * will never stop for tracing anyway.
+ */
+ discard_single_step (thread);
+
+ /* Do not stop the inferior */
+ return ret;
+ }
+
+ /* Now gdb handles the exception */
+ stopped_in_exception = TRUE;
+
+ ret = task_suspend (task);
+ CHK ("Error suspending inferior after exception", ret);
+
+ must_suspend_thread = 0;
+
+ if (current_thread != thread)
+ {
+ if (MACH_PORT_VALID (singlestepped_thread_port))
+ /* Cleanup discards single stepping */
+ error ("Exception from thread %d while singlestepping thread %d",
+ mid,
+ map_port_name_to_mid (current_thread, MACH_TYPE_THREAD));
+
+ /* Then select the thread that caused the exception */
+ if (select_thread (inferior_task, mid, 0) != KERN_SUCCESS)
+ error ("Could not select thread %d causing exception", mid);
+ else
+ warning ("Gdb selected thread %d", mid);
+ }
+
+ /* If we receive an exception that is not breakpoint
+ * exception, we interrupt the single step and return to
+ * debugger. Trace condition is cleared.
+ */
+ if (MACH_PORT_VALID (singlestepped_thread_port))
+ {
+ if (stop_exception != EXC_BREAKPOINT)
+ warning ("Single step interrupted by exception");
+ else if (port == singlestepped_thread_port)
+ {
+ /* Single step exception occurred, remove trace bit
+ * and return to gdb.
+ */
+ if (! MACH_PORT_VALID (current_thread))
+ error ("Single stepped thread is not valid");
+
+ /* Resume threads, but leave the task suspended */
+ resume_all_threads (0);
+ }
+ else
+ warning ("Breakpoint while single stepping?");
+
+ discard_single_step (current_thread);
+ }
+
+ (void) mach_port_deallocate (mach_task_self (), task);
+ (void) mach_port_deallocate (mach_task_self (), thread);
+
+ return KERN_SUCCESS;
+}
+
+int
+port_valid (port, mask)
+ mach_port_t port;
+ int mask;
+{
+ kern_return_t ret;
+ mach_port_type_t type;
+
+ ret = mach_port_type (mach_task_self (),
+ port,
+ &type);
+ if (ret != KERN_SUCCESS || (type & mask) != mask)
+ return 0;
+ return 1;
+}
+
+/* @@ No vm read cache implemented yet */
+boolean_t vm_read_cache_valid = FALSE;
+
+/*
+ * Read inferior task's LEN bytes from ADDR and copy it to MYADDR
+ * in gdb's address space.
+ *
+ * Return 0 on failure; number of bytes read otherwise.
+ */
+int
+mach3_read_inferior (addr, myaddr, length)
+ CORE_ADDR addr;
+ char *myaddr;
+ int length;
+{
+ kern_return_t ret;
+ vm_address_t low_address = (vm_address_t) trunc_page (addr);
+ vm_size_t aligned_length =
+ (vm_size_t) round_page (addr+length) - low_address;
+ pointer_t copied_memory;
+ int copy_count;
+
+ /* Get memory from inferior with page aligned addresses */
+ ret = vm_read (inferior_task,
+ low_address,
+ aligned_length,
+ &copied_memory,
+ &copy_count);
+ if (ret != KERN_SUCCESS)
+ {
+ /* the problem is that the inferior might be killed for whatever reason
+ * before we go to mach_really_wait. This is one place that ought to
+ * catch many of those errors.
+ * @@ A better fix would be to make all external events to GDB
+ * to arrive via a SINGLE port set. (Including user input!)
+ */
+
+ if (! port_valid (inferior_task, MACH_PORT_TYPE_SEND))
+ {
+ m3_kill_inferior ();
+ error ("Inferior killed (task port invalid)");
+ }
+ else
+ {
+#ifdef OSF
+ extern int errno;
+ /* valprint.c gives nicer format if this does not
+ screw it. Eamonn seems to like this, so I enable
+ it if OSF is defined...
+ */
+ warning ("[read inferior %x failed: %s]",
+ addr, mach_error_string (ret));
+ errno = 0;
+#endif
+ return 0;
+ }
+ }
+
+ memcpy (myaddr, (char *)addr - low_address + copied_memory, length);
+
+ ret = vm_deallocate (mach_task_self (),
+ copied_memory,
+ copy_count);
+ CHK("mach3_read_inferior vm_deallocate failed", ret);
+
+ return length;
+}
+
+#ifdef __STDC__
+#define CHK_GOTO_OUT(str,ret) \
+ do if (ret != KERN_SUCCESS) { errstr = #str; goto out; } while(0)
+#else
+#define CHK_GOTO_OUT(str,ret) \
+ do if (ret != KERN_SUCCESS) { errstr = str; goto out; } while(0)
+#endif
+
+struct vm_region_list {
+ struct vm_region_list *next;
+ vm_prot_t protection;
+ vm_address_t start;
+ vm_size_t length;
+};
+
+struct obstack region_obstack;
+
+/*
+ * Write inferior task's LEN bytes from ADDR and copy it to MYADDR
+ * in gdb's address space.
+ */
+int
+mach3_write_inferior (addr, myaddr, length)
+ CORE_ADDR addr;
+ char *myaddr;
+ int length;
+{
+ kern_return_t ret;
+ vm_address_t low_address = (vm_address_t) trunc_page (addr);
+ vm_size_t aligned_length =
+ (vm_size_t) round_page (addr+length) - low_address;
+ pointer_t copied_memory;
+ int copy_count;
+ int deallocate = 0;
+
+ char *errstr = "Bug in mach3_write_inferior";
+
+ struct vm_region_list *region_element;
+ struct vm_region_list *region_head = (struct vm_region_list *)NULL;
+
+ /* Get memory from inferior with page aligned addresses */
+ ret = vm_read (inferior_task,
+ low_address,
+ aligned_length,
+ &copied_memory,
+ &copy_count);
+ CHK_GOTO_OUT ("mach3_write_inferior vm_read failed", ret);
+
+ deallocate++;
+
+ memcpy ((char *)addr - low_address + copied_memory, myaddr, length);
+
+ obstack_init (&region_obstack);
+
+ /* Do writes atomically.
+ * First check for holes and unwritable memory.
+ */
+ {
+ vm_size_t remaining_length = aligned_length;
+ vm_address_t region_address = low_address;
+
+ struct vm_region_list *scan;
+
+ while(region_address < low_address + aligned_length)
+ {
+ vm_prot_t protection;
+ vm_prot_t max_protection;
+ vm_inherit_t inheritance;
+ boolean_t shared;
+ mach_port_t object_name;
+ vm_offset_t offset;
+ vm_size_t region_length = remaining_length;
+ vm_address_t old_address = region_address;
+
+ ret = vm_region (inferior_task,
+ &region_address,
+ &region_length,
+ &protection,
+ &max_protection,
+ &inheritance,
+ &shared,
+ &object_name,
+ &offset);
+ CHK_GOTO_OUT ("vm_region failed", ret);
+
+ /* Check for holes in memory */
+ if (old_address != region_address)
+ {
+ warning ("No memory at 0x%x. Nothing written",
+ old_address);
+ ret = KERN_SUCCESS;
+ length = 0;
+ goto out;
+ }
+
+ if (!(max_protection & VM_PROT_WRITE))
+ {
+ warning ("Memory at address 0x%x is unwritable. Nothing written",
+ old_address);
+ ret = KERN_SUCCESS;
+ length = 0;
+ goto out;
+ }
+
+ /* Chain the regions for later use */
+ region_element =
+ (struct vm_region_list *)
+ obstack_alloc (&region_obstack, sizeof (struct vm_region_list));
+
+ region_element->protection = protection;
+ region_element->start = region_address;
+ region_element->length = region_length;
+
+ /* Chain the regions along with protections */
+ region_element->next = region_head;
+ region_head = region_element;
+
+ region_address += region_length;
+ remaining_length = remaining_length - region_length;
+ }
+
+ /* If things fail after this, we give up.
+ * Somebody is messing up inferior_task's mappings.
+ */
+
+ /* Enable writes to the chained vm regions */
+ for (scan = region_head; scan; scan = scan->next)
+ {
+ boolean_t protection_changed = FALSE;
+
+ if (!(scan->protection & VM_PROT_WRITE))
+ {
+ ret = vm_protect (inferior_task,
+ scan->start,
+ scan->length,
+ FALSE,
+ scan->protection | VM_PROT_WRITE);
+ CHK_GOTO_OUT ("vm_protect: enable write failed", ret);
+ }
+ }
+
+ ret = vm_write (inferior_task,
+ low_address,
+ copied_memory,
+ aligned_length);
+ CHK_GOTO_OUT ("vm_write failed", ret);
+
+ /* Set up the original region protections, if they were changed */
+ for (scan = region_head; scan; scan = scan->next)
+ {
+ boolean_t protection_changed = FALSE;
+
+ if (!(scan->protection & VM_PROT_WRITE))
+ {
+ ret = vm_protect (inferior_task,
+ scan->start,
+ scan->length,
+ FALSE,
+ scan->protection);
+ CHK_GOTO_OUT ("vm_protect: enable write failed", ret);
+ }
+ }
+ }
+
+ out:
+ if (deallocate)
+ {
+ obstack_free (&region_obstack, 0);
+
+ (void) vm_deallocate (mach_task_self (),
+ copied_memory,
+ copy_count);
+ }
+
+ if (ret != KERN_SUCCESS)
+ {
+ warning ("%s %s", errstr, mach_error_string (ret));
+ return 0;
+ }
+
+ return length;
+}
+
+/* Return 0 on failure, number of bytes handled otherwise. */
+static int
+m3_xfer_memory (memaddr, myaddr, len, write, target)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+ int write;
+ struct target_ops *target; /* IGNORED */
+{
+ int result;
+
+ if (write)
+ result = mach3_write_inferior (memaddr, myaddr, len);
+ else
+ result = mach3_read_inferior (memaddr, myaddr, len);
+
+ return result;
+}
+
+
+static char *
+translate_state(state)
+int state;
+{
+ switch (state) {
+ case TH_STATE_RUNNING: return("R");
+ case TH_STATE_STOPPED: return("S");
+ case TH_STATE_WAITING: return("W");
+ case TH_STATE_UNINTERRUPTIBLE: return("U");
+ case TH_STATE_HALTED: return("H");
+ default: return("?");
+ }
+}
+
+static char *
+translate_cstate (state)
+ int state;
+{
+ switch (state)
+ {
+ case CPROC_RUNNING: return "R";
+ case CPROC_SWITCHING: return "S";
+ case CPROC_BLOCKED: return "B";
+ case CPROC_CONDWAIT: return "C";
+ case CPROC_CONDWAIT|CPROC_SWITCHING: return "CS";
+ default: return "?";
+ }
+}
+
+/* type == MACH_MSG_TYPE_COPY_SEND || type == MACH_MSG_TYPE_MAKE_SEND */
+
+mach_port_t /* no mach_port_name_t found in include files. */
+map_inferior_port_name (inferior_name, type)
+ mach_port_t inferior_name;
+ mach_msg_type_name_t type;
+{
+ kern_return_t ret;
+ mach_msg_type_name_t acquired;
+ mach_port_t iport;
+
+ ret = mach_port_extract_right (inferior_task,
+ inferior_name,
+ type,
+ &iport,
+ &acquired);
+ CHK("mach_port_extract_right (map_inferior_port_name)", ret);
+
+ if (acquired != MACH_MSG_TYPE_PORT_SEND)
+ error("Incorrect right extracted, (map_inferior_port_name)");
+
+ ret = mach_port_deallocate (mach_task_self (),
+ iport);
+ CHK ("Deallocating mapped port (map_inferior_port_name)", ret);
+
+ return iport;
+}
+
+/*
+ * Naming convention:
+ * Always return user defined name if found.
+ * _K == A kernel thread with no matching CPROC
+ * _C == A cproc with no current cthread
+ * _t == A cthread with no user defined name
+ *
+ * The digits that follow the _names are the SLOT number of the
+ * kernel thread if there is such a thing, otherwise just a negation
+ * of the sequential number of such cprocs.
+ */
+
+static char buf[7];
+
+static char *
+get_thread_name (one_cproc, id)
+ gdb_thread_t one_cproc;
+ int id;
+{
+ if (one_cproc)
+ if (one_cproc->cthread == NULL)
+ {
+ /* cproc not mapped to any cthread */
+ sprintf(buf, "_C%d", id);
+ }
+ else if (! one_cproc->cthread->name)
+ {
+ /* cproc and cthread, but no name */
+ sprintf(buf, "_t%d", id);
+ }
+ else
+ return (char *)(one_cproc->cthread->name);
+ else
+ {
+ if (id < 0)
+ warning ("Inconsistency in thread name id %d", id);
+
+ /* Kernel thread without cproc */
+ sprintf(buf, "_K%d", id);
+ }
+
+ return buf;
+}
+
+int
+fetch_thread_info (task, mthreads_out)
+ mach_port_t task;
+ gdb_thread_t *mthreads_out; /* out */
+{
+ kern_return_t ret;
+ thread_array_t th_table;
+ int th_count;
+ gdb_thread_t mthreads = NULL;
+ int index;
+
+ ret = task_threads (task, &th_table, &th_count);
+ if (ret != KERN_SUCCESS)
+ {
+ warning ("Error getting inferior's thread list:%s",
+ mach_error_string(ret));
+ m3_kill_inferior ();
+ return -1;
+ }
+
+ mthreads = (gdb_thread_t)
+ obstack_alloc
+ (cproc_obstack,
+ th_count * sizeof (struct gdb_thread));
+
+ for (index = 0; index < th_count; index++)
+ {
+ thread_t saved_thread = MACH_PORT_NULL;
+ int mid;
+
+ if (must_suspend_thread)
+ setup_thread (th_table[ index ], 1);
+
+ if (th_table[index] != current_thread)
+ {
+ saved_thread = current_thread;
+
+ mid = switch_to_thread (th_table[ index ]);
+ }
+
+ mthreads[index].name = th_table[index];
+ mthreads[index].cproc = NULL; /* map_cprocs_to_kernel_threads() */
+ mthreads[index].in_emulator = FALSE;
+ mthreads[index].slotid = index;
+
+ mthreads[index].sp = read_register (SP_REGNUM);
+ mthreads[index].fp = read_register (FP_REGNUM);
+ mthreads[index].pc = read_pc ();
+
+ if (MACH_PORT_VALID (saved_thread))
+ mid = switch_to_thread (saved_thread);
+
+ if (must_suspend_thread)
+ setup_thread (th_table[ index ], 0);
+ }
+
+ consume_send_rights (th_table, th_count);
+ ret = vm_deallocate (mach_task_self(), (vm_address_t)th_table,
+ (th_count * sizeof(mach_port_t)));
+ if (ret != KERN_SUCCESS)
+ {
+ warning ("Error trying to deallocate thread list : %s",
+ mach_error_string (ret));
+ }
+
+ *mthreads_out = mthreads;
+
+ return th_count;
+}
+
+
+/*
+ * Current emulator always saves the USP on top of
+ * emulator stack below struct emul_stack_top stuff.
+ */
+CORE_ADDR
+fetch_usp_from_emulator_stack (sp)
+ CORE_ADDR sp;
+{
+ CORE_ADDR stack_pointer;
+
+ sp = (sp & ~(EMULATOR_STACK_SIZE-1)) +
+ EMULATOR_STACK_SIZE - sizeof (struct emul_stack_top);
+
+ if (mach3_read_inferior (sp,
+ &stack_pointer,
+ sizeof (CORE_ADDR)) != sizeof (CORE_ADDR))
+ {
+ warning ("Can't read user sp from emulator stack address 0x%x", sp);
+ return 0;
+ }
+
+ return stack_pointer;
+}
+
+#ifdef MK67
+
+/* get_emulation_vector() interface was changed after mk67 */
+#define EMUL_VECTOR_COUNT 400 /* Value does not matter too much */
+
+#endif /* MK67 */
+
+/* Check if the emulator exists at task's address space.
+ */
+boolean_t
+have_emulator_p (task)
+ task_t task;
+{
+ kern_return_t ret;
+#ifndef EMUL_VECTOR_COUNT
+ vm_offset_t *emulation_vector;
+ int n;
+#else
+ vm_offset_t emulation_vector[ EMUL_VECTOR_COUNT ];
+ int n = EMUL_VECTOR_COUNT;
+#endif
+ int i;
+ int vector_start;
+
+ ret = task_get_emulation_vector (task,
+ &vector_start,
+#ifndef EMUL_VECTOR_COUNT
+ &emulation_vector,
+#else
+ emulation_vector,
+#endif
+ &n);
+ CHK("task_get_emulation_vector", ret);
+ xx_debug ("%d vectors from %d at 0x%08x\n",
+ n, vector_start, emulation_vector);
+
+ for(i = 0; i < n; i++)
+ {
+ vm_offset_t entry = emulation_vector [i];
+
+ if (EMULATOR_BASE <= entry && entry <= EMULATOR_END)
+ return TRUE;
+ else if (entry)
+ {
+ static boolean_t informed = FALSE;
+ if (!informed)
+ {
+ warning("Emulation vector address 0x08%x outside emulator space",
+ entry);
+ informed = TRUE;
+ }
+ }
+ }
+ return FALSE;
+}
+
+/* Map cprocs to kernel threads and vice versa. */
+
+void
+map_cprocs_to_kernel_threads (cprocs, mthreads, thread_count)
+ gdb_thread_t cprocs;
+ gdb_thread_t mthreads;
+ int thread_count;
+{
+ int index;
+ gdb_thread_t scan;
+ boolean_t all_mapped = TRUE;
+ LONGEST stack_base;
+ LONGEST stack_size;
+
+ for (scan = cprocs; scan; scan = scan->next)
+ {
+ /* Default to: no kernel thread for this cproc */
+ scan->reverse_map = -1;
+
+ /* Check if the cproc is found by its stack */
+ for (index = 0; index < thread_count; index++)
+ {
+ stack_base =
+ extract_signed_integer (scan->raw_cproc + CPROC_BASE_OFFSET,
+ CPROC_BASE_SIZE);
+ stack_size =
+ extract_signed_integer (scan->raw_cproc + CPROC_SIZE_OFFSET,
+ CPROC_SIZE_SIZE);
+ if ((mthreads + index)->sp > stack_base &&
+ (mthreads + index)->sp <= stack_base + stack_size)
+ {
+ (mthreads + index)->cproc = scan;
+ scan->reverse_map = index;
+ break;
+ }
+ }
+ all_mapped &= (scan->reverse_map != -1);
+ }
+
+ /* Check for threads that are currently in the emulator.
+ * If so, they have a different stack, and the still unmapped
+ * cprocs may well get mapped to these threads.
+ *
+ * If:
+ * - cproc stack does not match any kernel thread stack pointer
+ * - there is at least one extra kernel thread
+ * that has no cproc mapped above.
+ * - some kernel thread stack pointer points to emulator space
+ * then we find the user stack pointer saved in the emulator
+ * stack, and try to map that to the cprocs.
+ *
+ * Also set in_emulator for kernel threads.
+ */
+
+ if (emulator_present)
+ {
+ for (index = 0; index < thread_count; index++)
+ {
+ CORE_ADDR emul_sp;
+ CORE_ADDR usp;
+
+ gdb_thread_t mthread = (mthreads+index);
+ emul_sp = mthread->sp;
+
+ if (mthread->cproc == NULL &&
+ EMULATOR_BASE <= emul_sp && emul_sp <= EMULATOR_END)
+ {
+ mthread->in_emulator = emulator_present;
+
+ if (!all_mapped && cprocs)
+ {
+ usp = fetch_usp_from_emulator_stack (emul_sp);
+
+ /* @@ Could be more accurate */
+ if (! usp)
+ error ("Zero stack pointer read from emulator?");
+
+ /* Try to match this stack pointer to the cprocs that
+ * don't yet have a kernel thread.
+ */
+ for (scan = cprocs; scan; scan = scan->next)
+ {
+
+ /* Check is this unmapped CPROC stack contains
+ * the user stack pointer saved in the
+ * emulator.
+ */
+ if (scan->reverse_map == -1)
+ {
+ stack_base =
+ extract_signed_integer
+ (scan->raw_cproc + CPROC_BASE_OFFSET,
+ CPROC_BASE_SIZE);
+ stack_size =
+ extract_signed_integer
+ (scan->raw_cproc + CPROC_SIZE_OFFSET,
+ CPROC_SIZE_SIZE);
+ if (usp > stack_base &&
+ usp <= stack_base + stack_size)
+ {
+ mthread->cproc = scan;
+ scan->reverse_map = index;
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+/*
+ * Format of the thread_list command
+ *
+ * slot mid sel name emul ks susp cstate wired address
+ */
+#define TL_FORMAT "%-2.2s %5d%c %-10.10s %1.1s%s%-5.5s %-2.2s %-5.5s "
+
+#define TL_HEADER "\n@ MID Name KState CState Where\n"
+
+void
+print_tl_address (stream, pc)
+ GDB_FILE *stream;
+ CORE_ADDR pc;
+{
+ if (! lookup_minimal_symbol_by_pc (pc))
+ fprintf_filtered (stream, local_hex_format(), pc);
+ else
+ {
+ extern int addressprint;
+ extern int asm_demangle;
+
+ int store = addressprint;
+ addressprint = 0;
+ print_address_symbolic (pc, stream, asm_demangle, "");
+ addressprint = store;
+ }
+}
+
+/* For thread names, but also for gdb_message_port external name */
+#define MAX_NAME_LEN 50
+
+/* Returns the address of variable NAME or 0 if not found */
+CORE_ADDR
+lookup_address_of_variable (name)
+ char *name;
+{
+ struct symbol *sym;
+ CORE_ADDR symaddr = 0;
+ struct minimal_symbol *msymbol;
+
+ sym = lookup_symbol (name,
+ (struct block *)NULL,
+ VAR_NAMESPACE,
+ (int *)NULL,
+ (struct symtab **)NULL);
+
+ if (sym)
+ symaddr = SYMBOL_VALUE (sym);
+
+ if (! symaddr)
+ {
+ msymbol = lookup_minimal_symbol (name, NULL, NULL);
+
+ if (msymbol && msymbol->type == mst_data)
+ symaddr = SYMBOL_VALUE_ADDRESS (msymbol);
+ }
+
+ return symaddr;
+}
+
+static gdb_thread_t
+get_cprocs()
+{
+ gdb_thread_t cproc_head;
+ gdb_thread_t cproc_copy;
+ CORE_ADDR their_cprocs;
+ char *buf[TARGET_PTR_BIT / HOST_CHAR_BIT];
+ char *name;
+ cthread_t cthread;
+ CORE_ADDR symaddr;
+
+ symaddr = lookup_address_of_variable ("cproc_list");
+
+ if (! symaddr)
+ {
+ /* cproc_list is not in a file compiled with debugging
+ symbols, but don't give up yet */
+
+ symaddr = lookup_address_of_variable ("cprocs");
+
+ if (symaddr)
+ {
+ static int informed = 0;
+ if (!informed)
+ {
+ informed++;
+ warning ("Your program is loaded with an old threads library.");
+ warning ("GDB does not know the old form of threads");
+ warning ("so things may not work.");
+ }
+ }
+ }
+
+ /* Stripped or no -lthreads loaded or "cproc_list" is in wrong segment. */
+ if (! symaddr)
+ return NULL;
+
+ /* Get the address of the first cproc in the task */
+ if (!mach3_read_inferior (symaddr,
+ buf,
+ TARGET_PTR_BIT / HOST_CHAR_BIT))
+ error ("Can't read cproc master list at address (0x%x).", symaddr);
+ their_cprocs = extract_address (buf, TARGET_PTR_BIT / HOST_CHAR_BIT);
+
+ /* Scan the CPROCs in the task.
+ CPROCs are chained with LIST field, not NEXT field, which
+ chains mutexes, condition variables and queues */
+
+ cproc_head = NULL;
+
+ while (their_cprocs != (CORE_ADDR)0)
+ {
+ CORE_ADDR cproc_copy_incarnation;
+ cproc_copy = (gdb_thread_t) obstack_alloc (cproc_obstack,
+ sizeof (struct gdb_thread));
+
+ if (!mach3_read_inferior (their_cprocs,
+ &cproc_copy->raw_cproc[0],
+ CPROC_SIZE))
+ error("Can't read next cproc at 0x%x.", their_cprocs);
+
+ their_cprocs =
+ extract_address (cproc_copy->raw_cproc + CPROC_LIST_OFFSET,
+ CPROC_LIST_SIZE);
+ cproc_copy_incarnation =
+ extract_address (cproc_copy->raw_cproc + CPROC_INCARNATION_OFFSET,
+ CPROC_INCARNATION_SIZE);
+
+ if (cproc_copy_incarnation == (CORE_ADDR)0)
+ cproc_copy->cthread = NULL;
+ else
+ {
+ /* This CPROC has an attached CTHREAD. Get its name */
+ cthread = (cthread_t)obstack_alloc (cproc_obstack,
+ sizeof(struct cthread));
+
+ if (!mach3_read_inferior (cproc_copy_incarnation,
+ cthread,
+ sizeof(struct cthread)))
+ error("Can't read next thread at 0x%x.",
+ cproc_copy_incarnation);
+
+ cproc_copy->cthread = cthread;
+
+ if (cthread->name)
+ {
+ name = (char *) obstack_alloc (cproc_obstack, MAX_NAME_LEN);
+
+ if (!mach3_read_inferior(cthread->name, name, MAX_NAME_LEN))
+ error("Can't read next thread's name at 0x%x.", cthread->name);
+
+ cthread->name = name;
+ }
+ }
+
+ /* insert in front */
+ cproc_copy->next = cproc_head;
+ cproc_head = cproc_copy;
+ }
+ return cproc_head;
+}
+
+#ifndef FETCH_CPROC_STATE
+/*
+ * Check if your machine does not grok the way this routine
+ * fetches the FP,PC and SP of a cproc that is not
+ * currently attached to any kernel thread (e.g. its cproc.context
+ * field points to the place in stack where the context
+ * is saved).
+ *
+ * If it doesn't, define your own routine.
+ */
+#define FETCH_CPROC_STATE(mth) mach3_cproc_state (mth)
+
+int
+mach3_cproc_state (mthread)
+ gdb_thread_t mthread;
+{
+ int context;
+
+ if (! mthread || !mthread->cproc)
+ return -1;
+
+ context = extract_signed_integer
+ (mthread->cproc->raw_cproc + CPROC_CONTEXT_OFFSET,
+ CPROC_CONTEXT_SIZE);
+ if (context == 0)
+ return -1;
+
+ mthread->sp = context + MACHINE_CPROC_SP_OFFSET;
+
+ if (mach3_read_inferior (context + MACHINE_CPROC_PC_OFFSET,
+ &mthread->pc,
+ sizeof (CORE_ADDR)) != sizeof (CORE_ADDR))
+ {
+ warning ("Can't read cproc pc from inferior");
+ return -1;
+ }
+
+ if (mach3_read_inferior (context + MACHINE_CPROC_FP_OFFSET,
+ &mthread->fp,
+ sizeof (CORE_ADDR)) != sizeof (CORE_ADDR))
+ {
+ warning ("Can't read cproc fp from inferior");
+ return -1;
+ }
+
+ return 0;
+}
+#endif /* FETCH_CPROC_STATE */
+
+
+void
+thread_list_command()
+{
+ thread_basic_info_data_t ths;
+ int thread_count;
+ gdb_thread_t cprocs;
+ gdb_thread_t scan;
+ int index;
+ char *name;
+ char selected;
+ char *wired;
+ int infoCnt;
+ kern_return_t ret;
+ mach_port_t mid_or_port;
+ gdb_thread_t their_threads;
+ gdb_thread_t kthread;
+
+ int neworder = 1;
+
+ char *fmt = "There are %d kernel threads in task %d.\n";
+
+ int tmid = map_port_name_to_mid (inferior_task, MACH_TYPE_TASK);
+
+ MACH_ERROR_NO_INFERIOR;
+
+ thread_count = fetch_thread_info (inferior_task,
+ &their_threads);
+ if (thread_count == -1)
+ return;
+
+ if (thread_count == 1)
+ fmt = "There is %d kernel thread in task %d.\n";
+
+ printf_filtered (fmt, thread_count, tmid);
+
+ puts_filtered (TL_HEADER);
+
+ cprocs = get_cprocs();
+
+ map_cprocs_to_kernel_threads (cprocs, their_threads, thread_count);
+
+ for (scan = cprocs; scan; scan = scan->next)
+ {
+ int mid;
+ char buf[10];
+ char slot[3];
+ int cproc_state =
+ extract_signed_integer
+ (scan->raw_cproc + CPROC_STATE_OFFSET, CPROC_STATE_SIZE);
+
+ selected = ' ';
+
+ /* a wired cproc? */
+ wired = (extract_address (scan->raw_cproc + CPROC_WIRED_OFFSET,
+ CPROC_WIRED_SIZE)
+ ? "wired" : "");
+
+ if (scan->reverse_map != -1)
+ kthread = (their_threads + scan->reverse_map);
+ else
+ kthread = NULL;
+
+ if (kthread)
+ {
+ /* These cprocs have a kernel thread */
+
+ mid = map_port_name_to_mid (kthread->name, MACH_TYPE_THREAD);
+
+ infoCnt = THREAD_BASIC_INFO_COUNT;
+
+ ret = thread_info (kthread->name,
+ THREAD_BASIC_INFO,
+ (thread_info_t)&ths,
+ &infoCnt);
+
+ if (ret != KERN_SUCCESS)
+ {
+ warning ("Unable to get basic info on thread %d : %s",
+ mid,
+ mach_error_string (ret));
+ continue;
+ }
+
+ /* Who is the first to have more than 100 threads */
+ sprintf (slot, "%d", kthread->slotid%100);
+
+ if (kthread->name == current_thread)
+ selected = '*';
+
+ if (ths.suspend_count)
+ sprintf (buf, "%d", ths.suspend_count);
+ else
+ buf[0] = '\000';
+
+#if 0
+ if (ths.flags & TH_FLAGS_SWAPPED)
+ strcat (buf, "S");
+#endif
+
+ if (ths.flags & TH_FLAGS_IDLE)
+ strcat (buf, "I");
+
+ printf_filtered (TL_FORMAT,
+ slot,
+ mid,
+ selected,
+ get_thread_name (scan, kthread->slotid),
+ kthread->in_emulator ? "E" : "",
+ translate_state (ths.run_state),
+ buf,
+ translate_cstate (cproc_state),
+ wired);
+ print_tl_address (gdb_stdout, kthread->pc);
+ }
+ else
+ {
+ /* These cprocs don't have a kernel thread.
+ * find out the calling frame with
+ * FETCH_CPROC_STATE.
+ */
+
+ struct gdb_thread state;
+
+#if 0
+ /* jtv -> emcmanus: why do you want this here? */
+ if (scan->incarnation == NULL)
+ continue; /* EMcM */
+#endif
+
+ printf_filtered (TL_FORMAT,
+ "-",
+ -neworder, /* Pseudo MID */
+ selected,
+ get_thread_name (scan, -neworder),
+ "",
+ "-", /* kernel state */
+ "",
+ translate_cstate (cproc_state),
+ "");
+ state.cproc = scan;
+
+ if (FETCH_CPROC_STATE (&state) == -1)
+ puts_filtered ("???");
+ else
+ print_tl_address (gdb_stdout, state.pc);
+
+ neworder++;
+ }
+ puts_filtered ("\n");
+ }
+
+ /* Scan for kernel threads without cprocs */
+ for (index = 0; index < thread_count; index++)
+ {
+ if (! their_threads[index].cproc)
+ {
+ int mid;
+
+ char buf[10];
+ char slot[3];
+
+ mach_port_t name = their_threads[index].name;
+
+ mid = map_port_name_to_mid (name, MACH_TYPE_THREAD);
+
+ infoCnt = THREAD_BASIC_INFO_COUNT;
+
+ ret = thread_info(name,
+ THREAD_BASIC_INFO,
+ (thread_info_t)&ths,
+ &infoCnt);
+
+ if (ret != KERN_SUCCESS)
+ {
+ warning ("Unable to get basic info on thread %d : %s",
+ mid,
+ mach_error_string (ret));
+ continue;
+ }
+
+ sprintf (slot, "%d", index%100);
+
+ if (name == current_thread)
+ selected = '*';
+ else
+ selected = ' ';
+
+ if (ths.suspend_count)
+ sprintf (buf, "%d", ths.suspend_count);
+ else
+ buf[0] = '\000';
+
+#if 0
+ if (ths.flags & TH_FLAGS_SWAPPED)
+ strcat (buf, "S");
+#endif
+
+ if (ths.flags & TH_FLAGS_IDLE)
+ strcat (buf, "I");
+
+ printf_filtered (TL_FORMAT,
+ slot,
+ mid,
+ selected,
+ get_thread_name (NULL, index),
+ their_threads[index].in_emulator ? "E" : "",
+ translate_state (ths.run_state),
+ buf,
+ "", /* No cproc state */
+ ""); /* Can't be wired */
+ print_tl_address (gdb_stdout, their_threads[index].pc);
+ puts_filtered ("\n");
+ }
+ }
+
+ obstack_free (cproc_obstack, 0);
+ obstack_init (cproc_obstack);
+}
+
+void
+thread_select_command(args, from_tty)
+ char *args;
+ int from_tty;
+{
+ int mid;
+ thread_array_t thread_list;
+ int thread_count;
+ kern_return_t ret;
+ int is_slot = 0;
+
+ MACH_ERROR_NO_INFERIOR;
+
+ if (!args)
+ error_no_arg ("MID or @SLOTNUMBER to specify a thread to select");
+
+ while (*args == ' ' || *args == '\t')
+ args++;
+
+ if (*args == '@')
+ {
+ is_slot++;
+ args++;
+ }
+
+ mid = atoi(args);
+
+ if (mid == 0)
+ if (!is_slot || *args != '0') /* Rudimentary checks */
+ error ("You must select threads by MID or @SLOTNUMBER");
+
+ if (select_thread (inferior_task, mid, is_slot?2:1) != KERN_SUCCESS)
+ return;
+
+ if (from_tty)
+ printf_filtered ("Thread %d selected\n",
+ is_slot ? map_port_name_to_mid (current_thread,
+ MACH_TYPE_THREAD) : mid);
+}
+
+thread_trace (thread, set)
+mach_port_t thread;
+boolean_t set;
+{
+ int flavor = TRACE_FLAVOR;
+ unsigned int stateCnt = TRACE_FLAVOR_SIZE;
+ kern_return_t ret;
+ thread_state_data_t state;
+
+ if (! MACH_PORT_VALID (thread))
+ {
+ warning ("thread_trace: invalid thread");
+ return;
+ }
+
+ if (must_suspend_thread)
+ setup_thread (thread, 1);
+
+ ret = thread_get_state(thread, flavor, state, &stateCnt);
+ CHK ("thread_trace: error reading thread state", ret);
+
+ if (set)
+ {
+ TRACE_SET (thread, state);
+ }
+ else
+ {
+ if (! TRACE_CLEAR (thread, state))
+ {
+ if (must_suspend_thread)
+ setup_thread (thread, 0);
+ return;
+ }
+ }
+
+ ret = thread_set_state(thread, flavor, state, stateCnt);
+ CHK ("thread_trace: error writing thread state", ret);
+ if (must_suspend_thread)
+ setup_thread (thread, 0);
+}
+
+#ifdef FLUSH_INFERIOR_CACHE
+
+/* When over-writing code on some machines the I-Cache must be flushed
+ explicitly, because it is not kept coherent by the lazy hardware.
+ This definitely includes breakpoints, for instance, or else we
+ end up looping in mysterious Bpt traps */
+
+flush_inferior_icache(pc, amount)
+ CORE_ADDR pc;
+{
+ vm_machine_attribute_val_t flush = MATTR_VAL_ICACHE_FLUSH;
+ kern_return_t ret;
+
+ ret = vm_machine_attribute (inferior_task,
+ pc,
+ amount,
+ MATTR_CACHE,
+ &flush);
+ if (ret != KERN_SUCCESS)
+ warning ("Error flushing inferior's cache : %s",
+ mach_error_string (ret));
+}
+#endif FLUSH_INFERIOR_CACHE
+
+
+static
+suspend_all_threads (from_tty)
+ int from_tty;
+{
+ kern_return_t ret;
+ thread_array_t thread_list;
+ int thread_count, index;
+ int infoCnt;
+ thread_basic_info_data_t th_info;
+
+
+ ret = task_threads (inferior_task, &thread_list, &thread_count);
+ if (ret != KERN_SUCCESS)
+ {
+ warning ("Could not suspend inferior threads.");
+ m3_kill_inferior ();
+ return_to_top_level (RETURN_ERROR);
+ }
+
+ for (index = 0; index < thread_count; index++)
+ {
+ int mid;
+
+ mid = map_port_name_to_mid (thread_list[ index ],
+ MACH_TYPE_THREAD);
+
+ ret = thread_suspend(thread_list[ index ]);
+
+ if (ret != KERN_SUCCESS)
+ warning ("Error trying to suspend thread %d : %s",
+ mid, mach_error_string (ret));
+
+ if (from_tty)
+ {
+ infoCnt = THREAD_BASIC_INFO_COUNT;
+ ret = thread_info (thread_list[ index ],
+ THREAD_BASIC_INFO,
+ (thread_info_t) &th_info,
+ &infoCnt);
+ CHK ("suspend can't get thread info", ret);
+
+ warning ("Thread %d suspend count is %d",
+ mid, th_info.suspend_count);
+ }
+ }
+
+ consume_send_rights (thread_list, thread_count);
+ ret = vm_deallocate(mach_task_self(),
+ (vm_address_t)thread_list,
+ (thread_count * sizeof(int)));
+ CHK ("Error trying to deallocate thread list", ret);
+}
+
+void
+thread_suspend_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ kern_return_t ret;
+ int mid;
+ mach_port_t saved_thread;
+ int infoCnt;
+ thread_basic_info_data_t th_info;
+
+ MACH_ERROR_NO_INFERIOR;
+
+ if (!strcasecmp (args, "all")) {
+ suspend_all_threads (from_tty);
+ return;
+ }
+
+ saved_thread = current_thread;
+
+ mid = parse_thread_id (args, 0, 0);
+
+ if (mid < 0)
+ error ("You can suspend only existing kernel threads with MID or @SLOTNUMBER");
+
+ if (mid == 0)
+ mid = map_port_name_to_mid (current_thread, MACH_TYPE_THREAD);
+ else
+ if (select_thread (inferior_task, mid, 0) != KERN_SUCCESS)
+ {
+ if (current_thread)
+ current_thread = saved_thread;
+ error ("Could not select thread %d", mid);
+ }
+
+ ret = thread_suspend (current_thread);
+ if (ret != KERN_SUCCESS)
+ warning ("thread_suspend failed : %s",
+ mach_error_string (ret));
+
+ infoCnt = THREAD_BASIC_INFO_COUNT;
+ ret = thread_info (current_thread,
+ THREAD_BASIC_INFO,
+ (thread_info_t) &th_info,
+ &infoCnt);
+ CHK ("suspend can't get thread info", ret);
+
+ warning ("Thread %d suspend count is %d", mid, th_info.suspend_count);
+
+ current_thread = saved_thread;
+}
+
+resume_all_threads (from_tty)
+ int from_tty;
+{
+ kern_return_t ret;
+ thread_array_t thread_list;
+ int thread_count, index;
+ int mid;
+ int infoCnt;
+ thread_basic_info_data_t th_info;
+
+ ret = task_threads (inferior_task, &thread_list, &thread_count);
+ if (ret != KERN_SUCCESS)
+ {
+ m3_kill_inferior ();
+ error("task_threads", mach_error_string( ret));
+ }
+
+ for (index = 0; index < thread_count; index++)
+ {
+ infoCnt = THREAD_BASIC_INFO_COUNT;
+ ret = thread_info (thread_list [ index ],
+ THREAD_BASIC_INFO,
+ (thread_info_t) &th_info,
+ &infoCnt);
+ CHK ("resume_all can't get thread info", ret);
+
+ mid = map_port_name_to_mid (thread_list[ index ],
+ MACH_TYPE_THREAD);
+
+ if (! th_info.suspend_count)
+ {
+ if (mid != -1 && from_tty)
+ warning ("Thread %d is not suspended", mid);
+ continue;
+ }
+
+ ret = thread_resume (thread_list[ index ]);
+
+ if (ret != KERN_SUCCESS)
+ warning ("Error trying to resume thread %d : %s",
+ mid, mach_error_string (ret));
+ else if (mid != -1 && from_tty)
+ warning ("Thread %d suspend count is %d",
+ mid, --th_info.suspend_count);
+ }
+
+ consume_send_rights (thread_list, thread_count);
+ ret = vm_deallocate(mach_task_self(),
+ (vm_address_t)thread_list,
+ (thread_count * sizeof(int)));
+ CHK("Error trying to deallocate thread list", ret);
+}
+
+void
+thread_resume_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ int mid;
+ mach_port_t saved_thread;
+ kern_return_t ret;
+ thread_basic_info_data_t th_info;
+ int infoCnt = THREAD_BASIC_INFO_COUNT;
+
+ MACH_ERROR_NO_INFERIOR;
+
+ if (!strcasecmp (args, "all")) {
+ resume_all_threads (from_tty);
+ return;
+ }
+
+ saved_thread = current_thread;
+
+ mid = parse_thread_id (args, 0, 0);
+
+ if (mid < 0)
+ error ("You can resume only existing kernel threads with MID or @SLOTNUMBER");
+
+ if (mid == 0)
+ mid = map_port_name_to_mid (current_thread, MACH_TYPE_THREAD);
+ else
+ if (select_thread (inferior_task, mid, 0) != KERN_SUCCESS)
+ {
+ if (current_thread)
+ current_thread = saved_thread;
+ return_to_top_level (RETURN_ERROR);
+ }
+
+ ret = thread_info (current_thread,
+ THREAD_BASIC_INFO,
+ (thread_info_t) &th_info,
+ &infoCnt);
+ CHK ("resume can't get thread info", ret);
+
+ if (! th_info.suspend_count)
+ {
+ warning ("Thread %d is not suspended", mid);
+ goto out;
+ }
+
+ ret = thread_resume (current_thread);
+ if (ret != KERN_SUCCESS)
+ warning ("thread_resume failed : %s",
+ mach_error_string (ret));
+ else
+ {
+ th_info.suspend_count--;
+ warning ("Thread %d suspend count is %d", mid, th_info.suspend_count);
+ }
+
+ out:
+ current_thread = saved_thread;
+}
+
+void
+thread_kill_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ int mid;
+ kern_return_t ret;
+ int thread_count;
+ thread_array_t thread_table;
+ int index;
+ mach_port_t thread_to_kill = MACH_PORT_NULL;
+
+
+ MACH_ERROR_NO_INFERIOR;
+
+ if (!args)
+ error_no_arg ("thread mid to kill from the inferior task");
+
+ mid = parse_thread_id (args, 0, 0);
+
+ if (mid < 0)
+ error ("You can kill only existing kernel threads with MID or @SLOTNUMBER");
+
+ if (mid)
+ {
+ ret = machid_mach_port (mid_server, mid_auth, mid, &thread_to_kill);
+ CHK ("thread_kill_command: machid_mach_port map failed", ret);
+ }
+ else
+ mid = map_port_name_to_mid (current_thread, MACH_TYPE_THREAD);
+
+ /* Don't allow gdb to kill *any* thread in the system. Use mkill program for that */
+ ret = task_threads (inferior_task, &thread_table, &thread_count);
+ CHK ("Error getting inferior's thread list", ret);
+
+ if (thread_to_kill == current_thread)
+ {
+ ret = thread_terminate (thread_to_kill);
+ CHK ("Thread could not be terminated", ret);
+
+ if (select_thread (inferior_task, 0, 1) != KERN_SUCCESS)
+ warning ("Last thread was killed, use \"kill\" command to kill task");
+ }
+ else
+ for (index = 0; index < thread_count; index++)
+ if (thread_table [ index ] == thread_to_kill)
+ {
+ ret = thread_terminate (thread_to_kill);
+ CHK ("Thread could not be terminated", ret);
+ }
+
+ if (thread_count > 1)
+ consume_send_rights (thread_table, thread_count);
+
+ ret = vm_deallocate (mach_task_self(), (vm_address_t)thread_table,
+ (thread_count * sizeof(mach_port_t)));
+ CHK ("Error trying to deallocate thread list", ret);
+
+ warning ("Thread %d killed", mid);
+}
+
+
+/* Task specific commands; add more if you like */
+
+void
+task_resume_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ kern_return_t ret;
+ task_basic_info_data_t ta_info;
+ int infoCnt = TASK_BASIC_INFO_COUNT;
+ int mid = map_port_name_to_mid (inferior_task, MACH_TYPE_TASK);
+
+ MACH_ERROR_NO_INFERIOR;
+
+ /* Would be trivial to change, but is it desirable? */
+ if (args)
+ error ("Currently gdb can resume only it's inferior task");
+
+ ret = task_info (inferior_task,
+ TASK_BASIC_INFO,
+ (task_info_t) &ta_info,
+ &infoCnt);
+ CHK ("task_resume_command: task_info failed", ret);
+
+ if (ta_info.suspend_count == 0)
+ error ("Inferior task %d is not suspended", mid);
+ else if (ta_info.suspend_count == 1 &&
+ from_tty &&
+ !query ("Suspend count is now 1. Do you know what you are doing? "))
+ error ("Task not resumed");
+
+ ret = task_resume (inferior_task);
+ CHK ("task_resume_command: task_resume", ret);
+
+ if (ta_info.suspend_count == 1)
+ {
+ warning ("Inferior task %d is no longer suspended", mid);
+ must_suspend_thread = 1;
+ /* @@ This is not complete: Registers change all the time when not
+ suspended! */
+ registers_changed ();
+ }
+ else
+ warning ("Inferior task %d suspend count is now %d",
+ mid, ta_info.suspend_count-1);
+}
+
+
+void
+task_suspend_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ kern_return_t ret;
+ task_basic_info_data_t ta_info;
+ int infoCnt = TASK_BASIC_INFO_COUNT;
+ int mid = map_port_name_to_mid (inferior_task, MACH_TYPE_TASK);
+
+ MACH_ERROR_NO_INFERIOR;
+
+ /* Would be trivial to change, but is it desirable? */
+ if (args)
+ error ("Currently gdb can suspend only it's inferior task");
+
+ ret = task_suspend (inferior_task);
+ CHK ("task_suspend_command: task_suspend", ret);
+
+ must_suspend_thread = 0;
+
+ ret = task_info (inferior_task,
+ TASK_BASIC_INFO,
+ (task_info_t) &ta_info,
+ &infoCnt);
+ CHK ("task_suspend_command: task_info failed", ret);
+
+ warning ("Inferior task %d suspend count is now %d",
+ mid, ta_info.suspend_count);
+}
+
+static char *
+get_size (bytes)
+ int bytes;
+{
+ static char size [ 30 ];
+ int zz = bytes/1024;
+
+ if (zz / 1024)
+ sprintf (size, "%-2.1f M", ((float)bytes)/(1024.0*1024.0));
+ else
+ sprintf (size, "%d K", zz);
+
+ return size;
+}
+
+/* Does this require the target task to be suspended?? I don't think so. */
+void
+task_info_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ int mid = -5;
+ mach_port_t task;
+ kern_return_t ret;
+ task_basic_info_data_t ta_info;
+ int infoCnt = TASK_BASIC_INFO_COUNT;
+ int page_size = round_page(1);
+ int thread_count = 0;
+
+ if (MACH_PORT_VALID (inferior_task))
+ mid = map_port_name_to_mid (inferior_task,
+ MACH_TYPE_TASK);
+
+ task = inferior_task;
+
+ if (args)
+ {
+ int tmid = atoi (args);
+
+ if (tmid <= 0)
+ error ("Invalid mid %d for task info", tmid);
+
+ if (tmid != mid)
+ {
+ mid = tmid;
+ ret = machid_mach_port (mid_server, mid_auth, tmid, &task);
+ CHK ("task_info_command: machid_mach_port map failed", ret);
+ }
+ }
+
+ if (mid < 0)
+ error ("You have to give the task MID as an argument");
+
+ ret = task_info (task,
+ TASK_BASIC_INFO,
+ (task_info_t) &ta_info,
+ &infoCnt);
+ CHK ("task_info_command: task_info failed", ret);
+
+ printf_filtered ("\nTask info for task %d:\n\n", mid);
+ printf_filtered (" Suspend count : %d\n", ta_info.suspend_count);
+ printf_filtered (" Base priority : %d\n", ta_info.base_priority);
+ printf_filtered (" Virtual size : %s\n", get_size (ta_info.virtual_size));
+ printf_filtered (" Resident size : %s\n", get_size (ta_info.resident_size));
+
+ {
+ thread_array_t thread_list;
+
+ ret = task_threads (task, &thread_list, &thread_count);
+ CHK ("task_info_command: task_threads", ret);
+
+ printf_filtered (" Thread count : %d\n", thread_count);
+
+ consume_send_rights (thread_list, thread_count);
+ ret = vm_deallocate(mach_task_self(),
+ (vm_address_t)thread_list,
+ (thread_count * sizeof(int)));
+ CHK("Error trying to deallocate thread list", ret);
+ }
+ if (have_emulator_p (task))
+ printf_filtered (" Emulator at : 0x%x..0x%x\n",
+ EMULATOR_BASE, EMULATOR_END);
+ else
+ printf_filtered (" No emulator.\n");
+
+ if (thread_count && task == inferior_task)
+ printf_filtered ("\nUse the \"thread list\" command to see the threads\n");
+}
+
+/* You may either FORWARD the exception to the inferior, or KEEP
+ * it and return to GDB command level.
+ *
+ * exception mid [ forward | keep ]
+ */
+
+static void
+exception_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ char *scan = args;
+ int exception;
+ int len;
+
+ if (!args)
+ error_no_arg ("exception number action");
+
+ while (*scan == ' ' || *scan == '\t') scan++;
+
+ if ('0' <= *scan && *scan <= '9')
+ while ('0' <= *scan && *scan <= '9')
+ scan++;
+ else
+ error ("exception number action");
+
+ exception = atoi (args);
+ if (exception <= 0 || exception > MAX_EXCEPTION)
+ error ("Allowed exception numbers are in range 1..%d",
+ MAX_EXCEPTION);
+
+ if (*scan != ' ' && *scan != '\t')
+ error ("exception number must be followed by a space");
+ else
+ while (*scan == ' ' || *scan == '\t') scan++;
+
+ args = scan;
+ len = 0;
+ while (*scan)
+ {
+ len++;
+ scan++;
+ }
+
+ if (!len)
+ error("exception number action");
+
+ if (!strncasecmp (args, "forward", len))
+ exception_map[ exception ].forward = TRUE;
+ else if (!strncasecmp (args, "keep", len))
+ exception_map[ exception ].forward = FALSE;
+ else
+ error ("exception action is either \"keep\" or \"forward\"");
+}
+
+static void
+print_exception_info (exception)
+ int exception;
+{
+ boolean_t forward = exception_map[ exception ].forward;
+
+ printf_filtered ("%s\t(%d): ", exception_map[ exception ].name,
+ exception);
+ if (!forward)
+ if (exception_map[ exception ].sigmap != SIG_UNKNOWN)
+ printf_filtered ("keep and handle as signal %d\n",
+ exception_map[ exception ].sigmap);
+ else
+ printf_filtered ("keep and handle as unknown signal %d\n",
+ exception_map[ exception ].sigmap);
+ else
+ printf_filtered ("forward exception to inferior\n");
+}
+
+void
+exception_info (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ int exception;
+
+ if (!args)
+ for (exception = 1; exception <= MAX_EXCEPTION; exception++)
+ print_exception_info (exception);
+ else
+ {
+ exception = atoi (args);
+
+ if (exception <= 0 || exception > MAX_EXCEPTION)
+ error ("Invalid exception number, values from 1 to %d allowed",
+ MAX_EXCEPTION);
+ print_exception_info (exception);
+ }
+}
+
+/* Check for actions for mach exceptions.
+ */
+mach3_exception_actions (w, force_print_only, who)
+ WAITTYPE *w;
+ boolean_t force_print_only;
+ char *who;
+{
+ boolean_t force_print = FALSE;
+
+
+ if (force_print_only ||
+ exception_map[stop_exception].sigmap == SIG_UNKNOWN)
+ force_print = TRUE;
+ else
+ WSETSTOP (*w, exception_map[stop_exception].sigmap);
+
+ if (exception_map[stop_exception].print || force_print)
+ {
+ target_terminal_ours ();
+
+ printf_filtered ("\n%s received %s exception : ",
+ who,
+ exception_map[stop_exception].name);
+
+ wrap_here (" ");
+
+ switch(stop_exception) {
+ case EXC_BAD_ACCESS:
+ printf_filtered ("referencing address 0x%x : %s\n",
+ stop_subcode,
+ mach_error_string (stop_code));
+ break;
+ case EXC_BAD_INSTRUCTION:
+ printf_filtered
+ ("illegal or undefined instruction. code %d subcode %d\n",
+ stop_code, stop_subcode);
+ break;
+ case EXC_ARITHMETIC:
+ printf_filtered ("code %d\n", stop_code);
+ break;
+ case EXC_EMULATION:
+ printf_filtered ("code %d subcode %d\n", stop_code, stop_subcode);
+ break;
+ case EXC_SOFTWARE:
+ printf_filtered ("%s specific, code 0x%x\n",
+ stop_code < 0xffff ? "hardware" : "os emulation",
+ stop_code);
+ break;
+ case EXC_BREAKPOINT:
+ printf_filtered ("type %d (machine dependent)\n",
+ stop_code);
+ break;
+ default:
+ fatal ("Unknown exception");
+ }
+ }
+}
+
+setup_notify_port (create_new)
+ int create_new;
+{
+ kern_return_t ret;
+
+ if (MACH_PORT_VALID (our_notify_port))
+ {
+ ret = mach_port_destroy (mach_task_self (), our_notify_port);
+ CHK ("Could not destroy our_notify_port", ret);
+ }
+
+ our_notify_port = MACH_PORT_NULL;
+ notify_chain = (port_chain_t) NULL;
+ port_chain_destroy (port_chain_obstack);
+
+ if (create_new)
+ {
+ ret = mach_port_allocate (mach_task_self(),
+ MACH_PORT_RIGHT_RECEIVE,
+ &our_notify_port);
+ if (ret != KERN_SUCCESS)
+ fatal("Creating notify port %s", mach_error_string(ret));
+
+ ret = mach_port_move_member(mach_task_self(),
+ our_notify_port,
+ inferior_wait_port_set);
+ if (ret != KERN_SUCCESS)
+ fatal("initial move member %s",mach_error_string(ret));
+ }
+}
+
+/*
+ * Register our message port to the net name server
+ *
+ * Currently used only by the external stop-gdb program
+ * since ^C does not work if you would like to enter
+ * gdb command level while debugging your program.
+ *
+ * NOTE: If the message port is sometimes used for other
+ * purposes also, the NAME must not be a guessable one.
+ * Then, there should be a way to change it.
+ */
+
+char registered_name[ MAX_NAME_LEN ];
+
+void
+message_port_info (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ if (registered_name[0])
+ printf_filtered ("gdb's message port name: '%s'\n",
+ registered_name);
+ else
+ printf_filtered ("gdb's message port is not currently registered\n");
+}
+
+void
+gdb_register_port (name, port)
+ char *name;
+ mach_port_t port;
+{
+ kern_return_t ret;
+ static int already_signed = 0;
+ int len;
+
+ if (! MACH_PORT_VALID (port) || !name || !*name)
+ {
+ warning ("Invalid registration request");
+ return;
+ }
+
+ if (! already_signed)
+ {
+ ret = mach_port_insert_right (mach_task_self (),
+ our_message_port,
+ our_message_port,
+ MACH_MSG_TYPE_MAKE_SEND);
+ CHK ("Failed to create a signature to our_message_port", ret);
+ already_signed = 1;
+ }
+ else if (already_signed > 1)
+ {
+ ret = netname_check_out (name_server_port,
+ registered_name,
+ our_message_port);
+ CHK ("Failed to check out gdb's message port", ret);
+ registered_name[0] = '\000';
+ already_signed = 1;
+ }
+
+ ret = netname_check_in (name_server_port, /* Name server port */
+ name, /* Name of service */
+ our_message_port, /* Signature */
+ port); /* Creates a new send right */
+ CHK("Failed to check in the port", ret);
+
+ len = 0;
+ while(len < MAX_NAME_LEN && *(name+len))
+ {
+ registered_name[len] = *(name+len);
+ len++;
+ }
+ registered_name[len] = '\000';
+ already_signed = 2;
+}
+
+struct cmd_list_element *cmd_thread_list;
+struct cmd_list_element *cmd_task_list;
+
+/*ARGSUSED*/
+static void
+thread_command (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ printf_unfiltered ("\"thread\" must be followed by the name of a thread command.\n");
+ help_list (cmd_thread_list, "thread ", -1, gdb_stdout);
+}
+
+/*ARGSUSED*/
+static void
+task_command (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ printf_unfiltered ("\"task\" must be followed by the name of a task command.\n");
+ help_list (cmd_task_list, "task ", -1, gdb_stdout);
+}
+
+add_mach_specific_commands ()
+{
+ /* Thread handling commands */
+
+ /* FIXME: Move our thread support into the generic thread.c stuff so we
+ can share that code. */
+ add_prefix_cmd ("mthread", class_stack, thread_command,
+ "Generic command for handling Mach threads in the debugged task.",
+ &cmd_thread_list, "thread ", 0, &cmdlist);
+
+ add_com_alias ("th", "mthread", class_stack, 1);
+
+ add_cmd ("select", class_stack, thread_select_command,
+ "Select and print MID of the selected thread",
+ &cmd_thread_list);
+ add_cmd ("list", class_stack, thread_list_command,
+ "List info of task's threads. Selected thread is marked with '*'",
+ &cmd_thread_list);
+ add_cmd ("suspend", class_run, thread_suspend_command,
+ "Suspend one or all of the threads in the selected task.",
+ &cmd_thread_list);
+ add_cmd ("resume", class_run, thread_resume_command,
+ "Resume one or all of the threads in the selected task.",
+ &cmd_thread_list);
+ add_cmd ("kill", class_run, thread_kill_command,
+ "Kill the specified thread MID from inferior task.",
+ &cmd_thread_list);
+#if 0
+ /* The rest of this support (condition_thread) was not merged. It probably
+ should not be merged in this form, but instead added to the generic GDB
+ thread support. */
+ add_cmd ("break", class_breakpoint, condition_thread,
+ "Breakpoint N will only be effective for thread MID or @SLOT\n\
+ If MID/@SLOT is omitted allow all threads to break at breakpoint",
+ &cmd_thread_list);
+#endif
+ /* Thread command shorthands (for backward compatibility) */
+ add_alias_cmd ("ts", "mthread select", 0, 0, &cmdlist);
+ add_alias_cmd ("tl", "mthread list", 0, 0, &cmdlist);
+
+ /* task handling commands */
+
+ add_prefix_cmd ("task", class_stack, task_command,
+ "Generic command for handling debugged task.",
+ &cmd_task_list, "task ", 0, &cmdlist);
+
+ add_com_alias ("ta", "task", class_stack, 1);
+
+ add_cmd ("suspend", class_run, task_suspend_command,
+ "Suspend the inferior task.",
+ &cmd_task_list);
+ add_cmd ("resume", class_run, task_resume_command,
+ "Resume the inferior task.",
+ &cmd_task_list);
+ add_cmd ("info", no_class, task_info_command,
+ "Print information about the specified task.",
+ &cmd_task_list);
+
+ /* Print my message port name */
+
+ add_info ("message-port", message_port_info,
+ "Returns the name of gdb's message port in the netnameserver");
+
+ /* Exception commands */
+
+ add_info ("exceptions", exception_info,
+ "What debugger does when program gets various exceptions.\n\
+Specify an exception number as argument to print info on that\n\
+exception only.");
+
+ add_com ("exception", class_run, exception_command,
+ "Specify how to handle an exception.\n\
+Args are exception number followed by \"forward\" or \"keep\".\n\
+`Forward' means forward the exception to the program's normal exception\n\
+handler.\n\
+`Keep' means reenter debugger if this exception happens, and GDB maps\n\
+the exception to some signal (see info exception)\n\
+Normally \"keep\" is used to return to GDB on exception.");
+}
+
+kern_return_t
+do_mach_notify_dead_name (notify, name)
+ mach_port_t notify;
+ mach_port_t name;
+{
+ kern_return_t kr = KERN_SUCCESS;
+
+ /* Find the thing that notified */
+ port_chain_t element = port_chain_member (notify_chain, name);
+
+ /* Take name of from unreceived dead name notification list */
+ notify_chain = port_chain_delete (notify_chain, name);
+
+ if (! element)
+ error ("Received a dead name notify from unchained port (0x%x)", name);
+
+ switch (element->type) {
+
+ case MACH_TYPE_THREAD:
+ target_terminal_ours_for_output ();
+ if (name == current_thread)
+ {
+ printf_filtered ("\nCurrent thread %d died", element->mid);
+ current_thread = MACH_PORT_NULL;
+ }
+ else
+ printf_filtered ("\nThread %d died", element->mid);
+
+ break;
+
+ case MACH_TYPE_TASK:
+ target_terminal_ours_for_output ();
+ if (name != inferior_task)
+ printf_filtered ("Task %d died, but it was not the selected task",
+ element->mid);
+ else
+ {
+ printf_filtered ("Current task %d died", element->mid);
+
+ mach_port_destroy (mach_task_self(), name);
+ inferior_task = MACH_PORT_NULL;
+
+ if (notify_chain)
+ warning ("There were still unreceived dead_name_notifications???");
+
+ /* Destroy the old notifications */
+ setup_notify_port (0);
+
+ }
+ break;
+
+ default:
+ error ("Unregistered dead_name 0x%x notification received. Type is %d, mid is 0x%x",
+ name, element->type, element->mid);
+ break;
+ }
+
+ return KERN_SUCCESS;
+}
+
+kern_return_t
+do_mach_notify_msg_accepted (notify, name)
+ mach_port_t notify;
+ mach_port_t name;
+{
+ warning ("do_mach_notify_msg_accepted : notify %x, name %x",
+ notify, name);
+ return KERN_SUCCESS;
+}
+
+kern_return_t
+do_mach_notify_no_senders (notify, mscount)
+ mach_port_t notify;
+ mach_port_mscount_t mscount;
+{
+ warning ("do_mach_notify_no_senders : notify %x, mscount %x",
+ notify, mscount);
+ return KERN_SUCCESS;
+}
+
+kern_return_t
+do_mach_notify_port_deleted (notify, name)
+ mach_port_t notify;
+ mach_port_t name;
+{
+ warning ("do_mach_notify_port_deleted : notify %x, name %x",
+ notify, name);
+ return KERN_SUCCESS;
+}
+
+kern_return_t
+do_mach_notify_port_destroyed (notify, rights)
+ mach_port_t notify;
+ mach_port_t rights;
+{
+ warning ("do_mach_notify_port_destroyed : notify %x, rights %x",
+ notify, rights);
+ return KERN_SUCCESS;
+}
+
+kern_return_t
+do_mach_notify_send_once (notify)
+ mach_port_t notify;
+{
+#ifdef DUMP_SYSCALL
+ /* MANY of these are generated. */
+ warning ("do_mach_notify_send_once : notify %x",
+ notify);
+#endif
+ return KERN_SUCCESS;
+}
+
+/* Kills the inferior. It's gone when you call this */
+static void
+kill_inferior_fast ()
+{
+ WAITTYPE w;
+
+ if (inferior_pid == 0 || inferior_pid == 1)
+ return;
+
+ /* kill() it, since the Unix server does not otherwise notice when
+ * killed with task_terminate().
+ */
+ if (inferior_pid > 0)
+ kill (inferior_pid, SIGKILL);
+
+ /* It's propably terminate already */
+ (void) task_terminate (inferior_task);
+
+ inferior_task = MACH_PORT_NULL;
+ current_thread = MACH_PORT_NULL;
+
+ wait3 (&w, WNOHANG, 0);
+
+ setup_notify_port (0);
+}
+
+static void
+m3_kill_inferior ()
+{
+ kill_inferior_fast ();
+ target_mourn_inferior ();
+}
+
+/* Clean up after the inferior dies. */
+
+static void
+m3_mourn_inferior ()
+{
+ unpush_target (&m3_ops);
+ generic_mourn_inferior ();
+}
+
+
+/* Fork an inferior process, and start debugging it. */
+
+static void
+m3_create_inferior (exec_file, allargs, env)
+ char *exec_file;
+ char *allargs;
+ char **env;
+{
+ fork_inferior (exec_file, allargs, env, m3_trace_me, m3_trace_him, NULL, NULL);
+ /* We are at the first instruction we care about. */
+ /* Pedal to the metal... */
+ proceed ((CORE_ADDR) -1, 0, 0);
+}
+
+/* Mark our target-struct as eligible for stray "run" and "attach"
+ commands. */
+static int
+m3_can_run ()
+{
+ return 1;
+}
+
+/* Mach 3.0 does not need ptrace for anything
+ * Make sure nobody uses it on mach.
+ */
+ptrace (a,b,c,d)
+int a,b,c,d;
+{
+ error ("Lose, Lose! Somebody called ptrace\n");
+}
+
+/* Resume execution of the inferior process.
+ If STEP is nonzero, single-step it.
+ If SIGNAL is nonzero, give it that signal. */
+
+void
+m3_resume (pid, step, signal)
+ int pid;
+ int step;
+ enum target_signal signal;
+{
+ kern_return_t ret;
+
+ if (step)
+ {
+ thread_basic_info_data_t th_info;
+ unsigned int infoCnt = THREAD_BASIC_INFO_COUNT;
+
+ /* There is no point in single stepping when current_thread
+ * is dead.
+ */
+ if (! MACH_PORT_VALID (current_thread))
+ error ("No thread selected; can not single step");
+
+ /* If current_thread is suspended, tracing it would never return.
+ */
+ ret = thread_info (current_thread,
+ THREAD_BASIC_INFO,
+ (thread_info_t) &th_info,
+ &infoCnt);
+ CHK ("child_resume: can't get thread info", ret);
+
+ if (th_info.suspend_count)
+ error ("Can't trace a suspended thread. Use \"thread resume\" command to resume it");
+ }
+
+ vm_read_cache_valid = FALSE;
+
+ if (signal && inferior_pid > 0) /* Do not signal, if attached by MID */
+ kill (inferior_pid, target_signal_to_host (signal));
+
+ if (step)
+ {
+ suspend_all_threads (0);
+
+ setup_single_step (current_thread, TRUE);
+
+ ret = thread_resume (current_thread);
+ CHK ("thread_resume", ret);
+ }
+
+ ret = task_resume (inferior_task);
+ if (ret == KERN_FAILURE)
+ warning ("Task was not suspended");
+ else
+ CHK ("Resuming task", ret);
+
+ /* HACK HACK This is needed by the multiserver system HACK HACK */
+ while ((ret = task_resume(inferior_task)) == KERN_SUCCESS)
+ /* make sure it really runs */;
+ /* HACK HACK This is needed by the multiserver system HACK HACK */
+}
+
+#ifdef ATTACH_DETACH
+
+/* Start debugging the process with the given task */
+void
+task_attach (tid)
+ task_t tid;
+{
+ kern_return_t ret;
+ inferior_task = tid;
+
+ ret = task_suspend (inferior_task);
+ CHK("task_attach: task_suspend", ret);
+
+ must_suspend_thread = 0;
+
+ setup_notify_port (1);
+
+ request_notify (inferior_task, MACH_NOTIFY_DEAD_NAME, MACH_TYPE_TASK);
+
+ setup_exception_port ();
+
+ emulator_present = have_emulator_p (inferior_task);
+
+ attach_flag = 1;
+}
+
+/* Well, we can call error also here and leave the
+ * target stack inconsistent. Sigh.
+ * Fix this sometime (the only way to fail here is that
+ * the task has no threads at all, which is rare, but
+ * possible; or if the target task has died, which is also
+ * possible, but unlikely, since it has been suspended.
+ * (Someone must have killed it))
+ */
+void
+attach_to_thread ()
+{
+ if (select_thread (inferior_task, 0, 1) != KERN_SUCCESS)
+ error ("Could not select any threads to attach to");
+}
+
+mid_attach (mid)
+ int mid;
+{
+ kern_return_t ret;
+
+ ret = machid_mach_port (mid_server, mid_auth, mid, &inferior_task);
+ CHK("mid_attach: machid_mach_port", ret);
+
+ task_attach (inferior_task);
+
+ return mid;
+}
+
+/*
+ * Start debugging the process whose unix process-id is PID.
+ * A negative "pid" value is legal and signifies a mach_id not a unix pid.
+ *
+ * Prevent (possible unwanted) dangerous operations by enabled users
+ * like "atta 0" or "atta foo" (equal to the previous :-) and
+ * "atta pidself". Anyway, the latter is allowed by specifying a MID.
+ */
+static int
+m3_do_attach (pid)
+ int pid;
+{
+ kern_return_t ret;
+
+ if (pid == 0)
+ error("MID=0, Debugging the master unix server does not compute");
+
+ /* Foo. This assumes gdb has a unix pid */
+ if (pid == getpid())
+ error ("I will debug myself only by mid. (Gdb would suspend itself!)");
+
+ if (pid < 0)
+ {
+ mid_attach (-(pid));
+
+ /* inferior_pid will be NEGATIVE! */
+ inferior_pid = pid;
+
+ return inferior_pid;
+ }
+
+ inferior_task = task_by_pid (pid);
+ if (! MACH_PORT_VALID (inferior_task))
+ error("Cannot map Unix pid %d to Mach task port", pid);
+
+ task_attach (inferior_task);
+
+ inferior_pid = pid;
+
+ return inferior_pid;
+}
+
+/* Attach to process PID, then initialize for debugging it
+ and wait for the trace-trap that results from attaching. */
+
+static void
+m3_attach (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ char *exec_file;
+ int pid;
+
+ if (!args)
+ error_no_arg ("process-id to attach");
+
+ 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_unfiltered ("Attaching to program `%s', %s\n", exec_file, target_pid_to_str (pid));
+ else
+ printf_unfiltered ("Attaching to %s\n", target_pid_to_str (pid));
+
+ gdb_flush (gdb_stdout);
+ }
+
+ m3_do_attach (pid);
+ inferior_pid = pid;
+ push_target (&m3_ops);
+}
+
+void
+deallocate_inferior_ports ()
+{
+ kern_return_t ret;
+ thread_array_t thread_list;
+ int thread_count, index;
+
+ if (!MACH_PORT_VALID (inferior_task))
+ return;
+
+ ret = task_threads (inferior_task, &thread_list, &thread_count);
+ if (ret != KERN_SUCCESS)
+ {
+ warning ("deallocate_inferior_ports: task_threads",
+ mach_error_string(ret));
+ return;
+ }
+
+ /* Get rid of send rights to task threads */
+ for (index = 0; index < thread_count; index++)
+ {
+ int rights;
+ ret = mach_port_get_refs (mach_task_self (),
+ thread_list[index],
+ MACH_PORT_RIGHT_SEND,
+ &rights);
+ CHK("deallocate_inferior_ports: get refs", ret);
+
+ if (rights > 0)
+ {
+ ret = mach_port_mod_refs (mach_task_self (),
+ thread_list[index],
+ MACH_PORT_RIGHT_SEND,
+ -rights);
+ CHK("deallocate_inferior_ports: mod refs", ret);
+ }
+ }
+
+ ret = mach_port_mod_refs (mach_task_self (),
+ inferior_exception_port,
+ MACH_PORT_RIGHT_RECEIVE,
+ -1);
+ CHK ("deallocate_inferior_ports: cannot get rid of exception port", ret);
+
+ ret = mach_port_deallocate (mach_task_self (),
+ inferior_task);
+ CHK ("deallocate_task_port: deallocating inferior_task", ret);
+
+ current_thread = MACH_PORT_NULL;
+ inferior_task = MACH_PORT_NULL;
+}
+
+/* Stop debugging the process whose number is PID
+ and continue it with signal number SIGNAL.
+ SIGNAL = 0 means just continue it. */
+
+static void
+m3_do_detach (signal)
+ int signal;
+{
+ kern_return_t ret;
+
+ MACH_ERROR_NO_INFERIOR;
+
+ if (current_thread != MACH_PORT_NULL)
+ {
+ /* Store the gdb's view of the thread we are deselecting
+ * before we detach.
+ * @@ I am really not sure if this is ever needeed.
+ */
+ target_prepare_to_store ();
+ target_store_registers (-1);
+ }
+
+ ret = task_set_special_port (inferior_task,
+ TASK_EXCEPTION_PORT,
+ inferior_old_exception_port);
+ CHK ("task_set_special_port", ret);
+
+ /* Discard all requested notifications */
+ setup_notify_port (0);
+
+ if (remove_breakpoints ())
+ warning ("Could not remove breakpoints when detaching");
+
+ if (signal && inferior_pid > 0)
+ kill (inferior_pid, signal);
+
+ /* the task might be dead by now */
+ (void) task_resume (inferior_task);
+
+ deallocate_inferior_ports ();
+
+ attach_flag = 0;
+}
+
+/* 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 fork. */
+
+static void
+m3_detach (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ int siggnal = 0;
+
+ if (from_tty)
+ {
+ char *exec_file = get_exec_file (0);
+ if (exec_file == 0)
+ exec_file = "";
+ printf_unfiltered ("Detaching from program: %s %s\n",
+ exec_file, target_pid_to_str (inferior_pid));
+ gdb_flush (gdb_stdout);
+ }
+ if (args)
+ siggnal = atoi (args);
+
+ m3_do_detach (siggnal);
+ inferior_pid = 0;
+ unpush_target (&m3_ops); /* Pop out of handling an inferior */
+}
+#endif /* ATTACH_DETACH */
+
+/* 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
+m3_prepare_to_store ()
+{
+#ifdef CHILD_PREPARE_TO_STORE
+ CHILD_PREPARE_TO_STORE ();
+#endif
+}
+
+/* Print status information about what we're accessing. */
+
+static void
+m3_files_info (ignore)
+ struct target_ops *ignore;
+{
+ /* FIXME: should print MID and all that crap. */
+ printf_unfiltered ("\tUsing the running image of %s %s.\n",
+ attach_flag? "attached": "child", target_pid_to_str (inferior_pid));
+}
+
+static void
+m3_open (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ error ("Use the \"run\" command to start a Unix child process.");
+}
+
+#ifdef DUMP_SYSCALL
+#ifdef __STDC__
+#define STR(x) #x
+#else
+#define STR(x) "x"
+#endif
+
+char *bsd1_names[] = {
+ "execve",
+ "fork",
+ "take_signal",
+ "sigreturn",
+ "getrusage",
+ "chdir",
+ "chroot",
+ "open",
+ "creat",
+ "mknod",
+ "link",
+ "symlink",
+ "unlink",
+ "access",
+ "stat",
+ "readlink",
+ "chmod",
+ "chown",
+ "utimes",
+ "truncate",
+ "rename",
+ "mkdir",
+ "rmdir",
+ "xutimes",
+ "mount",
+ "umount",
+ "acct",
+ "setquota",
+ "write_short",
+ "write_long",
+ "send_short",
+ "send_long",
+ "sendto_short",
+ "sendto_long",
+ "select",
+ "task_by_pid",
+ "recvfrom_short",
+ "recvfrom_long",
+ "setgroups",
+ "setrlimit",
+ "sigvec",
+ "sigstack",
+ "settimeofday",
+ "adjtime",
+ "setitimer",
+ "sethostname",
+ "bind",
+ "accept",
+ "connect",
+ "setsockopt",
+ "getsockopt",
+ "getsockname",
+ "getpeername",
+ "init_process",
+ "table_set",
+ "table_get",
+ "pioctl",
+ "emulator_error",
+ "readwrite",
+ "share_wakeup",
+ 0,
+ "maprw_request_it",
+ "maprw_release_it",
+ "maprw_remap",
+ "pid_by_task",
+};
+
+int bsd1_nnames = sizeof(bsd1_names)/sizeof(bsd1_names[0]);
+
+char*
+name_str(name,buf)
+
+int name;
+char *buf;
+
+{
+ switch (name) {
+ case MACH_MSG_TYPE_BOOLEAN:
+ return "boolean";
+ case MACH_MSG_TYPE_INTEGER_16:
+ return "short";
+ case MACH_MSG_TYPE_INTEGER_32:
+ return "long";
+ case MACH_MSG_TYPE_CHAR:
+ return "char";
+ case MACH_MSG_TYPE_BYTE:
+ return "byte";
+ case MACH_MSG_TYPE_REAL:
+ return "real";
+ case MACH_MSG_TYPE_STRING:
+ return "string";
+ default:
+ sprintf(buf,"%d",name);
+ return buf;
+ }
+}
+
+char *
+id_str(id,buf)
+
+int id;
+char *buf;
+
+{
+ char *p;
+ if (id >= 101000 && id < 101000+bsd1_nnames) {
+ if (p = bsd1_names[id-101000])
+ return p;
+ }
+ if (id == 102000)
+ return "psignal_retry";
+ if (id == 100000)
+ return "syscall";
+ sprintf(buf,"%d",id);
+ return buf;
+}
+
+print_msg(mp)
+mach_msg_header_t *mp;
+{
+ char *fmt_x = "%20s : 0x%08x\n";
+ char *fmt_d = "%20s : %10d\n";
+ char *fmt_s = "%20s : %s\n";
+ char buf[100];
+
+ puts_filtered ("\n");
+#define pr(fmt,h,x) printf_filtered(fmt,STR(x),(h).x)
+ pr(fmt_x,(*mp),msgh_bits);
+ pr(fmt_d,(*mp),msgh_size);
+ pr(fmt_x,(*mp),msgh_remote_port);
+ pr(fmt_x,(*mp),msgh_local_port);
+ pr(fmt_d,(*mp),msgh_kind);
+ printf_filtered(fmt_s,STR(msgh_id),id_str(mp->msgh_id,buf));
+
+ if (debug_level > 1)
+ {
+ char *p,*ep,*dp;
+ int plen;
+ p = (char*)mp;
+ ep = p+mp->msgh_size;
+ p += sizeof(*mp);
+ for(; p < ep; p += plen) {
+ mach_msg_type_t *tp;
+ mach_msg_type_long_t *tlp;
+ int name,size,number;
+ tp = (mach_msg_type_t*)p;
+ if (tp->msgt_longform) {
+ tlp = (mach_msg_type_long_t*)tp;
+ name = tlp->msgtl_name;
+ size = tlp->msgtl_size;
+ number = tlp->msgtl_number;
+ plen = sizeof(*tlp);
+ } else {
+ name = tp->msgt_name;
+ size = tp->msgt_size;
+ number = tp->msgt_number;
+ plen = sizeof(*tp);
+ }
+ printf_filtered("name=%-16s size=%2d number=%7d inline=%d long=%d deal=%d\n",
+ name_str(name,buf),size,number,tp->msgt_inline,
+ tp->msgt_longform, tp->msgt_deallocate);
+ dp = p+plen;
+ if (tp->msgt_inline) {
+ int l;
+ l = size*number/8;
+ l = (l+sizeof(long)-1)&~((sizeof(long))-1);
+ plen += l;
+ print_data(dp,size,number);
+ } else {
+ plen += sizeof(int*);
+ }
+ printf_filtered("plen=%d\n",plen);
+ }
+ }
+}
+
+print_data(p,size,number)
+
+char *p;
+
+{
+ int *ip;
+ short *sp;
+ int i;
+
+ switch (size) {
+ case 8:
+ for(i = 0; i < number; i++) {
+ printf_filtered(" %02x",p[i]);
+ }
+ break;
+ case 16:
+ sp = (short*)p;
+ for(i = 0; i < number; i++) {
+ printf_filtered(" %04x",sp[i]);
+ }
+ break;
+ case 32:
+ ip = (int*)p;
+ for(i = 0; i < number; i++) {
+ printf_filtered(" %08x",ip[i]);
+ }
+ break;
+ }
+ puts_filtered("\n");
+}
+#endif DUMP_SYSCALL
+
+static void
+m3_stop ()
+{
+ error ("to_stop target function not implemented");
+}
+
+static char *
+m3_pid_to_exec_file (pid)
+int pid;
+{
+ error ("to_pid_to_exec_file target function not implemented");
+ return NULL; /* To keep all compilers happy. */
+}
+
+static void
+init_m3_ops ()
+{
+ m3_ops.to_shortname = "mach";
+ m3_ops.to_longname = "Mach child process";
+ m3_ops.to_doc = "Mach child process (started by the \"run\" command).";
+ m3_ops.to_open = m3_open;
+ m3_ops.to_attach = m3_attach;
+ m3_ops.to_detach = m3_detach;
+ m3_ops.to_resume = m3_resume;
+ m3_ops.to_wait = mach_really__wait;
+ m3_ops.to_fetch_registers = fetch_inferior_registers;
+ m3_ops.to_store_registers = store_inferior_registers;
+ m3_ops.to_prepare_to_store = m3_prepare_to_store;
+ m3_ops.to_xfer_memory = m3_xfer_memory;
+ m3_ops.to_files_info = m3_files_info;
+ m3_ops.to_insert_breakpoint = memory_insert_breakpoint;
+ m3_ops.to_remove_breakpoint = memory_remove_breakpoint;
+ m3_ops.to_terminal_init = terminal_init_inferior;
+ m3_ops.to_terminal_inferior = terminal_inferior;
+ m3_ops.to_terminal_ours_for_output = terminal_ours_for_output;
+ m3_ops.to_terminal_ours = terminal_ours;
+ m3_ops.to_terminal_info = child_terminal_info;
+ m3_ops.to_kill = m3_kill_inferior;
+ m3_ops.to_create_inferior = m3_create_inferior;
+ m3_ops.to_mourn_inferior = m3_mourn_inferior;
+ m3_ops.to_can_run = m3_can_run;
+ m3_ops.to_stop = m3_stop;
+ m3_ops.to_pid_to_exec_file = m3_pid_to_exec_file;
+ m3_ops.to_stratum = process_stratum;
+ m3_ops.to_has_all_memory = 1;
+ m3_ops.to_has_memory = 1;
+ m3_ops.to_has_stack = 1;
+ m3_ops.to_has_registers = 1;
+ m3_ops.to_has_execution = 1;
+ m3_ops.to_magic = OPS_MAGIC;
+}
+
+void
+_initialize_m3_nat ()
+{
+ kern_return_t ret;
+
+ init_m3_ops ();
+ add_target (&m3_ops);
+
+ ret = mach_port_allocate(mach_task_self(),
+ MACH_PORT_RIGHT_PORT_SET,
+ &inferior_wait_port_set);
+ if (ret != KERN_SUCCESS)
+ fatal("initial port set %s",mach_error_string(ret));
+
+ /* mach_really_wait now waits for this */
+ currently_waiting_for = inferior_wait_port_set;
+
+ ret = netname_look_up(name_server_port, hostname, "MachID", &mid_server);
+ if (ret != KERN_SUCCESS)
+ {
+ mid_server = MACH_PORT_NULL;
+
+ warning ("initialize machid: netname_lookup_up(MachID) : %s",
+ mach_error_string(ret));
+ warning ("Some (most?) features disabled...");
+ }
+
+ mid_auth = mach_privileged_host_port();
+ if (mid_auth == MACH_PORT_NULL)
+ mid_auth = mach_task_self();
+
+ obstack_init (port_chain_obstack);
+
+ ret = mach_port_allocate (mach_task_self (),
+ MACH_PORT_RIGHT_RECEIVE,
+ &thread_exception_port);
+ CHK ("Creating thread_exception_port for single stepping", ret);
+
+ ret = mach_port_insert_right (mach_task_self (),
+ thread_exception_port,
+ thread_exception_port,
+ MACH_MSG_TYPE_MAKE_SEND);
+ CHK ("Inserting send right to thread_exception_port", ret);
+
+ /* Allocate message port */
+ ret = mach_port_allocate (mach_task_self (),
+ MACH_PORT_RIGHT_RECEIVE,
+ &our_message_port);
+ if (ret != KERN_SUCCESS)
+ warning ("Creating message port %s", mach_error_string (ret));
+ else
+ {
+ char buf[ MAX_NAME_LEN ];
+ ret = mach_port_move_member(mach_task_self (),
+ our_message_port,
+ inferior_wait_port_set);
+ if (ret != KERN_SUCCESS)
+ warning ("message move member %s", mach_error_string (ret));
+
+
+ /* @@@@ No way to change message port name currently */
+ /* Foo. This assumes gdb has a unix pid */
+ sprintf (buf, "gdb-%d", getpid ());
+ gdb_register_port (buf, our_message_port);
+ }
+
+ /* Heap for thread commands */
+ obstack_init (cproc_obstack);
+
+ add_mach_specific_commands ();
+}
diff --git a/gdb/m32r-rom.c b/gdb/m32r-rom.c
new file mode 100644
index 00000000000..2be833e32e2
--- /dev/null
+++ b/gdb/m32r-rom.c
@@ -0,0 +1,650 @@
+/* Remote debugging interface to m32r and mon2000 ROM monitors for GDB,
+ the GNU debugger.
+ Copyright 1996 Free Software Foundation, Inc.
+
+ Adapted by Michael Snyder of 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* This module defines communication with the Mitsubishi m32r monitor */
+
+#include "defs.h"
+#include "gdbcore.h"
+#include "target.h"
+#include "monitor.h"
+#include "serial.h"
+#include "symtab.h"
+#include "command.h"
+#include "gdbcmd.h"
+#include "symfile.h" /* for generic load */
+#include <time.h> /* for time_t */
+#include "gdb_string.h"
+#include "objfiles.h" /* for ALL_OBJFILES etc. */
+
+
+extern void report_transfer_performance PARAMS ((unsigned long, time_t, time_t));
+
+#ifndef _MSC_VER
+/*
+ * All this stuff just to get my host computer's IP address!
+ */
+#include <sys/types.h>
+#include <netdb.h> /* for hostent */
+#include <netinet/in.h> /* for struct in_addr */
+#if 1
+#include <arpa/inet.h> /* for inet_ntoa */
+#endif
+#endif
+
+static char *board_addr; /* user-settable IP address for M32R-EVA */
+static char *server_addr; /* user-settable IP address for gdb host */
+static char *download_path; /* user-settable path for SREC files */
+
+
+/*
+ * Function: m32r_load_1 (helper function)
+ */
+
+static void
+m32r_load_section (abfd, s, data_count)
+ bfd *abfd;
+ asection *s;
+ unsigned int *data_count;
+{
+ if (s->flags & SEC_LOAD)
+ {
+ bfd_size_type section_size = bfd_section_size (abfd, s);
+ bfd_vma section_base = bfd_section_lma (abfd, s);
+ unsigned int buffer, i;
+
+ *data_count += section_size;
+
+ printf_filtered ("Loading section %s, size 0x%lx lma ",
+ bfd_section_name (abfd, s), section_size);
+ print_address_numeric (section_base, 1, gdb_stdout);
+ printf_filtered ("\n");
+ gdb_flush (gdb_stdout);
+ monitor_printf ("%x mw\r" , section_base);
+ for (i = 0; i < section_size; i += 4)
+ {
+ QUIT;
+ monitor_expect (" -> ", NULL, 0);
+ bfd_get_section_contents (abfd, s, (char *) &buffer, i, 4);
+ monitor_printf ("%x\n", buffer);
+ }
+ monitor_expect (" -> ", NULL, 0);
+ monitor_printf ("q\n");
+ monitor_expect_prompt (NULL, 0);
+ }
+}
+
+static int
+m32r_load_1 (dummy)
+ void *dummy;
+{
+ int data_count = 0;
+
+ bfd_map_over_sections ((bfd *) dummy, m32r_load_section, &data_count);
+ return data_count;
+}
+
+/*
+ * Function: m32r_load (an alternate way to load)
+ */
+
+static void
+m32r_load (filename, from_tty)
+ char *filename;
+ int from_tty;
+{
+ extern int inferior_pid;
+ bfd *abfd;
+ asection *s;
+ unsigned int i, data_count = 0;
+ time_t start_time, end_time; /* for timing of download */
+
+ if (filename == NULL || filename[0] == 0)
+ filename = get_exec_file (1);
+
+ abfd = bfd_openr (filename, 0);
+ if (!abfd)
+ error ("Unable to open file %s\n", filename);
+ if (bfd_check_format (abfd, bfd_object) == 0)
+ error ("File is not an object file\n");
+ start_time = time (NULL);
+#if 0
+ for (s = abfd->sections; s; s = s->next)
+ if (s->flags & SEC_LOAD)
+ {
+ bfd_size_type section_size = bfd_section_size (abfd, s);
+ bfd_vma section_base = bfd_section_vma (abfd, s);
+ unsigned int buffer;
+
+ data_count += section_size;
+
+ printf_filtered ("Loading section %s, size 0x%lx vma ",
+ bfd_section_name (abfd, s), section_size);
+ print_address_numeric (section_base, 1, gdb_stdout);
+ printf_filtered ("\n");
+ gdb_flush (gdb_stdout);
+ monitor_printf ("%x mw\r" , section_base);
+ for (i = 0; i < section_size; i += 4)
+ {
+ monitor_expect (" -> ", NULL, 0);
+ bfd_get_section_contents (abfd, s, (char *) &buffer, i, 4);
+ monitor_printf ("%x\n", buffer);
+ }
+ monitor_expect (" -> ", NULL, 0);
+ monitor_printf ("q\n");
+ monitor_expect_prompt (NULL, 0);
+ }
+#else
+ if (!(catch_errors (m32r_load_1, abfd, "Load aborted!\n", RETURN_MASK_ALL)))
+ {
+ monitor_printf ("q\n");
+ return;
+ }
+#endif
+ end_time = time (NULL);
+ printf_filtered ("Start address 0x%lx\n", bfd_get_start_address (abfd));
+ report_transfer_performance (data_count, start_time, end_time);
+
+ /* Finally, make the PC point at the start address */
+ if (exec_bfd)
+ write_pc (bfd_get_start_address (exec_bfd));
+
+ inferior_pid = 0; /* No process now */
+
+ /* This is necessary because many things were based on the PC at the
+ time that we attached to the monitor, which is no longer valid
+ now that we have loaded new code (and just changed the PC).
+ Another way to do this might be to call normal_stop, except that
+ the stack may not be valid, and things would get horribly
+ confused... */
+
+ clear_symtab_users ();
+}
+
+static void
+m32r_load_gen (filename, from_tty)
+ char *filename;
+ int from_tty;
+{
+ generic_load (filename, from_tty);
+}
+
+static void m32r_open PARAMS ((char *args, int from_tty));
+static void mon2000_open PARAMS ((char *args, int from_tty));
+
+/* This array of registers needs to match the indexes used by GDB. The
+ whole reason this exists is because the various ROM monitors use
+ different names than GDB does, and don't support all the registers
+ either. So, typing "info reg sp" becomes an "A7". */
+
+static char *m32r_regnames[] =
+{ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
+ "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
+ "psw", "cbr", "spi", "spu", "bpc", "pc", "accl", "acch",
+};
+
+static void
+m32r_supply_register (regname, regnamelen, val, vallen)
+ char *regname;
+ int regnamelen;
+ char *val;
+ int vallen;
+{
+ int regno;
+ int num_regs = sizeof(m32r_regnames) / sizeof(m32r_regnames[0]);
+
+ for (regno = 0; regno < num_regs; regno++)
+ if (strncmp(regname, m32r_regnames[regno], regnamelen) == 0)
+ break;
+
+ if (regno >= num_regs)
+ return; /* no match */
+
+ if (regno == ACCL_REGNUM)
+ { /* special handling for 64-bit acc reg */
+ monitor_supply_register (ACCH_REGNUM, val);
+ if (val = (char *) strchr(val, ':')) /* skip past ':' to get 2nd word */
+ monitor_supply_register (ACCL_REGNUM, val + 1);
+ }
+ else
+ {
+ monitor_supply_register (regno, val);
+ if (regno == PSW_REGNUM)
+ {
+ unsigned long psw = strtoul (val, NULL, 16);
+ char *zero = "00000000", *one = "00000001";
+
+#ifdef SM_REGNUM
+ /* Stack mode bit */
+ monitor_supply_register (SM_REGNUM, (psw & 0x80) ? one : zero);
+#endif
+#ifdef BSM_REGNUM
+ /* Backup stack mode bit */
+ monitor_supply_register (BSM_REGNUM, (psw & 0x8000) ? one : zero);
+#endif
+#ifdef IE_REGNUM
+ /* Interrupt enable bit */
+ monitor_supply_register (IE_REGNUM, (psw & 0x40) ? one : zero);
+#endif
+#ifdef BIE_REGNUM
+ /* Backup interrupt enable bit */
+ monitor_supply_register (BIE_REGNUM, (psw & 0x4000) ? one : zero);
+#endif
+#ifdef COND_REGNUM
+ /* Condition bit (carry etc.) */
+ monitor_supply_register (COND_REGNUM, (psw & 0x1) ? one : zero);
+#endif
+#ifdef CBR_REGNUM
+ monitor_supply_register (CBR_REGNUM, (psw & 0x1) ? one : zero);
+#endif
+#ifdef BPC_REGNUM
+ monitor_supply_register (BPC_REGNUM, zero); /* KLUDGE: (???????) */
+#endif
+#ifdef BCARRY_REGNUM
+ monitor_supply_register (BCARRY_REGNUM, zero); /* KLUDGE: (??????) */
+#endif
+ }
+
+ if (regno == SPI_REGNUM || regno == SPU_REGNUM)
+ { /* special handling for stack pointer (spu or spi) */
+ unsigned long stackmode = read_register (PSW_REGNUM) & 0x80;
+
+ if (regno == SPI_REGNUM && !stackmode) /* SP == SPI */
+ monitor_supply_register (SP_REGNUM, val);
+ else if (regno == SPU_REGNUM && stackmode) /* SP == SPU */
+ monitor_supply_register (SP_REGNUM, val);
+ }
+ }
+}
+
+/* m32r RevC board monitor */
+
+static struct target_ops m32r_ops;
+
+static char *m32r_inits[] = {"\r", NULL};
+
+static struct monitor_ops m32r_cmds ;
+
+static void
+init_m32r_cmds(void)
+{
+ m32r_cmds.flags = MO_CLR_BREAK_USES_ADDR | MO_REGISTER_VALUE_FIRST;
+ m32r_cmds.init = m32r_inits; /* Init strings */
+ m32r_cmds.cont = "go\r"; /* continue command */
+ m32r_cmds.step = "step\r"; /* single step */
+ m32r_cmds.stop = NULL; /* interrupt command */
+ m32r_cmds.set_break = "%x +bp\r"; /* set a breakpoint */
+ m32r_cmds.clr_break = "%x -bp\r"; /* clear a breakpoint */
+ m32r_cmds.clr_all_break = "bpoff\r"; /* clear all breakpoints */
+ m32r_cmds.fill = "%x %x %x fill\r"; /* fill (start length val) */
+ m32r_cmds.setmem.cmdb = "%x 1 %x fill\r"; /* setmem.cmdb (addr, value) */
+ m32r_cmds.setmem.cmdw = "%x 1 %x fillh\r";/* setmem.cmdw (addr, value) */
+ m32r_cmds.setmem.cmdl = "%x 1 %x fillw\r";/* setmem.cmdl (addr, value) */
+ m32r_cmds.setmem.cmdll = NULL; /* setmem.cmdll (addr, value) */
+ m32r_cmds.setmem.resp_delim = NULL; /* setmem.resp_delim */
+ m32r_cmds.setmem.term = NULL; /* setmem.term */
+ m32r_cmds.setmem.term_cmd = NULL; /* setmem.term_cmd */
+ m32r_cmds.getmem.cmdb = "%x %x dump\r"; /* getmem.cmdb (addr, len) */
+ m32r_cmds.getmem.cmdw = NULL; /* getmem.cmdw (addr, len) */
+ m32r_cmds.getmem.cmdl = NULL; /* getmem.cmdl (addr, len) */
+ m32r_cmds.getmem.cmdll = NULL; /* getmem.cmdll (addr, len) */
+ m32r_cmds.getmem.resp_delim = ": "; /* getmem.resp_delim */
+ m32r_cmds.getmem.term = NULL; /* getmem.term */
+ m32r_cmds.getmem.term_cmd = NULL ; /* getmem.term_cmd */
+ m32r_cmds.setreg.cmd = "%x to %%%s\r"; /* setreg.cmd (name, value) */
+ m32r_cmds.setreg.resp_delim = NULL; /* setreg.resp_delim */
+ m32r_cmds.setreg.term = NULL; /* setreg.term */
+ m32r_cmds.setreg.term_cmd = NULL ; /* setreg.term_cmd */
+ m32r_cmds.getreg.cmd = NULL; /* getreg.cmd (name) */
+ m32r_cmds.getreg.resp_delim = NULL; /* getreg.resp_delim */
+ m32r_cmds.getreg.term = NULL; /* getreg.term */
+ m32r_cmds.getreg.term_cmd = NULL ; /* getreg.term_cmd */
+ m32r_cmds.dump_registers = ".reg\r"; /* dump_registers */
+ m32r_cmds.register_pattern = "\\(\\w+\\) += \\([0-9a-fA-F]+\\b\\)"; /* register_pattern */
+ m32r_cmds.supply_register = m32r_supply_register; /* supply_register */
+ m32r_cmds.load_routine = NULL; /* load_routine (defaults to SRECs) */
+ m32r_cmds.load = NULL; /* download command */
+ m32r_cmds.loadresp = NULL; /* load response */
+ m32r_cmds.prompt = "ok "; /* monitor command prompt */
+ m32r_cmds.line_term = "\r"; /* end-of-line terminator */
+ m32r_cmds.cmd_end = NULL; /* optional command terminator */
+ m32r_cmds.target = &m32r_ops; /* target operations */
+ m32r_cmds.stopbits = SERIAL_1_STOPBITS; /* number of stop bits */
+ m32r_cmds.regnames = m32r_regnames; /* registers names */
+ m32r_cmds.magic = MONITOR_OPS_MAGIC ; /* magic */
+} /* init_m32r_cmds */
+
+static void
+m32r_open(args, from_tty)
+ char *args;
+ int from_tty;
+{
+ monitor_open (args, &m32r_cmds, from_tty);
+}
+
+/* Mon2000 monitor (MSA2000 board) */
+
+static struct target_ops mon2000_ops;
+static struct monitor_ops mon2000_cmds;
+
+static void
+init_mon2000_cmds(void)
+{
+ mon2000_cmds.flags = MO_CLR_BREAK_USES_ADDR | MO_REGISTER_VALUE_FIRST;
+ mon2000_cmds.init = m32r_inits; /* Init strings */
+ mon2000_cmds.cont = "go\r"; /* continue command */
+ mon2000_cmds.step = "step\r"; /* single step */
+ mon2000_cmds.stop = NULL; /* interrupt command */
+ mon2000_cmds.set_break = "%x +bp\r"; /* set a breakpoint */
+ mon2000_cmds.clr_break = "%x -bp\r"; /* clear a breakpoint */
+ mon2000_cmds.clr_all_break = "bpoff\r"; /* clear all breakpoints */
+ mon2000_cmds.fill = "%x %x %x fill\r"; /* fill (start length val) */
+ mon2000_cmds.setmem.cmdb = "%x 1 %x fill\r"; /* setmem.cmdb (addr, value) */
+ mon2000_cmds.setmem.cmdw = "%x 1 %x fillh\r";/* setmem.cmdw (addr, value) */
+ mon2000_cmds.setmem.cmdl = "%x 1 %x fillw\r";/* setmem.cmdl (addr, value) */
+ mon2000_cmds.setmem.cmdll = NULL; /* setmem.cmdll (addr, value) */
+ mon2000_cmds.setmem.resp_delim = NULL; /* setmem.resp_delim */
+ mon2000_cmds.setmem.term = NULL; /* setmem.term */
+ mon2000_cmds.setmem.term_cmd = NULL; /* setmem.term_cmd */
+ mon2000_cmds.getmem.cmdb = "%x %x dump\r"; /* getmem.cmdb (addr, len) */
+ mon2000_cmds.getmem.cmdw = NULL; /* getmem.cmdw (addr, len) */
+ mon2000_cmds.getmem.cmdl = NULL; /* getmem.cmdl (addr, len) */
+ mon2000_cmds.getmem.cmdll = NULL; /* getmem.cmdll (addr, len) */
+ mon2000_cmds.getmem.resp_delim = ": "; /* getmem.resp_delim */
+ mon2000_cmds.getmem.term = NULL; /* getmem.term */
+ mon2000_cmds.getmem.term_cmd = NULL ; /* getmem.term_cmd */
+ mon2000_cmds.setreg.cmd = "%x to %%%s\r"; /* setreg.cmd (name, value) */
+ mon2000_cmds.setreg.resp_delim = NULL; /* setreg.resp_delim */
+ mon2000_cmds.setreg.term = NULL; /* setreg.term */
+ mon2000_cmds.setreg.term_cmd = NULL ; /* setreg.term_cmd */
+ mon2000_cmds.getreg.cmd = NULL; /* getreg.cmd (name) */
+ mon2000_cmds.getreg.resp_delim = NULL; /* getreg.resp_delim */
+ mon2000_cmds.getreg.term = NULL; /* getreg.term */
+ mon2000_cmds.getreg.term_cmd = NULL ; /* getreg.term_cmd */
+ mon2000_cmds.dump_registers = ".reg\r"; /* dump_registers */
+ mon2000_cmds.register_pattern = "\\(\\w+\\) += \\([0-9a-fA-F]+\\b\\)"; /* register_pattern */
+ mon2000_cmds.supply_register = m32r_supply_register; /* supply_register */
+ mon2000_cmds.load_routine = NULL; /* load_routine (defaults to SRECs) */
+ mon2000_cmds.load = NULL; /* download command */
+ mon2000_cmds.loadresp = NULL; /* load response */
+ mon2000_cmds.prompt = "Mon2000>"; /* monitor command prompt */
+ mon2000_cmds.line_term = "\r"; /* end-of-line terminator */
+ mon2000_cmds.cmd_end = NULL; /* optional command terminator */
+ mon2000_cmds.target = &mon2000_ops; /* target operations */
+ mon2000_cmds.stopbits = SERIAL_1_STOPBITS; /* number of stop bits */
+ mon2000_cmds.regnames = m32r_regnames; /* registers names */
+ mon2000_cmds.magic = MONITOR_OPS_MAGIC ; /* magic */
+} /* init_mon2000_cmds */
+
+static void
+mon2000_open(args, from_tty)
+ char *args;
+ int from_tty;
+{
+ monitor_open (args, &mon2000_cmds, from_tty);
+}
+
+#ifndef _MSC_VER
+
+/* Function: set_board_address
+ Tell the BootOne monitor what it's ethernet IP address is. */
+
+static void
+m32r_set_board_address (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ int resp_len;
+ char buf[1024];
+
+ if (args && *args)
+ {
+ monitor_printf ("ulip %s\n", args);
+ resp_len = monitor_expect_prompt (buf, sizeof(buf));
+ /* now parse the result for success */
+ }
+ else
+ error ("Requires argument (IP address for M32R-EVA board)");
+}
+
+/* Function: set_server_address
+ Tell the BootOne monitor what gdb's ethernet IP address is. */
+
+static void
+m32r_set_server_address (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ int resp_len;
+ char buf[1024];
+
+ if (args && *args)
+ {
+ monitor_printf ("uhip %s\n", args);
+ resp_len = monitor_expect_prompt (buf, sizeof(buf));
+ /* now parse the result for success */
+ }
+ else
+ error ("Requires argument (IP address of GDB's host computer)");
+}
+
+/* Function: set_download_path
+ Tell the BootOne monitor the default path for downloadable SREC files. */
+
+static void
+m32r_set_download_path (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ int resp_len;
+ char buf[1024];
+
+ if (args && *args)
+ {
+ monitor_printf ("up %s\n", args);
+ resp_len = monitor_expect_prompt (buf, sizeof(buf));
+ /* now parse the result for success */
+ }
+ else
+ error ("Requires argument (default path for downloadable SREC files)");
+}
+
+static void
+m32r_upload_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ bfd *abfd;
+ asection *s;
+ time_t start_time, end_time; /* for timing of download */
+ extern int inferior_pid;
+ int resp_len, data_count = 0;
+ char buf[1024];
+ struct hostent *hostent;
+ struct in_addr inet_addr;
+
+ /* first check to see if there's an ethernet port! */
+ monitor_printf ("ust\r");
+ resp_len = monitor_expect_prompt (buf, sizeof(buf));
+ if (!strchr (buf, ':'))
+ error ("No ethernet connection!");
+
+ if (board_addr == 0)
+ {
+ /* scan second colon in the output from the "ust" command */
+ char * myIPaddress = strchr (strchr (buf, ':') + 1, ':') + 1;
+
+ while (isspace(*myIPaddress))
+ myIPaddress++;
+
+ if (!strncmp (myIPaddress, "0.0.", 4)) /* empty */
+ error ("Please use 'set board-address' to set the M32R-EVA board's IP address.");
+ if (strchr (myIPaddress, '('))
+ *(strchr (myIPaddress, '(')) = '\0'; /* delete trailing junk */
+ board_addr = strsave (myIPaddress);
+ }
+ if (server_addr == 0)
+ {
+ buf[0] = 0;
+ gethostname (buf, sizeof(buf));
+ if (buf[0] != 0)
+ hostent = gethostbyname (buf);
+ if (hostent != 0)
+ {
+#if 1
+ memcpy (&inet_addr.s_addr, hostent->h_addr,
+ sizeof(inet_addr.s_addr));
+ server_addr = (char *) inet_ntoa (inet_addr);
+#else
+ server_addr = (char *) inet_ntoa (hostent->h_addr);
+#endif
+ }
+ if (server_addr == 0) /* failed? */
+ error ("Need to know gdb host computer's IP address (use 'set server-address')");
+ }
+
+ if (args == 0 || args[0] == 0) /* no args: upload the current file */
+ args = get_exec_file (1);
+
+ if (args[0] != '/' && download_path == 0)
+ if (current_directory)
+ download_path = strsave (current_directory);
+ else
+ error ("Need to know default download path (use 'set download-path')");
+
+ start_time = time (NULL);
+ monitor_printf ("uhip %s\r", server_addr);
+ resp_len = monitor_expect_prompt (buf, sizeof(buf)); /* parse result? */
+ monitor_printf ("ulip %s\r", board_addr);
+ resp_len = monitor_expect_prompt (buf, sizeof(buf)); /* parse result? */
+ if (args[0] != '/')
+ monitor_printf ("up %s\r", download_path); /* use default path */
+ else
+ monitor_printf ("up\r"); /* rooted filename/path */
+ resp_len = monitor_expect_prompt (buf, sizeof(buf)); /* parse result? */
+
+ if (strrchr (args, '.') && !strcmp (strrchr (args, '.'), ".srec"))
+ monitor_printf ("ul %s\r", args);
+ else /* add ".srec" suffix */
+ monitor_printf ("ul %s.srec\r", args);
+ resp_len = monitor_expect_prompt (buf, sizeof(buf)); /* parse result? */
+
+ if (buf[0] == 0 || strstr(buf, "complete") == 0)
+ error("Upload file not found: %s.srec\nCheck IP addresses and download path.", args);
+ else
+ printf_filtered (" -- Ethernet load complete.\n");
+
+ end_time = time (NULL);
+ if (abfd = bfd_openr (args, 0))
+ { /* Download is done -- print section statistics */
+ if (bfd_check_format (abfd, bfd_object) == 0)
+ {
+ printf_filtered ("File is not an object file\n");
+ }
+ for (s = abfd->sections; s; s = s->next)
+ if (s->flags & SEC_LOAD)
+ {
+ bfd_size_type section_size = bfd_section_size (abfd, s);
+ bfd_vma section_base = bfd_section_lma (abfd, s);
+ unsigned int buffer;
+
+ data_count += section_size;
+
+ printf_filtered ("Loading section %s, size 0x%lx lma ",
+ bfd_section_name (abfd, s), section_size);
+ print_address_numeric (section_base, 1, gdb_stdout);
+ printf_filtered ("\n");
+ gdb_flush (gdb_stdout);
+ }
+ /* Finally, make the PC point at the start address */
+ write_pc (bfd_get_start_address (abfd));
+ report_transfer_performance (data_count, start_time, end_time);
+ printf_filtered ("Start address 0x%lx\n", bfd_get_start_address (abfd));
+ }
+ inferior_pid = 0; /* No process now */
+
+ /* This is necessary because many things were based on the PC at the
+ time that we attached to the monitor, which is no longer valid
+ now that we have loaded new code (and just changed the PC).
+ Another way to do this might be to call normal_stop, except that
+ the stack may not be valid, and things would get horribly
+ confused... */
+
+ clear_symtab_users ();
+}
+
+#endif /* ! _MSC_VER */
+
+void
+_initialize_m32r_rom ()
+{
+ /* Initialize m32r RevC monitor target */
+ init_m32r_cmds () ;
+ init_monitor_ops (&m32r_ops);
+
+ m32r_ops.to_shortname = "m32r";
+ m32r_ops.to_longname = "m32r monitor";
+ m32r_ops.to_load = m32r_load_gen; /* monitor lacks a download command */
+ m32r_ops.to_doc = "Debug via the m32r monitor.\n\
+Specify the serial device it is connected to (e.g. /dev/ttya).";
+ m32r_ops.to_open = m32r_open;
+ add_target (&m32r_ops);
+
+ /* Initialize mon2000 monitor target */
+ init_mon2000_cmds ();
+ init_monitor_ops (&mon2000_ops);
+
+ mon2000_ops.to_shortname = "mon2000";
+ mon2000_ops.to_longname = "Mon2000 monitor";
+ mon2000_ops.to_load = m32r_load_gen; /* monitor lacks a download command */
+ mon2000_ops.to_doc = "Debug via the Mon2000 monitor.\n\
+Specify the serial device it is connected to (e.g. /dev/ttya).";
+ mon2000_ops.to_open = mon2000_open;
+ add_target (&mon2000_ops);
+
+#ifndef _MSC_VER
+ add_show_from_set
+ (add_set_cmd ("download-path", class_obscure, var_string,
+ (char *) &download_path,
+ "Set the default path for downloadable SREC files.",
+ &setlist),
+ &showlist);
+
+ add_show_from_set
+ (add_set_cmd ("board-address", class_obscure, var_string,
+ (char *) &board_addr,
+ "Set IP address for M32R-EVA target board.",
+ &setlist),
+ &showlist);
+
+ add_show_from_set
+ (add_set_cmd ("server-address", class_obscure, var_string,
+ (char *) &server_addr,
+ "Set IP address for download server (GDB's host computer).",
+ &setlist),
+ &showlist);
+
+ add_com ("upload", class_obscure, m32r_upload_command,
+ "Upload the srec file via the monitor's Ethernet upload capability.");
+
+ add_com ("tload", class_obscure, m32r_load, "test upload command.");
+#endif
+}
diff --git a/gdb/m32r-stub.c b/gdb/m32r-stub.c
new file mode 100644
index 00000000000..60c828ffbe2
--- /dev/null
+++ b/gdb/m32r-stub.c
@@ -0,0 +1,1685 @@
+/****************************************************************************
+
+ THIS SOFTWARE IS NOT COPYRIGHTED
+
+ HP offers the following for use in the public domain. HP makes no
+ warranty with regard to the software or it's performance and the
+ user accepts the software "AS IS" with all faults.
+
+ HP DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD
+ TO THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+
+****************************************************************************/
+
+/****************************************************************************
+ * Header: remcom.c,v 1.34 91/03/09 12:29:49 glenne Exp $
+ *
+ * Module name: remcom.c $
+ * Revision: 1.34 $
+ * Date: 91/03/09 12:29:49 $
+ * Contributor: Lake Stevens Instrument Division$
+ *
+ * Description: low level support for gdb debugger. $
+ *
+ * Considerations: only works on target hardware $
+ *
+ * Written by: Glenn Engel $
+ * ModuleState: Experimental $
+ *
+ * NOTES: See Below $
+ *
+ * Modified for M32R by Michael Snyder, Cygnus Support.
+ *
+ * To enable debugger support, two things need to happen. One, a
+ * call to set_debug_traps() is necessary in order to allow any breakpoints
+ * or error conditions to be properly intercepted and reported to gdb.
+ * Two, a breakpoint needs to be generated to begin communication. This
+ * is most easily accomplished by a call to breakpoint(). Breakpoint()
+ * simulates a breakpoint by executing a trap #1.
+ *
+ * The external function exceptionHandler() is
+ * used to attach a specific handler to a specific M32R vector number.
+ * It should use the same privilege level it runs at. It should
+ * install it as an interrupt gate so that interrupts are masked
+ * while the handler runs.
+ *
+ * Because gdb will sometimes write to the stack area to execute function
+ * calls, this program cannot rely on using the supervisor stack so it
+ * uses it's own stack area reserved in the int array remcomStack.
+ *
+ *************
+ *
+ * The following gdb commands are supported:
+ *
+ * command function Return value
+ *
+ * g return the value of the CPU registers hex data or ENN
+ * G set the value of the CPU registers OK or ENN
+ *
+ * mAA..AA,LLLL Read LLLL bytes at address AA..AA hex data or ENN
+ * MAA..AA,LLLL: Write LLLL bytes at address AA.AA OK or ENN
+ * XAA..AA,LLLL: Write LLLL binary bytes at address OK or ENN
+ * AA..AA
+ *
+ * c Resume at current address SNN ( signal NN)
+ * cAA..AA Continue at address AA..AA SNN
+ *
+ * s Step one instruction SNN
+ * sAA..AA Step one instruction from AA..AA SNN
+ *
+ * k kill
+ *
+ * ? What was the last sigval ? SNN (signal NN)
+ *
+ * All commands and responses are sent with a packet which includes a
+ * checksum. A packet consists of
+ *
+ * $<packet info>#<checksum>.
+ *
+ * where
+ * <packet info> :: <characters representing the command or response>
+ * <checksum> :: <two hex digits computed as modulo 256 sum of <packetinfo>>
+ *
+ * When a packet is received, it is first acknowledged with either '+' or '-'.
+ * '+' indicates a successful transfer. '-' indicates a failed transfer.
+ *
+ * Example:
+ *
+ * Host: Reply:
+ * $m0,10#2a +$00010203040506070809101112131415#42
+ *
+ ****************************************************************************/
+
+
+/************************************************************************
+ *
+ * external low-level support routines
+ */
+extern void putDebugChar(); /* write a single character */
+extern int getDebugChar(); /* read and return a single char */
+extern void exceptionHandler(); /* assign an exception handler */
+
+/*****************************************************************************
+ * BUFMAX defines the maximum number of characters in inbound/outbound buffers
+ * at least NUMREGBYTES*2 are needed for register packets
+ */
+#define BUFMAX 400
+
+static char initialized; /* boolean flag. != 0 means we've been initialized */
+
+int remote_debug;
+/* debug > 0 prints ill-formed commands in valid packets & checksum errors */
+
+static const unsigned char hexchars[]="0123456789abcdef";
+
+#define NUMREGS 24
+
+/* Number of bytes of registers. */
+#define NUMREGBYTES (NUMREGS * 4)
+enum regnames { R0, R1, R2, R3, R4, R5, R6, R7,
+ R8, R9, R10, R11, R12, R13, R14, R15,
+ PSW, CBR, SPI, SPU, BPC, PC, ACCL, ACCH };
+
+enum SYS_calls {
+ SYS_null,
+ SYS_exit,
+ SYS_open,
+ SYS_close,
+ SYS_read,
+ SYS_write,
+ SYS_lseek,
+ SYS_unlink,
+ SYS_getpid,
+ SYS_kill,
+ SYS_fstat,
+ SYS_sbrk,
+ SYS_fork,
+ SYS_execve,
+ SYS_wait4,
+ SYS_link,
+ SYS_chdir,
+ SYS_stat,
+ SYS_utime,
+ SYS_chown,
+ SYS_chmod,
+ SYS_time,
+ SYS_pipe };
+
+static int registers[NUMREGS];
+
+#define STACKSIZE 8096
+static unsigned char remcomInBuffer[BUFMAX];
+static unsigned char remcomOutBuffer[BUFMAX];
+static int remcomStack[STACKSIZE/sizeof(int)];
+static int* stackPtr = &remcomStack[STACKSIZE/sizeof(int) - 1];
+
+static unsigned int save_vectors[18]; /* previous exception vectors */
+
+/* Indicate to caller of mem2hex or hex2mem that there has been an error. */
+static volatile int mem_err = 0;
+
+/* Store the vector number here (since GDB only gets the signal
+ number through the usual means, and that's not very specific). */
+int gdb_m32r_vector = -1;
+
+#if 0
+#include "syscall.h" /* for SYS_exit, SYS_write etc. */
+#endif
+
+/* Global entry points:
+ */
+
+extern void handle_exception(int);
+extern void set_debug_traps(void);
+extern void breakpoint(void);
+
+/* Local functions:
+ */
+
+static int computeSignal(int);
+static void putpacket(unsigned char *);
+static void getpacket(unsigned char *);
+
+static unsigned char *mem2hex(unsigned char *, unsigned char *, int, int);
+static unsigned char *hex2mem(unsigned char *, unsigned char *, int, int);
+static int hexToInt(unsigned char **, int *);
+static unsigned char *bin2mem(unsigned char *, unsigned char *, int, int);
+static void stash_registers(void);
+static void restore_registers(void);
+static int prepare_to_step(int);
+static int finish_from_step(void);
+
+static void gdb_error(char *, char *);
+static int gdb_putchar(int), gdb_puts(char *), gdb_write(char *, int);
+
+static unsigned char *strcpy (unsigned char *, const unsigned char *);
+static int strlen (const unsigned char *);
+
+/*
+ * This function does all command procesing for interfacing to gdb.
+ */
+
+void
+handle_exception(int exceptionVector)
+{
+ int sigval;
+ int addr, length, i;
+ unsigned char * ptr;
+ unsigned char buf[16];
+ int binary;
+
+ if (!finish_from_step())
+ return; /* "false step": let the target continue */
+
+ gdb_m32r_vector = exceptionVector;
+
+ if (remote_debug)
+ {
+ mem2hex((unsigned char *) &exceptionVector, buf, 4, 0);
+ gdb_error("Handle exception %s, ", buf);
+ mem2hex((unsigned char *) &registers[PC], buf, 4, 0);
+ gdb_error("PC == 0x%s\n", buf);
+ }
+
+ /* reply to host that an exception has occurred */
+ sigval = computeSignal( exceptionVector );
+
+ ptr = remcomOutBuffer;
+
+ *ptr++ = 'T'; /* notify gdb with signo, PC, FP and SP */
+ *ptr++ = hexchars[sigval >> 4];
+ *ptr++ = hexchars[sigval & 0xf];
+
+ *ptr++ = hexchars[PC >> 4];
+ *ptr++ = hexchars[PC & 0xf];
+ *ptr++ = ':';
+ ptr = mem2hex((unsigned char *)&registers[PC], ptr, 4, 0); /* PC */
+ *ptr++ = ';';
+
+ *ptr++ = hexchars[R13 >> 4];
+ *ptr++ = hexchars[R13 & 0xf];
+ *ptr++ = ':';
+ ptr = mem2hex((unsigned char *)&registers[R13], ptr, 4, 0); /* FP */
+ *ptr++ = ';';
+
+ *ptr++ = hexchars[R15 >> 4];
+ *ptr++ = hexchars[R15 & 0xf];
+ *ptr++ = ':';
+ ptr = mem2hex((unsigned char *)&registers[R15], ptr, 4, 0); /* SP */
+ *ptr++ = ';';
+ *ptr++ = 0;
+
+ if (exceptionVector == 0) /* simulated SYS call stuff */
+ {
+ mem2hex((unsigned char *) &registers[PC], buf, 4, 0);
+ switch (registers[R0]) {
+ case SYS_exit:
+ gdb_error("Target program has exited at %s\n", buf);
+ ptr = remcomOutBuffer;
+ *ptr++ = 'W';
+ sigval = registers[R1] & 0xff;
+ *ptr++ = hexchars[sigval >> 4];
+ *ptr++ = hexchars[sigval & 0xf];
+ *ptr++ = 0;
+ break;
+ case SYS_open:
+ gdb_error("Target attempts SYS_open call at %s\n", buf);
+ break;
+ case SYS_close:
+ gdb_error("Target attempts SYS_close call at %s\n", buf);
+ break;
+ case SYS_read:
+ gdb_error("Target attempts SYS_read call at %s\n", buf);
+ break;
+ case SYS_write:
+ if (registers[R1] == 1 || /* write to stdout */
+ registers[R1] == 2) /* write to stderr */
+ { /* (we can do that) */
+ registers[R0] = gdb_write((void *) registers[R2], registers[R3]);
+ return;
+ }
+ else
+ gdb_error("Target attempts SYS_write call at %s\n", buf);
+ break;
+ case SYS_lseek:
+ gdb_error("Target attempts SYS_lseek call at %s\n", buf);
+ break;
+ case SYS_unlink:
+ gdb_error("Target attempts SYS_unlink call at %s\n", buf);
+ break;
+ case SYS_getpid:
+ gdb_error("Target attempts SYS_getpid call at %s\n", buf);
+ break;
+ case SYS_kill:
+ gdb_error("Target attempts SYS_kill call at %s\n", buf);
+ break;
+ case SYS_fstat:
+ gdb_error("Target attempts SYS_fstat call at %s\n", buf);
+ break;
+ default:
+ gdb_error("Target attempts unknown SYS call at %s\n", buf);
+ break;
+ }
+ }
+
+ putpacket(remcomOutBuffer);
+
+ while (1==1) {
+ remcomOutBuffer[0] = 0;
+ getpacket(remcomInBuffer);
+ binary = 0;
+ switch (remcomInBuffer[0]) {
+ default: /* Unknown code. Return an empty reply message. */
+ break;
+ case 'R':
+ ptr = &remcomInBuffer[1];
+ if (hexToInt (&ptr, &addr))
+ registers[PC] = addr;
+ strcpy(remcomOutBuffer, "OK");
+ break;
+ case '!':
+ strcpy(remcomOutBuffer, "OK");
+ break;
+ case 'X': /* XAA..AA,LLLL:<binary data>#cs */
+ binary = 1;
+ case 'M': /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
+ /* TRY TO READ '%x,%x:'. IF SUCCEED, SET PTR = 0 */
+ {
+ ptr = &remcomInBuffer[1];
+ if (hexToInt(&ptr,&addr))
+ if (*(ptr++) == ',')
+ if (hexToInt(&ptr,&length))
+ if (*(ptr++) == ':')
+ {
+ mem_err = 0;
+ if (binary)
+ bin2mem (ptr, (unsigned char *) addr, length, 1);
+ else
+ hex2mem(ptr, (unsigned char*) addr, length, 1);
+ if (mem_err) {
+ strcpy (remcomOutBuffer, "E03");
+ gdb_error ("memory fault", "");
+ } else {
+ strcpy(remcomOutBuffer,"OK");
+ }
+ ptr = 0;
+ }
+ if (ptr)
+ {
+ strcpy(remcomOutBuffer,"E02");
+ gdb_error("malformed write memory command: %s",
+ remcomInBuffer);
+ }
+ }
+ break;
+ case 'm': /* mAA..AA,LLLL Read LLLL bytes at address AA..AA */
+ /* TRY TO READ %x,%x. IF SUCCEED, SET PTR = 0 */
+ ptr = &remcomInBuffer[1];
+ if (hexToInt(&ptr,&addr))
+ if (*(ptr++) == ',')
+ if (hexToInt(&ptr,&length))
+ {
+ ptr = 0;
+ mem_err = 0;
+ mem2hex((unsigned char*) addr, remcomOutBuffer, length, 1);
+ if (mem_err) {
+ strcpy (remcomOutBuffer, "E03");
+ gdb_error ("memory fault", "");
+ }
+ }
+ if (ptr)
+ {
+ strcpy(remcomOutBuffer,"E01");
+ gdb_error("malformed read memory command: %s",
+ remcomInBuffer);
+ }
+ break;
+ case '?':
+ remcomOutBuffer[0] = 'S';
+ remcomOutBuffer[1] = hexchars[sigval >> 4];
+ remcomOutBuffer[2] = hexchars[sigval % 16];
+ remcomOutBuffer[3] = 0;
+ break;
+ case 'd':
+ remote_debug = !(remote_debug); /* toggle debug flag */
+ break;
+ case 'g': /* return the value of the CPU registers */
+ mem2hex((unsigned char*) registers, remcomOutBuffer, NUMREGBYTES, 0);
+ break;
+ case 'P': /* set the value of a single CPU register - return OK */
+ {
+ int regno;
+
+ ptr = &remcomInBuffer[1];
+ if (hexToInt (&ptr, &regno) && *ptr++ == '=')
+ if (regno >= 0 && regno < NUMREGS)
+ {
+ int stackmode;
+
+ hex2mem (ptr, (unsigned char *) &registers[regno], 4, 0);
+ /*
+ * Since we just changed a single CPU register, let's
+ * make sure to keep the several stack pointers consistant.
+ */
+ stackmode = registers[PSW] & 0x80;
+ if (regno == R15) /* stack pointer changed */
+ { /* need to change SPI or SPU */
+ if (stackmode == 0)
+ registers[SPI] = registers[R15];
+ else
+ registers[SPU] = registers[R15];
+ }
+ else if (regno == SPU) /* "user" stack pointer changed */
+ {
+ if (stackmode != 0) /* stack in user mode: copy SP */
+ registers[R15] = registers[SPU];
+ }
+ else if (regno == SPI) /* "interrupt" stack pointer changed */
+ {
+ if (stackmode == 0) /* stack in interrupt mode: copy SP */
+ registers[R15] = registers[SPI];
+ }
+ else if (regno == PSW) /* stack mode may have changed! */
+ { /* force SP to either SPU or SPI */
+ if (stackmode == 0) /* stack in user mode */
+ registers[R15] = registers[SPI];
+ else /* stack in interrupt mode */
+ registers[R15] = registers[SPU];
+ }
+ strcpy (remcomOutBuffer, "OK");
+ break;
+ }
+ strcpy (remcomOutBuffer, "P01");
+ break;
+ }
+ case 'G': /* set the value of the CPU registers - return OK */
+ hex2mem(&remcomInBuffer[1], (unsigned char*) registers, NUMREGBYTES, 0);
+ strcpy(remcomOutBuffer,"OK");
+ break;
+ case 's': /* sAA..AA Step one instruction from AA..AA(optional) */
+ case 'c': /* cAA..AA Continue from address AA..AA(optional) */
+ /* try to read optional parameter, pc unchanged if no parm */
+ ptr = &remcomInBuffer[1];
+ if (hexToInt(&ptr,&addr))
+ registers[ PC ] = addr;
+
+ if (remcomInBuffer[0] == 's') /* single-stepping */
+ {
+ if (!prepare_to_step(0)) /* set up for single-step */
+ {
+ /* prepare_to_step has already emulated the target insn:
+ Send SIGTRAP to gdb, don't resume the target at all. */
+ ptr = remcomOutBuffer;
+ *ptr++ = 'T'; /* Simulate stopping with SIGTRAP */
+ *ptr++ = '0';
+ *ptr++ = '5';
+
+ *ptr++ = hexchars[PC >> 4]; /* send PC */
+ *ptr++ = hexchars[PC & 0xf];
+ *ptr++ = ':';
+ ptr = mem2hex((unsigned char *)&registers[PC], ptr, 4, 0);
+ *ptr++ = ';';
+
+ *ptr++ = hexchars[R13 >> 4]; /* send FP */
+ *ptr++ = hexchars[R13 & 0xf];
+ *ptr++ = ':';
+ ptr = mem2hex((unsigned char *)&registers[R13], ptr, 4, 0);
+ *ptr++ = ';';
+
+ *ptr++ = hexchars[R15 >> 4]; /* send SP */
+ *ptr++ = hexchars[R15 & 0xf];
+ *ptr++ = ':';
+ ptr = mem2hex((unsigned char *)&registers[R15], ptr, 4, 0);
+ *ptr++ = ';';
+ *ptr++ = 0;
+
+ break;
+ }
+ }
+ else /* continuing, not single-stepping */
+ {
+ /* OK, about to do a "continue". First check to see if the
+ target pc is on an odd boundary (second instruction in the
+ word). If so, we must do a single-step first, because
+ ya can't jump or return back to an odd boundary! */
+ if ((registers[PC] & 2) != 0)
+ prepare_to_step(1);
+ }
+ return;
+
+ case 'D': /* Detach */
+ /* I am interpreting this to mean, release the board from control
+ by the remote stub. To do this, I am restoring the original
+ (or at least previous) exception vectors.
+ */
+ for (i = 0; i < 18; i++)
+ exceptionHandler (i, save_vectors[i]);
+ putpacket ("OK");
+ return; /* continue the inferior */
+
+ case 'k': /* kill the program */
+ continue;
+ } /* switch */
+
+ /* reply to the request */
+ putpacket(remcomOutBuffer);
+ }
+}
+
+static int
+hex(ch)
+ unsigned char ch;
+{
+ if ((ch >= 'a') && (ch <= 'f')) return (ch-'a'+10);
+ if ((ch >= '0') && (ch <= '9')) return (ch-'0');
+ if ((ch >= 'A') && (ch <= 'F')) return (ch-'A'+10);
+ return (-1);
+}
+
+/* scan for the sequence $<data>#<checksum> */
+
+static void
+getpacket(buffer)
+ unsigned char * buffer;
+{
+ unsigned char checksum;
+ unsigned char xmitcsum;
+ int i;
+ int count;
+ unsigned char ch;
+
+ do {
+ /* wait around for the start character, ignore all other characters */
+ while ((ch = getDebugChar()) != '$');
+ checksum = 0;
+ xmitcsum = -1;
+
+ count = 0;
+
+ /* now, read until a # or end of buffer is found */
+ while (count < BUFMAX) {
+ ch = getDebugChar();
+
+ if (ch == '#' && (count == 0 || buffer[count-1] != 0x7d))
+ break;
+
+ checksum = checksum + ch;
+ buffer[count] = ch;
+ count = count + 1;
+ }
+ buffer[count] = 0;
+
+ if (ch == '#') {
+ xmitcsum = hex(getDebugChar()) << 4;
+ xmitcsum += hex(getDebugChar());
+ if (checksum != xmitcsum) {
+ if (remote_debug) {
+ unsigned char buf[16];
+
+ mem2hex((unsigned char *) &checksum, buf, 4, 0);
+ gdb_error("Bad checksum: my count = %s, ", buf);
+ mem2hex((unsigned char *) &xmitcsum, buf, 4, 0);
+ gdb_error("sent count = %s\n", buf);
+ gdb_error(" -- Bad buffer: \"%s\"\n", buffer);
+ }
+
+ putDebugChar('-'); /* failed checksum */
+ } else {
+ putDebugChar('+'); /* successful transfer */
+ /* if a sequence char is present, reply the sequence ID */
+ if (buffer[2] == ':') {
+ putDebugChar( buffer[0] );
+ putDebugChar( buffer[1] );
+ /* remove sequence chars from buffer */
+ count = strlen(buffer);
+ for (i=3; i <= count; i++) buffer[i-3] = buffer[i];
+ }
+ }
+ }
+ } while (checksum != xmitcsum);
+}
+
+/* send the packet in buffer. */
+
+static void
+putpacket(buffer)
+ unsigned char *buffer;
+{
+ unsigned char checksum;
+ int count;
+ char ch;
+
+ /* $<packet info>#<checksum>. */
+ do {
+ putDebugChar('$');
+ checksum = 0;
+ count = 0;
+
+ while (ch=buffer[count]) {
+ putDebugChar(ch);
+ checksum += ch;
+ count += 1;
+ }
+ putDebugChar('#');
+ putDebugChar(hexchars[checksum >> 4]);
+ putDebugChar(hexchars[checksum % 16]);
+ } while (getDebugChar() != '+');
+}
+
+/* Address of a routine to RTE to if we get a memory fault. */
+
+static void (*volatile mem_fault_routine)() = 0;
+
+static void
+set_mem_err ()
+{
+ mem_err = 1;
+}
+
+/* Check the address for safe access ranges. As currently defined,
+ this routine will reject the "expansion bus" address range(s).
+ To make those ranges useable, someone must implement code to detect
+ whether there's anything connected to the expansion bus. */
+
+static int
+mem_safe (addr)
+ unsigned char *addr;
+{
+#define BAD_RANGE_ONE_START ((unsigned char *) 0x600000)
+#define BAD_RANGE_ONE_END ((unsigned char *) 0xa00000)
+#define BAD_RANGE_TWO_START ((unsigned char *) 0xff680000)
+#define BAD_RANGE_TWO_END ((unsigned char *) 0xff800000)
+
+ if (addr < BAD_RANGE_ONE_START) return 1; /* safe */
+ if (addr < BAD_RANGE_ONE_END) return 0; /* unsafe */
+ if (addr < BAD_RANGE_TWO_START) return 1; /* safe */
+ if (addr < BAD_RANGE_TWO_END) return 0; /* unsafe */
+}
+
+/* These are separate functions so that they are so short and sweet
+ that the compiler won't save any registers (if there is a fault
+ to mem_fault, they won't get restored, so there better not be any
+ saved). */
+static int
+get_char (addr)
+ unsigned char *addr;
+{
+#if 1
+ if (mem_fault_routine && !mem_safe(addr))
+ {
+ mem_fault_routine ();
+ return 0;
+ }
+#endif
+ return *addr;
+}
+
+static void
+set_char (addr, val)
+ unsigned char *addr;
+ unsigned char val;
+{
+#if 1
+ if (mem_fault_routine && !mem_safe (addr))
+ {
+ mem_fault_routine ();
+ return;
+ }
+#endif
+ *addr = val;
+}
+
+/* Convert the memory pointed to by mem into hex, placing result in buf.
+ Return a pointer to the last char put in buf (null).
+ If MAY_FAULT is non-zero, then we should set mem_err in response to
+ a fault; if zero treat a fault like any other fault in the stub. */
+
+static unsigned char *
+mem2hex(mem, buf, count, may_fault)
+ unsigned char* mem;
+ unsigned char* buf;
+ int count;
+ int may_fault;
+{
+ int i;
+ unsigned char ch;
+
+ if (may_fault)
+ mem_fault_routine = set_mem_err;
+ for (i=0;i<count;i++) {
+ ch = get_char (mem++);
+ if (may_fault && mem_err)
+ return (buf);
+ *buf++ = hexchars[ch >> 4];
+ *buf++ = hexchars[ch % 16];
+ }
+ *buf = 0;
+ if (may_fault)
+ mem_fault_routine = 0;
+ return(buf);
+}
+
+/* Convert the hex array pointed to by buf into binary to be placed in mem.
+ Return a pointer to the character AFTER the last byte written. */
+
+static unsigned char*
+hex2mem(buf, mem, count, may_fault)
+ unsigned char* buf;
+ unsigned char* mem;
+ int count;
+ int may_fault;
+{
+ int i;
+ unsigned char ch;
+
+ if (may_fault)
+ mem_fault_routine = set_mem_err;
+ for (i=0;i<count;i++) {
+ ch = hex(*buf++) << 4;
+ ch = ch + hex(*buf++);
+ set_char (mem++, ch);
+ if (may_fault && mem_err)
+ return (mem);
+ }
+ if (may_fault)
+ mem_fault_routine = 0;
+ return(mem);
+}
+
+/* Convert the binary stream in BUF to memory.
+
+ Gdb will escape $, #, and the escape char (0x7d).
+ COUNT is the total number of bytes to write into
+ memory. */
+static unsigned char *
+bin2mem (buf, mem, count, may_fault)
+ unsigned char *buf;
+ unsigned char *mem;
+ int count;
+ int may_fault;
+{
+ int i;
+ unsigned char ch;
+
+ if (may_fault)
+ mem_fault_routine = set_mem_err;
+ for (i = 0; i < count; i++)
+ {
+ /* Check for any escaped characters. Be paranoid and
+ only unescape chars that should be escaped. */
+ if (*buf == 0x7d)
+ {
+ switch (*(buf+1))
+ {
+ case 0x3: /* # */
+ case 0x4: /* $ */
+ case 0x5d: /* escape char */
+ buf++;
+ *buf += 0x20;
+ break;
+ default:
+ /* nothing */
+ break;
+ }
+ }
+
+ set_char (mem++, *buf++);
+
+ if (may_fault && mem_err)
+ return mem;
+ }
+
+ if (may_fault)
+ mem_fault_routine = 0;
+ return mem;
+}
+
+/* this function takes the m32r exception vector and attempts to
+ translate this number into a unix compatible signal value */
+
+static int
+computeSignal(exceptionVector)
+ int exceptionVector;
+{
+ int sigval;
+ switch (exceptionVector) {
+ case 0 : sigval = 23; break; /* I/O trap */
+ case 1 : sigval = 5; break; /* breakpoint */
+ case 2 : sigval = 5; break; /* breakpoint */
+ case 3 : sigval = 5; break; /* breakpoint */
+ case 4 : sigval = 5; break; /* breakpoint */
+ case 5 : sigval = 5; break; /* breakpoint */
+ case 6 : sigval = 5; break; /* breakpoint */
+ case 7 : sigval = 5; break; /* breakpoint */
+ case 8 : sigval = 5; break; /* breakpoint */
+ case 9 : sigval = 5; break; /* breakpoint */
+ case 10 : sigval = 5; break; /* breakpoint */
+ case 11 : sigval = 5; break; /* breakpoint */
+ case 12 : sigval = 5; break; /* breakpoint */
+ case 13 : sigval = 5; break; /* breakpoint */
+ case 14 : sigval = 5; break; /* breakpoint */
+ case 15 : sigval = 5; break; /* breakpoint */
+ case 16 : sigval = 10; break; /* BUS ERROR (alignment) */
+ case 17 : sigval = 2; break; /* INTerrupt */
+ default : sigval = 7; break; /* "software generated" */
+ }
+ return (sigval);
+}
+
+/**********************************************/
+/* WHILE WE FIND NICE HEX CHARS, BUILD AN INT */
+/* RETURN NUMBER OF CHARS PROCESSED */
+/**********************************************/
+static int
+hexToInt(ptr, intValue)
+ unsigned char **ptr;
+ int *intValue;
+{
+ int numChars = 0;
+ int hexValue;
+
+ *intValue = 0;
+ while (**ptr)
+ {
+ hexValue = hex(**ptr);
+ if (hexValue >=0)
+ {
+ *intValue = (*intValue <<4) | hexValue;
+ numChars ++;
+ }
+ else
+ break;
+ (*ptr)++;
+ }
+ return (numChars);
+}
+
+/*
+ Table of branch instructions:
+
+ 10B6 RTE return from trap or exception
+ 1FCr JMP jump
+ 1ECr JL jump and link
+ 7Fxx BRA branch
+ FFxxxxxx BRA branch (long)
+ B09rxxxx BNEZ branch not-equal-zero
+ Br1rxxxx BNE branch not-equal
+ 7Dxx BNC branch not-condition
+ FDxxxxxx BNC branch not-condition (long)
+ B0Arxxxx BLTZ branch less-than-zero
+ B0Crxxxx BLEZ branch less-equal-zero
+ 7Exx BL branch and link
+ FExxxxxx BL branch and link (long)
+ B0Drxxxx BGTZ branch greater-than-zero
+ B0Brxxxx BGEZ branch greater-equal-zero
+ B08rxxxx BEQZ branch equal-zero
+ Br0rxxxx BEQ branch equal
+ 7Cxx BC branch condition
+ FCxxxxxx BC branch condition (long)
+ */
+
+static int
+isShortBranch(instr)
+ unsigned char *instr;
+{
+ unsigned char instr0 = instr[0] & 0x7F; /* mask off high bit */
+
+ if (instr0 == 0x10 && instr[1] == 0xB6) /* RTE */
+ return 1; /* return from trap or exception */
+
+ if (instr0 == 0x1E || instr0 == 0x1F) /* JL or JMP */
+ if ((instr[1] & 0xF0) == 0xC0)
+ return 2; /* jump thru a register */
+
+ if (instr0 == 0x7C || instr0 == 0x7D || /* BC, BNC, BL, BRA */
+ instr0 == 0x7E || instr0 == 0x7F)
+ return 3; /* eight bit PC offset */
+
+ return 0;
+}
+
+static int
+isLongBranch(instr)
+ unsigned char *instr;
+{
+ if (instr[0] == 0xFC || instr[0] == 0xFD || /* BRA, BNC, BL, BC */
+ instr[0] == 0xFE || instr[0] == 0xFF) /* 24 bit relative */
+ return 4;
+ if ((instr[0] & 0xF0) == 0xB0) /* 16 bit relative */
+ {
+ if ((instr[1] & 0xF0) == 0x00 || /* BNE, BEQ */
+ (instr[1] & 0xF0) == 0x10)
+ return 5;
+ if (instr[0] == 0xB0) /* BNEZ, BLTZ, BLEZ, BGTZ, BGEZ, BEQZ */
+ if ((instr[1] & 0xF0) == 0x80 || (instr[1] & 0xF0) == 0x90 ||
+ (instr[1] & 0xF0) == 0xA0 || (instr[1] & 0xF0) == 0xB0 ||
+ (instr[1] & 0xF0) == 0xC0 || (instr[1] & 0xF0) == 0xD0)
+ return 6;
+ }
+ return 0;
+}
+
+/* if address is NOT on a 4-byte boundary, or high-bit of instr is zero,
+ then it's a 2-byte instruction, else it's a 4-byte instruction. */
+
+#define INSTRUCTION_SIZE(addr) \
+ ((((int) addr & 2) || (((unsigned char *) addr)[0] & 0x80) == 0) ? 2 : 4)
+
+static int
+isBranch(instr)
+ unsigned char *instr;
+{
+ if (INSTRUCTION_SIZE(instr) == 2)
+ return isShortBranch(instr);
+ else
+ return isLongBranch(instr);
+}
+
+static int
+willBranch(instr, branchCode)
+ unsigned char *instr;
+{
+ switch (branchCode)
+ {
+ case 0: return 0; /* not a branch */
+ case 1: return 1; /* RTE */
+ case 2: return 1; /* JL or JMP */
+ case 3: /* BC, BNC, BL, BRA (short) */
+ case 4: /* BC, BNC, BL, BRA (long) */
+ switch (instr[0] & 0x0F)
+ {
+ case 0xC: /* Branch if Condition Register */
+ return (registers[CBR] != 0);
+ case 0xD: /* Branch if NOT Condition Register */
+ return (registers[CBR] == 0);
+ case 0xE: /* Branch and Link */
+ case 0xF: /* Branch (unconditional) */
+ return 1;
+ default: /* oops? */
+ return 0;
+ }
+ case 5: /* BNE, BEQ */
+ switch (instr[1] & 0xF0)
+ {
+ case 0x00: /* Branch if r1 equal to r2 */
+ return (registers[instr[0] & 0x0F] == registers[instr[1] & 0x0F]);
+ case 0x10: /* Branch if r1 NOT equal to r2 */
+ return (registers[instr[0] & 0x0F] != registers[instr[1] & 0x0F]);
+ default: /* oops? */
+ return 0;
+ }
+ case 6: /* BNEZ, BLTZ, BLEZ, BGTZ, BGEZ ,BEQZ */
+ switch (instr[1] & 0xF0)
+ {
+ case 0x80: /* Branch if reg equal to zero */
+ return (registers[instr[1] & 0x0F] == 0);
+ case 0x90: /* Branch if reg NOT equal to zero */
+ return (registers[instr[1] & 0x0F] != 0);
+ case 0xA0: /* Branch if reg less than zero */
+ return (registers[instr[1] & 0x0F] < 0);
+ case 0xB0: /* Branch if reg greater or equal to zero */
+ return (registers[instr[1] & 0x0F] >= 0);
+ case 0xC0: /* Branch if reg less than or equal to zero */
+ return (registers[instr[1] & 0x0F] <= 0);
+ case 0xD0: /* Branch if reg greater than zero */
+ return (registers[instr[1] & 0x0F] > 0);
+ default: /* oops? */
+ return 0;
+ }
+ default: /* oops? */
+ return 0;
+ }
+}
+
+static int
+branchDestination(instr, branchCode)
+ unsigned char *instr;
+{
+ switch (branchCode) {
+ default:
+ case 0: /* not a branch */
+ return 0;
+ case 1: /* RTE */
+ return registers[BPC] & ~3; /* pop BPC into PC */
+ case 2: /* JL or JMP */
+ return registers[instr[1] & 0x0F] & ~3; /* jump thru a register */
+ case 3: /* BC, BNC, BL, BRA (short, 8-bit relative offset) */
+ return (((int) instr) & ~3) + ((unsigned char) instr[1] << 2);
+ case 4: /* BC, BNC, BL, BRA (long, 24-bit relative offset) */
+ return ((int) instr +
+ ((((unsigned char) instr[1] << 16) | (instr[2] << 8) | (instr[3])) << 2));
+ case 5: /* BNE, BEQ (16-bit relative offset) */
+ case 6: /* BNEZ, BLTZ, BLEZ, BGTZ, BGEZ ,BEQZ (ditto) */
+ return ((int) instr + ((((unsigned char) instr[2] << 8) | (instr[3])) << 2));
+ }
+
+ /* An explanatory note: in the last three return expressions, I have
+ cast the most-significant byte of the return offset to char.
+ What this accomplishes is sign extension. If the other
+ less-significant bytes were signed as well, they would get sign
+ extended too and, if negative, their leading bits would clobber
+ the bits of the more-significant bytes ahead of them. There are
+ other ways I could have done this, but sign extension from
+ odd-sized integers is always a pain. */
+}
+
+static void
+branchSideEffects(instr, branchCode)
+ unsigned char *instr;
+ int branchCode;
+{
+ switch (branchCode)
+ {
+ case 1: /* RTE */
+ return; /* I <THINK> this is already handled... */
+ case 2: /* JL (or JMP) */
+ case 3: /* BL (or BC, BNC, BRA) */
+ case 4:
+ if ((instr[0] & 0x0F) == 0x0E) /* branch/jump and link */
+ registers[R14] = (registers[PC] & ~3) + 4;
+ return;
+ default: /* any other branch has no side effects */
+ return;
+ }
+}
+
+static struct STEPPING_CONTEXT {
+ int stepping; /* true when we've started a single-step */
+ unsigned long target_addr; /* the instr we're trying to execute */
+ unsigned long target_size; /* the size of the target instr */
+ unsigned long noop_addr; /* where we've inserted a no-op, if any */
+ unsigned long trap1_addr; /* the trap following the target instr */
+ unsigned long trap2_addr; /* the trap at a branch destination, if any */
+ unsigned short noop_save; /* instruction overwritten by our no-op */
+ unsigned short trap1_save; /* instruction overwritten by trap1 */
+ unsigned short trap2_save; /* instruction overwritten by trap2 */
+ unsigned short continue_p; /* true if NOT returning to gdb after step */
+} stepping;
+
+/* Function: prepare_to_step
+ Called from handle_exception to prepare the user program to single-step.
+ Places a trap instruction after the target instruction, with special
+ extra handling for branch instructions and for instructions in the
+ second half-word of a word.
+
+ Returns: True if we should actually execute the instruction;
+ False if we are going to emulate executing the instruction,
+ in which case we simply report to GDB that the instruction
+ has already been executed. */
+
+#define TRAP1 0x10f1; /* trap #1 instruction */
+#define NOOP 0x7000; /* noop instruction */
+
+static unsigned short trap1 = TRAP1;
+static unsigned short noop = NOOP;
+
+static int
+prepare_to_step(continue_p)
+ int continue_p; /* if this isn't REALLY a single-step (see below) */
+{
+ unsigned long pc = registers[PC];
+ int branchCode = isBranch((unsigned char *) pc);
+ unsigned char *p;
+
+ /* zero out the stepping context
+ (paranoia -- it should already be zeroed) */
+ for (p = (unsigned char *) &stepping;
+ p < ((unsigned char *) &stepping) + sizeof(stepping);
+ p++)
+ *p = 0;
+
+ if (branchCode != 0) /* next instruction is a branch */
+ {
+ branchSideEffects((unsigned char *) pc, branchCode);
+ if (willBranch((unsigned char *)pc, branchCode))
+ registers[PC] = branchDestination((unsigned char *) pc, branchCode);
+ else
+ registers[PC] = pc + INSTRUCTION_SIZE(pc);
+ return 0; /* branch "executed" -- just notify GDB */
+ }
+ else if (((int) pc & 2) != 0) /* "second-slot" instruction */
+ {
+ /* insert no-op before pc */
+ stepping.noop_addr = pc - 2;
+ stepping.noop_save = *(unsigned short *) stepping.noop_addr;
+ *(unsigned short *) stepping.noop_addr = noop;
+ /* insert trap after pc */
+ stepping.trap1_addr = pc + 2;
+ stepping.trap1_save = *(unsigned short *) stepping.trap1_addr;
+ *(unsigned short *) stepping.trap1_addr = trap1;
+ }
+ else /* "first-slot" instruction */
+ {
+ /* insert trap after pc */
+ stepping.trap1_addr = pc + INSTRUCTION_SIZE(pc);
+ stepping.trap1_save = *(unsigned short *) stepping.trap1_addr;
+ *(unsigned short *) stepping.trap1_addr = trap1;
+ }
+ /* "continue_p" means that we are actually doing a continue, and not
+ being requested to single-step by GDB. Sometimes we have to do
+ one single-step before continuing, because the PC is on a half-word
+ boundary. There's no way to simply resume at such an address. */
+ stepping.continue_p = continue_p;
+ stepping.stepping = 1; /* starting a single-step */
+ return 1;
+}
+
+/* Function: finish_from_step
+ Called from handle_exception to finish up when the user program
+ returns from a single-step. Replaces the instructions that had
+ been overwritten by traps or no-ops,
+
+ Returns: True if we should notify GDB that the target stopped.
+ False if we only single-stepped because we had to before we
+ could continue (ie. we were trying to continue at a
+ half-word boundary). In that case don't notify GDB:
+ just "continue continuing". */
+
+static int
+finish_from_step()
+{
+ if (stepping.stepping) /* anything to do? */
+ {
+ int continue_p = stepping.continue_p;
+ unsigned char *p;
+
+ if (stepping.noop_addr) /* replace instr "under" our no-op */
+ *(unsigned short *) stepping.noop_addr = stepping.noop_save;
+ if (stepping.trap1_addr) /* replace instr "under" our trap */
+ *(unsigned short *) stepping.trap1_addr = stepping.trap1_save;
+ if (stepping.trap2_addr) /* ditto our other trap, if any */
+ *(unsigned short *) stepping.trap2_addr = stepping.trap2_save;
+
+ for (p = (unsigned char *) &stepping; /* zero out the stepping context */
+ p < ((unsigned char *) &stepping) + sizeof(stepping);
+ p++)
+ *p = 0;
+
+ return !(continue_p);
+ }
+ else /* we didn't single-step, therefore this must be a legitimate stop */
+ return 1;
+}
+
+struct PSWreg { /* separate out the bit flags in the PSW register */
+ int pad1 : 16;
+ int bsm : 1;
+ int bie : 1;
+ int pad2 : 5;
+ int bc : 1;
+ int sm : 1;
+ int ie : 1;
+ int pad3 : 5;
+ int c : 1;
+} *psw;
+
+/* Upon entry the value for LR to save has been pushed.
+ We unpush that so that the value for the stack pointer saved is correct.
+ Upon entry, all other registers are assumed to have not been modified
+ since the interrupt/trap occured. */
+
+asm ("
+stash_registers:
+ push r0
+ push r1
+ seth r1, #shigh(registers)
+ add3 r1, r1, #low(registers)
+ pop r0 ; r1
+ st r0, @(4,r1)
+ pop r0 ; r0
+ st r0, @r1
+ addi r1, #4 ; only add 4 as subsequent saves are `pre inc'
+ st r2, @+r1
+ st r3, @+r1
+ st r4, @+r1
+ st r5, @+r1
+ st r6, @+r1
+ st r7, @+r1
+ st r8, @+r1
+ st r9, @+r1
+ st r10, @+r1
+ st r11, @+r1
+ st r12, @+r1
+ st r13, @+r1 ; fp
+ pop r0 ; lr (r14)
+ st r0, @+r1
+ st sp, @+r1 ; sp contains right value at this point
+ mvfc r0, cr0
+ st r0, @+r1 ; cr0 == PSW
+ mvfc r0, cr1
+ st r0, @+r1 ; cr1 == CBR
+ mvfc r0, cr2
+ st r0, @+r1 ; cr2 == SPI
+ mvfc r0, cr3
+ st r0, @+r1 ; cr3 == SPU
+ mvfc r0, cr6
+ st r0, @+r1 ; cr6 == BPC
+ st r0, @+r1 ; PC == BPC
+ mvfaclo r0
+ st r0, @+r1 ; ACCL
+ mvfachi r0
+ st r0, @+r1 ; ACCH
+ jmp lr");
+
+/* C routine to clean up what stash_registers did.
+ It is called after calling stash_registers.
+ This is separate from stash_registers as we want to do this in C
+ but doing stash_registers in C isn't straightforward. */
+
+static void
+cleanup_stash ()
+{
+ psw = (struct PSWreg *) &registers[PSW]; /* fields of PSW register */
+ psw->sm = psw->bsm; /* fix up pre-trap values of psw fields */
+ psw->ie = psw->bie;
+ psw->c = psw->bc;
+ registers[CBR] = psw->bc; /* fix up pre-trap "C" register */
+
+#if 0 /* FIXME: Was in previous version. Necessary?
+ (Remember that we use the "rte" insn to return from the
+ trap/interrupt so the values of bsm, bie, bc are important. */
+ psw->bsm = psw->bie = psw->bc = 0; /* zero post-trap values */
+#endif
+
+ /* FIXME: Copied from previous version. This can probably be deleted
+ since methinks stash_registers has already done this. */
+ registers[PC] = registers[BPC]; /* pre-trap PC */
+
+ /* FIXME: Copied from previous version. Necessary? */
+ if (psw->sm) /* copy R15 into (psw->sm ? SPU : SPI) */
+ registers[SPU] = registers[R15];
+ else
+ registers[SPI] = registers[R15];
+}
+
+asm ("
+restore_and_return:
+ seth r0, #shigh(registers+8)
+ add3 r0, r0, #low(registers+8)
+ ld r2, @r0+ ; restore r2
+ ld r3, @r0+ ; restore r3
+ ld r4, @r0+ ; restore r4
+ ld r5, @r0+ ; restore r5
+ ld r6, @r0+ ; restore r6
+ ld r7, @r0+ ; restore r7
+ ld r8, @r0+ ; restore r8
+ ld r9, @r0+ ; restore r9
+ ld r10, @r0+ ; restore r10
+ ld r11, @r0+ ; restore r11
+ ld r12, @r0+ ; restore r12
+ ld r13, @r0+ ; restore r13
+ ld r14, @r0+ ; restore r14
+ ld r15, @r0+ ; restore r15
+ ld r1, @r0+ ; restore cr0 == PSW
+ mvtc r1, cr0
+ ld r1, @r0+ ; restore cr1 == CBR (no-op, because it's read only)
+ mvtc r1, cr1
+ ld r1, @r0+ ; restore cr2 == SPI
+ mvtc r1, cr2
+ ld r1, @r0+ ; restore cr3 == SPU
+ mvtc r1, cr3
+ addi r0, #4 ; skip BPC
+ ld r1, @r0+ ; restore cr6 (BPC) == PC
+ mvtc r1, cr6
+ ld r1, @r0+ ; restore ACCL
+ mvtaclo r1
+ ld r1, @r0+ ; restore ACCH
+ mvtachi r1
+ seth r0, #shigh(registers)
+ add3 r0, r0, #low(registers)
+ ld r1, @(4,r0) ; restore r1
+ ld r0, @r0 ; restore r0
+ rte");
+
+/* General trap handler, called after the registers have been stashed.
+ NUM is the trap/exception number. */
+
+static void
+process_exception (num)
+ int num;
+{
+ cleanup_stash ();
+ asm volatile ("
+ seth r1, #shigh(stackPtr)
+ add3 r1, r1, #low(stackPtr)
+ ld r15, @r1 ; setup local stack (protect user stack)
+ mv r0, %0
+ bl handle_exception
+ bl restore_and_return"
+ : : "r" (num) : "r0", "r1");
+}
+
+void _catchException0 ();
+
+asm ("
+_catchException0:
+ push lr
+ bl stash_registers
+ ; Note that at this point the pushed value of `lr' has been popped
+ ldi r0, #0
+ bl process_exception");
+
+void _catchException1 ();
+
+asm ("
+_catchException1:
+ push lr
+ bl stash_registers
+ ; Note that at this point the pushed value of `lr' has been popped
+ bl cleanup_stash
+ seth r1, #shigh(stackPtr)
+ add3 r1, r1, #low(stackPtr)
+ ld r15, @r1 ; setup local stack (protect user stack)
+ seth r1, #shigh(registers + 21*4) ; PC
+ add3 r1, r1, #low(registers + 21*4)
+ ld r0, @r1
+ addi r0, #-4 ; back up PC for breakpoint trap.
+ st r0, @r1 ; FIXME: what about bp in right slot?
+ ldi r0, #1
+ bl handle_exception
+ bl restore_and_return");
+
+void _catchException2 ();
+
+asm ("
+_catchException2:
+ push lr
+ bl stash_registers
+ ; Note that at this point the pushed value of `lr' has been popped
+ ldi r0, #2
+ bl process_exception");
+
+void _catchException3 ();
+
+asm ("
+_catchException3:
+ push lr
+ bl stash_registers
+ ; Note that at this point the pushed value of `lr' has been popped
+ ldi r0, #3
+ bl process_exception");
+
+void _catchException4 ();
+
+asm ("
+_catchException4:
+ push lr
+ bl stash_registers
+ ; Note that at this point the pushed value of `lr' has been popped
+ ldi r0, #4
+ bl process_exception");
+
+void _catchException5 ();
+
+asm ("
+_catchException5:
+ push lr
+ bl stash_registers
+ ; Note that at this point the pushed value of `lr' has been popped
+ ldi r0, #5
+ bl process_exception");
+
+void _catchException6 ();
+
+asm ("
+_catchException6:
+ push lr
+ bl stash_registers
+ ; Note that at this point the pushed value of `lr' has been popped
+ ldi r0, #6
+ bl process_exception");
+
+void _catchException7 ();
+
+asm ("
+_catchException7:
+ push lr
+ bl stash_registers
+ ; Note that at this point the pushed value of `lr' has been popped
+ ldi r0, #7
+ bl process_exception");
+
+void _catchException8 ();
+
+asm ("
+_catchException8:
+ push lr
+ bl stash_registers
+ ; Note that at this point the pushed value of `lr' has been popped
+ ldi r0, #8
+ bl process_exception");
+
+void _catchException9 ();
+
+asm ("
+_catchException9:
+ push lr
+ bl stash_registers
+ ; Note that at this point the pushed value of `lr' has been popped
+ ldi r0, #9
+ bl process_exception");
+
+void _catchException10 ();
+
+asm ("
+_catchException10:
+ push lr
+ bl stash_registers
+ ; Note that at this point the pushed value of `lr' has been popped
+ ldi r0, #10
+ bl process_exception");
+
+void _catchException11 ();
+
+asm ("
+_catchException11:
+ push lr
+ bl stash_registers
+ ; Note that at this point the pushed value of `lr' has been popped
+ ldi r0, #11
+ bl process_exception");
+
+void _catchException12 ();
+
+asm ("
+_catchException12:
+ push lr
+ bl stash_registers
+ ; Note that at this point the pushed value of `lr' has been popped
+ ldi r0, #12
+ bl process_exception");
+
+void _catchException13 ();
+
+asm ("
+_catchException13:
+ push lr
+ bl stash_registers
+ ; Note that at this point the pushed value of `lr' has been popped
+ ldi r0, #13
+ bl process_exception");
+
+void _catchException14 ();
+
+asm ("
+_catchException14:
+ push lr
+ bl stash_registers
+ ; Note that at this point the pushed value of `lr' has been popped
+ ldi r0, #14
+ bl process_exception");
+
+void _catchException15 ();
+
+asm ("
+_catchException15:
+ push lr
+ bl stash_registers
+ ; Note that at this point the pushed value of `lr' has been popped
+ ldi r0, #15
+ bl process_exception");
+
+void _catchException16 ();
+
+asm ("
+_catchException16:
+ push lr
+ bl stash_registers
+ ; Note that at this point the pushed value of `lr' has been popped
+ ldi r0, #16
+ bl process_exception");
+
+void _catchException17 ();
+
+asm ("
+_catchException17:
+ push lr
+ bl stash_registers
+ ; Note that at this point the pushed value of `lr' has been popped
+ ldi r0, #17
+ bl process_exception");
+
+
+/* this function is used to set up exception handlers for tracing and
+ breakpoints */
+void
+set_debug_traps()
+{
+ /* extern void remcomHandler(); */
+ int i;
+
+ for (i = 0; i < 18; i++) /* keep a copy of old vectors */
+ if (save_vectors[i] == 0) /* only copy them the first time */
+ save_vectors[i] = getExceptionHandler (i);
+
+ stackPtr = &remcomStack[STACKSIZE/sizeof(int) - 1];
+
+ exceptionHandler (0, _catchException0);
+ exceptionHandler (1, _catchException1);
+ exceptionHandler (2, _catchException2);
+ exceptionHandler (3, _catchException3);
+ exceptionHandler (4, _catchException4);
+ exceptionHandler (5, _catchException5);
+ exceptionHandler (6, _catchException6);
+ exceptionHandler (7, _catchException7);
+ exceptionHandler (8, _catchException8);
+ exceptionHandler (9, _catchException9);
+ exceptionHandler (10, _catchException10);
+ exceptionHandler (11, _catchException11);
+ exceptionHandler (12, _catchException12);
+ exceptionHandler (13, _catchException13);
+ exceptionHandler (14, _catchException14);
+ exceptionHandler (15, _catchException15);
+ exceptionHandler (16, _catchException16);
+ /* exceptionHandler (17, _catchException17); */
+
+ /* In case GDB is started before us, ack any packets (presumably
+ "$?#xx") sitting there. */
+ putDebugChar ('+');
+
+ initialized = 1;
+}
+
+/* This function will generate a breakpoint exception. It is used at the
+ beginning of a program to sync up with a debugger and can be used
+ otherwise as a quick means to stop program execution and "break" into
+ the debugger. */
+
+#define BREAKPOINT() asm volatile (" trap #2");
+
+void
+breakpoint()
+{
+ if (initialized)
+ BREAKPOINT();
+}
+
+/* STDOUT section:
+ Stuff pertaining to simulating stdout by sending chars to gdb to be echoed.
+ Functions: gdb_putchar(char ch)
+ gdb_puts(char *str)
+ gdb_write(char *str, int len)
+ gdb_error(char *format, char *parm)
+ */
+
+/* Function: gdb_putchar(int)
+ Make gdb write a char to stdout.
+ Returns: the char */
+
+static int
+gdb_putchar(ch)
+ int ch;
+{
+ char buf[4];
+
+ buf[0] = 'O';
+ buf[1] = hexchars[ch >> 4];
+ buf[2] = hexchars[ch & 0x0F];
+ buf[3] = 0;
+ putpacket(buf);
+ return ch;
+}
+
+/* Function: gdb_write(char *, int)
+ Make gdb write n bytes to stdout (not assumed to be null-terminated).
+ Returns: number of bytes written */
+
+static int
+gdb_write(data, len)
+ char *data;
+ int len;
+{
+ char *buf, *cpy;
+ int i;
+
+ buf = remcomOutBuffer;
+ buf[0] = 'O';
+ i = 0;
+ while (i < len)
+ {
+ for (cpy = buf+1;
+ i < len && cpy < buf + sizeof(remcomOutBuffer) - 3;
+ i++)
+ {
+ *cpy++ = hexchars[data[i] >> 4];
+ *cpy++ = hexchars[data[i] & 0x0F];
+ }
+ *cpy = 0;
+ putpacket(buf);
+ }
+ return len;
+}
+
+/* Function: gdb_puts(char *)
+ Make gdb write a null-terminated string to stdout.
+ Returns: the length of the string */
+
+static int
+gdb_puts(str)
+ char *str;
+{
+ return gdb_write(str, strlen(str));
+}
+
+/* Function: gdb_error(char *, char *)
+ Send an error message to gdb's stdout.
+ First string may have 1 (one) optional "%s" in it, which
+ will cause the optional second string to be inserted. */
+
+static void
+gdb_error(format, parm)
+ char * format;
+ char * parm;
+{
+ char buf[400], *cpy;
+ int len;
+
+ if (remote_debug)
+ {
+ if (format && *format)
+ len = strlen(format);
+ else
+ return; /* empty input */
+
+ if (parm && *parm)
+ len += strlen(parm);
+
+ for (cpy = buf; *format; )
+ {
+ if (format[0] == '%' && format[1] == 's') /* include second string */
+ {
+ format += 2; /* advance two chars instead of just one */
+ while (parm && *parm)
+ *cpy++ = *parm++;
+ }
+ else
+ *cpy++ = *format++;
+ }
+ *cpy = '\0';
+ gdb_puts(buf);
+ }
+}
+
+static unsigned char *
+strcpy (unsigned char *dest, const unsigned char *src)
+{
+ unsigned char *ret = dest;
+
+ if (dest && src)
+ {
+ while (*src)
+ *dest++ = *src++;
+ *dest = 0;
+ }
+ return ret;
+}
+
+static int
+strlen (const unsigned char *src)
+{
+ int ret;
+
+ for (ret = 0; *src; src++)
+ ret++;
+
+ return ret;
+}
+
+#if 0
+void exit (code)
+ int code;
+{
+ _exit (code);
+}
+
+int atexit (void *p)
+{
+ return 0;
+}
+
+void abort (void)
+{
+ _exit (1);
+}
+#endif
diff --git a/gdb/m32r-tdep.c b/gdb/m32r-tdep.c
new file mode 100644
index 00000000000..acd34fa84e4
--- /dev/null
+++ b/gdb/m32r-tdep.c
@@ -0,0 +1,745 @@
+/* Target-dependent code for the Mitsubishi m32r for GDB, the GNU debugger.
+ Copyright 1996, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "frame.h"
+#include "inferior.h"
+#include "obstack.h"
+#include "target.h"
+#include "value.h"
+#include "bfd.h"
+#include "gdb_string.h"
+#include "gdbcore.h"
+#include "symfile.h"
+
+/* Function: m32r_use_struct_convention
+ Return nonzero if call_function should allocate stack space for a
+ struct return? */
+int
+m32r_use_struct_convention (gcc_p, type)
+ int gcc_p;
+ struct type *type;
+{
+ return (TYPE_LENGTH (type) > 8);
+}
+
+/* Function: frame_find_saved_regs
+ Return the frame_saved_regs structure for the frame.
+ Doesn't really work for dummy frames, but it does pass back
+ an empty frame_saved_regs, so I guess that's better than total failure */
+
+void
+m32r_frame_find_saved_regs (fi, regaddr)
+ struct frame_info *fi;
+ struct frame_saved_regs *regaddr;
+{
+ memcpy(regaddr, &fi->fsr, sizeof(struct frame_saved_regs));
+}
+
+/* Turn this on if you want to see just how much instruction decoding
+ if being done, its quite a lot
+ */
+#if 0
+static void dump_insn(char * commnt,CORE_ADDR pc, int insn)
+{
+ printf_filtered(" %s %08x %08x ",
+ commnt,(unsigned int)pc,(unsigned int) insn);
+ (*tm_print_insn)(pc,&tm_print_insn_info);
+ printf_filtered("\n");
+}
+#define insn_debug(args) { printf_filtered args; }
+#else
+#define dump_insn(a,b,c) {}
+#define insn_debug(args) {}
+#endif
+
+#define DEFAULT_SEARCH_LIMIT 44
+
+/* Function: scan_prologue
+ This function decodes the target function prologue to determine
+ 1) the size of the stack frame, and 2) which registers are saved on it.
+ It saves the offsets of saved regs in the frame_saved_regs argument,
+ and returns the frame size. */
+
+/*
+ The sequence it currently generates is:
+
+ if (varargs function) { ddi sp,#n }
+ push registers
+ if (additional stack <= 256) { addi sp,#-stack }
+ else if (additional stack < 65k) { add3 sp,sp,#-stack
+
+ } else if (additional stack) {
+ seth sp,#(stack & 0xffff0000)
+ or3 sp,sp,#(stack & 0x0000ffff)
+ sub sp,r4
+ }
+ if (frame pointer) {
+ mv sp,fp
+ }
+
+These instructions are scheduled like everything else, so you should stop at
+the first branch instruction.
+
+*/
+
+/* This is required by skip prologue and by m32r_init_extra_frame_info.
+ The results of decoding a prologue should be cached because this
+ thrashing is getting nuts.
+ I am thinking of making a container class with two indexes, name and
+ address. It may be better to extend the symbol table.
+ */
+
+static void decode_prologue (start_pc, scan_limit,
+ pl_endptr, framelength,
+ fi, fsr)
+ CORE_ADDR start_pc;
+ CORE_ADDR scan_limit;
+ CORE_ADDR * pl_endptr; /* var parameter */
+ unsigned long * framelength;
+ struct frame_info * fi;
+ struct frame_saved_regs * fsr;
+{
+ unsigned long framesize;
+ int insn;
+ int op1;
+ int maybe_one_more = 0;
+ CORE_ADDR after_prologue = 0;
+ CORE_ADDR after_stack_adjust = 0;
+ CORE_ADDR current_pc;
+
+
+ framesize = 0;
+ after_prologue = 0;
+ insn_debug(("rd prolog l(%d)\n",scan_limit - current_pc));
+
+ for (current_pc = start_pc; current_pc < scan_limit; current_pc += 2)
+ {
+
+ insn = read_memory_unsigned_integer (current_pc, 2);
+ dump_insn("insn-1",current_pc,insn); /* MTZ */
+
+ /* If this is a 32 bit instruction, we dont want to examine its
+ immediate data as though it were an instruction */
+ if (current_pc & 0x02)
+ { /* Clear the parallel execution bit from 16 bit instruction */
+ if (maybe_one_more)
+ { /* The last instruction was a branch, usually terminates
+ the series, but if this is a parallel instruction,
+ it may be a stack framing instruction */
+ if (! (insn & 0x8000))
+ { insn_debug(("Really done"));
+ break; /* nope, we are really done */
+ }
+ }
+ insn &= 0x7fff; /* decode this instruction further */
+ }
+ else
+ {
+ if (maybe_one_more)
+ break; /* This isnt the one more */
+ if (insn & 0x8000)
+ {
+ insn_debug(("32 bit insn\n"));
+ if (current_pc == scan_limit)
+ scan_limit += 2; /* extend the search */
+ current_pc += 2; /* skip the immediate data */
+ if (insn == 0x8faf) /* add3 sp, sp, xxxx */
+ /* add 16 bit sign-extended offset */
+ { insn_debug(("stack increment\n"));
+ framesize += -((short) read_memory_unsigned_integer (current_pc, 2));
+ }
+ else
+ {
+ if (((insn >> 8) == 0xe4) && /* ld24 r4, xxxxxx; sub sp, r4 */
+ read_memory_unsigned_integer (current_pc + 2, 2) == 0x0f24)
+ { /* subtract 24 bit sign-extended negative-offset */
+ dump_insn("insn-2",current_pc+2,insn);
+ insn = read_memory_unsigned_integer (current_pc - 2, 4);
+ dump_insn("insn-3(l4)",current_pc -2,insn);
+ if (insn & 0x00800000) /* sign extend */
+ insn |= 0xff000000; /* negative */
+ else
+ insn &= 0x00ffffff; /* positive */
+ framesize += insn;
+ }
+ }
+ after_prologue = current_pc;
+ continue;
+ }
+ }
+ op1 = insn & 0xf000; /* isolate just the first nibble */
+
+ if ((insn & 0xf0ff) == 0x207f)
+ { /* st reg, @-sp */
+ int regno;
+ insn_debug(("push\n"));
+#if 0 /* No, PUSH FP is not an indication that we will use a frame pointer. */
+ if (((insn & 0xffff) == 0x2d7f) && fi)
+ fi->using_frame_pointer = 1;
+#endif
+ framesize += 4;
+#if 0
+/* Why should we increase the scan limit, just because we did a push?
+ And if there is a reason, surely we would only want to do it if we
+ had already reached the scan limit... */
+ if (current_pc == scan_limit)
+ scan_limit += 2;
+#endif
+ regno = ((insn >> 8) & 0xf);
+ if (fsr) /* save_regs offset */
+ fsr->regs[regno] = framesize;
+ after_prologue = 0;
+ continue;
+ }
+ if ((insn >> 8) == 0x4f) /* addi sp, xx */
+ /* add 8 bit sign-extended offset */
+ {
+ int stack_adjust = (char) (insn & 0xff);
+
+ /* there are probably two of these stack adjustments:
+ 1) A negative one in the prologue, and
+ 2) A positive one in the epilogue.
+ We are only interested in the first one. */
+
+ if (stack_adjust < 0)
+ {
+ framesize -= stack_adjust;
+ after_prologue = 0;
+ /* A frameless function may have no "mv fp, sp".
+ In that case, this is the end of the prologue. */
+ after_stack_adjust = current_pc + 2;
+ }
+ continue;
+ }
+ if (insn == 0x1d8f) { /* mv fp, sp */
+ if (fi)
+ fi->using_frame_pointer = 1; /* fp is now valid */
+ insn_debug(("done fp found\n"));
+ after_prologue = current_pc + 2;
+ break; /* end of stack adjustments */
+ }
+ if (insn == 0x7000) /* Nop looks like a branch, continue explicitly */
+ { insn_debug(("nop\n"));
+ after_prologue = current_pc + 2;
+ continue; /* nop occurs between pushes */
+ }
+ /* End of prolog if any of these are branch instructions */
+ if ((op1 == 0x7000)
+ || ( op1 == 0xb000)
+ || (op1 == 0x7000))
+ {
+ after_prologue = current_pc;
+ insn_debug(("Done: branch\n"));
+ maybe_one_more = 1;
+ continue;
+ }
+ /* Some of the branch instructions are mixed with other types */
+ if (op1 == 0x1000)
+ {int subop = insn & 0x0ff0;
+ if ((subop == 0x0ec0) || (subop == 0x0fc0))
+ { insn_debug(("done: jmp\n"));
+ after_prologue = current_pc;
+ maybe_one_more = 1;
+ continue; /* jmp , jl */
+ }
+ }
+ }
+
+ if (current_pc >= scan_limit)
+ {
+ if (pl_endptr)
+#if 1
+ if (after_stack_adjust != 0)
+ /* We did not find a "mv fp,sp", but we DID find
+ a stack_adjust. Is it safe to use that as the
+ end of the prologue? I just don't know. */
+ {
+ *pl_endptr = after_stack_adjust;
+ if (framelength)
+ *framelength = framesize;
+ }
+ else
+#endif
+ /* We reached the end of the loop without finding the end
+ of the prologue. No way to win -- we should report failure.
+ The way we do that is to return the original start_pc.
+ GDB will set a breakpoint at the start of the function (etc.) */
+
+ *pl_endptr = start_pc;
+
+ return;
+ }
+ if (after_prologue == 0)
+ after_prologue = current_pc;
+
+ insn_debug((" framesize %d, firstline %08x\n",framesize,after_prologue));
+ if (framelength)
+ *framelength = framesize;
+ if (pl_endptr)
+ *pl_endptr = after_prologue;
+} /* decode_prologue */
+
+/* Function: skip_prologue
+ Find end of function prologue */
+
+CORE_ADDR
+m32r_skip_prologue (pc)
+ CORE_ADDR pc;
+{
+ CORE_ADDR func_addr, func_end;
+ struct symtab_and_line sal;
+
+ /* See what the symbol table says */
+
+ if (find_pc_partial_function (pc, NULL, &func_addr, &func_end))
+ {
+ sal = find_pc_line (func_addr, 0);
+
+ if (sal.line != 0 && sal.end <= func_end)
+ {
+
+ insn_debug(("BP after prologue %08x\n",sal.end));
+ func_end = sal.end;
+ }
+ else
+ /* Either there's no line info, or the line after the prologue is after
+ the end of the function. In this case, there probably isn't a
+ prologue. */
+ {
+ insn_debug(("No line info, line(%x) sal_end(%x) funcend(%x)\n",
+ sal.line,sal.end,func_end));
+ func_end = min(func_end,func_addr + DEFAULT_SEARCH_LIMIT);
+ }
+ }
+ else
+ func_end = pc + DEFAULT_SEARCH_LIMIT;
+ decode_prologue (pc, func_end, &sal.end, 0, 0, 0);
+ return sal.end;
+}
+
+static unsigned long
+m32r_scan_prologue (fi, fsr)
+ struct frame_info *fi;
+ struct frame_saved_regs *fsr;
+{
+ struct symtab_and_line sal;
+ CORE_ADDR prologue_start, prologue_end, current_pc;
+ unsigned long framesize;
+
+ /* this code essentially duplicates skip_prologue,
+ but we need the start address below. */
+
+ if (find_pc_partial_function (fi->pc, NULL, &prologue_start, &prologue_end))
+ {
+ sal = find_pc_line (prologue_start, 0);
+
+ if (sal.line == 0) /* no line info, use current PC */
+ if (prologue_start == entry_point_address ())
+ return 0;
+ }
+ else
+ {
+ prologue_start = fi->pc;
+ prologue_end = prologue_start + 48; /* We're in the boondocks:
+ allow for 16 pushes, an add,
+ and "mv fp,sp" */
+ }
+#if 0
+ prologue_end = min (prologue_end, fi->pc);
+#endif
+ insn_debug(("fipc(%08x) start(%08x) end(%08x)\n",
+ fi->pc,prologue_start,prologue_end));
+ prologue_end = min(prologue_end, prologue_start + DEFAULT_SEARCH_LIMIT);
+ decode_prologue (prologue_start,prologue_end,&prologue_end,&framesize,
+ fi,fsr);
+ return framesize;
+}
+
+/* Function: init_extra_frame_info
+ This function actually figures out the frame address for a given pc and
+ sp. This is tricky on the m32r because we sometimes don't use an explicit
+ frame pointer, and the previous stack pointer isn't necessarily recorded
+ on the stack. The only reliable way to get this info is to
+ examine the prologue. */
+
+void
+m32r_init_extra_frame_info (fi)
+ struct frame_info *fi;
+{
+ int reg;
+
+ if (fi->next)
+ fi->pc = FRAME_SAVED_PC (fi->next);
+
+ memset (fi->fsr.regs, '\000', sizeof fi->fsr.regs);
+
+ if (PC_IN_CALL_DUMMY (fi->pc, fi->frame, fi->frame))
+ {
+ /* We need to setup fi->frame here because run_stack_dummy gets it wrong
+ by assuming it's always FP. */
+ fi->frame = generic_read_register_dummy (fi->pc, fi->frame, SP_REGNUM);
+ fi->framesize = 0;
+ return;
+ }
+ else
+ {
+ fi->using_frame_pointer = 0;
+ fi->framesize = m32r_scan_prologue (fi, &fi->fsr);
+
+ if (!fi->next)
+ if (fi->using_frame_pointer)
+ {
+ fi->frame = read_register (FP_REGNUM);
+ }
+ else
+ fi->frame = read_register (SP_REGNUM);
+ else /* fi->next means this is not the innermost frame */
+ if (fi->using_frame_pointer) /* we have an FP */
+ if (fi->next->fsr.regs[FP_REGNUM] != 0) /* caller saved our FP */
+ fi->frame = read_memory_integer (fi->next->fsr.regs[FP_REGNUM], 4);
+ for (reg = 0; reg < NUM_REGS; reg++)
+ if (fi->fsr.regs[reg] != 0)
+ fi->fsr.regs[reg] = fi->frame + fi->framesize - fi->fsr.regs[reg];
+ }
+}
+
+/* Function: mn10300_virtual_frame_pointer
+ Return the register that the function uses for a frame pointer,
+ plus any necessary offset to be applied to the register before
+ any frame pointer offsets. */
+
+void
+m32r_virtual_frame_pointer (pc, reg, offset)
+ CORE_ADDR pc;
+ long *reg;
+ long *offset;
+{
+ struct frame_info fi;
+
+ /* Set up a dummy frame_info. */
+ fi.next = NULL;
+ fi.prev = NULL;
+ fi.frame = 0;
+ fi.pc = pc;
+
+ /* Analyze the prolog and fill in the extra info. */
+ m32r_init_extra_frame_info (&fi);
+
+
+ /* Results will tell us which type of frame it uses. */
+ if (fi.using_frame_pointer)
+ {
+ *reg = FP_REGNUM;
+ *offset = 0;
+ }
+ else
+ {
+ *reg = SP_REGNUM;
+ *offset = 0;
+ }
+}
+
+/* Function: find_callers_reg
+ Find REGNUM on the stack. Otherwise, it's in an active register. One thing
+ we might want to do here is to check REGNUM against the clobber mask, and
+ somehow flag it as invalid if it isn't saved on the stack somewhere. This
+ would provide a graceful failure mode when trying to get the value of
+ caller-saves registers for an inner frame. */
+
+CORE_ADDR
+m32r_find_callers_reg (fi, regnum)
+ struct frame_info *fi;
+ int regnum;
+{
+ for (; fi; fi = fi->next)
+ if (PC_IN_CALL_DUMMY (fi->pc, fi->frame, fi->frame))
+ return generic_read_register_dummy (fi->pc, fi->frame, regnum);
+ else if (fi->fsr.regs[regnum] != 0)
+ return read_memory_integer (fi->fsr.regs[regnum],
+ REGISTER_RAW_SIZE(regnum));
+ return read_register (regnum);
+}
+
+/* Function: 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
+ INIT_EXTRA_FRAME_INFO and INIT_FRAME_PC will be called for the new frame.
+ For m32r, we save the frame size when we initialize the frame_info. */
+
+CORE_ADDR
+m32r_frame_chain (fi)
+ struct frame_info *fi;
+{
+ CORE_ADDR fn_start, callers_pc, fp;
+
+ /* is this a dummy frame? */
+ if (PC_IN_CALL_DUMMY(fi->pc, fi->frame, fi->frame))
+ return fi->frame; /* dummy frame same as caller's frame */
+
+ /* is caller-of-this a dummy frame? */
+ callers_pc = FRAME_SAVED_PC(fi); /* find out who called us: */
+ fp = m32r_find_callers_reg (fi, FP_REGNUM);
+ if (PC_IN_CALL_DUMMY(callers_pc, fp, fp))
+ return fp; /* dummy frame's frame may bear no relation to ours */
+
+ if (find_pc_partial_function (fi->pc, 0, &fn_start, 0))
+ if (fn_start == entry_point_address ())
+ return 0; /* in _start fn, don't chain further */
+ if (fi->framesize == 0)
+ {
+ printf_filtered("cannot determine frame size @ %08x , pc(%08x)\n",
+ (unsigned long) fi->frame,
+ (unsigned long) fi->pc );
+ return 0;
+ }
+ insn_debug(("m32rx frame %08x\n",fi->frame+fi->framesize));
+ return fi->frame + fi->framesize;
+}
+
+/* Function: push_return_address (pc)
+ Set up the return address for the inferior function call.
+ Necessary for targets that don't actually execute a JSR/BSR instruction
+ (ie. when using an empty CALL_DUMMY) */
+
+CORE_ADDR
+m32r_push_return_address (pc, sp)
+ CORE_ADDR pc;
+ CORE_ADDR sp;
+{
+ write_register (RP_REGNUM, CALL_DUMMY_ADDRESS ());
+ return sp;
+}
+
+
+/* Function: pop_frame
+ Discard from the stack the innermost frame,
+ restoring all saved registers. */
+
+struct frame_info *
+m32r_pop_frame (frame)
+ struct frame_info *frame;
+{
+ int regnum;
+
+ if (PC_IN_CALL_DUMMY (frame->pc, frame->frame, frame->frame))
+ generic_pop_dummy_frame ();
+ else
+ {
+ for (regnum = 0; regnum < NUM_REGS; regnum++)
+ if (frame->fsr.regs[regnum] != 0)
+ write_register (regnum,
+ read_memory_integer (frame->fsr.regs[regnum], 4));
+
+ write_register (PC_REGNUM, FRAME_SAVED_PC (frame));
+ write_register (SP_REGNUM, read_register (FP_REGNUM));
+ if (read_register (PSW_REGNUM) & 0x80)
+ write_register (SPU_REGNUM, read_register (SP_REGNUM));
+ else
+ write_register (SPI_REGNUM, read_register (SP_REGNUM));
+ }
+ flush_cached_frames ();
+ return NULL;
+}
+
+/* Function: frame_saved_pc
+ Find the caller of this frame. We do this by seeing if RP_REGNUM is saved
+ in the stack anywhere, otherwise we get it from the registers. */
+
+CORE_ADDR
+m32r_frame_saved_pc (fi)
+ struct frame_info *fi;
+{
+ if (PC_IN_CALL_DUMMY(fi->pc, fi->frame, fi->frame))
+ return generic_read_register_dummy(fi->pc, fi->frame, PC_REGNUM);
+ else
+ return m32r_find_callers_reg (fi, RP_REGNUM);
+}
+
+/* Function: push_arguments
+ Setup the function arguments for calling a function in the inferior.
+
+ On the Mitsubishi M32R architecture, there are four registers (R0 to R3)
+ which are dedicated for passing function arguments. Up to the first
+ four arguments (depending on size) may go into these registers.
+ The rest go on the stack.
+
+ Arguments that are smaller than 4 bytes will still take up a whole
+ register or a whole 32-bit word on the stack, and will be
+ right-justified in the register or the stack word. This includes
+ chars, shorts, and small aggregate types.
+
+ Arguments of 8 bytes size are split between two registers, if
+ available. If only one register is available, the argument will
+ be split between the register and the stack. Otherwise it is
+ passed entirely on the stack. Aggregate types with sizes between
+ 4 and 8 bytes are passed entirely on the stack, and are left-justified
+ within the double-word (as opposed to aggregates smaller than 4 bytes
+ which are right-justified).
+
+ Aggregates of greater than 8 bytes are first copied onto the stack,
+ and then a pointer to the copy is passed in the place of the normal
+ argument (either in a register if available, or on the stack).
+
+ Functions that must return an aggregate type can return it in the
+ normal return value registers (R0 and R1) if its size is 8 bytes or
+ less. For larger return values, the caller must allocate space for
+ the callee to copy the return value to. A pointer to this space is
+ passed as an implicit first argument, always in R0. */
+
+CORE_ADDR
+m32r_push_arguments (nargs, args, sp, struct_return, struct_addr)
+ int nargs;
+ value_ptr *args;
+ CORE_ADDR sp;
+ unsigned char struct_return;
+ CORE_ADDR struct_addr;
+{
+ int stack_offset, stack_alloc;
+ int argreg;
+ int argnum;
+ struct type *type;
+ CORE_ADDR regval;
+ char *val;
+ char valbuf[4];
+ int len;
+ int odd_sized_struct;
+
+ /* first force sp to a 4-byte alignment */
+ sp = sp & ~3;
+
+ argreg = ARG0_REGNUM;
+ /* The "struct return pointer" pseudo-argument goes in R0 */
+ if (struct_return)
+ write_register (argreg++, struct_addr);
+
+ /* Now make sure there's space on the stack */
+ for (argnum = 0, stack_alloc = 0;
+ argnum < nargs; argnum++)
+ stack_alloc += ((TYPE_LENGTH(VALUE_TYPE(args[argnum])) + 3) & ~3);
+ sp -= stack_alloc; /* make room on stack for args */
+
+
+ /* Now load as many as possible of the first arguments into
+ registers, and push the rest onto the stack. There are 16 bytes
+ in four registers available. Loop thru args from first to last. */
+
+ argreg = ARG0_REGNUM;
+ for (argnum = 0, stack_offset = 0; argnum < nargs; argnum++)
+ {
+ type = VALUE_TYPE (args[argnum]);
+ len = TYPE_LENGTH (type);
+ memset(valbuf, 0, sizeof(valbuf));
+ if (len < 4)
+ { /* value gets right-justified in the register or stack word */
+ memcpy(valbuf + (4 - len),
+ (char *) VALUE_CONTENTS (args[argnum]), len);
+ val = valbuf;
+ }
+ else
+ val = (char *) VALUE_CONTENTS (args[argnum]);
+
+ if (len > 4 && (len & 3) != 0)
+ odd_sized_struct = 1; /* such structs go entirely on stack */
+ else
+ odd_sized_struct = 0;
+ while (len > 0)
+ {
+ if (argreg > ARGLAST_REGNUM || odd_sized_struct)
+ { /* must go on the stack */
+ write_memory (sp + stack_offset, val, 4);
+ stack_offset += 4;
+ }
+ /* NOTE WELL!!!!! This is not an "else if" clause!!!
+ That's because some *&^%$ things get passed on the stack
+ AND in the registers! */
+ if (argreg <= ARGLAST_REGNUM)
+ { /* there's room in a register */
+ regval = extract_address (val, REGISTER_RAW_SIZE(argreg));
+ write_register (argreg++, regval);
+ }
+ /* Store the value 4 bytes at a time. This means that things
+ larger than 4 bytes may go partly in registers and partly
+ on the stack. */
+ len -= REGISTER_RAW_SIZE(argreg);
+ val += REGISTER_RAW_SIZE(argreg);
+ }
+ }
+ return sp;
+}
+
+/* Function: fix_call_dummy
+ If there is real CALL_DUMMY code (eg. on the stack), this function
+ has the responsability to insert the address of the actual code that
+ is the target of the target function call. */
+
+void
+m32r_fix_call_dummy (dummy, pc, fun, nargs, args, type, gcc_p)
+ char *dummy;
+ CORE_ADDR pc;
+ CORE_ADDR fun;
+ int nargs;
+ value_ptr *args;
+ struct type *type;
+ int gcc_p;
+{
+ /* ld24 r8, <(imm24) fun> */
+ *(unsigned long *) (dummy) = (fun & 0x00ffffff) | 0xe8000000;
+}
+
+/* Function: get_saved_register
+ Just call the generic_get_saved_register function. */
+
+void
+get_saved_register (raw_buffer, optimized, addrp, frame, regnum, lval)
+ char *raw_buffer;
+ int *optimized;
+ CORE_ADDR *addrp;
+ struct frame_info *frame;
+ int regnum;
+ enum lval_type *lval;
+{
+ generic_get_saved_register (raw_buffer, optimized, addrp,
+ frame, regnum, lval);
+}
+
+
+/* Function: m32r_write_sp
+ Because SP is really a read-only register that mirrors either SPU or SPI,
+ we must actually write one of those two as well, depending on PSW. */
+
+void
+m32r_write_sp (val)
+ CORE_ADDR val;
+{
+ unsigned long psw = read_register (PSW_REGNUM);
+
+ if (psw & 0x80) /* stack mode: user or interrupt */
+ write_register (SPU_REGNUM, val);
+ else
+ write_register (SPI_REGNUM, val);
+ write_register (SP_REGNUM, val);
+}
+
+void
+_initialize_m32r_tdep ()
+{
+ tm_print_insn = print_insn_m32r;
+}
+
diff --git a/gdb/m68k-stub.c b/gdb/m68k-stub.c
new file mode 100644
index 00000000000..c2f1d3f89d6
--- /dev/null
+++ b/gdb/m68k-stub.c
@@ -0,0 +1,1014 @@
+/****************************************************************************
+
+ THIS SOFTWARE IS NOT COPYRIGHTED
+
+ HP offers the following for use in the public domain. HP makes no
+ warranty with regard to the software or it's performance and the
+ user accepts the software "AS IS" with all faults.
+
+ HP DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD
+ TO THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+
+****************************************************************************/
+
+/****************************************************************************
+ * Header: remcom.c,v 1.34 91/03/09 12:29:49 glenne Exp $
+ *
+ * Module name: remcom.c $
+ * Revision: 1.34 $
+ * Date: 91/03/09 12:29:49 $
+ * Contributor: Lake Stevens Instrument Division$
+ *
+ * Description: low level support for gdb debugger. $
+ *
+ * Considerations: only works on target hardware $
+ *
+ * Written by: Glenn Engel $
+ * ModuleState: Experimental $
+ *
+ * NOTES: See Below $
+ *
+ * To enable debugger support, two things need to happen. One, a
+ * call to set_debug_traps() is necessary in order to allow any breakpoints
+ * or error conditions to be properly intercepted and reported to gdb.
+ * Two, a breakpoint needs to be generated to begin communication. This
+ * is most easily accomplished by a call to breakpoint(). Breakpoint()
+ * simulates a breakpoint by executing a trap #1. The breakpoint instruction
+ * is hardwired to trap #1 because not to do so is a compatibility problem--
+ * there either should be a standard breakpoint instruction, or the protocol
+ * should be extended to provide some means to communicate which breakpoint
+ * instruction is in use (or have the stub insert the breakpoint).
+ *
+ * Some explanation is probably necessary to explain how exceptions are
+ * handled. When an exception is encountered the 68000 pushes the current
+ * program counter and status register onto the supervisor stack and then
+ * transfers execution to a location specified in it's vector table.
+ * The handlers for the exception vectors are hardwired to jmp to an address
+ * given by the relation: (exception - 256) * 6. These are decending
+ * addresses starting from -6, -12, -18, ... By allowing 6 bytes for
+ * each entry, a jsr, jmp, bsr, ... can be used to enter the exception
+ * handler. Using a jsr to handle an exception has an added benefit of
+ * allowing a single handler to service several exceptions and use the
+ * return address as the key differentiation. The vector number can be
+ * computed from the return address by [ exception = (addr + 1530) / 6 ].
+ * The sole purpose of the routine _catchException is to compute the
+ * exception number and push it on the stack in place of the return address.
+ * The external function exceptionHandler() is
+ * used to attach a specific handler to a specific m68k exception.
+ * For 68020 machines, the ability to have a return address around just
+ * so the vector can be determined is not necessary because the '020 pushes an
+ * extra word onto the stack containing the vector offset
+ *
+ * Because gdb will sometimes write to the stack area to execute function
+ * calls, this program cannot rely on using the supervisor stack so it
+ * uses it's own stack area reserved in the int array remcomStack.
+ *
+ *************
+ *
+ * The following gdb commands are supported:
+ *
+ * command function Return value
+ *
+ * g return the value of the CPU registers hex data or ENN
+ * G set the value of the CPU registers OK or ENN
+ *
+ * mAA..AA,LLLL Read LLLL bytes at address AA..AA hex data or ENN
+ * MAA..AA,LLLL: Write LLLL bytes at address AA.AA OK or ENN
+ *
+ * c Resume at current address SNN ( signal NN)
+ * cAA..AA Continue at address AA..AA SNN
+ *
+ * s Step one instruction SNN
+ * sAA..AA Step one instruction from AA..AA SNN
+ *
+ * k kill
+ *
+ * ? What was the last sigval ? SNN (signal NN)
+ *
+ * All commands and responses are sent with a packet which includes a
+ * checksum. A packet consists of
+ *
+ * $<packet info>#<checksum>.
+ *
+ * where
+ * <packet info> :: <characters representing the command or response>
+ * <checksum> :: < two hex digits computed as modulo 256 sum of <packetinfo>>
+ *
+ * When a packet is received, it is first acknowledged with either '+' or '-'.
+ * '+' indicates a successful transfer. '-' indicates a failed transfer.
+ *
+ * Example:
+ *
+ * Host: Reply:
+ * $m0,10#2a +$00010203040506070809101112131415#42
+ *
+ ****************************************************************************/
+
+#include <stdio.h>
+#include <string.h>
+#include <setjmp.h>
+
+/************************************************************************
+ *
+ * external low-level support routines
+ */
+typedef void (*ExceptionHook)(int); /* pointer to function with int parm */
+typedef void (*Function)(); /* pointer to a function */
+
+extern void putDebugChar(); /* write a single character */
+extern int getDebugChar(); /* read and return a single char */
+
+extern Function exceptionHandler(); /* assign an exception handler */
+extern ExceptionHook exceptionHook; /* hook variable for errors/exceptions */
+
+/************************/
+/* FORWARD DECLARATIONS */
+/************************/
+static void
+initializeRemcomErrorFrame ();
+
+/************************************************************************/
+/* BUFMAX defines the maximum number of characters in inbound/outbound buffers*/
+/* at least NUMREGBYTES*2 are needed for register packets */
+#define BUFMAX 400
+
+static char initialized; /* boolean flag. != 0 means we've been initialized */
+
+int remote_debug;
+/* debug > 0 prints ill-formed commands in valid packets & checksum errors */
+
+static const char hexchars[]="0123456789abcdef";
+
+/* there are 180 bytes of registers on a 68020 w/68881 */
+/* many of the fpa registers are 12 byte (96 bit) registers */
+#define NUMREGBYTES 180
+enum regnames {D0,D1,D2,D3,D4,D5,D6,D7,
+ A0,A1,A2,A3,A4,A5,A6,A7,
+ PS,PC,
+ FP0,FP1,FP2,FP3,FP4,FP5,FP6,FP7,
+ FPCONTROL,FPSTATUS,FPIADDR
+ };
+
+
+/* We keep a whole frame cache here. "Why?", I hear you cry, "doesn't
+ GDB handle that sort of thing?" Well, yes, I believe the only
+ reason for this cache is to save and restore floating point state
+ (fsave/frestore). A cleaner way to do this would be to make the
+ fsave data part of the registers which GDB deals with like any
+ other registers. This should not be a performance problem if the
+ ability to read individual registers is added to the protocol. */
+
+typedef struct FrameStruct
+{
+ struct FrameStruct *previous;
+ int exceptionPC; /* pc value when this frame created */
+ int exceptionVector; /* cpu vector causing exception */
+ short frameSize; /* size of cpu frame in words */
+ short sr; /* for 68000, this not always sr */
+ int pc;
+ short format;
+ int fsaveHeader;
+ int morejunk[0]; /* exception frame, fp save... */
+} Frame;
+
+#define FRAMESIZE 500
+int gdbFrameStack[FRAMESIZE];
+static Frame *lastFrame;
+
+/*
+ * these should not be static cuz they can be used outside this module
+ */
+int registers[NUMREGBYTES/4];
+int superStack;
+
+#define STACKSIZE 10000
+int remcomStack[STACKSIZE/sizeof(int)];
+static int* stackPtr = &remcomStack[STACKSIZE/sizeof(int) - 1];
+
+/*
+ * In many cases, the system will want to continue exception processing
+ * when a continue command is given.
+ * oldExceptionHook is a function to invoke in this case.
+ */
+
+static ExceptionHook oldExceptionHook;
+
+#ifdef mc68020
+/* the size of the exception stack on the 68020 varies with the type of
+ * exception. The following table is the number of WORDS used
+ * for each exception format.
+ */
+const short exceptionSize[] = { 4,4,6,4,4,4,4,4,29,10,16,46,12,4,4,4 };
+#endif
+
+#ifdef mc68332
+static const short exceptionSize[] = { 4,4,6,4,4,4,4,4,4,4,4,4,16,4,4,4 };
+#endif
+
+/************* jump buffer used for setjmp/longjmp **************************/
+jmp_buf remcomEnv;
+
+/*************************** ASSEMBLY CODE MACROS *************************/
+/* */
+
+#ifdef __HAVE_68881__
+/* do an fsave, then remember the address to begin a restore from */
+#define SAVE_FP_REGS() asm(" fsave a0@-"); \
+ asm(" fmovemx fp0-fp7,_registers+72"); \
+ asm(" fmoveml fpcr/fpsr/fpi,_registers+168");
+#define RESTORE_FP_REGS() \
+asm(" \n\
+ fmoveml _registers+168,fpcr/fpsr/fpi \n\
+ fmovemx _registers+72,fp0-fp7 \n\
+ cmpl #-1,a0@ | skip frestore flag set ? \n\
+ beq skip_frestore \n\
+ frestore a0@+ \n\
+skip_frestore: \n\
+");
+
+#else
+#define SAVE_FP_REGS()
+#define RESTORE_FP_REGS()
+#endif /* __HAVE_68881__ */
+
+void return_to_super();
+void return_to_user();
+
+asm("
+.text
+.globl _return_to_super
+_return_to_super:
+ movel _registers+60,sp /* get new stack pointer */
+ movel _lastFrame,a0 /* get last frame info */
+ bra return_to_any
+
+.globl _return_to_user
+_return_to_user:
+ movel _registers+60,a0 /* get usp */
+ movel a0,usp /* set usp */
+ movel _superStack,sp /* get original stack pointer */
+
+return_to_any:
+ movel _lastFrame,a0 /* get last frame info */
+ movel a0@+,_lastFrame /* link in previous frame */
+ addql #8,a0 /* skip over pc, vector#*/
+ movew a0@+,d0 /* get # of words in cpu frame */
+ addw d0,a0 /* point to end of data */
+ addw d0,a0 /* point to end of data */
+ movel a0,a1
+#
+# copy the stack frame
+ subql #1,d0
+copyUserLoop:
+ movew a1@-,sp@-
+ dbf d0,copyUserLoop
+");
+ RESTORE_FP_REGS()
+ asm(" moveml _registers,d0-d7/a0-a6");
+ asm(" rte"); /* pop and go! */
+
+#define DISABLE_INTERRUPTS() asm(" oriw #0x0700,sr");
+#define BREAKPOINT() asm(" trap #1");
+
+/* this function is called immediately when a level 7 interrupt occurs */
+/* if the previous interrupt level was 7 then we're already servicing */
+/* this interrupt and an rte is in order to return to the debugger. */
+/* For the 68000, the offset for sr is 6 due to the jsr return address */
+asm("
+.text
+.globl __debug_level7
+__debug_level7:
+ movew d0,sp@-");
+#if defined (mc68020) || defined (mc68332)
+asm(" movew sp@(2),d0");
+#else
+asm(" movew sp@(6),d0");
+#endif
+asm(" andiw #0x700,d0
+ cmpiw #0x700,d0
+ beq _already7
+ movew sp@+,d0
+ bra __catchException
+_already7:
+ movew sp@+,d0");
+#if !defined (mc68020) && !defined (mc68332)
+asm(" lea sp@(4),sp"); /* pull off 68000 return address */
+#endif
+asm(" rte");
+
+extern void _catchException ();
+
+#if defined (mc68020) || defined (mc68332)
+/* This function is called when a 68020 exception occurs. It saves
+ * all the cpu and fpcp regs in the _registers array, creates a frame on a
+ * linked list of frames which has the cpu and fpcp stack frames needed
+ * to properly restore the context of these processors, and invokes
+ * an exception handler (remcom_handler).
+ *
+ * stack on entry: stack on exit:
+ * N bytes of junk exception # MSWord
+ * Exception Format Word exception # MSWord
+ * Program counter LSWord
+ * Program counter MSWord
+ * Status Register
+ *
+ *
+ */
+asm("
+.text
+.globl __catchException
+__catchException:");
+DISABLE_INTERRUPTS();
+asm("
+ moveml d0-d7/a0-a6,_registers /* save registers */
+ movel _lastFrame,a0 /* last frame pointer */
+");
+SAVE_FP_REGS();
+asm("
+ lea _registers,a5 /* get address of registers */
+ movew sp@,d1 /* get status register */
+ movew d1,a5@(66) /* save sr */
+ movel sp@(2),a4 /* save pc in a4 for later use */
+ movel a4,a5@(68) /* save pc in _regisers[] */
+
+#
+# figure out how many bytes in the stack frame
+ movew sp@(6),d0 /* get '020 exception format */
+ movew d0,d2 /* make a copy of format word */
+ andiw #0xf000,d0 /* mask off format type */
+ rolw #5,d0 /* rotate into the low byte *2 */
+ lea _exceptionSize,a1
+ addw d0,a1 /* index into the table */
+ movew a1@,d0 /* get number of words in frame */
+ movew d0,d3 /* save it */
+ subw d0,a0 /* adjust save pointer */
+ subw d0,a0 /* adjust save pointer(bytes) */
+ movel a0,a1 /* copy save pointer */
+ subql #1,d0 /* predecrement loop counter */
+#
+# copy the frame
+saveFrameLoop:
+ movew sp@+,a1@+
+ dbf d0,saveFrameLoop
+#
+# now that the stack has been clenaed,
+# save the a7 in use at time of exception
+ movel sp,_superStack /* save supervisor sp */
+ andiw #0x2000,d1 /* were we in supervisor mode ? */
+ beq userMode
+ movel a7,a5@(60) /* save a7 */
+ bra a7saveDone
+userMode:
+ movel usp,a1
+ movel a1,a5@(60) /* save user stack pointer */
+a7saveDone:
+
+#
+# save size of frame
+ movew d3,a0@-
+
+#
+# compute exception number
+ andl #0xfff,d2 /* mask off vector offset */
+ lsrw #2,d2 /* divide by 4 to get vect num */
+ movel d2,a0@- /* save it */
+#
+# save pc causing exception
+ movel a4,a0@-
+#
+# save old frame link and set the new value
+ movel _lastFrame,a1 /* last frame pointer */
+ movel a1,a0@- /* save pointer to prev frame */
+ movel a0,_lastFrame
+
+ movel d2,sp@- /* push exception num */
+ movel _exceptionHook,a0 /* get address of handler */
+ jbsr a0@ /* and call it */
+ clrl sp@ /* replace exception num parm with frame ptr */
+ jbsr __returnFromException /* jbsr, but never returns */
+");
+#else /* mc68000 */
+/* This function is called when an exception occurs. It translates the
+ * return address found on the stack into an exception vector # which
+ * is then handled by either handle_exception or a system handler.
+ * _catchException provides a front end for both.
+ *
+ * stack on entry: stack on exit:
+ * Program counter MSWord exception # MSWord
+ * Program counter LSWord exception # MSWord
+ * Status Register
+ * Return Address MSWord
+ * Return Address LSWord
+ */
+asm("
+.text
+.globl __catchException
+__catchException:");
+DISABLE_INTERRUPTS();
+asm("
+ moveml d0-d7/a0-a6,_registers /* save registers */
+ movel _lastFrame,a0 /* last frame pointer */
+");
+SAVE_FP_REGS();
+asm("
+ lea _registers,a5 /* get address of registers */
+ movel sp@+,d2 /* pop return address */
+ addl #1530,d2 /* convert return addr to */
+ divs #6,d2 /* exception number */
+ extl d2
+
+ moveql #3,d3 /* assume a three word frame */
+
+ cmpiw #3,d2 /* bus error or address error ? */
+ bgt normal /* if >3 then normal error */
+ movel sp@+,a0@- /* copy error info to frame buff*/
+ movel sp@+,a0@- /* these are never used */
+ moveql #7,d3 /* this is a 7 word frame */
+
+normal:
+ movew sp@+,d1 /* pop status register */
+ movel sp@+,a4 /* pop program counter */
+ movew d1,a5@(66) /* save sr */
+ movel a4,a5@(68) /* save pc in _regisers[] */
+ movel a4,a0@- /* copy pc to frame buffer */
+ movew d1,a0@- /* copy sr to frame buffer */
+
+ movel sp,_superStack /* save supervisor sp */
+
+ andiw #0x2000,d1 /* were we in supervisor mode ? */
+ beq userMode
+ movel a7,a5@(60) /* save a7 */
+ bra saveDone
+userMode:
+ movel usp,a1 /* save user stack pointer */
+ movel a1,a5@(60) /* save user stack pointer */
+saveDone:
+
+ movew d3,a0@- /* push frame size in words */
+ movel d2,a0@- /* push vector number */
+ movel a4,a0@- /* push exception pc */
+
+#
+# save old frame link and set the new value
+ movel _lastFrame,a1 /* last frame pointer */
+ movel a1,a0@- /* save pointer to prev frame */
+ movel a0,_lastFrame
+
+ movel d2,sp@- /* push exception num */
+ movel _exceptionHook,a0 /* get address of handler */
+ jbsr a0@ /* and call it */
+ clrl sp@ /* replace exception num parm with frame ptr */
+ jbsr __returnFromException /* jbsr, but never returns */
+");
+#endif
+
+
+/*
+ * remcomHandler is a front end for handle_exception. It moves the
+ * stack pointer into an area reserved for debugger use in case the
+ * breakpoint happened in supervisor mode.
+ */
+asm("_remcomHandler:");
+asm(" addl #4,sp"); /* pop off return address */
+asm(" movel sp@+,d0"); /* get the exception number */
+asm(" movel _stackPtr,sp"); /* move to remcom stack area */
+asm(" movel d0,sp@-"); /* push exception onto stack */
+asm(" jbsr _handle_exception"); /* this never returns */
+asm(" rts"); /* return */
+
+void _returnFromException( Frame *frame )
+{
+ /* if no passed in frame, use the last one */
+ if (! frame)
+ {
+ frame = lastFrame;
+ frame->frameSize = 4;
+ frame->format = 0;
+ frame->fsaveHeader = -1; /* restore regs, but we dont have fsave info*/
+ }
+
+#if !defined (mc68020) && !defined (mc68332)
+ /* a 68000 cannot use the internal info pushed onto a bus error
+ * or address error frame when doing an RTE so don't put this info
+ * onto the stack or the stack will creep every time this happens.
+ */
+ frame->frameSize=3;
+#endif
+
+ /* throw away any frames in the list after this frame */
+ lastFrame = frame;
+
+ frame->sr = registers[(int) PS];
+ frame->pc = registers[(int) PC];
+
+ if (registers[(int) PS] & 0x2000)
+ {
+ /* return to supervisor mode... */
+ return_to_super();
+ }
+ else
+ { /* return to user mode */
+ return_to_user();
+ }
+}
+
+int hex(ch)
+char ch;
+{
+ if ((ch >= 'a') && (ch <= 'f')) return (ch-'a'+10);
+ if ((ch >= '0') && (ch <= '9')) return (ch-'0');
+ if ((ch >= 'A') && (ch <= 'F')) return (ch-'A'+10);
+ return (-1);
+}
+
+
+/* scan for the sequence $<data>#<checksum> */
+void getpacket(buffer)
+char * buffer;
+{
+ unsigned char checksum;
+ unsigned char xmitcsum;
+ int i;
+ int count;
+ char ch;
+
+ do {
+ /* wait around for the start character, ignore all other characters */
+ while ((ch = (getDebugChar() & 0x7f)) != '$');
+ checksum = 0;
+ xmitcsum = -1;
+
+ count = 0;
+
+ /* now, read until a # or end of buffer is found */
+ while (count < BUFMAX) {
+ ch = getDebugChar() & 0x7f;
+ if (ch == '#') break;
+ checksum = checksum + ch;
+ buffer[count] = ch;
+ count = count + 1;
+ }
+ buffer[count] = 0;
+
+ if (ch == '#') {
+ xmitcsum = hex(getDebugChar() & 0x7f) << 4;
+ xmitcsum += hex(getDebugChar() & 0x7f);
+ if ((remote_debug ) && (checksum != xmitcsum)) {
+ fprintf (stderr,"bad checksum. My count = 0x%x, sent=0x%x. buf=%s\n",
+ checksum,xmitcsum,buffer);
+ }
+
+ if (checksum != xmitcsum) putDebugChar('-'); /* failed checksum */
+ else {
+ putDebugChar('+'); /* successful transfer */
+ /* if a sequence char is present, reply the sequence ID */
+ if (buffer[2] == ':') {
+ putDebugChar( buffer[0] );
+ putDebugChar( buffer[1] );
+ /* remove sequence chars from buffer */
+ count = strlen(buffer);
+ for (i=3; i <= count; i++) buffer[i-3] = buffer[i];
+ }
+ }
+ }
+ } while (checksum != xmitcsum);
+
+}
+
+/* send the packet in buffer. The host get's one chance to read it.
+ This routine does not wait for a positive acknowledge. */
+
+
+void putpacket(buffer)
+char * buffer;
+{
+ unsigned char checksum;
+ int count;
+ char ch;
+
+ /* $<packet info>#<checksum>. */
+ do {
+ putDebugChar('$');
+ checksum = 0;
+ count = 0;
+
+ while (ch=buffer[count]) {
+ putDebugChar(ch);
+ checksum += ch;
+ count += 1;
+ }
+
+ putDebugChar('#');
+ putDebugChar(hexchars[checksum >> 4]);
+ putDebugChar(hexchars[checksum % 16]);
+
+ } while (1 == 0); /* (getDebugChar() != '+'); */
+
+}
+
+char remcomInBuffer[BUFMAX];
+char remcomOutBuffer[BUFMAX];
+static short error;
+
+
+void debug_error(format, parm)
+char * format;
+char * parm;
+{
+ if (remote_debug) fprintf (stderr,format,parm);
+}
+
+/* convert the memory pointed to by mem into hex, placing result in buf */
+/* return a pointer to the last char put in buf (null) */
+char* mem2hex(mem, buf, count)
+char* mem;
+char* buf;
+int count;
+{
+ int i;
+ unsigned char ch;
+ for (i=0;i<count;i++) {
+ ch = *mem++;
+ *buf++ = hexchars[ch >> 4];
+ *buf++ = hexchars[ch % 16];
+ }
+ *buf = 0;
+ return(buf);
+}
+
+/* convert the hex array pointed to by buf into binary to be placed in mem */
+/* return a pointer to the character AFTER the last byte written */
+char* hex2mem(buf, mem, count)
+char* buf;
+char* mem;
+int count;
+{
+ int i;
+ unsigned char ch;
+ for (i=0;i<count;i++) {
+ ch = hex(*buf++) << 4;
+ ch = ch + hex(*buf++);
+ *mem++ = ch;
+ }
+ return(mem);
+}
+
+/* a bus error has occurred, perform a longjmp
+ to return execution and allow handling of the error */
+
+void handle_buserror()
+{
+ longjmp(remcomEnv,1);
+}
+
+/* this function takes the 68000 exception number and attempts to
+ translate this number into a unix compatible signal value */
+int computeSignal( exceptionVector )
+int exceptionVector;
+{
+ int sigval;
+ switch (exceptionVector) {
+ case 2 : sigval = 10; break; /* bus error */
+ case 3 : sigval = 10; break; /* address error */
+ case 4 : sigval = 4; break; /* illegal instruction */
+ case 5 : sigval = 8; break; /* zero divide */
+ case 6 : sigval = 8; break; /* chk instruction */
+ case 7 : sigval = 8; break; /* trapv instruction */
+ case 8 : sigval = 11; break; /* privilege violation */
+ case 9 : sigval = 5; break; /* trace trap */
+ case 10: sigval = 4; break; /* line 1010 emulator */
+ case 11: sigval = 4; break; /* line 1111 emulator */
+
+ /* Coprocessor protocol violation. Using a standard MMU or FPU
+ this cannot be triggered by software. Call it a SIGBUS. */
+ case 13: sigval = 10; break;
+
+ case 31: sigval = 2; break; /* interrupt */
+ case 33: sigval = 5; break; /* breakpoint */
+
+ /* This is a trap #8 instruction. Apparently it is someone's software
+ convention for some sort of SIGFPE condition. Whose? How many
+ people are being screwed by having this code the way it is?
+ Is there a clean solution? */
+ case 40: sigval = 8; break; /* floating point err */
+
+ case 48: sigval = 8; break; /* floating point err */
+ case 49: sigval = 8; break; /* floating point err */
+ case 50: sigval = 8; break; /* zero divide */
+ case 51: sigval = 8; break; /* underflow */
+ case 52: sigval = 8; break; /* operand error */
+ case 53: sigval = 8; break; /* overflow */
+ case 54: sigval = 8; break; /* NAN */
+ default:
+ sigval = 7; /* "software generated"*/
+ }
+ return (sigval);
+}
+
+/**********************************************/
+/* WHILE WE FIND NICE HEX CHARS, BUILD AN INT */
+/* RETURN NUMBER OF CHARS PROCESSED */
+/**********************************************/
+int hexToInt(char **ptr, int *intValue)
+{
+ int numChars = 0;
+ int hexValue;
+
+ *intValue = 0;
+
+ while (**ptr)
+ {
+ hexValue = hex(**ptr);
+ if (hexValue >=0)
+ {
+ *intValue = (*intValue <<4) | hexValue;
+ numChars ++;
+ }
+ else
+ break;
+
+ (*ptr)++;
+ }
+
+ return (numChars);
+}
+
+/*
+ * This function does all command procesing for interfacing to gdb.
+ */
+void handle_exception(int exceptionVector)
+{
+ int sigval;
+ int addr, length;
+ char * ptr;
+ int newPC;
+ Frame *frame;
+
+ if (remote_debug) printf("vector=%d, sr=0x%x, pc=0x%x\n",
+ exceptionVector,
+ registers[ PS ],
+ registers[ PC ]);
+
+ /* reply to host that an exception has occurred */
+ sigval = computeSignal( exceptionVector );
+ remcomOutBuffer[0] = 'S';
+ remcomOutBuffer[1] = hexchars[sigval >> 4];
+ remcomOutBuffer[2] = hexchars[sigval % 16];
+ remcomOutBuffer[3] = 0;
+
+ putpacket(remcomOutBuffer);
+
+ while (1==1) {
+ error = 0;
+ remcomOutBuffer[0] = 0;
+ getpacket(remcomInBuffer);
+ switch (remcomInBuffer[0]) {
+ case '?' : remcomOutBuffer[0] = 'S';
+ remcomOutBuffer[1] = hexchars[sigval >> 4];
+ remcomOutBuffer[2] = hexchars[sigval % 16];
+ remcomOutBuffer[3] = 0;
+ break;
+ case 'd' : remote_debug = !(remote_debug); /* toggle debug flag */
+ break;
+ case 'g' : /* return the value of the CPU registers */
+ mem2hex((char*) registers, remcomOutBuffer, NUMREGBYTES);
+ break;
+ case 'G' : /* set the value of the CPU registers - return OK */
+ hex2mem(&remcomInBuffer[1], (char*) registers, NUMREGBYTES);
+ strcpy(remcomOutBuffer,"OK");
+ break;
+
+ /* mAA..AA,LLLL Read LLLL bytes at address AA..AA */
+ case 'm' :
+ if (setjmp(remcomEnv) == 0)
+ {
+ exceptionHandler(2,handle_buserror);
+
+ /* TRY TO READ %x,%x. IF SUCCEED, SET PTR = 0 */
+ ptr = &remcomInBuffer[1];
+ if (hexToInt(&ptr,&addr))
+ if (*(ptr++) == ',')
+ if (hexToInt(&ptr,&length))
+ {
+ ptr = 0;
+ mem2hex((char*) addr, remcomOutBuffer, length);
+ }
+
+ if (ptr)
+ {
+ strcpy(remcomOutBuffer,"E01");
+ debug_error("malformed read memory command: %s",remcomInBuffer);
+ }
+ }
+ else {
+ exceptionHandler(2,_catchException);
+ strcpy(remcomOutBuffer,"E03");
+ debug_error("bus error");
+ }
+
+ /* restore handler for bus error */
+ exceptionHandler(2,_catchException);
+ break;
+
+ /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
+ case 'M' :
+ if (setjmp(remcomEnv) == 0) {
+ exceptionHandler(2,handle_buserror);
+
+ /* TRY TO READ '%x,%x:'. IF SUCCEED, SET PTR = 0 */
+ ptr = &remcomInBuffer[1];
+ if (hexToInt(&ptr,&addr))
+ if (*(ptr++) == ',')
+ if (hexToInt(&ptr,&length))
+ if (*(ptr++) == ':')
+ {
+ hex2mem(ptr, (char*) addr, length);
+ ptr = 0;
+ strcpy(remcomOutBuffer,"OK");
+ }
+ if (ptr)
+ {
+ strcpy(remcomOutBuffer,"E02");
+ debug_error("malformed write memory command: %s",remcomInBuffer);
+ }
+ }
+ else {
+ exceptionHandler(2,_catchException);
+ strcpy(remcomOutBuffer,"E03");
+ debug_error("bus error");
+ }
+
+ /* restore handler for bus error */
+ exceptionHandler(2,_catchException);
+ break;
+
+ /* cAA..AA Continue at address AA..AA(optional) */
+ /* sAA..AA Step one instruction from AA..AA(optional) */
+ case 'c' :
+ case 's' :
+ /* try to read optional parameter, pc unchanged if no parm */
+ ptr = &remcomInBuffer[1];
+ if (hexToInt(&ptr,&addr))
+ registers[ PC ] = addr;
+
+ newPC = registers[ PC];
+
+ /* clear the trace bit */
+ registers[ PS ] &= 0x7fff;
+
+ /* set the trace bit if we're stepping */
+ if (remcomInBuffer[0] == 's') registers[ PS ] |= 0x8000;
+
+ /*
+ * look for newPC in the linked list of exception frames.
+ * if it is found, use the old frame it. otherwise,
+ * fake up a dummy frame in returnFromException().
+ */
+ if (remote_debug) printf("new pc = 0x%x\n",newPC);
+ frame = lastFrame;
+ while (frame)
+ {
+ if (remote_debug)
+ printf("frame at 0x%x has pc=0x%x, except#=%d\n",
+ frame,frame->exceptionPC,
+ frame->exceptionVector);
+ if (frame->exceptionPC == newPC) break; /* bingo! a match */
+ /*
+ * for a breakpoint instruction, the saved pc may
+ * be off by two due to re-executing the instruction
+ * replaced by the trap instruction. Check for this.
+ */
+ if ((frame->exceptionVector == 33) &&
+ (frame->exceptionPC == (newPC+2))) break;
+ if (frame == frame->previous)
+ {
+ frame = 0; /* no match found */
+ break;
+ }
+ frame = frame->previous;
+ }
+
+ /*
+ * If we found a match for the PC AND we are not returning
+ * as a result of a breakpoint (33),
+ * trace exception (9), nmi (31), jmp to
+ * the old exception handler as if this code never ran.
+ */
+ if (frame)
+ {
+ if ((frame->exceptionVector != 9) &&
+ (frame->exceptionVector != 31) &&
+ (frame->exceptionVector != 33))
+ {
+ /*
+ * invoke the previous handler.
+ */
+ if (oldExceptionHook)
+ (*oldExceptionHook) (frame->exceptionVector);
+ newPC = registers[ PC ]; /* pc may have changed */
+ if (newPC != frame->exceptionPC)
+ {
+ if (remote_debug)
+ printf("frame at 0x%x has pc=0x%x, except#=%d\n",
+ frame,frame->exceptionPC,
+ frame->exceptionVector);
+ /* re-use the last frame, we're skipping it (longjump?)*/
+ frame = (Frame *) 0;
+ _returnFromException( frame ); /* this is a jump */
+ }
+ }
+ }
+
+ /* if we couldn't find a frame, create one */
+ if (frame == 0)
+ {
+ frame = lastFrame -1 ;
+
+ /* by using a bunch of print commands with breakpoints,
+ it's possible for the frame stack to creep down. If it creeps
+ too far, give up and reset it to the top. Normal use should
+ not see this happen.
+ */
+ if ((unsigned int) (frame-2) < (unsigned int) &gdbFrameStack)
+ {
+ initializeRemcomErrorFrame();
+ frame = lastFrame;
+ }
+ frame->previous = lastFrame;
+ lastFrame = frame;
+ frame = 0; /* null so _return... will properly initialize it */
+ }
+
+ _returnFromException( frame ); /* this is a jump */
+
+ break;
+
+ /* kill the program */
+ case 'k' : /* do nothing */
+ break;
+ } /* switch */
+
+ /* reply to the request */
+ putpacket(remcomOutBuffer);
+ }
+}
+
+
+void
+initializeRemcomErrorFrame()
+{
+ lastFrame = ((Frame *) &gdbFrameStack[FRAMESIZE-1]) - 1;
+ lastFrame->previous = lastFrame;
+}
+
+/* this function is used to set up exception handlers for tracing and
+ breakpoints */
+void set_debug_traps()
+{
+ extern void _debug_level7();
+ extern void remcomHandler();
+ int exception;
+
+ initializeRemcomErrorFrame();
+ stackPtr = &remcomStack[STACKSIZE/sizeof(int) - 1];
+
+ for (exception = 2; exception <= 23; exception++)
+ exceptionHandler(exception,_catchException);
+
+ /* level 7 interrupt */
+ exceptionHandler(31,_debug_level7);
+
+ /* breakpoint exception (trap #1) */
+ exceptionHandler(33,_catchException);
+
+ /* This is a trap #8 instruction. Apparently it is someone's software
+ convention for some sort of SIGFPE condition. Whose? How many
+ people are being screwed by having this code the way it is?
+ Is there a clean solution? */
+ exceptionHandler(40,_catchException);
+
+ /* 48 to 54 are floating point coprocessor errors */
+ for (exception = 48; exception <= 54; exception++)
+ exceptionHandler(exception,_catchException);
+
+ if (oldExceptionHook != remcomHandler)
+ {
+ oldExceptionHook = exceptionHook;
+ exceptionHook = remcomHandler;
+ }
+
+ initialized = 1;
+
+}
+
+/* This function will generate a breakpoint exception. It is used at the
+ beginning of a program to sync up with a debugger and can be used
+ otherwise as a quick means to stop program execution and "break" into
+ the debugger. */
+
+void breakpoint()
+{
+ if (initialized) BREAKPOINT();
+}
+
diff --git a/gdb/m68k-tdep.c b/gdb/m68k-tdep.c
new file mode 100644
index 00000000000..d597efa0ec7
--- /dev/null
+++ b/gdb/m68k-tdep.c
@@ -0,0 +1,516 @@
+/* Target dependent code for the Motorola 68000 series.
+ Copyright (C) 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "frame.h"
+#include "symtab.h"
+#include "gdbcore.h"
+#include "value.h"
+#include "gdb_string.h"
+
+
+/* Push an empty stack frame, to record the current PC, etc. */
+
+void
+m68k_push_dummy_frame ()
+{
+ register CORE_ADDR sp = read_register (SP_REGNUM);
+ register int regnum;
+ char raw_buffer[12];
+
+ sp = push_word (sp, read_register (PC_REGNUM));
+ sp = push_word (sp, read_register (FP_REGNUM));
+ write_register (FP_REGNUM, sp);
+
+ /* Always save the floating-point registers, whether they exist on
+ this target or not. */
+ for (regnum = FP0_REGNUM + 7; regnum >= FP0_REGNUM; regnum--)
+ {
+ read_register_bytes (REGISTER_BYTE (regnum), raw_buffer, 12);
+ sp = push_bytes (sp, raw_buffer, 12);
+ }
+
+ for (regnum = FP_REGNUM - 1; regnum >= 0; regnum--)
+ {
+ sp = push_word (sp, read_register (regnum));
+ }
+ sp = push_word (sp, read_register (PS_REGNUM));
+ write_register (SP_REGNUM, sp);
+}
+
+/* Discard from the stack the innermost frame,
+ restoring all saved registers. */
+
+void
+m68k_pop_frame ()
+{
+ register struct frame_info *frame = get_current_frame ();
+ register CORE_ADDR fp;
+ register int regnum;
+ struct frame_saved_regs fsr;
+ char raw_buffer[12];
+
+ fp = FRAME_FP (frame);
+ get_frame_saved_regs (frame, &fsr);
+ for (regnum = FP0_REGNUM + 7 ; regnum >= FP0_REGNUM ; regnum--)
+ {
+ if (fsr.regs[regnum])
+ {
+ read_memory (fsr.regs[regnum], raw_buffer, 12);
+ write_register_bytes (REGISTER_BYTE (regnum), raw_buffer, 12);
+ }
+ }
+ for (regnum = FP_REGNUM - 1 ; regnum >= 0 ; regnum--)
+ {
+ if (fsr.regs[regnum])
+ {
+ write_register (regnum, read_memory_integer (fsr.regs[regnum], 4));
+ }
+ }
+ if (fsr.regs[PS_REGNUM])
+ {
+ write_register (PS_REGNUM, read_memory_integer (fsr.regs[PS_REGNUM], 4));
+ }
+ write_register (FP_REGNUM, read_memory_integer (fp, 4));
+ write_register (PC_REGNUM, read_memory_integer (fp + 4, 4));
+ write_register (SP_REGNUM, fp + 8);
+ flush_cached_frames ();
+}
+
+
+/* Given an ip value corresponding to the start of a function,
+ return the ip of the first instruction after the function
+ prologue. This is the generic m68k support. Machines which
+ require something different can override the SKIP_PROLOGUE
+ macro to point elsewhere.
+
+ Some instructions which typically may appear in a function
+ prologue include:
+
+ A link instruction, word form:
+
+ link.w %a6,&0 4e56 XXXX
+
+ A link instruction, long form:
+
+ link.l %fp,&F%1 480e XXXX XXXX
+
+ A movm instruction to preserve integer regs:
+
+ movm.l &M%1,(4,%sp) 48ef XXXX XXXX
+
+ A fmovm instruction to preserve float regs:
+
+ fmovm &FPM%1,(FPO%1,%sp) f237 XXXX XXXX XXXX XXXX
+
+ Some profiling setup code (FIXME, not recognized yet):
+
+ lea.l (.L3,%pc),%a1 43fb XXXX XXXX XXXX
+ bsr _mcount 61ff XXXX XXXX
+
+ */
+
+#define P_LINK_L 0x480e
+#define P_LINK_W 0x4e56
+#define P_MOV_L 0x207c
+#define P_JSR 0x4eb9
+#define P_BSR 0x61ff
+#define P_LEA_L 0x43fb
+#define P_MOVM_L 0x48ef
+#define P_FMOVM 0xf237
+#define P_TRAP 0x4e40
+
+CORE_ADDR
+m68k_skip_prologue (ip)
+CORE_ADDR ip;
+{
+ register CORE_ADDR limit;
+ struct symtab_and_line sal;
+ register int op;
+
+ /* Find out if there is a known limit for the extent of the prologue.
+ If so, ensure we don't go past it. If not, assume "infinity". */
+
+ sal = find_pc_line (ip, 0);
+ limit = (sal.end) ? sal.end : (CORE_ADDR) ~0;
+
+ while (ip < limit)
+ {
+ op = read_memory_integer (ip, 2);
+ op &= 0xFFFF;
+
+ if (op == P_LINK_W)
+ {
+ ip += 4; /* Skip link.w */
+ }
+ else if (op == 0x4856)
+ ip += 2; /* Skip pea %fp */
+ else if (op == 0x2c4f)
+ ip += 2; /* Skip move.l %sp, %fp */
+ else if (op == P_LINK_L)
+ {
+ ip += 6; /* Skip link.l */
+ }
+ else if (op == P_MOVM_L)
+ {
+ ip += 6; /* Skip movm.l */
+ }
+ else if (op == P_FMOVM)
+ {
+ ip += 10; /* Skip fmovm */
+ }
+ else
+ {
+ break; /* Found unknown code, bail out. */
+ }
+ }
+ return (ip);
+}
+
+void
+m68k_find_saved_regs (frame_info, saved_regs)
+ struct frame_info *frame_info;
+ struct frame_saved_regs *saved_regs;
+{
+ register int regnum;
+ register int regmask;
+ register CORE_ADDR next_addr;
+ register CORE_ADDR pc;
+
+ /* First possible address for a pc in a call dummy for this frame. */
+ CORE_ADDR possible_call_dummy_start =
+ (frame_info)->frame - CALL_DUMMY_LENGTH - FP_REGNUM*4 - 4 - 8*12;
+
+ int nextinsn;
+ memset (saved_regs, 0, sizeof (*saved_regs));
+ if ((frame_info)->pc >= possible_call_dummy_start
+ && (frame_info)->pc <= (frame_info)->frame)
+ {
+
+ /* It is a call dummy. We could just stop now, since we know
+ what the call dummy saves and where. But this code proceeds
+ to parse the "prologue" which is part of the call dummy.
+ This is needlessly complex and confusing. FIXME. */
+
+ next_addr = (frame_info)->frame;
+ pc = possible_call_dummy_start;
+ }
+ else
+ {
+ pc = get_pc_function_start ((frame_info)->pc);
+
+ if (0x4856 == read_memory_integer (pc, 2)
+ && 0x2c4f == read_memory_integer (pc + 2, 2))
+ {
+ /*
+ pea %fp
+ move.l %sp, %fp */
+
+ pc += 4;
+ next_addr = frame_info->frame;
+ }
+ else if (044016 == read_memory_integer (pc, 2))
+ /* link.l %fp */
+ /* Find the address above the saved
+ regs using the amount of storage from the link instruction. */
+ next_addr = (frame_info)->frame + read_memory_integer (pc += 2, 4), pc+=4;
+ else if (047126 == read_memory_integer (pc, 2))
+ /* link.w %fp */
+ /* Find the address above the saved
+ regs using the amount of storage from the link instruction. */
+ next_addr = (frame_info)->frame + read_memory_integer (pc += 2, 2), pc+=2;
+ else goto lose;
+
+ /* If have an addal #-n, sp next, adjust next_addr. */
+ if ((0177777 & read_memory_integer (pc, 2)) == 0157774)
+ next_addr += read_memory_integer (pc += 2, 4), pc += 4;
+ }
+ regmask = read_memory_integer (pc + 2, 2);
+
+ /* Here can come an fmovem. Check for it. */
+ nextinsn = 0xffff & read_memory_integer (pc, 2);
+ if (0xf227 == nextinsn
+ && (regmask & 0xff00) == 0xe000)
+ { pc += 4; /* Regmask's low bit is for register fp7, the first pushed */
+ for (regnum = FP0_REGNUM + 7; regnum >= FP0_REGNUM; regnum--, regmask >>= 1)
+ if (regmask & 1)
+ saved_regs->regs[regnum] = (next_addr -= 12);
+ regmask = read_memory_integer (pc + 2, 2); }
+
+ /* next should be a moveml to (sp) or -(sp) or a movl r,-(sp) */
+ if (0044327 == read_memory_integer (pc, 2))
+ { pc += 4; /* Regmask's low bit is for register 0, the first written */
+ for (regnum = 0; regnum < 16; regnum++, regmask >>= 1)
+ if (regmask & 1)
+ saved_regs->regs[regnum] = (next_addr += 4) - 4; }
+ else if (0044347 == read_memory_integer (pc, 2))
+ {
+ pc += 4; /* Regmask's low bit is for register 15, the first pushed */
+ for (regnum = 15; regnum >= 0; regnum--, regmask >>= 1)
+ if (regmask & 1)
+ saved_regs->regs[regnum] = (next_addr -= 4);
+ }
+ else if (0x2f00 == (0xfff0 & read_memory_integer (pc, 2)))
+ {
+ regnum = 0xf & read_memory_integer (pc, 2); pc += 2;
+ saved_regs->regs[regnum] = (next_addr -= 4);
+ /* gcc, at least, may use a pair of movel instructions when saving
+ exactly 2 registers. */
+ if (0x2f00 == (0xfff0 & read_memory_integer (pc, 2)))
+ {
+ regnum = 0xf & read_memory_integer (pc, 2);
+ pc += 2;
+ saved_regs->regs[regnum] = (next_addr -= 4);
+ }
+ }
+
+ /* fmovemx to index of sp may follow. */
+ regmask = read_memory_integer (pc + 2, 2);
+ nextinsn = 0xffff & read_memory_integer (pc, 2);
+ if (0xf236 == nextinsn
+ && (regmask & 0xff00) == 0xf000)
+ { pc += 10; /* Regmask's low bit is for register fp0, the first written */
+ for (regnum = FP0_REGNUM + 7; regnum >= FP0_REGNUM; regnum--, regmask >>= 1)
+ if (regmask & 1)
+ saved_regs->regs[regnum] = (next_addr += 12) - 12;
+ regmask = read_memory_integer (pc + 2, 2); }
+
+ /* clrw -(sp); movw ccr,-(sp) may follow. */
+ if (0x426742e7 == read_memory_integer (pc, 4))
+ saved_regs->regs[PS_REGNUM] = (next_addr -= 4);
+ lose: ;
+ saved_regs->regs[SP_REGNUM] = (frame_info)->frame + 8;
+ saved_regs->regs[FP_REGNUM] = (frame_info)->frame;
+ saved_regs->regs[PC_REGNUM] = (frame_info)->frame + 4;
+#ifdef SIG_SP_FP_OFFSET
+ /* Adjust saved SP_REGNUM for fake _sigtramp frames. */
+ if (frame_info->signal_handler_caller && frame_info->next)
+ saved_regs->regs[SP_REGNUM] = frame_info->next->frame + SIG_SP_FP_OFFSET;
+#endif
+}
+
+
+#ifdef USE_PROC_FS /* Target dependent support for /proc */
+
+#include <sys/procfs.h>
+
+/* The /proc interface divides the target machine's register set up into
+ two different sets, the general register set (gregset) and the floating
+ point register set (fpregset). For each set, there is an ioctl to get
+ the current register set and another ioctl to set the current values.
+
+ The actual structure passed through the ioctl interface is, of course,
+ naturally machine dependent, and is different for each set of registers.
+ For the m68k for example, the general register set is typically defined
+ by:
+
+ typedef int gregset_t[18];
+
+ #define R_D0 0
+ ...
+ #define R_PS 17
+
+ and the floating point set by:
+
+ typedef struct fpregset {
+ int f_pcr;
+ int f_psr;
+ int f_fpiaddr;
+ int f_fpregs[8][3]; (8 regs, 96 bits each)
+ } fpregset_t;
+
+ These routines provide the packing and unpacking of gregset_t and
+ fpregset_t formatted data.
+
+ */
+
+/* Atari SVR4 has R_SR but not R_PS */
+
+#if !defined (R_PS) && defined (R_SR)
+#define R_PS R_SR
+#endif
+
+/* Given a pointer to a general register set in /proc format (gregset_t *),
+ unpack the register contents and supply them as gdb's idea of the current
+ register values. */
+
+void
+supply_gregset (gregsetp)
+gregset_t *gregsetp;
+{
+ register int regi;
+ register greg_t *regp = (greg_t *) gregsetp;
+
+ for (regi = 0 ; regi < R_PC ; regi++)
+ {
+ supply_register (regi, (char *) (regp + regi));
+ }
+ supply_register (PS_REGNUM, (char *) (regp + R_PS));
+ supply_register (PC_REGNUM, (char *) (regp + R_PC));
+}
+
+void
+fill_gregset (gregsetp, regno)
+gregset_t *gregsetp;
+int regno;
+{
+ register int regi;
+ register greg_t *regp = (greg_t *) gregsetp;
+ extern char registers[];
+
+ for (regi = 0 ; regi < R_PC ; regi++)
+ {
+ if ((regno == -1) || (regno == regi))
+ {
+ *(regp + regi) = *(int *) &registers[REGISTER_BYTE (regi)];
+ }
+ }
+ if ((regno == -1) || (regno == PS_REGNUM))
+ {
+ *(regp + R_PS) = *(int *) &registers[REGISTER_BYTE (PS_REGNUM)];
+ }
+ if ((regno == -1) || (regno == PC_REGNUM))
+ {
+ *(regp + R_PC) = *(int *) &registers[REGISTER_BYTE (PC_REGNUM)];
+ }
+}
+
+#if defined (FP0_REGNUM)
+
+/* Given a pointer to a floating point register set in /proc format
+ (fpregset_t *), unpack the register contents and supply them as gdb's
+ idea of the current floating point register values. */
+
+void
+supply_fpregset (fpregsetp)
+fpregset_t *fpregsetp;
+{
+ register int regi;
+ char *from;
+
+ for (regi = FP0_REGNUM ; regi < FPC_REGNUM ; regi++)
+ {
+ from = (char *) &(fpregsetp -> f_fpregs[regi-FP0_REGNUM][0]);
+ supply_register (regi, from);
+ }
+ supply_register (FPC_REGNUM, (char *) &(fpregsetp -> f_pcr));
+ supply_register (FPS_REGNUM, (char *) &(fpregsetp -> f_psr));
+ supply_register (FPI_REGNUM, (char *) &(fpregsetp -> f_fpiaddr));
+}
+
+/* Given a pointer to a floating point register set in /proc format
+ (fpregset_t *), update the register specified by REGNO from gdb's idea
+ of the current floating point register set. If REGNO is -1, update
+ them all. */
+
+void
+fill_fpregset (fpregsetp, regno)
+fpregset_t *fpregsetp;
+int regno;
+{
+ int regi;
+ char *to;
+ char *from;
+ extern char registers[];
+
+ for (regi = FP0_REGNUM ; regi < FPC_REGNUM ; regi++)
+ {
+ if ((regno == -1) || (regno == regi))
+ {
+ from = (char *) &registers[REGISTER_BYTE (regi)];
+ to = (char *) &(fpregsetp -> f_fpregs[regi-FP0_REGNUM][0]);
+ memcpy (to, from, REGISTER_RAW_SIZE (regi));
+ }
+ }
+ if ((regno == -1) || (regno == FPC_REGNUM))
+ {
+ fpregsetp -> f_pcr = *(int *) &registers[REGISTER_BYTE (FPC_REGNUM)];
+ }
+ if ((regno == -1) || (regno == FPS_REGNUM))
+ {
+ fpregsetp -> f_psr = *(int *) &registers[REGISTER_BYTE (FPS_REGNUM)];
+ }
+ if ((regno == -1) || (regno == FPI_REGNUM))
+ {
+ fpregsetp -> f_fpiaddr = *(int *) &registers[REGISTER_BYTE (FPI_REGNUM)];
+ }
+}
+
+#endif /* defined (FP0_REGNUM) */
+
+#endif /* USE_PROC_FS */
+
+#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 */
+
+/* Immediately after a function call, return the saved pc before the frame
+ is setup. For sun3's, we check for the common case of being inside of a
+ system call, and if so, we know that Sun pushes the call # on the stack
+ prior to doing the trap. */
+
+CORE_ADDR
+m68k_saved_pc_after_call(frame)
+ struct frame_info *frame;
+{
+#ifdef SYSCALL_TRAP
+ int op;
+
+ op = read_memory_integer (frame->pc - SYSCALL_TRAP_OFFSET, 2);
+
+ if (op == SYSCALL_TRAP)
+ return read_memory_integer (read_register (SP_REGNUM) + 4, 4);
+ else
+#endif /* SYSCALL_TRAP */
+ return read_memory_integer (read_register (SP_REGNUM), 4);
+}
+
+void
+_initialize_m68k_tdep ()
+{
+ tm_print_insn = print_insn_m68k;
+}
diff --git a/gdb/m68klinux-nat.c b/gdb/m68klinux-nat.c
new file mode 100644
index 00000000000..8367b24820b
--- /dev/null
+++ b/gdb/m68klinux-nat.c
@@ -0,0 +1,155 @@
+/* Motorola m68k native support for Linux
+ Copyright (C) 1996,1998 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "frame.h"
+#include "inferior.h"
+#include "language.h"
+#include "gdbcore.h"
+
+#ifdef USG
+#include <sys/types.h>
+#endif
+
+#include <sys/param.h>
+#include <sys/dir.h>
+#include <signal.h>
+#include <sys/user.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <sys/procfs.h>
+
+#include <sys/file.h>
+#include "gdb_stat.h"
+
+#include "floatformat.h"
+
+#include "target.h"
+
+
+/* This table must line up with REGISTER_NAMES in tm-m68k.h */
+static const int regmap[] =
+{
+ PT_D0, PT_D1, PT_D2, PT_D3, PT_D4, PT_D5, PT_D6, PT_D7,
+ PT_A0, PT_A1, PT_A2, PT_A3, PT_A4, PT_A5, PT_A6, PT_USP,
+ PT_SR, PT_PC,
+ /* PT_FP0, ..., PT_FP7 */
+ 21, 24, 27, 30, 33, 36, 39, 42,
+ /* PT_FPCR, PT_FPSR, PT_FPIAR */
+ 45, 46, 47
+};
+
+/* BLOCKEND is the value of u.u_ar0, and points to the place where GS
+ is stored. */
+
+int
+m68k_linux_register_u_addr (blockend, regnum)
+ int blockend;
+ int regnum;
+{
+ return (blockend + 4 * regmap[regnum]);
+}
+
+/* Given a pointer to a general register set in /proc format (gregset_t *),
+ unpack the register contents and supply them as gdb's idea of the current
+ register values. */
+
+
+/* Note both m68k-tdep.c and m68klinux-nat.c contain definitions
+ for supply_gregset and supply_fpregset. The definitions
+ in m68k-tdep.c are valid if USE_PROC_FS is defined. Otherwise,
+ the definitions in m68klinux-nat.c will be used. This is a
+ bit of a hack. The supply_* routines do not belong in
+ *_tdep.c files. But, there are several lynx ports that currently
+ depend on these definitions. */
+
+#ifndef USE_PROC_FS
+
+void
+supply_gregset (gregsetp)
+ gregset_t *gregsetp;
+{
+ int regi;
+
+ for (regi = D0_REGNUM ; regi <= SP_REGNUM ; regi++)
+ supply_register (regi, (char *) (*gregsetp + regmap[regi]));
+ supply_register (PS_REGNUM, (char *) (*gregsetp + PT_SR));
+ supply_register (PC_REGNUM, (char *) (*gregsetp + PT_PC));
+}
+
+/* Given a pointer to a floating point register set in /proc format
+ (fpregset_t *), unpack the register contents and supply them as gdb's
+ idea of the current floating point register values. */
+
+void
+supply_fpregset (fpregsetp)
+ fpregset_t *fpregsetp;
+{
+ int regi;
+
+ for (regi = FP0_REGNUM ; regi < FPC_REGNUM ; regi++)
+ supply_register (regi, (char *) &fpregsetp->fpregs[(regi - FP0_REGNUM) * 3]);
+ supply_register (FPC_REGNUM, (char *) &fpregsetp->fpcntl[0]);
+ supply_register (FPS_REGNUM, (char *) &fpregsetp->fpcntl[1]);
+ supply_register (FPI_REGNUM, (char *) &fpregsetp->fpcntl[2]);
+}
+
+#endif
+
+
+int
+kernel_u_size ()
+{
+ return (sizeof (struct user));
+}
+
+/* Return non-zero if PC points into the signal trampoline. */
+
+int
+in_sigtramp (pc)
+ CORE_ADDR pc;
+{
+ CORE_ADDR sp;
+ char buf[TARGET_SHORT_BIT / TARGET_CHAR_BIT];
+ int insn;
+
+ sp = read_register (SP_REGNUM);
+ if (pc - 2 < sp)
+ return 0;
+
+ if (read_memory_nobpt (pc, buf, sizeof (buf)))
+ return 0;
+ insn = extract_unsigned_integer (buf, sizeof (buf));
+ if (insn == 0xdefc /* addaw #,sp */
+ || insn == 0x7077 /* moveq #119,d0 */
+ || insn == 0x4e40 /* trap #0 */
+ || insn == 0x203c /* movel #,d0 */)
+ return 1;
+
+ if (read_memory_nobpt (pc - 2, buf, sizeof (buf)))
+ return 0;
+ insn = extract_unsigned_integer (buf, sizeof (buf));
+ if (insn == 0xdefc /* addaw #,sp */
+ || insn == 0x7077 /* moveq #119,d0 */
+ || insn == 0x4e40 /* trap #0 */
+ || insn == 0x203c /* movel #,d0 */)
+ return 1;
+
+ return 0;
+}
diff --git a/gdb/m68knbsd-nat.c b/gdb/m68knbsd-nat.c
new file mode 100644
index 00000000000..c2e71dfb570
--- /dev/null
+++ b/gdb/m68knbsd-nat.c
@@ -0,0 +1,86 @@
+/* Native-dependent code for Motorola m68k's running NetBSD, for GDB.
+ Copyright 1988, 1989, 1991, 1992, 1994, 1996 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include <sys/types.h>
+#include <sys/ptrace.h>
+#include <machine/reg.h>
+#include <machine/frame.h>
+
+#include "defs.h"
+#include "inferior.h"
+
+void
+fetch_inferior_registers(regno)
+ int regno;
+{
+ struct reg inferior_registers;
+ struct fpreg inferior_fp_registers;
+
+ ptrace (PT_GETREGS, inferior_pid,
+ (PTRACE_ARG3_TYPE) &inferior_registers, 0);
+ memcpy (&registers[REGISTER_BYTE (0)], &inferior_registers,
+ sizeof(inferior_registers));
+
+ ptrace (PT_GETFPREGS, inferior_pid,
+ (PTRACE_ARG3_TYPE) &inferior_fp_registers, 0);
+ memcpy (&registers[REGISTER_BYTE (FP0_REGNUM)], &inferior_fp_registers,
+ sizeof(inferior_fp_registers));
+
+ registers_fetched ();
+}
+
+void
+store_inferior_registers(regno)
+ int regno;
+{
+ struct reg inferior_registers;
+ struct fpreg inferior_fp_registers;
+
+ memcpy (&inferior_registers, &registers[REGISTER_BYTE (0)],
+ sizeof(inferior_registers));
+ ptrace (PT_SETREGS, inferior_pid,
+ (PTRACE_ARG3_TYPE) &inferior_registers, 0);
+
+ memcpy (&inferior_fp_registers, &registers[REGISTER_BYTE (FP0_REGNUM)],
+ sizeof(inferior_fp_registers));
+ ptrace (PT_SETFPREGS, inferior_pid,
+ (PTRACE_ARG3_TYPE) &inferior_fp_registers, 0);
+}
+
+struct md_core {
+ struct reg intreg;
+ struct fpreg freg;
+};
+
+void
+fetch_core_registers (core_reg_sect, core_reg_size, which, ignore)
+ char *core_reg_sect;
+ unsigned core_reg_size;
+ int which;
+ CORE_ADDR ignore;
+{
+ struct md_core *core_reg = (struct md_core *)core_reg_sect;
+
+ /* Integer registers */
+ memcpy(&registers[REGISTER_BYTE (0)],
+ &core_reg->intreg, sizeof(struct reg));
+ /* Floating point registers */
+ memcpy(&registers[REGISTER_BYTE (FP0_REGNUM)],
+ &core_reg->freg, sizeof(struct fpreg));
+}
diff --git a/gdb/m88k-nat.c b/gdb/m88k-nat.c
new file mode 100644
index 00000000000..19e9392ea66
--- /dev/null
+++ b/gdb/m88k-nat.c
@@ -0,0 +1,285 @@
+/* Native-dependent Motorola 88xxx support for GDB, the GNU Debugger.
+ Copyright 1988, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "frame.h"
+#include "inferior.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/dir.h>
+#include <signal.h>
+#include "gdbcore.h"
+#include <sys/user.h>
+
+#ifndef USER /* added to support BCS ptrace_user */
+#define USER ptrace_user
+#endif
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <sys/file.h>
+#include "gdb_stat.h"
+
+#include "symtab.h"
+#include "setjmp.h"
+#include "value.h"
+
+#ifdef DELTA88
+#include <sys/ptrace.h>
+
+/* define offsets to the pc instruction offsets in ptrace_user struct */
+#define SXIP_OFFSET ((char *)&u.pt_sigframe.sig_sxip - (char *)&u)
+#define SNIP_OFFSET ((char *)&u.pt_sigframe.sig_snip - (char *)&u)
+#define SFIP_OFFSET ((char *)&u.pt_sigframe.sig_sfip - (char *)&u)
+#else
+/* define offsets to the pc instruction offsets in ptrace_user struct */
+#define SXIP_OFFSET ((char *)&u.pt_sigframe.dg_sigframe.sc_sxip - (char *)&u)
+#define SNIP_OFFSET ((char *)&u.pt_sigframe.dg_sigframe.sc_snip - (char *)&u)
+#define SFIP_OFFSET ((char *)&u.pt_sigframe.dg_sigframe.sc_sfip - (char *)&u)
+#endif
+
+extern int have_symbol_file_p();
+
+extern jmp_buf stack_jmp;
+
+extern int errno;
+extern char registers[REGISTER_BYTES];
+
+void
+fetch_inferior_registers (regno)
+ int regno; /* Original value discarded */
+{
+ register unsigned int regaddr;
+ char buf[MAX_REGISTER_RAW_SIZE];
+ register int i;
+
+ struct USER u;
+ unsigned int offset;
+
+ offset = (char *) &u.pt_r0 - (char *) &u;
+ regaddr = offset; /* byte offset to r0;*/
+
+/* offset = ptrace (3, inferior_pid, (PTRACE_ARG3_TYPE) offset, 0) - KERNEL_U_ADDR; */
+ for (regno = 0; regno < NUM_REGS; regno++)
+ {
+ /*regaddr = register_addr (regno, offset);*/
+ /* 88k enhancement */
+
+ for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (int))
+ {
+ *(int *) &buf[i] = ptrace (3, inferior_pid,
+ (PTRACE_ARG3_TYPE) regaddr, 0);
+ regaddr += sizeof (int);
+ }
+ supply_register (regno, buf);
+ }
+ /* now load up registers 36 - 38; special pc registers */
+ *(int *) &buf[0] = ptrace (3,inferior_pid,
+ (PTRACE_ARG3_TYPE) SXIP_OFFSET ,0);
+ supply_register (SXIP_REGNUM, buf);
+ *(int *) &buf[0] = ptrace (3, inferior_pid,
+ (PTRACE_ARG3_TYPE) SNIP_OFFSET,0);
+ supply_register (SNIP_REGNUM, buf);
+ *(int *) &buf[0] = ptrace (3, inferior_pid,
+ (PTRACE_ARG3_TYPE) SFIP_OFFSET,0);
+ supply_register (SFIP_REGNUM, 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). */
+
+void
+store_inferior_registers (regno)
+ int regno;
+{
+ register unsigned int regaddr;
+ char buf[80];
+
+ struct USER u;
+
+ unsigned int offset = (char *) &u.pt_r0 - (char *) &u;
+
+ regaddr = offset;
+
+ /* Don't try to deal with EXIP_REGNUM or ENIP_REGNUM, because I think either
+ svr3 doesn't run on an 88110, or the kernel isolates the different (not
+ completely sure this is true, but seems to be. */
+ if (regno >= 0)
+ {
+ /* regaddr = register_addr (regno, offset); */
+ if (regno < PC_REGNUM)
+ {
+ regaddr = offset + regno * sizeof (int);
+ errno = 0;
+ ptrace (6, inferior_pid,
+ (PTRACE_ARG3_TYPE) regaddr, read_register (regno));
+ if (errno != 0)
+ {
+ sprintf (buf, "writing register number %d", regno);
+ perror_with_name (buf);
+ }
+ }
+ else if (regno == SXIP_REGNUM)
+ ptrace (6, inferior_pid,
+ (PTRACE_ARG3_TYPE) SXIP_OFFSET, read_register(regno));
+ else if (regno == SNIP_REGNUM)
+ ptrace (6, inferior_pid,
+ (PTRACE_ARG3_TYPE) SNIP_OFFSET, read_register(regno));
+ else if (regno == SFIP_REGNUM)
+ ptrace (6, inferior_pid,
+ (PTRACE_ARG3_TYPE) SFIP_OFFSET, read_register(regno));
+ else
+ printf_unfiltered ("Bad register number for store_inferior routine\n");
+ }
+ else
+ {
+ for (regno = 0; regno < PC_REGNUM; regno++)
+ {
+ /* regaddr = register_addr (regno, offset); */
+ errno = 0;
+ regaddr = offset + regno * sizeof (int);
+ ptrace (6, inferior_pid,
+ (PTRACE_ARG3_TYPE) regaddr, read_register (regno));
+ if (errno != 0)
+ {
+ sprintf (buf, "writing register number %d", regno);
+ perror_with_name (buf);
+ }
+ }
+ ptrace (6,inferior_pid,
+ (PTRACE_ARG3_TYPE) SXIP_OFFSET,read_register(SXIP_REGNUM));
+ ptrace (6,inferior_pid,
+ (PTRACE_ARG3_TYPE) SNIP_OFFSET,read_register(SNIP_REGNUM));
+ ptrace (6,inferior_pid,
+ (PTRACE_ARG3_TYPE) SFIP_OFFSET,read_register(SFIP_REGNUM));
+ }
+}
+
+
+/* blockend is the address of the end of the user structure */
+m88k_register_u_addr (blockend, regnum)
+{
+ struct USER u;
+ int ustart = blockend - sizeof (struct USER);
+ switch (regnum)
+ {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ case 8:
+ case 9:
+ case 10:
+ case 11:
+ case 12:
+ case 13:
+ case 14:
+ case 15:
+ case 16:
+ case 17:
+ case 18:
+ case 19:
+ case 20:
+ case 21:
+ case 22:
+ case 23:
+ case 24:
+ case 25:
+ case 26:
+ case 27:
+ case 28:
+ case 29:
+ case 30:
+ case 31:
+ return (ustart + ((int) &u.pt_r0 - (int) &u) + REGISTER_SIZE * regnum);
+ case PSR_REGNUM: return (ustart + ((int) &u.pt_psr - (int) &u));
+ case FPSR_REGNUM: return (ustart + ((int) &u.pt_fpsr - (int) &u));
+ case FPCR_REGNUM: return (ustart + ((int) &u.pt_fpcr - (int) &u));
+ case SXIP_REGNUM: return (ustart + SXIP_OFFSET);
+ case SNIP_REGNUM: return (ustart + SNIP_OFFSET);
+ case SFIP_REGNUM: return (ustart + SFIP_OFFSET);
+ default:
+ if (regnum < NUM_REGS)
+ /* The register is one of those which is not defined...
+ give it zero */
+ return (ustart + ((int) &u.pt_r0 - (int) &u));
+ else
+ return (blockend + REGISTER_SIZE * regnum);
+ }
+}
+
+#ifdef USE_PROC_FS
+
+#include <sys/procfs.h>
+
+/* Given a pointer to a general register set in /proc format (gregset_t *),
+ unpack the register contents and supply them as gdb's idea of the current
+ register values. */
+
+void
+supply_gregset (gregsetp)
+ gregset_t *gregsetp;
+{
+ register int regi;
+ register greg_t *regp = (greg_t *) gregsetp;
+
+ for (regi=0; regi <= SP_REGNUM; regi++)
+ supply_register (regi, (char *) (regp + regi));
+
+ supply_register (SXIP_REGNUM, (char *) (regp + R_XIP));
+ supply_register (SNIP_REGNUM, (char *) (regp + R_NIP));
+ supply_register (SFIP_REGNUM, (char *) (regp + R_FIP));
+ supply_register (PSR_REGNUM, (char *) (regp + R_PSR));
+ supply_register (FPSR_REGNUM, (char *) (regp + R_FPSR));
+ supply_register (FPCR_REGNUM, (char *) (regp + R_FPCR));
+}
+
+void
+fill_gregset (gregsetp, regno)
+ gregset_t *gregsetp;
+ int regno;
+{
+ int regi;
+ register greg_t *regp = (greg_t *) gregsetp;
+ extern char registers[];
+
+ for (regi = 0 ; regi <= R_R31 ; regi++)
+ if ((regno == -1) || (regno == regi))
+ *(regp + regi) = *(int *) &registers[REGISTER_BYTE(regi)];
+
+ if ((regno == -1) || (regno == SXIP_REGNUM))
+ *(regp + R_XIP) = *(int *) &registers[REGISTER_BYTE(SXIP_REGNUM)];
+ if ((regno == -1) || (regno == SNIP_REGNUM))
+ *(regp + R_NIP) = *(int *) &registers[REGISTER_BYTE(SNIP_REGNUM)];
+ if ((regno == -1) || (regno == SFIP_REGNUM))
+ *(regp + R_FIP) = *(int *) &registers[REGISTER_BYTE(SFIP_REGNUM)];
+ if ((regno == -1) || (regno == PSR_REGNUM))
+ *(regp + R_PSR) = *(int *) &registers[REGISTER_BYTE(PSR_REGNUM)];
+ if ((regno == -1) || (regno == FPSR_REGNUM))
+ *(regp + R_FPSR) = *(int *) &registers[REGISTER_BYTE(FPSR_REGNUM)];
+ if ((regno == -1) || (regno == FPCR_REGNUM))
+ *(regp + R_FPCR) = *(int *) &registers[REGISTER_BYTE(FPCR_REGNUM)];
+}
+
+#endif /* USE_PROC_FS */
diff --git a/gdb/m88k-tdep.c b/gdb/m88k-tdep.c
new file mode 100644
index 00000000000..f82cb764d06
--- /dev/null
+++ b/gdb/m88k-tdep.c
@@ -0,0 +1,629 @@
+/* Target-machine dependent code for Motorola 88000 series, for GDB.
+ Copyright 1988, 1990, 1991, 1994, 1995 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "frame.h"
+#include "inferior.h"
+#include "value.h"
+#include "gdbcore.h"
+#include "symtab.h"
+#include "setjmp.h"
+#include "value.h"
+
+/* Size of an instruction */
+#define BYTES_PER_88K_INSN 4
+
+void frame_find_saved_regs ();
+
+/* Is this target an m88110? Otherwise assume m88100. This has
+ relevance for the ways in which we screw with instruction pointers. */
+
+int target_is_m88110 = 0;
+
+/* The m88k kernel aligns all instructions on 4-byte boundaries. The
+ kernel also uses the least significant two bits for its own hocus
+ pocus. When gdb receives an address from the kernel, it needs to
+ preserve those right-most two bits, but gdb also needs to be careful
+ to realize that those two bits are not really a part of the address
+ of an instruction. Shrug. */
+
+CORE_ADDR
+m88k_addr_bits_remove (addr)
+ CORE_ADDR addr;
+{
+ return ((addr) & ~3);
+}
+
+
+/* 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
+ INIT_EXTRA_FRAME_INFO and INIT_FRAME_PC will be called for the new frame.
+
+ For us, the frame address is its stack pointer value, so we look up
+ the function prologue to determine the caller's sp value, and return it. */
+
+CORE_ADDR
+frame_chain (thisframe)
+ struct frame_info *thisframe;
+{
+
+ frame_find_saved_regs (thisframe, (struct frame_saved_regs *) 0);
+ /* NOTE: this depends on frame_find_saved_regs returning the VALUE, not
+ the ADDRESS, of SP_REGNUM. It also depends on the cache of
+ frame_find_saved_regs results. */
+ if (thisframe->fsr->regs[SP_REGNUM])
+ return thisframe->fsr->regs[SP_REGNUM];
+ else
+ return thisframe->frame; /* Leaf fn -- next frame up has same SP. */
+}
+
+int
+frameless_function_invocation (frame)
+ struct frame_info *frame;
+{
+
+ frame_find_saved_regs (frame, (struct frame_saved_regs *) 0);
+ /* NOTE: this depends on frame_find_saved_regs returning the VALUE, not
+ the ADDRESS, of SP_REGNUM. It also depends on the cache of
+ frame_find_saved_regs results. */
+ if (frame->fsr->regs[SP_REGNUM])
+ return 0; /* Frameful -- return addr saved somewhere */
+ else
+ return 1; /* Frameless -- no saved return address */
+}
+
+void
+init_extra_frame_info (fromleaf, frame)
+ int fromleaf;
+ struct frame_info *frame;
+{
+ frame->fsr = 0; /* Not yet allocated */
+ frame->args_pointer = 0; /* Unknown */
+ frame->locals_pointer = 0; /* Unknown */
+}
+
+/* Examine an m88k function prologue, recording the addresses at which
+ registers are saved explicitly by the prologue code, and returning
+ the address of the first instruction after the prologue (but not
+ after the instruction at address LIMIT, as explained below).
+
+ LIMIT places an upper bound on addresses of the instructions to be
+ examined. If the prologue code scan reaches LIMIT, the scan is
+ aborted and LIMIT is returned. This is used, when examining the
+ prologue for the current frame, to keep examine_prologue () from
+ claiming that a given register has been saved when in fact the
+ instruction that saves it has not yet been executed. LIMIT is used
+ at other times to stop the scan when we hit code after the true
+ function prologue (e.g. for the first source line) which might
+ otherwise be mistaken for function prologue.
+
+ The format of the function prologue matched by this routine is
+ derived from examination of the source to gcc 1.95, particularly
+ the routine output_prologue () in config/out-m88k.c.
+
+ subu r31,r31,n # stack pointer update
+
+ (st rn,r31,offset)? # save incoming regs
+ (st.d rn,r31,offset)?
+
+ (addu r30,r31,n)? # frame pointer update
+
+ (pic sequence)? # PIC code prologue
+
+ (or rn,rm,0)? # Move parameters to other regs
+*/
+
+/* Macros for extracting fields from instructions. */
+
+#define BITMASK(pos, width) (((0x1 << (width)) - 1) << (pos))
+#define EXTRACT_FIELD(val, pos, width) ((val) >> (pos) & BITMASK (0, width))
+#define SUBU_OFFSET(x) ((unsigned)(x & 0xFFFF))
+#define ST_OFFSET(x) ((unsigned)((x) & 0xFFFF))
+#define ST_SRC(x) EXTRACT_FIELD ((x), 21, 5)
+#define ADDU_OFFSET(x) ((unsigned)(x & 0xFFFF))
+
+/*
+ * prologue_insn_tbl is a table of instructions which may comprise a
+ * function prologue. Associated with each table entry (corresponding
+ * to a single instruction or group of instructions), is an action.
+ * This action is used by examine_prologue (below) to determine
+ * the state of certain machine registers and where the stack frame lives.
+ */
+
+enum prologue_insn_action {
+ PIA_SKIP, /* don't care what the instruction does */
+ PIA_NOTE_ST, /* note register stored and where */
+ PIA_NOTE_STD, /* note pair of registers stored and where */
+ PIA_NOTE_SP_ADJUSTMENT, /* note stack pointer adjustment */
+ PIA_NOTE_FP_ASSIGNMENT, /* note frame pointer assignment */
+ PIA_NOTE_PROLOGUE_END, /* no more prologue */
+};
+
+struct prologue_insns {
+ unsigned long insn;
+ unsigned long mask;
+ enum prologue_insn_action action;
+};
+
+struct prologue_insns prologue_insn_tbl[] = {
+ /* Various register move instructions */
+ { 0x58000000, 0xf800ffff, PIA_SKIP }, /* or/or.u with immed of 0 */
+ { 0xf4005800, 0xfc1fffe0, PIA_SKIP }, /* or rd, r0, rs */
+ { 0xf4005800, 0xfc00ffff, PIA_SKIP }, /* or rd, rs, r0 */
+
+ /* Stack pointer setup: "subu sp, sp, n" where n is a multiple of 8 */
+ { 0x67ff0000, 0xffff0007, PIA_NOTE_SP_ADJUSTMENT },
+
+ /* Frame pointer assignment: "addu r30, r31, n" */
+ { 0x63df0000, 0xffff0000, PIA_NOTE_FP_ASSIGNMENT },
+
+ /* Store to stack instructions; either "st rx, sp, n" or "st.d rx, sp, n" */
+ { 0x241f0000, 0xfc1f0000, PIA_NOTE_ST }, /* st rx, sp, n */
+ { 0x201f0000, 0xfc1f0000, PIA_NOTE_STD }, /* st.d rs, sp, n */
+
+ /* Instructions needed for setting up r25 for pic code. */
+ { 0x5f200000, 0xffff0000, PIA_SKIP }, /* or.u r25, r0, offset_high */
+ { 0xcc000002, 0xffffffff, PIA_SKIP }, /* bsr.n Lab */
+ { 0x5b390000, 0xffff0000, PIA_SKIP }, /* or r25, r25, offset_low */
+ { 0xf7396001, 0xffffffff, PIA_SKIP }, /* Lab: addu r25, r25, r1 */
+
+ /* Various branch or jump instructions which have a delay slot -- these
+ do not form part of the prologue, but the instruction in the delay
+ slot might be a store instruction which should be noted. */
+ { 0xc4000000, 0xe4000000, PIA_NOTE_PROLOGUE_END },
+ /* br.n, bsr.n, bb0.n, or bb1.n */
+ { 0xec000000, 0xfc000000, PIA_NOTE_PROLOGUE_END }, /* bcnd.n */
+ { 0xf400c400, 0xfffff7e0, PIA_NOTE_PROLOGUE_END } /* jmp.n or jsr.n */
+
+};
+
+
+/* Fetch the instruction at ADDR, returning 0 if ADDR is beyond LIM or
+ is not the address of a valid instruction, the address of the next
+ instruction beyond ADDR otherwise. *PWORD1 receives the first word
+ of the instruction. */
+
+#define NEXT_PROLOGUE_INSN(addr, lim, pword1) \
+ (((addr) < (lim)) ? next_insn (addr, pword1) : 0)
+
+/* Read the m88k instruction at 'memaddr' and return the address of
+ the next instruction after that, or 0 if 'memaddr' is not the
+ address of a valid instruction. The instruction
+ is stored at 'pword1'. */
+
+CORE_ADDR
+next_insn (memaddr, pword1)
+ unsigned long *pword1;
+ CORE_ADDR memaddr;
+{
+ *pword1 = read_memory_integer (memaddr, BYTES_PER_88K_INSN);
+ return memaddr + BYTES_PER_88K_INSN;
+}
+
+/* Read a register from frames called by us (or from the hardware regs). */
+
+static int
+read_next_frame_reg(frame, regno)
+ struct frame_info *frame;
+ int regno;
+{
+ for (; frame; frame = frame->next) {
+ if (regno == SP_REGNUM)
+ return FRAME_FP (frame);
+ else if (frame->fsr->regs[regno])
+ return read_memory_integer(frame->fsr->regs[regno], 4);
+ }
+ return read_register(regno);
+}
+
+/* Examine the prologue of a function. `ip' points to the first instruction.
+ `limit' is the limit of the prologue (e.g. the addr of the first
+ linenumber, or perhaps the program counter if we're stepping through).
+ `frame_sp' is the stack pointer value in use in this frame.
+ `fsr' is a pointer to a frame_saved_regs structure into which we put
+ info about the registers saved by this frame.
+ `fi' is a struct frame_info pointer; we fill in various fields in it
+ to reflect the offsets of the arg pointer and the locals pointer. */
+
+static CORE_ADDR
+examine_prologue (ip, limit, frame_sp, fsr, fi)
+ register CORE_ADDR ip;
+ register CORE_ADDR limit;
+ CORE_ADDR frame_sp;
+ struct frame_saved_regs *fsr;
+ struct frame_info *fi;
+{
+ register CORE_ADDR next_ip;
+ register int src;
+ unsigned int insn;
+ int size, offset;
+ char must_adjust[32]; /* If set, must adjust offsets in fsr */
+ int sp_offset = -1; /* -1 means not set (valid must be mult of 8) */
+ int fp_offset = -1; /* -1 means not set */
+ CORE_ADDR frame_fp;
+ CORE_ADDR prologue_end = 0;
+
+ memset (must_adjust, '\0', sizeof (must_adjust));
+ next_ip = NEXT_PROLOGUE_INSN (ip, limit, &insn);
+
+ while (next_ip)
+ {
+ struct prologue_insns *pip;
+
+ for (pip=prologue_insn_tbl; (insn & pip->mask) != pip->insn; )
+ if (++pip >= prologue_insn_tbl + sizeof prologue_insn_tbl)
+ goto end_of_prologue_found; /* not a prologue insn */
+
+ switch (pip->action)
+ {
+ case PIA_NOTE_ST:
+ case PIA_NOTE_STD:
+ if (sp_offset != -1) {
+ src = ST_SRC (insn);
+ offset = ST_OFFSET (insn);
+ must_adjust[src] = 1;
+ fsr->regs[src++] = offset; /* Will be adjusted later */
+ if (pip->action == PIA_NOTE_STD && src < 32)
+ {
+ offset += 4;
+ must_adjust[src] = 1;
+ fsr->regs[src++] = offset;
+ }
+ }
+ else
+ goto end_of_prologue_found;
+ break;
+ case PIA_NOTE_SP_ADJUSTMENT:
+ if (sp_offset == -1)
+ sp_offset = -SUBU_OFFSET (insn);
+ else
+ goto end_of_prologue_found;
+ break;
+ case PIA_NOTE_FP_ASSIGNMENT:
+ if (fp_offset == -1)
+ fp_offset = ADDU_OFFSET (insn);
+ else
+ goto end_of_prologue_found;
+ break;
+ case PIA_NOTE_PROLOGUE_END:
+ if (!prologue_end)
+ prologue_end = ip;
+ break;
+ case PIA_SKIP:
+ default :
+ /* Do nothing */
+ break;
+ }
+
+ ip = next_ip;
+ next_ip = NEXT_PROLOGUE_INSN (ip, limit, &insn);
+ }
+
+end_of_prologue_found:
+
+ if (prologue_end)
+ ip = prologue_end;
+
+ /* We're done with the prologue. If we don't care about the stack
+ frame itself, just return. (Note that fsr->regs has been trashed,
+ but the one caller who calls with fi==0 passes a dummy there.) */
+
+ if (fi == 0)
+ return ip;
+
+ /*
+ OK, now we have:
+
+ sp_offset original (before any alloca calls) displacement of SP
+ (will be negative).
+
+ fp_offset displacement from original SP to the FP for this frame
+ or -1.
+
+ fsr->regs[0..31] displacement from original SP to the stack
+ location where reg[0..31] is stored.
+
+ must_adjust[0..31] set if corresponding offset was set.
+
+ If alloca has been called between the function prologue and the current
+ IP, then the current SP (frame_sp) will not be the original SP as set by
+ the function prologue. If the current SP is not the original SP, then the
+ compiler will have allocated an FP for this frame, fp_offset will be set,
+ and we can use it to calculate the original SP.
+
+ Then, we figure out where the arguments and locals are, and relocate the
+ offsets in fsr->regs to absolute addresses. */
+
+ if (fp_offset != -1) {
+ /* We have a frame pointer, so get it, and base our calc's on it. */
+ frame_fp = (CORE_ADDR) read_next_frame_reg (fi->next, ACTUAL_FP_REGNUM);
+ frame_sp = frame_fp - fp_offset;
+ } else {
+ /* We have no frame pointer, therefore frame_sp is still the same value
+ as set by prologue. But where is the frame itself? */
+ if (must_adjust[SRP_REGNUM]) {
+ /* Function header saved SRP (r1), the return address. Frame starts
+ 4 bytes down from where it was saved. */
+ frame_fp = frame_sp + fsr->regs[SRP_REGNUM] - 4;
+ fi->locals_pointer = frame_fp;
+ } else {
+ /* Function header didn't save SRP (r1), so we are in a leaf fn or
+ are otherwise confused. */
+ frame_fp = -1;
+ }
+ }
+
+ /* The locals are relative to the FP (whether it exists as an allocated
+ register, or just as an assumed offset from the SP) */
+ fi->locals_pointer = frame_fp;
+
+ /* The arguments are just above the SP as it was before we adjusted it
+ on entry. */
+ fi->args_pointer = frame_sp - sp_offset;
+
+ /* Now that we know the SP value used by the prologue, we know where
+ it saved all the registers. */
+ for (src = 0; src < 32; src++)
+ if (must_adjust[src])
+ fsr->regs[src] += frame_sp;
+
+ /* The saved value of the SP is always known. */
+ /* (we hope...) */
+ if (fsr->regs[SP_REGNUM] != 0
+ && fsr->regs[SP_REGNUM] != frame_sp - sp_offset)
+ fprintf_unfiltered(gdb_stderr, "Bad saved SP value %x != %x, offset %x!\n",
+ fsr->regs[SP_REGNUM],
+ frame_sp - sp_offset, sp_offset);
+
+ fsr->regs[SP_REGNUM] = frame_sp - sp_offset;
+
+ return (ip);
+}
+
+/* Given an ip value corresponding to the start of a function,
+ return the ip of the first instruction after the function
+ prologue. */
+
+CORE_ADDR
+skip_prologue (ip)
+ CORE_ADDR (ip);
+{
+ struct frame_saved_regs saved_regs_dummy;
+ struct symtab_and_line sal;
+ CORE_ADDR limit;
+
+ sal = find_pc_line (ip, 0);
+ limit = (sal.end) ? sal.end : 0xffffffff;
+
+ return (examine_prologue (ip, limit, (CORE_ADDR) 0, &saved_regs_dummy,
+ (struct frame_info *)0 ));
+}
+
+/* Put here the code to store, into a struct frame_saved_regs,
+ the addresses of the saved registers of frame described by FRAME_INFO.
+ This includes special registers such as pc and fp saved in special
+ ways in the stack frame. sp is even more special:
+ the address we return for it IS the sp for the next frame.
+
+ We cache the result of doing this in the frame_obstack, since it is
+ fairly expensive. */
+
+void
+frame_find_saved_regs (fi, fsr)
+ struct frame_info *fi;
+ struct frame_saved_regs *fsr;
+{
+ register struct frame_saved_regs *cache_fsr;
+ CORE_ADDR ip;
+ struct symtab_and_line sal;
+ CORE_ADDR limit;
+
+ if (!fi->fsr)
+ {
+ cache_fsr = (struct frame_saved_regs *)
+ frame_obstack_alloc (sizeof (struct frame_saved_regs));
+ memset (cache_fsr, '\0', sizeof (struct frame_saved_regs));
+ fi->fsr = cache_fsr;
+
+ /* Find the start and end of the function prologue. If the PC
+ is in the function prologue, we only consider the part that
+ has executed already. In the case where the PC is not in
+ the function prologue, we set limit to two instructions beyond
+ where the prologue ends in case if any of the prologue instructions
+ were moved into a delay slot of a branch instruction. */
+
+ ip = get_pc_function_start (fi->pc);
+ sal = find_pc_line (ip, 0);
+ limit = (sal.end && sal.end < fi->pc) ? sal.end + 2 * BYTES_PER_88K_INSN
+ : fi->pc;
+
+ /* This will fill in fields in *fi as well as in cache_fsr. */
+#ifdef SIGTRAMP_FRAME_FIXUP
+ if (fi->signal_handler_caller)
+ SIGTRAMP_FRAME_FIXUP(fi->frame);
+#endif
+ examine_prologue (ip, limit, fi->frame, cache_fsr, fi);
+#ifdef SIGTRAMP_SP_FIXUP
+ if (fi->signal_handler_caller && fi->fsr->regs[SP_REGNUM])
+ SIGTRAMP_SP_FIXUP(fi->fsr->regs[SP_REGNUM]);
+#endif
+ }
+
+ if (fsr)
+ *fsr = *fi->fsr;
+}
+
+/* Return the address of the locals block for the frame
+ described by FI. Returns 0 if the address is unknown.
+ NOTE! Frame locals are referred to by negative offsets from the
+ argument pointer, so this is the same as frame_args_address(). */
+
+CORE_ADDR
+frame_locals_address (fi)
+ struct frame_info *fi;
+{
+ struct frame_saved_regs fsr;
+
+ if (fi->args_pointer) /* Cached value is likely there. */
+ return fi->args_pointer;
+
+ /* Nope, generate it. */
+
+ get_frame_saved_regs (fi, &fsr);
+
+ return fi->args_pointer;
+}
+
+/* Return the address of the argument block for the frame
+ described by FI. Returns 0 if the address is unknown. */
+
+CORE_ADDR
+frame_args_address (fi)
+ struct frame_info *fi;
+{
+ struct frame_saved_regs fsr;
+
+ if (fi->args_pointer) /* Cached value is likely there. */
+ return fi->args_pointer;
+
+ /* Nope, generate it. */
+
+ get_frame_saved_regs (fi, &fsr);
+
+ return fi->args_pointer;
+}
+
+/* Return the saved PC from this frame.
+
+ If the frame has a memory copy of SRP_REGNUM, use that. If not,
+ just use the register SRP_REGNUM itself. */
+
+CORE_ADDR
+frame_saved_pc (frame)
+ struct frame_info *frame;
+{
+ return read_next_frame_reg(frame, SRP_REGNUM);
+}
+
+
+#define DUMMY_FRAME_SIZE 192
+
+static void
+write_word (sp, word)
+ CORE_ADDR sp;
+ ULONGEST word;
+{
+ register int len = REGISTER_SIZE;
+ char buffer[MAX_REGISTER_RAW_SIZE];
+
+ store_unsigned_integer (buffer, len, word);
+ write_memory (sp, buffer, len);
+}
+
+void
+m88k_push_dummy_frame()
+{
+ register CORE_ADDR sp = read_register (SP_REGNUM);
+ register int rn;
+ int offset;
+
+ sp -= DUMMY_FRAME_SIZE; /* allocate a bunch of space */
+
+ for (rn = 0, offset = 0; rn <= SP_REGNUM; rn++, offset+=4)
+ write_word (sp+offset, read_register(rn));
+
+ write_word (sp+offset, read_register (SXIP_REGNUM));
+ offset += 4;
+
+ write_word (sp+offset, read_register (SNIP_REGNUM));
+ offset += 4;
+
+ write_word (sp+offset, read_register (SFIP_REGNUM));
+ offset += 4;
+
+ write_word (sp+offset, read_register (PSR_REGNUM));
+ offset += 4;
+
+ write_word (sp+offset, read_register (FPSR_REGNUM));
+ offset += 4;
+
+ write_word (sp+offset, read_register (FPCR_REGNUM));
+ offset += 4;
+
+ write_register (SP_REGNUM, sp);
+ write_register (ACTUAL_FP_REGNUM, sp);
+}
+
+void
+pop_frame ()
+{
+ register struct frame_info *frame = get_current_frame ();
+ register CORE_ADDR fp;
+ register int regnum;
+ struct frame_saved_regs fsr;
+
+ fp = FRAME_FP (frame);
+ get_frame_saved_regs (frame, &fsr);
+
+ if (PC_IN_CALL_DUMMY (read_pc (), read_register (SP_REGNUM), FRAME_FP (fi)))
+ {
+ /* FIXME: I think get_frame_saved_regs should be handling this so
+ that we can deal with the saved registers properly (e.g. frame
+ 1 is a call dummy, the user types "frame 2" and then "print $ps"). */
+ register CORE_ADDR sp = read_register (ACTUAL_FP_REGNUM);
+ int offset;
+
+ for (regnum = 0, offset = 0; regnum <= SP_REGNUM; regnum++, offset+=4)
+ (void) write_register (regnum, read_memory_integer (sp+offset, 4));
+
+ write_register (SXIP_REGNUM, read_memory_integer (sp+offset, 4));
+ offset += 4;
+
+ write_register (SNIP_REGNUM, read_memory_integer (sp+offset, 4));
+ offset += 4;
+
+ write_register (SFIP_REGNUM, read_memory_integer (sp+offset, 4));
+ offset += 4;
+
+ write_register (PSR_REGNUM, read_memory_integer (sp+offset, 4));
+ offset += 4;
+
+ write_register (FPSR_REGNUM, read_memory_integer (sp+offset, 4));
+ offset += 4;
+
+ write_register (FPCR_REGNUM, read_memory_integer (sp+offset, 4));
+ offset += 4;
+
+ }
+ else
+ {
+ for (regnum = FP_REGNUM ; regnum > 0 ; regnum--)
+ if (fsr.regs[regnum])
+ write_register (regnum,
+ read_memory_integer (fsr.regs[regnum], 4));
+ write_pc (frame_saved_pc (frame));
+ }
+ reinit_frame_cache ();
+}
+
+void
+_initialize_m88k_tdep ()
+{
+ tm_print_insn = print_insn_m88k;
+}
diff --git a/gdb/mac-defs.h b/gdb/mac-defs.h
new file mode 100644
index 00000000000..82f7e71a338
--- /dev/null
+++ b/gdb/mac-defs.h
@@ -0,0 +1,34 @@
+/* Definitions shared between C and Rez files. */
+
+#define mbMain 128
+
+#define mApple 128
+
+#define miAbout 1
+
+#define mFile 129
+
+#define miFileNew 1
+#define miFileOpen 2
+/* 3 */
+#define miFileQuit 4
+
+#define mEdit 130
+
+#define miEditCut 1
+#define miEditCopy 2
+#define miEditPaste 3
+#define miEditClear 4
+
+#define mDebug 131
+
+#define miDebugTarget 1
+/* 2 */
+#define miDebugRun 3
+#define miDebugContinue 4
+#define miDebugStep 5
+#define miDebugNext 6
+
+#define wConsole 128
+
+
diff --git a/gdb/mac-gdb.r b/gdb/mac-gdb.r
new file mode 100644
index 00000000000..3736ddef944
--- /dev/null
+++ b/gdb/mac-gdb.r
@@ -0,0 +1,184 @@
+/* Resource file for MacGDB. */
+
+#include "SysTypes.r"
+#include "Types.r"
+
+#include "mac-defs.h"
+
+/* Version resources. */
+
+resource 'vers' (1) {
+ 0,
+ 0,
+ 0,
+ 0,
+ verUS,
+ VERSION_STRING,
+ VERSION_STRING " (C) 1986-95 FSF, Inc."
+};
+
+resource 'vers' (2, purgeable) {
+ 0,
+ 0,
+ 0,
+ 0,
+ verUs,
+ VERSION_STRING,
+ "GDB " VERSION_STRING " for MPW"
+};
+
+#ifdef WANT_CFRG
+
+#include "CodeFragmentTypes.r"
+
+resource 'cfrg' (0) {
+ {
+ kPowerPC,
+ kFullLib,
+ kNoVersionNum, kNoVersionNum,
+ 0, 0,
+ kIsApp, kOnDiskFlat, kZeroOffset, kWholeFork,
+ PROG_NAME
+ }
+};
+
+#endif /* WANT_CFRG */
+
+#ifdef Macgdb /* Exclude the following from SIOWgdb which uses SIOW.r. */
+
+resource 'MBAR' (128) {
+ { mApple, mFile, mEdit, mDebug };
+};
+
+resource 'MENU' (mApple, preload) {
+ mApple,
+ textMenuProc,
+ 0x7FFFFFFD,
+ enabled,
+ apple,
+ {
+ "About...", noIcon, noKey, noMark, plain,
+ "-", noIcon, noKey, noMark, plain
+ }
+};
+
+resource 'MENU' (mFile, preload) {
+ mFile,
+ textMenuProc,
+ allEnabled,
+ enabled,
+ "File",
+ {
+ "New", noIcon, noKey, noMark, plain,
+ "Open...", noIcon, "O", noMark, plain,
+ "-", noIcon, noKey, noMark, plain,
+ "Quit", noIcon, "Q", noMark, plain
+ }
+};
+
+resource 'MENU' (mEdit, preload) {
+ mEdit,
+ textMenuProc,
+ allEnabled,
+ enabled,
+ "Edit",
+ {
+ "Undo", noIcon, "Z", noMark, plain,
+ "-", noIcon, noKey, noMark, plain,
+ "Cut", noIcon, "X", noMark, plain,
+ "Copy", noIcon, "C", noMark, plain,
+ "Paste", noIcon, "V", noMark, plain,
+ "Clear", noIcon, noKey, noMark, plain
+ }
+};
+
+resource 'MENU' (mDebug, preload) {
+ mDebug,
+ textMenuProc,
+ allEnabled,
+ enabled,
+ "Debug",
+ {
+ "Target", noIcon, "T", noMark, plain,
+ "-", noIcon, noKey, noMark, plain,
+ "Run", noIcon, "R", noMark, plain,
+ "Continue", noIcon, "K", noMark, plain,
+ "Step", noIcon, "S", noMark, plain,
+ "Next", noIcon, "N", noMark, plain
+ }
+};
+
+resource 'ALRT' (128) {
+ {40, 40, 180, 420},
+ 128,
+ { /* array: 4 elements */
+ /* [1] */
+ OK, visible, sound1,
+ /* [2] */
+ OK, visible, sound1,
+ /* [3] */
+ OK, visible, sound1,
+ /* [4] */
+ OK, visible, sound1
+ }
+};
+
+resource 'DITL' (128) {
+ { /* array DITLarray: 2 elements */
+ /* [1] */
+ {110, 150, 128, 200},
+ Button {
+ enabled,
+ "OK"
+ },
+ /* [2] */
+ {10, 10, 100, 370},
+ StaticText {
+ disabled,
+ "GDB 4.12.3\n"
+ "Copyright © 1994 Free Software Foundation, Inc.\n"
+ },
+ }
+};
+
+resource 'WIND' (wConsole, preload, purgeable) {
+ {40, 40, 310, 572},
+ zoomDocProc,
+ visible,
+ goAway,
+ 0x0,
+ "GDB Console"
+};
+
+resource 'SIZE' (-1) {
+ reserved,
+ acceptSuspendResumeEvents,
+ reserved,
+ canBackground,
+ multiFinderAware,
+ backgroundAndForeground,
+ dontGetFrontClicks,
+ ignoreChildDiedEvents,
+ not32BitCompatible,
+ isHighLevelEventAware,
+ localAndRemoteHLEvents,
+ notStationeryAware,
+ dontUseTextEditServices,
+ reserved,
+ reserved,
+ reserved,
+ 5000*1024,
+ 2000*1024
+};
+
+resource 'DLOG' (128) {
+ {40, 40, 240, 280},
+ documentProc,
+ visible,
+ goAway,
+ 0x0,
+ 128,
+ ""
+};
+
+#endif
diff --git a/gdb/mac-nat.c b/gdb/mac-nat.c
new file mode 100644
index 00000000000..3518fe5d5ce
--- /dev/null
+++ b/gdb/mac-nat.c
@@ -0,0 +1,412 @@
+/* Target-vector operations for controlling Mac applications, for GDB.
+ Copyright (C) 1995 Free Software Foundation, Inc.
+ Written by Stan Shebs. 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 eve nthe implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Note that because all the available Mac compilers are ANSI or very
+ close, and this is a native-only file, the code may be purely ANSI. */
+
+#include "defs.h"
+#include "frame.h" /* required by inferior.h */
+#include "inferior.h"
+#include "target.h"
+#include "wait.h"
+#include "gdbcore.h"
+#include "command.h"
+#include <signal.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include "buildsym.h"
+#include "gdb_string.h"
+#include "gdbthread.h"
+#include "gdbcmd.h"
+
+#include <Processes.h>
+
+/* We call the functions "child_..." rather than "mac_..." so no one
+ is tempted to try to link this with other native-only code. */
+
+/* Forward declaration */
+
+extern struct target_ops child_ops;
+
+static void child_stop PARAMS ((void));
+
+static void
+child_fetch_inferior_registers (int r)
+{
+ if (r < 0)
+ {
+ for (r = 0; r < NUM_REGS; r++)
+ child_fetch_inferior_registers (r);
+ }
+ else
+ {
+ supply_register (r, 0);
+ }
+}
+
+static void
+child_store_inferior_registers (int r)
+{
+ if (r < 0)
+ {
+ for (r = 0; r < NUM_REGS; r++)
+ child_store_inferior_registers (r);
+ }
+ else
+ {
+ read_register_gen (r, 0);
+ }
+}
+
+static int
+child_wait (int pid, struct target_waitstatus *ourstatus)
+{
+}
+
+/* Attach to process PID, then initialize for debugging it. */
+
+static void
+child_attach (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ ProcessSerialNumber psn;
+ ProcessInfoRec inforec;
+ Str31 name;
+ FSSpecPtr fsspec;
+ OSType code;
+ int pid;
+ char *exec_file;
+
+ if (!args)
+ error_no_arg ("process-id to attach");
+
+ pid = atoi (args);
+
+ psn.highLongOfPSN = 0;
+ psn.lowLongOfPSN = pid;
+
+ inforec.processInfoLength = sizeof(ProcessInfoRec);
+ inforec.processName = name;
+ inforec.processAppSpec = fsspec;
+
+ if (GetProcessInformation (&psn, &inforec) == noErr)
+ {
+ if (from_tty)
+ {
+ exec_file = (char *) get_exec_file (0);
+
+ if (exec_file)
+ printf_unfiltered ("Attaching to program `%s', %s\n", exec_file,
+ target_pid_to_str (pid));
+ else
+ printf_unfiltered ("Attaching to %s\n", target_pid_to_str (pid));
+
+ gdb_flush (gdb_stdout);
+ }
+ /* Do we need to do anything special? */
+ attach_flag = 1;
+ inferior_pid = pid;
+ push_target (&child_ops);
+ }
+}
+
+static void
+child_detach (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ char *exec_file;
+
+ if (from_tty)
+ {
+ exec_file = get_exec_file (0);
+ if (exec_file == 0)
+ exec_file = "";
+ printf_unfiltered ("Detaching from program: %s %s\n", exec_file,
+ target_pid_to_str (inferior_pid));
+ gdb_flush (gdb_stdout);
+ }
+ inferior_pid = 0;
+ unpush_target (&child_ops);
+}
+
+/* Print status information about what we're accessing. */
+
+static void
+child_files_info (ignore)
+ struct target_ops *ignore;
+{
+ printf_unfiltered ("\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 Mac application.");
+}
+
+/* Start an inferior Mac program 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;
+{
+ LaunchParamBlockRec launchparms;
+ FSSpec fsspec;
+ OSErr launch_err;
+
+ if (!exec_file)
+ {
+ error ("No executable specified, use `target exec'.\n");
+ }
+
+ launchparms.launchBlockID = extendedBlock;
+ launchparms.launchEPBLength = extendedBlockLen;
+ launchparms.launchFileFlags = 0;
+ launchparms.launchControlFlags = launchContinue | launchNoFileFlags;
+ fsspec.vRefNum = 0;
+ fsspec.parID = 0;
+ strcpy(fsspec.name + 1, exec_file);
+ fsspec.name[0] = strlen(exec_file);
+ launchparms.launchAppSpec = &fsspec;
+ launchparms.launchAppParameters = nil;
+
+ launch_err = LaunchApplication (&launchparms);
+
+ if (launch_err == 999 /*memFullErr*/)
+ {
+ error ("Not enough memory to launch %s\n", exec_file);
+ }
+ else if (launch_err != noErr)
+ {
+ error ("Error launching %s, code %d\n", exec_file, launch_err);
+ }
+
+ inferior_pid = launchparms.launchProcessSN.lowLongOfPSN;
+ /* FIXME be sure that high long of PSN is 0 */
+
+ push_target (&child_ops);
+ init_wait_for_inferior ();
+ clear_proceed_status ();
+
+/* proceed ((CORE_ADDR) - 1, TARGET_SIGNAL_0, 0); */
+}
+
+static void
+child_mourn_inferior ()
+{
+ unpush_target (&child_ops);
+ generic_mourn_inferior ();
+}
+
+static void
+child_stop ()
+{
+}
+
+int
+child_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len,
+ int write, struct target_ops *target)
+{
+ int i;
+
+ for (i = 0; i < len; ++i)
+ {
+ if (write)
+ {
+ ((char *) memaddr)[i] = myaddr[i];
+ }
+ else
+ {
+ myaddr[i] = ((char *) memaddr)[i];
+ }
+ }
+ return len;
+}
+
+void
+child_kill_inferior (void)
+{
+}
+
+void
+child_resume (int pid, int step, enum target_signal signal)
+{
+}
+
+static void
+child_prepare_to_store ()
+{
+ /* Do nothing, since we can store individual regs */
+}
+
+static int
+child_can_run ()
+{
+ return 1;
+}
+
+static void
+child_close ()
+{
+}
+
+static void
+info_proc (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ ProcessSerialNumber psn;
+ ProcessInfoRec inforec;
+ Str31 name;
+ FSSpecPtr fsspec;
+ OSType code;
+
+ /* Eventually use args, but not right now. */
+
+ psn.highLongOfPSN = 0;
+ psn.lowLongOfPSN = kNoProcess;
+
+ inforec.processInfoLength = sizeof(ProcessInfoRec);
+ inforec.processName = name;
+ inforec.processAppSpec = fsspec;
+
+ printf_filtered ("Process Name Sgnt Type PSN Loc Size FreeMem Time\n");
+
+ while (GetNextProcess (&psn) == noErr)
+ {
+ if (GetProcessInformation (&psn, &inforec) == noErr)
+ {
+ name[name[0] + 1] = '\0';
+ printf_filtered ("%-32.32s", name + 1);
+ code = inforec.processSignature;
+ printf_filtered (" %c%c%c%c",
+ (code >> 24) & 0xff,
+ (code >> 16) & 0xff,
+ (code >> 8) & 0xff,
+ (code >> 0) & 0xff);
+ code = inforec.processType;
+ printf_filtered (" %c%c%c%c",
+ (code >> 24) & 0xff,
+ (code >> 16) & 0xff,
+ (code >> 8) & 0xff,
+ (code >> 0) & 0xff);
+ if (psn.highLongOfPSN == 0)
+ printf_filtered (" %9d", psn.lowLongOfPSN);
+ else
+ printf_filtered (" %9d,%9d\n",
+ psn.highLongOfPSN, psn.lowLongOfPSN);
+ printf_filtered (" 0x%x", inforec.processLocation);
+ printf_filtered (" %9d", inforec.processSize);
+ printf_filtered (" %9d", inforec.processFreeMem);
+ printf_filtered (" %9d", inforec.processActiveTime);
+ printf_filtered ("\n");
+ }
+ }
+}
+
+struct target_ops child_ops ;
+
+static void
+init_child_ops(void)
+{
+ child_ops.to_shortname = "mac";
+ child_ops.to_longname = "MacOS application";
+ child_ops.to_doc = "MacOS application (started by the \"run\" command).";
+ child_ops.to_open = child_open;
+ child_ops.to_close = child_close;
+ child_ops.to_attach = child_attach;
+ child_ops.to_post_attach = NULL;
+ child_ops.to_require_attach = NULL; /* to_require_attach */
+ child_ops.to_detach = child_detach;
+ child_ops.to_require_detach = NULL; /* to_require_detach */
+ child_ops.to_resume = child_resume;
+ child_ops.to_wait = child_wait;
+ child_ops.to_post_wait = NULL; /* to_post_wait */
+ child_ops.to_fetch_registers = child_fetch_inferior_registers;
+ child_ops.to_store_registers = child_store_inferior_registers;
+ child_ops.to_prepare_to_store = child_prepare_to_store;
+ child_ops.to_xfer_memory = child_xfer_memory;
+ child_ops.to_files_info = child_files_info;
+ child_ops.to_insert_breakpoint = memory_insert_breakpoint;
+ child_ops.to_remove_breakpoint = memory_remove_breakpoint;
+ child_ops.to_terminal_init = 0;
+ child_ops.to_terminal_inferior = 0;
+ child_ops.to_terminal_ours_for_output = 0;
+ child_ops.to_terminal_ours = 0;
+ child_ops.to_terminal_info = 0;
+ child_ops.to_kill = child_kill_inferior;
+ child_ops.to_load = 0;
+ child_ops.to_lookup_symbol = 0;
+ child_ops.to_create_inferior = child_create_inferior;
+ child_ops.to_post_startup_inferior = NULL; /* to_post_startup_inferior */
+ child_ops.to_acknowledge_created_inferior = NULL; /* to_acknowledge_created_inferior */
+ child_ops.to_clone_and_follow_inferior = NULL; /* to_clone_and_follow_inferior */
+ child_ops.to_post_follow_inferior_by_clone = NULL; /* to_post_follow_inferior_by_clone */
+ child_ops.to_insert_fork_catchpoint = NULL;
+ child_ops.to_remove_fork_catchpoint = NULL;
+ child_ops.to_insert_vfork_catchpoint = NULL;
+ child_ops.to_remove_vfork_catchpoint = NULL;
+ child_ops.to_has_forked = NULL; /* to_has_forked */
+ child_ops.to_has_vforked = NULL; /* to_has_vforked */
+ child_ops.to_can_follow_vfork_prior_to_exec = NULL;
+ child_ops.to_post_follow_vfork = NULL; /* to_post_follow_vfork */
+ child_ops.to_insert_exec_catchpoint = NULL;
+ child_ops.to_remove_exec_catchpoint = NULL;
+ child_ops.to_has_execd = NULL;
+ child_ops.to_reported_exec_events_per_exec_call = NULL;
+ child_ops.to_has_exited = NULL;
+ child_ops.to_mourn_inferior = child_mourn_inferior;
+ child_ops.to_can_run = child_can_run;
+ child_ops.to_notice_signals = 0;
+ child_ops.to_thread_alive = 0;
+ child_ops.to_stop = child_stop;
+ child_ops.to_pid_to_exec_file = NULL; /* to_pid_to_exec_file */
+ child_ops.to_core_file_to_sym_file = NULL;
+ child_ops.to_stratum = process_stratum;
+ child_ops.DONT_USE = 0;
+ child_ops.to_has_all_memory = 1;
+ child_ops.to_has_memory = 1;
+ child_ops.to_has_stack = 1;
+ child_ops.to_has_registers = 1;
+ child_ops.to_has_execution = 1;
+ child_ops.to_sections = 0;
+ child_ops.to_sections_end = 0;
+ child_ops.to_magic = OPS_MAGIC;
+};
+
+void
+_initialize_mac_nat ()
+{
+ init_child_ops() ;
+
+ add_info ("proc", info_proc,
+ "Show information about processes.");
+}
diff --git a/gdb/mac-xdep.c b/gdb/mac-xdep.c
new file mode 100644
index 00000000000..bf3f78deb1f
--- /dev/null
+++ b/gdb/mac-xdep.c
@@ -0,0 +1,1087 @@
+/* Top level support for Mac interface to GDB, the GNU debugger.
+ Copyright 1994 Free Software Foundation, Inc.
+ Contributed by Cygnus Support. Written by Stan Shebs.
+
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+
+#include <readline/readline.h>
+#include <readline/history.h>
+
+#include <Types.h>
+#include <Resources.h>
+#include <QuickDraw.h>
+#include <Fonts.h>
+#include <Events.h>
+#include <Windows.h>
+#include <Menus.h>
+#include <TextEdit.h>
+#include <Dialogs.h>
+#include <Desk.h>
+#include <ToolUtils.h>
+#include <Memory.h>
+#include <SegLoad.h>
+#include <Files.h>
+#include <Folders.h>
+#include <OSUtils.h>
+#include <OSEvents.h>
+#include <DiskInit.h>
+#include <Packages.h>
+#include <Traps.h>
+#include <Lists.h>
+#include <Gestalt.h>
+#include <PPCToolbox.h>
+#include <AppleEvents.h>
+#include <StandardFile.h>
+#include <Sound.h>
+
+#ifdef MPW
+#define QD(whatever) (qd.##whatever)
+#define QDPat(whatever) (&(qd.##whatever))
+#endif /* MPW */
+
+#ifdef THINK_C
+#define QD(whatever) (whatever)
+#endif
+
+#define p2c(pstr,cbuf) \
+ strncpy(cbuf, ((char *) (pstr) + 1), pstr[0]); \
+ cbuf[pstr[0]] = '\0';
+
+#define pascalify(STR) \
+ sprintf(tmpbuf, " %s", STR); \
+ tmpbuf[0] = strlen(STR);
+
+#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 "mac-defs.h"
+
+int debug_openp = 0;
+
+/* This is true if we are running as a standalone application. */
+
+int mac_app;
+
+/* This is true if we are using WaitNextEvent. */
+
+int use_wne;
+
+/* This is true if we have Color Quickdraw. */
+
+int has_color_qd;
+
+/* This is true if we are using Color Quickdraw. */
+
+int use_color_qd;
+
+int inbackground;
+
+Rect dragrect = { -32000, -32000, 32000, 32000 };
+Rect sizerect;
+
+int sbarwid = 15;
+
+/* Globals for the console window. */
+
+WindowPtr console_window;
+
+ControlHandle console_v_scrollbar;
+
+Rect console_v_scroll_rect;
+
+TEHandle console_text;
+
+Rect console_text_rect;
+
+/* This will go away eventually. */
+gdb_has_a_terminal () { return 1; }
+
+mac_init ()
+{
+ SysEnvRec se;
+ int eventloopdone = 0;
+ char *str;
+ Boolean gotevent;
+ Point mouse;
+ EventRecord event;
+ WindowPtr win;
+ RgnHandle cursorRgn;
+ int i;
+ Handle menubar;
+ MenuHandle menu;
+ Handle siow_resource;
+
+ mac_app = 0;
+
+ str = getenv("DEBUG_GDB");
+ if (str != NULL && str[0] != '\0')
+ {
+ if (strcmp(str, "openp") == 0)
+ debug_openp = 1;
+ }
+
+ /* Don't do anything if we`re running under MPW. */
+ if (!StandAlone)
+ return;
+
+ /* Don't do anything if we're using SIOW. */
+ /* This test requires that the siow 0 resource, as defined in
+ {RIncludes}siow.r, not be messed with. If it is, then the
+ standard Mac setup below will step on SIOW's Mac setup and
+ most likely crash the machine. */
+ siow_resource = GetResource('siow', 0);
+ if (siow_resource != nil)
+ return;
+
+ mac_app = 1;
+
+ /* Do the standard Mac environment setup. */
+ InitGraf (&QD (thePort));
+ InitFonts ();
+ FlushEvents (everyEvent, 0);
+ InitWindows ();
+ InitMenus ();
+ TEInit ();
+ InitDialogs (NULL);
+ InitCursor ();
+
+ /* Color Quickdraw is different from Classic QD. */
+ SysEnvirons(2, &se);
+ has_color_qd = se.hasColorQD;
+ /* Use it if we got it. */
+ use_color_qd = has_color_qd;
+
+ sizerect.top = 50;
+ sizerect.left = 50;
+ sizerect.bottom = 1000;
+ sizerect.right = 1000;
+#if 0
+ sizerect.bottom = screenBits.bounds.bottom - screenBits.bounds.top;
+ sizerect.right = screenBits.bounds.right - screenBits.bounds.left;
+#endif
+
+ /* Set up the menus. */
+ menubar = GetNewMBar (mbMain);
+ SetMenuBar (menubar);
+ /* Add the DAs etc as usual. */
+ menu = GetMHandle (mApple);
+ if (menu != nil) {
+ AddResMenu (menu, 'DRVR');
+ }
+ DrawMenuBar ();
+
+ new_console_window ();
+}
+
+new_console_window ()
+{
+ /* Create the main window we're going to play in. */
+ if (has_color_qd)
+ console_window = GetNewCWindow (wConsole, NULL, (WindowPtr) -1L);
+ else
+ console_window = GetNewWindow (wConsole, NULL, (WindowPtr) -1L);
+
+ SetPort (console_window);
+ console_text_rect = console_window->portRect;
+ /* Leave 8 pixels of blank space, for aesthetic reasons and to
+ make it easier to select from the beginning of a line. */
+ console_text_rect.left += 8;
+ console_text_rect.bottom -= sbarwid - 1;
+ console_text_rect.right -= sbarwid - 1;
+ console_text = TENew (&console_text_rect, &console_text_rect);
+ TESetSelect (0, 40000, console_text);
+ TEDelete (console_text);
+ TEAutoView (1, console_text);
+
+ console_v_scroll_rect = console_window->portRect;
+ console_v_scroll_rect.bottom -= sbarwid - 1;
+ console_v_scroll_rect.left = console_v_scroll_rect.right - sbarwid;
+ console_v_scrollbar =
+ NewControl (console_window, &console_v_scroll_rect,
+ "\p", 1, 0, 0, 0, scrollBarProc, 0L);
+
+ ShowWindow (console_window);
+ SelectWindow (console_window);
+}
+
+mac_command_loop()
+{
+ SysEnvRec se;
+ int eventloopdone = 0;
+ Boolean gotevent;
+ Point mouse;
+ EventRecord event;
+ WindowPtr win;
+ RgnHandle cursorRgn;
+ int i, tm;
+ Handle menubar;
+ MenuHandle menu;
+
+ /* Figure out if the WaitNextEvent Trap is available. */
+ use_wne =
+ (NGetTrapAddress (0x60, ToolTrap) != NGetTrapAddress (0x9f, ToolTrap));
+ /* Pass WaitNextEvent an empty region the first time through. */
+ cursorRgn = NewRgn ();
+ /* Go into the main event-handling loop. */
+ while (!eventloopdone)
+ {
+ /* Use WaitNextEvent if it is available, otherwise GetNextEvent. */
+ if (use_wne)
+ {
+ get_global_mouse (&mouse);
+ adjust_cursor (mouse, cursorRgn);
+ tm = GetCaretTime();
+ gotevent = WaitNextEvent (everyEvent, &event, tm, cursorRgn);
+ }
+ else
+ {
+ SystemTask ();
+ gotevent = GetNextEvent (everyEvent, &event);
+ }
+ /* First decide if the event is for a dialog or is just any old event. */
+ if (FrontWindow () != nil && IsDialogEvent (&event))
+ {
+ short itemhit;
+ DialogPtr dialog;
+
+ /* Handle all the modeless dialogs here. */
+ if (DialogSelect (&event, &dialog, &itemhit))
+ {
+ }
+ }
+ else if (gotevent)
+ {
+ /* Make sure we have the right cursor before handling the event. */
+ adjust_cursor (event.where, cursorRgn);
+ do_event (&event);
+ }
+ else
+ {
+ do_idle ();
+ }
+ }
+}
+
+/* Collect the global coordinates of the mouse pointer. */
+
+get_global_mouse (mouse)
+Point *mouse;
+{
+ EventRecord evt;
+
+ OSEventAvail (0, &evt);
+ *mouse = evt.where;
+}
+
+/* Change the cursor's appearance to be appropriate for the given mouse
+ location. */
+
+adjust_cursor (mouse, region)
+Point mouse;
+RgnHandle region;
+{
+}
+
+/* Decipher an event, maybe do something with it. */
+
+do_event (evt)
+EventRecord *evt;
+{
+ short part, err, rslt = 0;
+ WindowPtr win;
+ Boolean hit;
+ char key;
+ Point pnt;
+
+ switch (evt->what)
+ {
+ case mouseDown:
+ /* See if the click happened in a special part of the screen. */
+ part = FindWindow (evt->where, &win);
+ switch (part)
+ {
+ case inMenuBar:
+ adjust_menus ();
+ do_menu_command (MenuSelect (evt->where));
+ break;
+ case inSysWindow:
+ SystemClick (evt, win);
+ break;
+ case inContent:
+ if (win != FrontWindow ())
+ {
+ /* Bring the clicked-on window to the front. */
+ SelectWindow (win);
+ /* Fix the menu to match the new front window. */
+ adjust_menus ();
+ /* We always want to discard the event now, since clicks in a
+ windows are often irreversible actions. */
+ } else
+ /* Mouse clicks in the front window do something useful. */
+ do_mouse_down (win, evt);
+ break;
+ case inDrag:
+ /* Standard drag behavior, no tricks necessary. */
+ DragWindow (win, evt->where, &dragrect);
+ break;
+ case inGrow:
+ grow_window (win, evt->where);
+ break;
+ case inZoomIn:
+ case inZoomOut:
+ zoom_window (win, evt->where, part);
+ break;
+ case inGoAway:
+ close_window (win);
+ break;
+ }
+ break;
+ case keyDown:
+ case autoKey:
+ key = evt->message & charCodeMask;
+ /* Check for menukey equivalents. */
+ if (evt->modifiers & cmdKey)
+ {
+ if (evt->what == keyDown)
+ {
+ adjust_menus ();
+ do_menu_command (MenuKey (key));
+ }
+ }
+ else
+ {
+ if (evt->what == keyDown)
+ {
+ /* Random keypress, interpret it. */
+ do_keyboard_command (key);
+ }
+ }
+ break;
+ case activateEvt:
+ activate_window ((WindowPtr) evt->message, evt->modifiers & activeFlag);
+ break;
+ case updateEvt:
+ update_window ((WindowPtr) evt->message);
+ break;
+ case diskEvt:
+ /* Call DIBadMount in response to a diskEvt, so that the user can format
+ a floppy. (from DTS Sample) */
+ if (HiWord (evt->message) != noErr)
+ {
+ SetPt (&pnt, 50, 50);
+ err = DIBadMount (pnt, evt->message);
+ }
+ break;
+ case app4Evt:
+ /* Grab only a single byte. */
+ switch ((evt->message >> 24) & 0xFF)
+ {
+ case 0xfa:
+ break;
+ case 1:
+ inbackground = !(evt->message & 1);
+ activate_window (FrontWindow (), !inbackground);
+ break;
+ }
+ break;
+ case kHighLevelEvent:
+ AEProcessAppleEvent (evt);
+ break;
+ case nullEvent:
+ do_idle ();
+ rslt = 1;
+ break;
+ default:
+ break;
+ }
+ return rslt;
+}
+
+/* Do any idle-time activities. */
+
+do_idle ()
+{
+ TEIdle (console_text);
+}
+
+grow_window (win, where)
+WindowPtr win;
+Point where;
+{
+ long winsize;
+ int h, v;
+ GrafPtr oldport;
+
+ winsize = GrowWindow (win, where, &sizerect);
+ /* Only do anything if it actually changed size. */
+ if (winsize != 0)
+ {
+ GetPort (&oldport);
+ SetPort (win);
+ if (win == console_window)
+ {
+ EraseRect (&win->portRect);
+ h = LoWord (winsize);
+ v = HiWord (winsize);
+ SizeWindow (win, h, v, 1);
+ resize_console_window ();
+ }
+ SetPort (oldport);
+ }
+}
+
+zoom_window (win, where, part)
+WindowPtr win;
+Point where;
+short part;
+{
+ ZoomWindow (win, part, (win == FrontWindow ()));
+ if (win == console_window)
+ {
+ resize_console_window ();
+ }
+}
+
+resize_console_window ()
+{
+ adjust_console_sizes ();
+ adjust_console_scrollbars ();
+ adjust_console_text ();
+ InvalRect (&console_window->portRect);
+}
+
+close_window (win)
+WindowPtr win;
+{
+}
+
+pascal void
+v_scroll_proc (ControlHandle control, short part)
+{
+ int oldval, amount = 0, newval;
+ int pagesize = ((*console_text)->viewRect.bottom - (*console_text)->viewRect.top) / (*console_text)->lineHeight;
+ if (part)
+ {
+ oldval = GetCtlValue (control);
+ switch (part)
+ {
+ case inUpButton:
+ amount = 1;
+ break;
+ case inDownButton:
+ amount = -1;
+ break;
+ case inPageUp:
+ amount = pagesize;
+ break;
+ case inPageDown:
+ amount = - pagesize;
+ break;
+ default:
+ /* (should freak out) */
+ break;
+ }
+ SetCtlValue(control, oldval - amount);
+ newval = GetCtlValue (control);
+ amount = oldval - newval;
+ if (amount)
+ TEScroll (0, amount * (*console_text)->lineHeight, console_text);
+ }
+}
+
+do_mouse_down (WindowPtr win, EventRecord *event)
+{
+ short part, value;
+ Point mouse;
+ ControlHandle control;
+
+ if (1 /*is_app_window(win)*/)
+ {
+ SetPort (win);
+ mouse = event->where;
+ GlobalToLocal (&mouse);
+ part = FindControl(mouse, win, &control);
+ if (control == console_v_scrollbar)
+ {
+ switch (part)
+ {
+ case inThumb:
+ value = GetCtlValue (control);
+ part = TrackControl (control, mouse, nil);
+ if (part)
+ {
+ value -= GetCtlValue (control);
+ if (value)
+ TEScroll(0, value * (*console_text)->lineHeight,
+ console_text);
+ }
+ break;
+ default:
+#if 0 /* don't deal with right now */
+#if 1 /* universal headers */
+ value = TrackControl (control, mouse, (ControlActionUPP) v_scroll_proc);
+#else
+ value = TrackControl (control, mouse, (ProcPtr) v_scroll_proc);
+#endif
+#endif
+ break;
+ }
+ }
+ else
+ {
+ TEClick (mouse, 0, console_text);
+ }
+ }
+}
+
+scroll_text (hlines, vlines)
+int hlines, vlines;
+{
+}
+
+activate_window (win, activate)
+WindowPtr win;
+int activate;
+{
+ Rect grow_rect;
+
+ if (win == nil) return;
+ /* It's convenient to make the activated window also be the
+ current GrafPort. */
+ if (activate)
+ SetPort(win);
+ /* Activate the console window's scrollbar. */
+ if (win == console_window)
+ {
+ if (activate)
+ {
+ TEActivate (console_text);
+ /* Cause the grow icon to be redrawn at the next update. */
+ grow_rect = console_window->portRect;
+ grow_rect.top = grow_rect.bottom - sbarwid;
+ grow_rect.left = grow_rect.right - sbarwid;
+ InvalRect (&grow_rect);
+ }
+ else
+ {
+ TEDeactivate (console_text);
+ DrawGrowIcon (console_window);
+ }
+ HiliteControl (console_v_scrollbar, (activate ? 0 : 255));
+ }
+}
+
+update_window (win)
+WindowPtr win;
+{
+ int controls = 1, growbox = 0;
+ GrafPtr oldport;
+
+ /* Set the updating window to be the current grafport. */
+ GetPort (&oldport);
+ SetPort (win);
+/* recalc_depths(); */
+ BeginUpdate (win);
+ if (win == console_window)
+ {
+ draw_console ();
+ controls = 1;
+ growbox = 1;
+ }
+ if (controls)
+ UpdateControls (win, win->visRgn);
+ if (growbox)
+ DrawGrowIcon (win);
+ EndUpdate (win);
+ SetPort (oldport);
+}
+
+adjust_menus ()
+{
+}
+
+do_menu_command (which)
+long which;
+{
+ short menuid, menuitem;
+ short itemHit;
+ Str255 daname;
+ short daRefNum;
+ Boolean handledbyda;
+ WindowPtr win;
+ short ditem;
+ int i;
+ char cmdbuf[300];
+
+ cmdbuf[0] = '\0';
+ menuid = HiWord (which);
+ menuitem = LoWord (which);
+ switch (menuid)
+ {
+ case mApple:
+ switch (menuitem)
+ {
+ case miAbout:
+ Alert (128, nil);
+ break;
+#if 0
+ case miHelp:
+ /* (should pop up help info) */
+ break;
+#endif
+ default:
+ GetItem (GetMHandle (mApple), menuitem, daname);
+ daRefNum = OpenDeskAcc (daname);
+ }
+ break;
+ case mFile:
+ switch (menuitem)
+ {
+ case miFileNew:
+ if (console_window == FrontWindow ())
+ {
+ close_window (console_window);
+ }
+ new_console_window ();
+ break;
+ case miFileOpen:
+ SysBeep (20);
+ break;
+ case miFileQuit:
+ ExitToShell ();
+ break;
+ }
+ break;
+ case mEdit:
+ /* handledbyda = SystemEdit(menuitem-1); */
+ switch (menuitem)
+ {
+ case miEditCut:
+ TECut (console_text);
+ break;
+ case miEditCopy:
+ TECopy (console_text);
+ break;
+ case miEditPaste:
+ TEPaste (console_text);
+ break;
+ case miEditClear:
+ TEDelete (console_text);
+ break;
+ }
+ /* All of these operations need the same postprocessing. */
+ adjust_console_sizes ();
+ adjust_console_scrollbars ();
+ adjust_console_text ();
+ break;
+ case mDebug:
+ switch (menuitem)
+ {
+ case miDebugTarget:
+ sprintf (cmdbuf, "target %s", "remote");
+ break;
+ case miDebugRun:
+ sprintf (cmdbuf, "run");
+ break;
+ case miDebugContinue:
+ sprintf (cmdbuf, "continue");
+ break;
+ case miDebugStep:
+ sprintf (cmdbuf, "step");
+ break;
+ case miDebugNext:
+ sprintf (cmdbuf, "next");
+ break;
+ }
+ break;
+ }
+ HiliteMenu (0);
+ /* Execute a command if one had been given. Do here because a command
+ may longjmp before we get a chance to unhilite the menu. */
+ if (strlen (cmdbuf) > 0)
+ execute_command (cmdbuf, 0);
+}
+
+char commandbuf[1000];
+
+do_keyboard_command (key)
+int key;
+{
+ int startpos, endpos, i, len;
+ char *last_newline;
+ char buf[10], *text_str, *command, *cmd_start;
+ CharsHandle text;
+
+ if (key == '\015' || key == '\003')
+ {
+ text = TEGetText (console_text);
+ HLock ((Handle) text);
+ text_str = *text;
+ startpos = (*console_text)->selStart;
+ endpos = (*console_text)->selEnd;
+ if (startpos != endpos)
+ {
+ len = endpos - startpos;
+ cmd_start = text_str + startpos;
+ }
+ else
+ {
+ for (i = startpos - 1; i >= 0; --i)
+ if (text_str[i] == '\015')
+ break;
+ last_newline = text_str + i;
+ len = (text_str + startpos) - 1 - last_newline;
+ cmd_start = last_newline + 1;
+ }
+ if (len > 1000) len = 999;
+ if (len < 0) len = 0;
+ strncpy (commandbuf + 1, cmd_start, len);
+ commandbuf[1 + len] = 0;
+ command = commandbuf + 1;
+ HUnlock ((Handle) text);
+ commandbuf[0] = strlen(command);
+
+ /* Insert a newline and recalculate before doing any command. */
+ key = '\015';
+ TEKey (key, console_text);
+ TEInsert (buf, 1, console_text);
+ adjust_console_sizes ();
+ adjust_console_scrollbars ();
+ adjust_console_text ();
+
+ if (strlen (command) > 0)
+ {
+ execute_command (command, 0);
+ bpstat_do_actions (&stop_bpstat);
+ }
+ }
+ else
+ {
+ /* A self-inserting character. This includes delete. */
+ TEKey (key, console_text);
+ }
+}
+
+/* Draw all graphical stuff in the console window. */
+
+draw_console ()
+{
+ SetPort (console_window);
+ TEUpdate (&(console_window->portRect), console_text);
+}
+
+/* Cause an update of a given window's entire contents. */
+
+force_update (win)
+WindowPtr win;
+{
+ GrafPtr oldport;
+
+ if (win == nil) return;
+ GetPort (&oldport);
+ SetPort (win);
+ EraseRect (&win->portRect);
+ InvalRect (&win->portRect);
+ SetPort (oldport);
+}
+
+adjust_console_sizes ()
+{
+ Rect tmprect;
+
+ tmprect = console_window->portRect;
+ /* Move and size the scrollbar. */
+ MoveControl (console_v_scrollbar, tmprect.right - sbarwid, 0);
+ SizeControl (console_v_scrollbar, sbarwid + 1, tmprect.bottom - sbarwid + 1);
+ /* Move and size the text. */
+ tmprect.left += 7;
+ tmprect.right -= sbarwid;
+ tmprect.bottom -= sbarwid;
+ InsetRect(&tmprect, 1, 1);
+ (*console_text)->destRect = tmprect;
+ /* Fiddle bottom of viewrect to be even multiple of text lines. */
+ tmprect.bottom = tmprect.top
+ + ((tmprect.bottom - tmprect.top) / (*console_text)->lineHeight)
+ * (*console_text)->lineHeight;
+ (*console_text)->viewRect = tmprect;
+}
+
+adjust_console_scrollbars ()
+{
+ int lines, newmax, value;
+
+ (*console_v_scrollbar)->contrlVis = 0;
+ lines = (*console_text)->nLines;
+ newmax = lines - (((*console_text)->viewRect.bottom
+ - (*console_text)->viewRect.top)
+ / (*console_text)->lineHeight);
+ if (newmax < 0) newmax = 0;
+ SetCtlMax (console_v_scrollbar, newmax);
+ value = ((*console_text)->viewRect.top - (*console_text)->destRect.top)
+ / (*console_text)->lineHeight;
+ SetCtlValue (console_v_scrollbar, value);
+ (*console_v_scrollbar)->contrlVis = 0xff;
+ ShowControl (console_v_scrollbar);
+}
+
+/* Scroll the TE record so that it is consistent with the scrollbar(s). */
+
+adjust_console_text ()
+{
+ TEScroll (((*console_text)->viewRect.left
+ - (*console_text)->destRect.left)
+ - 0 /* get h scroll value */,
+ ((((*console_text)->viewRect.top - (*console_text)->destRect.top)
+ / (*console_text)->lineHeight)
+ - GetCtlValue (console_v_scrollbar))
+ * (*console_text)->lineHeight,
+ console_text);
+}
+
+/* Readline substitute. */
+
+char *
+readline (char *prrompt)
+{
+ return gdb_readline (prrompt);
+}
+
+char *rl_completer_word_break_characters;
+
+char *rl_completer_quote_characters;
+
+int (*rl_completion_entry_function) ();
+
+int rl_point;
+
+char *rl_line_buffer;
+
+char *rl_readline_name;
+
+/* History substitute. */
+
+void
+add_history (char *buf)
+{
+}
+
+void
+stifle_history (int n)
+{
+}
+
+int
+unstifle_history ()
+{
+}
+
+int
+read_history (char *name)
+{
+}
+
+int
+write_history (char *name)
+{
+}
+
+int
+history_expand (char *x, char **y)
+{
+}
+
+extern HIST_ENTRY *
+history_get (int xxx)
+{
+ return NULL;
+}
+
+int history_base;
+
+char *
+filename_completion_function (char *text, char *name)
+{
+ return "?";
+}
+
+char *
+tilde_expand (char *str)
+{
+ return strsave (str);
+}
+
+/* Modified versions of standard I/O. */
+
+#undef fprintf
+
+int
+hacked_fprintf (FILE *fp, const char *fmt, ...)
+{
+ int ret;
+ va_list ap;
+
+ va_start (ap, fmt);
+ if (mac_app && (fp == stdout || fp == stderr))
+ {
+ char buf[1000];
+
+ ret = vsprintf(buf, fmt, ap);
+ TEInsert (buf, strlen(buf), console_text);
+ }
+ else
+ ret = vfprintf (fp, fmt, ap);
+ va_end (ap);
+ return ret;
+}
+
+#undef printf
+
+int
+hacked_printf (const char *fmt, ...)
+{
+ int ret;
+ va_list ap;
+
+ va_start (ap, fmt);
+ ret = hacked_vfprintf(stdout, fmt, ap);
+ va_end (ap);
+ return ret;
+}
+
+#undef vfprintf
+
+int
+hacked_vfprintf (FILE *fp, const char *format, va_list args)
+{
+ if (mac_app && (fp == stdout || fp == stderr))
+ {
+ char buf[1000];
+ int ret;
+
+ ret = vsprintf(buf, format, args);
+ TEInsert (buf, strlen(buf), console_text);
+ if (strchr(buf, '\n'))
+ {
+ adjust_console_sizes ();
+ adjust_console_scrollbars ();
+ adjust_console_text ();
+ }
+ return ret;
+ }
+ else
+ return vfprintf (fp, format, args);
+}
+
+#undef fputs
+
+hacked_fputs (const char *s, FILE *fp)
+{
+ if (mac_app && (fp == stdout || fp == stderr))
+ {
+ TEInsert (s, strlen(s), console_text);
+ if (strchr(s, '\n'))
+ {
+ adjust_console_sizes ();
+ adjust_console_scrollbars ();
+ adjust_console_text ();
+ }
+ return 0;
+ }
+ else
+ return fputs (s, fp);
+}
+
+#undef fputc
+
+hacked_fputc (const char c, FILE *fp)
+{
+ if (mac_app && (fp == stdout || fp == stderr))
+ {
+ char buf[1];
+
+ buf[0] = c;
+ TEInsert (buf, 1, console_text);
+ if (c == '\n')
+ {
+ adjust_console_sizes ();
+ adjust_console_scrollbars ();
+ adjust_console_text ();
+ }
+ return c;
+ }
+ else
+ return fputc (c, fp);
+}
+
+#undef putc
+
+hacked_putc (const char c, FILE *fp)
+{
+ if (mac_app && (fp == stdout || fp == stderr))
+ {
+ char buf[1];
+
+ buf[0] = c;
+ TEInsert (buf, 1, console_text);
+ if (c == '\n')
+ {
+ adjust_console_sizes ();
+ adjust_console_scrollbars ();
+ adjust_console_text ();
+ }
+ return c;
+ }
+ else
+ return fputc (c, fp);
+}
+
+#undef fflush
+
+hacked_fflush (FILE *fp)
+{
+ if (mac_app && (fp == stdout || fp == stderr))
+ {
+ adjust_console_sizes ();
+ adjust_console_scrollbars ();
+ adjust_console_text ();
+ return 0;
+ }
+ return fflush (fp);
+}
+
+#undef fgetc
+
+hacked_fgetc (FILE *fp)
+{
+ if (mac_app && (fp == stdin))
+ {
+ /* Catch any attempts to use this. */
+ DebugStr("\pShould not be reading from stdin!");
+ return '\n';
+ }
+ return fgetc (fp);
+}
diff --git a/gdb/main.c b/gdb/main.c
new file mode 100644
index 00000000000..18c24459e8d
--- /dev/null
+++ b/gdb/main.c
@@ -0,0 +1,780 @@
+/* Top level stuff for GDB, the GNU debugger.
+ Copyright 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include <setjmp.h>
+#include "top.h"
+#include "target.h"
+#include "inferior.h"
+#include "call-cmds.h"
+
+#include "getopt.h"
+
+#include <sys/types.h>
+#include "gdb_stat.h"
+#include <ctype.h>
+
+#include "gdb_string.h"
+
+/* 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 = SIGSETJMP (error_return)) \
+ ? (PTR) 0 : (PTR) memcpy (quit_return, error_return, sizeof (SIGJMP_BUF))) \
+ , top_level_val)
+
+/* If nonzero, display time usage both at startup and for each command. */
+
+int display_time;
+
+/* If nonzero, display space usage both at startup and for each command. */
+
+int display_space;
+
+/* Whether this is the command line version or not */
+int tui_version = 0;
+
+/* Whether xdb commands will be handled */
+int xdb_commands = 0;
+
+/* Whether dbx commands will be handled */
+int dbx_commands = 0;
+
+GDB_FILE *gdb_stdout;
+GDB_FILE *gdb_stderr;
+
+/* Whether to enable writing into executable and core files */
+extern int write_files;
+
+static void print_gdb_help PARAMS ((GDB_FILE *));
+extern void gdb_init PARAMS ((char *));
+
+/* These two are used to set the external editor commands when gdb is farming
+ out files to be edited by another program. */
+
+extern int enable_external_editor;
+extern char * external_editor_command;
+
+#ifdef __CYGWIN__
+#include <windows.h> /* for MAX_PATH */
+#include <sys/cygwin.h> /* for cygwin32_conv_to_posix_path */
+#endif
+
+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;
+
+ long time_at_startup = get_run_time ();
+
+ int gdb_file_size;
+
+ START_PROGRESS (argv[0], 0);
+
+#ifdef MPW
+ /* Do all Mac-specific setup. */
+ mac_init ();
+#endif /* MPW */
+
+ /* 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 (gdb_dirbuf, sizeof (gdb_dirbuf));
+ current_directory = gdb_dirbuf;
+
+ gdb_file_size = sizeof(GDB_FILE);
+
+ gdb_stdout = (GDB_FILE *)xmalloc (gdb_file_size);
+ gdb_stdout->ts_streamtype = afile;
+ gdb_stdout->ts_filestream = stdout;
+ gdb_stdout->ts_strbuf = NULL;
+ gdb_stdout->ts_buflen = 0;
+
+ gdb_stderr = (GDB_FILE *)xmalloc (gdb_file_size);
+ gdb_stderr->ts_streamtype = afile;
+ gdb_stderr->ts_filestream = stderr;
+ gdb_stderr->ts_strbuf = NULL;
+ gdb_stderr->ts_buflen = 0;
+
+ /* 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[] =
+ {
+#if defined(TUI)
+ {"tui", no_argument, &tui_version, 1},
+#endif
+ {"xdb", no_argument, &xdb_commands, 1},
+ {"dbx", no_argument, &dbx_commands, 1},
+ {"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},
+
+ /* This is a synonym for "--annotate=1". --annotate is now preferred,
+ but keep this here for a long time because people will be running
+ emacses which use --fullname. */
+ {"fullname", no_argument, 0, 'f'},
+ {"f", no_argument, 0, 'f'},
+
+ {"annotate", required_argument, 0, 12},
+ {"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'},
+ {"nw", no_argument, &use_windows, 0},
+ {"nowindows", no_argument, &use_windows, 0},
+ {"w", no_argument, &use_windows, 1},
+ {"windows", no_argument, &use_windows, 1},
+ {"statistics", no_argument, 0, 13},
+ {"write", no_argument, &write_files, 1},
+/* 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 12:
+ /* FIXME: what if the syntax is wrong (e.g. not digits)? */
+ annotation_level = atoi (optarg);
+ break;
+ case 13:
+ /* Enable the display of both time and space usage. */
+ display_time = 1;
+ display_space = 1;
+ break;
+ case 'f':
+ annotation_level = 1;
+/* We have probably been invoked from emacs. Disable window interface. */
+ use_windows = 0;
+ 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)
+
+ /* Don't use *_filtered or warning() (which relies on
+ current_target) until after initialize_all_files(). */
+
+ fprintf_unfiltered
+ (gdb_stderr,
+ "warning: could not set baud rate to `%s'.\n", optarg);
+ else
+ baud_rate = i;
+ }
+ case 'l':
+ {
+ int i;
+ char *p;
+
+ i = strtol (optarg, &p, 0);
+ if (i == 0 && p == optarg)
+
+ /* Don't use *_filtered or warning() (which relies on
+ current_target) until after initialize_all_files(). */
+
+ fprintf_unfiltered
+ (gdb_stderr,
+ "warning: could not set timeout limit to `%s'.\n", optarg);
+ else
+ remote_timeout = i;
+ }
+ break;
+
+#ifdef ADDITIONAL_OPTION_CASES
+ ADDITIONAL_OPTION_CASES
+#endif
+ case '?':
+ fprintf_unfiltered (gdb_stderr,
+ "Use `%s --help' for a complete list of options.\n",
+ argv[0]);
+ exit (1);
+ }
+ }
+
+ /* If --help or --version, disable window interface. */
+ if (print_help || print_version)
+ {
+ use_windows = 0;
+#ifdef TUI
+ /* Disable the TUI as well. */
+ tui_version = 0;
+#endif
+ }
+
+#ifdef TUI
+ /* An explicit --tui flag overrides the default UI, which is the
+ window system. */
+ if (tui_version)
+ use_windows = 0;
+#endif
+
+ /* 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_unfiltered (gdb_stderr,
+ "Excess command line arguments ignored. (%s%s)\n",
+ argv[optind], (optind == argc - 1) ? "" : " ...");
+ break;
+ }
+ if (batch)
+ quiet = 1;
+ }
+
+#if defined(TUI)
+ if (tui_version)
+ init_ui_hook = tuiInit;
+#endif
+ gdb_init (argv[0]);
+
+ /* Do these (and anything which might call wrap_here or *_filtered)
+ after initialize_all_files. */
+ if (print_version)
+ {
+ print_gdb_version (gdb_stdout);
+ wrap_here ("");
+ printf_filtered ("\n");
+ exit (0);
+ }
+
+ if (print_help)
+ {
+ print_gdb_help (gdb_stdout);
+ fputs_unfiltered ("\n", gdb_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_gdb_version (gdb_stdout);
+ if (symarg)
+ printf_filtered ("..");
+ wrap_here("");
+ gdb_flush (gdb_stdout); /* Force to screen during slow operations */
+ }
+
+ error_pre_print = "\n\n";
+ quit_pre_print = error_pre_print;
+
+ /* We may get more than one warning, don't double space all of them... */
+ warning_pre_print = "\nwarning: ";
+
+ /* 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. */
+#ifdef __CYGWIN32__
+ {
+ char * tmp = getenv ("HOME");
+
+ if (tmp != NULL)
+ {
+ homedir = (char *) alloca (MAX_PATH+1);
+ cygwin32_conv_to_posix_path (tmp, homedir);
+ }
+ else
+ homedir = NULL;
+ }
+#else
+ homedir = getenv ("HOME");
+#endif
+ if (homedir)
+ {
+ homeinit = (char *) alloca (strlen (homedir) +
+ strlen (gdbinit) + 10);
+ strcpy (homeinit, homedir);
+ strcat (homeinit, "/");
+ strcat (homeinit, gdbinit);
+
+ if (!inhibit_gdbinit)
+ {
+ 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);
+ }
+ }
+ 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";
+ quit_pre_print = error_pre_print;
+ 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 = NULL;
+ quit_pre_print = NULL;
+ 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)
+ {
+ 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
+
+ END_PROGRESS (argv[0]);
+
+ /* Show time and/or space usage. */
+
+ if (display_time)
+ {
+ long init_time = get_run_time () - time_at_startup;
+
+ printf_unfiltered ("Startup time: %ld.%06ld\n",
+ init_time / 1000000, init_time % 1000000);
+ }
+
+ if (display_space)
+ {
+#ifdef HAVE_SBRK
+ extern char **environ;
+ char *lim = (char *) sbrk (0);
+
+ printf_unfiltered ("Startup size: data size %ld\n",
+ (long) (lim - (char *) &environ));
+#endif
+ }
+
+ /* The default command loop.
+ The WIN32 Gui calls this main to set up gdb's state, and
+ has its own command loop. */
+#if !defined _WIN32 || defined __GNUC__
+ while (1)
+ {
+ if (!SET_TOP_LEVEL ())
+ {
+ do_cleanups (ALL_CLEANUPS); /* Do complete cleanup */
+ /* GUIs generally have their own command loop, mainloop, or whatever.
+ This is a good place to gain control because many error
+ conditions will end up here via longjmp(). */
+ if (command_loop_hook)
+ command_loop_hook ();
+ else
+ command_loop ();
+ quit_command ((char *)0, instream == stdin);
+ }
+ }
+
+ /* No exit -- exit is through quit_command. */
+#endif
+
+}
+
+/* Don't use *_filtered for printing help. We don't want to prompt
+ for continue no matter how small the screen or how much we're going
+ to print. */
+
+static void
+print_gdb_help (stream)
+ GDB_FILE *stream;
+{
+ fputs_unfiltered ("\
+This is the GNU debugger. Usage:\n\n\
+ gdb [options] [executable-file [core-file or process-id]]\n\n\
+Options:\n\n\
+", stream);
+ fputs_unfiltered ("\
+ -b BAUDRATE Set serial port baud rate used for remote debugging.\n\
+ --batch Exit after processing options.\n\
+ --cd=DIR Change current directory to DIR.\n\
+ --command=FILE Execute GDB commands from FILE.\n\
+ --core=COREFILE Analyze the core dump COREFILE.\n\
+", stream);
+ fputs_unfiltered ("\
+ --dbx DBX compatibility mode.\n\
+ --directory=DIR Search for source files in DIR.\n\
+ --epoch Output information used by epoch emacs-GDB interface.\n\
+ --exec=EXECFILE Use EXECFILE as the executable.\n\
+ --fullname Output information used by emacs-GDB interface.\n\
+ --help Print this message.\n\
+", stream);
+ fputs_unfiltered ("\
+ --mapped Use mapped symbol files if supported on this system.\n\
+ --nw Do not use a window interface.\n\
+ --nx Do not read .gdbinit file.\n\
+ --quiet Do not print version number on startup.\n\
+ --readnow Fully read symbol files on first access.\n\
+", stream);
+ fputs_unfiltered ("\
+ --se=FILE Use FILE as symbol file and executable file.\n\
+ --symbols=SYMFILE Read symbols from SYMFILE.\n\
+ --tty=TTY Use TTY for input/output by the program being debugged.\n\
+", stream);
+#if defined(TUI)
+ fputs_unfiltered ("\
+ --tui Use a terminal user interface.\n\
+", stream);
+#endif
+ fputs_unfiltered ("\
+ --version Print version information and then exit.\n\
+ -w Use a window interface.\n\
+ --write Set writing into executable and core files.\n\
+ --xdb XDB compatibility mode.\n\
+", stream);
+#ifdef ADDITIONAL_OPTION_HELP
+ fputs_unfiltered (ADDITIONAL_OPTION_HELP, stream);
+#endif
+ fputs_unfiltered ("\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\
+Report bugs to \"bug-gdb@prep.ai.mit.edu\".\
+", stream);
+}
+
+
+void
+init_proc ()
+{
+}
+
+void
+proc_remove_foreign (pid)
+ int pid;
+{
+}
+
+/* All I/O sent to the *_filtered and *_unfiltered functions eventually ends up
+ here. The fputs_unfiltered_hook is primarily used by GUIs to collect all
+ output and send it to the GUI, instead of the controlling terminal. Only
+ output to gdb_stdout and gdb_stderr are sent to the hook. Everything else
+ is sent on to fputs to allow file I/O to be handled appropriately. */
+
+void
+fputs_unfiltered (linebuffer, stream)
+ const char *linebuffer;
+ GDB_FILE *stream;
+{
+#if defined(TUI)
+ extern int tui_owns_terminal;
+#endif
+ /* If anything (GUI, TUI) wants to capture GDB output, this is
+ * the place... the way to do it is to set up
+ * fputs_unfiltered_hook.
+ * Our TUI ("gdb -tui") used to hook output, but in the
+ * new (XDB style) scheme, we do not do that anymore... - RT
+ */
+ if (fputs_unfiltered_hook
+ && (stream == gdb_stdout
+ || stream == gdb_stderr))
+ fputs_unfiltered_hook (linebuffer, stream);
+ else
+ {
+#if defined(TUI)
+ if (tui_version && tui_owns_terminal) {
+ /* If we get here somehow while updating the TUI (from
+ * within a tuiDo(), then we need to temporarily
+ * set up the terminal for GDB output. This probably just
+ * happens on error output.
+ */
+
+ if (stream->ts_streamtype == astring) {
+ gdb_file_adjust_strbuf(strlen(linebuffer), stream);
+ strcat(stream->ts_strbuf, linebuffer);
+ } else {
+ tuiTermUnsetup(0, (tui_version) ? cmdWin->detail.commandInfo.curch : 0);
+ fputs (linebuffer, stream->ts_filestream);
+ tuiTermSetup(0);
+ if (linebuffer[strlen(linebuffer) - 1] == '\n')
+ tuiClearCommandCharCount();
+ else
+ tuiIncrCommandCharCountBy(strlen(linebuffer));
+ }
+ } else {
+ /* The normal case - just do a fputs() */
+ if (stream->ts_streamtype == astring) {
+ gdb_file_adjust_strbuf(strlen(linebuffer), stream);
+ strcat(stream->ts_strbuf, linebuffer);
+ } else fputs (linebuffer, stream->ts_filestream);
+ }
+
+
+#else
+ if (stream->ts_streamtype == astring) {
+ gdb_file_adjust_strbuf(strlen(linebuffer), stream);
+ strcat(stream->ts_strbuf, linebuffer);
+ } else fputs (linebuffer, stream->ts_filestream);
+#endif
+ }
+}
diff --git a/gdb/maint.c b/gdb/maint.c
new file mode 100644
index 00000000000..cf4ceb7e9a1
--- /dev/null
+++ b/gdb/maint.c
@@ -0,0 +1,449 @@
+/* Support for GDB maintenance commands.
+ Copyright 1992, 1993, 1994 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+
+#include "defs.h"
+
+#if MAINTENANCE_CMDS /* Entire rest of file goes away if not including maint cmds */
+
+#include <ctype.h>
+#include <signal.h>
+#include "command.h"
+#include "gdbcmd.h"
+#include "symtab.h"
+#include "gdbtypes.h"
+#include "demangle.h"
+#include "gdbcore.h"
+#include "expression.h" /* For language.h */
+#include "language.h"
+#include "symfile.h"
+#include "objfiles.h"
+#include "value.h"
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+static void maintenance_command PARAMS ((char *, int));
+
+static void maintenance_dump_me PARAMS ((char *, int));
+
+static void maintenance_demangle PARAMS ((char *, int));
+
+static void maintenance_time_display PARAMS ((char *, int));
+
+static void maintenance_space_display PARAMS ((char *, int));
+
+static void maintenance_info_command PARAMS ((char *, int));
+
+static void print_section_table PARAMS ((bfd *, asection *, PTR));
+
+static void maintenance_info_sections PARAMS ((char *, int));
+
+static void maintenance_print_command PARAMS ((char *, int));
+
+/* Set this to the maximum number of seconds to wait instead of waiting forever
+ in target_wait(). If this timer times out, then it generates an error and
+ the command is aborted. This replaces most of the need for timeouts in the
+ GDB test suite, and makes it possible to distinguish between a hung target
+ and one with slow communications. */
+
+int watchdog = 0;
+
+/*
+
+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_unfiltered ("\"maintenance\" must be followed by the name of a maintenance command.\n");
+ help_list (maintenancelist, "maintenance ", -1, gdb_stdout);
+}
+
+#ifndef _WIN32
+/* 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);
+ }
+}
+#endif
+
+/* 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_unfiltered ("\"maintenance demangle\" takes an argument to demangle.\n");
+ }
+ else
+ {
+ demangled = cplus_demangle (args, DMGL_ANSI | DMGL_PARAMS);
+ if (demangled != NULL)
+ {
+ printf_unfiltered ("%s\n", demangled);
+ free (demangled);
+ }
+ else
+ {
+ printf_unfiltered ("Can't demangle \"%s\"\n", args);
+ }
+ }
+}
+
+static void
+maintenance_time_display (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ extern int display_time;
+
+ if (args == NULL || *args == '\0')
+ printf_unfiltered ("\"maintenance time\" takes a numeric argument.\n");
+ else
+ display_time = strtol (args, NULL, 10);
+}
+
+static void
+maintenance_space_display (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ extern int display_space;
+
+ if (args == NULL || *args == '\0')
+ printf_unfiltered ("\"maintenance space\" takes a numeric argument.\n");
+ else
+ display_space = strtol (args, NULL, 10);
+}
+
+/* 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_unfiltered ("\"maintenance info\" must be followed by the name of an info command.\n");
+ help_list (maintenanceinfolist, "maintenance info ", -1, gdb_stdout);
+}
+
+static void
+print_section_table (abfd, asect, ignore)
+ bfd *abfd;
+ asection *asect;
+ PTR ignore;
+{
+ flagword flags;
+
+ flags = bfd_get_section_flags (abfd, asect);
+
+ /* FIXME-32x64: Need print_address_numeric with field width. */
+ 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_COFF_SHARED_LIBRARY)
+ printf_filtered (" COFF_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);
+ }
+}
+
+/* ARGSUSED */
+void
+maintenance_print_statistics (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ print_objfile_statistics ();
+ print_symbol_bcache_statistics ();
+}
+
+/* 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_unfiltered ("\"maintenance print\" must be followed by the name of a print command.\n");
+ help_list (maintenanceprintlist, "maintenance print ", -1, gdb_stdout);
+}
+
+/* The "maintenance translate-address" command converts a section and address
+ to a symbol. This can be called in two ways:
+ maintenance translate-address <secname> <addr>
+ or maintenance translate-address <addr>
+*/
+
+static void
+maintenance_translate_address (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ CORE_ADDR address;
+ asection *sect;
+ char *p;
+ struct minimal_symbol *sym;
+ struct objfile *objfile;
+
+ if (arg == NULL || *arg == 0)
+ error ("requires argument (address or section + address)");
+
+ sect = NULL;
+ p = arg;
+
+ if (!isdigit (*p))
+ { /* See if we have a valid section name */
+ while (*p && !isspace (*p)) /* Find end of section name */
+ p++;
+ if (*p == '\000') /* End of command? */
+ error ("Need to specify <section-name> and <address>");
+ *p++ = '\000';
+ while (isspace (*p)) p++; /* Skip whitespace */
+
+ ALL_OBJFILES (objfile)
+ {
+ sect = bfd_get_section_by_name (objfile->obfd, arg);
+ if (sect != NULL)
+ break;
+ }
+
+ if (!sect)
+ error ("Unknown section %s.", arg);
+ }
+
+ address = parse_and_eval_address (p);
+
+ if (sect)
+ sym = lookup_minimal_symbol_by_pc_section (address, sect);
+ else
+ sym = lookup_minimal_symbol_by_pc (address);
+
+ if (sym)
+ printf_filtered ("%s+%u\n",
+ SYMBOL_SOURCE_NAME (sym),
+ address - SYMBOL_VALUE_ADDRESS (sym));
+ else if (sect)
+ printf_filtered ("no symbol at %s:0x%08x\n", sect->name, address);
+ else
+ printf_filtered ("no symbol at 0x%08x\n", address);
+
+ return;
+}
+
+#endif /* MAINTENANCE_CMDS */
+
+void
+_initialize_maint_cmds ()
+{
+#if MAINTENANCE_CMDS /* Entire file goes away if not including 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);
+
+#ifndef _WIN32
+ 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);
+#endif
+
+ 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 ("time", class_maintenance, maintenance_time_display,
+ "Set the display of time usage.\n\
+If nonzero, will cause the execution time for each command to be\n\
+displayed, following the command's output.",
+ &maintenancelist);
+
+ add_cmd ("space", class_maintenance, maintenance_space_display,
+ "Set the display of space usage.\n\
+If nonzero, will cause the execution space for each command to be\n\
+displayed, following the command's output.",
+ &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);
+
+ add_cmd ("statistics", class_maintenance, maintenance_print_statistics,
+ "Print statistics about internal gdb state.",
+ &maintenanceprintlist);
+
+ add_cmd ("check-symtabs", class_maintenance, maintenance_check_symtabs,
+ "Check consistency of psymtabs and symtabs.",
+ &maintenancelist);
+
+ add_cmd ("translate-address", class_maintenance, maintenance_translate_address,
+ "Translate a section name and address to a symbol.",
+ &maintenancelist);
+
+ add_show_from_set (
+ add_set_cmd ("watchdog", class_maintenance, var_zinteger, (char *)&watchdog,
+ "Set watchdog timer.\n\
+When non-zero, this timeout is used instead of waiting forever for a target to\n\
+finish a low-level step or continue operation. If the specified amount of time\n\
+passes without a response from the target, an error occurs.", &setlist),
+ &showlist);
+#endif /* MAINTENANCE_CMDS */
+}
diff --git a/gdb/mdebugread.c b/gdb/mdebugread.c
new file mode 100644
index 00000000000..1064490dcff
--- /dev/null
+++ b/gdb/mdebugread.c
@@ -0,0 +1,4544 @@
+/* Read a symbol table in ECOFF format (Third-Eye).
+ Copyright 1986, 87, 89, 90, 91, 92, 93, 94, 95, 96, 97, 1998
+ Free Software Foundation, Inc.
+ Original version 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* This module provides the function mdebug_build_psymtabs. It reads
+ ECOFF debugging information into partial symbol tables. The
+ debugging information is read from two structures. A struct
+ ecoff_debug_swap includes the sizes of each ECOFF structure and
+ swapping routines; these are fixed for a particular target. A
+ struct ecoff_debug_info points to the debugging information for a
+ particular object file.
+
+ 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"
+#include "demangle.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__"
+extern void ecoff_relocate_efi PARAMS ((struct symbol *, CORE_ADDR));
+#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 "gdb_stat.h"
+#include "gdb_string.h"
+
+#include "gdb-stabs.h"
+
+#include "bfd.h"
+
+#include "coff/ecoff.h" /* COFF-like aspects of ecoff files */
+
+#include "libaout.h" /* Private BFD a.out information. */
+#include "aout/aout64.h"
+#include "aout/stab_gnu.h" /* STABS 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
+
+/* Provide a way to test if we have both ECOFF and ELF symbol tables.
+ We use this define in order to know whether we should override a
+ symbol's ECOFF section with its ELF section. This is necessary in
+ case the symbol's ELF section could not be represented in ECOFF. */
+#define ECOFF_IN_ELF(bfd) (bfd_get_flavour (bfd) == bfd_target_elf_flavour \
+ && bfd_get_section_by_name (bfd, ".mdebug") != NULL)
+
+
+/* We put a pointer to this structure in the read_symtab_private field
+ of the psymtab. */
+
+struct symloc
+{
+ /* Index of the FDR that this psymtab represents. */
+ int fdr_idx;
+ /* The BFD that the psymtab was created from. */
+ bfd *cur_bfd;
+ const struct ecoff_debug_swap *debug_swap;
+ struct ecoff_debug_info *debug_info;
+ struct mdebug_pending **pending_list;
+ /* Pointer to external symbols for this file. */
+ EXTR *extern_tab;
+ /* Size of extern_tab. */
+ int extern_count;
+ enum language pst_language;
+};
+
+#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)
+#define DEBUG_SWAP(p) (PST_PRIVATE(p)->debug_swap)
+#define DEBUG_INFO(p) (PST_PRIVATE(p)->debug_info)
+#define PENDING_LIST(p) (PST_PRIVATE(p)->pending_list)
+
+#define SC_IS_TEXT(sc) ((sc) == scText \
+ || (sc) == scRConst \
+ || (sc) == scInit \
+ || (sc) == scFini)
+#define SC_IS_DATA(sc) ((sc) == scData \
+ || (sc) == scSData \
+ || (sc) == scRData \
+ || (sc) == scPData \
+ || (sc) == scXData)
+#define SC_IS_COMMON(sc) ((sc) == scCommon || (sc) == scSCommon)
+#define SC_IS_BSS(sc) ((sc) == scBss || (sc) == scSBss)
+#define SC_IS_UNDEF(sc) ((sc) == scUndefined || (sc) == scSUndefined)
+
+
+/* Things we import explicitly from other modules */
+
+extern int info_verbose;
+
+/* Various complaints about symbol reading that don't abort the process */
+
+static struct complaint bad_file_number_complaint =
+{"bad file number %d", 0, 0};
+
+static struct complaint index_complaint =
+{"bad aux index at symbol %s", 0, 0};
+
+static struct complaint aux_index_complaint =
+{"bad proc end in aux found from symbol %s", 0, 0};
+
+static struct complaint block_index_complaint =
+{"bad aux index at block symbol %s", 0, 0};
+
+static struct complaint unknown_ext_complaint =
+{"unknown external symbol %s", 0, 0};
+
+static struct complaint unknown_sym_complaint =
+{"unknown local symbol %s", 0, 0};
+
+static struct complaint unknown_st_complaint =
+{"with type %d", 0, 0};
+
+static struct complaint block_overflow_complaint =
+{"block containing %s overfilled", 0, 0};
+
+static struct complaint basic_type_complaint =
+{"cannot map ECOFF basic type 0x%x for %s", 0, 0};
+
+static struct complaint unknown_type_qual_complaint =
+{"unknown type qualifier 0x%x", 0, 0};
+
+static struct complaint array_index_type_complaint =
+{"illegal array index type for %s, assuming int", 0, 0};
+
+static struct complaint bad_tag_guess_complaint =
+{"guessed tag type of %s incorrectly", 0, 0};
+
+static struct complaint block_member_complaint =
+{"declaration block contains unhandled symbol type %d", 0, 0};
+
+static struct complaint stEnd_complaint =
+{"stEnd with storage class %d not handled", 0, 0};
+
+static struct complaint unknown_mdebug_symtype_complaint =
+{"unknown symbol type 0x%x", 0, 0};
+
+static struct complaint stab_unknown_complaint =
+{"unknown stabs symbol %s", 0, 0};
+
+static struct complaint pdr_for_nonsymbol_complaint =
+{"PDR for %s, but no symbol", 0, 0};
+
+static struct complaint pdr_static_symbol_complaint =
+{"can't handle PDR for static proc at 0x%lx", 0, 0};
+
+static struct complaint bad_setjmp_pdr_complaint =
+{"fixing bad setjmp PDR from libc", 0, 0};
+
+static struct complaint bad_fbitfield_complaint =
+{"can't handle TIR fBitfield for %s", 0, 0};
+
+static struct complaint bad_continued_complaint =
+{"illegal TIR continued for %s", 0, 0};
+
+static struct complaint bad_rfd_entry_complaint =
+{"bad rfd entry for %s: file %d, index %d", 0, 0};
+
+static struct complaint unexpected_type_code_complaint =
+{"unexpected type code for %s", 0, 0};
+
+static struct complaint unable_to_cross_ref_complaint =
+{"unable to cross ref btTypedef for %s", 0, 0};
+
+static struct complaint bad_indirect_xref_complaint =
+{"unable to cross ref btIndirect for %s", 0, 0};
+
+static struct complaint illegal_forward_tq0_complaint =
+{"illegal tq0 in forward typedef for %s", 0, 0};
+
+static struct complaint illegal_forward_bt_complaint =
+{"illegal bt %d in forward typedef for %s", 0, 0};
+
+static struct complaint bad_linetable_guess_complaint =
+{"guessed size of linetable for %s incorrectly", 0, 0};
+
+static struct complaint bad_ext_ifd_complaint =
+{"bad ifd for external symbol: %d (max %d)", 0, 0};
+
+static struct complaint bad_ext_iss_complaint =
+{"bad iss for external symbol: %ld (max %ld)", 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;
+
+/* How to parse debugging information for CUR_BFD. */
+
+static const struct ecoff_debug_swap *debug_swap;
+
+/* Pointers to debugging information for CUR_BFD. */
+
+static struct ecoff_debug_info *debug_info;
+
+/* 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 int max_gdbinfo;
+static int 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;
+
+/* Types corresponding to mdebug format bt* basic types. */
+
+static struct type *mdebug_type_void;
+static struct type *mdebug_type_char;
+static struct type *mdebug_type_short;
+static struct type *mdebug_type_int_32;
+#define mdebug_type_int mdebug_type_int_32
+static struct type *mdebug_type_int_64;
+static struct type *mdebug_type_long_32;
+static struct type *mdebug_type_long_64;
+static struct type *mdebug_type_long_long_64;
+static struct type *mdebug_type_unsigned_char;
+static struct type *mdebug_type_unsigned_short;
+static struct type *mdebug_type_unsigned_int_32;
+static struct type *mdebug_type_unsigned_int_64;
+static struct type *mdebug_type_unsigned_long_32;
+static struct type *mdebug_type_unsigned_long_64;
+static struct type *mdebug_type_unsigned_long_long_64;
+static struct type *mdebug_type_adr_32;
+static struct type *mdebug_type_adr_64;
+static struct type *mdebug_type_float;
+static struct type *mdebug_type_double;
+static struct type *mdebug_type_complex;
+static struct type *mdebug_type_double_complex;
+static struct type *mdebug_type_fixed_dec;
+static struct type *mdebug_type_float_dec;
+static struct type *mdebug_type_string;
+
+/* Types for symbols from files compiled without debugging info. */
+
+static struct type *nodebug_func_symbol_type;
+static struct type *nodebug_var_symbol_type;
+
+/* Nonzero if we have seen ecoff debugging info for a file. */
+
+static int found_ecoff_debugging_info;
+
+/* Forward declarations */
+
+static void
+add_pending PARAMS ((FDR *, char *, struct type *));
+
+static struct mdebug_pending *
+is_pending_symbol PARAMS ((FDR *, char *));
+
+static void
+pop_parse_stack PARAMS ((void));
+
+static void
+push_parse_stack PARAMS ((void));
+
+static char *
+fdr_name PARAMS ((FDR *));
+
+static void
+mdebug_psymtab_to_symtab PARAMS ((struct partial_symtab *));
+
+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 FDR
+*get_rfd PARAMS ((int, int));
+
+static int
+has_opaque_xref PARAMS ((FDR *, SYMR *));
+
+static int
+cross_ref PARAMS ((int, union aux_ext *, struct type **, enum type_code,
+ char **, int, char *));
+
+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, struct section_offsets *));
+
+static struct type *
+parse_type PARAMS ((int, union aux_ext *, unsigned int, int *, int, char *));
+
+static struct symbol *
+mylookup_symbol PARAMS ((char *, struct block *, namespace_enum,
+ 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 *, struct section_offsets *));
+
+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 void
+handle_psymbol_enumerators PARAMS ((struct objfile *, FDR *, int, CORE_ADDR));
+
+static char *
+mdebug_next_symbol_text PARAMS ((struct objfile *));
+
+/* Address bounds for the signal trampoline in inferior, if any */
+
+CORE_ADDR sigtramp_address, sigtramp_end;
+
+/* 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
+mdebug_psymtab_to_symtab (pst)
+ struct partial_symtab *pst;
+{
+
+ if (!pst)
+ return;
+
+ if (info_verbose)
+ {
+ printf_filtered ("Reading in symbols for %s...", pst->filename);
+ gdb_flush (gdb_stdout);
+ }
+
+ next_symbol_text_func = mdebug_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");
+}
+
+/* File-level interface functions */
+
+/* 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 = debug_info->fdr;
+ f = fdrs + cf;
+ /* Object files do not have the RFD table, all refs are absolute */
+ if (f->rfdBase == 0)
+ return fdrs + rf;
+ (*debug_swap->swap_rfd_in) (cur_bfd,
+ ((char *) debug_info->external_rfd
+ + ((f->rfdBase + rf)
+ * debug_swap->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 debug_info->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. */
+
+void
+mdebug_build_psymtabs (objfile, swap, info, section_offsets)
+ struct objfile *objfile;
+ const struct ecoff_debug_swap *swap;
+ struct ecoff_debug_info *info;
+ struct section_offsets *section_offsets;
+{
+ cur_bfd = objfile->obfd;
+ debug_swap = swap;
+ debug_info = info;
+
+ /* Make sure all the FDR information is swapped in. */
+ if (info->fdr == (FDR *) NULL)
+ {
+ char *fdr_src;
+ char *fdr_end;
+ FDR *fdr_ptr;
+
+ info->fdr = (FDR *) obstack_alloc (&objfile->psymbol_obstack,
+ (info->symbolic_header.ifdMax
+ * sizeof (FDR)));
+ fdr_src = info->external_fdr;
+ fdr_end = (fdr_src
+ + info->symbolic_header.ifdMax * swap->external_fdr_size);
+ fdr_ptr = info->fdr;
+ for (; fdr_src < fdr_end; fdr_src += swap->external_fdr_size, fdr_ptr++)
+ (*swap->swap_fdr_in) (objfile->obfd, fdr_src, fdr_ptr);
+ }
+
+ 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_unfiltered ("\n%s not compiled with -g, debugging support is limited.\n",
+ objfile->name);
+ printf_unfiltered ("You should compile with -g2 or -g3 for best debugging support.\n");
+ gdb_flush (gdb_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. */
+
+ /* What are we parsing. stFile, or stBlock are for files and
+ blocks. stProc or stStaticProc means we have seen the start of a
+ procedure, but not the start of the block within in. When we see
+ the start of that block, we change it to stNil, without pushing a
+ new block, i.e. stNil means both a procedure and a block. */
+
+ int blocktype;
+
+ 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 mdebug_pending
+{
+ struct mdebug_pending *next; /* link */
+ char *s; /* the unswapped symbol */
+ struct type *t; /* its partial type descriptor */
+};
+
+
+/* The pending information is kept for an entire object file, and used
+ to be in the sym_private field. I took it out when I split
+ mdebugread from mipsread, because this might not be the only type
+ of symbols read from an object file. Instead, we allocate the
+ pending information table when we create the partial symbols, and
+ we store a pointer to the single table in each psymtab. */
+
+static struct mdebug_pending **pending_list;
+
+/* Check whether we already saw symbol SH in file FH */
+
+static struct mdebug_pending *
+is_pending_symbol (fh, sh)
+ FDR *fh;
+ char *sh;
+{
+ int f_idx = fh - debug_info->fdr;
+ register struct mdebug_pending *p;
+
+ /* Linear search is ok, list is typically no more than 10 deep */
+ for (p = pending_list[f_idx]; p; p = p->next)
+ if (p->s == sh)
+ break;
+ return p;
+}
+
+/* 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 - debug_info->fdr;
+ struct mdebug_pending *p = is_pending_symbol (fh, sh);
+
+ /* Make sure we do not make duplicates */
+ if (!p)
+ {
+ p = ((struct mdebug_pending *)
+ obstack_alloc (&current_objfile->psymbol_obstack,
+ sizeof (struct mdebug_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, section_offsets)
+ SYMR *sh;
+ union aux_ext *ax;
+ char *ext_sh;
+ int bigend;
+ struct section_offsets *section_offsets;
+{
+ const bfd_size_type external_sym_size = debug_swap->external_sym_size;
+ void (* const swap_sym_in) PARAMS ((bfd *, PTR, SYMR *)) =
+ debug_swap->swap_sym_in;
+ char *name;
+ struct symbol *s;
+ struct block *b;
+ struct mdebug_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 = debug_info->ssext + sh->iss;
+ else
+ name = debug_info->ss + cur_fdr->issBase + sh->iss;
+
+ switch (sh->sc)
+ {
+ case scText:
+ case scRConst:
+ /* Do not relocate relative values.
+ The value of a stEnd symbol is the displacement from the
+ corresponding start symbol value.
+ The value of a stBlock symbol is the displacement from the
+ procedure address. */
+ if (sh->st != stEnd && sh->st != stBlock)
+ sh->value += ANOFFSET (section_offsets, SECT_OFF_TEXT);
+ break;
+ case scData:
+ case scSData:
+ case scRData:
+ case scPData:
+ case scXData:
+ sh->value += ANOFFSET (section_offsets, SECT_OFF_DATA);
+ break;
+ case scBss:
+ case scSBss:
+ sh->value += ANOFFSET (section_offsets, SECT_OFF_BSS);
+ break;
+ }
+
+ 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 (SC_IS_COMMON(sh->sc))
+ {
+ /* 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 if file is compiled without debugging info. */
+ if (SC_IS_UNDEF(sh->sc)
+ || sh->sc == scNil || sh->index == indexNil)
+ SYMBOL_TYPE (s) = nodebug_var_symbol_type;
+ 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++;
+ found_ecoff_debugging_info = 1;
+ top_stack->numargs++;
+
+ /* Special GNU C++ name. */
+ if (is_cplus_marker (name[0]) && 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);
+ 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) = mdebug_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 (SC_IS_UNDEF(sh->sc) || sh->sc == scNil)
+ t = mdebug_type_int;
+ else
+ {
+ t = parse_type (cur_fd, ax, sh->index + 1, 0, bigend, name);
+ if (STREQ(name, "malloc") && t->code == TYPE_CODE_VOID)
+ {
+ /* I don't know why, but, at least under Alpha GNU/Linux,
+ when linking against a malloc without debugging
+ symbols, its read as a function returning void---this
+ is bad because it means we cannot call functions with
+ string arguments interactively; i.e., "call
+ printf("howdy\n")" would fail with the error message
+ "program has no memory available". To avoid this, we
+ patch up the type and make it void*
+ instead. (davidm@azstarnet.com)
+ */
+ t = make_pointer_type (t, NULL);
+ }
+ }
+ 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);
+ /* Irix 5 sometimes has duplicate names for the same
+ function. We want to add such names up at the global
+ level, not as a nested function. */
+ else if (sh->value == top_stack->procadr)
+ b = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
+ }
+ add_symbol (s, b);
+
+ /* Make a type for the procedure itself */
+ SYMBOL_TYPE (s) = lookup_function_type (t);
+
+ /* Create and enter a new lexical context */
+ b = new_block (top_stack->maxsyms);
+ SYMBOL_BLOCK_VALUE (s) = b;
+ BLOCK_FUNCTION (b) = s;
+ BLOCK_START (b) = BLOCK_END (b) = sh->value;
+ BLOCK_SUPERBLOCK (b) = top_stack->cur_block;
+ add_block (b, top_stack->cur_st);
+
+ /* Not if we only have partial info */
+ if (SC_IS_UNDEF(sh->sc) || 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 && !SC_IS_COMMON(sh->sc))
+ 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:
+ found_ecoff_debugging_info = 1;
+ 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.
+ Alpha cc -migrate enums are recognized by a zero
+ index and a zero symbol value.
+ DU 4.0 cc enums are recognized by a member type of
+ btEnum without qualifiers and a zero symbol value. */
+ if (tsym.index == indexNil
+ || (tsym.index == 0 && sh->value == 0))
+ type_code = TYPE_CODE_ENUM;
+ else
+ {
+ (*debug_swap->swap_tir_in) (bigend,
+ &ax[tsym.index].a_ti,
+ &tir);
+ if ((tir.bt == btNil || tir.bt == btVoid
+ || (tir.bt == btEnum && sh->value == 0))
+ && 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 *) debug_info->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;
+
+ case stIndirect:
+ /* Irix5 cc puts out a stIndirect 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 mdebug_pending *) NULL)
+ {
+ t = new_type (NULL);
+ add_pending (cur_fdr, ext_sh, t);
+ }
+ else
+ t = pend->t;
+
+ /* Do not set the tag name if it is a compiler generated tag name
+ (.Fxx or .xxfake or empty) for unnamed struct/union/enums.
+ Alpha cc puts out an sh->iss of zero for those. */
+ if (sh->iss == 0 || name[0] == '.' || name[0] == '\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)
+ {
+ int unsigned_enum = 1;
+
+ /* This is a non-empty enum. */
+
+ /* DEC c89 has the number of enumerators in the sh.value field,
+ not the type length, so we have to compensate for that
+ incompatibility quirk.
+ This might do the wrong thing for an enum with one or two
+ enumerators and gcc -gcoff -fshort-enums, but these cases
+ are hopefully rare enough.
+ Alpha cc -migrate has a sh.value field of zero, we adjust
+ that too. */
+ if (TYPE_LENGTH (t) == TYPE_NFIELDS (t)
+ || TYPE_LENGTH (t) == 0)
+ TYPE_LENGTH (t) = TARGET_INT_BIT / HOST_CHAR_BIT;
+ 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;
+
+ FIELD_BITPOS (*f) = tsym.value;
+ FIELD_TYPE (*f) = t;
+ FIELD_NAME (*f) = debug_info->ss + cur_fdr->issBase + tsym.iss;
+ FIELD_BITSIZE (*f) = 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) =
+ obsavestring (f->name, strlen (f->name),
+ &current_objfile->symbol_obstack);
+ SYMBOL_CLASS (enum_sym) = LOC_CONST;
+ SYMBOL_TYPE (enum_sym) = t;
+ SYMBOL_NAMESPACE (enum_sym) = VAR_NAMESPACE;
+ SYMBOL_VALUE (enum_sym) = tsym.value;
+ if (SYMBOL_VALUE (enum_sym) < 0)
+ unsigned_enum = 0;
+ add_symbol (enum_sym, top_stack->cur_block);
+
+ /* Skip the stMembers that we've handled. */
+ count++;
+ f++;
+ }
+ if (unsigned_enum)
+ TYPE_FLAGS (t) |= TYPE_FLAG_UNSIGNED;
+ }
+ /* 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;
+
+ /* gcc puts out an empty struct for an opaque struct definitions,
+ do not create a symbol for it either. */
+ if (TYPE_NFIELDS (t) == 0)
+ {
+ TYPE_FLAGS (t) |= TYPE_FLAG_STUB;
+ break;
+ }
+
+ s = new_symbol (name);
+ SYMBOL_NAMESPACE (s) = STRUCT_NAMESPACE;
+ SYMBOL_CLASS (s) = LOC_TYPEDEF;
+ SYMBOL_VALUE (s) = 0;
+ SYMBOL_TYPE (s) = t;
+ 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:
+ found_ecoff_debugging_info = 1;
+ /* beginnning of (code) block. Value of symbol
+ is the displacement from procedure start */
+ push_parse_stack ();
+
+ /* Do not start a new block if this is the outermost block of a
+ procedure. This allows the LOC_BLOCK symbol to point to the
+ block with the local variables, so funcname::var works. */
+ if (top_stack->blocktype == stProc
+ || top_stack->blocktype == stStaticProc)
+ {
+ top_stack->blocktype = stNil;
+ break;
+ }
+
+ 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 || SC_IS_COMMON(sh->sc))
+ {
+ /* 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;
+ struct type *ftype = top_stack->cur_type;
+ 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) = mdebug_type_void;
+ e = ((struct mips_extra_func_info *)
+ obstack_alloc (&current_objfile->symbol_obstack,
+ sizeof (struct mips_extra_func_info)));
+ memset ((PTR) e, 0, sizeof (struct mips_extra_func_info));
+ SYMBOL_VALUE (s) = (long) e;
+ e->numargs = top_stack->numargs;
+ e->pdr.framereg = -1;
+ 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);
+ }
+ }
+
+ if (TYPE_NFIELDS (ftype) <= 0)
+ {
+ /* No parameter type information is recorded with the function's
+ type. Set that from the type of the parameter symbols. */
+ int nparams = top_stack->numargs;
+ int iparams;
+ struct symbol *sym;
+
+ if (nparams > 0)
+ {
+ TYPE_NFIELDS (ftype) = nparams;
+ TYPE_FIELDS (ftype) = (struct field *)
+ TYPE_ALLOC (ftype, nparams * sizeof (struct field));
+
+ for (i = iparams = 0; iparams < nparams; i++)
+ {
+ sym = BLOCK_SYM (b, i);
+ switch (SYMBOL_CLASS (sym))
+ {
+ case LOC_ARG:
+ case LOC_REF_ARG:
+ case LOC_REGPARM:
+ case LOC_REGPARM_ADDR:
+ TYPE_FIELD_TYPE (ftype, iparams) = SYMBOL_TYPE (sym);
+ iparams++;
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ }
+ }
+ 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 == stNil)
+ {
+ /* End of outermost block. Pop parse stack and ignore. The
+ following stEnd of stProc will take care of the block. */
+ ;
+ }
+ 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++];
+ FIELD_NAME (*f) = name;
+ FIELD_BITPOS (*f) = sh->value;
+ bitsize = 0;
+ FIELD_TYPE (*f) = parse_type (cur_fd, ax, sh->index, &bitsize, bigend, name);
+ FIELD_BITSIZE (*f) = bitsize;
+ break;
+
+ case stIndirect: /* forward declaration on Irix5 */
+ /* Forward declarations from Irix5 cc are handled by cross_ref,
+ skip them. */
+ break;
+
+ case stTypedef: /* type definition */
+ found_ecoff_debugging_info = 1;
+
+ /* 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 mdebug_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 and Irix5 cc. */
+
+ /* However if the typedef cross references to an opaque aggregate, it
+ is safe to omit it from the symbol table. */
+
+ if (has_opaque_xref (cur_fdr, sh))
+ break;
+ 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_mdebug_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[] =
+ {
+ &mdebug_type_void, /* btNil */
+ &mdebug_type_adr_32, /* btAdr */
+ &mdebug_type_char, /* btChar */
+ &mdebug_type_unsigned_char, /* btUChar */
+ &mdebug_type_short, /* btShort */
+ &mdebug_type_unsigned_short, /* btUShort */
+ &mdebug_type_int_32, /* btInt */
+ &mdebug_type_unsigned_int_32, /* btUInt */
+ &mdebug_type_long_32, /* btLong */
+ &mdebug_type_unsigned_long_32, /* btULong */
+ &mdebug_type_float, /* btFloat */
+ &mdebug_type_double, /* btDouble */
+ 0, /* btStruct */
+ 0, /* btUnion */
+ 0, /* btEnum */
+ 0, /* btTypedef */
+ 0, /* btRange */
+ 0, /* btSet */
+ &mdebug_type_complex, /* btComplex */
+ &mdebug_type_double_complex, /* btDComplex */
+ 0, /* btIndirect */
+ &mdebug_type_fixed_dec, /* btFixedDec */
+ &mdebug_type_float_dec, /* btFloatDec */
+ &mdebug_type_string, /* btString */
+ 0, /* btBit */
+ 0, /* btPicture */
+ &mdebug_type_void, /* btVoid */
+ 0, /* DEC C++: Pointer to member */
+ 0, /* DEC C++: Virtual function table */
+ 0, /* DEC C++: Class (Record) */
+ &mdebug_type_long_64, /* btLong64 */
+ &mdebug_type_unsigned_long_64, /* btULong64 */
+ &mdebug_type_long_long_64, /* btLongLong64 */
+ &mdebug_type_unsigned_long_long_64, /* btULongLong64 */
+ &mdebug_type_adr_64, /* btAdr64 */
+ &mdebug_type_int_64, /* btInt64 */
+ &mdebug_type_unsigned_int_64, /* btUInt64 */
+ };
+
+ TIR t[1];
+ struct type *tp = 0;
+ enum type_code type_code = TYPE_CODE_UNDEF;
+
+ /* Handle undefined types, they have indexNil. */
+ if (aux_index == indexNil)
+ return mdebug_type_int;
+
+ /* Handle corrupt aux indices. */
+ if (aux_index >= (debug_info->fdr + fd)->caux)
+ {
+ complain (&index_complaint, sym_name);
+ return mdebug_type_int;
+ }
+ ax += aux_index;
+
+ /* Use aux as a type information record, map its basic type. */
+ (*debug_swap->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 mdebug_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 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 btIndirect:
+ /* alpha cc -migrate uses this for typedefs. The true type will
+ be obtained by crossreferencing below. */
+ type_code = TYPE_CODE_ERROR;
+ 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 mdebug_type_int;
+ }
+ }
+
+ /* Move on to next aux */
+ ax++;
+
+ if (t->fBitfield)
+ {
+ int width = AUX_GET_WIDTH (bigend, ax);
+
+ /* Inhibit core dumps with some cfront generated objects that
+ corrupt the TIR. */
+ if (bs == (int *)NULL)
+ {
+ /* Alpha cc -migrate encodes char and unsigned char types
+ as short and unsigned short types with a field width of 8.
+ Enum types also have a field width which we ignore for now. */
+ if (t->bt == btShort && width == 8)
+ tp = mdebug_type_char;
+ else if (t->bt == btUShort && width == 8)
+ tp = mdebug_type_unsigned_char;
+ else if (t->bt == btEnum)
+ ;
+ else
+ complain (&bad_fbitfield_complaint, sym_name);
+ }
+ else
+ *bs = width;
+ ax++;
+ }
+
+ /* A btIndirect entry cross references to an aux entry containing
+ the type. */
+ if (t->bt == btIndirect)
+ {
+ RNDXR rn[1];
+ int rf;
+ FDR *xref_fh;
+ int xref_fd;
+
+ (*debug_swap->swap_rndx_in) (bigend, &ax->a_rndx, rn);
+ ax++;
+ if (rn->rfd == 0xfff)
+ {
+ rf = AUX_GET_ISYM (bigend, ax);
+ ax++;
+ }
+ else
+ rf = rn->rfd;
+
+ if (rf == -1)
+ {
+ complain (&bad_indirect_xref_complaint, sym_name);
+ return mdebug_type_int;
+ }
+ xref_fh = get_rfd (fd, rf);
+ xref_fd = xref_fh - debug_info->fdr;
+ tp = parse_type (xref_fd, debug_info->external_aux + xref_fh->iauxBase,
+ rn->index, (int *) NULL, xref_fh->fBigendian, sym_name);
+ }
+
+ /* 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);
+
+ /* DEC c89 produces cross references to qualified aggregate types,
+ dereference them. */
+ while (TYPE_CODE (tp) == TYPE_CODE_PTR
+ || TYPE_CODE (tp) == TYPE_CODE_ARRAY)
+ tp = tp->target_type;
+
+ /* 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: We are not doing any guessing on range types. */
+ if (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 = mdebug_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;
+
+ (*debug_swap->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) */
+ (*debug_swap->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 (fh - debug_info->fdr,
+ debug_info->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 = mdebug_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. */
+
+ /* TYPE_FLAG_TARGET_STUB now takes care of the zero TYPE_LENGTH
+ problem. */
+ if (TYPE_LENGTH (*tpp) == 0)
+ {
+ TYPE_FLAGS (t) |= TYPE_FLAG_TARGET_STUB;
+ }
+
+ *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 *,
+ struct partial_symtab *));
+
+static void
+parse_procedure (pr, search_symtab, pst)
+ PDR *pr;
+ struct symtab *search_symtab;
+ struct partial_symtab *pst;
+{
+ 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. */
+ /* FIXME-32x64. assuming pr->adr fits in long. */
+ complain (&pdr_static_symbol_complaint, (unsigned long) pr->adr);
+ return;
+ }
+ else
+ {
+ /* external */
+ EXTR she;
+
+ (*debug_swap->swap_ext_in) (cur_bfd,
+ ((char *) debug_info->external_ext
+ + (pr->isym
+ * debug_swap->external_ext_size)),
+ &she);
+ sh_name = debug_info->ssext + she.asym.iss;
+ }
+ }
+ else
+ {
+ /* Full symbols */
+ SYMR sh;
+
+ (*debug_swap->swap_sym_in) (cur_bfd,
+ ((char *) debug_info->external_sym
+ + ((cur_fdr->isymBase + pr->isym)
+ * debug_swap->external_sym_size)),
+ &sh);
+ sh_name = debug_info->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 (mdebug_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;
+
+ /* GDB expects the absolute function start address for the
+ procedure descriptor in e->pdr.adr.
+ As the address in the procedure descriptor is usually relative,
+ we would have to relocate e->pdr.adr with cur_fdr->adr and
+ ANOFFSET (pst->section_offsets, SECT_OFF_TEXT).
+ Unfortunately cur_fdr->adr and e->pdr.adr are both absolute
+ in shared libraries on some systems, and on other systems
+ e->pdr.adr is sometimes offset by a bogus value.
+ To work around these problems, we replace e->pdr.adr with
+ the start address of the function. */
+ e->pdr.adr = BLOCK_START (b);
+
+ /* 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;
+ }
+ }
+
+ /* It would be reasonable that functions that have been compiled
+ without debugging info have a btNil type for their return value,
+ and functions that are void and are compiled with debugging info
+ have btVoid.
+ gcc and DEC f77 put out btNil types for both cases, so btNil is mapped
+ to TYPE_CODE_VOID in parse_type to get the `compiled with debugging info'
+ case right.
+ The glevel field in cur_fdr could be used to determine the presence
+ of debugging info, but GCC doesn't always pass the -g switch settings
+ to the assembler and GAS doesn't set the glevel field from the -g switch
+ settings.
+ To work around these problems, the return value type of a TYPE_CODE_VOID
+ function is adjusted accordingly if no debugging info was found in the
+ compilation unit. */
+
+ if (processing_gcc_compilation == 0
+ && found_ecoff_debugging_info == 0
+ && TYPE_CODE (TYPE_TARGET_TYPE (SYMBOL_TYPE (s))) == TYPE_CODE_VOID)
+ SYMBOL_TYPE (s) = nodebug_func_symbol_type;
+}
+
+/* Relocate the extra function info pointed to by the symbol table. */
+
+void
+ecoff_relocate_efi (sym, delta)
+ struct symbol *sym;
+ CORE_ADDR delta;
+{
+ struct mips_extra_func_info *e;
+
+ e = (struct mips_extra_func_info *) SYMBOL_VALUE (sym);
+
+ e->pdr.adr += delta;
+}
+
+/* Parse the external symbol ES. Just call parse_symbol() after
+ making sure we know where the aux are for it.
+ 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 PARAMS ((EXTR *, int, struct section_offsets *));
+
+static void
+parse_external (es, bigend, section_offsets)
+ EXTR *es;
+ int bigend;
+ struct section_offsets *section_offsets;
+{
+ union aux_ext *ax;
+
+ if (es->ifd != ifdNil)
+ {
+ cur_fd = es->ifd;
+ cur_fdr = debug_info->fdr + cur_fd;
+ ax = debug_info->external_aux + cur_fdr->iauxBase;
+ }
+ else
+ {
+ cur_fdr = debug_info->fdr;
+ ax = 0;
+ }
+
+ /* Reading .o files */
+ if (SC_IS_UNDEF(es->asym.sc) || 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, debug_info->ssext + es->asym.iss,
+ fdr_name (cur_fdr));
+ return;
+ }
+
+ switch (es->asym.st)
+ {
+ case stProc:
+ case stStaticProc:
+ /* There is no need to parse the external procedure symbols.
+ If they are from objects compiled without -g, their index will
+ be indexNil, and the symbol definition from the minimal symbol
+ is preferrable (yielding a function returning int instead of int).
+ If the index points to a local procedure symbol, the local
+ symbol already provides the correct type.
+ Note that the index of the external procedure symbol points
+ to the local procedure symbol in the local symbol table, and
+ _not_ to the auxiliary symbol info. */
+ break;
+ case stGlobal:
+ case stLabel:
+ /* Global common symbols are resolved by the runtime loader,
+ ignore them. */
+ if (SC_IS_COMMON(es->asym.sc))
+ break;
+
+ /* Note that the case of a symbol with indexNil must be handled
+ anyways by parse_symbol(). */
+ parse_symbol (&es->asym, ax, (char *) NULL, bigend, section_offsets);
+ 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 PARAMS ((FDR *, PDR *, struct linetable *, int,
+ struct partial_symtab *, CORE_ADDR));
+
+static void
+parse_lines (fh, pr, lt, maxlines, pst, lowest_pdr_addr)
+ FDR *fh;
+ PDR *pr;
+ struct linetable *lt;
+ int maxlines;
+ struct partial_symtab *pst;
+ CORE_ADDR lowest_pdr_addr;
+{
+ unsigned char *base;
+ int j, k;
+ int delta, count, lineno = 0;
+
+ if (fh->cbLine == 0)
+ return;
+
+ /* Scan by procedure descriptors */
+ k = 0;
+ for (j = 0; j < fh->cpd; j++, pr++)
+ {
+ CORE_ADDR l;
+ CORE_ADDR 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 = debug_info->line + fh->cbLineOffset;
+ if (j != (fh->cpd - 1))
+ halt = base + pr[1].cbLineOffset;
+ else
+ halt = base + fh->cbLine;
+ base += pr->cbLineOffset;
+
+ adr = pst->textlow + pr->adr - lowest_pdr_addr;
+
+ 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 bfd_size_type external_sym_size = debug_swap->external_sym_size;
+ const bfd_size_type external_rfd_size = debug_swap->external_rfd_size;
+ const bfd_size_type external_ext_size = debug_swap->external_ext_size;
+ void (* const swap_ext_in) PARAMS ((bfd *, PTR, EXTR *))
+ = debug_swap->swap_ext_in;
+ void (* const swap_sym_in) PARAMS ((bfd *, PTR, SYMR *))
+ = debug_swap->swap_sym_in;
+ void (* const swap_rfd_in) PARAMS ((bfd *, PTR, RFDT *))
+ = debug_swap->swap_rfd_in;
+ int f_idx, s_idx;
+ HDRR *hdr = &debug_info->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 textlow_not_set = 1;
+ 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;
+ asection *text_sect;
+ int relocatable = 0;
+
+ /* Irix 5.2 shared libraries have a fh->adr field of zero, but
+ the shared libraries are prelinked at a high memory address.
+ We have to adjust the start address of the object file for this case,
+ by setting it to the start address of the first procedure in the file.
+ But we should do no adjustments if we are debugging a .o file, where
+ the text section (and fh->adr) really starts at zero. */
+ text_sect = bfd_get_section_by_name (cur_bfd, ".text");
+ if (text_sect != NULL
+ && (bfd_get_section_flags (cur_bfd, text_sect) & SEC_RELOC))
+ relocatable = 1;
+
+ 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 = mdebug_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, section_offsets);
+ fdr_to_pst[-1].pst = pst;
+ FDR_IDX (pst) = -1;
+ }
+
+ /* Allocate the global pending list. */
+ pending_list =
+ ((struct mdebug_pending **)
+ obstack_alloc (&objfile->psymbol_obstack,
+ hdr->ifdMax * sizeof (struct mdebug_pending *)));
+ memset ((PTR) pending_list, 0,
+ hdr->ifdMax * sizeof (struct mdebug_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 *) debug_info->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++)
+ {
+ /* See calls to complain below. */
+ if (ext_in->ifd >= -1
+ && ext_in->ifd < hdr->ifdMax
+ && ext_in->asym.iss >= 0
+ && ext_in->asym.iss < hdr->issExtMax)
+ 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;
+ }
+
+ /* ECOFF in ELF:
+
+ For ECOFF in ELF, we skip the creation of the minimal symbols.
+ The ECOFF symbols should be a subset of the Elf symbols, and the
+ section information of the elf symbols will be more accurate.
+ FIXME! What about Irix 5's native linker?
+
+ By default, Elf sections which don't exist in ECOFF
+ get put in ECOFF's absolute section by the gnu linker.
+ Since absolute sections don't get relocated, we
+ end up calculating an address different from that of
+ the symbol's minimal symbol (created earlier from the
+ Elf symtab).
+
+ To fix this, either :
+ 1) don't create the duplicate symbol
+ (assumes ECOFF symtab is a subset of the ELF symtab;
+ assumes no side-effects result from ignoring ECOFF symbol)
+ 2) create it, only if lookup for existing symbol in ELF's minimal
+ symbols fails
+ (inefficient;
+ assumes no side-effects result from ignoring ECOFF symbol)
+ 3) create it, but lookup ELF's minimal symbol and use it's section
+ during relocation, then modify "uniqify" phase to merge and
+ eliminate the duplicate symbol
+ (highly inefficient)
+
+ I've implemented #1 here...
+ Skip the creation of the minimal symbols based on the ECOFF
+ symbol table. */
+
+ /* 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;
+ CORE_ADDR svalue = ext_in->asym.value;
+
+ /* The Irix 5 native tools seem to sometimes generate bogus
+ external symbols. */
+ if (ext_in->ifd < -1 || ext_in->ifd >= hdr->ifdMax)
+ {
+ complain (&bad_ext_ifd_complaint, ext_in->ifd, hdr->ifdMax);
+ continue;
+ }
+ if (ext_in->asym.iss < 0 || ext_in->asym.iss >= hdr->issExtMax)
+ {
+ complain (&bad_ext_iss_complaint, ext_in->asym.iss,
+ hdr->issExtMax);
+ continue;
+ }
+
+ extern_tab[fdr_to_pst[ext_in->ifd].globals_offset
+ + fdr_to_pst[ext_in->ifd].n_globals++] = *ext_in;
+
+
+ if (SC_IS_UNDEF(ext_in->asym.sc) || ext_in->asym.sc == scNil)
+ continue;
+
+
+ /* Pass 3 over files, over local syms: fill in static symbols */
+ name = debug_info->ssext + ext_in->asym.iss;
+
+ /* Process ECOFF Symbol Types and Storage Classes */
+ switch (ext_in->asym.st)
+ {
+ case stProc:
+ /* Beginnning of Procedure */
+ svalue += ANOFFSET (section_offsets, SECT_OFF_TEXT);
+ break;
+ case stStaticProc:
+ /* Load time only static procs */
+ ms_type = mst_file_text;
+ svalue += ANOFFSET (section_offsets, SECT_OFF_TEXT);
+ break;
+ case stGlobal:
+ /* External symbol */
+ if (SC_IS_COMMON (ext_in->asym.sc))
+ {
+ /* The value of a common symbol is its size, not its address.
+ Ignore it. */
+ continue;
+ }
+ else if (SC_IS_DATA (ext_in->asym.sc))
+ {
+ ms_type = mst_data;
+ svalue += ANOFFSET (section_offsets, SECT_OFF_DATA);
+ }
+ else if (SC_IS_BSS (ext_in->asym.sc))
+ {
+ ms_type = mst_bss;
+ svalue += ANOFFSET (section_offsets, SECT_OFF_BSS);
+ }
+ else
+ ms_type = mst_abs;
+ break;
+ case stLabel:
+ /* Label */
+ if (SC_IS_TEXT (ext_in->asym.sc))
+ {
+ ms_type = mst_file_text;
+ svalue += ANOFFSET (section_offsets, SECT_OFF_TEXT);
+ }
+ else if (SC_IS_DATA (ext_in->asym.sc))
+ {
+ ms_type = mst_file_data;
+ svalue += ANOFFSET (section_offsets, SECT_OFF_DATA);
+ }
+ else if (SC_IS_BSS (ext_in->asym.sc))
+ {
+ ms_type = mst_file_bss;
+ svalue += ANOFFSET (section_offsets, SECT_OFF_BSS);
+ }
+ else
+ ms_type = mst_abs;
+ break;
+ case stLocal:
+ case stNil:
+ /* The alpha has the section start addresses in stLocal symbols
+ whose name starts with a `.'. Skip those but complain for all
+ other stLocal symbols.
+ Irix6 puts the section start addresses in stNil symbols, skip
+ those too.*/
+ if (name[0] == '.')
+ continue;
+ /* Fall through. */
+ default:
+ ms_type = mst_unknown;
+ complain (&unknown_ext_complaint, name);
+ }
+ if (!ECOFF_IN_ELF(cur_bfd))
+ prim_record_minimal_symbol (name, svalue, ms_type, objfile);
+ }
+
+ /* 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;
+ CORE_ADDR textlow;
+
+ cur_fdr = fh = debug_info->fdr + f_idx;
+
+ if (fh->csym == 0)
+ {
+ fdr_to_pst[f_idx].pst = NULL;
+ continue;
+ }
+
+ /* Determine the start address for this object file from the
+ file header and relocate it, except for Irix 5.2 zero fh->adr. */
+ if (fh->cpd)
+ {
+ textlow = fh->adr;
+ if (relocatable || textlow != 0)
+ textlow += ANOFFSET (section_offsets, SECT_OFF_TEXT);
+ }
+ else
+ textlow = 0;
+ pst = start_psymtab_common (objfile, section_offsets,
+ fdr_name (fh),
+ textlow,
+ 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;
+ DEBUG_SWAP (pst) = debug_swap;
+ DEBUG_INFO (pst) = debug_info;
+ PENDING_LIST (pst) = pending_list;
+
+ /* The way to turn this into a symtab is to call... */
+ pst->read_symtab = mdebug_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 *) debug_info->external_sym
+ + (fh->isymBase + 1) * external_sym_size),
+ &sh);
+ if (STREQ (debug_info->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 *) debug_info->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)
+ {
+ CORE_ADDR procaddr;
+ long isym;
+
+ sh.value += ANOFFSET (section_offsets, SECT_OFF_TEXT);
+ if (sh.st == stStaticProc)
+ {
+ namestring = debug_info->ss + fh->issBase + sh.iss;
+ prim_record_minimal_symbol_and_info (namestring,
+ sh.value,
+ mst_file_text,
+ NULL,
+ SECT_OFF_TEXT,
+ NULL,
+ objfile);
+ }
+ procaddr = sh.value;
+
+ isym = AUX_GET_ISYM (fh->fBigendian,
+ (debug_info->external_aux
+ + fh->iauxBase
+ + sh.index));
+ (*swap_sym_in) (cur_bfd,
+ ((char *) debug_info->external_sym
+ + ((fh->isymBase + isym - 1)
+ * external_sym_size)),
+ &sh);
+ if (sh.st == stEnd)
+ {
+ CORE_ADDR high = procaddr + sh.value;
+
+ /* Kludge for Irix 5.2 zero fh->adr. */
+ if (!relocatable
+ && (pst->textlow == 0 || procaddr < pst->textlow))
+ pst->textlow = procaddr;
+ if (high > pst->texthigh)
+ pst->texthigh = high;
+ }
+ }
+ else if (sh.st == stStatic)
+ {
+ switch (sh.sc)
+ {
+ case scUndefined:
+ case scSUndefined:
+ case scNil:
+ case scAbs:
+ break;
+
+ case scData:
+ case scSData:
+ case scRData:
+ case scPData:
+ case scXData:
+ namestring = debug_info->ss + fh->issBase + sh.iss;
+ sh.value += ANOFFSET (section_offsets, SECT_OFF_DATA);
+ prim_record_minimal_symbol_and_info (namestring,
+ sh.value,
+ mst_file_data,
+ NULL,
+ SECT_OFF_DATA,
+ NULL,
+ objfile);
+ break;
+
+ default:
+ /* FIXME! Shouldn't this use cases for bss,
+ then have the default be abs? */
+ namestring = debug_info->ss + fh->issBase + sh.iss;
+ sh.value += ANOFFSET (section_offsets, SECT_OFF_BSS);
+ prim_record_minimal_symbol_and_info (namestring,
+ sh.value,
+ mst_file_bss,
+ NULL,
+ SECT_OFF_BSS,
+ NULL,
+ objfile);
+ break;
+ }
+ }
+ continue;
+ }
+ /* Handle stabs continuation */
+ {
+ char *stabstring = debug_info->ss + fh->issBase + sh.iss;
+ int len = strlen (stabstring);
+ while (stabstring[len-1] == '\\')
+ {
+ SYMR sh2;
+ char *stabstring1 = stabstring;
+ char *stabstring2;
+ int len2;
+
+ /* Ignore continuation char from 1st string */
+ len--;
+
+ /* Read next stabstring */
+ cur_sdx++;
+ (*swap_sym_in) (cur_bfd,
+ (((char *) debug_info->external_sym)
+ + (fh->isymBase + cur_sdx)
+ * external_sym_size),
+ &sh2);
+ stabstring2 = debug_info->ss + fh->issBase + sh2.iss;
+ len2 = strlen (stabstring2);
+
+ /* Concatinate stabstring2 with stabstring1 */
+ if (stabstring
+ && stabstring != debug_info->ss + fh->issBase + sh.iss)
+ stabstring = xrealloc (stabstring, len + len2 + 1);
+ else
+ stabstring = xmalloc (len + len2 + 1);
+ strcpy (stabstring, stabstring1);
+ strcpy (stabstring + len, stabstring2);
+ len += len2;
+ }
+
+#define SET_NAMESTRING() \
+ namestring = stabstring
+#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,textlow_not_set) (void)0
+#define HANDLE_RBRAC(val) \
+ if ((val) > save_pst->texthigh) save_pst->texthigh = (val);
+#include "partial-stab.h"
+
+ if (stabstring
+ && stabstring != debug_info->ss + fh->issBase + sh.iss)
+ free (stabstring);
+ }
+ /* end - Handle continuation */
+ }
+ }
+ else
+ {
+ for (cur_sdx = 0; cur_sdx < fh->csym;)
+ {
+ char *name;
+ enum address_class class;
+
+ (*swap_sym_in) (cur_bfd,
+ ((char *) debug_info->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 (SC_IS_UNDEF(sh.sc) || sh.sc == scNil
+ || (sh.index == indexNil
+ && (sh.st != stStatic || sh.sc == scAbs)))
+ {
+ /* FIXME, premature? */
+ cur_sdx++;
+ continue;
+ }
+
+ name = debug_info->ss + fh->issBase + sh.iss;
+
+ switch (sh.sc)
+ {
+ case scText:
+ case scRConst:
+ /* The value of a stEnd symbol is the displacement from the
+ corresponding start symbol value, do not relocate it. */
+ if (sh.st != stEnd)
+ sh.value += ANOFFSET (section_offsets, SECT_OFF_TEXT);
+ break;
+ case scData:
+ case scSData:
+ case scRData:
+ case scPData:
+ case scXData:
+ sh.value += ANOFFSET (section_offsets, SECT_OFF_DATA);
+ break;
+ case scBss:
+ case scSBss:
+ sh.value += ANOFFSET (section_offsets, SECT_OFF_BSS);
+ break;
+ }
+
+ switch (sh.st)
+ {
+ CORE_ADDR high;
+ CORE_ADDR procaddr;
+ int new_sdx;
+
+ case stStaticProc:
+ prim_record_minimal_symbol_and_info (name, sh.value,
+ mst_file_text, NULL,
+ SECT_OFF_TEXT, NULL,
+ objfile);
+
+ /* FALLTHROUGH */
+
+ case stProc:
+ /* Usually there is a local and a global stProc symbol
+ for a function. This means that the function name
+ has already been entered into the mimimal symbol table
+ while processing the global symbols in pass 2 above.
+ One notable exception is the PROGRAM name from
+ f77 compiled executables, it is only put out as
+ local stProc symbol, and a global MAIN__ stProc symbol
+ points to it. It doesn't matter though, as gdb is
+ still able to find the PROGRAM name via the partial
+ symbol table, and the MAIN__ symbol via the minimal
+ symbol table. */
+ if (sh.st == stProc)
+ add_psymbol_to_list (name, strlen (name),
+ VAR_NAMESPACE, LOC_BLOCK,
+ &objfile->global_psymbols,
+ 0, sh.value, psymtab_language, objfile);
+ else
+ add_psymbol_to_list (name, strlen (name),
+ VAR_NAMESPACE, LOC_BLOCK,
+ &objfile->static_psymbols,
+ 0, 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,
+ (debug_info->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 *) debug_info->external_sym
+ + ((fh->isymBase + cur_sdx - 1)
+ * external_sym_size)),
+ &sh);
+ if (sh.st != stEnd)
+ continue;
+
+ /* Kludge for Irix 5.2 zero fh->adr. */
+ if (!relocatable
+ && (pst->textlow == 0 || procaddr < pst->textlow))
+ pst->textlow = procaddr;
+
+ high = procaddr + sh.value;
+ if (high > pst->texthigh)
+ pst->texthigh = high;
+ continue;
+
+ case stStatic: /* Variable */
+ if (SC_IS_DATA (sh.sc))
+ prim_record_minimal_symbol_and_info (name, sh.value,
+ mst_file_data, NULL,
+ SECT_OFF_DATA,
+ NULL,
+ objfile);
+ else
+ prim_record_minimal_symbol_and_info (name, sh.value,
+ mst_file_bss, NULL,
+ SECT_OFF_BSS,
+ NULL,
+ objfile);
+ class = LOC_STATIC;
+ break;
+
+ case stIndirect:/* Irix5 forward declaration */
+ /* Skip forward declarations from Irix5 cc */
+ goto skip;
+
+ case stTypedef:/* Typedef */
+ /* Skip typedefs for forward declarations and opaque
+ structs from alpha and mips cc. */
+ if (sh.iss == 0 || has_opaque_xref (fh, &sh))
+ goto skip;
+ class = LOC_TYPEDEF;
+ break;
+
+ case stConstant: /* Constant decl */
+ class = LOC_CONST;
+ break;
+
+ case stUnion:
+ case stStruct:
+ case stEnum:
+ case stBlock: /* { }, str, un, enum*/
+ /* Do not create a partial symbol for cc unnamed aggregates
+ and gcc empty aggregates. */
+ if ((sh.sc == scInfo
+ || SC_IS_COMMON(sh.sc))
+ && sh.iss != 0
+ && sh.index != cur_sdx + 2)
+ {
+ add_psymbol_to_list (name, strlen (name),
+ STRUCT_NAMESPACE, LOC_TYPEDEF,
+ &objfile->static_psymbols,
+ 0, (CORE_ADDR) 0,
+ psymtab_language, objfile);
+ }
+ handle_psymbol_enumerators (objfile, fh, sh.st, sh.value);
+
+ /* 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,
+ 0, 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;
+ CORE_ADDR svalue;
+
+ if (ext_ptr->ifd != f_idx)
+ abort ();
+ psh = &ext_ptr->asym;
+
+ /* Do not add undefined symbols to the partial symbol table. */
+ if (SC_IS_UNDEF(psh->sc) || psh->sc == scNil)
+ continue;
+
+ svalue = psh->value;
+ switch (psh->sc)
+ {
+ case scText:
+ case scRConst:
+ svalue += ANOFFSET (section_offsets, SECT_OFF_TEXT);
+ break;
+ case scData:
+ case scSData:
+ case scRData:
+ case scPData:
+ case scXData:
+ svalue += ANOFFSET (section_offsets, SECT_OFF_DATA);
+ break;
+ case scBss:
+ case scSBss:
+ svalue += ANOFFSET (section_offsets, SECT_OFF_BSS);
+ break;
+ }
+
+ switch (psh->st)
+ {
+ case stNil:
+ /* These are generated for static symbols in .o files,
+ ignore them. */
+ continue;
+ case stProc:
+ case stStaticProc:
+ /* External procedure symbols have been entered
+ into the minimal symbol table in pass 2 above.
+ Ignore them, as parse_external will ignore them too. */
+ continue;
+ case stLabel:
+ class = LOC_LABEL;
+ break;
+ default:
+ complain (&unknown_ext_complaint,
+ debug_info->ssext + psh->iss);
+ /* Fall through, pretend it's global. */
+ case stGlobal:
+ /* Global common symbols are resolved by the runtime loader,
+ ignore them. */
+ if (SC_IS_COMMON(psh->sc))
+ continue;
+
+ class = LOC_STATIC;
+ break;
+ }
+ name = debug_info->ssext + psh->iss;
+ add_psymbol_to_list (name, strlen (name),
+ VAR_NAMESPACE, class,
+ &objfile->global_psymbols,
+ 0, svalue,
+ 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, textlow_not_set);
+ includes_used = 0;
+ dependencies_used = 0;
+
+ 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;
+ }
+
+ /* The objfile has its functions reordered if this partial symbol
+ table overlaps any other partial symbol table.
+ We cannot assume a reordered objfile if a partial symbol table
+ is contained within another partial symbol table, as partial symbol
+ tables for include files with executable code are contained
+ within the partial symbol table for the including source file,
+ and we do not want to flag the objfile reordered for these cases.
+
+ This strategy works well for Irix-5.2 shared libraries, but we
+ might have to use a more elaborate (and slower) algorithm for
+ other cases. */
+ save_pst = fdr_to_pst[f_idx].pst;
+ if (save_pst != NULL
+ && save_pst->textlow != 0
+ && !(objfile->flags & OBJF_REORDERED))
+ {
+ ALL_OBJFILE_PSYMTABS (objfile, pst)
+ {
+ if (save_pst != pst
+ && save_pst->textlow >= pst->textlow
+ && save_pst->textlow < pst->texthigh
+ && save_pst->texthigh > pst->texthigh)
+ {
+ objfile->flags |= OBJF_REORDERED;
+ break;
+ }
+ }
+ }
+ }
+
+ /* Now scan the FDRs for dependencies */
+ for (f_idx = 0; f_idx < hdr->ifdMax; f_idx++)
+ {
+ fh = f_idx + debug_info->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 *) debug_info->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;
+ }
+ }
+
+ /* Remove the dummy psymtab created for -O3 images above, if it is
+ still empty, to enable the detection of stripped executables. */
+ if (objfile->psymtabs->next == NULL
+ && objfile->psymtabs->number_of_dependencies == 0
+ && objfile->psymtabs->n_global_syms == 0
+ && objfile->psymtabs->n_static_syms == 0)
+ objfile->psymtabs = NULL;
+ do_cleanups (old_chain);
+}
+
+/* If the current psymbol has an enumerated type, we need to add
+ all the the enum constants to the partial symbol table. */
+
+static void
+handle_psymbol_enumerators (objfile, fh, stype, svalue)
+ struct objfile *objfile;
+ FDR *fh;
+ int stype;
+ CORE_ADDR svalue;
+{
+ const bfd_size_type external_sym_size = debug_swap->external_sym_size;
+ void (* const swap_sym_in) PARAMS ((bfd *, PTR, SYMR *))
+ = debug_swap->swap_sym_in;
+ char *ext_sym = ((char *) debug_info->external_sym
+ + ((fh->isymBase + cur_sdx + 1) * external_sym_size));
+ SYMR sh;
+ TIR tir;
+
+ switch (stype)
+ {
+ case stEnum:
+ break;
+
+ case stBlock:
+ /* It is an enumerated type if the next symbol entry is a stMember
+ and its auxiliary index is indexNil or its auxiliary entry
+ is a plain btNil or btVoid.
+ Alpha cc -migrate enums are recognized by a zero index and
+ a zero symbol value.
+ DU 4.0 cc enums are recognized by a member type of btEnum without
+ qualifiers and a zero symbol value. */
+ (*swap_sym_in) (cur_bfd, ext_sym, &sh);
+ if (sh.st != stMember)
+ return;
+
+ if (sh.index == indexNil
+ || (sh.index == 0 && svalue == 0))
+ break;
+ (*debug_swap->swap_tir_in) (fh->fBigendian,
+ &(debug_info->external_aux
+ + fh->iauxBase + sh.index)->a_ti,
+ &tir);
+ if ((tir.bt != btNil
+ && tir.bt != btVoid
+ && (tir.bt != btEnum || svalue != 0))
+ || tir.tq0 != tqNil)
+ return;
+ break;
+
+ default:
+ return;
+ }
+
+ for (;;)
+ {
+ char *name;
+
+ (*swap_sym_in) (cur_bfd, ext_sym, &sh);
+ if (sh.st != stMember)
+ break;
+ name = debug_info->ss + cur_fdr->issBase + sh.iss;
+
+ /* Note that the value doesn't matter for enum constants
+ in psymtabs, just in symtabs. */
+ add_psymbol_to_list (name, strlen (name),
+ VAR_NAMESPACE, LOC_CONST,
+ &objfile->static_psymbols, 0,
+ (CORE_ADDR) 0, psymtab_language, objfile);
+ ext_sym += external_sym_size;
+ }
+}
+
+static char *
+mdebug_next_symbol_text (objfile)
+ struct objfile *objfile; /* argument objfile is currently unused */
+{
+ SYMR sh;
+
+ cur_sdx++;
+ (*debug_swap->swap_sym_in) (cur_bfd,
+ ((char *) debug_info->external_sym
+ + ((cur_fdr->isymBase + cur_sdx)
+ * debug_swap->external_sym_size)),
+ &sh);
+ return debug_info->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;
+{
+ bfd_size_type external_sym_size;
+ bfd_size_type external_pdr_size;
+ void (*swap_sym_in) PARAMS ((bfd *, PTR, SYMR *));
+ void (*swap_pdr_in) PARAMS ((bfd *, PTR, PDR *));
+ int i;
+ struct symtab *st;
+ FDR *fh;
+ struct linetable *lines;
+ CORE_ADDR lowest_pdr_addr = 0;
+
+ 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 (" ", gdb_stdout);
+ wrap_here ("");
+ fputs_filtered ("and ", gdb_stdout);
+ wrap_here ("");
+ printf_filtered ("%s...",
+ pst->dependencies[i]->filename);
+ wrap_here (""); /* Flush output */
+ gdb_flush (gdb_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);
+ debug_swap = DEBUG_SWAP (pst);
+ debug_info = DEBUG_INFO (pst);
+ pending_list = PENDING_LIST (pst);
+ external_sym_size = debug_swap->external_sym_size;
+ external_pdr_size = debug_swap->external_pdr_size;
+ swap_sym_in = debug_swap->swap_sym_in;
+ swap_pdr_in = debug_swap->swap_pdr_in;
+ current_objfile = pst->objfile;
+ cur_fd = FDR_IDX (pst);
+ fh = ((cur_fd == -1)
+ ? (FDR *) NULL
+ : debug_info->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 *) debug_info->external_sym
+ + (fh->isymBase + 1) * external_sym_size),
+ &sh);
+ if (STREQ (debug_info->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)
+ {
+
+ /* 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 *) debug_info->external_sym)
+ + (fh->isymBase + cur_sdx) * external_sym_size),
+ &sh);
+ name = debug_info->ss + fh->issBase + sh.iss;
+ valu = sh.value;
+ /* XXX This is a hack. It will go away! */
+ if (ECOFF_IS_STAB (&sh) || (name[0] == '#'))
+ {
+ int type_code = ECOFF_UNMARK_STAB (sh.index);
+
+ /* We should never get non N_STAB symbols here, but they
+ should be harmless, so keep process_one_symbol from
+ complaining about them. */
+ if (type_code & N_STAB)
+ {
+ process_one_symbol (type_code, 0, valu, name,
+ pst->section_offsets, pst->objfile);
+ }
+ /* Similarly a hack. */
+ else if (name[0] == '#')
+ {
+ process_one_symbol (N_SLINE, 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);
+
+ memset ((PTR) e, 0, sizeof (struct mips_extra_func_info));
+ SYMBOL_NAMESPACE (s) = LABEL_NAMESPACE;
+ SYMBOL_CLASS (s) = LOC_CONST;
+ SYMBOL_TYPE (s) = mdebug_type_void;
+ SYMBOL_VALUE (s) = (long) e;
+ e->pdr.framereg = -1;
+ add_symbol_to_list (s, &local_symbols);
+ }
+ }
+ else if (sh.st == stLabel)
+ {
+ if (sh.index == indexNil)
+ {
+ /* This is what the gcc2_compiled and __gnu_compiled_*
+ show up as. So don't complain. */
+ ;
+ }
+ else
+ {
+ /* Handle encoded stab line number. */
+ valu += ANOFFSET (pst->section_offsets, SECT_OFF_TEXT);
+ record_line (current_subfile, sh.index, valu);
+ }
+ }
+ else if (sh.st == stProc || sh.st == stStaticProc
+ || sh.st == stStatic || sh.st == stEnd)
+ /* These are generated by gcc-2.x, do not complain */
+ ;
+ else
+ complain (&stab_unknown_complaint, name);
+ }
+ st = end_symtab (pst->texthigh, 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);
+
+ /* There used to be a call to sort_blocks here, but this should not
+ be necessary for stabs symtabs. And as sort_blocks modifies the
+ start address of the GLOBAL_BLOCK to the FIRST_LOCAL_BLOCK,
+ it did the wrong thing if the first procedure in a file was
+ generated via asm statements. */
+
+ /* Fill in procedure info next. */
+ 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 *) debug_info->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);
+
+ /* Determine lowest PDR address, the PDRs are not always
+ sorted. */
+ if (pdr_in == pr_block)
+ lowest_pdr_addr = pdr_in->adr;
+ else if (pdr_in->adr < lowest_pdr_addr)
+ lowest_pdr_addr = pdr_in->adr;
+ }
+
+ pdr_in = pr_block;
+ pdr_in_end = pdr_in + fh->cpd;
+ for (; pdr_in < pdr_in_end; pdr_in++)
+ parse_procedure (pdr_in, st, pst);
+
+ do_cleanups (old_chain);
+ }
+ }
+ else
+ {
+ /* This symbol table contains ordinary ecoff entries. */
+
+ 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) = pst->textlow;
+ 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;
+ found_ecoff_debugging_info = 0;
+
+ if (fh)
+ {
+ char *sym_ptr;
+ char *sym_end;
+
+ /* Parse local symbols first */
+ sym_ptr = ((char *) debug_info->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,
+ debug_info->external_aux + fh->iauxBase,
+ sym_ptr, fh->fBigendian, pst->section_offsets);
+ 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 *) debug_info->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);
+
+ /* Determine lowest PDR address, the PDRs are not always
+ sorted. */
+ if (pdr_in == pr_block)
+ lowest_pdr_addr = pdr_in->adr;
+ else if (pdr_in->adr < lowest_pdr_addr)
+ lowest_pdr_addr = pdr_in->adr;
+ }
+
+ parse_lines (fh, pr_block, lines, maxlines, pst, lowest_pdr_addr);
+ 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, pst);
+
+ 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
+ = (debug_info->symbolic_header.isymMax
+ + debug_info->symbolic_header.ipdMax
+ + debug_info->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, fh->fBigendian, pst->section_offsets);
+
+ /* 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 ();
+
+ st->primary = 1;
+
+ /* 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. */
+
+/* Return 1 if the symbol pointed to by SH has a cross reference
+ to an opaque aggregate type, else 0. */
+
+static int
+has_opaque_xref (fh, sh)
+ FDR *fh;
+ SYMR *sh;
+{
+ TIR tir;
+ union aux_ext *ax;
+ RNDXR rn[1];
+ unsigned int rf;
+
+ if (sh->index == indexNil)
+ return 0;
+
+ ax = debug_info->external_aux + fh->iauxBase + sh->index;
+ (*debug_swap->swap_tir_in) (fh->fBigendian, &ax->a_ti, &tir);
+ if (tir.bt != btStruct && tir.bt != btUnion && tir.bt != btEnum)
+ return 0;
+
+ ax++;
+ (*debug_swap->swap_rndx_in) (fh->fBigendian, &ax->a_rndx, rn);
+ if (rn->rfd == 0xfff)
+ rf = AUX_GET_ISYM (fh->fBigendian, ax + 1);
+ else
+ rf = rn->rfd;
+ if (rf != -1)
+ return 0;
+ return 1;
+}
+
+/* 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 mdebug_pending *pend;
+
+ *tpp = (struct type *)NULL;
+
+ (*debug_swap->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_typedef 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 - debug_info->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 *) debug_info->external_sym
+ + ((fh->isymBase + rn->index)
+ * debug_swap->external_sym_size));
+ (*debug_swap->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 != stIndirect
+ && sh.st != stStruct && sh.st != stUnion
+ && sh.st != stEnum))
+ && (sh.st != stBlock || !SC_IS_COMMON(sh.sc)))
+ {
+ /* File indirect entry is corrupt. */
+ *pname = "<illegal>";
+ complain (&bad_rfd_entry_complaint,
+ sym_name, xref_fd, rn->index);
+ return result;
+ }
+
+ *pname = debug_info->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) || sh.st == stIndirect)
+ {
+ 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/typedefs which
+ are defined later in this file or in another file in the same
+ compilation unit. Irix5 cc uses a stIndirect symbol for this.
+ 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. */
+
+ (*debug_swap->swap_tir_in) (bigend,
+ &(debug_info->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,
+ (debug_info->external_aux
+ + fh->iauxBase + sh.index + 1),
+ tpp, type_code, pname,
+ fh->fBigendian, sym_name);
+ break;
+
+ case btTypedef:
+ /* Follow a forward 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. 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,
+ debug_info->external_aux + fh->iauxBase,
+ sh.index,
+ (int *)NULL,
+ fh->fBigendian,
+ debug_info->ss + fh->issBase + sh.iss);
+ add_pending (fh, esh, *tpp);
+ 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,
+ debug_info->external_aux + fh->iauxBase,
+ sh.index,
+ (int *)NULL,
+ fh->fBigendian,
+ debug_info->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;
+ namespace_enum 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;
+{
+ /* DEC c89 sometimes produces zero linenos which confuse gdb.
+ Change them to something sensible. */
+ if (lineno == 0)
+ lineno = 1;
+ 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;
+ s->debugformat = obsavestring ("ECOFF", 5,
+ &objfile -> symbol_obstack);
+ return (s);
+}
+
+/* Allocate a new partial_symtab NAME */
+
+static struct partial_symtab *
+new_psymtab (name, objfile, section_offsets)
+ char *name;
+ struct objfile *objfile;
+ struct section_offsets *section_offsets;
+{
+ struct partial_symtab *psymtab;
+
+ psymtab = allocate_psymtab (name, objfile);
+ psymtab->section_offsets = section_offsets;
+
+ /* 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;
+ DEBUG_SWAP (psymtab) = debug_swap;
+ DEBUG_INFO (psymtab) = debug_info;
+ PENDING_LIST (psymtab) = pending_list;
+
+ /* The way to turn this into a symtab is to call... */
+ psymtab->read_symtab = mdebug_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) = obsavestring (name, strlen (name),
+ &current_objfile->symbol_obstack);
+ 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;
+}
+
+/* Read ECOFF debugging information from a BFD section. This is
+ called from elfread.c. It parses the section into a
+ ecoff_debug_info struct, and then lets the rest of the file handle
+ it as normal. */
+
+void
+elfmdebug_build_psymtabs (objfile, swap, sec, section_offsets)
+ struct objfile *objfile;
+ const struct ecoff_debug_swap *swap;
+ asection *sec;
+ struct section_offsets *section_offsets;
+{
+ bfd *abfd = objfile->obfd;
+ struct ecoff_debug_info *info;
+
+ info = ((struct ecoff_debug_info *)
+ obstack_alloc (&objfile->psymbol_obstack,
+ sizeof (struct ecoff_debug_info)));
+
+ if (!(*swap->read_debug_info) (abfd, sec, info))
+ error ("Error reading ECOFF debugging information: %s",
+ bfd_errmsg (bfd_get_error ()));
+
+ mdebug_build_psymtabs (objfile, swap, info, section_offsets);
+}
+
+
+/* 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. */
+
+/* FIXME: This function is called only by mips-tdep.c. It needs to be
+ here because it calls functions defined in this file, but perhaps
+ this could be handled in a better way. Only compile it in when
+ tm-mips.h is included. */
+
+#ifdef TM_MIPS_H
+
+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)) = mdebug_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 */
+ e->pdr.frameoffset = 32;
+ e->pdr.framereg = SP_REGNUM;
+ /* Note that setting pcreg is no longer strictly necessary as
+ mips_frame_saved_pc is now aware of signal handler frames. */
+ e->pdr.pcreg = PC_REGNUM;
+ e->pdr.regmask = -2;
+ /* Offset to saved r31, in the sigtramp case the saved registers
+ are above the frame in the sigcontext.
+ We have 4 alignment bytes, 12 bytes for onstack, mask and pc,
+ 32 * 4 bytes for the general registers, 12 bytes for mdhi, mdlo, ownedfp
+ and 32 * 4 bytes for the floating point registers. */
+ e->pdr.regoffset = 4 + 12 + 31 * 4;
+ e->pdr.fregmask = -1;
+ /* Offset to saved f30 (first saved *double* register). */
+ e->pdr.fregoffset = 4 + 12 + 32 * 4 + 12 + 30 * 4;
+ 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) = mdebug_type_void;
+ current_objfile = NULL;
+ }
+
+ BLOCK_SYM (b, BLOCK_NSYMS (b)++) = s;
+}
+
+#endif /* TM_MIPS_H */
+
+void
+_initialize_mdebugread ()
+{
+ mdebug_type_void =
+ init_type (TYPE_CODE_VOID, 1,
+ 0,
+ "void", (struct objfile *) NULL);
+ mdebug_type_char =
+ init_type (TYPE_CODE_INT, 1,
+ 0,
+ "char", (struct objfile *) NULL);
+ mdebug_type_unsigned_char =
+ init_type (TYPE_CODE_INT, 1,
+ TYPE_FLAG_UNSIGNED,
+ "unsigned char", (struct objfile *) NULL);
+ mdebug_type_short =
+ init_type (TYPE_CODE_INT, 2,
+ 0,
+ "short", (struct objfile *) NULL);
+ mdebug_type_unsigned_short =
+ init_type (TYPE_CODE_INT, 2,
+ TYPE_FLAG_UNSIGNED,
+ "unsigned short", (struct objfile *) NULL);
+ mdebug_type_int_32 =
+ init_type (TYPE_CODE_INT, 4,
+ 0,
+ "int", (struct objfile *) NULL);
+ mdebug_type_unsigned_int_32 =
+ init_type (TYPE_CODE_INT, 4,
+ TYPE_FLAG_UNSIGNED,
+ "unsigned int", (struct objfile *) NULL);
+ mdebug_type_int_64 =
+ init_type (TYPE_CODE_INT, 8,
+ 0,
+ "int", (struct objfile *) NULL);
+ mdebug_type_unsigned_int_64 =
+ init_type (TYPE_CODE_INT, 8,
+ TYPE_FLAG_UNSIGNED,
+ "unsigned int", (struct objfile *) NULL);
+ mdebug_type_long_32 =
+ init_type (TYPE_CODE_INT, 4,
+ 0,
+ "long", (struct objfile *) NULL);
+ mdebug_type_unsigned_long_32 =
+ init_type (TYPE_CODE_INT, 4,
+ TYPE_FLAG_UNSIGNED,
+ "unsigned long", (struct objfile *) NULL);
+ mdebug_type_long_64 =
+ init_type (TYPE_CODE_INT, 8,
+ 0,
+ "long", (struct objfile *) NULL);
+ mdebug_type_unsigned_long_64 =
+ init_type (TYPE_CODE_INT, 8,
+ TYPE_FLAG_UNSIGNED,
+ "unsigned long", (struct objfile *) NULL);
+ mdebug_type_long_long_64 =
+ init_type (TYPE_CODE_INT, 8,
+ 0,
+ "long long", (struct objfile *) NULL);
+ mdebug_type_unsigned_long_long_64 =
+ init_type (TYPE_CODE_INT, 8,
+ TYPE_FLAG_UNSIGNED,
+ "unsigned long long", (struct objfile *) NULL);
+ mdebug_type_adr_32 =
+ init_type (TYPE_CODE_PTR, 4,
+ TYPE_FLAG_UNSIGNED,
+ "adr_32", (struct objfile *) NULL);
+ TYPE_TARGET_TYPE (mdebug_type_adr_32) = mdebug_type_void;
+ mdebug_type_adr_64 =
+ init_type (TYPE_CODE_PTR, 8,
+ TYPE_FLAG_UNSIGNED,
+ "adr_64", (struct objfile *) NULL);
+ TYPE_TARGET_TYPE (mdebug_type_adr_64) = mdebug_type_void;
+ mdebug_type_float =
+ init_type (TYPE_CODE_FLT, TARGET_FLOAT_BIT / TARGET_CHAR_BIT,
+ 0,
+ "float", (struct objfile *) NULL);
+ mdebug_type_double =
+ init_type (TYPE_CODE_FLT, TARGET_DOUBLE_BIT / TARGET_CHAR_BIT,
+ 0,
+ "double", (struct objfile *) NULL);
+ mdebug_type_complex =
+ init_type (TYPE_CODE_COMPLEX, 2 * TARGET_FLOAT_BIT / TARGET_CHAR_BIT,
+ 0,
+ "complex", (struct objfile *) NULL);
+ TYPE_TARGET_TYPE (mdebug_type_complex) = mdebug_type_float;
+ mdebug_type_double_complex =
+ init_type (TYPE_CODE_COMPLEX, 2 * TARGET_DOUBLE_BIT / TARGET_CHAR_BIT,
+ 0,
+ "double complex", (struct objfile *) NULL);
+ TYPE_TARGET_TYPE (mdebug_type_double_complex) = mdebug_type_double;
+
+ /* Is a "string" the way btString means it the same as TYPE_CODE_STRING?
+ FIXME. */
+ mdebug_type_string =
+ init_type (TYPE_CODE_STRING,
+ TARGET_CHAR_BIT / TARGET_CHAR_BIT,
+ 0, "string",
+ (struct objfile *) NULL);
+
+ /* We use TYPE_CODE_INT to print these as integers. Does this do any
+ good? Would we be better off with TYPE_CODE_ERROR? Should
+ TYPE_CODE_ERROR print things in hex if it knows the size? */
+ mdebug_type_fixed_dec =
+ init_type (TYPE_CODE_INT,
+ TARGET_INT_BIT / TARGET_CHAR_BIT,
+ 0, "fixed decimal",
+ (struct objfile *) NULL);
+
+ mdebug_type_float_dec =
+ init_type (TYPE_CODE_ERROR,
+ TARGET_DOUBLE_BIT / TARGET_CHAR_BIT,
+ 0, "floating decimal",
+ (struct objfile *) NULL);
+
+ nodebug_func_symbol_type = init_type (TYPE_CODE_FUNC, 1, 0,
+ "<function, no debug info>", NULL);
+ TYPE_TARGET_TYPE (nodebug_func_symbol_type) = mdebug_type_int;
+ nodebug_var_symbol_type =
+ init_type (TYPE_CODE_INT, TARGET_INT_BIT / HOST_CHAR_BIT, 0,
+ "<variable, no debug info>", NULL);
+}
diff --git a/gdb/mem-break.c b/gdb/mem-break.c
new file mode 100644
index 00000000000..b0a1b4f6371
--- /dev/null
+++ b/gdb/mem-break.c
@@ -0,0 +1,124 @@
+/* Simulate breakpoints by patching locations in the target system, for GDB.
+ Copyright 1990, 1991, 1995 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+
+/* 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"
+
+
+/* Use the program counter to determine the contents and size
+ of a breakpoint instruction. If no target-dependent macro
+ BREAKPOINT_FROM_PC has been defined to implement this function,
+ assume that the breakpoint doesn't depend on the PC, and
+ use the values of the BIG_BREAKPOINT and LITTLE_BREAKPOINT macros.
+ Return a pointer to a string of bytes that encode a breakpoint
+ instruction, stores the length of the string to *lenptr,
+ and optionally adjust the pc to point to the correct memory location
+ for inserting the breakpoint. */
+
+unsigned char *
+memory_breakpoint_from_pc (pcptr, lenptr)
+ CORE_ADDR *pcptr;
+ int *lenptr;
+{
+ /* {BIG_,LITTLE_}BREAKPOINT 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. */
+#ifdef BIG_BREAKPOINT
+ if (TARGET_BYTE_ORDER == BIG_ENDIAN)
+ {
+ static unsigned char big_break_insn[] = BIG_BREAKPOINT;
+ *lenptr = sizeof (big_break_insn);
+ return big_break_insn;
+ }
+#endif
+#ifdef LITTLE_BREAKPOINT
+ if (TARGET_BYTE_ORDER != BIG_ENDIAN)
+ {
+ static unsigned char little_break_insn[] = LITTLE_BREAKPOINT;
+ *lenptr = sizeof (little_break_insn);
+ return little_break_insn;
+ }
+#endif
+#ifdef BREAKPOINT
+ {
+ static unsigned char break_insn[] = BREAKPOINT;
+ *lenptr = sizeof (break_insn);
+ return break_insn;
+ }
+#endif
+ *lenptr = 0;
+ return NULL;
+}
+
+
+/* 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 BREAKPOINT_LEN bytes (this
+ is accomplished via BREAKPOINT_MAX). */
+
+int
+memory_insert_breakpoint (addr, contents_cache)
+ CORE_ADDR addr;
+ char *contents_cache;
+{
+ int val;
+ unsigned char *bp;
+ int bplen;
+
+ /* Determine appropriate breakpoint contents and size for this address. */
+ bp = BREAKPOINT_FROM_PC (&addr, &bplen);
+ if (bp == NULL)
+ error ("Software breakpoints not implemented for this target.");
+
+ /* Save the memory contents. */
+ val = target_read_memory (addr, contents_cache, bplen);
+
+ /* Write the breakpoint. */
+ if (val == 0)
+ val = target_write_memory (addr, (char *)bp, bplen);
+
+ return val;
+}
+
+
+int
+memory_remove_breakpoint (addr, contents_cache)
+ CORE_ADDR addr;
+ char *contents_cache;
+{
+ unsigned char *bp;
+ int bplen;
+
+ /* Determine appropriate breakpoint contents and size for this address. */
+ bp = BREAKPOINT_FROM_PC (&addr, &bplen);
+ if (bp == NULL)
+ error ("Software breakpoints not implemented for this target.");
+
+ return target_write_memory (addr, contents_cache, bplen);
+}
diff --git a/gdb/minimon.h b/gdb/minimon.h
new file mode 100644
index 00000000000..f60c4176f1c
--- /dev/null
+++ b/gdb/minimon.h
@@ -0,0 +1,562 @@
+/* Definitions and macros for support of AMD's remote debugger, MiniMON.
+ Copyright (C) 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/*
+ * Some basic types. FIXME, this should be done by declaring bitfield
+ * sizes in the structs. We can't portably depend on a "long int" being
+ * 32 bits, etc.
+ */
+typedef long int INT32; /* 32 bit integer */
+typedef unsigned long int UINT32; /* 32 bit integer (unsigned) */
+typedef unsigned long int ADDR32; /* 32 bit address */
+typedef unsigned long int INST32; /* 32 bit instruction */
+typedef long int BOOLEAN; /* Boolean value (32 bit) */
+typedef unsigned char BYTE; /* byte (8 bit) */
+typedef short int INT16; /* 16 bit integer */
+typedef unsigned short int UINT16; /* 16 bit integer (unsigned) */
+
+/****************************************************************************/
+/************************* Message Information ******************************/
+/****************************************************************************/
+
+/*
+ * Error codes
+ */
+
+/* General errors */
+#define EMUSAGE 1 /* Bad args / flags */
+#define EMFAIL 2 /* Unrecoverable error */
+#define EMBADADDR 3 /* Illegal address */
+#define EMBADREG 4 /* Illegal register */
+#define EMSYNTAX 5 /* Illegal command syntax */
+#define EMACCESS 6 /* Could not access memory */
+#define EMALLOC 7 /* Could not allocate memory */
+#define EMTARGET 8 /* Unknown target type */
+#define EMHINIT 9 /* Could not initialize host */
+#define EMCOMM 10 /* Could not open communication channel */
+
+/* Message errors */
+#define EMBADMSG 11 /* Unknown message type */
+#define EMMSG2BIG 12 /* Message to large for buffer */
+#define EMNOSEND 13 /* Could not send message */
+#define EMNORECV 14 /* Could not receive message */
+
+#define EMRESET 15 /* Could not RESET target */
+#define EMCONFIG 16 /* Could not get target CONFIG */
+#define EMSTATUS 17 /* Could not get target STATUS */
+#define EMREAD 18 /* Could not READ target memory */
+#define EMWRITE 19 /* Could not WRITE target memory */
+#define EMBKPTSET 20 /* Could not set breakpoint */
+#define EMBKPTRM 21 /* Could not remove breakpoint */
+#define EMBKPTSTAT 22 /* Could not get breakpoint status */
+#define EMBKPTNONE 23 /* All breakpoints in use */
+#define EMBKPTUSED 24 /* Breakpoints already in use */
+#define EMCOPY 25 /* Could not COPY target memory */
+#define EMFILL 26 /* Could not FILL target memory */
+#define EMINIT 27 /* Could not initialize target memory */
+#define EMGO 28 /* Could not start execution */
+#define EMSTEP 29 /* Could not single step */
+#define EMBREAK 30 /* Could not BREAK */
+#define EMHIF 31 /* Could not perform HIF service */
+#define EMCHANNEL0 32 /* Could not read CHANNEL0 */
+#define EMCHANNEL1 33 /* Could not write CHANNEL1 */
+
+/* COFF file loader errors */
+#define EMOPEN 34 /* Could not open COFF file */
+#define EMHDR 35 /* Could not read COFF header */
+#define EMMAGIC 36 /* Bad magic number */
+#define EMAOUT 37 /* Could not read COFF a.out header */
+#define EMSCNHDR 38 /* Could not read COFF section header */
+#define EMSCN 39 /* Could not read COFF section */
+#define EMCLOSE 40 /* Could not close COFF file */
+
+/* Log file errors */
+#define EMLOGOPEN 41 /* Could not open log file */
+#define EMLOGREAD 42 /* Could not read log file */
+#define EMLOGWRITE 43 /* Could not write to log file */
+#define EMLOGCLOSE 44 /* Could not close log file */
+
+/* Command file errors */
+#define EMCMDOPEN 45 /* Could not open command file */
+#define EMCMDREAD 46 /* Could not read command file */
+#define EMCMDWRITE 47 /* Could not write to command file */
+#define EMCMDCLOSE 48 /* Could not close comand file */
+
+#define EMTIMEOUT 49 /* Host timed out waiting for a message */
+#define EMCOMMTYPE 50 /* A '-t' flag must be specified */
+#define EMCOMMERR 51 /* Communication error */
+#define EMBAUD 52 /* Invalid baud rate specified */
+/*
+ * Memory Spaces
+ */
+#define LOCAL_REG 0 /* Local processor register */
+#define GLOBAL_REG 1 /* Global processor register */
+#define SPECIAL_REG 2 /* Special processor register */
+#define TLB_REG 3 /* Translation Lookaside Buffer */
+#define COPROC_REG 4 /* Coprocessor register */
+#define I_MEM 5 /* Instruction Memory */
+#define D_MEM 6 /* Data Memory */
+#define I_ROM 7 /* Instruction ROM */
+#define D_ROM 8 /* Data ROM */
+#define I_O 9 /* Input/Output */
+#define I_CACHE 10 /* Instruction Cache */
+#define D_CACHE 11 /* Data Cache */
+
+/* To supress warnings for zero length array definitions */
+#define DUMMY 1
+
+/*
+** Host to target definitions
+*/
+
+#define RESET 0
+#define CONFIG_REQ 1
+#define STATUS_REQ 2
+#define READ_REQ 3
+#define WRITE_REQ 4
+#define BKPT_SET 5
+#define BKPT_RM 6
+#define BKPT_STAT 7
+#define COPY 8
+#define FILL 9
+#define INIT 10
+#define GO 11
+#define STEP 12
+#define BREAK 13
+
+#define HIF_CALL_RTN 64
+#define CHANNEL0 65
+#define CHANNEL1_ACK 66
+
+
+/*
+** Target to host definitions
+*/
+
+#define RESET_ACK 32
+#define CONFIG 33
+#define STATUS 34
+#define READ_ACK 35
+#define WRITE_ACK 36
+#define BKPT_SET_ACK 37
+#define BKPT_RM_ACK 38
+#define BKPT_STAT_ACK 39
+#define COPY_ACK 40
+#define FILL_ACK 41
+#define INIT_ACK 42
+#define HALT 43
+
+#define ERROR 63
+
+#define HIF_CALL 96
+#define CHANNEL0_ACK 97
+#define CHANNEL1 98
+
+
+/* A "generic" message */
+struct generic_msg_t {
+ INT32 code; /* generic */
+ INT32 length;
+ BYTE byte[DUMMY];
+};
+
+
+/* A "generic" message (with an INT32 array) */
+struct generic_int32_msg_t {
+ INT32 code; /* generic */
+ INT32 length;
+ INT32 int32[DUMMY];
+};
+
+
+/*
+** Host to target messages
+*/
+
+struct reset_msg_t {
+ INT32 code; /* 0 */
+ INT32 length;
+};
+
+
+struct config_req_msg_t {
+ INT32 code; /* 1 */
+ INT32 length;
+};
+
+
+struct status_req_msg_t {
+ INT32 code; /* 2 */
+ INT32 length;
+};
+
+
+struct read_req_msg_t {
+ INT32 code; /* 3 */
+ INT32 length;
+ INT32 memory_space;
+ ADDR32 address;
+ INT32 byte_count;
+};
+
+
+struct write_req_msg_t {
+ INT32 code; /* 4 */
+ INT32 length;
+ INT32 memory_space;
+ ADDR32 address;
+ INT32 byte_count;
+ BYTE data[DUMMY];
+};
+
+
+struct write_r_msg_t {
+ INT32 code; /* 4 */
+ INT32 length;
+ INT32 memory_space;
+ ADDR32 address;
+ INT32 byte_count;
+ INT32 data[DUMMY];
+};
+
+
+struct bkpt_set_msg_t {
+ INT32 code; /* 5 */
+ INT32 length;
+ INT32 memory_space;
+ ADDR32 bkpt_addr;
+ INT32 pass_count;
+ INT32 bkpt_type;
+};
+
+
+struct bkpt_rm_msg_t {
+ INT32 code; /* 6 */
+ INT32 length;
+ INT32 memory_space;
+ ADDR32 bkpt_addr;
+};
+
+
+struct bkpt_stat_msg_t {
+ INT32 code; /* 7 */
+ INT32 length;
+ INT32 memory_space;
+ ADDR32 bkpt_addr;
+};
+
+
+struct copy_msg_t {
+ INT32 code; /* 8 */
+ INT32 length;
+ INT32 source_space;
+ ADDR32 source_addr;
+ INT32 dest_space;
+ ADDR32 dest_addr;
+ INT32 byte_count;
+};
+
+
+struct fill_msg_t {
+ INT32 code; /* 9 */
+ INT32 length;
+ INT32 memory_space;
+ ADDR32 start_addr;
+ INT32 fill_count;
+ INT32 byte_count;
+ BYTE fill_data[DUMMY];
+};
+
+
+struct init_msg_t {
+ INT32 code; /* 10 */
+ INT32 length;
+ ADDR32 text_start;
+ ADDR32 text_end;
+ ADDR32 data_start;
+ ADDR32 data_end;
+ ADDR32 entry_point;
+ INT32 mem_stack_size;
+ INT32 reg_stack_size;
+ ADDR32 arg_start;
+ INT32 os_control;
+};
+
+
+struct go_msg_t {
+ INT32 code; /* 11 */
+ INT32 length;
+};
+
+
+struct step_msg_t {
+ INT32 code; /* 12 */
+ INT32 length;
+ INT32 count;
+};
+
+
+struct break_msg_t {
+ INT32 code; /* 13 */
+ INT32 length;
+};
+
+
+struct hif_call_rtn_msg_t {
+ INT32 code; /* 64 */
+ INT32 length;
+ INT32 service_number;
+ INT32 gr121;
+ INT32 gr96;
+ INT32 gr97;
+};
+
+
+struct channel0_msg_t {
+ INT32 code; /* 65 */
+ INT32 length;
+ BYTE data;
+};
+
+
+struct channel1_ack_msg_t {
+ INT32 code; /* 66 */
+ INT32 length;
+};
+
+
+/*
+** Target to host messages
+*/
+
+
+struct reset_ack_msg_t {
+ INT32 code; /* 32 */
+ INT32 length;
+};
+
+
+struct config_msg_t {
+ INT32 code; /* 33 */
+ INT32 length;
+ INT32 processor_id;
+ INT32 version;
+ ADDR32 I_mem_start;
+ INT32 I_mem_size;
+ ADDR32 D_mem_start;
+ INT32 D_mem_size;
+ ADDR32 ROM_start;
+ INT32 ROM_size;
+ INT32 max_msg_size;
+ INT32 max_bkpts;
+ INT32 coprocessor;
+ INT32 reserved;
+};
+
+
+struct status_msg_t {
+ INT32 code; /* 34 */
+ INT32 length;
+ INT32 msgs_sent;
+ INT32 msgs_received;
+ INT32 errors;
+ INT32 bkpts_hit;
+ INT32 bkpts_free;
+ INT32 traps;
+ INT32 fills;
+ INT32 spills;
+ INT32 cycles;
+ INT32 reserved;
+};
+
+
+struct read_ack_msg_t {
+ INT32 code; /* 35 */
+ INT32 length;
+ INT32 memory_space;
+ ADDR32 address;
+ INT32 byte_count;
+ BYTE data[DUMMY];
+};
+
+struct read_r_ack_msg_t {
+ INT32 code; /* 35 */
+ INT32 length;
+ INT32 memory_space;
+ ADDR32 address;
+ INT32 byte_count;
+ INT32 data[DUMMY];
+};
+
+
+struct write_ack_msg_t {
+ INT32 code; /* 36 */
+ INT32 length;
+ INT32 memory_space;
+ ADDR32 address;
+ INT32 byte_count;
+};
+
+
+struct bkpt_set_ack_msg_t {
+ INT32 code; /* 37 */
+ INT32 length;
+ INT32 memory_space;
+ ADDR32 address;
+ INT32 pass_count;
+ INT32 bkpt_type;
+};
+
+
+struct bkpt_rm_ack_msg_t {
+ INT32 code; /* 38 */
+ INT32 length;
+ INT32 memory_space;
+ ADDR32 address;
+};
+
+
+struct bkpt_stat_ack_msg_t {
+ INT32 code; /* 39 */
+ INT32 length;
+ INT32 memory_space;
+ ADDR32 address;
+ INT32 pass_count;
+ INT32 bkpt_type;
+};
+
+
+struct copy_ack_msg_t {
+ INT32 code; /* 40 */
+ INT32 length;
+ INT32 source_space;
+ ADDR32 source_addr;
+ INT32 dest_space;
+ ADDR32 dest_addr;
+ INT32 byte_count;
+};
+
+
+struct fill_ack_msg_t {
+ INT32 code; /* 41 */
+ INT32 length;
+ INT32 memory_space;
+ ADDR32 start_addr;
+ INT32 fill_count;
+ INT32 byte_count;
+};
+
+
+struct init_ack_msg_t {
+ INT32 code; /* 42 */
+ INT32 length;
+};
+
+
+struct halt_msg_t {
+ INT32 code; /* 43 */
+ INT32 length;
+ INT32 memory_space;
+ ADDR32 pc0;
+ ADDR32 pc1;
+ INT32 trap_number;
+};
+
+
+struct error_msg_t {
+ INT32 code; /* 63 */
+ INT32 length;
+ INT32 error_code;
+ INT32 memory_space;
+ ADDR32 address;
+};
+
+
+struct hif_call_msg_t {
+ INT32 code; /* 96 */
+ INT32 length;
+ INT32 service_number;
+ INT32 lr2;
+ INT32 lr3;
+ INT32 lr4;
+};
+
+
+struct channel0_ack_msg_t {
+ INT32 code; /* 97 */
+ INT32 length;
+};
+
+
+struct channel1_msg_t {
+ INT32 code; /* 98 */
+ INT32 length;
+ BYTE data[DUMMY];
+};
+
+
+
+/*
+** Union all of the message types together
+*/
+
+union msg_t {
+ struct generic_msg_t generic_msg;
+ struct generic_int32_msg_t generic_int32_msg;
+
+ struct reset_msg_t reset_msg;
+ struct config_req_msg_t config_req_msg;
+ struct status_req_msg_t status_req_msg;
+ struct read_req_msg_t read_req_msg;
+ struct write_req_msg_t write_req_msg;
+ struct write_r_msg_t write_r_msg;
+ struct bkpt_set_msg_t bkpt_set_msg;
+ struct bkpt_rm_msg_t bkpt_rm_msg;
+ struct bkpt_stat_msg_t bkpt_stat_msg;
+ struct copy_msg_t copy_msg;
+ struct fill_msg_t fill_msg;
+ struct init_msg_t init_msg;
+ struct go_msg_t go_msg;
+ struct step_msg_t step_msg;
+ struct break_msg_t break_msg;
+
+ struct hif_call_rtn_msg_t hif_call_rtn_msg;
+ struct channel0_msg_t channel0_msg;
+ struct channel1_ack_msg_t channel1_ack_msg;
+
+ struct reset_ack_msg_t reset_ack_msg;
+ struct config_msg_t config_msg;
+ struct status_msg_t status_msg;
+ struct read_ack_msg_t read_ack_msg;
+ struct read_r_ack_msg_t read_r_ack_msg;
+ struct write_ack_msg_t write_ack_msg;
+ struct bkpt_set_ack_msg_t bkpt_set_ack_msg;
+ struct bkpt_rm_ack_msg_t bkpt_rm_ack_msg;
+ struct bkpt_stat_ack_msg_t bkpt_stat_ack_msg;
+ struct copy_ack_msg_t copy_ack_msg;
+ struct fill_ack_msg_t fill_ack_msg;
+ struct init_ack_msg_t init_ack_msg;
+ struct halt_msg_t halt_msg;
+
+ struct error_msg_t error_msg;
+
+ struct hif_call_msg_t hif_call_msg;
+ struct channel0_ack_msg_t channel0_ack_msg;
+ struct channel1_msg_t channel1_msg;
+};
diff --git a/gdb/minsyms.c b/gdb/minsyms.c
new file mode 100644
index 00000000000..a271c9180c1
--- /dev/null
+++ b/gdb/minsyms.c
@@ -0,0 +1,904 @@
+/* GDB routines for manipulating the minimal symbol tables.
+ Copyright 1992, 93, 94, 96, 97, 1998 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 "gdb_string.h"
+#include "symtab.h"
+#include "bfd.h"
+#include "symfile.h"
+#include "objfiles.h"
+#include "demangle.h"
+#include "gdb-stabs.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, limit
+ the search to that objfile. If SFILE is non-NULL, limit the search
+ to that source file. 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, sfile, objf)
+ register const char *name;
+ const char *sfile;
+ struct objfile *objf;
+{
+ struct objfile *objfile;
+ struct minimal_symbol *msymbol;
+ struct minimal_symbol *found_symbol = NULL;
+ struct minimal_symbol *found_file_symbol = NULL;
+ struct minimal_symbol *trampoline_symbol = NULL;
+
+#ifdef SOFUN_ADDRESS_MAYBE_MISSING
+ if (sfile != NULL)
+ {
+ char *p = strrchr (sfile, '/');
+ if (p != NULL)
+ sfile = p + 1;
+ }
+#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:
+#ifdef SOFUN_ADDRESS_MAYBE_MISSING
+ if (sfile == NULL || STREQ (msymbol->filename, sfile))
+ found_file_symbol = msymbol;
+#else
+ /* We have neither the ability nor the need to
+ deal with the SFILE parameter. If we find
+ more than one symbol, just return the latest
+ one (the user can't expect useful behavior in
+ that case). */
+ found_file_symbol = msymbol;
+#endif
+ break;
+
+ case mst_solib_trampoline:
+
+ /* If a trampoline symbol is found, we prefer to
+ keep looking for the *real* symbol. If the
+ actual symbol is not found, then we'll use the
+ trampoline entry. */
+ if (trampoline_symbol == NULL)
+ trampoline_symbol = msymbol;
+ break;
+
+ case mst_unknown:
+ 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 shared library trampolines are next best. */
+ if (trampoline_symbol)
+ return trampoline_symbol;
+
+ return NULL;
+}
+
+/* Look through all the current minimal symbol tables and find the
+ first minimal symbol that matches NAME and of text type.
+ If OBJF is non-NULL, limit
+ the search to that objfile. If SFILE is non-NULL, limit the search
+ to that source file. Returns a pointer to the minimal symbol that
+ matches, or NULL if no match is found.
+*/
+
+struct minimal_symbol *
+lookup_minimal_symbol_text (name, sfile, objf)
+ register const char *name;
+ const char *sfile;
+ struct objfile *objf;
+{
+ struct objfile *objfile;
+ struct minimal_symbol *msymbol;
+ struct minimal_symbol *found_symbol = NULL;
+ struct minimal_symbol *found_file_symbol = NULL;
+
+#ifdef SOFUN_ADDRESS_MAYBE_MISSING
+ if (sfile != NULL)
+ {
+ char *p = strrchr (sfile, '/');
+ if (p != NULL)
+ sfile = p + 1;
+ }
+#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) &&
+ (MSYMBOL_TYPE (msymbol) == mst_text ||
+ MSYMBOL_TYPE (msymbol) == mst_file_text))
+ {
+ switch (MSYMBOL_TYPE (msymbol))
+ {
+ case mst_file_text:
+#ifdef SOFUN_ADDRESS_MAYBE_MISSING
+ if (sfile == NULL || STREQ (msymbol->filename, sfile))
+ found_file_symbol = msymbol;
+#else
+ /* We have neither the ability nor the need to
+ deal with the SFILE parameter. If we find
+ more than one symbol, just return the latest
+ one (the user can't expect useful behavior in
+ that case). */
+ found_file_symbol = msymbol;
+#endif
+ break;
+ 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;
+
+ return NULL;
+}
+
+/* Look through all the current minimal symbol tables and find the
+ first minimal symbol that matches NAME and of solib trampoline type.
+ If OBJF is non-NULL, limit
+ the search to that objfile. If SFILE is non-NULL, limit the search
+ to that source file. Returns a pointer to the minimal symbol that
+ matches, or NULL if no match is found.
+*/
+
+struct minimal_symbol *
+lookup_minimal_symbol_solib_trampoline (name, sfile, objf)
+ register const char *name;
+ const char *sfile;
+ struct objfile *objf;
+{
+ struct objfile *objfile;
+ struct minimal_symbol *msymbol;
+ struct minimal_symbol *found_symbol = NULL;
+
+#ifdef SOFUN_ADDRESS_MAYBE_MISSING
+ if (sfile != NULL)
+ {
+ char *p = strrchr (sfile, '/');
+ if (p != NULL)
+ sfile = p + 1;
+ }
+#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) &&
+ MSYMBOL_TYPE (msymbol) == mst_solib_trampoline)
+ return msymbol;
+ }
+ }
+ }
+
+ 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, and matches SECTION (if non-null). 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_section (pc, section)
+ CORE_ADDR pc;
+ asection *section;
+{
+ int lo;
+ int hi;
+ int new;
+ struct objfile *objfile;
+ struct minimal_symbol *msymbol;
+ struct minimal_symbol *best_symbol = NULL;
+
+ /* pc has to be in a known section. This ensures that anything beyond
+ the end of the last segment doesn't appear to be part of the last
+ function in the last segment. */
+ if (find_pc_section (pc) == NULL)
+ return 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 require 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;
+ }
+ }
+
+ /* If we have multiple symbols at the same address, we want
+ hi to point to the last one. That way we can find the
+ right symbol if it has an index greater than hi. */
+ while (hi < objfile -> minimal_symbol_count - 1
+ && (SYMBOL_VALUE_ADDRESS (&msymbol[hi])
+ == SYMBOL_VALUE_ADDRESS (&msymbol[hi+1])))
+ hi++;
+
+ /* 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 "section" specified, skip any symbol from wrong section */
+ /* This is the new code that distinguishes it from the old function */
+ if (section)
+ while (hi >= 0
+ && SYMBOL_BFD_SECTION (&msymbol[hi]) != section)
+ --hi;
+
+ if (hi >= 0
+ && ((best_symbol == NULL) ||
+ (SYMBOL_VALUE_ADDRESS (best_symbol) <
+ SYMBOL_VALUE_ADDRESS (&msymbol[hi]))))
+ {
+ best_symbol = &msymbol[hi];
+ }
+ }
+ }
+ }
+ return (best_symbol);
+}
+
+/* Backward compatibility: search through the minimal symbol table
+ for a matching PC (no section given) */
+
+struct minimal_symbol *
+lookup_minimal_symbol_by_pc (pc)
+ CORE_ADDR pc;
+{
+ return lookup_minimal_symbol_by_pc_section (pc, find_pc_mapped_section (pc));
+}
+
+#ifdef SOFUN_ADDRESS_MAYBE_MISSING
+CORE_ADDR
+find_stab_function_addr (namestring, pst, objfile)
+ char *namestring;
+ struct partial_symtab *pst;
+ struct objfile *objfile;
+{
+ struct minimal_symbol *msym;
+ char *p;
+ int n;
+
+ p = strchr (namestring, ':');
+ if (p == NULL)
+ p = namestring;
+ n = p - namestring;
+ p = alloca (n + 2);
+ strncpy (p, namestring, n);
+ p[n] = 0;
+
+ msym = lookup_minimal_symbol (p, pst->filename, objfile);
+ if (msym == NULL)
+ {
+ /* Sun Fortran appends an underscore to the minimal symbol name,
+ try again with an appended underscore if the minimal symbol
+ was not found. */
+ p[n] = '_';
+ p[n + 1] = 0;
+ msym = lookup_minimal_symbol (p, pst->filename, objfile);
+ }
+ return msym == NULL ? 0 : SYMBOL_VALUE_ADDRESS (msym);
+}
+#endif /* SOFUN_ADDRESS_MAYBE_MISSING */
+
+
+/* Return leading symbol character for a BFD. If BFD is NULL,
+ return the leading symbol character from the main objfile. */
+
+static int get_symbol_leading_char PARAMS ((bfd *));
+
+static int
+get_symbol_leading_char (abfd)
+ bfd * abfd;
+{
+ if (abfd != NULL)
+ return bfd_get_symbol_leading_char (abfd);
+ if (symfile_objfile != NULL && symfile_objfile->obfd != NULL)
+ return bfd_get_symbol_leading_char (symfile_objfile->obfd);
+ return 0;
+}
+
+/* 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, objfile)
+ const char *name;
+ CORE_ADDR address;
+ enum minimal_symbol_type ms_type;
+ struct objfile *objfile;
+{
+ int section;
+
+ switch (ms_type)
+ {
+ case mst_text:
+ case mst_file_text:
+ case mst_solib_trampoline:
+ 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;
+ }
+
+ prim_record_minimal_symbol_and_info (name, address, ms_type,
+ NULL, section, NULL, objfile);
+}
+
+/* Record a minimal symbol in the msym bunches. Returns the symbol
+ newly created. */
+
+struct minimal_symbol *
+prim_record_minimal_symbol_and_info (name, address, ms_type, info, section,
+ bfd_section, objfile)
+ const char *name;
+ CORE_ADDR address;
+ enum minimal_symbol_type ms_type;
+ char *info;
+ int section;
+ asection *bfd_section;
+ struct objfile *objfile;
+{
+ register struct msym_bunch *new;
+ register struct minimal_symbol *msymbol;
+
+ if (ms_type == mst_file_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 (NULL);
+
+ {
+ const char *tempstring = name;
+ if (tempstring[0] == get_symbol_leading_char (objfile->obfd))
+ ++tempstring;
+ if (STREQN (tempstring, "__gnu_compiled", 14))
+ return (NULL);
+ }
+ }
+
+ 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) = obsavestring ((char *) name, strlen (name),
+ &objfile->symbol_obstack);
+ SYMBOL_INIT_LANGUAGE_SPECIFIC (msymbol, language_unknown);
+ SYMBOL_VALUE_ADDRESS (msymbol) = address;
+ SYMBOL_SECTION (msymbol) = section;
+ SYMBOL_BFD_SECTION (msymbol) = bfd_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++;
+ OBJSTAT (objfile, n_minsyms++);
+ return msymbol;
+}
+
+/* Compare two minimal symbols by address and return a signed result based
+ on unsigned comparisons, so that we sort into unsigned numeric order.
+ Within groups with the same address, sort by name. */
+
+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); /* addr 1 is less than addr 2 */
+ }
+ else if (SYMBOL_VALUE_ADDRESS (fn1) > SYMBOL_VALUE_ADDRESS (fn2))
+ {
+ return (1); /* addr 1 is greater than addr 2 */
+ }
+ else /* addrs are equal: sort by name */
+ {
+ char *name1 = SYMBOL_NAME (fn1);
+ char *name2 = SYMBOL_NAME (fn2);
+
+ if (name1 && name2) /* both have names */
+ return strcmp (name1, name2);
+ else if (name2)
+ return 1; /* fn1 has no name, so it is "less" */
+ else if (name1) /* fn2 has no name, so it is "less" */
+ return -1;
+ else
+ return (0); /* neither has a name, so they're equal. */
+ }
+}
+
+/* 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 = 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);
+ }
+ }
+}
+
+/* Sort all the minimal symbols in OBJFILE. */
+
+void
+msymbols_sort (objfile)
+ struct objfile *objfile;
+{
+ qsort (objfile->msymbols, objfile->minimal_symbol_count,
+ sizeof (struct minimal_symbol), compare_minimal_symbols);
+}
+
+/* Check if PC is in a shared library trampoline code stub.
+ Return minimal symbol for the trampoline entry or NULL if PC is not
+ in a trampoline code stub. */
+
+struct minimal_symbol *
+lookup_solib_trampoline_symbol_by_pc (pc)
+ CORE_ADDR pc;
+{
+ struct minimal_symbol *msymbol = lookup_minimal_symbol_by_pc (pc);
+
+ if (msymbol != NULL && MSYMBOL_TYPE (msymbol) == mst_solib_trampoline)
+ return msymbol;
+ return NULL;
+}
+
+/* If PC is in a shared library trampoline code stub, return the
+ address of the `real' function belonging to the stub.
+ Return 0 if PC is not in a trampoline code stub or if the real
+ function is not found in the minimal symbol table.
+
+ We may fail to find the right function if a function with the
+ same name is defined in more than one shared library, but this
+ is considered bad programming style. We could return 0 if we find
+ a duplicate function in case this matters someday. */
+
+CORE_ADDR
+find_solib_trampoline_target (pc)
+ CORE_ADDR pc;
+{
+ struct objfile *objfile;
+ struct minimal_symbol *msymbol;
+ struct minimal_symbol *tsymbol = lookup_solib_trampoline_symbol_by_pc (pc);
+
+ if (tsymbol != NULL)
+ {
+ ALL_MSYMBOLS (objfile, msymbol)
+ {
+ if (MSYMBOL_TYPE (msymbol) == mst_text
+ && STREQ (SYMBOL_NAME (msymbol), SYMBOL_NAME (tsymbol)))
+ return SYMBOL_VALUE_ADDRESS (msymbol);
+ }
+ }
+ return 0;
+}
+
diff --git a/gdb/mips-nat.c b/gdb/mips-nat.c
new file mode 100644
index 00000000000..9f5717475e1
--- /dev/null
+++ b/gdb/mips-nat.c
@@ -0,0 +1,244 @@
+/* Low level DECstation interface to ptrace, for GDB when running native.
+ Copyright 1988, 1989, 1991, 1992, 1995 Free Software Foundation, Inc.
+ Contributed by Alessandro Forin(af@cs.cmu.edu) at CMU
+ and by Per Bothner(bothner@cs.wisc.edu) at U.Wisconsin.
+
+This file is part of GDB.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "inferior.h"
+#include "gdbcore.h"
+#include <sys/ptrace.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/user.h>
+#undef JB_S0
+#undef JB_S1
+#undef JB_S2
+#undef JB_S3
+#undef JB_S4
+#undef JB_S5
+#undef JB_S6
+#undef JB_S7
+#undef JB_SP
+#undef JB_S8
+#undef JB_PC
+#undef JB_SR
+#undef NJBREGS
+#include <setjmp.h> /* For JB_XXX. */
+
+/* Size of elements in jmpbuf */
+
+#define JB_ELEMENT_SIZE 4
+
+/* Map gdb internal register number to ptrace ``address''.
+ These ``addresses'' are defined in DECstation <sys/ptrace.h> */
+
+#define REGISTER_PTRACE_ADDR(regno) \
+ (regno < 32 ? GPR_BASE + regno \
+ : regno == PC_REGNUM ? PC \
+ : regno == CAUSE_REGNUM ? CAUSE \
+ : regno == HI_REGNUM ? MMHI \
+ : regno == LO_REGNUM ? MMLO \
+ : regno == FCRCS_REGNUM ? FPC_CSR \
+ : regno == FCRIR_REGNUM ? FPC_EIR \
+ : regno >= FP0_REGNUM ? FPR_BASE + (regno - FP0_REGNUM) \
+ : 0)
+
+static char zerobuf[MAX_REGISTER_RAW_SIZE] = {0};
+
+static void fetch_core_registers PARAMS ((char *, unsigned, int, CORE_ADDR));
+
+/* Get all registers from the inferior */
+
+void
+fetch_inferior_registers (regno)
+ int regno;
+{
+ register unsigned int regaddr;
+ char buf[MAX_REGISTER_RAW_SIZE];
+ register int i;
+
+ registers_fetched ();
+
+ for (regno = 1; regno < NUM_REGS; regno++)
+ {
+ regaddr = REGISTER_PTRACE_ADDR (regno);
+ for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (int))
+ {
+ *(int *) &buf[i] = ptrace (PT_READ_U, inferior_pid,
+ (PTRACE_ARG3_TYPE) regaddr, 0);
+ regaddr += sizeof (int);
+ }
+ supply_register (regno, buf);
+ }
+
+ supply_register (ZERO_REGNUM, zerobuf);
+ /* Frame ptr reg must appear to be 0; it is faked by stack handling code. */
+ supply_register (FP_REGNUM, zerobuf);
+}
+
+/* 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];
+
+ if (regno > 0)
+ {
+ if (regno == ZERO_REGNUM || regno == PS_REGNUM
+ || regno == BADVADDR_REGNUM || regno == CAUSE_REGNUM
+ || regno == FCRIR_REGNUM || regno == FP_REGNUM
+ || (regno >= FIRST_EMBED_REGNUM && regno <= LAST_EMBED_REGNUM))
+ return;
+ regaddr = REGISTER_PTRACE_ADDR (regno);
+ errno = 0;
+ ptrace (PT_WRITE_U, inferior_pid, (PTRACE_ARG3_TYPE) 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++)
+ store_inferior_registers (regno);
+ }
+}
+
+
+/* Figure out where the longjmp will land.
+ 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;
+{
+ CORE_ADDR jb_addr;
+ char buf[TARGET_PTR_BIT / TARGET_CHAR_BIT];
+
+ jb_addr = read_register (A0_REGNUM);
+
+ 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;
+}
+
+/* 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.
+ */
+
+static void
+fetch_core_registers (core_reg_sect, core_reg_size, which, reg_addr)
+ char *core_reg_sect;
+ unsigned core_reg_size;
+ int which;
+ CORE_ADDR 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)
+#ifdef KERNEL_U_ADDR
+ reg_ptr -= KERNEL_U_ADDR;
+#else
+ error ("Old mips core file can't be processed on this machine.");
+#endif
+
+ 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.", REGISTER_NAME (bad_reg));
+ }
+ supply_register (ZERO_REGNUM, zerobuf);
+ /* Frame ptr reg must appear to be 0; it is faked by stack handling code. */
+ supply_register (FP_REGNUM, zerobuf);
+}
+
+/* Return the address in the core dump or inferior of register REGNO.
+ BLOCKEND is the address of the end of the user structure. */
+
+CORE_ADDR
+register_addr (regno, blockend)
+ int regno;
+ CORE_ADDR blockend;
+{
+ CORE_ADDR addr;
+
+ if (regno < 0 || regno >= NUM_REGS)
+ error ("Invalid register number %d.", regno);
+
+ REGISTER_U_ADDR (addr, blockend, regno);
+
+ return addr;
+}
+
+
+/* Register that we are able to handle mips core file formats.
+ FIXME: is this really bfd_target_unknown_flavour? */
+
+static struct core_fns mips_core_fns =
+{
+ bfd_target_unknown_flavour,
+ fetch_core_registers,
+ NULL
+};
+
+void
+_initialize_core_mips ()
+{
+ add_core_fns (&mips_core_fns);
+}
diff --git a/gdb/mips-tdep.c b/gdb/mips-tdep.c
new file mode 100644
index 00000000000..e4aa2bb297b
--- /dev/null
+++ b/gdb/mips-tdep.c
@@ -0,0 +1,3259 @@
+/* Target-dependent code for the MIPS architecture, for GDB, the GNU Debugger.
+ Copyright 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998
+ Free Software Foundation, Inc.
+ Contributed by Alessandro Forin(af@cs.cmu.edu) at CMU
+ and by Per Bothner(bothner@cs.wisc.edu) at U.Wisconsin.
+
+This file is part of GDB.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "gdb_string.h"
+#include "frame.h"
+#include "inferior.h"
+#include "symtab.h"
+#include "value.h"
+#include "gdbcmd.h"
+#include "language.h"
+#include "gdbcore.h"
+#include "symfile.h"
+#include "objfiles.h"
+#include "gdbtypes.h"
+#include "target.h"
+
+#include "opcode/mips.h"
+
+/* Some MIPS boards don't support floating point, so we permit the
+ user to turn it off. */
+
+enum mips_fpu_type
+{
+ MIPS_FPU_DOUBLE, /* Full double precision floating point. */
+ MIPS_FPU_SINGLE, /* Single precision floating point (R4650). */
+ MIPS_FPU_NONE /* No floating point. */
+};
+
+#ifndef MIPS_DEFAULT_FPU_TYPE
+#define MIPS_DEFAULT_FPU_TYPE MIPS_FPU_DOUBLE
+#endif
+static int mips_fpu_type_auto = 1;
+static enum mips_fpu_type mips_fpu_type = MIPS_DEFAULT_FPU_TYPE;
+#define MIPS_FPU_TYPE mips_fpu_type
+
+
+#define VM_MIN_ADDRESS (CORE_ADDR)0x400000
+
+/* Do not use "TARGET_IS_MIPS64" to test the size of floating point registers */
+#define FP_REGISTER_DOUBLE (REGISTER_VIRTUAL_SIZE(FP0_REGNUM) == 8)
+
+#if 0
+static int mips_in_lenient_prologue PARAMS ((CORE_ADDR, CORE_ADDR));
+#endif
+
+int gdb_print_insn_mips PARAMS ((bfd_vma, disassemble_info *));
+
+static void mips_print_register PARAMS ((int, int));
+
+static mips_extra_func_info_t
+heuristic_proc_desc PARAMS ((CORE_ADDR, CORE_ADDR, struct frame_info *));
+
+static CORE_ADDR heuristic_proc_start PARAMS ((CORE_ADDR));
+
+static CORE_ADDR read_next_frame_reg PARAMS ((struct frame_info *, int));
+
+void mips_set_processor_type_command PARAMS ((char *, int));
+
+int mips_set_processor_type PARAMS ((char *));
+
+static void mips_show_processor_type_command PARAMS ((char *, int));
+
+static void reinit_frame_cache_sfunc PARAMS ((char *, int,
+ struct cmd_list_element *));
+
+static mips_extra_func_info_t
+ find_proc_desc PARAMS ((CORE_ADDR pc, struct frame_info *next_frame));
+
+static CORE_ADDR after_prologue PARAMS ((CORE_ADDR pc,
+ mips_extra_func_info_t proc_desc));
+
+/* This value is the model of MIPS in use. It is derived from the value
+ of the PrID register. */
+
+char *mips_processor_type;
+
+char *tmp_mips_processor_type;
+
+/* A set of original names, to be used when restoring back to generic
+ registers from a specific set. */
+
+char *mips_generic_reg_names[] = REGISTER_NAMES;
+
+/* Names of IDT R3041 registers. */
+
+char *mips_r3041_reg_names[] = {
+ "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3",
+ "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
+ "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
+ "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra",
+ "sr", "lo", "hi", "bad", "cause","pc",
+ "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
+ "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
+ "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
+ "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
+ "fsr", "fir", "fp", "",
+ "", "", "bus", "ccfg", "", "", "", "",
+ "", "", "port", "cmp", "", "", "epc", "prid",
+};
+
+/* Names of IDT R3051 registers. */
+
+char *mips_r3051_reg_names[] = {
+ "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3",
+ "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
+ "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
+ "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra",
+ "sr", "lo", "hi", "bad", "cause","pc",
+ "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
+ "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
+ "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
+ "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
+ "fsr", "fir", "fp", "",
+ "inx", "rand", "elo", "", "ctxt", "", "", "",
+ "", "", "ehi", "", "", "", "epc", "prid",
+};
+
+/* Names of IDT R3081 registers. */
+
+char *mips_r3081_reg_names[] = {
+ "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3",
+ "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
+ "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
+ "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra",
+ "sr", "lo", "hi", "bad", "cause","pc",
+ "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
+ "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
+ "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
+ "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
+ "fsr", "fir", "fp", "",
+ "inx", "rand", "elo", "cfg", "ctxt", "", "", "",
+ "", "", "ehi", "", "", "", "epc", "prid",
+};
+
+/* Names of LSI 33k registers. */
+
+char *mips_lsi33k_reg_names[] = {
+ "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3",
+ "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
+ "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
+ "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra",
+ "epc", "hi", "lo", "sr", "cause","badvaddr",
+ "dcic", "bpc", "bda", "", "", "", "", "",
+ "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "",
+ "", "", "", "",
+ "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "",
+};
+
+struct {
+ char *name;
+ char **regnames;
+} mips_processor_type_table[] = {
+ { "generic", mips_generic_reg_names },
+ { "r3041", mips_r3041_reg_names },
+ { "r3051", mips_r3051_reg_names },
+ { "r3071", mips_r3081_reg_names },
+ { "r3081", mips_r3081_reg_names },
+ { "lsi33k", mips_lsi33k_reg_names },
+ { NULL, NULL }
+};
+
+/* Table to translate MIPS16 register field to actual register number. */
+static int mips16_to_32_reg[8] = { 16, 17, 2, 3, 4, 5, 6, 7 };
+
+/* Heuristic_proc_start may hunt through the text section for a long
+ time across a 2400 baud serial line. Allows the user to limit this
+ search. */
+
+static unsigned int heuristic_fence_post = 0;
+
+#define PROC_LOW_ADDR(proc) ((proc)->pdr.adr) /* least address */
+#define PROC_HIGH_ADDR(proc) ((proc)->high_addr) /* upper address bound */
+#define PROC_FRAME_OFFSET(proc) ((proc)->pdr.frameoffset)
+#define PROC_FRAME_REG(proc) ((proc)->pdr.framereg)
+#define PROC_FRAME_ADJUST(proc) ((proc)->frame_adjust)
+#define PROC_REG_MASK(proc) ((proc)->pdr.regmask)
+#define PROC_FREG_MASK(proc) ((proc)->pdr.fregmask)
+#define PROC_REG_OFFSET(proc) ((proc)->pdr.regoffset)
+#define PROC_FREG_OFFSET(proc) ((proc)->pdr.fregoffset)
+#define PROC_PC_REG(proc) ((proc)->pdr.pcreg)
+#define PROC_SYMBOL(proc) (*(struct symbol**)&(proc)->pdr.isym)
+#define _PROC_MAGIC_ 0x0F0F0F0F
+#define PROC_DESC_IS_DUMMY(proc) ((proc)->pdr.isym == _PROC_MAGIC_)
+#define SET_PROC_DESC_IS_DUMMY(proc) ((proc)->pdr.isym = _PROC_MAGIC_)
+
+struct linked_proc_info
+{
+ struct mips_extra_func_info info;
+ struct linked_proc_info *next;
+} *linked_proc_desc_table = NULL;
+
+
+/* Should the upper word of 64-bit addresses be zeroed? */
+static int mask_address_p = 1;
+
+/* Should call_function allocate stack space for a struct return? */
+int
+mips_use_struct_convention (gcc_p, type)
+ int gcc_p;
+ struct type *type;
+{
+ if (MIPS_EABI)
+ return (TYPE_LENGTH (type) > 2 * MIPS_REGSIZE);
+ else
+ return 1; /* Structures are returned by ref in extra arg0 */
+}
+
+/* Tell if the program counter value in MEMADDR is in a MIPS16 function. */
+
+static int
+pc_is_mips16 (bfd_vma memaddr)
+{
+ struct minimal_symbol *sym;
+
+ /* If bit 0 of the address is set, assume this is a MIPS16 address. */
+ if (IS_MIPS16_ADDR (memaddr))
+ return 1;
+
+ /* A flag indicating that this is a MIPS16 function is stored by elfread.c in
+ the high bit of the info field. Use this to decide if the function is
+ MIPS16 or normal MIPS. */
+ sym = lookup_minimal_symbol_by_pc (memaddr);
+ if (sym)
+ return MSYMBOL_IS_SPECIAL (sym);
+ else
+ return 0;
+}
+
+
+/* This returns the PC of the first inst after the prologue. If we can't
+ find the prologue, then return 0. */
+
+static CORE_ADDR
+after_prologue (pc, proc_desc)
+ CORE_ADDR pc;
+ mips_extra_func_info_t proc_desc;
+{
+ struct symtab_and_line sal;
+ CORE_ADDR func_addr, func_end;
+
+ if (!proc_desc)
+ proc_desc = find_proc_desc (pc, NULL);
+
+ if (proc_desc)
+ {
+ /* If function is frameless, then we need to do it the hard way. I
+ strongly suspect that frameless always means prologueless... */
+ if (PROC_FRAME_REG (proc_desc) == SP_REGNUM
+ && PROC_FRAME_OFFSET (proc_desc) == 0)
+ return 0;
+ }
+
+ if (!find_pc_partial_function (pc, NULL, &func_addr, &func_end))
+ return 0; /* Unknown */
+
+ sal = find_pc_line (func_addr, 0);
+
+ if (sal.end < func_end)
+ return sal.end;
+
+ /* The line after the prologue is after the end of the function. In this
+ case, tell the caller to find the prologue the hard way. */
+
+ return 0;
+}
+
+/* Decode a MIPS32 instruction that saves a register in the stack, and
+ set the appropriate bit in the general register mask or float register mask
+ to indicate which register is saved. This is a helper function
+ for mips_find_saved_regs. */
+
+static void
+mips32_decode_reg_save (inst, gen_mask, float_mask)
+ t_inst inst;
+ unsigned long *gen_mask;
+ unsigned long *float_mask;
+{
+ int reg;
+
+ if ((inst & 0xffe00000) == 0xafa00000 /* sw reg,n($sp) */
+ || (inst & 0xffe00000) == 0xafc00000 /* sw reg,n($r30) */
+ || (inst & 0xffe00000) == 0xffa00000) /* sd reg,n($sp) */
+ {
+ /* It might be possible to use the instruction to
+ find the offset, rather than the code below which
+ is based on things being in a certain order in the
+ frame, but figuring out what the instruction's offset
+ is relative to might be a little tricky. */
+ reg = (inst & 0x001f0000) >> 16;
+ *gen_mask |= (1 << reg);
+ }
+ else if ((inst & 0xffe00000) == 0xe7a00000 /* swc1 freg,n($sp) */
+ || (inst & 0xffe00000) == 0xe7c00000 /* swc1 freg,n($r30) */
+ || (inst & 0xffe00000) == 0xf7a00000)/* sdc1 freg,n($sp) */
+
+ {
+ reg = ((inst & 0x001f0000) >> 16);
+ *float_mask |= (1 << reg);
+ }
+}
+
+/* Decode a MIPS16 instruction that saves a register in the stack, and
+ set the appropriate bit in the general register or float register mask
+ to indicate which register is saved. This is a helper function
+ for mips_find_saved_regs. */
+
+static void
+mips16_decode_reg_save (inst, gen_mask)
+ t_inst inst;
+ unsigned long *gen_mask;
+{
+ if ((inst & 0xf800) == 0xd000) /* sw reg,n($sp) */
+ {
+ int reg = mips16_to_32_reg[(inst & 0x700) >> 8];
+ *gen_mask |= (1 << reg);
+ }
+ else if ((inst & 0xff00) == 0xf900) /* sd reg,n($sp) */
+ {
+ int reg = mips16_to_32_reg[(inst & 0xe0) >> 5];
+ *gen_mask |= (1 << reg);
+ }
+ else if ((inst & 0xff00) == 0x6200 /* sw $ra,n($sp) */
+ || (inst & 0xff00) == 0xfa00) /* sd $ra,n($sp) */
+ *gen_mask |= (1 << RA_REGNUM);
+}
+
+
+/* Fetch and return instruction from the specified location. If the PC
+ is odd, assume it's a MIPS16 instruction; otherwise MIPS32. */
+
+static t_inst
+mips_fetch_instruction (addr)
+ CORE_ADDR addr;
+{
+ char buf[MIPS_INSTLEN];
+ int instlen;
+ int status;
+
+ if (pc_is_mips16 (addr))
+ {
+ instlen = MIPS16_INSTLEN;
+ addr = UNMAKE_MIPS16_ADDR (addr);
+ }
+ else
+ instlen = MIPS_INSTLEN;
+ status = read_memory_nobpt (addr, buf, instlen);
+ if (status)
+ memory_error (status, addr);
+ return extract_unsigned_integer (buf, instlen);
+}
+
+
+/* These the fields of 32 bit mips instructions */
+#define mips32_op(x) (x >> 25)
+#define itype_op(x) (x >> 25)
+#define itype_rs(x) ((x >> 21)& 0x1f)
+#define itype_rt(x) ((x >> 16) & 0x1f)
+#define itype_immediate(x) ( x & 0xffff)
+
+#define jtype_op(x) (x >> 25)
+#define jtype_target(x) ( x & 0x03fffff)
+
+#define rtype_op(x) (x >>25)
+#define rtype_rs(x) ((x>>21) & 0x1f)
+#define rtype_rt(x) ((x>>16) & 0x1f)
+#define rtype_rd(x) ((x>>11) & 0x1f)
+#define rtype_shamt(x) ((x>>6) & 0x1f)
+#define rtype_funct(x) (x & 0x3f )
+
+static CORE_ADDR
+mips32_relative_offset(unsigned long inst)
+{ long x ;
+ x = itype_immediate(inst) ;
+ if (x & 0x8000) /* sign bit set */
+ {
+ x |= 0xffff0000 ; /* sign extension */
+ }
+ x = x << 2 ;
+ return x ;
+}
+
+/* Determine whate to set a single step breakpoint while considering
+ branch prediction */
+CORE_ADDR
+mips32_next_pc(CORE_ADDR pc)
+{
+ unsigned long inst ;
+ int op ;
+ inst = mips_fetch_instruction(pc) ;
+ if ((inst & 0xe0000000) != 0) /* Not a special, junp or branch instruction */
+ { if ((inst >> 27) == 5) /* BEQL BNEZ BLEZL BGTZE , bits 0101xx */
+ { op = ((inst >> 25) & 0x03) ;
+ switch (op)
+ {
+ case 0 : goto equal_branch ; /* BEQL */
+ case 1 : goto neq_branch ; /* BNEZ */
+ case 2 : goto less_branch ; /* BLEZ */
+ case 3 : goto greater_branch ; /* BGTZ */
+ default : pc += 4 ;
+ }
+ }
+ else pc += 4 ; /* Not a branch, next instruction is easy */
+ }
+ else
+ { /* This gets way messy */
+
+ /* Further subdivide into SPECIAL, REGIMM and other */
+ switch (op = ((inst >> 26) & 0x07)) /* extract bits 28,27,26 */
+ {
+ case 0 : /* SPECIAL */
+ op = rtype_funct(inst) ;
+ switch (op)
+ {
+ case 8 : /* JR */
+ case 9 : /* JALR */
+ pc = read_register(rtype_rs(inst)) ; /* Set PC to that address */
+ break ;
+ default: pc += 4 ;
+ }
+
+ break ; /* end special */
+ case 1 : /* REGIMM */
+ {
+ op = jtype_op(inst) ; /* branch condition */
+ switch (jtype_op(inst))
+ {
+ case 0 : /* BLTZ */
+ case 2 : /* BLTXL */
+ case 16 : /* BLTZALL */
+ case 18 : /* BLTZALL */
+ less_branch:
+ if (read_register(itype_rs(inst)) < 0)
+ pc += mips32_relative_offset(inst) + 4 ;
+ else pc += 8 ; /* after the delay slot */
+ break ;
+ case 1 : /* GEZ */
+ case 3 : /* BGEZL */
+ case 17 : /* BGEZAL */
+ case 19 : /* BGEZALL */
+ greater_equal_branch:
+ if (read_register(itype_rs(inst)) >= 0)
+ pc += mips32_relative_offset(inst) + 4 ;
+ else pc += 8 ; /* after the delay slot */
+ break ;
+ /* All of the other intructions in the REGIMM catagory */
+ default: pc += 4 ;
+ }
+ }
+ break ; /* end REGIMM */
+ case 2 : /* J */
+ case 3 : /* JAL */
+ { unsigned long reg ;
+ reg = jtype_target(inst) << 2 ;
+ pc = reg + ((pc+4) & 0xf0000000) ;
+ /* Whats this mysterious 0xf000000 adjustment ??? */
+ }
+ break ;
+ /* FIXME case JALX :*/
+ { unsigned long reg ;
+ reg = jtype_target(inst) << 2 ;
+ pc = reg + ((pc+4) & 0xf0000000) + 1 ; /* yes, +1 */
+ /* Add 1 to indicate 16 bit mode - Invert ISA mode */
+ }
+ break ; /* The new PC will be alternate mode */
+ case 4 : /* BEQ , BEQL */
+ equal_branch :
+ if (read_register(itype_rs(inst)) ==
+ read_register(itype_rt(inst)))
+ pc += mips32_relative_offset(inst) + 4 ;
+ else pc += 8 ;
+ break ;
+ case 5 : /* BNE , BNEL */
+ neq_branch :
+ if (read_register(itype_rs(inst)) !=
+ read_register(itype_rs(inst)))
+ pc += mips32_relative_offset(inst) + 4 ;
+ else pc += 8 ;
+ break ;
+ case 6 : /* BLEZ , BLEZL */
+ less_zero_branch:
+ if (read_register(itype_rs(inst) <= 0))
+ pc += mips32_relative_offset(inst) + 4 ;
+ else pc += 8 ;
+ break ;
+ case 7 :
+ greater_branch : /* BGTZ BGTZL */
+ if (read_register(itype_rs(inst) > 0))
+ pc += mips32_relative_offset(inst) + 4 ;
+ else pc += 8 ;
+ break ;
+ default : pc += 8 ;
+ } /* switch */
+ } /* else */
+ return pc ;
+} /* mips32_next_pc */
+
+/* Decoding the next place to set a breakpoint is irregular for the
+ mips 16 variant, but fortunatly, there fewer instructions. We have to cope
+ ith extensions for 16 bit instructions and a pair of actual 32 bit instructions.
+ We dont want to set a single step instruction on the extend instruction
+ either.
+ */
+
+/* Lots of mips16 instruction formats */
+/* Predicting jumps requires itype,ritype,i8type
+ and their extensions extItype,extritype,extI8type
+ */
+enum mips16_inst_fmts
+{
+ itype, /* 0 immediate 5,10 */
+ ritype, /* 1 5,3,8 */
+ rrtype, /* 2 5,3,3,5 */
+ rritype, /* 3 5,3,3,5 */
+ rrrtype, /* 4 5,3,3,3,2 */
+ rriatype, /* 5 5,3,3,1,4 */
+ shifttype, /* 6 5,3,3,3,2 */
+ i8type, /* 7 5,3,8 */
+ i8movtype, /* 8 5,3,3,5 */
+ i8mov32rtype, /* 9 5,3,5,3 */
+ i64type, /* 10 5,3,8 */
+ ri64type, /* 11 5,3,3,5 */
+ jalxtype, /* 12 5,1,5,5,16 - a 32 bit instruction */
+ exiItype, /* 13 5,6,5,5,1,1,1,1,1,1,5 */
+ extRitype, /* 14 5,6,5,5,3,1,1,1,5 */
+ extRRItype, /* 15 5,5,5,5,3,3,5 */
+ extRRIAtype, /* 16 5,7,4,5,3,3,1,4 */
+ EXTshifttype, /* 17 5,5,1,1,1,1,1,1,5,3,3,1,1,1,2 */
+ extI8type, /* 18 5,6,5,5,3,1,1,1,5 */
+ extI64type, /* 19 5,6,5,5,3,1,1,1,5 */
+ extRi64type, /* 20 5,6,5,5,3,3,5 */
+ extshift64type /* 21 5,5,1,1,1,1,1,1,5,1,1,1,3,5 */
+} ;
+/* I am heaping all the fields of the formats into one structure and then,
+ only the fields which are involved in instruction extension */
+struct upk_mips16
+{
+ unsigned short inst ;
+ enum mips16_inst_fmts fmt ;
+ unsigned long offset ;
+ unsigned int regx ; /* Function in i8 type */
+ unsigned int regy ;
+} ;
+
+
+
+static void print_unpack(char * comment,
+ struct upk_mips16 * u)
+{
+ printf("%s %04x ,f(%d) off(%08x) (x(%x) y(%x)\n",
+ comment,u->inst,u->fmt,u->offset,u->regx,u->regy) ;
+}
+
+/* The EXT-I, EXT-ri nad EXT-I8 instructions all have the same
+ format for the bits which make up the immediatate extension.
+ */
+static unsigned long
+extended_offset(unsigned long extension)
+{
+ unsigned long value ;
+ value = (extension >> 21) & 0x3f ; /* * extract 15:11 */
+ value = value << 6 ;
+ value |= (extension >> 16) & 0x1f ; /* extrace 10:5 */
+ value = value << 5 ;
+ value |= extension & 0x01f ; /* extract 4:0 */
+ return value ;
+}
+
+/* Only call this function if you know that this is an extendable
+ instruction, It wont malfunction, but why make excess remote memory references?
+ If the immediate operands get sign extended or somthing, do it after
+ the extension is performed.
+ */
+/* FIXME: Every one of these cases needs to worry about sign extension
+ when the offset is to be used in relative addressing */
+
+
+static unsigned short fetch_mips_16(CORE_ADDR pc)
+{
+ char buf[8] ;
+ pc &= 0xfffffffe ; /* clear the low order bit */
+ target_read_memory(pc,buf,2) ;
+ return extract_unsigned_integer(buf,2) ;
+}
+
+static void
+unpack_mips16(CORE_ADDR pc,
+ struct upk_mips16 * upk)
+{
+ CORE_ADDR extpc ;
+ unsigned long extension ;
+ int extended ;
+ extpc = (pc - 4) & ~0x01 ; /* Extensions are 32 bit instructions */
+ /* Decrement to previous address and loose the 16bit mode flag */
+ /* return if the instruction was extendable, but not actually extended */
+ extended = ((mips32_op(extension) == 30) ? 1 : 0) ;
+ if (extended) { extension = mips_fetch_instruction(extpc) ;}
+ switch (upk->fmt)
+ {
+ case itype :
+ {
+ unsigned long value ;
+ if (extended)
+ { value = extended_offset(extension) ;
+ value = value << 11 ; /* rom for the original value */
+ value |= upk->inst & 0x7ff ; /* eleven bits from instruction */
+ }
+ else
+ { value = upk->inst & 0x7ff ;
+ /* FIXME : Consider sign extension */
+ }
+ upk->offset = value ;
+ }
+ break ;
+ case ritype :
+ case i8type :
+ { /* A register identifier and an offset */
+ /* Most of the fields are the same as I type but the
+ immediate value is of a different length */
+ unsigned long value ;
+ if (extended)
+ {
+ value = extended_offset(extension) ;
+ value = value << 8 ; /* from the original instruction */
+ value |= upk->inst & 0xff ; /* eleven bits from instruction */
+ upk->regx = (extension >> 8) & 0x07 ; /* or i8 funct */
+ if (value & 0x4000) /* test the sign bit , bit 26 */
+ { value &= ~ 0x3fff ; /* remove the sign bit */
+ value = -value ;
+ }
+ }
+ else {
+ value = upk->inst & 0xff ; /* 8 bits */
+ upk->regx = (upk->inst >> 8) & 0x07 ; /* or i8 funct */
+ /* FIXME: Do sign extension , this format needs it */
+ if (value & 0x80) /* THIS CONFUSES ME */
+ { value &= 0xef ; /* remove the sign bit */
+ value = -value ;
+ }
+
+ }
+ upk->offset = value ;
+ break ;
+ }
+ case jalxtype :
+ {
+ unsigned long value ;
+ unsigned short nexthalf ;
+ value = ((upk->inst & 0x1f) << 5) | ((upk->inst >> 5) & 0x1f) ;
+ value = value << 16 ;
+ nexthalf = mips_fetch_instruction(pc+2) ; /* low bit still set */
+ value |= nexthalf ;
+ upk->offset = value ;
+ break ;
+ }
+ default:
+ printf_filtered("Decoding unimplemented instruction format type\n") ;
+ break ;
+ }
+ /* print_unpack("UPK",upk) ; */
+}
+
+
+#define mips16_op(x) (x >> 11)
+
+/* This is a map of the opcodes which ae known to perform branches */
+static unsigned char map16[32] =
+{ 0,0,1,1,1,1,0,0,
+ 0,0,0,0,1,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,1,1,0
+} ;
+
+static CORE_ADDR add_offset_16(CORE_ADDR pc, int offset)
+{
+ return ((offset << 2) | ((pc + 2) & (0xf0000000))) ;
+
+}
+
+
+
+static struct upk_mips16 upk ;
+
+CORE_ADDR mips16_next_pc(CORE_ADDR pc)
+{
+ int op ;
+ t_inst inst ;
+ /* inst = mips_fetch_instruction(pc) ; - This doesnt always work */
+ inst = fetch_mips_16(pc) ;
+ upk.inst = inst ;
+ op = mips16_op(upk.inst) ;
+ if (map16[op])
+ {
+ int reg ;
+ switch (op)
+ {
+ case 2 : /* Branch */
+ upk.fmt = itype ;
+ unpack_mips16(pc,&upk) ;
+ { long offset ;
+ offset = upk.offset ;
+ if (offset & 0x800)
+ { offset &= 0xeff ;
+ offset = - offset ;
+ }
+ pc += (offset << 1) + 2 ;
+ }
+ break ;
+ case 3 : /* JAL , JALX - Watch out, these are 32 bit instruction*/
+ upk.fmt = jalxtype ;
+ unpack_mips16(pc,&upk) ;
+ pc = add_offset_16(pc,upk.offset) ;
+ if ((upk.inst >> 10) & 0x01) /* Exchange mode */
+ pc = pc & ~ 0x01 ; /* Clear low bit, indicate 32 bit mode */
+ else pc |= 0x01 ;
+ break ;
+ case 4 : /* beqz */
+ upk.fmt = ritype ;
+ unpack_mips16(pc,&upk) ;
+ reg = read_register(upk.regx) ;
+ if (reg == 0)
+ pc += (upk.offset << 1) + 2 ;
+ else pc += 2 ;
+ break ;
+ case 5 : /* bnez */
+ upk.fmt = ritype ;
+ unpack_mips16(pc,&upk) ;
+ reg = read_register(upk.regx) ;
+ if (reg != 0)
+ pc += (upk.offset << 1) + 2 ;
+ else pc += 2 ;
+ break ;
+ case 12 : /* I8 Formats btez btnez */
+ upk.fmt = i8type ;
+ unpack_mips16(pc,&upk) ;
+ /* upk.regx contains the opcode */
+ reg = read_register(24) ; /* Test register is 24 */
+ if (((upk.regx == 0) && (reg == 0)) /* BTEZ */
+ || ((upk.regx == 1 ) && (reg != 0))) /* BTNEZ */
+ /* pc = add_offset_16(pc,upk.offset) ; */
+ pc += (upk.offset << 1) + 2 ;
+ else pc += 2 ;
+ break ;
+ case 29 : /* RR Formats JR, JALR, JALR-RA */
+ upk.fmt = rrtype ;
+ op = upk.inst & 0x1f ;
+ if (op == 0)
+ {
+ upk.regx = (upk.inst >> 8) & 0x07 ;
+ upk.regy = (upk.inst >> 5) & 0x07 ;
+ switch (upk.regy)
+ {
+ case 0 : reg = upk.regx ; break ;
+ case 1 : reg = 31 ; break ; /* Function return instruction*/
+ case 2 : reg = upk.regx ; break ;
+ default: reg = 31 ; break ; /* BOGUS Guess */
+ }
+ pc = read_register(reg) ;
+ }
+ else pc += 2 ;
+ break ;
+ case 30 : /* This is an extend instruction */
+ pc += 4 ; /* Dont be setting breakpints on the second half */
+ break ;
+ default :
+ printf("Filtered - next PC probably incorrrect due to jump inst\n");
+ pc += 2 ;
+ break ;
+ }
+ }
+ else pc+= 2 ; /* just a good old instruction */
+ /* See if we CAN actually break on the next instruction */
+ /* printf("NXTm16PC %08x\n",(unsigned long)pc) ; */
+ return pc ;
+} /* mips16_next_pc */
+
+/* The mips_next_pc function supports single_tep when the remote target monitor or
+ stub is not developed enough to so a single_step.
+ It works by decoding the current instruction and predicting where a branch
+ will go. This isnt hard because all the data is available.
+ The MIPS32 and MIPS16 variants are quite different
+ */
+CORE_ADDR mips_next_pc(CORE_ADDR pc)
+{
+ t_inst inst ;
+ /* inst = mips_fetch_instruction(pc) ; */
+ /* if (pc_is_mips16) <----- This is failing */
+ if (pc & 0x01)
+ return mips16_next_pc(pc) ;
+ else return mips32_next_pc(pc) ;
+} /* mips_next_pc */
+
+/* Guaranteed to set fci->saved_regs to some values (it never leaves it
+ NULL). */
+
+void
+mips_find_saved_regs (fci)
+ struct frame_info *fci;
+{
+ int ireg;
+ CORE_ADDR reg_position;
+ /* r0 bit means kernel trap */
+ int kernel_trap;
+ /* What registers have been saved? Bitmasks. */
+ unsigned long gen_mask, float_mask;
+ mips_extra_func_info_t proc_desc;
+ t_inst inst;
+
+ frame_saved_regs_zalloc (fci);
+
+ /* If it is the frame for sigtramp, the saved registers are located
+ in a sigcontext structure somewhere on the stack.
+ If the stack layout for sigtramp changes we might have to change these
+ constants and the companion fixup_sigtramp in mdebugread.c */
+#ifndef SIGFRAME_BASE
+/* To satisfy alignment restrictions, sigcontext is located 4 bytes
+ above the sigtramp frame. */
+#define SIGFRAME_BASE MIPS_REGSIZE
+/* FIXME! Are these correct?? */
+#define SIGFRAME_PC_OFF (SIGFRAME_BASE + 2 * MIPS_REGSIZE)
+#define SIGFRAME_REGSAVE_OFF (SIGFRAME_BASE + 3 * MIPS_REGSIZE)
+#define SIGFRAME_FPREGSAVE_OFF \
+ (SIGFRAME_REGSAVE_OFF + MIPS_NUMREGS * MIPS_REGSIZE + 3 * MIPS_REGSIZE)
+#endif
+#ifndef SIGFRAME_REG_SIZE
+/* FIXME! Is this correct?? */
+#define SIGFRAME_REG_SIZE MIPS_REGSIZE
+#endif
+ if (fci->signal_handler_caller)
+ {
+ for (ireg = 0; ireg < MIPS_NUMREGS; ireg++)
+ {
+ reg_position = fci->frame + SIGFRAME_REGSAVE_OFF
+ + ireg * SIGFRAME_REG_SIZE;
+ fci->saved_regs[ireg] = reg_position;
+ }
+ for (ireg = 0; ireg < MIPS_NUMREGS; ireg++)
+ {
+ reg_position = fci->frame + SIGFRAME_FPREGSAVE_OFF
+ + ireg * SIGFRAME_REG_SIZE;
+ fci->saved_regs[FP0_REGNUM + ireg] = reg_position;
+ }
+ fci->saved_regs[PC_REGNUM] = fci->frame + SIGFRAME_PC_OFF;
+ return;
+ }
+
+ proc_desc = fci->proc_desc;
+ if (proc_desc == NULL)
+ /* I'm not sure how/whether this can happen. Normally when we can't
+ find a proc_desc, we "synthesize" one using heuristic_proc_desc
+ and set the saved_regs right away. */
+ return;
+
+ kernel_trap = PROC_REG_MASK(proc_desc) & 1;
+ gen_mask = kernel_trap ? 0xFFFFFFFF : PROC_REG_MASK(proc_desc);
+ float_mask = kernel_trap ? 0xFFFFFFFF : PROC_FREG_MASK(proc_desc);
+
+ if (/* In any frame other than the innermost or a frame interrupted by
+ a signal, we assume that all registers have been saved.
+ This assumes that all register saves in a function happen before
+ the first function call. */
+ (fci->next == NULL || fci->next->signal_handler_caller)
+
+ /* In a dummy frame we know exactly where things are saved. */
+ && !PROC_DESC_IS_DUMMY (proc_desc)
+
+ /* Don't bother unless we are inside a function prologue. Outside the
+ prologue, we know where everything is. */
+
+ && in_prologue (fci->pc, PROC_LOW_ADDR (proc_desc))
+
+ /* Not sure exactly what kernel_trap means, but if it means
+ the kernel saves the registers without a prologue doing it,
+ we better not examine the prologue to see whether registers
+ have been saved yet. */
+ && !kernel_trap)
+ {
+ /* We need to figure out whether the registers that the proc_desc
+ claims are saved have been saved yet. */
+
+ CORE_ADDR addr;
+
+ /* Bitmasks; set if we have found a save for the register. */
+ unsigned long gen_save_found = 0;
+ unsigned long float_save_found = 0;
+ int instlen;
+
+ /* If the address is odd, assume this is MIPS16 code. */
+ addr = PROC_LOW_ADDR (proc_desc);
+ instlen = pc_is_mips16 (addr) ? MIPS16_INSTLEN : MIPS_INSTLEN;
+
+ /* Scan through this function's instructions preceding the current
+ PC, and look for those that save registers. */
+ while (addr < fci->pc)
+ {
+ inst = mips_fetch_instruction (addr);
+ if (pc_is_mips16 (addr))
+ mips16_decode_reg_save (inst, &gen_save_found);
+ else
+ mips32_decode_reg_save (inst, &gen_save_found, &float_save_found);
+ addr += instlen;
+ }
+ gen_mask = gen_save_found;
+ float_mask = float_save_found;
+ }
+
+ /* Fill in the offsets for the registers which gen_mask says
+ were saved. */
+ reg_position = fci->frame + PROC_REG_OFFSET (proc_desc);
+ for (ireg= MIPS_NUMREGS-1; gen_mask; --ireg, gen_mask <<= 1)
+ if (gen_mask & 0x80000000)
+ {
+ fci->saved_regs[ireg] = reg_position;
+ reg_position -= MIPS_REGSIZE;
+ }
+
+ /* The MIPS16 entry instruction saves $s0 and $s1 in the reverse order
+ of that normally used by gcc. Therefore, we have to fetch the first
+ instruction of the function, and if it's an entry instruction that
+ saves $s0 or $s1, correct their saved addresses. */
+ if (pc_is_mips16 (PROC_LOW_ADDR (proc_desc)))
+ {
+ inst = mips_fetch_instruction (PROC_LOW_ADDR (proc_desc));
+ if ((inst & 0xf81f) == 0xe809 && (inst & 0x700) != 0x700) /* entry */
+ {
+ int reg;
+ int sreg_count = (inst >> 6) & 3;
+
+ /* Check if the ra register was pushed on the stack. */
+ reg_position = fci->frame + PROC_REG_OFFSET (proc_desc);
+ if (inst & 0x20)
+ reg_position -= MIPS_REGSIZE;
+
+ /* Check if the s0 and s1 registers were pushed on the stack. */
+ for (reg = 16; reg < sreg_count+16; reg++)
+ {
+ fci->saved_regs[reg] = reg_position;
+ reg_position -= MIPS_REGSIZE;
+ }
+ }
+ }
+
+ /* Fill in the offsets for the registers which float_mask says
+ were saved. */
+ reg_position = fci->frame + PROC_FREG_OFFSET (proc_desc);
+
+ /* The freg_offset points to where the first *double* register
+ is saved. So skip to the high-order word. */
+ if (! GDB_TARGET_IS_MIPS64)
+ reg_position += MIPS_REGSIZE;
+
+ /* Fill in the offsets for the float registers which float_mask says
+ were saved. */
+ for (ireg = MIPS_NUMREGS-1; float_mask; --ireg, float_mask <<= 1)
+ if (float_mask & 0x80000000)
+ {
+ fci->saved_regs[FP0_REGNUM+ireg] = reg_position;
+ reg_position -= MIPS_REGSIZE;
+ }
+
+ fci->saved_regs[PC_REGNUM] = fci->saved_regs[RA_REGNUM];
+}
+
+static CORE_ADDR
+read_next_frame_reg(fi, regno)
+ struct frame_info *fi;
+ int regno;
+{
+ for (; fi; fi = fi->next)
+ {
+ /* We have to get the saved sp from the sigcontext
+ if it is a signal handler frame. */
+ if (regno == SP_REGNUM && !fi->signal_handler_caller)
+ return fi->frame;
+ else
+ {
+ if (fi->saved_regs == NULL)
+ mips_find_saved_regs (fi);
+ if (fi->saved_regs[regno])
+ return read_memory_integer(fi->saved_regs[regno], MIPS_REGSIZE);
+ }
+ }
+ return read_register (regno);
+}
+
+/* mips_addr_bits_remove - remove useless address bits */
+
+CORE_ADDR
+mips_addr_bits_remove (addr)
+ CORE_ADDR addr;
+{
+#if GDB_TARGET_IS_MIPS64
+ if (mask_address_p && (addr >> 32 == (CORE_ADDR)0xffffffff))
+ {
+ /* This hack is a work-around for existing boards using PMON,
+ the simulator, and any other 64-bit targets that doesn't have
+ true 64-bit addressing. On these targets, the upper 32 bits
+ of addresses are ignored by the hardware. Thus, the PC or SP
+ are likely to have been sign extended to all 1s by instruction
+ sequences that load 32-bit addresses. For example, a typical
+ piece of code that loads an address is this:
+ lui $r2, <upper 16 bits>
+ ori $r2, <lower 16 bits>
+ But the lui sign-extends the value such that the upper 32 bits
+ may be all 1s. The workaround is simply to mask off these bits.
+ In the future, gcc may be changed to support true 64-bit
+ addressing, and this masking will have to be disabled. */
+ addr &= (CORE_ADDR)0xffffffff;
+ }
+#else
+ /* Even when GDB is configured for some 32-bit targets (e.g. mips-elf),
+ BFD is configured to handle 64-bit targets, so CORE_ADDR is 64 bits.
+ So we still have to mask off useless bits from addresses. */
+ addr &= (CORE_ADDR)0xffffffff;
+#endif
+
+ return addr;
+}
+
+void
+mips_init_frame_pc_first (fromleaf, prev)
+ int fromleaf;
+ struct frame_info *prev;
+{
+ CORE_ADDR pc, tmp;
+
+ pc = ((fromleaf) ? SAVED_PC_AFTER_CALL (prev->next) :
+ prev->next ? FRAME_SAVED_PC (prev->next) : read_pc ());
+ tmp = mips_skip_stub (pc);
+ prev->pc = tmp ? tmp : pc;
+}
+
+
+CORE_ADDR
+mips_frame_saved_pc(frame)
+ struct frame_info *frame;
+{
+ CORE_ADDR saved_pc;
+ mips_extra_func_info_t proc_desc = frame->proc_desc;
+ /* We have to get the saved pc from the sigcontext
+ if it is a signal handler frame. */
+ int pcreg = frame->signal_handler_caller ? PC_REGNUM
+ : (proc_desc ? PROC_PC_REG(proc_desc) : RA_REGNUM);
+
+ if (proc_desc && PROC_DESC_IS_DUMMY(proc_desc))
+ saved_pc = read_memory_integer(frame->frame - MIPS_REGSIZE, MIPS_REGSIZE);
+ else
+ saved_pc = read_next_frame_reg(frame, pcreg);
+
+ return ADDR_BITS_REMOVE (saved_pc);
+}
+
+static struct mips_extra_func_info temp_proc_desc;
+static struct frame_saved_regs temp_saved_regs;
+
+/* Set a register's saved stack address in temp_saved_regs. If an address
+ has already been set for this register, do nothing; this way we will
+ only recognize the first save of a given register in a function prologue.
+ This is a helper function for mips{16,32}_heuristic_proc_desc. */
+
+static void
+set_reg_offset (regno, offset)
+ int regno;
+ CORE_ADDR offset;
+{
+ if (temp_saved_regs.regs[regno] == 0)
+ temp_saved_regs.regs[regno] = offset;
+}
+
+
+/* Test whether the PC points to the return instruction at the
+ end of a function. */
+
+static int
+mips_about_to_return (pc)
+ CORE_ADDR pc;
+{
+ if (pc_is_mips16 (pc))
+ /* This mips16 case isn't necessarily reliable. Sometimes the compiler
+ generates a "jr $ra"; other times it generates code to load
+ the return address from the stack to an accessible register (such
+ as $a3), then a "jr" using that register. This second case
+ is almost impossible to distinguish from an indirect jump
+ used for switch statements, so we don't even try. */
+ return mips_fetch_instruction (pc) == 0xe820; /* jr $ra */
+ else
+ return mips_fetch_instruction (pc) == 0x3e00008; /* jr $ra */
+}
+
+
+/* This fencepost looks highly suspicious to me. Removing it also
+ seems suspicious as it could affect remote debugging across serial
+ lines. */
+
+static CORE_ADDR
+heuristic_proc_start (pc)
+ CORE_ADDR pc;
+{
+ CORE_ADDR start_pc;
+ CORE_ADDR fence;
+ int instlen;
+ int seen_adjsp = 0;
+
+ pc = ADDR_BITS_REMOVE (pc);
+ start_pc = pc;
+ fence = start_pc - heuristic_fence_post;
+ if (start_pc == 0) return 0;
+
+ if (heuristic_fence_post == UINT_MAX
+ || fence < VM_MIN_ADDRESS)
+ fence = VM_MIN_ADDRESS;
+
+ instlen = pc_is_mips16 (pc) ? MIPS16_INSTLEN : MIPS_INSTLEN;
+
+ /* search back for previous return */
+ for (start_pc -= instlen; ; start_pc -= instlen)
+ if (start_pc < fence)
+ {
+ /* It's not clear to me why we reach this point when
+ stop_soon_quietly, but with this test, at least we
+ don't print out warnings for every child forked (eg, on
+ decstation). 22apr93 rich@cygnus.com. */
+ if (!stop_soon_quietly)
+ {
+ static int blurb_printed = 0;
+
+ if (fence == VM_MIN_ADDRESS)
+ warning("Hit beginning of text section without finding");
+ else
+ warning("Hit heuristic-fence-post without finding");
+
+ warning("enclosing function for address 0x%s", paddr_nz (pc));
+ if (!blurb_printed)
+ {
+ printf_filtered ("\
+This warning occurs if you are debugging a function without any symbols\n\
+(for example, in a stripped executable). In that case, you may wish to\n\
+increase the size of the search with the `set heuristic-fence-post' command.\n\
+\n\
+Otherwise, you told GDB there was a function where there isn't one, or\n\
+(more likely) you have encountered a bug in GDB.\n");
+ blurb_printed = 1;
+ }
+ }
+
+ return 0;
+ }
+ else if (pc_is_mips16 (start_pc))
+ {
+ unsigned short inst;
+
+ /* On MIPS16, any one of the following is likely to be the
+ start of a function:
+ entry
+ addiu sp,-n
+ daddiu sp,-n
+ extend -n followed by 'addiu sp,+n' or 'daddiu sp,+n' */
+ inst = mips_fetch_instruction (start_pc);
+ if (((inst & 0xf81f) == 0xe809 && (inst & 0x700) != 0x700) /* entry */
+ || (inst & 0xff80) == 0x6380 /* addiu sp,-n */
+ || (inst & 0xff80) == 0xfb80 /* daddiu sp,-n */
+ || ((inst & 0xf810) == 0xf010 && seen_adjsp)) /* extend -n */
+ break;
+ else if ((inst & 0xff00) == 0x6300 /* addiu sp */
+ || (inst & 0xff00) == 0xfb00) /* daddiu sp */
+ seen_adjsp = 1;
+ else
+ seen_adjsp = 0;
+ }
+ else if (mips_about_to_return (start_pc))
+ {
+ start_pc += 2 * MIPS_INSTLEN; /* skip return, and its delay slot */
+ break;
+ }
+
+#if 0
+ /* skip nops (usually 1) 0 - is this */
+ while (start_pc < pc && read_memory_integer (start_pc, MIPS_INSTLEN) == 0)
+ start_pc += MIPS_INSTLEN;
+#endif
+ return start_pc;
+}
+
+/* Fetch the immediate value from a MIPS16 instruction.
+ If the previous instruction was an EXTEND, use it to extend
+ the upper bits of the immediate value. This is a helper function
+ for mips16_heuristic_proc_desc. */
+
+static int
+mips16_get_imm (prev_inst, inst, nbits, scale, is_signed)
+ unsigned short prev_inst; /* previous instruction */
+ unsigned short inst; /* current instruction */
+ int nbits; /* number of bits in imm field */
+ int scale; /* scale factor to be applied to imm */
+ int is_signed; /* is the imm field signed? */
+{
+ int offset;
+
+ if ((prev_inst & 0xf800) == 0xf000) /* prev instruction was EXTEND? */
+ {
+ offset = ((prev_inst & 0x1f) << 11) | (prev_inst & 0x7e0);
+ if (offset & 0x8000) /* check for negative extend */
+ offset = 0 - (0x10000 - (offset & 0xffff));
+ return offset | (inst & 0x1f);
+ }
+ else
+ {
+ int max_imm = 1 << nbits;
+ int mask = max_imm - 1;
+ int sign_bit = max_imm >> 1;
+
+ offset = inst & mask;
+ if (is_signed && (offset & sign_bit))
+ offset = 0 - (max_imm - offset);
+ return offset * scale;
+ }
+}
+
+
+/* Fill in values in temp_proc_desc based on the MIPS16 instruction
+ stream from start_pc to limit_pc. */
+
+static void
+mips16_heuristic_proc_desc(start_pc, limit_pc, next_frame, sp)
+ CORE_ADDR start_pc, limit_pc;
+ struct frame_info *next_frame;
+ CORE_ADDR sp;
+{
+ CORE_ADDR cur_pc;
+ CORE_ADDR frame_addr = 0; /* Value of $r17, used as frame pointer */
+ unsigned short prev_inst = 0; /* saved copy of previous instruction */
+ unsigned inst = 0; /* current instruction */
+ unsigned entry_inst = 0; /* the entry instruction */
+ int reg, offset;
+
+ PROC_FRAME_OFFSET(&temp_proc_desc) = 0; /* size of stack frame */
+ PROC_FRAME_ADJUST(&temp_proc_desc) = 0; /* offset of FP from SP */
+
+ for (cur_pc = start_pc; cur_pc < limit_pc; cur_pc += MIPS16_INSTLEN)
+ {
+ /* Save the previous instruction. If it's an EXTEND, we'll extract
+ the immediate offset extension from it in mips16_get_imm. */
+ prev_inst = inst;
+
+ /* Fetch and decode the instruction. */
+ inst = (unsigned short) mips_fetch_instruction (cur_pc);
+ if ((inst & 0xff00) == 0x6300 /* addiu sp */
+ || (inst & 0xff00) == 0xfb00) /* daddiu sp */
+ {
+ offset = mips16_get_imm (prev_inst, inst, 8, 8, 1);
+ if (offset < 0) /* negative stack adjustment? */
+ PROC_FRAME_OFFSET(&temp_proc_desc) -= offset;
+ else
+ /* Exit loop if a positive stack adjustment is found, which
+ usually means that the stack cleanup code in the function
+ epilogue is reached. */
+ break;
+ }
+ else if ((inst & 0xf800) == 0xd000) /* sw reg,n($sp) */
+ {
+ offset = mips16_get_imm (prev_inst, inst, 8, 4, 0);
+ reg = mips16_to_32_reg[(inst & 0x700) >> 8];
+ PROC_REG_MASK(&temp_proc_desc) |= (1 << reg);
+ set_reg_offset (reg, sp + offset);
+ }
+ else if ((inst & 0xff00) == 0xf900) /* sd reg,n($sp) */
+ {
+ offset = mips16_get_imm (prev_inst, inst, 5, 8, 0);
+ reg = mips16_to_32_reg[(inst & 0xe0) >> 5];
+ PROC_REG_MASK(&temp_proc_desc) |= (1 << reg);
+ set_reg_offset (reg, sp + offset);
+ }
+ else if ((inst & 0xff00) == 0x6200) /* sw $ra,n($sp) */
+ {
+ offset = mips16_get_imm (prev_inst, inst, 8, 4, 0);
+ PROC_REG_MASK(&temp_proc_desc) |= (1 << RA_REGNUM);
+ set_reg_offset (RA_REGNUM, sp + offset);
+ }
+ else if ((inst & 0xff00) == 0xfa00) /* sd $ra,n($sp) */
+ {
+ offset = mips16_get_imm (prev_inst, inst, 8, 8, 0);
+ PROC_REG_MASK(&temp_proc_desc) |= (1 << RA_REGNUM);
+ set_reg_offset (RA_REGNUM, sp + offset);
+ }
+ else if (inst == 0x673d) /* move $s1, $sp */
+ {
+ frame_addr = sp;
+ PROC_FRAME_REG (&temp_proc_desc) = 17;
+ }
+ else if ((inst & 0xff00) == 0x0100) /* addiu $s1,sp,n */
+ {
+ offset = mips16_get_imm (prev_inst, inst, 8, 4, 0);
+ frame_addr = sp + offset;
+ PROC_FRAME_REG (&temp_proc_desc) = 17;
+ PROC_FRAME_ADJUST (&temp_proc_desc) = offset;
+ }
+ else if ((inst & 0xFF00) == 0xd900) /* sw reg,offset($s1) */
+ {
+ offset = mips16_get_imm (prev_inst, inst, 5, 4, 0);
+ reg = mips16_to_32_reg[(inst & 0xe0) >> 5];
+ PROC_REG_MASK(&temp_proc_desc) |= 1 << reg;
+ set_reg_offset (reg, frame_addr + offset);
+ }
+ else if ((inst & 0xFF00) == 0x7900) /* sd reg,offset($s1) */
+ {
+ offset = mips16_get_imm (prev_inst, inst, 5, 8, 0);
+ reg = mips16_to_32_reg[(inst & 0xe0) >> 5];
+ PROC_REG_MASK(&temp_proc_desc) |= 1 << reg;
+ set_reg_offset (reg, frame_addr + offset);
+ }
+ else if ((inst & 0xf81f) == 0xe809 && (inst & 0x700) != 0x700) /* entry */
+ entry_inst = inst; /* save for later processing */
+ else if ((inst & 0xf800) == 0x1800) /* jal(x) */
+ cur_pc += MIPS16_INSTLEN; /* 32-bit instruction */
+ }
+
+ /* The entry instruction is typically the first instruction in a function,
+ and it stores registers at offsets relative to the value of the old SP
+ (before the prologue). But the value of the sp parameter to this
+ function is the new SP (after the prologue has been executed). So we
+ can't calculate those offsets until we've seen the entire prologue,
+ and can calculate what the old SP must have been. */
+ if (entry_inst != 0)
+ {
+ int areg_count = (entry_inst >> 8) & 7;
+ int sreg_count = (entry_inst >> 6) & 3;
+
+ /* The entry instruction always subtracts 32 from the SP. */
+ PROC_FRAME_OFFSET(&temp_proc_desc) += 32;
+
+ /* Now we can calculate what the SP must have been at the
+ start of the function prologue. */
+ sp += PROC_FRAME_OFFSET(&temp_proc_desc);
+
+ /* Check if a0-a3 were saved in the caller's argument save area. */
+ for (reg = 4, offset = 0; reg < areg_count+4; reg++)
+ {
+ PROC_REG_MASK(&temp_proc_desc) |= 1 << reg;
+ set_reg_offset (reg, sp + offset);
+ offset += MIPS_REGSIZE;
+ }
+
+ /* Check if the ra register was pushed on the stack. */
+ offset = -4;
+ if (entry_inst & 0x20)
+ {
+ PROC_REG_MASK(&temp_proc_desc) |= 1 << RA_REGNUM;
+ set_reg_offset (RA_REGNUM, sp + offset);
+ offset -= MIPS_REGSIZE;
+ }
+
+ /* Check if the s0 and s1 registers were pushed on the stack. */
+ for (reg = 16; reg < sreg_count+16; reg++)
+ {
+ PROC_REG_MASK(&temp_proc_desc) |= 1 << reg;
+ set_reg_offset (reg, sp + offset);
+ offset -= MIPS_REGSIZE;
+ }
+ }
+}
+
+static void
+mips32_heuristic_proc_desc(start_pc, limit_pc, next_frame, sp)
+ CORE_ADDR start_pc, limit_pc;
+ struct frame_info *next_frame;
+ CORE_ADDR sp;
+{
+ CORE_ADDR cur_pc;
+ CORE_ADDR frame_addr = 0; /* Value of $r30. Used by gcc for frame-pointer */
+restart:
+ memset (&temp_saved_regs, '\0', sizeof(struct frame_saved_regs));
+ PROC_FRAME_OFFSET(&temp_proc_desc) = 0;
+ PROC_FRAME_ADJUST (&temp_proc_desc) = 0; /* offset of FP from SP */
+ for (cur_pc = start_pc; cur_pc < limit_pc; cur_pc += MIPS_INSTLEN)
+ {
+ unsigned long inst, high_word, low_word;
+ int reg;
+
+ /* Fetch the instruction. */
+ inst = (unsigned long) mips_fetch_instruction (cur_pc);
+
+ /* Save some code by pre-extracting some useful fields. */
+ high_word = (inst >> 16) & 0xffff;
+ low_word = inst & 0xffff;
+ reg = high_word & 0x1f;
+
+ if (high_word == 0x27bd /* addiu $sp,$sp,-i */
+ || high_word == 0x23bd /* addi $sp,$sp,-i */
+ || high_word == 0x67bd) /* daddiu $sp,$sp,-i */
+ {
+ if (low_word & 0x8000) /* negative stack adjustment? */
+ PROC_FRAME_OFFSET(&temp_proc_desc) += 0x10000 - low_word;
+ else
+ /* Exit loop if a positive stack adjustment is found, which
+ usually means that the stack cleanup code in the function
+ epilogue is reached. */
+ break;
+ }
+ else if ((high_word & 0xFFE0) == 0xafa0) /* sw reg,offset($sp) */
+ {
+ PROC_REG_MASK(&temp_proc_desc) |= 1 << reg;
+ set_reg_offset (reg, sp + low_word);
+ }
+ else if ((high_word & 0xFFE0) == 0xffa0) /* sd reg,offset($sp) */
+ {
+ /* Irix 6.2 N32 ABI uses sd instructions for saving $gp and $ra,
+ but the register size used is only 32 bits. Make the address
+ for the saved register point to the lower 32 bits. */
+ PROC_REG_MASK(&temp_proc_desc) |= 1 << reg;
+ set_reg_offset (reg, sp + low_word + 8 - MIPS_REGSIZE);
+ }
+ else if (high_word == 0x27be) /* addiu $30,$sp,size */
+ {
+ /* Old gcc frame, r30 is virtual frame pointer. */
+ if ((long)low_word != PROC_FRAME_OFFSET(&temp_proc_desc))
+ frame_addr = sp + low_word;
+ else if (PROC_FRAME_REG (&temp_proc_desc) == SP_REGNUM)
+ {
+ unsigned alloca_adjust;
+ PROC_FRAME_REG (&temp_proc_desc) = 30;
+ frame_addr = read_next_frame_reg(next_frame, 30);
+ alloca_adjust = (unsigned)(frame_addr - (sp + low_word));
+ if (alloca_adjust > 0)
+ {
+ /* FP > SP + frame_size. This may be because
+ * of an alloca or somethings similar.
+ * Fix sp to "pre-alloca" value, and try again.
+ */
+ sp += alloca_adjust;
+ goto restart;
+ }
+ }
+ }
+ /* move $30,$sp. With different versions of gas this will be either
+ `addu $30,$sp,$zero' or `or $30,$sp,$zero' or `daddu 30,sp,$0'.
+ Accept any one of these. */
+ else if (inst == 0x03A0F021 || inst == 0x03a0f025 || inst == 0x03a0f02d)
+ {
+ /* New gcc frame, virtual frame pointer is at r30 + frame_size. */
+ if (PROC_FRAME_REG (&temp_proc_desc) == SP_REGNUM)
+ {
+ unsigned alloca_adjust;
+ PROC_FRAME_REG (&temp_proc_desc) = 30;
+ frame_addr = read_next_frame_reg(next_frame, 30);
+ alloca_adjust = (unsigned)(frame_addr - sp);
+ if (alloca_adjust > 0)
+ {
+ /* FP > SP + frame_size. This may be because
+ * of an alloca or somethings similar.
+ * Fix sp to "pre-alloca" value, and try again.
+ */
+ sp += alloca_adjust;
+ goto restart;
+ }
+ }
+ }
+ else if ((high_word & 0xFFE0) == 0xafc0) /* sw reg,offset($30) */
+ {
+ PROC_REG_MASK(&temp_proc_desc) |= 1 << reg;
+ set_reg_offset (reg, frame_addr + low_word);
+ }
+ }
+}
+
+static mips_extra_func_info_t
+heuristic_proc_desc(start_pc, limit_pc, next_frame)
+ CORE_ADDR start_pc, limit_pc;
+ struct frame_info *next_frame;
+{
+ CORE_ADDR sp = read_next_frame_reg (next_frame, SP_REGNUM);
+
+ if (start_pc == 0) return NULL;
+ memset (&temp_proc_desc, '\0', sizeof(temp_proc_desc));
+ memset (&temp_saved_regs, '\0', sizeof(struct frame_saved_regs));
+ PROC_LOW_ADDR (&temp_proc_desc) = start_pc;
+ PROC_FRAME_REG (&temp_proc_desc) = SP_REGNUM;
+ PROC_PC_REG (&temp_proc_desc) = RA_REGNUM;
+
+ if (start_pc + 200 < limit_pc)
+ limit_pc = start_pc + 200;
+ if (pc_is_mips16 (start_pc))
+ mips16_heuristic_proc_desc (start_pc, limit_pc, next_frame, sp);
+ else
+ mips32_heuristic_proc_desc (start_pc, limit_pc, next_frame, sp);
+ return &temp_proc_desc;
+}
+
+static mips_extra_func_info_t
+non_heuristic_proc_desc (pc, addrptr)
+ CORE_ADDR pc;
+ CORE_ADDR *addrptr;
+{
+ CORE_ADDR startaddr;
+ mips_extra_func_info_t proc_desc;
+ struct block *b = block_for_pc(pc);
+ struct symbol *sym;
+
+ find_pc_partial_function (pc, NULL, &startaddr, NULL);
+ if (addrptr)
+ *addrptr = startaddr;
+ if (b == NULL || PC_IN_CALL_DUMMY (pc, 0, 0))
+ sym = NULL;
+ else
+ {
+ if (startaddr > BLOCK_START (b))
+ /* This is the "pathological" case referred to in a comment in
+ print_frame_info. It might be better to move this check into
+ symbol reading. */
+ sym = NULL;
+ else
+ sym = lookup_symbol (MIPS_EFI_SYMBOL_NAME, b, LABEL_NAMESPACE, 0, NULL);
+ }
+
+ /* If we never found a PDR for this function in symbol reading, then
+ examine prologues to find the information. */
+ if (sym)
+ {
+ proc_desc = (mips_extra_func_info_t) SYMBOL_VALUE (sym);
+ if (PROC_FRAME_REG (proc_desc) == -1)
+ return NULL;
+ else
+ return proc_desc;
+ }
+ else
+ return NULL;
+}
+
+
+static mips_extra_func_info_t
+find_proc_desc (pc, next_frame)
+ CORE_ADDR pc;
+ struct frame_info *next_frame;
+{
+ mips_extra_func_info_t proc_desc;
+ CORE_ADDR startaddr;
+
+ proc_desc = non_heuristic_proc_desc (pc, &startaddr);
+
+ if (proc_desc)
+ {
+ /* IF this is the topmost frame AND
+ * (this proc does not have debugging information OR
+ * the PC is in the procedure prologue)
+ * THEN create a "heuristic" proc_desc (by analyzing
+ * the actual code) to replace the "official" proc_desc.
+ */
+ if (next_frame == NULL)
+ {
+ struct symtab_and_line val;
+ struct symbol *proc_symbol =
+ PROC_DESC_IS_DUMMY(proc_desc) ? 0 : PROC_SYMBOL(proc_desc);
+
+ if (proc_symbol)
+ {
+ val = find_pc_line (BLOCK_START
+ (SYMBOL_BLOCK_VALUE(proc_symbol)),
+ 0);
+ val.pc = val.end ? val.end : pc;
+ }
+ if (!proc_symbol || pc < val.pc)
+ {
+ mips_extra_func_info_t found_heuristic =
+ heuristic_proc_desc (PROC_LOW_ADDR (proc_desc),
+ pc, next_frame);
+ if (found_heuristic)
+ proc_desc = found_heuristic;
+ }
+ }
+ }
+ else
+ {
+ /* Is linked_proc_desc_table really necessary? It only seems to be used
+ by procedure call dummys. However, the procedures being called ought
+ to have their own proc_descs, and even if they don't,
+ heuristic_proc_desc knows how to create them! */
+
+ register struct linked_proc_info *link;
+
+ for (link = linked_proc_desc_table; link; link = link->next)
+ if (PROC_LOW_ADDR(&link->info) <= pc
+ && PROC_HIGH_ADDR(&link->info) > pc)
+ return &link->info;
+
+ if (startaddr == 0)
+ startaddr = heuristic_proc_start (pc);
+
+ proc_desc =
+ heuristic_proc_desc (startaddr, pc, next_frame);
+ }
+ return proc_desc;
+}
+
+static CORE_ADDR
+get_frame_pointer(frame, proc_desc)
+ struct frame_info *frame;
+ mips_extra_func_info_t proc_desc;
+{
+ return ADDR_BITS_REMOVE (
+ read_next_frame_reg (frame, PROC_FRAME_REG (proc_desc)) +
+ PROC_FRAME_OFFSET (proc_desc) - PROC_FRAME_ADJUST (proc_desc));
+}
+
+mips_extra_func_info_t cached_proc_desc;
+
+CORE_ADDR
+mips_frame_chain(frame)
+ struct frame_info *frame;
+{
+ mips_extra_func_info_t proc_desc;
+ CORE_ADDR tmp;
+ CORE_ADDR saved_pc = FRAME_SAVED_PC(frame);
+
+ if (saved_pc == 0 || inside_entry_file (saved_pc))
+ return 0;
+
+ /* Check if the PC is inside a call stub. If it is, fetch the
+ PC of the caller of that stub. */
+ if ((tmp = mips_skip_stub (saved_pc)) != 0)
+ saved_pc = tmp;
+
+ /* Look up the procedure descriptor for this PC. */
+ proc_desc = find_proc_desc(saved_pc, frame);
+ if (!proc_desc)
+ return 0;
+
+ cached_proc_desc = proc_desc;
+
+ /* If no frame pointer and frame size is zero, we must be at end
+ of stack (or otherwise hosed). If we don't check frame size,
+ we loop forever if we see a zero size frame. */
+ if (PROC_FRAME_REG (proc_desc) == SP_REGNUM
+ && PROC_FRAME_OFFSET (proc_desc) == 0
+ /* The previous frame from a sigtramp frame might be frameless
+ and have frame size zero. */
+ && !frame->signal_handler_caller)
+ return 0;
+ else
+ return get_frame_pointer (frame, proc_desc);
+}
+
+void
+init_extra_frame_info(fci)
+ struct frame_info *fci;
+{
+ int regnum;
+
+ /* Use proc_desc calculated in frame_chain */
+ mips_extra_func_info_t proc_desc =
+ fci->next ? cached_proc_desc : find_proc_desc(fci->pc, fci->next);
+
+ fci->saved_regs = NULL;
+ fci->proc_desc =
+ proc_desc == &temp_proc_desc ? 0 : proc_desc;
+ if (proc_desc)
+ {
+ /* Fixup frame-pointer - only needed for top frame */
+ /* This may not be quite right, if proc has a real frame register.
+ Get the value of the frame relative sp, procedure might have been
+ interrupted by a signal at it's very start. */
+ if (fci->pc == PROC_LOW_ADDR (proc_desc)
+ && !PROC_DESC_IS_DUMMY (proc_desc))
+ fci->frame = read_next_frame_reg (fci->next, SP_REGNUM);
+ else
+ fci->frame = get_frame_pointer (fci->next, proc_desc);
+
+ if (proc_desc == &temp_proc_desc)
+ {
+ char *name;
+
+ /* Do not set the saved registers for a sigtramp frame,
+ mips_find_saved_registers will do that for us.
+ We can't use fci->signal_handler_caller, it is not yet set. */
+ find_pc_partial_function (fci->pc, &name,
+ (CORE_ADDR *)NULL,(CORE_ADDR *)NULL);
+ if (!IN_SIGTRAMP (fci->pc, name))
+ {
+ fci->saved_regs = (CORE_ADDR*)
+ frame_obstack_alloc (SIZEOF_FRAME_SAVED_REGS);
+ memcpy (fci->saved_regs, temp_saved_regs.regs, SIZEOF_FRAME_SAVED_REGS);
+ fci->saved_regs[PC_REGNUM]
+ = fci->saved_regs[RA_REGNUM];
+ }
+ }
+
+ /* hack: if argument regs are saved, guess these contain args */
+ fci->num_args = -1; /* assume we can't tell how many args for now */
+ for (regnum = MIPS_LAST_ARG_REGNUM; regnum >= A0_REGNUM; regnum--)
+ {
+ if (PROC_REG_MASK(proc_desc) & (1 << regnum))
+ {
+ fci->num_args = regnum - A0_REGNUM + 1;
+ break;
+ }
+ }
+ }
+}
+
+/* MIPS stack frames are almost impenetrable. When execution stops,
+ we basically have to look at symbol information for the function
+ that we stopped in, which tells us *which* register (if any) is
+ the base of the frame pointer, and what offset from that register
+ the frame itself is at.
+
+ This presents a problem when trying to examine a stack in memory
+ (that isn't executing at the moment), using the "frame" command. We
+ don't have a PC, nor do we have any registers except SP.
+
+ This routine takes two arguments, SP and PC, and tries to make the
+ cached frames look as if these two arguments defined a frame on the
+ cache. This allows the rest of info frame to extract the important
+ arguments without difficulty. */
+
+struct frame_info *
+setup_arbitrary_frame (argc, argv)
+ int argc;
+ CORE_ADDR *argv;
+{
+ if (argc != 2)
+ error ("MIPS frame specifications require two arguments: sp and pc");
+
+ return create_new_frame (argv[0], argv[1]);
+}
+
+/*
+ * STACK_ARGSIZE -- how many bytes does a pushed function arg take up on the stack?
+ *
+ * For n32 ABI, eight.
+ * For all others, he same as the size of a general register.
+ */
+#if defined (_MIPS_SIM_NABI32) && _MIPS_SIM == _MIPS_SIM_NABI32
+#define MIPS_NABI32 1
+#define STACK_ARGSIZE 8
+#else
+#define MIPS_NABI32 0
+#define STACK_ARGSIZE MIPS_REGSIZE
+#endif
+
+CORE_ADDR
+mips_push_arguments(nargs, args, sp, struct_return, struct_addr)
+ int nargs;
+ value_ptr *args;
+ CORE_ADDR sp;
+ int struct_return;
+ CORE_ADDR struct_addr;
+{
+ int argreg;
+ int float_argreg;
+ int argnum;
+ int len = 0;
+ int stack_offset = 0;
+
+ /* Macros to round N up or down to the next A boundary; A must be
+ a power of two. */
+#define ROUND_DOWN(n,a) ((n) & ~((a)-1))
+#define ROUND_UP(n,a) (((n)+(a)-1) & ~((a)-1))
+
+ /* First ensure that the stack and structure return address (if any)
+ are properly aligned. The stack has to be at least 64-bit aligned
+ even on 32-bit machines, because doubles must be 64-bit aligned.
+ On at least one MIPS variant, stack frames need to be 128-bit
+ aligned, so we round to this widest known alignment. */
+ sp = ROUND_DOWN (sp, 16);
+ struct_addr = ROUND_DOWN (struct_addr, MIPS_REGSIZE);
+
+ /* Now make space on the stack for the args. We allocate more
+ than necessary for EABI, because the first few arguments are
+ passed in registers, but that's OK. */
+ for (argnum = 0; argnum < nargs; argnum++)
+ len += ROUND_UP (TYPE_LENGTH(VALUE_TYPE(args[argnum])), MIPS_REGSIZE);
+ sp -= ROUND_UP (len, 16);
+
+ /* Initialize the integer and float register pointers. */
+ argreg = A0_REGNUM;
+ float_argreg = FPA0_REGNUM;
+
+ /* the struct_return pointer occupies the first parameter-passing reg */
+ if (struct_return)
+ write_register (argreg++, struct_addr);
+
+ /* Now load as many as possible of the first arguments into
+ registers, and push the rest onto the stack. Loop thru args
+ from first to last. */
+ for (argnum = 0; argnum < nargs; argnum++)
+ {
+ char *val;
+ char valbuf[MAX_REGISTER_RAW_SIZE];
+ value_ptr arg = args[argnum];
+ struct type *arg_type = check_typedef (VALUE_TYPE (arg));
+ int len = TYPE_LENGTH (arg_type);
+ enum type_code typecode = TYPE_CODE (arg_type);
+
+ /* The EABI passes structures that do not fit in a register by
+ reference. In all other cases, pass the structure by value. */
+ if (MIPS_EABI && len > MIPS_REGSIZE &&
+ (typecode == TYPE_CODE_STRUCT || typecode == TYPE_CODE_UNION))
+ {
+ store_address (valbuf, MIPS_REGSIZE, VALUE_ADDRESS (arg));
+ typecode = TYPE_CODE_PTR;
+ len = MIPS_REGSIZE;
+ val = valbuf;
+ }
+ else
+ val = (char *)VALUE_CONTENTS (arg);
+
+ /* 32-bit ABIs always start floating point arguments in an
+ even-numbered floating point register. */
+ if (!FP_REGISTER_DOUBLE && typecode == TYPE_CODE_FLT
+ && (float_argreg & 1))
+ float_argreg++;
+
+ /* Floating point arguments passed in registers have to be
+ treated specially. On 32-bit architectures, doubles
+ are passed in register pairs; the even register gets
+ the low word, and the odd register gets the high word.
+ On non-EABI processors, the first two floating point arguments are
+ also copied to general registers, because MIPS16 functions
+ don't use float registers for arguments. This duplication of
+ arguments in general registers can't hurt non-MIPS16 functions
+ because those registers are normally skipped. */
+ if (typecode == TYPE_CODE_FLT
+ && float_argreg <= MIPS_LAST_FP_ARG_REGNUM
+ && MIPS_FPU_TYPE != MIPS_FPU_NONE)
+ {
+ if (!FP_REGISTER_DOUBLE && len == 8)
+ {
+ int low_offset = TARGET_BYTE_ORDER == BIG_ENDIAN ? 4 : 0;
+ unsigned long regval;
+
+ /* Write the low word of the double to the even register(s). */
+ regval = extract_unsigned_integer (val+low_offset, 4);
+ write_register (float_argreg++, regval);
+ if (!MIPS_EABI)
+ write_register (argreg+1, regval);
+
+ /* Write the high word of the double to the odd register(s). */
+ regval = extract_unsigned_integer (val+4-low_offset, 4);
+ write_register (float_argreg++, regval);
+ if (!MIPS_EABI)
+ {
+ write_register (argreg, regval);
+ argreg += 2;
+ }
+
+ }
+ else
+ {
+ /* This is a floating point value that fits entirely
+ in a single register. */
+ CORE_ADDR regval = extract_address (val, len);
+ write_register (float_argreg++, regval);
+ if (!MIPS_EABI)
+ {
+ write_register (argreg, regval);
+ argreg += FP_REGISTER_DOUBLE ? 1 : 2;
+ }
+ }
+ }
+ else
+ {
+ /* Copy the argument to general registers or the stack in
+ register-sized pieces. Large arguments are split between
+ registers and stack. */
+ /* Note: structs whose size is not a multiple of MIPS_REGSIZE
+ are treated specially: Irix cc passes them in registers
+ where gcc sometimes puts them on the stack. For maximum
+ compatibility, we will put them in both places. */
+
+ int odd_sized_struct = ((len > MIPS_REGSIZE) &&
+ (len % MIPS_REGSIZE != 0));
+ while (len > 0)
+ {
+ int partial_len = len < MIPS_REGSIZE ? len : MIPS_REGSIZE;
+
+ if (argreg > MIPS_LAST_ARG_REGNUM || odd_sized_struct)
+ {
+ /* Write this portion of the argument to the stack. */
+ /* Should shorter than int integer values be
+ promoted to int before being stored? */
+
+ int longword_offset = 0;
+ if (TARGET_BYTE_ORDER == BIG_ENDIAN)
+ if (STACK_ARGSIZE == 8 &&
+ (typecode == TYPE_CODE_INT ||
+ typecode == TYPE_CODE_PTR ||
+ typecode == TYPE_CODE_FLT) && len <= 4)
+ longword_offset = STACK_ARGSIZE - len;
+ else if ((typecode == TYPE_CODE_STRUCT ||
+ typecode == TYPE_CODE_UNION) &&
+ TYPE_LENGTH (arg_type) < STACK_ARGSIZE)
+ longword_offset = STACK_ARGSIZE - len;
+
+ write_memory (sp + stack_offset + longword_offset,
+ val, partial_len);
+ }
+
+ /* Note!!! This is NOT an else clause.
+ Odd sized structs may go thru BOTH paths. */
+ if (argreg <= MIPS_LAST_ARG_REGNUM)
+ {
+ CORE_ADDR regval = extract_address (val, partial_len);
+
+ /* A non-floating-point argument being passed in a
+ general register. If a struct or union, and if
+ the remaining length is smaller than the register
+ size, we have to adjust the register value on
+ big endian targets.
+
+ It does not seem to be necessary to do the
+ same for integral types.
+
+ Also don't do this adjustment on EABI and O64
+ binaries. */
+
+ if (!MIPS_EABI
+ && (MIPS_REGSIZE < 8)
+ && TARGET_BYTE_ORDER == BIG_ENDIAN
+ && (partial_len < MIPS_REGSIZE)
+ && (typecode == TYPE_CODE_STRUCT ||
+ typecode == TYPE_CODE_UNION))
+ regval <<= ((MIPS_REGSIZE - partial_len) *
+ TARGET_CHAR_BIT);
+
+ write_register (argreg, regval);
+ argreg++;
+
+ /* If this is the old ABI, prevent subsequent floating
+ point arguments from being passed in floating point
+ registers. */
+ if (!MIPS_EABI)
+ float_argreg = MIPS_LAST_FP_ARG_REGNUM + 1;
+ }
+
+ len -= partial_len;
+ val += partial_len;
+
+ /* The offset onto the stack at which we will start
+ copying parameters (after the registers are used up)
+ begins at (4 * MIPS_REGSIZE) in the old ABI. This
+ leaves room for the "home" area for register parameters.
+
+ In the new EABI (and the NABI32), the 8 register parameters
+ do not have "home" stack space reserved for them, so the
+ stack offset does not get incremented until after
+ we have used up the 8 parameter registers. */
+
+ if (!(MIPS_EABI || MIPS_NABI32) ||
+ argnum >= 8)
+ stack_offset += ROUND_UP (partial_len, STACK_ARGSIZE);
+ }
+ }
+ }
+
+ /* Set the return address register to point to the entry
+ point of the program, where a breakpoint lies in wait. */
+ write_register (RA_REGNUM, CALL_DUMMY_ADDRESS());
+
+ /* Return adjusted stack pointer. */
+ return sp;
+}
+
+static void
+mips_push_register(CORE_ADDR *sp, int regno)
+{
+ char buffer[MAX_REGISTER_RAW_SIZE];
+ int regsize = REGISTER_RAW_SIZE (regno);
+
+ *sp -= regsize;
+ read_register_gen (regno, buffer);
+ write_memory (*sp, buffer, regsize);
+}
+
+/* MASK(i,j) == (1<<i) + (1<<(i+1)) + ... + (1<<j)). Assume i<=j<(MIPS_NUMREGS-1). */
+#define MASK(i,j) (((1 << ((j)+1))-1) ^ ((1 << (i))-1))
+
+void
+mips_push_dummy_frame()
+{
+ int ireg;
+ struct linked_proc_info *link = (struct linked_proc_info*)
+ xmalloc(sizeof(struct linked_proc_info));
+ mips_extra_func_info_t proc_desc = &link->info;
+ CORE_ADDR sp = ADDR_BITS_REMOVE (read_register (SP_REGNUM));
+ CORE_ADDR old_sp = sp;
+ link->next = linked_proc_desc_table;
+ linked_proc_desc_table = link;
+
+/* FIXME! are these correct ? */
+#define PUSH_FP_REGNUM 16 /* must be a register preserved across calls */
+#define GEN_REG_SAVE_MASK MASK(1,16)|MASK(24,28)|(1<<(MIPS_NUMREGS-1))
+#define FLOAT_REG_SAVE_MASK MASK(0,19)
+#define FLOAT_SINGLE_REG_SAVE_MASK \
+ ((1<<18)|(1<<16)|(1<<14)|(1<<12)|(1<<10)|(1<<8)|(1<<6)|(1<<4)|(1<<2)|(1<<0))
+ /*
+ * The registers we must save are all those not preserved across
+ * procedure calls. Dest_Reg (see tm-mips.h) must also be saved.
+ * In addition, we must save the PC, PUSH_FP_REGNUM, MMLO/-HI
+ * and FP Control/Status registers.
+ *
+ *
+ * Dummy frame layout:
+ * (high memory)
+ * Saved PC
+ * Saved MMHI, MMLO, FPC_CSR
+ * Saved R31
+ * Saved R28
+ * ...
+ * Saved R1
+ * Saved D18 (i.e. F19, F18)
+ * ...
+ * Saved D0 (i.e. F1, F0)
+ * Argument build area and stack arguments written via mips_push_arguments
+ * (low memory)
+ */
+
+ /* Save special registers (PC, MMHI, MMLO, FPC_CSR) */
+ PROC_FRAME_REG(proc_desc) = PUSH_FP_REGNUM;
+ PROC_FRAME_OFFSET(proc_desc) = 0;
+ PROC_FRAME_ADJUST(proc_desc) = 0;
+ mips_push_register (&sp, PC_REGNUM);
+ mips_push_register (&sp, HI_REGNUM);
+ mips_push_register (&sp, LO_REGNUM);
+ mips_push_register (&sp, MIPS_FPU_TYPE == MIPS_FPU_NONE ? 0 : FCRCS_REGNUM);
+
+ /* Save general CPU registers */
+ PROC_REG_MASK(proc_desc) = GEN_REG_SAVE_MASK;
+ /* PROC_REG_OFFSET is the offset of the first saved register from FP. */
+ PROC_REG_OFFSET(proc_desc) = sp - old_sp - MIPS_REGSIZE;
+ for (ireg = 32; --ireg >= 0; )
+ if (PROC_REG_MASK(proc_desc) & (1 << ireg))
+ mips_push_register (&sp, ireg);
+
+ /* Save floating point registers starting with high order word */
+ PROC_FREG_MASK(proc_desc) =
+ MIPS_FPU_TYPE == MIPS_FPU_DOUBLE ? FLOAT_REG_SAVE_MASK
+ : MIPS_FPU_TYPE == MIPS_FPU_SINGLE ? FLOAT_SINGLE_REG_SAVE_MASK : 0;
+ /* PROC_FREG_OFFSET is the offset of the first saved *double* register
+ from FP. */
+ PROC_FREG_OFFSET(proc_desc) = sp - old_sp - 8;
+ for (ireg = 32; --ireg >= 0; )
+ if (PROC_FREG_MASK(proc_desc) & (1 << ireg))
+ mips_push_register (&sp, ireg + FP0_REGNUM);
+
+ /* Update the frame pointer for the call dummy and the stack pointer.
+ Set the procedure's starting and ending addresses to point to the
+ call dummy address at the entry point. */
+ write_register (PUSH_FP_REGNUM, old_sp);
+ write_register (SP_REGNUM, sp);
+ PROC_LOW_ADDR(proc_desc) = CALL_DUMMY_ADDRESS();
+ PROC_HIGH_ADDR(proc_desc) = CALL_DUMMY_ADDRESS() + 4;
+ SET_PROC_DESC_IS_DUMMY(proc_desc);
+ PROC_PC_REG(proc_desc) = RA_REGNUM;
+}
+
+void
+mips_pop_frame()
+{
+ register int regnum;
+ struct frame_info *frame = get_current_frame ();
+ CORE_ADDR new_sp = FRAME_FP (frame);
+
+ mips_extra_func_info_t proc_desc = frame->proc_desc;
+
+ write_register (PC_REGNUM, FRAME_SAVED_PC(frame));
+ if (frame->saved_regs == NULL)
+ mips_find_saved_regs (frame);
+ for (regnum = 0; regnum < NUM_REGS; regnum++)
+ {
+ if (regnum != SP_REGNUM && regnum != PC_REGNUM
+ && frame->saved_regs[regnum])
+ write_register (regnum,
+ read_memory_integer (frame->saved_regs[regnum],
+ MIPS_REGSIZE));
+ }
+ write_register (SP_REGNUM, new_sp);
+ flush_cached_frames ();
+
+ if (proc_desc && PROC_DESC_IS_DUMMY(proc_desc))
+ {
+ struct linked_proc_info *pi_ptr, *prev_ptr;
+
+ for (pi_ptr = linked_proc_desc_table, prev_ptr = NULL;
+ pi_ptr != NULL;
+ prev_ptr = pi_ptr, pi_ptr = pi_ptr->next)
+ {
+ if (&pi_ptr->info == proc_desc)
+ break;
+ }
+
+ if (pi_ptr == NULL)
+ error ("Can't locate dummy extra frame info\n");
+
+ if (prev_ptr != NULL)
+ prev_ptr->next = pi_ptr->next;
+ else
+ linked_proc_desc_table = pi_ptr->next;
+
+ free (pi_ptr);
+
+ write_register (HI_REGNUM,
+ read_memory_integer (new_sp - 2*MIPS_REGSIZE, MIPS_REGSIZE));
+ write_register (LO_REGNUM,
+ read_memory_integer (new_sp - 3*MIPS_REGSIZE, MIPS_REGSIZE));
+ if (MIPS_FPU_TYPE != MIPS_FPU_NONE)
+ write_register (FCRCS_REGNUM,
+ read_memory_integer (new_sp - 4*MIPS_REGSIZE, MIPS_REGSIZE));
+ }
+}
+
+static void
+mips_print_register (regnum, all)
+ int regnum, all;
+{
+ char raw_buffer[MAX_REGISTER_RAW_SIZE];
+
+ /* Get the data in raw format. */
+ if (read_relative_register_raw_bytes (regnum, raw_buffer))
+ {
+ printf_filtered ("%s: [Invalid]", REGISTER_NAME (regnum));
+ return;
+ }
+
+ /* If an even floating point register, also print as double. */
+ if (TYPE_CODE (REGISTER_VIRTUAL_TYPE (regnum)) == TYPE_CODE_FLT
+ && !((regnum-FP0_REGNUM) & 1))
+ if (REGISTER_RAW_SIZE(regnum) == 4) /* this would be silly on MIPS64 or N32 (Irix 6) */
+ {
+ char dbuffer[2 * MAX_REGISTER_RAW_SIZE];
+
+ read_relative_register_raw_bytes (regnum, dbuffer);
+ read_relative_register_raw_bytes (regnum+1, dbuffer+MIPS_REGSIZE);
+ REGISTER_CONVERT_TO_TYPE (regnum, builtin_type_double, dbuffer);
+
+ printf_filtered ("(d%d: ", regnum-FP0_REGNUM);
+ val_print (builtin_type_double, dbuffer, 0, 0,
+ gdb_stdout, 0, 1, 0, Val_pretty_default);
+ printf_filtered ("); ");
+ }
+ fputs_filtered (REGISTER_NAME (regnum), gdb_stdout);
+
+ /* The problem with printing numeric register names (r26, etc.) is that
+ the user can't use them on input. Probably the best solution is to
+ fix it so that either the numeric or the funky (a2, etc.) names
+ are accepted on input. */
+ if (regnum < MIPS_NUMREGS)
+ printf_filtered ("(r%d): ", regnum);
+ else
+ printf_filtered (": ");
+
+ /* If virtual format is floating, print it that way. */
+ if (TYPE_CODE (REGISTER_VIRTUAL_TYPE (regnum)) == TYPE_CODE_FLT)
+ if (FP_REGISTER_DOUBLE)
+ { /* show 8-byte floats as float AND double: */
+ int offset = 4 * (TARGET_BYTE_ORDER == BIG_ENDIAN);
+
+ printf_filtered (" (float) ");
+ val_print (builtin_type_float, raw_buffer + offset, 0, 0,
+ gdb_stdout, 0, 1, 0, Val_pretty_default);
+ printf_filtered (", (double) ");
+ val_print (builtin_type_double, raw_buffer, 0, 0,
+ gdb_stdout, 0, 1, 0, Val_pretty_default);
+ }
+ else
+ val_print (REGISTER_VIRTUAL_TYPE (regnum), raw_buffer, 0, 0,
+ gdb_stdout, 0, 1, 0, Val_pretty_default);
+ /* Else print as integer in hex. */
+ else
+ print_scalar_formatted (raw_buffer, REGISTER_VIRTUAL_TYPE (regnum),
+ 'x', 0, gdb_stdout);
+}
+
+/* Replacement for generic do_registers_info.
+ Print regs in pretty columns. */
+
+static int
+do_fp_register_row (regnum)
+ int regnum;
+{ /* do values for FP (float) regs */
+ char *raw_buffer[2];
+ char *dbl_buffer;
+ /* use HI and LO to control the order of combining two flt regs */
+ int HI = (TARGET_BYTE_ORDER == BIG_ENDIAN);
+ int LO = (TARGET_BYTE_ORDER != BIG_ENDIAN);
+ double doub, flt1, flt2; /* doubles extracted from raw hex data */
+ int inv1, inv2, inv3;
+
+ raw_buffer[0] = (char *) alloca (REGISTER_RAW_SIZE (FP0_REGNUM));
+ raw_buffer[1] = (char *) alloca (REGISTER_RAW_SIZE (FP0_REGNUM));
+ dbl_buffer = (char *) alloca (2 * REGISTER_RAW_SIZE (FP0_REGNUM));
+
+ /* Get the data in raw format. */
+ if (read_relative_register_raw_bytes (regnum, raw_buffer[HI]))
+ error ("can't read register %d (%s)", regnum, REGISTER_NAME (regnum));
+ if (REGISTER_RAW_SIZE(regnum) == 4)
+ {
+ /* 4-byte registers: we can fit two registers per row. */
+ /* Also print every pair of 4-byte regs as an 8-byte double. */
+ if (read_relative_register_raw_bytes (regnum + 1, raw_buffer[LO]))
+ error ("can't read register %d (%s)",
+ regnum + 1, REGISTER_NAME (regnum + 1));
+
+ /* copy the two floats into one double, and unpack both */
+ memcpy (dbl_buffer, raw_buffer, sizeof(dbl_buffer));
+ flt1 = unpack_double (builtin_type_float, raw_buffer[HI], &inv1);
+ flt2 = unpack_double (builtin_type_float, raw_buffer[LO], &inv2);
+ doub = unpack_double (builtin_type_double, dbl_buffer, &inv3);
+
+ printf_filtered (inv1 ? " %-5s: <invalid float>" :
+ " %-5s%-17.9g", REGISTER_NAME (regnum), flt1);
+ printf_filtered (inv2 ? " %-5s: <invalid float>" :
+ " %-5s%-17.9g", REGISTER_NAME (regnum + 1), flt2);
+ printf_filtered (inv3 ? " dbl: <invalid double>\n" :
+ " dbl: %-24.17g\n", doub);
+ /* may want to do hex display here (future enhancement) */
+ regnum +=2;
+ }
+ else
+ { /* eight byte registers: print each one as float AND as double. */
+ int offset = 4 * (TARGET_BYTE_ORDER == BIG_ENDIAN);
+
+ memcpy (dbl_buffer, raw_buffer[HI], sizeof(dbl_buffer));
+ flt1 = unpack_double (builtin_type_float,
+ &raw_buffer[HI][offset], &inv1);
+ doub = unpack_double (builtin_type_double, dbl_buffer, &inv3);
+
+ printf_filtered (inv1 ? " %-5s: <invalid float>" :
+ " %-5s flt: %-17.9g", REGISTER_NAME (regnum), flt1);
+ printf_filtered (inv3 ? " dbl: <invalid double>\n" :
+ " dbl: %-24.17g\n", doub);
+ /* may want to do hex display here (future enhancement) */
+ regnum++;
+ }
+ return regnum;
+}
+
+/* Print a row's worth of GP (int) registers, with name labels above */
+
+static int
+do_gp_register_row (regnum)
+ int regnum;
+{
+ /* do values for GP (int) regs */
+ char raw_buffer[MAX_REGISTER_RAW_SIZE];
+ int ncols = (MIPS_REGSIZE == 8 ? 4 : 8); /* display cols per row */
+ int col, byte;
+ int start_regnum = regnum;
+ int numregs = NUM_REGS;
+
+
+ /* For GP registers, we print a separate row of names above the vals */
+ printf_filtered (" ");
+ for (col = 0; col < ncols && regnum < numregs; regnum++)
+ {
+ if (*REGISTER_NAME (regnum) == '\0')
+ continue; /* unused register */
+ if (TYPE_CODE (REGISTER_VIRTUAL_TYPE (regnum)) == TYPE_CODE_FLT)
+ break; /* end the row: reached FP register */
+ printf_filtered (MIPS_REGSIZE == 8 ? "%17s" : "%9s",
+ REGISTER_NAME (regnum));
+ col++;
+ }
+ printf_filtered (start_regnum < MIPS_NUMREGS ? "\n R%-4d" : "\n ",
+ start_regnum); /* print the R0 to R31 names */
+
+ regnum = start_regnum; /* go back to start of row */
+ /* now print the values in hex, 4 or 8 to the row */
+ for (col = 0; col < ncols && regnum < numregs; regnum++)
+ {
+ if (*REGISTER_NAME (regnum) == '\0')
+ continue; /* unused register */
+ if (TYPE_CODE (REGISTER_VIRTUAL_TYPE (regnum)) == TYPE_CODE_FLT)
+ break; /* end row: reached FP register */
+ /* OK: get the data in raw format. */
+ if (read_relative_register_raw_bytes (regnum, raw_buffer))
+ error ("can't read register %d (%s)", regnum, REGISTER_NAME (regnum));
+ /* pad small registers */
+ for (byte = 0; byte < (MIPS_REGSIZE - REGISTER_RAW_SIZE (regnum)); byte++)
+ printf_filtered (" ");
+ /* Now print the register value in hex, endian order. */
+ if (TARGET_BYTE_ORDER == BIG_ENDIAN)
+ for (byte = 0; byte < REGISTER_RAW_SIZE (regnum); byte++)
+ printf_filtered ("%02x", (unsigned char) raw_buffer[byte]);
+ else
+ for (byte = REGISTER_RAW_SIZE (regnum) - 1; byte >= 0; byte--)
+ printf_filtered ("%02x", (unsigned char) raw_buffer[byte]);
+ printf_filtered (" ");
+ col++;
+ }
+ if (col > 0) /* ie. if we actually printed anything... */
+ printf_filtered ("\n");
+
+ return regnum;
+}
+
+/* MIPS_DO_REGISTERS_INFO(): called by "info register" command */
+
+void
+mips_do_registers_info (regnum, fpregs)
+ int regnum;
+ int fpregs;
+{
+ if (regnum != -1) /* do one specified register */
+ {
+ if (*(REGISTER_NAME (regnum)) == '\0')
+ error ("Not a valid register for the current processor type");
+
+ mips_print_register (regnum, 0);
+ printf_filtered ("\n");
+ }
+ else /* do all (or most) registers */
+ {
+ regnum = 0;
+ while (regnum < NUM_REGS)
+ {
+ if (TYPE_CODE(REGISTER_VIRTUAL_TYPE (regnum)) == TYPE_CODE_FLT)
+ if (fpregs) /* true for "INFO ALL-REGISTERS" command */
+ regnum = do_fp_register_row (regnum); /* FP regs */
+ else
+ regnum += MIPS_NUMREGS; /* skip floating point regs */
+ else
+ regnum = do_gp_register_row (regnum); /* GP (int) regs */
+ }
+ }
+}
+
+/* Return number of args passed to a frame. described by FIP.
+ Can return -1, meaning no way to tell. */
+
+int
+mips_frame_num_args (frame)
+ struct frame_info *frame;
+{
+#if 0 /* FIXME Use or lose this! */
+ struct chain_info_t *p;
+
+ p = mips_find_cached_frame (FRAME_FP (frame));
+ if (p->valid)
+ return p->the_info.numargs;
+#endif
+ return -1;
+}
+
+/* Is this a branch with a delay slot? */
+
+static int is_delayed PARAMS ((unsigned long));
+
+static int
+is_delayed (insn)
+ unsigned long insn;
+{
+ int i;
+ for (i = 0; i < NUMOPCODES; ++i)
+ if (mips_opcodes[i].pinfo != INSN_MACRO
+ && (insn & mips_opcodes[i].mask) == mips_opcodes[i].match)
+ break;
+ return (i < NUMOPCODES
+ && (mips_opcodes[i].pinfo & (INSN_UNCOND_BRANCH_DELAY
+ | INSN_COND_BRANCH_DELAY
+ | INSN_COND_BRANCH_LIKELY)));
+}
+
+int
+mips_step_skips_delay (pc)
+ CORE_ADDR pc;
+{
+ char buf[MIPS_INSTLEN];
+
+ /* There is no branch delay slot on MIPS16. */
+ if (pc_is_mips16 (pc))
+ return 0;
+
+ if (target_read_memory (pc, buf, MIPS_INSTLEN) != 0)
+ /* If error reading memory, guess that it is not a delayed branch. */
+ return 0;
+ return is_delayed ((unsigned long)extract_unsigned_integer (buf, MIPS_INSTLEN));
+}
+
+
+/* Skip the PC past function prologue instructions (32-bit version).
+ This is a helper function for mips_skip_prologue. */
+
+static CORE_ADDR
+mips32_skip_prologue (pc, lenient)
+ CORE_ADDR pc; /* starting PC to search from */
+ int lenient;
+{
+ t_inst inst;
+ CORE_ADDR end_pc;
+ int seen_sp_adjust = 0;
+ int load_immediate_bytes = 0;
+
+ /* Skip the typical prologue instructions. These are the stack adjustment
+ instruction and the instructions that save registers on the stack
+ or in the gcc frame. */
+ for (end_pc = pc + 100; pc < end_pc; pc += MIPS_INSTLEN)
+ {
+ unsigned long high_word;
+
+ inst = mips_fetch_instruction (pc);
+ high_word = (inst >> 16) & 0xffff;
+
+#if 0
+ if (lenient && is_delayed (inst))
+ continue;
+#endif
+
+ if (high_word == 0x27bd /* addiu $sp,$sp,offset */
+ || high_word == 0x67bd) /* daddiu $sp,$sp,offset */
+ seen_sp_adjust = 1;
+ else if (inst == 0x03a1e823 || /* subu $sp,$sp,$at */
+ inst == 0x03a8e823) /* subu $sp,$sp,$t0 */
+ seen_sp_adjust = 1;
+ else if (((inst & 0xFFE00000) == 0xAFA00000 /* sw reg,n($sp) */
+ || (inst & 0xFFE00000) == 0xFFA00000) /* sd reg,n($sp) */
+ && (inst & 0x001F0000)) /* reg != $zero */
+ continue;
+
+ else if ((inst & 0xFFE00000) == 0xE7A00000) /* swc1 freg,n($sp) */
+ continue;
+ else if ((inst & 0xF3E00000) == 0xA3C00000 && (inst & 0x001F0000))
+ /* sx reg,n($s8) */
+ continue; /* reg != $zero */
+
+ /* move $s8,$sp. With different versions of gas this will be either
+ `addu $s8,$sp,$zero' or `or $s8,$sp,$zero' or `daddu s8,sp,$0'.
+ Accept any one of these. */
+ else if (inst == 0x03A0F021 || inst == 0x03a0f025 || inst == 0x03a0f02d)
+ continue;
+
+ else if ((inst & 0xFF9F07FF) == 0x00800021) /* move reg,$a0-$a3 */
+ continue;
+ else if (high_word == 0x3c1c) /* lui $gp,n */
+ continue;
+ else if (high_word == 0x279c) /* addiu $gp,$gp,n */
+ continue;
+ else if (inst == 0x0399e021 /* addu $gp,$gp,$t9 */
+ || inst == 0x033ce021) /* addu $gp,$t9,$gp */
+ continue;
+ /* The following instructions load $at or $t0 with an immediate
+ value in preparation for a stack adjustment via
+ subu $sp,$sp,[$at,$t0]. These instructions could also initialize
+ a local variable, so we accept them only before a stack adjustment
+ instruction was seen. */
+ else if (!seen_sp_adjust)
+ {
+ if (high_word == 0x3c01 || /* lui $at,n */
+ high_word == 0x3c08) /* lui $t0,n */
+ {
+ load_immediate_bytes += MIPS_INSTLEN; /* FIXME!! */
+ continue;
+ }
+ else if (high_word == 0x3421 || /* ori $at,$at,n */
+ high_word == 0x3508 || /* ori $t0,$t0,n */
+ high_word == 0x3401 || /* ori $at,$zero,n */
+ high_word == 0x3408) /* ori $t0,$zero,n */
+ {
+ load_immediate_bytes += MIPS_INSTLEN; /* FIXME!! */
+ continue;
+ }
+ else
+ break;
+ }
+ else
+ break;
+ }
+
+ /* In a frameless function, we might have incorrectly
+ skipped some load immediate instructions. Undo the skipping
+ if the load immediate was not followed by a stack adjustment. */
+ if (load_immediate_bytes && !seen_sp_adjust)
+ pc -= load_immediate_bytes;
+ return pc;
+}
+
+/* Skip the PC past function prologue instructions (16-bit version).
+ This is a helper function for mips_skip_prologue. */
+
+static CORE_ADDR
+mips16_skip_prologue (pc, lenient)
+ CORE_ADDR pc; /* starting PC to search from */
+ int lenient;
+{
+ CORE_ADDR end_pc;
+ int extend_bytes = 0;
+ int prev_extend_bytes;
+
+ /* Table of instructions likely to be found in a function prologue. */
+ static struct
+ {
+ unsigned short inst;
+ unsigned short mask;
+ } table[] =
+ {
+ { 0x6300, 0xff00 }, /* addiu $sp,offset */
+ { 0xfb00, 0xff00 }, /* daddiu $sp,offset */
+ { 0xd000, 0xf800 }, /* sw reg,n($sp) */
+ { 0xf900, 0xff00 }, /* sd reg,n($sp) */
+ { 0x6200, 0xff00 }, /* sw $ra,n($sp) */
+ { 0xfa00, 0xff00 }, /* sd $ra,n($sp) */
+ { 0x673d, 0xffff }, /* move $s1,sp */
+ { 0xd980, 0xff80 }, /* sw $a0-$a3,n($s1) */
+ { 0x6704, 0xff1c }, /* move reg,$a0-$a3 */
+ { 0xe809, 0xf81f }, /* entry pseudo-op */
+ { 0x0100, 0xff00 }, /* addiu $s1,$sp,n */
+ { 0, 0 } /* end of table marker */
+ };
+
+ /* Skip the typical prologue instructions. These are the stack adjustment
+ instruction and the instructions that save registers on the stack
+ or in the gcc frame. */
+ for (end_pc = pc + 100; pc < end_pc; pc += MIPS16_INSTLEN)
+ {
+ unsigned short inst;
+ int i;
+
+ inst = mips_fetch_instruction (pc);
+
+ /* Normally we ignore an extend instruction. However, if it is
+ not followed by a valid prologue instruction, we must adjust
+ the pc back over the extend so that it won't be considered
+ part of the prologue. */
+ if ((inst & 0xf800) == 0xf000) /* extend */
+ {
+ extend_bytes = MIPS16_INSTLEN;
+ continue;
+ }
+ prev_extend_bytes = extend_bytes;
+ extend_bytes = 0;
+
+ /* Check for other valid prologue instructions besides extend. */
+ for (i = 0; table[i].mask != 0; i++)
+ if ((inst & table[i].mask) == table[i].inst) /* found, get out */
+ break;
+ if (table[i].mask != 0) /* it was in table? */
+ continue; /* ignore it */
+ else /* non-prologue */
+ {
+ /* Return the current pc, adjusted backwards by 2 if
+ the previous instruction was an extend. */
+ return pc - prev_extend_bytes;
+ }
+ }
+ return pc;
+}
+
+/* To skip prologues, I use this predicate. Returns either PC itself
+ if the code at PC does not look like a function prologue; otherwise
+ returns an address that (if we're lucky) follows the prologue. If
+ LENIENT, then we must skip everything which is involved in setting
+ up the frame (it's OK to skip more, just so long as we don't skip
+ anything which might clobber the registers which are being saved.
+ We must skip more in the case where part of the prologue is in the
+ delay slot of a non-prologue instruction). */
+
+CORE_ADDR
+mips_skip_prologue (pc, lenient)
+ CORE_ADDR pc;
+ int lenient;
+{
+ /* See if we can determine the end of the prologue via the symbol table.
+ If so, then return either PC, or the PC after the prologue, whichever
+ is greater. */
+
+ CORE_ADDR post_prologue_pc = after_prologue (pc, NULL);
+
+ if (post_prologue_pc != 0)
+ return max (pc, post_prologue_pc);
+
+ /* Can't determine prologue from the symbol table, need to examine
+ instructions. */
+
+ if (pc_is_mips16 (pc))
+ return mips16_skip_prologue (pc, lenient);
+ else
+ return mips32_skip_prologue (pc, lenient);
+}
+
+#if 0
+/* The lenient prologue stuff should be superseded by the code in
+ init_extra_frame_info which looks to see whether the stores mentioned
+ in the proc_desc have actually taken place. */
+
+/* Is address PC in the prologue (loosely defined) for function at
+ STARTADDR? */
+
+static int
+mips_in_lenient_prologue (startaddr, pc)
+ CORE_ADDR startaddr;
+ CORE_ADDR pc;
+{
+ CORE_ADDR end_prologue = mips_skip_prologue (startaddr, 1);
+ return pc >= startaddr && pc < end_prologue;
+}
+#endif
+
+/* Given a return value in `regbuf' with a type `valtype',
+ extract and copy its value into `valbuf'. */
+void
+mips_extract_return_value (valtype, regbuf, valbuf)
+ struct type *valtype;
+ char regbuf[REGISTER_BYTES];
+ char *valbuf;
+{
+ int regnum;
+ int offset = 0;
+ int len = TYPE_LENGTH (valtype);
+
+ regnum = 2;
+ if (TYPE_CODE (valtype) == TYPE_CODE_FLT
+ && (MIPS_FPU_TYPE == MIPS_FPU_DOUBLE
+ || (MIPS_FPU_TYPE == MIPS_FPU_SINGLE
+ && len <= MIPS_FPU_SINGLE_REGSIZE)))
+ regnum = FP0_REGNUM;
+
+ if (TARGET_BYTE_ORDER == BIG_ENDIAN)
+ { /* "un-left-justify" the value from the register */
+ if (len < REGISTER_RAW_SIZE (regnum))
+ offset = REGISTER_RAW_SIZE (regnum) - len;
+ if (len > REGISTER_RAW_SIZE (regnum) && /* odd-size structs */
+ len < REGISTER_RAW_SIZE (regnum) * 2 &&
+ (TYPE_CODE (valtype) == TYPE_CODE_STRUCT ||
+ TYPE_CODE (valtype) == TYPE_CODE_UNION))
+ offset = 2 * REGISTER_RAW_SIZE (regnum) - len;
+ }
+ memcpy (valbuf, regbuf + REGISTER_BYTE (regnum) + offset, len);
+ REGISTER_CONVERT_TO_TYPE (regnum, valtype, valbuf);
+}
+
+/* Given a return value in `regbuf' with a type `valtype',
+ write it's value into the appropriate register. */
+void
+mips_store_return_value (valtype, valbuf)
+ struct type *valtype;
+ char *valbuf;
+{
+ int regnum;
+ int offset = 0;
+ int len = TYPE_LENGTH (valtype);
+ char raw_buffer[MAX_REGISTER_RAW_SIZE];
+
+ regnum = 2;
+ if (TYPE_CODE (valtype) == TYPE_CODE_FLT
+ && (MIPS_FPU_TYPE == MIPS_FPU_DOUBLE
+ || (MIPS_FPU_TYPE == MIPS_FPU_SINGLE
+ && len <= MIPS_REGSIZE)))
+ regnum = FP0_REGNUM;
+
+ if (TARGET_BYTE_ORDER == BIG_ENDIAN)
+ { /* "left-justify" the value in the register */
+ if (len < REGISTER_RAW_SIZE (regnum))
+ offset = REGISTER_RAW_SIZE (regnum) - len;
+ if (len > REGISTER_RAW_SIZE (regnum) && /* odd-size structs */
+ len < REGISTER_RAW_SIZE (regnum) * 2 &&
+ (TYPE_CODE (valtype) == TYPE_CODE_STRUCT ||
+ TYPE_CODE (valtype) == TYPE_CODE_UNION))
+ offset = 2 * REGISTER_RAW_SIZE (regnum) - len;
+ }
+ memcpy(raw_buffer + offset, valbuf, len);
+ REGISTER_CONVERT_FROM_TYPE(regnum, valtype, raw_buffer);
+ write_register_bytes(REGISTER_BYTE (regnum), raw_buffer,
+ len > REGISTER_RAW_SIZE (regnum) ?
+ len : REGISTER_RAW_SIZE (regnum));
+}
+
+/* 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);
+}
+
+/* Commands to show/set the MIPS FPU type. */
+
+static void show_mipsfpu_command PARAMS ((char *, int));
+static void
+show_mipsfpu_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ char *msg;
+ char *fpu;
+ switch (MIPS_FPU_TYPE)
+ {
+ case MIPS_FPU_SINGLE:
+ fpu = "single-precision";
+ break;
+ case MIPS_FPU_DOUBLE:
+ fpu = "double-precision";
+ break;
+ case MIPS_FPU_NONE:
+ fpu = "absent (none)";
+ break;
+ }
+ if (mips_fpu_type_auto)
+ printf_unfiltered ("The MIPS floating-point coprocessor is set automatically (currently %s)\n",
+ fpu);
+ else
+ printf_unfiltered ("The MIPS floating-point coprocessor is assumed to be %s\n",
+ fpu);
+}
+
+
+static void set_mipsfpu_command PARAMS ((char *, int));
+static void
+set_mipsfpu_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ printf_unfiltered ("\"set mipsfpu\" must be followed by \"double\", \"single\",\"none\" or \"auto\".\n");
+ show_mipsfpu_command (args, from_tty);
+}
+
+static void set_mipsfpu_single_command PARAMS ((char *, int));
+static void
+set_mipsfpu_single_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ mips_fpu_type = MIPS_FPU_SINGLE;
+ mips_fpu_type_auto = 0;
+}
+
+static void set_mipsfpu_double_command PARAMS ((char *, int));
+static void
+set_mipsfpu_double_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ mips_fpu_type = MIPS_FPU_DOUBLE;
+ mips_fpu_type_auto = 0;
+}
+
+static void set_mipsfpu_none_command PARAMS ((char *, int));
+static void
+set_mipsfpu_none_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ mips_fpu_type = MIPS_FPU_NONE;
+ mips_fpu_type_auto = 0;
+}
+
+static void set_mipsfpu_auto_command PARAMS ((char *, int));
+static void
+set_mipsfpu_auto_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ mips_fpu_type_auto = 1;
+}
+
+/* Command to set the processor type. */
+
+void
+mips_set_processor_type_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ int i;
+
+ if (tmp_mips_processor_type == NULL || *tmp_mips_processor_type == '\0')
+ {
+ printf_unfiltered ("The known MIPS processor types are as follows:\n\n");
+ for (i = 0; mips_processor_type_table[i].name != NULL; ++i)
+ printf_unfiltered ("%s\n", mips_processor_type_table[i].name);
+
+ /* Restore the value. */
+ tmp_mips_processor_type = strsave (mips_processor_type);
+
+ return;
+ }
+
+ if (!mips_set_processor_type (tmp_mips_processor_type))
+ {
+ error ("Unknown processor type `%s'.", tmp_mips_processor_type);
+ /* Restore its value. */
+ tmp_mips_processor_type = strsave (mips_processor_type);
+ }
+}
+
+static void
+mips_show_processor_type_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+}
+
+/* Modify the actual processor type. */
+
+int
+mips_set_processor_type (str)
+ char *str;
+{
+ int i, j;
+
+ if (str == NULL)
+ return 0;
+
+ for (i = 0; mips_processor_type_table[i].name != NULL; ++i)
+ {
+ if (strcasecmp (str, mips_processor_type_table[i].name) == 0)
+ {
+ mips_processor_type = str;
+
+ for (j = 0; j < NUM_REGS; ++j)
+ /* FIXME - MIPS should be defining REGISTER_NAME() instead */
+ gdb_register_names[j] = mips_processor_type_table[i].regnames[j];
+
+ return 1;
+
+ /* FIXME tweak fpu flag too */
+ }
+ }
+
+ return 0;
+}
+
+/* Attempt to identify the particular processor model by reading the
+ processor id. */
+
+char *
+mips_read_processor_type ()
+{
+ CORE_ADDR prid;
+
+ prid = read_register (PRID_REGNUM);
+
+ if ((prid & ~0xf) == 0x700)
+ return savestring ("r3041", strlen("r3041"));
+
+ return NULL;
+}
+
+/* Just like reinit_frame_cache, but with the right arguments to be
+ callable as an sfunc. */
+
+static void
+reinit_frame_cache_sfunc (args, from_tty, c)
+ char *args;
+ int from_tty;
+ struct cmd_list_element *c;
+{
+ reinit_frame_cache ();
+}
+
+int
+gdb_print_insn_mips (memaddr, info)
+ bfd_vma memaddr;
+ disassemble_info *info;
+{
+ mips_extra_func_info_t proc_desc;
+
+ /* Search for the function containing this address. Set the low bit
+ of the address when searching, in case we were given an even address
+ that is the start of a 16-bit function. If we didn't do this,
+ the search would fail because the symbol table says the function
+ starts at an odd address, i.e. 1 byte past the given address. */
+ memaddr = ADDR_BITS_REMOVE (memaddr);
+ proc_desc = non_heuristic_proc_desc (MAKE_MIPS16_ADDR (memaddr), NULL);
+
+ /* Make an attempt to determine if this is a 16-bit function. If
+ the procedure descriptor exists and the address therein is odd,
+ it's definitely a 16-bit function. Otherwise, we have to just
+ guess that if the address passed in is odd, it's 16-bits. */
+ if (proc_desc)
+ info->mach = pc_is_mips16 (PROC_LOW_ADDR (proc_desc)) ? 16 : TM_PRINT_INSN_MACH;
+ else
+ info->mach = pc_is_mips16 (memaddr) ? 16 : TM_PRINT_INSN_MACH;
+
+ /* Round down the instruction address to the appropriate boundary. */
+ memaddr &= (info->mach == 16 ? ~1 : ~3);
+
+ /* Call the appropriate disassembler based on the target endian-ness. */
+ if (TARGET_BYTE_ORDER == BIG_ENDIAN)
+ return print_insn_big_mips (memaddr, info);
+ else
+ return print_insn_little_mips (memaddr, info);
+}
+
+/* Old-style breakpoint macros.
+ The IDT board uses an unusual breakpoint value, and sometimes gets
+ confused when it sees the usual MIPS breakpoint instruction. */
+
+#define BIG_BREAKPOINT {0, 0x5, 0, 0xd}
+#define LITTLE_BREAKPOINT {0xd, 0, 0x5, 0}
+#define PMON_BIG_BREAKPOINT {0, 0, 0, 0xd}
+#define PMON_LITTLE_BREAKPOINT {0xd, 0, 0, 0}
+#define IDT_BIG_BREAKPOINT {0, 0, 0x0a, 0xd}
+#define IDT_LITTLE_BREAKPOINT {0xd, 0x0a, 0, 0}
+#define MIPS16_BIG_BREAKPOINT {0xe8, 0xa5}
+#define MIPS16_LITTLE_BREAKPOINT {0xa5, 0xe8}
+
+/* This function implements the BREAKPOINT_FROM_PC macro. It uses the program
+ counter value to determine whether a 16- or 32-bit breakpoint should be
+ used. It returns a pointer to a string of bytes that encode a breakpoint
+ instruction, stores the length of the string to *lenptr, and adjusts pc
+ (if necessary) to point to the actual memory location where the
+ breakpoint should be inserted. */
+
+unsigned char *mips_breakpoint_from_pc (pcptr, lenptr)
+ CORE_ADDR *pcptr;
+ int *lenptr;
+{
+ if (TARGET_BYTE_ORDER == BIG_ENDIAN)
+ {
+ if (pc_is_mips16 (*pcptr))
+ {
+ static char mips16_big_breakpoint[] = MIPS16_BIG_BREAKPOINT;
+ *pcptr = UNMAKE_MIPS16_ADDR (*pcptr);
+ *lenptr = sizeof(mips16_big_breakpoint);
+ return mips16_big_breakpoint;
+ }
+ else
+ {
+ static char big_breakpoint[] = BIG_BREAKPOINT;
+ static char pmon_big_breakpoint[] = PMON_BIG_BREAKPOINT;
+ static char idt_big_breakpoint[] = IDT_BIG_BREAKPOINT;
+
+ *lenptr = sizeof(big_breakpoint);
+
+ if (strcmp (target_shortname, "mips") == 0)
+ return idt_big_breakpoint;
+ else if (strcmp (target_shortname, "ddb") == 0
+ || strcmp (target_shortname, "pmon") == 0
+ || strcmp (target_shortname, "lsi") == 0)
+ return pmon_big_breakpoint;
+ else
+ return big_breakpoint;
+ }
+ }
+ else
+ {
+ if (pc_is_mips16 (*pcptr))
+ {
+ static char mips16_little_breakpoint[] = MIPS16_LITTLE_BREAKPOINT;
+ *pcptr = UNMAKE_MIPS16_ADDR (*pcptr);
+ *lenptr = sizeof(mips16_little_breakpoint);
+ return mips16_little_breakpoint;
+ }
+ else
+ {
+ static char little_breakpoint[] = LITTLE_BREAKPOINT;
+ static char pmon_little_breakpoint[] = PMON_LITTLE_BREAKPOINT;
+ static char idt_little_breakpoint[] = IDT_LITTLE_BREAKPOINT;
+
+ *lenptr = sizeof(little_breakpoint);
+
+ if (strcmp (target_shortname, "mips") == 0)
+ return idt_little_breakpoint;
+ else if (strcmp (target_shortname, "ddb") == 0
+ || strcmp (target_shortname, "pmon") == 0
+ || strcmp (target_shortname, "lsi") == 0)
+ return pmon_little_breakpoint;
+ else
+ return little_breakpoint;
+ }
+ }
+}
+
+/* If PC is in a mips16 call or return stub, return the address of the target
+ PC, which is either the callee or the caller. There are several
+ cases which must be handled:
+
+ * If the PC is in __mips16_ret_{d,s}f, this is a return stub and the
+ target PC is in $31 ($ra).
+ * If the PC is in __mips16_call_stub_{1..10}, this is a call stub
+ and the target PC is in $2.
+ * If the PC at the start of __mips16_call_stub_{s,d}f_{0..10}, i.e.
+ before the jal instruction, this is effectively a call stub
+ and the the target PC is in $2. Otherwise this is effectively
+ a return stub and the target PC is in $18.
+
+ See the source code for the stubs in gcc/config/mips/mips16.S for
+ gory details.
+
+ This function implements the SKIP_TRAMPOLINE_CODE macro.
+*/
+
+CORE_ADDR
+mips_skip_stub (pc)
+ CORE_ADDR pc;
+{
+ char *name;
+ CORE_ADDR start_addr;
+
+ /* Find the starting address and name of the function containing the PC. */
+ if (find_pc_partial_function (pc, &name, &start_addr, NULL) == 0)
+ return 0;
+
+ /* If the PC is in __mips16_ret_{d,s}f, this is a return stub and the
+ target PC is in $31 ($ra). */
+ if (strcmp (name, "__mips16_ret_sf") == 0
+ || strcmp (name, "__mips16_ret_df") == 0)
+ return read_register (RA_REGNUM);
+
+ if (strncmp (name, "__mips16_call_stub_", 19) == 0)
+ {
+ /* If the PC is in __mips16_call_stub_{1..10}, this is a call stub
+ and the target PC is in $2. */
+ if (name[19] >= '0' && name[19] <= '9')
+ return read_register (2);
+
+ /* If the PC at the start of __mips16_call_stub_{s,d}f_{0..10}, i.e.
+ before the jal instruction, this is effectively a call stub
+ and the the target PC is in $2. Otherwise this is effectively
+ a return stub and the target PC is in $18. */
+ else if (name[19] == 's' || name[19] == 'd')
+ {
+ if (pc == start_addr)
+ {
+ /* Check if the target of the stub is a compiler-generated
+ stub. Such a stub for a function bar might have a name
+ like __fn_stub_bar, and might look like this:
+ mfc1 $4,$f13
+ mfc1 $5,$f12
+ mfc1 $6,$f15
+ mfc1 $7,$f14
+ la $1,bar (becomes a lui/addiu pair)
+ jr $1
+ So scan down to the lui/addi and extract the target
+ address from those two instructions. */
+
+ CORE_ADDR target_pc = read_register (2);
+ t_inst inst;
+ int i;
+
+ /* See if the name of the target function is __fn_stub_*. */
+ if (find_pc_partial_function (target_pc, &name, NULL, NULL) == 0)
+ return target_pc;
+ if (strncmp (name, "__fn_stub_", 10) != 0
+ && strcmp (name, "etext") != 0
+ && strcmp (name, "_etext") != 0)
+ return target_pc;
+
+ /* Scan through this _fn_stub_ code for the lui/addiu pair.
+ The limit on the search is arbitrarily set to 20
+ instructions. FIXME. */
+ for (i = 0, pc = 0; i < 20; i++, target_pc += MIPS_INSTLEN)
+ {
+ inst = mips_fetch_instruction (target_pc);
+ if ((inst & 0xffff0000) == 0x3c010000) /* lui $at */
+ pc = (inst << 16) & 0xffff0000; /* high word */
+ else if ((inst & 0xffff0000) == 0x24210000) /* addiu $at */
+ return pc | (inst & 0xffff); /* low word */
+ }
+
+ /* Couldn't find the lui/addui pair, so return stub address. */
+ return target_pc;
+ }
+ else
+ /* This is the 'return' part of a call stub. The return
+ address is in $r18. */
+ return read_register (18);
+ }
+ }
+ return 0; /* not a stub */
+}
+
+
+/* Return non-zero if the PC is inside a call thunk (aka stub or trampoline).
+ This implements the IN_SOLIB_CALL_TRAMPOLINE macro. */
+
+int
+mips_in_call_stub (pc, name)
+ CORE_ADDR pc;
+ char *name;
+{
+ CORE_ADDR start_addr;
+
+ /* Find the starting address of the function containing the PC. If the
+ caller didn't give us a name, look it up at the same time. */
+ if (find_pc_partial_function (pc, name ? NULL : &name, &start_addr, NULL) == 0)
+ return 0;
+
+ if (strncmp (name, "__mips16_call_stub_", 19) == 0)
+ {
+ /* If the PC is in __mips16_call_stub_{1..10}, this is a call stub. */
+ if (name[19] >= '0' && name[19] <= '9')
+ return 1;
+ /* If the PC at the start of __mips16_call_stub_{s,d}f_{0..10}, i.e.
+ before the jal instruction, this is effectively a call stub. */
+ else if (name[19] == 's' || name[19] == 'd')
+ return pc == start_addr;
+ }
+
+ return 0; /* not a stub */
+}
+
+
+/* Return non-zero if the PC is inside a return thunk (aka stub or trampoline).
+ This implements the IN_SOLIB_RETURN_TRAMPOLINE macro. */
+
+int
+mips_in_return_stub (pc, name)
+ CORE_ADDR pc;
+ char *name;
+{
+ CORE_ADDR start_addr;
+
+ /* Find the starting address of the function containing the PC. */
+ if (find_pc_partial_function (pc, NULL, &start_addr, NULL) == 0)
+ return 0;
+
+ /* If the PC is in __mips16_ret_{d,s}f, this is a return stub. */
+ if (strcmp (name, "__mips16_ret_sf") == 0
+ || strcmp (name, "__mips16_ret_df") == 0)
+ return 1;
+
+ /* If the PC is in __mips16_call_stub_{s,d}f_{0..10} but not at the start,
+ i.e. after the jal instruction, this is effectively a return stub. */
+ if (strncmp (name, "__mips16_call_stub_", 19) == 0
+ && (name[19] == 's' || name[19] == 'd')
+ && pc != start_addr)
+ return 1;
+
+ return 0; /* not a stub */
+}
+
+
+/* Return non-zero if the PC is in a library helper function that should
+ be ignored. This implements the IGNORE_HELPER_CALL macro. */
+
+int
+mips_ignore_helper (pc)
+ CORE_ADDR pc;
+{
+ char *name;
+
+ /* Find the starting address and name of the function containing the PC. */
+ if (find_pc_partial_function (pc, &name, NULL, NULL) == 0)
+ return 0;
+
+ /* If the PC is in __mips16_ret_{d,s}f, this is a library helper function
+ that we want to ignore. */
+ return (strcmp (name, "__mips16_ret_sf") == 0
+ || strcmp (name, "__mips16_ret_df") == 0);
+}
+
+
+/* Return a location where we can set a breakpoint that will be hit
+ when an inferior function call returns. This is normally the
+ program's entry point. Executables that don't have an entry
+ point (e.g. programs in ROM) should define a symbol __CALL_DUMMY_ADDRESS
+ whose address is the location where the breakpoint should be placed. */
+
+CORE_ADDR
+mips_call_dummy_address ()
+{
+ struct minimal_symbol *sym;
+
+ sym = lookup_minimal_symbol ("__CALL_DUMMY_ADDRESS", NULL, NULL);
+ if (sym)
+ return SYMBOL_VALUE_ADDRESS (sym);
+ else
+ return entry_point_address ();
+}
+
+
+void
+_initialize_mips_tdep ()
+{
+ static struct cmd_list_element *mipsfpulist = NULL;
+ struct cmd_list_element *c;
+
+ if (!tm_print_insn) /* Someone may have already set it */
+ tm_print_insn = gdb_print_insn_mips;
+
+ /* Let the user turn off floating point and set the fence post for
+ heuristic_proc_start. */
+
+ add_prefix_cmd ("mipsfpu", class_support, set_mipsfpu_command,
+ "Set use of MIPS floating-point coprocessor.",
+ &mipsfpulist, "set mipsfpu ", 0, &setlist);
+ add_cmd ("single", class_support, set_mipsfpu_single_command,
+ "Select single-precision MIPS floating-point coprocessor.",
+ &mipsfpulist);
+ add_cmd ("double", class_support, set_mipsfpu_double_command,
+ "Select double-precision MIPS floating-point coprocessor .",
+ &mipsfpulist);
+ add_alias_cmd ("on", "double", class_support, 1, &mipsfpulist);
+ add_alias_cmd ("yes", "double", class_support, 1, &mipsfpulist);
+ add_alias_cmd ("1", "double", class_support, 1, &mipsfpulist);
+ add_cmd ("none", class_support, set_mipsfpu_none_command,
+ "Select no MIPS floating-point coprocessor.",
+ &mipsfpulist);
+ add_alias_cmd ("off", "none", class_support, 1, &mipsfpulist);
+ add_alias_cmd ("no", "none", class_support, 1, &mipsfpulist);
+ add_alias_cmd ("0", "none", class_support, 1, &mipsfpulist);
+ add_cmd ("auto", class_support, set_mipsfpu_auto_command,
+ "Select MIPS floating-point coprocessor automatically.",
+ &mipsfpulist);
+ add_cmd ("mipsfpu", class_support, show_mipsfpu_command,
+ "Show current use of MIPS floating-point coprocessor target.",
+ &showlist);
+
+ c = add_set_cmd ("processor", class_support, var_string_noescape,
+ (char *) &tmp_mips_processor_type,
+ "Set the type of MIPS processor in use.\n\
+Set this to be able to access processor-type-specific registers.\n\
+",
+ &setlist);
+ c->function.cfunc = mips_set_processor_type_command;
+ c = add_show_from_set (c, &showlist);
+ c->function.cfunc = mips_show_processor_type_command;
+
+ tmp_mips_processor_type = strsave (DEFAULT_MIPS_TYPE);
+ mips_set_processor_type_command (strsave (DEFAULT_MIPS_TYPE), 0);
+
+ /* We really would like to have both "0" and "unlimited" work, but
+ command.c doesn't deal with that. So make it a var_zinteger
+ because the user can always use "999999" or some such for unlimited. */
+ c = add_set_cmd ("heuristic-fence-post", class_support, var_zinteger,
+ (char *) &heuristic_fence_post,
+ "\
+Set the distance searched for the start of a function.\n\
+If you are debugging a stripped executable, GDB needs to search through the\n\
+program for the start of a function. This command sets the distance of the\n\
+search. The only need to set it is when debugging a stripped executable.",
+ &setlist);
+ /* We need to throw away the frame cache when we set this, since it
+ might change our ability to get backtraces. */
+ c->function.sfunc = reinit_frame_cache_sfunc;
+ add_show_from_set (c, &showlist);
+
+ /* Allow the user to control whether the upper bits of 64-bit
+ addresses should be zeroed. */
+ add_show_from_set
+ (add_set_cmd ("mask-address", no_class, var_boolean, (char *)&mask_address_p,
+ "Set zeroing of upper 32 bits of 64-bit addresses.\n\
+Use \"on\" to enable the masking, and \"off\" to disable it.\n\
+Without an argument, zeroing of upper address bits is enabled.", &setlist),
+ &showlist);
+}
diff --git a/gdb/mipsm3-nat.c b/gdb/mipsm3-nat.c
new file mode 100644
index 00000000000..089ecd6556c
--- /dev/null
+++ b/gdb/mipsm3-nat.c
@@ -0,0 +1,386 @@
+/* Definitions to make GDB run on a mips box under Mach 3.0
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Mach specific routines for little endian mips (e.g. pmax)
+ * running Mach 3.0
+ *
+ * Author: Jukka Virtanen <jtv@hut.fi>
+ */
+
+#include "defs.h"
+#include "inferior.h"
+
+#include <stdio.h>
+
+#include <mach.h>
+#include <mach/message.h>
+#include <mach/exception.h>
+#include <mach_error.h>
+
+/* Find offsets to thread states at compile time.
+ * If your compiler does not grok this, check the hand coded
+ * offsets and use them.
+ */
+
+#if 1
+
+#define REG_OFFSET(reg) (int)(&((struct mips_thread_state *)0)->reg)
+#define CREG_OFFSET(reg) (int)(&((struct mips_float_state *)0)->reg)
+#define EREG_OFFSET(reg) (int)(&((struct mips_exc_state *)0)->reg)
+
+/* at reg_offset[i] is the offset to the mips_thread_state
+ * location where the gdb registers[i] is stored.
+ *
+ * -1 means mach does not save it anywhere.
+ */
+static int reg_offset[] =
+{
+ /* zero at v0 v1 */
+ -1, REG_OFFSET(r1), REG_OFFSET(r2), REG_OFFSET(r3),
+
+ /* a0 a1 a2 a3 */
+ REG_OFFSET(r4), REG_OFFSET(r5), REG_OFFSET(r6), REG_OFFSET(r7),
+
+ /* t0 t1 t2 t3 */
+ REG_OFFSET(r8), REG_OFFSET(r9), REG_OFFSET(r10), REG_OFFSET(r11),
+
+ /* t4 t5 t6 t7 */
+ REG_OFFSET(r12), REG_OFFSET(r13), REG_OFFSET(r14), REG_OFFSET(r15),
+
+ /* s0 s1 s2 s3 */
+ REG_OFFSET(r16), REG_OFFSET(r17), REG_OFFSET(r18), REG_OFFSET(r19),
+
+ /* s4 s5 s6 s7 */
+ REG_OFFSET(r20), REG_OFFSET(r21), REG_OFFSET(r22), REG_OFFSET(r23),
+
+ /* t8 t9 k0 k1 */
+ REG_OFFSET(r24), REG_OFFSET(r25), REG_OFFSET(r26), REG_OFFSET(r27),
+
+ /* gp sp s8(30) == fp(72) ra */
+ REG_OFFSET(r28), REG_OFFSET(r29), REG_OFFSET(r30), REG_OFFSET(r31),
+
+ /* sr(32) PS_REGNUM */
+ EREG_OFFSET(coproc_state),
+
+ /* lo(33) hi(34) */
+ REG_OFFSET(mdlo), REG_OFFSET(mdhi),
+
+ /* bad(35) cause(36) pc(37) */
+ EREG_OFFSET(address), EREG_OFFSET(cause), REG_OFFSET(pc),
+
+ /* f0(38) f1(39) f2(40) f3(41) */
+ CREG_OFFSET(r0), CREG_OFFSET(r1), CREG_OFFSET(r2), CREG_OFFSET(r3),
+ CREG_OFFSET(r4), CREG_OFFSET(r5), CREG_OFFSET(r6), CREG_OFFSET(r7),
+ CREG_OFFSET(r8), CREG_OFFSET(r9), CREG_OFFSET(r10), CREG_OFFSET(r11),
+ CREG_OFFSET(r12), CREG_OFFSET(r13), CREG_OFFSET(r14), CREG_OFFSET(r15),
+ CREG_OFFSET(r16), CREG_OFFSET(r17), CREG_OFFSET(r18), CREG_OFFSET(r19),
+ CREG_OFFSET(r20), CREG_OFFSET(r21), CREG_OFFSET(r22), CREG_OFFSET(r23),
+ CREG_OFFSET(r24), CREG_OFFSET(r25), CREG_OFFSET(r26), CREG_OFFSET(r27),
+ CREG_OFFSET(r28), CREG_OFFSET(r29), CREG_OFFSET(r30), CREG_OFFSET(r31),
+
+ /* fsr(70) fir(71) fp(72) == s8(30) */
+ CREG_OFFSET(csr), CREG_OFFSET(esr), REG_OFFSET(r30)
+};
+#else
+/* If the compiler does not grok the above defines */
+static int reg_offset[] =
+{
+/* mach_thread_state offsets: */
+ -1, 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56,
+ 60, 64, 68, 72, 76, 80, 84, 88, 92, 96,100,104, 108,112,116,120,
+/*sr, lo, hi,addr,cause,pc */
+ 8,124,128, 4, 0,132,
+/* mach_float_state offsets: */
+ 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60,
+ 64, 68, 72, 76, 80, 84, 88, 92, 96,100,104,108, 112,116,120,124,
+/*fsr,fir*/
+ 128,132,
+/* FP_REGNUM pseudo maps to s8==r30 in mach_thread_state */
+ 116
+};
+#endif
+
+/* Fetch COUNT contiguous registers from thread STATE starting from REGNUM
+ * Caller knows that the regs handled in one transaction are of same size.
+ */
+#define FETCH_REGS(state, regnum, count) \
+ memcpy (&registers[REGISTER_BYTE (regnum)], \
+ (char *)state+reg_offset[ regnum ], \
+ count*REGISTER_SIZE)
+
+/* Store COUNT contiguous registers to thread STATE starting from REGNUM */
+#define STORE_REGS(state, regnum, count) \
+ memcpy ((char *)state+reg_offset[ regnum ], \
+ &registers[REGISTER_BYTE (regnum)], \
+ count*REGISTER_SIZE)
+
+#define REGS_ALL -1
+#define REGS_NORMAL 1
+#define REGS_EXC 2
+#define REGS_COP1 4
+
+/* Hardware regs that matches FP_REGNUM */
+#define MACH_FP_REGNUM 30
+
+/* Fech thread's registers. if regno == -1, fetch all regs */
+void
+fetch_inferior_registers (regno)
+ int regno;
+{
+ kern_return_t ret;
+
+ thread_state_data_t state;
+ struct mips_exc_state exc_state;
+
+ int stateCnt = MIPS_THREAD_STATE_COUNT;
+
+ int which_regs = 0; /* A bit mask */
+
+ if (! MACH_PORT_VALID (current_thread))
+ error ("fetch inferior registers: Invalid thread");
+
+ if (regno < -1 || regno >= NUM_REGS)
+ error ("invalid register %d supplied to fetch_inferior_registers", regno);
+
+ if (regno == -1)
+ which_regs = REGS_ALL;
+ else if (regno == ZERO_REGNUM)
+ {
+ int zero = 0;
+ supply_register (ZERO_REGNUM, &zero);
+ return;
+ }
+ else if ((ZERO_REGNUM < regno && regno < PS_REGNUM)
+ || regno == FP_REGNUM
+ || regno == LO_REGNUM
+ || regno == HI_REGNUM
+ || regno == PC_REGNUM)
+ which_regs = REGS_NORMAL;
+ else if (FP0_REGNUM <= regno && regno <= FCRIR_REGNUM)
+ which_regs = REGS_COP1 | REGS_EXC;
+ else
+ which_regs = REGS_EXC;
+
+ /* fetch regs saved to mips_thread_state */
+ if (which_regs & REGS_NORMAL)
+ {
+ ret = thread_get_state (current_thread,
+ MIPS_THREAD_STATE,
+ state,
+ &stateCnt);
+ CHK ("fetch inferior registers: thread_get_state", ret);
+
+ if (which_regs == REGS_NORMAL)
+ {
+ /* Fetch also FP_REGNUM if fetching MACH_FP_REGNUM and vice versa */
+ if (regno == MACH_FP_REGNUM || regno == FP_REGNUM)
+ {
+ supply_register (FP_REGNUM,
+ (char *)state+reg_offset[ MACH_FP_REGNUM ]);
+ supply_register (MACH_FP_REGNUM,
+ (char *)state+reg_offset[ MACH_FP_REGNUM ]);
+ }
+ else
+ supply_register (regno,
+ (char *)state+reg_offset[ regno ]);
+ return;
+ }
+
+ /* ZERO_REGNUM is always zero */
+ *(int *) registers = 0;
+
+ /* Copy thread saved regs 1..31 to gdb's reg value array
+ * Luckily, they are contiquous
+ */
+ FETCH_REGS (state, 1, 31);
+
+ /* Copy mdlo and mdhi */
+ FETCH_REGS (state, LO_REGNUM, 2);
+
+ /* Copy PC */
+ FETCH_REGS (state, PC_REGNUM, 1);
+
+ /* Mach 3.0 saves FP to MACH_FP_REGNUM.
+ * For some reason gdb wants to assign a pseudo register for it.
+ */
+ FETCH_REGS (state, FP_REGNUM, 1);
+ }
+
+ /* Read exc state. Also read if need to fetch floats */
+ if (which_regs & REGS_EXC)
+ {
+ stateCnt = MIPS_EXC_STATE_COUNT;
+ ret = thread_get_state (current_thread,
+ MIPS_EXC_STATE,
+ (thread_state_t) &exc_state,
+ &stateCnt);
+ CHK ("fetch inferior regs (exc): thread_get_state", ret);
+
+ /* We need to fetch exc_state to see if the floating
+ * state is valid for the thread.
+ */
+
+ /* cproc_state: Which coprocessors the thread uses */
+ supply_register (PS_REGNUM,
+ (char *)&exc_state+reg_offset[ PS_REGNUM ]);
+
+ if (which_regs == REGS_EXC || which_regs == REGS_ALL)
+ {
+ supply_register (BADVADDR_REGNUM,
+ (char *)&exc_state+reg_offset[ BADVADDR_REGNUM ]);
+
+ supply_register (CAUSE_REGNUM,
+ (char *)&exc_state+reg_offset[ CAUSE_REGNUM ]);
+ if (which_regs == REGS_EXC)
+ return;
+ }
+ }
+
+
+ if (which_regs & REGS_COP1)
+ {
+ /* If the thread does not have saved COPROC1, set regs to zero */
+
+ if (! (exc_state.coproc_state & MIPS_STATUS_USE_COP1))
+ bzero (&registers[ REGISTER_BYTE (FP0_REGNUM) ],
+ sizeof (struct mips_float_state));
+ else
+ {
+ stateCnt = MIPS_FLOAT_STATE_COUNT;
+ ret = thread_get_state (current_thread,
+ MIPS_FLOAT_STATE,
+ state,
+ &stateCnt);
+ CHK ("fetch inferior regs (floats): thread_get_state", ret);
+
+ if (regno != -1)
+ {
+ supply_register (regno,
+ (char *)state+reg_offset[ regno ]);
+ return;
+ }
+
+ FETCH_REGS (state, FP0_REGNUM, 34);
+ }
+ }
+
+ /* All registers are valid, if not returned yet */
+ registers_fetched ();
+}
+
+/* Store gdb's view of registers to the thread.
+ * All registers are always valid when entering here.
+ * @@ ahem, maybe that is too strict, we could validate the necessary ones
+ * here.
+ *
+ * Hmm. It seems that gdb set $reg=value command first reads everything,
+ * then sets the reg and then stores everything. -> we must make sure
+ * that the immutable registers are not changed by reading them first.
+ */
+
+void
+store_inferior_registers (regno)
+ register int regno;
+{
+ thread_state_data_t state;
+ kern_return_t ret;
+
+ if (! MACH_PORT_VALID (current_thread))
+ error ("store inferior registers: Invalid thread");
+
+ /* Check for read only regs.
+ * @@ If some of these is can be changed, fix this
+ */
+ if (regno == ZERO_REGNUM ||
+ regno == PS_REGNUM ||
+ regno == BADVADDR_REGNUM ||
+ regno == CAUSE_REGNUM ||
+ regno == FCRIR_REGNUM)
+ {
+ message ("You can not alter read-only register `%s'",
+ REGISTER_NAME ( regno ));
+ fetch_inferior_registers (regno);
+ return;
+ }
+
+ if (regno == -1)
+ {
+ /* Don't allow these to change */
+
+ /* ZERO_REGNUM */
+ *(int *)registers = 0;
+
+ fetch_inferior_registers (PS_REGNUM);
+ fetch_inferior_registers (BADVADDR_REGNUM);
+ fetch_inferior_registers (CAUSE_REGNUM);
+ fetch_inferior_registers (FCRIR_REGNUM);
+ }
+
+ if (regno == -1 || (ZERO_REGNUM < regno && regno <= PC_REGNUM))
+ {
+#if 1
+ /* Mach 3.0 saves thread's FP to MACH_FP_REGNUM.
+ * GDB wants assigns a pseudo register FP_REGNUM for frame pointer.
+ *
+ * @@@ Here I assume (!) that gdb's FP has the value that
+ * should go to threads frame pointer. If not true, this
+ * fails badly!!!!!
+ */
+ memcpy (&registers[REGISTER_BYTE (MACH_FP_REGNUM)],
+ &registers[REGISTER_BYTE (FP_REGNUM)],
+ REGISTER_RAW_SIZE (FP_REGNUM));
+#endif
+
+ /* Save gdb's regs 1..31 to thread saved regs 1..31
+ * Luckily, they are contiquous
+ */
+ STORE_REGS (state, 1, 31);
+
+ /* Save mdlo, mdhi */
+ STORE_REGS (state, LO_REGNUM, 2);
+
+ /* Save PC */
+ STORE_REGS (state, PC_REGNUM, 1);
+
+ ret = thread_set_state (current_thread,
+ MIPS_THREAD_STATE,
+ state,
+ MIPS_FLOAT_STATE_COUNT);
+ CHK ("store inferior regs : thread_set_state", ret);
+ }
+
+ if (regno == -1 || regno >= FP0_REGNUM)
+ {
+ /* If thread has floating state, save it */
+ if (read_register (PS_REGNUM) & MIPS_STATUS_USE_COP1)
+ {
+ /* Do NOT save FCRIR_REGNUM */
+ STORE_REGS (state, FP0_REGNUM, 33);
+
+ ret = thread_set_state (current_thread,
+ MIPS_FLOAT_STATE,
+ state,
+ MIPS_FLOAT_STATE_COUNT);
+ CHK ("store inferior registers (floats): thread_set_state", ret);
+ }
+ else if (regno != -1)
+ message
+ ("Thread does not use floating point unit, floating regs not saved");
+ }
+}
diff --git a/gdb/mipsread.c b/gdb/mipsread.c
new file mode 100644
index 00000000000..614c27ec91f
--- /dev/null
+++ b/gdb/mipsread.c
@@ -0,0 +1,446 @@
+/* Read a symbol table in MIPS' format (Third-Eye).
+ Copyright 1986, 87, 89, 90, 91, 92, 93, 94, 95, 96, 1998
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Read symbols from an ECOFF file. Most of the work is done in
+ mdebugread.c. */
+
+#include "defs.h"
+#include "gdb_string.h"
+#include "bfd.h"
+#include "symtab.h"
+#include "symfile.h"
+#include "objfiles.h"
+#include "buildsym.h"
+#include "stabsread.h"
+#include "gdb-stabs.h"
+
+#include "coff/sym.h"
+#include "coff/internal.h"
+#include "coff/ecoff.h"
+#include "libcoff.h" /* Private BFD COFF information. */
+#include "libecoff.h" /* Private BFD ECOFF information. */
+#include "elf/common.h"
+#include "elf/mips.h"
+
+static void
+mipscoff_new_init PARAMS ((struct objfile *));
+
+static void
+mipscoff_symfile_init PARAMS ((struct objfile *));
+
+static void
+mipscoff_symfile_read PARAMS ((struct objfile *, struct section_offsets *,
+ int));
+
+static void
+mipscoff_symfile_finish PARAMS ((struct objfile *));
+
+static void
+read_alphacoff_dynamic_symtab PARAMS ((struct section_offsets *,
+ struct objfile *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). */
+
+extern CORE_ADDR sigtramp_address;
+
+static void
+mipscoff_new_init (ignore)
+ struct objfile *ignore;
+{
+ sigtramp_address = 0;
+ stabsread_new_init ();
+ buildsym_new_init ();
+}
+
+/* Initialize to read a symbol file (nothing to do). */
+
+static void
+mipscoff_symfile_init (objfile)
+ struct objfile *objfile;
+{
+}
+
+/* Read a symbol file from a file. */
+
+static void
+mipscoff_symfile_read (objfile, section_offsets, mainline)
+ struct objfile *objfile;
+ struct section_offsets *section_offsets;
+ int mainline;
+{
+ bfd *abfd = objfile->obfd;
+ struct cleanup * back_to;
+
+ init_minimal_symbol_collection ();
+ back_to = make_cleanup ((make_cleanup_func) discard_minimal_symbols, 0);
+
+ /* Now that the executable file is positioned at symbol table,
+ process it and define symbols accordingly. */
+
+ if (!((*ecoff_backend (abfd)->debug_swap.read_debug_info)
+ (abfd, (asection *) NULL, &ecoff_data (abfd)->debug_info)))
+ error ("Error reading symbol table: %s", bfd_errmsg (bfd_get_error ()));
+
+ mdebug_build_psymtabs (objfile, &ecoff_backend (abfd)->debug_swap,
+ &ecoff_data (abfd)->debug_info, section_offsets);
+
+ /* Add alpha coff dynamic symbols. */
+
+ read_alphacoff_dynamic_symtab (section_offsets, objfile);
+
+ /* Install any minimal symbols that have been collected as the current
+ minimal symbols for this objfile. */
+
+ install_minimal_symbols (objfile);
+
+ /* If the entry_file bounds are still unknown after processing the
+ partial symbols, then try to set them from the minimal symbols
+ surrounding the entry_point. */
+
+ if (mainline
+ && objfile->ei.entry_point != INVALID_ENTRY_POINT
+ && objfile->ei.entry_file_lowpc == INVALID_ENTRY_LOWPC)
+ {
+ struct minimal_symbol *m;
+
+ m = lookup_minimal_symbol_by_pc (objfile->ei.entry_point);
+ if (m && SYMBOL_NAME (m + 1))
+ {
+ objfile->ei.entry_file_lowpc = SYMBOL_VALUE_ADDRESS (m);
+ objfile->ei.entry_file_highpc = SYMBOL_VALUE_ADDRESS (m + 1);
+ }
+ }
+
+ do_cleanups (back_to);
+}
+
+/* Perform any local cleanups required when we are done with a
+ particular objfile. */
+
+static void
+mipscoff_symfile_finish (objfile)
+ struct objfile *objfile;
+{
+}
+
+/* Alpha OSF/1 encapsulates the dynamic symbols in ELF format in a
+ standard coff section. The ELF format for the symbols differs from
+ the format defined in elf/external.h. It seems that a normal ELF 32 bit
+ format is used, and the representation only changes because longs are
+ 64 bit on the alpha. In addition, the handling of text/data section
+ indices for symbols is different from the ELF ABI.
+ As the BFD linker currently does not support dynamic linking on the alpha,
+ there seems to be no reason to pollute BFD with another mixture of object
+ file formats for now. */
+
+/* Format of an alpha external ELF symbol. */
+
+typedef struct {
+ unsigned char st_name[4]; /* Symbol name, index in string tbl */
+ unsigned char st_pad[4]; /* Pad to long word boundary */
+ unsigned char st_value[8]; /* 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 */
+} Elfalpha_External_Sym;
+
+/* Format of an alpha external ELF dynamic info structure. */
+
+typedef struct {
+ unsigned char d_tag[4]; /* Tag */
+ unsigned char d_pad[4]; /* Pad to long word boundary */
+ union {
+ unsigned char d_ptr[8]; /* Pointer value */
+ unsigned char d_val[4]; /* Integer value */
+ } d_un;
+} Elfalpha_External_Dyn;
+
+/* Struct to obtain the section pointers for alpha dynamic symbol info. */
+
+struct alphacoff_dynsecinfo {
+ asection *sym_sect; /* Section pointer for .dynsym section */
+ asection *str_sect; /* Section pointer for .dynstr section */
+ asection *dyninfo_sect; /* Section pointer for .dynamic section */
+ asection *got_sect; /* Section pointer for .got section */
+};
+
+static void
+alphacoff_locate_sections PARAMS ((bfd *, asection *, void *));
+
+/* We are called once per section from read_alphacoff_dynamic_symtab.
+ 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. */
+
+static void
+alphacoff_locate_sections (ignore_abfd, sectp, sip)
+ bfd *ignore_abfd;
+ asection *sectp;
+ PTR sip;
+{
+ register struct alphacoff_dynsecinfo *si;
+
+ si = (struct alphacoff_dynsecinfo *) sip;
+
+ if (STREQ (sectp->name, ".dynsym"))
+ {
+ si->sym_sect = sectp;
+ }
+ else if (STREQ (sectp->name, ".dynstr"))
+ {
+ si->str_sect = sectp;
+ }
+ else if (STREQ (sectp->name, ".dynamic"))
+ {
+ si->dyninfo_sect = sectp;
+ }
+ else if (STREQ (sectp->name, ".got"))
+ {
+ si->got_sect = sectp;
+ }
+}
+
+/* Scan an alpha dynamic symbol table for symbols of interest and
+ add them to the minimal symbol table. */
+
+static void
+read_alphacoff_dynamic_symtab (section_offsets, objfile)
+ struct section_offsets *section_offsets;
+ struct objfile *objfile;
+{
+ bfd *abfd = objfile->obfd;
+ struct alphacoff_dynsecinfo si;
+ char *sym_secptr;
+ char *str_secptr;
+ char *dyninfo_secptr;
+ char *got_secptr;
+ bfd_size_type sym_secsize;
+ bfd_size_type str_secsize;
+ bfd_size_type dyninfo_secsize;
+ bfd_size_type got_secsize;
+ int sym_count;
+ int i;
+ int stripped;
+ Elfalpha_External_Sym *x_symp;
+ char *dyninfo_p;
+ char *dyninfo_end;
+ int got_entry_size = 8;
+ int dt_mips_local_gotno = -1;
+ int dt_mips_gotsym = -1;
+
+
+ /* We currently only know how to handle alpha dynamic symbols. */
+ if (bfd_get_arch (abfd) != bfd_arch_alpha)
+ return;
+
+ /* Locate the dynamic symbols sections and read them in. */
+ memset ((char *) &si, 0, sizeof (si));
+ bfd_map_over_sections (abfd, alphacoff_locate_sections, (PTR) &si);
+ if (si.sym_sect == NULL
+ || si.str_sect == NULL
+ || si.dyninfo_sect == NULL
+ || si.got_sect == NULL)
+ return;
+
+ sym_secsize = bfd_get_section_size_before_reloc (si.sym_sect);
+ str_secsize = bfd_get_section_size_before_reloc (si.str_sect);
+ dyninfo_secsize = bfd_get_section_size_before_reloc (si.dyninfo_sect);
+ got_secsize = bfd_get_section_size_before_reloc (si.got_sect);
+ sym_secptr = alloca (sym_secsize);
+ str_secptr = alloca (str_secsize);
+ dyninfo_secptr = alloca (dyninfo_secsize);
+ got_secptr = alloca (got_secsize);
+
+ if (!bfd_get_section_contents (abfd, si.sym_sect, sym_secptr,
+ (file_ptr)0, sym_secsize))
+ return;
+ if (!bfd_get_section_contents (abfd, si.str_sect, str_secptr,
+ (file_ptr)0, str_secsize))
+ return;
+ if (!bfd_get_section_contents (abfd, si.dyninfo_sect, dyninfo_secptr,
+ (file_ptr)0, dyninfo_secsize))
+ return;
+ if (!bfd_get_section_contents (abfd, si.got_sect, got_secptr,
+ (file_ptr)0, got_secsize))
+ return;
+
+ /* Find the number of local GOT entries and the index for the
+ the first dynamic symbol in the GOT. */
+ for (dyninfo_p = dyninfo_secptr, dyninfo_end = dyninfo_p + dyninfo_secsize;
+ dyninfo_p < dyninfo_end;
+ dyninfo_p += sizeof (Elfalpha_External_Dyn))
+ {
+ Elfalpha_External_Dyn *x_dynp = (Elfalpha_External_Dyn *)dyninfo_p;
+ long dyn_tag;
+
+ dyn_tag = bfd_h_get_32 (abfd, (bfd_byte *) x_dynp->d_tag);
+ if (dyn_tag == DT_NULL)
+ break;
+ else if (dyn_tag == DT_MIPS_LOCAL_GOTNO)
+ {
+ if (dt_mips_local_gotno < 0)
+ dt_mips_local_gotno
+ = bfd_h_get_32 (abfd, (bfd_byte *) x_dynp->d_un.d_val);
+ }
+ else if (dyn_tag == DT_MIPS_GOTSYM)
+ {
+ if (dt_mips_gotsym < 0)
+ dt_mips_gotsym
+ = bfd_h_get_32 (abfd, (bfd_byte *) x_dynp->d_un.d_val);
+ }
+ }
+ if (dt_mips_local_gotno < 0 || dt_mips_gotsym < 0)
+ return;
+
+ /* Scan all dynamic symbols and enter them into the minimal symbol table
+ if appropriate. */
+ sym_count = sym_secsize / sizeof (Elfalpha_External_Sym);
+ stripped = (bfd_get_symcount (abfd) == 0);
+
+ /* Skip first symbol, which is a null dummy. */
+ for (i = 1, x_symp = (Elfalpha_External_Sym *) sym_secptr + 1;
+ i < sym_count;
+ i++, x_symp++)
+ {
+ unsigned long strx;
+ char *name;
+ bfd_vma sym_value;
+ unsigned char sym_info;
+ unsigned int sym_shndx;
+ int isglobal;
+ enum minimal_symbol_type ms_type;
+
+ strx = bfd_h_get_32 (abfd, (bfd_byte *) x_symp->st_name);
+ if (strx >= str_secsize)
+ continue;
+ name = str_secptr + strx;
+ if (*name == '\0' || *name == '.')
+ continue;
+
+ sym_value = bfd_h_get_64 (abfd, (bfd_byte *) x_symp->st_value);
+ sym_info = bfd_h_get_8 (abfd, (bfd_byte *) x_symp->st_info);
+ sym_shndx = bfd_h_get_16 (abfd, (bfd_byte *) x_symp->st_shndx);
+ isglobal = (ELF_ST_BIND (sym_info) == STB_GLOBAL);
+
+ if (sym_shndx == SHN_UNDEF)
+ {
+ /* Handle undefined functions which are defined in a shared
+ library. */
+ if (ELF_ST_TYPE (sym_info) != STT_FUNC
+ || ELF_ST_BIND (sym_info) != STB_GLOBAL)
+ continue;
+
+ ms_type = mst_solib_trampoline;
+
+ /* If sym_value is nonzero, it points to the shared library
+ trampoline entry, which is what we are looking for.
+
+ If sym_value is zero, then we have to get the GOT entry
+ for the symbol.
+ If the GOT entry is nonzero, it represents the quickstart
+ address of the function and we use that as the symbol value.
+
+ If the GOT entry is zero, the function address has to be resolved
+ by the runtime loader before the executable is started.
+ We are unable to find any meaningful address for these
+ functions in the executable file, so we skip them. */
+ if (sym_value == 0)
+ {
+ int got_entry_offset =
+ (i - dt_mips_gotsym + dt_mips_local_gotno) * got_entry_size;
+
+ if (got_entry_offset < 0 || got_entry_offset >= got_secsize)
+ continue;
+ sym_value =
+ bfd_h_get_64 (abfd,
+ (bfd_byte *) (got_secptr + got_entry_offset));
+ if (sym_value == 0)
+ continue;
+ }
+ }
+ else
+ {
+ /* Symbols defined in the executable itself. We only care about
+ them if this is a stripped executable, otherwise they have
+ been retrieved from the normal symbol table already. */
+ if (!stripped)
+ continue;
+
+ if (sym_shndx == SHN_MIPS_TEXT)
+ {
+ if (isglobal)
+ ms_type = mst_text;
+ else
+ ms_type = mst_file_text;
+ sym_value += ANOFFSET (section_offsets, SECT_OFF_TEXT);
+ }
+ else if (sym_shndx == SHN_MIPS_DATA)
+ {
+ if (isglobal)
+ ms_type = mst_data;
+ else
+ ms_type = mst_file_data;
+ sym_value += ANOFFSET (section_offsets, SECT_OFF_DATA);
+ }
+ else if (sym_shndx == SHN_MIPS_ACOMMON)
+ {
+ if (isglobal)
+ ms_type = mst_bss;
+ else
+ ms_type = mst_file_bss;
+ sym_value += ANOFFSET (section_offsets, SECT_OFF_BSS);
+ }
+ else if (sym_shndx == SHN_ABS)
+ {
+ ms_type = mst_abs;
+ }
+ else
+ {
+ continue;
+ }
+ }
+
+ prim_record_minimal_symbol (name, sym_value, ms_type, objfile);
+ }
+}
+
+/* Initialization */
+
+static struct sym_fns ecoff_sym_fns =
+{
+ bfd_target_ecoff_flavour,
+ 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 */
+ default_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);
+}
diff --git a/gdb/mipsv4-nat.c b/gdb/mipsv4-nat.c
new file mode 100644
index 00000000000..df4b6e9a090
--- /dev/null
+++ b/gdb/mipsv4-nat.c
@@ -0,0 +1,159 @@
+/* Native support for MIPS running SVR4, for GDB.
+ Copyright 1994, 1995 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "inferior.h"
+#include "gdbcore.h"
+#include "target.h"
+
+#include <sys/time.h>
+#include <sys/procfs.h>
+#include <setjmp.h> /* For JB_XXX. */
+
+/* Size of elements in jmpbuf */
+
+#define JB_ELEMENT_SIZE 4
+
+/*
+ * See the comment in m68k-tdep.c regarding the utility of these functions.
+ *
+ * These definitions are from the MIPS SVR4 ABI, so they may work for
+ * any MIPS SVR4 target.
+ */
+
+void
+supply_gregset (gregsetp)
+ gregset_t *gregsetp;
+{
+ register int regi;
+ register greg_t *regp = &(*gregsetp)[0];
+ static char zerobuf[MAX_REGISTER_RAW_SIZE] = {0};
+
+ for (regi = 0; regi <= CXT_RA; regi++)
+ supply_register (regi, (char *)(regp + regi));
+
+ supply_register (PC_REGNUM, (char *)(regp + CXT_EPC));
+ supply_register (HI_REGNUM, (char *)(regp + CXT_MDHI));
+ supply_register (LO_REGNUM, (char *)(regp + CXT_MDLO));
+ supply_register (CAUSE_REGNUM, (char *)(regp + CXT_CAUSE));
+
+ /* Fill inaccessible registers with zero. */
+ supply_register (PS_REGNUM, zerobuf);
+ supply_register (BADVADDR_REGNUM, zerobuf);
+ supply_register (FP_REGNUM, zerobuf);
+ supply_register (UNUSED_REGNUM, zerobuf);
+ for (regi = FIRST_EMBED_REGNUM; regi <= LAST_EMBED_REGNUM; regi++)
+ supply_register (regi, zerobuf);
+}
+
+void
+fill_gregset (gregsetp, regno)
+ gregset_t *gregsetp;
+ int regno;
+{
+ int regi;
+ register greg_t *regp = &(*gregsetp)[0];
+
+ for (regi = 0; regi <= 32; regi++)
+ if ((regno == -1) || (regno == regi))
+ *(regp + regi) = *(greg_t *) &registers[REGISTER_BYTE (regi)];
+
+ if ((regno == -1) || (regno == PC_REGNUM))
+ *(regp + CXT_EPC) = *(greg_t *) &registers[REGISTER_BYTE (PC_REGNUM)];
+
+ if ((regno == -1) || (regno == CAUSE_REGNUM))
+ *(regp + CXT_CAUSE) = *(greg_t *) &registers[REGISTER_BYTE (CAUSE_REGNUM)];
+
+ if ((regno == -1) || (regno == HI_REGNUM))
+ *(regp + CXT_MDHI) = *(greg_t *) &registers[REGISTER_BYTE (HI_REGNUM)];
+
+ if ((regno == -1) || (regno == LO_REGNUM))
+ *(regp + CXT_MDLO) = *(greg_t *) &registers[REGISTER_BYTE (LO_REGNUM)];
+}
+
+/*
+ * Now we do the same thing for floating-point registers.
+ * We don't bother to condition on FP0_REGNUM since any
+ * reasonable MIPS configuration has an R3010 in it.
+ *
+ * Again, see the comments in m68k-tdep.c.
+ */
+
+void
+supply_fpregset (fpregsetp)
+ fpregset_t *fpregsetp;
+{
+ register int regi;
+ static char zerobuf[MAX_REGISTER_RAW_SIZE] = {0};
+
+ for (regi = 0; regi < 32; regi++)
+ supply_register (FP0_REGNUM + regi,
+ (char *)&fpregsetp->fp_r.fp_regs[regi]);
+
+ supply_register (FCRCS_REGNUM, (char *)&fpregsetp->fp_csr);
+
+ /* FIXME: how can we supply FCRIR_REGNUM? The ABI doesn't tell us. */
+ supply_register (FCRIR_REGNUM, zerobuf);
+}
+
+void
+fill_fpregset (fpregsetp, regno)
+ fpregset_t *fpregsetp;
+ int regno;
+{
+ int regi;
+ char *from, *to;
+
+ for (regi = FP0_REGNUM; regi < FP0_REGNUM + 32; regi++)
+ {
+ if ((regno == -1) || (regno == regi))
+ {
+ from = (char *) &registers[REGISTER_BYTE (regi)];
+ to = (char *) &(fpregsetp->fp_r.fp_regs[regi - FP0_REGNUM]);
+ memcpy(to, from, REGISTER_RAW_SIZE (regi));
+ }
+ }
+
+ if ((regno == -1) || (regno == FCRCS_REGNUM))
+ fpregsetp->fp_csr = *(unsigned *) &registers[REGISTER_BYTE(FCRCS_REGNUM)];
+}
+
+
+/* Figure out where the longjmp will land.
+ 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 jb_addr;
+
+ jb_addr = read_register (A0_REGNUM);
+
+ 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;
+}
diff --git a/gdb/mn10200-tdep.c b/gdb/mn10200-tdep.c
new file mode 100644
index 00000000000..cb7ead09313
--- /dev/null
+++ b/gdb/mn10200-tdep.c
@@ -0,0 +1,919 @@
+/* Target-dependent code for the Matsushita MN10200 for GDB, the GNU debugger.
+ Copyright 1997 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "frame.h"
+#include "inferior.h"
+#include "obstack.h"
+#include "target.h"
+#include "value.h"
+#include "bfd.h"
+#include "gdb_string.h"
+#include "gdbcore.h"
+#include "symfile.h"
+
+
+/* Should call_function allocate stack space for a struct return? */
+int
+mn10200_use_struct_convention (gcc_p, type)
+ int gcc_p;
+ struct type *type;
+{
+ return (TYPE_NFIELDS (type) > 1 || TYPE_LENGTH (type) > 8);
+}
+
+
+
+/* The main purpose of this file is dealing with prologues to extract
+ information about stack frames and saved registers.
+
+ For reference here's how prologues look on the mn10200:
+
+ With frame pointer:
+ mov fp,a0
+ mov sp,fp
+ add <size>,sp
+ Register saves for d2, d3, a1, a2 as needed. Saves start
+ at fp - <size> + <outgoing_args_size> and work towards higher
+ addresses. Note that the saves are actually done off the stack
+ pointer in the prologue! This makes for smaller code and easier
+ prologue scanning as the displacement fields will unlikely
+ be more than 8 bits!
+
+ Without frame pointer:
+ add <size>,sp
+ Register saves for d2, d3, a1, a2 as needed. Saves start
+ at sp + <outgoing_args_size> and work towards higher addresses.
+
+ Out of line prologue:
+ add <local size>,sp -- optional
+ jsr __prologue
+ add <outgoing_size>,sp -- optional
+
+ The stack pointer remains constant throughout the life of most
+ functions. As a result the compiler will usually omit the
+ frame pointer, so we must handle frame pointerless functions. */
+
+/* Analyze the prologue to determine where registers are saved,
+ the end of the prologue, etc etc. Return the end of the prologue
+ scanned.
+
+ We store into FI (if non-null) several tidbits of information:
+
+ * stack_size -- size of this stack frame. Note that if we stop in
+ certain parts of the prologue/epilogue we may claim the size of the
+ current frame is zero. This happens when the current frame has
+ not been allocated yet or has already been deallocated.
+
+ * fsr -- Addresses of registers saved in the stack by this frame.
+
+ * status -- A (relatively) generic status indicator. It's a bitmask
+ with the following bits:
+
+ MY_FRAME_IN_SP: The base of the current frame is actually in
+ the stack pointer. This can happen for frame pointerless
+ functions, or cases where we're stopped in the prologue/epilogue
+ itself. For these cases mn10200_analyze_prologue will need up
+ update fi->frame before returning or analyzing the register
+ save instructions.
+
+ MY_FRAME_IN_FP: The base of the current frame is in the
+ frame pointer register ($a2).
+
+ CALLER_A2_IN_A0: $a2 from the caller's frame is temporarily
+ in $a0. This can happen if we're stopped in the prologue.
+
+ NO_MORE_FRAMES: Set this if the current frame is "start" or
+ if the first instruction looks like mov <imm>,sp. This tells
+ frame chain to not bother trying to unwind past this frame. */
+
+#define MY_FRAME_IN_SP 0x1
+#define MY_FRAME_IN_FP 0x2
+#define CALLER_A2_IN_A0 0x4
+#define NO_MORE_FRAMES 0x8
+
+static CORE_ADDR
+mn10200_analyze_prologue (fi, pc)
+ struct frame_info *fi;
+ CORE_ADDR pc;
+{
+ CORE_ADDR func_addr, func_end, addr, stop;
+ CORE_ADDR stack_size;
+ unsigned char buf[4];
+ int status;
+ char *name;
+ int out_of_line_prologue = 0;
+
+ /* Use the PC in the frame if it's provided to look up the
+ start of this function. */
+ pc = (fi ? fi->pc : pc);
+
+ /* Find the start of this function. */
+ status = find_pc_partial_function (pc, &name, &func_addr, &func_end);
+
+ /* Do nothing if we couldn't find the start of this function or if we're
+ stopped at the first instruction in the prologue. */
+ if (status == 0)
+ return pc;
+
+ /* If we're in start, then give up. */
+ if (strcmp (name, "start") == 0)
+ {
+ if (fi)
+ fi->status = NO_MORE_FRAMES;
+ return pc;
+ }
+
+ /* At the start of a function our frame is in the stack pointer. */
+ if (fi)
+ fi->status = MY_FRAME_IN_SP;
+
+ /* If we're physically on an RTS instruction, then our frame has already
+ been deallocated.
+
+ fi->frame is bogus, we need to fix it. */
+ if (fi && fi->pc + 1 == func_end)
+ {
+ status = target_read_memory (fi->pc, buf, 1);
+ if (status != 0)
+ {
+ if (fi->next == NULL)
+ fi->frame = read_sp ();
+ return fi->pc;
+ }
+
+ if (buf[0] == 0xfe)
+ {
+ if (fi->next == NULL)
+ fi->frame = read_sp ();
+ return fi->pc;
+ }
+ }
+
+ /* Similarly if we're stopped on the first insn of a prologue as our
+ frame hasn't been allocated yet. */
+ if (fi && fi->pc == func_addr)
+ {
+ if (fi->next == NULL)
+ fi->frame = read_sp ();
+ return fi->pc;
+ }
+
+ /* Figure out where to stop scanning. */
+ stop = fi ? fi->pc : func_end;
+
+ /* Don't walk off the end of the function. */
+ stop = stop > func_end ? func_end : stop;
+
+ /* Start scanning on the first instruction of this function. */
+ addr = func_addr;
+
+ status = target_read_memory (addr, buf, 2);
+ if (status != 0)
+ {
+ if (fi && fi->next == NULL && fi->status & MY_FRAME_IN_SP)
+ fi->frame = read_sp ();
+ return addr;
+ }
+
+ /* First see if this insn sets the stack pointer; if so, it's something
+ we won't understand, so quit now. */
+ if (buf[0] == 0xdf
+ || (buf[0] == 0xf4 && buf[1] == 0x77))
+ {
+ if (fi)
+ fi->status = NO_MORE_FRAMES;
+ return addr;
+ }
+
+ /* Now see if we have a frame pointer.
+
+ Search for mov a2,a0 (0xf278)
+ then mov a3,a2 (0xf27e). */
+
+ if (buf[0] == 0xf2 && buf[1] == 0x78)
+ {
+ /* Our caller's $a2 will be found in $a0 now. Note it for
+ our callers. */
+ if (fi)
+ fi->status |= CALLER_A2_IN_A0;
+ addr += 2;
+ if (addr >= stop)
+ {
+ /* We still haven't allocated our local stack. Handle this
+ as if we stopped on the first or last insn of a function. */
+ if (fi && fi->next == NULL)
+ fi->frame = read_sp ();
+ return addr;
+ }
+
+ status = target_read_memory (addr, buf, 2);
+ if (status != 0)
+ {
+ if (fi && fi->next == NULL)
+ fi->frame = read_sp ();
+ return addr;
+ }
+ if (buf[0] == 0xf2 && buf[1] == 0x7e)
+ {
+ addr += 2;
+
+ /* Our frame pointer is valid now. */
+ if (fi)
+ {
+ fi->status |= MY_FRAME_IN_FP;
+ fi->status &= ~MY_FRAME_IN_SP;
+ }
+ if (addr >= stop)
+ return addr;
+ }
+ else
+ {
+ if (fi && fi->next == NULL)
+ fi->frame = read_sp ();
+ return addr;
+ }
+ }
+
+ /* Next we should allocate the local frame.
+
+ Search for add imm8,a3 (0xd3XX)
+ or add imm16,a3 (0xf70bXXXX)
+ or add imm24,a3 (0xf467XXXXXX).
+
+ If none of the above was found, then this prologue has
+ no stack, and therefore can't have any register saves,
+ so quit now. */
+ status = target_read_memory (addr, buf, 2);
+ if (status != 0)
+ {
+ if (fi && fi->next == NULL && (fi->status & MY_FRAME_IN_SP))
+ fi->frame = read_sp ();
+ return addr;
+ }
+ if (buf[0] == 0xd3)
+ {
+ stack_size = extract_signed_integer (&buf[1], 1);
+ if (fi)
+ fi->stack_size = stack_size;
+ addr += 2;
+ if (addr >= stop)
+ {
+ if (fi && fi->next == NULL && (fi->status & MY_FRAME_IN_SP))
+ fi->frame = read_sp () - stack_size;
+ return addr;
+ }
+ }
+ else if (buf[0] == 0xf7 && buf[1] == 0x0b)
+ {
+ status = target_read_memory (addr + 2, buf, 2);
+ if (status != 0)
+ {
+ if (fi && fi->next == NULL && (fi->status & MY_FRAME_IN_SP))
+ fi->frame = read_sp ();
+ return addr;
+ }
+ stack_size = extract_signed_integer (buf, 2);
+ if (fi)
+ fi->stack_size = stack_size;
+ addr += 4;
+ if (addr >= stop)
+ {
+ if (fi && fi->next == NULL && (fi->status & MY_FRAME_IN_SP))
+ fi->frame = read_sp () - stack_size;
+ return addr;
+ }
+ }
+ else if (buf[0] == 0xf4 && buf[1] == 0x67)
+ {
+ status = target_read_memory (addr + 2, buf, 3);
+ if (status != 0)
+ {
+ if (fi && fi->next == NULL && (fi->status & MY_FRAME_IN_SP))
+ fi->frame = read_sp ();
+ return addr;
+ }
+ stack_size = extract_signed_integer (buf, 3);
+ if (fi)
+ fi->stack_size = stack_size;
+ addr += 5;
+ if (addr >= stop)
+ {
+ if (fi && fi->next == NULL && (fi->status & MY_FRAME_IN_SP))
+ fi->frame = read_sp () - stack_size;
+ return addr;
+ }
+ }
+
+ /* Now see if we have a call to __prologue for an out of line
+ prologue. */
+ status = target_read_memory (addr, buf, 2);
+ if (status != 0)
+ return addr;
+
+ /* First check for 16bit pc-relative call to __prologue. */
+ if (buf[0] == 0xfd)
+ {
+ CORE_ADDR temp;
+ status = target_read_memory (addr + 1, buf, 2);
+ if (status != 0)
+ {
+ if (fi && fi->next == NULL && (fi->status & MY_FRAME_IN_SP))
+ fi->frame = read_sp ();
+ return addr;
+ }
+
+ /* Get the PC this instruction will branch to. */
+ temp = (extract_signed_integer (buf, 2) + addr + 3) & 0xffffff;
+
+ /* Get the name of the function at the target address. */
+ status = find_pc_partial_function (temp, &name, NULL, NULL);
+ if (status == 0)
+ {
+ if (fi && fi->next == NULL && (fi->status & MY_FRAME_IN_SP))
+ fi->frame = read_sp ();
+ return addr;
+ }
+
+ /* Note if it is an out of line prologue. */
+ out_of_line_prologue = (strcmp (name, "__prologue") == 0);
+
+ /* This sucks up 3 bytes of instruction space. */
+ if (out_of_line_prologue)
+ addr += 3;
+
+ if (addr >= stop)
+ {
+ if (fi && fi->next == NULL)
+ {
+ fi->stack_size -= 16;
+ fi->frame = read_sp () - fi->stack_size;
+ }
+ return addr;
+ }
+ }
+ /* Now check for the 24bit pc-relative call to __prologue. */
+ else if (buf[0] == 0xf4 && buf[1] == 0xe1)
+ {
+ CORE_ADDR temp;
+ status = target_read_memory (addr + 2, buf, 3);
+ if (status != 0)
+ {
+ if (fi && fi->next == NULL && (fi->status & MY_FRAME_IN_SP))
+ fi->frame = read_sp ();
+ return addr;
+ }
+
+ /* Get the PC this instruction will branch to. */
+ temp = (extract_signed_integer (buf, 3) + addr + 5) & 0xffffff;
+
+ /* Get the name of the function at the target address. */
+ status = find_pc_partial_function (temp, &name, NULL, NULL);
+ if (status == 0)
+ {
+ if (fi && fi->next == NULL && (fi->status & MY_FRAME_IN_SP))
+ fi->frame = read_sp ();
+ return addr;
+ }
+
+ /* Note if it is an out of line prologue. */
+ out_of_line_prologue = (strcmp (name, "__prologue") == 0);
+
+ /* This sucks up 5 bytes of instruction space. */
+ if (out_of_line_prologue)
+ addr += 5;
+
+ if (addr >= stop)
+ {
+ if (fi && fi->next == NULL && (fi->status & MY_FRAME_IN_SP))
+ {
+ fi->stack_size -= 16;
+ fi->frame = read_sp () - fi->stack_size;
+ }
+ return addr;
+ }
+ }
+
+ /* Now actually handle the out of line prologue. */
+ if (out_of_line_prologue)
+ {
+ int outgoing_args_size = 0;
+
+ /* First adjust the stack size for this function. The out of
+ line prologue saves 4 registers (16bytes of data). */
+ if (fi)
+ fi->stack_size -= 16;
+
+ /* Update fi->frame if necessary. */
+ if (fi && fi->next == NULL)
+ fi->frame = read_sp () - fi->stack_size;
+
+ /* After the out of line prologue, there may be another
+ stack adjustment for the outgoing arguments.
+
+ Search for add imm8,a3 (0xd3XX)
+ or add imm16,a3 (0xf70bXXXX)
+ or add imm24,a3 (0xf467XXXXXX). */
+
+ status = target_read_memory (addr, buf, 2);
+ if (status != 0)
+ {
+ if (fi)
+ {
+ fi->fsr.regs[2] = fi->frame + fi->stack_size + 4;
+ fi->fsr.regs[3] = fi->frame + fi->stack_size + 8;
+ fi->fsr.regs[5] = fi->frame + fi->stack_size + 12;
+ fi->fsr.regs[6] = fi->frame + fi->stack_size + 16;
+ }
+ return addr;
+ }
+
+ if (buf[0] == 0xd3)
+ {
+ outgoing_args_size = extract_signed_integer (&buf[1], 1);
+ addr += 2;
+ }
+ else if (buf[0] == 0xf7 && buf[1] == 0x0b)
+ {
+ status = target_read_memory (addr + 2, buf, 2);
+ if (status != 0)
+ {
+ if (fi)
+ {
+ fi->fsr.regs[2] = fi->frame + fi->stack_size + 4;
+ fi->fsr.regs[3] = fi->frame + fi->stack_size + 8;
+ fi->fsr.regs[5] = fi->frame + fi->stack_size + 12;
+ fi->fsr.regs[6] = fi->frame + fi->stack_size + 16;
+ }
+ return addr;
+ }
+ outgoing_args_size = extract_signed_integer (buf, 2);
+ addr += 4;
+ }
+ else if (buf[0] == 0xf4 && buf[1] == 0x67)
+ {
+ status = target_read_memory (addr + 2, buf, 3);
+ if (status != 0)
+ {
+ if (fi && fi->next == NULL)
+ {
+ fi->fsr.regs[2] = fi->frame + fi->stack_size + 4;
+ fi->fsr.regs[3] = fi->frame + fi->stack_size + 8;
+ fi->fsr.regs[5] = fi->frame + fi->stack_size + 12;
+ fi->fsr.regs[6] = fi->frame + fi->stack_size + 16;
+ }
+ return addr;
+ }
+ outgoing_args_size = extract_signed_integer (buf, 3);
+ addr += 5;
+ }
+ else
+ outgoing_args_size = 0;
+
+ /* Now that we know the size of the outgoing arguments, fix
+ fi->frame again if this is the innermost frame. */
+ if (fi && fi->next == NULL)
+ fi->frame -= outgoing_args_size;
+
+ /* Note the register save information and update the stack
+ size for this frame too. */
+ if (fi)
+ {
+ fi->fsr.regs[2] = fi->frame + fi->stack_size + 4;
+ fi->fsr.regs[3] = fi->frame + fi->stack_size + 8;
+ fi->fsr.regs[5] = fi->frame + fi->stack_size + 12;
+ fi->fsr.regs[6] = fi->frame + fi->stack_size + 16;
+ fi->stack_size += outgoing_args_size;
+ }
+ /* There can be no more prologue insns, so return now. */
+ return addr;
+ }
+
+ /* At this point fi->frame needs to be correct.
+
+ If MY_FRAME_IN_SP is set and we're the innermost frame, then we
+ need to fix fi->frame so that backtracing, find_frame_saved_regs,
+ etc work correctly. */
+ if (fi && fi->next == NULL && (fi->status & MY_FRAME_IN_SP) != 0)
+ fi->frame = read_sp () - fi->stack_size;
+
+ /* And last we have the register saves. These are relatively
+ simple because they're physically done off the stack pointer,
+ and thus the number of different instructions we need to
+ check is greatly reduced because we know the displacements
+ will be small.
+
+ Search for movx d2,(X,a3) (0xf55eXX)
+ then movx d3,(X,a3) (0xf55fXX)
+ then mov a1,(X,a3) (0x5dXX) No frame pointer case
+ then mov a2,(X,a3) (0x5eXX) No frame pointer case
+ or mov a0,(X,a3) (0x5cXX) Frame pointer case. */
+
+ status = target_read_memory (addr, buf, 2);
+ if (status != 0)
+ return addr;
+ if (buf[0] == 0xf5 && buf[1] == 0x5e)
+ {
+ if (fi)
+ {
+ status = target_read_memory (addr + 2, buf, 1);
+ if (status != 0)
+ return addr;
+ fi->fsr.regs[2] = (fi->frame + stack_size
+ + extract_signed_integer (buf, 1));
+ }
+ addr += 3;
+ if (addr >= stop)
+ return addr;
+ status = target_read_memory (addr, buf, 2);
+ if (status != 0)
+ return addr;
+ }
+ if (buf[0] == 0xf5 && buf[1] == 0x5f)
+ {
+ if (fi)
+ {
+ status = target_read_memory (addr + 2, buf, 1);
+ if (status != 0)
+ return addr;
+ fi->fsr.regs[3] = (fi->frame + stack_size
+ + extract_signed_integer (buf, 1));
+ }
+ addr += 3;
+ if (addr >= stop)
+ return addr;
+ status = target_read_memory (addr, buf, 2);
+ if (status != 0)
+ return addr;
+ }
+ if (buf[0] == 0x5d)
+ {
+ if (fi)
+ {
+ status = target_read_memory (addr + 1, buf, 1);
+ if (status != 0)
+ return addr;
+ fi->fsr.regs[5] = (fi->frame + stack_size
+ + extract_signed_integer (buf, 1));
+ }
+ addr += 2;
+ if (addr >= stop)
+ return addr;
+ status = target_read_memory (addr, buf, 2);
+ if (status != 0)
+ return addr;
+ }
+ if (buf[0] == 0x5e || buf[0] == 0x5c)
+ {
+ if (fi)
+ {
+ status = target_read_memory (addr + 1, buf, 1);
+ if (status != 0)
+ return addr;
+ fi->fsr.regs[6] = (fi->frame + stack_size
+ + extract_signed_integer (buf, 1));
+ fi->status &= ~CALLER_A2_IN_A0;
+ }
+ addr += 2;
+ if (addr >= stop)
+ return addr;
+ return addr;
+ }
+ return addr;
+}
+
+/* Function: frame_chain
+ Figure out and return the caller's frame pointer given current
+ frame_info struct.
+
+ We don't handle dummy frames yet but we would probably just return the
+ stack pointer that was in use at the time the function call was made? */
+
+CORE_ADDR
+mn10200_frame_chain (fi)
+ struct frame_info *fi;
+{
+ struct frame_info dummy_frame;
+
+ /* Walk through the prologue to determine the stack size,
+ location of saved registers, end of the prologue, etc. */
+ if (fi->status == 0)
+ mn10200_analyze_prologue (fi, (CORE_ADDR)0);
+
+ /* Quit now if mn10200_analyze_prologue set NO_MORE_FRAMES. */
+ if (fi->status & NO_MORE_FRAMES)
+ return 0;
+
+ /* Now that we've analyzed our prologue, determine the frame
+ pointer for our caller.
+
+ If our caller has a frame pointer, then we need to
+ find the entry value of $a2 to our function.
+
+ If CALLER_A2_IN_A0, then the chain is in $a0.
+
+ If fsr.regs[6] is nonzero, then it's at the memory
+ location pointed to by fsr.regs[6].
+
+ Else it's still in $a2.
+
+ If our caller does not have a frame pointer, then his
+ frame base is fi->frame + -caller's stack size + 4. */
+
+ /* The easiest way to get that info is to analyze our caller's frame.
+
+ So we set up a dummy frame and call mn10200_analyze_prologue to
+ find stuff for us. */
+ dummy_frame.pc = FRAME_SAVED_PC (fi);
+ dummy_frame.frame = fi->frame;
+ memset (dummy_frame.fsr.regs, '\000', sizeof dummy_frame.fsr.regs);
+ dummy_frame.status = 0;
+ dummy_frame.stack_size = 0;
+ mn10200_analyze_prologue (&dummy_frame);
+
+ if (dummy_frame.status & MY_FRAME_IN_FP)
+ {
+ /* Our caller has a frame pointer. So find the frame in $a2, $a0,
+ or in the stack. */
+ if (fi->fsr.regs[6])
+ return (read_memory_integer (fi->fsr.regs[FP_REGNUM], REGISTER_SIZE)
+ & 0xffffff);
+ else if (fi->status & CALLER_A2_IN_A0)
+ return read_register (4);
+ else
+ return read_register (FP_REGNUM);
+ }
+ else
+ {
+ /* Our caller does not have a frame pointer. So his frame starts
+ at the base of our frame (fi->frame) + <his size> + 4 (saved pc). */
+ return fi->frame + -dummy_frame.stack_size + 4;
+ }
+}
+
+/* Function: skip_prologue
+ Return the address of the first inst past the prologue of the function. */
+
+CORE_ADDR
+mn10200_skip_prologue (pc)
+ CORE_ADDR pc;
+{
+ /* We used to check the debug symbols, but that can lose if
+ we have a null prologue. */
+ return mn10200_analyze_prologue (NULL, pc);
+}
+
+/* Function: pop_frame
+ This routine gets called when either the user uses the `return'
+ command, or the call dummy breakpoint gets hit. */
+
+void
+mn10200_pop_frame (frame)
+ struct frame_info *frame;
+{
+ int regnum;
+
+ if (PC_IN_CALL_DUMMY(frame->pc, frame->frame, frame->frame))
+ generic_pop_dummy_frame ();
+ else
+ {
+ write_register (PC_REGNUM, FRAME_SAVED_PC (frame));
+
+ /* Restore any saved registers. */
+ for (regnum = 0; regnum < NUM_REGS; regnum++)
+ if (frame->fsr.regs[regnum] != 0)
+ {
+ ULONGEST value;
+
+ value = read_memory_unsigned_integer (frame->fsr.regs[regnum],
+ REGISTER_RAW_SIZE (regnum));
+ write_register (regnum, value);
+ }
+
+ /* Actually cut back the stack. */
+ write_register (SP_REGNUM, FRAME_FP (frame));
+
+ /* Don't we need to set the PC?!? XXX FIXME. */
+ }
+
+ /* Throw away any cached frame information. */
+ flush_cached_frames ();
+}
+
+/* Function: push_arguments
+ Setup arguments for a call to the target. Arguments go in
+ order on the stack. */
+
+CORE_ADDR
+mn10200_push_arguments (nargs, args, sp, struct_return, struct_addr)
+ int nargs;
+ value_ptr *args;
+ CORE_ADDR sp;
+ unsigned char struct_return;
+ CORE_ADDR struct_addr;
+{
+ int argnum = 0;
+ int len = 0;
+ int stack_offset = 0;
+ int regsused = struct_return ? 1 : 0;
+
+ /* This should be a nop, but align the stack just in case something
+ went wrong. Stacks are two byte aligned on the mn10200. */
+ sp &= ~1;
+
+ /* Now make space on the stack for the args.
+
+ XXX This doesn't appear to handle pass-by-invisible reference
+ arguments. */
+ for (argnum = 0; argnum < nargs; argnum++)
+ {
+ int arg_length = (TYPE_LENGTH (VALUE_TYPE (args[argnum])) + 1) & ~1;
+
+ /* If we've used all argument registers, then this argument is
+ pushed. */
+ if (regsused >= 2 || arg_length > 4)
+ {
+ regsused = 2;
+ len += arg_length;
+ }
+ /* We know we've got some arg register space left. If this argument
+ will fit entirely in regs, then put it there. */
+ else if (arg_length <= 2
+ || TYPE_CODE (VALUE_TYPE (args[argnum])) == TYPE_CODE_PTR)
+ {
+ regsused++;
+ }
+ else if (regsused == 0)
+ {
+ regsused = 2;
+ }
+ else
+ {
+ regsused = 2;
+ len += arg_length;
+ }
+ }
+
+ /* Allocate stack space. */
+ sp -= len;
+
+ regsused = struct_return ? 1 : 0;
+ /* Push all arguments onto the stack. */
+ for (argnum = 0; argnum < nargs; argnum++)
+ {
+ int len;
+ char *val;
+
+ /* XXX Check this. What about UNIONS? */
+ if (TYPE_CODE (VALUE_TYPE (*args)) == TYPE_CODE_STRUCT
+ && TYPE_LENGTH (VALUE_TYPE (*args)) > 8)
+ {
+ /* XXX Wrong, we want a pointer to this argument. */
+ len = TYPE_LENGTH (VALUE_TYPE (*args));
+ val = (char *)VALUE_CONTENTS (*args);
+ }
+ else
+ {
+ len = TYPE_LENGTH (VALUE_TYPE (*args));
+ val = (char *)VALUE_CONTENTS (*args);
+ }
+
+ if (regsused < 2
+ && (len <= 2
+ || TYPE_CODE (VALUE_TYPE (*args)) == TYPE_CODE_PTR))
+ {
+ write_register (regsused, extract_unsigned_integer (val, 4));
+ regsused++;
+ }
+ else if (regsused == 0 && len == 4)
+ {
+ write_register (regsused, extract_unsigned_integer (val, 2));
+ write_register (regsused + 1, extract_unsigned_integer (val + 2, 2));
+ regsused = 2;
+ }
+ else
+ {
+ regsused = 2;
+ while (len > 0)
+ {
+ write_memory (sp + stack_offset, val, 2);
+
+ len -= 2;
+ val += 2;
+ stack_offset += 2;
+ }
+ }
+ args++;
+ }
+
+ return sp;
+}
+
+/* Function: push_return_address (pc)
+ Set up the return address for the inferior function call.
+ Needed for targets where we don't actually execute a JSR/BSR instruction */
+
+CORE_ADDR
+mn10200_push_return_address (pc, sp)
+ CORE_ADDR pc;
+ CORE_ADDR sp;
+{
+ unsigned char buf[4];
+
+ store_unsigned_integer (buf, 4, CALL_DUMMY_ADDRESS ());
+ write_memory (sp - 4, buf, 4);
+ return sp - 4;
+}
+
+/* Function: store_struct_return (addr,sp)
+ Store the structure value return address for an inferior function
+ call. */
+
+CORE_ADDR
+mn10200_store_struct_return (addr, sp)
+ CORE_ADDR addr;
+ CORE_ADDR sp;
+{
+ /* The structure return address is passed as the first argument. */
+ write_register (0, addr);
+ return sp;
+}
+
+/* Function: frame_saved_pc
+ Find the caller of this frame. We do this by seeing if RP_REGNUM
+ is saved in the stack anywhere, otherwise we get it from the
+ registers. If the inner frame is a dummy frame, return its PC
+ instead of RP, because that's where "caller" of the dummy-frame
+ will be found. */
+
+CORE_ADDR
+mn10200_frame_saved_pc (fi)
+ struct frame_info *fi;
+{
+ /* The saved PC will always be at the base of the current frame. */
+ return (read_memory_integer (fi->frame, REGISTER_SIZE) & 0xffffff);
+}
+
+void
+get_saved_register (raw_buffer, optimized, addrp, frame, regnum, lval)
+ char *raw_buffer;
+ int *optimized;
+ CORE_ADDR *addrp;
+ struct frame_info *frame;
+ int regnum;
+ enum lval_type *lval;
+{
+ generic_get_saved_register (raw_buffer, optimized, addrp,
+ frame, regnum, lval);
+}
+
+/* Function: init_extra_frame_info
+ Setup the frame's frame pointer, pc, and frame addresses for saved
+ registers. Most of the work is done in mn10200_analyze_prologue().
+
+ Note that when we are called for the last frame (currently active frame),
+ that fi->pc and fi->frame will already be setup. However, fi->frame will
+ be valid only if this routine uses FP. For previous frames, fi-frame will
+ always be correct. mn10200_analyze_prologue will fix fi->frame if
+ it's not valid.
+
+ We can be called with the PC in the call dummy under two circumstances.
+ First, during normal backtracing, second, while figuring out the frame
+ pointer just prior to calling the target function (see run_stack_dummy). */
+
+void
+mn10200_init_extra_frame_info (fi)
+ struct frame_info *fi;
+{
+ if (fi->next)
+ fi->pc = FRAME_SAVED_PC (fi->next);
+
+ memset (fi->fsr.regs, '\000', sizeof fi->fsr.regs);
+ fi->status = 0;
+ fi->stack_size = 0;
+
+ mn10200_analyze_prologue (fi, 0);
+}
+
+void
+_initialize_mn10200_tdep ()
+{
+ tm_print_insn = print_insn_mn10200;
+}
+
diff --git a/gdb/mn10300-tdep.c b/gdb/mn10300-tdep.c
new file mode 100644
index 00000000000..6c43176193b
--- /dev/null
+++ b/gdb/mn10300-tdep.c
@@ -0,0 +1,791 @@
+/* Target-dependent code for the Matsushita MN10300 for GDB, the GNU debugger.
+ Copyright 1996, 1997, 1998 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "frame.h"
+#include "inferior.h"
+#include "obstack.h"
+#include "target.h"
+#include "value.h"
+#include "bfd.h"
+#include "gdb_string.h"
+#include "gdbcore.h"
+#include "symfile.h"
+
+static char *mn10300_generic_register_names[] =
+{ "d0", "d1", "d2", "d3", "a0", "a1", "a2", "a3",
+ "sp", "pc", "mdr", "psw", "lir", "lar", "", "",
+ "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "fp" };
+
+char **mn10300_register_names = mn10300_generic_register_names;
+
+static CORE_ADDR mn10300_analyze_prologue PARAMS ((struct frame_info *fi,
+ CORE_ADDR pc));
+
+/* Additional info used by the frame */
+
+struct frame_extra_info
+{
+ int status;
+ int stack_size;
+};
+
+static struct frame_info *analyze_dummy_frame PARAMS ((CORE_ADDR, CORE_ADDR));
+static struct frame_info *
+analyze_dummy_frame (pc, frame)
+ CORE_ADDR pc;
+ CORE_ADDR frame;
+{
+ static struct frame_info *dummy = NULL;
+ if (dummy == NULL)
+ {
+ dummy = xmalloc (sizeof (struct frame_info));
+ dummy->saved_regs = xmalloc (SIZEOF_FRAME_SAVED_REGS);
+ dummy->extra_info = xmalloc (sizeof (struct frame_extra_info));
+ }
+ dummy->next = NULL;
+ dummy->prev = NULL;
+ dummy->pc = pc;
+ dummy->frame = frame;
+ dummy->extra_info->status = 0;
+ dummy->extra_info->stack_size = 0;
+ memset (dummy->saved_regs, '\000', SIZEOF_FRAME_SAVED_REGS);
+ mn10300_analyze_prologue (dummy, 0);
+ return dummy;
+}
+
+/* Values for frame_info.status */
+
+#define MY_FRAME_IN_SP 0x1
+#define MY_FRAME_IN_FP 0x2
+#define NO_MORE_FRAMES 0x4
+
+
+/* Should call_function allocate stack space for a struct return? */
+int
+mn10300_use_struct_convention (gcc_p, type)
+ int gcc_p;
+ struct type *type;
+{
+ return (TYPE_NFIELDS (type) > 1 || TYPE_LENGTH (type) > 8);
+}
+
+/* The breakpoint instruction must be the same size as the smallest
+ instruction in the instruction set.
+
+ The Matsushita mn10x00 processors have single byte instructions
+ so we need a single byte breakpoint. Matsushita hasn't defined
+ one, so we defined it ourselves. */
+
+unsigned char *
+mn10300_breakpoint_from_pc (bp_addr, bp_size)
+ CORE_ADDR *bp_addr;
+ int *bp_size;
+{
+ static char breakpoint[] = {0xff};
+ *bp_size = 1;
+ return breakpoint;
+}
+
+
+/* Fix fi->frame if it's bogus at this point. This is a helper
+ function for mn10300_analyze_prologue. */
+
+static void
+fix_frame_pointer (fi, stack_size)
+ struct frame_info *fi;
+ int stack_size;
+{
+ if (fi && fi->next == NULL)
+ {
+ if (fi->extra_info->status & MY_FRAME_IN_SP)
+ fi->frame = read_sp () - stack_size;
+ else if (fi->extra_info->status & MY_FRAME_IN_FP)
+ fi->frame = read_register (A3_REGNUM);
+ }
+}
+
+
+/* Set offsets of registers saved by movm instruction.
+ This is a helper function for mn10300_analyze_prologue. */
+
+static void
+set_movm_offsets (fi, movm_args)
+ struct frame_info *fi;
+ int movm_args;
+{
+ int offset = 0;
+
+ if (fi == NULL || movm_args == 0)
+ return;
+
+ if (movm_args & 0x10)
+ {
+ fi->saved_regs[A3_REGNUM] = fi->frame + offset;
+ offset += 4;
+ }
+ if (movm_args & 0x20)
+ {
+ fi->saved_regs[A2_REGNUM] = fi->frame + offset;
+ offset += 4;
+ }
+ if (movm_args & 0x40)
+ {
+ fi->saved_regs[D3_REGNUM] = fi->frame + offset;
+ offset += 4;
+ }
+ if (movm_args & 0x80)
+ {
+ fi->saved_regs[D2_REGNUM] = fi->frame + offset;
+ offset += 4;
+ }
+}
+
+
+/* The main purpose of this file is dealing with prologues to extract
+ information about stack frames and saved registers.
+
+ For reference here's how prologues look on the mn10300:
+
+ With frame pointer:
+ movm [d2,d3,a2,a3],sp
+ mov sp,a3
+ add <size>,sp
+
+ Without frame pointer:
+ movm [d2,d3,a2,a3],sp (if needed)
+ add <size>,sp
+
+ One day we might keep the stack pointer constant, that won't
+ change the code for prologues, but it will make the frame
+ pointerless case much more common. */
+
+/* Analyze the prologue to determine where registers are saved,
+ the end of the prologue, etc etc. Return the end of the prologue
+ scanned.
+
+ We store into FI (if non-null) several tidbits of information:
+
+ * stack_size -- size of this stack frame. Note that if we stop in
+ certain parts of the prologue/epilogue we may claim the size of the
+ current frame is zero. This happens when the current frame has
+ not been allocated yet or has already been deallocated.
+
+ * fsr -- Addresses of registers saved in the stack by this frame.
+
+ * status -- A (relatively) generic status indicator. It's a bitmask
+ with the following bits:
+
+ MY_FRAME_IN_SP: The base of the current frame is actually in
+ the stack pointer. This can happen for frame pointerless
+ functions, or cases where we're stopped in the prologue/epilogue
+ itself. For these cases mn10300_analyze_prologue will need up
+ update fi->frame before returning or analyzing the register
+ save instructions.
+
+ MY_FRAME_IN_FP: The base of the current frame is in the
+ frame pointer register ($a2).
+
+ NO_MORE_FRAMES: Set this if the current frame is "start" or
+ if the first instruction looks like mov <imm>,sp. This tells
+ frame chain to not bother trying to unwind past this frame. */
+
+static CORE_ADDR
+mn10300_analyze_prologue (fi, pc)
+ struct frame_info *fi;
+ CORE_ADDR pc;
+{
+ CORE_ADDR func_addr, func_end, addr, stop;
+ CORE_ADDR stack_size;
+ int imm_size;
+ unsigned char buf[4];
+ int status, movm_args = 0;
+ char *name;
+
+ /* Use the PC in the frame if it's provided to look up the
+ start of this function. */
+ pc = (fi ? fi->pc : pc);
+
+ /* Find the start of this function. */
+ status = find_pc_partial_function (pc, &name, &func_addr, &func_end);
+
+ /* Do nothing if we couldn't find the start of this function or if we're
+ stopped at the first instruction in the prologue. */
+ if (status == 0)
+ return pc;
+
+ /* If we're in start, then give up. */
+ if (strcmp (name, "start") == 0)
+ {
+ if (fi != NULL)
+ fi->extra_info->status = NO_MORE_FRAMES;
+ return pc;
+ }
+
+ /* At the start of a function our frame is in the stack pointer. */
+ if (fi)
+ fi->extra_info->status = MY_FRAME_IN_SP;
+
+ /* Get the next two bytes into buf, we need two because rets is a two
+ byte insn and the first isn't enough to uniquely identify it. */
+ status = read_memory_nobpt (pc, buf, 2);
+ if (status != 0)
+ return pc;
+
+ /* If we're physically on an "rets" instruction, then our frame has
+ already been deallocated. Note this can also be true for retf
+ and ret if they specify a size of zero.
+
+ In this case fi->frame is bogus, we need to fix it. */
+ if (fi && buf[0] == 0xf0 && buf[1] == 0xfc)
+ {
+ if (fi->next == NULL)
+ fi->frame = read_sp ();
+ return fi->pc;
+ }
+
+ /* Similarly if we're stopped on the first insn of a prologue as our
+ frame hasn't been allocated yet. */
+ if (fi && fi->pc == func_addr)
+ {
+ if (fi->next == NULL)
+ fi->frame = read_sp ();
+ return fi->pc;
+ }
+
+ /* Figure out where to stop scanning. */
+ stop = fi ? fi->pc : func_end;
+
+ /* Don't walk off the end of the function. */
+ stop = stop > func_end ? func_end : stop;
+
+ /* Start scanning on the first instruction of this function. */
+ addr = func_addr;
+
+ /* Suck in two bytes. */
+ status = read_memory_nobpt (addr, buf, 2);
+ if (status != 0)
+ {
+ fix_frame_pointer (fi, 0);
+ return addr;
+ }
+
+ /* First see if this insn sets the stack pointer; if so, it's something
+ we won't understand, so quit now. */
+ if (buf[0] == 0xf2 && (buf[1] & 0xf3) == 0xf0)
+ {
+ if (fi)
+ fi->extra_info->status = NO_MORE_FRAMES;
+ return addr;
+ }
+
+ /* Now look for movm [regs],sp, which saves the callee saved registers.
+
+ At this time we don't know if fi->frame is valid, so we only note
+ that we encountered a movm instruction. Later, we'll set the entries
+ in fsr.regs as needed. */
+ if (buf[0] == 0xcf)
+ {
+ /* Extract the register list for the movm instruction. */
+ status = read_memory_nobpt (addr + 1, buf, 1);
+ movm_args = *buf;
+
+ addr += 2;
+
+ /* Quit now if we're beyond the stop point. */
+ if (addr >= stop)
+ {
+ /* Fix fi->frame since it's bogus at this point. */
+ if (fi && fi->next == NULL)
+ fi->frame = read_sp ();
+
+ /* Note if/where callee saved registers were saved. */
+ set_movm_offsets (fi, movm_args);
+ return addr;
+ }
+
+ /* Get the next two bytes so the prologue scan can continue. */
+ status = read_memory_nobpt (addr, buf, 2);
+ if (status != 0)
+ {
+ /* Fix fi->frame since it's bogus at this point. */
+ if (fi && fi->next == NULL)
+ fi->frame = read_sp ();
+
+ /* Note if/where callee saved registers were saved. */
+ set_movm_offsets (fi, movm_args);
+ return addr;
+ }
+ }
+
+ /* Now see if we set up a frame pointer via "mov sp,a3" */
+ if (buf[0] == 0x3f)
+ {
+ addr += 1;
+
+ /* The frame pointer is now valid. */
+ if (fi)
+ {
+ fi->extra_info->status |= MY_FRAME_IN_FP;
+ fi->extra_info->status &= ~MY_FRAME_IN_SP;
+ }
+
+ /* Quit now if we're beyond the stop point. */
+ if (addr >= stop)
+ {
+ /* Fix fi->frame if it's bogus at this point. */
+ fix_frame_pointer (fi, 0);
+
+ /* Note if/where callee saved registers were saved. */
+ set_movm_offsets (fi, movm_args);
+ return addr;
+ }
+
+ /* Get two more bytes so scanning can continue. */
+ status = read_memory_nobpt (addr, buf, 2);
+ if (status != 0)
+ {
+ /* Fix fi->frame if it's bogus at this point. */
+ fix_frame_pointer (fi, 0);
+
+ /* Note if/where callee saved registers were saved. */
+ set_movm_offsets (fi, movm_args);
+ return addr;
+ }
+ }
+
+ /* Next we should allocate the local frame. No more prologue insns
+ are found after allocating the local frame.
+
+ Search for add imm8,sp (0xf8feXX)
+ or add imm16,sp (0xfafeXXXX)
+ or add imm32,sp (0xfcfeXXXXXXXX).
+
+ If none of the above was found, then this prologue has no
+ additional stack. */
+
+ status = read_memory_nobpt (addr, buf, 2);
+ if (status != 0)
+ {
+ /* Fix fi->frame if it's bogus at this point. */
+ fix_frame_pointer (fi, 0);
+
+ /* Note if/where callee saved registers were saved. */
+ set_movm_offsets (fi, movm_args);
+ return addr;
+ }
+
+ imm_size = 0;
+ if (buf[0] == 0xf8 && buf[1] == 0xfe)
+ imm_size = 1;
+ else if (buf[0] == 0xfa && buf[1] == 0xfe)
+ imm_size = 2;
+ else if (buf[0] == 0xfc && buf[1] == 0xfe)
+ imm_size = 4;
+
+ if (imm_size != 0)
+ {
+ /* Suck in imm_size more bytes, they'll hold the size of the
+ current frame. */
+ status = read_memory_nobpt (addr + 2, buf, imm_size);
+ if (status != 0)
+ {
+ /* Fix fi->frame if it's bogus at this point. */
+ fix_frame_pointer (fi, 0);
+
+ /* Note if/where callee saved registers were saved. */
+ set_movm_offsets (fi, movm_args);
+ return addr;
+ }
+
+ /* Note the size of the stack in the frame info structure. */
+ stack_size = extract_signed_integer (buf, imm_size);
+ if (fi)
+ fi->extra_info->stack_size = stack_size;
+
+ /* We just consumed 2 + imm_size bytes. */
+ addr += 2 + imm_size;
+
+ /* No more prologue insns follow, so begin preparation to return. */
+ /* Fix fi->frame if it's bogus at this point. */
+ fix_frame_pointer (fi, stack_size);
+
+ /* Note if/where callee saved registers were saved. */
+ set_movm_offsets (fi, movm_args);
+ return addr;
+ }
+
+ /* We never found an insn which allocates local stack space, regardless
+ this is the end of the prologue. */
+ /* Fix fi->frame if it's bogus at this point. */
+ fix_frame_pointer (fi, 0);
+
+ /* Note if/where callee saved registers were saved. */
+ set_movm_offsets (fi, movm_args);
+ return addr;
+}
+
+/* Function: frame_chain
+ Figure out and return the caller's frame pointer given current
+ frame_info struct.
+
+ We don't handle dummy frames yet but we would probably just return the
+ stack pointer that was in use at the time the function call was made? */
+
+CORE_ADDR
+mn10300_frame_chain (fi)
+ struct frame_info *fi;
+{
+ struct frame_info *dummy;
+ /* Walk through the prologue to determine the stack size,
+ location of saved registers, end of the prologue, etc. */
+ if (fi->extra_info->status == 0)
+ mn10300_analyze_prologue (fi, (CORE_ADDR)0);
+
+ /* Quit now if mn10300_analyze_prologue set NO_MORE_FRAMES. */
+ if (fi->extra_info->status & NO_MORE_FRAMES)
+ return 0;
+
+ /* Now that we've analyzed our prologue, determine the frame
+ pointer for our caller.
+
+ If our caller has a frame pointer, then we need to
+ find the entry value of $a3 to our function.
+
+ If fsr.regs[A3_REGNUM] is nonzero, then it's at the memory
+ location pointed to by fsr.regs[A3_REGNUM].
+
+ Else it's still in $a3.
+
+ If our caller does not have a frame pointer, then his
+ frame base is fi->frame + -caller's stack size. */
+
+ /* The easiest way to get that info is to analyze our caller's frame.
+ So we set up a dummy frame and call mn10300_analyze_prologue to
+ find stuff for us. */
+ dummy = analyze_dummy_frame (FRAME_SAVED_PC (fi), fi->frame);
+
+ if (dummy->extra_info->status & MY_FRAME_IN_FP)
+ {
+ /* Our caller has a frame pointer. So find the frame in $a3 or
+ in the stack. */
+ if (fi->saved_regs[A3_REGNUM])
+ return (read_memory_integer (fi->saved_regs[A3_REGNUM], REGISTER_SIZE));
+ else
+ return read_register (A3_REGNUM);
+ }
+ else
+ {
+ int adjust = 0;
+
+ adjust += (fi->saved_regs[D2_REGNUM] ? 4 : 0);
+ adjust += (fi->saved_regs[D3_REGNUM] ? 4 : 0);
+ adjust += (fi->saved_regs[A2_REGNUM] ? 4 : 0);
+ adjust += (fi->saved_regs[A3_REGNUM] ? 4 : 0);
+
+ /* Our caller does not have a frame pointer. So his frame starts
+ at the base of our frame (fi->frame) + register save space
+ + <his size>. */
+ return fi->frame + adjust + -dummy->extra_info->stack_size;
+ }
+}
+
+/* Function: skip_prologue
+ Return the address of the first inst past the prologue of the function. */
+
+CORE_ADDR
+mn10300_skip_prologue (pc)
+ CORE_ADDR pc;
+{
+ /* We used to check the debug symbols, but that can lose if
+ we have a null prologue. */
+ return mn10300_analyze_prologue (NULL, pc);
+}
+
+
+/* Function: pop_frame
+ This routine gets called when either the user uses the `return'
+ command, or the call dummy breakpoint gets hit. */
+
+void
+mn10300_pop_frame (frame)
+ struct frame_info *frame;
+{
+ int regnum;
+
+ if (PC_IN_CALL_DUMMY(frame->pc, frame->frame, frame->frame))
+ generic_pop_dummy_frame ();
+ else
+ {
+ write_register (PC_REGNUM, FRAME_SAVED_PC (frame));
+
+ /* Restore any saved registers. */
+ for (regnum = 0; regnum < NUM_REGS; regnum++)
+ if (frame->saved_regs[regnum] != 0)
+ {
+ ULONGEST value;
+
+ value = read_memory_unsigned_integer (frame->saved_regs[regnum],
+ REGISTER_RAW_SIZE (regnum));
+ write_register (regnum, value);
+ }
+
+ /* Actually cut back the stack. */
+ write_register (SP_REGNUM, FRAME_FP (frame));
+
+ /* Don't we need to set the PC?!? XXX FIXME. */
+ }
+
+ /* Throw away any cached frame information. */
+ flush_cached_frames ();
+}
+
+/* Function: push_arguments
+ Setup arguments for a call to the target. Arguments go in
+ order on the stack. */
+
+CORE_ADDR
+mn10300_push_arguments (nargs, args, sp, struct_return, struct_addr)
+ int nargs;
+ value_ptr *args;
+ CORE_ADDR sp;
+ unsigned char struct_return;
+ CORE_ADDR struct_addr;
+{
+ int argnum = 0;
+ int len = 0;
+ int stack_offset = 0;
+ int regsused = struct_return ? 1 : 0;
+
+ /* This should be a nop, but align the stack just in case something
+ went wrong. Stacks are four byte aligned on the mn10300. */
+ sp &= ~3;
+
+ /* Now make space on the stack for the args.
+
+ XXX This doesn't appear to handle pass-by-invisible reference
+ arguments. */
+ for (argnum = 0; argnum < nargs; argnum++)
+ {
+ int arg_length = (TYPE_LENGTH (VALUE_TYPE (args[argnum])) + 3) & ~3;
+
+ while (regsused < 2 && arg_length > 0)
+ {
+ regsused++;
+ arg_length -= 4;
+ }
+ len += arg_length;
+ }
+
+ /* Allocate stack space. */
+ sp -= len;
+
+ regsused = struct_return ? 1 : 0;
+ /* Push all arguments onto the stack. */
+ for (argnum = 0; argnum < nargs; argnum++)
+ {
+ int len;
+ char *val;
+
+ /* XXX Check this. What about UNIONS? */
+ if (TYPE_CODE (VALUE_TYPE (*args)) == TYPE_CODE_STRUCT
+ && TYPE_LENGTH (VALUE_TYPE (*args)) > 8)
+ {
+ /* XXX Wrong, we want a pointer to this argument. */
+ len = TYPE_LENGTH (VALUE_TYPE (*args));
+ val = (char *)VALUE_CONTENTS (*args);
+ }
+ else
+ {
+ len = TYPE_LENGTH (VALUE_TYPE (*args));
+ val = (char *)VALUE_CONTENTS (*args);
+ }
+
+ while (regsused < 2 && len > 0)
+ {
+ write_register (regsused, extract_unsigned_integer (val, 4));
+ val += 4;
+ len -= 4;
+ regsused++;
+ }
+
+ while (len > 0)
+ {
+ write_memory (sp + stack_offset, val, 4);
+ len -= 4;
+ val += 4;
+ stack_offset += 4;
+ }
+
+ args++;
+ }
+
+ /* Make space for the flushback area. */
+ sp -= 8;
+ return sp;
+}
+
+/* Function: push_return_address (pc)
+ Set up the return address for the inferior function call.
+ Needed for targets where we don't actually execute a JSR/BSR instruction */
+
+CORE_ADDR
+mn10300_push_return_address (pc, sp)
+ CORE_ADDR pc;
+ CORE_ADDR sp;
+{
+ unsigned char buf[4];
+
+ store_unsigned_integer (buf, 4, CALL_DUMMY_ADDRESS ());
+ write_memory (sp - 4, buf, 4);
+ return sp - 4;
+}
+
+/* Function: store_struct_return (addr,sp)
+ Store the structure value return address for an inferior function
+ call. */
+
+CORE_ADDR
+mn10300_store_struct_return (addr, sp)
+ CORE_ADDR addr;
+ CORE_ADDR sp;
+{
+ /* The structure return address is passed as the first argument. */
+ write_register (0, addr);
+ return sp;
+}
+
+/* Function: frame_saved_pc
+ Find the caller of this frame. We do this by seeing if RP_REGNUM
+ is saved in the stack anywhere, otherwise we get it from the
+ registers. If the inner frame is a dummy frame, return its PC
+ instead of RP, because that's where "caller" of the dummy-frame
+ will be found. */
+
+CORE_ADDR
+mn10300_frame_saved_pc (fi)
+ struct frame_info *fi;
+{
+ int adjust = 0;
+
+ adjust += (fi->saved_regs[D2_REGNUM] ? 4 : 0);
+ adjust += (fi->saved_regs[D3_REGNUM] ? 4 : 0);
+ adjust += (fi->saved_regs[A2_REGNUM] ? 4 : 0);
+ adjust += (fi->saved_regs[A3_REGNUM] ? 4 : 0);
+
+ return (read_memory_integer (fi->frame + adjust, REGISTER_SIZE));
+}
+
+void
+get_saved_register (raw_buffer, optimized, addrp, frame, regnum, lval)
+ char *raw_buffer;
+ int *optimized;
+ CORE_ADDR *addrp;
+ struct frame_info *frame;
+ int regnum;
+ enum lval_type *lval;
+{
+ generic_get_saved_register (raw_buffer, optimized, addrp,
+ frame, regnum, lval);
+}
+
+/* Function: mn10300_init_extra_frame_info
+ Setup the frame's frame pointer, pc, and frame addresses for saved
+ registers. Most of the work is done in mn10300_analyze_prologue().
+
+ Note that when we are called for the last frame (currently active frame),
+ that fi->pc and fi->frame will already be setup. However, fi->frame will
+ be valid only if this routine uses FP. For previous frames, fi-frame will
+ always be correct. mn10300_analyze_prologue will fix fi->frame if
+ it's not valid.
+
+ We can be called with the PC in the call dummy under two circumstances.
+ First, during normal backtracing, second, while figuring out the frame
+ pointer just prior to calling the target function (see run_stack_dummy). */
+
+void
+mn10300_init_extra_frame_info (fi)
+ struct frame_info *fi;
+{
+ if (fi->next)
+ fi->pc = FRAME_SAVED_PC (fi->next);
+
+ frame_saved_regs_zalloc (fi);
+ fi->extra_info = (struct frame_extra_info *)
+ frame_obstack_alloc (sizeof (struct frame_extra_info));
+
+ fi->extra_info->status = 0;
+ fi->extra_info->stack_size = 0;
+
+ mn10300_analyze_prologue (fi, 0);
+}
+
+/* Function: mn10300_virtual_frame_pointer
+ Return the register that the function uses for a frame pointer,
+ plus any necessary offset to be applied to the register before
+ any frame pointer offsets. */
+
+void
+mn10300_virtual_frame_pointer (pc, reg, offset)
+ CORE_ADDR pc;
+ long *reg;
+ long *offset;
+{
+ struct frame_info *dummy = analyze_dummy_frame (pc, 0);
+ /* Set up a dummy frame_info, Analyze the prolog and fill in the
+ extra info. */
+ /* Results will tell us which type of frame it uses. */
+ if (dummy->extra_info->status & MY_FRAME_IN_SP)
+ {
+ *reg = SP_REGNUM;
+ *offset = -(dummy->extra_info->stack_size);
+ }
+ else
+ {
+ *reg = A3_REGNUM;
+ *offset = 0;
+ }
+}
+
+/* This can be made more generic later. */
+static void
+set_machine_hook (filename)
+ char *filename;
+{
+ int i;
+
+ if (bfd_get_mach (exec_bfd) == bfd_mach_mn10300
+ || bfd_get_mach (exec_bfd) == 0)
+ {
+ mn10300_register_names = mn10300_generic_register_names;
+ }
+
+}
+
+void
+_initialize_mn10300_tdep ()
+{
+/* printf("_initialize_mn10300_tdep\n"); */
+
+ tm_print_insn = print_insn_mn10300;
+
+ specify_exec_file_hook (set_machine_hook);
+}
+
diff --git a/gdb/mon960-rom.c b/gdb/mon960-rom.c
new file mode 100644
index 00000000000..32dcaff7a99
--- /dev/null
+++ b/gdb/mon960-rom.c
@@ -0,0 +1,264 @@
+/* Remote target glue for the Intel 960 MON960 ROM monitor.
+ Copyright 1995, 1996 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+
+#include "defs.h"
+#include "gdbcore.h"
+#include "target.h"
+#include "monitor.h"
+#include "serial.h"
+#include "srec.h"
+#include "xmodem.h"
+#include "symtab.h"
+#include "symfile.h" /* for generic_load */
+
+
+#define USE_GENERIC_LOAD
+
+static struct target_ops mon960_ops;
+
+static void mon960_open PARAMS ((char *args, int from_tty));
+
+#ifdef USE_GENERIC_LOAD
+
+static void
+mon960_load_gen (filename, from_tty)
+ char *filename;
+ int from_tty;
+{
+ extern int inferior_pid;
+
+ generic_load (filename, from_tty);
+ /* Finally, make the PC point at the start address */
+ if (exec_bfd)
+ write_pc (bfd_get_start_address (exec_bfd));
+
+ inferior_pid = 0; /* No process now */
+}
+
+#else
+
+static void
+mon960_load (desc, file, hashmark)
+ serial_t desc;
+ char *file;
+ int hashmark;
+{
+ bfd *abfd;
+ asection *s;
+ char *buffer;
+ int i;
+
+ buffer = alloca (XMODEM_PACKETSIZE);
+ abfd = bfd_openr (file, 0);
+ if (!abfd)
+ {
+ printf_filtered ("Unable to open file %s\n", file);
+ return;
+ }
+ if (bfd_check_format (abfd, bfd_object) == 0)
+ {
+ printf_filtered ("File is not an object file\n");
+ return;
+ }
+ for (s = abfd->sections; s; s = s->next)
+ if (s->flags & SEC_LOAD)
+ {
+ bfd_size_type section_size;
+ printf_filtered ("%s\t: 0x%4x .. 0x%4x ", s->name, s->vma,
+ s->vma + s->_raw_size);
+ gdb_flush (gdb_stdout);
+ monitor_printf (current_monitor->load, s->vma);
+ if (current_monitor->loadresp)
+ monitor_expect (current_monitor->loadresp, NULL, 0);
+ xmodem_init_xfer (desc);
+ section_size = bfd_section_size (abfd, s);
+ for (i = 0; i < section_size; i += XMODEM_DATASIZE)
+ {
+ int numbytes;
+ numbytes = min (XMODEM_DATASIZE, section_size - i);
+ bfd_get_section_contents (abfd, s, buffer + XMODEM_DATAOFFSET, i,
+ numbytes);
+ xmodem_send_packet (desc, buffer, numbytes, hashmark);
+ if (hashmark)
+ {
+ putchar_unfiltered ('#');
+ gdb_flush (gdb_stdout);
+ }
+ } /* Per-packet (or S-record) loop */
+ xmodem_finish_xfer (desc);
+ monitor_expect_prompt (NULL, 0);
+ putchar_unfiltered ('\n');
+ } /* Loadable sections */
+ if (hashmark)
+ putchar_unfiltered ('\n');
+}
+
+#endif /* USE_GENERIC_LOAD */
+
+/* This array of registers need to match the indexes used by GDB.
+ This exists because the various ROM monitors use different strings
+ than does GDB, and don't necessarily support all the registers
+ either. So, typing "info reg sp" becomes a "r30". */
+
+/* these correspond to the offsets from tm-* files from config directories */
+/* g0-g14, fp, pfp, sp, rip,r3-15, pc, ac, tc, fp0-3 */
+/* NOTE: "ip" is documented as "ir" in the Mon960 UG. */
+/* NOTE: "ir" can't be accessed... but there's an ip and rip. */
+static char *full_regnames[NUM_REGS] = {
+ /* 0 */ "pfp", "sp", "rip", "r3", "r4", "r5", "r6", "r7",
+ /* 8 */ "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
+ /* 16 */ "g0", "g1", "g2", "g3", "g4", "g5", "g6", "g7",
+ /* 24 */ "g8", "g9", "g10", "g11", "g12", "g13", "g14", "fp",
+ /* 32 */ "pc", "ac", "tc", "ip", "fp0", "fp1", "fp2", "fp3",
+ };
+
+static char *mon960_regnames[NUM_REGS];
+
+/* Define the monitor command strings. Since these are passed directly
+ through to a printf style function, we may include formatting
+ strings. We also need a CR or LF on the end. */
+
+/* need to pause the monitor for timing reasons, so slow it down */
+
+#if 0
+/* FIXME: this extremely long init string causes MON960 to return two NAKS
+ instead of performing the autobaud recognition, at least when gdb
+ is running on GNU/Linux. The short string below works on Linux, and on
+ SunOS using a tcp serial connection. Must retest on SunOS using a
+ direct serial connection; if that works, get rid of the long string. */
+static char *mon960_inits[] = {"\n\r\r\r\r\r\r\r\r\r\r\r\r\r\r\n\r\n\r\n", NULL};
+#else
+static char *mon960_inits[] = { "\r", NULL};
+#endif
+
+static struct monitor_ops mon960_cmds ;
+
+static void
+init_mon960_cmds (void)
+{
+ mon960_cmds.flags = MO_CLR_BREAK_USES_ADDR
+ | MO_NO_ECHO_ON_OPEN | MO_SEND_BREAK_ON_STOP | MO_GETMEM_READ_SINGLE ; /* flags */
+ mon960_cmds.init = mon960_inits; /* Init strings */
+ mon960_cmds.cont = "go\n\r"; /* continue command */
+ mon960_cmds.step = "st\n\r"; /* single step */
+ mon960_cmds.stop = NULL; /* break interrupts the program */
+ mon960_cmds.set_break = NULL; /* set a breakpoint */
+ mon960_cmds.clr_break = /* can't use "br" because only 2 hw bps are supported */
+ mon960_cmds.clr_all_break = NULL; /* clear a breakpoint - "de" is for hw bps */
+ NULL, /* clear all breakpoints */
+ mon960_cmds.fill = NULL; /* fill (start end val) */
+ /* can't use "fi" because it takes words, not bytes */
+ /* can't use "mb", "md" or "mo" because they require interaction */
+ mon960_cmds.setmem.cmdb = NULL; /* setmem.cmdb (addr, value) */
+ mon960_cmds.setmem.cmdw = NULL; /* setmem.cmdw (addr, value) */
+ mon960_cmds.setmem.cmdl = "md %x %x\n\r"; /* setmem.cmdl (addr, value) */
+ mon960_cmds.setmem.cmdll = NULL; /* setmem.cmdll (addr, value) */
+ mon960_cmds.setmem.resp_delim = NULL; /* setmem.resp_delim */
+ mon960_cmds.setmem.term = NULL; /* setmem.term */
+ mon960_cmds.setmem.term_cmd = NULL; /* setmem.term_cmd */
+ /* since the parsing of multiple bytes is difficult due to
+ interspersed addresses, we'll only read 1 value at a time,
+ even tho these can handle a count */
+ mon960_cmds.getmem.cmdb = "db %x\n\r"; /* getmem.cmdb (addr, #bytes) */
+ mon960_cmds.getmem.cmdw = "ds %x\n\r"; /* getmem.cmdw (addr, #swords) */
+ mon960_cmds.getmem.cmdl = "di %x\n\r"; /* getmem.cmdl (addr, #words) */
+ mon960_cmds.getmem.cmdll = "dd %x\n\r"; /* getmem.cmdll (addr, #dwords) */
+ mon960_cmds.getmem.resp_delim = " : "; /* getmem.resp_delim */
+ mon960_cmds.getmem.term = NULL; /* getmem.term */
+ mon960_cmds.getmem.term_cmd = NULL; /* getmem.term_cmd */
+ mon960_cmds.setreg.cmd = "md %s %x\n\r"; /* setreg.cmd (name, value) */
+ mon960_cmds.setreg.resp_delim = NULL; /* setreg.resp_delim */
+ mon960_cmds.setreg.term = NULL; /* setreg.term */
+ mon960_cmds.setreg.term_cmd = NULL, /* setreg.term_cmd */
+ mon960_cmds.getreg.cmd = "di %s\n\r"; /* getreg.cmd (name) */
+ mon960_cmds.getreg.resp_delim = " : "; /* getreg.resp_delim */
+ mon960_cmds.getreg.term = NULL; /* getreg.term */
+ mon960_cmds.getreg.term_cmd = NULL; /* getreg.term_cmd */
+ mon960_cmds.dump_registers = "re\n\r"; /* dump_registers */
+ mon960_cmds.register_pattern = "\\(\\w+\\)=\\([0-9a-fA-F]+\\)"; /* register_pattern */
+ mon960_cmds.supply_register = NULL; /* supply_register */
+#ifdef USE_GENERIC_LOAD
+ mon960_cmds.load_routine = NULL; /* load_routine (defaults to SRECs) */
+ mon960_cmds.load = NULL; /* download command */
+ mon960_cmds.loadresp = NULL; /* load response */
+#else
+ mon960_cmds.load_routine = mon960_load ; /* load_routine (defaults to SRECs) */
+ mon960_cmds.load = "do\n\r"; /* download command */
+ mon960_cmds.loadresp = "Downloading\n\r" ;/* load response */
+#endif
+ mon960_cmds.prompt = "=>"; /* monitor command prompt */
+ mon960_cmds.line_term = "\n\r"; /* end-of-command delimitor */
+ mon960_cmds.cmd_end = NULL; /* optional command terminator */
+ mon960_cmds.target = &mon960_ops; /* target operations */
+ mon960_cmds.stopbits = SERIAL_1_STOPBITS; /* number of stop bits */
+ mon960_cmds.regnames = mon960_regnames; /* registers names */
+ mon960_cmds.magic = MONITOR_OPS_MAGIC; /* magic */
+};
+
+static void
+mon960_open (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ char buf[64];
+
+ monitor_open (args, &mon960_cmds, from_tty);
+
+ /* Attempt to fetch the value of the first floating point register (fp0).
+ If the monitor returns a string containing the word "Bad" we'll assume
+ this processor has no floating point registers, and nullify the
+ regnames entries that refer to FP registers. */
+
+ monitor_printf (mon960_cmds.getreg.cmd, full_regnames[FP0_REGNUM]); /* di fp0 */
+ if (monitor_expect_prompt (buf, sizeof(buf)) != -1)
+ if (strstr(buf, "Bad") != NULL)
+ {
+ int i;
+
+ for (i = FP0_REGNUM; i < FP0_REGNUM + 4; i++)
+ mon960_regnames[i] = NULL;
+ }
+}
+
+void
+_initialize_mon960 ()
+{
+ memcpy(mon960_regnames, full_regnames, sizeof(full_regnames));
+
+ init_mon960_cmds ();
+
+ init_monitor_ops (&mon960_ops);
+
+ mon960_ops.to_shortname = "mon960"; /* for the target command */
+ mon960_ops.to_longname = "Intel 960 MON960 monitor";
+#ifdef USE_GENERIC_LOAD
+ mon960_ops.to_load = mon960_load_gen; /* FIXME - should go back and try "do" */
+#endif
+ /* use SW breaks; target only supports 2 HW breakpoints */
+ mon960_ops.to_insert_breakpoint = memory_insert_breakpoint;
+ mon960_ops.to_remove_breakpoint = memory_remove_breakpoint;
+
+ mon960_ops.to_doc =
+ "Use an Intel 960 board running the MON960 debug monitor.\n\
+Specify the serial device it is connected to (e.g. /dev/ttya).";
+
+ mon960_ops.to_open = mon960_open;
+ add_target (&mon960_ops);
+}
diff --git a/gdb/monitor.c b/gdb/monitor.c
new file mode 100644
index 00000000000..dc47d8c02f3
--- /dev/null
+++ b/gdb/monitor.c
@@ -0,0 +1,2296 @@
+/* Remote debugging interface for boot monitors, for GDB.
+ Copyright 1990, 1991, 1992, 1993, 1995, 1996, 1997, 1999
+ Free Software Foundation, Inc.
+ Contributed by Cygnus Support. Written by Rob Savoye for Cygnus.
+ Resurrected from the ashes by Stu Grossman.
+
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* This file was derived from various remote-* modules. It is a collection
+ of generic support functions so GDB can talk directly to a ROM based
+ monitor. This saves use from having to hack an exception based handler
+ into existance, and makes for quick porting.
+
+ This module talks to a debug monitor called 'MONITOR', which
+ We communicate with MONITOR via either a direct serial line, or a TCP
+ (or possibly TELNET) stream to a terminal multiplexor,
+ which in turn talks to the target board. */
+
+/* FIXME 32x64: This code assumes that registers and addresses are at
+ most 32 bits long. If they can be larger, you will need to declare
+ values as LONGEST and use %llx or some such to print values when
+ building commands to send to the monitor. Since we don't know of
+ any actual 64-bit targets with ROM monitors that use this code,
+ it's not an issue right now. -sts 4/18/96 */
+
+#include "defs.h"
+#include "gdbcore.h"
+#include "target.h"
+#include "wait.h"
+#ifdef ANSI_PROTOTYPES
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+#include <signal.h>
+#include <ctype.h>
+#include "gdb_string.h"
+#include <sys/types.h>
+#include "command.h"
+#include "serial.h"
+#include "monitor.h"
+#include "gdbcmd.h"
+#include "inferior.h"
+#include "gnu-regex.h"
+#include "dcache.h"
+#include "srec.h"
+
+static char *dev_name;
+static struct target_ops *targ_ops;
+
+static void monitor_vsprintf PARAMS ((char *sndbuf, char *pattern, va_list args));
+
+static int readchar PARAMS ((int timeout));
+
+static void monitor_command PARAMS ((char *args, int fromtty));
+
+static void monitor_fetch_register PARAMS ((int regno));
+static void monitor_store_register PARAMS ((int regno));
+
+static int monitor_printable_string PARAMS ((char *newstr, char *oldstr));
+static void monitor_error PARAMS ((char *format, CORE_ADDR memaddr, int len, char *string, int final_char));
+static void monitor_detach PARAMS ((char *args, int from_tty));
+static void monitor_resume PARAMS ((int pid, int step, enum target_signal sig));
+static void monitor_interrupt PARAMS ((int signo));
+static void monitor_interrupt_twice PARAMS ((int signo));
+static void monitor_interrupt_query PARAMS ((void));
+static void monitor_wait_cleanup PARAMS ((void *old_timeout));
+
+static int monitor_wait PARAMS ((int pid, struct target_waitstatus *status));
+static void monitor_fetch_registers PARAMS ((int regno));
+static void monitor_store_registers PARAMS ((int regno));
+static void monitor_prepare_to_store PARAMS ((void));
+static int monitor_xfer_memory PARAMS ((CORE_ADDR memaddr, char *myaddr, int len, int write, struct target_ops *target));
+static void monitor_files_info PARAMS ((struct target_ops *ops));
+static int monitor_insert_breakpoint PARAMS ((CORE_ADDR addr, char *shadow));
+static int monitor_remove_breakpoint PARAMS ((CORE_ADDR addr, char *shadow));
+static void monitor_kill PARAMS ((void));
+static void monitor_load PARAMS ((char *file, int from_tty));
+static void monitor_mourn_inferior PARAMS ((void));
+static void monitor_stop PARAMS ((void));
+
+static int monitor_read_memory PARAMS ((CORE_ADDR addr, char *myaddr,int len));
+static int monitor_write_memory PARAMS ((CORE_ADDR addr, char *myaddr,int len));
+static int monitor_write_memory_bytes PARAMS ((CORE_ADDR addr,
+ char *myaddr,int len));
+static int monitor_write_memory_block PARAMS((
+ CORE_ADDR memaddr ,
+ char * myaddr ,
+ int len)) ;
+static int monitor_expect_regexp PARAMS ((struct re_pattern_buffer *pat,
+ char *buf, int buflen));
+static void monitor_dump_regs PARAMS((void)) ;
+#if 0
+static int from_hex PARAMS ((int a));
+static unsigned long get_hex_word PARAMS ((void));
+#endif
+static void parse_register_dump PARAMS ((char *, int));
+
+static struct monitor_ops *current_monitor;
+
+static int hashmark; /* flag set by "set hash" */
+
+static int timeout = 30;
+
+static int in_monitor_wait = 0; /* Non-zero means we are in monitor_wait() */
+
+static void (*ofunc)(); /* Old SIGINT signal handler */
+
+/* Extra remote debugging for developing a new rom monitor variation */
+#if ! defined(EXTRA_RDEBUG)
+#define EXTRA_RDEBUG 0
+#endif
+#define RDEBUG(stuff) { if (EXTRA_RDEBUG && remote_debug) printf stuff ; }
+
+/* Descriptor for I/O to remote machine. Initialize it to NULL so
+ that monitor_open knows that we don't have a file open when the
+ program starts. */
+
+static serial_t monitor_desc = NULL;
+
+/* Pointer to regexp pattern matching data */
+
+static struct re_pattern_buffer register_pattern;
+static char register_fastmap[256];
+
+static struct re_pattern_buffer getmem_resp_delim_pattern;
+static char getmem_resp_delim_fastmap[256];
+
+static int dump_reg_flag; /* Non-zero means do a dump_registers cmd when
+ monitor_wait wakes up. */
+
+static DCACHE *remote_dcache;
+static int first_time=0; /* is this the first time we're executing after
+ gaving created the child proccess? */
+
+/* Convert a string into a printable representation, Return # byte in the
+ new string. */
+
+static int
+monitor_printable_string (newstr, oldstr)
+ char *newstr;
+ char *oldstr;
+{
+ char *save = newstr;
+ int ch;
+
+ while ((ch = *oldstr++) != '\0')
+ {
+ switch (ch)
+ {
+ default:
+ if (isprint (ch))
+ *newstr++ = ch;
+
+ else
+ {
+ sprintf (newstr, "\\x%02x", ch & 0xff);
+ newstr += 4;
+ }
+ break;
+
+ case '\\': *newstr++ = '\\'; *newstr++ = '\\'; break;
+ case '\b': *newstr++ = '\\'; *newstr++ = 'b'; break;
+ case '\f': *newstr++ = '\\'; *newstr++ = 't'; break;
+ case '\n': *newstr++ = '\\'; *newstr++ = 'n'; break;
+ case '\r': *newstr++ = '\\'; *newstr++ = 'r'; break;
+ case '\t': *newstr++ = '\\'; *newstr++ = 't'; break;
+ case '\v': *newstr++ = '\\'; *newstr++ = 'v'; break;
+ }
+ }
+
+ *newstr++ = '\0';
+ return newstr - save;
+}
+
+/* Print monitor errors with a string, converting the string to printable
+ representation. */
+
+static void
+monitor_error (format, memaddr, len, string, final_char)
+ char *format;
+ CORE_ADDR memaddr;
+ int len;
+ char *string;
+ int final_char;
+{
+ int real_len = (len == 0 && string != (char *)0) ? strlen (string) : len;
+ char *safe_string = alloca ((real_len * 4) + 1);
+ char *p, *q;
+ int ch;
+ int safe_len = monitor_printable_string (safe_string, string);
+
+ if (final_char)
+ error (format, (int)memaddr, p - safe_string, safe_string, final_char);
+ else
+ error (format, (int)memaddr, p - safe_string, safe_string);
+}
+
+/* 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
+ if (a >= 'A' && a <= 'F')
+ return a - 'A' + 10 ;
+ else error ("Invalid hex digit %d", a);
+}
+
+/* monitor_vsprintf - similar to vsprintf but handles 64-bit addresses
+
+ This function exists to get around the problem that many host platforms
+ don't have a printf that can print 64-bit addresses. The %A format
+ specification is recognized as a special case, and causes the argument
+ to be printed as a 64-bit hexadecimal address.
+
+ Only format specifiers of the form "[0-9]*[a-z]" are recognized.
+ If it is a '%s' format, the argument is a string; otherwise the
+ argument is assumed to be a long integer.
+
+ %% is also turned into a single %.
+*/
+
+static void
+monitor_vsprintf (sndbuf, pattern, args)
+ char *sndbuf;
+ char *pattern;
+ va_list args;
+{
+ char format[10];
+ char fmt;
+ char *p;
+ int i;
+ long arg_int;
+ CORE_ADDR arg_addr;
+ char *arg_string;
+
+ for (p = pattern; *p; p++)
+ {
+ if (*p == '%')
+ {
+ /* Copy the format specifier to a separate buffer. */
+ format[0] = *p++;
+ for (i = 1; *p >= '0' && *p <= '9' && i < (int) sizeof (format) - 2;
+ i++, p++)
+ format[i] = *p;
+ format[i] = fmt = *p;
+ format[i+1] = '\0';
+
+ /* Fetch the next argument and print it. */
+ switch (fmt)
+ {
+ case '%':
+ strcpy (sndbuf, "%");
+ break;
+ case 'A':
+ arg_addr = va_arg (args, CORE_ADDR);
+ strcpy (sndbuf, paddr_nz (arg_addr));
+ break;
+ case 's':
+ arg_string = va_arg (args, char *);
+ sprintf (sndbuf, format, arg_string);
+ break;
+ default:
+ arg_int = va_arg (args, long);
+ sprintf (sndbuf, format, arg_int);
+ break;
+ }
+ sndbuf += strlen (sndbuf);
+ }
+ else
+ *sndbuf++ = *p;
+ }
+ *sndbuf = '\0';
+}
+
+
+/* monitor_printf_noecho -- Send data to monitor, but don't expect an echo.
+ Works just like printf. */
+
+void
+#ifdef ANSI_PROTOTYPES
+monitor_printf_noecho (char *pattern, ...)
+#else
+monitor_printf_noecho (va_alist)
+ va_dcl
+#endif
+{
+ va_list args;
+ char sndbuf[2000];
+ int len;
+
+#if ANSI_PROTOTYPES
+ va_start (args, pattern);
+#else
+ char *pattern;
+ va_start (args);
+ pattern = va_arg (args, char *);
+#endif
+
+ monitor_vsprintf (sndbuf, pattern, args);
+
+ len = strlen (sndbuf);
+ if (len + 1 > sizeof sndbuf)
+ abort ();
+
+#if 0
+ if (remote_debug > 0)
+ puts_debug ("sent -->", sndbuf, "<--");
+#endif
+ if (EXTRA_RDEBUG
+ && remote_debug)
+ {
+ char *safe_string = (char *) alloca ((strlen (sndbuf) * 4) + 1);
+ monitor_printable_string (safe_string, sndbuf);
+ printf ("sent[%s]\n", safe_string);
+ }
+
+ monitor_write (sndbuf, len);
+}
+
+/* monitor_printf -- Send data to monitor and check the echo. Works just like
+ printf. */
+
+void
+#ifdef ANSI_PROTOTYPES
+monitor_printf (char *pattern, ...)
+#else
+monitor_printf (va_alist)
+ va_dcl
+#endif
+{
+ va_list args;
+ char sndbuf[2000];
+ int len;
+
+#ifdef ANSI_PROTOTYPES
+ va_start (args, pattern);
+#else
+ char *pattern;
+ va_start (args);
+ pattern = va_arg (args, char *);
+#endif
+
+ monitor_vsprintf (sndbuf, pattern, args);
+
+ len = strlen (sndbuf);
+ if (len + 1 > sizeof sndbuf)
+ abort ();
+
+#if 0
+ if (remote_debug > 0)
+ puts_debug ("sent -->", sndbuf, "<--");
+#endif
+ if (EXTRA_RDEBUG
+ && remote_debug)
+ {
+ char *safe_string = (char *) alloca ((len * 4) + 1);
+ monitor_printable_string (safe_string, sndbuf);
+ printf ("sent[%s]\n", safe_string);
+ }
+
+ monitor_write (sndbuf, len);
+
+ /* We used to expect that the next immediate output was the characters we
+ just output, but sometimes some extra junk appeared before the characters
+ we expected, like an extra prompt, or a portmaster sending telnet negotiations.
+ So, just start searching for what we sent, and skip anything unknown. */
+ RDEBUG(("ExpectEcho\n"))
+ monitor_expect (sndbuf, (char *)0, 0);
+}
+
+
+/* Write characters to the remote system. */
+
+void
+monitor_write (buf, buflen)
+ char *buf;
+ int buflen;
+{
+ if (SERIAL_WRITE(monitor_desc, buf, buflen))
+ fprintf_unfiltered (gdb_stderr, "SERIAL_WRITE failed: %s\n",
+ safe_strerror (errno));
+}
+
+
+/* Read a binary character from the remote system, doing all the fancy
+ timeout stuff, but without interpreting the character in any way,
+ and without printing remote debug information. */
+
+int
+monitor_readchar ()
+{
+ int c;
+ int looping;
+
+ do
+ {
+ looping = 0;
+ c = SERIAL_READCHAR (monitor_desc, timeout);
+
+ if (c >= 0)
+ c &= 0xff; /* don't lose bit 7 */
+ }
+ while (looping);
+
+ if (c >= 0)
+ return c;
+
+ if (c == SERIAL_TIMEOUT)
+ error ("Timeout reading from remote system.");
+
+ perror_with_name ("remote-monitor");
+}
+
+
+/* Read a character from the remote system, doing all the fancy
+ timeout stuff. */
+
+static int
+readchar (timeout)
+ int timeout;
+{
+ int c;
+ static enum { last_random, last_nl, last_cr, last_crnl } state = last_random;
+ int looping;
+
+ do
+ {
+ looping = 0;
+ c = SERIAL_READCHAR (monitor_desc, timeout);
+
+ if (c >= 0)
+ {
+ c &= 0x7f;
+#if 0
+ /* This seems to interfere with proper function of the
+ input stream */
+ if (remote_debug > 0)
+ {
+ char buf[2];
+ buf[0] = c;
+ buf[1] = '\0';
+ puts_debug ("read -->", buf, "<--");
+ }
+
+#endif
+ }
+
+ /* Canonicialize \n\r combinations into one \r */
+ if ((current_monitor->flags & MO_HANDLE_NL) != 0)
+ {
+ if ((c == '\r' && state == last_nl)
+ || (c == '\n' && state == last_cr))
+ {
+ state = last_crnl;
+ looping = 1;
+ }
+ else if (c == '\r')
+ state = last_cr;
+ else if (c != '\n')
+ state = last_random;
+ else
+ {
+ state = last_nl;
+ c = '\r';
+ }
+ }
+ }
+ while (looping);
+
+ if (c >= 0)
+ return c;
+
+ if (c == SERIAL_TIMEOUT)
+#if 0 /* MAINTENANCE_CMDS */
+ /* I fail to see how detaching here can be useful */
+ if (in_monitor_wait) /* Watchdog went off */
+ {
+ target_mourn_inferior ();
+ error ("GDB serial timeout has expired. Target detached.\n");
+ }
+ else
+#endif
+ error ("Timeout reading from remote system.");
+
+ perror_with_name ("remote-monitor");
+}
+
+/* Scan input from the remote system, until STRING is found. If BUF is non-
+ zero, then collect input until we have collected either STRING or BUFLEN-1
+ chars. In either case we terminate BUF with a 0. If input overflows BUF
+ because STRING can't be found, return -1, else return number of chars in BUF
+ (minus the terminating NUL). Note that in the non-overflow case, STRING
+ will be at the end of BUF. */
+
+int
+monitor_expect (string, buf, buflen)
+ char *string;
+ char *buf;
+ int buflen;
+{
+ char *p = string;
+ int obuflen = buflen;
+ int c;
+ extern struct target_ops *targ_ops;
+
+ if (EXTRA_RDEBUG
+ && remote_debug)
+ {
+ char *safe_string = (char *) alloca ((strlen (string) * 4) + 1);
+ monitor_printable_string (safe_string, string);
+ printf ("MON Expecting '%s'\n", safe_string);
+ }
+
+ immediate_quit = 1;
+ while (1)
+ {
+ if (buf)
+ {
+ if (buflen < 2)
+ {
+ *buf = '\000';
+ immediate_quit = 0;
+ return -1;
+ }
+
+ c = readchar (timeout);
+ if (c == '\000')
+ continue;
+ *buf++ = c;
+ buflen--;
+ }
+ else
+ c = readchar (timeout);
+
+ /* Don't expect any ^C sent to be echoed */
+
+ if (*p == '\003' || c == *p)
+ {
+ p++;
+ if (*p == '\0')
+ {
+ immediate_quit = 0;
+
+ if (buf)
+ {
+ *buf++ = '\000';
+ return obuflen - buflen;
+ }
+ else
+ return 0;
+ }
+ }
+ else if ((c == '\021' || c == '\023') &&
+ (STREQ (targ_ops->to_shortname, "m32r")
+ || STREQ (targ_ops->to_shortname, "mon2000")))
+ { /* m32r monitor emits random DC1/DC3 chars */
+ continue;
+ }
+ else
+ {
+ p = string;
+ if (c == *p)
+ p++;
+ }
+ }
+}
+
+/* Search for a regexp. */
+
+static int
+monitor_expect_regexp (pat, buf, buflen)
+ struct re_pattern_buffer *pat;
+ char *buf;
+ int buflen;
+{
+ char *mybuf;
+ char *p;
+ RDEBUG(("MON Expecting regexp\n")) ;
+ if (buf)
+ mybuf = buf;
+ else
+ {
+ mybuf = alloca (1024);
+ buflen = 1024;
+ }
+
+ p = mybuf;
+ while (1)
+ {
+ int retval;
+
+ if (p - mybuf >= buflen)
+ { /* Buffer about to overflow */
+
+/* On overflow, we copy the upper half of the buffer to the lower half. Not
+ great, but it usually works... */
+
+ memcpy (mybuf, mybuf + buflen / 2, buflen / 2);
+ p = mybuf + buflen / 2;
+ }
+
+ *p++ = readchar (timeout);
+
+ retval = re_search (pat, mybuf, p - mybuf, 0, p - mybuf, NULL);
+ if (retval >= 0)
+ return 1;
+ }
+}
+
+/* Keep discarding input until we see the MONITOR 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 monitor_expect_prompt(). Exception: monitor_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 monitor_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. */
+
+int
+monitor_expect_prompt (buf, buflen)
+ char *buf;
+ int buflen;
+{
+ RDEBUG(("MON Expecting prompt\n"))
+ return monitor_expect (current_monitor->prompt, buf, buflen);
+}
+
+/* Get N 32-bit words from remote, each preceded by a space, and put
+ them in registers starting at REGNO. */
+
+#if 0
+static unsigned long
+get_hex_word ()
+{
+ unsigned long val;
+ int i;
+ int ch;
+
+ do
+ ch = readchar (timeout);
+ while (isspace(ch));
+
+ val = from_hex (ch);
+
+ for (i = 7; i >= 1; i--)
+ {
+ ch = readchar (timeout);
+ if (!isxdigit (ch))
+ break;
+ val = (val << 4) | from_hex (ch);
+ }
+
+ return val;
+}
+#endif
+
+static void
+compile_pattern (pattern, compiled_pattern, fastmap)
+ char *pattern;
+ struct re_pattern_buffer *compiled_pattern;
+ char *fastmap;
+{
+ int tmp;
+ const char *val;
+
+ compiled_pattern->fastmap = fastmap;
+
+ tmp = re_set_syntax (RE_SYNTAX_EMACS);
+ val = re_compile_pattern (pattern,
+ strlen (pattern),
+ compiled_pattern);
+ re_set_syntax (tmp);
+
+ if (val)
+ error ("compile_pattern: Can't compile pattern string `%s': %s!", pattern, val);
+
+ if (fastmap)
+ re_compile_fastmap (compiled_pattern);
+}
+
+/* Open a connection to a remote debugger. NAME is the filename used
+ for communication. */
+
+void
+monitor_open (args, mon_ops, from_tty)
+ char *args;
+ struct monitor_ops *mon_ops;
+ int from_tty;
+{
+ char *name;
+ char **p;
+
+ if (mon_ops->magic != MONITOR_OPS_MAGIC)
+ error ("Magic number of monitor_ops struct wrong.");
+
+ targ_ops = mon_ops->target;
+ name = targ_ops->to_shortname;
+
+ if (!args)
+ error ("Use `target %s DEVICE-NAME' to use a serial port, or \n\
+`target %s HOST-NAME:PORT-NUMBER' to use a network connection.", name, name);
+
+ target_preopen (from_tty);
+
+ /* Setup pattern for register dump */
+
+ if (mon_ops->register_pattern)
+ compile_pattern (mon_ops->register_pattern, &register_pattern,
+ register_fastmap);
+
+ if (mon_ops->getmem.resp_delim)
+ compile_pattern (mon_ops->getmem.resp_delim, &getmem_resp_delim_pattern,
+ getmem_resp_delim_fastmap);
+
+ unpush_target (targ_ops);
+
+ if (dev_name)
+ free (dev_name);
+ dev_name = strsave (args);
+
+ monitor_desc = SERIAL_OPEN (dev_name);
+
+ if (!monitor_desc)
+ perror_with_name (dev_name);
+
+ if (baud_rate != -1)
+ {
+ if (SERIAL_SETBAUDRATE (monitor_desc, baud_rate))
+ {
+ SERIAL_CLOSE (monitor_desc);
+ perror_with_name (dev_name);
+ }
+ }
+
+ SERIAL_RAW (monitor_desc);
+
+ SERIAL_FLUSH_INPUT (monitor_desc);
+
+ /* some systems only work with 2 stop bits */
+
+ SERIAL_SETSTOPBITS (monitor_desc, mon_ops->stopbits);
+
+ current_monitor = mon_ops;
+
+ /* See if we can wake up the monitor. First, try sending a stop sequence,
+ then send the init strings. Last, remove all breakpoints. */
+
+ if (current_monitor->stop)
+ {
+ monitor_stop ();
+ if ((current_monitor->flags & MO_NO_ECHO_ON_OPEN) == 0)
+ {
+ RDEBUG(("EXP Open echo\n")) ;
+ monitor_expect_prompt (NULL, 0);
+ }
+ }
+
+ /* wake up the monitor and see if it's alive */
+ for (p = mon_ops->init; *p != NULL; p++)
+ {
+ /* Some of the characters we send may not be echoed,
+ but we hope to get a prompt at the end of it all. */
+
+ if ((current_monitor->flags & MO_NO_ECHO_ON_OPEN) == 0)
+ monitor_printf(*p);
+ else
+ monitor_printf_noecho (*p);
+ monitor_expect_prompt (NULL, 0);
+ }
+
+ SERIAL_FLUSH_INPUT (monitor_desc);
+
+ /* Remove all breakpoints */
+
+ if (mon_ops->clr_all_break)
+ {
+ monitor_printf (mon_ops->clr_all_break);
+ monitor_expect_prompt (NULL, 0);
+ }
+
+ if (from_tty)
+ printf_unfiltered ("Remote target %s connected to %s\n", name, dev_name);
+
+ push_target (targ_ops);
+
+ inferior_pid = 42000; /* Make run command think we are busy... */
+
+ /* Give monitor_wait something to read */
+
+ monitor_printf (current_monitor->line_term);
+
+ if (current_monitor->flags & MO_HAS_BLOCKWRITES)
+ remote_dcache = dcache_init (monitor_read_memory, monitor_write_memory_block);
+ else
+ remote_dcache = dcache_init (monitor_read_memory, monitor_write_memory);
+ start_remote ();
+}
+
+/* Close out all files and local state before this target loses
+ control. */
+
+void
+monitor_close (quitting)
+ int quitting;
+{
+ if (monitor_desc)
+ SERIAL_CLOSE (monitor_desc);
+ monitor_desc = NULL;
+}
+
+/* Terminate the open connection to the remote debugger. Use this
+ when you want to detach and do something else with your gdb. */
+
+static void
+monitor_detach (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ pop_target (); /* calls monitor_close to do the real work */
+ if (from_tty)
+ printf_unfiltered ("Ending remote %s debugging\n", target_shortname);
+}
+
+/* Convert VALSTR into the target byte-ordered value of REGNO and store it. */
+
+char *
+monitor_supply_register (regno, valstr)
+ int regno;
+ char *valstr;
+{
+ unsigned int val;
+ unsigned char regbuf[MAX_REGISTER_RAW_SIZE];
+ char *p;
+
+ val = strtoul (valstr, &p, 16);
+ RDEBUG(("Supplying Register %d %s\n",regno,valstr)) ;
+
+ if (val == 0 && valstr == p)
+ error ("monitor_supply_register (%d): bad value from monitor: %s.",
+ regno, valstr);
+
+ /* supply register stores in target byte order, so swap here */
+
+ store_unsigned_integer (regbuf, REGISTER_RAW_SIZE (regno), val);
+
+ supply_register (regno, regbuf);
+
+ return p;
+}
+
+/* Tell the remote machine to resume. */
+
+void
+flush_monitor_dcache ()
+{
+ dcache_flush (remote_dcache);
+}
+
+static void
+monitor_resume (pid, step, sig)
+ int pid, step;
+ enum target_signal sig;
+{
+ /* Some monitors require a different command when starting a program */
+ RDEBUG(("MON resume\n")) ;
+ if (current_monitor->flags & MO_RUN_FIRST_TIME && first_time == 1)
+ {
+ first_time = 0;
+ monitor_printf ("run\r");
+ if (current_monitor->flags & MO_NEED_REGDUMP_AFTER_CONT)
+ dump_reg_flag = 1;
+ return;
+ }
+ dcache_flush (remote_dcache);
+ if (step)
+ monitor_printf (current_monitor->step);
+ else
+ {
+ if (current_monitor->continue_hook)
+ (*current_monitor->continue_hook)() ;
+ else monitor_printf (current_monitor->cont);
+ if (current_monitor->flags & MO_NEED_REGDUMP_AFTER_CONT)
+ dump_reg_flag = 1;
+ }
+}
+
+/* Parse the output of a register dump command. A monitor specific
+ regexp is used to extract individual register descriptions of the
+ form REG=VAL. Each description is split up into a name and a value
+ string which are passed down to monitor specific code. */
+
+static void
+parse_register_dump (buf, len)
+ char *buf;
+ int len;
+{
+ RDEBUG(("MON Parsing register dump\n"))
+ while (1)
+ {
+ int regnamelen, vallen;
+ char *regname, *val;
+ /* Element 0 points to start of register name, and element 1
+ points to the start of the register value. */
+ struct re_registers register_strings;
+
+ memset (&register_strings, 0, sizeof (struct re_registers));
+
+ if (re_search (&register_pattern, buf, len, 0, len,
+ &register_strings) == -1)
+ break;
+
+ regnamelen = register_strings.end[1] - register_strings.start[1];
+ regname = buf + register_strings.start[1];
+ vallen = register_strings.end[2] - register_strings.start[2];
+ val = buf + register_strings.start[2];
+
+ current_monitor->supply_register (regname, regnamelen, val, vallen);
+
+ buf += register_strings.end[0];
+ len -= register_strings.end[0];
+ }
+}
+
+/* Send ^C to target to halt it. Target will respond, and send us a
+ packet. */
+
+static void
+monitor_interrupt (signo)
+ int signo;
+{
+ /* If this doesn't work, try more severe steps. */
+ signal (signo, monitor_interrupt_twice);
+
+ if (remote_debug)
+ printf_unfiltered ("monitor_interrupt called\n");
+
+ target_stop ();
+}
+
+/* The user typed ^C twice. */
+
+static void
+monitor_interrupt_twice (signo)
+ int signo;
+{
+ signal (signo, ofunc);
+
+ monitor_interrupt_query ();
+
+ signal (signo, monitor_interrupt);
+}
+
+/* Ask the user what to do when an interrupt is received. */
+
+static void
+monitor_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 ();
+}
+
+static void
+monitor_wait_cleanup (old_timeout)
+ void *old_timeout;
+{
+ timeout = *(int*)old_timeout;
+ signal (SIGINT, ofunc);
+ in_monitor_wait = 0;
+}
+
+
+
+void monitor_wait_filter(char * buf,
+ int bufmax,
+ int * ext_resp_len,
+ struct target_waitstatus * status
+ )
+{
+ int resp_len ;
+ do
+ {
+ resp_len = monitor_expect_prompt (buf, bufmax);
+ * ext_resp_len =resp_len ;
+
+ if (resp_len <= 0)
+ fprintf_unfiltered (gdb_stderr, "monitor_wait: excessive response from monitor: %s.", buf);
+ }
+ while (resp_len < 0);
+
+ /* Print any output characters that were preceded by ^O. */
+ /* FIXME - This would be great as a user settabgle flag */
+ if (remote_debug ||
+ current_monitor->flags & MO_PRINT_PROGRAM_OUTPUT)
+ {
+ int i;
+
+ for (i = 0; i < resp_len - 1; i++)
+ if (buf[i] == 0x0f)
+ putchar_unfiltered (buf[++i]);
+ }
+}
+
+
+
+/* Wait until the remote machine stops, then return, storing status in
+ status just as `wait' would. */
+
+static int
+monitor_wait (pid, status)
+ int pid;
+ struct target_waitstatus *status;
+{
+ int old_timeout = timeout;
+ char buf[1024];
+ int resp_len;
+ struct cleanup *old_chain;
+
+ status->kind = TARGET_WAITKIND_EXITED;
+ status->value.integer = 0;
+
+ old_chain = make_cleanup (monitor_wait_cleanup, &old_timeout);
+ RDEBUG(("MON wait\n"))
+
+#if 0 /* MAINTENANCE_CMDS */
+ /* This is somthing other than a maintenance command */
+ in_monitor_wait = 1;
+ timeout = watchdog > 0 ? watchdog : -1;
+#else
+ timeout = -1; /* Don't time out -- user program is running. */
+#endif
+
+ ofunc = (void (*)()) signal (SIGINT, monitor_interrupt);
+
+ if (current_monitor->wait_filter)
+ (*current_monitor->wait_filter)(buf,sizeof (buf),&resp_len,status) ;
+ else monitor_wait_filter(buf,sizeof (buf),&resp_len,status) ;
+
+#if 0 /* Transferred to monitor wait filter */
+ do
+ {
+ resp_len = monitor_expect_prompt (buf, sizeof (buf));
+
+ if (resp_len <= 0)
+ fprintf_unfiltered (gdb_stderr, "monitor_wait: excessive response from monitor: %s.", buf);
+ }
+ while (resp_len < 0);
+
+ /* Print any output characters that were preceded by ^O. */
+ /* FIXME - This would be great as a user settabgle flag */
+ if (remote_debug ||
+ current_monitor->flags & MO_PRINT_PROGRAM_OUTPUT)
+ {
+ int i;
+
+ for (i = 0; i < resp_len - 1; i++)
+ if (buf[i] == 0x0f)
+ putchar_unfiltered (buf[++i]);
+ }
+#endif
+
+ signal (SIGINT, ofunc);
+
+ timeout = old_timeout;
+#if 0
+ if (dump_reg_flag && current_monitor->dump_registers)
+ {
+ dump_reg_flag = 0;
+ monitor_printf (current_monitor->dump_registers);
+ resp_len = monitor_expect_prompt (buf, sizeof (buf));
+ }
+
+ if (current_monitor->register_pattern)
+ parse_register_dump (buf, resp_len);
+#else
+ RDEBUG(("Wait fetching registers after stop\n")) ;
+ monitor_dump_regs() ;
+#endif
+
+ status->kind = TARGET_WAITKIND_STOPPED;
+ status->value.sig = TARGET_SIGNAL_TRAP;
+
+ discard_cleanups (old_chain);
+
+ in_monitor_wait = 0;
+
+ return inferior_pid;
+}
+
+/* Fetch register REGNO, or all registers if REGNO is -1. Returns
+ errno value. */
+
+static void
+monitor_fetch_register (regno)
+ int regno;
+{
+ char *name;
+ static char zerobuf[MAX_REGISTER_RAW_SIZE] = {0};
+ char regbuf[MAX_REGISTER_RAW_SIZE * 2 + 1];
+ int i;
+
+ name = current_monitor->regnames[regno];
+ RDEBUG(("MON fetchreg %d '%s'\n",regno,name))
+
+ if (!name || (*name == '\0'))
+ { RDEBUG(("No register known for %d\n",regno))
+ supply_register (regno, zerobuf);
+ return;
+ }
+
+ /* send the register examine command */
+
+ monitor_printf (current_monitor->getreg.cmd, name);
+
+ /* If RESP_DELIM is specified, we search for that as a leading
+ delimiter for the register value. Otherwise, we just start
+ searching from the start of the buf. */
+
+ if (current_monitor->getreg.resp_delim)
+ {
+ RDEBUG(("EXP getreg.resp_delim\n"))
+ monitor_expect (current_monitor->getreg.resp_delim, NULL, 0);
+ /* Handle case of first 32 registers listed in pairs. */
+ if (current_monitor->flags & MO_32_REGS_PAIRED
+ && regno & 1 == 1 && regno < 32)
+ { RDEBUG(("EXP getreg.resp_delim\n")) ;
+ monitor_expect (current_monitor->getreg.resp_delim, NULL, 0);
+ }
+ }
+
+ /* Skip leading spaces and "0x" if MO_HEX_PREFIX flag is set */
+ if (current_monitor->flags & MO_HEX_PREFIX)
+ {
+ int c;
+ c = readchar (timeout);
+ while (c == ' ')
+ c = readchar (timeout);
+ if ((c == '0') && ((c = readchar (timeout)) == 'x'))
+ ;
+ else
+ error ("Bad value returned from monitor while fetching register %x.",
+ regno);
+ }
+
+ /* Read upto the maximum number of hex digits for this register, skipping
+ spaces, but stop reading if something else is seen. Some monitors
+ like to drop leading zeros. */
+
+ for (i = 0; i < REGISTER_RAW_SIZE (regno) * 2; i++)
+ {
+ int c;
+ c = readchar (timeout);
+ while (c == ' ')
+ c = readchar (timeout);
+
+ if (!isxdigit (c))
+ break;
+
+ regbuf[i] = c;
+ }
+
+ regbuf[i] = '\000'; /* terminate the number */
+ RDEBUG(("REGVAL '%s'\n",regbuf)) ;
+
+ /* If TERM is present, we wait for that to show up. Also, (if TERM
+ is present), we will send TERM_CMD if that is present. In any
+ case, we collect all of the output into buf, and then wait for
+ the normal prompt. */
+
+ if (current_monitor->getreg.term)
+ {
+ RDEBUG(("EXP getreg.term\n"))
+ monitor_expect (current_monitor->getreg.term, NULL, 0); /* get response */
+ }
+
+ if (current_monitor->getreg.term_cmd)
+ { RDEBUG(("EMIT getreg.term.cmd\n"))
+ monitor_printf (current_monitor->getreg.term_cmd);
+ }
+ if (! current_monitor->getreg.term || /* Already expected or */
+ current_monitor->getreg.term_cmd) /* ack expected */
+ monitor_expect_prompt (NULL, 0); /* get response */
+
+ monitor_supply_register (regno, regbuf);
+}
+
+/* Sometimes, it takes several commands to dump the registers */
+/* This is a primitive for use by variations of monitor interfaces in
+ case they need to compose the operation.
+ */
+int monitor_dump_reg_block(char * block_cmd)
+{
+ char buf[1024];
+ int resp_len;
+ monitor_printf (block_cmd);
+ resp_len = monitor_expect_prompt (buf, sizeof (buf));
+ parse_register_dump (buf, resp_len);
+ return 1 ;
+}
+
+
+/* Read the remote registers into the block regs. */
+/* Call the specific function if it has been provided */
+
+static void
+monitor_dump_regs ()
+{
+ char buf[1024];
+ int resp_len;
+ if (current_monitor->dumpregs)
+ (*(current_monitor->dumpregs))() ; /* call supplied function */
+ else
+ if (current_monitor->dump_registers) /* default version */
+ { monitor_printf (current_monitor->dump_registers);
+ resp_len = monitor_expect_prompt (buf, sizeof (buf));
+ parse_register_dump (buf, resp_len);
+ }
+ else
+ abort(); /* Need some way to read registers */
+}
+
+static void
+monitor_fetch_registers (regno)
+ int regno;
+{
+ RDEBUG(("MON fetchregs\n")) ;
+ if (current_monitor->getreg.cmd)
+ {
+ if (regno >= 0)
+ {
+ monitor_fetch_register (regno);
+ return;
+ }
+
+ for (regno = 0; regno < NUM_REGS; regno++)
+ monitor_fetch_register (regno);
+ }
+ else {
+ monitor_dump_regs ();
+ }
+}
+
+/* Store register REGNO, or all if REGNO == 0. Return errno value. */
+
+static void
+monitor_store_register (regno)
+ int regno;
+{
+ char *name;
+ unsigned int val;
+
+ name = current_monitor->regnames[regno];
+ if (!name || (*name == '\0'))
+ { RDEBUG(("MON Cannot store unknown register\n"))
+ return;
+ }
+
+ val = read_register (regno);
+ RDEBUG(("MON storeg %d %08x\n",regno,(unsigned int)val))
+
+ /* send the register deposit command */
+
+ if (current_monitor->flags & MO_REGISTER_VALUE_FIRST)
+ monitor_printf (current_monitor->setreg.cmd, val, name);
+ else if (current_monitor->flags & MO_SETREG_INTERACTIVE)
+ monitor_printf (current_monitor->setreg.cmd, name);
+ else
+ monitor_printf (current_monitor->setreg.cmd, name, val);
+
+ if (current_monitor->setreg.term)
+ { RDEBUG(("EXP setreg.term\n"))
+ monitor_expect (current_monitor->setreg.term, NULL, 0);
+ if (current_monitor->flags & MO_SETREG_INTERACTIVE)
+ monitor_printf ("%x\r", val);
+ monitor_expect_prompt (NULL, 0);
+ }
+ else
+ monitor_expect_prompt (NULL, 0);
+ if (current_monitor->setreg.term_cmd) /* Mode exit required */
+ { RDEBUG(("EXP setreg_termcmd\n")) ;
+ monitor_printf("%s",current_monitor->setreg.term_cmd) ;
+ monitor_expect_prompt(NULL,0) ;
+ }
+} /* monitor_store_register */
+
+/* Store the remote registers. */
+
+static void
+monitor_store_registers (regno)
+ int regno;
+{
+ if (regno >= 0)
+ {
+ monitor_store_register (regno);
+ return;
+ }
+
+ for (regno = 0; regno < NUM_REGS; regno++)
+ monitor_store_register (regno);
+}
+
+/* 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
+monitor_prepare_to_store ()
+{
+ /* Do nothing, since we can store individual regs */
+}
+
+static void
+monitor_files_info (ops)
+ struct target_ops *ops;
+{
+ printf_unfiltered ("\tAttached to %s at %d baud.\n", dev_name, baud_rate);
+}
+
+static int
+monitor_write_memory (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+{
+ unsigned int val, hostval ;
+ char *cmd;
+ int i;
+
+ RDEBUG(("MON write %d %08x\n",len,(unsigned long)memaddr))
+
+ if (current_monitor->flags & MO_ADDR_BITS_REMOVE)
+ memaddr = ADDR_BITS_REMOVE (memaddr);
+
+ /* Use memory fill command for leading 0 bytes. */
+
+ if (current_monitor->fill)
+ {
+ for (i = 0; i < len; i++)
+ if (myaddr[i] != 0)
+ break;
+
+ if (i > 4) /* More than 4 zeros is worth doing */
+ {
+ RDEBUG(("MON FILL %d\n",i))
+ if (current_monitor->flags & MO_FILL_USES_ADDR)
+ monitor_printf (current_monitor->fill, memaddr, (memaddr + i)-1, 0);
+ else
+ monitor_printf (current_monitor->fill, memaddr, i, 0);
+
+ monitor_expect_prompt (NULL, 0);
+
+ return i;
+ }
+ }
+
+#if 0
+ /* Can't actually use long longs if VAL is an int (nice idea, though). */
+ if ((memaddr & 0x7) == 0 && len >= 8 && current_monitor->setmem.cmdll)
+ {
+ len = 8;
+ cmd = current_monitor->setmem.cmdll;
+ }
+ else
+#endif
+ if ((memaddr & 0x3) == 0 && len >= 4 && current_monitor->setmem.cmdl)
+ {
+ len = 4;
+ cmd = current_monitor->setmem.cmdl;
+ }
+ else if ((memaddr & 0x1) == 0 && len >= 2 && current_monitor->setmem.cmdw)
+ {
+ len = 2;
+ cmd = current_monitor->setmem.cmdw;
+ }
+ else
+ {
+ len = 1;
+ cmd = current_monitor->setmem.cmdb;
+ }
+
+ val = extract_unsigned_integer (myaddr, len);
+
+ if (len == 4)
+ { hostval = * (unsigned int *) myaddr ;
+ RDEBUG(("Hostval(%08x) val(%08x)\n",hostval,val)) ;
+ }
+
+
+ if (current_monitor->flags & MO_NO_ECHO_ON_SETMEM)
+ monitor_printf_noecho (cmd, memaddr, val);
+ else if (current_monitor->flags & MO_SETMEM_INTERACTIVE)
+ {
+
+ monitor_printf_noecho (cmd, memaddr);
+
+ if (current_monitor->setmem.term)
+ { RDEBUG(("EXP setmem.term")) ;
+ monitor_expect (current_monitor->setmem.term, NULL, 0);
+ monitor_printf ("%x\r", val);
+ }
+ if (current_monitor->setmem.term_cmd)
+ { /* Emit this to get out of the memory editing state */
+ monitor_printf("%s",current_monitor->setmem.term_cmd) ;
+ /* Drop through to expecting a prompt */
+ }
+ }
+ else
+ monitor_printf (cmd, memaddr, val);
+
+ monitor_expect_prompt (NULL, 0);
+
+ return len;
+}
+
+
+static int
+monitor_write_even_block(memaddr,myaddr,len)
+ CORE_ADDR memaddr ;
+ char * myaddr ;
+ int len ;
+{
+ unsigned int val ;
+ int written = 0 ;;
+ /* Enter the sub mode */
+ monitor_printf(current_monitor->setmem.cmdl,memaddr) ;
+ monitor_expect_prompt(NULL,0) ;
+
+ while (len)
+ {
+ val = extract_unsigned_integer(myaddr,4) ; /* REALLY */
+ monitor_printf("%x\r",val) ;
+ myaddr += 4 ;
+ memaddr += 4 ;
+ written += 4 ;
+ RDEBUG((" @ %08x\n",memaddr))
+ /* If we wanted to, here we could validate the address */
+ monitor_expect_prompt(NULL,0) ;
+ }
+ /* Now exit the sub mode */
+ monitor_printf (current_monitor->getreg.term_cmd);
+ monitor_expect_prompt(NULL,0) ;
+ return written ;
+}
+
+
+static int monitor_write_memory_bytes(memaddr,myaddr,len)
+ CORE_ADDR memaddr ;
+ char * myaddr ;
+ int len ;
+{
+ unsigned char val ;
+ int written = 0 ;
+ if (len == 0) return 0 ;
+ /* Enter the sub mode */
+ monitor_printf(current_monitor->setmem.cmdb,memaddr) ;
+ monitor_expect_prompt(NULL,0) ;
+ while (len)
+ {
+ val = *myaddr ;
+ monitor_printf("%x\r",val) ;
+ myaddr++ ;
+ memaddr++ ;
+ written++ ;
+ /* If we wanted to, here we could validate the address */
+ monitor_expect_prompt(NULL,0) ;
+ len-- ;
+ }
+ /* Now exit the sub mode */
+ monitor_printf (current_monitor->getreg.term_cmd);
+ monitor_expect_prompt(NULL,0) ;
+ return written ;
+}
+
+
+static void
+longlongendswap (unsigned char * a)
+{
+ int i,j ;
+ unsigned char x ;
+ i = 0 ; j = 7 ;
+ while (i < 4)
+ { x = *(a+i) ;
+ *(a+i) = *(a+j) ;
+ *(a+j) = x ;
+ i++ , j-- ;
+ }
+}
+/* Format 32 chars of long long value, advance the pointer */
+static char * hexlate = "0123456789abcdef" ;
+static char * longlong_hexchars(unsigned long long value,
+ char * outbuff )
+{
+ if (value == 0) { *outbuff++ = '0' ; return outbuff ; }
+ else
+ { static unsigned char disbuf[8] ; /* disassembly buffer */
+ unsigned char * scan , * limit ; /* loop controls */
+ unsigned char c , nib ;
+ int leadzero = 1 ;
+ scan = disbuf ; limit = scan + 8 ;
+ { unsigned long long * dp ;
+ dp = (unsigned long long *) scan ;
+ *dp = value ;
+ }
+ longlongendswap(disbuf) ; /* FIXME: ONly on big endian hosts */
+ while (scan < limit)
+ { c = *scan++ ; /* a byte of our long long value */
+ if (leadzero)
+ if (c == 0) continue ;
+ else leadzero = 0 ; /* henceforth we print even zeroes */
+ nib = c >> 4 ; /* high nibble bits */
+ *outbuff++ = hexlate[nib] ;
+ nib = c & 0x0f ; /* low nibble bits */
+ *outbuff++ = hexlate[nib] ;
+ }
+ return outbuff ;
+ }
+} /* longlong_hexchars */
+
+
+
+/* I am only going to call this when writing virtual byte streams.
+ Which possably entails endian conversions
+ */
+static int monitor_write_memory_longlongs(memaddr,myaddr,len)
+ CORE_ADDR memaddr ;
+ char * myaddr ;
+ int len ;
+{
+ static char hexstage[20] ; /* At least 16 digits required, plus null */
+ char * endstring ;
+ long long * llptr ;
+ long long value ;
+ int written = 0 ;
+ llptr = (unsigned long long *) myaddr ;
+ if (len == 0 ) return 0 ;
+ monitor_printf(current_monitor->setmem.cmdll,memaddr) ;
+ monitor_expect_prompt(NULL,0) ;
+ while (len >= 8 )
+ {
+ value = *llptr ;
+ endstring = longlong_hexchars(*llptr,hexstage) ;
+ *endstring = '\0' ; /* NUll terminate for printf */
+ monitor_printf("%s\r",hexstage) ;
+ llptr++ ;
+ memaddr += 8 ;
+ written += 8 ;
+ /* If we wanted to, here we could validate the address */
+ monitor_expect_prompt(NULL,0) ;
+ len -= 8 ;
+ }
+ /* Now exit the sub mode */
+ monitor_printf (current_monitor->getreg.term_cmd);
+ monitor_expect_prompt(NULL,0) ;
+ return written ;
+} /* */
+
+
+
+/* ----- MONITOR_WRITE_MEMORY_BLOCK ---------------------------- */
+/* This is for the large blocks of memory which may occur in downloading.
+ And for monitors which use interactive entry,
+ And for monitors which do not have other downloading methods.
+ Without this, we will end up calling monitor_write_memory many times
+ and do the entry and exit of the sub mode many times
+ This currently assumes...
+ MO_SETMEM_INTERACTIVE
+ ! MO_NO_ECHO_ON_SETMEM
+ To use this, the you have to patch the monitor_cmds block with
+ this function. Otherwise, its not tuned up for use by all
+ monitor variations.
+ */
+
+static int monitor_write_memory_block(memaddr,myaddr,len)
+ CORE_ADDR memaddr ;
+ char * myaddr ;
+ int len ;
+{
+ int written ;
+ written = 0 ;
+ /* FIXME: This would be a good place to put the zero test */
+#if 1
+ if ((len > 8) && (((len & 0x07)) == 0) && current_monitor->setmem.cmdll)
+ {
+ return monitor_write_memory_longlongs(memaddr,myaddr,len) ;
+ }
+#endif
+#if 0
+ if (len > 4)
+ {
+ int sublen ;
+ written = monitor_write_even_block(memaddr,myaddr,len) ;
+ /* Adjust calling parameters by written amount */
+ memaddr += written ;
+ myaddr += written ;
+ len -= written ;
+ }
+#endif
+ written = monitor_write_memory_bytes(memaddr,myaddr,len) ;
+ return written ;
+}
+
+/* This is an alternate form of monitor_read_memory which is used for monitors
+ which can only read a single byte/word/etc. at a time. */
+
+static int
+monitor_read_memory_single (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+{
+ unsigned int val;
+ char membuf[sizeof(int) * 2 + 1];
+ char *p;
+ char *cmd;
+ int i;
+
+ RDEBUG(("MON read single\n")) ;
+#if 0
+ /* Can't actually use long longs (nice idea, though). In fact, the
+ call to strtoul below will fail if it tries to convert a value
+ that's too big to fit in a long. */
+ if ((memaddr & 0x7) == 0 && len >= 8 && current_monitor->getmem.cmdll)
+ {
+ len = 8;
+ cmd = current_monitor->getmem.cmdll;
+ }
+ else
+#endif
+ if ((memaddr & 0x3) == 0 && len >= 4 && current_monitor->getmem.cmdl)
+ {
+ len = 4;
+ cmd = current_monitor->getmem.cmdl;
+ }
+ else if ((memaddr & 0x1) == 0 && len >= 2 && current_monitor->getmem.cmdw)
+ {
+ len = 2;
+ cmd = current_monitor->getmem.cmdw;
+ }
+ else
+ {
+ len = 1;
+ cmd = current_monitor->getmem.cmdb;
+ }
+
+ /* Send the examine command. */
+
+ monitor_printf (cmd, memaddr);
+
+ /* If RESP_DELIM is specified, we search for that as a leading
+ delimiter for the memory value. Otherwise, we just start
+ searching from the start of the buf. */
+
+ if (current_monitor->getmem.resp_delim)
+ { RDEBUG(("EXP getmem.resp_delim\n")) ;
+ monitor_expect_regexp (&getmem_resp_delim_pattern, NULL, 0);
+ }
+
+ /* Now, read the appropriate number of hex digits for this loc,
+ skipping spaces. */
+
+ /* Skip leading spaces and "0x" if MO_HEX_PREFIX flag is set. */
+ if (current_monitor->flags & MO_HEX_PREFIX)
+ {
+ int c;
+
+ c = readchar (timeout);
+ while (c == ' ')
+ c = readchar (timeout);
+ if ((c == '0') && ((c = readchar (timeout)) == 'x'))
+ ;
+ else
+ monitor_error ("monitor_read_memory_single (0x%x): bad response from monitor: %.*s%c.",
+ memaddr, i, membuf, c);
+ }
+ for (i = 0; i < len * 2; i++)
+ {
+ int c;
+
+ while (1)
+ {
+ c = readchar (timeout);
+ if (isxdigit (c))
+ break;
+ if (c == ' ')
+ continue;
+
+ monitor_error ("monitor_read_memory_single (0x%x): bad response from monitor: %.*s%c.",
+ memaddr, i, membuf, c);
+ }
+
+ membuf[i] = c;
+ }
+
+ membuf[i] = '\000'; /* terminate the number */
+
+/* If TERM is present, we wait for that to show up. Also, (if TERM is
+ present), we will send TERM_CMD if that is present. In any case, we collect
+ all of the output into buf, and then wait for the normal prompt. */
+
+ if (current_monitor->getmem.term)
+ {
+ monitor_expect (current_monitor->getmem.term, NULL, 0); /* get response */
+
+ if (current_monitor->getmem.term_cmd)
+ {
+ monitor_printf (current_monitor->getmem.term_cmd);
+ monitor_expect_prompt (NULL, 0);
+ }
+ }
+ else
+ monitor_expect_prompt (NULL, 0); /* get response */
+
+ p = membuf;
+ val = strtoul (membuf, &p, 16);
+
+ if (val == 0 && membuf == p)
+ monitor_error ("monitor_read_memory_single (0x%x): bad value from monitor: %s.",
+ memaddr, 0, membuf, 0);
+
+ /* supply register stores in target byte order, so swap here */
+
+ store_unsigned_integer (myaddr, len, val);
+
+ return len;
+}
+
+/* Copy LEN bytes of data from debugger memory at MYADDR to inferior's
+ memory at MEMADDR. Returns length moved. Currently, we do no more
+ than 16 bytes at a time. */
+
+static int
+monitor_read_memory (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+{
+ unsigned int val;
+ char buf[512];
+ char *p, *p1;
+ int resp_len;
+ int i;
+ CORE_ADDR dumpaddr;
+
+ if (len <= 0)
+ {
+ RDEBUG (("Zero length call to monitor_read_memory\n"));
+ return 0;
+ }
+
+ if (remote_debug) printf("MON read block ta(%08x) ha(%08x) %d\n",
+ (unsigned long) memaddr , (unsigned long)myaddr, len);
+
+ if (current_monitor->flags & MO_ADDR_BITS_REMOVE)
+ memaddr = ADDR_BITS_REMOVE (memaddr);
+
+ if (current_monitor->flags & MO_GETMEM_READ_SINGLE)
+ return monitor_read_memory_single (memaddr, myaddr, len);
+
+ len = min (len, 16);
+
+ /* Some dumpers align the first data with the preceeding 16
+ byte boundary. Some print blanks and start at the
+ requested boundary. EXACT_DUMPADDR
+ */
+
+ dumpaddr = (current_monitor->flags & MO_EXACT_DUMPADDR)
+ ? memaddr : memaddr & ~ 0x0f ;
+
+ /* See if xfer would cross a 16 byte boundary. If so, clip it. */
+ if (((memaddr ^ (memaddr + len - 1)) & ~0xf) != 0)
+ len = ((memaddr + len) & ~0xf) - memaddr;
+
+ /* send the memory examine command */
+
+ if (current_monitor->flags & MO_GETMEM_NEEDS_RANGE)
+ monitor_printf (current_monitor->getmem.cmdb, memaddr, memaddr + len - 1);
+ else if (current_monitor->flags & MO_GETMEM_16_BOUNDARY)
+ monitor_printf (current_monitor->getmem.cmdb, dumpaddr);
+ else
+ monitor_printf (current_monitor->getmem.cmdb, memaddr, len);
+
+ /* If TERM is present, we wait for that to show up. Also, (if TERM
+ is present), we will send TERM_CMD if that is present. In any
+ case, we collect all of the output into buf, and then wait for
+ the normal prompt. */
+
+ if (current_monitor->getmem.term)
+ {
+ resp_len = monitor_expect (current_monitor->getmem.term, buf, sizeof buf); /* get response */
+
+ if (resp_len <= 0)
+ monitor_error ("monitor_read_memory (0x%x): excessive response from monitor: %.*s.",
+ memaddr, resp_len, buf, 0);
+
+ if (current_monitor->getmem.term_cmd)
+ {
+ SERIAL_WRITE (monitor_desc, current_monitor->getmem.term_cmd,
+ strlen (current_monitor->getmem.term_cmd));
+ monitor_expect_prompt (NULL, 0);
+ }
+ }
+ else
+ resp_len = monitor_expect_prompt (buf, sizeof buf); /* get response */
+
+ p = buf;
+
+ /* If RESP_DELIM is specified, we search for that as a leading
+ delimiter for the values. Otherwise, we just start searching
+ from the start of the buf. */
+
+ if (current_monitor->getmem.resp_delim)
+ {
+ int retval, tmp;
+ struct re_registers resp_strings;
+ RDEBUG(("MON getmem.resp_delim %s\n",current_monitor->getmem.resp_delim)) ;
+
+ memset (&resp_strings, 0, sizeof (struct re_registers));
+ tmp = strlen (p);
+ retval = re_search (&getmem_resp_delim_pattern, p, tmp, 0, tmp,
+ &resp_strings);
+
+ if (retval < 0)
+ monitor_error ("monitor_read_memory (0x%x): bad response from monitor: %.*s.",
+ memaddr, resp_len, buf, 0);
+
+ p += resp_strings.end[0];
+#if 0
+ p = strstr (p, current_monitor->getmem.resp_delim);
+ if (!p)
+ monitor_error ("monitor_read_memory (0x%x): bad response from monitor: %.*s.",
+ memaddr, resp_len, buf, 0);
+ p += strlen (current_monitor->getmem.resp_delim);
+#endif
+ }
+ if (remote_debug) printf("MON scanning %d ,%08x '%s'\n",len,p,p) ;
+ if (current_monitor->flags & MO_GETMEM_16_BOUNDARY)
+ {
+ char c ;
+ int fetched = 0 ;
+ i = len;
+ c = *p ;
+
+
+ while (!(c == '\000' || c == '\n' || c == '\r') && i > 0)
+ { if (isxdigit (c))
+ { if ((dumpaddr >= memaddr) && (i > 0))
+ { val = fromhex (c) * 16 + fromhex (*(p+1));
+ *myaddr++ = val;
+ if (remote_debug) printf("[%02x]",val) ;
+ --i;
+ fetched++ ;
+ }
+ ++dumpaddr;
+ ++p;
+ }
+ ++p; /* skip a blank or other non hex char */
+ c = *p ;
+ }
+ if (fetched == 0) error("Failed to read via monitor") ;
+ if (remote_debug) printf("\n") ;
+ return fetched ; /* Return the number of bytes actually read */
+ }
+ RDEBUG(("MON scanning bytes\n")) ;
+
+ for (i = len; i > 0; i--)
+ {
+ /* Skip non-hex chars, but bomb on end of string and newlines */
+
+ while (1)
+ {
+ if (isxdigit (*p))
+ break;
+
+ if (*p == '\000' || *p == '\n' || *p == '\r')
+ monitor_error ("monitor_read_memory (0x%x): badly terminated response from monitor: %.*s",
+ memaddr, resp_len, buf, 0);
+ p++;
+ }
+
+ val = strtoul (p, &p1, 16);
+
+ if (val == 0 && p == p1)
+ monitor_error ("monitor_read_memory (0x%x): bad value from monitor: %.*s.",
+ memaddr, resp_len, buf, 0);
+
+ *myaddr++ = val;
+
+ if (i == 1)
+ break;
+
+ p = p1;
+ }
+
+ return len;
+}
+
+static int
+monitor_xfer_memory (memaddr, myaddr, len, write, target)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+ int write;
+ struct target_ops *target; /* ignored */
+{
+ return dcache_xfer_memory (remote_dcache, memaddr, myaddr, len, write);
+}
+
+static void
+monitor_kill ()
+{
+ return; /* ignore attempts to kill target system */
+}
+
+/* All we actually do is set the PC to the start address of exec_bfd, and start
+ the program at that point. */
+
+static void
+monitor_create_inferior (exec_file, args, env)
+ char *exec_file;
+ char *args;
+ char **env;
+{
+ if (args && (*args != '\000'))
+ error ("Args are not supported by the monitor.");
+
+ first_time = 1;
+ clear_proceed_status ();
+ proceed (bfd_get_start_address (exec_bfd), TARGET_SIGNAL_0, 0);
+}
+
+/* Clean up when a program exits.
+ The program actually lives on in the remote processor's RAM, and may be
+ run again without a download. Don't leave it full of breakpoint
+ instructions. */
+
+static void
+monitor_mourn_inferior ()
+{
+ unpush_target (targ_ops);
+ generic_mourn_inferior (); /* Do all the proper things now */
+}
+
+#define NUM_MONITOR_BREAKPOINTS 8
+
+static CORE_ADDR breakaddr[NUM_MONITOR_BREAKPOINTS] = {0};
+
+/* Tell the monitor to add a breakpoint. */
+
+static int
+monitor_insert_breakpoint (addr, shadow)
+ CORE_ADDR addr;
+ char *shadow;
+{
+ int i;
+ unsigned char *bp;
+ int bplen;
+
+ RDEBUG(("MON inst bkpt %08x\n",addr))
+ if (current_monitor->set_break == NULL)
+ error ("No set_break defined for this monitor");
+
+ if (current_monitor->flags & MO_ADDR_BITS_REMOVE)
+ addr = ADDR_BITS_REMOVE (addr);
+
+ /* Determine appropriate breakpoint size for this address. */
+ bp = memory_breakpoint_from_pc (&addr, &bplen);
+
+ for (i = 0; i < NUM_MONITOR_BREAKPOINTS; i++)
+ {
+ if (breakaddr[i] == 0)
+ {
+ breakaddr[i] = addr;
+ monitor_read_memory (addr, shadow, bplen);
+ monitor_printf (current_monitor->set_break, addr);
+ monitor_expect_prompt (NULL, 0);
+ return 0;
+ }
+ }
+
+ error ("Too many breakpoints (> %d) for monitor.", NUM_MONITOR_BREAKPOINTS);
+}
+
+/* Tell the monitor to remove a breakpoint. */
+
+static int
+monitor_remove_breakpoint (addr, shadow)
+ CORE_ADDR addr;
+ char *shadow;
+{
+ int i;
+
+ RDEBUG(("MON rmbkpt %08x\n",addr))
+ if (current_monitor->clr_break == NULL)
+ error ("No clr_break defined for this monitor");
+
+ if (current_monitor->flags & MO_ADDR_BITS_REMOVE)
+ addr = ADDR_BITS_REMOVE (addr);
+
+ for (i = 0; i < NUM_MONITOR_BREAKPOINTS; i++)
+ {
+ if (breakaddr[i] == addr)
+ {
+ breakaddr[i] = 0;
+ /* some monitors remove breakpoints based on the address */
+ if (current_monitor->flags & MO_CLR_BREAK_USES_ADDR)
+ monitor_printf (current_monitor->clr_break, addr);
+ else if (current_monitor->flags & MO_CLR_BREAK_1_BASED)
+ monitor_printf (current_monitor->clr_break, i + 1);
+ else
+ monitor_printf (current_monitor->clr_break, i);
+ monitor_expect_prompt (NULL, 0);
+ return 0;
+ }
+ }
+ fprintf_unfiltered (gdb_stderr,
+ "Can't find breakpoint associated with 0x%x\n", addr);
+ return 1;
+}
+
+/* monitor_wait_srec_ack -- wait for the target to send an acknowledgement for
+ an S-record. Return non-zero if the ACK is received properly. */
+
+static int
+monitor_wait_srec_ack ()
+{
+ int i, ch;
+
+ if (current_monitor->flags & MO_SREC_ACK_PLUS)
+ {
+ return (readchar (timeout) == '+');
+ }
+ else if (current_monitor->flags & MO_SREC_ACK_ROTATE)
+ {
+ /* Eat two backspaces, a "rotating" char (|/-\), and a space. */
+ if ((ch = readchar (1)) < 0)
+ return 0;
+ if ((ch = readchar (1)) < 0)
+ return 0;
+ if ((ch = readchar (1)) < 0)
+ return 0;
+ if ((ch = readchar (1)) < 0)
+ return 0;
+ }
+ return 1;
+}
+
+/* monitor_load -- download a file. */
+
+static void
+monitor_load (file, from_tty)
+ char *file;
+ int from_tty;
+{
+ dcache_flush (remote_dcache);
+ RDEBUG(("MON load\n"))
+
+ if (current_monitor->load_routine)
+ current_monitor->load_routine (monitor_desc, file, hashmark);
+ else
+ { /* The default is ascii S-records */
+ int n;
+ unsigned long load_offset;
+ char buf[128];
+
+ /* enable user to specify address for downloading as 2nd arg to load */
+ n = sscanf (file, "%s 0x%lx", buf, &load_offset);
+ if (n > 1)
+ file = buf;
+ else
+ load_offset = 0;
+
+ monitor_printf (current_monitor->load);
+ if (current_monitor->loadresp)
+ monitor_expect (current_monitor->loadresp, NULL, 0);
+
+ load_srec (monitor_desc, file, (bfd_vma) load_offset,
+ 32, SREC_ALL, hashmark,
+ current_monitor->flags & MO_SREC_ACK ?
+ monitor_wait_srec_ack : NULL);
+
+ monitor_expect_prompt (NULL, 0);
+ }
+
+/* Finally, make the PC point at the start address */
+
+ if (exec_bfd)
+ write_pc (bfd_get_start_address (exec_bfd));
+
+ inferior_pid = 0; /* No process now */
+
+/* This is necessary because many things were based on the PC at the time that
+ we attached to the monitor, which is no longer valid now that we have loaded
+ new code (and just changed the PC). Another way to do this might be to call
+ normal_stop, except that the stack may not be valid, and things would get
+ horribly confused... */
+
+ clear_symtab_users ();
+}
+
+static void
+monitor_stop ()
+{
+ RDEBUG(("MON stop\n")) ;
+ if ((current_monitor->flags & MO_SEND_BREAK_ON_STOP) != 0)
+ SERIAL_SEND_BREAK (monitor_desc);
+ if (current_monitor->stop)
+ monitor_printf_noecho (current_monitor->stop);
+}
+
+/* Put a command string, in args, out to MONITOR. Output from MONITOR
+ is placed on the users terminal until the prompt is seen. FIXME: We
+ read the characters ourseleves here cause of a nasty echo. */
+
+static void
+monitor_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ char *p;
+ int resp_len;
+ char buf[1000];
+
+ if (monitor_desc == NULL)
+ error ("monitor target not open.");
+
+ p = current_monitor->prompt;
+
+ /* Send the command. Note that if no args were supplied, then we're
+ just sending the monitor a newline, which is sometimes useful. */
+
+ monitor_printf ("%s\r", (args ? args : ""));
+
+ resp_len = monitor_expect_prompt (buf, sizeof buf);
+
+ fputs_unfiltered (buf, gdb_stdout); /* Output the response */
+}
+
+/* Convert hex digit A to a number. */
+
+#if 0
+static int
+from_hex (a)
+ int a;
+{
+ if (a >= '0' && a <= '9')
+ return a - '0';
+ if (a >= 'a' && a <= 'f')
+ return a - 'a' + 10;
+ if (a >= 'A' && a <= 'F')
+ return a - 'A' + 10;
+
+ error ("Reply contains invalid hex digit 0x%x", a);
+}
+#endif
+
+char *
+monitor_get_dev_name ()
+{
+ return dev_name;
+}
+
+static struct target_ops monitor_ops;
+
+static void
+init_base_monitor_ops (void)
+{
+ monitor_ops.to_shortname = NULL;
+ monitor_ops.to_longname = NULL;
+ monitor_ops.to_doc = NULL;
+ monitor_ops.to_open = NULL;
+ monitor_ops.to_close = monitor_close;
+ monitor_ops.to_attach = NULL;
+ monitor_ops.to_post_attach = NULL;
+ monitor_ops.to_require_attach = NULL;
+ monitor_ops.to_detach = monitor_detach;
+ monitor_ops.to_require_detach = NULL;
+ monitor_ops.to_resume = monitor_resume;
+ monitor_ops.to_wait = monitor_wait;
+ monitor_ops.to_post_wait = NULL;
+ monitor_ops.to_fetch_registers = monitor_fetch_registers;
+ monitor_ops.to_store_registers = monitor_store_registers;
+ monitor_ops.to_prepare_to_store = monitor_prepare_to_store;
+ monitor_ops.to_xfer_memory = monitor_xfer_memory;
+ monitor_ops.to_files_info = monitor_files_info;
+ monitor_ops.to_insert_breakpoint = monitor_insert_breakpoint;
+ monitor_ops.to_remove_breakpoint = monitor_remove_breakpoint;
+ monitor_ops.to_terminal_init = 0;
+ monitor_ops.to_terminal_inferior = 0;
+ monitor_ops.to_terminal_ours_for_output = 0;
+ monitor_ops.to_terminal_ours = 0;
+ monitor_ops.to_terminal_info = 0;
+ monitor_ops.to_kill = monitor_kill;
+ monitor_ops.to_load = monitor_load;
+ monitor_ops.to_lookup_symbol = 0;
+ monitor_ops.to_create_inferior = monitor_create_inferior;
+ monitor_ops.to_post_startup_inferior = NULL;
+ monitor_ops.to_acknowledge_created_inferior = NULL;
+ monitor_ops.to_clone_and_follow_inferior = NULL;
+ monitor_ops.to_post_follow_inferior_by_clone = NULL;
+ monitor_ops.to_insert_fork_catchpoint = NULL;
+ monitor_ops.to_remove_fork_catchpoint = NULL;
+ monitor_ops.to_insert_vfork_catchpoint = NULL;
+ monitor_ops.to_remove_vfork_catchpoint = NULL;
+ monitor_ops.to_has_forked = NULL;
+ monitor_ops.to_has_vforked = NULL;
+ monitor_ops.to_can_follow_vfork_prior_to_exec = NULL;
+ monitor_ops.to_post_follow_vfork = NULL;
+ monitor_ops.to_insert_exec_catchpoint = NULL;
+ monitor_ops.to_remove_exec_catchpoint = NULL;
+ monitor_ops.to_has_execd = NULL;
+ monitor_ops.to_reported_exec_events_per_exec_call = NULL;
+ monitor_ops.to_has_exited = NULL;
+ monitor_ops.to_mourn_inferior = monitor_mourn_inferior;
+ monitor_ops.to_can_run = 0;
+ monitor_ops.to_notice_signals = 0;
+ monitor_ops.to_thread_alive = 0;
+ monitor_ops.to_stop = monitor_stop;
+ monitor_ops.to_pid_to_exec_file = NULL;
+ monitor_ops.to_core_file_to_sym_file = NULL;
+ monitor_ops.to_stratum = process_stratum;
+ monitor_ops.DONT_USE = 0;
+ monitor_ops.to_has_all_memory = 1;
+ monitor_ops.to_has_memory = 1;
+ monitor_ops.to_has_stack = 1;
+ monitor_ops.to_has_registers = 1;
+ monitor_ops.to_has_execution = 1;
+ monitor_ops.to_sections = 0;
+ monitor_ops.to_sections_end = 0;
+ monitor_ops.to_magic = OPS_MAGIC;
+} /* init_base_monitor_ops */
+
+/* Init the target_ops structure pointed at by OPS */
+
+void
+init_monitor_ops (ops)
+ struct target_ops *ops;
+{
+ if (monitor_ops.to_magic != OPS_MAGIC)
+ init_base_monitor_ops ();
+
+ memcpy (ops, &monitor_ops, sizeof monitor_ops);
+}
+
+/* Define additional commands that are usually only used by monitors. */
+
+void
+_initialize_remote_monitors ()
+{
+ init_base_monitor_ops ();
+ add_show_from_set (add_set_cmd ("hash", no_class, var_boolean,
+ (char *)&hashmark,
+ "Set display of activity while downloading a file.\n\
+When enabled, a hashmark \'#\' is displayed.",
+ &setlist),
+ &showlist);
+
+ add_com ("monitor", class_obscure, monitor_command,
+ "Send a command to the debug monitor.");
+}
+
+
diff --git a/gdb/monitor.h b/gdb/monitor.h
new file mode 100644
index 00000000000..4ccddd59e6b
--- /dev/null
+++ b/gdb/monitor.h
@@ -0,0 +1,247 @@
+/* Definitions for remote debugging interface for ROM monitors.
+ Copyright 1990, 1991, 1992, 1996 Free Software Foundation, Inc.
+ Contributed by Cygnus Support. Written by Rob Savoye for Cygnus.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "serial.h"
+
+/* This structure describes the strings necessary to give small command
+ sequences to the monitor, and parse the response.
+
+ CMD is the actual command typed at the monitor. Usually this has
+ embedded sequences ala printf, which are substituted with the
+ arguments appropriate to that type of command. Ie: to examine a
+ register, we substitute the register name for the first arg. To
+ modify memory, we substitute the memory location and the new
+ contents for the first and second args, etc...
+
+ RESP_DELIM used to home in on the response string, and is used to
+ disambiguate the answer within the pile of text returned by the
+ monitor. This should be a unique string that immediately precedes
+ the answer. Ie: if your monitor prints out `PC: 00000001= ' in
+ response to asking for the PC, you should use `: ' as the
+ RESP_DELIM. RESP_DELIM may be NULL if the res- ponse is going to
+ be ignored, or has no particular leading text.
+
+ TERM is the string that the monitor outputs to indicate that it is
+ idle, and waiting for input. This is usually a prompt of some
+ sort. In the previous example, it would be `= '. It is important
+ that TERM really means that the monitor is idle, otherwise GDB may
+ try to type at it when it isn't ready for input. This is a problem
+ because many monitors cannot deal with type-ahead. TERM may be
+ NULL if the normal prompt is output.
+
+ TERM_CMD is used to quit out of the subcommand mode and get back to
+ the main prompt. TERM_CMD may be NULL if it isn't necessary. It
+ will also be ignored if TERM is NULL. */
+
+struct memrw_cmd
+{
+ char *cmdb; /* Command to send for byte read/write */
+ char *cmdw; /* Command for word (16 bit) read/write */
+ char *cmdl; /* Command for long (32 bit) read/write */
+ char *cmdll; /* Command for long long (64 bit) read/write */
+ char *resp_delim; /* String just prior to the desired value */
+ char *term; /* Terminating string to search for */
+ char *term_cmd; /* String to get out of sub-mode (if necessary) */
+};
+
+struct regrw_cmd
+{
+ char *cmd; /* Command to send for reg read/write */
+ char *resp_delim; /* String (actually a regexp if getmem) just
+ prior to the desired value */
+ char *term; /* Terminating string to search for */
+ char *term_cmd; /* String to get out of sub-mode (if necessary) */
+};
+
+struct monitor_ops
+{
+ int flags; /* See below */
+ char **init; /* List of init commands. NULL terminated. */
+ char *cont; /* continue command */
+ char *step; /* single step */
+ char *stop; /* Interrupt program string */
+ char *set_break; /* set a breakpoint */
+ char *clr_break; /* clear a breakpoint */
+ char *clr_all_break; /* Clear all breakpoints */
+ char *fill; /* Memory fill cmd (addr len val) */
+ struct memrw_cmd setmem; /* set memory to a value */
+ struct memrw_cmd getmem; /* display memory */
+ struct regrw_cmd setreg; /* set a register */
+ struct regrw_cmd getreg; /* get a register */
+ /* Some commands can dump a bunch of registers
+ at once. This comes as a set of REG=VAL
+ pairs. This should be called for each pair
+ of registers that we can parse to supply
+ GDB with the value of a register. */
+ char *dump_registers; /* Command to dump all regs at once */
+ char *register_pattern; /* Pattern that picks out register from reg dump */
+ void (*supply_register) PARAMS ((char *name, int namelen,
+ char *val, int vallen));
+ void (*load_routine) PARAMS ((serial_t desc, char *file,
+ int hashmark)); /* Download routine */
+ int (*dumpregs) PARAMS((void)) ; /* routine to dump all registers */
+ int (*continue_hook) PARAMS((void)) ; /* Emit the continue command */
+ int (*wait_filter) PARAMS((char * buf, /* Maybe contains registers */
+ int bufmax ,
+ int * response_length,
+ struct target_waitstatus * status)) ;
+ char *load; /* load command */
+ char *loadresp; /* Response to load command */
+ char *prompt; /* monitor command prompt */
+ char *line_term; /* end-of-command delimitor */
+ char *cmd_end; /* optional command terminator */
+ struct target_ops *target; /* target operations */
+ int stopbits; /* number of stop bits */
+ char **regnames; /* array of register names in ascii */
+ int magic; /* Check value */
+};
+
+/* The monitor ops magic number, used to detect if an ops structure doesn't
+ have the right number of entries filled in. */
+
+#define MONITOR_OPS_MAGIC 600925
+
+/* Flag definitions. */
+
+/* If set, then clear breakpoint command uses address, otherwise it
+ uses an index returned by the monitor. */
+
+#define MO_CLR_BREAK_USES_ADDR 0x1
+
+/* If set, then memory fill command uses STARTADDR, ENDADDR+1, VALUE
+ as args, else it uses STARTADDR, LENGTH, VALUE as args. */
+
+#define MO_FILL_USES_ADDR 0x2
+
+/* If set, then monitor doesn't automatically supply register dump
+ when coming back after a continue. */
+
+#define MO_NEED_REGDUMP_AFTER_CONT 0x4
+
+/* getmem needs start addr and end addr */
+
+#define MO_GETMEM_NEEDS_RANGE 0x8
+
+/* getmem can only read one loc at a time */
+
+#define MO_GETMEM_READ_SINGLE 0x10
+
+/* handle \r\n combinations */
+
+#define MO_HANDLE_NL 0x20
+
+/* don't expect echos in monitor_open */
+
+#define MO_NO_ECHO_ON_OPEN 0x40
+
+/* If set, send break to stop monitor */
+
+#define MO_SEND_BREAK_ON_STOP 0x80
+
+/* If set, target sends an ACK after each S-record */
+
+#define MO_SREC_ACK 0x100
+
+/* Allow 0x prefix on addresses retured from monitor */
+
+#define MO_HEX_PREFIX 0x200
+
+/* Some monitors require a different command when starting a program */
+
+#define MO_RUN_FIRST_TIME 0x400
+
+/* Don't expect echos when getting memory */
+
+#define MO_NO_ECHO_ON_SETMEM 0x800
+
+/* If set, then register store command expects value BEFORE regname */
+
+#define MO_REGISTER_VALUE_FIRST 0x1000
+
+/* If set, then the monitor displays registers as pairs. */
+
+#define MO_32_REGS_PAIRED 0x2000
+
+/* If set, then register setting happens interactively. */
+
+#define MO_SETREG_INTERACTIVE 0x4000
+
+/* If set, then memory setting happens interactively. */
+
+#define MO_SETMEM_INTERACTIVE 0x8000
+
+/* If set, then memory dumps are always on 16-byte boundaries, even
+ when less is desired. */
+
+#define MO_GETMEM_16_BOUNDARY 0x10000
+
+/* If set, then the monitor numbers its breakpoints starting from 1. */
+
+#define MO_CLR_BREAK_1_BASED 0x20000
+
+/* If set, then the monitor acks srecords with a plus sign. */
+
+#define MO_SREC_ACK_PLUS 0x40000
+
+/* If set, then the monitor "acks" srecords with rotating lines. */
+
+#define MO_SREC_ACK_ROTATE 0x80000
+
+/* If set, then remove useless address bits from memory addresses. */
+
+#define MO_ADDR_BITS_REMOVE 0x100000
+
+/* If set, then display target program output if prefixed by ^O. */
+
+#define MO_PRINT_PROGRAM_OUTPUT 0x200000
+
+/* Some dump bytes commands align the first data with the preceeding
+16 byte boundary. Some print blanks and start at the exactly the
+requested boundary. */
+
+#define MO_EXACT_DUMPADDR 0x400000
+
+/* Rather entering and exiting the write memory dialog for each word byte,
+ we can save time by transferring the whole block without exiting
+ the memory editing mode. You only need to worry about this
+ if you are doing memory downloading.
+ This engages a new write function registered with dcache.
+ */
+#define MO_HAS_BLOCKWRITES 0x800000
+
+#define SREC_SIZE 160
+
+extern void monitor_open PARAMS ((char *args, struct monitor_ops *ops,
+ int from_tty));
+extern void monitor_close PARAMS ((int quitting));
+extern char *monitor_supply_register PARAMS ((int regno, char *valstr));
+extern int monitor_expect PARAMS ((char *prompt, char *buf, int buflen));
+extern int monitor_expect_prompt PARAMS ((char *buf, int buflen));
+extern void monitor_printf PARAMS ((char *, ...))
+ ATTR_FORMAT(printf, 1, 2);
+extern void monitor_printf_noecho PARAMS ((char *, ...))
+ ATTR_FORMAT(printf, 1, 2);
+extern void monitor_write PARAMS ((char *buf, int buflen));
+extern int monitor_readchar PARAMS ((void));
+extern char *monitor_get_dev_name PARAMS ((void));
+extern void init_monitor_ops PARAMS ((struct target_ops *));
+extern int monitor_dump_reg_block PARAMS((char * dump_cmd)) ;
+extern void flush_monitor_dcache PARAMS ((void));
diff --git a/gdb/mpw-config.in b/gdb/mpw-config.in
new file mode 100644
index 00000000000..ed07878338b
--- /dev/null
+++ b/gdb/mpw-config.in
@@ -0,0 +1,81 @@
+# Configuration fragment for GDB.
+
+If "{host_canonical}" =~ /m68k-apple-mpw/
+ forward-include "{srcdir}"config:m68k:xm-mpw.h xm.h
+ Set siow_lib '"{Libraries}"SIOW.o'
+
+Else If "{host_canonical}" =~ /powerpc-apple-mpw/
+ forward-include "{srcdir}"config:powerpc:xm-mpw.h xm.h
+ Set siow_lib '"{PPCLibraries}"PPCSIOW.o'
+
+End If
+
+Set xdepfiles '"{o}"mac-xdep.c.o'
+
+Set enable_cflags ""
+
+# Make a copy of this file and give it a different name, so it
+# won't be confused with GDB's serial.h.
+
+Duplicate -y "{CIncludes}"Serial.h MacSerial.h
+
+Echo "/* dummy */" >termio.h
+
+If "{target_canonical}" =~ /m68k-apple-macos/
+ forward-include "{srcdir}"config:m68k:tm-mac.h tm.h
+ forward-include "{srcdir}"config:m68k:tm-m68k.h 'm68k/tm-m68k.h'
+ Set tdepfiles '"{o}"m68k-tdep.c.o'
+
+Else If "{target_canonical}" =~ /powerpc-apple-macos/
+ forward-include "{srcdir}"config:powerpc:tm-macos.h tm.h
+ forward-include "{srcdir}"config:rs6000:tm-rs6000.h 'rs6000/tm-rs6000.h'
+ Set tdepfiles '"{o}"rs6000-tdep.c.o "{o}"xcoffread.c.o'
+
+Else If "{target_canonical}" =~ /i386-unknown-go32/
+ forward-include "{srcdir}"config:i386:tm-i386v.h tm.h
+ Set tdepfiles '"{o}"i386-tdep.c.o'
+
+Else If "{target_canonical}" =~ /mips-idt-ecoff/
+ forward-include "{srcdir}"config:mips:tm-embed.h tm.h
+ forward-include "{srcdir}"config:mips:tm-bigmips.h 'mips/tm-bigmips.h'
+ forward-include "{srcdir}"config:mips:tm-mips.h 'mips/tm-mips.h'
+ Set tdepfiles '"{o}"mips-tdep.c.o "{o}"remote-mips.c.o'
+
+Else If "{target_canonical}" =~ /sh-hitachi-hms/
+ forward-include "{srcdir}"config:sh:tm-sh.h tm.h
+ Set tdepfiles '"{o}"sh-tdep.c.o'
+
+End If
+
+If "{target_canonical}" =~ /m68k-apple-macos/
+ forward-include "{srcdir}"config:m68k:nm-macos.h nm.h
+ Set natdepfiles '"{o}"mac-nat.c.o'
+
+Else If "{target_canonical}" =~ /powerpc-apple-macos/
+ forward-include "{srcdir}"config:powerpc:nm-macos.h nm.h
+ Set natdepfiles '"{o}"mac-nat.c.o'
+
+Else
+ forward-include "{srcdir}"config:nm-empty.h nm.h
+ Set natdepfiles ' '
+
+End If
+
+Echo '# From mpw-config.in' > "{o}"mk.tmp
+Echo "TDEPFILES = " {tdepfiles} >> "{o}"mk.tmp
+Echo "XDEPFILES = " {xdepfiles} >> "{o}"mk.tmp
+Echo "NATDEPFILES = " {natdepfiles} >> "{o}"mk.tmp
+Echo "XM_ADD_FILES = " >> "{o}"mk.tmp
+Echo "TM_ADD_FILES = " >> "{o}"mk.tmp
+Echo "NAT_ADD_FILES = " >> "{o}"mk.tmp
+Echo "XM_CDEPS = " >> "{o}"mk.tmp
+Echo "TM_CDEPS = " >> "{o}"mk.tmp
+Echo "NAT_CDEPS = " >> "{o}"mk.tmp
+Echo "SIOW_LIB = " {siow_lib} >> "{o}"mk.tmp
+Echo "ENABLE_CFLAGS = " {enable_cflags} >> "{o}"mk.tmp
+Echo '# End from mpw-config.in' >> "{o}"mk.tmp
+
+Echo '/* config.h. Generated by mpw-configure. */' > "{o}"config.new
+Echo '#include "mpw.h"' >> "{o}"config.new
+
+MoveIfChange "{o}"config.new "{o}"config.h
diff --git a/gdb/mpw-make.sed b/gdb/mpw-make.sed
new file mode 100644
index 00000000000..ce6a9ecdb15
--- /dev/null
+++ b/gdb/mpw-make.sed
@@ -0,0 +1,178 @@
+# Sed commands that finish translating the GDB Unix Makefile to MPW syntax.
+
+/^host_alias =/s/^/#/
+/^target_alias =/s/^/#/
+
+/^host_makefile_frag@$/d
+/^target_makefile_frag@$/d
+
+/@ENABLE_CFLAGS@/s/@ENABLE_CFLAGS@/{ENABLE_CFLAGS}/g
+/^ENABLE_CFLAGS=/s/^/#/
+
+# Edit all the symbolic definitions pointing to various libraries and such.
+
+/^INCLUDE_DIR = /s/"{srcdir}":include/"{topsrcdir}"include:/
+
+/^MMALLOC_DIR = /s/::mmalloc/mmalloc:/
+/^MMALLOC_SRC = /s/"{srcdir}"/"{topsrcdir}"/
+/^MMALLOC =/s/=.*$/=/
+/MMALLOC_CFLAGS =/s/=.*$/= -u USE_MMALLOC/
+
+/^BFD_DIR = /s/::bfd/bfd:/
+/^BFD = /s/{BFD_DIR}:libbfd/{BFD_DIR}libbfd/
+/^BFD_SRC = /s/"{srcdir}"/"{topsrcdir}"/
+
+/^READLINE_DIR = /s/::readline/readline:/
+/^READLINE =/s/=.*$/=/
+/^READLINE_SRC = /s/"{srcdir}"/"{topsrcdir}"/
+
+/^INCLUDE_CFLAGS = /s/$/ -i "{topsrcdir}"include:mpw: -i ::extra-include:/
+
+/^SER_HARDWIRE =/s/ser-unix/ser-mac/
+
+/^TERMCAP =/s/ =.*$/ =/
+
+# Whack out various autoconf vars that we don't need.
+/@CONFIG_LDFLAGS@/s/@CONFIG_LDFLAGS@//g
+/@HLDFLAGS@/s/@HLDFLAGS@//g
+/@DEFS@/s/@DEFS@//g
+/@YACC@/s/@YACC@/byacc/g
+/@ENABLE_OBS@/s/@ENABLE_OBS@//g
+/@ENABLE_CLIBS@/s/@ENABLE_CLIBS@//g
+/@LIBS@/s/@LIBS@//g
+
+# Whack out autoconf hook for thread debugging.
+/@THREAD_DB_OBS@/s/@THREAD_DB_OBS@//g
+
+# Fix up paths to include directories.
+/INCLUDE_DIR/s/"{s}"{INCLUDE_DIR}/{INCLUDE_DIR}/g
+/INCLUDE_DIR/s/{INCLUDE_DIR}:/{INCLUDE_DIR}/g
+/INCLUDE_DIR/s/"{INCLUDE_DIR}":/"{INCLUDE_DIR}"/g
+
+/{BFD_DIR}/s/"{BFD_DIR}":/"{BFD_DIR}"/g
+/{BFD_DIR}/s/\([ ]\){BFD_DIR}/\1::{BFD_DIR}/g
+/{BFD_DIR}/s/\([ ]\)"{BFD_DIR}"/\1::"{BFD_DIR}"/g
+
+/{BFD_SRC}/s/"{s}"{BFD_SRC}/{BFD_SRC}/g
+/{BFD_SRC}/s/{BFD_SRC}:/{BFD_SRC}/g
+
+/{READLINE_SRC}/s/"{s}"{READLINE_SRC}/{READLINE_SRC}/g
+
+/^readline_headers =/,/^$/c\
+readline_headers =\
+
+
+# This isn't really useful, and seems to cause nonsensical complaints.
+/{ALLDEPFILES}/s/{ALLDEPFILES}//g
+
+/^copying.c \\Option-f /,/^$/d
+
+# Fix the syntax of bits of C code that go into version.c.
+/char /s/'char .Option-x/'char */
+
+# Point at files in the obj dir rather than src dir.
+/version/s/"{s}"version\.c/"{o}"version.c/g
+/version/s/^version\.c/"{o}"version.c/
+/config/s/"{s}"config\.h/"{o}"config.h/g
+/config/s/^config\.h/"{o}"config.h/
+/xm/s/"{s}"xm\.h/"{o}"xm.h/g
+/xm/s/^xm\.h/"{o}"xm.h/
+/tm/s/"{s}"tm\.h/"{o}"tm.h/g
+/tm/s/^tm\.h/"{o}"tm.h/
+/nm/s/"{s}"nm\.h/"{o}"nm.h/g
+/nm/s/^nm\.h/"{o}"nm.h/
+
+/exp.tab.c/s/"{s}"\([a-z0-9]*\)-exp\.tab\.c/"{o}"\1-exp.tab.c/g
+/exp.tab.c/s/^\([a-z0-9]*\)-exp\.tab\.c/"{o}"\1-exp.tab.c/
+
+/y.tab/s/"{s}"y.tab\.c/"{o}"y.tab.c/g
+/y.tab/s/^y.tab\.c/"{o}"y.tab.c/
+
+/init/s/"{s}"init\.c-tmp/"{o}"init.c-tmp/g
+/init/s/^init\.c-tmp/"{o}"init.c-tmp/
+/init/s/"{s}"init\.c/"{o}"init.c/g
+/init/s/^init\.c/"{o}"init.c/
+
+# Fix up the generation of version.c.
+/"{o}"version.c \\Option-f Makefile/,/^$/c\
+"{o}"version.c \\Option-f Makefile\
+ echo -n 'char *version = "' >"{o}"version.c\
+ echo -n "{VERSION}" >>"{o}"version.c\
+ echo '";' >>"{o}"version.c\
+ echo -n 'char *host_name = "' >>"{o}"version.c\
+ echo -n "{host_alias}" >>"{o}"version.c\
+ echo '";' >>"{o}"version.c\
+ echo -n 'char *target_name = "' >>"{o}"version.c\
+ echo -n "{target_alias}" >>"{o}"version.c\
+ echo '";' >>"{o}"version.c\
+
+
+/ansidecl/s/include "{s}""ansidecl.h"/include "ansidecl.h"/
+
+# Open-brace in a command causes much confusion; replace with the
+# result from a script.
+/initialize_all_files ()/c\
+ Echo -n 'void initialize_all_files () ' >> "{o}"init.c-tmp\
+ open-brace >> "{o}"init.c-tmp
+
+# Replace the whole sed bit for init.c; it's simpler that way...
+/echo {OBS} {TSOBS}/,/echo '}'/c\
+ For i in {OBS} {TSOBS}\
+ Set filename "`Echo {i} | sed \\Option-d\
+ -e '/^Onindy.c.o/d' \\Option-d\
+ -e '/^nindy.c.o/d' \\Option-d\
+ -e '/ttyflush.c.o/d' \\Option-d\
+ -e '/xdr_ld.c.o/d' \\Option-d\
+ -e '/xdr_ptrace.c.o/d' \\Option-d\
+ -e '/xdr_rdb.c.o/d' \\Option-d\
+ -e '/udr.c.o/d' \\Option-d\
+ -e '/udip2soc.c.o/d' \\Option-d\
+ -e '/udi2go32.c.o/d' \\Option-d\
+ -e '/version.c.o/d' \\Option-d\
+ -e '/[a-z0-9A-Z_]*-exp.tab.c.o/d' \\Option-d\
+ -e 's/\\.c\\.o/.c/' \\Option-d\
+ -e 's/^://'`"\
+ If "{filename}" != ""\
+ sed <"{s}""{filename}" >>"{o}"init.c-tmp -n \\Option-d\
+ -e '/^_initialize_[a-z_0-9A-Z]* *(/s/^\\([a-z_0-9A-Z]*\\).*/ {extern void \\1 (); \\1 ();}/p'\
+ End If\
+ End For\
+ Echo '}' >>"{o}"init.c-tmp
+
+# Fix the main compile/link command.
+/{CC_LD} {INTERNAL_LDFLAGS} -o gdb/,/"{o}"init.c.o {OBS} {TSOBS} {ADD_FILES} {CLIBS} {LOADLIBES}/c\
+ {CC_LD} {INTERNAL_LDFLAGS} -o gdb{PROG_EXT} "{o}"init.c.o {OBS} {TSOBS} {ADD_FILES} {CLIBS} {LOADLIBES} {EXTRALIBS}\
+ {MAKEPEF} gdb{PROG_EXT} -o gdb {MAKEPEF_TOOL_FLAGS} {MAKEPEF_FLAGS}\
+ {REZ} "{s}"mac-gdb.r -o gdb -append -d PROG_NAME='"'gdb'"' -d VERSION_STRING='"'{version}'"'\
+
+# Replace the install actions with MPW-friendly script.
+/^install \\Option-f /,/^$/c\
+install \\Option-f all install-only\
+\
+install-only \\Option-f \
+ NewFolderRecursive "{bindir}"\
+ Duplicate -y gdb "{bindir}"gdb\
+ If "`Exists SiowGDB`" != ""\
+ Duplicate -y SiowGDB "{bindir}"SiowGDB\
+ End If\
+
+
+# Don't do any recursive subdir stuff.
+/ subdir_do/s/{MAKE}/null-command/
+
+# Edit out actions that only confuse MPW Make.
+/^config.status \\Option-f/,/^$/d
+/^Makefile \\Option-f/,/^$/d
+
+# Don't test config.h dependencies.
+/^"{o}"config.h \\Option-f/s/^/#/
+
+# Add an action to build SIOWgdb.
+$a\
+SIOWgdb \\Option-f {OBS} {TSOBS} {ADD_DEPS} {CDEPS} "{o}"init.c.o\
+ Delete -i -y SIOWgdb\
+ {CC_LD} {INTERNAL_LDFLAGS} -t 'APPL' -c 'gdb ' -o SIOWgdb{PROG_EXT} "{o}"init.c.o {OBS} {TSOBS} {ADD_FILES} {CLIBS} {SIOW_LIB} {LOADLIBES} {EXTRALIBS}\
+ {MAKEPEF} SIOWgdb{PROG_EXT} -o SIOWgdb -ft 'APPL' -fc 'gdb ' {MAKEPEF_FLAGS} \
+ {REZ} -o SIOWgdb "{RIncludes}"siow.r -append -d __kPrefSize=5000 -d __kMinSize=2000 -d APPNAME='"'SIOWgdb'"' \
+ {REZ} "{s}"mac-gdb.r -o SIOWgdb -append -d VERSION_STRING='"'{version}'"'\
+
diff --git a/gdb/msg.defs b/gdb/msg.defs
new file mode 100644
index 00000000000..7c9fcd15f54
--- /dev/null
+++ b/gdb/msg.defs
@@ -0,0 +1 @@
+#include <hurd/msg.defs>
diff --git a/gdb/msg_reply.defs b/gdb/msg_reply.defs
new file mode 100644
index 00000000000..049bfa87cfa
--- /dev/null
+++ b/gdb/msg_reply.defs
@@ -0,0 +1 @@
+#include <hurd/msg_reply.defs>
diff --git a/gdb/news-xdep.c b/gdb/news-xdep.c
new file mode 100644
index 00000000000..7f57aeb1d46
--- /dev/null
+++ b/gdb/news-xdep.c
@@ -0,0 +1,65 @@
+/* Low level interface to ptrace, for GDB when running under Unix.
+ Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifdef __GNUC__
+/* Bad implement execle(3). It's depend for "/bin/cc".
+
+ main()
+ {
+ printf("execle:\n");
+ execle(FILE, ARGS, envp);
+ exit(1);
+ }
+
+ GCC:
+ link a6,#0
+ pea LC5 ; call printf
+ jbsr _printf
+ ; ; (not popd stack)
+ pea _envp ; call execle
+ clrl sp@-
+ pea LC4
+ pea LC4
+ pea LC4
+ pea LC3
+ pea LC6
+ jbsr _execle
+ addw #32,sp ; delayed pop !!
+
+ /bin/cc:
+ link.l fp,#L23
+ movem.l #L24,(sp)
+ pea L26 ; call printf
+ jbsr _printf
+ addq.l #4,sp ; <--- popd stack !!
+ pea _envp ; call execle
+ clr.l -(sp)
+ pea L32
+
+ */
+
+execle(name, args)
+ char *name, *args;
+{
+ register char **env = &args;
+ while (*env++)
+ ;
+ execve(name, (char **)&args, (char **)*env);
+}
+#endif
diff --git a/gdb/nindy-share/Makefile b/gdb/nindy-share/Makefile
new file mode 100644
index 00000000000..5ec99ba38e7
--- /dev/null
+++ b/gdb/nindy-share/Makefile
@@ -0,0 +1,117 @@
+#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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+#-----------------------------------------------------------------------------
+# Makefile for toolib.a -- host code shAred by more than one tool
+#-----------------------------------------------------------------------------
+
+RANLIB = ranlib
+
+# The following lines should be uncommented for system V (i386v).
+#__i386v__#USG = -DUSG
+#__i386v__#SYSV_INCL = ${IPATH}/sysv.h
+#__i386v__#RANLIB = echo >/dev/null
+
+# The following line should be uncommented for HP-UX
+#__hp9000__#USG = -DUSG
+#__hp9000__#SYSV_INCL = ${IPATH}/sysv.h
+#__hp9000__#RANLIB = echo >/dev/null
+
+# Essential under System V, harmless elsewhere
+SHELL = /bin/sh
+
+#'HOST' will be defined in the host-specific makefile by 'make make'
+
+TARG = toolib.a
+OPT = -g
+IPATH = ../../include
+CFLAGS = ${OPT} ${USG} -I${IPATH} -DHOST=\"${HOST}\"
+OBJS = coffstrip.o nindy.o ttybreak.o ttyflush.o Onindy.o
+
+${TARG}: ${OBJS} VERSION
+ make ver960.o
+ rm -f ${TARG}
+ ar cvr ${TARG} ${OBJS} ver960.o
+ ${RANLIB} ${TARG}
+
+coffstrip.o: ${IPATH}/b.out.h ${IPATH}/coff.h ${IPATH}/sysv.h
+nindy.o: ${IPATH}/block_io.h ${IPATH}/env.h ${IPATH}/sysv.h
+nindy.o: ${IPATH}/ttycntl.h ${IPATH}/wait.h
+ttybreak.o: ${IPATH}/ttycntl.h
+ttyflush.o: ${IPATH}/ttycntl.h
+Onindy.o: ${IPATH}/block_io.h ${IPATH}/env.h ${IPATH}/sysv.h
+Onindy.o: ${IPATH}/ttycntl.h ${IPATH}/wait.h
+
+
+#-----------------------------------------------------------------------------
+# 'STANDARD' GNU/960 TARGETS BELOW THIS POINT
+#
+# 'VERSION' file must be present and contain a string of the form "x.y"
+#-----------------------------------------------------------------------------
+
+ver960.c: FORCE
+ rm -f ver960.c
+ echo "char toolib_ver[]= \"${TARG} `cat VERSION`, `date`\";" > ver960.c
+
+
+# This target should be invoked before building a new release.
+# 'VERSION' file must be present and contain a string of the form "x.y"
+#
+roll:
+ @V=`cat VERSION` ; \
+ MAJ=`sed 's/\..*//' VERSION` ; \
+ MIN=`sed 's/.*\.//' VERSION` ; \
+ V=$$MAJ.`expr $$MIN + 1` ; \
+ rm -f VERSION ; \
+ echo $$V >VERSION ; \
+ echo Version $$V
+
+# Dummy target to force execution of dependent targets.
+#
+FORCE:
+
+# 'G960BASE' will be defined at invocation
+#
+install:
+ make ${TARG}
+ mv -f ${TARG} ${G960BASE}/lib
+
+clean:
+ rm -f ${TARG} *.o core
+
+# Target to uncomment host-specific lines in this makefile. Such lines must
+# have the following string beginning in column 1: #__<hostname>__#
+# Original Makefile is backed up as 'Makefile.old'.
+#
+# Invoke with: make make HOST=xxx
+#
+make:
+ -@if test $(HOST)x = x ; then \
+ echo 'Specify "make make HOST=???"'; \
+ exit 1; \
+ fi ; \
+ grep -s "^#The next line was generated by 'make make'" Makefile; \
+ if test $$? = 0 ; then \
+ echo "Makefile has already been processed with 'make make'";\
+ exit 1; \
+ fi ; \
+ mv -f Makefile Makefile.old; \
+ echo "#The next line was generated by 'make make'" >Makefile ; \
+ echo "HOST=$(HOST)" >>Makefile ; \
+ echo >>Makefile ; \
+ sed "s/^#__$(HOST)__#//" < Makefile.old >>Makefile
diff --git a/gdb/nindy-share/Onindy.c b/gdb/nindy-share/Onindy.c
new file mode 100644
index 00000000000..c3724e6c792
--- /dev/null
+++ b/gdb/nindy-share/Onindy.c
@@ -0,0 +1,743 @@
+/* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* This started out life as code shared between the nindy monitor and
+ GDB. For various reasons, this is no longer true. Eventually, it
+ probably should be merged into remote-nindy.c. */
+
+/******************************************************************************
+ *
+ * NINDY INTERFACE ROUTINES
+ *
+ * This version of the NINDY interface routines supports NINDY versions
+ * 2.13 and older. The older versions used a hex communication protocol,
+ * instead of the (faster) current binary protocol. These routines have
+ * been renamed by prepending the letter 'O' to their names, to avoid
+ * conflict with the current version. The old versions are kept only for
+ * backward compatibility, and well disappear in a future release.
+ *
+ **************************************************************************/
+
+/* Having these in a separate file from nindy.c is really ugly, and should
+ be merged with nindy.c. */
+
+#include <stdio.h>
+#if 0
+#include <sys/ioctl.h>
+#include <sys/types.h> /* Needed by file.h on Sys V */
+#include <sys/file.h>
+#include <signal.h>
+#include <sys/stat.h>
+#include <fcntl.h> /* Needed on Sys V */
+#include "ttycntl.h"
+#endif
+#include "defs.h"
+#include "serial.h"
+
+#include "block_io.h"
+#include "wait.h"
+#include "env.h"
+
+/* Number of bytes that we send to nindy. I believe this is defined by
+ the protocol (it does not agree with REGISTER_BYTES). */
+#define OLD_NINDY_REGISTER_BYTES ((36*4) + (4*8))
+
+extern int quiet; /* 1 => stifle unnecessary messages */
+
+/* tty connected to 960/NINDY board. */
+extern serial_t nindy_serial;
+
+static OninStrGet();
+
+ /****************************
+ * *
+ * MISCELLANEOUS UTILTIES *
+ * *
+ ****************************/
+
+
+/******************************************************************************
+ * fromhex:
+ * Convert a hex ascii digit h to a binary integer
+ ******************************************************************************/
+static
+int
+fromhex( h )
+ int h;
+{
+ if (h >= '0' && h <= '9'){
+ h -= '0';
+ } else if (h >= 'a' && h <= 'f'){
+ h -= 'a' - 10;
+ } else {
+ h = 0;
+ }
+ return (h & 0xff);
+}
+
+
+/******************************************************************************
+ * hexbin:
+ * Convert a string of ASCII hex digits to a string of binary bytes.
+ ******************************************************************************/
+static
+hexbin( n, hexp, binp )
+ int n; /* Number of bytes to convert (twice this many digits)*/
+ char *hexp; /* Get hex from here */
+ char *binp; /* Put binary here */
+{
+ while ( n-- ){
+ *binp++ = (fromhex(*hexp) << 4) | fromhex(*(hexp+1));
+ hexp += 2;
+ }
+}
+
+
+/******************************************************************************
+ * binhex:
+ * Convert a string of binary bytes to a string of ASCII hex digits
+ ******************************************************************************/
+static
+binhex( n, binp, hexp )
+ int n; /* Number of bytes to convert */
+ char *binp; /* Get binary from here */
+ char *hexp; /* Place hex here */
+{
+ static char tohex[] = "0123456789abcdef";
+
+ while ( n-- ){
+ *hexp++ = tohex[ (*binp >> 4) & 0xf ];
+ *hexp++ = tohex[ *binp & 0xf ];
+ binp++;
+ }
+}
+
+/******************************************************************************
+ * byte_order:
+ * If the host byte order is different from 960 byte order (i.e., the
+ * host is big-endian), reverse the bytes in the passed value; otherwise,
+ * return the passed value unchanged.
+ *
+ ******************************************************************************/
+static
+long
+byte_order( n )
+ long n;
+{
+ long rev;
+ int i;
+ static short test = 0x1234;
+
+ if (*((char *) &test) == 0x12) {
+ /*
+ * Big-endian host, swap the bytes.
+ */
+ rev = 0;
+ for ( i = 0; i < sizeof(n); i++ ){
+ rev <<= 8;
+ rev |= n & 0xff;
+ n >>= 8;
+ }
+ n = rev;
+ }
+ return n;
+}
+
+/******************************************************************************
+ * say:
+ * This is a printf that takes at most two arguments (in addition to the
+ * format string) and that outputs nothing if verbose output has been
+ * suppressed.
+ ******************************************************************************/
+static
+say( fmt, arg1, arg2 )
+ char *fmt;
+ int arg1, arg2;
+{
+ if ( !quiet ){
+ printf( fmt, arg1, arg2 );
+ fflush( stdout );
+ }
+}
+
+ /*****************************
+ * *
+ * LOW-LEVEL COMMUNICATION *
+ * *
+ *****************************/
+
+/* Read a single character from the remote end. */
+
+static int
+readchar()
+{
+ /* FIXME: Do we really want to be reading without a timeout? */
+ return SERIAL_READCHAR (nindy_serial, -1);
+}
+
+/******************************************************************************
+ * getpkt:
+ * Read a packet from a remote NINDY, with error checking, and return
+ * it in the indicated buffer.
+ ******************************************************************************/
+static
+getpkt (buf)
+ char *buf;
+{
+ unsigned char recv; /* Checksum received */
+ unsigned char csum; /* Checksum calculated */
+ char *bp; /* Poointer into the buffer */
+ int c;
+
+ while (1){
+ csum = 0;
+ bp = buf;
+ /* FIXME: check for error from readchar (). */
+ while ( (c = readchar()) != '#' ){
+ *bp++ = c;
+ csum += c;
+ }
+ *bp = 0;
+
+ /* FIXME: check for error from readchar (). */
+ recv = fromhex(readchar()) << 4;
+ recv |= fromhex(readchar());
+ if ( csum == recv ){
+ break;
+ }
+
+ fprintf(stderr,
+ "Bad checksum (recv=0x%02x; calc=0x%02x); retrying\r\n",
+ recv, csum );
+ SERIAL_WRITE (nindy_serial, "-", 1);
+ }
+
+ SERIAL_WRITE (nindy_serial, "+", 1);
+}
+
+
+/******************************************************************************
+ * putpkt:
+ * Checksum and send a gdb command to a remote NINDY, and wait for
+ * positive acknowledgement.
+ *
+ ******************************************************************************/
+static
+putpkt( cmd )
+ char *cmd; /* Command to be sent, without lead ^P (\020)
+ * or trailing checksum
+ */
+{
+ char ack; /* Response received from NINDY */
+ char checksum[4];
+ char *p;
+ unsigned int s;
+ char resend;
+
+ for ( s='\020', p=cmd; *p; p++ ){
+ s += *p;
+ }
+ sprintf( checksum, "#%02x", s & 0xff );
+
+ /* Send checksummed message over and over until we get a positive ack
+ */
+ resend = 1;
+ do {
+ if ( resend ) {
+ SERIAL_WRITE ( nindy_serial, "\020", 1 );
+ SERIAL_WRITE( nindy_serial, cmd, strlen(cmd) );
+ SERIAL_WRITE( nindy_serial, checksum, strlen(checksum) );
+ }
+ /* FIXME: do we really want to be reading without timeout? */
+ ack = SERIAL_READCHAR (nindy_serial, -1);
+ if (ack < 0)
+ {
+ fprintf (stderr, "error reading from serial port\n");
+ }
+ if ( ack == '-' ){
+ fprintf( stderr, "Remote NAK, resending\r\n" );
+ resend = 1;
+ } else if ( ack != '+' ){
+ fprintf( stderr, "Bad ACK, ignored: <%c>\r\n", ack );
+ resend = 0;
+ }
+ } while ( ack != '+' );
+}
+
+
+
+/******************************************************************************
+ * send:
+ * Send a message to a remote NINDY and return the reply in the same
+ * buffer (clobbers the input message). Check for error responses
+ * as indicated by the second argument.
+ *
+ ******************************************************************************/
+static
+send( buf, ack_required )
+ char *buf; /* Message to be sent to NINDY; replaced by
+ * NINDY's response.
+ */
+ int ack_required; /* 1 means NINDY's response MUST be either "X00" (no
+ * error) or an error code "Xnn".
+ * 0 means the it's OK as long as it doesn't
+ * begin with "Xnn".
+ */
+{
+ int errnum;
+ static char *errmsg[] = {
+ "", /* X00 */
+ "Buffer overflow", /* X01 */
+ "Unknown command", /* X02 */
+ "Wrong amount of data to load register(s)", /* X03 */
+ "Missing command argument(s)", /* X04 */
+ "Odd number of digits sent to load memory", /* X05 */
+ "Unknown register name", /* X06 */
+ "No such memory segment", /* X07 */
+ "No breakpoint available", /* X08 */
+ "Can't set requested baud rate", /* X09 */
+ };
+# define NUMERRS ( sizeof(errmsg) / sizeof(errmsg[0]) )
+
+ static char err0[] = "NINDY failed to acknowledge command: <%s>\r\n";
+ static char err1[] = "Unknown error response from NINDY: <%s>\r\n";
+ static char err2[] = "Error response %s from NINDY: %s\r\n";
+
+ putpkt (buf);
+ getpkt (buf);
+
+ if ( buf[0] != 'X' ){
+ if ( ack_required ){
+ fprintf( stderr, err0, buf );
+ abort();
+ }
+
+ } else if ( strcmp(buf,"X00") ){
+ sscanf( &buf[1], "%x", &errnum );
+ if ( errnum > NUMERRS ){
+ fprintf( stderr, err1, buf );
+ } else{
+ fprintf( stderr, err2, buf, errmsg[errnum] );
+ }
+ abort();
+ }
+}
+
+ /**********************************
+ * *
+ * NINDY INTERFACE ROUTINES *
+ * *
+ * ninConnect *MUST* be the first *
+ * one of these routines called. *
+ **********************************/
+
+/******************************************************************************
+ * ninBptDel:
+ * Ask NINDY to delete the specified type of *hardware* breakpoint at
+ * the specified address. If the 'addr' is -1, all breakpoints of
+ * the specified type are deleted.
+ ******************************************************************************/
+OninBptDel( addr, data )
+ long addr; /* Address in 960 memory */
+ int data; /* '1' => data bkpt, '0' => instruction breakpoint */
+{
+ char buf[100];
+
+ if ( addr == -1 ){
+ sprintf( buf, "b%c", data ? '1' : '0' );
+ } else {
+ sprintf( buf, "b%c%x", data ? '1' : '0', addr );
+ }
+ return send( buf, 0 );
+}
+
+
+/******************************************************************************
+ * ninBptSet:
+ * Ask NINDY to set the specified type of *hardware* breakpoint at
+ * the specified address.
+ ******************************************************************************/
+OninBptSet( addr, data )
+ long addr; /* Address in 960 memory */
+ int data; /* '1' => data bkpt, '0' => instruction breakpoint */
+{
+ char buf[100];
+
+ sprintf( buf, "B%c%x", data ? '1' : '0', addr );
+ return send( buf, 0 );
+}
+
+/******************************************************************************
+ * ninGdbExit:
+ * Ask NINDY to leave GDB mode and print a NINDY prompt.
+ * Since it'll no longer be in GDB mode, don't wait for a response.
+ ******************************************************************************/
+OninGdbExit()
+{
+ putpkt( "E" );
+}
+
+/******************************************************************************
+ * ninGo:
+ * Ask NINDY to start or continue execution of an application program
+ * in it's memory at the current ip.
+ ******************************************************************************/
+OninGo( step_flag )
+ int step_flag; /* 1 => run in single-step mode */
+{
+ putpkt( step_flag ? "s" : "c" );
+}
+
+
+/******************************************************************************
+ * ninMemGet:
+ * Read a string of bytes from NINDY's address space (960 memory).
+ ******************************************************************************/
+OninMemGet(ninaddr, hostaddr, len)
+ long ninaddr; /* Source address, in the 960 memory space */
+ char *hostaddr; /* Destination address, in our memory space */
+ int len; /* Number of bytes to read */
+{
+ /* How much do we send at a time? */
+#define OLD_NINDY_MEMBYTES 1024
+ /* Buffer: hex in, binary out */
+ char buf[2*OLD_NINDY_MEMBYTES+20];
+
+ int cnt; /* Number of bytes in next transfer */
+
+ for ( ; len > 0; len -= OLD_NINDY_MEMBYTES ){
+ cnt = len > OLD_NINDY_MEMBYTES ? OLD_NINDY_MEMBYTES : len;
+
+ sprintf( buf, "m%x,%x", ninaddr, cnt );
+ send( buf, 0 );
+ hexbin( cnt, buf, hostaddr );
+
+ ninaddr += cnt;
+ hostaddr += cnt;
+ }
+}
+
+
+/******************************************************************************
+ * ninMemPut:
+ * Write a string of bytes into NINDY's address space (960 memory).
+ ******************************************************************************/
+OninMemPut( destaddr, srcaddr, len )
+ long destaddr; /* Destination address, in NINDY memory space */
+ char *srcaddr; /* Source address, in our memory space */
+ int len; /* Number of bytes to write */
+{
+ char buf[2*OLD_NINDY_MEMBYTES+20]; /* Buffer: binary in, hex out */
+ char *p; /* Pointer into buffer */
+ int cnt; /* Number of bytes in next transfer */
+
+ for ( ; len > 0; len -= OLD_NINDY_MEMBYTES ){
+ cnt = len > OLD_NINDY_MEMBYTES ? OLD_NINDY_MEMBYTES : len;
+
+ sprintf( buf, "M%x,", destaddr );
+ p = buf + strlen(buf);
+ binhex( cnt, srcaddr, p );
+ *(p+(2*cnt)) = '\0';
+ send( buf, 1 );
+
+ srcaddr += cnt;
+ destaddr += cnt;
+ }
+}
+
+/******************************************************************************
+ * ninRegGet:
+ * Retrieve the contents of a 960 register, and return them as a long
+ * in host byte order.
+ *
+ * THIS ROUTINE CAN ONLY BE USED TO READ THE LOCAL, GLOBAL, AND
+ * ip/ac/pc/tc REGISTERS.
+ *
+ ******************************************************************************/
+long
+OninRegGet( regname )
+ char *regname; /* Register name recognized by NINDY, subject to the
+ * above limitations.
+ */
+{
+ char buf[200];
+ long val;
+
+ sprintf( buf, "u%s", regname );
+ send( buf, 0 );
+ hexbin( 4, buf, (char *)&val );
+ return byte_order(val);
+}
+
+/******************************************************************************
+ * ninRegPut:
+ * Set the contents of a 960 register.
+ *
+ * THIS ROUTINE CAN ONLY BE USED TO SET THE LOCAL, GLOBAL, AND
+ * ip/ac/pc/tc REGISTERS.
+ *
+ ******************************************************************************/
+OninRegPut( regname, val )
+ char *regname; /* Register name recognized by NINDY, subject to the
+ * above limitations.
+ */
+ long val; /* New contents of register, in host byte-order */
+{
+ char buf[200];
+
+ sprintf( buf, "U%s,%08x", regname, byte_order(val) );
+ send( buf, 1 );
+}
+
+/******************************************************************************
+ * ninRegsGet:
+ * Get a dump of the contents of the entire 960 register set. The
+ * individual registers appear in the dump in the following order:
+ *
+ * pfp sp rip r3 r4 r5 r6 r7
+ * r8 r9 r10 r11 r12 r13 r14 r15
+ * g0 g1 g2 g3 g4 g5 g6 g7
+ * g8 g9 g10 g11 g12 g13 g14 fp
+ * pc ac ip tc fp0 fp1 fp2 fp3
+ *
+ * Each individual register comprises exactly 4 bytes, except for
+ * fp0-fp3, which are 8 bytes.
+ *
+ * WARNING:
+ * Each register value is in 960 (little-endian) byte order.
+ *
+ ******************************************************************************/
+OninRegsGet( regp )
+ char *regp; /* Where to place the register dump */
+{
+ char buf[(2*OLD_NINDY_REGISTER_BYTES)+10]; /* Registers in ASCII hex */
+
+ strcpy( buf, "r" );
+ send( buf, 0 );
+ hexbin( OLD_NINDY_REGISTER_BYTES, buf, regp );
+}
+
+/******************************************************************************
+ * ninRegsPut:
+ * Initialize the entire 960 register set to a specified set of values.
+ * The format of the register value data should be the same as that
+ * returned by ninRegsGet.
+ *
+ * WARNING:
+ * Each register value should be in 960 (little-endian) byte order.
+ *
+ ******************************************************************************/
+OninRegsPut( regp )
+ char *regp; /* Pointer to desired values of registers */
+{
+ char buf[(2*OLD_NINDY_REGISTER_BYTES)+10]; /* Registers in ASCII hex */
+
+ buf[0] = 'R';
+ binhex( OLD_NINDY_REGISTER_BYTES, regp, buf+1 );
+ buf[ (2*OLD_NINDY_REGISTER_BYTES)+1 ] = '\0';
+
+ send( buf, 1 );
+}
+
+
+/******************************************************************************
+ * ninReset:
+ * Ask NINDY to perform a soft reset; wait for the reset to complete.
+ ******************************************************************************/
+OninReset()
+{
+
+ putpkt( "X" );
+ /* FIXME: check for error from readchar (). */
+ while ( readchar() != '+' ){
+ ;
+ }
+}
+
+
+/******************************************************************************
+ * ninSrq:
+ * Assume NINDY has stopped execution of the 960 application program in
+ * order to process a host service request (srq). Ask NINDY for the
+ * srq arguments, perform the requested service, and send an "srq
+ * complete" message so NINDY will return control to the application.
+ *
+ ******************************************************************************/
+OninSrq()
+{
+ /* FIXME: Imposes arbitrary limits on lengths of pathnames and such. */
+ char buf[BUFSIZE];
+ int retcode;
+ unsigned char srqnum;
+ char *p;
+ char *argp;
+ int nargs;
+ int arg[MAX_SRQ_ARGS];
+
+
+ /* Get srq number and arguments
+ */
+ strcpy( buf, "!" );
+ send( buf, 0 );
+ hexbin( 1, buf, (char *)&srqnum );
+
+ /* Set up array of pointers the each of the individual
+ * comma-separated args
+ */
+ nargs=0;
+ argp = p = buf+2;
+ while ( 1 ){
+ while ( *p != ',' && *p != '\0' ){
+ p++;
+ }
+ sscanf( argp, "%x", &arg[nargs++] );
+ if ( *p == '\0' || nargs == MAX_SRQ_ARGS ){
+ break;
+ }
+ argp = ++p;
+ }
+
+ /* Process Srq
+ */
+ switch( srqnum ){
+ case BS_CLOSE:
+ /* args: file descriptor */
+ if ( arg[0] > 2 ){
+ retcode = close( arg[0] );
+ } else {
+ retcode = 0;
+ }
+ break;
+ case BS_CREAT:
+ /* args: filename, mode */
+ OninStrGet( arg[0], buf );
+ retcode = creat(buf,arg[1]);
+ break;
+ case BS_OPEN:
+ /* args: filename, flags, mode */
+ OninStrGet( arg[0], buf );
+ retcode = open(buf,arg[1],arg[2]);
+ break;
+ case BS_READ:
+ /* args: file descriptor, buffer, count */
+ retcode = read(arg[0],buf,arg[2]);
+ if ( retcode > 0 ){
+ OninMemPut( arg[1], buf, retcode );
+ }
+ break;
+ case BS_SEEK:
+ /* args: file descriptor, offset, whence */
+ retcode = lseek(arg[0],arg[1],arg[2]);
+ break;
+ case BS_WRITE:
+ /* args: file descriptor, buffer, count */
+ OninMemGet( arg[1], buf, arg[2] );
+ retcode = write(arg[0],buf,arg[2]);
+ break;
+ default:
+ retcode = -1;
+ break;
+ }
+
+ /* Tell NINDY to continue
+ */
+ sprintf( buf, "e%x", retcode );
+ send( buf, 1 );
+}
+
+
+/******************************************************************************
+ * ninStopWhy:
+ * Assume the application program has stopped (i.e., a DLE was received
+ * from NINDY). Ask NINDY for status information describing the
+ * reason for the halt.
+ *
+ * Returns a non-zero value if the user program has exited, 0 otherwise.
+ * Also returns the following information, through passed pointers:
+ * - why: an exit code if program the exited; otherwise the reason
+ * why the program halted (see stop.h for values).
+ * - contents of register ip (little-endian byte order)
+ * - contents of register sp (little-endian byte order)
+ * - contents of register fp (little-endian byte order)
+ ******************************************************************************/
+char
+OninStopWhy( whyp, ipp, fpp, spp )
+ char *whyp; /* Return the 'why' code through this pointer */
+ char *ipp; /* Return contents of register ip through this pointer */
+ char *fpp; /* Return contents of register fp through this pointer */
+ char *spp; /* Return contents of register sp through this pointer */
+{
+ char buf[30];
+ char stop_exit;
+
+ strcpy( buf, "?" );
+ send( buf, 0 );
+ hexbin( 1, buf, &stop_exit );
+ hexbin( 1, buf+2, whyp );
+ hexbin( 4, buf+4, ipp );
+ hexbin( 4, buf+12, fpp );
+ hexbin( 4, buf+20, spp );
+ return stop_exit;
+}
+
+/******************************************************************************
+ * ninStrGet:
+ * Read a '\0'-terminated string of data out of the 960 memory space.
+ *
+ ******************************************************************************/
+static
+OninStrGet( ninaddr, hostaddr )
+ unsigned long ninaddr; /* Address of string in NINDY memory space */
+ char *hostaddr; /* Address of the buffer to which string should
+ * be copied.
+ */
+{
+ /* FIXME: seems to be an arbitrary limit on the length of the string. */
+ char buf[BUFSIZE]; /* String as 2 ASCII hex digits per byte */
+ int numchars; /* Length of string in bytes. */
+
+ sprintf( buf, "\"%x", ninaddr );
+ send( buf, 0 );
+ numchars = strlen(buf)/2;
+ hexbin( numchars, buf, hostaddr );
+ hostaddr[numchars] = '\0';
+}
+
+#if 0
+/* never used. */
+
+/******************************************************************************
+ * ninVersion:
+ * Ask NINDY for version information about itself.
+ * The information is sent as an ascii string in the form "x.xx,<arch>",
+ * where,
+ * x.xx is the version number
+ * <arch> is the processor architecture: "KA", "KB", "MC", "CA" *
+ *
+ ******************************************************************************/
+int
+OninVersion( p )
+ char *p; /* Where to place version string */
+{
+ /* FIXME: this is an arbitrary limit on the length of version string. */
+ char buf[BUFSIZE];
+
+ strcpy( buf, "v" );
+ send( buf, 0 );
+ strcpy( p, buf );
+ return strlen( buf );
+}
+#endif
diff --git a/gdb/nindy-share/README b/gdb/nindy-share/README
new file mode 100644
index 00000000000..3f217ad9527
--- /dev/null
+++ b/gdb/nindy-share/README
@@ -0,0 +1,3 @@
+The files in this directory started out life as code shared between
+the nindy monitor and GDB. For various reasons, this is no longer
+true. Eventually, they probably should be merged into remote-nindy.c.
diff --git a/gdb/nindy-share/VERSION b/gdb/nindy-share/VERSION
new file mode 100644
index 00000000000..5625e59da88
--- /dev/null
+++ b/gdb/nindy-share/VERSION
@@ -0,0 +1 @@
+1.2
diff --git a/gdb/nindy-share/b.out.h b/gdb/nindy-share/b.out.h
new file mode 100644
index 00000000000..a82c261a7fd
--- /dev/null
+++ b/gdb/nindy-share/b.out.h
@@ -0,0 +1,158 @@
+/* Copyright 1992 Free Software Foundation, Inc.
+ *
+ * This file is a modified version of 'a.out.h'. It is to be used in all
+ * all GNU tools modified to support the i80960 (or tools that operate on
+ * object files created by such tools).
+ *
+ * All i80960 development is done in a CROSS-DEVELOPMENT environment. I.e.,
+ * object code is generated on, and executed under the direction of a symbolic
+ * debugger running on, a host system. We do not want to be subject to the
+ * vagaries of which host it is or whether it supports COFF or a.out format,
+ * or anything else. We DO want to:
+ *
+ * o always generate the same format object files, regardless of host.
+ *
+ * o have an 'a.out' header that we can modify for our own purposes
+ * (the 80960 is typically an embedded processor and may require
+ * enhanced linker support that the normal a.out.h header can't
+ * accommodate).
+ *
+ * As for byte-ordering, the following rules apply:
+ *
+ * o Text and data that is actually downloaded to the target is always
+ * in i80960 (little-endian) order.
+ *
+ * o All other numbers (in the header, symbols, relocation directives)
+ * are in host byte-order: object files CANNOT be lifted from a
+ * little-end host and used on a big-endian (or vice versa) without
+ * modification.
+ *
+ * o The downloader ('comm960') takes care to generate a pseudo-header
+ * with correct (i80960) byte-ordering before shipping text and data
+ * off to the NINDY monitor in the target systems. Symbols and
+ * relocation info are never sent to the target.
+ */
+
+
+#define BMAGIC 0415
+/* We don't accept the following (see N_BADMAG macro).
+ * They're just here so GNU code will compile.
+ */
+#define OMAGIC 0407 /* old impure format */
+#define NMAGIC 0410 /* read-only text */
+#define ZMAGIC 0413 /* demand load format */
+
+/* FILE HEADER
+ * 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 exec {
+ /* Standard stuff */
+ unsigned long a_magic; /* Identifies this as a b.out file */
+ unsigned long a_text; /* Length of text */
+ unsigned long a_data; /* Length of data */
+ unsigned long a_bss; /* Length of runtime uninitialized data area */
+ unsigned long a_syms; /* Length of symbol table */
+ unsigned long a_entry; /* Runtime start address */
+ unsigned long a_trsize; /* Length of text relocation info */
+ unsigned long a_drsize; /* Length of data relocation info */
+
+ /* Added for i960 */
+ unsigned long a_tload; /* Text runtime load address */
+ unsigned long 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 */
+ unsigned char unused; /* (Just to make struct size a multiple of 4) */
+};
+
+#define N_BADMAG(x) (((x).a_magic)!=BMAGIC)
+#define N_TXTOFF(x) ( sizeof(struct exec) )
+#define N_DATOFF(x) ( N_TXTOFF(x) + (x).a_text )
+#define N_TROFF(x) ( N_DATOFF(x) + (x).a_data )
+#define N_DROFF(x) ( N_TROFF(x) + (x).a_trsize )
+#define N_SYMOFF(x) ( N_DROFF(x) + (x).a_drsize )
+#define N_STROFF(x) ( N_SYMOFF(x) + (x).a_syms )
+
+/* A single entry in the symbol table
+ */
+struct nlist {
+ union {
+ char *n_name;
+ struct nlist *n_next;
+ long n_strx; /* Index into string table */
+ } n_un;
+ unsigned char n_type; /* See below */
+ char n_other; /* Used in i80960 support -- see below */
+ short n_desc;
+ unsigned long n_value;
+};
+
+
+/* Legal values of n_type
+ */
+#define N_UNDF 0 /* Undefined symbol */
+#define N_ABS 2 /* Absolute symbol */
+#define N_TEXT 4 /* Text symbol */
+#define N_DATA 6 /* Data symbol */
+#define N_BSS 8 /* BSS symbol */
+#define N_FN 31 /* Filename symbol */
+
+#define N_EXT 1 /* External symbol (OR'd in with one of above) */
+#define N_TYPE 036 /* Mask for all the type bits */
+#define N_STAB 0340 /* Mask for all bits used for SDB entries */
+
+/* MEANING OF 'n_other'
+ *
+ * If non-zero, the 'n_other' fields indicates either a leaf procedure or
+ * a system procedure, as follows:
+ *
+ * 1 <= n_other <= 32 :
+ * The symbol is the entry point to a system procedure.
+ * 'n_value' is the address of the entry, as for any other
+ * procedure. The system procedure number (which can be used in
+ * a 'calls' instruction) is (n_other-1). These entries come from
+ * '.sysproc' directives.
+ *
+ * n_other == N_CALLNAME
+ * the symbol is the 'call' entry point to a leaf procedure.
+ * The *next* symbol in the symbol table must be the corresponding
+ * 'bal' entry point to the procedure (see following). These
+ * entries come from '.leafproc' directives in which two different
+ * symbols are specified (the first one is represented here).
+ *
+ *
+ * n_other == N_BALNAME
+ * the symbol is the 'bal' entry point to a leaf procedure.
+ * These entries result from '.leafproc' directives in which only
+ * one symbol is specified, or in which the same symbol is
+ * specified twice.
+ *
+ * Note that an N_CALLNAME entry *must* have a corresponding N_BALNAME entry,
+ * but not every N_BALNAME entry must have an N_CALLNAME entry.
+ */
+#define N_CALLNAME -1
+#define N_BALNAME -2
+
+
+struct relocation_info {
+ int r_address; /* File address of item to be relocated */
+ unsigned
+ r_symbolnum:24,/* Index of symbol on which relocation is based*/
+ r_pcrel:1, /* 1 => relocate PC-relative; else absolute
+ * On i960, pc-relative implies 24-bit
+ * address, absolute implies 32-bit.
+ */
+ r_length:2, /* Number of bytes to relocate:
+ * 0 => 1 byte
+ * 1 => 2 bytes
+ * 2 => 4 bytes -- only value used for i960
+ */
+ r_extern:1,
+ r_bsr:1, /* Something for the GNU NS32K assembler */
+ r_disp:1, /* Something for the GNU NS32K assembler */
+ r_callj:1, /* 1 if relocation target is an i960 'callj' */
+ nuthin:1; /* Unused */
+};
diff --git a/gdb/nindy-share/block_io.h b/gdb/nindy-share/block_io.h
new file mode 100644
index 00000000000..6521cdb9b05
--- /dev/null
+++ b/gdb/nindy-share/block_io.h
@@ -0,0 +1,68 @@
+/******************************************************************
+ Copyright 1990, 1992 Free Software Foundation, Inc.
+
+ This code was donated by Intel Corp.
+
+ Intel hereby grants you permission to copy, modify, and
+ distribute this software and its documentation. Intel grants
+ this permission provided that the above copyright notice
+ appears in all copies and that both the copyright notice and
+ this permission notice appear in supporting documentation. In
+ addition, Intel grants this permission provided that you
+ prominently mark as not part of the original any modifications
+ made to this software or documentation, and that the name of
+ Intel Corporation not be used in advertising or publicity
+ pertaining to distribution of the software or the documentation
+ without specific, written prior permission.
+
+ Intel Corporation does not warrant, guarantee or make any
+ representations regarding the use of, or the results of the use
+ of, the software and documentation in terms of correctness,
+ accuracy, reliability, currentness, or otherwise; and you rely
+ on the software, documentation and results solely at your own
+ risk. */
+/******************************************************************/
+
+/*****************************************************************************
+ * Structures and definitions supporting NINDY requests for services by a
+ * remote host. Used by NINDY monitor, library libnin, comm960, gdb960,
+ * etc. Also contains some defines for NINDY console I/O requests.
+ *****************************************************************************/
+
+/* the following four are hardware dependent */
+#define BIT_16 short
+#define BIT_32 int
+#define UBIT_16 unsigned short
+#define UBIT_32 unsigned int
+
+/* Service request numbers -- these are the services that can be asked of the
+ * host.
+ */
+#define BS_ACCESS 0x10
+#define BS_CLOSE 0x20
+#define BS_CREAT 0x30
+#define BS_SEEK 0x40
+#define BS_OPEN 0x50
+#define BS_READ 0x60
+#define BS_STAT 0x70
+#define BS_SYSTEMD 0x80
+#define BS_TIME 0x90
+#define BS_UNMASK 0xa0
+#define BS_UNLINK 0xb0
+#define BS_WRITE 0xc0
+
+
+/* Maximum number of arguments to any of the above service requests
+ * (in addition to the request number).
+ */
+#define MAX_SRQ_ARGS 3
+
+/* Number of bytes of data that can be read or written by a single I/O request
+ */
+#define BUFSIZE 1024
+
+/* NINDY console I/O requests: CO sends a single character to stdout,
+ * CI reads one.
+ */
+#define CI 0
+#define CO 1
diff --git a/gdb/nindy-share/coff.h b/gdb/nindy-share/coff.h
new file mode 100644
index 00000000000..b169b71ec53
--- /dev/null
+++ b/gdb/nindy-share/coff.h
@@ -0,0 +1,336 @@
+/* Copyright 1990, 1992 Free Software Foundation, Inc.
+ *
+ * This code was donated by Intel Corp.
+ *
+ * This is a coff version of a.out.h to support 80960 debugging from
+ * a Unix (possibly BSD) host. It's used by:
+ * o gdb960 to symbols in code generated with Intel (non-GNU) tools.
+ * o comm960 to convert a b.out file to a coff file for download.
+ */
+
+
+/********************** FILE HEADER **********************/
+
+struct filehdr {
+ unsigned short f_magic; /* magic number */
+ unsigned short f_nscns; /* number of sections */
+ long f_timdat; /* time & date stamp */
+ long f_symptr; /* file pointer to symtab */
+ long f_nsyms; /* number of symtab entries */
+ unsigned short f_opthdr; /* sizeof(optional hdr) */
+ unsigned short f_flags; /* flags */
+};
+
+
+/* Bits for f_flags:
+ * F_RELFLG relocation info stripped from file
+ * F_EXEC file is executable (no unresolved externel references)
+ * F_LNNO line nunbers stripped from file
+ * F_LSYMS local symbols stripped from file
+ * F_AR32WR file has byte ordering of an AR32WR machine (e.g. vax)
+ */
+#define F_RELFLG 0000001
+#define F_EXEC 0000002
+#define F_LNNO 0000004
+#define F_LSYMS 0000010
+#define F_AR32WR 0000400
+
+
+/*
+ * Intel 80960 (I960) processor flags.
+ * F_I960TYPE == mask for processor type field.
+ */
+#define F_I960TYPE 0170000
+#define F_I960CA 0010000
+#define F_I960FLOAT 0020000
+#define F_I960BA 0030000
+#define F_I960XA 0040000
+
+/*
+ * i80960 Magic Numbers
+ */
+#define I960ROMAGIC 0540 /* read-only text segments */
+#define I960RWMAGIC 0541 /* read-write text segments */
+
+#define I960BADMAG(x) (((x).f_magic!=I960ROMAGIC) && ((x).f_magic!=I960RWMAGIC))
+
+#define FILHDR struct filehdr
+#define FILHSZ sizeof(FILHDR)
+
+
+/********************** AOUT "OPTIONAL HEADER" **********************/
+
+typedef struct {
+ unsigned long phys_addr;
+ unsigned long bitarray;
+} TAGBITS;
+
+typedef struct aouthdr {
+ short magic; /* type of file */
+ short vstamp; /* version stamp */
+ unsigned long tsize; /* text size in bytes, padded to FW bdry*/
+ unsigned long dsize; /* initialized data " " */
+ unsigned long bsize; /* uninitialized data " " */
+#if U3B
+ unsigned long dum1;
+ unsigned long dum2; /* pad to entry point */
+#endif
+ unsigned long entry; /* entry pt. */
+ unsigned long text_start; /* base of text used for this file */
+ unsigned long data_start; /* base of data used for this file */
+ unsigned long tagentries; /* number of tag entries to follow */
+} AOUTHDR;
+
+/* return a pointer to the tag bits array */
+
+#define TAGPTR(aout) ((TAGBITS *) (&(aout.tagentries)+1))
+
+/* compute size of a header */
+
+#define AOUTSZ(aout) (sizeof(AOUTHDR)+(aout.tagentries*sizeof(TAGBITS)))
+
+/********************** STORAGE CLASSES **********************/
+
+#define C_EFCN -1 /* physical end of function */
+#define C_NULL 0
+#define C_AUTO 1 /* automatic variable */
+#define C_EXT 2 /* external symbol */
+#define C_STAT 3 /* static */
+#define C_REG 4 /* register variable */
+#define C_EXTDEF 5 /* external definition */
+#define C_LABEL 6 /* label */
+#define C_ULABEL 7 /* undefined label */
+#define C_MOS 8 /* member of structure */
+#define C_ARG 9 /* function argument */
+#define C_STRTAG 10 /* structure tag */
+#define C_MOU 11 /* member of union */
+#define C_UNTAG 12 /* union tag */
+#define C_TPDEF 13 /* type definition */
+#define C_USTATIC 14 /* undefined static */
+#define C_ENTAG 15 /* enumeration tag */
+#define C_MOE 16 /* member of enumeration */
+#define C_REGPARM 17 /* register parameter */
+#define C_FIELD 18 /* bit field */
+#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 */
+
+#define C_SCALL 107 /* Procedure reachable via system call */
+#define C_LEAFPROC 108 /* Leaf procedure, "call" via BAL */
+
+
+/********************** SECTION HEADER **********************/
+
+struct scnhdr {
+ char s_name[8]; /* section name */
+ long s_paddr; /* physical address, aliased s_nlib */
+ long s_vaddr; /* virtual address */
+ long s_size; /* section size */
+ long s_scnptr; /* file ptr to raw data for section */
+ long s_relptr; /* file ptr to relocation */
+ long s_lnnoptr; /* file ptr to line numbers */
+ unsigned short s_nreloc; /* number of relocation entries */
+ unsigned short s_nlnno; /* number of line number entries*/
+ long s_flags; /* flags */
+ unsigned long s_align; /* section alignment */
+};
+
+/*
+ * names of "special" sections
+ */
+#define _TEXT ".text"
+#define _DATA ".data"
+#define _BSS ".bss"
+
+/*
+ * s_flags "type"
+ */
+#define STYP_TEXT 0x20 /* section contains text only */
+#define STYP_DATA 0x40 /* section contains data only */
+#define STYP_BSS 0x80 /* section contains bss only */
+
+#define SCNHDR struct scnhdr
+#define SCNHSZ sizeof(SCNHDR)
+
+
+/********************** LINE NUMBERS **********************/
+
+/* 1 line number entry for every "breakpointable" source line in a section.
+ * Line numbers are grouped on a per function basis; first entry in a function
+ * grouping will have l_lnno = 0 and in place of physical address will be the
+ * symbol table index of the function name.
+ */
+struct lineno{
+ union {
+ long l_symndx; /* function name symbol index, iff l_lnno == 0*/
+ long l_paddr; /* (physical) address of line number */
+ } l_addr;
+ unsigned short l_lnno; /* line number */
+ char padding[2]; /* force alignment */
+};
+
+#define LINENO struct lineno
+#define LINESZ sizeof(LINENO)
+
+
+/********************** SYMBOLS **********************/
+
+#define SYMNMLEN 8 /* # characters in a symbol name */
+#define FILNMLEN 14 /* # characters in a file name */
+#define DIMNUM 4 /* # array dimensions in auxiliary entry */
+
+
+struct syment {
+ union {
+ char _n_name[SYMNMLEN]; /* old COFF version */
+ struct {
+ long _n_zeroes; /* new == 0 */
+ long _n_offset; /* offset into string table */
+ } _n_n;
+ char *_n_nptr[2]; /* allows for overlaying */
+ } _n;
+ long n_value; /* value of symbol */
+ short n_scnum; /* section number */
+ char pad1[2]; /* force alignment */
+ unsigned long n_type; /* type and derived type */
+ char n_sclass; /* storage class */
+ char n_numaux; /* number of aux. entries */
+ char pad2[2]; /* force alignment */
+};
+
+#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 0 /* undefined symbol */
+#define N_ABS -1 /* value of symbol is absolute */
+#define N_DEBUG -2 /* debugging symbol -- symbol value is meaningless */
+
+/*
+ * Type of a symbol, in low 4 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
+ */
+#define DT_PTR 1 /* pointer */
+#define DT_FCN 2 /* function */
+#define DT_ARY 3 /* array */
+
+#define N_BTMASK 037
+#define N_TMASK 0140
+#define N_BTSHFT 5
+#define N_TSHIFT 2
+
+#define BTYPE(x) ((x) & N_BTMASK)
+
+
+#define ISPTR(x) (((x) & N_TMASK) == (DT_PTR << N_BTSHFT))
+#define ISFCN(x) (((x) & N_TMASK) == (DT_FCN << N_BTSHFT))
+#define ISARY(x) (((x) & N_TMASK) == (DT_ARY << N_BTSHFT))
+
+#define DECREF(x) ((((x)>>N_TSHIFT)&~N_BTMASK)|((x)&N_BTMASK))
+
+union auxent {
+ struct {
+ long x_tagndx; /* str, un, or enum tag indx */
+ union {
+ struct {
+ unsigned short x_lnno; /* declaration line number */
+ unsigned short x_size; /* str/union/array size */
+ } x_lnsz;
+ long x_fsize; /* size of function */
+ } x_misc;
+ union {
+ struct { /* if ISFCN, tag, or .bb */
+ long x_lnnoptr; /* ptr to fcn line # */
+ long x_endndx; /* entry ndx past block end */
+ } x_fcn;
+ struct { /* if ISARY, up to 4 dimen. */
+ unsigned short x_dimen[DIMNUM];
+ } x_ary;
+ } x_fcnary;
+ unsigned short x_tvndx; /* tv index */
+ } x_sym;
+
+ 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_stdindx;
+ } x_sc;
+
+ struct {
+ unsigned long x_balntry;
+ } x_bal;
+
+ char a[sizeof(struct syment)]; /* force auxent/syment sizes to match */
+};
+
+#define SYMENT struct syment
+#define SYMESZ sizeof(SYMENT)
+#define AUXENT union auxent
+#define AUXESZ sizeof(AUXENT)
+
+#if VAX || I960
+# define _ETEXT "_etext"
+#else
+# define _ETEXT "etext"
+#endif
+
+/********************** RELOCATION DIRECTIVES **********************/
+
+struct reloc {
+ long r_vaddr; /* Virtual address of reference */
+ long r_symndx; /* Index into symbol table */
+ unsigned short r_type; /* Relocation type */
+ char pad[2]; /* Unused */
+};
+
+/* Only values of r_type GNU/960 cares about */
+#define R_RELLONG 17 /* Direct 32-bit relocation */
+#define R_IPRMED 25 /* 24-bit ip-relative relocation */
+#define R_OPTCALL 27 /* 32-bit optimizable call (leafproc/sysproc) */
+
+
+#define RELOC struct reloc
+#define RELSZ sizeof(RELOC)
diff --git a/gdb/nindy-share/env.h b/gdb/nindy-share/env.h
new file mode 100644
index 00000000000..df1ceef24b0
--- /dev/null
+++ b/gdb/nindy-share/env.h
@@ -0,0 +1,12 @@
+/* Copyright 1990, 1992 Free Software Foundation, Inc.
+ *
+ * This code was donated by Intel Corp.
+ *
+ * GNU/960 tool runtime environment
+ */
+
+
+/* Base directory at which GNU/960 tools are assumed to be installed, if
+ * the environment variable G960BASE is not defined.
+ */
+#define DEFAULT_BASE "/usr/local/g960"
diff --git a/gdb/nindy-share/nindy.c b/gdb/nindy-share/nindy.c
new file mode 100644
index 00000000000..e275e49b404
--- /dev/null
+++ b/gdb/nindy-share/nindy.c
@@ -0,0 +1,1154 @@
+/* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* This started out life as code shared between the nindy monitor and
+ GDB. For various reasons, this is no longer true. Eventually, it
+ probably should be merged into remote-nindy.c. */
+
+/******************************************************************************
+ *
+ * NINDY INTERFACE ROUTINES
+ *
+ * The caller of these routines should be aware that:
+ *
+ * (1) ninConnect() should be called to open communications with the
+ * remote NINDY board before any of the other routines are invoked.
+ *
+ * (2) almost all interactions are driven by the host: nindy sends information
+ * in response to host commands.
+ *
+ * (3) the lone exception to (2) is the single character DLE (^P, 0x10).
+ * Receipt of a DLE from NINDY indicates that the application program
+ * running under NINDY has stopped execution and that NINDY is now
+ * available to talk to the host (all other communication received after
+ * the application has been started should be presumed to come from the
+ * application and should be passed on by the host to stdout).
+ *
+ * (4) the reason the application program stopped can be determined with the
+ * ninStopWhy() function. There are three classes of stop reasons:
+ *
+ * (a) the application has terminated execution.
+ * The host should take appropriate action.
+ *
+ * (b) the application had a fault or trace event.
+ * The host should take appropriate action.
+ *
+ * (c) the application wishes to make a service request (srq) of the host;
+ * e.g., to open/close a file, read/write a file, etc. The ninSrq()
+ * function should be called to determine the nature of the request
+ * and process it.
+ */
+
+#include <stdio.h>
+#include "defs.h"
+#include "serial.h"
+#ifdef ANSI_PROTOTYPES
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+
+#if !defined (HAVE_TERMIOS) && !defined (HAVE_TERMIO) && !defined (HAVE_SGTTY)
+#define HAVE_SGTTY
+#endif
+
+#ifdef HAVE_SGTTY
+#include <sys/ioctl.h>
+#endif
+
+#include <sys/types.h> /* Needed by file.h on Sys V */
+#include <sys/file.h>
+#include <signal.h>
+#include <sys/stat.h>
+
+#if 0
+#include "ttycntl.h"
+#endif
+#include "block_io.h"
+#include "wait.h"
+#include "env.h"
+
+#define DLE 0x10 /* ^P */
+#define XON 0x11 /* ^Q */
+#define XOFF 0x13 /* ^S */
+#define ESC 0x1b
+
+#define TIMEOUT -1
+
+int quiet = 0; /* 1 => stifle unnecessary messages */
+serial_t nindy_serial;
+
+static int old_nindy = 0; /* 1 => use old (hex) communication protocol */
+static ninStrGet();
+
+ /****************************
+ * *
+ * MISCELLANEOUS UTILTIES *
+ * *
+ ****************************/
+
+/******************************************************************************
+ * say:
+ * This is a printf that takes at most two arguments (in addition to the
+ * format string) and that outputs nothing if verbose output has been
+ * suppressed.
+ *****************************************************************************/
+
+/* VARARGS */
+static void
+#ifdef ANSI_PROTOTYPES
+say (char *fmt, ...)
+#else
+say (va_alist)
+ va_dcl
+#endif
+{
+ va_list args;
+#ifdef ANSI_PROTOTYPES
+ va_start(args, fmt);
+#else
+ char *fmt;
+
+ va_start (args);
+ fmt = va_arg (args, char *);
+#endif
+
+ if (!quiet)
+ {
+ vfprintf_unfiltered (gdb_stdout, fmt, args);
+ gdb_flush (gdb_stdout);
+ }
+ va_end (args);
+}
+
+/******************************************************************************
+ * exists:
+ * Creates a full pathname by concatenating up to three name components
+ * onto a specified base name; optionally looks up the base name as a
+ * runtime environment variable; and checks to see if the file or
+ * directory specified by the pathname actually exists.
+ *
+ * Returns: the full pathname if it exists, NULL otherwise.
+ * (returned pathname is in malloc'd memory and must be freed
+ * by caller).
+ *****************************************************************************/
+static char *
+exists( base, c1, c2, c3, env )
+ char *base; /* Base directory of path */
+ char *c1, *c2, *c3; /* Components (subdirectories and/or file name) to be
+ * appended onto the base directory name. One or
+ * more may be omitted by passing NULL pointers.
+ */
+ int env; /* If 1, '*base' is the name of an environment variable
+ * to be examined for the base directory name;
+ * otherwise, '*base' is the actual name of the
+ * base directory.
+ */
+{
+ struct stat buf;/* For call to 'stat' -- never examined */
+ char *path; /* Pointer to full pathname (malloc'd memory) */
+ int len; /* Length of full pathname (incl. terminator) */
+ extern char *getenv();
+
+
+ if ( env ){
+ base = getenv( base );
+ if ( base == NULL ){
+ return NULL;
+ }
+ }
+
+ len = strlen(base) + 4;
+ /* +4 for terminator and "/" before each component */
+ if ( c1 != NULL ){
+ len += strlen(c1);
+ }
+ if ( c2 != NULL ){
+ len += strlen(c2);
+ }
+ if ( c3 != NULL ){
+ len += strlen(c3);
+ }
+
+ path = xmalloc (len);
+
+ strcpy( path, base );
+ if ( c1 != NULL ){
+ strcat( path, "/" );
+ strcat( path, c1 );
+ if ( c2 != NULL ){
+ strcat( path, "/" );
+ strcat( path, c2 );
+ if ( c3 != NULL ){
+ strcat( path, "/" );
+ strcat( path, c3 );
+ }
+ }
+ }
+
+ if ( stat(path,&buf) != 0 ){
+ free( path );
+ path = NULL;
+ }
+ return path;
+}
+
+ /*****************************
+ * *
+ * LOW-LEVEL COMMUNICATION *
+ * *
+ *****************************/
+
+/* Read *exactly* N characters from the NINDY tty, and put them in
+ *BUF. Translate escape sequences into single characters, counting
+ each such sequence as 1 character.
+
+ An escape sequence consists of ESC and a following character. The
+ ESC is discarded and the other character gets bit 0x40 cleared --
+ thus ESC P == ^P, ESC S == ^S, ESC [ == ESC, etc.
+
+ Return 1 if successful, 0 if more than TIMEOUT seconds pass without
+ any input. */
+
+static int
+rdnin (buf,n,timeout)
+ unsigned char * buf; /* Where to place characters read */
+ int n; /* Number of characters to read */
+ int timeout; /* Timeout, in seconds */
+{
+ int escape_seen; /* 1 => last character of a read was an ESC */
+ int c;
+
+ escape_seen = 0;
+ while (n)
+ {
+ c = SERIAL_READCHAR (nindy_serial, timeout);
+ switch (c)
+ {
+ case SERIAL_ERROR:
+ case SERIAL_TIMEOUT:
+ case SERIAL_EOF:
+ return 0;
+
+ case ESC:
+ escape_seen = 1;
+ break;
+
+ default:
+ if (escape_seen)
+ {
+ escape_seen = 0;
+ c &= ~0x40;
+ }
+ *buf++ = c;
+ --n;
+ break;
+ }
+ }
+ return 1;
+}
+
+
+/******************************************************************************
+ * getpkt:
+ * Read a packet from a remote NINDY, with error checking, into the
+ * indicated buffer.
+ *
+ * Return packet status byte on success, TIMEOUT on failure.
+ ******************************************************************************/
+static
+int
+getpkt(buf)
+ unsigned char *buf;
+{
+ int i;
+ unsigned char hdr[3]; /* Packet header:
+ * hdr[0] = low byte of message length
+ * hdr[1] = high byte of message length
+ * hdr[2] = message status
+ */
+ int cnt; /* Message length (status byte + data) */
+ unsigned char cs_calc; /* Checksum calculated */
+ unsigned char cs_recv; /* Checksum received */
+ static char errfmt[] =
+ "Bad checksum (recv=0x%02x; calc=0x%02x); retrying\r\n";
+
+ while (1){
+ if ( !rdnin(hdr,3,5) ){
+ return TIMEOUT;
+ }
+ cnt = (hdr[1]<<8) + hdr[0] - 1;
+ /* -1 for status byte (already read) */
+
+ /* Caller's buffer may only be big enough for message body,
+ * without status byte and checksum, so make sure to read
+ * checksum into a separate buffer.
+ */
+ if ( !rdnin(buf,cnt,5) || !rdnin(&cs_recv,1,5) ){
+ return TIMEOUT;
+ }
+
+ /* Calculate checksum
+ */
+ cs_calc = hdr[0] + hdr[1] + hdr[2];
+ for ( i = 0; i < cnt; i++ ){
+ cs_calc += buf[i];
+ }
+ if ( cs_calc == cs_recv ){
+ SERIAL_WRITE (nindy_serial, "+", 1);
+ return hdr[2];
+ }
+
+ /* Bad checksum: report, send NAK, and re-receive
+ */
+ fprintf(stderr, errfmt, cs_recv, cs_calc );
+ SERIAL_WRITE (nindy_serial, "-", 1);
+ }
+}
+
+
+/******************************************************************************
+ * putpkt:
+ * Send a packet to NINDY, checksumming it and converting special
+ * characters to escape sequences.
+ ******************************************************************************/
+
+/* This macro puts the character 'c' into the buffer pointed at by 'p',
+ * and increments the pointer. If 'c' is one of the 4 special characters
+ * in the transmission protocol, it is converted into a 2-character
+ * escape sequence.
+ */
+#define PUTBUF(c,p) \
+ if ( c == DLE || c == ESC || c == XON || c == XOFF ){ \
+ *p++ = ESC; \
+ *p++ = c | 0x40; \
+ } else { \
+ *p++ = c; \
+ }
+
+static
+putpkt( msg, len )
+ unsigned char *msg; /* Command to be sent, without lead ^P (\020) or checksum */
+ int len; /* Number of bytes in message */
+{
+ static char *buf = NULL;/* Local buffer -- build packet here */
+ static int maxbuf = 0; /* Current length of buffer */
+ unsigned char ack; /* Response received from NINDY */
+ unsigned char checksum; /* Packet checksum */
+ char *p; /* Pointer into buffer */
+ int lenhi, lenlo; /* High and low bytes of message length */
+ int i;
+
+
+ /* Make sure local buffer is big enough. Must include space for
+ * packet length, message body, and checksum. And in the worst
+ * case, each character would expand into a 2-character escape
+ * sequence.
+ */
+ if ( maxbuf < ((2*len)+10) ){
+ if ( buf ){
+ free( buf );
+ }
+ buf = xmalloc( maxbuf=((2*len)+10) );
+ }
+
+ /* Attention, NINDY!
+ */
+ SERIAL_WRITE (nindy_serial, "\020", 1);
+
+
+ lenlo = len & 0xff;
+ lenhi = (len>>8) & 0xff;
+ checksum = lenlo + lenhi;
+ p = buf;
+
+ PUTBUF( lenlo, p );
+ PUTBUF( lenhi, p );
+
+ for ( i=0; i<len; i++ ){
+ PUTBUF( msg[i], p );
+ checksum += msg[i];
+ }
+
+ PUTBUF( checksum, p );
+
+ /* Send checksummed message over and over until we get a positive ack
+ */
+ SERIAL_WRITE (nindy_serial, buf, p - buf);
+ while (1){
+ if ( !rdnin(&ack,1,5) ){
+ /* timed out */
+ fprintf(stderr,"ACK timed out; resending\r\n");
+ /* Attention, NINDY! */
+ SERIAL_WRITE (nindy_serial, "\020", 1);
+ SERIAL_WRITE (nindy_serial, buf, p - buf);
+ } else if ( ack == '+' ){
+ return;
+ } else if ( ack == '-' ){
+ fprintf( stderr, "Remote NAK; resending\r\n" );
+ SERIAL_WRITE (nindy_serial, buf, p - buf);
+ } else {
+ fprintf( stderr, "Bad ACK, ignored: <%c>\r\n", ack );
+ }
+ }
+}
+
+
+
+/******************************************************************************
+ * send:
+ * Send a message to a remote NINDY. Check message status byte
+ * for error responses. If no error, return NINDY reponse (if any).
+ ******************************************************************************/
+static
+send( out, len, in )
+ unsigned char *out; /* Message to be sent to NINDY */
+ int len; /* Number of meaningful bytes in out buffer */
+ unsigned char *in; /* Where to put response received from NINDY */
+{
+ char *fmt;
+ int status;
+ static char *errmsg[] = {
+ "", /* 0 */
+ "Buffer overflow", /* 1 */
+ "Unknown command", /* 2 */
+ "Wrong amount of data to load register(s)", /* 3 */
+ "Missing command argument(s)", /* 4 */
+ "Odd number of digits sent to load memory", /* 5 */
+ "Unknown register name", /* 6 */
+ "No such memory segment", /* 7 */
+ "No breakpoint available", /* 8 */
+ "Can't set requested baud rate", /* 9 */
+ };
+# define NUMERRS ( sizeof(errmsg) / sizeof(errmsg[0]) )
+
+ static char err1[] = "Unknown error response from NINDY: #%d\r\n";
+ static char err2[] = "Error response #%d from NINDY: %s\r\n";
+
+ while (1){
+ putpkt(out,len);
+ status = getpkt(in);
+ if ( status == TIMEOUT ){
+ fprintf( stderr, "Response timed out; resending\r\n" );
+ } else {
+ break;
+ }
+ }
+
+ if ( status ){
+ fmt = status > NUMERRS ? err1 : err2;
+ fprintf( stderr, fmt, status, errmsg[status] );
+ abort();
+ }
+}
+
+ /************************
+ * *
+ * BAUD RATE ROUTINES *
+ * *
+ ************************/
+
+/* Table of baudrates known to be acceptable to NINDY. Each baud rate
+ * appears both as character string and as a Unix baud rate constant.
+ */
+struct baudrate {
+ char *string;
+ int rate;
+};
+
+static struct baudrate baudtab[] = {
+ "1200", 1200,
+ "2400", 2400,
+ "4800", 4800,
+ "9600", 9600,
+ "19200", 19200,
+ "38400", 38400,
+ NULL, 0 /* End of table */
+};
+
+/******************************************************************************
+ * parse_baudrate:
+ * Look up the passed baud rate in the baudrate table. If found, change
+ * our internal record of the current baud rate, but don't do anything
+ * about the tty just now.
+ *
+ * Return pointer to baudrate structure on success, NULL on failure.
+ ******************************************************************************/
+static
+struct baudrate *
+parse_baudrate(s)
+ char *s; /* Desired baud rate, as an ASCII (decimal) string */
+{
+ int i;
+
+ for ( i=0; baudtab[i].string != NULL; i++ ){
+ if ( !strcmp(baudtab[i].string,s) ){
+ return &baudtab[i];
+ }
+ }
+ return NULL;
+}
+
+/******************************************************************************
+ * try_baudrate:
+ * Try speaking to NINDY via the specified file descriptor at the
+ * specified baudrate. Assume success if we can send an empty command
+ * with a bogus checksum and receive a NAK (response of '-') back within
+ * one second.
+ *
+ * Return 1 on success, 0 on failure.
+ ***************************************************************************/
+
+static int
+try_baudrate (serial, brp)
+ serial_t serial;
+ struct baudrate *brp;
+{
+ unsigned char c;
+
+ /* Set specified baud rate and flush all pending input */
+ SERIAL_SETBAUDRATE (serial, brp->rate);
+ tty_flush (serial);
+
+ /* Send empty command with bad checksum, hope for NAK ('-') response */
+ SERIAL_WRITE (serial, "\020\0\0\001", 4);
+
+ /* Anything but a quick '-', including error, eof, or timeout, means that
+ this baudrate doesn't work. */
+ return SERIAL_READCHAR (serial, 1) == '-';
+}
+
+/******************************************************************************
+ * autobaud:
+ * Get NINDY talking over the specified file descriptor at the specified
+ * baud rate. First see if NINDY's already talking at 'baudrate'. If
+ * not, run through all the legal baudrates in 'baudtab' until one works,
+ * and then tell NINDY to talk at 'baudrate' instead.
+ ******************************************************************************/
+static
+autobaud( serial, brp )
+ serial_t serial;
+ struct baudrate *brp;
+{
+ int i;
+ int failures;
+
+ say("NINDY at wrong baud rate? Trying to autobaud...\n");
+ failures = i = 0;
+ while (1)
+ {
+ say( "\r%s... ", baudtab[i].string );
+ if (try_baudrate(serial, &baudtab[i]))
+ {
+ break;
+ }
+ if (baudtab[++i].string == NULL)
+ {
+ /* End of table -- wraparound */
+ i = 0;
+ if ( failures++ )
+ {
+ say("\nAutobaud failed again. Giving up.\n");
+ exit(1);
+ }
+ else
+ {
+ say("\nAutobaud failed. Trying again...\n");
+ }
+ }
+ }
+
+ /* Found NINDY's current baud rate; now change it. */
+ say("Changing NINDY baudrate to %s\n", brp->string);
+ ninBaud (brp->string);
+
+ /* Change our baud rate back to rate to which we just set NINDY. */
+ SERIAL_SETBAUDRATE (serial, brp->rate);
+}
+
+ /**********************************
+ * *
+ * NINDY INTERFACE ROUTINES *
+ * *
+ * ninConnect *MUST* be the first *
+ * one of these routines called. *
+ **********************************/
+
+
+/******************************************************************************
+ * ninBaud:
+ * Ask NINDY to change the baud rate on its serial port.
+ * Assumes we know the baud rate at which NINDY's currently talking.
+ ******************************************************************************/
+ninBaud( baudrate )
+ char *baudrate; /* Desired baud rate, as a string of ASCII decimal
+ * digits.
+ */
+{
+ unsigned char msg[100];
+
+ tty_flush (nindy_serial);
+
+ if (old_nindy)
+ {
+ char *p; /* Pointer into buffer */
+ unsigned char csum; /* Calculated checksum */
+
+ /* Can't use putpkt() because after the baudrate change NINDY's
+ ack/nak will look like gibberish. */
+
+ for (p=baudrate, csum=020+'z'; *p; p++)
+ {
+ csum += *p;
+ }
+ sprintf (msg, "\020z%s#%02x", baudrate, csum);
+ SERIAL_WRITE (nindy_serial, msg, strlen (msg));
+ }
+ else
+ {
+ /* Can't use "send" because NINDY reply will be unreadable after
+ baud rate change. */
+ sprintf( msg, "z%s", baudrate );
+ putpkt( msg, strlen(msg)+1 ); /* "+1" to send terminator too */
+ }
+}
+
+/******************************************************************************
+ * ninBptDel:
+ * Ask NINDY to delete the specified type of *hardware* breakpoint at
+ * the specified address. If the 'addr' is -1, all breakpoints of
+ * the specified type are deleted.
+ ***************************************************************************/
+ninBptDel( addr, type )
+ long addr; /* Address in 960 memory */
+ char type; /* 'd' => data bkpt, 'i' => instruction breakpoint */
+{
+ unsigned char buf[10];
+
+ if ( old_nindy ){
+ OninBptDel( addr, type == 'd' ? 1 : 0 );
+ return;
+ }
+
+ buf[0] = 'b';
+ buf[1] = type;
+
+ if ( addr == -1 ){
+ send( buf, 2, NULL );
+ } else {
+ store_unsigned_integer (&buf[2], 4, addr);
+ send( buf, 6, NULL );
+ }
+}
+
+
+/******************************************************************************
+ * ninBptSet:
+ * Ask NINDY to set the specified type of *hardware* breakpoint at
+ * the specified address.
+ ******************************************************************************/
+ninBptSet( addr, type )
+ long addr; /* Address in 960 memory */
+ char type; /* 'd' => data bkpt, 'i' => instruction breakpoint */
+{
+ unsigned char buf[10];
+
+ if ( old_nindy ){
+ OninBptSet( addr, type == 'd' ? 1 : 0 );
+ return;
+ }
+
+
+ buf[0] = 'B';
+ buf[1] = type;
+ store_unsigned_integer (&buf[2], 4, addr);
+ send( buf, 6, NULL );
+}
+
+
+/******************************************************************************
+ * ninConnect:
+ * Open the specified tty. Get communications working at the specified
+ * baud rate. Flush any pending I/O on the tty.
+ *
+ * Return the file descriptor, or -1 on failure.
+ ******************************************************************************/
+int
+ninConnect( name, baudrate, brk, silent, old_protocol )
+ char *name; /* "/dev/ttyXX" to be opened */
+ char *baudrate;/* baud rate: a string of ascii decimal digits (eg,"9600")*/
+ int brk; /* 1 => send break to tty first thing after opening it*/
+ int silent; /* 1 => stifle unnecessary messages when talking to
+ * this tty.
+ */
+ int old_protocol;
+{
+ int i;
+ char *p;
+ struct baudrate *brp;
+
+ /* We will try each of the following paths when trying to open the tty
+ */
+ static char *prefix[] = { "", "/dev/", "/dev/tty", NULL };
+
+ if ( old_protocol ){
+ old_nindy = 1;
+ }
+
+ quiet = silent; /* Make global to this file */
+
+ for ( i=0; prefix[i] != NULL; i++ ){
+ p = xmalloc(strlen(prefix[i]) + strlen(name) + 1 );
+ strcpy( p, prefix[i] );
+ strcat( p, name );
+ nindy_serial = SERIAL_OPEN (p);
+ if (nindy_serial != NULL) {
+#ifdef TIOCEXCL
+ /* Exclusive use mode (hp9000 does not support it) */
+ ioctl(nindy_serial->fd,TIOCEXCL,NULL);
+#endif
+ SERIAL_RAW (nindy_serial);
+
+ if (brk)
+ {
+ SERIAL_SEND_BREAK (nindy_serial);
+ }
+
+ brp = parse_baudrate( baudrate );
+ if ( brp == NULL ){
+ say("Illegal baudrate %s ignored; using 9600\n",
+ baudrate);
+ brp = parse_baudrate( "9600" );
+ }
+
+ if ( !try_baudrate(nindy_serial, brp) ){
+ autobaud(nindy_serial, brp);
+ }
+ tty_flush (nindy_serial);
+ say( "Connected to %s\n", p );
+ free(p);
+ break;
+ }
+ free(p);
+ }
+ return 0;
+}
+
+#if 0
+
+/* Currently unused; shouldn't we be doing this on target_kill and
+perhaps target_mourn? FIXME. */
+
+/******************************************************************************
+ * ninGdbExit:
+ * Ask NINDY to leave GDB mode and print a NINDY prompt.
+ ****************************************************************************/
+ninGdbExit()
+{
+ if ( old_nindy ){
+ OninGdbExit();
+ return;
+ }
+ putpkt((unsigned char *) "E", 1 );
+}
+#endif
+
+/******************************************************************************
+ * ninGo:
+ * Ask NINDY to start or continue execution of an application program
+ * in it's memory at the current ip.
+ ******************************************************************************/
+ninGo( step_flag )
+ int step_flag; /* 1 => run in single-step mode */
+{
+ if ( old_nindy ){
+ OninGo( step_flag );
+ return;
+ }
+ putpkt((unsigned char *) (step_flag ? "s" : "c"), 1 );
+}
+
+
+/******************************************************************************
+ * ninMemGet:
+ * Read a string of bytes from NINDY's address space (960 memory).
+ ******************************************************************************/
+int
+ninMemGet(ninaddr, hostaddr, len)
+ long ninaddr; /* Source address, in the 960 memory space */
+ unsigned char *hostaddr; /* Destination address, in our memory space */
+ int len; /* Number of bytes to read */
+{
+ unsigned char buf[BUFSIZE+20];
+ int cnt; /* Number of bytes in next transfer */
+ int origlen = len;
+
+ if ( old_nindy ){
+ OninMemGet(ninaddr, hostaddr, len);
+ return;
+ }
+
+ for ( ; len > 0; len -= BUFSIZE ){
+ cnt = len > BUFSIZE ? BUFSIZE : len;
+
+ buf[0] = 'm';
+ store_unsigned_integer (&buf[1], 4, ninaddr);
+ buf[5] = cnt & 0xff;
+ buf[6] = (cnt>>8) & 0xff;
+
+ send( buf, 7, hostaddr );
+
+ ninaddr += cnt;
+ hostaddr += cnt;
+ }
+ return origlen;
+}
+
+
+/******************************************************************************
+ * ninMemPut:
+ * Write a string of bytes into NINDY's address space (960 memory).
+ ******************************************************************************/
+int
+ninMemPut( ninaddr, hostaddr, len )
+ long ninaddr; /* Destination address, in NINDY memory space */
+ unsigned char *hostaddr; /* Source address, in our memory space */
+ int len; /* Number of bytes to write */
+{
+ unsigned char buf[BUFSIZE+20];
+ int cnt; /* Number of bytes in next transfer */
+ int origlen = len;
+
+ if ( old_nindy ){
+ OninMemPut( ninaddr, hostaddr, len );
+ return;
+ }
+ for ( ; len > 0; len -= BUFSIZE ){
+ cnt = len > BUFSIZE ? BUFSIZE : len;
+
+ buf[0] = 'M';
+ store_unsigned_integer (&buf[1], 4, ninaddr);
+ memcpy(buf + 5, hostaddr, cnt);
+ send( buf, cnt+5, NULL );
+
+ ninaddr += cnt;
+ hostaddr += cnt;
+ }
+ return origlen;
+}
+
+/******************************************************************************
+ * ninRegGet:
+ * Retrieve the contents of a 960 register, and return them as a long
+ * in host byte order.
+ *
+ * THIS ROUTINE CAN ONLY BE USED TO READ THE LOCAL, GLOBAL, AND
+ * ip/ac/pc/tc REGISTERS.
+ *
+ ******************************************************************************/
+long
+ninRegGet( regname )
+ char *regname; /* Register name recognized by NINDY, subject to the
+ * above limitations.
+ */
+{
+ unsigned char outbuf[10];
+ unsigned char inbuf[20];
+
+ if ( old_nindy ){
+ return OninRegGet( regname );
+ }
+
+ sprintf( outbuf, "u%s:", regname );
+ send( outbuf, strlen(outbuf), inbuf );
+ return extract_unsigned_integer (inbuf, 4);
+}
+
+/******************************************************************************
+ * ninRegPut:
+ * Set the contents of a 960 register.
+ *
+ * THIS ROUTINE CAN ONLY BE USED TO SET THE LOCAL, GLOBAL, AND
+ * ip/ac/pc/tc REGISTERS.
+ *
+ ******************************************************************************/
+ninRegPut( regname, val )
+ char *regname; /* Register name recognized by NINDY, subject to the
+ * above limitations.
+ */
+ long val; /* New contents of register, in host byte-order */
+{
+ unsigned char buf[20];
+ int len;
+
+ if ( old_nindy ){
+ OninRegPut( regname, val );
+ return;
+ }
+
+ sprintf( buf, "U%s:", regname );
+ len = strlen(buf);
+ store_unsigned_integer (&buf[len], 4, val);
+ send( buf, len+4, NULL );
+}
+
+/******************************************************************************
+ * ninRegsGet:
+ * Get a dump of the contents of the entire 960 register set. The
+ * individual registers appear in the dump in the following order:
+ *
+ * pfp sp rip r3 r4 r5 r6 r7
+ * r8 r9 r10 r11 r12 r13 r14 r15
+ * g0 g1 g2 g3 g4 g5 g6 g7
+ * g8 g9 g10 g11 g12 g13 g14 fp
+ * pc ac ip tc fp0 fp1 fp2 fp3
+ *
+ * Each individual register comprises exactly 4 bytes, except for
+ * fp0-fp3, which are 8 bytes. All register values are in 960
+ * (little-endian) byte order.
+ *
+ ******************************************************************************/
+ninRegsGet( regp )
+ unsigned char *regp; /* Where to place the register dump */
+{
+ if ( old_nindy ){
+ OninRegsGet( regp );
+ return;
+ }
+ send( (unsigned char *) "r", 1, regp );
+}
+
+
+/******************************************************************************
+ * ninRegsPut:
+ * Initialize the entire 960 register set to a specified set of values.
+ * The format of the register value data should be the same as that
+ * returned by ninRegsGet.
+ *
+ * WARNING:
+ * All register values must be in 960 (little-endian) byte order.
+ *
+ ******************************************************************************/
+ninRegsPut( regp )
+ char *regp; /* Pointer to desired values of registers */
+{
+/* Number of bytes that we send to nindy. I believe this is defined by
+ the protocol (it does not agree with REGISTER_BYTES). */
+#define NINDY_REGISTER_BYTES ((36*4) + (4*8))
+ unsigned char buf[NINDY_REGISTER_BYTES+10];
+
+ if ( old_nindy ){
+ OninRegsPut( regp );
+ return;
+ }
+
+ buf[0] = 'R';
+ memcpy(buf+1, regp, NINDY_REGISTER_BYTES );
+ send( buf, NINDY_REGISTER_BYTES+1, NULL );
+}
+
+
+/******************************************************************************
+ * ninReset:
+ * Ask NINDY to perform a soft reset; wait for the reset to complete.
+ *
+ ******************************************************************************/
+ninReset()
+{
+ unsigned char ack;
+
+ if ( old_nindy ){
+ OninReset();
+ return;
+ }
+
+ while (1){
+ putpkt((unsigned char *) "X", 1 );
+ while (1){
+ if ( !rdnin(&ack,1,5) ){
+ /* Timed out */
+ break; /* Resend */
+ }
+ if ( ack == '+' ){
+ return;
+ }
+ }
+ }
+}
+
+
+/******************************************************************************
+ * ninSrq:
+ * Assume NINDY has stopped execution of the 960 application program in
+ * order to process a host service request (srq). Ask NINDY for the
+ * srq arguments, perform the requested service, and send an "srq
+ * complete" message so NINDY will return control to the application.
+ *
+ ******************************************************************************/
+ninSrq()
+{
+ /* FIXME: Imposes arbitrary limits on lengths of pathnames and such. */
+ unsigned char buf[BUFSIZE];
+ int retcode;
+ unsigned char srqnum;
+ int i;
+ int offset;
+ int arg[MAX_SRQ_ARGS];
+
+ if ( old_nindy ){
+ OninSrq();
+ return;
+ }
+
+
+ /* Get srq number and arguments
+ */
+ send((unsigned char *) "!", 1, buf );
+
+ srqnum = buf[0];
+ for ( i=0, offset=1; i < MAX_SRQ_ARGS; i++, offset+=4 ){
+ arg[i] = extract_unsigned_integer (&buf[offset], 4);
+ }
+
+ /* Process Srq
+ */
+ switch( srqnum ){
+ case BS_CLOSE:
+ /* args: file descriptor */
+ if ( arg[0] > 2 ){
+ retcode = close( arg[0] );
+ } else {
+ retcode = 0;
+ }
+ break;
+ case BS_CREAT:
+ /* args: filename, mode */
+ ninStrGet( arg[0], buf );
+ retcode = creat(buf,arg[1]);
+ break;
+ case BS_OPEN:
+ /* args: filename, flags, mode */
+ ninStrGet( arg[0], buf );
+ retcode = open(buf,arg[1],arg[2]);
+ break;
+ case BS_READ:
+ /* args: file descriptor, buffer, count */
+ retcode = read(arg[0],buf,arg[2]);
+ if ( retcode > 0 ){
+ ninMemPut( arg[1], buf, retcode );
+ }
+ break;
+ case BS_SEEK:
+ /* args: file descriptor, offset, whence */
+ retcode = lseek(arg[0],arg[1],arg[2]);
+ break;
+ case BS_WRITE:
+ /* args: file descriptor, buffer, count */
+ ninMemGet( arg[1], buf, arg[2] );
+ retcode = write(arg[0],buf,arg[2]);
+ break;
+ default:
+ retcode = -1;
+ break;
+ }
+
+ /* Send request termination status to NINDY
+ */
+ buf[0] = 'e';
+ store_unsigned_integer (&buf[1], 4, retcode);
+ send( buf, 5, NULL );
+}
+
+
+/******************************************************************************
+ * ninStopWhy:
+ * Assume the application program has stopped (i.e., a DLE was received
+ * from NINDY). Ask NINDY for status information describing the
+ * reason for the halt.
+ *
+ * Returns a non-zero value if the user program has exited, 0 otherwise.
+ * Also returns the following information, through passed pointers:
+ * - why: an exit code if program the exited; otherwise the reason
+ * why the program halted (see stop.h for values).
+ * - contents of register ip (little-endian byte order)
+ * - contents of register sp (little-endian byte order)
+ * - contents of register fp (little-endian byte order)
+ ******************************************************************************/
+char
+ninStopWhy( whyp, ipp, fpp, spp )
+ unsigned char *whyp; /* Return the 'why' code through this pointer */
+ long *ipp; /* Return contents of register ip through this pointer */
+ long *fpp; /* Return contents of register fp through this pointer */
+ long *spp; /* Return contents of register sp through this pointer */
+{
+ unsigned char buf[30];
+ extern char OninStopWhy ();
+
+ if ( old_nindy ){
+ return OninStopWhy( whyp, ipp, fpp, spp );
+ }
+ send((unsigned char *) "?", 1, buf );
+
+ *whyp = buf[1];
+ memcpy ((char *)ipp, &buf[2], sizeof (*ipp));
+ memcpy ((char *)fpp, &buf[6], sizeof (*ipp));
+ memcpy ((char *)spp, &buf[10], sizeof (*ipp));
+ return buf[0];
+}
+
+/******************************************************************************
+ * ninStrGet:
+ * Read a '\0'-terminated string of data out of the 960 memory space.
+ *
+ ******************************************************************************/
+static
+ninStrGet( ninaddr, hostaddr )
+ unsigned long ninaddr; /* Address of string in NINDY memory space */
+ unsigned char *hostaddr; /* Address of the buffer to which string should
+ * be copied.
+ */
+{
+ unsigned char cmd[5];
+
+ cmd[0] = '"';
+ store_unsigned_integer (&cmd[1], 4, ninaddr);
+ send( cmd, 5, hostaddr );
+}
+
+#if 0
+/* Not used. */
+
+/******************************************************************************
+ * ninVersion:
+ * Ask NINDY for version information about itself.
+ * The information is sent as an ascii string in the form "x.xx,<arch>",
+ * where,
+ * x.xx is the version number
+ * <arch> is the processor architecture: "KA", "KB", "MC", "CA" *
+ *
+ ******************************************************************************/
+int
+ninVersion( p )
+ unsigned char *p; /* Where to place version string */
+{
+
+ if ( old_nindy ){
+ return OninVersion( p );
+ }
+ send((unsigned char *) "v", 1, p );
+ return strlen(p);
+}
+#endif /* 0 */
diff --git a/gdb/nindy-share/stop.h b/gdb/nindy-share/stop.h
new file mode 100644
index 00000000000..82a90a54840
--- /dev/null
+++ b/gdb/nindy-share/stop.h
@@ -0,0 +1,86 @@
+/******************************************************************
+ Copyright 1990, 1992 Free Software Foundation, Inc.
+
+ This code was donated by Intel Corp.
+
+ Intel hereby grants you permission to copy, modify, and
+ distribute this software and its documentation. Intel grants
+ this permission provided that the above copyright notice
+ appears in all copies and that both the copyright notice and
+ this permission notice appear in supporting documentation. In
+ addition, Intel grants this permission provided that you
+ prominently mark as not part of the original any modifications
+ made to this software or documentation, and that the name of
+ Intel Corporation not be used in advertising or publicity
+ pertaining to distribution of the software or the documentation
+ without specific, written prior permission.
+
+ Intel Corporation does not warrant, guarantee or make any
+ representations regarding the use of, or the results of the use
+ of, the software and documentation in terms of correctness,
+ accuracy, reliability, currentness, or otherwise; and you rely
+ on the software, documentation and results solely at your own
+ risk. */
+/******************************************************************/
+
+
+/******************************************************************
+ *
+ * REASONS WHY NINDY CAN STOP EXECUTING AN APPLICATION PROGRAM
+ *
+ * When NINDY stops executing an application program that was running
+ * under remote host ("gdb") control, it signals the host by sending
+ * a single ^P. The host can then query as to the reason for the halt.
+ * NINDY responds with two bytes of information.
+ *
+ * The first byte is a boolean flag that indicates whether or not
+ * the application has exited.
+ *
+ * If the flag is true, the second byte contains the exit code.
+ *
+ * If the flag is false, the second byte contains a "reason for
+ * stopping" code. This file defines the possible values of that
+ * code.
+ *
+ * There are three categories of reasons why the halt may have occurred:
+ * faults, traces, and software interactions. The first two categories
+ * are processor-dependent; the values of these codes are tightly coupled
+ * to the hardware and should not be changed without first examining
+ * src/nindy/common/fault.c. The software interactions involve
+ * communication between NINDY and the host debugger; their codes are
+ * arbitrary.
+ *
+ ******************************************************************/
+
+#define FAULT_PARALLEL 0x00
+#define FAULT_UNKNOWN 0x01
+#define FAULT_OPERATION 0x02
+#define FAULT_ARITH 0x03
+#define FAULT_FP 0x04
+#define FAULT_CONSTR 0x05
+#define FAULT_VM 0x06
+#define FAULT_PROTECT 0x07
+#define FAULT_MACHINE 0x08
+#define FAULT_STRUCT 0x09
+#define FAULT_TYPE 0x0a
+ /* 0x0b reserved */
+#define FAULT_PROCESS 0x0c
+#define FAULT_DESC 0x0d
+#define FAULT_EVENT 0x0e
+ /* 0x0f reserved */
+
+#define LAST_FAULT 0x0f
+
+#define TRACE_STEP 0x10
+#define TRACE_BRANCH 0x11
+#define TRACE_CALL 0x12
+#define TRACE_RET 0x13
+#define TRACE_PRERET 0x14
+#define TRACE_SVC 0x15
+#define TRACE_BKPT 0x16
+
+#define STOP_SRQ 0xfe
+ /* Application program has service request to make of host */
+
+#define STOP_GDB_BPT 0xff
+ /* Application program has reached breakpoint (fmark) set by host */
diff --git a/gdb/nindy-share/ttyflush.c b/gdb/nindy-share/ttyflush.c
new file mode 100644
index 00000000000..9754472ddd7
--- /dev/null
+++ b/gdb/nindy-share/ttyflush.c
@@ -0,0 +1,53 @@
+/* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* This started out life as code shared between the nindy monitor and
+ GDB. For various reasons, this is no longer true. Eventually, it
+ probably should be merged into remote-nindy.c. */
+
+#include <stdio.h>
+#include "defs.h"
+#include "serial.h"
+
+#ifdef _MSC_VER
+# include <stdlib.h>
+# define sleep _sleep
+#endif
+
+/* Flush all pending input and output for SERIAL, wait for a second, and
+ then if there is a character pending, discard it and flush again. */
+
+int
+tty_flush (serial)
+ serial_t serial;
+{
+ while (1)
+ {
+ SERIAL_FLUSH_INPUT (serial);
+ SERIAL_FLUSH_OUTPUT (serial);
+ sleep(1);
+ switch (SERIAL_READCHAR (serial, 0))
+ {
+ case SERIAL_TIMEOUT:
+ case SERIAL_ERROR:
+ case SERIAL_EOF:
+ return 0;
+ default:
+ /* We read something. Eeek. Try again. */
+ break;
+ }
+ }
+}
diff --git a/gdb/nindy-tdep.c b/gdb/nindy-tdep.c
new file mode 100644
index 00000000000..2e0b10c6a94
--- /dev/null
+++ b/gdb/nindy-tdep.c
@@ -0,0 +1,74 @@
+/* Target-machine dependent code for the NINDY monitor running on the Intel 960
+ Copyright (C) 1991 Free Software Foundation, Inc.
+ Contributed by Intel Corporation.
+
+This file is part of GDB.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Miscellaneous NINDY-dependent routines.
+ Some replace macros normally defined in "tm.h". */
+
+#include "defs.h"
+#include "symtab.h"
+#include "frame.h"
+#include "gdbcore.h"
+
+/* 'start_frame' is a variable in the NINDY runtime startup routine
+ that contains the frame pointer of the 'start' routine (the routine
+ that calls 'main'). By reading its contents out of remote memory,
+ we can tell where the frame chain ends: backtraces should halt before
+ they display this frame. */
+
+int
+nindy_frame_chain_valid (chain, curframe)
+ CORE_ADDR chain;
+ struct frame_info *curframe;
+{
+ struct symbol *sym;
+ struct minimal_symbol *msymbol;
+
+ /* crtnindy.o is an assembler module that is assumed to be linked
+ * first in an i80960 executable. It contains the true entry point;
+ * it performs startup up initialization and then calls 'main'.
+ *
+ * 'sf' is the name of a variable in crtnindy.o that is set
+ * during startup to the address of the first frame.
+ *
+ * 'a' is the address of that variable in 80960 memory.
+ */
+ static char sf[] = "start_frame";
+ CORE_ADDR a;
+
+
+ chain &= ~0x3f; /* Zero low 6 bits because previous frame pointers
+ contain return status info in them. */
+ if ( chain == 0 ){
+ return 0;
+ }
+
+ sym = lookup_symbol(sf, 0, VAR_NAMESPACE, (int *)NULL,
+ (struct symtab **)NULL);
+ if ( sym != 0 ){
+ a = SYMBOL_VALUE (sym);
+ } else {
+ msymbol = lookup_minimal_symbol (sf, NULL, NULL);
+ if (msymbol == NULL)
+ return 0;
+ a = SYMBOL_VALUE_ADDRESS (msymbol);
+ }
+
+ return ( chain != read_memory_integer(a,4) );
+}
diff --git a/gdb/nlm/Makefile.in b/gdb/nlm/Makefile.in
new file mode 100644
index 00000000000..54511387a00
--- /dev/null
+++ b/gdb/nlm/Makefile.in
@@ -0,0 +1,172 @@
+#Copyright 1989, 1990, 91, 92, 93, 94, 95, 1999 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+host_alias = @host_alias@
+target_alias = @target_alias@
+program_transform_name = @program_transform_name@
+bindir = @bindir@
+libdir = @libdir@
+tooldir = $(libdir)/$(target_alias)
+
+datadir = @datadir@
+mandir = @mandir@
+man1dir = $(mandir)/man1
+man2dir = $(mandir)/man2
+man3dir = $(mandir)/man3
+man4dir = $(mandir)/man4
+man5dir = $(mandir)/man5
+man6dir = $(mandir)/man6
+man7dir = $(mandir)/man7
+man8dir = $(mandir)/man8
+man9dir = $(mandir)/man9
+infodir = @infodir@
+includedir = @includedir@
+
+SHELL = @SHELL@
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA = @INSTALL_DATA@
+
+CC_FOR_TARGET = ` \
+ if [ -f ../../gcc/xgcc ] ; then \
+ echo ../../gcc/xgcc -B../../gcc/; \
+ else \
+ t='$(program_transform_name)'; echo gcc | sed -e '' $$t; \
+ fi`
+
+NLMCONV_FOR_TARGET = ` \
+ if [ -f ../../binutils/nlmconv ] ; then \
+ echo ../../binutils/nlmconv; \
+ else \
+ t='$(program_transform_name)'; echo nlmconv | sed -e '' $$t; \
+ fi`
+
+# All the includes used for CFLAGS and for lint.
+INCLUDE_CFLAGS = -I. -I${srcdir}
+
+# CFLAGS is specifically reserved for setting from the command line
+# when running make. I.E. "make CFLAGS=-Wmissing-prototypes".
+CFLAGS = -g
+# INTERNAL_CFLAGS is the aggregate of all other *CFLAGS macros.
+INTERNAL_CFLAGS = ${CFLAGS} ${INCLUDE_CFLAGS} ${USER_CFLAGS}
+LDFLAGS = $(CFLAGS)
+
+# Perhaps should come from parent Makefile
+VERSION = gdbserve-4.12
+DIST=gdb
+
+# target-dependent makefile fragment come in here.
+@target_makefile_frag@
+# End target-dependent makefile fragment
+
+# All source files that go into linking GDB remote server.
+
+DEPFILES = $(GDBSERVE_DEPFILES)
+
+SOURCES = $(ALLDEPFILES)
+TAGFILES = $(SOURCES) ${HFILES} ${ALLPARAM} ${POSSLIBS}
+
+# Prevent Sun make from putting in the machine type. Setting
+# TARGET_ARCH to nothing works for SunOS 3, 4.0, but not for 4.1.
+.c.o:
+ ${CC_FOR_TARGET} -c ${INTERNAL_CFLAGS} $<
+
+.S.o:
+ ${CC_FOR_TARGET} -c ${INTERNAL_CFLAGS} $<
+
+all: gdbserve.nlm
+
+# Traditionally "install" depends on "all". But it may be useful
+# not to; for example, if the user has made some trivial change to a
+# source file and doesn't care about rebuilding or just wants to save the
+# time it takes for make to check that all is up to date.
+# install-only is intended to address that need.
+install: all install-only
+install-only:
+ $(INSTALL) gdbserve.nlm $(bindir)/gdbserve.nlm
+
+uninstall: force
+ rm -f $(bindir)/gdbserve.nlm
+
+installcheck:
+check:
+info dvi:
+install-info:
+clean-info:
+
+gdbserve.nlm: gdbserve.O $(srcdir)/gdbserve.def
+ ${NLMCONV_FOR_TARGET} -T $(srcdir)/gdbserve.def
+
+gdbserve.O: prelude.o gdbserve.o $(TDEPFILES)
+ ${CC_FOR_TARGET} $(LDFLAGS) -r -o gdbserve.O prelude.o gdbserve.o ${TDEPFILES}
+
+# Put the proper machine-specific files first, so M-. on a machine
+# specific routine gets the one for the correct machine.
+# The xyzzy stuff below deals with empty DEPFILES
+TAGS: ${TAGFILES}
+ etags `find ${srcdir}/../config -name $(TM_FILE) -print` \
+ `find ${srcdir}/../config -name ${XM_FILE} -print` \
+ `find ${srcdir}/../config -name ${NAT_FILE} -print` \
+ `for i in yzzy ${DEPFILES}; do \
+ if [ x$$i != xyzzy ]; then \
+ echo ${srcdir}/$$i | sed -e 's/\.o$$/\.c/' ; \
+ fi; \
+ done` \
+ ${TAGFILES}
+tags: TAGS
+
+clean:
+ rm -f *.o ${ADD_FILES} *~
+ rm -f gdbserve.O gdbserve.nlm core make.log
+
+distclean: clean TAGS
+ rm -f config.log config.cache config.status
+ rm -f Makefile
+
+maintainer-clean realclean: clean
+ rm -f TAGS
+ rm -f config.log config.cache config.status
+ rm -f Makefile
+
+Makefile: Makefile.in config.status @target_makefile_frag_path@
+ $(SHELL) config.status
+
+config.status: configure
+ $(SHELL) config.status --recheck
+
+force:
+
+# GNU Make has an annoying habit of putting *all* the Makefile variables
+# into the environment, unless you include this target as a circumvention.
+# Rumor is that this will be fixed (and this target can be removed)
+# in GNU Make 4.0.
+.NOEXPORT:
+
+# GNU Make 3.63 has a different problem: it keeps tacking command line
+# overrides onto the definition of $(MAKE). This variable setting
+# will remove them.
+MAKEOVERRIDES=
+
+# This is the end of "Makefile.in".
diff --git a/gdb/nlm/configure b/gdb/nlm/configure
new file mode 100755
index 00000000000..3918fee794c
--- /dev/null
+++ b/gdb/nlm/configure
@@ -0,0 +1,1074 @@
+#! /bin/sh
+
+# Guess values for system-dependent variables and create Makefiles.
+# Generated automatically using autoconf version 2.12.2
+# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc.
+#
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+
+# Defaults:
+ac_help=
+ac_default_prefix=/usr/local
+# Any additions from configure.in:
+
+# Initialize some variables set by options.
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+build=NONE
+cache_file=./config.cache
+exec_prefix=NONE
+host=NONE
+no_create=
+nonopt=NONE
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+target=NONE
+verbose=
+x_includes=NONE
+x_libraries=NONE
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datadir='${prefix}/share'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+libdir='${exec_prefix}/lib'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+infodir='${prefix}/info'
+mandir='${prefix}/man'
+
+# Initialize some other variables.
+subdirs=
+MFLAGS= MAKEFLAGS=
+SHELL=${CONFIG_SHELL-/bin/sh}
+# Maximum number of lines to put in a shell here document.
+ac_max_here_lines=12
+
+ac_prev=
+for ac_option
+do
+
+ # If the previous option needs an argument, assign it.
+ if test -n "$ac_prev"; then
+ eval "$ac_prev=\$ac_option"
+ ac_prev=
+ continue
+ fi
+
+ case "$ac_option" in
+ -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
+ *) ac_optarg= ;;
+ esac
+
+ # Accept the important Cygnus configure options, so we can diagnose typos.
+
+ case "$ac_option" in
+
+ -bindir | --bindir | --bindi | --bind | --bin | --bi)
+ ac_prev=bindir ;;
+ -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+ bindir="$ac_optarg" ;;
+
+ -build | --build | --buil | --bui | --bu)
+ ac_prev=build ;;
+ -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+ build="$ac_optarg" ;;
+
+ -cache-file | --cache-file | --cache-fil | --cache-fi \
+ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+ ac_prev=cache_file ;;
+ -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+ cache_file="$ac_optarg" ;;
+
+ -datadir | --datadir | --datadi | --datad | --data | --dat | --da)
+ ac_prev=datadir ;;
+ -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \
+ | --da=*)
+ datadir="$ac_optarg" ;;
+
+ -disable-* | --disable-*)
+ ac_feature=`echo $ac_option|sed -e 's/-*disable-//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then
+ { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
+ fi
+ ac_feature=`echo $ac_feature| sed 's/-/_/g'`
+ eval "enable_${ac_feature}=no" ;;
+
+ -enable-* | --enable-*)
+ ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then
+ { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
+ fi
+ ac_feature=`echo $ac_feature| sed 's/-/_/g'`
+ case "$ac_option" in
+ *=*) ;;
+ *) ac_optarg=yes ;;
+ esac
+ eval "enable_${ac_feature}='$ac_optarg'" ;;
+
+ -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+ | --exec | --exe | --ex)
+ ac_prev=exec_prefix ;;
+ -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+ | --exec=* | --exe=* | --ex=*)
+ exec_prefix="$ac_optarg" ;;
+
+ -gas | --gas | --ga | --g)
+ # Obsolete; use --with-gas.
+ with_gas=yes ;;
+
+ -help | --help | --hel | --he)
+ # Omit some internal or obsolete options to make the list less imposing.
+ # This message is too long to be a string in the A/UX 3.1 sh.
+ cat << EOF
+Usage: configure [options] [host]
+Options: [defaults in brackets after descriptions]
+Configuration:
+ --cache-file=FILE cache test results in FILE
+ --help print this message
+ --no-create do not create output files
+ --quiet, --silent do not print \`checking...' messages
+ --version print the version of autoconf that created configure
+Directory and file names:
+ --prefix=PREFIX install architecture-independent files in PREFIX
+ [$ac_default_prefix]
+ --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
+ [same as prefix]
+ --bindir=DIR user executables in DIR [EPREFIX/bin]
+ --sbindir=DIR system admin executables in DIR [EPREFIX/sbin]
+ --libexecdir=DIR program executables in DIR [EPREFIX/libexec]
+ --datadir=DIR read-only architecture-independent data in DIR
+ [PREFIX/share]
+ --sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc]
+ --sharedstatedir=DIR modifiable architecture-independent data in DIR
+ [PREFIX/com]
+ --localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var]
+ --libdir=DIR object code libraries in DIR [EPREFIX/lib]
+ --includedir=DIR C header files in DIR [PREFIX/include]
+ --oldincludedir=DIR C header files for non-gcc in DIR [/usr/include]
+ --infodir=DIR info documentation in DIR [PREFIX/info]
+ --mandir=DIR man documentation in DIR [PREFIX/man]
+ --srcdir=DIR find the sources in DIR [configure dir or ..]
+ --program-prefix=PREFIX prepend PREFIX to installed program names
+ --program-suffix=SUFFIX append SUFFIX to installed program names
+ --program-transform-name=PROGRAM
+ run sed PROGRAM on installed program names
+EOF
+ cat << EOF
+Host type:
+ --build=BUILD configure for building on BUILD [BUILD=HOST]
+ --host=HOST configure for HOST [guessed]
+ --target=TARGET configure for TARGET [TARGET=HOST]
+Features and packages:
+ --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
+ --enable-FEATURE[=ARG] include FEATURE [ARG=yes]
+ --with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
+ --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
+ --x-includes=DIR X include files are in DIR
+ --x-libraries=DIR X library files are in DIR
+EOF
+ if test -n "$ac_help"; then
+ echo "--enable and --with options recognized:$ac_help"
+ fi
+ exit 0 ;;
+
+ -host | --host | --hos | --ho)
+ ac_prev=host ;;
+ -host=* | --host=* | --hos=* | --ho=*)
+ host="$ac_optarg" ;;
+
+ -includedir | --includedir | --includedi | --included | --include \
+ | --includ | --inclu | --incl | --inc)
+ ac_prev=includedir ;;
+ -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+ | --includ=* | --inclu=* | --incl=* | --inc=*)
+ includedir="$ac_optarg" ;;
+
+ -infodir | --infodir | --infodi | --infod | --info | --inf)
+ ac_prev=infodir ;;
+ -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+ infodir="$ac_optarg" ;;
+
+ -libdir | --libdir | --libdi | --libd)
+ ac_prev=libdir ;;
+ -libdir=* | --libdir=* | --libdi=* | --libd=*)
+ libdir="$ac_optarg" ;;
+
+ -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+ | --libexe | --libex | --libe)
+ ac_prev=libexecdir ;;
+ -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+ | --libexe=* | --libex=* | --libe=*)
+ libexecdir="$ac_optarg" ;;
+
+ -localstatedir | --localstatedir | --localstatedi | --localstated \
+ | --localstate | --localstat | --localsta | --localst \
+ | --locals | --local | --loca | --loc | --lo)
+ ac_prev=localstatedir ;;
+ -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+ | --localstate=* | --localstat=* | --localsta=* | --localst=* \
+ | --locals=* | --local=* | --loca=* | --loc=* | --lo=*)
+ localstatedir="$ac_optarg" ;;
+
+ -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+ ac_prev=mandir ;;
+ -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+ mandir="$ac_optarg" ;;
+
+ -nfp | --nfp | --nf)
+ # Obsolete; use --without-fp.
+ with_fp=no ;;
+
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c)
+ no_create=yes ;;
+
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+ no_recursion=yes ;;
+
+ -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+ | --oldin | --oldi | --old | --ol | --o)
+ ac_prev=oldincludedir ;;
+ -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+ oldincludedir="$ac_optarg" ;;
+
+ -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+ ac_prev=prefix ;;
+ -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+ prefix="$ac_optarg" ;;
+
+ -program-prefix | --program-prefix | --program-prefi | --program-pref \
+ | --program-pre | --program-pr | --program-p)
+ ac_prev=program_prefix ;;
+ -program-prefix=* | --program-prefix=* | --program-prefi=* \
+ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+ program_prefix="$ac_optarg" ;;
+
+ -program-suffix | --program-suffix | --program-suffi | --program-suff \
+ | --program-suf | --program-su | --program-s)
+ ac_prev=program_suffix ;;
+ -program-suffix=* | --program-suffix=* | --program-suffi=* \
+ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+ program_suffix="$ac_optarg" ;;
+
+ -program-transform-name | --program-transform-name \
+ | --program-transform-nam | --program-transform-na \
+ | --program-transform-n | --program-transform- \
+ | --program-transform | --program-transfor \
+ | --program-transfo | --program-transf \
+ | --program-trans | --program-tran \
+ | --progr-tra | --program-tr | --program-t)
+ ac_prev=program_transform_name ;;
+ -program-transform-name=* | --program-transform-name=* \
+ | --program-transform-nam=* | --program-transform-na=* \
+ | --program-transform-n=* | --program-transform-=* \
+ | --program-transform=* | --program-transfor=* \
+ | --program-transfo=* | --program-transf=* \
+ | --program-trans=* | --program-tran=* \
+ | --progr-tra=* | --program-tr=* | --program-t=*)
+ program_transform_name="$ac_optarg" ;;
+
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ silent=yes ;;
+
+ -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+ ac_prev=sbindir ;;
+ -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+ | --sbi=* | --sb=*)
+ sbindir="$ac_optarg" ;;
+
+ -sharedstatedir | --sharedstatedir | --sharedstatedi \
+ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+ | --sharedst | --shareds | --shared | --share | --shar \
+ | --sha | --sh)
+ ac_prev=sharedstatedir ;;
+ -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+ | --sha=* | --sh=*)
+ sharedstatedir="$ac_optarg" ;;
+
+ -site | --site | --sit)
+ ac_prev=site ;;
+ -site=* | --site=* | --sit=*)
+ site="$ac_optarg" ;;
+
+ -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+ ac_prev=srcdir ;;
+ -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+ srcdir="$ac_optarg" ;;
+
+ -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+ | --syscon | --sysco | --sysc | --sys | --sy)
+ ac_prev=sysconfdir ;;
+ -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+ sysconfdir="$ac_optarg" ;;
+
+ -target | --target | --targe | --targ | --tar | --ta | --t)
+ ac_prev=target ;;
+ -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+ target="$ac_optarg" ;;
+
+ -v | -verbose | --verbose | --verbos | --verbo | --verb)
+ verbose=yes ;;
+
+ -version | --version | --versio | --versi | --vers)
+ echo "configure generated by autoconf version 2.12.2"
+ exit 0 ;;
+
+ -with-* | --with-*)
+ ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then
+ { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
+ fi
+ ac_package=`echo $ac_package| sed 's/-/_/g'`
+ case "$ac_option" in
+ *=*) ;;
+ *) ac_optarg=yes ;;
+ esac
+ eval "with_${ac_package}='$ac_optarg'" ;;
+
+ -without-* | --without-*)
+ ac_package=`echo $ac_option|sed -e 's/-*without-//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then
+ { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
+ fi
+ ac_package=`echo $ac_package| sed 's/-/_/g'`
+ eval "with_${ac_package}=no" ;;
+
+ --x)
+ # Obsolete; use --with-x.
+ with_x=yes ;;
+
+ -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+ | --x-incl | --x-inc | --x-in | --x-i)
+ ac_prev=x_includes ;;
+ -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+ x_includes="$ac_optarg" ;;
+
+ -x-libraries | --x-libraries | --x-librarie | --x-librari \
+ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+ ac_prev=x_libraries ;;
+ -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+ x_libraries="$ac_optarg" ;;
+
+ -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; }
+ ;;
+
+ *)
+ if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then
+ echo "configure: warning: $ac_option: invalid host type" 1>&2
+ fi
+ if test "x$nonopt" != xNONE; then
+ { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; }
+ fi
+ nonopt="$ac_option"
+ ;;
+
+ esac
+done
+
+if test -n "$ac_prev"; then
+ { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; }
+fi
+
+trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
+
+# File descriptor usage:
+# 0 standard input
+# 1 file creation
+# 2 errors and warnings
+# 3 some systems may open it to /dev/tty
+# 4 used on the Kubota Titan
+# 6 checking for... messages and results
+# 5 compiler messages saved in config.log
+if test "$silent" = yes; then
+ exec 6>/dev/null
+else
+ exec 6>&1
+fi
+exec 5>./config.log
+
+echo "\
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+" 1>&5
+
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Also quote any args containing shell metacharacters.
+ac_configure_args=
+for ac_arg
+do
+ case "$ac_arg" in
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c) ;;
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;;
+ *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*)
+ ac_configure_args="$ac_configure_args '$ac_arg'" ;;
+ *) ac_configure_args="$ac_configure_args $ac_arg" ;;
+ esac
+done
+
+# NLS nuisances.
+# Only set these to C if already set. These must not be set unconditionally
+# because not all systems understand e.g. LANG=C (notably SCO).
+# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'!
+# Non-C LC_CTYPE values break the ctype check.
+if test "${LANG+set}" = set; then LANG=C; export LANG; fi
+if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi
+if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi
+if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -rf conftest* confdefs.h
+# AIX cpp loses on an empty file, so make sure it contains at least a newline.
+echo > confdefs.h
+
+# A filename unique to this package, relative to the directory that
+# configure is in, which we can look for to find out if srcdir is correct.
+ac_unique_file=gdbserve.c
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+ ac_srcdir_defaulted=yes
+ # Try the directory containing this script, then its parent.
+ ac_prog=$0
+ ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'`
+ test "x$ac_confdir" = "x$ac_prog" && ac_confdir=.
+ srcdir=$ac_confdir
+ if test ! -r $srcdir/$ac_unique_file; then
+ srcdir=..
+ fi
+else
+ ac_srcdir_defaulted=no
+fi
+if test ! -r $srcdir/$ac_unique_file; then
+ if test "$ac_srcdir_defaulted" = yes; then
+ { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; }
+ else
+ { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; }
+ fi
+fi
+srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'`
+
+# Prefer explicitly selected file to automatically selected ones.
+if test -z "$CONFIG_SITE"; then
+ if test "x$prefix" != xNONE; then
+ CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site"
+ else
+ CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
+ fi
+fi
+for ac_site_file in $CONFIG_SITE; do
+ if test -r "$ac_site_file"; then
+ echo "loading site script $ac_site_file"
+ . "$ac_site_file"
+ fi
+done
+
+if test -r "$cache_file"; then
+ echo "loading cache $cache_file"
+ . $cache_file
+else
+ echo "creating cache $cache_file"
+ > $cache_file
+fi
+
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+ac_exeext=
+ac_objext=o
+if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then
+ # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu.
+ if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then
+ ac_n= ac_c='
+' ac_t=' '
+ else
+ ac_n=-n ac_c= ac_t=
+ fi
+else
+ ac_n= ac_c='\c' ac_t=
+fi
+
+
+
+ac_aux_dir=
+for ac_dir in `cd $srcdir;pwd`/../.. $srcdir/`cd $srcdir;pwd`/../..; do
+ if test -f $ac_dir/install-sh; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install-sh -c"
+ break
+ elif test -f $ac_dir/install.sh; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install.sh -c"
+ break
+ fi
+done
+if test -z "$ac_aux_dir"; then
+ { echo "configure: error: can not find install-sh or install.sh in `cd $srcdir;pwd`/../.. $srcdir/`cd $srcdir;pwd`/../.." 1>&2; exit 1; }
+fi
+ac_config_guess=$ac_aux_dir/config.guess
+ac_config_sub=$ac_aux_dir/config.sub
+ac_configure=$ac_aux_dir/configure # This should be Cygnus configure.
+
+
+# Do some error checking and defaulting for the host and target type.
+# The inputs are:
+# configure --host=HOST --target=TARGET --build=BUILD NONOPT
+#
+# The rules are:
+# 1. You are not allowed to specify --host, --target, and nonopt at the
+# same time.
+# 2. Host defaults to nonopt.
+# 3. If nonopt is not specified, then host defaults to the current host,
+# as determined by config.guess.
+# 4. Target and build default to nonopt.
+# 5. If nonopt is not specified, then target and build default to host.
+
+# The aliases save the names the user supplied, while $host etc.
+# will get canonicalized.
+case $host---$target---$nonopt in
+NONE---*---* | *---NONE---* | *---*---NONE) ;;
+*) { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; } ;;
+esac
+
+
+# Make sure we can run config.sub.
+if ${CONFIG_SHELL-/bin/sh} $ac_config_sub sun4 >/dev/null 2>&1; then :
+else { echo "configure: error: can not run $ac_config_sub" 1>&2; exit 1; }
+fi
+
+echo $ac_n "checking host system type""... $ac_c" 1>&6
+echo "configure:573: checking host system type" >&5
+
+host_alias=$host
+case "$host_alias" in
+NONE)
+ case $nonopt in
+ NONE)
+ if host_alias=`${CONFIG_SHELL-/bin/sh} $ac_config_guess`; then :
+ else { echo "configure: error: can not guess host type; you must specify one" 1>&2; exit 1; }
+ fi ;;
+ *) host_alias=$nonopt ;;
+ esac ;;
+esac
+
+host=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $host_alias`
+host_cpu=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+host_vendor=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+host_os=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+echo "$ac_t""$host" 1>&6
+
+echo $ac_n "checking target system type""... $ac_c" 1>&6
+echo "configure:594: checking target system type" >&5
+
+target_alias=$target
+case "$target_alias" in
+NONE)
+ case $nonopt in
+ NONE) target_alias=$host_alias ;;
+ *) target_alias=$nonopt ;;
+ esac ;;
+esac
+
+target=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $target_alias`
+target_cpu=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+target_vendor=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+target_os=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+echo "$ac_t""$target" 1>&6
+
+echo $ac_n "checking build system type""... $ac_c" 1>&6
+echo "configure:612: checking build system type" >&5
+
+build_alias=$build
+case "$build_alias" in
+NONE)
+ case $nonopt in
+ NONE) build_alias=$host_alias ;;
+ *) build_alias=$nonopt ;;
+ esac ;;
+esac
+
+build=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $build_alias`
+build_cpu=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+build_vendor=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+build_os=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+echo "$ac_t""$build" 1>&6
+
+test "$host_alias" != "$target_alias" &&
+ test "$program_prefix$program_suffix$program_transform_name" = \
+ NONENONEs,x,x, &&
+ program_prefix=${target_alias}-
+
+if test "$program_transform_name" = s,x,x,; then
+ program_transform_name=
+else
+ # Double any \ or $. echo might interpret backslashes.
+ cat <<\EOF_SED > conftestsed
+s,\\,\\\\,g; s,\$,$$,g
+EOF_SED
+ program_transform_name="`echo $program_transform_name|sed -f conftestsed`"
+ rm -f conftestsed
+fi
+test "$program_prefix" != NONE &&
+ program_transform_name="s,^,${program_prefix},; $program_transform_name"
+# Use a double $ so make ignores it.
+test "$program_suffix" != NONE &&
+ program_transform_name="s,\$\$,${program_suffix},; $program_transform_name"
+
+# sed with no file args requires a program.
+test "$program_transform_name" = "" && program_transform_name="s,x,x,"
+
+
+# Find a good install program. We prefer a C program (faster),
+# so one script is as good as another. But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# ./install, which can be erroneously created by make from ./install.sh.
+echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6
+echo "configure:666: checking for a BSD compatible install" >&5
+if test -z "$INSTALL"; then
+if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ IFS="${IFS= }"; ac_save_IFS="$IFS"; IFS=":"
+ for ac_dir in $PATH; do
+ # Account for people who put trailing slashes in PATH elements.
+ case "$ac_dir/" in
+ /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;;
+ *)
+ # OSF1 and SCO ODT 3.0 have their own names for install.
+ # Don't use installbsd from OSF since it installs stuff as root
+ # by default.
+ for ac_prog in ginstall scoinst install; do
+ if test -f $ac_dir/$ac_prog; then
+ if test $ac_prog = install &&
+ grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then
+ # AIX install. It has an incompatible calling convention.
+ :
+ else
+ ac_cv_path_install="$ac_dir/$ac_prog -c"
+ break 2
+ fi
+ fi
+ done
+ ;;
+ esac
+ done
+ IFS="$ac_save_IFS"
+
+fi
+ if test "${ac_cv_path_install+set}" = set; then
+ INSTALL="$ac_cv_path_install"
+ else
+ # As a last resort, use the slow shell script. We don't cache a
+ # path for INSTALL within a source directory, because that will
+ # break other packages using the cache if that directory is
+ # removed, or if the path is relative.
+ INSTALL="$ac_install_sh"
+ fi
+fi
+echo "$ac_t""$INSTALL" 1>&6
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+
+# Map target cpu into the config cpu subdirectory name.
+# The default is $target_cpu.
+case "${target_cpu}" in
+alpha) gdb_target_cpu=alpha ;;
+c[12]) gdb_target_cpu=convex ;;
+hppa*) gdb_target_cpu=pa ;;
+i[3456]86) gdb_target_cpu=i386 ;;
+m68*) gdb_target_cpu=m68k ;;
+np1) gdb_target_cpu=gould ;;
+pn) gdb_target_cpu=gould ;;
+pyramid) gdb_target_cpu=pyr ;;
+sparc*) gdb_target_cpu=sparc ;;
+*) gdb_target_cpu=$target_cpu ;;
+esac
+
+target_makefile_frag=${srcdir}/../config/${gdb_target_cpu}/gdbserve.mt
+if ! -f ${target_makefile_frag} ; then
+ { echo "configure: error: "*** GDBSERVE does not support target ${target}"" 1>&2; exit 1; }
+fi
+
+target_makefile_frag_path=$target_makefile_frag
+
+
+
+cpufile=`sed -n '
+s/CPU_FILE *= *\(^ *\)/\1/p
+' ${target_makefile_frag}
+
+files=
+links=
+rm -f cpu.h
+if "${cpufile}" != "" ; then
+ files="${files} ${cpufile}.h"
+ links="${links} cpu.h"
+fi
+
+
+trap '' 1 2 15
+cat > confcache <<\EOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs. It is not useful on other systems.
+# If it contains results you don't want to keep, you may remove or edit it.
+#
+# By default, configure uses ./config.cache as the cache file,
+# creating it if it does not exist already. You can give configure
+# the --cache-file=FILE option to use a different cache file; that is
+# what configure does when it calls configure scripts in
+# subdirectories, so they share the cache.
+# Giving --cache-file=/dev/null disables caching, for debugging configure.
+# config.status only pays attention to the cache file if you give it the
+# --recheck option to rerun configure.
+#
+EOF
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, don't put newlines in cache variables' values.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(set) 2>&1 |
+ case `(ac_space=' '; set) 2>&1 | grep ac_space` in
+ *ac_space=\ *)
+ # `set' does not quote correctly, so add quotes (double-quote substitution
+ # turns \\\\ into \\, and sed turns \\ into \).
+ sed -n \
+ -e "s/'/'\\\\''/g" \
+ -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p"
+ ;;
+ *)
+ # `set' quotes correctly as required by POSIX, so do not add quotes.
+ sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p'
+ ;;
+ esac >> confcache
+if cmp -s $cache_file confcache; then
+ :
+else
+ if test -w $cache_file; then
+ echo "updating cache $cache_file"
+ cat confcache > $cache_file
+ else
+ echo "not updating unwritable cache $cache_file"
+ fi
+fi
+rm -f confcache
+
+trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+# Any assignment to VPATH causes Sun make to only execute
+# the first set of double-colon rules, so remove it if not needed.
+# If there is a colon in the path, we need to keep it.
+if test "x$srcdir" = x.; then
+ ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d'
+fi
+
+trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15
+
+# Transform confdefs.h into DEFS.
+# Protect against shell expansion while executing Makefile rules.
+# Protect against Makefile macro expansion.
+cat > conftest.defs <<\EOF
+s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%-D\1=\2%g
+s%[ `~#$^&*(){}\\|;'"<>?]%\\&%g
+s%\[%\\&%g
+s%\]%\\&%g
+s%\$%$$%g
+EOF
+DEFS=`sed -f conftest.defs confdefs.h | tr '\012' ' '`
+rm -f conftest.defs
+
+
+# Without the "./", some shells look in PATH for config.status.
+: ${CONFIG_STATUS=./config.status}
+
+echo creating $CONFIG_STATUS
+rm -f $CONFIG_STATUS
+cat > $CONFIG_STATUS <<EOF
+#! /bin/sh
+# Generated automatically by configure.
+# Run this file to recreate the current configuration.
+# This directory was configured as follows,
+# on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+#
+# $0 $ac_configure_args
+#
+# Compiler output produced by configure, useful for debugging
+# configure, is in ./config.log if it exists.
+
+ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]"
+for ac_option
+do
+ case "\$ac_option" in
+ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+ echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion"
+ exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;;
+ -version | --version | --versio | --versi | --vers | --ver | --ve | --v)
+ echo "$CONFIG_STATUS generated by autoconf version 2.12.2"
+ exit 0 ;;
+ -help | --help | --hel | --he | --h)
+ echo "\$ac_cs_usage"; exit 0 ;;
+ *) echo "\$ac_cs_usage"; exit 1 ;;
+ esac
+done
+
+ac_given_srcdir=$srcdir
+ac_given_INSTALL="$INSTALL"
+
+trap 'rm -fr `echo "Makefile" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15
+EOF
+cat >> $CONFIG_STATUS <<EOF
+
+# Protect against being on the right side of a sed subst in config.status.
+sed 's/%@/@@/; s/@%/@@/; s/%g\$/@g/; /@g\$/s/[\\\\&%]/\\\\&/g;
+ s/@@/%@/; s/@@/@%/; s/@g\$/%g/' > conftest.subs <<\\CEOF
+$ac_vpsub
+$extrasub
+s%@SHELL@%$SHELL%g
+s%@CFLAGS@%$CFLAGS%g
+s%@CPPFLAGS@%$CPPFLAGS%g
+s%@CXXFLAGS@%$CXXFLAGS%g
+s%@DEFS@%$DEFS%g
+s%@LDFLAGS@%$LDFLAGS%g
+s%@LIBS@%$LIBS%g
+s%@exec_prefix@%$exec_prefix%g
+s%@prefix@%$prefix%g
+s%@program_transform_name@%$program_transform_name%g
+s%@bindir@%$bindir%g
+s%@sbindir@%$sbindir%g
+s%@libexecdir@%$libexecdir%g
+s%@datadir@%$datadir%g
+s%@sysconfdir@%$sysconfdir%g
+s%@sharedstatedir@%$sharedstatedir%g
+s%@localstatedir@%$localstatedir%g
+s%@libdir@%$libdir%g
+s%@includedir@%$includedir%g
+s%@oldincludedir@%$oldincludedir%g
+s%@infodir@%$infodir%g
+s%@mandir@%$mandir%g
+s%@host@%$host%g
+s%@host_alias@%$host_alias%g
+s%@host_cpu@%$host_cpu%g
+s%@host_vendor@%$host_vendor%g
+s%@host_os@%$host_os%g
+s%@target@%$target%g
+s%@target_alias@%$target_alias%g
+s%@target_cpu@%$target_cpu%g
+s%@target_vendor@%$target_vendor%g
+s%@target_os@%$target_os%g
+s%@build@%$build%g
+s%@build_alias@%$build_alias%g
+s%@build_cpu@%$build_cpu%g
+s%@build_vendor@%$build_vendor%g
+s%@build_os@%$build_os%g
+s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g
+s%@INSTALL_DATA@%$INSTALL_DATA%g
+s%@target_makefile_frag_path@%$target_makefile_frag_path%g
+/@target_makefile_frag@/r $target_makefile_frag
+s%@target_makefile_frag@%%g
+
+CEOF
+EOF
+
+cat >> $CONFIG_STATUS <<\EOF
+
+# Split the substitutions into bite-sized pieces for seds with
+# small command number limits, like on Digital OSF/1 and HP-UX.
+ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script.
+ac_file=1 # Number of current file.
+ac_beg=1 # First line for current file.
+ac_end=$ac_max_sed_cmds # Line after last line for current file.
+ac_more_lines=:
+ac_sed_cmds=""
+while $ac_more_lines; do
+ if test $ac_beg -gt 1; then
+ sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file
+ else
+ sed "${ac_end}q" conftest.subs > conftest.s$ac_file
+ fi
+ if test ! -s conftest.s$ac_file; then
+ ac_more_lines=false
+ rm -f conftest.s$ac_file
+ else
+ if test -z "$ac_sed_cmds"; then
+ ac_sed_cmds="sed -f conftest.s$ac_file"
+ else
+ ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file"
+ fi
+ ac_file=`expr $ac_file + 1`
+ ac_beg=$ac_end
+ ac_end=`expr $ac_end + $ac_max_sed_cmds`
+ fi
+done
+if test -z "$ac_sed_cmds"; then
+ ac_sed_cmds=cat
+fi
+EOF
+
+cat >> $CONFIG_STATUS <<EOF
+
+CONFIG_FILES=\${CONFIG_FILES-"Makefile"}
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then
+ # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+ case "$ac_file" in
+ *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'`
+ ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
+ *) ac_file_in="${ac_file}.in" ;;
+ esac
+
+ # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories.
+
+ # Remove last slash and all that follows it. Not all systems have dirname.
+ ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
+ if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
+ # The file is in a subdirectory.
+ test ! -d "$ac_dir" && mkdir "$ac_dir"
+ ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`"
+ # A "../" for each directory in $ac_dir_suffix.
+ ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'`
+ else
+ ac_dir_suffix= ac_dots=
+ fi
+
+ case "$ac_given_srcdir" in
+ .) srcdir=.
+ if test -z "$ac_dots"; then top_srcdir=.
+ else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;;
+ /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;;
+ *) # Relative path.
+ srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix"
+ top_srcdir="$ac_dots$ac_given_srcdir" ;;
+ esac
+
+ case "$ac_given_INSTALL" in
+ [/$]*) INSTALL="$ac_given_INSTALL" ;;
+ *) INSTALL="$ac_dots$ac_given_INSTALL" ;;
+ esac
+
+ echo creating "$ac_file"
+ rm -f "$ac_file"
+ configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure."
+ case "$ac_file" in
+ *Makefile*) ac_comsub="1i\\
+# $configure_input" ;;
+ *) ac_comsub= ;;
+ esac
+
+ ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"`
+ sed -e "$ac_comsub
+s%@configure_input@%$configure_input%g
+s%@srcdir@%$srcdir%g
+s%@top_srcdir@%$top_srcdir%g
+s%@INSTALL@%$INSTALL%g
+" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file
+fi; done
+rm -f conftest.s*
+
+EOF
+
+cat >> $CONFIG_STATUS <<EOF
+ac_sources="$files"
+ac_dests="$links"
+EOF
+
+cat >> $CONFIG_STATUS <<\EOF
+srcdir=$ac_given_srcdir
+while test -n "$ac_sources"; do
+ set $ac_dests; ac_dest=$1; shift; ac_dests=$*
+ set $ac_sources; ac_source=$1; shift; ac_sources=$*
+
+ echo "linking $srcdir/$ac_source to $ac_dest"
+
+ if test ! -r $srcdir/$ac_source; then
+ { echo "configure: error: $srcdir/$ac_source: File not found" 1>&2; exit 1; }
+ fi
+ rm -f $ac_dest
+
+ # Make relative symlinks.
+ # Remove last slash and all that follows it. Not all systems have dirname.
+ ac_dest_dir=`echo $ac_dest|sed 's%/[^/][^/]*$%%'`
+ if test "$ac_dest_dir" != "$ac_dest" && test "$ac_dest_dir" != .; then
+ # The dest file is in a subdirectory.
+ test ! -d "$ac_dest_dir" && mkdir "$ac_dest_dir"
+ ac_dest_dir_suffix="/`echo $ac_dest_dir|sed 's%^\./%%'`"
+ # A "../" for each directory in $ac_dest_dir_suffix.
+ ac_dots=`echo $ac_dest_dir_suffix|sed 's%/[^/]*%../%g'`
+ else
+ ac_dest_dir_suffix= ac_dots=
+ fi
+
+ case "$srcdir" in
+ [/$]*) ac_rel_source="$srcdir/$ac_source" ;;
+ *) ac_rel_source="$ac_dots$srcdir/$ac_source" ;;
+ esac
+
+ # Make a symlink if possible; otherwise try a hard link.
+ if ln -s $ac_rel_source $ac_dest 2>/dev/null ||
+ ln $srcdir/$ac_source $ac_dest; then :
+ else
+ { echo "configure: error: can not link $ac_dest to $srcdir/$ac_source" 1>&2; exit 1; }
+ fi
+done
+EOF
+cat >> $CONFIG_STATUS <<EOF
+
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+
+exit 0
+EOF
+chmod +x $CONFIG_STATUS
+rm -fr confdefs* $ac_clean_files
+test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1
+
+
diff --git a/gdb/nlm/configure.in b/gdb/nlm/configure.in
new file mode 100644
index 00000000000..845b486e524
--- /dev/null
+++ b/gdb/nlm/configure.in
@@ -0,0 +1,55 @@
+dnl Process this file with autoconf to produce a configure script.
+AC_PREREQ(2.12.1)dnl
+AC_INIT(gdbserve.c)
+
+AC_CONFIG_AUX_DIR(`cd $srcdir;pwd`/../..)
+AC_CANONICAL_SYSTEM
+AC_ARG_PROGRAM
+
+AC_PROG_INSTALL
+
+# Map target cpu into the config cpu subdirectory name.
+# The default is $target_cpu.
+changequote(,)dnl
+case "${target_cpu}" in
+alpha) gdb_target_cpu=alpha ;;
+c[12]) gdb_target_cpu=convex ;;
+hppa*) gdb_target_cpu=pa ;;
+i[3456]86) gdb_target_cpu=i386 ;;
+m68*) gdb_target_cpu=m68k ;;
+np1) gdb_target_cpu=gould ;;
+pn) gdb_target_cpu=gould ;;
+pyramid) gdb_target_cpu=pyr ;;
+sparc*) gdb_target_cpu=sparc ;;
+*) gdb_target_cpu=$target_cpu ;;
+esac
+changequote([,])dnl
+
+target_makefile_frag=${srcdir}/../config/${gdb_target_cpu}/gdbserve.mt
+if [ ! -f ${target_makefile_frag} ]; then
+ AC_MSG_ERROR("*** GDBSERVE does not support target ${target}")
+fi
+
+dnl We have to assign the same value to other variables because autoconf
+dnl doesn't provide a mechanism to substitute a replacement keyword with
+dnl arbitrary data or pathnames.
+dnl
+target_makefile_frag_path=$target_makefile_frag
+AC_SUBST(target_makefile_frag_path)
+AC_SUBST_FILE(target_makefile_frag)
+
+cpufile=`sed -n '
+s/CPU_FILE[ ]*=[ ]*\([^ ]*\)/\1/p
+' ${target_makefile_frag}
+
+files=
+links=
+rm -f cpu.h
+if [ "${cpufile}" != "" ]; then
+ files="${files} ${cpufile}.h"
+ links="${links} cpu.h"
+fi
+
+AC_LINK_FILES($files, $links)
+AC_OUTPUT(Makefile)
+
diff --git a/gdb/nlm/gdbserve.c b/gdb/nlm/gdbserve.c
new file mode 100644
index 00000000000..62adf3a8d1b
--- /dev/null
+++ b/gdb/nlm/gdbserve.c
@@ -0,0 +1,1056 @@
+/* gdbserve.c -- NLM debugging stub for Novell NetWare.
+
+ This is originally based on an m68k software stub written by Glenn
+ Engel at HP, but has changed quite a bit. It was modified for the
+ i386 by Jim Kingdon, Cygnus Support. It was modified to run under
+ NetWare by Ian Lance Taylor, Cygnus Support.
+
+ This code is intended to produce an NLM (a NetWare Loadable Module)
+ to run under Novell NetWare. To create the NLM, compile this code
+ into an object file using the NLM SDK on any i386 host, and use the
+ nlmconv program (available in the GNU binutils) to transform the
+ resulting object file into an NLM. */
+
+/****************************************************************************
+
+ THIS SOFTWARE IS NOT COPYRIGHTED
+
+ HP offers the following for use in the public domain. HP makes no
+ warranty with regard to the software or it's performance and the
+ user accepts the software "AS IS" with all faults.
+
+ HP DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD
+ TO THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+
+****************************************************************************/
+
+/****************************************************************************
+ *
+ * The following gdb commands are supported:
+ *
+ * command function Return value
+ *
+ * g return the value of the CPU registers hex data or ENN
+ * G set the value of the CPU registers OK or ENN
+ *
+ * mAA..AA,LLLL Read LLLL bytes at address AA..AA hex data or ENN
+ * MAA..AA,LLLL: Write LLLL bytes at address AA.AA OK or ENN
+ *
+ * c Resume at current address SNN ( signal NN)
+ * cAA..AA Continue at address AA..AA SNN
+ *
+ * s Step one instruction SNN
+ * sAA..AA Step one instruction from AA..AA SNN
+ *
+ * k kill
+ *
+ * ? What was the last sigval ? SNN (signal NN)
+ *
+ * All commands and responses are sent with a packet which includes a
+ * checksum. A packet consists of
+ *
+ * $<packet info>#<checksum>.
+ *
+ * where
+ * <packet info> :: <characters representing the command or response>
+ * <checksum> :: < two hex digits computed as modulo 256 sum of <packetinfo>>
+ *
+ * When a packet is received, it is first acknowledged with either '+' or '-'.
+ * '+' indicates a successful transfer. '-' indicates a failed transfer.
+ *
+ * Example:
+ *
+ * Host: Reply:
+ * $m0,10#2a +$00010203040506070809101112131415#42
+ *
+ ****************************************************************************/
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <errno.h>
+#include <time.h>
+
+#ifdef __i386__
+#include <dfs.h>
+#include <conio.h>
+#include <advanced.h>
+#include <debugapi.h>
+#include <process.h>
+#else
+#include <nwtypes.h>
+#include <nwdfs.h>
+#include <nwconio.h>
+#include <nwadv.h>
+#include <nwdbgapi.h>
+#include <nwthread.h>
+#endif
+
+#include <aio.h>
+#include "cpu.h"
+
+
+/****************************************************/
+/* This information is from Novell. It is not in any of the standard
+ NetWare header files. */
+
+struct DBG_LoadDefinitionStructure
+{
+ void *reserved1[4];
+ LONG reserved5;
+ LONG LDCodeImageOffset;
+ LONG LDCodeImageLength;
+ LONG LDDataImageOffset;
+ LONG LDDataImageLength;
+ LONG LDUninitializedDataLength;
+ LONG LDCustomDataOffset;
+ LONG LDCustomDataSize;
+ LONG reserved6[2];
+ LONG (*LDInitializationProcedure)(void);
+};
+
+#define LO_NORMAL 0x0000
+#define LO_STARTUP 0x0001
+#define LO_PROTECT 0x0002
+#define LO_DEBUG 0x0004
+#define LO_AUTO_LOAD 0x0008
+
+/* Loader returned error codes */
+#define LOAD_COULD_NOT_FIND_FILE 1
+#define LOAD_ERROR_READING_FILE 2
+#define LOAD_NOT_NLM_FILE_FORMAT 3
+#define LOAD_WRONG_NLM_FILE_VERSION 4
+#define LOAD_REENTRANT_INITIALIZE_FAILURE 5
+#define LOAD_CAN_NOT_LOAD_MULTIPLE_COPIES 6
+#define LOAD_ALREADY_IN_PROGRESS 7
+#define LOAD_NOT_ENOUGH_MEMORY 8
+#define LOAD_INITIALIZE_FAILURE 9
+#define LOAD_INCONSISTENT_FILE_FORMAT 10
+#define LOAD_CAN_NOT_LOAD_AT_STARTUP 11
+#define LOAD_AUTO_LOAD_MODULES_NOT_LOADED 12
+#define LOAD_UNRESOLVED_EXTERNAL 13
+#define LOAD_PUBLIC_ALREADY_DEFINED 14
+/****************************************************/
+
+/* The main thread ID. */
+static int mainthread;
+
+/* An error message for the main thread to print. */
+static char *error_message;
+
+/* The AIO port handle. */
+static int AIOhandle;
+
+/* BUFMAX defines the maximum number of characters in inbound/outbound
+ buffers. At least NUMREGBYTES*2 are needed for register packets */
+#define BUFMAX (REGISTER_BYTES * 2 + 16)
+
+/* remote_debug > 0 prints ill-formed commands in valid packets and
+ checksum errors. */
+static int remote_debug = 1;
+
+static const char hexchars[] = "0123456789abcdef";
+
+unsigned char breakpoint_insn[] = BREAKPOINT;
+
+char *mem2hex (void *mem, char *buf, int count, int may_fault);
+char *hex2mem (char *buf, void *mem, int count, int may_fault);
+extern void set_step_traps (struct StackFrame *);
+extern void clear_step_traps (struct StackFrame *);
+
+static int __main() {};
+
+/* Read a character from the serial port. This must busy wait, but
+ that's OK because we will be the only thread running anyhow. */
+
+static int
+getDebugChar ()
+{
+ int err;
+ LONG got;
+ unsigned char ret;
+
+ do
+ {
+ err = AIOReadData (AIOhandle, (char *) &ret, 1, &got);
+ if (err != 0)
+ {
+ error_message = "AIOReadData failed";
+ ResumeThread (mainthread);
+ return -1;
+ }
+ }
+ while (got == 0);
+
+ return ret;
+}
+
+/* Write a character to the serial port. Returns 0 on failure,
+ non-zero on success. */
+
+static int
+putDebugChar (c)
+ unsigned char c;
+{
+ int err;
+ LONG put;
+
+ put = 0;
+ while (put < 1)
+ {
+ err = AIOWriteData (AIOhandle, (char *) &c, 1, &put);
+ if (err != 0)
+ ConsolePrintf ("AIOWriteData: err = %d, put = %d\r\n", err, put);
+ }
+ return 1;
+}
+
+/* Turn a hex character into a number. */
+
+static int
+hex (ch)
+ char ch;
+{
+ if ((ch >= 'a') && (ch <= 'f'))
+ return (ch-'a'+10);
+ if ((ch >= '0') && (ch <= '9'))
+ return (ch-'0');
+ if ((ch >= 'A') && (ch <= 'F'))
+ return (ch-'A'+10);
+ return (-1);
+}
+
+/* Scan for the sequence $<data>#<checksum>. Returns 0 on failure,
+ non-zero on success. */
+
+static int
+getpacket (buffer)
+ char * buffer;
+{
+ unsigned char checksum;
+ unsigned char xmitcsum;
+ int i;
+ int count;
+ int ch;
+
+ do
+ {
+ /* wait around for the start character, ignore all other characters */
+ while ((ch = getDebugChar()) != '$')
+ if (ch == -1)
+ return 0;
+ checksum = 0;
+ xmitcsum = -1;
+
+ count = 0;
+
+ /* now, read until a # or end of buffer is found */
+ while (count < BUFMAX)
+ {
+ ch = getDebugChar();
+ if (ch == -1)
+ return 0;
+ if (ch == '#')
+ break;
+ checksum = checksum + ch;
+ buffer[count] = ch;
+ count = count + 1;
+ }
+ buffer[count] = 0;
+
+ if (ch == '#')
+ {
+ ch = getDebugChar ();
+ if (ch == -1)
+ return 0;
+ xmitcsum = hex(ch) << 4;
+ ch = getDebugChar ();
+ if (ch == -1)
+ return 0;
+ xmitcsum += hex(ch);
+
+ if (checksum != xmitcsum)
+ {
+ if (remote_debug)
+ ConsolePrintf ("bad checksum. My count = 0x%x, sent=0x%x. buf=%s\n",
+ checksum,xmitcsum,buffer);
+ /* failed checksum */
+ if (! putDebugChar('-'))
+ return 0;
+ return 1;
+ }
+ else
+ {
+ /* successful transfer */
+ if (! putDebugChar('+'))
+ return 0;
+ /* if a sequence char is present, reply the sequence ID */
+ if (buffer[2] == ':')
+ {
+ if (! putDebugChar (buffer[0])
+ || ! putDebugChar (buffer[1]))
+ return 0;
+ /* remove sequence chars from buffer */
+ count = strlen(buffer);
+ for (i=3; i <= count; i++)
+ buffer[i-3] = buffer[i];
+ }
+ }
+ }
+ }
+ while (checksum != xmitcsum);
+
+ if (remote_debug)
+ ConsolePrintf ("Received packet \"%s\"\r\n", buffer);
+
+ return 1;
+}
+
+/* Send the packet in buffer. Returns 0 on failure, non-zero on
+ success. */
+
+static int
+putpacket (buffer)
+ char * buffer;
+{
+ unsigned char checksum;
+ int count;
+ int ch;
+
+ if (remote_debug)
+ ConsolePrintf ("Sending packet \"%s\"\r\n", buffer);
+
+ /* $<packet info>#<checksum>. */
+ do
+ {
+ if (! putDebugChar('$'))
+ return 0;
+ checksum = 0;
+ count = 0;
+
+ while (ch=buffer[count])
+ {
+ if (! putDebugChar(ch))
+ return 0;
+ checksum += ch;
+ count += 1;
+ }
+
+ if (! putDebugChar('#')
+ || ! putDebugChar(hexchars[checksum >> 4])
+ || ! putDebugChar(hexchars[checksum % 16]))
+ return 0;
+
+ ch = getDebugChar ();
+ if (ch == -1)
+ return 0;
+ }
+ while (ch != '+');
+
+ return 1;
+}
+
+static char remcomInBuffer[BUFMAX];
+static char remcomOutBuffer[BUFMAX];
+static short error;
+
+static void
+debug_error (format, parm)
+ char *format;
+ char *parm;
+{
+ if (remote_debug)
+ {
+ ConsolePrintf (format, parm);
+ ConsolePrintf ("\n");
+ }
+}
+
+/* This is set if we could get a memory access fault. */
+static int mem_may_fault;
+
+/* Indicate to caller of mem2hex or hex2mem that there has been an
+ error. */
+volatile int mem_err = 0;
+
+#ifndef ALTERNATE_MEM_FUNCS
+/* These are separate functions so that they are so short and sweet
+ that the compiler won't save any registers (if there is a fault
+ to mem_fault, they won't get restored, so there better not be any
+ saved). */
+
+int
+get_char (addr)
+ char *addr;
+{
+ return *addr;
+}
+
+void
+set_char (addr, val)
+ char *addr;
+ int val;
+{
+ *addr = val;
+}
+#endif /* ALTERNATE_MEM_FUNCS */
+
+/* convert the memory pointed to by mem into hex, placing result in buf */
+/* return a pointer to the last char put in buf (null) */
+/* If MAY_FAULT is non-zero, then we should set mem_err in response to
+ a fault; if zero treat a fault like any other fault in the stub. */
+
+char *
+mem2hex (mem, buf, count, may_fault)
+ void *mem;
+ char *buf;
+ int count;
+ int may_fault;
+{
+ int i;
+ unsigned char ch;
+ char *ptr = mem;
+
+ mem_may_fault = may_fault;
+ for (i = 0; i < count; i++)
+ {
+ ch = get_char (ptr++);
+ if (may_fault && mem_err)
+ return (buf);
+ *buf++ = hexchars[ch >> 4];
+ *buf++ = hexchars[ch % 16];
+ }
+ *buf = 0;
+ mem_may_fault = 0;
+ return(buf);
+}
+
+/* convert the hex array pointed to by buf into binary to be placed in mem */
+/* return a pointer to the character AFTER the last byte written */
+
+char *
+hex2mem (buf, mem, count, may_fault)
+ char *buf;
+ void *mem;
+ int count;
+ int may_fault;
+{
+ int i;
+ unsigned char ch;
+ char *ptr = mem;
+
+ mem_may_fault = may_fault;
+ for (i=0;i<count;i++)
+ {
+ ch = hex(*buf++) << 4;
+ ch = ch + hex(*buf++);
+ set_char (ptr++, ch);
+ if (may_fault && mem_err)
+ return (ptr);
+ }
+ mem_may_fault = 0;
+ return(mem);
+}
+
+/* This function takes the 386 exception vector and attempts to
+ translate this number into a unix compatible signal value. */
+
+int
+computeSignal (exceptionVector)
+ int exceptionVector;
+{
+ int sigval;
+ switch (exceptionVector)
+ {
+ case 0 : sigval = 8; break; /* divide by zero */
+ case 1 : sigval = 5; break; /* debug exception */
+ case 3 : sigval = 5; break; /* breakpoint */
+ case 4 : sigval = 16; break; /* into instruction (overflow) */
+ case 5 : sigval = 16; break; /* bound instruction */
+ case 6 : sigval = 4; break; /* Invalid opcode */
+ case 7 : sigval = 8; break; /* coprocessor not available */
+ case 8 : sigval = 7; break; /* double fault */
+ case 9 : sigval = 11; break; /* coprocessor segment overrun */
+ case 10 : sigval = 11; break; /* Invalid TSS */
+ case 11 : sigval = 11; break; /* Segment not present */
+ case 12 : sigval = 11; break; /* stack exception */
+ case 13 : sigval = 11; break; /* general protection */
+ case 14 : sigval = 11; break; /* page fault */
+ case 16 : sigval = 7; break; /* coprocessor error */
+ default:
+ sigval = 7; /* "software generated"*/
+ }
+ return (sigval);
+}
+
+/**********************************************/
+/* WHILE WE FIND NICE HEX CHARS, BUILD AN INT */
+/* RETURN NUMBER OF CHARS PROCESSED */
+/**********************************************/
+static int
+hexToInt(ptr, intValue)
+ char **ptr;
+ int *intValue;
+{
+ int numChars = 0;
+ int hexValue;
+
+ *intValue = 0;
+
+ while (**ptr)
+ {
+ hexValue = hex(**ptr);
+ if (hexValue >=0)
+ {
+ *intValue = (*intValue <<4) | hexValue;
+ numChars ++;
+ }
+ else
+ break;
+
+ (*ptr)++;
+ }
+
+ return (numChars);
+}
+
+/* This function does all command processing for interfacing to gdb.
+ It is called whenever an exception occurs in the module being
+ debugged. */
+
+static LONG
+handle_exception (frame)
+ struct StackFrame *frame;
+{
+ int addr, length;
+ char *ptr;
+ static struct DBG_LoadDefinitionStructure *ldinfo = 0;
+ static unsigned char first_insn[BREAKPOINT_SIZE]; /* The first instruction in the program. */
+
+#if 0
+ /* According to some documentation from Novell, the bell sometimes
+ may be ringing at this point. This can be stopped on Netware 4
+ systems by calling the undocumented StopBell() function. */
+
+ StopBell ();
+#endif
+
+ if (remote_debug)
+ {
+ ConsolePrintf ("vector=%d: %s, pc=%08x, thread=%08x\r\n",
+ frame->ExceptionNumber,
+ frame->ExceptionDescription,
+ frame->ExceptionPC,
+ GetThreadID ());
+ }
+
+ switch (frame->ExceptionNumber)
+ {
+ case START_NLM_EVENT:
+ /* If the NLM just started, we record the module load information
+ and the thread ID, and set a breakpoint at the first instruction
+ in the program. */
+
+ ldinfo = ((struct DBG_LoadDefinitionStructure *)
+ frame->ExceptionErrorCode);
+ memcpy (first_insn, ldinfo->LDInitializationProcedure,
+ BREAKPOINT_SIZE);
+ memcpy (ldinfo->LDInitializationProcedure, breakpoint_insn,
+ BREAKPOINT_SIZE);
+ flush_i_cache ();
+ return RETURN_TO_PROGRAM;
+
+ case ENTER_DEBUGGER_EVENT:
+ case KEYBOARD_BREAK_EVENT:
+ /* Pass some events on to the next debugger, in case it will handle
+ them. */
+ return RETURN_TO_NEXT_DEBUGGER;
+
+ case 3: /* Breakpoint */
+ /* After we've reached the initial breakpoint, reset it. */
+ if (frame->ExceptionPC - DECR_PC_AFTER_BREAK == (LONG) ldinfo->LDInitializationProcedure
+ && memcmp (ldinfo->LDInitializationProcedure, breakpoint_insn,
+ BREAKPOINT_SIZE) == 0)
+ {
+ memcpy (ldinfo->LDInitializationProcedure, first_insn,
+ BREAKPOINT_SIZE);
+ frame->ExceptionPC -= DECR_PC_AFTER_BREAK;
+ flush_i_cache ();
+ }
+ /* Normal breakpoints end up here */
+ do_status (remcomOutBuffer, frame);
+ break;
+
+ default:
+ /* At the moment, we don't care about most of the unusual NetWare
+ exceptions. */
+ if (frame->ExceptionNumber > 31)
+ return RETURN_TO_PROGRAM;
+
+ /* Most machine level exceptions end up here */
+ do_status (remcomOutBuffer, frame);
+ break;
+
+ case 11: /* Segment not present */
+ case 13: /* General protection */
+ case 14: /* Page fault */
+ /* If we get a GP fault, and mem_may_fault is set, and the
+ instruction pointer is near set_char or get_char, then we caused
+ the fault ourselves accessing an illegal memory location. */
+ if (mem_may_fault
+ && ((frame->ExceptionPC >= (long) &set_char
+ && frame->ExceptionPC < (long) &set_char + 50)
+ || (frame->ExceptionPC >= (long) &get_char
+ && frame->ExceptionPC < (long) &get_char + 50)))
+ {
+ mem_err = 1;
+ /* Point the instruction pointer at an assembly language stub
+ which just returns from the function. */
+
+ frame->ExceptionPC += 4; /* Skip the load or store */
+
+ /* Keep going. This will act as though it returned from
+ set_char or get_char. The calling routine will check
+ mem_err, and do the right thing. */
+ return RETURN_TO_PROGRAM;
+ }
+ /* Random mem fault, report it */
+ do_status (remcomOutBuffer, frame);
+ break;
+
+ case TERMINATE_NLM_EVENT:
+ /* There is no way to get the exit status. */
+ sprintf (remcomOutBuffer, "W%02x", 0);
+ break; /* We generate our own status */
+ }
+
+ /* FIXME: How do we know that this exception has anything to do with
+ the program we are debugging? We can check whether the PC is in
+ the range of the module we are debugging, but that doesn't help
+ much since an error could occur in a library routine. */
+
+ clear_step_traps (frame);
+
+ if (! putpacket(remcomOutBuffer))
+ return RETURN_TO_NEXT_DEBUGGER;
+
+ if (frame->ExceptionNumber == TERMINATE_NLM_EVENT)
+ {
+ ResumeThread (mainthread);
+ return RETURN_TO_PROGRAM;
+ }
+
+ while (1)
+ {
+ error = 0;
+ remcomOutBuffer[0] = 0;
+ if (! getpacket (remcomInBuffer))
+ return RETURN_TO_NEXT_DEBUGGER;
+ switch (remcomInBuffer[0])
+ {
+ case '?':
+ do_status (remcomOutBuffer, frame);
+ break;
+ case 'd':
+ remote_debug = !(remote_debug); /* toggle debug flag */
+ break;
+ case 'g':
+ /* return the value of the CPU registers */
+ frame_to_registers (frame, remcomOutBuffer);
+ break;
+ case 'G':
+ /* set the value of the CPU registers - return OK */
+ registers_to_frame (&remcomInBuffer[1], frame);
+ strcpy(remcomOutBuffer,"OK");
+ break;
+
+ case 'm':
+ /* mAA..AA,LLLL Read LLLL bytes at address AA..AA */
+ /* TRY TO READ %x,%x. IF SUCCEED, SET PTR = 0 */
+ ptr = &remcomInBuffer[1];
+ if (hexToInt(&ptr,&addr))
+ if (*(ptr++) == ',')
+ if (hexToInt(&ptr,&length))
+ {
+ ptr = 0;
+ mem_err = 0;
+ mem2hex((char*) addr, remcomOutBuffer, length, 1);
+ if (mem_err)
+ {
+ strcpy (remcomOutBuffer, "E03");
+ debug_error ("memory fault");
+ }
+ }
+
+ if (ptr)
+ {
+ strcpy(remcomOutBuffer,"E01");
+ debug_error("malformed read memory command: %s",remcomInBuffer);
+ }
+ break;
+
+ case 'M':
+ /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
+ /* TRY TO READ '%x,%x:'. IF SUCCEED, SET PTR = 0 */
+ ptr = &remcomInBuffer[1];
+ if (hexToInt(&ptr,&addr))
+ if (*(ptr++) == ',')
+ if (hexToInt(&ptr,&length))
+ if (*(ptr++) == ':')
+ {
+ mem_err = 0;
+ hex2mem(ptr, (char*) addr, length, 1);
+
+ if (mem_err)
+ {
+ strcpy (remcomOutBuffer, "E03");
+ debug_error ("memory fault");
+ }
+ else
+ {
+ strcpy(remcomOutBuffer,"OK");
+ }
+
+ ptr = 0;
+ }
+ if (ptr)
+ {
+ strcpy(remcomOutBuffer,"E02");
+ debug_error("malformed write memory command: %s",remcomInBuffer);
+ }
+ break;
+
+ case 'c':
+ case 's':
+ /* cAA..AA Continue at address AA..AA(optional) */
+ /* sAA..AA Step one instruction from AA..AA(optional) */
+ /* try to read optional parameter, pc unchanged if no parm */
+ ptr = &remcomInBuffer[1];
+ if (hexToInt(&ptr,&addr))
+ {
+/* registers[PC_REGNUM].lo = addr;*/
+ fprintf (stderr, "Setting PC to 0x%x\n", addr);
+ while (1);
+ }
+
+ if (remcomInBuffer[0] == 's')
+ set_step_traps (frame);
+
+ flush_i_cache ();
+ return RETURN_TO_PROGRAM;
+
+ case 'k':
+ /* kill the program */
+ KillMe (ldinfo);
+ ResumeThread (mainthread);
+ return RETURN_TO_PROGRAM;
+
+ case 'q': /* Query message */
+ if (strcmp (&remcomInBuffer[1], "Offsets") == 0)
+ {
+ sprintf (remcomOutBuffer, "Text=%x;Data=%x;Bss=%x",
+ ldinfo->LDCodeImageOffset,
+ ldinfo->LDDataImageOffset,
+ ldinfo->LDDataImageOffset + ldinfo->LDDataImageLength);
+ }
+ else
+ sprintf (remcomOutBuffer, "E04, Unknown query %s", &remcomInBuffer[1]);
+ break;
+ }
+
+ /* reply to the request */
+ if (! putpacket(remcomOutBuffer))
+ return RETURN_TO_NEXT_DEBUGGER;
+ }
+}
+
+char *progname;
+
+struct bitRate {
+ BYTE bitRate;
+ const char *bitRateString;
+};
+
+struct bitRate bitRateTable[] =
+{
+ { AIO_BAUD_50 , "50" },
+ { AIO_BAUD_75 , "75" },
+ { AIO_BAUD_110 , "110" },
+ { AIO_BAUD_134p5 , "134.5" },
+ { AIO_BAUD_150 , "150" },
+ { AIO_BAUD_300 , "300" },
+ { AIO_BAUD_600 , "600" },
+ { AIO_BAUD_1200 , "1200" },
+ { AIO_BAUD_1800 , "1800" },
+ { AIO_BAUD_2000 , "2000" },
+ { AIO_BAUD_2400 , "2400" },
+ { AIO_BAUD_3600 , "3600" },
+ { AIO_BAUD_4800 , "4800" },
+ { AIO_BAUD_7200 , "7200" },
+ { AIO_BAUD_9600 , "9600" },
+ { AIO_BAUD_19200 , "19200" },
+ { AIO_BAUD_38400 , "38400" },
+ { AIO_BAUD_57600 , "57600" },
+ { AIO_BAUD_115200, "115200" },
+ { -1, NULL }
+};
+
+char dataBitsTable[] = "5678";
+
+char *stopBitsTable[] = { "1", "1.5", "2" };
+
+char parity[] = "NOEMS";
+
+/* Start up. The main thread opens the named serial I/O port, loads
+ the named NLM module and then goes to sleep. The serial I/O port
+ is named as a board number and a port number. It would be more DOS
+ like to provide a menu of available serial ports, but I don't want
+ to have to figure out how to do that. */
+
+int
+main (argc, argv)
+ int argc;
+ char **argv;
+{
+ int hardware, board, port;
+ BYTE bitRate;
+ BYTE dataBits;
+ BYTE stopBits;
+ BYTE parityMode;
+ LONG err;
+ struct debuggerStructure s;
+ int cmdindx;
+ char *cmdlin;
+ int i;
+
+ /* set progname */
+ progname = "gdbserve";
+
+ /* set default serial line */
+ hardware = -1;
+ board = 0;
+ port = 0;
+
+ /* set default serial line characteristics */
+ bitRate = AIO_BAUD_9600;
+ dataBits = AIO_DATA_BITS_8;
+ stopBits = AIO_STOP_BITS_1;
+ parityMode = AIO_PARITY_NONE;
+
+ cmdindx = 0;
+ for (argc--, argv++; *argv; argc--, argv++)
+ {
+ char *bp;
+ char *ep;
+
+ if (strnicmp(*argv, "BAUD=", 5) == 0)
+ {
+ struct bitRate *brp;
+
+ bp = *argv + 5;
+ for (brp = bitRateTable; brp->bitRate != (BYTE) -1; brp++)
+ {
+ if (strcmp(brp->bitRateString, bp) == 0)
+ {
+ bitRate = brp->bitRate;
+ break;
+ }
+ }
+
+ if (brp->bitRateString == NULL)
+ {
+ fprintf(stderr, "%s: %s: unknown or unsupported bit rate",
+ progname, bp);
+ exit (1);
+ }
+ }
+ else if (strnicmp(*argv, "BOARD=", 6) == 0)
+ {
+ bp = *argv + 6;
+ board = strtol (bp, &ep, 0);
+ if (ep == bp || *ep != '\0')
+ {
+ fprintf (stderr, "%s: %s: expected integer argument\n",
+ progname, bp);
+ exit(1);
+ }
+ }
+#if 1 /* FIXME: this option has been depricated */
+ else if (strnicmp(*argv, "NODE=", 5) == 0)
+ {
+ bp = *argv + 5;
+ board = strtol (bp, &ep, 0);
+ if (ep == bp || *ep != '\0')
+ {
+ fprintf (stderr, "%s: %s: expected integer argument\n",
+ progname, bp);
+ exit(1);
+ }
+ }
+#endif
+ else if (strnicmp(*argv, "PORT=", 5) == 0)
+ {
+ bp = *argv + 5;
+ port = strtol (bp, &ep, 0);
+ if (ep == bp || *ep != '\0')
+ {
+ fprintf (stderr, "%s: %s: expected integer argument\n",
+ progname, bp);
+ exit(1);
+ }
+ }
+ else
+ {
+ break;
+ }
+
+ cmdindx++;
+ }
+
+ if (argc == 0)
+ {
+ fprintf (stderr,
+ "Usage: load %s [options] program [arguments]\n", progname);
+ exit (1);
+ }
+
+ err = AIOAcquirePort (&hardware, &board, &port, &AIOhandle);
+ if (err != AIO_SUCCESS)
+ {
+ switch (err)
+ {
+ case AIO_PORT_NOT_AVAILABLE:
+ fprintf (stderr, "Port not available\n");
+ break;
+
+ case AIO_BOARD_NUMBER_INVALID:
+ case AIO_PORT_NUMBER_INVALID:
+ fprintf (stderr, "No such port\n");
+ break;
+
+ default:
+ fprintf (stderr, "Could not open port: %d\n", err);
+ break;
+ }
+
+ exit (1);
+ }
+
+ err = AIOConfigurePort (AIOhandle, bitRate, dataBits, stopBits, parityMode,
+ AIO_HARDWARE_FLOW_CONTROL_OFF);
+
+ if (err == AIO_QUALIFIED_SUCCESS)
+ {
+ AIOPORTCONFIG portConfig;
+
+ fprintf (stderr, "Port configuration changed!\n");
+
+ portConfig.returnLength = sizeof(portConfig);
+ AIOGetPortConfiguration (AIOhandle, &portConfig, NULL);
+
+ fprintf (stderr,
+ " Bit Rate: %s, Data Bits: %c, Stop Bits: %s, Parity: %c,\
+ Flow:%s\n",
+ bitRateTable[portConfig.bitRate].bitRateString,
+ dataBitsTable[portConfig.dataBits],
+ stopBitsTable[portConfig.stopBits],
+ parity[portConfig.parityMode],
+ portConfig.flowCtrlMode ? "ON" : "OFF");
+ }
+ else if (err != AIO_SUCCESS)
+ {
+ fprintf (stderr, "Could not configure port: %d\n", err);
+ AIOReleasePort (AIOhandle);
+ exit (1);
+ }
+
+ if (AIOSetExternalControl(AIOhandle, AIO_EXTERNAL_CONTROL,
+ (AIO_EXTCTRL_DTR | AIO_EXTCTRL_RTS))
+ != AIO_SUCCESS)
+ {
+ LONG extStatus, chgdExtStatus;
+
+ fprintf (stderr, "Could not set desired port controls!\n");
+ AIOGetExternalStatus (AIOhandle, &extStatus, &chgdExtStatus);
+ fprintf (stderr, "Port controls now: %d, %d\n", extStatus,
+ chgdExtStatus);
+ }
+
+ /* Register ourselves as an alternate debugger. */
+ memset (&s, 0, sizeof s);
+ s.DDSResourceTag = ((struct ResourceTagStructure *)
+ AllocateResourceTag (GetNLMHandle (),
+ (BYTE *)"gdbserver",
+ DebuggerSignature));
+ if (s.DDSResourceTag == 0)
+ {
+ fprintf (stderr, "AllocateResourceTag failed\n");
+ AIOReleasePort (AIOhandle);
+ exit (1);
+ }
+ s.DDSdebuggerEntry = handle_exception;
+ s.DDSFlags = TSS_FRAME_BIT;
+
+ err = RegisterDebuggerRTag (&s, AT_FIRST);
+ if (err != 0)
+ {
+ fprintf (stderr, "RegisterDebuggerRTag failed\n");
+ AIOReleasePort (AIOhandle);
+ exit (1);
+ }
+
+ /* Get the command line we were invoked with, and advance it past
+ our name and the board and port arguments. */
+ cmdlin = getcmd ((char *) NULL);
+ for (i = 0; i < cmdindx; i++)
+ {
+ while (! isspace (*cmdlin))
+ ++cmdlin;
+ while (isspace (*cmdlin))
+ ++cmdlin;
+ }
+
+ /* In case GDB is started before us, ack any packets (presumably
+ "$?#xx") sitting there. */
+ if (! putDebugChar ('+'))
+ {
+ fprintf (stderr, "putDebugChar failed\n");
+ UnRegisterDebugger (&s);
+ AIOReleasePort (AIOhandle);
+ exit (1);
+ }
+
+ mainthread = GetThreadID ();
+
+ if (remote_debug > 0)
+ ConsolePrintf ("About to call LoadModule with \"%s\" %08x\r\n",
+ cmdlin, __GetScreenID (GetCurrentScreen()));
+
+ /* Start up the module to be debugged. */
+ err = LoadModule ((struct ScreenStruct *) __GetScreenID (GetCurrentScreen()),
+ (BYTE *)cmdlin, LO_DEBUG);
+ if (err != 0)
+ {
+ fprintf (stderr, "LoadModule failed: %d\n", err);
+ UnRegisterDebugger (&s);
+ AIOReleasePort (AIOhandle);
+ exit (1);
+ }
+
+ /* Wait for the debugger to wake us up. */
+ if (remote_debug > 0)
+ ConsolePrintf ("Suspending main thread (%08x)\r\n", mainthread);
+ SuspendThread (mainthread);
+ if (remote_debug > 0)
+ ConsolePrintf ("Resuming main thread (%08x)\r\n", mainthread);
+
+ /* If we are woken up, print an optional error message, deregister
+ ourselves and exit. */
+ if (error_message != NULL)
+ fprintf (stderr, "%s\n", error_message);
+ UnRegisterDebugger (&s);
+ AIOReleasePort (AIOhandle);
+ exit (0);
+}
diff --git a/gdb/nlm/gdbserve.def b/gdb/nlm/gdbserve.def
new file mode 100644
index 00000000000..588028d6f33
--- /dev/null
+++ b/gdb/nlm/gdbserve.def
@@ -0,0 +1,42 @@
+description "GDB debugger stub"
+version 1,2
+debug
+module clib
+screenname "System Console"
+input gdbserve.O
+output gdbserve.nlm
+start _Prelude
+exit _Stop
+import
+ AllocateResourceTag
+ ConsolePrintf
+ GetCurrentScreen
+ GetNLMHandle
+ GetThreadID
+ KillMe
+ LoadModule
+ ReadByteAltDebugger
+ RegisterDebuggerRTag
+ ResumeThread
+ SuspendThread
+ UnRegisterDebugger
+ WriteByteAltDebugger
+ _GetCLibNLMLibHandle
+ _NWRegisterNLMLibraryUser
+ _SetupArgv
+ _StartNLM
+ _TerminateNLM
+ __GetScreenID
+ __get_errno_ptr
+ exit
+ fprintf
+ getcmd
+ memcmp
+ memcpy
+ memset
+ sprintf
+ strcmp
+ strcpy
+ strlen
+ strnicmp
+ strtol
diff --git a/gdb/nlm/i386.c b/gdb/nlm/i386.c
new file mode 100644
index 00000000000..560198e3702
--- /dev/null
+++ b/gdb/nlm/i386.c
@@ -0,0 +1,108 @@
+#include <dfs.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <time.h>
+#include <conio.h>
+#include <advanced.h>
+#include <debugapi.h>
+#include <process.h>
+#include <errno.h>
+#include "i386.h"
+
+extern char *mem2hex (void *mem, char *buf, int count, int may_fault);
+extern char *hex2mem (char *buf, void *mem, int count, int may_fault);
+extern int computeSignal (int exceptionVector);
+
+void
+flush_i_cache()
+{
+}
+
+/* Get the registers out of the frame information. */
+
+void
+frame_to_registers (frame, regs)
+ struct StackFrame *frame;
+ char *regs;
+{
+ /* Copy EAX -> EDI */
+ mem2hex (&frame->ExceptionEAX, &regs[0 * 4 * 2], 4 * 8, 0);
+
+ /* Copy EIP & PS */
+ mem2hex (&frame->ExceptionPC, &regs[8 * 4 * 2], 4 * 2, 0);
+
+ /* Copy CS, SS, DS */
+ mem2hex (&frame->ExceptionCS, &regs[10 * 4 * 2], 4 * 3, 0);
+
+ /* Copy ES */
+ mem2hex (&frame->ExceptionES, &regs[13 * 4 * 2], 4 * 1, 0);
+
+ /* Copy FS & GS */
+ mem2hex (&frame->ExceptionFS, &regs[14 * 4 * 2], 4 * 2, 0);
+}
+
+/* Put the registers back into the frame information. */
+
+void
+registers_to_frame (regs, frame)
+ char *regs;
+ struct StackFrame *frame;
+{
+ /* Copy EAX -> EDI */
+ hex2mem (&regs[0 * 4 * 2], &frame->ExceptionEAX, 4 * 8, 0);
+
+ /* Copy EIP & PS */
+ hex2mem (&regs[8 * 4 * 2], &frame->ExceptionPC, 4 * 2, 0);
+
+ /* Copy CS, SS, DS */
+ hex2mem (&regs[10 * 4 * 2], &frame->ExceptionCS, 4 * 3, 0);
+
+ /* Copy ES */
+ hex2mem (&regs[13 * 4 * 2], &frame->ExceptionES, 4 * 1, 0);
+
+ /* Copy FS & GS */
+ hex2mem (&regs[14 * 4 * 2], &frame->ExceptionFS, 4 * 2, 0);
+}
+
+void
+set_step_traps (frame)
+ struct StackFrame *frame;
+{
+ frame->ExceptionSystemFlags |= 0x100;
+}
+
+void
+clear_step_traps (frame)
+ struct StackFrame *frame;
+{
+ frame->ExceptionSystemFlags &= ~0x100;
+}
+
+void
+do_status (ptr, frame)
+ char *ptr;
+ struct StackFrame *frame;
+{
+ int sigval;
+
+ sigval = computeSignal (frame->ExceptionNumber);
+
+ sprintf (ptr, "T%02x", sigval);
+ ptr += 3;
+
+ sprintf (ptr, "%02x:", PC_REGNUM);
+ ptr = mem2hex (&frame->ExceptionPC, ptr + 3, 4, 0);
+ *ptr++ = ';';
+
+ sprintf (ptr, "%02x:", SP_REGNUM);
+ ptr = mem2hex (&frame->ExceptionESP, ptr + 3, 4, 0);
+ *ptr++ = ';';
+
+ sprintf (ptr, "%02x:", FP_REGNUM);
+ ptr = mem2hex (&frame->ExceptionEBP, ptr + 3, 4, 0);
+ *ptr++ = ';';
+
+ *ptr = '\000';
+}
diff --git a/gdb/nlm/i386.h b/gdb/nlm/i386.h
new file mode 100644
index 00000000000..155702bd503
--- /dev/null
+++ b/gdb/nlm/i386.h
@@ -0,0 +1,13 @@
+/* Register values. All of these values *MUST* agree with tm.h */
+#define SP_REGNUM 4 /* Contains address of top of stack */
+#define PC_REGNUM 8 /* Contains program counter */
+#define FP_REGNUM 5 /* Virtual frame pointer */
+#define NUM_REGS 16 /* Number of machine registers */
+#define REGISTER_BYTES (NUM_REGS * 4) /* Total size of registers array */
+
+#define ExceptionPC ExceptionEIP
+#define DECR_PC_AFTER_BREAK 1 /* int 3 leaves PC pointing after insn */
+#define BREAKPOINT {0xcc}
+#define BREAKPOINT_SIZE (sizeof breakpoint_insn)
+
+#define StackFrame T_TSS_StackFrame
diff --git a/gdb/nlm/ppc.c b/gdb/nlm/ppc.c
new file mode 100644
index 00000000000..e68397bc96b
--- /dev/null
+++ b/gdb/nlm/ppc.c
@@ -0,0 +1,257 @@
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <time.h>
+#include <errno.h>
+
+#include <nwtypes.h>
+#include <nwdfs.h>
+#include <nwconio.h>
+#include <nwadv.h>
+#include <nwdbgapi.h>
+#include <nwthread.h>
+#include "ppc.h"
+
+extern char *mem2hex (void *mem, char *buf, int count, int may_fault);
+extern char *hex2mem (char *buf, void *mem, int count, int may_fault);
+extern int computeSignal (int exceptionVector);
+
+void
+flush_i_cache (void)
+{
+}
+
+/* Get the registers out of the frame information. */
+
+void
+frame_to_registers (frame, regs)
+ struct StackFrame *frame;
+ char *regs;
+{
+ mem2hex (&frame->ExceptionState.CsavedRegs, &regs[GP0_REGNUM * 4 * 2], 4 * 32, 0);
+
+ mem2hex (&frame->ExceptionState.CSavedFPRegs, &regs[FP0_REGNUM * 4 * 2], 4 * 32, 0);
+
+ mem2hex (&frame->ExceptionPC, &regs[PC_REGNUM * 4 * 2], 4 * 1, 0);
+
+ mem2hex (&frame->ExceptionState.u.SpecialRegistersEnumerated.CsavedSRR1, &regs[CR_REGNUM * 4 * 2], 4 * 1, 0);
+ mem2hex (&frame->ExceptionState.u.SpecialRegistersEnumerated.CsavedLR, &regs[LR_REGNUM * 4 * 2], 4 * 1, 0);
+ mem2hex (&frame->ExceptionState.u.SpecialRegistersEnumerated.CsavedCTR, &regs[CTR_REGNUM * 4 * 2], 4 * 1, 0);
+ mem2hex (&frame->ExceptionState.u.SpecialRegistersEnumerated.CsavedXER, &regs[XER_REGNUM * 4 * 2], 4 * 1, 0);
+ mem2hex (&frame->ExceptionState.u.SpecialRegistersEnumerated.CsavedMQ, &regs[MQ_REGNUM * 4 * 2], 4 * 1, 0);
+}
+
+/* Put the registers back into the frame information. */
+
+void
+registers_to_frame (regs, frame)
+ char *regs;
+ struct StackFrame *frame;
+{
+ hex2mem (&regs[GP0_REGNUM * 4 * 2], &frame->ExceptionState.CsavedRegs, 4 * 32, 0);
+
+ hex2mem (&regs[FP0_REGNUM * 4 * 2], &frame->ExceptionState.CSavedFPRegs, 4 * 32, 0);
+
+ hex2mem (&regs[PC_REGNUM * 4 * 2], &frame->ExceptionPC, 4 * 1, 0);
+
+ hex2mem (&regs[CR_REGNUM * 4 * 2], &frame->ExceptionState.u.SpecialRegistersEnumerated.CsavedSRR1, 4 * 1, 0);
+ hex2mem (&regs[LR_REGNUM * 4 * 2], &frame->ExceptionState.u.SpecialRegistersEnumerated.CsavedLR, 4 * 1, 0);
+ hex2mem (&regs[CTR_REGNUM * 4 * 2], &frame->ExceptionState.u.SpecialRegistersEnumerated.CsavedCTR, 4 * 1, 0);
+ hex2mem (&regs[XER_REGNUM * 4 * 2], &frame->ExceptionState.u.SpecialRegistersEnumerated.CsavedXER, 4 * 1, 0);
+ hex2mem (&regs[MQ_REGNUM * 4 * 2], &frame->ExceptionState.u.SpecialRegistersEnumerated.CsavedMQ, 4 * 1, 0);
+}
+
+
+extern volatile int mem_err;
+
+#ifdef ALTERNATE_MEM_FUNCS
+extern int ReadByteAltDebugger (char* addr, char *theByte);
+extern int WriteByteAltDebugger (char* addr, char theByte);
+int
+get_char (addr)
+ char *addr;
+{
+ char c;
+
+ if (!ReadByteAltDebugger (addr, &c))
+ mem_err = 1;
+
+ return c;
+}
+
+void
+set_char (addr, val)
+ char *addr;
+ int val;
+{
+ if (!WriteByteAltDebugger (addr, val))
+ mem_err = 1;
+}
+#endif
+
+int
+mem_write (dst, src, len)
+ char *dst, *src;
+ int len;
+{
+ while (len-- && !mem_err)
+ set_char (dst++, *src++);
+
+ return mem_err;
+}
+
+union inst
+{
+ LONG l;
+
+ struct
+ {
+ union
+ {
+ struct /* Unconditional branch */
+ {
+ unsigned opcode : 6; /* 18 */
+ signed li : 24;
+ unsigned aa : 1;
+ unsigned lk : 1;
+ } b;
+ struct /* Conditional branch */
+ {
+ unsigned opcode : 6; /* 16 */
+ unsigned bo : 5;
+ unsigned bi : 5;
+ signed bd : 14;
+ unsigned aa : 1;
+ unsigned lk : 1;
+ } bc;
+ struct /* Conditional branch to ctr or lr reg */
+ {
+ unsigned opcode : 6; /* 19 */
+ unsigned bo : 5;
+ unsigned bi : 5;
+ unsigned type : 15; /* 528 = ctr, 16 = lr */
+ unsigned lk : 1;
+ } bclr;
+ } variant;
+ } inst;
+};
+
+static LONG saved_inst;
+static LONG *saved_inst_pc = 0;
+static LONG saved_target_inst;
+static LONG *saved_target_inst_pc = 0;
+
+void
+set_step_traps (frame)
+ struct StackFrame *frame;
+{
+ union inst inst;
+ LONG *target;
+ int opcode;
+ int ra, rb;
+ LONG *pc = (LONG *)frame->ExceptionPC;
+
+ inst.l = *pc++;
+
+ opcode = inst.inst.variant.b.opcode;
+
+ target = pc;
+
+ switch (opcode)
+ {
+ case 18: /* Unconditional branch */
+
+ if (inst.inst.variant.b.aa) /* Absolute? */
+ target = 0;
+ target += inst.inst.variant.b.li;
+
+ break;
+ case 16: /* Conditional branch */
+
+ if (!inst.inst.variant.bc.aa) /* Absolute? */
+ target = 0;
+ target += inst.inst.variant.bc.bd;
+
+ break;
+ case 19: /* Cond. branch via ctr or lr reg */
+ switch (inst.inst.variant.bclr.type)
+ {
+ case 528: /* ctr */
+ target = (LONG *)frame->ExceptionState.u.SpecialRegistersEnumerated.CsavedCTR;
+ break;
+ case 16: /* lr */
+ target = (LONG *)frame->ExceptionState.u.SpecialRegistersEnumerated.CsavedLR;
+ break;
+ }
+ break;
+ }
+
+ saved_inst = *pc;
+ mem_write (pc, breakpoint_insn, BREAKPOINT_SIZE);
+ saved_inst_pc = pc;
+
+ if (target != pc)
+ {
+ saved_target_inst = *target;
+ mem_write (target, breakpoint_insn, BREAKPOINT_SIZE);
+ saved_target_inst_pc = target;
+ }
+}
+
+/* Remove step breakpoints. Returns non-zero if pc was at a step breakpoint,
+ zero otherwise. This routine works even if there were no step breakpoints
+ set. */
+
+int
+clear_step_traps (frame)
+ struct StackFrame *frame;
+{
+ int retcode;
+ LONG *pc = (LONG *)frame->ExceptionPC;
+
+ if (saved_inst_pc == pc || saved_target_inst_pc == pc)
+ retcode = 1;
+ else
+ retcode = 0;
+
+ if (saved_inst_pc)
+ {
+ mem_write (saved_inst_pc, saved_inst, BREAKPOINT_SIZE);
+ saved_inst_pc = 0;
+ }
+
+ if (saved_target_inst_pc)
+ {
+ mem_write (saved_target_inst_pc, saved_target_inst, BREAKPOINT_SIZE);
+ saved_target_inst_pc = 0;
+ }
+
+ return retcode;
+}
+
+void
+do_status (ptr, frame)
+ char *ptr;
+ struct StackFrame *frame;
+{
+ int sigval;
+
+ sigval = computeSignal (frame->ExceptionNumber);
+
+ sprintf (ptr, "T%02x", sigval);
+ ptr += 3;
+
+ sprintf (ptr, "%02x:", PC_REGNUM);
+ ptr = mem2hex (&frame->ExceptionPC, ptr + 3, 4, 0);
+ *ptr++ = ';';
+
+ sprintf (ptr, "%02x:", SP_REGNUM);
+ ptr = mem2hex (&frame->ExceptionState.CsavedRegs[SP_REGNUM], ptr + 3, 4, 0);
+ *ptr++ = ';';
+
+ sprintf (ptr, "%02x:", LR_REGNUM);
+ ptr = mem2hex (&frame->ExceptionState.CsavedRegs[LR_REGNUM], ptr + 3, 4, 0);
+ *ptr++ = ';';
+
+ *ptr = '\000';
+}
diff --git a/gdb/nlm/ppc.h b/gdb/nlm/ppc.h
new file mode 100644
index 00000000000..84cee6b11a3
--- /dev/null
+++ b/gdb/nlm/ppc.h
@@ -0,0 +1,165 @@
+typedef long Long;
+
+/* The following enum is used to access the special registers in
+ the saved machine state. */
+
+typedef enum
+{
+ kDc_SavedPC = 0, /* really SRR0 */
+ kDc_SavedMSR = 1, /* really SRR1 */
+ kDc_SavedCR = 2,
+ kDc_SavedLR = 3,
+ kDc_SavedDSISR = 4,
+ kDc_SavedDAR = 5,
+ kDc_SavedXER = 6,
+ kDc_SavedCTR = 7,
+ kDc_SavedSDR1 = 8,
+ kDc_SavedRTCU = 9,
+ kDc_SavedRTCL = 10,
+ kDc_SavedDEC = 11,
+ kDc_SavedSR00 = 12, /* The Segement Registers are consecutive */
+ kDc_SavedSR01 = 13, /* kDc_SavedSR00 + n is supported */
+ kDc_SavedSR02 = 14,
+ kDc_SavedSR03 = 15,
+ kDc_SavedSR04 = 16,
+ kDc_SavedSR05 = 17,
+ kDc_SavedSR06 = 18,
+ kDc_SavedSR07 = 19,
+ kDc_SavedSR08 = 20,
+ kDc_SavedSR09 = 21,
+ kDc_SavedSR10 = 22,
+ kDc_SavedSR11 = 23,
+ kDc_SavedSR12 = 24,
+ kDc_SavedSR13 = 25,
+ kDc_SavedSR14 = 26,
+ kDc_SavedSR15 = 27,
+ kDc_SavedFPSCR = 29,
+ kDc_SavedMQ = 30,
+ kDc_SavedBAT0U = 31,
+ kDc_SavedBAT0L = 32,
+ kDc_SavedBAT1U = 33,
+ kDc_SavedBAT1L = 34,
+ kDc_SavedBAT2U = 35,
+ kDc_SavedBAT2L = 36,
+ kDc_SavedBAT3U = 37,
+ kDc_SavedBAT3L = 38,
+
+ kNumberSpecialRegisters = 39
+} Dc_SavedRegisterName;
+
+/* Access to floating points is not very easy. This allows the number to be
+ accessed both as a floating number and as a pair of Longs. */
+
+typedef union
+{
+ double asfloat; /* access the variable as a floating number */
+ struct
+ {
+ Long high;
+ Long low;
+ }
+ asLONG; /* access the variable as two Longs */
+} FloatingPoints;
+
+/* The following is the standard record for Saving a machine state */
+
+struct SavedMachineState
+{
+ FloatingPoints CSavedFPRegs[32]; /* The floating point registers [0->31] */
+ /* ***32bit assumption*** */
+ Long CsavedRegs[32]; /* space to save the General Registers */
+ /* These are saved 0->31 */
+ Long CexReason;
+ Long SavedDomainID;
+ union
+ { /* must be 8-byte aligned, so doubleFPSCR is 8-byte aligned */
+ struct
+ {
+ Long CsavedSRR0; /* Index 0 - The saved PC */
+ Long CsavedSRR1; /* 1 saved MSR */
+ Long CsavedCR; /* 2 */
+ Long CsavedLR; /* 3 */
+ Long CsavedDSISR; /* 4 */
+ Long CsavedDAR; /* 5 */
+
+ Long CsavedXER; /* 6 */
+ Long CsavedCTR; /* 7 */
+ Long CsavedSDR1; /* 8 */
+ Long CsavedRTCU; /* 9 */
+ Long CsavedRTCL; /* 10 */
+ Long CsavedDEC; /* 11 */
+ Long CsavedSR0; /* 12 */
+ Long CsavedSR1; /* 13 */
+ Long CsavedSR2; /* 14 */
+ Long CsavedSR3; /* 15 */
+ Long CsavedSR4; /* 16 */
+ Long CsavedSR5; /* 17 */
+ Long CsavedSR6; /* 18 */
+ Long CsavedSR7; /* 19 */
+ Long CsavedSR8; /* 20 */
+ Long CsavedSR9; /* 21 */
+ Long CsavedSR10; /* 22 */
+ Long CsavedSR11; /* 23 */
+ Long CsavedSR12; /* 24 */
+ Long CsavedSR13; /* 25 */
+ Long CsavedSR14; /* 26 */
+ Long CsavedSR15; /* 27 */
+ /* CdoubleFPSCR must be double word aligned */
+ Long CdoubleFPSCR; /* 28 this is the upper part of the store and has
+ no meaning */
+ Long CsavedFPSCR; /* 29 */
+ Long CsavedMQ; /* 30 */
+ Long CsavedBAT0U; /* 31 */
+ Long CsavedBAT0L; /* 32 */
+ Long CsavedBAT1U; /* 33 */
+ Long CsavedBAT1L; /* 34 */
+ Long CsavedBAT2U; /* 35 */
+ Long CsavedBAT2L; /* 36 */
+ Long CsavedBAT3U; /* 37 */
+ Long CsavedBAT3L; /* 38 */
+ }
+ SpecialRegistersEnumerated;
+
+ Long SpecialRegistersIndexed[kNumberSpecialRegisters];
+ } u;
+
+ Long Padding[3]; /* Needed for quad-word alignment */
+};
+
+struct StackFrame
+{
+ LONG *ExceptionDomainID;
+ /*ProcessorStructure*/ int *ExceptionProcessorID;
+ BYTE *ExceptionDescription;
+ LONG ExceptionFlags;
+ LONG ExceptionErrorCode;
+ LONG ExceptionNumber;
+ struct SavedMachineState ExceptionState;
+};
+
+/* Register values. All of these values *MUST* agree with tm.h */
+#define GP0_REGNUM 0 /* GPR register 0 */
+#define SP_REGNUM 1 /* Contains address of top of stack */
+#define FP0_REGNUM 32 /* FPR (Floating point) register 0 */
+#define PC_REGNUM 64 /* Contains program counter */
+#define PS_REGNUM 65 /* Processor (or machine) status (%msr) */
+#define CR_REGNUM 66 /* Condition register */
+#define LR_REGNUM 67 /* Link register */
+#define CTR_REGNUM 68 /* Count register */
+#define XER_REGNUM 69 /* Fixed point exception registers */
+#define MQ_REGNUM 70 /* Multiply/quotient register */
+#define NUM_REGS 71 /* Number of machine registers */
+#define REGISTER_BYTES (420) /* Total size of registers array */
+
+#define ExceptionPC ExceptionState.u.SpecialRegistersEnumerated.CsavedSRR0
+#define DECR_PC_AFTER_BREAK 0 /* PPCs get this right! */
+#define BREAKPOINT {0x7d, 0x82, 0x10, 0x08}
+extern unsigned char breakpoint_insn[];
+#define BREAKPOINT_SIZE 4
+
+#if 0
+#define ALTERNATE_MEM_FUNCS /* We need our own get_char/set_char */
+#endif
+
+extern int get_char (char *addr);
+extern void set_char (char *addr, int val);
diff --git a/gdb/nlm/prelude.c b/gdb/nlm/prelude.c
new file mode 100644
index 00000000000..37e12c89a2b
--- /dev/null
+++ b/gdb/nlm/prelude.c
@@ -0,0 +1,67 @@
+/*===========================================================================
+= Novell Standard C Library for NetWare Loadable Modules
+=
+= Unpublished Copyright (C) 1993 by Novell, Inc. All rights reserved.
+=
+= No part of this file may be duplicated, revised, translated, localized or
+= modified in any manner or compiled, linked or uploaded or downloaded to or
+= from any computer system without the prior written consent of Novell, Inc.
+==============================================================================
+= The object produced by compiling this file is for use by the client of this
+= library and is not linked in; Prelude.Obj is therefore one of the files to
+= be distributed with CLib.NLM and its headers.
+==============================================================================
+*/
+
+#include <stddef.h>
+#if defined(__netware__) && defined(__i386__)
+#define TERMINATE_BY_UNLOAD 5
+#else
+#include <nwpre.h>
+#endif
+/*#include "libhooks.h"*/
+
+extern int main (int, char **);
+
+static int NLMID;
+
+
+void _Stop( void )
+{
+ _TerminateNLM(NLMID, NULL, TERMINATE_BY_UNLOAD);
+}
+
+int _cstart_( void )
+{
+ return _SetupArgv(main);
+}
+
+int _Prelude
+(
+ int NLMHandle,
+ int initErrorScreenID,
+ char *commandLine,
+ char *loadDirectoryPath,
+ int uninitializedDataLength,
+ int NLMFileHandle,
+ int (*readRoutineP)(),
+ int customDataOffset,
+ int customDataSize
+)
+{
+ int rc;
+
+ rc = _StartNLM(NLMHandle,
+ initErrorScreenID,
+ commandLine,
+ loadDirectoryPath,
+ uninitializedDataLength,
+ NLMFileHandle,
+ readRoutineP,
+ customDataOffset,
+ customDataSize,
+ &NLMID,
+ _cstart_);
+
+ return rc;
+}
diff --git a/gdb/nlmread.c b/gdb/nlmread.c
new file mode 100644
index 00000000000..afdea43a6b0
--- /dev/null
+++ b/gdb/nlmread.c
@@ -0,0 +1,261 @@
+/* Read NLM (NetWare Loadable Module) format executable files for GDB.
+ Copyright 1993, 1994, 1998 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "gdb_string.h"
+#include "bfd.h"
+#include "symtab.h"
+#include "symfile.h"
+#include "objfiles.h"
+#include "gdb-stabs.h"
+#include "buildsym.h"
+#include "stabsread.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 *));
+
+/* 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;
+{
+}
+
+/*
+
+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;
+{
+ long storage_needed;
+ asymbol *sym;
+ asymbol **symbol_table;
+ long number_of_symbols;
+ long i;
+ struct cleanup *back_to;
+ CORE_ADDR symaddr;
+ enum minimal_symbol_type ms_type;
+
+ storage_needed = bfd_get_symtab_upper_bound (abfd);
+ if (storage_needed < 0)
+ error ("Can't read symbols from %s: %s", bfd_get_filename (abfd),
+ bfd_errmsg (bfd_get_error ()));
+ 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);
+ if (number_of_symbols < 0)
+ error ("Can't read symbols from %s: %s", bfd_get_filename (abfd),
+ bfd_errmsg (bfd_get_error ()));
+
+ for (i = 0; i < number_of_symbols; i++)
+ {
+ sym = symbol_table[i];
+ if (/*sym -> flags & BSF_GLOBAL*/ 1)
+ {
+ /* 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;
+
+ prim_record_minimal_symbol (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;
+ struct symbol *mainsym;
+
+ init_minimal_symbol_collection ();
+ back_to = make_cleanup ((make_cleanup_func) 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);
+
+ stabsect_build_psymtabs (objfile, section_offsets, mainline, ".stab",
+ ".stabstr", ".text");
+
+ mainsym = lookup_symbol ("main", NULL, VAR_NAMESPACE, NULL, NULL);
+
+ if (mainsym
+ && SYMBOL_CLASS(mainsym) == LOC_BLOCK)
+ {
+ objfile->ei.main_func_lowpc = BLOCK_START (SYMBOL_BLOCK_VALUE (mainsym));
+ objfile->ei.main_func_highpc = BLOCK_END (SYMBOL_BLOCK_VALUE (mainsym));
+ }
+
+ /* FIXME: We could locate and read the optional native debugging format
+ here and add the symbols to the minimal symbol table. */
+
+ /* 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);
+ }
+}
+
+/* Register that we are able to handle NLM file format. */
+
+static struct sym_fns nlm_sym_fns =
+{
+ bfd_target_nlm_flavour,
+ 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 */
+ default_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/gdb/notify.defs b/gdb/notify.defs
new file mode 100644
index 00000000000..2014be5ca44
--- /dev/null
+++ b/gdb/notify.defs
@@ -0,0 +1 @@
+#include <mach/notify.defs>
diff --git a/gdb/ns32k-tdep.c b/gdb/ns32k-tdep.c
new file mode 100644
index 00000000000..3edb7f5d5d9
--- /dev/null
+++ b/gdb/ns32k-tdep.c
@@ -0,0 +1,122 @@
+/* Print NS 32000 instructions for GDB, the GNU debugger.
+ Copyright 1986, 1988, 1991, 1992, 1994, 1995
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+
+void
+_initialize_ns32k_tdep ()
+{
+ tm_print_insn = print_insn_ns32k;
+}
+
+sign_extend (value, bits)
+{
+ value = value & ((1 << bits) - 1);
+ return (value & (1 << (bits-1))
+ ? value | (~((1 << bits) - 1))
+ : value);
+}
+
+void
+flip_bytes (ptr, count)
+ char *ptr;
+ int count;
+{
+ char tmp;
+
+ while (count > 0)
+ {
+ tmp = *ptr;
+ ptr[0] = ptr[count-1];
+ ptr[count-1] = tmp;
+ ptr++;
+ count -= 2;
+ }
+}
+
+/* Return the number of locals in the current frame given a pc
+ pointing to the enter instruction. This is used in the macro
+ FRAME_FIND_SAVED_REGS. */
+
+int
+ns32k_localcount (enter_pc)
+ CORE_ADDR enter_pc;
+{
+ unsigned char localtype;
+ int localcount;
+
+ localtype = read_memory_integer (enter_pc+2, 1);
+ if ((localtype & 0x80) == 0)
+ localcount = localtype;
+ else if ((localtype & 0xc0) == 0x80)
+ localcount = (((localtype & 0x3f) << 8)
+ | (read_memory_integer (enter_pc+3, 1) & 0xff));
+ else
+ localcount = (((localtype & 0x3f) << 24)
+ | ((read_memory_integer (enter_pc+3, 1) & 0xff) << 16)
+ | ((read_memory_integer (enter_pc+4, 1) & 0xff) << 8 )
+ | (read_memory_integer (enter_pc+5, 1) & 0xff));
+ return localcount;
+}
+
+
+/* Nonzero if instruction at PC is a return instruction. */
+
+static int
+ns32k_about_to_return (pc)
+ CORE_ADDR pc;
+{
+ return (read_memory_integer (pc, 1) == 0x12);
+}
+
+
+/*
+ * Get the address of the enter opcode for the function
+ * containing PC, if there is an enter for the function,
+ * and if the pc is between the enter and exit.
+ * Returns positive address if pc is between enter/exit,
+ * 1 if pc before enter or after exit, 0 otherwise.
+ */
+
+CORE_ADDR
+ns32k_get_enter_addr (pc)
+ CORE_ADDR pc;
+{
+ CORE_ADDR enter_addr;
+ unsigned char op;
+
+ if (pc == 0)
+ return 0;
+
+ if (ns32k_about_to_return (pc))
+ return 1; /* after exit */
+
+ enter_addr = get_pc_function_start (pc);
+
+ if (pc == enter_addr)
+ return 1; /* before enter */
+
+ op = read_memory_integer (enter_addr, 1);
+
+ if (op != 0x82)
+ return 0; /* function has no enter/exit */
+
+ return enter_addr; /* pc is between enter and exit */
+}
diff --git a/gdb/ns32km3-nat.c b/gdb/ns32km3-nat.c
new file mode 100644
index 00000000000..cdafb9ce0d4
--- /dev/null
+++ b/gdb/ns32km3-nat.c
@@ -0,0 +1,183 @@
+/* Low level interface to ns532 running mach 3.0.
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "inferior.h"
+
+#include <stdio.h>
+
+#include <mach.h>
+#include <mach/message.h>
+#include <mach/exception.h>
+#include <mach_error.h>
+
+#define private static
+
+
+/* Find offsets to thread states at compile time.
+ * If your compiler does not grok this, calculate offsets
+ * offsets yourself and use them (or get a compatible compiler :-)
+ */
+
+#define REG_N_OFFSET(reg) (int)(&((struct ns532_combined_state *)0)->ts.reg)
+#define REG_F_OFFSET(reg) (int)(&((struct ns532_combined_state *)0)->fs.reg)
+
+/* at reg_offset[i] is the offset to the ns532_combined_state
+ * location where the gdb registers[i] is stored.
+ */
+
+static int reg_offset[] =
+{
+ REG_N_OFFSET(r0), REG_N_OFFSET(r1), REG_N_OFFSET(r2), REG_N_OFFSET(r3),
+ REG_N_OFFSET(r4), REG_N_OFFSET(r5), REG_N_OFFSET(r6), REG_N_OFFSET(r7),
+ REG_F_OFFSET(l0a), REG_F_OFFSET(l0b),REG_F_OFFSET(l2a),REG_F_OFFSET(l2b),
+ REG_F_OFFSET(l4a), REG_F_OFFSET(l4b),REG_F_OFFSET(l6a),REG_F_OFFSET(l6b),
+ REG_N_OFFSET(sp), REG_N_OFFSET(fp), REG_N_OFFSET(pc), REG_N_OFFSET(psr),
+ REG_F_OFFSET(fsr),
+ REG_F_OFFSET(l0a), REG_F_OFFSET(l1a),REG_F_OFFSET(l2a),REG_F_OFFSET(l3a),
+ REG_F_OFFSET(l4a), REG_F_OFFSET(l5a),REG_F_OFFSET(l6a),REG_F_OFFSET(l7a),
+};
+
+#define REG_ADDRESS(state,regnum) ((char *)(state)+reg_offset[regnum])
+
+/* Fetch COUNT contiguous registers from thread STATE starting from REGNUM
+ * Caller knows that the regs handled in one transaction are of same size.
+ */
+#define FETCH_REGS(state, regnum, count) \
+ memcpy (&registers[REGISTER_BYTE (regnum)], \
+ (char *)state+reg_offset[ regnum ], \
+ count*REGISTER_SIZE)
+
+/* Store COUNT contiguous registers to thread STATE starting from REGNUM */
+#define STORE_REGS(state, regnum, count) \
+ memcpy ((char *)state+reg_offset[ regnum ], \
+ &registers[REGISTER_BYTE (regnum)], \
+ count*REGISTER_SIZE)
+
+/*
+ * Fetch inferiors registers for gdb.
+ * REGNO specifies which (as gdb views it) register, -1 for all.
+ */
+
+void
+fetch_inferior_registers (regno)
+ int regno;
+{
+ kern_return_t ret;
+ thread_state_data_t state;
+ unsigned int stateCnt = NS532_COMBINED_STATE_COUNT;
+ int index;
+
+ if (! MACH_PORT_VALID (current_thread))
+ error ("fetch inferior registers: Invalid thread");
+
+ if (must_suspend_thread)
+ setup_thread (current_thread, 1);
+
+ ret = thread_get_state (current_thread,
+ NS532_COMBINED_STATE,
+ state,
+ &stateCnt);
+
+ if (ret != KERN_SUCCESS)
+ warning ("fetch_inferior_registers: %s ",
+ mach_error_string (ret));
+#if 0
+ /* It may be more effective to store validate all of them,
+ * since we fetched them all anyway
+ */
+ else if (regno != -1)
+ supply_register (regno, (char *)state+reg_offset[regno]);
+#endif
+ else
+ {
+ for (index = 0; index < NUM_REGS; index++)
+ supply_register (index, (char *)state+reg_offset[index]);
+ }
+
+ if (must_suspend_thread)
+ setup_thread (current_thread, 0);
+}
+
+/* Store our register values back into the inferior.
+ * If REGNO is -1, do this for all registers.
+ * Otherwise, REGNO specifies which register
+ *
+ * On mach3 all registers are always saved in one call.
+ */
+void
+store_inferior_registers (regno)
+ int regno;
+{
+ kern_return_t ret;
+ thread_state_data_t state;
+ unsigned int stateCnt = NS532_COMBINED_STATE_COUNT;
+ register int index;
+
+ if (! MACH_PORT_VALID (current_thread))
+ error ("store inferior registers: Invalid thread");
+
+ if (must_suspend_thread)
+ setup_thread (current_thread, 1);
+
+ /* Fetch the state of the current thread */
+ ret = thread_get_state (current_thread,
+ NS532_COMBINED_STATE,
+ state,
+ &stateCnt);
+
+ if (ret != KERN_SUCCESS)
+ {
+ warning ("store_inferior_registers (get): %s",
+ mach_error_string (ret));
+ if (must_suspend_thread)
+ setup_thread (current_thread, 0);
+ return;
+ }
+
+ /* move gdb's registers to thread's state
+ *
+ * Since we save all registers anyway, save the ones
+ * that gdb thinks are valid (e.g. ignore the regno
+ * parameter)
+ */
+#if 0
+ if (regno != -1)
+ STORE_REGS (state, regno, 1);
+ else
+#endif
+ {
+ for (index = 0; index < NUM_REGS; index++)
+ STORE_REGS (state, index, 1);
+ }
+
+ /* Write gdb's current view of register to the thread
+ */
+ ret = thread_set_state (current_thread,
+ NS532_COMBINED_STATE,
+ state,
+ NS532_COMBINED_STATE_COUNT);
+
+ if (ret != KERN_SUCCESS)
+ warning ("store_inferior_registers (set): %s",
+ mach_error_string (ret));
+
+ if (must_suspend_thread)
+ setup_thread (current_thread, 0);
+}
diff --git a/gdb/ns32knbsd-nat.c b/gdb/ns32knbsd-nat.c
new file mode 100644
index 00000000000..c9f75cac87f
--- /dev/null
+++ b/gdb/ns32knbsd-nat.c
@@ -0,0 +1,353 @@
+/* Functions specific to running gdb native on an ns32k running NetBSD
+ Copyright 1989, 1992, 1993, 1994, 1996 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include <sys/types.h>
+#include <sys/ptrace.h>
+#include <machine/reg.h>
+#include <machine/frame.h>
+#include <machine/pcb.h>
+
+#include "defs.h"
+#include "inferior.h"
+#include "target.h"
+#include "gdbcore.h"
+
+#define RF(dst, src) \
+ memcpy(&registers[REGISTER_BYTE(dst)], &src, sizeof(src))
+
+#define RS(src, dst) \
+ memcpy(&dst, &registers[REGISTER_BYTE(src)], sizeof(dst))
+
+void
+fetch_inferior_registers (regno)
+ int regno;
+{
+ struct reg inferior_registers;
+ struct fpreg inferior_fpregisters;
+
+ ptrace (PT_GETREGS, inferior_pid,
+ (PTRACE_ARG3_TYPE) &inferior_registers, 0);
+ ptrace (PT_GETFPREGS, inferior_pid,
+ (PTRACE_ARG3_TYPE) &inferior_fpregisters, 0);
+
+ RF(R0_REGNUM + 0, inferior_registers.r_r0);
+ RF(R0_REGNUM + 1, inferior_registers.r_r1);
+ RF(R0_REGNUM + 2, inferior_registers.r_r2);
+ RF(R0_REGNUM + 3, inferior_registers.r_r3);
+ RF(R0_REGNUM + 4, inferior_registers.r_r4);
+ RF(R0_REGNUM + 5, inferior_registers.r_r5);
+ RF(R0_REGNUM + 6, inferior_registers.r_r6);
+ RF(R0_REGNUM + 7, inferior_registers.r_r7);
+
+ RF(SP_REGNUM , inferior_registers.r_sp);
+ RF(FP_REGNUM , inferior_registers.r_fp);
+ RF(PC_REGNUM , inferior_registers.r_pc);
+ RF(PS_REGNUM , inferior_registers.r_psr);
+
+ RF(FPS_REGNUM , inferior_fpregisters.r_fsr);
+ RF(FP0_REGNUM +0, inferior_fpregisters.r_freg[0]);
+ RF(FP0_REGNUM +2, inferior_fpregisters.r_freg[2]);
+ RF(FP0_REGNUM +4, inferior_fpregisters.r_freg[4]);
+ RF(FP0_REGNUM +6, inferior_fpregisters.r_freg[6]);
+ RF(LP0_REGNUM + 1, inferior_fpregisters.r_freg[1]);
+ RF(LP0_REGNUM + 3, inferior_fpregisters.r_freg[3]);
+ RF(LP0_REGNUM + 5, inferior_fpregisters.r_freg[5]);
+ RF(LP0_REGNUM + 7, inferior_fpregisters.r_freg[7]);
+ registers_fetched ();
+}
+
+void
+store_inferior_registers (regno)
+ int regno;
+{
+ struct reg inferior_registers;
+ struct fpreg inferior_fpregisters;
+
+ RS(R0_REGNUM + 0, inferior_registers.r_r0);
+ RS(R0_REGNUM + 1, inferior_registers.r_r1);
+ RS(R0_REGNUM + 2, inferior_registers.r_r2);
+ RS(R0_REGNUM + 3, inferior_registers.r_r3);
+ RS(R0_REGNUM + 4, inferior_registers.r_r4);
+ RS(R0_REGNUM + 5, inferior_registers.r_r5);
+ RS(R0_REGNUM + 6, inferior_registers.r_r6);
+ RS(R0_REGNUM + 7, inferior_registers.r_r7);
+
+ RS(SP_REGNUM , inferior_registers.r_sp);
+ RS(FP_REGNUM , inferior_registers.r_fp);
+ RS(PC_REGNUM , inferior_registers.r_pc);
+ RS(PS_REGNUM , inferior_registers.r_psr);
+
+ RS(FPS_REGNUM , inferior_fpregisters.r_fsr);
+ RS(FP0_REGNUM +0, inferior_fpregisters.r_freg[0]);
+ RS(FP0_REGNUM +2, inferior_fpregisters.r_freg[2]);
+ RS(FP0_REGNUM +4, inferior_fpregisters.r_freg[4]);
+ RS(FP0_REGNUM +6, inferior_fpregisters.r_freg[6]);
+ RS(LP0_REGNUM + 1, inferior_fpregisters.r_freg[1]);
+ RS(LP0_REGNUM + 3, inferior_fpregisters.r_freg[3]);
+ RS(LP0_REGNUM + 5, inferior_fpregisters.r_freg[5]);
+ RS(LP0_REGNUM + 7, inferior_fpregisters.r_freg[7]);
+
+ ptrace (PT_SETREGS, inferior_pid,
+ (PTRACE_ARG3_TYPE) &inferior_registers, 0);
+ ptrace (PT_SETFPREGS, inferior_pid,
+ (PTRACE_ARG3_TYPE) &inferior_fpregisters, 0);
+}
+
+
+/* XXX - Add this to machine/regs.h instead? */
+struct coreregs {
+ struct reg intreg;
+ struct fpreg freg;
+};
+
+/* Get registers from a core file. */
+static void
+fetch_core_registers (core_reg_sect, core_reg_size, which, reg_addr)
+ char *core_reg_sect;
+ unsigned core_reg_size;
+ int which;
+ unsigned int reg_addr; /* Unused in this version */
+{
+ struct coreregs *core_reg;
+
+ core_reg = (struct coreregs *)core_reg_sect;
+
+ /*
+ * We have *all* registers
+ * in the first core section.
+ * Ignore which.
+ */
+
+ if (core_reg_size < sizeof(*core_reg)) {
+ fprintf_unfiltered (gdb_stderr, "Couldn't read regs from core file\n");
+ return;
+ }
+
+ /* Integer registers */
+ RF(R0_REGNUM + 0, core_reg->intreg.r_r0);
+ RF(R0_REGNUM + 1, core_reg->intreg.r_r1);
+ RF(R0_REGNUM + 2, core_reg->intreg.r_r2);
+ RF(R0_REGNUM + 3, core_reg->intreg.r_r3);
+ RF(R0_REGNUM + 4, core_reg->intreg.r_r4);
+ RF(R0_REGNUM + 5, core_reg->intreg.r_r5);
+ RF(R0_REGNUM + 6, core_reg->intreg.r_r6);
+ RF(R0_REGNUM + 7, core_reg->intreg.r_r7);
+
+ RF(SP_REGNUM , core_reg->intreg.r_sp);
+ RF(FP_REGNUM , core_reg->intreg.r_fp);
+ RF(PC_REGNUM , core_reg->intreg.r_pc);
+ RF(PS_REGNUM , core_reg->intreg.r_psr);
+
+ /* Floating point registers */
+ RF(FPS_REGNUM , core_reg->freg.r_fsr);
+ RF(FP0_REGNUM +0, core_reg->freg.r_freg[0]);
+ RF(FP0_REGNUM +2, core_reg->freg.r_freg[2]);
+ RF(FP0_REGNUM +4, core_reg->freg.r_freg[4]);
+ RF(FP0_REGNUM +6, core_reg->freg.r_freg[6]);
+ RF(LP0_REGNUM + 1, core_reg->freg.r_freg[1]);
+ RF(LP0_REGNUM + 3, core_reg->freg.r_freg[3]);
+ RF(LP0_REGNUM + 5, core_reg->freg.r_freg[5]);
+ RF(LP0_REGNUM + 7, core_reg->freg.r_freg[7]);
+ registers_fetched ();
+}
+
+/* Register that we are able to handle ns32knbsd core file formats.
+ FIXME: is this really bfd_target_unknown_flavour? */
+
+static struct core_fns nat_core_fns =
+{
+ bfd_target_unknown_flavour,
+ fetch_core_registers,
+ NULL
+};
+
+void
+_initialize_ns32knbsd_nat ()
+{
+ add_core_fns (&nat_core_fns);
+}
+
+
+/*
+ * kernel_u_size() is not helpful on NetBSD because
+ * the "u" struct is NOT in the core dump file.
+ */
+
+#ifdef FETCH_KCORE_REGISTERS
+/*
+ * Get registers from a kernel crash dump or live kernel.
+ * Called by kcore-nbsd.c:get_kcore_registers().
+ */
+void
+fetch_kcore_registers (pcb)
+ struct pcb *pcb;
+{
+ struct switchframe sf;
+ struct reg intreg;
+ int dummy;
+
+ /* Integer registers */
+ if (target_read_memory((CORE_ADDR)pcb->pcb_ksp, (char *)&sf, sizeof sf))
+ error("Cannot read integer registers.");
+
+ /* We use the psr at kernel entry */
+ if (target_read_memory((CORE_ADDR)pcb->pcb_onstack, (char *)&intreg, sizeof intreg))
+ error("Cannot read processor status register.");
+
+ dummy = 0;
+ RF(R0_REGNUM + 0, dummy);
+ RF(R0_REGNUM + 1, dummy);
+ RF(R0_REGNUM + 2, dummy);
+ RF(R0_REGNUM + 3, sf.sf_r3);
+ RF(R0_REGNUM + 4, sf.sf_r4);
+ RF(R0_REGNUM + 5, sf.sf_r5);
+ RF(R0_REGNUM + 6, sf.sf_r6);
+ RF(R0_REGNUM + 7, sf.sf_r7);
+
+ dummy = pcb->pcb_kfp + 8;
+ RF(SP_REGNUM , dummy);
+ RF(FP_REGNUM , sf.sf_fp);
+ RF(PC_REGNUM , sf.sf_pc);
+ RF(PS_REGNUM , intreg.r_psr);
+
+ /* Floating point registers */
+ RF(FPS_REGNUM , pcb->pcb_fsr);
+ RF(FP0_REGNUM +0, pcb->pcb_freg[0]);
+ RF(FP0_REGNUM +2, pcb->pcb_freg[2]);
+ RF(FP0_REGNUM +4, pcb->pcb_freg[4]);
+ RF(FP0_REGNUM +6, pcb->pcb_freg[6]);
+ RF(LP0_REGNUM + 1, pcb->pcb_freg[1]);
+ RF(LP0_REGNUM + 3, pcb->pcb_freg[3]);
+ RF(LP0_REGNUM + 5, pcb->pcb_freg[5]);
+ RF(LP0_REGNUM + 7, pcb->pcb_freg[7]);
+ registers_fetched ();
+}
+#endif /* FETCH_KCORE_REGISTERS */
+
+void
+clear_regs()
+{
+ double zero = 0.0;
+ int null = 0;
+
+ /* Integer registers */
+ RF(R0_REGNUM + 0, null);
+ RF(R0_REGNUM + 1, null);
+ RF(R0_REGNUM + 2, null);
+ RF(R0_REGNUM + 3, null);
+ RF(R0_REGNUM + 4, null);
+ RF(R0_REGNUM + 5, null);
+ RF(R0_REGNUM + 6, null);
+ RF(R0_REGNUM + 7, null);
+
+ RF(SP_REGNUM , null);
+ RF(FP_REGNUM , null);
+ RF(PC_REGNUM , null);
+ RF(PS_REGNUM , null);
+
+ /* Floating point registers */
+ RF(FPS_REGNUM , zero);
+ RF(FP0_REGNUM +0, zero);
+ RF(FP0_REGNUM +2, zero);
+ RF(FP0_REGNUM +4, zero);
+ RF(FP0_REGNUM +6, zero);
+ RF(LP0_REGNUM + 0, zero);
+ RF(LP0_REGNUM + 1, zero);
+ RF(LP0_REGNUM + 2, zero);
+ RF(LP0_REGNUM + 3, zero);
+ return;
+}
+
+/* Return number of args passed to a frame.
+ Can return -1, meaning no way to tell. */
+
+int
+frame_num_args(fi)
+struct frame_info *fi;
+{
+ CORE_ADDR enter_addr;
+ CORE_ADDR argp;
+ int inst;
+ int args;
+ int i;
+
+ if (read_memory_integer (fi->frame, 4) == 0 && fi->pc < 0x10000) {
+ /* main is always called with three args */
+ return(3);
+ }
+ enter_addr = ns32k_get_enter_addr(fi->pc);
+ if (enter_addr = 0)
+ return(-1);
+ argp = enter_addr == 1 ? SAVED_PC_AFTER_CALL(fi) : FRAME_SAVED_PC(fi);
+ for (i = 0; i < 16; i++) {
+ /*
+ * After a bsr gcc may emit the following instructions
+ * to remove the arguments from the stack:
+ * cmpqd 0,tos - to remove 4 bytes from the stack
+ * cmpd tos,tos - to remove 8 bytes from the stack
+ * adjsp[bwd] -n - to remove n bytes from the stack
+ * Gcc sometimes delays emitting these instructions and
+ * may even throw a branch between our feet.
+ */
+ inst = read_memory_integer(argp , 4);
+ args = read_memory_integer(argp + 2, 4);
+ if ((inst & 0xff) == 0xea) { /* br */
+ args = ((inst >> 8) & 0xffffff) | (args << 24);
+ if (args & 0x80) {
+ if (args & 0x40) {
+ args = ntohl(args);
+ } else {
+ args = ntohs(args & 0xffff);
+ if (args & 0x2000)
+ args |= 0xc000;
+ }
+ } else {
+ args = args & 0xff;
+ if (args & 0x40)
+ args |= 0x80;
+ }
+ argp += args;
+ continue;
+ }
+ if ((inst & 0xffff) == 0xb81f) /* cmpqd 0,tos */
+ return(1);
+ else if ((inst & 0xffff) == 0xbdc7) /* cmpd tos,tos */
+ return(2);
+ else if ((inst & 0xfffc) == 0xa57c) { /* adjsp[bwd] */
+ switch (inst & 3) {
+ case 0:
+ args = ((args & 0xff) + 0x80);
+ break;
+ case 1:
+ args = ((ntohs(args) & 0xffff) + 0x8000);
+ break;
+ case 3:
+ args = -ntohl(args);
+ break;
+ default:
+ return(-1);
+ }
+ if (args / 4 > 10 || (args & 3) != 0)
+ continue;
+ return(args / 4);
+ }
+ argp += 1;
+ }
+ return(-1);
+}
diff --git a/gdb/objfiles.c b/gdb/objfiles.c
new file mode 100644
index 00000000000..971a7d4de49
--- /dev/null
+++ b/gdb/objfiles.c
@@ -0,0 +1,988 @@
+/* GDB routines for manipulating objfiles.
+ Copyright 1992, 1993, 1994, 1995 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 "gdb_stat.h"
+#include <fcntl.h>
+#include "obstack.h"
+#include "gdb_string.h"
+
+/* Prototypes for local functions */
+
+#if defined(USE_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 PTR
+map_to_file PARAMS ((int));
+
+#endif /* defined(USE_MMALLOC) && defined(HAVE_MMAP) */
+
+static void
+add_to_objfile_sections PARAMS ((bfd *, sec_ptr, PTR));
+
+/* 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 */
+struct objfile *rt_common_objfile; /* For runtime common symbols */
+
+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. */
+
+#ifndef TARGET_KEEP_SECTION
+#define TARGET_KEEP_SECTION(ASECT) 0
+#endif
+
+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);
+
+ if (!(aflag & SEC_ALLOC) && !(TARGET_KEEP_SECTION(asect)))
+ return;
+
+ if (0 == bfd_section_size (abfd, asect))
+ return;
+ section.offset = 0;
+ section.objfile = objfile;
+ section.the_bfd_section = asect;
+ section.ovly_mapped = 0;
+ section.addr = bfd_section_vma (abfd, asect);
+ section.endaddr = section.addr + bfd_section_size (abfd, asect);
+ obstack_grow (&objfile->psymbol_obstack, (char *) &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 (in which case bfd_error contains the
+ error). */
+
+int
+build_objfile_section_table (objfile)
+ struct objfile *objfile;
+{
+ /* objfile->sections can be already set when reading a mapped symbol
+ file. I believe that we do need to rebuild the section table in
+ this case (we rebuild other things derived from the bfd), but we
+ can't free the old one (it's in the psymbol_obstack). So we just
+ waste some memory. */
+
+ 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.
+
+ USER_LOADED is simply recorded in the objfile. This record offers a way for
+ run_command to remove old objfile entries which are no longer valid (i.e.,
+ are associated with an old inferior), but to preserve ones that the user
+ explicitly loaded via the add-symbol-file command.
+
+ IS_SOLIB is also simply recorded in the objfile. */
+
+struct objfile *
+allocate_objfile (abfd, mapped, user_loaded, is_solib)
+ bfd *abfd;
+ int mapped;
+ int user_loaded;
+ int is_solib;
+{
+ struct objfile *objfile = NULL;
+ struct objfile *last_one = NULL;
+
+ mapped |= mapped_symbol_files;
+
+#if defined(USE_MMALLOC) && defined(HAVE_MMAP)
+ if (abfd != NULL)
+ {
+
+ /* 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. */
+
+ int fd;
+
+ fd = open_mapped_file (bfd_get_filename (abfd), bfd_get_mtime (abfd),
+ mapped);
+ if (fd >= 0)
+ {
+ PTR md;
+
+ if ((md = map_to_file (fd)) == 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_cache.cache, xmmalloc);
+ obstack_freefun (&objfile -> psymbol_cache.cache, mfree);
+ 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_cache.cache,
+ 0, 0, xmmalloc, mfree,
+ objfile -> md);
+ 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(USE_MMALLOC) || !defined(HAVE_MMAP) */
+
+ if (mapped)
+ {
+ warning ("mapped symbol tables are not supported on this machine; missing or broken mmap().");
+
+ /* 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(USE_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_cache.cache, 0, 0,
+ xmalloc, free);
+ 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);
+ }
+ if (abfd != NULL)
+ {
+ 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_get_error ()));
+ }
+ }
+
+ /* Add this file onto the tail of the linked list of other such files. */
+
+ objfile -> next = NULL;
+ if (object_files == NULL)
+ object_files = objfile;
+ else
+ {
+ for (last_one = object_files;
+ last_one -> next;
+ last_one = last_one -> next);
+ last_one -> next = objfile;
+ }
+
+ /* Record whether this objfile was created because the user explicitly
+ caused it (e.g., used the add-symbol-file command).
+ */
+ objfile -> user_loaded = user_loaded;
+
+ /* Record whether this objfile definitely represents a solib. */
+ objfile -> is_solib = is_solib;
+
+ return (objfile);
+}
+
+/* Put OBJFILE at the front of the list. */
+
+void
+objfile_to_front (objfile)
+ struct objfile *objfile;
+{
+ struct objfile **objp;
+ for (objp = &object_files; *objp != NULL; objp = &((*objp)->next))
+ {
+ if (*objp == objfile)
+ {
+ /* Unhook it from where it is. */
+ *objp = objfile->next;
+ /* Put it in the front. */
+ objfile->next = object_files;
+ object_files = objfile;
+ break;
+ }
+ }
+}
+
+/* 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;
+{
+ /* 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);
+ if (!bfd_close (objfile -> obfd))
+ warning ("cannot close \"%s\": %s",
+ name, bfd_errmsg (bfd_get_error ()));
+ free (name);
+ }
+
+ /* Remove it from the chain of all objfiles. */
+
+ unlink_objfile (objfile);
+
+ /* If we are going to free the runtime common objfile, mark it
+ as unallocated. */
+
+ if (objfile == rt_common_objfile)
+ rt_common_objfile = NULL;
+
+ /* 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
+ /* I *think* all our callers call clear_symtab_users. If so, no need
+ to call this here. */
+ 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(USE_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. */
+ int mmfd;
+
+ mmfd = objfile -> mmfd;
+ mmalloc_detach (objfile -> md);
+ objfile = NULL;
+ close (mmfd);
+ }
+
+#endif /* defined(USE_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_cache.cache, 0);
+ 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;
+
+ ALL_OBJFILE_SYMTABS (objfile, s)
+ {
+ 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_CLASS (sym) == LOC_INDIRECT)
+ && SYMBOL_SECTION (sym) >= 0)
+ {
+ SYMBOL_VALUE_ADDRESS (sym) +=
+ ANOFFSET (delta, SYMBOL_SECTION (sym));
+ }
+#ifdef MIPS_EFI_SYMBOL_NAME
+ /* Relocate Extra Function Info for ecoff. */
+
+ else
+ if (SYMBOL_CLASS (sym) == LOC_CONST
+ && SYMBOL_NAMESPACE (sym) == LABEL_NAMESPACE
+ && STRCMP (SYMBOL_NAME (sym), MIPS_EFI_SYMBOL_NAME) == 0)
+ ecoff_relocate_efi (sym, ANOFFSET (delta,
+ s->block_line_section));
+#endif
+ }
+ }
+ }
+ }
+
+ {
+ struct partial_symtab *p;
+
+ ALL_OBJFILE_PSYMTABS (objfile, p)
+ {
+ 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));
+ }
+ /* Relocating different sections by different amounts may cause the symbols
+ to be out of order. */
+ msymbols_sort (objfile);
+
+ {
+ int i;
+ for (i = 0; i < objfile->num_sections; ++i)
+ ANOFFSET (objfile->section_offsets, i) = ANOFFSET (new_offsets, i);
+ }
+
+ {
+ struct obj_section *s;
+ bfd *abfd;
+
+ abfd = objfile->obfd;
+
+ for (s = objfile->sections;
+ s < objfile->sections_end; ++s)
+ {
+ flagword flags;
+
+ flags = bfd_get_section_flags (abfd, s->the_bfd_section);
+
+ if (flags & SEC_CODE)
+ {
+ s->addr += ANOFFSET (delta, SECT_OFF_TEXT);
+ s->endaddr += ANOFFSET (delta, SECT_OFF_TEXT);
+ }
+ else if (flags & (SEC_DATA | SEC_LOAD))
+ {
+ s->addr += ANOFFSET (delta, SECT_OFF_DATA);
+ s->endaddr += ANOFFSET (delta, SECT_OFF_DATA);
+ }
+ else if (flags & SEC_ALLOC)
+ {
+ s->addr += ANOFFSET (delta, SECT_OFF_BSS);
+ s->endaddr += ANOFFSET (delta, SECT_OFF_BSS);
+ }
+ }
+ }
+
+ if (objfile->ei.entry_point != ~(CORE_ADDR)0)
+ objfile->ei.entry_point += ANOFFSET (delta, SECT_OFF_TEXT);
+
+ if (objfile->ei.entry_func_lowpc != INVALID_ENTRY_LOWPC)
+ {
+ objfile->ei.entry_func_lowpc += ANOFFSET (delta, SECT_OFF_TEXT);
+ objfile->ei.entry_func_highpc += ANOFFSET (delta, SECT_OFF_TEXT);
+ }
+
+ if (objfile->ei.entry_file_lowpc != INVALID_ENTRY_LOWPC)
+ {
+ objfile->ei.entry_file_lowpc += ANOFFSET (delta, SECT_OFF_TEXT);
+ objfile->ei.entry_file_highpc += ANOFFSET (delta, SECT_OFF_TEXT);
+ }
+
+ if (objfile->ei.main_func_lowpc != INVALID_ENTRY_LOWPC)
+ {
+ objfile->ei.main_func_lowpc += ANOFFSET (delta, SECT_OFF_TEXT);
+ objfile->ei.main_func_highpc += ANOFFSET (delta, SECT_OFF_TEXT);
+ }
+
+ /* Relocate breakpoints as necessary, after things are relocated. */
+ breakpoint_re_set ();
+}
+
+/* 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;
+}
+
+
+/* This operations deletes all objfile entries that represent solibs that
+ weren't explicitly loaded by the user, via e.g., the add-symbol-file
+ command.
+ */
+void
+objfile_purge_solibs ()
+{
+ struct objfile * objf;
+ struct objfile * temp;
+
+ ALL_OBJFILES_SAFE (objf, temp)
+ {
+ /* We assume that the solib package has been purged already, or will
+ be soon.
+ */
+ if (! objf->user_loaded && objf->is_solib)
+ free_objfile (objf);
+ }
+}
+
+
+/* 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(USE_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_unfiltered (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_unfiltered (error_pre_print);
+ }
+ print_sys_errmsg (symsfilename, errno);
+ }
+ }
+
+ free (symsfilename);
+ return (fd);
+}
+
+static PTR
+map_to_file (fd)
+ int fd;
+{
+ PTR md;
+ CORE_ADDR mapto;
+
+ md = mmalloc_attach (fd, (PTR) 0);
+ if (md != NULL)
+ {
+ mapto = (CORE_ADDR) mmalloc_getkey (md, 1);
+ md = mmalloc_detach (md);
+ if (md != NULL)
+ {
+ /* FIXME: should figure out why detach failed */
+ md = NULL;
+ }
+ else if (mapto != (CORE_ADDR) NULL)
+ {
+ /* This mapping file needs to be remapped at "mapto" */
+ md = mmalloc_attach (fd, (PTR) mapto);
+ }
+ else
+ {
+ /* This is a freshly created mapping file. */
+ mapto = (CORE_ADDR) mmalloc_findbase (20 * 1024 * 1024);
+ if (mapto != 0)
+ {
+ /* To avoid reusing the freshly created mapping file, at the
+ address selected by mmap, we must truncate it before trying
+ to do an attach at the address we want. */
+ ftruncate (fd, 0);
+ md = mmalloc_attach (fd, (PTR) mapto);
+ if (md != NULL)
+ {
+ mmalloc_setkey (md, 1, (PTR) mapto);
+ }
+ }
+ }
+ }
+ return (md);
+}
+
+#endif /* defined(USE_MMALLOC) && defined(HAVE_MMAP) */
+
+/* Returns a section whose range includes PC and SECTION,
+ or NULL if none found. Note the distinction between the return type,
+ struct obj_section (which is defined in gdb), and the input type
+ struct sec (which is a bfd-defined data type). The obj_section
+ contains a pointer to the bfd struct sec section. */
+
+struct obj_section *
+find_pc_sect_section (pc, section)
+ CORE_ADDR pc;
+ struct sec *section;
+{
+ struct obj_section *s;
+ struct objfile *objfile;
+
+ ALL_OBJFILES (objfile)
+ for (s = objfile->sections; s < objfile->sections_end; ++s)
+#if defined(HPUXHPPA)
+ if ((section == 0 || section == s->the_bfd_section) &&
+ s->addr <= pc && pc <= s->endaddr)
+#else
+ if ((section == 0 || section == s->the_bfd_section) &&
+ s->addr <= pc && pc < s->endaddr)
+#endif
+ return(s);
+
+ return(NULL);
+}
+
+/* Returns a section whose range includes PC or NULL if none found.
+ Backward compatibility, no section. */
+
+struct obj_section *
+find_pc_section(pc)
+ CORE_ADDR pc;
+{
+ return find_pc_sect_section (pc, find_pc_mapped_section (pc));
+}
+
+
+/* In SVR4, we recognize a trampoline by it's section name.
+ That is, if the pc is in a section named ".plt" then we are in
+ a trampoline. */
+
+int
+in_plt_section(pc, name)
+ CORE_ADDR pc;
+ char *name;
+{
+ struct obj_section *s;
+ int retval = 0;
+
+ s = find_pc_section(pc);
+
+ retval = (s != NULL
+ && s->the_bfd_section->name != NULL
+ && STREQ (s->the_bfd_section->name, ".plt"));
+ return(retval);
+}
diff --git a/gdb/objfiles.h b/gdb/objfiles.h
new file mode 100644
index 00000000000..2a5df06160f
--- /dev/null
+++ b/gdb/objfiles.h
@@ -0,0 +1,572 @@
+/* Definitions for symbol file management in GDB.
+ Copyright (C) 1992, 1993, 1994, 1995 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 its 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.
+
+ Gdb also supports an alternate method to avoid running off the 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;
+
+#define INVALID_ENTRY_POINT (~0) /* ~0 will not be in any file, we hope. */
+
+ /* 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;
+
+/* Use these values when any of the above ranges is invalid. */
+
+/* We use these values because it guarantees that there is no number that is
+ both >= LOWPC && < HIGHPC. It is also highly unlikely that 3 is a valid
+ module or function start address (as opposed to 0). */
+
+#define INVALID_ENTRY_LOWPC (3)
+#define INVALID_ENTRY_HIGHPC (1)
+
+};
+
+/* 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 the_bfd_section; /* BFD section pointer */
+
+ /* Objfile this section is part of. */
+ struct objfile *objfile;
+
+ /* True if this "overlay section" is mapped into an "overlay region". */
+ int ovly_mapped;
+};
+
+/* An import entry contains information about a symbol that
+ is used in this objfile but not defined in it, and so needs
+ to be imported from some other objfile */
+/* Currently we just store the name; no attributes. 1997-08-05 */
+typedef char * ImportEntry;
+
+
+/* An export entry contains information about a symbol that
+ is defined in this objfile and available for use in other
+ objfiles */
+typedef struct {
+ char * name; /* name of exported symbol */
+ int address; /* offset subject to relocation */
+ /* Currently no other attributes 1997-08-05 */
+} ExportEntry;
+
+
+
+/* The "objstats" structure provides a place for gdb to record some
+ interesting information about its internal state at runtime, on a
+ per objfile basis, such as information about the number of symbols
+ read, size of string table (if any), etc. */
+
+#if MAINTENANCE_CMDS
+
+struct objstats {
+ int n_minsyms; /* Number of minimal symbols read */
+ int n_psyms; /* Number of partial symbols read */
+ int n_syms; /* Number of full symbols read */
+ int n_stabs; /* Number of ".stabs" read (if applicable) */
+ int n_types; /* Number of types */
+ int sz_strtab; /* Size of stringtable, (if applicable) */
+};
+
+#define OBJSTAT(objfile, expr) (objfile -> stats.expr)
+#define OBJSTATS struct objstats stats
+extern void print_objfile_statistics PARAMS ((void));
+extern void print_symbol_bcache_statistics PARAMS ((void));
+
+#else
+
+#define OBJSTAT(objfile, expr) /* Nothing */
+#define OBJSTATS /* Nothing */
+
+#endif /* MAINTENANCE_CMDS */
+
+/* Master structure for keeping track of each file from which
+ gdb reads symbols. There are several ways these get allocated: 1.
+ The main symbol file, symfile_objfile, set by the symbol-file command,
+ 2. Additional symbol files added by the add-symbol-file command,
+ 3. Shared library objfiles, added by ADD_SOLIB, 4. symbol files
+ for modules that were loaded when GDB attached to a remote system
+ (see remote-vx.c). */
+
+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;
+
+ /* TRUE if this objfile was created because the user explicitly caused
+ it (e.g., used the add-symbol-file command).
+ */
+ int user_loaded;
+
+ /* TRUE if this objfile was explicitly created to represent a solib.
+
+ (If FALSE, the objfile may actually be a solib. This can happen if
+ the user created the objfile by using the add-symbol-file command.
+ GDB doesn't in that situation actually check whether the file is a
+ solib. Rather, the target's implementation of the solib interface
+ is responsible for setting this flag when noticing solibs used by
+ an inferior.)
+ */
+ int is_solib;
+
+ /* 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 if the objfile contains only
+ minimal symbols, e.g. the run time common symbols for SunOS4. */
+
+ 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 */
+
+ /* A byte cache where we can stash arbitrary "chunks" of bytes that
+ will not change. */
+
+ struct bcache psymbol_cache; /* Byte cache for partial syms */
+
+ /* 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 not 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. */
+
+ struct dbx_symfile_info *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;
+
+ /* two auxiliary fields, used to hold the fp of separate symbol files */
+ FILE *auxf1, *auxf2;
+
+ /* Imported symbols */
+ ImportEntry * import_list;
+ int import_list_size;
+
+ /* Exported symbols */
+ ExportEntry * export_list;
+ int export_list_size;
+
+ /* Place to stash various statistics about this objfile */
+ OBJSTATS;
+};
+
+/* 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 its 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 */
+
+/* When an object file has its functions reordered (currently Irix-5.2
+ shared libraries exhibit this behaviour), we will need an expensive
+ algorithm to locate a partial symtab or symtab via an address.
+ To avoid this penalty for normal object files, we use this flag,
+ whose setting is determined upon symbol table read in. */
+
+#define OBJF_REORDERED (1 << 2) /* Functions are reordered */
+
+/* Distinguish between an objfile for a shared library and a
+ "vanilla" objfile. */
+
+#define OBJF_SHARED (1 << 3) /* From a shared library */
+
+/* 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;
+
+/* The object file that contains the runtime common minimal symbols
+ for SunOS4. Note that this objfile has no associated BFD. */
+
+extern struct objfile *rt_common_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, int, int));
+
+extern int
+build_objfile_section_table PARAMS ((struct objfile *));
+
+extern void objfile_to_front PARAMS ((struct objfile *));
+
+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));
+
+/* This operation deletes all objfile entries that represent solibs that
+ weren't explicitly loaded by the user, via e.g., the add-symbol-file
+ command.
+ */
+extern void
+objfile_purge_solibs 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));
+
+extern struct obj_section *
+find_pc_sect_section PARAMS((CORE_ADDR pc, asection *section));
+
+extern int
+in_plt_section PARAMS ((CORE_ADDR, char *));
+
+/* 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)
+
+#define ALL_OBJFILE_OSECTIONS(objfile, osect) \
+ for (osect = objfile->sections; osect < objfile->sections_end; osect++)
+
+#define ALL_OBJSECTIONS(objfile, osect) \
+ ALL_OBJFILES (objfile) \
+ ALL_OBJFILE_OSECTIONS (objfile, osect)
+
+#endif /* !defined (OBJFILES_H) */
diff --git a/gdb/ocd.c b/gdb/ocd.c
new file mode 100644
index 00000000000..343fa627e4f
--- /dev/null
+++ b/gdb/ocd.c
@@ -0,0 +1,1444 @@
+/* Target communications support for Macraigor Systems' On-Chip Debugging
+ Copyright 1996, 1997 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "gdbcore.h"
+#include "gdb_string.h"
+#include <fcntl.h>
+#include "frame.h"
+#include "inferior.h"
+#include "bfd.h"
+#include "symfile.h"
+#include "target.h"
+#include "wait.h"
+#include "gdbcmd.h"
+#include "objfiles.h"
+#include "gdb-stabs.h"
+#include "dcache.h"
+#include <sys/types.h>
+#include <signal.h>
+#include "serial.h"
+#include "ocd.h"
+
+/* Prototypes for local functions */
+
+static int ocd_read_bytes PARAMS ((CORE_ADDR memaddr,
+ char *myaddr, int len));
+
+static int ocd_start_remote PARAMS ((PTR dummy));
+
+static int readchar PARAMS ((int timeout));
+
+static void reset_packet PARAMS ((void));
+
+static void output_packet PARAMS ((void));
+
+static int get_quoted_char PARAMS ((int timeout));
+
+static void put_quoted_char PARAMS ((int c));
+
+static void ocd_interrupt PARAMS ((int signo));
+
+static void ocd_interrupt_twice PARAMS ((int signo));
+
+static void interrupt_query PARAMS ((void));
+
+static unsigned char * ocd_do_command PARAMS ((int cmd, int *statusp, int *lenp));
+
+static void ocd_put_packet PARAMS ((unsigned char *packet, int pktlen));
+
+static unsigned char * ocd_get_packet PARAMS ((int cmd, int *pktlen, int timeout));
+
+static struct target_ops *current_ops = NULL;
+
+static int last_run_status;
+
+/* 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. */
+
+#if 0
+/* FIXME: Change to allow option to set timeout value on a per target
+ basis. */
+static int remote_timeout = 2;
+#endif
+
+/* Descriptor for I/O to remote machine. Initialize it to NULL so that
+ ocd_open knows that we don't have a file open when the program
+ starts. */
+static serial_t ocd_desc = NULL;
+
+void
+ocd_error (s, error_code)
+ char *s;
+ int error_code;
+{
+ char buf[100];
+
+ fputs_filtered (s, gdb_stderr);
+ fputs_filtered (" ", gdb_stderr);
+
+ switch (error_code)
+ {
+ case 0x1: s = "Unknown fault"; break;
+ case 0x2: s = "Power failed"; break;
+ case 0x3: s = "Cable disconnected"; break;
+ case 0x4: s = "Couldn't enter OCD mode"; break;
+ case 0x5: s = "Target stuck in reset"; break;
+ case 0x6: s = "OCD hasn't been initialized"; break;
+ case 0x7: s = "Write verify failed"; break;
+ case 0x8: s = "Reg buff error (during MPC5xx fp reg read/write)"; break;
+ case 0x9: s = "Invalid CPU register access attempt failed"; break;
+ case 0x11: s = "Bus error"; break;
+ case 0x12: s = "Checksum error"; break;
+ case 0x13: s = "Illegal command"; break;
+ case 0x14: s = "Parameter error"; break;
+ case 0x15: s = "Internal error"; break;
+ case 0x80: s = "Flash erase error"; break;
+ default:
+ sprintf (buf, "Unknown error code %d", error_code);
+ s = buf;
+ }
+
+ error (s);
+}
+
+/* Return nonzero if the thread TH is still alive on the remote system. */
+
+int
+ocd_thread_alive (th)
+ int th;
+{
+ return 1;
+}
+
+/* Clean up connection to a remote debugger. */
+
+/* ARGSUSED */
+void
+ocd_close (quitting)
+ int quitting;
+{
+ if (ocd_desc)
+ SERIAL_CLOSE (ocd_desc);
+ ocd_desc = NULL;
+}
+
+/* Stub for catch_errors. */
+
+static int
+ocd_start_remote (dummy)
+ PTR dummy;
+{
+ unsigned char buf[10], *p;
+ int pktlen;
+ int status;
+ int error_code;
+ int speed;
+ enum ocd_target_type target_type;
+
+ target_type = *(enum ocd_target_type*)dummy;
+
+ immediate_quit = 1; /* Allow user to interrupt it */
+
+ SERIAL_SEND_BREAK (ocd_desc); /* Wake up the wiggler */
+
+ speed = 80; /* Divide clock by 4000 */
+
+ buf[0] = OCD_INIT;
+ buf[1] = speed >> 8;
+ buf[2] = speed & 0xff;
+ buf[3] = target_type;
+ ocd_put_packet (buf, 4); /* Init OCD params */
+ p = ocd_get_packet (buf[0], &pktlen, remote_timeout);
+
+ if (pktlen < 2)
+ error ("Truncated response packet from OCD device");
+
+ status = p[1];
+ error_code = p[2];
+
+ if (error_code != 0)
+ ocd_error ("OCD_INIT:", error_code);
+
+ ocd_do_command (OCD_AYT, &status, &pktlen);
+
+ p = ocd_do_command (OCD_GET_VERSION, &status, &pktlen);
+
+ printf_unfiltered ("[Wiggler version %x.%x, capability 0x%x]\n",
+ p[0], p[1], (p[2] << 16) | p[3]);
+
+#if 0
+ /* Reset the target */
+
+ ocd_do_command (OCD_RESET_RUN, &status, &pktlen);
+/* ocd_do_command (OCD_RESET, &status, &pktlen);*/
+#endif
+
+ /* If processor is still running, stop it. */
+
+ if (!(status & OCD_FLAG_BDM))
+ ocd_stop ();
+
+#if 1
+ /* When using a target box, we want to asynchronously return status when
+ target stops. The OCD_SET_CTL_FLAGS command is ignored by Wigglers.dll
+ when using a parallel Wiggler */
+ buf[0] = OCD_SET_CTL_FLAGS;
+ buf[1] = 0;
+ buf[2] = 1;
+ ocd_put_packet (buf, 3);
+
+ p = ocd_get_packet (buf[0], &pktlen, remote_timeout);
+
+ if (pktlen < 2)
+ error ("Truncated response packet from OCD device");
+
+ status = p[1];
+ error_code = p[2];
+
+ if (error_code != 0)
+ ocd_error ("OCD_SET_CTL_FLAGS:", error_code);
+#endif
+
+ immediate_quit = 0;
+
+/* This is really the job of start_remote however, that makes an assumption
+ that the target is about to print out a status message of some sort. That
+ doesn't happen here (in fact, it may not be possible to get the monitor to
+ send the appropriate packet). */
+
+ flush_cached_frames ();
+ registers_changed ();
+ stop_pc = read_pc ();
+ set_current_frame (create_new_frame (read_fp (), stop_pc));
+ select_frame (get_current_frame (), 0);
+ print_stack_frame (selected_frame, -1, 1);
+
+ buf[0] = OCD_LOG_FILE;
+ buf[1] = 3; /* close existing WIGGLERS.LOG */
+ ocd_put_packet (buf, 2);
+ p = ocd_get_packet (buf[0], &pktlen, remote_timeout);
+
+ buf[0] = OCD_LOG_FILE;
+ buf[1] = 2; /* append to existing WIGGLERS.LOG */
+ ocd_put_packet (buf, 2);
+ p = ocd_get_packet (buf[0], &pktlen, remote_timeout);
+
+ return 1;
+}
+
+/* Open a connection to a remote debugger.
+ NAME is the filename used for communication. */
+
+static DCACHE *ocd_dcache;
+
+void
+ocd_open (name, from_tty, target_type, ops)
+ char *name;
+ int from_tty;
+ enum ocd_target_type target_type;
+ struct target_ops *ops;
+{
+ unsigned char buf[10], *p;
+ int status;
+ int pktlen;
+
+ if (name == 0)
+ error ("To open an OCD connection, you need to specify the\n\
+device the OCD device is attached to (e.g. /dev/ttya).");
+
+ target_preopen (from_tty);
+
+ current_ops = ops;
+
+ unpush_target (current_ops);
+
+ ocd_dcache = dcache_init (ocd_read_bytes, ocd_write_bytes);
+
+ if (strncmp(name,"wiggler",7) == 0)
+ {
+ ocd_desc = SERIAL_OPEN ("ocd");
+ if (!ocd_desc)
+ perror_with_name (name);
+
+ buf[0] = OCD_LOG_FILE;
+ buf[1] = 1; /* open new or overwrite existing WIGGLERS.LOG */
+ ocd_put_packet (buf, 2);
+ p = ocd_get_packet (buf[0], &pktlen, remote_timeout);
+
+ buf[0] = OCD_SET_CONNECTION;
+ buf[1] = 0x01; /* atoi (name[11]); */
+ ocd_put_packet (buf, 2);
+ p = ocd_get_packet (buf[0], &pktlen, remote_timeout);
+ }
+ else /* not using Wigglers.dll */
+ {
+ ocd_desc = SERIAL_OPEN (name);
+ if (!ocd_desc)
+ perror_with_name (name);
+ }
+
+ if (baud_rate != -1)
+ {
+ if (SERIAL_SETBAUDRATE (ocd_desc, baud_rate))
+ {
+ SERIAL_CLOSE (ocd_desc);
+ perror_with_name (name);
+ }
+ }
+
+ SERIAL_RAW (ocd_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 (ocd_desc);
+
+ if (from_tty)
+ {
+ puts_filtered ("Remote target wiggler connected to ");
+ puts_filtered (name);
+ puts_filtered ("\n");
+ }
+ push_target (current_ops); /* Switch to using remote target now */
+
+ /* Without this, some commands which require an active target (such as kill)
+ won't work. This variable serves (at least) double duty as both the pid
+ of the target process (if it has such), and as a flag indicating that a
+ target is active. These functions should be split out into seperate
+ variables, especially since GDB will someday have a notion of debugging
+ several processes. */
+
+ inferior_pid = 42000;
+ /* 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 (ocd_start_remote, &target_type,
+ "Couldn't establish connection to remote target\n",
+ RETURN_MASK_ALL))
+ {
+ pop_target();
+ error ("Failed to connect to OCD.");
+ }
+}
+
+/* This takes a program previously attached to and detaches it. After
+ this is done, GDB can be used to debug some other program. We
+ better not have left any breakpoints in the target program or it'll
+ die when it hits one. */
+
+void
+ocd_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");
+}
+
+/* Tell the remote machine to resume. */
+
+void
+ocd_resume (pid, step, siggnal)
+ int pid, step;
+ enum target_signal siggnal;
+{
+ int pktlen;
+
+ dcache_flush (ocd_dcache);
+
+ if (step)
+ ocd_do_command (OCD_STEP, &last_run_status, &pktlen);
+ else
+ ocd_do_command (OCD_RUN, &last_run_status, &pktlen);
+}
+
+void
+ocd_stop ()
+{
+ int status;
+ int pktlen;
+
+ ocd_do_command (OCD_STOP, &status, &pktlen);
+
+ if (!(status & OCD_FLAG_BDM))
+ error ("Can't stop target via BDM");
+}
+
+static volatile int ocd_interrupt_flag;
+
+/* Send ^C to target to halt it. Target will respond, and send us a
+ packet. */
+
+static void
+ocd_interrupt (signo)
+ int signo;
+{
+ /* If this doesn't work, try more severe steps. */
+ signal (signo, ocd_interrupt_twice);
+
+ if (remote_debug)
+ printf_unfiltered ("ocd_interrupt called\n");
+
+ {
+ char buf[1];
+
+ ocd_stop ();
+ buf[0] = OCD_AYT;
+ ocd_put_packet (buf, 1);
+ ocd_interrupt_flag = 1;
+ }
+}
+
+static void (*ofunc)();
+
+/* The user typed ^C twice. */
+static void
+ocd_interrupt_twice (signo)
+ int signo;
+{
+ signal (signo, ofunc);
+
+ interrupt_query ();
+
+ signal (signo, ocd_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 ();
+}
+
+/* If nonzero, ignore the next kill. */
+static int kill_kludge;
+
+/* 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). */
+
+int
+ocd_wait ()
+{
+ unsigned char *p;
+ int error_code;
+ int pktlen;
+ char buf[1];
+
+ ocd_interrupt_flag = 0;
+
+ /* Target might already be stopped by the time we get here. */
+ /* If we aren't already stopped, we need to loop until we've dropped
+ back into BDM mode */
+
+ while (!(last_run_status & OCD_FLAG_BDM))
+ {
+ buf[0] = OCD_AYT;
+ ocd_put_packet (buf, 1);
+ p = ocd_get_packet (OCD_AYT, &pktlen, -1);
+
+ ofunc = (void (*)()) signal (SIGINT, ocd_interrupt);
+ signal (SIGINT, ofunc);
+
+ if (pktlen < 2)
+ error ("Truncated response packet from OCD device");
+
+ last_run_status = p[1];
+ error_code = p[2];
+
+ if (error_code != 0)
+ ocd_error ("target_wait:", error_code);
+
+ if (last_run_status & OCD_FLAG_PWF)
+ error ("OCD device lost VCC at BDM interface.");
+ else if (last_run_status & OCD_FLAG_CABLE_DISC)
+ error ("OCD device cable appears to have been disconnected.");
+ }
+
+ if (ocd_interrupt_flag)
+ return 1;
+ else
+ return 0;
+}
+
+/* Read registers from the OCD device. Specify the starting and ending
+ register number. Return the number of regs actually read in *NUMREGS.
+ Returns a pointer to a static array containing the register contents. */
+
+unsigned char *
+ocd_read_bdm_registers (first_bdm_regno, last_bdm_regno, reglen)
+ int first_bdm_regno;
+ int last_bdm_regno;
+ int *reglen;
+{
+ unsigned char buf[10];
+ int i;
+ unsigned char *p;
+ unsigned char *regs;
+ int error_code, status;
+ int pktlen;
+
+ buf[0] = OCD_READ_REGS;
+ buf[1] = first_bdm_regno >> 8;
+ buf[2] = first_bdm_regno & 0xff;
+ buf[3] = last_bdm_regno >> 8;
+ buf[4] = last_bdm_regno & 0xff;
+
+ ocd_put_packet (buf, 5);
+ p = ocd_get_packet (OCD_READ_REGS, &pktlen, remote_timeout);
+
+ status = p[1];
+ error_code = p[2];
+
+ if (error_code != 0)
+ ocd_error ("read_bdm_registers:", error_code);
+
+ i = p[3];
+ if (i == 0)
+ i = 256;
+
+ if (i > pktlen - 4
+ || ((i & 3) != 0))
+ error ("Register block size bad: %d", i);
+
+ *reglen = i;
+
+ regs = p + 4;
+
+ return regs;
+}
+
+/* Read register BDM_REGNO and returns its value ala read_register() */
+
+CORE_ADDR
+ocd_read_bdm_register (bdm_regno)
+ int bdm_regno;
+{
+ int reglen;
+ unsigned char *p;
+ CORE_ADDR regval;
+
+ p = ocd_read_bdm_registers (bdm_regno, bdm_regno, &reglen);
+ regval = extract_unsigned_integer (p, reglen);
+
+ return regval;
+}
+
+void
+ocd_write_bdm_registers (first_bdm_regno, regptr, reglen)
+ int first_bdm_regno;
+ unsigned char *regptr;
+ int reglen;
+{
+ unsigned char *buf;
+ unsigned char *p;
+ int error_code, status;
+ int pktlen;
+
+ buf = alloca (4 + reglen);
+
+ buf[0] = OCD_WRITE_REGS;
+ buf[1] = first_bdm_regno >> 8;
+ buf[2] = first_bdm_regno & 0xff;
+ buf[3] = reglen;
+ memcpy (buf + 4, regptr, reglen);
+
+ ocd_put_packet (buf, 4 + reglen);
+ p = ocd_get_packet (OCD_WRITE_REGS, &pktlen, remote_timeout);
+
+ if (pktlen < 3)
+ error ("Truncated response packet from OCD device");
+
+ status = p[1];
+ error_code = p[2];
+
+ if (error_code != 0)
+ ocd_error ("ocd_write_bdm_registers:", error_code);
+}
+
+void
+ocd_write_bdm_register (bdm_regno, reg)
+ int bdm_regno;
+ CORE_ADDR reg;
+{
+ unsigned char buf[4];
+
+ store_unsigned_integer (buf, 4, reg);
+
+ ocd_write_bdm_registers (bdm_regno, buf, 4);
+}
+
+void
+ocd_prepare_to_store ()
+{
+}
+
+/* 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 write_mem_command = OCD_WRITE_MEM;
+
+int
+ocd_write_bytes (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+{
+ char buf[256 + 10];
+ unsigned char *p;
+ int origlen;
+
+ origlen = len;
+
+ buf[0] = write_mem_command;
+ buf[5] = 1; /* Write as bytes */
+ buf[6] = 0; /* Don't verify */
+
+ while (len > 0)
+ {
+ int numbytes;
+ int pktlen;
+ int status, error_code;
+
+ numbytes = min (len, 256 - 8);
+
+ buf[1] = memaddr >> 24;
+ buf[2] = memaddr >> 16;
+ buf[3] = memaddr >> 8;
+ buf[4] = memaddr;
+
+ buf[7] = numbytes;
+
+ memcpy (&buf[8], myaddr, numbytes);
+ ocd_put_packet (buf, 8 + numbytes);
+ p = ocd_get_packet (OCD_WRITE_MEM, &pktlen, remote_timeout);
+ if (pktlen < 3)
+ error ("Truncated response packet from OCD device");
+
+ status = p[1];
+ error_code = p[2];
+
+ if (error_code == 0x11) /* Got a bus error? */
+ {
+ CORE_ADDR error_address;
+
+ error_address = p[3] << 24;
+ error_address |= p[4] << 16;
+ error_address |= p[5] << 8;
+ error_address |= p[6];
+ numbytes = error_address - memaddr;
+
+ len -= numbytes;
+
+ errno = EIO;
+
+ break;
+ }
+ else if (error_code != 0)
+ ocd_error ("ocd_write_bytes:", error_code);
+
+ len -= numbytes;
+ memaddr += numbytes;
+ myaddr += numbytes;
+ }
+
+ return origlen - 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
+ocd_read_bytes (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+{
+ char buf[256 + 10];
+ unsigned char *p;
+ int origlen;
+
+ origlen = len;
+
+ buf[0] = OCD_READ_MEM;
+ buf[5] = 1; /* Read as bytes */
+
+ while (len > 0)
+ {
+ int numbytes;
+ int pktlen;
+ int status, error_code;
+
+ numbytes = min (len, 256 - 7);
+
+ buf[1] = memaddr >> 24;
+ buf[2] = memaddr >> 16;
+ buf[3] = memaddr >> 8;
+ buf[4] = memaddr;
+
+ buf[6] = numbytes;
+
+ ocd_put_packet (buf, 7);
+ p = ocd_get_packet (OCD_READ_MEM, &pktlen, remote_timeout);
+ if (pktlen < 4)
+ error ("Truncated response packet from OCD device");
+
+ status = p[1];
+ error_code = p[2];
+
+ if (error_code == 0x11) /* Got a bus error? */
+ {
+ CORE_ADDR error_address;
+
+ error_address = p[3] << 24;
+ error_address |= p[4] << 16;
+ error_address |= p[5] << 8;
+ error_address |= p[6];
+ numbytes = error_address - memaddr;
+
+ len -= numbytes;
+
+ errno = EIO;
+
+ break;
+ }
+ else if (error_code != 0)
+ ocd_error ("ocd_read_bytes:", error_code);
+
+ memcpy (myaddr, &p[4], numbytes);
+
+ len -= numbytes;
+ memaddr += numbytes;
+ myaddr += numbytes;
+ }
+
+ return origlen - len;
+}
+
+/* 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 */
+int
+ocd_xfer_memory (memaddr, myaddr, len, should_write, target)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+ int should_write;
+ struct target_ops *target; /* ignored */
+{
+ return dcache_xfer_memory (ocd_dcache, memaddr, myaddr, len, should_write);
+}
+
+void
+ocd_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 side, handling wierd errors. */
+
+static int
+readchar (timeout)
+ int timeout;
+{
+ int ch;
+
+ ch = SERIAL_READCHAR (ocd_desc, timeout);
+
+ switch (ch)
+ {
+ case SERIAL_EOF:
+ error ("Remote connection closed");
+ case SERIAL_ERROR:
+ perror_with_name ("Remote communication error");
+ case SERIAL_TIMEOUT:
+ default:
+ return ch;
+ }
+}
+
+#if 0
+/* Read a character from the data stream, dequoting as necessary. SYN is
+ treated special. Any SYNs appearing in the data stream are returned as the
+ distinct value RAW_SYN (which has a value > 8 bits and therefore cannot be
+ mistaken for real data). */
+
+static int
+get_quoted_char (timeout)
+ int timeout;
+{
+ int ch;
+
+ ch = readchar (timeout);
+
+ switch (ch)
+ {
+ case SERIAL_TIMEOUT:
+ error ("Timeout in mid-packet, aborting");
+ case SYN:
+ return RAW_SYN;
+ case DLE:
+ ch = readchar (timeout);
+ if (ch == SYN)
+ return RAW_SYN;
+ return ch & ~0100;
+ default:
+ return ch;
+ }
+}
+
+static unsigned char pkt[256 * 2 + 10], *pktp; /* Worst case */
+
+static void
+reset_packet ()
+{
+ pktp = pkt;
+}
+
+static void
+output_packet ()
+{
+ if (SERIAL_WRITE (ocd_desc, pkt, pktp - pkt))
+ perror_with_name ("output_packet: write failed");
+
+ reset_packet ();
+}
+
+/* Output a quoted character. SYNs and DLEs are quoted. Everything else goes
+ through untouched. */
+
+static void
+put_quoted_char (c)
+ int c;
+{
+ switch (c)
+ {
+ case SYN:
+ case DLE:
+ *pktp++ = DLE;
+ c |= 0100;
+ }
+
+ *pktp++ = c;
+}
+
+/* Send a packet to the OCD device. The packet framed by a SYN character,
+ a byte count and a checksum. The byte count only counts the number of
+ bytes between the count and the checksum. A count of zero actually
+ means 256. Any SYNs within the packet (including the checksum and
+ count) must be quoted. The quote character must be quoted as well.
+ Quoting is done by replacing the character with the two-character sequence
+ DLE, {char} | 0100. Note that the quoting mechanism has no effect on the
+ byte count. */
+
+static void
+stu_put_packet (buf, len)
+ unsigned char *buf;
+ int len;
+{
+ unsigned char checksum;
+ unsigned char c;
+
+ if (len == 0 || len > 256)
+ abort (); /* Can't represent 0 length packet */
+
+ reset_packet ();
+
+ checksum = 0;
+
+ put_quoted_char (RAW_SYN);
+
+ c = len;
+
+ do
+ {
+ checksum += c;
+
+ put_quoted_char (c);
+
+ c = *buf++;
+ }
+ while (len-- > 0);
+
+ put_quoted_char (-checksum & 0xff);
+
+ output_packet ();
+}
+
+#else
+
+/* Send a packet to the OCD device. The packet framed by a SYN character,
+ a byte count and a checksum. The byte count only counts the number of
+ bytes between the count and the checksum. A count of zero actually
+ means 256. Any SYNs within the packet (including the checksum and
+ count) must be quoted. The quote character must be quoted as well.
+ Quoting is done by replacing the character with the two-character sequence
+ DLE, {char} | 0100. Note that the quoting mechanism has no effect on the
+ byte count. */
+
+static void
+ocd_put_packet (buf, len)
+ unsigned char *buf;
+ int len;
+{
+ unsigned char checksum;
+ unsigned char c;
+ unsigned char *packet, *packet_ptr;
+
+ packet = alloca (len + 1 + 1); /* packet + SYN + checksum */
+ packet_ptr = packet;
+
+ checksum = 0;
+
+ *packet_ptr++ = 0x55;
+
+ while (len-- > 0)
+ {
+ c = *buf++;
+
+ checksum += c;
+ *packet_ptr++ = c;
+ }
+
+ *packet_ptr++ = -checksum;
+ if (SERIAL_WRITE (ocd_desc, packet, packet_ptr - packet))
+ perror_with_name ("output_packet: write failed");
+}
+#endif
+
+#if 0
+/* Get a packet from the OCD device. Timeout is only enforced for the
+ first byte of the packet. Subsequent bytes are expected to arrive in
+ time <= remote_timeout. Returns a pointer to a static buffer containing
+ the payload of the packet. *LENP contains the length of the packet.
+*/
+
+static unsigned char *
+stu_get_packet (cmd, lenp, timeout)
+ unsigned char cmd;
+ int *lenp;
+{
+ int ch;
+ int len;
+ static unsigned char buf[256 + 10], *p;
+ unsigned char checksum;
+
+ find_packet:
+
+ ch = get_quoted_char (timeout);
+
+ if (ch < 0)
+ error ("get_packet (readchar): %d", ch);
+
+ if (ch != RAW_SYN)
+ goto find_packet;
+
+ found_syn: /* Found the start of a packet */
+
+ p = buf;
+ checksum = 0;
+
+ len = get_quoted_char (remote_timeout);
+
+ if (len == RAW_SYN)
+ goto found_syn;
+
+ checksum += len;
+
+ if (len == 0)
+ len = 256;
+
+ len++; /* Include checksum */
+
+ while (len-- > 0)
+ {
+ ch = get_quoted_char (remote_timeout);
+ if (ch == RAW_SYN)
+ goto found_syn;
+
+ *p++ = ch;
+ checksum += ch;
+ }
+
+ if (checksum != 0)
+ goto find_packet;
+
+ if (cmd != buf[0])
+ error ("Response phase error. Got 0x%x, expected 0x%x", buf[0], cmd);
+
+ *lenp = p - buf - 1;
+ return buf;
+}
+
+#else
+
+/* Get a packet from the OCD device. Timeout is only enforced for the
+ first byte of the packet. Subsequent bytes are expected to arrive in
+ time <= remote_timeout. Returns a pointer to a static buffer containing
+ the payload of the packet. *LENP contains the length of the packet.
+*/
+
+static unsigned char *
+ocd_get_packet (cmd, lenp, timeout)
+ int cmd;
+ int *lenp;
+{
+ int ch;
+ int len;
+ int i;
+ static unsigned char packet[512];
+ unsigned char *packet_ptr;
+ unsigned char checksum;
+
+ ch = readchar (timeout);
+
+ if (ch < 0)
+ error ("ocd_get_packet (readchar): %d", ch);
+
+ if (ch != 0x55)
+ error ("ocd_get_packet (readchar): %d", ch);
+
+/* Found the start of a packet */
+
+ packet_ptr = packet;
+ checksum = 0;
+
+/* Read command char. That sort of tells us how long the packet is. */
+
+ ch = readchar (timeout);
+
+ if (ch < 0)
+ error ("ocd_get_packet (readchar): %d", ch);
+
+ *packet_ptr++ = ch;
+ checksum += ch;
+
+/* Get status. */
+
+ ch = readchar (timeout);
+
+ if (ch < 0)
+ error ("ocd_get_packet (readchar): %d", ch);
+ *packet_ptr++ = ch;
+ checksum += ch;
+
+/* Get error code. */
+
+ ch = readchar (timeout);
+
+ if (ch < 0)
+ error ("ocd_get_packet (readchar): %d", ch);
+ *packet_ptr++ = ch;
+ checksum += ch;
+
+ switch (ch) /* Figure out length of packet */
+ {
+ case 0x7: /* Write verify error? */
+ len = 8; /* write address, value read back */
+ break;
+ case 0x11: /* Bus error? */
+ /* write address, read flag */
+ case 0x15: /* Internal error */
+ len = 5; /* error code, vector */
+ break;
+ default: /* Error w/no params */
+ len = 0;
+ break;
+ case 0x0: /* Normal result */
+ switch (packet[0])
+ {
+ case OCD_AYT: /* Are You There? */
+ case OCD_SET_BAUD_RATE: /* Set Baud Rate */
+ case OCD_INIT: /* Initialize OCD device */
+ case OCD_SET_SPEED: /* Set Speed */
+ case OCD_SET_FUNC_CODE: /* Set Function Code */
+ case OCD_SET_CTL_FLAGS: /* Set Control Flags */
+ case OCD_SET_BUF_ADDR: /* Set Register Buffer Address */
+ case OCD_RUN: /* Run Target from PC */
+ case OCD_RUN_ADDR: /* Run Target from Specified Address */
+ case OCD_STOP: /* Stop Target */
+ case OCD_RESET_RUN: /* Reset Target and Run */
+ case OCD_RESET: /* Reset Target and Halt */
+ case OCD_STEP: /* Single Step */
+ case OCD_WRITE_REGS: /* Write Register */
+ case OCD_WRITE_MEM: /* Write Memory */
+ case OCD_FILL_MEM: /* Fill Memory */
+ case OCD_MOVE_MEM: /* Move Memory */
+ case OCD_WRITE_INT_MEM: /* Write Internal Memory */
+ case OCD_JUMP: /* Jump to Subroutine */
+ case OCD_ERASE_FLASH: /* Erase flash memory */
+ case OCD_PROGRAM_FLASH: /* Write flash memory */
+ case OCD_EXIT_MON: /* Exit the flash programming monitor */
+ case OCD_ENTER_MON: /* Enter the flash programming monitor */
+ case OCD_LOG_FILE: /* Make Wigglers.dll save Wigglers.log */
+ case OCD_SET_CONNECTION: /* Set type of connection in Wigglers.dll */
+ len = 0;
+ break;
+ case OCD_GET_VERSION: /* Get Version */
+ len = 10;
+ break;
+ case OCD_GET_STATUS_MASK: /* Get Status Mask */
+ len = 1;
+ break;
+ case OCD_GET_CTRS: /* Get Error Counters */
+ case OCD_READ_REGS: /* Read Register */
+ case OCD_READ_MEM: /* Read Memory */
+ case OCD_READ_INT_MEM: /* Read Internal Memory */
+ len = 257;
+ break;
+ default:
+ error ("ocd_get_packet: unknown packet type 0x%x\n", ch);
+ }
+ }
+
+ if (len == 257) /* Byte stream? */
+ { /* Yes, byte streams contain the length */
+ ch = readchar (timeout);
+
+ if (ch < 0)
+ error ("ocd_get_packet (readchar): %d", ch);
+ *packet_ptr++ = ch;
+ checksum += ch;
+ len = ch;
+ if (len == 0)
+ len = 256;
+ }
+
+ while (len-- >= 0) /* Do rest of packet and checksum */
+ {
+ ch = readchar (timeout);
+
+ if (ch < 0)
+ error ("ocd_get_packet (readchar): %d", ch);
+ *packet_ptr++ = ch;
+ checksum += ch;
+ }
+
+ if (checksum != 0)
+ error ("ocd_get_packet: bad packet checksum");
+
+ if (cmd != -1 && cmd != packet[0])
+ error ("Response phase error. Got 0x%x, expected 0x%x", packet[0], cmd);
+
+ *lenp = packet_ptr - packet - 1; /* Subtract checksum byte */
+ return packet;
+}
+#endif
+
+/* Execute a simple (one-byte) command. Returns a pointer to the data
+ following the error code. */
+
+static unsigned char *
+ocd_do_command (cmd, statusp, lenp)
+ int cmd;
+ int *statusp;
+ int *lenp;
+{
+ unsigned char buf[100], *p;
+ int status, error_code;
+ char errbuf[100];
+
+ unsigned char logbuf[100];
+ int logpktlen;
+
+ buf[0] = cmd;
+ ocd_put_packet (buf, 1); /* Send command */
+ p = ocd_get_packet (*buf, lenp, remote_timeout);
+
+ if (*lenp < 3)
+ error ("Truncated response packet from OCD device");
+
+ status = p[1];
+ error_code = p[2];
+
+ if (error_code != 0)
+ {
+ sprintf (errbuf, "ocd_do_command (0x%x):", cmd);
+ ocd_error (errbuf, error_code);
+ }
+
+ if (status & OCD_FLAG_PWF)
+ error ("OCD device can't detect VCC at BDM interface.");
+ else if (status & OCD_FLAG_CABLE_DISC)
+ error ("BDM cable appears to be disconnected.");
+
+ *statusp = status;
+
+ logbuf[0] = OCD_LOG_FILE;
+ logbuf[1] = 3; /* close existing WIGGLERS.LOG */
+ ocd_put_packet (logbuf, 2);
+ ocd_get_packet (logbuf[0], &logpktlen, remote_timeout);
+
+ logbuf[0] = OCD_LOG_FILE;
+ logbuf[1] = 2; /* append to existing WIGGLERS.LOG */
+ ocd_put_packet (logbuf, 2);
+ ocd_get_packet (logbuf[0], &logpktlen, remote_timeout);
+
+ return p + 3;
+}
+
+void
+ocd_kill ()
+{
+ /* For some mysterious reason, wait_for_inferior calls kill instead of
+ mourn after it gets TARGET_WAITKIND_SIGNALLED. Work around it. */
+ if (kill_kludge)
+ {
+ kill_kludge = 0;
+ target_mourn_inferior ();
+ return;
+ }
+
+ /* Don't wait for it to die. I'm not really sure it matters whether
+ we do or not. */
+ target_mourn_inferior ();
+}
+
+void
+ocd_mourn ()
+{
+ unpush_target (current_ops);
+ generic_mourn_inferior ();
+}
+
+/* All we actually do is set the PC to the start address of exec_bfd, and start
+ the program at that point. */
+
+void
+ocd_create_inferior (exec_file, args, env)
+ char *exec_file;
+ char *args;
+ char **env;
+{
+ if (args && (*args != '\000'))
+ error ("Args are not supported by BDM.");
+
+ clear_proceed_status ();
+ proceed (bfd_get_start_address (exec_bfd), TARGET_SIGNAL_0, 0);
+}
+
+void
+ocd_load (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ generic_load (args, from_tty);
+
+ inferior_pid = 0;
+
+/* This is necessary because many things were based on the PC at the time that
+ we attached to the monitor, which is no longer valid now that we have loaded
+ new code (and just changed the PC). Another way to do this might be to call
+ normal_stop, except that the stack may not be valid, and things would get
+ horribly confused... */
+
+ clear_symtab_users ();
+}
+
+/* This should be defined for each target */
+/* But we want to be able to compile this file for some configurations
+ not yet supported fully */
+
+#define BDM_BREAKPOINT {0x0,0x0,0x0,0x0} /* For ppc 8xx */
+#if 0
+#define BDM_BREAKPOINT {0x4a,0xfa} /* BGND insn used for CPU32 */
+#endif
+
+/* BDM (at least on CPU32) uses a different breakpoint */
+
+int
+ocd_insert_breakpoint (addr, contents_cache)
+ CORE_ADDR addr;
+ char *contents_cache;
+{
+ static char break_insn[] = BDM_BREAKPOINT;
+ int val;
+
+ val = target_read_memory (addr, contents_cache, sizeof (break_insn));
+
+ if (val == 0)
+ val = target_write_memory (addr, break_insn, sizeof (break_insn));
+
+ return val;
+}
+
+int
+ocd_remove_breakpoint (addr, contents_cache)
+ CORE_ADDR addr;
+ char *contents_cache;
+{
+ static char break_insn[] = BDM_BREAKPOINT;
+ int val;
+
+ val = target_write_memory (addr, contents_cache, sizeof (break_insn));
+
+ return val;
+}
+
+static void
+bdm_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ error ("bdm command must be followed by `reset'");
+}
+
+static void
+bdm_reset_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ int status, pktlen;
+
+ if (!ocd_desc)
+ error ("Not connected to OCD device.");
+
+ ocd_do_command (OCD_RESET, &status, &pktlen);
+ dcache_flush (ocd_dcache);
+ registers_changed ();
+}
+
+static void
+bdm_restart_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ int status, pktlen;
+
+ if (!ocd_desc)
+ error ("Not connected to OCD device.");
+
+ ocd_do_command (OCD_RESET_RUN, &status, &pktlen);
+ last_run_status = status;
+ clear_proceed_status ();
+ wait_for_inferior ();
+ normal_stop ();
+}
+
+/* Temporary replacement for target_store_registers(). This prevents
+ generic_load from trying to set the PC. */
+
+static void
+noop_store_registers (regno)
+ int regno;
+{
+}
+
+static void
+bdm_update_flash_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ int status, pktlen;
+ struct cleanup *old_chain;
+ void (*store_registers_tmp) PARAMS ((int));
+
+ if (!ocd_desc)
+ error ("Not connected to OCD device.");
+
+ if (!args)
+ error ("Must specify file containing new OCD code.");
+
+/* old_chain = make_cleanup (flash_cleanup, 0);*/
+
+ ocd_do_command (OCD_ENTER_MON, &status, &pktlen);
+
+ ocd_do_command (OCD_ERASE_FLASH, &status, &pktlen);
+
+ write_mem_command = OCD_PROGRAM_FLASH;
+ store_registers_tmp = current_target.to_store_registers;
+ current_target.to_store_registers = noop_store_registers;
+
+ generic_load (args, from_tty);
+
+ current_target.to_store_registers = store_registers_tmp;
+ write_mem_command = OCD_WRITE_MEM;
+
+ ocd_do_command (OCD_EXIT_MON, &status, &pktlen);
+
+/* discard_cleanups (old_chain);*/
+}
+
+static void
+bdm_read_register_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ /* XXX repeat should go on to the next register */
+
+ if (!ocd_desc)
+ error ("Not connected to OCD device.");
+
+ if (!args)
+ error ("Must specify BDM register number.");
+
+}
+
+void
+_initialize_remote_ocd ()
+{
+ extern struct cmd_list_element *cmdlist;
+ static struct cmd_list_element *ocd_cmd_list = NULL;
+
+ add_show_from_set (add_set_cmd ("remotetimeout", no_class,
+ var_integer, (char *)&remote_timeout,
+ "Set timeout value for remote read.\n", &setlist),
+ &showlist);
+
+ add_prefix_cmd ("ocd", class_obscure, bdm_command, "", &ocd_cmd_list, "ocd ",
+ 0, &cmdlist);
+
+ add_cmd ("reset", class_obscure, bdm_reset_command, "", &ocd_cmd_list);
+ add_cmd ("restart", class_obscure, bdm_restart_command, "", &ocd_cmd_list);
+ add_cmd ("update-flash", class_obscure, bdm_update_flash_command, "", &ocd_cmd_list);
+ /* add_cmd ("read-register", class_obscure, bdm_read_register_command, "", &ocd_cmd_list);*/
+}
diff --git a/gdb/ocd.h b/gdb/ocd.h
new file mode 100644
index 00000000000..020d3e2a41d
--- /dev/null
+++ b/gdb/ocd.h
@@ -0,0 +1,139 @@
+/* Definitions for the Macraigor Systems BDM Wiggler
+ Copyright 1996, 1997 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef OCD_H
+#define OCD_H
+
+/* Wiggler serial protocol definitions */
+
+#define DLE 020 /* Quote char */
+#define SYN 026 /* Start of packet */
+#define RAW_SYN ((026 << 8) | 026) /* get_quoted_char found a naked SYN */
+
+/* Status flags */
+
+#define OCD_FLAG_RESET 0x01 /* Target is being reset */
+#define OCD_FLAG_STOPPED 0x02 /* Target is halted */
+#define OCD_FLAG_BDM 0x04 /* Target is in BDM */
+#define OCD_FLAG_PWF 0x08 /* Power failed */
+#define OCD_FLAG_CABLE_DISC 0x10 /* BDM cable disconnected */
+
+/* Commands */
+
+#define OCD_AYT 0x0 /* Are you there? */
+#define OCD_GET_VERSION 0x1 /* Get Version */
+#define OCD_SET_BAUD_RATE 0x2 /* Set Baud Rate */
+#define OCD_INIT 0x10 /* Initialize Wiggler */
+#define OCD_SET_SPEED 0x11 /* Set Speed */
+#define OCD_GET_STATUS_MASK 0x12 /* Get Status Mask */
+#define OCD_GET_CTRS 0x13 /* Get Error Counters */
+#define OCD_SET_FUNC_CODE 0x14 /* Set Function Code */
+#define OCD_SET_CTL_FLAGS 0x15 /* Set Control Flags */
+#define OCD_SET_BUF_ADDR 0x16 /* Set Register Buffer Address */
+#define OCD_RUN 0x20 /* Run Target from PC */
+#define OCD_RUN_ADDR 0x21 /* Run Target from Specified Address */
+#define OCD_STOP 0x22 /* Stop Target */
+#define OCD_RESET_RUN 0x23 /* Reset Target and Run */
+#define OCD_RESET 0x24 /* Reset Target and Halt */
+#define OCD_STEP 0x25 /* Single step */
+#define OCD_READ_REGS 0x30 /* Read Registers */
+#define OCD_WRITE_REGS 0x31 /* Write Registers */
+#define OCD_READ_MEM 0x32 /* Read Memory */
+#define OCD_WRITE_MEM 0x33 /* Write Memory */
+#define OCD_FILL_MEM 0x34 /* Fill Memory */
+#define OCD_MOVE_MEM 0x35 /* Move Memory */
+
+#define OCD_READ_INT_MEM 0x80 /* Read Internal Memory */
+#define OCD_WRITE_INT_MEM 0x81 /* Write Internal Memory */
+#define OCD_JUMP 0x82 /* Jump to Subroutine */
+
+#define OCD_ERASE_FLASH 0x90 /* Erase flash memory */
+#define OCD_PROGRAM_FLASH 0x91 /* Write flash memory */
+#define OCD_EXIT_MON 0x93 /* Exit the flash programming monitor */
+#define OCD_ENTER_MON 0x94 /* Enter the flash programming monitor */
+
+#define OCD_SET_STATUS 0x0a /* Set status */
+#define OCD_SET_CONNECTION 0xf0 /* Set connection (init Wigglers.dll) */
+#define OCD_LOG_FILE 0xf1 /* Cmd to get Wigglers.dll to log cmds */
+#define OCD_FLAG_STOP 0x0 /* Stop the target, enter BDM */
+#define OCD_FLAG_START 0x01 /* Start the target at PC */
+#define OCD_FLAG_RETURN_STATUS 0x04 /* Return async status */
+
+/* Target type (for OCD_INIT command) */
+
+enum ocd_target_type {
+ OCD_TARGET_CPU32=0x0, /* Moto cpu32 family */
+ OCD_TARGET_CPU16=0x1,
+ OCD_TARGET_MOTO_PPC=0x2, /* Motorola PPC 5xx/8xx */
+ OCD_TARGET_IBM_PPC=0x3}; /* IBM PPC 4xx */
+
+void ocd_open PARAMS ((char *name, int from_tty, enum ocd_target_type,
+ struct target_ops *ops));
+
+void ocd_close PARAMS ((int quitting));
+
+void ocd_detach PARAMS ((char *args, int from_tty));
+
+void ocd_resume PARAMS ((int pid, int step, enum target_signal siggnal));
+
+void ocd_prepare_to_store PARAMS ((void));
+
+void ocd_stop PARAMS ((void));
+
+void ocd_files_info PARAMS ((struct target_ops *ignore));
+
+
+int ocd_xfer_memory PARAMS ((CORE_ADDR memaddr, char *myaddr,
+ int len, int should_write,
+ struct target_ops *target));
+
+void ocd_mourn PARAMS ((void));
+
+void ocd_create_inferior PARAMS ((char *exec_file,
+ char *args,
+ char **env));
+
+int ocd_thread_alive PARAMS ((int th));
+
+void ocd_error PARAMS ((char *s, int error_code));
+
+void ocd_kill PARAMS ((void));
+
+void ocd_load PARAMS((char *args, int from_tty));
+
+unsigned char * ocd_read_bdm_registers PARAMS ((int first_bdm_regno,
+ int last_bdm_regno,
+ int *reglen));
+
+CORE_ADDR ocd_read_bdm_register PARAMS ((int bdm_regno));
+
+void ocd_write_bdm_registers PARAMS ((int first_bdm_regno,
+ unsigned char *regptr,
+ int reglen));
+
+void ocd_write_bdm_register PARAMS ((int bdm_regno, CORE_ADDR reg));
+
+int ocd_wait PARAMS ((void));
+
+int ocd_insert_breakpoint PARAMS ((CORE_ADDR addr, char *contents_cache));
+int ocd_remove_breakpoint PARAMS ((CORE_ADDR addr, char *contents_cache));
+
+int ocd_write_bytes PARAMS ((CORE_ADDR memaddr, char *myaddr, int len));
+
+#endif /* OCD_H */
diff --git a/gdb/op50-rom.c b/gdb/op50-rom.c
new file mode 100644
index 00000000000..32620918414
--- /dev/null
+++ b/gdb/op50-rom.c
@@ -0,0 +1,142 @@
+/* Remote target glue for the Oki op50n based eval board.
+
+ Copyright 1995 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "gdbcore.h"
+#include "target.h"
+#include "monitor.h"
+#include "serial.h"
+
+static void op50n_open PARAMS ((char *args, int from_tty));
+
+/*
+ * this array of registers need to match the indexes used by GDB. The
+ * whole reason this exists is cause the various ROM monitors use
+ * different strings than GDB does, and doesn't support all the
+ * registers either. So, typing "info reg sp" becomes a "r30".
+ */
+
+static char *op50n_regnames[NUM_REGS] =
+{
+ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
+ "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
+ "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
+ "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
+ "cr11", "p", NULL, NULL, NULL, "cr15", "cr19", "cr20",
+ "cr21", "cr22", NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, "cr0", "cr8", "cr9", "cr10","cr12",
+ "cr13", "cr24", "cr25", "cr26",
+};
+
+/*
+ * Define the monitor command strings. Since these are passed directly
+ * through to a printf style function, we need can include formatting
+ * strings. We also need a CR or LF on the end.
+ */
+
+static struct target_ops op50n_ops;
+
+static char *op50n_inits[] = {".\r", NULL};
+
+static struct monitor_ops op50n_cmds ;
+
+static void
+init_op50n_cmds(void)
+{
+ op50n_cmds.flags = MO_CLR_BREAK_USES_ADDR /*| MO_GETMEM_READ_SINGLE*/; /* flags */
+ op50n_cmds.init = op50n_inits; /* Init strings */
+ op50n_cmds.cont = "g\r"; /* continue command */
+ op50n_cmds.step = "t\r"; /* single step */
+ op50n_cmds.stop = "\003.\r"; /* Interrupt char */
+ op50n_cmds.set_break = "b %x\r"; /* set a breakpoint */
+ op50n_cmds.clr_break = "b %x;0\r"; /* clear breakpoint at addr */
+ op50n_cmds.clr_all_break = "bx\r"; /* clear all breakpoints */
+ op50n_cmds.fill = "fx %x s%x %x\r"; /* memory fill cmd (addr, len, val) */
+ op50n_cmds.setmem.cmdb = "sx %x %x\r"; /* setmem.cmdb (addr, value) */
+ op50n_cmds.setmem.cmdw = "sh %x %x\r"; /* setmem.cmdw (addr, value) */
+ op50n_cmds.setmem.cmdl = "s %x %x\r"; /* setmem.cmdl (addr, value) */
+ op50n_cmds.setmem.cmdll = NULL; /* setmem.cmdll (addr, value) */
+ op50n_cmds.setmem.resp_delim = NULL; /* setmem.resp_delim */
+ op50n_cmds.setmem.term = NULL; /* setmem.term */
+ op50n_cmds.setmem.term_cmd = NULL; /* setmem.term_cmd */
+#if 0
+ {
+ "sx %x\r", /* getmem.cmdb (addr, len) */
+ "sh %x\r", /* getmem.cmdw (addr, len) */
+ "s %x\r", /* getmem.cmdl (addr, len) */
+ NULL, /* getmem.cmdll (addr, len) */
+ " : ", /* getmem.resp_delim */
+ " ", /* getmem.term */
+ ".\r", /* getmem.term_cmd */
+ } ;
+#else
+ op50n_cmds.getmem.cmdb = "dx %x s%x\r"; /* getmem.cmdb (addr, len) */
+ op50n_cmds.getmem.cmdw = NULL; /* getmem.cmdw (addr, len) */
+ op50n_cmds.getmem.cmdl = NULL; /* getmem.cmdl (addr, len) */
+ op50n_cmds.getmem.cmdll = NULL; /* getmem.cmdll (addr, len) */
+ op50n_cmds.getmem.resp_delim = " : "; /* getmem.resp_delim */
+ op50n_cmds.getmem.term = NULL; /* getmem.term */
+ op50n_cmds.getmem.term_cmd = NULL; /* getmem.term_cmd */
+#endif
+ op50n_cmds.setreg.cmd = "x %s %x\r"; /* setreg.cmd (name, value) */
+ op50n_cmds.setreg.resp_delim = NULL; /* setreg.resp_delim */
+ op50n_cmds.setreg.term = NULL; /* setreg.term */
+ op50n_cmds.setreg.term_cmd = NULL; /* setreg.term_cmd */
+ op50n_cmds.getreg.cmd = "x %s\r"; /* getreg.cmd (name) */
+ op50n_cmds.getreg.resp_delim = "="; /* getreg.resp_delim */
+ op50n_cmds.getreg.term = " "; /* getreg.term */
+ op50n_cmds.getreg.term_cmd = ".\r"; /* getreg.term_cmd */
+ op50n_cmds.dump_registers = NULL; /* dump_registers */
+ op50n_cmds.register_pattern = NULL; /* register_pattern */
+ op50n_cmds.supply_register = NULL; /* supply_register */
+ op50n_cmds.load_routine = NULL; /* load routine */
+ op50n_cmds.load = "r 0\r"; /* download command */
+ op50n_cmds.loadresp = NULL; /* load response */
+ op50n_cmds.prompt = "\n#"; /* monitor command prompt */
+ op50n_cmds.line_term = "\r"; /* end-of-command delimitor */
+ op50n_cmds.cmd_end = NULL; /* optional command terminator */
+ op50n_cmds.target = &op50n_ops; /* target operations */
+ op50n_cmds.stopbits = SERIAL_1_STOPBITS; /* number of stop bits */
+ op50n_cmds.regnames = op50n_regnames; /* register names */
+ op50n_cmds.magic = MONITOR_OPS_MAGIC; /* magic */
+};
+
+static void
+op50n_open (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ monitor_open (args, &op50n_cmds, from_tty);
+}
+
+void
+_initialize_op50n ()
+{
+ init_op50n_cmds() ;
+ init_monitor_ops (&op50n_ops);
+
+ op50n_ops.to_shortname = "op50n";
+ op50n_ops.to_longname = "Oki's debug monitor for the Op50n Eval board";
+ op50n_ops.to_doc = "Debug on a Oki OP50N eval board.\n\
+Specify the serial device it is connected to (e.g. /dev/ttya).";
+ op50n_ops.to_open = op50n_open;
+
+ add_target (&op50n_ops);
+}
diff --git a/gdb/os9kread.c b/gdb/os9kread.c
new file mode 100644
index 00000000000..673d415c6e2
--- /dev/null
+++ b/gdb/os9kread.c
@@ -0,0 +1,1624 @@
+/* Read os9/os9k symbol tables and convert to internal format, for GDB.
+ Copyright 1986, 87, 88, 89, 90, 91, 92, 93, 94, 96, 1998
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* This module provides three functions: os9k_symfile_init,
+ which initializes to read a symbol file; os9k_new_init, which
+ discards existing cached information when all symbols are being
+ discarded; and os9k_symfile_read, which reads a symbol table
+ from a file.
+
+ os9k_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. os9k_psymtab_to_symtab() is the function that does this */
+
+#include "defs.h"
+#include "gdb_string.h"
+#include <stdio.h>
+
+#if defined(USG) || defined(__CYGNUSCLIB__)
+#include <sys/types.h>
+#include <fcntl.h>
+#endif
+
+#include "obstack.h"
+#include "gdb_stat.h"
+#include <ctype.h>
+#include "symtab.h"
+#include "breakpoint.h"
+#include "command.h"
+#include "target.h"
+#include "gdbcore.h" /* for bfd stuff */
+#include "libaout.h" /* FIXME Secret internal BFD stuff for a.out */
+#include "symfile.h"
+#include "objfiles.h"
+#include "buildsym.h"
+#include "gdb-stabs.h"
+#include "demangle.h"
+#include "language.h" /* Needed inside partial-stab.h */
+#include "complaints.h"
+#include "os9k.h"
+#include "stabsread.h"
+
+/* 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 count 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 ldsymcnt 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 LDSYMCNT(p) (((struct symloc *)((p)->read_symtab_private))->ldsymnum)
+
+struct symloc {
+ int ldsymoff;
+ int ldsymnum;
+};
+
+/* Remember what we deduced to be the source language of this psymtab. */
+static enum language psymtab_language = language_unknown;
+
+/* keep partial symbol table file nested depth */
+static int psymfile_depth = 0;
+
+/* keep symbol table file nested depth */
+static int symfile_depth = 0;
+
+/* Nonzero means give verbose info on gdb action. From main.c. */
+extern int info_verbose;
+
+extern int previous_stab_code;
+
+/* Name of last function encountered. Used in Solaris to approximate
+ object file boundaries. */
+static char *last_function_name;
+
+/* Complaints about the symbols we have encountered. */
+extern struct complaint lbrac_complaint;
+
+extern struct complaint unknown_symtype_complaint;
+
+extern struct complaint unknown_symchar_complaint;
+
+extern struct complaint lbrac_rbrac_complaint;
+
+extern struct complaint repeated_header_complaint;
+
+extern struct complaint repeated_header_name_complaint;
+
+#if 0
+static struct complaint lbrac_unmatched_complaint =
+ {"unmatched Increment Block Entry before symtab pos %d", 0, 0};
+
+static struct complaint lbrac_mismatch_complaint =
+ {"IBE/IDE symbol mismatch at symtab pos %d", 0, 0};
+#endif
+
+/* Local function prototypes */
+
+static void
+read_minimal_symbols PARAMS ((struct objfile *, struct section_offsets *));
+
+static void
+os9k_read_ofile_symtab PARAMS ((struct partial_symtab *));
+
+static void
+os9k_psymtab_to_symtab PARAMS ((struct partial_symtab *));
+
+static void
+os9k_psymtab_to_symtab_1 PARAMS ((struct partial_symtab *));
+
+static void
+read_os9k_psymtab PARAMS ((struct section_offsets *, struct objfile *,
+ CORE_ADDR, int));
+
+static int
+fill_sym PARAMS ((FILE *, bfd *));
+
+static void
+os9k_symfile_init PARAMS ((struct objfile *));
+
+static void
+os9k_new_init PARAMS ((struct objfile *));
+
+static void
+os9k_symfile_read PARAMS ((struct objfile *, struct section_offsets *, int));
+
+static void
+os9k_symfile_finish PARAMS ((struct objfile *));
+
+static void
+os9k_process_one_symbol PARAMS ((int, int, CORE_ADDR, char *,
+ struct section_offsets *, struct objfile *));
+
+static struct partial_symtab *
+os9k_start_psymtab PARAMS ((struct objfile *, struct section_offsets *, char *,
+ CORE_ADDR, int, int, struct partial_symbol **,
+ struct partial_symbol **));
+
+static struct partial_symtab *
+os9k_end_psymtab PARAMS ((struct partial_symtab *, char **, int, int, CORE_ADDR,
+ struct partial_symtab **, int));
+
+static void
+record_minimal_symbol PARAMS ((char *, CORE_ADDR, int, struct objfile *,
+ struct section_offsets *));
+
+#define HANDLE_RBRAC(val) \
+ if ((val) > pst->texthigh) pst->texthigh = (val);
+
+#define SWAP_STBHDR(hdrp, abfd) \
+ { \
+ (hdrp)->fmtno = bfd_get_16(abfd, (unsigned char *)&(hdrp)->fmtno); \
+ (hdrp)->crc = bfd_get_32(abfd, (unsigned char *)&(hdrp)->crc); \
+ (hdrp)->offset = bfd_get_32(abfd, (unsigned char *)&(hdrp)->offset); \
+ (hdrp)->nsym = bfd_get_32(abfd, (unsigned char *)&(hdrp)->nsym); \
+ }
+#define SWAP_STBSYM(symp, abfd) \
+ { \
+ (symp)->value = bfd_get_32(abfd, (unsigned char *)&(symp)->value); \
+ (symp)->type = bfd_get_16(abfd, (unsigned char *)&(symp)->type); \
+ (symp)->stroff = bfd_get_32(abfd, (unsigned char *)&(symp)->stroff); \
+ }
+#define N_DATA 0
+#define N_BSS 1
+#define N_RDATA 2
+#define N_IDATA 3
+#define N_TEXT 4
+#define N_ABS 6
+
+static void
+record_minimal_symbol (name, address, type, objfile, section_offsets)
+ char *name;
+ CORE_ADDR address;
+ int type;
+ struct objfile *objfile;
+ struct section_offsets *section_offsets;
+{
+ enum minimal_symbol_type ms_type;
+
+ switch (type)
+ {
+ case N_TEXT:
+ ms_type = mst_text;
+ address += ANOFFSET(section_offsets, SECT_OFF_TEXT);
+ break;
+ case N_DATA:
+ ms_type = mst_data;
+ break;
+ case N_BSS:
+ ms_type = mst_bss;
+ break;
+ case N_RDATA:
+ ms_type = mst_bss;
+ break;
+ case N_IDATA:
+ ms_type = mst_data;
+ break;
+ case N_ABS:
+ ms_type = mst_abs;
+ break;
+ default:
+ ms_type = mst_unknown; break;
+ }
+
+ prim_record_minimal_symbol (name, address, ms_type, objfile);
+}
+
+/* read and process .stb file and store in minimal symbol table */
+typedef char mhhdr[80];
+struct stbhdr {
+ mhhdr comhdr;
+ char * name;
+ short fmtno;
+ int crc;
+ int offset;
+ int nsym;
+ char *pad;
+};
+struct stbsymbol {
+ int value;
+ short type;
+ int stroff;
+};
+#define STBSYMSIZE 10
+
+static void
+read_minimal_symbols(objfile, section_offsets)
+ struct objfile *objfile;
+ struct section_offsets *section_offsets;
+{
+FILE *fp;
+bfd *abfd;
+struct stbhdr hdr;
+struct stbsymbol sym;
+int ch, i, j, off;
+char buf[64], buf1[128];
+
+ fp = objfile->auxf1;
+ if (fp == NULL) return;
+ abfd = objfile->obfd;
+ fread(&hdr.comhdr[0], sizeof(mhhdr), 1, fp);
+ i = 0;
+ ch = getc(fp);
+ while (ch != -1) {
+ buf[i] = (char)ch;
+ i++;
+ if (ch == 0) break;
+ ch = getc(fp);
+ };
+ if (i%2) ch=getc(fp);
+ hdr.name = &buf[0];
+
+ fread(&hdr.fmtno, sizeof(hdr.fmtno), 1, fp);
+ fread(&hdr.crc, sizeof(hdr.crc), 1, fp);
+ fread(&hdr.offset, sizeof(hdr.offset), 1, fp);
+ fread(&hdr.nsym, sizeof(hdr.nsym), 1, fp);
+ SWAP_STBHDR(&hdr, abfd);
+
+ /* read symbols */
+ init_minimal_symbol_collection();
+ off = hdr.offset;
+ for (i = hdr.nsym; i > 0; i--) {
+ fseek(fp, (long)off, 0);
+ fread(&sym.value, sizeof(sym.value), 1, fp);
+ fread(&sym.type, sizeof(sym.type), 1, fp);
+ fread(&sym.stroff, sizeof(sym.stroff), 1, fp);
+ SWAP_STBSYM (&sym, abfd);
+ fseek(fp, (long)sym.stroff, 0);
+ j = 0;
+ ch = getc(fp);
+ while (ch != -1) {
+ buf1[j] = (char)ch;
+ j++;
+ if (ch == 0) break;
+ ch = getc(fp);
+ };
+ record_minimal_symbol(buf1, sym.value, sym.type&7, objfile, section_offsets);
+ off += STBSYMSIZE;
+ };
+ install_minimal_symbols (objfile);
+ return;
+}
+
+/* Scan and build partial symbols for a symbol file.
+ We have been initialized by a call to os9k_symfile_init, which
+ put all the relevant info into a "struct os9k_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
+os9k_symfile_read (objfile, section_offsets, mainline)
+ struct objfile *objfile;
+ struct section_offsets *section_offsets;
+ int mainline; /* FIXME comments above */
+{
+ bfd *sym_bfd;
+ struct cleanup *back_to;
+
+ sym_bfd = objfile->obfd;
+ /* 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, DBX_SYMCOUNT (objfile));
+
+ free_pending_blocks ();
+ back_to = make_cleanup ((make_cleanup_func) really_free_pendings, 0);
+
+ make_cleanup ((make_cleanup_func) discard_minimal_symbols, 0);
+ read_minimal_symbols (objfile, section_offsets);
+
+ /* Now that the symbol table data of the executable file are all in core,
+ process them and define symbols accordingly. */
+ read_os9k_psymtab (section_offsets, objfile,
+ DBX_TEXT_ADDR (objfile),
+ DBX_TEXT_SIZE (objfile));
+
+ 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
+os9k_new_init (ignore)
+ struct objfile *ignore;
+{
+ stabsread_new_init ();
+ buildsym_new_init ();
+ psymfile_depth = 0;
+/*
+ init_header_files ();
+*/
+}
+
+/* os9k_symfile_init ()
+ 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.
+
+ 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. */
+
+static void
+os9k_symfile_init (objfile)
+ struct objfile *objfile;
+{
+ bfd *sym_bfd = objfile->obfd;
+ char *name = bfd_get_filename (sym_bfd);
+ char dbgname[512], stbname[512];
+ FILE *symfile = 0;
+ FILE *minfile = 0;
+ asection *text_sect;
+
+ strcpy(dbgname, name);
+ strcat(dbgname, ".dbg");
+ strcpy(stbname, name);
+ strcat(stbname, ".stb");
+
+ if ((symfile = fopen(dbgname, "r")) == NULL) {
+ warning("Symbol file %s not found", dbgname);
+ }
+ objfile->auxf2 = symfile;
+
+ if ((minfile = fopen(stbname, "r")) == NULL) {
+ warning("Symbol file %s not found", stbname);
+ }
+ objfile->auxf1 = minfile;
+
+ /* Allocate struct to keep track of the symfile */
+ objfile->sym_stab_info = (struct dbx_symfile_info *)
+ xmmalloc (objfile -> md, sizeof (struct dbx_symfile_info));
+ DBX_SYMFILE_INFO (objfile)->stab_section_info = NULL;
+
+ text_sect = bfd_get_section_by_name (sym_bfd, ".text");
+ if (!text_sect)
+ error ("Can't find .text section in file");
+ DBX_TEXT_ADDR (objfile) = bfd_section_vma (sym_bfd, text_sect);
+ DBX_TEXT_SIZE (objfile) = bfd_section_size (sym_bfd, text_sect);
+
+ DBX_SYMBOL_SIZE (objfile) = 0; /* variable size symbol */
+ DBX_SYMCOUNT (objfile) = 0; /* used to be bfd_get_symcount(sym_bfd) */
+ DBX_SYMTAB_OFFSET (objfile) = 0; /* used to be SYMBOL_TABLE_OFFSET */
+}
+
+/* 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
+os9k_symfile_finish (objfile)
+ struct objfile *objfile;
+{
+ if (objfile->sym_stab_info != NULL)
+ {
+ mfree (objfile -> md, objfile->sym_stab_info);
+ }
+/*
+ free_header_files ();
+*/
+}
+
+
+struct st_dbghdr {
+ int sync;
+ short rev;
+ int crc;
+ short os;
+ short cpu;
+};
+#define SYNC (int)0xefbefeca
+
+#define SWAP_DBGHDR(hdrp, abfd) \
+ { \
+ (hdrp)->sync = bfd_get_32(abfd, (unsigned char *)&(hdrp)->sync); \
+ (hdrp)->rev = bfd_get_16(abfd, (unsigned char *)&(hdrp)->rev); \
+ (hdrp)->crc = bfd_get_32(abfd, (unsigned char *)&(hdrp)->crc); \
+ (hdrp)->os = bfd_get_16(abfd, (unsigned char *)&(hdrp)->os); \
+ (hdrp)->cpu = bfd_get_16(abfd, (unsigned char *)&(hdrp)->cpu); \
+ }
+
+#define N_SYM_CMPLR 0
+#define N_SYM_SLINE 1
+#define N_SYM_SYM 2
+#define N_SYM_LBRAC 3
+#define N_SYM_RBRAC 4
+#define N_SYM_SE 5
+
+struct internal_symstruct {
+ short n_type;
+ short n_desc;
+ long n_value;
+ char * n_strx;
+};
+static struct internal_symstruct symbol;
+static struct internal_symstruct *symbuf = &symbol;
+static char strbuf[4096];
+static struct st_dbghdr dbghdr;
+static short cmplrid;
+
+#define VER_PRE_ULTRAC ((short)4)
+#define VER_ULTRAC ((short)5)
+
+static int
+fill_sym (dbg_file, abfd)
+ FILE *dbg_file;
+ bfd *abfd;
+{
+short si, nmask;
+long li;
+int ii;
+char *p;
+
+ int nbytes = fread(&si, sizeof(si), 1, dbg_file);
+ if (nbytes == 0)
+ return 0;
+ if (nbytes < 0)
+ perror_with_name ("reading .dbg file.");
+ symbuf->n_desc = 0;
+ symbuf->n_value = 0;
+ symbuf->n_strx = NULL;
+ symbuf->n_type = bfd_get_16 (abfd, (unsigned char *)&si);
+ symbuf->n_type = 0xf & symbuf->n_type;
+ switch (symbuf->n_type)
+ {
+ case N_SYM_CMPLR:
+ fread(&si, sizeof(si), 1, dbg_file);
+ symbuf->n_desc = bfd_get_16(abfd, (unsigned char *)&si);
+ cmplrid = symbuf->n_desc & 0xff;
+ break;
+ case N_SYM_SLINE:
+ fread(&li, sizeof(li), 1, dbg_file);
+ symbuf->n_value = bfd_get_32(abfd, (unsigned char *)&li);
+ fread(&li, sizeof(li), 1, dbg_file);
+ li = bfd_get_32(abfd, (unsigned char *)&li);
+ symbuf->n_strx = (char *)(li >> 12);
+ symbuf->n_desc = li & 0xfff;
+ break;
+ case N_SYM_SYM:
+ fread(&li, sizeof(li), 1, dbg_file);
+ symbuf->n_value = bfd_get_32(abfd, (unsigned char *)&li);
+ si = 0;
+ do {
+ ii = getc(dbg_file);
+ strbuf[si++] = (char) ii;
+ } while (ii != 0 || si % 2 != 0);
+ symbuf->n_strx = strbuf;
+ p = (char *) strchr (strbuf, ':');
+ if (!p) break;
+ if ((p[1] == 'F' || p[1] == 'f') && cmplrid == VER_PRE_ULTRAC)
+ {
+ fread(&si, sizeof(si), 1, dbg_file);
+ nmask = bfd_get_16(abfd, (unsigned char *)&si);
+ for (ii=0; ii<nmask; ii++)
+ fread(&si, sizeof(si), 1, dbg_file);
+ }
+ break;
+ case N_SYM_LBRAC:
+ fread(&li, sizeof(li), 1, dbg_file);
+ symbuf->n_value = bfd_get_32(abfd, (unsigned char *)&li);
+ break;
+ case N_SYM_RBRAC:
+ fread(&li, sizeof(li), 1, dbg_file);
+ symbuf->n_value = bfd_get_32(abfd, (unsigned char *)&li);
+ break;
+ case N_SYM_SE:
+ break;
+ }
+ return 1;
+}
+
+/* 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_os9k_psymtab (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_symstruct *bufp = 0; /* =0 avoids gcc -Wall glitch*/
+ register char *namestring;
+ int past_first_source_file = 0;
+ CORE_ADDR last_o_file_start = 0;
+#if 0
+ struct cleanup *back_to;
+#endif
+ bfd *abfd;
+ FILE *fp;
+
+ /* End of the text segment of the executable file. */
+ static CORE_ADDR end_of_text_addr;
+
+ /* Current partial symtab */
+ static struct partial_symtab *pst = 0;
+
+ /* 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;
+
+ 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 *));
+
+ 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
+
+ abfd = objfile->obfd;
+ fp = objfile->auxf2;
+ if (!fp) return;
+
+ fread(&dbghdr.sync, sizeof(dbghdr.sync), 1, fp);
+ fread(&dbghdr.rev, sizeof(dbghdr.rev), 1, fp);
+ fread(&dbghdr.crc, sizeof(dbghdr.crc), 1, fp);
+ fread(&dbghdr.os, sizeof(dbghdr.os), 1, fp);
+ fread(&dbghdr.cpu, sizeof(dbghdr.cpu), 1, fp);
+ SWAP_DBGHDR(&dbghdr, abfd);
+
+ symnum = 0;
+ while(1)
+ {
+ int ret;
+ long cursymoffset;
+
+ /* Get the symbol for this run and pull out some info */
+ QUIT; /* allow this to be interruptable */
+ cursymoffset = ftell(objfile->auxf2);
+ ret = fill_sym(objfile->auxf2, abfd);
+ if (ret <= 0) break;
+ else symnum++;
+ bufp = symbuf;
+
+ /* Special case to speed up readin. */
+ if (bufp->n_type == (short)N_SYM_SLINE) continue;
+
+#define CUR_SYMBOL_VALUE bufp->n_value
+ /* partial-stab.h */
+
+ switch (bufp->n_type)
+ {
+ char *p;
+
+ case N_SYM_CMPLR:
+ continue;
+
+ case N_SYM_SE:
+ CUR_SYMBOL_VALUE += ANOFFSET(section_offsets, SECT_OFF_TEXT);
+ if (psymfile_depth == 1 && pst)
+ {
+ os9k_end_psymtab (pst, psymtab_include_list, includes_used,
+ symnum, CUR_SYMBOL_VALUE,
+ dependency_list, dependencies_used);
+ pst = (struct partial_symtab *) 0;
+ includes_used = 0;
+ dependencies_used = 0;
+ }
+ psymfile_depth--;
+ continue;
+
+ case N_SYM_SYM: /* Typedef or automatic variable. */
+ namestring = bufp->n_strx;
+ 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' :
+ {
+ unsigned long valu;
+ enum language tmp_language;
+ char *str, *p;
+ int n;
+
+ valu = CUR_SYMBOL_VALUE;
+ if (valu)
+ valu += ANOFFSET (section_offsets, SECT_OFF_TEXT);
+ past_first_source_file = 1;
+
+ p = strchr(namestring, ':');
+ if (p) n = p-namestring;
+ else n = strlen(namestring);
+ str = alloca(n+1);
+ strncpy(str, namestring, n);
+ str[n] = '\0';
+
+ if (psymfile_depth == 0) {
+ if (!pst)
+ pst = os9k_start_psymtab (objfile, section_offsets,
+ str, valu,
+ cursymoffset,
+ symnum-1,
+ objfile -> global_psymbols.next,
+ objfile -> static_psymbols.next);
+ } else { /* this is a include file */
+ tmp_language = deduce_language_from_filename (str);
+ if (tmp_language != language_unknown
+ && (tmp_language != language_c
+ || psymtab_language != language_cplus))
+ psymtab_language = tmp_language;
+
+/*
+ if (pst && STREQ (str, pst->filename))
+ continue;
+ {
+ register int i;
+ for (i = 0; i < includes_used; i++)
+ if (STREQ (str, psymtab_include_list[i]))
+ {
+ i = -1;
+ break;
+ }
+ if (i == -1)
+ continue;
+ }
+*/
+
+ psymtab_include_list[includes_used++] = str;
+ 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 *));
+ }
+
+ }
+ psymfile_depth++;
+ continue;
+ }
+
+ case 'v':
+ add_psymbol_to_list (namestring, p - namestring,
+ VAR_NAMESPACE, LOC_STATIC,
+ &objfile->static_psymbols,
+ 0, CUR_SYMBOL_VALUE,
+ psymtab_language, objfile);
+ continue;
+ case 'V':
+ add_psymbol_to_list (namestring, p - namestring,
+ VAR_NAMESPACE, LOC_STATIC,
+ &objfile->global_psymbols,
+ 0, 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, 0,
+ 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, 0, psymtab_language,
+ objfile);
+ p += 1;
+ }
+ /* The semantics of C++ state that "struct foo { ... }"
+ also defines a typedef for "foo". Unfortuantely, cfront
+ never makes the typedef when translating from C++ to C.
+ We make the typedef here so that "ptype foo" works as
+ expected for cfront translated code. */
+ else if (psymtab_language == language_cplus)
+ {
+ /* Also a typedef with the same name. */
+ add_psymbol_to_list (namestring, p - namestring,
+ VAR_NAMESPACE, LOC_TYPEDEF,
+ &objfile->static_psymbols,
+ CUR_SYMBOL_VALUE, 0, psymtab_language,
+ objfile);
+ }
+ }
+ 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, 0,
+ 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" <size>
+ {<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. skip size */
+ while (*p >= '0' && *p <= '9') p++;
+ /* 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 (objfile);
+ */
+
+ /* 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,
+ 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,
+ 0, psymtab_language, objfile);
+ continue;
+
+ case 'f':
+ CUR_SYMBOL_VALUE += ANOFFSET(section_offsets, SECT_OFF_TEXT);
+ if (pst && pst->textlow == 0)
+ pst->textlow = CUR_SYMBOL_VALUE;
+
+ add_psymbol_to_list (namestring, p - namestring,
+ VAR_NAMESPACE, LOC_BLOCK,
+ &objfile->static_psymbols, CUR_SYMBOL_VALUE,
+ 0, psymtab_language, objfile);
+ continue;
+
+ case 'F':
+ CUR_SYMBOL_VALUE += ANOFFSET(section_offsets, SECT_OFF_TEXT);
+ if (pst && pst->textlow == 0)
+ pst->textlow = CUR_SYMBOL_VALUE;
+
+ add_psymbol_to_list (namestring, p - namestring,
+ VAR_NAMESPACE, LOC_BLOCK,
+ &objfile->global_psymbols, CUR_SYMBOL_VALUE,
+ 0, psymtab_language, objfile);
+ continue;
+
+ case 'p':
+ case 'l':
+ case 's':
+ continue;
+
+ case ':':
+ /* It is a C++ nested symbol. We don't need to record it
+ (I don't think); if we try to look up foo::bar::baz,
+ then symbols for the symtab containing foo should get
+ read in, I think. */
+ /* Someone says sun cc puts out symbols like
+ /foo/baz/maclib::/usr/local/bin/maclib,
+ which would get here with a symbol type of ':'. */
+ continue;
+
+ default:
+ /* Unexpected symbol descriptor. The second and subsequent stabs
+ of a continued stab can show up here. The question is
+ whether they ever can mimic a normal stab--it would be
+ nice if not, since we certainly don't want to spend the
+ time searching to the end of every string looking for
+ a backslash. */
+
+ complain (&unknown_symchar_complaint, p[1]);
+ continue;
+ }
+
+ case N_SYM_RBRAC:
+ CUR_SYMBOL_VALUE += ANOFFSET(section_offsets, SECT_OFF_TEXT);
+#ifdef HANDLE_RBRAC
+ HANDLE_RBRAC(CUR_SYMBOL_VALUE);
+ continue;
+#endif
+ case N_SYM_LBRAC:
+ 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) bufp->n_type));
+ continue;
+ }
+ }
+
+ DBX_SYMCOUNT (objfile) = symnum;
+
+ /* If there's stuff to be cleaned up, clean it up. */
+ if (DBX_SYMCOUNT (objfile) > 0
+/*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)
+ {
+ os9k_end_psymtab (pst, psymtab_include_list, includes_used,
+ symnum, 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). */
+
+
+static struct partial_symtab *
+os9k_start_psymtab (objfile, section_offsets,
+ filename, textlow, ldsymoff,ldsymcnt, global_syms, static_syms)
+ struct objfile *objfile;
+ struct section_offsets *section_offsets;
+ char *filename;
+ CORE_ADDR textlow;
+ int ldsymoff;
+ int ldsymcnt;
+ 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;
+ LDSYMCNT(result) = ldsymcnt;
+ result->read_symtab = os9k_psymtab_to_symtab;
+
+ /* 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. */
+
+static struct partial_symtab *
+os9k_end_psymtab (pst, include_list, num_includes, capping_symbol_cnt,
+ capping_text, dependency_list, number_dependencies)
+ struct partial_symtab *pst;
+ char **include_list;
+ int num_includes;
+ int capping_symbol_cnt;
+ 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_cnt != -1)
+ LDSYMCNT(pst) = capping_symbol_cnt - LDSYMCNT(pst);
+
+ /* 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, NULL, 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) =
+ LDSYMCNT(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. */
+ /* Indicate that psymtab was thrown away. */
+
+ discard_psymtab (pst);
+
+ pst = (struct partial_symtab *)NULL;
+ }
+ return pst;
+}
+
+static void
+os9k_psymtab_to_symtab_1 (pst)
+ struct partial_symtab *pst;
+{
+ struct cleanup *old_chain;
+ int i;
+
+ if (!pst)
+ return;
+
+ if (pst->readin)
+ {
+ fprintf_unfiltered (gdb_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 (" ", gdb_stdout);
+ wrap_here ("");
+ fputs_filtered ("and ", gdb_stdout);
+ wrap_here ("");
+ printf_filtered ("%s...", pst->dependencies[i]->filename);
+ wrap_here (""); /* Flush output */
+ gdb_flush (gdb_stdout);
+ }
+ os9k_psymtab_to_symtab_1 (pst->dependencies[i]);
+ }
+
+ if (LDSYMCNT(pst)) /* Otherwise it's a dummy */
+ {
+ /* Init stuff necessary for reading in symbols */
+ stabsread_init ();
+ buildsym_init ();
+ old_chain = make_cleanup ((make_cleanup_func) really_free_pendings, 0);
+
+ /* Read in this file's symbols */
+ os9k_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
+os9k_psymtab_to_symtab (pst)
+ struct partial_symtab *pst;
+{
+ bfd *sym_bfd;
+
+ if (!pst)
+ return;
+
+ if (pst->readin)
+ {
+ fprintf_unfiltered (gdb_stderr, "Psymtab for %s already read in. Shouldn't happen.\n",
+ pst->filename);
+ return;
+ }
+
+ if (LDSYMCNT(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);
+ gdb_flush (gdb_stdout);
+ }
+
+ sym_bfd = pst->objfile->obfd;
+ os9k_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
+os9k_read_ofile_symtab (pst)
+ struct partial_symtab *pst;
+{
+ register struct internal_symstruct *bufp;
+ unsigned char type;
+ unsigned max_symnum;
+ register bfd *abfd;
+ struct objfile *objfile;
+ int sym_offset; /* Offset to start 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;
+ FILE *dbg_file;
+
+ objfile = pst->objfile;
+ sym_offset = LDSYMOFF(pst);
+ max_symnum = LDSYMCNT(pst);
+ text_offset = pst->textlow;
+ text_size = pst->texthigh - pst->textlow;
+ section_offsets = pst->section_offsets;
+
+ current_objfile = objfile;
+ subfile_stack = NULL;
+ last_source_file = NULL;
+
+ abfd = objfile->obfd;
+ dbg_file = objfile->auxf2;
+
+#if 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)
+ {
+ fseek (objefile->auxf2, sym_offset, SEEK_CUR);
+ fill_sym(objfile->auxf2, abfd);
+ bufp = symbuf;
+
+ 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;
+ }
+#endif /* 0 */
+
+ fseek(dbg_file, (long)sym_offset, 0);
+/*
+ if (bufp->n_type != (unsigned char)N_SYM_SYM)
+ error("First symbol in segment of executable not a source symbol");
+*/
+
+ for (symnum = 0; symnum < max_symnum; symnum++)
+ {
+ QUIT; /* Allow this to be interruptable */
+ fill_sym(dbg_file, abfd);
+ bufp = symbuf;
+ type = bufp->n_type;
+
+ os9k_process_one_symbol ((int)type, (int)bufp->n_desc,
+ (CORE_ADDR)bufp->n_value, bufp->n_strx, section_offsets, objfile);
+
+ /* We skip checking for a new .o or -l file; that should never
+ happen in this routine. */
+#if 0
+ 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. */
+ ;
+ }
+#endif /* 0 */
+ }
+
+ 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, 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. */
+
+static void
+os9k_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;
+{
+ register struct context_stack *new;
+ /* 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;
+
+#if 0
+ /* 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,
+ but this should not be an error (). */
+ return;
+ }
+#endif /* 0 */
+
+ switch (type)
+ {
+ case N_SYM_LBRAC:
+ /* On most machines, the block addresses are relative to the
+ N_SO, the linker did not relocate them (sigh). */
+ valu += ANOFFSET (section_offsets, SECT_OFF_TEXT);
+ new = push_context (desc, valu);
+ break;
+
+ case N_SYM_RBRAC:
+ valu += ANOFFSET (section_offsets, SECT_OFF_TEXT);
+ new = pop_context();
+
+#if !defined (OS9K_VARIABLES_INSIDE_BLOCK)
+#define OS9K_VARIABLES_INSIDE_BLOCK(desc, gcc_p) 1
+#endif
+
+ if (!OS9K_VARIABLES_INSIDE_BLOCK(desc, processing_gcc_compilation))
+ local_symbols = new->locals;
+
+ if (context_stack_depth > 1)
+ {
+ /* 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. Define the block for them (but don't
+ bother if the block contains no symbols. Should we complain
+ on blocks without symbols? I can't think of any useful purpose
+ for them). */
+ if (local_symbols != NULL)
+ {
+ /* Muzzle a compiler bug that makes end < start. (which
+ compilers? Is this ever harmful?). */
+ 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
+ {
+ if (context_stack_depth == 0)
+ {
+ within_function = 0;
+ /* Make a block for the local symbols within. */
+ finish_block (new->name, &local_symbols, new->old_blocks,
+ new->start_addr, valu, objfile);
+ }
+ else
+ {
+ /* attach local_symbols to the end of new->locals */
+ if (!new->locals) new->locals = local_symbols;
+ else {
+ struct pending *p;
+
+ p = new->locals;
+ while (p->next) p = p->next;
+ p->next = local_symbols;
+ }
+ }
+ }
+
+ if (OS9K_VARIABLES_INSIDE_BLOCK(desc, processing_gcc_compilation))
+ /* Now pop locals of block just finished. */
+ local_symbols = new->locals;
+ break;
+
+
+ case N_SYM_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 += ANOFFSET (section_offsets, SECT_OFF_TEXT);
+ /* FIXME: loses if sizeof (char *) > sizeof (int) */
+ record_line (current_subfile, (int)name, valu);
+ 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_SYM_SYM:
+
+ if (name)
+ {
+ char deftype;
+ char *dirn, *n;
+ char *p = strchr (name, ':');
+ if (p == NULL)
+ deftype = '\0';
+ else
+ deftype = p[1];
+
+
+ switch (deftype)
+ {
+ case 'S':
+ valu += ANOFFSET (section_offsets, SECT_OFF_TEXT);
+ n = strrchr(name, '/');
+ if (n != NULL) {
+ *n = '\0';
+ n++;
+ dirn = name;
+ } else {
+ n = name;
+ dirn = NULL;
+ }
+ *p = '\0';
+ if (symfile_depth++ == 0) {
+ if (last_source_file) {
+ end_symtab (valu, objfile, SECT_OFF_TEXT);
+ end_stabs ();
+ }
+ start_stabs ();
+ os9k_stabs = 1;
+ start_symtab (n, dirn, valu);
+ record_debugformat ("OS9");
+ } else {
+ push_subfile();
+ start_subfile (n, dirn!=NULL ? dirn : current_subfile->dirname);
+ }
+ break;
+
+ case 'f':
+ case 'F':
+ valu += ANOFFSET (section_offsets, SECT_OFF_TEXT);
+ function_stab_type = type;
+
+ within_function = 1;
+ new = push_context (0, valu);
+ new->name = define_symbol (valu, name, desc, type, objfile);
+ break;
+
+ case 'V':
+ case 'v':
+ valu += ANOFFSET (section_offsets, SECT_OFF_DATA);
+ define_symbol (valu, name, desc, type, objfile);
+ break;
+
+ default:
+ define_symbol (valu, name, desc, type, objfile);
+ break;
+ }
+ }
+ break;
+
+ case N_SYM_SE:
+ if (--symfile_depth != 0)
+ start_subfile(pop_subfile(), current_subfile->dirname);
+ break;
+
+ default:
+ complain (&unknown_symtype_complaint,
+ local_hex_string((unsigned long) type));
+ /* FALLTHROUGH */
+ break;
+
+ case N_SYM_CMPLR:
+ break;
+ }
+ previous_stab_code = type;
+}
+
+static struct sym_fns os9k_sym_fns =
+{
+ bfd_target_os9k_flavour,
+ os9k_new_init, /* sym_new_init: init anything gbl to entire symtab */
+ os9k_symfile_init, /* sym_init: read initial info, setup for sym_read() */
+ os9k_symfile_read, /* sym_read: read a symbol file into symtab */
+ os9k_symfile_finish, /* sym_finish: finished with file, cleanup */
+ default_symfile_offsets,
+ /* sym_offsets: parse user's offsets to internal form*/
+ NULL /* next: pointer to next struct sym_fns */
+};
+
+void
+_initialize_os9kread ()
+{
+ add_symtab_fns(&os9k_sym_fns);
+}
diff --git a/gdb/osf-share/AT386/cma_thread_io.h b/gdb/osf-share/AT386/cma_thread_io.h
new file mode 100644
index 00000000000..a90dba17583
--- /dev/null
+++ b/gdb/osf-share/AT386/cma_thread_io.h
@@ -0,0 +1,457 @@
+/*
+ * (c) Copyright 1990-1996 OPEN SOFTWARE FOUNDATION, INC.
+ * (c) Copyright 1990-1996 HEWLETT-PACKARD COMPANY
+ * (c) Copyright 1990-1996 DIGITAL EQUIPMENT CORPORATION
+ * (c) Copyright 1991, 1992 Siemens-Nixdorf Information Systems
+ * To anyone who acknowledges that this file is provided "AS IS" without
+ * any express or implied warranty: permission to use, copy, modify, and
+ * distribute this file for any purpose is hereby granted without fee,
+ * provided that the above copyright notices and this notice appears in
+ * all source code copies, and that none of the names listed above be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. None of these organizations
+ * makes any representations about the suitability of this software for
+ * any purpose.
+ */
+/*
+ * Header file for thread synchrounous I/O
+ */
+
+#ifndef CMA_THREAD_IO
+#define CMA_THREAD_IO
+
+/*
+ * INCLUDE FILES
+ */
+
+#include <cma_config.h>
+#include <sys/file.h>
+#include <cma.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <cma_init.h>
+#include <cma_errors.h>
+
+/*
+ * CONSTANTS
+ */
+
+/*
+ * Define symbols which indicate whether to compile code for obsolete
+ * "non-blocking mode" flags: FNDELAY and FNBLOCK. If the obsolete
+ * symbols are defined, and if their replacement symbols are defined
+ * and are different or if they are undefined, then define a symbol
+ * that says to compile the code in; otherwise no code will be compiled
+ * for these obsolete symbols.
+ */
+#ifdef FNDELAY
+# ifdef O_NDELAY
+# if O_NDELAY != FNDELAY
+# define _CMA_FNDELAY_
+# endif
+# else
+# define _CMA_FNDELAY_
+# endif
+#endif
+
+#ifdef FNBLOCK
+# ifdef O_NONBLOCK
+# if O_NONBLOCK != FNBLOCK
+# define _CMA_FNBLOCK_
+# endif
+# else
+# define _CMA_FNBLOCK_
+# endif
+#endif
+
+
+extern cma_t_boolean cma_is_open(int);
+/*
+ * Maximum number of files (ie, max_fd+1)
+ */
+#define cma__c_mx_file FD_SETSIZE
+
+/*
+ * Number of bits per file descriptor bit mask (ie number of bytes * bits/byte)
+ */
+#define cma__c_nbpm NFDBITS
+
+/*
+ * TYPE DEFINITIONS
+ */
+
+typedef enum CMA__T_IO_TYPE {
+ cma__c_io_read = 0,
+ cma__c_io_write = 1,
+ cma__c_io_except = 2
+ } cma__t_io_type;
+#define cma__c_max_io_type 2
+
+/*
+ * From our local <sys/types.h>:
+ *
+ * typedef long fd_mask;
+ *
+ * typedef struct fd_set {
+ * fd_mask fds_bits[howmany(FD_SETSIZE, NFDBITS)];
+ * } fd_set;
+ *
+ */
+typedef fd_mask cma__t_mask;
+typedef fd_set cma__t_file_mask;
+
+
+/*
+ * GLOBAL DATA
+ */
+
+/*
+ * Maximum number of files (ie, max_fd+1) as determined by getdtablesize().
+ */
+extern int cma__g_mx_file;
+
+/*
+ * Number of submasks (ie "int" sized chunks) per file descriptor mask as
+ * determined by getdtablesize().
+ */
+extern int cma__g_nspm;
+
+/*
+ * MACROS
+ */
+
+/*
+ * Define a constant for the errno value which indicates that the requested
+ * operation was not performed because it would block the process.
+ */
+# define cma__is_blocking(s) \
+ ((s == EAGAIN) || (s == EWOULDBLOCK) || (s == EINPROGRESS) || \
+ (s == EALREADY) || (s == EDEADLK))
+
+/*
+* It is necessary to issue an I/O function, before calling cma__io_wait()
+* in the following cases:
+*
+* * This file descriptor has been set non-blocking by CMA
+* * This file descriptor has been set non-blocking by the user.
+*/
+
+#define cma__issue_io_call(fd) \
+ ( (cma__g_file[fd]->non_blocking) || \
+ (cma__g_file[fd]->user_fl.user_non_blocking) )
+
+
+#define cma__set_user_nonblocking(flags) \
+
+/*
+ * Determine if the file is open
+ */
+/*
+ * If the file gets closed while waiting for the mutex cma__g_file[rfd]
+ * gets set to null. This results in a crash if NDEBUG is set to 0
+ * since cma__int_lock tries to dereference it to set the mutex ownership
+ * after it gets the mutex. The following will still set the ownership
+ * in cma__int_lock so we'll set it back to noone if cma__g_file is null
+ * when we come back just in case it matters. It shouldn't since its no
+ * longer in use but.....
+ * Callers of this should recheck cma__g_file after the reservation to
+ * make sure continueing makes sense.
+ */
+#define cma__fd_reserve(rfd) \
+ { \
+ cma__t_int_mutex *__mutex__; \
+ __mutex__ = cma__g_file[rfd]->mutex; \
+ cma__int_lock (__mutex__); \
+ if(cma__g_file[rfd] == (cma__t_file_obj *)cma_c_null_ptr) \
+ cma__int_unlock(__mutex__); \
+ }
+
+
+/*
+ * Unreserve a file descriptor
+ */
+#define cma__fd_unreserve(ufd) cma__int_unlock (cma__g_file[ufd]->mutex)
+
+/*
+ * AND together two select file descriptor masks
+ */
+#define cma__fdm_and(target,a,b) \
+ { \
+ int __i__ = cma__g_nspm; \
+ while (__i__--) \
+ (target)->fds_bits[__i__] = \
+ (a)->fds_bits[__i__] & (b)->fds_bits[__i__]; \
+ }
+
+/*
+ * Clear a bit in a select file descriptor mask
+ *
+ * FD_CLR(n, p) := ((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS)))
+ */
+#define cma__fdm_clr_bit(n,p) FD_CLR (n, p)
+
+/*
+ * Copy the contents of one file descriptor mask into another. If the
+ * destination operand is null, do nothing; if the source operand is null,
+ * simply zero the destination.
+ */
+#define cma__fdm_copy(src,dst,nfds) { \
+ if (dst) \
+ if (src) { \
+ cma__t_mask *__s__ = (cma__t_mask *)(src); \
+ cma__t_mask *__d__ = (cma__t_mask *)(dst); \
+ int __i__; \
+ for (__i__ = 0; __i__ < (nfds); __i__ += cma__c_nbpm) \
+ *__d__++ = *__s__++; \
+ } \
+ else \
+ cma__fdm_zero (dst); \
+ }
+
+/*
+ * To increment count for each bit set in fd - mask
+ */
+#define cma__fdm_count_bits(map,count) \
+ { \
+ int __i__ = cma__g_nspm; \
+ while (__i__--) { \
+ cma__t_mask __tm__; \
+ __tm__ = (map)->fds_bits[__i__]; \
+ while(__tm__) { \
+ (count)++; \
+ __tm__ &= ~(__tm__ & (-__tm__)); /* Assumes 2's comp */ \
+ } \
+ } \
+ }
+
+/*
+ * Test if a bit is set in a select file descriptor mask
+ *
+ * FD_ISSET(n,p) := ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS)))
+ */
+#define cma__fdm_is_set(n,p) FD_ISSET (n, p)
+
+/*
+ * OR together two select file descriptor masks
+ */
+#define cma__fdm_or(target,a,b) \
+ { \
+ int __i__ = cma__g_nspm; \
+ while (__i__--) \
+ (target)->fds_bits[__i__] = \
+ (a)->fds_bits[__i__] | (b)->fds_bits[__i__]; \
+ }
+
+/*
+ * Set a bit in a select file descriptor mask
+ *
+ * FD_SET(n,p) := ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS)))
+ */
+#define cma__fdm_set_bit(n,p) FD_SET (n, p)
+
+/*
+ * Clear a select file descriptor mask.
+ */
+#define cma__fdm_zero(n) \
+ cma__memset ((char *) n, 0, cma__g_nspm * sizeof(cma__t_mask))
+
+
+
+/*
+ * CMA "thread-synchronous" I/O read/write operations
+ */
+
+ /*
+ * Since all CMA "thread-synchronous" I/O (read or write) operations on
+ * U*ix follow the exact same structure, the wrapper routines have been
+ * condensed into a macro.
+ *
+ * The steps performed are as follows:
+ * 1. Check that the file descriptor is a legitimate value.
+ * 2. Check that the entry in the CMA file "database" which corresponds to
+ * the file descriptor indicates that the "file" was "opened" by CMA.
+ * 3. Reserve the file, to serialized access to files. This not only
+ * simplifies things, but also defends against non-reentrancy.
+ * 4. If the "file" is "set" for non-blocking I/O, check if we
+ * have actually set the file non-blocking yet, and if not do so.
+ * Then, issue the I/O operantion.
+ * Success or failure is returned immediately, after unreserving the
+ * file. If the error indicates that the operation would have caused
+ * the process to block, continue to the next step.
+ * 5. The I/O prolog adds this "file" to the global bit mask, which
+ * represents all "files" which have threads waiting to perform I/O on
+ * them, and causes the thread to block on the condition variable for
+ * this "file". Periodically, a select is done on this global bit
+ * mask, and the condition variables corresponding to "files" which
+ * are ready for I/O are signaled, releasing those waiting threads to
+ * perform their I/O.
+ * 6. When the thread returns from the I/O prolog, it can (hopefully)
+ * perform its operation without blocking the process.
+ * 7. The I/O epilog clears the bit in the global mask and/or signals the
+ * the next thread waiting for this "file", as appropriate.
+ * 8. If the I/O failed, continue to loop.
+ * 9. Finally, the "file" is unreserved, as we're done with it, and the
+ * result of the operation is returned.
+ *
+ *
+ * Note: currently, we believe that timeslicing which is based on the
+ * virtual-time timer does not cause system calls to return EINTR.
+ * Threfore, any EINTR returns are relayed directly to the caller.
+ * On platforms which do not support a virtual-time timer, the code
+ * should probably catch EINTR returns and restart the system call.
+ */
+
+/*
+ * This macro is used for both read-type and write-type functions.
+ *
+ * Note: the second call to "func" may require being bracketed in a
+ * cma__interrupt_disable/cma__interrupt_enable pair, but we'll
+ * wait and see if this is necessary.
+ */
+#define cma__ts_func(func,fd,arglist,type,post_process) { \
+ cma_t_integer __res__; \
+ cma_t_boolean __done__ = cma_c_false; \
+ if ((fd < 0) || (fd >= cma__g_mx_file)) return (cma__set_errno (EBADF), -1); \
+ if (!cma__is_open(fd)) return (cma__set_errno (EBADF), -1); \
+ cma__fd_reserve (fd); \
+ if (!cma__is_open(fd)) return (cma__set_errno (EBADF), -1); \
+ if (cma__issue_io_call(fd)) {\
+ if ((!cma__g_file[fd]->set_non_blocking) && \
+ (cma__g_file[fd]->non_blocking == cma_c_true)) \
+ cma__set_nonblocking(fd); \
+ cma__interrupt_disable (0); \
+ TRY { \
+ __res__ = func arglist; \
+ } \
+ CATCH_ALL { \
+ cma__interrupt_enable (0); \
+ cma__fd_unreserve (fd); \
+ RERAISE; \
+ } \
+ ENDTRY \
+ cma__interrupt_enable (0); \
+ if ((__res__ != -1) \
+ || (!cma__is_blocking (errno)) \
+ || (cma__g_file[fd]->user_fl.user_non_blocking)) \
+ __done__ = cma_c_true; \
+ } \
+ if (__done__) { \
+ cma__fd_unreserve (fd); \
+ } \
+ else { \
+ TRY { \
+ cma__io_prolog (type, fd); \
+ while (!__done__) { \
+ cma__io_wait (type, fd); \
+ __res__ = func arglist; \
+ if ((__res__ != -1) \
+ || (!cma__is_blocking (errno)) \
+ || (cma__g_file[fd]->user_fl.user_non_blocking)) \
+ __done__ = cma_c_true; \
+ } \
+ } \
+ FINALLY { \
+ cma__io_epilog (type, fd); \
+ cma__fd_unreserve (fd); \
+ } \
+ ENDTRY \
+ } \
+ if (__res__ != -1) post_process; \
+ return __res__; \
+ }
+
+ /*
+ * Since most CMA "thread-synchronous" I/O ("open"-type) operations on
+ * U*ix follow the exact same structure, the wrapper routines have been
+ * condensed into a macro.
+ *
+ * The steps performed are as follows:
+ * 1. Issue the open function.
+ * 2. If the value returned indicates an error, return it to the caller.
+ * 3. If the file descriptor returned is larger than what we think is the
+ * maximum value (ie if it is too big for our database) then bugcheck.
+ * 4. "Open" the "file" in the CMA file database.
+ * 5. Return the file descriptor value to the caller.
+ *
+ * FIX-ME: for the time being, if the I/O operation returns EINTR, we
+ * simply return it to the caller; eventually, we should catch this
+ * and "do the right thing" (if we can figure out what that is).
+ */
+
+/*
+ * This macro is used for all "open"-type functions which return a single file
+ * desciptor by immediate value.
+ */
+#define cma__ts_open(func,arglist,post_process) { \
+ int __fd__; \
+ TRY { \
+ cma__int_init (); \
+ cma__int_lock (cma__g_io_data_mutex); \
+ __fd__ = func arglist; \
+ cma__int_unlock (cma__g_io_data_mutex); \
+ if (__fd__ >= 0 && __fd__ < cma__g_mx_file) \
+ post_process; \
+ } \
+ CATCH_ALL \
+ { \
+ cma__set_errno (EBADF); \
+ __fd__ = -1; \
+ } \
+ ENDTRY \
+ if (__fd__ >= cma__g_mx_file) \
+ cma__bugcheck ("cma__ts_open: fd is too large"); \
+ return __fd__; \
+ }
+/*
+ * This macro is used for all "open"-type functions which return a pair of file
+ * desciptors by reference parameter.
+ */
+#define cma__ts_open2(func,fdpair,arglist,post_process) { \
+ int __res__; \
+ TRY { \
+ cma__int_init (); \
+ cma__int_lock (cma__g_io_data_mutex); \
+ __res__ = func arglist; \
+ cma__int_unlock (cma__g_io_data_mutex); \
+ if (__res__ >= 0 && fdpair[0] < cma__g_mx_file \
+ && fdpair[1] < cma__g_mx_file) \
+ post_process; \
+ } \
+ CATCH_ALL \
+ { \
+ cma__set_errno (EBADF); \
+ __res__ = -1; \
+ } \
+ ENDTRY \
+ if ((fdpair[0] >= cma__g_mx_file) || (fdpair[1] >= cma__g_mx_file)) \
+ cma__bugcheck ("cma__ts_open2: one of fd's is too large"); \
+ return __res__; \
+ }
+
+/*
+ * INTERNAL INTERFACES
+ */
+extern void cma__close_general (int);
+
+extern void cma__init_thread_io (void);
+
+extern cma_t_boolean cma__io_available (cma__t_io_type,int,struct timeval *);
+
+extern void cma__io_epilog (cma__t_io_type,int);
+
+extern void cma__io_prolog (cma__t_io_type,int);
+
+extern void cma__io_wait (cma__t_io_type,int);
+
+extern void cma__open_general (int);
+
+extern void cma__reinit_thread_io (int);
+
+extern void cma__set_nonblocking (int);
+
+extern void cma__set_user_nonblock_flags (int,int);
+
+extern cma_t_boolean cma__is_open (int);
+
+
+#endif
diff --git a/gdb/osf-share/HP800/cma_thread_io.h b/gdb/osf-share/HP800/cma_thread_io.h
new file mode 100644
index 00000000000..e9bef3be457
--- /dev/null
+++ b/gdb/osf-share/HP800/cma_thread_io.h
@@ -0,0 +1,432 @@
+/*
+ * (c) Copyright 1990-1996 OPEN SOFTWARE FOUNDATION, INC.
+ * (c) Copyright 1990-1996 HEWLETT-PACKARD COMPANY
+ * (c) Copyright 1990-1996 DIGITAL EQUIPMENT CORPORATION
+ * (c) Copyright 1991, 1992 Siemens-Nixdorf Information Systems
+ * To anyone who acknowledges that this file is provided "AS IS" without
+ * any express or implied warranty: permission to use, copy, modify, and
+ * distribute this file for any purpose is hereby granted without fee,
+ * provided that the above copyright notices and this notice appears in
+ * all source code copies, and that none of the names listed above be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. None of these organizations
+ * makes any representations about the suitability of this software for
+ * any purpose.
+ */
+/*
+ *
+ * Header file for thread synchrounous I/O
+ */
+
+#ifndef CMA_THREAD_IO
+#define CMA_THREAD_IO
+
+/*
+ * INCLUDE FILES
+ */
+
+#include <cma_config.h>
+#include <sys/file.h>
+#include <cma.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <cma_init.h>
+#include <cma_errors.h>
+
+/*
+ * CONSTANTS
+ */
+
+
+
+/*
+ * Maximum number of files (ie, max_fd+1)
+ */
+#define cma__c_mx_file FD_SETSIZE
+
+/*
+ * Number of bits per file descriptor bit mask (ie number of bytes * bits/byte)
+ */
+#define cma__c_nbpm NFDBITS
+
+/*
+ * TYPE DEFINITIONS
+ */
+
+typedef enum CMA__T_IO_TYPE {
+ cma__c_io_read = 0,
+ cma__c_io_write = 1,
+ cma__c_io_except = 2
+ } cma__t_io_type;
+#define cma__c_max_io_type 2
+
+/*
+ * From our local <sys/types.h>:
+ *
+ * typedef long fd_mask;
+ *
+ * typedef struct fd_set {
+ * fd_mask fds_bits[howmany(FD_SETSIZE, NFDBITS)];
+ * } fd_set;
+ *
+ */
+typedef fd_mask cma__t_mask;
+typedef fd_set cma__t_file_mask;
+
+
+
+/*
+ * GLOBAL DATA
+ */
+
+/*
+ * Maximum number of files (ie, max_fd+1) as determined by getdtablesize().
+ */
+extern int cma__g_mx_file;
+
+/*
+ * Number of submasks (ie "int" sized chunks) per file descriptor mask as
+ * determined by getdtablesize().
+ */
+extern int cma__g_nspm;
+
+/*
+ * MACROS
+ */
+
+/*
+ * Define a constant for the errno value which indicates that the requested
+ * operation was not performed because it would block the process.
+ */
+# define cma__is_blocking(s) \
+ ((s == EAGAIN) || (s == EWOULDBLOCK) || (s == EINPROGRESS) || \
+ (s == EALREADY) || (s == EDEADLK))
+
+/*
+* It is necessary to issue an I/O function, before calling cma__io_wait()
+* in the following cases:
+*
+* * This file descriptor has been set non-blocking by CMA
+* * This file descriptor has been set non-blocking by the user.
+*/
+
+#define cma__issue_io_call(fd) \
+ ( (cma__g_file[fd]->non_blocking) || \
+ (cma__g_file[fd]->user_fl.user_non_blocking) )
+
+
+#define cma__set_user_nonblocking(flags) \
+
+/*
+ * Determine if the file is open
+ */
+/*
+ * If the file gets closed while waiting for the mutex cma__g_file[rfd]
+ * gets set to null. This results in a crash if NDEBUG is set to 0
+ * since cma__int_lock tries to dereference it to set the mutex ownership
+ * after it gets the mutex. The following will still set the ownership
+ * in cma__int_lock so we'll set it back to noone if cma__g_file is null
+ * when we come back just in case it matters. It shouldn't since its no
+ * longer in use but.....
+ * Callers of this should recheck cma__g_file after the reservation to
+ * make sure continueing makes sense.
+ */
+#define cma__fd_reserve(rfd) \
+ { \
+ cma__t_int_mutex *__mutex__; \
+ __mutex__ = cma__g_file[rfd]->mutex; \
+ cma__int_lock (__mutex__); \
+ if(cma__g_file[rfd] == (cma__t_file_obj *)cma_c_null_ptr) \
+ cma__int_unlock(__mutex__); \
+ }
+
+
+/*
+ * Unreserve a file descriptor
+ */
+#define cma__fd_unreserve(ufd) cma__int_unlock (cma__g_file[ufd]->mutex)
+
+/*
+ * AND together two select file descriptor masks
+ */
+#define cma__fdm_and(target,a,b) \
+ { \
+ int __i__ = cma__g_nspm; \
+ while (__i__--) \
+ (target)->fds_bits[__i__] = \
+ (a)->fds_bits[__i__] & (b)->fds_bits[__i__]; \
+ }
+
+/*
+ * Clear a bit in a select file descriptor mask
+ *
+ * FD_CLR(n, p) := ((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS)))
+ */
+#define cma__fdm_clr_bit(n,p) FD_CLR (n, p)
+
+/*
+ * Copy the contents of one file descriptor mask into another. If the
+ * destination operand is null, do nothing; if the source operand is null,
+ * simply zero the destination.
+ */
+#define cma__fdm_copy(src,dst,nfds) { \
+ if (dst) \
+ if (src) { \
+ cma__t_mask *__s__ = (cma__t_mask *)(src); \
+ cma__t_mask *__d__ = (cma__t_mask *)(dst); \
+ int __i__; \
+ for (__i__ = 0; __i__ < (nfds); __i__ += cma__c_nbpm) \
+ *__d__++ = *__s__++; \
+ } \
+ else \
+ cma__fdm_zero (dst); \
+ }
+
+/*
+ * To increment count for each bit set in fd - mask
+ */
+#define cma__fdm_count_bits(map,count) \
+ { \
+ int __i__ = cma__g_nspm; \
+ while (__i__--) { \
+ cma__t_mask __tm__; \
+ __tm__ = (map)->fds_bits[__i__]; \
+ while(__tm__) { \
+ (count)++; \
+ __tm__ &= ~(__tm__ & (-__tm__)); /* Assumes 2's comp */ \
+ } \
+ } \
+ }
+
+/*
+ * Test if a bit is set in a select file descriptor mask
+ *
+ * FD_ISSET(n,p) := ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS)))
+ */
+#define cma__fdm_is_set(n,p) FD_ISSET (n, p)
+
+/*
+ * OR together two select file descriptor masks
+ */
+#define cma__fdm_or(target,a,b) \
+ { \
+ int __i__ = cma__g_nspm; \
+ while (__i__--) \
+ (target)->fds_bits[__i__] = \
+ (a)->fds_bits[__i__] | (b)->fds_bits[__i__]; \
+ }
+
+/*
+ * Set a bit in a select file descriptor mask
+ *
+ * FD_SET(n,p) := ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS)))
+ */
+#define cma__fdm_set_bit(n,p) FD_SET (n, p)
+
+/*
+ * Clear a select file descriptor mask.
+ */
+#define cma__fdm_zero(n) \
+ cma__memset ((char *) n, 0, cma__g_nspm * sizeof(cma__t_mask))
+
+
+
+
+
+/*
+ * CMA "thread-synchronous" I/O read/write operations
+ */
+
+ /*
+ * Since all CMA "thread-synchronous" I/O (read or write) operations on
+ * U*ix follow the exact same structure, the wrapper routines have been
+ * condensed into a macro.
+ *
+ * The steps performed are as follows:
+ * 1. Check that the file descriptor is a legitimate value.
+ * 2. Check that the entry in the CMA file "database" which corresponds to
+ * the file descriptor indicates that the "file" was "opened" by CMA.
+ * 3. Reserve the file, to serialized access to files. This not only
+ * simplifies things, but also defends against non-reentrancy.
+ * 4. If the "file" is "set" for non-blocking I/O, check if we
+ * have actually set the file non-blocking yet, and if not do so.
+ * Then, issue the I/O operantion.
+ * Success or failure is returned immediately, after unreserving the
+ * file. If the error indicates that the operation would have caused
+ * the process to block, continue to the next step.
+ * 5. The I/O prolog adds this "file" to the global bit mask, which
+ * represents all "files" which have threads waiting to perform I/O on
+ * them, and causes the thread to block on the condition variable for
+ * this "file". Periodically, a select is done on this global bit
+ * mask, and the condition variables corresponding to "files" which
+ * are ready for I/O are signaled, releasing those waiting threads to
+ * perform their I/O.
+ * 6. When the thread returns from the I/O prolog, it can (hopefully)
+ * perform its operation without blocking the process.
+ * 7. The I/O epilog clears the bit in the global mask and/or signals the
+ * the next thread waiting for this "file", as appropriate.
+ * 8. If the I/O failed, continue to loop.
+ * 9. Finally, the "file" is unreserved, as we're done with it, and the
+ * result of the operation is returned.
+ *
+ *
+ * Note: currently, we believe that timeslicing which is based on the
+ * virtual-time timer does not cause system calls to return EINTR.
+ * Threfore, any EINTR returns are relayed directly to the caller.
+ * On platforms which do not support a virtual-time timer, the code
+ * should probably catch EINTR returns and restart the system call.
+ */
+
+/*
+ * This macro is used for both read-type and write-type functions.
+ *
+ * Note: the second call to "func" may require being bracketed in a
+ * cma__interrupt_disable/cma__interrupt_enable pair, but we'll
+ * wait and see if this is necessary.
+ */
+#define cma__ts_func(func,fd,arglist,type,post_process) { \
+ cma_t_integer __res__; \
+ cma_t_boolean __done__ = cma_c_false; \
+ if ((fd < 0) || (fd >= cma__g_mx_file)) return (cma__set_errno (EBADF), -1); \
+ if (!cma__is_open(fd)) return (cma__set_errno (EBADF), -1); \
+ cma__fd_reserve (fd); \
+ if (!cma__is_open(fd)) return (cma__set_errno (EBADF), -1); \
+ if (cma__issue_io_call(fd)) {\
+ if ((!cma__g_file[fd]->set_non_blocking) && \
+ (cma__g_file[fd]->non_blocking == cma_c_true)) \
+ cma__set_nonblocking(fd); \
+ cma__interrupt_disable (0); \
+ TRY { \
+ __res__ = func arglist; \
+ } \
+ CATCH_ALL { \
+ cma__interrupt_enable (0); \
+ cma__fd_unreserve (fd); \
+ RERAISE; \
+ } \
+ ENDTRY \
+ cma__interrupt_enable (0); \
+ if ((__res__ != -1) \
+ || (!cma__is_blocking (errno)) \
+ || (cma__g_file[fd]->user_fl.user_non_blocking)) \
+ __done__ = cma_c_true; \
+ } \
+ if (__done__) { \
+ cma__fd_unreserve (fd); \
+ } \
+ else { \
+ TRY { \
+ cma__io_prolog (type, fd); \
+ while (!__done__) { \
+ cma__io_wait (type, fd); \
+ __res__ = func arglist; \
+ if ((__res__ != -1) \
+ || (!cma__is_blocking (errno)) \
+ || (cma__g_file[fd]->user_fl.user_non_blocking)) \
+ __done__ = cma_c_true; \
+ } \
+ } \
+ FINALLY { \
+ cma__io_epilog (type, fd); \
+ cma__fd_unreserve (fd); \
+ } \
+ ENDTRY \
+ } \
+ if (__res__ != -1) post_process; \
+ return __res__; \
+ }
+
+ /*
+ * Since most CMA "thread-synchronous" I/O ("open"-type) operations on
+ * U*ix follow the exact same structure, the wrapper routines have been
+ * condensed into a macro.
+ *
+ * The steps performed are as follows:
+ * 1. Issue the open function.
+ * 2. If the value returned indicates an error, return it to the caller.
+ * 3. If the file descriptor returned is larger than what we think is the
+ * maximum value (ie if it is too big for our database) then bugcheck.
+ * 4. "Open" the "file" in the CMA file database.
+ * 5. Return the file descriptor value to the caller.
+ *
+ * FIX-ME: for the time being, if the I/O operation returns EINTR, we
+ * simply return it to the caller; eventually, we should catch this
+ * and "do the right thing" (if we can figure out what that is).
+ */
+
+/*
+ * This macro is used for all "open"-type functions which return a single file
+ * desciptor by immediate value.
+ */
+#define cma__ts_open(func,arglist,post_process) { \
+ int __fd__; \
+ TRY { \
+ cma__int_init (); \
+ cma__int_lock (cma__g_io_data_mutex); \
+ __fd__ = func arglist; \
+ cma__int_unlock (cma__g_io_data_mutex); \
+ if (__fd__ >= 0 && __fd__ < cma__g_mx_file) \
+ post_process; \
+ } \
+ CATCH_ALL \
+ { \
+ cma__set_errno (EBADF); \
+ __fd__ = -1; \
+ } \
+ ENDTRY \
+ if (__fd__ >= cma__g_mx_file) \
+ cma__bugcheck ("cma__ts_open: fd is too large"); \
+ return __fd__; \
+ }
+/*
+ * This macro is used for all "open"-type functions which return a pair of file
+ * desciptors by reference parameter.
+ */
+#define cma__ts_open2(func,fdpair,arglist,post_process) { \
+ int __res__; \
+ TRY { \
+ cma__int_init (); \
+ cma__int_lock (cma__g_io_data_mutex); \
+ __res__ = func arglist; \
+ cma__int_unlock (cma__g_io_data_mutex); \
+ if (__res__ >= 0 && fdpair[0] < cma__g_mx_file \
+ && fdpair[1] < cma__g_mx_file) \
+ post_process; \
+ } \
+ CATCH_ALL \
+ { \
+ cma__set_errno (EBADF); \
+ __res__ = -1; \
+ } \
+ ENDTRY \
+ if ((fdpair[0] >= cma__g_mx_file) || (fdpair[1] >= cma__g_mx_file)) \
+ cma__bugcheck ("cma__ts_open2: one of fd's is too large"); \
+ return __res__; \
+ }
+
+/*
+ * INTERNAL INTERFACES
+ */
+extern void cma__close_general (int);
+
+extern void cma__init_thread_io (void);
+
+extern cma_t_boolean cma__io_available (cma__t_io_type,int,struct timeval *);
+
+extern void cma__io_epilog (cma__t_io_type,int);
+
+extern void cma__io_prolog (cma__t_io_type,int);
+
+extern void cma__io_wait (cma__t_io_type,int);
+
+extern void cma__open_general (int);
+
+extern void cma__reinit_thread_io (int);
+
+extern void cma__set_nonblocking (int);
+
+extern void cma__set_user_nonblock_flags (int,int);
+
+extern cma_t_boolean cma__is_open (int);
+
+#endif
diff --git a/gdb/osf-share/README b/gdb/osf-share/README
new file mode 100644
index 00000000000..c6d2e0fb532
--- /dev/null
+++ b/gdb/osf-share/README
@@ -0,0 +1,8 @@
+This directory contains header files necessary to build a thread-aware GDB on
+systems based on OSF's CMA threads package.
+
+The latest version of these header files are available for free from:
+
+ http://www.osf.org/mall/dce/SW-code
+
+Currently, the only port of GDB which supports CMA threads is HP/UX-10.10.
diff --git a/gdb/osf-share/RIOS/cma_thread_io.h b/gdb/osf-share/RIOS/cma_thread_io.h
new file mode 100644
index 00000000000..98117caf7d3
--- /dev/null
+++ b/gdb/osf-share/RIOS/cma_thread_io.h
@@ -0,0 +1,434 @@
+/*
+ * (c) Copyright 1990-1996 OPEN SOFTWARE FOUNDATION, INC.
+ * (c) Copyright 1990-1996 HEWLETT-PACKARD COMPANY
+ * (c) Copyright 1990-1996 DIGITAL EQUIPMENT CORPORATION
+ * (c) Copyright 1991, 1992 Siemens-Nixdorf Information Systems
+ * To anyone who acknowledges that this file is provided "AS IS" without
+ * any express or implied warranty: permission to use, copy, modify, and
+ * distribute this file for any purpose is hereby granted without fee,
+ * provided that the above copyright notices and this notice appears in
+ * all source code copies, and that none of the names listed above be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. None of these organizations
+ * makes any representations about the suitability of this software for
+ * any purpose.
+ */
+/*
+ * Header file for thread synchrounous I/O
+ */
+
+#ifndef CMA_THREAD_IO
+#define CMA_THREAD_IO
+
+/*
+ * INCLUDE FILES
+ */
+
+#include <cma_config.h>
+#include <sys/select.h>
+#include <cma.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <cma_init.h>
+#include <cma_errors.h>
+
+/*
+ * CONSTANTS
+ */
+
+/*
+ * Maximum number of files (ie, max_fd+1)
+ */
+#define cma__c_mx_file FD_SETSIZE
+
+/*
+ * Number of bits per file descriptor bit mask (ie number of bytes * bits/byte)
+ */
+#define cma__c_nbpm NFDBITS
+
+/*
+ * TYPE DEFINITIONS
+ */
+
+typedef enum CMA__T_IO_TYPE {
+ cma__c_io_read = 0,
+ cma__c_io_write = 1,
+ cma__c_io_except = 2
+ } cma__t_io_type;
+#define cma__c_max_io_type 2
+
+/*
+ * From our local <sys/types.h>:
+ *
+ * typedef long fd_mask;
+ *
+ * typedef struct fd_set {
+ * fd_mask fds_bits[howmany(FD_SETSIZE, NFDBITS)];
+ * } fd_set;
+ *
+ */
+typedef fd_mask cma__t_mask;
+typedef fd_set cma__t_file_mask;
+
+
+
+/*
+ * GLOBAL DATA
+ */
+
+/*
+ * Maximum number of files (ie, max_fd+1) as determined by getdtablesize().
+ */
+extern int cma__g_mx_file;
+
+/*
+ * Number of submasks (ie "int" sized chunks) per file descriptor mask as
+ * determined by getdtablesize().
+ */
+extern int cma__g_nspm;
+
+/*
+ * MACROS
+ */
+
+/*
+ * Define a constant for the errno value which indicates that the requested
+ * operation was not performed because it would block the process.
+ */
+# define cma__is_blocking(s) \
+ ((s == EAGAIN) || (s == EWOULDBLOCK) || (s == EINPROGRESS) || \
+ (s == EALREADY) || (s == EDEADLK))
+
+/*
+* It is necessary to issue an I/O function, before calling cma__io_wait()
+* in the following cases:
+*
+* * This file descriptor has been set non-blocking by CMA
+* * This file descriptor has been set non-blocking by the user.
+*/
+
+#define cma__issue_io_call(fd) \
+ ( (cma__g_file[fd]->non_blocking) || \
+ (cma__g_file[fd]->user_fl.user_non_blocking) )
+
+
+#define cma__set_user_nonblocking(flags) \
+
+/*
+ * Determine if the file is open
+ */
+/*
+ * If the file gets closed while waiting for the mutex cma__g_file[rfd]
+ * gets set to null. This results in a crash if NDEBUG is set to 0
+ * since cma__int_lock tries to dereference it to set the mutex ownership
+ * after it gets the mutex. The following will still set the ownership
+ * in cma__int_lock so we'll set it back to noone if cma__g_file is null
+ * when we come back just in case it matters. It shouldn't since its no
+ * longer in use but.....
+ * Callers of this should recheck cma__g_file after the reservation to
+ * make sure continueing makes sense.
+ */
+#define cma__fd_reserve(rfd) \
+ { \
+ cma__t_int_mutex *__mutex__; \
+ __mutex__ = cma__g_file[rfd]->mutex; \
+ cma__int_lock (__mutex__); \
+ if(cma__g_file[rfd] == (cma__t_file_obj *)cma_c_null_ptr) \
+ cma__int_unlock(__mutex__); \
+ }
+
+
+/*
+ * Unreserve a file descriptor
+ */
+#define cma__fd_unreserve(ufd) cma__int_unlock (cma__g_file[ufd]->mutex)
+
+/*
+ * AND together two select file descriptor masks
+ */
+#define cma__fdm_and(target,a,b) \
+ { \
+ int __i__ = cma__g_nspm; \
+ while (__i__--) \
+ (target)->fds_bits[__i__] = \
+ (a)->fds_bits[__i__] & (b)->fds_bits[__i__]; \
+ }
+
+/*
+ * Clear a bit in a select file descriptor mask
+ *
+ * FD_CLR(n, p) := ((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS)))
+ */
+#define cma__fdm_clr_bit(n,p) FD_CLR (n, p)
+
+/*
+ * Copy the contents of one file descriptor mask into another. If the
+ * destination operand is null, do nothing; if the source operand is null,
+ * simply zero the destination.
+ */
+#define cma__fdm_copy(src,dst,nfds) { \
+ if (dst) \
+ if (src) { \
+ cma__t_mask *__s__ = (cma__t_mask *)(src); \
+ cma__t_mask *__d__ = (cma__t_mask *)(dst); \
+ int __i__; \
+ for (__i__ = 0; __i__ < (nfds); __i__ += cma__c_nbpm) \
+ *__d__++ = *__s__++; \
+ } \
+ else \
+ cma__fdm_zero (dst); \
+ }
+
+/*
+ * To increment count for each bit set in fd - mask
+ */
+#define cma__fdm_count_bits(map,count) \
+ { \
+ int __i__ = cma__g_nspm; \
+ while (__i__--) { \
+ cma__t_mask __tm__; \
+ __tm__ = (map)->fds_bits[__i__]; \
+ while(__tm__) { \
+ (count)++; \
+ __tm__ &= ~(__tm__ & (-__tm__)); /* Assumes 2's comp */ \
+ } \
+ } \
+ }
+
+/*
+ * Test if a bit is set in a select file descriptor mask
+ *
+ * FD_ISSET(n,p) := ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS)))
+ */
+#define cma__fdm_is_set(n,p) FD_ISSET (n, p)
+
+/*
+ * OR together two select file descriptor masks
+ */
+#define cma__fdm_or(target,a,b) \
+ { \
+ int __i__ = cma__g_nspm; \
+ while (__i__--) \
+ (target)->fds_bits[__i__] = \
+ (a)->fds_bits[__i__] | (b)->fds_bits[__i__]; \
+ }
+
+/*
+ * Set a bit in a select file descriptor mask
+ *
+ * FD_SET(n,p) := ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS)))
+ */
+#define cma__fdm_set_bit(n,p) FD_SET (n, p)
+
+/*
+ * Clear a select file descriptor mask.
+ */
+#define cma__fdm_zero(n) \
+ cma__memset ((char *) n, 0, cma__g_nspm * sizeof(cma__t_mask))
+
+
+
+
+
+/*
+ * CMA "thread-synchronous" I/O read/write operations
+ */
+
+ /*
+ * Since all CMA "thread-synchronous" I/O (read or write) operations on
+ * U*ix follow the exact same structure, the wrapper routines have been
+ * condensed into a macro.
+ *
+ * The steps performed are as follows:
+ * 1. Check that the file descriptor is a legitimate value.
+ * 2. Check that the entry in the CMA file "database" which corresponds to
+ * the file descriptor indicates that the "file" was "opened" by CMA.
+ * 3. Reserve the file, to serialized access to files. This not only
+ * simplifies things, but also defends against non-reentrancy.
+ * 4. If the "file" is "set" for non-blocking I/O, check if we
+ * have actually set the file non-blocking yet, and if not do so.
+ * Then, issue the I/O operantion.
+ * Success or failure is returned immediately, after unreserving the
+ * file. If the error indicates that the operation would have caused
+ * the process to block, continue to the next step.
+ * 5. The I/O prolog adds this "file" to the global bit mask, which
+ * represents all "files" which have threads waiting to perform I/O on
+ * them, and causes the thread to block on the condition variable for
+ * this "file". Periodically, a select is done on this global bit
+ * mask, and the condition variables corresponding to "files" which
+ * are ready for I/O are signaled, releasing those waiting threads to
+ * perform their I/O.
+ * 6. When the thread returns from the I/O prolog, it can (hopefully)
+ * perform its operation without blocking the process.
+ * 7. The I/O epilog clears the bit in the global mask and/or signals the
+ * the next thread waiting for this "file", as appropriate.
+ * 8. If the I/O failed, continue to loop.
+ * 9. Finally, the "file" is unreserved, as we're done with it, and the
+ * result of the operation is returned.
+ *
+ *
+ * Note: currently, we believe that timeslicing which is based on the
+ * virtual-time timer does not cause system calls to return EINTR.
+ * Threfore, any EINTR returns are relayed directly to the caller.
+ * On platforms which do not support a virtual-time timer, the code
+ * should probably catch EINTR returns and restart the system call.
+ */
+
+/*
+ * This macro is used for both read-type and write-type functions.
+ *
+ * Note: the second call to "func" may require being bracketed in a
+ * cma__interrupt_disable/cma__interrupt_enable pair, but we'll
+ * wait and see if this is necessary.
+ */
+#define cma__ts_func(func,fd,arglist,type,post_process) { \
+ cma_t_integer __res__; \
+ cma_t_boolean __done__ = cma_c_false; \
+ if ((fd < 0) || (fd >= cma__g_mx_file)) return (cma__set_errno (EBADF), -1); \
+ if (!cma__is_open(fd)) return (cma__set_errno (EBADF), -1); \
+ cma__fd_reserve (fd); \
+ if (!cma__is_open(fd)) return (cma__set_errno (EBADF), -1); \
+ if (cma__issue_io_call(fd)) {\
+ if ((!cma__g_file[fd]->set_non_blocking) && \
+ (cma__g_file[fd]->non_blocking == cma_c_true)) \
+ cma__set_nonblocking(fd); \
+ cma__interrupt_disable (0); \
+ TRY { \
+ __res__ = func arglist; \
+ } \
+ CATCH_ALL { \
+ cma__interrupt_enable (0); \
+ cma__fd_unreserve (fd); \
+ RERAISE; \
+ } \
+ ENDTRY \
+ cma__interrupt_enable (0); \
+ if ((__res__ != -1) \
+ || (!cma__is_blocking (errno)) \
+ || (cma__g_file[fd]->user_fl.user_non_blocking)) \
+ __done__ = cma_c_true; \
+ } \
+ if (__done__) { \
+ cma__fd_unreserve (fd); \
+ } \
+ else { \
+ TRY { \
+ cma__io_prolog (type, fd); \
+ while (!__done__) { \
+ cma__io_wait (type, fd); \
+ __res__ = func arglist; \
+ if ((__res__ != -1) \
+ || (!cma__is_blocking (errno)) \
+ || (cma__g_file[fd]->user_fl.user_non_blocking)) \
+ __done__ = cma_c_true; \
+ } \
+ } \
+ FINALLY { \
+ cma__io_epilog (type, fd); \
+ cma__fd_unreserve (fd); \
+ } \
+ ENDTRY \
+ } \
+ if (__res__ != -1) post_process; \
+ return __res__; \
+ }
+
+ /*
+ * Since most CMA "thread-synchronous" I/O ("open"-type) operations on
+ * U*ix follow the exact same structure, the wrapper routines have been
+ * condensed into a macro.
+ *
+ * The steps performed are as follows:
+ * 1. Issue the open function.
+ * 2. If the value returned indicates an error, return it to the caller.
+ * 3. If the file descriptor returned is larger than what we think is the
+ * maximum value (ie if it is too big for our database) then bugcheck.
+ * 4. "Open" the "file" in the CMA file database.
+ * 5. Return the file descriptor value to the caller.
+ *
+ * FIX-ME: for the time being, if the I/O operation returns EINTR, we
+ * simply return it to the caller; eventually, we should catch this
+ * and "do the right thing" (if we can figure out what that is).
+ */
+
+/*
+ * This macro is used for all "open"-type functions which return a single file
+ * desciptor by immediate value.
+ */
+#define cma__ts_open(func,arglist,post_process) { \
+ int __fd__; \
+ TRY { \
+ cma__int_init (); \
+ cma__int_lock (cma__g_io_data_mutex); \
+ __fd__ = func arglist; \
+ cma__int_unlock (cma__g_io_data_mutex); \
+ if (__fd__ >= 0 && __fd__ < cma__g_mx_file) \
+ post_process; \
+ } \
+ CATCH_ALL \
+ { \
+ cma__set_errno (EBADF); \
+ __fd__ = -1; \
+ } \
+ ENDTRY \
+ if (__fd__ >= cma__g_mx_file) \
+ cma__bugcheck ("cma__ts_open: fd is too large"); \
+ return __fd__; \
+ }
+/*
+ * This macro is used for all "open"-type functions which return a pair of file
+ * desciptors by reference parameter.
+ */
+#define cma__ts_open2(func,fdpair,arglist,post_process) { \
+ int __res__; \
+ TRY { \
+ cma__int_init (); \
+ cma__int_lock (cma__g_io_data_mutex); \
+ __res__ = func arglist; \
+ cma__int_unlock (cma__g_io_data_mutex); \
+ if (__res__ >= 0 && fdpair[0] < cma__g_mx_file \
+ && fdpair[1] < cma__g_mx_file) \
+ post_process; \
+ } \
+ CATCH_ALL \
+ { \
+ cma__set_errno (EBADF); \
+ __res__ = -1; \
+ } \
+ ENDTRY \
+ if ((fdpair[0] >= cma__g_mx_file) || (fdpair[1] >= cma__g_mx_file)) \
+ cma__bugcheck ("cma__ts_open2: one of fd's is too large"); \
+ return __res__; \
+ }
+
+/*
+ * INTERNAL INTERFACES
+ */
+extern void cma__close_general (int);
+
+extern void
+cma__init_thread_io (void);
+
+extern cma_t_boolean cma__io_available (cma__t_io_type,int,struct timeval *);
+
+extern void cma__io_epilog (cma__t_io_type,int);
+
+extern void cma__io_prolog (cma__t_io_type,int);
+
+extern void cma__io_wait (cma__t_io_type,int);
+
+extern void cma__open_general (int);
+
+extern void cma__reinit_thread_io (int);
+
+extern void cma__set_nonblocking (int);
+
+extern void cma__set_user_nonblock_flags (int,int);
+
+extern cma_t_boolean
+cma__is_open (int fd);
+
+
+#endif
+
+
diff --git a/gdb/osf-share/cma_attr.h b/gdb/osf-share/cma_attr.h
new file mode 100644
index 00000000000..389fd6fd207
--- /dev/null
+++ b/gdb/osf-share/cma_attr.h
@@ -0,0 +1,341 @@
+/*
+ * (c) Copyright 1990-1996 OPEN SOFTWARE FOUNDATION, INC.
+ * (c) Copyright 1990-1996 HEWLETT-PACKARD COMPANY
+ * (c) Copyright 1990-1996 DIGITAL EQUIPMENT CORPORATION
+ * (c) Copyright 1991, 1992 Siemens-Nixdorf Information Systems
+ * To anyone who acknowledges that this file is provided "AS IS" without
+ * any express or implied warranty: permission to use, copy, modify, and
+ * distribute this file for any purpose is hereby granted without fee,
+ * provided that the above copyright notices and this notice appears in
+ * all source code copies, and that none of the names listed above be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. None of these organizations
+ * makes any representations about the suitability of this software for
+ * any purpose.
+ */
+/*
+ * Header file for attributes object
+ */
+
+#ifndef CMA_ATTR
+#define CMA_ATTR
+
+/*
+ * INCLUDE FILES
+ */
+
+#include <cma_defs.h>
+#include <cma_queue.h>
+#ifdef __hpux
+# include <sys/param.h>
+#endif
+#if _CMA_UNIX_TYPE == _CMA__SVR4
+#include <sys/unistd.h>
+#endif
+/*
+ * CONSTANTS AND MACROS
+ */
+
+
+/*
+ * FUNCTIONAL DESCRIPTION:
+ *
+ * cma__int_attr_get_priority - Performs the work of cma_attr_get_priority
+ *
+ * FORMAL PARAMETERS:
+ *
+ * cma_t_attr *_att_ - Attribute object to get from
+ * cma_t_priority *_setting_ - Current setting
+ *
+ * IMPLICIT INPUTS:
+ *
+ * none
+ *
+ * IMPLICIT OUTPUTS:
+ *
+ * priority
+ *
+ * FUNCTION VALUE:
+ *
+ * none
+ *
+ * SIDE EFFECTS:
+ *
+ * none
+ */
+#define cma__int_attr_get_priority(_att_,_setting_) { \
+ cma__t_int_attr *_int_att_; \
+ (_int_att_) = cma__validate_default_attr (_att_); \
+ cma__int_lock ((_int_att_)->mutex); \
+ (*(_setting_)) = (_int_att_)->priority; \
+ cma__int_unlock ((_int_att_)->mutex); \
+ }
+
+
+/*
+ * FUNCTIONAL DESCRIPTION:
+ *
+ * cma__int_attr_get_sched - Performs work of cma_attr_get_sched
+ *
+ * FORMAL PARAMETERS:
+ *
+ * cma_t_attr *_att_ _ Attributes object used
+ * cma_t_sched_policy *_setting_ - Current setting
+ *
+ * IMPLICIT INPUTS:
+ *
+ * none
+ *
+ * IMPLICIT OUTPUTS:
+ *
+ * scheduling policy
+ *
+ * FUNCTION VALUE:
+ *
+ * none
+ *
+ * SIDE EFFECTS:
+ *
+ * none
+ */
+#define cma__int_attr_get_sched(_att_,_setting_) { \
+ cma__t_int_attr *_int_att_; \
+ (_int_att_) = cma__validate_default_attr (_att_); \
+ cma__int_lock ((_int_att_)->mutex); \
+ (*(_setting_)) = (_int_att_)->policy; \
+ cma__int_unlock ((_int_att_)->mutex); \
+ }
+
+
+/*
+ * FUNCTIONAL DESCRIPTION:
+ *
+ * cma__int_attr_get_inherit_sched - Performs work of
+ * cma_attr_get_inherit_sched
+ *
+ * FORMAL PARAMETERS:
+ *
+ * cma_t_attr *_att_ - Attributes object to use
+ * cma_t_sched_inherit *_setting_ - Current setting
+ *
+ * IMPLICIT INPUTS:
+ *
+ * none
+ *
+ * IMPLICIT OUTPUTS:
+ *
+ * Inheritable scheduling policy
+ *
+ * FUNCTION VALUE:
+ *
+ * none
+ *
+ * SIDE EFFECTS:
+ *
+ * none
+ */
+#define cma__int_attr_get_inherit_sched(_att_,_setting_) { \
+ cma__t_int_attr *_int_att_; \
+ (_int_att_) = cma__validate_default_attr (_att_); \
+ cma__int_lock ((_int_att_)->mutex); \
+ (*(_setting_)) \
+ = ((_int_att_)->inherit_sched ? cma_c_sched_inherit : cma_c_sched_use_default); \
+ cma__int_unlock ((_int_att_)->mutex); \
+ }
+
+/*
+ * FUNCTIONAL DESCRIPTION:
+ *
+ * cma__int_attr_set_stacksize - Performs work for cma_attr_set_stacksize
+ *
+ * FORMAL PARAMETERS:
+ *
+ * cma_t_attr *_att_ - Attributes object to use
+ * cma_t_natural _setting_ - Setting
+ *
+ * IMPLICIT INPUTS:
+ *
+ * none
+ *
+ * IMPLICIT OUTPUTS:
+ *
+ * none
+ *
+ * FUNCTION VALUE:
+ *
+ * none
+ *
+ * SIDE EFFECTS:
+ *
+ * Change attribute objects stack size setting
+ */
+#define cma__int_attr_set_stacksize(_att_,_setting_) { \
+ cma__t_int_attr *_int_att_; \
+ if ((_setting_) <= 0) \
+ cma__error (cma_s_badparam); \
+ _int_att_ = cma__validate_attr (_att_); \
+ cma__int_lock ((_int_att_)->mutex); \
+ _int_att_->stack_size = cma__roundup_chunksize(_setting_); \
+ cma__free_cache (_int_att_, cma__c_obj_tcb); \
+ _int_att_->cache[cma__c_obj_tcb].revision++; \
+ _int_att_->cache[cma__c_obj_stack].revision++; \
+ cma__int_unlock (_int_att_->mutex); \
+ }
+
+/*
+ * FUNCTIONAL DESCRIPTION:
+ *
+ * cma__int_attr_get_stacksize - Performs work of cma_attr_get_stacksize
+ *
+ * FORMAL PARAMETERS:
+ *
+ * cma_t_attr *_att_ - Attributes object to use
+ * cma_t_natural *_setting_ - Current setting
+ *
+ * IMPLICIT INPUTS:
+ *
+ * none
+ *
+ * IMPLICIT OUTPUTS:
+ *
+ * Attribute objects stack size setting
+ *
+ * FUNCTION VALUE:
+ *
+ * none
+ *
+ * SIDE EFFECTS:
+ *
+ * none
+ */
+#define cma__int_attr_get_stacksize(_att_,_setting_) { \
+ cma__t_int_attr *_int_att_; \
+ (_int_att_) = cma__validate_default_attr (_att_); \
+ cma__int_lock ((_int_att_)->mutex); \
+ (*(_setting_)) = (_int_att_)->stack_size; \
+ cma__int_unlock ((_int_att_)->mutex); \
+ }
+
+
+/*
+ * FUNCTIONAL DESCRIPTION:
+ *
+ * cma__int_attr_set_guardsize - Performs work for cma_attr_set_guardsize
+ *
+ * FORMAL PARAMETERS:
+ *
+ * cma_t_attr *_att_ - Attributes object to use
+ * cma_t_natural _setting_ - Setting
+ *
+ * IMPLICIT INPUTS:
+ *
+ * none
+ *
+ * IMPLICIT OUTPUTS:
+ *
+ * none
+ *
+ * FUNCTION VALUE:
+ *
+ * none
+ *
+ * SIDE EFFECTS:
+ *
+ * Change attribute objects guard size setting
+ */
+#define cma__int_attr_set_guardsize(_att_,_setting_) { \
+ cma__t_int_attr *_int_att_; \
+ _int_att_ = cma__validate_attr (_att_); \
+ cma__int_lock ((_int_att_)->mutex); \
+ _int_att_->guard_size = cma__roundup_chunksize(_setting_); \
+ cma__free_cache (_int_att_, cma__c_obj_tcb); \
+ _int_att_->cache[cma__c_obj_tcb].revision++; \
+ _int_att_->cache[cma__c_obj_stack].revision++; \
+ cma__int_unlock (_int_att_->mutex); \
+ }
+
+/*
+ * FUNCTIONAL DESCRIPTION:
+ *
+ * cma__int_attr_get_guardsize - Performs work of cma_attr_get_guardsize
+ *
+ * FORMAL PARAMETERS:
+ *
+ * cma_t_attr *_att_ - Attributes object to use
+ * cma_t_natural *_setting_ - Current setting
+ *
+ * IMPLICIT INPUTS:
+ *
+ * none
+ *
+ * IMPLICIT OUTPUTS:
+ *
+ * Attribute objects guard size setting
+ *
+ * FUNCTION VALUE:
+ *
+ * none
+ *
+ * SIDE EFFECTS:
+ *
+ * none
+ */
+#define cma__int_attr_get_guardsize(_att_,_setting_) { \
+ cma__t_int_attr *_int_att_; \
+ (_int_att_) = cma__validate_default_attr (_att_); \
+ cma__int_lock ((_int_att_)->mutex); \
+ (*(_setting_)) = (_int_att_)->guard_size; \
+ cma__int_unlock ((_int_att_)->mutex); \
+ }
+
+/*
+ * TYPEDEFS
+ */
+#ifndef __STDC__
+struct CMA__T_INT_MUTEX; /* Avoid circular dependency */
+#endif
+
+typedef struct CMA__T_CACHE {
+ cma_t_natural revision; /* Revisions */
+ cma_t_natural count;
+ cma__t_queue queue; /* Cache headers */
+ } cma__t_cache;
+
+typedef struct CMA__T_INT_ATTR {
+ cma__t_object header; /* Common header */
+ struct CMA__T_INT_ATTR *attributes; /* Point to controlling attr */
+ struct CMA__T_INT_MUTEX *mutex; /* Serialize access to object */
+ cma_t_priority priority; /* Priority of new thread */
+ cma_t_sched_policy policy; /* Sched policy of thread */
+ cma_t_boolean inherit_sched; /* Is scheduling inherited? */
+ cma_t_natural stack_size; /* Size of stack (bytes) */
+ cma_t_natural guard_size; /* Size of guard (bytes) */
+ cma_t_mutex_kind mutex_kind; /* Mutex kind */
+ cma__t_cache cache[cma__c_obj_num]; /* Cache information */
+ cma_t_boolean delete_pending; /* attr. obj. is deleted */
+ cma_t_natural refcnt; /* Number of objects using attr. obj */
+ } cma__t_int_attr;
+
+/*
+ * GLOBAL DATA
+ */
+
+extern cma__t_int_attr cma__g_def_attr;
+
+/*
+ * INTERNAL INTERFACES
+ */
+
+extern void cma__destroy_attributes (cma__t_int_attr *);
+
+extern void cma__free_attributes (cma__t_int_attr *);
+
+extern void cma__free_cache (cma__t_int_attr *,cma_t_natural );
+
+extern cma__t_int_attr *cma__get_attributes (cma__t_int_attr *);
+
+extern void cma__init_attr (void);
+
+extern void cma__reinit_attr (cma_t_integer);
+
+#endif
diff --git a/gdb/osf-share/cma_deb_core.h b/gdb/osf-share/cma_deb_core.h
new file mode 100644
index 00000000000..f0a9c341670
--- /dev/null
+++ b/gdb/osf-share/cma_deb_core.h
@@ -0,0 +1,164 @@
+/*
+ * (c) Copyright 1990-1996 OPEN SOFTWARE FOUNDATION, INC.
+ * (c) Copyright 1990-1996 HEWLETT-PACKARD COMPANY
+ * (c) Copyright 1990-1996 DIGITAL EQUIPMENT CORPORATION
+ * (c) Copyright 1991, 1992 Siemens-Nixdorf Information Systems
+ * To anyone who acknowledges that this file is provided "AS IS" without
+ * any express or implied warranty: permission to use, copy, modify, and
+ * distribute this file for any purpose is hereby granted without fee,
+ * provided that the above copyright notices and this notice appears in
+ * all source code copies, and that none of the names listed above be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. None of these organizations
+ * makes any representations about the suitability of this software for
+ * any purpose.
+ */
+/*
+ * This file defines the internal interface to the core of CMA
+ * debugging services. (The client interface to debugging services
+ * is provided by cma_debug_client.h).
+ */
+
+#ifndef CMA_DEB_CORE
+#define CMA_DEB_CORE
+
+/*
+ * INCLUDE FILES
+ */
+#include <cma.h>
+#include <cma_mutex.h>
+#include <cma_queue.h>
+#include <cma_tcb_defs.h>
+#include <cma_util.h>
+
+/*
+ * CONSTANTS AND MACROS
+ */
+
+
+/*
+ * TYPEDEFS
+ */
+
+/*FIX-ME* Need to use sizes that are platform specific */
+typedef long int cma___t_debug_ctx[17];
+
+/*
+ * Type defing the format of known object lists
+ */
+typedef struct CMA__T_KNOWN_OBJECT {
+ cma__t_queue queue; /* Queue header for known objects */
+ cma__t_int_mutex *mutex; /* Mutex to control access to queue */
+ } cma__t_known_object;
+
+
+/*
+ * Type defining the registration for one debug client (e.g. Ada)
+ */
+typedef struct CMA__T_DEB_REGISTRY {
+ cma_t_address entry; /* Client's debug entry point */
+ cma_t_key key; /* Client's context key */
+ cma_t_integer fac; /* Client's debug facility number */
+ cma_t_boolean has_prolog; /* Client's TCBs have std prolog */
+ } cma__t_deb_registry;
+
+#define cma__c_deb_max_clients 10
+
+/*
+ * Type defining the global debugging state for all threads.
+ */
+typedef struct CMA__T_DEBUG_STATE {
+ /*
+ * The following flag is set if changes were made while in the
+ * debugger that may make the ready lists inconsistent. For
+ * example, if a thread priority is changed in the debugger, the
+ * thread is not moved between queues. Making things consistent
+ * is deferred to when the dispatcher is next invoked -- which we
+ * try to make very soon.
+ */
+ cma_t_boolean is_inconsistency; /* Ready lists are inconsistent */
+
+
+ cma_t_boolean events_enabled; /* Set if _any_ event is enabled */
+ cma_t_boolean flags[cma__c_debevt__dim];
+ /* Which events are enabled */
+ cma__t_int_tcb *next_to_run; /* TCB of thread to run next */
+
+ cma__t_int_mutex *mutex; /* Mutex for registering clients */
+ cma_t_integer client_count; /* Count of debug clients */
+ cma__t_deb_registry clients[cma__c_deb_max_clients+1];
+ /* Array of current debug clients */
+ } cma__t_debug_state;
+
+
+/*
+ * Routine that will symbolize and address and print it.
+ */
+typedef void (*cma__t_print_symbol) (cma_t_address);
+
+
+/*
+ * GLOBAL DATA
+ */
+
+/*
+ * Variable holding the global debugging state
+ *
+ * (This is primarily written by the debugger interface and read
+ * by the thread dispatcher).
+ */
+extern cma__t_debug_state cma__g_debug_state;
+
+/*
+ * Known object queues
+ */
+extern cma__t_known_object cma__g_known_atts;
+extern cma__t_known_object cma__g_known_cvs;
+extern cma__t_known_object cma__g_known_mutexes;
+extern cma__t_known_object cma__g_known_threads;
+
+/*
+ * INTERNAL INTERFACES
+ */
+
+/* Get information while in debugger context */
+extern void cma__deb_get
+ (cma__t_int_tcb *,cma_t_debug_get,cma_t_address,cma_t_integer,cma_t_integer);
+
+/* Set information while in debugger context */
+extern void cma__deb_set (cma__t_int_tcb *,cma_t_debug_set,cma_t_address,cma_t_integer);
+
+extern void cma__init_debug (void);
+
+extern void cma__reinit_debug (cma_t_integer);
+
+extern void cma__deb_anytcb_to_tcb (cma_t_tcb_header *,cma__t_int_tcb **);
+
+extern void cma__deb_fac_to_client (cma_t_integer,cma_t_key *);
+
+extern void cma__deb_get_client_info (cma_t_key,cma_t_address *,cma_t_boolean *);
+
+extern void cma__deb_get_context (cma__t_int_tcb *,cma_t_key,cma_t_address *);
+
+extern cma__t_int_tcb *cma__deb_get_self_tcb (void);
+
+extern void cma__deb_get_time_slice (cma_t_interval *);
+
+extern cma__t_int_tcb *cma__deb_next_tcb
+ (cma__t_int_tcb *,cma_t_integer *,cma_t_integer *,cma_t_boolean *);
+
+extern cma_t_boolean cma__deb_set_alert (cma__t_int_tcb *);
+
+extern void cma__deb_set_next_thread (cma__t_int_tcb *);
+
+extern void cma__deb_set_force_dispatch (cma_t_address );
+
+extern void cma__deb_set_time_slice (cma_t_interval);
+
+extern void cma__deb_show_thread
+ (cma__t_int_tcb *,cma_t_boolean,cma_t_boolean,cma___t_debug_ctx,cma__t_eol_routine,
+ cma__t_eol_routine,cma__t_print_symbol);
+
+extern void
+cma__deb_show_stats (cma__t_int_tcb *,cma_t_boolean,cma_t_boolean,cma__t_eol_routine,cma__t_eol_routine,cma__t_print_symbol);
+#endif
diff --git a/gdb/osf-share/cma_debug_client.h b/gdb/osf-share/cma_debug_client.h
new file mode 100644
index 00000000000..adb0909ad7d
--- /dev/null
+++ b/gdb/osf-share/cma_debug_client.h
@@ -0,0 +1,195 @@
+/*
+ * (c) Copyright 1990-1996 OPEN SOFTWARE FOUNDATION, INC.
+ * (c) Copyright 1990-1996 HEWLETT-PACKARD COMPANY
+ * (c) Copyright 1990-1996 DIGITAL EQUIPMENT CORPORATION
+ * (c) Copyright 1991, 1992 Siemens-Nixdorf Information Systems
+ * To anyone who acknowledges that this file is provided "AS IS" without
+ * any express or implied warranty: permission to use, copy, modify, and
+ * distribute this file for any purpose is hereby granted without fee,
+ * provided that the above copyright notices and this notice appears in
+ * all source code copies, and that none of the names listed above be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. None of these organizations
+ * makes any representations about the suitability of this software for
+ * any purpose.
+ */
+/*
+ * Header file providing access to CMA clients that implement
+ * language run-times to the CMA debugger capabilities.
+ *
+ * NOTE: the clients that are able to use this interface is
+ * very limited because clients needing task debugging must have
+ * support in the system debugger as well as here (at present).
+ * The following are the only legitimate clients of this interface:
+ * ADA runtime, C++ tasking library, and CMA.
+ *
+ *FIX-ME* We shall endeavor to extend these capabilities so that the
+ * all-platform CMA debugger CMA_DEBUG and any client can layer
+ * on thread debugging. But that is still an open design problem.
+ * The design here does not preclude that extension (for example,
+ * the identity of the debug-client is indicated in an "open"
+ * manner by using the CMA context key as the identifier.
+ */
+
+#ifndef CMA_DEBUG_CLIENT
+#define CMA_DEBUG_CLIENT
+
+/*
+ * INCLUDE FILES
+ */
+#include <cma.h>
+
+/*
+ * CONSTANTS AND MACROS
+ */
+
+/*
+ * TYPEDEFS
+ */
+
+/*
+ * Type describing constants for a valid TCB sentinel.
+ * Exactly one value is valid, but we provide a symbolic name for
+ * at least one invalid sentinel as a convenience.
+ */
+typedef enum CMA_T_TCB_SENTINEL {
+ cma_c_tcb_sentinel_nogood = 0, /* Invalid sentinel constant */
+ cma_c_tcb_sentinel = 0x0ACEFACE /* Valid TCB sentinel */
+ } cma_t_tcb_sentinel;
+
+/*
+ * Type describing pad fields needed to align the "standard prolog"
+ * to the right byte at the front of each TCB. These fields are
+ * free to be put to any use by the client.
+ *
+ * This is 32 bytes long and is fixed at this size for all clients
+ * and CMA, for all time.
+ */
+typedef struct CMA_T_TCB_PRIVATE {
+ cma_t_integer pad1;
+ cma_t_integer pad2;
+ cma_t_integer pad3;
+ cma_t_integer pad4;
+ cma_t_integer pad5;
+ cma_t_integer pad6;
+ cma_t_integer pad7;
+ cma_t_integer pad8;
+ } cma_t_tcb_private;
+
+/*
+ * Type describing the "standard prolog" that clients should use
+ * within their task control blocks. We assume that the client will
+ * store their "task control block" as a per-thread context under
+ * the context key specified here.
+ */
+typedef struct CMA_T_TCB_PROLOG {
+ cma_t_tcb_sentinel sentinel; /* Validity sentinel */
+ cma_t_thread client_thread; /* Thread corresonding to task */
+ cma_t_key client_key; /* Context key this is stored under */
+ cma_t_address reserved1; /* Must be zero, reserved to CMA */
+ } cma_t_tcb_prolog;
+
+/*
+ * Type defining the layout of all TCBs and TASKS. This format
+ * ensures that tasks will be self-identifying to the debugger.
+ * this layout must never change as the CMA DEBUG Clients cannot
+ * be changed after CMA ships.
+ */
+typedef struct CMA_T_TCB_HEADER {
+ cma_t_tcb_private IGNORED; /* TCB fields private to the client */
+ cma_t_tcb_prolog prolog; /* The standard prolog goes here */
+ } cma_t_tcb_header;
+
+
+/*
+ * Type describing the kinds of information that a CMA debug
+ * client can GET about a thread.
+ */
+typedef enum CMA_T_DEBUG_GET {
+ /*
+ * All of the following items use a buffer whose size is
+ * four bytes. (That is four must be passed as the buffer_size
+ * parameter to cma_debug_get.)
+ */
+ cma_c_debget_guardsize = 1, /* Current guard size (bytes) */
+ cma_c_debget_is_held = 2, /* Is it on hold? */
+ cma_c_debget_is_initial = 3, /* Is it the initial thread? */
+ cma_c_debget_number = 4, /* Thread's number */
+ cma_c_debget_stack_ptr = 5, /* Current stack pointer */
+ cma_c_debget_stack_base = 6, /* Stack base address */
+ cma_c_debget_stack_top = 7, /* Stack top address */
+ cma_c_debget_sched_state = 8, /* Scheduler state
+ * 0 - run
+ * 1 - ready
+ * 2 - blocked
+ * 3 - terminated
+ */
+ cma_c_debget_reserve_size = 9, /* Size of stack reserve (bytes) */
+ cma_c_debget_base_prio = 10, /* Base priority */
+ cma_c_debget_priority = 11, /* Current priority */
+ cma_c_debget_regs = 12, /* Register set (and proc. state) */
+ cma_c_debget_alt_pending = 13, /* Alert is pending */
+ cma_c_debget_alt_a_enable = 14, /* Asynch alert delivery enabled */
+ cma_c_debget_alt_g_enable = 15, /* General alert delivery enabled */
+ cma_c_debget_substate = 16, /* Substate (or wait state) */
+ cma_c_debget_object_addr = 17, /* Address of thread object */
+ cma_c_debget_thkind = 18, /* Kind of thread */
+ cma_c_debget_detached = 19, /* Thread is detached */
+ cma_c_debget_tcb_size = 20, /* TCB size */
+ cma_c_debget_start_pc = 21, /* Start address */
+ cma_c_debget_next_pc = 22, /* Next instruction */
+ cma_c_debget_policy = 23, /* Sched policy */
+ cma_c_debget_stack_yellow = 24, /* Addr of start of guard area */
+ cma_c_debget_stack_default = 25 /* True if on default stack */
+
+ } cma_t_debug_get;
+
+/*
+ * Type describing the kinds of information that a CMA debug
+ * client can SET (or change) about a thread using cma_debug_set.
+ */
+typedef enum CMA_T_DEBUG_SET {
+ /*
+ * All of the following items use a buffer whose size is
+ * four bytes. (That is four must be passed as the buffer_size
+ * parameter to cma_debug_set.)
+ */
+ cma_c_debset_priority = 1, /* Set the priority */
+ cma_c_debset_policy = 2, /* Set the sched policy */
+ cma_c_debset_hold = 3, /* Put thread on hold */
+ cma_c_debset_regs = 4 /* Set the regs and proc. state */
+
+ } cma_t_debug_set;
+
+
+/*
+ * GLOBAL DATA
+ *
+ * none
+ */
+
+/*
+ * EXTERNAL INTERFACES
+ */
+
+/*
+ * Routine to register with the CMA debug dispatcher.
+ */
+extern void cma_debug_register (cma_t_address,cma_t_key,cma_t_integer,cma_t_boolean);
+
+/*
+ * Routine to get get thread state needed by the CMA debug client.
+ */
+extern void cma_debug_get (cma_t_thread *,cma_t_debug_get,cma_t_address,cma_t_integer);
+
+/*
+ * Get thread context given an sp and a key
+ */
+extern void cma_debug_get_sp_context (cma_t_address,cma_t_key,cma_t_address *);
+
+/*
+ * Routine to set thread state as needed by the CMA debug client.
+ */
+extern void cma_debug_set (cma_t_thread *,cma_t_debug_set,cma_t_address,cma_t_integer);
+
+#endif
diff --git a/gdb/osf-share/cma_errors.h b/gdb/osf-share/cma_errors.h
new file mode 100644
index 00000000000..8ac1795745f
--- /dev/null
+++ b/gdb/osf-share/cma_errors.h
@@ -0,0 +1,55 @@
+/*
+ * (c) Copyright 1990-1996 OPEN SOFTWARE FOUNDATION, INC.
+ * (c) Copyright 1990-1996 HEWLETT-PACKARD COMPANY
+ * (c) Copyright 1990-1996 DIGITAL EQUIPMENT CORPORATION
+ * (c) Copyright 1991, 1992 Siemens-Nixdorf Information Systems
+ * To anyone who acknowledges that this file is provided "AS IS" without
+ * any express or implied warranty: permission to use, copy, modify, and
+ * distribute this file for any purpose is hereby granted without fee,
+ * provided that the above copyright notices and this notice appears in
+ * all source code copies, and that none of the names listed above be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. None of these organizations
+ * makes any representations about the suitability of this software for
+ * any purpose.
+ */
+/*
+ * This module is the interface between CMA services and
+ * the platform-specific error reporting mechanism.
+ */
+
+#ifndef CMA_ERRORS
+#define CMA_ERRORS
+
+/*
+ * INCLUDE FILES
+ */
+
+/*
+ * CONSTANTS AND MACROS
+ */
+
+/*
+ * TYPEDEFS
+ */
+
+/*
+ * GLOBAL DATA
+ */
+
+/*
+ * INTERNAL INTERFACES
+ */
+
+/*
+ * The cma__bugcheck function will print information to stderr (or sys$error
+ * on VMS), and more extensive information to the file cma_dump.log in the
+ * current working directory.
+ */
+extern void cma__bugcheck (char *,...);
+
+extern void cma__error (int);
+
+extern void cma__unimplemented (void);
+
+#endif
diff --git a/gdb/osf-share/cma_handle.h b/gdb/osf-share/cma_handle.h
new file mode 100644
index 00000000000..e63de018a04
--- /dev/null
+++ b/gdb/osf-share/cma_handle.h
@@ -0,0 +1,182 @@
+/*
+ * (c) Copyright 1990-1996 OPEN SOFTWARE FOUNDATION, INC.
+ * (c) Copyright 1990-1996 HEWLETT-PACKARD COMPANY
+ * (c) Copyright 1990-1996 DIGITAL EQUIPMENT CORPORATION
+ * (c) Copyright 1991, 1992 Siemens-Nixdorf Information Systems
+ * To anyone who acknowledges that this file is provided "AS IS" without
+ * any express or implied warranty: permission to use, copy, modify, and
+ * distribute this file for any purpose is hereby granted without fee,
+ * provided that the above copyright notices and this notice appears in
+ * all source code copies, and that none of the names listed above be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. None of these organizations
+ * makes any representations about the suitability of this software for
+ * any purpose.
+ */
+/*
+ * Header file for handles
+ */
+
+#ifndef CMA_HANDLE
+#define CMA_HANDLE
+
+/*
+ * INCLUDE FILES
+ */
+
+#include <cma_defs.h>
+#include <cma_attr.h>
+
+/*
+ * CONSTANTS AND MACROS
+ */
+
+#define cma__validate_attr(handle) \
+ ((cma__t_int_attr *)cma__validate_handle ( \
+ (cma_t_handle *)(handle), \
+ cma__c_obj_attr))
+
+#define cma__validate_cv(handle) \
+ ((cma__t_int_cv *)cma__validate_handle ( \
+ (cma_t_handle *)(handle), \
+ cma__c_obj_cv))
+
+#define cma__validate_mutex(handle) \
+ ((cma__t_int_mutex *)cma__validate_handle ( \
+ (cma_t_handle *)(handle), \
+ cma__c_obj_mutex))
+
+#define cma__validate_tcb(handle) \
+ ((cma__t_int_tcb *)cma__validate_handle ( \
+ (cma_t_handle *)(handle), \
+ cma__c_obj_tcb))
+
+#define cma__validate_stack(handle) \
+ ((cma__t_int_stack *)cma__validate_handle ( \
+ (cma_t_handle *)(handle), \
+ cma__c_obj_stack))
+
+#define cma__validate_null_attr(handle) \
+ ((cma__t_int_attr *)cma__validate_handle_null ( \
+ (cma_t_handle *)(handle), \
+ cma__c_obj_attr))
+
+#define cma__validate_null_cv(handle) \
+ ((cma__t_int_cv *)cma__validate_handle_null ( \
+ (cma_t_handle *)(handle), \
+ cma__c_obj_cv))
+
+#define cma__validate_null_mutex(handle) \
+ ((cma__t_int_mutex *)cma__validate_handle_null ( \
+ (cma_t_handle *)(handle), \
+ cma__c_obj_mutex))
+
+#define cma__validate_null_tcb(handle) \
+ ((cma__t_int_tcb *)cma__validate_handle_null ( \
+ (cma_t_handle *)(handle), \
+ cma__c_obj_tcb))
+
+#define cma__validate_null_stack(handle) \
+ ((cma__t_int_stack *)cma__validate_handle_null ( \
+ (cma_t_handle *)(handle), \
+ cma__c_obj_stack))
+
+#define cma__val_attr_stat(handle,obj) \
+ cma__val_hand_stat ( \
+ (cma_t_handle *)(handle), \
+ cma__c_obj_attr, \
+ (cma__t_object **)obj)
+
+#define cma__val_cv_stat(handle,obj) \
+ cma__val_hand_stat ( \
+ (cma_t_handle *)(handle), \
+ cma__c_obj_cv, \
+ (cma__t_object **)obj)
+
+#define cma__val_mutex_stat(handle,obj) \
+ cma__val_hand_stat ( \
+ (cma_t_handle *)(handle), \
+ cma__c_obj_mutex, \
+ (cma__t_object **)obj)
+
+#define cma__val_tcb_stat(handle) \
+ cma__val_hand_stat ( \
+ (cma_t_handle *)(handle), \
+ cma__c_obj_tcb, \
+ (cma__t_object **)obj)
+
+#define cma__val_stack_stat(handle,obj) \
+ cma__val_hand_stat ( \
+ (cma_t_handle *)(handle), \
+ cma__c_obj_stack, \
+ (cma__t_object **)obj)
+
+#define cma__val_nullattr_stat(handle,obj) \
+ cma__val_handnull_stat ( \
+ (cma_t_handle *)(handle), \
+ cma__c_obj_attr, \
+ (cma__t_object **)obj)
+
+#define cma__val_nullcv_stat(handle,obj) \
+ cma__val_handnull_stat ( \
+ (cma_t_handle *)(handle), \
+ cma__c_obj_cv, \
+ (cma__t_object **)obj)
+
+#define cma__val_nullmutex_stat(handle,obj) \
+ cma__val_handnull_stat ( \
+ (cma_t_handle *)(handle), \
+ cma__c_obj_mutex, \
+ (cma__t_object **)obj)
+
+#define cma__val_nulltcb_stat(handle,obj) \
+ cma__val_handnull_stat ( \
+ (cma_t_handle *)(handle), \
+ cma__c_obj_tcb, \
+ (cma__t_object **)obj)
+
+#define cma__val_nullstack_stat(handle) \
+ cma__val_handnull_stat ( \
+ (cma_t_handle *)(handle), \
+ cma__c_obj_stack, \
+ (cma__t_object **)obj)
+
+/*
+ * TYPEDEFS
+ */
+
+/*
+ * Internal format of a handle (to the outside world it's an array of two
+ * addresses, but we know better).
+ */
+typedef struct CMA__T_INT_HANDLE {
+ cma__t_object *pointer; /* Address of internal structure */
+ cma__t_short sequence; /* Sequence number of object */
+ cma__t_short type; /* Type code of object */
+ } cma__t_int_handle;
+
+/*
+ * GLOBAL DATA
+ */
+
+/*
+ * INTERNAL INTERFACES
+ */
+
+extern void cma__clear_handle (cma_t_handle *);
+
+extern void cma__object_to_handle (cma__t_object *,cma_t_handle *);
+
+extern cma__t_int_attr * cma__validate_default_attr (cma_t_handle *);
+
+extern cma_t_status cma__val_defattr_stat (cma_t_handle *,cma__t_int_attr **);
+
+extern cma__t_object * cma__validate_handle (cma_t_handle *,cma_t_natural );
+
+extern cma_t_status cma__val_hand_stat (cma_t_handle *,cma_t_natural,cma__t_object **);
+
+extern cma__t_object *cma__validate_handle_null (cma_t_handle *,cma_t_natural);
+
+extern cma_t_status cma__val_handnull_stat (cma_t_handle *,cma_t_natural,cma__t_object **);
+
+#endif
diff --git a/gdb/osf-share/cma_init.h b/gdb/osf-share/cma_init.h
new file mode 100644
index 00000000000..7309736c19c
--- /dev/null
+++ b/gdb/osf-share/cma_init.h
@@ -0,0 +1,114 @@
+/*
+ * (c) Copyright 1990-1996 OPEN SOFTWARE FOUNDATION, INC.
+ * (c) Copyright 1990-1996 HEWLETT-PACKARD COMPANY
+ * (c) Copyright 1990-1996 DIGITAL EQUIPMENT CORPORATION
+ * (c) Copyright 1991, 1992 Siemens-Nixdorf Information Systems
+ * To anyone who acknowledges that this file is provided "AS IS" without
+ * any express or implied warranty: permission to use, copy, modify, and
+ * distribute this file for any purpose is hereby granted without fee,
+ * provided that the above copyright notices and this notice appears in
+ * all source code copies, and that none of the names listed above be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. None of these organizations
+ * makes any representations about the suitability of this software for
+ * any purpose.
+ */
+/*
+ * Header file for CMA initialization
+ */
+
+#ifndef CMA_INIT
+#define CMA_INIT
+
+/*
+ * INCLUDE FILES
+ */
+#include <dce/cma_host.h>
+#include <cma_errors.h>
+
+/*
+ * CONSTANTS AND MACROS
+ */
+
+#define cma__c_env_maxattr 0
+#define cma__c_env_minattr 1
+#define cma__c_env_maxcond 2
+#define cma__c_env_mincond 3
+#define cma__c_env_maxmutex 4
+#define cma__c_env_minmutex 5
+#define cma__c_env_maxthread 6
+#define cma__c_env_minthread 7
+#define cma__c_env_maxcluster 8
+#define cma__c_env_mincluster 9
+#define cma__c_env_maxvp 10
+#define cma__c_env_multiplex 11
+#define cma__c_env_trace 12
+#define cma__c_env_trace_file 13
+
+#define cma__c_env_count 13
+
+
+/*
+ * cma__int_init
+ *
+ * Initialize the main body of CMA exactly once.
+ *
+ * We raise an exception if, for some odd reason, there are already threads
+ * in the environment (e.g. kernel threads), and one of them is trying to
+ * initialize CMA before the first thread got all the way through the actual
+ * initialization. This code maintains the invariants: "after successfully
+ * calling CMA_INIT, you can call any CMA function", and "CMA is actually
+ * initialized at most once".
+ */
+/*#ifndef _HP_LIBC_R */
+
+#if defined _HP_LIBC_R ||(defined(SNI_SVR4) && !defined(CMA_INIT_NEEDED))
+# define cma__int_init()
+#else
+# define cma__int_init() { \
+ if (!cma__tac_isset(&cma__g_init_started)) { \
+ if (!cma__test_and_set (&cma__g_init_started)) { \
+ cma__init_static (); \
+ cma__test_and_set (&cma__g_init_done); \
+ } \
+ else if (!cma__tac_isset (&cma__g_init_done)) { \
+ cma__error (cma_s_inialrpro); \
+ }}}
+#endif
+
+/*
+ * TYPEDEFS
+ */
+
+typedef enum CMA__T_ENV_TYPE {
+ cma__c_env_type_int,
+ cma__c_env_type_file
+ } cma__t_env_type;
+
+typedef struct CMA__T_ENV {
+ char *name; /* Name of environment variable */
+ cma__t_env_type type; /* Type of variable */
+ cma_t_integer value; /* Numeric value of the variable */
+ } cma__t_env;
+
+/*
+ * GLOBAL DATA
+ */
+
+extern cma__t_env cma__g_env[cma__c_env_count];
+extern cma__t_atomic_bit cma__g_init_started;
+extern cma__t_atomic_bit cma__g_init_done;
+extern char *cma__g_version;
+
+/*
+ * INTERNAL INTERFACES
+ */
+
+extern void
+cma__init_static (void); /* Initialize static data */
+
+#if _CMA_OS_ != _CMA__VMS
+extern void cma__init_atfork (void);
+#endif
+
+#endif
diff --git a/gdb/osf-share/cma_list.h b/gdb/osf-share/cma_list.h
new file mode 100644
index 00000000000..463fa49870f
--- /dev/null
+++ b/gdb/osf-share/cma_list.h
@@ -0,0 +1,84 @@
+/*
+ * (c) Copyright 1990-1996 OPEN SOFTWARE FOUNDATION, INC.
+ * (c) Copyright 1990-1996 HEWLETT-PACKARD COMPANY
+ * (c) Copyright 1990-1996 DIGITAL EQUIPMENT CORPORATION
+ * (c) Copyright 1991, 1992 Siemens-Nixdorf Information Systems
+ * To anyone who acknowledges that this file is provided "AS IS" without
+ * any express or implied warranty: permission to use, copy, modify, and
+ * distribute this file for any purpose is hereby granted without fee,
+ * provided that the above copyright notices and this notice appears in
+ * all source code copies, and that none of the names listed above be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. None of these organizations
+ * makes any representations about the suitability of this software for
+ * any purpose.
+ */
+/*
+ * Header file for generic list functions operating on singly linked
+ * null-terminated lists. Items may not be REMOVED from the list! The
+ * intent is that the list can be traversed (for read-only operations)
+ * without locking, since insertion is "safe" (though not truely
+ * atomic). THIS ASSUMES THAT THE HARDWARE MAKES WRITES VISIBLE TO READS
+ * IN THE ORDER IN WHICH THEY OCCURRED! WITHOUT SUCH READ/WRITE
+ * ORDERING, IT MAY BE NECESSARY TO INSERT "BARRIERS" TO PRODUCE THE
+ * REQUIRED VISIBILITY!
+ */
+
+#ifndef CMA_LIST
+#define CMA_LIST
+
+/*
+ * INCLUDE FILES
+ */
+
+#include <cma.h>
+
+/*
+ * CONSTANTS AND MACROS
+ */
+
+#define cma__c_null_list ((cma__t_list *)cma_c_null_ptr)
+
+/*
+ * Test whether a list is empty. Return cma_c_true if so, else
+ * cma_c_false.
+ */
+#define cma__list_empty(head) ((head)->link == cma__c_null_list)
+
+/*
+ * Initialize a queue header to empty.
+ */
+#define cma__list_init(head) (void)((head)->link = cma__c_null_list)
+
+/*
+ * Insert an element in a list following the specified item (or at the
+ * beginning of the list if "list" is the list head). NOTE: insertion
+ * operations should be interlocked by the caller!
+ */
+#define cma__list_insert(element,list) (void)( \
+ (element)->link = (list)->link, \
+ (list)->link = (element))
+
+/*
+ * Return the next item in a list (or the first, if the address is of the
+ * list header)
+ */
+#define cma__list_next(element) ((element)->link)
+
+/*
+ * TYPEDEFS
+ */
+
+typedef struct CMA__T_LIST {
+ struct CMA__T_LIST *link; /* Forward link */
+ } cma__t_list;
+
+/*
+ * GLOBAL DATA
+ */
+
+/*
+ * INTERNAL INTERFACES
+ */
+
+#endif
diff --git a/gdb/osf-share/cma_mutex.h b/gdb/osf-share/cma_mutex.h
new file mode 100644
index 00000000000..c178630dc84
--- /dev/null
+++ b/gdb/osf-share/cma_mutex.h
@@ -0,0 +1,230 @@
+/*
+ * (c) Copyright 1990-1996 OPEN SOFTWARE FOUNDATION, INC.
+ * (c) Copyright 1990-1996 HEWLETT-PACKARD COMPANY
+ * (c) Copyright 1990-1996 DIGITAL EQUIPMENT CORPORATION
+ * (c) Copyright 1991, 1992 Siemens-Nixdorf Information Systems
+ * To anyone who acknowledges that this file is provided "AS IS" without
+ * any express or implied warranty: permission to use, copy, modify, and
+ * distribute this file for any purpose is hereby granted without fee,
+ * provided that the above copyright notices and this notice appears in
+ * all source code copies, and that none of the names listed above be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. None of these organizations
+ * makes any representations about the suitability of this software for
+ * any purpose.
+ */
+/*
+ * Header file for mutex operations
+ */
+
+#ifndef CMA_MUTEX
+#define CMA_MUTEX
+
+/*
+ * INCLUDE FILES
+ */
+
+#include <cma.h>
+#include <cma_attr.h>
+#include <cma_defs.h>
+#include <cma_semaphore_defs.h>
+#include <cma_sequence.h>
+#include <cma_tcb_defs.h>
+#include <cma_stack.h>
+
+/*
+ * CONSTANTS AND MACROS
+ */
+
+/*
+ * TYPEDEFS
+ */
+
+typedef struct CMA__T_INT_MUTEX {
+ cma__t_object header; /* Common header (sequence, type) */
+ cma__t_int_attr *attributes; /* Back link */
+ cma__t_int_tcb *owner; /* Current owner (if any) */
+ cma_t_integer nest_count; /* Nesting level for recursive mutex */
+ cma__t_atomic_bit *unlock; /* Pointer used for unlock operation */
+ cma__t_atomic_bit lock; /* Set if currently locked */
+ struct CMA__T_INT_MUTEX *int_lock; /* Internal protection for mutex */
+ cma__t_atomic_bit event; /* Clear when unlock requires action */
+ cma__t_atomic_bit waiters; /* Clear when threads are waiting */
+ cma__t_atomic_bit bitbucket; /* Fake bit to keep friendlies locked */
+ cma_t_mutex_kind mutex_kind; /* Kind of mutex */
+ cma__t_semaphore semaphore; /* Semaphore for low-level wait */
+ } cma__t_int_mutex;
+
+
+/*
+ * FUNCTIONAL DESCRIPTION:
+ *
+ * Lock a mutex (internal)
+ *
+ * FORMAL PARAMETERS:
+ *
+ * mutex Pointer to mutex object to lock
+ *
+ * IMPLICIT INPUTS:
+ *
+ * none
+ *
+ * IMPLICIT OUTPUTS:
+ *
+ * none
+ *
+ * FUNCTION VALUE:
+ *
+ * none
+ *
+ * SIDE EFFECTS:
+ *
+ * none
+ */
+#ifdef NDEBUG
+# define cma__int_lock(mutex) { \
+ if (cma__test_and_set (&((cma__t_int_mutex *)mutex)->lock)) { \
+ cma_t_status res;\
+ res = cma__int_mutex_block ((cma__t_int_mutex *)mutex); \
+ if (res != cma_s_normal) cma__error (res); \
+ } \
+ }
+#else
+# define cma__int_lock(mutex) { \
+ cma__t_int_tcb *__ltcb__; \
+ __ltcb__ = cma__get_self_tcb (); \
+ if (cma__test_and_set (&((cma__t_int_mutex *)mutex)->lock)) { \
+ cma_t_status res;\
+ res = cma__int_mutex_block ((cma__t_int_mutex *)mutex); \
+ if (res != cma_s_normal) cma__error (res); \
+ } \
+ ((cma__t_int_mutex *)mutex)->owner = __ltcb__; \
+ }
+#endif
+
+/*
+ * FUNCTIONAL DESCRIPTION:
+ *
+ * Unlock a mutex (internal)
+ *
+ * FORMAL PARAMETERS:
+ *
+ * mutex Pointer to mutex object to unlock
+ *
+ * IMPLICIT INPUTS:
+ *
+ * none
+ *
+ * IMPLICIT OUTPUTS:
+ *
+ * none
+ *
+ * FUNCTION VALUE:
+ *
+ * none
+ *
+ * SIDE EFFECTS:
+ *
+ * none
+ */
+#ifdef NDEBUG
+# define cma__int_unlock(mutex) { \
+ cma__unset (((cma__t_int_mutex *)mutex)->unlock); \
+ if (!cma__test_and_set (&((cma__t_int_mutex *)mutex)->event)) { \
+ cma_t_status res;\
+ res = cma__int_mutex_unblock ((cma__t_int_mutex *)mutex); \
+ if (res != cma_s_normal) cma__error (res); \
+ } \
+ }
+#else
+# define cma__int_unlock(mutex) { \
+ cma__t_int_tcb *__utcb__; \
+ __utcb__ = cma__get_self_tcb (); \
+ if (((cma__t_int_mutex *)mutex)->mutex_kind == cma_c_mutex_fast) { \
+ cma__assert_warn ( \
+ (__utcb__ == ((cma__t_int_mutex *)mutex)->owner), \
+ "attempt to release mutx owned by another thread"); \
+ ((cma__t_int_mutex *)mutex)->owner = (cma__t_int_tcb *)cma_c_null_ptr; \
+ } \
+ cma__unset (((cma__t_int_mutex *)mutex)->unlock); \
+ if (!cma__test_and_set (&((cma__t_int_mutex *)mutex)->event)) { \
+ cma_t_status res;\
+ res = cma__int_mutex_unblock ((cma__t_int_mutex *)mutex); \
+ if (res != cma_s_normal) cma__error (res); \
+ } \
+ }
+#endif
+
+/*
+ * FUNCTIONAL DESCRIPTION:
+ *
+ * cma__int_mutex_delete - Performs work for cma_mutex_delete
+ *
+ * FORMAL PARAMETERS:
+ *
+ * cma__t_mutex _mutex_ - Mutex to be deleted
+ *
+ * IMPLICIT INPUTS:
+ *
+ * none
+ *
+ * IMPLICIT OUTPUTS:
+ *
+ * none
+ *
+ * FUNCTION VALUE:
+ *
+ * none
+ *
+ * SIDE EFFECTS:
+ *
+ * none
+ */
+#define cma__int_mutex_delete(_mutex_) { \
+ cma__t_int_mutex *_int_mutex_; \
+ _int_mutex_ = cma__validate_null_mutex (_mutex_); \
+ if (_int_mutex_ == (cma__t_int_mutex *)cma_c_null_ptr) \
+ return; \
+ if (cma__int_mutex_locked (_int_mutex_)) \
+ cma__error (cma_s_in_use); \
+ cma__free_mutex (_int_mutex_); \
+ cma__clear_handle (_mutex_); \
+ }
+
+
+/*
+ * GLOBAL DATA
+ */
+
+extern cma__t_sequence cma__g_mutex_seq;
+extern cma__t_int_mutex *cma__g_global_lock;
+
+/*
+ * INTERNAL INTERFACES
+ */
+
+extern void cma__destroy_mutex (cma__t_int_mutex *);
+
+extern void cma__free_mutex (cma__t_int_mutex *);
+
+extern void cma__free_mutex_nolock (cma__t_int_mutex *);
+
+extern cma__t_int_mutex * cma__get_first_mutex (cma__t_int_attr *);
+
+extern cma__t_int_mutex * cma__get_mutex (cma__t_int_attr *);
+
+extern void cma__init_mutex (void);
+
+extern cma_t_status cma__int_mutex_block (cma__t_int_mutex *);
+
+extern cma_t_boolean cma__int_mutex_locked (cma__t_int_mutex *);
+
+extern cma_t_boolean cma__int_try_lock (cma__t_int_mutex *);
+
+extern cma_t_status cma__int_mutex_unblock (cma__t_int_mutex *);
+
+extern cma_t_boolean cma__mutex_locked (cma_t_mutex);
+
+extern void cma__reinit_mutex (cma_t_integer);
+
+#endif
diff --git a/gdb/osf-share/cma_sched.h b/gdb/osf-share/cma_sched.h
new file mode 100644
index 00000000000..6eb78743baf
--- /dev/null
+++ b/gdb/osf-share/cma_sched.h
@@ -0,0 +1,279 @@
+/*
+ * (c) Copyright 1990-1996 OPEN SOFTWARE FOUNDATION, INC.
+ * (c) Copyright 1990-1996 HEWLETT-PACKARD COMPANY
+ * (c) Copyright 1990-1996 DIGITAL EQUIPMENT CORPORATION
+ * (c) Copyright 1991, 1992 Siemens-Nixdorf Information Systems
+ * To anyone who acknowledges that this file is provided "AS IS" without
+ * any express or implied warranty: permission to use, copy, modify, and
+ * distribute this file for any purpose is hereby granted without fee,
+ * provided that the above copyright notices and this notice appears in
+ * all source code copies, and that none of the names listed above be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. None of these organizations
+ * makes any representations about the suitability of this software for
+ * any purpose.
+ */
+/*
+ * Header file for priority scheduling
+ */
+
+
+#ifndef CMA_SCHED
+#define CMA_SCHED
+
+/*
+ * INCLUDE FILES
+ */
+
+/*
+ * CONSTANTS AND MACROS
+ */
+
+/*
+ * Scaling factor for integer priority calculations
+ */
+#define cma__c_prio_scale 8
+
+#if _CMA_VENDOR_ == _CMA__APOLLO
+/*
+ * FIX-ME: Apollo cc 6.8 blows contant folded "<<" and ">>"
+ */
+# define cma__scale_up(exp) ((exp) * 256)
+# define cma__scale_dn(exp) ((exp) / 256)
+#else
+# define cma__scale_up(exp) ((exp) << cma__c_prio_scale)
+# define cma__scale_dn(exp) ((exp) >> cma__c_prio_scale)
+#endif
+
+
+/*
+ * Min. num. of ticks between self-adjustments for priority adjusting policies.
+ */
+#define cma__c_prio_interval 10
+
+
+/*
+ * Number of queues in each class of queues
+ */
+#define cma__c_prio_n_id 1 /* Very-low-priority class threads */
+#define cma__c_prio_n_bg 8 /* Background class threads */
+#define cma__c_prio_n_0 1 /* Very low priority throughput quartile */
+#define cma__c_prio_n_1 2 /* Low priority throughput quartile */
+#define cma__c_prio_n_2 3 /* Medium priority throughput quartile */
+#define cma__c_prio_n_3 4 /* High priority throughput quartile */
+#define cma__c_prio_n_rt 1 /* Real Time priority queues */
+
+/*
+ * Number of queues to skip (offset) to get to the queues in this section of LA
+ */
+#define cma__c_prio_o_id 0
+#define cma__c_prio_o_bg cma__c_prio_o_id + cma__c_prio_n_id
+#define cma__c_prio_o_0 cma__c_prio_o_bg + cma__c_prio_n_bg
+#define cma__c_prio_o_1 cma__c_prio_o_0 + cma__c_prio_n_0
+#define cma__c_prio_o_2 cma__c_prio_o_1 + cma__c_prio_n_1
+#define cma__c_prio_o_3 cma__c_prio_o_2 + cma__c_prio_n_2
+#define cma__c_prio_o_rt cma__c_prio_o_3 + cma__c_prio_n_3
+
+/*
+ * Ada_low: These threads are queued in the background queues, thus there
+ * must be enough queues to allow one queue for each Ada priority below the
+ * Ada default.
+ */
+#define cma__c_prio_o_al cma__c_prio_o_bg
+
+/*
+ * Total number of ready queues, for declaration purposes
+ */
+#define cma__c_prio_n_tot \
+ cma__c_prio_n_id + cma__c_prio_n_bg + cma__c_prio_n_rt \
+ + cma__c_prio_n_0 + cma__c_prio_n_1 + cma__c_prio_n_2 + cma__c_prio_n_3
+
+/*
+ * Formulae for determining a thread's priority. Variable priorities (such
+ * as foreground and background) are scaled values.
+ */
+#define cma__sched_priority(tcb) \
+ ((tcb)->sched.class == cma__c_class_fore ? cma__sched_prio_fore (tcb) \
+ :((tcb)->sched.class == cma__c_class_back ? cma__sched_prio_back (tcb) \
+ :((tcb)->sched.class == cma__c_class_rt ? cma__sched_prio_rt (tcb) \
+ :((tcb)->sched.class == cma__c_class_idle ? cma__sched_prio_idle (tcb) \
+ :(cma__bugcheck ("cma__sched_priority: unrecognized class"), 0) ))))
+
+#define cma__sched_prio_fore(tcb) cma__sched_prio_fore_var (tcb)
+#define cma__sched_prio_back(tcb) ((tcb)->sched.fixed_prio \
+ ? cma__sched_prio_back_fix (tcb) : cma__sched_prio_back_var (tcb) )
+#define cma__sched_prio_rt(tcb) ((tcb)->sched.priority)
+#define cma__sched_prio_idle(tcb) ((tcb)->sched.priority)
+
+#define cma__sched_prio_back_fix(tcb) \
+ (cma__g_prio_bg_min + (cma__g_prio_bg_max - cma__g_prio_bg_min) \
+ * ((tcb)->sched.priority + cma__c_prio_o_al - cma__c_prio_o_bg) \
+ / cma__c_prio_n_bg)
+
+/*
+ * FIX-ME: Enable after modeling (if we like it)
+ */
+#if 1
+# define cma__sched_prio_fore_var(tcb) \
+ ((cma__g_prio_fg_max + cma__g_prio_fg_min)/2)
+# define cma__sched_prio_back_var(tcb) \
+ ((cma__g_prio_bg_max + cma__g_prio_bg_min)/2)
+#else
+# define cma__sched_prio_back_var(tcb) cma__sched_prio_fore_var (tcb)
+
+# if 1
+/*
+ * Re-scale, since the division removes the scale factor.
+ * Scale and multiply before dividing to avoid loss of precision.
+ */
+# define cma__sched_prio_fore_var(tcb) \
+ ((cma__g_vp_count * cma__scale_up((tcb)->sched.tot_time)) \
+ / (tcb)->sched.cpu_time)
+# else
+/*
+ * Re-scale, since the division removes the scale factor.
+ * Scale and multiply before dividing to avoid loss of precision.
+ * Left shift the numerator to multiply by two.
+ */
+# define cma__sched_prio_fore_var(tcb) \
+ (((cma__g_vp_count * cma__scale_up((tcb)->sched.tot_time) \
+ * (tcb)->sched.priority * cma__g_init_frac_sum) << 1) \
+ / ((tcb)->sched.cpu_time * (tcb)->sched.priority * cma__g_init_frac_sum \
+ + (tcb)->sched.tot_time))
+# endif
+#endif
+
+/*
+ * Update weighted-averaged, scaled tick counters
+ */
+#define cma__sched_update_time(ave, new) \
+ (ave) = (ave) - ((cma__scale_dn((ave)) - (new)) << (cma__c_prio_scale - 4))
+
+#define cma__sched_parameterize(tcb, policy) { \
+ switch (policy) { \
+ case cma_c_sched_fifo : { \
+ (tcb)->sched.rtb = cma_c_true; \
+ (tcb)->sched.spp = cma_c_true; \
+ (tcb)->sched.fixed_prio = cma_c_true; \
+ (tcb)->sched.class = cma__c_class_rt; \
+ break; \
+ } \
+ case cma_c_sched_rr : { \
+ (tcb)->sched.rtb = cma_c_false; \
+ (tcb)->sched.spp = cma_c_true; \
+ (tcb)->sched.fixed_prio = cma_c_true; \
+ (tcb)->sched.class = cma__c_class_rt; \
+ break; \
+ } \
+ case cma_c_sched_throughput : { \
+ (tcb)->sched.rtb = cma_c_false; \
+ (tcb)->sched.spp = cma_c_false; \
+ (tcb)->sched.fixed_prio = cma_c_false; \
+ (tcb)->sched.class = cma__c_class_fore; \
+ break; \
+ } \
+ case cma_c_sched_background : { \
+ (tcb)->sched.rtb = cma_c_false; \
+ (tcb)->sched.spp = cma_c_false; \
+ (tcb)->sched.fixed_prio = cma_c_false; \
+ (tcb)->sched.class = cma__c_class_back; \
+ break; \
+ } \
+ case cma_c_sched_ada_low : { \
+ (tcb)->sched.rtb = cma_c_false; \
+ (tcb)->sched.spp = cma_c_true; \
+ (tcb)->sched.fixed_prio = cma_c_true; \
+ (tcb)->sched.class = cma__c_class_back; \
+ break; \
+ } \
+ case cma_c_sched_idle : { \
+ (tcb)->sched.rtb = cma_c_false; \
+ (tcb)->sched.spp = cma_c_false; \
+ (tcb)->sched.fixed_prio = cma_c_false; \
+ (tcb)->sched.class = cma__c_class_idle; \
+ break; \
+ } \
+ default : { \
+ cma__bugcheck ("cma__sched_parameterize: bad scheduling Policy"); \
+ break; \
+ } \
+ } \
+ }
+
+/*
+ * TYPEDEFS
+ */
+
+/*
+ * Scheduling classes
+ */
+typedef enum CMA__T_SCHED_CLASS {
+ cma__c_class_rt,
+ cma__c_class_fore,
+ cma__c_class_back,
+ cma__c_class_idle
+ } cma__t_sched_class;
+
+/*
+ * GLOBAL DATA
+ */
+
+/*
+ * Minimuma and maximum prioirities, for foreground and background threads,
+ * as of the last time the scheduler ran. (Scaled once.)
+ */
+extern cma_t_integer cma__g_prio_fg_min;
+extern cma_t_integer cma__g_prio_fg_max;
+extern cma_t_integer cma__g_prio_bg_min;
+extern cma_t_integer cma__g_prio_bg_max;
+
+/*
+ * The "m" values are the slopes of the four sections of linear approximation.
+ *
+ * cma__g_prio_m_I = 4*N(I)/cma__g_prio_range (Scaled once.)
+ */
+extern cma_t_integer cma__g_prio_m_0,
+ cma__g_prio_m_1,
+ cma__g_prio_m_2,
+ cma__g_prio_m_3;
+
+/*
+ * The "b" values are the intercepts of the four sections of linear approx.
+ * (Not scaled.)
+ *
+ * cma__g_prio_b_I = -N(I)*(I*prio_max + (4-I)*prio_min)/prio_range + prio_o_I
+ */
+extern cma_t_integer cma__g_prio_b_0,
+ cma__g_prio_b_1,
+ cma__g_prio_b_2,
+ cma__g_prio_b_3;
+
+/*
+ * The "p" values are the end points of the four sections of linear approx.
+ *
+ * cma__g_prio_p_I = cma__g_prio_fg_min + (I/4)*cma__g_prio_range
+ *
+ * [cma__g_prio_p_0 is not defined since it is not used (also, it is the same
+ * as cma__g_prio_fg_min).] (Scaled once.)
+ */
+extern cma_t_integer cma__g_prio_p_1,
+ cma__g_prio_p_2,
+ cma__g_prio_p_3;
+
+/*
+ * Points to the next queue for the dispatcher to check for ready threads.
+ */
+extern cma_t_integer cma__g_next_ready_queue;
+
+/*
+ * Points to the queues of virtual processors (for preempt victim search)
+ */
+extern cma__t_queue cma__g_run_vps;
+extern cma__t_queue cma__g_susp_vps;
+extern cma_t_integer cma__g_vp_count;
+
+/*
+ * INTERNAL INTERFACES
+ */
+
+#endif
diff --git a/gdb/osf-share/cma_semaphore_defs.h b/gdb/osf-share/cma_semaphore_defs.h
new file mode 100644
index 00000000000..e160de33944
--- /dev/null
+++ b/gdb/osf-share/cma_semaphore_defs.h
@@ -0,0 +1,46 @@
+/*
+ * (c) Copyright 1990-1996 OPEN SOFTWARE FOUNDATION, INC.
+ * (c) Copyright 1990-1996 HEWLETT-PACKARD COMPANY
+ * (c) Copyright 1990-1996 DIGITAL EQUIPMENT CORPORATION
+ * (c) Copyright 1991, 1992 Siemens-Nixdorf Information Systems
+ * To anyone who acknowledges that this file is provided "AS IS" without
+ * any express or implied warranty: permission to use, copy, modify, and
+ * distribute this file for any purpose is hereby granted without fee,
+ * provided that the above copyright notices and this notice appears in
+ * all source code copies, and that none of the names listed above be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. None of these organizations
+ * makes any representations about the suitability of this software for
+ * any purpose.
+ */
+/*
+ * Header file for semaphore structure definition.
+ */
+#ifndef CMA_SEMAPHORE_DEFS
+#define CMA_SEMAPHORE_DEFS
+
+/*
+ * INCLUDE FILES
+ */
+#include <cma.h>
+#include <cma_queue.h>
+#include <cma_defs.h>
+
+/*
+ * CONSTANTS AND MACROS
+ */
+
+#define cma__c_semaphore_timeout 1
+#define cma__c_semaphore_event 0
+#define cma__c_select_timeout 2
+
+/*
+ * TYPEDEFS
+ */
+
+typedef struct CMA__T_SEMAPHORE {
+ cma__t_queue queue;
+ cma__t_atomic_bit nopending;
+ } cma__t_semaphore;
+
+#endif
diff --git a/gdb/osf-share/cma_sequence.h b/gdb/osf-share/cma_sequence.h
new file mode 100644
index 00000000000..8d362ed8d87
--- /dev/null
+++ b/gdb/osf-share/cma_sequence.h
@@ -0,0 +1,56 @@
+/*
+ * (c) Copyright 1990-1996 OPEN SOFTWARE FOUNDATION, INC.
+ * (c) Copyright 1990-1996 HEWLETT-PACKARD COMPANY
+ * (c) Copyright 1990-1996 DIGITAL EQUIPMENT CORPORATION
+ * (c) Copyright 1991, 1992 Siemens-Nixdorf Information Systems
+ * To anyone who acknowledges that this file is provided "AS IS" without
+ * any express or implied warranty: permission to use, copy, modify, and
+ * distribute this file for any purpose is hereby granted without fee,
+ * provided that the above copyright notices and this notice appears in
+ * all source code copies, and that none of the names listed above be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. None of these organizations
+ * makes any representations about the suitability of this software for
+ * any purpose.
+ */
+/*
+ * Header file for sequence generator functions
+ */
+
+#ifndef CMA_SEQUENCE
+#define CMA_SEQUENCE
+
+/*
+ * INCLUDE FILES
+ */
+
+/*
+ * CONSTANTS AND MACROS
+ */
+
+/*
+ * TYPEDEFS
+ */
+
+#ifndef __STDC__
+struct CMA__T_INT_MUTEX;
+#endif
+
+typedef struct CMA__T_SEQUENCE {
+ struct CMA__T_INT_MUTEX *mutex; /* Serialize access to counter */
+ cma_t_natural seq; /* Sequence number for object */
+ } cma__t_sequence;
+
+/*
+ * GLOBAL DATA
+ */
+
+/*
+ * INTERNAL INTERFACES
+ */
+
+extern cma_t_natural cma__assign_sequence (cma__t_sequence *);
+
+extern void cma__init_sequence (cma__t_sequence *);
+
+#endif
diff --git a/gdb/osf-share/cma_stack.h b/gdb/osf-share/cma_stack.h
new file mode 100644
index 00000000000..97a41fd6e95
--- /dev/null
+++ b/gdb/osf-share/cma_stack.h
@@ -0,0 +1,83 @@
+/*
+ * (c) Copyright 1990-1996 OPEN SOFTWARE FOUNDATION, INC.
+ * (c) Copyright 1990-1996 HEWLETT-PACKARD COMPANY
+ * (c) Copyright 1990-1996 DIGITAL EQUIPMENT CORPORATION
+ * (c) Copyright 1991, 1992 Siemens-Nixdorf Information Systems
+ * To anyone who acknowledges that this file is provided "AS IS" without
+ * any express or implied warranty: permission to use, copy, modify, and
+ * distribute this file for any purpose is hereby granted without fee,
+ * provided that the above copyright notices and this notice appears in
+ * all source code copies, and that none of the names listed above be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. None of these organizations
+ * makes any representations about the suitability of this software for
+ * any purpose.
+ */
+/*
+ * Header file for stack management
+ */
+#ifndef CMA_STACK
+#define CMA_STACK
+
+/*
+ * INCLUDE FILES
+ */
+
+#include <cma_tcb_defs.h>
+#include <cma.h>
+#include <cma_attr.h>
+#include <cma_queue.h>
+#include <cma_stack_int.h>
+
+/*
+ * CONSTANTS AND MACROS
+ */
+
+#if _CMA_UNIPROCESSOR_
+# define cma__get_self_tcb() (cma__g_current_thread)
+#endif
+
+/*
+ * Round the given value (a) upto cma__g_chunk_size
+ */
+#define cma__roundup_chunksize(a) (cma__roundup(a,cma__g_chunk_size))
+
+/*
+ * TYPEDEFS
+ */
+
+/*
+ * GLOBAL DATA
+ */
+
+extern cma__t_list cma__g_stack_clusters;
+extern cma__t_int_tcb *cma__g_current_thread;
+extern cma_t_integer cma__g_chunk_size;
+
+/*
+ * INTERNAL INTERFACES
+ */
+
+extern void cma__assign_stack (cma__t_int_stack *,cma__t_int_tcb *);
+
+extern void cma__free_stack (cma__t_int_stack *);
+
+extern void cma__free_stack_list (cma__t_queue *);
+
+#if !_CMA_UNIPROCESSOR_
+extern cma__t_int_tcb * cma__get_self_tcb (void);
+#endif
+
+extern cma__t_int_tcb * cma__get_sp_tcb (cma_t_address);
+
+extern cma__t_int_stack * cma__get_stack (cma__t_int_attr *);
+
+extern void cma__init_stack (void);
+
+extern void cma__reinit_stack (cma_t_integer);
+
+#if _CMA_PROTECT_MEMORY_
+extern void cma__remap_stack_holes (void);
+#endif
+
+#endif
diff --git a/gdb/osf-share/cma_stack_int.h b/gdb/osf-share/cma_stack_int.h
new file mode 100644
index 00000000000..bf76f60756e
--- /dev/null
+++ b/gdb/osf-share/cma_stack_int.h
@@ -0,0 +1,136 @@
+/*
+ * (c) Copyright 1990-1996 OPEN SOFTWARE FOUNDATION, INC.
+ * (c) Copyright 1990-1996 HEWLETT-PACKARD COMPANY
+ * (c) Copyright 1990-1996 DIGITAL EQUIPMENT CORPORATION
+ * (c) Copyright 1991, 1992 Siemens-Nixdorf Information Systems
+ * To anyone who acknowledges that this file is provided "AS IS" without
+ * any express or implied warranty: permission to use, copy, modify, and
+ * distribute this file for any purpose is hereby granted without fee,
+ * provided that the above copyright notices and this notice appears in
+ * all source code copies, and that none of the names listed above be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. None of these organizations
+ * makes any representations about the suitability of this software for
+ * any purpose.
+ */
+/*
+ * Header file for stack management (internal to cma_stack.c, but
+ * separate for convenience, and unit testing).
+ */
+
+#ifndef CMA_STACK_INT
+#define CMA_STACK_INT
+
+/*
+ * INCLUDE FILES
+ */
+
+#include <cma.h>
+#include <cma_queue.h>
+#include <cma_list.h>
+#include <cma_tcb_defs.h>
+
+/*
+ * CONSTANTS AND MACROS
+ */
+
+#define cma___c_first_free_chunk 0
+#define cma___c_min_count 2 /* Smallest number of chunks to leave */
+#define cma___c_end (-1) /* End of free list (flag) */
+#define cma__c_yellow_size 0
+
+/*
+ * Cluster types
+ */
+#define cma___c_cluster 0 /* Default cluster */
+#define cma___c_bigstack 1 /* Looks like a cluster, but it's a stack */
+
+
+#define cma___c_null_cluster (cma___t_cluster *)cma_c_null_ptr
+
+
+/*
+ * TYPEDEFS
+ */
+
+#ifndef __STDC__
+struct CMA__T_INT_STACK;
+#endif
+
+typedef cma_t_natural cma___t_index; /* Type for chunk index */
+
+typedef struct CMA___T_CLU_DESC {
+ cma__t_list list; /* Queue element for cluster list */
+ cma_t_integer type; /* Type of cluster */
+ cma_t_address stacks;
+ cma_t_address limit;
+ } cma___t_clu_desc;
+
+typedef union CMA___T_MAP_ENTRY {
+ struct {
+ cma__t_int_tcb *tcb; /* TCB associated with stack chunk */
+ struct CMA__T_INT_STACK *stack; /* Stack desc. ass. with stack chunk */
+ } mapped;
+ struct {
+ cma___t_index size; /* Number of chunks in block */
+ cma___t_index next; /* Next free block */
+ } free;
+ } cma___t_map_entry;
+
+/*
+ * NOTE: It is VERY IMPORTANT that both cma___t_cluster and cma___t_bigstack
+ * begin with the cma___t_clu_desc structure, as there is some code in the
+ * stack manager that relies on being able to treat both as equivalent!
+ */
+typedef struct CMA___T_CLUSTER {
+ cma___t_clu_desc desc; /* Describe this cluster */
+ cma___t_map_entry map[cma__c_chunk_count]; /* thread map */
+ cma___t_index free; /* First free chunk index */
+ } cma___t_cluster;
+
+/*
+ * NOTE: It is VERY IMPORTANT that both cma___t_cluster and cma___t_bigstack
+ * begin with the cma___t_clu_desc structure, as there is some code in the
+ * stack manager that relies on being able to treat both as equivalent!
+ */
+typedef struct CMA___T_BIGSTACK {
+ cma___t_clu_desc desc; /* Describe this cluster */
+ cma__t_int_tcb *tcb; /* TCB associated with stack */
+ struct CMA__T_INT_STACK *stack; /* Stack desc. ass. with stack */
+ cma_t_natural size; /* Size of big stack */
+ cma_t_boolean in_use; /* Set if allocated */
+ } cma___t_bigstack;
+
+#if _CMA_PROTECT_MEMORY_
+typedef struct CMA___T_INT_HOLE {
+ cma__t_queue link; /* Link holes together */
+ cma_t_boolean protected; /* Set when pages are protected */
+ cma_t_address first; /* First protected byte */
+ cma_t_address last; /* Last protected byte */
+ } cma___t_int_hole;
+#endif
+
+typedef struct CMA__T_INT_STACK {
+ cma__t_object header; /* Common header (sequence, type info */
+ cma__t_int_attr *attributes; /* Backpointer to attr obj */
+ cma___t_cluster *cluster; /* Stack's cluster */
+ cma_t_address stack_base; /* base address of stack */
+ cma_t_address yellow_zone; /* first address of yellow zone */
+ cma_t_address last_guard; /* last address of guard pages */
+ cma_t_natural first_chunk; /* First chunk allocated */
+ cma_t_natural chunk_count; /* Count of chunks allocated */
+ cma__t_int_tcb *tcb; /* TCB backpointer */
+#if _CMA_PROTECT_MEMORY_
+ cma___t_int_hole hole; /* Description of hole */
+#endif
+ } cma__t_int_stack;
+
+/*
+ * GLOBAL DATA
+ */
+
+/*
+ * INTERNAL INTERFACES
+ */
+
+#endif
diff --git a/gdb/osf-share/cma_tcb_defs.h b/gdb/osf-share/cma_tcb_defs.h
new file mode 100644
index 00000000000..6622050cf73
--- /dev/null
+++ b/gdb/osf-share/cma_tcb_defs.h
@@ -0,0 +1,269 @@
+/*
+ * (c) Copyright 1990-1996 OPEN SOFTWARE FOUNDATION, INC.
+ * (c) Copyright 1990-1996 HEWLETT-PACKARD COMPANY
+ * (c) Copyright 1990-1996 DIGITAL EQUIPMENT CORPORATION
+ * (c) Copyright 1991, 1992 Siemens-Nixdorf Information Systems
+ * To anyone who acknowledges that this file is provided "AS IS" without
+ * any express or implied warranty: permission to use, copy, modify, and
+ * distribute this file for any purpose is hereby granted without fee,
+ * provided that the above copyright notices and this notice appears in
+ * all source code copies, and that none of the names listed above be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. None of these organizations
+ * makes any representations about the suitability of this software for
+ * any purpose.
+ */
+/*
+ * TCB-related type definitions.
+ */
+
+#ifndef CMA_TCB_DEFS
+#define CMA_TCB_DEFS
+
+/*
+ * INCLUDE FILES
+ */
+# if !_CMA_THREAD_SYNC_IO_
+# include <cma_thread_io.h>
+# endif
+#include <cma.h>
+#include <cma_debug_client.h>
+#include <cma_attr.h>
+#include <cma_defs.h>
+#include <cma_handle.h>
+#include <cma_queue.h>
+#if _CMA_OS_ == _CMA__UNIX
+# if defined(SNI_DCOSX)
+# include <sys/ucontext.h>
+# endif
+# include <signal.h>
+#endif
+#include <cma_sched.h>
+
+/*
+ * CONSTANTS AND MACROS
+ */
+
+#if _CMA_PLATFORM_ == _CMA__IBMR2_UNIX
+# define cma__c_ibmr2_ctx_stack_size 2048
+# define cma__c_ibmr2_ctx_stack_top (cma__c_ibmr2_ctx_stack_size - 1)
+#endif
+
+/*
+ * TYPEDEFS
+ */
+
+#ifndef __STDC__
+# if _CMA_HARDWARE_ != _CMA__HPPA
+struct CMA__T_SEMAPHORE;
+# endif
+struct CMA__T_INT_CV;
+struct CMA__T_INT_MUTEX;
+struct CMA__T_INT_TCB;
+#endif
+
+typedef cma_t_address *cma__t_context_list;
+
+typedef struct CMA__T_TCB_PAD {
+ /*
+ * Adjust to align the tcb prolog at byte 32.
+ * 12 bytes are required as object header is currently
+ * 20 bytes long.
+ */
+ cma_t_integer pad1; /* pad bytes */
+ cma_t_integer pad2; /* pad bytes */
+ cma_t_integer pad3; /* pad bytes */
+ } cma__t_tcb_pad;
+
+#if (_CMA_OS_ == _CMA__UNIX) && !_CMA_THREAD_SYNC_IO_
+typedef struct CMA__T_TCB_SELECT {
+ cma__t_queue queue;
+#if (_CMA_UNIX_TYPE != _CMA__SVR4)
+ cma__t_file_mask *rfds;
+ cma__t_file_mask *wfds;
+ cma__t_file_mask *efds;
+#else
+ cma__t_poll_info poll_info;
+#endif /* (_CMA_UNIX_TYPE != _CMA__SVR4) */
+ cma_t_integer nfound;
+ } cma__t_tcb_select;
+#endif
+
+typedef struct CMA__T_TCB_TIME {
+ cma__t_queue queue; /* must be first entry! */
+ cma_t_integer mode;
+ struct CMA__T_SEMAPHORE *semaphore; /* used for timed semaphores */
+ cma_t_date_time wakeup_time;
+ cma_t_integer quanta_remaining;
+ } cma__t_tcb_time;
+
+typedef enum CMA__T_DEBEVT {
+ cma__c_debevt_activating = 1, /* First transition to running */
+ cma__c_debevt_running = 2, /* Any transition to running */
+ cma__c_debevt_preempting = 3, /* Preemted (replaced) another thread */
+ cma__c_debevt_blocking = 4, /* Any transition to blocked */
+ cma__c_debevt_terminating = 5, /* Final state transition */
+ cma__c_debevt_term_alert = 6, /* Terminated due to alert/cancel */
+ cma__c_debevt_term_exc = 7, /* Terminated due to exception */
+ cma__c_debevt_exc_handled = 8 /* Exception is being handled */
+ } cma__t_debevt;
+
+#define cma__c_debevt__first ((cma_t_integer)cma__c_debevt_activating)
+#define cma__c_debevt__last ((cma_t_integer)cma__c_debevt_exc_handled)
+#define cma__c_debevt__dim (cma__c_debevt__last + 1)
+
+/*
+ * Type defining thread substate, which is used by the debugger.
+ * If the state is blocked, substate indicates WHY the thread is blocked.
+ */
+typedef enum CMA__T_SUBSTATE {
+ cma__c_substa_normal = 0,
+ cma__c_substa_mutex = 1,
+ cma__c_substa_cv = 2,
+ cma__c_substa_timed_cv = 3,
+ cma__c_substa_term_alt = 4,
+ cma__c_substa_term_exc = 5,
+ cma__c_substa_delay =6,
+ cma__c_substa_not_yet_run = 7
+ } cma__t_substate;
+#define cma__c_substa__first ((cma_t_integer)cma__c_substa_normal)
+#define cma__c_substa__last ((cma_t_integer)cma__c_substa_not_yet_run)
+#define cma__c_substa__dim (cma__c_substa__last + 1)
+
+
+/*
+ * Per-thread state for the debugger
+ */
+typedef struct CMA__T_TCB_DEBUG {
+ cma_t_boolean on_hold; /* Thread was put on hold by debugger */
+ cma_t_boolean activated; /* Activation event was reported */
+ cma_t_boolean did_preempt; /* Thread preempted prior one */
+ cma_t_address start_pc; /* Start routine address */
+ cma_t_address object_addr; /* Addr of thread object */
+ cma__t_substate substate; /* Reason blocked, terminated, etc.*/
+ cma_t_boolean notify_debugger;/* Notify debugger thread is running */
+ cma_t_address SPARE2; /* SPARE */
+ cma_t_address SPARE3; /* SPARE */
+ struct CMA__T_INT_TCB
+ *preempted_tcb; /* TCB of thread that got preempted */
+ cma_t_boolean flags[cma__c_debevt__dim];
+ /* Events enabled for this thread */
+ } cma__t_tcb_debug;
+
+typedef struct CMA__T_TCB_SCHED {
+ cma_t_integer adj_time; /* Abs. time in ticks of last prio adj */
+ cma_t_integer tot_time; /* Weighted ave in ticks (scaled) */
+ cma_t_integer time_stamp; /* Abs. time in ticks of last update */
+ cma_t_integer cpu_time; /* Weighted average in ticks */
+ cma_t_integer cpu_ticks; /* # of ticks while comp. (scaled) */
+ cma_t_integer q_num; /* Number of last ready queue on */
+ cma_t_priority priority; /* Thread priority */
+ cma_t_sched_policy policy; /* Scheduling policy of thread */
+ cma_t_boolean rtb; /* "Run 'Till Block" scheduling */
+ cma_t_boolean spp; /* "Strict Priority Preemption" sched */
+ cma_t_boolean fixed_prio; /* Fixed priority */
+ cma__t_sched_class class; /* Scheduling class */
+ struct CMA__T_VP *processor; /* Current processor (if running) */
+ } cma__t_tcb_sched;
+
+typedef struct CMA__T_INT_ALERT {
+ cma_t_boolean pending : 1; /* alert_pending bit */
+ cma_t_boolean g_enable : 1; /* general delivery state */
+ cma_t_boolean a_enable : 1; /* asynchronous delivery state */
+ cma_t_integer spare : 29; /* Pad to longword */
+ cma_t_natural count; /* Alert scope nesting count */
+ } cma__t_int_alert;
+
+typedef enum CMA__T_STATE {
+ cma__c_state_running = 0, /* For consistency with initial TCB */
+ cma__c_state_ready = 1,
+ cma__c_state_blocked = 2,
+ cma__c_state_terminated = 3
+ } cma__t_state;
+#define cma__c_state__first ((cma_t_integer)cma__c_state_running)
+#define cma__c_state__last ((cma_t_integer)cma__c_state_terminated)
+#define cma__c_state__dim (cma__c_state__last + 1)
+
+typedef enum CMA__T_THKIND {
+ cma__c_thkind_initial = 0, /* Initial thread */
+ cma__c_thkind_normal = 1, /* Normal thread */
+ cma__c_thkind_null = 2 /* A null thread */
+ } cma__t_thkind;
+#define cma__c_thkind__first ((cma_t_integer)cma__c_thkind_initial)
+#define cma__c_thkind__last ((cma_t_integer)cma__c_thkind_null)
+#define cma__c_thkind__dim (cma__c_thkind__last + 1)
+
+typedef enum CMA__T_SYSCALL_STATE {
+ cma__c_syscall_ok = 1, /* syscall was not interrupted */
+ cma__c_syscall_intintrpt = 1, /* syscall was interrupted by VTALRM */
+ cma__c_syscall_extintrpt = 2 /* syscall was interrupted by external signal */
+ } cma__t_syscall_state;
+
+
+typedef struct CMA__T_INT_TCB {
+ /*
+ * Fixed part of TCB.
+ * Modifications to the following three fields must be coordinated.
+ * The object header must always be first, and the prolog must always
+ * remain at the same offset (32) for all time. Thus the object header
+ * must never grow beyond a maximum of 32 bytes.
+ */
+ cma__t_object header; /* Common object header */
+ cma__t_tcb_pad pad1; /* Pad required to align prolog */
+ cma_t_tcb_prolog prolog; /* Standard prolog for tasks, threads */
+
+ /*
+ * Floating part of TCB (fields here on are free to be moved and resized).
+ */
+ cma__t_queue threads; /* List of all known threads */
+ cma__t_int_attr *attributes; /* Backpointer to attr obj */
+ cma__t_state state; /* Current state of thread */
+ cma__t_thkind kind; /* Which kind of thread */
+ struct CMA__T_INT_MUTEX
+ *mutex; /* Mutex to control TCB access */
+ struct CMA__T_INT_CV
+ *term_cv; /* CV for join */
+ struct CMA__T_INT_MUTEX
+ *tswait_mutex; /* Mutex for thread-synchronous waits */
+ struct CMA__T_INT_CV
+ *tswait_cv; /* CV for thread-synchronous waits */
+ cma_t_start_routine start_code; /* Address of start routine */
+ cma_t_address start_arg; /* Argument to pass to start_code */
+ cma__t_queue stack; /* Queue header for stack descr. */
+ cma_t_natural context_count; /* Size of context array */
+ cma__t_context_list contexts; /* Context value array pointer */
+ cma_t_exit_status exit_status; /* Exit status of thread */
+ cma_t_address return_value; /* Thread's return value */
+ cma__t_async_ctx async_ctx; /* Asynchronous context switch info */
+ cma__t_static_ctx static_ctx; /* Static context switch information */
+ cma_t_integer event_status; /* Status of semaphore operation */
+ cma__t_tcb_time timer; /* Time info for dispatcher */
+ cma__t_tcb_sched sched; /* Scheduler info */
+ cma__t_tcb_debug debug; /* Debugger info */
+#if _CMA_OS_ == _CMA__UNIX
+# if !_CMA_THREAD_SYNC_IO_
+ cma__t_tcb_select select; /* Select info for timed selects */
+# endif
+ struct sigaction sigaction_data[NSIG];
+#endif
+ cma_t_natural syscall_state; /* set if one of the cma wrapped syscalls was interrupted. */
+ cma_t_boolean detached; /* Set if already detached */
+ cma_t_boolean terminated; /* Set if terminated */
+ cma_t_integer joiners; /* Count of joiners, for zombie frees */
+ cma__t_int_alert alert; /* Current alert state info */
+ struct CMA__T_INT_CV
+ *wait_cv; /* CV thread is currently waiting on */
+ struct CMA__T_INT_MUTEX
+ *wait_mutex; /* Mutex thread is waiting on */
+ struct EXC_CONTEXT_T
+ *exc_stack; /* Top of exception stack */
+#if _CMA_PLATFORM_ == _CMA__IBMR2_UNIX
+ char ctx_stack[cma__c_ibmr2_ctx_stack_size];
+#endif
+ cma_t_integer thd_errno; /* Per-thread errno value */
+#if _CMA_OS_ == _CMA__VMS
+ cma_t_integer thd_vmserrno; /* Per-thread VMS errno value */
+#endif
+ } cma__t_int_tcb;
+
+#endif
diff --git a/gdb/osf-share/cma_util.h b/gdb/osf-share/cma_util.h
new file mode 100644
index 00000000000..00451c45a34
--- /dev/null
+++ b/gdb/osf-share/cma_util.h
@@ -0,0 +1,125 @@
+/*
+ * (c) Copyright 1990-1996 OPEN SOFTWARE FOUNDATION, INC.
+ * (c) Copyright 1990-1996 HEWLETT-PACKARD COMPANY
+ * (c) Copyright 1990-1996 DIGITAL EQUIPMENT CORPORATION
+ * (c) Copyright 1991, 1992 Siemens-Nixdorf Information Systems
+ * To anyone who acknowledges that this file is provided "AS IS" without
+ * any express or implied warranty: permission to use, copy, modify, and
+ * distribute this file for any purpose is hereby granted without fee,
+ * provided that the above copyright notices and this notice appears in
+ * all source code copies, and that none of the names listed above be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. None of these organizations
+ * makes any representations about the suitability of this software for
+ * any purpose.
+ */
+/*
+ * Header file for CMA internal UTIL operations
+ */
+
+#ifndef CMA_UTIL
+#define CMA_UTIL
+
+/*
+ * INCLUDE FILES
+ */
+
+#include <cma.h>
+#include <cma_attr.h>
+#include <cma_defs.h>
+
+#if _CMA_OS_ == _CMA__VMS
+# include <cma_rms.h>
+#endif
+
+#if _CMA_VENDOR_ == _CMA__SUN
+# include <sys/time.h>
+#else
+# include <time.h>
+#endif
+
+#if _CMA_OS_ == _CMA__UNIX
+# include <stdio.h>
+#endif
+
+/*
+ * CONSTANTS AND MACROS
+ */
+
+#define cma__c_buffer_size 256 /* Size of output buffer */
+
+/*
+ * TYPEDEFS
+ */
+
+/*
+ * Alternate eol routine
+ */
+typedef void (*cma__t_eol_routine) (char *);
+
+#if _CMA_OS_ == _CMA__VMS
+ typedef struct CMA__T_VMSFILE {
+ struct RAB rab;
+ struct FAB fab;
+ } cma__t_vmsfile, *cma__t_file;
+#elif ( _CMA_UNIX_TYPE == _CMA__SVR4 )
+ typedef int cma__t_file;
+#else
+ typedef FILE *cma__t_file;
+#endif
+
+/*
+ * GLOBAL DATA
+ */
+
+/*
+ * INTERNAL INTERFACES
+ */
+
+extern void cma__abort (void);
+
+extern cma_t_integer cma__atol (char *);
+
+extern cma_t_integer cma__atoi (char *);
+
+extern char * cma__getenv (char *,char *,int);
+
+extern int cma__gettimespec (struct timespec *);
+
+extern cma__t_file cma__int_fopen (char *,char *);
+
+#ifndef NDEBUG
+extern void cma__init_trace (char *_env);
+#endif
+
+extern char * cma__memcpy (char *,char *,cma_t_integer);
+
+#ifndef cma__memset
+extern char * cma__memset (char *,cma_t_integer,cma_t_integer);
+#endif
+
+extern void cma__putformat (char *,char *,...);
+
+extern void cma__putstring (char *,char *);
+
+extern void cma__putint (char *,cma_t_integer);
+
+extern void cma__putint_5 (char *,cma_t_integer);
+
+extern void cma__putint_10 (char *,cma_t_integer);
+
+extern void cma__puthex (char *,cma_t_integer);
+
+extern void cma__puthex_8 (char *,cma_t_integer);
+
+extern void cma__puteol (char *);
+
+extern void cma__set_eol_routine (cma__t_eol_routine,cma__t_eol_routine *);
+
+extern cma_t_integer cma__strlen (char *);
+
+extern int cma__strncmp (char *,char *,cma_t_integer);
+
+extern char *cma__gets (char *,char *);
+
+#endif
diff --git a/gdb/osfsolib.c b/gdb/osfsolib.c
new file mode 100644
index 00000000000..31c9bf99893
--- /dev/null
+++ b/gdb/osfsolib.c
@@ -0,0 +1,980 @@
+/* Handle OSF/1 shared libraries for GDB, the GNU Debugger.
+ Copyright 1993, 94, 95, 96, 98, 1999 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* FIXME: Most of this code could be merged with solib.c by using
+ next_link_map_member and xfer_link_map_member in solib.c. */
+
+#include "defs.h"
+
+#include <sys/types.h>
+#include <signal.h>
+#include "gdb_string.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 "gnu-regex.h"
+#include "inferior.h"
+#include "language.h"
+#include "gdbcmd.h"
+
+#define MAX_PATH_SIZE 1024 /* FIXME: Should be dynamic */
+
+/* When handling shared libraries, GDB has to find out the pathnames
+ of all shared libraries that are currently loaded (to read in their
+ symbols) and where the shared libraries are loaded in memory
+ (to relocate them properly from their prelinked addresses to the
+ current load address).
+
+ Under OSF/1 there are two possibilities to get at this information:
+ 1) Peek around in the runtime loader structures.
+ These are not documented, and they are not defined in the system
+ header files. The definitions below were obtained by experimentation,
+ but they seem stable enough.
+ 2) Use the undocumented libxproc.a library, which contains the
+ equivalent ldr_* routines.
+ This approach is somewhat cleaner, but it requires that the GDB
+ executable is dynamically linked. In addition it requires a
+ NAT_CLIBS= -lxproc -Wl,-expect_unresolved,ldr_process_context
+ linker specification for GDB and all applications that are using
+ libgdb.
+ We will use the peeking approach until it becomes unwieldy. */
+
+#ifndef USE_LDR_ROUTINES
+
+/* Definition of runtime loader structures, found by experimentation. */
+#define RLD_CONTEXT_ADDRESS 0x3ffc0000000
+
+typedef struct
+{
+ CORE_ADDR next;
+ CORE_ADDR previous;
+ CORE_ADDR unknown1;
+ char *module_name;
+ CORE_ADDR modinfo_addr;
+ long module_id;
+ CORE_ADDR unknown2;
+ CORE_ADDR unknown3;
+ long region_count;
+ CORE_ADDR regioninfo_addr;
+} ldr_module_info_t;
+
+typedef struct
+{
+ long unknown1;
+ CORE_ADDR regionname_addr;
+ long protection;
+ CORE_ADDR vaddr;
+ CORE_ADDR mapaddr;
+ long size;
+ long unknown2[5];
+} ldr_region_info_t;
+
+typedef struct
+{
+ CORE_ADDR unknown1;
+ CORE_ADDR unknown2;
+ CORE_ADDR head;
+ CORE_ADDR tail;
+} ldr_context_t;
+
+static ldr_context_t ldr_context;
+
+#else
+
+#include <loader.h>
+static ldr_process_t fake_ldr_process;
+
+/* Called by ldr_* routines to read memory from the current target. */
+
+static int ldr_read_memory PARAMS ((CORE_ADDR, char *, int, int));
+
+static int
+ldr_read_memory (memaddr, myaddr, len, readstring)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+ int readstring;
+{
+ int result;
+ char *buffer;
+
+ if (readstring)
+ {
+ target_read_string (memaddr, &buffer, len, &result);
+ if (result == 0)
+ strcpy (myaddr, buffer);
+ free (buffer);
+ }
+ else
+ result = target_read_memory (memaddr, myaddr, len);
+
+ if (result != 0)
+ result = -result;
+ return result;
+}
+
+#endif
+
+/* Define our own link_map structure.
+ This will help to share code with solib.c. */
+
+struct link_map {
+ CORE_ADDR l_offset; /* prelink to load address offset */
+ char *l_name; /* full name of loaded object */
+ ldr_module_info_t module_info; /* corresponding module info */
+};
+
+#define LM_OFFSET(so) ((so) -> lm.l_offset)
+#define LM_NAME(so) ((so) -> lm.l_name)
+
+struct so_list {
+ struct so_list *next; /* next structure in linked list */
+ struct link_map lm; /* copy of link map from inferior */
+ struct link_map *lmaddr; /* addr in inferior lm was read from */
+ 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 */
+
+extern int
+fdmatch PARAMS ((int, int)); /* In libiberty */
+
+/* Local function prototypes */
+
+static void
+sharedlibrary_command PARAMS ((char *, int));
+
+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 *));
+
+static struct link_map *
+first_link_map_member PARAMS ((void));
+
+static struct link_map *
+next_link_map_member PARAMS ((struct so_list *));
+
+static void
+xfer_link_map_member PARAMS ((struct so_list *, struct link_map *));
+
+static int
+solib_map_sections PARAMS ((char *));
+
+/*
+
+LOCAL FUNCTION
+
+ solib_map_sections -- open bfd and build sections for shared lib
+
+SYNOPSIS
+
+ static int 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 int
+solib_map_sections (arg)
+ char *arg;
+{
+ struct so_list *so = (struct so_list *) arg; /* catch_errors bogon */
+ 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. bfd->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_get_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_get_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_get_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 offset to get the address to which the
+ object was actually mapped. */
+ p -> addr += LM_OFFSET (so);
+ p -> endaddr += LM_OFFSET (so);
+ so -> lmend = (CORE_ADDR) max (p -> endaddr, so -> lmend);
+ if (STREQ (p -> the_bfd_section -> name, ".text"))
+ {
+ so -> textsection = p;
+ }
+ }
+
+ /* Free the file names, close the file now. */
+ do_cleanups (old_chain);
+
+ return (1);
+}
+
+/*
+
+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.
+*/
+
+static struct link_map *
+first_link_map_member ()
+{
+ struct link_map *lm = NULL;
+ static struct link_map first_lm;
+
+#ifdef USE_LDR_ROUTINES
+ ldr_module_t mod_id = LDR_NULL_MODULE;
+ size_t retsize;
+
+ fake_ldr_process = ldr_core_process ();
+ ldr_set_core_reader (ldr_read_memory);
+ ldr_xdetach (fake_ldr_process);
+ if (ldr_xattach (fake_ldr_process) != 0
+ || ldr_next_module(fake_ldr_process, &mod_id) != 0
+ || mod_id == LDR_NULL_MODULE
+ || ldr_inq_module(fake_ldr_process, mod_id,
+ &first_lm.module_info, sizeof(ldr_module_info_t),
+ &retsize) != 0)
+ return lm;
+#else
+ CORE_ADDR ldr_context_addr;
+
+ if (target_read_memory ((CORE_ADDR) RLD_CONTEXT_ADDRESS,
+ (char *) &ldr_context_addr,
+ sizeof (CORE_ADDR)) != 0
+ || target_read_memory (ldr_context_addr,
+ (char *) &ldr_context,
+ sizeof (ldr_context_t)) != 0
+ || target_read_memory ((CORE_ADDR) ldr_context.head,
+ (char *) &first_lm.module_info,
+ sizeof (ldr_module_info_t)) != 0)
+ return lm;
+#endif
+
+ lm = &first_lm;
+
+ /* The first entry is for the main program and should be skipped. */
+ lm->l_name = NULL;
+
+ return lm;
+}
+
+static struct link_map *
+next_link_map_member (so_list_ptr)
+ struct so_list *so_list_ptr;
+{
+ struct link_map *lm = NULL;
+ static struct link_map next_lm;
+#ifdef USE_LDR_ROUTINES
+ ldr_module_t mod_id = so_list_ptr->lm.module_info.lmi_modid;
+ size_t retsize;
+
+ if (ldr_next_module(fake_ldr_process, &mod_id) != 0
+ || mod_id == LDR_NULL_MODULE
+ || ldr_inq_module(fake_ldr_process, mod_id,
+ &next_lm.module_info, sizeof(ldr_module_info_t),
+ &retsize) != 0)
+ return lm;
+
+ lm = &next_lm;
+ lm->l_name = lm->module_info.lmi_name;
+#else
+ CORE_ADDR ldr_context_addr;
+
+ /* Reread context in case ldr_context.tail was updated. */
+
+ if (target_read_memory ((CORE_ADDR) RLD_CONTEXT_ADDRESS,
+ (char *) &ldr_context_addr,
+ sizeof (CORE_ADDR)) != 0
+ || target_read_memory (ldr_context_addr,
+ (char *) &ldr_context,
+ sizeof (ldr_context_t)) != 0
+ || so_list_ptr->lm.module_info.modinfo_addr == ldr_context.tail
+ || target_read_memory (so_list_ptr->lm.module_info.next,
+ (char *) &next_lm.module_info,
+ sizeof (ldr_module_info_t)) != 0)
+ return lm;
+
+ lm = &next_lm;
+ lm->l_name = lm->module_info.module_name;
+#endif
+ return lm;
+}
+
+static void
+xfer_link_map_member (so_list_ptr, lm)
+ struct so_list *so_list_ptr;
+ struct link_map *lm;
+{
+ int i;
+ so_list_ptr->lm = *lm;
+
+ /* OSF/1 shared libraries are pre-linked to particular addresses,
+ but the runtime loader may have to relocate them if the
+ address ranges of the libraries used by the target executable clash,
+ or if the target executable is linked with the -taso option.
+ The offset is the difference between the address where the shared
+ library is mapped and the pre-linked address of the shared library.
+
+ FIXME: GDB is currently unable to relocate the shared library
+ sections by different offsets. If sections are relocated by
+ different offsets, put out a warning and use the offset of the
+ first section for all remaining sections. */
+ LM_OFFSET (so_list_ptr) = 0;
+
+ /* There is one entry that has no name (for the inferior executable)
+ since it is not a shared object. */
+ if (LM_NAME (so_list_ptr) != 0)
+ {
+
+#ifdef USE_LDR_ROUTINES
+ int len = strlen (LM_NAME (so_list_ptr) + 1);
+
+ if (len > MAX_PATH_SIZE)
+ len = MAX_PATH_SIZE;
+ strncpy (so_list_ptr->so_name, LM_NAME (so_list_ptr), MAX_PATH_SIZE);
+ so_list_ptr->so_name[MAX_PATH_SIZE - 1] = '\0';
+
+ for (i = 0; i < lm->module_info.lmi_nregion; i++)
+ {
+ ldr_region_info_t region_info;
+ size_t retsize;
+ CORE_ADDR region_offset;
+
+ if (ldr_inq_region (fake_ldr_process, lm->module_info.lmi_modid,
+ i, &region_info, sizeof (region_info),
+ &retsize) != 0)
+ break;
+ region_offset = (CORE_ADDR) region_info.lri_mapaddr
+ - (CORE_ADDR) region_info.lri_vaddr;
+ if (i == 0)
+ LM_OFFSET (so_list_ptr) = region_offset;
+ else if (LM_OFFSET (so_list_ptr) != region_offset)
+ warning ("cannot handle shared library relocation for %s (%s)",
+ so_list_ptr->so_name, region_info.lri_name);
+ }
+#else
+ int errcode;
+ char *buffer;
+ target_read_string ((CORE_ADDR) LM_NAME (so_list_ptr), &buffer,
+ MAX_PATH_SIZE - 1, &errcode);
+ if (errcode != 0)
+ error ("xfer_link_map_member: Can't read pathname for load map: %s\n",
+ safe_strerror (errcode));
+ strncpy (so_list_ptr->so_name, buffer, MAX_PATH_SIZE - 1);
+ free (buffer);
+ so_list_ptr->so_name[MAX_PATH_SIZE - 1] = '\0';
+
+ for (i = 0; i < lm->module_info.region_count; i++)
+ {
+ ldr_region_info_t region_info;
+ CORE_ADDR region_offset;
+
+ if (target_read_memory (lm->module_info.regioninfo_addr
+ + i * sizeof (region_info),
+ (char *) &region_info,
+ sizeof (region_info)) != 0)
+ break;
+ region_offset = region_info.mapaddr - region_info.vaddr;
+ if (i == 0)
+ LM_OFFSET (so_list_ptr) = region_offset;
+ else if (LM_OFFSET (so_list_ptr) != region_offset)
+ {
+ char *region_name;
+ target_read_string (region_info.regionname_addr, &buffer,
+ MAX_PATH_SIZE - 1, &errcode);
+ if (errcode == 0)
+ region_name = buffer;
+ else
+ region_name = "??";
+ warning ("cannot handle shared library relocation for %s (%s)",
+ so_list_ptr->so_name, region_name);
+ free (buffer);
+ }
+ }
+#endif
+
+ catch_errors (solib_map_sections, (char *) so_list_ptr,
+ "Error while mapping shared library sections:\n",
+ RETURN_MASK_ALL);
+ }
+}
+
+/*
+
+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;
+ struct link_map *lm = NULL;
+ 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)
+ {
+ /* Find 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. */
+ lm = next_link_map_member (so_list_ptr);
+ 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;
+ xfer_link_map_member (new, lm);
+ }
+ 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 */
+ CORE_ADDR text_addr = 0;
+
+ if (so -> textsection)
+ text_addr = so -> textsection -> addr;
+ else if (so -> abfd != NULL)
+ {
+ asection *lowest_sect;
+
+ /* If we didn't find a mapped non zero sized .text section, set up
+ text_addr so that the relocation in symbol_file_add does no harm. */
+
+ lowest_sect = bfd_get_section_by_name (so -> abfd, ".text");
+ if (lowest_sect == NULL)
+ bfd_map_over_sections (so -> abfd, find_lowest_section,
+ (PTR) &lowest_sect);
+ if (lowest_sect)
+ text_addr = bfd_section_vma (so -> abfd, lowest_sect) + LM_OFFSET (so);
+ }
+
+ so -> objfile = symbol_file_add (so -> so_name, so -> from_tty,
+ text_addr,
+ 0, 0, 0, 0, 1);
+ 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);
+ }
+
+
+ /* 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)
+ {
+ int update_coreops;
+
+ /* We must update the to_sections field in the core_ops structure
+ here, otherwise we dereference a potential dangling pointer
+ for each call to target_read/write_memory within this routine. */
+ update_coreops = core_ops.to_sections == target->to_sections;
+
+ /* 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);
+
+ /* Update the to_sections field in the core_ops structure
+ if needed. */
+ if (update_coreops)
+ {
+ core_ops.to_sections = target->to_sections;
+ core_ops.to_sections_end = target->to_sections_end;
+ }
+
+ /* 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;
+ }
+ }
+ }
+ }
+
+ /* Now add the symbol files. */
+ so = NULL;
+ 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_unfiltered ("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;
+ }
+ }
+ }
+
+ /* Getting new symbols may change our opinion about what is
+ frameless. */
+ if (so_last)
+ reinit_frame_cache ();
+}
+
+/*
+
+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_unfiltered ("No exec file.\n");
+ return;
+ }
+ while ((so = find_solib (so)) != NULL)
+ {
+ if (so -> so_name[0])
+ {
+ unsigned long txt_start = 0;
+ unsigned long txt_end = 0;
+
+ if (!header_done)
+ {
+ printf_unfiltered("%-20s%-20s%-12s%s\n", "From", "To", "Syms Read",
+ "Shared Object Library");
+ header_done++;
+ }
+ if (so -> textsection)
+ {
+ txt_start = (unsigned long) so -> textsection -> addr;
+ txt_end = (unsigned long) so -> textsection -> endaddr;
+ }
+ printf_unfiltered ("%-20s", local_hex_string_custom (txt_start, "08l"));
+ printf_unfiltered ("%-20s", local_hex_string_custom (txt_end, "08l"));
+ printf_unfiltered ("%-12s", so -> symbols_loaded ? "Yes" : "No");
+ printf_unfiltered ("%s\n", so -> so_name);
+ }
+ }
+ if (so_list_head == NULL)
+ {
+ printf_unfiltered ("No shared libraries loaded at this time.\n");
+ }
+}
+
+/*
+
+GLOBAL FUNCTION
+
+ solib_address -- check to see if an address is in a shared lib
+
+SYNOPSIS
+
+ char *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.
+ */
+
+char *
+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] && so -> textsection)
+ {
+ if ((address >= (CORE_ADDR) so -> textsection -> addr) &&
+ (address < (CORE_ADDR) so -> textsection -> endaddr))
+ return (so->so_name);
+ }
+ }
+ return (0);
+}
+
+/* Called by free_all_symtabs */
+
+void
+clear_solib()
+{
+ struct so_list *next;
+ char *bfd_filename;
+
+ disable_breakpoints_in_shlibs (1);
+
+ 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);
+ if (!bfd_close (so_list_head -> abfd))
+ warning ("cannot close \"%s\": %s",
+ bfd_filename, bfd_errmsg (bfd_get_error ()));
+ }
+ 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;
+ }
+}
+
+/*
+
+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 a statically bound executable, this first instruction is the
+ one at "_start", or a similar text label. No further processing is
+ needed in that case.
+ For a dynamically bound executable, this first instruction is somewhere
+ in the rld, and the actual user executable is not yet mapped in.
+ We continue the inferior again, rld then maps in the actual user
+ executable and any needed shared libraries and then sends
+ itself a SIGTRAP.
+ At that point we discover the names of all shared libraries and
+ read their symbols in.
+
+FIXME
+
+ This code does not properly handle hitting breakpoints which the
+ user might have set in the rld itself. Proper handling would have
+ to check if the SIGTRAP happened due to a kill call.
+
+ Also, what if child has exit()ed? Must exit loop somehow.
+ */
+
+void
+solib_create_inferior_hook()
+{
+
+ /* Nothing to do for statically bound executables. */
+
+ if (symfile_objfile == NULL
+ || symfile_objfile->obfd == NULL
+ || ((bfd_get_file_flags (symfile_objfile->obfd) & DYNAMIC) == 0))
+ return;
+
+ /* Now run the target. It will eventually get a SIGTRAP, at
+ which point all of the libraries will have been mapped in and we
+ can go groveling around in the rld structures to find
+ out what we need to know about them. */
+
+ clear_proceed_status ();
+ stop_soon_quietly = 1;
+ stop_signal = TARGET_SIGNAL_0;
+ do
+ {
+ target_resume (-1, 0, stop_signal);
+ wait_for_inferior ();
+ }
+ while (stop_signal != TARGET_SIGNAL_TRAP);
+
+ /* solib_add will call reinit_frame_cache.
+ But we are stopped in the runtime loader and we do not have symbols
+ for the runtime loader. So heuristic_proc_start will be called
+ and will put out an annoying warning.
+ Delaying the resetting of stop_soon_quietly until after symbol loading
+ suppresses the warning. */
+ if (auto_solib_add)
+ solib_add ((char *) 0, 0, (struct target_ops *) 0);
+ stop_soon_quietly = 0;
+}
+
+
+/*
+
+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.");
+
+ add_show_from_set
+ (add_set_cmd ("auto-solib-add", class_support, var_zinteger,
+ (char *) &auto_solib_add,
+ "Set autoloading of shared library symbols.\n\
+If nonzero, symbols from all shared object libraries will be loaded\n\
+automatically when the inferior begins execution or when the dynamic linker\n\
+informs gdb that a new library has been loaded. Otherwise, symbols\n\
+must be loaded manually, using `sharedlibrary'.",
+ &setlist),
+ &showlist);
+}
diff --git a/gdb/parse.c b/gdb/parse.c
new file mode 100644
index 00000000000..af68fbfbcd2
--- /dev/null
+++ b/gdb/parse.c
@@ -0,0 +1,1351 @@
+/* Parse expressions for GDB.
+ Copyright (C) 1986, 89, 90, 91, 94, 1998 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 "gdb_string.h"
+#include <ctype.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"
+#include "gdbcmd.h"
+#include "symfile.h" /* for overlay functions */
+
+/* Global variables declared in parser-defs.h (and commented there). */
+struct expression *expout;
+int expout_size;
+int expout_ptr;
+struct block *expression_context_block;
+struct block *innermost_block;
+int arglist_len;
+union type_stack_elt *type_stack;
+int type_stack_depth, type_stack_size;
+char *lexptr;
+char *namecopy;
+int paren_depth;
+int comma_terminates;
+
+#ifdef MAINTENANCE_CMDS
+static int expressiondebug = 0;
+#endif
+
+extern int hp_som_som_object_present;
+
+static void
+free_funcalls PARAMS ((void));
+
+static void
+prefixify_expression PARAMS ((struct expression *));
+
+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
+
+/* The generic method for targets to specify how their registers are
+ named. The mapping can be derived from three sources:
+ REGISTER_NAME; std_regs; or a target specific alias hook. */
+
+int
+target_map_name_to_register (str, len)
+ char *str;
+ int len;
+{
+ int i;
+
+ /* First try target specific aliases. We try these first because on some
+ systems standard names can be context dependent (eg. $pc on a
+ multiprocessor can be could be any of several PCs). */
+#ifdef REGISTER_NAME_ALIAS_HOOK
+ i = REGISTER_NAME_ALIAS_HOOK (str, len);
+ if (i >= 0)
+ return i;
+#endif
+
+ /* Search architectural register name space. */
+ for (i = 0; i < NUM_REGS; i++)
+ if (REGISTER_NAME (i) && len == strlen (REGISTER_NAME (i))
+ && STREQN (str, REGISTER_NAME (i), len))
+ {
+ return i;
+ }
+
+ /* Try standard aliases */
+ for (i = 0; i < num_std_regs; i++)
+ if (std_regs[i].name && len == strlen (std_regs[i].name)
+ && STREQN (str, std_regs[i].name, len))
+ {
+ return std_regs[i].regnum;
+ }
+
+ return -1;
+}
+
+/* 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)
+ DOUBLEST 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);
+}
+
+/* Add the appropriate elements for a minimal symbol to the end of
+ the expression. The rationale behind passing in text_symbol_type and
+ data_symbol_type was so that Modula-2 could pass in WORD for
+ data_symbol_type. Perhaps it still is useful to have those types vary
+ based on the language, but they no longer have names like "int", so
+ the initial rationale is gone. */
+
+static struct type *msym_text_symbol_type;
+static struct type *msym_data_symbol_type;
+static struct type *msym_unknown_symbol_type;
+
+void
+write_exp_msymbol (msymbol, text_symbol_type, data_symbol_type)
+ struct minimal_symbol *msymbol;
+ struct type *text_symbol_type;
+ struct type *data_symbol_type;
+{
+ CORE_ADDR addr;
+
+ write_exp_elt_opcode (OP_LONG);
+ write_exp_elt_type (lookup_pointer_type (builtin_type_void));
+
+ addr = SYMBOL_VALUE_ADDRESS (msymbol);
+ if (overlay_debugging)
+ addr = symbol_overlayed_address (addr, SYMBOL_BFD_SECTION (msymbol));
+ write_exp_elt_longcst ((LONGEST) addr);
+
+ write_exp_elt_opcode (OP_LONG);
+
+ write_exp_elt_opcode (UNOP_MEMVAL);
+ switch (msymbol -> type)
+ {
+ case mst_text:
+ case mst_file_text:
+ case mst_solib_trampoline:
+ write_exp_elt_type (msym_text_symbol_type);
+ break;
+
+ case mst_data:
+ case mst_file_data:
+ case mst_bss:
+ case mst_file_bss:
+ write_exp_elt_type (msym_data_symbol_type);
+ break;
+
+ default:
+ write_exp_elt_type (msym_unknown_symbol_type);
+ break;
+ }
+ write_exp_elt_opcode (UNOP_MEMVAL);
+}
+
+/* Recognize tokens that start with '$'. These include:
+
+ $regname A native register name or a "standard
+ register name".
+
+ $variable A convenience variable with a name chosen
+ by the user.
+
+ $digits Value history with index <digits>, starting
+ from the first value which has index 1.
+
+ $$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.
+
+ $ | $0 | $$0 The last value in the value history.
+
+ $$ An abbreviation for the second to the last
+ value in the value history, I.E. $$1
+
+ */
+
+void
+write_dollar_variable (str)
+ struct stoken str;
+{
+ /* Handle the tokens $digits; also $ (short for $0) and $$ (short for $$1)
+ and $$digits (equivalent to $<-digits> if you could type that). */
+
+ struct symbol * sym = NULL;
+ struct minimal_symbol * msym = NULL;
+
+ int negate = 0;
+ int i = 1;
+ /* Double dollar means negate the number and add -1 as well.
+ Thus $$ alone means -1. */
+ if (str.length >= 2 && str.ptr[1] == '$')
+ {
+ negate = 1;
+ i = 2;
+ }
+ if (i == str.length)
+ {
+ /* Just dollars (one or two) */
+ i = - negate;
+ goto handle_last;
+ }
+ /* Is the rest of the token digits? */
+ for (; i < str.length; i++)
+ if (!(str.ptr[i] >= '0' && str.ptr[i] <= '9'))
+ break;
+ if (i == str.length)
+ {
+ i = atoi (str.ptr + 1 + negate);
+ if (negate)
+ i = - i;
+ goto handle_last;
+ }
+
+ /* Handle tokens that refer to machine registers:
+ $ followed by a register name. */
+ i = target_map_name_to_register( str.ptr + 1, str.length - 1 );
+ if( i >= 0 )
+ goto handle_register;
+
+ /* On HP-UX, certain system routines (millicode) have names beginning
+ with $ or $$, e.g. $$dyncall, which handles inter-space procedure
+ calls on PA-RISC. Check for those, first. */
+
+ sym = lookup_symbol (copy_name (str), (struct block *) NULL,
+ VAR_NAMESPACE, (int *) NULL, (struct symtab **) NULL);
+ if (sym)
+ {
+ write_exp_elt_opcode (OP_VAR_VALUE);
+ write_exp_elt_block (block_found); /* set by lookup_symbol */
+ write_exp_elt_sym (sym);
+ write_exp_elt_opcode (OP_VAR_VALUE);
+ return;
+ }
+ msym = lookup_minimal_symbol (copy_name (str), NULL, NULL);
+ if (msym)
+ {
+ write_exp_msymbol (msym,
+ lookup_function_type (builtin_type_int),
+ builtin_type_int);
+ return;
+ }
+
+ /* Any other names starting in $ are debugger internal variables. */
+
+ write_exp_elt_opcode (OP_INTERNALVAR);
+ write_exp_elt_intern (lookup_internalvar (copy_name (str) + 1));
+ write_exp_elt_opcode (OP_INTERNALVAR);
+ return;
+ handle_last:
+ write_exp_elt_opcode (OP_LAST);
+ write_exp_elt_longcst ((LONGEST) i);
+ write_exp_elt_opcode (OP_LAST);
+ return;
+ handle_register:
+ write_exp_elt_opcode (OP_REGISTER);
+ write_exp_elt_longcst (i);
+ write_exp_elt_opcode (OP_REGISTER);
+ return;
+}
+
+
+/* Parse a string that is possibly a namespace / nested class
+ specification, i.e., something of the form A::B::C::x. Input
+ (NAME) is the entire string; LEN is the current valid length; the
+ output is a string, TOKEN, which points to the largest recognized
+ prefix which is a series of namespaces or classes. CLASS_PREFIX is
+ another output, which records whether a nested class spec was
+ recognized (= 1) or a fully qualified variable name was found (=
+ 0). ARGPTR is side-effected (if non-NULL) to point to beyond the
+ string recognized and consumed by this routine.
+
+ The return value is a pointer to the symbol for the base class or
+ variable if found, or NULL if not found. Callers must check this
+ first -- if NULL, the outputs may not be correct.
+
+ This function is used c-exp.y. This is used specifically to get
+ around HP aCC (and possibly other compilers), which insists on
+ generating names with embedded colons for namespace or nested class
+ members.
+
+ (Argument LEN is currently unused. 1997-08-27)
+
+ Callers must free memory allocated for the output string TOKEN. */
+
+static const char coloncolon[2] = {':',':'};
+
+struct symbol *
+parse_nested_classes_for_hpacc (name, len, token, class_prefix, argptr)
+ char * name;
+ int len;
+ char ** token;
+ int * class_prefix;
+ char ** argptr;
+{
+ /* Comment below comes from decode_line_1 which has very similar
+ code, which is called for "break" command parsing. */
+
+ /* We have what looks like a class or namespace
+ scope specification (A::B), possibly with many
+ levels of namespaces or classes (A::B::C::D).
+
+ Some versions of the HP ANSI C++ compiler (as also possibly
+ other compilers) generate class/function/member names with
+ embedded double-colons if they are inside namespaces. To
+ handle this, we loop a few times, considering larger and
+ larger prefixes of the string as though they were single
+ symbols. So, if the initially supplied string is
+ A::B::C::D::foo, we have to look up "A", then "A::B",
+ then "A::B::C", then "A::B::C::D", and finally
+ "A::B::C::D::foo" as single, monolithic symbols, because
+ A, B, C or D may be namespaces.
+
+ Note that namespaces can nest only inside other
+ namespaces, and not inside classes. So we need only
+ consider *prefixes* of the string; there is no need to look up
+ "B::C" separately as a symbol in the previous example. */
+
+ register char * p;
+ char * start, * end;
+ char * prefix = NULL;
+ char * tmp;
+ struct symbol * sym_class = NULL;
+ struct symbol * sym_var = NULL;
+ struct type * t;
+ register int i;
+ int colons_found = 0;
+ int prefix_len = 0;
+ int done = 0;
+ char * q;
+
+ /* Check for HP-compiled executable -- in other cases
+ return NULL, and caller must default to standard GDB
+ behaviour. */
+
+ if (!hp_som_som_object_present)
+ return (struct symbol *) NULL;
+
+ p = name;
+
+ /* Skip over whitespace and possible global "::" */
+ while (*p && (*p == ' ' || *p == '\t')) p++;
+ if (p[0] == ':' && p[1] == ':')
+ p += 2;
+ while (*p && (*p == ' ' || *p == '\t')) p++;
+
+ while (1)
+ {
+ /* Get to the end of the next namespace or class spec. */
+ /* If we're looking at some non-token, fail immediately */
+ start = p;
+ if (!(isalpha (*p) || *p == '$' || *p == '_'))
+ return (struct symbol *) NULL;
+ p++;
+ while (*p && (isalnum (*p) || *p == '$' || *p == '_')) p++;
+
+ if (*p == '<')
+ {
+ /* If we have the start of a template specification,
+ scan right ahead to its end */
+ q = find_template_name_end (p);
+ if (q)
+ p = q;
+ }
+
+ end = p;
+
+ /* Skip over "::" and whitespace for next time around */
+ while (*p && (*p == ' ' || *p == '\t')) p++;
+ if (p[0] == ':' && p[1] == ':')
+ p += 2;
+ while (*p && (*p == ' ' || *p == '\t')) p++;
+
+ /* Done with tokens? */
+ if (!*p || !(isalpha (*p) || *p == '$' || *p == '_'))
+ done = 1;
+
+ tmp = (char *) alloca (prefix_len + end - start + 3);
+ if (prefix)
+ {
+ memcpy (tmp, prefix, prefix_len);
+ memcpy (tmp + prefix_len, coloncolon, 2);
+ memcpy (tmp + prefix_len + 2, start, end - start);
+ tmp[prefix_len + 2 + end - start] = '\000';
+ }
+ else
+ {
+ memcpy (tmp, start, end - start);
+ tmp[end - start] = '\000';
+ }
+
+ prefix = tmp;
+ prefix_len = strlen (prefix);
+
+#if 0 /* DEBUGGING */
+ printf ("Searching for nested class spec: Prefix is %s\n", prefix);
+#endif
+
+ /* See if the prefix we have now is something we know about */
+
+ if (!done)
+ {
+ /* More tokens to process, so this must be a class/namespace */
+ sym_class = lookup_symbol (prefix, 0, STRUCT_NAMESPACE,
+ 0, (struct symtab **) NULL);
+ }
+ else
+ {
+ /* No more tokens, so try as a variable first */
+ sym_var = lookup_symbol (prefix, 0, VAR_NAMESPACE,
+ 0, (struct symtab **) NULL);
+ /* If failed, try as class/namespace */
+ if (!sym_var)
+ sym_class = lookup_symbol (prefix, 0, STRUCT_NAMESPACE,
+ 0, (struct symtab **) NULL);
+ }
+
+ if (sym_var ||
+ (sym_class &&
+ (t = check_typedef (SYMBOL_TYPE (sym_class)),
+ (TYPE_CODE (t) == TYPE_CODE_STRUCT
+ || TYPE_CODE (t) == TYPE_CODE_UNION))))
+ {
+ /* We found a valid token */
+ *token = (char *) xmalloc (prefix_len + 1 );
+ memcpy (*token, prefix, prefix_len);
+ (*token)[prefix_len] = '\000';
+ break;
+ }
+
+ /* No variable or class/namespace found, no more tokens */
+ if (done)
+ return (struct symbol *) NULL;
+ }
+
+ /* Out of loop, so we must have found a valid token */
+ if (sym_var)
+ *class_prefix = 0;
+ else
+ *class_prefix = 1;
+
+ if (argptr)
+ *argptr = done ? p : end;
+
+#if 0 /* DEBUGGING */
+ printf ("Searching for nested class spec: Token is %s, class_prefix %d\n", *token, *class_prefix);
+#endif
+
+ return sym_var ? sym_var : sym_class; /* found */
+}
+
+char *
+find_template_name_end (p)
+ char * p;
+{
+ int depth = 1;
+ int just_seen_right = 0;
+ int just_seen_colon = 0;
+ int just_seen_space = 0;
+
+ if (!p || (*p != '<'))
+ return 0;
+
+ while (*++p)
+ {
+ switch (*p)
+ {
+ case '\'': case '\"':
+ case '{': case '}':
+ /* In future, may want to allow these?? */
+ return 0;
+ case '<':
+ depth++; /* start nested template */
+ if (just_seen_colon || just_seen_right || just_seen_space)
+ return 0; /* but not after : or :: or > or space */
+ break;
+ case '>':
+ if (just_seen_colon || just_seen_right)
+ return 0; /* end a (nested?) template */
+ just_seen_right = 1; /* but not after : or :: */
+ if (--depth == 0) /* also disallow >>, insist on > > */
+ return ++p; /* if outermost ended, return */
+ break;
+ case ':':
+ if (just_seen_space || (just_seen_colon > 1))
+ return 0; /* nested class spec coming up */
+ just_seen_colon++; /* we allow :: but not :::: */
+ break;
+ case ' ':
+ break;
+ default:
+ if (!((*p >= 'a' && *p <= 'z') || /* allow token chars */
+ (*p >= 'A' && *p <= 'Z') ||
+ (*p >= '0' && *p <= '9') ||
+ (*p == '_') || (*p == ',') || /* commas for template args */
+ (*p == '&') || (*p == '*') || /* pointer and ref types */
+ (*p == '(') || (*p == ')') || /* function types */
+ (*p == '[') || (*p == ']') )) /* array types */
+ return 0;
+ }
+ if (*p != ' ')
+ just_seen_space = 0;
+ if (*p != ':')
+ just_seen_colon = 0;
+ if (*p != '>')
+ just_seen_right = 0;
+ }
+ return 0;
+}
+
+
+
+/* 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. */
+
+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_COMPLEX:
+ oplen = 1;
+ args = 2;
+ break;
+
+ case OP_FUNCALL:
+ case OP_F77_UNDETERMINED_ARGLIST:
+ 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 OP_LABELED:
+ case STRUCTOP_STRUCT:
+ case STRUCTOP_PTR:
+ args = 1;
+ /* fall through */
+ case OP_M2_STRING:
+ case OP_STRING:
+ case OP_NAME:
+ case OP_EXPRSTRING:
+ 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:
+ case TERNOP_SLICE:
+ case TERNOP_SLICE_COUNT:
+ 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_COMPLEX:
+ oplen = 1;
+ args = 2;
+ break;
+
+ case OP_FUNCALL:
+ case OP_F77_UNDETERMINED_ARGLIST:
+ 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:
+ case OP_LABELED:
+ args = 1;
+ /* fall through */
+ case OP_M2_STRING:
+ case OP_STRING:
+ case OP_NAME:
+ case OP_EXPRSTRING:
+ 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:
+ case TERNOP_SLICE:
+ case TERNOP_SLICE_COUNT:
+ 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 ((make_cleanup_func) 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 ((make_cleanup_func) 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. */
+
+#ifdef MAINTENANCE_CMDS
+ if (expressiondebug)
+ dump_prefix_expression (expout, gdb_stdout,
+ "before conversion to prefix form");
+#endif /* MAINTENANCE_CMDS */
+
+ prefixify_expression (expout);
+
+#ifdef MAINTENANCE_CMDS
+ if (expressiondebug)
+ dump_postfix_expression (expout, gdb_stdout,
+ "after conversion to prefix form");
+#endif /* MAINTENANCE_CMDS */
+
+ *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 ();
+ /* FIXME-type-allocation: need a way to free this type when we are
+ done with it. */
+ range_type =
+ create_range_type ((struct type *) NULL,
+ builtin_type_int, 0,
+ array_size >= 0 ? array_size - 1 : 0);
+ follow_type =
+ create_array_type ((struct type *) NULL,
+ follow_type, range_type);
+ if (array_size < 0)
+ TYPE_ARRAY_UPPER_BOUND_TYPE(follow_type)
+ = BOUND_CANNOT_BE_DETERMINED;
+ break;
+ case tp_function:
+ /* FIXME-type-allocation: need a way to free this type when we are
+ done with it. */
+ 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));
+
+ msym_text_symbol_type =
+ init_type (TYPE_CODE_FUNC, 1, 0, "<text variable, no debug info>", NULL);
+ TYPE_TARGET_TYPE (msym_text_symbol_type) = builtin_type_int;
+ msym_data_symbol_type =
+ init_type (TYPE_CODE_INT, TARGET_INT_BIT / HOST_CHAR_BIT, 0,
+ "<data variable, no debug info>", NULL);
+ msym_unknown_symbol_type =
+ init_type (TYPE_CODE_INT, 1, 0,
+ "<variable (not text or data), no debug info>",
+ NULL);
+
+#ifdef MAINTENANCE_CMDS
+ add_show_from_set (
+ add_set_cmd ("expressiondebug", class_maintenance, var_zinteger,
+ (char *)&expressiondebug,
+ "Set expression debugging.\n\
+When non-zero, the internal representation of expressions will be printed.",
+ &setlist),
+ &showlist);
+#endif
+}
diff --git a/gdb/parser-defs.h b/gdb/parser-defs.h
new file mode 100644
index 00000000000..3226fdd8ad1
--- /dev/null
+++ b/gdb/parser-defs.h
@@ -0,0 +1,198 @@
+/* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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;
+
+extern struct expression *expout;
+extern int expout_size;
+extern int expout_ptr;
+
+/* If this is nonzero, this block is used as the lexical context
+ for symbol names. */
+
+extern struct block *expression_context_block;
+
+/* The innermost context required by the stack and register variables
+ we've encountered so far. */
+extern struct block *innermost_block;
+
+/* The block in which the most recently discovered symbol was found.
+ FIXME: Should be declared along with lookup_symbol in symtab.h; is not
+ related specifically to parsing. */
+extern struct block *block_found;
+
+/* Number of arguments seen so far in innermost function call. */
+extern 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;
+};
+extern union type_stack_elt *type_stack;
+extern 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 ((DOUBLEST));
+
+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 write_exp_elt_block PARAMS ((struct block *));
+
+extern void write_exp_msymbol PARAMS ((struct minimal_symbol *,
+ struct type *, struct type *));
+
+extern void write_dollar_variable PARAMS ((struct stoken str));
+
+extern struct symbol * parse_nested_classes_for_hpacc PARAMS ((char *, int, char **, int *, char **));
+
+extern char * find_template_name_end PARAMS ((char *));
+
+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 int
+length_of_subexp PARAMS ((struct expression *, int));
+
+extern struct type *follow_types PARAMS ((struct type *));
+
+/* During parsing of a C expression, the pointer to the next character
+ is in this variable. */
+
+extern 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. */
+
+extern char *namecopy;
+
+/* Current depth in parentheses within the expression. */
+
+extern int paren_depth;
+
+/* Nonzero means stop parsing on first comma (if not within parentheses). */
+
+extern 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, PREC_BUILTIN_FUNCTION };
+
+/* 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;
+
+ /* For a binary operator: 1 iff right associate.
+ For a unary operator: 1 iff postfix. */
+ int right_assoc;
+};
+
+#endif /* PARSER_DEFS_H */
diff --git a/gdb/partial-stab.h b/gdb/partial-stab.h
new file mode 100644
index 00000000000..d74c1c9ca5f
--- /dev/null
+++ b/gdb/partial-stab.h
@@ -0,0 +1,812 @@
+/* Shared code to pre-read a stab (dbx-style), when building a psymtab.
+ Copyright 1986, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 1998
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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.
+ namestring - variable pointing to the name of the stab.
+ section_offsets - variable pointing to the section offsets.
+ pst - the partial symbol table being built.
+
+ psymtab_include_list, includes_used, includes_allocated - list of include
+ file names (N_SOL) seen so far.
+ dependency_list, dependencies_used, dependencies_allocated - list of
+ N_EXCL stabs seen so far.
+
+ END_PSYMTAB -- end a partial symbol table.
+ START_PSYMTAB -- start a partial symbol table.
+ */
+
+/* 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] == '.'))
+ {
+ 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;
+ }
+ 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 > pst->texthigh
+ ? CUR_SYMBOL_VALUE : pst->texthigh,
+ dependency_list, dependencies_used, textlow_not_set);
+ 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 && CUR_SYMBOL_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 + CUR_SYMBOL_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;
+ int prev_textlow_not_set;
+
+ valu = CUR_SYMBOL_VALUE + ANOFFSET (section_offsets, SECT_OFF_TEXT);
+
+ prev_textlow_not_set = textlow_not_set;
+
+#ifdef SOFUN_ADDRESS_MAYBE_MISSING
+ /* A zero value is probably an indication for the SunPRO 3.0
+ compiler. end_psymtab explicitly tests for zero, so
+ don't relocate it. */
+
+ if (CUR_SYMBOL_VALUE == 0)
+ {
+ textlow_not_set = 1;
+ valu = 0;
+ }
+ else
+ textlow_not_set = 0;
+#else
+ textlow_not_set = 0;
+#endif
+ 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 > pst->texthigh ? valu : pst->texthigh,
+ dependency_list, dependencies_used,
+ prev_textlow_not_set);
+ 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();
+
+ /* Null name means end of .o file. Don't start a new one. */
+ if (*namestring == '\000')
+ continue;
+
+ /* 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
+ enum language tmp_language;
+ /* 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();
+
+ tmp_language = deduce_language_from_filename (namestring);
+
+ /* Only change the psymtab's language if we've learned
+ something useful (eg. tmp_language is not language_unknown).
+ In addition, to match what start_subfile does, never change
+ from C++ to C. */
+ if (tmp_language != language_unknown
+ && (tmp_language != language_c
+ || psymtab_language != language_cplus))
+ psymtab_language = tmp_language;
+
+ if (pst == NULL)
+ {
+ /* FIXME: we should not get here without a PST to work on.
+ Attempt to recover. */
+ complain (&unclaimed_bincl_complaint, namestring, symnum);
+ continue;
+ }
+ 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:
+ {
+ enum language tmp_language;
+ /* Mark down an include file in the current psymtab */
+
+ SET_NAMESTRING();
+
+ tmp_language = deduce_language_from_filename (namestring);
+
+ /* Only change the psymtab's language if we've learned
+ something useful (eg. tmp_language is not language_unknown).
+ In addition, to match what start_subfile does, never change
+ from C++ to C. */
+ if (tmp_language != language_unknown
+ && (tmp_language != language_c
+ || psymtab_language != language_cplus))
+ psymtab_language = tmp_language;
+
+ /* 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();
+
+#ifdef DBXREAD_ONLY
+ /* See if this is an end of function stab. */
+ if (CUR_SYMBOL_TYPE == N_FUN && *namestring == '\000')
+ {
+ unsigned long valu;
+
+ /* It's value is the size (in bytes) of the function for
+ function relative stabs, or the address of the function's
+ end for old style stabs. */
+ valu = CUR_SYMBOL_VALUE + last_function_start;
+ if (pst->texthigh == 0 || valu > pst->texthigh)
+ pst->texthigh = valu;
+ break;
+ }
+#endif
+
+ 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);
+#ifdef STATIC_TRANSFORM_NAME
+ namestring = STATIC_TRANSFORM_NAME (namestring);
+#endif
+ add_psymbol_to_list (namestring, p - namestring,
+ VAR_NAMESPACE, LOC_STATIC,
+ &objfile->static_psymbols,
+ 0, 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_to_list (namestring, p - namestring,
+ VAR_NAMESPACE, LOC_STATIC,
+ &objfile->global_psymbols,
+ 0, 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, 0,
+ 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, 0,
+ psymtab_language, objfile);
+ p += 1;
+ }
+ /* The semantics of C++ state that "struct foo { ... }"
+ also defines a typedef for "foo". Unfortuantely, cfront
+ never makes the typedef when translating from C++ to C.
+ We make the typedef here so that "ptype foo" works as
+ expected for cfront translated code. */
+ else if (psymtab_language == language_cplus)
+ {
+ /* Also a typedef with the same name. */
+ add_psymbol_to_list (namestring, p - namestring,
+ VAR_NAMESPACE, LOC_TYPEDEF,
+ &objfile->static_psymbols,
+ CUR_SYMBOL_VALUE, 0,
+ psymtab_language, objfile);
+ }
+ }
+ 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, 0,
+ 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')
+ {
+ /* The aix4 compiler emits extra crud before the members. */
+ if (*p == '-')
+ {
+ /* Skip over the type (?). */
+ while (*p != ':')
+ p++;
+
+ /* Skip over the colon. */
+ p++;
+ }
+
+ /* 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 == '?' && p[1] == '\0'))
+ p = next_symbol_text (objfile);
+
+ /* 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,
+ 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,
+ 0, psymtab_language, objfile);
+ continue;
+
+ case 'f':
+ CUR_SYMBOL_VALUE += ANOFFSET (section_offsets, SECT_OFF_TEXT);
+#ifdef DBXREAD_ONLY
+ /* Keep track of the start of the last function so we
+ can handle end of function symbols. */
+ last_function_start = CUR_SYMBOL_VALUE;
+ /* Kludges for ELF/STABS with Sun ACC */
+ last_function_name = namestring;
+#ifdef SOFUN_ADDRESS_MAYBE_MISSING
+ /* Do not fix textlow==0 for .o or NLM files, as 0 is a legit
+ value for the bottom of the text seg in those cases. */
+ if (pst && textlow_not_set)
+ {
+ pst->textlow =
+ find_stab_function_addr (namestring, pst, objfile);
+ textlow_not_set = 0;
+ }
+#endif
+#if 0
+ if (startup_file_end == 0)
+ startup_file_end = CUR_SYMBOL_VALUE;
+#endif
+ /* End kludge. */
+
+ /* In reordered executables this function may lie outside
+ the bounds created by N_SO symbols. If that's the case
+ use the address of this function as the low bound for
+ the partial symbol table. */
+ if (textlow_not_set
+ || (CUR_SYMBOL_VALUE < pst->textlow
+ && CUR_SYMBOL_VALUE
+ != ANOFFSET (section_offsets, SECT_OFF_TEXT)))
+ {
+ pst->textlow = CUR_SYMBOL_VALUE;
+ textlow_not_set = 0;
+ }
+#endif /* DBXREAD_ONLY */
+ add_psymbol_to_list (namestring, p - namestring,
+ VAR_NAMESPACE, LOC_BLOCK,
+ &objfile->static_psymbols,
+ 0, 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':
+ CUR_SYMBOL_VALUE += ANOFFSET (section_offsets, SECT_OFF_TEXT);
+#ifdef DBXREAD_ONLY
+ /* Keep track of the start of the last function so we
+ can handle end of function symbols. */
+ last_function_start = CUR_SYMBOL_VALUE;
+ /* Kludges for ELF/STABS with Sun ACC */
+ last_function_name = namestring;
+#ifdef SOFUN_ADDRESS_MAYBE_MISSING
+ /* Do not fix textlow==0 for .o or NLM files, as 0 is a legit
+ value for the bottom of the text seg in those cases. */
+ if (pst && textlow_not_set)
+ {
+ pst->textlow =
+ find_stab_function_addr (namestring, pst, objfile);
+ textlow_not_set = 0;
+ }
+#endif
+#if 0
+ if (startup_file_end == 0)
+ startup_file_end = CUR_SYMBOL_VALUE;
+#endif
+ /* End kludge. */
+ /* In reordered executables this function may lie outside
+ the bounds created by N_SO symbols. If that's the case
+ use the address of this function as the low bound for
+ the partial symbol table. */
+ if (textlow_not_set
+ || (CUR_SYMBOL_VALUE < pst->textlow
+ && CUR_SYMBOL_VALUE
+ != ANOFFSET (section_offsets, SECT_OFF_TEXT)))
+ {
+ pst->textlow = CUR_SYMBOL_VALUE;
+ textlow_not_set = 0;
+ }
+#endif /* DBXREAD_ONLY */
+ add_psymbol_to_list (namestring, p - namestring,
+ VAR_NAMESPACE, LOC_BLOCK,
+ &objfile->global_psymbols,
+ 0, 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':
+ case '-':
+ case '#': /* for symbol identification (used in live ranges) */
+ /* added to support cfront stabs strings */
+ case 'Z': /* for definition continuations */
+ case 'P': /* for prototypes */
+ continue;
+
+ case ':':
+ /* It is a C++ nested symbol. We don't need to record it
+ (I don't think); if we try to look up foo::bar::baz,
+ then symbols for the symtab containing foo should get
+ read in, I think. */
+ /* Someone says sun cc puts out symbols like
+ /foo/baz/maclib::/usr/local/bin/maclib,
+ which would get here with a symbol type of ':'. */
+ continue;
+
+ default:
+ /* Unexpected symbol descriptor. The second and subsequent stabs
+ of a continued stab can show up here. The question is
+ whether they ever can mimic a normal stab--it would be
+ nice if not, since we certainly don't want to spend the
+ time searching to the end of every string looking for
+ a backslash. */
+
+ complain (&unknown_symchar_complaint, p[1]);
+
+ /* Ignore it; perhaps it is an extension that we don't
+ know about. */
+ 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_unfiltered (gdb_stderr, "Had to reallocate dependency list.\n");
+ fprintf_unfiltered (gdb_stderr, "New dependencies allocated: %d\n",
+ dependencies_allocated);
+#endif
+ }
+ }
+ }
+#endif /* DBXREAD_ONLY */
+ continue;
+
+ case N_ENDM:
+#ifdef SOFUN_ADDRESS_MAYBE_MISSING
+ /* Solaris 2 end of module, finish current partial symbol table.
+ END_PSYMTAB will set pst->texthigh to the proper value, which
+ is necessary if a module compiled without debugging info
+ follows this module. */
+ if (pst)
+ {
+ END_PSYMTAB (pst, psymtab_include_list, includes_used,
+ symnum * symbol_size,
+ (CORE_ADDR) 0,
+ dependency_list, dependencies_used, textlow_not_set);
+ pst = (struct partial_symtab *) 0;
+ includes_used = 0;
+ dependencies_used = 0;
+ }
+#endif
+ 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_ALIAS: /* SunPro F77: alias name, ignore for now. */
+
+ case N_OBJ: /* useless types from Solaris */
+ case N_OPT:
+ /* 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 (CUR_SYMBOL_TYPE));
+ continue;
+ }
diff --git a/gdb/ppc-bdm.c b/gdb/ppc-bdm.c
new file mode 100644
index 00000000000..e6b6adfdd71
--- /dev/null
+++ b/gdb/ppc-bdm.c
@@ -0,0 +1,387 @@
+/* Remote target communications for the Macraigor Systems BDM Wiggler
+ talking to a Motorola PPC 8xx ADS board
+ Copyright 1996, 1997 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "gdbcore.h"
+#include "gdb_string.h"
+#include <fcntl.h>
+#include "frame.h"
+#include "inferior.h"
+#include "bfd.h"
+#include "symfile.h"
+#include "target.h"
+#include "wait.h"
+#include "gdbcmd.h"
+#include "objfiles.h"
+#include "gdb-stabs.h"
+#include <sys/types.h>
+#include <signal.h>
+#include "serial.h"
+#include "ocd.h"
+
+static void bdm_ppc_open PARAMS ((char *name, int from_tty));
+
+static int bdm_ppc_wait PARAMS ((int pid,
+ struct target_waitstatus *target_status));
+
+static void bdm_ppc_fetch_registers PARAMS ((int regno));
+
+static void bdm_ppc_store_registers PARAMS ((int regno));
+
+extern struct target_ops bdm_ppc_ops; /* Forward decl */
+
+/*#define BDM_NUM_REGS 71*/
+#define BDM_NUM_REGS 24
+
+#define BDM_REGMAP \
+ 2048, 2049, 2050, 2051, 2052, 2053, 2054, 2055, /* r0-r7 */ \
+ 2056, 2057, 2058, 2059, 2060, 2061, 2062, 2063, /* r8-r15 */ \
+ 2064, 2065, 2066, 2067, 2068, 2069, 2070, 2071, /* r16-r23 */ \
+ 2072, 2073, 2074, 2075, 2076, 2077, 2078, 2079, /* r24-r31 */ \
+\
+ 2080, 2082, 2084, 2086, 2088, 2090, 2092, 2094, /* fp0->fp8 */ \
+ 2096, 2098, 2100, 2102, 2104, 2106, 2108, 2110, /* fp0->fp8 */ \
+ 2112, 2114, 2116, 2118, 2120, 2122, 2124, 2126, /* fp0->fp8 */ \
+ 2128, 2130, 2132, 2134, 2136, 2138, 2140, 2142, /* fp0->fp8 */ \
+\
+ 26, /* pc (SRR0 (SPR 26)) */ \
+ 2146, /* ps (MSR) */ \
+ 2144, /* cnd (CR) */ \
+ 8, /* lr (SPR 8) */ \
+ 9, /* cnt (CTR (SPR 9)) */ \
+ 1, /* xer (SPR 1) */ \
+ 0, /* mq (SPR 0) */
+
+
+char nowatchdog[4] = {0xff,0xff,0xff,0x88};
+
+/* Open a connection to a remote debugger.
+ NAME is the filename used for communication. */
+
+static void
+bdm_ppc_open (name, from_tty)
+ char *name;
+ int from_tty;
+{
+ CORE_ADDR watchdogaddr = 0xff000004;
+
+ ocd_open (name, from_tty, OCD_TARGET_MOTO_PPC, &bdm_ppc_ops);
+
+ /* We want interrupts to drop us into debugging mode. */
+ /* Modify the DER register to accomplish this. */
+ ocd_write_bdm_register (149, 0x20024000);
+
+ /* Disable watchdog timer on the board */
+ ocd_write_bytes (watchdogaddr, nowatchdog, 4);
+}
+
+/* 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
+bdm_ppc_wait (pid, target_status)
+ int pid;
+ struct target_waitstatus *target_status;
+{
+ int stop_reason;
+
+ target_status->kind = TARGET_WAITKIND_STOPPED;
+
+ stop_reason = ocd_wait ();
+
+ if (stop_reason)
+ {
+ target_status->value.sig = TARGET_SIGNAL_INT;
+ return inferior_pid;
+ }
+
+ target_status->value.sig = TARGET_SIGNAL_TRAP; /* XXX for now */
+
+#if 0
+ {
+ unsigned long ecr, der;
+
+ ecr = ocd_read_bdm_register (148); /* Read the exception cause register */
+ der = ocd_read_bdm_register (149); /* Read the debug enables register */
+ fprintf_unfiltered (gdb_stdout, "ecr = 0x%x, der = 0x%x\n", ecr, der);
+ }
+#endif
+
+ return inferior_pid;
+}
+
+static int bdm_regmap[] = {BDM_REGMAP};
+
+/* Read the remote registers into regs.
+ Fetch register REGNO, or all registers if REGNO == -1
+
+ The Wiggler uses the following codes to access the registers:
+
+ 0 -> 1023 SPR 0 -> 1023
+ 0 - SPR 0 - MQ
+ 1 - SPR 1 - XER
+ 8 - SPR 8 - LR
+ 9 - SPR 9 - CTR (known as cnt in GDB)
+ 26 - SPR 26 - SRR0 - pc
+ 1024 -> 2047 DCR 0 -> DCR 1023 (IBM PPC 4xx only)
+ 2048 -> 2079 R0 -> R31
+ 2080 -> 2143 FP0 -> FP31 (64 bit regs) (IBM PPC 5xx only)
+ 2144 CR (known as cnd in GDB)
+ 2145 FPCSR
+ 2146 MSR (known as ps in GDB)
+ */
+
+static void
+bdm_ppc_fetch_registers (regno)
+ int regno;
+{
+ int i;
+ unsigned char *regs, *beginregs, *endregs, *almostregs;
+ unsigned char midregs[32];
+ unsigned char mqreg[1];
+ int first_regno, last_regno;
+ int first_bdm_regno, last_bdm_regno;
+ int reglen, beginreglen, endreglen;
+
+#if 1
+ for (i = 0; i < (FPLAST_REGNUM - FP0_REGNUM + 1); i++)
+ {
+ midregs[i] = -1;
+ }
+ mqreg[0] = -1;
+#endif
+
+ if (regno == -1)
+ {
+ first_regno = 0;
+ last_regno = NUM_REGS - 1;
+
+ first_bdm_regno = 0;
+ last_bdm_regno = BDM_NUM_REGS - 1;
+ }
+ else
+ {
+ first_regno = regno;
+ last_regno = regno;
+
+ first_bdm_regno = bdm_regmap [regno];
+ last_bdm_regno = bdm_regmap [regno];
+ }
+
+ if (first_bdm_regno == -1)
+ {
+ supply_register (first_regno, NULL);
+ return; /* Unsupported register */
+ }
+
+#if 1
+ /* Can't ask for floating point regs on ppc 8xx, also need to
+ avoid asking for the mq register. */
+ if (first_regno == last_regno) /* only want one reg */
+ {
+/* printf("Asking for register %d\n", first_regno); */
+
+ /* if asking for an invalid register */
+ if ((first_regno == MQ_REGNUM) ||
+ ((first_regno >= FP0_REGNUM) && (first_regno <= FPLAST_REGNUM)))
+ {
+/* printf("invalid reg request!\n"); */
+ supply_register (first_regno, NULL);
+ return; /* Unsupported register */
+ }
+ else
+ {
+ regs = ocd_read_bdm_registers (first_bdm_regno,
+ last_bdm_regno, &reglen);
+ }
+ }
+ else /* want all regs */
+ {
+/* printf("Asking for registers %d to %d\n", first_regno, last_regno); */
+ beginregs = ocd_read_bdm_registers (first_bdm_regno,
+ FP0_REGNUM - 1, &beginreglen);
+ endregs = (strcat (midregs,
+ ocd_read_bdm_registers (FPLAST_REGNUM + 1,
+ last_bdm_regno - 1, &endreglen)));
+ almostregs = (strcat (beginregs, endregs));
+ regs = (strcat (almostregs, mqreg));
+ reglen = beginreglen + 32 + endreglen + 1;
+ }
+
+#endif
+#if 0
+ regs = ocd_read_bdm_registers (first_bdm_regno, last_bdm_regno, &reglen);
+#endif
+
+ for (i = first_regno; i <= last_regno; i++)
+ {
+ int bdm_regno, regoffset;
+
+ bdm_regno = bdm_regmap [i];
+ if (bdm_regno != -1)
+ {
+ regoffset = bdm_regno - first_bdm_regno;
+
+ if (regoffset >= reglen / 4)
+ continue;
+
+ supply_register (i, regs + 4 * regoffset);
+ }
+ else
+ supply_register (i, NULL); /* Unsupported register */
+ }
+}
+
+/* Store register REGNO, or all registers if REGNO == -1, from the contents
+ of REGISTERS. FIXME: ignores errors. */
+
+static void
+bdm_ppc_store_registers (regno)
+ int regno;
+{
+ int i;
+ int first_regno, last_regno;
+ int first_bdm_regno, last_bdm_regno;
+
+ if (regno == -1)
+ {
+ first_regno = 0;
+ last_regno = NUM_REGS - 1;
+
+ first_bdm_regno = 0;
+ last_bdm_regno = BDM_NUM_REGS - 1;
+ }
+ else
+ {
+ first_regno = regno;
+ last_regno = regno;
+
+ first_bdm_regno = bdm_regmap [regno];
+ last_bdm_regno = bdm_regmap [regno];
+ }
+
+ if (first_bdm_regno == -1)
+ return; /* Unsupported register */
+
+ for (i = first_regno; i <= last_regno; i++)
+ {
+ int bdm_regno;
+
+ bdm_regno = bdm_regmap [i];
+
+ /* only attempt to write if it's a valid ppc 8xx register */
+ /* (need to avoid FP regs and MQ reg) */
+ if ((i != MQ_REGNUM) && ((i < FP0_REGNUM) || (i > FPLAST_REGNUM)))
+ {
+/* printf("write valid reg %d\n", bdm_regno); */
+ ocd_write_bdm_registers (bdm_regno, registers + REGISTER_BYTE (i), 4);
+ }
+/*
+ else if (i == MQ_REGNUM)
+ printf("don't write invalid reg %d (MQ_REGNUM)\n", bdm_regno);
+ else
+ printf("don't write invalid reg %d\n", bdm_regno);
+*/
+ }
+}
+
+/* Define the target subroutine names */
+
+struct target_ops bdm_ppc_ops ;
+
+static void
+init_bdm_ppc_ops(void)
+{
+ bdm_ppc_ops.to_shortname = "ocd";
+ bdm_ppc_ops.to_longname = "Remote target with On-Chip Debugging";
+ bdm_ppc_ops.to_doc = "Use a remote target with On-Chip Debugging. To use a target box;\n\
+specify the serial device it is connected to (e.g. /dev/ttya). To use\n\
+a wiggler, specify wiggler and then the port it is connected to\n\
+(e.g. wiggler lpt1)." ; /* to_doc */
+ bdm_ppc_ops.to_open = bdm_ppc_open;
+ bdm_ppc_ops.to_close = ocd_close;
+ bdm_ppc_ops.to_attach = NULL;
+ bdm_ppc_ops.to_post_attach = NULL;
+ bdm_ppc_ops.to_require_attach = NULL;
+ bdm_ppc_ops.to_detach = ocd_detach;
+ bdm_ppc_ops.to_require_detach = NULL;
+ bdm_ppc_ops.to_resume = ocd_resume;
+ bdm_ppc_ops.to_wait = bdm_ppc_wait;
+ bdm_ppc_ops.to_post_wait = NULL;
+ bdm_ppc_ops.to_fetch_registers = bdm_ppc_fetch_registers;
+ bdm_ppc_ops.to_store_registers = bdm_ppc_store_registers;
+ bdm_ppc_ops.to_prepare_to_store = ocd_prepare_to_store;
+ bdm_ppc_ops.to_xfer_memory = ocd_xfer_memory;
+ bdm_ppc_ops.to_files_info = ocd_files_info;
+ bdm_ppc_ops.to_insert_breakpoint = ocd_insert_breakpoint;
+ bdm_ppc_ops.to_remove_breakpoint = ocd_remove_breakpoint;
+ bdm_ppc_ops.to_terminal_init = NULL;
+ bdm_ppc_ops.to_terminal_inferior = NULL;
+ bdm_ppc_ops.to_terminal_ours_for_output = NULL;
+ bdm_ppc_ops.to_terminal_ours = NULL;
+ bdm_ppc_ops.to_terminal_info = NULL;
+ bdm_ppc_ops.to_kill = ocd_kill;
+ bdm_ppc_ops.to_load = ocd_load;
+ bdm_ppc_ops.to_lookup_symbol = NULL;
+ bdm_ppc_ops.to_create_inferior = ocd_create_inferior;
+ bdm_ppc_ops.to_post_startup_inferior = NULL;
+ bdm_ppc_ops.to_acknowledge_created_inferior = NULL;
+ bdm_ppc_ops.to_clone_and_follow_inferior = NULL;
+ bdm_ppc_ops.to_post_follow_inferior_by_clone = NULL;
+ bdm_ppc_ops.to_insert_fork_catchpoint = NULL;
+ bdm_ppc_ops.to_remove_fork_catchpoint = NULL;
+ bdm_ppc_ops.to_insert_vfork_catchpoint = NULL;
+ bdm_ppc_ops.to_remove_vfork_catchpoint = NULL;
+ bdm_ppc_ops.to_has_forked = NULL;
+ bdm_ppc_ops.to_has_vforked = NULL;
+ bdm_ppc_ops.to_can_follow_vfork_prior_to_exec = NULL;
+ bdm_ppc_ops.to_post_follow_vfork = NULL;
+ bdm_ppc_ops.to_insert_exec_catchpoint = NULL;
+ bdm_ppc_ops.to_remove_exec_catchpoint = NULL;
+ bdm_ppc_ops.to_has_execd = NULL;
+ bdm_ppc_ops.to_reported_exec_events_per_exec_call = NULL;
+ bdm_ppc_ops.to_has_exited = NULL;
+ bdm_ppc_ops.to_mourn_inferior = ocd_mourn;
+ bdm_ppc_ops.to_can_run = 0;
+ bdm_ppc_ops.to_notice_signals = 0;
+ bdm_ppc_ops.to_thread_alive = ocd_thread_alive;
+ bdm_ppc_ops.to_stop = ocd_stop;
+ bdm_ppc_ops.to_pid_to_exec_file = NULL;
+ bdm_ppc_ops.to_core_file_to_sym_file = NULL;
+ bdm_ppc_ops.to_stratum = process_stratum;
+ bdm_ppc_ops.DONT_USE = NULL;
+ bdm_ppc_ops.to_has_all_memory = 1;
+ bdm_ppc_ops.to_has_memory = 1;
+ bdm_ppc_ops.to_has_stack = 1;
+ bdm_ppc_ops.to_has_registers = 1;
+ bdm_ppc_ops.to_has_execution = 1;
+ bdm_ppc_ops.to_sections = NULL;
+ bdm_ppc_ops.to_sections_end = NULL;
+ bdm_ppc_ops.to_magic = OPS_MAGIC ;
+} /* init_bdm_ppc_ops */
+
+void
+_initialize_bdm_ppc ()
+{
+ init_bdm_ppc_ops() ;
+ add_target (&bdm_ppc_ops);
+}
diff --git a/gdb/ppcbug-rom.c b/gdb/ppcbug-rom.c
new file mode 100644
index 00000000000..9496916f44b
--- /dev/null
+++ b/gdb/ppcbug-rom.c
@@ -0,0 +1,230 @@
+/* Remote debugging interface for PPCbug (PowerPC) Rom monitor
+ for GDB, the GNU debugger.
+ Copyright 1995 Free Software Foundation, Inc.
+
+ Written by Stu Grossman of 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "gdbcore.h"
+#include "target.h"
+#include "monitor.h"
+#include "serial.h"
+
+static void ppcbug_open PARAMS ((char *args, int from_tty));
+
+static void
+ppcbug_supply_register (regname, regnamelen, val, vallen)
+ char *regname;
+ int regnamelen;
+ char *val;
+ int vallen;
+{
+ int regno = 0, base = 0;
+
+ if (regnamelen < 2 || regnamelen > 4)
+ return;
+
+ switch (regname[0])
+ {
+ case 'R':
+ if (regname[1] < '0' || regname[1] > '9')
+ return;
+ if (regnamelen == 2)
+ regno = regname[1] - '0';
+ else if (regnamelen == 3 && regname[2] >= '0' && regname[2] <= '9')
+ regno = (regname[1] - '0') * 10 + (regname[2] - '0');
+ else
+ return;
+ break;
+ case 'F':
+ if (regname[1] != 'R' || regname[2] < '0' || regname[2] > '9')
+ return;
+ if (regnamelen == 3)
+ regno = 32 + regname[2] - '0';
+ else if (regnamelen == 4 && regname[3] >= '0' && regname[3] <= '9')
+ regno = 32 + (regname[2] - '0') * 10 + (regname[3] - '0');
+ else
+ return;
+ break;
+ case 'I':
+ if (regnamelen != 2 || regname[1] != 'P')
+ return;
+ regno = 64;
+ break;
+ case 'M':
+ if (regnamelen != 3 || regname[1] != 'S' || regname[2] != 'R')
+ return;
+ regno = 65;
+ break;
+ case 'C':
+ if (regnamelen != 2 || regname[1] != 'R')
+ return;
+ regno = 66;
+ break;
+ case 'S':
+ if (regnamelen != 4 || regname[1] != 'P' || regname[2] != 'R')
+ return;
+ else if (regname[3] == '8')
+ regno = 67;
+ else if (regname[3] == '9')
+ regno = 68;
+ else if (regname[3] == '1')
+ regno = 69;
+ else if (regname[3] == '0')
+ regno = 70;
+ else
+ return;
+ break;
+ default:
+ return;
+ }
+
+ monitor_supply_register (regno, val);
+}
+
+/*
+ * This array of registers needs to match the indexes used by GDB. The
+ * whole reason this exists is because the various ROM monitors use
+ * different names than GDB does, and don't support all the
+ * registers either. So, typing "info reg sp" becomes an "A7".
+ */
+
+static char *ppcbug_regnames[NUM_REGS] =
+{
+ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
+ "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
+ "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
+ "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
+
+ "fr0", "fr1", "fr2", "fr3", "fr4", "fr5", "fr6", "fr7",
+ "fr8", "fr9", "fr10", "fr11", "fr12", "fr13", "fr14", "fr15",
+ "fr16", "fr17", "fr18", "fr19", "fr20", "fr21", "fr22", "fr23",
+ "fr24", "fr25", "fr26", "fr27", "fr28", "fr29", "fr30", "fr31",
+
+/* pc ps cnd lr cnt xer mq */
+ "ip", "msr", "cr", "spr8", "spr9", "spr1", "spr0"
+};
+
+/*
+ * Define the monitor command strings. Since these are passed directly
+ * through to a printf style function, we need can include formatting
+ * strings. We also need a CR or LF on the end.
+ */
+
+static struct target_ops ppcbug_ops0;
+static struct target_ops ppcbug_ops1;
+
+static char *ppcbug_inits[] = {"\r", NULL};
+
+static void
+init_ppc_cmds (char * LOAD_CMD,
+ struct monitor_ops * OPS,
+ struct target_ops * targops)
+{
+ OPS->flags = MO_CLR_BREAK_USES_ADDR | MO_HANDLE_NL;
+ OPS->init = ppcbug_inits; /* Init strings */
+ OPS->cont = "g\r"; /* continue command */
+ OPS->step = "t\r"; /* single step */
+ OPS->stop = NULL; /* interrupt command */
+ OPS->set_break = "br %x\r"; /* set a breakpoint */
+ OPS->clr_break = "nobr %x\r"; /* clear a breakpoint */
+ OPS->clr_all_break = "nobr\r"; /* clear all breakpoints */
+ OPS->fill = "bf %x:%x %x;b\r"; /* fill (start count val) */
+ OPS->setmem.cmdb = "ms %x %02x\r"; /* setmem.cmdb (addr, value) */
+ OPS->setmem.cmdw = "ms %x %04x\r"; /* setmem.cmdw (addr, value) */
+ OPS->setmem.cmdl = "ms %x %08x\r"; /* setmem.cmdl (addr, value) */
+ OPS->setmem.cmdll = NULL; /* setmem.cmdll (addr, value) */
+ OPS->setmem.resp_delim = NULL; /* setreg.resp_delim */
+ OPS->setmem.term = NULL; /* setreg.term */
+ OPS->setmem.term_cmd = NULL; /* setreg.term_cmd */
+ OPS->getmem.cmdb = "md %x:%x;b\r"; /* getmem.cmdb (addr, len) */
+ OPS->getmem.cmdw = "md %x:%x;b\r"; /* getmem.cmdw (addr, len) */
+ OPS->getmem.cmdl = "md %x:%x;b\r"; /* getmem.cmdl (addr, len) */
+ OPS->getmem.cmdll = NULL; /* getmem.cmdll (addr, len) */
+ OPS->getmem.resp_delim = " "; /* getmem.resp_delim */
+ OPS->getmem.term = NULL; /* getmem.term */
+ OPS->getmem.term_cmd = NULL; /* getmem.term_cmd */
+ OPS->setreg.cmd = "rs %s %x\r"; /* setreg.cmd (name, value) */
+ OPS->setreg.resp_delim = NULL; /* setreg.resp_delim */
+ OPS->setreg.term = NULL; /* setreg.term */
+ OPS->setreg.term_cmd = NULL ; /* setreg.term_cmd */
+ OPS->getreg.cmd = "rs %s\r"; /* getreg.cmd (name) */
+ OPS->getreg.resp_delim = "="; /* getreg.resp_delim */
+ OPS->getreg.term = NULL; /* getreg.term */
+ OPS->getreg.term_cmd = NULL ; /* getreg.term_cmd */
+ OPS->register_pattern = "\\(\\w+\\) +=\\([0-9a-fA-F]+\\b\\)"; /* register_pattern */
+ OPS->supply_register = ppcbug_supply_register; /* supply_register */
+ OPS->dump_registers = "rd\r"; /* dump all registers */
+ OPS->load_routine = NULL; /* load_routine (defaults to SRECs) */
+ OPS->load = LOAD_CMD; /* download command */
+ OPS->loadresp = NULL; /* load response */
+ OPS->prompt = "PPC1-Bug>"; /* monitor command prompt */
+ OPS->line_term = "\r"; /* end-of-line terminator */
+ OPS->cmd_end = NULL; /* optional command terminator */
+ OPS->target = targops ; /* target operations */
+ OPS->stopbits = SERIAL_1_STOPBITS; /* number of stop bits */
+ OPS->regnames = ppcbug_regnames; /* registers names */
+ OPS->magic = MONITOR_OPS_MAGIC; /* magic */
+}
+
+
+static struct monitor_ops ppcbug_cmds0 ;
+static struct monitor_ops ppcbug_cmds1 ;
+
+static void
+ppcbug_open0(args, from_tty)
+ char *args;
+ int from_tty;
+{
+ monitor_open (args, &ppcbug_cmds0, from_tty);
+}
+
+static void
+ppcbug_open1(args, from_tty)
+ char *args;
+ int from_tty;
+{
+ monitor_open (args, &ppcbug_cmds1, from_tty);
+}
+
+void
+_initialize_ppcbug_rom ()
+{
+ init_ppc_cmds("lo 0\r", &ppcbug_cmds0, &ppcbug_ops0) ;
+ init_ppc_cmds("lo 1\r", &ppcbug_cmds1, &ppcbug_ops1);
+ init_monitor_ops (&ppcbug_ops0);
+
+ ppcbug_ops0.to_shortname = "ppcbug";
+ ppcbug_ops0.to_longname = "PowerPC PPCBug monitor on port 0";
+ ppcbug_ops0.to_doc = "Debug via the PowerPC PPCBug monitor using port 0.\n\
+Specify the serial device it is connected to (e.g. /dev/ttya).";
+ ppcbug_ops0.to_open = ppcbug_open0;
+
+ add_target (&ppcbug_ops0);
+
+ init_monitor_ops (&ppcbug_ops1);
+
+ ppcbug_ops1.to_shortname = "ppcbug1";
+ ppcbug_ops1.to_longname = "PowerPC PPCBug monitor on port 1";
+ ppcbug_ops1.to_doc = "Debug via the PowerPC PPCBug monitor using port 1.\n\
+Specify the serial device it is connected to (e.g. /dev/ttya).";
+ ppcbug_ops1.to_open = ppcbug_open1;
+
+ add_target (&ppcbug_ops1);
+}
diff --git a/gdb/printcmd.c b/gdb/printcmd.c
new file mode 100644
index 00000000000..0f0b8abd202
--- /dev/null
+++ b/gdb/printcmd.c
@@ -0,0 +1,2575 @@
+/* Print values for GNU debugger GDB.
+ Copyright 1986, 87, 88, 89, 90, 91, 93, 94, 95, 1998
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "gdb_string.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"
+#include "valprint.h"
+#include "annotate.h"
+#include "symfile.h" /* for overlay functions */
+#include "objfiles.h" /* ditto */
+
+extern int asm_demangle; /* Whether to demangle syms in asm printouts */
+extern int addressprint; /* Whether to print hex addresses in HLL " */
+
+struct format_data
+{
+ int count;
+ char format;
+ char size;
+};
+
+/* Last specified output format. */
+
+static char last_format = 'x';
+
+/* Last specified examination size. 'b', 'h', 'w' or `q'. */
+
+static char last_size = 'w';
+
+/* Default address to examine next. */
+
+static CORE_ADDR next_address;
+
+/* Default section to examine next. */
+
+static asection *next_section;
+
+/* Last address examined. */
+
+static CORE_ADDR last_examine_address;
+
+/* Contents of last address examined.
+ This is not valid past the end of the `x' command! */
+
+static value_ptr 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 disable it if we get an error or a signal within it.
+ -1 when not doing one. */
+
+int current_display_number;
+
+/* Flag to low-level print routines that this value is being printed
+ in an epoch window. We'd like to pass this as a parameter, but
+ every routine would need to take it. Perhaps we can encapsulate
+ this in the I/O stream once we have GNU stdio. */
+
+int inspect_it = 0;
+
+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 exported functions. */
+
+void output_command PARAMS ((char *, int));
+
+void _initialize_printcmd PARAMS ((void));
+
+/* 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, GDB_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));
+
+void x_command PARAMS ((char *, int));
+
+static void address_info PARAMS ((char *, int));
+
+static void set_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 addr, asection *section));
+
+static void print_formatted PARAMS ((value_ptr, int, int));
+
+static struct format_data decode_format PARAMS ((char **, int, int));
+
+static int print_insn PARAMS ((CORE_ADDR, GDB_FILE *));
+
+static void sym_info PARAMS ((char *, int));
+
+
+/* Decode a format specification. *STRING_PTR should point to it.
+ OFORMAT and OSIZE are used as defaults for the format and size
+ if none are given in the format specification.
+ If OSIZE is zero, then the size field of the returned value
+ should be set only if a size is explicitly specified by the
+ user.
+ The structure returned describes all the data
+ found in the specification. In addition, *STRING_PTR is advanced
+ past the specification and past all whitespace following it. */
+
+static struct format_data
+decode_format (string_ptr, oformat, osize)
+ char **string_ptr;
+ int oformat;
+ int osize;
+{
+ struct format_data val;
+ register char *p = *string_ptr;
+
+ val.format = '?';
+ val.size = '?';
+ val.count = 1;
+
+ if (*p >= '0' && *p <= '9')
+ val.count = atoi (p);
+ while (*p >= '0' && *p <= '9') p++;
+
+ /* Now process size or format letters that follow. */
+
+ while (1)
+ {
+ if (*p == 'b' || *p == 'h' || *p == 'w' || *p == 'g')
+ val.size = *p++;
+ else if (*p >= 'a' && *p <= 'z')
+ val.format = *p++;
+ else
+ break;
+ }
+
+ while (*p == ' ' || *p == '\t') p++;
+ *string_ptr = p;
+
+ /* Set defaults for format and size if not specified. */
+ if (val.format == '?')
+ {
+ if (val.size == '?')
+ {
+ /* Neither has been specified. */
+ val.format = oformat;
+ val.size = osize;
+ }
+ else
+ /* If a size is specified, any format makes a reasonable
+ default except 'i'. */
+ val.format = oformat == 'i' ? 'x' : oformat;
+ }
+ else if (val.size == '?')
+ switch (val.format)
+ {
+ case 'a':
+ case 's':
+ /* Pick the appropriate size for an address. */
+ if (TARGET_PTR_BIT == 64)
+ val.size = osize ? 'g' : osize;
+ else if (TARGET_PTR_BIT == 32)
+ val.size = osize ? 'w' : osize;
+ else if (TARGET_PTR_BIT == 16)
+ val.size = osize ? 'h' : osize;
+ else
+ /* Bad value for TARGET_PTR_BIT */
+ abort ();
+ break;
+ case 'f':
+ /* Floating point has to be word or giantword. */
+ if (osize == 'w' || osize == 'g')
+ val.size = osize;
+ else
+ /* Default it to giantword if the last used size is not
+ appropriate. */
+ val.size = osize ? 'g' : osize;
+ break;
+ case 'c':
+ /* Characters default to one byte. */
+ val.size = osize ? 'b' : osize;
+ break;
+ default:
+ /* The default is the size most recently specified. */
+ val.size = osize;
+ }
+
+ return val;
+}
+
+/* Print value VAL on gdb_stdout according to FORMAT, a letter or 0.
+ Do not end with a newline.
+ 0 means print VAL according to its own type.
+ SIZE is the letter for the size of datum being printed.
+ This is used to pad hex numbers so they line up. */
+
+static void
+print_formatted (val, format, size)
+ register value_ptr val;
+ register int format;
+ int size;
+{
+ struct type *type = check_typedef (VALUE_TYPE (val));
+ int len = TYPE_LENGTH (type);
+
+ if (VALUE_LVAL (val) == lval_memory)
+ {
+ next_address = VALUE_ADDRESS (val) + len;
+ next_section = VALUE_BFD_SECTION (val);
+ }
+
+ switch (format)
+ {
+ case 's':
+ /* FIXME: Need to handle wchar_t's here... */
+ next_address = VALUE_ADDRESS (val)
+ + val_print_string (VALUE_ADDRESS (val), -1, 1, gdb_stdout);
+ next_section = VALUE_BFD_SECTION (val);
+ 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.
+ --Yes, it does filter now, and so this is obsolete. -JB */
+
+ /* We often wrap here if there are long symbolic names. */
+ wrap_here (" ");
+ next_address = VALUE_ADDRESS (val)
+ + print_insn (VALUE_ADDRESS (val), gdb_stdout);
+ next_section = VALUE_BFD_SECTION (val);
+ break;
+
+ default:
+ if (format == 0
+ || TYPE_CODE (type) == TYPE_CODE_ARRAY
+ || TYPE_CODE (type) == TYPE_CODE_STRING
+ || TYPE_CODE (type) == TYPE_CODE_STRUCT
+ || TYPE_CODE (type) == TYPE_CODE_UNION)
+ /* If format is 0, use the 'natural' format for
+ * that type of value. If the type is non-scalar,
+ * we have to use language rules to print it as
+ * a series of scalars.
+ */
+ value_print (val, gdb_stdout, format, Val_pretty_default);
+ else
+ /* User specified format, so don't look to the
+ * the type to tell us what to do.
+ */
+ print_scalar_formatted (VALUE_CONTENTS (val), type,
+ format, size, gdb_stdout);
+ }
+}
+
+/* Print a scalar of data of type TYPE, pointed to in GDB by VALADDR,
+ according to letters FORMAT and SIZE on STREAM.
+ FORMAT may not be zero. Formats s and i are not supported at this level.
+
+ This is how the elements of an array or structure are printed
+ with a format. */
+
+void
+print_scalar_formatted (valaddr, type, format, size, stream)
+ char *valaddr;
+ struct type *type;
+ int format;
+ int size;
+ GDB_FILE *stream;
+{
+ LONGEST val_long;
+ unsigned int len = TYPE_LENGTH (type);
+
+ if (len > sizeof (LONGEST)
+ && (format == 't'
+ || format == 'c'
+ || format == 'o'
+ || format == 'u'
+ || format == 'd'
+ || format == 'x'))
+ {
+ if (! TYPE_UNSIGNED (type)
+ || ! extract_long_unsigned_integer (valaddr, len, &val_long))
+ {
+ /* 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. */
+
+ if( format == 'o' )
+ print_octal_chars (stream, valaddr, len);
+ else if( format == 'd' )
+ print_decimal_chars (stream, valaddr, len );
+ else if( format == 't' )
+ print_binary_chars (stream, valaddr, len);
+ else
+
+ /* replace with call to print_hex_chars? Looks
+ like val_print_type_code_int is redoing
+ work. - edie */
+
+ val_print_type_code_int (type, valaddr, stream);
+
+ return;
+ }
+
+ /* If we get here, extract_long_unsigned_integer set val_long. */
+ }
+ else if (format != 'f')
+ val_long = unpack_long (type, valaddr);
+
+ /* 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 (LONGEST))
+ val_long &= ((LONGEST) 1 << HOST_CHAR_BIT * len) - 1;
+ }
+
+ switch (format)
+ {
+ case 'x':
+ if (!size)
+ {
+ /* no size specified, like in print. Print varying # of digits. */
+ print_longest (stream, 'x', 1, val_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':
+ print_longest (stream, 'd', 1, val_long);
+ break;
+
+ case 'u':
+ print_longest (stream, 'u', 0, val_long);
+ break;
+
+ case 'o':
+ if (val_long)
+ print_longest (stream, 'o', 1, val_long);
+ else
+ fprintf_filtered (stream, "0");
+ break;
+
+ case 'a':
+ print_address (unpack_pointer (type, valaddr), stream);
+ break;
+
+ case 'c':
+ value_print (value_from_longest (builtin_type_char, val_long), stream, 0,
+ Val_pretty_default);
+ break;
+
+ case 'f':
+ if (len == sizeof (float))
+ type = builtin_type_float;
+ else if (len == sizeof (double))
+ type = builtin_type_double;
+ print_floating (valaddr, type, stream);
+ break;
+
+ case 0:
+ abort ();
+
+ case 't':
+ /* Binary; 't' stands for "two". */
+ {
+ char bits[8*(sizeof val_long) + 1];
+ char buf[8*(sizeof val_long) + 32];
+ 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);
+ }
+
+ 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--;
+ }
+ strcpy (buf, local_binary_format_prefix());
+ strcat (buf, cp);
+ strcat (buf, local_binary_format_suffix());
+ fprintf_filtered (stream, buf);
+ }
+ break;
+
+ default:
+ error ("Undefined output format \"%c\".", format);
+ }
+}
+
+/* Specify default address for `x' command.
+ `info lines' uses this. */
+
+void
+set_next_address (addr)
+ CORE_ADDR addr;
+{
+ next_address = addr;
+
+ /* Make address available to the user as $_. */
+ set_internalvar (lookup_internalvar ("_"),
+ value_from_longest (lookup_pointer_type (builtin_type_void),
+ (LONGEST) addr));
+}
+
+/* Optionally print address ADDR symbolically as <SYMBOL+OFFSET> on STREAM,
+ after LEADIN. Print nothing if no symbolic name is found nearby.
+ Optionally also print source file and line number, if available.
+ 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, do_demangle, leadin)
+ CORE_ADDR addr;
+ GDB_FILE *stream;
+ int do_demangle;
+ char *leadin;
+{
+ struct minimal_symbol *msymbol;
+ struct symbol *symbol;
+ struct symtab *symtab = 0;
+ CORE_ADDR name_location = 0;
+ char *name = "";
+ asection *section = 0;
+ int unmapped = 0;
+
+ /* Determine if the address is in an overlay, and whether it is mapped. */
+ if (overlay_debugging)
+ {
+ section = find_pc_overlay (addr);
+ if (pc_in_unmapped_range (addr, section))
+ {
+ unmapped = 1;
+ addr = overlay_mapped_address (addr, section);
+ }
+ }
+
+ /* On some targets, add in extra "flag" bits to PC for
+ disassembly. This should ensure that "rounding errors" in
+ symbol addresses that are masked for disassembly favour the
+ the correct symbol. */
+
+#ifdef GDB_TARGET_UNMASK_DISAS_PC
+ addr = GDB_TARGET_UNMASK_DISAS_PC (addr);
+#endif
+
+ /* First try to find the address in the symbol table, then
+ in the minsyms. Take the closest one. */
+
+ /* This is defective in the sense that it only finds text symbols. So
+ really this is kind of pointless--we should make sure that the
+ minimal symbols have everything we need (by changing that we could
+ save some memory, but for many debug format--ELF/DWARF or
+ anything/stabs--it would be inconvenient to eliminate those minimal
+ symbols anyway). */
+ msymbol = lookup_minimal_symbol_by_pc_section (addr, section);
+ symbol = find_pc_sect_function (addr, section);
+
+ if (symbol)
+ {
+ name_location = BLOCK_START (SYMBOL_BLOCK_VALUE (symbol));
+ if (do_demangle)
+ name = SYMBOL_SOURCE_NAME (symbol);
+ else
+ name = SYMBOL_LINKAGE_NAME (symbol);
+ }
+
+ if (msymbol != NULL)
+ {
+ if (SYMBOL_VALUE_ADDRESS (msymbol) > name_location || symbol == NULL)
+ {
+ /* The msymbol is closer to the address than the symbol;
+ use the msymbol instead. */
+ symbol = 0;
+ symtab = 0;
+ name_location = SYMBOL_VALUE_ADDRESS (msymbol);
+ if (do_demangle)
+ name = SYMBOL_SOURCE_NAME (msymbol);
+ else
+ name = SYMBOL_LINKAGE_NAME (msymbol);
+ }
+ }
+ if (symbol == NULL && msymbol == NULL)
+ return;
+
+ /* On some targets, mask out extra "flag" bits from PC for handsome
+ disassembly. */
+
+#ifdef GDB_TARGET_MASK_DISAS_PC
+ name_location = GDB_TARGET_MASK_DISAS_PC (name_location);
+ addr = GDB_TARGET_MASK_DISAS_PC (addr);
+#endif
+
+ /* 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);
+ if (unmapped)
+ fputs_filtered ("<*", stream);
+ else
+ 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. Give specific
+ line # of this addr, if we have it; else line # of the nearest symbol. */
+ if (print_symbol_filename)
+ {
+ struct symtab_and_line sal;
+
+ sal = find_pc_sect_line (addr, section, 0);
+
+ if (sal.symtab)
+ fprintf_filtered (stream, " at %s:%d", sal.symtab->filename, sal.line);
+ else if (symtab && symbol && symbol->line)
+ fprintf_filtered (stream, " at %s:%d", symtab->filename, symbol->line);
+ else if (symtab)
+ fprintf_filtered (stream, " in %s", symtab->filename);
+ }
+ if (unmapped)
+ fputs_filtered ("*>", stream);
+ else
+ fputs_filtered (">", stream);
+}
+
+
+/* Print address ADDR on STREAM. USE_LOCAL means the same thing as for
+ print_longest. */
+void
+print_address_numeric (addr, use_local, stream)
+ CORE_ADDR addr;
+ int use_local;
+ GDB_FILE *stream;
+{
+ /* This assumes a CORE_ADDR can fit in a LONGEST. Probably a safe
+ assumption. */
+ print_longest (stream, 'x', use_local, (ULONGEST) addr);
+}
+
+/* Print address ADDR symbolically on STREAM.
+ First print it as a number. Then perhaps print
+ <SYMBOL + OFFSET> after the number. */
+
+void
+print_address (addr, stream)
+ CORE_ADDR addr;
+ GDB_FILE *stream;
+{
+ print_address_numeric (addr, 1, stream);
+ print_address_symbolic (addr, stream, asm_demangle, " ");
+}
+
+/* Print address ADDR symbolically on STREAM. Parameter DEMANGLE
+ controls whether to print the symbolic name "raw" or demangled.
+ Global setting "addressprint" controls whether to print hex address
+ or not. */
+
+void
+print_address_demangle (addr, stream, do_demangle)
+ CORE_ADDR addr;
+ GDB_FILE *stream;
+ int do_demangle;
+{
+ if (addr == 0)
+ {
+ fprintf_filtered (stream, "0");
+ }
+ else if (addressprint)
+ {
+ print_address_numeric (addr, 1, stream);
+ 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_i_type;
+
+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 gdb_stdout. */
+
+static void
+do_examine (fmt, addr, sect)
+ struct format_data fmt;
+ CORE_ADDR addr;
+ asection *sect;
+{
+ register char format = 0;
+ register char size;
+ register int count = 1;
+ struct type *val_type = NULL;
+ register int i;
+ register int maxelts;
+
+ format = fmt.format;
+ size = fmt.size;
+ count = fmt.count;
+ next_address = addr;
+ next_section = sect;
+
+ /* String or instruction format implies fetch single bytes
+ regardless of the specified size. */
+ if (format == 's' || format == 'i')
+ size = 'b';
+
+ if (format == 'i')
+ val_type = examine_i_type;
+ else if (size == 'b')
+ val_type = examine_b_type;
+ else if (size == 'h')
+ val_type = examine_h_type;
+ else if (size == 'w')
+ val_type = examine_w_type;
+ else if (size == 'g')
+ val_type = examine_g_type;
+
+ maxelts = 8;
+ if (size == 'w')
+ maxelts = 4;
+ if (size == 'g')
+ maxelts = 2;
+ if (format == 's' || format == 'i')
+ maxelts = 1;
+
+ /* Print as many objects as specified in COUNT, at most maxelts per line,
+ with the address of the next one at the start of each line. */
+
+ while (count > 0)
+ {
+ QUIT;
+ print_address (next_address, gdb_stdout);
+ printf_filtered (":");
+ for (i = maxelts;
+ i > 0 && count > 0;
+ i--, count--)
+ {
+ printf_filtered ("\t");
+ /* Note that print_formatted sets next_address for the next
+ object. */
+ last_examine_address = next_address;
+
+ if (last_examine_value)
+ value_free (last_examine_value);
+
+ /* The value to be displayed is not fetched greedily.
+ Instead, to avoid the posibility of a fetched value not
+ being used, its retreval is delayed until the print code
+ uses it. When examining an instruction stream, the
+ disassembler will perform its own memory fetch using just
+ the address stored in LAST_EXAMINE_VALUE. FIXME: Should
+ the disassembler be modified so that LAST_EXAMINE_VALUE
+ is left with the byte sequence from the last complete
+ instruction fetched from memory? */
+ last_examine_value = value_at_lazy (val_type, next_address, sect);
+
+ if (last_examine_value)
+ release_value (last_examine_value);
+
+ print_formatted (last_examine_value, format, size);
+ }
+ printf_filtered ("\n");
+ gdb_flush (gdb_stdout);
+ }
+}
+
+static void
+validate_format (fmt, cmdname)
+ struct format_data fmt;
+ char *cmdname;
+{
+ if (fmt.size != 0)
+ error ("Size letters are meaningless in \"%s\" command.", cmdname);
+ if (fmt.count != 1)
+ error ("Item count other than 1 is meaningless in \"%s\" command.",
+ cmdname);
+ if (fmt.format == 'i' || fmt.format == 's')
+ error ("Format letter \"%c\" is meaningless in \"%s\" command.",
+ fmt.format, cmdname);
+}
+
+/* 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_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_ptr val;
+ struct format_data fmt;
+ int cleanup = 0;
+
+ /* Pass inspect flag to the rest of the print routines in a global (sigh). */
+ inspect_it = inspect;
+
+ if (exp && *exp == '/')
+ {
+ exp++;
+ fmt = decode_format (&exp, last_format, 0);
+ validate_format (fmt, "print");
+ last_format = format = fmt.format;
+ }
+ else
+ {
+ fmt.count = 1;
+ fmt.format = 0;
+ fmt.size = 0;
+ }
+
+ if (exp && *exp)
+ {
+ extern int objectprint;
+ struct type *type;
+ expr = parse_expression (exp);
+ old_chain = make_cleanup ((make_cleanup_func) 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_ptr 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);
+
+ if (voidprint || (val && VALUE_TYPE (val) &&
+ TYPE_CODE (VALUE_TYPE (val)) != TYPE_CODE_VOID))
+ {
+ int histindex = record_latest_value (val);
+
+ if (histindex >= 0)
+ annotate_value_history_begin (histindex, VALUE_TYPE (val));
+ else
+ annotate_value_begin (VALUE_TYPE (val));
+
+ if (inspect)
+ printf_unfiltered ("\031(gdb-makebuffer \"%s\" %d '(\"", exp, histindex);
+ else
+ if (histindex >= 0) printf_filtered ("$%d = ", histindex);
+
+ if (histindex >= 0)
+ annotate_value_history_value ();
+
+ print_formatted (val, format, fmt.size);
+ printf_filtered ("\n");
+
+ if (histindex >= 0)
+ annotate_value_history_end ();
+ else
+ annotate_value_end ();
+
+ if (inspect)
+ printf_unfiltered("\") )\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 */
+void
+output_command (exp, from_tty)
+ char *exp;
+ int from_tty;
+{
+ struct expression *expr;
+ register struct cleanup *old_chain;
+ register char format = 0;
+ register value_ptr val;
+ struct format_data fmt;
+
+ if (exp && *exp == '/')
+ {
+ exp++;
+ fmt = decode_format (&exp, 0, 0);
+ validate_format (fmt, "output");
+ format = fmt.format;
+ }
+
+ expr = parse_expression (exp);
+ old_chain = make_cleanup ((make_cleanup_func) free_current_contents, &expr);
+
+ val = evaluate_expression (expr);
+
+ annotate_value_begin (VALUE_TYPE (val));
+
+ print_formatted (val, format, fmt.size);
+
+ annotate_value_end ();
+
+ do_cleanups (old_chain);
+}
+
+/* ARGSUSED */
+static void
+set_command (exp, from_tty)
+ char *exp;
+ int from_tty;
+{
+ struct expression *expr = parse_expression (exp);
+ register struct cleanup *old_chain
+ = make_cleanup ((make_cleanup_func) free_current_contents, &expr);
+ evaluate_expression (expr);
+ do_cleanups (old_chain);
+}
+
+/* ARGSUSED */
+static void
+sym_info (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ struct minimal_symbol *msymbol;
+ struct objfile *objfile;
+ struct obj_section *osect;
+ asection *sect;
+ CORE_ADDR addr, sect_addr;
+ int matches = 0;
+ unsigned int offset;
+
+ if (!arg)
+ error_no_arg ("address");
+
+ addr = parse_and_eval_address (arg);
+ ALL_OBJSECTIONS (objfile, osect)
+ {
+ sect = osect->the_bfd_section;
+ sect_addr = overlay_mapped_address (addr, sect);
+
+ if (osect->addr <= sect_addr && sect_addr < osect->endaddr &&
+ (msymbol = lookup_minimal_symbol_by_pc_section (sect_addr, sect)))
+ {
+ matches = 1;
+ offset = sect_addr - SYMBOL_VALUE_ADDRESS (msymbol);
+ if (offset)
+ printf_filtered ("%s + %u in ",
+ SYMBOL_SOURCE_NAME (msymbol), offset);
+ else
+ printf_filtered ("%s in ",
+ SYMBOL_SOURCE_NAME (msymbol));
+ if (pc_in_unmapped_range (addr, sect))
+ printf_filtered ("load address range of ");
+ if (section_is_overlay (sect))
+ printf_filtered ("%s overlay ",
+ section_is_mapped (sect) ? "mapped" : "unmapped");
+ printf_filtered ("section %s", sect->name);
+ printf_filtered ("\n");
+ }
+ }
+ if (matches == 0)
+ printf_filtered ("No symbol matches %s.\n", arg);
+}
+
+/* ARGSUSED */
+static void
+address_info (exp, from_tty)
+ char *exp;
+ int from_tty;
+{
+ register struct symbol *sym;
+ register struct minimal_symbol *msymbol;
+ register long val;
+ register long basereg;
+ asection *section;
+ CORE_ADDR load_addr;
+ int is_a_field_of_this; /* C++: lookup_symbol sets this to nonzero
+ if exp is a field of `this'. */
+
+ if (exp == 0)
+ error ("Argument required.");
+
+ sym = lookup_symbol (exp, get_selected_block (), VAR_NAMESPACE,
+ &is_a_field_of_this, (struct symtab **)NULL);
+ if (sym == NULL)
+ {
+ if (is_a_field_of_this)
+ {
+ printf_filtered ("Symbol \"");
+ fprintf_symbol_filtered (gdb_stdout, exp,
+ current_language->la_language, DMGL_ANSI);
+ printf_filtered ("\" is a field of the local class variable `this'\n");
+ return;
+ }
+
+ msymbol = lookup_minimal_symbol (exp, NULL, NULL);
+
+ if (msymbol != NULL)
+ {
+ load_addr = SYMBOL_VALUE_ADDRESS (msymbol);
+
+ printf_filtered ("Symbol \"");
+ fprintf_symbol_filtered (gdb_stdout, exp,
+ current_language->la_language, DMGL_ANSI);
+ printf_filtered ("\" is at ");
+ print_address_numeric (load_addr, 1, gdb_stdout);
+ printf_filtered (" in a file compiled without debugging");
+ section = SYMBOL_BFD_SECTION (msymbol);
+ if (section_is_overlay (section))
+ {
+ load_addr = overlay_unmapped_address (load_addr, section);
+ printf_filtered (",\n -- loaded at ");
+ print_address_numeric (load_addr, 1, gdb_stdout);
+ printf_filtered (" in overlay section %s", section->name);
+ }
+ printf_filtered (".\n");
+ }
+ else
+ error ("No symbol \"%s\" in current context.", exp);
+ return;
+ }
+
+ printf_filtered ("Symbol \"");
+ fprintf_symbol_filtered (gdb_stdout, SYMBOL_NAME (sym),
+ current_language->la_language, DMGL_ANSI);
+ printf_filtered ("\" is ");
+ val = SYMBOL_VALUE (sym);
+ basereg = SYMBOL_BASEREG (sym);
+ section = SYMBOL_BFD_SECTION (sym);
+
+ switch (SYMBOL_CLASS (sym))
+ {
+ case LOC_CONST:
+ case LOC_CONST_BYTES:
+ printf_filtered ("constant");
+ break;
+
+ case LOC_LABEL:
+ printf_filtered ("a label at address ");
+ print_address_numeric (load_addr = SYMBOL_VALUE_ADDRESS (sym),
+ 1, gdb_stdout);
+ if (section_is_overlay (section))
+ {
+ load_addr = overlay_unmapped_address (load_addr, section);
+ printf_filtered (",\n -- loaded at ");
+ print_address_numeric (load_addr, 1, gdb_stdout);
+ printf_filtered (" in overlay section %s", section->name);
+ }
+ break;
+
+ case LOC_REGISTER:
+ printf_filtered ("a variable in register %s", REGISTER_NAME (val));
+ break;
+
+ case LOC_STATIC:
+ printf_filtered ("static storage at address ");
+ print_address_numeric (load_addr = SYMBOL_VALUE_ADDRESS (sym),
+ 1, gdb_stdout);
+ if (section_is_overlay (section))
+ {
+ load_addr = overlay_unmapped_address (load_addr, section);
+ printf_filtered (",\n -- loaded at ");
+ print_address_numeric (load_addr, 1, gdb_stdout);
+ printf_filtered (" in overlay section %s", section->name);
+ }
+ break;
+
+ case LOC_INDIRECT:
+ printf_filtered ("external global (indirect addressing), at address *(");
+ print_address_numeric (load_addr = SYMBOL_VALUE_ADDRESS (sym),
+ 1, gdb_stdout);
+ printf_filtered (")");
+ if (section_is_overlay (section))
+ {
+ load_addr = overlay_unmapped_address (load_addr, section);
+ printf_filtered (",\n -- loaded at ");
+ print_address_numeric (load_addr, 1, gdb_stdout);
+ printf_filtered (" in overlay section %s", section->name);
+ }
+ break;
+
+ case LOC_REGPARM:
+ printf_filtered ("an argument in register %s", REGISTER_NAME (val));
+ break;
+
+ case LOC_REGPARM_ADDR:
+ printf_filtered ("address of an argument in register %s", REGISTER_NAME (val));
+ break;
+
+ case LOC_ARG:
+ printf_filtered ("an argument at offset %ld", val);
+ break;
+
+ case LOC_LOCAL_ARG:
+ printf_filtered ("an argument at frame offset %ld", val);
+ break;
+
+ case LOC_LOCAL:
+ printf_filtered ("a local variable at frame offset %ld", val);
+ break;
+
+ case LOC_REF_ARG:
+ printf_filtered ("a reference argument at offset %ld", val);
+ break;
+
+ case LOC_BASEREG:
+ printf_filtered ("a variable at offset %ld from register %s",
+ val, REGISTER_NAME (basereg));
+ break;
+
+ case LOC_BASEREG_ARG:
+ printf_filtered ("an argument at offset %ld from register %s",
+ val, REGISTER_NAME (basereg));
+ break;
+
+ case LOC_TYPEDEF:
+ printf_filtered ("a typedef");
+ break;
+
+ case LOC_BLOCK:
+ printf_filtered ("a function at address ");
+#ifdef GDB_TARGET_MASK_DISAS_PC
+ print_address_numeric
+ (load_addr= GDB_TARGET_MASK_DISAS_PC (BLOCK_START (SYMBOL_BLOCK_VALUE (sym))),
+ 1, gdb_stdout);
+#else
+ print_address_numeric (load_addr=BLOCK_START (SYMBOL_BLOCK_VALUE (sym)),
+ 1, gdb_stdout);
+#endif
+ if (section_is_overlay (section))
+ {
+ load_addr = overlay_unmapped_address (load_addr, section);
+ printf_filtered (",\n -- loaded at ");
+ print_address_numeric (load_addr, 1, gdb_stdout);
+ printf_filtered (" in overlay section %s", section->name);
+ }
+ break;
+
+ case LOC_UNRESOLVED:
+ {
+ struct minimal_symbol *msym;
+
+ msym = lookup_minimal_symbol (SYMBOL_NAME (sym), NULL, NULL);
+ if (msym == NULL)
+ printf_filtered ("unresolved");
+ else
+ {
+ section = SYMBOL_BFD_SECTION (msym);
+ printf_filtered ("static storage at address ");
+ print_address_numeric (load_addr = SYMBOL_VALUE_ADDRESS (msym),
+ 1, gdb_stdout);
+ if (section_is_overlay (section))
+ {
+ load_addr = overlay_unmapped_address (load_addr, section);
+ printf_filtered (",\n -- loaded at ");
+ print_address_numeric (load_addr, 1, gdb_stdout);
+ printf_filtered (" in overlay section %s", section->name);
+ }
+ }
+ }
+ break;
+
+ case LOC_THREAD_LOCAL_STATIC:
+ printf_filtered (
+ "a thread-local variable at offset %ld from the thread base register %s",
+ val, REGISTER_NAME (basereg));
+ break;
+
+ case LOC_OPTIMIZED_OUT:
+ printf_filtered ("optimized out");
+ break;
+
+ default:
+ printf_filtered ("of unknown (botched) type");
+ break;
+ }
+ printf_filtered (".\n");
+}
+
+void
+x_command (exp, from_tty)
+ char *exp;
+ int from_tty;
+{
+ struct expression *expr;
+ struct format_data fmt;
+ struct cleanup *old_chain;
+ struct value *val;
+
+ fmt.format = last_format;
+ fmt.size = last_size;
+ fmt.count = 1;
+
+ if (exp && *exp == '/')
+ {
+ exp++;
+ fmt = decode_format (&exp, last_format, last_size);
+ }
+
+ /* If we have an expression, evaluate it and use it as the address. */
+
+ if (exp != 0 && *exp != 0)
+ {
+ 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. */
+ if (from_tty)
+ *exp = 0;
+ old_chain = make_cleanup ((make_cleanup_func) 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'
+ && */ TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_FUNC
+ && VALUE_LVAL (val) == lval_memory)
+ next_address = VALUE_ADDRESS (val);
+ else
+ next_address = value_as_pointer (val);
+ if (VALUE_BFD_SECTION (val))
+ next_section = VALUE_BFD_SECTION (val);
+ do_cleanups (old_chain);
+ }
+
+ do_examine (fmt, next_address, next_section);
+
+ /* 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 $_. Use
+ the correct pointer type. */
+ set_internalvar (lookup_internalvar ("_"),
+ 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 $__.*/
+ /* If the last value has not been fetched from memory then don't
+ fetch it now - instead mark it by voiding the $__ variable. */
+ if (VALUE_LAZY (last_examine_value))
+ set_internalvar (lookup_internalvar ("__"),
+ allocate_value (builtin_type_void));
+ else
+ set_internalvar (lookup_internalvar ("__"), last_examine_value);
+ }
+}
+
+
+/* Add an expression to the auto-display chain.
+ Specify the expression. */
+
+static void
+display_command (exp, from_tty)
+ char *exp;
+ int from_tty;
+{
+ struct format_data fmt;
+ register struct expression *expr;
+ register struct display *new;
+ int display_it = 1;
+
+#if defined(TUI)
+ if (tui_version && *exp == '$')
+ display_it = ((TuiStatus)tuiDo(
+ (TuiOpaqueFuncPtr)tui_vSetLayoutTo, exp) == TUI_FAILURE);
+#endif
+
+ if (display_it)
+ {
+ if (exp == 0)
+ {
+ do_displays ();
+ return;
+ }
+
+ if (*exp == '/')
+ {
+ exp++;
+ fmt = decode_format (&exp, 0, 0);
+ if (fmt.size && fmt.format == 0)
+ fmt.format = 'x';
+ if (fmt.format == 'i' || fmt.format == 's')
+ fmt.size = 'b';
+ }
+ else
+ {
+ fmt.format = 0;
+ fmt.size = 0;
+ fmt.count = 0;
+ }
+
+ innermost_block = 0;
+ expr = parse_expression (exp);
+
+ new = (struct display *) xmalloc (sizeof (struct display));
+
+ new->exp = expr;
+ new->block = innermost_block;
+ new->next = display_chain;
+ new->number = ++display_number;
+ new->format = fmt;
+ new->status = enabled;
+ display_chain = new;
+
+ if (from_tty && target_has_execution)
+ do_one_display (new);
+
+ dont_repeat ();
+ }
+}
+
+static void
+free_display (d)
+ struct display *d;
+{
+ free ((PTR)d->exp);
+ free ((PTR)d);
+}
+
+/* Clear out the display_chain.
+ Done when new symtabs are loaded, since this invalidates
+ the types stored in many expressions. */
+
+void
+clear_displays ()
+{
+ register struct display *d;
+
+ while ((d = display_chain) != NULL)
+ {
+ free ((PTR)d->exp);
+ display_chain = d->next;
+ free ((PTR)d);
+ }
+}
+
+/* Delete the auto-display number NUM. */
+
+static void
+delete_display (num)
+ int num;
+{
+ register struct display *d1, *d;
+
+ if (!display_chain)
+ error ("No display number %d.", num);
+
+ if (display_chain->number == num)
+ {
+ d1 = display_chain;
+ display_chain = d1->next;
+ free_display (d1);
+ }
+ else
+ for (d = display_chain; ; d = d->next)
+ {
+ if (d->next == 0)
+ error ("No display number %d.", num);
+ if (d->next->number == num)
+ {
+ d1 = d->next;
+ d->next = d1->next;
+ free_display (d1);
+ break;
+ }
+ }
+}
+
+/* Delete some values from the auto-display chain.
+ Specify the element numbers. */
+
+static void
+undisplay_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ register char *p = args;
+ register char *p1;
+ register int num;
+
+ if (args == 0)
+ {
+ if (query ("Delete all auto-display expressions? "))
+ clear_displays ();
+ dont_repeat ();
+ return;
+ }
+
+ while (*p)
+ {
+ p1 = p;
+ while (*p1 >= '0' && *p1 <= '9') p1++;
+ if (*p1 && *p1 != ' ' && *p1 != '\t')
+ error ("Arguments must be display numbers.");
+
+ num = atoi (p);
+
+ delete_display (num);
+
+ p = p1;
+ while (*p == ' ' || *p == '\t') p++;
+ }
+ dont_repeat ();
+}
+
+/* Display a single auto-display.
+ Do nothing if the display cannot be printed in the current context,
+ or if the display is disabled. */
+
+static void
+do_one_display (d)
+ struct display *d;
+{
+ int within_current_scope;
+
+ if (d->status == disabled)
+ return;
+
+ if (d->block)
+ within_current_scope = contained_in (get_selected_block (), d->block);
+ else
+ within_current_scope = 1;
+ if (!within_current_scope)
+ return;
+
+ current_display_number = d->number;
+
+ annotate_display_begin ();
+ printf_filtered ("%d", d->number);
+ annotate_display_number_end ();
+ printf_filtered (": ");
+ if (d->format.size)
+ {
+ CORE_ADDR addr;
+ value_ptr val;
+
+ annotate_display_format ();
+
+ printf_filtered ("x/");
+ if (d->format.count != 1)
+ printf_filtered ("%d", d->format.count);
+ printf_filtered ("%c", d->format.format);
+ if (d->format.format != 'i' && d->format.format != 's')
+ printf_filtered ("%c", d->format.size);
+ printf_filtered (" ");
+
+ annotate_display_expression ();
+
+ print_expression (d->exp, gdb_stdout);
+ annotate_display_expression_end ();
+
+ if (d->format.count != 1)
+ printf_filtered ("\n");
+ else
+ printf_filtered (" ");
+
+ val = evaluate_expression (d->exp);
+ addr = value_as_pointer (val);
+ if (d->format.format == 'i')
+ addr = ADDR_BITS_REMOVE (addr);
+
+ annotate_display_value ();
+
+ do_examine (d->format, addr, VALUE_BFD_SECTION (val));
+ }
+ else
+ {
+ annotate_display_format ();
+
+ if (d->format.format)
+ printf_filtered ("/%c ", d->format.format);
+
+ annotate_display_expression ();
+
+ print_expression (d->exp, gdb_stdout);
+ annotate_display_expression_end ();
+
+ printf_filtered (" = ");
+
+ annotate_display_expression ();
+
+ print_formatted (evaluate_expression (d->exp),
+ d->format.format, d->format.size);
+ printf_filtered ("\n");
+ }
+
+ annotate_display_end ();
+
+ gdb_flush (gdb_stdout);
+ current_display_number = -1;
+}
+
+/* Display all of the values on the auto-display chain which can be
+ evaluated in the current scope. */
+
+void
+do_displays ()
+{
+ register struct display *d;
+
+ for (d = display_chain; d; d = d->next)
+ do_one_display (d);
+}
+
+/* Delete the auto-display which we were in the process of displaying.
+ This is done when there is an error or a signal. */
+
+void
+disable_display (num)
+ int num;
+{
+ register struct display *d;
+
+ for (d = display_chain; d; d = d->next)
+ if (d->number == num)
+ {
+ d->status = disabled;
+ return;
+ }
+ printf_unfiltered ("No display number %d.\n", num);
+}
+
+void
+disable_current_display ()
+{
+ if (current_display_number >= 0)
+ {
+ disable_display (current_display_number);
+ fprintf_unfiltered (gdb_stderr, "Disabling display %d to avoid infinite recursion.\n",
+ current_display_number);
+ }
+ current_display_number = -1;
+}
+
+static void
+display_info (ignore, from_tty)
+ char *ignore;
+ int from_tty;
+{
+ register struct display *d;
+
+ if (!display_chain)
+ printf_unfiltered ("There are no auto-display expressions now.\n");
+ else
+ printf_filtered ("Auto-display expressions now in effect:\n\
+Num Enb Expression\n");
+
+ for (d = display_chain; d; d = d->next)
+ {
+ printf_filtered ("%d: %c ", d->number, "ny"[(int)d->status]);
+ if (d->format.size)
+ printf_filtered ("/%d%c%c ", d->format.count, d->format.size,
+ d->format.format);
+ else if (d->format.format)
+ printf_filtered ("/%c ", d->format.format);
+ print_expression (d->exp, gdb_stdout);
+ if (d->block && !contained_in (get_selected_block (), d->block))
+ printf_filtered (" (cannot be evaluated in the current context)");
+ printf_filtered ("\n");
+ gdb_flush (gdb_stdout);
+ }
+}
+
+static void
+enable_display (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)
+ {
+ for (d = display_chain; d; d = d->next)
+ d->status = enabled;
+ }
+ else
+ while (*p)
+ {
+ p1 = p;
+ while (*p1 >= '0' && *p1 <= '9')
+ p1++;
+ if (*p1 && *p1 != ' ' && *p1 != '\t')
+ error ("Arguments must be display numbers.");
+
+ num = atoi (p);
+
+ for (d = display_chain; d; d = d->next)
+ if (d->number == num)
+ {
+ d->status = enabled;
+ goto win;
+ }
+ printf_unfiltered ("No display number %d.\n", num);
+ win:
+ p = p1;
+ while (*p == ' ' || *p == '\t')
+ p++;
+ }
+}
+
+/* ARGSUSED */
+static void
+disable_display_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ register char *p = args;
+ register char *p1;
+ register struct display *d;
+
+ if (p == 0)
+ {
+ for (d = display_chain; d; d = d->next)
+ d->status = disabled;
+ }
+ else
+ while (*p)
+ {
+ p1 = p;
+ while (*p1 >= '0' && *p1 <= '9')
+ p1++;
+ if (*p1 && *p1 != ' ' && *p1 != '\t')
+ error ("Arguments must be display numbers.");
+
+ disable_display (atoi (p));
+
+ p = p1;
+ while (*p == ' ' || *p == '\t')
+ p++;
+ }
+}
+
+
+/* Print the value in stack frame FRAME of a variable
+ specified by a struct symbol. */
+
+void
+print_variable_value (var, frame, stream)
+ struct symbol *var;
+ struct frame_info *frame;
+ GDB_FILE *stream;
+{
+ value_ptr val = read_var_value (var, frame);
+
+ value_print (val, stream, 0, Val_pretty_default);
+}
+
+/* Print the arguments of a stack frame, given the function FUNC
+ running in that frame (as a symbol), the info on the frame,
+ and the number of args according to the stack frame (or -1 if unknown). */
+
+/* References here and elsewhere to "number of args according to the
+ stack frame" appear in all cases to refer to "number of ints of args
+ according to the stack frame". At least for VAX, i386, isi. */
+
+void
+print_frame_args (func, fi, num, stream)
+ struct symbol *func;
+ struct frame_info *fi;
+ int num;
+ GDB_FILE *stream;
+{
+ struct block *b = NULL;
+ int nsyms = 0;
+ int first = 1;
+ register int i;
+ register struct symbol *sym;
+ register value_ptr val;
+ /* Offset of next stack argument beyond the one we have seen that is
+ at the highest offset.
+ -1 if we haven't come to a stack argument yet. */
+ long highest_offset = -1;
+ int arg_size;
+ /* Number of ints of arguments that we have printed so far. */
+ int args_printed = 0;
+
+ if (func)
+ {
+ b = SYMBOL_BLOCK_VALUE (func);
+ nsyms = BLOCK_NSYMS (b);
+ }
+
+ for (i = 0; i < nsyms; i++)
+ {
+ QUIT;
+ sym = BLOCK_SYM (b, i);
+
+ /* Keep track of the highest stack argument offset seen, and
+ skip over any kinds of symbols we don't care about. */
+
+ switch (SYMBOL_CLASS (sym)) {
+ case LOC_ARG:
+ case LOC_REF_ARG:
+ {
+ long current_offset = SYMBOL_VALUE (sym);
+ arg_size = TYPE_LENGTH (SYMBOL_TYPE (sym));
+
+ /* Compute address of next argument by adding the size of
+ this argument and rounding to an int boundary. */
+ current_offset
+ = ((current_offset + arg_size + sizeof (int) - 1)
+ & ~(sizeof (int) - 1));
+
+ /* If this is the highest offset seen yet, set highest_offset. */
+ if (highest_offset == -1
+ || (current_offset > highest_offset))
+ highest_offset = current_offset;
+
+ /* Add the number of ints we're about to print to args_printed. */
+ args_printed += (arg_size + sizeof (int) - 1) / sizeof (int);
+ }
+
+ /* 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). */
+ /* 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))
+ {
+ struct symbol *nsym;
+ nsym = lookup_symbol
+ (SYMBOL_NAME (sym),
+ b, VAR_NAMESPACE, (int *)NULL, (struct symtab **)NULL);
+ if (SYMBOL_CLASS (nsym) == LOC_REGISTER)
+ {
+ /* There is a LOC_ARG/LOC_REGISTER pair. This means that
+ it was passed on the stack and loaded into a register,
+ or passed in a register and stored in a stack slot.
+ GDB 3.x used the LOC_ARG; GDB 4.0-4.11 used the LOC_REGISTER.
+
+ Reasons for using the LOC_ARG:
+ (1) because find_saved_registers may be slow for remote
+ debugging,
+ (2) because registers are often re-used and stack slots
+ rarely (never?) are. Therefore using the stack slot is
+ much less likely to print garbage.
+
+ Reasons why we might want to use the LOC_REGISTER:
+ (1) So that the backtrace prints the same value as
+ "print foo". I see no compelling reason why this needs
+ to be the case; having the backtrace print the value which
+ was passed in, and "print foo" print the value as modified
+ within the called function, makes perfect sense to me.
+
+ Additional note: It might be nice if "info args" displayed
+ both values.
+ One more note: There is a case with sparc structure passing
+ where we need to use the LOC_REGISTER, but this is dealt with
+ by creating a single LOC_REGPARM in symbol reading. */
+
+ /* Leave sym (the LOC_ARG) alone. */
+ ;
+ }
+ else
+ sym = nsym;
+ }
+
+ /* Print the current arg. */
+ if (! first)
+ fprintf_filtered (stream, ", ");
+ wrap_here (" ");
+
+ annotate_arg_begin ();
+
+ fprintf_symbol_filtered (stream, SYMBOL_SOURCE_NAME (sym),
+ SYMBOL_LANGUAGE (sym), DMGL_PARAMS | DMGL_ANSI);
+ annotate_arg_name_end ();
+ fputs_filtered ("=", stream);
+
+ /* Avoid value_print because it will deref ref parameters. We just
+ want to print their addresses. Print ??? for args whose address
+ we do not know. 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, fi);
+
+ annotate_arg_value (val == NULL ? NULL : VALUE_TYPE (val));
+
+ if (val)
+ {
+#ifdef GDB_TARGET_IS_D10V
+ if (SYMBOL_CLASS(sym) == LOC_REGPARM && TYPE_CODE(VALUE_TYPE(val)) == TYPE_CODE_PTR)
+ TYPE_LENGTH(VALUE_TYPE(val)) = 2;
+#endif
+ val_print (VALUE_TYPE (val), VALUE_CONTENTS (val), 0,
+ VALUE_ADDRESS (val),
+ stream, 0, 0, 2, Val_no_prettyprint);
+ }
+ else
+ fputs_filtered ("???", stream);
+
+ annotate_arg_end ();
+
+ first = 0;
+ }
+
+ /* Don't print nameless args in situations where we don't know
+ enough about the stack to find them. */
+ if (num != -1)
+ {
+ 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, start, num, first, stream)
+ struct frame_info *fi;
+ long start;
+ int num;
+ int first;
+ GDB_FILE *stream;
+{
+ 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
+ argsaddr = FRAME_ARGS_ADDRESS (fi);
+ if (!argsaddr)
+ return;
+
+ arg_value = read_memory_integer (argsaddr + start, sizeof (int));
+#endif
+
+ 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, "%ld", arg_value);
+#endif /* PRINT_TYPELESS_INTEGER */
+#endif /* PRINT_NAMELESS_INTEGER */
+ first = 0;
+ start += sizeof (int);
+ }
+}
+
+/* ARGSUSED */
+static void
+printf_command (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ register char *f = NULL;
+ register char *s = arg;
+ char *string = NULL;
+ value_ptr *val_args;
+ char *substrings;
+ char *current_substring;
+ int nargs = 0;
+ int allocated_args = 20;
+ struct cleanup *old_cleanups;
+
+ val_args = (value_ptr *) xmalloc (allocated_args * sizeof (value_ptr));
+ old_cleanups = make_cleanup ((make_cleanup_func) free_current_contents,
+ &val_args);
+
+ if (s == 0)
+ error_no_arg ("format-control string and values to print");
+
+ /* Skip white space before format string */
+ while (*s == ' ' || *s == '\t') s++;
+
+ /* A format string should follow, enveloped in double quotes */
+ if (*s++ != '"')
+ error ("Bad format string, missing '\"'.");
+
+ /* Parse the format-control string and copy it into the string STRING,
+ processing some kinds of escape sequence. */
+
+ f = string = (char *) alloca (strlen (s) + 1);
+
+ while (*s != '"')
+ {
+ int c = *s++;
+ switch (c)
+ {
+ case '\0':
+ error ("Bad format string, non-terminated '\"'.");
+
+ case '\\':
+ switch (c = *s++)
+ {
+ case '\\':
+ *f++ = '\\';
+ break;
+ case 'a':
+#ifdef __STDC__
+ *f++ = '\a';
+#else
+ *f++ = '\007'; /* Bell */
+#endif
+ break;
+ case 'b':
+ *f++ = '\b';
+ break;
+ case 'f':
+ *f++ = '\f';
+ break;
+ case 'n':
+ *f++ = '\n';
+ break;
+ case 'r':
+ *f++ = '\r';
+ break;
+ case 't':
+ *f++ = '\t';
+ break;
+ case 'v':
+ *f++ = '\v';
+ break;
+ case '"':
+ *f++ = '"';
+ break;
+ default:
+ /* ??? TODO: handle other escape sequences */
+ error ("Unrecognized escape character \\%c in format string.",
+ c);
+ }
+ break;
+
+ default:
+ *f++ = c;
+ }
+ }
+
+ /* Skip over " and following space and comma. */
+ s++;
+ *f++ = '\0';
+ while (*s == ' ' || *s == '\t') s++;
+
+ if (*s != ',' && *s != 0)
+ error ("Invalid argument syntax");
+
+ if (*s == ',') s++;
+ while (*s == ' ' || *s == '\t') s++;
+
+ /* 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 printf_filtered
+ something of the right size. */
+
+ 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 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 (strchr ("0123456789.hlL-+ #", *f))
+ {
+ if (*f == 'l' || *f == 'L')
+ lcount++;
+ f++;
+ }
+ 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_ptr *) xrealloc ((char *) val_args,
+ (allocated_args *= 2)
+ * sizeof (value_ptr));
+ s1 = s;
+ val_args[nargs] = parse_to_comma_and_eval (&s1);
+
+ /* If format string wants a float, unchecked-convert the value to
+ floating point of the same size */
+
+ if (argclass[nargs] == double_arg)
+ {
+ struct type *type = VALUE_TYPE (val_args[nargs]);
+ if (TYPE_LENGTH (type) == sizeof (float))
+ VALUE_TYPE (val_args[nargs]) = builtin_type_float;
+ if (TYPE_LENGTH (type) == sizeof (double))
+ VALUE_TYPE (val_args[nargs]) = builtin_type_double;
+ }
+ nargs++;
+ s = s1;
+ if (*s == ',')
+ s++;
+ }
+
+ if (nargs != nargs_wanted)
+ error ("Wrong number of arguments for specified format-string");
+
+ /* Now actually print them. */
+ current_substring = substrings;
+ for (i = 0; i < nargs; i++)
+ {
+ switch (argclass[i])
+ {
+ case string_arg:
+ {
+ 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_section (tem + j, &c, 1,
+ VALUE_BFD_SECTION (val_args[i]));
+ if (c == 0)
+ break;
+ }
+
+ /* Copy the string contents into a string inside GDB. */
+ str = (char *) alloca (j + 1);
+ read_memory_section (tem, str, j, VALUE_BFD_SECTION (val_args[i]));
+ str[j] = 0;
+
+ printf_filtered (current_substring, str);
+ }
+ break;
+ case double_arg:
+ {
+ double val = value_as_double (val_args[i]);
+ printf_filtered (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]);
+ printf_filtered (current_substring, val);
+ break;
+ }
+#else
+ error ("long long not supported in printf");
+#endif
+ case int_arg:
+ {
+ /* FIXME: there should be separate int_arg and long_arg. */
+ long val = value_as_long (val_args[i]);
+ printf_filtered (current_substring, val);
+ break;
+ }
+ default: /* purecov: deadcode */
+ error ("internal error in printf_command"); /* purecov: deadcode */
+ }
+ /* Skip to the next substring. */
+ current_substring += strlen (current_substring) + 1;
+ }
+ /* Print the portion of the format string after the last argument. */
+ printf_filtered (last_arg);
+ }
+ do_cleanups (old_cleanups);
+}
+
+/* Dump a specified section of assembly code. With no command line
+ arguments, this command will dump the assembly code for the
+ function surrounding the pc value in the selected frame. With one
+ argument, it will dump the assembly code surrounding that pc value.
+ Two arguments are interpeted as bounds within which to dump
+ assembly. */
+
+/* ARGSUSED */
+static void
+disassemble_command (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ CORE_ADDR low, high;
+ char *name;
+ CORE_ADDR pc, pc_masked;
+ char *space_index;
+#if 0
+ asection *section;
+#endif
+
+ name = NULL;
+ if (!arg)
+ {
+ if (!selected_frame)
+ error ("No frame selected.\n");
+
+ 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");
+#if defined(TUI)
+ else if (tui_version)
+ low = (CORE_ADDR)tuiDo((TuiOpaqueFuncPtr)tui_vGetLowDisassemblyAddress,
+ (Opaque)low,
+ (Opaque)pc);
+#endif
+ low += FUNCTION_START_OFFSET;
+ }
+ else if (!(space_index = (char *) strchr (arg, ' ')))
+ {
+ /* One argument. */
+ pc = parse_and_eval_address (arg);
+ if (find_pc_partial_function (pc, &name, &low, &high) == 0)
+ error ("No function contains specified address.\n");
+#if defined(TUI)
+ else if (tui_version)
+ low = (CORE_ADDR)tuiDo((TuiOpaqueFuncPtr)tui_vGetLowDisassemblyAddress,
+ (Opaque)low,
+ (Opaque)pc);
+#endif
+#if 0
+ if (overlay_debugging)
+ {
+ section = find_pc_overlay (pc);
+ if (pc_in_unmapped_range (pc, section))
+ {
+ /* find_pc_partial_function will have returned low and high
+ relative to the symbolic (mapped) address range. Need to
+ translate them back to the unmapped range where PC is. */
+ low = overlay_unmapped_address (low, section);
+ high = overlay_unmapped_address (high, section);
+ }
+ }
+#endif
+ low += FUNCTION_START_OFFSET;
+ }
+ else
+ {
+ /* Two arguments. */
+ *space_index = '\0';
+ low = parse_and_eval_address (arg);
+ high = parse_and_eval_address (space_index + 1);
+ }
+
+#if defined(TUI)
+ if (!tui_version ||
+ m_winPtrIsNull(disassemWin) || !disassemWin->generic.isVisible)
+#endif
+ {
+ printf_filtered ("Dump of assembler code ");
+ if (name != NULL)
+ {
+ printf_filtered ("for function %s:\n", name);
+ }
+ else
+ {
+ printf_filtered ("from ");
+ print_address_numeric (low, 1, gdb_stdout);
+ printf_filtered (" to ");
+ print_address_numeric (high, 1, gdb_stdout);
+ printf_filtered (":\n");
+ }
+
+ /* Dump the specified range. */
+ pc = low;
+
+#ifdef GDB_TARGET_MASK_DISAS_PC
+ pc_masked = GDB_TARGET_MASK_DISAS_PC (pc);
+#else
+ pc_masked = pc;
+#endif
+
+ while (pc_masked < high)
+ {
+ QUIT;
+ print_address (pc_masked, gdb_stdout);
+ printf_filtered (":\t");
+ /* We often wrap here if there are long symbolic names. */
+ wrap_here (" ");
+ pc += print_insn (pc, gdb_stdout);
+ printf_filtered ("\n");
+
+#ifdef GDB_TARGET_MASK_DISAS_PC
+ pc_masked = GDB_TARGET_MASK_DISAS_PC (pc);
+#else
+ pc_masked = pc;
+#endif
+ }
+ printf_filtered ("End of assembler dump.\n");
+ gdb_flush (gdb_stdout);
+ }
+#if defined(TUI)
+ else
+ {
+ tuiDo((TuiOpaqueFuncPtr)tui_vAddWinToLayout, DISASSEM_WIN);
+ tuiDo((TuiOpaqueFuncPtr)tui_vUpdateSourceWindowsWithAddr, low);
+ }
+#endif
+}
+
+/* Print the instruction at address MEMADDR in debugged memory,
+ on STREAM. Returns length of the instruction, in bytes. */
+
+static int
+print_insn (memaddr, stream)
+ CORE_ADDR memaddr;
+ GDB_FILE *stream;
+{
+ if (TARGET_BYTE_ORDER == BIG_ENDIAN)
+ TARGET_PRINT_INSN_INFO->endian = BFD_ENDIAN_BIG;
+ else
+ TARGET_PRINT_INSN_INFO->endian = BFD_ENDIAN_LITTLE;
+
+ if (TARGET_ARCHITECTURE != NULL)
+ TARGET_PRINT_INSN_INFO->mach = TARGET_ARCHITECTURE->mach;
+ /* else: should set .mach=0 but some disassemblers don't grok this */
+
+ return TARGET_PRINT_INSN (memaddr, TARGET_PRINT_INSN_INFO);
+}
+
+
+void
+_initialize_printcmd ()
+{
+ current_display_number = -1;
+
+ add_info ("address", address_info,
+ "Describe where symbol SYM is stored.");
+
+ add_info ("symbol", sym_info,
+ "Describe what symbol is at location ADDR.\n\
+Only for symbols with fixed locations (global or static scope).");
+
+ add_com ("x", class_vars, x_command,
+ concat ("Examine memory: x/FMT ADDRESS.\n\
+ADDRESS is an expression for the memory address to examine.\n\
+FMT is a repeat count followed by a format letter and a size letter.\n\
+Format letters are o(octal), x(hex), d(decimal), u(unsigned decimal),\n\
+ 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\
+The specified number of objects of the specified size are printed\n\
+according to the format.\n\n\
+Defaults for format and size letters are those previously used.\n\
+Default count is 1. Default address is following last thing printed\n\
+with this command or \"print\".", NULL));
+
+ add_com ("disassemble", class_vars, disassemble_command,
+ "Disassemble a specified section of memory.\n\
+Default is the function surrounding the pc of the selected frame.\n\
+With a single argument, the function surrounding that address is dumped.\n\
+Two arguments are taken as a range of memory to dump.");
+ if (xdb_commands)
+ add_com_alias ("va", "disassemble", class_xdb, 0);
+
+#if 0
+ add_com ("whereis", class_vars, whereis_command,
+ "Print line number and file of definition of variable.");
+#endif
+
+ add_info ("display", display_info,
+ "Expressions to display when program stops, with code numbers.");
+
+ add_cmd ("undisplay", class_vars, undisplay_command,
+ "Cancel some expressions to be displayed when program stops.\n\
+Arguments are the code numbers of the expressions to stop displaying.\n\
+No argument means cancel all automatic-display expressions.\n\
+\"delete display\" has the same effect as this command.\n\
+Do \"info display\" to see current list of code numbers.",
+ &cmdlist);
+
+ add_com ("display", class_vars, display_command,
+ "Print value of expression EXP each time the program stops.\n\
+/FMT may be used before EXP as in the \"print\" command.\n\
+/FMT \"i\" or \"s\" or including a size-letter is allowed,\n\
+as in the \"x\" command, and then EXP is used to get the address to examine\n\
+and examining is done as in the \"x\" command.\n\n\
+With no argument, display all currently requested auto-display expressions.\n\
+Use \"undisplay\" to cancel display requests previously made."
+);
+
+ add_cmd ("display", class_vars, enable_display,
+ "Enable some expressions to be displayed when program stops.\n\
+Arguments are the code numbers of the expressions to resume displaying.\n\
+No argument means enable all automatic-display expressions.\n\
+Do \"info display\" to see current list of code numbers.", &enablelist);
+
+ add_cmd ("display", class_vars, disable_display_command,
+ "Disable some expressions to be displayed when program stops.\n\
+Arguments are the code numbers of the expressions to stop displaying.\n\
+No argument means disable all automatic-display expressions.\n\
+Do \"info display\" to see current list of code numbers.", &disablelist);
+
+ add_cmd ("display", class_vars, undisplay_command,
+ "Cancel some expressions to be displayed when program stops.\n\
+Arguments are the code numbers of the expressions to stop displaying.\n\
+No argument means cancel all automatic-display expressions.\n\
+Do \"info display\" to see current list of code numbers.", &deletelist);
+
+ add_com ("printf", class_vars, printf_command,
+ "printf \"printf format string\", arg1, arg2, arg3, ..., argn\n\
+This is useful for formatted output in user-defined commands.");
+
+ add_com ("output", class_vars, output_command,
+ "Like \"print\" but don't put in value history and don't print newline.\n\
+This is useful in user-defined commands.");
+
+ add_prefix_cmd ("set", class_vars, set_command,
+concat ("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.\n\
+You can see these environment settings with the \"show\" command.", NULL),
+ &setlist, "set ", 1, &cmdlist);
+ if (dbx_commands)
+ add_com("assign", class_vars, set_command, concat ("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.\n\
+You can see these environment settings with the \"show\" command.", NULL));
+
+ /* "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,
+"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);
+
+ add_com ("print", class_vars, print_command,
+ concat ("Print value of expression EXP.\n\
+Variables accessible are those of the lexical environment of the selected\n\
+stack frame, plus all those whose scope is global or an entire file.\n\
+\n\
+$NUM gets previous value number NUM. $ and $$ are the last two values.\n\
+$$NUM refers to NUM'th value back from the last one.\n\
+Names starting with $ refer to registers (with the values they would have\n",
+"if the program were to return to the stack frame now selected, restoring\n\
+all registers saved by frames farther in) or else to debugger\n\
+\"convenience\" variables (any such name not a known register).\n\
+Use assignment expressions to give values to convenience variables.\n",
+ "\n\
+{TYPE}ADREXP refers to a datum of data type TYPE, located at address ADREXP.\n\
+@ is a binary operator for treating consecutive data objects\n\
+anywhere in memory as an array. FOO@NUM gives an array whose first\n\
+element is FOO, whose second element is stored in the space following\n\
+where FOO is stored, etc. FOO must be an expression whose value\n\
+resides in memory.\n",
+ "\n\
+EXP may be preceded with /FMT, where FMT is a format letter\n\
+but no count or size letter (see \"x\" command).", 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);
+
+ /* For examine/instruction a single byte quantity is specified as
+ the data. This avoids problems with value_at_lazy() requiring a
+ valid data type (and rejecting VOID). */
+ examine_i_type = init_type (TYPE_CODE_INT, 1, 0, "examine_i_type", NULL);
+
+ examine_b_type = init_type (TYPE_CODE_INT, 1, 0, "examine_b_type", NULL);
+ examine_h_type = init_type (TYPE_CODE_INT, 2, 0, "examine_h_type", NULL);
+ examine_w_type = init_type (TYPE_CODE_INT, 4, 0, "examine_w_type", NULL);
+ examine_g_type = init_type (TYPE_CODE_INT, 8, 0, "examine_g_type", NULL);
+
+}
diff --git a/gdb/process_reply.defs b/gdb/process_reply.defs
new file mode 100644
index 00000000000..824b5c65c2e
--- /dev/null
+++ b/gdb/process_reply.defs
@@ -0,0 +1 @@
+#include <hurd/process_reply.defs>
diff --git a/gdb/procfs.c b/gdb/procfs.c
new file mode 100644
index 00000000000..ff20240e0a5
--- /dev/null
+++ b/gdb/procfs.c
@@ -0,0 +1,5764 @@
+/* Machine independent support for SVR4 /proc (process file system) for GDB.
+ Copyright 1991, 1992-98, 1999 Free Software Foundation, Inc.
+ Written by Fred Fish at Cygnus Support. Changes for sysv4.2mp procfs
+ compatibility by Geoffrey Noer at Cygnus Solutions.
+
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+
+/* N O T E S
+
+For information on the details of using /proc consult section proc(4)
+in the UNIX System V Release 4 System Administrator's Reference Manual.
+
+The general register and floating point register sets are manipulated
+separately. This file makes the assumption that if FP0_REGNUM is
+defined, then support for the floating point register set is desired,
+regardless of whether or not the actual target has floating point hardware.
+
+ */
+
+
+#include "defs.h"
+
+#include <sys/types.h>
+#include <time.h>
+#include <sys/fault.h>
+#include <sys/syscall.h>
+#include <sys/procfs.h>
+#include <fcntl.h>
+#include <errno.h>
+#include "gdb_string.h"
+#include <stropts.h>
+#include <poll.h>
+#include <unistd.h>
+#include "gdb_stat.h"
+
+#include "inferior.h"
+#include "target.h"
+#include "command.h"
+#include "gdbcore.h"
+#include "gdbthread.h"
+
+#if !defined(SYS_lwp_create) && defined(SYS_lwpcreate)
+# define SYS_lwp_create SYS_lwpcreate
+#endif
+
+#if !defined(SYS_lwp_exit) && defined(SYS_lwpexit)
+# define SYS_lwp_exit SYS_lwpexit
+#endif
+
+#if !defined(SYS_lwp_wait) && defined(SYS_lwpwait)
+# define SYS_lwp_wait SYS_lwpwait
+#endif
+
+#if !defined(SYS_lwp_self) && defined(SYS_lwpself)
+# define SYS_lwp_self SYS_lwpself
+#endif
+
+#if !defined(SYS_lwp_info) && defined(SYS_lwpinfo)
+# define SYS_lwp_info SYS_lwpinfo
+#endif
+
+#if !defined(SYS_lwp_private) && defined(SYS_lwpprivate)
+# define SYS_lwp_private SYS_lwpprivate
+#endif
+
+#if !defined(SYS_lwp_kill) && defined(SYS_lwpkill)
+# define SYS_lwp_kill SYS_lwpkill
+#endif
+
+#if !defined(SYS_lwp_suspend) && defined(SYS_lwpsuspend)
+# define SYS_lwp_suspend SYS_lwpsuspend
+#endif
+
+#if !defined(SYS_lwp_continue) && defined(SYS_lwpcontinue)
+# define SYS_lwp_continue SYS_lwpcontinue
+#endif
+
+/* the name of the proc status struct depends on the implementation */
+/* Wrap Light Weight Process member in THE_PR_LWP macro for clearer code */
+#ifndef HAVE_PSTATUS_T
+ typedef prstatus_t gdb_prstatus_t;
+#define THE_PR_LWP(a) a
+#else /* HAVE_PSTATUS_T */
+ typedef pstatus_t gdb_prstatus_t;
+#define THE_PR_LWP(a) a.pr_lwp
+#if !defined(HAVE_PRRUN_T) && defined(HAVE_MULTIPLE_PROC_FDS)
+ /* Fallback definitions - for using configure information directly */
+#ifndef UNIXWARE
+#define UNIXWARE 1
+#endif
+#if !defined(PROCFS_USE_READ_WRITE) && !defined(HAVE_PROCFS_PIOCSET)
+#define PROCFS_USE_READ_WRITE 1
+#endif
+#endif /* !HAVE_PRRUN_T && HAVE_MULTIPLE_PROC_FDS */
+#endif /* HAVE_PSTATUS_T */
+
+#define MAX_SYSCALLS 256 /* Maximum number of syscalls for table */
+
+/* proc name formats may vary depending on the proc implementation */
+#ifdef HAVE_MULTIPLE_PROC_FDS
+# ifndef CTL_PROC_NAME_FMT
+# define CTL_PROC_NAME_FMT "/proc/%d/ctl"
+# define AS_PROC_NAME_FMT "/proc/%d/as"
+# define MAP_PROC_NAME_FMT "/proc/%d/map"
+# define STATUS_PROC_NAME_FMT "/proc/%d/status"
+# endif
+#else /* HAVE_MULTIPLE_PROC_FDS */
+# ifndef CTL_PROC_NAME_FMT
+# define CTL_PROC_NAME_FMT "/proc/%05d"
+# define AS_PROC_NAME_FMT "/proc/%05d"
+# define MAP_PROC_NAME_FMT "/proc/%05d"
+# define STATUS_PROC_NAME_FMT "/proc/%05d"
+# endif
+#endif /* HAVE_MULTIPLE_PROC_FDS */
+
+
+/* These #ifdefs are for sol2.x in particular. sol2.x has
+ both a "gregset_t" and a "prgregset_t", which have
+ similar uses but different layouts. sol2.x gdb tries to
+ use prgregset_t (and prfpregset_t) everywhere. */
+
+#ifdef GDB_GREGSET_TYPE
+ typedef GDB_GREGSET_TYPE gdb_gregset_t;
+#else
+ typedef gregset_t gdb_gregset_t;
+#endif
+
+#ifdef GDB_FPREGSET_TYPE
+ typedef GDB_FPREGSET_TYPE gdb_fpregset_t;
+#else
+ typedef fpregset_t gdb_fpregset_t;
+#endif
+
+
+#define MAX_PROC_NAME_SIZE sizeof("/proc/1234567890/status")
+
+struct target_ops procfs_ops;
+
+int procfs_suppress_run = 0; /* Non-zero if procfs should pretend not to
+ be a runnable target. Used by targets
+ that can sit atop procfs, such as solaris
+ thread support. */
+
+#if 1 /* FIXME: Gross and ugly hack to resolve coredep.c global */
+CORE_ADDR kernel_u_addr;
+#endif
+
+#ifdef BROKEN_SIGINFO_H /* Workaround broken SGS <sys/siginfo.h> */
+#undef si_pid
+#define si_pid _data._proc.pid
+#undef si_uid
+#define si_uid _data._proc._pdata._kill.uid
+#endif /* BROKEN_SIGINFO_H */
+
+/* Define structures for passing commands to /proc/pid/ctl file. Note that
+ while we create these for the PROCFS_USE_READ_WRITE world, we use them
+ and ignore the extra cmd int in other proc schemes.
+*/
+/* generic ctl msg */
+struct proc_ctl {
+ int cmd;
+ long data;
+};
+
+/* set general registers */
+struct greg_ctl {
+ int cmd;
+ gdb_gregset_t gregset;
+};
+
+/* set fp registers */
+struct fpreg_ctl {
+ int cmd;
+ gdb_fpregset_t fpregset;
+};
+
+/* set signals to be traced */
+struct sig_ctl {
+ int cmd;
+ sigset_t sigset;
+};
+
+/* set faults to be traced */
+struct flt_ctl {
+ int cmd;
+ fltset_t fltset;
+};
+
+/* set system calls to be traced */
+struct sys_ctl {
+ int cmd;
+ sysset_t sysset;
+};
+
+/* set current signal to be traced */
+struct sigi_ctl {
+ int cmd;
+ siginfo_t siginfo;
+};
+
+/* All access to the inferior, either one started by gdb or one that has
+ been attached to, is controlled by an instance of a procinfo structure,
+ defined below. Since gdb currently only handles one inferior at a time,
+ the procinfo structure for the inferior is statically allocated and
+ only one exists at any given time. There is a separate procinfo
+ structure for use by the "info proc" command, so that we can print
+ useful information about any random process without interfering with
+ the inferior's procinfo information. */
+
+struct procinfo {
+ struct procinfo *next;
+ int pid; /* Process ID of inferior */
+ int ctl_fd; /* File descriptor for /proc ctl file */
+ int status_fd; /* File descriptor for /proc status file */
+ int as_fd; /* File descriptor for /proc as file */
+ int map_fd; /* File descriptor for /proc map file */
+ char *pathname; /* Pathname to /proc entry */
+ int had_event; /* poll/select says something happened */
+ int was_stopped; /* Nonzero if was stopped prior to attach */
+ int nopass_next_sigstop; /* Don't pass a sigstop on next resume */
+#ifdef HAVE_PRRUN_T
+ prrun_t prrun; /* Control state when it is run */
+#endif
+ gdb_prstatus_t prstatus; /* Current process status info */
+ struct greg_ctl gregset; /* General register set */
+ struct fpreg_ctl fpregset; /* Floating point register set */
+ struct flt_ctl fltset; /* Current traced hardware fault set */
+ struct sig_ctl trace; /* Current traced signal set */
+ struct sys_ctl exitset; /* Current traced system call exit set */
+ struct sys_ctl entryset; /* Current traced system call entry set */
+ struct sig_ctl saved_sighold; /* Saved held signal set */
+ struct flt_ctl saved_fltset; /* Saved traced hardware fault set */
+ struct sig_ctl saved_trace; /* Saved traced signal set */
+ struct sys_ctl saved_exitset; /* Saved traced system call exit set */
+ struct sys_ctl saved_entryset;/* Saved traced system call entry set */
+ int num_syscall_handlers; /* Number of syscall trap handlers
+ currently installed */
+ /* Pointer to list of syscall trap handlers */
+ struct procfs_syscall_handler *syscall_handlers;
+ int saved_rtnval; /* return value and status for wait(), */
+ int saved_statval; /* as supplied by a syscall handler. */
+ int new_child; /* Non-zero if it's a new thread */
+};
+
+/* List of inferior process information */
+static struct procinfo *procinfo_list = NULL;
+static struct pollfd *poll_list; /* pollfds used for waiting on /proc */
+
+static int num_poll_list = 0; /* Number of entries in poll_list */
+
+/* Much of the information used in the /proc interface, particularly for
+ printing status information, is kept as tables of structures of the
+ following form. These tables can be used to map numeric values to
+ their symbolic names and to a string that describes their specific use. */
+
+struct trans {
+ int value; /* The numeric value */
+ char *name; /* The equivalent symbolic value */
+ char *desc; /* Short description of value */
+};
+
+/* Translate bits in the pr_flags member of the prstatus structure, into the
+ names and desc information. */
+
+static struct trans pr_flag_table[] =
+{
+#if defined (PR_STOPPED)
+ { PR_STOPPED, "PR_STOPPED", "Process is stopped" },
+#endif
+#if defined (PR_ISTOP)
+ { PR_ISTOP, "PR_ISTOP", "Stopped on an event of interest" },
+#endif
+#if defined (PR_DSTOP)
+ { PR_DSTOP, "PR_DSTOP", "A stop directive is in effect" },
+#endif
+#if defined (PR_ASLEEP)
+ { PR_ASLEEP, "PR_ASLEEP", "Sleeping in an interruptible system call" },
+#endif
+#if defined (PR_FORK)
+ { PR_FORK, "PR_FORK", "Inherit-on-fork is in effect" },
+#endif
+#if defined (PR_RLC)
+ { PR_RLC, "PR_RLC", "Run-on-last-close is in effect" },
+#endif
+#if defined (PR_PTRACE)
+ { PR_PTRACE, "PR_PTRACE", "Process is being controlled by ptrace" },
+#endif
+#if defined (PR_PCINVAL)
+ { PR_PCINVAL, "PR_PCINVAL", "PC refers to an invalid virtual address" },
+#endif
+#if defined (PR_ISSYS)
+ { PR_ISSYS, "PR_ISSYS", "Is a system process" },
+#endif
+#if defined (PR_STEP)
+ { PR_STEP, "PR_STEP", "Process has single step pending" },
+#endif
+#if defined (PR_KLC)
+ { PR_KLC, "PR_KLC", "Kill-on-last-close is in effect" },
+#endif
+#if defined (PR_ASYNC)
+ { PR_ASYNC, "PR_ASYNC", "Asynchronous stop is in effect" },
+#endif
+#if defined (PR_PCOMPAT)
+ { PR_PCOMPAT, "PR_PCOMPAT", "Ptrace compatibility mode in effect" },
+#endif
+#if defined (PR_MSACCT)
+ { PR_MSACCT, "PR_MSACCT", "Microstate accounting enabled" },
+#endif
+#if defined (PR_BPTADJ)
+ { PR_BPTADJ, "PR_BPTADJ", "Breakpoint PC adjustment in effect" },
+#endif
+#if defined (PR_ASLWP)
+ { PR_ASLWP, "PR_ASLWP", "Asynchronus signal LWP" },
+#endif
+ { 0, NULL, NULL }
+};
+
+/* Translate values in the pr_why field of the prstatus struct. */
+
+static struct trans pr_why_table[] =
+{
+#if defined (PR_REQUESTED)
+ { PR_REQUESTED, "PR_REQUESTED", "Directed to stop via PIOCSTOP/PIOCWSTOP" },
+#endif
+#if defined (PR_SIGNALLED)
+ { PR_SIGNALLED, "PR_SIGNALLED", "Receipt of a traced signal" },
+#endif
+#if defined (PR_SYSENTRY)
+ { PR_SYSENTRY, "PR_SYSENTRY", "Entry to a traced system call" },
+#endif
+#if defined (PR_SYSEXIT)
+ { PR_SYSEXIT, "PR_SYSEXIT", "Exit from a traced system call" },
+#endif
+#if defined (PR_JOBCONTROL)
+ { PR_JOBCONTROL, "PR_JOBCONTROL", "Default job control stop signal action" },
+#endif
+#if defined (PR_FAULTED)
+ { PR_FAULTED, "PR_FAULTED", "Incurred a traced hardware fault" },
+#endif
+#if defined (PR_SUSPENDED)
+ { PR_SUSPENDED, "PR_SUSPENDED", "Process suspended" },
+#endif
+#if defined (PR_CHECKPOINT)
+ { PR_CHECKPOINT, "PR_CHECKPOINT", "(???)" },
+#endif
+ { 0, NULL, NULL }
+};
+
+/* Hardware fault translation table. */
+
+static struct trans faults_table[] =
+{
+#if defined (FLTILL)
+ { FLTILL, "FLTILL", "Illegal instruction" },
+#endif
+#if defined (FLTPRIV)
+ { FLTPRIV, "FLTPRIV", "Privileged instruction" },
+#endif
+#if defined (FLTBPT)
+ { FLTBPT, "FLTBPT", "Breakpoint trap" },
+#endif
+#if defined (FLTTRACE)
+ { FLTTRACE, "FLTTRACE", "Trace trap" },
+#endif
+#if defined (FLTACCESS)
+ { FLTACCESS, "FLTACCESS", "Memory access fault" },
+#endif
+#if defined (FLTBOUNDS)
+ { FLTBOUNDS, "FLTBOUNDS", "Memory bounds violation" },
+#endif
+#if defined (FLTIOVF)
+ { FLTIOVF, "FLTIOVF", "Integer overflow" },
+#endif
+#if defined (FLTIZDIV)
+ { FLTIZDIV, "FLTIZDIV", "Integer zero divide" },
+#endif
+#if defined (FLTFPE)
+ { FLTFPE, "FLTFPE", "Floating-point exception" },
+#endif
+#if defined (FLTSTACK)
+ { FLTSTACK, "FLTSTACK", "Unrecoverable stack fault" },
+#endif
+#if defined (FLTPAGE)
+ { FLTPAGE, "FLTPAGE", "Recoverable page fault" },
+#endif
+ { 0, NULL, NULL }
+};
+
+/* Translation table for signal generation information. See UNIX System
+ V Release 4 Programmer's Reference Manual, siginfo(5). */
+
+static struct sigcode {
+ int signo;
+ int code;
+ char *codename;
+ char *desc;
+} siginfo_table[] = {
+#if defined (SIGILL) && defined (ILL_ILLOPC)
+ { SIGILL, ILL_ILLOPC, "ILL_ILLOPC", "Illegal opcode" },
+#endif
+#if defined (SIGILL) && defined (ILL_ILLOPN)
+ { SIGILL, ILL_ILLOPN, "ILL_ILLOPN", "Illegal operand", },
+#endif
+#if defined (SIGILL) && defined (ILL_ILLADR)
+ { SIGILL, ILL_ILLADR, "ILL_ILLADR", "Illegal addressing mode" },
+#endif
+#if defined (SIGILL) && defined (ILL_ILLTRP)
+ { SIGILL, ILL_ILLTRP, "ILL_ILLTRP", "Illegal trap" },
+#endif
+#if defined (SIGILL) && defined (ILL_PRVOPC)
+ { SIGILL, ILL_PRVOPC, "ILL_PRVOPC", "Privileged opcode" },
+#endif
+#if defined (SIGILL) && defined (ILL_PRVREG)
+ { SIGILL, ILL_PRVREG, "ILL_PRVREG", "Privileged register" },
+#endif
+#if defined (SIGILL) && defined (ILL_COPROC)
+ { SIGILL, ILL_COPROC, "ILL_COPROC", "Coprocessor error" },
+#endif
+#if defined (SIGILL) && defined (ILL_BADSTK)
+ { SIGILL, ILL_BADSTK, "ILL_BADSTK", "Internal stack error" },
+#endif
+#if defined (SIGFPE) && defined (FPE_INTDIV)
+ { SIGFPE, FPE_INTDIV, "FPE_INTDIV", "Integer divide by zero" },
+#endif
+#if defined (SIGFPE) && defined (FPE_INTOVF)
+ { SIGFPE, FPE_INTOVF, "FPE_INTOVF", "Integer overflow" },
+#endif
+#if defined (SIGFPE) && defined (FPE_FLTDIV)
+ { SIGFPE, FPE_FLTDIV, "FPE_FLTDIV", "Floating point divide by zero" },
+#endif
+#if defined (SIGFPE) && defined (FPE_FLTOVF)
+ { SIGFPE, FPE_FLTOVF, "FPE_FLTOVF", "Floating point overflow" },
+#endif
+#if defined (SIGFPE) && defined (FPE_FLTUND)
+ { SIGFPE, FPE_FLTUND, "FPE_FLTUND", "Floating point underflow" },
+#endif
+#if defined (SIGFPE) && defined (FPE_FLTRES)
+ { SIGFPE, FPE_FLTRES, "FPE_FLTRES", "Floating point inexact result" },
+#endif
+#if defined (SIGFPE) && defined (FPE_FLTINV)
+ { SIGFPE, FPE_FLTINV, "FPE_FLTINV", "Invalid floating point operation" },
+#endif
+#if defined (SIGFPE) && defined (FPE_FLTSUB)
+ { SIGFPE, FPE_FLTSUB, "FPE_FLTSUB", "Subscript out of range" },
+#endif
+#if defined (SIGSEGV) && defined (SEGV_MAPERR)
+ { SIGSEGV, SEGV_MAPERR, "SEGV_MAPERR", "Address not mapped to object" },
+#endif
+#if defined (SIGSEGV) && defined (SEGV_ACCERR)
+ { SIGSEGV, SEGV_ACCERR, "SEGV_ACCERR", "Invalid permissions for object" },
+#endif
+#if defined (SIGBUS) && defined (BUS_ADRALN)
+ { SIGBUS, BUS_ADRALN, "BUS_ADRALN", "Invalid address alignment" },
+#endif
+#if defined (SIGBUS) && defined (BUS_ADRERR)
+ { SIGBUS, BUS_ADRERR, "BUS_ADRERR", "Non-existent physical address" },
+#endif
+#if defined (SIGBUS) && defined (BUS_OBJERR)
+ { SIGBUS, BUS_OBJERR, "BUS_OBJERR", "Object specific hardware error" },
+#endif
+#if defined (SIGTRAP) && defined (TRAP_BRKPT)
+ { SIGTRAP, TRAP_BRKPT, "TRAP_BRKPT", "Process breakpoint" },
+#endif
+#if defined (SIGTRAP) && defined (TRAP_TRACE)
+ { SIGTRAP, TRAP_TRACE, "TRAP_TRACE", "Process trace trap" },
+#endif
+#if defined (SIGCLD) && defined (CLD_EXITED)
+ { SIGCLD, CLD_EXITED, "CLD_EXITED", "Child has exited" },
+#endif
+#if defined (SIGCLD) && defined (CLD_KILLED)
+ { SIGCLD, CLD_KILLED, "CLD_KILLED", "Child was killed" },
+#endif
+#if defined (SIGCLD) && defined (CLD_DUMPED)
+ { SIGCLD, CLD_DUMPED, "CLD_DUMPED", "Child has terminated abnormally" },
+#endif
+#if defined (SIGCLD) && defined (CLD_TRAPPED)
+ { SIGCLD, CLD_TRAPPED, "CLD_TRAPPED", "Traced child has trapped" },
+#endif
+#if defined (SIGCLD) && defined (CLD_STOPPED)
+ { SIGCLD, CLD_STOPPED, "CLD_STOPPED", "Child has stopped" },
+#endif
+#if defined (SIGCLD) && defined (CLD_CONTINUED)
+ { SIGCLD, CLD_CONTINUED, "CLD_CONTINUED", "Stopped child had continued" },
+#endif
+#if defined (SIGPOLL) && defined (POLL_IN)
+ { SIGPOLL, POLL_IN, "POLL_IN", "Input input available" },
+#endif
+#if defined (SIGPOLL) && defined (POLL_OUT)
+ { SIGPOLL, POLL_OUT, "POLL_OUT", "Output buffers available" },
+#endif
+#if defined (SIGPOLL) && defined (POLL_MSG)
+ { SIGPOLL, POLL_MSG, "POLL_MSG", "Input message available" },
+#endif
+#if defined (SIGPOLL) && defined (POLL_ERR)
+ { SIGPOLL, POLL_ERR, "POLL_ERR", "I/O error" },
+#endif
+#if defined (SIGPOLL) && defined (POLL_PRI)
+ { SIGPOLL, POLL_PRI, "POLL_PRI", "High priority input available" },
+#endif
+#if defined (SIGPOLL) && defined (POLL_HUP)
+ { SIGPOLL, POLL_HUP, "POLL_HUP", "Device disconnected" },
+#endif
+ { 0, 0, NULL, NULL }
+};
+
+static char *syscall_table[MAX_SYSCALLS];
+
+/* Prototypes for local functions */
+
+static void procfs_stop PARAMS ((void));
+
+static int procfs_thread_alive PARAMS ((int));
+
+static int procfs_can_run PARAMS ((void));
+
+static void procfs_mourn_inferior PARAMS ((void));
+
+static void procfs_fetch_registers PARAMS ((int));
+
+static int procfs_wait PARAMS ((int, struct target_waitstatus *));
+
+static void procfs_open PARAMS ((char *, int));
+
+static void procfs_files_info PARAMS ((struct target_ops *));
+
+static void procfs_prepare_to_store PARAMS ((void));
+
+static void procfs_detach PARAMS ((char *, int));
+
+static void procfs_attach PARAMS ((char *, int));
+
+static void proc_set_exec_trap PARAMS ((void));
+
+static void procfs_init_inferior PARAMS ((int));
+
+static struct procinfo *create_procinfo PARAMS ((int));
+
+static void procfs_store_registers PARAMS ((int));
+
+static int procfs_xfer_memory PARAMS ((CORE_ADDR, char *, int, int, struct target_ops *));
+
+static void procfs_kill_inferior PARAMS ((void));
+
+static char *sigcodedesc PARAMS ((siginfo_t *));
+
+static char *sigcodename PARAMS ((siginfo_t *));
+
+static struct procinfo *wait_fd PARAMS ((void));
+
+static void remove_fd PARAMS ((struct procinfo *));
+
+static void add_fd PARAMS ((struct procinfo *));
+
+static void set_proc_siginfo PARAMS ((struct procinfo *, int));
+
+static void init_syscall_table PARAMS ((void));
+
+static char *syscallname PARAMS ((int));
+
+static char *signalname PARAMS ((int));
+
+static char *errnoname PARAMS ((int));
+
+static int proc_address_to_fd PARAMS ((struct procinfo *, CORE_ADDR, int));
+
+static int open_proc_file PARAMS ((int, struct procinfo *, int, int));
+
+static void close_proc_file PARAMS ((struct procinfo *));
+
+static void unconditionally_kill_inferior PARAMS ((struct procinfo *));
+
+static NORETURN void proc_init_failed PARAMS ((struct procinfo *, char *, int)) ATTR_NORETURN;
+
+static void info_proc PARAMS ((char *, int));
+
+static void info_proc_flags PARAMS ((struct procinfo *, int));
+
+static void info_proc_stop PARAMS ((struct procinfo *, int));
+
+static void info_proc_siginfo PARAMS ((struct procinfo *, int));
+
+static void info_proc_syscalls PARAMS ((struct procinfo *, int));
+
+static void info_proc_mappings PARAMS ((struct procinfo *, int));
+
+static void info_proc_signals PARAMS ((struct procinfo *, int));
+
+static void info_proc_faults PARAMS ((struct procinfo *, int));
+
+static char *mappingflags PARAMS ((long));
+
+static char *lookupname PARAMS ((struct trans *, unsigned int, char *));
+
+static char *lookupdesc PARAMS ((struct trans *, unsigned int));
+
+static int do_attach PARAMS ((int pid));
+
+static void do_detach PARAMS ((int siggnal));
+
+static void procfs_create_inferior PARAMS ((char *, char *, char **));
+
+static void procfs_notice_signals PARAMS ((int pid));
+
+static void notice_signals PARAMS ((struct procinfo *, struct sig_ctl *));
+
+static struct procinfo *find_procinfo PARAMS ((pid_t pid, int okfail));
+
+static int procfs_write_pcwstop PARAMS ((struct procinfo *));
+static int procfs_read_status PARAMS ((struct procinfo *));
+static void procfs_write_pckill PARAMS ((struct procinfo *));
+
+typedef int syscall_func_t PARAMS ((struct procinfo *pi, int syscall_num,
+ int why, int *rtnval, int *statval));
+
+static void procfs_set_syscall_trap PARAMS ((struct procinfo *pi,
+ int syscall_num, int flags,
+ syscall_func_t *func));
+
+static void procfs_clear_syscall_trap PARAMS ((struct procinfo *pi,
+ int syscall_num, int errok));
+
+#define PROCFS_SYSCALL_ENTRY 0x1 /* Trap on entry to sys call */
+#define PROCFS_SYSCALL_EXIT 0x2 /* Trap on exit from sys call */
+
+static syscall_func_t procfs_exit_handler;
+
+static syscall_func_t procfs_exec_handler;
+
+#ifdef SYS_sproc
+static syscall_func_t procfs_sproc_handler;
+static syscall_func_t procfs_fork_handler;
+#endif
+
+#ifdef SYS_lwp_create
+static syscall_func_t procfs_lwp_creation_handler;
+#endif
+
+static void modify_inherit_on_fork_flag PARAMS ((int fd, int flag));
+static void modify_run_on_last_close_flag PARAMS ((int fd, int flag));
+
+/* */
+
+struct procfs_syscall_handler
+{
+ int syscall_num; /* The number of the system call being handled */
+ /* The function to be called */
+ syscall_func_t *func;
+};
+
+static void procfs_resume PARAMS ((int pid, int step,
+ enum target_signal signo));
+
+static void init_procfs_ops PARAMS ((void));
+
+/* External function prototypes that can't be easily included in any
+ header file because the args are typedefs in system include files. */
+
+extern void supply_gregset PARAMS ((gdb_gregset_t *));
+
+extern void fill_gregset PARAMS ((gdb_gregset_t *, int));
+
+#ifdef FP0_REGNUM
+extern void supply_fpregset PARAMS ((gdb_fpregset_t *));
+
+extern void fill_fpregset PARAMS ((gdb_fpregset_t *, int));
+#endif
+
+/*
+
+LOCAL FUNCTION
+
+ find_procinfo -- convert a process id to a struct procinfo
+
+SYNOPSIS
+
+ static struct procinfo * find_procinfo (pid_t pid, int okfail);
+
+DESCRIPTION
+
+ Given a process id, look it up in the procinfo chain. Returns
+ a struct procinfo *. If can't find pid, then call error(),
+ unless okfail is set, in which case, return NULL;
+ */
+
+static struct procinfo *
+find_procinfo (pid, okfail)
+ pid_t pid;
+ int okfail;
+{
+ struct procinfo *procinfo;
+
+ for (procinfo = procinfo_list; procinfo; procinfo = procinfo->next)
+ if (procinfo->pid == pid)
+ return procinfo;
+
+ if (okfail)
+ return NULL;
+
+ error ("procfs (find_procinfo): Couldn't locate pid %d", pid);
+}
+
+/*
+
+LOCAL MACRO
+
+ current_procinfo -- convert inferior_pid to a struct procinfo
+
+SYNOPSIS
+
+ static struct procinfo * current_procinfo;
+
+DESCRIPTION
+
+ Looks up inferior_pid in the procinfo chain. Always returns a
+ struct procinfo *. If process can't be found, we error() out.
+ */
+
+#define current_procinfo find_procinfo (inferior_pid, 0)
+
+/*
+
+LOCAL FUNCTION
+
+ add_fd -- Add the fd to the poll/select list
+
+SYNOPSIS
+
+ static void add_fd (struct procinfo *);
+
+DESCRIPTION
+
+ Add the fd of the supplied procinfo to the list of fds used for
+ poll/select operations.
+ */
+
+static void
+add_fd (pi)
+ struct procinfo *pi;
+{
+ if (num_poll_list <= 0)
+ poll_list = (struct pollfd *) xmalloc (sizeof (struct pollfd));
+ else
+ poll_list = (struct pollfd *) xrealloc (poll_list,
+ (num_poll_list + 1)
+ * sizeof (struct pollfd));
+ poll_list[num_poll_list].fd = pi->ctl_fd;
+#ifdef UNIXWARE
+ poll_list[num_poll_list].events = POLLWRNORM;
+#else
+ poll_list[num_poll_list].events = POLLPRI;
+#endif
+
+ num_poll_list++;
+}
+
+/*
+
+LOCAL FUNCTION
+
+ remove_fd -- Remove the fd from the poll/select list
+
+SYNOPSIS
+
+ static void remove_fd (struct procinfo *);
+
+DESCRIPTION
+
+ Remove the fd of the supplied procinfo from the list of fds used
+ for poll/select operations.
+ */
+
+static void
+remove_fd (pi)
+ struct procinfo *pi;
+{
+ int i;
+
+ for (i = 0; i < num_poll_list; i++)
+ {
+ if (poll_list[i].fd == pi->ctl_fd)
+ {
+ if (i != num_poll_list - 1)
+ memcpy (poll_list + i, poll_list + i + 1,
+ (num_poll_list - i - 1) * sizeof (struct pollfd));
+
+ num_poll_list--;
+
+ if (num_poll_list == 0)
+ free (poll_list);
+ else
+ poll_list = (struct pollfd *) xrealloc (poll_list,
+ num_poll_list
+ * sizeof (struct pollfd));
+ return;
+ }
+ }
+}
+
+/*
+
+LOCAL FUNCTION
+
+ procfs_read_status - get procfs fd status
+
+SYNOPSIS
+
+ static int procfs_read_status (pi) struct procinfo *pi;
+
+DESCRIPTION
+
+ Given a pointer to a procinfo struct, get the status of
+ the status_fd in the appropriate way. Returns 0 on failure,
+ 1 on success.
+ */
+
+static int
+procfs_read_status (pi)
+ struct procinfo *pi;
+{
+#ifdef PROCFS_USE_READ_WRITE
+ if ((lseek (pi->status_fd, 0, SEEK_SET) < 0) ||
+ (read (pi->status_fd, (char *) &pi->prstatus,
+ sizeof (gdb_prstatus_t)) != sizeof (gdb_prstatus_t)))
+#else
+ if (ioctl (pi->status_fd, PIOCSTATUS, &pi->prstatus) < 0)
+#endif
+ return 0;
+ else
+ return 1;
+}
+
+/*
+
+LOCAL FUNCTION
+
+ procfs_write_pcwstop - send a PCWSTOP to procfs fd
+
+SYNOPSIS
+
+ static int procfs_write_pcwstop (pi) struct procinfo *pi;
+
+DESCRIPTION
+
+ Given a pointer to a procinfo struct, send a PCWSTOP to
+ the ctl_fd in the appropriate way. Returns 0 on failure,
+ 1 on success.
+ */
+
+static int
+procfs_write_pcwstop (pi)
+ struct procinfo *pi;
+{
+#ifdef PROCFS_USE_READ_WRITE
+ long cmd = PCWSTOP;
+ if (write (pi->ctl_fd, (char *) &cmd, sizeof (long)) < 0)
+#else
+ if (ioctl (pi->ctl_fd, PIOCWSTOP, &pi->prstatus) < 0)
+#endif
+ return 0;
+ else
+ return 1;
+}
+
+/*
+
+LOCAL FUNCTION
+
+ procfs_write_pckill - send a kill to procfs fd
+
+SYNOPSIS
+
+ static void procfs_write_pckill (pi) struct procinfo *pi;
+
+DESCRIPTION
+
+ Given a pointer to a procinfo struct, send a kill to
+ the ctl_fd in the appropriate way. Returns 0 on failure,
+ 1 on success.
+ */
+
+static void
+procfs_write_pckill (pi)
+ struct procinfo *pi;
+{
+#ifdef PROCFS_USE_READ_WRITE
+ struct proc_ctl pctl;
+ pctl.cmd = PCKILL;
+ pctl.data = SIGKILL;
+ write (pi->ctl_fd, &pctl, sizeof (struct proc_ctl));
+#else
+ int signo = SIGKILL;
+ ioctl (pi->ctl_fd, PIOCKILL, &signo);
+#endif
+}
+
+static struct procinfo *
+wait_fd ()
+{
+ struct procinfo *pi, *next_pi;
+#ifndef LOSING_POLL
+ int num_fds;
+ int i;
+#endif
+
+ set_sigint_trap (); /* Causes SIGINT to be passed on to the
+ attached process. */
+ set_sigio_trap ();
+
+ wait_again:
+#ifndef LOSING_POLL
+ while (1)
+ {
+ num_fds = poll (poll_list, num_poll_list, -1);
+ if (num_fds > 0)
+ break;
+ if (num_fds < 0 && errno == EINTR)
+ continue;
+ print_sys_errmsg ("poll failed", errno);
+ error ("Poll failed, returned %d", num_fds);
+ }
+#else /* LOSING_POLL */
+ pi = current_procinfo;
+
+ while (!procfs_write_pcwstop (pi))
+ {
+ if (errno == ENOENT)
+ {
+ /* Process exited. */
+ pi->prstatus.pr_flags = 0;
+ break;
+ }
+ else if (errno != EINTR)
+ {
+ print_sys_errmsg (pi->pathname, errno);
+ error ("procfs_write_pcwstop failed");
+ }
+ }
+ pi->had_event = 1;
+#endif /* LOSING_POLL */
+
+ clear_sigint_trap ();
+ clear_sigio_trap ();
+
+#ifndef LOSING_POLL
+
+ for (i = 0; i < num_poll_list && num_fds > 0; i++)
+ {
+ if (0 == (poll_list[i].revents &
+ (POLLWRNORM | POLLPRI | POLLERR | POLLHUP | POLLNVAL)))
+ continue;
+ for (pi = procinfo_list; pi; pi = next_pi)
+ {
+ next_pi = pi->next;
+ if (poll_list[i].fd == pi->ctl_fd)
+ {
+ num_fds--;
+ if ((poll_list[i].revents & POLLHUP) != 0 ||
+ !procfs_read_status(pi))
+ { /* The LWP has apparently terminated. */
+ if (num_poll_list <= 1)
+ {
+ pi->prstatus.pr_flags = 0;
+ pi->had_event = 1;
+ break;
+ }
+ if (info_verbose)
+ printf_filtered ("LWP %d exited.\n",
+ (pi->pid >> 16) & 0xffff);
+ close_proc_file (pi);
+ i--; /* don't skip deleted entry */
+ if (num_fds != 0)
+ break; /* already another event to process */
+ else
+ goto wait_again; /* wait for another event */
+ }
+ pi->had_event = 1;
+ break;
+ }
+ }
+ if (!pi)
+ error ("wait_fd: Couldn't find procinfo for fd %d\n",
+ poll_list[i].fd);
+ }
+#endif /* LOSING_POLL */
+
+ return pi;
+}
+
+/*
+
+LOCAL FUNCTION
+
+ lookupdesc -- translate a value to a summary desc string
+
+SYNOPSIS
+
+ static char *lookupdesc (struct trans *transp, unsigned int val);
+
+DESCRIPTION
+
+ Given a pointer to a translation table and a value to be translated,
+ lookup the desc string and return it.
+ */
+
+static char *
+lookupdesc (transp, val)
+ struct trans *transp;
+ unsigned int val;
+{
+ char *desc;
+
+ for (desc = NULL; transp -> name != NULL; transp++)
+ {
+ if (transp -> value == val)
+ {
+ desc = transp -> desc;
+ break;
+ }
+ }
+
+ /* Didn't find a translation for the specified value, set a default one. */
+
+ if (desc == NULL)
+ {
+ desc = "Unknown";
+ }
+ return (desc);
+}
+
+/*
+
+LOCAL FUNCTION
+
+ lookupname -- translate a value to symbolic name
+
+SYNOPSIS
+
+ static char *lookupname (struct trans *transp, unsigned int val,
+ char *prefix);
+
+DESCRIPTION
+
+ Given a pointer to a translation table, a value to be translated,
+ and a default prefix to return if the value can't be translated,
+ match the value with one of the translation table entries and
+ return a pointer to the symbolic name.
+
+ If no match is found it just returns the value as a printable string,
+ with the given prefix. The previous such value, if any, is freed
+ at this time.
+ */
+
+static char *
+lookupname (transp, val, prefix)
+ struct trans *transp;
+ unsigned int val;
+ char *prefix;
+{
+ static char *locbuf;
+ char *name;
+
+ for (name = NULL; transp -> name != NULL; transp++)
+ {
+ if (transp -> value == val)
+ {
+ name = transp -> name;
+ break;
+ }
+ }
+
+ /* Didn't find a translation for the specified value, build a default
+ one using the specified prefix and return it. The lifetime of
+ the value is only until the next one is needed. */
+
+ if (name == NULL)
+ {
+ if (locbuf != NULL)
+ {
+ free (locbuf);
+ }
+ locbuf = xmalloc (strlen (prefix) + 16);
+ sprintf (locbuf, "%s %u", prefix, val);
+ name = locbuf;
+ }
+ return (name);
+}
+
+static char *
+sigcodename (sip)
+ siginfo_t *sip;
+{
+ struct sigcode *scp;
+ char *name = NULL;
+ static char locbuf[32];
+
+ for (scp = siginfo_table; scp -> codename != NULL; scp++)
+ {
+ if ((scp -> signo == sip -> si_signo) &&
+ (scp -> code == sip -> si_code))
+ {
+ name = scp -> codename;
+ break;
+ }
+ }
+ if (name == NULL)
+ {
+ sprintf (locbuf, "sigcode %u", sip -> si_signo);
+ name = locbuf;
+ }
+ return (name);
+}
+
+static char *
+sigcodedesc (sip)
+ siginfo_t *sip;
+{
+ struct sigcode *scp;
+ char *desc = NULL;
+
+ for (scp = siginfo_table; scp -> codename != NULL; scp++)
+ {
+ if ((scp -> signo == sip -> si_signo) &&
+ (scp -> code == sip -> si_code))
+ {
+ desc = scp -> desc;
+ break;
+ }
+ }
+ if (desc == NULL)
+ {
+ desc = "Unrecognized signal or trap use";
+ }
+ return (desc);
+}
+
+/*
+
+LOCAL FUNCTION
+
+ syscallname - translate a system call number into a system call name
+
+SYNOPSIS
+
+ char *syscallname (int syscallnum)
+
+DESCRIPTION
+
+ Given a system call number, translate it into the printable name
+ of a system call, or into "syscall <num>" if it is an unknown
+ number.
+ */
+
+static char *
+syscallname (syscallnum)
+ int syscallnum;
+{
+ static char locbuf[32];
+
+ if (syscallnum >= 0 && syscallnum < MAX_SYSCALLS
+ && syscall_table[syscallnum] != NULL)
+ return syscall_table[syscallnum];
+ else
+ {
+ sprintf (locbuf, "syscall %u", syscallnum);
+ return locbuf;
+ }
+}
+
+/*
+
+LOCAL FUNCTION
+
+ init_syscall_table - initialize syscall translation table
+
+SYNOPSIS
+
+ void init_syscall_table (void)
+
+DESCRIPTION
+
+ Dynamically initialize the translation table to convert system
+ call numbers into printable system call names. Done once per
+ gdb run, on initialization.
+
+NOTES
+
+ This is awfully ugly, but preprocessor tricks to make it prettier
+ tend to be nonportable.
+ */
+
+static void
+init_syscall_table ()
+{
+#if defined (SYS_exit)
+ syscall_table[SYS_exit] = "exit";
+#endif
+#if defined (SYS_fork)
+ syscall_table[SYS_fork] = "fork";
+#endif
+#if defined (SYS_read)
+ syscall_table[SYS_read] = "read";
+#endif
+#if defined (SYS_write)
+ syscall_table[SYS_write] = "write";
+#endif
+#if defined (SYS_open)
+ syscall_table[SYS_open] = "open";
+#endif
+#if defined (SYS_close)
+ syscall_table[SYS_close] = "close";
+#endif
+#if defined (SYS_wait)
+ syscall_table[SYS_wait] = "wait";
+#endif
+#if defined (SYS_creat)
+ syscall_table[SYS_creat] = "creat";
+#endif
+#if defined (SYS_link)
+ syscall_table[SYS_link] = "link";
+#endif
+#if defined (SYS_unlink)
+ syscall_table[SYS_unlink] = "unlink";
+#endif
+#if defined (SYS_exec)
+ syscall_table[SYS_exec] = "exec";
+#endif
+#if defined (SYS_execv)
+ syscall_table[SYS_execv] = "execv";
+#endif
+#if defined (SYS_execve)
+ syscall_table[SYS_execve] = "execve";
+#endif
+#if defined (SYS_chdir)
+ syscall_table[SYS_chdir] = "chdir";
+#endif
+#if defined (SYS_time)
+ syscall_table[SYS_time] = "time";
+#endif
+#if defined (SYS_mknod)
+ syscall_table[SYS_mknod] = "mknod";
+#endif
+#if defined (SYS_chmod)
+ syscall_table[SYS_chmod] = "chmod";
+#endif
+#if defined (SYS_chown)
+ syscall_table[SYS_chown] = "chown";
+#endif
+#if defined (SYS_brk)
+ syscall_table[SYS_brk] = "brk";
+#endif
+#if defined (SYS_stat)
+ syscall_table[SYS_stat] = "stat";
+#endif
+#if defined (SYS_lseek)
+ syscall_table[SYS_lseek] = "lseek";
+#endif
+#if defined (SYS_getpid)
+ syscall_table[SYS_getpid] = "getpid";
+#endif
+#if defined (SYS_mount)
+ syscall_table[SYS_mount] = "mount";
+#endif
+#if defined (SYS_umount)
+ syscall_table[SYS_umount] = "umount";
+#endif
+#if defined (SYS_setuid)
+ syscall_table[SYS_setuid] = "setuid";
+#endif
+#if defined (SYS_getuid)
+ syscall_table[SYS_getuid] = "getuid";
+#endif
+#if defined (SYS_stime)
+ syscall_table[SYS_stime] = "stime";
+#endif
+#if defined (SYS_ptrace)
+ syscall_table[SYS_ptrace] = "ptrace";
+#endif
+#if defined (SYS_alarm)
+ syscall_table[SYS_alarm] = "alarm";
+#endif
+#if defined (SYS_fstat)
+ syscall_table[SYS_fstat] = "fstat";
+#endif
+#if defined (SYS_pause)
+ syscall_table[SYS_pause] = "pause";
+#endif
+#if defined (SYS_utime)
+ syscall_table[SYS_utime] = "utime";
+#endif
+#if defined (SYS_stty)
+ syscall_table[SYS_stty] = "stty";
+#endif
+#if defined (SYS_gtty)
+ syscall_table[SYS_gtty] = "gtty";
+#endif
+#if defined (SYS_access)
+ syscall_table[SYS_access] = "access";
+#endif
+#if defined (SYS_nice)
+ syscall_table[SYS_nice] = "nice";
+#endif
+#if defined (SYS_statfs)
+ syscall_table[SYS_statfs] = "statfs";
+#endif
+#if defined (SYS_sync)
+ syscall_table[SYS_sync] = "sync";
+#endif
+#if defined (SYS_kill)
+ syscall_table[SYS_kill] = "kill";
+#endif
+#if defined (SYS_fstatfs)
+ syscall_table[SYS_fstatfs] = "fstatfs";
+#endif
+#if defined (SYS_pgrpsys)
+ syscall_table[SYS_pgrpsys] = "pgrpsys";
+#endif
+#if defined (SYS_xenix)
+ syscall_table[SYS_xenix] = "xenix";
+#endif
+#if defined (SYS_dup)
+ syscall_table[SYS_dup] = "dup";
+#endif
+#if defined (SYS_pipe)
+ syscall_table[SYS_pipe] = "pipe";
+#endif
+#if defined (SYS_times)
+ syscall_table[SYS_times] = "times";
+#endif
+#if defined (SYS_profil)
+ syscall_table[SYS_profil] = "profil";
+#endif
+#if defined (SYS_plock)
+ syscall_table[SYS_plock] = "plock";
+#endif
+#if defined (SYS_setgid)
+ syscall_table[SYS_setgid] = "setgid";
+#endif
+#if defined (SYS_getgid)
+ syscall_table[SYS_getgid] = "getgid";
+#endif
+#if defined (SYS_signal)
+ syscall_table[SYS_signal] = "signal";
+#endif
+#if defined (SYS_msgsys)
+ syscall_table[SYS_msgsys] = "msgsys";
+#endif
+#if defined (SYS_sys3b)
+ syscall_table[SYS_sys3b] = "sys3b";
+#endif
+#if defined (SYS_sysi86)
+ syscall_table[SYS_sysi86] = "sysi86";
+#endif
+#if defined (SYS_acct)
+ syscall_table[SYS_acct] = "acct";
+#endif
+#if defined (SYS_shmsys)
+ syscall_table[SYS_shmsys] = "shmsys";
+#endif
+#if defined (SYS_semsys)
+ syscall_table[SYS_semsys] = "semsys";
+#endif
+#if defined (SYS_ioctl)
+ syscall_table[SYS_ioctl] = "ioctl";
+#endif
+#if defined (SYS_uadmin)
+ syscall_table[SYS_uadmin] = "uadmin";
+#endif
+#if defined (SYS_utssys)
+ syscall_table[SYS_utssys] = "utssys";
+#endif
+#if defined (SYS_fsync)
+ syscall_table[SYS_fsync] = "fsync";
+#endif
+#if defined (SYS_umask)
+ syscall_table[SYS_umask] = "umask";
+#endif
+#if defined (SYS_chroot)
+ syscall_table[SYS_chroot] = "chroot";
+#endif
+#if defined (SYS_fcntl)
+ syscall_table[SYS_fcntl] = "fcntl";
+#endif
+#if defined (SYS_ulimit)
+ syscall_table[SYS_ulimit] = "ulimit";
+#endif
+#if defined (SYS_rfsys)
+ syscall_table[SYS_rfsys] = "rfsys";
+#endif
+#if defined (SYS_rmdir)
+ syscall_table[SYS_rmdir] = "rmdir";
+#endif
+#if defined (SYS_mkdir)
+ syscall_table[SYS_mkdir] = "mkdir";
+#endif
+#if defined (SYS_getdents)
+ syscall_table[SYS_getdents] = "getdents";
+#endif
+#if defined (SYS_sysfs)
+ syscall_table[SYS_sysfs] = "sysfs";
+#endif
+#if defined (SYS_getmsg)
+ syscall_table[SYS_getmsg] = "getmsg";
+#endif
+#if defined (SYS_putmsg)
+ syscall_table[SYS_putmsg] = "putmsg";
+#endif
+#if defined (SYS_poll)
+ syscall_table[SYS_poll] = "poll";
+#endif
+#if defined (SYS_lstat)
+ syscall_table[SYS_lstat] = "lstat";
+#endif
+#if defined (SYS_symlink)
+ syscall_table[SYS_symlink] = "symlink";
+#endif
+#if defined (SYS_readlink)
+ syscall_table[SYS_readlink] = "readlink";
+#endif
+#if defined (SYS_setgroups)
+ syscall_table[SYS_setgroups] = "setgroups";
+#endif
+#if defined (SYS_getgroups)
+ syscall_table[SYS_getgroups] = "getgroups";
+#endif
+#if defined (SYS_fchmod)
+ syscall_table[SYS_fchmod] = "fchmod";
+#endif
+#if defined (SYS_fchown)
+ syscall_table[SYS_fchown] = "fchown";
+#endif
+#if defined (SYS_sigprocmask)
+ syscall_table[SYS_sigprocmask] = "sigprocmask";
+#endif
+#if defined (SYS_sigsuspend)
+ syscall_table[SYS_sigsuspend] = "sigsuspend";
+#endif
+#if defined (SYS_sigaltstack)
+ syscall_table[SYS_sigaltstack] = "sigaltstack";
+#endif
+#if defined (SYS_sigaction)
+ syscall_table[SYS_sigaction] = "sigaction";
+#endif
+#if defined (SYS_sigpending)
+ syscall_table[SYS_sigpending] = "sigpending";
+#endif
+#if defined (SYS_context)
+ syscall_table[SYS_context] = "context";
+#endif
+#if defined (SYS_evsys)
+ syscall_table[SYS_evsys] = "evsys";
+#endif
+#if defined (SYS_evtrapret)
+ syscall_table[SYS_evtrapret] = "evtrapret";
+#endif
+#if defined (SYS_statvfs)
+ syscall_table[SYS_statvfs] = "statvfs";
+#endif
+#if defined (SYS_fstatvfs)
+ syscall_table[SYS_fstatvfs] = "fstatvfs";
+#endif
+#if defined (SYS_nfssys)
+ syscall_table[SYS_nfssys] = "nfssys";
+#endif
+#if defined (SYS_waitsys)
+ syscall_table[SYS_waitsys] = "waitsys";
+#endif
+#if defined (SYS_sigsendsys)
+ syscall_table[SYS_sigsendsys] = "sigsendsys";
+#endif
+#if defined (SYS_hrtsys)
+ syscall_table[SYS_hrtsys] = "hrtsys";
+#endif
+#if defined (SYS_acancel)
+ syscall_table[SYS_acancel] = "acancel";
+#endif
+#if defined (SYS_async)
+ syscall_table[SYS_async] = "async";
+#endif
+#if defined (SYS_priocntlsys)
+ syscall_table[SYS_priocntlsys] = "priocntlsys";
+#endif
+#if defined (SYS_pathconf)
+ syscall_table[SYS_pathconf] = "pathconf";
+#endif
+#if defined (SYS_mincore)
+ syscall_table[SYS_mincore] = "mincore";
+#endif
+#if defined (SYS_mmap)
+ syscall_table[SYS_mmap] = "mmap";
+#endif
+#if defined (SYS_mprotect)
+ syscall_table[SYS_mprotect] = "mprotect";
+#endif
+#if defined (SYS_munmap)
+ syscall_table[SYS_munmap] = "munmap";
+#endif
+#if defined (SYS_fpathconf)
+ syscall_table[SYS_fpathconf] = "fpathconf";
+#endif
+#if defined (SYS_vfork)
+ syscall_table[SYS_vfork] = "vfork";
+#endif
+#if defined (SYS_fchdir)
+ syscall_table[SYS_fchdir] = "fchdir";
+#endif
+#if defined (SYS_readv)
+ syscall_table[SYS_readv] = "readv";
+#endif
+#if defined (SYS_writev)
+ syscall_table[SYS_writev] = "writev";
+#endif
+#if defined (SYS_xstat)
+ syscall_table[SYS_xstat] = "xstat";
+#endif
+#if defined (SYS_lxstat)
+ syscall_table[SYS_lxstat] = "lxstat";
+#endif
+#if defined (SYS_fxstat)
+ syscall_table[SYS_fxstat] = "fxstat";
+#endif
+#if defined (SYS_xmknod)
+ syscall_table[SYS_xmknod] = "xmknod";
+#endif
+#if defined (SYS_clocal)
+ syscall_table[SYS_clocal] = "clocal";
+#endif
+#if defined (SYS_setrlimit)
+ syscall_table[SYS_setrlimit] = "setrlimit";
+#endif
+#if defined (SYS_getrlimit)
+ syscall_table[SYS_getrlimit] = "getrlimit";
+#endif
+#if defined (SYS_lchown)
+ syscall_table[SYS_lchown] = "lchown";
+#endif
+#if defined (SYS_memcntl)
+ syscall_table[SYS_memcntl] = "memcntl";
+#endif
+#if defined (SYS_getpmsg)
+ syscall_table[SYS_getpmsg] = "getpmsg";
+#endif
+#if defined (SYS_putpmsg)
+ syscall_table[SYS_putpmsg] = "putpmsg";
+#endif
+#if defined (SYS_rename)
+ syscall_table[SYS_rename] = "rename";
+#endif
+#if defined (SYS_uname)
+ syscall_table[SYS_uname] = "uname";
+#endif
+#if defined (SYS_setegid)
+ syscall_table[SYS_setegid] = "setegid";
+#endif
+#if defined (SYS_sysconfig)
+ syscall_table[SYS_sysconfig] = "sysconfig";
+#endif
+#if defined (SYS_adjtime)
+ syscall_table[SYS_adjtime] = "adjtime";
+#endif
+#if defined (SYS_systeminfo)
+ syscall_table[SYS_systeminfo] = "systeminfo";
+#endif
+#if defined (SYS_seteuid)
+ syscall_table[SYS_seteuid] = "seteuid";
+#endif
+#if defined (SYS_sproc)
+ syscall_table[SYS_sproc] = "sproc";
+#endif
+#if defined (SYS_keyctl)
+ syscall_table[SYS_keyctl] = "keyctl";
+#endif
+#if defined (SYS_secsys)
+ syscall_table[SYS_secsys] = "secsys";
+#endif
+#if defined (SYS_filepriv)
+ syscall_table[SYS_filepriv] = "filepriv";
+#endif
+#if defined (SYS_procpriv)
+ syscall_table[SYS_procpriv] = "procpriv";
+#endif
+#if defined (SYS_devstat)
+ syscall_table[SYS_devstat] = "devstat";
+#endif
+#if defined (SYS_aclipc)
+ syscall_table[SYS_aclipc] = "aclipc";
+#endif
+#if defined (SYS_fdevstat)
+ syscall_table[SYS_fdevstat] = "fdevstat";
+#endif
+#if defined (SYS_flvlfile)
+ syscall_table[SYS_flvlfile] = "flvlfile";
+#endif
+#if defined (SYS_lvlfile)
+ syscall_table[SYS_lvlfile] = "lvlfile";
+#endif
+#if defined (SYS_lvlequal)
+ syscall_table[SYS_lvlequal] = "lvlequal";
+#endif
+#if defined (SYS_lvlproc)
+ syscall_table[SYS_lvlproc] = "lvlproc";
+#endif
+#if defined (SYS_lvlipc)
+ syscall_table[SYS_lvlipc] = "lvlipc";
+#endif
+#if defined (SYS_acl)
+ syscall_table[SYS_acl] = "acl";
+#endif
+#if defined (SYS_auditevt)
+ syscall_table[SYS_auditevt] = "auditevt";
+#endif
+#if defined (SYS_auditctl)
+ syscall_table[SYS_auditctl] = "auditctl";
+#endif
+#if defined (SYS_auditdmp)
+ syscall_table[SYS_auditdmp] = "auditdmp";
+#endif
+#if defined (SYS_auditlog)
+ syscall_table[SYS_auditlog] = "auditlog";
+#endif
+#if defined (SYS_auditbuf)
+ syscall_table[SYS_auditbuf] = "auditbuf";
+#endif
+#if defined (SYS_lvldom)
+ syscall_table[SYS_lvldom] = "lvldom";
+#endif
+#if defined (SYS_lvlvfs)
+ syscall_table[SYS_lvlvfs] = "lvlvfs";
+#endif
+#if defined (SYS_mkmld)
+ syscall_table[SYS_mkmld] = "mkmld";
+#endif
+#if defined (SYS_mldmode)
+ syscall_table[SYS_mldmode] = "mldmode";
+#endif
+#if defined (SYS_secadvise)
+ syscall_table[SYS_secadvise] = "secadvise";
+#endif
+#if defined (SYS_online)
+ syscall_table[SYS_online] = "online";
+#endif
+#if defined (SYS_setitimer)
+ syscall_table[SYS_setitimer] = "setitimer";
+#endif
+#if defined (SYS_getitimer)
+ syscall_table[SYS_getitimer] = "getitimer";
+#endif
+#if defined (SYS_gettimeofday)
+ syscall_table[SYS_gettimeofday] = "gettimeofday";
+#endif
+#if defined (SYS_settimeofday)
+ syscall_table[SYS_settimeofday] = "settimeofday";
+#endif
+#if defined (SYS_lwp_create)
+ syscall_table[SYS_lwp_create] = "_lwp_create";
+#endif
+#if defined (SYS_lwp_exit)
+ syscall_table[SYS_lwp_exit] = "_lwp_exit";
+#endif
+#if defined (SYS_lwp_wait)
+ syscall_table[SYS_lwp_wait] = "_lwp_wait";
+#endif
+#if defined (SYS_lwp_self)
+ syscall_table[SYS_lwp_self] = "_lwp_self";
+#endif
+#if defined (SYS_lwp_info)
+ syscall_table[SYS_lwp_info] = "_lwp_info";
+#endif
+#if defined (SYS_lwp_private)
+ syscall_table[SYS_lwp_private] = "_lwp_private";
+#endif
+#if defined (SYS_processor_bind)
+ syscall_table[SYS_processor_bind] = "processor_bind";
+#endif
+#if defined (SYS_processor_exbind)
+ syscall_table[SYS_processor_exbind] = "processor_exbind";
+#endif
+#if defined (SYS_prepblock)
+ syscall_table[SYS_prepblock] = "prepblock";
+#endif
+#if defined (SYS_block)
+ syscall_table[SYS_block] = "block";
+#endif
+#if defined (SYS_rdblock)
+ syscall_table[SYS_rdblock] = "rdblock";
+#endif
+#if defined (SYS_unblock)
+ syscall_table[SYS_unblock] = "unblock";
+#endif
+#if defined (SYS_cancelblock)
+ syscall_table[SYS_cancelblock] = "cancelblock";
+#endif
+#if defined (SYS_pread)
+ syscall_table[SYS_pread] = "pread";
+#endif
+#if defined (SYS_pwrite)
+ syscall_table[SYS_pwrite] = "pwrite";
+#endif
+#if defined (SYS_truncate)
+ syscall_table[SYS_truncate] = "truncate";
+#endif
+#if defined (SYS_ftruncate)
+ syscall_table[SYS_ftruncate] = "ftruncate";
+#endif
+#if defined (SYS_lwp_kill)
+ syscall_table[SYS_lwp_kill] = "_lwp_kill";
+#endif
+#if defined (SYS_sigwait)
+ syscall_table[SYS_sigwait] = "sigwait";
+#endif
+#if defined (SYS_fork1)
+ syscall_table[SYS_fork1] = "fork1";
+#endif
+#if defined (SYS_forkall)
+ syscall_table[SYS_forkall] = "forkall";
+#endif
+#if defined (SYS_modload)
+ syscall_table[SYS_modload] = "modload";
+#endif
+#if defined (SYS_moduload)
+ syscall_table[SYS_moduload] = "moduload";
+#endif
+#if defined (SYS_modpath)
+ syscall_table[SYS_modpath] = "modpath";
+#endif
+#if defined (SYS_modstat)
+ syscall_table[SYS_modstat] = "modstat";
+#endif
+#if defined (SYS_modadm)
+ syscall_table[SYS_modadm] = "modadm";
+#endif
+#if defined (SYS_getksym)
+ syscall_table[SYS_getksym] = "getksym";
+#endif
+#if defined (SYS_lwp_suspend)
+ syscall_table[SYS_lwp_suspend] = "_lwp_suspend";
+#endif
+#if defined (SYS_lwp_continue)
+ syscall_table[SYS_lwp_continue] = "_lwp_continue";
+#endif
+#if defined (SYS_priocntllst)
+ syscall_table[SYS_priocntllst] = "priocntllst";
+#endif
+#if defined (SYS_sleep)
+ syscall_table[SYS_sleep] = "sleep";
+#endif
+#if defined (SYS_lwp_sema_wait)
+ syscall_table[SYS_lwp_sema_wait] = "_lwp_sema_wait";
+#endif
+#if defined (SYS_lwp_sema_post)
+ syscall_table[SYS_lwp_sema_post] = "_lwp_sema_post";
+#endif
+#if defined (SYS_lwp_sema_trywait)
+ syscall_table[SYS_lwp_sema_trywait] = "lwp_sema_trywait";
+#endif
+#if defined(SYS_fstatvfs64)
+ syscall_table[SYS_fstatvfs64] = "fstatvfs64";
+#endif
+#if defined(SYS_statvfs64)
+ syscall_table[SYS_statvfs64] = "statvfs64";
+#endif
+#if defined(SYS_ftruncate64)
+ syscall_table[SYS_ftruncate64] = "ftruncate64";
+#endif
+#if defined(SYS_truncate64)
+ syscall_table[SYS_truncate64] = "truncate64";
+#endif
+#if defined(SYS_getrlimit64)
+ syscall_table[SYS_getrlimit64] = "getrlimit64";
+#endif
+#if defined(SYS_setrlimit64)
+ syscall_table[SYS_setrlimit64] = "setrlimit64";
+#endif
+#if defined(SYS_lseek64)
+ syscall_table[SYS_lseek64] = "lseek64";
+#endif
+#if defined(SYS_mmap64)
+ syscall_table[SYS_mmap64] = "mmap64";
+#endif
+#if defined(SYS_pread64)
+ syscall_table[SYS_pread64] = "pread64";
+#endif
+#if defined(SYS_creat64)
+ syscall_table[SYS_creat64] = "creat64";
+#endif
+#if defined(SYS_dshmsys)
+ syscall_table[SYS_dshmsys] = "dshmsys";
+#endif
+#if defined(SYS_invlpg)
+ syscall_table[SYS_invlpg] = "invlpg";
+#endif
+#if defined(SYS_cg_ids)
+ syscall_table[SYS_cg_ids] = "cg_ids";
+#endif
+#if defined(SYS_cg_processors)
+ syscall_table[SYS_cg_processors] = "cg_processors";
+#endif
+#if defined(SYS_cg_info)
+ syscall_table[SYS_cg_info] = "cg_info";
+#endif
+#if defined(SYS_cg_bind)
+ syscall_table[SYS_cg_bind] = "cg_bind";
+#endif
+#if defined(SYS_cg_current)
+ syscall_table[SYS_cg_current] = "cg_current";
+#endif
+#if defined(SYS_cg_memloc)
+ syscall_table[SYS_cg_memloc] = "cg_memloc";
+#endif
+}
+
+/*
+
+LOCAL FUNCTION
+
+ procfs_kill_inferior - kill any currently inferior
+
+SYNOPSIS
+
+ void procfs_kill_inferior (void)
+
+DESCRIPTION
+
+ Kill any current inferior.
+
+NOTES
+
+ Kills even attached inferiors. Presumably the user has already
+ been prompted that the inferior is an attached one rather than
+ one started by gdb. (FIXME?)
+
+*/
+
+static void
+procfs_kill_inferior ()
+{
+ target_mourn_inferior ();
+}
+
+/*
+
+LOCAL FUNCTION
+
+ unconditionally_kill_inferior - terminate the inferior
+
+SYNOPSIS
+
+ static void unconditionally_kill_inferior (struct procinfo *)
+
+DESCRIPTION
+
+ Kill the specified inferior.
+
+NOTE
+
+ A possibly useful enhancement would be to first try sending
+ the inferior a terminate signal, politely asking it to commit
+ suicide, before we murder it (we could call that
+ politely_kill_inferior()).
+
+*/
+
+static void
+unconditionally_kill_inferior (pi)
+ struct procinfo *pi;
+{
+ int ppid;
+ struct proc_ctl pctl;
+
+ ppid = pi->prstatus.pr_ppid;
+
+#ifdef PROCFS_NEED_CLEAR_CURSIG_FOR_KILL
+ /* Alpha OSF/1-3.x procfs needs a clear of the current signal
+ before the PIOCKILL, otherwise it might generate a corrupted core
+ file for the inferior. */
+ ioctl (pi->ctl_fd, PIOCSSIG, NULL);
+#endif
+#ifdef PROCFS_NEED_PIOCSSIG_FOR_KILL
+ /* Alpha OSF/1-2.x procfs needs a PIOCSSIG call with a SIGKILL signal
+ to kill the inferior, otherwise it might remain stopped with a
+ pending SIGKILL.
+ We do not check the result of the PIOCSSIG, the inferior might have
+ died already. */
+ {
+ struct siginfo newsiginfo;
+
+ memset ((char *) &newsiginfo, 0, sizeof (newsiginfo));
+ newsiginfo.si_signo = SIGKILL;
+ newsiginfo.si_code = 0;
+ newsiginfo.si_errno = 0;
+ newsiginfo.si_pid = getpid ();
+ newsiginfo.si_uid = getuid ();
+ ioctl (pi->ctl_fd, PIOCSSIG, &newsiginfo);
+ }
+#else /* PROCFS_NEED_PIOCSSIG_FOR_KILL */
+ procfs_write_pckill (pi);
+#endif /* PROCFS_NEED_PIOCSSIG_FOR_KILL */
+
+ close_proc_file (pi);
+
+/* Only wait() for our direct children. Our grandchildren zombies are killed
+ by the death of their parents. */
+
+ if (ppid == getpid())
+ wait ((int *) 0);
+}
+
+/*
+
+LOCAL FUNCTION
+
+ procfs_xfer_memory -- copy data to or from inferior memory space
+
+SYNOPSIS
+
+ int procfs_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len,
+ int dowrite, struct target_ops target)
+
+DESCRIPTION
+
+ Copy LEN bytes to/from inferior's memory starting at MEMADDR
+ from/to debugger memory starting at MYADDR. Copy from inferior
+ if DOWRITE is zero or to inferior if DOWRITE is nonzero.
+
+ Returns the length copied, which is either the LEN argument or
+ zero. This xfer function does not do partial moves, since procfs_ops
+ doesn't allow memory operations to cross below us in the target stack
+ anyway.
+
+NOTES
+
+ The /proc interface makes this an almost trivial task.
+ */
+
+static int
+procfs_xfer_memory (memaddr, myaddr, len, dowrite, target)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+ int dowrite;
+ struct target_ops *target; /* ignored */
+{
+ int nbytes = 0;
+ struct procinfo *pi;
+
+ pi = current_procinfo;
+
+ if (lseek(pi->as_fd, (off_t) memaddr, SEEK_SET) == (off_t) memaddr)
+ {
+ if (dowrite)
+ {
+ nbytes = write (pi->as_fd, myaddr, len);
+ }
+ else
+ {
+ nbytes = read (pi->as_fd, myaddr, len);
+ }
+ if (nbytes < 0)
+ {
+ nbytes = 0;
+ }
+ }
+ return (nbytes);
+}
+
+/*
+
+LOCAL FUNCTION
+
+ procfs_store_registers -- copy register values back to inferior
+
+SYNOPSIS
+
+ void procfs_store_registers (int regno)
+
+DESCRIPTION
+
+ Store our current register values back into the inferior. If
+ REGNO is -1 then store all the register, otherwise store just
+ the value specified by REGNO.
+
+NOTES
+
+ If we are storing only a single register, we first have to get all
+ the current values from the process, overwrite the desired register
+ in the gregset with the one we want from gdb's registers, and then
+ send the whole set back to the process. For writing all the
+ registers, all we have to do is generate the gregset and send it to
+ the process.
+
+ Also note that the process has to be stopped on an event of interest
+ for this to work, which basically means that it has to have been
+ run under the control of one of the other /proc ioctl calls and not
+ ptrace. Since we don't use ptrace anyway, we don't worry about this
+ fine point, but it is worth noting for future reference.
+
+ Gdb is confused about what this function is supposed to return.
+ Some versions return a value, others return nothing. Some are
+ declared to return a value and actually return nothing. Gdb ignores
+ anything returned. (FIXME)
+
+ */
+
+static void
+procfs_store_registers (regno)
+ int regno;
+{
+ struct procinfo *pi;
+#ifdef PROCFS_USE_READ_WRITE
+ struct greg_ctl greg;
+ struct fpreg_ctl fpreg;
+#endif
+
+ pi = current_procinfo;
+
+#ifdef PROCFS_USE_READ_WRITE
+ if (regno != -1)
+ {
+ procfs_read_status (pi);
+ memcpy ((char *) &greg.gregset,
+ (char *) &pi->prstatus.pr_lwp.pr_context.uc_mcontext.gregs,
+ sizeof (gdb_gregset_t));
+ }
+ fill_gregset (&greg.gregset, regno);
+ greg.cmd = PCSREG;
+ write (pi->ctl_fd, &greg, sizeof (greg));
+#else /* PROCFS_USE_READ_WRITE */
+ if (regno != -1)
+ {
+ ioctl (pi->ctl_fd, PIOCGREG, &pi->gregset.gregset);
+ }
+ fill_gregset (&pi->gregset.gregset, regno);
+ ioctl (pi->ctl_fd, PIOCSREG, &pi->gregset.gregset);
+#endif /* PROCFS_USE_READ_WRITE */
+
+#if defined (FP0_REGNUM)
+
+ /* Now repeat everything using the floating point register set, if the
+ target has floating point hardware. Since we ignore the returned value,
+ we'll never know whether it worked or not anyway. */
+
+#ifdef PROCFS_USE_READ_WRITE
+ if (regno != -1)
+ {
+ procfs_read_status (pi);
+ memcpy ((char *) &fpreg.fpregset,
+ (char *) &pi->prstatus.pr_lwp.pr_context.uc_mcontext.fpregs,
+ sizeof (gdb_fpregset_t));
+ }
+ fill_fpregset (&fpreg.fpregset, regno);
+ fpreg.cmd = PCSFPREG;
+ write (pi->ctl_fd, &fpreg, sizeof (fpreg));
+#else /* PROCFS_USE_READ_WRITE */
+ if (regno != -1)
+ {
+ ioctl (pi->ctl_fd, PIOCGFPREG, &pi->fpregset.fpregset);
+ }
+ fill_fpregset (&pi->fpregset.fpregset, regno);
+ ioctl (pi->ctl_fd, PIOCSFPREG, &pi->fpregset.fpregset);
+#endif /* PROCFS_USE_READ_WRITE */
+
+#endif /* FP0_REGNUM */
+
+}
+
+/*
+
+LOCAL FUNCTION
+
+ init_procinfo - setup a procinfo struct and connect it to a process
+
+SYNOPSIS
+
+ struct procinfo * init_procinfo (int pid)
+
+DESCRIPTION
+
+ Allocate a procinfo structure, open the /proc file and then set up the
+ set of signals and faults that are to be traced. Returns a pointer to
+ the new procinfo structure.
+
+NOTES
+
+ If proc_init_failed ever gets called, control returns to the command
+ processing loop via the standard error handling code.
+
+ */
+
+static struct procinfo *
+init_procinfo (pid, kill)
+ int pid;
+ int kill;
+{
+ struct procinfo *pi = (struct procinfo *)
+ xmalloc (sizeof (struct procinfo));
+ struct sig_ctl sctl;
+ struct flt_ctl fctl;
+
+ memset ((char *) pi, 0, sizeof (*pi));
+ if (!open_proc_file (pid, pi, O_RDWR, 1))
+ proc_init_failed (pi, "can't open process file", kill);
+
+ /* open_proc_file may modify pid. */
+
+ pid = pi -> pid;
+
+ /* Add new process to process info list */
+
+ pi->next = procinfo_list;
+ procinfo_list = pi;
+
+ add_fd (pi); /* Add to list for poll/select */
+
+ /* Remember some things about the inferior that we will, or might, change
+ so that we can restore them when we detach. */
+#ifdef UNIXWARE
+ memcpy ((char *) &pi->saved_trace.sigset,
+ (char *) &pi->prstatus.pr_sigtrace, sizeof (sigset_t));
+ memcpy ((char *) &pi->saved_fltset.fltset,
+ (char *) &pi->prstatus.pr_flttrace, sizeof (fltset_t));
+ memcpy ((char *) &pi->saved_entryset.sysset,
+ (char *) &pi->prstatus.pr_sysentry, sizeof (sysset_t));
+ memcpy ((char *) &pi->saved_exitset.sysset,
+ (char *) &pi->prstatus.pr_sysexit, sizeof (sysset_t));
+
+ /* Set up trace and fault sets, as gdb expects them. */
+
+ prfillset (&sctl.sigset);
+ notice_signals (pi, &sctl);
+ prfillset (&fctl.fltset);
+ prdelset (&fctl.fltset, FLTPAGE);
+
+#else /* ! UNIXWARE */
+ ioctl (pi->ctl_fd, PIOCGTRACE, &pi->saved_trace.sigset);
+ ioctl (pi->ctl_fd, PIOCGHOLD, &pi->saved_sighold.sigset);
+ ioctl (pi->ctl_fd, PIOCGFAULT, &pi->saved_fltset.fltset);
+ ioctl (pi->ctl_fd, PIOCGENTRY, &pi->saved_entryset.sysset);
+ ioctl (pi->ctl_fd, PIOCGEXIT, &pi->saved_exitset.sysset);
+
+ /* Set up trace and fault sets, as gdb expects them. */
+
+ memset ((char *) &pi->prrun, 0, sizeof (pi->prrun));
+ prfillset (&pi->prrun.pr_trace);
+ procfs_notice_signals (pid);
+ prfillset (&pi->prrun.pr_fault);
+ prdelset (&pi->prrun.pr_fault, FLTPAGE);
+#ifdef PROCFS_DONT_TRACE_FAULTS
+ premptyset (&pi->prrun.pr_fault);
+#endif
+#endif /* UNIXWARE */
+
+ if (!procfs_read_status (pi))
+ proc_init_failed (pi, "procfs_read_status failed", kill);
+
+ return pi;
+}
+
+/*
+
+LOCAL FUNCTION
+
+ create_procinfo - initialize access to a /proc entry
+
+SYNOPSIS
+
+ struct procinfo * create_procinfo (int pid)
+
+DESCRIPTION
+
+ Allocate a procinfo structure, open the /proc file and then set up the
+ set of signals and faults that are to be traced. Returns a pointer to
+ the new procinfo structure.
+
+NOTES
+
+ If proc_init_failed ever gets called, control returns to the command
+ processing loop via the standard error handling code.
+
+ */
+
+static struct procinfo *
+create_procinfo (pid)
+ int pid;
+{
+ struct procinfo *pi;
+ struct sig_ctl sctl;
+ struct flt_ctl fctl;
+
+ pi = find_procinfo (pid, 1);
+ if (pi != NULL)
+ return pi; /* All done! It already exists */
+
+ pi = init_procinfo (pid, 1);
+
+#ifndef UNIXWARE
+/* A bug in Solaris (2.5 at least) causes PIOCWSTOP to hang on LWPs that are
+ already stopped, even if they all have PR_ASYNC set. */
+ if (!(pi->prstatus.pr_flags & PR_STOPPED))
+#endif
+ if (!procfs_write_pcwstop (pi))
+ proc_init_failed (pi, "procfs_write_pcwstop failed", 1);
+
+#ifdef PROCFS_USE_READ_WRITE
+ fctl.cmd = PCSFAULT;
+ if (write (pi->ctl_fd, (char *) &fctl, sizeof (struct flt_ctl)) < 0)
+ proc_init_failed (pi, "PCSFAULT failed", 1);
+#else
+ if (ioctl (pi->ctl_fd, PIOCSFAULT, &pi->prrun.pr_fault) < 0)
+ proc_init_failed (pi, "PIOCSFAULT failed", 1);
+#endif
+
+ return pi;
+}
+
+/*
+
+LOCAL FUNCTION
+
+ procfs_exit_handler - handle entry into the _exit syscall
+
+SYNOPSIS
+
+ int procfs_exit_handler (pi, syscall_num, why, rtnvalp, statvalp)
+
+DESCRIPTION
+
+ This routine is called when an inferior process enters the _exit()
+ system call. It continues the process, and then collects the exit
+ status and pid which are returned in *statvalp and *rtnvalp. After
+ that it returns non-zero to indicate that procfs_wait should wake up.
+
+NOTES
+ There is probably a better way to do this.
+
+ */
+
+static int
+procfs_exit_handler (pi, syscall_num, why, rtnvalp, statvalp)
+ struct procinfo *pi;
+ int syscall_num;
+ int why;
+ int *rtnvalp;
+ int *statvalp;
+{
+ struct procinfo *temp_pi, *next_pi;
+ struct proc_ctl pctl;
+
+#ifdef UNIXWARE
+ pctl.cmd = PCRUN;
+ pctl.data = PRCFAULT;
+#else
+ pi->prrun.pr_flags = PRCFAULT;
+#endif
+
+#ifdef PROCFS_USE_READ_WRITE
+ if (write (pi->ctl_fd, (char *)&pctl, sizeof (struct proc_ctl)) < 0)
+#else
+ if (ioctl (pi->ctl_fd, PIOCRUN, &pi->prrun) != 0)
+#endif
+ perror_with_name (pi->pathname);
+
+ if (attach_flag)
+ {
+ /* Claim it exited (don't call wait). */
+ if (info_verbose)
+ printf_filtered ("(attached process has exited)\n");
+ *statvalp = 0;
+ *rtnvalp = inferior_pid;
+ }
+ else
+ {
+ *rtnvalp = wait (statvalp);
+ if (*rtnvalp >= 0)
+ *rtnvalp = pi->pid;
+ }
+
+ /* Close ALL open proc file handles,
+ except the one that called SYS_exit. */
+ for (temp_pi = procinfo_list; temp_pi; temp_pi = next_pi)
+ {
+ next_pi = temp_pi->next;
+ if (temp_pi == pi)
+ continue; /* Handled below */
+ close_proc_file (temp_pi);
+ }
+ return 1;
+}
+
+/*
+
+LOCAL FUNCTION
+
+ procfs_exec_handler - handle exit from the exec family of syscalls
+
+SYNOPSIS
+
+ int procfs_exec_handler (pi, syscall_num, why, rtnvalp, statvalp)
+
+DESCRIPTION
+
+ This routine is called when an inferior process is about to finish any
+ of the exec() family of system calls. It pretends that we got a
+ SIGTRAP (for compatibility with ptrace behavior), and returns non-zero
+ to tell procfs_wait to wake up.
+
+NOTES
+ This need for compatibility with ptrace is questionable. In the
+ future, it shouldn't be necessary.
+
+ */
+
+static int
+procfs_exec_handler (pi, syscall_num, why, rtnvalp, statvalp)
+ struct procinfo *pi;
+ int syscall_num;
+ int why;
+ int *rtnvalp;
+ int *statvalp;
+{
+ *statvalp = (SIGTRAP << 8) | 0177;
+
+ return 1;
+}
+
+#if defined(SYS_sproc) && !defined(UNIXWARE)
+/* IRIX lwp creation system call */
+
+/*
+
+LOCAL FUNCTION
+
+ procfs_sproc_handler - handle exit from the sproc syscall
+
+SYNOPSIS
+
+ int procfs_sproc_handler (pi, syscall_num, why, rtnvalp, statvalp)
+
+DESCRIPTION
+
+ This routine is called when an inferior process is about to finish an
+ sproc() system call. This is the system call that IRIX uses to create
+ a lightweight process. When the target process gets this event, we can
+ look at rval1 to find the new child processes ID, and create a new
+ procinfo struct from that.
+
+ After that, it pretends that we got a SIGTRAP, and returns non-zero
+ to tell procfs_wait to wake up. Subsequently, wait_for_inferior gets
+ woken up, sees the new process and continues it.
+
+NOTES
+ We actually never see the child exiting from sproc because we will
+ shortly stop the child with PIOCSTOP, which is then registered as the
+ event of interest.
+ */
+
+static int
+procfs_sproc_handler (pi, syscall_num, why, rtnvalp, statvalp)
+ struct procinfo *pi;
+ int syscall_num;
+ int why;
+ int *rtnvalp;
+ int *statvalp;
+{
+/* We've just detected the completion of an sproc system call. Now we need to
+ setup a procinfo struct for this thread, and notify the thread system of the
+ new arrival. */
+
+/* If sproc failed, then nothing interesting happened. Continue the process
+ and go back to sleep. */
+
+ if (pi->prstatus.pr_errno != 0)
+ {
+ pi->prrun.pr_flags &= PRSTEP;
+ pi->prrun.pr_flags |= PRCFAULT;
+
+ if (ioctl (pi->ctl_fd, PIOCRUN, &pi->prrun) != 0)
+ perror_with_name (pi->pathname);
+
+ return 0;
+ }
+
+ /* At this point, the new thread is stopped at it's first instruction, and
+ the parent is stopped at the exit from sproc. */
+
+ /* Notify the caller of the arrival of a new thread. */
+ create_procinfo (pi->prstatus.pr_rval1);
+
+ *rtnvalp = pi->prstatus.pr_rval1;
+ *statvalp = (SIGTRAP << 8) | 0177;
+
+ return 1;
+}
+
+/*
+
+LOCAL FUNCTION
+
+ procfs_fork_handler - handle exit from the fork syscall
+
+SYNOPSIS
+
+ int procfs_fork_handler (pi, syscall_num, why, rtnvalp, statvalp)
+
+DESCRIPTION
+
+ This routine is called when an inferior process is about to finish a
+ fork() system call. We will open up the new process, and then close
+ it, which releases it from the clutches of the debugger.
+
+ After that, we continue the target process as though nothing had
+ happened.
+
+NOTES
+ This is necessary for IRIX because we have to set PR_FORK in order
+ to catch the creation of lwps (via sproc()). When an actual fork
+ occurs, it becomes necessary to reset the forks debugger flags and
+ continue it because we can't hack multiple processes yet.
+ */
+
+static int
+procfs_fork_handler (pi, syscall_num, why, rtnvalp, statvalp)
+ struct procinfo *pi;
+ int syscall_num;
+ int why;
+ int *rtnvalp;
+ int *statvalp;
+{
+ struct procinfo *pitemp;
+
+/* At this point, we've detected the completion of a fork (or vfork) call in
+ our child. The grandchild is also stopped because we set inherit-on-fork
+ earlier. (Note that nobody has the grandchilds' /proc file open at this
+ point.) We will release the grandchild from the debugger by opening it's
+ /proc file and then closing it. Since run-on-last-close is set, the
+ grandchild continues on its' merry way. */
+
+
+ pitemp = create_procinfo (pi->prstatus.pr_rval1);
+ if (pitemp)
+ close_proc_file (pitemp);
+
+ if (ioctl (pi->ctl_fd, PIOCRUN, &pi->prrun) != 0)
+ perror_with_name (pi->pathname);
+
+ return 0;
+}
+#endif /* SYS_sproc && !UNIXWARE */
+
+/*
+
+LOCAL FUNCTION
+
+ procfs_set_inferior_syscall_traps - setup the syscall traps
+
+SYNOPSIS
+
+ void procfs_set_inferior_syscall_traps (struct procinfo *pip)
+
+DESCRIPTION
+
+ Called for each "procinfo" (process, thread, or LWP) in the
+ inferior, to register for notification of and handlers for
+ syscall traps in the inferior.
+
+ */
+
+static void
+procfs_set_inferior_syscall_traps (pip)
+ struct procinfo *pip;
+{
+ procfs_set_syscall_trap (pip, SYS_exit, PROCFS_SYSCALL_ENTRY,
+ procfs_exit_handler);
+
+#ifndef PRFS_STOPEXEC
+#ifdef SYS_exec
+ procfs_set_syscall_trap (pip, SYS_exec, PROCFS_SYSCALL_EXIT,
+ procfs_exec_handler);
+#endif
+#ifdef SYS_execv
+ procfs_set_syscall_trap (pip, SYS_execv, PROCFS_SYSCALL_EXIT,
+ procfs_exec_handler);
+#endif
+#ifdef SYS_execve
+ procfs_set_syscall_trap (pip, SYS_execve, PROCFS_SYSCALL_EXIT,
+ procfs_exec_handler);
+#endif
+#endif /* PRFS_STOPEXEC */
+
+ /* Setup traps on exit from sproc() */
+
+#ifdef SYS_sproc
+ procfs_set_syscall_trap (pip, SYS_sproc, PROCFS_SYSCALL_EXIT,
+ procfs_sproc_handler);
+ procfs_set_syscall_trap (pip, SYS_fork, PROCFS_SYSCALL_EXIT,
+ procfs_fork_handler);
+#ifdef SYS_vfork
+ procfs_set_syscall_trap (pip, SYS_vfork, PROCFS_SYSCALL_EXIT,
+ procfs_fork_handler);
+#endif
+/* Turn on inherit-on-fork flag so that all children of the target process
+ start with tracing flags set. This allows us to trap lwp creation. Note
+ that we also have to trap on fork and vfork in order to disable all tracing
+ in the targets child processes. */
+
+ modify_inherit_on_fork_flag (pip->ctl_fd, 1);
+#endif
+
+#ifdef SYS_lwp_create
+ procfs_set_syscall_trap (pip, SYS_lwp_create, PROCFS_SYSCALL_EXIT,
+ procfs_lwp_creation_handler);
+#endif
+}
+
+/*
+
+LOCAL FUNCTION
+
+ procfs_init_inferior - initialize target vector and access to a
+ /proc entry
+
+SYNOPSIS
+
+ void procfs_init_inferior (int pid)
+
+DESCRIPTION
+
+ When gdb starts an inferior, this function is called in the parent
+ process immediately after the fork. It waits for the child to stop
+ on the return from the exec system call (the child itself takes care
+ of ensuring that this is set up), then sets up the set of signals
+ and faults that are to be traced. Returns the pid, which may have had
+ the thread-id added to it.
+
+NOTES
+
+ If proc_init_failed ever gets called, control returns to the command
+ processing loop via the standard error handling code.
+
+ */
+
+static void
+procfs_init_inferior (pid)
+ int pid;
+{
+ struct procinfo *pip;
+
+ push_target (&procfs_ops);
+
+ pip = create_procinfo (pid);
+
+ procfs_set_inferior_syscall_traps (pip);
+
+ /* create_procinfo may change the pid, so we have to update inferior_pid
+ here before calling other gdb routines that need the right pid. */
+
+ pid = pip -> pid;
+ inferior_pid = pid;
+
+ add_thread (pip -> pid); /* Setup initial thread */
+
+#ifdef START_INFERIOR_TRAPS_EXPECTED
+ startup_inferior (START_INFERIOR_TRAPS_EXPECTED);
+#else
+ /* One trap to exec the shell, one to exec the program being debugged. */
+ startup_inferior (2);
+#endif
+}
+
+/*
+
+GLOBAL FUNCTION
+
+ procfs_notice_signals
+
+SYNOPSIS
+
+ static void procfs_notice_signals (int pid);
+
+DESCRIPTION
+
+ When the user changes the state of gdb's signal handling via the
+ "handle" command, this function gets called to see if any change
+ in the /proc interface is required. It is also called internally
+ by other /proc interface functions to initialize the state of
+ the traced signal set.
+
+ One thing it does is that signals for which the state is "nostop",
+ "noprint", and "pass", have their trace bits reset in the pr_trace
+ field, so that they are no longer traced. This allows them to be
+ delivered directly to the inferior without the debugger ever being
+ involved.
+ */
+
+static void
+procfs_notice_signals (pid)
+ int pid;
+{
+ struct procinfo *pi;
+ struct sig_ctl sctl;
+
+ pi = find_procinfo (pid, 0);
+
+#ifndef HAVE_PRRUN_T
+ premptyset (&sctl.sigset);
+#else
+ sctl.sigset = pi->prrun.pr_trace;
+#endif
+
+ notice_signals (pi, &sctl);
+
+#ifdef HAVE_PRRUN_T
+ pi->prrun.pr_trace = sctl.sigset;
+#endif
+}
+
+static void
+notice_signals (pi, sctl)
+ struct procinfo *pi;
+ struct sig_ctl *sctl;
+{
+ int signo;
+
+ for (signo = 0; signo < NSIG; signo++)
+ {
+ if (signal_stop_state (target_signal_from_host (signo)) == 0 &&
+ signal_print_state (target_signal_from_host (signo)) == 0 &&
+ signal_pass_state (target_signal_from_host (signo)) == 1)
+ {
+ prdelset (&sctl->sigset, signo);
+ }
+ else
+ {
+ praddset (&sctl->sigset, signo);
+ }
+ }
+#ifdef PROCFS_USE_READ_WRITE
+ sctl->cmd = PCSTRACE;
+ if (write (pi->ctl_fd, (char *) sctl, sizeof (struct sig_ctl)) < 0)
+#else
+ if (ioctl (pi->ctl_fd, PIOCSTRACE, &sctl->sigset))
+#endif
+ {
+ print_sys_errmsg ("PIOCSTRACE failed", errno);
+ }
+}
+
+/*
+
+LOCAL FUNCTION
+
+ proc_set_exec_trap -- arrange for exec'd child to halt at startup
+
+SYNOPSIS
+
+ void proc_set_exec_trap (void)
+
+DESCRIPTION
+
+ This function is called in the child process when starting up
+ an inferior, prior to doing the exec of the actual inferior.
+ It sets the child process's exitset to make exit from the exec
+ system call an event of interest to stop on, and then simply
+ returns. The child does the exec, the system call returns, and
+ the child stops at the first instruction, ready for the gdb
+ parent process to take control of it.
+
+NOTE
+
+ We need to use all local variables since the child may be sharing
+ it's data space with the parent, if vfork was used rather than
+ fork.
+
+ Also note that we want to turn off the inherit-on-fork flag in
+ the child process so that any grand-children start with all
+ tracing flags cleared.
+ */
+
+static void
+proc_set_exec_trap ()
+{
+ struct sys_ctl exitset;
+ struct sys_ctl entryset;
+ char procname[MAX_PROC_NAME_SIZE];
+ int fd;
+
+ sprintf (procname, CTL_PROC_NAME_FMT, getpid ());
+#ifdef UNIXWARE
+ if ((fd = open (procname, O_WRONLY)) < 0)
+#else
+ if ((fd = open (procname, O_RDWR)) < 0)
+#endif
+ {
+ perror (procname);
+ gdb_flush (gdb_stderr);
+ _exit (127);
+ }
+ premptyset (&exitset.sysset);
+ premptyset (&entryset.sysset);
+
+#ifdef PRFS_STOPEXEC
+ /* Under Alpha OSF/1 we have to use a PIOCSSPCACT ioctl to trace
+ exits from exec system calls because of the user level loader. */
+ {
+ int prfs_flags;
+
+ if (ioctl (fd, PIOCGSPCACT, &prfs_flags) < 0)
+ {
+ perror (procname);
+ gdb_flush (gdb_stderr);
+ _exit (127);
+ }
+ prfs_flags |= PRFS_STOPEXEC;
+ if (ioctl (fd, PIOCSSPCACT, &prfs_flags) < 0)
+ {
+ perror (procname);
+ gdb_flush (gdb_stderr);
+ _exit (127);
+ }
+ }
+#else /* PRFS_STOPEXEC */
+ /* GW: Rationale...
+ Not all systems with /proc have all the exec* syscalls with the same
+ names. On the SGI, for example, there is no SYS_exec, but there
+ *is* a SYS_execv. So, we try to account for that. */
+
+#ifdef SYS_exec
+ praddset (&exitset.sysset, SYS_exec);
+#endif
+#ifdef SYS_execve
+ praddset (&exitset.sysset, SYS_execve);
+#endif
+#ifdef SYS_execv
+ praddset (&exitset.sysset, SYS_execv);
+#endif
+
+#ifdef PROCFS_USE_READ_WRITE
+ exitset.cmd = PCSEXIT;
+ if (write (fd, (char *) &exitset, sizeof (struct sys_ctl)) < 0)
+#else
+ if (ioctl (fd, PIOCSEXIT, &exitset.sysset) < 0)
+#endif
+ {
+ perror (procname);
+ gdb_flush (gdb_stderr);
+ _exit (127);
+ }
+#endif /* PRFS_STOPEXEC */
+
+ praddset (&entryset.sysset, SYS_exit);
+
+#ifdef PROCFS_USE_READ_WRITE
+ entryset.cmd = PCSENTRY;
+ if (write (fd, (char *) &entryset, sizeof (struct sys_ctl)) < 0)
+#else
+ if (ioctl (fd, PIOCSENTRY, &entryset.sysset) < 0)
+#endif
+ {
+ perror (procname);
+ gdb_flush (gdb_stderr);
+ _exit (126);
+ }
+
+ /* Turn off inherit-on-fork flag so that all grand-children of gdb
+ start with tracing flags cleared. */
+
+ modify_inherit_on_fork_flag (fd, 0);
+
+ /* Turn on run-on-last-close flag so that this process will not hang
+ if GDB goes away for some reason. */
+
+ modify_run_on_last_close_flag (fd, 1);
+
+#ifndef UNIXWARE /* since this is a solaris-ism, we don't want it */
+ /* NOTE: revisit when doing thread support for UW */
+#ifdef PR_ASYNC
+ {
+ long pr_flags;
+ struct proc_ctl pctl;
+
+/* Solaris needs this to make procfs treat all threads seperately. Without
+ this, all threads halt whenever something happens to any thread. Since
+ GDB wants to control all this itself, it needs to set PR_ASYNC. */
+
+ pr_flags = PR_ASYNC;
+#ifdef PROCFS_USE_READ_WRITE
+ pctl.cmd = PCSET;
+ pctl.data = PR_FORK|PR_ASYNC;
+ write (fd, (char *) &pctl, sizeof (struct proc_ctl));
+#else
+ ioctl (fd, PIOCSET, &pr_flags);
+#endif
+ }
+#endif /* PR_ASYNC */
+#endif /* !UNIXWARE */
+}
+
+/*
+
+GLOBAL FUNCTION
+
+ proc_iterate_over_mappings -- call function for every mapped space
+
+SYNOPSIS
+
+ int proc_iterate_over_mappings (int (*func)())
+
+DESCRIPTION
+
+ Given a pointer to a function, call that function for every
+ mapped address space, passing it an open file descriptor for
+ the file corresponding to that mapped address space (if any)
+ and the base address of the mapped space. Quit when we hit
+ the end of the mappings or the function returns nonzero.
+ */
+
+#ifdef UNIXWARE
+int
+proc_iterate_over_mappings (func)
+ int (*func) PARAMS ((int, CORE_ADDR));
+{
+ int nmap;
+ int fd;
+ int funcstat = 0;
+ prmap_t *prmaps;
+ prmap_t *prmap;
+ struct procinfo *pi;
+ struct stat sbuf;
+
+ pi = current_procinfo;
+
+ if (fstat (pi->map_fd, &sbuf) < 0)
+ return 0;
+
+ nmap = sbuf.st_size / sizeof (prmap_t);
+ prmaps = (prmap_t *) alloca (nmap * sizeof(prmap_t));
+ if ((lseek (pi->map_fd, 0, SEEK_SET) == 0) &&
+ (read (pi->map_fd, (char *) prmaps, nmap * sizeof (prmap_t)) ==
+ (nmap * sizeof (prmap_t))))
+ {
+ int i = 0;
+ for (prmap = prmaps; i < nmap && funcstat == 0; ++prmap, ++i)
+ {
+ char name[sizeof ("/proc/1234567890/object") +
+ sizeof (prmap->pr_mapname)];
+ sprintf (name, "/proc/%d/object/%s", pi->pid, prmap->pr_mapname);
+ if ((fd = open (name, O_RDONLY)) == -1)
+ {
+ funcstat = 1;
+ break;
+ }
+ funcstat = (*func) (fd, (CORE_ADDR) prmap->pr_vaddr);
+ close (fd);
+ }
+ }
+ return (funcstat);
+}
+#else /* UNIXWARE */
+int
+proc_iterate_over_mappings (func)
+ int (*func) PARAMS ((int, CORE_ADDR));
+{
+ int nmap;
+ int fd;
+ int funcstat = 0;
+ struct prmap *prmaps;
+ struct prmap *prmap;
+ struct procinfo *pi;
+
+ pi = current_procinfo;
+
+ if (ioctl (pi->map_fd, PIOCNMAP, &nmap) == 0)
+ {
+ prmaps = (struct prmap *) alloca ((nmap + 1) * sizeof (*prmaps));
+ if (ioctl (pi->map_fd, PIOCMAP, prmaps) == 0)
+ {
+ for (prmap = prmaps; prmap -> pr_size && funcstat == 0; ++prmap)
+ {
+ fd = proc_address_to_fd (pi, (CORE_ADDR) prmap -> pr_vaddr, 0);
+ funcstat = (*func) (fd, (CORE_ADDR) prmap -> pr_vaddr);
+ close (fd);
+ }
+ }
+ }
+ return (funcstat);
+}
+#endif /* UNIXWARE */
+
+#if 0 /* Currently unused */
+/*
+
+GLOBAL FUNCTION
+
+ proc_base_address -- find base address for segment containing address
+
+SYNOPSIS
+
+ CORE_ADDR proc_base_address (CORE_ADDR addr)
+
+DESCRIPTION
+
+ Given an address of a location in the inferior, find and return
+ the base address of the mapped segment containing that address.
+
+ This is used for example, by the shared library support code,
+ where we have the pc value for some location in the shared library
+ where we are stopped, and need to know the base address of the
+ segment containing that address.
+*/
+
+CORE_ADDR
+proc_base_address (addr)
+ CORE_ADDR addr;
+{
+ int nmap;
+ struct prmap *prmaps;
+ struct prmap *prmap;
+ CORE_ADDR baseaddr = 0;
+ struct procinfo *pi;
+
+ pi = current_procinfo;
+
+ if (ioctl (pi->map_fd, PIOCNMAP, &nmap) == 0)
+ {
+ prmaps = (struct prmap *) alloca ((nmap + 1) * sizeof (*prmaps));
+ if (ioctl (pi->map_fd, PIOCMAP, prmaps) == 0)
+ {
+ for (prmap = prmaps; prmap -> pr_size; ++prmap)
+ {
+ if ((prmap -> pr_vaddr <= (caddr_t) addr) &&
+ (prmap -> pr_vaddr + prmap -> pr_size > (caddr_t) addr))
+ {
+ baseaddr = (CORE_ADDR) prmap -> pr_vaddr;
+ break;
+ }
+ }
+ }
+ }
+ return (baseaddr);
+}
+
+#endif /* 0 */
+
+#ifndef UNIXWARE
+/*
+
+LOCAL FUNCTION
+
+ proc_address_to_fd -- return open fd for file mapped to address
+
+SYNOPSIS
+
+ int proc_address_to_fd (struct procinfo *pi, CORE_ADDR addr, complain)
+
+DESCRIPTION
+
+ Given an address in the current inferior's address space, use the
+ /proc interface to find an open file descriptor for the file that
+ this address was mapped in from. Return -1 if there is no current
+ inferior. Print a warning message if there is an inferior but
+ the address corresponds to no file (IE a bogus address).
+
+*/
+
+static int
+proc_address_to_fd (pi, addr, complain)
+ struct procinfo *pi;
+ CORE_ADDR addr;
+ int complain;
+{
+ int fd = -1;
+
+ if ((fd = ioctl (pi->ctl_fd, PIOCOPENM, (caddr_t *) &addr)) < 0)
+ {
+ if (complain)
+ {
+ print_sys_errmsg (pi->pathname, errno);
+ warning ("can't find mapped file for address 0x%x", addr);
+ }
+ }
+ return (fd);
+}
+#endif /* !UNIXWARE */
+
+/* Attach to process PID, then initialize for debugging it
+ and wait for the trace-trap that results from attaching. */
+
+static void
+procfs_attach (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ char *exec_file;
+ int pid;
+
+ if (!args)
+ error_no_arg ("process-id to attach");
+
+ 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_unfiltered ("Attaching to program `%s', %s\n", exec_file, target_pid_to_str (pid));
+ else
+ printf_unfiltered ("Attaching to %s\n", target_pid_to_str (pid));
+
+ gdb_flush (gdb_stdout);
+ }
+
+ inferior_pid = pid = do_attach (pid);
+ push_target (&procfs_ops);
+}
+
+
+/* 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
+procfs_detach (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ int siggnal = 0;
+
+ if (from_tty)
+ {
+ char *exec_file = get_exec_file (0);
+ if (exec_file == 0)
+ exec_file = "";
+ printf_unfiltered ("Detaching from program: %s %s\n",
+ exec_file, target_pid_to_str (inferior_pid));
+ gdb_flush (gdb_stdout);
+ }
+ if (args)
+ siggnal = atoi (args);
+
+ do_detach (siggnal);
+ inferior_pid = 0;
+ unpush_target (&procfs_ops); /* Pop out of handling an inferior */
+}
+
+/* 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
+procfs_prepare_to_store ()
+{
+#ifdef CHILD_PREPARE_TO_STORE
+ CHILD_PREPARE_TO_STORE ();
+#endif
+}
+
+/* Print status information about what we're accessing. */
+
+static void
+procfs_files_info (ignore)
+ struct target_ops *ignore;
+{
+ printf_unfiltered ("\tUsing the running image of %s %s via /proc.\n",
+ attach_flag? "attached": "child", target_pid_to_str (inferior_pid));
+}
+
+/* ARGSUSED */
+static void
+procfs_open (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ error ("Use the \"run\" command to start a Unix child process.");
+}
+
+/*
+
+LOCAL FUNCTION
+
+ do_attach -- attach to an already existing process
+
+SYNOPSIS
+
+ int do_attach (int pid)
+
+DESCRIPTION
+
+ Attach to an already existing process with the specified process
+ id. If the process is not already stopped, query whether to
+ stop it or not.
+
+NOTES
+
+ The option of stopping at attach time is specific to the /proc
+ versions of gdb. Versions using ptrace force the attachee
+ to stop. (I have changed this version to do so, too. All you
+ have to do is "continue" to make it go on. -- gnu@cygnus.com)
+
+*/
+
+static int
+do_attach (pid)
+ int pid;
+{
+ struct procinfo *pi;
+ struct sig_ctl sctl;
+ struct flt_ctl fctl;
+ int nlwp, *lwps;
+
+ pi = init_procinfo (pid, 0);
+
+#ifdef PIOCLWPIDS
+ nlwp = pi->prstatus.pr_nlwp;
+ lwps = alloca ((2 * nlwp + 2) * sizeof (id_t));
+
+ if (ioctl (pi->ctl_fd, PIOCLWPIDS, lwps))
+ {
+ print_sys_errmsg (pi -> pathname, errno);
+ error ("PIOCLWPIDS failed");
+ }
+#else /* PIOCLWPIDS */
+ nlwp = 1;
+ lwps = alloca ((2 * nlwp + 2) * sizeof *lwps);
+ lwps[0] = 0;
+#endif
+ for (; nlwp > 0; nlwp--, lwps++)
+ {
+ /* First one has already been created above. */
+ if ((pi = find_procinfo ((*lwps << 16) | pid, 1)) == 0)
+ pi = init_procinfo ((*lwps << 16) | pid, 0);
+
+ if (THE_PR_LWP(pi->prstatus).pr_flags & (PR_STOPPED | PR_ISTOP))
+ {
+ pi->was_stopped = 1;
+ }
+ else
+ {
+ pi->was_stopped = 0;
+ if (1 || query ("Process is currently running, stop it? "))
+ {
+ long cmd;
+ /* Make it run again when we close it. */
+ modify_run_on_last_close_flag (pi->ctl_fd, 1);
+#ifdef PROCFS_USE_READ_WRITE
+ cmd = PCSTOP;
+ if (write (pi->ctl_fd, (char *) &cmd, sizeof (long)) < 0)
+#else
+ if (ioctl (pi->ctl_fd, PIOCSTOP, &pi->prstatus) < 0)
+#endif
+ {
+ print_sys_errmsg (pi->pathname, errno);
+ close_proc_file (pi);
+ error ("PIOCSTOP failed");
+ }
+#ifdef UNIXWARE
+ if (!procfs_read_status (pi))
+ {
+ print_sys_errmsg (pi->pathname, errno);
+ close_proc_file (pi);
+ error ("procfs_read_status failed");
+ }
+#endif
+ pi->nopass_next_sigstop = 1;
+ }
+ else
+ {
+ printf_unfiltered ("Ok, gdb will wait for %s to stop.\n",
+ target_pid_to_str (pi->pid));
+ }
+ }
+
+#ifdef PROCFS_USE_READ_WRITE
+ fctl.cmd = PCSFAULT;
+ if (write (pi->ctl_fd, (char *) &fctl, sizeof (struct flt_ctl)) < 0)
+ print_sys_errmsg ("PCSFAULT failed", errno);
+#else /* PROCFS_USE_READ_WRITE */
+ if (ioctl (pi->ctl_fd, PIOCSFAULT, &pi->prrun.pr_fault))
+ {
+ print_sys_errmsg ("PIOCSFAULT failed", errno);
+ }
+ if (ioctl (pi->ctl_fd, PIOCSTRACE, &pi->prrun.pr_trace))
+ {
+ print_sys_errmsg ("PIOCSTRACE failed", errno);
+ }
+ add_thread (pi->pid);
+ procfs_set_inferior_syscall_traps (pi);
+#endif /* PROCFS_USE_READ_WRITE */
+ }
+ attach_flag = 1;
+ return (pi->pid);
+}
+
+/*
+
+LOCAL FUNCTION
+
+ do_detach -- detach from an attached-to process
+
+SYNOPSIS
+
+ void do_detach (int signal)
+
+DESCRIPTION
+
+ Detach from the current attachee.
+
+ If signal is non-zero, the attachee is started running again and sent
+ the specified signal.
+
+ If signal is zero and the attachee was not already stopped when we
+ attached to it, then we make it runnable again when we detach.
+
+ Otherwise, we query whether or not to make the attachee runnable
+ again, since we may simply want to leave it in the state it was in
+ when we attached.
+
+ We report any problems, but do not consider them errors, since we
+ MUST detach even if some things don't seem to go right. This may not
+ be the ideal situation. (FIXME).
+ */
+
+static void
+do_detach (signal)
+ int signal;
+{
+ struct procinfo *pi;
+
+ for (pi = procinfo_list; pi; pi = pi->next)
+ {
+ if (signal)
+ {
+ set_proc_siginfo (pi, signal);
+ }
+#ifdef PROCFS_USE_READ_WRITE
+ pi->saved_exitset.cmd = PCSEXIT;
+ if (write (pi->ctl_fd, (char *) &pi->saved_exitset,
+ sizeof (struct sys_ctl)) < 0)
+#else
+ if (ioctl (pi->ctl_fd, PIOCSEXIT, &pi->saved_exitset.sysset) < 0)
+#endif
+ {
+ print_sys_errmsg (pi->pathname, errno);
+ printf_unfiltered ("PIOCSEXIT failed.\n");
+ }
+#ifdef PROCFS_USE_READ_WRITE
+ pi->saved_entryset.cmd = PCSENTRY;
+ if (write (pi->ctl_fd, (char *) &pi->saved_entryset,
+ sizeof (struct sys_ctl)) < 0)
+#else
+ if (ioctl (pi->ctl_fd, PIOCSENTRY, &pi->saved_entryset.sysset) < 0)
+#endif
+ {
+ print_sys_errmsg (pi->pathname, errno);
+ printf_unfiltered ("PIOCSENTRY failed.\n");
+ }
+#ifdef PROCFS_USE_READ_WRITE
+ pi->saved_trace.cmd = PCSTRACE;
+ if (write (pi->ctl_fd, (char *) &pi->saved_trace,
+ sizeof (struct sig_ctl)) < 0)
+#else
+ if (ioctl (pi->ctl_fd, PIOCSTRACE, &pi->saved_trace.sigset) < 0)
+#endif
+ {
+ print_sys_errmsg (pi->pathname, errno);
+ printf_unfiltered ("PIOCSTRACE failed.\n");
+ }
+#ifndef UNIXWARE
+ if (ioctl (pi->ctl_fd, PIOCSHOLD, &pi->saved_sighold.sigset) < 0)
+ {
+ print_sys_errmsg (pi->pathname, errno);
+ printf_unfiltered ("PIOSCHOLD failed.\n");
+ }
+#endif
+#ifdef PROCFS_USE_READ_WRITE
+ pi->saved_fltset.cmd = PCSFAULT;
+ if (write (pi->ctl_fd, (char *) &pi->saved_fltset,
+ sizeof (struct flt_ctl)) < 0)
+#else
+ if (ioctl (pi->ctl_fd, PIOCSFAULT, &pi->saved_fltset.fltset) < 0)
+#endif
+ {
+ print_sys_errmsg (pi->pathname, errno);
+ printf_unfiltered ("PIOCSFAULT failed.\n");
+ }
+ if (!procfs_read_status (pi))
+ {
+ print_sys_errmsg (pi->pathname, errno);
+ printf_unfiltered ("procfs_read_status failed.\n");
+ }
+ else
+ {
+ if (signal
+ || (THE_PR_LWP(pi->prstatus).pr_flags & (PR_STOPPED | PR_ISTOP)))
+ {
+ long cmd;
+ struct proc_ctl pctl;
+
+ if (signal || !pi->was_stopped ||
+ query ("Was stopped when attached, make it runnable again? "))
+ {
+ /* Clear any pending signal if we want to detach without
+ a signal. */
+ if (signal == 0)
+ set_proc_siginfo (pi, signal);
+
+ /* Clear any fault that might have stopped it. */
+#ifdef PROCFS_USE_READ_WRITE
+ cmd = PCCFAULT;
+ if (write (pi->ctl_fd, (char *) &cmd, sizeof (long)) < 0)
+#else
+ if (ioctl (pi->ctl_fd, PIOCCFAULT, 0))
+#endif
+ {
+ print_sys_errmsg (pi->pathname, errno);
+ printf_unfiltered ("PIOCCFAULT failed.\n");
+ }
+
+ /* Make it run again when we close it. */
+
+ modify_run_on_last_close_flag (pi->ctl_fd, 1);
+ }
+ }
+ }
+ close_proc_file (pi);
+ }
+ attach_flag = 0;
+}
+
+/* emulate wait() as much as possible.
+ Wait for child to do something. Return pid of child, or -1 in case
+ of error; store status in *OURSTATUS.
+
+ Not sure why we can't
+ just use wait(), but it seems to have problems when applied to a
+ process being controlled with the /proc interface.
+
+ We have a race problem here with no obvious solution. We need to let
+ the inferior run until it stops on an event of interest, which means
+ that we need to use the PIOCWSTOP ioctl. However, we cannot use this
+ ioctl if the process is already stopped on something that is not an
+ event of interest, or the call will hang indefinitely. Thus we first
+ use PIOCSTATUS to see if the process is not stopped. If not, then we
+ use PIOCWSTOP. But during the window between the two, if the process
+ stops for any reason that is not an event of interest (such as a job
+ control signal) then gdb will hang. One possible workaround is to set
+ an alarm to wake up every minute of so and check to see if the process
+ is still running, and if so, then reissue the PIOCWSTOP. But this is
+ a real kludge, so has not been implemented. FIXME: investigate
+ alternatives.
+
+ FIXME: Investigate why wait() seems to have problems with programs
+ being control by /proc routines. */
+static int
+procfs_wait (pid, ourstatus)
+ int pid;
+ struct target_waitstatus *ourstatus;
+{
+ short what;
+ short why;
+ int statval = 0;
+ int checkerr = 0;
+ int rtnval = -1;
+ struct procinfo *pi;
+ struct proc_ctl pctl;
+
+scan_again:
+
+ /* handle all syscall events first, otherwise we might not
+ notice a thread was created until too late. */
+
+ for (pi = procinfo_list; pi; pi = pi->next)
+ {
+ if (!pi->had_event)
+ continue;
+
+ if (! (THE_PR_LWP(pi->prstatus).pr_flags & (PR_STOPPED | PR_ISTOP)) )
+ continue;
+
+ why = THE_PR_LWP(pi->prstatus).pr_why;
+ what = THE_PR_LWP(pi->prstatus).pr_what;
+ if (why == PR_SYSENTRY || why == PR_SYSEXIT)
+ {
+ int i;
+ int found_handler = 0;
+
+ for (i = 0; i < pi->num_syscall_handlers; i++)
+ if (pi->syscall_handlers[i].syscall_num == what)
+ {
+ found_handler = 1;
+ pi->saved_rtnval = pi->pid;
+ pi->saved_statval = 0;
+ if (!pi->syscall_handlers[i].func
+ (pi, what, why, &pi->saved_rtnval, &pi->saved_statval))
+ pi->had_event = 0;
+ break;
+ }
+
+ if (!found_handler)
+ {
+ if (why == PR_SYSENTRY)
+ error ("PR_SYSENTRY, unhandled system call %d", what);
+ else
+ error ("PR_SYSEXIT, unhandled system call %d", what);
+ }
+ }
+ }
+
+ /* find a relevant process with an event */
+
+ for (pi = procinfo_list; pi; pi = pi->next)
+ if (pi->had_event && (pid == -1 || pi->pid == pid))
+ break;
+
+ if (!pi)
+ {
+ wait_fd ();
+ goto scan_again;
+ }
+
+ if (!checkerr
+ && !(THE_PR_LWP(pi->prstatus).pr_flags & (PR_STOPPED | PR_ISTOP)))
+ {
+ if (!procfs_write_pcwstop (pi))
+ {
+ checkerr++;
+ }
+ }
+ if (checkerr)
+ {
+ if (errno == ENOENT)
+ {
+ /* XXX Fixme -- what to do if attached? Can't call wait... */
+ rtnval = wait (&statval);
+ if ((rtnval) != (PIDGET (inferior_pid)))
+ {
+ print_sys_errmsg (pi->pathname, errno);
+ error ("procfs_wait: wait failed, returned %d", rtnval);
+ /* NOTREACHED */
+ }
+ }
+ else
+ {
+ print_sys_errmsg (pi->pathname, errno);
+ error ("PIOCSTATUS or PIOCWSTOP failed.");
+ /* NOTREACHED */
+ }
+ }
+ else if (THE_PR_LWP(pi->prstatus).pr_flags & (PR_STOPPED | PR_ISTOP))
+ {
+#ifdef UNIXWARE
+ rtnval = pi->prstatus.pr_pid;
+#else
+ rtnval = pi->pid;
+#endif
+ why = THE_PR_LWP(pi->prstatus).pr_why;
+ what = THE_PR_LWP(pi->prstatus).pr_what;
+
+ switch (why)
+ {
+ case PR_SIGNALLED:
+ statval = (what << 8) | 0177;
+ break;
+ case PR_SYSENTRY:
+ case PR_SYSEXIT:
+ rtnval = pi->saved_rtnval;
+ statval = pi->saved_statval;
+ break;
+ case PR_REQUESTED:
+ statval = (SIGSTOP << 8) | 0177;
+ break;
+ case PR_JOBCONTROL:
+ statval = (what << 8) | 0177;
+ break;
+ case PR_FAULTED:
+ switch (what)
+ {
+#ifdef FLTWATCH
+ case FLTWATCH:
+ statval = (SIGTRAP << 8) | 0177;
+ break;
+#endif
+#ifdef FLTKWATCH
+ case FLTKWATCH:
+ statval = (SIGTRAP << 8) | 0177;
+ break;
+#endif
+#ifndef FAULTED_USE_SIGINFO
+ /* Irix, contrary to the documentation, fills in 0 for si_signo.
+ Solaris fills in si_signo. I'm not sure about others. */
+ case FLTPRIV:
+ case FLTILL:
+ statval = (SIGILL << 8) | 0177;
+ break;
+ case FLTBPT:
+ case FLTTRACE:
+ statval = (SIGTRAP << 8) | 0177;
+ break;
+ case FLTSTACK:
+ case FLTACCESS:
+ case FLTBOUNDS:
+ statval = (SIGSEGV << 8) | 0177;
+ break;
+ case FLTIOVF:
+ case FLTIZDIV:
+ case FLTFPE:
+ statval = (SIGFPE << 8) | 0177;
+ break;
+ case FLTPAGE: /* Recoverable page fault */
+#endif /* not FAULTED_USE_SIGINFO */
+ default:
+ /* Use the signal which the kernel assigns. This is better than
+ trying to second-guess it from the fault. In fact, I suspect
+ that FLTACCESS can be either SIGSEGV or SIGBUS. */
+ statval =
+ ((THE_PR_LWP(pi->prstatus).pr_info.si_signo) << 8) | 0177;
+ break;
+ }
+ break;
+ default:
+ error ("PIOCWSTOP, unknown why %d, what %d", why, what);
+ }
+ /* Stop all the other threads when any of them stops. */
+
+ {
+ struct procinfo *procinfo, *next_pi;
+
+ for (procinfo = procinfo_list; procinfo; procinfo = next_pi)
+ {
+ next_pi = procinfo->next;
+ if (!procinfo->had_event)
+ {
+#ifdef PROCFS_USE_READ_WRITE
+ long cmd = PCSTOP;
+ if (write (pi->ctl_fd, (char *) &cmd, sizeof (long)) < 0)
+ {
+ print_sys_errmsg (procinfo->pathname, errno);
+ error ("PCSTOP failed");
+ }
+#else
+ /* A bug in Solaris (2.5) causes us to hang when trying to
+ stop a stopped process. So, we have to check first in
+ order to avoid the hang. */
+ if (!procfs_read_status (procinfo))
+ {
+ /* The LWP has apparently terminated. */
+ if (info_verbose)
+ printf_filtered ("LWP %d doesn't respond.\n",
+ (procinfo->pid >> 16) & 0xffff);
+ close_proc_file (procinfo);
+ continue;
+ }
+
+ if (!(procinfo->prstatus.pr_flags & PR_STOPPED))
+ if (ioctl (procinfo->ctl_fd, PIOCSTOP, &procinfo->prstatus)
+ < 0)
+ {
+ print_sys_errmsg (procinfo->pathname, errno);
+ warning ("PIOCSTOP failed");
+ }
+#endif
+ }
+ }
+ }
+ }
+ else
+ {
+ error ("PIOCWSTOP, stopped for unknown/unhandled reason, flags %#x",
+ THE_PR_LWP(pi->prstatus).pr_flags);
+ }
+
+ store_waitstatus (ourstatus, statval);
+
+ if (rtnval == -1) /* No more children to wait for */
+ {
+ warning ("Child process unexpectedly missing");
+ /* Claim it exited with unknown signal. */
+ ourstatus->kind = TARGET_WAITKIND_SIGNALLED;
+ ourstatus->value.sig = TARGET_SIGNAL_UNKNOWN;
+ return rtnval;
+ }
+
+ pi->had_event = 0; /* Indicate that we've seen this one */
+ return (rtnval);
+}
+
+/*
+
+LOCAL FUNCTION
+
+ set_proc_siginfo - set a process's current signal info
+
+SYNOPSIS
+
+ void set_proc_siginfo (struct procinfo *pip, int signo);
+
+DESCRIPTION
+
+ Given a pointer to a process info struct in PIP and a signal number
+ in SIGNO, set the process's current signal and its associated signal
+ information. The signal will be delivered to the process immediately
+ after execution is resumed, even if it is being held. In addition,
+ this particular delivery will not cause another PR_SIGNALLED stop
+ even if the signal is being traced.
+
+ If we are not delivering the same signal that the prstatus siginfo
+ struct contains information about, then synthesize a siginfo struct
+ to match the signal we are doing to deliver, make it of the type
+ "generated by a user process", and send this synthesized copy. When
+ used to set the inferior's signal state, this will be required if we
+ are not currently stopped because of a traced signal, or if we decide
+ to continue with a different signal.
+
+ Note that when continuing the inferior from a stop due to receipt
+ of a traced signal, we either have set PRCSIG to clear the existing
+ signal, or we have to call this function to do a PIOCSSIG with either
+ the existing siginfo struct from pr_info, or one we have synthesized
+ appropriately for the signal we want to deliver. Otherwise if the
+ signal is still being traced, the inferior will immediately stop
+ again.
+
+ See siginfo(5) for more details.
+*/
+
+static void
+set_proc_siginfo (pip, signo)
+ struct procinfo *pip;
+ int signo;
+{
+ struct siginfo newsiginfo;
+ struct siginfo *sip;
+ struct sigi_ctl sictl;
+
+#ifdef PROCFS_DONT_PIOCSSIG_CURSIG
+ /* With Alpha OSF/1 procfs, the kernel gets really confused if it
+ receives a PIOCSSIG with a signal identical to the current signal,
+ it messes up the current signal. Work around the kernel bug. */
+ if (signo == THE_PR_LWP(pip->prstatus).pr_cursig)
+ return;
+#endif
+
+#ifdef UNIXWARE
+ if (signo == THE_PR_LWP(pip->prstatus).pr_info.si_signo)
+ {
+ memcpy ((char *) &sictl.siginfo, (char *) &pip->prstatus.pr_lwp.pr_info,
+ sizeof (siginfo_t));
+ }
+#else
+ if (signo == THE_PR_LWP(pip->prstatus).pr_info.si_signo)
+ {
+ sip = &pip -> prstatus.pr_info;
+ }
+#endif
+ else
+ {
+#ifdef UNIXWARE
+ siginfo_t *sip = &sictl.siginfo;
+ memset ((char *) sip, 0, sizeof (siginfo_t));
+#else
+ memset ((char *) &newsiginfo, 0, sizeof (newsiginfo));
+ sip = &newsiginfo;
+#endif
+ sip -> si_signo = signo;
+ sip -> si_code = 0;
+ sip -> si_errno = 0;
+ sip -> si_pid = getpid ();
+ sip -> si_uid = getuid ();
+ }
+#ifdef PROCFS_USE_READ_WRITE
+ sictl.cmd = PCSSIG;
+ if (write (pip->ctl_fd, (char *) &sictl, sizeof (struct sigi_ctl)) < 0)
+#else
+ if (ioctl (pip->ctl_fd, PIOCSSIG, sip) < 0)
+#endif
+ {
+ print_sys_errmsg (pip -> pathname, errno);
+ warning ("PIOCSSIG failed");
+ }
+}
+
+/* Resume execution of process PID. If STEP is nozero, then
+ just single step it. If SIGNAL is nonzero, restart it with that
+ signal activated. */
+
+static void
+procfs_resume (pid, step, signo)
+ int pid;
+ int step;
+ enum target_signal signo;
+{
+ int signal_to_pass;
+ struct procinfo *pi, *procinfo, *next_pi;
+ struct proc_ctl pctl;
+
+ pi = find_procinfo (pid == -1 ? inferior_pid : pid, 0);
+
+ errno = 0;
+#ifdef UNIXWARE
+ pctl.cmd = PCRUN;
+ pctl.data = PRCFAULT;
+#else
+ pi->prrun.pr_flags = PRSTRACE | PRSFAULT | PRCFAULT;
+#endif
+
+#if 0
+ /* It should not be necessary. If the user explicitly changes the value,
+ value_assign calls write_register_bytes, which writes it. */
+/* It may not be absolutely necessary to specify the PC value for
+ restarting, but to be safe we use the value that gdb considers
+ to be current. One case where this might be necessary is if the
+ user explicitly changes the PC value that gdb considers to be
+ current. FIXME: Investigate if this is necessary or not. */
+
+#ifdef PRSVADDR_BROKEN
+/* Can't do this under Solaris running on a Sparc, as there seems to be no
+ place to put nPC. In fact, if you use this, nPC seems to be set to some
+ random garbage. We have to rely on the fact that PC and nPC have been
+ written previously via PIOCSREG during a register flush. */
+
+ pi->prrun.pr_vaddr = (caddr_t) *(int *) &registers[REGISTER_BYTE (PC_REGNUM)];
+ pi->prrun.pr_flags != PRSVADDR;
+#endif
+#endif
+
+ if (signo == TARGET_SIGNAL_STOP && pi->nopass_next_sigstop)
+ /* When attaching to a child process, if we forced it to stop with
+ a PIOCSTOP, then we will have set the nopass_next_sigstop flag.
+ Upon resuming the first time after such a stop, we explicitly
+ inhibit sending it another SIGSTOP, which would be the normal
+ result of default signal handling. One potential drawback to
+ this is that we will also ignore any attempt to by the user
+ to explicitly continue after the attach with a SIGSTOP. Ultimately
+ this problem should be dealt with by making the routines that
+ deal with the inferior a little smarter, and possibly even allow
+ an inferior to continue running at the same time as gdb. (FIXME?) */
+ signal_to_pass = 0;
+ else if (signo == TARGET_SIGNAL_TSTP
+ && THE_PR_LWP(pi->prstatus).pr_cursig == SIGTSTP
+ && THE_PR_LWP(pi->prstatus).pr_action.sa_handler == SIG_DFL
+ )
+
+ /* We are about to pass the inferior a SIGTSTP whose action is
+ SIG_DFL. The SIG_DFL action for a SIGTSTP is to stop
+ (notifying the parent via wait()), and then keep going from the
+ same place when the parent is ready for you to keep going. So
+ under the debugger, it should do nothing (as if the program had
+ been stopped and then later resumed. Under ptrace, this
+ happens for us, but under /proc, the system obligingly stops
+ the process, and wait_for_inferior would have no way of
+ distinguishing that type of stop (which indicates that we
+ should just start it again), with a stop due to the pr_trace
+ field of the prrun_t struct.
+
+ Note that if the SIGTSTP is being caught, we *do* need to pass it,
+ because the handler needs to get executed. */
+ signal_to_pass = 0;
+ else
+ signal_to_pass = target_signal_to_host (signo);
+
+ if (signal_to_pass)
+ {
+ set_proc_siginfo (pi, signal_to_pass);
+ }
+ else
+ {
+#ifdef UNIXWARE
+ pctl.data |= PRCSIG;
+#else
+ pi->prrun.pr_flags |= PRCSIG;
+#endif
+ }
+ pi->nopass_next_sigstop = 0;
+ if (step)
+ {
+#ifdef UNIXWARE
+ pctl.data |= PRSTEP;
+#else
+ pi->prrun.pr_flags |= PRSTEP;
+#endif
+ }
+ pi->had_event = 0;
+ /* Don't try to start a process unless it's stopped on an
+ `event of interest'. Doing so will cause errors. */
+
+ if (!procfs_read_status (pi))
+ {
+ /* The LWP has apparently terminated. */
+ if (info_verbose)
+ printf_filtered ("LWP %d doesn't respond.\n",
+ (pi->pid >> 16) & 0xffff);
+ close_proc_file (pi);
+ }
+ else
+ {
+#ifdef PROCFS_USE_READ_WRITE
+ if (write (pi->ctl_fd, (char *) &pctl, sizeof (struct proc_ctl)) < 0)
+#else
+ if ((pi->prstatus.pr_flags & PR_ISTOP)
+ && ioctl (pi->ctl_fd, PIOCRUN, &pi->prrun) != 0)
+#endif
+ {
+ /* The LWP has apparently terminated. */
+ if (info_verbose)
+ printf_filtered ("LWP %d doesn't respond.\n",
+ (pi->pid >> 16) & 0xffff);
+ close_proc_file (pi);
+ }
+ }
+
+ /* Continue all the other threads that haven't had an event of interest.
+ Also continue them if they have NOPASS_NEXT_SIGSTOP set; this is only
+ set by do_attach, and means this is the first resume after an attach.
+ All threads were CSTOP'd by do_attach, and should be resumed now. */
+
+ if (pid == -1)
+ for (procinfo = procinfo_list; procinfo; procinfo = next_pi)
+ {
+ next_pi = procinfo->next;
+ if (pi != procinfo)
+ if (!procinfo->had_event ||
+ (procinfo->nopass_next_sigstop && signo == TARGET_SIGNAL_STOP))
+ {
+ procinfo->had_event = procinfo->nopass_next_sigstop = 0;
+#ifdef PROCFS_USE_READ_WRITE
+ pctl.data = PRCFAULT | PRCSIG;
+ if (write (procinfo->ctl_fd, (char *) &pctl,
+ sizeof (struct proc_ctl)) < 0)
+ {
+ if (!procfs_read_status (procinfo))
+ fprintf_unfiltered(gdb_stderr,
+ "procfs_read_status failed, errno=%d\n",
+ errno);
+ print_sys_errmsg (procinfo->pathname, errno);
+ error ("PCRUN failed");
+ }
+#else
+ procinfo->prrun.pr_flags &= PRSTEP;
+ procinfo->prrun.pr_flags |= PRCFAULT | PRCSIG;
+ if (!procfs_read_status (procinfo))
+ {
+ /* The LWP has apparently terminated. */
+ if (info_verbose)
+ printf_filtered ("LWP %d doesn't respond.\n",
+ (procinfo->pid >> 16) & 0xffff);
+ close_proc_file (procinfo);
+ continue;
+ }
+
+ /* Don't try to start a process unless it's stopped on an
+ `event of interest'. Doing so will cause errors. */
+
+ if ((procinfo->prstatus.pr_flags & PR_ISTOP)
+ && ioctl (procinfo->ctl_fd, PIOCRUN, &procinfo->prrun) < 0)
+ {
+ if (!procfs_read_status (procinfo))
+ fprintf_unfiltered(gdb_stderr,
+ "procfs_read_status failed, errno=%d\n",
+ errno);
+ print_sys_errmsg (procinfo->pathname, errno);
+ warning ("PIOCRUN failed");
+ }
+#endif
+ }
+ procfs_read_status (procinfo);
+ }
+}
+
+/*
+
+LOCAL FUNCTION
+
+ procfs_fetch_registers -- fetch current registers from inferior
+
+SYNOPSIS
+
+ void procfs_fetch_registers (int regno)
+
+DESCRIPTION
+
+ Read the current values of the inferior's registers, both the
+ general register set and floating point registers (if supported)
+ and update gdb's idea of their current values.
+
+*/
+
+static void
+procfs_fetch_registers (regno)
+ int regno;
+{
+ struct procinfo *pi;
+
+ pi = current_procinfo;
+
+#ifdef UNIXWARE
+ if (procfs_read_status (pi))
+ {
+ supply_gregset (&pi->prstatus.pr_lwp.pr_context.uc_mcontext.gregs);
+#if defined (FP0_REGNUM)
+ supply_fpregset (&pi->prstatus.pr_lwp.pr_context.uc_mcontext.fpregs);
+#endif
+ }
+#else /* UNIXWARE */
+ if (ioctl (pi->ctl_fd, PIOCGREG, &pi->gregset.gregset) != -1)
+ {
+ supply_gregset (&pi->gregset.gregset);
+ }
+#if defined (FP0_REGNUM)
+ if (ioctl (pi->ctl_fd, PIOCGFPREG, &pi->fpregset.fpregset) != -1)
+ {
+ supply_fpregset (&pi->fpregset.fpregset);
+ }
+#endif
+#endif /* UNIXWARE */
+}
+
+/*
+
+LOCAL FUNCTION
+
+ proc_init_failed - called when /proc access initialization fails
+fails
+
+SYNOPSIS
+
+ static void proc_init_failed (struct procinfo *pi,
+ char *why, int kill_p)
+
+DESCRIPTION
+
+ This function is called whenever initialization of access to a /proc
+ entry fails. It prints a suitable error message, does some cleanup,
+ and then invokes the standard error processing routine which dumps
+ us back into the command loop. If KILL_P is true, sends SIGKILL.
+ */
+
+static void
+proc_init_failed (pi, why, kill_p)
+ struct procinfo *pi;
+ char *why;
+ int kill_p;
+{
+ print_sys_errmsg (pi->pathname, errno);
+ if (kill_p)
+ kill (pi->pid, SIGKILL);
+ close_proc_file (pi);
+ error (why);
+ /* NOTREACHED */
+}
+
+/*
+
+LOCAL FUNCTION
+
+ close_proc_file - close any currently open /proc entry
+
+SYNOPSIS
+
+ static void close_proc_file (struct procinfo *pip)
+
+DESCRIPTION
+
+ Close any currently open /proc entry and mark the process information
+ entry as invalid. In order to ensure that we don't try to reuse any
+ stale information, the pid, fd, and pathnames are explicitly
+ invalidated, which may be overkill.
+
+ */
+
+static void
+close_proc_file (pip)
+ struct procinfo *pip;
+{
+ struct procinfo *procinfo;
+
+ delete_thread (pip->pid); /* remove thread from GDB's thread list */
+ remove_fd (pip); /* Remove fd from poll/select list */
+
+ close (pip->ctl_fd);
+#ifdef HAVE_MULTIPLE_PROC_FDS
+ close (pip->as_fd);
+ close (pip->status_fd);
+ close (pip->map_fd);
+#endif
+
+ free (pip -> pathname);
+
+ /* Unlink pip from the procinfo chain. Note pip might not be on the list. */
+
+ if (procinfo_list == pip)
+ procinfo_list = pip->next;
+ else
+ {
+ for (procinfo = procinfo_list; procinfo; procinfo = procinfo->next)
+ {
+ if (procinfo->next == pip)
+ {
+ procinfo->next = pip->next;
+ break;
+ }
+ }
+ free (pip);
+ }
+}
+
+/*
+
+LOCAL FUNCTION
+
+ open_proc_file - open a /proc entry for a given process id
+
+SYNOPSIS
+
+ static int open_proc_file (int pid, struct procinfo *pip, int mode)
+
+DESCRIPTION
+
+ Given a process id and a mode, close the existing open /proc
+ entry (if any) and open one for the new process id, in the
+ specified mode. Once it is open, then mark the local process
+ information structure as valid, which guarantees that the pid,
+ fd, and pathname fields match an open /proc entry. Returns
+ zero if the open fails, nonzero otherwise.
+
+ Note that the pathname is left intact, even when the open fails,
+ so that callers can use it to construct meaningful error messages
+ rather than just "file open failed".
+
+ Note that for Solaris, the process-id also includes an LWP-id, so we
+ actually attempt to open that. If we are handed a pid with a 0 LWP-id,
+ then we will ask the kernel what it is and add it to the pid. Hence,
+ the pid can be changed by us.
+ */
+
+static int
+open_proc_file (pid, pip, mode, control)
+ int pid;
+ struct procinfo *pip;
+ int mode;
+ int control;
+{
+ int tmp, tmpfd;
+
+ pip -> next = NULL;
+ pip -> had_event = 0;
+ pip -> pathname = xmalloc (MAX_PROC_NAME_SIZE);
+ pip -> pid = pid;
+
+#ifndef PIOCOPENLWP
+ tmp = pid;
+#else
+ tmp = pid & 0xffff;
+#endif
+
+#ifdef HAVE_MULTIPLE_PROC_FDS
+ sprintf (pip->pathname, STATUS_PROC_NAME_FMT, tmp);
+ if ((pip->status_fd = open (pip->pathname, O_RDONLY)) < 0)
+ {
+ return 0;
+ }
+
+ sprintf (pip->pathname, AS_PROC_NAME_FMT, tmp);
+ if ((pip->as_fd = open (pip->pathname, O_RDWR)) < 0)
+ {
+ close (pip->status_fd);
+ return 0;
+ }
+
+ sprintf (pip->pathname, MAP_PROC_NAME_FMT, tmp);
+ if ((pip->map_fd = open (pip->pathname, O_RDONLY)) < 0)
+ {
+ close (pip->status_fd);
+ close (pip->as_fd);
+ return 0;
+ }
+
+ if (control)
+ {
+ sprintf (pip->pathname, CTL_PROC_NAME_FMT, tmp);
+ if ((pip->ctl_fd = open (pip->pathname, O_WRONLY)) < 0)
+ {
+ close (pip->status_fd);
+ close (pip->as_fd);
+ close (pip->map_fd);
+ return 0;
+ }
+ }
+
+#else /* HAVE_MULTIPLE_PROC_FDS */
+ sprintf (pip -> pathname, CTL_PROC_NAME_FMT, tmp);
+
+ if ((tmpfd = open (pip -> pathname, mode)) < 0)
+ return 0;
+
+#ifndef PIOCOPENLWP
+ pip -> ctl_fd = tmpfd;
+ pip -> as_fd = tmpfd;
+ pip -> map_fd = tmpfd;
+ pip -> status_fd = tmpfd;
+#else
+ tmp = (pid >> 16) & 0xffff; /* Extract thread id */
+
+ if (tmp == 0)
+ { /* Don't know thread id yet */
+ if (ioctl (tmpfd, PIOCSTATUS, &pip -> prstatus) < 0)
+ {
+ print_sys_errmsg (pip -> pathname, errno);
+ close (tmpfd);
+ error ("open_proc_file: PIOCSTATUS failed");
+ }
+
+ tmp = pip -> prstatus.pr_who; /* Get thread id from prstatus_t */
+ pip -> pid = (tmp << 16) | pid; /* Update pip */
+ }
+
+ if ((pip -> ctl_fd = ioctl (tmpfd, PIOCOPENLWP, &tmp)) < 0)
+ {
+ close (tmpfd);
+ return 0;
+ }
+
+#ifdef PIOCSET /* New method */
+ {
+ long pr_flags;
+ pr_flags = PR_ASYNC;
+ ioctl (pip -> ctl_fd, PIOCSET, &pr_flags);
+ }
+#endif
+
+ /* keep extra fds in sync */
+ pip->as_fd = pip->ctl_fd;
+ pip->map_fd = pip->ctl_fd;
+ pip->status_fd = pip->ctl_fd;
+
+ close (tmpfd); /* All done with main pid */
+#endif /* PIOCOPENLWP */
+
+#endif /* HAVE_MULTIPLE_PROC_FDS */
+
+ return 1;
+}
+
+static char *
+mappingflags (flags)
+ long flags;
+{
+ static char asciiflags[8];
+
+ strcpy (asciiflags, "-------");
+#if defined (MA_PHYS)
+ if (flags & MA_PHYS) asciiflags[0] = 'd';
+#endif
+ if (flags & MA_STACK) asciiflags[1] = 's';
+ if (flags & MA_BREAK) asciiflags[2] = 'b';
+ if (flags & MA_SHARED) asciiflags[3] = 's';
+ if (flags & MA_READ) asciiflags[4] = 'r';
+ if (flags & MA_WRITE) asciiflags[5] = 'w';
+ if (flags & MA_EXEC) asciiflags[6] = 'x';
+ return (asciiflags);
+}
+
+static void
+info_proc_flags (pip, summary)
+ struct procinfo *pip;
+ int summary;
+{
+ struct trans *transp;
+#ifdef UNIXWARE
+ long flags = pip->prstatus.pr_flags | pip->prstatus.pr_lwp.pr_flags;
+#else
+ long flags = pip->prstatus.pr_flags;
+#endif
+
+ printf_filtered ("%-32s", "Process status flags:");
+ if (!summary)
+ {
+ printf_filtered ("\n\n");
+ }
+ for (transp = pr_flag_table; transp -> name != NULL; transp++)
+ {
+ if (flags & transp -> value)
+ {
+ if (summary)
+ {
+ printf_filtered ("%s ", transp -> name);
+ }
+ else
+ {
+ printf_filtered ("\t%-16s %s.\n", transp -> name, transp -> desc);
+ }
+ }
+ }
+ printf_filtered ("\n");
+}
+
+static void
+info_proc_stop (pip, summary)
+ struct procinfo *pip;
+ int summary;
+{
+ struct trans *transp;
+ int why;
+ int what;
+
+ why = THE_PR_LWP(pip->prstatus).pr_why;
+ what = THE_PR_LWP(pip->prstatus).pr_what;
+
+ if (THE_PR_LWP(pip->prstatus).pr_flags & PR_STOPPED)
+ {
+ printf_filtered ("%-32s", "Reason for stopping:");
+ if (!summary)
+ {
+ printf_filtered ("\n\n");
+ }
+ for (transp = pr_why_table; transp -> name != NULL; transp++)
+ {
+ if (why == transp -> value)
+ {
+ if (summary)
+ {
+ printf_filtered ("%s ", transp -> name);
+ }
+ else
+ {
+ printf_filtered ("\t%-16s %s.\n",
+ transp -> name, transp -> desc);
+ }
+ break;
+ }
+ }
+
+ /* Use the pr_why field to determine what the pr_what field means, and
+ print more information. */
+
+ switch (why)
+ {
+ case PR_REQUESTED:
+ /* pr_what is unused for this case */
+ break;
+ case PR_JOBCONTROL:
+ case PR_SIGNALLED:
+ if (summary)
+ {
+ printf_filtered ("%s ", signalname (what));
+ }
+ else
+ {
+ printf_filtered ("\t%-16s %s.\n", signalname (what),
+ safe_strsignal (what));
+ }
+ break;
+ case PR_SYSENTRY:
+ if (summary)
+ {
+ printf_filtered ("%s ", syscallname (what));
+ }
+ else
+ {
+ printf_filtered ("\t%-16s %s.\n", syscallname (what),
+ "Entered this system call");
+ }
+ break;
+ case PR_SYSEXIT:
+ if (summary)
+ {
+ printf_filtered ("%s ", syscallname (what));
+ }
+ else
+ {
+ printf_filtered ("\t%-16s %s.\n", syscallname (what),
+ "Returned from this system call");
+ }
+ break;
+ case PR_FAULTED:
+ if (summary)
+ {
+ printf_filtered ("%s ",
+ lookupname (faults_table, what, "fault"));
+ }
+ else
+ {
+ printf_filtered ("\t%-16s %s.\n",
+ lookupname (faults_table, what, "fault"),
+ lookupdesc (faults_table, what));
+ }
+ break;
+ }
+ printf_filtered ("\n");
+ }
+}
+
+static void
+info_proc_siginfo (pip, summary)
+ struct procinfo *pip;
+ int summary;
+{
+ struct siginfo *sip;
+
+ if ((THE_PR_LWP(pip->prstatus).pr_flags & PR_STOPPED) &&
+ (THE_PR_LWP(pip->prstatus).pr_why == PR_SIGNALLED ||
+ THE_PR_LWP(pip->prstatus).pr_why == PR_FAULTED))
+ {
+ printf_filtered ("%-32s", "Additional signal/fault info:");
+ sip = &(THE_PR_LWP(pip->prstatus).pr_info);
+ if (summary)
+ {
+ printf_filtered ("%s ", signalname (sip -> si_signo));
+ if (sip -> si_errno > 0)
+ {
+ printf_filtered ("%s ", errnoname (sip -> si_errno));
+ }
+ if (sip -> si_code <= 0)
+ {
+ printf_filtered ("sent by %s, uid %d ",
+ target_pid_to_str (sip -> si_pid),
+ sip -> si_uid);
+ }
+ else
+ {
+ printf_filtered ("%s ", sigcodename (sip));
+ if ((sip -> si_signo == SIGILL) ||
+ (sip -> si_signo == SIGFPE) ||
+ (sip -> si_signo == SIGSEGV) ||
+ (sip -> si_signo == SIGBUS))
+ {
+ printf_filtered ("addr=%#lx ",
+ (unsigned long) sip -> si_addr);
+ }
+ else if ((sip -> si_signo == SIGCHLD))
+ {
+ printf_filtered ("child %s, status %u ",
+ target_pid_to_str (sip -> si_pid),
+ sip -> si_status);
+ }
+ else if ((sip -> si_signo == SIGPOLL))
+ {
+ printf_filtered ("band %u ", sip -> si_band);
+ }
+ }
+ }
+ else
+ {
+ printf_filtered ("\n\n");
+ printf_filtered ("\t%-16s %s.\n", signalname (sip -> si_signo),
+ safe_strsignal (sip -> si_signo));
+ if (sip -> si_errno > 0)
+ {
+ printf_filtered ("\t%-16s %s.\n",
+ errnoname (sip -> si_errno),
+ safe_strerror (sip -> si_errno));
+ }
+ if (sip -> si_code <= 0)
+ {
+ printf_filtered ("\t%-16u %s\n", sip -> si_pid, /* XXX need target_pid_to_str() */
+ "PID of process sending signal");
+ printf_filtered ("\t%-16u %s\n", sip -> si_uid,
+ "UID of process sending signal");
+ }
+ else
+ {
+ printf_filtered ("\t%-16s %s.\n", sigcodename (sip),
+ sigcodedesc (sip));
+ if ((sip -> si_signo == SIGILL) ||
+ (sip -> si_signo == SIGFPE))
+ {
+ printf_filtered ("\t%#-16lx %s.\n",
+ (unsigned long) sip -> si_addr,
+ "Address of faulting instruction");
+ }
+ else if ((sip -> si_signo == SIGSEGV) ||
+ (sip -> si_signo == SIGBUS))
+ {
+ printf_filtered ("\t%#-16lx %s.\n",
+ (unsigned long) sip -> si_addr,
+ "Address of faulting memory reference");
+ }
+ else if ((sip -> si_signo == SIGCHLD))
+ {
+ printf_filtered ("\t%-16u %s.\n", sip -> si_pid, /* XXX need target_pid_to_str() */
+ "Child process ID");
+ printf_filtered ("\t%-16u %s.\n", sip -> si_status,
+ "Child process exit value or signal");
+ }
+ else if ((sip -> si_signo == SIGPOLL))
+ {
+ printf_filtered ("\t%-16u %s.\n", sip -> si_band,
+ "Band event for POLL_{IN,OUT,MSG}");
+ }
+ }
+ }
+ printf_filtered ("\n");
+ }
+}
+
+static void
+info_proc_syscalls (pip, summary)
+ struct procinfo *pip;
+ int summary;
+{
+ int syscallnum;
+
+ if (!summary)
+ {
+
+#if 0 /* FIXME: Needs to use gdb-wide configured info about system calls. */
+ if (pip -> prstatus.pr_flags & PR_ASLEEP)
+ {
+ int syscallnum = pip -> prstatus.pr_reg[R_D0];
+ if (summary)
+ {
+ printf_filtered ("%-32s", "Sleeping in system call:");
+ printf_filtered ("%s", syscallname (syscallnum));
+ }
+ else
+ {
+ printf_filtered ("Sleeping in system call '%s'.\n",
+ syscallname (syscallnum));
+ }
+ }
+#endif
+
+#ifndef UNIXWARE
+ if (ioctl (pip -> ctl_fd, PIOCGENTRY, &pip -> entryset) < 0)
+ {
+ print_sys_errmsg (pip -> pathname, errno);
+ error ("PIOCGENTRY failed");
+ }
+
+ if (ioctl (pip -> ctl_fd, PIOCGEXIT, &pip -> exitset) < 0)
+ {
+ print_sys_errmsg (pip -> pathname, errno);
+ error ("PIOCGEXIT failed");
+ }
+#endif
+
+ printf_filtered ("System call tracing information:\n\n");
+
+ printf_filtered ("\t%-12s %-8s %-8s\n",
+ "System call",
+ "Entry",
+ "Exit");
+ for (syscallnum = 0; syscallnum < MAX_SYSCALLS; syscallnum++)
+ {
+ QUIT;
+ if (syscall_table[syscallnum] != NULL)
+ printf_filtered ("\t%-12s ", syscall_table[syscallnum]);
+ else
+ printf_filtered ("\t%-12d ", syscallnum);
+
+#ifdef UNIXWARE
+ printf_filtered ("%-8s ",
+ prismember (&pip->prstatus.pr_sysentry, syscallnum)
+ ? "on" : "off");
+ printf_filtered ("%-8s ",
+ prismember (&pip->prstatus.pr_sysexit, syscallnum)
+ ? "on" : "off");
+#else
+ printf_filtered ("%-8s ",
+ prismember (&pip -> entryset, syscallnum)
+ ? "on" : "off");
+ printf_filtered ("%-8s ",
+ prismember (&pip -> exitset, syscallnum)
+ ? "on" : "off");
+#endif
+ printf_filtered ("\n");
+ }
+ printf_filtered ("\n");
+ }
+}
+
+static char *
+signalname (signo)
+ int signo;
+{
+ const char *name;
+ static char locbuf[32];
+
+ name = strsigno (signo);
+ if (name == NULL)
+ {
+ sprintf (locbuf, "Signal %d", signo);
+ }
+ else
+ {
+ sprintf (locbuf, "%s (%d)", name, signo);
+ }
+ return (locbuf);
+}
+
+static char *
+errnoname (errnum)
+ int errnum;
+{
+ const char *name;
+ static char locbuf[32];
+
+ name = strerrno (errnum);
+ if (name == NULL)
+ {
+ sprintf (locbuf, "Errno %d", errnum);
+ }
+ else
+ {
+ sprintf (locbuf, "%s (%d)", name, errnum);
+ }
+ return (locbuf);
+}
+
+static void
+info_proc_signals (pip, summary)
+ struct procinfo *pip;
+ int summary;
+{
+ int signo;
+
+ if (!summary)
+ {
+#ifndef PROCFS_USE_READ_WRITE
+ if (ioctl (pip -> ctl_fd, PIOCGTRACE, &pip -> trace) < 0)
+ {
+ print_sys_errmsg (pip -> pathname, errno);
+ error ("PIOCGTRACE failed");
+ }
+#endif
+
+ printf_filtered ("Disposition of signals:\n\n");
+ printf_filtered ("\t%-15s %-8s %-8s %-8s %s\n\n",
+ "Signal", "Trace", "Hold", "Pending", "Description");
+ for (signo = 0; signo < NSIG; signo++)
+ {
+ QUIT;
+ printf_filtered ("\t%-15s ", signalname (signo));
+#ifdef UNIXWARE
+ printf_filtered ("%-8s ",
+ prismember (&pip -> prstatus.pr_sigtrace, signo)
+ ? "on" : "off");
+ printf_filtered ("%-8s ",
+ prismember (&pip -> prstatus.pr_lwp.pr_context.uc_sigmask, signo)
+ ? "on" : "off");
+#else
+ printf_filtered ("%-8s ",
+ prismember (&pip -> trace, signo)
+ ? "on" : "off");
+ printf_filtered ("%-8s ",
+ prismember (&pip -> prstatus.pr_sighold, signo)
+ ? "on" : "off");
+#endif
+
+#ifdef UNIXWARE
+ if (prismember (&pip->prstatus.pr_sigpend, signo) ||
+ prismember (&pip->prstatus.pr_lwp.pr_lwppend, signo))
+ printf_filtered("%-8s ", "yes");
+ else
+ printf_filtered("%-8s ", "no");
+#else /* UNIXWARE */
+#ifdef PROCFS_SIGPEND_OFFSET
+ /* Alpha OSF/1 numbers the pending signals from 1. */
+ printf_filtered ("%-8s ",
+ (signo ? prismember (&pip -> prstatus.pr_sigpend,
+ signo - 1)
+ : 0)
+ ? "yes" : "no");
+#else
+ printf_filtered ("%-8s ",
+ prismember (&pip -> prstatus.pr_sigpend, signo)
+ ? "yes" : "no");
+#endif
+#endif /* UNIXWARE */
+ printf_filtered (" %s\n", safe_strsignal (signo));
+ }
+ printf_filtered ("\n");
+ }
+}
+
+static void
+info_proc_faults (pip, summary)
+ struct procinfo *pip;
+ int summary;
+{
+ struct trans *transp;
+
+ if (!summary)
+ {
+#ifndef UNIXWARE
+ if (ioctl (pip -> ctl_fd, PIOCGFAULT, &pip->fltset.fltset) < 0)
+ {
+ print_sys_errmsg (pip -> pathname, errno);
+ error ("PIOCGFAULT failed");
+ }
+#endif
+
+ printf_filtered ("Current traced hardware fault set:\n\n");
+ printf_filtered ("\t%-12s %-8s\n", "Fault", "Trace");
+
+ for (transp = faults_table; transp -> name != NULL; transp++)
+ {
+ QUIT;
+ printf_filtered ("\t%-12s ", transp -> name);
+#ifdef UNIXWARE
+ printf_filtered ("%-8s", prismember (&pip->prstatus.pr_flttrace, transp -> value)
+ ? "on" : "off");
+#else
+ printf_filtered ("%-8s", prismember (&pip->fltset.fltset, transp -> value)
+ ? "on" : "off");
+#endif
+ printf_filtered ("\n");
+ }
+ printf_filtered ("\n");
+ }
+}
+
+static void
+info_proc_mappings (pip, summary)
+ struct procinfo *pip;
+ int summary;
+{
+ int nmap;
+ struct prmap *prmaps;
+ struct prmap *prmap;
+ struct stat sbuf;
+
+ if (!summary)
+ {
+ printf_filtered ("Mapped address spaces:\n\n");
+#ifdef BFD_HOST_64_BIT
+ printf_filtered (" %18s %18s %10s %10s %7s\n",
+#else
+ printf_filtered ("\t%10s %10s %10s %10s %7s\n",
+#endif
+ "Start Addr",
+ " End Addr",
+ " Size",
+ " Offset",
+ "Flags");
+#ifdef PROCFS_USE_READ_WRITE
+ if (fstat (pip->map_fd, &sbuf) == 0)
+ {
+ nmap = sbuf.st_size / sizeof (prmap_t);
+ prmaps = (struct prmap *) alloca ((nmap + 1) * sizeof (*prmaps));
+ if ((lseek (pip->map_fd, 0, SEEK_SET) == 0) &&
+ (read (pip->map_fd, (char *) prmaps,
+ nmap * sizeof (*prmaps)) == (nmap * sizeof (*prmaps))))
+ {
+ int i = 0;
+ for (prmap = prmaps; i < nmap; ++prmap, ++i)
+#else
+ if (ioctl (pip -> ctl_fd, PIOCNMAP, &nmap) == 0)
+ {
+ prmaps = (struct prmap *) alloca ((nmap + 1) * sizeof (*prmaps));
+ if (ioctl (pip -> ctl_fd, PIOCMAP, prmaps) == 0)
+ {
+ for (prmap = prmaps; prmap -> pr_size; ++prmap)
+#endif /* PROCFS_USE_READ_WRITE */
+ {
+#ifdef BFD_HOST_64_BIT
+ printf_filtered (" %#18lx %#18lx %#10x %#10x %7s\n",
+#else
+ printf_filtered ("\t%#10lx %#10lx %#10x %#10x %7s\n",
+#endif
+ (unsigned long)prmap -> pr_vaddr,
+ (unsigned long)prmap -> pr_vaddr
+ + prmap -> pr_size - 1,
+ prmap -> pr_size,
+ prmap -> pr_off,
+ mappingflags (prmap -> pr_mflags));
+ }
+ }
+ }
+ printf_filtered ("\n");
+ }
+}
+
+/*
+
+LOCAL FUNCTION
+
+ info_proc -- implement the "info proc" command
+
+SYNOPSIS
+
+ void info_proc (char *args, int from_tty)
+
+DESCRIPTION
+
+ Implement gdb's "info proc" command by using the /proc interface
+ to print status information about any currently running process.
+
+ Examples of the use of "info proc" are:
+
+ info proc (prints summary info for current inferior)
+ info proc 123 (prints summary info for process with pid 123)
+ info proc mappings (prints address mappings)
+ info proc times (prints process/children times)
+ info proc id (prints pid, ppid, gid, sid, etc)
+ FIXME: i proc id not implemented.
+ info proc status (prints general process state info)
+ FIXME: i proc status not implemented.
+ info proc signals (prints info about signal handling)
+ info proc all (prints all info)
+
+ */
+
+static void
+info_proc (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ int pid;
+ struct procinfo *pip;
+ struct cleanup *old_chain;
+ char **argv;
+ int argsize;
+ int summary = 1;
+ int flags = 0;
+ int syscalls = 0;
+ int signals = 0;
+ int faults = 0;
+ int mappings = 0;
+ int times = 0;
+ int id = 0;
+ int status = 0;
+ int all = 0;
+ int nlwp;
+ int *lwps;
+
+ old_chain = make_cleanup (null_cleanup, 0);
+
+ /* Default to using the current inferior if no pid specified. Note
+ that inferior_pid may be 0, hence we set okerr. */
+
+ pid = inferior_pid & 0x7fffffff; /* strip off sol-thread bit */
+ if (!(pip = find_procinfo (pid, 1))) /* inferior_pid no good? */
+ pip = procinfo_list; /* take first available */
+ pid = pid & 0xffff; /* extract "real" pid */
+
+ if (args != NULL)
+ {
+ if ((argv = buildargv (args)) == NULL)
+ {
+ nomem (0);
+ }
+ make_cleanup (freeargv, (char *) argv);
+
+ while (*argv != NULL)
+ {
+ argsize = strlen (*argv);
+ if (argsize >= 1 && strncmp (*argv, "all", argsize) == 0)
+ {
+ summary = 0;
+ all = 1;
+ }
+ else if (argsize >= 2 && strncmp (*argv, "faults", argsize) == 0)
+ {
+ summary = 0;
+ faults = 1;
+ }
+ else if (argsize >= 2 && strncmp (*argv, "flags", argsize) == 0)
+ {
+ summary = 0;
+ flags = 1;
+ }
+ else if (argsize >= 1 && strncmp (*argv, "id", argsize) == 0)
+ {
+ summary = 0;
+ id = 1;
+ }
+ else if (argsize >= 1 && strncmp (*argv, "mappings", argsize) == 0)
+ {
+ summary = 0;
+ mappings = 1;
+ }
+ else if (argsize >= 2 && strncmp (*argv, "signals", argsize) == 0)
+ {
+ summary = 0;
+ signals = 1;
+ }
+ else if (argsize >= 2 && strncmp (*argv, "status", argsize) == 0)
+ {
+ summary = 0;
+ status = 1;
+ }
+ else if (argsize >= 2 && strncmp (*argv, "syscalls", argsize) == 0)
+ {
+ summary = 0;
+ syscalls = 1;
+ }
+ else if (argsize >= 1 && strncmp (*argv, "times", argsize) == 0)
+ {
+ summary = 0;
+ times = 1;
+ }
+ else if ((pid = atoi (*argv)) > 0)
+ {
+ pip = (struct procinfo *) xmalloc (sizeof (struct procinfo));
+ memset (pip, 0, sizeof (*pip));
+
+ pip->pid = pid;
+ if (!open_proc_file (pid, pip, O_RDONLY, 0))
+ {
+ perror_with_name (pip -> pathname);
+ /* NOTREACHED */
+ }
+ pid = pip->pid;
+ make_cleanup (close_proc_file, pip);
+ }
+ else if (**argv != '\000')
+ {
+ error ("Unrecognized or ambiguous keyword `%s'.", *argv);
+ }
+ argv++;
+ }
+ }
+
+ /* If we don't have a valid open process at this point, then we have no
+ inferior or didn't specify a specific pid. */
+
+ if (!pip)
+ {
+ error ("\
+No process. Start debugging a program or specify an explicit process ID.");
+ }
+
+ if (!procfs_read_status (pip))
+ {
+ print_sys_errmsg (pip -> pathname, errno);
+ error ("procfs_read_status failed");
+ }
+
+#ifndef PROCFS_USE_READ_WRITE
+#ifdef PIOCLWPIDS
+ nlwp = pip->prstatus.pr_nlwp;
+ lwps = alloca ((2 * nlwp + 2) * sizeof (*lwps));
+
+ if (ioctl (pip->ctl_fd, PIOCLWPIDS, lwps))
+ {
+ print_sys_errmsg (pip -> pathname, errno);
+ error ("PIOCLWPIDS failed");
+ }
+#else /* PIOCLWPIDS */
+ nlwp = 1;
+ lwps = alloca ((2 * nlwp + 2) * sizeof *lwps);
+ lwps[0] = 0;
+#endif /* PIOCLWPIDS */
+
+ for (; nlwp > 0; nlwp--, lwps++)
+ {
+ pip = find_procinfo ((*lwps << 16) | pid, 1);
+
+ if (!pip)
+ {
+ pip = (struct procinfo *) xmalloc (sizeof (struct procinfo));
+ memset (pip, 0, sizeof (*pip));
+ if (!open_proc_file ((*lwps << 16) | pid, pip, O_RDONLY, 0))
+ continue;
+
+ make_cleanup (close_proc_file, pip);
+
+ if (!procfs_read_status (pip))
+ {
+ print_sys_errmsg (pip -> pathname, errno);
+ error ("procfs_read_status failed");
+ }
+ }
+
+#endif /* PROCFS_USE_READ_WRITE */
+
+ /* Print verbose information of the requested type(s), or just a summary
+ of the information for all types. */
+
+ printf_filtered ("\nInformation for %s.%d:\n\n", pip -> pathname, *lwps);
+ if (summary || all || flags)
+ {
+ info_proc_flags (pip, summary);
+ }
+ if (summary || all)
+ {
+ info_proc_stop (pip, summary);
+#ifdef UNIXWARE
+ supply_gregset (&pip->prstatus.pr_lwp.pr_context.uc_mcontext.gregs);
+#else
+ supply_gregset (&pip->prstatus.pr_reg);
+#endif
+ printf_filtered ("PC: ");
+ print_address (read_pc (), gdb_stdout);
+ printf_filtered ("\n");
+ }
+ if (summary || all || signals || faults)
+ {
+ info_proc_siginfo (pip, summary);
+ }
+ if (summary || all || syscalls)
+ {
+ info_proc_syscalls (pip, summary);
+ }
+ if (summary || all || mappings)
+ {
+ info_proc_mappings (pip, summary);
+ }
+ if (summary || all || signals)
+ {
+ info_proc_signals (pip, summary);
+ }
+ if (summary || all || faults)
+ {
+ info_proc_faults (pip, summary);
+ }
+ printf_filtered ("\n");
+
+ /* All done, deal with closing any temporary process info structure,
+ freeing temporary memory , etc. */
+
+ do_cleanups (old_chain);
+#ifndef PROCFS_USE_READ_WRITE
+ }
+#endif
+}
+
+/*
+
+LOCAL FUNCTION
+
+ modify_inherit_on_fork_flag - Change the inherit-on-fork flag
+
+SYNOPSIS
+
+ void modify_inherit_on_fork_flag (fd, flag)
+
+DESCRIPTION
+
+ Call this routine to modify the inherit-on-fork flag. This routine is
+ just a nice wrapper to hide the #ifdefs needed by various systems to
+ control this flag.
+
+ */
+
+static void
+modify_inherit_on_fork_flag (fd, flag)
+ int fd;
+ int flag;
+{
+#if defined (PIOCSET) || defined (PCSET)
+ long pr_flags;
+#endif
+ int retval = 0;
+ struct proc_ctl pctl;
+
+#if defined (PIOCSET) || defined (PCSET) /* New method */
+ pr_flags = PR_FORK;
+ if (flag)
+ {
+#ifdef PROCFS_USE_READ_WRITE
+ pctl.cmd = PCSET;
+ pctl.data = PR_FORK;
+ if (write (fd, (char *) &pctl, sizeof (struct proc_ctl)) < 0)
+ retval = -1;
+#else
+ retval = ioctl (fd, PIOCSET, &pr_flags);
+#endif
+ }
+ else
+ {
+#ifdef PROCFS_USE_READ_WRITE
+ pctl.cmd = PCRESET;
+ pctl.data = PR_FORK;
+ if (write (fd, (char *) &pctl, sizeof (struct proc_ctl)) < 0)
+ retval = -1;
+#else
+ retval = ioctl (fd, PIOCRESET, &pr_flags);
+#endif
+ }
+
+#else
+#ifdef PIOCSFORK /* Original method */
+ if (flag)
+ {
+ retval = ioctl (fd, PIOCSFORK, NULL);
+ }
+ else
+ {
+ retval = ioctl (fd, PIOCRFORK, NULL);
+ }
+#else
+ Neither PR_FORK nor PIOCSFORK exist!!!
+#endif
+#endif
+
+ if (!retval)
+ return;
+
+ print_sys_errmsg ("modify_inherit_on_fork_flag", errno);
+ error ("PIOCSFORK or PR_FORK modification failed");
+}
+
+/*
+
+LOCAL FUNCTION
+
+ modify_run_on_last_close_flag - Change the run-on-last-close flag
+
+SYNOPSIS
+
+ void modify_run_on_last_close_flag (fd, flag)
+
+DESCRIPTION
+
+ Call this routine to modify the run-on-last-close flag. This routine
+ is just a nice wrapper to hide the #ifdefs needed by various systems to
+ control this flag.
+
+ */
+
+static void
+modify_run_on_last_close_flag (fd, flag)
+ int fd;
+ int flag;
+{
+#if defined (PIOCSET) || defined (PCSET)
+ long pr_flags;
+#endif
+ int retval = 0;
+ struct proc_ctl pctl;
+
+#if defined (PIOCSET) || defined (PCSET) /* New method */
+ pr_flags = PR_RLC;
+ if (flag)
+ {
+#ifdef PROCFS_USE_READ_WRITE
+ pctl.cmd = PCSET;
+ pctl.data = PR_RLC;
+ if (write (fd, (char *) &pctl, sizeof (struct proc_ctl)) < 0)
+ retval = -1;
+#else
+ retval = ioctl (fd, PIOCSET, &pr_flags);
+#endif
+ }
+ else
+ {
+#ifdef PROCFS_USE_READ_WRITE
+ pctl.cmd = PCRESET;
+ pctl.data = PR_RLC;
+ if (write (fd, (char *) &pctl, sizeof (struct proc_ctl)) < 0)
+ retval = -1;
+#else
+ retval = ioctl (fd, PIOCRESET, &pr_flags);
+#endif
+ }
+
+#else
+#ifdef PIOCSRLC /* Original method */
+ if (flag)
+ retval = ioctl (fd, PIOCSRLC, NULL);
+ else
+ retval = ioctl (fd, PIOCRRLC, NULL);
+#else
+ Neither PR_RLC nor PIOCSRLC exist!!!
+#endif
+#endif
+
+ if (!retval)
+ return;
+
+ print_sys_errmsg ("modify_run_on_last_close_flag", errno);
+ error ("PIOCSRLC or PR_RLC modification failed");
+}
+
+/*
+
+LOCAL FUNCTION
+
+ procfs_clear_syscall_trap -- Deletes the trap for the specified system call.
+
+SYNOPSIS
+
+ void procfs_clear_syscall_trap (struct procinfo *, int syscall_num, int errok)
+
+DESCRIPTION
+
+ This function function disables traps for the specified system call.
+ errok is non-zero if errors should be ignored.
+ */
+
+static void
+procfs_clear_syscall_trap (pi, syscall_num, errok)
+ struct procinfo *pi;
+ int syscall_num;
+ int errok;
+{
+ sysset_t sysset;
+ int goterr, i;
+
+#ifndef UNIXWARE
+ goterr = ioctl (pi->ctl_fd, PIOCGENTRY, &sysset) < 0;
+
+ if (goterr && !errok)
+ {
+ print_sys_errmsg (pi->pathname, errno);
+ error ("PIOCGENTRY failed");
+ }
+
+ if (!goterr)
+ {
+ prdelset (&sysset, syscall_num);
+
+ if ((ioctl (pi->ctl_fd, PIOCSENTRY, &sysset) < 0) && !errok)
+ {
+ print_sys_errmsg (pi->pathname, errno);
+ error ("PIOCSENTRY failed");
+ }
+ }
+
+ goterr = ioctl (pi->ctl_fd, PIOCGEXIT, &sysset) < 0;
+
+ if (goterr && !errok)
+ {
+ procfs_clear_syscall_trap (pi, syscall_num, 1);
+ print_sys_errmsg (pi->pathname, errno);
+ error ("PIOCGEXIT failed");
+ }
+
+ if (!goterr)
+ {
+ praddset (&sysset, syscall_num);
+
+ if ((ioctl (pi->ctl_fd, PIOCSEXIT, &sysset) < 0) && !errok)
+ {
+ procfs_clear_syscall_trap (pi, syscall_num, 1);
+ print_sys_errmsg (pi->pathname, errno);
+ error ("PIOCSEXIT failed");
+ }
+ }
+#endif
+
+ if (!pi->syscall_handlers)
+ {
+ if (!errok)
+ error ("procfs_clear_syscall_trap: syscall_handlers is empty");
+ return;
+ }
+
+ /* Remove handler func from the handler list */
+
+ for (i = 0; i < pi->num_syscall_handlers; i++)
+ if (pi->syscall_handlers[i].syscall_num == syscall_num)
+ {
+ if (i + 1 != pi->num_syscall_handlers)
+ { /* Not the last entry.
+ Move subsequent entries fwd. */
+ memcpy (&pi->syscall_handlers[i], &pi->syscall_handlers[i + 1],
+ (pi->num_syscall_handlers - i - 1)
+ * sizeof (struct procfs_syscall_handler));
+ }
+
+ pi->syscall_handlers = xrealloc (pi->syscall_handlers,
+ (pi->num_syscall_handlers - 1)
+ * sizeof (struct procfs_syscall_handler));
+ pi->num_syscall_handlers--;
+ return;
+ }
+
+ if (!errok)
+ error ("procfs_clear_syscall_trap: Couldn't find handler for sys call %d",
+ syscall_num);
+}
+
+/*
+
+LOCAL FUNCTION
+
+ procfs_set_syscall_trap -- arrange for a function to be called when the
+ child executes the specified system call.
+
+SYNOPSIS
+
+ void procfs_set_syscall_trap (struct procinfo *, int syscall_num, int flags,
+ syscall_func_t *function)
+
+DESCRIPTION
+
+ This function sets up an entry and/or exit trap for the specified system
+ call. When the child executes the specified system call, your function
+ will be called with the call #, a flag that indicates entry or exit, and
+ pointers to rtnval and statval (which are used by procfs_wait). The
+ function should return non-zero if something interesting happened, zero
+ otherwise.
+ */
+
+static void
+procfs_set_syscall_trap (pi, syscall_num, flags, func)
+ struct procinfo *pi;
+ int syscall_num;
+ int flags;
+ syscall_func_t *func;
+{
+ sysset_t sysset;
+
+#ifndef UNIXWARE
+ if (flags & PROCFS_SYSCALL_ENTRY)
+ {
+ if (ioctl (pi->ctl_fd, PIOCGENTRY, &sysset) < 0)
+ {
+ print_sys_errmsg (pi->pathname, errno);
+ error ("PIOCGENTRY failed");
+ }
+
+ praddset (&sysset, syscall_num);
+
+ if (ioctl (pi->ctl_fd, PIOCSENTRY, &sysset) < 0)
+ {
+ print_sys_errmsg (pi->pathname, errno);
+ error ("PIOCSENTRY failed");
+ }
+ }
+
+ if (flags & PROCFS_SYSCALL_EXIT)
+ {
+ if (ioctl (pi->ctl_fd, PIOCGEXIT, &sysset) < 0)
+ {
+ procfs_clear_syscall_trap (pi, syscall_num, 1);
+ print_sys_errmsg (pi->pathname, errno);
+ error ("PIOCGEXIT failed");
+ }
+
+ praddset (&sysset, syscall_num);
+
+ if (ioctl (pi->ctl_fd, PIOCSEXIT, &sysset) < 0)
+ {
+ procfs_clear_syscall_trap (pi, syscall_num, 1);
+ print_sys_errmsg (pi->pathname, errno);
+ error ("PIOCSEXIT failed");
+ }
+ }
+#endif
+
+ if (!pi->syscall_handlers)
+ {
+ pi->syscall_handlers = xmalloc (sizeof (struct procfs_syscall_handler));
+ pi->syscall_handlers[0].syscall_num = syscall_num;
+ pi->syscall_handlers[0].func = func;
+ pi->num_syscall_handlers = 1;
+ }
+ else
+ {
+ int i;
+
+ for (i = 0; i < pi->num_syscall_handlers; i++)
+ if (pi->syscall_handlers[i].syscall_num == syscall_num)
+ {
+ pi->syscall_handlers[i].func = func;
+ return;
+ }
+
+ pi->syscall_handlers = xrealloc (pi->syscall_handlers, (i + 1)
+ * sizeof (struct procfs_syscall_handler));
+ pi->syscall_handlers[i].syscall_num = syscall_num;
+ pi->syscall_handlers[i].func = func;
+ pi->num_syscall_handlers++;
+ }
+}
+
+#ifdef SYS_lwp_create
+
+/*
+
+LOCAL FUNCTION
+
+ procfs_lwp_creation_handler - handle exit from the _lwp_create syscall
+
+SYNOPSIS
+
+ int procfs_lwp_creation_handler (pi, syscall_num, why, rtnvalp, statvalp)
+
+DESCRIPTION
+
+ This routine is called both when an inferior process and it's new lwp
+ are about to finish a _lwp_create() system call. This is the system
+ call that Solaris uses to create a lightweight process. When the
+ target process gets this event, we can look at sysarg[2] to find the
+ new childs lwp ID, and create a procinfo struct from that. After that,
+ we pretend that we got a SIGTRAP, and return non-zero to tell
+ procfs_wait to wake up. Subsequently, wait_for_inferior gets woken up,
+ sees the new process and continues it.
+
+ When we see the child exiting from lwp_create, we just contine it,
+ since everything was handled when the parent trapped.
+
+NOTES
+ In effect, we are only paying attention to the parent's completion of
+ the lwp_create syscall. If we only paid attention to the child
+ instead, then we wouldn't detect the creation of a suspended thread.
+ */
+
+static int
+procfs_lwp_creation_handler (pi, syscall_num, why, rtnvalp, statvalp)
+ struct procinfo *pi;
+ int syscall_num;
+ int why;
+ int *rtnvalp;
+ int *statvalp;
+{
+ int lwp_id;
+ struct procinfo *childpi;
+ struct proc_ctl pctl;
+
+ /* We've just detected the completion of an lwp_create system call. Now we
+ need to setup a procinfo struct for this thread, and notify the thread
+ system of the new arrival. */
+
+ /* If lwp_create failed, then nothing interesting happened. Continue the
+ process and go back to sleep. */
+
+#ifdef UNIXWARE
+ /* Joel ... can you check this logic out please? JKJ */
+ if (pi->prstatus.pr_lwp.pr_context.uc_mcontext.gregs[R_EFL] & 1)
+ { /* _lwp_create failed */
+ pctl.cmd = PCRUN;
+ pctl.data = PRCFAULT;
+
+ if (write (pi->ctl_fd, (char *) &pctl, sizeof (struct proc_ctl)) < 0)
+ perror_with_name (pi->pathname);
+
+ return 0;
+ }
+#else /* UNIXWARE */
+ if (PROCFS_GET_CARRY (pi->prstatus.pr_reg))
+ { /* _lwp_create failed */
+ pi->prrun.pr_flags &= PRSTEP;
+ pi->prrun.pr_flags |= PRCFAULT;
+
+ if (ioctl (pi->ctl_fd, PIOCRUN, &pi->prrun) != 0)
+ perror_with_name (pi->pathname);
+
+ return 0;
+ }
+#endif
+
+ /* At this point, the new thread is stopped at it's first instruction, and
+ the parent is stopped at the exit from lwp_create. */
+
+ if (pi->new_child) /* Child? */
+ { /* Yes, just continue it */
+#ifdef UNIXWARE
+ pctl.cmd = PCRUN;
+ pctl.data = PRCFAULT;
+
+ if (write(pi->ctl_fd, (char *)&pctl, sizeof (struct proc_ctl)) < 0)
+#else /* !UNIXWARE */
+ pi->prrun.pr_flags &= PRSTEP;
+ pi->prrun.pr_flags |= PRCFAULT;
+
+ if ((pi->prstatus.pr_flags & PR_ISTOP)
+ && ioctl (pi->ctl_fd, PIOCRUN, &pi->prrun) != 0)
+#endif /* !UNIXWARE */
+ perror_with_name (pi->pathname);
+
+ pi->new_child = 0; /* No longer new */
+
+ return 0;
+ }
+
+ /* We're the proud parent of a new thread. Setup an exit trap for lwp_create
+ in the child and continue the parent. */
+
+ /* Third arg is pointer to new thread id. */
+ lwp_id = read_memory_integer (
+ THE_PR_LWP(pi->prstatus).pr_sysarg[2], sizeof (int));
+
+ lwp_id = (lwp_id << 16) | PIDGET (pi->pid);
+
+ childpi = create_procinfo (lwp_id);
+
+ /* The new process has actually inherited the lwp_create syscall trap from
+ it's parent, but we still have to call this to register handlers for
+ that child. */
+
+ procfs_set_inferior_syscall_traps (childpi);
+ add_thread (lwp_id);
+ printf_filtered ("[New %s]\n", target_pid_to_str (lwp_id));
+
+ /* Continue the parent */
+#ifdef UNIXWARE
+ pctl.cmd = PCRUN;
+ pctl.data = PRCFAULT;
+
+ if (write(pi->ctl_fd, (char *)&pctl, sizeof (struct proc_ctl)) < 0)
+#else
+ pi->prrun.pr_flags &= PRSTEP;
+ pi->prrun.pr_flags |= PRCFAULT;
+ if (ioctl (pi->ctl_fd, PIOCRUN, &pi->prrun) != 0)
+#endif
+ perror_with_name (pi->pathname);
+
+ /* The new child may have been created in one of two states:
+ SUSPENDED or RUNNABLE. If runnable, we will simply signal it to run.
+ If suspended, we flag it to be continued later, when it has an event. */
+
+ if (THE_PR_LWP(childpi->prstatus).pr_why == PR_SUSPENDED)
+ childpi->new_child = 1; /* Flag this as an unseen child process */
+ else
+ {
+ /* Continue the child */
+#ifdef UNIXWARE
+ pctl.cmd = PCRUN;
+ pctl.data = PRCFAULT;
+
+ if (write(pi->ctl_fd, (char *)&pctl, sizeof (struct proc_ctl)) < 0)
+#else
+ childpi->prrun.pr_flags &= PRSTEP;
+ childpi->prrun.pr_flags |= PRCFAULT;
+
+ if (ioctl (childpi->ctl_fd, PIOCRUN, &childpi->prrun) != 0)
+#endif
+ perror_with_name (childpi->pathname);
+ }
+ return 0;
+}
+#endif /* SYS_lwp_create */
+
+/* Fork an inferior process, and start debugging it with /proc. */
+
+static void
+procfs_create_inferior (exec_file, allargs, env)
+ char *exec_file;
+ char *allargs;
+ char **env;
+{
+ char *shell_file = getenv ("SHELL");
+ char *tryname;
+ if (shell_file != NULL && strchr (shell_file, '/') == NULL)
+ {
+
+ /* We will be looking down the PATH to find shell_file. If we
+ just do this the normal way (via execlp, which operates by
+ attempting an exec for each element of the PATH until it
+ finds one which succeeds), then there will be an exec for
+ each failed attempt, each of which will cause a PR_SYSEXIT
+ stop, and we won't know how to distinguish the PR_SYSEXIT's
+ for these failed execs with the ones for successful execs
+ (whether the exec has succeeded is stored at that time in the
+ carry bit or some such architecture-specific and
+ non-ABI-specified place).
+
+ So I can't think of anything better than to search the PATH
+ now. This has several disadvantages: (1) There is a race
+ condition; if we find a file now and it is deleted before we
+ exec it, we lose, even if the deletion leaves a valid file
+ further down in the PATH, (2) there is no way to know exactly
+ what an executable (in the sense of "capable of being
+ exec'd") file is. Using access() loses because it may lose
+ if the caller is the superuser; failing to use it loses if
+ there are ACLs or some such. */
+
+ char *p;
+ char *p1;
+ /* FIXME-maybe: might want "set path" command so user can change what
+ path is used from within GDB. */
+ char *path = getenv ("PATH");
+ int len;
+ struct stat statbuf;
+
+ if (path == NULL)
+ path = "/bin:/usr/bin";
+
+ tryname = alloca (strlen (path) + strlen (shell_file) + 2);
+ for (p = path; p != NULL; p = p1 ? p1 + 1: NULL)
+ {
+ p1 = strchr (p, ':');
+ if (p1 != NULL)
+ len = p1 - p;
+ else
+ len = strlen (p);
+ strncpy (tryname, p, len);
+ tryname[len] = '\0';
+ strcat (tryname, "/");
+ strcat (tryname, shell_file);
+ if (access (tryname, X_OK) < 0)
+ continue;
+ if (stat (tryname, &statbuf) < 0)
+ continue;
+ if (!S_ISREG (statbuf.st_mode))
+ /* We certainly need to reject directories. I'm not quite
+ as sure about FIFOs, sockets, etc., but I kind of doubt
+ that people want to exec() these things. */
+ continue;
+ break;
+ }
+ if (p == NULL)
+ /* Not found. This must be an error rather than merely passing
+ the file to execlp(), because execlp() would try all the
+ exec()s, causing GDB to get confused. */
+ error ("Can't find shell %s in PATH", shell_file);
+
+ shell_file = tryname;
+ }
+
+ fork_inferior (exec_file, allargs, env,
+ proc_set_exec_trap, procfs_init_inferior, NULL, shell_file);
+
+ /* We are at the first instruction we care about. */
+ /* Pedal to the metal... */
+
+ proceed ((CORE_ADDR) -1, TARGET_SIGNAL_0, 0);
+}
+
+/* Clean up after the inferior dies. */
+
+static void
+procfs_mourn_inferior ()
+{
+ struct procinfo *pi;
+ struct procinfo *next_pi;
+
+ for (pi = procinfo_list; pi; pi = next_pi)
+ {
+ next_pi = pi->next;
+ unconditionally_kill_inferior (pi);
+ }
+
+ unpush_target (&procfs_ops);
+ generic_mourn_inferior ();
+}
+
+
+/* Mark our target-struct as eligible for stray "run" and "attach" commands. */
+static int
+procfs_can_run ()
+{
+ /* This variable is controlled by modules that sit atop procfs that may layer
+ their own process structure atop that provided here. sol-thread.c does
+ this because of the Solaris two-level thread model. */
+
+ return !procfs_suppress_run;
+}
+#ifdef TARGET_HAS_HARDWARE_WATCHPOINTS
+#ifndef UNIXWARE
+
+/* Insert a watchpoint */
+int
+procfs_set_watchpoint(pid, addr, len, rw)
+ int pid;
+ CORE_ADDR addr;
+ int len;
+ int rw;
+{
+ struct procinfo *pi;
+ prwatch_t wpt;
+
+ pi = find_procinfo (pid == -1 ? inferior_pid : pid, 0);
+ wpt.pr_vaddr = (caddr_t)addr;
+ wpt.pr_size = len;
+ wpt.pr_wflags = ((rw & 1) ? MA_READ : 0) | ((rw & 2) ? MA_WRITE : 0);
+ if (ioctl (pi->ctl_fd, PIOCSWATCH, &wpt) < 0)
+ {
+ if (errno == E2BIG)
+ return -1;
+ /* Currently it sometimes happens that the same watchpoint gets
+ deleted twice - don't die in this case (FIXME please) */
+ if (errno == ESRCH && len == 0)
+ return 0;
+ print_sys_errmsg (pi->pathname, errno);
+ error ("PIOCSWATCH failed");
+ }
+ return 0;
+}
+
+int
+procfs_stopped_by_watchpoint(pid)
+ int pid;
+{
+ struct procinfo *pi;
+ short what;
+ short why;
+
+ pi = find_procinfo (pid == -1 ? inferior_pid : pid, 0);
+ if (pi->prstatus.pr_flags & (PR_STOPPED | PR_ISTOP))
+ {
+ why = pi->prstatus.pr_why;
+ what = pi->prstatus.pr_what;
+ if (why == PR_FAULTED
+#if defined (FLTWATCH) && defined (FLTKWATCH)
+ && (what == FLTWATCH || what == FLTKWATCH)
+#else
+#ifdef FLTWATCH
+ && (what == FLTWATCH)
+#endif
+#ifdef FLTKWATCH
+ && (what == FLTKWATCH)
+#endif
+#endif
+ )
+ return what;
+ }
+ return 0;
+}
+#endif /* !UNIXWARE */
+#endif /* TARGET_HAS_HARDWARE_WATCHPOINTS */
+
+/* Why is this necessary? Shouldn't dead threads just be removed from the
+ thread database? */
+
+static int
+procfs_thread_alive (pid)
+ int pid;
+{
+ struct procinfo *pi, *next_pi;
+
+ for (pi = procinfo_list; pi; pi = next_pi)
+ {
+ next_pi = pi->next;
+ if (pi -> pid == pid)
+ if (procfs_read_status (pi)) /* alive */
+ return 1;
+ else /* defunct (exited) */
+ {
+ close_proc_file (pi);
+ return 0;
+ }
+ }
+ return 0;
+}
+
+int
+procfs_first_available ()
+{
+ struct procinfo *pi;
+
+ for (pi = procinfo_list; pi; pi = pi->next)
+ {
+ if (procfs_read_status (pi))
+ return pi->pid;
+ }
+ return -1;
+}
+
+int
+procfs_get_pid_fd (pid)
+ int pid;
+{
+ struct procinfo *pi = find_procinfo (pid, 1);
+
+ if (pi == NULL)
+ return -1;
+
+ return pi->ctl_fd;
+}
+
+/* Send a SIGINT to the process group. This acts just like the user typed a
+ ^C on the controlling terminal.
+
+ XXX - This may not be correct for all systems. Some may want to use
+ killpg() instead of kill (-pgrp). */
+
+static void
+procfs_stop ()
+{
+ extern pid_t inferior_process_group;
+
+ kill (-inferior_process_group, SIGINT);
+}
+
+/* Convert a pid to printable form. */
+
+#ifdef TIDGET
+char *
+procfs_pid_to_str (pid)
+ int pid;
+{
+ static char buf[100];
+
+ sprintf (buf, "Kernel thread %d", TIDGET (pid));
+
+ return buf;
+}
+#endif /* TIDGET */
+
+
+static void
+init_procfs_ops ()
+{
+ procfs_ops.to_shortname = "procfs";
+ procfs_ops.to_longname = "Unix /proc child process";
+ procfs_ops.to_doc = "Unix /proc child process (started by the \"run\" command).";
+ procfs_ops.to_open = procfs_open;
+ procfs_ops.to_attach = procfs_attach;
+ procfs_ops.to_detach = procfs_detach;
+ procfs_ops.to_resume = procfs_resume;
+ procfs_ops.to_wait = procfs_wait;
+ procfs_ops.to_fetch_registers = procfs_fetch_registers;
+ procfs_ops.to_store_registers = procfs_store_registers;
+ procfs_ops.to_prepare_to_store = procfs_prepare_to_store;
+ procfs_ops.to_xfer_memory = procfs_xfer_memory;
+ procfs_ops.to_files_info = procfs_files_info;
+ procfs_ops.to_insert_breakpoint = memory_insert_breakpoint;
+ procfs_ops.to_remove_breakpoint = memory_remove_breakpoint;
+ procfs_ops.to_terminal_init = terminal_init_inferior;
+ procfs_ops.to_terminal_inferior = terminal_inferior;
+ procfs_ops.to_terminal_ours_for_output = terminal_ours_for_output;
+ procfs_ops.to_terminal_ours = terminal_ours;
+ procfs_ops.to_terminal_info = child_terminal_info;
+ procfs_ops.to_kill = procfs_kill_inferior;
+ procfs_ops.to_create_inferior = procfs_create_inferior;
+ procfs_ops.to_mourn_inferior = procfs_mourn_inferior;
+ procfs_ops.to_can_run = procfs_can_run;
+ procfs_ops.to_notice_signals = procfs_notice_signals;
+ procfs_ops.to_thread_alive = procfs_thread_alive;
+ procfs_ops.to_stop = procfs_stop;
+ procfs_ops.to_stratum = process_stratum;
+ procfs_ops.to_has_all_memory = 1;
+ procfs_ops.to_has_memory = 1;
+ procfs_ops.to_has_stack = 1;
+ procfs_ops.to_has_registers = 1;
+ procfs_ops.to_has_execution = 1;
+ procfs_ops.to_magic = OPS_MAGIC;
+}
+
+void
+_initialize_procfs ()
+{
+#ifdef HAVE_OPTIONAL_PROC_FS
+ char procname[MAX_PROC_NAME_SIZE];
+ int fd;
+
+ /* If we have an optional /proc filesystem (e.g. under OSF/1),
+ don't add procfs support if we cannot access the running
+ GDB via /proc. */
+ sprintf (procname, STATUS_PROC_NAME_FMT, getpid ());
+ if ((fd = open (procname, O_RDONLY)) < 0)
+ return;
+ close (fd);
+#endif
+
+ init_procfs_ops ();
+ add_target (&procfs_ops);
+
+ add_info ("processes", info_proc,
+"Show process status information using /proc entry.\n\
+Specify process id or use current inferior by default.\n\
+Specify keywords for detailed information; default is summary.\n\
+Keywords are: `all', `faults', `flags', `id', `mappings', `signals',\n\
+`status', `syscalls', and `times'.\n\
+Unambiguous abbreviations may be used.");
+
+ init_syscall_table ();
+}
diff --git a/gdb/ptx4-nat.c b/gdb/ptx4-nat.c
new file mode 100644
index 00000000000..564b7991728
--- /dev/null
+++ b/gdb/ptx4-nat.c
@@ -0,0 +1,209 @@
+/* Native-dependent code for ptx 4.0
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "inferior.h"
+#include "gdbcore.h"
+#include <sys/procfs.h>
+#include <sys/ptrace.h>
+#include <sys/param.h>
+#include <fcntl.h>
+
+/* Given a pointer to a general register set in /proc format (gregset_t *),
+ unpack the register contents and supply them as gdb's idea of the current
+ register values. */
+
+void
+supply_gregset (gregsetp)
+ gregset_t *gregsetp;
+{
+ supply_register(EAX_REGNUM, (char *)&(*gregsetp)[EAX]);
+ supply_register(EDX_REGNUM, (char *)&(*gregsetp)[EDX]);
+ supply_register(ECX_REGNUM, (char *)&(*gregsetp)[ECX]);
+ supply_register(EBX_REGNUM, (char *)&(*gregsetp)[EBX]);
+ supply_register(ESI_REGNUM, (char *)&(*gregsetp)[ESI]);
+ supply_register(EDI_REGNUM, (char *)&(*gregsetp)[EDI]);
+ supply_register(ESP_REGNUM, (char *)&(*gregsetp)[UESP]);
+ supply_register(EBP_REGNUM, (char *)&(*gregsetp)[EBP]);
+ supply_register(EIP_REGNUM, (char *)&(*gregsetp)[EIP]);
+ supply_register(EFLAGS_REGNUM, (char *)&(*gregsetp)[EFL]);
+}
+
+void
+fill_gregset (gregsetp, regno)
+ gregset_t *gregsetp;
+ int regno;
+{
+ int regi;
+ extern char registers[];
+
+ for (regi = 0 ; regi < NUM_REGS ; regi++)
+ {
+ if ((regno == -1) || (regno == regi))
+ {
+ (*gregsetp)[regi] = *(greg_t *)&registers[REGISTER_BYTE (regi)];
+ }
+ }
+}
+
+#if defined (FP0_REGNUM)
+
+/* Given a pointer to a floating point register set in /proc format
+ (fpregset_t *), unpack the register contents and supply them as gdb's
+ idea of the current floating point register values. */
+
+void
+supply_fpregset (fpregsetp)
+ fpregset_t *fpregsetp;
+{
+ supply_fpu_registers((struct fpusave *)&fpregsetp->fp_reg_set);
+ supply_fpa_registers((struct fpasave *)&fpregsetp->f_wregs);
+}
+
+/* Given a pointer to a floating point register set in /proc format
+ (fpregset_t *), update the register specified by REGNO from gdb's idea
+ of the current floating point register set. If REGNO is -1, update
+ them all. */
+
+void
+fill_fpregset (fpregsetp, regno)
+ fpregset_t *fpregsetp;
+ int regno;
+{
+ int regi;
+ char *to;
+ char *from;
+ extern char registers[];
+
+ /* FIXME: see m68k-tdep.c for an example, for the m68k. */
+}
+
+#endif /* defined (FP0_REGNUM) */
+
+/*
+ * This doesn't quite do the same thing as the procfs.c version, but give
+ * it the same name so we don't have to put an ifdef in solib.c.
+ */
+/* this could use elf_interpreter() from elfread.c */
+int
+proc_iterate_over_mappings(func)
+ int (*func) PARAMS ((int, CORE_ADDR));
+{
+ vaddr_t curseg, memptr;
+ pt_vseg_t pv;
+ int rv, cmperr;
+ sec_ptr interp_sec;
+ char *interp_content;
+ int interp_fd, funcstat;
+ unsigned int size;
+ char buf1[NBPG], buf2[NBPG];
+
+ /*
+ * The following is really vile. We can get the name of the
+ * shared library from the exec_bfd, and we can get a list of
+ * each virtual memory segment, but there is no simple way to
+ * find the mapped segment from the shared library (ala
+ * procfs's PIOCOPENMEM). As a pretty nasty kludge, we
+ * compare the virtual memory segment to the contents of the
+ * .interp file. If they match, we assume that we've got the
+ * right one.
+ */
+
+ /*
+ * TODO: for attach, use XPT_OPENT to get the executable, in
+ * case we're attached without knowning the executable's
+ * filename.
+ */
+
+#ifdef VERBOSE_DEBUG
+ printf("proc_iter\n");
+#endif
+ interp_sec = bfd_get_section_by_name(exec_bfd, ".interp");
+ if (!interp_sec) {
+ return 0;
+ }
+
+ size = bfd_section_size(exec_bfd, interp_sec);
+ interp_content = alloca(size);
+ if (0 == bfd_get_section_contents(exec_bfd, interp_sec,
+ interp_content, (file_ptr)0, size)) {
+ return 0;
+ }
+
+#ifdef VERBOSE_DEBUG
+ printf("proc_iter: \"%s\"\n", interp_content);
+#endif
+ interp_fd = open(interp_content, O_RDONLY, 0);
+ if (-1 == interp_fd) {
+ return 0;
+ }
+
+ curseg = 0;
+ while (1) {
+ rv = ptrace(PT_NEXT_VSEG, inferior_pid, &pv, curseg);
+#ifdef VERBOSE_DEBUG
+ printf("PT_NEXT_VSEG: rv %d errno %d\n", rv, errno);
+#endif
+ if (-1 == rv)
+ break;
+ if (0 == rv)
+ break;
+#ifdef VERBOSE_DEBUG
+ printf("pv.pv_start 0x%x pv_size 0x%x pv_prot 0x%x\n",
+ pv.pv_start, pv.pv_size, pv.pv_prot);
+#endif
+ curseg = pv.pv_start + pv.pv_size;
+
+ rv = lseek(interp_fd, 0, SEEK_SET);
+ if (-1 == rv) {
+ perror("lseek");
+ close(interp_fd);
+ return 0;
+ }
+ for (memptr = pv.pv_start; memptr < pv.pv_start + pv.pv_size;
+ memptr += NBPG) {
+#ifdef VERBOSE_DEBUG
+ printf("memptr 0x%x\n", memptr);
+#endif
+ rv = read(interp_fd, buf1, NBPG);
+ if (-1 == rv) {
+ perror("read");
+ close(interp_fd);
+ return 0;
+ }
+ rv = ptrace(PT_RDATA_PAGE, inferior_pid, buf2,
+ memptr);
+ if (-1 == rv) {
+ perror("ptrace");
+ close(interp_fd);
+ return 0;
+ }
+ cmperr = memcmp(buf1, buf2, NBPG);
+ if (cmperr)
+ break;
+ }
+ if (0 == cmperr) {
+ /* this is it */
+ funcstat = (*func)(interp_fd, pv.pv_start);
+ break;
+ }
+ }
+ close(interp_fd);
+ return 0;
+}
diff --git a/gdb/pyr-tdep.c b/gdb/pyr-tdep.c
new file mode 100644
index 00000000000..85e9a072f3c
--- /dev/null
+++ b/gdb/pyr-tdep.c
@@ -0,0 +1,452 @@
+/* Pyramid target-dependent code for GDB.
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+
+/*** Prettier register printing. ***/
+
+/* Print registers in the same format as pyramid's dbx, adb, sdb. */
+pyr_print_registers(reg_buf, regnum)
+ long *reg_buf[];
+{
+ register int regno;
+ int usp, ksp;
+ struct user u;
+
+ for (regno = 0; regno < 16; regno++) {
+ printf_unfiltered/*_filtered*/ ("%6.6s: %8x %6.6s: %8x %6s: %8x %6s: %8x\n",
+ REGISTER_NAME (regno), reg_buf[regno],
+ REGISTER_NAME (regno+16), reg_buf[regno+16],
+ REGISTER_NAME (regno+32), reg_buf[regno+32],
+ REGISTER_NAME (regno+48), reg_buf[regno+48]);
+ }
+ usp = ptrace (3, inferior_pid,
+ (PTRACE_ARG3_TYPE) ((char *)&u.u_pcb.pcb_usp) -
+ ((char *)&u), 0);
+ ksp = ptrace (3, inferior_pid,
+ (PTRACE_ARG3_TYPE) ((char *)&u.u_pcb.pcb_ksp) -
+ ((char *)&u), 0);
+ printf_unfiltered/*_filtered*/ ("\n%6.6s: %8x %6.6s: %8x (%08x) %6.6s %8x\n",
+ REGISTER_NAME (CSP_REGNUM),reg_buf[CSP_REGNUM],
+ REGISTER_NAME (KSP_REGNUM), reg_buf[KSP_REGNUM], ksp,
+ "usp", usp);
+}
+
+/* Print the register regnum, or all registers if regnum is -1.
+ fpregs is currently ignored. */
+
+pyr_do_registers_info (regnum, fpregs)
+ int regnum;
+ int fpregs;
+{
+ /* On a pyr, we know a virtual register can always fit in an long.
+ Here (and elsewhere) we take advantage of that. Yuk. */
+ long raw_regs[MAX_REGISTER_RAW_SIZE*NUM_REGS];
+ register int i;
+
+ for (i = 0 ; i < 64 ; i++) {
+ read_relative_register_raw_bytes(i, raw_regs+i);
+ }
+ if (regnum == -1)
+ pyr_print_registers (raw_regs, regnum);
+ else
+ for (i = 0; i < NUM_REGS; i++)
+ if (i == regnum) {
+ long val = raw_regs[i];
+
+ fputs_filtered (REGISTER_NAME (i), gdb_stdout);
+ printf_filtered(":");
+ print_spaces_filtered (6 - strlen (REGISTER_NAME (i)), gdb_stdout);
+ if (val == 0)
+ printf_filtered ("0");
+ else
+ printf_filtered ("%s %d", local_hex_string_custom(val,"08"), val);
+ printf_filtered("\n");
+ }
+}
+
+/*** Debugging editions of various macros from m-pyr.h ****/
+
+CORE_ADDR frame_locals_address (frame)
+ struct frame_info *frame;
+{
+ register int addr = find_saved_register (frame,CFP_REGNUM);
+ register int result = read_memory_integer (addr, 4);
+#ifdef PYRAMID_CONTROL_FRAME_DEBUGGING
+ fprintf_unfiltered (gdb_stderr,
+ "\t[[..frame_locals:%8x, %s= %x @%x fcfp= %x foo= %x\n\t gr13=%x pr13=%x tr13=%x @%x]]\n",
+ frame->frame,
+ REGISTER_NAME (CFP_REGNUM),
+ result, addr,
+ frame->frame_cfp, (CFP_REGNUM),
+
+
+ read_register(13), read_register(29), read_register(61),
+ find_saved_register(frame, 61));
+#endif /* PYRAMID_CONTROL_FRAME_DEBUGGING */
+
+ /* FIXME: I thought read_register (CFP_REGNUM) should be the right answer;
+ or at least CFP_REGNUM relative to FRAME (ie, result).
+ There seems to be a bug in the way the innermost frame is set up. */
+
+ return ((frame->next) ? result: frame->frame_cfp);
+}
+
+CORE_ADDR frame_args_addr (frame)
+ struct frame_info *frame;
+{
+ register int addr = find_saved_register (frame,CFP_REGNUM);
+ register int result = read_memory_integer (addr, 4);
+
+#ifdef PYRAMID_CONTROL_FRAME_DEBUGGING
+ fprintf_unfiltered (gdb_stderr,
+ "\t[[..frame_args:%8x, %s= %x @%x fcfp= %x r_r= %x\n\t gr13=%x pr13=%x tr13=%x @%x]]\n",
+ frame->frame,
+ REGISTER_NAME (CFP_REGNUM),
+ result, addr,
+ frame->frame_cfp, read_register(CFP_REGNUM),
+
+ read_register(13), read_register(29), read_register(61),
+ find_saved_register(frame, 61));
+#endif /* PYRAMID_CONTROL_FRAME_DEBUGGING */
+
+ /* FIXME: I thought read_register (CFP_REGNUM) should be the right answer;
+ or at least CFP_REGNUM relative to FRAME (ie, result).
+ There seems to be a bug in the way the innermost frame is set up. */
+ return ((frame->next) ? result: frame->frame_cfp);
+}
+
+#include "symtab.h"
+#include "opcode/pyr.h"
+#include "gdbcore.h"
+
+
+/* A couple of functions used for debugging frame-handling on
+ Pyramids. (The Pyramid-dependent handling of register values for
+ windowed registers is known to be buggy.)
+
+ When debugging, these functions can supplant the normal definitions of some
+ of the macros in tm-pyramid.h The quantity of information produced
+ when these functions are used makes the gdb unusable as a
+ debugger for user programs. */
+
+extern unsigned pyr_saved_pc(), pyr_frame_chain();
+
+CORE_ADDR pyr_frame_chain(frame)
+ CORE_ADDR frame;
+{
+ int foo=frame - CONTROL_STACK_FRAME_SIZE;
+ /* printf_unfiltered ("...following chain from %x: got %x\n", frame, foo);*/
+ return foo;
+}
+
+CORE_ADDR pyr_saved_pc(frame)
+ CORE_ADDR frame;
+{
+ int foo=0;
+ foo = read_memory_integer (((CORE_ADDR)(frame))+60, 4);
+ printf_unfiltered ("..reading pc from frame 0x%0x+%d regs: got %0x\n",
+ frame, 60/4, foo);
+ return foo;
+}
+
+/* Pyramid instructions are never longer than this many bytes. */
+#define MAXLEN 24
+
+/* Number of elements in the opcode table. */
+/*const*/ static int nopcodes = (sizeof (pyr_opcodes) / sizeof( pyr_opcodes[0]));
+#define NOPCODES (nopcodes)
+
+/* Let's be byte-independent so we can use this as a cross-assembler. */
+
+#define NEXTLONG(p) \
+ (p += 4, (((((p[-4] << 8) + p[-3]) << 8) + p[-2]) << 8) + p[-1])
+
+/* Print one instruction at address MEMADDR in debugged memory,
+ on STREAM. Returns length of the instruction, in bytes. */
+
+int
+pyr_print_insn (memaddr, stream)
+ CORE_ADDR memaddr;
+ GDB_FILE *stream;
+{
+ unsigned char buffer[MAXLEN];
+ register int i, nargs, insn_size =4;
+ register unsigned char *p;
+ register char *d;
+ register int insn_opcode, operand_mode;
+ register int index_multiplier, index_reg_regno, op_1_regno, op_2_regno ;
+ long insn; /* first word of the insn, not broken down. */
+ pyr_insn_format insn_decode; /* the same, broken out into op{code,erands} */
+ long extra_1, extra_2;
+
+ read_memory (memaddr, buffer, MAXLEN);
+ insn_decode = *((pyr_insn_format *) buffer);
+ insn = * ((int *) buffer);
+ insn_opcode = insn_decode.operator;
+ operand_mode = insn_decode.mode;
+ index_multiplier = insn_decode.index_scale;
+ index_reg_regno = insn_decode.index_reg;
+ op_1_regno = insn_decode.operand_1;
+ op_2_regno = insn_decode.operand_2;
+
+
+ if (*((int *)buffer) == 0x0) {
+ /* "halt" looks just like an invalid "jump" to the insn decoder,
+ so is dealt with as a special case */
+ fprintf_unfiltered (stream, "halt");
+ return (4);
+ }
+
+ for (i = 0; i < NOPCODES; i++)
+ if (pyr_opcodes[i].datum.code == insn_opcode)
+ break;
+
+ if (i == NOPCODES)
+ /* FIXME: Handle unrecognised instructions better. */
+ fprintf_unfiltered (stream, "???\t#%08x\t(op=%x mode =%x)",
+ insn, insn_decode.operator, insn_decode.mode);
+ else
+ {
+ /* Print the mnemonic for the instruction. Pyramid insn operands
+ are so regular that we can deal with almost all of them
+ separately.
+ Unconditional branches are an exception: they are encoded as
+ conditional branches (branch if false condition, I think)
+ with no condition specified. The average user will not be
+ aware of this. To maintain their illusion that an
+ unconditional branch insn exists, we will have to FIXME to
+ treat the insn mnemnonic of all branch instructions here as a
+ special case: check the operands of branch insn and print an
+ appropriate mnemonic. */
+
+ fprintf_unfiltered (stream, "%s\t", pyr_opcodes[i].name);
+
+ /* Print the operands of the insn (as specified in
+ insn.operand_mode).
+ Branch operands of branches are a special case: they are a word
+ offset, not a byte offset. */
+
+ if (insn_decode.operator == 0x01 || insn_decode.operator == 0x02) {
+ register int bit_codes=(insn >> 16)&0xf;
+ register int i;
+ register int displacement = (insn & 0x0000ffff) << 2;
+
+ static char cc_bit_names[] = "cvzn"; /* z,n,c,v: strange order? */
+
+ /* Is bfc and no bits specified an unconditional branch?*/
+ for (i=0;i<4;i++) {
+ if ((bit_codes) & 0x1)
+ fputc_unfiltered (cc_bit_names[i], stream);
+ bit_codes >>= 1;
+ }
+
+ fprintf_unfiltered (stream, ",%0x",
+ displacement + memaddr);
+ return (insn_size);
+ }
+
+ switch (operand_mode) {
+ case 0:
+ fprintf_unfiltered (stream, "%s,%s",
+ REGISTER_NAME (op_1_regno),
+ REGISTER_NAME (op_2_regno));
+ break;
+
+ case 1:
+ fprintf_unfiltered (stream, " 0x%0x,%s",
+ op_1_regno,
+ REGISTER_NAME (op_2_regno));
+ break;
+
+ case 2:
+ read_memory (memaddr+4, buffer, MAXLEN);
+ insn_size += 4;
+ extra_1 = * ((int *) buffer);
+ fprintf_unfiltered (stream, " $0x%0x,%s",
+ extra_1,
+ REGISTER_NAME (op_2_regno));
+ break;
+ case 3:
+ fprintf_unfiltered (stream, " (%s),%s",
+ REGISTER_NAME (op_1_regno),
+ REGISTER_NAME (op_2_regno));
+ break;
+
+ case 4:
+ read_memory (memaddr+4, buffer, MAXLEN);
+ insn_size += 4;
+ extra_1 = * ((int *) buffer);
+ fprintf_unfiltered (stream, " 0x%0x(%s),%s",
+ extra_1,
+ REGISTER_NAME (op_1_regno),
+ REGISTER_NAME (op_2_regno));
+ break;
+
+ /* S1 destination mode */
+ case 5:
+ fprintf_unfiltered (stream,
+ ((index_reg_regno) ? "%s,(%s)[%s*%1d]" : "%s,(%s)"),
+ REGISTER_NAME (op_1_regno),
+ REGISTER_NAME (op_2_regno),
+ REGISTER_NAME (index_reg_regno),
+ index_multiplier);
+ break;
+
+ case 6:
+ fprintf_unfiltered (stream,
+ ((index_reg_regno) ? " $%#0x,(%s)[%s*%1d]"
+ : " $%#0x,(%s)"),
+ op_1_regno,
+ REGISTER_NAME (op_2_regno),
+ REGISTER_NAME (index_reg_regno),
+ index_multiplier);
+ break;
+
+ case 7:
+ read_memory (memaddr+4, buffer, MAXLEN);
+ insn_size += 4;
+ extra_1 = * ((int *) buffer);
+ fprintf_unfiltered (stream,
+ ((index_reg_regno) ? " $%#0x,(%s)[%s*%1d]"
+ : " $%#0x,(%s)"),
+ extra_1,
+ REGISTER_NAME (op_2_regno),
+ REGISTER_NAME (index_reg_regno),
+ index_multiplier);
+ break;
+
+ case 8:
+ fprintf_unfiltered (stream,
+ ((index_reg_regno) ? " (%s),(%s)[%s*%1d]" : " (%s),(%s)"),
+ REGISTER_NAME (op_1_regno),
+ REGISTER_NAME (op_2_regno),
+ REGISTER_NAME (index_reg_regno),
+ index_multiplier);
+ break;
+
+ case 9:
+ read_memory (memaddr+4, buffer, MAXLEN);
+ insn_size += 4;
+ extra_1 = * ((int *) buffer);
+ fprintf_unfiltered (stream,
+ ((index_reg_regno)
+ ? "%#0x(%s),(%s)[%s*%1d]"
+ : "%#0x(%s),(%s)"),
+ extra_1,
+ REGISTER_NAME (op_1_regno),
+ REGISTER_NAME (op_2_regno),
+ REGISTER_NAME (index_reg_regno),
+ index_multiplier);
+ break;
+
+ /* S2 destination mode */
+ case 10:
+ read_memory (memaddr+4, buffer, MAXLEN);
+ insn_size += 4;
+ extra_1 = * ((int *) buffer);
+ fprintf_unfiltered (stream,
+ ((index_reg_regno) ? "%s,%#0x(%s)[%s*%1d]" : "%s,%#0x(%s)"),
+ REGISTER_NAME (op_1_regno),
+ extra_1,
+ REGISTER_NAME (op_2_regno),
+ REGISTER_NAME (index_reg_regno),
+ index_multiplier);
+ break;
+ case 11:
+ read_memory (memaddr+4, buffer, MAXLEN);
+ insn_size += 4;
+ extra_1 = * ((int *) buffer);
+ fprintf_unfiltered (stream,
+ ((index_reg_regno) ?
+ " $%#0x,%#0x(%s)[%s*%1d]" : " $%#0x,%#0x(%s)"),
+ op_1_regno,
+ extra_1,
+ REGISTER_NAME (op_2_regno),
+ REGISTER_NAME (index_reg_regno),
+ index_multiplier);
+ break;
+ case 12:
+ read_memory (memaddr+4, buffer, MAXLEN);
+ insn_size += 4;
+ extra_1 = * ((int *) buffer);
+ read_memory (memaddr+8, buffer, MAXLEN);
+ insn_size += 4;
+ extra_2 = * ((int *) buffer);
+ fprintf_unfiltered (stream,
+ ((index_reg_regno) ?
+ " $%#0x,%#0x(%s)[%s*%1d]" : " $%#0x,%#0x(%s)"),
+ extra_1,
+ extra_2,
+ REGISTER_NAME (op_2_regno),
+ REGISTER_NAME (index_reg_regno),
+ index_multiplier);
+ break;
+
+ case 13:
+ read_memory (memaddr+4, buffer, MAXLEN);
+ insn_size += 4;
+ extra_1 = * ((int *) buffer);
+ fprintf_unfiltered (stream,
+ ((index_reg_regno)
+ ? " (%s),%#0x(%s)[%s*%1d]"
+ : " (%s),%#0x(%s)"),
+ REGISTER_NAME (op_1_regno),
+ extra_1,
+ REGISTER_NAME (op_2_regno),
+ REGISTER_NAME (index_reg_regno),
+ index_multiplier);
+ break;
+ case 14:
+ read_memory (memaddr+4, buffer, MAXLEN);
+ insn_size += 4;
+ extra_1 = * ((int *) buffer);
+ read_memory (memaddr+8, buffer, MAXLEN);
+ insn_size += 4;
+ extra_2 = * ((int *) buffer);
+ fprintf_unfiltered (stream,
+ ((index_reg_regno) ? "%#0x(%s),%#0x(%s)[%s*%1d]"
+ : "%#0x(%s),%#0x(%s) "),
+ extra_1,
+ REGISTER_NAME (op_1_regno),
+ extra_2,
+ REGISTER_NAME (op_2_regno),
+ REGISTER_NAME (index_reg_regno),
+ index_multiplier);
+ break;
+
+ default:
+ fprintf_unfiltered (stream,
+ ((index_reg_regno) ? "%s,%s [%s*%1d]" : "%s,%s"),
+ REGISTER_NAME (op_1_regno),
+ REGISTER_NAME (op_2_regno),
+ REGISTER_NAME (index_reg_regno),
+ index_multiplier);
+ fprintf_unfiltered (stream,
+ "\t\t# unknown mode in %08x",
+ insn);
+ break;
+ } /* switch */
+ }
+
+ {
+ return insn_size;
+ }
+ abort ();
+}
diff --git a/gdb/pyr-xdep.c b/gdb/pyr-xdep.c
new file mode 100644
index 00000000000..dd6d9a92400
--- /dev/null
+++ b/gdb/pyr-xdep.c
@@ -0,0 +1,370 @@
+/* Low level Pyramid interface to ptrace, for GDB when running under Unix.
+ Copyright (C) 1988, 1989, 1991 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "frame.h"
+#include "inferior.h"
+
+#include <sys/param.h>
+#include <sys/dir.h>
+#include <signal.h>
+#include <sys/ioctl.h>
+/* #include <fcntl.h> Can we live without this? */
+
+#include "gdbcore.h"
+#include <sys/user.h> /* After a.out.h */
+#include <sys/file.h>
+#include "gdb_stat.h"
+
+
+void
+fetch_inferior_registers (regno)
+ int regno;
+{
+ register int datum;
+ register unsigned int regaddr;
+ int reg_buf[NUM_REGS+1];
+ struct user u;
+ register int skipped_frames = 0;
+
+ registers_fetched ();
+
+ for (regno = 0; regno < 64; regno++) {
+ reg_buf[regno] = ptrace (3, inferior_pid, (PTRACE_ARG3_TYPE) regno, 0);
+
+#if defined(PYRAMID_CONTROL_FRAME_DEBUGGING)
+ printf_unfiltered ("Fetching register %s, got %0x\n",
+ REGISTER_NAME (regno),
+ reg_buf[regno]);
+#endif /* PYRAMID_CONTROL_FRAME_DEBUGGING */
+
+ if (reg_buf[regno] == -1 && errno == EIO) {
+ printf_unfiltered("fetch_interior_registers: fetching register %s\n",
+ REGISTER_NAME (regno));
+ errno = 0;
+ }
+ supply_register (regno, reg_buf+regno);
+ }
+ /* that leaves regs 64, 65, and 66 */
+ datum = ptrace (3, inferior_pid,
+ (PTRACE_ARG3_TYPE) (((char *)&u.u_pcb.pcb_csp) -
+ ((char *)&u)), 0);
+
+
+
+ /* FIXME: Find the Current Frame Pointer (CFP). CFP is a global
+ register (ie, NOT windowed), that gets saved in a frame iff
+ the code for that frame has a prologue (ie, "adsf N"). If
+ there is a prologue, the adsf insn saves the old cfp in
+ pr13, cfp is set to sp, and N bytes of locals are allocated
+ (sp is decremented by n).
+ This makes finding CFP hard. I guess the right way to do it
+ is:
+ - If this is the innermost frame, believe ptrace() or
+ the core area.
+ - Otherwise:
+ Find the first insn of the current frame.
+ - find the saved pc;
+ - find the call insn that saved it;
+ - figure out where the call is to;
+ - if the first insn is an adsf, we got a frame
+ pointer. */
+
+
+ /* Normal processors have separate stack pointers for user and
+ kernel mode. Getting the last user mode frame on such
+ machines is easy: the kernel context of the ptrace()'d
+ process is on the kernel stack, and the USP points to what
+ we want. But Pyramids only have a single cfp for both user and
+ kernel mode. And processes being ptrace()'d have some
+ kernel-context control frames on their stack.
+ To avoid tracing back into the kernel context of an inferior,
+ we skip 0 or more contiguous control frames where the pc is
+ in the kernel. */
+
+ while (1) {
+ register int inferior_saved_pc;
+ inferior_saved_pc = ptrace (1, inferior_pid,
+ (PTRACE_ARG3_TYPE) (datum+((32+15)*4)), 0);
+ if (inferior_saved_pc > 0) break;
+#if defined(PYRAMID_CONTROL_FRAME_DEBUGGING)
+ printf_unfiltered("skipping kernel frame %08x, pc=%08x\n", datum,
+ inferior_saved_pc);
+#endif /* PYRAMID_CONTROL_FRAME_DEBUGGING */
+ skipped_frames++;
+ datum -= CONTROL_STACK_FRAME_SIZE;
+ }
+
+ reg_buf[CSP_REGNUM] = datum;
+ supply_register(CSP_REGNUM, reg_buf+CSP_REGNUM);
+#ifdef PYRAMID_CONTROL_FRAME_DEBUGGING
+ if (skipped_frames) {
+ fprintf_unfiltered (gdb_stderr,
+ "skipped %d frames from %x to %x; cfp was %x, now %x\n",
+ skipped_frames, reg_buf[CSP_REGNUM]);
+ }
+#endif /* PYRAMID_CONTROL_FRAME_DEBUGGING */
+}
+
+/* Store our register values back into the inferior.
+ If REGNO is -1, do this for all registers.
+ Otherwise, REGNO specifies which register (so we can save time). */
+
+void
+store_inferior_registers (regno)
+ int regno;
+{
+ register unsigned int regaddr;
+ char buf[80];
+
+ if (regno >= 0)
+ {
+ if ((0 <= regno) && (regno < 64)) {
+ /*regaddr = register_addr (regno, offset);*/
+ regaddr = regno;
+ errno = 0;
+ ptrace (6, inferior_pid, (PTRACE_ARG3_TYPE) regaddr,
+ read_register (regno));
+ if (errno != 0)
+ {
+ sprintf (buf, "writing register number %d", regno);
+ perror_with_name (buf);
+ }
+ }
+ }
+ else
+ {
+ for (regno = 0; regno < NUM_REGS; regno++)
+ {
+ /*regaddr = register_addr (regno, offset);*/
+ regaddr = regno;
+ errno = 0;
+ ptrace (6, inferior_pid, (PTRACE_ARG3_TYPE) regaddr,
+ read_register (regno));
+ if (errno != 0)
+ {
+ sprintf (buf, "writing all regs, number %d", regno);
+ perror_with_name (buf);
+ }
+ }
+}
+
+/*** Extensions to core and dump files, for GDB. */
+
+extern unsigned int last_frame_offset;
+
+#ifdef PYRAMID_CORE
+
+/* Can't make definitions here static, since corefile.c needs them
+ to do bounds checking on the core-file areas. O well. */
+
+/* have two stacks: one for data, one for register windows. */
+extern CORE_ADDR reg_stack_start;
+extern CORE_ADDR reg_stack_end;
+
+/* need this so we can find the global registers: they never get saved. */
+CORE_ADDR global_reg_offset;
+static CORE_ADDR last_frame_address;
+CORE_ADDR last_frame_offset;
+
+
+/* Address in core file of start of register window stack area.
+ Don't know if is this any of meaningful, useful or necessary. */
+extern int reg_stack_offset;
+
+#endif /* PYRAMID_CORE */
+
+
+/* Work with core dump and executable files, for GDB.
+ This code would be in corefile.c if it weren't machine-dependent. */
+
+void
+core_file_command (filename, from_tty)
+ char *filename;
+ int from_tty;
+{
+ int val;
+ extern char registers[];
+
+ /* Discard all vestiges of any previous core file
+ and mark data and stack spaces as empty. */
+
+ if (corefile)
+ free (corefile);
+ corefile = 0;
+
+ if (corechan >= 0)
+ close (corechan);
+ corechan = -1;
+
+ data_start = 0;
+ data_end = 0;
+ stack_start = STACK_END_ADDR;
+ stack_end = STACK_END_ADDR;
+
+#ifdef PYRAMID_CORE
+ reg_stack_start = CONTROL_STACK_ADDR;
+ reg_stack_end = CONTROL_STACK_ADDR; /* this isn't strictly true...*/
+#endif /* PYRAMID_CORE */
+
+ /* Now, if a new core file was specified, open it and digest it. */
+
+ if (filename)
+ {
+ filename = tilde_expand (filename);
+ make_cleanup (free, filename);
+
+ if (have_inferior_p ())
+ error ("To look at a core file, you must kill the program with \"kill\".");
+ corechan = open (filename, O_RDONLY, 0);
+ if (corechan < 0)
+ perror_with_name (filename);
+ /* 4.2-style (and perhaps also sysV-style) core dump file. */
+ {
+ struct user u;
+
+ unsigned int reg_offset;
+
+ val = myread (corechan, &u, sizeof u);
+ if (val < 0)
+ perror_with_name ("Not a core file: reading upage");
+ if (val != sizeof u)
+ error ("Not a core file: could only read %d bytes", val);
+ data_start = exec_data_start;
+
+ data_end = data_start + NBPG * u.u_dsize;
+ data_offset = NBPG * UPAGES;
+ stack_offset = NBPG * (UPAGES + u.u_dsize);
+
+ /* find registers in core file */
+#ifdef PYRAMID_PTRACE
+ stack_start = stack_end - NBPG * u.u_ussize;
+ reg_stack_offset = stack_offset + (NBPG *u.u_ussize);
+ reg_stack_end = reg_stack_start + NBPG * u.u_cssize;
+
+ last_frame_address = ((int) u.u_pcb.pcb_csp);
+ last_frame_offset = reg_stack_offset + last_frame_address
+ - CONTROL_STACK_ADDR ;
+ global_reg_offset = (char *)&u - (char *)&u.u_pcb.pcb_gr0 ;
+
+ /* skip any control-stack frames that were executed in the
+ kernel. */
+
+ while (1) {
+ char buf[4];
+ val = lseek (corechan, last_frame_offset+(47*4), 0);
+ if (val < 0)
+ perror_with_name (filename);
+ val = myread (corechan, buf, sizeof buf);
+ if (val < 0)
+ perror_with_name (filename);
+
+ if (*(int *)buf >= 0)
+ break;
+ printf_unfiltered ("skipping frame %s\n", local_hex_string (last_frame_address));
+ last_frame_offset -= CONTROL_STACK_FRAME_SIZE;
+ last_frame_address -= CONTROL_STACK_FRAME_SIZE;
+ }
+ reg_offset = last_frame_offset;
+
+#if 1 || defined(PYRAMID_CONTROL_FRAME_DEBUGGING)
+ printf_unfiltered ("Control stack pointer = %s\n",
+ local_hex_string (u.u_pcb.pcb_csp));
+ printf_unfiltered ("offset to control stack %d outermost frame %d (%s)\n",
+ reg_stack_offset, reg_offset, local_hex_string (last_frame_address));
+#endif /* PYRAMID_CONTROL_FRAME_DEBUGGING */
+
+#else /* not PYRAMID_CORE */
+ stack_start = stack_end - NBPG * u.u_ssize;
+ reg_offset = (int) u.u_ar0 - KERNEL_U_ADDR;
+#endif /* not PYRAMID_CORE */
+
+#ifdef __not_on_pyr_yet
+ /* Some machines put an absolute address in here and some put
+ the offset in the upage of the regs. */
+ reg_offset = (int) u.u_ar0;
+ if (reg_offset > NBPG * UPAGES)
+ reg_offset -= KERNEL_U_ADDR;
+#endif
+
+ /* I don't know where to find this info.
+ So, for now, mark it as not available. */
+ N_SET_MAGIC (core_aouthdr, 0);
+
+ /* Read the register values out of the core file and store
+ them where `read_register' will find them. */
+
+ {
+ register int regno;
+
+ for (regno = 0; regno < 64; regno++)
+ {
+ char buf[MAX_REGISTER_RAW_SIZE];
+
+ val = lseek (corechan, register_addr (regno, reg_offset), 0);
+ if (val < 0
+ || (val = myread (corechan, buf, sizeof buf)) < 0)
+ {
+ char * buffer = (char *) alloca (strlen (REGISTER_NAME (regno))
+ + 30);
+ strcpy (buffer, "Reading register ");
+ strcat (buffer, REGISTER_NAME (regno));
+
+ perror_with_name (buffer);
+ }
+
+ if (val < 0)
+ perror_with_name (filename);
+#ifdef PYRAMID_CONTROL_FRAME_DEBUGGING
+ printf_unfiltered ("[reg %s(%d), offset in file %s=0x%0x, addr =0x%0x, =%0x]\n",
+ REGISTER_NAME (regno), regno, filename,
+ register_addr(regno, reg_offset),
+ regno * 4 + last_frame_address,
+ *((int *)buf));
+#endif /* PYRAMID_CONTROL_FRAME_DEBUGGING */
+ supply_register (regno, buf);
+ }
+ }
+ }
+ if (filename[0] == '/')
+ corefile = savestring (filename, strlen (filename));
+ else
+ {
+ corefile = concat (current_directory, "/", filename, NULL);
+ }
+
+#if 1 || defined(PYRAMID_CONTROL_FRAME_DEBUGGING)
+ printf_unfiltered ("Providing CSP (%s) as nominal address of current frame.\n",
+ local_hex_string(last_frame_address));
+#endif PYRAMID_CONTROL_FRAME_DEBUGGING
+ /* FIXME: Which of the following is correct? */
+#if 0
+ set_current_frame ( create_new_frame (read_register (FP_REGNUM),
+ read_pc ()));
+#else
+ set_current_frame ( create_new_frame (last_frame_address,
+ read_pc ()));
+#endif
+
+ select_frame (get_current_frame (), 0);
+ validate_files ();
+ }
+ else if (from_tty)
+ printf_unfiltered ("No core file now.\n");
+}
diff --git a/gdb/rdi-share/Makefile.am b/gdb/rdi-share/Makefile.am
new file mode 100644
index 00000000000..9d63d1c6486
--- /dev/null
+++ b/gdb/rdi-share/Makefile.am
@@ -0,0 +1,19 @@
+## Process this file with automake to generate Makefile.in
+
+AUTOMAKE_OPTIONS = cygnus
+
+noinst_LIBRARIES = libangsd.a
+
+libangsd_a_SOURCES = ardi.c bytesex.c crc.c devsw.c drivers.c etherdrv.c \
+ hostchan.c hsys.c logging.c msgbuild.c params.c rx.c \
+ serdrv.c serpardr.c tx.c unixcomm.c
+
+noinst_HEADERS = adp.h adperr.h angel.h ardi.h armdbg.h buffers.h bytesex.h \
+ chandefs.h channels.h chanpriv.h crc.h dbg_conf.h dbg_cp.h \
+ dbg_hif.h dbg_rdi.h devclnt.h devices.h devsw.h drivers.h \
+ endian.h ethernet.h host.h hostchan.h hsys.h logging.h \
+ msgbuild.h params.h rxtx.h sys.h unixcomm.h
+
+EXTRA_DIST = README.CYGNUS
+
+INCLUDES = -DRETRANS -DARM_RELEASE='"Berkeley Licence for Cygnus"'
diff --git a/gdb/rdi-share/Makefile.in b/gdb/rdi-share/Makefile.in
new file mode 100644
index 00000000000..11410058a67
--- /dev/null
+++ b/gdb/rdi-share/Makefile.in
@@ -0,0 +1,293 @@
+# Makefile.in generated automatically by automake 1.3b from Makefile.am
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+
+SHELL = @SHELL@
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+bindir = @bindir@
+sbindir = @sbindir@
+libexecdir = @libexecdir@
+datadir = @datadir@
+sysconfdir = @sysconfdir@
+sharedstatedir = @sharedstatedir@
+localstatedir = @localstatedir@
+libdir = @libdir@
+infodir = @infodir@
+mandir = @mandir@
+includedir = @includedir@
+oldincludedir = /usr/include
+
+DESTDIR =
+
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+
+top_builddir = .
+
+ACLOCAL = @ACLOCAL@
+AUTOCONF = @AUTOCONF@
+AUTOMAKE = @AUTOMAKE@
+AUTOHEADER = @AUTOHEADER@
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+transform = @program_transform_name@
+
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+CC = @CC@
+EXEEXT = @EXEEXT@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+PACKAGE = @PACKAGE@
+RANLIB = @RANLIB@
+VERSION = @VERSION@
+
+AUTOMAKE_OPTIONS = cygnus
+
+noinst_LIBRARIES = libangsd.a
+
+libangsd_a_SOURCES = ardi.c bytesex.c crc.c devsw.c drivers.c etherdrv.c \
+ hostchan.c hsys.c logging.c msgbuild.c params.c rx.c \
+ serdrv.c serpardr.c tx.c unixcomm.c
+
+noinst_HEADERS = adp.h adperr.h angel.h ardi.h armdbg.h buffers.h bytesex.h \
+ chandefs.h channels.h chanpriv.h crc.h dbg_conf.h dbg_cp.h \
+ dbg_hif.h dbg_rdi.h devclnt.h devices.h devsw.h drivers.h \
+ endian.h ethernet.h host.h hostchan.h hsys.h logging.h \
+ msgbuild.h params.h rxtx.h sys.h unixcomm.h
+
+EXTRA_DIST = README.CYGNUS
+
+INCLUDES = -DRETRANS -DARM_RELEASE='"Berkeley Licence for Cygnus"'
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+mkinstalldirs = $(SHELL) $(top_srcdir)/../../mkinstalldirs
+CONFIG_CLEAN_FILES =
+LIBRARIES = $(noinst_LIBRARIES)
+
+
+DEFS = @DEFS@ -I. -I$(srcdir)
+CPPFLAGS = @CPPFLAGS@
+LDFLAGS = @LDFLAGS@
+LIBS = @LIBS@
+libangsd_a_LIBADD =
+libangsd_a_OBJECTS = ardi.o bytesex.o crc.o devsw.o drivers.o \
+etherdrv.o hostchan.o hsys.o logging.o msgbuild.o params.o rx.o \
+serdrv.o serpardr.o tx.o unixcomm.o
+AR = ar
+CFLAGS = @CFLAGS@
+COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LINK = $(CC) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@
+HEADERS = $(noinst_HEADERS)
+
+DIST_COMMON = Makefile.am Makefile.in aclocal.m4 configure configure.in
+
+
+DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
+
+TAR = tar
+GZIP = --best
+SOURCES = $(libangsd_a_SOURCES)
+OBJECTS = $(libangsd_a_OBJECTS)
+
+all: Makefile $(LIBRARIES) $(HEADERS)
+
+.SUFFIXES:
+.SUFFIXES: .S .c .o .s
+$(srcdir)/Makefile.in: @MAINT@Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
+ cd $(top_srcdir) && $(AUTOMAKE) --cygnus Makefile
+
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ cd $(top_builddir) \
+ && CONFIG_FILES=$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+$(ACLOCAL_M4): @MAINT@ configure.in
+ cd $(srcdir) && $(ACLOCAL)
+
+config.status: $(srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ $(SHELL) ./config.status --recheck
+$(srcdir)/configure: @MAINT@$(srcdir)/configure.in $(ACLOCAL_M4) $(CONFIGURE_DEPENDENCIES)
+ cd $(srcdir) && $(AUTOCONF)
+
+mostlyclean-noinstLIBRARIES:
+
+clean-noinstLIBRARIES:
+ -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
+
+distclean-noinstLIBRARIES:
+
+maintainer-clean-noinstLIBRARIES:
+
+.c.o:
+ $(COMPILE) -c $<
+
+.s.o:
+ $(COMPILE) -c $<
+
+.S.o:
+ $(COMPILE) -c $<
+
+mostlyclean-compile:
+ -rm -f *.o core *.core
+
+clean-compile:
+
+distclean-compile:
+ -rm -f *.tab.c
+
+maintainer-clean-compile:
+
+libangsd.a: $(libangsd_a_OBJECTS) $(libangsd_a_DEPENDENCIES)
+ -rm -f libangsd.a
+ $(AR) cru libangsd.a $(libangsd_a_OBJECTS) $(libangsd_a_LIBADD)
+ $(RANLIB) libangsd.a
+
+tags: TAGS
+
+ID: $(HEADERS) $(SOURCES) $(LISP)
+ here=`pwd` && cd $(srcdir) \
+ && mkid -f$$here/ID $(SOURCES) $(HEADERS) $(LISP)
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS)'; \
+ unique=`for i in $$list; do echo $$i; done | \
+ awk ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
+ || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS)
+
+mostlyclean-tags:
+
+clean-tags:
+
+distclean-tags:
+ -rm -f TAGS ID
+
+maintainer-clean-tags:
+
+distdir = $(PACKAGE)-$(VERSION)
+top_distdir = $(distdir)
+
+# This target untars the dist file and tries a VPATH configuration. Then
+# it guarantees that the distribution is self-contained by making another
+# tarfile.
+distcheck: dist
+ -rm -rf $(distdir)
+ GZIP=$(GZIP) $(TAR) zxf $(distdir).tar.gz
+ mkdir $(distdir)/=build
+ mkdir $(distdir)/=inst
+ dc_install_base=`cd $(distdir)/=inst && pwd`; \
+ cd $(distdir)/=build \
+ && ../configure --srcdir=.. --prefix=$$dc_install_base \
+ && $(MAKE) $(AM_MAKEFLAGS) \
+ && $(MAKE) $(AM_MAKEFLAGS) dvi \
+ && $(MAKE) $(AM_MAKEFLAGS) check \
+ && $(MAKE) $(AM_MAKEFLAGS) install \
+ && $(MAKE) $(AM_MAKEFLAGS) installcheck \
+ && $(MAKE) $(AM_MAKEFLAGS) dist
+ -rm -rf $(distdir)
+ @echo "========================"; \
+ echo "$(distdir).tar.gz is ready for distribution"; \
+ echo "========================"
+dist: distdir
+ -chmod -R a+r $(distdir)
+ GZIP=$(GZIP) $(TAR) chozf $(distdir).tar.gz $(distdir)
+ -rm -rf $(distdir)
+dist-all: distdir
+ -chmod -R a+r $(distdir)
+ GZIP=$(GZIP) $(TAR) chozf $(distdir).tar.gz $(distdir)
+ -rm -rf $(distdir)
+distdir: $(DISTFILES)
+ -rm -rf $(distdir)
+ mkdir $(distdir)
+ -chmod 777 $(distdir)
+ @for file in $(DISTFILES); do \
+ if test -f $$file; then d=.; else d=$(srcdir); fi; \
+ test -f $(distdir)/$$file \
+ || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
+ || cp -p $$d/$$file $(distdir)/$$file; \
+ done
+info:
+dvi:
+check:
+installcheck:
+install-info:
+install-exec:
+ @$(NORMAL_INSTALL)
+
+install-data:
+ @$(NORMAL_INSTALL)
+
+install: install-exec install-data all
+ @:
+
+uninstall:
+
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM='$(INSTALL_PROGRAM) -s' INSTALL_SCRIPT='$(INSTALL_PROGRAM)' install
+installdirs:
+
+
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -rm -f Makefile $(CONFIG_CLEAN_FILES)
+ -rm -f config.cache config.log stamp-h stamp-h[0-9]*
+
+maintainer-clean-generic:
+mostlyclean: mostlyclean-noinstLIBRARIES mostlyclean-compile \
+ mostlyclean-tags mostlyclean-generic
+
+clean: clean-noinstLIBRARIES clean-compile clean-tags clean-generic \
+ mostlyclean
+
+distclean: distclean-noinstLIBRARIES distclean-compile distclean-tags \
+ distclean-generic clean
+ -rm -f config.status
+
+maintainer-clean: maintainer-clean-noinstLIBRARIES \
+ maintainer-clean-compile maintainer-clean-tags \
+ maintainer-clean-generic distclean
+ @echo "This command is intended for maintainers to use;"
+ @echo "it deletes files that may require special tools to rebuild."
+ -rm -f config.status
+
+.PHONY: mostlyclean-noinstLIBRARIES distclean-noinstLIBRARIES \
+clean-noinstLIBRARIES maintainer-clean-noinstLIBRARIES \
+mostlyclean-compile distclean-compile clean-compile \
+maintainer-clean-compile tags mostlyclean-tags distclean-tags \
+clean-tags maintainer-clean-tags distdir info dvi installcheck \
+install-info install-exec install-data install uninstall all \
+installdirs mostlyclean-generic distclean-generic clean-generic \
+maintainer-clean-generic clean mostlyclean distclean maintainer-clean
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/gdb/rdi-share/README.CYGNUS b/gdb/rdi-share/README.CYGNUS
new file mode 100644
index 00000000000..4bf06c93c3d
--- /dev/null
+++ b/gdb/rdi-share/README.CYGNUS
@@ -0,0 +1,6 @@
+This is a version of ARM's RDI library which has been been put under a
+free software license.
+
+See ARM's Software Development Tools Reference Manual (Remote
+Debugging chapter), and the file gdb/remote-rdi.c for information
+about how to use it.
diff --git a/gdb/rdi-share/aclocal.m4 b/gdb/rdi-share/aclocal.m4
new file mode 100644
index 00000000000..55a8225b960
--- /dev/null
+++ b/gdb/rdi-share/aclocal.m4
@@ -0,0 +1,202 @@
+dnl aclocal.m4 generated automatically by aclocal 1.3b
+
+dnl Copyright (C) 1994, 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+dnl This program is distributed in the hope that it will be useful,
+dnl but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+dnl even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+dnl PARTICULAR PURPOSE.
+
+# Do all the work for Automake. This macro actually does too much --
+# some checks are only needed if your package does certain things.
+# But this isn't really a big deal.
+
+# serial 1
+
+dnl Usage:
+dnl AM_INIT_AUTOMAKE(package,version, [no-define])
+
+AC_DEFUN(AM_INIT_AUTOMAKE,
+[AC_REQUIRE([AM_PROG_INSTALL])
+PACKAGE=[$1]
+AC_SUBST(PACKAGE)
+VERSION=[$2]
+AC_SUBST(VERSION)
+dnl test to see if srcdir already configured
+if test "`cd $srcdir && pwd`" != "`pwd`" && test -f $srcdir/config.status; then
+ AC_MSG_ERROR([source directory already configured; run "make distclean" there first])
+fi
+ifelse([$3],,
+AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE")
+AC_DEFINE_UNQUOTED(VERSION, "$VERSION"))
+AC_REQUIRE([AM_SANITY_CHECK])
+AC_REQUIRE([AC_ARG_PROGRAM])
+dnl FIXME This is truly gross.
+missing_dir=`cd $ac_aux_dir && pwd`
+AM_MISSING_PROG(ACLOCAL, aclocal, $missing_dir)
+AM_MISSING_PROG(AUTOCONF, autoconf, $missing_dir)
+AM_MISSING_PROG(AUTOMAKE, automake, $missing_dir)
+AM_MISSING_PROG(AUTOHEADER, autoheader, $missing_dir)
+AM_MISSING_PROG(MAKEINFO, makeinfo, $missing_dir)
+AC_REQUIRE([AC_PROG_MAKE_SET])])
+
+
+# serial 1
+
+AC_DEFUN(AM_PROG_INSTALL,
+[AC_REQUIRE([AC_PROG_INSTALL])
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL_PROGRAM}'
+AC_SUBST(INSTALL_SCRIPT)dnl
+])
+
+#
+# Check to make sure that the build environment is sane.
+#
+
+AC_DEFUN(AM_SANITY_CHECK,
+[AC_MSG_CHECKING([whether build environment is sane])
+# Just in case
+sleep 1
+echo timestamp > conftestfile
+# Do `set' in a subshell so we don't clobber the current shell's
+# arguments. Must try -L first in case configure is actually a
+# symlink; some systems play weird games with the mod time of symlinks
+# (eg FreeBSD returns the mod time of the symlink's containing
+# directory).
+if (
+ set X `ls -Lt $srcdir/configure conftestfile 2> /dev/null`
+ if test "[$]*" = "X"; then
+ # -L didn't work.
+ set X `ls -t $srcdir/configure conftestfile`
+ fi
+ if test "[$]*" != "X $srcdir/configure conftestfile" \
+ && test "[$]*" != "X conftestfile $srcdir/configure"; then
+
+ # If neither matched, then we have a broken ls. This can happen
+ # if, for instance, CONFIG_SHELL is bash and it inherits a
+ # broken ls alias from the environment. This has actually
+ # happened. Such a system could not be considered "sane".
+ AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken
+alias in your environment])
+ fi
+
+ test "[$]2" = conftestfile
+ )
+then
+ # Ok.
+ :
+else
+ AC_MSG_ERROR([newly created file is older than distributed files!
+Check your system clock])
+fi
+rm -f conftest*
+AC_MSG_RESULT(yes)])
+
+dnl AM_MISSING_PROG(NAME, PROGRAM, DIRECTORY)
+dnl The program must properly implement --version.
+AC_DEFUN(AM_MISSING_PROG,
+[AC_MSG_CHECKING(for working $2)
+# Run test in a subshell; some versions of sh will print an error if
+# an executable is not found, even if stderr is redirected.
+# Redirect stdin to placate older versions of autoconf. Sigh.
+if ($2 --version) < /dev/null > /dev/null 2>&1; then
+ $1=$2
+ AC_MSG_RESULT(found)
+else
+ $1="$3/missing $2"
+ AC_MSG_RESULT(missing)
+fi
+AC_SUBST($1)])
+
+# Add --enable-maintainer-mode option to configure.
+# From Jim Meyering
+
+# serial 1
+
+AC_DEFUN(AM_MAINTAINER_MODE,
+[AC_MSG_CHECKING([whether to enable maintainer-specific portions of Makefiles])
+ dnl maintainer-mode is disabled by default
+ AC_ARG_ENABLE(maintainer-mode,
+[ --enable-maintainer-mode enable make rules and dependencies not useful
+ (and sometimes confusing) to the casual installer],
+ USE_MAINTAINER_MODE=$enableval,
+ USE_MAINTAINER_MODE=no)
+ AC_MSG_RESULT($USE_MAINTAINER_MODE)
+ if test $USE_MAINTAINER_MODE = yes; then
+ MAINT=
+ else
+ MAINT='#M#'
+ fi
+ AC_SUBST(MAINT)dnl
+]
+)
+
+# Check to see if we're running under Win32, without using
+# AC_CANONICAL_*. If so, set output variable EXEEXT to ".exe".
+# Otherwise set it to "".
+
+dnl AM_EXEEXT()
+dnl This knows we add .exe if we're building in the Cygwin
+dnl environment. But if we're not, then it compiles a test program
+dnl to see if there is a suffix for executables.
+AC_DEFUN(AM_EXEEXT,
+[AC_REQUIRE([AM_CYGWIN])
+AC_REQUIRE([AM_MINGW32])
+AC_MSG_CHECKING([for executable suffix])
+AC_CACHE_VAL(am_cv_exeext,
+[if test "$CYGWIN" = yes || test "$MINGW32" = yes; then
+am_cv_exeext=.exe
+else
+cat > am_c_test.c << 'EOF'
+int main() {
+/* Nothing needed here */
+}
+EOF
+${CC-cc} -o am_c_test $CFLAGS $CPPFLAGS $LDFLAGS am_c_test.c $LIBS 1>&5
+am_cv_exeext=
+for file in am_c_test.*; do
+ case $file in
+ *.c) ;;
+ *.o) ;;
+ *) am_cv_exeext=`echo $file | sed -e s/am_c_test//` ;;
+ esac
+done
+rm -f am_c_test*])
+test x"${am_cv_exeext}" = x && am_cv_exeext=no
+fi
+EXEEXT=""
+test x"${am_cv_exeext}" != xno && EXEEXT=${am_cv_exeext}
+AC_MSG_RESULT(${am_cv_exeext})
+AC_SUBST(EXEEXT)])
+
+# Check to see if we're running under Cygwin, without using
+# AC_CANONICAL_*. If so, set output variable CYGWIN to "yes".
+# Otherwise set it to "no".
+
+dnl AM_CYGWIN()
+AC_DEFUN(AM_CYGWIN,
+[AC_CACHE_CHECK(for Cygwin environment, am_cv_cygwin,
+[AC_TRY_COMPILE(,[return __CYGWIN32__;],
+am_cv_cygwin=yes, am_cv_cygwin=no)
+rm -f conftest*])
+CYGWIN=
+test "$am_cv_cygwin" = yes && CYGWIN=yes])
+
+
+
+# Check to see if we're running under Mingw, without using
+# AC_CANONICAL_*. If so, set output variable MINGW32 to "yes".
+# Otherwise set it to "no".
+
+dnl AM_MINGW32()
+AC_DEFUN(AM_MINGW32,
+[AC_CACHE_CHECK(for Mingw32 environment, am_cv_mingw32,
+[AC_TRY_COMPILE(,[return __MINGW32__;],
+am_cv_mingw32=yes, am_cv_mingw32=no)
+rm -f conftest*])
+MINGW32=
+test "$am_cv_mingw32" = yes && MINGW32=yes])
+
diff --git a/gdb/rdi-share/adp.h b/gdb/rdi-share/adp.h
new file mode 100644
index 00000000000..099fa4db149
--- /dev/null
+++ b/gdb/rdi-share/adp.h
@@ -0,0 +1,2528 @@
+/*
+ * Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
+ *
+ * This software may be freely used, copied, modified, and distributed
+ * provided that the above copyright notice is preserved in all copies of the
+ * software.
+ */
+
+/* -*-C-*-
+ *
+ * $Revision$
+ * $Date$
+ *
+ *
+ *
+ * INTRODUCTION
+ * ------------
+ * The early RDP message definitions were held in an ARM Ltd "armdbg"
+ * source file. Since the relevant header files were not exported
+ * publicly as part of an ARM Ltd core tools release, it was a problem
+ * for developers manipulating the target side of the protocol.
+ *
+ * For Angel, this new (ANSI 'C' clean) header file defines the ADP
+ * protocol. The header should be useable by both host and target
+ * systems, thus avoiding problems that can arise from duplicate
+ * definitions. Care has been taken in the construction of this header
+ * file to avoid any host/target differences.
+ *
+ * MESSAGE FORMAT
+ * --------------
+ * Format of the "data" section of debug and boot agent messages. This is
+ * the standard ADP (Angel Debug Protocol) message format:
+ *
+ * unsigned32 reason - Main debug reason code.
+ * unsigned32 debugID - Information describing host debug world;
+ * - private to host and used in any target initiated
+ * messages.
+ * unsigned32 OSinfo1 \ Target OS information to identify process/thread
+ * unsigned32 OSinfo2 / memory/world, etc. These two fields are target
+ * defined.
+ * byte args[n] - Data for message "reason" code.
+ *
+ * NOTE: The message format is the same for single threaded debugging,
+ * except that the "OSinfo" fields should be -1 (0xFFFFFFFF). Even
+ * single-threaded debugging *MAY* have different host specified
+ * debugID values, so the Angel debug system will preserve the "debugID"
+ * information for replies, and the relevant asynchronous target-to-host
+ * messages. The "debugID" is defined by the host-end of the
+ * protocol, and is used by the host to ensure that messages are
+ * routed to the correct handler program/veneer.
+ *
+ * The reason there are two target specified "OSinfo" words is because
+ * thread identifiers may not be unique when processes/tasks have
+ * private virtual address spaces. It allows more flexibility when
+ * supporting multi-threaded or O/S aware debugging.
+ *
+ * NOTE: The reason that there is no "size" information, is that the
+ * message IDs themselves encode the format of any arguments. Also it
+ * would be a duplication of information used by the physical
+ * transport layer (which is distinct from this logical message
+ * layer). Any routing of messages through programs, hosts,
+ * etc. should be performed at the physical layer, or the boundaries
+ * between physical layers. i.e. packet received on socket in host,
+ * and transferred to serial packet for passing on down the line.
+ *
+ * NOTE: Pointers aren't passed in messages because they are dangerous in
+ * a multi-threaded environment.
+ *
+ * ADP REASON CODE
+ * ---------------
+ * The message reason codes contain some information that ties them to
+ * the channel and direction that the message will be used with. This
+ * will ensure that even if the message "#define name" is not
+ * completely descriptive, the message reason code is.
+ *
+ * b31 = direction. 0=Host-to-Target; 1=Target-to-Host;
+ * b30-28 = debug agent multi-threaded control (see below)
+ * b27-24 = reserved. should be zero.
+ * b23-16 = channelid. The fixed Angel channel number
+ * (see "channels.h").
+ * b15-0 = message reason code.
+ *
+ * It is unfortunate that to aid the error-checking capabilities of
+ * the Angel communications we have changed the message numbers from
+ * the original ARM Ltd RDP. However this also has benefits, in that
+ * the Angel work is meant to be a clean break.
+ *
+ * However, it isn't so bad since even though the numbers are
+ * different, the majority of the reason codes have exactly the same
+ * functionality as the original RDP messages.
+ *
+ * NOTES
+ * -----
+ * It would be ideal to use "rpcgen" (or some equivalent) to
+ * automatically maintain compatibility between the target and host
+ * ends of the protocol. However, ARM Ltd expressed that the message
+ * handling should be hand-coded, to avoid dependance on external
+ * tools.
+ *
+ * All other channels have undefined data formats and are purely
+ * application defined. The C library "_sys_" support will provide a
+ * veneer to perform message block operations as required.
+ *
+ * It is IMPLIED that all of the ADP messages will fit within the
+ * buffer DATASIZE. This has a minimum value, calculated from
+ * BUFFERMINSIZE.
+ *
+ * All messages are passed and received to the channel system in little
+ * endian order (ie. use little endian order when writing a word as
+ * a sequence of bytes within a message).
+ *
+ * A reply / acknowledgement to an ADP message is always sent and has the
+ * same reason code as the original except that the TtoH / HtoT bit is
+ * reversed. This makes it simple to check that the reply really
+ * is a reply to the message which was just sent! [Boot Channel messages
+ * also require that this protocol is used].
+ */
+
+#ifndef angel_adp_h
+#define angel_adp_h
+
+#include "chandefs.h"
+
+
+/*
+ * Buffer minimum sizes
+ */
+
+/* the minimum target internal size */
+#define ADP_BUFFER_MIN_SIZE (256)
+
+/* a word is always reserved for internal use in the target */
+#define ADP_BUFFER_MAX_INTERNAL (sizeof(word))
+
+/* the minimum available data portion */
+#define ADP_BUFFER_MIN_DATASIZE \
+ (ADP_BUFFER_MIN_SIZE - ADP_BUFFER_MAX_INTERNAL - CHAN_HEADER_SIZE)
+
+/*
+ * the space taken up by the standard ADP header
+ * (reason, debugID, OSinfo1, OSinfo2)
+ */
+#define ADP_DEFAULT_HEADER_SIZE (4*sizeof(word))
+
+
+/* 8bit ADP version identification */
+#define ADPVSN (0x03)
+/* This value can be used to identify the protocol version supported
+ * by target or host systems. This version number should only be
+ * changed if the protocol undergoes a non-backward compatible
+ * change. It should *NOT* be used to reflect extensions to the
+ * protocol. Such extensions can be added to the existing protocol
+ * version by allocating new reason codes, and by extending the
+ * ADP_Info message to identify new features.
+ */
+
+/* The following value is used in the OSinfo fields for
+ * single-threaded messages, or where the host wants to alter the
+ * global CPU state. NOTE: The "debugID" field should always be
+ * defined by the host, and returned in target initiated messages. The
+ * only exception to this rule is the ADP_Booted message at the
+ * start-of-day.
+ */
+#define ADP_HandleUnknown (-1)
+
+/******************************************************************
+ *
+ * ADP reason code subfields
+ *
+ */
+
+/* The following bits are used to describe the basic direction of
+ * messages. This allows some extra checking of message validity to be
+ * performed, as well as providing a description of the message that
+ * may not be available in the "cpp" macro:
+ */
+#define HtoT ((unsigned)0 << 31) /* Host-to-Target message */
+#define TtoH ((unsigned)1 << 31) /* Target-to-Host message */
+
+/* The following bits are used to control how the target system
+ * executes whilst processing messages. This allows for O/S specific
+ * host-based debug programs to interrogate system structures whilst
+ * ensuring that the access is atomic within the constraints imposed
+ * by the target O/S.
+ *
+ * NOTE: That only the channel is inserted into the reason code
+ * automatically. Thus both direction and multi thread control bits
+ * must be added by the host / target.
+ */
+/* Disable FIQ whilst processing message */
+#define DisableFIQ (1 << 30)
+/* Disable IRQ whilst processing message */
+#define DisableIRQ (1 << 29)
+/* Disable O/S pre-emption whilst processing message */
+#define DisablePreemption (1 << 28)
+
+/* The channel identification number is held in the reason code as a
+ * check:
+ */
+#define ADPCHANNEL(b) (((b) & 0xFF) << 16)
+
+/* The following macro constructs the reason code number, from the
+ * various fields - note that the direction is NOT inlcuded since
+ * this depends on whether the Host or Target system is including
+ * this file!
+ */
+#define ADPREASON(c,r) (ADPCHANNEL(c) | ((r) & 0xFFFF))
+
+/* This macros is used when constructing manifests for sub-reason
+ * codes. At the moment it is identical to the main reason macro. If
+ * desired we could add a new bit that explicitly identifies the value
+ * as a sub-reason code, where the corresponding bit in the main
+ * message ID would be zero.
+ */
+#define ADPSUBREASON(c,r) (ADPCHANNEL(c) | ((r) & 0xFFFF))
+
+/* All other undefined bits are reserved, and should be zero. */
+
+
+
+/*****************************************************************
+ *
+ * channel_BOOT messages
+ *
+ */
+
+/* The BOOT agent only supports a few messages. They are used purely
+ * to control the "start-of-day" connection to a host program. All
+ * Angel systems with host communications *MUST* provide the BOOT
+ * agent, even if they don't have support for either the single- or
+ * multi-threaded debug agents.
+ *
+ * The way the BOOT channel will be used on startup will be as follows:
+ *
+ * a) Target board is powered up before host debugger is invoked
+ *
+ * After switching on the target and initialisation is completed the
+ * target will send an ADP_Booted or ADP_Reset message. The debugger
+ * has not been started yet so this message will not be received. In
+ * a serial world this makes it important that any buffers on the host
+ * side are flushed during initialisation of the debugger, and in an
+ * Ethernet world it makes it important that the target can cope with the
+ * message not being received.
+ *
+ * Eventually the Debugger will be started up and will send an
+ * ADP_Reboot or ADP_Reset request. The target will respond to this with
+ * an ADP_Reboot or ADP_Reset acknowldege and will then reboot, finally
+ * sending an ADP_Rebooted when it has done all it needs to do (very little
+ * in the case of ADP_Reset, but completely rebooting in the case of
+ * ADP_Reboot). Note that it is important that an ADP_Rebooted message is
+ * sent so that the Debugger does not attempt to send any data after it has
+ * made a request to ADP_Reboot and before it receives an ADP_Rebooted, as
+ * data can be lost be the target during this time.
+ *
+ * The target and host are now ready to start a debug session.
+ *
+ * b) Target board is powered up after host debugger is invoked
+ *
+ * The debugger will send an ADP_Reboot or ADP_Reset request, but will
+ * receive no reply until the target is powered up.
+/ *
+ * When the target is powered up then it will send an ADP_Rebooted
+ * message to the debugger. The debugger should accept this message
+ * even though it has received no ADP_Reboot or ADP_Reset acknowldege message
+ * from the target.
+ *
+ * The target and host are now ready to start a debug session.
+ *
+ *
+ * If at any point during the bootup sequence and ADP messages are
+ * sent down the S_DBG channel then they should be responded to with a
+ * RDI_NotInitialised error. [This should never happen however].
+ *
+ * An ADP_Boot or ADP Rebooted message should be accepted at
+ * any point, since it is possible for a catastrophe to occur (such as
+ * disconnecteing the host and target during a debug message) which
+ * requires that one or other end be reset.
+ *
+ */
+
+/*
+ * A list of parameter types - for now just baud rate
+ */
+typedef enum ADP_Parameter {
+ AP_PARAMS_START = 0xC000,
+ AP_BAUD_RATE = AP_PARAMS_START,
+ /* extra parameters go in here */
+#ifdef TEST_PARAMS
+ AP_CAFE_MENU, /* extra just for testing */
+#endif
+ AP_PARAMS_END
+} ADP_Parameter;
+
+#define AP_NUM_PARAMS (AP_PARAMS_END - AP_PARAMS_START)
+
+/*
+ * Parameter types should have associated semantics which can be represented
+ * within one word per parameter, or an associated enum for choices.
+ *
+ * AP_BAUD_RATE: the word contains the exact baud rate, eg. 9600, 38400.
+ */
+
+/* this is not strictly necessary, but it's an example */
+typedef enum ADP_BaudRate {
+ AB_9600 = 9600,
+ AB_19200 = 19200,
+ AB_38400 = 38400,
+ AB_57600 = 57600,
+ AB_115200 = 115200
+} ADP_BaudRate;
+
+#define AB_NUM_BAUD_RATES 5 /* this is more useful, for sizing arrays */
+
+/* This must be set to the max number of options per parameter type */
+#define AP_MAX_OPTIONS (AB_NUM_BAUD_RATES)
+
+
+#define ADP_Booted ADPREASON(CI_TBOOT,0)
+/* This message is sent by the target after the Angel system has been
+ * initialised. This message also contains information describing the
+ * Angel world. The information can then be used to check that the
+ * target debug agent and source debugger are compatible.
+ *
+ * Message arguments:
+ * word Angel message default buffer size.
+ * word Angel message large buffer size (may be same as default)
+ * word Angel version ; inc. type (e.g. boot ROM) See (1)
+ * word ADP version. See (2)
+ * word ARM Architecture info See (3)
+ * word ARM CPU information ; including target endianness. See (4)
+ * word Target hardware status. See (5)
+ * word Number of bytes in banner message
+ * bytes Startup banner message (single-threaded readable
+ * descriptive text - NOT NULL terminated).
+ *
+ * Reply:
+ * word status
+ *
+ * 'status' returns RDIError_NoError for success, and otherwise
+ * indicates an error.
+ */
+
+/* Angel version word [Reference(1)] : */
+/* Angel version number is a 16bit BCD value */
+#define ADP_ANGELVSN_MASK (0x0000FFFF)
+#define ADP_ANGELVSN_SHIFT (0)
+
+/* Type of Angel system */
+#define ADP_ANGELVSN_TYPE_MASK (0x00FF0000)
+#define ADP_ANGELVSN_TYPE_SHIFT (16)
+
+typedef enum {
+ ADP_AngelType_bootROM, /* Simple ROM system providing download capability */
+ ADP_AngelType_appROM, /* ROM based application */
+ ADP_AngelType_appDLOAD,/* Downloaded Angel based application */
+ ADP_AngelType_Last /* Unknown type. This typedef can be extended */
+ /* but if the host and target vsns differ */
+ /* Then one will spot that it dies not understand */
+} ADP_Angel_Types ; /* this field and can whinge appropriately */
+
+/* First unknown ADP_AngelType */
+#define ADP_ANGELVSN_UNKTYPE_MASK (0xFF000000)
+#define ADP_ANGELVSN_UNKYPE_SHIFT (24)
+
+/* Currently only 8 bits are used in the word: */
+/* ADP protocol supported by target [Reference (2)] */
+#define ADP_ANGELVSN_ADP_MASK (0x000000FF)
+#define ADP_ANGELVSN_ADP_SHIFT (0)
+
+/* ARM Architecture info: [Reference (3)] */
+/* ARM Architecture Verson of target CPU */
+#define ADP_ARM_ARCH_VSN_MASK (0x000000FF)
+#define ADP_ARM_ARCH_VSN_SHIFT (0)
+/* Does the processor support the Thumb Instruction Set */
+#define ADP_ARM_ARCH_THUMB (0x80000000)
+/* Does the processor support Long Multiplies */
+#define ADP_ARM_ARCH_LONGMUL (0x40000000)
+/* All other flags are current undefined, and should be zero. */
+
+/* The following flags describe the feature set of the processor: */
+/* Set if cpu supports little-endian model [Reference (4)] */
+#define ADP_CPU_LE (1 << 0)
+/* Set if cpu supports big-endian model */
+#define ADP_CPU_BE (1 << 1)
+/* Set if processor has a cache */
+#define ADP_CPU_CACHE (1 << 2)
+/* Set if processor has a MMU */
+#define ADP_CPU_MMU (1 << 3)
+/* All other flags are current undefined, and should be zero. */
+
+/* The following flags reflect current Target hardware status: */
+/* [Reference (5)] */
+/* 0 = no MMU or MMU off; 1 = MMU on */
+#define ADP_CPU_MMUOn (1 << 29)
+/* 0 = no cache or cache off; 1 = cache on */
+#define ADP_CPU_CacheOn (1 << 30)
+/* 0 = little-endian; 1 = big-endian */
+#define ADP_CPU_BigEndian (1U << 31)
+/* All other flags are current undefined, and should be zero. */
+
+
+#ifdef LINK_RECOVERY
+
+#define ADP_TargetResetIndication ADPREASON(CI_TBOOT, 1)
+/*
+ * If parameter negotiation is enabled at the target, it configures itself
+ * to various likely parameter settings and sends this message at each
+ * configuration. The message describes the default settings, and after
+ * sending at each configuration the target sets itself to the defaults
+ * it has just broadcast, to await either an ack on TBOOT or a request
+ * or reset indication on HBOOT.
+ *
+ * If the host receives this message successfully, it should reset to the
+ * indicated parameters and send a reply.
+ *
+ * Message arguments:
+ * word status (always 0, makes body same as
+ * ADP_ParamNegotiate response)
+ * word n-parameters
+ * n-parameters * {
+ * word ADP_Parameter
+ * word parameter-value
+ * }
+ *
+ * Reply:
+ * - empty acknowledgement
+ */
+
+#endif /* def LINK_RECOVERY */
+
+typedef enum ADP_Boot_Ack {
+ AB_NORMAL_ACK, /* will comply, immediate booted message */
+ AB_LATE_ACK, /* will comply, late startup */
+ AB_ERROR /* cannot comply */
+} ADP_Boot_Ack;
+
+/* If the host sets neither of these in the word sent on a Reset / Reboot
+ * then it doesn;t care about the endianess of the target
+ */
+#define ADP_BootHostFeature_LittleEnd 0x80000000
+#define ADP_BootHostFeature_BigEnd 0x40000000
+
+#define ADP_Reboot ADPREASON(CI_HBOOT,2)
+/* This message is sent when the host wants the target system to be
+ * completely reset, back to the boot monitor Angel. This is the
+ * method of the host forcing a cold-reboot.
+ * Note that an acknowledgement message will be sent immediately and
+ * that this must be sent before the target can reset.
+ *
+ * The parameter to this function is a bitset of host supported
+ * features. (in fact the same as ADP_Reset below. This can be used by
+ * the target system to avoid using debug channel bandwidth raising
+ * messages that will be ignored by the host.
+ *
+ * Parameters:
+ * word host supported features (see above)
+ *
+ * Reply:
+ * word status, one of enum ADP_Boot_Ack above.
+ *
+ * Currently there are no such features defined, so the word indicating
+ * host supported features should be set to 0.
+ */
+
+
+
+#define ADP_Reset ADPREASON(CI_HBOOT,3)
+/* This message is a request from the host, which should eventually
+ * result in the "ADP_Booted" message being sent by the target.
+ * Note that an acknowledgement message will be sent immediately and
+ * that this must be sent before the target can reset.
+ * This reset message is *ALWAYS* treated as a warm boot, with the target
+ * preserving as much state as possible.
+ *
+ * The parameter to this function is a bitset of host supported
+ * features. This can be used by the target system to avoid using
+ * debug channel bandwitdth raising messages that will be ignored by
+ * the host.
+ *
+ * Parameters:
+ * word host supported features (see above)
+ *
+ * Reply:
+ * word status, one of enum ADP_Boot_Ack above.
+ *
+ * Currently there are no such features defined, so the word indicating
+ * host supported features should be set to 0.
+ */
+
+
+#ifdef LINK_RECOVERY
+
+#define ADP_HostResetIndication ADPREASON(CI_HBOOT, 4)
+/*
+ * This is as for ADP_TargetResetIndication, but is sent by the host when
+ * it first starts up in case the target is listening at a non-default
+ * setting. Having sent at various configurations, the host then listens
+ * at the defaults it has just broadcast, to await either an ack on HBOOT
+ * or a reset indication on TBOOT.
+ *
+ * For arguments and reply, see ADP_TargetResetIndication.
+ */
+
+#endif /* def LINK_RECOVERY */
+
+
+#define ADP_ParamNegotiate ADPREASON(CI_HBOOT, 5)
+/*
+ * The host sends this messages to negotiate new parameters with the target.
+ * For each parameter the host specifies a range of possibilities, starting
+ * with the most favoured. All possible combinations of parameters
+ * must be valid.
+ *
+ * If the target can operate at a combination of the offered parameters,
+ * it will reply with the parameters it is willing to use. AFTER sending
+ * the reply, the target switches to this combination. On receiving the
+ * reply, the host will switch to the new combination and send a LinkCheck
+ * message (see below).
+ *
+ * If the target cannot operate at any combination of the offered parameters,
+ * it will reply with an error status.
+ *
+ * Message arguments:
+ * word n-parameter-blocks
+ * n-parameter-blocks * {
+ * word ADP_Parameter
+ * word n-options
+ * n-options * { word parameter-value }
+ * }
+ *
+ * Reply:
+ * word status
+ * if (status == RDIError_NoError) {
+ * word n-parameters
+ * n-parameters * {
+ * word ADP_Parameter
+ * word chosen-value
+ * }
+ * }
+ */
+
+#define ADP_LinkCheck ADPREASON(CI_HBOOT, 6)
+/*
+ * This should be the first message that the host sends after a successful
+ * parameter negotiation. It is really just a 'ping'.
+ *
+ * Message arguments:
+ * - empty message
+ *
+ * Reply:
+ * - empty acknowledgement
+ */
+
+
+/********************************************************************
+ *
+ * CI_HADP messages
+ *
+ */
+
+#define ADP_HADPUnrecognised ADPREASON(CI_HADP,0)
+/* This message is unusual in that it is normally sent in reply to
+ * another message which is not understood. This is an exception
+ * to the normal protocol which says that a reply must have the
+ * same base reason code as the original. There is a single reply
+ * parameter which is the reason code which was not understood.
+ *
+ * As well as being a reply this message can also be sent and will
+ * return as if this message were unrecognised!
+ *
+ * Parameters:
+ * none
+ *
+ * Reply:
+ * word reason code which was not recognised
+ */
+
+
+#define ADP_Info ADPREASON(CI_HADP,1)
+/* This is the new ADP information message. It is used to interrogate
+ * the target debug agent. It provides information on the processor,
+ * as well as the state of the debug world. This allows the host to
+ * configure itself to the capabilities of the target.
+ *
+ * We try not to use feature bitsets, since we could quickly run out
+ * of known bits. Thus when the feature set is extended, this can be
+ * done in a couple of supported ways:
+ *
+ * If an undivided reason code is to be added (no reason subcodes)
+ * then add a new ADP_Info code which responds with a flag indicating
+ * whether that feature is supported by the target. If this has not
+ * even been implemented then the reply will be ADP_HADPUnrecognised
+ *
+ * If a reason code which is subdivided into reason subcodes is
+ * added then reason subcode 0 should be set aside to indicate
+ * whether the functionality of that reason code is supported
+ * by the target. If it is not even implemented then the reply will
+ * be ADP_Unrecognised.
+ *
+ * The first parameter to ADP_Info is a reason subcode, and subsequent
+ * parameters are defined by that subcode
+ *
+ * Parameters:
+ * word reason subcode
+ * other arguments as reason subcode determines.
+ *
+ * Reply:
+ * word reason subcode
+ * other argument as reason subcode determines
+ */
+
+/* ADP_Info reason subcodes: */
+
+
+
+#define ADP_Info_NOP ADPSUBREASON(CI_HADP,0)
+/* ADP_Info_NOP
+ * ------------
+ * Summary: This message is used to check for ADP_Info being supported.
+ *
+ * Arguments:
+ * Send: ()
+ * Return: (word status)
+ *
+ * 'status' returns RDIError_NoError for success, non-zero indicates an error.
+ * If an error is returned then there is no handler for the ADP_Info
+ * message. The normal action will be to return an OK status.
+ */
+
+
+#define ADP_Info_Target ADPSUBREASON(CI_HADP,1)
+/* ADP_Info_Target
+ * ---------------
+ * Summary:
+ * This reason code is used to interrogate target system details.
+ *
+ * Arguments:
+ * Send: ()
+ * Return: (word status, word bitset, word model)
+ *
+ * 'status' is RDIError_NoError to indicate OK, or non-zero to indicate
+ * some sort of error.
+ * 'bitset' is described in more detail below, and is mostly compatible
+ * with the old RDI/RDP system to avoid gratuitous changes to the debugger
+ * toolbox.
+ * 'model' is the target hardware ID word, as returned by the ADP_Booted
+ * message.
+ *
+ * NOTE: The minimum and maximum protocol levels are no longer supported.
+ * It is the Angel view that debugging complexity should be shifted to the
+ * host if at all possible. This means that the host debugger should
+ * always try to configure itself to the features available in the target
+ * debug agent. This can be done by checking individual messages, rather
+ * than by a blanket version number dictating the feature set.
+ */
+
+/* 'bitset':- */
+/* Target speed in instructions per second = 10**(bits0..3). */
+#define ADP_Info_Target_LogSpeedMask (0xF)
+
+/* Target is running on [0 = emulator / 1 = hardware] */
+#define ADP_Info_Target_HW (1 << 4)
+
+/* Bits 5..10 are currently undefined and should be zero. */
+/* Other bis are kept the same as the RDP in order to */
+/* eliminate the need to change the position of some bits */
+
+/* If set then the debug agent can be reloaded. */
+#define ADP_Info_Target_CanReloadAgent (1 << 11)
+
+/* Can request AngelBufferSize information. */
+#define ADP_Info_Target_CanInquireBufferSize (1 << 12)
+
+/* Bit 13 is no longer required as it inquired whether
+ * a special RDP Interrupt code was supported
+ */
+
+/* Debug agent can perform profiling. */
+#define ADP_Info_Target_Profiling (1 << 14)
+
+/* Debug agent can support Thumb code. */
+#define ADP_Info_Target_Thumb (1 << 15)
+
+/* Bit 16 was the communications channel check.
+ * This is always available on Angel systems.
+ */
+
+#define ADP_Info_Points ADPSUBREASON(CI_HADP,2)
+/* ADP_Info_Points
+ * ---------------
+ * Summary: Returns a 32bit wide bitset of break- and watch-point
+ * features supported by the target debug agent.
+ *
+ * Arguments:
+ * Send: ()
+ * Return: (word status, word breakinfo)
+ *
+ * 'status' returns RDIError_NoError on success or non-zero to indicate
+ * some sort of error.
+ * 'breakinfo' is a 32bit wide bitset described in detail below. Note
+ * that only bits 1..12 are used.
+ */
+
+/* 'breakinfo':- */
+/* Can trap on address equality. */
+#define ADP_Info_Points_Comparison (1 << 0)
+
+/* Can trap on address range. */
+#define ADP_Info_Points_Range (1 << 1)
+
+/* Can trap on 8bit memory reads. */
+#define ADP_Info_Points_ReadByteWatch (1 << 2)
+
+/* Can trap on 16bit memory reads. */
+#define ADP_Info_Points_ReadHalfWatch (1 << 3)
+
+/* Can trap on 32bit memory reads. */
+#define ADP_Info_Points_ReadWordWatch (1 << 4)
+
+/* Can trap on 8bit write accesses. */
+#define ADP_Info_Points_WriteByteWatch (1 << 5)
+
+/* Can trap on 16bit write accesses. */
+#define ADP_Info_Points_WriteHalfWatch (1 << 6)
+
+/* Can trap on 32bit write accesses. */
+#define ADP_Info_Points_WriteWordWatch (1 << 7)
+
+/* Like range, but based on address bitmask<. */
+#define ADP_Info_Points_Mask (1 << 8)
+
+/* Multi-threaded support only - thread specific breakpoints. */
+#define ADP_Info_Points_ThreadBreak (1 << 9)
+
+/* Multi-threaded support only - thread specific watchpoints. */
+#define ADP_Info_Points_ThreadWatch (1 << 10)
+
+/* Allows conditional breakpoints. */
+#define ADP_Info_Points_Conditionals (1 << 11)
+
+/* Break- and watch-points can be interrogated */
+#define ADP_Info_Points_Status (1 << 12)
+
+
+#define ADP_Info_Step ADPSUBREASON(CI_HADP,3)
+/* ADP_Info_Step
+ * -------------
+ * Summary: Returns a 32bit wide bitmask of the single-stepping
+ * capabilities of the target debug agent.
+ *
+ * Arguments:
+ * Send: ()
+ * Return: (word status, word stepinfo)
+ *
+ * 'status' returns RDIError_NoError on success, or non-zero to indicate
+ * some kind of error.
+ * 'stepinfo' is a 32bit wide bitmask described in detail below. Note that
+ * only 3 bits are used.
+ */
+
+/* 'stepinfo':- */
+/* Single-stepping of more than one instruction is possible. */
+#define ADP_Info_Step_Multiple (1 << 0)
+
+/* Single-stepping until next direct PC change is possible. */
+#define ADP_Info_Step_PCChange (1 << 1)
+
+/* Single-stepping of a single instruction is possible. */
+#define ADP_Info_Step_Single (1 << 2)
+
+
+#define ADP_Info_MMU ADPSUBREASON(CI_HADP,4)
+/* ADP_Info_MMU
+ * ------------
+ * Summary: Returns information about the memory management system (if
+ * any).
+ *
+ * Arguments:
+ * Send: ()
+ * Return: (word status, word meminfo)
+ *
+ * 'status' returns RDIError_NoError to indicate success or non-zero to
+ * indicate some kind of error.
+ * 'meminfo' should be a 32bit unique ID, or zero if there is no MMU
+ * support on the target.
+ */
+
+
+#define ADP_Info_SemiHosting ADPSUBREASON(CI_HADP,5)
+/* ADP_Info_SemiHosting
+ * --------------------
+ * Summary: This message is used to check whether semi-hosting info calls
+ * are available on the target.
+ *
+ * Arguments:
+ * Send: ()
+ * Return: (word status)
+ *
+ * 'status' returns RDIError_NoError if semi-hosting info calls are available,
+ * non-zero otherwise.
+ */
+
+
+#define ADP_Info_CoPro ADPSUBREASON(CI_HADP,6)
+/* ADP_Info_CoPro
+ * --------------
+ * Summary: This message checks whether CoProcessor info calls are
+ * supported.
+ *
+ * Arguments:
+ * Send: ()
+ * Return: (word status)
+ *
+ * 'status' returns RDIError_NoError to indicate these facilities
+ * are supported, non-zero otherwise.
+ */
+
+
+#define ADP_Info_Cycles ADPSUBREASON(CI_HADP,7)
+/* ADP_Info_Cycles
+ * ---------------
+ * Summary: Returns the number of instructions and cycles executed since
+ * the target was initialised.
+ *
+ * Arguments:
+ * Send: ()
+ * Return: (word status, word ninstr, word Scycles, word Ncycles,
+ * word Icycles, word Ccycles, word Fcycles)
+ *
+ * 'status' is RDIError_NoError to indicate success, or non-zero if there
+ * is no target support for gathering cycle count information.
+ * 'ninstr' is the number of instructions executed.
+ * 'Scycles' is the number of S-cycles executed.
+ * 'Ncycles' is the number of N-cycles executed.
+ * 'Icycles' is the number of I-cycles executed.
+ * 'Ccycles' is the number of C-cycles executed.
+ * 'Fcycles' is the number of F-cycles executed.
+ */
+
+
+#define ADP_Info_DescribeCoPro ADPSUBREASON(CI_HADP,8)
+/* ADP_Info_DescribeCoPro
+ * ----------------------
+ * Summary: Describe the registers of a coprocessor. Use only if
+ * ADP_Info_CoPro return RDIError_NoError.
+ *
+ * Arguments:
+ * Send: Arguments of the form:
+ * (byte cpno, byte rmin, byte rmax, byte nbytes, byte access,
+ * byte cprt_r_b0, byte cprt_r_b1, byte cprt_w_b0, byte cprt_w_b1)
+ * And a terminating byte = 0xff. Must be within maximum buffer size.
+ * Return: (word status)
+ *
+ * 'cpno' is the number of the coprocessor to be described.
+ * 'rmin' is the bottom of a range of registers with the same description.
+ * 'rmax' is the top of a range of registers with the same description.
+ * 'nbytes' is the size of the register.
+ * 'access' describes access to the register and is described in more detail
+ * below.
+ *
+ * If bit 2 of access is set:-
+ * 'cprt_r0' provides bits 0 to 7, and
+ * 'cprt_r1' provides bits 16 to 23 of a CPRT instruction to read the
+ * register.
+ * 'cprt_w0' provides bits 0 to 7, and
+ * 'cprt_w1' provides bits 16 to 23 of a CPRT instruction to write the
+ * register.
+ *
+ * Otherwise, 'cprt_r0' provides bits 12 to 15, and 'cprt_r1' bit 22 of CPDT
+ * instructions to read and write the register ('cprt_w0' and 'cprt_w1' are
+ * junk).
+ */
+
+/* 'access':- */
+/* Readable. */
+#define ADP_Info_DescribeCoPro_Readable (1 << 0)
+
+/* Writeable. */
+#define ADP_Info_DescribeCoPro_Writeable (1 << 1)
+
+/* Registers read or written via CPDT instructions (else CPRT) with this
+ bit set. */
+#define ADP_Info_DescribeCoPro_CPDT (1 << 2)
+
+#define ADP_Info_RequestCoProDesc ADPSUBREASON(CI_HADP,9)
+/* ADP_Info_RequestCoProDesc
+ * -------------------------
+ * Summary: Requests a description of the registers of a coprocessor. Use
+ * only if ADP_Info_CoPro return RDIError_NoError.
+ *
+ * Arguments:
+ * Send: (byte cpno)
+ * Return: Arguments of the form:-
+ * (word status, byte rmin, byte rmax, byte nbytes, byte access)
+ * Followed by a terminating byte = 0xFF. Must be within maximum
+ * buffer size.
+ * 'cpno' is the number of the coprocessor to describe.
+ * 'status' is RDIError_NoError to indicate success, non-zero otherwise.
+ * 'rmin' is the bottom of a range of registers with the same description.
+ * 'rmax' is the top of a range of registers with the same description.
+ * 'nbytes' is the size in bytes of the register(s).
+ * 'access' is as above in ADP_Info_DescribeCoPro.
+ */
+
+
+#define ADP_Info_AngelBufferSize ADPSUBREASON(CI_HADP,10)
+/* ADP_Info_AngelBufferSize
+ * ------------------------
+ * Summary: Returns the Angel buffer sizes.
+ *
+ * Arguments:
+ * Send: ()
+ * Return: (word status, word defaultsize, word maxsize)
+ *
+ * 'status' returns RDIError_NoError to indicate success or non-zero to
+ * indicate some kind of error.
+ * 'defaultsize' is the default Angel ADP buffer size in bytes. This is
+ * at least 256 bytes.
+ * 'maxsize' is the largest Angel ADP buffer size in bytes. This will be
+ * greater than or equal to defaultsize. The target will accept ADP messages
+ * of up to this length for download, etc.
+ *
+ * Was DownLoadSize in RDP/RDI world. This is the amount that the target
+ * should transmit in a single operation. This should now be the Angel
+ * buffer size. This information is also given in the ADP_Booted message.
+ *
+ * NOTE: The value returned should be the DATASIZE and *NOT* BUFFERDEFSIZE.
+ * This is needed to ensure that the transport protocol information
+ * can be wrapped around the data.
+ */
+
+#define ADP_Info_ChangeableSHSWI ADPSUBREASON(CI_HADP,11)
+/* ADP_Info_ChangeableSHSWI
+ * ------------------------
+ * Summary: This message is used to check whether it is possible to change
+ * which SWI's are used for semihosting.
+ *
+ * Arguments:
+ * Send: ()
+ * Return: (word status)
+ *
+ * 'status' returns RDIError_NoError if semi-hosting info calls are available,
+ * non-zero otherwise.
+ */
+
+#define ADP_Info_CanTargetExecute ADPSUBREASON(CI_HADP,12)
+/* ADP_Info_CanTargetExecute
+ * -------------------------
+ * Summary: This message is used to see if the target is currently in
+ * an executable state. Typically this is called after the debugger
+ * initialises. If a non-error statis is returned then the user is
+ * allowed to 'go' immediately.
+ *
+ * Arguments:
+ * Send: ()
+ * Return: (word status)
+ *
+ * 'status' returns RDIError_NoError if target is ready to execute.
+ * other values indicate why it cannot execute.
+ */
+
+#define ADP_Info_AgentEndianess ADPSUBREASON(CI_HADP,13)
+/* ADP_Info_AgentEndianess
+ * -------------------------
+ * Summary: This message is used to determine the endianess of the
+ * debug agent
+ * Arguments:
+ * Send: ()
+ * Return: (word status)
+ *
+ * status should be RDIError_LittleEndian or RDIError_BigEndian
+ * any other value indicates the target does not support this
+ * request, so the debugger will have to make a best guess, which
+ * probably means only allow little endian loadagenting.
+ */
+
+
+#define ADP_Control ADPREASON(CI_HADP,2)
+/* This message allows for the state of the debug agent to be
+ * manipulated by the host.
+ */
+
+/* The following are sub reason codes to ADP control, the first parameter
+ * is the sub reason code which defines the format of subsequent parameters.
+ *
+ * word sub reason code
+ */
+
+#define ADP_Ctrl_NOP ADPSUBREASON(CI_HADP,0)
+/* ADP_Ctrl_NOP
+ * ------------
+ * Summary: This message is used to check that ADP_Ctrl messages are
+ * supported.
+ *
+ * Arguments:
+ * Send: ()
+ * Return: (word status)
+ *
+ * 'status' is RDIError_NoError to indicate ADP_Ctrl messages are
+ * supported, non-zero otherwise.
+ */
+
+#define ADP_Ctrl_VectorCatch ADPSUBREASON(CI_HADP,1)
+/* ADP_Ctrl_VectorCatch
+ * --------------------
+ * Summary: Specifies which hardware exceptions should be reported to the
+ * debugger.
+ *
+ * Arguments:
+ * Send: (word bitmap)
+ * Return: (word status)
+ *
+ * 'bitmap' is a bit-mask of exceptions to be reported, described in more
+ * detail below. A set bit indicates that the exception should be
+ * reported to the debugger, a clear bit indicates that the corresponding
+ * exception vector should be taken.
+ * 'status' is RDIError_NoError to indicate success, non-zero otherwise.
+ */
+
+/* 'bitmap':- */
+/* Reset(branch through zero). */
+#define ADP_Ctrl_VectorCatch_BranchThroughZero (1 << 0)
+
+/* Undefined Instruction. */
+#define ADP_Ctrl_VectorCatch_UndefinedInstr (1 << 1)
+
+/* Software Interrupt. */
+#define ADP_Ctrl_VectorCatch_SWI (1 << 2)
+
+/* Prefetch Abort. */
+#define ADP_Ctrl_VectorCatch_PrefetchAbort (1 << 3)
+
+/* Data Abort. */
+#define ADP_Ctrl_VectorCatch_DataAbort (1 << 4)
+
+/* Address Exception. */
+#define ADP_Ctrl_VectorCatch_AddressException (1 << 5)
+
+/* Interrupt Request. */
+#define ADP_Ctrl_VectorCatch_IRQ (1 << 6)
+
+/* Fast Interrupt Request. */
+#define ADP_Ctrl_VectorCatch_FIQ (1 << 7)
+
+/* Error. */
+#define ADP_Ctrl_VectorCatch_Error (1 << 8)
+
+
+#define ADP_Ctrl_PointStatus_Watch ADPSUBREASON(CI_HADP,2)
+/* ADP_Ctrl_PointStatus_Watch
+ * --------------------------
+ * Summary: Returns the hardware resource number and the type of that
+ * resource when given a watchpoint handle. Should only be called if
+ * the value returned by ADP_Info_Points had ADP_Info_Points_Status set.
+ *
+ * Arguments:
+ * Send: (word handle)
+ * Return: (word status, word hwresource, word type)
+ *
+ * 'handle' is a handle to a watchpoint.
+ * 'status' is RDIError_NoError to indicate success, non-zero otherwise.
+ * 'hwresource' is the hardware resource number. !!!!!
+ * 'type' is the type of the resource.
+ */
+
+
+#define ADP_Ctrl_PointStatus_Break ADPSUBREASON(CI_HADP,3)
+/* ADP_Ctrl_PointStatus_Break
+ * --------------------------
+ * Summary: Returns the hardware resource number and the type of that
+ * resource when given a breakpoint handle. Should only be called if
+ * the value returned by ADP_Info_Points had ADP_Info_Points_Status set.
+ *
+ * Arguments:
+ * Send: (word handle)
+ * Return: (word status, word hwresource, word type)
+ *
+ * 'handle' is a handle to a breakpoint.
+ * 'status' is RDIError_NoError to indicate success, non-zero otherwise.
+ * 'hwresource' is the hardware resource number.
+ * 'type' is the type of the resource.
+ */
+
+#define ADP_Ctrl_SemiHosting_SetState ADPSUBREASON(CI_HADP,4)
+/* ADP_Ctrl_SemiHosting_SetState
+ * -----------------------------
+ * Summary: Sets whether or not semi-hosting is enabled.
+ *
+ * Arguments:
+ * Send: (word semihostingstate)
+ * Return: (word status)
+ *
+ * 'semihostingstate' sets semi-hosting to enabled if zero, otherwise
+ * it disables semi-hosting.
+ * 'status' is RDIError_NoError to indicate success, non-zero otherwise.
+ *
+ * NOTE: This should only be called if ADP_Info_SemiHosting didn't return
+ * an error.
+ */
+
+
+#define ADP_Ctrl_SemiHosting_GetState ADPSUBREASON(CI_HADP,5)
+/* ADP_Ctrl_SemiHosting_GetState
+ * -----------------------------
+ * Summary: Reads whether or not semi-hosting is enabled.
+ *
+ * Arguments:
+ * Send: ()
+ * Return: (word status, word semihostingstate)
+ *
+ * 'status' is RDIError_NoError to indicate success, non-zero otherwise.
+ * 'semihostingstate' is zero if semi-hosting is enabled, non-zero otherwise.
+ *
+ * NOTE: This should only be called if ADP_Info_SemiHosting didn't return
+ * an error.
+ */
+
+
+#define ADP_Ctrl_SemiHosting_SetVector ADPSUBREASON(CI_HADP,6)
+/* ADP_Ctrl_SemiHosting_SetVector
+ * ------------------------------
+ * Summary: Sets the semi-hosting vector.
+ *
+ * Arguments:
+ * Send: (word semihostingvector)
+ * Return: (word status)
+ *
+ * 'semihostingvector' holds the value the vector is to be set to.
+ * 'status' is RDIError_NoError to indicate success, non-zero otherwise.
+ *
+ * NOTE: This should only be called if ADP_Info_SemiHosting didn't return
+ * an error.
+ */
+
+
+#define ADP_Ctrl_SemiHosting_GetVector ADPSUBREASON(CI_HADP,7)
+/* ADP_Ctrl_SemiHosting_GetVector
+ * ------------------------------
+ * Summary: Gets the value of the semi-hosting vector.
+ *
+ * Arguments:
+ * Send: ()
+ * Return: (word status, word semihostingvector)
+ *
+ * 'status' is RDIError_NoError to indicate success, non-zero otherwise.
+ * 'semihostingvector' holds the value of the vector.
+ *
+ * NOTE: This should only be called if ADP_Info_SemiHosting didn't return
+ * an error.
+ */
+
+
+#define ADP_Ctrl_Log ADPSUBREASON(CI_HADP,8)
+/* ADP_Ctrl_Log
+ * ------------
+ * Summary: Returns the logging state.
+ *
+ * Arguments:
+ * Send: ()
+ * Return: (word status, word logsetting)
+ *
+ * 'status' is RDIError_NoError to indicate success, non-zero otherwise.
+ * 'logsetting' is a bitmap specifying the level of logging desired,
+ * described in more detail below. The bits can be ORed together
+ */
+
+/* 'logsetting':- */
+
+/* No logging. */
+#define ADP_Ctrl_Log_NoLogging (0)
+/* RDI level logging. */
+#define ADP_Ctrl_Log_RDI (1 << 0)
+/* ADP byte level logging. */
+#define ADP_Ctrl_Log_ADP (1 << 1)
+
+
+#define ADP_Ctrl_SetLog ADPSUBREASON(CI_HADP,9)
+/* ADP_Ctrl_SetLog
+ * ---------------
+ * Summary: Sets the logging state.
+ *
+ * Arguments:
+ * Send: (word logsetting)
+ * Return: (word status)
+ *
+ * 'logsetting' is the same as in ADP_Ctrl_Log above.
+ * 'status' is RDIError_NoError to indicate success, non-zero otherwise.
+ */
+
+#define ADP_Ctrl_SemiHosting_SetARMSWI ADPSUBREASON(CI_HADP,10)
+/* ADP_Ctrl_SemiHosting_SetARMSWI
+ * ------------------------------
+ * Summary: Sets the number of the ARM SWI used for semihosting
+ *
+ * Arguments:
+ * Send: (word ARM_SWI_number)
+ * Return: (word status)
+ *
+ * The debug agent will interpret ARM SWI's with the SWI number specified
+ * as semihosting SWI's.
+ * 'status' is RDIError_NoError to indicate success, non-zero otherwise.
+ *
+ * NOTE: This should only be called if ADP_Info_ChangeableSHSWI didn't return
+ * an error.
+ */
+
+
+#define ADP_Ctrl_SemiHosting_GetARMSWI ADPSUBREASON(CI_HADP,11)
+/* ADP_Ctrl_SemiHosting_GetARMSWI
+ * ------------------------------
+ * Summary: Reads the number of the ARM SWI used for semihosting
+ *
+ * Arguments:
+ * Send: ()
+ * Return: (word status, word ARM_SWI_number)
+ *
+ * 'status' is RDIError_NoError to indicate success, non-zero otherwise.
+ * ARM_SWI_number is the SWI number which is used for semihosting.
+ *
+ * NOTE: This should only be called if ADP_Info_SemiHosting didn't return
+ * an error.
+ */
+
+#define ADP_Ctrl_SemiHosting_SetThumbSWI ADPSUBREASON(CI_HADP,12)
+/* ADP_Ctrl_SemiHosting_SetThumbSWI
+ * --------------------------------
+ * Summary: Sets the number of the Thumb SWI used for semihosting
+ *
+ * Arguments:
+ * Send: (word Thumb_SWI_number)
+ * Return: (word status)
+ *
+ * The debug agent will interpret Thumb SWI's with the SWI number specified
+ * as semihosting SWI's.
+ * 'status' is RDIError_NoError to indicate success, non-zero otherwise.
+ *
+ * NOTE: This should only be called if ADP_Info_ChangeableSHSWI didn't return
+ * an error.
+ */
+
+
+#define ADP_Ctrl_SemiHosting_GetThumbSWI ADPSUBREASON(CI_HADP,13)
+/* ADP_Ctrl_SemiHosting_GetThumbSWI
+ * --------------------------------
+ * Summary: Reads the number of the Thumb SWI used for semihosting
+ *
+ * Arguments:
+ * Send: ()
+ * Return: (word status, word ARM_Thumb_number)
+ *
+ * 'status' is RDIError_NoError to indicate success, non-zero otherwise.
+ * Thumb_SWI_number is the SWI number which is used for semihosting.
+ *
+ * NOTE: This should only be called if ADP_Info_SemiHosting didn't return
+ * an error.
+ */
+
+
+#define ADP_Ctrl_Download_Supported ADPSUBREASON(CI_HADP,14)
+/* ADP_Ctrl_Download_Supported
+ * ---------------------------
+ * Summary: Can configuration be downloaded?
+ *
+ * Arguments:
+ * Send: ()
+ * Return: (word status)
+ *
+ * 'status' is RDIError_NoError if the configuration can be downloaded,
+ * non-zero otherwise.
+ *
+ * NOTE: Equivalent to RDIInfo_DownLoad.
+ */
+
+
+#define ADP_Ctrl_Download_Data ADPSUBREASON(CI_HADP,15)
+/* ADP_Ctrl_Download_Data
+ * ----------------------
+ * Summary: Loads configuration data.
+ *
+ * Arguments:
+ * Send: (word nbytes, words data)
+ * Return: (word status)
+ *
+ * 'nbytes' is the number of *bytes* being sent.
+ * 'data' is the configuration data. NOTE: data must not cause the buffer
+ * size to exceed the maximum allowed buffer size.
+ * 'status' is RDIError_NoError to indicate success, non-zero otherwise.
+ *
+ * NOTE: Equivalent to RDP_LoadConfigData. Should only be used if
+ * ADP_ICEM_AddConfig didn't return an error.
+ */
+
+
+#define ADP_Ctrl_Download_Agent ADPSUBREASON(CI_HADP,16)
+/* ADP_Ctrl_Download_Agent
+ * -----------------------
+ * Summary: Prepares Debug Agent to receive configuration data which it
+ * should interpret as a new version of the Debug Agent code.
+ *
+ * Arguments:
+ * Send: (word loadaddress, word size)
+ * Return: (word status)
+ *
+ * 'loadaddress' is the address where the new Debug Agent code should be
+ * loaded.
+ * 'size' is the number of bytes of Debug Agent code to be loaded.
+ * 'status' is RDIError_NoError to indicate success, non-zero otherwise.
+ *
+ * NOTE: Equivalent to RDP_LoadAgent. The data will be downloaded using
+ * ADP_Ctrl_Download_Data. The new agent is started with ADP_Ctrl_Start_Agent
+ */
+
+
+#define ADP_Ctrl_Start_Agent ADPSUBREASON(CI_HADP,17)
+/* ADP_Ctrl_Start_Agent
+ * -----------------------
+ * Summary: Instruct Debug Agent to begin execution of new agent,
+ * which has been downloaded by ADP_Ctrl_Download_Agent.
+ *
+ * Arguments:
+ * Send: (word startaddress)
+ * Return: (word status)
+ *
+ * 'startaddress' is the address where the new Debug Agent code should be
+ * entered, and must satisfy:
+ * (loadaddress <= startaddress <= (loadaddress + size))
+ * where 'loadaddress' and 'size' were specified in the
+ * ADP_Ctrl_Download_Agent message.
+ *
+ * 'status' is RDIError_NoError to indicate success, non-zero otherwise.
+ */
+
+
+#define ADP_Ctrl_SetTopMem ADPSUBREASON(CI_HADP,18)
+/* ADP_Ctrl_SetTopMem
+ * ------------------
+ * Summary: Sets the top of memory for ICEman2 systems, so that the C Library
+ * can allocate the stack in the correct place on startup.
+ *
+ * Arguments:
+ * Send: (word mem_top)
+ * Return: (word status)
+ *
+ * This request should only be supported by ICEman2. Standard Angel systems
+ * should return an error (unrecognised is fine).
+ */
+
+
+#define ADP_Read ADPREASON(CI_HADP,3)
+#define ADP_ReadHeaderSize (ADP_DEFAULT_HEADER_SIZE + 2*sizeof(word))
+
+/* ADP_Read
+ * --------
+ * Summary: Request for a transer of memory contents from the target to the
+ * debugger.
+ *
+ * Arguments:
+ * Send: (word address, word nbytes)
+ * Return: (word status, word rnbytes [, bytes data])
+ *
+ * 'address' is the address from which memory transer should start.
+ * 'nbytes' is the number of bytes to transfer.
+ * 'status' is RDIError_NoError to indicate success, non-zero otherwise.
+ * 'rnbytes' holds the number of requested bytes NOT read (i.e. zero
+ * indicates success, non-zero indicates an error).
+ * 'data' is the number of bytes requested minus 'rnbytes'.
+ */
+
+
+
+#define ADP_Write ADPREASON(CI_HADP,4)
+#define ADP_WriteHeaderSize (ADP_DEFAULT_HEADER_SIZE + 2*sizeof(word))
+
+/* ADP_Write
+ * ---------
+ * Summary: Request for a transfer of memory contents from the debugger to
+ * the target.
+ *
+ * Arguments:
+ * Send: (word address, word nbytes, bytes data)
+ * Return: (word status [, word rnbytes])
+ *
+ * 'address' is the address from which memory transer should start.
+ * 'nbytes' is the number of bytes to transfer.
+ * 'data' holds the bytes to be transferred.
+ * 'status' is RDIError_NoError to indicate success, non-zero otherwise.
+ * 'rnbytes' holds the number of requested bytes NOT written (i.e. zero
+ * indicates success, non-zero indicates an error) if status indicated an
+ * error.
+ */
+
+
+
+#define ADP_CPUread ADPREASON(CI_HADP,5)
+/* ADP_CPUread
+ * -----------
+ * Summary: This is a request to read values in the CPU.
+ *
+ * Arguments:
+ * Send: (byte mode, word mask)
+ * Return: (word status, words data)
+ *
+ * 'mode' defines the processor mode from which the transfer should be made.
+ * It is described in more detail below.
+ * 'mask' indicates which registers should be transferred. Setting a bit to
+ * one will cause the designated register to be transferred. The details
+ * of mask are specified below.
+ * 'status' is RDIError_NoError to indicate success, non-zero otherwise.
+ * 'data' holds the values of the registers on successful completion,
+ * otherwise it just holds rubbish. The lowest numbered register is
+ * transferred first. NOTE: data must not cause the buffer size to exceed
+ * the maximum allowed buffer size.
+ */
+
+/* 'mode':- */
+/* The mode number is the same as the mode number used by an ARM; a value of
+ 255 indicates the current mode. */
+#define ADP_CPUmode_Current (255)
+
+/* 26bit user mode. */
+#define ADP_CPUread_26bitUser (0x0)
+
+/* 26bit FIQ mode. */
+#define ADP_CPUread_26bitFIQ (0x1)
+
+/* 26bit IRQ mode. */
+#define ADP_CPUread_26bitIRQ (0x2)
+
+/* 26bit Supervisor mode. */
+#define ADP_CPUread_26bitSVC (0x3)
+
+/* 32bit user mode. */
+#define ADP_CPUread_32bitUser (0x10)
+
+/* 32bit FIQ mode. */
+#define ADP_CPUread_32bitFIQ (0x11)
+
+/* 32bit IRQ mode. */
+#define ADP_CPUread_32bitIRQ (0x12)
+
+/* 32bit Supervisor mode. */
+#define ADP_CPUread_32bitSVC (0x13)
+
+/* 32bit Abort mode. */
+#define ADP_CPUread_32bitAbort (0x17)
+
+/* 32bit Undefined mode. */
+#define ADP_CPUread_32bitUndef (0x1B)
+
+/* #32bit System mode - Added in Architecture 4 ARMs e.g.ARM7TDMI */
+#define ADP_CPUread_32bitSystem (0x1F)
+
+/* 'mask':- */
+/* Request registers RO-R14. */
+#define ADP_CPUread_RegsMask (0x7FFF)
+
+/* Request Program Counter (including mode and flag bits in 26-bit modes. */
+#define ADP_CPUread_PCmode (1 << 15)
+
+/* Request Program Counter (without mode and flag bits in 26-bit modes. */
+#define ADP_CPUread_PCnomode (1 << 16)
+
+/* Requests the transfer of the CPSR */
+#define ADP_CPUread_CPSR (1 << 17)
+
+/* In processor modes with an SPSR(non-user modes), bit 19 requests its
+ transfer */
+#define ADP_CPUread_SPSR (1 << 18)
+
+
+
+#define ADP_CPUwrite ADPREASON(CI_HADP,6)
+/* ADP_CPUwrite
+ * ------------
+ * Summary: This is a request to write values to the CPU.
+ *
+ * Arguments:
+ * Send: (byte mode, word mask, words data)
+ * Return: (word status)
+ *
+ * 'mode' defines the processor mode to which the transfer should be made.
+ * The mode number is the same as the mode number used by ARM; a value of
+ * 255 indicates the current mode. See ADP_CPUread above for more detail.
+ * 'mask' indicates which registers should be transferred. Setting a bit to
+ * one will cause the designated register to be transferred. The details
+ * of mask are specified above in ADP_CPUread.
+ * 'data' holds the values of the registers to be transferred. The first
+ * value is written to the lowest numbered register. NOTE: data must not
+ * cause the buffer size to exceed the maximum allowed buffer size.
+ * 'status' is RDIError_NoError to indicate success, non-zero otherwise.
+ */
+
+
+
+#define ADP_CPread ADPREASON(CI_HADP,7)
+/* ADP_CPread
+ * ----------
+ * Summary: This message requests a co-processors internal state.
+ *
+ * Arguments:
+ * Send: (byte CPnum, word mask)
+ * Return: (word status, words data)
+ *
+ * 'CPnum' is the number of the co-processor to transfer values from.
+ * 'mask' specifies which registers to transfer and is co-processor
+ * specific.
+ * 'status' is RDIError_NoError to indicate success, non-zero otherwise.
+ * 'data' holds the registers specified in 'mask' if successful, otherwise
+ * just rubbish. The lowest numbered register is transferred first.
+ * NOTE: data must not cause the buffer size to exceed the maximum allowed
+ * buffer size.
+ */
+
+
+
+#define ADP_CPwrite ADPREASON(CI_HADP,8)
+/* ADP_CPwrite
+ * -----------
+ * Summary: This message requests a write to a co-processors internal state.
+ *
+ * Arguments:
+ * Send: (byte CPnum, word mask, words data)
+ * Return: (word status)
+ *
+ * 'CPnum' is the number of the co-processor to transfer values to.
+ * 'mask' specifies which registers to transfer and is co-processor
+ * specific.
+ * 'data' holds the values to transfer to the registers specified in 'mask'.
+ * The first value is written to the lowest numbered register.
+ * NOTE: data must not cause the buffer size to exceed the maximum allowed
+ * buffer size.
+ * 'status' is RDIError_NoError to indicate success, non-zero otherwise.
+ */
+
+
+
+#define ADP_SetBreak ADPREASON(CI_HADP,9)
+/* ADP_SetBreak
+ * ------------
+ * Summary: Sets a breakpoint.
+ *
+ * Arguments:
+ * Send: (word address, byte type [, word bound])
+ * Return: (word status, word pointhandle, word raddress, word rbound)
+ *
+ * 'address' is the address of the instruction to set the breakpoint on.
+ * 'type' specifies the sort of breakpoint and is described in more detail
+ * below.
+ * 'bound' is included if the least significant 4 bits of type are set to
+ * 5 or above (see below for more detail).
+ * 'status' is RDIError_NoError to indicate success, non-zero otherwise.
+ * 'pointhandle' returns a handle to the breakpoint, it will be valid if bit
+ * 7 of 'type' is set. See below for more detail.
+ * 'raddress' is valid depending on 'type', see below for more detail.
+ * 'rbound' is valid depending on 'type', see below for more detail.
+ */
+
+/* 'type':- */
+/* The least significant 4 bits define the sort of breakpoint to set:- */
+/* Halt if the pc is equal to 'address'. */
+#define ADP_SetBreak_EqualsAddress (0)
+
+/* Halt if the pc is greater than 'address'. */
+#define ADP_SetBreak_GreaterAddress (1)
+
+/* Halt if the pc is greater than or equal to 'address'. */
+#define ADP_SetBreak_GEqualsAddress (2)
+
+/* Halt if the pc is less than 'address'. */
+#define ADP_SetBreak_LessAddress (3)
+
+/* Halt if the pc is less than or equal to 'address'. */
+#define ADP_SetBreak_LEqualsAddress (4)
+
+/* Halt if the pc is in the range from 'address' to 'bound' inclusive. */
+#define ADP_SetBreak_Range (5)
+
+/* Halt if the pc is not in the range from 'address' to 'bound' inclusive. */
+#define ADP_SetBreak_NotRange (6)
+
+/* Halt if (pc & 'bound') = 'address'. */
+#define ADP_SetBreak_AndBound (7)
+
+/* Bits 5,6 and 7 are used as follows :- */
+/* If set this indicates that the breakpoint is on a 16bit (Thumb)
+ instruction rather than a 32bit (ARM) instruction. */
+#define ADP_SetBreak_Thumb (1 << 4)
+
+/* This requests that the breakpoint should be conditional (execution halts
+ only if the breakpointed instruction is executed, not if it is
+ conditionally skipped). If bit 5 is not set, execution halts whenever
+ the breakpointed instruction is reached (whether executed or skipped). */
+#define ADP_SetBreak_Cond (1 << 5)
+
+/* This requests a dry run: the breakpoint is not set and the 'raddress', and
+ if appropriate the 'rbound', that would be used, are returned (for
+ comparison and range breakpoints the address and bound used need not be
+ exactly as requested). A RDIError_NoError 'status' byte indicates that
+ resources are currently available to set the breakpoint, non-zero
+ indicates an error. RDIError_NoMorePoints indicates that the required
+ breakpoint resources are not currently available. */
+#define ADP_SetBreak_DryRun (1 << 6)
+
+/* If the request is successful, but there are no more breakpoint registers
+ (of the requested type), then the value RDIError_NoMorePoints is
+ returned. */
+
+/* If a breakpoint is set on a location which already has a breakpoint, the
+ first breakpoint will be removed before the new breakpoint is set. */
+
+
+
+#define ADP_ClearBreak ADPREASON(CI_HADP,10)
+/* ADP_ClearBreak
+ * --------------
+ * Summary: Clears a breakpoint.
+ *
+ * Arguments:
+ * Send: (word pointhandle)
+ * Return: (word status)
+ *
+ * 'pointhandle' is a handle returned by a previous ADP_SetBreak.
+ * 'status' is RDIError_NoError to indicate success, non-zero otherwise.
+ */
+
+
+#define ADP_SetWatch ADPREASON(CI_HADP,11)
+/* ADP_SetWatch
+ * ------------
+ * Summary: Sets a watchpoint.
+ *
+ * Arguments:
+ * Send: (word address, byte type, byte datatype [,word bound])
+ * Return: (word status, word pointhandle, word raddress, word rbound)
+ *
+ * 'address' is the address at which to set the watchpoint.
+ * 'type' is the type of watchpoint to set and is described in detail below.
+ * 'datatype' defines the sort of data access to watch for and is described
+ * in more detail below.
+ * 'bound' is included depending on the value of type (see description of
+ * type below).
+ * 'status' is RDIError_NoError to indicate success, non-zero otherwise.
+ * 'pointhandle' is valid depending on the value of type (see description
+ * of type below).
+ * 'raddress' is valid depending on the value of type (see description
+ * of type below).
+ * 'rbound' is valid depending on the value of type (see description
+ * of type below).
+ */
+
+/* 'type':- */
+/* The least significant 4 bits of 'type' define the sort of watchpoint to
+ set:- */
+/* Halt on a data access to the address equal to 'address'. */
+#define ADP_SetWatch_EqualsAddress (0)
+
+/* Halt on a data access to an address greater than 'address'. */
+#define ADP_SetWatch_GreaterAddress (1)
+
+/* Halt on a data access to an address greater than or equal to 'address'. */
+#define ADP_SetWatch_GEqualsAddress (2)
+
+/* Halt on a data access to an address less than 'address'. */
+#define ADP_SetWatch_LessAddress (3)
+
+/* Halt on a data access to an address less than or equal to 'address'. */
+#define ADP_SetWatch_LEqualsAddress (4)
+
+/* Halt on a data access to an address in the range from 'address' to
+ 'bound' inclusive. */
+#define ADP_SetWatch_Range (5)
+
+/* Halt on a data access to an address not in the range from 'address' to
+ 'bound' inclusive. */
+#define ADP_SetWatch_NotRange (6)
+
+/* Halt if (data-access-address & 'bound')='address'. */
+#define ADP_SetWatch_AndBound (7)
+
+/* Bits 6 and 7 of 'type' also have further significance:-
+ NOTE: they must not be simulataneously set. */
+
+/* Bit 6 of 'type' set: Requests a dry run: the watchpoint is not set and
+ the 'address' and, if appropriate, the 'bound', that would be used are
+ returned (for range and comparison watchpoints, the 'address' and 'bound'
+ used need not be exactly as requested). A RDIError_NoError status byte
+ indicates that resources are currently available to set the watchpoint;
+ RDIError_NoMorePoints indicates that the required watchpoint resources
+ are not currently available. */
+
+/* Bit 7 of 'type' set: Requests that a handle should be returned for the
+ watchpoint by which it will be identified subsequently. If bit 7 is
+ set, a handle will be returned ('pointhandle'), whether or not the
+ request succeeds or fails (but, obviously, it will only be meaningful
+ if the request succeesd). */
+
+/* 'datatype':- */
+/* The 'datatype' argument defines the sort of data access to watch for,
+ values can be summed or ORed together to halt on any set of sorts of
+ memory access. */
+
+/* Watch for byte reads. */
+#define ADP_SetWatch_ByteReads (1)
+
+/* Watch for half-word reads. */
+#define ADP_SetWatch_HalfWordReads (2)
+
+/* Watch for word reads. */
+#define ADP_SetWatch_WordReads (4)
+
+/* Watch for half-word reads. */
+#define ADP_SetWatch_ByteWrites (8)
+
+/* Watch for half-word reads. */
+#define ADP_SetWatch_HalfWordWrites (16)
+
+/* Watch for half-word reads. */
+#define ADP_SetWatch_WordWrites (32)
+
+/* On successful completion a RDIError_NoError 'status' byte is returned. On
+ unsuccessful completion, a non-zero error code byte is returned. If the
+ request is successful, but there are now no more watchpoint registers
+ (of the requested type), then the value RDIError_NoMorePoints is
+ returned. */
+
+/* If a watchpoint is set on a location which already has a watchpoint, the
+ first watchpoint will be removed before the new watchpoint is set. */
+
+
+#define ADP_ClearWatch ADPREASON(CI_HADP,12)
+/* ADP_ClearWatch
+ * --------------
+ * Summary: Clears a watchpoint.
+ *
+ * Arguments:
+ * Send: (word pointhandle)
+ * Return: (word status)
+ *
+ * 'pointhandle' is a handle to a watchpoint returned by a previous
+ * ADP_SetWatch.
+ * 'status' is RDIError_NoError to indicate success, non-zero otherwise.
+ */
+
+
+
+#define ADP_Execute ADPREASON(CI_HADP,13)
+/* ADP_Execute
+ * -----------
+ * Summary: This message requests that the target starts executing from
+ * the stored CPU state.
+ *
+ * Arguments:
+ * Send: ()
+ * Return: (word status)
+ *
+ * 'status' is RDIError_NoError to indicate success, non-zero otherwise.
+ * The message will *ALWAYS* respond immediately with an ACK (unlike the
+ * old RDI definition, which allowed asynchronous message replies).
+ *
+ * Execution will stop when allowed system events occur. The host will
+ * be notified via a ADP_Stopped message (described below).
+ */
+
+
+
+#define ADP_Step ADPREASON(CI_HADP,14)
+/* ADP_Step
+ * --------
+ * Summary: Execute 'ninstr' instructions.
+ *
+ * Arguments:
+ * Send: (word ninstr)
+ * Return: (word status)
+ *
+ * 'ninstr' is the number of instructions to execute, starting at the
+ * address currently loaded into the CPU program counter. If it is zero,
+ * the target should execute instructions upto the next instruction that
+ * explicitly alters the Program Counter. i.e. a branch or ALU operation
+ * with the PC as the destination.
+ * 'status' is RDIError_NoError to indicate success, non-zero otherwise.
+ *
+ * The ADP_Step function (unlike the earlier RDI system) will *ALWAYS*
+ * return an ACK immediately. A subsequent ADP_Stopped message will be
+ * delivered from the target to the host when the ADP_Step operation
+ * has completed.
+ */
+
+
+
+#define ADP_InterruptRequest ADPREASON(CI_HADP,15)
+/* ADP_InterruptRequest
+ * --------------------
+ * Summary: Interrupt execution.
+ *
+ * Arguments:
+ * Send: ()
+ * Return: (word status)
+ *
+ * 'status' is RDIError_NoError to indicate success, non-zero otherwise.
+ * On receiving this message the target should attempt to stop execution.
+ */
+
+
+
+#define ADP_HW_Emulation ADPREASON(CI_HADP,16)
+/* ADP_HW_Emulation
+ * ----------------
+ * The first parameter to ADP_HW_Emulation is a Reason Subcode, and
+ * subsequent parameters are defined by that subcode
+ *
+ * word reason subcode
+ * other arguments as reason subcode determines
+ *
+ */
+
+/* ADP__HW_Emulation sub-reason codes: */
+
+#define ADP_HW_Emul_Supported ADPSUBREASON(CI_HADP,0)
+/* ADP_HW_Emul_Supported
+ * ---------------------
+ * Summary: Enquires whether calls to the next 4 messages are available
+ * (MemoryAccess, MemoryMap, Set_CPUspeed, ReadClock).
+ *
+ * Arguments:
+ * Send: ()
+ * Return: (word status)
+ *
+ * 'status' is RDIError_NoError to indicate the messages are available,
+ * non-zero otherwise.
+ *
+ * NOTE: Equivalent to RDI_Info_Memory_Stats.
+ */
+
+
+#define ADP_HW_Emul_MemoryAccess ADPSUBREASON(CI_HADP,1)
+/* ADP_HW_Emul_MemoryAccess
+ * ------------------------
+ * Summary: Get memory access information for memory block with specified
+ * handle.
+ *
+ * Arguments:
+ * Send: (word handle)
+ * Return: (word status, word nreads, word nwrites, word sreads,
+ * word swrites, word ns, word s)
+ *
+ * 'handle' is a handle to a memory block.
+ * 'status' is RDIError_NoError to indicate success, non-zero otherwise.
+ * 'nreads' is the number of non-sequential reads.
+ * 'nwrites' is the number of non-sequential writes.
+ * 'sreads' is the number of sequential reads.
+ * 'swrites' is the number of sequential writes.
+ * 'ns' is time in nano seconds.
+ * 's' is time in seconds.
+ *
+ * NOTE: Equivalent to RDIMemory_Access.
+ */
+
+
+#define ADP_HW_Emul_MemoryMap ADPSUBREASON(CI_HADP,2)
+/* ADP_HW_Emul_MemoryMap
+ * ---------------------
+ * Summary: Sets memory characteristics.
+ *
+ * Arguments:
+ * Send: (word n,
+ Then 'n' sets of arguments of the form:-
+ word handle, word start, word limit, byte width,
+ byte access, word Nread_ns, word Nwrite_ns, word Sread_ns,
+ word Swrite_ns)
+ * Return: (word status)
+ *
+ * 'n' is the number of sets of arguments.
+ * 'handle' is a handle to the region.
+ * 'start' is the start of this region.
+ * 'limit' is the limit of this region.
+ * 'width' is the memory width, described in detail below.
+ * 'access' is described in detail below.
+ * 'Nread_ns' is the access time for N read cycles in nano seconds.
+ * 'Nwrite_ns' is the access time for N write cycles in nano seconds.
+ * 'Sread_ns' is the access time for S read cycles in nano seconds.
+ * 'Swrite_ns' is the access time for S write cycles in nano seconds.
+ * 'status' is RDIError_NoError to indicate success, non-zero otherwise.
+ * NOTE: Equivalent to RDIMemory_Map.
+ */
+
+/* 'width':- */
+/* 8 bit memory width. */
+#define ADP_HW_Emul_MemoryMap_Width8 (0)
+
+/* 16 bit memory width. */
+#define ADP_HW_Emul_MemoryMap_Width16 (1)
+
+/* 32 bit memory width. */
+#define ADP_HW_Emul_MemoryMap_Width32 (2)
+
+/* 'access':- */
+/* Bit 0 - read access. */
+#define ADP_HW_Emul_MemoryMap_Access_Read (1 << 0)
+
+/* Bit 1 - write access. */
+#define ADP_HW_Emul_MemoryMap_Access_Write (1 << 1)
+
+/* Bit 2 - latched 32 bit memory. */
+#define ADP_HW_Emul_MemoryMap_Access_Latched (1 << 2)
+
+
+#define ADP_HW_Emul_SetCPUSpeed ADPSUBREASON(CI_HADP,3)
+/* ADP_HW_Emul_SetCPUSpeed
+ * -----------------------
+ * Summary: Sets the speed of the CPU.
+ *
+ * Arguments:
+ * Send: (word speed)
+ * Return: (word status)
+ *
+ * 'speed' is the CPU speed in nano seconds.
+ * 'status' is RDIError_NoError to indicate success, non-zero otherwise.
+ *
+ * NOTE: Equivalent to RDISet_CPUSpeed.
+ */
+
+
+#define ADP_HW_Emul_ReadClock ADPSUBREASON(CI_HADP,4)
+/* ADP_HW_Emul_ReadClock
+ * ---------------------
+ * Summary: Reads simulated time.
+ *
+ * Arguments:
+ * Send: ()
+ * Return: (word status, word ns, word s)
+ *
+ * 'status' is RDIError_NoError to indicate success, non-zero otherwise.
+ * 'ns' is time in nano seconds.
+ * 's' is time in seconds.
+ *
+ * NOTE: Equivalent to RDIRead_Clock.
+ */
+
+
+#define ADP_ICEbreakerHADP ADPREASON(CI_HADP,17)
+
+/* The first parameter to ADP_ICEbreaker is a Reason Subcode, and
+ * subsequent parameters are defined by that subcode
+ *
+ * word reason subcode
+ * other arguments as reason subcode determines
+ *
+ */
+
+/* ADP_ICEbreaker sub-reason codes: */
+
+#define ADP_ICEB_Exists ADPSUBREASON(CI_HADP,0)
+/* ADP_ICEB_Exists
+ * ---------------
+ * Summary: Is there an ICEbreaker in the system?
+ *
+ * Arguments:
+ * Send: ()
+ * Return: (word status)
+ *
+ * 'status' is RDIError_NoError to indicate there is an ICEbreaker,
+ * non-zero otherwise.
+ */
+
+
+#define ADP_ICEB_GetLocks ADPSUBREASON(CI_HADP,1)
+/* ADP_ICEB_GetLocks
+ * -----------------
+ * Summary: Returns which ICEbreaker registers are locked.
+ *
+ * Arguments:
+ * Send: ()
+ * Return: (word status, word lockedstate)
+ *
+ * 'status' is RDIError_NoError to indicate success, non-zero otherwise.
+ * 'lockedstate' is a bitmap if the ICEbreaker registers locked against use
+ * by IceMan (because explicitly written by the user). Bit n represents
+ * hardware breakpoint n, and if set the register is locked.
+ *
+ * NOTE: Equivalent to RDIIcebreaker_GetLocks. Should only be used if
+ * ADP_ICEB_Exists didn't return an error.
+ */
+
+
+#define ADP_ICEB_SetLocks ADPSUBREASON(CI_HADP,2)
+/* ADP_ICEB_SetLocks
+ * -----------------
+ * Summary: Sets which ICEbreaker registers are locked.
+ *
+ * Arguments:
+ * Send: (word lockedstate)
+ * Return: (word status)
+ *
+ * 'lockedstate' is the same as in ADP_ICEB_GetLocks above.
+ * 'status' is RDIError_NoError to indicate success, non-zero otherwise.
+ *
+ * NOTE: Equivalent to RDIIcebreaker_SetLocks. Should only be used if
+ * ADP_ICEB_Exists didn't return an error.
+ */
+
+
+#define ADP_ICEB_CC_Exists ADPSUBREASON(CI_HADP,3)
+/* ADP_ICEB_CC_Exists
+ * ------------------
+ * Summary: Is there an ICEbreaker Comms Channel?
+ *
+ * Arguments:
+ * Send: ()
+ * Return: (word status)
+ *
+ * 'status' is RDIError_NoError to indicate there is a Comms Channel,
+ * non-zero otherwise.
+ *
+ * NOTE: Should only be used if ADP_ICEB_Exists didn't return an error.
+ */
+
+
+#define ADP_ICEB_CC_Connect_ToHost ADPSUBREASON(CI_HADP,4)
+/* ADP_ICEB_CC_Connect_ToHost
+ * --------------------------
+ * Summary: Connect Comms Channel in ToHost direction.
+ *
+ * Arguments:
+ * Send: (byte connect)
+ * Return: (word status)
+ *
+ * 'connect' !!!!!
+ * 'status' is RDIError_NoError to indicate success, non-zero otherwise.
+ *
+ * NOTE: Equivalent to RDICommsChannel_ToHost. Should only be used if
+ * ADP_ICEB_CC_Exists didn't return an error.
+ */
+
+
+#define ADP_ICEB_CC_Connect_FromHost ADPSUBREASON(CI_HADP,5)
+/* ADP_ICEB_CC_Connect_FromHost
+ * ----------------------------
+ * Summary: Connect Comms Channel in FromHost direction.
+ *
+ * Arguments:
+ * Send: (byte connect)
+ * Return: (word status)
+ *
+ * 'connect' is the same as in ADP_ICEB_CC_Connect_ToHost above.
+ * 'status' is RDIError_NoError to indicate success, non-zero otherwise.
+ *
+ * NOTE: Equivalent to RDICommsChannel_FromHost. Should only be used if
+ * ADP_ICEB_CC_Exists didn't return an error.
+ */
+
+
+#define ADP_ICEman ADPREASON(CI_HADP,18)
+
+/* The first parameter to ADP_ICEman is a Reason Subcode, and
+ * subsequent parameters are defined by that subcode
+ *
+ * word reason subcode
+ * other arguments as reason subcode determines
+ *
+ */
+
+/* ADP_ICEman sub-reason codes: */
+
+
+#define ADP_ICEM_AddConfig ADPSUBREASON(CI_HADP,0)
+/* ADP_ICEM_AddConfig
+ * ------------------
+ * Summary: Prepares target to receive configuration data block.
+ *
+ * Arguments:
+ * Send: (word nbytes)
+ * Return: (word status)
+ *
+ * 'nbytes' is the number of bytes in the configuration block.
+ * 'status' is RDIError_NoError to indicate success, non-zero if a
+ * configuration block of this size can't be accepted.
+ *
+ * NOTE: Equivalent to RDP_AddConfig.
+ */
+
+
+#define ADP_ICEM_SelectConfig ADPSUBREASON(CI_HADP,1)
+/* ADP_ICEM_SelectConfig
+ * ---------------------
+ * Summary: Selects one of the sets of configuration data blocks and
+ * reinitialises to use the new configuration.
+ *
+ * Arguments:
+ * Send: (byte aspect, byte namelen, byte matchtype, word vsn_req,
+ bytes name)
+ * Return: (word status, word vsn_sel)
+ *
+ * 'aspect' is one of two values defined below.
+ * 'namelen' is the number of bytes in 'name'.
+ * 'matchtype' specifies how the selected version must match that specified,
+ * and takes one of the values defined below.
+ * 'vsn_req' is the requested version of the named configuration.
+ * 'name' is the name of the configuration.
+ * 'status' is RDIError_NoError to indicate success, non-zero otherwise.
+ * 'vsn_sel' is the version number of the configuration selected on success.
+ *
+ * NOTE: Equivalent to RDP_SelectConfig.
+ */
+
+/* 'aspect':- */
+#define ADP_ICEM_SelectConfig_ConfigCPU (0)
+#define ADP_ICEM_SelectConfig_ConfigSystem (1)
+
+/* 'matchtype':- */
+#define ADP_ICEM_SelectConfig_MatchAny (0)
+#define ADP_ICEM_SelectConfig_MatchExactly (1)
+#define ADP_ICEM_SelectConfig_MatchNoEarlier (2)
+
+
+#define ADP_ICEM_ConfigCount ADPSUBREASON(CI_HADP,2)
+/* ADP_ICEM_ConfigCount
+ * --------------------
+ * Summary: Return number of configurations.
+ *
+ * Arguments:
+ * Send: ()
+ * Return: (word status [, word count])
+ *
+ * 'status' is RDIError_NoError to indicate success, non-zero otherwise.
+ * 'count' returns the number of configurations if status is zero.
+ *
+ * NOTE: Equivalent to RDIConfig_Count.
+ */
+
+
+#define ADP_ICEM_ConfigNth ADPSUBREASON(CI_HADP,3)
+/* ADP_ICEM_ConfigNth
+ * ------------------
+ * Summary: Gets the nth configuration details.
+ *
+ * Arguments:
+ * Send: (word confign)
+ * Return: (word status, word version, byte namelen, bytes name)
+ *
+ * 'confign' is the number of the configuration.
+ * 'status' is RDIError_NoError to indicate success, non-zero otherwise.
+ * 'version' is the configuration version number.
+ * 'namelen' is the number of bytes in 'name'.
+ * 'name' is the name of the configuration.
+ *
+ * NOTE: Equivalent to RDIConfig_Nth.
+ */
+
+
+
+#define ADP_Profile ADPREASON(CI_HADP,19)
+
+/* The first parameter to ADP_Profile is a Reason Subcode, and
+ * subsequent parameters are defined by that subcode
+ *
+ * word reason subcode
+ * other arguments as reason subcode determines
+ *
+ */
+
+/* ADP_Profile sub-reason codes: */
+
+
+#define ADP_Profile_Supported ADPSUBREASON(CI_HADP,0)
+/* ADP_Profile_Supported
+ * ---------------------
+ * Summary: Checks whether profiling is supported.
+ *
+ * Arguments:
+ * Send: ()
+ * Return: (word status)
+ *
+ * 'status' is RDIError_NoError if profiling is supported, non-zero otherwise.
+ *
+ * NOTE: Can also be determined using Info_Target.
+ */
+
+
+#define ADP_Profile_Stop ADPSUBREASON(CI_HADP,1)
+/* ADP_Profile_Stop
+ * ----------------
+ * Summary: Stops profiling.
+ *
+ * Arguments:
+ * Send: ()
+ * Return: (word status)
+ *
+ * 'status' is RDIError_NoError to indicate success, non-zero otherwise.
+ *
+ * NOTE: Equivalent to RDIProfile_Stop.
+ */
+
+
+#define ADP_Profile_Start ADPSUBREASON(CI_HADP,2)
+/* ADP_Profile_Start
+ * -----------------
+ * Summary: Starts profiling (PC sampling).
+ *
+ * Arguments:
+ * Send: (word interval)
+ * Return: (word status)
+ *
+ * 'interval' is the period of PC sampling in micro seconds.
+ * 'status' is RDIError_NoError to indicate success, non-zero otherwise.
+ *
+ * NOTE: Equivalent to RDIProfile_Start.
+ */
+
+
+#define ADP_Profile_WriteMap ADPSUBREASON(CI_HADP,3)
+#define ADP_ProfileWriteHeaderSize (ADP_DEFAULT_HEADER_SIZE + 4*sizeof(word))
+
+/* ADP_Profile_WriteMap
+ * --------------------
+ * Summary: Downloads a map array, which describes the PC ranges for profiling.
+ *
+ * Arguments: A number of messages each of form:-
+ * Send: (word len, word size, word offset, words map_data)
+ * Return: (word status)
+ *
+ * 'len' is the number of elements in the entire map array being downloaded.
+ * 'size' is the number of words being downloaded in this message, i.e. the
+ * length of 'map_data'.
+ * 'offset' is the offset into the entire map array which this message starts
+ * from, in words.
+ * 'map_data' consists of 'size' words of map data.
+ * 'status' is RDIError_NoError to indicate success, non-zero otherwise.
+ *
+ * NOTE: Equivalent to RDIProfile_WriteMap.
+ */
+
+
+#define ADP_Profile_ReadMap ADPSUBREASON(CI_HADP,4)
+#define ADP_ProfileReadHeaderSize (ADP_DEFAULT_HEADER_SIZE + 2*sizeof(word))
+
+/* ADP_Profile_ReadMap
+ * -------------------
+ * Summary: Uploads a set of profile counts which correspond to the current
+ * profile map.
+ *
+ * Arguments: A number of messages, each of the form:
+ * Send: (word offset, word size)
+ * Return: (word status, words counts)
+ *
+ * 'offset' is the offset in the entire array of counts that this message
+ * starts from, in words.
+ * 'size' is the number of words uploaded in this message (in counts).
+ * 'status' is RDIError_NoError to indicate success, non-zero otherwise.
+ * 'counts' is 'size' words of profile counts.
+ *
+ * NOTE: Equivalent to RDIProfile_ReadMap.
+ */
+
+
+#define ADP_Profile_ClearCounts ADPSUBREASON(CI_HADP,5)
+/* ADP_Profile_ClearCounts
+ * -----------------------
+ * Summary: Requests that PC sample counts be set to zero.
+ *
+ * Arguments:
+ * Send: ()
+ * Return: (word status)
+ *
+ * 'status' is RDIError_NoError to indicate success, non-zero otherwise.
+ *
+ * NOTE: Equivalent to RDIProfile_ClearCounts.
+ */
+
+#define ADP_InitialiseApplication ADPREASON(CI_HADP,20)
+/* ADP_InitialiseApplication
+ * -------------------------
+ * Summary: Requests that OS setup up the thread/task so that it can be
+ * executed.
+ *
+ * Arguments:
+ * Send: ()
+ * Return: (word status)
+ *
+ * 'status' is RDIError_NoError to indicate success, non-zero otherwise.
+ */
+
+#define ADP_End ADPREASON(CI_HADP,21)
+/* ADP_End
+ * -------
+ * Summary: Sent by the host debugger to tell angel this debugging session
+ * is is finished
+ * Arguments:
+ * Send: ()
+ * Return: (word status)
+ * status' is RDIError_NoError to indicate success, non-zero otherwise.
+ */
+
+/******************************************************************
+ *
+ * CI_TADP messages
+ *
+ */
+
+#define ADP_TADPUnrecognised ADPREASON(CI_TADP,0)
+/* This message is unusual in that it is normally sent in reply to
+ * another message which is not understood. This is an exception
+ * to the normal protocol which says that a reply must have the
+ * same base reason code as the original. There is a single reply
+ * parameter which is the reason code which was not understood.
+ *
+ * As well as being a reply this message can also be sent and will
+ * return as if this message were unrecognised!
+ *
+ * Parameters:
+ * none
+ *
+ * Reply:
+ * word reason code which was not recognised
+ */
+
+/*-------------------------------------------------------------------------*/
+
+#define ADP_Stopped ADPREASON(CI_TADP,1)
+/* ADP_Stopped
+ * -----------
+ * Summary: This message is sent to the host when the application stops,
+ * either naturally or due to an exception.
+ *
+ * Parameters:
+ * word reason subcode
+ * other arguments as reason subcode determines.
+ * Unless stated otherwise (below) there will be none.
+ *
+ * Reply:
+ * word status unless reason subcode says otherwise
+ *
+ * This message is sent to the host when execution has stopped. This
+ * can be when the end of the application has been reached, or as the
+ * result of an exception. It can also be the return from an ADP_Step
+ * process, when the requested number of instructions have been
+ * executed., or a breakpoint or watchpoint has been hit etc.
+ */
+
+/* The first set of Stopped subreason codes are for the ARM hardware
+ * vectors. These events will be raised if the
+ * ADP_Control_Vector_Catch allows, or if the target application has
+ * not provided its own handlers.
+ */
+#define ADP_Stopped_BranchThroughZero ADPSUBREASON(CI_TADP,0)
+#define ADP_Stopped_UndefinedInstr ADPSUBREASON(CI_TADP,1)
+#define ADP_Stopped_SoftwareInterrupt ADPSUBREASON(CI_TADP,2)
+#define ADP_Stopped_PrefetchAbort ADPSUBREASON(CI_TADP,3)
+#define ADP_Stopped_DataAbort ADPSUBREASON(CI_TADP,4)
+#define ADP_Stopped_AddressException ADPSUBREASON(CI_TADP,5)
+#define ADP_Stopped_IRQ ADPSUBREASON(CI_TADP,6)
+#define ADP_Stopped_FIQ ADPSUBREASON(CI_TADP,7)
+
+/* We leave the rest of what would be the bits in the VectorCatch
+ * bitmask free for future expansion.
+ */
+
+/* The following are software reasons for execution stopping: */
+#define ADP_Stopped_BreakPoint ADPSUBREASON(CI_TADP,32)
+/* Breakpoint was reached
+ * extra send parameter: word handle - indicates which breakpoint
+ */
+
+#define ADP_Stopped_WatchPoint ADPSUBREASON(CI_TADP,33)
+/* Watchpoint was triggered
+ * extra send parameter: word handle - indicates which watchpoint
+ */
+
+#define ADP_Stopped_StepComplete ADPSUBREASON(CI_TADP,34)
+/* End of ADP_Step request */
+
+#define ADP_Stopped_RunTimeErrorUnknown ADPSUBREASON(CI_TADP,35)
+/*
+ * non-specific fatal runtime support error
+ */
+
+#define ADP_Stopped_InternalError ADPSUBREASON(CI_TADP,36)
+/* extra send parameter: word error - indicates the nature of the error
+ *
+ * An Angel internal error has happened. The error number should be
+ * displayed for the user to report to his software supplier. Once
+ * this error has been received the internal state of Angel can no longer
+ * be trusted.
+ */
+
+#define ADP_Stopped_UserInterruption ADPSUBREASON(CI_TADP,37)
+/* Host requested interruption */
+
+#define ADP_Stopped_ApplicationExit ADPSUBREASON(CI_TADP,38)
+/* extra send parameter: word exitcode
+ * This indicates that the application has exited via exit(), an exitcode
+ * of zero indiactes successful termination.
+ */
+
+#define ADP_Stopped_StackOverflow ADPSUBREASON(CI_TADP, 39)
+/*
+ * Software stack overflow has occurred
+ */
+
+#define ADP_Stopped_DivisionByZero ADPSUBREASON(CI_TADP, 40)
+/*
+ * Division by zero has occurred
+ */
+
+#define ADP_Stopped_OSSpecific ADPSUBREASON(CI_TADP, 41)
+/*
+ * The OS has requested that execution stops. The OS will know
+ * why this has happened.
+ */
+
+
+
+/******************************************************************
+ *
+ * CI_TTDCC messages (Target-initiated debug comms channel)
+ *
+ */
+
+#define ADP_TDCC_ToHost ADPREASON(CI_TTDCC,0)
+/* ADP_TDCC_ToHost
+ * ------------------
+ * Summary: Send Data down Comms Channel in ToHost direction.
+ *
+ * Arguments:
+ * Send: (word nbytes, words data)
+ * Return: (word status)
+ *
+ * 'nbytes' is number of BYTES to be transferred from the target to the
+ * host via the Debug Comms channel.
+ * 'data' is (nbytes/sizeof(word)) WORDS of data to be transferred from
+ * the target to the host via the Debug Comms channel.
+ * 'status' is RDIError_NoError to indicate success, non-zero otherwise.
+ *
+ * NOTE: Equivalent to RDP_CCToHost and RDP_CCToHostReply (just set the
+ * direction bit).
+ * NOTE II: Current implementations only support single word transfers
+ * (nbytes = 4).
+ */
+
+
+#define ADP_TDCC_FromHost ADPREASON(CI_TTDCC,1)
+/* ADP_TDCC_FromHost
+ * --------------------
+ * Summary: Send Data down Comms Channel in FromHost direction.
+ *
+ * Arguments:
+ * Send: ()
+ * Return: (word status, word nbytes, words data)
+ *
+ * 'status' is RDIError_NoError to indicate success, non-zero otherwise.
+ * 'nbytes' is number of BYTES to be transferred from the host to the
+ * target via the Debug Comms channel, or zero if the host has no data
+ * to transfer.
+ * 'data' is (nbytes/sizeof(word)) WORDS of transferred data.
+ *
+ * NOTE: Equivalent to RDP_CCFromHost and RDP_CCFromHostReply (just set the
+ * direction bit).
+ * NOTE II: Current implementations only support single word transfers
+ * (nbytes = 4).
+ */
+
+
+/*******************************************************************
+ *
+ * Error Codes
+ *
+ */
+
+#define RDIError_NoError 0
+
+#define RDIError_Reset 1
+#define RDIError_UndefinedInstruction 2
+#define RDIError_SoftwareInterrupt 3
+#define RDIError_PrefetchAbort 4
+#define RDIError_DataAbort 5
+#define RDIError_AddressException 6
+#define RDIError_IRQ 7
+#define RDIError_FIQ 8
+#define RDIError_Error 9
+#define RDIError_BranchThrough0 10
+
+#define RDIError_NotInitialised 128
+#define RDIError_UnableToInitialise 129
+#define RDIError_WrongByteSex 130
+#define RDIError_UnableToTerminate 131
+#define RDIError_BadInstruction 132
+#define RDIError_IllegalInstruction 133
+#define RDIError_BadCPUStateSetting 134
+#define RDIError_UnknownCoPro 135
+#define RDIError_UnknownCoProState 136
+#define RDIError_BadCoProState 137
+#define RDIError_BadPointType 138
+#define RDIError_UnimplementedType 139
+#define RDIError_BadPointSize 140
+#define RDIError_UnimplementedSize 141
+#define RDIError_NoMorePoints 142
+#define RDIError_BreakpointReached 143
+#define RDIError_WatchpointAccessed 144
+#define RDIError_NoSuchPoint 145
+#define RDIError_ProgramFinishedInStep 146
+#define RDIError_UserInterrupt 147
+#define RDIError_CantSetPoint 148
+#define RDIError_IncompatibleRDILevels 149
+
+#define RDIError_CantLoadConfig 150
+#define RDIError_BadConfigData 151
+#define RDIError_NoSuchConfig 152
+#define RDIError_BufferFull 153
+#define RDIError_OutOfStore 154
+#define RDIError_NotInDownload 155
+#define RDIError_PointInUse 156
+#define RDIError_BadImageFormat 157
+#define RDIError_TargetRunning 158
+#define RDIError_DeviceWouldNotOpen 159
+#define RDIError_NoSuchHandle 160
+#define RDIError_ConflictingPoint 161
+
+#define RDIError_LittleEndian 240
+#define RDIError_BigEndian 241
+#define RDIError_SoftInitialiseError 242
+
+#define RDIError_InsufficientPrivilege 253
+#define RDIError_UnimplementedMessage 254
+#define RDIError_UndefinedMessage 255
+
+
+#endif
+
+/* EOF adp_h */
diff --git a/gdb/rdi-share/adperr.h b/gdb/rdi-share/adperr.h
new file mode 100644
index 00000000000..f90f1dcc3fd
--- /dev/null
+++ b/gdb/rdi-share/adperr.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
+ *
+ * This software may be freely used, copied, modified, and distributed
+ * provided that the above copyright notice is preserved in all copies of the
+ * software.
+ */
+
+/* -*-C-*-
+ *
+ * $Revision$
+ * $Date$
+ *
+ *
+ * Project: ANGEL
+ *
+ * Title: Definitions of ADP error codes
+ */
+
+#ifndef angsd_adperrs_h
+#define angsd_adperrs_h
+/*
+ * ADP failure codes start at 256 to distinguish them for debug purposes
+ */
+enum AdpErrs
+{
+ adp_ok = 0,
+ adp_failed = 256,
+ adp_malloc_failure,
+ adp_illegal_args,
+ adp_device_not_found,
+ adp_device_open_failed,
+ adp_device_already_open,
+ adp_device_not_open,
+ adp_bad_channel_id,
+ adp_callback_already_registered,
+ adp_write_busy,
+ adp_bad_packet,
+ adp_seq_high,
+ adp_seq_low,
+ adp_timeout_on_open,
+ adp_abandon_boot_wait,
+ adp_late_startup,
+ adp_new_agent_starting
+};
+
+#ifndef __cplusplus
+typedef enum AdpErrs AdpErrs;
+#endif
+
+#define AdpMess_Failed "ADP Error - unspecific failure"
+#define AdpMess_MallocFailed "ADP Error - malloc failed"
+#define AdpMess_IllegalArgs "ADP Error - illegal arguments"
+#define AdpMess_DeviceNotFound "ADP Error - invalid device specified"
+#define AdpMess_DeviceOpenFailed "ADP Error - specified device failed to open"
+#define AdpMess_DeviceAlreadyOpen "ADP Error - device already open"
+#define AdpMess_DeviceNotOpen "ADP Error - device not open"
+#define AdpMess_BadChannelId "ADP Error - bad channel Id"
+#define AdpMess_CBAlreadyRegd "ADP Error - callback already registered"
+#define AdpMess_WriteBusy "ADP Error - write busy"
+#define AdpMess_BadPacket "ADP Error - bad packet"
+#define AdpMess_SeqHigh "ADP Error - sequence number too high"
+#define AdpMess_SeqLow "ADP Error - sequence number too low"
+#define AdpMess_TimeoutOnOpen "ADP Error - target did not respond"
+#define AdpMess_AbandonBootWait "abandoned wait for late startup"
+#define AdpMess_LateStartup "Target compiled with LATE_STARTUP set.\n" \
+ "Waiting for target...\n" \
+ "Press <Ctrl-C> to abort.\n"
+#define AdpMessLen_LateStartup (3*80)
+#define AdpMess_NewAgentStarting "New Debug Agent about to start.\n"
+
+#endif /* ndef angsd_adperr_h */
+
+/* EOF adperr.h */
diff --git a/gdb/rdi-share/angel.h b/gdb/rdi-share/angel.h
new file mode 100644
index 00000000000..60a5f31720f
--- /dev/null
+++ b/gdb/rdi-share/angel.h
@@ -0,0 +1,177 @@
+/*
+ * Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
+ *
+ * This software may be freely used, copied, modified, and distributed
+ * provided that the above copyright notice is preserved in all copies of the
+ * software.
+ */
+
+/*> angel.h <*/
+/*---------------------------------------------------------------------------*/
+/* This header file is the main holder for the declarations and
+ * prototypes for the core Angel system. Some Angel concepts are
+ * described at the start of this file to ensure that a complete view
+ * of the Angel world can be derived purely from the source.
+ *
+ * $Revision$
+ * $Date$
+ *
+ *
+ * NOTE: Currently the Angel source is designed to be simple,
+ * understandable and easy to port to new hardware platforms. However,
+ * this does not always yield the highest performing system. The
+ * current layered approach introduces an overhead to the performance
+ * of the system. In a true commercial target, this code should be
+ * re-designed to build a system where the Angel logical message
+ * system, device driver and hardware accesses are merged to provide
+ * the best performance.
+ */
+/*---------------------------------------------------------------------------*/
+/* Angel overview:
+
+... some comments describing Angel ...
+
+ * Angel is designed as a kit-of-parts that can be used to provide
+ * run-time support for the development of ARM applications. The main
+ * core of Angel is in providing support for the "debug" message
+ * communication with a host system. These messages do not just cover
+ * debugging ARM processes, but also the process of downloading ARM
+ * programs or attaching to executing processes on the target.
+ *
+ * A stand-alone ROM based Angel world is the basic starting point for
+ * a system, since it will allow programs to be downloaded to the
+ * target. The ROM version of Angel will provide the generic debug
+ * support, but no system specific routines. The preferred method of
+ * using Angel is as a link library. This ensures that applications
+ * carry with them the Angel routines necessary to support debugging
+ * (and also ensure that the Angel version is up-to-date, independant
+ * of the version in the target ROM). Eventually, once a program has
+ * been fully debugged, a ROMmed version of the program can be
+ * generated with the Angel code being provided in the application.
+
+.. more comments ..
+
+ * The standard Angel routines do *NOT* perform any dynamic memory
+ * allocation. To simplify the source, and aid the porting to a non C
+ * library world, memory is either pre-allocated (as build-time
+ * globals) or actually given to the particular Angel routine by the
+ * active run-time. This ensures that the interaction between Angel
+ * and the target O/S is minimised.
+ *
+ * Notes: We sub-include more header files to keep the source
+ * modular. Since Angel is a kit-of-parts alternative systems may need
+ * to change the prototypes of particular functions, whilst
+ * maintaining a fixed external interface. e.g. using the standard
+ * DEBUG messages, but with a different communications world.
+ */
+/*---------------------------------------------------------------------------*/
+
+#ifndef __angel_h
+#define __angel_h
+
+/*---------------------------------------------------------------------------*/
+/*-- Global Angel definitions and manifests ---------------------------------*/
+/*---------------------------------------------------------------------------*/
+/* When building Angel we may not include the standard library
+ * headers. However, it is useful coding using standard macro names
+ * since it makes the code easier to understand.
+ */
+
+typedef unsigned int word ;
+typedef unsigned char byte ;
+
+/* The following typedefs can be used to access I/O registers: */
+typedef volatile unsigned int vuword ;
+typedef volatile unsigned char vubyte ;
+
+/*
+ * The following typedefs are used when defining objects that may also
+ * be created on a host system, where the word size is not
+ * 32bits. This ensures that the same data values are manipulated.
+ */
+#ifdef TARGET
+typedef unsigned int unsigned32;
+typedef signed int signed32;
+typedef int int32;
+
+typedef unsigned short int unsigned16;
+typedef signed short int signed16;
+
+/*
+ * yet another solution for the bool/boolean problem, this one is
+ * copied from Scott's modifications to clx/host.h
+ */
+# ifdef IMPLEMENT_BOOL_AS_ENUM
+ enum _bool { _false, _true };
+# define _bool enum _bool
+# elif defined(IMPLEMENT_BOOL_AS_INT) || !defined(__cplusplus)
+# define _bool int
+# define _false 0
+# define _true 1
+# endif
+
+# ifdef _bool
+# define bool _bool
+# endif
+
+# ifndef true
+# define true _true
+# define false _false
+# endif
+
+# ifndef YES
+# define YES true
+# define NO false
+# endif
+
+# undef TRUE /* some OSF headers define as 1 */
+# define TRUE true
+
+# undef FALSE /* some OSF headers define as 1 */
+# define FALSE false
+
+# ifndef NULL
+# define NULL 0
+# endif
+
+#else
+
+# include "host.h"
+
+#endif
+
+#ifndef IGNORE
+# define IGNORE(x) ((x)=(x))
+#endif
+
+/* The following typedef allows us to cast between integral and
+ * function pointers. This isn't allowed by direct casting when
+ * conforming to the ANSI spec.
+ */
+typedef union ansibodge
+{
+ word w ;
+ word *wp ;
+ void *vp ;
+ byte *bp ;
+ void (*vfn)(void) ;
+ word (*wfn)(void) ;
+ int (*ifn)(void) ;
+ byte (*bfn)(void) ;
+} ansibodge ;
+
+/*---------------------------------------------------------------------------*/
+
+/* The amount setup aside by the run-time system for stack overflow
+ * handlers to execute in. This must be at least 256bytes, since that
+ * value is assumed by the current ARM Ltd compiler.
+ * This space is _only_ kept for the USR stack, not any of the privileged
+ * mode stacks, as stack overflow on these is always fatal - there is
+ * no point attemptingto recover. In addition is is important that
+ * Angel should keep privileged stack space requirements to a minimum.
+ */
+#define APCS_STACKGUARD 256
+
+#endif /* __angel_h */
+
+/* EOF angel.h */
diff --git a/gdb/rdi-share/ardi.c b/gdb/rdi-share/ardi.c
new file mode 100644
index 00000000000..f61f7242f73
--- /dev/null
+++ b/gdb/rdi-share/ardi.c
@@ -0,0 +1,2672 @@
+/*
+ * Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
+ *
+ * This software may be freely used, copied, modified, and distributed
+ * provided that the above copyright notice is preserved in all copies of the
+ * software.
+ */
+
+/*
+ * ARDI.c
+ * Angel Remote Debug Interface
+ *
+ *
+ * $Revision$
+ * $Date$
+ *
+ * This file is based on /plg/pisd/rdi.c, but instead of using RDP it uses
+ * ADP messages.
+ */
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#define uint HIDE_HPs_uint
+#include <signal.h>
+#undef uint
+
+
+#include "endian.h"
+#include "ardi.h"
+#include "buffers.h"
+#include "channels.h"
+#include "hostchan.h"
+#include "host.h"
+#include "bytesex.h"
+#include "dbg_cp.h"
+#include "adp.h"
+#include "hsys.h"
+#include "logging.h"
+#include "msgbuild.h"
+#include "rxtx.h"
+#include "devsw.h"
+#include "params.h"
+
+#ifdef COMPILING_ON_WINDOWS
+# define IGNORE(x) (x = x) /* must go after #includes to work on Windows */
+#endif
+#define NOT(x) (!(x))
+
+#define ADP_INITIAL_TIMEOUT_PERIOD 5
+
+static volatile int executing;
+static int rdi_log = 0 ; /* debugging ? */
+
+/* we need a starting point for our first buffers, this is a safe one */
+int Armsd_BufferSize = ADP_BUFFER_MIN_SIZE;
+int Armsd_LongBufSize = ADP_BUFFER_MIN_SIZE;
+
+#ifdef WIN32
+ extern int interrupted;
+ extern int swiprocessing;
+#endif
+
+static char dummycline = 0;
+char *ardi_commandline = &dummycline ; /* exported in ardi.h */
+
+extern unsigned int heartbeat_enabled;
+
+static unsigned char *cpwords[16];
+
+typedef struct stoppedProcListElement {
+ struct stoppedProcListElement *next;
+ angel_RDI_TargetStoppedProc *fn;
+ void *arg;
+} stoppedProcListElement;
+
+static stoppedProcListElement *stopped_proc_list=NULL;
+
+const struct Dbg_HostosInterface *angel_hostif;
+static hsys_state *hstate;
+
+static void angel_DebugPrint(const char *format, ...)
+{ va_list ap;
+ va_start(ap, format);
+ angel_hostif->dbgprint(angel_hostif->dbgarg, format, ap);
+ va_end(ap);
+}
+
+#ifdef RDI_VERBOSE
+#define TracePrint(s) \
+ if (rdi_log & 2) angel_DebugPrint("\n"); \
+ if (rdi_log & 1) angel_DebugPrint s
+#else
+#define TracePrint(s)
+#endif
+
+typedef struct receive_dbgmsg_state {
+ volatile int received;
+ Packet *packet;
+} receive_dbgmsg_state;
+
+static receive_dbgmsg_state dbgmsg_state;
+
+static void receive_debug_packet(Packet *packet, void *stateptr)
+{
+ receive_dbgmsg_state *state = stateptr;
+
+ state->packet = packet;
+ state->received = 1;
+}
+
+static int register_debug_message_handler(void)
+{
+ int err;
+ dbgmsg_state.received = 0;
+
+ err = Adp_ChannelRegisterRead(CI_HADP, receive_debug_packet, &dbgmsg_state);
+#ifdef DEBUG
+ if (err!=adp_ok) angel_DebugPrint("register_debug_message_handler failed %i\n", err);
+#endif
+ return err;
+}
+
+
+static int wait_for_debug_message(int *rcode, int *debugID,
+ int *OSinfo1, int *OSinfo2,
+ int *status, Packet **packet)
+{
+ unsigned int reason;
+
+#ifdef DEBUG
+ angel_DebugPrint("wait_for_debug_message waiting for %X\n", *rcode);
+#endif
+
+ for ( ; dbgmsg_state.received == 0 ; )
+ Adp_AsynchronousProcessing(async_block_on_read);
+
+#ifdef DEBUG
+ angel_DebugPrint("wait_for_debug_message got packet\n");
+#endif
+
+ *packet = dbgmsg_state.packet;
+
+ Adp_ChannelRegisterRead(CI_HADP, NULL, NULL);
+
+ /*
+ * TODO:
+ * If ADP_Unrecognised return error.
+ * If ADP_Acknowledge - handle appropriately.
+ * If expected message read arguments and return RDIError_NoError.
+ * Note: if RDIError occurs then the data values returned are junk
+ */
+
+ unpack_message(BUFFERDATA((*packet)->pk_buffer), "%w%w%w%w%w", &reason, debugID,
+ OSinfo1, OSinfo2, status);
+ if (reason&0xffffff == ADP_HADPUnrecognised)
+ return RDIError_UnimplementedMessage;
+ if (reason != (unsigned ) *rcode) {
+ if((reason&0xffffff) == ADP_HADPUnrecognised)
+ return RDIError_UnimplementedMessage;
+ else {
+ angel_DebugPrint("ARDI ERROR: Expected reasoncode %x got reasoncode %x.\n",
+ *rcode, reason);
+ return RDIError_Error;
+ }
+ }
+ else
+ return RDIError_NoError;
+ return RDIError_Error; /* stop a pesky ANSI compiler warning */
+}
+
+
+/*
+ * Handler and registration for logging messages from target
+ */
+static void TargetLogCallback( Packet *packet, void *state )
+{
+ p_Buffer reply = BUFFERDATA(packet->pk_buffer);
+ unsigned int len = packet->pk_length;
+ IGNORE(state);
+ angel_hostif->write(angel_hostif->hostosarg,
+ (char *)reply, len - CHAN_HEADER_SIZE);
+ DevSW_FreePacket(packet);
+
+ packet = DevSW_AllocatePacket(4); /* better not ask for 0 */
+ /* the reply is the ACK - any contents are ignored */
+ if (packet != NULL)
+ Adp_ChannelWrite( CI_TLOG, packet );
+}
+
+static void TargetLogInit( void )
+{
+ AdpErrs err = Adp_ChannelRegisterRead( CI_TLOG, TargetLogCallback, NULL );
+
+#ifdef DEBUG
+ if (err != adp_ok)
+ angel_DebugPrint("CI_TLOG RegisterRead failed %d\n", err);
+#else
+ IGNORE(err);
+#endif
+}
+
+/*----------------------------------------------------------------------*/
+/*----angel_RDI_open-----------------------------------------------------*/
+/*----------------------------------------------------------------------*/
+
+typedef struct NegotiateState {
+ bool negotiate_resp;
+ bool negotiate_ack;
+ bool link_check_resp;
+ ParameterConfig *accepted_config;
+} NegotiateState;
+
+static void receive_negotiate(Packet *packet, void *stateptr)
+{
+ unsigned reason, debugID, OSinfo1, OSinfo2, status;
+ NegotiateState *n_state = (NegotiateState *)stateptr;
+ p_Buffer reply = BUFFERDATA(packet->pk_buffer);
+
+ unpack_message( reply, "%w%w%w%w",
+ &reason, &debugID, &OSinfo1, &OSinfo2 );
+ reply += ADP_DEFAULT_HEADER_SIZE;
+
+#ifdef DEBUG
+ angel_DebugPrint( "receive_negotiate: reason %x\n", reason );
+#endif
+
+ switch ( reason )
+ {
+ case ADP_ParamNegotiate | TtoH:
+ {
+ n_state->negotiate_resp = TRUE;
+
+ status = GET32LE( reply );
+ reply += sizeof(word);
+#ifdef DEBUG
+ angel_DebugPrint( "ParamNegotiate status %u\n", status );
+#endif
+ if ( status == RDIError_NoError )
+ {
+ if ( Angel_ReadParamConfigMessage(
+ reply, n_state->accepted_config ) )
+ n_state->negotiate_ack = TRUE;
+ }
+ break;
+ }
+
+ case ADP_LinkCheck | TtoH:
+ {
+#ifdef DEBUG
+ angel_DebugPrint( "PONG!\n" );
+#endif
+ n_state->link_check_resp = TRUE;
+ break;
+ }
+
+ default:
+ {
+#ifdef DEBUG
+ angel_DebugPrint( "Unexpected!\n" );
+#endif
+ break;
+ }
+ }
+ DevSW_FreePacket( packet );
+}
+
+# include <sys/types.h>
+#ifdef __unix
+# include <sys/time.h>
+#else
+# include <time.h>
+#endif
+
+/*
+ * convert a config into a single-valued options list
+ */
+static ParameterOptions *config_to_options( const ParameterConfig *config )
+{
+ unsigned int num_params;
+ size_t size;
+ ParameterOptions *base_p;
+
+ num_params = config->num_parameters;
+ size =
+ sizeof(ParameterOptions)
+ + num_params*(sizeof(ParameterList) + sizeof(unsigned int));
+ base_p = malloc( size );
+
+ if ( base_p != NULL )
+ {
+ unsigned int u;
+ ParameterList *list_p =
+ (ParameterList *)((char *)base_p + sizeof(ParameterOptions));
+ unsigned int *option_p =
+ (unsigned int *)(list_p + num_params);
+
+ base_p->num_param_lists = num_params;
+ base_p->param_list = list_p;
+
+ for ( u = 0; u < num_params; ++u )
+ {
+ option_p[u] = config->param[u].value;
+ list_p[u].type = config->param[u].type;
+ list_p[u].num_options = 1;
+ list_p[u].option = &option_p[u];
+ }
+ }
+
+ return base_p;
+}
+
+static AdpErrs negotiate_params( const ParameterOptions *user_options )
+{
+ Packet *packet;
+ unsigned int count;
+ static Parameter params[AP_NUM_PARAMS];
+ static ParameterConfig accepted_config = { AP_NUM_PARAMS, params };
+
+ time_t t;
+
+ static volatile NegotiateState n_state = {
+ FALSE, FALSE, FALSE, &accepted_config };
+
+#ifdef DEBUG
+ angel_DebugPrint( "negotiate_params\n" );
+#endif
+
+ Adp_ChannelRegisterRead( CI_HBOOT, receive_negotiate, (void *)&n_state );
+
+ packet = (Packet *)DevSW_AllocatePacket(Armsd_BufferSize);
+ count = msgbuild( BUFFERDATA(packet->pk_buffer), "%w%w%w%w",
+ ADP_ParamNegotiate | HtoT, 0,
+ ADP_HandleUnknown, ADP_HandleUnknown );
+ count += Angel_BuildParamOptionsMessage(
+ BUFFERDATA(packet->pk_buffer) + count, user_options );
+ packet->pk_length = count;
+ Adp_ChannelWriteAsync( CI_HBOOT, packet );
+
+#ifdef DEBUG
+ angel_DebugPrint( "sent negotiate packet\n" );
+#endif
+
+ t=time(NULL);
+
+ do {
+ Adp_AsynchronousProcessing(async_block_on_nothing);
+
+ if ((time(NULL)-t) > ADP_INITIAL_TIMEOUT_PERIOD) {
+ return adp_timeout_on_open;
+ }
+ } while ( ! n_state.negotiate_resp );
+
+ if ( n_state.negotiate_ack )
+ {
+ /* select accepted config */
+ Adp_Ioctl( DC_SET_PARAMS, (void *)n_state.accepted_config );
+
+ /*
+ * 960430 KWelton
+ *
+ * There is a race in the renegotiation protocol: the
+ * target has to have had time to load new config before
+ * we send the link check packet - insert a deliberate
+ * pause (100ms) to give the target some time
+ */
+ Adp_delay(100000);
+
+ /* do link check */
+ msgsend( CI_HBOOT, "%w%w%w%w", ADP_LinkCheck | HtoT, 0,
+ ADP_HandleUnknown, ADP_HandleUnknown );
+#ifdef DEBUG
+ angel_DebugPrint("sent link check\n");
+#endif
+
+ do {
+ Adp_AsynchronousProcessing(async_block_on_read);
+ } while ( ! n_state.link_check_resp );
+ Adp_initSeq();
+ }
+ return adp_ok;
+}
+
+static int late_booted = FALSE;
+static bool ardi_handler_installed = FALSE;
+
+#ifdef __unix
+static struct sigaction old_action;
+#else
+static void (*old_handler)();
+#endif
+
+static bool boot_interrupted = FALSE;
+
+static void ardi_sigint_handler(int sig) {
+#ifdef DEBUG
+ if (sig != SIGINT)
+ angel_DebugPrint("Expecting SIGINT got %d.\n", sig);
+#else
+ IGNORE(sig);
+#endif
+ boot_interrupted = TRUE;
+#ifndef __unix
+ signal(SIGINT, ardi_sigint_handler);
+#endif
+}
+
+static void install_ardi_handler( void ) {
+ if (!ardi_handler_installed) {
+ /* install a new Ctrl-C handler so we can abandon waiting */
+#ifdef __unix
+ struct sigaction new_action;
+ sigemptyset(&new_action.sa_mask);
+ new_action.sa_handler = ardi_sigint_handler;
+ new_action.sa_flags = 0;
+ sigaction(SIGINT, &new_action, &old_action);
+#else
+ old_handler = signal(SIGINT, ardi_sigint_handler);
+#endif
+ ardi_handler_installed = TRUE;
+ }
+}
+
+static int angel_RDI_errmess(char *buf, int blen, int errnum);
+
+static void receive_reset_acknowledge(Packet *packet, void *stateptr) {
+ unsigned reason, debugID, OSinfo1, OSinfo2, status;
+ IGNORE(stateptr);
+
+ unpack_message(BUFFERDATA(packet->pk_buffer), "%w%w%w%w%w", &reason, &debugID,
+ &OSinfo1, &OSinfo2, &status);
+ if (reason==(ADP_Reset | TtoH) && status==AB_NORMAL_ACK) {
+#ifdef DEBUG
+ angel_DebugPrint("DEBUG: Successfully received normal reset acknowledgement\n");
+ late_booted = FALSE;
+#endif
+ } else if (reason==(ADP_Reset | TtoH) && status==AB_LATE_ACK) {
+ char late_msg[AdpMessLen_LateStartup];
+ int late_len;
+#ifdef DEBUG
+ angel_DebugPrint("DEBUG: Successfully received LATE reset acknowledgement\n");
+#endif
+ late_booted = TRUE;
+ install_ardi_handler();
+ late_len = angel_RDI_errmess(late_msg,
+ AdpMessLen_LateStartup, adp_late_startup);
+ angel_hostif->write(angel_hostif->hostosarg, late_msg, late_len);
+ } else {
+#ifdef DEBUG
+ angel_DebugPrint("DEBUG: Bad reset ack: reason=%8X, status=%8X\n", reason, status);
+#endif
+ }
+ DevSW_FreePacket(packet);
+}
+
+static int booted_not_received;
+static unsigned int angel_version;
+static unsigned int adp_version;
+static unsigned int arch_info;
+static unsigned int cpu_info;
+static unsigned int hw_status;
+
+static void receive_booted(Packet *packet, void *stateptr) {
+ unsigned reason, debugID, OSinfo1, OSinfo2, banner_length, bufsiz, longsiz;
+ unsigned i, count;
+
+ IGNORE(stateptr);
+
+ count = unpack_message(BUFFERDATA(packet->pk_buffer),
+ "%w%w%w%w%w%w%w%w%w%w%w%w",
+ &reason, &debugID, &OSinfo1, &OSinfo2, &bufsiz, &longsiz,
+ &angel_version, &adp_version,
+ &arch_info, &cpu_info, &hw_status, &banner_length);
+ if (reason==(ADP_Booted | TtoH)) {
+#ifdef MONITOR_DOWNLOAD_PACKETS
+ angel_DebugPrint("DEBUG: Successfully received Booted\n");
+ angel_DebugPrint(" cpu_info=%8X, hw_status=%8X, bufsiz=%d, longsiz=%d\n",
+ cpu_info, hw_status, bufsiz, longsiz);
+#endif
+ /* Get the banner from the booted message */
+ for (i=0; i<banner_length; i++)
+ angel_hostif->writec(angel_hostif->hostosarg,
+ (BUFFERDATA(packet->pk_buffer)+count)[i]);
+
+ booted_not_received=0;
+#ifndef NO_HEARTBEAT
+ heartbeat_enabled = TRUE;
+#endif
+ Armsd_BufferSize = bufsiz + CHAN_HEADER_SIZE;
+ Armsd_LongBufSize = longsiz + CHAN_HEADER_SIZE;
+ } else {
+#ifdef DEBUG
+ angel_DebugPrint("DEBUG: Bad Booted msg: reason=%8X\n", reason);
+#endif
+ }
+ DevSW_FreePacket(packet);
+}
+
+
+/* forward declaration */
+static int angel_negotiate_defaults( void );
+
+/* Open communications. */
+int angel_RDI_open(
+ unsigned type, Dbg_ConfigBlock const *config,
+ Dbg_HostosInterface const *hostif, struct Dbg_MCState *dbg_state)
+{
+ Packet *packet;
+ int status, reasoncode, debugID, OSinfo1, OSinfo2, err;
+ ParameterOptions *user_options = NULL;
+
+ time_t t;
+
+ IGNORE( dbg_state );
+
+ if ((type & 1) == 0) {
+ /* cold start */
+ if (hostif != NULL) {
+ angel_hostif = hostif;
+ err = HostSysInit(hostif, &ardi_commandline, &hstate);
+ if (err != RDIError_NoError) {
+#ifdef DEBUG
+ angel_DebugPrint("DEBUG: HostSysInit error %i\n",err);
+#endif
+ return err;
+ }
+ }
+ TargetLogInit();
+ }
+
+#ifdef DEBUG
+ angel_DebugPrint("DEBUG: Buffer allocated in angel_RDI_open(type=%i).\n",type);
+#endif
+
+ if ((type & 1) == 0) {
+ /* cold start */
+ unsigned endian;
+ Adp_Ioctl( DC_GET_USER_PARAMS, (void *)&user_options );
+ if ( user_options != NULL ) {
+ err = negotiate_params( user_options );
+ if (err != adp_ok) return err;
+ }
+ else {
+ ParameterConfig *default_config = NULL;
+ Adp_Ioctl( DC_GET_DEFAULT_PARAMS, (void *)&default_config );
+ if ( default_config != NULL ) {
+ ParameterOptions *default_options = config_to_options(default_config);
+ err = negotiate_params( default_options );
+ if (err != adp_ok) return err;
+ }
+ }
+
+ /* Register handlers before sending any messages */
+ booted_not_received=1;
+ Adp_ChannelRegisterRead(CI_HBOOT, receive_reset_acknowledge, NULL);
+ Adp_ChannelRegisterRead(CI_TBOOT, receive_booted, NULL);
+ endian = 0;
+ if (config!=NULL) {
+ if (config->bytesex & RDISex_Little) endian |= ADP_BootHostFeature_LittleEnd;
+ if (config->bytesex & RDISex_Big) endian |= ADP_BootHostFeature_BigEnd;
+ }
+ msgsend(CI_HBOOT,"%w%w%w%w%w", ADP_Reset | HtoT, 0,
+ ADP_HandleUnknown, ADP_HandleUnknown, endian);
+#ifdef DEBUG
+ angel_DebugPrint("DEBUG: Transmitted Reset message in angel_RDI_open.\n");
+#endif
+
+ /* We will now either get an acknowledgement for the Reset message
+ * or if the target was started after the host, we will get a
+ * rebooted message first.
+ */
+
+#ifdef DEBUG
+ angel_DebugPrint("DEBUG: waiting for a booted message\n");
+#endif
+
+ {
+ boot_interrupted = FALSE;
+
+ if (late_booted)
+ install_ardi_handler();
+
+ t=time(NULL);
+
+ do {
+ Adp_AsynchronousProcessing(async_block_on_nothing);
+ if ((time(NULL)-t) > ADP_INITIAL_TIMEOUT_PERIOD && !late_booted) {
+ return adp_timeout_on_open;
+ }
+ } while (booted_not_received && !boot_interrupted);
+
+ if (ardi_handler_installed)
+ {
+ /* uninstall our Ctrl-C handler */
+#ifdef __unix
+ sigaction(SIGINT, &old_action, NULL);
+#else
+ signal(SIGINT, old_handler);
+#endif
+ }
+
+ if (boot_interrupted) {
+ angel_negotiate_defaults();
+ return adp_abandon_boot_wait;
+ }
+ }
+
+ booted_not_received=1;
+ Adp_ChannelRegisterRead(CI_HBOOT, NULL, NULL);
+
+ /* Leave the booted handler installed */
+ msgsend(CI_TBOOT, "%w%w%w%w%w", ADP_Booted | HtoT, 0,
+ ADP_HandleUnknown, ADP_HandleUnknown, 0);
+ Adp_initSeq();
+#ifdef DEBUG
+ angel_DebugPrint("DEBUG: Transmitted ADP_Booted acknowledgement.\n");
+ angel_DebugPrint("DEBUG: Boot sequence completed, leaving angel_RDI_open.\n");
+#endif
+
+ return (hw_status & ADP_CPU_BigEndian )? RDIError_BigEndian :
+ RDIError_LittleEndian;
+ }
+ else {
+ /* warm start */
+ register_debug_message_handler();
+
+ msgsend(CI_HADP, "%w%w%w%w",
+ ADP_InitialiseApplication | HtoT, 0,
+ ADP_HandleUnknown, ADP_HandleUnknown);
+#ifdef DEBUG
+ angel_DebugPrint("DEBUG: Transmitted Initialise Application\n");
+#endif
+ reasoncode=ADP_InitialiseApplication | TtoH;
+ err = wait_for_debug_message(&reasoncode, &debugID, &OSinfo1, &OSinfo2,
+ &status, &packet);
+ if (err != RDIError_NoError) return err;
+ return status;
+ }
+ return -1;
+}
+
+
+/*----------------------------------------------------------------------*/
+/*----angel_RDI_close----------------------------------------------------*/
+/*----------------------------------------------------------------------*/
+
+static int angel_negotiate_defaults( void ) {
+ int err = adp_ok;
+ ParameterConfig *default_config = NULL;
+ Adp_Ioctl( DC_GET_DEFAULT_PARAMS, (void *)&default_config );
+ if ( default_config != NULL ) {
+ ParameterOptions *default_options = config_to_options(default_config);
+ err = negotiate_params( default_options );
+ free( default_options );
+ }
+ return err;
+}
+
+int angel_RDI_close(void) {
+/*Angel host exit */
+ int err;
+ int status,debugID, OSinfo1,OSinfo2;
+ int reason;
+ Packet *packet = NULL;;
+#ifdef DEBUG
+ angel_DebugPrint("DEBUG: Entered angel_RDI_Close.\n");
+#endif
+
+ register_debug_message_handler();
+
+ heartbeat_enabled = FALSE;
+
+ err = msgsend(CI_HADP,"%w%w%w%w",ADP_End | HtoT,0,
+ ADP_HandleUnknown, ADP_HandleUnknown);
+ if (err != RDIError_NoError) return err;
+ reason = ADP_End | TtoH;
+ err = wait_for_debug_message(&reason, &debugID, &OSinfo1, &OSinfo2,
+ &status, &packet);
+ DevSW_FreePacket(packet);
+ if (err != RDIError_NoError) return err;
+ if (status == RDIError_NoError) {
+ err = angel_negotiate_defaults();
+ if (err != adp_ok) return err;
+ Adp_Ioctl( DC_RESET, NULL ); /* just to be safe */
+ return HostSysExit(hstate);
+ }
+ else
+ return status;
+}
+
+
+/*----------------------------------------------------------------------*/
+/*----angel_RDI_read-----------------------------------------------------*/
+/*----------------------------------------------------------------------*/
+
+/* Read memory contents from target to host: use ADP_Read */
+int angel_RDI_read(ARMword source, void *dest, unsigned *nbytes)
+{
+ Packet *packet=NULL;
+ int len; /* Integer to hold message length. */
+ unsigned int nbtogo = *nbytes, nbinpacket, nbdone=0;
+ int rnbytes = 0, status, reason, debugID, OSinfo1, OSinfo2, err;
+ unsigned int maxlen = Armsd_BufferSize-CHAN_HEADER_SIZE-ADP_ReadHeaderSize;
+
+ /* Print debug trace information, this is just copied straight from rdi.c
+ and I can see no reason why it should have to be changed. */
+ TracePrint(("angel_RDI_read: source=%.8lx dest=%p nbytes=%.8x\n",
+ (unsigned long)source, dest, *nbytes));
+ if (*nbytes == 0) return RDIError_NoError; /* Read nothing - easy! */
+ /* check the buffer size */
+ while (nbtogo >0) {
+ register_debug_message_handler();
+
+ nbinpacket = (nbtogo <= maxlen) ? nbtogo : maxlen;
+ len = msgsend(CI_HADP, "%w%w%w%w%w%w", ADP_Read | HtoT, 0,
+ ADP_HandleUnknown, ADP_HandleUnknown, source+nbdone,
+ nbinpacket);
+ reason=ADP_Read | TtoH;
+ err = wait_for_debug_message(&reason, &debugID, &OSinfo1, &OSinfo2,
+ &status, &packet);
+ TracePrint(("angel_RDI_read: nbinpacket =%d status=%08x err = %d\n",
+ nbinpacket,status,err));
+ if (err != RDIError_NoError) return err; /* Was there an error? */
+ if (status == RDIError_NoError){
+ rnbytes += PREAD(LE,(unsigned int *)(BUFFERDATA(packet->pk_buffer)+20));
+ TracePrint(("angel_RDI_read: rnbytes = %d\n",rnbytes));
+ memcpy(((unsigned char *)dest)+nbdone, BUFFERDATA(packet->pk_buffer)+24,
+ nbinpacket);
+ }
+ nbdone += nbinpacket;
+ nbtogo -= nbinpacket;
+ }
+ *nbytes -= rnbytes;
+ return status;
+}
+
+
+/*----------------------------------------------------------------------*/
+/*----angel_RDI_write----------------------------------------------------*/
+/*----------------------------------------------------------------------*/
+
+/* Transfer memory block from host to target. Use ADP_Write>. */
+int angel_RDI_write(const void *source, ARMword dest, unsigned *nbytes)
+{
+ Packet *packet;/* Message buffers. */
+ unsigned int len, nbtogo = *nbytes, nboffset = 0, nbinpacket;
+ int status, reason, debugID, OSinfo1, OSinfo2, err;
+ unsigned int maxlen = Armsd_LongBufSize-CHAN_HEADER_SIZE-ADP_WriteHeaderSize;
+
+ TracePrint(("angel_RDI_write: source=%p dest=%.8lx nbytes=%.8x\n",
+ source, (unsigned long)dest, *nbytes));
+
+ if (*nbytes == 0) return RDIError_NoError;
+
+ *nbytes = 0;
+ while (nbtogo > 0) {
+ packet = (Packet *) DevSW_AllocatePacket(Armsd_LongBufSize);
+ nbinpacket = (nbtogo <= maxlen) ? nbtogo : maxlen;
+ len = msgbuild(BUFFERDATA(packet->pk_buffer), "%w%w%w%w%w%w",
+ ADP_Write | HtoT, 0, ADP_HandleUnknown,
+ ADP_HandleUnknown, dest+nboffset, nbinpacket);
+ /* Copy the data into the packet. */
+
+ memcpy(BUFFERDATA(packet->pk_buffer)+len,
+ ((const unsigned char *) source)+nboffset, nbinpacket);
+ nboffset += nbinpacket;
+ packet->pk_length = nbinpacket+len;
+
+#ifdef MONITOR_DOWNLOAD_PACKETS
+ angel_DebugPrint("angel_RDI_write packet size=%i, bytes done=%i\n",
+ nbinpacket, nboffset);
+#endif
+
+ register_debug_message_handler();
+ Adp_ChannelWrite(CI_HADP, packet);
+ reason=ADP_Write | TtoH;
+ err = wait_for_debug_message(&reason, &debugID, &OSinfo1, &OSinfo2,
+ &status, &packet);
+ nbtogo -= nbinpacket;
+ if (err != RDIError_NoError) return err;
+ if (status == RDIError_NoError)
+ *nbytes += nbinpacket;
+
+ DevSW_FreePacket(packet);
+ }
+ return status;
+}
+
+
+/*----------------------------------------------------------------------*/
+/*----angel_RDI_CPUread--------------------------------------------------*/
+/*----------------------------------------------------------------------*/
+
+/* Reads the values of registers in the CPU, uses ADP_CPUwrite. */
+int angel_RDI_CPUread(unsigned mode, unsigned long mask, ARMword *buffer)
+{
+ unsigned int i, j;
+ Packet *packet = NULL;
+ int err, status, reason, debugID, OSinfo1, OSinfo2;
+#ifdef DEBUG
+ angel_DebugPrint("DEBUG: Entered angel_RDI_CPUread.\n");
+#endif
+ for (i=0, j=0 ; i < RDINumCPURegs ; i++)
+ if (mask & (1L << i)) j++; /* Count the number of registers. */
+
+ register_debug_message_handler();
+ msgsend(CI_HADP, "%w%w%w%w%c%w", ADP_CPUread | HtoT, 0,
+ ADP_HandleUnknown, ADP_HandleUnknown, mode, mask);
+ reason = ADP_CPUread | TtoH;
+ err = wait_for_debug_message(&reason, &debugID, &OSinfo1, &OSinfo2,
+ &status, &packet);
+ if (err != RDIError_NoError) {
+ DevSW_FreePacket(packet);
+ return err;
+ }
+ if(status == RDIError_NoError) {
+ for (i=0; i<j; i++)
+ buffer[i] = GET32LE(BUFFERDATA(packet->pk_buffer)+20+(i*4));
+ TracePrint(("angel_RDI_CPUread: mode=%.8x mask=%.8lx", mode, mask));
+ DevSW_FreePacket(packet);
+#ifdef RDI_VERBOSE
+ if (rdi_log & 1) {
+ unsigned k;
+ for (k = 0, j = 0 ; j <= 20 ; j++)
+ if (mask & (1L << j)) {
+ angel_DebugPrint("%c%.8lx",k%4==0?'\n':' ',
+ (unsigned long)buffer[k]);
+ k++ ;
+ }
+ angel_DebugPrint("\n") ;
+ }
+#endif
+
+ }
+ return status;
+}
+
+/*----------------------------------------------------------------------*/
+/*----angel_RDI_CPUwrite-------------------------------------------------*/
+/*----------------------------------------------------------------------*/
+
+/* Write CPU registers: use ADP_CPUwrite. */
+int angel_RDI_CPUwrite(unsigned mode, unsigned long mask,
+ ARMword const *buffer){
+
+ unsigned i, j, c;
+ Packet *packet;
+ int status, reason, debugID, OSinfo1, OSinfo2, err, len;
+
+ TracePrint(("angel_RDI_CPUwrite: mode=%.8x mask=%.8lx", mode, mask));
+#ifdef RDI_VERBOSE
+ if (rdi_log & 1) {
+ for (j = 0, i = 0 ; i <= 20 ; i++)
+ if (mask & (1L << i)) {
+ angel_DebugPrint("%c%.8lx",j%4==0?'\n':' ',
+ (unsigned long)buffer[j]);
+ j++ ;
+ }
+ angel_DebugPrint("\n") ;
+ }
+#endif
+ packet = (Packet *)DevSW_AllocatePacket(Armsd_BufferSize);
+ for (i=0, j=0; i < RDINumCPURegs ; i++)
+ if (mask & (1L << i)) j++; /* count the number of registers */
+
+ len = msgbuild(BUFFERDATA(packet->pk_buffer), "%w%w%w%w%b%w",
+ ADP_CPUwrite | HtoT, 0,
+ ADP_HandleUnknown, ADP_HandleUnknown, mode, mask);
+ for(c=0; c<j; c++)
+ PUT32LE(BUFFERDATA(packet->pk_buffer)+len+(c*4), buffer[c]);
+ packet->pk_length = len+(j*4);
+ register_debug_message_handler();
+
+ Adp_ChannelWrite(CI_HADP, packet);
+ reason = ADP_CPUwrite | TtoH;
+ err = wait_for_debug_message(&reason, &debugID, &OSinfo1, &OSinfo2,
+ &status, &packet);
+ unpack_message(BUFFERDATA(packet->pk_buffer), "%w%w%w%w%w", &reason, &debugID,
+ &OSinfo1, &OSinfo2, &status);
+ DevSW_FreePacket(packet);
+ if (err != RDIError_NoError)
+ return err; /* Was there an error? */
+ else
+ return status;
+ }
+
+
+/*----------------------------------------------------------------------*/
+/*----angel_RDI_CPread---------------------------------------------------*/
+/*----------------------------------------------------------------------*/
+
+/* Read coprocessor's internal state. See dbg_cp.h for help.
+ * Use ADP_CPRead.
+ * It would appear that the correct behaviour at this point is to leave
+ * the unpacking to a the caller and to simply copy the stream of data
+ * words into the buffer
+ */
+
+int angel_RDI_CPread(unsigned CPnum, unsigned long mask, ARMword *buffer){
+ Packet *packet = NULL;
+ int i, j, status, reasoncode, OSinfo1, OSinfo2, err, debugID;
+ unsigned char *rmap = cpwords[CPnum];
+ int n;
+#ifdef DEBUG
+ angel_DebugPrint("DEBUG: Entered angel_RDI_CPread.\n");
+#endif
+ if (rmap == NULL) return RDIError_UnknownCoPro;
+
+ register_debug_message_handler();
+ n = rmap[-1];
+ msgsend(CI_HADP, "%w%w%w%w%b%w", ADP_CPread | HtoT, 0,
+ ADP_HandleUnknown, ADP_HandleUnknown, CPnum, mask);
+ reasoncode=ADP_CPread | TtoH;
+ err = wait_for_debug_message(&reasoncode, &debugID, &OSinfo1, &OSinfo2,
+ &status, &packet);
+ if (err != RDIError_NoError) {
+ DevSW_FreePacket(packet);
+ return err; /* Was there an error? */
+ }
+ for (j=i=0; i < n ; i++) /* count the number of registers */
+ if (mask & (1L << i)) {
+ j++;
+ }
+ for (i=0; i<j; i++)
+ buffer[i] = PREAD32(LE, BUFFERDATA(packet->pk_buffer) + 20 + (i*4));
+ DevSW_FreePacket(packet);
+ TracePrint(("angel_RDI_CPread: CPnum=%.8x mask=%.8lx\n", CPnum, mask));
+#ifdef RDI_VERBOSE
+ if (rdi_log & 1) {
+ for (i = 0, j = 0; j < n ; j++) {
+ if (mask & (1L << j)) {
+ int nw = rmap[j];
+ angel_DebugPrint("%2d ", j);
+ while (--nw > 0)
+ angel_DebugPrint("%.8lx ", (unsigned long)buffer[i++]);
+ angel_DebugPrint("%.8lx\n", (unsigned long)buffer[i++]);
+ }
+ }
+ }
+#endif
+ return status;
+}
+
+
+/*----------------------------------------------------------------------*/
+/*----angel_RDI_CPwrite--------------------------------------------------*/
+/*----------------------------------------------------------------------*/
+
+/* Write coprocessor's internal state. See dbg_cp.h for help. Use
+ * ADP_CPwrite.
+ */
+
+int angel_RDI_CPwrite(unsigned CPnum, unsigned long mask,
+ ARMword const *buffer)
+{
+ Packet *packet = NULL;
+ int i, j, len, status, reason, OSinfo1, OSinfo2, err, debugID;
+ unsigned char *rmap = cpwords[CPnum];
+ int n;
+
+ if (rmap == NULL) return RDIError_UnknownCoPro;
+ n = rmap[-1];
+
+ TracePrint(("angel_RDI_CPwrite: CPnum=%d mask=%.8lx\n", CPnum, mask));
+
+#ifdef RDI_VERBOSE
+ if (rdi_log & 1) {
+ for (i = 0, j = 0; j < n ; j++)
+ if (mask & (1L << j)) {
+ int nw = rmap[j];
+ angel_DebugPrint("%2d ", j);
+ while (--nw > 0)
+ angel_DebugPrint("%.8lx ", (unsigned long)buffer[i++]);
+ angel_DebugPrint("%.8lx\n", (unsigned long)buffer[i++]);
+ }
+ }
+#endif
+
+ for (j=i=0; i < n ; i++) /* Count the number of registers. */
+ if (mask & (1L << i)) j++;
+ packet = DevSW_AllocatePacket(Armsd_BufferSize);
+ len = msgbuild(BUFFERDATA(packet->pk_buffer), "%w%w%w%w%c%w",
+ ADP_CPwrite | HtoT, 0,
+ ADP_HandleUnknown, ADP_HandleUnknown, CPnum, mask);
+ for(i=0; i<j; i++)
+ len+=msgbuild(BUFFERDATA(packet->pk_buffer) + len, "%w", buffer[i]);
+ packet->pk_length = len;
+ register_debug_message_handler();
+ Adp_ChannelWrite(CI_HADP, packet); /* Transmit message. */
+ reason=ADP_CPwrite | TtoH;
+ err = wait_for_debug_message(&reason, &debugID, &OSinfo1, &OSinfo2,
+ &status, &packet);
+ DevSW_FreePacket(packet);
+ if (err != RDIError_NoError)
+ return err;
+ else
+ return status;
+}
+
+
+/*----------------------------------------------------------------------*/
+/*----angel_RDI_pointinq-------------------------------------------------*/
+/*----------------------------------------------------------------------*/
+
+/* Do test calls to ADP_SetBreak/ADP_SetWatch to see if resources exist to
+ carry out request. */
+int angel_RDI_pointinq(ARMword *address, unsigned type, unsigned datatype,
+ ARMword *bound)
+{
+ Packet *packet = NULL;
+ int len, status, reason, OSinfo1, OSinfo2, err=RDIError_NoError;
+ /* stop a compiler warning */
+ int debugID, pointhandle;
+ TracePrint(
+ ("angel_RDI_pointinq: address=%.8lx type=%d datatype=%d bound=%.8lx ",
+ (unsigned long)*address, type, datatype, (unsigned long)*bound));
+ /* for a buffer. */
+ packet = DevSW_AllocatePacket(Armsd_BufferSize);
+ len = msgbuild(BUFFERDATA(packet->pk_buffer), "%w%w%w%w%w%b",
+ ((datatype == 0) ? ADP_SetBreak : ADP_SetWatch) | HtoT, 0,
+ ADP_HandleUnknown, ADP_HandleUnknown, address, type);
+ if (datatype == 0)
+ len += msgbuild(BUFFERDATA(packet->pk_buffer) + 21, "%w", bound);
+ else
+ len += msgbuild(BUFFERDATA(packet->pk_buffer) + 21, "%b%w", datatype, bound);
+
+ register_debug_message_handler();
+ packet->pk_length = len;
+ Adp_ChannelWrite(CI_HADP, packet);
+ reason = ((datatype == 0) ? ADP_SetBreak : ADP_SetWatch | TtoH);
+ err = wait_for_debug_message(&reason, &debugID, &OSinfo1, &OSinfo2,
+ &status, &packet);
+ if (err != RDIError_NoError) {
+ DevSW_FreePacket(packet);
+ return err; /* Was there an error? */
+ }
+ unpack_message(BUFFERDATA(packet->pk_buffer), "%w%w%w%w%w%w%w%w",
+ &reason, &debugID, &OSinfo1, &OSinfo2, &status,
+ &pointhandle, &address, &bound);
+ DevSW_FreePacket(packet);
+ return err;
+}
+
+
+/*----------------------------------------------------------------------*/
+/*----angel_RDI_setbreak-------------------------------------------------*/
+/*----------------------------------------------------------------------*/
+
+/* Set a breakpoint: Use ADP_SetBreak */
+int angel_RDI_setbreak(ARMword address, unsigned type, ARMword bound,
+ PointHandle *handle)
+{
+ int status, reason, OSinfo1, OSinfo2, err, debugID;
+ int tmpval, tmpaddr, tmpbnd;
+ Packet *packet;
+ TracePrint(("angel_RDI_setbreak address=%.8lx type=%d bound=%.8lx \n",
+ (unsigned long)address, type, (unsigned long)bound));
+
+ register_debug_message_handler();
+ msgsend(CI_HADP, "%w%w%w%w%w%b%w",
+ ADP_SetBreak| HtoT, 0, ADP_HandleUnknown,
+ ADP_HandleUnknown, address, type, bound);
+ reason = ADP_SetBreak |TtoH;
+ err = wait_for_debug_message(&reason, &debugID, &OSinfo1, &OSinfo2,
+ &status, &packet);
+ if (err != RDIError_NoError) {
+ DevSW_FreePacket(packet);
+ return err; /* Was there an error? */
+ }
+ /* Work around varargs problem... -sts */
+ unpack_message(BUFFERDATA(packet->pk_buffer), "%w%w%w%w%w%w%w%w",
+ &reason, &debugID, &OSinfo1, &OSinfo2, &status,
+ &tmpval, &tmpaddr, &tmpbnd);
+ *handle = tmpval;
+ address = tmpaddr;
+ bound = tmpbnd;
+ DevSW_FreePacket(packet);
+ if (status != RDIError_NoError) return status;
+ TracePrint(("returns handle %.8lx\n", (unsigned long)*handle));
+ return RDIError_NoError;
+}
+
+
+/*----------------------------------------------------------------------*/
+/*----angel_RDI_clearbreak-----------------------------------------------*/
+/*----------------------------------------------------------------------*/
+
+/* Clear a breakpoint: Use ADP_ClearBreak. */
+int angel_RDI_clearbreak(PointHandle handle)
+{
+ Packet *packet = NULL;
+ int status, reason, OSinfo1, OSinfo2, err, debugID;
+
+ TracePrint(("angel_RDI_clearbreak: handle=%.8lx\n", (unsigned long)handle));
+
+ register_debug_message_handler();
+ msgsend(CI_HADP, "%w%w%w%w%w",
+ ADP_ClearBreak| HtoT, 0, ADP_HandleUnknown,
+ ADP_HandleUnknown, handle);
+ reason = ADP_ClearBreak|TtoH;
+ err = wait_for_debug_message(&reason, &debugID, &OSinfo1, &OSinfo2,
+ &status, &packet);
+ if (err != RDIError_NoError) {
+ DevSW_FreePacket(packet);
+ angel_DebugPrint("***RECEIVE DEBUG MESSAGE RETURNED ERR = %d.\n", err);
+ return err; /* Was there an error? */
+ }
+ unpack_message(BUFFERDATA(packet->pk_buffer), "%w%w%w%w%w", &reason,
+ &debugID, &OSinfo1, &OSinfo2, &status);
+ DevSW_FreePacket(packet);
+#ifdef DEBUG
+ angel_DebugPrint("DEBUG: Clear Break completed OK.\n");
+#endif
+ return RDIError_NoError;
+}
+
+
+/*----------------------------------------------------------------------*/
+/*----angel_RDI_setwatch-------------------------------------------------*/
+/*----------------------------------------------------------------------*/
+
+/* Set a watchpoint: use ADP_SetWatch. */
+int angel_RDI_setwatch(ARMword address, unsigned type, unsigned datatype,
+ ARMword bound, PointHandle *handle)
+{
+ Packet *packet = NULL;
+ int status, reason, OSinfo1, OSinfo2, err, debugID;
+
+ TracePrint(("angel_RDI_setwatch: address=%.8lx type=%d bound=%.8lx ",
+ (unsigned long)address, type, (unsigned long)bound));
+
+ register_debug_message_handler();
+ msgsend(CI_HADP, "%w%w%w%w%w%b%b%w",
+ ADP_SetWatch| HtoT, 0, ADP_HandleUnknown,
+ ADP_HandleUnknown, address, type, datatype, bound);
+
+ reason = ADP_SetWatch | TtoH;
+ err = wait_for_debug_message(&reason, &debugID, &OSinfo1, &OSinfo2,
+ &status, &packet);
+ if (err != RDIError_NoError) {
+ DevSW_FreePacket(packet);
+ return err; /* Was there an error? */
+ }
+ unpack_message(BUFFERDATA(packet->pk_buffer), "%w%w%w%w%w%w%w%w",
+ &reason, &debugID, &OSinfo1, &OSinfo2, &status,
+ handle, &address, &bound);
+ DevSW_FreePacket(packet);
+ TracePrint(("returns handle %.8lx\n", (unsigned long)*handle));
+ return RDIError_NoError;
+}
+
+/*----------------------------------------------------------------------*/
+/*----angel_RDI_clearwatch-----------------------------------------------*/
+/*----------------------------------------------------------------------*/
+
+/* Clear a watchpoint: use ADP_ClearWatch. */
+int angel_RDI_clearwatch(PointHandle handle) {
+
+ int status, reason, OSinfo1, OSinfo2, err, debugID;
+ Packet *packet = NULL;
+
+ TracePrint(("angel_RDI_clearwatch: handle=%.8lx\n", (unsigned long)handle));
+
+ register_debug_message_handler();
+ msgsend(CI_HADP, "%w%w%w%w%w",
+ ADP_ClearWatch| HtoT, 0, ADP_HandleUnknown,
+ ADP_HandleUnknown, handle);
+ reason = ADP_ClearWatch|TtoH;
+ err = wait_for_debug_message(&reason, &debugID, &OSinfo1, &OSinfo2,
+ &status, &packet);
+ if (err != RDIError_NoError) {
+ DevSW_FreePacket(packet);
+ return err; /* Was there an error? */
+ }
+ unpack_message(BUFFERDATA(packet->pk_buffer), "%w%w%w%w%w", &reason, &debugID,
+ &OSinfo1, &OSinfo2, &status);
+ DevSW_FreePacket(packet);
+ return RDIError_NoError;
+}
+
+typedef struct {
+ unsigned stopped_reason;
+ int stopped_status;
+ int data;
+} adp_stopped_struct;
+
+
+int angel_RDI_OnTargetStopping(angel_RDI_TargetStoppedProc *fn,
+ void *arg)
+{
+ stoppedProcListElement **lptr = &stopped_proc_list;
+
+ /* Find the address of the NULL ptr at the end of the list */
+ for (; *lptr!=NULL ; lptr = &((*lptr)->next))
+ ; /* Do nothing */
+
+ *lptr = (stoppedProcListElement *) malloc(sizeof(stoppedProcListElement));
+ if (*lptr == NULL) return RDIError_OutOfStore;
+ (*lptr)->fn = fn;
+ (*lptr)->arg = arg;
+
+ return RDIError_NoError;
+}
+
+static int CallStoppedProcs(unsigned reason)
+{
+ stoppedProcListElement *p = stopped_proc_list;
+ int err=RDIError_NoError;
+
+ for (; p!=NULL ; p=p->next) {
+ int local_err = p->fn(reason, p->arg);
+ if (local_err != RDIError_NoError) err=local_err;
+ }
+
+ return err;
+}
+
+/*----------------------------------------------------------------------*/
+/*----angel_RDI_execute--------------------------------------------------*/
+/*----------------------------------------------------------------------*/
+
+static int HandleStoppedMessage(Packet *packet, void *stateptr) {
+ unsigned int err, reason, debugID, OSinfo1, OSinfo2, count;
+ adp_stopped_struct *stopped_info;
+ stopped_info = (adp_stopped_struct *) stateptr;
+ IGNORE(stateptr);
+ count = unpack_message(BUFFERDATA(packet->pk_buffer), "%w%w%w%w%w%w",
+ &reason, &debugID,
+ &OSinfo1, &OSinfo2,
+ &stopped_info->stopped_reason, &stopped_info->data);
+ DevSW_FreePacket(packet);
+
+ if (reason != (ADP_Stopped | TtoH)) {
+#ifdef DEBUG
+ angel_DebugPrint("Expecting stopped message, got %x", reason);
+#endif
+ return RDIError_Error;
+ }
+ else {
+ executing = FALSE;
+#ifdef DEBUG
+ angel_DebugPrint("Received stopped message.\n");
+#endif
+ }
+
+ err = msgsend(CI_TADP, "%w%w%w%w%w", (ADP_Stopped | HtoT), 0,
+ ADP_HandleUnknown, ADP_HandleUnknown, RDIError_NoError);
+#ifdef DEBUG
+ angel_DebugPrint("Transmiting stopped acknowledge.\n");
+#endif
+ if (err != RDIError_NoError) angel_DebugPrint("Transmit failed.\n");
+#ifdef DEBUG
+ angel_DebugPrint("DEBUG: Stopped reason : %x\n", stopped_info->stopped_reason);
+#endif
+ switch (stopped_info->stopped_reason) {
+ case ADP_Stopped_BranchThroughZero:
+ stopped_info->stopped_status = RDIError_BranchThrough0;
+ break;
+ case ADP_Stopped_UndefinedInstr:
+ stopped_info->stopped_status = RDIError_UndefinedInstruction;
+ break;
+ case ADP_Stopped_SoftwareInterrupt:
+ stopped_info->stopped_status = RDIError_SoftwareInterrupt;
+ break;
+ case ADP_Stopped_PrefetchAbort:
+ stopped_info->stopped_status = RDIError_PrefetchAbort;
+ break;
+ case ADP_Stopped_DataAbort:
+ stopped_info->stopped_status = RDIError_DataAbort;
+ break;
+ case ADP_Stopped_AddressException:
+ stopped_info->stopped_status = RDIError_AddressException;
+ break;
+ case ADP_Stopped_IRQ:
+ stopped_info->stopped_status = RDIError_IRQ;
+ break;
+ case ADP_Stopped_BreakPoint:
+ stopped_info->stopped_status = RDIError_BreakpointReached;
+ break;
+ case ADP_Stopped_WatchPoint:
+ stopped_info->stopped_status = RDIError_WatchpointAccessed;
+ break;
+ case ADP_Stopped_StepComplete:
+ stopped_info->stopped_status = RDIError_ProgramFinishedInStep;
+ break;
+ case ADP_Stopped_RunTimeErrorUnknown:
+ case ADP_Stopped_StackOverflow:
+ case ADP_Stopped_DivisionByZero:
+ stopped_info->stopped_status = RDIError_Error;
+ break;
+ case ADP_Stopped_FIQ:
+ stopped_info->stopped_status = RDIError_FIQ;
+ break;
+ case ADP_Stopped_UserInterruption:
+ case ADP_Stopped_OSSpecific:
+ stopped_info->stopped_status = RDIError_UserInterrupt;
+ break;
+ case ADP_Stopped_ApplicationExit:
+ stopped_info->stopped_status = RDIError_NoError;
+ break;
+ default:
+ stopped_info->stopped_status = RDIError_NoError;
+ break;
+ }
+ return RDIError_NoError;
+}
+
+static volatile bool interrupt_request = FALSE;
+
+static void interrupt_target( void )
+{
+ Packet *packet = NULL;
+ int err;
+ int reason, debugID, OSinfo1, OSinfo2, status;
+
+#ifdef DEBUG
+ angel_DebugPrint("DEBUG: interrupt_target.\n");
+#endif
+
+ register_debug_message_handler();
+ msgsend(CI_HADP, "%w%w%w%w", ADP_InterruptRequest | HtoT, 0,
+ ADP_HandleUnknown, ADP_HandleUnknown);
+
+ reason = ADP_InterruptRequest |TtoH;
+ err = wait_for_debug_message(&reason, &debugID, &OSinfo1, &OSinfo2,
+ &status, &packet);
+ DevSW_FreePacket(packet);
+#ifdef DEBUG
+ angel_DebugPrint("DEBUG: got interrupt ack ok err = %d, status=%i\n",
+ err, status);
+#endif
+
+ return;
+}
+
+#ifdef TEST_DC_APPL
+ extern void test_dc_appl_handler( const DeviceDescr *device,
+ Packet *packet );
+#endif
+
+/* Core functionality for execute and step */
+static int angel_RDI_ExecuteOrStep(PointHandle *handle, word type,
+ unsigned ninstr)
+{
+ int err;
+ adp_stopped_struct stopped_info;
+ void* stateptr = (void *)&stopped_info;
+ ChannelCallback HandleStoppedMessageFPtr=(ChannelCallback) HandleStoppedMessage;
+ int status, reasoncode, debugID, OSinfo1, OSinfo2;
+ Packet *packet = NULL;
+
+ TracePrint(("angel_RDI_ExecuteOrStep\n"));
+
+ err = Adp_ChannelRegisterRead(CI_TADP,
+ HandleStoppedMessageFPtr, stateptr);
+ if (err != RDIError_NoError) {
+#ifdef DEBUG
+ angel_DebugPrint("TADP Register failed.\n");
+#endif
+ return err;
+ }
+ /* Set executing TRUE here, as it must be set up before the target has
+ * had any chance at all to execute, or it may send its stopped message
+ * before we get round to setting executing = TRUE !!!
+ */
+ executing = TRUE;
+
+ register_debug_message_handler();
+
+#ifdef TEST_DC_APPL
+ Adp_Install_DC_Appl_Handler( test_dc_appl_handler );
+#endif
+
+#ifdef DEBUG
+ angel_DebugPrint("Transmiting %s message.\n",
+ type == ADP_Execute ? "execute": "step");
+#endif
+
+ register_debug_message_handler();
+ /* Extra ninstr parameter for execute message will simply be ignored */
+ err = msgsend(CI_HADP,"%w%w%w%w%w", type | HtoT, 0,
+ ADP_HandleUnknown, ADP_HandleUnknown, ninstr);
+#if DEBUG
+ if (err != RDIError_NoError) angel_DebugPrint("Transmit failed.\n");
+#endif
+
+ reasoncode = type | TtoH;
+ err = wait_for_debug_message( &reasoncode, &debugID, &OSinfo1, &OSinfo2,
+ &status, &packet );
+ if (err != RDIError_NoError)
+ return err;
+ else if (status != RDIError_NoError)
+ return status;
+
+#ifdef DEBUG
+ angel_DebugPrint("Waiting for program to finish...\n");
+#endif
+
+ while( executing )
+ {
+ if (interrupt_request)
+ {
+ interrupt_target();
+ interrupt_request = FALSE;
+ }
+ Adp_AsynchronousProcessing( async_block_on_nothing );
+ }
+
+#ifdef TEST_DC_APPL
+ Adp_Install_DC_Appl_Handler( NULL );
+#endif
+
+ (void)Adp_ChannelRegisterRead(CI_TADP, NULL, NULL);
+
+ *handle = (PointHandle)stopped_info.data;
+
+ CallStoppedProcs(stopped_info.stopped_reason);
+
+ return stopped_info.stopped_status;
+}
+
+/* Request that the target starts executing from the stored CPU state: use
+ ADP_Execute. */
+int angel_RDI_execute(PointHandle *handle)
+{
+ return angel_RDI_ExecuteOrStep(handle, ADP_Execute, 0);
+}
+
+#ifdef __WATCOMC__
+typedef void handlertype(int);
+
+static int interrupted=0;
+
+static void myhandler(int sig) {
+ IGNORE(sig);
+ interrupted=1;
+ signal(SIGINT, myhandler);
+}
+#endif
+
+/*----------------------------------------------------------------------*/
+/*----angel_RDI_step-----------------------------------------------------*/
+/*----------------------------------------------------------------------*/
+
+/* Step 'ninstr' through the code: use ADP_Step. */
+int angel_RDI_step(unsigned ninstr, PointHandle *handle)
+{
+ int err = angel_RDI_ExecuteOrStep(handle, ADP_Step, ninstr);
+ if (err == RDIError_ProgramFinishedInStep)
+ return RDIError_NoError;
+ else
+ return err;
+}
+
+
+static void SetCPWords(int cpnum, struct Dbg_CoProDesc const *cpd) {
+ int i, rmax = 0;
+ for (i = 0; i < cpd->entries; i++)
+ if (cpd->regdesc[i].rmax > rmax)
+ rmax = cpd->regdesc[i].rmax;
+
+ { unsigned char *rmap = (unsigned char *)malloc(rmax + 2);
+ *rmap++ = rmax + 1;
+ for (i = 0; i < cpd->entries; i++) {
+ int r;
+ for (r = cpd->regdesc[i].rmin; r <= cpd->regdesc[i].rmax; r++)
+ rmap[r] = (cpd->regdesc[i].nbytes+3) / 4;
+ }
+/* if (cpwords[cpnum] != NULL) free(cpwords[cpnum]); */
+ cpwords[cpnum] = rmap;
+ }
+}
+
+/*----------------------------------------------------------------------*/
+/*----angel_RDI_info-----------------------------------------------------*/
+/*----------------------------------------------------------------------*/
+
+/* Use ADP_Info, ADP_Ctrl and ADP_Profile calls to implement these,
+ see adp.h for more details. */
+
+static int angel_cc_exists( void )
+{
+ Packet *packet = NULL;
+ int err;
+ int reason, debugID, OSinfo1, OSinfo2, subreason, status;
+
+#ifdef DEBUG
+ angel_DebugPrint("DEBUG: ADP_ICEB_CC_Exists.\n");
+#endif
+
+ if ( angel_RDI_info( RDIInfo_Icebreaker, NULL, NULL ) == RDIError_NoError ) {
+ register_debug_message_handler();
+ msgsend(CI_HADP, "%w%w%w%w%w", ADP_ICEbreakerHADP | HtoT, 0,
+ ADP_HandleUnknown, ADP_HandleUnknown,
+ ADP_ICEB_CC_Exists );
+ reason = ADP_ICEbreakerHADP |TtoH;
+ err = wait_for_debug_message(&reason, &debugID, &OSinfo1, &OSinfo2,
+ &status, &packet);
+ if (err != RDIError_NoError) {
+ DevSW_FreePacket(packet);
+ return err;
+ }
+ unpack_message(BUFFERDATA(packet->pk_buffer), "%w%w%w%w%w%w", &reason,
+ &debugID, &OSinfo1, &OSinfo2, &subreason, &status);
+ if (subreason != ADP_ICEB_CC_Exists) {
+ DevSW_FreePacket(packet);
+ return RDIError_Error;
+ }
+ else
+ return status;
+ }
+ else
+ return RDIError_UnimplementedMessage;
+}
+
+typedef struct {
+ RDICCProc_ToHost *tohost; void *tohostarg;
+ RDICCProc_FromHost *fromhost; void *fromhostarg;
+ bool registered;
+} CCState;
+static CCState ccstate = { NULL, NULL, NULL, NULL, FALSE };
+
+static void HandleDCCMessage( Packet *packet, void *stateptr )
+{
+ unsigned int reason, debugID, OSinfo1, OSinfo2;
+ int count;
+ CCState *ccstate_p = (CCState *)stateptr;
+
+ count = unpack_message( BUFFERDATA(packet->pk_buffer), "%w%w%w%w",
+ &reason, &debugID, &OSinfo1, &OSinfo2 );
+ switch ( reason )
+ {
+ case ADP_TDCC_ToHost | TtoH:
+ {
+ /* only handles a single word of data, for now */
+
+ unsigned int nbytes, data;
+
+ unpack_message( BUFFERDATA(packet->pk_buffer)+count, "%w%w",
+ &nbytes, &data );
+#ifdef DEBUG
+ angel_DebugPrint( "DEBUG: received CC_ToHost message: nbytes %d data %08x.\n",
+ nbytes, data );
+#endif
+ ccstate_p->tohost( ccstate_p->tohostarg, data );
+ msgsend(CI_TTDCC, "%w%w%w%w%w",
+ ADP_TDCC_ToHost | HtoT, debugID, OSinfo1, OSinfo2,
+ RDIError_NoError );
+ break;
+ }
+
+ case ADP_TDCC_FromHost | TtoH:
+ {
+ /* only handles a single word of data, for now */
+
+ int valid;
+ ARMword data;
+
+ ccstate_p->fromhost( ccstate_p->fromhostarg, &data, &valid );
+#ifdef DEBUG
+ angel_DebugPrint( "DEBUG: received CC_FromHost message, returning: %08x %s.\n",
+ data, valid ? "VALID" : "INvalid" );
+#endif
+ msgsend(CI_TTDCC, "%w%w%w%w%w%w%w",
+ ADP_TDCC_FromHost | HtoT, debugID, OSinfo1, OSinfo2,
+ RDIError_NoError, valid ? 1 : 0, data );
+ break;
+ }
+
+ default:
+#ifdef DEBUG
+ angel_DebugPrint( "Unexpected TDCC message %08x received\n", reason );
+#endif
+ break;
+ }
+ DevSW_FreePacket(packet);
+ return;
+}
+
+static void angel_check_DCC_handler( CCState *ccstate_p )
+{
+ int err;
+
+ if ( ccstate_p->tohost != NULL || ccstate_p->fromhost != NULL )
+ {
+ /* doing DCC, so need a handler */
+ if ( ! ccstate_p->registered )
+ {
+#ifdef DEBUG
+ angel_DebugPrint( "Registering handler for TTDCC channel.\n" );
+#endif
+ err = Adp_ChannelRegisterRead( CI_TTDCC, HandleDCCMessage,
+ ccstate_p );
+ if ( err == adp_ok )
+ ccstate_p->registered = TRUE;
+#ifdef DEBUG
+ else
+ angel_DebugPrint( "angel_check_DCC_handler: register failed!\n" );
+#endif
+ }
+ }
+ else
+ {
+ /* not doing DCC, so don't need a handler */
+ if ( ccstate_p->registered )
+ {
+#ifdef DEBUG
+ angel_DebugPrint( "Unregistering handler for TTDCC channel.\n" );
+#endif
+ err = Adp_ChannelRegisterRead( CI_TTDCC, NULL, NULL );
+ if ( err == adp_ok )
+ ccstate_p->registered = FALSE;
+#ifdef DEBUG
+ else
+ angel_DebugPrint( "angel_check_DCC_handler: unregister failed!\n" );
+#endif
+ }
+ }
+}
+
+
+static int CheckSubMessageReply(int reason, int subreason) {
+ Packet *packet = NULL;
+ int status, debugID, OSinfo1, OSinfo2;
+ int err = RDIError_NoError;
+ reason |= TtoH;
+ err = wait_for_debug_message(&reason, &debugID, &OSinfo1, &OSinfo2,
+ &status, &packet);
+ if (err != RDIError_NoError) {
+ status = err;
+ } else {
+ int sr;
+ unpack_message(BUFFERDATA(packet->pk_buffer), "%w%w%w%w%w%w", &reason, &debugID,
+ &OSinfo1, &OSinfo2, &sr, &status);
+ if (subreason != sr) status = RDIError_Error;
+ }
+ DevSW_FreePacket(packet);
+ return status;
+}
+
+static int SendSubMessageAndCheckReply(int reason, int subreason) {
+ register_debug_message_handler();
+ msgsend(CI_HADP, "%w%w%w%w%w", reason | HtoT, 0,
+ ADP_HandleUnknown, ADP_HandleUnknown,
+ subreason);
+ return CheckSubMessageReply(reason, subreason);
+}
+
+static int SendSubMessageWordAndCheckReply(int reason, int subreason, ARMword word) {
+ register_debug_message_handler();
+ msgsend(CI_HADP, "%w%w%w%w%w%w", reason | HtoT, 0,
+ ADP_HandleUnknown, ADP_HandleUnknown,
+ subreason, word);
+ return CheckSubMessageReply(reason, subreason);
+}
+
+static int SendSubMessageGetWordAndCheckReply(int reason, int subreason, ARMword *resp) {
+ Packet *packet = NULL;
+ int status, debugID, OSinfo1, OSinfo2;
+ int err = RDIError_NoError;
+
+ register_debug_message_handler();
+ msgsend(CI_HADP, "%w%w%w%w%w", reason | HtoT, 0,
+ ADP_HandleUnknown, ADP_HandleUnknown,
+ subreason);
+ reason |= TtoH;
+ err = wait_for_debug_message(&reason, &debugID, &OSinfo1, &OSinfo2,
+ &status, &packet);
+ if (err != RDIError_NoError) {
+ status = err;
+ } else {
+ int sr;
+ unpack_message(BUFFERDATA(packet->pk_buffer), "%w%w%w%w%w%w%w", &reason, &debugID,
+ &OSinfo1, &OSinfo2, &sr, &status, resp);
+ if (subreason != sr) status = RDIError_Error;
+ }
+ DevSW_FreePacket(packet);
+ return status;
+}
+
+static int const hostsex = 1;
+
+int angel_RDI_info(unsigned type, ARMword *arg1, ARMword *arg2) {
+ Packet *packet = NULL;
+ int len, status, c, reason, subreason, debugID, OSinfo1, OSinfo2;
+ int err=RDIError_NoError, cpnum=0;
+ struct Dbg_CoProDesc *cpd;
+ int count, i;
+ unsigned char *bp;
+
+#ifdef DEBUG
+ angel_DebugPrint("DEBUG: Entered angel_RDI_info.\n");
+#endif
+ switch (type) {
+ case RDIInfo_Target:
+#ifdef DEBUG
+ angel_DebugPrint("DEBUG: RDIInfo_Target.\n");
+#endif
+
+ register_debug_message_handler();
+ msgsend(CI_HADP, "%w%w%w%w%w", ADP_Info | HtoT, 0,
+ ADP_HandleUnknown, ADP_HandleUnknown, ADP_Info_Target);
+ reason = ADP_Info |TtoH;
+ err = wait_for_debug_message(&reason, &debugID, &OSinfo1, &OSinfo2,
+ &status, &packet);
+ if (err != RDIError_NoError) {
+ DevSW_FreePacket(packet);
+ return err;
+ }
+ unpack_message(BUFFERDATA(packet->pk_buffer), "%w%w%w%w%w%w%w%w", &reason,
+ &debugID, &OSinfo1, &OSinfo2, &subreason, &status,
+ arg1, arg2);
+ DevSW_FreePacket(packet);
+
+ if (subreason != ADP_Info_Target)
+ return RDIError_Error;
+ else
+ return status;
+
+ case RDISignal_Stop:
+#ifdef DEBUG
+ angel_DebugPrint("DEBUG: RDISignal_Stop.\n");
+ if (interrupt_request)
+ angel_DebugPrint(" STILL WAITING to send previous interrupt request\n");
+#endif
+ interrupt_request = TRUE;
+ return RDIError_NoError;
+
+ case RDIInfo_Points:
+#ifdef DEBUG
+ angel_DebugPrint("DEBUG: RDIInfo_Points.\n");
+#endif
+ return SendSubMessageGetWordAndCheckReply(ADP_Info, ADP_Info_Points, arg1);
+
+ case RDIInfo_Step:
+#ifdef DEBUG
+ angel_DebugPrint("DEBUG: RDIInfo_Step.\n");
+#endif
+ return SendSubMessageGetWordAndCheckReply(ADP_Info, ADP_Info_Step, arg1);
+
+ case RDISet_Cmdline:
+#ifdef DEBUG
+ angel_DebugPrint("DEBUG: RDISet_Cmdline.\n");
+#endif
+ if (ardi_commandline != &dummycline)
+ free(ardi_commandline);
+ ardi_commandline = (char *)malloc(strlen((char*)arg1) + 1) ;
+ (void)strcpy(ardi_commandline, (char *)arg1) ;
+ return RDIError_NoError;
+
+ case RDIInfo_SetLog:
+#ifdef DEBUG
+ angel_DebugPrint("DEBUG: RDIInfo_SetLog.\n");
+#endif
+ rdi_log = (int) *arg1;
+ return RDIError_NoError;
+
+ case RDIInfo_Log:
+#ifdef DEBUG
+ angel_DebugPrint("DEBUG: RDIInfo_Log.\n");
+#endif
+ *arg1 = rdi_log;
+ return RDIError_NoError;
+
+
+ case RDIInfo_MMU:
+#ifdef DEBUG
+ angel_DebugPrint("DEBUG: RDIInfo_MMU.\n");
+#endif
+ return SendSubMessageGetWordAndCheckReply(ADP_Info, ADP_Info_MMU, arg1);
+
+ case RDIInfo_SemiHosting:
+#ifdef DEBUG
+ angel_DebugPrint("DEBUG: RDIInfo_SemiHosting.\n");
+#endif
+ return SendSubMessageAndCheckReply(ADP_Info, ADP_Info_SemiHosting);
+
+ case RDIInfo_CoPro:
+#ifdef DEBUG
+ angel_DebugPrint("DEBUG: RDIInfo_CoPro.\n");
+#endif
+ return SendSubMessageAndCheckReply(ADP_Info, ADP_Info_CoPro);
+
+ case RDICycles:
+#ifdef DEBUG
+ angel_DebugPrint("DEBUG: RDICycles.\n");
+#endif
+ register_debug_message_handler();
+ msgsend(CI_HADP, "%w%w%w%w%w", ADP_Info | HtoT, 0,
+ ADP_HandleUnknown, ADP_HandleUnknown, ADP_Info_Cycles);
+ reason = ADP_Info |TtoH;
+ err = wait_for_debug_message(&reason, &debugID, &OSinfo1, &OSinfo2,
+ &status, &packet);
+ if (err != RDIError_NoError) {
+ DevSW_FreePacket(packet);
+ return err;
+ }
+ unpack_message(BUFFERDATA(packet->pk_buffer), "%w%w%w%w%w%w", &reason, &debugID,
+ &OSinfo1, &OSinfo2, &subreason, &status);
+ DevSW_FreePacket(packet);
+ if (subreason != ADP_Info_Cycles)
+ return RDIError_Error;
+ if (status != RDIError_NoError) return status;
+ for (c=0; c<12; c++)
+ arg1[c]=GET32LE(BUFFERDATA(packet->pk_buffer)+24+(c*4));
+ return status;
+
+ case RDIInfo_DescribeCoPro:
+#ifdef DEBUG
+ angel_DebugPrint("DEBUG: RDIInfo_DescribeCoPro.\n");
+#endif
+ cpnum = *(int *)arg1;
+ cpd = (struct Dbg_CoProDesc *)arg2;
+ packet = DevSW_AllocatePacket(Armsd_BufferSize);
+ if (angel_RDI_info(ADP_Info_CoPro, NULL, NULL) != RDIError_NoError)
+ return RDIError_Error;
+ len = msgbuild(BUFFERDATA(packet->pk_buffer), "%w%w%w%w%w", ADP_Info | HtoT, 0,
+ ADP_HandleUnknown, ADP_HandleUnknown,
+ ADP_Info_DescribeCoPro);
+ len +=msgbuild(BUFFERDATA(packet->pk_buffer)+20, "%b%b%b%b%b", cpnum,
+ cpd->regdesc[cpnum].rmin, cpd->regdesc[cpnum].rmax,
+ cpd->regdesc[cpnum].nbytes, cpd->regdesc[cpnum].access);
+ if (cpd->regdesc[cpnum].access&0x3 == 0x3){
+ len += msgbuild(BUFFERDATA(packet->pk_buffer)+25, "%b%b%b%b%b",
+ cpd->regdesc[cpnum].accessinst.cprt.read_b0,
+ cpd->regdesc[cpnum].accessinst.cprt.read_b1,
+ cpd->regdesc[cpnum].accessinst.cprt.write_b0,
+ cpd->regdesc[cpnum].accessinst.cprt.write_b1, 0xff);
+ }
+ else {
+ len += msgbuild(BUFFERDATA(packet->pk_buffer)+25, "%b%b%b%b%b%",
+ cpd->regdesc[cpnum].accessinst.cpdt.rdbits,
+ cpd->regdesc[cpnum].accessinst.cpdt.nbit,0,0, 0xff);
+ }
+ register_debug_message_handler();
+ packet->pk_length = len;
+ Adp_ChannelWrite(CI_HADP, packet); /* Transmit message. */
+ reason = ADP_Info |TtoH;
+ err = wait_for_debug_message(&reason, &debugID, &OSinfo1, &OSinfo2,
+ &status, &packet);
+ if (err != RDIError_NoError) {
+ DevSW_FreePacket(packet);
+ return err;
+ }
+ unpack_message(BUFFERDATA(packet->pk_buffer), "%w%w%w%w%w%w", &reason, &debugID,
+ &OSinfo1, &OSinfo2, &subreason, &status);
+ DevSW_FreePacket(packet);
+ if (subreason != ADP_Info_DescribeCoPro)
+ return RDIError_Error;
+ else
+ return status;
+
+ case RDIInfo_RequestCoProDesc:
+#ifdef DEBUG
+ angel_DebugPrint("DEBUG: RDIInfo_RequestCoProDesc.\n");
+#endif
+ cpnum = *(int *)arg1;
+ cpd = (struct Dbg_CoProDesc *)arg2;
+ packet = DevSW_AllocatePacket(Armsd_BufferSize);
+ len = msgbuild(BUFFERDATA(packet->pk_buffer), "%w%w%w%w%w", ADP_Info | HtoT, 0,
+ ADP_HandleUnknown, ADP_HandleUnknown,
+ ADP_Info_RequestCoProDesc);
+ len += msgbuild(BUFFERDATA(packet->pk_buffer)+20, "%b", *(int *)arg1);
+ packet->pk_length = len;
+ register_debug_message_handler();
+ Adp_ChannelWrite(CI_HADP, packet); /* Transmit message. */
+ reason = ADP_Info |TtoH;
+ err = wait_for_debug_message(&reason, &debugID, &OSinfo1, &OSinfo2,
+ &status, &packet);
+ if (err != RDIError_NoError) {
+ DevSW_FreePacket(packet);
+ return err;
+ }
+ count = unpack_message(BUFFERDATA(packet->pk_buffer), "%w%w%w%w%w%w", &reason,
+ &debugID, &OSinfo1, &OSinfo2, &subreason, &status);
+ if (subreason != ADP_Info_RequestCoProDesc) {
+ DevSW_FreePacket(packet);
+ return RDIError_Error;
+ } else if ( status != RDIError_NoError ) {
+ DevSW_FreePacket(packet);
+ return status;
+ } else {
+ bp = BUFFERDATA(packet->pk_buffer)+count;
+ for ( i = 0; *bp != 0xFF && i < cpd->entries; ++i ) {
+ cpd->regdesc[i].rmin = *bp++;
+ cpd->regdesc[i].rmax = *bp++;
+ cpd->regdesc[i].nbytes = *bp++;
+ cpd->regdesc[i].access = *bp++;
+ }
+ cpd->entries = i;
+ if ( *bp != 0xFF )
+ status = RDIError_BufferFull;
+ else
+ SetCPWords( cpnum, cpd );
+ DevSW_FreePacket(packet);
+ return status;
+ }
+
+ case RDIInfo_GetLoadSize:
+#ifdef DEBUG
+ angel_DebugPrint("DEBUG: ADP_Info_AngelBufferSize.\n");
+#endif
+ register_debug_message_handler();
+ msgsend(CI_HADP, "%w%w%w%w%w", ADP_Info | HtoT, 0,
+ ADP_HandleUnknown, ADP_HandleUnknown,
+ ADP_Info_AngelBufferSize);
+ reason = ADP_Info |TtoH;
+ err = wait_for_debug_message(&reason, &debugID, &OSinfo1, &OSinfo2,
+ &status, &packet);
+ if (err != RDIError_NoError) {
+ DevSW_FreePacket(packet);
+ return err;
+ }
+ unpack_message(BUFFERDATA(packet->pk_buffer), "%w%w%w%w%w%w", &reason,
+ &debugID, &OSinfo1, &OSinfo2, &subreason, &status);
+ if (subreason != ADP_Info_AngelBufferSize) {
+ DevSW_FreePacket(packet);
+ return RDIError_Error;
+ }
+ else {
+ word defaultsize, longsize;
+ unpack_message(BUFFERDATA(packet->pk_buffer)+24, "%w%w",
+ &defaultsize, &longsize);
+ *arg1 = longsize - ADP_WriteHeaderSize; /* space for ADP header */
+#ifdef MONITOR_DOWNLOAD_PACKETS
+ angel_DebugPrint("DEBUG: ADP_Info_AngelBufferSize: got (%d, %d), returning %d.\n",
+ defaultsize, longsize, *arg1);
+#endif
+ DevSW_FreePacket(packet);
+ return status;
+ }
+
+ case RDIVector_Catch:
+#ifdef DEBUG
+ angel_DebugPrint("DEBUG: ADP_Ctrl_VectorCatch %lx.\n", *arg1);
+#endif
+ return SendSubMessageWordAndCheckReply(ADP_Control, ADP_Ctrl_VectorCatch, *arg1);
+
+ case RDISemiHosting_SetState:
+#ifdef DEBUG
+ angel_DebugPrint("DEBUG: ADP_Ctrl_SemiHosting_SetState %lx.\n", *arg1);
+#endif
+ return SendSubMessageWordAndCheckReply(ADP_Control, ADP_Ctrl_SemiHosting_SetState, *arg1);
+
+ case RDISemiHosting_GetState:
+#ifdef DEBUG
+ angel_DebugPrint("DEBUG: ADP_Ctrl_SemiHosting_GetState.\n");
+#endif
+ return SendSubMessageGetWordAndCheckReply(ADP_Control, ADP_Ctrl_SemiHosting_GetState, arg1);
+
+ case RDISemiHosting_SetVector:
+#ifdef DEBUG
+ angel_DebugPrint("DEBUG: ADP_Ctrl_SemiHosting_SetVector %lx.\n", *arg1);
+#endif
+ return SendSubMessageWordAndCheckReply(ADP_Control, ADP_Ctrl_SemiHosting_SetVector, *arg1);
+
+ case RDISemiHosting_GetVector:
+#ifdef DEBUG
+ angel_DebugPrint("DEBUG: ADP_Ctrl_SemiHosting_GetVector.\n");
+#endif
+ return SendSubMessageGetWordAndCheckReply(ADP_Control, ADP_Ctrl_SemiHosting_GetVector, arg1);
+
+ case RDISemiHosting_SetARMSWI:
+#ifdef DEBUG
+ angel_DebugPrint("DEBUG: ADP_Ctrl_SemiHosting_SetARMSWI.\n");
+#endif
+ return SendSubMessageWordAndCheckReply(ADP_Control, ADP_Ctrl_SemiHosting_SetARMSWI, *arg1);
+
+ case RDISemiHosting_GetARMSWI:
+#ifdef DEBUG
+ angel_DebugPrint("DEBUG: ADP_Ctrl_SemiHosting_GetARMSWI.\n");
+#endif
+ return SendSubMessageGetWordAndCheckReply(ADP_Control, ADP_Ctrl_SemiHosting_GetARMSWI, arg1);
+
+ case RDISemiHosting_SetThumbSWI:
+#ifdef DEBUG
+ angel_DebugPrint("DEBUG: ADP_Ctrl_SemiHosting_SetThumbSWI.\n");
+#endif
+ return SendSubMessageWordAndCheckReply(ADP_Control, ADP_Ctrl_SemiHosting_SetThumbSWI, *arg1);
+
+ case RDISemiHosting_GetThumbSWI:
+#ifdef DEBUG
+ angel_DebugPrint("DEBUG: ADP_Ctrl_SemiHosting_GetThumbSWI.\n");
+#endif
+ return SendSubMessageGetWordAndCheckReply(ADP_Control, ADP_Ctrl_SemiHosting_GetThumbSWI, arg1);
+
+ case RDIInfo_SetTopMem:
+#ifdef DEBUG
+ angel_DebugPrint("DEBUG: ADP_Ctrl_SetTopMem.\n");
+#endif
+ return SendSubMessageWordAndCheckReply(ADP_Control, ADP_Ctrl_SetTopMem, *arg1);
+
+ case RDIPointStatus_Watch:
+#ifdef DEBUG
+ angel_DebugPrint("DEBUG: ADP_Ctrl_PointStatus_Watch.\n");
+#endif
+ register_debug_message_handler();
+ msgsend(CI_HADP, "%w%w%w%w%w%w", ADP_Control | HtoT, 0,
+ ADP_HandleUnknown, ADP_HandleUnknown,
+ ADP_Ctrl_PointStatus_Watch, *arg1 );
+ reason = ADP_Control |TtoH;
+ err = wait_for_debug_message(&reason, &debugID, &OSinfo1, &OSinfo2,
+ &status, &packet);
+ if (err != RDIError_NoError) {
+ DevSW_FreePacket(packet);
+ return err;
+ }
+ unpack_message(BUFFERDATA(packet->pk_buffer), "%w%w%w%w%w%w%w%w", &reason,
+ &debugID, &OSinfo1, &OSinfo2, &subreason, &status,
+ arg1, arg2);
+ if (subreason != ADP_Ctrl_PointStatus_Watch) {
+ DevSW_FreePacket(packet);
+ return RDIError_Error;
+ }
+ else
+ return status;
+
+ case RDIPointStatus_Break:
+#ifdef DEBUG
+ angel_DebugPrint("DEBUG: ADP_Ctrl_PointStatus_Break.\n");
+#endif
+ register_debug_message_handler();
+ msgsend(CI_HADP, "%w%w%w%w%w%w", ADP_Control | HtoT, 0,
+ ADP_HandleUnknown, ADP_HandleUnknown,
+ ADP_Ctrl_PointStatus_Break, *arg1 );
+ reason = ADP_Control |TtoH;
+ err = wait_for_debug_message(&reason, &debugID, &OSinfo1, &OSinfo2,
+ &status, &packet);
+ if (err != RDIError_NoError) {
+ DevSW_FreePacket(packet);
+ return err;
+ }
+ unpack_message(BUFFERDATA(packet->pk_buffer), "%w%w%w%w%w%w%w%w", &reason,
+ &debugID, &OSinfo1, &OSinfo2, &subreason, &status,
+ arg1, arg2);
+ if (subreason != ADP_Ctrl_PointStatus_Break) {
+ DevSW_FreePacket(packet);
+ return RDIError_Error;
+ }
+ else
+ return status;
+
+ case RDIInfo_DownLoad:
+#ifdef DEBUG
+ angel_DebugPrint("DEBUG: ADP_Ctrl_Download_Supported.\n");
+#endif
+ return SendSubMessageAndCheckReply(ADP_Control, ADP_Ctrl_Download_Supported);
+
+ case RDIConfig_Count:
+#ifdef DEBUG
+ angel_DebugPrint("DEBUG: ADP_ICEM_ConfigCount.\n");
+#endif
+ return SendSubMessageGetWordAndCheckReply(ADP_ICEman, ADP_ICEM_ConfigCount, arg1);
+
+ case RDIConfig_Nth:
+#ifdef DEBUG
+ angel_DebugPrint("DEBUG: ADP_ICEM_ConfigNth.\n");
+#endif
+ register_debug_message_handler();
+ msgsend(CI_HADP, "%w%w%w%w%w%w", ADP_ICEman | HtoT, 0,
+ ADP_HandleUnknown, ADP_HandleUnknown,
+ ADP_ICEM_ConfigNth, *arg1 );
+ reason = ADP_ICEman |TtoH;
+ err = wait_for_debug_message(&reason, &debugID, &OSinfo1, &OSinfo2,
+ &status, &packet);
+ if (err != RDIError_NoError) {
+ DevSW_FreePacket(packet);
+ return err;
+ } else {
+ RDI_ConfigDesc *cd = (RDI_ConfigDesc *)arg2;
+ unsigned char n;
+ len = unpack_message(BUFFERDATA(packet->pk_buffer), "%w%w%w%w%w%w%w%b",
+ &reason, &debugID,
+ &OSinfo1, &OSinfo2, &subreason, &status,
+ &cd->version, &n);
+ if (subreason != ADP_ICEM_ConfigNth) {
+ DevSW_FreePacket(packet);
+ return RDIError_Error;
+ }
+ else {
+ memcpy( cd->name, BUFFERDATA(packet->pk_buffer)+len, n+1 );
+ cd->name[n] = 0;
+ return status;
+ }
+ }
+
+ case RDIInfo_Icebreaker:
+#ifdef DEBUG
+ angel_DebugPrint("DEBUG: ADP_ICEB_Exists.\n");
+#endif
+ return SendSubMessageAndCheckReply(ADP_ICEbreakerHADP, ADP_ICEB_Exists);
+
+ case RDIIcebreaker_GetLocks:
+#ifdef DEBUG
+ angel_DebugPrint("DEBUG: ADP_ICEB_GetLocks.\n");
+#endif
+ return SendSubMessageGetWordAndCheckReply(ADP_ICEbreakerHADP, ADP_ICEB_GetLocks, arg1);
+
+ case RDIIcebreaker_SetLocks:
+#ifdef DEBUG
+ angel_DebugPrint("DEBUG: ADP_ICEB_SetLocks.\n");
+#endif
+ return SendSubMessageWordAndCheckReply(ADP_ICEbreakerHADP, ADP_ICEB_SetLocks, *arg1);
+
+ case RDICommsChannel_ToHost:
+#ifdef DEBUG
+ angel_DebugPrint("DEBUG: ADP_ICEB_CC_Connect_ToHost.\n");
+#endif
+ if ( angel_cc_exists() == RDIError_NoError ) {
+
+ /*
+ * The following three lines of code have to be removed in order to get
+ * the Windows Angel Channel Viewer working with the Thumb comms channel.
+ * At the moment it allows the ARMSD command line to register a CCIN/CCOUT
+ * callback which stops the ACV working!
+ */
+#ifdef __unix
+ ccstate.tohost = (RDICCProc_ToHost *)arg1;
+ ccstate.tohostarg = arg2;
+ angel_check_DCC_handler( &ccstate );
+#endif
+#ifdef _WIN32
+
+#endif
+
+ register_debug_message_handler();
+ msgsend(CI_HADP, "%w%w%w%w%w%b", ADP_ICEbreakerHADP | HtoT, 0,
+ ADP_HandleUnknown, ADP_HandleUnknown,
+ ADP_ICEB_CC_Connect_ToHost, (arg1 != NULL) );
+ return CheckSubMessageReply(ADP_ICEbreakerHADP, ADP_ICEB_CC_Connect_ToHost);
+ } else {
+ return RDIError_UnimplementedMessage;
+ }
+
+ case RDICommsChannel_FromHost:
+#ifdef DEBUG
+ angel_DebugPrint("DEBUG: ADP_ICEB_CC_Connect_FromHost.\n");
+#endif
+ if ( angel_cc_exists() == RDIError_NoError ) {
+
+ ccstate.fromhost = (RDICCProc_FromHost *)arg1;
+ ccstate.fromhostarg = arg2;
+ angel_check_DCC_handler( &ccstate );
+
+ register_debug_message_handler();
+ msgsend(CI_HADP, "%w%w%w%w%w%b", ADP_ICEbreakerHADP | HtoT, 0,
+ ADP_HandleUnknown, ADP_HandleUnknown,
+ ADP_ICEB_CC_Connect_FromHost, (arg1 != NULL) );
+ return CheckSubMessageReply(ADP_ICEbreakerHADP, ADP_ICEB_CC_Connect_FromHost);
+ } else {
+ return RDIError_UnimplementedMessage;
+ }
+
+ case RDIProfile_Stop:
+ return SendSubMessageAndCheckReply(ADP_Profile, ADP_Profile_Stop);
+
+ case RDIProfile_ClearCounts:
+ return SendSubMessageAndCheckReply(ADP_Profile, ADP_Profile_ClearCounts);
+
+ case RDIProfile_Start:
+#ifdef DEBUG
+ angel_DebugPrint("DEBUG: ADP_Profile_Start %ld.\n", (long)*arg1);
+#endif
+ return SendSubMessageWordAndCheckReply(ADP_Profile, ADP_Profile_Start, *arg1);
+
+ case RDIProfile_WriteMap:
+ { RDI_ProfileMap *map = (RDI_ProfileMap *)arg1;
+ int32 maplen = map->len,
+ offset,
+ size;
+ int32 chunk = (Armsd_LongBufSize-CHAN_HEADER_SIZE-ADP_ProfileWriteHeaderSize) / sizeof(ARMword);
+ /* Maximum number of words sendable in one message */
+ int oldrev = bytesex_reversing();
+ int host_little = *(uint8 const *)&hostsex;
+#ifdef DEBUG
+ angel_DebugPrint("DEBUG: ADP_Profile_WriteMap %ld.\n", maplen);
+#endif
+ status = RDIError_NoError;
+ if (!host_little) {
+ bytesex_reverse(1);
+ for (offset = 0; offset < maplen; offset++)
+ map->map[offset] = bytesex_hostval(map->map[offset]);
+ }
+ for (offset = 0; offset < maplen; offset += size) {
+ unsigned hdrlen;
+ size = maplen - offset;
+ packet = (Packet *)DevSW_AllocatePacket(Armsd_LongBufSize);
+ if (size > chunk) size = chunk;
+ hdrlen = msgbuild(BUFFERDATA(packet->pk_buffer), "%w%w%w%w%w%w%w%w",
+ ADP_Profile | HtoT, 0, ADP_HandleUnknown,
+ ADP_HandleUnknown, ADP_Profile_WriteMap,
+ maplen, size, offset);
+
+ /* Copy the data into the packet. */
+ memcpy(BUFFERDATA(packet->pk_buffer)+hdrlen,
+ &map->map[offset], (size_t)size * sizeof(ARMword));
+ packet->pk_length = size * sizeof(ARMword) + hdrlen;
+ register_debug_message_handler();
+ Adp_ChannelWrite(CI_HADP, packet);
+ reason = ADP_Profile | TtoH;
+ err = wait_for_debug_message(&reason, &debugID, &OSinfo1, &OSinfo2,
+ &status, &packet);
+ if (err == RDIError_NoError) {
+ unpack_message(BUFFERDATA(packet->pk_buffer), "%w%w%w%w%w%w", &reason,
+ &debugID, &OSinfo1, &OSinfo2, &subreason, &status);
+ if (subreason != ADP_Profile_WriteMap) {
+ err = RDIError_Error;
+ }
+ DevSW_FreePacket(packet);
+ }
+ if (err != RDIError_NoError) { status = err; break; }
+ }
+ if (!host_little) {
+ for (offset = 0; offset < maplen; offset++)
+ map->map[offset] = bytesex_hostval(map->map[offset]);
+ bytesex_reverse(oldrev);
+ }
+ return status;
+ }
+
+ case RDIProfile_ReadMap:
+ { int32 maplen = *(int32 *)arg1,
+ offset = 0,
+ size;
+ int32 chunk = (Armsd_BufferSize-CHAN_HEADER_SIZE-ADP_ProfileReadHeaderSize) / sizeof(ARMword);
+#ifdef DEBUG
+ angel_DebugPrint("DEBUG: ADP_Profile_ReadMap %ld.\n", maplen);
+#endif
+ status = RDIError_NoError;
+ for (offset = 0; offset < maplen; offset += size) {
+ size = maplen - offset;
+ if (size > chunk) size = chunk;
+ register_debug_message_handler();
+ msgsend(CI_HADP, "%w%w%w%w%w%w%w", ADP_Profile | HtoT, 0,
+ ADP_HandleUnknown, ADP_HandleUnknown,
+ ADP_Profile_ReadMap, offset, size);
+ reason = ADP_Profile | TtoH;
+ err = wait_for_debug_message(&reason, &debugID, &OSinfo1, &OSinfo2,
+ &status, &packet);
+ if (err != RDIError_NoError) return err;
+ unpack_message(BUFFERDATA(packet->pk_buffer), "%w%w%w%w%w%w", &reason,
+ &debugID, &OSinfo1, &OSinfo2, &subreason, &status);
+ memcpy(&arg2[offset], BUFFERDATA(packet->pk_buffer)+ADP_ProfileReadHeaderSize,
+ size * sizeof(ARMword));
+ DevSW_FreePacket(packet);
+ if (status != RDIError_NoError) break;
+ }
+ { int oldrev = bytesex_reversing();
+ int host_little = *(uint8 const *)&hostsex;
+ if (!host_little) {
+ bytesex_reverse(1);
+ for (offset = 0; offset < maplen; offset++)
+ arg2[offset] = bytesex_hostval(arg2[offset]);
+ }
+ bytesex_reverse(oldrev);
+ }
+ return status;
+ }
+
+ case RDIInfo_CanTargetExecute:
+#ifdef DEBUG
+ printf("DEBUG: RDIInfo_CanTargetExecute.\n");
+#endif
+ return SendSubMessageAndCheckReply(ADP_Info, ADP_Info_CanTargetExecute);
+
+ case RDIInfo_AgentEndianess:
+ return SendSubMessageAndCheckReply(ADP_Info, ADP_Info_AgentEndianess);
+
+ default:
+#ifdef DEBUG
+ angel_DebugPrint("DEBUG: Fell through ADP_Info, default case taken.\n");
+ angel_DebugPrint("DEBUG: type = 0x%x.\n", type);
+#endif
+ if (type & RDIInfo_CapabilityRequest) {
+ switch (type & ~RDIInfo_CapabilityRequest) {
+ case RDISemiHosting_SetARMSWI:
+ return SendSubMessageAndCheckReply(ADP_Info, ADP_Info_ChangeableSHSWI);
+ default:
+#ifdef DEBUG
+ angel_DebugPrint(
+ "DEBUG: ADP_Info - Capability Request(%d) - reporting unimplemented \n",
+ type & ~RDIInfo_CapabilityRequest);
+#endif
+ break;
+ }
+ }
+ return RDIError_UnimplementedMessage;
+ }
+}
+
+
+/*----------------------------------------------------------------------*/
+/*----angel_RDI_AddConfig------------------------------------------------*/
+/*----------------------------------------------------------------------*/
+
+/* Add a configuration: use ADP_ICEM_AddConfig. */
+int angel_RDI_AddConfig(unsigned long nbytes) {
+ Packet *packet = NULL;
+ int status, reason, subreason, debugID, OSinfo1, OSinfo2, err;
+
+#ifdef DEBUG
+ angel_DebugPrint("DEBUG: Entered angel_RDI_AddConfig.\n");
+#endif
+ register_debug_message_handler();
+ msgsend(CI_HADP, "%w%w%w%w%w%w", ADP_ICEman | HtoT,
+ 0, ADP_HandleUnknown, ADP_HandleUnknown,
+ ADP_ICEM_AddConfig, nbytes);
+ reason=ADP_ICEman | TtoH;
+ err = wait_for_debug_message(&reason, &debugID, &OSinfo1, &OSinfo2,
+ &status, &packet);
+ if (err != RDIError_NoError) {
+ DevSW_FreePacket(packet);
+ return -1;
+ }
+ unpack_message(BUFFERDATA(packet->pk_buffer), "%w%w%w%w%w%w", &reason, &debugID,
+ &OSinfo1, &OSinfo2, &subreason, &status);
+ DevSW_FreePacket(packet);
+ if ( subreason != ADP_ICEM_AddConfig )
+ return RDIError_Error;
+ else
+ return status;
+}
+
+
+/*----------------------------------------------------------------------*/
+/*----angel_RDI_LoadConfigData-------------------------------------------*/
+/*----------------------------------------------------------------------*/
+
+/* Load configuration data: use ADP_Ctrl_Download_Data. */
+int angel_RDI_LoadConfigData(unsigned long nbytes, char const *data) {
+ Packet *packet = NULL;
+ int len, status, reason, subreason, debugID, OSinfo1, OSinfo2, err;
+
+#ifdef DEBUG
+ angel_DebugPrint("DEBUG: Entered angel_RDI_LoadConfigData (%d bytes)\n", nbytes);
+#endif
+#if 0
+ if (err = angel_RDI_AddConfig(nbytes) != RDIError_NoError)
+ return err;
+#endif
+ packet = DevSW_AllocatePacket(Armsd_LongBufSize);
+ len = msgbuild(BUFFERDATA(packet->pk_buffer), "%w%w%w%w%w%w",
+ ADP_Control | HtoT, 0,
+ ADP_HandleUnknown, ADP_HandleUnknown,
+ ADP_Ctrl_Download_Data, nbytes);
+ memcpy(BUFFERDATA(packet->pk_buffer)+len, data, nbytes);
+ len += nbytes;
+ packet->pk_length = len;
+#ifdef DEBUG
+ angel_DebugPrint("DEBUG: packet len %d.\n", len);
+#endif
+ register_debug_message_handler();
+ Adp_ChannelWrite(CI_HADP, packet);
+ reason=ADP_Control | TtoH;
+ err = wait_for_debug_message(&reason, &debugID, &OSinfo1, &OSinfo2,
+ &status, &packet);
+ if (err != RDIError_NoError) {
+ DevSW_FreePacket(packet);
+ return -1;
+ }
+ unpack_message(BUFFERDATA(packet->pk_buffer), "%w%w%w%w%w%w", &reason, &debugID,
+ &OSinfo1, &OSinfo2, &subreason, &status);
+ DevSW_FreePacket(packet);
+ if ( subreason != ADP_Ctrl_Download_Data )
+ return RDIError_Error;
+ else
+ return status;
+}
+
+
+/*----------------------------------------------------------------------*/
+/*----angel_RDI_SelectConfig---------------------------------------------*/
+/*----------------------------------------------------------------------*/
+
+/* Select a configuration: use ADP_ICEM_SelecConfig.*/
+int angel_RDI_SelectConfig(RDI_ConfigAspect aspect, char const *name,
+ RDI_ConfigMatchType matchtype, unsigned versionreq,
+ unsigned *versionp)
+{
+ Packet *packet = NULL;
+ int len, status, reason, subreason, debugID, OSinfo1, OSinfo2, err;
+
+#ifdef DEBUG
+ angel_DebugPrint("DEBUG: Entered angel_RDI_SelectConfig.\n");
+#endif
+ packet = DevSW_AllocatePacket(Armsd_BufferSize);
+ len = msgbuild(BUFFERDATA(packet->pk_buffer), "%w%w%w%w%w%b%b%b%w",
+ ADP_ICEman | HtoT, 0,
+ ADP_HandleUnknown, ADP_HandleUnknown,
+ ADP_ICEM_SelectConfig, aspect, strlen(name),
+ matchtype, versionreq);
+ /* copy the name into the buffer */
+ memcpy(BUFFERDATA(packet->pk_buffer)+len, name, strlen(name));
+ len += strlen(name);
+ packet->pk_length = len;
+ register_debug_message_handler();
+ Adp_ChannelWrite(CI_HADP, packet);
+ reason=ADP_ICEman | TtoH;
+ err = wait_for_debug_message(&reason, &debugID, &OSinfo1, &OSinfo2,
+ &status, &packet);
+ if (err != RDIError_NoError) {
+ DevSW_FreePacket(packet);
+ return err;
+ }
+ unpack_message(BUFFERDATA(packet->pk_buffer), "%w%w%w%w%w%w%w",
+ &reason, &debugID, &OSinfo1, &OSinfo2,
+ &subreason, &status, versionp);
+ DevSW_FreePacket(packet);
+ if ( subreason != ADP_ICEM_SelectConfig )
+ return RDIError_Error;
+ else
+ return status;
+}
+
+
+/*----------------------------------------------------------------------*/
+/*----angel_RDI_LoadAgent------------------------------------------------*/
+/*----------------------------------------------------------------------*/
+
+/* Load a new debug agent: use ADP_Ctrl_Download_Agent. */
+int angel_RDI_LoadAgent(ARMword dest, unsigned long size,
+ getbufferproc *getb, void *getbarg)
+{
+ Packet *packet = NULL;
+ int status, reason, subreason, debugID, OSinfo1, OSinfo2, err;
+ time_t t;
+
+#if defined(DEBUG) || defined(DEBUG_LOADAGENT)
+ angel_DebugPrint("DEBUG: Entered angel_RDI_LoadAgent.\n");
+#endif
+ register_debug_message_handler();
+ msgsend(CI_HADP, "%w%w%w%w%w%w%w", ADP_Control | HtoT,
+ 0, ADP_HandleUnknown, ADP_HandleUnknown,
+ ADP_Ctrl_Download_Agent, dest, size);
+ reason=ADP_Control | TtoH;
+ err = wait_for_debug_message(&reason, &debugID, &OSinfo1, &OSinfo2,
+ &status, &packet);
+ if (err != RDIError_NoError) {
+ DevSW_FreePacket(packet);
+ return -1;
+ }
+ unpack_message(BUFFERDATA(packet->pk_buffer), "%w%w%w%w%w%w", &reason, &debugID,
+ &OSinfo1, &OSinfo2, &subreason, &status);
+ DevSW_FreePacket(packet);
+ if ( subreason != ADP_Ctrl_Download_Agent )
+ return RDIError_Error;
+ if ( status != RDIError_NoError )
+ return status;
+
+#if defined(DEBUG) || defined(DEBUG_LOADAGENT)
+ angel_DebugPrint("DEBUG: starting agent data download.\n");
+#endif
+ { unsigned long pos = 0, segsize;
+ for (; pos < size; pos += segsize) {
+ char *b = getb(getbarg, &segsize);
+ if (b == NULL) return RDIError_NoError;
+ err = angel_RDI_LoadConfigData( segsize, b );
+ if (err != RDIError_NoError) return err;
+ }
+ }
+#if defined(DEBUG) || defined(DEBUG_LOADAGENT)
+ angel_DebugPrint("DEBUG: finished downloading new agent.\n");
+#endif
+
+ /* renegotiate back down */
+ err = angel_negotiate_defaults();
+ if (err != adp_ok)
+ return err;
+
+ /* Output a message to tell the user what is going on. This is vital
+ * when switching from ADP EICE to ADP over JTAG, as then the user
+ * has to reset the target board !
+ */
+ { char msg[256];
+ int len=angel_RDI_errmess(msg, 256, adp_new_agent_starting);
+ angel_hostif->write(angel_hostif->hostosarg, msg, len);
+ }
+
+ /* get new image started */
+#if defined(DEBUG) || defined(DEBUG_LOADAGENT)
+ angel_DebugPrint("DEBUG: sending start message for new agent.\n");
+#endif
+
+ register_debug_message_handler();
+ msgsend(CI_HADP, "%w%w%w%w%w%w", ADP_Control | HtoT,
+ 0, ADP_HandleUnknown, ADP_HandleUnknown,
+ ADP_Ctrl_Start_Agent, dest);
+ reason=ADP_Control | TtoH;
+ err = wait_for_debug_message(&reason, &debugID, &OSinfo1, &OSinfo2,
+ &status, &packet);
+ if (err != RDIError_NoError) {
+ DevSW_FreePacket(packet);
+ return -1;
+ }
+ unpack_message(BUFFERDATA(packet->pk_buffer), "%w%w%w%w%w%w", &reason,
+ &debugID, &OSinfo1, &OSinfo2, &subreason, &status);
+ DevSW_FreePacket(packet);
+ if ( subreason != ADP_Ctrl_Start_Agent )
+ return RDIError_Error;
+ if ( status != RDIError_NoError )
+ return status;
+
+ /* wait for image to start up */
+ heartbeat_enabled = FALSE;
+ t=time(NULL);
+ do {
+ Adp_AsynchronousProcessing(async_block_on_nothing);
+ if ((time(NULL)-t) > 2) {
+#ifdef DEBUG
+ angel_DebugPrint("DEBUG: no booted message from new image yet.\n");
+#endif
+ break;
+ }
+ } while (booted_not_received);
+ booted_not_received=1;
+
+ /* Give device driver a chance to do any necessary resyncing with new agent.
+ * Only used by etherdrv.c at the moment.
+ */
+ (void)Adp_Ioctl( DC_RESYNC, NULL );
+
+#if defined(DEBUG) || defined(DEBUG_LOADAGENT)
+ angel_DebugPrint("DEBUG: reopening to new agent.\n");
+#endif
+ err = angel_RDI_open(0, NULL, NULL, NULL);
+ switch ( err )
+ {
+ case RDIError_NoError:
+ {
+#if defined(DEBUG) || defined(DEBUG_LOADAGENT)
+ angel_DebugPrint( "LoadAgent: Open returned RDIError_NoError\n" );
+#endif
+ break;
+ }
+
+ case RDIError_LittleEndian:
+ {
+#if defined(DEBUG) || defined(DEBUG_LOADAGENT)
+ angel_DebugPrint( "LoadAgent: Open returned RDIError_LittleEndian (OK)\n" );
+#endif
+ err = RDIError_NoError;
+ break;
+ }
+
+ case RDIError_BigEndian:
+ {
+#if defined(DEBUG) || defined(DEBUG_LOADAGENT)
+ angel_DebugPrint( "LoadAgent: Open returned RDIError_BigEndian (OK)\n" );
+#endif
+ err = RDIError_NoError;
+ break;
+ }
+
+ default:
+ {
+#if defined(DEBUG) || defined(DEBUG_LOADAGENT)
+ angel_DebugPrint( "LoadAgent: Open returned %d - unexpected!\n", err );
+#endif
+ break;
+ }
+ }
+#ifndef NO_HEARTBEAT
+ heartbeat_enabled = TRUE;
+#endif
+ return err;
+}
+
+static int angel_RDI_errmess(char *buf, int blen, int errnum) {
+ char *s=NULL;
+ int n;
+
+ switch (errnum) {
+ case adp_malloc_failure:
+ s=AdpMess_MallocFailed; break;
+ case adp_illegal_args:
+ s=AdpMess_IllegalArgs; break;
+ case adp_device_not_found:
+ s=AdpMess_DeviceNotFound; break;
+ case adp_device_open_failed:
+ s=AdpMess_DeviceOpenFailed; break;
+ case adp_device_already_open:
+ s=AdpMess_DeviceAlreadyOpen; break;
+ case adp_device_not_open:
+ s=AdpMess_DeviceNotOpen; break;
+ case adp_bad_channel_id:
+ s=AdpMess_BadChannelId; break;
+ case adp_callback_already_registered:
+ s=AdpMess_CBAlreadyRegd; break;
+ case adp_write_busy:
+ s=AdpMess_WriteBusy; break;
+ case adp_bad_packet:
+ s=AdpMess_BadPacket; break;
+ case adp_seq_high:
+ s=AdpMess_SeqHigh; break;
+ case adp_seq_low:
+ s=AdpMess_SeqLow; break;
+ case adp_timeout_on_open:
+ s=AdpMess_TimeoutOnOpen; break;
+ case adp_failed:
+ s=AdpMess_Failed; break;
+ case adp_abandon_boot_wait:
+ s=AdpMess_AbandonBootWait; break;
+ case adp_late_startup:
+ s=AdpMess_LateStartup; break;
+ case adp_new_agent_starting:
+ s=AdpMess_NewAgentStarting; break;
+ default: return 0;
+ }
+ n=strlen(s);
+ if (n>blen-1) n=blen-1;
+ memcpy(buf, s, n);
+ buf[n++]=0;
+ return n;
+}
+
+extern const struct RDIProcVec angel_rdi;
+const struct RDIProcVec angel_rdi = {
+ "ADP",
+ angel_RDI_open,
+ angel_RDI_close,
+ angel_RDI_read,
+ angel_RDI_write,
+ angel_RDI_CPUread,
+ angel_RDI_CPUwrite,
+ angel_RDI_CPread,
+ angel_RDI_CPwrite,
+ angel_RDI_setbreak,
+ angel_RDI_clearbreak,
+ angel_RDI_setwatch,
+ angel_RDI_clearwatch,
+ angel_RDI_execute,
+ angel_RDI_step,
+ angel_RDI_info,
+ angel_RDI_pointinq,
+
+ angel_RDI_AddConfig,
+ angel_RDI_LoadConfigData,
+ angel_RDI_SelectConfig,
+
+ 0, /*angel_RDI_drivernames,*/
+ 0, /* cpunames */
+
+ angel_RDI_errmess,
+
+ angel_RDI_LoadAgent
+};
+
+/* EOF ardi.c */
+
+/* Not strictly necessary, but allows linking this code into armsd. */
+
+struct foo {
+ char *name;
+ int (*action)();
+ char *syntax;
+ char **helpmessage;
+ int doafterend;
+ int dobeforestart;
+ int doinmidline;
+} hostappl_CmdTable[1] = {{"", NULL}};
+
+void
+hostappl_Init()
+{
+}
+
+int
+hostappl_Backstop()
+{
+ return -30;
+}
diff --git a/gdb/rdi-share/ardi.h b/gdb/rdi-share/ardi.h
new file mode 100644
index 00000000000..66acd1ad04c
--- /dev/null
+++ b/gdb/rdi-share/ardi.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
+ *
+ * This software may be freely used, copied, modified, and distributed
+ * provided that the above copyright notice is preserved in all copies of the
+ * software.
+ */
+
+/*
+ * ardi.h
+ * ADP RDI interfaces
+ *
+ * $Revision$
+ * $Date$
+ */
+
+#include "host.h"
+
+typedef unsigned32 ARMword;
+
+#include "dbg_rdi.h"
+#include "dbg_conf.h"
+
+extern char *commandline;
+extern ARMword last_vector_catch;
+
+/* This is the size of buffers that are asked for by standard channels
+ * Non standard channels may wish to copy this!
+ */
+extern int Armsd_BufferSize;
+
+typedef int (*host_ChannelBufferFilledFnPtr)(unsigned int ,unsigned char ** ,void *);
+
+int angel_RDI_open(
+ unsigned type, Dbg_ConfigBlock const *config,
+ Dbg_HostosInterface const *hostif, struct Dbg_MCState *dbg_state);
+int angel_RDI_close(void);
+
+int angel_RDI_read(ARMword source, void *dest, unsigned *nbytes);
+int angel_RDI_write(const void *source, ARMword dest, unsigned *nbytes);
+
+int angel_RDI_CPUread(unsigned mode, unsigned long mask, ARMword *buffer);
+int angel_RDI_CPUwrite(unsigned mode, unsigned long mask,
+ ARMword const *buffer);
+
+int angel_RDI_CPread(unsigned CPnum, unsigned long mask, ARMword *buffer);
+int angel_RDI_CPwrite(unsigned CPnum, unsigned long mask,
+ ARMword const *buffer);
+
+int angel_RDI_setbreak(ARMword address, unsigned type, ARMword bound,
+ PointHandle *handle);
+int angel_RDI_clearbreak(PointHandle handle);
+
+int angel_RDI_setwatch(ARMword address, unsigned type, unsigned datatype,
+ ARMword bound, PointHandle *handle);
+int angel_RDI_clearwatch(PointHandle handle);
+
+int angel_RDI_pointinq(ARMword *address, unsigned type, unsigned datatype,
+ ARMword *bound);
+
+int angel_RDI_execute(PointHandle *handle);
+
+int angel_RDI_step(unsigned ninstr, PointHandle *handle);
+
+int angel_RDI_info(unsigned type, ARMword *arg1, ARMword *arg2);
+
+int angel_RDI_AddConfig(unsigned long nbytes);
+
+int angel_RDI_LoadConfigData(unsigned long nbytes, char const *data);
+
+int angel_RDI_SelectConfig(RDI_ConfigAspect aspect, char const *name,
+ RDI_ConfigMatchType matchtype, unsigned versionreq,
+ unsigned *versionp);
+
+RDI_NameList const *angel_RDI_drivernames(void);
+
+int angel_RDI_LoadAgent(ARMword dest, unsigned long size, getbufferproc *getb,
+ void *getbarg);
+
+extern const struct Dbg_HostosInterface *angel_hostif;
+
+typedef int angel_RDI_TargetStoppedProc(unsigned stopped_reason, void *arg);
+
+extern int angel_RDI_OnTargetStopping(angel_RDI_TargetStoppedProc *fn,
+ void *arg);
diff --git a/gdb/rdi-share/armdbg.h b/gdb/rdi-share/armdbg.h
new file mode 100644
index 00000000000..b5fae113281
--- /dev/null
+++ b/gdb/rdi-share/armdbg.h
@@ -0,0 +1,1452 @@
+/*
+ * Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
+ *
+ * This software may be freely used, copied, modified, and distributed
+ * provided that the above copyright notice is preserved in all copies of the
+ * software.
+ */
+
+/*
+ * ARM symbolic debugger toolbox interface
+ */
+
+/*
+ * RCS $Revision$
+ * Checkin $Date$
+ */
+
+/* Minor points of uncertainty are indicated by a question mark in the
+ LH margin.
+
+ Wherever an interface is required to iterate over things of some class,
+ I prefer something of the form EnumerateXXs(..., XXProc *p, void *arg)
+ which results in a call of p(xx, arg) for each xx, rather than something
+ of the form
+ for (xxh = StartIterationOverXXs(); (xx = Next(xxh)) != 0; ) { ... }
+ EndIterationOverXXs(xxh);
+ Others may disagree.
+ (Each XXProc returns an Error value: if this is not Err_OK, iteration
+ stops immediately and the EnumerateXXs function returns that value).
+
+ ptrace has been retired as of insufficient utility. If such fuctionality is
+ required, it can be constructed using breakpoints.
+
+ The file form of all name fields in debug areas is in-line, with a length
+ byte and no terminator. The debugger toolbox makes an in-store translation,
+ where the strings are out of line (the namep variant in asdfmt.h) and have a
+ terminating zero byte: the pointer is to the first character of the string
+ with the length byte at ...->n.namep[-1].
+ */
+
+#ifndef armdbg__h
+#define armdbg__h
+
+#include <stddef.h>
+
+#include "host.h"
+#include "msg.h"
+
+typedef unsigned32 ARMaddress;
+typedef unsigned32 ARMword;
+typedef unsigned16 ARMhword;
+
+#include "dbg_conf.h"
+#include "dbg_rdi.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+typedef unsigned char Dbg_Byte;
+
+typedef int Dbg_Error;
+
+typedef struct Dbg_MCState Dbg_MCState;
+/* A representation of the state of the target. The structure is not revealed.
+ A pointer to one of these is returned by Dbg_Initialise(), is passed to all
+ toolbox calls which refer to the state of the target, and is discarded
+ by Dbg_Finalise().
+ Nothing in the toolbox itself precludes there being multiple targets, each
+ with its own state.
+ */
+
+/* Most toolbox interfaces return an error status. Only a few of the status
+ values are expected to be interesting to clients and defined here; the
+ rest are private (but a textual form can be produced by ErrorToChars()).
+ */
+
+#define Error_OK 0
+
+/* Partitioning of the error code space: errors below Dbg_Error_Base are RDI
+ errors (as defined in dbg_rdi.h). Codes above Dbg_Error_Limit are
+ available to clients, who may impose some further structure.
+ */
+#define Dbg_Error_Base 0x1000
+#define Dbg_Error_Limit 0x2000
+
+#define DbgError(n) ((Dbg_Error)(Dbg_Error_Base+(n)))
+
+#define Dbg_Err_OK Error_OK
+#define Dbg_Err_Interrupted DbgError(1)
+#define Dbg_Err_Overflow DbgError(2)
+#define Dbg_Err_FileNotFound DbgError(3)
+#define Dbg_Err_ActivationNotPresent DbgError(4)
+#define Dbg_Err_OutOfHeap DbgError(5)
+#define Dbg_Err_TypeNotSimple DbgError(6)
+#define Dbg_Err_BufferFull DbgError(7)
+#define Dbg_Err_AtStackBase DbgError(8)
+#define Dbg_Err_AtStackTop DbgError(9)
+#define Dbg_Err_DbgTableFormat DbgError(10)
+#define Dbg_Err_NotVariable DbgError(11)
+#define Dbg_Err_NoSuchBreakPoint DbgError(12)
+#define Dbg_Err_NoSuchWatchPoint DbgError(13)
+#define Dbg_Err_FileLineNotFound DbgError(14)
+#define Dbg_Err_DbgTableVersion DbgError(15)
+#define Dbg_Err_NoSuchPath DbgError(16)
+#define Dbg_Err_StateChanged DbgError(17)
+#define Dbg_Err_SoftInitialiseError DbgError(18)
+#define Dbg_Err_CoProRegNotWritable DbgError(19)
+#define Dbg_Err_NotInHistory DbgError(20)
+#define Dbg_Err_ContextSyntax DbgError(21)
+#define Dbg_Err_ContextNoLine DbgError(22)
+#define Dbg_Err_ContextTwoLines DbgError(23)
+#define Dbg_Err_VarReadOnly DbgError(24)
+#define Dbg_Err_FileNewerThanImage DbgError(25)
+#define Dbg_Err_NotFound DbgError(26)
+
+ /* functions which evaluate expressions may return this value, to indicate
+ that execution became suspended within a function called in the debugee */
+
+/* Functions returning characters take a BufDesc argument, with fields buffer
+ and bufsize being input arguments describing the buffer to be filled, and
+ filled being set on return to the number of bytes written to the buffer
+ (omitting the terminating 0).
+ */
+
+typedef struct Dbg_BufDesc Dbg_BufDesc;
+
+typedef void Dbg_BufferFullProc(Dbg_BufDesc *bd);
+
+struct Dbg_BufDesc {
+ char *buffer;
+ size_t size,
+ filled;
+ Dbg_BufferFullProc *p;
+ void *arg;
+};
+
+#define Dbg_InitBufDesc(bd, buf, bytes) \
+ ((bd).buffer = (buf), (bd).size = (bytes), (bd).filled = 0,\
+ (bd).p = NULL, (bd).arg = NULL)
+
+#define Dbg_InitBufDesc_P(bd, buf, bytes, fn, a) \
+ ((bd).buffer = (buf), (bd).size = (bytes), (bd).filled = 0,\
+ (bd).p = (fn), (bd).arg = (a))
+
+Dbg_Error Dbg_StringToBuf(Dbg_BufDesc *buf, char const *s);
+Dbg_Error Dbg_BufPrintf(Dbg_BufDesc *buf, char const *form, ...);
+#ifdef NLS
+Dbg_Error Dbg_MsgToBuf(Dbg_BufDesc *buf, msg_t t);
+Dbg_Error Dbg_BufMsgPrintf(Dbg_BufDesc *buf, msg_t form, ...);
+#else
+#define Dbg_MsgToBuf Dbg_StringToBuf
+#define Dbg_BufMsgPrintf Dbg_BufPrintf
+#endif
+Dbg_Error Dbg_CharToBuf(Dbg_BufDesc *buf, int ch);
+
+int Dbg_CIStrCmp(char const *s1, char const *s2);
+/* Case-independent string comparison, interface as for strcmp */
+
+int Dbg_CIStrnCmp(char const *s1, char const *s2, size_t n);
+/* Case-independent string comparison, interface as for strncmp */
+
+void Dbg_ErrorToChars(Dbg_MCState *state, Dbg_Error err, Dbg_BufDesc *buf);
+
+typedef int Dbg_RDIResetCheckProc(int);
+/* Type of a function to be called after each RDI operation performed by the
+ toolbox, with the status from the operation as argument. The value returned
+ is treated as the status. (The intent is to allow the toolbox's client to
+ take special action to handle RDIDbg_Error_Reset).
+ */
+
+typedef struct Dbg_CoProDesc Dbg_CoProDesc;
+
+typedef Dbg_Error Dbg_CoProFoundProc(Dbg_MCState *state, int cpno, Dbg_CoProDesc const *cpd);
+/* Type of a function to be called when the shape of a coprocessor is discovered
+ by enquiry of the target or agent (via RequestCoProDesc)
+ */
+
+typedef struct RDIProcVec RDIProcVec;
+
+Dbg_Error Dbg_RequestReset(Dbg_MCState *);
+
+Dbg_Error Dbg_Initialise(
+ Dbg_ConfigBlock *config, Dbg_HostosInterface const *i,
+ Dbg_RDIResetCheckProc *checkreset, Dbg_CoProFoundProc *coprofound,
+ RDIProcVec const *rdi, Dbg_MCState **statep);
+/* values in config are updated if they call for default values */
+
+void Dbg_Finalise(Dbg_MCState *state, bool targetdead);
+
+typedef struct {
+ char name[16];
+ RDI_MemDescr md;
+ RDI_MemAccessStats a;
+} Dbg_MemStats;
+
+/*--------------------------------------------------------------------------*/
+
+/* Symbol table management.
+ The structure of a Dbg_SymTable is not revealed. It is created by
+ Dbg_ReadSymbols() or by Dbg_LoadFile(), and associated with the argument
+ Dbg_MCState.
+ Many symbol tables may be concurrently active.
+ A Dbg_SymTable is removed either explicitly (by call to Dbg_DeleteSymbols)
+ or implicitly when a symbol table for an overlapping address range is read.
+
+ There is a pre-defined symbol table containing entries for ARM registers,
+ co-processor registers and the like.
+ */
+
+typedef struct Dbg_SymTable Dbg_SymTable;
+
+typedef struct Dbg_ImageFragmentDesc {
+ ARMaddress base, limit;
+} Dbg_ImageFragmentDesc;
+
+typedef enum {
+ Dbg_Lang_None,
+ Dbg_Lang_C,
+ Dbg_Lang_Pascal,
+ Dbg_Lang_Fortran,
+ Dbg_Lang_Asm,
+ Dbg_Lang_Cpp
+} Dbg_Lang;
+
+typedef struct Dbg_ImageDesc {
+ Dbg_Lang lang;
+ int executable;
+ ARMaddress robase, rolimit, rwbase, rwlimit;
+ int nfrags;
+ Dbg_ImageFragmentDesc *fragments;
+ char *name;
+} Dbg_ImageDesc;
+
+Dbg_ImageDesc *Dbg_ImageAreas(Dbg_SymTable *st);
+
+Dbg_SymTable *Dbg_LastImage(Dbg_MCState *state);
+
+Dbg_SymTable *Dbg_NewSymTable(Dbg_MCState *state, const char *name);
+
+Dbg_Error Dbg_ReadSymbols(Dbg_MCState *state, const char *filename, Dbg_SymTable **st);
+/* Just read the symbols from the named image. <st> is set to the allocated
+ symbol table.
+? Maybe we could usefully allow other formats than AIF images to describe
+ the symbols (eg) of shared libraries
+ */
+
+typedef struct Dbg_SymInfo {
+ int isize;
+ ARMaddress addr;
+ char *name;
+} Dbg_SymInfo;
+
+Dbg_SymInfo *Dbg_AsmSym(Dbg_SymTable *st, ARMaddress addr);
+int32 Dbg_AsmAddr(Dbg_SymTable *st, int32 line);
+int32 Dbg_AsmLine(Dbg_SymTable *st, ARMaddress addr);
+int32 Dbg_AsmLinesInRange(Dbg_SymTable *st, ARMaddress start, ARMaddress end);
+
+Dbg_Error Dbg_LoadFile(Dbg_MCState *state, const char *filename, Dbg_SymTable **st);
+/* load the image into target memory, and read its symbols. <st> is set to
+ the allocated symbol table.
+ A null filename reloads the most recently loaded file (and rereads its
+ symbols).
+ Loading an image leaves breakpoints unchanged. If a client wishes
+ otherwise, it must remove the breakpoints explicitly.
+*/
+
+Dbg_Error Dbg_CallGLoadFile(Dbg_MCState *state, const char *filename, Dbg_SymTable **st);
+
+typedef void Dbg_ImageLoadProc(Dbg_MCState *, Dbg_SymTable *);
+Dbg_Error Dbg_OnImageLoad(Dbg_MCState *, Dbg_ImageLoadProc *);
+/* Register function to be called back whenever an image is loaded, or symbols
+ * for an image read. (To allow multiple toolbox clients to coexist).
+ */
+
+Dbg_Error Dbg_LoadAgent(Dbg_MCState *state, const char *filename);
+/* Load a debug agent, and start it.
+ Symbols in the image for the agent are ignored.
+*/
+
+Dbg_Error Dbg_RelocateSymbols(Dbg_SymTable *st, ARMaddress reloc);
+/* add <reloc> to the value of all symbols in <st> describing absolute memory
+ locations. The intent is to allow the symbols in a load-time relocating
+ image (for example) to be useful.
+ */
+
+Dbg_Error Dbg_DeleteSymbols(Dbg_MCState *state, Dbg_SymTable **st);
+
+typedef enum Dbg_LLSymType {
+ llst_code,
+ llst_code16,
+ llst_data,
+ llst_const,
+ llst_unknown,
+ llst_max
+} Dbg_LLSymType;
+/* Since AIF images contain no type information for low-level symbols, this
+ classification is only a guess, and some symbols describing constants will
+ incorrectly be described as code or data.
+ */
+
+typedef Dbg_Error Dbg_SymProc(
+ Dbg_MCState *state,
+ const char *symbol, Dbg_LLSymType symtype, ARMaddress value,
+ void *arg);
+
+Dbg_Error Dbg_EnumerateLowLevelSymbols(
+ Dbg_MCState *state, const char *match, Dbg_SymProc *p,
+ void *arg);
+/* Call p(name, value) for each low level symbol in the tables of <state>
+ whose name matches the regular expression <match> (a NULL <match> matches
+ any name). Symbols are enumerated in no particular order.
+ */
+
+/*--------------------------------------------------------------------------*/
+
+/* Functions are provided here to allow quick mass access to register values
+ for display. There is no comparable need for quick mass update, so writing
+ should be via Assign().
+ */
+
+typedef struct Dbg_RegSet {
+ ARMword
+ user[15],
+ pc,
+ psr,
+ fiq[7],
+ spsr_fiq,
+ irq[2],
+ spsr_irq,
+ svc[2],
+ spsr_svc,
+ abort[2],
+ spsr_abort,
+ undef[2],
+ spsr_undef;
+} Dbg_RegSet;
+
+/* bits in the modemask argument for ReadRegisters */
+
+#define Dbg_MM_User 1
+#define Dbg_MM_FIQ 2
+#define Dbg_MM_IRQ 4
+#define Dbg_MM_SVC 8
+#define Dbg_MM_Abort 0x10
+#define Dbg_MM_Undef 0x20
+#define Dbg_MM_System 0x40
+
+Dbg_Error Dbg_ReadRegisters(Dbg_MCState *state, Dbg_RegSet *regs, int modemask);
+
+Dbg_Error Dbg_WriteRegister(Dbg_MCState *state, int rno, int modemask, ARMword val);
+
+int Dbg_StringToMode(const char *name);
+
+int Dbg_ModeToModeMask(ARMword mode);
+
+/* Some implementations of the FP instruction set keep FP values loaded into
+ registers in their unconverted format, converting only when necessary.
+ Some RDI implementations deliver these values uninterpreted.
+ (For the rest, register values will always have type F_Extended).
+ */
+
+typedef enum { F_Single, F_Double, F_Extended, F_Packed, /* fpe340 values */
+ F_Internal, /* new fpe : mostly as extended */
+ F_None } Dbg_FPType;
+
+typedef struct { ARMword w[3]; } Dbg_TargetExtendedVal;
+typedef struct { ARMword w[3]; } Dbg_TargetPackedVal;
+typedef struct { ARMword w[2]; } Dbg_TargetDoubleVal;
+typedef struct { ARMword w[1]; } Dbg_TargetFloatVal;
+
+typedef union { Dbg_TargetExtendedVal e; Dbg_TargetPackedVal p;
+ Dbg_TargetDoubleVal d; Dbg_TargetFloatVal f; } Dbg_TargetFPVal;
+
+#define TargetSizeof_Extended 12
+#define TargetSizeof_Packed 12
+#define TargetSizeof_Double 8
+#define TargetSizeof_Float 4
+
+typedef struct Dbg_FPRegVal {
+ Dbg_FPType type;
+ Dbg_TargetFPVal v;
+} Dbg_FPRegVal;
+
+typedef struct Dbg_FPRegSet {
+ Dbg_FPRegVal f[8];
+ ARMword fpsr, fpcr;
+} Dbg_FPRegSet;
+
+Dbg_Error Dbg_ReadFPRegisters(Dbg_MCState *state, Dbg_FPRegSet *regs);
+
+Dbg_Error Dbg_WriteFPRegisters(Dbg_MCState *state, int32 mask, Dbg_FPRegSet *regs);
+
+Dbg_Error Dbg_FPRegToDouble(DbleBin *d, Dbg_FPRegVal const *f);
+/* Converts from a FP register value (in any format) to a double with
+ approximately the same value (or returns Dbg_Err_Overflow)
+ */
+
+void Dbg_DoubleToFPReg(Dbg_FPRegVal *f, DbleBin const *d);
+/* Converts the double <d> to a Dbg_FPRegVal with type F_Extended */
+
+/*--------------------------------------------------------------------------*/
+
+#include "dbg_cp.h"
+
+Dbg_Error Dbg_DescribeCoPro(Dbg_MCState *state, int cpnum, Dbg_CoProDesc *p);
+
+Dbg_Error Dbg_DescribeCoPro_RDI(Dbg_MCState *state, int cpnum, Dbg_CoProDesc *p);
+
+Dbg_Error Dbg_ReadCPRegisters(Dbg_MCState *state, int cpnum, ARMword *regs);
+
+Dbg_Error Dbg_WriteCPRegisters(Dbg_MCState *state, int cpnum, int32 mask, ARMword *regs);
+
+/*--------------------------------------------------------------------------*/
+
+Dbg_Error Dbg_ReadWords(
+ Dbg_MCState *state,
+ ARMword *words, ARMaddress addr, unsigned count);
+/* Reads a number of (32-bit) words from target store. The values are in host
+ byte order; if they are also to be interpreted as bytes Dbg_SwapByteOrder()
+ must be called to convert to target byte order.
+ */
+
+Dbg_Error Dbg_WriteWords(
+ Dbg_MCState *state,
+ ARMaddress addr, const ARMword *words, unsigned count);
+/* Writes a number of (32-bit) words to target store. The values are in host
+ byte order (if what is being written is actually a byte string it must be
+ converted by Dbg_SwapByteOrder()).
+ */
+
+Dbg_Error Dbg_ReadHalf(Dbg_MCState *state, ARMhword *val, ARMaddress addr);
+Dbg_Error Dbg_WriteHalf(Dbg_MCState *state, ARMaddress addr, ARMword val);
+
+Dbg_Error Dbg_ReadBytes(Dbg_MCState *state, Dbg_Byte *val, ARMaddress addr, unsigned count);
+Dbg_Error Dbg_WriteBytes(Dbg_MCState *state, ARMaddress addr, const Dbg_Byte *val, unsigned count);
+
+void Dbg_HostWords(Dbg_MCState *state, ARMword *words, unsigned wordcount);
+/* (A noop unless host and target bytesexes differ) */
+
+ARMword Dbg_HostWord(Dbg_MCState *state, ARMword v);
+
+ARMhword Dbg_HostHalf(Dbg_MCState *state, ARMword v);
+
+/*--------------------------------------------------------------------------*/
+
+/* Types describing various aspects of position within code.
+ There are rather a lot of these, in the interests of describing precisely
+ what fields must be present (rather than having a single type with many
+ fields which may or may not be valid according to context).
+ */
+
+typedef struct Dbg_LLPos {
+ Dbg_SymTable *st;
+ char *llsym;
+ ARMaddress offset;
+} Dbg_LLPos;
+
+typedef struct Dbg_File {
+ Dbg_SymTable *st;
+ char *file;
+} Dbg_File;
+
+typedef struct Dbg_Line {
+ unsigned32 line; /* linenumber in the file */
+ unsigned16 statement, /* within the line (1-based) */
+ charpos; /* ditto */
+} Dbg_Line;
+/* As an output value from toolbox functions, both statement and charpos are set
+ if the version of the debugger tables for the section concerned permits.
+ On input, <charpos> is used only if <statement> is 0 (in which case, if
+ <charpos> is non-0, Dbg_Err_DbgTableVersion is returned if the version of
+ the debugger tables concerned is too early.
+ */
+
+typedef struct Dbg_FilePos {
+ Dbg_File f;
+ Dbg_Line line;
+} Dbg_FilePos;
+
+typedef struct Dbg_ProcDesc {
+ Dbg_File f;
+ char *name;
+} Dbg_ProcDesc;
+
+typedef struct Dbg_ProcPos {
+ Dbg_ProcDesc p;
+ Dbg_Line line;
+} Dbg_ProcPos;
+
+/* Support for conversions between position representations */
+
+Dbg_Error Dbg_ProcDescToLine(Dbg_MCState *state, Dbg_ProcDesc *proc, Dbg_Line *line);
+/* If proc->f.file is null (and there is just one function proc->name), it is
+ updated to point to the name of the file containing (the start of)
+ proc->name.
+ */
+
+Dbg_Error Dbg_FilePosToProc(Dbg_MCState *state, const Dbg_FilePos *pos, char **procname);
+
+/* Conversions from position representations to and from code addresses */
+
+Dbg_Error Dbg_AddressToProcPos(
+ Dbg_MCState *state, ARMaddress addr,
+ Dbg_ProcPos *pos);
+Dbg_Error Dbg_AddressToLLPos(
+ Dbg_MCState *state, ARMaddress addr,
+ Dbg_LLPos *pos, Dbg_LLSymType *res_type, int system_names);
+
+Dbg_Error Dbg_ProcPosToAddress(
+ Dbg_MCState *state, const Dbg_ProcPos *pos,
+ ARMaddress *res);
+Dbg_Error Dbg_LLPosToAddress(
+ Dbg_MCState *state, const Dbg_LLPos *pos,
+ ARMaddress *res);
+
+typedef struct {
+ ARMaddress start, end;
+} Dbg_AddressRange;
+
+typedef Dbg_Error Dbg_AddressRangeProc(void *arg, int32 first, int32 last, Dbg_AddressRange const *range);
+
+Dbg_Error Dbg_MapAddressRangesForFileRange(
+ Dbg_MCState *state,
+ Dbg_SymTable *st, const char *f, int32 first, int32 last, Dbg_AddressRangeProc *p, void *arg);
+
+typedef struct Dbg_Environment Dbg_Environment;
+/* A Dbg_Environment describes the context required to make sense of a variable
+ name and access its value. Its format is not revealed. Dbg_Environment
+ values are allocated by Dbg_NewEnvironment() and discarded by
+ Dbg_DeleteEnvironment().
+ */
+
+Dbg_Environment *Dbg_NewEnvironment(Dbg_MCState *state);
+void Dbg_DeleteEnvironment(Dbg_MCState *state, Dbg_Environment *env);
+
+Dbg_Error Dbg_StringToEnv(
+ Dbg_MCState *state, char *str, Dbg_Environment *resenv,
+ int forcontext, Dbg_Environment const *curenv);
+
+Dbg_Error Dbg_ProcPosToEnvironment(
+ Dbg_MCState *state, const Dbg_ProcPos *pos, int activation,
+ const Dbg_Environment *current, Dbg_Environment *res);
+
+/* Conversion from a position representation to an Dbg_Environment (as required
+ to access variable values). Only a Dbg_ProcPos argument here; other
+ representations need to be converted first.
+
+ Returns <res> describing the <activation>th instance of the function
+ described by <pos>, up from the stack base if <activation> is negative,
+ else down from <current>.
+ If this function returns Dbg_Err_ActivationNotPresent, the result
+ Dbg_Environment is still valid for accessing non-auto variables.
+ */
+
+typedef struct Dbg_DeclSpec Dbg_DeclSpec;
+
+Dbg_Error Dbg_EnvToProcItem(
+ Dbg_MCState *state, Dbg_Environment const *env, Dbg_DeclSpec *proc);
+
+Dbg_Error Dbg_ContainingEnvironment(
+ Dbg_MCState *state, const Dbg_Environment *context, Dbg_Environment *res);
+/* Set <res> to describe the containing function, file if <context> is within
+ a top-level function (or error if <context> already describes a file).
+ */
+
+/*--------------------------------------------------------------------------*/
+
+/* ASD debug table pointers are not by themselves sufficient description,
+ since there's an implied section context. Hence the DeclSpec and TypeSpec
+ structures.
+ */
+
+
+#ifndef Dbg_TypeSpec_Defined
+
+struct Dbg_DeclSpec { void *a; };
+
+#ifdef CALLABLE_COMPILER
+typedef void *Dbg_TypeSpec;
+
+/* The intention here is to give an alternative definition for Dbg_BasicType
+ which follows.
+ */
+
+#define Dbg_T_Void xDbg_T_Void
+#define Dbg_T_Bool xDbg_T_Bool
+#define Dbg_T_SByte xDbg_T_SByte
+#define Dbg_T_SHalf xDbg_T_Half
+#define Dbg_T_SWord xDbg_T_SWord
+#define Dbg_T_UByte xDbg_T_UByte
+#define Dbg_T_UHalf xDbg_T_UHalf
+#define Dbg_T_UWord xDbg_T_UWord
+#define Dbg_T_Float xDbg_T_Float
+#define Dbg_T_Double xDbg_T_Double
+#define Dbg_T_LDouble xDbg_T_LDouble
+#define Dbg_T_Complex xDbg_T_Complex
+#define Dbg_T_DComplex xDbg_T_DComplex
+#define Dbg_T_String xDbg_T_String
+#define Dbg_T_Function xDbg_T_Function
+
+#define Dbg_BasicType xDbg_BaiscType
+#define Dbg_PrimitiveTypeToTypeSpec xDbg_PrimitiveTypeToTypeSpec
+
+#else
+/* We want a Dbg_TypeSpec to be a an opaque type, but of known size (so the
+ toolbox's clients can allocate the store to hold one); unfortunately, we
+ can do this only by having one definition for the toolbox's clients and
+ one (elsewhere) for the toolbox itself.
+ */
+
+typedef struct Dbg_TypeSpec Dbg_TypeSpec;
+struct Dbg_TypeSpec { void *a; int32 b; };
+#endif /* CALLABLE_COMPILER */
+
+typedef enum {
+ Dbg_T_Void,
+
+ Dbg_T_Bool,
+
+ Dbg_T_SByte,
+ Dbg_T_SHalf,
+ Dbg_T_SWord,
+
+ Dbg_T_UByte,
+ Dbg_T_UHalf,
+ Dbg_T_UWord,
+
+ Dbg_T_Float,
+ Dbg_T_Double,
+ Dbg_T_LDouble,
+
+ Dbg_T_Complex,
+ Dbg_T_DComplex,
+
+ Dbg_T_String,
+
+ Dbg_T_Function
+} Dbg_BasicType;
+
+#endif
+
+void Dbg_PrimitiveTypeToTypeSpec(Dbg_TypeSpec *ts, Dbg_BasicType t);
+
+bool Dbg_TypeIsIntegral(Dbg_TypeSpec const *ts);
+
+bool Dbg_TypeIsPointer(Dbg_TypeSpec const *ts);
+
+bool Dbg_TypeIsFunction(Dbg_TypeSpec const *ts);
+
+bool Dbg_PruneType(Dbg_TypeSpec *tsres, Dbg_TypeSpec const *ts);
+/* Return to tsres a version of ts which has been pruned by the removal of all
+ toplevel typedefs. Result is YES if the result has changed.
+ */
+
+typedef Dbg_Error Dbg_FileProc(Dbg_MCState *state, const char *name, const Dbg_DeclSpec *procdef, void *arg);
+
+Dbg_Error Dbg_EnumerateFiles(Dbg_MCState *state, Dbg_SymTable *st, Dbg_FileProc *p, void *arg);
+/* The top level for a high level enumerate. Lower levels are performed by
+ EnumerateDeclarations (below).
+ */
+
+typedef enum {
+ ds_Invalid,
+ ds_Type,
+ ds_Var,
+ ds_Proc,
+ ds_Enum,
+ ds_Function,
+ ds_Label
+} Dbg_DeclSort;
+
+Dbg_DeclSort Dbg_SortOfDeclSpec(Dbg_DeclSpec const *decl);
+
+char *Dbg_NameOfDeclSpec(Dbg_DeclSpec const *decl);
+
+Dbg_TypeSpec Dbg_TypeSpecOfDeclSpec(Dbg_DeclSpec const *decl);
+
+typedef enum {
+ cs_None,
+ cs_Extern,
+ cs_Static,
+ cs_Auto,
+ cs_Reg,
+ cs_Var,
+ cs_Farg,
+ cs_Fcarg,
+ cs_Local,
+ cs_Filtered,
+ cs_Globalreg
+} Dbg_StgClass;
+
+Dbg_StgClass Dbg_StgClassOfDeclSpec(Dbg_DeclSpec const *decl);
+
+bool Dbg_VarsAtSameAddress(Dbg_DeclSpec const *d1, Dbg_DeclSpec const *d2);
+
+bool Dbg_VarsDecribedForDeclSpec(Dbg_DeclSpec const *decl);
+
+int Dbg_ArgCountOfDeclSpec(Dbg_DeclSpec const *decl);
+
+typedef struct Dbg_DComplex { DbleBin r, i; } Dbg_DComplex;
+
+typedef union Dbg_ConstantVal {
+ int32 l;
+ unsigned32 u;
+ DbleBin d;
+ Dbg_DComplex fc;
+ ARMaddress a;
+ char *s;
+} Dbg_ConstantVal;
+
+typedef struct Dbg_Constant {
+ Dbg_TypeSpec type;
+ Dbg_ConstantVal val;
+} Dbg_Constant;
+
+typedef enum Dbg_ValueSort {
+ vs_register,
+ vs_store,
+ vs_constant,
+ vs_local,
+ vs_filtered,
+ vs_none,
+ vs_error
+} Dbg_ValueSort;
+
+/* vs_local allows the use of symbol table entries to describe entities within
+ the debugger's own address space, accessed in the same way as target
+ variables.
+ vs_filtered describes entities which may be read or written only via an
+ access function (eg r15)
+ */
+
+#define fpr_base 16
+/* There's only one register ValueSort (reflecting asd table StgClass);
+ fp register n is encoded as register n+fpr_base.
+ */
+
+typedef struct Dbg_Value Dbg_Value;
+
+typedef Dbg_Error Dbg_AccessFn(Dbg_MCState *state, int write, Dbg_Value *self, Dbg_Constant *c);
+/* <write> == 0: read a vs_filtered value, updating the value self.
+ <write> == 1: update a vs_filtered value, with the value described by c.
+ <self> allows use of the same Dbg_AccessFn for several different entities
+ (using different val.f.id fields).
+ */
+
+typedef Dbg_Error Dbg_FormatFn(int decode, char *b, ARMword *valp, void *formatarg);
+
+typedef struct { Dbg_AccessFn *f; int id; } Dbg_AccessFnRec;
+
+struct Dbg_Value {
+ Dbg_TypeSpec type;
+ Dbg_ValueSort sort;
+ Dbg_FormatFn *formatp;
+ void *formatarg;
+ int f77csize;
+ union {
+ struct { int no; ARMaddress frame; } r;
+ ARMaddress ptr;
+ Dbg_ConstantVal c;
+ void *localp;
+ Dbg_AccessFnRec f;
+ Dbg_Error err;
+ } val;
+};
+
+Dbg_Error Dbg_AddLLSymbol(Dbg_SymTable *st, char const *name, Dbg_LLSymType type, ARMword val);
+
+Dbg_Error Dbg_AddSymbol(Dbg_SymTable *st, char const *name, Dbg_Value const *val);
+
+typedef struct Dbg_DeclSpecF {
+ Dbg_DeclSpec decl;
+ Dbg_FormatFn *formatp;
+ void *formatarg;
+} Dbg_DeclSpecF;
+
+typedef Dbg_Error Dbg_DeclProc(Dbg_MCState *state, Dbg_Environment const *context,
+ Dbg_DeclSpecF const *var, Dbg_DeclSort sort, int masked,
+ void *arg);
+
+Dbg_Error Dbg_EnumerateDeclarations(Dbg_MCState *state, Dbg_Environment const *context,
+ Dbg_DeclProc *p, void *arg);
+/* call p once for every declaration local to the function described by
+ <context> (or file if <context> describes a place outside a function).
+ p's argument <masked> is true if the variable is not visible, thanks to
+ a declaration in an inner scope.
+ */
+
+Dbg_Error Dbg_ValueOfVar(Dbg_MCState *state, const Dbg_Environment *context,
+ const Dbg_DeclSpec *var, Dbg_Value *val);
+/* Different from Dbg_EvalExpr() in that the thing being evaluated is described
+ by a Dbg_DeclSpec (which must be for a variable), rather than a string
+ needing to be decoded and associated with a symbol-table item. Intended to
+ be called from a Dbg_DeclProc called from Dbg_EnumerateDeclarations.
+ */
+
+Dbg_Error Dbg_EvalExpr(Dbg_MCState *state, Dbg_Environment const *context,
+ char const *expr, int flags, Dbg_Value *val);
+
+Dbg_Error Dbg_EvalExpr_ep(Dbg_MCState *state, Dbg_Environment const *context,
+ char const *expr, char **exprend, int flags, Dbg_Value *val);
+
+/* Both Dbg_ValueOfVar and Dbg_EvalExpr mostly deliver a value still containing
+ an indirection (since it may be wanted as the lhs of an assignment)
+ */
+
+void Dbg_RealLocation(Dbg_MCState *state, Dbg_Value *val);
+/* If val describes a register, this may really be a register, or a place on
+ the stack where the register's value is saved. In the latter case, val
+ is altered to describe the save place. (In all others, it remains
+ unchanged).
+ */
+
+Dbg_Error Dbg_DereferenceValue(Dbg_MCState *state, const Dbg_Value *value, Dbg_Constant *c);
+/* This fails if <value> describes a structure or array, returning
+ Dbg_Err_TypeNotSimple
+ */
+
+typedef struct Dbg_Expr Dbg_Expr;
+/* The result of parsing an expression in an environment: its structure is not
+ revealed. (Clients may wish to parse just once an expression which may be
+ evaluated often). In support of which, the following two functions partition
+ the work of Dbg_EvalExpr().
+ */
+
+#define Dbg_exfl_heap 1 /* allocate Expr on the heap (FreeExpr must then be
+ called to discard it). Otherwise, it goes in a
+ place overwritten by the next call to ParseExpr
+ or EvalExpr
+ */
+#define Dbg_exfl_needassign 2
+#define Dbg_exfl_lowlevel 4
+
+int Dbg_SetInputRadix(Dbg_MCState *state, int radix);
+char *Dbg_SetDefaultIntFormat(Dbg_MCState *state, char *format);
+
+Dbg_Error Dbg_ParseExpr(
+ Dbg_MCState *state, Dbg_Environment const *env, char *string,
+ char **end, Dbg_Expr **res, int flags);
+/* Just parse the argument string, returning a pointer to a parsed expression
+ and a pointer to the first non-white space character in the input string
+ which is not part of the parsed expression. (If macro expansion has taken
+ place, the returned pointer will not be into the argument string at all,
+ rather into the expanded version of it).
+ */
+
+Dbg_Error Dbg_ParseExprCheckEnd(
+ Dbg_MCState *state, Dbg_Environment const *env, char *string,
+ Dbg_Expr **res, int flags);
+/* As Dbg_ParseExpr, but the parsed expression is required completely to fill
+ the argument string (apart possibly for trailing whitespace), and an error
+ is returned if it does not.
+ */
+
+Dbg_Error Dbg_ParsedExprToValue(
+ Dbg_MCState *state, const Dbg_Environment *env, Dbg_Expr *expr, Dbg_Value *v);
+
+Dbg_Error Dbg_ReadDecl(
+ Dbg_MCState *state, Dbg_Environment const *env, char *string,
+ Dbg_TypeSpec *p, char **varp, int flags);
+/* Read a variable declaration, returing a description of the type of the
+ variable to p, and a pointer to its name to varp.
+ */
+
+bool Dbg_IsCastToArrayType(Dbg_MCState *state, Dbg_Expr *expr);
+
+void Dbg_FreeExpr(Dbg_Expr *expr);
+
+Dbg_Error Dbg_CopyType(Dbg_TypeSpec *tdest, Dbg_TypeSpec const *tsource);
+Dbg_Error Dbg_FreeCopiedType(Dbg_TypeSpec *ts);
+
+Dbg_Error Dbg_TypeOfExpr(Dbg_MCState *state, Dbg_Expr *tree, Dbg_TypeSpec *restype);
+
+Dbg_Error Dbg_ExprToVar(const Dbg_Expr *expr, Dbg_DeclSpec *var, Dbg_Environment *env);
+
+Dbg_Error Dbg_Assign(Dbg_MCState *state, const Dbg_Value *lv, const Dbg_Value *rv);
+
+typedef enum Dbg_TypeSort {
+ ts_simple,
+ ts_union,
+ ts_struct,
+ ts_array
+} Dbg_TypeSort;
+
+Dbg_TypeSort Dbg_TypeSortOfValue(Dbg_MCState *state, const Dbg_Value *val, int *fieldcount);
+
+Dbg_Error Dbg_TypeToChars(const Dbg_TypeSpec *var, Dbg_BufDesc *buf);
+
+Dbg_Error Dbg_TypeSize(Dbg_MCState *state, const Dbg_TypeSpec *type, unsigned32 *res);
+
+typedef int Dbg_ValToChars_cb(Dbg_MCState *state, Dbg_Value *subval, const char *fieldname,
+ Dbg_BufDesc *buf, void *arg);
+
+Dbg_Error Dbg_ValToChars(Dbg_MCState *state, Dbg_Value *val, int base,
+ Dbg_ValToChars_cb *cb, void *arg,
+ const char *form, Dbg_BufDesc *buf);
+/*
+ <base> is used for (any size) integer values.
+ If <val> is of an array or structure type, <cb> is called for each element,
+ with <arg> as its last parameter, and <subbuf> describing the space remaining
+ in <buf>. If <cb> returns 0, conversion ceases.
+ */
+
+Dbg_Error Dbg_NthElement(
+ Dbg_MCState *state,
+ const Dbg_Value *val, unsigned32 n, char **fieldname, Dbg_Value *subval);
+
+typedef Dbg_Error Dbg_HistoryProc(void *, int, Dbg_Value *);
+
+Dbg_Error Dbg_RegisterHistoryProc(Dbg_MCState *state, Dbg_HistoryProc *p, void *arg);
+
+typedef enum {
+ ls_cpu,
+ ls_store,
+ ls_copro,
+ ls_local,
+ ls_filtered
+} Dbg_LocSort;
+
+typedef struct {
+ Dbg_LocSort sort;
+ union {
+ struct { ARMaddress addr, size; } store;
+ struct { int modemask; int r; } cpu;
+ struct { int no; int r; } cp;
+ void *localp;
+ Dbg_AccessFnRec f;
+ } loc;
+} Dbg_Loc;
+
+typedef Dbg_Error Dbg_ObjectWriteProc(Dbg_MCState *state, Dbg_Loc const *loc);
+Dbg_Error Dbg_OnObjectWrite(Dbg_MCState *state, Dbg_ObjectWriteProc *p);
+/* Register function to be called back whenever the toolbox has written to any
+ * object accessible by the debuggee (or to local variables belonging to a
+ * toolbox client). The write has already been done.
+ * (To allow multiple toolbox clients to coexist).
+ */
+
+Dbg_Error Dbg_ObjectWritten(Dbg_MCState *state, Dbg_Loc const *loc);
+
+/*--------------------------------------------------------------------------*/
+
+/* Control of target program execution.
+ Currently, only synchronous operation is provided.
+ Execution could possibly be asynchronous where the target is a seperate
+ processor, but is necessarily synchronous if the target is Armulator.
+ Unfortunately, this may require modification to the RDI implementation
+ if multitasking is required but the the host system provides it only
+ cooperatively, or if there is no system-provided way to generate SIGINT.
+ */
+
+Dbg_Error Dbg_SetCommandline(Dbg_MCState *state, const char *args);
+/* Set the argument string to the concatenation of the name of the most
+ recently loaded image and args.
+ */
+
+typedef enum Dbg_ProgramState {
+ ps_notstarted,
+ /* Normal ways of stopping */
+ ps_atbreak, ps_atwatch, ps_stepdone,
+ ps_interrupted,
+ ps_stopped,
+ /* abnormal (but unsurprising) ways of stopping */
+ ps_lostwatch,
+ ps_branchthrough0, ps_undef, ps_caughtswi, ps_prefetch,
+ ps_abort, ps_addrexcept, ps_caughtirq, ps_caughtfiq,
+ ps_error,
+ /* only as a return value from Call() */
+ ps_callfailed, ps_callreturned,
+ /* internal inconsistencies */
+ ps_broken, /* target has "broken" */
+ ps_unknownbreak,
+ ps_unknown
+} Dbg_ProgramState;
+
+int Dbg_IsCallLink(Dbg_MCState *state, ARMaddress pc);
+
+typedef struct {
+ Dbg_FPRegVal fpres;
+ ARMword intres;
+} Dbg_CallResults;
+
+Dbg_CallResults *Dbg_GetCallResults(Dbg_MCState *state);
+
+#define Dbg_S_STATEMENTS 0
+#define Dbg_S_INSTRUCTIONS 1
+#define Dbg_S_STEPINTOPROCS 2
+
+Dbg_Error Dbg_Step(Dbg_MCState *state, int32 stepcount, int stepby, Dbg_ProgramState *status);
+/* <stepby> is a combination of the Dbg_S_... values above */
+
+Dbg_Error Dbg_StepOut(Dbg_MCState *state, Dbg_ProgramState *status);
+
+bool Dbg_CanGo(Dbg_MCState *state);
+
+bool Dbg_IsExecuting(Dbg_MCState *state);
+
+Dbg_Error Dbg_Go(Dbg_MCState *state, Dbg_ProgramState *status);
+
+Dbg_Error Dbg_Stop(Dbg_MCState *state);
+/* Asynchronous Stop request, for call from SIGINT handler. On return to the
+ caller, the call of Dbg_Go, Dbg_Step or Dbg_Call which started execution
+ should return ps_interrupted.
+ */
+
+typedef void Dbg_ExecuteProc(Dbg_MCState *state, Dbg_ProgramState status);
+Dbg_Error Dbg_OnExecute(Dbg_MCState *, Dbg_ExecuteProc *);
+/* Register function to be called back whenever execution stops.
+ * (To allow multiple toolbox clients to coexist).
+ */
+
+Dbg_Error Dbg_SetReturn(Dbg_MCState *state,
+ const Dbg_Environment *context, const Dbg_Value *value);
+/* Prepare continuation by returning <value> from the function activation
+ described by <context>. (Dbg_Go() or Dbg_Step() actually perform the
+ continuation).
+ */
+
+Dbg_Error Dbg_SetExecution(Dbg_MCState *state, Dbg_Environment *context);
+/* Set the pc in a high-level fashion */
+
+Dbg_Error Dbg_ProgramStateToChars(Dbg_MCState *state, Dbg_ProgramState event, Dbg_BufDesc *buf);
+/* This is guaranteed to give a completely accurate description of <event> if
+ this was the value returned by the most recent call of Dbg_Go, Dbg_Step,
+ or Dbg_Call.
+ */
+
+/*--------------------------------------------------------------------------*/
+
+Dbg_Error Dbg_CurrentEnvironment(Dbg_MCState *state, Dbg_Environment *context);
+
+Dbg_Error Dbg_PrevFrame(Dbg_MCState *state, Dbg_Environment *context);
+/* towards the base of the stack */
+
+Dbg_Error Dbg_NextFrame(Dbg_MCState *state, Dbg_Environment *context);
+/* away from the base of the stack */
+
+typedef struct Dbg_AnyPos {
+ enum { pos_source, pos_ll, pos_none } postype;
+ ARMaddress pc;
+ union {
+ Dbg_ProcPos source;
+ Dbg_LLPos ll;
+ ARMaddress none;
+ } pos;
+} Dbg_AnyPos;
+
+Dbg_Error Dbg_EnvironmentToPos(Dbg_MCState *state, const Dbg_Environment *context, Dbg_AnyPos *pos);
+/* <pos> is set to a Dbg_ProcPos if these is one corresponding to <context>
+ else a Dbg_LLPos if there is one.
+ */
+
+/*--------------------------------------------------------------------------*/
+
+/* Source file management.
+ Pretty vestigial. Handles source path (per loaded image),
+ and translates from line-number (as given in debugger tables) to character
+ position (as required to access files)
+ */
+
+Dbg_Error Dbg_ClearPaths(Dbg_MCState *state, Dbg_SymTable *st);
+Dbg_Error Dbg_AddPath(Dbg_MCState *state, Dbg_SymTable *st, const char *path);
+Dbg_Error Dbg_DeletePath(Dbg_MCState *state, Dbg_SymTable *st, const char *path);
+
+typedef enum {
+ Dbg_PathsCleared,
+ Dbg_PathAdded,
+ Dbg_PathDeleted
+} Dbg_PathAlteration;
+
+typedef void Dbg_PathAlteredProc(
+ Dbg_MCState *state, Dbg_SymTable *st, char const *path,
+ Dbg_PathAlteration sort);
+
+Dbg_Error Dbg_OnPathAlteration(Dbg_MCState *state, Dbg_PathAlteredProc *p);
+/* Register function to be called back whenever one of the source path
+ * modification functions above is called. (To allow multiple toolbox
+ * clients to coexist).
+ */
+
+typedef struct Dbg_FileRec Dbg_FileRec;
+typedef struct {
+ unsigned32 linecount;
+ Dbg_FileRec *handle;
+ char *fullname;
+} Dbg_FileDetails;
+
+Dbg_Error Dbg_GetFileDetails(
+ Dbg_MCState *state, const Dbg_File *fname, Dbg_FileDetails *res);
+Dbg_Error Dbg_FinishedWithFile(Dbg_MCState *state, Dbg_FileRec *handle);
+
+Dbg_Error Dbg_GetFileDetails_fr(
+ Dbg_MCState *state, Dbg_FileRec *handle, Dbg_FileDetails *res);
+/* Refresh details about the file associated with <handle> (in particular,
+ * its linecount).
+ */
+
+Dbg_Error Dbg_FileLineLength(
+ Dbg_MCState *state, Dbg_FileRec *handle, int32 lineno, int32 *len);
+/* Return to <len> the length of line <lineno> of the file associated with
+ * <handle> (without necessarily reading from the file).
+ */
+
+Dbg_Error Dbg_GetFileLine_fr(
+ Dbg_MCState *state, Dbg_FileRec *handle, int32 lineno, Dbg_BufDesc *buf);
+/* Return to <buf> the contents of line <lineno> of the file associated with
+ * <handle> (including its terminating newline).
+ */
+
+Dbg_Error Dbg_StartFileAccess(Dbg_MCState *state, Dbg_FileRec *handle);
+Dbg_Error Dbg_EndFileAccess(Dbg_MCState *state, Dbg_FileRec *handle);
+/* These two calls bracket a sequence of calls to GetFileLine. Between the
+ * calls, the toolbox is permitted to retain state allowing more rapid
+ * access to text on the file associated with <handle>.
+ */
+
+Dbg_Error Dbg_ControlSourceFileAccess(
+ Dbg_MCState *state, uint32 cachesize, bool closefiles);
+/* Control details of how the toolbox manages source files.
+ * If <cachesize> is non-zero, the text from the most recently accessed
+ * source files (of total size not to exceed <cachesize>) is saved in
+ * store on first access to the file; subsequent access to the text of
+ * the file uses this copy.
+ * If <closefiles> is true, no stream is left attached to uncached source
+ * files after Dbg_EndFileAccess has been closed. Otherwise, the toolbox
+ * may retain such streams, in order to improve access.
+ */
+
+/*--------------------------------------------------------------------------*/
+
+/* disassembly */
+
+/*
+ ? More exact control is wanted here, but that requires a more complicated
+ ? disass callback interface.
+ */
+
+typedef const char *Dbg_SWI_Decode(Dbg_MCState *state, ARMword swino);
+
+Dbg_Error Dbg_InstructionAt(Dbg_MCState *state, ARMaddress addr,
+ int isize, ARMhword *inst, Dbg_SymTable *st,
+ Dbg_SWI_Decode *swi_name, Dbg_BufDesc *buf, int *length);
+/* <isize> describes the form of disassembly wanted: 2 for 16-bit, 4 for 32-bit,
+ * 0 for 16- or 32-bit depending whether addr addresses 16- or 32-bit code.
+ * <inst> is a pointer to a pair of halfwords *in target byte order*
+ * Possibly only the first halfword will be consumed: the number of bytes used
+ * is returned via <length>.
+ */
+
+/*--------------------------------------------------------------------------*/
+
+int Dbg_RDIOpen(Dbg_MCState *state, unsigned type);
+int Dbg_RDIInfo(Dbg_MCState *state, unsigned type, ARMword *arg1, ARMword *arg2);
+
+/*--------------------------------------------------------------------------*/
+
+typedef enum {
+ Dbg_Point_Toolbox,
+ Dbg_Point_RDI_Unknown,
+ Dbg_Point_RDI_SW,
+ Dbg_Point_RDI_HW
+} Dbg_PointType;
+
+/* breakpoint management
+ Associated with a breakpoint there may be any of
+ a count
+ an expression
+ a function
+ the breakpoint is activated if
+ the expression evaluates to a non-zero value (or fails to evaluate).
+ && decrementing the count reaches zero (the count is then reset to its
+ initial value).
+ && the function, called with the breakpoint address as argument, returns
+ a non-zero value.
+? (The order here may be open to debate. Note that the first two are in
+ the opposite order in armsd, but I think this order more rational)
+ */
+
+typedef enum Dbg_BreakPosType {
+ bt_procpos,
+ bt_procexit,
+ bt_address
+} Dbg_BreakPosType;
+
+typedef union {
+ Dbg_ProcPos procpos;
+ Dbg_ProcDesc procexit;
+ ARMaddress address;
+} Dbg_BreakPosPos;
+
+typedef struct Dbg_BreakPos {
+ Dbg_BreakPosType sort;
+ Dbg_BreakPosPos loc;
+} Dbg_BreakPos;
+
+typedef int Dbg_BPProc(Dbg_MCState *state, void *BPArg, Dbg_BreakPos *where);
+
+typedef struct Dbg_BreakStatus {
+ int index;
+ int initcount, countnow;
+ Dbg_BreakPos where;
+ char *expr;
+ Dbg_BPProc *p; void *p_arg;
+ int incomplete;
+ Dbg_PointType type;
+ ARMword hwresource;
+} Dbg_BreakStatus;
+
+Dbg_Error Dbg_StringToBreakPos(
+ Dbg_MCState *state, Dbg_Environment *env, char const *str, size_t len,
+ Dbg_BreakPos *bpos, char *b);
+
+Dbg_Error Dbg_SetBreakPoint(Dbg_MCState *state, Dbg_BreakPos *where,
+ int count,
+ const char *expr,
+ Dbg_BPProc *p, void *arg);
+Dbg_Error Dbg_SetBreakPoint16(Dbg_MCState *state, Dbg_BreakPos *where,
+ int count,
+ const char *expr,
+ Dbg_BPProc *p, void *arg);
+Dbg_Error Dbg_SetBreakPointNaturalSize(Dbg_MCState *state, Dbg_BreakPos *where,
+ int count,
+ const char *expr,
+ Dbg_BPProc *p, void *arg);
+/* Setting a breakpoint at the same address as a previous breakpoint
+ completely removes the previous one.
+ */
+
+Dbg_Error Dbg_DeleteBreakPoint(Dbg_MCState *state, Dbg_BreakPos *where);
+
+Dbg_Error Dbg_SuspendBreakPoint(Dbg_MCState *state, Dbg_BreakPos *where);
+/* Temporarily remove the break point (until Reinstated) but leave intact
+ its associated expr, the value its count has reached, etc.
+? The debugger toolbox itself wants this, but I'm not sure what use a client
+ could have for it. Ditto Reinstate...
+ */
+
+Dbg_Error Dbg_ReinstateBreakPoint(Dbg_MCState *state, Dbg_BreakPos *where);
+/* Undo the effect of Dbg_SuspendBreakPoint
+ */
+
+Dbg_Error Dbg_DeleteAllBreakPoints(Dbg_MCState *state);
+
+Dbg_Error Dbg_SuspendAllBreakPoints(Dbg_MCState *state);
+
+Dbg_Error Dbg_ReinstateAllBreakPoints(Dbg_MCState *state);
+
+typedef Dbg_Error Dbg_BPEnumProc(Dbg_MCState *state, Dbg_BreakStatus *status, void *arg);
+
+Dbg_Error Dbg_EnumerateBreakPoints(Dbg_MCState *state, Dbg_BPEnumProc *p, void *arg);
+
+Dbg_Error Dbg_BreakPointStatus(Dbg_MCState *state,
+ const Dbg_BreakPos *where, Dbg_BreakStatus *status);
+
+typedef void Dbg_BreakAlteredProc(Dbg_MCState *state, ARMaddress addr, bool set);
+Dbg_Error Dbg_OnBreak(Dbg_MCState *state, Dbg_BreakAlteredProc *p);
+/* Register function to be called back whenever a breakpoint is set or
+ * cleared. (To allow multiple toolbox clients to coexist).
+ */
+
+bool Dbg_StoppedAtBreakPoint(Dbg_MCState *state, const Dbg_BreakPos *where);
+/* Called after execution which resulted in ps_atbreak, to find out whether
+ the specified breakpoint was hit (could be >1, eg. exit break and another
+ high-level breakpoint at the same position).
+ Returns NO if specified breakpoint not found, or execution didn't stop
+ with ps_atbreak status.
+ */
+
+/*--------------------------------------------------------------------------*/
+
+typedef struct {
+ Dbg_Value val;
+ char *name;
+} Dbg_WatchPos;
+
+typedef int Dbg_WPProc(Dbg_MCState *state, void *WPArg, Dbg_WatchPos *where);
+
+typedef struct Dbg_WPStatus {
+ int index;
+ int initcount, countnow;
+ Dbg_WatchPos what, target;
+ char *expr;
+ Dbg_WPProc *p; void *p_arg;
+ Dbg_PointType type;
+ ARMword hwresource;
+ int skip;
+} Dbg_WPStatus;
+
+Dbg_Error Dbg_SetWatchPoint(
+ Dbg_MCState *state, Dbg_Environment *context, char const *watchee,
+ char const *target,
+ int count,
+ char const *expr,
+ Dbg_WPProc *p, void *arg);
+
+/* Cause a watchpoint event if the value of <watchee> changes to the value of
+ <target> (or changes at all if <target> is NULL). <watchee> should
+ evaluate either to an L-value (when the size of the object being watched is
+ determined by its type) or to an integer constant (when the word with this
+ address is watched).
+ */
+
+Dbg_Error Dbg_DeleteWatchPoint(Dbg_MCState *state, Dbg_Environment *context, char const *watchee);
+
+
+Dbg_Error Dbg_SetWatchPoint_V(
+ Dbg_MCState *state,
+ char const *name, Dbg_Value const *val, char const *tname, Dbg_Value const *tval,
+ int count,
+ char const *expr,
+ Dbg_WPProc *p, void *arg);
+
+Dbg_Error Dbg_DeleteWatchPoint_V(Dbg_MCState *state, Dbg_Value const *val);
+
+
+Dbg_Error Dbg_DeleteAllWatchPoints(Dbg_MCState *state);
+
+typedef Dbg_Error Dbg_WPEnumProc(Dbg_MCState *state, Dbg_WPStatus const *watchee, void *arg);
+
+Dbg_Error Dbg_EnumerateWatchPoints(Dbg_MCState *state, Dbg_WPEnumProc *p, void *arg);
+
+Dbg_Error Dbg_WatchPointStatus(Dbg_MCState *state,
+ Dbg_WatchPos const *where, Dbg_WPStatus *status);
+
+typedef void Dbg_WPRemovedProc(void *arg, Dbg_WPStatus const *wp);
+Dbg_Error Dbg_RegisterWPRemovalProc(Dbg_MCState *state, Dbg_WPRemovedProc *p, void *arg);
+/* When a watchpoint goes out of scope it is removed by the toolbox, and the
+ function registered here gets called back to adjust its view
+ */
+
+typedef void Dbg_WatchAlteredProc(Dbg_MCState *state, Dbg_Value const *where, bool set);
+Dbg_Error Dbg_OnWatch(Dbg_MCState *state, Dbg_WatchAlteredProc *p);
+/* Register function to be called back whenever a watchpoint is set or
+ * cleared. (To allow multiple toolbox clients to coexist).
+ */
+
+/*--------------------------------------------------------------------------*/
+
+Dbg_Error Dbg_ProfileLoad(Dbg_MCState *state);
+
+Dbg_Error Dbg_ProfileStart(Dbg_MCState *state, ARMword interval);
+Dbg_Error Dbg_ProfileStop(Dbg_MCState *state);
+
+Dbg_Error Dbg_ProfileClear(Dbg_MCState *state);
+
+Dbg_Error Dbg_WriteProfile(Dbg_MCState *state, char const *filename,
+ char const *toolid, char const *arg);
+
+/*--------------------------------------------------------------------------*/
+
+Dbg_Error Dbg_ConnectChannel_ToHost(Dbg_MCState *state, RDICCProc_ToHost *p, void *arg);
+Dbg_Error Dbg_ConnectChannel_FromHost(Dbg_MCState *state, RDICCProc_FromHost *p, void *arg);
+
+/*--------------------------------------------------------------------------*/
+
+/* Configuration data management */
+
+Dbg_Error Dbg_LoadConfigData(Dbg_MCState *state, char const *filename);
+
+Dbg_Error Dbg_SelectConfig(
+ Dbg_MCState *state,
+ RDI_ConfigAspect aspect, char const *name, RDI_ConfigMatchType matchtype,
+ unsigned versionreq, unsigned *versionp);
+
+Dbg_Error Dbg_ParseConfigVersion(
+ char const *s, RDI_ConfigMatchType *matchp, unsigned *versionp);
+
+typedef Dbg_Error Dbg_ConfigEnumProc(Dbg_MCState *state, RDI_ConfigDesc const *desc, void *arg);
+
+Dbg_Error Dbg_EnumerateConfigs(Dbg_MCState *state, Dbg_ConfigEnumProc *p, void *arg);
+
+/*--------------------------------------------------------------------------*/
+
+/* Angel OS support */
+
+Dbg_Error Dbg_CreateTask(Dbg_MCState **statep, Dbg_MCState *parent, bool inherit);
+/* This is called when a task is to be debugged which has not been debugged
+ before - ie. there is no existing Dbg_MCState for this task. It
+ initialises a new Dbg_MCState and returns a pointer to it.
+ <parent> is any valid previously-created MCCState. If <inherit> is TRUE,
+ the new MCState inherits certain features from it (eg. symbols).
+ Otherwise, only features which are the same across all tasks are inherited,
+ (eg. global breakpoints).
+ */
+
+Dbg_Error Dbg_DeleteTask(Dbg_MCState *state);
+/* This is called when a task dies, and frees up everything which relates to that
+ task which is controlled by armdbg.
+ */
+
+Dbg_Error Dbg_DetachTask(Dbg_MCState *state);
+
+Dbg_Error Dbg_AttachTask(Dbg_MCState *state);
+/* These are called to request a switch of the current task. First
+ Dbg_DetachTask should be called with the state of the old task.
+ Dbg_DetachTask will ensure that any cached state held by armdbg for
+ the old task is immediately written out to the target.
+
+ After Dbg_DetachTask is called and before Dbg_AttachTask is called
+ the OS channel manager should tell the target that any future
+ requests from the debugger will be fore the new task.
+
+ If the new task does not have an armdbg state structure
+ already, then Dbg_CreateTask should be called to create one (see
+ above). Then Dbg_AttachTask is called to tell armdbg to treat the
+ new armdbg state as the current task.
+ */
+
+typedef Dbg_Error Dbg_TaskSwitchProc(void *arg, Dbg_MCState *newstate);
+
+Dbg_Error Dbg_OnTaskSwitch(Dbg_MCState *state, Dbg_TaskSwitchProc *fn, void *arg);
+/* The front end may register a callback which gets called by armdbg whenever
+ Dbg_AttachTask is called. This callback tells the front end the new current
+ Dbg_MCState it should use to call armdbg.
+ [Note that this is only useful if there is one front end shared between all
+ tasks rather than one front end per task]
+ The value of <arg> passed to Dbg_OnTaskSwitch is passed to <fn>
+ when it is called.
+ */
+
+typedef Dbg_Error Dbg_RestartProc(
+ void *arg, Dbg_MCState *curstate, Dbg_MCState **newstate);
+
+Dbg_Error Dbg_OnRestart(Dbg_MCState *state, Dbg_RestartProc *fn, void *arg);
+/* This is used by the OS channels layer to register a callback which
+ will be made by the debugger toolbox early in the process of resuming
+ execution.
+
+ This callback must determine which task will be resumed when the target
+ restarts execution. If this is not already the current task then it must
+ call Dbg_DetachTask and Dbg_AttachTask as decribed above to switch to the
+ task about to be resumed and return the state for the new task in
+ <newstate>.
+
+ This will ensure that armdbg updates the correct task on execution as well
+ as ensuring that stepping over a breakpointed instruction on restarting
+ happens correctly.
+
+ The value of <arg> passed to Dbg_OnRestart is passed to <fn>
+ when it is called.
+ */
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+/* End of armdbg.h */
diff --git a/gdb/rdi-share/buffers.h b/gdb/rdi-share/buffers.h
new file mode 100644
index 00000000000..78549de0097
--- /dev/null
+++ b/gdb/rdi-share/buffers.h
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
+ *
+ * This software may be freely used, copied, modified, and distributed
+ * provided that the above copyright notice is preserved in all copies of the
+ * software.
+ */
+
+/* -*-C-*-
+ *
+ * $Revision$
+ * $Date$
+ *
+ *
+ * Project: ANGEL
+ *
+ * Title: Public interface to buffer management
+ */
+
+#ifndef angel_buffers_h
+#define angel_buffers_h
+
+#include "chandefs.h" /* CHAN_HEADER_SIZE */
+
+
+/* the handle to a buffer */
+typedef unsigned char *p_Buffer;
+
+
+/*
+ * Angel Packets are structured as a fixed size header, followed
+ * by the packet data
+ */
+#ifdef TARGET
+# define BUFFERDATA(b) (b) /* channels layer takes care of it */
+#else
+# define BUFFERDATA(b) (&((b)[CHAN_HEADER_SIZE]))
+#endif
+
+
+/*
+ * The buffer management function prototypes are only applicable
+ * when compiling target code
+ */
+#ifdef TARGET
+
+/*
+ * Function: Angel_BufferQuerySizes
+ * Purpose: Request infomation on the default and maximum buffer sizes
+ * that can be allocated
+ *
+ * Params:
+ * In/Out: default_size, max_size: pointers to place the
+ * sizes in on return
+ */
+
+void Angel_BufferQuerySizes(unsigned int *default_size,
+ unsigned int *max_size );
+
+/*
+ * Function: Angel_RxEnginBuffersLeft
+ * Purpose: return the number of free buffers
+ *
+ * Params:
+ * Returns: number of free buffers
+ */
+unsigned int Angel_BuffersLeft( void );
+
+/*
+ * Function: Angel_BufferAlloc
+ * Purpose: allocate a buffer that is at least req_size bytes long
+ *
+ * Params:
+ * Input: req_size the required size of the buffer
+ *
+ * Returns: pointer to the buffer NULL if unable to
+ * fulfil the request
+ */
+p_Buffer Angel_BufferAlloc(unsigned int req_size);
+
+/*
+ * Function: Angel_BufferRelease
+ * Purpose: release a buffer back to the free pool
+ *
+ * Params:
+ * Input: pointer to the buffer to free
+ */
+void Angel_BufferRelease(p_Buffer buffer);
+
+
+/* return values for angel_InitBuffers */
+typedef enum buf_init_error{
+ INIT_BUF_OK,
+ INIT_BUF_FAIL
+} buf_init_error;
+
+/*
+ * Function: Angel_InitBuffers
+ * Purpose: Initalised and malloc the buffer pool
+ *
+ * Params:
+ * Returns: see above
+ */
+
+buf_init_error Angel_InitBuffers(void);
+
+#endif /* def TARGET */
+
+#endif /* ndef angel_buffers_h */
+
+/* EOF buffers.h */
diff --git a/gdb/rdi-share/bytesex.c b/gdb/rdi-share/bytesex.c
new file mode 100644
index 00000000000..0c6aaae2c54
--- /dev/null
+++ b/gdb/rdi-share/bytesex.c
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
+ *
+ * This software may be freely used, copied, modified, and distributed
+ * provided that the above copyright notice is preserved in all copies of the
+ * software.
+ */
+
+/*
+ * bytesex.c - Code to support byte-sex independence
+ * Copyright: (C) 1991, Advanced RISC Machines Ltd., Cambridge, England.
+ */
+
+/*
+ * RCS $Revision$
+ * Checkin $Date$
+ */
+
+#include "bytesex.h"
+
+static int reversing_bytes = 0;
+
+void bytesex_reverse(yes_or_no)
+int yes_or_no;
+{ reversing_bytes = yes_or_no;
+}
+
+int bytesex_reversing()
+{
+ return reversing_bytes;
+}
+
+int32 bytesex_hostval(v)
+int32 v;
+{ /* Return v with the same endian-ness as the host */
+ /* This mess generates better ARM code than the more obvious mess */
+ /* and may eventually peephole to optimal code... */
+ if (reversing_bytes)
+ { unsigned32 t;
+ /* t = v ^ (v ror 16) */
+ t = v ^ ((v << 16) | (((unsigned32)v) >> 16));
+ t &= ~0xff0000;
+ /* v = v ror 8 */
+ v = (v << 24) | (((unsigned32)v) >> 8);
+ v = v ^ (t >> 8);
+ }
+ return v;
+}
+
+int32 bytesex_hostval_16(v)
+int32 v;
+{
+ if (reversing_bytes) {
+ v = ((v >> 8) & 0xff) | ((v << 8) & 0xff00);
+ }
+ return v;
+}
diff --git a/gdb/rdi-share/bytesex.h b/gdb/rdi-share/bytesex.h
new file mode 100644
index 00000000000..4b53ef38247
--- /dev/null
+++ b/gdb/rdi-share/bytesex.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
+ *
+ * This software may be freely used, copied, modified, and distributed
+ * provided that the above copyright notice is preserved in all copies of the
+ * software.
+ */
+
+/*
+ Title: Code to support byte-sex independence
+ Copyright: (C) 1991, Advanced RISC Machines Ltd., Cambridge, England.
+*/
+/*
+ * RCS $Revision$
+ * Checkin $Date$
+ */
+
+#ifndef __bytesex_h
+#define __bytesex_h
+
+#include "host.h"
+
+void bytesex_reverse(int yes_or_no);
+/*
+ * Turn sex-reversal on or off - 0 means off, non-0 means on.
+ */
+
+int bytesex_reversing(void);
+/*
+ * Return non-0 if reversing the byte sex, else 0.
+ */
+
+int32 bytesex_hostval(int32 v);
+/*
+ * Return v or byte-reversed v, according to whether sex-reversval
+ * is on or off.
+ */
+
+int32 bytesex_hostval_16(int32 v);
+/* Return v or byte-reversed v for a 16 bit value */
+
+#endif
diff --git a/gdb/rdi-share/chandefs.h b/gdb/rdi-share/chandefs.h
new file mode 100644
index 00000000000..d97f0b5bcef
--- /dev/null
+++ b/gdb/rdi-share/chandefs.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
+ *
+ * This software may be freely used, copied, modified, and distributed
+ * provided that the above copyright notice is preserved in all copies of the
+ * software.
+ */
+
+/* -*-C-*-
+ *
+ * $Revision$
+ * $Date$
+ *
+ *
+ * Project: ANGEL
+ *
+ * Title: Enumeration with all supported channels
+ */
+
+#ifndef angel_chandefs_h
+#define angel_chandefs_h
+
+enum channelIDs {
+ CI_PRIVATE = 0, /* channels protocol control messages */
+ CI_HADP, /* ADP, host originated */
+ CI_TADP, /* ADP, target originated */
+ CI_HBOOT, /* Boot, host originated */
+ CI_TBOOT, /* Boot, target originated */
+ CI_CLIB, /* Semihosting C library support */
+ CI_HUDBG, /* User debug support, host originated */
+ CI_TUDBG, /* User debug support, target originated */
+ CI_HTDCC, /* Thumb direct comms channel, host orig. */
+ CI_TTDCC, /* Thumb direct comms channel, target orig. */
+ CI_TLOG, /* Target debug/logging */
+ CI_NUM_CHANNELS
+};
+
+typedef unsigned ChannelID;
+
+
+/*
+ * Size in bytes of the channel header.
+ * This is a duplicate of XXX in chanpriv.h, but we don't want everyone
+ * to have access to all of chanpriv.h, so we'll double-check in chanpriv.h.
+ */
+#define CHAN_HEADER_SIZE (4)
+
+#endif /* ndef angel_chandefs_h */
+
+/* EOF chandefs.h */
diff --git a/gdb/rdi-share/channels.h b/gdb/rdi-share/channels.h
new file mode 100644
index 00000000000..b43ebc10a65
--- /dev/null
+++ b/gdb/rdi-share/channels.h
@@ -0,0 +1,384 @@
+/*
+ * Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
+ *
+ * This software may be freely used, copied, modified, and distributed
+ * provided that the above copyright notice is preserved in all copies of the
+ * software.
+ */
+
+/* -*-C-*-
+ *
+ * $Revision$
+ * $Date$
+ *
+ *
+ * Project: ANGEL
+ *
+ * Title: User interface to the channels layer
+ */
+
+#ifndef angel_channels_h
+#define angel_channels_h
+
+/*
+ * This provides the public interface to the channels layer read and write
+ * routines, and buffer management routines.
+ */
+
+/* Nested header files, if required */
+
+#include "devices.h"
+#include "chandefs.h"
+#include "adperr.h"
+
+/* General purpose constants, macros, enums, typedefs */
+
+/* use the default device */
+#define CH_DEFAULT_DEV ((DeviceID)-1)
+
+/* return codes */
+typedef enum ChanError {
+ CE_OKAY, /* no error */
+ CE_ABANDONED, /* abandoned due to device switch */
+ CE_DEV_ERROR, /* unexpected error from device driver */
+ CE_BUSY, /* channel in use */
+ CE_BUFF_ERROR, /* unable to get buffer */
+ CE_PRIVATE /* start of internal error codes */
+} ChanError;
+
+
+/* Publically-accessible globals */
+
+/*
+ * The following two globals are only valid after angel_InitialiseChannels()
+ * has been called.
+ */
+
+/* the default size of a channel buffer, for global use */
+extern unsigned Angel_ChanBuffSize;
+
+/* the size of a long buffer, for global use */
+extern unsigned Angel_ChanLongSize;
+
+#ifdef TARGET
+AdpErrs send_resend_msg(DeviceID devid);
+#endif
+
+/*
+ * Function: angel_InitialiseChannels
+ * Purpose: initialise the channels layer
+ *
+ * Params:
+ * Input: -
+ * Output: -
+ * In/Out: -
+ *
+ * Returns: -
+ *
+ * Reads globals: -
+ * Modifies globals: -
+ *
+ * Other side effects: -
+ */
+
+void angel_InitialiseChannels( void );
+
+/*
+ * Function: adp_init_seq
+ * Purpose: initialise sequence numbers and free anyt leftover buffers
+ *
+ * Params:
+ * Input: -
+ * Output: -
+ * In/Out: -
+ *
+ * Returns: - adp_ok if things went ok else an error code
+ *
+ * Reads globals: -
+ * Modifies globals: -
+ *
+ * Other side effects: -
+ */
+
+AdpErrs adp_init_seq(void);
+
+/*
+ * Function: angel_ChannelAllocBuffer
+ * Purpose: allocate a buffer that is at least req_size bytes long
+ *
+ * Params:
+ * Input: req_size the minimum size required
+ * Output: -
+ * In/Out: -
+ *
+ * Returns: pointer to allocated buffer, or
+ * NULL if unable to allocate suitable buffer
+ *
+ * Reads globals: -
+ * Modifies globals: -
+ *
+ * Other side effects: -
+ */
+
+p_Buffer angel_ChannelAllocBuffer(unsigned req_size);
+
+
+/*
+ * Function: angel_ChannelReleaseBuffer
+ * Purpose: release a buffer back to the free pool
+ *
+ * Params:
+ * Input: buffer the buffer to release
+ * Output: -
+ * In/Out: -
+ *
+ * Returns: -
+ *
+ * Reads globals: -
+ * Modifies globals: -
+ *
+ * Other side effects: -
+ */
+
+void angel_ChannelReleaseBuffer(p_Buffer buffer);
+
+
+/*
+ * Function: angel_ChannelSend
+ * Purpose: blocking send of a packet via a channel
+ *
+ * Params:
+ * Input: devid Device to use, or CH_DEFAULT_DEV
+ * chanid Channel to use for tx
+ * buffer Pointer to data to send
+ * len Length of data to send
+ * Output: -
+ * In/Out: -
+ *
+ * Returns: CE_OKAY Transmission completed
+ * CE_BAD_CHAN Channel id invalid
+ * CE_ABANDONED Tx abandoned due to device switch
+ *
+ * Reads globals: -
+ * Modifies globals: -
+ *
+ * Other side effects: -
+ */
+
+ChanError angel_ChannelSend(DeviceID devid, ChannelID chanid,
+ const p_Buffer buffer, unsigned len);
+
+
+/*
+ * Function: angel_ChannelSendAsync
+ * Purpose: asynchronous send of a packet via a channel
+ *
+ * Params:
+ * Input: devid Device to use, or CH_DEFAULT_DEV
+ * chanid Channel to use for tx
+ * buffer Pointer to data to send
+ * len Length of data to send
+ * callback Function to call on completion
+ * callback_data Pointer to pass to callback
+ * Output: -
+ * In/Out: -
+ *
+ * Returns: CE_OKAY Transmission underway
+ * CE_BAD_CHAN Channel id invalid
+ * CE_ABANDONED Tx abandoned due to device switch
+ *
+ * Reads globals: -
+ * Modifies globals: -
+ *
+ * Other side effects: -
+ *
+ * register an asynchronous send on the given channel
+ * (blocks until send can be commenced)
+ */
+
+typedef void (*ChanTx_CB_Fn)(ChannelID chanid, /* which channel */
+ void *callback_data); /* as supplied... */
+
+
+ChanError angel_ChannelSendAsync( DeviceID devid,
+ ChannelID chanid,
+ const p_Buffer buffer,
+ unsigned len,
+ ChanTx_CB_Fn callback,
+ void *callback_data);
+
+
+/*
+ * Function: angel_ChannelRead
+ * Purpose: blocking read of a packet from a channel
+ *
+ * Params:
+ * Input: devid Device to use, or CH_DEFAULT_DEV
+ * chanid Channel to use for rx
+ * Output: buffer The buffer, supplied and filled
+ * len How many bytes there are in the buffer
+ * In/Out: -
+ *
+ * Returns: CE_OKAY Reception successful
+ * CE_BAD_CHAN Channel id invalid
+ * CE_ABANDONED Tx abandoned due to device switch
+ *
+ * Reads globals: -
+ * Modifies globals: -
+ *
+ * Other side effects: -
+ *
+ * Note that in the present version, if an asynchronous read has been
+ * registered, a blocking read will be refused with CE_BUSY.
+ */
+ChanError angel_ChannelRead(DeviceID devid,
+ ChannelID chanid,
+ p_Buffer *buffer,
+ unsigned *len);
+
+
+/*
+ * Function: angel_ChannelReadAsync
+ * Purpose: asynchronous read of a packet via a channel
+ *
+ * Params:
+ * Input: devid Device to use, or CH_DEFAULT_DEV
+ * chanid Channel to wait on
+ * callback Function to call on completion, or NULL
+ * callback_data Pointer to pass to callback
+ * Output: -
+ * In/Out: -
+ *
+ * Returns: CE_OKAY Read request registered
+ * CE_BAD_CHAN Channel id invalid
+ * CE_BUSY Someone else is using the channel
+ * (in a single threaded world)
+ *
+ * Reads globals: -
+ * Modifies globals: -
+ *
+ * Other side effects: -
+ *
+ * Register an asynchronous read on the given channel. There can only be one
+ * async. reader per channel, and blocking reads are not permitted whilst
+ * an async. reader is registered.
+ *
+ * Reader can unregister by specifying NULL as the callback function.
+ */
+
+typedef void (*ChanRx_CB_Fn)(DeviceID devID, /* ID of receiving device */
+ ChannelID chanID, /* ID of receiving channel */
+ p_Buffer buff, /* pointer to buffer */
+ unsigned len, /* length of data */
+ void *cb_data /* callback data */
+ );
+
+ChanError angel_ChannelReadAsync(DeviceID devid,
+ ChannelID chanid,
+ ChanRx_CB_Fn callback,
+ void *callback_data);
+
+
+/*
+ * Function: angel_ChannelReadAll
+ * Purpose: register an asynchronous read across all devices
+ *
+ * Params:
+ * Input: chanid Channel to look for (usually HBOOT)
+ * callback Function to call on completion
+ * callback_data Pointer to pass to callback
+ * Output: -
+ * In/Out: -
+ *
+ * Returns: CE_OKAY Read request registered
+ * CE_BAD_CHAN Channel id invalid
+ * CE_BUSY Someone else is reading all devices
+ *
+ * Reads globals: -
+ * Modifies globals: -
+ *
+ * Other side effects: -
+ *
+ * Register an asynchronous read across all devices. This is a 'fallback',
+ * which will be superseded (temporarily) by a registered reader or blocking
+ * read on a specific device.
+ */
+
+ChanError angel_ChannelReadAll( ChannelID chanid,
+ ChanRx_CB_Fn callback,
+ void *callback_data);
+
+
+
+/*
+ * Function: angel_ChannelSendThenRead
+ * Purpose: blocking write to followed by read from a channel
+ *
+ * Params:
+ * Input: devid Device to use, or CH_DEFAULT_DEV
+ * chanid Channel to use for rx
+ * In/Out: buffer On entry: the packet to be sent
+ * On return: the packet received
+ * len On entry: length of packet to be sent
+ * On return: length of packet rx'd
+ * In/Out: -
+ *
+ * Returns: CE_OKAY Tx and Reception successful
+ * CE_BAD_CHAN Channel id invalid
+ * CE_ABANDONED Tx abandoned due to device switch
+ *
+ * Reads globals: -
+ * Modifies globals: -
+ *
+ * Other side effects: -
+ *
+ * Note that in the present version, if an asynchronous read has been
+ * registered, this will be refused with CE_BUSY.
+ */
+ChanError angel_ChannelSendThenRead(DeviceID devid,
+ ChannelID chanid,
+ p_Buffer *buffer,
+ unsigned *len);
+
+
+/*
+ * Function: angel_ChannelSelectDevice
+ * Purpose: select the device to be used for all channel comms
+ *
+ * Params:
+ * Input: device ID of device to use as the default
+ * Output: -
+ * In/Out: -
+ *
+ * Returns: CE_OKAY Default device selected
+ * CE_BAD_DEV Invalid device ID
+ *
+ * Reads globals: -
+ * Modifies globals: -
+ *
+ * Other side effects: Any channel operations in progress are
+ * abandoned.
+ *
+ * select the device for all channels comms
+ */
+
+ChanError angel_ChannelSelectDevice(DeviceID device);
+
+
+/*
+ * Function: angel_ChannelReadActiveDevice
+ * Purpose: reads the device id of the currently active device
+ *
+ * Params:
+ * Input: device address of a DeviceID variable
+ * Output: *device ID of device currently being used
+ * In/Out: -
+ *
+ * Returns: CE_OKAY Default device selected
+ */
+
+ChanError angel_ChannelReadActiveDevice(DeviceID *device);
+
+#endif /* ndef angel_channels_h */
+
+/* EOF channels.h */
diff --git a/gdb/rdi-share/chanpriv.h b/gdb/rdi-share/chanpriv.h
new file mode 100644
index 00000000000..155e864e297
--- /dev/null
+++ b/gdb/rdi-share/chanpriv.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
+ *
+ * This software may be freely used, copied, modified, and distributed
+ * provided that the above copyright notice is preserved in all copies of the
+ * software.
+ */
+
+/* -*-C-*-
+ *
+ * $Revision$
+ * $Date$
+ *
+ *
+ * Project: ANGEL
+ *
+ * Title: Private header for channels implementations
+ */
+
+#ifndef angel_chanpriv_h
+#define angel_chanpriv_h
+
+/*
+ * This describes the internal structure and flags for a channels packet.
+ */
+
+/* byte positions within channel packet */
+#define CF_CHANNEL_BYTE_POS 0
+#define CF_HOME_SEQ_BYTE_POS 1
+#define CF_OPPO_SEQ_BYTE_POS 2
+#define CF_FLAGS_BYTE_POS 3
+#define CF_DATA_BYTE_POS 4
+
+/* flags for FLAGS field */
+#define CF_RELIABLE (1 << 0) /* use reliable channels protocol */
+#define CF_RESEND (1 << 1) /* this is a renegotiation packet */
+#define CF_HEARTBEAT (1 << 2) /* heartbeat packet - prod target into sync */
+
+/* byte positions within buffer */
+#define CB_LINK_BYTE_POS 0 /* the link pointer */
+#define CB_CHAN_HEADER_BYTE_POS 4 /* the channel frame starts here */
+
+/* macro to get buffer position of packet component */
+#define CB_PACKET(x) (CB_CHAN_HEADER_BYTE_POS + (x))
+
+/* byte offset of packet data within buffer */
+#define CB_CHAN_DATA_BYTE_POS (CB_PACKET(CF_DATA_BYTE_POS))
+
+/* access the link in a buffer, where b is byte pointer to buffer */
+#define CB_LINK(b) ((p_Buffer)(&(b)[0]))
+
+#define invalidChannelID(chan) (((int)(chan)) < 0 || \
+ (chan) >= CI_NUM_CHANNELS)
+
+#endif /* ndef angel_chanpriv_h */
+
+/* EOF chanpriv.h */
diff --git a/gdb/rdi-share/configure b/gdb/rdi-share/configure
new file mode 100755
index 00000000000..e85f4f80cd4
--- /dev/null
+++ b/gdb/rdi-share/configure
@@ -0,0 +1,2115 @@
+#! /bin/sh
+
+# Guess values for system-dependent variables and create Makefiles.
+# Generated automatically using autoconf version 2.12.2
+# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc.
+#
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+
+# Defaults:
+ac_help=
+ac_default_prefix=/usr/local
+# Any additions from configure.in:
+ac_help="$ac_help
+ --enable-maintainer-mode enable make rules and dependencies not useful
+ (and sometimes confusing) to the casual installer"
+
+# Initialize some variables set by options.
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+build=NONE
+cache_file=./config.cache
+exec_prefix=NONE
+host=NONE
+no_create=
+nonopt=NONE
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+target=NONE
+verbose=
+x_includes=NONE
+x_libraries=NONE
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datadir='${prefix}/share'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+libdir='${exec_prefix}/lib'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+infodir='${prefix}/info'
+mandir='${prefix}/man'
+
+# Initialize some other variables.
+subdirs=
+MFLAGS= MAKEFLAGS=
+SHELL=${CONFIG_SHELL-/bin/sh}
+# Maximum number of lines to put in a shell here document.
+ac_max_here_lines=12
+
+ac_prev=
+for ac_option
+do
+
+ # If the previous option needs an argument, assign it.
+ if test -n "$ac_prev"; then
+ eval "$ac_prev=\$ac_option"
+ ac_prev=
+ continue
+ fi
+
+ case "$ac_option" in
+ -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
+ *) ac_optarg= ;;
+ esac
+
+ # Accept the important Cygnus configure options, so we can diagnose typos.
+
+ case "$ac_option" in
+
+ -bindir | --bindir | --bindi | --bind | --bin | --bi)
+ ac_prev=bindir ;;
+ -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+ bindir="$ac_optarg" ;;
+
+ -build | --build | --buil | --bui | --bu)
+ ac_prev=build ;;
+ -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+ build="$ac_optarg" ;;
+
+ -cache-file | --cache-file | --cache-fil | --cache-fi \
+ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+ ac_prev=cache_file ;;
+ -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+ cache_file="$ac_optarg" ;;
+
+ -datadir | --datadir | --datadi | --datad | --data | --dat | --da)
+ ac_prev=datadir ;;
+ -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \
+ | --da=*)
+ datadir="$ac_optarg" ;;
+
+ -disable-* | --disable-*)
+ ac_feature=`echo $ac_option|sed -e 's/-*disable-//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then
+ { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
+ fi
+ ac_feature=`echo $ac_feature| sed 's/-/_/g'`
+ eval "enable_${ac_feature}=no" ;;
+
+ -enable-* | --enable-*)
+ ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then
+ { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
+ fi
+ ac_feature=`echo $ac_feature| sed 's/-/_/g'`
+ case "$ac_option" in
+ *=*) ;;
+ *) ac_optarg=yes ;;
+ esac
+ eval "enable_${ac_feature}='$ac_optarg'" ;;
+
+ -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+ | --exec | --exe | --ex)
+ ac_prev=exec_prefix ;;
+ -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+ | --exec=* | --exe=* | --ex=*)
+ exec_prefix="$ac_optarg" ;;
+
+ -gas | --gas | --ga | --g)
+ # Obsolete; use --with-gas.
+ with_gas=yes ;;
+
+ -help | --help | --hel | --he)
+ # Omit some internal or obsolete options to make the list less imposing.
+ # This message is too long to be a string in the A/UX 3.1 sh.
+ cat << EOF
+Usage: configure [options] [host]
+Options: [defaults in brackets after descriptions]
+Configuration:
+ --cache-file=FILE cache test results in FILE
+ --help print this message
+ --no-create do not create output files
+ --quiet, --silent do not print \`checking...' messages
+ --version print the version of autoconf that created configure
+Directory and file names:
+ --prefix=PREFIX install architecture-independent files in PREFIX
+ [$ac_default_prefix]
+ --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
+ [same as prefix]
+ --bindir=DIR user executables in DIR [EPREFIX/bin]
+ --sbindir=DIR system admin executables in DIR [EPREFIX/sbin]
+ --libexecdir=DIR program executables in DIR [EPREFIX/libexec]
+ --datadir=DIR read-only architecture-independent data in DIR
+ [PREFIX/share]
+ --sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc]
+ --sharedstatedir=DIR modifiable architecture-independent data in DIR
+ [PREFIX/com]
+ --localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var]
+ --libdir=DIR object code libraries in DIR [EPREFIX/lib]
+ --includedir=DIR C header files in DIR [PREFIX/include]
+ --oldincludedir=DIR C header files for non-gcc in DIR [/usr/include]
+ --infodir=DIR info documentation in DIR [PREFIX/info]
+ --mandir=DIR man documentation in DIR [PREFIX/man]
+ --srcdir=DIR find the sources in DIR [configure dir or ..]
+ --program-prefix=PREFIX prepend PREFIX to installed program names
+ --program-suffix=SUFFIX append SUFFIX to installed program names
+ --program-transform-name=PROGRAM
+ run sed PROGRAM on installed program names
+EOF
+ cat << EOF
+Host type:
+ --build=BUILD configure for building on BUILD [BUILD=HOST]
+ --host=HOST configure for HOST [guessed]
+ --target=TARGET configure for TARGET [TARGET=HOST]
+Features and packages:
+ --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
+ --enable-FEATURE[=ARG] include FEATURE [ARG=yes]
+ --with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
+ --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
+ --x-includes=DIR X include files are in DIR
+ --x-libraries=DIR X library files are in DIR
+EOF
+ if test -n "$ac_help"; then
+ echo "--enable and --with options recognized:$ac_help"
+ fi
+ exit 0 ;;
+
+ -host | --host | --hos | --ho)
+ ac_prev=host ;;
+ -host=* | --host=* | --hos=* | --ho=*)
+ host="$ac_optarg" ;;
+
+ -includedir | --includedir | --includedi | --included | --include \
+ | --includ | --inclu | --incl | --inc)
+ ac_prev=includedir ;;
+ -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+ | --includ=* | --inclu=* | --incl=* | --inc=*)
+ includedir="$ac_optarg" ;;
+
+ -infodir | --infodir | --infodi | --infod | --info | --inf)
+ ac_prev=infodir ;;
+ -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+ infodir="$ac_optarg" ;;
+
+ -libdir | --libdir | --libdi | --libd)
+ ac_prev=libdir ;;
+ -libdir=* | --libdir=* | --libdi=* | --libd=*)
+ libdir="$ac_optarg" ;;
+
+ -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+ | --libexe | --libex | --libe)
+ ac_prev=libexecdir ;;
+ -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+ | --libexe=* | --libex=* | --libe=*)
+ libexecdir="$ac_optarg" ;;
+
+ -localstatedir | --localstatedir | --localstatedi | --localstated \
+ | --localstate | --localstat | --localsta | --localst \
+ | --locals | --local | --loca | --loc | --lo)
+ ac_prev=localstatedir ;;
+ -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+ | --localstate=* | --localstat=* | --localsta=* | --localst=* \
+ | --locals=* | --local=* | --loca=* | --loc=* | --lo=*)
+ localstatedir="$ac_optarg" ;;
+
+ -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+ ac_prev=mandir ;;
+ -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+ mandir="$ac_optarg" ;;
+
+ -nfp | --nfp | --nf)
+ # Obsolete; use --without-fp.
+ with_fp=no ;;
+
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c)
+ no_create=yes ;;
+
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+ no_recursion=yes ;;
+
+ -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+ | --oldin | --oldi | --old | --ol | --o)
+ ac_prev=oldincludedir ;;
+ -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+ oldincludedir="$ac_optarg" ;;
+
+ -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+ ac_prev=prefix ;;
+ -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+ prefix="$ac_optarg" ;;
+
+ -program-prefix | --program-prefix | --program-prefi | --program-pref \
+ | --program-pre | --program-pr | --program-p)
+ ac_prev=program_prefix ;;
+ -program-prefix=* | --program-prefix=* | --program-prefi=* \
+ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+ program_prefix="$ac_optarg" ;;
+
+ -program-suffix | --program-suffix | --program-suffi | --program-suff \
+ | --program-suf | --program-su | --program-s)
+ ac_prev=program_suffix ;;
+ -program-suffix=* | --program-suffix=* | --program-suffi=* \
+ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+ program_suffix="$ac_optarg" ;;
+
+ -program-transform-name | --program-transform-name \
+ | --program-transform-nam | --program-transform-na \
+ | --program-transform-n | --program-transform- \
+ | --program-transform | --program-transfor \
+ | --program-transfo | --program-transf \
+ | --program-trans | --program-tran \
+ | --progr-tra | --program-tr | --program-t)
+ ac_prev=program_transform_name ;;
+ -program-transform-name=* | --program-transform-name=* \
+ | --program-transform-nam=* | --program-transform-na=* \
+ | --program-transform-n=* | --program-transform-=* \
+ | --program-transform=* | --program-transfor=* \
+ | --program-transfo=* | --program-transf=* \
+ | --program-trans=* | --program-tran=* \
+ | --progr-tra=* | --program-tr=* | --program-t=*)
+ program_transform_name="$ac_optarg" ;;
+
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ silent=yes ;;
+
+ -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+ ac_prev=sbindir ;;
+ -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+ | --sbi=* | --sb=*)
+ sbindir="$ac_optarg" ;;
+
+ -sharedstatedir | --sharedstatedir | --sharedstatedi \
+ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+ | --sharedst | --shareds | --shared | --share | --shar \
+ | --sha | --sh)
+ ac_prev=sharedstatedir ;;
+ -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+ | --sha=* | --sh=*)
+ sharedstatedir="$ac_optarg" ;;
+
+ -site | --site | --sit)
+ ac_prev=site ;;
+ -site=* | --site=* | --sit=*)
+ site="$ac_optarg" ;;
+
+ -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+ ac_prev=srcdir ;;
+ -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+ srcdir="$ac_optarg" ;;
+
+ -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+ | --syscon | --sysco | --sysc | --sys | --sy)
+ ac_prev=sysconfdir ;;
+ -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+ sysconfdir="$ac_optarg" ;;
+
+ -target | --target | --targe | --targ | --tar | --ta | --t)
+ ac_prev=target ;;
+ -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+ target="$ac_optarg" ;;
+
+ -v | -verbose | --verbose | --verbos | --verbo | --verb)
+ verbose=yes ;;
+
+ -version | --version | --versio | --versi | --vers)
+ echo "configure generated by autoconf version 2.12.2"
+ exit 0 ;;
+
+ -with-* | --with-*)
+ ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then
+ { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
+ fi
+ ac_package=`echo $ac_package| sed 's/-/_/g'`
+ case "$ac_option" in
+ *=*) ;;
+ *) ac_optarg=yes ;;
+ esac
+ eval "with_${ac_package}='$ac_optarg'" ;;
+
+ -without-* | --without-*)
+ ac_package=`echo $ac_option|sed -e 's/-*without-//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then
+ { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
+ fi
+ ac_package=`echo $ac_package| sed 's/-/_/g'`
+ eval "with_${ac_package}=no" ;;
+
+ --x)
+ # Obsolete; use --with-x.
+ with_x=yes ;;
+
+ -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+ | --x-incl | --x-inc | --x-in | --x-i)
+ ac_prev=x_includes ;;
+ -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+ x_includes="$ac_optarg" ;;
+
+ -x-libraries | --x-libraries | --x-librarie | --x-librari \
+ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+ ac_prev=x_libraries ;;
+ -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+ x_libraries="$ac_optarg" ;;
+
+ -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; }
+ ;;
+
+ *)
+ if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then
+ echo "configure: warning: $ac_option: invalid host type" 1>&2
+ fi
+ if test "x$nonopt" != xNONE; then
+ { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; }
+ fi
+ nonopt="$ac_option"
+ ;;
+
+ esac
+done
+
+if test -n "$ac_prev"; then
+ { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; }
+fi
+
+trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
+
+# File descriptor usage:
+# 0 standard input
+# 1 file creation
+# 2 errors and warnings
+# 3 some systems may open it to /dev/tty
+# 4 used on the Kubota Titan
+# 6 checking for... messages and results
+# 5 compiler messages saved in config.log
+if test "$silent" = yes; then
+ exec 6>/dev/null
+else
+ exec 6>&1
+fi
+exec 5>./config.log
+
+echo "\
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+" 1>&5
+
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Also quote any args containing shell metacharacters.
+ac_configure_args=
+for ac_arg
+do
+ case "$ac_arg" in
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c) ;;
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;;
+ *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*)
+ ac_configure_args="$ac_configure_args '$ac_arg'" ;;
+ *) ac_configure_args="$ac_configure_args $ac_arg" ;;
+ esac
+done
+
+# NLS nuisances.
+# Only set these to C if already set. These must not be set unconditionally
+# because not all systems understand e.g. LANG=C (notably SCO).
+# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'!
+# Non-C LC_CTYPE values break the ctype check.
+if test "${LANG+set}" = set; then LANG=C; export LANG; fi
+if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi
+if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi
+if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -rf conftest* confdefs.h
+# AIX cpp loses on an empty file, so make sure it contains at least a newline.
+echo > confdefs.h
+
+# A filename unique to this package, relative to the directory that
+# configure is in, which we can look for to find out if srcdir is correct.
+ac_unique_file=adp.h
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+ ac_srcdir_defaulted=yes
+ # Try the directory containing this script, then its parent.
+ ac_prog=$0
+ ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'`
+ test "x$ac_confdir" = "x$ac_prog" && ac_confdir=.
+ srcdir=$ac_confdir
+ if test ! -r $srcdir/$ac_unique_file; then
+ srcdir=..
+ fi
+else
+ ac_srcdir_defaulted=no
+fi
+if test ! -r $srcdir/$ac_unique_file; then
+ if test "$ac_srcdir_defaulted" = yes; then
+ { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; }
+ else
+ { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; }
+ fi
+fi
+srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'`
+
+# Prefer explicitly selected file to automatically selected ones.
+if test -z "$CONFIG_SITE"; then
+ if test "x$prefix" != xNONE; then
+ CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site"
+ else
+ CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
+ fi
+fi
+for ac_site_file in $CONFIG_SITE; do
+ if test -r "$ac_site_file"; then
+ echo "loading site script $ac_site_file"
+ . "$ac_site_file"
+ fi
+done
+
+if test -r "$cache_file"; then
+ echo "loading cache $cache_file"
+ . $cache_file
+else
+ echo "creating cache $cache_file"
+ > $cache_file
+fi
+
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+ac_exeext=
+ac_objext=o
+if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then
+ # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu.
+ if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then
+ ac_n= ac_c='
+' ac_t=' '
+ else
+ ac_n=-n ac_c= ac_t=
+ fi
+else
+ ac_n= ac_c='\c' ac_t=
+fi
+
+
+
+ac_aux_dir=
+for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do
+ if test -f $ac_dir/install-sh; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install-sh -c"
+ break
+ elif test -f $ac_dir/install.sh; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install.sh -c"
+ break
+ fi
+done
+if test -z "$ac_aux_dir"; then
+ { echo "configure: error: can not find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." 1>&2; exit 1; }
+fi
+ac_config_guess=$ac_aux_dir/config.guess
+ac_config_sub=$ac_aux_dir/config.sub
+ac_configure=$ac_aux_dir/configure # This should be Cygnus configure.
+
+# Find a good install program. We prefer a C program (faster),
+# so one script is as good as another. But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# ./install, which can be erroneously created by make from ./install.sh.
+echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6
+echo "configure:560: checking for a BSD compatible install" >&5
+if test -z "$INSTALL"; then
+if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ IFS="${IFS= }"; ac_save_IFS="$IFS"; IFS=":"
+ for ac_dir in $PATH; do
+ # Account for people who put trailing slashes in PATH elements.
+ case "$ac_dir/" in
+ /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;;
+ *)
+ # OSF1 and SCO ODT 3.0 have their own names for install.
+ # Don't use installbsd from OSF since it installs stuff as root
+ # by default.
+ for ac_prog in ginstall scoinst install; do
+ if test -f $ac_dir/$ac_prog; then
+ if test $ac_prog = install &&
+ grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then
+ # AIX install. It has an incompatible calling convention.
+ :
+ else
+ ac_cv_path_install="$ac_dir/$ac_prog -c"
+ break 2
+ fi
+ fi
+ done
+ ;;
+ esac
+ done
+ IFS="$ac_save_IFS"
+
+fi
+ if test "${ac_cv_path_install+set}" = set; then
+ INSTALL="$ac_cv_path_install"
+ else
+ # As a last resort, use the slow shell script. We don't cache a
+ # path for INSTALL within a source directory, because that will
+ # break other packages using the cache if that directory is
+ # removed, or if the path is relative.
+ INSTALL="$ac_install_sh"
+ fi
+fi
+echo "$ac_t""$INSTALL" 1>&6
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL_PROGRAM}'
+
+echo $ac_n "checking whether build environment is sane""... $ac_c" 1>&6
+echo "configure:614: checking whether build environment is sane" >&5
+# Just in case
+sleep 1
+echo timestamp > conftestfile
+# Do `set' in a subshell so we don't clobber the current shell's
+# arguments. Must try -L first in case configure is actually a
+# symlink; some systems play weird games with the mod time of symlinks
+# (eg FreeBSD returns the mod time of the symlink's containing
+# directory).
+if (
+ set X `ls -Lt $srcdir/configure conftestfile 2> /dev/null`
+ if test "$*" = "X"; then
+ # -L didn't work.
+ set X `ls -t $srcdir/configure conftestfile`
+ fi
+ if test "$*" != "X $srcdir/configure conftestfile" \
+ && test "$*" != "X conftestfile $srcdir/configure"; then
+
+ # If neither matched, then we have a broken ls. This can happen
+ # if, for instance, CONFIG_SHELL is bash and it inherits a
+ # broken ls alias from the environment. This has actually
+ # happened. Such a system could not be considered "sane".
+ { echo "configure: error: ls -t appears to fail. Make sure there is not a broken
+alias in your environment" 1>&2; exit 1; }
+ fi
+
+ test "$2" = conftestfile
+ )
+then
+ # Ok.
+ :
+else
+ { echo "configure: error: newly created file is older than distributed files!
+Check your system clock" 1>&2; exit 1; }
+fi
+rm -f conftest*
+echo "$ac_t""yes" 1>&6
+if test "$program_transform_name" = s,x,x,; then
+ program_transform_name=
+else
+ # Double any \ or $. echo might interpret backslashes.
+ cat <<\EOF_SED > conftestsed
+s,\\,\\\\,g; s,\$,$$,g
+EOF_SED
+ program_transform_name="`echo $program_transform_name|sed -f conftestsed`"
+ rm -f conftestsed
+fi
+test "$program_prefix" != NONE &&
+ program_transform_name="s,^,${program_prefix},; $program_transform_name"
+# Use a double $ so make ignores it.
+test "$program_suffix" != NONE &&
+ program_transform_name="s,\$\$,${program_suffix},; $program_transform_name"
+
+# sed with no file args requires a program.
+test "$program_transform_name" = "" && program_transform_name="s,x,x,"
+
+echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6
+echo "configure:671: checking whether ${MAKE-make} sets \${MAKE}" >&5
+set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftestmake <<\EOF
+all:
+ @echo 'ac_maketemp="${MAKE}"'
+EOF
+# GNU make sometimes prints "make[1]: Entering...", which would confuse us.
+eval `${MAKE-make} -f conftestmake 2>/dev/null | grep temp=`
+if test -n "$ac_maketemp"; then
+ eval ac_cv_prog_make_${ac_make}_set=yes
+else
+ eval ac_cv_prog_make_${ac_make}_set=no
+fi
+rm -f conftestmake
+fi
+if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ SET_MAKE=
+else
+ echo "$ac_t""no" 1>&6
+ SET_MAKE="MAKE=${MAKE-make}"
+fi
+
+
+PACKAGE=rdi-share
+
+VERSION=1.0
+
+if test "`cd $srcdir && pwd`" != "`pwd`" && test -f $srcdir/config.status; then
+ { echo "configure: error: source directory already configured; run "make distclean" there first" 1>&2; exit 1; }
+fi
+cat >> confdefs.h <<EOF
+#define PACKAGE "$PACKAGE"
+EOF
+
+cat >> confdefs.h <<EOF
+#define VERSION "$VERSION"
+EOF
+
+
+
+missing_dir=`cd $ac_aux_dir && pwd`
+echo $ac_n "checking for working aclocal""... $ac_c" 1>&6
+echo "configure:717: checking for working aclocal" >&5
+# Run test in a subshell; some versions of sh will print an error if
+# an executable is not found, even if stderr is redirected.
+# Redirect stdin to placate older versions of autoconf. Sigh.
+if (aclocal --version) < /dev/null > /dev/null 2>&1; then
+ ACLOCAL=aclocal
+ echo "$ac_t""found" 1>&6
+else
+ ACLOCAL="$missing_dir/missing aclocal"
+ echo "$ac_t""missing" 1>&6
+fi
+
+echo $ac_n "checking for working autoconf""... $ac_c" 1>&6
+echo "configure:730: checking for working autoconf" >&5
+# Run test in a subshell; some versions of sh will print an error if
+# an executable is not found, even if stderr is redirected.
+# Redirect stdin to placate older versions of autoconf. Sigh.
+if (autoconf --version) < /dev/null > /dev/null 2>&1; then
+ AUTOCONF=autoconf
+ echo "$ac_t""found" 1>&6
+else
+ AUTOCONF="$missing_dir/missing autoconf"
+ echo "$ac_t""missing" 1>&6
+fi
+
+echo $ac_n "checking for working automake""... $ac_c" 1>&6
+echo "configure:743: checking for working automake" >&5
+# Run test in a subshell; some versions of sh will print an error if
+# an executable is not found, even if stderr is redirected.
+# Redirect stdin to placate older versions of autoconf. Sigh.
+if (automake --version) < /dev/null > /dev/null 2>&1; then
+ AUTOMAKE=automake
+ echo "$ac_t""found" 1>&6
+else
+ AUTOMAKE="$missing_dir/missing automake"
+ echo "$ac_t""missing" 1>&6
+fi
+
+echo $ac_n "checking for working autoheader""... $ac_c" 1>&6
+echo "configure:756: checking for working autoheader" >&5
+# Run test in a subshell; some versions of sh will print an error if
+# an executable is not found, even if stderr is redirected.
+# Redirect stdin to placate older versions of autoconf. Sigh.
+if (autoheader --version) < /dev/null > /dev/null 2>&1; then
+ AUTOHEADER=autoheader
+ echo "$ac_t""found" 1>&6
+else
+ AUTOHEADER="$missing_dir/missing autoheader"
+ echo "$ac_t""missing" 1>&6
+fi
+
+echo $ac_n "checking for working makeinfo""... $ac_c" 1>&6
+echo "configure:769: checking for working makeinfo" >&5
+# Run test in a subshell; some versions of sh will print an error if
+# an executable is not found, even if stderr is redirected.
+# Redirect stdin to placate older versions of autoconf. Sigh.
+if (makeinfo --version) < /dev/null > /dev/null 2>&1; then
+ MAKEINFO=makeinfo
+ echo "$ac_t""found" 1>&6
+else
+ MAKEINFO="$missing_dir/missing makeinfo"
+ echo "$ac_t""missing" 1>&6
+fi
+
+
+
+PACKAGE=rdi-share
+VERSION=1.0
+
+# Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:789: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ for ac_dir in $PATH; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_CC="gcc"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+ echo "$ac_t""$CC" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+if test -z "$CC"; then
+ # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:818: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_prog_rejected=no
+ for ac_dir in $PATH; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then
+ ac_prog_rejected=yes
+ continue
+ fi
+ ac_cv_prog_CC="cc"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+if test $ac_prog_rejected = yes; then
+ # We found a bogon in the path, so make sure we never use it.
+ set dummy $ac_cv_prog_CC
+ shift
+ if test $# -gt 0; then
+ # We chose a different compiler from the bogus one.
+ # However, it has the same basename, so the bogon will be chosen
+ # first if we set CC to just the basename; use the full file name.
+ shift
+ set dummy "$ac_dir/$ac_word" "$@"
+ shift
+ ac_cv_prog_CC="$@"
+ fi
+fi
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+ echo "$ac_t""$CC" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ if test -z "$CC"; then
+ case "`uname -s`" in
+ *win32* | *WIN32*)
+ # Extract the first word of "cl", so it can be a program name with args.
+set dummy cl; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:868: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ for ac_dir in $PATH; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_CC="cl"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+ echo "$ac_t""$CC" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+ ;;
+ esac
+ fi
+ test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; }
+fi
+
+echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6
+echo "configure:899: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5
+
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+cat > conftest.$ac_ext <<EOF
+#line 909 "configure"
+#include "confdefs.h"
+main(){return(0);}
+EOF
+if { (eval echo configure:913: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ ac_cv_prog_cc_works=yes
+ # If we can't run a trivial program, we are probably using a cross compiler.
+ if (./conftest; exit) 2>/dev/null; then
+ ac_cv_prog_cc_cross=no
+ else
+ ac_cv_prog_cc_cross=yes
+ fi
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ ac_cv_prog_cc_works=no
+fi
+rm -fr conftest*
+
+echo "$ac_t""$ac_cv_prog_cc_works" 1>&6
+if test $ac_cv_prog_cc_works = no; then
+ { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; }
+fi
+echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6
+echo "configure:933: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5
+echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6
+cross_compiling=$ac_cv_prog_cc_cross
+
+echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6
+echo "configure:938: checking whether we are using GNU C" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.c <<EOF
+#ifdef __GNUC__
+ yes;
+#endif
+EOF
+if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:947: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
+ ac_cv_prog_gcc=yes
+else
+ ac_cv_prog_gcc=no
+fi
+fi
+
+echo "$ac_t""$ac_cv_prog_gcc" 1>&6
+
+if test $ac_cv_prog_gcc = yes; then
+ GCC=yes
+else
+ GCC=
+fi
+
+ac_test_CFLAGS="${CFLAGS+set}"
+ac_save_CFLAGS="$CFLAGS"
+CFLAGS=
+echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6
+echo "configure:966: checking whether ${CC-cc} accepts -g" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ echo 'void f(){}' > conftest.c
+if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then
+ ac_cv_prog_cc_g=yes
+else
+ ac_cv_prog_cc_g=no
+fi
+rm -f conftest*
+
+fi
+
+echo "$ac_t""$ac_cv_prog_cc_g" 1>&6
+if test "$ac_test_CFLAGS" = set; then
+ CFLAGS="$ac_save_CFLAGS"
+elif test $ac_cv_prog_cc_g = yes; then
+ if test "$GCC" = yes; then
+ CFLAGS="-g -O2"
+ else
+ CFLAGS="-g"
+ fi
+else
+ if test "$GCC" = yes; then
+ CFLAGS="-O2"
+ else
+ CFLAGS=
+ fi
+fi
+
+# Find a good install program. We prefer a C program (faster),
+# so one script is as good as another. But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# ./install, which can be erroneously created by make from ./install.sh.
+echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6
+echo "configure:1009: checking for a BSD compatible install" >&5
+if test -z "$INSTALL"; then
+if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ IFS="${IFS= }"; ac_save_IFS="$IFS"; IFS=":"
+ for ac_dir in $PATH; do
+ # Account for people who put trailing slashes in PATH elements.
+ case "$ac_dir/" in
+ /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;;
+ *)
+ # OSF1 and SCO ODT 3.0 have their own names for install.
+ # Don't use installbsd from OSF since it installs stuff as root
+ # by default.
+ for ac_prog in ginstall scoinst install; do
+ if test -f $ac_dir/$ac_prog; then
+ if test $ac_prog = install &&
+ grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then
+ # AIX install. It has an incompatible calling convention.
+ :
+ else
+ ac_cv_path_install="$ac_dir/$ac_prog -c"
+ break 2
+ fi
+ fi
+ done
+ ;;
+ esac
+ done
+ IFS="$ac_save_IFS"
+
+fi
+ if test "${ac_cv_path_install+set}" = set; then
+ INSTALL="$ac_cv_path_install"
+ else
+ # As a last resort, use the slow shell script. We don't cache a
+ # path for INSTALL within a source directory, because that will
+ # break other packages using the cache if that directory is
+ # removed, or if the path is relative.
+ INSTALL="$ac_install_sh"
+ fi
+fi
+echo "$ac_t""$INSTALL" 1>&6
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6
+echo "configure:1060: checking whether ${MAKE-make} sets \${MAKE}" >&5
+set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftestmake <<\EOF
+all:
+ @echo 'ac_maketemp="${MAKE}"'
+EOF
+# GNU make sometimes prints "make[1]: Entering...", which would confuse us.
+eval `${MAKE-make} -f conftestmake 2>/dev/null | grep temp=`
+if test -n "$ac_maketemp"; then
+ eval ac_cv_prog_make_${ac_make}_set=yes
+else
+ eval ac_cv_prog_make_${ac_make}_set=no
+fi
+rm -f conftestmake
+fi
+if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ SET_MAKE=
+else
+ echo "$ac_t""no" 1>&6
+ SET_MAKE="MAKE=${MAKE-make}"
+fi
+
+# Extract the first word of "ranlib", so it can be a program name with args.
+set dummy ranlib; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:1089: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$RANLIB"; then
+ ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ for ac_dir in $PATH; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_RANLIB="ranlib"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ test -z "$ac_cv_prog_RANLIB" && ac_cv_prog_RANLIB=":"
+fi
+fi
+RANLIB="$ac_cv_prog_RANLIB"
+if test -n "$RANLIB"; then
+ echo "$ac_t""$RANLIB" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+
+
+echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6
+echo "configure:1118: checking how to run the C preprocessor" >&5
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+ CPP=
+fi
+if test -z "$CPP"; then
+if eval "test \"`echo '$''{'ac_cv_prog_CPP'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ # This must be in double quotes, not single quotes, because CPP may get
+ # substituted into the Makefile and "${CC-cc}" will confuse make.
+ CPP="${CC-cc} -E"
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp.
+ cat > conftest.$ac_ext <<EOF
+#line 1133 "configure"
+#include "confdefs.h"
+#include <assert.h>
+Syntax Error
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:1139: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ :
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ CPP="${CC-cc} -E -traditional-cpp"
+ cat > conftest.$ac_ext <<EOF
+#line 1150 "configure"
+#include "confdefs.h"
+#include <assert.h>
+Syntax Error
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:1156: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ :
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ CPP="${CC-cc} -nologo -E"
+ cat > conftest.$ac_ext <<EOF
+#line 1167 "configure"
+#include "confdefs.h"
+#include <assert.h>
+Syntax Error
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:1173: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ :
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ CPP=/lib/cpp
+fi
+rm -f conftest*
+fi
+rm -f conftest*
+fi
+rm -f conftest*
+ ac_cv_prog_CPP="$CPP"
+fi
+ CPP="$ac_cv_prog_CPP"
+else
+ ac_cv_prog_CPP="$CPP"
+fi
+echo "$ac_t""$CPP" 1>&6
+
+echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6
+echo "configure:1198: checking for ANSI C header files" >&5
+if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1203 "configure"
+#include "confdefs.h"
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:1211: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ ac_cv_header_stdc=yes
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+if test $ac_cv_header_stdc = yes; then
+ # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+cat > conftest.$ac_ext <<EOF
+#line 1228 "configure"
+#include "confdefs.h"
+#include <string.h>
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "memchr" >/dev/null 2>&1; then
+ :
+else
+ rm -rf conftest*
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+cat > conftest.$ac_ext <<EOF
+#line 1246 "configure"
+#include "confdefs.h"
+#include <stdlib.h>
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "free" >/dev/null 2>&1; then
+ :
+else
+ rm -rf conftest*
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+if test "$cross_compiling" = yes; then
+ :
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1267 "configure"
+#include "confdefs.h"
+#include <ctype.h>
+#define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+#define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int main () { int i; for (i = 0; i < 256; i++)
+if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2);
+exit (0); }
+
+EOF
+if { (eval echo configure:1278: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+ :
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -fr conftest*
+ ac_cv_header_stdc=no
+fi
+rm -fr conftest*
+fi
+
+fi
+fi
+
+echo "$ac_t""$ac_cv_header_stdc" 1>&6
+if test $ac_cv_header_stdc = yes; then
+ cat >> confdefs.h <<\EOF
+#define STDC_HEADERS 1
+EOF
+
+fi
+
+for ac_hdr in fcntl.h sys/ioctl.h sys/time.h unistd.h sys/filio.h
+do
+ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
+echo "configure:1305: checking for $ac_hdr" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1310 "configure"
+#include "confdefs.h"
+#include <$ac_hdr>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:1315: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=yes"
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_hdr 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+
+echo $ac_n "checking for working const""... $ac_c" 1>&6
+echo "configure:1343: checking for working const" >&5
+if eval "test \"`echo '$''{'ac_cv_c_const'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1348 "configure"
+#include "confdefs.h"
+
+int main() {
+
+/* Ultrix mips cc rejects this. */
+typedef int charset[2]; const charset x;
+/* SunOS 4.1.1 cc rejects this. */
+char const *const *ccp;
+char **p;
+/* NEC SVR4.0.2 mips cc rejects this. */
+struct point {int x, y;};
+static struct point const zero = {0,0};
+/* AIX XL C 1.02.0.0 rejects this.
+ It does not let you subtract one const X* pointer from another in an arm
+ of an if-expression whose if-part is not a constant expression */
+const char *g = "string";
+ccp = &g + (g ? g-g : 0);
+/* HPUX 7.0 cc rejects these. */
+++ccp;
+p = (char**) ccp;
+ccp = (char const *const *) p;
+{ /* SCO 3.2v4 cc rejects this. */
+ char *t;
+ char const *s = 0 ? (char *) 0 : (char const *) 0;
+
+ *t++ = 0;
+}
+{ /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */
+ int x[] = {25, 17};
+ const int *foo = &x[0];
+ ++foo;
+}
+{ /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */
+ typedef const int *iptr;
+ iptr p = 0;
+ ++p;
+}
+{ /* AIX XL C 1.02.0.0 rejects this saying
+ "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */
+ struct s { int j; const int *ap[3]; };
+ struct s *b; b->j = 5;
+}
+{ /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */
+ const int foo = 10;
+}
+
+; return 0; }
+EOF
+if { (eval echo configure:1397: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_c_const=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_c_const=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_c_const" 1>&6
+if test $ac_cv_c_const = no; then
+ cat >> confdefs.h <<\EOF
+#define const
+EOF
+
+fi
+
+echo $ac_n "checking for size_t""... $ac_c" 1>&6
+echo "configure:1418: checking for size_t" >&5
+if eval "test \"`echo '$''{'ac_cv_type_size_t'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1423 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#if STDC_HEADERS
+#include <stdlib.h>
+#include <stddef.h>
+#endif
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "size_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then
+ rm -rf conftest*
+ ac_cv_type_size_t=yes
+else
+ rm -rf conftest*
+ ac_cv_type_size_t=no
+fi
+rm -f conftest*
+
+fi
+echo "$ac_t""$ac_cv_type_size_t" 1>&6
+if test $ac_cv_type_size_t = no; then
+ cat >> confdefs.h <<\EOF
+#define size_t unsigned
+EOF
+
+fi
+
+echo $ac_n "checking whether time.h and sys/time.h may both be included""... $ac_c" 1>&6
+echo "configure:1451: checking whether time.h and sys/time.h may both be included" >&5
+if eval "test \"`echo '$''{'ac_cv_header_time'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1456 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <sys/time.h>
+#include <time.h>
+int main() {
+struct tm *tp;
+; return 0; }
+EOF
+if { (eval echo configure:1465: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_header_time=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_header_time=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_header_time" 1>&6
+if test $ac_cv_header_time = yes; then
+ cat >> confdefs.h <<\EOF
+#define TIME_WITH_SYS_TIME 1
+EOF
+
+fi
+
+
+if test $ac_cv_prog_gcc = yes; then
+ echo $ac_n "checking whether ${CC-cc} needs -traditional""... $ac_c" 1>&6
+echo "configure:1488: checking whether ${CC-cc} needs -traditional" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_gcc_traditional'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_pattern="Autoconf.*'x'"
+ cat > conftest.$ac_ext <<EOF
+#line 1494 "configure"
+#include "confdefs.h"
+#include <sgtty.h>
+Autoconf TIOCGETP
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "$ac_pattern" >/dev/null 2>&1; then
+ rm -rf conftest*
+ ac_cv_prog_gcc_traditional=yes
+else
+ rm -rf conftest*
+ ac_cv_prog_gcc_traditional=no
+fi
+rm -f conftest*
+
+
+ if test $ac_cv_prog_gcc_traditional = no; then
+ cat > conftest.$ac_ext <<EOF
+#line 1512 "configure"
+#include "confdefs.h"
+#include <termio.h>
+Autoconf TCGETA
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "$ac_pattern" >/dev/null 2>&1; then
+ rm -rf conftest*
+ ac_cv_prog_gcc_traditional=yes
+fi
+rm -f conftest*
+
+ fi
+fi
+
+echo "$ac_t""$ac_cv_prog_gcc_traditional" 1>&6
+ if test $ac_cv_prog_gcc_traditional = yes; then
+ CC="$CC -traditional"
+ fi
+fi
+
+echo $ac_n "checking return type of signal handlers""... $ac_c" 1>&6
+echo "configure:1534: checking return type of signal handlers" >&5
+if eval "test \"`echo '$''{'ac_cv_type_signal'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1539 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <signal.h>
+#ifdef signal
+#undef signal
+#endif
+#ifdef __cplusplus
+extern "C" void (*signal (int, void (*)(int)))(int);
+#else
+void (*signal ()) ();
+#endif
+
+int main() {
+int i;
+; return 0; }
+EOF
+if { (eval echo configure:1556: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_type_signal=void
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_type_signal=int
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_type_signal" 1>&6
+cat >> confdefs.h <<EOF
+#define RETSIGTYPE $ac_cv_type_signal
+EOF
+
+
+echo $ac_n "checking for vprintf""... $ac_c" 1>&6
+echo "configure:1575: checking for vprintf" >&5
+if eval "test \"`echo '$''{'ac_cv_func_vprintf'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1580 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char vprintf(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char vprintf();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_vprintf) || defined (__stub___vprintf)
+choke me
+#else
+vprintf();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:1603: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_vprintf=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_func_vprintf=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'vprintf`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ cat >> confdefs.h <<\EOF
+#define HAVE_VPRINTF 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+if test "$ac_cv_func_vprintf" != yes; then
+echo $ac_n "checking for _doprnt""... $ac_c" 1>&6
+echo "configure:1627: checking for _doprnt" >&5
+if eval "test \"`echo '$''{'ac_cv_func__doprnt'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1632 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char _doprnt(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char _doprnt();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub__doprnt) || defined (__stub____doprnt)
+choke me
+#else
+_doprnt();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:1655: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func__doprnt=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_func__doprnt=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'_doprnt`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ cat >> confdefs.h <<\EOF
+#define HAVE_DOPRNT 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+fi
+
+for ac_func in gettimeofday select socket strtod strtoul memcpy memmove
+do
+echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+echo "configure:1682: checking for $ac_func" >&5
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1687 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $ac_func();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:1710: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_func 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+
+echo $ac_n "checking whether to enable maintainer-specific portions of Makefiles""... $ac_c" 1>&6
+echo "configure:1736: checking whether to enable maintainer-specific portions of Makefiles" >&5
+ # Check whether --enable-maintainer-mode or --disable-maintainer-mode was given.
+if test "${enable_maintainer_mode+set}" = set; then
+ enableval="$enable_maintainer_mode"
+ USE_MAINTAINER_MODE=$enableval
+else
+ USE_MAINTAINER_MODE=no
+fi
+
+ echo "$ac_t""$USE_MAINTAINER_MODE" 1>&6
+ if test $USE_MAINTAINER_MODE = yes; then
+ MAINT=
+ else
+ MAINT='#M#'
+ fi
+
+
+echo $ac_n "checking for Cygwin environment""... $ac_c" 1>&6
+echo "configure:1754: checking for Cygwin environment" >&5
+if eval "test \"`echo '$''{'am_cv_cygwin'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1759 "configure"
+#include "confdefs.h"
+
+int main() {
+return __CYGWIN32__;
+; return 0; }
+EOF
+if { (eval echo configure:1766: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ am_cv_cygwin=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ am_cv_cygwin=no
+fi
+rm -f conftest*
+rm -f conftest*
+fi
+
+echo "$ac_t""$am_cv_cygwin" 1>&6
+CYGWIN=
+test "$am_cv_cygwin" = yes && CYGWIN=yes
+echo $ac_n "checking for Mingw32 environment""... $ac_c" 1>&6
+echo "configure:1783: checking for Mingw32 environment" >&5
+if eval "test \"`echo '$''{'am_cv_mingw32'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1788 "configure"
+#include "confdefs.h"
+
+int main() {
+return __MINGW32__;
+; return 0; }
+EOF
+if { (eval echo configure:1795: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ am_cv_mingw32=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ am_cv_mingw32=no
+fi
+rm -f conftest*
+rm -f conftest*
+fi
+
+echo "$ac_t""$am_cv_mingw32" 1>&6
+MINGW32=
+test "$am_cv_mingw32" = yes && MINGW32=yes
+
+
+echo $ac_n "checking for executable suffix""... $ac_c" 1>&6
+echo "configure:1814: checking for executable suffix" >&5
+if eval "test \"`echo '$''{'am_cv_exeext'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test "$CYGWIN" = yes || test "$MINGW32" = yes; then
+am_cv_exeext=.exe
+else
+cat > am_c_test.c << 'EOF'
+int main() {
+/* Nothing needed here */
+}
+EOF
+${CC-cc} -o am_c_test $CFLAGS $CPPFLAGS $LDFLAGS am_c_test.c $LIBS 1>&5
+am_cv_exeext=
+for file in am_c_test.*; do
+ case $file in
+ *.c) ;;
+ *.o) ;;
+ *) am_cv_exeext=`echo $file | sed -e s/am_c_test//` ;;
+ esac
+done
+rm -f am_c_test*
+fi
+
+test x"${am_cv_exeext}" = x && am_cv_exeext=no
+fi
+EXEEXT=""
+test x"${am_cv_exeext}" != xno && EXEEXT=${am_cv_exeext}
+echo "$ac_t""${am_cv_exeext}" 1>&6
+
+
+trap '' 1 2 15
+cat > confcache <<\EOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs. It is not useful on other systems.
+# If it contains results you don't want to keep, you may remove or edit it.
+#
+# By default, configure uses ./config.cache as the cache file,
+# creating it if it does not exist already. You can give configure
+# the --cache-file=FILE option to use a different cache file; that is
+# what configure does when it calls configure scripts in
+# subdirectories, so they share the cache.
+# Giving --cache-file=/dev/null disables caching, for debugging configure.
+# config.status only pays attention to the cache file if you give it the
+# --recheck option to rerun configure.
+#
+EOF
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, don't put newlines in cache variables' values.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(set) 2>&1 |
+ case `(ac_space=' '; set) 2>&1 | grep ac_space` in
+ *ac_space=\ *)
+ # `set' does not quote correctly, so add quotes (double-quote substitution
+ # turns \\\\ into \\, and sed turns \\ into \).
+ sed -n \
+ -e "s/'/'\\\\''/g" \
+ -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p"
+ ;;
+ *)
+ # `set' quotes correctly as required by POSIX, so do not add quotes.
+ sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p'
+ ;;
+ esac >> confcache
+if cmp -s $cache_file confcache; then
+ :
+else
+ if test -w $cache_file; then
+ echo "updating cache $cache_file"
+ cat confcache > $cache_file
+ else
+ echo "not updating unwritable cache $cache_file"
+ fi
+fi
+rm -f confcache
+
+trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+# Any assignment to VPATH causes Sun make to only execute
+# the first set of double-colon rules, so remove it if not needed.
+# If there is a colon in the path, we need to keep it.
+if test "x$srcdir" = x.; then
+ ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d'
+fi
+
+trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15
+
+# Transform confdefs.h into DEFS.
+# Protect against shell expansion while executing Makefile rules.
+# Protect against Makefile macro expansion.
+cat > conftest.defs <<\EOF
+s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%-D\1=\2%g
+s%[ `~#$^&*(){}\\|;'"<>?]%\\&%g
+s%\[%\\&%g
+s%\]%\\&%g
+s%\$%$$%g
+EOF
+DEFS=`sed -f conftest.defs confdefs.h | tr '\012' ' '`
+rm -f conftest.defs
+
+
+# Without the "./", some shells look in PATH for config.status.
+: ${CONFIG_STATUS=./config.status}
+
+echo creating $CONFIG_STATUS
+rm -f $CONFIG_STATUS
+cat > $CONFIG_STATUS <<EOF
+#! /bin/sh
+# Generated automatically by configure.
+# Run this file to recreate the current configuration.
+# This directory was configured as follows,
+# on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+#
+# $0 $ac_configure_args
+#
+# Compiler output produced by configure, useful for debugging
+# configure, is in ./config.log if it exists.
+
+ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]"
+for ac_option
+do
+ case "\$ac_option" in
+ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+ echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion"
+ exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;;
+ -version | --version | --versio | --versi | --vers | --ver | --ve | --v)
+ echo "$CONFIG_STATUS generated by autoconf version 2.12.2"
+ exit 0 ;;
+ -help | --help | --hel | --he | --h)
+ echo "\$ac_cs_usage"; exit 0 ;;
+ *) echo "\$ac_cs_usage"; exit 1 ;;
+ esac
+done
+
+ac_given_srcdir=$srcdir
+ac_given_INSTALL="$INSTALL"
+
+trap 'rm -fr `echo "Makefile" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15
+EOF
+cat >> $CONFIG_STATUS <<EOF
+
+# Protect against being on the right side of a sed subst in config.status.
+sed 's/%@/@@/; s/@%/@@/; s/%g\$/@g/; /@g\$/s/[\\\\&%]/\\\\&/g;
+ s/@@/%@/; s/@@/@%/; s/@g\$/%g/' > conftest.subs <<\\CEOF
+$ac_vpsub
+$extrasub
+s%@SHELL@%$SHELL%g
+s%@CFLAGS@%$CFLAGS%g
+s%@CPPFLAGS@%$CPPFLAGS%g
+s%@CXXFLAGS@%$CXXFLAGS%g
+s%@DEFS@%$DEFS%g
+s%@LDFLAGS@%$LDFLAGS%g
+s%@LIBS@%$LIBS%g
+s%@exec_prefix@%$exec_prefix%g
+s%@prefix@%$prefix%g
+s%@program_transform_name@%$program_transform_name%g
+s%@bindir@%$bindir%g
+s%@sbindir@%$sbindir%g
+s%@libexecdir@%$libexecdir%g
+s%@datadir@%$datadir%g
+s%@sysconfdir@%$sysconfdir%g
+s%@sharedstatedir@%$sharedstatedir%g
+s%@localstatedir@%$localstatedir%g
+s%@libdir@%$libdir%g
+s%@includedir@%$includedir%g
+s%@oldincludedir@%$oldincludedir%g
+s%@infodir@%$infodir%g
+s%@mandir@%$mandir%g
+s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g
+s%@INSTALL_DATA@%$INSTALL_DATA%g
+s%@INSTALL_SCRIPT@%$INSTALL_SCRIPT%g
+s%@PACKAGE@%$PACKAGE%g
+s%@VERSION@%$VERSION%g
+s%@ACLOCAL@%$ACLOCAL%g
+s%@AUTOCONF@%$AUTOCONF%g
+s%@AUTOMAKE@%$AUTOMAKE%g
+s%@AUTOHEADER@%$AUTOHEADER%g
+s%@MAKEINFO@%$MAKEINFO%g
+s%@SET_MAKE@%$SET_MAKE%g
+s%@CC@%$CC%g
+s%@RANLIB@%$RANLIB%g
+s%@CPP@%$CPP%g
+s%@MAINT@%$MAINT%g
+s%@EXEEXT@%$EXEEXT%g
+
+CEOF
+EOF
+
+cat >> $CONFIG_STATUS <<\EOF
+
+# Split the substitutions into bite-sized pieces for seds with
+# small command number limits, like on Digital OSF/1 and HP-UX.
+ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script.
+ac_file=1 # Number of current file.
+ac_beg=1 # First line for current file.
+ac_end=$ac_max_sed_cmds # Line after last line for current file.
+ac_more_lines=:
+ac_sed_cmds=""
+while $ac_more_lines; do
+ if test $ac_beg -gt 1; then
+ sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file
+ else
+ sed "${ac_end}q" conftest.subs > conftest.s$ac_file
+ fi
+ if test ! -s conftest.s$ac_file; then
+ ac_more_lines=false
+ rm -f conftest.s$ac_file
+ else
+ if test -z "$ac_sed_cmds"; then
+ ac_sed_cmds="sed -f conftest.s$ac_file"
+ else
+ ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file"
+ fi
+ ac_file=`expr $ac_file + 1`
+ ac_beg=$ac_end
+ ac_end=`expr $ac_end + $ac_max_sed_cmds`
+ fi
+done
+if test -z "$ac_sed_cmds"; then
+ ac_sed_cmds=cat
+fi
+EOF
+
+cat >> $CONFIG_STATUS <<EOF
+
+CONFIG_FILES=\${CONFIG_FILES-"Makefile"}
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then
+ # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+ case "$ac_file" in
+ *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'`
+ ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
+ *) ac_file_in="${ac_file}.in" ;;
+ esac
+
+ # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories.
+
+ # Remove last slash and all that follows it. Not all systems have dirname.
+ ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
+ if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
+ # The file is in a subdirectory.
+ test ! -d "$ac_dir" && mkdir "$ac_dir"
+ ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`"
+ # A "../" for each directory in $ac_dir_suffix.
+ ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'`
+ else
+ ac_dir_suffix= ac_dots=
+ fi
+
+ case "$ac_given_srcdir" in
+ .) srcdir=.
+ if test -z "$ac_dots"; then top_srcdir=.
+ else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;;
+ /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;;
+ *) # Relative path.
+ srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix"
+ top_srcdir="$ac_dots$ac_given_srcdir" ;;
+ esac
+
+ case "$ac_given_INSTALL" in
+ [/$]*) INSTALL="$ac_given_INSTALL" ;;
+ *) INSTALL="$ac_dots$ac_given_INSTALL" ;;
+ esac
+
+ echo creating "$ac_file"
+ rm -f "$ac_file"
+ configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure."
+ case "$ac_file" in
+ *Makefile*) ac_comsub="1i\\
+# $configure_input" ;;
+ *) ac_comsub= ;;
+ esac
+
+ ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"`
+ sed -e "$ac_comsub
+s%@configure_input@%$configure_input%g
+s%@srcdir@%$srcdir%g
+s%@top_srcdir@%$top_srcdir%g
+s%@INSTALL@%$INSTALL%g
+" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file
+fi; done
+rm -f conftest.s*
+
+EOF
+cat >> $CONFIG_STATUS <<EOF
+
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+
+exit 0
+EOF
+chmod +x $CONFIG_STATUS
+rm -fr confdefs* $ac_clean_files
+test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1
+
diff --git a/gdb/rdi-share/configure.in b/gdb/rdi-share/configure.in
new file mode 100644
index 00000000000..bbda5ccbad0
--- /dev/null
+++ b/gdb/rdi-share/configure.in
@@ -0,0 +1,36 @@
+dnl Process this file with autoconf to produce a configure script.
+AC_PREREQ(2.12.1)
+AC_INIT(adp.h)
+
+AM_INIT_AUTOMAKE(rdi-share, 1.0)
+
+PACKAGE=rdi-share
+VERSION=1.0
+
+dnl Checks for programs.
+AC_PROG_CC
+AC_PROG_INSTALL
+AC_PROG_MAKE_SET
+AC_PROG_RANLIB
+
+dnl Checks for libraries.
+
+dnl Checks for header files.
+AC_HEADER_STDC
+AC_CHECK_HEADERS(fcntl.h sys/ioctl.h sys/time.h unistd.h sys/filio.h)
+
+dnl Checks for typedefs, structures, and compiler characteristics.
+AC_C_CONST
+AC_TYPE_SIZE_T
+AC_HEADER_TIME
+
+dnl Checks for library functions.
+AC_PROG_GCC_TRADITIONAL
+AC_TYPE_SIGNAL
+AC_FUNC_VPRINTF
+AC_CHECK_FUNCS(gettimeofday select socket strtod strtoul memcpy memmove)
+
+AM_MAINTAINER_MODE
+AM_EXEEXT
+
+AC_OUTPUT(Makefile)
diff --git a/gdb/rdi-share/crc.c b/gdb/rdi-share/crc.c
new file mode 100644
index 00000000000..cfa6522e8d2
--- /dev/null
+++ b/gdb/rdi-share/crc.c
@@ -0,0 +1,257 @@
+/*
+ * Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
+ *
+ * This software may be freely used, copied, modified, and distributed
+ * provided that the above copyright notice is preserved in all copies of the
+ * software.
+ */
+
+/* -*-C-*-
+ *
+ * $Revision$
+ * $Date$
+ *
+ *
+ * crc.c - provides some "standard" CRC calculation routines.
+ *
+ */
+#include "crc.h" /* describes this code */
+
+/**********************************************************************/
+
+/*
+ * crc32 IEEE-802.3 32bit CRC
+ * ----- --------------------
+ */
+
+/* This table was generated by the "crctable" program */
+static const unsigned int crc32table[256] = {
+ /* 0x00 */ 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA,
+ /* 0x04 */ 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
+ /* 0x08 */ 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988,
+ /* 0x0C */ 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
+ /* 0x10 */ 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE,
+ /* 0x14 */ 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
+ /* 0x18 */ 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC,
+ /* 0x1C */ 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
+ /* 0x20 */ 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,
+ /* 0x24 */ 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
+ /* 0x28 */ 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940,
+ /* 0x2C */ 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
+ /* 0x30 */ 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116,
+ /* 0x34 */ 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
+ /* 0x38 */ 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924,
+ /* 0x3C */ 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
+ /* 0x40 */ 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A,
+ /* 0x44 */ 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
+ /* 0x48 */ 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818,
+ /* 0x4C */ 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
+ /* 0x50 */ 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
+ /* 0x54 */ 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
+ /* 0x58 */ 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C,
+ /* 0x5C */ 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
+ /* 0x60 */ 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2,
+ /* 0x64 */ 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
+ /* 0x68 */ 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,
+ /* 0x6C */ 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
+ /* 0x70 */ 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086,
+ /* 0x74 */ 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
+ /* 0x78 */ 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4,
+ /* 0x7C */ 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
+ /* 0x80 */ 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A,
+ /* 0x84 */ 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
+ /* 0x88 */ 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8,
+ /* 0x8C */ 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
+ /* 0x90 */ 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE,
+ /* 0x94 */ 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
+ /* 0x98 */ 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
+ /* 0x9C */ 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
+ /* 0xA0 */ 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252,
+ /* 0xA4 */ 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
+ /* 0xA8 */ 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60,
+ /* 0xAC */ 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
+ /* 0xB0 */ 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
+ /* 0xB4 */ 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
+ /* 0xB8 */ 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04,
+ /* 0xBC */ 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
+ /* 0xC0 */ 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A,
+ /* 0xC4 */ 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
+ /* 0xC8 */ 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38,
+ /* 0xCC */ 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
+ /* 0xD0 */ 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E,
+ /* 0xD4 */ 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
+ /* 0xD8 */ 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C,
+ /* 0xDC */ 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
+ /* 0xE0 */ 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2,
+ /* 0xE4 */ 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
+ /* 0xE8 */ 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0,
+ /* 0xEC */ 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
+ /* 0xF0 */ 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6,
+ /* 0xF4 */ 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
+ /* 0xF8 */ 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
+ /* 0xFC */ 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D,
+ };
+unsigned int crc32(unsigned char *address, unsigned int size, unsigned int crc)
+{
+#if 0
+ /* FAST, but bigger and only good for word-aligned data */
+ unsigned int *daddr = (unsigned int *)address;
+ unsigned int data = FALSE; /* little-endian by default */
+
+ /*
+ * TODO: We should really get the current processor big- or
+ * little-endian state and set "data" accordingly.
+ */
+
+ /* Perform word loop to save on memory accesses */
+ if (data)
+ /* big-endian */
+ for (; (size > 0); size -= sizeof(unsigned int))
+ {
+ data = *daddr++;
+ crc = (((crc >> 8) & 0x00FFFFFF) ^
+ crc32table[(crc ^ ((data >> 24) & 0xFF)) & 0xFF]);
+ crc = (((crc >> 8) & 0x00FFFFFF) ^
+ crc32table[(crc ^ ((data >> 16) & 0xFF)) & 0xFF]);
+ crc = (((crc >> 8) & 0x00FFFFFF) ^
+ crc32table[(crc ^ ((data >> 8) & 0xFF)) & 0xFF]);
+ crc = (((crc >> 8) & 0x00FFFFFF) ^
+ crc32table[(crc ^ ((data >> 0) & 0xFF)) & 0xFF]);
+ }
+ else
+ for (; (size > 0); size -= sizeof(unsigned int))
+ {
+ data = *daddr++;
+ crc = (((crc >> 8) & 0x00FFFFFF) ^
+ crc32table[(crc ^ ((data >> 0) & 0xFF)) & 0xFF]);
+ crc = (((crc >> 8) & 0x00FFFFFF) ^
+ crc32table[(crc ^ ((data >> 8) & 0xFF)) & 0xFF]);
+ crc = (((crc >> 8) & 0x00FFFFFF) ^
+ crc32table[(crc ^ ((data >> 16) & 0xFF)) & 0xFF]);
+ crc = (((crc >> 8) & 0x00FFFFFF) ^
+ crc32table[(crc ^ ((data >> 24) & 0xFF)) & 0xFF]);
+ }
+#else
+ for (; (size > 0); size--)
+ /* byte loop */
+ crc = (((crc >> 8) & 0x00FFFFFF) ^
+ crc32table[(crc ^ *address++) & 0x000000FF]);
+#endif
+
+ return(crc);
+}
+
+/**********************************************************************/
+
+/*
+ * crc16 16bit CRC-CCITT
+ * ----- ---------------
+ * This function provides a table driven 16bit CRC generation for byte data.
+ * This CRC is also known as the HDLC CRC.
+ */
+/*
+ * 960201 KWelton
+ *
+ *TODO: Is this correct? The compiler predefines __arm, *not* __ARM
+ */
+#ifdef __ARM
+/*
+ * To make the code quicker on the ARM, we double the table size and
+ * use integer slots rather than short slots for the table.
+ */
+static const unsigned int crctableA[16] = {
+#else
+static const unsigned short crctableA[16] = {
+#endif
+ 0x0000,
+ 0x1081,
+ 0x2102,
+ 0x3183,
+ 0x4204,
+ 0x5285,
+ 0x6306,
+ 0x7387,
+ 0x8408,
+ 0x9489,
+ 0xA50A,
+ 0xB58B,
+ 0xC60C,
+ 0xD68D,
+ 0xE70E,
+ 0xF78F
+ };
+
+#ifdef __ARM
+/* See comments above */
+static const unsigned int crctableB[16] = {
+#else
+static const unsigned short crctableB[16] = {
+#endif
+ 0x0000,
+ 0x1189,
+ 0x2312,
+ 0x329B,
+ 0x4624,
+ 0x57AD,
+ 0x6536,
+ 0x74BF,
+ 0x8C48,
+ 0x9DC1,
+ 0xAF5A,
+ 0xBED3,
+ 0xCA6C,
+ 0xDBE5,
+ 0xE97E,
+ 0xF8F7
+ };
+
+unsigned short crc16(unsigned char *address, unsigned int size,
+ unsigned short crc)
+{
+ for (; (size > 0); size--)
+ {
+ /* byte loop */
+ unsigned char data = *address++; /* fetch the next data byte */
+
+ data ^= crc; /* EOR data with current CRC value */
+ crc = ((crctableA[(data & 0xF0) >> 4] ^ crctableB[data & 0x0F]) ^
+ (crc >> 8));
+ }
+
+ return(crc);
+}
+
+/**********************************************************************/
+
+#if 0 /* not required at the moment */
+
+/*
+ * elf_hash
+ * --------
+ * This function is derived from the one on page 68 of chapter of the "Unix
+ * SVR4 Programmer's Guide". It is used to generate a hash-code from a
+ * symbol name.
+ */
+unsigned int elf_hash(const unsigned char *name)
+{
+ unsigned int h = 0;
+ unsigned int g;
+
+ /* NULL pointer returns a hash of zero */
+ while (name && (*name))
+ {
+ h = ((h << 4) + *name++);
+
+ if (g = (h & 0xF0000000))
+ h ^= (g >> 24);
+
+ h &= ~g;
+ }
+
+ return(h);
+}
+#endif
+
+/**********************************************************************/
+
+/* EOF crc.c */
diff --git a/gdb/rdi-share/crc.h b/gdb/rdi-share/crc.h
new file mode 100644
index 00000000000..77ba23e97df
--- /dev/null
+++ b/gdb/rdi-share/crc.h
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
+ *
+ * This software may be freely used, copied, modified, and distributed
+ * provided that the above copyright notice is preserved in all copies of the
+ * software.
+ */
+
+/* -*-C-*-
+ *
+ * $Revision$
+ * $Date$
+ *
+ *
+ * crc.h - describes some "standard" CRC calculation routines.
+ */
+#ifndef angel_crc_h
+#define angel_crc_h
+
+/*
+ * manifests
+ */
+
+/*
+ * When using "crc32" or "crc16" these initial CRC values must be given to
+ * the respective function the first time it is called. The function can
+ * then be called with the return value from the last call of the function
+ * to generate a running CRC over multiple data blocks.
+ * When the last data block has been processed using the "crc32" algorithm
+ * the CRC value should be inverted to produce the final CRC value:
+ * e.g. CRC = ~CRC
+ */
+
+#define startCRC32 (0xFFFFFFFF) /* CRC initialised to all 1s */
+#define startCRC16 (0x0000) /* CRC initialised to all 0s */
+
+/*
+ * For the CRC-32 residual to be calculated correctly requires that the CRC
+ * value is in memory little-endian due to the byte read, bit-ordering
+ * nature of the algorithm.
+ */
+#define CRC32residual (0xDEBB20E3) /* good CRC-32 residual */
+
+
+/**********************************************************************/
+
+/*
+ * exported functions
+ */
+
+/*
+ * Function: crc32
+ * Purpose: Provides a table driven implementation of the IEEE-802.3
+ * 32-bit CRC algorithm for byte data.
+ *
+ * Params:
+ * Input: address pointer to the byte data
+ * size number of bytes of data to be processed
+ * crc initial CRC value to be used (can be the output
+ * from a previous call to this function).
+ * Returns:
+ * OK: 32-bit CRC value for the specified data
+ */
+extern unsigned int crc32(unsigned char *address, unsigned int size,
+ unsigned int crc);
+
+/**********************************************************************/
+
+/*
+ *
+ * Function: crc16
+ * Purpose: Generates a table driven 16-bit CRC-CCITT for byte data
+ *
+ * Params:
+ * Input: address pointer to the byte data
+ * size number of bytes of data to be processed
+ * crc initial CRC value to be used (can be the output
+ * from a previous call to this function).
+ *
+ * Returns:
+ * OK: 16-bit CRC value for the specified data
+ */
+extern unsigned short crc16(unsigned char *address, unsigned int size,
+ unsigned short crc);
+
+/**********************************************************************/
+
+#endif /* !defined(angel_crc_h) */
+
+/* EOF crc.h */
diff --git a/gdb/rdi-share/dbg_conf.h b/gdb/rdi-share/dbg_conf.h
new file mode 100644
index 00000000000..bf79958e6c5
--- /dev/null
+++ b/gdb/rdi-share/dbg_conf.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
+ *
+ * This software may be freely used, copied, modified, and distributed
+ * provided that the above copyright notice is preserved in all copies of the
+ * software.
+ */
+
+/*
+ * ARM symbolic debugger toolbox: dbg_conf.h
+ */
+
+/*
+ * RCS $Revision$
+ * Checkin $Date$
+ */
+
+#ifndef Dbg_Conf__h
+
+#define Dbg_Conf__h
+
+typedef struct Dbg_ConfigBlock {
+ int bytesex;
+ int fpe; /* Target should initialise FPE */
+ long memorysize;
+ unsigned long cpu_speed;/* Cpu speed (HZ) */
+ int serialport; /*) remote connection parameters */
+ int seriallinespeed; /*) (serial connection) */
+ int parallelport; /*) ditto */
+ int parallellinespeed; /*) (parallel connection) */
+ char *ethernettarget; /* name of remote ethernet target */
+ int processor; /* processor the armulator is to emulate (eg ARM60) */
+ int rditype; /* armulator / remote processor */
+ int heartbeat_on; /* angel heartbeat */
+ int drivertype; /* parallel / serial / etc */
+ char const *configtoload;
+ char const *memconfigtoload;
+ int flags;
+} Dbg_ConfigBlock;
+
+#define Dbg_ConfigFlag_Reset 1
+#define Dbg_ConfigFlag_LLSymsNeedPrefix 2
+
+typedef struct Dbg_HostosInterface Dbg_HostosInterface;
+/* This structure allows access by the (host-independent) C-library support
+ module of armulator or pisd (armos.c) to host-dependent functions for
+ which there is no host-independent interface. Its contents are unknown
+ to the debugger toolbox.
+ The assumption is that, in a windowed system, fputc(stderr) for example
+ may not achieve the desired effect of the character appearing in some
+ window.
+ */
+
+#endif
diff --git a/gdb/rdi-share/dbg_cp.h b/gdb/rdi-share/dbg_cp.h
new file mode 100644
index 00000000000..8974f836442
--- /dev/null
+++ b/gdb/rdi-share/dbg_cp.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
+ *
+ * This software may be freely used, copied, modified, and distributed
+ * provided that the above copyright notice is preserved in all copies of the
+ * software.
+ */
+
+/*
+ * ARM symbolic debugger toolbox: dbg_cp.h
+ */
+
+/*
+ * RCS $Revision$
+ * Checkin $Date$
+ */
+
+#ifndef Dbg_CP__h
+
+#define Dbg_CP__h
+
+#define Dbg_Access_Readable 1
+#define Dbg_Access_Writable 2
+#define Dbg_Access_CPDT 4 /* else CPRT */
+
+typedef struct {
+ unsigned short rmin, rmax;
+ /* a single description can be used for a range of registers with
+ the same properties *accessed via CPDT instructions*
+ */
+ unsigned char nbytes; /* size of register */
+ unsigned char access; /* see above (Access_xxx) */
+ union {
+ struct { /* CPDT instructions do not allow the coprocessor much freedom:
+ only bit 22 ('N') and 12-15 ('CRd') are free for the
+ coprocessor to use as it sees fit.
+ */
+ unsigned char nbit;
+ unsigned char rdbits;
+ } cpdt;
+ struct { /* CPRT instructions have much more latitude. The bits fixed
+ by the ARM are 24..31 (condition mask & opcode)
+ 20 (direction)
+ 8..15 (cpnum, arm register)
+ 4 (CPRT not CPDO)
+ leaving 14 bits free to the coprocessor (fortunately
+ falling within two bytes).
+ */
+ unsigned char read_b0, read_b1,
+ write_b0, write_b1;
+ } cprt;
+ } accessinst;
+} Dbg_CoProRegDesc;
+
+struct Dbg_CoProDesc {
+ int entries;
+ Dbg_CoProRegDesc regdesc[1/* really nentries */];
+};
+
+#define Dbg_CoProDesc_Size(n) (sizeof(struct Dbg_CoProDesc) + ((n)-1)*sizeof(Dbg_CoProRegDesc))
+
+#endif
diff --git a/gdb/rdi-share/dbg_hif.h b/gdb/rdi-share/dbg_hif.h
new file mode 100644
index 00000000000..5be21563660
--- /dev/null
+++ b/gdb/rdi-share/dbg_hif.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
+ *
+ * This software may be freely used, copied, modified, and distributed
+ * provided that the above copyright notice is preserved in all copies of the
+ * software.
+ */
+
+/*
+ * ARM debugger toolbox : dbg_hif.c
+ * Description of the Dbg_HostosInterface structure. This is *NOT*
+ * part of the debugger toolbox, but it is required by 2 back ends
+ * (armul & pisd) and two front ends (armsd & wdbg), so putting it
+ * in the toolbox is the only way of avoiding multiple copies.
+ */
+
+/*
+ * RCS $Revision$
+ * Checkin $Date$
+ */
+
+#ifndef dbg_hif__h
+#define dbg_hif__h
+
+#ifdef STDC_HEADERS
+# include <stdarg.h>
+#else
+# include <varargs.h>
+#endif
+
+typedef void Hif_DbgPrint(void *arg, const char *format, va_list ap);
+typedef void Hif_DbgPause(void *arg);
+
+typedef void Hif_WriteC(void *arg, int c);
+typedef int Hif_ReadC(void *arg);
+typedef int Hif_Write(void *arg, char const *buffer, int len);
+typedef char *Hif_GetS(void *arg, char *buffer, int len);
+
+typedef void Hif_RDIResetProc(void *arg);
+
+struct Dbg_HostosInterface {
+ Hif_DbgPrint *dbgprint;
+ Hif_DbgPause *dbgpause;
+ void *dbgarg;
+
+ Hif_WriteC *writec;
+ Hif_ReadC *readc;
+ Hif_Write *write;
+ Hif_GetS *gets;
+ void *hostosarg;
+
+ Hif_RDIResetProc *reset;
+ void *resetarg;
+};
+
+#endif
diff --git a/gdb/rdi-share/dbg_rdi.h b/gdb/rdi-share/dbg_rdi.h
new file mode 100644
index 00000000000..efda7bd8800
--- /dev/null
+++ b/gdb/rdi-share/dbg_rdi.h
@@ -0,0 +1,511 @@
+/*
+ * Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
+ *
+ * This software may be freely used, copied, modified, and distributed
+ * provided that the above copyright notice is preserved in all copies of the
+ * software.
+ */
+
+/*
+ * ARM debugger toolbox : dbg_rdi.h
+ */
+
+/*
+ * RCS $Revision$
+ * Checkin $Date$
+ */
+
+#ifndef dbg_rdi__h
+#define dbg_rdi__h
+
+/***************************************************************************\
+* Other RDI values *
+\***************************************************************************/
+
+#define RDISex_Little 0 /* the byte sex of the debuggee */
+#define RDISex_Big 1
+#define RDISex_DontCare 2
+
+#define RDIPoint_EQ 0 /* the different types of break/watchpoints */
+#define RDIPoint_GT 1
+#define RDIPoint_GE 2
+#define RDIPoint_LT 3
+#define RDIPoint_LE 4
+#define RDIPoint_IN 5
+#define RDIPoint_OUT 6
+#define RDIPoint_MASK 7
+
+#define RDIPoint_16Bit 16 /* 16-bit breakpoint */
+#define RDIPoint_Conditional 32
+
+/* ORRed with point type in extended RDP break and watch messages */
+#define RDIPoint_Inquiry 64
+#define RDIPoint_Handle 128 /* messages */
+
+#define RDIWatch_ByteRead 1 /* types of data accesses to watch for*/
+#define RDIWatch_HalfRead 2
+#define RDIWatch_WordRead 4
+#define RDIWatch_ByteWrite 8
+#define RDIWatch_HalfWrite 16
+#define RDIWatch_WordWrite 32
+
+#define RDIReg_R15 (1L << 15) /* mask values for CPU */
+#define RDIReg_PC (1L << 16)
+#define RDIReg_CPSR (1L << 17)
+#define RDIReg_SPSR (1L << 18)
+#define RDINumCPURegs 19
+
+#define RDINumCPRegs 10 /* current maximum */
+
+#define RDIMode_Curr 255
+
+/* RDI_Info subcodes */
+/* rdp in parameters are all preceded by */
+/* in byte = RDP_Info, word = info subcode */
+/* out parameters are all preceded by */
+/* out byte = RDP_Return */
+
+#define RDIInfo_Target 0
+/* rdi: out ARMword *targetflags, out ARMword *processor id */
+/* rdp: in none, out word targetflags, word processorid, byte status */
+/* the following bits are defined in targetflags */
+# define RDITarget_LogSpeed 0x0f
+# define RDITarget_HW 0x10 /* else emulator */
+# define RDITarget_AgentMaxLevel 0xe0
+# define RDITarget_AgentLevelShift 5
+# define RDITarget_DebuggerMinLevel 0x700
+# define RDITarget_DebuggerLevelShift 8
+# define RDITarget_CanReloadAgent 0x800
+# define RDITarget_CanInquireLoadSize 0x1000
+# define RDITarget_UnderstandsRDPInterrupt 0x2000
+# define RDITarget_CanProfile 0x4000
+# define RDITarget_Code16 0x8000
+# define RDITarget_HasCommsChannel 0x10000
+
+#define RDIInfo_Points 1
+/* rdi: out ARMword *pointcapabilities */
+/* rdp: in none, out word pointcapabilities, byte status */
+/* the following bits are defined in pointcapabilities */
+# define RDIPointCapability_Comparison 1
+# define RDIPointCapability_Range 2
+/* 4 to 128 are RDIWatch_xx{Read,Write} left-shifted by two */
+# define RDIPointCapability_Mask 0x100
+# define RDIPointCapability_ThreadBreak 0x200
+# define RDIPointCapability_ThreadWatch 0x400
+# define RDIPointCapability_CondBreak 0x800
+# define RDIPointCapability_Status 0x1000 /* status enquiries available */
+
+#define RDIInfo_Step 2
+/* rdi: out ARMword *stepcapabilities */
+/* rdp: in none, out word stepcapabilities, byte status */
+/* the following bits are defined in stepcapabilities */
+# define RDIStep_Multiple 1
+# define RDIStep_PCChange 2
+# define RDIStep_Single 4
+
+#define RDIInfo_MMU 3
+/* rdi: out ARMword *mmuidentity */
+/* rdp: in none, out word mmuidentity, byte status */
+
+#define RDIInfo_DownLoad 4
+/* Inquires whether configuration download and selection is available. */
+/* rdp: in none, out byte status */
+/* No argument, no return value. status == ok if available */
+
+#define RDIInfo_SemiHosting 5
+/* Inquires whether RDISemiHosting_* RDI_Info calls are available. */
+/* rdp: in none, out byte status */
+/* No argument, no return value. status == ok if available */
+
+#define RDIInfo_CoPro 6
+/* Inquires whether CoPro RDI_Info calls are available. */
+/* rdp: in none, out byte status */
+/* No argument, no return value. status == ok if available */
+
+#define RDIInfo_Icebreaker 7
+/* Inquires whether debuggee controlled by IceBreaker. */
+/* rdp: in none, out byte status */
+/* No argument, no return value. status == ok if available */
+
+#define RDIMemory_Access 8
+/* rdi: out RDI_MemAccessStats *p, in ARMword *handle */
+/* rdp: in word handle */
+/* out word nreads, word nwrites, word sreads, word swrites, */
+/* word ns, word s, byte status */
+
+/* Get memory access information for memory block with specified handle */
+
+#define RDIMemory_Map 9
+/* rdi: in RDI_MemDescr md[n], in ARMword *n */
+/* rdp: in word n, n * { */
+/* word handle, word start, word limit, */
+/* byte width, byte access */
+/* word Nread_ns, word Nwrite_ns, */
+/* word Sread_ns, word Swrite_ns} */
+/* out byte status */
+/* Sets memory characteristics. */
+
+#define RDISet_CPUSpeed 10
+/* rdi: in ARMword *speed */
+/* rdp: in word speed, out byte status */
+/* Sets CPU speed (in ns) */
+
+#define RDIRead_Clock 12
+/* rdi: out ARMword *ns, out ARMword *s */
+/* rdp: in none, out word ns, word s, byte status */
+/* Reads simulated time */
+
+#define RDIInfo_Memory_Stats 13
+/* Inquires whether RDI_Info codes 8-10 are available */
+/* rdp: in none, out byte status */
+/* No argument, no return value. status == ok if available */
+
+/* The next two are only to be used if RDIInfo_DownLoad returned no */
+/* error */
+#define RDIConfig_Count 14
+/* rdi: out ARMword *count */
+/* rdp: out byte status, word count (if status == OK) */
+
+/* In addition, the next one is only to be used if RDIConfig_Count */
+/* returned no error */
+typedef struct { unsigned32 version; char name[32]; } RDI_ConfigDesc;
+#define RDIConfig_Nth 15
+/* rdi: in ARMword *n, out RDI_ConfigDesc * */
+/* rdp: in word n */
+/* out word version, byte namelen, bytes * bytelen name, */
+/* byte status */
+
+/* Set a front-end polling function to be used from within driver poll */
+/* loops */
+typedef void RDI_PollProc(void *);
+typedef struct { RDI_PollProc *p; void *arg; } RDI_PollDesc;
+#define RDISet_PollProc 16
+/* rdi: in RDI_PollDesc const *from, RDI_PollDesc *to */
+/* if from non-NULL, sets the polling function from it */
+/* if to non-NULL, returns the previous polling function to it */
+/* No corresponding RDP operation */
+
+/* Called on debugger startup to see if the target is ready to execute */
+#define RDIInfo_CanTargetExecute 20
+/* rdi: in void
+ * out byte status (RDIError_NoError => Yes, Otherwise No)
+ */
+
+/* Called to set the top of target memory in an ICEman2 system
+ * This is then used by ICEman to tell the C Library via the INFOHEAP
+ * SWI where the stack should start.
+ * Note that only ICEman2 supports this call. Other systems eg.
+ * Demon, Angel, will simply return an error, which means that setting
+ * the top of memory in this fashion is not supported.
+ */
+#define RDIInfo_SetTopMem 21
+/* rdi: in word mem_top
+ * out byte status (RDIError_NoError => Done, Other => Not supported
+ */
+
+/* Called before performing a loadagent to determine the endianess of
+ * the debug agent, so that images of the wrong bytesex can be
+ * complained about
+ */
+#define RDIInfo_AgentEndianess 22
+/* rdi: in void
+ * out byte status
+ * status should be RDIError_LittleEndian or RDIError_BigEndian
+ * any other value indicates the target does not support this
+ * request, so the debugger will have to make a best guess, which
+ * probably means only allow little endian loadagenting.
+ */
+
+/* The next two are only to be used if the value returned by */
+/* RDIInfo_Points has RDIPointCapability_Status set. */
+#define RDIPointStatus_Watch 0x80
+#define RDIPointStatus_Break 0x81
+/* rdi: inout ARMword * (in handle, out hwresource), out ARMword *type */
+/* rdp: in word handle, out word hwresource, word type, byte status */
+
+#define RDISignal_Stop 0x100
+/* Requests that the debuggee stop */
+/* No arguments, no return value */
+/* rdp: no reply (when the debuggee stops, there will be a reply to the */
+/* step or execute request which started it) */
+
+#define RDIVector_Catch 0x180
+/* rdi: in ARMword *bitmap */
+/* rdp: int word bitmap, out byte status */
+/* bit i in bitmap set to cause vector i to cause entry to debugger */
+
+/* The next four are only to be used if RDIInfo_Semihosting returned */
+/* no error */
+#define RDISemiHosting_SetState 0x181
+/* rdi: in ARMword *semihostingstate */
+/* rdp: in word semihostingstate, out byte status */
+#define RDISemiHosting_GetState 0x182
+/* rdi: out ARMword *semihostingstate */
+/* rdp: in none, out word semihostingstate, byte status */
+#define RDISemiHosting_SetVector 0x183
+/* rdi: in ARMword *semihostingvector */
+/* rdp: in word semihostingvector, out byte status */
+#define RDISemiHosting_GetVector 0x184
+/* rdi: out ARMword *semihostingvector */
+/* rdp: in none, out word semihostingvector, byte status */
+
+/* The next two are only to be used if RDIInfo_Icebreaker returned */
+/* no error */
+#define RDIIcebreaker_GetLocks 0x185
+/* rdi: out ARMword *lockedstate */
+/* rdp: in none, out word lockedstate, byte status */
+
+#define RDIIcebreaker_SetLocks 0x186
+/* rdi: in ARMword *lockedstate */
+/* rdp: in word lockedstate, out byte status */
+
+/* lockedstate is a bitmap of the icebreaker registers locked against */
+/* use by IceMan (because explicitly written by the user) */
+
+#define RDIInfo_GetLoadSize 0x187
+/* rdi: out ARMword *maxloadsize */
+/* rdp: in none, out word maxloadsize, byte status */
+/* Inquires the maximum length of data transfer the agent is prepared */
+/* to receive */
+/* Only usable if RDIInfo_Target returned RDITarget_CanInquireLoadSize */
+/* rdi: out ARMword *size */
+
+/* Only to be used if the value returned by RDIInfo_Target had */
+/* RDITarget_HasCommsChannel set */
+typedef void RDICCProc_ToHost(void *arg, ARMword data);
+typedef void RDICCProc_FromHost(void *arg, ARMword *data, int *valid);
+
+#define RDICommsChannel_ToHost 0x188
+/* rdi: in RDICCProc_ToHost *, in void *arg */
+/* rdp: in byte connect, out byte status */
+#define RDICommsChannel_FromHost 0x189
+/* rdi: in RDICCProc_FromHost *, in void *arg */
+/* rdp: in byte connect, out byte status */
+
+/* These 4 are only to be used if RDIInfo_Semihosting returns no error */
+#define RDISemiHosting_SetARMSWI 0x190
+/* rdi: in ARMword ARM_SWI_number */
+/* rdp: in ARMword ARM_SWI_number, out byte status */
+
+#define RDISemiHosting_GetARMSWI 0x191
+/* rdi: out ARMword ARM_SWI_number */
+/* rdp: out ARMword ARM_SWI_number, byte status */
+
+#define RDISemiHosting_SetThumbSWI 0x192
+/* rdi: in ARMword Thumb_SWI_number */
+/* rdp: in ARMword Thumb_SWI_number, out byte status */
+
+#define RDISemiHosting_GetThumbSWI 0x193
+/* rdi: out ARMword ARM_Thumb_number */
+/* rdp: out ARMword ARM_Thumb_number, byte status */
+
+
+#define RDICycles 0x200
+/* rdi: out ARMword cycles[12] */
+/* rdp: in none, out 6 words cycles, byte status */
+/* the rdi result represents 6 big-endian doublewords; the rdp results */
+/* return values for the ls halves of these */
+# define RDICycles_Size 48
+
+#define RDIErrorP 0x201
+/* rdi: out ARMaddress *errorp */
+/* rdp: in none, out word errorp, byte status */
+/* Returns the error pointer associated with the last return from step */
+/* or execute with status RDIError_Error. */
+
+#define RDISet_Cmdline 0x300
+/* rdi: in char *commandline (a null-terminated string) */
+/* No corresponding RDP operation (cmdline is sent to the agent in */
+/* response to SWI_GetEnv) */
+
+#define RDISet_RDILevel 0x301
+/* rdi: in ARMword *level */
+/* rdp: in word level, out byte status */
+/* Sets the RDI/RDP protocol level to be used (must lie between the */
+/* limits returned by RDIInfo_Target). */
+
+#define RDISet_Thread 0x302
+/* rdi: in ARMword *threadhandle */
+/* rdp: in word threadhandle, out byte status */
+/* Sets the thread context for subsequent thread-sensitive operations */
+/* (null value sets no thread) */
+
+/* The next two are only to be used if RDI_read or RDI_write returned */
+/* RDIError_LittleEndian or RDIError_BigEndian, to signify that the */
+/* debugger has noticed. */
+#define RDIInfo_AckByteSex 0x303
+/* rdi: in ARMword *sex (RDISex_Little or RDISex_Big) */
+
+/* The next two are only to be used if RDIInfo_CoPro returned no error */
+#define RDIInfo_DescribeCoPro 0x400
+/* rdi: in int *cpno, Dbg_CoProDesc *cpd */
+/* rdp: in byte cpno, */
+/* cpd->entries * { */
+/* byte rmin, byte rmax, byte nbytes, byte access, */
+/* byte cprt_r_b0, cprt_r_b1, cprt_w_b0, cprt_w_b1} */
+/* byte = 255 */
+/* out byte status */
+
+#define RDIInfo_RequestCoProDesc 0x401
+/* rdi: in int *cpno, out Dbg_CoProDesc *cpd */
+/* rpd: in byte cpno */
+/* out nentries * { */
+/* byte rmin, byte rmax, byte nbytes, byte access, */
+/* } */
+/* byte = 255, byte status */
+
+#define RDIInfo_Log 0x800
+/* rdi: out ARMword *logsetting */
+/* No corresponding RDP operation */
+#define RDIInfo_SetLog 0x801
+/* rdi: in ARMword *logsetting */
+/* No corresponding RDP operation */
+
+#define RDIProfile_Stop 0x500
+/* No arguments, no return value */
+/* rdp: in none, out byte status */
+/* Requests that pc sampling stop */
+
+#define RDIProfile_Start 0x501
+/* rdi: in ARMword *interval */
+/* rdp: in word interval, out byte status */
+/* Requests that pc sampling start, with period <interval> usec */
+
+#define RDIProfile_WriteMap 0x502
+/* rdi: in ARMword map[] */
+/* map[0] is the length of the array, subsequent elements are sorted */
+/* and are the base of ranges for pc sampling (so if the sampled pc */
+/* lies between map[i] and map[i+1], count[i] is incremented). */
+/* rdp: a number of messages, each of form: */
+/* in word len, word size, word offset, <size> words map data */
+/* out status */
+/* len, size and offset are all word counts. */
+
+#define RDIProfile_ReadMap 0x503
+/* rdi: in ARMword *len, out ARMword counts[len] */
+/* Requests that the counts array be set to the accumulated pc sample */
+/* counts */
+/* rdp: a number of messages, each of form: */
+/* in word offset, word size */
+/* out <size> words, status */
+/* len, size and offset are all word counts. */
+
+#define RDIProfile_ClearCounts 0x504
+/* No arguments, no return value */
+/* rdp: in none, out byte status */
+/* Requests that pc sample counts be set to zero */
+
+#define RDIInfo_RequestReset 0x900
+/* Request reset of the target environment */
+/* No arguments, no return value */
+/* No RDP equivalent, sends an RDP reset */
+
+#define RDIInfo_CapabilityRequest 0x8000
+/* Request whether the interface supports the named capability. The */
+/* capability is specified by or'ing the RDIInfo number with this, and */
+/* sending that request */
+/* rdi: in none */
+/* rdp: in none, out byte status */
+
+typedef struct {
+ ARMword len;
+ ARMword map[1];
+} RDI_ProfileMap;
+
+typedef unsigned32 PointHandle;
+typedef unsigned32 ThreadHandle;
+#define RDINoPointHandle ((PointHandle)-1L)
+#define RDINoHandle ((ThreadHandle)-1L)
+
+struct Dbg_ConfigBlock;
+struct Dbg_HostosInterface;
+struct Dbg_MCState;
+typedef int rdi_open_proc(unsigned type, struct Dbg_ConfigBlock const *config,
+ struct Dbg_HostosInterface const *i,
+ struct Dbg_MCState *dbg_state);
+typedef int rdi_close_proc(void);
+typedef int rdi_read_proc(ARMword source, void *dest, unsigned *nbytes);
+typedef int rdi_write_proc(const void *source, ARMword dest, unsigned *nbytes);
+typedef int rdi_CPUread_proc(unsigned mode, unsigned32 mask, ARMword *state);
+typedef int rdi_CPUwrite_proc(unsigned mode, unsigned32 mask, ARMword const *state);
+typedef int rdi_CPread_proc(unsigned CPnum, unsigned32 mask, ARMword *state);
+typedef int rdi_CPwrite_proc(unsigned CPnum, unsigned32 mask, ARMword const *state);
+typedef int rdi_setbreak_proc(ARMword address, unsigned type, ARMword bound,
+ PointHandle *handle);
+typedef int rdi_clearbreak_proc(PointHandle handle);
+typedef int rdi_setwatch_proc(ARMword address, unsigned type, unsigned datatype,
+ ARMword bound, PointHandle *handle);
+typedef int rdi_clearwatch_proc(PointHandle handle);
+typedef int rdi_execute_proc(PointHandle *handle);
+typedef int rdi_step_proc(unsigned ninstr, PointHandle *handle);
+typedef int rdi_info_proc(unsigned type, ARMword *arg1, ARMword *arg2);
+typedef int rdi_pointinq_proc(ARMword *address, unsigned type,
+ unsigned datatype, ARMword *bound);
+
+typedef enum {
+ RDI_ConfigCPU,
+ RDI_ConfigSystem
+} RDI_ConfigAspect;
+
+typedef enum {
+ RDI_MatchAny,
+ RDI_MatchExactly,
+ RDI_MatchNoEarlier
+} RDI_ConfigMatchType;
+
+typedef int rdi_addconfig_proc(unsigned32 nbytes);
+typedef int rdi_loadconfigdata_proc(unsigned32 nbytes, char const *data);
+typedef int rdi_selectconfig_proc(RDI_ConfigAspect aspect, char const *name,
+ RDI_ConfigMatchType matchtype, unsigned versionreq,
+ unsigned *versionp);
+
+typedef char *getbufferproc(void *getbarg, unsigned32 *sizep);
+typedef int rdi_loadagentproc(ARMword dest, unsigned32 size, getbufferproc *getb, void *getbarg);
+typedef int rdi_targetisdead(void);
+
+typedef struct {
+ int itemmax;
+ char const * const *names;
+} RDI_NameList;
+
+typedef RDI_NameList const *rdi_namelistproc(void);
+
+typedef int rdi_errmessproc(char *buf, int buflen, int errnum);
+
+struct RDIProcVec {
+ char rditypename[12];
+
+ rdi_open_proc *open;
+ rdi_close_proc *close;
+ rdi_read_proc *read;
+ rdi_write_proc *write;
+ rdi_CPUread_proc *CPUread;
+ rdi_CPUwrite_proc *CPUwrite;
+ rdi_CPread_proc *CPread;
+ rdi_CPwrite_proc *CPwrite;
+ rdi_setbreak_proc *setbreak;
+ rdi_clearbreak_proc *clearbreak;
+ rdi_setwatch_proc *setwatch;
+ rdi_clearwatch_proc *clearwatch;
+ rdi_execute_proc *execute;
+ rdi_step_proc *step;
+ rdi_info_proc *info;
+ /* V2 RDI */
+ rdi_pointinq_proc *pointinquiry;
+
+ /* These three useable only if RDIInfo_DownLoad returns no error */
+ rdi_addconfig_proc *addconfig;
+ rdi_loadconfigdata_proc *loadconfigdata;
+ rdi_selectconfig_proc *selectconfig;
+
+ rdi_namelistproc *drivernames;
+ rdi_namelistproc *cpunames;
+
+ rdi_errmessproc *errmess;
+
+ /* Only if RDIInfo_Target returns a value with RDITarget_LoadAgent set */
+ rdi_loadagentproc *loadagent;
+ rdi_targetisdead *targetisdead;
+};
+
+#endif
diff --git a/gdb/rdi-share/devclnt.h b/gdb/rdi-share/devclnt.h
new file mode 100644
index 00000000000..cb920f66baf
--- /dev/null
+++ b/gdb/rdi-share/devclnt.h
@@ -0,0 +1,260 @@
+/*
+ * Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
+ *
+ * This software may be freely used, copied, modified, and distributed
+ * provided that the above copyright notice is preserved in all copies of the
+ * software.
+ */
+
+/* -*-C-*-
+ *
+ * $Revision$
+ * $Date$
+ *
+ *
+ * Project: ANGEL
+ *
+ * Title: Public client interface to devices
+ */
+
+#ifndef angel_devclnt_h
+#define angel_devclnt_h
+
+/*
+ * This header exports the public interface to Angel-compliant device
+ * drivers.
+ *
+ * They are intended to be used solely by Angel, not by the User
+ * Application. See devappl.h for the User Application interface to
+ * the device drivers.
+ */
+
+#include "devices.h"
+
+/* General purpose constants, macros, enums, typedefs */
+
+/*
+ * possible channels at device level
+ *
+ * XXX
+ *
+ * these are used as array indices, so be specific about their values
+ */
+typedef enum DevChanID {
+ DC_DBUG = 0, /* reliable debug packets
+ * containing SDBG, CLIB,UDBG, etc.) */
+ DC_APPL = 1, /* application packets */
+ DC_NUM_CHANNELS
+} DevChanID;
+
+/* Publically-accessible globals */
+/* none */
+
+/* Public functions */
+
+/*
+ * Function: angel_DeviceWrite
+ * Purpose: The main entry point for asynchronous writes to a device.
+ *
+ * Params:
+ * Input: devID index of the device to write to
+ * buff data to write
+ * length how much data to write
+ * callback callback here when write finished
+ * or error
+ * cb_data data to be passed to callback
+ * chanID device channel to use
+ * Output: -
+ * In/Out: -
+ *
+ * Returns: DE_OKAY write request is underway
+ * DE_NO_DEV no such device
+ * DE_BAD_DEV device does not support angel writes
+ * DE_BAD_CHAN no such device channel
+ * DE_BUSY device busy with another write
+ * DE_INVAL silly length
+ *
+ * Reads globals: -
+ * Modifies globals: -
+ *
+ * Other side effects: -
+ *
+ * Commence asynchronous transmission of a buffer on a device. The
+ * callback will occur when the write completes or if there is an
+ * error.
+ *
+ * This must be called for each packet to be sent.
+ */
+
+DevError angel_DeviceWrite(DeviceID devID, p_Buffer buff,
+ unsigned length, DevWrite_CB_Fn callback,
+ void *cb_data, DevChanID chanID);
+
+
+/*
+ * Function: angel_DeviceRegisterRead
+ * Purpose: The main entry point for asynchronous reads from a device.
+ *
+ * Params:
+ * Input: devID index of the device to read from
+ * callback callback here when read finished
+ * or error
+ * cb_data data to be passed to callback
+ * get_buff callback to be used to acquire buffer
+ * for incoming packets
+ * getb_data data to be passed to get_buff
+ * chanID device channel to use
+ * Output: -
+ * In/Out: -
+ *
+ * Returns: DE_OKAY read request is underway
+ * DE_NO_DEV no such device
+ * DE_BAD_DEV device does not support angel reads
+ * DE_BAD_CHAN no such device channel
+ * DE_BUSY device busy with another read
+ * DE_INVAL silly length
+ *
+ * Reads globals: -
+ * Modifies globals: -
+ *
+ * Other side effects: -
+ *
+ * Register asynchronous packet read from a device. The callback will
+ * occur when the read completes or if there is an error.
+ *
+ * This is persistent: the read remains registered for all incoming
+ * packets on the device channel.
+ */
+
+DevError angel_DeviceRegisterRead(DeviceID devID,
+ DevRead_CB_Fn callback, void *cb_data,
+ DevGetBuff_Fn get_buff, void *getb_data,
+ DevChanID chanID);
+
+
+/*
+ * Function: angel_DeviceControl
+ * Purpose: Call a control function for a device
+ *
+ * Params:
+ * Input: devID index of the device to control to
+ * op operation to perform
+ * arg parameter depending on op
+ *
+ * Returns: DE_OKAY control request is underway
+ * DE_NO_DEV no such device
+ * DE_BAD_OP device does not support operation
+ *
+ * Reads globals: -
+ * Modifies globals: -
+ *
+ * Other side effects: -
+ *
+ * Have a device perform a control operation. Extra parameters vary
+ * according to the operation requested.
+ */
+
+DevError angel_DeviceControl(DeviceID devID, DeviceControl op, void *arg);
+
+
+/*
+ * Function: angel_ReceiveMode
+ * Purpose: enable or disable reception across all devices
+ *
+ * Params:
+ * Input: mode choose enable or disable
+ *
+ * Pass the mode parameter to the receive_mode control method of each device
+ */
+
+void angel_ReceiveMode(DevRecvMode mode);
+
+
+/*
+ * Function: angel_ResetDevices
+ * Purpose: reset all devices
+ *
+ * Params: none
+ *
+ * Call the reset control method for each device
+ */
+
+void angel_ResetDevices(void);
+
+
+/*
+ * Function: angel_InitialiseDevices
+ * Purpose: initialise the device driver layer
+ *
+ * Params: none
+ *
+ * Set up the device driver layer and call the init method for each device
+ */
+
+void angel_InitialiseDevices(void);
+
+
+/*
+ * Function: angel_IsAngelDevice
+ * Purpose: Find out if a device supports Angel packets
+ *
+ * Params:
+ * Input: devID index of the device to control to
+ *
+ * Returns: TRUE supports Angel packets
+ * FALSE raw device
+ *
+ * Reads globals: -
+ * Modifies globals: -
+ *
+ * Other side effects: -
+ */
+
+bool angel_IsAngelDevice(DeviceID devID);
+
+
+#if !defined(MINIMAL_ANGEL) || MINIMAL_ANGEL == 0
+
+/*
+ * Function: angel_ApplDeviceHandler
+ * Purpose: The entry point for User Application Device Driver requests
+ * in a full functiionality version of Angel.
+ * It will never be called directly by the User Application,
+ * but gets called indirectly, via the SWI handler.
+ *
+ * Params:
+ * Input: swi_r0 Argument to SWI indicating that
+ * angel_ApplDeviceHandler was to be called. This
+ * will not be used in this function, but is needed
+ * by the SWI handler.
+ * arg_blk pointer to block of arguments
+ * arg_blk[0] is one of
+ * angel_SWIreason_ApplDevice_{Read,Write,Yield}
+ * which indicates which angel_Device* fn is to
+ * be called. arg_blk[1] - arg_blk[n] are the
+ * arguments to the corresponding
+ * angel_ApplDevice* function.
+ * Output: -
+ * In/Out: -
+ *
+ * Returns: whatever the specified angel_Device* function
+ * returns.
+ *
+ * Reads globals: -
+ * Modifies globals: -
+ *
+ * Other side effects: -
+ *
+ * This has the side effects of angel_Device{Read,Write,Yield}
+ * depending upon which is operation is specified as described above.
+ */
+
+DevError angel_ApplDeviceHandler(
+ unsigned swi_r0, unsigned *arg_blk
+);
+
+#endif /* ndef MINIMAL_ANGEL */
+
+#endif /* ndef angel_devclnt_h */
+
+/* EOF devclnt.h */
diff --git a/gdb/rdi-share/devices.h b/gdb/rdi-share/devices.h
new file mode 100644
index 00000000000..eac6ee20fd7
--- /dev/null
+++ b/gdb/rdi-share/devices.h
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
+ *
+ * This software may be freely used, copied, modified, and distributed
+ * provided that the above copyright notice is preserved in all copies of the
+ * software.
+ */
+
+/* -*-C-*-
+ *
+ * $Revision$
+ * $Date$
+ *
+ *
+ * Project: ANGEL
+ *
+ * Title: Devices header file
+ */
+
+#ifndef angel_devices_h
+#define angel_devices_h
+
+/*
+ * Provides common types for using devices, and provides access to the
+ * device table.
+ */
+
+#include "angel.h"
+#include "buffers.h"
+
+/* General purpose constants, macros, enums, typedefs */
+
+/* a non-enum holder for device IDs */
+typedef unsigned int DeviceID;
+
+/* device error codes */
+typedef enum DevError {
+ DE_OKAY, /* no error */
+ DE_NO_DEV, /* no such device */
+ DE_BAD_DEV, /* device does not support angel */
+ DE_BAD_CHAN, /* no such device channel */
+ DE_BAD_OP, /* operation not supported by this device */
+ DE_BUSY, /* device already busy */
+ DE_INVAL, /* length invalid */
+ DE_FAILED /* something else went wrong */
+} DevError;
+
+/* return codes from asynchronous calls - primarily for channels' benefit */
+typedef enum DevStatus {
+ DS_DONE, /* operation succeeded */
+ DS_OVERFLOW, /* not enough buffer space */
+ DS_BAD_PACKET, /* packet failed */
+ DS_DEV_ERROR, /* device error */
+ DS_INT_ERROR /* internal error */
+} DevStatus;
+
+/* Callback for async. writes */
+typedef void (*DevWrite_CB_Fn)(
+ void *buff, /* pointer to data -- cast to p_Buffer */
+ void *length, /* how much done -- cast to unsigned */
+ void *status, /* success code -- cast to DevStatus */
+ void *cb_data /* as supplied */
+ );
+
+/* Callback for async. reads */
+typedef void (*DevRead_CB_Fn)(
+ void *buff, /* pointer to data -- cast to p_Buffer */
+ void *length, /* how much read -- cast to unsigned */
+ void *status, /* success code -- cast to DevStatus */
+ void *cb_data /* as supplied */
+ );
+
+/* control operations */
+typedef enum DeviceControl {
+ DC_INIT, /* initialise device */
+ DC_RESET, /* reset device */
+ DC_RECEIVE_MODE, /* control reception */
+ DC_SET_PARAMS, /* set parameters of device */
+#ifndef TARGET
+ DC_GET_USER_PARAMS, /* params set by user at open */
+ DC_GET_DEFAULT_PARAMS, /* device default parameters */
+ DC_RESYNC, /* resynchronise with new agent */
+#endif
+ DC_PRIVATE /* start of private device codes */
+} DeviceControl;
+
+typedef enum DevRecvMode {
+ DR_DISABLE,
+ DR_ENABLE
+} DevRecvMode;
+
+/*
+ * callback to allow a device driver to request a buffer, to be filled
+ * with an incoming packet
+ */
+typedef p_Buffer (*DevGetBuff_Fn)(unsigned req_size, void *cb_data);
+
+
+/* Publically-accessible globals */
+/* none */
+
+#endif /* ndef angel_devices_h */
+
+/* EOF devices.h */
diff --git a/gdb/rdi-share/devsw.c b/gdb/rdi-share/devsw.c
new file mode 100644
index 00000000000..7fa142b4722
--- /dev/null
+++ b/gdb/rdi-share/devsw.c
@@ -0,0 +1,404 @@
+/*
+ * Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
+ *
+ * This software may be freely used, copied, modified, and distributed
+ * provided that the above copyright notice is preserved in all copies of the
+ * software.
+ */
+
+/* -*-C-*-
+ *
+ * $Revision$
+ * $Date$
+ *
+ */
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "adp.h"
+#include "hsys.h"
+#include "rxtx.h"
+#include "drivers.h"
+#include "buffers.h"
+#include "devclnt.h"
+#include "adperr.h"
+#include "devsw.h"
+#include "hostchan.h"
+#include "logging.h"
+
+/*
+ * TODO: this should be adjustable - it could be done by defining
+ * a reason code for DevSW_Ioctl. It could even be a
+ * per-devicechannel parameter.
+ */
+static const unsigned int allocsize = ADP_BUFFER_MIN_SIZE;
+
+#define illegalDevChanID(type) ((type) >= DC_NUM_CHANNELS)
+
+/**********************************************************************/
+
+/*
+ * Function: initialise_read
+ * Purpose: Set up a read request for another packet
+ *
+ * Params:
+ * In/Out: ds State structure to be initialised
+ *
+ * Returns:
+ * OK: 0
+ * Error: -1
+ */
+static int initialise_read(DevSWState *ds)
+{
+ struct data_packet *dp;
+
+ /*
+ * try to claim the structure that will
+ * eventually hold the new packet.
+ */
+ if ((ds->ds_nextreadpacket = DevSW_AllocatePacket(allocsize)) == NULL)
+ return -1;
+
+ /*
+ * Calls into the device driver use the DriverCall structure: use
+ * the buffer we have just allocated, and declare its size. We
+ * are also obliged to clear the driver's context pointer.
+ */
+ dp = &ds->ds_activeread.dc_packet;
+ dp->buf_len = allocsize;
+ dp->data = ds->ds_nextreadpacket->pk_buffer;
+
+ ds->ds_activeread.dc_context = NULL;
+
+ return 0;
+}
+
+/*
+ * Function: initialise_write
+ * Purpose: Set up a write request for another packet
+ *
+ * Params:
+ * Input: packet The packet to be written
+ *
+ * type The type of the packet
+ *
+ * In/Out: dc The structure to be intialised
+ *
+ * Returns: Nothing
+ */
+static void initialise_write(DriverCall *dc, Packet *packet, DevChanID type)
+{
+ struct data_packet *dp = &dc->dc_packet;
+
+ dp->len = packet->pk_length;
+ dp->data = packet->pk_buffer;
+ dp->type = type;
+
+ /*
+ * we are required to clear the state structure for the driver
+ */
+ dc->dc_context = NULL;
+}
+
+/*
+ * Function: enqueue_packet
+ * Purpose: move a newly read packet onto the appropriate queue
+ * of read packets
+ *
+ * Params:
+ * In/Out: ds State structure with new packet
+ *
+ * Returns: Nothing
+ */
+static void enqueue_packet(DevSWState *ds)
+{
+ struct data_packet *dp = &ds->ds_activeread.dc_packet;
+ Packet *packet = ds->ds_nextreadpacket;
+
+ /*
+ * transfer the length
+ */
+ packet->pk_length = dp->len;
+
+ /*
+ * take this packet out of the incoming slot
+ */
+ ds->ds_nextreadpacket = NULL;
+
+ /*
+ * try to put it on the correct input queue
+ */
+ if (illegalDevChanID(dp->type))
+ {
+ /* this shouldn't happen */
+ WARN("Illegal type for Rx packet");
+ DevSW_FreePacket(packet);
+ }
+ else
+ Adp_addToQueue(&ds->ds_readqueue[dp->type], packet);
+}
+
+/*
+ * Function: flush_packet
+ * Purpose: Send a packet to the device driver
+ *
+ * Params:
+ * Input: device The device to be written to
+ *
+ * In/Out: dc Describes the packet to be sent
+ *
+ * Returns: Nothing
+ *
+ * Post-conditions: If the whole packet was accepted by the device
+ * driver, then dc->dc_packet.data will be
+ * set to NULL.
+ */
+static void flush_packet(const DeviceDescr *device, DriverCall *dc)
+{
+ if (device->DeviceWrite(dc) > 0)
+ /*
+ * the whole packet was swallowed
+ */
+ dc->dc_packet.data = NULL;
+}
+
+/**********************************************************************/
+
+/*
+ * These are the externally visible functions. They are documented in
+ * devsw.h
+ */
+Packet *DevSW_AllocatePacket(const unsigned int length)
+{
+ Packet *pk;
+
+ if ((pk = malloc(sizeof(*pk))) == NULL)
+ {
+ WARN("malloc failure");
+ return NULL;
+ }
+
+ if ((pk->pk_buffer = malloc(length+CHAN_HEADER_SIZE)) == NULL)
+ {
+ WARN("malloc failure");
+ free(pk);
+ return NULL;
+ }
+
+ return pk;
+}
+
+void DevSW_FreePacket(Packet *pk)
+{
+ free(pk->pk_buffer);
+ free(pk);
+}
+
+AdpErrs DevSW_Open(DeviceDescr *device, const char *name, const char *arg,
+ const DevChanID type)
+{
+ DevSWState *ds;
+
+ /*
+ * is this the very first open call for this driver?
+ */
+ if ((ds = (DevSWState *)(device->SwitcherState)) == NULL)
+ {
+ /*
+ * yes, it is: initialise state
+ */
+ if ((ds = malloc(sizeof(*ds))) == NULL)
+ /* give up */
+ return adp_malloc_failure;
+
+ (void)memset(ds, 0, sizeof(*ds));
+ device->SwitcherState = (void *)ds;
+ }
+
+ /*
+ * check that we haven't already been opened for this type
+ */
+ if ((ds->ds_opendevchans & (1 << type)) != 0)
+ return adp_device_already_open;
+
+ /*
+ * if no opens have been done for this device, then do it now
+ */
+ if (ds->ds_opendevchans == 0)
+ if (device->DeviceOpen(name, arg) < 0)
+ return adp_device_open_failed;
+
+ /*
+ * open has finished
+ */
+ ds->ds_opendevchans |= (1 << type);
+ return adp_ok;
+}
+
+AdpErrs DevSW_Match(const DeviceDescr *device, const char *name,
+ const char *arg)
+{
+ return (device->DeviceMatch(name, arg) == -1) ? adp_failed : adp_ok;
+}
+
+AdpErrs DevSW_Close(const DeviceDescr *device, const DevChanID type)
+{
+ DevSWState *ds = (DevSWState *)(device->SwitcherState);
+ Packet *pk;
+
+ if ((ds->ds_opendevchans & (1 << type)) == 0)
+ return adp_device_not_open;
+
+ ds->ds_opendevchans &= ~(1 << type);
+
+ /*
+ * if this is the last close for this channel, then inform the driver
+ */
+ if (ds->ds_opendevchans == 0)
+ device->DeviceClose();
+
+ /*
+ * release all packets of the appropriate type
+ */
+ for (pk = Adp_removeFromQueue(&(ds->ds_readqueue[type]));
+ pk != NULL;
+ pk = Adp_removeFromQueue(&(ds->ds_readqueue[type])))
+ DevSW_FreePacket(pk);
+
+ /* Free memory */
+ free ((char *) device->SwitcherState);
+ device->SwitcherState = 0x0;
+
+ /* that's all */
+ return adp_ok;
+}
+
+AdpErrs DevSW_Read(const DeviceDescr *device, const DevChanID type,
+ Packet **packet, bool block)
+{
+ int read_err;
+ DevSWState *ds = device->SwitcherState;
+
+ /*
+ * To try to get information out of the device driver as
+ * quickly as possible, we try and read more packets, even
+ * if a completed packet is already available.
+ */
+
+ /*
+ * have we got a packet currently pending?
+ */
+ if (ds->ds_nextreadpacket == NULL)
+ /*
+ * no - set things up
+ */
+ if (initialise_read(ds) < 0) {
+ /*
+ * we failed to initialise the next packet, but can
+ * still return a packet that has already arrived.
+ */
+ *packet = Adp_removeFromQueue(&ds->ds_readqueue[type]);
+ return adp_ok;
+ }
+ read_err = device->DeviceRead(&ds->ds_activeread, block);
+ switch (read_err) {
+ case 1:
+ /*
+ * driver has pulled in a complete packet, queue it up
+ */
+#ifdef RET_DEBUG
+ printf("got a complete packet\n");
+#endif
+ enqueue_packet(ds);
+ *packet = Adp_removeFromQueue(&ds->ds_readqueue[type]);
+ return adp_ok;
+ case 0:
+ /*
+ * OK, return the head of the read queue for the given type
+ */
+ /* enqueue_packet(ds); */
+ *packet = Adp_removeFromQueue(&ds->ds_readqueue[type]);
+ return adp_ok;
+ case -1:
+#ifdef RET_DEBUG
+ printf("got a bad packet\n");
+#endif
+ /* bad packet */
+ *packet = NULL;
+ return adp_bad_packet;
+ default:
+ panic("DevSW_Read: bad read status %d", read_err);
+ }
+ return 0; /* get rid of a potential compiler warning */
+}
+
+
+AdpErrs DevSW_FlushPendingWrite(const DeviceDescr *device)
+{
+ struct DriverCall *dc;
+ struct data_packet *dp;
+
+ dc = &((DevSWState *)(device->SwitcherState))->ds_activewrite;
+ dp = &dc->dc_packet;
+
+ /*
+ * try to flush any packet that is still being written
+ */
+ if (dp->data != NULL)
+ {
+ flush_packet(device, dc);
+
+ /* see if it has gone */
+ if (dp->data != NULL)
+ return adp_write_busy;
+ else
+ return adp_ok;
+ }
+ else
+ return adp_ok;
+}
+
+
+AdpErrs DevSW_Write(const DeviceDescr *device, Packet *packet, DevChanID type)
+{
+ struct DriverCall *dc;
+ struct data_packet *dp;
+
+ dc = &((DevSWState *)(device->SwitcherState))->ds_activewrite;
+ dp = &dc->dc_packet;
+
+ if (illegalDevChanID(type))
+ return adp_illegal_args;
+
+ /*
+ * try to flush any packet that is still being written
+ */
+ if (DevSW_FlushPendingWrite(device) != adp_ok)
+ return adp_write_busy;
+
+ /*
+ * we can take this packet - set things up, then try to get rid of it
+ */
+ initialise_write(dc, packet, type);
+ flush_packet(device, dc);
+
+ return adp_ok;
+}
+
+AdpErrs DevSW_Ioctl(const DeviceDescr *device, const int opcode, void *args)
+{
+ return (device->DeviceIoctl(opcode, args) < 0) ? adp_failed : adp_ok;
+}
+
+bool DevSW_WriteFinished(const DeviceDescr *device)
+{
+ struct DriverCall *dc;
+ struct data_packet *dp;
+
+ dc = &((DevSWState *)(device->SwitcherState))->ds_activewrite;
+ dp = &dc->dc_packet;
+
+ return (dp == NULL || dp->data == NULL);
+}
+
+/* EOF devsw.c */
diff --git a/gdb/rdi-share/devsw.h b/gdb/rdi-share/devsw.h
new file mode 100644
index 00000000000..f561768fd9d
--- /dev/null
+++ b/gdb/rdi-share/devsw.h
@@ -0,0 +1,268 @@
+/*
+ * Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
+ *
+ * This software may be freely used, copied, modified, and distributed
+ * provided that the above copyright notice is preserved in all copies of the
+ * software.
+ */
+
+/* -*-C-*-
+ *
+ * $Revision$
+ * $Date$
+ *
+ */
+#ifndef angsd_devsw_h
+#define angsd_devsw_h
+
+#include "devclnt.h"
+#include "adperr.h"
+#include "drivers.h"
+
+#ifndef __cplusplus
+typedef struct Packet Packet;
+typedef struct DevSWState DevSWState;
+#endif
+
+/*
+ * the basic structure used for passing packets around
+ */
+struct Packet
+{
+ struct Packet *pk_next; /* XXX first field in struct */
+ unsigned int pk_length;
+ unsigned char *pk_buffer;
+};
+
+/*
+ * control structure, used for maintaining device switcher state
+ */
+struct DevSWState
+{
+ unsigned int ds_opendevchans; /* bitmap of open device channels */
+
+ /*
+ * queue of packets read for the various device channels
+ */
+ Packet *ds_readqueue[DC_NUM_CHANNELS];
+
+ /*
+ * structures for managing active read and write operations
+ */
+ Packet *ds_nextreadpacket;
+ DriverCall ds_activeread;
+ DriverCall ds_activewrite;
+};
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/*
+ * Function: DevSW_AllocatePacket
+ * Purpose: Claim some memory to hold a struct Packet, and the buffer for
+ * that packet.
+ *
+ * Params:
+ * Input: length Size of the buffer in struct Packet.
+ *
+ * Returns:
+ * OK: Pointer to the newly malloc()ed Packet.
+ * Error: NULL
+ */
+Packet *DevSW_AllocatePacket(const unsigned int length);
+
+/*
+ * Function: DevSW_FreePacket
+ * Purpose: Free the memory associated with a struct Packet.
+ *
+ * Pre-conditions The structure must have been originally claimed
+ * via DevSW_AllocatePacket.
+ *
+ * Params:
+ * Input: pk The packet to be freed.
+ *
+ * Returns: Nothing
+ */
+void DevSW_FreePacket(Packet *pk);
+
+/*
+ * Function: DevSW_Open
+ * Purpose: Open the specified device driver
+ *
+ * Params:
+ * Input: name Identifies which device to open. This can either be
+ * a host specific identifier (e.g. "/dev/ttya",
+ * "COM1:"), or a number which is used to refer to
+ * `standard' interfaces, so "1" would be the first host
+ * interface, "2" the second, and so on.
+ *
+ * arg Driver specific arguments. For example, some serial
+ * drivers accept speed and control arguments such as
+ * "9600" or "19200/NO_BREAK". These arguments are
+ * completely free-form: it is the individual drivers
+ * which do the necessary interpretation.
+ *
+ * type The type of packet the caller is interested in. Only
+ * one open is allowed for each type of packet.
+ *
+ * In/Out: device The device driver to open
+ *
+ * Returns:
+ * OK: adp_ok
+ * Error: adp_device_open_failed
+ * adp_device_already_open
+ * adp_malloc_failure
+ */
+AdpErrs DevSW_Open(DeviceDescr *device, const char *name, const char *arg,
+ const DevChanID type);
+
+/*
+ * Function: DevSW_Match
+ * Purpose: Minimal veneer for DeviceMatch
+ *
+ * Params:
+ * Input: device The device driver to match.
+ *
+ * name Identifies which device to open. This can either be
+ * a host specific identifier (e.g. "/dev/ttya",
+ * "COM1:"), or a number which is used to refer to
+ * `standard' interfaces, so "1" would be the first host
+ * interface, "2" the second, and so on.
+ *
+ * arg Driver specific arguments. For example, some serial
+ * drivers accept speed and control arguments such as
+ * "9600" or "19200/NO_BREAK". These arguments are
+ * completely free-form: it is the individual drivers
+ * which do the necessary interpretation.
+ *
+ * Returns:
+ * OK: adp_ok
+ * Error: adp_failed
+ */
+AdpErrs DevSW_Match(const DeviceDescr *device, const char *name,
+ const char *arg);
+
+/*
+ * Function: DevSW_Close
+ * Purpose: Close the specified device driver. All packets of the type
+ * used by the caller held within the switching layer will
+ * be discarded.
+ *
+ * Pre-conditions: Device must have been previously opened.
+ *
+ * Params:
+ * Input: device The device driver to close
+ *
+ * type The type of packet the caller was interested in.
+ *
+ * Returns:
+ * OK: adp_ok
+ * Error: adp_device_not_open
+ */
+AdpErrs DevSW_Close(const DeviceDescr *device, const DevChanID type);
+
+/*
+ * Function: DevSW_Read
+ * Purpose: Read a packet of appropriate type from the device driver
+ *
+ * Params:
+ * Input: device The device driver to read packet from.
+ *
+ * type The type of packet the caller is interested in.
+ *
+ * Output: packet Pointer to new packet (if one is available)
+ * NULL (if no complete packet is available)
+ *
+ * Input: block If TRUE, read may safely block for a short period
+ * of time (say up to 20ms), to avoid high CPU load
+ * whilst waiting for a reply.
+ * If FALSE, read MUST NOT block.
+ *
+ * Returns:
+ * OK: adp_ok
+ * Error: adp_bad_packet
+ *
+ * Post-conditions: The calling function is responsible for freeing the
+ * resources used by the packet when it is no longer
+ * needed.
+ */
+AdpErrs DevSW_Read(const DeviceDescr *device, const DevChanID type,
+ Packet **packet, bool block);
+
+/*
+ * Function: DevSW_Write
+ * Purpose: Try to write a packet to the device driver. The write will
+ * be bounced if another write is still in progress.
+ *
+ * Params:
+ * Input: device The device driver to write a packet to.
+ *
+ * packet The packet to be written.
+ *
+ * type The type to be assigned to the packet.
+ *
+ * Returns:
+ * OK: adp_ok
+ * Error: adp_illegal_args
+ * adp_write_busy
+ *
+ * Post-conditions: The calling function retains "ownership" of the packet,
+ * i.e. it is responsible for freeing the resources used
+ * by the packet when it is no longer needed.
+ */
+AdpErrs DevSW_Write(const DeviceDescr *device, Packet *packet, DevChanID type);
+
+/*
+ * Function: DevSW_FlushPendingWrite
+ * Purpose: If a write is in progress, give it a chance to finish.
+ *
+ * Params:
+ * Input: device The device driver to flush.
+ *
+ * Returns:
+ * adp_ok no pending write, or write flushed completely
+ * adp_write_busy pending write not flushed completely
+ */
+AdpErrs DevSW_FlushPendingWrite(const DeviceDescr *device);
+
+/*
+ * Function: DevSW_Ioctl
+ * Purpose: Perform miscellaneous control operations. This is a minimal
+ * veneer to DeviceIoctl.
+ *
+ * Params:
+ * Input: device The device driver to control.
+ *
+ * opcode Reason code indicating the operation to perform.
+ *
+ * In/Out: args Pointer to opcode-sensitive arguments/result space.
+ *
+ * Returns:
+ * OK: adp_ok
+ * Error: adp_failed
+ */
+AdpErrs DevSW_Ioctl(const DeviceDescr *device, const int opcode, void *args);
+
+/*
+ * Function: DevSW_WriteFinished
+ * Purpose: Return TRUE if the active device has finished writing
+ * the last packet to be sent, or FALSE if a packet is still
+ * being transmitted.
+ *
+ * Params:
+ * Input: device The device driver to check.
+ *
+ * Returns:
+ * TRUE: write finished or inactive
+ * FALSE: write in progress
+ */
+bool DevSW_WriteFinished(const DeviceDescr *device);
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif /* ndef angsd_devsw_h */
+
+/* EOF devsw.h */
diff --git a/gdb/rdi-share/drivers.c b/gdb/rdi-share/drivers.c
new file mode 100644
index 00000000000..ba0eee50890
--- /dev/null
+++ b/gdb/rdi-share/drivers.c
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
+ *
+ * This software may be freely used, copied, modified, and distributed
+ * provided that the above copyright notice is preserved in all copies of the
+ * software.
+ */
+
+/* -*-C-*-
+ *
+ * $Revision$
+ * $Date$
+ *
+ *
+ * drivers.c - declares a NULL terminated list of device driver
+ * descriptors supported by the host.
+ */
+#include <stdio.h>
+
+#include "drivers.h"
+
+extern DeviceDescr angel_SerialDevice;
+extern DeviceDescr angel_SerparDevice;
+extern DeviceDescr angel_EthernetDevice;
+
+DeviceDescr *devices[] =
+{
+ &angel_SerialDevice,
+ &angel_SerparDevice,
+ &angel_EthernetDevice,
+ NULL
+};
+
+/* EOF drivers.c */
diff --git a/gdb/rdi-share/drivers.h b/gdb/rdi-share/drivers.h
new file mode 100644
index 00000000000..3655c18b0a2
--- /dev/null
+++ b/gdb/rdi-share/drivers.h
@@ -0,0 +1,193 @@
+/*
+ * Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
+ *
+ * This software may be freely used, copied, modified, and distributed
+ * provided that the above copyright notice is preserved in all copies of the
+ * software.
+ */
+
+/* -*-C-*-
+ *
+ * $Revision$
+ * $Date$
+ *
+ *
+ * Project: ANGEL
+ *
+ * Title: Definitions for device driver interface.
+ */
+#ifndef angsd_drivers_h
+#define angsd_drivers_h
+
+#include "rxtx.h"
+
+#ifndef __cplusplus
+typedef struct DeviceDescr DeviceDescr;
+typedef struct DriverCall DriverCall;
+#endif
+
+/*
+ * used to pass packets across the driver interface
+ */
+struct DriverCall
+{
+ struct data_packet dc_packet;
+ void *dc_context;
+};
+
+/*
+ * used to describe a device driver
+ */
+struct DeviceDescr
+{
+ char *DeviceName;
+ int (*DeviceOpen)(const char *name, const char *arg);
+ int (*DeviceMatch)(const char *name, const char *arg);
+ void (*DeviceClose)(void);
+ int (*DeviceRead)(DriverCall *dc, bool block);
+ int (*DeviceWrite)(DriverCall *dc);
+ int (*DeviceIoctl)(const int opcode, void *args);
+ void *SwitcherState; /* used by switcher interface */
+};
+
+/*
+ * Function: DeviceOpen
+ *
+ * Purpose: Open a communications device
+ *
+ * Pre-conditions: No previous open is still active
+ *
+ * Params:
+ * Input: name Identifies which device to open. This can either be
+ * a host specific identifier (e.g. "/dev/ttya",
+ * "COM1:"), or a number which is used to refer to
+ * `standard' interfaces, so "1" would be the first host
+ * interface, "2" the second, and so on.
+ *
+ * arg Driver specific arguments. For example, some serial
+ * drivers accept speed and control arguments such as
+ * "9600" or "19200/NO_BREAK". These arguments are
+ * completely free-form: it is the individual drivers
+ * which do the necessary interpretation.
+ *
+ * Returns:
+ * OK: 0
+ * Error: -1
+ */
+extern int DeviceOpen(const char *name, const char *arg);
+
+/*
+ * Function: DeviceMatch
+ *
+ * Purpose: Check whether parameters are OK to be passed to DeviceOpen
+ *
+ * Params:
+ * Input: name Identifies which device to open. This can either be
+ * a host specific identifier (e.g. "/dev/ttya",
+ * "COM1:"), or a number which is used to refer to
+ * `standard' interfaces, so "1" would be the first host
+ * interface, "2" the second, and so on.
+ *
+ * arg Driver specific arguments. For example, some serial
+ * drivers accept speed and control arguments such as
+ * "9600" or "19200/NO_BREAK". These arguments are
+ * completely free-form: it is the individual drivers
+ * which do the necessary interpretation.
+ *
+ * Returns:
+ * OK: 0
+ * Error: -1
+ */
+extern int DeviceMatch(const char *name, const char *arg);
+
+/*
+ * Function: DeviceClose
+ *
+ * Purpose: Close a communications device
+ *
+ * Pre-conditions: Device must have been previously opened
+ *
+ * Params: None
+ *
+ * Returns: Nothing
+ */
+extern void DeviceClose(void);
+
+/*
+ * Function: DeviceRead
+ *
+ * Purpose: Try to read a complete packet from a communications device.
+ * This read must usually be non-blocking, i.e. it should read as
+ * many data from the device as needed to complete the packet,
+ * but it should not wait if the packet is not complete, and no
+ * more data are currently available from the device.
+ * As an optimisation the read can optionally block when 'block'
+ * is TRUE, but only for a short time. It is acceptable for the
+ * 'block' parameter to be ignored in which case all reads
+ * should be non-blocking.
+ *
+ * Pre-conditions: Device has been opened via DeviceOpen()
+ *
+ * Params:
+ * In/Out: dc Describes the packet being read (dc->dc_packet);
+ * dc->dc_context is for the driver to store private
+ * context, and is guaranteed to be NULL the first
+ * time DeviceRead is called for a given packet.
+ *
+ * In: block If TRUE, read may safely block for a short period
+ * of time (say up to 20ms), to avoid high CPU load
+ * whilst waiting for a reply.
+ * If FALSE, read MUST NOT block.
+ *
+ * Returns:
+ * OK: 1 (packet is complete)
+ * 0 (packet is not yet complete)
+ * Error: -1 bad packet
+ *
+ * Post-conditions: should a calamatous error occur panic() will be called
+ */
+extern int DeviceRead(DriverCall *dc, bool block);
+
+/*
+ * Function: DeviceWrite
+ *
+ * Purpose: Try to write a packet to a communications device. This write
+ * must be non-blocking, i.e. it should write as many data to
+ * the device as is immediately possible, but should not wait
+ * for space to send any more after that.
+ *
+ * Pre-conditions: Device has been opened via DeviceOpen()
+ *
+ * Params:
+ * In/Out: dc Describes the packet being written (dc->dc_packet);
+ * dc->dc_context is for the driver to store private
+ * context, and is guaranteed to be NULL the first
+ * time DeviceWrite is called for a given packet.
+ *
+ * Returns:
+ * OK: 1 (all of the packet has been written)
+ * 0 (some of the packet remains to be written)
+ * Error: -1
+ */
+extern int DeviceWrite(DriverCall *dc);
+
+/*
+ * Function: DeviceIoctl
+ *
+ * Purpose: Perform miscellaneous driver operations
+ *
+ * Pre-conditions: Device has been open via DeviceOpen()
+ *
+ * Params:
+ * Input: opcode Reason code indicating the operation to perform
+ * In/Out: args Pointer to opcode-sensitive arguments/result space
+ *
+ * Returns:
+ * OK: 0
+ * Error: -1
+ */
+extern int DeviceIoctl(const int opcode, void *args);
+
+#endif /* !defined(angsd_drivers_h) */
+
+/* EOF drivers.h */
diff --git a/gdb/rdi-share/endian.h b/gdb/rdi-share/endian.h
new file mode 100644
index 00000000000..3d32d9a6e60
--- /dev/null
+++ b/gdb/rdi-share/endian.h
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
+ *
+ * This software may be freely used, copied, modified, and distributed
+ * provided that the above copyright notice is preserved in all copies of the
+ * software.
+ */
+
+/* -*-C-*-
+ *
+ * $Revision$
+ * $Date$
+ *
+ *
+ * endian.h - target endianness independent read/write primitives.
+ */
+
+#ifndef angel_endian_h
+#define angel_endian_h
+
+/*
+ * The endianness of the data being processed needs to be known, but
+ * the host endianness is not required (since the data is constructed
+ * using bytes). At the moment these are provided as macros. This
+ * gives the compiler freedom in optimising individual calls. However,
+ * if space is at a premium then functions should be provided.
+ *
+ * NOTE: These macros assume that the data has been packed in the same format
+ * as the packing on the build host. If this is not the case then
+ * the wrong addresses could be used when dealing with structures.
+ *
+ */
+
+/*
+ * For all the following routines the target endianness is defined by the
+ * following boolean definitions.
+ */
+#define BE (1 == 1) /* TRUE : big-endian */
+#define LE (1 == 0) /* FALSE : little-endian */
+
+/*
+ * The following type definitions are used by the endianness converting
+ * macros.
+ */
+typedef unsigned char U8;
+typedef U8 *P_U8;
+typedef const U8 *CP_U8;
+
+typedef unsigned short U16;
+typedef U16 *P_U16;
+
+typedef unsigned int U32;
+typedef U32 *P_U32;
+
+/*
+ * If the endianness of the host and target are known (fixed) and the same
+ * then the following macro definitions can be used. These just directly copy
+ * the data.
+ *
+ * #define READ(e,a) (a)
+ * #define WRITE(e,a,v) ((a) = (v))
+ * #define PREAD(e,a) (a)
+ * #define PWRITE(e,a,v) (*(a) = (v))
+ */
+
+/*
+ * These macros assume that a byte (char) is 8bits in size, and that the
+ * endianness is not important when reading or writing bytes.
+ */
+#define PUT8(a,v) (*((P_U8)(a)) = (U8)(v))
+#define PUT16LE(a,v) (PUT8(a,((v) & 0xFF)), \
+ PUT8((((P_U8)(a)) + sizeof(char)),((v) >> 8)))
+#define PUT16BE(a,v) (PUT8(a,((v) >> 8)), \
+ PUT8((((P_U8)(a)) + sizeof(char)),((v) & 0xFF)))
+#define PUT32LE(a,v) (PUT16LE(a,v), \
+ PUT16LE((((P_U8)(a)) + sizeof(short)),((v) >> 16)))
+#define PUT32BE(a,v) (PUT16BE(a,((v) >> 16)), \
+ PUT16BE((((P_U8)(a)) + sizeof(short)),v))
+
+#define GET8(a) (*((CP_U8)(a)))
+#define GET16LE(a) (GET8(a) | (((U16)GET8(((CP_U8)(a)) + sizeof(char))) << 8))
+#define GET16BE(a) ((((U16)GET8(a)) << 8) | GET8(((CP_U8)(a)) + sizeof(char)))
+#define GET32LE(a) (GET16LE(a) | \
+ (((U32)GET16LE(((CP_U8)(a)) + sizeof(short))) << 16))
+#define GET32BE(a) ((((U32)GET16BE(a)) << 16) | \
+ GET16BE(((CP_U8)(a)) + sizeof(short)))
+
+/*
+ * These macros simplify the code in respect to reading and writing the
+ * correct size data when dealing with endianness. "e" is TRUE if we are
+ * dealing with big-endian data, FALSE if we are dealing with little-endian.
+ */
+
+/* void WRITE(int endianness, void *address, unsigned value); */
+
+#define WRITE16(e,a,v) ((e) ? PUT16BE(&(a),v) : PUT16LE(&(a),v))
+#define WRITE32(e,a,v) ((e) ? PUT32BE(&(a),v) : PUT32LE(&(a),v))
+#define WRITE(e,a,v) ((sizeof(v) == sizeof(char)) ? \
+ PUT8(&(a),v) : ((sizeof(v) == sizeof(short)) ? \
+ WRITE16(e,a,v) : WRITE32(e,a,v)))
+
+/* unsigned READ(int endianness, void *address) */
+#define READ16(e,a) ((e) ? GET16BE(&(a)) : GET16LE(&(a)))
+#define READ32(e,a) ((e) ? GET32BE(&(a)) : GET32LE(&(a)))
+#define READ(e,a) ((sizeof(a) == sizeof(char)) ? \
+ GET8((CP_U8)&(a)) : ((sizeof(a) == sizeof(short)) ? \
+ READ16(e,a) : READ32(e,a)))
+
+/* void PWRITE(int endianness, void *address, unsigned value); */
+#define PWRITE16(e,a,v) ((e) ? PUT16BE(a,v) : PUT16LE(a,v))
+#define PWRITE32(e,a,v) ((e) ? PUT32BE(a,v) : PUT32LE(a,v))
+#define PWRITE(e,a,v) ((sizeof(v) == sizeof(char)) ? \
+ PUT8(a,v) : ((sizeof(v) == sizeof(short)) ? \
+ PWRITE16(e,a,v) : PWRITE32(e,a,v)))
+
+/* unsigned PREAD(int endianness, void *address) */
+#define PREAD16(e,a) ((e) ? GET16BE(a) : GET16LE(a))
+#define PREAD32(e,a) ((e) ? GET32BE(a) : GET32LE(a))
+#define PREAD(e,a) ((sizeof(*(a)) == sizeof(char)) ? \
+ GET8((CP_U8)a) : ((sizeof(*(a)) == sizeof(short)) ? \
+ PREAD16(e,a) : PREAD32(e,a)))
+
+#endif /* !defined(angel_endian_h) */
+
+/* EOF endian.h */
diff --git a/gdb/rdi-share/etherdrv.c b/gdb/rdi-share/etherdrv.c
new file mode 100644
index 00000000000..58462d44768
--- /dev/null
+++ b/gdb/rdi-share/etherdrv.c
@@ -0,0 +1,730 @@
+/*
+ * Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
+ *
+ * This software may be freely used, copied, modified, and distributed
+ * provided that the above copyright notice is preserved in all copies of the
+ * software.
+ */
+
+/* -*-C-*-
+ *
+ * $Revision$
+ * $Date$
+ *
+ *
+ * etherdrv.c - Ethernet Driver for Angel.
+ */
+
+#ifdef __hpux
+# define _POSIX_SOURCE 1
+# define _HPUX_SOURCE 1
+# define _XOPEN_SOURCE 1
+#endif
+
+#include <stdio.h>
+#ifdef __hpux
+# define uint hide_HPs_uint
+#endif
+#ifdef STDC_HEADERS
+# include <unistd.h>
+# ifdef __hpux
+# undef uint
+# endif
+#endif
+#include <stdlib.h>
+#include <string.h>
+#ifdef __hpux
+# define uint hide_HPs_uint
+#endif
+#include <fcntl.h>
+#ifdef __hpux
+# undef uint
+#endif
+#include <errno.h>
+#include <stdarg.h>
+#include <ctype.h>
+#include "host.h"
+
+#ifdef COMPILING_ON_WINDOWS
+ typedef char * caddr_t;
+# undef IGNORE
+# include <winsock.h>
+# include "angeldll.h"
+#else
+# ifdef __hpux
+# define uint hide_HPs_uint
+# endif
+# include <sys/types.h>
+# include <sys/socket.h>
+# ifdef __hpux
+# undef uint
+# endif
+# include <netdb.h>
+# include <sys/time.h>
+# include <sys/ioctl.h>
+# ifdef HAVE_SYS_FILIO_H
+# include <sys/filio.h>
+# endif
+# include <netinet/in.h>
+# include <arpa/inet.h>
+#endif
+
+#include "hsys.h"
+#include "devices.h"
+#include "endian.h"
+#include "buffers.h"
+#include "hostchan.h"
+#include "params.h"
+#include "logging.h"
+#include "ethernet.h"
+
+
+#if !defined(COMPILING_ON_WINDOWS) && !defined(STDC_HEADERS)
+/* These two might not work for windows. */
+extern int sys_nerr;
+extern char * sys_errlist[];
+#endif
+
+#ifndef UNUSED
+# define UNUSED(x) (x = x) /* Silence compiler warnings */
+#endif
+
+/*
+ * forward declarations of static functions
+ */
+static int EthernetOpen(const char *name, const char *arg);
+static int EthernetMatch(const char *name, const char *arg);
+static void EthernetClose(void);
+static int EthernetRead(DriverCall *dc, bool block);
+static int EthernetWrite(DriverCall *dc);
+static int EthernetIoctl(const int opcode, void *args);
+
+/*
+ * the device descriptor for Ethernet
+ */
+DeviceDescr angel_EthernetDevice =
+{
+ "Ethernet",
+ EthernetOpen,
+ EthernetMatch,
+ EthernetClose,
+ EthernetRead,
+ EthernetWrite,
+ EthernetIoctl
+};
+
+/*
+ * descriptor for the socket that we talk down
+ */
+static int sock = -1;
+
+/*
+ * address of the remote target
+ */
+static struct sockaddr_in remote, *ia = &remote;
+
+/*
+ * array of dynamic port numbers on target
+ */
+static unsigned short int ports[2];
+
+/*
+ * Function: set_address
+ * Purpose: Try to get an address into an understandable form
+ *
+ * Params:
+ * Input: addr The address to parse
+ *
+ * Output: ia Structure to hold the parsed address
+ *
+ * Returns:
+ * OK: 0
+ * Error: -1
+ */
+static int set_address(const char *const addr, struct sockaddr_in *const ia)
+{
+ ia->sin_family = AF_INET;
+
+ /*
+ * Try address as a dotted decimal
+ */
+ ia->sin_addr.s_addr = inet_addr(addr);
+
+ /*
+ * If that failed, try it as a hostname
+ */
+ if (ia->sin_addr.s_addr == (u_int)-1)
+ {
+ struct hostent *hp = gethostbyname(addr);
+
+ if (hp == NULL)
+ return -1;
+
+ (void)memcpy((caddr_t)&ia->sin_addr, hp->h_addr, hp->h_length);
+ }
+
+ return 0;
+}
+
+/*
+ * Function: open_socket
+ * Purpose: Open a non-blocking UDP socket, and bind it to a port
+ * assigned by the system.
+ *
+ * Params: None
+ *
+ * Returns:
+ * OK: socket descriptor
+ * Error: -1
+ */
+static int open_socket(void)
+{
+ int sfd;
+#if 0 /* see #if 0 just below -VVV- */
+ int yesplease = 1;
+#endif
+ struct sockaddr_in local;
+
+ /*
+ * open the socket
+ */
+#ifdef COMPILING_ON_WINDOWS
+ if ((sfd = socket(AF_INET, SOCK_DGRAM, 0)) == INVALID_SOCKET)
+ return -1;
+#else
+ if ((sfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
+ {
+# ifdef DEBUG
+ perror("socket");
+# endif
+ return -1;
+ }
+#endif
+
+ /*
+ * 960731 KWelton
+ *
+ * I don't believe that this should be necessary - if we
+ * use select(), then non-blocking I/O is redundant.
+ * Unfortunately, select() appears to be broken (under
+ * Solaris, with a limited amount of time available for
+ * debug), so this code stays in for the time being
+ */
+#if 0
+ /*
+ * enable non-blocking I/O
+ */
+ if (ioctlsocket(sfd, FIONBIO, &yesplease) < 0)
+ {
+# ifdef DEBUG
+ perror("ioctl(FIONBIO)");
+# endif
+ closesocket(sfd);
+
+ return -1;
+ }
+#endif /* 0/1 */
+
+ /*
+ * bind local address to a system-assigned port
+ */
+ memset((char *)&local, 0, sizeof(local));
+ local.sin_family = AF_INET;
+ local.sin_port = htons(0);
+ local.sin_addr.s_addr = INADDR_ANY;
+ if (bind(sfd, (struct sockaddr *)&local, sizeof(local)) < 0)
+ {
+#ifdef DEBUG
+ perror("bind");
+#endif
+ closesocket(sfd);
+
+ return -1;
+ }
+
+ /*
+ * all done
+ */
+ return sfd;
+}
+
+/*
+ * Function: fetch_ports
+ * Purpose: Request assigned port numbers from remote target
+ *
+ * Params: None
+ *
+ * Returns: Nothing
+ *
+ * Post-conditions: This routine will *always* return something for the
+ * port numbers. If the remote target does not
+ * respond, then it makes something up - this allows
+ * the standard error message (from ardi.c) to be
+ * generated when the target is dead for whatever
+ * reason.
+ */
+static void fetch_ports(void)
+{
+ int i;
+ const char ctrlpacket[] = CTRL_MAGIC;
+ CtrlResponse response;
+
+ /*
+ * we will try 3 times to elicit a response from the target
+ */
+ for (i = 0; i < 3; ++i)
+ {
+ struct timeval tv;
+ fd_set fdset;
+
+ /*
+ * send the magic string to the control
+ * port on the remote target
+ */
+ ia->sin_port = htons(CTRL_PORT);
+ if (sendto(sock, ctrlpacket, sizeof(ctrlpacket), 0,
+ (struct sockaddr *)ia, sizeof(*ia)) < 0)
+ {
+#ifdef DEBUG
+ perror("fetch_ports: sendto");
+#endif
+ return;
+ }
+
+ FD_ZERO(&fdset);
+ FD_SET(sock, &fdset);
+ tv.tv_sec = 0;
+ tv.tv_usec = 250000;
+
+ if (select(sock + 1, &fdset, NULL, NULL, &tv) < 0)
+ {
+#ifdef DEBUG
+ perror("fetch_ports: select");
+#endif
+ return;
+ }
+
+ if (FD_ISSET(sock, &fdset))
+ {
+ /*
+ * there is something there - read it
+ */
+ if (recv(sock, (char *)&response, sizeof(response), 0) < 0)
+ {
+#ifdef COMPILING_ON_WINDOWS
+ unsigned int werrno = WSAGetLastError();
+
+ if (werrno == WSAEWOULDBLOCK || werrno == 0)
+#else
+ if (errno == EWOULDBLOCK)
+#endif
+ {
+ --i;
+ continue;
+ }
+ else
+ {
+#ifdef DEBUG
+ perror("fetch_ports: recv");
+#endif
+ return;
+ }
+ }
+ {
+ /*
+ * XXX
+ *
+ * this is *very* unpleasant - try to match the structure
+ * layout
+ */
+ unsigned short *sptr = (unsigned short *)(response + RESP_DBUG);
+
+ if (strcmp(response, ctrlpacket) == 0)
+ {
+ ports[DBUG_INDEX] = htons(*sptr);
+ sptr++;
+ ports[APPL_INDEX] = htons(*sptr);
+ }
+
+#ifdef DEBUG
+ printf("fetch_ports: got response, DBUG=%d, APPL=%d\n",
+ ports[DBUG_INDEX], ports[APPL_INDEX]);
+#endif
+ return;
+ }
+ }
+ }
+
+ /*
+ * we failed to get a response
+ */
+#ifdef DEBUG
+ printf("fetch_ports: failed to get a real answer\n");
+#endif
+}
+
+/*
+ * Function: read_packet
+ * Purpose: read a packet, and pass it back to higher levels
+ *
+ * Params:
+ * In/Out: packet Holder for the read packet
+ *
+ * Returns: 1 - Packet is complete
+ * 0 - No complete packet read
+ *
+ * Post-conditions: Will call panic() if something goes wrong with the OS
+ */
+static int read_packet(struct data_packet *const packet)
+{
+ struct sockaddr_in from;
+ int nbytes, fromlen = sizeof(from);
+ DevChanID devchan;
+
+ /*
+ * try to get the packet
+ */
+ if ((nbytes = recvfrom(sock, (char *)(packet->data), packet->buf_len, 0,
+ (struct sockaddr *)&from, &fromlen)) < 0)
+ {
+#ifdef COMPILING_ON_WINDOWS
+ if (nbytes == SOCKET_ERROR && WSAGetLastError() != WSAEWOULDBLOCK)
+ MessageBox(GetFocus(), "Error receiving packet\n", "Angel", MB_OK | MB_ICONSTOP);
+#else
+ if (errno != EWOULDBLOCK)
+ {
+# ifdef DEBUG
+ perror("recv");
+# endif
+ panic("ethernet recv failure");
+ }
+#endif
+ return 0;
+ }
+
+#ifdef COMPILING_ON_WINDOWS
+ if (pfnProgressCallback != NULL && nbytes != SOCKET_ERROR)
+ {
+ progressInfo.nRead += nbytes;
+ (*pfnProgressCallback)(&progressInfo);
+ }
+#endif
+
+ /*
+ * work out where the packet was from
+ */
+ if (from.sin_addr.s_addr != remote.sin_addr.s_addr)
+ {
+ /*
+ * not from our target - ignore it
+ */
+#ifdef DEBUG
+ printf("read_packet: ignoring packet from %s\n",
+ inet_ntoa(from.sin_addr));
+#endif
+
+ return 0;
+ }
+ else if (ntohs(from.sin_port) == ports[DBUG_INDEX])
+ devchan = DC_DBUG;
+ else if (ntohs(from.sin_port) == ports[APPL_INDEX])
+ devchan = DC_APPL;
+ else
+ {
+ /*
+ * unknown port number - ignore it
+ */
+#ifdef DEBUG
+ printf("read_packet: ignore packet from port %hd\n",
+ htons(from.sin_port));
+#endif
+
+ return 0;
+ }
+
+#if defined(DEBUG) && !defined(DO_TRACE)
+ printf("EthernetRead: %d bytes from %s channel\n",
+ nbytes, (devchan == DC_DBUG) ? "DBUG" : "APPL");
+#endif
+
+#ifdef DO_TRACE
+ printf("[%d on %d]\n", nbytes, devchan);
+ {
+ int i = 0;
+ unsigned char *cptr = packet->data;
+
+ while (i < nbytes)
+ {
+ printf("<%02X ", *(cptr++));
+
+ if (!(++i % 16))
+ printf("\n");
+ }
+
+ if (i % 16)
+ printf("\n");
+ }
+#endif
+
+ /*
+ * OK - fill in the details
+ */
+ packet->type = devchan;
+ packet->len = nbytes;
+ return 1;
+}
+
+/**********************************************************************/
+
+/*
+ * Function: Ethernet_Open
+ * Purpose: Open the Ethernet device. See the documentation for
+ * DeviceOpen in drivers.h
+ *
+ * Post-conditions: Will have updated struct sockaddr_in remote (*ia)
+ * with the address of the remote target.
+ */
+static int EthernetOpen(const char *name, const char *arg)
+{
+#ifdef COMPILING_ON_WINDOWS
+ WORD wVersionRequested;
+ WSADATA wsaData;
+#endif
+ /*
+ * name is passed as e=<blah>, so skip 1st two characters
+ */
+ const char *etheraddr = name + 2;
+
+#ifdef DEBUG
+ printf("EthernetOpen: name `%s'\n", name);
+#endif
+
+ /* Check that the name is a valid one */
+ if (EthernetMatch(name, arg) != 0)
+ return -1;
+
+#ifdef COMPILING_ON_WINDOWS
+ wVersionRequested = MAKEWORD(1, 1);
+ if (WSAStartup(wVersionRequested, &wsaData) != 0)
+ /*
+ * Couldn't find a useable winsock.dll.
+ */
+ return -1;
+
+ if ( LOBYTE( wsaData.wVersion ) != 1 || HIBYTE( wsaData.wVersion ) != 1 )
+ {
+ WSACleanup();
+
+ /*
+ * Couldn't find a winsock.dll with supported version.
+ */
+ return -1;
+ }
+#endif
+
+ memset((char *)ia, 0, sizeof(*ia));
+ if (set_address(etheraddr, ia) < 0)
+ {
+#ifdef COMPILING_ON_WINDOWS
+ /*
+ * SJ - I'm not sure that this is the correct way to handle this
+ * as Fail calls remote_disable and exits, while panic just exits.
+ * However at the time of writing remote_disable does nothing!
+ */
+ /* Panic("EthernetOpen: bad name `%s'\n", etheraddr); */
+#else
+ Fail("EthernetOpen: bad name `%s'\n", etheraddr);
+#endif
+ return -1;
+ }
+
+ if ((sock = open_socket()) < 0)
+ return -1;
+
+ /*
+ * fetch the port numbers assigned by the remote target
+ * to its Debug and Application sockets
+ */
+ fetch_ports();
+
+ return 0;
+}
+
+static int EthernetMatch(const char *name, const char *arg)
+{
+ /* IGNORE arg */
+ if (0)
+ arg = arg;
+
+ if (name == NULL)
+ return -1;
+
+ if (tolower(name[0]) != 'e' || name[1] != '=')
+ return -1;
+
+ return 0;
+}
+
+static void EthernetClose(void)
+{
+ if (sock >= 0)
+ {
+ closesocket(sock);
+ sock = -1;
+ }
+
+#ifdef COMPILING_ON_WINDOWS
+ WSACleanup();
+#endif
+}
+
+static int EthernetRead(DriverCall *dc, bool block)
+{
+ fd_set fdset;
+ struct timeval tv;
+ int err;
+
+ FD_ZERO(&fdset);
+ FD_SET(sock, &fdset);
+
+#ifdef COMPILING_ON_WINDOWS
+ UNUSED(block);
+ tv.tv_sec = tv.tv_usec = 0;
+#else
+ tv.tv_sec = 0;
+ tv.tv_usec = (block ? 10000 : 0);
+#endif
+
+ err = select(sock + 1, &fdset, NULL, NULL, &tv);
+
+ if (err < 0) {
+ if (errno == EINTR) {
+ return 0;
+ }
+ panic("ethernet select failure (errno=%i)",errno);
+ return 0;
+ }
+
+ if (FD_ISSET(sock, &fdset))
+ return read_packet(&dc->dc_packet);
+ else
+ return 0;
+}
+
+static int EthernetWrite(DriverCall *dc)
+{
+ int nbytes;
+ struct data_packet *packet = &dc->dc_packet;
+
+ if (packet->type == DC_DBUG)
+ ia->sin_port = htons(ports[DBUG_INDEX]);
+ else if (packet->type == DC_APPL)
+ ia->sin_port = htons(ports[APPL_INDEX]);
+ else
+ {
+ panic("EthernetWrite: unknown devchan");
+ return 0;
+ }
+
+#if defined(DEBUG) && !defined(DO_TRACE)
+ printf("EthernetWrite: %d bytes to %s channel\n",
+ packet->len, (packet->type == DC_DBUG) ? "DBUG" : "APPL");
+#endif
+
+#ifdef DO_TRACE
+ printf("[%d on %d]\n", packet->len, packet->type);
+ {
+ int i = 0;
+ unsigned char *cptr = packet->data;
+
+ while (i < packet->len)
+ {
+ printf(">%02X ", *(cptr++));
+
+ if (!(++i % 16))
+ printf("\n");
+ }
+
+ if (i % 16)
+ printf("\n");
+ }
+#endif
+
+ if ((nbytes = sendto(sock, (char *)(packet->data), packet->len, 0,
+ (struct sockaddr *)ia, sizeof(*ia))) != packet->len)
+ {
+#ifdef COMPILING_ON_WINDOWS
+ if (nbytes == SOCKET_ERROR && WSAGetLastError() != WSAEWOULDBLOCK)
+#else
+ if (nbytes < 0 && errno != EWOULDBLOCK)
+#endif
+ {
+#ifdef DEBUG
+ perror("sendto");
+#endif
+
+#ifdef COMPILING_ON_WINDOWS
+ panic("ethernet send failure\n");
+#else
+ /* might not work for Windows */
+ panic("ethernet send failure [%s]\n",
+#ifdef STDC_HEADERS
+ strerror(errno));
+#else
+ errno < sys_nerr ? sys_errlist[errno] : "unknown errno");
+#endif /* STDC_HEADERS */
+#endif
+ }
+#ifdef DEBUG
+ else if (nbytes >= 0)
+ fprintf(stderr, "ethernet send: asked for %d, sent %d\n", packet->len, nbytes);
+#endif
+ return 0;
+ }
+
+#ifdef COMPILING_ON_WINDOWS
+ if (pfnProgressCallback != NULL && nbytes != SOCKET_ERROR)
+ {
+ progressInfo.nWritten += nbytes;
+ (*pfnProgressCallback)(&progressInfo);
+ }
+#endif
+
+ return 1;
+}
+
+static int EthernetIoctl(const int opcode, void *args)
+{
+#ifdef DEBUG
+ printf( "EthernetIoctl: op %d arg %x\n", opcode, args );
+#endif
+
+ /*
+ * IGNORE(opcode)
+ */
+ if (0)
+ {
+ int dummy = opcode;
+ UNUSED(dummy);
+ }
+ UNUSED(args);
+
+ switch ( opcode )
+ {
+ case DC_RESYNC:
+ {
+#ifdef DEBUG
+ printf( "EthernetIoctl: resync\n" );
+#endif
+ fetch_ports();
+ return 0;
+ }
+
+ default:
+ {
+ return -1;
+ }
+ }
+}
+
+/* EOF etherdrv.c */
diff --git a/gdb/rdi-share/ethernet.h b/gdb/rdi-share/ethernet.h
new file mode 100644
index 00000000000..930acedcf57
--- /dev/null
+++ b/gdb/rdi-share/ethernet.h
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
+ *
+ * This software may be freely used, copied, modified, and distributed
+ * provided that the above copyright notice is preserved in all copies of the
+ * software.
+ */
+
+/* -*-C-*-
+ *
+ * $Revision$
+ * $Date$
+ *
+ *
+ * ethernet.h: Angel drivers for Ethernet using Fusion UDP/IP stack
+ */
+#ifndef angel_ethernet_h
+#define angel_ethernet_h
+
+/*
+ * the UDP ports that Angel Ethernet uses
+ */
+#define CTRL_PORT 1913
+
+/*
+ * the size of the largest packet accepted on the control socket
+ */
+#define CTRL_MAXPACKET 6
+
+/*
+ * This is the "magic number" sent to the control port to
+ * request that the channel port numbers are returned
+ */
+#define CTRL_MAGIC "Angel"
+
+/*
+ * Array used for responding to a request on the control port
+ */
+typedef unsigned char CtrlResponse[10];
+#define RESP_MAGIC 0
+#define RESP_DBUG 6
+#define RESP_APPL 8
+
+/*
+ * indices for accessing the array of port numbers sent
+ * over the control socket
+ */
+#define DBUG_INDEX 0
+#define APPL_INDEX 1
+
+#ifdef TARGET
+
+# include "devdriv.h"
+
+extern const struct angel_DeviceEntry angel_EthernetDevice;
+
+/*
+ * Function: angel_EthernetPoll
+ * Purpose: Poll Fusion for newly arrived packets
+ *
+ * Pre-conditions: Called in SVC mode with the lock
+ *
+ * Params:
+ * Input: data IGNORE'd
+ *
+ * Returns: Nothing
+ *
+ * Post-conditions: Will have passed any packets received along to
+ * higher levels
+ */
+void angel_EthernetPoll(unsigned int data);
+
+void angel_EthernetNOP(unsigned int data);
+
+
+/*
+ * Function: angel_FindEthernetConfigBlock
+ * Purpose: Search the Flash for an ethernet config block and return
+ * it if found.
+ *
+ * Params: None
+ *
+ * Returns: NULL if no config block found, the address if one is found.
+ *
+ */
+extern angel_EthernetConfigBlock *angel_FindEthernetConfigBlock(void);
+
+#else /* def TARGET */
+
+# ifndef COMPILING_ON_WINDOWS
+# define ioctlsocket(x, y, z) ioctl((x), (y), (z))
+# define closesocket(x) close(x)
+# endif
+
+#endif /* def TARGET */
+
+#endif /* ndef angel_ethernet_h */
+
+/* EOF ethernet.h */
diff --git a/gdb/rdi-share/host.h b/gdb/rdi-share/host.h
new file mode 100644
index 00000000000..4dffa8475fb
--- /dev/null
+++ b/gdb/rdi-share/host.h
@@ -0,0 +1,230 @@
+/*
+ * Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
+ *
+ * This software may be freely used, copied, modified, and distributed
+ * provided that the above copyright notice is preserved in all copies of the
+ * software.
+ */
+
+
+#ifndef _host_LOADED
+#define _host_LOADED 1
+
+#include <stdio.h>
+#include <stddef.h>
+#include <stdlib.h>
+
+#ifndef SEEK_SET
+# define SEEK_SET 0
+#endif
+#ifndef SEEK_CUR
+# define SEEK_CUR 1
+#endif
+#ifndef SEEK_END
+# define SEEK_END 2
+#endif
+
+/* The following for the benefit of compiling on SunOS */
+#ifndef offsetof
+# define offsetof(T, member) ((char *)&(((T *)0)->member) - (char *)0)
+#endif
+
+/* If under Cygwin, provide backwards compatibility with older
+ Cygwin compilers that don't define the current cpp define. */
+#ifdef __CYGWIN32__
+#ifndef __CYGWIN__
+#define __CYGWIN__
+#endif
+#endif
+
+#ifdef unix /* A temporary sop to older compilers */
+# ifndef __unix /* (good for long-term portability?) */
+# define __unix 1
+# endif
+#endif
+
+#ifdef __unix
+/* Generic unix -- hopefully a split into other variants will not be */
+/* needed. However, beware the 'bsd' test above and safe_toupper etc. */
+/* which cope with backwards (pre-posix/X/open) unix compatility. */
+# define COMPILING_ON_UNIX 1
+#endif
+#if defined(_WIN32)
+# define COMPILING_ON_WIN32 1
+# if !defined(__CYGWIN32__)
+# define COMPILING_ON_WINDOWS 1
+# endif
+#endif
+#if defined(_CONSOLE)
+# define COMPILING_ON_WINDOWS_CONSOLE 1
+# define COMPILING_ON_WINDOWS 1
+#endif
+#ifdef _MSC_VER
+# define COMPILING_ON_MSDOS 1
+# define COMPILING_ON_WINDOWS 1
+# if defined(__cplusplus)
+# define IMPLEMENT_BOOL_AS_INT 1 /* VC++ doesn't have 'bool' (yet) */
+# endif
+#endif
+/* The '(defined(__sparc) && defined(P_tmpdir) */
+/* && !defined(__svr4__))' is to detect gcc on SunOS. */
+/* C++ compilers don't have to define __STDC__ */
+#if (defined(__sparc) && defined(P_tmpdir))
+# if defined(__svr4__)
+# define COMPILING_ON_SOLARIS
+# else
+# define COMPILING_ON_SUNOS
+# endif
+#endif
+#ifdef __hppa
+# define COMPILING_ON_HPUX
+#endif
+
+/*
+ * The following typedefs may need alteration for obscure host machines.
+ */
+#if defined(__alpha) && defined(__osf__) /* =========================== */
+/* Under OSF the alpha has 64-bit pointers and 64-bit longs. */
+typedef int int32;
+typedef unsigned int unsigned32;
+/* IPtr and UPtr are 'ints of same size as pointer'. Do not use in */
+/* new code. Currently only used within 'ncc'. */
+typedef long int IPtr;
+typedef unsigned long int UPtr;
+
+#else /* all hosts except alpha under OSF ============================= */
+
+typedef long int int32;
+typedef unsigned long int unsigned32;
+/* IPtr and UPtr are 'ints of same size as pointer'. Do not use in */
+/* new code. Currently only used within 'ncc'. */
+#define IPtr int32
+#define UPtr unsigned32
+#endif /* ============================================================= */
+
+typedef short int int16;
+typedef unsigned short int unsigned16;
+typedef signed char int8;
+typedef unsigned char unsigned8;
+
+/* The following code defines the 'bool' type to be 'int' under C */
+/* and real 'bool' under C++. It also avoids warnings such as */
+/* C++ keyword 'bool' used as identifier. It can be overridden by */
+/* defining IMPLEMENT_BOOL_AS_ENUM or IMPLEMENT_BOOL_AS_INT. */
+#undef _bool
+
+#ifdef IMPLEMENT_BOOL_AS_ENUM
+ enum _bool { _false, _true };
+# define _bool enum _bool
+#elif defined(IMPLEMENT_BOOL_AS_INT) || !defined(__cplusplus)
+# define _bool int
+# define _false 0
+# define _true 1
+#endif
+
+#ifdef _bool
+# if defined(_MFC_VER) || defined(__CC_NORCROFT) /* When using MS Visual C/C++ v4.2 */
+# define bool _bool /* avoids "'bool' is reserved word" warning */
+# else
+ typedef _bool bool;
+# endif
+# define true _true
+# define false _false
+#endif
+
+#define YES true
+#define NO false
+#undef TRUE /* some OSF headers define as 1 */
+#define TRUE true
+#undef FALSE /* some OSF headers define as 1 */
+#define FALSE false
+
+/* 'uint' conflicts with some Unixen sys/types.h, so we now don't define it */
+typedef unsigned8 uint8;
+typedef unsigned16 uint16;
+typedef unsigned32 uint32;
+
+typedef unsigned Uint;
+typedef unsigned8 Uint8;
+typedef unsigned16 Uint16;
+typedef unsigned32 Uint32;
+
+#ifdef ALPHA_TASO_SHORT_ON_OSF /* was __alpha && __osf. */
+/* The following sets ArgvType for 64-bit pointers so that */
+/* DEC Unix (OSF) cc can be used with the -xtaso_short compiler option */
+/* to force pointers to be 32-bit. Not currently used since most/all */
+/* ARM tools accept 32 or 64 bit pointers transparently. See IPtr. */
+#pragma pointer_size (save)
+#pragma pointer_size (long)
+typedef char *ArgvType;
+#pragma pointer_size (restore)
+#else
+typedef char *ArgvType;
+#endif
+
+/*
+ * Rotate macros
+ */
+#define ROL_32(val, n) \
+((((unsigned32)(val) << (n)) | ((unsigned32)(val) >> (32-(n)))) & 0xFFFFFFFFL)
+#define ROR_32(val, n) \
+((((unsigned32)(val) >> (n)) | ((unsigned32)(val) << (32-(n)))) & 0xFFFFFFFFL)
+
+#ifdef COMPILING_ON_UNIX
+# define FOPEN_WB "w"
+# define FOPEN_RB "r"
+# define FOPEN_RWB "r+"
+# ifndef __STDC__ /* caveat RISCiX... */
+# define remove(file) unlink(file) /* a horrid hack, but probably best? */
+# endif
+#else
+# define FOPEN_WB "wb"
+# define FOPEN_RB "rb"
+# define FOPEN_RWB "rb+"
+#endif
+
+#ifndef FILENAME_MAX
+# define FILENAME_MAX 256
+#endif
+
+#if (!defined(__STDC__) && !defined(__cplusplus) && !defined(_MSC_VER)) || \
+ defined(COMPILING_ON_SUNOS)
+/* Use bcopy rather than memmove, as memmove is not available. */
+/* There does not seem to be a header for bcopy. */
+void bcopy(const char *src, char *dst, int length);
+# define memmove(d,s,l) bcopy(s,d,l)
+
+/* BSD/SUN don't have strtoul(), but then strtol() doesn't barf on */
+/* overflow as required by ANSI... This bodge is horrid. */
+# define strtoul(s, ptr, base) strtol(s, ptr, base)
+
+/* strtod is present in the C-library but is not in stdlib.h */
+extern double strtod(const char *str, char **ptr);
+#endif
+
+/* For systems that do not define EXIT_SUCCESS and EXIT_FAILURE */
+#ifndef EXIT_SUCCESS
+# define EXIT_SUCCESS 0
+#endif
+#ifndef EXIT_FAILURE
+# define EXIT_FAILURE 1
+#endif
+
+#ifndef IGNORE
+#define IGNORE(x) (x = x) /* Silence compiler warnings for unused arguments */
+#endif
+
+/* Define endian-ness of host */
+
+#if defined(__acorn) || defined(__mvs) || defined(_WIN32) || \
+ (defined(__alpha) && defined(__osf__))
+# define HOST_ENDIAN_LITTLE
+#elif defined(__sparc) || defined(macintosh)
+# define HOST_ENDIAN_BIG
+#else
+# define HOST_ENDIAN_UNKNOWN
+#endif
+
+#endif
+
+/* end of host.h */
diff --git a/gdb/rdi-share/hostchan.c b/gdb/rdi-share/hostchan.c
new file mode 100644
index 00000000000..8e41da49860
--- /dev/null
+++ b/gdb/rdi-share/hostchan.c
@@ -0,0 +1,1057 @@
+/*
+ * Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
+ *
+ * This software may be freely used, copied, modified, and distributed
+ * provided that the above copyright notice is preserved in all copies of the
+ * software.
+ */
+
+/* -*-C-*-
+ *
+ * $Revision$
+ * $Date$
+ *
+ *
+ * hostchan.c - Semi Synchronous Host side channel interface for Angel.
+ */
+
+#include <stdio.h>
+
+#ifdef HAVE_SYS_TIME_H
+# include <sys/time.h>
+#else
+# include "winsock.h"
+# include "time.h"
+#endif
+#include "hsys.h"
+#include "host.h"
+#include "logging.h"
+#include "chandefs.h"
+#include "chanpriv.h"
+#include "devclnt.h"
+#include "buffers.h"
+#include "drivers.h"
+#include "adperr.h"
+#include "devsw.h"
+#include "hostchan.h"
+
+#ifndef UNUSED
+#define UNUSED(x) (x = x) /* Silence compiler warnings for unused arguments */
+#endif
+
+#define HEARTRATE 5000000
+
+/*
+ * list of available drivers, declared in drivers.c
+ */
+extern DeviceDescr *devices[];
+
+static DeviceDescr *deviceToUse = NULL;
+
+static struct Channel {
+ ChannelCallback callback;
+ void *callback_state;
+} channels[CI_NUM_CHANNELS];
+
+static unsigned char HomeSeq;
+static unsigned char OppoSeq;
+
+/*
+ * Handler for DC_APPL packets
+ */
+static DC_Appl_Handler dc_appl_handler = NULL;
+
+/*
+ * slots for registered asynchronous processing callback procedures
+ */
+#define MAX_ASYNC_CALLBACKS 8
+static unsigned int num_async_callbacks = 0;
+static Adp_Async_Callback async_callbacks[MAX_ASYNC_CALLBACKS];
+
+/*
+ * writeQueueRoot is the queue of write requests pending acknowledgement
+ * writeQueueSend is the queue of pending write requests which will
+ * be a subset of the list writeQueueRoot
+ */
+static Packet *writeQueueRoot = NULL;
+static Packet *writeQueueSend = NULL;
+static Packet *resend_pkt = NULL;
+static int resending = FALSE;
+
+/* heartbeat_enabled is a flag used to indicate whether the heartbeat is
+ * currently turned on, heartbeat_enabled will be false in situations
+ * where even though a heartbeat is being used it is problematical or
+ * dis-advantageous to have it turned on, for instance during the
+ * initial stages of boot up
+ */
+unsigned int heartbeat_enabled = FALSE;
+/* heartbeat_configured is set up by the device driver to indicate whether
+ * the heartbeat is being used during this debug session. In contrast to
+ * heartbeat_enabled it must not be changed during a session. The logic for
+ * deciding whether to send a heartbeat is: Is heartbeat_configured for this
+ * session? if and only if it is then if heartbeat[is currently]_enabled and
+ * we are due to send a pulse then send it
+ */
+unsigned int heartbeat_configured = TRUE;
+
+void Adp_initSeq( void ) {
+ Packet *tmp_pkt = writeQueueSend;
+
+ HomeSeq = 0;
+ OppoSeq = 0;
+ if ( writeQueueSend != NULL) {
+ while (writeQueueSend->pk_next !=NULL) {
+ tmp_pkt = writeQueueSend;
+ writeQueueSend = tmp_pkt->pk_next;
+ DevSW_FreePacket(tmp_pkt);
+ }
+ }
+ tmp_pkt = writeQueueRoot;
+ if ( writeQueueRoot == NULL)
+ return;
+
+ while (writeQueueRoot->pk_next !=NULL) {
+ tmp_pkt = writeQueueRoot;
+ writeQueueRoot = tmp_pkt->pk_next;
+ DevSW_FreePacket(tmp_pkt);
+ }
+ return;
+}
+
+/**********************************************************************/
+
+/*
+ * Function: DummyCallback
+ * Purpose: Default callback routine to handle unexpected input
+ * on a channel
+ *
+ * Params:
+ * Input: packet The received packet
+ *
+ * state Contains nothing of significance
+ *
+ * Returns: Nothing
+ */
+static void DummyCallback(Packet *packet, void *state)
+{
+ ChannelID chan;
+ const char fmt[] = "Unexpected read on channel %u, length %d\n";
+ char fmtbuf[sizeof(fmt) + 24];
+
+ UNUSED(state);
+
+ chan = *(packet->pk_buffer);
+ sprintf(fmtbuf, fmt, chan, packet->pk_length);
+ printf(fmtbuf);
+
+ /*
+ * junk this packet
+ */
+ DevSW_FreePacket(packet);
+}
+
+/*
+ * Function: BlockingCallback
+ * Purpose: Callback routine used to implement a blocking read call
+ *
+ * Params:
+ * Input: packet The received packet.
+ *
+ * Output: state Address of higher level's pointer to the received
+ * packet.
+ *
+ * Returns: Nothing
+ */
+static void BlockingCallback(Packet *packet, void *state)
+{
+ /*
+ * Pass the packet back to the caller which requested a packet
+ * from this channel. This also flags the completion of the I/O
+ * request to the blocking read call.
+ */
+ *((Packet **)state) = packet;
+}
+
+/*
+ * Function: FireCallback
+ * Purpose: Pass received packet along to the callback routine for
+ * the appropriate channel
+ *
+ * Params:
+ * Input: packet The received packet.
+ *
+ * Returns: Nothing
+ *
+ * Post-conditions: The Target-to-Host sequence number for the channel
+ * will have been incremented.
+ */
+static void FireCallback(Packet *packet)
+{
+ ChannelID chan;
+ struct Channel *ch;
+
+ /*
+ * is this a sensible channel number?
+ */
+ chan = *(packet->pk_buffer);
+ if (invalidChannelID(chan))
+ {
+ printf("ERROR: invalid ChannelID received from target\n");
+
+ /*
+ * free the packet's resources, 'cause no-one else will
+ */
+ DevSW_FreePacket(packet);
+ return;
+ }
+
+ /*
+ * looks OK - increment sequence number, and pass packet to callback
+ */
+ ch = channels + chan;
+ (ch->callback)(packet, ch->callback_state);
+}
+
+/**********************************************************************/
+
+/*
+ * These are the externally visible functions. They are documented
+ * in hostchan.h
+ */
+void Adp_addToQueue(Packet **head, Packet *newpkt)
+{
+ /*
+ * this is a bit of a hack
+ */
+ Packet *pk;
+
+ /*
+ * make sure that the hack we are about to use will work as expected
+ */
+ ASSERT(&(((Packet *)0)->pk_next) == 0, "bad struct Packet layout");
+
+#if DEBUG && 0
+ printf("Adp_addToQueue(%p, %p)\n", head, newpkt);
+#endif
+
+ /*
+ * here's the hack - it relies upon the next
+ * pointer being at the start of Packet.
+ */
+ pk = (Packet *)(head);
+
+ /*
+ * skip to the end of the queue
+ */
+ while (pk->pk_next != NULL)
+ pk = pk->pk_next;
+
+ /*
+ * now add the new element
+ */
+ newpkt->pk_next = NULL;
+ pk->pk_next = newpkt;
+}
+
+Packet *Adp_removeFromQueue(Packet **head)
+{
+ struct Packet *pk;
+
+ pk = *head;
+
+ if (pk != NULL)
+ *head = pk->pk_next;
+
+ return pk;
+}
+
+AdpErrs Adp_OpenDevice(const char *name, const char *arg,
+ unsigned int heartbeat_on)
+{
+ int i;
+ AdpErrs retc;
+ ChannelID chan;
+
+#ifdef DEBUG
+ printf("Adp_OpenDevice(%s, %s)\n", name, arg ? arg : "<NULL>");
+#endif
+
+ heartbeat_configured = heartbeat_on;
+ if (deviceToUse != NULL)
+ return adp_device_already_open;
+
+ for (i = 0; (deviceToUse = devices[i]) != NULL; ++i)
+ if (DevSW_Match(deviceToUse, name, arg) == adp_ok)
+ break;
+
+ if (deviceToUse == NULL)
+ return adp_device_not_found;
+
+ /*
+ * we seem to have found a suitable device driver, so try to open it
+ */
+ if ((retc = DevSW_Open(deviceToUse, name, arg, DC_DBUG)) != adp_ok)
+ {
+ /* we don't have a device to use */
+ deviceToUse = NULL;
+ return retc;
+ }
+
+ /*
+ * there is no explicit open on channels any more, so
+ * initialise state for all channels.
+ */
+ for (chan = 0; chan < CI_NUM_CHANNELS; ++chan)
+ {
+ struct Channel *ch = channels + chan;
+
+ ch->callback = DummyCallback;
+ ch->callback_state = NULL;
+ OppoSeq = 0;
+ HomeSeq = 0;
+ }
+
+ return adp_ok;
+}
+
+AdpErrs Adp_CloseDevice(void)
+{
+ AdpErrs retc;
+
+#ifdef DEBUG
+ printf("Adp_CloseDevice\n");
+#endif
+
+ if (deviceToUse == NULL)
+ return adp_device_not_open;
+
+ heartbeat_enabled = FALSE;
+
+ retc = DevSW_Close(deviceToUse, DC_DBUG);
+
+ /*
+ * we have to clear deviceToUse, even when the lower layers
+ * faulted the close, otherwise the condition will never clear
+ */
+ if (retc != adp_ok)
+ WARN("DevSW_Close faulted the call");
+
+ deviceToUse = NULL;
+ return retc;
+}
+
+AdpErrs Adp_Ioctl(int opcode, void *args)
+{
+#ifdef DEBUG
+ printf("Adp_Ioctl\n");
+#endif
+
+ if (deviceToUse == NULL)
+ return adp_device_not_open;
+
+ return DevSW_Ioctl(deviceToUse, opcode, args);
+}
+
+AdpErrs Adp_ChannelRegisterRead(const ChannelID chan,
+ const ChannelCallback cbfunc,
+ void *cbstate)
+{
+#ifdef DEBUG
+ printf("Adp_ChannelRegisterRead(%d, %p, %x)\n", chan, cbfunc, cbstate);
+#endif
+
+ if (deviceToUse == NULL)
+ return adp_device_not_open;
+
+ if (invalidChannelID(chan))
+ return adp_bad_channel_id;
+
+ if (cbfunc == NULL)
+ {
+ channels[chan].callback = DummyCallback;
+ channels[chan].callback_state = NULL;
+ }
+ else
+ {
+ channels[chan].callback = cbfunc;
+ channels[chan].callback_state = cbstate;
+ }
+
+ return adp_ok;
+}
+
+AdpErrs Adp_ChannelRead(const ChannelID chan, Packet **packet)
+{
+ struct Channel *ch;
+
+#ifdef DEBUG
+ printf("Adp_ChannelRead(%d, %x)\n", chan, *packet);
+#endif
+
+ if (deviceToUse == NULL)
+ return adp_device_not_open;
+
+ if (invalidChannelID(chan))
+ return adp_bad_channel_id;
+
+ /*
+ * if a callback has already been registered for this
+ * channel, then we do not allow this blocking read.
+ */
+ ch = channels + chan;
+ if (ch->callback != DummyCallback)
+ return adp_callback_already_registered;
+
+ /*
+ * OK, use our own callback to wait for a packet to arrive
+ * on this channel
+ */
+ ch->callback = BlockingCallback;
+ ch->callback_state = packet;
+ *packet = NULL;
+
+ /*
+ * keep polling until a packet appears for this channel
+ */
+ while (((volatile Packet *)(*packet)) == NULL)
+ /*
+ * this call will block until a packet is read on any channel
+ */
+ Adp_AsynchronousProcessing(async_block_on_read);
+
+ /*
+ * OK, the packet has arrived: clear the callback
+ */
+ ch->callback = DummyCallback;
+ ch->callback_state = NULL;
+
+ return adp_ok;
+}
+
+static AdpErrs ChannelWrite(
+ const ChannelID chan, Packet *packet, AsyncMode mode)
+{
+ struct Channel *ch;
+ unsigned char *cptr;
+
+#ifdef DEBUG
+ printf( "Adp_ChannelWrite(%d, %x)\n", chan, packet );
+#endif
+
+ if (deviceToUse == NULL)
+ return adp_device_not_open;
+
+ if (invalidChannelID(chan))
+ return adp_bad_channel_id;
+
+ /*
+ * fill in the channels header at the start of this buffer
+ */
+ ch = channels + chan;
+ cptr = packet->pk_buffer;
+ *cptr++ = chan;
+ *cptr = 0;
+ packet->pk_length += CHAN_HEADER_SIZE;
+
+ /*
+ * OK, add this packet to the write queue, and try to flush it out
+ */
+
+ Adp_addToQueue(&writeQueueSend, packet);
+ Adp_AsynchronousProcessing(mode);
+
+ return adp_ok;
+}
+
+AdpErrs Adp_ChannelWrite(const ChannelID chan, Packet *packet) {
+ return ChannelWrite(chan, packet, async_block_on_write);
+}
+
+AdpErrs Adp_ChannelWriteAsync(const ChannelID chan, Packet *packet) {
+ return ChannelWrite(chan, packet, async_block_on_nothing);
+}
+
+static AdpErrs send_resend_msg(DeviceID devid) {
+
+ /*
+ * Send a resend message, usually in response to a bad packet or
+ * a resend request */
+ Packet * packet;
+ packet = DevSW_AllocatePacket(CF_DATA_BYTE_POS);
+ packet->pk_buffer[CF_CHANNEL_BYTE_POS] = CI_PRIVATE;
+ packet->pk_buffer[CF_HOME_SEQ_BYTE_POS] = HomeSeq;
+ packet->pk_buffer[CF_OPPO_SEQ_BYTE_POS] = OppoSeq;
+ packet->pk_buffer[CF_FLAGS_BYTE_POS] = CF_RELIABLE | CF_RESEND;
+ packet->pk_length = CF_DATA_BYTE_POS;
+ return DevSW_Write(deviceToUse, packet, devid);
+}
+
+static AdpErrs check_seq(unsigned char msg_home, unsigned char msg_oppo) {
+ Packet *tmp_pkt;
+
+ UNUSED(msg_oppo);
+ /*
+ * check if we have got an ack for anything and if so remove it from the
+ * queue
+ */
+ if (msg_home == (unsigned char)(OppoSeq+1)) {
+ /*
+ * arrived in sequence can increment our opposing seq number and remove
+ * the relevant packet from our queue
+ * check that the packet we're going to remove really is the right one
+ */
+ tmp_pkt = writeQueueRoot;
+ while ((tmp_pkt->pk_next != NULL) &&
+ (tmp_pkt->pk_next->pk_buffer[CF_HOME_SEQ_BYTE_POS]
+ != OppoSeq)){
+ tmp_pkt = tmp_pkt->pk_next;
+ }
+ OppoSeq++;
+ if (tmp_pkt->pk_next == NULL) {
+#ifdef DEBUG
+ printf("trying to remove a non existant packet\n");
+#endif
+ return adp_bad_packet;
+ }
+ else {
+ Packet *tmp = tmp_pkt->pk_next;
+#ifdef RET_DEBUG
+ printf("removing a packet from the root queue\n");
+#endif
+ tmp_pkt->pk_next = tmp_pkt->pk_next->pk_next;
+ /* remove the appropriate packet */
+ DevSW_FreePacket(tmp);
+ return adp_ok;
+ }
+ }
+ else if (msg_home < (unsigned char) (OppoSeq+1)){
+ /* already received this message */
+#ifdef RET_DEBUG
+ printf("sequence numbers low\n");
+#endif
+ return adp_seq_low;
+ }
+ else { /* we've missed something */
+#ifdef RET_DEBUG
+ printf("sequence numbers high\n");
+#endif
+ return adp_seq_high;
+ }
+}
+
+static unsigned long tv_diff(const struct timeval *time_now,
+ const struct timeval *time_was)
+{
+ return ( ((time_now->tv_sec * 1000000) + time_now->tv_usec)
+ - ((time_was->tv_sec * 1000000) + time_was->tv_usec) );
+}
+
+#if !defined(__unix) && !defined(__CYGWIN32__)
+static void gettimeofday( struct timeval *time_now, void *dummy )
+{
+ time_t t = clock();
+ UNUSED(dummy);
+ time_now->tv_sec = t/CLOCKS_PER_SEC;
+ time_now->tv_usec = (t%CLOCKS_PER_SEC)*(1000000/CLOCKS_PER_SEC);
+}
+#endif
+
+static AdpErrs pacemaker(void)
+{
+ Packet *packet;
+
+ packet = DevSW_AllocatePacket(CF_DATA_BYTE_POS);
+ if (packet == NULL) {
+ printf("ERROR: could not allocate a packet in pacemaker()\n");
+ return adp_malloc_failure;
+ }
+ packet->pk_buffer[CF_CHANNEL_BYTE_POS] = CI_PRIVATE;
+ packet->pk_buffer[CF_HOME_SEQ_BYTE_POS] = HomeSeq;
+ packet->pk_buffer[CF_OPPO_SEQ_BYTE_POS] = OppoSeq;
+ packet->pk_buffer[CF_FLAGS_BYTE_POS] = CF_RELIABLE | CF_HEARTBEAT;
+ packet->pk_length = CF_DATA_BYTE_POS;
+ return DevSW_Write(deviceToUse, packet, DC_DBUG);
+}
+
+#ifdef FAKE_BAD_LINE_RX
+static AdpErrs fake_bad_line_rx( const Packet *const packet, AdpErrs adp_err )
+{
+ static unsigned int bl_num = 0;
+
+ if ( (packet != NULL)
+ && (bl_num++ >= 20 )
+ && ((bl_num % FAKE_BAD_LINE_RX) == 0))
+ {
+ printf("DEBUG: faking a bad packet\n");
+ return adp_bad_packet;
+ }
+ return adp_err;
+}
+#endif /* def FAKE_BAD_LINE_RX */
+
+#ifdef FAKE_BAD_LINE_TX
+static unsigned char tmp_ch;
+
+static void fake_bad_line_tx( void )
+{
+ static unsigned int bl_num = 0;
+
+ /* give the thing a chance to boot then try corrupting stuff */
+ if ( (bl_num++ >= 20) && ((bl_num % FAKE_BAD_LINE_TX) == 0))
+ {
+ printf("DEBUG: faking a bad packet for tx\n");
+ tmp_ch = writeQueueSend->pk_buffer[CF_FLAGS_BYTE_POS];
+ writeQueueSend->pk_buffer[CF_FLAGS_BYTE_POS] = 77;
+ }
+}
+
+static void unfake_bad_line_tx( void )
+{
+ static unsigned int bl_num = 0;
+
+ /*
+ * must reset the packet so that its not corrupted when we
+ * resend it
+ */
+ if ( (bl_num >= 20) && ((bl_num % FAKE_BAD_LINE_TX) != 0))
+ {
+ writeQueueSend->pk_buffer[CF_FLAGS_BYTE_POS] = tmp_ch;
+ }
+}
+#endif /* def FAKE_BAD_LINE_TX */
+
+/*
+ * NOTE: we are assuming that a resolution of microseconds will
+ * be good enough for the purporses of the heartbeat. If this proves
+ * not to be the case then we may need a rethink, possibly using
+ * [get,set]itimer
+ */
+static struct timeval time_now;
+static struct timeval time_lastalive;
+
+static void async_process_dbug_read( const AsyncMode mode,
+ bool *const finished )
+{
+ Packet *packet;
+ unsigned int msg_home, msg_oppo;
+ AdpErrs adp_err;
+
+ adp_err = DevSW_Read(deviceToUse, DC_DBUG, &packet,
+ mode == async_block_on_read );
+
+#ifdef FAKE_BAD_LINE_RX
+ adp_err = fake_bad_line_rx( packet, adp_err );
+#endif
+
+ if (adp_err == adp_bad_packet) {
+ /* We got a bad packet, ask for a resend, send a resend message */
+#ifdef DEBUG
+ printf("received a bad packet\n");
+#endif
+ send_resend_msg(DC_DBUG);
+ }
+ else if (packet != NULL)
+ {
+ /* update the heartbeat clock */
+ gettimeofday(&time_lastalive, NULL);
+
+ /*
+ * we got a live one here - were we waiting for it?
+ */
+ if (mode == async_block_on_read)
+ /* not any more */
+ *finished = TRUE;
+#ifdef RETRANS
+
+ if (packet->pk_length < CF_DATA_BYTE_POS) {
+ /* we've got a packet with no header information! */
+ printf("ERROR: packet with no transport header\n");
+ send_resend_msg(DC_DBUG);
+ }
+ else {
+#ifdef RET_DEBUG
+ unsigned int c;
+#endif
+ /*
+ * TODO: Check to see if its acknowledgeing anything, remove
+ * those packets it is from the queue. If its a retrans add the
+ * packets to the queue
+ */
+ msg_home = packet->pk_buffer[CF_HOME_SEQ_BYTE_POS];
+ msg_oppo = packet->pk_buffer[CF_OPPO_SEQ_BYTE_POS];
+#ifdef RET_DEBUG
+ printf("msg seq numbers are hseq 0x%x oseq 0x%x\n",
+ msg_home, msg_oppo);
+ for (c=0;c<packet->pk_length;c++)
+ printf("%02.2x", packet->pk_buffer[c]);
+ printf("\n");
+#endif
+ /* now was it a resend request? */
+ if ((packet->pk_buffer[CF_FLAGS_BYTE_POS])
+ & CF_RESEND) {
+ /* we've been asked for a resend so we had better resend */
+ /*
+ * I don't think we can use a resend as acknowledgement for
+ * anything so lets not do this for the moment
+ * check_seq(msg_home, msg_oppo);
+ */
+#ifdef RET_DEBUG
+ printf("received a resend request\n");
+#endif
+ if (HomeSeq != msg_oppo) {
+ int found = FALSE;
+ /* need to resend from msg_oppo +1 upwards */
+ DevSW_FreePacket(packet);
+ resending = TRUE;
+ /* find the correct packet to resend from */
+ packet = writeQueueRoot;
+ while (((packet->pk_next) != NULL) && !found) {
+ if ((packet->pk_buffer[CF_OPPO_SEQ_BYTE_POS])
+ != msg_oppo+1) {
+ resend_pkt = packet;
+ found = TRUE;
+ }
+ packet = packet->pk_next;
+ }
+ if (!found) {
+ panic("trying to resend non-existent packets\n");
+ }
+ }
+ else if (OppoSeq != msg_home) {
+ /*
+ * send a resend request telling the target where we think
+ * the world is at
+ */
+ DevSW_FreePacket(packet);
+ send_resend_msg(DC_DBUG);
+ }
+ }
+ else {
+ /* not a resend request, lets check the sequence numbers */
+
+ if ((packet->pk_buffer[CF_CHANNEL_BYTE_POS] != CI_HBOOT) &&
+ (packet->pk_buffer[CF_CHANNEL_BYTE_POS] != CI_TBOOT)) {
+ adp_err = check_seq(msg_home, msg_oppo);
+ if (adp_err == adp_seq_low) {
+ /* we have already received this packet so discard */
+ DevSW_FreePacket(packet);
+ }
+ else if (adp_err == adp_seq_high) {
+ /*
+ * we must have missed a packet somewhere, discard this
+ * packet and tell the target where we are
+ */
+ DevSW_FreePacket(packet);
+ send_resend_msg(DC_DBUG);
+ }
+ else
+ /*
+ * now pass the packet to whoever is waiting for it
+ */
+ FireCallback(packet);
+ }
+ else
+ FireCallback(packet);
+ }
+ }
+#else
+ /*
+ * now pass the packet to whoever is waiting for it
+ */
+ FireCallback(packet);
+#endif
+ }
+}
+
+static void async_process_appl_read(void)
+{
+ Packet *packet;
+ AdpErrs adp_err;
+
+ /* see if there is anything for the DC_APPL channel */
+ adp_err = DevSW_Read(deviceToUse, DC_APPL, &packet, FALSE);
+
+ if (adp_err == adp_ok && packet != NULL)
+ {
+ /* got an application packet on a shared device */
+
+#ifdef DEBUG
+ printf("GOT DC_APPL PACKET: len %d\nData: ", packet->pk_length);
+ {
+ unsigned int c;
+ for ( c = 0; c < packet->pk_length; ++c )
+ printf( "%02X ", packet->pk_buffer[c] );
+ }
+ printf("\n");
+#endif
+
+ if (dc_appl_handler != NULL)
+ {
+ dc_appl_handler( deviceToUse, packet );
+ }
+ else
+ {
+ /* for now, just free it!! */
+#ifdef DEBUG
+ printf("no handler - dropping DC_APPL packet\n");
+#endif
+ DevSW_FreePacket( packet );
+ }
+ }
+}
+
+static void async_process_write( const AsyncMode mode,
+ bool *const finished )
+{
+ Packet *packet;
+
+#ifdef DEBUG
+ static unsigned int num_written = 0;
+#endif
+
+ /*
+ * NOTE: here we rely in the fact that any packet in the writeQueueSend
+ * section of the queue will need its sequence number setting up while
+ * and packet in the writeQueueRoot section will have its sequence
+ * numbers set up from when it was first sent so we can easily look
+ * up the packet numbers when(if) we want to resend the packet.
+ */
+
+#ifdef DEBUG
+ if (writeQueueSend!=NULL)
+ printf("written 0x%x\n",num_written += writeQueueSend->pk_length);
+#endif
+ /*
+ * give the switcher a chance to complete any partial writes
+ */
+ if (DevSW_FlushPendingWrite(deviceToUse) == adp_write_busy)
+ {
+ /* no point trying a new write */
+ return;
+ }
+
+ /*
+ * now see whether there is anything to write
+ */
+ packet = NULL;
+ if (resending) {
+ packet = resend_pkt;
+#ifdef RET_DEBUG
+ printf("resending hseq 0x%x oseq 0x%x\n",
+ packet->pk_buffer[CF_HOME_SEQ_BYTE_POS],
+ packet->pk_buffer[CF_OPPO_SEQ_BYTE_POS]);
+#endif
+ }
+ else if (writeQueueSend != NULL) {
+#ifdef RETRANS
+ /* set up the sequence number on the packet */
+ packet = writeQueueSend;
+ HomeSeq++;
+ (writeQueueSend->pk_buffer[CF_OPPO_SEQ_BYTE_POS])
+ = OppoSeq;
+ (writeQueueSend->pk_buffer[CF_HOME_SEQ_BYTE_POS])
+ = HomeSeq;
+ (writeQueueSend->pk_buffer[CF_FLAGS_BYTE_POS])
+ = CF_RELIABLE;
+# ifdef RET_DEBUG
+ printf("sending packet with hseq 0x%x oseq 0x%x\n",
+ writeQueueSend->pk_buffer[CF_HOME_SEQ_BYTE_POS],
+ writeQueueSend->pk_buffer[CF_OPPO_SEQ_BYTE_POS]);
+# endif
+#endif /* RETRANS */
+ }
+
+ if (packet != NULL) {
+ AdpErrs dev_err;
+
+#ifdef FAKE_BAD_LINE_TX
+ fake_bad_line_tx();
+#endif
+
+ dev_err = DevSW_Write(deviceToUse, packet, DC_DBUG);
+ if (dev_err == adp_ok) {
+#ifdef RETRANS
+ if (resending) {
+ /* check to see if we've recovered yet */
+ if ((packet->pk_next) == NULL){
+# ifdef RET_DEBUG
+ printf("we have recovered\n");
+# endif
+ resending = FALSE;
+ }
+ else {
+ resend_pkt = resend_pkt->pk_next;
+ }
+ }
+ else {
+ /*
+ * move the packet we just sent from the send queue to the root
+ */
+ Packet *tmp_pkt, *tmp;
+
+# ifdef FAKE_BAD_LINE_TX
+ unfake_bad_line_tx();
+# endif
+
+ tmp_pkt = writeQueueSend;
+ writeQueueSend = writeQueueSend->pk_next;
+ tmp_pkt->pk_next = NULL;
+ if (writeQueueRoot == NULL)
+ writeQueueRoot = tmp_pkt;
+ else {
+ tmp = writeQueueRoot;
+ while (tmp->pk_next != NULL) {
+ tmp = tmp->pk_next;
+ }
+ tmp->pk_next = tmp_pkt;
+ }
+ }
+#else /* not RETRANS */
+ /*
+ * switcher has taken the write, so remove it from the
+ * queue, and free its resources
+ */
+ DevSW_FreePacket(Adp_removeFromQueue(&writeQueueSend));
+#endif /* if RETRANS ... else ... */
+
+ if (mode == async_block_on_write)
+ *finished = DevSW_WriteFinished(deviceToUse);
+
+ } /* endif write ok */
+ }
+ else /* packet == NULL */
+ {
+ if (mode == async_block_on_write)
+ *finished = DevSW_WriteFinished(deviceToUse);
+ }
+}
+
+static void async_process_heartbeat( void )
+{
+ /* check to see whether we need to send a heartbeat */
+ gettimeofday(&time_now, NULL);
+
+ if (tv_diff(&time_now, &time_lastalive) >= HEARTRATE)
+ {
+ /*
+ * if we've not booted then don't do send a heartrate the link
+ * must be reliable enough for us to boot without any clever stuff,
+ * if we can't do this then theres little chance of the link staying
+ * together even with the resends etc
+ */
+ if (heartbeat_enabled) {
+ gettimeofday(&time_lastalive, NULL);
+ pacemaker();
+ }
+ }
+}
+
+static void async_process_callbacks( void )
+{
+ /* call any registered asynchronous callbacks */
+ unsigned int i;
+ for ( i = 0; i < num_async_callbacks; ++i )
+ async_callbacks[i]( deviceToUse, &time_now );
+}
+
+void Adp_AsynchronousProcessing(const AsyncMode mode)
+{
+ bool finished = FALSE;
+#ifdef DEBUG
+ unsigned int wc = 0, dc = 0, ac = 0, hc = 0;
+# define INC_COUNT(x) ((x)++)
+#else
+# define INC_COUNT(x)
+#endif
+
+ if ((time_lastalive.tv_sec == 0) && (time_lastalive.tv_usec == 0)) {
+ /* first time through, needs initing */
+ gettimeofday(&time_lastalive, NULL);
+ }
+
+ /* main loop */
+ do
+ {
+ async_process_write( mode, &finished );
+ INC_COUNT(wc);
+
+ if ( ! finished && mode != async_block_on_write )
+ {
+ async_process_dbug_read( mode, &finished );
+ INC_COUNT(dc);
+ }
+
+ if ( ! finished && mode != async_block_on_write )
+ {
+ async_process_appl_read();
+ INC_COUNT(ac);
+ }
+
+ if ( ! finished )
+ {
+ if (heartbeat_configured)
+ async_process_heartbeat();
+ async_process_callbacks();
+ INC_COUNT(hc);
+ }
+
+ } while (!finished && mode != async_block_on_nothing);
+
+#ifdef DEBUG
+ if ( mode != async_block_on_nothing )
+ printf( "Async: %s - w %d, d %d, a %d, h %d\n",
+ mode == async_block_on_write ? "blk_write" : "blk_read",
+ wc, dc, ac, hc );
+#endif
+}
+
+/*
+ * install a handler for DC_APPL packets (can be NULL), returning old one.
+ */
+DC_Appl_Handler Adp_Install_DC_Appl_Handler(const DC_Appl_Handler handler)
+{
+ DC_Appl_Handler old_handler = dc_appl_handler;
+
+#ifdef DEBUG
+ printf( "Installing DC_APPL handler %x (old %x)\n", handler, old_handler );
+#endif
+
+ dc_appl_handler = handler;
+ return old_handler;
+}
+
+
+/*
+ * add an asynchronous processing callback to the list
+ * TRUE == okay, FALSE == no more async processing slots
+ */
+bool Adp_Install_Async_Callback( const Adp_Async_Callback callback_proc )
+{
+ if ( num_async_callbacks < MAX_ASYNC_CALLBACKS && callback_proc != NULL )
+ {
+ async_callbacks[num_async_callbacks] = callback_proc;
+ ++num_async_callbacks;
+ return TRUE;
+ }
+ else
+ return FALSE;
+}
+
+
+/*
+ * delay for a given period (in microseconds)
+ */
+void Adp_delay(unsigned int period)
+{
+ struct timeval tv;
+
+#ifdef DEBUG
+ printf("delaying for %d microseconds\n", period);
+#endif
+ tv.tv_sec = (period / 1000000);
+ tv.tv_usec = (period % 1000000);
+
+ (void)select(0, NULL, NULL, NULL, &tv);
+}
+
+/* EOF hostchan.c */
diff --git a/gdb/rdi-share/hostchan.h b/gdb/rdi-share/hostchan.h
new file mode 100644
index 00000000000..44563a6112a
--- /dev/null
+++ b/gdb/rdi-share/hostchan.h
@@ -0,0 +1,308 @@
+/*
+ * Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
+ *
+ * This software may be freely used, copied, modified, and distributed
+ * provided that the above copyright notice is preserved in all copies of the
+ * software.
+ */
+
+/* -*-C-*-
+ *
+ * $Revision$
+ * $Date$
+ *
+ */
+#ifndef angsd_hostchan_h
+#define angsd_hostchan_h
+
+/* If under Cygwin, provide backwards compatibility with older
+ Cygwin compilers that don't define the current cpp define. */
+#ifdef __CYGWIN32__
+#ifndef __CYGWIN__
+#define __CYGWIN__
+#endif
+#endif
+
+/* struct timeval */
+#if defined(__unix) || defined(__CYGWIN32__)
+# include <sys/time.h>
+#else
+# include "winsock.h"
+# include "time.h"
+#endif
+
+#include "chandefs.h"
+#include "adperr.h"
+#include "devsw.h"
+
+/*
+ * asynchronous processing modes
+ */
+enum AsyncMode
+{
+ async_block_on_nothing,
+ async_block_on_read,
+ async_block_on_write
+};
+
+#ifndef __cplusplus
+typedef enum AsyncMode AsyncMode;
+#endif
+
+/*
+ * prototype for channels callback function
+ */
+typedef void (*ChannelCallback)(Packet *packet, void *state);
+
+/*
+ * Function: Adp_initSeq
+ * Purpose: initialise the channel protocol and sequence numbers
+ *
+ * Params: none
+ *
+ * Returns: Nothing
+ */
+extern void Adp_initSeq(void);
+
+/*
+ * Function: Adp_addToQueue
+ * Purpose: chain a Packet to the end of a linked list of such structures
+ *
+ * Params:
+ * In/Out: head Head of the linked list
+ *
+ * newpkt Packet to be chained onto the list
+ *
+ * Returns: Nothing
+ */
+extern void Adp_addToQueue(Packet **head, Packet *newpkt);
+
+/*
+ * Function: removeFromQueue
+ * Purpose: remove a Packet from the head of a linked list of such structures
+ *
+ * Params:
+ * In/Out: head Head of the linked list
+ *
+ * Returns: Old head from the linked list
+ *
+ * Post-conditions: Second element in the list will be the new head.
+ */
+
+extern Packet *Adp_removeFromQueue(Packet **head);
+
+/*
+ * Function: Adp_OpenDevice
+ * Purpose: Open a device to use for channels communication. This is a
+ * very thin veneer to the device drivers: what hostchan.c
+ * will do is call DeviceMatch for each device driver until it
+ * finds a driver that will accept name and arg, then call
+ * DeviceOpen for that device.
+ *
+ * Pre-conditions: No previous open is still active
+ *
+ * Params:
+ * Input: name Identifies which device to open. This can either be
+ * a host specific identifier (e.g. "/dev/ttya",
+ * "COM1:"), or a number which is used to refer to
+ * `standard' interfaces, so "1" would be the first host
+ * interface, "2" the second, and so on.
+ *
+ * arg Driver specific arguments. For example, some serial
+ * drivers accept speed and control arguments such as
+ * "9600" or "19200/NO_BREAK". These arguments are
+ * completely free-form: it is the individual drivers
+ * which do the necessary interpretation.
+ *
+ * heartbeat_on Incicates if the heartbeat is configured to be
+ * used or not, true if it is, false otherwise
+ *
+ * Returns:
+ * OK: adp_ok
+ * Error: adp_device_not_known,
+ * adp_device_open_failed
+ * adp_device_already_open
+ */
+AdpErrs Adp_OpenDevice(const char *name, const char *arg,
+ unsigned int heartbeat_on);
+
+/*
+ * Function: Adp_CloseDevice
+ * Purpose: Close the device used for channels communication.
+ *
+ * Params: None
+ *
+ * Returns:
+ * OK: adp_ok
+ * Error: adp_device_not_open
+ */
+AdpErrs Adp_CloseDevice(void);
+
+/*
+ * Function: Adp_Ioctl
+ * Purpose: Perform miscellaneous control operations on
+ * the device used for channels communication.
+ * This is a minimal veneer to DevSW_Ioctl.
+ *
+ * Params:
+ * Input: opcode Reason code indicating the operation to perform.
+ * In/Out: args Pointer to opcode-sensitive arguments/result space.
+ *
+ *
+ * Returns:
+ * OK: adp_ok
+ * Error: adp_device_not_open, adp_failed
+ */
+AdpErrs Adp_Ioctl(int opcode, void *args);
+
+/*
+ * Function: Adp_ChannelRegisterRead
+ * Purpose: Register a callback function for received packets on a given
+ * channel
+ *
+ * Params:
+ * Input: chan The channel the callback function is for.
+ *
+ * cbfunc The callback function. If NULL, then the current
+ * callback is removed.
+ *
+ * cbstate State pointer to pass into the callback function
+ *
+ * Returns:
+ * OK: adp_ok
+ * Error: adp_device_not_open
+ * adp_bad_channel_id
+ *
+ * Post-conditions: The callback function is responsible for freeing the
+ * packet that is passed to it, when that packet is
+ * no longer needed.
+ */
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+
+extern AdpErrs Adp_ChannelRegisterRead(const ChannelID chan,
+ const ChannelCallback cbfunc,
+ void *cbstate);
+
+#ifdef __cplusplus
+ }
+#endif
+/*
+ * Function: Adp_ChannelRead
+ * Purpose: Wait until a packet has been read for a given channel, and
+ * then return it. Callbacks for other channels are still
+ * active while this read is blocking.
+ *
+ * Pre-conditions: No callback has been already been registered for
+ * the channel.
+ *
+ * Params:
+ * Input: chan The channel to read.
+ *
+ * Output: packet The received packet.
+ *
+ * Returns:
+ * OK: adp_ok
+ * Error: adp_device_not_open
+ * adp_bad_channel_id
+ * adp_callback_already_registered
+ *
+ * Post-conditions: The calling function is responsible for freeing the
+ * received packet, when that packet is no longer
+ * needed.
+ */
+AdpErrs Adp_ChannelRead(const ChannelID chan, Packet **packet);
+
+/*
+ * Function: Adp_ChannelWrite
+ * Purpose: Write a packet to the given channel
+ *
+ * Pre-conditions: Channel must have been previously opened.
+ *
+ * Params:
+ * Input: chan The channel to write.
+ *
+ * packet The packet to write.
+ *
+ * Returns:
+ * OK: adp_ok
+ * Error: adp_device_not_open
+ * adp_bad_channel_id
+ *
+ * Post-conditions: The packet being written becomes the "property" of
+ * Adp_ChannelWrite, which is responsible for freeing
+ * the packet when it is no longer needed.
+ */
+AdpErrs Adp_ChannelWrite(const ChannelID chan, Packet *packet);
+
+/*
+ * Function: Adp_ChannelWriteAsync
+ * Purpose: Write a packet to the given channel, but don't wait
+ * for the write to complete before returning.
+ *
+ * Pre-conditions: Channel must have been previously opened.
+ *
+ * Params:
+ * Input: chan The channel to write.
+ *
+ * packet The packet to write.
+ *
+ * Returns:
+ * OK: adp_ok
+ * Error: adp_device_not_open
+ * adp_bad_channel_id
+ *
+ * Post-conditions: The packet being written becomes the "property" of
+ * Adp_ChannelWrite, which is responsible for freeing
+ * the packet when it is no longer needed.
+ */
+AdpErrs Adp_ChannelWriteAsync(const ChannelID chan, Packet *packet);
+
+/*
+ * Function: Adp_AsynchronousProcessing
+ * Purpose: This routine should be called from persistent any idle loop
+ * to give the data I/O routines a chance to poll for packet
+ * activity. Depending upon the requested mode, this routine
+ * may, or may not, block.
+ *
+ * Params:
+ * Input: mode Specifies whether to block until a complete packet
+ * has been read, all pending writes have completed,
+ * or not to block at all.
+ *
+ * Returns: Nothing.
+ */
+void Adp_AsynchronousProcessing(const AsyncMode mode);
+
+/*
+ * prototype for DC_APPL packet handler
+ */
+typedef void (*DC_Appl_Handler)(const DeviceDescr *device, Packet *packet);
+
+/*
+ * install a handler for DC_APPL packets (can be NULL), returning old one.
+ */
+DC_Appl_Handler Adp_Install_DC_Appl_Handler(const DC_Appl_Handler handler);
+
+/*
+ * prototype for asynchronous processing callback
+ */
+typedef void (*Adp_Async_Callback)(const DeviceDescr *device,
+ const struct timeval *const time_now);
+
+/*
+ * add an asynchronous processing callback to the list
+ * TRUE == okay, FALSE == no more async processing slots
+ */
+bool Adp_Install_Async_Callback( const Adp_Async_Callback callback_proc );
+
+/*
+ * delay for a given period (in microseconds)
+ */
+void Adp_delay(unsigned int period);
+
+#endif /* ndef angsd_hostchan_h */
+
+/* EOF hostchan.h */
diff --git a/gdb/rdi-share/hsys.c b/gdb/rdi-share/hsys.c
new file mode 100644
index 00000000000..ef42a309b94
--- /dev/null
+++ b/gdb/rdi-share/hsys.c
@@ -0,0 +1,915 @@
+/*
+ * Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
+ *
+ * This software may be freely used, copied, modified, and distributed
+ * provided that the above copyright notice is preserved in all copies of the
+ * software.
+ */
+
+/*
+ * Host C Library support functions.
+ *
+ * $Revision$
+ * $Date$
+ */
+
+#ifdef DEBUG
+# include <ctype.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <errno.h>
+#include <time.h>
+
+#include "adp.h"
+#include "host.h"
+#include "ardi.h"
+#include "buffers.h"
+#include "channels.h" /* Channel interface. */
+#include "endian.h"
+#include "logging.h" /* Angel support functions. */
+#include "msgbuild.h"
+#include "sys.h"
+#include "hsys.h" /* Function and structure declarations. */
+#include "hostchan.h"
+
+#define FILEHANDLE int
+
+/* Note: no statics allowed. All globals must be malloc()ed on the heap.
+ The state struct is used for this purpose. See 'hsys.h'. */
+/* This is the message handler function passed to the channel manager in
+ HostSysInit. It is called whenever a message is received. 'buffptr'
+ points to the message body. Functionality is provided by the debugger
+ toolkit. The routine is very loosely based on the HandleSWI routine from
+ armos.c in the armulator source. */
+/* These routines could be tested by providing a simple interface to armsd,
+ and running them in that. */
+
+
+/* taken staight from armulator source */
+#ifdef __riscos
+ extern int _fisatty(FILE *);
+# define isatty_(f) _fisatty(f)
+# define EMFILE -1
+# define EBADF -1
+ int _kernel_escape_seen(void) { return 0 ;}
+#else
+# if defined(_WINDOWS) || defined(_CONSOLE)
+# define isatty_(f) (f == stdin || f == stdout)
+# else
+# ifdef __ZTC__
+# include <io.h>
+# define isatty_(f) isatty((f)->_file)
+# else
+# ifdef macintosh
+# include <ioctl.h>
+# define isatty_(f) (~ioctl((f)->_file,FIOINTERACTIVE,NULL))
+# else
+# define isatty_(f) isatty(fileno(f))
+# endif
+# endif
+# endif
+#endif
+
+/* Set up the state block, filetable and register the C lib callback fn */
+int HostSysInit(const struct Dbg_HostosInterface *hostif, char **cmdline,
+ hsys_state **stateptr)
+{
+ ChannelCallback HandleMessageFPtr = (ChannelCallback) HandleSysMessage;
+ int i;
+ *stateptr = (hsys_state *)malloc(sizeof(hsys_state));
+
+ if (*stateptr == NULL) return RDIError_OutOfStore;
+
+ (*stateptr)->hostif=hostif;
+ (*stateptr)->last_errno=0;
+ (*stateptr)->OSptr=(OSblock *)malloc(sizeof(OSblock));
+ if ((*stateptr)->OSptr == NULL) return RDIError_OutOfStore;
+ for (i=0; i<UNIQUETEMPS; i++) (*stateptr)->OSptr->TempNames[i]=NULL;
+ for (i=0; i<HSYS_FOPEN_MAX; i++) {
+ (*stateptr)->OSptr->FileTable[i]=NULL;
+ (*stateptr)->OSptr->FileFlags[i]=0;
+ }
+ (*stateptr)->CommandLine=cmdline;
+
+ return Adp_ChannelRegisterRead(CI_CLIB, (ChannelCallback)HandleMessageFPtr,
+ *stateptr);
+}
+
+/* Shut down the Clib support, this will probably never get called though */
+int HostSysExit(hsys_state *stateptr)
+{
+ free(stateptr->OSptr);
+ free(stateptr);
+ return RDIError_NoError;
+}
+
+#ifdef DEBUG
+static void DebugCheckNullTermString(char *prefix, bool nl,
+ unsigned int len, unsigned char *strp)
+{
+ printf("%s: %d: ", prefix, len);
+ if (strp[len]=='\0')
+ printf("\"%s\"", strp);
+ else
+ printf("NOT NULL TERMINATED");
+ if (nl)
+ printf("\n");
+ else
+ {
+ printf(" ");
+ fflush(stdout);
+ }
+}
+
+extern int sys_nerr;
+extern char *sys_errlist[];
+
+static char *DebugStrError(int last_errno)
+{
+ if (last_errno < sys_nerr)
+ return sys_errlist[last_errno];
+ else
+ return "NO MSG (errno>sys_nerr)";
+}
+
+static void DebugCheckErr(char *prefix, bool nl, int err, int last_errno)
+{
+ printf("\t%s: returned ", prefix);
+ if (err == 0)
+ printf("okay");
+ else
+ printf("%d, errno = %d \"%s\"", err, last_errno,
+ DebugStrError(last_errno));
+ if (nl)
+ printf("\n");
+ else
+ {
+ printf(" ");
+ fflush(stdout);
+ }
+}
+
+static void DebugCheckNonNull(char *prefix, bool nl,
+ void *handle, int last_errno)
+{
+ printf("\t%s: returned ", prefix);
+ if (handle != NULL)
+ printf("okay [%08x]", (unsigned int)handle);
+ else
+ printf("NULL, errno = %d \"%s\"", last_errno,
+ DebugStrError(last_errno));
+ if (nl)
+ printf("\n");
+ else
+ {
+ printf(" ");
+ fflush(stdout);
+ }
+}
+
+#define DebugPrintF(c) printf c;
+
+#else
+
+#define DebugCheckNullTermString(p, n, l, s) ((void)(0))
+#define DebugCheckErr(p, n, e, l) ((void)(0))
+#define DebugCheckNonNull(p, n, h, l) ((void)(0))
+#define DebugPrintF(c) ((void)(0))
+
+#endif /* ifdef DEBUG ... else */
+
+static FILE *hsysGetRealFileHandle(hsys_state *stateptr, int fh, char *flags)
+{
+ FILE *file_p = NULL;
+
+ if (fh < 0 || fh >= HSYS_FOPEN_MAX)
+ {
+ stateptr->last_errno = EBADF;
+ DebugPrintF(("\tfh %d out-of-bounds!\n", fh));
+ return NULL;
+ }
+ else
+ {
+ file_p = stateptr->OSptr->FileTable[fh];
+ if (file_p != NULL) {
+ if (flags != NULL)
+ *flags = stateptr->OSptr->FileFlags[fh];
+ }
+ else {
+ stateptr->last_errno = EBADF;
+ DebugPrintF(("\tFileTable[%d] is NULL\n", fh));
+ }
+
+ return file_p;
+ }
+}
+
+int HandleSysMessage(Packet *packet, hsys_state *stateptr)
+{
+ unsigned int reason_code, mode, len, c, nbytes, nbtotal, nbtogo = 0;
+ long posn, fl;
+ char character;
+ int err;
+
+ /* Note: We must not free the buffer passed in as the callback handler */
+ /* expects to do this. Freeing any other buffers we have malloced */
+ /* ourselves is acceptable */
+
+ unsigned char *buffp = ((unsigned char *)BUFFERDATA(packet->pk_buffer))+16;
+ /* buffp points to the parameters*/
+ /* the invidual messages, excluding*/
+ /* standard SYS fields (debugID, */
+ /* osinfo and reasoncode) */
+ unsigned char *buffhead = (unsigned char *)(packet->pk_buffer);
+
+ int DebugID, OSInfo1, OSInfo2, count;
+
+ const char* fmode[] = {"r","rb","r+","r+b",
+ "w","wb","w+","w+b",
+ "a","ab","a+","a+b",
+ "r","r","r","r"} /* last 4 are illegal */ ;
+
+ FILEHANDLE fh; /* fh is used as an index to the real file handle
+ * in OSptr */
+ FILE *fhreal;
+ unpack_message(BUFFERDATA(buffhead), "%w%w%w%w", &reason_code,
+ &DebugID, &OSInfo1, &OSInfo2);
+ /* Extract reason code from buffer. */
+ reason_code &= 0xFFFF; /* Strip away direction bit, OSInfo and */
+ /* DebugInfo fields. Will want to do some */
+ /* sort of validation on this later. */
+
+ switch(reason_code)
+ {
+
+ case CL_WriteC: /* Write a character to the terminal. */
+ /* byte data -> word status */
+ {
+#ifdef DEBUG
+ int c = (int)(*buffp);
+ printf("CL_WriteC: [%02x]>%c<", c, isprint(c) ? c : '.');
+#endif
+ stateptr->hostif->writec(stateptr->hostif->hostosarg, (int)(*buffp));
+ DevSW_FreePacket(packet);
+ return msgsend(CI_CLIB,"%w%w%w%w%w", CL_WriteC|HtoT,
+ DebugID, OSInfo1, OSInfo2, NoError);
+ }
+
+ case CL_Write0: /* Write a null terminated string to the terminal. */
+ {
+ unpack_message(buffp, "%w", &len);
+ DebugCheckNullTermString("CL_Write0", TRUE, len, buffp+4);
+ stateptr->hostif->write(stateptr->hostif->hostosarg,
+ (char *) buffp+4, len);
+ DevSW_FreePacket(packet);
+ return msgsend(CI_CLIB, "%w%w%w%w%w", CL_Write0|HtoT, DebugID,
+ OSInfo1, OSInfo2, NoError);
+ }
+
+ case CL_ReadC: /* Read a byte from the terminal */
+ {
+ DebugPrintF(("CL_ReadC: "));
+ DevSW_FreePacket(packet);
+
+ character = stateptr->hostif->readc(stateptr->hostif->hostosarg);
+ DebugPrintF(("\nCL_ReadC returning [%02x]>%c<\n", character,
+ isprint(character) ? character : '.'));
+
+ return msgsend(CI_CLIB, "%w%w%w%w%w%b", CL_ReadC|HtoT,
+ DebugID, OSInfo1, OSInfo2, NoError, character);
+ }
+
+ case CL_System: /* Pass NULL terminated string to the hosts command
+ * interpreter. As it is nULL terminated we dont need
+ * the length
+ */
+ {
+ unpack_message(buffp, "%w", &len);
+ DebugCheckNullTermString("CL_System", TRUE, len, buffp+4);
+
+ err = system((char *)buffp+4); /* Use the string in the buffer */
+ stateptr->last_errno = errno;
+ DebugCheckErr("system", TRUE, err, stateptr->last_errno);
+
+ err = msgsend(CI_CLIB, "%w%w%w%w%w%w", CL_System|HtoT,
+ DebugID, OSInfo1, OSInfo2, NoError, err);
+ DevSW_FreePacket(packet);
+ return err;
+ }
+
+ case CL_GetCmdLine: /* Returns the command line used to call the program */
+ {
+ /* Note: we reuse the packet here, this may not always be desirable */
+ /* /* TODO: Use long buffers if possible */
+ DebugPrintF(("CL_GetCmdLine: \"%s\"\n", *(stateptr->CommandLine)));
+
+ if (buffhead!=NULL) {
+ len = strlen(*(stateptr->CommandLine));
+ if (len > Armsd_BufferSize-24) len = Armsd_BufferSize-24;
+ packet->pk_length = len + msgbuild(BUFFERDATA(buffhead),
+ "%w%w%w%w%w%w", CL_GetCmdLine|HtoT,
+ DebugID, OSInfo1, OSInfo2,
+ NoError, len);
+ strncpy((char *) BUFFERDATA(buffhead)+24,*(stateptr->CommandLine),
+ len);
+
+ Adp_ChannelWrite(CI_CLIB, packet);/* Send message. */
+ return 0;
+ }
+ else return -1;
+ }
+
+ case CL_Clock: /* Return the number of centiseconds since the support */
+ /* code started executing */
+ {
+ time_t retTime = time(NULL);
+ if (retTime == (time_t)-1)
+ stateptr->last_errno = errno;
+ else
+ retTime *=100;
+
+ DebugPrintF(("CL_Clock: %lu\n", retTime));
+ DebugCheckErr("time", TRUE, (retTime == (time_t)-1),
+ stateptr->last_errno);
+
+ DevSW_FreePacket(packet);
+ return msgsend(CI_CLIB, "%w%w%w%w%w%w",CL_Clock|HtoT,
+ DebugID, OSInfo1, OSInfo2, NoError, retTime);
+ }
+
+ case CL_Time: /* return time, in seconds since the start of 1970 */
+ {
+ time_t retTime = time(NULL);
+ if (retTime == (time_t)-1)
+ stateptr->last_errno = errno;
+
+ DebugPrintF(("CL_Time: %lu\n", retTime));
+ DebugCheckErr("time", TRUE, (retTime == (time_t)-1),
+ stateptr->last_errno);
+
+ DevSW_FreePacket(packet);
+ return msgsend(CI_CLIB,"%w%w%w%w%w%w",CL_Time|HtoT,
+ DebugID, OSInfo1, OSInfo2, NoError, retTime);
+ }
+
+ case CL_Remove: /* delete named in the null terminated string */
+ {
+ /* Removing an open file will cause problems but once again
+ * its not our problem, likely result is a tangled FileTable */
+ /* As the filename is passed with a null terminator we can use it
+ * straight out of the buffer without copying it.*/
+
+ unpack_message(buffp, "%w", &len);
+ DebugCheckNullTermString("CL_Remove", TRUE, len, buffp+4);
+
+ err=remove((char *)buffp+4);
+ stateptr->last_errno = errno;
+ DevSW_FreePacket(packet);
+ DebugCheckErr("remove", TRUE, err, stateptr->last_errno);
+
+ return msgsend(CI_CLIB, "%w%w%w%w%w", CL_Remove|HtoT,
+ DebugID, OSInfo1, OSInfo2, err?-1:NoError);
+ }
+
+ case CL_Rename: /* rename file */
+ {
+ /* Rename(word nbytes, bytes oname, word nbytes, bytes nname)
+ * return(byte status)
+ */
+ unsigned int len2;
+
+ unpack_message(buffp, "%w", &len);
+ DebugCheckNullTermString("CL_Rename", FALSE, len, buffp+4);
+ unpack_message(buffp+5+len, "%w", &len2);
+ DebugCheckNullTermString("to", TRUE, len2, buffp+9+len);
+
+ /* Both names are passed with null terminators so we can use them
+ * directly from the buffer. */
+ err = rename((char *)buffp+4, (char *)buffp+9+len);
+ stateptr->last_errno = errno;
+ DebugCheckErr("rename", TRUE, err, stateptr->last_errno);
+ DevSW_FreePacket(packet);
+
+ return msgsend(CI_CLIB, "%w%w%w%w%w", CL_Rename|HtoT,
+ DebugID, OSInfo1, OSInfo2, (err==0)? NoError : -1);
+ }
+
+ case CL_Open: /* open the file */
+ {
+ /* Open(word nbytes, bytes name, byte mode)
+ * return(word handle)
+ */
+ unpack_message(buffp, "%w", &len);
+ /* get the open mode */
+ unpack_message((buffp)+4+len+1, "%w", &mode);
+ DebugCheckNullTermString("CL_Open", FALSE, len, buffp+4);
+ DebugPrintF(("mode: %d\n", mode));
+
+ /* do some checking on the file first? */
+ /* check if its a tty */
+ if (strcmp((char *)buffp+4, ":tt")==0 && (mode==0||mode==1)) {
+ /* opening tty "r" */
+ fhreal = stdin;
+ stateptr->last_errno = errno;
+ DebugPrintF(("\tstdin "));
+ }
+ else if (strcmp((char *)buffp+4, ":tt")== 0 && (mode==4||mode==5)) {
+ /* opening tty "w" */
+ fhreal = stdout;
+ stateptr->last_errno = errno;
+ DebugPrintF(("\tstdout "));
+ }
+ else
+ {
+ fhreal = fopen((char *)buffp+4, fmode[mode&0xFF]);
+ stateptr->last_errno = errno;
+ DebugCheckNonNull("fopen", FALSE, fhreal, stateptr->last_errno);
+ }
+ DevSW_FreePacket(packet);
+
+ c = NONHANDLE;
+ if (fhreal != NULL) {
+ /* update filetable */
+ for (c=3; c < HSYS_FOPEN_MAX; c++) {
+ /* allow for stdin, stdout, stderr (!!! WHY? MJG) */
+ if (stateptr->OSptr->FileTable[c] == NULL) {
+ stateptr->OSptr->FileTable[c]= fhreal;
+ stateptr->OSptr->FileFlags[c]= mode & 1;
+ DebugPrintF(("fh: %d\n", c));
+ break;
+ }
+ else if (c == HSYS_FOPEN_MAX) {
+ /* no filehandles free */
+ DebugPrintF(("no free fh: %d\n", c));
+ stateptr->last_errno = EMFILE;
+ }
+ }
+ }
+ else {
+ /* c = NULL;*/
+ DebugPrintF(("error fh: %d\n", c));
+ }
+ (void) msgsend(CI_CLIB, "%w%w%w%w%w", CL_Open|HtoT,
+ DebugID, OSInfo1, OSInfo2, c);
+ return 0;
+ }
+
+ case CL_Close: /* close the file pointed to by the filehandle */
+ {
+ unpack_message(buffp, "%w", &fh);
+ DebugPrintF(("CL_Close: fh %d\n", fh));
+ DevSW_FreePacket(packet);
+
+ fhreal = hsysGetRealFileHandle(stateptr, fh, NULL);
+ if (fhreal == NULL)
+ err = -1;
+ else {
+ if (fhreal == stdin || fhreal == stdout || fhreal == stderr) {
+ stateptr->last_errno = errno;
+ DebugPrintF(("\tskipping close of std*\n"));
+ err = 0;
+ }
+ else {
+ err = fclose(fhreal);
+ if (err == 0)
+ stateptr->OSptr->FileTable[fh]=NULL;
+ stateptr->last_errno = errno;
+ DebugCheckErr("fclose", TRUE, err, stateptr->last_errno);
+ }
+ }
+ return msgsend(CI_CLIB,"%w%w%w%w%w", CL_Close|HtoT, DebugID,
+ OSInfo1, OSInfo2, err);
+ }
+
+ case CL_Write:
+ {
+ /* Write(word handle, word nbtotal, word nbytes, bytes data)
+ * return(word nbytes)
+ * WriteX(word nbytes, bytes data)
+ * return(word nbytes)
+ */
+ unsigned char *rwdata = NULL, *rwhead = NULL;
+ unsigned char *write_source = NULL;
+ char flags;
+ FILE *fhreal;
+ unsigned int ack_reason = CL_Write; /* first ack is for CL_Write */
+
+ err = -1; /* err == 0 is fwrite() error indication */
+ unpack_message(buffp, "%w%w%w", &fh, &nbtotal, &nbytes);
+ DebugPrintF(("CL_Write: fh %d nbtotal %u nbytes %u\n",
+ fh, nbtotal, nbytes));
+
+ fhreal = hsysGetRealFileHandle(stateptr, fh, &flags);
+ nbtogo = nbtotal;
+
+ /* deal with the file handle */
+ if (fhreal == NULL)
+ err = 0;
+ else {
+ if (flags & READOP)
+ fseek(fhreal,0,SEEK_CUR);
+ stateptr->OSptr->FileFlags[fh] = (flags & BINARY) | WRITEOP;
+
+ nbtogo -= nbytes;
+
+ if (nbtogo > 0) {
+ write_source = rwdata = rwhead = (unsigned char *)malloc(nbtotal);
+ if (rwhead == NULL) {
+ fprintf(stderr, "OUT OF MEMORY at line %d in %s\n",
+ __LINE__, __FILE__);
+ return -1;
+ }
+ memcpy(rwdata, buffp+12, nbytes);
+ rwdata += nbytes;
+ }
+ else
+ write_source = buffp+12;
+ }
+
+ do {
+ /* at least once!! */
+
+ if (nbtogo == 0 && err != 0) {
+ /* Do the actual write! */
+ if (fhreal == stdout || fhreal == stderr) {
+ stateptr->hostif->write(stateptr->hostif->hostosarg,
+ (char *)write_source, nbtotal);
+ }
+ else
+ err = fwrite(write_source, 1, nbtotal, fhreal);
+ stateptr->last_errno = errno;
+ DebugCheckErr("fwrite", TRUE, (err == 0), stateptr->last_errno);
+ }
+
+ DevSW_FreePacket(packet);
+ if (msgsend(CI_CLIB,"%w%w%w%w%w%w", ack_reason|HtoT,
+ DebugID, OSInfo1, OSInfo2, (err == 0), nbtogo))
+ {
+ fprintf(stderr, "COULD NOT REPLY at line %d in %s\n",
+ __LINE__, __FILE__);
+ if (rwhead != NULL)
+ free(rwhead);
+ return -1;
+ }
+
+ if (nbtogo == 0 || err == 0) {
+ DebugPrintF(("\twrite complete - returning\n"));
+ if (rwhead != NULL)
+ free(rwhead);
+ return 0;
+ }
+ else {
+ /* await extension */
+ ack_reason = CL_WriteX;
+
+ packet = DevSW_AllocatePacket(Armsd_BufferSize);
+ if (packet == NULL)
+ {
+ fprintf(stderr, "COULD NOT ALLOC PACKET at line %d in %s\n",
+ __LINE__, __FILE__);
+ if (rwhead != NULL)
+ free(rwhead);
+ return -1;
+ }
+ Adp_ChannelRegisterRead(CI_CLIB, NULL, NULL);
+ Adp_ChannelRead(CI_CLIB, &packet);
+ Adp_ChannelRegisterRead(CI_CLIB,
+ (ChannelCallback)HandleSysMessage,
+ stateptr);
+
+ buffhead = packet->pk_buffer;
+ unpack_message(BUFFERDATA(buffhead), "%w%w%w%w%w", &reason_code,
+ &DebugID, &OSInfo1, &OSInfo2, &nbytes);
+ if (reason_code != (CL_WriteX|TtoH)) {
+ DevSW_FreePacket(packet);
+ free(rwhead);
+ fprintf(stderr, "EXPECTING CL_WriteX GOT %u at line %d in %s\n",
+ reason_code, __LINE__, __FILE__);
+ return -1;
+ }
+
+ DebugPrintF(("CL_WriteX: nbytes %u\n", nbytes));
+ memcpy(rwdata, BUFFERDATA(buffhead)+20, nbytes);
+ rwdata += nbytes;
+ nbtogo -= nbytes;
+ }
+
+ } while (TRUE); /* will return when done */
+ }
+
+ case CL_WriteX: /*
+ * NOTE: if we've got here something has gone wrong
+ * CL_WriteX's should all be picked up within the
+ * CL_Write loop, probably best to return an error here
+ * do this for the moment just so we do actually return
+ */
+ fprintf(stderr, "ERROR: unexpected CL_WriteX message received\n");
+ return -1;
+
+ case CL_Read:
+ {
+ /* Read(word handle, word nbtotal)
+ * return(word nbytes, word nbmore, bytes data)
+ */
+ /* ReadX()
+ * return(word nbytes, word nbmore, bytes data) */
+ unsigned char *rwdata, *rwhead;
+ int gotlen;
+ unsigned int max_data_in_buffer=Armsd_BufferSize-28;
+ char flags;
+ FILE *fhreal;
+ unsigned int nbleft = 0, reason = CL_Read;
+
+ err = NoError;
+
+ unpack_message(buffp, "%w%w", &fh, &nbtotal);
+ DebugPrintF(("CL_Read: fh %d, nbtotal %d: ", fh, nbtotal));
+
+ rwdata = rwhead = (unsigned char *)malloc(nbtotal);
+ if (rwdata == NULL) {
+ fprintf(stderr, "OUT OF MEMORY at line %d in %s\n",
+ __LINE__, __FILE__);
+ DevSW_FreePacket(packet);
+ return -1;
+ }
+
+ /* perform the actual read */
+ fhreal = hsysGetRealFileHandle(stateptr, fh, &flags);
+ if (fhreal == NULL)
+ {
+ /* bad file handle */
+ err = -1;
+ nbytes = 0;
+ gotlen = 0;
+ }
+ else
+ {
+ if (flags & WRITEOP)
+ fseek(fhreal,0,SEEK_CUR);
+ stateptr->OSptr->FileFlags[fh] = (flags & BINARY) | WRITEOP;
+ if (isatty_(fhreal)) {
+ /* reading from a tty, so do some nasty stuff, reading into rwdata */
+ if (angel_hostif->gets(stateptr->hostif->hostosarg, (char *)rwdata,
+ nbtotal) != 0)
+ gotlen = strlen((char *)rwdata);
+ else
+ gotlen = 0;
+ stateptr->last_errno = errno;
+ DebugPrintF(("ttyread %d\n", gotlen));
+ }
+ else {
+ /* not a tty, reading from a real file */
+ gotlen = fread(rwdata, 1, nbtotal, fhreal);
+ stateptr->last_errno = errno;
+ DebugCheckErr("fread", FALSE, (gotlen == 0), stateptr->last_errno);
+ DebugPrintF(("(%d)\n", gotlen));
+ }
+ }
+
+ nbtogo = gotlen;
+
+ do {
+ /* at least once */
+
+ if ((unsigned int) nbtogo <= max_data_in_buffer)
+ nbytes = nbtogo;
+ else
+ nbytes = max_data_in_buffer;
+ nbtogo -= nbytes;
+
+ /* last ReadX needs subtle adjustment to returned nbtogo */
+ if (nbtogo == 0 && err == NoError && reason == CL_ReadX)
+ nbleft = nbtotal - gotlen;
+ else
+ nbleft = nbtogo;
+
+ count = msgbuild(BUFFERDATA(buffhead), "%w%w%w%w%w%w%w",
+ reason|HtoT, 0, ADP_HandleUnknown,
+ ADP_HandleUnknown, err, nbytes, nbleft);
+
+ if (err == NoError) {
+ /* copy data into buffptr */
+ memcpy(BUFFERDATA(buffhead)+28, rwdata, nbytes);
+ rwdata += nbytes;
+ count += nbytes;
+ }
+
+ DebugPrintF(("\treplying err %d, nbytes %d, nbtogo %d\n",
+ err, nbytes, nbtogo));
+
+ packet->pk_length = count;
+ Adp_ChannelWrite(CI_CLIB, packet);
+
+ if (nbtogo == 0 || err != NoError) {
+ /* done */
+ free(rwhead);
+ return 0;
+ }
+ else {
+ /* await extension */
+ reason = CL_ReadX;
+
+ packet = DevSW_AllocatePacket(Armsd_BufferSize);
+ if (packet == NULL) {
+ fprintf(stderr, "COULD NOT ALLOC PACKET at line %d in %s\n",
+ __LINE__, __FILE__);
+ free(rwhead);
+ return -1;
+ }
+ Adp_ChannelRegisterRead(CI_CLIB, NULL, NULL);
+ Adp_ChannelRead(CI_CLIB, &packet);
+ Adp_ChannelRegisterRead(CI_CLIB,
+ (ChannelCallback)HandleSysMessage,
+ stateptr);
+ buffhead = packet->pk_buffer;
+ unpack_message(BUFFERDATA(buffhead),"%w", &reason_code);
+ if (reason_code != (CL_ReadX|TtoH)) {
+ fprintf(stderr, "EXPECTING CL_ReadX GOT %u at line %d in %s\n",
+ reason_code, __LINE__, __FILE__);
+ DevSW_FreePacket(packet);
+ free(rwdata);
+ return -1;
+ }
+ }
+
+ } while (TRUE); /* will return above on error or when done */
+ }
+
+ case CL_ReadX: /* If we're here something has probably gone wrong */
+ fprintf(stderr, "ERROR: Got unexpected CL_ReadX message\n");
+ return -1;
+
+ case CL_Seek:
+ {
+ unpack_message(buffp, "%w%w", &fh, &posn);
+ DebugPrintF(("CL_Seek: fh %d, posn %ld\n", fh, posn));
+ DevSW_FreePacket(packet);
+
+ fhreal = hsysGetRealFileHandle(stateptr, fh, NULL);
+ if (fhreal == NULL)
+ err = -1;
+ else {
+ err = fseek(fhreal, posn, SEEK_SET);
+ stateptr->last_errno = errno;
+ DebugCheckErr("fseek", TRUE, err, stateptr->last_errno);
+ }
+
+ return msgsend(CI_CLIB, "%w%w%w%w%w", CL_Seek|HtoT,
+ DebugID, OSInfo1, OSInfo2, err);
+ }
+
+ case CL_Flen:
+ {
+ unpack_message(buffp, "%w", &fh);
+ DebugPrintF(("CL_Flen: fh %d ", fh));
+ DevSW_FreePacket(packet);
+
+ fhreal = hsysGetRealFileHandle(stateptr, fh, NULL);
+ if (fhreal == NULL)
+ fl = -1;
+ else {
+ posn = ftell(fhreal);
+ if (fseek(fhreal, 0L, SEEK_END) < 0) {
+ fl=-1;
+ }
+ else {
+ fl = ftell(fhreal);
+ fseek(fhreal, posn, SEEK_SET);
+ }
+ stateptr->last_errno = errno;
+ }
+ DebugPrintF(("returning len %ld\n", fl));
+ return msgsend(CI_CLIB, "%w%w%w%w%w", CL_Flen|HtoT, DebugID, OSInfo1,
+ OSInfo2, fl);
+ }
+
+ case CL_IsTTY:
+ {
+ int ttyOrNot;
+ unpack_message(buffp, "%w", &fh);
+ DebugPrintF(("CL_IsTTY: fh %d ", fh));
+ DevSW_FreePacket(packet);
+
+ fhreal = hsysGetRealFileHandle(stateptr, fh, NULL);
+ if (fhreal == NULL)
+ ttyOrNot = FALSE;
+ else {
+ ttyOrNot = isatty_(fhreal);
+ stateptr->last_errno = errno;
+ }
+ DebugPrintF(("returning %s\n", ttyOrNot ? "tty (1)" : "not (0)"));
+
+ return msgsend(CI_CLIB, "%w%w%w%w%w",CL_IsTTY|HtoT,
+ DebugID, OSInfo1, OSInfo2, ttyOrNot);
+ }
+
+ case CL_TmpNam:
+ {
+ char *name;
+ unsigned int tnamelen, TargetID;
+ unpack_message(buffp, "%w%w", &tnamelen, &TargetID);
+ DebugPrintF(("CL_TmpNam: tnamelen %d TargetID %d: ",
+ tnamelen, TargetID));
+ DevSW_FreePacket(packet);
+
+ TargetID = TargetID & 0xFF;
+ if (stateptr->OSptr->TempNames[TargetID] == NULL) {
+ if ((stateptr->OSptr->TempNames[TargetID] =
+ (char *)malloc(L_tmpnam)) == NULL)
+ {
+ fprintf(stderr, "OUT OF MEMORY at line %d in %s\n",
+ __LINE__, __FILE__);
+ return -1;
+ }
+ tmpnam(stateptr->OSptr->TempNames[TargetID]);
+ }
+ name = stateptr->OSptr->TempNames[TargetID];
+ len = strlen(name) + 1;
+ packet = DevSW_AllocatePacket(Armsd_BufferSize);
+ if (packet == NULL)
+ {
+ fprintf(stderr, "COULD NOT ALLOC PACKET at line %d in %s\n",
+ __LINE__, __FILE__);
+ return -1;
+ }
+ buffhead = packet->pk_buffer;
+ if (len > tnamelen) {
+ DebugPrintF(("TMPNAME TOO LONG!\n"));
+ count = msgbuild(BUFFERDATA(buffhead), "%w%w%w%w%w",
+ CL_TmpNam|HtoT, DebugID, OSInfo1, OSInfo2, -1);
+ }
+ else {
+ DebugPrintF(("returning \"%s\"\n", name));
+ count = msgbuild(BUFFERDATA(buffhead), "%w%w%w%w%w%w", CL_TmpNam|HtoT,
+ DebugID, OSInfo1, OSInfo2, 0, len);
+ strcpy((char *)BUFFERDATA(buffhead)+count, name);
+ count +=len+1;
+ }
+ packet->pk_length = count;
+ Adp_ChannelWrite(CI_CLIB, packet);/* Send message. */
+ return 0;
+ }
+
+ case CL_Unrecognised:
+ DebugPrintF(("CL_Unrecognised!!\n"));
+ return 0;
+
+ default:
+ fprintf(stderr, "UNRECOGNISED CL code %08x\n", reason_code);
+ break;
+/* Need some sort of error handling here. */
+/* A call to CL_Unrecognised should suffice */
+ }
+ return -1; /* Stop a potential compiler warning */
+}
+
+#ifdef COMPILING_ON_WINDOWS
+
+#include <windows.h>
+
+extern HWND hwndParent;
+
+void panic(const char *format, ...)
+{
+ char buf[2048];
+ va_list args;
+
+ Adp_CloseDevice();
+
+ va_start(args, format);
+ vsprintf(buf, format, args);
+
+ MessageBox(hwndParent, (LPCTSTR)buf, (LPCTSTR)"Fatal Error:", MB_OK);
+
+ /* SJ - Not the proper way to shutdown the app */
+ exit(EXIT_FAILURE);
+
+/*
+ if (hwndParent != NULL)
+ SendMessage(hwndParent, WM_QUIT, 0, 0);
+*/
+
+ va_end(args);
+}
+
+#else
+
+void panic(const char *format, ...)
+{
+ va_list args;
+
+ va_start(args, format);
+ fprintf(stderr, "Fatal error: ");
+ vfprintf(stderr, format, args);
+ fprintf(stderr,"\n");
+
+ exit(EXIT_FAILURE);
+}
+
+#endif
+
+/* EOF hsys.c */
diff --git a/gdb/rdi-share/hsys.h b/gdb/rdi-share/hsys.h
new file mode 100644
index 00000000000..7f63d0103d1
--- /dev/null
+++ b/gdb/rdi-share/hsys.h
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
+ *
+ * This software may be freely used, copied, modified, and distributed
+ * provided that the above copyright notice is preserved in all copies of the
+ * software.
+ */
+
+/*
+ * Host C library support header file.
+ *
+ * $Revision$
+ * $Date$
+ *
+ */
+
+#ifndef angsd_hsys_h
+#define angsd_hsys_h
+
+#define HSYS_FOPEN_MAX 256
+#define NONHANDLE -1
+#define UNIQUETEMPS 256
+
+#include "dbg_hif.h"
+#include "hostchan.h"
+
+typedef struct {
+ FILE *FileTable[HSYS_FOPEN_MAX] ;
+ char FileFlags[HSYS_FOPEN_MAX] ;
+ char *TempNames[UNIQUETEMPS];
+} OSblock;
+
+#define NOOP 0
+#define BINARY 1
+#define READOP 2
+#define WRITEOP 4
+
+typedef struct {
+ const struct Dbg_HostosInterface *hostif; /* Interface to debug toolkit. */
+ int last_errno; /* Number of the last error. */
+ OSblock *OSptr;
+ char **CommandLine ; /* Ptr to cmd line d`string held by ardi.c */
+} hsys_state;
+
+/*
+ * Function: HostSysInit
+ * Purpose: Set up the state block, filetable and register the and C lib
+ * callback fn
+ *
+ * Params:
+ * Input: hostif, the host interface from the debug toolbox
+ * cmdline, the command line used to call the image
+ * state, the status block for the C lib
+ *
+ * Returns:
+ * OK: an RDIError_* valuee
+ */
+extern int HostSysInit(
+ const struct Dbg_HostosInterface *hostif, char **cmdline, hsys_state **state
+);
+
+/*
+ * Function: HostSysExit
+ * Purpose: Close down the host side C library support
+ *
+ * Params:
+ * Input: hstate, the status block for the C lib
+ *
+ * Returns: an RDIError_* valuee
+ */
+extern int HostSysExit(hsys_state *hstate);
+
+/*
+ * Function: HandleSysMessage
+ * Purpose: Handle an incoming C library message as a callback
+ *
+ * Params:
+ * Input: packet is the incoming data packet as described in devsw.h
+ * hstate, the status block for the C lib
+ *
+ * Returns: an RDIError_* valuee
+ */
+extern int HandleSysMessage(Packet *packet, hsys_state* stateptr);
+
+/*
+ * Function: panic
+ * Purpose: Print a fatal error message
+ *
+ * Params:
+ * Input: format printf() style message describing the problem
+ * ... extra arguments for printf().
+ *
+ * Returns: This routine does not return
+ *
+ * Post-conditions: Will have called exit(1);
+ */
+extern void panic(const char *format, ...);
+
+#endif /* ndef angsd_hsys_h */
+
+/* EOF hsys.h */
diff --git a/gdb/rdi-share/logging.c b/gdb/rdi-share/logging.c
new file mode 100644
index 00000000000..79b70ef348f
--- /dev/null
+++ b/gdb/rdi-share/logging.c
@@ -0,0 +1,369 @@
+/*
+ * Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
+ *
+ * This software may be freely used, copied, modified, and distributed
+ * provided that the above copyright notice is preserved in all copies of the
+ * software.
+ */
+
+/* -*-C-*-
+ *
+ * $Revision$
+ * $Date$
+ *
+ *
+ * logging.c - methods for logging warnings, errors and trace info
+ *
+ */
+
+#include <stdarg.h> /* ANSI varargs support */
+
+#ifdef TARGET
+# include "angel.h"
+# include "devconf.h"
+#else
+# include "host.h"
+#endif
+
+#include "logging.h" /* Header file for this source code */
+
+#ifndef UNUSED
+# define UNUSED(x) ((x)=(x))
+#endif
+
+/*
+ * __rt_warning
+ * ------------
+ * This routine is provided as a standard method of generating
+ * run-time system warnings. The actual action taken by this code can
+ * be board or target application specific, e.g. internal logging,
+ * debug message, etc.
+ */
+
+#ifdef DEBUG
+
+# ifdef DEBUG_METHOD
+
+# define STRINGIFY2(x) #x
+# define STRINGIFY(x) STRINGIFY2(x)
+# define DEBUG_METHOD_HEADER STRINGIFY(DEBUG_METHOD##.h)
+
+# include DEBUG_METHOD_HEADER
+
+# define METHOD_EXPAND_2(m, p, c) m##p(c)
+# define METHOD_EXPAND(m, p, c) METHOD_EXPAND_2(m, p, c)
+
+# define CHAROUT(c) METHOD_EXPAND(DEBUG_METHOD, _PutChar, (c))
+# define PRE_DEBUG(l) METHOD_EXPAND(DEBUG_METHOD, _PreWarn, (l))
+# define POST_DEBUG(n) METHOD_EXPAND(DEBUG_METHOD, _PostWarn, (n))
+
+# else
+# error Must define DEBUG_METHOD
+# endif
+
+#endif /* def DEBUG */
+
+/*
+ * the guts of __rt_warning
+ */
+
+#pragma no_check_stack
+#ifdef DEBUG
+
+static const char hextab[] = "0123456789ABCDEF";
+
+/*
+ * If debugging, then we break va_warn into sub-functions which
+ * allow us to get an easy breakpoint on the formatted string
+ */
+static int va_warn0(char *format, va_list args)
+{
+ int len = 0;
+
+ while ((format != NULL) && (*format != '\0'))
+ {
+ if (*format == '%')
+ {
+ char fch = *(++format); /* get format character (skipping '%') */
+ int ival; /* holder for integer arguments */
+ char *string; /* holder for string arguments */
+ int width = 0; /* No field width by default */
+ int padzero = FALSE; /* By default we pad with spaces */
+
+ /*
+ * Check if the format has a width specified. NOTE: We do
+ * not use the "isdigit" function here, since it will
+ * require run-time support. The current ARM Ltd header
+ * defines "isdigit" as a macro, that uses a fixed
+ * character description table.
+ */
+ if ((fch >= '0') && (fch <= '9'))
+ {
+ if (fch == '0')
+ {
+ /* Leading zeroes padding */
+ padzero = TRUE;
+ fch = *(++format);
+ }
+
+ while ((fch >= '0') && (fch <= '9'))
+ {
+ width = ((width * 10) + (fch - '0'));
+ fch = *(++format);
+ }
+ }
+
+ if (fch == 'l')
+ /* skip 'l' in "%lx", etc. */
+ fch = *(++format);
+
+ switch (fch)
+ {
+ case 'c':
+ /* char */
+ ival = va_arg(args, int);
+ CHAROUT((char)ival);
+ len++;
+ break;
+
+ case 'x':
+ case 'X':
+ {
+ /* hexadecimal */
+ unsigned int uval = va_arg(args, unsigned int);
+ int loop;
+
+ UNUSED(uval);
+
+ if ((width == 0) || (width > 8))
+ width = 8;
+
+ for(loop = (width * 4); (loop != 0); loop -= 4)
+ {
+ CHAROUT(hextab[(uval >> (loop - 4)) & 0xF]);
+ len++;
+ }
+ }
+
+ break;
+
+ case 'd':
+ /* decimal */
+ ival = va_arg(args, int);
+
+ if (ival < 0)
+ {
+ ival = -ival;
+ CHAROUT('-');
+ len++;
+ }
+
+ if (ival == 0)
+ {
+ CHAROUT('0');
+ len++;
+ }
+ else
+ {
+ /*
+ * The simplest method of displaying numbers is
+ * to provide a small recursive routine, that
+ * nests until the most-significant digit is
+ * reached, and then falls back out displaying
+ * individual digits. However, we want to avoid
+ * using recursive code within the lo-level
+ * parts of Angel (to minimise the stack
+ * usage). The following number conversion is a
+ * non-recursive solution.
+ */
+ char buffer[16]; /* stack space used to hold number */
+ int count = 0; /* pointer into buffer */
+
+ /*
+ * Place the conversion into the buffer in
+ * reverse order:
+ */
+ while (ival != 0)
+ {
+ buffer[count++] = ('0' + ((unsigned int)ival % 10));
+ ival = ((unsigned int)ival / 10);
+ }
+
+ /*
+ * Check if we are placing the data in a
+ * fixed width field:
+ */
+ if (width != 0)
+ {
+ width -= count;
+
+ for (; (width != 0); width--)
+ {
+ CHAROUT(padzero ? '0': ' ');
+ len++;
+ }
+ }
+
+ /* then display the buffer in reverse order */
+ for (; (count != 0); count--)
+ {
+ CHAROUT(buffer[count - 1]);
+ len++;
+ }
+ }
+
+ break;
+
+ case 's':
+ /* string */
+ string = va_arg(args, char *);
+
+ /* we only need this test once */
+ if (string != NULL)
+ /* whilst we check this for every character */
+ while (*string)
+ {
+ CHAROUT(*string);
+ len++;
+ string++;
+
+ /*
+ * NOTE: We do not use "*string++" as the macro
+ * parameter, since we do not know how many times
+ *the parameter may be expanded within the macro.
+ */
+ }
+
+ break;
+
+ case '\0':
+ /*
+ * string terminated by '%' character, bodge things
+ * to prepare for default "format++" below
+ */
+ format--;
+
+ break;
+
+ default:
+ /* just display the character */
+ CHAROUT(*format);
+ len++;
+
+ break;
+ }
+
+ format++; /* step over format character */
+ }
+ else
+ {
+ CHAROUT(*format);
+ len++;
+ format++;
+ }
+ }
+ return len;
+}
+
+/*
+ * this routine is simply here as a good breakpoint for dumping msg -
+ * can be used by DEBUG_METHOD macros or functions, if required.
+ */
+# ifdef DEBUG_NEED_VA_WARN1
+static void va_warn1(int len, char *msg)
+{
+ UNUSED(len); UNUSED(msg);
+}
+# endif
+
+void va_warn(WarnLevel level, char *format, va_list args)
+{
+ int len;
+
+ if ( PRE_DEBUG( level ) )
+ {
+ len = va_warn0(format, args);
+ POST_DEBUG( len );
+ }
+}
+
+#else /* ndef DEBUG */
+
+void va_warn(WarnLevel level, char *format, va_list args)
+{
+ UNUSED(level); UNUSED(format); UNUSED(args);
+}
+
+#endif /* ... else ndef(DEBUG) ... */
+#pragma check_stack
+
+#pragma no_check_stack
+void __rt_warning(char *format, ...)
+{
+ va_list args;
+
+ /*
+ * For a multi-threaded system we should provide a lock at this point
+ * to ensure that the warning messages are sequenced properly.
+ */
+
+ va_start(args, format);
+ va_warn(WL_WARN, format, args);
+ va_end(args);
+
+ return;
+}
+#pragma check_stack
+
+#ifdef TARGET
+
+#pragma no_check_stack
+void __rt_uninterruptable_loop( void ); /* in suppasm.s */
+
+void __rt_error(char *format, ...)
+{
+ va_list args;
+
+ va_start(args, format);
+
+ /* Display warning message */
+ va_warn(WL_ERROR, format, args);
+
+ __rt_uninterruptable_loop();
+
+ va_end(args);
+ return;
+}
+#pragma check_stack
+
+#endif /* def TARGET */
+
+#ifdef DO_TRACE
+
+static bool trace_on = FALSE; /* must be set true in debugger if req'd */
+
+#pragma no_check_stack
+void __rt_trace(char *format, ...)
+{
+ va_list args;
+
+ /*
+ * For a multi-threaded system we should provide a lock at this point
+ * to ensure that the warning messages are sequenced properly.
+ */
+
+ if (trace_on)
+ {
+ va_start(args, format);
+ va_warn(WL_TRACE, format, args);
+ va_end(args);
+ }
+
+ return;
+}
+#pragma check_stack
+
+#endif /* def DO_TRACE */
+
+
+/* EOF logging.c */
diff --git a/gdb/rdi-share/logging.h b/gdb/rdi-share/logging.h
new file mode 100644
index 00000000000..97bf902ad1a
--- /dev/null
+++ b/gdb/rdi-share/logging.h
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
+ *
+ * This software may be freely used, copied, modified, and distributed
+ * provided that the above copyright notice is preserved in all copies of the
+ * software.
+ */
+
+/* -*-C-*-
+ *
+ * $Revision$
+ * $Date$
+ *
+ *
+ * logging.h - methods for logging warnings, errors and trace info
+ */
+
+#ifndef angel_logging_h
+#define angel_logging_h
+
+#include <stdarg.h>
+
+/*
+ * __rt_warning
+ * ------------
+ * Provides a standard method of generating run-time system
+ * warnings. The actual action taken by this code can be board or
+ * target application specific, e.g. internal logging, debug message,
+ * etc.
+ */
+extern void __rt_warning(char *format, ...);
+
+/*---------------------------------------------------------------------------*/
+
+/*
+ * __rt_error
+ * ----------
+ * Raise an internal Angel error. The parameters are passed directly
+ * to "__rt_warning" for display, and the code then raises a debugger
+ * event and stops the target processing.
+ */
+extern void __rt_error(char *format, ...);
+
+/*
+ * Some macros for debugging and warning messages
+ */
+
+typedef enum WarnLevel {
+ WL_TRACE,
+ WL_WARN,
+ WL_ERROR
+} WarnLevel;
+
+void va_warn(WarnLevel level, char *format, va_list args);
+
+#ifdef _WINGDI_
+/* stupidity in MSVC <wingdi.h> (in <windows.h> in <winsock.h>) */
+# undef ERROR
+#endif
+
+#ifndef ERROR
+# define ERROR_FORMAT "Error \"%s\" in %s at line %d\n"
+# define ERROR(e) __rt_error(ERROR_FORMAT, (e), __FILE__, __LINE__)
+#endif
+
+#ifndef ASSERT
+# ifdef ASSERTIONS_ENABLED
+# define ASSERT(x, y) ((x) ? (void)(0) : ERROR((y)))
+# else
+# define ASSERT(x, y) ((void)(0))
+# endif
+#endif
+
+#ifndef WARN
+# ifdef ASSERTIONS_ENABLED
+# define WARN_FORMAT "Warning \"%s\" in %s at line %d\n"
+# define WARN(w) __rt_warning(WARN_FORMAT, (w), __FILE__, __LINE__)
+# else
+# define WARN(w) ((void)(0))
+# endif
+#endif
+
+
+#ifdef NO_INFO_MESSAGES
+# define __rt_info (void)
+# ifndef INFO
+# define INFO(w)
+# endif
+#else
+# define __rt_info __rt_warning
+# ifndef INFO
+# ifdef DEBUG
+# define INFO(w) __rt_warning("%s\n", (w))
+# else
+# define INFO(w) ((void)(0))
+# endif
+# endif
+#endif
+
+
+#if defined(DEBUG) && !defined(NO_IDLE_CHITCHAT)
+# ifndef DO_TRACE
+# define DO_TRACE (1)
+# endif
+#endif
+
+#ifdef DO_TRACE
+extern void __rt_trace(char *format, ...);
+#endif
+
+#ifndef TRACE
+# ifdef DO_TRACE
+# define TRACE(w) __rt_trace("%s ", (w))
+# else
+# define TRACE(w) ((void)(0))
+# endif
+#endif
+
+#endif /* ndef angel_logging_h */
+
+/* EOF logging.h */
diff --git a/gdb/rdi-share/msgbuild.c b/gdb/rdi-share/msgbuild.c
new file mode 100644
index 00000000000..e2db2cc0576
--- /dev/null
+++ b/gdb/rdi-share/msgbuild.c
@@ -0,0 +1,282 @@
+/*
+ * Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
+ *
+ * This software may be freely used, copied, modified, and distributed
+ * provided that the above copyright notice is preserved in all copies of the
+ * software.
+ */
+
+/* -*-C-*-
+ *
+ * $Revision$
+ * $Date$
+ *
+ *
+ * msgbuild.c - utilities for assembling and interpreting ADP messages
+ *
+ */
+
+#include <stdarg.h> /* ANSI varargs support */
+
+#ifdef TARGET
+# include "angel.h"
+# include "devconf.h"
+#else
+# include "host.h"
+# include "hostchan.h"
+#endif
+
+#include "channels.h"
+#include "buffers.h"
+#include "endian.h" /* Endianness support macros */
+#include "msgbuild.h" /* Header file for this source code */
+
+#ifndef UNUSED
+# define UNUSED(x) ((x)=(x))
+#endif
+
+#ifndef TARGET
+
+extern unsigned int Armsd_BufferSize;
+
+#endif /* ndef TARGET */
+
+
+unsigned int vmsgbuild(unsigned char *buffer, const char *format, va_list args)
+{
+ unsigned int blen = 0;
+ int ch;
+
+ /* Step through the format string */
+ while ((ch = *format++) != '\0')
+ {
+ if (ch != '%')
+ {
+ if (buffer != NULL)
+ *buffer++ = (unsigned char)ch;
+
+ blen++;
+ }
+ else
+ {
+ switch (ch = *format++)
+ {
+ case 'w':
+ case 'W':
+ /* 32bit pointer */
+ case 'p':
+ case 'P':
+ {
+ /* 32bit word / 32bit pointer */
+ unsigned int na = va_arg(args, unsigned int);
+
+ if (buffer != NULL)
+ {
+ PUT32LE(buffer, na);
+ buffer += sizeof(unsigned int);
+ }
+
+ blen += sizeof(unsigned int);
+
+ break;
+ }
+
+ case 'h':
+ case 'H':
+ {
+ /* 16bit value */
+ unsigned int na = va_arg(args, unsigned int);
+
+ if (buffer != NULL)
+ {
+ PUT16LE(buffer, na);
+ buffer += sizeof(unsigned short);
+ }
+
+ blen += sizeof(unsigned short);
+
+ break;
+ }
+
+ case 'c':
+ case 'C':
+ case 'b':
+ case 'B':
+ /* 8bit character / 8bit byte */
+ ch = va_arg(args, int);
+
+ /*
+ * XXX
+ *
+ * fall through to the normal character processing
+ */
+
+ case '%':
+ default:
+ /* normal '%' character, or a different normal character */
+ if (buffer != NULL)
+ *buffer++ = (unsigned char)ch;
+
+ blen++;
+ break;
+ }
+ }
+ }
+
+ return blen;
+}
+
+/*
+ * msgbuild
+ * --------
+ * Simple routine to aid in construction of Angel messages. See the
+ * "msgbuild.h" header file for a detailed description of the operation
+ * of this routine.
+ */
+unsigned int msgbuild(unsigned char *buffer, const char *format, ...)
+{
+ va_list args;
+ unsigned int blen;
+
+ va_start(args, format);
+ blen = vmsgbuild(buffer, format, args);
+ va_end(args);
+
+ return blen;
+}
+
+#if !defined(JTAG_ADP_SUPPORTED) && !defined(MSG_UTILS_ONLY)
+/*
+ * This routine allocates a buffer, puts the data supplied as
+ * parameters into the buffer and sends the message. It does *NOT*
+ * wait for a reply.
+ */
+extern int msgsend(ChannelID chan, const char *format,...)
+{
+ unsigned int length;
+ p_Buffer buffer;
+ va_list args;
+# ifndef TARGET
+ Packet *packet;
+
+ packet = DevSW_AllocatePacket(Armsd_BufferSize);
+ buffer = packet->pk_buffer;
+# else
+ buffer = angel_ChannelAllocBuffer(Angel_ChanBuffSize);
+# endif
+
+ if (buffer != NULL)
+ {
+ va_start(args, format);
+
+ length = vmsgbuild(BUFFERDATA(buffer), format, args);
+
+# ifdef TARGET
+ angel_ChannelSend(CH_DEFAULT_DEV, chan, buffer, length);
+# else
+ packet->pk_length = length;
+ Adp_ChannelWrite(chan, packet);
+# endif
+
+ va_end(args);
+ return 0;
+ }
+ else
+ return -1;
+}
+
+#endif /* ndef JTAG_ADP_SUPPORTED && ndef MSG_UTILS_ONLY */
+
+/*
+ * unpack_message
+ * --------------
+ */
+extern unsigned int unpack_message(unsigned char *buffer, const char *format, ...)
+{
+ va_list args;
+ unsigned int blen = 0;
+ int ch;
+ char *chp = NULL;
+
+ va_start(args, format);
+
+ /* Step through the format string. */
+ while ((ch = *format++) != '\0')
+ {
+ if (ch != '%')
+ {
+ if (buffer != NULL)
+ ch = (unsigned char)*buffer++;
+
+ blen++;
+ }
+ else
+ {
+ switch (ch = *format++)
+ {
+ case 'w':
+ case 'W':
+ {
+ /* 32bit word. */
+ unsigned int *nap = va_arg(args, unsigned int*);
+
+ if (buffer != NULL)
+ {
+ *nap = PREAD32(LE, buffer);
+ buffer += sizeof(unsigned int);
+ }
+
+ blen += sizeof(unsigned int);
+
+ break;
+ }
+
+ case 'h':
+ case 'H':
+ {
+ /* 16bit value. */
+ unsigned int *nap = va_arg(args, unsigned int*);
+
+ if (buffer != NULL)
+ {
+ *nap = PREAD16(LE,buffer);
+ buffer += sizeof(unsigned short);
+ }
+
+ blen += sizeof(unsigned short);
+
+ break;
+ }
+
+ case 'c':
+ case 'C':
+ case 'b':
+ case 'B':
+ /* 8-bit character, or 8-bit byte */
+ chp = va_arg(args, char*);
+
+ /*
+ * XXX
+ *
+ * fall through to the normal character processing.
+ */
+
+ case '%':
+ default:
+ /* normal '%' character, or a different normal character */
+ if (buffer != NULL)
+ *chp = (unsigned char)*buffer++;
+
+ blen++;
+
+ break;
+ }
+ }
+ }
+
+ va_end(args);
+ return(blen);
+}
+
+
+/* EOF msgbuild.c */
diff --git a/gdb/rdi-share/msgbuild.h b/gdb/rdi-share/msgbuild.h
new file mode 100644
index 00000000000..ac2436c1391
--- /dev/null
+++ b/gdb/rdi-share/msgbuild.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
+ *
+ * This software may be freely used, copied, modified, and distributed
+ * provided that the above copyright notice is preserved in all copies of the
+ * software.
+ */
+
+/* -*-C-*-
+ *
+ * $Revision$
+ * $Date$
+ *
+ *
+ * msgbuild.h - utilities for assembling and interpreting ADP messages
+ */
+
+#ifndef angel_msgbuild_h
+#define angel_msgbuild_h
+#include <stdarg.h>
+#include "channels.h"
+
+/*
+ * msgbuild
+ * --------
+ * We use a "varargs" function to enable a description of how the
+ * final message should look to be provided. We use a function rather
+ * than in-line macros to keep the size of Angel small.
+ *
+ * The "buffer" pointer is the starting point from where the data will
+ * be written. Note: If a NULL pointer is passed then no data will be
+ * written, but the size information will be returned. This allows
+ * code to call this routine with a NULL "buffer" pointer to ascertain
+ * whether the pointer they are passing contains enough space for the
+ * message being constructed.
+ *
+ * The "format" string should contain sequences of the following
+ * tokens:
+ * %w - insert 32bit word value
+ * %p - insert 32bit target pointer value
+ * %h - insert 16bit value
+ * %b - insert 8bit byte value
+ *
+ * The return parameter is the final byte length of the data written.
+ */
+unsigned int msgbuild(unsigned char *buffer, const char *format, ...);
+unsigned int vmsgbuild(unsigned char *buffer, const char *format,
+ va_list args);
+
+/*---------------------------------------------------------------------------*/
+
+/*
+ * msgsend
+ * -------
+ * As for msgbuild except that it allocates a buffer, formats the data as
+ * for msgbuild and transmits the packet. Returns 0 if successful non 0 if ot
+ * fails.
+ * Not for use on cooked channels e.g. debug channels only.
+ */
+extern int msgsend(ChannelID chan, const char *format, ...);
+
+/*---------------------------------------------------------------------------*/
+
+/*
+ * Unpack_message
+ * --------------
+ * This basically does the opposite of msg_build, it takes a message, and
+ * a scanf type format string (but much cut down functionality) and returns
+ * the arguments in the message.
+ */
+extern unsigned int unpack_message(unsigned char *buffer, const char *format, ...);
+
+#endif /* ndef angel_msgbuild_h */
+
+/* EOF msgbuild.h */
diff --git a/gdb/rdi-share/params.c b/gdb/rdi-share/params.c
new file mode 100644
index 00000000000..2c781887c19
--- /dev/null
+++ b/gdb/rdi-share/params.c
@@ -0,0 +1,325 @@
+/*
+ * Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
+ *
+ * This software may be freely used, copied, modified, and distributed
+ * provided that the above copyright notice is preserved in all copies of the
+ * software.
+ */
+
+/* -*-C-*-
+ *
+ * $Revision$
+ * $Date$
+ *
+ *
+ * Project: ANGEL
+ *
+ * Title: Parameter negotiation utility functions
+ */
+
+#include "params.h"
+
+#include "endian.h"
+#include "logging.h"
+
+
+/*
+ * Function: Angel_FindParam
+ * Purpose: find the value of a given parameter from a config.
+ *
+ * see params.h for details
+ */
+bool Angel_FindParam( ADP_Parameter type,
+ const ParameterConfig *config,
+ unsigned int *value )
+{
+ unsigned int i;
+
+ for ( i = 0; i < config->num_parameters; ++i )
+ if ( config->param[i].type == type )
+ {
+ *value = config->param[i].value;
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+#if !defined(TARGET) || !defined(MINIMAL_ANGEL) || MINIMAL_ANGEL == 0
+
+ParameterList *Angel_FindParamList( const ParameterOptions *options,
+ ADP_Parameter type )
+{
+ unsigned int i;
+
+ for ( i = 0; i < options->num_param_lists; ++i )
+ if ( options->param_list[i].type == type )
+ return &options->param_list[i];
+
+ return NULL;
+}
+
+
+#if defined(TARGET) || defined(TEST_PARAMS)
+/*
+ * Function: Angel_MatchParams
+ * Purpose: find a configuration from the requested options which is
+ * the best match from the supported options.
+ *
+ * see params.h for details
+ */
+const ParameterConfig *Angel_MatchParams( const ParameterOptions *requested,
+ const ParameterOptions *supported )
+{
+ static Parameter chosen_params[AP_NUM_PARAMS];
+ static ParameterConfig chosen_config = {
+ AP_NUM_PARAMS,
+ chosen_params
+ };
+ unsigned int i;
+
+ ASSERT( requested != NULL, "requested is NULL" );
+ ASSERT( requested != NULL, "requested is NULL" );
+ ASSERT( supported->num_param_lists <= AP_NUM_PARAMS, "supp_num too big" );
+
+ if ( requested->num_param_lists > supported->num_param_lists )
+ {
+ WARN( "req_num exceeds supp_num" );
+ return NULL;
+ }
+
+ for ( i = 0; i < requested->num_param_lists; ++i )
+ {
+ bool match;
+ unsigned int j;
+
+ const ParameterList *req_list = &requested->param_list[i];
+ ADP_Parameter req_type = req_list->type;
+ const ParameterList *sup_list = Angel_FindParamList(
+ supported, req_type );
+
+ if ( sup_list == NULL )
+ {
+#ifdef ASSERTIONS_ENABLED
+ __rt_warning( "option %x not supported\n", req_type );
+#endif
+ return NULL;
+ }
+
+ for ( j = 0, match = FALSE;
+ (j < req_list->num_options) && !match;
+ ++j
+ )
+ {
+ unsigned int k;
+
+ for ( k = 0;
+ (k < sup_list->num_options) && !match;
+ ++k
+ )
+ {
+ if ( req_list->option[j] == sup_list->option[k] )
+ {
+#ifdef DEBUG
+ __rt_info( "chose value %d for option %x\n",
+ req_list->option[j], req_type );
+#endif
+ match = TRUE;
+ chosen_config.param[i].type = req_type;
+ chosen_config.param[i].value = req_list->option[j];
+ }
+ }
+ }
+
+ if ( !match )
+ {
+#ifdef ASSERTIONS_ENABLED
+ __rt_warning( "no match found for option %x\n", req_type );
+#endif
+ return NULL;
+ }
+ }
+
+ chosen_config.num_parameters = i;
+ INFO( "match succeeded" );
+ return &chosen_config;
+}
+#endif /* defined(TARGET) || defined(TEST_PARAMS) */
+
+
+#if !defined(TARGET) || defined(TEST_PARAMS)
+/*
+ * Function: Angel_StoreParam
+ * Purpose: store the value of a given parameter to a config.
+ *
+ * see params.h for details
+ */
+bool Angel_StoreParam( ParameterConfig *config,
+ ADP_Parameter type,
+ unsigned int value )
+{
+ unsigned int i;
+
+ for ( i = 0; i < config->num_parameters; ++i )
+ if ( config->param[i].type == type )
+ {
+ config->param[i].value = value;
+ return TRUE;
+ }
+
+ return FALSE;
+}
+#endif /* !defined(TARGET) || defined(TEST_PARAMS) */
+
+
+#if defined(TARGET) || defined(LINK_RECOVERY) || defined(TEST_PARAMS)
+/*
+ * Function: Angel_BuildParamConfigMessage
+ * Purpose: write a parameter config to a buffer in ADP format.
+ *
+ * see params.h for details
+ */
+unsigned int Angel_BuildParamConfigMessage( unsigned char *buffer,
+ const ParameterConfig *config )
+{
+ unsigned char *start = buffer;
+ unsigned int i;
+
+ PUT32LE( buffer, config->num_parameters );
+ buffer += sizeof( word );
+
+ for ( i = 0; i < config->num_parameters; ++i )
+ {
+ PUT32LE( buffer, config->param[i].type );
+ buffer += sizeof( word );
+ PUT32LE( buffer, config->param[i].value );
+ buffer += sizeof( word );
+ }
+
+ return (buffer - start);
+}
+#endif /* defined(TARGET) || defined(LINK_RECOVERY) || defined(TEST_PARAMS) */
+
+
+#if !defined(TARGET) || defined(TEST_PARAMS)
+/*
+ * Function: Angel_BuildParamOptionsMessage
+ * Purpose: write a parameter Options to a buffer in ADP format.
+ *
+ * see params.h for details
+ */
+unsigned int Angel_BuildParamOptionsMessage( unsigned char *buffer,
+ const ParameterOptions *options )
+{
+ unsigned char *start = buffer;
+ unsigned int i, j;
+
+ PUT32LE( buffer, options->num_param_lists );
+ buffer += sizeof( word );
+
+ for ( i = 0; i < options->num_param_lists; ++i )
+ {
+ PUT32LE( buffer, options->param_list[i].type );
+ buffer += sizeof( word );
+ PUT32LE( buffer, options->param_list[i].num_options );
+ buffer += sizeof( word );
+ for ( j = 0; j < options->param_list[i].num_options; ++j )
+ {
+ PUT32LE( buffer, options->param_list[i].option[j] );
+ buffer += sizeof( word );
+ }
+ }
+
+ return (buffer - start);
+}
+#endif /* !defined(TARGET) || defined(TEST_PARAMS) */
+
+
+#if !defined(TARGET) || defined(LINK_RECOVERY) || defined(TEST_PARAMS)
+/*
+ * Function: Angel_ReadParamConfigMessage
+ * Purpose: read a parameter config from a buffer where it is in ADP format.
+ *
+ * see params.h for details
+ */
+bool Angel_ReadParamConfigMessage( const unsigned char *buffer,
+ ParameterConfig *config )
+{
+ unsigned int word;
+ unsigned int i;
+
+ word = GET32LE( buffer );
+ buffer += sizeof( word );
+ if ( word > config->num_parameters )
+ {
+ WARN( "not enough space" );
+ return FALSE;
+ }
+ config->num_parameters = word;
+
+ for ( i = 0; i < config->num_parameters; ++i )
+ {
+ config->param[i].type = (ADP_Parameter)GET32LE( buffer );
+ buffer += sizeof( word );
+ config->param[i].value = GET32LE( buffer );
+ buffer += sizeof( word );
+ }
+
+ return TRUE;
+}
+#endif /* !defined(TARGET) || defined(LINK_RECOVERY) || defined(TEST_PARAMS) */
+
+
+#if defined(TARGET) || defined(TEST_PARAMS)
+/*
+ * Function: Angel_ReadParamOptionsMessage
+ * Purpose: read a parameter options block from a buffer
+ * where it is in ADP format.
+ *
+ * see params.h for details
+ */
+bool Angel_ReadParamOptionsMessage( const unsigned char *buffer,
+ ParameterOptions *options )
+{
+ unsigned int word;
+ unsigned int i, j;
+
+ word = GET32LE( buffer );
+ buffer += sizeof( word );
+ if ( word > options->num_param_lists )
+ {
+ WARN( "not enough space" );
+ return FALSE;
+ }
+ options->num_param_lists = word;
+
+ for ( i = 0; i < options->num_param_lists; ++i )
+ {
+ ParameterList *list = &options->param_list[i];
+
+ list->type = (ADP_Parameter)GET32LE( buffer );
+ buffer += sizeof( word );
+ word = GET32LE( buffer );
+ buffer += sizeof( word );
+ if ( word > list->num_options )
+ {
+ WARN( "not enough list space" );
+ return FALSE;
+ }
+ list->num_options = word;
+
+ for ( j = 0; j < list->num_options; ++j )
+ {
+ list->option[j] = GET32LE( buffer );
+ buffer += sizeof( word );
+ }
+ }
+
+ return TRUE;
+}
+#endif /* defined(TARGET) || defined(TEST_PARAMS) */
+
+#endif /* !define(TARGET) || !defined(MINIMAL_ANGEL) || MINIMAL_ANGEL == 0 */
+
+/* EOF params.c */
diff --git a/gdb/rdi-share/params.h b/gdb/rdi-share/params.h
new file mode 100644
index 00000000000..5b0757bc92d
--- /dev/null
+++ b/gdb/rdi-share/params.h
@@ -0,0 +1,181 @@
+/*
+ * Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
+ *
+ * This software may be freely used, copied, modified, and distributed
+ * provided that the above copyright notice is preserved in all copies of the
+ * software.
+ */
+
+/* -*-C-*-
+ *
+ * $Revision$
+ * $Date$
+ *
+ *
+ * Project: ANGEL
+ *
+ * Title: Parameter negotiation structures and utilities
+ */
+
+#ifndef angel_params_h
+#define angel_params_h
+
+#include "angel.h"
+#include "adp.h"
+
+#ifndef TARGET
+# include "host.h"
+#endif
+
+/* A single parameter, with tag */
+typedef struct Parameter {
+ ADP_Parameter type;
+ unsigned int value;
+} Parameter;
+
+/* A list of parameter values, with tag */
+typedef struct ParameterList {
+ ADP_Parameter type;
+ unsigned int num_options;
+ unsigned int *option; /* points to array of values */
+} ParameterList;
+
+/* A configuration of one or more parameters */
+typedef struct ParameterConfig {
+ unsigned int num_parameters;
+ Parameter *param; /* pointer to array of Parameters */
+} ParameterConfig;
+
+/* A set of parameter options */
+typedef struct ParameterOptions {
+ unsigned int num_param_lists;
+ ParameterList *param_list; /* pointer to array of ParamLists */
+} ParameterOptions;
+
+/*
+ * Function: Angel_MatchParams
+ * Purpose: find a configuration from the requested options which is
+ * the best match from the supported options.
+ *
+ * Params:
+ * Input: requested The offered set of parameters.
+ * supported The supported set of parameters.
+ *
+ * Returns: ptr to config A match has been made, ptr to result
+ * will remain valid until next call to
+ * this function.
+ * NULL Match not possible
+ */
+const ParameterConfig *Angel_MatchParams( const ParameterOptions *requested,
+ const ParameterOptions *supported );
+
+/*
+ * Function: Angel_FindParam
+ * Purpose: find the value of a given parameter from a config.
+ *
+ * Params:
+ * Input: type parameter type to find
+ * config config to search
+ * Output: value parameter value if found
+ *
+ * Returns: TRUE parameter found
+ * FALSE parameter not found
+ */
+bool Angel_FindParam( ADP_Parameter type,
+ const ParameterConfig *config,
+ unsigned int *value );
+
+/*
+ * Function: Angel_StoreParam
+ * Purpose: store the value of a given parameter in a config.
+ *
+ * Params:
+ * In/Out: config config to store in
+ * Input: type parameter type to store
+ * value parameter value if found
+ *
+ * Returns: TRUE parameter found and new value stored
+ * FALSE parameter not found
+ */
+bool Angel_StoreParam( ParameterConfig *config,
+ ADP_Parameter type,
+ unsigned int value );
+
+/*
+ * Function: Angel_FindParamList
+ * Purpose: find the parameter list of a given parameter from an options.
+ *
+ * Params:
+ * Input: type parameter type to find
+ * options options block to search
+ *
+ * Returns: pointer to list
+ * NULL parameter not found
+ */
+ParameterList *Angel_FindParamList( const ParameterOptions *options,
+ ADP_Parameter type );
+
+/*
+ * Function: Angel_BuildParamConfigMessage
+ * Purpose: write a parameter config to a buffer in ADP format.
+ *
+ * Params:
+ * Input: buffer where to write to
+ * config the parameter config to write
+ *
+ * Returns: number of characters written to buffer
+ */
+unsigned int Angel_BuildParamConfigMessage( unsigned char *buffer,
+ const ParameterConfig *config );
+
+/*
+ * Function: Angel_BuildParamOptionsMessage
+ * Purpose: write a parameter Options to a buffer in ADP format.
+ *
+ * Params:
+ * Input: buffer where to write to
+ * options the options block to write
+ *
+ * Returns: number of characters written to buffer
+ */
+unsigned int Angel_BuildParamOptionsMessage( unsigned char *buffer,
+ const ParameterOptions *options );
+
+/*
+ * Function: Angel_ReadParamConfigMessage
+ * Purpose: read a parameter config from a buffer where it is in ADP format.
+ *
+ * Params:
+ * Input: buffer where to read from
+ * In/Out: config the parameter config to read to, which must
+ * be set up on entry with a valid array, and
+ * the size of the array in num_parameters.
+ *
+ * Returns: TRUE okay
+ * FALSE not enough space in config
+ */
+bool Angel_ReadParamConfigMessage( const unsigned char *buffer,
+ ParameterConfig *config );
+
+/*
+ * Function: Angel_ReadParamOptionsMessage
+ * Purpose: read a parameter options from a buffer
+ * where it is in ADP format.
+ *
+ * Params:
+ * Input: buffer where to read from
+ * In/Out: options the parameter options block to read to,
+ * which must be set up on entry with a valid
+ * array, and the size of the array in
+ * num_parameters. Each param_list must
+ * also be set up in the same way.
+ *
+ * Returns: TRUE okay
+ * FALSE not enough space in options
+ */
+bool Angel_ReadParamOptionsMessage( const unsigned char *buffer,
+ ParameterOptions *options );
+
+#endif /* ndef angel_params_h */
+
+/* EOF params.h */
diff --git a/gdb/rdi-share/rx.c b/gdb/rdi-share/rx.c
new file mode 100644
index 00000000000..4f434f0cbd6
--- /dev/null
+++ b/gdb/rdi-share/rx.c
@@ -0,0 +1,361 @@
+/*
+ * Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
+ *
+ * This software may be freely used, copied, modified, and distributed
+ * provided that the above copyright notice is preserved in all copies of the
+ * software.
+ */
+
+/*-*-C-*-
+ *
+ * $Revision$
+ * $Date$
+ *
+ *
+ * Project: ANGEL
+ *
+ * Title: Character reception engine
+ */
+
+#include <stdarg.h> /* ANSI varargs support */
+#include "angel.h" /* Angel system definitions */
+#include "endian.h" /* Endian independant memory access macros */
+#include "crc.h" /* crc generation definitions and headers */
+#include "rxtx.h"
+#include "channels.h"
+#include "buffers.h"
+#ifdef TARGET
+# include "devdriv.h"
+#endif
+#include "logging.h"
+
+static re_status unexp_stx(struct re_state *rxstate);
+static re_status unexp_etx(struct re_state *rxstate);
+
+/* bitfield for the rx_engine state */
+typedef enum rx_state_flag{
+ RST_STX,
+ RST_TYP,
+ RST_LEN,
+ RST_DAT,
+ RST_CRC,
+ RST_ETX,
+ RST_ESC = (0x1 << 0x3)
+} rx_state_flag;
+
+void Angel_RxEngineInit(const struct re_config *rxconfig,
+ struct re_state *rxstate)
+{
+ rxstate->rx_state = RST_STX;
+ rxstate->field_c = 0;
+ rxstate->index = 0;
+ rxstate->crc = 0;
+ rxstate->error = RE_OKAY;
+ rxstate->config = rxconfig;
+}
+
+re_status Angel_RxEngine(unsigned char new_ch, struct data_packet *packet,
+ struct re_state *rxstate)
+{
+ /*
+ * TODO: add the flow control bits in
+ * Note: We test for the data field in a seperate case so we can
+ * completely avoid entering the switch for most chars
+ */
+
+ /* see if we're expecting a escaped char */
+ if ((rxstate->rx_state & RST_ESC) == RST_ESC)
+ {
+ /* unescape the char and unset the flag*/
+ new_ch &= ~serial_ESCAPE;
+#ifdef DO_TRACE
+ __rt_trace("rxe-echar-%2x ", new_ch);
+#endif
+ rxstate->rx_state &= ~RST_ESC;
+ }
+ else if ( (1 << new_ch) & rxstate->config->esc_set )
+ {
+ /* see if the incoming char is a special one */
+ if (new_ch == rxstate->config->esc)
+ {
+#ifdef DO_TRACE
+ __rt_trace("rxe-esc ");
+#endif
+ rxstate->rx_state |= RST_ESC;
+ return RS_IN_PKT;
+ }
+ else
+ {
+ /*
+ * must be a normal packet so do some unexpected etx/stx checking
+ * we haven't been told to escape or received an escape so unless
+ * we are expecting an stx or etx then we can take the unexpected
+ * stx/etx trap
+ */
+ if ((new_ch == (rxstate->config->stx)) && (rxstate->rx_state != RST_STX))
+ return unexp_stx(rxstate);
+ if ((new_ch == (rxstate->config->etx)) && (rxstate->rx_state != RST_ETX))
+ return unexp_etx(rxstate);
+ }
+ }
+
+ if (rxstate->rx_state == RST_DAT)
+ {
+ /*
+ * do this to speed up the common case, no real penalty for
+ * other cases
+ */
+#ifdef DO_TRACE
+ __rt_trace("rxe-dat ");
+#endif
+
+ rxstate->crc = crc32(&new_ch, 1, rxstate->crc);
+ (packet->data)[rxstate->index++] = (unsigned int)new_ch & 0xff;
+
+ if (rxstate->index == packet->len)
+ rxstate->rx_state = RST_CRC;
+
+ return RS_IN_PKT;
+ }
+
+ /*
+ * Now that the common case is out of the way we can test for everything
+ * else without worrying quite so much about the speed, changing the
+ * order to len,crc,stx,etx,typ might gain a tiny bit of speed but lets
+ * leave that for the moment
+ */
+ switch (rxstate->rx_state)
+ {
+ case RST_STX:
+ if (new_ch == rxstate->config->stx)
+ {
+ rxstate->rx_state = RST_TYP;
+ rxstate->error = RE_OKAY;
+ rxstate->crc = startCRC32;
+ rxstate->index = 0;
+ return RS_IN_PKT;
+ }
+ else
+ {
+ rxstate->error = RE_OKAY;
+ return RS_WAIT_PKT;
+ }
+
+ case RST_TYP:
+ packet->type = (DevChanID)new_ch;
+ rxstate->rx_state = RST_LEN;
+ rxstate->error = RE_OKAY;
+ rxstate->field_c = 0; /* set up here for the length that follows */
+#ifdef DO_TRACE
+ __rt_trace("rxe-type-%2x ", packet->type);
+#endif
+ rxstate->crc = crc32(&new_ch, 1, rxstate->crc);
+
+ return RS_IN_PKT;
+
+ case RST_LEN:
+ rxstate->crc = crc32(&new_ch, 1, rxstate->crc);
+
+ if (rxstate->field_c++ == 0)
+ {
+ /* first length byte */
+ packet->len = ((unsigned int)new_ch) << 8;
+ return RS_IN_PKT;
+ }
+ else
+ {
+ /* got the whole legth */
+ packet->len |= new_ch;
+#ifdef DO_TRACE
+ __rt_trace("rxe-len-%4x\n", packet->len);
+#endif
+
+ /* check that the length is ok */
+ if (packet->len == 0)
+ {
+ /* empty pkt */
+ rxstate->field_c = 0;
+ rxstate->rx_state = RST_CRC;
+ return RS_IN_PKT;
+ }
+ else
+ {
+ if (packet->data == NULL)
+ {
+ /* need to alloc the data buffer */
+ if (!rxstate->config->ba_callback(
+ packet, rxstate->config->ba_data)) {
+ rxstate->rx_state = RST_STX;
+ rxstate->error = RE_INTERNAL;
+ return RS_BAD_PKT;
+ }
+ }
+
+ if (packet->len > packet->buf_len)
+ {
+ /* pkt bigger than buffer */
+ rxstate->field_c = 0;
+ rxstate->rx_state = RST_STX;
+ rxstate->error = RE_LEN;
+ return RS_BAD_PKT;
+ }
+ else
+ {
+ /* packet ok */
+ rxstate->field_c = 0;
+ rxstate->rx_state = RST_DAT;
+ return RS_IN_PKT;
+ }
+ }
+ }
+
+ case RST_DAT:
+ /* dummy case (dealt with earlier) */
+#ifdef ASSERTIONS_ENABLED
+ __rt_warning("ERROR: hit RST_dat in switch\n");
+#endif
+ rxstate->rx_state = RST_STX;
+ rxstate->error = RE_INTERNAL;
+ return RS_BAD_PKT;
+
+ case RST_CRC:
+ if (rxstate->field_c == 0)
+ packet->crc = 0;
+
+ packet->crc |= (new_ch & 0xFF) << ((3 - rxstate->field_c) * 8);
+ rxstate->field_c++;
+
+ if (rxstate->field_c == 4)
+ {
+ /* last crc field */
+ rxstate->field_c = 0;
+ rxstate->rx_state = RST_ETX;
+#ifdef DO_TRACE
+ __rt_trace("rxe-rcrc-%8x ", packet->crc);
+#endif
+ }
+
+ return RS_IN_PKT;
+
+ case RST_ETX:
+ if (new_ch == rxstate->config->etx)
+ {
+#if defined(DEBUG) && !defined(NO_PKT_DATA)
+ {
+ int c;
+# ifdef DO_TRACE
+ __rt_trace("\n");
+# endif
+ __rt_info("RXE Data =");
+ for (c=0; c < packet->len; c++)
+ __rt_info("%02x", packet->data[c]);
+ __rt_info("\n");
+ }
+#endif
+
+ /* check crc */
+ if (rxstate->crc == packet->crc)
+ {
+ /* crc ok */
+ rxstate->rx_state = RST_STX;
+ rxstate->field_c = 0;
+ return RS_GOOD_PKT;
+ }
+ else
+ {
+#ifdef ASSERTIONS_ENABLED
+ __rt_warning("Bad crc, rx calculates it should be 0x%x\n", rxstate->crc);
+#endif
+ rxstate->rx_state = RST_STX;
+ rxstate->error = RE_CRC;
+ return RS_BAD_PKT;
+ }
+ }
+ else if (new_ch == rxstate->config->stx)
+ return unexp_stx(rxstate);
+ else
+ {
+ rxstate->rx_state = RST_STX;
+ rxstate->error = RE_NETX;
+ return RS_BAD_PKT;
+ }
+
+ default:
+#ifdef ASSERTIONS_ENABLED
+ __rt_warning("ERROR fell through rxengine\n");
+#endif
+ rxstate->rx_state = RST_STX;
+ rxstate->error = RE_INTERNAL;
+ return RS_BAD_PKT;
+ }
+}
+
+static re_status unexp_stx(struct re_state *rxstate)
+{
+#ifdef ASSERTIONS_ENABLED
+ __rt_warning("Unexpected stx\n");
+#endif
+ rxstate->crc = startCRC32;
+ rxstate->index = 0;
+ rxstate->rx_state = RST_TYP;
+ rxstate->error = RE_U_STX;
+ rxstate->field_c = 0;
+ return RS_BAD_PKT;
+}
+
+static re_status unexp_etx(struct re_state *rxstate)
+{
+#ifdef ASSERTIONS_ENABLED
+ __rt_warning("Unexpected etx, rxstate: index= 0x%2x, field_c=0x%2x, state=0x%2x\n", rxstate->index, rxstate->field_c, rxstate->rx_state);
+#endif
+ rxstate->crc = 0;
+ rxstate->index = 0;
+ rxstate->rx_state = RST_STX;
+ rxstate->error = RE_U_ETX;
+ rxstate->field_c = 0;
+ return RS_BAD_PKT;
+}
+
+/*
+ * This can be used as the buffer allocation callback for the rx engine,
+ * and makes use of angel_DD_GetBuffer() [in devdrv.h].
+ *
+ * Saves duplicating this callback function in every device driver that
+ * uses the rx engine.
+ *
+ * Note that this REQUIRES that the device id is installed as ba_data
+ * in the rx engine config structure for the driver.
+ */
+bool angel_DD_RxEng_BufferAlloc( struct data_packet *packet, void *cb_data )
+{
+#ifdef TARGET
+ DeviceID devid = (DeviceID)cb_data;
+#else
+ IGNORE(cb_data);
+#endif
+
+ if ( packet->type < DC_NUM_CHANNELS )
+ {
+ /* request a buffer down from the channels layer */
+#ifdef TARGET
+ packet->data = angel_DD_GetBuffer( devid, packet->type,
+ packet->len );
+#else
+ packet->data = malloc(packet->len);
+#endif
+ if ( packet->data == NULL )
+ return FALSE;
+ else
+ {
+ packet->buf_len = packet->len;
+ return TRUE;
+ }
+ }
+ else
+ {
+ /* bad type field */
+ return FALSE;
+ }
+}
+
+/* EOF rx.c */
diff --git a/gdb/rdi-share/rxtx.h b/gdb/rdi-share/rxtx.h
new file mode 100644
index 00000000000..204e99870fa
--- /dev/null
+++ b/gdb/rdi-share/rxtx.h
@@ -0,0 +1,263 @@
+/*
+ * Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
+ *
+ * This software may be freely used, copied, modified, and distributed
+ * provided that the above copyright notice is preserved in all copies of the
+ * software.
+ */
+
+/*-*-C-*-
+ *
+ * $Revision$
+ * $Date$
+ *
+ *
+ * Project: ANGEL
+ *
+ * Title: Definitions required for the rx and tx engines
+ */
+
+#ifndef angel_rxtx_h
+#define angel_rxtx_h
+
+
+/*
+ * we need a definition for bool, which is "system" dependent
+ */
+#ifdef TARGET
+# include "angel.h"
+#else
+# include "host.h"
+#endif
+
+#include "devclnt.h"
+
+/* return status codes for the rx engine */
+typedef enum re_status {
+ RS_WAIT_PKT,
+ RS_IN_PKT,
+ RS_BAD_PKT,
+ RS_GOOD_PKT
+} re_status;
+
+/* return status codes for the tx engine */
+typedef enum te_status {
+ TS_IDLE,
+ TS_IN_PKT,
+ TS_DONE_PKT
+} te_status;
+
+
+/*
+ * required serial definitions, they should all be <32, refer to the
+ * re_config struct comments for more details
+ */
+#define serial_STX (0x1c) /* data packet start */
+#define serial_ETX (0x1d) /* packet end */
+#define serial_ESC (0x1b) /* standard escape character */
+#define serial_XON (0x11) /* software flow control - enable transmission */
+#define serial_XOFF (0x13) /* software flow control - disable transmission */
+
+/*
+ * All other characters are transmitted clean. If any of the above
+ * characters need to be transmitted as part of the serial data stream
+ * then the character will be preceded by the "serial_ESC" character,
+ * and then the required character transmitted (OR-ed with the
+ * "serial_ESCAPE" value, to ensure that the serial stream never has
+ * any of the exceptional characters generated by data transfers).
+ */
+
+#define serial_ESCAPE (0x40) /* OR-ed with escaped characters */
+
+/* bad packet error codes */
+typedef enum re_error {
+ RE_OKAY,
+ RE_U_STX,
+ RE_U_ETX,
+ RE_LEN,
+ RE_CRC,
+ RE_NETX,
+ RE_INTERNAL
+} re_error;
+
+/* a decoded packet */
+struct data_packet {
+ unsigned short buf_len; /* should be set by caller */
+ DevChanID type; /* valid when status is RS_GOOD_PKT */
+ unsigned short len; /* --"-- */
+ unsigned int crc; /* crc for the unescaped pkt */
+ unsigned char *data; /* should be set by caller */
+};
+
+/*
+ * Purpose: typedef for flow control function
+ *
+ * Params:
+ * Input: fc_char the flow control character in question
+ * In/Out: cb_data callback data as set in the fc_data
+ * field of re_config, typically device id
+ *
+ * This callback would tpyically respond to received XON and XOFF
+ * characters by controlling the transmit side of the device.
+ */
+typedef void (*fc_cb_func)(char fc_char, void *cb_data);
+
+
+/*
+ * Purpose: typedef for the function to alloc the data buffer
+ *
+ * Params:
+ * In/Out: packet the data packet: len and type will be set on
+ * entry, and buf_len and data should
+ * be set by this routine if successful.
+ * cb_data callback data as set in the ba_data
+ * field of re_config, typically device id
+ *
+ * Returns: TRUE buffer allocated okay
+ * FALSE couldn't allocate buffer of required size
+ * for given type
+ *
+ * This callback should attempt to acquire a buffer for the data portion
+ * of the packet which is currently being received, based on the len and
+ * type fields supplied in packet.
+ *
+ * angel_DD_RxEng_BufferAlloc() is supplied for use as this callback,
+ * and will be sufficient for most devices.
+ */
+typedef bool (*BufferAlloc_CB_Fn)(struct data_packet *packet, void *cb_data);
+
+
+/*
+ * The static info needed by the engine, may vary per device.
+ *
+ * fc_set and esc_set are bitmaps, e.g. bit 3 == charcode 3 == ASCII ETX.
+ * Thus any of the first 32 charcodes can be set for flow control or to
+ * be escaped.
+ *
+ * Note that esc_set should include all of fc_set, and should have bits
+ * set for stx, etx and esc, as a minimum.
+ *
+ * If character codes > 31 need to be used then fc_set and esc_set
+ * and their handling can be extended to use arrays and bit manipulation
+ * macros, potentially up to the full 256 possible chars.
+ *
+ * Note too that this could/should be shared with the tx engine.
+ */
+
+struct re_config {
+ unsigned char stx; /* the STX char for this device */
+ unsigned char etx; /* the ETX --"-- */
+ unsigned char esc; /* the ESC --"-- */
+ unsigned int fc_set; /* bitmap of flow control chars */
+ unsigned int esc_set; /* bitmap of special chars */
+ fc_cb_func fc_callback; /* flow control callback func */
+ void *fc_data; /* data to pass to fc_callback */
+ BufferAlloc_CB_Fn ba_callback; /* buffer alloc callback */
+ void *ba_data; /* data to pass to ba_calback */
+};
+
+/* the dynamic info needed by the rx engine */
+struct re_state {
+ unsigned char rx_state; /* 3 bits pkt state, 1 prepro state */
+ unsigned short field_c; /* chars left in current field */
+ unsigned short index; /* index into buffer */
+ unsigned int crc; /* crc accumulator */
+ re_error error; /* valid only if status is RS_BAD_PKT */
+ const struct re_config *config; /* pointer to static config */
+};
+
+/* dynamic state info needed by the tx engine */
+struct te_state {
+ unsigned short field_c; /* position in current field */
+ unsigned char tx_state; /* encodes n,e, and f (2+1+2=5 bits) */
+ unsigned char encoded; /* escape-encoded char for transmission */
+ const struct re_config *config; /* pointer to static config */
+ unsigned int crc; /* space for CRC (before escaping) */
+};
+
+/*
+ * Function: Angel_RxEngineInit
+ * Purpose: Initialise state (during device init) for engine.
+ *
+ * Params:
+ * Input: config static config info
+ * In/Out: state internal state
+ */
+
+void Angel_RxEngineInit(const struct re_config *config,
+ struct re_state *state);
+
+/*
+ * Function: Angel_RxEngine
+ * Purpose: Rx Engine for character-based devices
+ *
+ * Params:
+ * Input: new_ch the latest character
+ *
+ * In/Out: packet details of packet
+ * packet.buf_len and packet.data must
+ * be set on entry!
+ * state internal state, intially set by
+ * angel_RxEngineInit()
+ *
+ * Returns: re_status (see above)
+ *
+ */
+
+re_status Angel_RxEngine(unsigned char new_ch, struct data_packet *packet,
+ struct re_state *state);
+
+/*
+ * This can be used as the buffer allocation callback for the rx engine,
+ * and will make use of angel_DD_GetBuffer() [in devdrv.h].
+ *
+ * Saves duplicating this callback function in every device driver that
+ * uses the rx engine.
+ *
+ * Note that this REQUIRES that the device id is installed as ba_data
+ * in the rx engine config structure for the driver.
+ */
+bool angel_DD_RxEng_BufferAlloc( struct data_packet *packet, void *cb_data );
+
+/*
+ * Function: Angel_TxEngineInit
+ * Purpose: Set up tx engine at start of new packet, calculate CRC etc.
+ * (This should perform the actions described under
+ * "Initialisation" above)
+ *
+ * Params:
+ * Input: config static config info
+ * packet the packet to transmit
+ * In/Out: state internal state
+ */
+
+void Angel_TxEngineInit(const struct re_config *config,
+ const struct data_packet *packet,
+ struct te_state *state);
+
+/*
+ * Function: Angel_TxEngine
+ * Purpose: Tx Engine for character-based devices
+ *
+ * Params:
+ * Input: packet details of packet
+ * packet.len, packet.data and
+ * packet.type must
+ * be set on entry!
+ * In/Out: state internal state, intially set by
+ * angel_TxEngineStart()
+ * Output: tx_ch the character to be transmitted
+ * (NOT SET if return code is TS_IDLE)
+ *
+ * Returns: te_status (see above)
+ */
+
+te_status Angel_TxEngine(const struct data_packet *packet,
+ struct te_state *state,
+ unsigned char *tx_ch);
+
+
+
+#endif /* !defined(angel_rxtx_h) */
+
+/* EOF rxtx.h */
diff --git a/gdb/rdi-share/serdrv.c b/gdb/rdi-share/serdrv.c
new file mode 100644
index 00000000000..43fd5a00f22
--- /dev/null
+++ b/gdb/rdi-share/serdrv.c
@@ -0,0 +1,649 @@
+/*
+ * Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
+ *
+ * This software may be freely used, copied, modified, and distributed
+ * provided that the above copyright notice is preserved in all copies of the
+ * software.
+ */
+
+/* -*-C-*-
+ *
+ * $Revision$
+ * $Date$
+ *
+ *
+ * serdrv.c - Synchronous Serial Driver for Angel.
+ * This is nice and simple just to get something going.
+ */
+
+#ifdef __hpux
+# define _POSIX_SOURCE 1
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "crc.h"
+#include "devices.h"
+#include "buffers.h"
+#include "rxtx.h"
+#include "hostchan.h"
+#include "params.h"
+#include "logging.h"
+
+#ifdef COMPILING_ON_WINDOWS
+# undef ERROR
+# undef IGNORE
+# include <windows.h>
+# include "angeldll.h"
+# include "comb_api.h"
+#else
+# ifdef __hpux
+# define _TERMIOS_INCLUDED
+# include <sys/termio.h>
+# undef _TERMIOS_INCLUDED
+# else
+# include <termios.h>
+# endif
+# include "unixcomm.h"
+#endif
+
+#ifndef UNUSED
+# define UNUSED(x) (x = x) /* Silence compiler warnings */
+#endif
+
+#define MAXREADSIZE 512
+#define MAXWRITESIZE 512
+
+#define SERIAL_FC_SET ((1<<serial_XON)|(1<<serial_XOFF))
+#define SERIAL_CTL_SET ((1<<serial_STX)|(1<<serial_ETX)|(1<<serial_ESC))
+#define SERIAL_ESC_SET (SERIAL_FC_SET|SERIAL_CTL_SET)
+
+static const struct re_config config = {
+ serial_STX, serial_ETX, serial_ESC, /* self-explanatory? */
+ SERIAL_FC_SET, /* set of flow-control characters */
+ SERIAL_ESC_SET, /* set of characters to be escaped */
+ NULL /* serial_flow_control */, NULL , /* what to do with FC chars */
+ angel_DD_RxEng_BufferAlloc, NULL /* how to get a buffer */
+};
+
+static struct re_state rxstate;
+
+typedef struct writestate {
+ unsigned int wbindex;
+ /* static te_status testatus;*/
+ unsigned char writebuf[MAXWRITESIZE];
+ struct te_state txstate;
+} writestate;
+
+static struct writestate wstate;
+
+/*
+ * The set of parameter options supported by the device
+ */
+static unsigned int baud_options[] = {
+#ifdef __hpux
+ 115200, 57600,
+#endif
+ 38400, 19200, 9600
+};
+
+static ParameterList param_list[] = {
+ { AP_BAUD_RATE,
+ sizeof(baud_options)/sizeof(unsigned int),
+ baud_options }
+};
+
+static const ParameterOptions serial_options = {
+ sizeof(param_list)/sizeof(ParameterList), param_list };
+
+/*
+ * The default parameter config for the device
+ */
+static Parameter param_default[] = {
+ { AP_BAUD_RATE, 9600 }
+};
+
+static ParameterConfig serial_defaults = {
+ sizeof(param_default)/sizeof(Parameter), param_default };
+
+/*
+ * The user-modified options for the device
+ */
+static unsigned int user_baud_options[sizeof(baud_options)/sizeof(unsigned)];
+
+static ParameterList param_user_list[] = {
+ { AP_BAUD_RATE,
+ sizeof(user_baud_options)/sizeof(unsigned),
+ user_baud_options }
+};
+
+static ParameterOptions user_options = {
+ sizeof(param_user_list)/sizeof(ParameterList), param_user_list };
+
+static bool user_options_set;
+
+/* forward declarations */
+static int serial_reset( void );
+static int serial_set_params( const ParameterConfig *config );
+static int SerialMatch(const char *name, const char *arg);
+
+static void process_baud_rate( unsigned int target_baud_rate )
+{
+ const ParameterList *full_list;
+ ParameterList *user_list;
+
+ /* create subset of full options */
+ full_list = Angel_FindParamList( &serial_options, AP_BAUD_RATE );
+ user_list = Angel_FindParamList( &user_options, AP_BAUD_RATE );
+
+ if ( full_list != NULL && user_list != NULL )
+ {
+ unsigned int i, j;
+ unsigned int def_baud = 0;
+
+ /* find lower or equal to */
+ for ( i = 0; i < full_list->num_options; ++i )
+ if ( target_baud_rate >= full_list->option[i] )
+ {
+ /* copy remaining */
+ for ( j = 0; j < (full_list->num_options - i); ++j )
+ user_list->option[j] = full_list->option[i+j];
+ user_list->num_options = j;
+
+ /* check this is not the default */
+ Angel_FindParam( AP_BAUD_RATE, &serial_defaults, &def_baud );
+ if ( (j == 1) && (user_list->option[0] == def_baud) )
+ {
+#ifdef DEBUG
+ printf( "user selected default\n" );
+#endif
+ }
+ else
+ {
+ user_options_set = TRUE;
+#ifdef DEBUG
+ printf( "user options are: " );
+ for ( j = 0; j < user_list->num_options; ++j )
+ printf( "%u ", user_list->option[j] );
+ printf( "\n" );
+#endif
+ }
+
+ break; /* out of i loop */
+ }
+
+#ifdef DEBUG
+ if ( i >= full_list->num_options )
+ printf( "couldn't match baud rate %u\n", target_baud_rate );
+#endif
+ }
+#ifdef DEBUG
+ else
+ printf( "failed to find lists\n" );
+#endif
+}
+
+static int SerialOpen(const char *name, const char *arg)
+{
+ const char *port_name = name;
+
+#ifdef DEBUG
+ printf("SerialOpen: name %s arg %s\n", name, arg ? arg : "<NULL>");
+#endif
+
+#ifdef COMPILING_ON_WINDOWS
+ if (IsOpenSerial()) return -1;
+#else
+ if (Unix_IsSerialInUse()) return -1;
+#endif
+
+#ifdef COMPILING_ON_WINDOWS
+ if (SerialMatch(name, arg) != adp_ok)
+ return adp_failed;
+#else
+ port_name = Unix_MatchValidSerialDevice(port_name);
+# ifdef DEBUG
+ printf("translated port to %s\n", port_name == 0 ? "NULL" : port_name);
+# endif
+ if (port_name == 0) return adp_failed;
+#endif
+
+ user_options_set = FALSE;
+
+ /* interpret and store the arguments */
+ if ( arg != NULL )
+ {
+ unsigned int target_baud_rate;
+ target_baud_rate = (unsigned int)strtoul(arg, NULL, 10);
+ if (target_baud_rate > 0)
+ {
+#ifdef DEBUG
+ printf( "user selected baud rate %u\n", target_baud_rate );
+#endif
+ process_baud_rate( target_baud_rate );
+ }
+#ifdef DEBUG
+ else
+ printf( "could not understand baud rate %s\n", arg );
+#endif
+ }
+
+#ifdef COMPILING_ON_WINDOWS
+ {
+ int port = IsValidDevice(name);
+ if (OpenSerial(port, FALSE) != COM_OK)
+ return -1;
+ }
+#else
+ if (Unix_OpenSerial(port_name) < 0)
+ return -1;
+#endif
+
+ serial_reset();
+
+#if defined(__unix) || defined(__CYGWIN32__)
+ Unix_ioctlNonBlocking();
+#endif
+
+ Angel_RxEngineInit(&config, &rxstate);
+ /*
+ * DANGER!: passing in NULL as the packet is ok for now as it is just
+ * IGNOREd but this may well change
+ */
+ Angel_TxEngineInit(&config, NULL, &wstate.txstate);
+ return 0;
+}
+
+static int SerialMatch(const char *name, const char *arg)
+{
+ UNUSED(arg);
+#ifdef COMPILING_ON_WINDOWS
+ if (IsValidDevice(name) == COM_DEVICENOTVALID)
+ return -1;
+ else
+ return 0;
+#else
+ return Unix_MatchValidSerialDevice(name) == 0 ? -1 : 0;
+#endif
+}
+
+static void SerialClose(void)
+{
+#ifdef DO_TRACE
+ printf("SerialClose()\n");
+#endif
+
+#ifdef COMPILING_ON_WINDOWS
+ CloseSerial();
+#else
+ Unix_CloseSerial();
+#endif
+}
+
+static int SerialRead(DriverCall *dc, bool block) {
+ static unsigned char readbuf[MAXREADSIZE];
+ static int rbindex=0;
+
+ int nread;
+ int read_errno;
+ int c=0;
+ re_status restatus;
+ int ret_code = -1; /* assume bad packet or error */
+
+ /* must not overflow buffer and must start after the existing data */
+#ifdef COMPILING_ON_WINDOWS
+ {
+ BOOL dummy = FALSE;
+ nread = BytesInRXBufferSerial();
+
+ if (nread > MAXREADSIZE - rbindex)
+ nread = MAXREADSIZE - rbindex;
+
+ if ((read_errno = ReadSerial(readbuf+rbindex, nread, &dummy)) == COM_READFAIL)
+ {
+ MessageBox(GetFocus(), "Read error\n", "Angel", MB_OK | MB_ICONSTOP);
+ return -1; /* SJ - This really needs to return a value, which is picked up in */
+ /* DevSW_Read as meaning stop debugger but don't kill. */
+ }
+ else if (pfnProgressCallback != NULL && read_errno == COM_OK)
+ {
+ progressInfo.nRead += nread;
+ (*pfnProgressCallback)(&progressInfo);
+ }
+ }
+#else
+ nread = Unix_ReadSerial(readbuf+rbindex, MAXREADSIZE-rbindex, block);
+ read_errno = errno;
+#endif
+
+ if ((nread > 0) || (rbindex > 0)) {
+
+#ifdef DO_TRACE
+ printf("[%d@%d] ", nread, rbindex);
+#endif
+
+ if (nread>0)
+ rbindex = rbindex+nread;
+
+ do {
+ restatus = Angel_RxEngine(readbuf[c], &(dc->dc_packet), &rxstate);
+#ifdef DO_TRACE
+ printf("<%02X ",readbuf[c]);
+ if (!(++c % 16))
+ printf("\n");
+#else
+ c++;
+#endif
+ } while (c<rbindex &&
+ ((restatus == RS_IN_PKT) || (restatus == RS_WAIT_PKT)));
+
+#ifdef DO_TRACE
+ if (c % 16)
+ printf("\n");
+#endif
+
+ switch(restatus) {
+
+ case RS_GOOD_PKT:
+ ret_code = 1;
+ /* fall through to: */
+
+ case RS_BAD_PKT:
+ /*
+ * We now need to shuffle any left over data down to the
+ * beginning of our private buffer ready to be used
+ *for the next packet
+ */
+#ifdef DO_TRACE
+ printf("SerialRead() processed %d, moving down %d\n", c, rbindex-c);
+#endif
+ if (c != rbindex) memmove((char *) readbuf, (char *) (readbuf+c),
+ rbindex-c);
+ rbindex -= c;
+ break;
+
+ case RS_IN_PKT:
+ case RS_WAIT_PKT:
+ rbindex = 0; /* will have processed all we had */
+ ret_code = 0;
+ break;
+
+ default:
+#ifdef DEBUG
+ printf("Bad re_status in serialRead()\n");
+#endif
+ break;
+ }
+ } else if (nread == 0)
+ ret_code = 0; /* nothing to read */
+ else if (read_errno == ERRNO_FOR_BLOCKED_IO) /* nread < 0 */
+ ret_code = 0;
+
+#ifdef DEBUG
+ if ((nread<0) && (read_errno!=ERRNO_FOR_BLOCKED_IO))
+ perror("read() error in serialRead()");
+#endif
+
+ return ret_code;
+}
+
+
+static int SerialWrite(DriverCall *dc) {
+ int nwritten = 0;
+ te_status testatus = TS_IN_PKT;
+
+ if (dc->dc_context == NULL) {
+ Angel_TxEngineInit(&config, &(dc->dc_packet), &(wstate.txstate));
+ wstate.wbindex = 0;
+ dc->dc_context = &wstate;
+ }
+
+ while ((testatus == TS_IN_PKT) && (wstate.wbindex < MAXWRITESIZE))
+ {
+ /* send the raw data through the tx engine to escape and encapsulate */
+ testatus = Angel_TxEngine(&(dc->dc_packet), &(wstate.txstate),
+ &(wstate.writebuf)[wstate.wbindex]);
+ if (testatus != TS_IDLE) wstate.wbindex++;
+ }
+
+ if (testatus == TS_IDLE) {
+#ifdef DEBUG
+ printf("SerialWrite: testatus is TS_IDLE during preprocessing\n");
+#endif
+ }
+
+#ifdef DO_TRACE
+ {
+ int i = 0;
+
+ while (i<wstate.wbindex)
+ {
+ printf(">%02X ",wstate.writebuf[i]);
+
+ if (!(++i % 16))
+ printf("\n");
+ }
+ if (i % 16)
+ printf("\n");
+ }
+#endif
+
+#ifdef COMPILING_ON_WINDOWS
+ if (WriteSerial(wstate.writebuf, wstate.wbindex) == COM_OK)
+ {
+ nwritten = wstate.wbindex;
+ if (pfnProgressCallback != NULL)
+ {
+ progressInfo.nWritten += nwritten;
+ (*pfnProgressCallback)(&progressInfo);
+ }
+ }
+ else
+ {
+ MessageBox(GetFocus(), "Write error\n", "Angel", MB_OK | MB_ICONSTOP);
+ return -1; /* SJ - This really needs to return a value, which is picked up in */
+ /* DevSW_Read as meaning stop debugger but don't kill. */
+ }
+#else
+ nwritten = Unix_WriteSerial(wstate.writebuf, wstate.wbindex);
+
+ if (nwritten < 0) {
+ nwritten=0;
+ }
+#endif
+
+#ifdef DEBUG
+ if (nwritten > 0)
+ printf("Wrote %#04x bytes\n", nwritten);
+#endif
+
+ if ((unsigned) nwritten == wstate.wbindex &&
+ (testatus == TS_DONE_PKT || testatus == TS_IDLE)) {
+
+ /* finished sending the packet */
+
+#ifdef DEBUG
+ printf("SerialWrite: calling Angel_TxEngineInit after sending packet (len=%i)\n",wstate.wbindex);
+#endif
+ testatus = TS_IN_PKT;
+ wstate.wbindex = 0;
+ return 1;
+ }
+ else {
+#ifdef DEBUG
+ printf("SerialWrite: Wrote part of packet wbindex=%i, nwritten=%i\n",
+ wstate.wbindex, nwritten);
+#endif
+
+ /*
+ * still some data left to send shuffle whats left down and reset
+ * the ptr
+ */
+ memmove((char *) wstate.writebuf, (char *) (wstate.writebuf+nwritten),
+ wstate.wbindex-nwritten);
+ wstate.wbindex -= nwritten;
+ return 0;
+ }
+ return -1;
+}
+
+
+static int serial_reset( void )
+{
+#ifdef DEBUG
+ printf( "serial_reset\n" );
+#endif
+
+#ifdef COMPILING_ON_WINDOWS
+ FlushSerial();
+#else
+ Unix_ResetSerial();
+#endif
+
+ return serial_set_params( &serial_defaults );
+}
+
+
+static int find_baud_rate( unsigned int *speed )
+{
+ static struct {
+ unsigned int baud;
+ int termiosValue;
+ } possibleBaudRates[] = {
+#if defined(__hpux)
+ {115200,_B115200}, {57600,_B57600},
+#endif
+#ifdef COMPILING_ON_WINDOWS
+ {38400,CBR_38400}, {19200,CBR_19200}, {9600, CBR_9600}, {0,0}
+#else
+ {38400,B38400}, {19200,B19200}, {9600, B9600}, {0,0}
+#endif
+ };
+ unsigned int i;
+
+ /* look for lower or matching -- will always terminate at 0 end marker */
+ for ( i = 0; possibleBaudRates[i].baud > *speed; ++i )
+ /* do nothing */ ;
+
+ if ( possibleBaudRates[i].baud > 0 )
+ *speed = possibleBaudRates[i].baud;
+
+ return possibleBaudRates[i].termiosValue;
+}
+
+
+static int serial_set_params( const ParameterConfig *config )
+{
+ unsigned int speed;
+ int termios_value;
+
+#ifdef DEBUG
+ printf( "serial_set_params\n" );
+#endif
+
+ if ( ! Angel_FindParam( AP_BAUD_RATE, config, &speed ) )
+ {
+#ifdef DEBUG
+ printf( "speed not found in config\n" );
+#endif
+ return DE_OKAY;
+ }
+
+ termios_value = find_baud_rate( &speed );
+ if ( termios_value == 0 )
+ {
+#ifdef DEBUG
+ printf( "speed not valid: %u\n", speed );
+#endif
+ return DE_OKAY;
+ }
+
+#ifdef DEBUG
+ printf( "setting speed to %u\n", speed );
+#endif
+
+#ifdef COMPILING_ON_WINDOWS
+ SetBaudRate((WORD)termios_value);
+#else
+ Unix_SetSerialBaudRate(termios_value);
+#endif
+
+ return DE_OKAY;
+}
+
+
+static int serial_get_user_params( ParameterOptions **p_options )
+{
+#ifdef DEBUG
+ printf( "serial_get_user_params\n" );
+#endif
+
+ if ( user_options_set )
+ {
+ *p_options = &user_options;
+ }
+ else
+ {
+ *p_options = NULL;
+ }
+
+ return DE_OKAY;
+}
+
+
+static int serial_get_default_params( ParameterConfig **p_config )
+{
+#ifdef DEBUG
+ printf( "serial_get_default_params\n" );
+#endif
+
+ *p_config = (ParameterConfig *) &serial_defaults;
+ return DE_OKAY;
+}
+
+
+static int SerialIoctl(const int opcode, void *args) {
+
+ int ret_code;
+
+#ifdef DEBUG
+ printf( "SerialIoctl: op %d arg %p\n", opcode, args ? args : "<NULL>");
+#endif
+
+ switch (opcode)
+ {
+ case DC_RESET:
+ ret_code = serial_reset();
+ break;
+
+ case DC_SET_PARAMS:
+ ret_code = serial_set_params((const ParameterConfig *)args);
+ break;
+
+ case DC_GET_USER_PARAMS:
+ ret_code = serial_get_user_params((ParameterOptions **)args);
+ break;
+
+ case DC_GET_DEFAULT_PARAMS:
+ ret_code = serial_get_default_params((ParameterConfig **)args);
+ break;
+
+ default:
+ ret_code = DE_BAD_OP;
+ break;
+ }
+
+ return ret_code;
+}
+
+DeviceDescr angel_SerialDevice = {
+ "SERIAL",
+ SerialOpen,
+ SerialMatch,
+ SerialClose,
+ SerialRead,
+ SerialWrite,
+ SerialIoctl
+};
diff --git a/gdb/rdi-share/serpardr.c b/gdb/rdi-share/serpardr.c
new file mode 100644
index 00000000000..604d0480613
--- /dev/null
+++ b/gdb/rdi-share/serpardr.c
@@ -0,0 +1,730 @@
+/*
+ * Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
+ *
+ * This software may be freely used, copied, modified, and distributed
+ * provided that the above copyright notice is preserved in all copies of the
+ * software.
+ */
+
+/* -*-C-*-
+ *
+ * $Revision$
+ * $Date$
+ *
+ *
+ * serpardv.c - Serial/Parallel Driver for Angel.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "crc.h"
+#include "devices.h"
+#include "buffers.h"
+#include "rxtx.h"
+#include "hostchan.h"
+#include "params.h"
+#include "logging.h"
+#include "hsys.h"
+
+#ifdef COMPILING_ON_WINDOWS
+# undef ERROR
+# undef IGNORE
+# include <windows.h>
+# include "angeldll.h"
+# include "comb_api.h"
+#else
+# ifdef __hpux
+# define _TERMIOS_INCLUDED
+# include <sys/termio.h>
+# undef _TERMIOS_INCLUDED
+# else
+# include <termios.h>
+# endif
+# include "unixcomm.h"
+#endif
+
+#ifndef UNUSED
+# define UNUSED(x) (x = x) /* Silence compiler warnings */
+#endif
+
+#define MAXREADSIZE 512
+#define MAXWRITESIZE 512
+
+#define SERPAR_FC_SET ((1 << serial_XON) | (1 << serial_XOFF))
+#define SERPAR_CTL_SET ((1 << serial_STX) | (1 << serial_ETX) | \
+ (1 << serial_ESC))
+#define SERPAR_ESC_SET (SERPAR_FC_SET | SERPAR_CTL_SET)
+
+static const struct re_config config = {
+ serial_STX, serial_ETX, serial_ESC, /* self-explanatory? */
+ SERPAR_FC_SET, /* set of flow-control characters */
+ SERPAR_ESC_SET, /* set of characters to be escaped */
+ NULL, /* serial_flow_control */
+ NULL, /* what to do with FC chars */
+ angel_DD_RxEng_BufferAlloc, NULL /* how to get a buffer */
+};
+
+static struct re_state rxstate;
+
+/*
+ * structure used for manipulating transmit data
+ */
+typedef struct TxState
+{
+ struct te_state state;
+ unsigned int index;
+ unsigned char writebuf[MAXWRITESIZE];
+} TxState;
+
+/*
+ * The set of parameter options supported by the device
+ */
+static unsigned int baud_options[] =
+{
+#ifdef __hpux
+ 115200, 57600,
+#endif
+ 38400, 19200, 9600
+};
+
+static ParameterList param_list[] =
+{
+ {
+ AP_BAUD_RATE,
+ sizeof(baud_options) / sizeof(unsigned int),
+ baud_options
+ }
+};
+
+static const ParameterOptions serpar_options =
+{
+ sizeof(param_list) / sizeof(ParameterList),
+ param_list
+};
+
+/*
+ * The default parameter config for the device
+ */
+static Parameter param_default[] =
+{
+ { AP_BAUD_RATE, 9600 }
+};
+
+static const ParameterConfig serpar_defaults =
+{
+ sizeof(param_default)/sizeof(Parameter),
+ param_default
+};
+
+/*
+ * The user-modified options for the device
+ */
+static unsigned int user_baud_options[sizeof(baud_options) /
+ sizeof(unsigned int)];
+
+static ParameterList param_user_list[] =
+{
+ {
+ AP_BAUD_RATE,
+ sizeof(user_baud_options) / sizeof(unsigned),
+ user_baud_options
+ }
+};
+
+static ParameterOptions user_options =
+{
+ sizeof(param_user_list) / sizeof(ParameterList),
+ param_user_list
+};
+
+static bool user_options_set;
+
+/* forward declarations */
+static int serpar_reset(void);
+static int serpar_set_params(const ParameterConfig *config);
+static int SerparMatch(const char *name, const char *arg);
+
+static void process_baud_rate(unsigned int target_baud_rate)
+{
+ const ParameterList *full_list;
+ ParameterList *user_list;
+
+ /* create subset of full options */
+ full_list = Angel_FindParamList(&serpar_options, AP_BAUD_RATE);
+ user_list = Angel_FindParamList(&user_options, AP_BAUD_RATE);
+
+ if (full_list != NULL && user_list != NULL)
+ {
+ unsigned int i, j;
+ unsigned int def_baud = 0;
+
+ /* find lower or equal to */
+ for (i = 0; i < full_list->num_options; ++i)
+ if (target_baud_rate >= full_list->option[i])
+ {
+ /* copy remaining */
+ for (j = 0; j < (full_list->num_options - i); ++j)
+ user_list->option[j] = full_list->option[i+j];
+ user_list->num_options = j;
+
+ /* check this is not the default */
+ Angel_FindParam(AP_BAUD_RATE, &serpar_defaults, &def_baud);
+ if ((j == 1) && (user_list->option[0] == def_baud))
+ {
+#ifdef DEBUG
+ printf("user selected default\n");
+#endif
+ }
+ else
+ {
+ user_options_set = TRUE;
+#ifdef DEBUG
+ printf("user options are: ");
+ for (j = 0; j < user_list->num_options; ++j)
+ printf("%u ", user_list->option[j]);
+ printf("\n");
+#endif
+ }
+
+ break; /* out of i loop */
+ }
+
+#ifdef DEBUG
+ if (i >= full_list->num_options)
+ printf("couldn't match baud rate %u\n", target_baud_rate);
+#endif
+ }
+#ifdef DEBUG
+ else
+ printf("failed to find lists\n");
+#endif
+}
+
+static int SerparOpen(const char *name, const char *arg)
+{
+ char *sername = NULL;
+ char *parname = NULL;
+
+#ifdef DEBUG
+ printf("SerparOpen: name %s arg %s\n", name, arg ? arg : "<NULL>");
+#endif
+
+#ifdef COMPILING_ON_WINDOWS
+ if (IsOpenSerial() || IsOpenParallel()) return -1;
+#else
+ if (Unix_IsSerialInUse() || Unix_IsParallelInUse()) return -1;
+#endif
+
+#ifdef COMPILING_ON_WINDOWS
+ if (SerparMatch(name, arg) == -1)
+ return -1;
+#else
+ Unix_IsValidParallelDevice(name,&sername,&parname);
+# ifdef DEBUG
+ printf("translated %s to serial %s and parallel %s\n",
+ name==0 ? "NULL" : name,
+ sername==0 ? "NULL" : sername,
+ parname==0 ? "NULL" : parname);
+# endif
+ if (sername==NULL || parname==NULL) return -1;
+#endif
+
+ user_options_set = FALSE;
+
+ /* interpret and store the arguments */
+ if (arg != NULL)
+ {
+ unsigned int target_baud_rate;
+
+ target_baud_rate = (unsigned int)strtoul(arg, NULL, 10);
+
+ if (target_baud_rate > 0)
+ {
+#ifdef DEBUG
+ printf("user selected baud rate %u\n", target_baud_rate);
+#endif
+ process_baud_rate(target_baud_rate);
+ }
+#ifdef DEBUG
+ else
+ printf("could not understand baud rate %s\n", arg);
+#endif
+ }
+
+#ifdef COMPILING_ON_WINDOWS
+ {
+ /*
+ * The serial port number is in name[0] followed by
+ * the parallel port number in name[1]
+ */
+
+ int sport = name[0] - '0';
+ int pport = name[1] - '0';
+
+ if (OpenParallel(pport) != COM_OK)
+ return -1;
+
+ if (OpenSerial(sport, FALSE) != COM_OK)
+ {
+ CloseParallel();
+ return -1;
+ }
+ }
+#else
+ Unix_OpenParallel(parname);
+ Unix_OpenSerial(sername);
+#endif
+
+ serpar_reset();
+
+#if defined(__unix) || defined(__CYGWIN32__)
+ Unix_ioctlNonBlocking();
+#endif
+
+ Angel_RxEngineInit(&config, &rxstate);
+
+ return 0;
+}
+
+#ifdef COMPILING_ON_WINDOWS
+static int SerparMatch(const char *name, const char *arg)
+{
+ char sername[2];
+ char parname[2];
+
+ UNUSED(arg);
+
+ sername[0] = name[0];
+ parname[0] = name[1];
+ sername[1] = parname[1] = 0;
+
+ if (IsValidDevice(sername) == COM_DEVICENOTVALID ||
+ IsValidDevice(parname) == COM_DEVICENOTVALID)
+ return -1;
+ else
+ return 0;
+}
+#else
+static int SerparMatch(const char *portstring, const char *arg)
+{
+ char *sername=NULL, *parname=NULL;
+ UNUSED(arg);
+
+ Unix_IsValidParallelDevice(portstring,&sername,&parname);
+
+ /* Match failed if either sername or parname are still NULL */
+ if (sername==NULL || parname==NULL) return -1;
+ return 0;
+}
+#endif
+
+static void SerparClose(void)
+{
+#ifdef COMPILING_ON_WINDOWS
+ CloseParallel();
+ CloseSerial();
+#else
+ Unix_CloseParallel();
+ Unix_CloseSerial();
+#endif
+}
+
+static int SerparRead(DriverCall *dc, bool block)
+{
+ static unsigned char readbuf[MAXREADSIZE];
+ static int rbindex = 0;
+
+ int nread;
+ int read_errno;
+ int c = 0;
+ re_status restatus;
+ int ret_code = -1; /* assume bad packet or error */
+
+ /*
+ * we must not overflow buffer, and must start after
+ * the existing data
+ */
+#ifdef COMPILING_ON_WINDOWS
+ {
+ BOOL dummy = FALSE;
+ nread = BytesInRXBufferSerial();
+
+ if (nread > MAXREADSIZE - rbindex)
+ nread = MAXREADSIZE - rbindex;
+ read_errno = ReadSerial(readbuf+rbindex, nread, &dummy);
+ if (pfnProgressCallback != NULL && read_errno == COM_OK)
+ {
+ progressInfo.nRead += nread;
+ (*pfnProgressCallback)(&progressInfo);
+ }
+ }
+#else
+ nread = Unix_ReadSerial(readbuf+rbindex, MAXREADSIZE-rbindex, block);
+ read_errno = errno;
+#endif
+
+ if ((nread > 0) || (rbindex > 0))
+ {
+#ifdef DO_TRACE
+ printf("[%d@%d] ", nread, rbindex);
+#endif
+
+ if (nread > 0)
+ rbindex = rbindex + nread;
+
+ do
+ {
+ restatus = Angel_RxEngine(readbuf[c], &(dc->dc_packet), &rxstate);
+
+#ifdef DO_TRACE
+ printf("<%02X ",readbuf[c]);
+#endif
+ c++;
+ } while (c < rbindex &&
+ ((restatus == RS_IN_PKT) || (restatus == RS_WAIT_PKT)));
+
+#ifdef DO_TRACE
+ printf("\n");
+#endif
+
+ switch(restatus)
+ {
+ case RS_GOOD_PKT:
+ ret_code = 1;
+ /* fall through to: */
+
+ case RS_BAD_PKT:
+ /*
+ * We now need to shuffle any left over data down to the
+ * beginning of our private buffer ready to be used
+ *for the next packet
+ */
+#ifdef DO_TRACE
+ printf("SerparRead() processed %d, moving down %d\n",
+ c, rbindex - c);
+#endif
+
+ if (c != rbindex)
+ memmove((char *) readbuf, (char *) (readbuf + c), rbindex - c);
+
+ rbindex -= c;
+
+ break;
+
+ case RS_IN_PKT:
+ case RS_WAIT_PKT:
+ rbindex = 0; /* will have processed all we had */
+ ret_code = 0;
+ break;
+
+ default:
+#ifdef DEBUG
+ printf("Bad re_status in SerparRead()\n");
+#endif
+ break;
+ }
+ }
+ else if (nread == 0)
+ /* nothing to read */
+ ret_code = 0;
+ else if (read_errno == ERRNO_FOR_BLOCKED_IO) /* nread < 0 */
+ ret_code = 0;
+
+#ifdef DEBUG
+ if ((nread < 0) && (read_errno != ERRNO_FOR_BLOCKED_IO))
+ perror("read() error in SerparRead()");
+#endif
+
+ return ret_code;
+}
+
+/*
+ * Function: send_packet
+ * Purpose: Send a stream of bytes to Angel through the parallel port
+ *
+ * Algorithm: We need to present the data in a form that all boards can
+ * swallow. With the PID board, this is a problem: for reasons
+ * described in the driver (angel/pid/st16c552.c), data are
+ * sent a nybble at a time on D0-D2 and D4; D3 is wired to ACK,
+ * which generates an interrupt when it goes low. This routine
+ * fills in an array of nybbles, with ACK clear in all but the
+ * last one. If, for whatever reason, the write fails, then
+ * ACK is forced high (thereby enabling the next write a chance
+ * to be noticed when the falling edge of ACK generates an
+ * interrupt (hopefully).
+ *
+ * Params:
+ * Input: txstate Contains the packet to be sent
+ *
+ * Returns: Number of *complete* bytes written
+ */
+
+static int SerparWrite(DriverCall *dc)
+{
+ te_status status;
+ int nwritten = 0;
+ static TxState txstate;
+
+ /*
+ * is this a new packet?
+ */
+ if (dc->dc_context == NULL)
+ {
+ /*
+ * yes - initialise TxEngine
+ */
+ Angel_TxEngineInit(&config, &dc->dc_packet, &txstate.state);
+
+ txstate.index = 0;
+ dc->dc_context = &txstate;
+ }
+
+ /*
+ * fill the buffer using the Tx Engine
+ */
+ do
+ {
+ status = Angel_TxEngine(&dc->dc_packet, &txstate.state,
+ &txstate.writebuf[txstate.index]);
+ if (status != TS_IDLE) txstate.index++;
+
+ } while (status == TS_IN_PKT && txstate.index < MAXWRITESIZE);
+
+#ifdef DO_TRACE
+ {
+ unsigned int i = 0;
+
+ while (i < txstate.index)
+ {
+ printf(">%02X ", txstate.writebuf[i]);
+
+ if (!(++i % 16))
+ putc('\n', stdout);
+ }
+
+ if (i % 16)
+ putc('\n', stdout);
+ }
+#endif
+
+ /*
+ * the data are ready, all we need now is to send them out
+ * in a form that Angel can swallow.
+ */
+#ifdef COMPILING_ON_WINDOWS
+ if (WriteParallel(txstate.writebuf, txstate.index) == COM_OK)
+ {
+ nwritten = txstate.index;
+ if (pfnProgressCallback != NULL)
+ {
+ progressInfo.nWritten += nwritten;
+ (*pfnProgressCallback)(&progressInfo);
+ }
+ }
+ else
+ {
+ MessageBox(GetFocus(), "Write error\n", "Angel", MB_OK | MB_ICONSTOP);
+ return -1; /* SJ - This really needs to return a value, which is picked up in */
+ /* DevSW_Read as meaning stop debugger but don't kill. */
+ }
+#else
+ nwritten = Unix_WriteParallel(txstate.writebuf, txstate.index);
+#endif
+
+ if (nwritten < 0) nwritten = 0;
+
+#ifdef DO_TRACE
+ printf("SerparWrite: wrote %d out of %d bytes\n",
+ nwritten, txstate.index);
+#endif
+
+ /*
+ * has the whole packet gone?
+ */
+ if (nwritten == (int)txstate.index &&
+ (status == TS_DONE_PKT || status == TS_IDLE))
+ /*
+ * yes it has
+ */
+ return 1;
+ else
+ {
+ /*
+ * if some data are left, shuffle them
+ * to the start of the buffer
+ */
+ if (nwritten != (int)txstate.index && nwritten != 0)
+ {
+ txstate.index -= nwritten;
+ (void)memmove((char *) txstate.writebuf,
+ (char *) (txstate.writebuf + nwritten),
+ txstate.index);
+ }
+ else if (nwritten == (int)txstate.index)
+ txstate.index = 0;
+
+ return 0;
+ }
+}
+
+static int serpar_reset(void)
+{
+#ifdef COMPILING_ON_WINDOWS
+ FlushParallel();
+ FlushSerial();
+#else
+ Unix_ResetParallel();
+ Unix_ResetSerial();
+#endif
+
+ return serpar_set_params(&serpar_defaults);
+}
+
+static int find_baud_rate(unsigned int *speed)
+{
+ static struct
+ {
+ unsigned int baud;
+ int termiosValue;
+ } possibleBaudRates[] =
+ {
+#if defined(__hpux)
+ {115200, _B115200}, {57600, _B57600},
+#endif
+#ifdef COMPILING_ON_WINDOWS
+ {38400, CBR_38400}, {19200, CBR_19200}, {9600, CBR_9600}, {0, 0}
+#else
+ {38400, B38400}, {19200, B19200}, {9600, B9600}, {0, 0}
+#endif
+ };
+ unsigned int i;
+
+ /* look for lower or matching -- will always terminate at 0 end marker */
+ for (i = 0; possibleBaudRates[i].baud > *speed; ++i)
+ /* do nothing */
+ ;
+
+ if (possibleBaudRates[i].baud > 0)
+ *speed = possibleBaudRates[i].baud;
+
+ return possibleBaudRates[i].termiosValue;
+}
+
+static int serpar_set_params(const ParameterConfig *config)
+{
+ unsigned int speed;
+ int termios_value;
+
+#ifdef DEBUG
+ printf("serpar_set_params\n");
+#endif
+
+ if (!Angel_FindParam(AP_BAUD_RATE, config, &speed))
+ {
+#ifdef DEBUG
+ printf("speed not found in config\n");
+#endif
+ return DE_OKAY;
+ }
+
+ termios_value = find_baud_rate(&speed);
+ if (termios_value == 0)
+ {
+#ifdef DEBUG
+ printf("speed not valid: %u\n", speed);
+#endif
+ return DE_OKAY;
+ }
+
+#ifdef DEBUG
+ printf("setting speed to %u\n", speed);
+#endif
+
+#ifdef COMPILING_ON_WINDOWS
+ SetBaudRate((WORD)termios_value);
+#else
+ Unix_SetSerialBaudRate(termios_value);
+#endif
+
+ return DE_OKAY;
+}
+
+
+static int serpar_get_user_params(ParameterOptions **p_options)
+{
+#ifdef DEBUG
+ printf("serpar_get_user_params\n");
+#endif
+
+ if (user_options_set)
+ {
+ *p_options = &user_options;
+ }
+ else
+ {
+ *p_options = NULL;
+ }
+
+ return DE_OKAY;
+}
+
+
+static int serial_get_default_params( const ParameterConfig **p_config )
+{
+#ifdef DEBUG
+ printf( "serial_get_default_params\n" );
+#endif
+
+ *p_config = &serpar_defaults;
+ return DE_OKAY;
+}
+
+
+static int SerparIoctl(const int opcode, void *args)
+{
+ int ret_code;
+
+#ifdef DEBUG
+ printf("SerparIoctl: op %d arg %p\n", opcode, args ? args : "<NULL>");
+#endif
+
+ switch (opcode)
+ {
+ case DC_RESET:
+ ret_code = serpar_reset();
+ break;
+
+ case DC_SET_PARAMS:
+ ret_code = serpar_set_params((const ParameterConfig *)args);
+ break;
+
+ case DC_GET_USER_PARAMS:
+ ret_code = serpar_get_user_params((ParameterOptions **)args);
+ break;
+
+ case DC_GET_DEFAULT_PARAMS:
+ ret_code =
+ serial_get_default_params((const ParameterConfig **)args);
+ break;
+
+ default:
+ ret_code = DE_BAD_OP;
+ break;
+ }
+
+ return ret_code;
+}
+
+DeviceDescr angel_SerparDevice =
+{
+ "SERPAR",
+ SerparOpen,
+ SerparMatch,
+ SerparClose,
+ SerparRead,
+ SerparWrite,
+ SerparIoctl
+};
+
+/* EOF serpardr.c */
diff --git a/gdb/rdi-share/sys.h b/gdb/rdi-share/sys.h
new file mode 100644
index 00000000000..b68ac785cd6
--- /dev/null
+++ b/gdb/rdi-share/sys.h
@@ -0,0 +1,319 @@
+/*
+ * Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
+ *
+ * This software may be freely used, copied, modified, and distributed
+ * provided that the above copyright notice is preserved in all copies of the
+ * software.
+ */
+
+/* sys.h
+ ***********************************************************************
+ * Angel C Libary support channel protocol definitions
+ *
+ * $Revision$
+ * $Date$
+ *
+ *
+ *
+ *
+ * MESSAGE FORMAT
+ * --------------
+ * Format of the "data" section of C Lib Support Channel Messages.
+ * You will notice that the format is much the same as the format
+ * of ADP messages - this is so that multi-threaded C Libraries can
+ * be supported.
+ *
+ * unsigned32 reason - Main C Library reason code.
+ * unsigned32 debugID - Info. describing host debug world;
+ * private to host and used in any target
+ * initiated messages.
+ * unsigned32 OSinfo1 \ Target OS information to identify process/thread
+ * unsigned32 OSinfo2 / world, etc. These two fields are target defined.
+ * byte args[n] - Data for message "reason" code.
+ *
+ * The "debugID" is defined by the host-end of the protocol, and is used
+ * by the host to ensure that messages are routed to the correct handler
+ * program/veneer (eg. imagine several threads having opened stdout and
+ * each writing to a different window in a windowed debugger).
+ *
+ * NOTE: The reason that there is no "size" information, is that the
+ * message IDs themselves encode the format of any arguments.
+ *
+ * For further discussion of the format see adp.h
+ *
+ * N.B. All streams are little endian.
+ *
+ * CLIB REASON CODE
+ * ----------------
+ * The message reason codes contain some information that ties them to
+ * the channel and direction that the message will be used with. This
+ * will ensure that even if the message "#define name" is not
+ * completely descriptive, the message reason code is.
+ *
+ * b31 = direction. 0=Host-to-Target; 1=Target-to-Host;
+ * b30-16 = reserved. should be zero
+ * b15-0 = message reason code.
+ *
+ * Note that typically a request will be initiated by the target side, and
+ * that the host will then respond with either an acknowledgement or some
+ * data. In either case the same reason code will be used, but the direction
+ * bit will be reveresed.
+ */
+
+#ifndef __sys_h
+#define __sys_h
+
+#ifndef HtoT
+#define HtoT ((unsigned)0 << 31) /* Host-to-Target message */
+#define TtoH ((unsigned)1 << 31) /* Target-to-Host message */
+#endif
+
+/*
+ * The following are error codes used in the status field returned on
+ * sending a message. 0 represents no error having occurred, non-zero
+ * represents a general error. More codes should be added as required.
+ */
+
+#ifndef ErrCode
+#define NoError 0x0
+#endif
+
+/*************************************************************************/
+/* The following are direct conversions of the DeMon SWI's */
+/* NB: nbytes is the number of bytes INCLUDING THE NULL character where */
+/* applicable. */
+
+/* This message is used as a response to a packet whose message
+ * was not understood. The return parameter, code is the reason
+ * code which was not understood. Although intended for use as a
+ * default case on a received message switch it can also be used
+ * as a proper message*/
+#define CL_Unrecognised 0x00
+ /* Unrecognised()
+ * return(word code)
+ */
+
+/* Write a character to the terminal.
+ */
+#define CL_WriteC 0x01
+ /* WriteC(byte data)
+ * return(word status)
+ */
+
+/* Write a NULL terminated string of characters to the terminal. The length
+ * of the string excluding the NULL terminating character is passed in
+ * 'nbytes'.
+ */
+#define CL_Write0 0x02
+ /* Write0(word nbytes, bytes data)
+ * return(word status)
+ */
+
+/* Read a character from the terminal - probably the keyboard.
+ */
+#define CL_ReadC 0x04
+ /* ReadC(void)
+ * return(word status, byte data)
+ */
+
+/* Perform system call, pass NULL terminated string to host's command
+ * line interpreter(NOT AVAILABLE IN PC/DOS RELEASE). The data byte
+ * returned holds the return code from the system call.
+ */
+#define CL_System 0x05
+ /* CLI(word nbytes, bytes data)
+ * return(word status, word data)
+ */
+
+/* It returns the address of the null terminated command line string used to
+ * invoke the program. status will be set to NoError if the command line
+ * can be returned. Other status values will be treated as error conditions.
+ */
+#define CL_GetCmdLine 0x10
+ /* GetCmdLine(void)
+ * return(word status, word nbytes, bytes argline)
+ */
+
+/* Return the number of centi-seconds since the support code began
+ * execution. Only the difference between successive calls can be
+ * meaningful.
+ */
+#define CL_Clock 0x61
+ /* Clock(void)
+ * return(word status, word clks)
+ */
+
+/* Return the number of seconds since the beginning of 1970.
+ */
+#define CL_Time 0x63
+ /* Time(void)
+ * return(word status, word time)
+ */
+
+/* Delete(remove, un-link, wipe, destroy) the file named by the
+ * NULL-terminated string 'name'.
+ */
+#define CL_Remove 0x64
+ /* Remove(word nbytes, bytes name)
+ * return(word status)
+ */
+
+/* Rename the file specified by the NULL-terminated string 'oname'
+ * to 'nname'.
+ */
+#define CL_Rename 0x65
+ /* Rename(word nbytes, bytes oname, word nbytes, bytes nname)
+ * return(word status)
+ */
+
+/* 'name' specifies a NULL-terminated string containing a file name or a
+ * device name. Opens the file/device and returns a non-zero handle on
+ * success that can be quoted to CL_Close, CL_Read, CL_Write, CL_Seek,
+ * CL_Flen or CL_IsTTY. The mode is an integer in the range 0-11:-
+ *
+ * Mode: 0 1 2 3 4 5 6 7 8 9 10 11
+ * ANSI C fopen mode: r rb r+ r+b w wb w+ w+b a ab a+ a+b
+ *
+ * Values 12-15 are illegal. If 'name' is ":tt" the stdin/stdout is
+ * opened depending on whether 'mode' is read or write.
+ */
+#define CL_Open 0x66
+ /* Open(word nbytes, bytes name, word mode)
+ * return(word handle)
+ */
+
+/* 'handle' is a file handle previously returned by CL_Open. CL_Close
+ * closes the file.
+ */
+#define CL_Close 0x68
+ /* Close(word handle)
+ * return(word status)
+ */
+
+/* Writes data of length nbytes to the file/device specified by
+ * handle. nbtotal represents the total number of bytes to be
+ * written, whereas nbytes is the number of bytes in this packet
+ *
+ * If nbtotal is <= DATASIZE - CL_Write message header size in the
+ * packet then nbytes = nbtotal and the number of bytes not written
+ * is returned. If nbtotal is > the packet size then the CL_Write
+ * must be followed by a number of CL_WriteX's to complete the write,
+ * the nbytes returned by CL_Write can be ignored
+ * If the status word returned is non zero, an error has occurred and
+ * the write request has been aborted.
+ *
+ */
+#define CL_Write 0x69
+ /* Write(word handle, word nbtotal, word nbytes, bytes data)
+ * return(word status, word nbytes)
+ */
+
+/* Write Extension is a reads a continuation of data from a CL_Write
+ * which was too big to fit in a single packet.
+ * nbytes is the number of bytes of data in this packet, the
+ * returned value of nbytes can be ignored except if it is the
+ * last packet, in which case it is the number of bytes that were NOT
+ * written
+ */
+#define CL_WriteX 0x6A
+ /* WriteX(word nbytes, bytes data)
+ * return(word status, word nbytes)
+ */
+
+/* Reads 'nbytes' from the file/device specified by 'handle'.
+ *
+ * If nbytes <= DATASIZE then the read will occur in a single packet
+ * and the returned value of nbytes will be the number of bytes actually
+ * read and nbmore will be 0. If nbytes> DATASIZE then multiple packets
+ * will have to be used ie CL_Read followed by 1 or more CL_ReadX
+ * packets. In this case CL_Read will return nbytes read in the current
+ * packet and nbmore representing how many more bytes are expected to be
+ * read
+ * If the status word is non zero then the request has completed with an
+ * error. If the status word is 0xFFFFFFFF (-1) then an EOF condition
+ * has been reached.
+ */
+#define CL_Read 0x6B
+ /* Read(word handle, word nbytes)
+ * return(word status, word nbytes, word nbmore, bytes data)
+ */
+
+/* Read eXtension returns a continuation of the data that was opened for
+ * read in the earlier CL_Read. The return value nbytes is the number of
+ * data bytes in the packet, nbmore is the number of bytes more that are
+ * expected to be read in subsequent packets.
+ */
+#define CL_ReadX 0x6C
+ /* ReadX()
+ * return(word status, word nbytes, word nbmore, bytes data)
+ */
+
+/* Seeks to byte position 'posn' in the file/device specified by 'handle'.
+ */
+#define CL_Seek 0x6D
+ /* Seek(word handle, word posn)
+ * return(word status)
+ */
+
+/* Returns the current length of the file specified by 'handle' in 'len'.
+ * If an error occurs 'len' is set to -1.
+ */
+#define CL_Flen 0x6E
+ /* Flen(word handle)
+ * return(word len)
+ */
+
+/* Returns NoError if 'handle' specifies an interactive device, otherwise
+ * returns GenError
+ */
+#define CL_IsTTY 0x6F
+ /* IsTTY(word handle)
+ * return(word status)
+ */
+
+/* Returns a temporary host file name. The maximum length of a file name
+ * is passed to the host. The TargetID is some identifier from the target
+ * for this particular temporary filename. This value is could be used
+ * directly in the generation of the filename.
+ *
+ * If the host cannot create a suitable name or the generated name is too
+ * long then status is non zero. status will be NoError if the host can create
+ * a name.
+ */
+#define CL_TmpNam 0x70
+ /* TmpNam(word maxlength, word TargetID)
+ * return(word status, word nbytes, bytes fname)
+ */
+
+/* Note there is no message for Exit, EnterOS, InstallHandler or
+ * GenerateError as these will be supported entirely at the host end,
+ * or by the underlying Operating system.
+ */
+
+#define CL_UnknownReason (-1)
+
+extern unsigned int GetRaiseHandler( void );
+extern unsigned int SysLibraryHandler(unsigned int sysCode, unsigned int *args);
+extern void angel_SysLibraryInit(void);
+
+/*
+ * Function: Angel_IsSysHandlerRunning
+ * Purpose: return whether or not SysLibraryHandler is running
+ *
+ * No paramaters
+ *
+ * Returns 1 if SysLibraryHandler is running
+ * 0 otherwise
+ */
+extern int Angel_IsSysHandlerRunning(void);
+
+#ifdef ICEMAN2
+/* This function exists in an ICEman2 system only, and can be called by
+ * debug support code when the debugger tells it how much memory the
+ * target has. This will then be used to deal with the HEAPINFO SWI
+ */
+extern void angel_SetTopMem(unsigned addr);
+#endif
+
+#endif
+
diff --git a/gdb/rdi-share/tx.c b/gdb/rdi-share/tx.c
new file mode 100644
index 00000000000..a52286c12b5
--- /dev/null
+++ b/gdb/rdi-share/tx.c
@@ -0,0 +1,176 @@
+/*
+ * Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
+ *
+ * This software may be freely used, copied, modified, and distributed
+ * provided that the above copyright notice is preserved in all copies of the
+ * software.
+ */
+
+/*-*-C-*-
+ *
+ * $Revision$
+ * $Date$
+ *
+ * Project: ANGEL
+ *
+ * Title: Character based packet transmission engine
+ */
+
+#include <stdarg.h> /* ANSI varargs support */
+#include "angel.h" /* Angel system definitions */
+#include "endian.h" /* Endian independant memory access macros */
+#include "crc.h" /* crc generation definitions and headers */
+#include "rxtx.h"
+#include "channels.h"
+#include "buffers.h"
+#include "logging.h"
+
+/* definitions to describe the engines state */
+#define N_STX 0x0 /* first 2 bits for N_ */
+#define N_BODY 0x1
+#define N_ETX 0x2
+#define N_IDLE 0x3
+#define N_MASK 0x3 /* mask for the Encapsulator state */
+
+#define E_PLAIN (0x0 << 2) /* 3rd bit for E_ */
+#define E_ESC (0x1 << 2) /* 3rd bit for E_ */
+#define E_MASK (0x1 << 2) /* mask for the Escaper state */
+
+#define F_HEAD (0x0 << 3) /* 4th and 5th bits for F_ */
+#define F_DATA (0x1 << 3)
+#define F_CRC (0x1 << 4)
+#define F_MASK (0x3 << 3) /* mask for the Escaper state */
+
+static unsigned char escape(unsigned char ch_in, struct te_state *txstate);
+
+void Angel_TxEngineInit(const struct re_config *txconfig,
+ const struct data_packet *packet,
+ struct te_state *txstate){
+ IGNORE(packet);
+ txstate->tx_state = N_STX | E_PLAIN | F_HEAD;
+ txstate->field_c = 0;
+ txstate->encoded = 0;
+ txstate->config = txconfig;
+ txstate->crc = 0;
+}
+
+te_status Angel_TxEngine(const struct data_packet *packet,
+ struct te_state *txstate,
+ unsigned char *tx_ch){
+ /* TODO: gaurd on long/bad packets */
+ /*
+ * encapsulate the packet, framing has been moved from a seperate
+ * function into the encapsulation routine as it needed too much
+ * inherited state for it to be sensibly located elsewhere
+ */
+ switch ((txstate->tx_state) & N_MASK){
+ case N_STX:
+#ifdef DO_TRACE
+ __rt_trace("txe-stx ");
+#endif
+ txstate->tx_state = (txstate->tx_state & ~N_MASK) | N_BODY;
+ *tx_ch = txstate->config->stx;
+ txstate->field_c = 3; /* set up for the header */
+ txstate->crc = startCRC32; /* set up basic crc */
+ return TS_IN_PKT;
+ case N_BODY:{
+ switch (txstate->tx_state & F_MASK) {
+ case F_HEAD:
+#ifdef DO_TRACE
+ __rt_trace("txe-head ");
+#endif
+ if (txstate->field_c == 3) {
+ /* send type */
+ *tx_ch = escape(packet->type, txstate);
+ return TS_IN_PKT;
+ }
+ else {
+ *tx_ch = escape((packet->len >> (txstate->field_c - 1) * 8) & 0xff,
+ txstate);
+ if (txstate->field_c == 0) {
+ /* move on to the next state */
+ txstate->tx_state = (txstate->tx_state & ~F_MASK) | F_DATA;
+ txstate->field_c = packet->len;
+ }
+ return TS_IN_PKT;
+ }
+ case F_DATA:
+#ifdef DO_TRACE
+ __rt_trace("txe-data ");
+#endif
+ *tx_ch = escape(packet->data[packet->len - txstate->field_c], txstate);
+ if (txstate->field_c == 0) {
+ /* move on to the next state */
+ txstate->tx_state = (txstate->tx_state & ~F_MASK) | F_CRC;
+ txstate->field_c = 4;
+ }
+ return TS_IN_PKT;
+ case F_CRC:
+#ifdef DO_TRACE
+ __rt_trace("txe-crc ");
+#endif
+ *tx_ch = escape((txstate->crc >> ((txstate->field_c - 1) * 8)) & 0xff,
+ txstate);
+
+ if (txstate->field_c == 0) {
+#ifdef DO_TRACE
+ __rt_trace("txe crc = 0x%x\n", txstate->crc);
+#endif
+ /* move on to the next state */
+ txstate->tx_state = (txstate->tx_state & ~N_MASK) | N_ETX;
+ }
+ return TS_IN_PKT;
+ }
+ }
+ case N_ETX:
+#ifdef DO_TRACE
+ __rt_trace("txe-etx\n");
+#endif
+ txstate->tx_state = (txstate->tx_state & ~N_MASK) | N_IDLE;
+ *tx_ch = txstate->config->etx;
+ return TS_DONE_PKT;
+ default:
+#ifdef DEBUG
+ __rt_info("tx default\n");
+#endif
+ txstate->tx_state = (txstate->tx_state & ~N_MASK) | N_IDLE;
+ return TS_IDLE;
+ }
+ /* stop a silly -Wall warning */
+ return (te_status)-1;
+}
+
+/*
+ * crc generation occurs in the escape function because it is the only
+ * place where we know that we're putting a real char into the buffer
+ * rather than an escaped one.
+ * We must be careful here not to update the crc when we're sending it
+ */
+static unsigned char escape(unsigned char ch_in, struct te_state *txstate) {
+ if (((txstate->tx_state) & E_MASK) == E_ESC) {
+ /* char has been escaped so send the real char */
+#ifdef DO_TRACE
+ __rt_trace("txe-echar ");
+#endif
+ txstate->tx_state = (txstate->tx_state & ~E_MASK) | E_PLAIN;
+ txstate->field_c--;
+ if ((txstate->tx_state & F_MASK) != F_CRC)
+ txstate->crc = crc32( &ch_in, 1, txstate->crc);
+ return ch_in | serial_ESCAPE;
+ }
+ if ((ch_in < 32) && ((txstate->config->esc_set & (1 << ch_in)) != 0)) {
+ /* char needs escaping */
+#ifdef DO_TRACE
+ __rt_trace("txe-esc ");
+#endif
+ txstate->tx_state = (txstate->tx_state & ~E_MASK) | E_ESC;
+ return txstate->config->esc;
+ }
+ /* must be a char that can be sent plain */
+ txstate->field_c--;
+ if ((txstate->tx_state & F_MASK) != F_CRC)
+ txstate->crc = crc32(&ch_in, 1, txstate->crc);
+ return ch_in;
+}
+
+/* EOF tx.c */
diff --git a/gdb/rdi-share/unixcomm.c b/gdb/rdi-share/unixcomm.c
new file mode 100644
index 00000000000..7c2183de3e5
--- /dev/null
+++ b/gdb/rdi-share/unixcomm.c
@@ -0,0 +1,552 @@
+/*
+ * Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
+ *
+ * This software may be freely used, copied, modified, and distributed
+ * provided that the above copyright notice is preserved in all copies of the
+ * software.
+ */
+
+/* -*-C-*-
+ *
+ * $Revision$
+ * $Date$
+ *
+ */
+
+#ifdef __hpux
+# define _POSIX_SOURCE 1
+#endif
+
+#include <stdio.h>
+#include <unistd.h>
+#include <ctype.h>
+
+#ifdef __hpux
+# define _TERMIOS_INCLUDED
+# include <sys/termio.h>
+# undef _TERMIOS_INCLUDED
+#else
+# include <termios.h>
+#endif
+
+#include <string.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <stdarg.h>
+#include <sys/types.h>
+#include <sys/time.h>
+
+#ifdef sun
+# include <sys/ioccom.h>
+# ifdef __svr4__
+# include <sys/bpp_io.h>
+# else
+# include <sbusdev/bpp_io.h>
+# endif
+#endif
+
+#ifdef BSD
+# ifdef sun
+# include <sys/ttydev.h>
+# endif
+# ifdef __alpha
+# include <sys/ioctl.h>
+# else
+# include <sys/filio.h>
+# endif
+#endif
+
+#ifdef __hpux
+# define _INCLUDE_HPUX_SOURCE
+# include <sys/ioctl.h>
+# undef _INCLUDE_HPUX_SOURCE
+#endif
+
+#include "host.h"
+#include "unixcomm.h"
+
+#define PP_TIMEOUT 1 /* seconds */
+
+#ifdef sun
+#define SERPORT1 "/dev/ttya"
+#define SERPORT2 "/dev/ttyb"
+#define PARPORT1 "/dev/bpp0"
+#define PARPORT2 "/dev/bpp1"
+#endif
+
+#ifdef __hpux
+#define SERPORT1 "/dev/tty00"
+#define SERPORT2 "/dev/tty01"
+#define PARPORT1 "/dev/ptr_parallel"
+#define PARPORT2 "/dev/ptr_parallel"
+#endif
+
+#ifdef __linux__
+#define SERPORT1 "/dev/cua0"
+#define SERPORT2 "/dev/cua1"
+#define PARPORT1 "/dev/par0"
+#define PARPORT2 "/dev/par1"
+#endif
+
+#if defined (__FreeBSD__) || defined (__NetBSD__) || defined (__OpenBSD__) || defined (bsdi)
+#define SERPORT1 "/dev/cuaa0"
+#define SERPORT2 "/dev/cuaa1"
+#define PARPORT1 "/dev/lpt0"
+#define PARPORT2 "/dev/lpt1"
+#endif
+
+
+#define SERIAL_PREFIX "/dev/tty"
+#if defined(_WIN32) || defined (__CYGWIN32__)
+#define SERPORT1 "com1"
+#define SERPORT2 "com2"
+#define PARPORT1 "lpt1"
+#define PARPORT2 "lpt2"
+#undef SERIAL_PREFIX
+#define SERIAL_PREFIX "com"
+#endif
+
+
+
+/*
+ * Parallel port output pins, used for signalling to target
+ */
+
+#ifdef sun
+struct bpp_pins bp;
+#endif
+
+static int serpfd = -1;
+static int parpfd = -1;
+
+extern const char *Unix_MatchValidSerialDevice(const char *name)
+{
+ int i=0;
+ char *sername=NULL;
+
+ /* Accept no name as the default serial port */
+ if (name == NULL) {
+ return SERPORT1;
+ }
+
+ /* Look for the simple cases - 1,2,s,S,/dev/... first, and
+ * afterwards look for S=... clauses, which need parsing properly.
+ */
+
+ /* Accept /dev/tty* where * is limited */
+ if (strlen(name) == strlen(SERPORT1)
+ && strncmp(name, SERIAL_PREFIX, strlen (SERIAL_PREFIX)) == 0)
+ {
+ return name;
+ }
+
+ /* Accept "1" or "2" or "S" - S is equivalent to "1" */
+ if (strcmp(name, "1") == 0 ||
+ strcmp(name, "S") == 0 || strcmp(name, "s") == 0) {
+ return SERPORT1;
+ }
+ if (strcmp(name, "2") == 0) return SERPORT2;
+
+ /* It wasn't one of the simple cases, so now we have to parse it
+ * properly
+ */
+
+ do {
+ switch (name[i]) {
+ case ',':
+ /* Skip over commas */
+ i++;
+ break;
+
+ default:
+ return 0;
+ /* Unexpected character => error - not matched */
+
+ case 0:
+ /* End of string means return whatever we have matched */
+ return sername;
+
+ case 's':
+ case 'S':
+ case 'h':
+ case 'H': {
+ char ch = tolower(name[i]);
+ int j, continue_from, len;
+
+ /* If the next character is a comma or a NULL then this is
+ * a request for the default Serial port
+ */
+ if (name[++i] == 0 || name[i] == ',') {
+ if (ch=='s')
+ sername=SERPORT1;
+ break;
+ }
+
+ /* Next character must be an = */
+ if (name[i] != '=') return 0;
+ /* Search for the end of the port spec. (ends in NULL or ,) */
+ for (j= ++i; name[j] != 0 && name[j] != ','; j++)
+ ; /* Do nothing */
+ /* Notice whether this is the last thing to parse or not
+ * and also calaculate the length of the string
+ */
+ if (name[j] == '0') continue_from = -1;
+ else continue_from = j;
+ len=(j-i);
+
+ /* And now try to match the serial / parallel port */
+ switch (ch) {
+ case 's': {
+ /* Match serial port */
+ if (len==1) {
+ if (name[i]=='1')
+ sername=SERPORT1;
+ else if (name[i]=='2')
+ sername=SERPORT2;
+ } else if (len==strlen(SERPORT1)) {
+ if (strncmp(name+i,SERPORT1,strlen(SERPORT1)) == 0)
+ sername=SERPORT1;
+ else if (strncmp(name+i,SERPORT2,strlen(SERPORT2)) == 0)
+ sername=SERPORT2;
+ }
+
+ break;
+ }
+
+ case 'h':
+ /* We don't actually deal with the H case here, we just
+ * match it and allow it through.
+ */
+ break;
+ }
+
+ if (continue_from == -1) return sername;
+ i = continue_from;
+ break;
+ }
+ }
+ } while (1);
+
+ return 0;
+}
+
+
+extern int Unix_IsSerialInUse(void)
+{
+ if (serpfd >= 0)
+ return -1;
+
+ return 0;
+}
+
+extern int Unix_OpenSerial(const char *name)
+{
+#if defined(BSD) || defined(__CYGWIN32__)
+ serpfd = open(name, O_RDWR);
+#else
+ serpfd = open(name, O_RDWR | O_NONBLOCK);
+#endif
+
+ if (serpfd < 0) {
+ perror("open");
+ return -1;
+ }
+
+ return 0;
+}
+
+extern void Unix_CloseSerial(void)
+{
+ if (serpfd >= 0)
+ {
+ (void)close(serpfd);
+ serpfd = -1;
+ }
+}
+
+extern int Unix_ReadSerial(unsigned char *buf, int n, bool block)
+{
+ fd_set fdset;
+ struct timeval tv;
+ int err;
+
+ FD_ZERO(&fdset);
+ FD_SET(serpfd, &fdset);
+
+ tv.tv_sec = 0;
+ tv.tv_usec = (block ? 10000 : 0);
+
+ err = select(serpfd + 1, &fdset, NULL, NULL, &tv);
+
+ if (err < 0 && errno != EINTR)
+ {
+#ifdef DEBUG
+ perror("select");
+#endif
+ panic("select failure");
+ return -1;
+ }
+ else if (err > 0 && FD_ISSET(serpfd, &fdset))
+ return read(serpfd, buf, n);
+ else /* err == 0 || FD_CLR(serpfd, &fdset) */
+ {
+ errno = ERRNO_FOR_BLOCKED_IO;
+ return -1;
+ }
+}
+
+extern int Unix_WriteSerial(unsigned char *buf, int n)
+{
+ return write(serpfd, buf, n);
+}
+
+extern void Unix_ResetSerial(void)
+{
+ struct termios terminfo;
+
+ tcgetattr(serpfd, &terminfo);
+#ifdef __CYGWIN32__
+ /* Expedient, but it works. */
+ terminfo.c_iflag = 0;
+ terminfo.c_oflag = 0;
+ terminfo.c_cflag = 48;
+ terminfo.c_lflag = 0;
+ terminfo.c_cc[VMIN] = 0;
+ terminfo.c_cc[VTIME] = 1;
+#else
+ terminfo.c_lflag &= ~(ICANON | ISIG | ECHO | IEXTEN);
+ terminfo.c_iflag &= ~(IGNCR | INPCK | ISTRIP | ICRNL | BRKINT);
+ terminfo.c_iflag |= (IXON | IXOFF | IGNBRK);
+ terminfo.c_cflag = (terminfo.c_cflag & ~CSIZE) | CS8 | CREAD;
+ terminfo.c_cflag &= ~PARENB;
+ terminfo.c_cc[VMIN] = 1;
+ terminfo.c_cc[VTIME] = 0;
+ terminfo.c_oflag &= ~OPOST;
+#endif
+ tcsetattr(serpfd, TCSAFLUSH, &terminfo);
+}
+
+extern void Unix_SetSerialBaudRate(int baudrate)
+{
+ struct termios terminfo;
+
+ tcgetattr(serpfd, &terminfo);
+ cfsetospeed(&terminfo, baudrate);
+ cfsetispeed(&terminfo, baudrate);
+ tcsetattr(serpfd, TCSAFLUSH, &terminfo);
+}
+
+extern void Unix_ioctlNonBlocking(void)
+{
+#if defined(BSD)
+ int nonblockingIO = 1;
+ (void)ioctl(serpfd, FIONBIO, &nonblockingIO);
+
+ if (parpfd != -1)
+ (void)ioctl(parpfd, FIONBIO, &nonblockingIO);
+#endif
+}
+
+extern void Unix_IsValidParallelDevice(
+ const char *portstring, char **sername, char **parname)
+{
+ int i=0;
+ *sername=NULL;
+ *parname=NULL;
+
+ /* Do not recognise a NULL portstring */
+ if (portstring==NULL) return;
+
+ do {
+ switch (portstring[i]) {
+ case ',':
+ /* Skip over commas */
+ i++;
+ break;
+
+ default:
+ case 0:
+ /* End of string or bad characcter means we have finished */
+ return;
+
+ case 's':
+ case 'S':
+ case 'p':
+ case 'P':
+ case 'h':
+ case 'H': {
+ char ch = tolower(portstring[i]);
+ int j, continue_from, len;
+
+ /* If the next character is a comma or a NULL then this is
+ * a request for the default Serial or Parallel port
+ */
+ if (portstring[++i] == 0 || portstring[i] == ',') {
+ if (ch=='s') *sername=SERPORT1;
+ else if (ch=='p') *parname=PARPORT1;
+ break;
+ }
+
+ /* Next character must be an = */
+ if (portstring[i] != '=') return;
+ /* Search for the end of the port spec. (ends in NULL or ,) */
+ for (j= ++i; portstring[j] != 0 && portstring[j] != ','; j++)
+ ; /* Do nothing */
+ /* Notice whether this is the last thing to parse or not
+ * and also calaculate the length of the string
+ */
+ if (portstring[j] == '0') continue_from = -1;
+ else continue_from = j;
+ len=(j-i);
+
+ /* And now try to match the serial / parallel port */
+ switch (ch) {
+ case 's': {
+ /* Match serial port */
+ if (len==1) {
+ if (portstring[i]=='1') *sername=SERPORT1;
+ else if (portstring[i]=='2') *sername=SERPORT2;
+ } else if (len==strlen(SERPORT1)) {
+ if (strncmp(portstring+i,SERPORT1,strlen(SERPORT1)) == 0)
+ *sername=SERPORT1;
+ else if (strncmp(portstring+i,SERPORT2,strlen(SERPORT2)) == 0)
+ *sername=SERPORT2;
+ }
+ break;
+ }
+
+ case 'p': {
+ /* Match parallel port */
+ if (len==1) {
+ if (portstring[i]=='1') *parname=PARPORT1;
+ else if (portstring[i]=='2') *parname=PARPORT2;
+ } else if (len==strlen(PARPORT1)) {
+ if (strncmp(portstring+i,PARPORT1,strlen(PARPORT1)) == 0)
+ *parname=PARPORT1;
+ else if (strncmp(portstring+i,PARPORT2,strlen(PARPORT2)) == 0)
+ *parname=PARPORT2;
+ }
+ break;
+ }
+
+ case 'h':
+ /* We don't actually deal with the H case here, we just
+ * match it and allow it through.
+ */
+ break;
+ }
+
+ if (continue_from == -1) return;
+ i = continue_from;
+ break;
+ }
+ }
+ } while (1);
+ return; /* Will never get here */
+}
+
+extern int Unix_IsParallelInUse(void)
+{
+ if (parpfd >= 0)
+ return -1;
+
+ return 0;
+}
+
+extern int Unix_OpenParallel(const char *name)
+{
+#if defined(BSD)
+ parpfd = open(name, O_RDWR);
+#else
+ parpfd = open(name, O_RDWR | O_NONBLOCK);
+#endif
+
+ if (parpfd < 0)
+ {
+ char errbuf[256];
+
+ sprintf(errbuf, "open %s", name);
+ perror(errbuf);
+
+ return -1;
+ }
+
+ return 0;
+}
+
+extern void Unix_CloseParallel(void)
+{
+ if (parpfd >= 0)
+ {
+ (void)close(parpfd);
+ parpfd = -1;
+ }
+}
+
+
+extern unsigned int Unix_WriteParallel(unsigned char *buf, int n)
+{
+ int ngone;
+
+ if ((ngone = write(parpfd, buf, n)) < 0)
+ {
+ /*
+ * we ignore errors (except for debug purposes)
+ */
+#ifdef DEBUG
+ char errbuf[256];
+
+ sprintf(errbuf, "send_packet: write");
+ perror(errbuf);
+#endif
+ ngone = 0;
+ }
+
+ /* finished */
+ return (unsigned int)ngone;
+}
+
+
+#ifdef sun
+extern void Unix_ResetParallel(void)
+{
+ struct bpp_transfer_parms tp;
+
+#ifdef DEBUG
+ printf("serpar_reset\n");
+#endif
+
+ /*
+ * we need to set the parallel port up for BUSY handshaking,
+ * and select the timeout
+ */
+ if (ioctl(parpfd, BPPIOC_GETPARMS, &tp) < 0)
+ {
+#ifdef DEBUG
+ perror("ioctl(BPPIOCGETPARMS)");
+#endif
+ panic("serpar_reset: cannot get BPP parameters");
+ }
+
+ tp.write_handshake = BPP_BUSY_HS;
+ tp.write_timeout = PP_TIMEOUT;
+
+ if (ioctl(parpfd, BPPIOC_SETPARMS, &tp) < 0)
+ {
+#ifdef DEBUG
+ perror("ioctl(BPPIOC_SETPARMS)");
+#endif
+ panic("serpar_reset: cannot set BPP parameters");
+ }
+}
+
+#else
+
+/* Parallel not supported on HP */
+
+extern void Unix_ResetParallel(void)
+{
+}
+
+#endif
+
diff --git a/gdb/rdi-share/unixcomm.h b/gdb/rdi-share/unixcomm.h
new file mode 100644
index 00000000000..baa65520392
--- /dev/null
+++ b/gdb/rdi-share/unixcomm.h
@@ -0,0 +1,212 @@
+/*
+ * Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
+ *
+ * This software may be freely used, copied, modified, and distributed
+ * provided that the above copyright notice is preserved in all copies of the
+ * software.
+ */
+
+/* -*-C-*-
+ *
+ * $Revision$
+ * $Date$
+ *
+ */
+#ifndef angsd_unixcomm_h
+#define angsd_unixcomm_h
+
+#include <errno.h>
+
+#if defined(BSD)
+# define ERRNO_FOR_BLOCKED_IO EWOULDBLOCK
+#else
+# define ERRNO_FOR_BLOCKED_IO EAGAIN
+#endif
+
+/*
+ * Function: Unix_MatchValidSerialDevice
+ * Purpose: check that the serial driver/port name is valid
+ * and return the actual device name if it is.
+ *
+ * Params:
+ * Input: name Name of device going to be used
+ *
+ * Returns:
+ * OK: Pointer to name of the device matched
+ * Error or unrecognised deivce: 0
+ */
+extern const char *Unix_MatchValidSerialDevice(const char *name);
+
+/*
+ * Function: Unix_IsSerialInUse
+ * Purpose: check whether the serial port is in use
+ *
+ * Params:
+ * Input: Nothing
+ *
+ * Returns:
+ * OK: 0 Serial device not in use
+ * Error: -1 Serial device in use
+ */
+extern int Unix_IsSerialInUse(void);
+
+/*
+ * Function: Unix_OpenSerial
+ * Purpose: open the serial port
+ *
+ * Params:
+ * Input: name Name of device to open
+ *
+ * Returns: Unix 'open' returns
+ */
+extern int Unix_OpenSerial(const char *name);
+
+/*
+ * Function: Unix_CloseSerial
+ * Purpose: close the serial port
+ *
+ * Params:
+ * Input: Nothing
+ *
+ * Returns: Nothing
+ */
+extern void Unix_CloseSerial(void);
+
+/*
+ * Function: Unix_ReadSerial
+ * Purpose: reads a specified number of bytes (or less) from the serial port
+ *
+ * Params:
+ * Input: buf Buffer to store read bytes
+ * n Maximum number of bytes to read
+ *
+ * Returns: Unix 'read' returns
+ */
+extern int Unix_ReadSerial(unsigned char *buf, int n, bool block);
+
+/*
+ * Function: Unix_WriteSerial
+ * Purpose: writes a specified number of bytes (or less) to the serial port
+ *
+ * Params:
+ * Input: buf Buffer to write bytes from
+ * n Maximum number of bytes to write
+ *
+ * Returns: Unix 'write' returns
+ */
+extern int Unix_WriteSerial(unsigned char *buf, int n);
+
+/*
+ * Function: Unix_ResetSerial
+ * Purpose: resets the serial port for another operation
+ *
+ * Params:
+ * Input: Nothing
+ *
+ * Returns: Nothing
+ */
+extern void Unix_ResetSerial(void);
+
+/*
+ * Function: Unix_SetSerialBaudRate
+ * Purpose: check that the serial driver/port name is valid
+ *
+ * Params:
+ * Input: baudrate termios value for baud rate
+ *
+ * Returns: Nothing
+ */
+extern void Unix_SetSerialBaudRate(int baudrate);
+
+/*
+ * Function: Unix_ioctlNonBlocking
+ * Purpose: sets the serial port to non-blocking IO
+ *
+ * Params:
+ * Input: Nothing
+ *
+ * Returns: Nothing
+ */
+extern void Unix_ioctlNonBlocking(void);
+
+/*
+ * Function: Unix_IsValidParallelDevice
+ * Purpose: check whether the combined serial and parallel device specification
+ * is ok, and return the ports selected
+ *
+ * Params:
+ * Input: portstring - is a string which specifies which serial
+ * and parallel ports are to be used. Can
+ * include s=<val> and p=<val> separated by a
+ * comma.
+ *
+ * Returns:
+ * Output: *sername - returns the device name of the chosen serial port
+ * *parname - returns the device name of the chosen parallel port
+ * If either of these is NULL on return then the match failed.
+ */
+extern void Unix_IsValidParallelDevice(
+ const char *portstring, char **sername, char **parname
+);
+
+/*
+ * Function: Unix_IsParallelInUse
+ * Purpose: check whether the parallel port is in use
+ *
+ * Params:
+ * Input: Nothing
+ *
+ * Returns:
+ * OK: 0 Parallel device not in use
+ * Error: -1 Parallel device in use
+ */
+extern int Unix_IsParallelInUse(void);
+
+/*
+ * Function: Unix_OpenParallel
+ * Purpose: open the parallel port
+ *
+ * Params:
+ * Input: name Name of device to open
+ *
+ * Returns: Unix 'open' returns
+ */
+extern int Unix_OpenParallel(const char *name);
+
+/*
+ * Function: Unix_CloseParallel
+ * Purpose: close the parallel port
+ *
+ * Params:
+ * Input: Nothing
+ *
+ * Returns: Nothing
+ */
+extern void Unix_CloseParallel(void);
+
+/*
+ * Function: Unix_WriteParallel
+ * Purpose: writes a specified number of bytes (or less) to the parallel port
+ *
+ * Params:
+ * Input: buf Buffer to write bytes from
+ * n Maximum number of bytes to write
+ *
+ * Returns: Unix 'write' returns
+ */
+extern unsigned int Unix_WriteParallel(unsigned char *buf, int n);
+
+/*
+ * Function: Unix_ResetParallel
+ * Purpose: resets the parallel port for another operation
+ *
+ * Params:
+ * Input: Nothing
+ *
+ * Returns: Nothing
+ */
+extern void Unix_ResetParallel(void);
+
+#endif /* ndef angsd_unixcomm_h */
+
+/* EOF unixcomm.h */
diff --git a/gdb/remote-adapt.c b/gdb/remote-adapt.c
new file mode 100644
index 00000000000..b22f180885c
--- /dev/null
+++ b/gdb/remote-adapt.c
@@ -0,0 +1,1443 @@
+/* Remote debugging interface for AMD 290*0 Adapt Monitor Version 2.1d18.
+ Copyright 1990, 1991, 1992 Free Software Foundation, Inc.
+ Contributed by David Wood at New York University (wood@lab.ultra.nyu.edu).
+ Adapted from work done at Cygnus Support in remote-eb.c.
+
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* This is like remote.c but is for an esoteric situation--
+ having a 29k board attached to an Adapt inline monitor.
+ The monitor is connected via serial line to a unix machine
+ running gdb.
+
+ 3/91 - developed on Sun3 OS 4.1, by David Wood
+ o - I can't get binary coff to load.
+ o - I can't get 19200 baud rate to work.
+ 7/91 o - Freeze mode tracing can be done on a 29050. */
+
+
+
+#include "defs.h"
+#include "gdb_string.h"
+#include "inferior.h"
+#include "wait.h"
+#include "value.h"
+#include <ctype.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <errno.h>
+#include "terminal.h"
+#include "target.h"
+#include "gdbcore.h"
+
+/* This processor is getting rusty but I am trying to keep it
+ up to date at least with data structure changes.
+ Activate this block to compile just this file.
+ */
+#define COMPILE_CHECK 0
+#if COMPILE_CHECK
+#define Q_REGNUM 0
+#define VAB_REGNUM 0
+#define CPS_REGNUM 0
+#define IPA_REGNUM 0
+#define IPB_REGNUM 0
+#define GR1_REGNUM 0
+#define LR0_REGNUM 0
+#define IPC_REGNUM 0
+#define CR_REGNUM 0
+#define BP_REGNUM 0
+#define FC_REGNUM 0
+#define INTE_REGNUM 0
+#define EXO_REGNUM 0
+#define GR96_REGNUM 0
+#define NPC_REGNUM
+#define FPE_REGNUM 0
+#define PC2_REGNUM 0
+#define FPS_REGNUM 0
+#define ALU_REGNUM 0
+#define LRU_REGNUM 0
+#define TERMINAL int
+#define RAW 1
+#define ANYP 1
+extern int a29k_freeze_mode ;
+extern int processor_type ;
+extern char * processor_name ;
+#endif
+
+/* External data declarations */
+extern int stop_soon_quietly; /* for wait_for_inferior */
+
+/* Forward data declarations */
+extern struct target_ops adapt_ops; /* Forward declaration */
+
+/* Forward function declarations */
+static void adapt_fetch_registers ();
+static void adapt_store_registers ();
+static void adapt_close ();
+static int adapt_clear_breakpoints();
+
+#define FREEZE_MODE (read_register(CPS_REGNUM) && 0x400)
+#define USE_SHADOW_PC ((processor_type == a29k_freeze_mode) && FREEZE_MODE)
+
+/* Can't seem to get binary coff working */
+#define ASCII_COFF /* Adapt will be downloaded with ascii coff */
+
+/* FIXME: Replace with `set remotedebug'. */
+#define LOG_FILE "adapt.log"
+#if defined (LOG_FILE)
+FILE *log_file=NULL;
+#endif
+
+static int timeout = 5;
+static char *dev_name;
+
+/* Descriptor for I/O to remote machine. Initialize it to -1 so that
+ adapt_open knows that we don't have a file open when the program
+ starts. */
+int adapt_desc = -1;
+
+/* stream which is fdopen'd from adapt_desc. Only valid when
+ adapt_desc != -1. */
+FILE *adapt_stream;
+
+#define ON 1
+#define OFF 0
+static void
+rawmode(desc, turnon)
+int desc;
+int turnon;
+{
+
+ TERMINAL sg;
+
+ if (desc < 0)
+ return;
+
+ ioctl (desc, TIOCGETP, &sg);
+
+ if (turnon) {
+#ifdef HAVE_TERMIO
+ sg.c_lflag &= ~(ICANON);
+#else
+ sg.sg_flags |= RAW;
+#endif
+ } else {
+#ifdef HAVE_TERMIO
+ sg.c_lflag |= ICANON;
+#else
+ sg.sg_flags &= ~(RAW);
+#endif
+ }
+ ioctl (desc, TIOCSETP, &sg);
+}
+
+/* Suck up all the input from the adapt */
+slurp_input()
+{
+ char buf[8];
+
+#ifdef HAVE_TERMIO
+ /* termio does the timeout for us. */
+ while (read (adapt_desc, buf, 8) > 0);
+#else
+ alarm (timeout);
+ while (read (adapt_desc, buf, 8) > 0);
+ alarm (0);
+#endif
+}
+
+/* Read a character from the remote system, doing all the fancy
+ timeout stuff. */
+static int
+readchar ()
+{
+ char buf;
+
+ buf = '\0';
+#ifdef HAVE_TERMIO
+ /* termio does the timeout for us. */
+ read (adapt_desc, &buf, 1);
+#else
+ alarm (timeout);
+ if (read (adapt_desc, &buf, 1) < 0)
+ {
+ if (errno == EINTR)
+ error ("Timeout reading from remote system.");
+ else
+ perror_with_name ("remote");
+ }
+ alarm (0);
+#endif
+
+ if (buf == '\0')
+ error ("Timeout reading from remote system.");
+#if defined (LOG_FILE)
+ putc (buf & 0x7f, log_file);
+#endif
+ return buf & 0x7f;
+}
+
+/* Keep discarding input from the remote system, until STRING is found.
+ Let the user break out immediately. */
+static void
+expect (string)
+ char *string;
+{
+ char *p = string;
+
+ fflush(adapt_stream);
+ immediate_quit = 1;
+ while (1)
+ {
+ if (readchar() == *p)
+ {
+ p++;
+ if (*p == '\0')
+ {
+ immediate_quit = 0;
+ return;
+ }
+ }
+ else
+ p = string;
+ }
+}
+
+/* Keep discarding input until we see the adapt prompt.
+
+ The convention for dealing with the prompt is that you
+ o give your command
+ o *then* wait for the prompt.
+
+ Thus the last thing that a procedure does with the serial line
+ will be an expect_prompt(). Exception: adapt_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 adapt_wait which does wait for the prompt.
+ Note that this includes abnormal exit, e.g. error(). This is
+ necessary to prevent getting into states from which we can't
+ recover. */
+static void
+expect_prompt ()
+{
+#if defined (LOG_FILE)
+ /* This is a convenient place to do this. The idea is to do it often
+ enough that we never lose much data if we terminate abnormally. */
+ fflush (log_file);
+#endif
+ fflush(adapt_stream);
+ expect ("\n# ");
+}
+
+/* Get a hex digit from the remote system & return its value.
+ If ignore_space is nonzero, ignore spaces (not newline, tab, etc). */
+static int
+get_hex_digit (ignore_space)
+ int ignore_space;
+{
+ int ch;
+ while (1)
+ {
+ ch = readchar ();
+ if (ch >= '0' && ch <= '9')
+ return ch - '0';
+ else if (ch >= 'A' && ch <= 'F')
+ return ch - 'A' + 10;
+ else if (ch >= 'a' && ch <= 'f')
+ return ch - 'a' + 10;
+ else if (ch == ' ' && ignore_space)
+ ;
+ else
+ {
+ expect_prompt ();
+ error ("Invalid hex digit from remote system.");
+ }
+ }
+}
+
+/* Get a byte from adapt_desc and put it in *BYT. Accept any number
+ leading spaces. */
+static void
+get_hex_byte (byt)
+ char *byt;
+{
+ int val;
+
+ val = get_hex_digit (1) << 4;
+ val |= get_hex_digit (0);
+ *byt = val;
+}
+
+/* Read a 32-bit hex word from the adapt, preceded by a space */
+static long
+get_hex_word()
+{
+ long val;
+ int j;
+
+ val = 0;
+ for (j = 0; j < 8; j++)
+ val = (val << 4) + get_hex_digit (j == 0);
+ return val;
+}
+/* Get N 32-bit hex words from remote, each preceded by a space
+ and put them in registers starting at REGNO. */
+static void
+get_hex_regs (n, regno)
+ int n;
+ int regno;
+{
+ long val;
+ while (n--) {
+ val = get_hex_word();
+ supply_register(regno++,(char *) &val);
+ }
+}
+/* Called when SIGALRM signal sent due to alarm() timeout. */
+#ifndef HAVE_TERMIO
+
+#ifndef __STDC__
+# ifndef volatile
+# define volatile /**/
+# endif
+#endif
+volatile int n_alarms;
+
+void
+adapt_timer ()
+{
+#if 0
+ if (kiodebug)
+ printf ("adapt_timer called\n");
+#endif
+ n_alarms++;
+}
+#endif
+
+/* malloc'd name of the program on the remote system. */
+static char *prog_name = NULL;
+
+/* Number of SIGTRAPs we need to simulate. That is, the next
+ NEED_ARTIFICIAL_TRAP calls to adapt_wait should just return
+ SIGTRAP without actually waiting for anything. */
+
+static int need_artificial_trap = 0;
+
+void
+adapt_kill(arg,from_tty)
+char *arg;
+int from_tty;
+{
+ fprintf (adapt_stream, "K");
+ fprintf (adapt_stream, "\r");
+ expect_prompt ();
+}
+/*
+ * Download a file specified in 'args', to the adapt.
+ * FIXME: Assumes the file to download is a binary coff file.
+ */
+static void
+adapt_load(args,fromtty)
+char *args;
+int fromtty;
+{
+ FILE *fp;
+ int n;
+ char buffer[1024];
+
+ if (!adapt_stream) {
+ printf_filtered("Adapt not open. Use 'target' command to open adapt\n");
+ return;
+ }
+
+ /* OK, now read in the file. Y=read, C=COFF, T=dTe port
+ 0=start address. */
+
+#ifdef ASCII_COFF /* Ascii coff */
+ fprintf (adapt_stream, "YA T,0\r");
+ fflush(adapt_stream); /* Just in case */
+ /* FIXME: should check args for only 1 argument */
+ sprintf(buffer,"cat %s | btoa > /tmp/#adapt-btoa",args);
+ system(buffer);
+ fp = fopen("/tmp/#adapt-btoa","r");
+ rawmode(adapt_desc,OFF);
+ while (n=fread(buffer,1,1024,fp)) {
+ do { n -= write(adapt_desc,buffer,n); } while (n>0);
+ if (n<0) { perror("writing ascii coff"); break; }
+ }
+ fclose(fp);
+ rawmode(adapt_desc,ON);
+ system("rm /tmp/#adapt-btoa");
+#else /* Binary coff - can't get it to work .*/
+ fprintf (adapt_stream, "YC T,0\r");
+ fflush(adapt_stream); /* Just in case */
+ if (!(fp = fopen(args,"r"))) {
+ printf_filtered("Can't open %s\n",args);
+ return;
+ }
+ while (n=fread(buffer,1,512,fp)) {
+ do { n -= write(adapt_desc,buffer,n); } while (n>0);
+ if (n<0) { perror("writing ascii coff"); break; }
+ }
+ fclose(fp);
+#endif
+ expect_prompt (); /* Skip garbage that comes out */
+ fprintf (adapt_stream, "\r");
+ expect_prompt ();
+}
+
+/* This is called not only when we first attach, but also when the
+ user types "run" after having attached. */
+void
+adapt_create_inferior (execfile, args, env)
+ char *execfile;
+ char *args;
+ char **env;
+{
+ int entry_pt;
+
+ if (args && *args)
+ error ("Can't pass arguments to remote adapt process.");
+
+ if (execfile == 0 || exec_bfd == 0)
+ error ("No executable file specified");
+
+ entry_pt = (int) bfd_get_start_address (exec_bfd);
+
+ if (adapt_stream) {
+ adapt_kill(NULL,NULL);
+ adapt_clear_breakpoints();
+ init_wait_for_inferior ();
+ /* Clear the input because what the adapt sends back is different
+ * depending on whether it was running or not.
+ */
+ slurp_input(); /* After this there should be a prompt */
+ fprintf(adapt_stream,"\r");
+ expect_prompt();
+ printf_filtered("Do you want to download '%s' (y/n)? [y] : ",prog_name);
+ {
+ char buffer[10];
+ gets(buffer);
+ if (*buffer != 'n') {
+ adapt_load(prog_name,0);
+ }
+ }
+
+#ifdef NOTDEF
+ /* Set the PC and wait for a go/cont */
+ fprintf (adapt_stream, "G %x,N\r",entry_pt);
+ printf_filtered("Now use the 'continue' command to start.\n");
+ expect_prompt ();
+#else
+ insert_breakpoints (); /* Needed to get correct instruction in cache */
+ proceed(entry_pt, TARGET_SIGNAL_DEFAULT, 0);
+#endif
+
+ } else {
+ printf_filtered("Adapt not open yet.\n");
+ }
+}
+
+/* Translate baud rates from integers to damn B_codes. Unix should
+ have outgrown this crap years ago, but even POSIX wouldn't buck it. */
+
+#ifndef B19200
+#define B19200 EXTA
+#endif
+#ifndef B38400
+#define B38400 EXTB
+#endif
+
+static struct {int rate, damn_b;} baudtab[] = {
+ {0, B0},
+ {50, B50},
+ {75, B75},
+ {110, B110},
+ {134, B134},
+ {150, B150},
+ {200, B200},
+ {300, B300},
+ {600, B600},
+ {1200, B1200},
+ {1800, B1800},
+ {2400, B2400},
+ {4800, B4800},
+ {9600, B9600},
+ {19200, B19200},
+ {38400, B38400},
+ {-1, -1},
+};
+
+static int damn_b (rate)
+ int rate;
+{
+ int i;
+
+ for (i = 0; baudtab[i].rate != -1; i++)
+ if (rate == baudtab[i].rate) return baudtab[i].damn_b;
+ return B38400; /* Random */
+}
+
+
+/* Open a connection to a remote debugger.
+ NAME is the filename used for communication, then a space,
+ then the baud rate.
+ */
+
+static int baudrate = 9600;
+static void
+adapt_open (name, from_tty)
+ char *name;
+ int from_tty;
+{
+ TERMINAL sg;
+ unsigned int prl;
+ char *p;
+
+ /* Find the first whitespace character, it separates dev_name from
+ prog_name. */
+ if (name == 0)
+ goto erroid;
+
+ for (p = name;
+ *p != '\0' && !isspace (*p); p++)
+ ;
+ if (*p == '\0')
+erroid:
+ error ("\
+Please include the name of the device for the serial port,\n\
+the baud rate, and the name of the program to run on the remote system.");
+ dev_name = (char*)xmalloc(p - name + 1);
+ strncpy (dev_name, name, p - name);
+ dev_name[p - name] = '\0';
+
+ /* Skip over the whitespace after dev_name */
+ for (; isspace (*p); p++)
+ /*EMPTY*/;
+
+ if (1 != sscanf (p, "%d ", &baudrate))
+ goto erroid;
+
+ /* Skip the number and then the spaces */
+ for (; isdigit (*p); p++)
+ /*EMPTY*/;
+ for (; isspace (*p); p++)
+ /*EMPTY*/;
+
+ if (prog_name != NULL)
+ free (prog_name);
+ prog_name = savestring (p, strlen (p));
+
+ adapt_close (0);
+
+ adapt_desc = open (dev_name, O_RDWR);
+ if (adapt_desc < 0)
+ perror_with_name (dev_name);
+ ioctl (adapt_desc, TIOCGETP, &sg);
+#if ! defined(COMPILE_CHECK)
+#ifdef HAVE_TERMIO
+ sg.c_cc[VMIN] = 0; /* read with timeout. */
+ sg.c_cc[VTIME] = timeout * 10;
+ sg.c_lflag &= ~(ICANON | ECHO);
+ sg.c_cflag = (sg.c_cflag & ~CBAUD) | damn_b (baudrate);
+#else
+ sg.sg_ispeed = damn_b (baudrate);
+ sg.sg_ospeed = damn_b (baudrate);
+ sg.sg_flags |= RAW | ANYP;
+ sg.sg_flags &= ~ECHO;
+#endif
+
+ ioctl (adapt_desc, TIOCSETP, &sg);
+ adapt_stream = fdopen (adapt_desc, "r+");
+#endif /* compile_check */
+ push_target (&adapt_ops);
+
+#ifndef HAVE_TERMIO
+#ifndef NO_SIGINTERRUPT
+ /* Cause SIGALRM's to make reads fail with EINTR instead of resuming
+ the read. */
+ if (siginterrupt (SIGALRM, 1) != 0)
+ perror ("adapt_open: error in siginterrupt");
+#endif
+
+ /* Set up read timeout timer. */
+ if ((void (*)) signal (SIGALRM, adapt_timer) == (void (*)) -1)
+ perror ("adapt_open: error in signal");
+#endif
+
+#if defined (LOG_FILE)
+ log_file = fopen (LOG_FILE, "w");
+ if (log_file == NULL)
+ perror_with_name (LOG_FILE);
+#endif
+
+ /* Put this port into NORMAL mode, send the 'normal' character */
+ write(adapt_desc, "", 1); /* Control A */
+ write(adapt_desc, "\r", 1);
+ expect_prompt ();
+
+ /* Hello? Are you there? */
+ write (adapt_desc, "\r", 1);
+
+ expect_prompt ();
+
+ /* Clear any break points */
+ adapt_clear_breakpoints();
+
+ /* Print out some stuff, letting the user now what's going on */
+ printf_filtered("Connected to an Adapt via %s.\n", dev_name);
+ /* FIXME: can this restriction be removed? */
+ printf_filtered("Remote debugging using virtual addresses works only\n");
+ printf_filtered("\twhen virtual addresses map 1:1 to physical addresses.\n");
+ if (processor_type != a29k_freeze_mode) {
+ fprintf_filtered(gdb_stderr,
+ "Freeze-mode debugging not available, and can only be done on an A29050.\n");
+ }
+}
+
+/* Close out all files and local state before this target loses control. */
+
+static void
+adapt_close (quitting)
+ int quitting;
+{
+
+ /* Clear any break points */
+ adapt_clear_breakpoints();
+
+ /* Put this port back into REMOTE mode */
+ if (adapt_stream) {
+ fflush(adapt_stream);
+ sleep(1); /* Let any output make it all the way back */
+ write(adapt_desc, "R\r", 2);
+ }
+
+ /* Due to a bug in Unix, fclose closes not only the stdio stream,
+ but also the file descriptor. So we don't actually close
+ adapt_desc. */
+ if (adapt_stream)
+ fclose (adapt_stream); /* This also closes adapt_desc */
+ if (adapt_desc >= 0)
+ /* close (adapt_desc); */
+
+ /* Do not try to close adapt_desc again, later in the program. */
+ adapt_stream = NULL;
+ adapt_desc = -1;
+
+#if defined (LOG_FILE)
+ if (log_file) {
+ if (ferror (log_file))
+ printf_filtered ("Error writing log file.\n");
+ if (fclose (log_file) != 0)
+ printf_filtered ("Error closing log file.\n");
+ log_file = NULL;
+ }
+#endif
+}
+
+/* Attach to the target that is already loaded and possibly running */
+static void
+adapt_attach (args, from_tty)
+ char *args;
+ int from_tty;
+{
+
+ if (from_tty)
+ printf_filtered ("Attaching to remote program %s.\n", prog_name);
+
+ /* Send the adapt a kill. It is ok if it is not already running */
+ fprintf(adapt_stream, "K\r"); fflush(adapt_stream);
+ expect_prompt(); /* Slurp the echo */
+}
+
+
+/* Terminate the open connection to the remote debugger.
+ Use this when you want to detach and do something else
+ with your gdb. */
+void
+adapt_detach (args,from_tty)
+ char *args;
+ int from_tty;
+{
+
+ if (adapt_stream) { /* Send it on its way (tell it to continue) */
+ adapt_clear_breakpoints();
+ fprintf(adapt_stream,"G\r");
+ }
+
+ pop_target(); /* calls adapt_close to do the real work */
+ if (from_tty)
+ printf_filtered ("Ending remote %s debugging\n", target_shortname);
+}
+
+/* Tell the remote machine to resume. */
+
+void
+adapt_resume (pid, step, sig)
+ int pid, step;
+ enum target_signal sig;
+{
+ if (step)
+ {
+ write (adapt_desc, "t 1,s\r", 6);
+ /* Wait for the echo. */
+ expect ("t 1,s\r\n");
+ /* Then comes a line containing the instruction we stepped to. */
+ expect ("@");
+ /* Then we get the prompt. */
+ expect_prompt ();
+
+ /* Force the next adapt_wait to return a trap. Not doing anything
+ about I/O from the target means that the user has to type
+ "continue" to see any. FIXME, this should be fixed. */
+ need_artificial_trap = 1;
+ }
+ else
+ {
+ write (adapt_desc, "G\r", 2);
+ /* Swallow the echo. */
+ expect_prompt();
+ }
+}
+
+/* Wait until the remote machine stops, then return,
+ storing status in STATUS just as `wait' would. */
+
+int
+adapt_wait (status)
+ struct target_waitstatus *status;
+{
+ /* Strings to look for. '?' means match any single character.
+ Note that with the algorithm we use, the initial character
+ of the string cannot recur in the string, or we will not
+ find some cases of the string in the input. */
+
+ static char bpt[] = "@";
+ /* It would be tempting to look for "\n[__exit + 0x8]\n"
+ but that requires loading symbols with "yc i" and even if
+ we did do that we don't know that the file has symbols. */
+ static char exitmsg[] = "@????????I JMPTI GR121,LR0";
+ char *bp = bpt;
+ char *ep = exitmsg;
+
+ /* Large enough for either sizeof (bpt) or sizeof (exitmsg) chars. */
+ char swallowed[50];
+ /* Current position in swallowed. */
+ char *swallowed_p = swallowed;
+
+ int ch;
+ int ch_handled;
+ int old_timeout = timeout;
+ int old_immediate_quit = immediate_quit;
+
+ status->kind = TARGET_WAITKIND_EXITED;
+ status->value.integer = 0;
+
+ if (need_artificial_trap != 0)
+ {
+ status->kind = TARGET_WAITKIND_STOPPED;
+ status->value.sig = TARGET_SIGNAL_TRAP;
+ need_artificial_trap--;
+ return 0;
+ }
+
+ timeout = 0; /* Don't time out -- user program is running. */
+ immediate_quit = 1; /* Helps ability to QUIT */
+ while (1) {
+ QUIT; /* Let user quit and leave process running */
+ ch_handled = 0;
+ ch = readchar ();
+ if (ch == *bp) {
+ bp++;
+ if (*bp == '\0')
+ break;
+ ch_handled = 1;
+
+ *swallowed_p++ = ch;
+ } else
+ bp = bpt;
+ if (ch == *ep || *ep == '?') {
+ ep++;
+ if (*ep == '\0')
+ break;
+
+ if (!ch_handled)
+ *swallowed_p++ = ch;
+ ch_handled = 1;
+ } else
+ ep = exitmsg;
+ if (!ch_handled) {
+ char *p;
+ /* Print out any characters which have been swallowed. */
+ for (p = swallowed; p < swallowed_p; ++p)
+ putc (*p, stdout);
+ swallowed_p = swallowed;
+ putc (ch, stdout);
+ }
+ }
+ expect_prompt ();
+ if (*bp== '\0')
+ {
+ status->kind = TARGET_WAITKIND_STOPPED;
+ status->value.sig = TARGET_SIGNAL_TRAP;
+ }
+ else
+ {
+ status->kind = TARGET_WAITKIND_EXITED;
+ status->value.integer = 0;
+ }
+ timeout = old_timeout;
+ immediate_quit = old_immediate_quit;
+ return 0;
+}
+
+/* Return the name of register number REGNO
+ in the form input and output by adapt.
+
+ Returns a pointer to a static buffer containing the answer. */
+static char *
+get_reg_name (regno)
+ int regno;
+{
+ static char buf[80];
+ if (regno >= GR96_REGNUM && regno < GR96_REGNUM + 32 )
+ sprintf (buf, "GR%03d", regno - GR96_REGNUM + 96);
+#if defined(GR64_REGNUM)
+ else if (regno >= GR64_REGNUM && regno < GR64_REGNUM + 32 )
+ sprintf (buf, "GR%03d", regno - GR64_REGNUM + 64);
+#endif
+ else if (regno >= LR0_REGNUM && regno < LR0_REGNUM + 128)
+ sprintf (buf, "LR%03d", regno - LR0_REGNUM);
+ else if (regno == Q_REGNUM)
+ strcpy (buf, "SR131");
+ else if (regno >= BP_REGNUM && regno <= CR_REGNUM)
+ sprintf (buf, "SR%03d", regno - BP_REGNUM + 133);
+ else if (regno == ALU_REGNUM)
+ strcpy (buf, "SR132");
+ else if (regno >= IPC_REGNUM && regno <= IPB_REGNUM)
+ sprintf (buf, "SR%03d", regno - IPC_REGNUM + 128);
+ else if (regno >= VAB_REGNUM && regno <= LRU_REGNUM) {
+ /* When a 29050 is in freeze-mode, read shadow pcs instead */
+ if ((regno >= NPC_REGNUM && regno <= PC2_REGNUM) && USE_SHADOW_PC)
+ sprintf (buf, "SR%03d", regno - NPC_REGNUM + 20);
+ else
+ sprintf (buf, "SR%03d", regno - VAB_REGNUM);
+ }
+ else if (regno == GR1_REGNUM)
+ strcpy (buf, "GR001");
+ return buf;
+}
+
+/* Read the remote registers. */
+
+static void
+adapt_fetch_registers ()
+{
+ int reg_index;
+ int regnum_index;
+ char tempbuf[10];
+ int sreg_buf[16];
+ int i,j;
+
+/*
+ * Global registers
+ */
+#if defined(GR64_REGNUM)
+ write (adapt_desc, "dw gr64,gr95\r", 13);
+ for (reg_index = 64, regnum_index = GR64_REGNUM;
+ reg_index < 96;
+ reg_index += 4, regnum_index += 4)
+ {
+ sprintf (tempbuf, "GR%03d ", reg_index);
+ expect (tempbuf);
+ get_hex_regs (4, regnum_index);
+ expect ("\n");
+ }
+#endif
+ write (adapt_desc, "dw gr96,gr127\r", 14);
+ for (reg_index = 96, regnum_index = GR96_REGNUM;
+ reg_index < 128;
+ reg_index += 4, regnum_index += 4)
+ {
+ sprintf (tempbuf, "GR%03d ", reg_index);
+ expect (tempbuf);
+ get_hex_regs (4, regnum_index);
+ expect ("\n");
+ }
+
+/*
+ * Local registers
+ */
+ for (i = 0; i < 128; i += 32)
+ {
+ /* The PC has a tendency to hang if we get these
+ all in one fell swoop ("dw lr0,lr127"). */
+ sprintf (tempbuf, "dw lr%d\r", i);
+ write (adapt_desc, tempbuf, strlen (tempbuf));
+ for (reg_index = i, regnum_index = LR0_REGNUM + i;
+ reg_index < i + 32;
+ reg_index += 4, regnum_index += 4)
+ {
+ sprintf (tempbuf, "LR%03d ", reg_index);
+ expect (tempbuf);
+ get_hex_regs (4, regnum_index);
+ expect ("\n");
+ }
+ }
+
+/*
+ * Special registers
+ */
+ sprintf (tempbuf, "dw sr0\r");
+ write (adapt_desc, tempbuf, strlen (tempbuf));
+ for (i=0 ; i<4 ; i++) { /* SR0 - SR14 */
+ sprintf (tempbuf, "SR%3d",i*4);
+ expect(tempbuf);
+ for (j=0 ; j < (i==3 ? 3 : 4) ; j++)
+ sreg_buf[i*4 + j] = get_hex_word();
+ }
+ expect_prompt();
+ /*
+ * Read the pcs individually if we are in freeze mode.
+ * See get_reg_name(), it translates the register names for the pcs to
+ * the names of the shadow pcs.
+ */
+ if (USE_SHADOW_PC) {
+ sreg_buf[10] = read_register(NPC_REGNUM); /* pc0 */
+ sreg_buf[11] = read_register(PC_REGNUM); /* pc1 */
+ sreg_buf[12] = read_register(PC2_REGNUM); /* pc2 */
+ }
+ for (i=0 ; i<14 ; i++) /* Supply vab -> lru */
+ supply_register(VAB_REGNUM+i, (char *) &sreg_buf[i]);
+ sprintf (tempbuf, "dw sr128\r");
+ write (adapt_desc, tempbuf, strlen (tempbuf));
+ for (i=0 ; i<2 ; i++) { /* SR128 - SR135 */
+ sprintf (tempbuf, "SR%3d",128 + i*4);
+ expect(tempbuf);
+ for (j=0 ; j<4 ; j++)
+ sreg_buf[i*4 + j] = get_hex_word();
+ }
+ expect_prompt();
+ supply_register(IPC_REGNUM,(char *) &sreg_buf[0]);
+ supply_register(IPA_REGNUM,(char *) &sreg_buf[1]);
+ supply_register(IPB_REGNUM,(char *) &sreg_buf[2]);
+ supply_register(Q_REGNUM, (char *) &sreg_buf[3]);
+ /* Skip ALU */
+ supply_register(BP_REGNUM, (char *) &sreg_buf[5]);
+ supply_register(FC_REGNUM, (char *) &sreg_buf[6]);
+ supply_register(CR_REGNUM, (char *) &sreg_buf[7]);
+
+ /* There doesn't seem to be any way to get these. */
+ {
+ int val = -1;
+ supply_register (FPE_REGNUM, (char *) &val);
+ supply_register (INTE_REGNUM, (char *) &val);
+ supply_register (FPS_REGNUM, (char *) &val);
+ supply_register (EXO_REGNUM, (char *) &val);
+ }
+
+ write (adapt_desc, "dw gr1,gr1\r", 11);
+ expect ("GR001 ");
+ get_hex_regs (1, GR1_REGNUM);
+ expect_prompt ();
+}
+
+/* Fetch register REGNO, or all registers if REGNO is -1.
+ */
+static void
+adapt_fetch_register (regno)
+ int regno;
+{
+ if (regno == -1)
+ adapt_fetch_registers ();
+ else
+ {
+ char *name = get_reg_name (regno);
+ fprintf (adapt_stream, "dw %s,%s\r", name, name);
+ expect (name);
+ expect (" ");
+ get_hex_regs (1, regno);
+ expect_prompt ();
+ }
+}
+
+/* Store the remote registers from the contents of the block REGS. */
+
+static void
+adapt_store_registers ()
+{
+ int i, j;
+
+ fprintf (adapt_stream, "s gr1,%x\r", read_register (GR1_REGNUM));
+ expect_prompt ();
+
+#if defined(GR64_REGNUM)
+ for (j = 0; j < 32; j += 16)
+ {
+ fprintf (adapt_stream, "s gr%d,", j + 64);
+ for (i = 0; i < 15; ++i)
+ fprintf (adapt_stream, "%x,", read_register (GR64_REGNUM + j + i));
+ fprintf (adapt_stream, "%x\r", read_register (GR64_REGNUM + j + 15));
+ expect_prompt ();
+ }
+#endif
+ for (j = 0; j < 32; j += 16)
+ {
+ fprintf (adapt_stream, "s gr%d,", j + 96);
+ for (i = 0; i < 15; ++i)
+ fprintf (adapt_stream, "%x,", read_register (GR96_REGNUM + j + i));
+ fprintf (adapt_stream, "%x\r", read_register (GR96_REGNUM + j + 15));
+ expect_prompt ();
+ }
+
+ for (j = 0; j < 128; j += 16)
+ {
+ fprintf (adapt_stream, "s lr%d,", j);
+ for (i = 0; i < 15; ++i)
+ fprintf (adapt_stream, "%x,", read_register (LR0_REGNUM + j + i));
+ fprintf (adapt_stream, "%x\r", read_register (LR0_REGNUM + j + 15));
+ expect_prompt ();
+ }
+
+ fprintf (adapt_stream, "s sr128,%x,%x,%x\r", read_register (IPC_REGNUM),
+ read_register (IPA_REGNUM), read_register (IPB_REGNUM));
+ expect_prompt ();
+ fprintf (adapt_stream, "s sr133,%x,%x,%x\r", read_register (BP_REGNUM),
+ read_register (FC_REGNUM), read_register (CR_REGNUM));
+ expect_prompt ();
+ fprintf (adapt_stream, "s sr131,%x\r", read_register (Q_REGNUM));
+ expect_prompt ();
+ fprintf (adapt_stream, "s sr0,");
+ for (i=0 ; i<7 ; ++i)
+ fprintf (adapt_stream, "%x,", read_register (VAB_REGNUM + i));
+ expect_prompt ();
+ fprintf (adapt_stream, "s sr7,");
+ for (i=7; i<14 ; ++i)
+ fprintf (adapt_stream, "%x,", read_register (VAB_REGNUM + i));
+ expect_prompt ();
+}
+
+/* Store register REGNO, or all if REGNO == -1.
+ Return errno value. */
+void
+adapt_store_register (regno)
+ int regno;
+{
+ /* printf("adapt_store_register() called.\n"); fflush(stdout); /* */
+ if (regno == -1)
+ adapt_store_registers ();
+ else
+ {
+ char *name = get_reg_name (regno);
+ fprintf (adapt_stream, "s %s,%x\r", name, read_register (regno));
+ /* Setting GR1 changes the numbers of all the locals, so
+ invalidate the register cache. Do this *after* calling
+ read_register, because we want read_register to return the
+ value that write_register has just stuffed into the registers
+ array, not the value of the register fetched from the
+ inferior. */
+ if (regno == GR1_REGNUM)
+ registers_changed ();
+ expect_prompt ();
+ }
+}
+
+/* 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
+adapt_prepare_to_store ()
+{
+ /* Do nothing, since we can store individual regs */
+}
+
+static CORE_ADDR
+translate_addr(addr)
+CORE_ADDR addr;
+{
+#if defined(KERNEL_DEBUGGING)
+ /* Check for a virtual address in the kernel */
+ /* Assume physical address of ublock is in paddr_u register */
+ if (addr >= UVADDR) {
+ /* PADDR_U register holds the physical address of the ublock */
+ CORE_ADDR i = (CORE_ADDR)read_register(PADDR_U_REGNUM);
+ return(i + addr - (CORE_ADDR)UVADDR);
+ } else {
+ return(addr);
+ }
+#else
+ return(addr);
+#endif
+}
+
+
+/* FIXME! Merge these two. */
+int
+adapt_xfer_inferior_memory (memaddr, myaddr, len, write)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+ int write;
+{
+
+ memaddr = translate_addr(memaddr);
+
+ if (write)
+ return adapt_write_inferior_memory (memaddr, myaddr, len);
+ else
+ return adapt_read_inferior_memory (memaddr, myaddr, len);
+}
+
+void
+adapt_files_info ()
+{
+ printf_filtered("\tAttached to %s at %d baud and running program %s\n",
+ dev_name, baudrate, prog_name);
+ printf_filtered("\ton an %s processor.\n", processor_name[processor_type]);
+}
+
+/* Copy LEN bytes of data from debugger memory at MYADDR
+ to inferior's memory at MEMADDR. Returns errno value.
+ * sb/sh instructions don't work on unaligned addresses, when TU=1.
+ */
+int
+adapt_write_inferior_memory (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+{
+ int i;
+ unsigned int cps;
+
+ /* Turn TU bit off so we can do 'sb' commands */
+ cps = read_register(CPS_REGNUM);
+ if (cps & 0x00000800)
+ write_register(CPS_REGNUM,cps&~(0x00000800));
+
+ for (i = 0; i < len; i++)
+ {
+ if ((i % 16) == 0)
+ fprintf (adapt_stream, "sb %x,", memaddr + i);
+ if ((i % 16) == 15 || i == len - 1)
+ {
+ fprintf (adapt_stream, "%x\r", ((unsigned char *)myaddr)[i]);
+ expect_prompt ();
+ }
+ else
+ fprintf (adapt_stream, "%x,", ((unsigned char *)myaddr)[i]);
+ }
+ /* Restore the old value of cps if the TU bit was on */
+ if (cps & 0x00000800)
+ write_register(CPS_REGNUM,cps);
+ return len;
+}
+
+/* Read LEN bytes from inferior memory at MEMADDR. Put the result
+ at debugger address MYADDR. Returns errno value. */
+int
+adapt_read_inferior_memory(memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+{
+ int i;
+
+ /* Number of bytes read so far. */
+ int count;
+
+ /* Starting address of this pass. */
+ unsigned long startaddr;
+
+ /* Number of bytes to read in this pass. */
+ int len_this_pass;
+
+ /* Note that this code works correctly if startaddr is just less
+ than UINT_MAX (well, really CORE_ADDR_MAX if there was such a
+ thing). That is, something like
+ adapt_read_bytes (CORE_ADDR_MAX - 4, foo, 4)
+ works--it never adds len to memaddr and gets 0. */
+ /* However, something like
+ adapt_read_bytes (CORE_ADDR_MAX - 3, foo, 4)
+ doesn't need to work. Detect it and give up if there's an attempt
+ to do that. */
+
+ if (((memaddr - 1) + len) < memaddr)
+ return EIO;
+
+ startaddr = memaddr;
+ count = 0;
+ while (count < len)
+ {
+ len_this_pass = 16;
+ if ((startaddr % 16) != 0)
+ len_this_pass -= startaddr % 16;
+ if (len_this_pass > (len - count))
+ len_this_pass = (len - count);
+
+ fprintf (adapt_stream, "db %x,%x\r", startaddr,
+ (startaddr - 1) + len_this_pass);
+
+#ifdef NOTDEF /* Why do this */
+ expect ("\n");
+ /* Look for 8 hex digits. */
+ i = 0;
+ while (1)
+ {
+ if (isxdigit (readchar ()))
+ ++i;
+ else
+ {
+ expect_prompt ();
+ error ("Hex digit expected from remote system.");
+ }
+ if (i >= 8)
+ break;
+ }
+#endif /* NOTDEF */
+
+ expect (" ");
+
+ for (i = 0; i < len_this_pass; i++)
+ get_hex_byte (&myaddr[count++]);
+
+ expect_prompt ();
+
+ startaddr += len_this_pass;
+ }
+ return count;
+}
+
+#define MAX_BREAKS 8
+static int num_brkpts=0;
+static int
+adapt_insert_breakpoint(addr, save)
+CORE_ADDR addr;
+char *save; /* Throw away, let adapt save instructions */
+{
+ if (num_brkpts < MAX_BREAKS) {
+ num_brkpts++;
+ fprintf (adapt_stream, "B %x", addr);
+ fprintf (adapt_stream, "\r");
+ expect_prompt ();
+ return(0); /* Success */
+ } else {
+ fprintf_filtered(gdb_stderr,
+ "Too many break points, break point not installed\n");
+ return(1); /* Failure */
+ }
+
+}
+static int
+adapt_remove_breakpoint(addr, save)
+CORE_ADDR addr;
+char *save; /* Throw away, let adapt save instructions */
+{
+ if (num_brkpts > 0) {
+ num_brkpts--;
+ fprintf (adapt_stream, "BR %x", addr);
+ fprintf (adapt_stream, "\r");
+ fflush (adapt_stream);
+ expect_prompt ();
+ }
+ return(0);
+}
+
+/* Clear the adapts notion of what the break points are */
+static int
+adapt_clear_breakpoints()
+{
+ if (adapt_stream) {
+ fprintf (adapt_stream, "BR"); /* Clear all break points */
+ fprintf (adapt_stream, "\r");
+ fflush(adapt_stream);
+ expect_prompt ();
+ }
+ num_brkpts = 0;
+}
+static void
+adapt_mourn()
+{
+ adapt_clear_breakpoints();
+ pop_target (); /* Pop back to no-child state */
+ generic_mourn_inferior ();
+}
+
+/* Display everthing we read in from the adapt until we match/see the
+ * specified string
+ */
+static int
+display_until(str)
+char *str;
+{
+ int i=0,j,c;
+
+ while (c=readchar()) {
+ if (c==str[i]) {
+ i++;
+ if (i == strlen(str)) return;
+ } else {
+ if (i) {
+ for (j=0 ; j<i ; j++) /* Put everthing we matched */
+ putchar(str[j]);
+ i=0;
+ }
+ putchar(c);
+ }
+ }
+
+}
+
+
+/* Put a command string, in args, out to the adapt. The adapt is assumed to
+ be in raw mode, all writing/reading done through adapt_desc.
+ Ouput from the adapt is placed on the users terminal until the
+ prompt from the adapt is seen.
+ FIXME: Can't handle commands that take input. */
+
+void
+adapt_com (args, fromtty)
+ char *args;
+ int fromtty;
+{
+ if (!adapt_stream) {
+ printf_filtered("Adapt not open. Use the 'target' command to open.\n");
+ return;
+ }
+
+ /* Clear all input so only command relative output is displayed */
+ slurp_input();
+
+ switch(islower(args[0]) ? toupper(args[0]) : args[0]) {
+ default:
+ printf_filtered("Unknown/Unimplemented adapt command '%s'\n",args);
+ break;
+ case 'G': /* Go, begin execution */
+ write(adapt_desc,args,strlen(args));
+ write(adapt_desc,"\r",1);
+ expect_prompt();
+ break;
+ case 'B': /* Break points, B or BR */
+ case 'C': /* Check current 29k status (running/halted) */
+ case 'D': /* Display data/registers */
+ case 'I': /* Input from i/o space */
+ case 'J': /* Jam an instruction */
+ case 'K': /* Kill, stop execution */
+ case 'L': /* Disassemble */
+ case 'O': /* Output to i/o space */
+ case 'T': /* Trace */
+ case 'P': /* Pulse an input line */
+ case 'X': /* Examine special purpose registers */
+ case 'Z': /* Display trace buffer */
+ write(adapt_desc,args,strlen(args));
+ write(adapt_desc,"\r",1);
+ expect(args); /* Don't display the command */
+ display_until("# ");
+ break;
+ /* Begin commands that take input in the form 'c x,y[,z...]' */
+ case 'S': /* Set memory or register */
+ if (strchr(args,',')) { /* Assume it is properly formatted */
+ write(adapt_desc,args,strlen(args));
+ write(adapt_desc,"\r",1);
+ expect_prompt();
+ }
+ break;
+ }
+}
+
+/* Define the target subroutine names */
+
+struct target_ops adapt_ops ;
+
+static void
+init_adapt_ops(void)
+{
+ adapt_ops.to_shortname = "adapt";
+ adapt_ops.to_longname = "Remote AMD `Adapt' target";
+ adapt_ops.to_doc = "Remote debug an AMD 290*0 using an `Adapt' monitor via RS232";
+ adapt_ops.to_open = adapt_open;
+ adapt_ops.to_close = adapt_close;
+ adapt_ops.to_attach = adapt_attach;
+ adapt_ops.to_post_attach = NULL;
+ adapt_ops.to_require_attach = NULL;
+ adapt_ops.to_detach = adapt_detach;
+ adapt_ops.to_require_detach = NULL;
+ adapt_ops.to_resume = adapt_resume;
+ adapt_ops.to_wait = adapt_wait;
+ adapt_ops.to_post_wait = NULL;
+ adapt_ops.to_fetch_registers = adapt_fetch_register;
+ adapt_ops.to_store_registers = adapt_store_register;
+ adapt_ops.to_prepare_to_store = adapt_prepare_to_store;
+ adapt_ops.to_xfer_memory = adapt_xfer_inferior_memory;
+ adapt_ops.to_files_info = adapt_files_info;
+ adapt_ops.to_insert_breakpoint = adapt_insert_breakpoint;
+ adapt_ops.to_remove_breakpoint = adapt_remove_breakpoint;
+ adapt_ops.to_terminal_init = 0;
+ adapt_ops.to_terminal_inferior = 0;
+ adapt_ops.to_terminal_ours_for_output = 0;
+ adapt_ops.to_terminal_ours = 0;
+ adapt_ops.to_terminal_info = 0;
+ adapt_ops.to_kill = adapt_kill;
+ adapt_ops.to_load = adapt_load;
+ adapt_ops.to_lookup_symbol = 0;
+ adapt_ops.to_create_inferior = adapt_create_inferior;
+ adapt_ops.to_post_startup_inferior = NULL;
+ adapt_ops.to_acknowledge_created_inferior = NULL;
+ adapt_ops.to_clone_and_follow_inferior = NULL;
+ adapt_ops.to_post_follow_inferior_by_clone = NULL;
+ adapt_ops.to_insert_fork_catchpoint = NULL;
+ adapt_ops.to_remove_fork_catchpoint = NULL;
+ adapt_ops.to_insert_vfork_catchpoint = NULL;
+ adapt_ops.to_remove_vfork_catchpoint = NULL;
+ adapt_ops.to_has_forked = NULL;
+ adapt_ops.to_has_vforked = NULL;
+ adapt_ops.to_can_follow_vfork_prior_to_exec = NULL;
+ adapt_ops.to_post_follow_vfork = NULL;
+ adapt_ops.to_insert_exec_catchpoint = NULL;
+ adapt_ops.to_remove_exec_catchpoint = NULL;
+ adapt_ops.to_has_execd = NULL;
+ adapt_ops.to_reported_exec_events_per_exec_call = NULL;
+ adapt_ops.to_has_exited = NULL;
+ adapt_ops.to_mourn_inferior = adapt_mourn;
+ adapt_ops.to_can_run = 0;
+ adapt_ops.to_notice_signals = 0;
+ adapt_ops.to_thread_alive = 0;
+ adapt_ops.to_stop = 0 ; /* process_stratum; */
+ adapt_ops.to_pid_to_exec_file = NULL;
+ adapt_ops.to_core_file_to_sym_file = NULL;
+ adapt_ops.to_stratum = 0;
+ adapt_ops.DONT_USE = 0 ;
+ adapt_ops.to_has_all_memory = 1;
+ adapt_ops.to_has_memory = 1;
+ adapt_ops.to_has_stack = 1;
+ adapt_ops.to_has_registers = 1;
+ adapt_ops.to_has_execution = 0;
+ adapt_ops.to_sections = 0;
+ adapt_ops.to_sections_end = 0 ;
+ adapt_ops.to_magic = OPS_MAGIC;
+} /* init_adapt_ops */
+
+void
+_initialize_remote_adapt ()
+{
+ init_adapt_ops() ;
+ add_target (&adapt_ops);
+ add_com ("adapt <command>", class_obscure, adapt_com,
+ "Send a command to the AMD Adapt remote monitor.");
+}
diff --git a/gdb/remote-array.c b/gdb/remote-array.c
new file mode 100644
index 00000000000..624871cff02
--- /dev/null
+++ b/gdb/remote-array.c
@@ -0,0 +1,1497 @@
+/* Remote debugging interface for Array Tech RAID controller..
+ Copyright 90, 91, 92, 93, 94, 1995, 1998 Free Software Foundation, Inc.
+ Contributed by Cygnus Support. Written by Rob Savoye for Cygnus.
+
+ This module talks to a debug monitor called 'MONITOR', which
+ We communicate with MONITOR via either a direct serial line, or a TCP
+ (or possibly TELNET) stream to a terminal multiplexor,
+ which in turn talks to the target board.
+
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "defs.h"
+#include "gdbcore.h"
+#include "target.h"
+#include "wait.h"
+#ifdef ANSI_PROTOTYPES
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+#include <ctype.h>
+#include <signal.h>
+#include <sys/types.h>
+#include "gdb_string.h"
+#include "command.h"
+#include "serial.h"
+#include "monitor.h"
+#include "remote-utils.h"
+
+extern int baud_rate;
+
+#define ARRAY_PROMPT ">> "
+
+#define SWAP_TARGET_AND_HOST(buffer,len) \
+ do \
+ { \
+ if (TARGET_BYTE_ORDER != HOST_BYTE_ORDER) \
+ { \
+ char tmp; \
+ char *p = (char *)(buffer); \
+ char *q = ((char *)(buffer)) + len - 1; \
+ for (; p < q; p++, q--) \
+ { \
+ tmp = *q; \
+ *q = *p; \
+ *p = tmp; \
+ } \
+ } \
+ } \
+ while (0)
+
+static void debuglogs PARAMS((int, char *, ...));
+static void array_open();
+static void array_close();
+static void array_detach();
+static void array_attach();
+static void array_resume();
+static void array_fetch_register();
+static void array_store_register();
+static void array_fetch_registers();
+static void array_store_registers();
+static void array_prepare_to_store();
+static void array_files_info();
+static void array_kill();
+static void array_create_inferior();
+static void array_mourn_inferior();
+static void make_gdb_packet();
+static int array_xfer_memory();
+static int array_wait();
+static int array_insert_breakpoint();
+static int array_remove_breakpoint();
+static int tohex();
+static int to_hex();
+static int from_hex();
+static int array_send_packet();
+static int array_get_packet();
+static unsigned long ascii2hexword();
+static void hexword2ascii();
+
+extern char *version;
+
+#define LOG_FILE "monitor.log"
+#if defined (LOG_FILE)
+FILE *log_file;
+#endif
+
+static int timeout = 30;
+/* Having this larger than 400 causes us to be incompatible with m68k-stub.c
+ and i386-stub.c. Normally, no one would notice because it only matters
+ for writing large chunks of memory (e.g. in downloads). Also, this needs
+ to be more than 400 if required to hold the registers (see below, where
+ we round it up based on REGISTER_BYTES). */
+#define PBUFSIZ 400
+
+/*
+ * Descriptor for I/O to remote machine. Initialize it to NULL so that
+ * array_open knows that we don't have a file open when the program starts.
+ */
+serial_t array_desc = NULL;
+
+/*
+ * this array of registers need to match the indexes used by GDB. The
+ * whole reason this exists is cause the various ROM monitors use
+ * different strings than GDB does, and doesn't support all the
+ * registers either. So, typing "info reg sp" becomes a "r30".
+ */
+extern char *tmp_mips_processor_type;
+extern int mips_set_processor_type();
+
+static struct target_ops array_ops ;
+
+static void
+init_array_ops(void)
+{
+ array_ops.to_shortname = "array";
+ array_ops.to_longname =
+ "Debug using the standard GDB remote protocol for the Array Tech target.",
+ array_ops.to_doc =
+ "Debug using the standard GDB remote protocol for the Array Tech target.\n\
+Specify the serial device it is connected to (e.g. /dev/ttya)." ;
+ array_ops.to_open = array_open;
+ array_ops.to_close = array_close;
+ array_ops.to_attach = NULL;
+ array_ops.to_post_attach = NULL;
+ array_ops.to_require_attach = NULL;
+ array_ops.to_detach = array_detach;
+ array_ops.to_require_detach = NULL;
+ array_ops.to_resume = array_resume;
+ array_ops.to_wait = array_wait;
+ array_ops.to_post_wait = NULL;
+ array_ops.to_fetch_registers = array_fetch_registers;
+ array_ops.to_store_registers = array_store_registers;
+ array_ops.to_prepare_to_store = array_prepare_to_store;
+ array_ops.to_xfer_memory = array_xfer_memory;
+ array_ops.to_files_info = array_files_info;
+ array_ops.to_insert_breakpoint = array_insert_breakpoint;
+ array_ops.to_remove_breakpoint = array_remove_breakpoint;
+ array_ops.to_terminal_init = 0;
+ array_ops.to_terminal_inferior = 0;
+ array_ops.to_terminal_ours_for_output = 0;
+ array_ops.to_terminal_ours = 0;
+ array_ops.to_terminal_info = 0;
+ array_ops.to_kill = array_kill;
+ array_ops.to_load = 0;
+ array_ops.to_lookup_symbol = 0;
+ array_ops.to_create_inferior = array_create_inferior;
+ array_ops.to_post_startup_inferior = NULL;
+ array_ops.to_acknowledge_created_inferior = NULL;
+ array_ops.to_clone_and_follow_inferior = NULL;
+ array_ops.to_post_follow_inferior_by_clone = NULL;
+ array_ops.to_insert_fork_catchpoint = NULL;
+ array_ops.to_remove_fork_catchpoint = NULL;
+ array_ops.to_insert_vfork_catchpoint = NULL;
+ array_ops.to_remove_vfork_catchpoint = NULL;
+ array_ops.to_has_forked = NULL;
+ array_ops.to_has_vforked = NULL;
+ array_ops.to_can_follow_vfork_prior_to_exec = NULL;
+ array_ops.to_post_follow_vfork = NULL;
+ array_ops.to_insert_exec_catchpoint = NULL;
+ array_ops.to_remove_exec_catchpoint = NULL;
+ array_ops.to_has_execd = NULL;
+ array_ops.to_reported_exec_events_per_exec_call = NULL;
+ array_ops.to_has_exited = NULL;
+ array_ops.to_mourn_inferior = array_mourn_inferior;
+ array_ops.to_can_run = 0;
+ array_ops.to_notice_signals = 0;
+ array_ops.to_thread_alive = 0;
+ array_ops.to_stop = 0;
+ array_ops.to_pid_to_exec_file = NULL;
+ array_ops.to_core_file_to_sym_file = NULL;
+ array_ops.to_stratum = process_stratum;
+ array_ops.DONT_USE = 0;
+ array_ops.to_has_all_memory = 1;
+ array_ops.to_has_memory = 1;
+ array_ops.to_has_stack = 1;
+ array_ops.to_has_registers = 1;
+ array_ops.to_has_execution = 1;
+ array_ops.to_sections = 0;
+ array_ops.to_sections_end = 0;
+ array_ops.to_magic = OPS_MAGIC;
+};
+
+/*
+ * printf_monitor -- send data to monitor. Works just like printf.
+ */
+static void
+#ifdef ANSI_PROTOTYPES
+printf_monitor(char *pattern, ...)
+#else
+printf_monitor(va_alist)
+ va_dcl
+#endif
+{
+ va_list args;
+ char buf[PBUFSIZ];
+ int i;
+
+#ifdef ANSI_PROTOTYPES
+ va_start(args, pattern);
+#else
+ char *pattern;
+ va_start(args);
+ pattern = va_arg(args, char *);
+#endif
+
+ vsprintf(buf, pattern, args);
+
+ debuglogs (1, "printf_monitor(), Sending: \"%s\".", buf);
+
+ if (strlen(buf) > PBUFSIZ)
+ error ("printf_monitor(): string too long");
+ if (SERIAL_WRITE(array_desc, buf, strlen(buf)))
+ fprintf(stderr, "SERIAL_WRITE failed: %s\n", safe_strerror(errno));
+}
+/*
+ * write_monitor -- send raw data to monitor.
+ */
+static void
+write_monitor(data, len)
+ char data[];
+ int len;
+{
+ if (SERIAL_WRITE(array_desc, data, len))
+ fprintf(stderr, "SERIAL_WRITE failed: %s\n", safe_strerror(errno));
+
+ *(data + len+1) = '\0';
+ debuglogs (1, "write_monitor(), Sending: \"%s\".", data);
+
+}
+
+/*
+ * debuglogs -- deal with debugging info to multiple sources. This takes
+ * two real args, the first one is the level to be compared against
+ * the sr_get_debug() value, the second arg is a printf buffer and args
+ * to be formatted and printed. A CR is added after each string is printed.
+ */
+static void
+#ifdef ANSI_PROTOTYPES
+debuglogs(int level, char *pattern, ...)
+#else
+debuglogs(va_alist)
+ va_dcl
+#endif
+{
+ va_list args;
+ char *p;
+ unsigned char buf[PBUFSIZ];
+ char newbuf[PBUFSIZ];
+ int i;
+
+#ifdef ANSI_PROTOTYPES
+ va_start(args, pattern);
+#else
+ char *pattern;
+ int level;
+ va_start(args);
+ level = va_arg(args, int); /* get the debug level */
+ pattern = va_arg(args, char *); /* get the printf style pattern */
+#endif
+
+ if ((level <0) || (level > 100)) {
+ error ("Bad argument passed to debuglogs(), needs debug level");
+ return;
+ }
+
+ vsprintf(buf, pattern, args); /* format the string */
+
+ /* convert some characters so it'll look right in the log */
+ p = newbuf;
+ for (i = 0 ; buf[i] != '\0'; i++) {
+ if (i > PBUFSIZ)
+ error ("Debug message too long");
+ switch (buf[i]) {
+ case '\n': /* newlines */
+ *p++ = '\\';
+ *p++ = 'n';
+ continue;
+ case '\r': /* carriage returns */
+ *p++ = '\\';
+ *p++ = 'r';
+ continue;
+ case '\033': /* escape */
+ *p++ = '\\';
+ *p++ = 'e';
+ continue;
+ case '\t': /* tab */
+ *p++ = '\\';
+ *p++ = 't';
+ continue;
+ case '\b': /* backspace */
+ *p++ = '\\';
+ *p++ = 'b';
+ continue;
+ default: /* no change */
+ *p++ = buf[i];
+ }
+
+ if (buf[i] < 26) { /* modify control characters */
+ *p++ = '^';
+ *p++ = buf[i] + 'A';
+ continue;
+ }
+ if (buf[i] >= 128) { /* modify control characters */
+ *p++ = '!';
+ *p++ = buf[i] + 'A';
+ continue;
+ }
+ }
+ *p = '\0'; /* terminate the string */
+
+ if (sr_get_debug() > level)
+ printf_unfiltered ("%s\n", newbuf);
+
+#ifdef LOG_FILE /* write to the monitor log */
+ if (log_file != 0x0) {
+ fputs (newbuf, log_file);
+ fputc ('\n', log_file);
+ fflush (log_file);
+ }
+#endif
+}
+
+/* readchar -- read a character from the remote system, doing all the fancy
+ * timeout stuff.
+ */
+static int
+readchar(timeout)
+ int timeout;
+{
+ int c;
+
+ c = SERIAL_READCHAR(array_desc, abs(timeout));
+
+ if (sr_get_debug() > 5) {
+ putchar(c & 0x7f);
+ debuglogs (5, "readchar: timeout = %d\n", timeout);
+ }
+
+#ifdef LOG_FILE
+ if (isascii (c))
+ putc(c & 0x7f, log_file);
+#endif
+
+ if (c >= 0)
+ return c & 0x7f;
+
+ if (c == SERIAL_TIMEOUT) {
+ if (timeout <= 0)
+ return c; /* Polls shouldn't generate timeout errors */
+ error("Timeout reading from remote system.");
+#ifdef LOG_FILE
+ fputs ("ERROR: Timeout reading from remote system", log_file);
+#endif
+ }
+ perror_with_name("readchar");
+}
+
+/*
+ * expect -- scan input from the remote system, until STRING is found.
+ * If DISCARD is non-zero, then discard non-matching input, else print
+ * it out. Let the user break out immediately.
+ */
+static void
+expect (string, discard)
+ char *string;
+ int discard;
+{
+ char *p = string;
+ int c;
+
+
+ debuglogs (1, "Expecting \"%s\".", string);
+
+ immediate_quit = 1;
+ while (1) {
+ c = readchar(timeout);
+ if (!isascii (c))
+ continue;
+ if (c == *p++) {
+ if (*p == '\0') {
+ immediate_quit = 0;
+ debuglogs (4, "Matched");
+ return;
+ }
+ } else {
+ if (!discard) {
+ fputc_unfiltered (c, gdb_stdout);
+ }
+ p = string;
+ }
+ }
+}
+
+/* Keep discarding input until we see the MONITOR array_cmds->prompt.
+
+ The convention for dealing with the expect_prompt is that you
+ o give your command
+ o *then* wait for the expect_prompt.
+
+ Thus the last thing that a procedure does with the serial line
+ will be an expect_prompt(). Exception: array_resume does not
+ wait for the expect_prompt, because the terminal is being handed over
+ to the inferior. However, the next thing which happens after that
+ is a array_wait which does wait for the expect_prompt.
+ Note that this includes abnormal exit, e.g. error(). This is
+ necessary to prevent getting into states from which we can't
+ recover. */
+static void
+expect_prompt(discard)
+ int discard;
+{
+ expect (ARRAY_PROMPT, discard);
+}
+
+/*
+ * junk -- ignore junk characters. Returns a 1 if junk, 0 otherwise
+ */
+static int
+junk(ch)
+ char ch;
+{
+ switch (ch) {
+ case '\0':
+ case ' ':
+ case '-':
+ case '\t':
+ case '\r':
+ case '\n':
+ if (sr_get_debug() > 5)
+ debuglogs (5, "Ignoring \'%c\'.", ch);
+ return 1;
+ default:
+ if (sr_get_debug() > 5)
+ debuglogs (5, "Accepting \'%c\'.", ch);
+ return 0;
+ }
+}
+
+/*
+ * get_hex_digit -- Get a hex digit from the remote system & return its value.
+ * If ignore is nonzero, ignore spaces, newline & tabs.
+ */
+static int
+get_hex_digit(ignore)
+ int ignore;
+{
+ static int ch;
+ while (1) {
+ ch = readchar(timeout);
+ if (junk(ch))
+ continue;
+ if (sr_get_debug() > 4) {
+ debuglogs (4, "get_hex_digit() got a 0x%x(%c)", ch, ch);
+ } else {
+#ifdef LOG_FILE /* write to the monitor log */
+ if (log_file != 0x0) {
+ fputs ("get_hex_digit() got a 0x", log_file);
+ fputc (ch, log_file);
+ fputc ('\n', log_file);
+ fflush (log_file);
+ }
+#endif
+ }
+
+ 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)
+ ;
+ else {
+ expect_prompt(1);
+ debuglogs (4, "Invalid hex digit from remote system. (0x%x)", ch);
+ error("Invalid hex digit from remote system. (0x%x)", ch);
+ }
+ }
+}
+
+/* get_hex_byte -- Get a byte from monitor and put it in *BYT.
+ * Accept any number leading spaces.
+ */
+static void
+get_hex_byte (byt)
+ char *byt;
+{
+ int val;
+
+ val = get_hex_digit (1) << 4;
+ debuglogs (4, "get_hex_byte() -- Read first nibble 0x%x", val);
+
+ val |= get_hex_digit (0);
+ debuglogs (4, "get_hex_byte() -- Read second nibble 0x%x", val);
+ *byt = val;
+
+ debuglogs (4, "get_hex_byte() -- Read a 0x%x", val);
+}
+
+/*
+ * get_hex_word -- Get N 32-bit words from remote, each preceded by a space,
+ * and put them in registers starting at REGNO.
+ */
+static int
+get_hex_word ()
+{
+ long val, newval;
+ int i;
+
+ val = 0;
+
+#if 0
+ if (HOST_BYTE_ORDER == BIG_ENDIAN) {
+#endif
+ for (i = 0; i < 8; i++)
+ val = (val << 4) + get_hex_digit (i == 0);
+#if 0
+ } else {
+ for (i = 7; i >= 0; i--)
+ val = (val << 4) + get_hex_digit (i == 0);
+ }
+#endif
+
+ debuglogs (4, "get_hex_word() got a 0x%x for a %s host.", val, (HOST_BYTE_ORDER == BIG_ENDIAN) ? "big endian" : "little endian");
+
+ return val;
+}
+
+/* This is called not only when we first attach, but also when the
+ user types "run" after having attached. */
+static void
+array_create_inferior (execfile, args, env)
+ char *execfile;
+ char *args;
+ char **env;
+{
+ int entry_pt;
+
+ if (args && *args)
+ error("Can't pass arguments to remote MONITOR process");
+
+ if (execfile == 0 || exec_bfd == 0)
+ error("No executable file specified");
+
+ entry_pt = (int) bfd_get_start_address (exec_bfd);
+
+/* The "process" (board) is already stopped awaiting our commands, and
+ the program is already downloaded. We just set its PC and go. */
+
+ clear_proceed_status ();
+
+ /* Tell wait_for_inferior that we've started a new process. */
+ init_wait_for_inferior ();
+
+ /* Set up the "saved terminal modes" of the inferior
+ based on what modes we are starting it with. */
+ target_terminal_init ();
+
+ /* Install inferior's terminal modes. */
+ target_terminal_inferior ();
+
+ /* insert_step_breakpoint (); FIXME, do we need this? */
+
+ /* Let 'er rip... */
+ proceed ((CORE_ADDR)entry_pt, TARGET_SIGNAL_DEFAULT, 0);
+}
+
+/*
+ * array_open -- open a connection to a remote debugger.
+ * NAME is the filename used for communication.
+ */
+static int baudrate = 9600;
+static char dev_name[100];
+
+static void
+array_open(args, name, from_tty)
+ char *args;
+ char *name;
+ int from_tty;
+{
+ char packet[PBUFSIZ];
+
+ if (args == NULL)
+ error ("Use `target %s DEVICE-NAME' to use a serial port, or \n\
+`target %s HOST-NAME:PORT-NUMBER' to use a network connection.", name, name);
+
+/* if (is_open) */
+ array_close(0);
+
+ target_preopen (from_tty);
+ unpush_target (&array_ops);
+
+ tmp_mips_processor_type = "lsi33k"; /* change the default from r3051 */
+ mips_set_processor_type_command ("lsi33k", 0);
+
+ strcpy(dev_name, args);
+ array_desc = SERIAL_OPEN(dev_name);
+
+ if (array_desc == NULL)
+ perror_with_name(dev_name);
+
+ if (baud_rate != -1) {
+ if (SERIAL_SETBAUDRATE (array_desc, baud_rate)) {
+ SERIAL_CLOSE (array_desc);
+ perror_with_name (name);
+ }
+ }
+
+ SERIAL_RAW(array_desc);
+
+#if defined (LOG_FILE)
+ log_file = fopen (LOG_FILE, "w");
+ if (log_file == NULL)
+ perror_with_name (LOG_FILE);
+ fprintf (log_file, "GDB %s (%s", version);
+ fprintf (log_file, " --target %s)\n", array_ops.to_shortname);
+ fprintf (log_file, "Remote target %s connected to %s\n\n", array_ops.to_shortname, dev_name);
+#endif
+
+ /* see if the target is alive. For a ROM monitor, we can just try to force the
+ expect_prompt to print a few times. For the GDB remote protocol, the application
+ being debugged is sitting at a breakpoint and waiting for GDB to initialize
+ the connection. We force it to give us an empty packet to see if it's alive.
+ */
+ debuglogs (3, "Trying to ACK the target's debug stub");
+ /* unless your are on the new hardware, the old board won't initialize
+ because the '@' doesn't flush output like it does on the new ROMS.
+ */
+ printf_monitor ("@"); /* ask for the last signal */
+ expect_prompt(1); /* See if we get a expect_prompt */
+#ifdef TEST_ARRAY /* skip packet for testing */
+ make_gdb_packet (packet, "?"); /* ask for a bogus packet */
+ if (array_send_packet (packet) == 0)
+ error ("Couldn't transmit packet\n");
+ printf_monitor ("@\n"); /* force it to flush stdout */
+ expect_prompt(1); /* See if we get a expect_prompt */
+#endif
+ push_target (&array_ops);
+ if (from_tty)
+ printf("Remote target %s connected to %s\n", array_ops.to_shortname, dev_name);
+}
+
+/*
+ * array_close -- Close out all files and local state before this
+ * target loses control.
+ */
+
+static void
+array_close (quitting)
+ int quitting;
+{
+ SERIAL_CLOSE(array_desc);
+ array_desc = NULL;
+
+ debuglogs (1, "array_close (quitting=%d)", quitting);
+
+#if defined (LOG_FILE)
+ if (log_file) {
+ if (ferror(log_file))
+ printf_filtered ("Error writing log file.\n");
+ if (fclose(log_file) != 0)
+ printf_filtered ("Error closing log file.\n");
+ }
+#endif
+}
+
+/*
+ * array_detach -- terminate the open connection to the remote
+ * debugger. Use this when you want to detach and do something
+ * else with your gdb.
+ */
+static void
+array_detach (from_tty)
+ int from_tty;
+{
+
+ debuglogs (1, "array_detach ()");
+
+ pop_target(); /* calls array_close to do the real work */
+ if (from_tty)
+ printf ("Ending remote %s debugging\n", target_shortname);
+}
+
+/*
+ * array_attach -- attach GDB to the target.
+ */
+static void
+array_attach (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ if (from_tty)
+ printf ("Starting remote %s debugging\n", target_shortname);
+
+ debuglogs (1, "array_attach (args=%s)", args);
+
+ printf_monitor ("go %x\n");
+ /* swallow the echo. */
+ expect ("go %x\n", 1);
+}
+
+/*
+ * array_resume -- Tell the remote machine to resume.
+ */
+static void
+array_resume (pid, step, sig)
+ int pid, step;
+ enum target_signal sig;
+{
+ debuglogs (1, "array_resume (step=%d, sig=%d)", step, sig);
+
+ if (step) {
+ printf_monitor ("s\n");
+ } else {
+ printf_monitor ("go\n");
+ }
+}
+
+#define TMPBUFSIZ 5
+
+/*
+ * array_wait -- Wait until the remote machine stops, then return,
+ * storing status in status just as `wait' would.
+ */
+static int
+array_wait (pid, status)
+ int pid;
+ struct target_waitstatus *status;
+{
+ int old_timeout = timeout;
+ int result, i;
+ char c;
+ serial_t tty_desc;
+ serial_ttystate ttystate;
+
+ debuglogs(1, "array_wait (), printing extraneous text.");
+
+ status->kind = TARGET_WAITKIND_EXITED;
+ status->value.integer = 0;
+
+ timeout = 0; /* Don't time out -- user program is running. */
+
+#if !defined(__GO32__) && !defined(__MSDOS__) && !defined(_WIN32)
+ tty_desc = SERIAL_FDOPEN (0);
+ ttystate = SERIAL_GET_TTY_STATE (tty_desc);
+ SERIAL_RAW (tty_desc);
+
+ i = 0;
+ /* poll on the serial port and the keyboard. */
+ while (1) {
+ c = readchar(timeout);
+ if (c > 0) {
+ if (c == *(ARRAY_PROMPT + i)) {
+ if (++i >= strlen (ARRAY_PROMPT)) { /* matched the prompt */
+ debuglogs (4, "array_wait(), got the expect_prompt.");
+ break;
+ }
+ } else { /* not the prompt */
+ i = 0;
+ }
+ fputc_unfiltered (c, gdb_stdout);
+ gdb_flush (gdb_stdout);
+ }
+ c = SERIAL_READCHAR(tty_desc, timeout);
+ if (c > 0) {
+ SERIAL_WRITE(array_desc, &c, 1);
+ /* do this so it looks like there's keyboard echo */
+ if (c == 3) /* exit on Control-C */
+ break;
+#if 0
+ fputc_unfiltered (c, gdb_stdout);
+ gdb_flush (gdb_stdout);
+#endif
+ }
+ }
+ SERIAL_SET_TTY_STATE (tty_desc, ttystate);
+#else
+ expect_prompt(1);
+ debuglogs (4, "array_wait(), got the expect_prompt.");
+#endif
+
+ status->kind = TARGET_WAITKIND_STOPPED;
+ status->value.sig = TARGET_SIGNAL_TRAP;
+
+ timeout = old_timeout;
+
+ return 0;
+}
+
+/*
+ * array_fetch_registers -- read the remote registers into the
+ * block regs.
+ */
+static void
+array_fetch_registers (ignored)
+ int ignored;
+{
+ int regno, i;
+ char *p;
+ unsigned char packet[PBUFSIZ];
+ char regs[REGISTER_BYTES];
+
+ debuglogs (1, "array_fetch_registers (ignored=%d)\n", ignored);
+
+ memset (packet, 0, PBUFSIZ);
+ /* Unimplemented registers read as all bits zero. */
+ memset (regs, 0, REGISTER_BYTES);
+ make_gdb_packet (packet, "g");
+ if (array_send_packet (packet) == 0)
+ error ("Couldn't transmit packet\n");
+ if (array_get_packet (packet) == 0)
+ error ("Couldn't receive packet\n");
+ /* FIXME: read bytes from packet */
+ debuglogs (4, "array_fetch_registers: Got a \"%s\" back\n", packet);
+ for (regno = 0; regno <= PC_REGNUM+4; regno++) {
+ /* supply register stores in target byte order, so swap here */
+ /* FIXME: convert from ASCII hex to raw bytes */
+ i = ascii2hexword (packet + (regno * 8));
+ debuglogs (5, "Adding register %d = %x\n", regno, i);
+ SWAP_TARGET_AND_HOST (&i, 4);
+ supply_register (regno, (char *)&i);
+ }
+}
+
+/*
+ * This is unused by targets like this one that use a
+ * protocol based on GDB's remote protocol.
+ */
+static void
+array_fetch_register (ignored)
+ int ignored;
+{
+ array_fetch_registers ();
+}
+
+/*
+ * Get all the registers from the targets. They come back in a large array.
+ */
+static void
+array_store_registers (ignored)
+ int ignored;
+{
+ int regno;
+ unsigned long i;
+ char packet[PBUFSIZ];
+ char buf[PBUFSIZ];
+ char num[9];
+
+ debuglogs (1, "array_store_registers()");
+
+ memset (packet, 0, PBUFSIZ);
+ memset (buf, 0, PBUFSIZ);
+ buf[0] = 'G';
+
+ /* Unimplemented registers read as all bits zero. */
+ /* FIXME: read bytes from packet */
+ for (regno = 0; regno < 41; regno++) { /* FIXME */
+ /* supply register stores in target byte order, so swap here */
+ /* FIXME: convert from ASCII hex to raw bytes */
+ i = (unsigned long)read_register (regno);
+ hexword2ascii (num, i);
+ strcpy (buf+(regno * 8)+1, num);
+ }
+ *(buf + (regno * 8) + 2) = 0;
+ make_gdb_packet (packet, buf);
+ if (array_send_packet (packet) == 0)
+ error ("Couldn't transmit packet\n");
+ if (array_get_packet (packet) == 0)
+ error ("Couldn't receive packet\n");
+
+ registers_changed ();
+}
+
+/*
+ * This is unused by targets like this one that use a
+ * protocol based on GDB's remote protocol.
+ */
+static void
+array_store_register (ignored)
+ int ignored;
+{
+ array_store_registers ();
+}
+
+/* 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
+array_prepare_to_store ()
+{
+ /* Do nothing, since we can store individual regs */
+}
+
+static void
+array_files_info ()
+{
+ printf ("\tAttached to %s at %d baud.\n",
+ dev_name, baudrate);
+}
+
+/*
+ * array_write_inferior_memory -- Copy LEN bytes of data from debugger
+ * memory at MYADDR to inferior's memory at MEMADDR. Returns length moved.
+ */
+static int
+array_write_inferior_memory (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ unsigned char *myaddr;
+ int len;
+{
+ unsigned long i;
+ int j;
+ char packet[PBUFSIZ];
+ char buf[PBUFSIZ];
+ char num[9];
+ char *p;
+
+ debuglogs (1, "array_write_inferior_memory (memaddr=0x%x, myaddr=0x%x, len=%d)", memaddr, myaddr, len);
+ memset (buf, '\0', PBUFSIZ); /* this also sets the string terminator */
+ p = buf;
+
+ *p++ = 'M'; /* The command to write memory */
+ hexword2ascii (num, memaddr); /* convert the address */
+ strcpy (p, num); /* copy the address */
+ p += 8;
+ *p++ = ','; /* add comma delimeter */
+ hexword2ascii (num, len); /* Get the length as a 4 digit number */
+ *p++ = num[4];
+ *p++ = num[5];
+ *p++ = num[6];
+ *p++ = num[7];
+ *p++ = ':'; /* add the colon delimeter */
+ for (j = 0; j < len; j++) { /* copy the data in after converting it */
+ *p++ = tohex ((myaddr[j] >> 4) & 0xf);
+ *p++ = tohex (myaddr[j] & 0xf);
+ }
+
+ make_gdb_packet (packet, buf);
+ if (array_send_packet (packet) == 0)
+ error ("Couldn't transmit packet\n");
+ if (array_get_packet (packet) == 0)
+ error ("Couldn't receive packet\n");
+
+ return len;
+}
+
+/*
+ * array_read_inferior_memory -- read LEN bytes from inferior memory
+ * at MEMADDR. Put the result at debugger address MYADDR. Returns
+ * length moved.
+ */
+static int
+array_read_inferior_memory(memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+{
+ int j;
+ char buf[20];
+ char packet[PBUFSIZ];
+ int count; /* Number of bytes read so far. */
+ unsigned long startaddr; /* Starting address of this pass. */
+ int len_this_pass; /* Number of bytes to read in this pass. */
+
+ debuglogs (1, "array_read_inferior_memory (memaddr=0x%x, myaddr=0x%x, len=%d)", memaddr, myaddr, len);
+
+ /* Note that this code works correctly if startaddr is just less
+ than UINT_MAX (well, really CORE_ADDR_MAX if there was such a
+ thing). That is, something like
+ array_read_bytes (CORE_ADDR_MAX - 4, foo, 4)
+ works--it never adds len To memaddr and gets 0. */
+ /* However, something like
+ array_read_bytes (CORE_ADDR_MAX - 3, foo, 4)
+ doesn't need to work. Detect it and give up if there's an attempt
+ to do that. */
+ if (((memaddr - 1) + len) < memaddr) {
+ errno = EIO;
+ return 0;
+ }
+
+ for (count = 0, startaddr = memaddr; count < len; startaddr += len_this_pass)
+ {
+ /* Try to align to 16 byte boundry (why?) */
+ len_this_pass = 16;
+ if ((startaddr % 16) != 0)
+ {
+ len_this_pass -= startaddr % 16;
+ }
+ /* Only transfer bytes we need */
+ if (len_this_pass > (len - count))
+ {
+ len_this_pass = (len - count);
+ }
+ /* Fetch the bytes */
+ debuglogs (3, "read %d bytes from inferior address %x", len_this_pass,
+ startaddr);
+ sprintf (buf, "m%08x,%04x", startaddr, len_this_pass);
+ make_gdb_packet (packet, buf);
+ if (array_send_packet (packet) == 0)
+ {
+ error ("Couldn't transmit packet\n");
+ }
+ if (array_get_packet (packet) == 0)
+ {
+ error ("Couldn't receive packet\n");
+ }
+ if (*packet == 0)
+ {
+ error ("Got no data in the GDB packet\n");
+ }
+ /* Pick packet apart and xfer bytes to myaddr */
+ debuglogs (4, "array_read_inferior_memory: Got a \"%s\" back\n", packet);
+ for (j = 0; j < len_this_pass ; j++)
+ {
+ /* extract the byte values */
+ myaddr[count++] = from_hex (*(packet+(j*2))) * 16 + from_hex (*(packet+(j*2)+1));
+ debuglogs (5, "myaddr[%d] set to %x\n", count-1, myaddr[count-1]);
+ }
+ }
+ return (count);
+}
+
+/* FIXME-someday! merge these two. */
+static int
+array_xfer_memory (memaddr, myaddr, len, write, target)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+ int write;
+ struct target_ops *target; /* ignored */
+{
+ if (write)
+ return array_write_inferior_memory (memaddr, myaddr, len);
+ else
+ return array_read_inferior_memory (memaddr, myaddr, len);
+}
+
+static void
+array_kill (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ return; /* ignore attempts to kill target system */
+}
+
+/* Clean up when a program exits.
+ The program actually lives on in the remote processor's RAM, and may be
+ run again without a download. Don't leave it full of breakpoint
+ instructions. */
+
+static void
+array_mourn_inferior ()
+{
+ remove_breakpoints ();
+ generic_mourn_inferior (); /* Do all the proper things now */
+}
+
+#define MAX_ARRAY_BREAKPOINTS 16
+
+static CORE_ADDR breakaddr[MAX_ARRAY_BREAKPOINTS] = {0};
+
+/*
+ * array_insert_breakpoint -- add a breakpoint
+ */
+static int
+array_insert_breakpoint (addr, shadow)
+ CORE_ADDR addr;
+ char *shadow;
+{
+ int i;
+ int bp_size = 0;
+ CORE_ADDR bp_addr = addr;
+
+ debuglogs (1, "array_insert_breakpoint() addr = 0x%x", addr);
+ BREAKPOINT_FROM_PC (&bp_addr, &bp_size);
+
+ for (i = 0; i <= MAX_ARRAY_BREAKPOINTS; i++) {
+ if (breakaddr[i] == 0) {
+ breakaddr[i] = addr;
+ if (sr_get_debug() > 4)
+ printf ("Breakpoint at %x\n", addr);
+ array_read_inferior_memory (bp_addr, shadow, bp_size);
+ printf_monitor("b 0x%x\n", addr);
+ expect_prompt(1);
+ return 0;
+ }
+ }
+
+ fprintf(stderr, "Too many breakpoints (> 16) for monitor\n");
+ return 1;
+}
+
+/*
+ * _remove_breakpoint -- Tell the monitor to remove a breakpoint
+ */
+static int
+array_remove_breakpoint (addr, shadow)
+ CORE_ADDR addr;
+ char *shadow;
+{
+ int i;
+
+ debuglogs (1, "array_remove_breakpoint() addr = 0x%x", addr);
+
+ for (i = 0; i < MAX_ARRAY_BREAKPOINTS; i++) {
+ if (breakaddr[i] == addr) {
+ breakaddr[i] = 0;
+ /* some monitors remove breakpoints based on the address */
+ printf_monitor("bd %x\n", i);
+ expect_prompt(1);
+ return 0;
+ }
+ }
+ fprintf(stderr, "Can't find breakpoint associated with 0x%x\n", addr);
+ return 1;
+}
+
+static void
+array_stop ()
+{
+ debuglogs (1, "array_stop()");
+ printf_monitor("\003");
+ expect_prompt(1);
+}
+
+/*
+ * array_command -- put a command string, in args, out to MONITOR.
+ * Output from MONITOR is placed on the users terminal until the
+ * expect_prompt is seen. FIXME
+ */
+static void
+monitor_command (args, fromtty)
+ char *args;
+ int fromtty;
+{
+ debuglogs (1, "monitor_command (args=%s)", args);
+
+ if (array_desc == NULL)
+ error("monitor target not open.");
+
+ if (!args)
+ error("Missing command.");
+
+ printf_monitor ("%s\n", args);
+ expect_prompt(0);
+}
+
+/*
+ * make_gdb_packet -- make a GDB packet. The data is always ASCII.
+ * 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 '#'. If <data> starts with two characters followed by
+ * ':', then the existing stubs interpret this as a sequence number.
+ *
+ * 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.
+ *
+ */
+static void
+make_gdb_packet (buf, data)
+ char *buf, *data;
+{
+ int i;
+ unsigned char csum = 0;
+ int cnt;
+ char *p;
+
+ debuglogs (3, "make_gdb_packet(%s)\n", data);
+ cnt = strlen (data);
+ if (cnt > PBUFSIZ)
+ error ("make_gdb_packet(): to much data\n");
+
+ /* start with the packet header */
+ p = buf;
+ *p++ = '$';
+
+ /* calculate the checksum */
+ for (i = 0; i < cnt; i++) {
+ csum += data[i];
+ *p++ = data[i];
+ }
+
+ /* terminate the data with a '#' */
+ *p++ = '#';
+
+ /* add the checksum as two ascii digits */
+ *p++ = tohex ((csum >> 4) & 0xf);
+ *p++ = tohex (csum & 0xf);
+ *p = 0x0; /* Null terminator on string */
+}
+
+/*
+ * array_send_packet -- send a GDB packet to the target with error handling. We
+ * get a '+' (ACK) back if the packet is received and the checksum
+ * matches. Otherwise a '-' (NAK) is returned. It returns a 1 for a
+ * successful transmition, or a 0 for a failure.
+ */
+static int
+array_send_packet (packet)
+ char *packet;
+{
+ int c, retries, i;
+ char junk[PBUFSIZ];
+
+ retries = 0;
+
+#if 0
+ /* scan the packet to make sure it only contains valid characters.
+ this may sound silly, but sometimes a garbled packet will hang
+ the target board. We scan the whole thing, then print the error
+ message.
+ */
+ for (i = 0; i < strlen(packet); i++) {
+ debuglogs (5, "array_send_packet(): Scanning \'%c\'\n", packet[i]);
+ /* legit hex numbers or command */
+ if ((isxdigit(packet[i])) || (isalpha(packet[i])))
+ continue;
+ switch (packet[i]) {
+ case '+': /* ACK */
+ case '-': /* NAK */
+ case '#': /* end of packet */
+ case '$': /* start of packet */
+ continue;
+ default: /* bogus character */
+ retries++;
+ debuglogs (4, "array_send_packet(): Found a non-ascii digit \'%c\' in the packet.\n", packet[i]);
+ }
+ }
+#endif
+
+ if (retries > 0)
+ error ("Can't send packet, found %d non-ascii characters", retries);
+
+ /* ok, try to send the packet */
+ retries = 0;
+ while (retries++ <= 10) {
+ printf_monitor ("%s", packet);
+
+ /* read until either a timeout occurs (-2) or '+' is read */
+ while (retries <= 10) {
+ c = readchar (-timeout);
+ debuglogs (3, "Reading a GDB protocol packet... Got a '%c'\n", c);
+ switch (c) {
+ case '+':
+ debuglogs (3, "Got Ack\n");
+ return 1;
+ case SERIAL_TIMEOUT:
+ debuglogs (3, "Timed out reading serial port\n");
+ printf_monitor("@"); /* resync with the monitor */
+ expect_prompt(1); /* See if we get a expect_prompt */
+ break; /* Retransmit buffer */
+ case '-':
+ debuglogs (3, "Got NAK\n");
+ printf_monitor("@"); /* resync with the monitor */
+ expect_prompt(1); /* See if we get a expect_prompt */
+ break;
+ case '$':
+ /* it's probably an old response, or the echo of our command.
+ * just gobble up the packet and ignore it.
+ */
+ debuglogs (3, "Got a junk packet\n");
+ i = 0;
+ do {
+ c = readchar (timeout);
+ junk[i++] = c;
+ } while (c != '#');
+ c = readchar (timeout);
+ junk[i++] = c;
+ c = readchar (timeout);
+ junk[i++] = c;
+ junk[i++] = '\0';
+ debuglogs (3, "Reading a junk packet, got a \"%s\"\n", junk);
+ continue; /* Now, go look for next packet */
+ default:
+ continue;
+ }
+ retries++;
+ debuglogs (3, "Retransmitting packet \"%s\"\n", packet);
+ break; /* Here to retransmit */
+ }
+ } /* outer while */
+ return 0;
+}
+
+/*
+ * array_get_packet -- get a GDB packet from the target. Basically we read till we
+ * see a '#', then check the checksum. It returns a 1 if it's gotten a
+ * packet, or a 0 it the packet wasn't transmitted correctly.
+ */
+static int
+array_get_packet (packet)
+ char *packet;
+{
+ int c;
+ int retries;
+ unsigned char csum;
+ unsigned char pktcsum;
+ char *bp;
+
+ csum = 0;
+ bp = packet;
+
+ memset (packet, 1, PBUFSIZ);
+ retries = 0;
+ while (retries <= 10) {
+ do {
+ c = readchar (timeout);
+ if (c == SERIAL_TIMEOUT) {
+ debuglogs (3, "array_get_packet: got time out from serial port.\n");
+ }
+ debuglogs (3, "Waiting for a '$', got a %c\n", c);
+ } while (c != '$');
+
+ retries = 0;
+ while (retries <= 10) {
+ c = readchar (timeout);
+ debuglogs (3, "array_get_packet: got a '%c'\n", c);
+ switch (c) {
+ case SERIAL_TIMEOUT:
+ debuglogs (3, "Timeout in mid-packet, retrying\n");
+ return 0;
+ case '$':
+ debuglogs (3, "Saw new packet start in middle of old one\n");
+ return 0; /* Start a new packet, count retries */
+ case '#':
+ *bp = '\0';
+ pktcsum = from_hex (readchar (timeout)) << 4;
+ pktcsum |= from_hex (readchar (timeout));
+ if (csum == 0)
+ debuglogs (3, "\nGDB packet checksum zero, must be a bogus packet\n");
+ if (csum == pktcsum) {
+ debuglogs (3, "\nGDB packet checksum correct, packet data is \"%s\",\n", packet);
+ printf_monitor ("@");
+ expect_prompt (1);
+ return 1;
+ }
+ debuglogs (3, "Bad checksum, sentsum=0x%x, csum=0x%x\n", pktcsum, csum);
+ return 0;
+ case '*': /* Run length encoding */
+ debuglogs (5, "Run length encoding in packet\n");
+ csum += c;
+ c = readchar (timeout);
+ csum += c;
+ c = c - ' ' + 3; /* Compute repeat count */
+
+ if (c > 0 && c < 255 && bp + c - 1 < packet + PBUFSIZ - 1) {
+ memset (bp, *(bp - 1), c);
+ bp += c;
+ continue;
+ }
+ *bp = '\0';
+ printf_filtered ("Repeat count %d too large for buffer.\n", c);
+ return 0;
+
+ default:
+ if ((!isxdigit(c)) && (!ispunct(c)))
+ debuglogs (4, "Got a non-ascii digit \'%c\'.\\n", c);
+ if (bp < packet + PBUFSIZ - 1) {
+ *bp++ = c;
+ csum += c;
+ continue;
+ }
+
+ *bp = '\0';
+ puts_filtered ("Remote packet too long.\n");
+ return 0;
+ }
+ }
+ }
+ return 0; /* exceeded retries */
+}
+
+/*
+ * ascii2hexword -- convert an ascii number represented by 8 digits to a hex value.
+ */
+static unsigned long
+ascii2hexword (mem)
+ unsigned char *mem;
+{
+ unsigned long val;
+ int i;
+ char buf[9];
+
+ val = 0;
+ for (i = 0; i < 8; i++) {
+ val <<= 4;
+ if (mem[i] >= 'A' && mem[i] <= 'F')
+ val = val + mem[i] - 'A' + 10;
+ if (mem[i] >= 'a' && mem[i] <= 'f')
+ val = val + mem[i] - 'a' + 10;
+ if (mem[i] >= '0' && mem[i] <= '9')
+ val = val + mem[i] - '0';
+ buf[i] = mem[i];
+ }
+ buf[8] = '\0';
+ debuglogs (4, "ascii2hexword() got a 0x%x from %s(%x).\n", val, buf, mem);
+ return val;
+}
+
+/*
+ * ascii2hexword -- convert a hex value to an ascii number represented by 8
+ * digits.
+ */
+static void
+hexword2ascii (mem, num)
+ unsigned char *mem;
+ unsigned long num;
+{
+ int i;
+ unsigned char ch;
+
+ debuglogs (4, "hexword2ascii() converting %x ", num);
+ for (i = 7; i >= 0; i--) {
+ mem[i] = tohex ((num >> 4) & 0xf);
+ mem[i] = tohex (num & 0xf);
+ num = num >> 4;
+ }
+ mem[8] = '\0';
+ debuglogs (4, "\tto a %s", mem);
+}
+
+/* Convert hex digit A to a number. */
+static int
+from_hex (a)
+ int a;
+{
+ if (a == 0)
+ return 0;
+
+ debuglogs (4, "from_hex got a 0x%x(%c)\n",a,a);
+ if (a >= '0' && a <= '9')
+ return a - '0';
+ if (a >= 'a' && a <= 'f')
+ return a - 'a' + 10;
+ if (a >= 'A' && a <= 'F')
+ return a - 'A' + 10;
+ else {
+ error ("Reply contains invalid hex digit 0x%x", a);
+ }
+}
+
+/* Convert number NIB to a hex digit. */
+static int
+tohex (nib)
+ int nib;
+{
+ if (nib < 10)
+ return '0'+nib;
+ else
+ return 'a'+nib-10;
+}
+
+/*
+ * _initialize_remote_monitors -- setup a few addtitional commands that
+ * are usually only used by monitors.
+ */
+void
+_initialize_remote_monitors ()
+{
+ /* generic monitor command */
+ add_com ("monitor", class_obscure, monitor_command,
+ "Send a command to the debug monitor.");
+
+}
+
+/*
+ * _initialize_array -- do any special init stuff for the target.
+ */
+void
+_initialize_array ()
+{
+ init_array_ops() ;
+ add_target (&array_ops);
+}
diff --git a/gdb/remote-bug.c b/gdb/remote-bug.c
new file mode 100644
index 00000000000..2efd710a6b5
--- /dev/null
+++ b/gdb/remote-bug.c
@@ -0,0 +1,1099 @@
+/* Remote debugging interface for Motorola's MVME187BUG monitor, an embedded
+ monitor for the m88k.
+
+ Copyright 1992, 1993 Free Software Foundation, Inc.
+ Contributed by Cygnus Support. Written by K. Richard Pixley.
+
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "inferior.h"
+#include "wait.h"
+
+#include "gdb_string.h"
+#include <ctype.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <setjmp.h>
+#include <errno.h>
+
+#include "terminal.h"
+#include "gdbcore.h"
+#include "gdbcmd.h"
+
+#include "remote-utils.h"
+
+
+extern int sleep();
+
+/* External data declarations */
+extern int stop_soon_quietly; /* for wait_for_inferior */
+
+/* Forward data declarations */
+extern struct target_ops bug_ops; /* Forward declaration */
+
+/* Forward function declarations */
+static int bug_clear_breakpoints PARAMS((void));
+
+static int bug_read_memory PARAMS((CORE_ADDR memaddr,
+ unsigned char *myaddr,
+ int len));
+
+static int bug_write_memory PARAMS((CORE_ADDR memaddr,
+ unsigned char *myaddr,
+ int len));
+
+/* This variable is somewhat arbitrary. It's here so that it can be
+ set from within a running gdb. */
+
+static int srec_max_retries = 3;
+
+/* Each S-record download to the target consists of an S0 header
+ record, some number of S3 data records, and one S7 termination
+ record. I call this download a "frame". Srec_frame says how many
+ bytes will be represented in each frame. */
+
+#define SREC_SIZE 160
+static int srec_frame = SREC_SIZE;
+
+/* This variable determines how many bytes will be represented in each
+ S3 s-record. */
+
+static int srec_bytes = 40;
+
+/* At one point it appeared to me as though the bug monitor could not
+ really be expected to receive two sequential characters at 9600
+ baud reliably. Echo-pacing is an attempt to force data across the
+ line even in this condition. Specifically, in echo-pace mode, each
+ character is sent one at a time and we look for the echo before
+ sending the next. This is excruciatingly slow. */
+
+static int srec_echo_pace = 0;
+
+/* How long to wait after an srec for a possible error message.
+ Similar to the above, I tried sleeping after sending each S3 record
+ in hopes that I might actually see error messages from the bug
+ monitor. This might actually work if we were to use sleep
+ intervals smaller than 1 second. */
+
+static int srec_sleep = 0;
+
+/* Every srec_noise records, flub the checksum. This is a debugging
+ feature. Set the variable to something other than 1 in order to
+ inject *deliberate* checksum errors. One might do this if one
+ wanted to test error handling and recovery. */
+
+static int srec_noise = 0;
+
+/* Called when SIGALRM signal sent due to alarm() timeout. */
+
+/* Number of SIGTRAPs we need to simulate. That is, the next
+ NEED_ARTIFICIAL_TRAP calls to bug_wait should just return
+ SIGTRAP without actually waiting for anything. */
+
+static int need_artificial_trap = 0;
+
+/*
+ * Download a file specified in 'args', to the bug.
+ */
+
+static void
+bug_load (args, fromtty)
+ char *args;
+ int fromtty;
+{
+ bfd *abfd;
+ asection *s;
+ char buffer[1024];
+
+ sr_check_open ();
+
+ dcache_flush (gr_get_dcache());
+ inferior_pid = 0;
+ abfd = bfd_openr (args, 0);
+ if (!abfd)
+ {
+ printf_filtered ("Unable to open file %s\n", args);
+ return;
+ }
+
+ if (bfd_check_format (abfd, bfd_object) == 0)
+ {
+ printf_filtered ("File is not an object file\n");
+ return;
+ }
+
+ s = abfd->sections;
+ while (s != (asection *) NULL)
+ {
+ srec_frame = SREC_SIZE;
+ if (s->flags & SEC_LOAD)
+ {
+ int i;
+
+ char *buffer = xmalloc (srec_frame);
+
+ printf_filtered ("%s\t: 0x%4x .. 0x%4x ", s->name, s->vma, s->vma + s->_raw_size);
+ gdb_flush (gdb_stdout);
+ for (i = 0; i < s->_raw_size; i += srec_frame)
+ {
+ if (srec_frame > s->_raw_size - i)
+ srec_frame = s->_raw_size - i;
+
+ bfd_get_section_contents (abfd, s, buffer, i, srec_frame);
+ bug_write_memory (s->vma + i, buffer, srec_frame);
+ printf_filtered ("*");
+ gdb_flush (gdb_stdout);
+ }
+ printf_filtered ("\n");
+ free (buffer);
+ }
+ s = s->next;
+ }
+ sprintf (buffer, "rs ip %lx", (unsigned long) abfd->start_address);
+ sr_write_cr (buffer);
+ gr_expect_prompt ();
+}
+
+#if 0
+static char *
+get_word (p)
+ char **p;
+{
+ char *s = *p;
+ char *word;
+ char *copy;
+ size_t len;
+
+ while (isspace (*s))
+ s++;
+
+ word = s;
+
+ len = 0;
+
+ while (*s && !isspace (*s))
+ {
+ s++;
+ len++;
+
+ }
+ copy = xmalloc (len + 1);
+ memcpy (copy, word, len);
+ copy[len] = 0;
+ *p = s;
+ return copy;
+}
+#endif
+
+static struct gr_settings bug_settings = {
+ NULL, /* dcache */
+ "Bug>", /* prompt */
+ &bug_ops, /* ops */
+ bug_clear_breakpoints, /* clear_all_breakpoints */
+ bug_read_memory, /* readfunc */
+ bug_write_memory, /* writefunc */
+ gr_generic_checkin, /* checkin */
+};
+
+static char *cpu_check_strings[] = {
+ "=",
+ "Invalid Register",
+};
+
+static void
+bug_open (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ if (args == NULL)
+ args = "";
+
+ gr_open(args, from_tty, &bug_settings);
+ /* decide *now* whether we are on an 88100 or an 88110 */
+ sr_write_cr("rs cr06");
+ sr_expect("rs cr06");
+
+ switch (gr_multi_scan(cpu_check_strings, 0))
+ {
+ case 0: /* this is an m88100 */
+ target_is_m88110 = 0;
+ break;
+ case 1: /* this is an m88110 */
+ target_is_m88110 = 1;
+ break;
+ default:
+ abort();
+ }
+}
+
+/* Tell the remote machine to resume. */
+
+void
+bug_resume (pid, step, sig)
+ int pid, step;
+ enum target_signal sig;
+{
+ dcache_flush (gr_get_dcache());
+
+ if (step)
+ {
+ sr_write_cr("t");
+
+ /* Force the next bug_wait to return a trap. Not doing anything
+ about I/O from the target means that the user has to type
+ "continue" to see any. FIXME, this should be fixed. */
+ need_artificial_trap = 1;
+ }
+ else
+ sr_write_cr ("g");
+
+ return;
+}
+
+/* Wait until the remote machine stops, then return,
+ storing status in STATUS just as `wait' would. */
+
+static char *wait_strings[] = {
+ "At Breakpoint",
+ "Exception: Data Access Fault (Local Bus Timeout)",
+ "\r8??\?-Bug>", /* The '\?' avoids creating a trigraph */
+ "\r197-Bug>",
+ NULL,
+};
+
+int
+bug_wait (pid, status)
+ int pid;
+ struct target_waitstatus *status;
+{
+ int old_timeout = sr_get_timeout();
+ int old_immediate_quit = immediate_quit;
+
+ status->kind = TARGET_WAITKIND_EXITED;
+ status->value.integer = 0;
+
+ /* read off leftovers from resume so that the rest can be passed
+ back out as stdout. */
+ if (need_artificial_trap == 0)
+ {
+ sr_expect("Effective address: ");
+ (void) sr_get_hex_word();
+ sr_expect ("\r\n");
+ }
+
+ sr_set_timeout(-1); /* Don't time out -- user program is running. */
+ immediate_quit = 1; /* Helps ability to QUIT */
+
+ switch (gr_multi_scan(wait_strings, need_artificial_trap == 0))
+ {
+ case 0: /* breakpoint case */
+ status->kind = TARGET_WAITKIND_STOPPED;
+ status->value.sig = TARGET_SIGNAL_TRAP;
+ /* user output from the target can be discarded here. (?) */
+ gr_expect_prompt();
+ break;
+
+ case 1: /* bus error */
+ status->kind = TARGET_WAITKIND_STOPPED;
+ status->value.sig = TARGET_SIGNAL_BUS;
+ /* user output from the target can be discarded here. (?) */
+ gr_expect_prompt();
+ break;
+
+ case 2: /* normal case */
+ case 3:
+ if (need_artificial_trap != 0)
+ {
+ /* stepping */
+ status->kind = TARGET_WAITKIND_STOPPED;
+ status->value.sig = TARGET_SIGNAL_TRAP;
+ need_artificial_trap--;
+ break;
+ }
+ else
+ {
+ /* exit case */
+ status->kind = TARGET_WAITKIND_EXITED;
+ status->value.integer = 0;
+ break;
+ }
+
+ case -1: /* trouble */
+ default:
+ fprintf_filtered (gdb_stderr,
+ "Trouble reading target during wait\n");
+ break;
+ }
+
+ sr_set_timeout(old_timeout);
+ immediate_quit = old_immediate_quit;
+ return 0;
+}
+
+/* Return the name of register number REGNO
+ in the form input and output by bug.
+
+ Returns a pointer to a static buffer containing the answer. */
+static char *
+get_reg_name (regno)
+ int regno;
+{
+ static char *rn[] = {
+ "r00", "r01", "r02", "r03", "r04", "r05", "r06", "r07",
+ "r08", "r09", "r10", "r11", "r12", "r13", "r14", "r15",
+ "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
+ "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
+
+ /* these get confusing because we omit a few and switch some ordering around. */
+
+ "cr01", /* 32 = psr */
+ "fcr62", /* 33 = fpsr*/
+ "fcr63", /* 34 = fpcr */
+ "ip", /* this is something of a cheat. */
+ /* 35 = sxip */
+ "cr05", /* 36 = snip */
+ "cr06", /* 37 = sfip */
+
+ "x00", "x01", "x02", "x03", "x04", "x05", "x06", "x07",
+ "x08", "x09", "x10", "x11", "x12", "x13", "x14", "x15",
+ "x16", "x17", "x18", "x19", "x20", "x21", "x22", "x23",
+ "x24", "x25", "x26", "x27", "x28", "x29", "x30", "x31",
+ };
+
+ return rn[regno];
+}
+
+#if 0 /* not currently used */
+/* Read from remote while the input matches STRING. Return zero on
+ success, -1 on failure. */
+
+static int
+bug_scan (s)
+ char *s;
+{
+ int c;
+
+ while (*s)
+ {
+ c = sr_readchar();
+ if (c != *s++)
+ {
+ fflush(stdout);
+ printf("\nNext character is '%c' - %d and s is \"%s\".\n", c, c, --s);
+ return(-1);
+ }
+ }
+
+ return(0);
+}
+#endif /* never */
+
+static int
+bug_srec_write_cr (s)
+ char *s;
+{
+ char *p = s;
+
+ if (srec_echo_pace)
+ for (p = s; *p; ++p)
+ {
+ if (sr_get_debug() > 0)
+ printf ("%c", *p);
+
+ do
+ SERIAL_WRITE(sr_get_desc(), p, 1);
+ while (sr_pollchar() != *p);
+ }
+ else
+ {
+ sr_write_cr (s);
+/* return(bug_scan (s) || bug_scan ("\n")); */
+ }
+
+ return(0);
+}
+
+/* Store register REGNO, or all if REGNO == -1. */
+
+static void
+bug_fetch_register(regno)
+ int regno;
+{
+ sr_check_open();
+
+ if (regno == -1)
+ {
+ int i;
+
+ for (i = 0; i < NUM_REGS; ++i)
+ bug_fetch_register(i);
+ }
+ else if (target_is_m88110 && regno == SFIP_REGNUM)
+ {
+ /* m88110 has no sfip. */
+ long l = 0;
+ supply_register(regno, (char *) &l);
+ }
+ else if (regno < XFP_REGNUM)
+ {
+ char buffer[MAX_REGISTER_RAW_SIZE];
+
+ sr_write ("rs ", 3);
+ sr_write_cr (get_reg_name(regno));
+ sr_expect ("=");
+ store_unsigned_integer (buffer, REGISTER_RAW_SIZE (regno),
+ sr_get_hex_word());
+ gr_expect_prompt ();
+ supply_register (regno, buffer);
+ }
+ else
+ {
+ /* Float register so we need to parse a strange data format. */
+ long p;
+ unsigned char fpreg_buf[10];
+
+ sr_write("rs ", 3);
+ sr_write(get_reg_name(regno), strlen(get_reg_name(regno)));
+ sr_write_cr(";d");
+ sr_expect("rs");
+ sr_expect(get_reg_name(regno));
+ sr_expect(";d");
+ sr_expect("=");
+
+ /* sign */
+ p = sr_get_hex_digit(1);
+ fpreg_buf[0] = p << 7;
+
+ /* exponent */
+ sr_expect("_");
+ p = sr_get_hex_digit(1);
+ fpreg_buf[0] += (p << 4);
+ fpreg_buf[0] += sr_get_hex_digit(1);
+
+ fpreg_buf[1] = sr_get_hex_digit(1) << 4;
+
+ /* fraction */
+ sr_expect("_");
+ fpreg_buf[1] += sr_get_hex_digit(1);
+
+ fpreg_buf[2] = (sr_get_hex_digit(1) << 4) + sr_get_hex_digit(1);
+ fpreg_buf[3] = (sr_get_hex_digit(1) << 4) + sr_get_hex_digit(1);
+ fpreg_buf[4] = (sr_get_hex_digit(1) << 4) + sr_get_hex_digit(1);
+ fpreg_buf[5] = (sr_get_hex_digit(1) << 4) + sr_get_hex_digit(1);
+ fpreg_buf[6] = (sr_get_hex_digit(1) << 4) + sr_get_hex_digit(1);
+ fpreg_buf[7] = (sr_get_hex_digit(1) << 4) + sr_get_hex_digit(1);
+ fpreg_buf[8] = 0;
+ fpreg_buf[9] = 0;
+
+ gr_expect_prompt();
+ supply_register(regno, fpreg_buf);
+ }
+
+ return;
+}
+
+/* Store register REGNO, or all if REGNO == -1. */
+
+static void
+bug_store_register (regno)
+ int regno;
+{
+ char buffer[1024];
+ sr_check_open();
+
+ if (regno == -1)
+ {
+ int i;
+
+ for (i = 0; i < NUM_REGS; ++i)
+ bug_store_register(i);
+ }
+ else
+ {
+ char *regname;
+
+ regname = get_reg_name(regno);
+
+ if (target_is_m88110 && regno == SFIP_REGNUM)
+ return;
+ else if (regno < XFP_REGNUM)
+ sprintf(buffer, "rs %s %08x",
+ regname,
+ read_register(regno));
+ else
+ {
+ unsigned char *fpreg_buf =
+ (unsigned char *)&registers[REGISTER_BYTE(regno)];
+
+ sprintf(buffer, "rs %s %1x_%02x%1x_%1x%02x%02x%02x%02x%02x%02x;d",
+ regname,
+ /* sign */
+ (fpreg_buf[0] >> 7) & 0xf,
+ /* exponent */
+ fpreg_buf[0] & 0x7f,
+ (fpreg_buf[1] >> 8) & 0xf,
+ /* fraction */
+ fpreg_buf[1] & 0xf,
+ fpreg_buf[2],
+ fpreg_buf[3],
+ fpreg_buf[4],
+ fpreg_buf[5],
+ fpreg_buf[6],
+ fpreg_buf[7]);
+ }
+
+ sr_write_cr(buffer);
+ gr_expect_prompt();
+ }
+
+ return;
+}
+
+int
+bug_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;
+
+ /* Round ending address up; get number of longwords that makes. */
+ register int count;
+
+ /* Allocate buffer of that many longwords. */
+ register int *buffer;
+
+ addr = memaddr & -sizeof (int);
+ count = (((memaddr + len) - addr) + sizeof (int) - 1) / sizeof (int);
+
+ buffer = (int *) alloca (count * sizeof (int));
+
+ if (write)
+ {
+ /* Fill start and end extra bytes of buffer with existing memory data. */
+
+ if (addr != memaddr || len < (int) sizeof (int))
+ {
+ /* Need part of initial word -- fetch it. */
+ buffer[0] = gr_fetch_word (addr);
+ }
+
+ if (count > 1) /* FIXME, avoid if even boundary */
+ {
+ buffer[count - 1]
+ = gr_fetch_word (addr + (count - 1) * sizeof (int));
+ }
+
+ /* Copy data to be written over corresponding part of buffer */
+
+ memcpy ((char *) buffer + (memaddr & (sizeof (int) - 1)), myaddr, len);
+
+ /* Write the entire buffer. */
+
+ for (i = 0; i < count; i++, addr += sizeof (int))
+ {
+ errno = 0;
+ gr_store_word (addr, buffer[i]);
+ if (errno)
+ {
+
+ return 0;
+ }
+
+ }
+ }
+ else
+ {
+ /* Read all the longwords */
+ for (i = 0; i < count; i++, addr += sizeof (int))
+ {
+ errno = 0;
+ buffer[i] = gr_fetch_word (addr);
+ if (errno)
+ {
+ return 0;
+ }
+ QUIT;
+ }
+
+ /* Copy appropriate bytes out of the buffer. */
+ memcpy (myaddr, (char *) buffer + (memaddr & (sizeof (int) - 1)), len);
+ }
+
+ return len;
+}
+
+static void
+start_load()
+{
+ char *command;
+
+ command = (srec_echo_pace ? "lo 0 ;x" : "lo 0");
+
+ sr_write_cr (command);
+ sr_expect (command);
+ sr_expect ("\r\n");
+ bug_srec_write_cr ("S0030000FC");
+ return;
+}
+
+/* This is an extremely vulnerable and fragile function. I've made
+ considerable attempts to make this deterministic, but I've
+ certainly forgotten something. The trouble is that S-records are
+ only a partial file format, not a protocol. Worse, apparently the
+ m88k bug monitor does not run in real time while receiving
+ S-records. Hence, we must pay excruciating attention to when and
+ where error messages are returned, and what has actually been sent.
+
+ Each call represents a chunk of memory to be sent to the target.
+ We break that chunk into an S0 header record, some number of S3
+ data records each containing srec_bytes, and an S7 termination
+ record. */
+
+static char *srecord_strings[] = {
+ "S-RECORD",
+ "-Bug>",
+ NULL,
+};
+
+static int
+bug_write_memory (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ unsigned char *myaddr;
+ int len;
+{
+ int done;
+ int checksum;
+ int x;
+ int retries;
+ char *buffer = alloca ((srec_bytes + 8) << 1);
+
+ retries = 0;
+
+ do
+ {
+ done = 0;
+
+ if (retries > srec_max_retries)
+ return(-1);
+
+ if (retries > 0)
+ {
+ if (sr_get_debug() > 0)
+ printf("\n<retrying...>\n");
+
+ /* This gr_expect_prompt call is extremely important. Without
+ it, we will tend to resend our packet so fast that it
+ will arrive before the bug monitor is ready to receive
+ it. This would lead to a very ugly resend loop. */
+
+ gr_expect_prompt();
+ }
+
+ start_load();
+
+ while (done < len)
+ {
+ int thisgo;
+ int idx;
+ char *buf = buffer;
+ CORE_ADDR address;
+
+ checksum = 0;
+ thisgo = len - done;
+ if (thisgo > srec_bytes)
+ thisgo = srec_bytes;
+
+ address = memaddr + done;
+ sprintf (buf, "S3%02X%08X", thisgo + 4 + 1, address);
+ buf += 12;
+
+ checksum += (thisgo + 4 + 1
+ + (address & 0xff)
+ + ((address >> 8) & 0xff)
+ + ((address >> 16) & 0xff)
+ + ((address >> 24) & 0xff));
+
+ for (idx = 0; idx < thisgo; idx++)
+ {
+ sprintf (buf, "%02X", myaddr[idx + done]);
+ checksum += myaddr[idx + done];
+ buf += 2;
+ }
+
+ if (srec_noise > 0)
+ {
+ /* FIXME-NOW: insert a deliberate error every now and then.
+ This is intended for testing/debugging the error handling
+ stuff. */
+ static int counter = 0;
+ if (++counter > srec_noise)
+ {
+ counter = 0;
+ ++checksum;
+ }
+ }
+
+ sprintf(buf, "%02X", ~checksum & 0xff);
+ bug_srec_write_cr (buffer);
+
+ if (srec_sleep != 0)
+ sleep(srec_sleep);
+
+ /* This pollchar is probably redundant to the gr_multi_scan
+ below. Trouble is, we can't be sure when or where an
+ error message will appear. Apparently, when running at
+ full speed from a typical sun4, error messages tend to
+ appear to arrive only *after* the s7 record. */
+
+ if ((x = sr_pollchar()) != 0)
+ {
+ if (sr_get_debug() > 0)
+ printf("\n<retrying...>\n");
+
+ ++retries;
+
+ /* flush any remaining input and verify that we are back
+ at the prompt level. */
+ gr_expect_prompt();
+ /* start all over again. */
+ start_load();
+ done = 0;
+ continue;
+ }
+
+ done += thisgo;
+ }
+
+ bug_srec_write_cr("S7060000000000F9");
+ ++retries;
+
+ /* Having finished the load, we need to figure out whether we
+ had any errors. */
+ } while (gr_multi_scan(srecord_strings, 0) == 0);;
+
+ return(0);
+}
+
+/* Copy LEN bytes of data from debugger memory at MYADDR
+ to inferior's memory at MEMADDR. Returns errno value.
+ * sb/sh instructions don't work on unaligned addresses, when TU=1.
+ */
+
+/* Read LEN bytes from inferior memory at MEMADDR. Put the result
+ at debugger address MYADDR. Returns errno value. */
+static int
+bug_read_memory (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ unsigned char *myaddr;
+ int len;
+{
+ char request[100];
+ char *buffer;
+ char *p;
+ char type;
+ char size;
+ unsigned char c;
+ unsigned int inaddr;
+ unsigned int checksum;
+
+ sprintf(request, "du 0 %x:&%d", memaddr, len);
+ sr_write_cr(request);
+
+ p = buffer = alloca(len);
+
+ /* scan up through the header */
+ sr_expect("S0030000FC");
+
+ while (p < buffer + len)
+ {
+ /* scan off any white space. */
+ while (sr_readchar() != 'S') ;;
+
+ /* what kind of s-rec? */
+ type = sr_readchar();
+
+ /* scan record size */
+ sr_get_hex_byte(&size);
+ checksum = size;
+ --size;
+ inaddr = 0;
+
+ switch (type)
+ {
+ case '7':
+ case '8':
+ case '9':
+ goto done;
+
+ case '3':
+ sr_get_hex_byte(&c);
+ inaddr = (inaddr << 8) + c;
+ checksum += c;
+ --size;
+ /* intentional fall through */
+ case '2':
+ sr_get_hex_byte(&c);
+ inaddr = (inaddr << 8) + c;
+ checksum += c;
+ --size;
+ /* intentional fall through */
+ case '1':
+ sr_get_hex_byte(&c);
+ inaddr = (inaddr << 8) + c;
+ checksum += c;
+ --size;
+ sr_get_hex_byte(&c);
+ inaddr = (inaddr << 8) + c;
+ checksum += c;
+ --size;
+ break;
+
+ default:
+ /* bonk */
+ error("reading s-records.");
+ }
+
+ if (inaddr < memaddr
+ || (memaddr + len) < (inaddr + size))
+ error("srec out of memory range.");
+
+ if (p != buffer + inaddr - memaddr)
+ error("srec out of sequence.");
+
+ for (; size; --size, ++p)
+ {
+ sr_get_hex_byte(p);
+ checksum += *p;
+ }
+
+ sr_get_hex_byte(&c);
+ if (c != (~checksum & 0xff))
+ error("bad s-rec checksum");
+ }
+
+ done:
+ gr_expect_prompt();
+ if (p != buffer + len)
+ return(1);
+
+ memcpy(myaddr, buffer, len);
+ return(0);
+}
+
+#define MAX_BREAKS 16
+static int num_brkpts = 0;
+static int
+bug_insert_breakpoint (addr, save)
+ CORE_ADDR addr;
+ char *save; /* Throw away, let bug save instructions */
+{
+ sr_check_open ();
+
+ if (num_brkpts < MAX_BREAKS)
+ {
+ char buffer[100];
+
+ num_brkpts++;
+ sprintf (buffer, "br %x", addr);
+ sr_write_cr (buffer);
+ gr_expect_prompt ();
+ return(0);
+ }
+ else
+ {
+ fprintf_filtered (gdb_stderr,
+ "Too many break points, break point not installed\n");
+ return(1);
+ }
+
+}
+static int
+bug_remove_breakpoint (addr, save)
+ CORE_ADDR addr;
+ char *save; /* Throw away, let bug save instructions */
+{
+ if (num_brkpts > 0)
+ {
+ char buffer[100];
+
+ num_brkpts--;
+ sprintf (buffer, "nobr %x", addr);
+ sr_write_cr (buffer);
+ gr_expect_prompt ();
+
+ }
+ return (0);
+}
+
+/* Clear the bugs notion of what the break points are */
+static int
+bug_clear_breakpoints ()
+{
+
+ if (sr_is_open())
+ {
+ sr_write_cr ("nobr");
+ sr_expect("nobr");
+ gr_expect_prompt ();
+ }
+ num_brkpts = 0;
+ return(0);
+}
+
+struct target_ops bug_ops ;
+
+static void
+init_bug_ops(void)
+{
+ bug_ops.to_shortname = "bug"; "Remote BUG monitor",
+ bug_ops.to_longname = "Use the mvme187 board running the BUG monitor connected by a serial line.";
+ bug_ops.to_doc = " ";
+ bug_ops.to_open = bug_open;
+ bug_ops.to_close = gr_close;
+ bug_ops.to_attach = 0;
+ bug_ops.to_post_attach = NULL;
+ bug_ops.to_require_attach = NULL;
+ bug_ops.to_detach = gr_detach;
+ bug_ops.to_require_detach = NULL;
+ bug_ops.to_resume = bug_resume;
+ bug_ops.to_wait = bug_wait;
+ bug_ops.to_post_wait = NULL;
+ bug_ops.to_fetch_registers = bug_fetch_register;
+ bug_ops.to_store_registers = bug_store_register;
+ bug_ops.to_prepare_to_store = gr_prepare_to_store;
+ bug_ops.to_xfer_memory = bug_xfer_memory;
+ bug_ops.to_files_info = gr_files_info;
+ bug_ops.to_insert_breakpoint = bug_insert_breakpoint;
+ bug_ops.to_remove_breakpoint = bug_remove_breakpoint;
+ bug_ops.to_terminal_init = 0;
+ bug_ops.to_terminal_inferior = 0;
+ bug_ops.to_terminal_ours_for_output = 0;
+ bug_ops.to_terminal_ours = 0;
+ bug_ops.to_terminal_info = 0;
+ bug_ops.to_kill = gr_kill;
+ bug_ops.to_load = bug_load;
+ bug_ops.to_lookup_symbol = 0;
+ bug_ops.to_create_inferior = gr_create_inferior;
+ bug_ops.to_post_startup_inferior = NULL;
+ bug_ops.to_acknowledge_created_inferior = NULL;
+ bug_ops.to_clone_and_follow_inferior = NULL;
+ bug_ops.to_post_follow_inferior_by_clone = NULL;
+ bug_ops.to_insert_fork_catchpoint = NULL;
+ bug_ops.to_remove_fork_catchpoint = NULL;
+ bug_ops.to_insert_vfork_catchpoint = NULL;
+ bug_ops.to_remove_vfork_catchpoint = NULL;
+ bug_ops.to_has_forked = NULL;
+ bug_ops.to_has_vforked = NULL;
+ bug_ops.to_can_follow_vfork_prior_to_exec = NULL;
+ bug_ops.to_post_follow_vfork = NULL;
+ bug_ops.to_insert_exec_catchpoint = NULL;
+ bug_ops.to_remove_exec_catchpoint = NULL;
+ bug_ops.to_has_execd = NULL;
+ bug_ops.to_reported_exec_events_per_exec_call = NULL;
+ bug_ops.to_has_exited = NULL;
+ bug_ops.to_mourn_inferior = gr_mourn;
+ bug_ops.to_can_run = 0;
+ bug_ops.to_notice_signals = 0;
+ bug_ops.to_thread_alive = 0 ;
+ bug_ops.to_stop = 0;
+ bug_ops.to_pid_to_exec_file = NULL;
+ bug_ops.to_core_file_to_sym_file = NULL;
+ bug_ops.to_stratum = process_stratum ;
+ bug_ops.DONT_USE = 0;
+ bug_ops.to_has_all_memory = 1;
+ bug_ops.to_has_memory = 1;
+ bug_ops.to_has_stack = 1;
+ bug_ops.to_has_registers = 0;
+ bug_ops.to_has_execution = 0;
+ bug_ops.to_sections = 0 ;
+ bug_ops.to_sections_end = 0 ;
+ bug_ops.to_magic = OPS_MAGIC; /* Always the last thing */
+} /* init_bug_ops */
+
+void
+_initialize_remote_bug ()
+{
+ init_bug_ops() ;
+ add_target (&bug_ops);
+
+ add_show_from_set
+ (add_set_cmd ("srec-bytes", class_support, var_uinteger,
+ (char *) &srec_bytes,
+ "\
+Set the number of bytes represented in each S-record.\n\
+This affects the communication protocol with the remote target.",
+ &setlist),
+ &showlist);
+
+ add_show_from_set
+ (add_set_cmd ("srec-max-retries", class_support, var_uinteger,
+ (char *) &srec_max_retries,
+ "\
+Set the number of retries for shipping S-records.\n\
+This affects the communication protocol with the remote target.",
+ &setlist),
+ &showlist);
+
+#if 0
+ /* This needs to set SREC_SIZE, not srec_frame which gets changed at the
+ end of a download. But do we need the option at all? */
+ add_show_from_set
+ (add_set_cmd ("srec-frame", class_support, var_uinteger,
+ (char *) &srec_frame,
+ "\
+Set the number of bytes in an S-record frame.\n\
+This affects the communication protocol with the remote target.",
+ &setlist),
+ &showlist);
+#endif /* 0 */
+
+ add_show_from_set
+ (add_set_cmd ("srec-noise", class_support, var_zinteger,
+ (char *) &srec_noise,
+ "\
+Set number of S-record to send before deliberately flubbing a checksum.\n\
+Zero means flub none at all. This affects the communication protocol\n\
+with the remote target.",
+ &setlist),
+ &showlist);
+
+ add_show_from_set
+ (add_set_cmd ("srec-sleep", class_support, var_zinteger,
+ (char *) &srec_sleep,
+ "\
+Set number of seconds to sleep after an S-record for a possible error message to arrive.\n\
+This affects the communication protocol with the remote target.",
+ &setlist),
+ &showlist);
+
+ add_show_from_set
+ (add_set_cmd ("srec-echo-pace", class_support, var_boolean,
+ (char *) &srec_echo_pace,
+ "\
+Set echo-verification.\n\
+When on, use verification by echo when downloading S-records. This is\n\
+much slower, but generally more reliable.",
+ &setlist),
+ &showlist);
+}
diff --git a/gdb/remote-d10v.c b/gdb/remote-d10v.c
new file mode 100644
index 00000000000..d529b2180f6
--- /dev/null
+++ b/gdb/remote-d10v.c
@@ -0,0 +1,228 @@
+/* Remote target communications for d10v connected via a serial line.
+ Copyright 1988, 1991, 1992, 1993, 1994, 1995, 1996, 1997 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "gdb_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 "gdbthread.h"
+
+#include "dcache.h"
+
+#ifdef USG
+#include <sys/types.h>
+#endif
+
+#include <signal.h>
+#include "serial.h"
+
+/* Prototypes for local functions */
+
+static void remote_d10v_open PARAMS ((char *name, int from_tty));
+
+/* Define the target subroutine names */
+static struct target_ops remote_d10v_ops;
+
+/* Open a connection to a remote debugger.
+ NAME is the filename used for communication. */
+
+static void
+remote_d10v_open (name, from_tty)
+ char *name;
+ int from_tty;
+{
+ pop_target ();
+ push_remote_target (name, from_tty);
+}
+
+
+/* Translate a GDB virtual ADDR/LEN into a format the remote target
+ understands. Returns number of bytes that can be transfered
+ starting at taddr, ZERO if no bytes can be transfered. */
+int
+remote_d10v_translate_xfer_address (memaddr, nr_bytes, taddr)
+ CORE_ADDR memaddr;
+ int nr_bytes;
+ CORE_ADDR *taddr;
+{
+ CORE_ADDR phys;
+ CORE_ADDR seg;
+ CORE_ADDR off;
+ char *from = "unknown";
+ char *to = "unknown";
+ unsigned short imap0 = read_register (IMAP0_REGNUM);
+ unsigned short imap1 = read_register (IMAP1_REGNUM);
+ unsigned short dmap = read_register (DMAP_REGNUM);
+
+ /* GDB interprets addresses as:
+
+ 0x00xxxxxx: Logical data address segment (DMAP translated memory)
+ 0x01xxxxxx: Logical instruction address segment (IMAP translated memory)
+ 0x10xxxxxx: Physical data memory segment (On-chip data memory)
+ 0x11xxxxxx: Physical instruction memory segment (On-chip insn memory)
+ 0x12xxxxxx: Phisical unified memory segment (Unified memory)
+
+ The remote d10v board interprets addresses as:
+
+ 0x00xxxxxx: Phisical unified memory segment (Unified memory)
+ 0x01xxxxxx: Physical instruction memory segment (On-chip insn memory)
+ 0x02xxxxxx: Physical data memory segment (On-chip data memory)
+
+ Translate according to current IMAP/dmap registers */
+
+ enum {
+ targ_unified = 0x00000000,
+ targ_insn = 0x01000000,
+ targ_data = 0x02000000,
+ };
+
+ seg = (memaddr >> 24);
+ off = (memaddr & 0xffffffL);
+
+ switch (seg)
+ {
+ case 0x00: /* in logical data address segment */
+ {
+ from = "logical-data";
+ if (off <= 0x7fffL)
+ {
+ /* On chip data */
+ phys = targ_data + off;
+ if (off + nr_bytes > 0x7fffL)
+ /* don't cross VM boundary */
+ nr_bytes = 0x7fffL - off + 1;
+ to = "chip-data";
+ }
+ else if (off <= 0xbfffL)
+ {
+ short map = dmap;
+ if (map & 0x1000)
+ {
+ /* Instruction memory */
+ phys = targ_insn | ((map & 0xf) << 14) | (off & 0x3fff);
+ to = "chip-insn";
+ }
+ else
+ {
+ /* Unified memory */
+ phys = targ_unified | ((map & 0x3ff) << 14) | (off & 0x3fff);
+ to = "unified";
+ }
+ if (off + nr_bytes > 0xbfffL)
+ /* don't cross VM boundary */
+ nr_bytes = (0xbfffL - off + 1);
+ }
+ else
+ {
+ /* Logical address out side of data segments, not supported */
+ return (0);
+ }
+ break;
+ }
+
+ case 0x01: /* in logical instruction address segment */
+ {
+ short map;
+ from = "logical-insn";
+ if (off <= 0x1ffffL)
+ {
+ map = imap0;
+ }
+ else if (off <= 0x3ffffL)
+ {
+ map = imap1;
+ }
+ else
+ {
+ /* Logical address outside of IMAP[01] segment, not
+ supported */
+ return (0);
+ }
+ if ((off & 0x1ffff) + nr_bytes > 0x1ffffL)
+ {
+ /* don't cross VM boundary */
+ nr_bytes = 0x1ffffL - (off & 0x1ffffL) + 1;
+ }
+ if (map & 0x1000)
+ /* Instruction memory */
+ {
+ phys = targ_insn | off;
+ to = "chip-insn";
+ }
+ else
+ {
+ phys = ((map & 0x7fL) << 17) + (off & 0x1ffffL);
+ if (phys > 0xffffffL)
+ /* Address outside of unified address segment */
+ return (0);
+ phys |= targ_unified;
+ to = "unified";
+ }
+ break;
+ }
+
+ case 0x10: /* Physical data memory segment */
+ from = "phys-data";
+ phys = targ_data | off;
+ to = "chip-data";
+ break;
+
+ case 0x11: /* Physical instruction memory */
+ from = "phys-insn";
+ phys = targ_insn | off;
+ to = "chip-insn";
+ break;
+
+ case 0x12: /* Physical unified memory */
+ from = "phys-unified";
+ phys = targ_unified | off;
+ to = "unified";
+ break;
+
+ default:
+ return (0);
+ }
+
+
+ *taddr = phys;
+ return nr_bytes;
+}
+
+
+void
+_initialize_remote_d10v ()
+{
+ remote_d10v_ops.to_shortname = "d10v";
+ remote_d10v_ops.to_longname = "Remote d10v serial target in gdb-specific protocol";
+ remote_d10v_ops.to_doc = "Use a remote d10v via a serial line, using a gdb-specific protocol.\n\
+Specify the serial device it is connected to (e.g. /dev/ttya).";
+ remote_d10v_ops.to_open = remote_d10v_open;
+
+ add_target (&remote_d10v_ops);
+}
diff --git a/gdb/remote-e7000.c b/gdb/remote-e7000.c
new file mode 100644
index 00000000000..92e69b34981
--- /dev/null
+++ b/gdb/remote-e7000.c
@@ -0,0 +1,2258 @@
+/* Remote debugging interface for Hitachi E7000 ICE, for GDB
+ Copyright 1993, 1994, 1996, 1997, 1998 Free Software Foundation, Inc.
+ Contributed by Cygnus Support.
+
+ Written by Steve Chamberlain for 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* The E7000 is an in-circuit emulator for the Hitachi H8/300-H and
+ Hitachi-SH processor. It has serial port and a lan port.
+
+ The monitor command set makes it difficult to load large ammounts of
+ data over the lan without using ftp - so try not to issue load
+ commands when communicating over ethernet; use the ftpload command.
+
+ The monitor pauses for a second when dumping srecords to the serial
+ line too, so we use a slower per byte mechanism but without the
+ startup overhead. Even so, it's pretty slow... */
+
+#include "defs.h"
+#include "gdbcore.h"
+#include "gdbarch.h"
+#include "inferior.h"
+#include "target.h"
+#include "wait.h"
+#include "value.h"
+#include "command.h"
+#include <signal.h>
+#include "gdb_string.h"
+#include "gdbcmd.h"
+#include <sys/types.h>
+#include "serial.h"
+#include "remote-utils.h"
+#include "symfile.h"
+#include <time.h>
+#include <ctype.h>
+
+
+#if 1
+#define HARD_BREAKPOINTS /* Now handled by set option. */
+#define BC_BREAKPOINTS use_hard_breakpoints
+#endif
+
+#define CTRLC 0x03
+#define ENQ 0x05
+#define ACK 0x06
+#define CTRLZ 0x1a
+
+extern void notice_quit PARAMS ((void));
+
+extern void report_transfer_performance PARAMS ((unsigned long,
+ time_t, time_t));
+
+extern char *sh_processor_type;
+
+/* Local function declarations. */
+
+static void e7000_close PARAMS ((int));
+
+static void e7000_fetch_register PARAMS ((int));
+
+static void e7000_store_register PARAMS ((int));
+
+static void e7000_command PARAMS ((char *, int));
+
+static void e7000_login_command PARAMS ((char *, int));
+
+static void e7000_ftp_command PARAMS ((char *, int));
+
+static void e7000_drain_command PARAMS ((char *, int));
+
+static void expect PARAMS ((char *));
+
+static void expect_full_prompt PARAMS ((void));
+
+static void expect_prompt PARAMS ((void));
+
+static int e7000_parse_device PARAMS ((char *args, char *dev_name,
+ int baudrate));
+/* Variables. */
+
+static serial_t e7000_desc;
+
+/* Allow user to chose between using hardware breakpoints or memory. */
+static int use_hard_breakpoints = 0; /* use sw breakpoints by default */
+
+/* Nonzero if using the tcp serial driver. */
+
+static int using_tcp; /* direct tcp connection to target */
+static int using_tcp_remote; /* indirect connection to target
+ via tcp to controller */
+
+/* Nonzero if using the pc isa card. */
+
+static int using_pc;
+
+extern struct target_ops e7000_ops; /* Forward declaration */
+
+char *ENQSTRING = "\005";
+
+/* Nonzero if some routine (as opposed to the user) wants echoing.
+ FIXME: Do this reentrantly with an extra parameter. */
+
+static int echo;
+
+static int ctrl_c;
+
+static int timeout = 20;
+
+/* Send data to e7000debug. */
+
+static void
+puts_e7000debug (buf)
+ char *buf;
+{
+ if (!e7000_desc)
+ error ("Use \"target e7000 ...\" first.");
+
+ if (remote_debug)
+ printf_unfiltered ("Sending %s\n", buf);
+
+ if (SERIAL_WRITE (e7000_desc, buf, strlen (buf)))
+ fprintf_unfiltered (gdb_stderr, "SERIAL_WRITE failed: %s\n", safe_strerror (errno));
+
+ /* And expect to see it echoed, unless using the pc interface */
+#if 0
+ if (!using_pc)
+#endif
+ expect (buf);
+}
+
+static void
+putchar_e7000 (x)
+ int x;
+{
+ char b[1];
+
+ b[0] = x;
+ SERIAL_WRITE (e7000_desc, b, 1);
+}
+
+static void
+write_e7000 (s)
+ char *s;
+{
+ SERIAL_WRITE (e7000_desc, s, strlen (s));
+}
+
+static int
+normal (x)
+ int x;
+{
+ if (x == '\n')
+ return '\r';
+ return x;
+}
+
+/* Read a character from the remote system, doing all the fancy timeout
+ stuff. Handles serial errors and EOF. If TIMEOUT == 0, and no chars,
+ returns -1, else returns next char. Discards chars > 127. */
+
+static int
+readchar (timeout)
+ int timeout;
+{
+ int c;
+
+ do
+ {
+ c = SERIAL_READCHAR (e7000_desc, timeout);
+ }
+ while (c > 127);
+
+ if (c == SERIAL_TIMEOUT)
+ {
+ if (timeout == 0)
+ return -1;
+ echo = 0;
+ error ("Timeout reading from remote system.");
+ }
+ else if (c < 0)
+ error ("Serial communication error");
+
+ if (remote_debug)
+ {
+ putchar_unfiltered (c);
+ gdb_flush (gdb_stdout);
+ }
+
+ return normal (c);
+}
+
+#if 0
+char *
+tl (x)
+{
+ static char b[8][10];
+ static int p;
+
+ p++;
+ p &= 7;
+ if (x >= ' ')
+ {
+ b[p][0] = x;
+ b[p][1] = 0;
+ }
+ else
+ {
+ sprintf(b[p], "<%d>", x);
+ }
+
+ return b[p];
+}
+#endif
+
+/* Scan input from the remote system, until STRING is found. If
+ DISCARD is non-zero, then discard non-matching input, else print it
+ out. Let the user break out immediately. */
+
+static void
+expect (string)
+ char *string;
+{
+ char *p = string;
+ int c;
+ int nl = 0;
+
+ while (1)
+ {
+ c = readchar (timeout);
+#if 0
+ notice_quit ();
+ if (quit_flag == 1)
+ {
+ if (ctrl_c)
+ {
+ putchar_e7000(CTRLC);
+ --ctrl_c;
+ }
+ else
+ {
+ quit ();
+ }
+ }
+#endif
+
+ if (echo)
+ {
+ if (c == '\r' || c == '\n')
+ {
+ if (!nl)
+ putchar_unfiltered ('\n');
+ nl = 1;
+ }
+ else
+ {
+ nl = 0;
+ putchar_unfiltered (c);
+ }
+ gdb_flush (gdb_stdout);
+ }
+ if (normal (c) == normal (*p++))
+ {
+ if (*p == '\0')
+ return;
+ }
+ else
+ {
+ p = string;
+
+ if (normal (c) == normal (string[0]))
+ p++;
+ }
+ }
+}
+
+/* Keep discarding input until we see the e7000 prompt.
+
+ The convention for dealing with the prompt is that you
+ o give your command
+ o *then* wait for the prompt.
+
+ Thus the last thing that a procedure does with the serial line will
+ be an expect_prompt(). Exception: e7000_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
+ e7000_wait which does wait for the prompt. Note that this includes
+ abnormal exit, e.g. error(). This is necessary to prevent getting
+ into states from which we can't recover. */
+
+static void
+expect_prompt ()
+{
+ expect (":");
+}
+
+static void
+expect_full_prompt ()
+{
+ expect ("\r:");
+}
+
+static int
+convert_hex_digit (ch)
+ int ch;
+{
+ 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;
+ return -1;
+}
+
+static int
+get_hex (start)
+ int *start;
+{
+ int value = convert_hex_digit (*start);
+ int try;
+
+ *start = readchar (timeout);
+ while ((try = convert_hex_digit (*start)) >= 0)
+ {
+ value <<= 4;
+ value += try;
+ *start = readchar (timeout);
+ }
+ return value;
+}
+
+#if 0
+/* Get N 32-bit words from remote, each preceded by a space, and put
+ them in registers starting at REGNO. */
+
+static void
+get_hex_regs (n, regno)
+ int n;
+ int regno;
+{
+ long val;
+ int i;
+
+ for (i = 0; i < n; i++)
+ {
+ int j;
+
+ val = 0;
+ for (j = 0; j < 8; j++)
+ val = (val << 4) + get_hex_digit (j == 0);
+ supply_register (regno++, (char *) &val);
+ }
+}
+#endif
+
+/* This is called not only when we first attach, but also when the
+ user types "run" after having attached. */
+
+static void
+e7000_create_inferior (execfile, args, env)
+ char *execfile;
+ char *args;
+ char **env;
+{
+ int entry_pt;
+
+ if (args && *args)
+ error ("Can't pass arguments to remote E7000DEBUG process");
+
+ if (execfile == 0 || exec_bfd == 0)
+ error ("No executable file specified");
+
+ entry_pt = (int) bfd_get_start_address (exec_bfd);
+
+#ifdef CREATE_INFERIOR_HOOK
+ CREATE_INFERIOR_HOOK (0); /* No process-ID */
+#endif
+
+ /* The "process" (board) is already stopped awaiting our commands, and
+ the program is already downloaded. We just set its PC and go. */
+
+ clear_proceed_status ();
+
+ /* Tell wait_for_inferior that we've started a new process. */
+ init_wait_for_inferior ();
+
+ /* Set up the "saved terminal modes" of the inferior
+ based on what modes we are starting it with. */
+ target_terminal_init ();
+
+ /* Install inferior's terminal modes. */
+ target_terminal_inferior ();
+
+ /* insert_step_breakpoint (); FIXME, do we need this? */
+ proceed ((CORE_ADDR) entry_pt, -1, 0); /* Let 'er rip... */
+}
+
+/* Open a connection to a remote debugger. NAME is the filename used
+ for communication. */
+
+static int baudrate = 9600;
+static char dev_name[100];
+
+static char *machine = "";
+static char *user = "";
+static char *passwd = "";
+static char *dir = "";
+
+/* Grab the next token and buy some space for it */
+
+static char *
+next (ptr)
+ char **ptr;
+{
+ char *p = *ptr;
+ char *s;
+ char *r;
+ int l = 0;
+
+ while (*p && *p == ' ')
+ p++;
+ s = p;
+ while (*p && (*p != ' ' && *p != '\t'))
+ {
+ l++;
+ p++;
+ }
+ r = xmalloc (l + 1);
+ memcpy (r, s, l);
+ r[l] = 0;
+ *ptr = p;
+ return r;
+}
+
+static void
+e7000_login_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ if (args)
+ {
+ machine = next (&args);
+ user = next (&args);
+ passwd = next (&args);
+ dir = next (&args);
+ if (from_tty)
+ {
+ printf_unfiltered ("Set info to %s %s %s %s\n", machine, user, passwd, dir);
+ }
+ }
+ else
+ {
+ error ("Syntax is ftplogin <machine> <user> <passwd> <directory>");
+ }
+}
+
+/* Start an ftp transfer from the E7000 to a host */
+
+static void
+e7000_ftp_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ /* FIXME: arbitrary limit on machine names and such. */
+ char buf[200];
+
+ int oldtimeout = timeout;
+ timeout = remote_timeout;
+
+ sprintf (buf, "ftp %s\r", machine);
+ puts_e7000debug (buf);
+ expect (" Username : ");
+ sprintf (buf, "%s\r", user);
+ puts_e7000debug (buf);
+ expect (" Password : ");
+ write_e7000 (passwd);
+ write_e7000 ("\r");
+ expect ("success\r");
+ expect ("FTP>");
+ sprintf (buf, "cd %s\r", dir);
+ puts_e7000debug (buf);
+ expect ("FTP>");
+ sprintf (buf, "ll 0;s:%s\r", args);
+ puts_e7000debug (buf);
+ expect ("FTP>");
+ puts_e7000debug ("bye\r");
+ expect (":");
+ timeout = oldtimeout;
+}
+
+static int
+e7000_parse_device (args, dev_name, baudrate)
+ char *args;
+ char *dev_name;
+ int baudrate;
+{
+ char junk[128];
+ int n = 0;
+ if (args && strcasecmp (args, "pc") == 0)
+ {
+ strcpy (dev_name, args);
+ using_pc = 1;
+ }
+ else
+ {
+ /* FIXME! temp hack to allow use with port master -
+ target tcp_remote <device> */
+ if (args && strncmp (args, "tcp", 10) == 0)
+ {
+ char com_type[128];
+ n = sscanf (args, " %s %s %d %s", com_type, dev_name, &baudrate, junk);
+ using_tcp_remote=1;
+ n--;
+ }
+ else if (args)
+ {
+ n = sscanf (args, " %s %d %s", dev_name, &baudrate, junk);
+ }
+
+ if (n != 1 && n != 2)
+ {
+ error ("Bad arguments. Usage:\ttarget e7000 <device> <speed>\n\
+or \t\ttarget e7000 <host>[:<port>]\n\
+or \t\ttarget e7000 tcp_remote <host>[:<port>]\n\
+or \t\ttarget e7000 pc\n");
+ }
+
+#if !defined(__GO32__) && !defined(_WIN32)
+ /* FIXME! test for ':' is ambiguous */
+ if (n == 1 && strchr (dev_name, ':') == 0)
+ {
+ /* Default to normal telnet port */
+ /* serial_open will use this to determine tcp communication */
+ strcat (dev_name, ":23");
+ }
+#endif
+ if (!using_tcp_remote && strchr (dev_name, ':'))
+ using_tcp = 1;
+ }
+
+ return n;
+}
+
+/* Stub for catch_errors. */
+
+static int
+e7000_start_remote (dummy)
+ char *dummy;
+{
+ int loop;
+ int sync;
+ int try;
+ int quit_trying;
+
+ immediate_quit = 1; /* Allow user to interrupt it */
+
+ /* Hello? Are you there? */
+ sync = 0;
+ loop = 0;
+ try = 0;
+ quit_trying = 20;
+ putchar_e7000 (CTRLC);
+ while (!sync && ++try <= quit_trying)
+ {
+ int c;
+
+ printf_unfiltered ("[waiting for e7000...]\n");
+
+ write_e7000 ("\r");
+ c = readchar (1);
+
+ /* FIXME! this didn't seem right-> while (c != SERIAL_TIMEOUT)
+ * we get stuck in this loop ...
+ * We may never timeout, and never sync up :-(
+ */
+ while (!sync && c != -1)
+ {
+ /* Dont echo cr's */
+ if (c != '\r')
+ {
+ putchar_unfiltered (c);
+ gdb_flush (gdb_stdout);
+ }
+ /* Shouldn't we either break here, or check for sync in inner loop? */
+ if (c == ':')
+ sync = 1;
+
+ if (loop++ == 20)
+ {
+ putchar_e7000 (CTRLC);
+ loop = 0;
+ }
+
+ QUIT ;
+
+ if (quit_flag)
+ {
+ putchar_e7000 (CTRLC);
+ /* Was-> quit_flag = 0; */
+ c = -1;
+ quit_trying = try+1; /* we don't want to try anymore */
+ }
+ else
+ {
+ c = readchar (1);
+ }
+ }
+ }
+
+ if (!sync)
+ {
+ fprintf_unfiltered (gdb_stderr, "Giving up after %d tries...\n",try);
+ error ("Unable to syncronize with target.\n");
+ }
+
+ puts_e7000debug ("\r");
+ expect_prompt ();
+ puts_e7000debug ("b -\r"); /* Clear breakpoints */
+ expect_prompt ();
+
+ immediate_quit = 0;
+
+/* This is really the job of start_remote however, that makes an assumption
+ that the target is about to print out a status message of some sort. That
+ doesn't happen here. */
+
+ flush_cached_frames ();
+ registers_changed ();
+ stop_pc = read_pc ();
+ set_current_frame (create_new_frame (read_fp (), stop_pc));
+ select_frame (get_current_frame (), 0);
+ print_stack_frame (selected_frame, -1, 1);
+
+ return 1;
+}
+
+static void
+e7000_open (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ int n;
+
+ target_preopen (from_tty);
+
+ n = e7000_parse_device (args, dev_name, baudrate);
+
+ push_target (&e7000_ops);
+
+ e7000_desc = SERIAL_OPEN (dev_name);
+
+ if (!e7000_desc)
+ perror_with_name (dev_name);
+
+ SERIAL_SETBAUDRATE (e7000_desc, baudrate);
+ SERIAL_RAW (e7000_desc);
+
+#ifdef GDB_TARGET_IS_H8300
+ h8300hmode = 1;
+#endif
+
+ /* 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 (e7000_start_remote, (char *)0,
+ "Couldn't establish connection to remote target\n", RETURN_MASK_ALL))
+ if (from_tty)
+ printf_filtered ("Remote target %s connected to %s\n", target_shortname,
+ dev_name);
+}
+
+/* Close out all files and local state before this target loses control. */
+
+static void
+e7000_close (quitting)
+ int quitting;
+{
+ if (e7000_desc)
+ {
+ SERIAL_CLOSE (e7000_desc);
+ e7000_desc = 0;
+ }
+}
+
+/* Terminate the open connection to the remote debugger. Use this
+ when you want to detach and do something else with your gdb. */
+
+static void
+e7000_detach (from_tty)
+ int from_tty;
+{
+ pop_target (); /* calls e7000_close to do the real work */
+ if (from_tty)
+ printf_unfiltered ("Ending remote %s debugging\n", target_shortname);
+}
+
+/* Tell the remote machine to resume. */
+
+static void
+e7000_resume (pid, step, sig)
+ int pid, step, sig;
+{
+ if (step)
+ puts_e7000debug ("S\r");
+ else
+ puts_e7000debug ("G\r");
+}
+
+/* Read the remote registers into the block REGS.
+
+ For the H8/300 a register dump looks like:
+
+ PC=00021A CCR=80:I*******
+ ER0 - ER3 0000000A 0000002E 0000002E 00000000
+ ER4 - ER7 00000000 00000000 00000000 00FFEFF6
+ 000218 MOV.B R1L,R2L
+ STEP NORMAL END or
+ BREAK POINT
+ */
+
+#ifdef GDB_TARGET_IS_H8300
+
+char *want_h8300h = "PC=%p CCR=%c\n\
+ ER0 - ER3 %0 %1 %2 %3\n\
+ ER4 - ER7 %4 %5 %6 %7\n";
+
+char *want_nopc_h8300h = "%p CCR=%c\n\
+ ER0 - ER3 %0 %1 %2 %3\n\
+ ER4 - ER7 %4 %5 %6 %7";
+
+char *want_h8300s = "PC=%p CCR=%c\n\
+ MACH=\n\
+ ER0 - ER3 %0 %1 %2 %3\n\
+ ER4 - ER7 %4 %5 %6 %7\n";
+
+char *want_nopc_h8300s = "%p CCR=%c EXR=%9\n\
+ ER0 - ER3 %0 %1 %2 %3\n\
+ ER4 - ER7 %4 %5 %6 %7";
+
+#endif
+
+#ifdef GDB_TARGET_IS_SH
+
+char *want = "PC=%16 SR=%22\n\
+PR=%17 GBR=%18 VBR=%19\n\
+MACH=%20 MACL=%21\n\
+R0-7 %0 %1 %2 %3 %4 %5 %6 %7\n\
+R8-15 %8 %9 %10 %11 %12 %13 %14 %15\n";
+
+char *want_nopc = "%16 SR=%22\n\
+ PR=%17 GBR=%18 VBR=%19\n\
+ MACH=%20 MACL=%21\n\
+ R0-7 %0 %1 %2 %3 %4 %5 %6 %7\n\
+ R8-15 %8 %9 %10 %11 %12 %13 %14 %15";
+
+char *want_sh3 = "PC=%16 SR=%22\n\
+PR=%17 GBR=%18 VBR=%19\n\
+MACH=%20 MACL=%21 SSR=%23 SPC=%24\n\
+R0-7 %0 %1 %2 %3 %4 %5 %6 %7\n\
+R8-15 %8 %9 %10 %11 %12 %13 %14 %15\n\
+R0_BANK0-R3_BANK0 %25 %26 %27 %28\n\
+R4_BANK0-R7_BANK0 %29 %30 %31 %32\n\
+R0_BANK1-R3_BANK1 %33 %34 %35 %36\n\
+R4_BANK1-R7_BANK1 %37 %38 %39 %40";
+
+char *want_sh3_nopc = "%16 SR=%22\n\
+ PR=%17 GBR=%18 VBR=%19\n\
+ MACH=%20 MACL=%21 SSR=%22 SPC=%23\n\
+ R0-7 %0 %1 %2 %3 %4 %5 %6 %7\n\
+ R8-15 %8 %9 %10 %11 %12 %13 %14 %15\n\
+ R0_BANK0-R3_BANK0 %25 %26 %27 %28\n\
+ R4_BANK0-R7_BANK0 %29 %30 %31 %32\n\
+ R0_BANK1-R3_BANK1 %33 %34 %35 %36\n\
+ R4_BANK1-R7_BANK1 %37 %38 %39 %40";
+
+#endif
+
+static int
+gch ()
+{
+ return readchar (timeout);
+}
+
+static unsigned int
+gbyte ()
+{
+ int high = convert_hex_digit (gch ());
+ int low = convert_hex_digit (gch ());
+
+ return (high << 4) + low;
+}
+
+void
+fetch_regs_from_dump (nextchar, want)
+ int (*nextchar)();
+ char *want;
+{
+ int regno;
+ char buf[MAX_REGISTER_RAW_SIZE];
+
+ int thischar = nextchar ();
+
+ while (*want)
+ {
+ switch (*want)
+ {
+ case '\n':
+ /* Skip to end of line and then eat all new line type stuff */
+ while (thischar != '\n' && thischar != '\r')
+ thischar = nextchar ();
+ while (thischar == '\n' || thischar == '\r')
+ thischar = nextchar ();
+ want++;
+ break;
+
+ case ' ':
+ while (thischar == ' '
+ || thischar == '\t'
+ || thischar == '\r'
+ || thischar == '\n')
+ thischar = nextchar ();
+ want++;
+ break;
+
+ default:
+ if (*want == thischar)
+ {
+ want++;
+ if (*want)
+ thischar = nextchar ();
+
+ }
+ else if (thischar == ' ' || thischar == '\n' || thischar == '\r')
+ {
+ thischar = nextchar ();
+ }
+ else {
+ error ("out of sync in fetch registers wanted <%s>, got <%c 0x%x>",
+ want, thischar, thischar);
+ }
+
+ break;
+ case '%':
+ /* Got a register command */
+ want++;
+ switch (*want)
+ {
+#ifdef PC_REGNUM
+ case 'p':
+ regno = PC_REGNUM;
+ want++;
+ break;
+#endif
+#ifdef CCR_REGNUM
+ case 'c':
+ regno = CCR_REGNUM;
+ want++;
+ break;
+#endif
+#ifdef SP_REGNUM
+ case 's':
+ regno = SP_REGNUM;
+ want++;
+ break;
+#endif
+#ifdef FP_REGNUM
+ case 'f':
+ regno = FP_REGNUM;
+ want++;
+ break;
+#endif
+
+ default:
+ if (isdigit (want[0]))
+ {
+ if (isdigit (want[1]))
+ {
+ regno = (want[0] - '0') * 10 + want[1] - '0';
+ want += 2;
+ }
+ else
+ {
+ regno = want[0] - '0';
+ want++;
+ }
+ }
+
+ else
+ abort ();
+ }
+ store_signed_integer (buf,
+ REGISTER_RAW_SIZE(regno),
+ (LONGEST) get_hex (&thischar, nextchar));
+ supply_register (regno, buf);
+ break;
+ }
+ }
+}
+
+static void
+e7000_fetch_registers ()
+{
+ int regno;
+ char *wanted;
+
+ puts_e7000debug ("R\r");
+
+#ifdef GDB_TARGET_IS_SH
+ wanted = want;
+ if (TARGET_ARCHITECTURE->arch == bfd_arch_sh)
+ switch (TARGET_ARCHITECTURE->mach)
+ {
+ case bfd_mach_sh3:
+ case bfd_mach_sh3e:
+ wanted = want_sh3;
+ }
+#else
+ if (h8300smode)
+ wanted = want_h8300s;
+ else
+ wanted = want_h8300h;
+#endif
+ fetch_regs_from_dump (gch, wanted);
+
+ /* And supply the extra ones the simulator uses */
+ for (regno = NUM_REALREGS; regno < NUM_REGS; regno++)
+ {
+ int buf = 0;
+
+ supply_register (regno, (char *) (&buf));
+ }
+}
+
+/* Fetch register REGNO, or all registers if REGNO is -1. Returns
+ errno value. */
+
+static void
+e7000_fetch_register (regno)
+ int regno;
+{
+ e7000_fetch_registers ();
+}
+
+/* Store the remote registers from the contents of the block REGS. */
+
+static void
+e7000_store_registers ()
+{
+ int regno;
+
+ for (regno = 0; regno < NUM_REALREGS; regno++)
+ e7000_store_register (regno);
+
+ registers_changed ();
+}
+
+/* Store register REGNO, or all if REGNO == 0. Return errno value. */
+
+static void
+e7000_store_register (regno)
+ int regno;
+{
+ char buf[200];
+
+ if (regno == -1)
+ {
+ e7000_store_registers ();
+ return;
+ }
+
+#ifdef GDB_TARGET_IS_H8300
+ if (regno <= 7)
+ {
+ sprintf (buf, ".ER%d %x\r", regno, read_register (regno));
+ puts_e7000debug (buf);
+ }
+ else if (regno == PC_REGNUM)
+ {
+ sprintf (buf, ".PC %x\r", read_register (regno));
+ puts_e7000debug (buf);
+ }
+ else if (regno == CCR_REGNUM)
+ {
+ sprintf (buf, ".CCR %x\r", read_register (regno));
+ puts_e7000debug (buf);
+ }
+#endif /* GDB_TARGET_IS_H8300 */
+
+#ifdef GDB_TARGET_IS_SH
+ switch (regno)
+ {
+ default:
+ sprintf (buf, ".R%d %x\r", regno, read_register (regno));
+ puts_e7000debug (buf);
+ break;
+
+ case PC_REGNUM:
+ sprintf (buf, ".PC %x\r", read_register (regno));
+ puts_e7000debug (buf);
+ break;
+
+ case SR_REGNUM:
+ sprintf (buf, ".SR %x\r", read_register (regno));
+ puts_e7000debug (buf);
+ break;
+
+ case PR_REGNUM:
+ sprintf (buf, ".PR %x\r", read_register (regno));
+ puts_e7000debug (buf);
+ break;
+
+ case GBR_REGNUM:
+ sprintf (buf, ".GBR %x\r", read_register (regno));
+ puts_e7000debug (buf);
+ break;
+
+ case VBR_REGNUM:
+ sprintf (buf, ".VBR %x\r", read_register (regno));
+ puts_e7000debug (buf);
+ break;
+
+ case MACH_REGNUM:
+ sprintf (buf, ".MACH %x\r", read_register (regno));
+ puts_e7000debug (buf);
+ break;
+
+ case MACL_REGNUM:
+ sprintf (buf, ".MACL %x\r", read_register (regno));
+ puts_e7000debug (buf);
+ break;
+ }
+
+#endif /* GDB_TARGET_IS_SH */
+
+ expect_prompt ();
+}
+
+/* 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
+e7000_prepare_to_store ()
+{
+ /* Do nothing, since we can store individual regs */
+}
+
+static void
+e7000_files_info ()
+{
+ printf_unfiltered ("\tAttached to %s at %d baud.\n", dev_name, baudrate);
+}
+
+static int
+stickbyte (where, what)
+ char *where;
+ unsigned int what;
+{
+ static CONST char digs[] = "0123456789ABCDEF";
+
+ where[0] = digs[(what >> 4) & 0xf];
+ where[1] = digs[(what & 0xf) & 0xf];
+
+ return what;
+}
+
+/* Write a small ammount of memory. */
+
+static int
+write_small (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ unsigned char *myaddr;
+ int len;
+{
+ int i;
+ char buf[200];
+
+ for (i = 0; i < len; i++)
+ {
+ if (((memaddr + i) & 3) == 0 && (i + 3 < len))
+ {
+ /* Can be done with a long word */
+ sprintf (buf, "m %x %x%02x%02x%02x;l\r",
+ memaddr + i,
+ myaddr[i], myaddr[i + 1], myaddr[i + 2], myaddr[i + 3]);
+ puts_e7000debug (buf);
+ i += 3;
+ }
+ else
+ {
+ sprintf (buf, "m %x %x\r", memaddr + i, myaddr[i]);
+ puts_e7000debug (buf);
+ }
+ }
+
+ expect_prompt ();
+
+ return len;
+}
+
+/* Write a large ammount of memory, this only works with the serial
+ mode enabled. Command is sent as
+
+ il ;s:s\r ->
+ <- il ;s:s\r
+ <- ENQ
+ ACK ->
+ <- LO s\r
+ Srecords...
+ ^Z ->
+ <- ENQ
+ ACK ->
+ <- :
+ */
+
+static int
+write_large (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ unsigned char *myaddr;
+ int len;
+{
+ int i;
+#define maxstride 128
+ int stride;
+
+ puts_e7000debug ("IL ;S:FK\r");
+ expect (ENQSTRING);
+ putchar_e7000 (ACK);
+ expect ("LO FK\r");
+
+ for (i = 0; i < len; i += stride)
+ {
+ char compose[maxstride * 2 + 50];
+ int address = i + memaddr;
+ int j;
+ int check_sum;
+ int where = 0;
+ int alen;
+
+ stride = len - i;
+ if (stride > maxstride)
+ stride = maxstride;
+
+ compose[where++] = 'S';
+ check_sum = 0;
+ if (address >= 0xffffff)
+ alen = 4;
+ else if (address >= 0xffff)
+ alen = 3;
+ else
+ alen = 2;
+ /* Insert type. */
+ compose[where++] = alen - 1 + '0';
+ /* Insert length. */
+ check_sum += stickbyte (compose + where, alen + stride + 1);
+ where += 2;
+ while (alen > 0)
+ {
+ alen--;
+ check_sum += stickbyte (compose + where, address >> (8 * (alen)));
+ where += 2;
+ }
+
+ for (j = 0; j < stride; j++)
+ {
+ check_sum += stickbyte (compose + where, myaddr[i + j]);
+ where += 2;
+ }
+ stickbyte (compose + where, ~check_sum);
+ where += 2;
+ compose[where++] = '\r';
+ compose[where++] = '\n';
+ compose[where++] = 0;
+
+ SERIAL_WRITE (e7000_desc, compose, where);
+ j = readchar (0);
+ if (j == -1)
+ {
+ /* This is ok - nothing there */
+ }
+ else if (j == ENQ)
+ {
+ /* Hmm, it's trying to tell us something */
+ expect (":");
+ error ("Error writing memory");
+ }
+ else
+ {
+ printf_unfiltered ("@%d}@", j);
+ while ((j = readchar (0)) > 0)
+ {
+ printf_unfiltered ("@{%d}@",j);
+ }
+ }
+ }
+
+ /* Send the trailer record */
+ write_e7000 ("S70500000000FA\r");
+ putchar_e7000 (CTRLZ);
+ expect (ENQSTRING);
+ putchar_e7000 (ACK);
+ expect (":");
+
+ return len;
+}
+
+/* Copy LEN bytes of data from debugger memory at MYADDR to inferior's
+ memory at MEMADDR. Returns length moved.
+
+ Can't use the Srecord load over ethernet, so don't use fast method
+ then. */
+
+static int
+e7000_write_inferior_memory (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ unsigned char *myaddr;
+ int len;
+{
+ if (len < 16 || using_tcp || using_pc)
+ return write_small (memaddr, myaddr, len);
+ else
+ return write_large (memaddr, myaddr, len);
+}
+
+/* Read LEN bytes from inferior memory at MEMADDR. Put the result
+ at debugger address MYADDR. Returns length moved.
+
+ Small transactions we send
+ m <addr>;l
+ and receive
+ 00000000 12345678 ?
+ */
+
+static int
+e7000_read_inferior_memory (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ unsigned char *myaddr;
+ int len;
+{
+ int count;
+ int c;
+ int i;
+ char buf[200];
+ /* Starting address of this pass. */
+
+/* printf("READ INF %x %x %d\n", memaddr, myaddr, len);*/
+ if (((memaddr - 1) + len) < memaddr)
+ {
+ errno = EIO;
+ return 0;
+ }
+
+ sprintf (buf, "m %x;l\r", memaddr);
+ puts_e7000debug (buf);
+
+ for (count = 0; count < len; count += 4)
+ {
+ /* Suck away the address */
+ c = gch ();
+ while (c != ' ')
+ c = gch ();
+ c = gch ();
+ if (c == '*')
+ { /* Some kind of error */
+ puts_e7000debug (".\r"); /* Some errors leave us in memory input mode */
+ expect_full_prompt();
+ return -1;
+ }
+ while (c != ' ')
+ c = gch ();
+
+ /* Now read in the data */
+ for (i = 0; i < 4; i++)
+ {
+ int b = gbyte();
+ if (count + i < len) {
+ myaddr[count + i] = b;
+ }
+ }
+
+ /* Skip the trailing ? and send a . to end and a cr for more */
+ gch ();
+ gch ();
+ if (count + 4 >= len)
+ puts_e7000debug(".\r");
+ else
+ puts_e7000debug("\r");
+
+ }
+ expect_prompt();
+ return len;
+}
+
+
+
+/*
+ For large transfers we used to send
+
+
+ d <addr> <endaddr>\r
+
+ and receive
+ <ADDRESS> < D A T A > < ASCII CODE >
+ 00000000 5F FD FD FF DF 7F DF FF 01 00 01 00 02 00 08 04 "_..............."
+ 00000010 FF D7 FF 7F D7 F1 7F FF 00 05 00 00 08 00 40 00 "..............@."
+ 00000020 7F FD FF F7 7F FF FF F7 00 00 00 00 00 00 00 00 "................"
+
+ A cost in chars for each transaction of 80 + 5*n-bytes.
+
+ Large transactions could be done with the srecord load code, but
+ there is a pause for a second before dumping starts, which slows the
+ average rate down!
+*/
+
+static int
+e7000_read_inferior_memory_large (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ unsigned char *myaddr;
+ int len;
+{
+ int count;
+ int c;
+ char buf[200];
+
+ /* Starting address of this pass. */
+
+ if (((memaddr - 1) + len) < memaddr)
+ {
+ errno = EIO;
+ return 0;
+ }
+
+ sprintf (buf, "d %x %x\r", memaddr, memaddr + len - 1);
+ puts_e7000debug (buf);
+
+ count = 0;
+ c = gch ();
+
+ /* skip down to the first ">" */
+ while( c != '>' )
+ c = gch ();
+ /* now skip to the end of that line */
+ while( c != '\r' )
+ c = gch ();
+ c = gch ();
+
+ while (count < len)
+ {
+ /* get rid of any white space before the address */
+ while (c <= ' ')
+ c = gch ();
+
+ /* Skip the address */
+ get_hex (&c);
+
+ /* read in the bytes on the line */
+ while (c != '"' && count < len)
+ {
+ if (c == ' ')
+ c = gch ();
+ else
+ {
+ myaddr[count++] = get_hex (&c);
+ }
+ }
+ /* throw out the rest of the line */
+ while( c != '\r' )
+ c = gch ();
+ }
+
+ /* wait for the ":" prompt */
+ while (c != ':')
+ c = gch ();
+
+ return len;
+}
+
+#if 0
+
+static int
+fast_but_for_the_pause_e7000_read_inferior_memory (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+{
+ int loop;
+ int c;
+ char buf[200];
+
+ if (((memaddr - 1) + len) < memaddr)
+ {
+ errno = EIO;
+ return 0;
+ }
+
+ sprintf (buf, "is %x@%x:s\r", memaddr, len);
+ puts_e7000debug (buf);
+ gch ();
+ c = gch ();
+ if (c != ENQ)
+ {
+ /* Got an error */
+ error ("Memory read error");
+ }
+ putchar_e7000 (ACK);
+ expect ("SV s");
+ loop = 1;
+ while (loop)
+ {
+ int type;
+ int length;
+ int addr;
+ int i;
+
+ c = gch ();
+ switch (c)
+ {
+ case ENQ: /* ENQ, at the end */
+ loop = 0;
+ break;
+ case 'S':
+ /* Start of an Srecord */
+ type = gch ();
+ length = gbyte ();
+ switch (type)
+ {
+ case '7': /* Termination record, ignore */
+ case '0':
+ case '8':
+ case '9':
+ /* Header record - ignore it */
+ while (length--)
+ {
+ gbyte ();
+ }
+ break;
+ case '1':
+ case '2':
+ case '3':
+ {
+ int alen;
+
+ alen = type - '0' + 1;
+ addr = 0;
+ while (alen--)
+ {
+ addr = (addr << 8) + gbyte ();
+ length--;
+ }
+
+ for (i = 0; i < length - 1; i++)
+ myaddr[i + addr - memaddr] = gbyte ();
+
+ gbyte (); /* Ignore checksum */
+ }
+ }
+ }
+ }
+
+ putchar_e7000 (ACK);
+ expect ("TOP ADDRESS =");
+ expect ("END ADDRESS =");
+ expect (":");
+
+ return len;
+}
+
+#endif
+
+static int
+e7000_xfer_inferior_memory (memaddr, myaddr, len, write, target)
+ CORE_ADDR memaddr;
+ unsigned char *myaddr;
+ int len;
+ int write;
+ struct target_ops *target; /* ignored */
+{
+ if (write)
+ return e7000_write_inferior_memory( memaddr, myaddr, len);
+ else
+ if( len < 16 )
+ return e7000_read_inferior_memory( memaddr, myaddr, len);
+ else
+ return e7000_read_inferior_memory_large( memaddr, myaddr, len);
+}
+
+static void
+e7000_kill (args, from_tty)
+ char *args;
+ int from_tty;
+{
+}
+
+static void
+e7000_load (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ struct cleanup *old_chain;
+ asection *section;
+ bfd *pbfd;
+ bfd_vma entry;
+#define WRITESIZE 0x1000
+ char buf[2 + 4 + 4 + WRITESIZE]; /* `DT' + <addr> + <len> + <data> */
+ char *filename;
+ int quiet;
+ int nostart;
+ time_t start_time, end_time; /* Start and end times of download */
+ unsigned long data_count; /* Number of bytes transferred to memory */
+ int oldtimeout = timeout;
+
+ timeout = remote_timeout;
+
+
+ /* FIXME! change test to test for type of download */
+ if (!using_tcp)
+ {
+ generic_load (args, from_tty);
+ return;
+ }
+
+ /* for direct tcp connections, we can do a fast binary download */
+ buf[0] = 'D';
+ buf[1] = 'T';
+ quiet = 0;
+ nostart = 0;
+ filename = NULL;
+
+ while (*args != '\000')
+ {
+ char *arg;
+
+ while (isspace (*args)) args++;
+
+ arg = args;
+
+ while ((*args != '\000') && !isspace (*args)) args++;
+
+ if (*args != '\000')
+ *args++ = '\000';
+
+ if (*arg != '-')
+ filename = arg;
+ else if (strncmp (arg, "-quiet", strlen (arg)) == 0)
+ quiet = 1;
+ else if (strncmp (arg, "-nostart", strlen (arg)) == 0)
+ nostart = 1;
+ else
+ error ("unknown option `%s'", arg);
+ }
+
+ if (!filename)
+ filename = get_exec_file (1);
+
+ pbfd = bfd_openr (filename, gnutarget);
+ if (pbfd == NULL)
+ {
+ perror_with_name (filename);
+ return;
+ }
+ old_chain = make_cleanup ((make_cleanup_func) bfd_close, pbfd);
+
+ if (!bfd_check_format (pbfd, bfd_object))
+ error ("\"%s\" is not an object file: %s", filename,
+ bfd_errmsg (bfd_get_error ()));
+
+ start_time = time (NULL);
+ data_count = 0;
+
+ puts_e7000debug ("mw\r");
+
+ expect ("\nOK");
+
+ for (section = pbfd->sections; section; section = section->next)
+ {
+ if (bfd_get_section_flags (pbfd, section) & SEC_LOAD)
+ {
+ bfd_vma section_address;
+ bfd_size_type section_size;
+ file_ptr fptr;
+
+ section_address = bfd_get_section_vma (pbfd, section);
+ section_size = bfd_get_section_size_before_reloc (section);
+
+ if (!quiet)
+ printf_filtered ("[Loading section %s at 0x%x (%d bytes)]\n",
+ bfd_get_section_name (pbfd, section),
+ section_address,
+ section_size);
+
+ fptr = 0;
+
+ data_count += section_size;
+
+ while (section_size > 0)
+ {
+ int count;
+ static char inds[] = "|/-\\";
+ static int k = 0;
+
+ QUIT;
+
+ count = min (section_size, WRITESIZE);
+
+ buf[2] = section_address >> 24;
+ buf[3] = section_address >> 16;
+ buf[4] = section_address >> 8;
+ buf[5] = section_address;
+
+ buf[6] = count >> 24;
+ buf[7] = count >> 16;
+ buf[8] = count >> 8;
+ buf[9] = count;
+
+ bfd_get_section_contents (pbfd, section, buf + 10, fptr, count);
+
+ if (SERIAL_WRITE (e7000_desc, buf, count + 10))
+ fprintf_unfiltered (gdb_stderr,
+ "e7000_load: SERIAL_WRITE failed: %s\n",
+ safe_strerror(errno));
+
+ expect ("OK");
+
+ if (!quiet)
+ {
+ printf_unfiltered ("\r%c", inds[k++ % 4]);
+ gdb_flush (gdb_stdout);
+ }
+
+ section_address += count;
+ fptr += count;
+ section_size -= count;
+ }
+ }
+ }
+
+ write_e7000 ("ED");
+
+ expect_prompt ();
+
+ end_time = time (NULL);
+
+/* Finally, make the PC point at the start address */
+
+ if (exec_bfd)
+ write_pc (bfd_get_start_address (exec_bfd));
+
+ inferior_pid = 0; /* No process now */
+
+/* This is necessary because many things were based on the PC at the time that
+ we attached to the monitor, which is no longer valid now that we have loaded
+ new code (and just changed the PC). Another way to do this might be to call
+ normal_stop, except that the stack may not be valid, and things would get
+ horribly confused... */
+
+ clear_symtab_users ();
+
+ if (!nostart)
+ {
+ entry = bfd_get_start_address (pbfd);
+
+ if (!quiet)
+ printf_unfiltered ("[Starting %s at 0x%x]\n", filename, entry);
+
+/* start_routine (entry);*/
+ }
+
+ report_transfer_performance (data_count, start_time, end_time);
+
+ do_cleanups (old_chain);
+ timeout = oldtimeout;
+}
+
+/* Clean up when a program exits.
+
+ The program actually lives on in the remote processor's RAM, and may be
+ run again without a download. Don't leave it full of breakpoint
+ instructions. */
+
+static void
+e7000_mourn_inferior ()
+{
+ remove_breakpoints ();
+ unpush_target (&e7000_ops);
+ generic_mourn_inferior (); /* Do all the proper things now */
+}
+
+#define MAX_BREAKPOINTS 200
+#ifdef HARD_BREAKPOINTS
+#define MAX_E7000DEBUG_BREAKPOINTS (BC_BREAKPOINTS ? 5 : MAX_BREAKPOINTS)
+#else
+#define MAX_E7000DEBUG_BREAKPOINTS MAX_BREAKPOINTS
+#endif
+
+/* Since we can change to soft breakpoints dynamically, we must define
+ more than enough. Was breakaddr[MAX_E7000DEBUG_BREAKPOINTS]. */
+static CORE_ADDR breakaddr[MAX_BREAKPOINTS] = {0};
+
+static int
+e7000_insert_breakpoint (addr, shadow)
+ CORE_ADDR addr;
+ unsigned char *shadow;
+{
+ int i;
+ char buf[200];
+#if 0
+ static char nop[2] = NOP;
+#endif
+
+ for (i = 0; i <= MAX_E7000DEBUG_BREAKPOINTS; i++)
+ if (breakaddr[i] == 0)
+ {
+ breakaddr[i] = addr;
+ /* Save old contents, and insert a nop in the space */
+#ifdef HARD_BREAKPOINTS
+ if (BC_BREAKPOINTS)
+ {
+ sprintf (buf, "BC%d A=%x\r", i+1, addr);
+ puts_e7000debug (buf);
+ }
+ else
+ {
+ sprintf (buf, "B %x\r", addr);
+ puts_e7000debug (buf);
+ }
+#else
+#if 0
+ e7000_read_inferior_memory (addr, shadow, 2);
+ e7000_write_inferior_memory (addr, nop, 2);
+#endif
+
+ sprintf (buf, "B %x\r", addr);
+ puts_e7000debug (buf);
+#endif
+ expect_prompt ();
+ return 0;
+ }
+
+ error ("Too many breakpoints ( > %d) for the E7000\n",
+ MAX_E7000DEBUG_BREAKPOINTS);
+ return 1;
+}
+
+static int
+e7000_remove_breakpoint (addr, shadow)
+ CORE_ADDR addr;
+ unsigned char *shadow;
+{
+ int i;
+ char buf[200];
+
+ for (i = 0; i < MAX_E7000DEBUG_BREAKPOINTS; i++)
+ if (breakaddr[i] == addr)
+ {
+ breakaddr[i] = 0;
+#ifdef HARD_BREAKPOINTS
+ if (BC_BREAKPOINTS)
+ {
+ sprintf (buf, "BC%d - \r", i+1);
+ puts_e7000debug (buf);
+ }
+ else
+ {
+ sprintf (buf, "B - %x\r", addr);
+ puts_e7000debug (buf);
+ }
+ expect_prompt ();
+#else
+ sprintf (buf, "B - %x\r", addr);
+ puts_e7000debug (buf);
+ expect_prompt ();
+
+#if 0
+ /* Replace the insn under the break */
+ e7000_write_inferior_memory (addr, shadow, 2);
+#endif
+#endif
+
+ return 0;
+ }
+
+ warning ("Can't find breakpoint associated with 0x%x\n", addr);
+ return 1;
+}
+
+/* Put a command string, in args, out to STDBUG. Output from STDBUG
+ is placed on the users terminal until the prompt is seen. */
+
+static void
+e7000_command (args, fromtty)
+ char *args;
+ int fromtty;
+{
+ /* FIXME: arbitrary limit on length of args. */
+ char buf[200];
+
+ echo = 0;
+
+ if (!e7000_desc)
+ error ("e7000 target not open.");
+ if (!args)
+ {
+ puts_e7000debug ("\r");
+ }
+ else
+ {
+ sprintf (buf, "%s\r", args);
+ puts_e7000debug (buf);
+ }
+
+ echo++;
+ ctrl_c = 2;
+ expect_full_prompt ();
+ echo--;
+ ctrl_c = 0;
+ printf_unfiltered ("\n");
+
+ /* Who knows what the command did... */
+ registers_changed ();
+}
+
+
+static void
+e7000_drain_command (args, fromtty)
+ char *args;
+ int fromtty;
+
+{
+ int c;
+
+ puts_e7000debug("end\r");
+ putchar_e7000 (CTRLC);
+
+ while ((c = readchar (1) != -1))
+ {
+ if (quit_flag)
+ {
+ putchar_e7000(CTRLC);
+ quit_flag = 0;
+ }
+ if (c > ' ' && c < 127)
+ printf_unfiltered ("%c", c & 0xff);
+ else
+ printf_unfiltered ("<%x>", c & 0xff);
+ }
+}
+
+#define NITEMS 7
+
+static int
+why_stop ()
+{
+ static char *strings[NITEMS] = {
+ "STEP NORMAL",
+ "BREAK POINT",
+ "BREAK KEY",
+ "BREAK CONDI",
+ "CYCLE ACCESS",
+ "ILLEGAL INSTRUCTION",
+ "WRITE PROTECT",
+ };
+ char *p[NITEMS];
+ int c;
+ int i;
+
+ for (i = 0; i < NITEMS; ++i)
+ p[i] = strings[i];
+
+ c = gch ();
+ while (1)
+ {
+ for (i = 0; i < NITEMS; i++)
+ {
+ if (c == *(p[i]))
+ {
+ p[i]++;
+ if (*(p[i]) == 0)
+ {
+ /* found one of the choices */
+ return i;
+ }
+ }
+ else
+ p[i] = strings[i];
+ }
+
+ c = gch ();
+ }
+}
+
+/* Suck characters, if a string match, then return the strings index
+ otherwise echo them. */
+
+int
+expect_n (strings)
+char **strings;
+{
+ char *(ptr[10]);
+ int n;
+ int c;
+ char saveaway[100];
+ char *buffer = saveaway;
+ /* Count number of expect strings */
+
+ for (n = 0; strings[n]; n++)
+ {
+ ptr[n] = strings[n];
+ }
+
+ while (1)
+ {
+ int i;
+ int gotone = 0;
+
+ c = readchar (1);
+ if (c == -1)
+ {
+ printf_unfiltered ("[waiting for e7000...]\n");
+ }
+#ifdef __GO32__
+ if (kbhit ())
+ {
+ int k = getkey();
+
+ if (k == 1)
+ quit_flag = 1;
+ }
+#endif
+ if (quit_flag)
+ {
+ putchar_e7000 (CTRLC); /* interrupt the running program */
+ quit_flag = 0;
+ }
+
+ for (i = 0; i < n; i++)
+ {
+ if (c == ptr[i][0])
+ {
+ ptr[i]++;
+ if (ptr[i][0] == 0)
+ {
+ /* Gone all the way */
+ return i;
+ }
+ gotone = 1;
+ }
+ else
+ {
+ ptr[i] = strings[i];
+ }
+ }
+
+ if (gotone)
+ {
+ /* Save it up incase we find that there was no match */
+ *buffer ++ = c;
+ }
+ else
+ {
+ if (buffer != saveaway)
+ {
+ *buffer++ = 0;
+ printf_unfiltered ("%s", buffer);
+ buffer = saveaway;
+ }
+ if (c != -1)
+ {
+ putchar_unfiltered (c);
+ gdb_flush (gdb_stdout);
+ }
+ }
+ }
+}
+
+/* We subtract two from the pc here rather than use
+ DECR_PC_AFTER_BREAK since the e7000 doesn't always add two to the
+ pc, and the simulators never do. */
+
+static void
+sub2_from_pc ()
+{
+ char buf[4];
+ char buf2[200];
+
+ store_signed_integer (buf,
+ REGISTER_RAW_SIZE(PC_REGNUM),
+ read_register (PC_REGNUM) -2);
+ supply_register (PC_REGNUM, buf);
+ sprintf (buf2, ".PC %x\r", read_register (PC_REGNUM));
+ puts_e7000debug (buf2);
+}
+
+#define WAS_SLEEP 0
+#define WAS_INT 1
+#define WAS_RUNNING 2
+#define WAS_OTHER 3
+
+static char *estrings[] = {
+ "** SLEEP",
+ "BREAK !",
+ "** PC",
+ "PC",
+ NULL
+};
+
+/* Wait until the remote machine stops, then return, storing status in
+ STATUS just as `wait' would. */
+
+static int
+e7000_wait (pid, status)
+ int pid;
+ struct target_waitstatus *status;
+{
+ int stop_reason;
+ int regno;
+ int running_count = 0;
+ int had_sleep = 0;
+ int loop = 1;
+ char *wanted_nopc;
+
+ /* Then echo chars until PC= string seen */
+ gch (); /* Drop cr */
+ gch (); /* and space */
+
+ while (loop)
+ {
+ switch (expect_n (estrings))
+ {
+ case WAS_OTHER:
+ /* how did this happen ? */
+ loop = 0;
+ break;
+ case WAS_SLEEP:
+ had_sleep = 1;
+ putchar_e7000 (CTRLC);
+ loop = 0;
+ break;
+ case WAS_INT:
+ loop = 0;
+ break;
+ case WAS_RUNNING:
+ running_count++;
+ if (running_count == 20)
+ {
+ printf_unfiltered ("[running...]\n");
+ running_count = 0;
+ }
+ break;
+ default:
+ /* error? */
+ break;
+ }
+ }
+
+ /* Skip till the PC= */
+ expect ("=");
+
+#ifdef GDB_TARGET_IS_SH
+ wanted_nopc = want_nopc;
+ if (TARGET_ARCHITECTURE->arch == bfd_arch_sh)
+ switch (TARGET_ARCHITECTURE->mach)
+ {
+ case bfd_mach_sh3:
+ case bfd_mach_sh3e:
+ wanted_nopc = want_sh3_nopc;
+ }
+#else
+ if (h8300smode)
+ wanted_nopc = want_nopc_h8300s;
+ else
+ wanted_nopc = want_nopc_h8300h;
+#endif
+ fetch_regs_from_dump (gch, wanted_nopc);
+
+ /* And supply the extra ones the simulator uses */
+ for (regno = NUM_REALREGS; regno < NUM_REGS; regno++)
+ {
+ int buf = 0;
+ supply_register (regno, (char *) &buf);
+ }
+
+ stop_reason = why_stop ();
+ expect_full_prompt ();
+
+ status->kind = TARGET_WAITKIND_STOPPED;
+ status->value.sig = TARGET_SIGNAL_TRAP;
+
+ switch (stop_reason)
+ {
+ case 1: /* Breakpoint */
+ write_pc (read_pc ()); /* PC is always off by 2 for breakpoints */
+ status->value.sig = TARGET_SIGNAL_TRAP;
+ break;
+ case 0: /* Single step */
+ status->value.sig = TARGET_SIGNAL_TRAP;
+ break;
+ case 2: /* Interrupt */
+ if (had_sleep)
+ {
+ status->value.sig = TARGET_SIGNAL_TRAP;
+ sub2_from_pc ();
+ }
+ else
+ {
+ status->value.sig = TARGET_SIGNAL_INT;
+ }
+ break;
+ case 3:
+ break;
+ case 4:
+ printf_unfiltered ("a cycle address error?\n");
+ status->value.sig = TARGET_SIGNAL_UNKNOWN;
+ break;
+ case 5:
+ status->value.sig = TARGET_SIGNAL_ILL;
+ break;
+ case 6:
+ status->value.sig = TARGET_SIGNAL_SEGV;
+ break;
+ case 7: /* Anything else (NITEMS + 1) */
+ printf_unfiltered ("a write protect error?\n");
+ status->value.sig = TARGET_SIGNAL_UNKNOWN;
+ break;
+ default:
+ /* Get the user's attention - this should never happen. */
+ abort ();
+ }
+
+ return 0;
+}
+
+/* Stop the running program. */
+
+static void
+e7000_stop ()
+{
+ /* Sending a ^C is supposed to stop the running program. */
+ putchar_e7000 (CTRLC);
+}
+
+/* Define the target subroutine names. */
+
+struct target_ops e7000_ops ;
+
+static void
+init_e7000_ops(void)
+{
+ e7000_ops.to_shortname = "e7000";
+ e7000_ops.to_longname = "Remote Hitachi e7000 target";
+ e7000_ops.to_doc = "Use a remote Hitachi e7000 ICE connected by a serial line;\n\
+or a network connection.\n\
+Arguments are the name of the device for the serial line,\n\
+the speed to connect at in bits per second.\n\
+eg\n\
+target e7000 /dev/ttya 9600\n\
+target e7000 foobar" ;
+ e7000_ops.to_open = e7000_open;
+ e7000_ops.to_close = e7000_close;
+ e7000_ops.to_attach = 0;
+ e7000_ops.to_post_attach = NULL;
+ e7000_ops.to_require_attach = NULL;
+ e7000_ops.to_detach = e7000_detach;
+ e7000_ops.to_require_detach = NULL;
+ e7000_ops.to_resume = e7000_resume;
+ e7000_ops.to_wait = e7000_wait;
+ e7000_ops.to_post_wait = NULL;
+ e7000_ops.to_fetch_registers = e7000_fetch_register;
+ e7000_ops.to_store_registers = e7000_store_register;
+ e7000_ops.to_prepare_to_store = e7000_prepare_to_store;
+ e7000_ops.to_xfer_memory = e7000_xfer_inferior_memory;
+ e7000_ops.to_files_info = e7000_files_info;
+ e7000_ops.to_insert_breakpoint = e7000_insert_breakpoint;
+ e7000_ops.to_remove_breakpoint = e7000_remove_breakpoint;
+ e7000_ops.to_terminal_init = 0;
+ e7000_ops.to_terminal_inferior = 0;
+ e7000_ops.to_terminal_ours_for_output = 0;
+ e7000_ops.to_terminal_ours = 0;
+ e7000_ops.to_terminal_info = 0;
+ e7000_ops.to_kill = e7000_kill;
+ e7000_ops.to_load = e7000_load;
+ e7000_ops.to_lookup_symbol = 0;
+ e7000_ops.to_create_inferior = e7000_create_inferior;
+ e7000_ops.to_post_startup_inferior = NULL;
+ e7000_ops.to_acknowledge_created_inferior = NULL;
+ e7000_ops.to_clone_and_follow_inferior = NULL;
+ e7000_ops.to_post_follow_inferior_by_clone = NULL;
+ e7000_ops.to_insert_fork_catchpoint = NULL;
+ e7000_ops.to_remove_fork_catchpoint = NULL;
+ e7000_ops.to_insert_vfork_catchpoint = NULL;
+ e7000_ops.to_remove_vfork_catchpoint = NULL;
+ e7000_ops.to_has_forked = NULL;
+ e7000_ops.to_has_vforked = NULL;
+ e7000_ops.to_can_follow_vfork_prior_to_exec = NULL;
+ e7000_ops.to_post_follow_vfork = NULL;
+ e7000_ops.to_insert_exec_catchpoint = NULL;
+ e7000_ops.to_remove_exec_catchpoint = NULL;
+ e7000_ops.to_has_execd = NULL;
+ e7000_ops.to_reported_exec_events_per_exec_call = NULL;
+ e7000_ops.to_has_exited = NULL;
+ e7000_ops.to_mourn_inferior = e7000_mourn_inferior;
+ e7000_ops.to_can_run = 0;
+ e7000_ops.to_notice_signals = 0;
+ e7000_ops.to_thread_alive = 0;
+ e7000_ops.to_stop = e7000_stop;
+ e7000_ops.to_pid_to_exec_file = NULL;
+ e7000_ops.to_core_file_to_sym_file = NULL;
+ e7000_ops.to_stratum = process_stratum;
+ e7000_ops.DONT_USE = 0;
+ e7000_ops.to_has_all_memory = 1;
+ e7000_ops.to_has_memory = 1;
+ e7000_ops.to_has_stack = 1;
+ e7000_ops.to_has_registers = 1;
+ e7000_ops.to_has_execution = 1;
+ e7000_ops.to_sections = 0;
+ e7000_ops.to_sections_end = 0;
+ e7000_ops.to_magic = OPS_MAGIC;
+};
+
+void
+_initialize_remote_e7000 ()
+{
+ init_e7000_ops() ;
+ add_target (&e7000_ops);
+
+ add_com ("e7000", class_obscure, e7000_command,
+ "Send a command to the e7000 monitor.");
+
+ add_com ("ftplogin", class_obscure, e7000_login_command,
+ "Login to machine and change to directory.");
+
+ add_com ("ftpload", class_obscure, e7000_ftp_command,
+ "Fetch and load a file from previously described place.");
+
+ add_com ("drain", class_obscure, e7000_drain_command,
+ "Drain pending e7000 text buffers.");
+
+ add_show_from_set (add_set_cmd ("usehardbreakpoints", no_class,
+ var_integer, (char *)&use_hard_breakpoints,
+ "Set use of hardware breakpoints for all breakpoints.\n", &setlist),
+ &showlist);
+}
diff --git a/gdb/remote-eb.c b/gdb/remote-eb.c
new file mode 100644
index 00000000000..d3a3c4169c1
--- /dev/null
+++ b/gdb/remote-eb.c
@@ -0,0 +1,1056 @@
+/* Remote debugging interface for AMD 29000 EBMON on IBM PC, for GDB.
+ Copyright 1990, 1991, 1992 Free Software Foundation, Inc.
+ Contributed by Cygnus Support. Written by Jim Kingdon for Cygnus.
+
+This file is part of GDB.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* This is like remote.c but is for an esoteric situation--
+ having a a29k board in a PC hooked up to a unix machine with
+ a serial line, and running ctty com1 on the PC, through which
+ the unix machine can run ebmon. Not to mention that the PC
+ has PC/NFS, so it can access the same executables that gdb can,
+ over the net in real time. */
+
+#include "defs.h"
+#include "gdb_string.h"
+
+#include "inferior.h"
+#include "bfd.h"
+#include "symfile.h"
+#include "wait.h"
+#include "value.h"
+#include <ctype.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <errno.h>
+#include "terminal.h"
+#include "target.h"
+#include "gdbcore.h"
+
+extern struct target_ops eb_ops; /* Forward declaration */
+
+static void eb_close();
+
+#define LOG_FILE "eb.log"
+#if defined (LOG_FILE)
+FILE *log_file;
+#endif
+
+static int timeout = 24;
+
+/* Descriptor for I/O to remote machine. Initialize it to -1 so that
+ eb_open knows that we don't have a file open when the program
+ starts. */
+int eb_desc = -1;
+
+/* stream which is fdopen'd from eb_desc. Only valid when
+ eb_desc != -1. */
+FILE *eb_stream;
+
+/* Read a character from the remote system, doing all the fancy
+ timeout stuff. */
+static int
+readchar ()
+{
+ char buf;
+
+ buf = '\0';
+#ifdef HAVE_TERMIO
+ /* termio does the timeout for us. */
+ read (eb_desc, &buf, 1);
+#else
+ alarm (timeout);
+ if (read (eb_desc, &buf, 1) < 0)
+ {
+ if (errno == EINTR)
+ error ("Timeout reading from remote system.");
+ else
+ perror_with_name ("remote");
+ }
+ alarm (0);
+#endif
+
+ if (buf == '\0')
+ error ("Timeout reading from remote system.");
+#if defined (LOG_FILE)
+ putc (buf & 0x7f, log_file);
+#endif
+ return buf & 0x7f;
+}
+
+/* Keep discarding input from the remote system, until STRING is found.
+ Let the user break out immediately. */
+static void
+expect (string)
+ char *string;
+{
+ char *p = string;
+
+ immediate_quit = 1;
+ while (1)
+ {
+ if (readchar() == *p)
+ {
+ p++;
+ if (*p == '\0')
+ {
+ immediate_quit = 0;
+ return;
+ }
+ }
+ else
+ p = string;
+ }
+}
+
+/* Keep discarding input until we see the ebmon prompt.
+
+ The convention for dealing with the prompt is that you
+ o give your command
+ o *then* wait for the prompt.
+
+ Thus the last thing that a procedure does with the serial line
+ will be an expect_prompt(). Exception: eb_resume does not
+ wait for the prompt, because the terminal is being handed over
+ to the inferior. However, the next thing which happens after that
+ is a eb_wait which does wait for the prompt.
+ Note that this includes abnormal exit, e.g. error(). This is
+ necessary to prevent getting into states from which we can't
+ recover. */
+static void
+expect_prompt ()
+{
+#if defined (LOG_FILE)
+ /* This is a convenient place to do this. The idea is to do it often
+ enough that we never lose much data if we terminate abnormally. */
+ fflush (log_file);
+#endif
+ expect ("\n# ");
+}
+
+/* Get a hex digit from the remote system & return its value.
+ If ignore_space is nonzero, ignore spaces (not newline, tab, etc). */
+static int
+get_hex_digit (ignore_space)
+ int ignore_space;
+{
+ int ch;
+ while (1)
+ {
+ ch = readchar ();
+ if (ch >= '0' && ch <= '9')
+ return ch - '0';
+ else if (ch >= 'A' && ch <= 'F')
+ return ch - 'A' + 10;
+ else if (ch >= 'a' && ch <= 'f')
+ return ch - 'a' + 10;
+ else if (ch == ' ' && ignore_space)
+ ;
+ else
+ {
+ expect_prompt ();
+ error ("Invalid hex digit from remote system.");
+ }
+ }
+}
+
+/* Get a byte from eb_desc and put it in *BYT. Accept any number
+ leading spaces. */
+static void
+get_hex_byte (byt)
+ char *byt;
+{
+ int val;
+
+ val = get_hex_digit (1) << 4;
+ val |= get_hex_digit (0);
+ *byt = val;
+}
+
+/* Get N 32-bit words from remote, each preceded by a space,
+ and put them in registers starting at REGNO. */
+static void
+get_hex_regs (n, regno)
+ int n;
+ int regno;
+{
+ long val;
+ int i;
+
+ for (i = 0; i < n; i++)
+ {
+ int j;
+
+ val = 0;
+ for (j = 0; j < 8; j++)
+ val = (val << 4) + get_hex_digit (j == 0);
+ supply_register (regno++, (char *) &val);
+ }
+}
+
+/* Called when SIGALRM signal sent due to alarm() timeout. */
+#ifndef HAVE_TERMIO
+
+#ifndef __STDC__
+#define volatile /**/
+#endif
+volatile int n_alarms;
+
+void
+eb_timer ()
+{
+#if 0
+ if (kiodebug)
+ printf ("eb_timer called\n");
+#endif
+ n_alarms++;
+}
+#endif
+
+/* malloc'd name of the program on the remote system. */
+static char *prog_name = NULL;
+
+/* Nonzero if we have loaded the file ("yc") and not yet issued a "gi"
+ command. "gi" is supposed to happen exactly once for each "yc". */
+static int need_gi = 0;
+
+/* Number of SIGTRAPs we need to simulate. That is, the next
+ NEED_ARTIFICIAL_TRAP calls to eb_wait should just return
+ SIGTRAP without actually waiting for anything. */
+
+static int need_artificial_trap = 0;
+
+/* This is called not only when we first attach, but also when the
+ user types "run" after having attached. */
+static void
+eb_create_inferior (execfile, args, env)
+ char *execfile;
+ char *args;
+ char **env;
+{
+ int entry_pt;
+
+ if (args && *args)
+ error ("Can't pass arguments to remote EBMON process");
+
+ if (execfile == 0 || exec_bfd == 0)
+ error ("No executable file specified");
+
+ entry_pt = (int) bfd_get_start_address (exec_bfd);
+
+ {
+ /* OK, now read in the file. Y=read, C=COFF, D=no symbols
+ 0=start address, %s=filename. */
+
+ fprintf (eb_stream, "YC D,0:%s", prog_name);
+
+ if (args != NULL)
+ fprintf(eb_stream, " %s", args);
+
+ fprintf (eb_stream, "\n");
+ fflush (eb_stream);
+
+ expect_prompt ();
+
+ need_gi = 1;
+ }
+
+/* The "process" (board) is already stopped awaiting our commands, and
+ the program is already downloaded. We just set its PC and go. */
+
+ clear_proceed_status ();
+
+ /* Tell wait_for_inferior that we've started a new process. */
+ init_wait_for_inferior ();
+
+ /* Set up the "saved terminal modes" of the inferior
+ based on what modes we are starting it with. */
+ target_terminal_init ();
+
+ /* Install inferior's terminal modes. */
+ target_terminal_inferior ();
+
+ /* insert_step_breakpoint (); FIXME, do we need this? */
+ proceed ((CORE_ADDR)entry_pt, TARGET_SIGNAL_DEFAULT, 0); /* Let 'er rip... */
+}
+
+/* Translate baud rates from integers to damn B_codes. Unix should
+ have outgrown this crap years ago, but even POSIX wouldn't buck it. */
+
+#ifndef B19200
+#define B19200 EXTA
+#endif
+#ifndef B38400
+#define B38400 EXTB
+#endif
+
+struct {int rate, damn_b;} baudtab[] = {
+ {0, B0},
+ {50, B50},
+ {75, B75},
+ {110, B110},
+ {134, B134},
+ {150, B150},
+ {200, B200},
+ {300, B300},
+ {600, B600},
+ {1200, B1200},
+ {1800, B1800},
+ {2400, B2400},
+ {4800, B4800},
+ {9600, B9600},
+ {19200, B19200},
+ {38400, B38400},
+ {-1, -1},
+};
+
+int damn_b (rate)
+ int rate;
+{
+ int i;
+
+ for (i = 0; baudtab[i].rate != -1; i++)
+ if (rate == baudtab[i].rate) return baudtab[i].damn_b;
+ return B38400; /* Random */
+}
+
+
+/* Open a connection to a remote debugger.
+ NAME is the filename used for communication, then a space,
+ then the name of the program as we should name it to EBMON. */
+
+static int baudrate = 9600;
+static char *dev_name;
+void
+eb_open (name, from_tty)
+ char *name;
+ int from_tty;
+{
+ TERMINAL sg;
+
+ char *p;
+
+ target_preopen (from_tty);
+
+ /* Find the first whitespace character, it separates dev_name from
+ prog_name. */
+ if (name == 0)
+ goto erroid;
+
+ for (p = name;
+ *p != '\0' && !isspace (*p); p++)
+ ;
+ if (*p == '\0')
+erroid:
+ error ("\
+Please include the name of the device for the serial port,\n\
+the baud rate, and the name of the program to run on the remote system.");
+ dev_name = alloca (p - name + 1);
+ strncpy (dev_name, name, p - name);
+ dev_name[p - name] = '\0';
+
+ /* Skip over the whitespace after dev_name */
+ for (; isspace (*p); p++)
+ /*EMPTY*/;
+
+ if (1 != sscanf (p, "%d ", &baudrate))
+ goto erroid;
+
+ /* Skip the number and then the spaces */
+ for (; isdigit (*p); p++)
+ /*EMPTY*/;
+ for (; isspace (*p); p++)
+ /*EMPTY*/;
+
+ if (prog_name != NULL)
+ free (prog_name);
+ prog_name = savestring (p, strlen (p));
+
+ eb_close (0);
+
+ eb_desc = open (dev_name, O_RDWR);
+ if (eb_desc < 0)
+ perror_with_name (dev_name);
+ ioctl (eb_desc, TIOCGETP, &sg);
+#ifdef HAVE_TERMIO
+ sg.c_cc[VMIN] = 0; /* read with timeout. */
+ sg.c_cc[VTIME] = timeout * 10;
+ sg.c_lflag &= ~(ICANON | ECHO);
+ sg.c_cflag = (sg.c_cflag & ~CBAUD) | damn_b (baudrate);
+#else
+ sg.sg_ispeed = damn_b (baudrate);
+ sg.sg_ospeed = damn_b (baudrate);
+ sg.sg_flags |= RAW | ANYP;
+ sg.sg_flags &= ~ECHO;
+#endif
+
+ ioctl (eb_desc, TIOCSETP, &sg);
+ eb_stream = fdopen (eb_desc, "r+");
+
+ push_target (&eb_ops);
+ if (from_tty)
+ printf ("Remote %s debugging %s using %s\n", target_shortname,
+ prog_name, dev_name);
+
+#ifndef HAVE_TERMIO
+#ifndef NO_SIGINTERRUPT
+ /* Cause SIGALRM's to make reads fail with EINTR instead of resuming
+ the read. */
+ if (siginterrupt (SIGALRM, 1) != 0)
+ perror ("eb_open: error in siginterrupt");
+#endif
+
+ /* Set up read timeout timer. */
+ if ((void (*)) signal (SIGALRM, eb_timer) == (void (*)) -1)
+ perror ("eb_open: error in signal");
+#endif
+
+#if defined (LOG_FILE)
+ log_file = fopen (LOG_FILE, "w");
+ if (log_file == NULL)
+ perror_with_name (LOG_FILE);
+#endif
+
+ /* Hello? Are you there? */
+ write (eb_desc, "\n", 1);
+
+ expect_prompt ();
+}
+
+/* Close out all files and local state before this target loses control. */
+
+static void
+eb_close (quitting)
+ int quitting;
+{
+
+ /* Due to a bug in Unix, fclose closes not only the stdio stream,
+ but also the file descriptor. So we don't actually close
+ eb_desc. */
+ if (eb_stream)
+ fclose (eb_stream); /* This also closes eb_desc */
+ if (eb_desc >= 0)
+ /* close (eb_desc); */
+
+ /* Do not try to close eb_desc again, later in the program. */
+ eb_stream = NULL;
+ eb_desc = -1;
+
+#if defined (LOG_FILE)
+ if (log_file) {
+ if (ferror (log_file))
+ printf ("Error writing log file.\n");
+ if (fclose (log_file) != 0)
+ printf ("Error closing log file.\n");
+ }
+#endif
+}
+
+/* Terminate the open connection to the remote debugger.
+ Use this when you want to detach and do something else
+ with your gdb. */
+void
+eb_detach (from_tty)
+ int from_tty;
+{
+ pop_target(); /* calls eb_close to do the real work */
+ if (from_tty)
+ printf ("Ending remote %s debugging\n", target_shortname);
+}
+
+/* Tell the remote machine to resume. */
+
+void
+eb_resume (pid, step, sig)
+ int pid, step;
+ enum target_signal sig;
+{
+ if (step)
+ {
+ write (eb_desc, "t 1,s\n", 6);
+ /* Wait for the echo. */
+ expect ("t 1,s\r");
+ /* Then comes a line containing the instruction we stepped to. */
+ expect ("\n@");
+ /* Then we get the prompt. */
+ expect_prompt ();
+
+ /* Force the next eb_wait to return a trap. Not doing anything
+ about I/O from the target means that the user has to type
+ "continue" to see any. This should be fixed. */
+ need_artificial_trap = 1;
+ }
+ else
+ {
+ if (need_gi)
+ {
+ need_gi = 0;
+ write (eb_desc, "gi\n", 3);
+
+ /* Swallow the echo of "gi". */
+ expect ("gi\r");
+ }
+ else
+ {
+ write (eb_desc, "GR\n", 3);
+ /* Swallow the echo. */
+ expect ("GR\r");
+ }
+ }
+}
+
+/* Wait until the remote machine stops, then return,
+ storing status in STATUS just as `wait' would. */
+
+int
+eb_wait (status)
+ struct target_waitstatus *status;
+{
+ /* Strings to look for. '?' means match any single character.
+ Note that with the algorithm we use, the initial character
+ of the string cannot recur in the string, or we will not
+ find some cases of the string in the input. */
+
+ static char bpt[] = "Invalid interrupt taken - #0x50 - ";
+ /* It would be tempting to look for "\n[__exit + 0x8]\n"
+ but that requires loading symbols with "yc i" and even if
+ we did do that we don't know that the file has symbols. */
+ static char exitmsg[] = "\n@????????I JMPTI GR121,LR0";
+ char *bp = bpt;
+ char *ep = exitmsg;
+
+ /* Large enough for either sizeof (bpt) or sizeof (exitmsg) chars. */
+ char swallowed[50];
+ /* Current position in swallowed. */
+ char *swallowed_p = swallowed;
+
+ int ch;
+ int ch_handled;
+
+ int old_timeout = timeout;
+
+ status->kind = TARGET_WAITKIND_EXITED;
+ status->value.integer = 0;
+
+ if (need_artificial_trap != 0)
+ {
+ status->kind = TARGET_WAITKIND_STOPPED;
+ status->value.sig = TARGET_SIGNAL_TRAP;
+ need_artificial_trap--;
+ return 0;
+ }
+
+ timeout = 0; /* Don't time out -- user program is running. */
+ while (1)
+ {
+ ch_handled = 0;
+ ch = readchar ();
+ if (ch == *bp)
+ {
+ bp++;
+ if (*bp == '\0')
+ break;
+ ch_handled = 1;
+
+ *swallowed_p++ = ch;
+ }
+ else
+ bp = bpt;
+
+ if (ch == *ep || *ep == '?')
+ {
+ ep++;
+ if (*ep == '\0')
+ break;
+
+ if (!ch_handled)
+ *swallowed_p++ = ch;
+ ch_handled = 1;
+ }
+ else
+ ep = exitmsg;
+
+ if (!ch_handled)
+ {
+ char *p;
+
+ /* Print out any characters which have been swallowed. */
+ for (p = swallowed; p < swallowed_p; ++p)
+ putc (*p, stdout);
+ swallowed_p = swallowed;
+
+ putc (ch, stdout);
+ }
+ }
+ expect_prompt ();
+ if (*bp== '\0')
+ {
+ status->kind = TARGET_WAITKIND_STOPPED;
+ status->value.sig = TARGET_SIGNAL_TRAP;
+ }
+ else
+ {
+ status->kind = TARGET_WAITKIND_EXITED;
+ status->value.integer = 0;
+ }
+ timeout = old_timeout;
+
+ return 0;
+}
+
+/* Return the name of register number REGNO
+ in the form input and output by EBMON.
+
+ Returns a pointer to a static buffer containing the answer. */
+static char *
+get_reg_name (regno)
+ int regno;
+{
+ static char buf[80];
+ if (regno >= GR96_REGNUM && regno < GR96_REGNUM + 32)
+ sprintf (buf, "GR%03d", regno - GR96_REGNUM + 96);
+ else if (regno >= LR0_REGNUM && regno < LR0_REGNUM + 128)
+ sprintf (buf, "LR%03d", regno - LR0_REGNUM);
+ else if (regno == Q_REGNUM)
+ strcpy (buf, "SR131");
+ else if (regno >= BP_REGNUM && regno <= CR_REGNUM)
+ sprintf (buf, "SR%03d", regno - BP_REGNUM + 133);
+ else if (regno == ALU_REGNUM)
+ strcpy (buf, "SR132");
+ else if (regno >= IPC_REGNUM && regno <= IPB_REGNUM)
+ sprintf (buf, "SR%03d", regno - IPC_REGNUM + 128);
+ else if (regno >= VAB_REGNUM && regno <= LRU_REGNUM)
+ sprintf (buf, "SR%03d", regno - VAB_REGNUM);
+ else if (regno == GR1_REGNUM)
+ strcpy (buf, "GR001");
+ return buf;
+}
+
+/* Read the remote registers into the block REGS. */
+
+static void
+eb_fetch_registers ()
+{
+ int reg_index;
+ int regnum_index;
+ char tempbuf[10];
+ int i;
+
+#if 0
+ /* This should not be necessary, because one is supposed to read the
+ registers only when the inferior is stopped (at least with
+ ptrace() and why not make it the same for remote?). */
+ /* ^A is the "normal character" used to make sure we are talking to EBMON
+ and not to the program being debugged. */
+ write (eb_desc, "\001\n");
+ expect_prompt ();
+#endif
+
+ write (eb_desc, "dw gr96,gr127\n", 14);
+ for (reg_index = 96, regnum_index = GR96_REGNUM;
+ reg_index < 128;
+ reg_index += 4, regnum_index += 4)
+ {
+ sprintf (tempbuf, "GR%03d ", reg_index);
+ expect (tempbuf);
+ get_hex_regs (4, regnum_index);
+ expect ("\n");
+ }
+
+ for (i = 0; i < 128; i += 32)
+ {
+ /* The PC has a tendency to hang if we get these
+ all in one fell swoop ("dw lr0,lr127"). */
+ sprintf (tempbuf, "dw lr%d\n", i);
+ write (eb_desc, tempbuf, strlen (tempbuf));
+ for (reg_index = i, regnum_index = LR0_REGNUM + i;
+ reg_index < i + 32;
+ reg_index += 4, regnum_index += 4)
+ {
+ sprintf (tempbuf, "LR%03d ", reg_index);
+ expect (tempbuf);
+ get_hex_regs (4, regnum_index);
+ expect ("\n");
+ }
+ }
+
+ write (eb_desc, "dw sr133,sr133\n", 15);
+ expect ("SR133 ");
+ get_hex_regs (1, BP_REGNUM);
+ expect ("\n");
+
+ write (eb_desc, "dw sr134,sr134\n", 15);
+ expect ("SR134 ");
+ get_hex_regs (1, FC_REGNUM);
+ expect ("\n");
+
+ write (eb_desc, "dw sr135,sr135\n", 15);
+ expect ("SR135 ");
+ get_hex_regs (1, CR_REGNUM);
+ expect ("\n");
+
+ write (eb_desc, "dw sr131,sr131\n", 15);
+ expect ("SR131 ");
+ get_hex_regs (1, Q_REGNUM);
+ expect ("\n");
+
+ write (eb_desc, "dw sr0,sr14\n", 12);
+ for (reg_index = 0, regnum_index = VAB_REGNUM;
+ regnum_index <= LRU_REGNUM;
+ regnum_index += 4, reg_index += 4)
+ {
+ sprintf (tempbuf, "SR%03d ", reg_index);
+ expect (tempbuf);
+ get_hex_regs (reg_index == 12 ? 3 : 4, regnum_index);
+ expect ("\n");
+ }
+
+ /* There doesn't seem to be any way to get these. */
+ {
+ int val = -1;
+ supply_register (FPE_REGNUM, (char *) &val);
+ supply_register (INTE_REGNUM, (char *) &val);
+ supply_register (FPS_REGNUM, (char *) &val);
+ supply_register (EXO_REGNUM, (char *) &val);
+ }
+
+ write (eb_desc, "dw gr1,gr1\n", 11);
+ expect ("GR001 ");
+ get_hex_regs (1, GR1_REGNUM);
+ expect_prompt ();
+}
+
+/* Fetch register REGNO, or all registers if REGNO is -1.
+ Returns errno value. */
+void
+eb_fetch_register (regno)
+ int regno;
+{
+ if (regno == -1)
+ eb_fetch_registers ();
+ else
+ {
+ char *name = get_reg_name (regno);
+ fprintf (eb_stream, "dw %s,%s\n", name, name);
+ expect (name);
+ expect (" ");
+ get_hex_regs (1, regno);
+ expect_prompt ();
+ }
+ return;
+}
+
+/* Store the remote registers from the contents of the block REGS. */
+
+static void
+eb_store_registers ()
+{
+ int i, j;
+ fprintf (eb_stream, "s gr1,%x\n", read_register (GR1_REGNUM));
+ expect_prompt ();
+
+ for (j = 0; j < 32; j += 16)
+ {
+ fprintf (eb_stream, "s gr%d,", j + 96);
+ for (i = 0; i < 15; ++i)
+ fprintf (eb_stream, "%x,", read_register (GR96_REGNUM + j + i));
+ fprintf (eb_stream, "%x\n", read_register (GR96_REGNUM + j + 15));
+ expect_prompt ();
+ }
+
+ for (j = 0; j < 128; j += 16)
+ {
+ fprintf (eb_stream, "s lr%d,", j);
+ for (i = 0; i < 15; ++i)
+ fprintf (eb_stream, "%x,", read_register (LR0_REGNUM + j + i));
+ fprintf (eb_stream, "%x\n", read_register (LR0_REGNUM + j + 15));
+ expect_prompt ();
+ }
+
+ fprintf (eb_stream, "s sr133,%x,%x,%x\n", read_register (BP_REGNUM),
+ read_register (FC_REGNUM), read_register (CR_REGNUM));
+ expect_prompt ();
+ fprintf (eb_stream, "s sr131,%x\n", read_register (Q_REGNUM));
+ expect_prompt ();
+ fprintf (eb_stream, "s sr0,");
+ for (i = 0; i < 11; ++i)
+ fprintf (eb_stream, "%x,", read_register (VAB_REGNUM + i));
+ fprintf (eb_stream, "%x\n", read_register (VAB_REGNUM + 11));
+ expect_prompt ();
+}
+
+/* Store register REGNO, or all if REGNO == 0.
+ Return errno value. */
+void
+eb_store_register (regno)
+ int regno;
+{
+ if (regno == -1)
+ eb_store_registers ();
+ else
+ {
+ char *name = get_reg_name (regno);
+ fprintf (eb_stream, "s %s,%x\n", name, read_register (regno));
+ /* Setting GR1 changes the numbers of all the locals, so
+ invalidate the register cache. Do this *after* calling
+ read_register, because we want read_register to return the
+ value that write_register has just stuffed into the registers
+ array, not the value of the register fetched from the
+ inferior. */
+ if (regno == GR1_REGNUM)
+ registers_changed ();
+ expect_prompt ();
+ }
+}
+
+/* Get ready to modify the registers array. On machines which store
+ individual registers, this doesn't need to do anything. On machines
+ which store all the registers in one fell swoop, this makes sure
+ that registers contains all the registers from the program being
+ debugged. */
+
+void
+eb_prepare_to_store ()
+{
+ /* Do nothing, since we can store individual regs */
+}
+
+
+/* FIXME-someday! Merge these two. */
+int
+eb_xfer_inferior_memory (memaddr, myaddr, len, write, target)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+ int write;
+ struct target_ops *target; /* ignored */
+{
+ if (write)
+ return eb_write_inferior_memory (memaddr, myaddr, len);
+ else
+ return eb_read_inferior_memory (memaddr, myaddr, len);
+}
+
+void
+eb_files_info ()
+{
+ printf ("\tAttached to %s at %d baud and running program %s.\n",
+ dev_name, baudrate, prog_name);
+}
+
+/* Copy LEN bytes of data from debugger memory at MYADDR
+ to inferior's memory at MEMADDR. Returns length moved. */
+int
+eb_write_inferior_memory (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+{
+ int i;
+
+ for (i = 0; i < len; i++)
+ {
+ if ((i % 16) == 0)
+ fprintf (eb_stream, "sb %x,", memaddr + i);
+ if ((i % 16) == 15 || i == len - 1)
+ {
+ fprintf (eb_stream, "%x\n", ((unsigned char *)myaddr)[i]);
+ expect_prompt ();
+ }
+ else
+ fprintf (eb_stream, "%x,", ((unsigned char *)myaddr)[i]);
+ }
+ return len;
+}
+
+/* Read LEN bytes from inferior memory at MEMADDR. Put the result
+ at debugger address MYADDR. Returns length moved. */
+int
+eb_read_inferior_memory(memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+{
+ int i;
+
+ /* Number of bytes read so far. */
+ int count;
+
+ /* Starting address of this pass. */
+ unsigned long startaddr;
+
+ /* Number of bytes to read in this pass. */
+ int len_this_pass;
+
+ /* Note that this code works correctly if startaddr is just less
+ than UINT_MAX (well, really CORE_ADDR_MAX if there was such a
+ thing). That is, something like
+ eb_read_bytes (CORE_ADDR_MAX - 4, foo, 4)
+ works--it never adds len to memaddr and gets 0. */
+ /* However, something like
+ eb_read_bytes (CORE_ADDR_MAX - 3, foo, 4)
+ doesn't need to work. Detect it and give up if there's an attempt
+ to do that. */
+ if (((memaddr - 1) + len) < memaddr) {
+ errno = EIO;
+ return 0;
+ }
+
+ startaddr = memaddr;
+ count = 0;
+ while (count < len)
+ {
+ len_this_pass = 16;
+ if ((startaddr % 16) != 0)
+ len_this_pass -= startaddr % 16;
+ if (len_this_pass > (len - count))
+ len_this_pass = (len - count);
+
+ fprintf (eb_stream, "db %x,%x\n", startaddr,
+ (startaddr - 1) + len_this_pass);
+ expect ("\n");
+
+ /* Look for 8 hex digits. */
+ i = 0;
+ while (1)
+ {
+ if (isxdigit (readchar ()))
+ ++i;
+ else
+ {
+ expect_prompt ();
+ error ("Hex digit expected from remote system.");
+ }
+ if (i >= 8)
+ break;
+ }
+
+ expect (" ");
+
+ for (i = 0; i < len_this_pass; i++)
+ get_hex_byte (&myaddr[count++]);
+
+ expect_prompt ();
+
+ startaddr += len_this_pass;
+ }
+ return len;
+}
+
+static void
+eb_kill (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ return; /* Ignore attempts to kill target system */
+}
+
+/* Clean up when a program exits.
+
+ The program actually lives on in the remote processor's RAM, and may be
+ run again without a download. Don't leave it full of breakpoint
+ instructions. */
+
+void
+eb_mourn_inferior ()
+{
+ remove_breakpoints ();
+ unpush_target (&eb_ops);
+ generic_mourn_inferior (); /* Do all the proper things now */
+}
+/* Define the target subroutine names */
+
+struct target_ops eb_ops ;
+
+static void
+init_eb_ops(void)
+{
+ eb_ops.to_shortname = "amd-eb";
+ eb_ops.to_longname = "Remote serial AMD EBMON target";
+ eb_ops.to_doc = "Use a remote computer running EBMON connected by a serial line.\n\
+Arguments are the name of the device for the serial line,\n\
+the speed to connect at in bits per second, and the filename of the\n\
+executable as it exists on the remote computer. For example,\n\
+target amd-eb /dev/ttya 9600 demo",
+ eb_ops.to_open = eb_open;
+ eb_ops.to_close = eb_close;
+ eb_ops.to_attach = 0;
+ eb_ops.to_post_attach = NULL;
+ eb_ops.to_require_attach = NULL;
+ eb_ops.to_detach = eb_detach;
+ eb_ops.to_require_detach = NULL;
+ eb_ops.to_resume = eb_resume;
+ eb_ops.to_wait = eb_wait;
+ eb_ops.to_post_wait = NULL;
+ eb_ops.to_fetch_registers = eb_fetch_register;
+ eb_ops.to_store_registers = eb_store_register;
+ eb_ops.to_prepare_to_store = eb_prepare_to_store;
+ eb_ops.to_xfer_memory = eb_xfer_inferior_memory;
+ eb_ops.to_files_info = eb_files_info;
+ eb_ops.to_insert_breakpoint = 0;
+ eb_ops.to_remove_breakpoint = 0; /* Breakpoints */
+ eb_ops.to_terminal_init = 0;
+ eb_ops.to_terminal_inferior = 0;
+ eb_ops.to_terminal_ours_for_output = 0;
+ eb_ops.to_terminal_ours = 0;
+ eb_ops.to_terminal_info = 0; /* Terminal handling */
+ eb_ops.to_kill = eb_kill;
+ eb_ops.to_load = generic_load; /* load */
+ eb_ops.to_lookup_symbol = 0; /* lookup_symbol */
+ eb_ops.to_create_inferior = eb_create_inferior;
+ eb_ops.to_post_startup_inferior = NULL;
+ eb_ops.to_acknowledge_created_inferior = NULL;
+ eb_ops.to_clone_and_follow_inferior = NULL;
+ eb_ops.to_post_follow_inferior_by_clone = NULL;
+ eb_ops.to_insert_fork_catchpoint = NULL;
+ eb_ops.to_remove_fork_catchpoint = NULL;
+ eb_ops.to_insert_vfork_catchpoint = NULL;
+ eb_ops.to_remove_vfork_catchpoint = NULL;
+ eb_ops.to_has_forked = NULL;
+ eb_ops.to_has_vforked = NULL;
+ eb_ops.to_can_follow_vfork_prior_to_exec = NULL;
+ eb_ops.to_post_follow_vfork = NULL;
+ eb_ops.to_insert_exec_catchpoint = NULL;
+ eb_ops.to_remove_exec_catchpoint = NULL;
+ eb_ops.to_has_execd = NULL;
+ eb_ops.to_reported_exec_events_per_exec_call = NULL;
+ eb_ops.to_has_exited = NULL;
+ eb_ops.to_mourn_inferior = eb_mourn_inferior;
+ eb_ops.to_can_run = 0; /* can_run */
+ eb_ops.to_notice_signals = 0; /* notice_signals */
+ eb_ops.to_thread_alive = 0; /* thread-alive */
+ eb_ops.to_stop = 0; /* to_stop */
+ eb_ops.to_pid_to_exec_file = NULL;
+ eb_ops.to_core_file_to_sym_file = NULL;
+ eb_ops.to_stratum = process_stratum;
+ eb_ops.DONT_USE = 0; /* next */
+ eb_ops.to_has_all_memory = 1;
+ eb_ops.to_has_memory = 1;
+ eb_ops.to_has_stack = 1;
+ eb_ops.to_has_registers = 1;
+ eb_ops.to_has_execution = 1; /* all mem, mem, stack, regs, exec */
+ eb_ops.to_sections = 0; /* sections */
+ eb_ops.to_sections_end = 0; /* sections end */
+ eb_ops.to_magic = OPS_MAGIC; /* Always the last thing */
+};
+
+void
+_initialize_remote_eb ()
+{
+ init_eb_ops() ;
+ add_target (&eb_ops);
+}
diff --git a/gdb/remote-es.c b/gdb/remote-es.c
new file mode 100644
index 00000000000..d26e85b7890
--- /dev/null
+++ b/gdb/remote-es.c
@@ -0,0 +1,2202 @@
+/* Memory-access and commands for remote es1800 processes, for GDB.
+ Copyright (C) 1988, 1992 Free Software Foundation, Inc.
+
+ This file is added to GDB to make it possible to do debugging via an
+ ES-1800 emulator. The code was originally written by Johan Holmberg
+ TT/SJ Ericsson Telecom AB and later modified by Johan Henriksson
+ TT/SJ. It was modified for gdb 4.0 by TX/DK Jan Nordenand by TX/DKG
+ Harald Johansen.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+
+/* Emulator communication protocol.
+ All values are encoded in ascii hex digits.
+
+ Request
+Command
+Reply
+ read registers:
+DR<cr>
+ - 0 - - 1 - - 2 - - 3 - - 4 - - 5 - -- 6 - - 7 -
+D = XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX
+A = XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX
+ PC = XXXXXX SSP = XXXXXX USP = XXXXXX SR = XXXXXXXX
+ >
+Each byte of register data is described by two hex digits.
+
+ write regs
+D0=XXXXXXXX<cr>
+ >D1=XXXXXXXX<cr>
+ >D2=XXXXXXXX<cr>
+ >D3=XXXXXXXX<cr>
+ >D4=XXXXXXXX<cr>
+ >D5=XXXXXXXX<cr>
+ >D6=XXXXXXXX<cr>
+ >D7=XXXXXXXX<cr>
+ >A0=XXXXXXXX<cr>
+ >A1=XXXXXXXX<cr>
+ >A2=XXXXXXXX<cr>
+ >A3=XXXXXXXX<cr>
+ >A4=XXXXXXXX<cr>
+ >A5=XXXXXXXX<cr>
+ >A6=XXXXXXXX<cr>
+ >A7=XXXXXXXX<cr>
+ >SR=XXXXXXXX<cr>
+ >PC=XXXXXX<cr>
+ >
+Each byte of register data is described by two hex digits.
+
+ read mem
+@.BAA..AA
+$FFFFFFXX
+ >
+AA..AA is address, XXXXXXX is the contents
+
+ write mem
+ @.BAA..AA=$XXXXXXXX
+ >
+AA..AA is address, XXXXXXXX is data
+
+ cont
+PC=$AA..AA
+ >RBK
+R>
+AA..AA is address to resume. If AA..AA is omitted, resume at same address.
+
+ step
+PC=$AA..AA
+ >STP
+R>
+AA..AA is address to resume. If AA..AA is omitted, resume at same address.
+
+ kill req
+STP
+ >
+*/
+
+
+#include <stdio.h>
+#include <signal.h>
+#include <sys/ioctl.h>
+#include <sys/file.h>
+#include <errno.h>
+#include <ctype.h>
+#include <setjmp.h>
+#include <fcntl.h>
+#include "defs.h"
+#include "gdb_string.h"
+#include "frame.h"
+#include "inferior.h"
+#include "target.h"
+#include "wait.h"
+#include "command.h"
+#include "remote-utils.h"
+#include "gdbcore.h"
+#include "serial.h"
+
+/* Prototypes for local functions */
+
+static void
+es1800_child_detach PARAMS ((char *, int));
+
+static void
+es1800_child_open PARAMS ((char *, int));
+
+static void
+es1800_transparent PARAMS ((char *, int));
+
+static void
+es1800_create_inferior PARAMS ((char *, char *, char **));
+
+static void
+es1800_load PARAMS ((char *, int));
+
+static void
+es1800_kill PARAMS ((void));
+
+static int
+verify_break PARAMS ((int));
+
+static int
+es1800_remove_breakpoint PARAMS ((CORE_ADDR, char *));
+
+static int
+es1800_insert_breakpoint PARAMS ((CORE_ADDR, char *));
+
+static void
+es1800_files_info PARAMS ((struct target_ops *));
+
+static int
+es1800_xfer_inferior_memory PARAMS ((CORE_ADDR, char *, int, int,
+ struct target_ops *));
+
+static void
+es1800_prepare_to_store PARAMS ((void));
+
+static int es1800_wait PARAMS ((int, struct target_waitstatus *));
+
+static void es1800_resume PARAMS ((int, int, enum target_signal));
+
+static void
+es1800_detach PARAMS ((char *, int));
+
+static void
+es1800_attach PARAMS ((char *, int));
+
+static int
+damn_b PARAMS ((char *));
+
+static void
+es1800_open PARAMS ((char *, int));
+
+static void
+es1800_timer PARAMS ((void));
+
+static void
+es1800_reset PARAMS ((char *));
+
+static void
+es1800_request_quit PARAMS ((void));
+
+static int
+readchar PARAMS ((void));
+
+static void
+expect PARAMS ((char *, int));
+
+static void
+expect_prompt PARAMS ((void));
+
+static void
+download PARAMS ((FILE *, int, int));
+
+#if 0
+static void
+bfd_copy PARAMS ((bfd *, bfd *));
+#endif
+
+static void
+get_break_addr PARAMS ((int, CORE_ADDR *));
+
+static int
+fromhex PARAMS ((int));
+
+static int
+tohex PARAMS ((int));
+
+static void
+es1800_close PARAMS ((int));
+
+static void
+es1800_fetch_registers PARAMS ((void));
+
+static void
+es1800_fetch_register PARAMS ((int));
+
+static void
+es1800_store_register PARAMS ((int));
+
+static void
+es1800_read_bytes PARAMS ((CORE_ADDR, char *, int));
+
+static void
+es1800_write_bytes PARAMS ((CORE_ADDR, char *, int));
+
+static void
+send_with_reply PARAMS ((char *, char *, int));
+
+static void
+send_command PARAMS ((char *));
+
+static void
+send PARAMS ((char *));
+
+static void
+getmessage PARAMS ((char *, int));
+
+static void
+es1800_mourn_inferior PARAMS ((void));
+
+static void
+es1800_create_break_insn PARAMS ((char *, int));
+
+static void
+es1800_init_break PARAMS ((char *, int));
+
+/* Local variables */
+
+/* FIXME: Convert this to use "set remotedebug" instead. */
+#define LOG_FILE "es1800.log"
+#if defined (LOG_FILE)
+static FILE *log_file;
+#endif
+
+extern struct target_ops es1800_ops; /* Forward decl */
+extern struct target_ops es1800_child_ops; /* Forward decl */
+
+static int kiodebug;
+static int timeout = 100;
+static char *savename; /* Name of i/o device used */
+static serial_ttystate es1800_saved_ttystate;
+static int es1800_fc_save; /* Save fcntl state */
+
+/* indicates that the emulator uses 32-bit data-adress (68020-mode)
+ instead of 24-bit (68000 -mode) */
+
+static int m68020;
+
+#define MODE (m68020 ? "M68020" : "M68000" )
+#define ES1800_BREAK_VEC (0xf)
+
+/* Descriptor for I/O to remote machine. Initialize it to NULL so that
+ es1800_open knows that we don't have a file open when the program
+ starts. */
+
+static serial_t es1800_desc = NULL;
+
+#define PBUFSIZ 1000
+#define HDRLEN sizeof("@.BAAAAAAAA=$VV\r")
+
+/* Maximum number of bytes to read/write at once. The value here
+ is chosen to fill up a packet. */
+
+#define MAXBUFBYTES ((PBUFSIZ-150)*16/75 )
+
+static int es1800_break_vec = 0;
+static char es1800_break_insn[2];
+static long es1800_break_address;
+static void (*old_sigint)(); /* Old signal-handler for sigint */
+static jmp_buf interrupt;
+
+/* Local signalhandler to allow breaking tranfers or program run.
+ Rely on global variables: old_sigint(), interrupt */
+
+static void
+es1800_request_quit ()
+{
+ /* restore original signalhandler */
+ signal (SIGINT, old_sigint);
+ longjmp (interrupt, 1);
+}
+
+
+/* Reset emulator.
+ Sending reset character(octal 32) to emulator.
+ quit - return to '(esgdb)' prompt or continue */
+
+static void
+es1800_reset (quit)
+ char *quit;
+{
+ char buf[80];
+
+ if (quit)
+ {
+ printf ("\nResetting emulator... ");
+ }
+ strcpy (buf, "\032");
+ send (buf);
+ expect_prompt ();
+ if (quit)
+ {
+ error ("done\n");
+ }
+}
+
+
+/* Open a connection to a remote debugger and push the new target
+ onto the stack. Check if the emulator is responding and find out
+ what kind of processor the emulator is connected to.
+ Initiate the breakpoint handling in the emulator.
+
+ name - the filename used for communication (ex. '/dev/tta')
+ from_tty - says whether to be verbose or not */
+
+static void
+es1800_open (name, from_tty)
+ char *name;
+ int from_tty;
+{
+ char buf[PBUFSIZ];
+ char *p;
+ int i, fcflag;
+
+ m68020 = 0;
+
+ if (!name) /* no device name given in target command */
+ {
+ error_no_arg ("serial port device name");
+ }
+
+ target_preopen (from_tty);
+ es1800_close (0);
+
+ /* open the device and configure it for communication */
+
+#ifndef DEBUG_STDIN
+
+ es1800_desc = SERIAL_OPEN (name);
+ if (es1800_desc == NULL)
+ {
+ perror_with_name (name);
+ }
+ savename = savestring (name, strlen (name));
+
+ es1800_saved_ttystate = SERIAL_GET_TTY_STATE (es1800_desc);
+
+ if ((fcflag = fcntl (es1800_desc->fd, F_GETFL, 0)) == -1)
+ {
+ perror_with_name ("fcntl serial");
+ }
+ es1800_fc_save = fcflag;
+
+ fcflag = (fcflag & (FREAD | FWRITE)); /* mask out any funny stuff */
+ if (fcntl (es1800_desc->fd, F_SETFL, fcflag) == -1)
+ {
+ perror_with_name ("fcntl serial");
+ }
+
+ if (baud_rate != -1)
+ {
+ if (SERIAL_SETBAUDRATE (es1800_desc, baud_rate))
+ {
+ SERIAL_CLOSE (es1800_desc);
+ perror_with_name (name);
+ }
+ }
+
+ SERIAL_RAW (es1800_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 (es1800_desc);
+
+#endif /* DEBUG_STDIN */
+
+ push_target (&es1800_ops); /* Switch to using remote target now */
+ if (from_tty)
+ {
+ printf ("Remote ES1800 debugging using %s\n", name);
+ }
+
+#if defined (LOG_FILE)
+
+ log_file = fopen (LOG_FILE, "w");
+ if (log_file == NULL)
+ {
+ perror_with_name (LOG_FILE);
+ }
+
+#endif /* LOG_FILE */
+
+ /* Hello? Are you there?, also check mode */
+
+ /* send_with_reply( "DB 0 TO 1", buf, sizeof(buf)); */
+ /* for (p = buf, i = 0; *p++ =='0';) */ /* count the number of zeros */
+ /* i++; */
+
+ send ("\032");
+ getmessage (buf, sizeof (buf)); /* send reset character */
+
+ if (from_tty)
+ {
+ printf ("Checking mode.... ");
+ }
+ /* m68020 = (i==8); */ /* if eight zeros then we are in m68020 mode */
+
+ /* What kind of processor am i talking to ?*/
+ p = buf;
+ while (*p++ != '\n') {;}
+ while (*p++ != '\n') {;}
+ while (*p++ != '\n') {;}
+ for (i = 0; i < 20; i++, p++) {;}
+ m68020 = !strncmp (p, "68020", 5);
+ if (from_tty)
+ {
+ printf ("You are in %s(%c%c%c%c%c)-mode\n", MODE, p[0], p[1], p[2],
+ p[3], p[4]);
+ }
+
+ /* if no init_break statement is present in .gdb file we have to check
+ whether to download a breakpoint routine or not */
+
+#if 0
+ if ((es1800_break_vec == 0) || (verify_break (es1800_break_vec) != 0)
+ && query ("No breakpoint routine in ES 1800 emulator!\nDownload a breakpoint routine to the emulator? "))
+ {
+ CORE_ADDR memaddress;
+ printf ("Give the start address of the breakpoint routine: ");
+ scanf ("%li", &memaddress);
+ es1800_init_break ((es1800_break_vec ? es1800_break_vec :
+ ES1800_BREAK_VEC), memaddress);
+ }
+#endif
+
+}
+
+/* Close out all files and local state before this target loses control.
+ quitting - are we quitting gdb now? */
+
+static void
+es1800_close (quitting)
+ int quitting;
+{
+ if (es1800_desc != NULL)
+ {
+ printf ("\nClosing connection to emulator...\n");
+ if (SERIAL_SET_TTY_STATE (es1800_desc, es1800_saved_ttystate) < 0)
+ print_sys_errmsg ("warning: unable to restore tty state", errno);
+ fcntl (es1800_desc->fd, F_SETFL, es1800_fc_save);
+ SERIAL_CLOSE (es1800_desc);
+ es1800_desc = NULL;
+ }
+ if (savename != NULL)
+ {
+ free (savename);
+ }
+ savename = NULL;
+
+#if defined (LOG_FILE)
+
+ if (log_file != NULL)
+ {
+ if (ferror (log_file))
+ {
+ printf ("Error writing log file.\n");
+ }
+ if (fclose (log_file) != 0)
+ {
+ printf ("Error closing log file.\n");
+ }
+ log_file = NULL;
+ }
+
+#endif /* LOG_FILE */
+
+}
+
+/* Attaches to a process on the target side
+ proc_id - the id of the process to be attached.
+ from_tty - says whether to be verbose or not */
+
+static void
+es1800_attach (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ error ("Cannot attach to pid %s, this feature is not implemented yet.",
+ args);
+}
+
+
+/* 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.
+
+ args - arguments given to the 'detach' command
+ from_tty - says whether to be verbose or not */
+
+static void
+es1800_detach (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ if (args)
+ {
+ error ("Argument given to \"detach\" when remotely debugging.");
+ }
+ pop_target ();
+ if (from_tty)
+ {
+ printf ("Ending es1800 remote debugging.\n");
+ }
+}
+
+
+/* Tell the remote machine to resume.
+ step - single-step or run free
+ siggnal - the signal value to be given to the target (0 = no signal) */
+
+static void
+es1800_resume (pid, step, siggnal)
+ int pid;
+ int step;
+ enum target_signal siggnal;
+{
+ char buf[PBUFSIZ];
+
+ if (siggnal)
+ {
+ error ("Can't send signals to a remote system.");
+ }
+ if (step)
+ {
+ strcpy (buf,"STP\r");
+ send (buf);
+ }
+ else
+ {
+ send_command ("RBK");
+ }
+}
+
+/* Wait until the remote machine stops, then return,
+ storing status in STATUS just as `wait' would.
+ status - */
+
+static int
+es1800_wait (pid, status)
+ int pid;
+ struct target_waitstatus *status;
+{
+ unsigned char buf[PBUFSIZ];
+ int old_timeout = timeout;
+
+ status->kind = TARGET_WAITKIND_EXITED;
+ status->value.integer = 0;
+
+ timeout = 0; /* Don't time out -- user program is running. */
+ if (!setjmp (interrupt))
+ {
+ old_sigint = signal (SIGINT, es1800_request_quit);
+ while (1)
+ {
+ getmessage (buf, sizeof(buf));
+ if (strncmp ( buf, "\r\n* BREAK *", 11) == 0)
+ {
+ status->kind = TARGET_WAITKIND_STOPPED;
+ status->value.sig = TARGET_SIGNAL_TRAP;
+ send_command ("STP"); /* Restore stack and PC and such */
+ if (m68020)
+ {
+ send_command ("STP");
+ }
+ break;
+ }
+ if (strncmp (buf, "STP\r\n ", 6) == 0)
+ {
+ status->kind = TARGET_WAITKIND_STOPPED;
+ status->value.sig = TARGET_SIGNAL_TRAP;
+ break;
+ }
+ if (buf[strlen (buf) - 2] == 'R')
+ {
+ printf ("Unexpected emulator reply: \n%s\n", buf);
+ }
+ else
+ {
+ printf ("Unexpected stop: \n%s\n", buf);
+ status->kind = TARGET_WAITKIND_STOPPED;
+ status->value.sig = TARGET_SIGNAL_QUIT;
+ break;
+ }
+ }
+ }
+ else
+ {
+ fflush (stdin);
+ printf ("\nStopping emulator...");
+ if (!setjmp (interrupt))
+ {
+ old_sigint = signal (SIGINT, es1800_request_quit);
+ send_command ("STP");
+ printf (" emulator stopped\n");
+ status->kind = TARGET_WAITKIND_STOPPED;
+ status->value.sig = TARGET_SIGNAL_INT;
+ }
+ else
+ {
+ fflush (stdin);
+ es1800_reset ((char*) 1);
+ }
+ }
+ signal (SIGINT, old_sigint);
+ timeout = old_timeout;
+ return (0);
+}
+
+
+/* Fetch register values from remote machine.
+ regno - the register to be fetched (fetch all registers if -1) */
+
+static void
+es1800_fetch_register (regno)
+ int regno;
+{
+ char buf[PBUFSIZ];
+ int k;
+ int r;
+ char *p;
+ static char regtab[18][4] =
+ {
+ "D0 ", "D1 ", "D2 ", "D3 ", "D4 ", "D5 ", "D6 ", "D7 ",
+ "A0 ", "A1 ", "A2 ", "A3 ", "A4 ", "A5 ", "A6 ", "SSP",
+ "SR ", "PC "
+ };
+
+ if ((regno < 15) || (regno == 16) || (regno == 17))
+ {
+ r = regno * 4;
+ send_with_reply (regtab[regno], buf, sizeof (buf));
+ p = buf;
+ for (k = 0; k < 4; k++)
+ {
+ if ((p[k*2 + 1] == 0) || (p[k*2 + 2] == 0))
+ {
+ error ("Emulator reply is too short: %s", buf);
+ }
+ registers[r++] = (fromhex (p[k*2 + 1]) * 16) + fromhex (p[k*2 + 2]);
+ }
+ }
+ else
+ {
+ es1800_fetch_registers ();
+ }
+}
+
+/* Read the remote registers into REGISTERS.
+ Always fetches all registers. */
+
+static void
+es1800_fetch_registers ()
+{
+ char buf[PBUFSIZ];
+ char SR_buf[PBUFSIZ];
+ int i;
+ int k;
+ int r;
+ char *p;
+
+ send_with_reply ("DR", buf, sizeof (buf));
+
+ /* Reply is edited to a string that describes registers byte by byte,
+ each byte encoded as two hex characters. */
+
+ p = buf;
+ r = 0;
+
+ /* parsing row one - D0-D7-registers */
+
+ while (*p++ != '\n') {;}
+ for (i = 4; i < 70; i += (i == 39 ? 3 : 1))
+ {
+ for (k = 0; k < 4; k++)
+ {
+ if (p[i+0] == 0 || p[i+1] == 0)
+ {
+ error ("Emulator reply is too short: %s", buf);
+ }
+ registers[r++] = (fromhex (p[i+0]) * 16) + fromhex (p[i+1]);
+ i += 2;
+ }
+ }
+ p += i;
+
+ /* parsing row two - A0-A6-registers */
+
+ while (*p++ != '\n') {;}
+ for (i = 4; i < 61; i += (i == 39 ? 3 : 1))
+ {
+ for (k = 0; k < 4; k++)
+ {
+ if (p[i+0] == 0 || p[i+1] == 0)
+ {
+ error ("Emulator reply is too short: %s", buf);
+ }
+ registers[r++] = (fromhex (p[i+0])) * 16 + fromhex (p[i+1]);
+ i += 2;
+ }
+ }
+ p += i;
+
+ while (*p++ != '\n') {;}
+
+ /* fetch SSP-, SR- and PC-registers */
+
+ /* first - check STATUS-word and decide which stackpointer to use */
+
+ send_with_reply ("SR", SR_buf, sizeof (SR_buf));
+ p = SR_buf;
+ p += 5;
+
+ if (m68020)
+ {
+ if (*p == '3') /* use masterstackpointer MSP */
+ {
+ send_with_reply ("MSP", buf, sizeof (buf));
+ }
+ else if (*p == '2') /* use interruptstackpointer ISP */
+ {
+ send_with_reply ("ISP", buf, sizeof (buf));
+ }
+ else /* use userstackpointer USP */
+ {
+ send_with_reply ("USP", buf, sizeof (buf));
+ }
+ p = buf;
+ for (k = 0; k<4; k++)
+ {
+ if (p[k*2+1] == 0 || p[k*2+2] == 0)
+ {
+ error ("Emulator reply is too short: %s", buf);
+ }
+ registers[r++] = fromhex (buf[k*2+1]) * 16 + fromhex (buf[k*2+2]);
+ }
+
+ p = SR_buf;
+ for (k = 0; k < 4; k++)
+ {
+ if (p[k*2+1] == 0 || p[k*2+2] == 0)
+ {
+ error ("Emulator reply is too short: %s", buf);
+ }
+ registers[r++] =
+ fromhex (SR_buf[k*2+1]) * 16 + fromhex (SR_buf[k*2+2]);
+ }
+ send_with_reply ("PC", buf, sizeof (buf));
+ p = buf;
+ for (k = 0; k<4; k++)
+ {
+ if (p[k*2+1] == 0 || p[k*2+2] == 0)
+ {
+ error ("Emulator reply is too short: %s", buf);
+ }
+ registers[r++] = fromhex (buf[k*2+1]) * 16 + fromhex (buf[k*2+2]);
+ }
+ }
+ else /* 68000-mode */
+ {
+ if (*p == '2') /* use supervisorstackpointer SSP */
+ {
+ send_with_reply ("SSP", buf, sizeof (buf));
+ }
+ else /* use userstackpointer USP */
+ {
+ send_with_reply ("USP", buf, sizeof (buf));
+ }
+
+ /* fetch STACKPOINTER */
+
+ p = buf;
+ for (k = 0; k < 4; k++)
+ {
+ if (p[k*2 + 1] == 0 || p[k*2 + 2] == 0)
+ {
+ error ("Emulator reply is too short: %s", buf);
+ }
+ registers[r++] = fromhex (buf[k*2+1]) * 16 + fromhex (buf[k*2+2]);
+ }
+
+ /* fetch STATUS */
+
+ p = SR_buf;
+ for (k = 0; k < 4; k++)
+ {
+ if (p[k*2+1] == 0 || p[k*2+2] == 0)
+ {
+ error ("Emulator reply is too short: %s", buf);
+ }
+ registers[r++] =
+ fromhex (SR_buf[k*2+1]) * 16 + fromhex (SR_buf[k*2+2]);
+ }
+
+ /* fetch PC */
+
+ send_with_reply ("PC", buf, sizeof (buf));
+ p = buf;
+ for (k = 0; k < 4; k++)
+ {
+ if (p[k*2+1] == 0 || p[k*2+2] == 0)
+ {
+ error ("Emulator reply is too short: %s", buf);
+ }
+ registers[r++] = fromhex (buf[k*2+1]) * 16 + fromhex (buf[k*2+2]);
+ }
+ }
+}
+
+/* Store register value, located in REGISTER, on the target processor.
+ regno - the register-number of the register to store
+ (-1 means store them all)
+ FIXME: Return errno value. */
+
+static void
+es1800_store_register(regno)
+ int regno;
+{
+
+ static char regtab[18][4] =
+ {
+ "D0 ", "D1 ", "D2 ", "D3 ", "D4 ", "D5 ", "D6 ", "D7 ",
+ "A0 ", "A1 ", "A2 ", "A3 ", "A4 ", "A5 ", "A6 ", "SSP",
+ "SR ", "PC "
+ };
+
+ char buf[PBUFSIZ];
+ char SR_buf[PBUFSIZ];
+ char stack_pointer[4];
+ char *p;
+ int i;
+ int j;
+ int k;
+ unsigned char *r;
+
+ r = (unsigned char *) registers;
+
+ if (regno == -1) /* write all registers */
+ {
+ j = 0;
+ k = 18;
+ }
+ else /* write one register */
+ {
+ j = regno;
+ k = regno+1;
+ r += regno * 4;
+ }
+
+ if ((regno == -1) || (regno == 15))
+ {
+ /* fetch current status */
+ send_with_reply ("SR", SR_buf, sizeof (SR_buf));
+ p = SR_buf;
+ p += 5;
+ if (m68020)
+ {
+ if (*p == '3') /* use masterstackpointer MSP */
+ {
+ strcpy (stack_pointer,"MSP");
+ }
+ else
+ {
+ if (*p == '2') /* use interruptstackpointer ISP */
+ {
+ strcpy (stack_pointer,"ISP");
+ }
+ else
+ {
+ strcpy (stack_pointer,"USP"); /* use userstackpointer USP */
+ }
+ }
+ }
+ else /* 68000-mode */
+ {
+ if (*p == '2') /* use supervisorstackpointer SSP */
+ {
+ strcpy (stack_pointer,"SSP");
+ }
+ else
+ {
+ strcpy (stack_pointer,"USP");/* use userstackpointer USP */
+ }
+ }
+ strcpy (regtab[15],stack_pointer);
+ }
+
+ for (i = j; i<k; i++)
+ {
+ buf[0] = regtab[i][0];
+ buf[1] = regtab[i][1];
+ buf[2] = regtab[i][2];
+ buf[3] = '=';
+ buf[4] = '$';
+ buf[5] = tohex ((*r >> 4) & 0x0f);
+ buf[6] = tohex (*r++ & 0x0f);
+ buf[7] = tohex ((*r >> 4) & 0x0f);
+ buf[8] = tohex (*r++ & 0x0f);
+ buf[9] = tohex ((*r >> 4) & 0x0f);
+ buf[10] = tohex (*r++ & 0x0f);
+ buf[11] = tohex ((*r >> 4) & 0x0f);
+ buf[12] = tohex (*r++ & 0x0f);
+ buf[13] = 0;
+
+ send_with_reply (buf, buf, sizeof (buf)); /* FIXME, reply not used? */
+ }
+}
+
+
+/* Prepare to store registers. */
+
+static void
+es1800_prepare_to_store ()
+{
+ /* Do nothing, since we can store individual regs */
+}
+
+/* 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 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);
+ }
+}
+
+/* Read or write LEN bytes from inferior memory at MEMADDR, transferring
+ to or from debugger address MYADDR. Write to inferior if WRITE is
+ nonzero. Returns length of data written or read; 0 for error.
+
+ memaddr - the target's address
+ myaddr - gdb's address
+ len - number of bytes
+ write - write if != 0 otherwise read */
+
+static int
+es1800_xfer_inferior_memory (memaddr, myaddr, len, write, tops)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+ int write;
+ struct target_ops *tops; /* Unused */
+{
+ int origlen = len;
+ int xfersize;
+
+ while (len > 0)
+ {
+ xfersize = len > MAXBUFBYTES ? MAXBUFBYTES : len;
+ if (write)
+ {
+ es1800_write_bytes (memaddr, myaddr, xfersize);
+ }
+ else
+ {
+ es1800_read_bytes (memaddr, myaddr, xfersize);
+ }
+ memaddr += xfersize;
+ myaddr += xfersize;
+ len -= xfersize;
+ }
+ return (origlen); /* no error possible */
+}
+
+
+/* Write memory data directly to the emulator.
+ 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.
+
+ memaddr - the target's address
+ myaddr - gdb's address
+ len - number of bytes */
+
+static void
+es1800_write_bytes (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+{
+ char buf[PBUFSIZ];
+ int i;
+ char *p;
+
+ p = myaddr;
+ for (i = 0; i < len; i++)
+ {
+ sprintf (buf, "@.B$%x=$%x", memaddr+i, (*p++) & 0xff);
+ send_with_reply (buf, buf, sizeof (buf)); /* FIXME send_command? */
+ }
+}
+
+
+/* Read memory data directly from the emulator.
+ This does not use the data cache; the data cache uses this.
+
+ memaddr - the target's address
+ myaddr - gdb's address
+ len - number of bytes */
+
+static void
+es1800_read_bytes (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+{
+ static int DB_tab[16] = {8,11,14,17,20,23,26,29,34,37,40,43,46,49,52,55};
+ char buf[PBUFSIZ];
+ int i;
+ int low_addr;
+ char *p;
+ char *b;
+
+ if (len > PBUFSIZ / 2 - 1)
+ {
+ abort ();
+ }
+
+ if (len == 1) /* The emulator does not like expressions like: */
+ {
+ len = 2; /* DB.B $20018 TO $20018 */
+ }
+
+ /* Reply describes registers byte by byte, each byte encoded as two hex
+ characters. */
+
+ sprintf (buf, "DB.B $%x TO $%x", memaddr, memaddr+len-1);
+ send_with_reply (buf, buf, sizeof (buf));
+ b = buf;
+ low_addr = memaddr&0x0f;
+ for (i = low_addr; i < low_addr + len; i++)
+ {
+ if ((!(i % 16)) && i)
+ { /* if (i = 16,32,48) */
+ while (*p++!='\n') {;}
+ b = p;
+ }
+ p = b + DB_tab[i%16] + (m68020 ? 2 : 0);
+ if (p[0] == 32 || p[1] == 32)
+ {
+ error ("Emulator reply is too short: %s", buf);
+ }
+ myaddr[i-low_addr] = fromhex (p[0]) * 16 + fromhex (p[1]);
+ }
+}
+
+/* Information about the current target */
+
+static void
+es1800_files_info (tops)
+ struct target_ops *tops; /* Unused */
+{
+ printf ("ES1800 Attached to %s at %d baud in %s mode\n", savename, 19200,
+ MODE);
+}
+
+
+/* We read the contents of the target location and stash it,
+ then overwrite it with a breakpoint instruction.
+
+ addr - is the target location in the target machine.
+ contents_cache - is a pointer to memory allocated for saving the target contents.
+ It is guaranteed by the caller to be long enough to save sizeof
+ BREAKPOINT bytes.
+
+ FIXME: This size is target_arch dependent and should be available in
+ the target_arch transfer vector, if we ever have one... */
+
+static int
+es1800_insert_breakpoint (addr, contents_cache)
+ CORE_ADDR addr;
+ char *contents_cache;
+{
+ int val;
+
+ val = target_read_memory (addr, contents_cache, sizeof (es1800_break_insn));
+
+ if (val == 0)
+ {
+ val = target_write_memory (addr, es1800_break_insn,
+ sizeof (es1800_break_insn));
+ }
+
+ return (val);
+}
+
+
+/* Write back the stashed 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. */
+
+static int
+es1800_remove_breakpoint (addr, contents_cache)
+ CORE_ADDR addr;
+ char *contents_cache;
+{
+
+ return (target_write_memory (addr, contents_cache,
+ sizeof (es1800_break_insn)));
+}
+
+/* create_break_insn ()
+ Primitive datastructures containing the es1800 breakpoint instruction */
+
+static void
+es1800_create_break_insn (ins, vec)
+ char *ins;
+ int vec;
+{
+ if (vec == 15)
+ {
+ ins[0] = 0x4e;
+ ins[1] = 0x4f;
+ }
+}
+
+
+/* verify_break ()
+ Seach for breakpoint routine in emulator memory.
+ returns non-zero on failure
+ vec - trap vector used for breakpoints */
+
+static int
+verify_break (vec)
+ int vec;
+{
+ CORE_ADDR memaddress;
+ char buf[8];
+ char *instr = "NqNqNqNs"; /* breakpoint routine */
+ int status;
+
+ get_break_addr (vec, &memaddress);
+
+ if (memaddress)
+ {
+ status = target_read_memory (memaddress, buf, 8);
+ if (status != 0)
+ {
+ memory_error (status, memaddress);
+ }
+ return (STRCMP (instr, buf));
+ }
+ return (-1);
+}
+
+
+/* get_break_addr ()
+ find address of breakpint routine
+ vec - trap vector used for breakpoints
+ addrp - store the address here */
+
+static void
+get_break_addr (vec, addrp)
+ int vec;
+ CORE_ADDR *addrp;
+{
+ CORE_ADDR memaddress = 0;
+ int status;
+ int k;
+ char buf[PBUFSIZ];
+ char base_addr[4];
+ char *p;
+
+ if (m68020)
+ {
+ send_with_reply ("VBR ", buf, sizeof (buf));
+ p = buf;
+ for (k = 0; k < 4; k++)
+ {
+ if ((p[k*2 + 1] == 0) || (p[k*2 + 2] == 0))
+ {
+ error ("Emulator reply is too short: %s", buf);
+ }
+ base_addr[k] = (fromhex (p[k*2 + 1]) * 16) + fromhex (p[k*2 + 2]);
+ }
+ /* base addr of exception vector table */
+ memaddress = *((CORE_ADDR *) base_addr);
+ }
+
+ memaddress += (vec + 32) * 4; /* address of trap vector */
+ status = target_read_memory (memaddress, (char *) addrp, 4);
+ if (status != 0)
+ {
+ memory_error (status, memaddress);
+ }
+}
+
+
+/* Kill an inferior process */
+
+static void
+es1800_kill ()
+{
+ if (inferior_pid != 0)
+ {
+ inferior_pid = 0;
+ es1800_mourn_inferior ();
+ }
+}
+
+
+/* Load a file to the ES1800 emulator.
+ Converts the file from a.out format into Extended Tekhex format
+ before the file is loaded.
+ Also loads the trap routine, and sets the ES1800 breakpoint on it
+ filename - the a.out to be loaded
+ from_tty - says whether to be verbose or not
+ FIXME Uses emulator overlay memory for trap routine */
+
+static void
+es1800_load (filename, from_tty)
+ char *filename;
+ int from_tty;
+{
+
+ FILE *instream;
+ char loadname[15];
+ char buf[160];
+ struct cleanup *old_chain;
+ int es1800_load_format = 5;
+
+ if (es1800_desc == NULL)
+ {
+ printf ("No emulator attached, type emulator-command first\n");
+ return;
+ }
+
+ filename = tilde_expand (filename);
+ make_cleanup (free, filename);
+
+ switch (es1800_load_format)
+ {
+ case 2: /* Extended Tekhex */
+ if (from_tty)
+ {
+ printf ("Converting \"%s\" to Extended Tekhex Format\n", filename);
+ }
+ sprintf (buf, "tekhex %s", filename);
+ system (buf);
+ sprintf (loadname, "out.hex");
+ break;
+
+ case 5: /* Motorola S-rec */
+ if (from_tty)
+ {
+ printf ("Converting \"%s\" to Motorola S-record format\n",
+ filename);
+ }
+ /* in the future the source code in copy (part of binutils-1.93) will
+ be included in this file */
+ sprintf (buf,
+ "copy -s \"a.out-sunos-big\" -d \"srec\" %s /tmp/out.hex",
+ filename);
+ system (buf);
+ sprintf (loadname, "/tmp/out.hex");
+ break;
+
+ default:
+ error ("Downloading format not defined\n");
+ }
+
+ breakpoint_init_inferior ();
+ inferior_pid = 0;
+ if (from_tty)
+ {
+ printf ("Downloading \"%s\" to the ES 1800\n",filename);
+ }
+ if ((instream = fopen (loadname, "r")) == NULL)
+ {
+ perror_with_name ("fopen:");
+ }
+
+ old_chain = make_cleanup (fclose, instream);
+ immediate_quit++;
+
+ es1800_reset (0);
+
+ download (instream, from_tty, es1800_load_format);
+
+ /* if breakpoint routine is not present anymore we have to check
+ whether to download a new breakpoint routine or not */
+
+ if ((verify_break (es1800_break_vec) != 0)
+ && query ("No breakpoint routine in ES 1800 emulator!\nDownload a breakpoint routine to the emulator? "))
+ {
+ char buf[128];
+ printf ("Using break vector 0x%x\n", es1800_break_vec);
+ sprintf (buf, "0x%x ", es1800_break_vec);
+ printf ("Give the start address of the breakpoint routine: ");
+ fgets (buf + strlen (buf), sizeof (buf) - strlen (buf), stdin);
+ es1800_init_break (buf, 0);
+ }
+
+ do_cleanups (old_chain);
+ expect_prompt ();
+ readchar (); /* FIXME I am getting a ^G = 7 after the prompt */
+ printf ("\n");
+
+ if (fclose (instream) == EOF)
+ {
+ ;
+ }
+
+ if (es1800_load_format != 2)
+ {
+ sprintf (buf, "/usr/bin/rm %s", loadname);
+ system (buf);
+ }
+
+ symbol_file_command (filename, from_tty); /* reading symbol table */
+ immediate_quit--;
+}
+
+#if 0
+
+#define NUMCPYBYTES 20
+
+static void
+bfd_copy (from_bfd, to_bfd)
+ bfd *from_bfd;
+ bfd *to_bfd;
+{
+ asection *p, *new;
+ int i;
+ char buf[NUMCPYBYTES];
+
+ for (p = from_bfd->sections; p != NULL; p = p->next)
+ {
+ printf (" Copying section %s. Size = %x.\n", p->name, p->_cooked_size);
+ printf (" vma = %x, offset = %x, output_sec = %x\n",
+ p->vma, p->output_offset, p->output_section);
+ new = bfd_make_section (to_bfd, p->name);
+ if (p->_cooked_size &&
+ !bfd_set_section_size (to_bfd, new, p->_cooked_size))
+ {
+ error ("Wrong BFD size!\n");
+ }
+ if (!bfd_set_section_flags (to_bfd, new, p->flags))
+ {
+ error ("bfd_set_section_flags");
+ }
+ new->vma = p->vma;
+
+ for (i = 0; (i + NUMCPYBYTES) < p->_cooked_size ; i += NUMCPYBYTES)
+ {
+ if (!bfd_get_section_contents (from_bfd, p, (PTR) buf, (file_ptr) i,
+ (bfd_size_type) NUMCPYBYTES))
+ {
+ error ("bfd_get_section_contents\n");
+ }
+ if (!bfd_set_section_contents (to_bfd, new, (PTR) buf, (file_ptr) i,
+ (bfd_size_type) NUMCPYBYTES))
+ {
+ error ("bfd_set_section_contents\n");
+ }
+ }
+ bfd_get_section_contents (from_bfd, p, (PTR) buf, (file_ptr) i,
+ (bfd_size_type) (p->_cooked_size - i));
+ bfd_set_section_contents (to_bfd, new, (PTR) buf,(file_ptr) i,
+ (bfd_size_type) (p->_cooked_size - i));
+ }
+}
+
+#endif
+
+/* Start an process on the es1800 and set inferior_pid to the new
+ process' pid.
+ execfile - the file to run
+ args - arguments passed to the program
+ env - the environment vector to pass */
+
+static void
+es1800_create_inferior (execfile, args, env)
+ char *execfile;
+ char *args;
+ char **env;
+{
+ int entry_pt;
+ int pid;
+#if 0
+ struct expression *expr;
+ register struct cleanup *old_chain = 0;
+ register value val;
+#endif
+
+ if (args && *args)
+ {
+ error ("Can't pass arguments to remote ES1800 process");
+ }
+
+#if 0
+ if (query ("Use 'start' as entry point? "))
+ {
+ expr = parse_c_expression ("start");
+ old_chain = make_cleanup (free_current_contents, &expr);
+ val = evaluate_expression (expr);
+ entry_pt = (val->location).address;
+ }
+ else
+ {
+ printf ("Enter the program's entry point (in hexadecimal): ");
+ scanf ("%x", &entry_pt);
+ }
+#endif
+
+ if (execfile == 0 || exec_bfd == 0)
+ {
+ error ("No executable file specified");
+ }
+
+ entry_pt = (int) bfd_get_start_address (exec_bfd);
+
+ pid = 42;
+
+ /* Now that we have a child process, make it our target. */
+
+ push_target (&es1800_child_ops);
+
+ /* The "process" (board) is already stopped awaiting our commands, and
+ the program is already downloaded. We just set its PC and go. */
+
+ inferior_pid = pid; /* Needed for wait_for_inferior below */
+
+ clear_proceed_status ();
+
+ /* Tell wait_for_inferior that we've started a new process. */
+
+ init_wait_for_inferior ();
+
+ /* Set up the "saved terminal modes" of the inferior
+ based on what modes we are starting it with. */
+
+ target_terminal_init ();
+
+ /* Install inferior's terminal modes. */
+
+ target_terminal_inferior ();
+
+ /* remote_start (args); */
+ /* trap_expected = 0; */
+ /* insert_step_breakpoint (); FIXME, do we need this? */
+
+ /* Let 'er rip... */
+ proceed ((CORE_ADDR) entry_pt, TARGET_SIGNAL_DEFAULT, 0);
+
+}
+
+
+/* The process has died, clean up. */
+
+static void
+es1800_mourn_inferior ()
+{
+ remove_breakpoints ();
+ unpush_target (&es1800_child_ops);
+ generic_mourn_inferior (); /* Do all the proper things now */
+}
+
+/* ES1800-protocol specific routines */
+
+/* Keep discarding input from the remote system, until STRING is found.
+ Let the user break out immediately.
+ string - the string to expect
+ nowait - break out if string not the emulator's first respond otherwise
+ read until string is found (== 0) */
+
+static void
+expect (string, nowait)
+ char *string;
+ int nowait;
+{
+ char c;
+ char *p = string;
+
+ immediate_quit++;
+ while (1)
+ {
+ c = readchar ();
+ if (isalpha (c))
+ {
+ c = toupper (c);
+ }
+ if (c == toupper (*p))
+ {
+ p++;
+ if (*p == '\0')
+ {
+ immediate_quit--;
+ return;
+ }
+ }
+ else if (!nowait)
+ {
+ p = string;
+ }
+ else
+ {
+ printf ("\'%s\' expected\n" , string);
+ printf ("char %d is %d", p - string, c);
+ error ("\n" );
+ }
+ }
+}
+
+/* Keep discarding input until we see the prompt. */
+
+static void
+expect_prompt ()
+{
+ expect (">", 0);
+}
+
+
+/* Read one character */
+
+#ifdef DEBUG_STDIN
+
+/* read from stdin */
+
+static int
+readchar ()
+{
+ char buf[1];
+
+ buf[0] = '\0';
+ printf ("readchar, give one character\n");
+ read (0, buf, 1);
+
+#if defined (LOG_FILE)
+ putc (buf[0] & 0x7f, log_file);
+#endif
+
+ return (buf[0] & 0x7f);
+}
+
+#else /* !DEBUG_STDIN */
+
+/* Read a character from the remote system, doing all the fancy
+ timeout stuff. */
+
+static int
+readchar ()
+{
+ int ch;
+
+ ch = SERIAL_READCHAR (es1800_desc, timeout);
+
+ /* FIXME: doing an error() here will probably cause trouble, at least if from
+ es1800_wait. */
+ if (ch == SERIAL_TIMEOUT)
+ error ("Timeout reading from remote system.");
+ else if (ch == SERIAL_ERROR)
+ perror_with_name ("remote read");
+
+#if defined (LOG_FILE)
+ putc (ch & 0x7f, log_file);
+ fflush (log_file);
+#endif
+
+ return (ch);
+}
+
+#endif /* DEBUG_STDIN */
+
+
+/* Send a command to the emulator and save the reply.
+ Report an error if we get an error reply.
+ string - the es1800 command
+ buf - containing the emulator reply on return
+ len - size of buf */
+
+static void
+send_with_reply (string, buf, len)
+ char *string, *buf;
+ int len;
+{
+ send (string);
+ SERIAL_WRITE (es1800_desc, "\r", 1);
+
+#ifndef DEBUG_STDIN
+ expect (string, 1);
+ expect ("\r\n", 0);
+#endif
+
+ getmessage (buf, len);
+}
+
+
+/* Send the command in STR to the emulator adding \r. check
+ the echo for consistency.
+ string - the es1800 command */
+
+static void
+send_command (string)
+ char *string;
+{
+ send (string);
+ SERIAL_WRITE (es1800_desc, "\r", 1);
+
+#ifndef DEBUG_STDIN
+ expect (string, 0);
+ expect_prompt ();
+#endif
+
+}
+
+/* Send a string
+ string - the es1800 command */
+
+static void
+send (string)
+ char *string;
+{
+ if (kiodebug)
+ {
+ fprintf (stderr, "Sending: %s\n", string);
+ }
+ SERIAL_WRITE (es1800_desc, string, strlen (string));
+}
+
+
+/* Read a message from the emulator and store it in BUF.
+ buf - containing the emulator reply on return
+ len - size of buf */
+
+static void
+getmessage (buf, len)
+ char *buf;
+ int len;
+{
+ char *bp;
+ int c;
+ int prompt_found = 0;
+ extern kiodebug;
+
+#if defined (LOG_FILE)
+ /* This is a convenient place to do this. The idea is to do it often
+ enough that we never lose much data if we terminate abnormally. */
+ fflush (log_file);
+#endif
+
+ bp = buf;
+ c = readchar ();
+ do
+ {
+ if (c)
+ {
+ if (len-- < 2) /* char and terminaling NULL */
+ {
+ error ("input buffer overrun\n");
+ }
+ *bp++ = c;
+ }
+ c = readchar ();
+ if ((c == '>') && (*(bp - 1) == ' '))
+ {
+ prompt_found = 1;
+ }
+ }
+ while (!prompt_found);
+ *bp = 0;
+
+ if (kiodebug)
+ {
+ fprintf (stderr,"message received :%s\n", buf);
+ }
+}
+
+static void
+download (instream, from_tty, format)
+FILE *instream;
+ int from_tty;
+ int format;
+{
+ char c;
+ char buf[160];
+ int i = 0;
+
+ send_command ("SET #2,$1A"); /* reset char = ^Z */
+ send_command ("SET #3,$11,$13"); /* XON XOFF */
+ if (format == 2)
+ {
+ send_command ("SET #26,#2");
+ }
+ else
+ {
+ send_command ("SET #26,#5"); /* Format=Extended Tekhex */
+ }
+ send_command ("DFB = $10");
+ send_command ("PUR");
+ send_command ("CES");
+ send ("DNL\r");
+ expect ("DNL", 1);
+ if (from_tty)
+ {
+ printf (" 0 records loaded...\r");
+ }
+ while (fgets (buf, 160, instream))
+ {
+ send (buf);
+ if (from_tty)
+ {
+ printf ("%5d\b\b\b\b\b",++i);
+ fflush (stdout);
+ }
+ if ((c = readchar ()) != 006)
+ {
+ error ("expected ACK");
+ }
+ }
+ if (from_tty)
+ {
+ printf ("- All");
+ }
+}
+
+/* Additional commands */
+
+#if defined (TIOCGETP) && defined (FNDELAY) && defined (EWOULDBLOCK)
+#define PROVIDE_TRANSPARENT
+#endif
+
+#ifdef PROVIDE_TRANSPARENT
+/* Talk directly to the emulator
+ FIXME, uses busy wait, and is SUNOS (or at least BSD) specific */
+
+/*ARGSUSED*/
+static void
+es1800_transparent (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ int console;
+ struct sgttyb modebl;
+ int fcflag;
+ int cc;
+ struct sgttyb console_mode_save;
+ int console_fc_save;
+ int es1800_fc_save;
+ int inputcnt = 80;
+ char inputbuf[80];
+ int consolecnt = 0;
+ char consolebuf[80];
+ int es1800_cnt = 0;
+ char es1800_buf[80];
+ int i;
+
+ dont_repeat ();
+ if (es1800_desc == NULL)
+ {
+ printf ("No emulator attached, type emulator-command first\n");
+ return;
+ }
+
+ printf ("\n");
+ printf ("You are now communicating directly with the ES 1800 emulator.\n");
+ printf ("To leave this mode (transparent mode), press ^E.\n");
+ printf ("\n");
+ printf (" >");
+ fflush (stdout);
+
+ if ((console = open ("/dev/tty", O_RDWR)) == -1)
+ {
+ perror_with_name ("/dev/tty:");
+ }
+
+ if ((fcflag = fcntl (console, F_GETFL, 0)) == -1)
+ {
+ perror_with_name ("fcntl console");
+ }
+
+ console_fc_save = fcflag;
+ fcflag = fcflag | FNDELAY;
+
+ if (fcntl (console, F_SETFL, fcflag) == -1)
+ {
+ perror_with_name ("fcntl console");
+ }
+
+ if (ioctl (console, TIOCGETP, &modebl))
+ {
+ perror_with_name ("ioctl console");
+ }
+
+ console_mode_save = modebl;
+ modebl.sg_flags = RAW;
+
+ if (ioctl (console, TIOCSETP, &modebl))
+ {
+ perror_with_name ("ioctl console");
+ }
+
+ if ((fcflag = fcntl (es1800_desc->fd, F_GETFL, 0)) == -1)
+ {
+ perror_with_name ("fcntl serial");
+ }
+
+ es1800_fc_save = fcflag;
+ fcflag = fcflag | FNDELAY;
+
+ if (fcntl (es1800_desc->fd, F_SETFL, fcflag) == -1)
+ {
+ perror_with_name ("fcntl serial");
+ }
+
+ while (1)
+ {
+ cc = read (console, inputbuf, inputcnt);
+ if (cc != -1)
+ {
+ if ((*inputbuf & 0x7f) == 0x05)
+ {
+ break;
+ }
+ for (i = 0; i < cc; )
+ {
+ es1800_buf[es1800_cnt++] = inputbuf[i++];
+ }
+ if ((cc = SERIAL_WRITE (es1800_desc, es1800_buf, es1800_cnt)) == -1)
+ {
+ perror_with_name ("FEL! write:");
+ }
+ es1800_cnt -= cc;
+ if (es1800_cnt && cc)
+ {
+ for (i = 0; i < es1800_cnt; i++)
+ {
+ es1800_buf[i] = es1800_buf[cc+i];
+ }
+ }
+ }
+ else if (errno != EWOULDBLOCK)
+ {
+ perror_with_name ("FEL! read:");
+ }
+
+ cc = read (es1800_desc->fd,inputbuf,inputcnt);
+ if (cc != -1)
+ {
+ for (i = 0; i < cc; )
+ {
+ consolebuf[consolecnt++] = inputbuf[i++];
+ }
+ if ((cc = write (console,consolebuf,consolecnt)) == -1)
+ {
+ perror_with_name ("FEL! write:");
+ }
+ consolecnt -= cc;
+ if (consolecnt && cc)
+ {
+ for (i = 0; i < consolecnt; i++)
+ {
+ consolebuf[i] = consolebuf[cc+i];
+ }
+ }
+ }
+ else if (errno != EWOULDBLOCK)
+ {
+ perror_with_name ("FEL! read:");
+ }
+ }
+
+ console_fc_save = console_fc_save & !FNDELAY;
+ if (fcntl (console, F_SETFL, console_fc_save) == -1)
+ {
+ perror_with_name ("FEL! fcntl");
+ }
+
+ if (ioctl (console, TIOCSETP, &console_mode_save))
+ {
+ perror_with_name ("FEL! ioctl");
+ }
+
+ close (console);
+
+ if (fcntl (es1800_desc->fd, F_SETFL, es1800_fc_save) == -1)
+ {
+ perror_with_name ("FEL! fcntl");
+ }
+
+ printf ("\n");
+
+}
+#endif /* PROVIDE_TRANSPARENT */
+
+static void
+es1800_init_break (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ CORE_ADDR memaddress = 0;
+ char buf[PBUFSIZ];
+ char base_addr[4];
+ char *space_index;
+ char *p;
+ int k;
+
+ if (args == NULL)
+ {
+ error_no_arg ("a trap vector");
+ }
+
+ if (!(space_index = strchr (args, ' ')))
+ {
+ error ("Two arguments needed (trap vector and address of break routine).\n");
+ }
+
+ *space_index = '\0';
+
+ es1800_break_vec = strtol (args, (char **) NULL, 0);
+ es1800_break_address = parse_and_eval_address (space_index + 1);
+
+ es1800_create_break_insn (es1800_break_insn, es1800_break_vec);
+
+ if (m68020)
+ {
+ send_with_reply ("VBR ", buf, sizeof (buf));
+ p = buf;
+ for (k = 0; k < 4; k++)
+ {
+ if ((p[k*2 + 1] == 0) || (p[k*2 + 2] == 0))
+ {
+ error ("Emulator reply is too short: %s", buf);
+ }
+ base_addr[k] = (fromhex (p[k*2 + 1]) * 16) + fromhex (p[k*2 + 2]);
+ }
+ /* base addr of exception vector table */
+ memaddress = *((CORE_ADDR *) base_addr);
+ }
+
+ memaddress += (es1800_break_vec + 32) * 4; /* address of trap vector */
+
+ sprintf (buf, "@.L%lx=$%lx", memaddress, es1800_break_address);
+ send_command (buf); /* set the address of the break routine in the */
+ /* trap vector */
+
+ sprintf (buf, "@.L%lx=$4E714E71", es1800_break_address); /* NOP; NOP */
+ send_command (buf);
+ sprintf (buf, "@.L%lx=$4E714E73", es1800_break_address + 4); /* NOP; RTE */
+ send_command (buf);
+
+ sprintf (buf, "AC2=$%lx", es1800_break_address + 4);
+ /* breakpoint at es1800-break_address */
+ send_command (buf);
+ send_command ("WHEN AC2 THEN BRK"); /* ie in exception routine */
+
+ if (from_tty)
+ {
+ printf ("Breakpoint (trap $%x) routine at address: %lx\n",
+ es1800_break_vec, es1800_break_address);
+ }
+}
+
+static void
+es1800_child_open (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ error ("Use the \"run\" command to start a child process.");
+}
+
+static void
+es1800_child_detach (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ if (args)
+ {
+ error ("Argument given to \"detach\" when remotely debugging.");
+ }
+
+ pop_target ();
+ if (from_tty)
+ {
+ printf ("Ending debugging the process %d.\n", inferior_pid);
+ }
+}
+
+
+/* Define the target subroutine names */
+
+struct target_ops es1800_ops ;
+
+static void
+init_es1800_ops(void)
+{
+ es1800_ops.to_shortname = "es1800";
+ es1800_ops.to_longname = "Remote serial target in ES1800-emulator protocol";
+ es1800_ops.to_doc = "Remote debugging on the es1800 emulator via a serial line.\n\
+Specify the serial device it is connected to (e.g. /dev/ttya)." ;
+ es1800_ops.to_open = es1800_open;
+ es1800_ops.to_close = es1800_close;
+ es1800_ops.to_attach = es1800_attach;
+ es1800_ops.to_post_attach = NULL;
+ es1800_ops.to_require_attach = NULL;
+ es1800_ops.to_detach = es1800_detach;
+ es1800_ops.to_require_detach = NULL;
+ es1800_ops.to_resume = es1800_resume;
+ es1800_ops.to_wait = NULL;
+ es1800_ops.to_post_wait = NULL;
+ es1800_ops.to_fetch_registers = NULL;
+ es1800_ops.to_store_registers = NULL;
+ es1800_ops.to_prepare_to_store = es1800_prepare_to_store;
+ es1800_ops.to_xfer_memory = es1800_xfer_inferior_memory;
+ es1800_ops.to_files_info = es1800_files_info;
+ es1800_ops.to_insert_breakpoint = es1800_insert_breakpoint;
+ es1800_ops.to_remove_breakpoint = es1800_remove_breakpoint;
+ es1800_ops.to_terminal_init = NULL;
+ es1800_ops.to_terminal_inferior = NULL;
+ es1800_ops.to_terminal_ours_for_output = NULL;
+ es1800_ops.to_terminal_ours = NULL;
+ es1800_ops.to_terminal_info = NULL;
+ es1800_ops.to_kill = NULL;
+ es1800_ops.to_load = es1800_load;
+ es1800_ops.to_lookup_symbol = NULL;
+ es1800_ops.to_create_inferior = es1800_create_inferior;
+ es1800_ops.to_post_startup_inferior = NULL;
+ es1800_ops.to_acknowledge_created_inferior = NULL;
+ es1800_ops.to_clone_and_follow_inferior = NULL;
+ es1800_ops.to_post_follow_inferior_by_clone = NULL;
+ es1800_ops.to_insert_fork_catchpoint = NULL;
+ es1800_ops.to_remove_fork_catchpoint = NULL;
+ es1800_ops.to_insert_vfork_catchpoint = NULL;
+ es1800_ops.to_remove_vfork_catchpoint = NULL;
+ es1800_ops.to_has_forked = NULL;
+ es1800_ops.to_has_vforked = NULL;
+ es1800_ops.to_can_follow_vfork_prior_to_exec = NULL;
+ es1800_ops.to_post_follow_vfork = NULL;
+ es1800_ops.to_insert_exec_catchpoint = NULL;
+ es1800_ops.to_remove_exec_catchpoint = NULL;
+ es1800_ops.to_has_execd = NULL;
+ es1800_ops.to_reported_exec_events_per_exec_call = NULL;
+ es1800_ops.to_has_exited = NULL;
+ es1800_ops.to_mourn_inferior = NULL;
+ es1800_ops.to_can_run = 0;
+ es1800_ops.to_notice_signals = 0;
+ es1800_ops.to_thread_alive = 0;
+ es1800_ops.to_stop = 0;
+ es1800_ops.to_pid_to_exec_file = NULL;
+ es1800_ops.to_core_file_to_sym_file = NULL;
+ es1800_ops.to_stratum = core_stratum;
+ es1800_ops.DONT_USE = 0;
+ es1800_ops.to_has_all_memory = 0;
+ es1800_ops.to_has_memory = 1;
+ es1800_ops.to_has_stack = 0;
+ es1800_ops.to_has_registers = 0;
+ es1800_ops.to_has_execution = 0;
+ es1800_ops.to_sections = NULL;
+ es1800_ops.to_sections_end = NULL;
+ es1800_ops.to_magic = OPS_MAGIC ;
+}
+
+/* Define the target subroutine names */
+
+struct target_ops es1800_child_ops ;
+
+static void
+init_es1800_child_ops(void)
+{
+ es1800_child_ops.to_shortname = "es1800_process";
+ es1800_child_ops.to_longname = "Remote serial target in ES1800-emulator protocol";
+ es1800_child_ops.to_doc = "Remote debugging on the es1800 emulator via a serial line.\n\
+Specify the serial device it is connected to (e.g. /dev/ttya).";
+ es1800_child_ops.to_open = es1800_child_open;
+ es1800_child_ops.to_close = NULL;
+ es1800_child_ops.to_attach = es1800_attach;
+ es1800_child_ops.to_post_attach = NULL;
+ es1800_child_ops.to_require_attach = NULL;
+ es1800_child_ops.to_detach = es1800_child_detach;
+ es1800_child_ops.to_require_detach = NULL;
+ es1800_child_ops.to_resume = es1800_resume;
+ es1800_child_ops.to_wait = es1800_wait;
+ es1800_child_ops.to_post_wait = NULL;
+ es1800_child_ops.to_fetch_registers = es1800_fetch_register;
+ es1800_child_ops.to_store_registers = es1800_store_register;
+ es1800_child_ops.to_prepare_to_store = es1800_prepare_to_store;
+ es1800_child_ops.to_xfer_memory = es1800_xfer_inferior_memory;
+ es1800_child_ops.to_files_info = es1800_files_info;
+ es1800_child_ops.to_insert_breakpoint = es1800_insert_breakpoint;
+ es1800_child_ops.to_remove_breakpoint = es1800_remove_breakpoint;
+ es1800_child_ops.to_terminal_init = NULL;
+ es1800_child_ops.to_terminal_inferior = NULL;
+ es1800_child_ops.to_terminal_ours_for_output = NULL;
+ es1800_child_ops.to_terminal_ours = NULL;
+ es1800_child_ops.to_terminal_info = NULL;
+ es1800_child_ops.to_kill = es1800_kill;
+ es1800_child_ops.to_load = es1800_load;
+ es1800_child_ops.to_lookup_symbol = NULL;
+ es1800_child_ops.to_create_inferior = es1800_create_inferior;
+ es1800_child_ops.to_post_startup_inferior = NULL;
+ es1800_child_ops.to_acknowledge_created_inferior = NULL;
+ es1800_child_ops.to_clone_and_follow_inferior = NULL;
+ es1800_child_ops.to_post_follow_inferior_by_clone = NULL;
+ es1800_child_ops.to_insert_fork_catchpoint = NULL;
+ es1800_child_ops.to_remove_fork_catchpoint = NULL;
+ es1800_child_ops.to_insert_vfork_catchpoint = NULL;
+ es1800_child_ops.to_remove_vfork_catchpoint = NULL;
+ es1800_child_ops.to_has_forked = NULL;
+ es1800_child_ops.to_has_vforked = NULL;
+ es1800_child_ops.to_can_follow_vfork_prior_to_exec = NULL;
+ es1800_child_ops.to_post_follow_vfork = NULL;
+ es1800_child_ops.to_insert_exec_catchpoint = NULL;
+ es1800_child_ops.to_remove_exec_catchpoint = NULL;
+ es1800_child_ops.to_has_execd = NULL;
+ es1800_child_ops.to_reported_exec_events_per_exec_call = NULL;
+ es1800_child_ops.to_has_exited = NULL;
+ es1800_child_ops.to_mourn_inferior = es1800_mourn_inferior;
+ es1800_child_ops.to_can_run = 0;
+ es1800_child_ops.to_notice_signals = 0;
+ es1800_child_ops.to_thread_alive = 0;
+ es1800_child_ops.to_stop = 0;
+ es1800_child_ops.to_pid_to_exec_file = NULL;
+ es1800_child_ops.to_core_file_to_sym_file = NULL;
+ es1800_child_ops.to_stratum = process_stratum;
+ es1800_child_ops.DONT_USE = 0;
+ es1800_child_ops.to_has_all_memory = 1;
+ es1800_child_ops.to_has_memory = 1;
+ es1800_child_ops.to_has_stack = 1;
+ es1800_child_ops.to_has_registers = 1;
+ es1800_child_ops.to_has_execution = 1;
+ es1800_child_ops.to_sections = NULL;
+ es1800_child_ops.to_sections_end = NULL;
+ es1800_child_ops.to_magic = OPS_MAGIC;
+}
+
+void
+_initialize_es1800 ()
+{
+ init_es1800_ops() ;
+ init_es1800_child_ops() ;
+ add_target (&es1800_ops);
+ add_target (&es1800_child_ops);
+#ifdef PROVIDE_TRANSPARENT
+ add_com ("transparent", class_support, es1800_transparent,
+ "Start transparent communication with the ES 1800 emulator.");
+#endif /* PROVIDE_TRANSPARENT */
+ add_com ("init_break", class_support, es1800_init_break,
+ "Download break routine and initialize break facility on ES 1800");
+}
diff --git a/gdb/remote-est.c b/gdb/remote-est.c
new file mode 100644
index 00000000000..27fd8aa5184
--- /dev/null
+++ b/gdb/remote-est.c
@@ -0,0 +1,171 @@
+/* Remote debugging interface for EST-300 ICE, for GDB
+ Copyright 1995 Free Software Foundation, Inc.
+ Contributed by Cygnus Support.
+
+ Written by Steve Chamberlain for Cygnus Support.
+ Re-written by Stu Grossman of 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "gdbcore.h"
+#include "target.h"
+#include "monitor.h"
+#include "serial.h"
+
+static void est_open PARAMS ((char *args, int from_tty));
+
+static void
+est_supply_register (regname, regnamelen, val, vallen)
+ char *regname;
+ int regnamelen;
+ char *val;
+ int vallen;
+{
+ int regno;
+
+ if (regnamelen != 2)
+ return;
+
+ switch (regname[0])
+ {
+ case 'S':
+ if (regname[1] != 'R')
+ return;
+ regno = PS_REGNUM;
+ break;
+ case 'P':
+ if (regname[1] != 'C')
+ return;
+ regno = PC_REGNUM;
+ break;
+ case 'D':
+ if (regname[1] < '0' || regname[1] > '7')
+ return;
+ regno = regname[1] - '0' + D0_REGNUM;
+ break;
+ case 'A':
+ if (regname[1] < '0' || regname[1] > '7')
+ return;
+ regno = regname[1] - '0' + A0_REGNUM;
+ break;
+ default:
+ return;
+ }
+
+ monitor_supply_register (regno, val);
+}
+
+/*
+ * This array of registers needs to match the indexes used by GDB. The
+ * whole reason this exists is because the various ROM monitors use
+ * different names than GDB does, and don't support all the
+ * registers either. So, typing "info reg sp" becomes a "r30".
+ */
+
+static char *est_regnames[NUM_REGS] =
+{
+ "D0", "D1", "D2", "D3", "D4", "D5", "D6", "D7",
+ "A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7",
+ "SR", "PC",
+};
+
+/*
+ * Define the monitor command strings. Since these are passed directly
+ * through to a printf style function, we need can include formatting
+ * strings. We also need a CR or LF on the end.
+ */
+
+static struct target_ops est_ops;
+
+static char *est_inits[] = {"he\r", /* Resets the prompt, and clears repeated cmds */
+ NULL};
+
+static struct monitor_ops est_cmds ;
+
+static void
+init_est_cmds(void)
+{
+ est_cmds.flags = MO_CLR_BREAK_USES_ADDR | MO_FILL_USES_ADDR | MO_NEED_REGDUMP_AFTER_CONT |
+ MO_SREC_ACK | MO_SREC_ACK_PLUS ;
+ est_cmds.init = est_inits; /* Init strings */
+ est_cmds.cont = "go\r"; /* continue command */
+ est_cmds.step = "sidr\r"; /* single step */
+ est_cmds.stop = "\003"; /* ^C interrupts the program */
+ est_cmds.set_break = "sb %x\r"; /* set a breakpoint */
+ est_cmds.clr_break = "rb %x\r"; /* clear a breakpoint */
+ est_cmds.clr_all_break = "rb\r"; /* clear all breakpoints */
+ est_cmds.fill = "bfb %x %x %x\r"; /* fill (start end val) */
+ est_cmds.setmem.cmdb = "smb %x %x\r"; /* setmem.cmdb (addr, value) */
+ est_cmds.setmem.cmdw = "smw %x %x\r"; /* setmem.cmdw (addr, value) */
+ est_cmds.setmem.cmdl = "sml %x %x\r"; /* setmem.cmdl (addr, value) */
+ est_cmds.setmem.cmdll = NULL; /* setmem.cmdll (addr, value) */
+ est_cmds.setmem.resp_delim = NULL; /* setreg.resp_delim */
+ est_cmds.setmem.term = NULL; /* setreg.term */
+ est_cmds.setmem.term_cmd = NULL; /* setreg.term_cmd */
+ est_cmds.getmem.cmdb = "dmb %x %x\r"; /* getmem.cmdb (addr, len) */
+ est_cmds.getmem.cmdw = "dmw %x %x\r"; /* getmem.cmdw (addr, len) */
+ est_cmds.getmem.cmdl = "dml %x %x\r"; /* getmem.cmdl (addr, len) */
+ est_cmds.getmem.cmdll = NULL; /* getmem.cmdll (addr, len) */
+ est_cmds.getmem.resp_delim = ": "; /* getmem.resp_delim */
+ est_cmds.getmem.term = NULL; /* getmem.term */
+ est_cmds.getmem.term_cmd = NULL; /* getmem.term_cmd */
+ est_cmds.setreg.cmd = "sr %s %x\r"; /* setreg.cmd (name, value) */
+ est_cmds.setreg.resp_delim = NULL; /* setreg.resp_delim */
+ est_cmds.setreg.term = NULL; /* setreg.term */
+ est_cmds.setreg.term_cmd = NULL; /* setreg.term_cmd */
+ est_cmds.getreg.cmd = "dr %s\r"; /* getreg.cmd (name) */
+ est_cmds.getreg.resp_delim = " = "; /* getreg.resp_delim */
+ est_cmds.getreg.term = NULL; /* getreg.term */
+ est_cmds.getreg.term_cmd = NULL ; /* getreg.term_cmd */
+ est_cmds.dump_registers = "dr\r"; /* dump_registers */
+ est_cmds.register_pattern = "\\(\\w+\\) = \\([0-9a-fA-F]+\\)"; /* register_pattern */
+ est_cmds.supply_register = est_supply_register; /* supply_register */
+ est_cmds.load_routine = NULL; /* load_routine (defaults to SRECs) */
+ est_cmds.load = "dl\r"; /* download command */
+ est_cmds.loadresp = "+"; /* load response */
+ est_cmds.prompt = ">BKM>"; /* monitor command prompt */
+ est_cmds.line_term = "\r"; /* end-of-line terminator */
+ est_cmds.cmd_end = NULL; /* optional command terminator */
+ est_cmds.target = &est_ops; /* target operations */
+ est_cmds.stopbits = SERIAL_1_STOPBITS; /* number of stop bits */
+ est_cmds.regnames = est_regnames; /* registers names */
+ est_cmds.magic = MONITOR_OPS_MAGIC ; /* magic */
+} /* init_est_cmds */
+
+static void
+est_open(args, from_tty)
+ char *args;
+ int from_tty;
+{
+ monitor_open (args, &est_cmds, from_tty);
+}
+
+void
+_initialize_est ()
+{
+ init_est_cmds() ;
+ init_monitor_ops (&est_ops);
+
+ est_ops.to_shortname = "est";
+ est_ops.to_longname = "EST background debug monitor";
+ est_ops.to_doc = "Debug via the EST BDM.\n\
+Specify the serial device it is connected to (e.g. /dev/ttya).";
+ est_ops.to_open = est_open;
+
+ add_target (&est_ops);
+}
diff --git a/gdb/remote-hms.c b/gdb/remote-hms.c
new file mode 100644
index 00000000000..3ca8455d979
--- /dev/null
+++ b/gdb/remote-hms.c
@@ -0,0 +1,1500 @@
+/* Remote debugging interface for Hitachi HMS Monitor Version 1.0
+ Copyright 1995 Free Software Foundation, Inc.
+ Contributed by Cygnus Support. Written by Steve Chamberlain
+ (sac@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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "gdbcore.h"
+#include "target.h"
+#include "monitor.h"
+#include "serial.h"
+
+static void hms_open PARAMS ((char *args, int from_tty));
+static void
+hms_supply_register (regname, regnamelen, val, vallen)
+ char *regname;
+ int regnamelen;
+ char *val;
+ int vallen;
+{
+ int regno;
+
+ if (regnamelen != 2)
+ return;
+ if (regname[0] != 'P')
+ return;
+ /* We scan off all the registers in one go */
+
+ val = monitor_supply_register (PC_REGNUM, val);
+ /* Skip the ccr string */
+ while (*val != '=' && *val)
+ val++;
+
+ val = monitor_supply_register (CCR_REGNUM, val + 1);
+
+ /* Skip up to rest of regs */
+ while (*val != '=' && *val)
+ val++;
+
+ for (regno = 0; regno < 7; regno++)
+ {
+ val = monitor_supply_register (regno, val + 1);
+ }
+}
+
+/*
+ * This array of registers needs to match the indexes used by GDB. The
+ * whole reason this exists is because the various ROM monitors use
+ * different names than GDB does, and don't support all the
+ * registers either. So, typing "info reg sp" becomes a "r30".
+ */
+
+static char *hms_regnames[NUM_REGS] =
+{
+ "R0", "R1", "R2", "R3", "R4", "R5", "R6", "R7", "CCR", "PC"
+};
+
+/*
+ * Define the monitor command strings. Since these are passed directly
+ * through to a printf style function, we need can include formatting
+ * strings. We also need a CR or LF on the end.
+ */
+
+static struct target_ops hms_ops;
+
+static char *hms_inits[] =
+{"\003", /* Resets the prompt, and clears repeated cmds */
+ NULL};
+
+static struct monitor_ops hms_cmds ;
+
+static void
+init_hms_cmds(void)
+{
+ hms_cmds.flags = MO_CLR_BREAK_USES_ADDR | MO_FILL_USES_ADDR | MO_GETMEM_NEEDS_RANGE;
+ hms_cmds.init = hms_inits; /* Init strings */
+ hms_cmds.cont = "g\r"; /* continue command */
+ hms_cmds.step = "s\r"; /* single step */
+ hms_cmds.stop = "\003"; /* ^C interrupts the program */
+ hms_cmds.set_break = "b %x\r"; /* set a breakpoint */
+ hms_cmds.clr_break = "b - %x\r"; /* clear a breakpoint */
+ hms_cmds.clr_all_break = "b -\r"; /* clear all breakpoints */
+ hms_cmds.fill = "f %x %x %x\r"; /* fill (start end val) */
+ hms_cmds.setmem.cmdb = "m.b %x=%x\r"; /* setmem.cmdb (addr, value) */
+ hms_cmds.setmem.cmdw = "m.w %x=%x\r"; /* setmem.cmdw (addr, value) */
+ hms_cmds.setmem.cmdl = NULL; /* setmem.cmdl (addr, value) */
+ hms_cmds.setmem.cmdll = NULL; /* setmem.cmdll (addr, value) */
+ hms_cmds.setmem.resp_delim = NULL;/* setreg.resp_delim */
+ hms_cmds.setmem.term = NULL; /* setreg.term */
+ hms_cmds.setmem.term_cmd = NULL; /* setreg.term_cmd */
+ hms_cmds.getmem.cmdb = "m.b %x %x\r"; /* getmem.cmdb (addr, addr) */
+ hms_cmds.getmem.cmdw = "m.w %x %x\r"; /* getmem.cmdw (addr, addr) */
+ hms_cmds.getmem.cmdl = NULL; /* getmem.cmdl (addr, addr) */
+ hms_cmds.getmem.cmdll = NULL; /* getmem.cmdll (addr, addr) */
+ hms_cmds.getmem.resp_delim = ": ";/* getmem.resp_delim */
+ hms_cmds.getmem.term = ">"; /* getmem.term */
+ hms_cmds.getmem.term_cmd = "\003";/* getmem.term_cmd */
+ hms_cmds.setreg.cmd = "r %s=%x\r";/* setreg.cmd (name, value) */
+ hms_cmds.setreg.resp_delim = NULL;/* setreg.resp_delim */
+ hms_cmds.setreg.term = NULL; /* setreg.term */
+ hms_cmds.setreg.term_cmd = NULL; /* setreg.term_cmd */
+ hms_cmds.getreg.cmd = "r %s\r"; /* getreg.cmd (name) */
+ hms_cmds.getreg.resp_delim = " (";/* getreg.resp_delim */
+ hms_cmds.getreg.term = ":"; /* getreg.term */
+ hms_cmds.getreg.term_cmd = "\003";/* getreg.term_cmd */
+ hms_cmds.dump_registers = "r\r"; /* dump_registers */
+ hms_cmds.register_pattern = "\\(\\w+\\)=\\([0-9a-fA-F]+\\)"; /* register_pattern */
+ hms_cmds.supply_register = hms_supply_register; /* supply_register */
+ hms_cmds.load_routine = NULL; /* load_routine (defaults to SRECs) */
+ hms_cmds.load = "tl\r"; /* download command */
+ hms_cmds.loadresp = NULL; /* load response */
+ hms_cmds.prompt = ">"; /* monitor command prompt */
+ hms_cmds.line_term = "\r"; /* end-of-command delimitor */
+ hms_cmds.cmd_end = NULL; /* optional command terminator */
+ hms_cmds.target = &hms_ops; /* target operations */
+ hms_cmds.stopbits = SERIAL_1_STOPBITS;/* number of stop bits */
+ hms_cmds.regnames = hms_regnames; /* registers names */
+ hms_cmds.magic = MONITOR_OPS_MAGIC; /* magic */
+} /* init_hms-cmds */
+
+static void
+hms_open (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ monitor_open (args, &hms_cmds, from_tty);
+}
+
+int write_dos_tick_delay;
+
+void
+_initialize_remote_hms ()
+{
+ init_hms_cmds() ;
+ init_monitor_ops (&hms_ops);
+
+ hms_ops.to_shortname = "hms";
+ hms_ops.to_longname = "Hitachi Microsystems H8/300 debug monitor";
+ hms_ops.to_doc = "Debug via the HMS monitor.\n\
+Specify the serial device it is connected to (e.g. /dev/ttya).";
+ hms_ops.to_open = hms_open;
+ /* By trial and error I've found that this delay doesn't break things */
+ write_dos_tick_delay = 1;
+ add_target (&hms_ops);
+}
+
+#if 0
+/* This is kept here because we used to support the H8/500 in this module,
+ and I haven't done the H8/500 yet */
+#include "defs.h"
+#include "inferior.h"
+#include "wait.h"
+#include "value.h"
+#include "gdb_string.h"
+#include <ctype.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <setjmp.h>
+#include <errno.h>
+#include "terminal.h"
+#include "target.h"
+#include "gdbcore.h"
+#include "serial.h"
+#include "remote-utils.h"
+/* External data declarations */
+extern int stop_soon_quietly; /* for wait_for_inferior */
+
+/* Forward data declarations */
+extern struct target_ops hms_ops; /* Forward declaration */
+
+/* Forward function declarations */
+static void hms_fetch_registers ();
+static int hms_store_registers ();
+static void hms_close ();
+static int hms_clear_breakpoints ();
+
+extern struct target_ops hms_ops;
+static void hms_drain ();
+static void add_commands ();
+static void remove_commands ();
+
+static int quiet = 1; /* FIXME - can be removed after Dec '94 */
+
+
+
+/***********************************************************************
+ * I/O stuff stolen from remote-eb.c
+ ***********************************************************************/
+
+static int timeout = 2;
+
+static const char *dev_name;
+
+/* Descriptor for I/O to remote machine. Initialize it to -1 so that
+ hms_open knows that we don't have a file open when the program
+ starts. */
+
+static int before = 0xdead;
+static int is_open = 0;
+static int after = 0xdead;
+int
+check_open ()
+{
+ if (before != 0xdead
+ || after != 0xdead)
+ printf ("OUTCH! \n");
+ if (!is_open)
+ {
+ error ("remote device not open");
+ }
+}
+
+#define ON 1
+#define OFF 0
+
+/* Read a character from the remote system, doing all the fancy
+ timeout stuff. */
+static int
+readchar ()
+{
+ int buf;
+
+ buf = SERIAL_READCHAR (desc, timeout);
+
+ if (buf == SERIAL_TIMEOUT)
+ {
+ hms_write (".\r\n", 3);
+ error ("Timeout reading from remote system.");
+ }
+ if (buf == SERIAL_ERROR)
+ {
+ error ("Serial port error!");
+ }
+
+ if (!quiet || remote_debug)
+ printf_unfiltered ("%c", buf);
+
+ return buf & 0x7f;
+}
+
+static void
+flush ()
+{
+ while (1)
+ {
+ int b = SERIAL_READCHAR (desc, 0);
+ if (b == SERIAL_TIMEOUT)
+ return;
+ }
+}
+
+static int
+readchar_nofail ()
+{
+ int buf;
+
+ buf = SERIAL_READCHAR (desc, timeout);
+ if (buf == SERIAL_TIMEOUT)
+ buf = 0;
+ if (!quiet || remote_debug)
+ printf_unfiltered ("%c", buf);
+
+ return buf & 0x7f;
+
+}
+
+/* Keep discarding input from the remote system, until STRING is found.
+ Let the user break out immediately. */
+static void
+expect (string)
+ char *string;
+{
+ char *p = string;
+ char c;
+ immediate_quit = 1;
+ while (1)
+ {
+ c = readchar ();
+ if (c == *p)
+ {
+ p++;
+ if (*p == '\0')
+ {
+ immediate_quit = 0;
+ return;
+ }
+ }
+ else
+ {
+ p = string;
+ if (c == *p)
+ p++;
+ }
+ }
+}
+
+/* Keep discarding input until we see the hms prompt.
+
+ The convention for dealing with the prompt is that you
+ o give your command
+ o *then* wait for the prompt.
+
+ Thus the last thing that a procedure does with the serial line
+ will be an expect_prompt(). Exception: hms_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 hms_wait which does wait for the prompt.
+ Note that this includes abnormal exit, e.g. error(). This is
+ necessary to prevent getting into states from which we can't
+ recover. */
+static void
+expect_prompt ()
+{
+ expect ("HMS>");
+}
+
+/* Get a hex digit from the remote system & return its value.
+ If ignore_space is nonzero, ignore spaces (not newline, tab, etc). */
+static int
+get_hex_digit (ignore_space)
+ int ignore_space;
+{
+ int ch;
+
+ while (1)
+ {
+ ch = readchar ();
+ if (ch >= '0' && ch <= '9')
+ return ch - '0';
+ else if (ch >= 'A' && ch <= 'F')
+ return ch - 'A' + 10;
+ else if (ch >= 'a' && ch <= 'f')
+ return ch - 'a' + 10;
+ else if (ch == ' ' && ignore_space)
+ ;
+ else
+ {
+ expect_prompt ();
+ error ("Invalid hex digit from remote system.");
+ }
+ }
+}
+
+/* Get a byte from hms_desc and put it in *BYT. Accept any number
+ leading spaces. */
+static void
+get_hex_byte (byt)
+ char *byt;
+{
+ int val;
+
+ val = get_hex_digit (1) << 4;
+ val |= get_hex_digit (0);
+ *byt = val;
+}
+
+/* Read a 32-bit hex word from the hms, preceded by a space */
+static long
+get_hex_word ()
+{
+ long val;
+ int j;
+
+ val = 0;
+ for (j = 0; j < 8; j++)
+ val = (val << 4) + get_hex_digit (j == 0);
+ return val;
+}
+
+/* Called when SIGALRM signal sent due to alarm() timeout. */
+
+/* Number of SIGTRAPs we need to simulate. That is, the next
+ NEED_ARTIFICIAL_TRAP calls to hms_wait should just return
+ SIGTRAP without actually waiting for anything. */
+
+static int need_artificial_trap = 0;
+
+void
+hms_kill (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+
+}
+
+/* This is called not only when we first attach, but also when the
+ user types "run" after having attached. */
+void
+hms_create_inferior (execfile, args, env)
+ char *execfile;
+ char *args;
+ char **env;
+{
+ int entry_pt;
+ char buffer[100];
+
+ if (args && *args)
+ error ("Can't pass arguments to remote hms process.");
+
+ if (execfile == 0 || exec_bfd == 0)
+ error ("No executable file specified");
+
+ entry_pt = (int) bfd_get_start_address (exec_bfd);
+ check_open ();
+
+ hms_kill (NULL, NULL);
+ hms_clear_breakpoints ();
+ init_wait_for_inferior ();
+ hms_write_cr ("");
+ expect_prompt ();
+
+ insert_breakpoints (); /* Needed to get correct instruction in cache */
+ proceed (entry_pt, TARGET_SIGNAL_DEFAULT, 0);
+}
+
+/* Open a connection to a remote debugger.
+ NAME is the filename used for communication, then a space,
+ then the baud rate.
+ */
+
+static char *
+find_end_of_word (s)
+ char *s;
+{
+ while (*s && !isspace (*s))
+ s++;
+ return s;
+}
+
+static char *
+get_word (p)
+ char **p;
+{
+ char *s = *p;
+ char *word;
+ char *copy;
+ size_t len;
+
+ while (isspace (*s))
+ s++;
+
+ word = s;
+
+ len = 0;
+
+ while (*s && !isspace (*s))
+ {
+ s++;
+ len++;
+
+ }
+ copy = xmalloc (len + 1);
+ memcpy (copy, word, len);
+ copy[len] = 0;
+ *p = s;
+ return copy;
+}
+
+static int baudrate = 9600;
+
+static int
+is_baudrate_right ()
+{
+ int ok;
+
+ /* Put this port into NORMAL mode, send the 'normal' character */
+
+ hms_write ("\001", 1); /* Control A */
+ hms_write ("\r\n", 2); /* Cr */
+
+ while (1)
+ {
+ ok = SERIAL_READCHAR (desc, timeout);
+ if (ok < 0)
+ break;
+ }
+
+ hms_write ("r", 1);
+
+ if (readchar_nofail () == 'r')
+ return 1;
+
+ /* Not the right baudrate, or the board's not on */
+ return 0;
+}
+static void
+set_rate ()
+{
+ if (!SERIAL_SETBAUDRATE (desc, baudrate))
+ error ("Can't set baudrate");
+}
+
+
+
+/* Close out all files and local state before this target loses control. */
+
+static void
+hms_close (quitting)
+ int quitting;
+{
+ /* Clear any break points */
+ remove_commands ();
+ hms_clear_breakpoints ();
+ sleep (1); /* Let any output make it all the way back */
+ if (is_open)
+ {
+ SERIAL_WRITE (desc, "R\r\n", 3);
+ SERIAL_CLOSE (desc);
+ }
+ is_open = 0;
+}
+
+/* Terminate the open connection to the remote debugger. Use this
+ when you want to detach and do something else with your gdb. */ void
+hms_detach (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ if (is_open)
+ {
+ hms_clear_breakpoints ();
+ }
+
+ pop_target (); /* calls hms_close to do the real work
+ */
+ if (from_tty)
+ printf_filtered ("Ending remote %s debugging\n",
+ target_shortname);
+}
+
+/* Tell the remote machine to resume. */
+
+void
+hms_resume (pid, step, sig)
+ int pid, step;
+ enum target_signal
+ sig;
+{
+ if (step)
+ {
+ hms_write_cr ("s");
+ expect ("Step>");
+
+ /* Force the next hms_wait to return a trap. Not doing anything
+ about I/O from the target means that the user has to type "continue"
+ to see any. FIXME, this should be fixed. */
+ need_artificial_trap = 1;
+ }
+ else
+ {
+ hms_write_cr ("g");
+ expect ("g");
+ }
+}
+
+/* Wait until the remote machine stops, then return, storing status in
+ STATUS just as `wait' would. */
+
+int
+hms_wait (pid, status)
+ int pid;
+ struct target_waitstatus *status;
+{
+ /* Strings to look for. '?' means match any single character. Note
+ that with the algorithm we use, the initial character of the string
+ cannot recur in the string, or we will not find some cases of the
+ string in the input. */
+
+ static char bpt[] = "At breakpoint:";
+
+ /* It would be tempting to look for "\n[__exit + 0x8]\n" but that
+ requires loading symbols with "yc i" and even if we did do that we
+ don't know that the file has symbols. */
+ static char exitmsg[] = "HMS>";
+ char *bp = bpt;
+ char *ep = exitmsg;
+
+ /* Large enough for either sizeof (bpt) or sizeof (exitmsg) chars.
+ */
+ char swallowed[50];
+
+ /* Current position in swallowed. */
+ char *swallowed_p = swallowed;
+
+ int ch;
+ int ch_handled;
+ int old_timeout = timeout;
+ int
+ old_immediate_quit = immediate_quit;
+ int swallowed_cr = 0;
+
+ status->kind = TARGET_WAITKIND_EXITED;
+ status->value.integer = 0;
+
+ if (need_artificial_trap != 0)
+ {
+ status->kind =
+ TARGET_WAITKIND_STOPPED;
+ status->value.sig = TARGET_SIGNAL_TRAP;
+ need_artificial_trap--;
+ return 0;
+ }
+
+ timeout = 5; /* Don't time out for a while - user program is running.
+ */
+ immediate_quit = 1; /* Helps ability to QUIT */
+ while (1)
+ {
+ QUIT; /* Let user quit and leave process running */
+ ch_handled = 0;
+ ch = readchar ();
+ if (ch == *bp)
+ {
+ bp++;
+ if (*bp == '\0')
+ break;
+ ch_handled = 1;
+
+ *swallowed_p++ = ch;
+ }
+ else
+ {
+ bp = bpt;
+ }
+ if
+ (ch == *ep || *ep == '?')
+ {
+ ep++;
+ if (*ep == '\0')
+ break;
+
+ if (!ch_handled)
+ *swallowed_p++ = ch;
+ ch_handled =
+ 1;
+ }
+ else
+ {
+ ep = exitmsg;
+ }
+
+ if (!ch_handled)
+ {
+ char *p;
+
+ /* Print out any characters which have been swallowed. */
+ for (p = swallowed; p < swallowed_p; ++p)
+ putchar_unfiltered (*p);
+ swallowed_p = swallowed;
+
+ if ((ch != '\r' && ch != '\n') || swallowed_cr > 10)
+ {
+ putchar_unfiltered (ch);
+ swallowed_cr = 10;
+ }
+ swallowed_cr++;
+
+ }
+ }
+ if (*bp == '\0')
+ {
+ status->kind = TARGET_WAITKIND_STOPPED;
+ status->value.sig = TARGET_SIGNAL_TRAP;
+ expect_prompt ();
+ }
+ else
+ {
+ status->kind = TARGET_WAITKIND_EXITED;
+ status->value.integer =
+ TARGET_SIGNAL_STOP;
+ }
+
+ timeout = old_timeout;
+ immediate_quit = old_immediate_quit;
+ return
+ 0;
+}
+
+/* Return the name of register number REGNO in the form input and
+ output by hms.
+
+ Returns a pointer to a static buffer containing the answer. */
+static char *
+get_reg_name (regno)
+ int regno;
+{
+ static char *rn[] =
+ REGISTER_NAMES;
+
+ return rn[regno];
+}
+
+/* Read the remote registers. */
+
+static int
+gethex (length, start, ok)
+ unsigned int length;
+ char *start;
+ int *ok;
+{
+ int result = 0;
+
+ while (length--)
+ {
+ result <<= 4;
+ if (*start >= 'a' && *start <= 'f')
+ {
+ result += *start - 'a' + 10;
+ }
+ else if (*start >= 'A' &&
+ *start <= 'F')
+ {
+ result += *start - 'A' + 10;
+ }
+ else if
+ (*start >= '0' && *start <= '9')
+ {
+ result += *start - '0';
+ }
+ else
+ *ok = 0;
+ start++;
+
+ }
+ return result;
+}
+static int
+timed_read (buf, n, timeout)
+ char
+ *buf;
+
+{
+ int i;
+ char c;
+
+ i = 0;
+ while (i < n)
+ {
+ c = readchar ();
+
+ if (c == 0)
+ return i;
+ buf[i] = c;
+ i++;
+
+ }
+ return i;
+}
+
+hms_write (a, l)
+ char *a;
+{
+ int i;
+
+ SERIAL_WRITE (desc, a, l);
+
+ if (!quiet || remote_debug)
+ {
+ printf_unfiltered ("<");
+ for (i = 0; i < l; i++)
+ {
+ printf_unfiltered ("%c", a[i]);
+ }
+ printf_unfiltered (">");
+ }
+}
+
+hms_write_cr (s)
+ char *s;
+{
+ hms_write (s, strlen (s));
+ hms_write ("\r\n", 2);
+}
+
+#ifdef GDB_TARGET_IS_H8500
+
+/* H8/500 monitor reg dump looks like:
+
+ HMS>r
+ PC:8000 SR:070C .7NZ.. CP:00 DP:00 EP:00 TP:00 BR:00
+ R0-R7: FF5A 0001 F4FE F500 0000 F528 F528 F4EE
+ HMS>
+
+
+ */
+
+supply_val (n, size, ptr, segptr)
+ int n;
+ int size;
+ char *ptr;
+ char *segptr;
+{
+ int ok;
+ char raw[4];
+ switch (size)
+ {
+ case 2:
+ raw[0] = gethex (2, ptr, &ok);
+ raw[1] = gethex (2, ptr + 2, &ok);
+ supply_register (n, raw);
+ break;
+ case 1:
+ raw[0] = gethex (2, ptr, &ok);
+ supply_register (n, raw);
+ break;
+ case 4:
+ {
+ int v = gethex (4, ptr, &ok);
+ v |= gethex (2, segptr, &ok) << 16;
+ raw[0] = 0;
+ raw[1] = (v >> 16) & 0xff;
+ raw[2] = (v >> 8) & 0xff;
+ raw[3] = (v >> 0) & 0xff;
+ supply_register (n, raw);
+ }
+ }
+
+}
+static void
+hms_fetch_register (dummy)
+ int dummy;
+{
+#define REGREPLY_SIZE 108
+ char linebuf[REGREPLY_SIZE + 1];
+ int i;
+ int s;
+ int gottok;
+
+ LONGEST reg[NUM_REGS];
+ check_open ();
+
+ do
+ {
+
+ hms_write_cr ("r");
+ expect ("r");
+ s = timed_read (linebuf + 1, REGREPLY_SIZE, 1);
+
+ linebuf[REGREPLY_SIZE] = 0;
+ gottok = 0;
+ if (linebuf[3] == 'P' &&
+ linebuf[4] == 'C' &&
+ linebuf[5] == ':' &&
+ linebuf[105] == 'H' &&
+ linebuf[106] == 'M' &&
+ linebuf[107] == 'S')
+ {
+
+ /*
+ 012
+ r**
+ -------1---------2---------3---------4---------5-----
+ 345678901234567890123456789012345678901234567890123456
+ PC:8000 SR:070C .7NZ.. CP:00 DP:00 EP:00 TP:00 BR:00**
+ ---6---------7---------8---------9--------10----
+ 789012345678901234567890123456789012345678901234
+ R0-R7: FF5A 0001 F4FE F500 0000 F528 F528 F4EE**
+
+ 56789
+ HMS>
+ */
+ gottok = 1;
+
+
+ supply_val (PC_REGNUM, 4, linebuf + 6, linebuf + 29);
+
+ supply_val (CCR_REGNUM, 2, linebuf + 14);
+ supply_val (SEG_C_REGNUM, 1, linebuf + 29);
+ supply_val (SEG_D_REGNUM, 1, linebuf + 35);
+ supply_val (SEG_E_REGNUM, 1, linebuf + 41);
+ supply_val (SEG_T_REGNUM, 1, linebuf + 47);
+ for (i = 0; i < 8; i++)
+ {
+ static int sr[8] =
+ {35, 35, 35, 35,
+ 41, 41, 47, 47};
+
+ char raw[4];
+ char *src = linebuf + 64 + 5 * i;
+ char *segsrc = linebuf + sr[i];
+ supply_val (R0_REGNUM + i, 2, src);
+ supply_val (PR0_REGNUM + i, 4, src, segsrc);
+ }
+ }
+ if (!gottok)
+ {
+ hms_write_cr ("");
+ expect ("HMS>");
+ }
+ }
+ while (!gottok);
+}
+#endif
+
+#ifdef GDB_TARGET_IS_H8300
+static void
+hms_fetch_register (dummy)
+ int dummy;
+{
+#define REGREPLY_SIZE 79
+ char linebuf[REGREPLY_SIZE + 1];
+ int i;
+ int s;
+ int gottok;
+
+ ULONGEST reg[NUM_REGS];
+
+ check_open ();
+
+ do
+ {
+ hms_write_cr ("r");
+
+ s = timed_read (linebuf, 1, 1);
+
+ while (linebuf[0] != 'r')
+ s = timed_read (linebuf, 1, 1);
+
+ s = timed_read (linebuf + 1, REGREPLY_SIZE - 1, 1);
+
+ linebuf[REGREPLY_SIZE] = 0;
+ gottok = 0;
+ if (linebuf[0] == 'r' &&
+ linebuf[3] == 'P' &&
+ linebuf[4] == 'C' &&
+ linebuf[5] == '=' &&
+ linebuf[75] == 'H' &&
+ linebuf[76] == 'M' &&
+ linebuf[77] == 'S')
+ {
+ /*
+ PC=XXXX CCR=XX:XXXXXXXX R0-R7= XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX
+ 5436789012345678901234567890123456789012345678901234567890123456789012
+ 0 1 2 3 4 5 6
+ */
+ gottok = 1;
+
+ reg[PC_REGNUM] = gethex (4, linebuf + 6, &gottok);
+ reg[CCR_REGNUM] = gethex (2, linebuf + 15, &gottok);
+ for (i = 0; i < 8; i++)
+ {
+ reg[i] = gethex (4, linebuf + 34 + 5 * i, &gottok);
+ }
+ }
+ }
+ while (!gottok);
+ for (i = 0; i < NUM_REGS; i++)
+ {
+ char swapped[2];
+
+ swapped[1] = reg[i];
+ swapped[0] = (reg[i]) >> 8;
+
+ supply_register (i, swapped);
+ }
+}
+#endif
+/* Store register REGNO, or all if REGNO == -1.
+ Return errno value. */
+static void
+hms_store_register (regno)
+ int regno;
+{
+ if (regno == -1)
+ {
+ for (regno = 0; regno < NUM_REGS; regno++)
+ {
+ hms_store_register (regno);
+ }
+ }
+ else
+ {
+ char *name = get_reg_name (regno);
+ char buffer[100];
+ /* Some regs dont really exist */
+ if (!(name[0] == 'p' && name[1] == 'r')
+ && !(name[0] == 'c' && name[1] == 'y')
+ && !(name[0] == 't' && name[1] == 'i')
+ && !(name[0] == 'i' && name[1] == 'n'))
+ {
+ sprintf (buffer, "r %s=%x", name, read_register (regno));
+ hms_write_cr (buffer);
+ expect_prompt ();
+ }
+ }
+}
+
+
+/* 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
+hms_prepare_to_store ()
+{
+ /* Do nothing, since we can store individual regs */
+}
+
+static CORE_ADDR
+translate_addr (addr)
+ CORE_ADDR addr;
+{
+
+ return (addr);
+
+}
+
+
+int
+hms_xfer_inferior_memory (memaddr, myaddr, len, write, target)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+ int write;
+ struct target_ops *target; /* ignored */
+{
+
+ return len;
+}
+
+int
+hms_write_inferior_memory (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ unsigned char *myaddr;
+ int len;
+{
+ bfd_vma addr;
+ int done;
+ int todo;
+ char buffer[100];
+ done = 0;
+ hms_write_cr (".");
+ expect_prompt ();
+ while (done < len)
+ {
+ char *ptr = buffer;
+ int thisgo;
+ int idx;
+
+ thisgo = len - done;
+ if (thisgo > 20)
+ thisgo = 20;
+
+ sprintf (ptr, "M.B %4x =", memaddr + done);
+ ptr += 10;
+ for (idx = 0; idx < thisgo; idx++)
+ {
+ sprintf (ptr, "%2x ", myaddr[idx + done]);
+ ptr += 3;
+ }
+ hms_write_cr (buffer);
+ expect_prompt ();
+ done += thisgo;
+ }
+}
+
+void
+hms_files_info ()
+{
+ char *file = "nothing";
+
+ if (exec_bfd)
+ file = bfd_get_filename (exec_bfd);
+
+ if (exec_bfd)
+#ifdef __GO32__
+ printf_filtered ("\tAttached to DOS asynctsr and running program %s\n", file);
+#else
+ printf_filtered ("\tAttached to %s at %d baud and running program %s\n", dev_name, baudrate, file);
+#endif
+ printf_filtered ("\ton an H8/300 processor.\n");
+}
+
+/* Copy LEN bytes of data from debugger memory at MYADDR
+ to inferior's memory at MEMADDR. Returns errno value.
+ * sb/sh instructions don't work on unaligned addresses, when TU=1.
+ */
+
+/* Read LEN bytes from inferior memory at MEMADDR. Put the result
+ at debugger address MYADDR. Returns errno value. */
+int
+hms_read_inferior_memory (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+{
+ /* Align to nearest low 16 bits */
+ int i;
+
+ CORE_ADDR start = memaddr;
+ CORE_ADDR end = memaddr + len - 1;
+
+ int ok = 1;
+
+ /*
+ AAAA: XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX '................'
+ 012345678901234567890123456789012345678901234567890123456789012345
+ 0 1 2 3 4 5 6
+ */
+ char buffer[66];
+
+ if (memaddr & 0xf)
+ abort ();
+ if (len != 16)
+ abort ();
+
+ sprintf (buffer, "m %4x %4x", start & 0xffff, end & 0xffff);
+
+ flush ();
+ hms_write_cr (buffer);
+ /* drop the echo and newline */
+ for (i = 0; i < 13; i++)
+ readchar ();
+
+ /* Grab the lines as they come out and fill the area */
+ /* Skip over cr */
+ while (1)
+ {
+ int p;
+ int i;
+ int addr;
+ size_t idx;
+
+ char byte[16];
+
+ buffer[0] = readchar ();
+ while (buffer[0] == '\r'
+ || buffer[0] == '\n')
+ buffer[0] = readchar ();
+
+ if (buffer[0] == 'M')
+ break;
+
+ for (i = 1; i < 50; i++)
+ {
+ buffer[i] = readchar ();
+ }
+ /* sometimes we loose characters in the ascii representation of the
+ data. I don't know where. So just scan for the end of line */
+ i = readchar ();
+ while (i != '\n' && i != '\r')
+ i = readchar ();
+
+ /* Now parse the line */
+
+ addr = gethex (4, buffer, &ok);
+ idx = 6;
+ for (p = 0; p < 16; p += 2)
+ {
+ byte[p] = gethex (2, buffer + idx, &ok);
+ byte[p + 1] = gethex (2, buffer + idx + 2, &ok);
+ idx += 5;
+ }
+
+ for (p = 0; p < 16; p++)
+ {
+ if (addr + p >= memaddr &&
+ addr + p < memaddr + len)
+ {
+ myaddr[(addr + p) - memaddr] = byte[p];
+
+ }
+
+ }
+ }
+#ifdef GDB_TARGET_IS_H8500
+ expect ("ore>");
+#endif
+#ifdef GDB_TARGET_IS_H8300
+ expect ("emory>");
+#endif
+ hms_write_cr (".");
+
+ expect_prompt ();
+ return len;
+}
+
+
+
+#define MAX_BREAKS 16
+static int num_brkpts = 0;
+static int
+hms_insert_breakpoint (addr, save)
+ CORE_ADDR addr;
+ char *save; /* Throw away, let hms save instructions */
+{
+ check_open ();
+
+ if (num_brkpts < MAX_BREAKS)
+ {
+ char buffer[100];
+
+ num_brkpts++;
+ sprintf (buffer, "b %x", addr & 0xffff);
+ hms_write_cr (buffer);
+ expect_prompt ();
+ return (0);
+ }
+ else
+ {
+ fprintf_filtered (gdb_stderr,
+ "Too many break points, break point not installed\n");
+ return (1);
+ }
+
+}
+static int
+hms_remove_breakpoint (addr, save)
+ CORE_ADDR addr;
+ char *save; /* Throw away, let hms save instructions */
+{
+ if (num_brkpts > 0)
+ {
+ char buffer[100];
+
+ num_brkpts--;
+ sprintf (buffer, "b - %x", addr & 0xffff);
+ hms_write_cr (buffer);
+ expect_prompt ();
+
+ }
+ return (0);
+}
+
+/* Clear the hmss notion of what the break points are */
+static int
+hms_clear_breakpoints ()
+{
+
+ if (is_open)
+ {
+ hms_write_cr ("b -");
+ expect_prompt ();
+ }
+ num_brkpts = 0;
+}
+static void
+hms_mourn ()
+{
+ hms_clear_breakpoints ();
+ unpush_target (&hms_ops);
+ generic_mourn_inferior ();
+}
+
+/* Put a command string, in args, out to the hms. The hms is assumed to
+ be in raw mode, all writing/reading done through desc.
+ Ouput from the hms is placed on the users terminal until the
+ prompt from the hms is seen.
+ FIXME: Can't handle commands that take input. */
+
+void
+hms_com (args, fromtty)
+ char *args;
+ int fromtty;
+{
+ check_open ();
+
+ if (!args)
+ return;
+
+ /* Clear all input so only command relative output is displayed */
+
+ hms_write_cr (args);
+/* hms_write ("\030", 1); */
+ expect_prompt ();
+}
+
+static void
+hms_open (name, from_tty)
+ char *name;
+ int from_tty;
+{
+ unsigned int prl;
+ char *p;
+
+ if (name == 0)
+ {
+ name = "";
+ }
+ if (is_open)
+ hms_close (0);
+ dev_name = strdup (name);
+
+ if (!(desc = SERIAL_OPEN (dev_name)))
+ perror_with_name ((char *) dev_name);
+
+ SERIAL_RAW (desc);
+ is_open = 1;
+ push_target (&hms_ops);
+ dcache_ptr = dcache_init (hms_read_inferior_memory,
+ hms_write_inferior_memory);
+ remote_dcache = 1;
+ /* Hello? Are you there? */
+ SERIAL_WRITE (desc, "\r\n", 2);
+ expect_prompt ();
+
+ /* Clear any break points */
+ hms_clear_breakpoints ();
+
+ printf_filtered ("Connected to remote board running HMS monitor.\n");
+ add_commands ();
+/* hms_drain (); */
+}
+
+/* Define the target subroutine names */
+
+struct target_ops hms_ops ;
+
+static void
+init_hms_ops(void)
+{
+ hms_ops.to_shortname = "hms";
+ hms_ops.to_longname = "Remote HMS monitor";
+ hms_ops.to_doc = "Use the H8 evaluation board running the HMS monitor connected\n\
+by a serial line.";
+ hms_ops.to_open = hms_open;
+ hms_ops.to_close = hms_close;
+ hms_ops.to_attach = 0;
+ hms_ops.to_post_attach = NULL;
+ hms_ops.to_require_attach = NULL;
+ hms_ops.to_detach = hms_detach;
+ hms_ops.to_require_detach = NULL;
+ hms_ops.to_resume = hms_resume;
+ hms_ops.to_wait = hms_wait;
+ hms_ops.to_post_wait = NULL;
+ hms_ops.to_fetch_registers = hms_fetch_register;
+ hms_ops.to_store_registers = hms_store_register;
+ hms_ops.to_prepare_to_store = hms_prepare_to_store;
+ hms_ops.to_xfer_memory = hms_xfer_inferior_memory;
+ hms_ops.to_files_info = hms_files_info;
+ hms_ops.to_insert_breakpoint = hms_insert_breakpoint;
+ hms_ops.to_remove_breakpoint = hms_remove_breakpoint;
+ hms_ops.to_terminal_init = 0;
+ hms_ops.to_terminal_inferior = 0;
+ hms_ops.to_terminal_ours_for_output = 0;
+ hms_ops.to_terminal_ours = 0;
+ hms_ops.to_terminal_info = 0;
+ hms_ops.to_kill = hms_kill;
+ hms_ops.to_load = generic_load;
+ hms_ops.to_lookup_symbol = 0;
+ hms_ops.to_create_inferior = hms_create_inferior;
+ hms_ops.to_post_startup_inferior = NULL;
+ hms_ops.to_acknowledge_created_inferior = NULL;
+ hms_ops.to_clone_and_follow_inferior = NULL;
+ hms_ops.to_post_follow_inferior_by_clone = NULL;
+ hms_ops.to_insert_fork_catchpoint = NULL;
+ hms_ops.to_remove_fork_catchpoint = NULL;
+ hms_ops.to_insert_vfork_catchpoint = NULL;
+ hms_ops.to_remove_vfork_catchpoint = NULL;
+ hms_ops.to_has_forked = NULL;
+ hms_ops.to_has_vforked = NULL;
+ hms_ops.to_can_follow_vfork_prior_to_exec = NULL;
+ hms_ops.to_post_follow_vfork = NULL;
+ hms_ops.to_insert_exec_catchpoint = NULL;
+ hms_ops.to_remove_exec_catchpoint = NULL;
+ hms_ops.to_has_execd = NULL;
+ hms_ops.to_reported_exec_events_per_exec_call = NULL;
+ hms_ops.to_has_exited = NULL;
+ hms_ops.to_mourn_inferior = hms_mourn;
+ hms_ops.to_can_run = 0;
+ hms_ops.to_notice_signals = 0;
+ hms_ops.to_thread_alive = 0;
+ hms_ops.to_stop = 0;
+ hms_ops.to_pid_to_exec_file = NULL;
+ hms_ops.to_core_file_to_sym_file = NULL;
+ hms_ops.to_stratum = process_stratum;
+ hms_ops.DONT_USE = 0;
+ hms_ops.to_has_all_memory = 1;
+ hms_ops.to_has_memory = 1;
+ hms_ops.to_has_stack = 1;
+ hms_ops.to_has_registers = 1;
+ hms_ops.to_has_execution = 1;
+ hms_ops.to_sections = 0;
+ hms_ops.to_sections_end = 0;
+ hms_ops.to_magic = OPS_MAGIC;
+};
+
+hms_quiet () /* FIXME - this routine can be removed after Dec '94 */
+{
+ quiet = !quiet;
+ if (quiet)
+ printf_filtered ("Snoop disabled\n");
+ else
+ printf_filtered ("Snoop enabled\n");
+
+ printf_filtered ("`snoop' is obsolete, please use `set remotedebug'.\n");
+}
+
+hms_device (s)
+ char *s;
+{
+ if (s)
+ {
+ dev_name = get_word (&s);
+ }
+}
+
+static
+hms_speed (s)
+ char *s;
+{
+ check_open ();
+
+ if (s)
+ {
+ char buffer[100];
+ int newrate = atoi (s);
+ int which = 0;
+
+ if (SERIAL_SETBAUDRATE (desc, newrate))
+ error ("Can't use %d baud\n", newrate);
+
+ printf_filtered ("Checking target is in sync\n");
+
+ printf_filtered ("Sending commands to set target to %d\n",
+ baudrate);
+
+ sprintf (buffer, "tm %d. N 8 1", baudrate);
+ hms_write_cr (buffer);
+ }
+}
+
+/***********************************************************************/
+
+static void
+hms_drain (args, fromtty)
+ char *args;
+ int fromtty;
+{
+ int c;
+ while (1)
+ {
+ c = SERIAL_READCHAR (desc, 1);
+ if (c == SERIAL_TIMEOUT)
+ break;
+ if (c == SERIAL_ERROR)
+ break;
+ if (c > ' ' && c < 127)
+ printf ("%c", c & 0xff);
+ else
+ printf ("<%x>", c & 0xff);
+ }
+}
+
+static void
+add_commands ()
+{
+
+ add_com ("hms_drain", class_obscure, hms_drain,
+ "Drain pending hms text buffers.");
+}
+
+static void
+remove_commands ()
+{
+ extern struct cmd_list_element *cmdlist;
+ delete_cmd ("hms-drain", &cmdlist);
+}
+
+
+void
+_initialize_remote_hms ()
+{
+ init_hms_ops() ;
+ add_target (&hms_ops);
+
+ add_com ("hms <command>", class_obscure, hms_com,
+ "Send a command to the HMS monitor.");
+
+ /* FIXME - hms_quiet and `snoop' can be removed after Dec '94 */
+ add_com ("snoop", class_obscure, hms_quiet,
+ "Show what commands are going to the monitor (OBSOLETE - see 'set remotedebug')");
+
+ add_com ("device", class_obscure, hms_device,
+ "Set the terminal line for HMS communications");
+
+ add_com ("speed", class_obscure, hms_speed,
+ "Set the terminal line speed for HMS communications");
+
+ dev_name = NULL;
+}
+#endif
+
diff --git a/gdb/remote-mips.c b/gdb/remote-mips.c
new file mode 100644
index 00000000000..c92f8b706c9
--- /dev/null
+++ b/gdb/remote-mips.c
@@ -0,0 +1,3655 @@
+/* Remote debugging interface for MIPS remote debugging protocol.
+ Copyright 1993, 1994, 1995 Free Software Foundation, Inc.
+ Contributed by Cygnus Support. Written by Ian Lance Taylor
+ <ian@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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "inferior.h"
+#include "bfd.h"
+#include "symfile.h"
+#include "wait.h"
+#include "gdbcmd.h"
+#include "gdbcore.h"
+#include "serial.h"
+#include "target.h"
+#include "remote-utils.h"
+#include "gdb_string.h"
+
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#ifdef ANSI_PROTOTYPES
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+
+/* Microsoft C's stat.h doesn't define all the POSIX file modes. */
+#ifndef S_IROTH
+#define S_IROTH S_IREAD
+#endif
+
+extern void mips_set_processor_type_command PARAMS ((char *, int));
+
+
+/* Breakpoint types. Values 0, 1, and 2 must agree with the watch
+ types passed by breakpoint.c to target_insert_watchpoint.
+ Value 3 is our own invention, and is used for ordinary instruction
+ breakpoints. Value 4 is used to mark an unused watchpoint in tables. */
+enum break_type {
+ BREAK_WRITE, /* 0 */
+ BREAK_READ, /* 1 */
+ BREAK_ACCESS, /* 2 */
+ BREAK_FETCH, /* 3 */
+ BREAK_UNUSED /* 4 */
+};
+
+/* Prototypes for local functions. */
+
+static int mips_readchar PARAMS ((int timeout));
+
+static int mips_receive_header PARAMS ((unsigned char *hdr, int *pgarbage,
+ int ch, int timeout));
+
+static int mips_receive_trailer PARAMS ((unsigned char *trlr, int *pgarbage,
+ int *pch, int timeout));
+
+static int mips_cksum PARAMS ((const unsigned char *hdr,
+ const unsigned char *data,
+ int len));
+
+static void mips_send_packet PARAMS ((const char *s, int get_ack));
+
+static void mips_send_command PARAMS ((const char *cmd, int prompt));
+
+static int mips_receive_packet PARAMS ((char *buff, int throw_error,
+ int timeout));
+
+static CORE_ADDR mips_request PARAMS ((int cmd, CORE_ADDR addr,
+ CORE_ADDR data, int *perr, int timeout,
+ char *buff));
+
+static void mips_initialize PARAMS ((void));
+
+static void mips_open PARAMS ((char *name, int from_tty));
+
+static void pmon_open PARAMS ((char *name, int from_tty));
+
+static void ddb_open PARAMS ((char *name, int from_tty));
+
+static void lsi_open PARAMS ((char *name, int from_tty));
+
+static void mips_close PARAMS ((int quitting));
+
+static void mips_detach PARAMS ((char *args, int from_tty));
+
+static void mips_resume PARAMS ((int pid, int step,
+ enum target_signal siggnal));
+
+static int mips_wait PARAMS ((int pid, struct target_waitstatus *status));
+
+static int mips_map_regno PARAMS ((int regno));
+
+static void mips_fetch_registers PARAMS ((int regno));
+
+static void mips_prepare_to_store PARAMS ((void));
+
+static void mips_store_registers PARAMS ((int regno));
+
+static unsigned int mips_fetch_word PARAMS ((CORE_ADDR addr));
+
+static int mips_store_word PARAMS ((CORE_ADDR addr, unsigned int value,
+ char *old_contents));
+
+static int mips_xfer_memory PARAMS ((CORE_ADDR memaddr, char *myaddr, int len,
+ int write, struct target_ops *ignore));
+
+static void mips_files_info PARAMS ((struct target_ops *ignore));
+
+static void mips_create_inferior PARAMS ((char *execfile, char *args,
+ char **env));
+
+static void mips_mourn_inferior PARAMS ((void));
+
+static int pmon_makeb64 PARAMS ((unsigned long v, char *p, int n, int *chksum));
+
+static int pmon_zeroset PARAMS ((int recsize, char **buff, int *amount,
+ unsigned int *chksum));
+
+static int pmon_checkset PARAMS ((int recsize, char **buff, int *value));
+
+static void pmon_make_fastrec PARAMS ((char **outbuf, unsigned char *inbuf,
+ int *inptr, int inamount, int *recsize,
+ unsigned int *csum, unsigned int *zerofill));
+
+static int pmon_check_ack PARAMS ((char *mesg));
+
+static void pmon_start_download PARAMS ((void));
+
+static void pmon_end_download PARAMS ((int final, int bintotal));
+
+static void pmon_download PARAMS ((char *buffer, int length));
+
+static void pmon_load_fast PARAMS ((char *file));
+
+static void mips_load PARAMS ((char *file, int from_tty));
+
+static int mips_make_srec PARAMS ((char *buffer, int type, CORE_ADDR memaddr,
+ unsigned char *myaddr, int len));
+
+static int set_breakpoint PARAMS ((CORE_ADDR addr, int len,
+ enum break_type type));
+
+static int clear_breakpoint PARAMS ((CORE_ADDR addr, int len,
+ enum break_type type));
+
+static int common_breakpoint PARAMS ((int set, CORE_ADDR addr, int len,
+ enum break_type type));
+
+/* Forward declarations. */
+extern struct target_ops mips_ops;
+extern struct target_ops pmon_ops;
+extern struct target_ops ddb_ops;
+
+/* The MIPS remote debugging interface is built on top of a simple
+ packet protocol. Each packet is organized as follows:
+
+ SYN The first character is always a SYN (ASCII 026, or ^V). SYN
+ may not appear anywhere else in the packet. Any time a SYN is
+ seen, a new packet should be assumed to have begun.
+
+ TYPE_LEN
+ This byte contains the upper five bits of the logical length
+ of the data section, plus a single bit indicating whether this
+ is a data packet or an acknowledgement. The documentation
+ indicates that this bit is 1 for a data packet, but the actual
+ board uses 1 for an acknowledgement. The value of the byte is
+ 0x40 + (ack ? 0x20 : 0) + (len >> 6)
+ (we always have 0 <= len < 1024). Acknowledgement packets do
+ not carry data, and must have a data length of 0.
+
+ LEN1 This byte contains the lower six bits of the logical length of
+ the data section. The value is
+ 0x40 + (len & 0x3f)
+
+ SEQ This byte contains the six bit sequence number of the packet.
+ The value is
+ 0x40 + seq
+ An acknowlegment packet contains the sequence number of the
+ packet being acknowledged plus 1 modulo 64. Data packets are
+ transmitted in sequence. There may only be one outstanding
+ unacknowledged data packet at a time. The sequence numbers
+ are independent in each direction. If an acknowledgement for
+ the previous packet is received (i.e., an acknowledgement with
+ the sequence number of the packet just sent) the packet just
+ sent should be retransmitted. If no acknowledgement is
+ received within a timeout period, the packet should be
+ retransmitted. This has an unfortunate failure condition on a
+ high-latency line, as a delayed acknowledgement may lead to an
+ endless series of duplicate packets.
+
+ DATA The actual data bytes follow. The following characters are
+ escaped inline with DLE (ASCII 020, or ^P):
+ SYN (026) DLE S
+ DLE (020) DLE D
+ ^C (003) DLE C
+ ^S (023) DLE s
+ ^Q (021) DLE q
+ The additional DLE characters are not counted in the logical
+ length stored in the TYPE_LEN and LEN1 bytes.
+
+ CSUM1
+ CSUM2
+ CSUM3
+ These bytes contain an 18 bit checksum of the complete
+ contents of the packet excluding the SEQ byte and the
+ CSUM[123] bytes. The checksum is simply the twos complement
+ addition of all the bytes treated as unsigned characters. The
+ values of the checksum bytes are:
+ CSUM1: 0x40 + ((cksum >> 12) & 0x3f)
+ CSUM2: 0x40 + ((cksum >> 6) & 0x3f)
+ CSUM3: 0x40 + (cksum & 0x3f)
+
+ It happens that the MIPS remote debugging protocol always
+ communicates with ASCII strings. Because of this, this
+ implementation doesn't bother to handle the DLE quoting mechanism,
+ since it will never be required. */
+
+/* The SYN character which starts each packet. */
+#define SYN '\026'
+
+/* The 0x40 used to offset each packet (this value ensures that all of
+ the header and trailer bytes, other than SYN, are printable ASCII
+ characters). */
+#define HDR_OFFSET 0x40
+
+/* The indices of the bytes in the packet header. */
+#define HDR_INDX_SYN 0
+#define HDR_INDX_TYPE_LEN 1
+#define HDR_INDX_LEN1 2
+#define HDR_INDX_SEQ 3
+#define HDR_LENGTH 4
+
+/* The data/ack bit in the TYPE_LEN header byte. */
+#define TYPE_LEN_DA_BIT 0x20
+#define TYPE_LEN_DATA 0
+#define TYPE_LEN_ACK TYPE_LEN_DA_BIT
+
+/* How to compute the header bytes. */
+#define HDR_SET_SYN(data, len, seq) (SYN)
+#define HDR_SET_TYPE_LEN(data, len, seq) \
+ (HDR_OFFSET \
+ + ((data) ? TYPE_LEN_DATA : TYPE_LEN_ACK) \
+ + (((len) >> 6) & 0x1f))
+#define HDR_SET_LEN1(data, len, seq) (HDR_OFFSET + ((len) & 0x3f))
+#define HDR_SET_SEQ(data, len, seq) (HDR_OFFSET + (seq))
+
+/* Check that a header byte is reasonable. */
+#define HDR_CHECK(ch) (((ch) & HDR_OFFSET) == HDR_OFFSET)
+
+/* Get data from the header. These macros evaluate their argument
+ multiple times. */
+#define HDR_IS_DATA(hdr) \
+ (((hdr)[HDR_INDX_TYPE_LEN] & TYPE_LEN_DA_BIT) == TYPE_LEN_DATA)
+#define HDR_GET_LEN(hdr) \
+ ((((hdr)[HDR_INDX_TYPE_LEN] & 0x1f) << 6) + (((hdr)[HDR_INDX_LEN1] & 0x3f)))
+#define HDR_GET_SEQ(hdr) ((unsigned int)(hdr)[HDR_INDX_SEQ] & 0x3f)
+
+/* The maximum data length. */
+#define DATA_MAXLEN 1023
+
+/* The trailer offset. */
+#define TRLR_OFFSET HDR_OFFSET
+
+/* The indices of the bytes in the packet trailer. */
+#define TRLR_INDX_CSUM1 0
+#define TRLR_INDX_CSUM2 1
+#define TRLR_INDX_CSUM3 2
+#define TRLR_LENGTH 3
+
+/* How to compute the trailer bytes. */
+#define TRLR_SET_CSUM1(cksum) (TRLR_OFFSET + (((cksum) >> 12) & 0x3f))
+#define TRLR_SET_CSUM2(cksum) (TRLR_OFFSET + (((cksum) >> 6) & 0x3f))
+#define TRLR_SET_CSUM3(cksum) (TRLR_OFFSET + (((cksum) ) & 0x3f))
+
+/* Check that a trailer byte is reasonable. */
+#define TRLR_CHECK(ch) (((ch) & TRLR_OFFSET) == TRLR_OFFSET)
+
+/* Get data from the trailer. This evaluates its argument multiple
+ times. */
+#define TRLR_GET_CKSUM(trlr) \
+ ((((trlr)[TRLR_INDX_CSUM1] & 0x3f) << 12) \
+ + (((trlr)[TRLR_INDX_CSUM2] & 0x3f) << 6) \
+ + ((trlr)[TRLR_INDX_CSUM3] & 0x3f))
+
+/* The sequence number modulos. */
+#define SEQ_MODULOS (64)
+
+/* PMON commands to load from the serial port or UDP socket. */
+#define LOAD_CMD "load -b -s tty0\r"
+#define LOAD_CMD_UDP "load -b -s udp\r"
+
+/* The target vectors for the four different remote MIPS targets.
+ These are initialized with code in _initialize_remote_mips instead
+ of static initializers, to make it easier to extend the target_ops
+ vector later. */
+struct target_ops mips_ops, pmon_ops, ddb_ops, lsi_ops;
+
+enum mips_monitor_type {
+ /* IDT/SIM monitor being used: */
+ MON_IDT,
+ /* PMON monitor being used: */
+ MON_PMON, /* 3.0.83 [COGENT,EB,FP,NET] Algorithmics Ltd. Nov 9 1995 17:19:50 */
+ MON_DDB, /* 2.7.473 [DDBVR4300,EL,FP,NET] Risq Modular Systems, Thu Jun 6 09:28:40 PDT 1996 */
+ MON_LSI, /* 4.3.12 [EB,FP], LSI LOGIC Corp. Tue Feb 25 13:22:14 1997 */
+ /* Last and unused value, for sizing vectors, etc. */
+ MON_LAST
+};
+static enum mips_monitor_type mips_monitor = MON_LAST;
+
+/* The monitor prompt text. If the user sets the PMON prompt
+ to some new value, the GDB `set monitor-prompt' command must also
+ be used to inform GDB about the expected prompt. Otherwise, GDB
+ will not be able to connect to PMON in mips_initialize().
+ If the `set monitor-prompt' command is not used, the expected
+ default prompt will be set according the target:
+ target prompt
+ ----- -----
+ pmon PMON>
+ ddb NEC010>
+ lsi PMON>
+*/
+static char *mips_monitor_prompt;
+
+/* Set to 1 if the target is open. */
+static int mips_is_open;
+
+/* Currently active target description (if mips_is_open == 1) */
+static struct target_ops *current_ops;
+
+/* Set to 1 while the connection is being initialized. */
+static int mips_initializing;
+
+/* Set to 1 while the connection is being brought down. */
+static int mips_exiting;
+
+/* The next sequence number to send. */
+static unsigned int mips_send_seq;
+
+/* The next sequence number we expect to receive. */
+static unsigned int mips_receive_seq;
+
+/* The time to wait before retransmitting a packet, in seconds. */
+static int mips_retransmit_wait = 3;
+
+/* The number of times to try retransmitting a packet before giving up. */
+static int mips_send_retries = 10;
+
+/* The number of garbage characters to accept when looking for an
+ SYN for the next packet. */
+static int mips_syn_garbage = 1050;
+
+/* The time to wait for a packet, in seconds. */
+static int mips_receive_wait = 5;
+
+/* Set if we have sent a packet to the board but have not yet received
+ a reply. */
+static int mips_need_reply = 0;
+
+/* Handle used to access serial I/O stream. */
+static serial_t mips_desc;
+
+/* UDP handle used to download files to target. */
+static serial_t udp_desc;
+static int udp_in_use;
+
+/* TFTP filename used to download files to DDB board, in the form
+ host:filename. */
+static char *tftp_name; /* host:filename */
+static char *tftp_localname; /* filename portion of above */
+static int tftp_in_use;
+static FILE *tftp_file;
+
+/* Counts the number of times the user tried to interrupt the target (usually
+ via ^C. */
+static int interrupt_count;
+
+/* If non-zero, means that the target is running. */
+static int mips_wait_flag = 0;
+
+/* If non-zero, monitor supports breakpoint commands. */
+static monitor_supports_breakpoints = 0;
+
+/* Data cache header. */
+
+#if 0 /* not used (yet?) */
+static DCACHE *mips_dcache;
+#endif
+
+/* Non-zero means that we've just hit a read or write watchpoint */
+static int hit_watchpoint;
+
+/* Table of breakpoints/watchpoints (used only on LSI PMON target).
+ The table is indexed by a breakpoint number, which is an integer
+ from 0 to 255 returned by the LSI PMON when a breakpoint is set.
+*/
+#define MAX_LSI_BREAKPOINTS 256
+struct lsi_breakpoint_info
+{
+ enum break_type type; /* type of breakpoint */
+ CORE_ADDR addr; /* address of breakpoint */
+ int len; /* length of region being watched */
+ unsigned long value; /* value to watch */
+} lsi_breakpoints [MAX_LSI_BREAKPOINTS];
+
+/* Error/warning codes returned by LSI PMON for breakpoint commands.
+ Warning values may be ORed together; error values may not. */
+#define W_WARN 0x100 /* This bit is set if the error code is a warning */
+#define W_MSK 0x101 /* warning: Range feature is supported via mask */
+#define W_VAL 0x102 /* warning: Value check is not supported in hardware */
+#define W_QAL 0x104 /* warning: Requested qualifiers are not supported in hardware */
+
+#define E_ERR 0x200 /* This bit is set if the error code is an error */
+#define E_BPT 0x200 /* error: No such breakpoint number */
+#define E_RGE 0x201 /* error: Range is not supported */
+#define E_QAL 0x202 /* error: The requested qualifiers can not be used */
+#define E_OUT 0x203 /* error: Out of hardware resources */
+#define E_NON 0x204 /* error: Hardware breakpoint not supported */
+
+struct lsi_error
+{
+ int code; /* error code */
+ char *string; /* string associated with this code */
+};
+
+struct lsi_error lsi_warning_table[] =
+{
+ { W_MSK, "Range feature is supported via mask" },
+ { W_VAL, "Value check is not supported in hardware" },
+ { W_QAL, "Requested qualifiers are not supported in hardware" },
+ { 0, NULL }
+};
+
+struct lsi_error lsi_error_table[] =
+{
+ { E_BPT, "No such breakpoint number" },
+ { E_RGE, "Range is not supported" },
+ { E_QAL, "The requested qualifiers can not be used" },
+ { E_OUT, "Out of hardware resources" },
+ { E_NON, "Hardware breakpoint not supported" },
+ { 0, NULL }
+};
+
+/* Set to 1 with the 'set monitor-warnings' command to enable printing
+ of warnings returned by PMON when hardware breakpoints are used. */
+static int monitor_warnings;
+
+
+static void
+close_ports()
+{
+ mips_is_open = 0;
+ SERIAL_CLOSE (mips_desc);
+
+ if (udp_in_use)
+ {
+ SERIAL_CLOSE (udp_desc);
+ udp_in_use = 0;
+ }
+ tftp_in_use = 0;
+}
+
+/* Handle low-level error that we can't recover from. Note that just
+ error()ing out from target_wait or some such low-level place will cause
+ all hell to break loose--the rest of GDB will tend to get left in an
+ inconsistent state. */
+
+static NORETURN void
+#ifdef ANSI_PROTOTYPES
+mips_error (char *string, ...)
+#else
+mips_error (va_alist)
+ va_dcl
+#endif
+{
+ va_list args;
+
+#ifdef ANSI_PROTOTYPES
+ va_start (args, string);
+#else
+ char *string;
+ va_start (args);
+ string = va_arg (args, char *);
+#endif
+
+ target_terminal_ours ();
+ wrap_here(""); /* Force out any buffered output */
+ gdb_flush (gdb_stdout);
+ if (error_pre_print)
+ fprintf_filtered (gdb_stderr, error_pre_print);
+ vfprintf_filtered (gdb_stderr, string, args);
+ fprintf_filtered (gdb_stderr, "\n");
+ va_end (args);
+ gdb_flush (gdb_stderr);
+
+ /* Clean up in such a way that mips_close won't try to talk to the
+ board (it almost surely won't work since we weren't able to talk to
+ it). */
+ close_ports ();
+
+ printf_unfiltered ("Ending remote MIPS debugging.\n");
+ target_mourn_inferior ();
+
+ return_to_top_level (RETURN_ERROR);
+}
+
+/* putc_readable - print a character, displaying non-printable chars in
+ ^x notation or in hex. */
+
+static void
+putc_readable (ch)
+ int ch;
+{
+ if (ch == '\n')
+ putchar_unfiltered ('\n');
+ else if (ch == '\r')
+ printf_unfiltered ("\\r");
+ else if (ch < 0x20) /* ASCII control character */
+ printf_unfiltered ("^%c", ch + '@');
+ else if (ch >= 0x7f) /* non-ASCII characters (rubout or greater) */
+ printf_unfiltered ("[%02x]", ch & 0xff);
+ else
+ putchar_unfiltered (ch);
+}
+
+
+/* puts_readable - print a string, displaying non-printable chars in
+ ^x notation or in hex. */
+
+static void
+puts_readable (string)
+ char *string;
+{
+ int c;
+
+ while ((c = *string++) != '\0')
+ putc_readable (c);
+}
+
+
+/* Wait until STRING shows up in mips_desc. Returns 1 if successful, else 0 if
+ timed out. TIMEOUT specifies timeout value in seconds.
+*/
+
+int
+mips_expect_timeout (string, timeout)
+ char *string;
+ int timeout;
+{
+ char *p = string;
+
+ if (remote_debug)
+ {
+ printf_unfiltered ("Expected \"");
+ puts_readable (string);
+ printf_unfiltered ("\", got \"");
+ }
+
+ immediate_quit = 1;
+ while (1)
+ {
+ int c;
+
+/* Must use SERIAL_READCHAR here cuz mips_readchar would get confused if we
+ were waiting for the mips_monitor_prompt... */
+
+ c = SERIAL_READCHAR (mips_desc, timeout);
+
+ if (c == SERIAL_TIMEOUT)
+ {
+ if (remote_debug)
+ printf_unfiltered ("\": FAIL\n");
+ return 0;
+ }
+
+ if (remote_debug)
+ putc_readable (c);
+
+ if (c == *p++)
+ {
+ if (*p == '\0')
+ {
+ immediate_quit = 0;
+ if (remote_debug)
+ printf_unfiltered ("\": OK\n");
+ return 1;
+ }
+ }
+ else
+ {
+ p = string;
+ if (c == *p)
+ p++;
+ }
+ }
+}
+
+/* Wait until STRING shows up in mips_desc. Returns 1 if successful, else 0 if
+ timed out. The timeout value is hard-coded to 2 seconds. Use
+ mips_expect_timeout if a different timeout value is needed.
+*/
+
+int
+mips_expect (string)
+ char *string;
+{
+ return mips_expect_timeout (string, 2);
+}
+
+/* Read the required number of characters into the given buffer (which
+ is assumed to be large enough). The only failure is a timeout. */
+int
+mips_getstring (string, n)
+ char *string;
+ int n;
+{
+ char *p = string;
+ int c;
+
+ immediate_quit = 1;
+ while (n > 0)
+ {
+ c = SERIAL_READCHAR (mips_desc, 2);
+
+ if (c == SERIAL_TIMEOUT) {
+ fprintf_unfiltered (gdb_stderr,
+ "Failed to read %d characters from target (TIMEOUT)\n", n);
+ return 0;
+ }
+
+ *p++ = c;
+ n--;
+ }
+
+ return 1;
+}
+
+/* Read a character from the remote, aborting on error. Returns
+ SERIAL_TIMEOUT on timeout (since that's what SERIAL_READCHAR
+ returns). FIXME: If we see the string mips_monitor_prompt from
+ the board, then we are debugging on the main console port, and we
+ have somehow dropped out of remote debugging mode. In this case,
+ we automatically go back in to remote debugging mode. This is a
+ hack, put in because I can't find any way for a program running on
+ the remote board to terminate without also ending remote debugging
+ mode. I assume users won't have any trouble with this; for one
+ thing, the IDT documentation generally assumes that the remote
+ debugging port is not the console port. This is, however, very
+ convenient for DejaGnu when you only have one connected serial
+ port. */
+
+static int
+mips_readchar (timeout)
+ int timeout;
+{
+ int ch;
+ static int state = 0;
+ int mips_monitor_prompt_len = strlen (mips_monitor_prompt);
+
+#ifdef MAINTENANCE_CMDS
+ {
+ int i;
+
+ i = timeout;
+ if (i == -1 && watchdog > 0)
+ i = watchdog;
+ }
+#endif
+
+ if (state == mips_monitor_prompt_len)
+ timeout = 1;
+ ch = SERIAL_READCHAR (mips_desc, timeout);
+#ifdef MAINTENANCE_CMDS
+ if (ch == SERIAL_TIMEOUT && timeout == -1) /* Watchdog went off */
+ {
+ target_mourn_inferior ();
+ error ("Watchdog has expired. Target detached.\n");
+ }
+#endif
+ if (ch == SERIAL_EOF)
+ mips_error ("End of file from remote");
+ if (ch == SERIAL_ERROR)
+ mips_error ("Error reading from remote: %s", safe_strerror (errno));
+ if (remote_debug > 1)
+ {
+ /* Don't use _filtered; we can't deal with a QUIT out of
+ target_wait, and I think this might be called from there. */
+ if (ch != SERIAL_TIMEOUT)
+ printf_unfiltered ("Read '%c' %d 0x%x\n", ch, ch, ch);
+ else
+ printf_unfiltered ("Timed out in read\n");
+ }
+
+ /* If we have seen mips_monitor_prompt and we either time out, or
+ we see a @ (which was echoed from a packet we sent), reset the
+ board as described above. The first character in a packet after
+ the SYN (which is not echoed) is always an @ unless the packet is
+ more than 64 characters long, which ours never are. */
+ if ((ch == SERIAL_TIMEOUT || ch == '@')
+ && state == mips_monitor_prompt_len
+ && ! mips_initializing
+ && ! mips_exiting)
+ {
+ if (remote_debug > 0)
+ /* Don't use _filtered; we can't deal with a QUIT out of
+ target_wait, and I think this might be called from there. */
+ printf_unfiltered ("Reinitializing MIPS debugging mode\n");
+
+ mips_need_reply = 0;
+ mips_initialize ();
+
+ state = 0;
+
+ /* At this point, about the only thing we can do is abort the command
+ in progress and get back to command level as quickly as possible. */
+
+ error ("Remote board reset, debug protocol re-initialized.");
+ }
+
+ if (ch == mips_monitor_prompt[state])
+ ++state;
+ else
+ state = 0;
+
+ return ch;
+}
+
+/* Get a packet header, putting the data in the supplied buffer.
+ PGARBAGE is a pointer to the number of garbage characters received
+ so far. CH is the last character received. Returns 0 for success,
+ or -1 for timeout. */
+
+static int
+mips_receive_header (hdr, pgarbage, ch, timeout)
+ unsigned char *hdr;
+ int *pgarbage;
+ int ch;
+ int timeout;
+{
+ int i;
+
+ while (1)
+ {
+ /* Wait for a SYN. mips_syn_garbage is intended to prevent
+ sitting here indefinitely if the board sends us one garbage
+ character per second. ch may already have a value from the
+ last time through the loop. */
+ while (ch != SYN)
+ {
+ ch = mips_readchar (timeout);
+ if (ch == SERIAL_TIMEOUT)
+ return -1;
+ if (ch != SYN)
+ {
+ /* Printing the character here lets the user of gdb see
+ what the program is outputting, if the debugging is
+ being done on the console port. Don't use _filtered;
+ we can't deal with a QUIT out of target_wait. */
+ if (! mips_initializing || remote_debug > 0)
+ {
+ putc_readable (ch);
+ gdb_flush (gdb_stdout);
+ }
+
+ ++*pgarbage;
+ if (mips_syn_garbage > 0
+ && *pgarbage > mips_syn_garbage)
+ mips_error ("Debug protocol failure: more than %d characters before a sync.",
+ mips_syn_garbage);
+ }
+ }
+
+ /* Get the packet header following the SYN. */
+ for (i = 1; i < HDR_LENGTH; i++)
+ {
+ ch = mips_readchar (timeout);
+ if (ch == SERIAL_TIMEOUT)
+ return -1;
+ /* Make sure this is a header byte. */
+ if (ch == SYN || ! HDR_CHECK (ch))
+ break;
+
+ hdr[i] = ch;
+ }
+
+ /* If we got the complete header, we can return. Otherwise we
+ loop around and keep looking for SYN. */
+ if (i >= HDR_LENGTH)
+ return 0;
+ }
+}
+
+/* Get a packet header, putting the data in the supplied buffer.
+ PGARBAGE is a pointer to the number of garbage characters received
+ so far. The last character read is returned in *PCH. Returns 0
+ for success, -1 for timeout, -2 for error. */
+
+static int
+mips_receive_trailer (trlr, pgarbage, pch, timeout)
+ unsigned char *trlr;
+ int *pgarbage;
+ int *pch;
+ int timeout;
+{
+ int i;
+ int ch;
+
+ for (i = 0; i < TRLR_LENGTH; i++)
+ {
+ ch = mips_readchar (timeout);
+ *pch = ch;
+ if (ch == SERIAL_TIMEOUT)
+ return -1;
+ if (! TRLR_CHECK (ch))
+ return -2;
+ trlr[i] = ch;
+ }
+ return 0;
+}
+
+/* Get the checksum of a packet. HDR points to the packet header.
+ DATA points to the packet data. LEN is the length of DATA. */
+
+static int
+mips_cksum (hdr, data, len)
+ const unsigned char *hdr;
+ const unsigned char *data;
+ int len;
+{
+ register const unsigned char *p;
+ register int c;
+ register int cksum;
+
+ cksum = 0;
+
+ /* The initial SYN is not included in the checksum. */
+ c = HDR_LENGTH - 1;
+ p = hdr + 1;
+ while (c-- != 0)
+ cksum += *p++;
+
+ c = len;
+ p = data;
+ while (c-- != 0)
+ cksum += *p++;
+
+ return cksum;
+}
+
+/* Send a packet containing the given ASCII string. */
+
+static void
+mips_send_packet (s, get_ack)
+ const char *s;
+ int get_ack;
+{
+ /* unsigned */ int len;
+ unsigned char *packet;
+ register int cksum;
+ int try;
+
+ len = strlen (s);
+ if (len > DATA_MAXLEN)
+ mips_error ("MIPS protocol data packet too long: %s", s);
+
+ packet = (unsigned char *) alloca (HDR_LENGTH + len + TRLR_LENGTH + 1);
+
+ packet[HDR_INDX_SYN] = HDR_SET_SYN (1, len, mips_send_seq);
+ packet[HDR_INDX_TYPE_LEN] = HDR_SET_TYPE_LEN (1, len, mips_send_seq);
+ packet[HDR_INDX_LEN1] = HDR_SET_LEN1 (1, len, mips_send_seq);
+ packet[HDR_INDX_SEQ] = HDR_SET_SEQ (1, len, mips_send_seq);
+
+ memcpy (packet + HDR_LENGTH, s, len);
+
+ cksum = mips_cksum (packet, packet + HDR_LENGTH, len);
+ packet[HDR_LENGTH + len + TRLR_INDX_CSUM1] = TRLR_SET_CSUM1 (cksum);
+ packet[HDR_LENGTH + len + TRLR_INDX_CSUM2] = TRLR_SET_CSUM2 (cksum);
+ packet[HDR_LENGTH + len + TRLR_INDX_CSUM3] = TRLR_SET_CSUM3 (cksum);
+
+ /* Increment the sequence number. This will set mips_send_seq to
+ the sequence number we expect in the acknowledgement. */
+ mips_send_seq = (mips_send_seq + 1) % SEQ_MODULOS;
+
+ /* We can only have one outstanding data packet, so we just wait for
+ the acknowledgement here. Keep retransmitting the packet until
+ we get one, or until we've tried too many times. */
+ for (try = 0; try < mips_send_retries; try++)
+ {
+ int garbage;
+ int ch;
+
+ if (remote_debug > 0)
+ {
+ /* Don't use _filtered; we can't deal with a QUIT out of
+ target_wait, and I think this might be called from there. */
+ packet[HDR_LENGTH + len + TRLR_LENGTH] = '\0';
+ printf_unfiltered ("Writing \"%s\"\n", packet + 1);
+ }
+
+ if (SERIAL_WRITE (mips_desc, packet,
+ HDR_LENGTH + len + TRLR_LENGTH) != 0)
+ mips_error ("write to target failed: %s", safe_strerror (errno));
+
+ if (! get_ack)
+ return;
+
+ garbage = 0;
+ ch = 0;
+ while (1)
+ {
+ unsigned char hdr[HDR_LENGTH + 1];
+ unsigned char trlr[TRLR_LENGTH + 1];
+ int err;
+ unsigned int seq;
+
+ /* Get the packet header. If we time out, resend the data
+ packet. */
+ err = mips_receive_header (hdr, &garbage, ch, mips_retransmit_wait);
+ if (err != 0)
+ break;
+
+ ch = 0;
+
+ /* If we get a data packet, assume it is a duplicate and
+ ignore it. FIXME: If the acknowledgement is lost, this
+ data packet may be the packet the remote sends after the
+ acknowledgement. */
+ if (HDR_IS_DATA (hdr)) {
+ int i;
+
+ /* Ignore any errors raised whilst attempting to ignore
+ packet. */
+
+ len = HDR_GET_LEN (hdr);
+
+ for (i = 0; i < len; i++)
+ {
+ int rch;
+
+ rch = mips_readchar (2);
+ if (rch == SYN)
+ {
+ ch = SYN;
+ break;
+ }
+ if (rch == SERIAL_TIMEOUT)
+ break;
+ /* ignore the character */
+ }
+
+ if (i == len)
+ (void) mips_receive_trailer (trlr, &garbage, &ch, 2);
+
+ /* We don't bother checking the checksum, or providing an
+ ACK to the packet. */
+ continue;
+ }
+
+ /* If the length is not 0, this is a garbled packet. */
+ if (HDR_GET_LEN (hdr) != 0)
+ continue;
+
+ /* Get the packet trailer. */
+ err = mips_receive_trailer (trlr, &garbage, &ch,
+ mips_retransmit_wait);
+
+ /* If we timed out, resend the data packet. */
+ if (err == -1)
+ break;
+
+ /* If we got a bad character, reread the header. */
+ if (err != 0)
+ continue;
+
+ /* If the checksum does not match the trailer checksum, this
+ is a bad packet; ignore it. */
+ if (mips_cksum (hdr, (unsigned char *) NULL, 0)
+ != TRLR_GET_CKSUM (trlr))
+ continue;
+
+ if (remote_debug > 0)
+ {
+ hdr[HDR_LENGTH] = '\0';
+ trlr[TRLR_LENGTH] = '\0';
+ /* Don't use _filtered; we can't deal with a QUIT out of
+ target_wait, and I think this might be called from there. */
+ printf_unfiltered ("Got ack %d \"%s%s\"\n",
+ HDR_GET_SEQ (hdr), hdr + 1, trlr);
+ }
+
+ /* If this ack is for the current packet, we're done. */
+ seq = HDR_GET_SEQ (hdr);
+ if (seq == mips_send_seq)
+ return;
+
+ /* If this ack is for the last packet, resend the current
+ packet. */
+ if ((seq + 1) % SEQ_MODULOS == mips_send_seq)
+ break;
+
+ /* Otherwise this is a bad ack; ignore it. Increment the
+ garbage count to ensure that we do not stay in this loop
+ forever. */
+ ++garbage;
+ }
+ }
+
+ mips_error ("Remote did not acknowledge packet");
+}
+
+/* Receive and acknowledge a packet, returning the data in BUFF (which
+ should be DATA_MAXLEN + 1 bytes). The protocol documentation
+ implies that only the sender retransmits packets, so this code just
+ waits silently for a packet. It returns the length of the received
+ packet. If THROW_ERROR is nonzero, call error() on errors. If not,
+ don't print an error message and return -1. */
+
+static int
+mips_receive_packet (buff, throw_error, timeout)
+ char *buff;
+ int throw_error;
+ int timeout;
+{
+ int ch;
+ int garbage;
+ int len;
+ unsigned char ack[HDR_LENGTH + TRLR_LENGTH + 1];
+ int cksum;
+
+ ch = 0;
+ garbage = 0;
+ while (1)
+ {
+ unsigned char hdr[HDR_LENGTH];
+ unsigned char trlr[TRLR_LENGTH];
+ int i;
+ int err;
+
+ if (mips_receive_header (hdr, &garbage, ch, timeout) != 0)
+ {
+ if (throw_error)
+ mips_error ("Timed out waiting for remote packet");
+ else
+ return -1;
+ }
+
+ ch = 0;
+
+ /* An acknowledgement is probably a duplicate; ignore it. */
+ if (! HDR_IS_DATA (hdr))
+ {
+ len = HDR_GET_LEN (hdr);
+ /* Check if the length is valid for an ACK, we may aswell
+ try and read the remainder of the packet: */
+ if (len == 0)
+ {
+ /* Ignore the error condition, since we are going to
+ ignore the packet anyway. */
+ (void) mips_receive_trailer (trlr, &garbage, &ch, timeout);
+ }
+ /* Don't use _filtered; we can't deal with a QUIT out of
+ target_wait, and I think this might be called from there. */
+ if (remote_debug > 0)
+ printf_unfiltered ("Ignoring unexpected ACK\n");
+ continue;
+ }
+
+ len = HDR_GET_LEN (hdr);
+ for (i = 0; i < len; i++)
+ {
+ int rch;
+
+ rch = mips_readchar (timeout);
+ if (rch == SYN)
+ {
+ ch = SYN;
+ break;
+ }
+ if (rch == SERIAL_TIMEOUT)
+ {
+ if (throw_error)
+ mips_error ("Timed out waiting for remote packet");
+ else
+ return -1;
+ }
+ buff[i] = rch;
+ }
+
+ if (i < len)
+ {
+ /* Don't use _filtered; we can't deal with a QUIT out of
+ target_wait, and I think this might be called from there. */
+ if (remote_debug > 0)
+ printf_unfiltered ("Got new SYN after %d chars (wanted %d)\n",
+ i, len);
+ continue;
+ }
+
+ err = mips_receive_trailer (trlr, &garbage, &ch, timeout);
+ if (err == -1)
+ {
+ if (throw_error)
+ mips_error ("Timed out waiting for packet");
+ else
+ return -1;
+ }
+ if (err == -2)
+ {
+ /* Don't use _filtered; we can't deal with a QUIT out of
+ target_wait, and I think this might be called from there. */
+ if (remote_debug > 0)
+ printf_unfiltered ("Got SYN when wanted trailer\n");
+ continue;
+ }
+
+ /* If this is the wrong sequence number, ignore it. */
+ if (HDR_GET_SEQ (hdr) != mips_receive_seq)
+ {
+ /* Don't use _filtered; we can't deal with a QUIT out of
+ target_wait, and I think this might be called from there. */
+ if (remote_debug > 0)
+ printf_unfiltered ("Ignoring sequence number %d (want %d)\n",
+ HDR_GET_SEQ (hdr), mips_receive_seq);
+ continue;
+ }
+
+ if (mips_cksum (hdr, buff, len) == TRLR_GET_CKSUM (trlr))
+ break;
+
+ if (remote_debug > 0)
+ /* Don't use _filtered; we can't deal with a QUIT out of
+ target_wait, and I think this might be called from there. */
+ printf_unfiltered ("Bad checksum; data %d, trailer %d\n",
+ mips_cksum (hdr, buff, len),
+ TRLR_GET_CKSUM (trlr));
+
+ /* The checksum failed. Send an acknowledgement for the
+ previous packet to tell the remote to resend the packet. */
+ ack[HDR_INDX_SYN] = HDR_SET_SYN (0, 0, mips_receive_seq);
+ ack[HDR_INDX_TYPE_LEN] = HDR_SET_TYPE_LEN (0, 0, mips_receive_seq);
+ ack[HDR_INDX_LEN1] = HDR_SET_LEN1 (0, 0, mips_receive_seq);
+ ack[HDR_INDX_SEQ] = HDR_SET_SEQ (0, 0, mips_receive_seq);
+
+ cksum = mips_cksum (ack, (unsigned char *) NULL, 0);
+
+ ack[HDR_LENGTH + TRLR_INDX_CSUM1] = TRLR_SET_CSUM1 (cksum);
+ ack[HDR_LENGTH + TRLR_INDX_CSUM2] = TRLR_SET_CSUM2 (cksum);
+ ack[HDR_LENGTH + TRLR_INDX_CSUM3] = TRLR_SET_CSUM3 (cksum);
+
+ if (remote_debug > 0)
+ {
+ ack[HDR_LENGTH + TRLR_LENGTH] = '\0';
+ /* Don't use _filtered; we can't deal with a QUIT out of
+ target_wait, and I think this might be called from there. */
+ printf_unfiltered ("Writing ack %d \"%s\"\n", mips_receive_seq,
+ ack + 1);
+ }
+
+ if (SERIAL_WRITE (mips_desc, ack, HDR_LENGTH + TRLR_LENGTH) != 0)
+ {
+ if (throw_error)
+ mips_error ("write to target failed: %s", safe_strerror (errno));
+ else
+ return -1;
+ }
+ }
+
+ if (remote_debug > 0)
+ {
+ buff[len] = '\0';
+ /* Don't use _filtered; we can't deal with a QUIT out of
+ target_wait, and I think this might be called from there. */
+ printf_unfiltered ("Got packet \"%s\"\n", buff);
+ }
+
+ /* We got the packet. Send an acknowledgement. */
+ mips_receive_seq = (mips_receive_seq + 1) % SEQ_MODULOS;
+
+ ack[HDR_INDX_SYN] = HDR_SET_SYN (0, 0, mips_receive_seq);
+ ack[HDR_INDX_TYPE_LEN] = HDR_SET_TYPE_LEN (0, 0, mips_receive_seq);
+ ack[HDR_INDX_LEN1] = HDR_SET_LEN1 (0, 0, mips_receive_seq);
+ ack[HDR_INDX_SEQ] = HDR_SET_SEQ (0, 0, mips_receive_seq);
+
+ cksum = mips_cksum (ack, (unsigned char *) NULL, 0);
+
+ ack[HDR_LENGTH + TRLR_INDX_CSUM1] = TRLR_SET_CSUM1 (cksum);
+ ack[HDR_LENGTH + TRLR_INDX_CSUM2] = TRLR_SET_CSUM2 (cksum);
+ ack[HDR_LENGTH + TRLR_INDX_CSUM3] = TRLR_SET_CSUM3 (cksum);
+
+ if (remote_debug > 0)
+ {
+ ack[HDR_LENGTH + TRLR_LENGTH] = '\0';
+ /* Don't use _filtered; we can't deal with a QUIT out of
+ target_wait, and I think this might be called from there. */
+ printf_unfiltered ("Writing ack %d \"%s\"\n", mips_receive_seq,
+ ack + 1);
+ }
+
+ if (SERIAL_WRITE (mips_desc, ack, HDR_LENGTH + TRLR_LENGTH) != 0)
+ {
+ if (throw_error)
+ mips_error ("write to target failed: %s", safe_strerror (errno));
+ else
+ return -1;
+ }
+
+ return len;
+}
+
+/* Optionally send a request to the remote system and optionally wait
+ for the reply. This implements the remote debugging protocol,
+ which is built on top of the packet protocol defined above. Each
+ request has an ADDR argument and a DATA argument. The following
+ requests are defined:
+
+ \0 don't send a request; just wait for a reply
+ i read word from instruction space at ADDR
+ d read word from data space at ADDR
+ I write DATA to instruction space at ADDR
+ D write DATA to data space at ADDR
+ r read register number ADDR
+ R set register number ADDR to value DATA
+ c continue execution (if ADDR != 1, set pc to ADDR)
+ s single step (if ADDR != 1, set pc to ADDR)
+
+ The read requests return the value requested. The write requests
+ return the previous value in the changed location. The execution
+ requests return a UNIX wait value (the approximate signal which
+ caused execution to stop is in the upper eight bits).
+
+ If PERR is not NULL, this function waits for a reply. If an error
+ occurs, it sets *PERR to 1 and sets errno according to what the
+ target board reports. */
+
+static CORE_ADDR
+mips_request (cmd, addr, data, perr, timeout, buff)
+ int cmd;
+ CORE_ADDR addr;
+ CORE_ADDR data;
+ int *perr;
+ int timeout;
+ char *buff;
+{
+ char myBuff[DATA_MAXLEN + 1];
+ int len;
+ int rpid;
+ char rcmd;
+ int rerrflg;
+ unsigned long rresponse;
+
+ if (buff == (char *) NULL)
+ buff = myBuff;
+
+ if (cmd != '\0')
+ {
+ if (mips_need_reply)
+ fatal ("mips_request: Trying to send command before reply");
+ sprintf (buff, "0x0 %c 0x%s 0x%s", cmd, paddr_nz (addr), paddr_nz (data));
+ mips_send_packet (buff, 1);
+ mips_need_reply = 1;
+ }
+
+ if (perr == (int *) NULL)
+ return 0;
+
+ if (! mips_need_reply)
+ fatal ("mips_request: Trying to get reply before command");
+
+ mips_need_reply = 0;
+
+ len = mips_receive_packet (buff, 1, timeout);
+ buff[len] = '\0';
+
+ if (sscanf (buff, "0x%x %c 0x%x 0x%lx",
+ &rpid, &rcmd, &rerrflg, &rresponse) != 4
+ || (cmd != '\0' && rcmd != cmd))
+ mips_error ("Bad response from remote board");
+
+ if (rerrflg != 0)
+ {
+ *perr = 1;
+
+ /* FIXME: This will returns MIPS errno numbers, which may or may
+ not be the same as errno values used on other systems. If
+ they stick to common errno values, they will be the same, but
+ if they don't, they must be translated. */
+ errno = rresponse;
+
+ return 0;
+ }
+
+ *perr = 0;
+ return rresponse;
+}
+
+static void
+mips_initialize_cleanups (arg)
+ PTR arg;
+{
+ mips_initializing = 0;
+}
+
+static void
+mips_exit_cleanups (arg)
+ PTR arg;
+{
+ mips_exiting = 0;
+}
+
+static void
+mips_send_command (cmd, prompt)
+ const char *cmd;
+ int prompt;
+{
+ SERIAL_WRITE (mips_desc, cmd, strlen(cmd));
+ mips_expect (cmd);
+ mips_expect ("\n");
+ if (prompt)
+ mips_expect (mips_monitor_prompt);
+}
+
+/* Enter remote (dbx) debug mode: */
+static void
+mips_enter_debug ()
+{
+ /* Reset the sequence numbers, ready for the new debug sequence: */
+ mips_send_seq = 0;
+ mips_receive_seq = 0;
+
+ if (mips_monitor != MON_IDT)
+ mips_send_command ("debug\r", 0);
+ else /* assume IDT monitor by default */
+ mips_send_command ("db tty0\r", 0);
+
+ sleep(1);
+ SERIAL_WRITE (mips_desc, "\r", sizeof "\r" - 1);
+
+ /* We don't need to absorb any spurious characters here, since the
+ mips_receive_header will eat up a reasonable number of characters
+ whilst looking for the SYN, however this avoids the "garbage"
+ being displayed to the user. */
+ if (mips_monitor != MON_IDT)
+ mips_expect ("\r");
+
+ {
+ char buff[DATA_MAXLEN + 1];
+ if (mips_receive_packet (buff, 1, 3) < 0)
+ mips_error ("Failed to initialize (didn't receive packet).");
+ }
+}
+
+/* Exit remote (dbx) debug mode, returning to the monitor prompt: */
+static int
+mips_exit_debug ()
+{
+ int err;
+ struct cleanup *old_cleanups = make_cleanup (mips_exit_cleanups, NULL);
+
+ mips_exiting = 1;
+
+ if (mips_monitor != MON_IDT)
+ {
+ /* The DDB (NEC) and MiniRISC (LSI) versions of PMON exit immediately,
+ so we do not get a reply to this command: */
+ mips_request ('x', (unsigned int) 0, (unsigned int) 0, NULL,
+ mips_receive_wait, NULL);
+ mips_need_reply = 0;
+ if (!mips_expect (" break!"))
+ return -1;
+ }
+ else
+ mips_request ('x', (unsigned int) 0, (unsigned int) 0, &err,
+ mips_receive_wait, NULL);
+
+ if (!mips_expect (mips_monitor_prompt))
+ return -1;
+
+ do_cleanups (old_cleanups);
+
+ return 0;
+}
+
+/* Initialize a new connection to the MIPS board, and make sure we are
+ really connected. */
+
+static void
+mips_initialize ()
+{
+ int err;
+ struct cleanup *old_cleanups = make_cleanup (mips_initialize_cleanups, NULL);
+ int j;
+
+ /* What is this code doing here? I don't see any way it can happen, and
+ it might mean mips_initializing didn't get cleared properly.
+ So I'll make it a warning. */
+
+ if (mips_initializing)
+ {
+ warning ("internal error: mips_initialize called twice");
+ return;
+ }
+
+ mips_wait_flag = 0;
+ mips_initializing = 1;
+
+ /* At this point, the packit protocol isn't responding. We'll try getting
+ into the monitor, and restarting the protocol. */
+
+ /* Force the system into the monitor. After this we *should* be at
+ the mips_monitor_prompt. */
+ if (mips_monitor != MON_IDT)
+ j = 0; /* start by checking if we are already at the prompt */
+ else
+ j = 1; /* start by sending a break */
+ for (; j <= 4; j++)
+ {
+ switch (j)
+ {
+ case 0: /* First, try sending a CR */
+ SERIAL_FLUSH_INPUT (mips_desc);
+ SERIAL_WRITE (mips_desc, "\r", 1);
+ break;
+ case 1: /* First, try sending a break */
+ SERIAL_SEND_BREAK (mips_desc);
+ break;
+ case 2: /* Then, try a ^C */
+ SERIAL_WRITE (mips_desc, "\003", 1);
+ break;
+ case 3: /* Then, try escaping from download */
+ {
+ if (mips_monitor != MON_IDT)
+ {
+ char tbuff[7];
+
+ /* We shouldn't need to send multiple termination
+ sequences, since the target performs line (or
+ block) reads, and then processes those
+ packets. In-case we were downloading a large packet
+ we flush the output buffer before inserting a
+ termination sequence. */
+ SERIAL_FLUSH_OUTPUT (mips_desc);
+ sprintf (tbuff, "\r/E/E\r");
+ SERIAL_WRITE (mips_desc, tbuff, 6);
+ }
+ else
+ {
+ char srec[10];
+ int i;
+
+ /* We are possibly in binary download mode, having
+ aborted in the middle of an S-record. ^C won't
+ work because of binary mode. The only reliable way
+ out is to send enough termination packets (8 bytes)
+ to fill up and then overflow the largest size
+ S-record (255 bytes in this case). This amounts to
+ 256/8 + 1 packets.
+ */
+
+ mips_make_srec (srec, '7', 0, NULL, 0);
+
+ for (i = 1; i <= 33; i++)
+ {
+ SERIAL_WRITE (mips_desc, srec, 8);
+
+ if (SERIAL_READCHAR (mips_desc, 0) >= 0)
+ break; /* Break immediatly if we get something from
+ the board. */
+ }
+ }
+ }
+ break;
+ case 4:
+ mips_error ("Failed to initialize.");
+ }
+
+ if (mips_expect (mips_monitor_prompt))
+ break;
+ }
+
+ if (mips_monitor != MON_IDT)
+ {
+ /* Sometimes PMON ignores the first few characters in the first
+ command sent after a load. Sending a blank command gets
+ around that. */
+ mips_send_command ("\r", -1);
+
+ /* Ensure the correct target state: */
+ if (mips_monitor != MON_LSI)
+ mips_send_command ("set regsize 64\r", -1);
+ mips_send_command ("set hostport tty0\r", -1);
+ mips_send_command ("set brkcmd \"\"\r", -1);
+ /* Delete all the current breakpoints: */
+ mips_send_command ("db *\r", -1);
+ /* NOTE: PMON does not have breakpoint support through the
+ "debug" mode, only at the monitor command-line. */
+ }
+
+ mips_enter_debug ();
+
+ /* Clear all breakpoints: */
+ if ((mips_monitor == MON_IDT
+ && clear_breakpoint (-1, 0, BREAK_UNUSED) == 0)
+ || mips_monitor == MON_LSI)
+ monitor_supports_breakpoints = 1;
+ else
+ monitor_supports_breakpoints = 0;
+
+ do_cleanups (old_cleanups);
+
+ /* If this doesn't call error, we have connected; we don't care if
+ the request itself succeeds or fails. */
+
+ mips_request ('r', (unsigned int) 0, (unsigned int) 0, &err,
+ mips_receive_wait, NULL);
+ set_current_frame (create_new_frame (read_fp (), read_pc ()));
+ select_frame (get_current_frame (), 0);
+}
+
+/* Open a connection to the remote board. */
+static void
+common_open (ops, name, from_tty, new_monitor, new_monitor_prompt)
+ struct target_ops *ops;
+ char *name;
+ int from_tty;
+ enum mips_monitor_type new_monitor;
+ char *new_monitor_prompt;
+{
+ char *ptype;
+ char *serial_port_name;
+ char *remote_name = 0;
+ char *local_name = 0;
+ char **argv;
+
+ if (name == 0)
+ error (
+"To open a MIPS remote debugging connection, you need to specify what serial\n\
+device is attached to the target board (e.g., /dev/ttya).\n"
+"If you want to use TFTP to download to the board, specify the name of a\n"
+"temporary file to be used by GDB for downloads as the second argument.\n"
+"This filename must be in the form host:filename, where host is the name\n"
+"of the host running the TFTP server, and the file must be readable by the\n"
+"world. If the local name of the temporary file differs from the name as\n"
+"seen from the board via TFTP, specify that name as the third parameter.\n");
+
+ /* Parse the serial port name, the optional TFTP name, and the
+ optional local TFTP name. */
+ if ((argv = buildargv (name)) == NULL)
+ nomem(0);
+ make_cleanup ((make_cleanup_func) freeargv, argv);
+
+ serial_port_name = strsave (argv[0]);
+ if (argv[1]) /* remote TFTP name specified? */
+ {
+ remote_name = argv[1];
+ if (argv[2]) /* local TFTP filename specified? */
+ local_name = argv[2];
+ }
+
+ target_preopen (from_tty);
+
+ if (mips_is_open)
+ unpush_target (current_ops);
+
+ /* Open and initialize the serial port. */
+ mips_desc = SERIAL_OPEN (serial_port_name);
+ if (mips_desc == (serial_t) NULL)
+ perror_with_name (serial_port_name);
+
+ if (baud_rate != -1)
+ {
+ if (SERIAL_SETBAUDRATE (mips_desc, baud_rate))
+ {
+ SERIAL_CLOSE (mips_desc);
+ perror_with_name (serial_port_name);
+ }
+ }
+
+ SERIAL_RAW (mips_desc);
+
+ /* Open and initialize the optional download port. If it is in the form
+ hostname#portnumber, it's a UDP socket. If it is in the form
+ hostname:filename, assume it's the TFTP filename that must be
+ passed to the DDB board to tell it where to get the load file. */
+ if (remote_name)
+ {
+ if (strchr (remote_name, '#'))
+ {
+ udp_desc = SERIAL_OPEN (remote_name);
+ if (!udp_desc)
+ perror_with_name ("Unable to open UDP port");
+ udp_in_use = 1;
+ }
+ else
+ {
+ /* Save the remote and local names of the TFTP temp file. If
+ the user didn't specify a local name, assume it's the same
+ as the part of the remote name after the "host:". */
+ if (tftp_name)
+ free (tftp_name);
+ if (tftp_localname)
+ free (tftp_localname);
+ if (local_name == NULL)
+ if ((local_name = strchr (remote_name, ':')) != NULL)
+ local_name++; /* skip over the colon */
+ if (local_name == NULL)
+ local_name = remote_name; /* local name same as remote name */
+ tftp_name = strsave (remote_name);
+ tftp_localname = strsave (local_name);
+ tftp_in_use = 1;
+ }
+ }
+
+ current_ops = ops;
+ mips_is_open = 1;
+
+ /* Reset the expected monitor prompt if it's never been set before. */
+ if (mips_monitor_prompt == NULL)
+ mips_monitor_prompt = strsave (new_monitor_prompt);
+ mips_monitor = new_monitor;
+
+ mips_initialize ();
+
+ if (from_tty)
+ printf_unfiltered ("Remote MIPS debugging using %s\n", serial_port_name);
+
+ /* Switch to using remote target now. */
+ push_target (ops);
+
+ /* FIXME: Should we call start_remote here? */
+
+ /* Try to figure out the processor model if possible. */
+ ptype = mips_read_processor_type ();
+ if (ptype)
+ mips_set_processor_type_command (strsave (ptype), 0);
+
+/* This is really the job of start_remote however, that makes an assumption
+ that the target is about to print out a status message of some sort. That
+ doesn't happen here (in fact, it may not be possible to get the monitor to
+ send the appropriate packet). */
+
+ flush_cached_frames ();
+ registers_changed ();
+ stop_pc = read_pc ();
+ set_current_frame (create_new_frame (read_fp (), stop_pc));
+ select_frame (get_current_frame (), 0);
+ print_stack_frame (selected_frame, -1, 1);
+ free (serial_port_name);
+}
+
+static void
+mips_open (name, from_tty)
+ char *name;
+ int from_tty;
+{
+ common_open (&mips_ops, name, from_tty, MON_IDT, TARGET_MONITOR_PROMPT);
+}
+
+static void
+pmon_open (name, from_tty)
+ char *name;
+ int from_tty;
+{
+ common_open (&pmon_ops, name, from_tty, MON_PMON, "PMON> ");
+}
+
+static void
+ddb_open (name, from_tty)
+ char *name;
+ int from_tty;
+{
+ common_open (&ddb_ops, name, from_tty, MON_DDB, "NEC010>");
+}
+
+static void
+lsi_open (name, from_tty)
+ char *name;
+ int from_tty;
+{
+ int i;
+
+ /* Clear the LSI breakpoint table. */
+ for (i = 0; i < MAX_LSI_BREAKPOINTS; i++)
+ lsi_breakpoints[i].type = BREAK_UNUSED;
+
+ common_open (&lsi_ops, name, from_tty, MON_LSI, "PMON> ");
+}
+
+/* Close a connection to the remote board. */
+
+static void
+mips_close (quitting)
+ int quitting;
+{
+ if (mips_is_open)
+ {
+ /* Get the board out of remote debugging mode. */
+ (void) mips_exit_debug ();
+
+ close_ports ();
+ }
+}
+
+/* Detach from the remote board. */
+
+static void
+mips_detach (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ if (args)
+ error ("Argument given to \"detach\" when remotely debugging.");
+
+ pop_target ();
+
+ mips_close (1);
+
+ if (from_tty)
+ printf_unfiltered ("Ending remote MIPS debugging.\n");
+}
+
+/* Tell the target board to resume. This does not wait for a reply
+ from the board, except in the case of single-stepping on LSI boards,
+ where PMON does return a reply. */
+
+static void
+mips_resume (pid, step, siggnal)
+ int pid, step;
+ enum target_signal siggnal;
+{
+ int err;
+
+ /* LSI PMON requires returns a reply packet "0x1 s 0x0 0x57f" after
+ a single step, so we wait for that. */
+ mips_request (step ? 's' : 'c',
+ (unsigned int) 1,
+ (unsigned int) siggnal,
+ mips_monitor == MON_LSI && step ? &err : (int *) NULL,
+ mips_receive_wait, NULL);
+}
+
+/* Return the signal corresponding to SIG, where SIG is the number which
+ the MIPS protocol uses for the signal. */
+enum target_signal
+mips_signal_from_protocol (sig)
+ int sig;
+{
+ /* We allow a few more signals than the IDT board actually returns, on
+ the theory that there is at least *some* hope that perhaps the numbering
+ for these signals is widely agreed upon. */
+ if (sig <= 0
+ || sig > 31)
+ return TARGET_SIGNAL_UNKNOWN;
+
+ /* Don't want to use target_signal_from_host because we are converting
+ from MIPS signal numbers, not host ones. Our internal numbers
+ match the MIPS numbers for the signals the board can return, which
+ are: SIGINT, SIGSEGV, SIGBUS, SIGILL, SIGFPE, SIGTRAP. */
+ return (enum target_signal) sig;
+}
+
+/* Wait until the remote stops, and return a wait status. */
+
+static int
+mips_wait (pid, status)
+ int pid;
+ struct target_waitstatus *status;
+{
+ int rstatus;
+ int err;
+ char buff[DATA_MAXLEN];
+ int rpc, rfp, rsp;
+ char flags[20];
+ int nfields;
+ int i;
+
+ interrupt_count = 0;
+ hit_watchpoint = 0;
+
+ /* If we have not sent a single step or continue command, then the
+ board is waiting for us to do something. Return a status
+ indicating that it is stopped. */
+ if (! mips_need_reply)
+ {
+ status->kind = TARGET_WAITKIND_STOPPED;
+ status->value.sig = TARGET_SIGNAL_TRAP;
+ return 0;
+ }
+
+ /* No timeout; we sit here as long as the program continues to execute. */
+ mips_wait_flag = 1;
+ rstatus = mips_request ('\000', (unsigned int) 0, (unsigned int) 0, &err, -1,
+ buff);
+ mips_wait_flag = 0;
+ if (err)
+ mips_error ("Remote failure: %s", safe_strerror (errno));
+
+ /* On returning from a continue, the PMON monitor seems to start
+ echoing back the messages we send prior to sending back the
+ ACK. The code can cope with this, but to try and avoid the
+ unnecessary serial traffic, and "spurious" characters displayed
+ to the user, we cheat and reset the debug protocol. The problems
+ seems to be caused by a check on the number of arguments, and the
+ command length, within the monitor causing it to echo the command
+ as a bad packet. */
+ if (mips_monitor == MON_PMON)
+ {
+ mips_exit_debug ();
+ mips_enter_debug ();
+ }
+
+ /* See if we got back extended status. If so, pick out the pc, fp, sp, etc... */
+
+ nfields = sscanf (buff, "0x%*x %*c 0x%*x 0x%*x 0x%x 0x%x 0x%x 0x%*x %s",
+ &rpc, &rfp, &rsp, flags);
+ if (nfields >= 3)
+ {
+ char buf[MAX_REGISTER_RAW_SIZE];
+
+ store_unsigned_integer (buf, REGISTER_RAW_SIZE (PC_REGNUM), rpc);
+ supply_register (PC_REGNUM, buf);
+
+ store_unsigned_integer (buf, REGISTER_RAW_SIZE (PC_REGNUM), rfp);
+ supply_register (30, buf); /* This register they are avoiding and so it is unnamed */
+
+ store_unsigned_integer (buf, REGISTER_RAW_SIZE (SP_REGNUM), rsp);
+ supply_register (SP_REGNUM, buf);
+
+ store_unsigned_integer (buf, REGISTER_RAW_SIZE (FP_REGNUM), 0);
+ supply_register (FP_REGNUM, buf);
+
+ if (nfields == 9)
+ {
+ int i;
+
+ for (i = 0; i <= 2; i++)
+ if (flags[i] == 'r' || flags[i] == 'w')
+ hit_watchpoint = 1;
+ else if (flags[i] == '\000')
+ break;
+ }
+ }
+
+ if (strcmp (target_shortname, "lsi") == 0)
+ {
+#if 0
+ /* If this is an LSI PMON target, see if we just hit a hardrdware watchpoint.
+ Right now, PMON doesn't give us enough information to determine which
+ breakpoint we hit. So we have to look up the PC in our own table
+ of breakpoints, and if found, assume it's just a normal instruction
+ fetch breakpoint, not a data watchpoint. FIXME when PMON
+ provides some way to tell us what type of breakpoint it is. */
+ int i;
+ CORE_ADDR pc = read_pc();
+
+ hit_watchpoint = 1;
+ for (i = 0; i < MAX_LSI_BREAKPOINTS; i++)
+ {
+ if (lsi_breakpoints[i].addr == pc
+ && lsi_breakpoints[i].type == BREAK_FETCH)
+ {
+ hit_watchpoint = 0;
+ break;
+ }
+ }
+#else
+ /* If a data breakpoint was hit, PMON returns the following packet:
+ 0x1 c 0x0 0x57f 0x1
+ The return packet from an ordinary breakpoint doesn't have the
+ extra 0x01 field tacked onto the end. */
+ if (nfields == 1 && rpc == 1)
+ hit_watchpoint = 1;
+#endif
+ }
+
+ /* NOTE: The following (sig) numbers are defined by PMON:
+ SPP_SIGTRAP 5 breakpoint
+ SPP_SIGINT 2
+ SPP_SIGSEGV 11
+ SPP_SIGBUS 10
+ SPP_SIGILL 4
+ SPP_SIGFPE 8
+ SPP_SIGTERM 15 */
+
+ /* Translate a MIPS waitstatus. We use constants here rather than WTERMSIG
+ and so on, because the constants we want here are determined by the
+ MIPS protocol and have nothing to do with what host we are running on. */
+ if ((rstatus & 0xff) == 0)
+ {
+ status->kind = TARGET_WAITKIND_EXITED;
+ status->value.integer = (((rstatus) >> 8) & 0xff);
+ }
+ else if ((rstatus & 0xff) == 0x7f)
+ {
+ status->kind = TARGET_WAITKIND_STOPPED;
+ status->value.sig = mips_signal_from_protocol (((rstatus) >> 8) & 0xff);
+
+ /* If the stop PC is in the _exit function, assume
+ we hit the 'break 0x3ff' instruction in _exit, so this
+ is not a normal breakpoint. */
+ if (strcmp (target_shortname, "lsi") == 0)
+ {
+ char *func_name;
+ CORE_ADDR func_start;
+ CORE_ADDR pc = read_pc();
+
+ find_pc_partial_function (pc, &func_name, &func_start, NULL);
+ if (func_name != NULL && strcmp (func_name, "_exit") == 0
+ && func_start == pc)
+ status->kind = TARGET_WAITKIND_EXITED;
+ }
+ }
+ else
+ {
+ status->kind = TARGET_WAITKIND_SIGNALLED;
+ status->value.sig = mips_signal_from_protocol (rstatus & 0x7f);
+ }
+
+ return 0;
+}
+
+/* We have to map between the register numbers used by gdb and the
+ register numbers used by the debugging protocol. This function
+ assumes that we are using tm-mips.h. */
+
+#define REGNO_OFFSET 96
+
+static int
+mips_map_regno (regno)
+ int regno;
+{
+ if (regno < 32)
+ return regno;
+ if (regno >= FP0_REGNUM && regno < FP0_REGNUM + 32)
+ return regno - FP0_REGNUM + 32;
+ switch (regno)
+ {
+ case PC_REGNUM:
+ return REGNO_OFFSET + 0;
+ case CAUSE_REGNUM:
+ return REGNO_OFFSET + 1;
+ case HI_REGNUM:
+ return REGNO_OFFSET + 2;
+ case LO_REGNUM:
+ return REGNO_OFFSET + 3;
+ case FCRCS_REGNUM:
+ return REGNO_OFFSET + 4;
+ case FCRIR_REGNUM:
+ return REGNO_OFFSET + 5;
+ default:
+ /* FIXME: Is there a way to get the status register? */
+ return 0;
+ }
+}
+
+/* Fetch the remote registers. */
+
+static void
+mips_fetch_registers (regno)
+ int regno;
+{
+ unsigned LONGEST val;
+ int err;
+
+ if (regno == -1)
+ {
+ for (regno = 0; regno < NUM_REGS; regno++)
+ mips_fetch_registers (regno);
+ return;
+ }
+
+ if (regno == FP_REGNUM || regno == ZERO_REGNUM)
+ /* FP_REGNUM on the mips is a hack which is just supposed to read
+ zero (see also mips-nat.c). */
+ val = 0;
+ else
+ {
+ /* If PMON doesn't support this register, don't waste serial
+ bandwidth trying to read it. */
+ int pmon_reg = mips_map_regno (regno);
+ if (regno != 0 && pmon_reg == 0)
+ val = 0;
+ else
+ {
+ /* Unfortunately the PMON version in the Vr4300 board has been
+ compiled without the 64bit register access commands. This
+ means we cannot get hold of the full register width. */
+ if (mips_monitor == MON_DDB)
+ val = (unsigned)mips_request ('t', (unsigned int) pmon_reg,
+ (unsigned int) 0, &err, mips_receive_wait, NULL);
+ else
+ val = mips_request ('r', (unsigned int) pmon_reg,
+ (unsigned int) 0, &err, mips_receive_wait, NULL);
+ if (err)
+ mips_error ("Can't read register %d: %s", regno,
+ safe_strerror (errno));
+ }
+ }
+
+ {
+ char buf[MAX_REGISTER_RAW_SIZE];
+
+ /* We got the number the register holds, but gdb expects to see a
+ value in the target byte ordering. */
+ store_unsigned_integer (buf, REGISTER_RAW_SIZE (regno), val);
+ supply_register (regno, buf);
+ }
+}
+
+/* Prepare to store registers. The MIPS protocol can store individual
+ registers, so this function doesn't have to do anything. */
+
+static void
+mips_prepare_to_store ()
+{
+}
+
+/* Store remote register(s). */
+
+static void
+mips_store_registers (regno)
+ int regno;
+{
+ int err;
+
+ if (regno == -1)
+ {
+ for (regno = 0; regno < NUM_REGS; regno++)
+ mips_store_registers (regno);
+ return;
+ }
+
+ mips_request ('R', (unsigned int) mips_map_regno (regno),
+ read_register (regno),
+ &err, mips_receive_wait, NULL);
+ if (err)
+ mips_error ("Can't write register %d: %s", regno, safe_strerror (errno));
+}
+
+/* Fetch a word from the target board. */
+
+static unsigned int
+mips_fetch_word (addr)
+ CORE_ADDR addr;
+{
+ unsigned int val;
+ int err;
+
+ /* FIXME! addr was cast to uint! */
+ val = mips_request ('d', addr, (unsigned int) 0, &err,
+ mips_receive_wait, NULL);
+ if (err)
+ {
+ /* Data space failed; try instruction space. */
+ /* FIXME! addr was cast to uint! */
+ val = mips_request ('i', addr, (unsigned int) 0, &err,
+ mips_receive_wait, NULL);
+ if (err)
+ mips_error ("Can't read address 0x%s: %s",
+ paddr_nz (addr), safe_strerror (errno));
+ }
+ return val;
+}
+
+/* Store a word to the target board. Returns errno code or zero for
+ success. If OLD_CONTENTS is non-NULL, put the old contents of that
+ memory location there. */
+
+/* FIXME! make sure only 32-bit quantities get stored! */
+static int
+mips_store_word (addr, val, old_contents)
+ CORE_ADDR addr;
+ unsigned int val;
+ char *old_contents;
+{
+ int err;
+ unsigned int oldcontents;
+
+ oldcontents = mips_request ('D', addr, (unsigned int) val,
+ &err,
+ mips_receive_wait, NULL);
+ if (err)
+ {
+ /* Data space failed; try instruction space. */
+ oldcontents = mips_request ('I', addr,
+ (unsigned int) val, &err,
+ mips_receive_wait, NULL);
+ if (err)
+ return errno;
+ }
+ if (old_contents != NULL)
+ store_unsigned_integer (old_contents, 4, oldcontents);
+ return 0;
+}
+
+/* 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. Note that protocol gives us the correct value
+ for a longword, since it transfers values in ASCII. We want the
+ byte values, so we have to swap the longword values. */
+
+static int
+mips_xfer_memory (memaddr, myaddr, len, write, ignore)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+ int write;
+ struct target_ops *ignore;
+{
+ register int i;
+ /* Round starting address down to longword boundary. */
+ register CORE_ADDR addr = memaddr &~ 3;
+ /* Round ending address up; get number of longwords that makes. */
+ register int count = (((memaddr + len) - addr) + 3) / 4;
+ /* Allocate buffer of that many longwords. */
+ register char *buffer = alloca (count * 4);
+
+ int status;
+
+ if (write)
+ {
+ /* Fill start and end extra bytes of buffer with existing data. */
+ if (addr != memaddr || len < 4)
+ {
+ /* Need part of initial word -- fetch it. */
+ store_unsigned_integer (&buffer[0], 4, mips_fetch_word (addr));
+ }
+
+ if (count > 1)
+ {
+ /* Need part of last word -- fetch it. FIXME: we do this even
+ if we don't need it. */
+ store_unsigned_integer (&buffer[(count - 1) * 4], 4,
+ mips_fetch_word (addr + (count - 1) * 4));
+ }
+
+ /* Copy data to be written over corresponding part of buffer */
+
+ memcpy ((char *) buffer + (memaddr & 3), myaddr, len);
+
+ /* Write the entire buffer. */
+
+ for (i = 0; i < count; i++, addr += 4)
+ {
+ status = mips_store_word (addr,
+ extract_unsigned_integer (&buffer[i*4], 4),
+ NULL);
+ /* Report each kilobyte (we download 32-bit words at a time) */
+ if (i % 256 == 255)
+ {
+ printf_unfiltered ("*");
+ gdb_flush (gdb_stdout);
+ }
+ if (status)
+ {
+ errno = status;
+ return 0;
+ }
+ /* FIXME: Do we want a QUIT here? */
+ }
+ if (count >= 256)
+ printf_unfiltered ("\n");
+ }
+ else
+ {
+ /* Read all the longwords */
+ for (i = 0; i < count; i++, addr += 4)
+ {
+ store_unsigned_integer (&buffer[i*4], 4, mips_fetch_word (addr));
+ QUIT;
+ }
+
+ /* Copy appropriate bytes out of the buffer. */
+ memcpy (myaddr, buffer + (memaddr & 3), len);
+ }
+ return len;
+}
+
+/* Print info on this target. */
+
+static void
+mips_files_info (ignore)
+ struct target_ops *ignore;
+{
+ printf_unfiltered ("Debugging a MIPS board over a serial line.\n");
+}
+
+/* Kill the process running on the board. This will actually only
+ work if we are doing remote debugging over the console input. I
+ think that if IDT/sim had the remote debug interrupt enabled on the
+ right port, we could interrupt the process with a break signal. */
+
+static void
+mips_kill ()
+{
+ if (!mips_wait_flag)
+ return;
+
+ interrupt_count++;
+
+ if (interrupt_count >= 2)
+ {
+ interrupt_count = 0;
+
+ target_terminal_ours ();
+
+ if (query ("Interrupted while waiting for the program.\n\
+Give up (and stop debugging it)? "))
+ {
+ /* Clean up in such a way that mips_close won't try to talk to the
+ board (it almost surely won't work since we weren't able to talk to
+ it). */
+ mips_wait_flag = 0;
+ close_ports();
+
+ printf_unfiltered ("Ending remote MIPS debugging.\n");
+ target_mourn_inferior ();
+
+ return_to_top_level (RETURN_QUIT);
+ }
+
+ target_terminal_inferior ();
+ }
+
+ if (remote_debug > 0)
+ printf_unfiltered ("Sending break\n");
+
+ SERIAL_SEND_BREAK (mips_desc);
+
+#if 0
+ if (mips_is_open)
+ {
+ char cc;
+
+ /* Send a ^C. */
+ cc = '\003';
+ SERIAL_WRITE (mips_desc, &cc, 1);
+ sleep (1);
+ target_mourn_inferior ();
+ }
+#endif
+}
+
+/* Start running on the target board. */
+
+static void
+mips_create_inferior (execfile, args, env)
+ char *execfile;
+ char *args;
+ char **env;
+{
+ CORE_ADDR entry_pt;
+
+ if (args && *args)
+ {
+ warning ("\
+Can't pass arguments to remote MIPS board; arguments ignored.");
+ /* And don't try to use them on the next "run" command. */
+ execute_command ("set args", 0);
+ }
+
+ if (execfile == 0 || exec_bfd == 0)
+ error ("No executable file specified");
+
+ entry_pt = (CORE_ADDR) bfd_get_start_address (exec_bfd);
+
+ init_wait_for_inferior ();
+
+ /* FIXME: Should we set inferior_pid here? */
+
+ proceed (entry_pt, TARGET_SIGNAL_DEFAULT, 0);
+}
+
+/* Clean up after a process. Actually nothing to do. */
+
+static void
+mips_mourn_inferior ()
+{
+ if (current_ops != NULL)
+ unpush_target (current_ops);
+ generic_mourn_inferior ();
+}
+
+/* We can write a breakpoint and read the shadow contents in one
+ operation. */
+
+/* Insert a breakpoint. On targets that don't have built-in 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
+mips_insert_breakpoint (addr, contents_cache)
+ CORE_ADDR addr;
+ char *contents_cache;
+{
+ if (monitor_supports_breakpoints)
+ return set_breakpoint (addr, MIPS_INSTLEN, BREAK_FETCH);
+ else
+ return memory_insert_breakpoint (addr, contents_cache);
+}
+
+static int
+mips_remove_breakpoint (addr, contents_cache)
+ CORE_ADDR addr;
+ char *contents_cache;
+{
+ if (monitor_supports_breakpoints)
+ return clear_breakpoint (addr, MIPS_INSTLEN, BREAK_FETCH);
+ else
+ return memory_remove_breakpoint (addr, contents_cache);
+}
+
+#if 0 /* currently not used */
+/* PMON does not currently provide support for the debug mode 'b'
+ commands to manipulate breakpoints. However, if we wanted to use
+ the monitor breakpoints (rather than the GDB BREAK_INSN version)
+ then this code performs the work needed to leave debug mode,
+ set/clear the breakpoint, and then return to debug mode. */
+
+#define PMON_MAX_BP (33) /* 32 SW, 1 HW */
+static CORE_ADDR mips_pmon_bp_info[PMON_MAX_BP];
+/* NOTE: The code relies on this vector being zero-initialised by the system */
+
+static int
+pmon_insert_breakpoint (addr, contents_cache)
+ CORE_ADDR addr;
+ char *contents_cache;
+{
+ int status;
+
+ if (monitor_supports_breakpoints)
+ {
+ char tbuff[12]; /* space for breakpoint command */
+ int bpnum;
+ CORE_ADDR bpaddr;
+
+ /* PMON does not support debug level breakpoint set/remove: */
+ if (mips_exit_debug ())
+ mips_error ("Failed to exit debug mode");
+
+ sprintf (tbuff, "b %08x\r", addr);
+ mips_send_command (tbuff, 0);
+
+ mips_expect ("Bpt ");
+
+ if (!mips_getstring (tbuff, 2))
+ return 1;
+ tbuff[2] = '\0'; /* terminate the string */
+ if (sscanf (tbuff, "%d", &bpnum) != 1)
+ {
+ fprintf_unfiltered (gdb_stderr,
+ "Invalid decimal breakpoint number from target: %s\n", tbuff);
+ return 1;
+ }
+
+ mips_expect (" = ");
+
+ /* Lead in the hex number we are expecting: */
+ tbuff[0] = '0';
+ tbuff[1] = 'x';
+
+ /* FIXME!! only 8 bytes! need to expand for Bfd64;
+ which targets return 64-bit addresses? PMON returns only 32! */
+ if (!mips_getstring (&tbuff[2], 8))
+ return 1;
+ tbuff[10] = '\0'; /* terminate the string */
+
+ if (sscanf (tbuff, "0x%08x", &bpaddr) != 1)
+ {
+ fprintf_unfiltered (gdb_stderr,
+ "Invalid hex address from target: %s\n", tbuff);
+ return 1;
+ }
+
+ if (bpnum >= PMON_MAX_BP)
+ {
+ fprintf_unfiltered (gdb_stderr,
+ "Error: Returned breakpoint number %d outside acceptable range (0..%d)\n",
+ bpnum, PMON_MAX_BP - 1);
+ return 1;
+ }
+
+ if (bpaddr != addr)
+ fprintf_unfiltered (gdb_stderr, "Warning: Breakpoint addresses do not match: 0x%x != 0x%x\n", addr, bpaddr);
+
+ mips_pmon_bp_info[bpnum] = bpaddr;
+
+ mips_expect ("\r\n");
+ mips_expect (mips_monitor_prompt);
+
+ mips_enter_debug ();
+
+ return 0;
+ }
+
+ return mips_store_word (addr, BREAK_INSN, contents_cache);
+}
+
+static int
+pmon_remove_breakpoint (addr, contents_cache)
+ CORE_ADDR addr;
+ char *contents_cache;
+{
+ if (monitor_supports_breakpoints)
+ {
+ int bpnum;
+ char tbuff[7]; /* enough for delete breakpoint command */
+
+ for (bpnum = 0; bpnum < PMON_MAX_BP; bpnum++)
+ if (mips_pmon_bp_info[bpnum] == addr)
+ break;
+
+ if (bpnum >= PMON_MAX_BP)
+ {
+ fprintf_unfiltered (gdb_stderr,
+ "pmon_remove_breakpoint: Failed to find breakpoint at address 0x%s\n",
+ paddr_nz (addr));
+ return 1;
+ }
+
+ if (mips_exit_debug ())
+ mips_error ("Failed to exit debug mode");
+
+ sprintf (tbuff, "db %02d\r", bpnum);
+
+ mips_send_command (tbuff, -1);
+ /* NOTE: If the breakpoint does not exist then a "Bpt <dd> not
+ set" message will be returned. */
+
+ mips_enter_debug ();
+
+ return 0;
+ }
+
+ return target_write_memory (addr, contents_cache, BREAK_INSN_SIZE);
+}
+#endif
+
+
+/* Tell whether this target can support a hardware breakpoint. CNT
+ is the number of hardware breakpoints already installed. This
+ implements the TARGET_CAN_USE_HARDWARE_WATCHPOINT macro. */
+
+int
+remote_mips_can_use_hardware_watchpoint (cnt)
+ int cnt;
+{
+ return cnt < MAX_LSI_BREAKPOINTS && strcmp (target_shortname, "lsi") == 0;
+}
+
+
+/* Compute a don't care mask for the region bounding ADDR and ADDR + LEN - 1.
+ This is used for memory ref breakpoints. */
+
+static unsigned long
+calculate_mask (addr, len)
+ CORE_ADDR addr;
+ int len;
+{
+ unsigned long mask;
+ int i;
+
+ mask = addr ^ (addr + len - 1);
+
+ for (i = 32; i >= 0; i--)
+ if (mask == 0)
+ break;
+ else
+ mask >>= 1;
+
+ mask = (unsigned long) 0xffffffff >> i;
+
+ return mask;
+}
+
+
+/* Insert a hardware breakpoint. This works only on LSI targets, which
+ implement ordinary breakpoints using hardware facilities. */
+
+int
+remote_mips_insert_hw_breakpoint (addr, contents_cache)
+ CORE_ADDR addr;
+ char *contents_cache;
+{
+ if (strcmp (target_shortname, "lsi") == 0)
+ return mips_insert_breakpoint (addr, contents_cache);
+ else
+ return -1;
+}
+
+
+/* Remove a hardware breakpoint. This works only on LSI targets, which
+ implement ordinary breakpoints using hardware facilities. */
+
+int
+remote_mips_remove_hw_breakpoint (addr, contents_cache)
+ CORE_ADDR addr;
+ char *contents_cache;
+{
+ if (strcmp (target_shortname, "lsi") == 0)
+ return mips_remove_breakpoint (addr, contents_cache);
+ else
+ return -1;
+}
+
+/* Set a data watchpoint. ADDR and LEN should be obvious. TYPE is 0
+ for a write watchpoint, 1 for a read watchpoint, or 2 for a read/write
+ watchpoint. */
+
+int
+remote_mips_set_watchpoint (addr, len, type)
+ CORE_ADDR addr;
+ int len;
+ int type;
+{
+ if (set_breakpoint (addr, len, type))
+ return -1;
+
+ return 0;
+}
+
+int
+remote_mips_remove_watchpoint (addr, len, type)
+ CORE_ADDR addr;
+ int len;
+ int type;
+{
+ if (clear_breakpoint (addr, len, type))
+ return -1;
+
+ return 0;
+}
+
+int
+remote_mips_stopped_by_watchpoint ()
+{
+ return hit_watchpoint;
+}
+
+
+/* Insert a breakpoint. */
+
+static int
+set_breakpoint (addr, len, type)
+ CORE_ADDR addr;
+ int len;
+ enum break_type type;
+{
+ return common_breakpoint (1, addr, len, type);
+}
+
+
+/* Clear a breakpoint. */
+
+static int
+clear_breakpoint (addr, len, type)
+ CORE_ADDR addr;
+ int len;
+ enum break_type type;
+{
+ return common_breakpoint (0, addr, len, type);
+}
+
+
+/* Check the error code from the return packet for an LSI breakpoint
+ command. If there's no error, just return 0. If it's a warning,
+ print the warning text and return 0. If it's an error, print
+ the error text and return 1. <ADDR> is the address of the breakpoint
+ that was being set. <RERRFLG> is the error code returned by PMON.
+ This is a helper function for common_breakpoint. */
+
+static int
+check_lsi_error (addr, rerrflg)
+ CORE_ADDR addr;
+ int rerrflg;
+{
+ struct lsi_error *err;
+ char *saddr = paddr_nz (addr); /* printable address string */
+
+ if (rerrflg == 0) /* no error */
+ return 0;
+
+ /* Warnings can be ORed together, so check them all. */
+ if (rerrflg & W_WARN)
+ {
+ if (monitor_warnings)
+ {
+ int found = 0;
+ for (err = lsi_warning_table; err->code != 0; err++)
+ {
+ if ((err->code & rerrflg) == err->code)
+ {
+ found = 1;
+ fprintf_unfiltered (gdb_stderr,
+ "common_breakpoint (0x%s): Warning: %s\n",
+ saddr,
+ err->string);
+ }
+ }
+ if (!found)
+ fprintf_unfiltered (gdb_stderr,
+ "common_breakpoint (0x%s): Unknown warning: 0x%x\n",
+ saddr,
+ rerrflg);
+ }
+ return 0;
+ }
+
+ /* Errors are unique, i.e. can't be ORed together. */
+ for (err = lsi_error_table; err->code != 0; err++)
+ {
+ if ((err->code & rerrflg) == err->code)
+ {
+ fprintf_unfiltered (gdb_stderr,
+ "common_breakpoint (0x%s): Error: %s\n",
+ saddr,
+ err->string);
+ return 1;
+ }
+ }
+ fprintf_unfiltered (gdb_stderr,
+ "common_breakpoint (0x%s): Unknown error: 0x%x\n",
+ saddr,
+ rerrflg);
+ return 1;
+}
+
+
+/* This routine sends a breakpoint command to the remote target.
+
+ <SET> is 1 if setting a breakpoint, or 0 if clearing a breakpoint.
+ <ADDR> is the address of the breakpoint.
+ <LEN> the length of the region to break on.
+ <TYPE> is the type of breakpoint:
+ 0 = write (BREAK_WRITE)
+ 1 = read (BREAK_READ)
+ 2 = read/write (BREAK_ACCESS)
+ 3 = instruction fetch (BREAK_FETCH)
+
+ Return 0 if successful; otherwise 1. */
+
+static int
+common_breakpoint (set, addr, len, type)
+ int set;
+ CORE_ADDR addr;
+ int len;
+ enum break_type type;
+{
+ char buf[DATA_MAXLEN + 1];
+ char cmd, rcmd;
+ int rpid, rerrflg, rresponse, rlen;
+ int nfields;
+
+ addr = ADDR_BITS_REMOVE (addr);
+
+ if (mips_monitor == MON_LSI)
+ {
+ if (set == 0) /* clear breakpoint */
+ {
+ /* The LSI PMON "clear breakpoint" has this form:
+ <pid> 'b' <bptn> 0x0
+ reply:
+ <pid> 'b' 0x0 <code>
+
+ <bptn> is a breakpoint number returned by an earlier 'B' command.
+ Possible return codes: OK, E_BPT. */
+
+ int i;
+
+ /* Search for the breakpoint in the table. */
+ for (i = 0; i < MAX_LSI_BREAKPOINTS; i++)
+ if (lsi_breakpoints[i].type == type
+ && lsi_breakpoints[i].addr == addr
+ && lsi_breakpoints[i].len == len)
+ break;
+
+ /* Clear the table entry and tell PMON to clear the breakpoint. */
+ if (i == MAX_LSI_BREAKPOINTS)
+ {
+ warning ("common_breakpoint: Attempt to clear bogus breakpoint at %s\n",
+ paddr_nz (addr));
+ return 1;
+ }
+
+ lsi_breakpoints[i].type = BREAK_UNUSED;
+ sprintf (buf, "0x0 b 0x%x 0x0", i);
+ mips_send_packet (buf, 1);
+
+ rlen = mips_receive_packet (buf, 1, mips_receive_wait);
+ buf[rlen] = '\0';
+
+ nfields = sscanf (buf, "0x%x b 0x0 0x%x", &rpid, &rerrflg);
+ if (nfields != 2)
+ mips_error ("common_breakpoint: Bad response from remote board: %s", buf);
+
+ return (check_lsi_error (addr, rerrflg));
+ }
+ else /* set a breakpoint */
+ {
+ /* The LSI PMON "set breakpoint" command has this form:
+ <pid> 'B' <addr> 0x0
+ reply:
+ <pid> 'B' <bptn> <code>
+
+ The "set data breakpoint" command has this form:
+
+ <pid> 'A' <addr1> <type> [<addr2> [<value>]]
+
+ where: type= "0x1" = read
+ "0x2" = write
+ "0x3" = access (read or write)
+
+ The reply returns two values:
+ bptn - a breakpoint number, which is a small integer with
+ possible values of zero through 255.
+ code - an error return code, a value of zero indicates a
+ succesful completion, other values indicate various
+ errors and warnings.
+
+ Possible return codes: OK, W_QAL, E_QAL, E_OUT, E_NON.
+
+ */
+
+ if (type == BREAK_FETCH) /* instruction breakpoint */
+ {
+ cmd = 'B';
+ sprintf (buf, "0x0 B 0x%s 0x0", paddr_nz (addr));
+ }
+ else /* watchpoint */
+ {
+ cmd = 'A';
+ sprintf (buf, "0x0 A 0x%s 0x%x 0x%s", paddr_nz (addr),
+ type == BREAK_READ ? 1 : (type == BREAK_WRITE ? 2 : 3),
+ paddr_nz (addr + len - 1));
+ }
+ mips_send_packet (buf, 1);
+
+ rlen = mips_receive_packet (buf, 1, mips_receive_wait);
+ buf[rlen] = '\0';
+
+ nfields = sscanf (buf, "0x%x %c 0x%x 0x%x",
+ &rpid, &rcmd, &rresponse, &rerrflg);
+ if (nfields != 4 || rcmd != cmd || rresponse > 255)
+ mips_error ("common_breakpoint: Bad response from remote board: %s", buf);
+
+ if (rerrflg != 0)
+ if (check_lsi_error (addr, rerrflg))
+ return 1;
+
+ /* rresponse contains PMON's breakpoint number. Record the
+ information for this breakpoint so we can clear it later. */
+ lsi_breakpoints[rresponse].type = type;
+ lsi_breakpoints[rresponse].addr = addr;
+ lsi_breakpoints[rresponse].len = len;
+
+ return 0;
+ }
+ }
+ else
+ {
+ /* On non-LSI targets, the breakpoint command has this form:
+ 0x0 <CMD> <ADDR> <MASK> <FLAGS>
+ <MASK> is a don't care mask for addresses.
+ <FLAGS> is any combination of `r', `w', or `f' for read/write/fetch.
+ */
+ unsigned long mask;
+
+ mask = calculate_mask (addr, len);
+ addr &= ~mask;
+
+ if (set) /* set a breakpoint */
+ {
+ char *flags;
+ switch (type)
+ {
+ case BREAK_WRITE: /* write */
+ flags = "w";
+ break;
+ case BREAK_READ: /* read */
+ flags = "r";
+ break;
+ case BREAK_ACCESS: /* read/write */
+ flags = "rw";
+ break;
+ case BREAK_FETCH: /* fetch */
+ flags = "f";
+ break;
+ default:
+ abort ();
+ }
+
+ cmd = 'B';
+ sprintf (buf, "0x0 B 0x%s 0x%s %s", paddr_nz (addr),
+ paddr_nz (mask), flags);
+ }
+ else
+ {
+ cmd = 'b';
+ sprintf (buf, "0x0 b 0x%s", paddr_nz (addr));
+ }
+
+ mips_send_packet (buf, 1);
+
+ rlen = mips_receive_packet (buf, 1, mips_receive_wait);
+ buf[rlen] = '\0';
+
+ nfields = sscanf (buf, "0x%x %c 0x%x 0x%x",
+ &rpid, &rcmd, &rerrflg, &rresponse);
+
+ if (nfields != 4 || rcmd != cmd)
+ mips_error ("common_breakpoint: Bad response from remote board: %s",
+ buf);
+
+ if (rerrflg != 0)
+ {
+ /* Ddb returns "0x0 b 0x16 0x0\000", whereas
+ Cogent returns "0x0 b 0xffffffff 0x16\000": */
+ if (mips_monitor == MON_DDB)
+ rresponse = rerrflg;
+ if (rresponse != 22) /* invalid argument */
+ fprintf_unfiltered (gdb_stderr,
+ "common_breakpoint (0x%s): Got error: 0x%x\n",
+ paddr_nz (addr), rresponse);
+ return 1;
+ }
+ }
+ return 0;
+}
+
+static void
+send_srec (srec, len, addr)
+ char *srec;
+ int len;
+ CORE_ADDR addr;
+{
+ while (1)
+ {
+ int ch;
+
+ SERIAL_WRITE (mips_desc, srec, len);
+
+ ch = mips_readchar (2);
+
+ switch (ch)
+ {
+ case SERIAL_TIMEOUT:
+ error ("Timeout during download.");
+ break;
+ case 0x6: /* ACK */
+ return;
+ case 0x15: /* NACK */
+ fprintf_unfiltered (gdb_stderr, "Download got a NACK at byte %d! Retrying.\n", addr);
+ continue;
+ default:
+ error ("Download got unexpected ack char: 0x%x, retrying.\n", ch);
+ }
+ }
+}
+
+/* Download a binary file by converting it to S records. */
+
+static void
+mips_load_srec (args)
+ char *args;
+{
+ bfd *abfd;
+ asection *s;
+ char *buffer, srec[1024];
+ unsigned int i;
+ unsigned int srec_frame = 200;
+ int reclen;
+ static int hashmark = 1;
+
+ buffer = alloca (srec_frame * 2 + 256);
+
+ abfd = bfd_openr (args, 0);
+ if (!abfd)
+ {
+ printf_filtered ("Unable to open file %s\n", args);
+ return;
+ }
+
+ if (bfd_check_format (abfd, bfd_object) == 0)
+ {
+ printf_filtered ("File is not an object file\n");
+ return;
+ }
+
+/* This actually causes a download in the IDT binary format: */
+ mips_send_command (LOAD_CMD, 0);
+
+ for (s = abfd->sections; s; s = s->next)
+ {
+ if (s->flags & SEC_LOAD)
+ {
+ unsigned int numbytes;
+
+ /* FIXME! vma too small?? */
+ printf_filtered ("%s\t: 0x%4x .. 0x%4x ", s->name, s->vma,
+ s->vma + s->_raw_size);
+ gdb_flush (gdb_stdout);
+
+ for (i = 0; i < s->_raw_size; i += numbytes)
+ {
+ numbytes = min (srec_frame, s->_raw_size - i);
+
+ bfd_get_section_contents (abfd, s, buffer, i, numbytes);
+
+ reclen = mips_make_srec (srec, '3', s->vma + i, buffer, numbytes);
+ send_srec (srec, reclen, s->vma + i);
+
+ if (hashmark)
+ {
+ putchar_unfiltered ('#');
+ gdb_flush (gdb_stdout);
+ }
+
+ } /* Per-packet (or S-record) loop */
+
+ putchar_unfiltered ('\n');
+ } /* Loadable sections */
+ }
+ if (hashmark)
+ putchar_unfiltered ('\n');
+
+ /* Write a type 7 terminator record. no data for a type 7, and there
+ is no data, so len is 0. */
+
+ reclen = mips_make_srec (srec, '7', abfd->start_address, NULL, 0);
+
+ send_srec (srec, reclen, abfd->start_address);
+
+ SERIAL_FLUSH_INPUT (mips_desc);
+}
+
+/*
+ * mips_make_srec -- make an srecord. This writes each line, one at a
+ * time, each with it's own header and trailer line.
+ * An srecord looks like this:
+ *
+ * byte count-+ address
+ * start ---+ | | data +- checksum
+ * | | | |
+ * S01000006F6B692D746573742E73726563E4
+ * S315000448600000000000000000FC00005900000000E9
+ * S31A0004000023C1400037DE00F023604000377B009020825000348D
+ * S30B0004485A0000000000004E
+ * S70500040000F6
+ *
+ * S<type><length><address><data><checksum>
+ *
+ * Where
+ * - 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.
+ * - 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
+ *
+ * - address
+ * is the start address of the data following, or in the case of
+ * a termination record, the start address of the image
+ * - data
+ * is the data.
+ * - checksum
+ * is the sum of all the raw byte data in the record, from the length
+ * upwards, modulo 256 and subtracted from 255.
+ *
+ * This routine returns the length of the S-record.
+ *
+ */
+
+static int
+mips_make_srec (buf, type, memaddr, myaddr, len)
+ char *buf;
+ int type;
+ CORE_ADDR memaddr;
+ unsigned char *myaddr;
+ int len;
+{
+ unsigned char checksum;
+ int i;
+
+ /* Create the header for the srec. addr_size is the number of bytes in the address,
+ and 1 is the number of bytes in the count. */
+
+ /* FIXME!! bigger buf required for 64-bit! */
+ buf[0] = 'S';
+ buf[1] = type;
+ buf[2] = len + 4 + 1; /* len + 4 byte address + 1 byte checksum */
+ /* This assumes S3 style downloads (4byte addresses). There should
+ probably be a check, or the code changed to make it more
+ explicit. */
+ buf[3] = memaddr >> 24;
+ buf[4] = memaddr >> 16;
+ buf[5] = memaddr >> 8;
+ buf[6] = memaddr;
+ memcpy (&buf[7], myaddr, len);
+
+ /* Note that the checksum is calculated on the raw data, not the
+ hexified data. It includes the length, address and the data
+ portions of the packet. */
+ checksum = 0;
+ buf += 2; /* Point at length byte */
+ for (i = 0; i < len + 4 + 1; i++)
+ checksum += *buf++;
+
+ *buf = ~checksum;
+
+ return len + 8;
+}
+
+/* The following manifest controls whether we enable the simple flow
+ control support provided by the monitor. If enabled the code will
+ wait for an affirmative ACK between transmitting packets. */
+#define DOETXACK (1)
+
+/* The PMON fast-download uses an encoded packet format constructed of
+ 3byte data packets (encoded as 4 printable ASCII characters), and
+ escape sequences (preceded by a '/'):
+
+ 'K' clear checksum
+ 'C' compare checksum (12bit value, not included in checksum calculation)
+ 'S' define symbol name (for addr) terminated with "," and padded to 4char boundary
+ 'Z' zero fill multiple of 3bytes
+ 'B' byte (12bit encoded value, of 8bit data)
+ 'A' address (36bit encoded value)
+ 'E' define entry as original address, and exit load
+
+ The packets are processed in 4 character chunks, so the escape
+ sequences that do not have any data (or variable length data)
+ should be padded to a 4 character boundary. The decoder will give
+ an error if the complete message block size is not a multiple of
+ 4bytes (size of record).
+
+ The encoding of numbers is done in 6bit fields. The 6bit value is
+ used to index into this string to get the specific character
+ encoding for the value: */
+static char encoding[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789,.";
+
+/* Convert the number of bits required into an encoded number, 6bits
+ at a time (range 0..63). Keep a checksum if required (passed
+ pointer non-NULL). The function returns the number of encoded
+ characters written into the buffer. */
+static int
+pmon_makeb64 (v, p, n, chksum)
+ unsigned long v;
+ char *p;
+ int n;
+ int *chksum;
+{
+ int count = (n / 6);
+
+ if ((n % 12) != 0) {
+ fprintf_unfiltered(gdb_stderr,
+ "Fast encoding bitcount must be a multiple of 12bits: %dbit%s\n",n,(n == 1)?"":"s");
+ return(0);
+ }
+ if (n > 36) {
+ fprintf_unfiltered(gdb_stderr,
+ "Fast encoding cannot process more than 36bits at the moment: %dbits\n",n);
+ return(0);
+ }
+
+ /* Deal with the checksum: */
+ if (chksum != NULL) {
+ switch (n) {
+ case 36: *chksum += ((v >> 24) & 0xFFF);
+ case 24: *chksum += ((v >> 12) & 0xFFF);
+ case 12: *chksum += ((v >> 0) & 0xFFF);
+ }
+ }
+
+ do {
+ n -= 6;
+ *p++ = encoding[(v >> n) & 0x3F];
+ } while (n > 0);
+
+ return(count);
+}
+
+/* Shorthand function (that could be in-lined) to output the zero-fill
+ escape sequence into the data stream. */
+static int
+pmon_zeroset (recsize, buff, amount, chksum)
+ int recsize;
+ char **buff;
+ int *amount;
+ unsigned int *chksum;
+{
+ int count;
+
+ sprintf(*buff,"/Z");
+ count = pmon_makeb64 (*amount, (*buff + 2), 12, chksum);
+ *buff += (count + 2);
+ *amount = 0;
+ return(recsize + count + 2);
+}
+
+static int
+pmon_checkset (recsize, buff, value)
+ int recsize;
+ char **buff;
+ int *value;
+{
+ int count;
+
+ /* Add the checksum (without updating the value): */
+ sprintf (*buff, "/C");
+ count = pmon_makeb64 (*value, (*buff + 2), 12, NULL);
+ *buff += (count + 2);
+ sprintf (*buff, "\n");
+ *buff += 2; /* include zero terminator */
+ /* Forcing a checksum validation clears the sum: */
+ *value = 0;
+ return(recsize + count + 3);
+}
+
+/* Amount of padding we leave after at the end of the output buffer,
+ for the checksum and line termination characters: */
+#define CHECKSIZE (4 + 4 + 4 + 2)
+/* zero-fill, checksum, transfer end and line termination space. */
+
+/* The amount of binary data loaded from the object file in a single
+ operation: */
+#define BINCHUNK (1024)
+
+/* Maximum line of data accepted by the monitor: */
+#define MAXRECSIZE (550)
+/* NOTE: This constant depends on the monitor being used. This value
+ is for PMON 5.x on the Cogent Vr4300 board. */
+
+static void
+pmon_make_fastrec (outbuf, inbuf, inptr, inamount, recsize, csum, zerofill)
+ char **outbuf;
+ unsigned char *inbuf;
+ int *inptr;
+ int inamount;
+ int *recsize;
+ unsigned int *csum;
+ unsigned int *zerofill;
+{
+ int count = 0;
+ char *p = *outbuf;
+
+ /* This is a simple check to ensure that our data will fit within
+ the maximum allowable record size. Each record output is 4bytes
+ in length. We must allow space for a pending zero fill command,
+ the record, and a checksum record. */
+ while ((*recsize < (MAXRECSIZE - CHECKSIZE)) && ((inamount - *inptr) > 0)) {
+ /* Process the binary data: */
+ if ((inamount - *inptr) < 3) {
+ if (*zerofill != 0)
+ *recsize = pmon_zeroset (*recsize, &p, zerofill, csum);
+ sprintf (p, "/B");
+ count = pmon_makeb64 (inbuf[*inptr], &p[2], 12, csum);
+ p += (2 + count);
+ *recsize += (2 + count);
+ (*inptr)++;
+ } else {
+ unsigned int value = ((inbuf[*inptr + 0] << 16) | (inbuf[*inptr + 1] << 8) | inbuf[*inptr + 2]);
+ /* Simple check for zero data. TODO: A better check would be
+ to check the last, and then the middle byte for being zero
+ (if the first byte is not). We could then check for
+ following runs of zeros, and if above a certain size it is
+ worth the 4 or 8 character hit of the byte insertions used
+ to pad to the start of the zeroes. NOTE: This also depends
+ on the alignment at the end of the zero run. */
+ if (value == 0x00000000) {
+ (*zerofill)++;
+ if (*zerofill == 0xFFF) /* 12bit counter */
+ *recsize = pmon_zeroset (*recsize, &p, zerofill, csum);
+ }else {
+ if (*zerofill != 0)
+ *recsize = pmon_zeroset (*recsize, &p, zerofill, csum);
+ count = pmon_makeb64 (value, p, 24, csum);
+ p += count;
+ *recsize += count;
+ }
+ *inptr += 3;
+ }
+ }
+
+ *outbuf = p;
+ return;
+}
+
+static int
+pmon_check_ack(mesg)
+ char *mesg;
+{
+#if defined(DOETXACK)
+ int c;
+
+ if (!tftp_in_use)
+ {
+ c = SERIAL_READCHAR (udp_in_use ? udp_desc : mips_desc, 2);
+ if ((c == SERIAL_TIMEOUT) || (c != 0x06))
+ {
+ fprintf_unfiltered (gdb_stderr,
+ "Failed to receive valid ACK for %s\n", mesg);
+ return(-1); /* terminate the download */
+ }
+ }
+#endif /* DOETXACK */
+ return(0);
+}
+
+/* pmon_download - Send a sequence of characters to the PMON download port,
+ which is either a serial port or a UDP socket. */
+
+static void
+pmon_start_download ()
+{
+ if (tftp_in_use)
+ {
+ /* Create the temporary download file. */
+ if ((tftp_file = fopen (tftp_localname, "w")) == NULL)
+ perror_with_name (tftp_localname);
+ }
+ else
+ {
+ mips_send_command (udp_in_use ? LOAD_CMD_UDP : LOAD_CMD, 0);
+ mips_expect ("Downloading from ");
+ mips_expect (udp_in_use ? "udp" : "tty0");
+ mips_expect (", ^C to abort\r\n");
+ }
+}
+
+static int
+mips_expect_download (char *string)
+{
+ if (!mips_expect (string))
+ {
+ fprintf_unfiltered (gdb_stderr, "Load did not complete successfully.\n");
+ if (tftp_in_use)
+ remove (tftp_localname); /* Remove temporary file */
+ return 0;
+ }
+ else
+ return 1;
+}
+
+static void
+pmon_end_download (final, bintotal)
+ int final;
+ int bintotal;
+{
+ char hexnumber[9]; /* includes '\0' space */
+
+ if (tftp_in_use)
+ {
+ static char *load_cmd_prefix = "load -b -s ";
+ char *cmd;
+ struct stat stbuf;
+
+ /* Close off the temporary file containing the load data. */
+ fclose (tftp_file);
+ tftp_file = NULL;
+
+ /* Make the temporary file readable by the world. */
+ if (stat (tftp_localname, &stbuf) == 0)
+ chmod (tftp_localname, stbuf.st_mode | S_IROTH);
+
+ /* Must reinitialize the board to prevent PMON from crashing. */
+ mips_send_command ("initEther\r", -1);
+
+ /* Send the load command. */
+ cmd = xmalloc (strlen (load_cmd_prefix) + strlen (tftp_name) + 2);
+ strcpy (cmd, load_cmd_prefix);
+ strcat (cmd, tftp_name);
+ strcat (cmd, "\r");
+ mips_send_command (cmd, 0);
+ free (cmd);
+ if (!mips_expect_download ("Downloading from "))
+ return;
+ if (!mips_expect_download (tftp_name))
+ return;
+ if (!mips_expect_download (", ^C to abort\r\n"))
+ return;
+ }
+
+ /* Wait for the stuff that PMON prints after the load has completed.
+ The timeout value for use in the tftp case (15 seconds) was picked
+ arbitrarily but might be too small for really large downloads. FIXME. */
+ if (mips_monitor == MON_LSI)
+ {
+ pmon_check_ack ("termination");
+ mips_expect_timeout ("Entry address is ", tftp_in_use ? 15 : 2);
+ }
+ else
+ mips_expect_timeout ("Entry Address = ", tftp_in_use ? 15 : 2);
+
+ sprintf (hexnumber,"%x",final);
+ mips_expect (hexnumber);
+ mips_expect ("\r\n");
+ if (mips_monitor != MON_LSI)
+ pmon_check_ack ("termination");
+ mips_expect ("\r\ntotal = 0x");
+ sprintf (hexnumber,"%x",bintotal);
+ mips_expect (hexnumber);
+ if (!mips_expect_download (" bytes\r\n"))
+ return;
+
+ if (tftp_in_use)
+ remove (tftp_localname); /* Remove temporary file */
+}
+
+static void
+pmon_download (buffer, length)
+ char *buffer;
+ int length;
+{
+ if (tftp_in_use)
+ fwrite (buffer, 1, length, tftp_file);
+ else
+ SERIAL_WRITE (udp_in_use ? udp_desc : mips_desc, buffer, length);
+}
+
+static void
+pmon_load_fast (file)
+ char *file;
+{
+ bfd *abfd;
+ asection *s;
+ unsigned char *binbuf;
+ char *buffer;
+ int reclen;
+ unsigned int csum = 0;
+ int hashmark = !tftp_in_use;
+ int bintotal = 0;
+ int final = 0;
+ int finished = 0;
+
+ buffer = (char *)xmalloc(MAXRECSIZE + 1);
+ binbuf = (unsigned char *)xmalloc(BINCHUNK);
+
+ abfd = bfd_openr(file,0);
+ if (!abfd)
+ {
+ printf_filtered ("Unable to open file %s\n",file);
+ return;
+ }
+
+ if (bfd_check_format(abfd,bfd_object) == 0)
+ {
+ printf_filtered("File is not an object file\n");
+ return;
+ }
+
+ /* Setup the required download state: */
+ mips_send_command ("set dlproto etxack\r", -1);
+ mips_send_command ("set dlecho off\r", -1);
+ /* NOTE: We get a "cannot set variable" message if the variable is
+ already defined to have the argument we give. The code doesn't
+ care, since it just scans to the next prompt anyway. */
+ /* Start the download: */
+ pmon_start_download();
+
+ /* Zero the checksum */
+ sprintf(buffer,"/Kxx\n");
+ reclen = strlen(buffer);
+ pmon_download (buffer, reclen);
+ finished = pmon_check_ack("/Kxx");
+
+ for (s = abfd->sections; s && !finished; s = s->next)
+ if (s->flags & SEC_LOAD) /* only deal with loadable sections */
+ {
+ bintotal += s->_raw_size;
+ final = (s->vma + s->_raw_size);
+
+ printf_filtered ("%s\t: 0x%4x .. 0x%4x ", s->name, (unsigned int)s->vma,
+ (unsigned int)(s->vma + s->_raw_size));
+ gdb_flush (gdb_stdout);
+
+ /* Output the starting address */
+ sprintf(buffer,"/A");
+ reclen = pmon_makeb64(s->vma,&buffer[2],36,&csum);
+ buffer[2 + reclen] = '\n';
+ buffer[3 + reclen] = '\0';
+ reclen += 3; /* for the initial escape code and carriage return */
+ pmon_download (buffer, reclen);
+ finished = pmon_check_ack("/A");
+
+ if (!finished)
+ {
+ unsigned int binamount;
+ unsigned int zerofill = 0;
+ char *bp = buffer;
+ unsigned int i;
+
+ reclen = 0;
+
+ for (i = 0; ((i < s->_raw_size) && !finished); i += binamount) {
+ int binptr = 0;
+
+ binamount = min (BINCHUNK, s->_raw_size - i);
+
+ bfd_get_section_contents (abfd, s, binbuf, i, binamount);
+
+ /* This keeps a rolling checksum, until we decide to output
+ the line: */
+ for (; ((binamount - binptr) > 0);) {
+ pmon_make_fastrec (&bp, binbuf, &binptr, binamount, &reclen, &csum, &zerofill);
+ if (reclen >= (MAXRECSIZE - CHECKSIZE)) {
+ reclen = pmon_checkset (reclen, &bp, &csum);
+ pmon_download (buffer, reclen);
+ finished = pmon_check_ack("data record");
+ if (finished) {
+ zerofill = 0; /* do not transmit pending zerofills */
+ break;
+ }
+
+ if (hashmark) {
+ putchar_unfiltered ('#');
+ gdb_flush (gdb_stdout);
+ }
+
+ bp = buffer;
+ reclen = 0; /* buffer processed */
+ }
+ }
+ }
+
+ /* Ensure no out-standing zerofill requests: */
+ if (zerofill != 0)
+ reclen = pmon_zeroset (reclen, &bp, &zerofill, &csum);
+
+ /* and then flush the line: */
+ if (reclen > 0) {
+ reclen = pmon_checkset (reclen, &bp, &csum);
+ /* Currently pmon_checkset outputs the line terminator by
+ default, so we write out the buffer so far: */
+ pmon_download (buffer, reclen);
+ finished = pmon_check_ack("record remnant");
+ }
+ }
+
+ putchar_unfiltered ('\n');
+ }
+
+ /* Terminate the transfer. We know that we have an empty output
+ buffer at this point. */
+ sprintf (buffer, "/E/E\n"); /* include dummy padding characters */
+ reclen = strlen (buffer);
+ pmon_download (buffer, reclen);
+
+ if (finished) { /* Ignore the termination message: */
+ SERIAL_FLUSH_INPUT (udp_in_use ? udp_desc : mips_desc);
+ } else { /* Deal with termination message: */
+ pmon_end_download (final, bintotal);
+ }
+
+ return;
+}
+
+/* mips_load -- download a file. */
+
+static void
+mips_load (file, from_tty)
+ char *file;
+ int from_tty;
+{
+ /* Get the board out of remote debugging mode. */
+ if (mips_exit_debug ())
+ error ("mips_load: Couldn't get into monitor mode.");
+
+ if (mips_monitor != MON_IDT)
+ pmon_load_fast (file);
+ else
+ mips_load_srec (file);
+
+ mips_initialize ();
+
+ /* Finally, make the PC point at the start address */
+ if (mips_monitor != MON_IDT)
+ {
+ /* Work around problem where PMON monitor updates the PC after a load
+ to a different value than GDB thinks it has. The following ensures
+ that the write_pc() WILL update the PC value: */
+ register_valid[PC_REGNUM] = 0;
+ }
+ if (exec_bfd)
+ write_pc (bfd_get_start_address (exec_bfd));
+
+ inferior_pid = 0; /* No process now */
+
+/* This is necessary because many things were based on the PC at the time that
+ we attached to the monitor, which is no longer valid now that we have loaded
+ new code (and just changed the PC). Another way to do this might be to call
+ normal_stop, except that the stack may not be valid, and things would get
+ horribly confused... */
+
+ clear_symtab_users ();
+}
+
+
+/* Pass the command argument as a packet to PMON verbatim. */
+
+static void
+pmon_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ char buf[DATA_MAXLEN + 1];
+ int rlen;
+
+ sprintf (buf, "0x0 %s", args);
+ mips_send_packet (buf, 1);
+ printf_filtered ("Send packet: %s\n", buf);
+
+ rlen = mips_receive_packet (buf, 1, mips_receive_wait);
+ buf[rlen] = '\0';
+ printf_filtered ("Received packet: %s\n", buf);
+}
+
+void
+_initialize_remote_mips ()
+{
+ /* Initialize the fields in mips_ops that are common to all four targets. */
+ mips_ops.to_longname = "Remote MIPS debugging over serial line";
+ mips_ops.to_close = mips_close;
+ mips_ops.to_detach = mips_detach;
+ mips_ops.to_resume = mips_resume;
+ mips_ops.to_fetch_registers = mips_fetch_registers;
+ mips_ops.to_store_registers = mips_store_registers;
+ mips_ops.to_prepare_to_store = mips_prepare_to_store;
+ mips_ops.to_xfer_memory = mips_xfer_memory;
+ mips_ops.to_files_info = mips_files_info;
+ mips_ops.to_insert_breakpoint = mips_insert_breakpoint;
+ mips_ops.to_remove_breakpoint = mips_remove_breakpoint;
+ mips_ops.to_kill = mips_kill;
+ mips_ops.to_load = mips_load;
+ mips_ops.to_create_inferior = mips_create_inferior;
+ mips_ops.to_mourn_inferior = mips_mourn_inferior;
+ mips_ops.to_stratum = process_stratum;
+ mips_ops.to_has_all_memory = 1;
+ mips_ops.to_has_memory = 1;
+ mips_ops.to_has_stack = 1;
+ mips_ops.to_has_registers = 1;
+ mips_ops.to_has_execution = 1;
+ mips_ops.to_magic = OPS_MAGIC;
+
+ /* Copy the common fields to all four target vectors. */
+ pmon_ops = ddb_ops = lsi_ops = mips_ops;
+
+ /* Initialize target-specific fields in the target vectors. */
+ mips_ops.to_shortname = "mips";
+ mips_ops.to_doc = "\
+Debug a board using the MIPS remote debugging protocol over a serial line.\n\
+The argument is the device it is connected to or, if it contains a colon,\n\
+HOST:PORT to access a board over a network";
+ mips_ops.to_open = mips_open;
+ mips_ops.to_wait = mips_wait;
+
+ pmon_ops.to_shortname = "pmon";
+ pmon_ops.to_doc = "\
+Debug a board using the PMON MIPS remote debugging protocol over a serial\n\
+line. The argument is the device it is connected to or, if it contains a\n\
+colon, HOST:PORT to access a board over a network";
+ pmon_ops.to_open = pmon_open;
+ pmon_ops.to_wait = mips_wait;
+
+ ddb_ops.to_shortname = "ddb";
+ ddb_ops.to_doc = "\
+Debug a board using the PMON MIPS remote debugging protocol over a serial\n\
+line. The first argument is the device it is connected to or, if it contains\n\
+a colon, HOST:PORT to access a board over a network. The optional second\n\
+parameter is the temporary file in the form HOST:FILENAME to be used for\n\
+TFTP downloads to the board. The optional third parameter is the local name\n\
+of the TFTP temporary file, if it differs from the filename seen by the board.";
+ ddb_ops.to_open = ddb_open;
+ ddb_ops.to_wait = mips_wait;
+
+ lsi_ops.to_shortname = "lsi";
+ lsi_ops.to_doc = pmon_ops.to_doc;
+ lsi_ops.to_open = lsi_open;
+ lsi_ops.to_wait = mips_wait;
+
+ /* Add the targets. */
+ add_target (&mips_ops);
+ add_target (&pmon_ops);
+ add_target (&ddb_ops);
+ add_target (&lsi_ops);
+
+ add_show_from_set (
+ add_set_cmd ("timeout", no_class, var_zinteger,
+ (char *) &mips_receive_wait,
+ "Set timeout in seconds for remote MIPS serial I/O.",
+ &setlist),
+ &showlist);
+
+ add_show_from_set (
+ add_set_cmd ("retransmit-timeout", no_class, var_zinteger,
+ (char *) &mips_retransmit_wait,
+ "Set retransmit timeout in seconds for remote MIPS serial I/O.\n\
+This is the number of seconds to wait for an acknowledgement to a packet\n\
+before resending the packet.", &setlist),
+ &showlist);
+
+ add_show_from_set (
+ add_set_cmd ("syn-garbage-limit", no_class, var_zinteger,
+ (char *) &mips_syn_garbage,
+"Set the maximum number of characters to ignore when scanning for a SYN.\n\
+This is the maximum number of characters GDB will ignore when trying to\n\
+synchronize with the remote system. A value of -1 means that there is no limit\n\
+(Note that these characters are printed out even though they are ignored.)",
+ &setlist),
+ &showlist);
+
+ add_show_from_set
+ (add_set_cmd ("monitor-prompt", class_obscure, var_string,
+ (char *) &mips_monitor_prompt,
+ "Set the prompt that GDB expects from the monitor.",
+ &setlist),
+ &showlist);
+
+ add_show_from_set (
+ add_set_cmd ("monitor-warnings", class_obscure, var_zinteger,
+ (char *)&monitor_warnings,
+ "Set printing of monitor warnings.\n"
+ "When enabled, monitor warnings about hardware breakpoints "
+ "will be displayed.",
+ &setlist),
+ &showlist);
+
+ add_com ("pmon <command>", class_obscure, pmon_command,
+ "Send a packet to PMON (must be in debug mode).");
+}
diff --git a/gdb/remote-mm.c b/gdb/remote-mm.c
new file mode 100644
index 00000000000..19455b4fc05
--- /dev/null
+++ b/gdb/remote-mm.c
@@ -0,0 +1,1673 @@
+/* Remote debugging interface for Am290*0 running MiniMON monitor, for GDB.
+ Copyright 1990, 1991, 1992 Free Software Foundation, Inc.
+ Originally written by Daniel Mann at AMD.
+
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* This is like remote.c but ecpects MiniMON to be running on the Am29000
+ target hardware.
+ - David Wood (wood@lab.ultra.nyu.edu) at New York University adapted this
+ file to gdb 3.95. I was unable to get this working on sun3os4
+ with termio, only with sgtty. Because we are only attempting to
+ use this module to debug our kernel, which is already loaded when
+ gdb is started up, I did not code up the file downloading facilities.
+ As a result this module has only the stubs to download files.
+ You should get tagged at compile time if you need to make any
+ changes/additions. */
+
+#include "defs.h"
+#include "inferior.h"
+#include "wait.h"
+#include "value.h"
+#include <ctype.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <errno.h>
+#include "gdb_string.h"
+#include "terminal.h"
+#include "minimon.h"
+#include "target.h"
+
+/* Offset of member MEMBER in a struct of type TYPE. */
+#define offsetof(TYPE, MEMBER) ((int) &((TYPE *)0)->MEMBER)
+
+#define DRAIN_INPUT() (msg_recv_serial((union msg_t*)0))
+
+extern int stop_soon_quietly; /* for wait_for_inferior */
+
+static void mm_resume();
+static void mm_fetch_registers ();
+static int fetch_register ();
+static void mm_store_registers ();
+static int store_register ();
+static int regnum_to_srnum();
+static void mm_close ();
+static char* msg_str();
+static char* error_msg_str();
+static int expect_msg();
+static void init_target_mm();
+static int mm_memory_space();
+
+#define FREEZE_MODE (read_register(CPS_REGNUM) && 0x400)
+#define USE_SHADOW_PC ((processor_type == a29k_freeze_mode) && FREEZE_MODE)
+
+/* FIXME: Replace with `set remotedebug'. */
+#define LLOG_FILE "minimon.log"
+#if defined (LOG_FILE)
+FILE *log_file;
+#endif
+
+/*
+ * Size of message buffers. I couldn't get memory reads to work when
+ * the byte_count was larger than 512 (it may be a baud rate problem).
+ */
+#define BUFER_SIZE 512
+/*
+ * Size of data area in message buffer on the TARGET (remote system).
+ */
+#define MAXDATA_T (target_config.max_msg_size - \
+ offsetof(struct write_r_msg_t,data[0]))
+/*
+ * Size of data area in message buffer on the HOST (gdb).
+ */
+#define MAXDATA_H (BUFER_SIZE - offsetof(struct write_r_msg_t,data[0]))
+/*
+ * Defined as the minimum size of data areas of the two message buffers
+ */
+#define MAXDATA (MAXDATA_H < MAXDATA_T ? MAXDATA_H : MAXDATA_T)
+
+static char out_buf[BUFER_SIZE];
+static char in_buf[BUFER_SIZE];
+
+int msg_recv_serial();
+int msg_send_serial();
+
+#define MAX_RETRIES 5000
+extern struct target_ops mm_ops; /* Forward declaration */
+struct config_msg_t target_config; /* HIF needs this */
+union msg_t *out_msg_buf = (union msg_t*)out_buf;
+union msg_t *in_msg_buf = (union msg_t*)in_buf;
+
+static int timeout = 5;
+
+/* Descriptor for I/O to remote machine. Initialize it to -1 so that
+ mm_open knows that we don't have a file open when the program
+ starts. */
+int mm_desc = -1;
+
+/* stream which is fdopen'd from mm_desc. Only valid when
+ mm_desc != -1. */
+FILE *mm_stream;
+
+/* Called when SIGALRM signal sent due to alarm() timeout. */
+#ifndef HAVE_TERMIO
+
+#ifndef __STDC__
+# ifndef volatile
+# define volatile /**/
+# endif
+#endif
+volatile int n_alarms;
+
+static void
+mm_timer ()
+{
+#if 0
+ if (kiodebug)
+ printf ("mm_timer called\n");
+#endif
+ n_alarms++;
+}
+#endif /* HAVE_TERMIO */
+
+/* malloc'd name of the program on the remote system. */
+static char *prog_name = NULL;
+
+
+/* Number of SIGTRAPs we need to simulate. That is, the next
+ NEED_ARTIFICIAL_TRAP calls to mm_wait should just return
+ SIGTRAP without actually waiting for anything. */
+
+/**************************************************** REMOTE_CREATE_INFERIOR */
+/* This is called not only when we first attach, but also when the
+ user types "run" after having attached. */
+static void
+mm_create_inferior (execfile, args, env)
+ char *execfile;
+ char *args;
+ char **env;
+{
+#define MAX_TOKENS 25
+#define BUFFER_SIZE 256
+ int token_count;
+ int result;
+ char *token[MAX_TOKENS];
+ char cmd_line[BUFFER_SIZE];
+
+ if (args && *args)
+ error ("Can't pass arguments to remote mm process (yet).");
+
+ if (execfile == 0 /* || exec_bfd == 0 */ )
+ error ("No executable file specified");
+
+ if (!mm_stream) {
+ printf("Minimon not open yet.\n");
+ return;
+ }
+
+ /* On ultra3 (NYU) we assume the kernel is already running so there is
+ no file to download.
+ FIXME: Fixed required here -> load your program, possibly with mm_load().
+ */
+ printf_filtered ("\n\
+Assuming you are at NYU debuging a kernel, i.e., no need to download.\n\n");
+
+ /* We will get a task spawn event immediately. */
+ init_wait_for_inferior ();
+ clear_proceed_status ();
+ stop_soon_quietly = 1;
+ proceed (-1, TARGET_SIGNAL_DEFAULT, 0);
+ normal_stop ();
+}
+/**************************************************** REMOTE_MOURN_INFERIOR */
+static void
+mm_mourn()
+{
+ pop_target (); /* Pop back to no-child state */
+ generic_mourn_inferior ();
+}
+
+/********************************************************************** damn_b
+*/
+/* Translate baud rates from integers to damn B_codes. Unix should
+ have outgrown this crap years ago, but even POSIX wouldn't buck it. */
+
+#ifndef B19200
+#define B19200 EXTA
+#endif
+#ifndef B38400
+#define B38400 EXTB
+#endif
+
+static struct {int rate, damn_b;} baudtab[] = {
+ {0, B0},
+ {50, B50},
+ {75, B75},
+ {110, B110},
+ {134, B134},
+ {150, B150},
+ {200, B200},
+ {300, B300},
+ {600, B600},
+ {1200, B1200},
+ {1800, B1800},
+ {2400, B2400},
+ {4800, B4800},
+ {9600, B9600},
+ {19200, B19200},
+ {38400, B38400},
+ {-1, -1},
+};
+
+static int damn_b (rate)
+ int rate;
+{
+ int i;
+
+ for (i = 0; baudtab[i].rate != -1; i++)
+ if (rate == baudtab[i].rate) return baudtab[i].damn_b;
+ return B38400; /* Random */
+}
+
+
+/***************************************************************** REMOTE_OPEN
+** Open a connection to remote minimon.
+ NAME is the filename used for communication, then a space,
+ then the baud rate.
+ 'target adapt /dev/ttya 9600 [prognam]' for example.
+ */
+
+static char *dev_name;
+int baudrate = 9600;
+static void
+mm_open (name, from_tty)
+ char *name;
+ int from_tty;
+{
+ TERMINAL sg;
+ unsigned int prl;
+ char *p;
+
+ /* Find the first whitespace character, it separates dev_name from
+ prog_name. */
+ for (p = name;
+ p && *p && !isspace (*p); p++)
+ ;
+ if (p == 0 || *p == '\0')
+erroid:
+ error ("Usage : <command> <serial-device> <baud-rate> [progname]");
+ dev_name = (char*)xmalloc (p - name + 1);
+ strncpy (dev_name, name, p - name);
+ dev_name[p - name] = '\0';
+
+ /* Skip over the whitespace after dev_name */
+ for (; isspace (*p); p++)
+ /*EMPTY*/;
+
+ if (1 != sscanf (p, "%d ", &baudrate))
+ goto erroid;
+
+ /* Skip the number and then the spaces */
+ for (; isdigit (*p); p++)
+ /*EMPTY*/;
+ for (; isspace (*p); p++)
+ /*EMPTY*/;
+
+ if (prog_name != NULL)
+ free (prog_name);
+ prog_name = savestring (p, strlen (p));
+
+
+ if (mm_desc >= 0)
+ close (mm_desc);
+
+ mm_desc = open (dev_name, O_RDWR);
+ if (mm_desc < 0)
+ perror_with_name (dev_name);
+ ioctl (mm_desc, TIOCGETP, &sg);
+#ifdef HAVE_TERMIO
+ sg.c_cc[VMIN] = 0; /* read with timeout. */
+ sg.c_cc[VTIME] = timeout * 10;
+ sg.c_lflag &= ~(ICANON | ECHO);
+ sg.c_cflag = (sg.c_cflag & ~CBAUD) | damn_b (baudrate);
+#else
+ sg.sg_ispeed = damn_b (baudrate);
+ sg.sg_ospeed = damn_b (baudrate);
+ sg.sg_flags |= RAW;
+ sg.sg_flags |= ANYP;
+ sg.sg_flags &= ~ECHO;
+#endif
+
+
+ ioctl (mm_desc, TIOCSETP, &sg);
+ mm_stream = fdopen (mm_desc, "r+");
+
+ push_target (&mm_ops);
+
+#ifndef HAVE_TERMIO
+#ifndef NO_SIGINTERRUPT
+ /* Cause SIGALRM's to make reads fail with EINTR instead of resuming
+ the read. */
+ if (siginterrupt (SIGALRM, 1) != 0)
+ perror ("mm_open: error in siginterrupt");
+#endif
+
+ /* Set up read timeout timer. */
+ if ((void (*)) signal (SIGALRM, mm_timer) == (void (*)) -1)
+ perror ("mm_open: error in signal");
+#endif
+
+#if defined (LOG_FILE)
+ log_file = fopen (LOG_FILE, "w");
+ if (log_file == NULL)
+ perror_with_name (LOG_FILE);
+#endif
+ /*
+ ** Initialize target configuration structure (global)
+ */
+ DRAIN_INPUT();
+ out_msg_buf->config_req_msg.code = CONFIG_REQ;
+ out_msg_buf->config_req_msg.length = 4*0;
+ msg_send_serial(out_msg_buf); /* send config request message */
+
+ expect_msg(CONFIG,in_msg_buf,1);
+
+ a29k_get_processor_type ();
+
+ /* Print out some stuff, letting the user now what's going on */
+ printf_filtered("Connected to MiniMon via %s.\n", dev_name);
+ /* FIXME: can this restriction be removed? */
+ printf_filtered("Remote debugging using virtual addresses works only\n");
+ printf_filtered("\twhen virtual addresses map 1:1 to physical addresses.\n")
+;
+ if (processor_type != a29k_freeze_mode) {
+ fprintf_filtered(gdb_stderr,
+ "Freeze-mode debugging not available, and can only be done on an A29050.\n");
+ }
+
+ target_config.code = CONFIG;
+ target_config.length = 0;
+ target_config.processor_id = in_msg_buf->config_msg.processor_id;
+ target_config.version = in_msg_buf->config_msg.version;
+ target_config.I_mem_start = in_msg_buf->config_msg.I_mem_start;
+ target_config.I_mem_size = in_msg_buf->config_msg.I_mem_size;
+ target_config.D_mem_start = in_msg_buf->config_msg.D_mem_start;
+ target_config.D_mem_size = in_msg_buf->config_msg.D_mem_size;
+ target_config.ROM_start = in_msg_buf->config_msg.ROM_start;
+ target_config.ROM_size = in_msg_buf->config_msg.ROM_size;
+ target_config.max_msg_size = in_msg_buf->config_msg.max_msg_size;
+ target_config.max_bkpts = in_msg_buf->config_msg.max_bkpts;
+ target_config.coprocessor = in_msg_buf->config_msg.coprocessor;
+ target_config.reserved = in_msg_buf->config_msg.reserved;
+ if (from_tty) {
+ printf("Connected to MiniMON :\n");
+ printf(" Debugcore version %d.%d\n",
+ 0x0f & (target_config.version >> 4),
+ 0x0f & (target_config.version ) );
+ printf(" Configuration version %d.%d\n",
+ 0x0f & (target_config.version >> 12),
+ 0x0f & (target_config.version >> 8) );
+ printf(" Message system version %d.%d\n",
+ 0x0f & (target_config.version >> 20),
+ 0x0f & (target_config.version >> 16) );
+ printf(" Communication driver version %d.%d\n",
+ 0x0f & (target_config.version >> 28),
+ 0x0f & (target_config.version >> 24) );
+ }
+
+ /* Leave the target running...
+ * The above message stopped the target in the dbg core (MiniMon),
+ * so restart the target out of MiniMon,
+ */
+ out_msg_buf->go_msg.code = GO;
+ out_msg_buf->go_msg.length = 0;
+ msg_send_serial(out_msg_buf);
+ /* No message to expect after a GO */
+}
+
+/**************************************************************** REMOTE_CLOSE
+** Close the open connection to the minimon debugger.
+ Use this when you want to detach and do something else
+ with your gdb. */
+static void
+mm_close (quitting) /*FIXME: how is quitting used */
+ int quitting;
+{
+ if (mm_desc < 0)
+ error ("Can't close remote connection: not debugging remotely.");
+
+ /* We should never get here if there isn't something valid in
+ mm_desc and mm_stream.
+
+ Due to a bug in Unix, fclose closes not only the stdio stream,
+ but also the file descriptor. So we don't actually close
+ mm_desc. */
+ DRAIN_INPUT();
+ fclose (mm_stream);
+ /* close (mm_desc); */
+
+ /* Do not try to close mm_desc again, later in the program. */
+ mm_stream = NULL;
+ mm_desc = -1;
+
+#if defined (LOG_FILE)
+ if (ferror (log_file))
+ printf ("Error writing log file.\n");
+ if (fclose (log_file) != 0)
+ printf ("Error closing log file.\n");
+#endif
+
+ printf ("Ending remote debugging\n");
+}
+
+/************************************************************* REMOTE_ATACH */
+/* Attach to a program that is already loaded and running
+ * Upon exiting the process's execution is stopped.
+ */
+static void
+mm_attach (args, from_tty)
+ char *args;
+ int from_tty;
+{
+
+ if (!mm_stream)
+ error ("MiniMon not opened yet, use the 'target minimon' command.\n");
+
+ if (from_tty)
+ printf ("Attaching to remote program %s...\n", prog_name);
+
+ /* Make sure the target is currently running, it is supposed to be. */
+ /* FIXME: is it ok to send MiniMon a BREAK if it is already stopped in
+ * the dbg core. If so, we don't need to send this GO.
+ */
+ out_msg_buf->go_msg.code = GO;
+ out_msg_buf->go_msg.length = 0;
+ msg_send_serial(out_msg_buf);
+ sleep(2); /* At the worst it will stop, receive a message, continue */
+
+ /* Send the mm a break. */
+ out_msg_buf->break_msg.code = BREAK;
+ out_msg_buf->break_msg.length = 0;
+ msg_send_serial(out_msg_buf);
+}
+/********************************************************** REMOTE_DETACH */
+/* Terminate the open connection to the remote debugger.
+ Use this when you want to detach and do something else
+ with your gdb. Leave remote process running (with no breakpoints set). */
+static void
+mm_detach (args,from_tty)
+ char *args;
+ int from_tty;
+{
+ remove_breakpoints(); /* Just in case there were any left in */
+ out_msg_buf->go_msg.code = GO;
+ out_msg_buf->go_msg.length = 0;
+ msg_send_serial(out_msg_buf);
+ pop_target(); /* calls mm_close to do the real work */
+}
+
+
+/*************************************************************** REMOTE_RESUME
+** Tell the remote machine to resume. */
+
+static void
+mm_resume (pid, step, sig)
+ int pid, step;
+ enum target_signal sig;
+{
+ if (sig != TARGET_SIGNAL_0)
+ warning ("Can't send signals to a remote MiniMon system.");
+
+ if (step) {
+ out_msg_buf->step_msg.code= STEP;
+ out_msg_buf->step_msg.length = 1*4;
+ out_msg_buf->step_msg.count = 1; /* step 1 instruction */
+ msg_send_serial(out_msg_buf);
+ } else {
+ out_msg_buf->go_msg.code= GO;
+ out_msg_buf->go_msg.length = 0;
+ msg_send_serial(out_msg_buf);
+ }
+}
+
+/***************************************************************** REMOTE_WAIT
+** Wait until the remote machine stops, then return,
+ storing status in STATUS just as `wait' would. */
+
+static int
+mm_wait (status)
+ struct target_waitstatus *status;
+{
+ int i, result;
+ int old_timeout = timeout;
+ int old_immediate_quit = immediate_quit;
+
+ status->kind = TARGET_WAITKIND_EXITED;
+ status->value.integer = 0;
+
+/* wait for message to arrive. It should be:
+ - A HIF service request.
+ - A HIF exit service request.
+ - A CHANNEL0_ACK.
+ - A CHANNEL1 request.
+ - a debugcore HALT message.
+ HIF services must be responded too, and while-looping continued.
+ If the target stops executing, mm_wait() should return.
+*/
+ timeout = 0; /* Wait indefinetly for a message */
+ immediate_quit = 1; /* Helps ability to QUIT */
+ while(1)
+ {
+ while(msg_recv_serial(in_msg_buf)) {
+ QUIT; /* Let user quit if they want */
+ }
+ switch (in_msg_buf->halt_msg.code)
+ {
+ case HIF_CALL:
+ i = in_msg_buf->hif_call_rtn_msg.service_number;
+ result=service_HIF(in_msg_buf);
+ if(i == 1) /* EXIT */
+ goto exit;
+ if(result)
+ printf("Warning: failure during HIF service %d\n", i);
+ break;
+ case CHANNEL0_ACK:
+ service_HIF(in_msg_buf);
+ break;
+ case CHANNEL1:
+ i=in_msg_buf->channel1_msg.length;
+ in_msg_buf->channel1_msg.data[i] = '\0';
+ printf("%s", in_msg_buf->channel1_msg.data);
+ gdb_flush(gdb_stdout);
+ /* Send CHANNEL1_ACK message */
+ out_msg_buf->channel1_ack_msg.code = CHANNEL1_ACK;
+ out_msg_buf->channel1_ack_msg.length = 0;
+ result = msg_send_serial(out_msg_buf);
+ break;
+ case HALT:
+ goto halted;
+ default:
+ goto halted;
+ }
+ }
+halted:
+ /* FIXME, these printfs should not be here. This is a source level
+ debugger, guys! */
+ if (in_msg_buf->halt_msg.trap_number== 0)
+ { printf("Am290*0 received vector number %d (break point)\n",
+ in_msg_buf->halt_msg.trap_number);
+ status->kind = TARGET_WAITKIND_STOPPED;
+ status->value.sig = TARGET_SIGNAL_TRAP;
+ }
+ else if (in_msg_buf->halt_msg.trap_number== 1)
+ {
+ printf("Am290*0 received vector number %d\n",
+ in_msg_buf->halt_msg.trap_number);
+ status->kind = TARGET_WAITKIND_STOPPED;
+ status->value.sig = TARGET_SIGNAL_BUS;
+ }
+ else if (in_msg_buf->halt_msg.trap_number== 3
+ || in_msg_buf->halt_msg.trap_number== 4)
+ { printf("Am290*0 received vector number %d\n",
+ in_msg_buf->halt_msg.trap_number);
+ status->kind = TARGET_WAITKIND_STOPPED;
+ status->value.sig = TARGET_SIGNAL_FPE;
+ }
+ else if (in_msg_buf->halt_msg.trap_number== 5)
+ { printf("Am290*0 received vector number %d\n",
+ in_msg_buf->halt_msg.trap_number);
+ status->kind = TARGET_WAITKIND_STOPPED;
+ status->value.sig = TARGET_SIGNAL_ILL;
+ }
+ else if (in_msg_buf->halt_msg.trap_number >= 6
+ && in_msg_buf->halt_msg.trap_number <= 11)
+ { printf("Am290*0 received vector number %d\n",
+ in_msg_buf->halt_msg.trap_number);
+ status->kind = TARGET_WAITKIND_STOPPED;
+ status->value.sig = TARGET_SIGNAL_SEGV;
+ }
+ else if (in_msg_buf->halt_msg.trap_number== 12
+ || in_msg_buf->halt_msg.trap_number== 13)
+ { printf("Am290*0 received vector number %d\n",
+ in_msg_buf->halt_msg.trap_number);
+ status->kind = TARGET_WAITKIND_STOPPED;
+ status->value.sig = TARGET_SIGNAL_ILL;
+ }
+ else if (in_msg_buf->halt_msg.trap_number== 14)
+ { printf("Am290*0 received vector number %d\n",
+ in_msg_buf->halt_msg.trap_number);
+ status->kind = TARGET_WAITKIND_STOPPED;
+ status->value.sig = TARGET_SIGNAL_ALRM;
+ }
+ else if (in_msg_buf->halt_msg.trap_number== 15)
+ {
+ status->kind = TARGET_WAITKIND_STOPPED;
+ status->value.sig = TARGET_SIGNAL_TRAP;
+ }
+ else if (in_msg_buf->halt_msg.trap_number >= 16
+ && in_msg_buf->halt_msg.trap_number <= 21)
+ { printf("Am290*0 received vector number %d\n",
+ in_msg_buf->halt_msg.trap_number);
+ status->kind = TARGET_WAITKIND_STOPPED;
+ status->value.sig = TARGET_SIGNAL_INT;
+ }
+ else if (in_msg_buf->halt_msg.trap_number== 22)
+ { printf("Am290*0 received vector number %d\n",
+ in_msg_buf->halt_msg.trap_number);
+ status->kind = TARGET_WAITKIND_STOPPED;
+ status->value.sig = TARGET_SIGNAL_ILL;
+ } /* BREAK message was sent */
+ else if (in_msg_buf->halt_msg.trap_number== 75)
+ {
+ status->kind = TARGET_WAITKIND_STOPPED;
+ status->value.sig = TARGET_SIGNAL_TRAP;
+ }
+ else
+exit:
+ {
+ status->kind = TARGET_WAITKIND_EXITED;
+ status->value.integer = 0;
+ }
+
+ timeout = old_timeout; /* Restore original timeout value */
+ immediate_quit = old_immediate_quit;
+ return 0;
+}
+
+/******************************************************* REMOTE_FETCH_REGISTERS
+ * Read a remote register 'regno'.
+ * If regno==-1 then read all the registers.
+ */
+static void
+mm_fetch_registers (regno)
+int regno;
+{
+ INT32 *data_p;
+
+ if (regno >= 0) {
+ fetch_register(regno);
+ return;
+ }
+
+/* Gr1/rsp */
+ out_msg_buf->read_req_msg.byte_count = 4*1;
+ out_msg_buf->read_req_msg.memory_space = GLOBAL_REG;
+ out_msg_buf->read_req_msg.address = 1;
+ msg_send_serial(out_msg_buf);
+ expect_msg(READ_ACK,in_msg_buf,1);
+ data_p = &(in_msg_buf->read_r_ack_msg.data[0]);
+ supply_register (GR1_REGNUM , data_p);
+
+#if defined(GR64_REGNUM) /* Read gr64-127 */
+/* Global Registers gr64-gr95 */
+ out_msg_buf->read_req_msg.code= READ_REQ;
+ out_msg_buf->read_req_msg.length = 4*3;
+ out_msg_buf->read_req_msg.byte_count = 4*32;
+ out_msg_buf->read_req_msg.memory_space = GLOBAL_REG;
+ out_msg_buf->read_req_msg.address = 64;
+ msg_send_serial(out_msg_buf);
+ expect_msg(READ_ACK,in_msg_buf,1);
+ data_p = &(in_msg_buf->read_r_ack_msg.data[0]);
+
+ for (regno=GR64_REGNUM; regno<GR64_REGNUM+32; regno++) {
+ supply_register (regno, data_p++);
+ }
+#endif /* GR64_REGNUM */
+
+/* Global Registers gr96-gr127 */
+ out_msg_buf->read_req_msg.code= READ_REQ;
+ out_msg_buf->read_req_msg.length = 4*3;
+ out_msg_buf->read_req_msg.byte_count = 4 * 32;
+ out_msg_buf->read_req_msg.memory_space = GLOBAL_REG;
+ out_msg_buf->read_req_msg.address = 96;
+ msg_send_serial(out_msg_buf);
+ expect_msg(READ_ACK,in_msg_buf,1);
+ data_p = &(in_msg_buf->read_r_ack_msg.data[0]);
+
+ for (regno=GR96_REGNUM; regno<GR96_REGNUM+32; regno++) {
+ supply_register (regno, data_p++);
+ }
+
+/* Local Registers */
+ out_msg_buf->read_req_msg.byte_count = 4 * (128);
+ out_msg_buf->read_req_msg.memory_space = LOCAL_REG;
+ out_msg_buf->read_req_msg.address = 0;
+ msg_send_serial(out_msg_buf);
+ expect_msg(READ_ACK,in_msg_buf,1);
+ data_p = &(in_msg_buf->read_r_ack_msg.data[0]);
+
+ for (regno=LR0_REGNUM; regno<LR0_REGNUM+128; regno++) {
+ supply_register (regno, data_p++);
+ }
+
+/* Protected Special Registers */
+ out_msg_buf->read_req_msg.byte_count = 4*15;
+ out_msg_buf->read_req_msg.memory_space = SPECIAL_REG;
+ out_msg_buf->read_req_msg.address = 0;
+ msg_send_serial( out_msg_buf);
+ expect_msg(READ_ACK,in_msg_buf,1);
+ data_p = &(in_msg_buf->read_r_ack_msg.data[0]);
+
+ for (regno=0; regno<=14; regno++) {
+ supply_register (SR_REGNUM(regno), data_p++);
+ }
+ if (USE_SHADOW_PC) { /* Let regno_to_srnum() handle the register number */
+ fetch_register(NPC_REGNUM);
+ fetch_register(PC_REGNUM);
+ fetch_register(PC2_REGNUM);
+ }
+
+/* Unprotected Special Registers */
+ out_msg_buf->read_req_msg.byte_count = 4*8;
+ out_msg_buf->read_req_msg.memory_space = SPECIAL_REG;
+ out_msg_buf->read_req_msg.address = 128;
+ msg_send_serial( out_msg_buf);
+ expect_msg(READ_ACK,in_msg_buf,1);
+ data_p = &(in_msg_buf->read_r_ack_msg.data[0]);
+
+ for (regno=128; regno<=135; regno++) {
+ supply_register (SR_REGNUM(regno), data_p++);
+ }
+
+ /* There doesn't seem to be any way to get these. */
+ {
+ int val = -1;
+ supply_register (FPE_REGNUM, &val);
+ supply_register (INTE_REGNUM, &val);
+ supply_register (FPS_REGNUM, &val);
+ supply_register (EXO_REGNUM, &val);
+ }
+}
+
+
+/****************************************************** REMOTE_STORE_REGISTERS
+ * Store register regno into the target.
+ * If regno==-1 then store all the registers.
+ * Result is 0 for success, -1 for failure.
+ */
+
+static void
+mm_store_registers (regno)
+int regno;
+{
+ int result;
+
+ if (regno >= 0) {
+ store_register(regno);
+ return;
+ }
+
+ result = 0;
+
+ out_msg_buf->write_r_msg.code= WRITE_REQ;
+
+/* Gr1/rsp */
+ out_msg_buf->write_r_msg.byte_count = 4*1;
+ out_msg_buf->write_r_msg.length = 3*4 + out_msg_buf->write_r_msg.byte_count;
+ out_msg_buf->write_r_msg.memory_space = GLOBAL_REG;
+ out_msg_buf->write_r_msg.address = 1;
+ out_msg_buf->write_r_msg.data[0] = read_register (GR1_REGNUM);
+
+ msg_send_serial( out_msg_buf);
+ if (!expect_msg(WRITE_ACK,in_msg_buf,1)) {
+ result = -1;
+ }
+
+#if defined(GR64_REGNUM)
+/* Global registers gr64-gr95 */
+ out_msg_buf->write_r_msg.byte_count = 4* (32);
+ out_msg_buf->write_r_msg.length = 3*4 + out_msg_buf->write_r_msg.byte_count;
+ out_msg_buf->write_r_msg.address = 64;
+
+ for (regno=GR64_REGNUM ; regno<GR64_REGNUM+32 ; regno++)
+ {
+ out_msg_buf->write_r_msg.data[regno-GR64_REGNUM] = read_register (regno);
+ }
+ msg_send_serial(out_msg_buf);
+ if (!expect_msg(WRITE_ACK,in_msg_buf,1)) {
+ result = -1;
+ }
+#endif /* GR64_REGNUM */
+
+/* Global registers gr96-gr127 */
+ out_msg_buf->write_r_msg.byte_count = 4* (32);
+ out_msg_buf->write_r_msg.length = 3*4 + out_msg_buf->write_r_msg.byte_count;
+ out_msg_buf->write_r_msg.address = 96;
+ for (regno=GR96_REGNUM ; regno<GR96_REGNUM+32 ; regno++)
+ {
+ out_msg_buf->write_r_msg.data[regno-GR96_REGNUM] = read_register (regno);
+ }
+ msg_send_serial( out_msg_buf);
+ if (!expect_msg(WRITE_ACK,in_msg_buf,1)) {
+ result = -1;
+ }
+
+/* Local Registers */
+ out_msg_buf->write_r_msg.memory_space = LOCAL_REG;
+ out_msg_buf->write_r_msg.byte_count = 4*128;
+ out_msg_buf->write_r_msg.length = 3*4 + out_msg_buf->write_r_msg.byte_count;
+ out_msg_buf->write_r_msg.address = 0;
+
+ for (regno = LR0_REGNUM ; regno < LR0_REGNUM+128 ; regno++)
+ {
+ out_msg_buf->write_r_msg.data[regno-LR0_REGNUM] = read_register (regno);
+ }
+ msg_send_serial( out_msg_buf);
+ if (!expect_msg(WRITE_ACK,in_msg_buf,1)) {
+ result = -1;
+ }
+
+/* Protected Special Registers */
+ /* VAB through TMR */
+ out_msg_buf->write_r_msg.memory_space = SPECIAL_REG;
+ out_msg_buf->write_r_msg.byte_count = 4* 10;
+ out_msg_buf->write_r_msg.length = 3*4 + out_msg_buf->write_r_msg.byte_count;
+ out_msg_buf->write_r_msg.address = 0;
+ for (regno = 0 ; regno<=9 ; regno++) /* VAB through TMR */
+ out_msg_buf->write_r_msg.data[regno] = read_register (SR_REGNUM(regno));
+ msg_send_serial( out_msg_buf);
+ if (!expect_msg(WRITE_ACK,in_msg_buf,1)) {
+ result = -1;
+ }
+
+ /* PC0, PC1, PC2 possibly as shadow registers */
+ out_msg_buf->write_r_msg.byte_count = 4* 3;
+ out_msg_buf->write_r_msg.length = 3*4 + out_msg_buf->write_r_msg.byte_count;
+ for (regno=10 ; regno<=12 ; regno++) /* LRU and MMU */
+ out_msg_buf->write_r_msg.data[regno-10] = read_register (SR_REGNUM(regno));
+ if (USE_SHADOW_PC)
+ out_msg_buf->write_r_msg.address = 20; /* SPC0 */
+ else
+ out_msg_buf->write_r_msg.address = 10; /* PC0 */
+ msg_send_serial( out_msg_buf);
+ if (!expect_msg(WRITE_ACK,in_msg_buf,1)) {
+ result = -1;
+ }
+
+ /* LRU and MMU */
+ out_msg_buf->write_r_msg.byte_count = 4* 2;
+ out_msg_buf->write_r_msg.length = 3*4 + out_msg_buf->write_r_msg.byte_count;
+ out_msg_buf->write_r_msg.address = 13;
+ for (regno=13 ; regno<=14 ; regno++) /* LRU and MMU */
+ out_msg_buf->write_r_msg.data[regno-13] = read_register (SR_REGNUM(regno));
+ msg_send_serial( out_msg_buf);
+ if (!expect_msg(WRITE_ACK,in_msg_buf,1)) {
+ result = -1;
+ }
+
+/* Unprotected Special Registers */
+ out_msg_buf->write_r_msg.byte_count = 4*8;
+ out_msg_buf->write_r_msg.length = 3*4 + out_msg_buf->write_r_msg.byte_count;
+ out_msg_buf->write_r_msg.address = 128;
+ for (regno = 128 ; regno<=135 ; regno++)
+ out_msg_buf->write_r_msg.data[regno-128] = read_register(SR_REGNUM(regno));
+ msg_send_serial( out_msg_buf);
+ if (!expect_msg(WRITE_ACK,in_msg_buf,1)) {
+ result = -1;
+ }
+
+ registers_changed ();
+}
+
+/*************************************************** REMOTE_PREPARE_TO_STORE */
+/* 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
+mm_prepare_to_store ()
+{
+ /* Do nothing, since we can store individual regs */
+}
+
+/******************************************************* REMOTE_XFER_MEMORY */
+static CORE_ADDR
+translate_addr(addr)
+CORE_ADDR addr;
+{
+#if defined(KERNEL_DEBUGGING)
+ /* Check for a virtual address in the kernel */
+ /* Assume physical address of ublock is in paddr_u register */
+ /* FIXME: doesn't work for user virtual addresses */
+ if (addr >= UVADDR) {
+ /* PADDR_U register holds the physical address of the ublock */
+ CORE_ADDR i = (CORE_ADDR)read_register(PADDR_U_REGNUM);
+ return(i + addr - (CORE_ADDR)UVADDR);
+ } else {
+ return(addr);
+ }
+#else
+ return(addr);
+#endif
+}
+
+/******************************************************* REMOTE_FILES_INFO */
+static void
+mm_files_info ()
+{
+ printf ("\tAttached to %s at %d baud and running program %s.\n",
+ dev_name, baudrate, prog_name);
+}
+
+/************************************************* REMOTE_INSERT_BREAKPOINT */
+static int
+mm_insert_breakpoint (addr, contents_cache)
+ CORE_ADDR addr;
+ char *contents_cache;
+{
+ out_msg_buf->bkpt_set_msg.code = BKPT_SET;
+ out_msg_buf->bkpt_set_msg.length = 4*4;
+ out_msg_buf->bkpt_set_msg.memory_space = I_MEM;
+ out_msg_buf->bkpt_set_msg.bkpt_addr = (ADDR32) addr;
+ out_msg_buf->bkpt_set_msg.pass_count = 1;
+ out_msg_buf->bkpt_set_msg.bkpt_type = -1; /* use illop for 29000 */
+ msg_send_serial( out_msg_buf);
+ if (expect_msg(BKPT_SET_ACK,in_msg_buf,1)) {
+ return 0; /* Success */
+ } else {
+ return 1; /* Failure */
+ }
+}
+
+/************************************************* REMOTE_DELETE_BREAKPOINT */
+static int
+mm_remove_breakpoint (addr, contents_cache)
+ CORE_ADDR addr;
+ char *contents_cache;
+{
+ out_msg_buf->bkpt_rm_msg.code = BKPT_RM;
+ out_msg_buf->bkpt_rm_msg.length = 4*3;
+ out_msg_buf->bkpt_rm_msg.memory_space = I_MEM;
+ out_msg_buf->bkpt_rm_msg.bkpt_addr = (ADDR32) addr;
+ msg_send_serial( out_msg_buf);
+ if (expect_msg(BKPT_RM_ACK,in_msg_buf,1)) {
+ return 0; /* Success */
+ } else {
+ return 1; /* Failure */
+ }
+}
+
+
+/******************************************************* REMOTE_KILL */
+static void
+mm_kill(arg,from_tty)
+char *arg;
+int from_tty;
+{
+ char buf[4];
+
+#if defined(KERNEL_DEBUGGING)
+ /* We don't ever kill the kernel */
+ if (from_tty) {
+ printf("Kernel not killed, but left in current state.\n");
+ printf("Use detach to leave kernel running.\n");
+ }
+#else
+ out_msg_buf->break_msg.code = BREAK;
+ out_msg_buf->bkpt_set_msg.length = 4*0;
+ expect_msg(HALT,in_msg_buf,from_tty);
+ if (from_tty) {
+ printf("Target has been stopped.");
+ printf("Would you like to do a hardware reset (y/n) [n] ");
+ fgets(buf,3,stdin);
+ if (buf[0] == 'y') {
+ out_msg_buf->reset_msg.code = RESET;
+ out_msg_buf->bkpt_set_msg.length = 4*0;
+ expect_msg(RESET_ACK,in_msg_buf,from_tty);
+ printf("Target has been reset.");
+ }
+ }
+ pop_target();
+#endif
+}
+
+
+
+/***************************************************************************/
+/*
+ * Load a program into the target.
+ */
+static void
+mm_load(arg_string,from_tty)
+char *arg_string;
+int from_tty;
+{
+ dont_repeat ();
+
+#if defined(KERNEL_DEBUGGING)
+ printf("The kernel had better be loaded already! Loading not done.\n");
+#else
+ if (arg_string == 0)
+ error ("The load command takes a file name");
+
+ arg_string = tilde_expand (arg_string);
+ make_cleanup (free, arg_string);
+ QUIT;
+ immediate_quit++;
+ error("File loading is not yet supported for MiniMon.");
+ /* FIXME, code to load your file here... */
+ /* You may need to do an init_target_mm() */
+ /* init_target_mm(?,?,?,?,?,?,?,?); */
+ immediate_quit--;
+ /* symbol_file_add (arg_string, from_tty, text_addr, 0, 0, 0, 0); */
+#endif
+
+}
+
+/************************************************ REMOTE_WRITE_INFERIOR_MEMORY
+** Copy LEN bytes of data from debugger memory at MYADDR
+ to inferior's memory at MEMADDR. Returns number of bytes written. */
+static int
+mm_write_inferior_memory (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+{
+ int i,nwritten;
+
+ out_msg_buf->write_req_msg.code= WRITE_REQ;
+ out_msg_buf->write_req_msg.memory_space = mm_memory_space(memaddr);
+
+ nwritten=0;
+ while (nwritten < len) {
+ int num_to_write = len - nwritten;
+ if (num_to_write > MAXDATA) num_to_write = MAXDATA;
+ for (i=0 ; i < num_to_write ; i++)
+ out_msg_buf->write_req_msg.data[i] = myaddr[i+nwritten];
+ out_msg_buf->write_req_msg.byte_count = num_to_write;
+ out_msg_buf->write_req_msg.length = 3*4 + num_to_write;
+ out_msg_buf->write_req_msg.address = memaddr + nwritten;
+ msg_send_serial(out_msg_buf);
+
+ if (expect_msg(WRITE_ACK,in_msg_buf,1)) {
+ nwritten += in_msg_buf->write_ack_msg.byte_count;
+ } else {
+ break;
+ }
+ }
+ return(nwritten);
+}
+
+/************************************************* REMOTE_READ_INFERIOR_MEMORY
+** Read LEN bytes from inferior memory at MEMADDR. Put the result
+ at debugger address MYADDR. Returns number of bytes read. */
+static int
+mm_read_inferior_memory(memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+{
+ int i,nread;
+
+ out_msg_buf->read_req_msg.code= READ_REQ;
+ out_msg_buf->read_req_msg.memory_space = mm_memory_space(memaddr);
+
+ nread=0;
+ while (nread < len) {
+ int num_to_read = (len - nread);
+ if (num_to_read > MAXDATA) num_to_read = MAXDATA;
+ out_msg_buf->read_req_msg.byte_count = num_to_read;
+ out_msg_buf->read_req_msg.length = 3*4 + num_to_read;
+ out_msg_buf->read_req_msg.address = memaddr + nread;
+ msg_send_serial(out_msg_buf);
+
+ if (expect_msg(READ_ACK,in_msg_buf,1)) {
+ for (i=0 ; i<in_msg_buf->read_ack_msg.byte_count ; i++)
+ myaddr[i+nread] = in_msg_buf->read_ack_msg.data[i];
+ nread += in_msg_buf->read_ack_msg.byte_count;
+ } else {
+ break;
+ }
+ }
+ return(nread);
+}
+
+/* FIXME! Merge these two. */
+static int
+mm_xfer_inferior_memory (memaddr, myaddr, len, write)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+ int write;
+{
+
+ memaddr = translate_addr(memaddr);
+
+ if (write)
+ return mm_write_inferior_memory (memaddr, myaddr, len);
+ else
+ return mm_read_inferior_memory (memaddr, myaddr, len);
+}
+
+
+/********************************************************** MSG_SEND_SERIAL
+** This function is used to send a message over the
+** serial line.
+**
+** If the message is successfully sent, a zero is
+** returned. If the message was not sendable, a -1
+** is returned. This function blocks. That is, it
+** does not return until the message is completely
+** sent, or until an error is encountered.
+**
+*/
+
+int
+msg_send_serial(msg_ptr)
+ union msg_t *msg_ptr;
+{
+ INT32 message_size;
+ int byte_count;
+ int result;
+ char c;
+
+ /* Send message header */
+ byte_count = 0;
+ message_size = msg_ptr->generic_msg.length + (2 * sizeof(INT32));
+ do {
+ c = *((char *)msg_ptr+byte_count);
+ result = write(mm_desc, &c, 1);
+ if (result == 1) {
+ byte_count = byte_count + 1;
+ }
+ } while ((byte_count < message_size) );
+
+ return(0);
+} /* end msg_send_serial() */
+
+/********************************************************** MSG_RECV_SERIAL
+** This function is used to receive a message over a
+** serial line.
+**
+** If the message is waiting in the buffer, a zero is
+** returned and the buffer pointed to by msg_ptr is filled
+** in. If no message was available, a -1 is returned.
+** If timeout==0, wait indefinetly for a character.
+**
+*/
+
+int
+msg_recv_serial(msg_ptr)
+union msg_t *msg_ptr;
+{
+ static INT32 length=0;
+ static INT32 byte_count=0;
+ int result;
+ char c;
+ if(msg_ptr == 0) /* re-sync request */
+ { length=0;
+ byte_count=0;
+#ifdef HAVE_TERMIO
+ /* The timeout here is the prevailing timeout set with VTIME */
+ ->"timeout==0 semantics not supported"
+ read(mm_desc, in_buf, BUFER_SIZE);
+#else
+ alarm (1);
+ read(mm_desc, in_buf, BUFER_SIZE);
+ alarm (0);
+#endif
+ return(0);
+ }
+ /* Receive message */
+#ifdef HAVE_TERMIO
+/* Timeout==0, help support the mm_wait() routine */
+ ->"timeout==0 semantics not supported (and its nice if they are)"
+ result = read(mm_desc, &c, 1);
+#else
+ alarm(timeout);
+ result = read(mm_desc, &c, 1);
+ alarm (0);
+#endif
+ if ( result < 0) {
+ if (errno == EINTR) {
+ error ("Timeout reading from remote system.");
+ } else
+ perror_with_name ("remote");
+ } else if (result == 1) {
+ *((char *)msg_ptr+byte_count) = c;
+ byte_count = byte_count + 1;
+ }
+
+ /* Message header received. Save message length. */
+ if (byte_count == (2 * sizeof(INT32)))
+ length = msg_ptr->generic_msg.length;
+
+ if (byte_count >= (length + (2 * sizeof(INT32)))) {
+ /* Message received */
+ byte_count = 0;
+ return(0);
+ } else
+ return (-1);
+
+} /* end msg_recv_serial() */
+
+/********************************************************************* KBD_RAW
+** This function is used to put the keyboard in "raw"
+** mode for BSD Unix. The original status is saved
+** so that it may be restored later.
+*/
+TERMINAL kbd_tbuf;
+
+int
+kbd_raw() {
+ int result;
+ TERMINAL tbuf;
+
+ /* Get keyboard termio (to save to restore original modes) */
+#ifdef HAVE_TERMIO
+ result = ioctl(0, TCGETA, &kbd_tbuf);
+#else
+ result = ioctl(0, TIOCGETP, &kbd_tbuf);
+#endif
+ if (result == -1)
+ return (errno);
+
+ /* Get keyboard TERMINAL (for modification) */
+#ifdef HAVE_TERMIO
+ result = ioctl(0, TCGETA, &tbuf);
+#else
+ result = ioctl(0, TIOCGETP, &tbuf);
+#endif
+ if (result == -1)
+ return (errno);
+
+ /* Set up new parameters */
+#ifdef HAVE_TERMIO
+ tbuf.c_iflag = tbuf.c_iflag &
+ ~(INLCR | ICRNL | IUCLC | ISTRIP | IXON | BRKINT);
+ tbuf.c_lflag = tbuf.c_lflag & ~(ICANON | ISIG | ECHO);
+ tbuf.c_cc[4] = 0; /* MIN */
+ tbuf.c_cc[5] = 0; /* TIME */
+#else
+ /* FIXME: not sure if this is correct (matches HAVE_TERMIO). */
+ tbuf.sg_flags |= RAW;
+ tbuf.sg_flags |= ANYP;
+ tbuf.sg_flags &= ~ECHO;
+#endif
+
+ /* Set keyboard termio to new mode (RAW) */
+#ifdef HAVE_TERMIO
+ result = ioctl(0, TCSETAF, &tbuf);
+#else
+ result = ioctl(0, TIOCSETP, &tbuf);
+#endif
+ if (result == -1)
+ return (errno);
+
+ return (0);
+} /* end kbd_raw() */
+
+
+
+/***************************************************************** KBD_RESTORE
+** This function is used to put the keyboard back in the
+** mode it was in before kbk_raw was called. Note that
+** kbk_raw() must have been called at least once before
+** kbd_restore() is called.
+*/
+
+int
+kbd_restore() {
+ int result;
+
+ /* Set keyboard termio to original mode */
+#ifdef HAVE_TERMIO
+ result = ioctl(0, TCSETAF, &kbd_tbuf);
+#else
+ result = ioctl(0, TIOCGETP, &kbd_tbuf);
+#endif
+
+ if (result == -1)
+ return (errno);
+
+ return(0);
+} /* end kbd_cooked() */
+
+
+/*****************************************************************************/
+/* Fetch a single register indicatated by 'regno'.
+ * Returns 0/-1 on success/failure.
+ */
+static int
+fetch_register (regno)
+ int regno;
+{
+ int result;
+ out_msg_buf->read_req_msg.code= READ_REQ;
+ out_msg_buf->read_req_msg.length = 4*3;
+ out_msg_buf->read_req_msg.byte_count = 4;
+
+ if (regno == GR1_REGNUM)
+ { out_msg_buf->read_req_msg.memory_space = GLOBAL_REG;
+ out_msg_buf->read_req_msg.address = 1;
+ }
+ else if (regno >= GR96_REGNUM && regno < GR96_REGNUM + 32)
+ { out_msg_buf->read_req_msg.memory_space = GLOBAL_REG;
+ out_msg_buf->read_req_msg.address = (regno - GR96_REGNUM) + 96;
+ }
+#if defined(GR64_REGNUM)
+ else if (regno >= GR64_REGNUM && regno < GR64_REGNUM + 32 )
+ { out_msg_buf->read_req_msg.memory_space = GLOBAL_REG;
+ out_msg_buf->read_req_msg.address = (regno - GR64_REGNUM) + 64;
+ }
+#endif /* GR64_REGNUM */
+ else if (regno >= LR0_REGNUM && regno < LR0_REGNUM + 128)
+ { out_msg_buf->read_req_msg.memory_space = LOCAL_REG;
+ out_msg_buf->read_req_msg.address = (regno - LR0_REGNUM);
+ }
+ else if (regno>=FPE_REGNUM && regno<=EXO_REGNUM)
+ { int val = -1;
+ supply_register(160 + (regno - FPE_REGNUM),&val);
+ return 0; /* Pretend Success */
+ }
+ else
+ { out_msg_buf->read_req_msg.memory_space = SPECIAL_REG;
+ out_msg_buf->read_req_msg.address = regnum_to_srnum(regno);
+ }
+
+ msg_send_serial(out_msg_buf);
+
+ if (expect_msg(READ_ACK,in_msg_buf,1)) {
+ supply_register (regno, &(in_msg_buf->read_r_ack_msg.data[0]));
+ result = 0;
+ } else {
+ result = -1;
+ }
+ return result;
+}
+/*****************************************************************************/
+/* Store a single register indicated by 'regno'.
+ * Returns 0/-1 on success/failure.
+ */
+static int
+store_register (regno)
+ int regno;
+{
+ int result;
+
+ out_msg_buf->write_req_msg.code= WRITE_REQ;
+ out_msg_buf->write_req_msg.length = 4*4;
+ out_msg_buf->write_req_msg.byte_count = 4;
+ out_msg_buf->write_r_msg.data[0] = read_register (regno);
+
+ if (regno == GR1_REGNUM)
+ { out_msg_buf->write_req_msg.memory_space = GLOBAL_REG;
+ out_msg_buf->write_req_msg.address = 1;
+ /* Setting GR1 changes the numbers of all the locals, so invalidate the
+ * register cache. Do this *after* calling read_register, because we want
+ * read_register to return the value that write_register has just stuffed
+ * into the registers array, not the value of the register fetched from
+ * the inferior.
+ */
+ registers_changed ();
+ }
+#if defined(GR64_REGNUM)
+ else if (regno >= GR64_REGNUM && regno < GR64_REGNUM + 32 )
+ { out_msg_buf->write_req_msg.memory_space = GLOBAL_REG;
+ out_msg_buf->write_req_msg.address = (regno - GR64_REGNUM) + 64;
+ }
+#endif /* GR64_REGNUM */
+ else if (regno >= GR96_REGNUM && regno < GR96_REGNUM + 32)
+ { out_msg_buf->write_req_msg.memory_space = GLOBAL_REG;
+ out_msg_buf->write_req_msg.address = (regno - GR96_REGNUM) + 96;
+ }
+ else if (regno >= LR0_REGNUM && regno < LR0_REGNUM + 128)
+ { out_msg_buf->write_req_msg.memory_space = LOCAL_REG;
+ out_msg_buf->write_req_msg.address = (regno - LR0_REGNUM);
+ }
+ else if (regno>=FPE_REGNUM && regno<=EXO_REGNUM)
+ {
+ return 0; /* Pretend Success */
+ }
+ else /* An unprotected or protected special register */
+ { out_msg_buf->write_req_msg.memory_space = SPECIAL_REG;
+ out_msg_buf->write_req_msg.address = regnum_to_srnum(regno);
+ }
+
+ msg_send_serial(out_msg_buf);
+
+ if (expect_msg(WRITE_ACK,in_msg_buf,1)) {
+ result = 0;
+ } else {
+ result = -1;
+ }
+ return result;
+}
+/****************************************************************************/
+/*
+ * Convert a gdb special register number to a 29000 special register number.
+ */
+static int
+regnum_to_srnum(regno)
+int regno;
+{
+ switch(regno) {
+ case VAB_REGNUM: return(0);
+ case OPS_REGNUM: return(1);
+ case CPS_REGNUM: return(2);
+ case CFG_REGNUM: return(3);
+ case CHA_REGNUM: return(4);
+ case CHD_REGNUM: return(5);
+ case CHC_REGNUM: return(6);
+ case RBP_REGNUM: return(7);
+ case TMC_REGNUM: return(8);
+ case TMR_REGNUM: return(9);
+ case NPC_REGNUM: return(USE_SHADOW_PC ? (20) : (10));
+ case PC_REGNUM: return(USE_SHADOW_PC ? (21) : (11));
+ case PC2_REGNUM: return(USE_SHADOW_PC ? (22) : (12));
+ case MMU_REGNUM: return(13);
+ case LRU_REGNUM: return(14);
+ case IPC_REGNUM: return(128);
+ case IPA_REGNUM: return(129);
+ case IPB_REGNUM: return(130);
+ case Q_REGNUM: return(131);
+ case ALU_REGNUM: return(132);
+ case BP_REGNUM: return(133);
+ case FC_REGNUM: return(134);
+ case CR_REGNUM: return(135);
+ case FPE_REGNUM: return(160);
+ case INTE_REGNUM: return(161);
+ case FPS_REGNUM: return(162);
+ case EXO_REGNUM:return(164);
+ default:
+ return(255); /* Failure ? */
+ }
+}
+/****************************************************************************/
+/*
+ * Initialize the target debugger (minimon only).
+ */
+static void
+init_target_mm(tstart,tend,dstart,dend,entry,ms_size,rs_size,arg_start)
+ADDR32 tstart,tend,dstart,dend,entry;
+INT32 ms_size,rs_size;
+ADDR32 arg_start;
+{
+ out_msg_buf->init_msg.code = INIT;
+ out_msg_buf->init_msg.length= sizeof(struct init_msg_t)-2*sizeof(INT32);
+ out_msg_buf->init_msg.text_start = tstart;
+ out_msg_buf->init_msg.text_end = tend;
+ out_msg_buf->init_msg.data_start = dstart;
+ out_msg_buf->init_msg.data_end = dend;
+ out_msg_buf->init_msg.entry_point = entry;
+ out_msg_buf->init_msg.mem_stack_size = ms_size;
+ out_msg_buf->init_msg.reg_stack_size = rs_size;
+ out_msg_buf->init_msg.arg_start = arg_start;
+ msg_send_serial(out_msg_buf);
+ expect_msg(INIT_ACK,in_msg_buf,1);
+}
+/****************************************************************************/
+/*
+ * Return a pointer to a string representing the given message code.
+ * Not all messages are represented here, only the ones that we expect
+ * to be called with.
+ */
+static char*
+msg_str(code)
+INT32 code;
+{
+ static char cbuf[32];
+
+ switch (code) {
+ case BKPT_SET_ACK: sprintf(cbuf,"%s (%d)","BKPT_SET_ACK",code); break;
+ case BKPT_RM_ACK: sprintf(cbuf,"%s (%d)","BKPT_RM_ACK",code); break;
+ case INIT_ACK: sprintf(cbuf,"%s (%d)","INIT_ACK",code); break;
+ case READ_ACK: sprintf(cbuf,"%s (%d)","READ_ACK",code); break;
+ case WRITE_ACK: sprintf(cbuf,"%s (%d)","WRITE_ACK",code); break;
+ case ERROR: sprintf(cbuf,"%s (%d)","ERROR",code); break;
+ case HALT: sprintf(cbuf,"%s (%d)","HALT",code); break;
+ default: sprintf(cbuf,"UNKNOWN (%d)",code); break;
+ }
+ return(cbuf);
+}
+/****************************************************************************/
+/*
+ * Selected (not all of them) error codes that we might get.
+ */
+static char*
+error_msg_str(code)
+INT32 code;
+{
+ static char cbuf[50];
+
+ switch (code) {
+ case EMFAIL: return("EMFAIL: unrecoverable error");
+ case EMBADADDR: return("EMBADADDR: Illegal address");
+ case EMBADREG: return("EMBADREG: Illegal register ");
+ case EMACCESS: return("EMACCESS: Could not access memory");
+ case EMBADMSG: return("EMBADMSG: Unknown message type");
+ case EMMSG2BIG: return("EMMSG2BIG: Message to large");
+ case EMNOSEND: return("EMNOSEND: Could not send message");
+ case EMNORECV: return("EMNORECV: Could not recv message");
+ case EMRESET: return("EMRESET: Could not RESET target");
+ case EMCONFIG: return("EMCONFIG: Could not get target CONFIG");
+ case EMSTATUS: return("EMSTATUS: Could not get target STATUS");
+ case EMREAD: return("EMREAD: Could not READ target memory");
+ case EMWRITE: return("EMWRITE: Could not WRITE target memory");
+ case EMBKPTSET: return("EMBKPTSET: Could not set breakpoint");
+ case EMBKPTRM: return("EMBKPTRM: Could not remove breakpoint");
+ case EMBKPTSTAT:return("EMBKPTSTAT: Could not get breakpoint status");
+ case EMBKPTNONE:return("EMBKPTNONE: All breakpoints in use");
+ case EMBKPTUSED:return("EMBKPTUSED: Breakpoints already in use");
+ case EMINIT: return("EMINIT: Could not init target memory");
+ case EMGO: return("EMGO: Could not start execution");
+ case EMSTEP: return("EMSTEP: Could not single step");
+ case EMBREAK: return("EMBREAK: Could not BREAK");
+ case EMCOMMERR: return("EMCOMMERR: Communication error");
+ default: sprintf(cbuf,"error number %d",code); break;
+ } /* end switch */
+
+ return (cbuf);
+}
+/****************************************************************************/
+/*
+ * Receive a message and expect it to be of type msgcode.
+ * Returns 0/1 on failure/success.
+ */
+static int
+expect_msg(msgcode,msg_buf,from_tty)
+INT32 msgcode; /* Msg code we expect */
+union msg_t *msg_buf; /* Where to put the message received */
+int from_tty; /* Print message on error if non-zero */
+{
+ int retries=0;
+ while(msg_recv_serial(msg_buf) && (retries++<MAX_RETRIES));
+ if (retries >= MAX_RETRIES) {
+ printf("Expected msg %s, ",msg_str(msgcode));
+ printf("no message received!\n");
+ return(0); /* Failure */
+ }
+
+ if (msg_buf->generic_msg.code != msgcode) {
+ if (from_tty) {
+ printf("Expected msg %s, ",msg_str(msgcode));
+ printf("got msg %s\n",msg_str(msg_buf->generic_msg.code));
+ if (msg_buf->generic_msg.code == ERROR)
+ printf("%s\n",error_msg_str(msg_buf->error_msg.error_code));
+ }
+ return(0); /* Failure */
+ }
+ return(1); /* Success */
+}
+/****************************************************************************/
+/*
+ * Determine the MiniMon memory space qualifier based on the addr.
+ * FIXME: Can't distinguis I_ROM/D_ROM.
+ * FIXME: Doesn't know anything about I_CACHE/D_CACHE.
+ */
+static int
+mm_memory_space(addr)
+CORE_ADDR *addr;
+{
+ ADDR32 tstart = target_config.I_mem_start;
+ ADDR32 tend = tstart + target_config.I_mem_size;
+ ADDR32 dstart = target_config.D_mem_start;
+ ADDR32 dend = tstart + target_config.D_mem_size;
+ ADDR32 rstart = target_config.ROM_start;
+ ADDR32 rend = tstart + target_config.ROM_size;
+
+ if (((ADDR32)addr >= tstart) && ((ADDR32)addr < tend)) {
+ return I_MEM;
+ } else if (((ADDR32)addr >= dstart) && ((ADDR32)addr < dend)) {
+ return D_MEM;
+ } else if (((ADDR32)addr >= rstart) && ((ADDR32)addr < rend)) {
+ /* FIXME: how do we determine between D_ROM and I_ROM */
+ return D_ROM;
+ } else /* FIXME: what do me do now? */
+ return D_MEM; /* Hmmm! */
+}
+
+/****************************************************************************/
+/*
+ * Define the target subroutine names
+ */
+struct target_ops mm_ops ;
+
+static void
+init_mm_ops(void)
+{
+ mm_ops.to_shortname = "minimon";
+ mm_ops.to_longname = "Remote AMD/Minimon target";
+ mm_ops.to_doc = "Remote debug an AMD 290*0 using the MiniMon dbg core on the target";
+ mm_ops.to_open = mm_open;
+ mm_ops.to_close = mm_close;
+ mm_ops.to_attach = mm_attach;
+ mm_ops.to_post_attach = NULL;
+ mm_ops.to_require_attach = NULL;
+ mm_ops.to_detach = mm_detach;
+ mm_ops.to_require_detach = NULL;
+ mm_ops.to_resume = mm_resume;
+ mm_ops.to_wait = mm_wait;
+ mm_ops.to_post_wait = NULL;
+ mm_ops.to_fetch_registers = mm_fetch_registers;
+ mm_ops.to_store_registers = mm_store_registers;
+ mm_ops.to_prepare_to_store = mm_prepare_to_store;
+ mm_ops.to_xfer_memory = mm_xfer_inferior_memory;
+ mm_ops.to_files_info = mm_files_info;
+ mm_ops.to_insert_breakpoint = mm_insert_breakpoint;
+ mm_ops.to_remove_breakpoint = mm_remove_breakpoint;
+ mm_ops.to_terminal_init = 0;
+ mm_ops.to_terminal_inferior = 0;
+ mm_ops.to_terminal_ours_for_output = 0;
+ mm_ops.to_terminal_ours = 0;
+ mm_ops.to_terminal_info = 0;
+ mm_ops.to_kill = mm_kill;
+ mm_ops.to_load = mm_load;
+ mm_ops.to_lookup_symbol = 0;
+ mm_ops.to_create_inferior = mm_create_inferior;
+ mm_ops.to_post_startup_inferior = NULL;
+ mm_ops.to_acknowledge_created_inferior = NULL;
+ mm_ops.to_clone_and_follow_inferior = NULL;
+ mm_ops.to_post_follow_inferior_by_clone = NULL;
+ mm_ops.to_insert_fork_catchpoint = NULL;
+ mm_ops.to_remove_fork_catchpoint = NULL;
+ mm_ops.to_insert_vfork_catchpoint = NULL;
+ mm_ops.to_remove_vfork_catchpoint = NULL;
+ mm_ops.to_has_forked = NULL;
+ mm_ops.to_has_vforked = NULL;
+ mm_ops.to_can_follow_vfork_prior_to_exec = NULL;
+ mm_ops.to_post_follow_vfork = NULL;
+ mm_ops.to_insert_exec_catchpoint = NULL;
+ mm_ops.to_remove_exec_catchpoint = NULL;
+ mm_ops.to_has_execd = NULL;
+ mm_ops.to_reported_exec_events_per_exec_call = NULL;
+ mm_ops.to_has_exited = NULL;
+ mm_ops.to_mourn_inferior = mm_mourn;
+ mm_ops.to_can_run = 0;
+ mm_ops.to_notice_signals = 0;
+ mm_ops.to_thread_alive = 0;
+ mm_ops.to_stop = 0;
+ mm_ops.to_pid_to_exec_file = NULL;
+ mm_ops.to_core_file_to_sym_file = NULL;
+ mm_ops.to_stratum = process_stratum;
+ mm_ops.DONT_USE = 0;
+ mm_ops.to_has_all_memory = 1;
+ mm_ops.to_has_memory = 1;
+ mm_ops.to_has_stack = 1;
+ mm_ops.to_has_registers = 1;
+ mm_ops.to_has_execution = 1;
+ mm_ops.to_sections = 0;
+ mm_ops.to_sections_end = 0;
+ mm_ops.to_magic = OPS_MAGIC;
+};
+
+void
+_initialize_remote_mm()
+{
+ init_mm_ops() ;
+ add_target (&mm_ops);
+}
+
+#ifdef NO_HIF_SUPPORT
+service_HIF(msg)
+union msg_t *msg;
+{
+ return(0); /* Emulate a failure */
+}
+#endif
diff --git a/gdb/remote-nindy.c b/gdb/remote-nindy.c
new file mode 100644
index 00000000000..58e89b86859
--- /dev/null
+++ b/gdb/remote-nindy.c
@@ -0,0 +1,852 @@
+/* Memory-access and commands for remote NINDY process, for GDB.
+ Copyright 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
+ Contributed by Intel Corporation. Modified from remote.c by Chris Benenati.
+
+GDB is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY. No author or distributor accepts responsibility to anyone
+for the consequences of using it or for whether it serves any
+particular purpose or works at all, unless he says so in writing.
+Refer to the GDB General Public License for full details.
+
+Everyone is granted permission to copy, modify and redistribute GDB,
+but only under the conditions described in the GDB General Public
+License. A copy of this license is supposed to have been given to you
+along with GDB so you can know your rights and responsibilities. It
+should be in a file named COPYING. Among other things, the copyright
+notice and this notice must be preserved on all copies.
+
+In other words, go ahead and share GDB, but don't try to stop
+anyone else from sharing it farther. Help stamp out software hoarding!
+*/
+
+/*
+Except for the data cache routines, this file bears little resemblence
+to remote.c. A new (although similar) protocol has been specified, and
+portions of the code are entirely dependent on having an i80960 with a
+NINDY ROM monitor at the other end of the line.
+*/
+
+/*****************************************************************************
+ *
+ * REMOTE COMMUNICATION PROTOCOL BETWEEN GDB960 AND THE NINDY ROM MONITOR.
+ *
+ *
+ * MODES OF OPERATION
+ * ----- -- ---------
+ *
+ * As far as NINDY is concerned, GDB is always in one of two modes: command
+ * mode or passthrough mode.
+ *
+ * In command mode (the default) pre-defined packets containing requests
+ * are sent by GDB to NINDY. NINDY never talks except in reponse to a request.
+ *
+ * Once the the user program is started, GDB enters passthrough mode, to give
+ * the user program access to the terminal. GDB remains in this mode until
+ * NINDY indicates that the program has stopped.
+ *
+ *
+ * PASSTHROUGH MODE
+ * ----------- ----
+ *
+ * GDB writes all input received from the keyboard directly to NINDY, and writes
+ * all characters received from NINDY directly to the monitor.
+ *
+ * Keyboard input is neither buffered nor echoed to the monitor.
+ *
+ * GDB remains in passthrough mode until NINDY sends a single ^P character,
+ * to indicate that the user process has stopped.
+ *
+ * Note:
+ * GDB assumes NINDY performs a 'flushreg' when the user program stops.
+ *
+ *
+ * COMMAND MODE
+ * ------- ----
+ *
+ * All info (except for message ack and nak) is transferred between gdb
+ * and the remote processor in messages of the following format:
+ *
+ * <info>#<checksum>
+ *
+ * where
+ * # is a literal character
+ *
+ * <info> ASCII information; all numeric information is in the
+ * form of hex digits ('0'-'9' and lowercase 'a'-'f').
+ *
+ * <checksum>
+ * is a pair of ASCII hex digits representing an 8-bit
+ * checksum formed by adding together each of the
+ * characters in <info>.
+ *
+ * The receiver of a message always sends a single character to the sender
+ * to indicate that the checksum was good ('+') or bad ('-'); the sender
+ * re-transmits the entire message over until a '+' is received.
+ *
+ * In response to a command NINDY always sends back either data or
+ * a result code of the form "Xnn", where "nn" are hex digits and "X00"
+ * means no errors. (Exceptions: the "s" and "c" commands don't respond.)
+ *
+ * SEE THE HEADER OF THE FILE "gdb.c" IN THE NINDY MONITOR SOURCE CODE FOR A
+ * FULL DESCRIPTION OF LEGAL COMMANDS.
+ *
+ * SEE THE FILE "stop.h" IN THE NINDY MONITOR SOURCE CODE FOR A LIST
+ * OF STOP CODES.
+ *
+ ***************************************************************************/
+
+#include "defs.h"
+#include <signal.h>
+#include <sys/types.h>
+#include <setjmp.h>
+
+#include "frame.h"
+#include "inferior.h"
+#include "bfd.h"
+#include "symfile.h"
+#include "target.h"
+#include "gdbcore.h"
+#include "command.h"
+#include "floatformat.h"
+
+#include "wait.h"
+#include <sys/file.h>
+#include <ctype.h>
+#include "serial.h"
+#include "nindy-share/env.h"
+#include "nindy-share/stop.h"
+
+#include "dcache.h"
+#include "remote-utils.h"
+
+static DCACHE *nindy_dcache;
+
+extern int unlink();
+extern char *getenv();
+extern char *mktemp();
+
+extern void generic_mourn_inferior ();
+
+extern struct target_ops nindy_ops;
+extern FILE *instream;
+
+extern char ninStopWhy ();
+extern int ninMemGet ();
+extern int ninMemPut ();
+
+int nindy_initial_brk; /* nonzero if want to send an initial BREAK to nindy */
+int nindy_old_protocol; /* nonzero if want to use old protocol */
+char *nindy_ttyname; /* name of tty to talk to nindy on, or null */
+
+#define DLE '\020' /* Character NINDY sends to indicate user program has
+ * halted. */
+#define TRUE 1
+#define FALSE 0
+
+/* From nindy-share/nindy.c. */
+extern serial_t nindy_serial;
+
+static int have_regs = 0; /* 1 iff regs read since i960 last halted */
+static int regs_changed = 0; /* 1 iff regs were modified since last read */
+
+extern char *exists();
+
+static void
+nindy_fetch_registers PARAMS ((int));
+
+static void
+nindy_store_registers PARAMS ((int));
+
+static char *savename;
+
+static void
+nindy_close (quitting)
+ int quitting;
+{
+ if (nindy_serial != NULL)
+ SERIAL_CLOSE (nindy_serial);
+ nindy_serial = NULL;
+
+ if (savename)
+ free (savename);
+ savename = 0;
+}
+
+/* Open a connection to a remote debugger.
+ FIXME, there should be "set" commands for the options that are
+ now specified with gdb command-line options (old_protocol,
+ and initial_brk). */
+void
+nindy_open (name, from_tty)
+ char *name; /* "/dev/ttyXX", "ttyXX", or "XX": tty to be opened */
+ int from_tty;
+{
+ char baudrate[1024];
+
+ if (!name)
+ error_no_arg ("serial port device name");
+
+ target_preopen (from_tty);
+
+ nindy_close (0);
+
+ have_regs = regs_changed = 0;
+ nindy_dcache = dcache_init(ninMemGet, ninMemPut);
+
+ /* Allow user to interrupt the following -- we could hang if there's
+ no NINDY at the other end of the remote tty. */
+ immediate_quit++;
+ /* If baud_rate is -1, then ninConnect will not recognize the baud rate
+ and will deal with the situation in a (more or less) reasonable
+ fashion. */
+ sprintf(baudrate, "%d", baud_rate);
+ ninConnect(name, baudrate,
+ nindy_initial_brk, !from_tty, nindy_old_protocol);
+ immediate_quit--;
+
+ if (nindy_serial == NULL)
+ {
+ perror_with_name (name);
+ }
+
+ savename = savestring (name, strlen (name));
+ push_target (&nindy_ops);
+
+ target_fetch_registers(-1);
+
+ init_thread_list ();
+ init_wait_for_inferior ();
+ clear_proceed_status ();
+ normal_stop ();
+}
+
+/* User-initiated quit of nindy operations. */
+
+static void
+nindy_detach (name, from_tty)
+ char *name;
+ int from_tty;
+{
+ if (name)
+ error ("Too many arguments");
+ pop_target ();
+}
+
+static void
+nindy_files_info ()
+{
+ /* FIXME: this lies about the baud rate if we autobauded. */
+ printf_unfiltered("\tAttached to %s at %d bits per second%s%s.\n", savename,
+ baud_rate,
+ nindy_old_protocol? " in old protocol": "",
+ nindy_initial_brk? " with initial break": "");
+}
+
+/* Return the number of characters in the buffer before
+ the first DLE character. */
+
+static
+int
+non_dle( buf, n )
+ char *buf; /* Character buffer; NOT '\0'-terminated */
+ int n; /* Number of characters in buffer */
+{
+ int i;
+
+ for ( i = 0; i < n; i++ ){
+ if ( buf[i] == DLE ){
+ break;
+ }
+ }
+ return i;
+}
+
+/* Tell the remote machine to resume. */
+
+void
+nindy_resume (pid, step, siggnal)
+ int pid, step;
+ enum target_signal siggnal;
+{
+ if (siggnal != TARGET_SIGNAL_0 && siggnal != stop_signal)
+ warning ("Can't send signals to remote NINDY targets.");
+
+ dcache_flush(nindy_dcache);
+ if ( regs_changed )
+ {
+ nindy_store_registers (-1);
+ regs_changed = 0;
+ }
+ have_regs = 0;
+ ninGo( step );
+}
+
+/* FIXME, we can probably use the normal terminal_inferior stuff here.
+ We have to do terminal_inferior and then set up the passthrough
+ settings initially. Thereafter, terminal_ours and terminal_inferior
+ will automatically swap the settings around for us. */
+
+struct clean_up_tty_args {
+ serial_ttystate state;
+ serial_t serial;
+};
+static struct clean_up_tty_args tty_args;
+
+static void
+clean_up_tty (ptrarg)
+ PTR ptrarg;
+{
+ struct clean_up_tty_args *args = (struct clean_up_tty_args *) ptrarg;
+ SERIAL_SET_TTY_STATE (args->serial, args->state);
+ free (args->state);
+ warning ("\n\nYou may need to reset the 80960 and/or reload your program.\n");
+}
+
+/* Recover from ^Z or ^C while remote process is running */
+static void (*old_ctrlc)();
+#ifdef SIGTSTP
+static void (*old_ctrlz)();
+#endif
+
+static void
+clean_up_int()
+{
+ SERIAL_SET_TTY_STATE (tty_args.serial, tty_args.state);
+ free (tty_args.state);
+
+ signal(SIGINT, old_ctrlc);
+#ifdef SIGTSTP
+ signal(SIGTSTP, old_ctrlz);
+#endif
+ error("\n\nYou may need to reset the 80960 and/or reload your program.\n");
+}
+
+/* Wait until the remote machine stops. While waiting, operate in passthrough
+ * mode; i.e., pass everything NINDY sends to gdb_stdout, and everything from
+ * stdin to NINDY.
+ *
+ * Return to caller, storing status in 'status' just as `wait' would.
+ */
+
+static int
+nindy_wait( pid, status )
+ int pid;
+ struct target_waitstatus *status;
+{
+ fd_set fds;
+ int c;
+ char buf[2];
+ int i, n;
+ unsigned char stop_exit;
+ unsigned char stop_code;
+ struct cleanup *old_cleanups;
+ long ip_value, fp_value, sp_value; /* Reg values from stop */
+
+ status->kind = TARGET_WAITKIND_EXITED;
+ status->value.integer = 0;
+
+ /* OPERATE IN PASSTHROUGH MODE UNTIL NINDY SENDS A DLE CHARACTER */
+
+ /* Save current tty attributes, and restore them when done. */
+ tty_args.serial = SERIAL_FDOPEN (0);
+ tty_args.state = SERIAL_GET_TTY_STATE (tty_args.serial);
+ old_ctrlc = signal( SIGINT, clean_up_int );
+#ifdef SIGTSTP
+ old_ctrlz = signal( SIGTSTP, clean_up_int );
+#endif
+
+ old_cleanups = make_cleanup (clean_up_tty, &tty_args);
+
+ /* Pass input from keyboard to NINDY as it arrives. NINDY will interpret
+ <CR> and perform echo. */
+ /* This used to set CBREAK and clear ECHO and CRMOD. I hope this is close
+ enough. */
+ SERIAL_RAW (tty_args.serial);
+
+ while (1)
+ {
+ /* Input on remote */
+ c = SERIAL_READCHAR (nindy_serial, -1);
+ if (c == SERIAL_ERROR)
+ {
+ error ("Cannot read from serial line");
+ }
+ else if (c == 0x1b) /* ESC */
+ {
+ c = SERIAL_READCHAR (nindy_serial, -1);
+ c &= ~0x40;
+ }
+ else if (c != 0x10) /* DLE */
+ /* Write out any characters preceding DLE */
+ {
+ buf[0] = (char)c;
+ write (1, buf, 1);
+ }
+ else
+ {
+ stop_exit = ninStopWhy(&stop_code,
+ &ip_value, &fp_value, &sp_value);
+ if (!stop_exit && (stop_code == STOP_SRQ))
+ {
+ immediate_quit++;
+ ninSrq();
+ immediate_quit--;
+ }
+ else
+ {
+ /* Get out of loop */
+ supply_register (IP_REGNUM,
+ (char *)&ip_value);
+ supply_register (FP_REGNUM,
+ (char *)&fp_value);
+ supply_register (SP_REGNUM,
+ (char *)&sp_value);
+ break;
+ }
+ }
+ }
+
+ SERIAL_SET_TTY_STATE (tty_args.serial, tty_args.state);
+ free (tty_args.state);
+ discard_cleanups (old_cleanups);
+
+ if (stop_exit)
+ {
+ status->kind = TARGET_WAITKIND_EXITED;
+ status->value.integer = stop_code;
+ }
+ else
+ {
+ /* nindy has some special stop code need to be handled */
+ if (stop_code == STOP_GDB_BPT)
+ stop_code = TRACE_STEP;
+ status->kind = TARGET_WAITKIND_STOPPED;
+ status->value.sig = i960_fault_to_signal (stop_code);
+ }
+ return inferior_pid;
+}
+
+/* Read the remote registers into the block REGS. */
+
+/* This is the block that ninRegsGet and ninRegsPut handles. */
+struct nindy_regs {
+ char local_regs[16 * 4];
+ char global_regs[16 * 4];
+ char pcw_acw[2 * 4];
+ char ip[4];
+ char tcw[4];
+ char fp_as_double[4 * 8];
+};
+
+static void
+nindy_fetch_registers(regno)
+ int regno;
+{
+ struct nindy_regs nindy_regs;
+ int regnum;
+
+ immediate_quit++;
+ ninRegsGet( (char *) &nindy_regs );
+ immediate_quit--;
+
+ memcpy (&registers[REGISTER_BYTE (R0_REGNUM)], nindy_regs.local_regs, 16*4);
+ memcpy (&registers[REGISTER_BYTE (G0_REGNUM)], nindy_regs.global_regs, 16*4);
+ memcpy (&registers[REGISTER_BYTE (PCW_REGNUM)], nindy_regs.pcw_acw, 2*4);
+ memcpy (&registers[REGISTER_BYTE (IP_REGNUM)], nindy_regs.ip, 1*4);
+ memcpy (&registers[REGISTER_BYTE (TCW_REGNUM)], nindy_regs.tcw, 1*4);
+ memcpy (&registers[REGISTER_BYTE (FP0_REGNUM)], nindy_regs.fp_as_double, 4 * 8);
+
+ registers_fetched ();
+}
+
+static void
+nindy_prepare_to_store()
+{
+ /* Fetch all regs if they aren't already here. */
+ read_register_bytes (0, NULL, REGISTER_BYTES);
+}
+
+static void
+nindy_store_registers(regno)
+ int regno;
+{
+ struct nindy_regs nindy_regs;
+ int regnum;
+
+ memcpy (nindy_regs.local_regs, &registers[REGISTER_BYTE (R0_REGNUM)], 16*4);
+ memcpy (nindy_regs.global_regs, &registers[REGISTER_BYTE (G0_REGNUM)], 16*4);
+ memcpy (nindy_regs.pcw_acw, &registers[REGISTER_BYTE (PCW_REGNUM)], 2*4);
+ memcpy (nindy_regs.ip, &registers[REGISTER_BYTE (IP_REGNUM)], 1*4);
+ memcpy (nindy_regs.tcw, &registers[REGISTER_BYTE (TCW_REGNUM)], 1*4);
+ memcpy (nindy_regs.fp_as_double, &registers[REGISTER_BYTE (FP0_REGNUM)], 8*4);
+
+ immediate_quit++;
+ ninRegsPut( (char *) &nindy_regs );
+ immediate_quit--;
+}
+
+/* Read a word from remote address ADDR and return it.
+ * This goes through the data cache.
+ */
+int
+nindy_fetch_word (addr)
+ CORE_ADDR addr;
+{
+ return dcache_fetch (nindy_dcache, addr);
+}
+
+/* Write a word WORD into remote address ADDR.
+ This goes through the data cache. */
+
+void
+nindy_store_word (addr, word)
+ CORE_ADDR addr;
+ int word;
+{
+ dcache_poke (nindy_dcache, addr, word);
+}
+
+/* Copy LEN bytes to or from inferior's memory starting at MEMADDR
+ to debugger memory starting at MYADDR. Copy to inferior if
+ WRITE is nonzero. Returns the length copied.
+
+ This is stolen almost directly from infptrace.c's child_xfer_memory,
+ which also deals with a word-oriented memory interface. Sometime,
+ FIXME, rewrite this to not use the word-oriented routines. */
+
+int
+nindy_xfer_inferior_memory(memaddr, myaddr, len, should_write, target)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+ int should_write;
+ struct target_ops *target; /* ignored */
+{
+ register int i;
+ /* Round starting address down to longword boundary. */
+ register CORE_ADDR addr = memaddr & - sizeof (int);
+ /* Round ending address up; get number of longwords that makes. */
+ register int count
+ = (((memaddr + len) - addr) + sizeof (int) - 1) / sizeof (int);
+ /* Allocate buffer of that many longwords. */
+ register int *buffer = (int *) alloca (count * sizeof (int));
+
+ if (should_write)
+ {
+ /* Fill start and end extra bytes of buffer with existing memory data. */
+
+ if (addr != memaddr || len < (int)sizeof (int)) {
+ /* Need part of initial word -- fetch it. */
+ buffer[0] = nindy_fetch_word (addr);
+ }
+
+ if (count > 1) /* FIXME, avoid if even boundary */
+ {
+ buffer[count - 1]
+ = nindy_fetch_word (addr + (count - 1) * sizeof (int));
+ }
+
+ /* Copy data to be written over corresponding part of buffer */
+
+ memcpy ((char *) buffer + (memaddr & (sizeof (int) - 1)), myaddr, len);
+
+ /* Write the entire buffer. */
+
+ for (i = 0; i < count; i++, addr += sizeof (int))
+ {
+ errno = 0;
+ nindy_store_word (addr, buffer[i]);
+ if (errno)
+ return 0;
+ }
+ }
+ else
+ {
+ /* Read all the longwords */
+ for (i = 0; i < count; i++, addr += sizeof (int))
+ {
+ errno = 0;
+ buffer[i] = nindy_fetch_word (addr);
+ if (errno)
+ return 0;
+ QUIT;
+ }
+
+ /* Copy appropriate bytes out of the buffer. */
+ memcpy (myaddr, (char *) buffer + (memaddr & (sizeof (int) - 1)), len);
+ }
+ return len;
+}
+
+static void
+nindy_create_inferior (execfile, args, env)
+ char *execfile;
+ char *args;
+ char **env;
+{
+ int entry_pt;
+ int pid;
+
+ if (args && *args)
+ error ("Can't pass arguments to remote NINDY process");
+
+ if (execfile == 0 || exec_bfd == 0)
+ error ("No executable file specified");
+
+ entry_pt = (int) bfd_get_start_address (exec_bfd);
+
+ pid = 42;
+
+ /* The "process" (board) is already stopped awaiting our commands, and
+ the program is already downloaded. We just set its PC and go. */
+
+ inferior_pid = pid; /* Needed for wait_for_inferior below */
+
+ clear_proceed_status ();
+
+ /* Tell wait_for_inferior that we've started a new process. */
+ init_wait_for_inferior ();
+
+ /* Set up the "saved terminal modes" of the inferior
+ based on what modes we are starting it with. */
+ target_terminal_init ();
+
+ /* Install inferior's terminal modes. */
+ target_terminal_inferior ();
+
+ /* insert_step_breakpoint (); FIXME, do we need this? */
+ /* Let 'er rip... */
+ proceed ((CORE_ADDR)entry_pt, TARGET_SIGNAL_DEFAULT, 0);
+}
+
+static void
+reset_command(args, from_tty)
+ char *args;
+ int from_tty;
+{
+ if (nindy_serial == NULL)
+ {
+ error( "No target system to reset -- use 'target nindy' command.");
+ }
+ if ( query("Really reset the target system?",0,0) )
+ {
+ SERIAL_SEND_BREAK (nindy_serial);
+ tty_flush (nindy_serial);
+ }
+}
+
+void
+nindy_kill (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ return; /* Ignore attempts to kill target system */
+}
+
+/* Clean up when a program exits.
+
+ The program actually lives on in the remote processor's RAM, and may be
+ run again without a download. Don't leave it full of breakpoint
+ instructions. */
+
+void
+nindy_mourn_inferior ()
+{
+ remove_breakpoints ();
+ unpush_target (&nindy_ops);
+ generic_mourn_inferior (); /* Do all the proper things now */
+}
+
+/* Pass the args the way catch_errors wants them. */
+static int
+nindy_open_stub (arg)
+ char *arg;
+{
+ nindy_open (arg, 1);
+ return 1;
+}
+
+static void
+nindy_load( filename, from_tty )
+ char *filename;
+ int from_tty;
+{
+ asection *s;
+ /* Can't do unix style forking on a VMS system, so we'll use bfd to do
+ all the work for us
+ */
+
+ bfd *file = bfd_openr(filename,0);
+ if (!file)
+ {
+ perror_with_name(filename);
+ return;
+ }
+
+ if (!bfd_check_format(file, bfd_object))
+ {
+ error("can't prove it's an object file\n");
+ return;
+ }
+
+ for ( s = file->sections; s; s=s->next)
+ {
+ if (s->flags & SEC_LOAD)
+ {
+ char *buffer = xmalloc(s->_raw_size);
+ bfd_get_section_contents(file, s, buffer, 0, s->_raw_size);
+ printf("Loading section %s, size %x vma %x\n",
+ s->name,
+ s->_raw_size,
+ s->vma);
+ ninMemPut(s->vma, buffer, s->_raw_size);
+ free(buffer);
+ }
+ }
+ bfd_close(file);
+}
+
+static int
+load_stub (arg)
+ char *arg;
+{
+ target_load (arg, 1);
+ return 1;
+}
+
+/* This routine is run as a hook, just before the main command loop is
+ entered. If gdb is configured for the i960, but has not had its
+ nindy target specified yet, this will loop prompting the user to do so.
+
+ Unlike the loop provided by Intel, we actually let the user get out
+ of this with a RETURN. This is useful when e.g. simply examining
+ an i960 object file on the host system. */
+
+void
+nindy_before_main_loop ()
+{
+ char ttyname[100];
+ char *p, *p2;
+
+ while (target_stack->target_ops != &nindy_ops) /* What is this crap??? */
+ { /* remote tty not specified yet */
+ if ( instream == stdin ){
+ printf_unfiltered("\nAttach /dev/ttyNN -- specify NN, or \"quit\" to quit: ");
+ gdb_flush( gdb_stdout );
+ }
+ fgets( ttyname, sizeof(ttyname)-1, stdin );
+
+ /* Strip leading and trailing whitespace */
+ for ( p = ttyname; isspace(*p); p++ ){
+ ;
+ }
+ if ( *p == '\0' ){
+ return; /* User just hit spaces or return, wants out */
+ }
+ for ( p2= p; !isspace(*p2) && (*p2 != '\0'); p2++ ){
+ ;
+ }
+ *p2= '\0';
+ if ( STREQ("quit",p) ){
+ exit(1);
+ }
+
+ if (catch_errors (nindy_open_stub, p, "", RETURN_MASK_ALL))
+ {
+ /* Now that we have a tty open for talking to the remote machine,
+ download the executable file if one was specified. */
+ if (exec_bfd)
+ {
+ catch_errors (load_stub, bfd_get_filename (exec_bfd), "",
+ RETURN_MASK_ALL);
+ }
+ }
+ }
+}
+
+/* Define the target subroutine names */
+
+struct target_ops nindy_ops ;
+
+static void
+init_nindy_ops(void)
+{
+ nindy_ops.to_shortname = "nindy"; "Remote serial target in i960 NINDY-specific protocol",
+ nindy_ops.to_longname = "Use a remote i960 system running NINDY connected by a serial line.\n\
+Specify the name of the device the serial line is connected to.\n\
+The speed (baud rate), whether to use the old NINDY protocol,\n\
+and whether to send a break on startup, are controlled by options\n\
+specified when you started GDB." ;
+ nindy_ops.to_doc = "";
+ nindy_ops.to_open = nindy_open;
+ nindy_ops.to_close = nindy_close;
+ nindy_ops.to_attach = 0;
+ nindy_ops.to_post_attach = NULL;
+ nindy_ops.to_require_attach = NULL;
+ nindy_ops.to_detach = nindy_detach;
+ nindy_ops.to_require_detach = NULL;
+ nindy_ops.to_resume = nindy_resume;
+ nindy_ops.to_wait = nindy_wait;
+ nindy_ops.to_post_wait = NULL;
+ nindy_ops.to_fetch_registers = nindy_fetch_registers;
+ nindy_ops.to_store_registers = nindy_store_registers;
+ nindy_ops.to_prepare_to_store = nindy_prepare_to_store;
+ nindy_ops.to_xfer_memory = nindy_xfer_inferior_memory;
+ nindy_ops.to_files_info = nindy_files_info;
+ nindy_ops.to_insert_breakpoint = memory_insert_breakpoint;
+ nindy_ops.to_remove_breakpoint = memory_remove_breakpoint;
+ nindy_ops.to_terminal_init = 0;
+ nindy_ops.to_terminal_inferior = 0;
+ nindy_ops.to_terminal_ours_for_output = 0;
+ nindy_ops.to_terminal_ours = 0;
+ nindy_ops.to_terminal_info = 0; /* Terminal crud */
+ nindy_ops.to_kill = nindy_kill;
+ nindy_ops.to_load = nindy_load;
+ nindy_ops.to_lookup_symbol = 0; /* lookup_symbol */
+ nindy_ops.to_create_inferior = nindy_create_inferior;
+ nindy_ops.to_post_startup_inferior = NULL;
+ nindy_ops.to_acknowledge_created_inferior = NULL;
+ nindy_ops.to_clone_and_follow_inferior = NULL;
+ nindy_ops.to_post_follow_inferior_by_clone = NULL;
+ nindy_ops.to_insert_fork_catchpoint = NULL;
+ nindy_ops.to_remove_fork_catchpoint = NULL;
+ nindy_ops.to_insert_vfork_catchpoint = NULL;
+ nindy_ops.to_remove_vfork_catchpoint = NULL;
+ nindy_ops.to_has_forked = NULL;
+ nindy_ops.to_has_vforked = NULL;
+ nindy_ops.to_can_follow_vfork_prior_to_exec = NULL;
+ nindy_ops.to_post_follow_vfork = NULL;
+ nindy_ops.to_insert_exec_catchpoint = NULL;
+ nindy_ops.to_remove_exec_catchpoint = NULL;
+ nindy_ops.to_has_execd = NULL;
+ nindy_ops.to_reported_exec_events_per_exec_call = NULL;
+ nindy_ops.to_has_exited = NULL;
+ nindy_ops.to_mourn_inferior = nindy_mourn_inferior;
+ nindy_ops.to_can_run = 0; /* can_run */
+ nindy_ops.to_notice_signals = 0; /* notice_signals */
+ nindy_ops.to_thread_alive = 0; /* to_thread_alive */
+ nindy_ops.to_stop = 0; /* to_stop */
+ nindy_ops.to_pid_to_exec_file = NULL;
+ nindy_ops.to_core_file_to_sym_file = NULL;
+ nindy_ops.to_stratum = process_stratum;
+ nindy_ops.DONT_USE = 0; /* next */
+ nindy_ops.to_has_all_memory = 1;
+ nindy_ops.to_has_memory = 1;
+ nindy_ops.to_has_stack = 1;
+ nindy_ops.to_has_registers = 1;
+ nindy_ops.to_has_execution = 1; /* all mem, mem, stack, regs, exec */
+ nindy_ops.to_sections = 0;
+ nindy_ops.to_sections_end = 0; /* Section pointers */
+ nindy_ops.to_magic = OPS_MAGIC; /* Always the last thing */
+}
+
+void
+_initialize_nindy ()
+{
+ init_nindy_ops() ;
+ add_target (&nindy_ops);
+ add_com ("reset", class_obscure, reset_command,
+ "Send a 'break' to the remote target system.\n\
+Only useful if the target has been equipped with a circuit\n\
+to perform a hard reset when a break is detected.");
+}
diff --git a/gdb/remote-nrom.c b/gdb/remote-nrom.c
new file mode 100644
index 00000000000..4999a68b8e0
--- /dev/null
+++ b/gdb/remote-nrom.c
@@ -0,0 +1,360 @@
+/* Remote debugging with the XLNT Designs, Inc (XDI) NetROM.
+ Copyright 1990, 1991, 1992, 1995 Free Software Foundation, Inc.
+ Contributed by:
+ Roger Moyers
+ XLNT Designs, Inc.
+ 15050 Avenue of Science, Suite 106
+ San Diego, CA 92128
+ (619)487-9320
+ roger@xlnt.com
+ Adapted from work done at Cygnus Support in remote-nindy.c,
+ later merged in by Stan Shebs at Cygnus.
+
+This file is part of GDB.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "gdbcmd.h"
+#include "serial.h"
+#include "target.h"
+
+/* Default ports used to talk with the NetROM. */
+
+#define DEFAULT_NETROM_LOAD_PORT 1236
+#define DEFAULT_NETROM_CONTROL_PORT 1237
+
+static void nrom_close PARAMS ((int quitting));
+
+/* New commands. */
+
+static void nrom_passthru PARAMS ((char *, int));
+
+/* We talk to the NetROM over these sockets. */
+
+static serial_t load_desc = NULL;
+static serial_t ctrl_desc = NULL;
+
+static int load_port = DEFAULT_NETROM_LOAD_PORT;
+static int control_port = DEFAULT_NETROM_CONTROL_PORT;
+
+static char nrom_hostname[100];
+
+/* Forward data declaration. */
+
+extern struct target_ops nrom_ops;
+
+/* Scan input from the remote system, until STRING is found. Print chars that
+ don't match. */
+
+static int
+expect (string)
+ char *string;
+{
+ char *p = string;
+ int c;
+
+ immediate_quit = 1;
+
+ while (1)
+ {
+ c = SERIAL_READCHAR (ctrl_desc, 5);
+
+ if (c == *p++)
+ {
+ if (*p == '\0')
+ {
+ immediate_quit = 0;
+
+ return 0;
+ }
+ }
+ else
+ {
+ fputc_unfiltered (c, gdb_stdout);
+ p = string;
+ if (c == *p)
+ p++;
+ }
+ }
+}
+
+static void
+nrom_kill ()
+{
+ nrom_close (0);
+}
+
+static serial_t
+open_socket (name, port)
+ char *name;
+ int port;
+{
+ char sockname[100];
+ serial_t desc;
+
+ sprintf (sockname, "%s:%d", name, port);
+ desc = SERIAL_OPEN (sockname);
+ if (!desc)
+ perror_with_name (sockname);
+
+ return desc;
+}
+
+static void
+load_cleanup ()
+{
+ SERIAL_CLOSE (load_desc);
+ load_desc = NULL;
+}
+
+/* Download a file specified in ARGS to the netROM. */
+
+static void
+nrom_load (args, fromtty)
+ char *args;
+ int fromtty;
+{
+ int fd, rd_amt, fsize;
+ bfd *pbfd;
+ asection *section;
+ char *downloadstring = "download 0\n";
+ struct cleanup *old_chain;
+
+ /* Tell the netrom to get ready to download. */
+ if (SERIAL_WRITE (ctrl_desc, downloadstring, strlen (downloadstring)))
+ error ("nrom_load: control_send() of `%s' failed", downloadstring);
+
+ expect ("Waiting for a connection...\n");
+
+ load_desc = open_socket (nrom_hostname, load_port);
+
+ old_chain = make_cleanup (load_cleanup, 0);
+
+ pbfd = bfd_openr (args, 0);
+
+ if (pbfd)
+ {
+ make_cleanup (bfd_close, pbfd);
+
+ if (!bfd_check_format (pbfd, bfd_object))
+ error ("\"%s\": not in executable format: %s",
+ args, bfd_errmsg (bfd_get_error ()));
+
+ for (section = pbfd->sections; section; section = section->next)
+ {
+ if (bfd_get_section_flags (pbfd, section) & SEC_ALLOC)
+ {
+ bfd_vma section_address;
+ unsigned long section_size;
+ const char *section_name;
+
+ section_name = bfd_get_section_name (pbfd, section);
+ section_address = bfd_get_section_vma (pbfd, section);
+ section_size = bfd_section_size (pbfd, section);
+
+ if (bfd_get_section_flags (pbfd, section) & SEC_LOAD)
+ {
+ file_ptr fptr;
+
+ printf_filtered ("[Loading section %s at %x (%d bytes)]\n",
+ section_name, section_address,
+ section_size);
+
+ fptr = 0;
+
+ while (section_size > 0)
+ {
+ char buffer[1024];
+ int count;
+
+ count = min (section_size, 1024);
+
+ bfd_get_section_contents (pbfd, section, buffer, fptr,
+ count);
+
+ SERIAL_WRITE (load_desc, buffer, count);
+ section_address += count;
+ fptr += count;
+ section_size -= count;
+ }
+ }
+ else /* BSS and such */
+ {
+ printf_filtered ("[section %s: not loading]\n",
+ section_name);
+ }
+ }
+ }
+ }
+ else
+ error ("\"%s\": Could not open", args);
+
+ do_cleanups (old_chain);
+}
+
+/* Open a connection to the remote NetROM devices. */
+
+static void
+nrom_open (name, from_tty)
+ char *name;
+ int from_tty;
+{
+ int errn;
+
+ if (!name || strchr (name, '/') || strchr (name, ':'))
+ error (
+"To open a NetROM connection, you must specify the hostname\n\
+or IP address of the NetROM device you wish to use.");
+
+ strcpy (nrom_hostname, name);
+
+ target_preopen (from_tty);
+
+ unpush_target (&nrom_ops);
+
+ ctrl_desc = open_socket (nrom_hostname, control_port);
+
+ push_target (&nrom_ops);
+
+ if (from_tty)
+ printf_filtered ("Connected to NetROM device \"%s\"\n", nrom_hostname);
+}
+
+/* Close out all files and local state before this target loses control. */
+
+static void
+nrom_close (quitting)
+ int quitting;
+{
+ if (load_desc)
+ SERIAL_CLOSE (load_desc);
+ if (ctrl_desc)
+ SERIAL_CLOSE (ctrl_desc);
+}
+
+/* Pass arguments directly to the NetROM. */
+
+static void
+nrom_passthru (args, fromtty)
+ char *args;
+ int fromtty;
+{
+ char buf[1024];
+
+ sprintf (buf, "%s\n", args);
+ if (SERIAL_WRITE (ctrl_desc, buf, strlen (buf)))
+ error ("nrom_reset: control_send() of `%s'failed", args);
+}
+
+static void
+nrom_mourn()
+{
+ unpush_target (&nrom_ops);
+ generic_mourn_inferior ();
+}
+
+/* Define the target vector. */
+
+struct target_ops nrom_ops ;
+
+static void
+init_nrom_ops(void)
+{
+ nrom_ops.to_shortname = "nrom";
+ nrom_ops.to_longname = "Remote XDI `NetROM' target";
+ nrom_ops.to_doc = "Remote debug using a NetROM over Ethernet";
+ nrom_ops.to_open = nrom_open;
+ nrom_ops.to_close = nrom_close;
+ nrom_ops.to_attach = NULL;
+ nrom_ops.to_post_attach = NULL;
+ nrom_ops.to_require_attach = NULL;
+ nrom_ops.to_detach = NULL;
+ nrom_ops.to_require_detach = NULL;
+ nrom_ops.to_resume = NULL;
+ nrom_ops.to_wait = NULL;
+ nrom_ops.to_post_wait = NULL;
+ nrom_ops.to_fetch_registers = NULL;
+ nrom_ops.to_store_registers = NULL;
+ nrom_ops.to_prepare_to_store = NULL;
+ nrom_ops.to_xfer_memory = NULL;
+ nrom_ops.to_files_info = NULL;
+ nrom_ops.to_insert_breakpoint = NULL;
+ nrom_ops.to_remove_breakpoint = NULL;
+ nrom_ops.to_terminal_init = NULL;
+ nrom_ops.to_terminal_inferior = NULL;
+ nrom_ops.to_terminal_ours_for_output = NULL;
+ nrom_ops.to_terminal_ours = NULL;
+ nrom_ops.to_terminal_info = NULL;
+ nrom_ops.to_kill = nrom_kill;
+ nrom_ops.to_load = nrom_load;
+ nrom_ops.to_lookup_symbol = NULL;
+ nrom_ops.to_create_inferior = NULL;
+ nrom_ops.to_post_startup_inferior = NULL;
+ nrom_ops.to_acknowledge_created_inferior = NULL;
+ nrom_ops.to_clone_and_follow_inferior = NULL;
+ nrom_ops.to_post_follow_inferior_by_clone = NULL;
+ nrom_ops.to_insert_fork_catchpoint = NULL;
+ nrom_ops.to_remove_fork_catchpoint = NULL;
+ nrom_ops.to_insert_vfork_catchpoint = NULL;
+ nrom_ops.to_remove_vfork_catchpoint = NULL;
+ nrom_ops.to_has_forked = NULL;
+ nrom_ops.to_has_vforked = NULL;
+ nrom_ops.to_can_follow_vfork_prior_to_exec = NULL;
+ nrom_ops.to_post_follow_vfork = NULL;
+ nrom_ops.to_insert_exec_catchpoint = NULL;
+ nrom_ops.to_remove_exec_catchpoint = NULL;
+ nrom_ops.to_has_execd = NULL;
+ nrom_ops.to_reported_exec_events_per_exec_call = NULL;
+ nrom_ops.to_has_exited = NULL;
+ nrom_ops.to_mourn_inferior = nrom_mourn;
+ nrom_ops.to_can_run = NULL;
+ nrom_ops.to_notice_signals = 0;
+ nrom_ops.to_thread_alive = 0;
+ nrom_ops.to_stop = 0;
+ nrom_ops.to_pid_to_exec_file = NULL;
+ nrom_ops.to_core_file_to_sym_file = NULL;
+ nrom_ops.to_stratum = download_stratum;
+ nrom_ops.DONT_USE = NULL;
+ nrom_ops.to_has_all_memory = 1;
+ nrom_ops.to_has_memory = 1;
+ nrom_ops.to_has_stack = 1;
+ nrom_ops.to_has_registers = 1;
+ nrom_ops.to_has_execution = 0;
+ nrom_ops.to_sections = NULL;
+ nrom_ops.to_sections_end = NULL;
+ nrom_ops.to_magic = OPS_MAGIC ;
+};
+
+void
+_initialize_remote_nrom ()
+{
+ init_nrom_ops() ;
+ add_target (&nrom_ops);
+
+ add_show_from_set (
+ add_set_cmd ("nrom_load_port", no_class, var_zinteger, (char *)&load_port,
+ "Set the port to use for NetROM downloads\n", &setlist),
+ &showlist);
+
+ add_show_from_set (
+ add_set_cmd ("nrom_control_port", no_class, var_zinteger, (char *)&control_port,
+ "Set the port to use for NetROM debugger services\n", &setlist),
+ &showlist);
+
+ add_cmd ("nrom", no_class, nrom_passthru,
+ "Pass arguments as command to NetROM",
+ &cmdlist);
+}
diff --git a/gdb/remote-os9k.c b/gdb/remote-os9k.c
new file mode 100644
index 00000000000..2abfa837683
--- /dev/null
+++ b/gdb/remote-os9k.c
@@ -0,0 +1,1264 @@
+/* Remote debugging interface for boot monitors, for GDB.
+ Copyright 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* This file was derived from remote-eb.c, which did a similar job, but for
+ an AMD-29K running EBMON. That file was in turn derived from remote.c
+ as mentioned in the following comment (left in for comic relief):
+
+ "This is like remote.c but is for a different situation--
+ having a PC running os9000 hook up with a unix machine with
+ a serial line, and running ctty com2 on the PC. os9000 has a debug
+ monitor called ROMBUG running. Not to mention that the PC
+ has PC/NFS, so it can access the same executables that gdb can,
+ over the net in real time."
+
+ In reality, this module talks to a debug monitor called 'ROMBUG', which
+ We communicate with ROMBUG via a direct serial line, the network version
+ of ROMBUG is not available yet.
+*/
+
+/* FIXME This file needs to be rewritten if it's to work again, either
+ to self-contained or to use the new monitor interface. */
+
+#include "defs.h"
+#include "gdbcore.h"
+#include "target.h"
+#include "wait.h"
+#ifdef ANSI_PROTOTYPES
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+#include <signal.h>
+#include "gdb_string.h"
+#include <sys/types.h>
+#include "command.h"
+#include "serial.h"
+#include "monitor.h"
+#include "remote-utils.h"
+#include "symtab.h"
+#include "symfile.h"
+#include "objfiles.h"
+#include "gdb-stabs.h"
+
+struct cmd_list_element *showlist;
+extern struct target_ops rombug_ops; /* Forward declaration */
+extern struct monitor_ops rombug_cmds; /* Forward declaration */
+extern struct cmd_list_element *setlist;
+extern struct cmd_list_element *unsetlist;
+extern int attach_flag;
+
+static void rombug_close();
+static void rombug_fetch_register();
+static void rombug_fetch_registers();
+static void rombug_store_register();
+#if 0
+static int sr_get_debug(); /* flag set by "set remotedebug" */
+#endif
+static int hashmark; /* flag set by "set hash" */
+static int rombug_is_open = 0;
+
+/* FIXME: Replace with sr_get_debug (). */
+#define LOG_FILE "monitor.log"
+FILE *log_file;
+static int monitor_log = 0;
+static int tty_xon = 0;
+static int tty_xoff = 0;
+
+static int timeout = 10;
+static int is_trace_mode = 0;
+/* Descriptor for I/O to remote machine. Initialize it to NULL*/
+static serial_t monitor_desc = NULL;
+
+static CORE_ADDR bufaddr = 0;
+static int buflen = 0;
+static char readbuf[16];
+
+/* Send data to monitor. Works just like printf. */
+static void
+#ifdef ANSI_PROTOTYPES
+printf_monitor(char *pattern, ...)
+#else
+printf_monitor(va_alist)
+ va_dcl
+#endif
+{
+ va_list args;
+ char buf[200];
+ int i;
+
+#ifdef ANSI_PROTOTYPES
+ va_start (args, pattern);
+#else
+ char *pattern;
+ va_start(args);
+ pattern = va_arg(args, char *);
+#endif
+
+ vsprintf(buf, pattern, args);
+ va_end(args);
+
+ if (SERIAL_WRITE(monitor_desc, buf, strlen(buf)))
+ fprintf(stderr, "SERIAL_WRITE failed: %s\n", safe_strerror(errno));
+}
+
+/* Read a character from the remote system, doing all the fancy timeout stuff*/
+static int
+readchar(timeout)
+ int timeout;
+{
+ int c;
+
+ c = SERIAL_READCHAR(monitor_desc, timeout);
+
+ if (sr_get_debug())
+ putchar(c & 0x7f);
+
+ if (monitor_log && isascii(c))
+ putc(c & 0x7f, log_file);
+
+ if (c >= 0)
+ return c & 0x7f;
+
+ if (c == SERIAL_TIMEOUT)
+ {
+ if (timeout == 0)
+ return c; /* Polls shouldn't generate timeout errors */
+
+ error("Timeout reading from remote system.");
+ }
+
+ perror_with_name("remote-monitor");
+}
+
+/* Scan input from the remote system, until STRING is found. If DISCARD is
+ non-zero, then discard non-matching input, else print it out.
+ Let the user break out immediately. */
+static void
+expect(string, discard)
+ char *string;
+ int discard;
+{
+ char *p = string;
+ int c;
+
+ if (sr_get_debug())
+ printf ("Expecting \"%s\"\n", string);
+
+ immediate_quit = 1;
+ while (1)
+ {
+ c = readchar(timeout);
+ if (!isascii (c))
+ continue;
+ if (c == *p++)
+ {
+ if (*p == '\0')
+ {
+ immediate_quit = 0;
+ if (sr_get_debug())
+ printf ("\nMatched\n");
+ return;
+ }
+ }
+ else
+ {
+ if (!discard)
+ {
+ fwrite(string, 1, (p - 1) - string, stdout);
+ putchar((char)c);
+ fflush(stdout);
+ }
+ p = string;
+ }
+ }
+}
+
+/* Keep discarding input until we see the ROMBUG prompt.
+
+ The convention for dealing with the prompt is that you
+ o give your command
+ o *then* wait for the prompt.
+
+ Thus the last thing that a procedure does with the serial line
+ will be an expect_prompt(). Exception: rombug_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 rombug_wait which does wait for the prompt.
+ Note that this includes abnormal exit, e.g. error(). This is
+ necessary to prevent getting into states from which we can't
+ recover. */
+static void
+expect_prompt(discard)
+ int discard;
+{
+ if (monitor_log)
+ /* This is a convenient place to do this. The idea is to do it often
+ enough that we never lose much data if we terminate abnormally. */
+ fflush(log_file);
+
+ if (is_trace_mode) {
+ expect("trace", discard);
+ } else {
+ expect (PROMPT, discard);
+ }
+}
+
+/* Get a hex digit from the remote system & return its value.
+ If ignore_space is nonzero, ignore spaces (not newline, tab, etc). */
+static int
+get_hex_digit(ignore_space)
+ int ignore_space;
+{
+ int ch;
+ while (1)
+ {
+ ch = readchar(timeout);
+ if (ch >= '0' && ch <= '9')
+ return ch - '0';
+ else if (ch >= 'A' && ch <= 'F')
+ return ch - 'A' + 10;
+ else if (ch >= 'a' && ch <= 'f')
+ return ch - 'a' + 10;
+ else if (ch == ' ' && ignore_space)
+ ;
+ else
+ {
+ expect_prompt(1);
+ error("Invalid hex digit from remote system.");
+ }
+ }
+}
+
+/* Get a byte from monitor and put it in *BYT. Accept any number
+ leading spaces. */
+static void
+get_hex_byte (byt)
+ char *byt;
+{
+ int val;
+
+ val = get_hex_digit (1) << 4;
+ val |= get_hex_digit (0);
+ *byt = val;
+}
+
+/* Get N 32-bit words from remote, each preceded by a space,
+ and put them in registers starting at REGNO. */
+static void
+get_hex_regs (n, regno)
+ int n;
+ int regno;
+{
+ long val;
+ int i;
+ unsigned char b;
+
+ for (i = 0; i < n; i++)
+ {
+ int j;
+
+ val = 0;
+ for (j = 0; j < 4; j++)
+ {
+ get_hex_byte (&b);
+ if (TARGET_BYTE_ORDER == BIG_ENDIAN)
+ val = (val << 8) + b;
+ else
+ val = val + (b << (j*8));
+ }
+ supply_register (regno++, (char *) &val);
+ }
+}
+
+/* This is called not only when we first attach, but also when the
+ user types "run" after having attached. */
+static void
+rombug_create_inferior (execfile, args, env)
+ char *execfile;
+ char *args;
+ char **env;
+{
+ int entry_pt;
+
+ if (args && *args)
+ error("Can't pass arguments to remote ROMBUG process");
+
+ if (execfile == 0 || exec_bfd == 0)
+ error("No executable file specified");
+
+ entry_pt = (int) bfd_get_start_address (exec_bfd);
+
+ if (monitor_log)
+ fputs ("\nIn Create_inferior()", log_file);
+
+
+/* The "process" (board) is already stopped awaiting our commands, and
+ the program is already downloaded. We just set its PC and go. */
+
+ init_wait_for_inferior ();
+ proceed ((CORE_ADDR)entry_pt, TARGET_SIGNAL_DEFAULT, 0);
+}
+
+/* Open a connection to a remote debugger.
+ NAME is the filename used for communication. */
+
+static char dev_name[100];
+
+static void
+rombug_open(args, from_tty)
+ char *args;
+ int from_tty;
+{
+ if (args == NULL)
+ error ("Use `target RomBug DEVICE-NAME' to use a serial port, or \n\
+`target RomBug HOST-NAME:PORT-NUMBER' to use a network connection.");
+
+ target_preopen(from_tty);
+
+ if (rombug_is_open)
+ unpush_target(&rombug_ops);
+
+ strcpy(dev_name, args);
+ monitor_desc = SERIAL_OPEN(dev_name);
+ if (monitor_desc == NULL)
+ perror_with_name(dev_name);
+
+ /* if baud rate is set by 'set remotebaud' */
+ if (SERIAL_SETBAUDRATE (monitor_desc, sr_get_baud_rate()))
+ {
+ SERIAL_CLOSE (monitor_desc);
+ perror_with_name ("RomBug");
+ }
+ SERIAL_RAW(monitor_desc);
+ if (tty_xon || tty_xoff)
+ {
+ struct hardware_ttystate { struct termios t;} *tty_s;
+
+ tty_s =(struct hardware_ttystate *)SERIAL_GET_TTY_STATE(monitor_desc);
+ if (tty_xon) tty_s->t.c_iflag |= IXON;
+ if (tty_xoff) tty_s->t.c_iflag |= IXOFF;
+ SERIAL_SET_TTY_STATE(monitor_desc, (serial_ttystate) tty_s);
+ }
+
+ rombug_is_open = 1;
+
+ log_file = fopen (LOG_FILE, "w");
+ if (log_file == NULL)
+ perror_with_name (LOG_FILE);
+
+ push_monitor (&rombug_cmds);
+ printf_monitor("\r"); /* CR wakes up monitor */
+ expect_prompt(1);
+ push_target (&rombug_ops);
+ attach_flag = 1;
+
+ if (from_tty)
+ printf("Remote %s connected to %s\n", target_shortname,
+ dev_name);
+
+ rombug_fetch_registers();
+
+ printf_monitor ("ov e \r");
+ expect_prompt(1);
+ bufaddr = 0;
+ buflen = 0;
+}
+
+/*
+ * Close out all files and local state before this target loses control.
+ */
+
+static void
+rombug_close (quitting)
+ int quitting;
+{
+ if (rombug_is_open) {
+ SERIAL_CLOSE(monitor_desc);
+ monitor_desc = NULL;
+ rombug_is_open = 0;
+ }
+
+ if (log_file) {
+ if (ferror(log_file))
+ fprintf(stderr, "Error writing log file.\n");
+ if (fclose(log_file) != 0)
+ fprintf(stderr, "Error closing log file.\n");
+ log_file = 0;
+ }
+}
+
+int
+rombug_link(mod_name, text_reloc)
+ char *mod_name;
+ CORE_ADDR *text_reloc;
+{
+ int i, j;
+ unsigned long val;
+ unsigned char b;
+
+ printf_monitor("l %s \r", mod_name);
+ expect_prompt(1);
+ printf_monitor(".r \r");
+ expect(REG_DELIM, 1);
+ for (i=0; i <= 7; i++)
+ {
+ val = 0;
+ for (j = 0; j < 4; j++)
+ {
+ get_hex_byte(&b);
+ val = (val << 8) + b;
+ }
+ }
+ expect_prompt(1);
+ *text_reloc = val;
+ return 1;
+}
+
+/* Terminate the open connection to the remote debugger.
+ Use this when you want to detach and do something else
+ with your gdb. */
+static void
+rombug_detach (from_tty)
+ int from_tty;
+{
+ if (attach_flag) {
+ printf_monitor (GO_CMD);
+ attach_flag = 0;
+ }
+ pop_target(); /* calls rombug_close to do the real work */
+ if (from_tty)
+ printf ("Ending remote %s debugging\n", target_shortname);
+}
+
+/*
+ * Tell the remote machine to resume.
+ */
+static void
+rombug_resume (pid, step, sig)
+ int pid, step;
+ enum target_signal sig;
+{
+ if (monitor_log)
+ fprintf (log_file, "\nIn Resume (step=%d, sig=%d)\n", step, sig);
+
+ if (step)
+ {
+ is_trace_mode = 1;
+ printf_monitor (STEP_CMD);
+ /* wait for the echo. **
+ expect (STEP_CMD, 1);
+ */
+ }
+ else
+ {
+ printf_monitor (GO_CMD);
+ /* swallow the echo. **
+ expect (GO_CMD, 1);
+ */
+ }
+ bufaddr = 0;
+ buflen= 0;
+}
+
+/*
+ * Wait until the remote machine stops, then return,
+ * storing status in status just as `wait' would.
+ */
+
+static int
+rombug_wait (pid, status)
+ int pid;
+ struct target_waitstatus *status;
+{
+ int old_timeout = timeout;
+ struct section_offsets *offs;
+ CORE_ADDR addr, pc;
+ struct obj_section *obj_sec;
+
+ if (monitor_log)
+ fputs ("\nIn wait ()", log_file);
+
+ status->kind = TARGET_WAITKIND_EXITED;
+ status->value.integer = 0;
+
+ timeout = -1; /* Don't time out -- user program is running. */
+ expect ("eax:", 0); /* output any message before register display */
+ expect_prompt(1); /* Wait for prompt, outputting extraneous text */
+
+ status->kind = TARGET_WAITKIND_STOPPED;
+ status->value.sig = TARGET_SIGNAL_TRAP;
+ timeout = old_timeout;
+ rombug_fetch_registers();
+ bufaddr = 0;
+ buflen = 0;
+ pc = read_register(PC_REGNUM);
+ addr = read_register(DATABASE_REG);
+ obj_sec = find_pc_section (pc);
+ if (obj_sec != NULL)
+ {
+ if (obj_sec->objfile != symfile_objfile)
+ new_symfile_objfile(obj_sec->objfile, 1, 0);
+ 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_DATA) = addr;
+ ANOFFSET (offs, SECT_OFF_BSS) = addr;
+
+ objfile_relocate(symfile_objfile, offs);
+ }
+
+ return 0;
+}
+
+/* Return the name of register number regno in the form input and output by
+ monitor. Currently, register_names just happens to contain exactly what
+ monitor wants. Lets take advantage of that just as long as possible! */
+
+static char *
+get_reg_name (regno)
+ int regno;
+{
+ static char buf[50];
+ char *p;
+ char *b;
+
+ b = buf;
+
+ if (regno < 0)
+ return ("");
+/*
+ for (p = REGISTER_NAME (regno); *p; p++)
+ *b++ = toupper(*p);
+ *b = '\000';
+*/
+ p = (char *)REGISTER_NAME (regno);
+ return p;
+/*
+ return buf;
+*/
+}
+
+/* read the remote registers into the block regs. */
+
+static void
+rombug_fetch_registers ()
+{
+ int regno, j, i;
+ long val;
+ unsigned char b;
+
+ printf_monitor (GET_REG);
+ expect("eax:", 1);
+ expect("\n", 1);
+ get_hex_regs(1, 0);
+ get_hex_regs(1, 3);
+ get_hex_regs(1, 1);
+ get_hex_regs(1, 2);
+ get_hex_regs(1, 6);
+ get_hex_regs(1, 7);
+ get_hex_regs(1, 5);
+ get_hex_regs(1, 4);
+ for (regno = 8; regno <= 15; regno++)
+ {
+ expect(REG_DELIM, 1);
+ if (regno >= 8 && regno <= 13)
+ {
+ val = 0;
+ for (j = 0; j < 2; j++)
+ {
+ get_hex_byte (&b);
+ if (TARGET_BYTE_ORDER == BIG_ENDIAN)
+ val = (val << 8) + b;
+ else
+ val = val + (b << (j*8));
+ }
+
+ if (regno == 8) i = 10;
+ if (regno >= 9 && regno <= 12) i = regno + 3;
+ if (regno == 13) i = 11;
+ supply_register (i, (char *) &val);
+ }
+ else if (regno == 14)
+ {
+ get_hex_regs(1, PC_REGNUM);
+ }
+ else if (regno == 15)
+ {
+ get_hex_regs(1, 9);
+ }
+ else
+ {
+ val = 0;
+ supply_register(regno, (char *) &val);
+ }
+ }
+ is_trace_mode = 0;
+ expect_prompt (1);
+}
+
+/* Fetch register REGNO, or all registers if REGNO is -1.
+ Returns errno value. */
+static void
+rombug_fetch_register (regno)
+ int regno;
+{
+ int val, j;
+ unsigned char b;
+
+ if (monitor_log) {
+ fprintf (log_file, "\nIn Fetch Register (reg=%s)\n", get_reg_name (regno));
+ fflush (log_file);
+ }
+
+ if (regno < 0)
+ {
+ rombug_fetch_registers ();
+ }
+ else
+ {
+ char *name = get_reg_name (regno);
+ printf_monitor (GET_REG);
+ if (regno >= 10 && regno <= 15)
+ {
+ expect ("\n", 1);
+ expect ("\n", 1);
+ expect (name, 1);
+ expect (REG_DELIM, 1);
+ val = 0;
+ for (j = 0; j < 2; j++)
+ {
+ get_hex_byte (&b);
+ if (TARGET_BYTE_ORDER == BIG_ENDIAN)
+ val = (val << 8) + b;
+ else
+ val = val + (b << (j*8));
+ }
+ supply_register (regno, (char *) &val);
+ }
+ else if (regno == 8 || regno == 9)
+ {
+ expect ("\n", 1);
+ expect ("\n", 1);
+ expect ("\n", 1);
+ expect (name, 1);
+ expect (REG_DELIM, 1);
+ get_hex_regs (1, regno);
+ }
+ else
+ {
+ expect (name, 1);
+ expect (REG_DELIM, 1);
+ expect("\n", 1);
+ get_hex_regs(1, 0);
+ get_hex_regs(1, 3);
+ get_hex_regs(1, 1);
+ get_hex_regs(1, 2);
+ get_hex_regs(1, 6);
+ get_hex_regs(1, 7);
+ get_hex_regs(1, 5);
+ get_hex_regs(1, 4);
+ }
+ expect_prompt (1);
+ }
+ return;
+}
+
+/* Store the remote registers from the contents of the block REGS. */
+
+static void
+rombug_store_registers ()
+{
+ int regno;
+
+ for (regno = 0; regno <= PC_REGNUM; regno++)
+ rombug_store_register(regno);
+
+ registers_changed ();
+}
+
+/* Store register REGNO, or all if REGNO == 0.
+ return errno value. */
+static void
+rombug_store_register (regno)
+ int regno;
+{
+char *name;
+
+ if (monitor_log)
+ fprintf (log_file, "\nIn Store_register (regno=%d)\n", regno);
+
+ if (regno == -1)
+ rombug_store_registers ();
+ else
+ {
+ if (sr_get_debug())
+ printf ("Setting register %s to 0x%x\n", get_reg_name (regno), read_register (regno));
+
+ name = get_reg_name(regno);
+ if (name == 0) return;
+ printf_monitor (SET_REG, name, read_register (regno));
+
+ is_trace_mode = 0;
+ expect_prompt (1);
+ }
+}
+
+/* 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
+rombug_prepare_to_store ()
+{
+ /* Do nothing, since we can store individual regs */
+}
+
+static void
+rombug_files_info ()
+{
+ printf ("\tAttached to %s at %d baud.\n",
+ dev_name, sr_get_baud_rate());
+}
+
+/* Copy LEN bytes of data from debugger memory at MYADDR
+ to inferior's memory at MEMADDR. Returns length moved. */
+static int
+rombug_write_inferior_memory (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ unsigned char *myaddr;
+ int len;
+{
+ int i;
+ char buf[10];
+
+ if (monitor_log)
+ fprintf (log_file, "\nIn Write_inferior_memory (memaddr=%x, len=%d)\n", memaddr, len);
+
+ printf_monitor (MEM_SET_CMD, memaddr);
+ for (i = 0; i < len; i++)
+ {
+ expect (CMD_DELIM, 1);
+ printf_monitor ("%x \r", myaddr[i]);
+ if (sr_get_debug())
+ printf ("\nSet 0x%x to 0x%x\n", memaddr + i, myaddr[i]);
+ }
+ expect (CMD_DELIM, 1);
+ if (CMD_END)
+ printf_monitor (CMD_END);
+ is_trace_mode = 0;
+ expect_prompt (1);
+
+ bufaddr = 0;
+ buflen = 0;
+ return len;
+}
+
+/* Read LEN bytes from inferior memory at MEMADDR. Put the result
+ at debugger address MYADDR. Returns length moved. */
+static int
+rombug_read_inferior_memory(memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+{
+ int i, j;
+
+ /* Number of bytes read so far. */
+ int count;
+
+ /* Starting address of this pass. */
+ unsigned long startaddr;
+
+ /* Number of bytes to read in this pass. */
+ int len_this_pass;
+
+ if (monitor_log)
+ fprintf (log_file, "\nIn Read_inferior_memory (memaddr=%x, len=%d)\n", memaddr, len);
+
+ /* Note that this code works correctly if startaddr is just less
+ than UINT_MAX (well, really CORE_ADDR_MAX if there was such a
+ thing). That is, something like
+ rombug_read_bytes (CORE_ADDR_MAX - 4, foo, 4)
+ works--it never adds len To memaddr and gets 0. */
+ /* However, something like
+ rombug_read_bytes (CORE_ADDR_MAX - 3, foo, 4)
+ doesn't need to work. Detect it and give up if there's an attempt
+ to do that. */
+ if (((memaddr - 1) + len) < memaddr) {
+ errno = EIO;
+ return 0;
+ }
+ if (bufaddr <= memaddr && (memaddr+len) <= (bufaddr+buflen))
+ {
+ memcpy(myaddr, &readbuf[memaddr-bufaddr], len);
+ return len;
+ }
+
+ startaddr = memaddr;
+ count = 0;
+ while (count < len)
+ {
+ len_this_pass = 16;
+ if ((startaddr % 16) != 0)
+ len_this_pass -= startaddr % 16;
+ if (len_this_pass > (len - count))
+ len_this_pass = (len - count);
+ if (sr_get_debug())
+ printf ("\nDisplay %d bytes at %x\n", len_this_pass, startaddr);
+
+ printf_monitor (MEM_DIS_CMD, startaddr, 8);
+ expect ("- ", 1);
+ for (i = 0; i < 16; i++)
+ {
+ get_hex_byte (&readbuf[i]);
+ }
+ bufaddr = startaddr;
+ buflen = 16;
+ memcpy(&myaddr[count], readbuf, len_this_pass);
+ count += len_this_pass;
+ startaddr += len_this_pass;
+ expect(CMD_DELIM, 1);
+ }
+ if (CMD_END)
+ printf_monitor (CMD_END);
+ is_trace_mode = 0;
+ expect_prompt (1);
+
+ return len;
+}
+
+/* FIXME-someday! merge these two. */
+static int
+rombug_xfer_inferior_memory (memaddr, myaddr, len, write, target)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+ int write;
+ struct target_ops *target; /* ignored */
+{
+ if (write)
+ return rombug_write_inferior_memory (memaddr, myaddr, len);
+ else
+ return rombug_read_inferior_memory (memaddr, myaddr, len);
+}
+
+static void
+rombug_kill (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ return; /* ignore attempts to kill target system */
+}
+
+/* Clean up when a program exits.
+ The program actually lives on in the remote processor's RAM, and may be
+ run again without a download. Don't leave it full of breakpoint
+ instructions. */
+
+static void
+rombug_mourn_inferior ()
+{
+ remove_breakpoints ();
+ generic_mourn_inferior (); /* Do all the proper things now */
+}
+
+#define MAX_MONITOR_BREAKPOINTS 16
+
+static CORE_ADDR breakaddr[MAX_MONITOR_BREAKPOINTS] = {0};
+
+static int
+rombug_insert_breakpoint (addr, shadow)
+ CORE_ADDR addr;
+ char *shadow;
+{
+ int i;
+ CORE_ADDR bp_addr = addr;
+ int bp_size = 0;
+
+ if (monitor_log)
+ fprintf (log_file, "\nIn Insert_breakpoint (addr=%x)\n", addr);
+ BREAKPOINT_FROM_PC (&bp_addr, &bp_size);
+
+ for (i = 0; i <= MAX_MONITOR_BREAKPOINTS; i++)
+ if (breakaddr[i] == 0)
+ {
+ breakaddr[i] = addr;
+ if (sr_get_debug())
+ printf ("Breakpoint at %x\n", addr);
+ rombug_read_inferior_memory (bp_addr, shadow, bp_size);
+ printf_monitor(SET_BREAK_CMD, addr);
+ is_trace_mode = 0;
+ expect_prompt(1);
+ return 0;
+ }
+
+ fprintf(stderr, "Too many breakpoints (> 16) for monitor\n");
+ return 1;
+}
+
+/*
+ * _remove_breakpoint -- Tell the monitor to remove a breakpoint
+ */
+static int
+rombug_remove_breakpoint (addr, shadow)
+ CORE_ADDR addr;
+ char *shadow;
+{
+ int i;
+
+ if (monitor_log)
+ fprintf (log_file, "\nIn Remove_breakpoint (addr=%x)\n", addr);
+
+ for (i = 0; i < MAX_MONITOR_BREAKPOINTS; i++)
+ if (breakaddr[i] == addr)
+ {
+ breakaddr[i] = 0;
+ printf_monitor(CLR_BREAK_CMD, addr);
+ is_trace_mode = 0;
+ expect_prompt(1);
+ return 0;
+ }
+
+ fprintf(stderr, "Can't find breakpoint associated with 0x%x\n", addr);
+ return 1;
+}
+
+/* Load a file. This is usually an srecord, which is ascii. No
+ protocol, just sent line by line. */
+
+#define DOWNLOAD_LINE_SIZE 100
+static void
+rombug_load (arg)
+ char *arg;
+{
+/* this part comment out for os9* */
+#if 0
+ FILE *download;
+ char buf[DOWNLOAD_LINE_SIZE];
+ int i, bytes_read;
+
+ if (sr_get_debug())
+ printf ("Loading %s to monitor\n", arg);
+
+ download = fopen (arg, "r");
+ if (download == NULL)
+ {
+ error (sprintf (buf, "%s Does not exist", arg));
+ return;
+ }
+
+ printf_monitor (LOAD_CMD);
+/* expect ("Waiting for S-records from host... ", 1); */
+
+ while (!feof (download))
+ {
+ bytes_read = fread (buf, sizeof (char), DOWNLOAD_LINE_SIZE, download);
+ if (hashmark)
+ {
+ putchar ('.');
+ fflush (stdout);
+ }
+
+ if (SERIAL_WRITE(monitor_desc, buf, bytes_read)) {
+ fprintf(stderr, "SERIAL_WRITE failed: (while downloading) %s\n", safe_strerror(errno));
+ break;
+ }
+ i = 0;
+ while (i++ <=200000) {} ; /* Ugly HACK, probably needs flow control */
+ if (bytes_read < DOWNLOAD_LINE_SIZE)
+ {
+ if (!feof (download))
+ error ("Only read %d bytes\n", bytes_read);
+ break;
+ }
+ }
+
+ if (hashmark)
+ {
+ putchar ('\n');
+ }
+ if (!feof (download))
+ error ("Never got EOF while downloading");
+ fclose (download);
+#endif 0
+}
+
+/* Put a command string, in args, out to MONITOR.
+ Output from MONITOR is placed on the users terminal until the prompt
+ is seen. */
+
+static void
+rombug_command (args, fromtty)
+ char *args;
+ int fromtty;
+{
+ if (monitor_desc == NULL)
+ error("monitor target not open.");
+
+ if (monitor_log)
+ fprintf (log_file, "\nIn command (args=%s)\n", args);
+
+ if (!args)
+ error("Missing command.");
+
+ printf_monitor("%s\r", args);
+ expect_prompt(0);
+}
+
+#if 0
+/* Connect the user directly to MONITOR. This command acts just like the
+ 'cu' or 'tip' command. Use <CR>~. or <CR>~^D to break out. */
+
+static struct ttystate ttystate;
+
+static void
+cleanup_tty()
+{ printf("\r\n[Exiting connect mode]\r\n");
+ /*SERIAL_RESTORE(0, &ttystate);*/
+}
+
+static void
+connect_command (args, fromtty)
+ char *args;
+ int fromtty;
+{
+ fd_set readfds;
+ int numfds;
+ int c;
+ char cur_esc = 0;
+
+ dont_repeat();
+
+ if (monitor_desc == NULL)
+ error("monitor target not open.");
+
+ if (args)
+ fprintf("This command takes no args. They have been ignored.\n");
+
+ printf("[Entering connect mode. Use ~. or ~^D to escape]\n");
+
+ serial_raw(0, &ttystate);
+
+ make_cleanup(cleanup_tty, 0);
+
+ FD_ZERO(&readfds);
+
+ while (1)
+ {
+ do
+ {
+ FD_SET(0, &readfds);
+ FD_SET(monitor_desc, &readfds);
+ numfds = select(sizeof(readfds)*8, &readfds, 0, 0, 0);
+ }
+ while (numfds == 0);
+
+ if (numfds < 0)
+ perror_with_name("select");
+
+ if (FD_ISSET(0, &readfds))
+ { /* tty input, send to monitor */
+ c = getchar();
+ if (c < 0)
+ perror_with_name("connect");
+
+ printf_monitor("%c", c);
+ 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 (FD_ISSET(monitor_desc, &readfds))
+ {
+ while (1)
+ {
+ c = readchar(0);
+ if (c < 0)
+ break;
+ putchar(c);
+ }
+ fflush(stdout);
+ }
+ }
+}
+#endif
+
+/*
+ * Define the monitor command strings. Since these are passed directly
+ * through to a printf style function, we need can include formatting
+ * strings. We also need a CR or LF on the end.
+ */
+#warning FIXME: monitor interface pattern strings, stale struct decl
+struct monitor_ops rombug_cmds = {
+ "g \r", /* execute or usually GO command */
+ "g \r", /* continue command */
+ "t \r", /* single step */
+ "b %x\r", /* set a breakpoint */
+ "k %x\r", /* clear a breakpoint */
+ "c %x\r", /* set memory to a value */
+ "d %x %d\r", /* display memory */
+ "$%08X", /* prompt memory commands use */
+ ".%s %x\r", /* set a register */
+ ":", /* delimiter between registers */
+ ". \r", /* read a register */
+ "mf \r", /* download command */
+ "RomBug: ", /* monitor command prompt */
+ ": ", /* end-of-command delimitor */
+ ".\r" /* optional command terminator */
+};
+
+struct target_ops rombug_ops ;
+
+static void
+init_rombug_ops(void)
+{
+ rombug_ops.to_shortname = "rombug";
+ rombug_ops.to_longname = "Microware's ROMBUG debug monitor";
+ rombug_ops.to_doc = "Use a remote computer running the ROMBUG debug monitor.\n\
+Specify the serial device it is connected to (e.g. /dev/ttya).",
+ rombug_ops.to_open = rombug_open;
+ rombug_ops.to_close = rombug_close;
+ rombug_ops.to_attach = 0;
+ rombug_ops.to_post_attach = NULL;
+ rombug_ops.to_require_attach = NULL;
+ rombug_ops.to_detach = rombug_detach;
+ rombug_ops.to_require_detach = NULL;
+ rombug_ops.to_resume = rombug_resume;
+ rombug_ops.to_wait = rombug_wait;
+ rombug_ops.to_post_wait = NULL;
+ rombug_ops.to_fetch_registers = rombug_fetch_register;
+ rombug_ops.to_store_registers = rombug_store_register;
+ rombug_ops.to_prepare_to_store = rombug_prepare_to_store;
+ rombug_ops.to_xfer_memory = rombug_xfer_inferior_memory;
+ rombug_ops.to_files_info = rombug_files_info;
+ rombug_ops.to_insert_breakpoint = rombug_insert_breakpoint;
+ rombug_ops.to_remove_breakpoint = rombug_remove_breakpoint; /* Breakpoints */
+ rombug_ops.to_terminal_init = 0;
+ rombug_ops.to_terminal_inferior = 0;
+ rombug_ops.to_terminal_ours_for_output = 0;
+ rombug_ops.to_terminal_ours = 0;
+ rombug_ops.to_terminal_info = 0; /* Terminal handling */
+ rombug_ops.to_kill = rombug_kill;
+ rombug_ops.to_load = rombug_load; /* load */
+ rombug_ops.to_lookup_symbol = rombug_link; /* lookup_symbol */
+ rombug_ops.to_create_inferior = rombug_create_inferior;
+ rombug_ops.to_post_startup_inferior = NULL;
+ rombug_ops.to_acknowledge_created_inferior = NULL;
+ rombug_ops.to_clone_and_follow_inferior = NULL;
+ rombug_ops.to_post_follow_inferior_by_clone = NULL;
+ rombug_ops.to_insert_fork_catchpoint = NULL;
+ rombug_ops.to_remove_fork_catchpoint = NULL;
+ rombug_ops.to_insert_vfork_catchpoint = NULL;
+ rombug_ops.to_remove_vfork_catchpoint = NULL;
+ rombug_ops.to_has_forked = NULL;
+ rombug_ops.to_has_vforked = NULL;
+ rombug_ops.to_can_follow_vfork_prior_to_exec = NULL;
+ rombug_ops.to_post_follow_vfork = NULL;
+ rombug_ops.to_insert_exec_catchpoint = NULL;
+ rombug_ops.to_remove_exec_catchpoint = NULL;
+ rombug_ops.to_has_execd = NULL;
+ rombug_ops.to_reported_exec_events_per_exec_call = NULL;
+ rombug_ops.to_has_exited = NULL;
+ rombug_ops.to_mourn_inferior = rombug_mourn_inferior;
+ rombug_ops.to_can_run = 0; /* can_run */
+ rombug_ops.to_notice_signals = 0; /* notice_signals */
+ rombug_ops.to_thread_alive = 0;
+ rombug_ops.to_stop = 0; /* to_stop */
+ rombug_ops.to_pid_to_exec_file = NULL;
+ rombug_ops.to_core_file_to_sym_file = NULL;
+ rombug_ops.to_stratum = process_stratum;
+ rombug_ops.DONT_USE = 0; /* next */
+ rombug_ops.to_has_all_memory = 1;
+ rombug_ops.to_has_memory = 1;
+ rombug_ops.to_has_stack = 1;
+ rombug_ops.to_has_registers = 1;
+ rombug_ops.to_has_execution = 1; /* has execution */
+ rombug_ops.to_sections = 0;
+ rombug_ops.to_sections_end = 0; /* Section pointers */
+ rombug_ops.to_magic = OPS_MAGIC; /* Always the last thing */
+}
+
+void
+_initialize_remote_os9k ()
+{
+ init_rombug_ops() ;
+ add_target (&rombug_ops);
+
+ add_show_from_set (
+ add_set_cmd ("hash", no_class, var_boolean, (char *)&hashmark,
+ "Set display of activity while downloading a file.\nWhen enabled, a period \'.\' is displayed.",
+ &setlist),
+ &showlist);
+
+ add_show_from_set (
+ add_set_cmd ("timeout", no_class, var_zinteger,
+ (char *) &timeout,
+ "Set timeout in seconds for remote MIPS serial I/O.",
+ &setlist),
+ &showlist);
+
+ add_show_from_set (
+ add_set_cmd ("remotelog", no_class, var_zinteger,
+ (char *) &monitor_log,
+ "Set monitor activity log on(=1) or off(=0).",
+ &setlist),
+ &showlist);
+
+ add_show_from_set (
+ add_set_cmd ("remotexon", no_class, var_zinteger,
+ (char *) &tty_xon,
+ "Set remote tty line XON control",
+ &setlist),
+ &showlist);
+
+ add_show_from_set (
+ add_set_cmd ("remotexoff", no_class, var_zinteger,
+ (char *) &tty_xoff,
+ "Set remote tty line XOFF control",
+ &setlist),
+ &showlist);
+
+ add_com ("rombug <command>", class_obscure, rombug_command,
+ "Send a command to the debug monitor.");
+#if 0
+ add_com ("connect", class_obscure, connect_command,
+ "Connect the terminal directly up to a serial based command monitor.\nUse <CR>~. or <CR>~^D to break out.");
+#endif
+}
diff --git a/gdb/remote-rdi.c b/gdb/remote-rdi.c
new file mode 100644
index 00000000000..dba920e36f2
--- /dev/null
+++ b/gdb/remote-rdi.c
@@ -0,0 +1,973 @@
+/* GDB interface to ARM RDI library.
+ Copyright 1997, 1998 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "gdb_string.h"
+#include <fcntl.h>
+#include "frame.h"
+#include "inferior.h"
+#include "bfd.h"
+#include "symfile.h"
+#include "target.h"
+#include "wait.h"
+#include "gdbcmd.h"
+#include "objfiles.h"
+#include "gdb-stabs.h"
+#include "gdbthread.h"
+#include "gdbcore.h"
+
+#ifdef USG
+#include <sys/types.h>
+#endif
+
+#include <signal.h>
+
+#include "rdi-share/ardi.h"
+#include "rdi-share/adp.h"
+#include "rdi-share/hsys.h"
+
+extern int isascii PARAMS ((int));
+
+/* Prototypes for local functions */
+
+static void arm_rdi_files_info PARAMS ((struct target_ops *ignore));
+
+static int arm_rdi_xfer_memory PARAMS ((CORE_ADDR memaddr, char *myaddr,
+ int len, int should_write,
+ struct target_ops *target));
+
+static void arm_rdi_prepare_to_store PARAMS ((void));
+
+static void arm_rdi_fetch_registers PARAMS ((int regno));
+
+static void arm_rdi_resume PARAMS ((int pid, int step,
+ enum target_signal siggnal));
+
+static int arm_rdi_start_remote PARAMS ((char *dummy));
+
+static void arm_rdi_open PARAMS ((char *name, int from_tty));
+
+static void arm_rdi_create_inferior PARAMS ((char *exec_file, char *args,
+ char **env));
+
+static void arm_rdi_close PARAMS ((int quitting));
+
+static void arm_rdi_store_registers PARAMS ((int regno));
+
+static void arm_rdi_mourn PARAMS ((void));
+
+static void arm_rdi_send PARAMS ((char *buf));
+
+static int arm_rdi_wait PARAMS ((int pid, struct target_waitstatus *status));
+
+static void arm_rdi_kill PARAMS ((void));
+
+static void arm_rdi_detach PARAMS ((char *args, int from_tty));
+
+static void arm_rdi_interrupt PARAMS ((int signo));
+
+static void arm_rdi_interrupt_twice PARAMS ((int signo));
+
+static void interrupt_query PARAMS ((void));
+
+static int arm_rdi_insert_breakpoint PARAMS ((CORE_ADDR, char *));
+
+static int arm_rdi_remove_breakpoint PARAMS ((CORE_ADDR, char *));
+
+static char *rdi_error_message PARAMS ((int err));
+
+static enum target_signal rdi_error_signal PARAMS ((int err));
+
+/* Global variables. */
+
+struct target_ops arm_rdi_ops;
+
+static struct Dbg_ConfigBlock gdb_config;
+
+static struct Dbg_HostosInterface gdb_hostif;
+
+static int max_load_size;
+
+static int execute_status;
+
+/* A little list of breakpoints that have been set. */
+
+static struct local_bp_list_entry {
+ CORE_ADDR addr;
+ PointHandle point;
+ struct local_bp_list_entry *next;
+} *local_bp_list;
+
+
+/* Stub for catch_errors. */
+
+static int
+arm_rdi_start_remote (dummy)
+ char *dummy;
+{
+ return 1;
+}
+
+/* Helper callbacks for the "host interface" structure. RDI functions call
+ these to forward output from the target system and so forth. */
+
+void
+voiddummy ()
+{
+ fprintf_unfiltered (gdb_stdout, "void dummy\n");
+}
+
+static void
+myprint (arg, format, ap)
+ PTR arg;
+ const char *format;
+ va_list ap;
+{
+ vfprintf_unfiltered (gdb_stdout, format, ap);
+}
+
+static void
+mywritec (arg, c)
+ PTR arg;
+ int c;
+{
+ if (isascii (c))
+ fputc_unfiltered (c, gdb_stdout);
+}
+
+static int
+mywrite (arg, buffer, len)
+ PTR arg;
+ char const *buffer;
+ int len;
+{
+ int i;
+ char *e;
+
+ e = (char *) buffer;
+ for (i = 0; i < len; i++)
+{
+ if (isascii ((int) *e))
+ {
+ fputc_unfiltered ((int) *e, gdb_stdout);
+ e++;
+ }
+}
+
+ return len;
+}
+
+static void
+mypause (arg)
+ PTR arg;
+{
+}
+
+/* These last two are tricky as we have to handle the special case of
+ being interrupted more carefully */
+
+static int
+myreadc (arg)
+ PTR arg;
+{
+ return fgetc (stdin);
+}
+
+static char *
+mygets (arg, buffer, len)
+ PTR arg;
+ char *buffer;
+ int len;
+{
+ return fgets(buffer, len, stdin);
+}
+
+/* Prevent multiple calls to angel_RDI_close(). */
+static int closed_already = 1;
+
+/* Open a connection to a remote debugger. NAME is the filename used
+ for communication. */
+
+static void
+arm_rdi_open (name, from_tty)
+ char *name;
+ int from_tty;
+{
+ int rslt, i;
+ unsigned long arg1, arg2;
+
+ if (name == NULL)
+ error ("To open an RDI connection, you need to specify what serial\n\
+device is attached to the remote system (e.g. /dev/ttya).");
+
+ /* Make the basic low-level connection. */
+
+ rslt = Adp_OpenDevice (name, NULL, 1);
+
+ if (rslt != adp_ok)
+ error ("Could not open device \"%s\"", name);
+
+ gdb_config.bytesex = 2 | (TARGET_BYTE_ORDER == BIG_ENDIAN ? 1 : 0);
+ gdb_config.fpe = 1;
+ gdb_config.rditype = 2;
+ gdb_config.heartbeat_on = 1;
+ gdb_config.flags = 2;
+
+ gdb_hostif.dbgprint = myprint;
+ gdb_hostif.dbgpause = mypause;
+ gdb_hostif.dbgarg = NULL;
+ gdb_hostif.writec = mywritec;
+ gdb_hostif.readc = myreadc;
+ gdb_hostif.write = mywrite;
+ gdb_hostif.gets = mygets;
+ gdb_hostif.hostosarg = NULL;
+ gdb_hostif.reset = voiddummy;
+
+ rslt = angel_RDI_open (10, &gdb_config, &gdb_hostif, NULL);
+ if (rslt == RDIError_BigEndian || rslt == RDIError_LittleEndian)
+ ; /* do nothing, this is the expected return */
+ else if (rslt)
+ {
+ printf_filtered ("RDI_open: %s\n", rdi_error_message (rslt));
+ }
+
+ rslt = angel_RDI_info (RDIInfo_Target, &arg1, &arg2);
+ if (rslt)
+ {
+ printf_filtered ("RDI_info: %s\n", rdi_error_message (rslt));
+ }
+ rslt = angel_RDI_info (RDIInfo_Points, &arg1, &arg2);
+ if (rslt)
+ {
+ printf_filtered ("RDI_info: %s\n", rdi_error_message (rslt));
+ }
+ rslt = angel_RDI_info (RDIInfo_Step, &arg1, &arg2);
+ if (rslt)
+ {
+ printf_filtered ("RDI_info: %s\n", rdi_error_message (rslt));
+ }
+ rslt = angel_RDI_info (RDIInfo_CoPro, &arg1, &arg2);
+ if (rslt)
+ {
+ printf_filtered ("RDI_info: %s\n", rdi_error_message (rslt));
+ }
+ rslt = angel_RDI_info (RDIInfo_SemiHosting, &arg1, &arg2);
+ if (rslt)
+ {
+ printf_filtered ("RDI_info: %s\n", rdi_error_message (rslt));
+ }
+
+ rslt = angel_RDI_info (RDIInfo_GetLoadSize, &arg1, &arg2);
+ if (rslt)
+ {
+ printf_filtered ("RDI_info: %s\n", rdi_error_message (rslt));
+ }
+ max_load_size = arg1;
+
+ push_target (&arm_rdi_ops);
+
+ target_fetch_registers (-1);
+
+ rslt = angel_RDI_open (1, &gdb_config, NULL, NULL);
+ if (rslt)
+ {
+ printf_filtered ("RDI_open: %s\n", rdi_error_message (rslt));
+ }
+
+ arg1 = 0x13b;
+ rslt = angel_RDI_info (RDIVector_Catch, &arg1, &arg2);
+ if (rslt)
+ {
+ printf_filtered ("RDI_info: %s\n", rdi_error_message (rslt));
+ }
+
+ arg1 = (unsigned long) "";
+ rslt = angel_RDI_info (RDISet_Cmdline, &arg1, &arg2);
+ if (rslt)
+ {
+ printf_filtered ("RDI_info: %s\n", rdi_error_message (rslt));
+ }
+
+ /* Clear out any existing records of breakpoints. */
+ {
+ struct local_bp_list_entry *entry, *preventry = NULL;
+
+ for (entry = local_bp_list; entry != NULL; entry = entry->next)
+ {
+ if (preventry)
+ free (preventry);
+ }
+ }
+
+ printf_filtered ("Connected to ARM RDI target.\n");
+ closed_already = 0;
+ inferior_pid = 42;
+}
+
+/* Start an inferior process and set inferior_pid to its pid.
+ EXEC_FILE is the file to run.
+ ARGS 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. */
+/* This is called not only when we first attach, but also when the
+ user types "run" after having attached. */
+
+static void
+arm_rdi_create_inferior (exec_file, args, env)
+ char *exec_file;
+ char *args;
+ char **env;
+{
+ int len, rslt;
+ unsigned long arg1, arg2;
+ char *arg_buf;
+ CORE_ADDR entry_point;
+
+ if (exec_file == 0 || exec_bfd == 0)
+ error ("No executable file specified.");
+
+ entry_point = (CORE_ADDR) bfd_get_start_address (exec_bfd);
+
+ arm_rdi_kill ();
+ remove_breakpoints ();
+ init_wait_for_inferior ();
+
+ len = strlen (exec_file) + 1 + strlen (args) + 1 + /*slop*/ 10;
+ arg_buf = (char *) alloca (len);
+ arg_buf[0] = '\0';
+ strcat (arg_buf, exec_file);
+ strcat (arg_buf, " ");
+ strcat (arg_buf, args);
+
+ inferior_pid = 42;
+ insert_breakpoints (); /* Needed to get correct instruction in cache */
+
+ if (env != NULL)
+ {
+ while (*env)
+ {
+ if (strncmp (*env, "MEMSIZE=", sizeof ("MEMSIZE=") - 1) == 0)
+ {
+ unsigned long top_of_memory;
+ char *end_of_num;
+
+ /* Set up memory limit */
+ top_of_memory = strtoul (*env + sizeof ("MEMSIZE=") - 1,
+ &end_of_num, 0);
+ printf_filtered ("Setting top-of-memory to 0x%x\n",
+ top_of_memory);
+
+ rslt = angel_RDI_info (RDIInfo_SetTopMem, &top_of_memory, &arg2);
+ if (rslt)
+ {
+ printf_filtered ("RDI_info: %s\n", rdi_error_message (rslt));
+ }
+ }
+ env++;
+ }
+ }
+
+ arg1 = (unsigned long) arg_buf;
+ rslt = angel_RDI_info (RDISet_Cmdline, /* &arg1 */ (unsigned long *)arg_buf, &arg2);
+ if (rslt)
+ {
+ printf_filtered ("RDI_info: %s\n", rdi_error_message (rslt));
+ }
+
+ proceed (entry_point, TARGET_SIGNAL_DEFAULT, 0);
+}
+
+/* This takes a program previously attached to and detaches it. After
+ this is done, GDB can be used to debug some other program. We
+ better not have left any breakpoints in the target program or it'll
+ die when it hits one. */
+
+static void
+arm_rdi_detach (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ pop_target ();
+}
+
+/* Clean up connection to a remote debugger. */
+
+static void
+arm_rdi_close (quitting)
+ int quitting;
+{
+ int rslt;
+
+ if (! closed_already)
+ {
+ rslt = angel_RDI_close ();
+ if (rslt)
+ {
+ printf_filtered ("RDI_close: %s\n", rdi_error_message (rslt));
+ }
+ closed_already = 1;
+ inferior_pid = 0;
+ }
+}
+
+/* Tell the remote machine to resume. */
+
+static void
+arm_rdi_resume (pid, step, siggnal)
+ int pid, step;
+ enum target_signal siggnal;
+{
+ int rslt;
+ PointHandle point;
+
+ if (0 /* turn on when hardware supports single-stepping */)
+ {
+ rslt = angel_RDI_step (1, &point);
+ if (rslt)
+ {
+ printf_filtered ("RDI_step: %s\n", rdi_error_message (rslt));
+ }
+ }
+ else
+ {
+ char handle[4];
+ CORE_ADDR pc;
+
+ if (step)
+ {
+ pc = read_register (PC_REGNUM);
+ pc = arm_get_next_pc (pc);
+ arm_rdi_insert_breakpoint (pc, handle);
+ }
+ execute_status = rslt = angel_RDI_execute (&point);
+ if (rslt == RDIError_BreakpointReached)
+ ;
+ else if (rslt)
+ {
+ printf_filtered ("RDI_execute: %s\n", rdi_error_message (rslt));
+ }
+ if (step)
+ {
+ arm_rdi_remove_breakpoint (pc, handle);
+ }
+ }
+}
+
+/* Send ^C to target to halt it. Target will respond, and send us a
+ packet. */
+
+static void
+arm_rdi_interrupt (signo)
+ int signo;
+{
+}
+
+static void (*ofunc)();
+
+/* The user typed ^C twice. */
+static void
+arm_rdi_interrupt_twice (signo)
+ int signo;
+{
+}
+
+/* Ask the user what to do when an interrupt is received. */
+
+static void
+interrupt_query ()
+{
+}
+
+/* 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
+arm_rdi_wait (pid, status)
+ int pid;
+ struct target_waitstatus *status;
+{
+ status->kind = (execute_status == RDIError_NoError ?
+ TARGET_WAITKIND_EXITED : TARGET_WAITKIND_STOPPED);
+
+ /* convert stopped code from target into right signal */
+ status->value.sig = rdi_error_signal (execute_status);
+
+ return inferior_pid;
+}
+
+/* Read the remote registers into the block REGS. */
+
+/* ARGSUSED */
+static void
+arm_rdi_fetch_registers (regno)
+ int regno;
+{
+ int rslt, rdi_regmask;
+ unsigned long rawreg, rawregs[32];
+ char cookedreg[4];
+
+ if (regno == -1)
+ {
+ rslt = angel_RDI_CPUread (255, 0x27fff, rawregs);
+ if (rslt)
+ {
+ printf_filtered ("RDI_CPUread: %s\n", rdi_error_message (rslt));
+ }
+
+ for (regno = 0; regno < 15; regno++)
+ {
+ store_unsigned_integer (cookedreg, 4, rawregs[regno]);
+ supply_register (regno, (char *) cookedreg);
+ }
+ store_unsigned_integer (cookedreg, 4, rawregs[15]);
+ supply_register (PS_REGNUM, (char *) cookedreg);
+ arm_rdi_fetch_registers (PC_REGNUM);
+ }
+ else
+ {
+ if (regno == PC_REGNUM)
+ rdi_regmask = RDIReg_PC;
+ else if (regno == PS_REGNUM)
+ rdi_regmask = RDIReg_CPSR;
+ else if (regno < 0 || regno > 15)
+ {
+ rawreg = 0;
+ supply_register (regno, (char *) &rawreg);
+ return;
+ }
+ else
+ rdi_regmask = 1 << regno;
+
+ rslt = angel_RDI_CPUread (255, rdi_regmask, &rawreg);
+ if (rslt)
+ {
+ printf_filtered ("RDI_CPUread: %s\n", rdi_error_message (rslt));
+ }
+ store_unsigned_integer (cookedreg, 4, rawreg);
+ supply_register (regno, (char *) cookedreg);
+ }
+}
+
+static void
+arm_rdi_prepare_to_store ()
+{
+ /* Nothing to do. */
+}
+
+/* Store register REGNO, or all registers if REGNO == -1, from the contents
+ of REGISTERS. FIXME: ignores errors. */
+
+static void
+arm_rdi_store_registers (regno)
+ int regno;
+{
+ int rslt, rdi_regmask;
+
+ /* These need to be able to take 'floating point register' contents */
+ unsigned long rawreg[3], rawerreg[3];
+
+ if (regno == -1)
+ {
+ for (regno = 0; regno < NUM_REGS; regno++)
+ arm_rdi_store_registers (regno);
+ }
+ else
+ {
+ read_register_gen (regno, (char *) rawreg);
+ /* RDI manipulates data in host byte order, so convert now. */
+ store_unsigned_integer (rawerreg, 4, rawreg[0]);
+
+ if (regno == PC_REGNUM)
+ rdi_regmask = RDIReg_PC;
+ else if (regno == PS_REGNUM)
+ rdi_regmask = RDIReg_CPSR;
+ else if (regno < 0 || regno > 15)
+ return;
+ else
+ rdi_regmask = 1 << regno;
+
+ rslt = angel_RDI_CPUwrite (255, rdi_regmask, rawerreg);
+ if (rslt)
+ {
+ printf_filtered ("RDI_CPUwrite: %s\n", rdi_error_message (rslt));
+ }
+ }
+}
+
+/* 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
+arm_rdi_xfer_memory(memaddr, myaddr, len, should_write, target)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+ int should_write;
+ struct target_ops *target; /* ignored */
+{
+ int rslt, i;
+
+ if (should_write)
+ {
+ rslt = angel_RDI_write (myaddr, memaddr, &len);
+ if (rslt)
+ {
+ printf_filtered ("RDI_write: %s\n", rdi_error_message (rslt));
+ }
+ }
+ else
+ {
+ rslt = angel_RDI_read (memaddr, myaddr, &len);
+ if (rslt)
+ {
+ printf_filtered ("RDI_read: %s\n", rdi_error_message (rslt));
+ len = 0;
+ }
+ }
+ return len;
+}
+
+/* Display random info collected from the target. */
+
+static void
+arm_rdi_files_info (ignore)
+ struct target_ops *ignore;
+{
+ char *file = "nothing";
+ int rslt;
+ unsigned long arg1, arg2;
+
+ rslt = angel_RDI_info (RDIInfo_Target, &arg1, &arg2);
+ if (rslt)
+ {
+ printf_filtered ("RDI_info: %s\n", rdi_error_message (rslt));
+ }
+ if (arg1 & (1 << 15))
+ printf_filtered ("Target supports Thumb code.\n");
+ if (arg1 & (1 << 14))
+ printf_filtered ("Target can do profiling.\n");
+ if (arg1 & (1 << 4))
+ printf_filtered ("Target is real hardware.\n");
+
+ rslt = angel_RDI_info (RDIInfo_Step, &arg1, &arg2);
+ if (rslt)
+ {
+ printf_filtered ("RDI_info: %s\n", rdi_error_message (rslt));
+ }
+ printf_filtered ("Target can%s single-step.\n", (arg1 & 0x4 ? "" : "not"));
+
+ rslt = angel_RDI_info (RDIInfo_Icebreaker, &arg1, &arg2);
+ if (rslt)
+ {
+ printf_filtered ("RDI_info: %s\n", rdi_error_message (rslt));
+ }
+ else
+ printf_filtered ("Target includes an EmbeddedICE.\n");
+}
+
+static void
+arm_rdi_kill ()
+{
+ int rslt;
+
+ rslt = angel_RDI_open (1, &gdb_config, NULL, NULL);
+ if (rslt)
+ {
+ printf_filtered ("RDI_open: %s\n", rdi_error_message (rslt));
+ }
+}
+
+static void
+arm_rdi_mourn_inferior ()
+{
+ unpush_target (&arm_rdi_ops);
+ generic_mourn_inferior ();
+}
+
+/* While the RDI library keeps track of its own breakpoints, we need
+ to remember "handles" so that we can delete them later. Since
+ breakpoints get used for stepping, be careful not to leak memory
+ here. */
+
+static int
+arm_rdi_insert_breakpoint (addr, contents_cache)
+ CORE_ADDR addr;
+ char *contents_cache;
+{
+ int rslt;
+ PointHandle point;
+ struct local_bp_list_entry *entry;
+ int type = RDIPoint_EQ;
+
+ if (arm_pc_is_thumb (addr) || arm_pc_is_thumb_dummy (addr))
+ type |= RDIPoint_16Bit;
+ rslt = angel_RDI_setbreak (addr, type, 0, &point);
+ if (rslt)
+ {
+ printf_filtered ("RDI_setbreak: %s\n", rdi_error_message (rslt));
+ }
+ entry =
+ (struct local_bp_list_entry *) xmalloc (sizeof (struct local_bp_list_entry));
+ entry->addr = addr;
+ entry->point = point;
+ entry->next = local_bp_list;
+ local_bp_list = entry;
+ return rslt;
+}
+
+static int
+arm_rdi_remove_breakpoint (addr, contents_cache)
+ CORE_ADDR addr;
+ char *contents_cache;
+{
+ int rslt;
+ PointHandle point;
+ struct local_bp_list_entry *entry, *preventry;
+
+ for (entry = local_bp_list; entry != NULL; entry = entry->next)
+ {
+ if (entry->addr == addr)
+ {
+ break;
+ }
+ preventry = entry;
+ }
+ if (entry)
+ {
+ rslt = angel_RDI_clearbreak (entry->point);
+ if (rslt)
+ {
+ printf_filtered ("RDI_clearbreak: %s\n", rdi_error_message (rslt));
+ }
+ /* Delete the breakpoint entry locally. */
+ if (entry == local_bp_list)
+ {
+ local_bp_list = entry->next;
+ }
+ else
+ {
+ preventry->next = entry->next;
+ }
+ free (entry);
+ }
+ return 0;
+}
+
+static char *
+rdi_error_message (err)
+ int err;
+{
+ switch (err)
+ {
+ case RDIError_NoError:
+ return "no error";
+ case RDIError_Reset:
+ return "debuggee reset";
+ case RDIError_UndefinedInstruction:
+ return "undefined instruction";
+ case RDIError_SoftwareInterrupt:
+ return "SWI trapped";
+ case RDIError_PrefetchAbort:
+ return "prefetch abort, execution ran into unmapped memory?";
+ case RDIError_DataAbort:
+ return "data abort, no memory at specified address?";
+ case RDIError_AddressException:
+ return "address exception, access >26bit in 26bit mode";
+ case RDIError_IRQ:
+ return "IRQ, interrupt trapped";
+ case RDIError_FIQ:
+ return "FIQ, fast interrupt trapped";
+ case RDIError_Error:
+ return "a miscellaneous type of error";
+ case RDIError_BranchThrough0:
+ return "branch through location 0";
+ case RDIError_NotInitialised:
+ return "internal error, RDI_open not called first";
+ case RDIError_UnableToInitialise:
+ return "internal error, target world is broken";
+ case RDIError_WrongByteSex:
+ return "See Operator: WrongByteSex";
+ case RDIError_UnableToTerminate:
+ return "See Operator: Unable to Terminate";
+ case RDIError_BadInstruction:
+ return "bad instruction, illegal to execute this instruction";
+ case RDIError_IllegalInstruction:
+ return "illegal instruction, the effect of executing it is undefined";
+ case RDIError_BadCPUStateSetting:
+ return "internal error, tried to set SPSR of user mode";
+ case RDIError_UnknownCoPro:
+ return "unknown co-processor";
+ case RDIError_UnknownCoProState:
+ return "cannot execute co-processor request";
+ case RDIError_BadCoProState:
+ return "recognizably broken co-processor request";
+ case RDIError_BadPointType:
+ return "internal error, bad point yype";
+ case RDIError_UnimplementedType:
+ return "internal error, unimplemented type";
+ case RDIError_BadPointSize:
+ return "internal error, bad point size";
+ case RDIError_UnimplementedSize:
+ return "internal error, unimplemented size";
+ case RDIError_NoMorePoints:
+ return "last break/watch point was used";
+ case RDIError_BreakpointReached:
+ return "breakpoint reached";
+ case RDIError_WatchpointAccessed:
+ return "watchpoint accessed";
+ case RDIError_NoSuchPoint:
+ return "attempted to clear non-existent break/watch point";
+ case RDIError_ProgramFinishedInStep:
+ return "end of the program reached while stepping";
+ case RDIError_UserInterrupt:
+ return "you pressed Escape";
+ case RDIError_CantSetPoint:
+ return "no more break/watch points available";
+ case RDIError_IncompatibleRDILevels:
+ return "incompatible RDI levels";
+ case RDIError_LittleEndian:
+ return "debuggee is little endian";
+ case RDIError_BigEndian:
+ return "debuggee is big endian";
+ case RDIError_SoftInitialiseError:
+ return "recoverable error in RDI initialization";
+ case RDIError_InsufficientPrivilege:
+ return "internal error, supervisor state not accessible to monitor";
+ case RDIError_UnimplementedMessage:
+ return "internal error, unimplemented message";
+ case RDIError_UndefinedMessage:
+ return "internal error, undefined message";
+ default:
+ return "undefined error message, should reset target";
+ }
+}
+
+/* Convert the ARM error messages to signals that GDB knows about. */
+
+static enum target_signal
+rdi_error_signal (err)
+ int err;
+{
+ switch (err)
+ {
+ case RDIError_NoError:
+ return 0;
+ case RDIError_Reset:
+ return TARGET_SIGNAL_TERM; /* ??? */
+ case RDIError_UndefinedInstruction:
+ return TARGET_SIGNAL_ILL;
+ case RDIError_SoftwareInterrupt:
+ case RDIError_PrefetchAbort:
+ case RDIError_DataAbort:
+ return TARGET_SIGNAL_TRAP;
+ case RDIError_AddressException:
+ return TARGET_SIGNAL_SEGV;
+ case RDIError_IRQ:
+ case RDIError_FIQ:
+ return TARGET_SIGNAL_TRAP;
+ case RDIError_Error:
+ return TARGET_SIGNAL_TERM;
+ case RDIError_BranchThrough0:
+ return TARGET_SIGNAL_TRAP;
+ case RDIError_NotInitialised:
+ case RDIError_UnableToInitialise:
+ case RDIError_WrongByteSex:
+ case RDIError_UnableToTerminate:
+ return TARGET_SIGNAL_UNKNOWN;
+ case RDIError_BadInstruction:
+ case RDIError_IllegalInstruction:
+ return TARGET_SIGNAL_ILL;
+ case RDIError_BadCPUStateSetting:
+ case RDIError_UnknownCoPro:
+ case RDIError_UnknownCoProState:
+ case RDIError_BadCoProState:
+ case RDIError_BadPointType:
+ case RDIError_UnimplementedType:
+ case RDIError_BadPointSize:
+ case RDIError_UnimplementedSize:
+ case RDIError_NoMorePoints:
+ return TARGET_SIGNAL_UNKNOWN;
+ case RDIError_BreakpointReached:
+ case RDIError_WatchpointAccessed:
+ return TARGET_SIGNAL_TRAP;
+ case RDIError_NoSuchPoint:
+ case RDIError_ProgramFinishedInStep:
+ return TARGET_SIGNAL_UNKNOWN;
+ case RDIError_UserInterrupt:
+ return TARGET_SIGNAL_INT;
+ case RDIError_IncompatibleRDILevels:
+ case RDIError_LittleEndian:
+ case RDIError_BigEndian:
+ case RDIError_SoftInitialiseError:
+ case RDIError_InsufficientPrivilege:
+ case RDIError_UnimplementedMessage:
+ case RDIError_UndefinedMessage:
+ default:
+ return TARGET_SIGNAL_UNKNOWN;
+ }
+}
+
+/* Define the target operations structure. */
+
+static void
+init_rdi_ops ()
+{
+ arm_rdi_ops.to_shortname = "rdi";
+ arm_rdi_ops.to_longname = "ARM RDI";
+ arm_rdi_ops.to_doc = "Use a remote ARM-based computer; via the RDI library.\n\
+Specify the serial device it is connected to (e.g. /dev/ttya)." ;
+ arm_rdi_ops.to_open = arm_rdi_open;
+ arm_rdi_ops.to_close = arm_rdi_close;
+ arm_rdi_ops.to_detach = arm_rdi_detach;
+ arm_rdi_ops.to_resume = arm_rdi_resume;
+ arm_rdi_ops.to_wait = arm_rdi_wait;
+ arm_rdi_ops.to_fetch_registers = arm_rdi_fetch_registers;
+ arm_rdi_ops.to_store_registers = arm_rdi_store_registers;
+ arm_rdi_ops.to_prepare_to_store = arm_rdi_prepare_to_store;
+ arm_rdi_ops.to_xfer_memory = arm_rdi_xfer_memory;
+ arm_rdi_ops.to_files_info = arm_rdi_files_info;
+ arm_rdi_ops.to_insert_breakpoint = arm_rdi_insert_breakpoint;
+ arm_rdi_ops.to_remove_breakpoint = arm_rdi_remove_breakpoint;
+ arm_rdi_ops.to_kill = arm_rdi_kill;
+ arm_rdi_ops.to_load = generic_load;
+ arm_rdi_ops.to_create_inferior = arm_rdi_create_inferior;
+ arm_rdi_ops.to_mourn_inferior = arm_rdi_mourn_inferior;
+ arm_rdi_ops.to_stratum = process_stratum;
+ arm_rdi_ops.to_has_all_memory = 1;
+ arm_rdi_ops.to_has_memory = 1;
+ arm_rdi_ops.to_has_stack = 1;
+ arm_rdi_ops.to_has_registers = 1;
+ arm_rdi_ops.to_has_execution = 1;
+ arm_rdi_ops.to_magic = OPS_MAGIC;
+}
+
+void
+_initialize_remote_rdi ()
+{
+ init_rdi_ops () ;
+ add_target (&arm_rdi_ops);
+}
+
+/* A little dummy to make linking with the library succeed. */
+
+int Fail() { return 0; }
diff --git a/gdb/remote-rdp.c b/gdb/remote-rdp.c
new file mode 100644
index 00000000000..1d596a42c1f
--- /dev/null
+++ b/gdb/remote-rdp.c
@@ -0,0 +1,1512 @@
+/* Remote debugging for the ARM RDP interface.
+ Copyright 1994, 1995 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+
+ */
+
+
+/*
+ Much of this file (in particular the SWI stuff) is based on code by
+ David Taylor (djt1000@uk.ac.cam.hermes).
+
+ I hacked on and simplified it by removing a lot of sexy features he
+ had added, and some of the (unix specific) workarounds he'd done
+ for other GDB problems - which if they still exist should be fixed
+ in GDB, not in a remote-foo thing . I also made it conform more to
+ the doc I have; which may be wrong.
+
+ Steve Chamberlain (sac@cygnus.com).
+ */
+
+
+#include "defs.h"
+#include "inferior.h"
+#include "wait.h"
+#include "value.h"
+#include "callback.h"
+#include "command.h"
+#ifdef ANSI_PROTOTYPES
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+#include <ctype.h>
+#include <fcntl.h>
+#include "symfile.h"
+#include "remote-utils.h"
+#include "gdb_string.h"
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include "gdbcore.h"
+
+
+extern struct target_ops remote_rdp_ops;
+static serial_t io;
+static host_callback *callback = &default_callback;
+
+struct
+ {
+ int step_info;
+ int break_info;
+ int model_info;
+ int target_info;
+ int can_step;
+ char command_line[10];
+ int rdi_level;
+ int rdi_stopped_status;
+ }
+ds;
+
+
+
+/* Definitions for the RDP protocol. */
+
+#define RDP_MOUTHFULL (1<<6)
+#define FPU_COPRO_NUMBER 1
+
+#define RDP_OPEN 0
+#define RDP_OPEN_TYPE_COLD 0
+#define RDP_OPEN_TYPE_WARM 1
+#define RDP_OPEN_TYPE_BAUDRATE 2
+
+#define RDP_OPEN_BAUDRATE_9600 1
+#define RDP_OPEN_BAUDRATE_19200 2
+#define RDP_OPEN_BAUDRATE_38400 3
+
+#define RDP_OPEN_TYPE_RETURN_SEX (1<<3)
+
+#define RDP_CLOSE 1
+
+#define RDP_MEM_READ 2
+
+#define RDP_MEM_WRITE 3
+
+#define RDP_CPU_READ 4
+#define RDP_CPU_WRITE 5
+#define RDP_CPU_READWRITE_MODE_CURRENT 255
+#define RDP_CPU_READWRITE_MASK_PC (1<<16)
+#define RDP_CPU_READWRITE_MASK_CPSR (1<<17)
+#define RDP_CPU_READWRITE_MASK_SPSR (1<<18)
+
+#define RDP_COPRO_READ 6
+#define RDP_COPRO_WRITE 7
+#define RDP_FPU_READWRITE_MASK_FPS (1<<8)
+
+#define RDP_SET_BREAK 0xa
+#define RDP_SET_BREAK_TYPE_PC_EQUAL 0
+#define RDP_SET_BREAK_TYPE_GET_HANDLE (0x10)
+
+#define RDP_CLEAR_BREAK 0xb
+
+#define RDP_EXEC 0x10
+#define RDP_EXEC_TYPE_SYNC 0
+
+#define RDP_STEP 0x11
+
+#define RDP_INFO 0x12
+#define RDP_INFO_ABOUT_STEP 2
+#define RDP_INFO_ABOUT_STEP_GT_1 1
+#define RDP_INFO_ABOUT_STEP_TO_JMP 2
+#define RDP_INFO_ABOUT_STEP_1 4
+#define RDP_INFO_ABOUT_TARGET 0
+#define RDP_INFO_ABOUT_BREAK 1
+#define RDP_INFO_ABOUT_BREAK_COMP 1
+#define RDP_INFO_ABOUT_BREAK_RANGE 2
+#define RDP_INFO_ABOUT_BREAK_BYTE_READ 4
+#define RDP_INFO_ABOUT_BREAK_HALFWORD_READ 8
+#define RDP_INFO_ABOUT_BREAK_WORD_READ (1<<4)
+#define RDP_INFO_ABOUT_BREAK_BYTE_WRITE (1<<5)
+#define RDP_INFO_ABOUT_BREAK_HALFWORD_WRITE (1<<6)
+#define RDP_INFO_ABOUT_BREAK_WORD_WRITE (1<<7)
+#define RDP_INFO_ABOUT_BREAK_MASK (1<<8)
+#define RDP_INFO_ABOUT_BREAK_THREAD_BREAK (1<<9)
+#define RDP_INFO_ABOUT_BREAK_THREAD_WATCH (1<<10)
+#define RDP_INFO_ABOUT_BREAK_COND (1<<11)
+#define RDP_INFO_VECTOR_CATCH (0x180)
+#define RDP_INFO_ICEBREAKER (7)
+#define RDP_INFO_SET_CMDLINE (0x300)
+
+#define RDP_SELECT_CONFIG (0x16)
+#define RDI_ConfigCPU 0
+#define RDI_ConfigSystem 1
+#define RDI_MatchAny 0
+#define RDI_MatchExactly 1
+#define RDI_MatchNoEarlier 2
+
+#define RDP_RESET 0x7f
+
+/* Returns from RDP */
+#define RDP_RES_STOPPED 0x20
+#define RDP_RES_SWI 0x21
+#define RDP_RES_FATAL 0x5e
+#define RDP_RES_VALUE 0x5f
+#define RDP_RES_VALUE_LITTLE_ENDIAN 240
+#define RDP_RES_VALUE_BIG_ENDIAN 241
+#define RDP_RES_RESET 0x7f
+#define RDP_RES_AT_BREAKPOINT 143
+#define RDP_RES_IDUNNO 0xe6
+#define RDP_OSOpReply 0x13
+#define RDP_OSOpWord 2
+#define RDP_OSOpNothing 0
+
+static int timeout = 2;
+
+static char * commandline = NULL;
+
+static int
+remote_rdp_xfer_inferior_memory PARAMS ((CORE_ADDR memaddr,
+ char *myaddr,
+ int len,
+ int write,
+ struct target_ops * target));
+
+
+/* Stuff for talking to the serial layer. */
+
+static unsigned char
+get_byte ()
+{
+ int c = SERIAL_READCHAR (io, timeout);
+
+ if (remote_debug)
+ printf ("[%02x]\n", c);
+
+ if (c == SERIAL_TIMEOUT)
+ {
+ if (timeout == 0)
+ return (unsigned char) c;
+
+ error ("Timeout reading from remote_system");
+ }
+
+ return c;
+}
+
+/* Note that the target always speaks little-endian to us,
+ even if it's a big endian machine. */
+static unsigned int
+get_word ()
+{
+ unsigned int val = 0;
+ unsigned int c;
+ int n;
+ for (n = 0; n < 4; n++)
+ {
+ c = get_byte ();
+ val |= c << (n * 8);
+ }
+ return val;
+}
+
+static void
+put_byte (val)
+ char val;
+{
+ if (remote_debug)
+ printf ("(%02x)\n", val);
+ SERIAL_WRITE (io, &val, 1);
+}
+
+static void
+put_word (val)
+ int val;
+{
+ /* We always send in little endian */
+ unsigned char b[4];
+ b[0] = val;
+ b[1] = val >> 8;
+ b[2] = val >> 16;
+ b[3] = val >> 24;
+
+ if (remote_debug)
+ printf ("(%04x)", val);
+
+ SERIAL_WRITE (io, b, 4);
+}
+
+
+
+/* Stuff for talking to the RDP layer. */
+
+/* This is a bit more fancy that need be so that it syncs even in nasty cases.
+
+ I'be been unable to make it reliably sync up with the change
+ baudrate open command. It likes to sit and say it's been reset,
+ with no more action. So I took all that code out. I'd rather sync
+ reliably at 9600 than wait forever for a possible 19200 connection.
+
+ */
+static void
+rdp_init (cold, tty)
+ int cold;
+ int tty;
+{
+ int sync = 0;
+ int type = cold ? RDP_OPEN_TYPE_COLD : RDP_OPEN_TYPE_WARM;
+ int baudtry = 9600;
+
+ time_t now = time (0);
+ time_t stop_time = now + 10; /* Try and sync for 10 seconds, then give up */
+
+
+ while (time (0) < stop_time && !sync)
+ {
+ int restype;
+ QUIT;
+
+ SERIAL_FLUSH_INPUT (io);
+ SERIAL_FLUSH_OUTPUT (io);
+
+ if (tty)
+ printf_unfiltered ("Trying to connect at %d baud.\n", baudtry);
+
+ /*
+ ** It seems necessary to reset an EmbeddedICE to get it going.
+ ** This has the side benefit of displaying the startup banner.
+ */
+ if (cold)
+ {
+ put_byte (RDP_RESET);
+ while ((restype = SERIAL_READCHAR (io, 1)) > 0)
+ {
+ switch (restype)
+ {
+ case SERIAL_TIMEOUT:
+ break;
+ case RDP_RESET:
+ /* Sent at start of reset process: ignore */
+ break;
+ default:
+ printf_unfiltered ("%c", isgraph (restype) ? restype : ' ');
+ break;
+ }
+ }
+
+ if (restype == 0)
+ {
+ /* Got end-of-banner mark */
+ printf_filtered ("\n");
+ }
+ }
+
+ put_byte (RDP_OPEN);
+
+ put_byte (type | RDP_OPEN_TYPE_RETURN_SEX );
+ put_word (0);
+
+ while (!sync && (restype = SERIAL_READCHAR (io, 1)) > 0)
+ {
+ if (remote_debug)
+ printf_unfiltered ("[%02x]\n", restype);
+
+ switch (restype)
+ {
+ case SERIAL_TIMEOUT:
+ break;
+
+ case RDP_RESET:
+ while ((restype = SERIAL_READCHAR (io, 1)) == RDP_RESET)
+ ;
+ do
+ {
+ printf_unfiltered ("%c", isgraph (restype) ? restype : ' ');
+ }
+ while ((restype = SERIAL_READCHAR (io, 1)) > 0);
+
+ if (tty)
+ {
+ printf_unfiltered ("\nThe board has sent notification that it was reset.\n");
+ printf_unfiltered ("Waiting for it to settle down...\n");
+ }
+ sleep (3);
+ if (tty)
+ printf_unfiltered ("\nTrying again.\n");
+ cold = 0;
+ break;
+
+ default:
+ break;
+
+ case RDP_RES_VALUE:
+ {
+ int resval = SERIAL_READCHAR (io, 1);
+
+ if (remote_debug)
+ printf_unfiltered ("[%02x]\n", resval);
+
+ switch (resval)
+ {
+ case SERIAL_TIMEOUT:
+ break;
+ case RDP_RES_VALUE_LITTLE_ENDIAN:
+ target_byte_order = LITTLE_ENDIAN;
+ sync = 1;
+ break;
+ case RDP_RES_VALUE_BIG_ENDIAN:
+ target_byte_order = BIG_ENDIAN;
+ sync = 1;
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ if (!sync)
+ {
+ error ("Couldn't reset the board, try pressing the reset button");
+ }
+}
+
+
+#ifdef ANSI_PROTOTYPES
+void
+send_rdp (char *template,...)
+#else
+void
+send_rdp (char *template, va_alist)
+ va_dcl
+#endif
+{
+ char buf[200];
+ char *dst = buf;
+ va_list alist;
+#ifdef ANSI_PROTOTYPES
+ va_start (alist, template);
+#else
+ va_start (alist);
+#endif
+
+ while (*template)
+ {
+ unsigned int val;
+ int *pi;
+ int *pstat;
+ char *pc;
+ int i;
+ switch (*template++)
+ {
+ case 'b':
+ val = va_arg (alist, int);
+ *dst++ = val;
+ break;
+ case 'w':
+ val = va_arg (alist, int);
+ *dst++ = val;
+ *dst++ = val >> 8;
+ *dst++ = val >> 16;
+ *dst++ = val >> 24;
+ break;
+ case 'S':
+ val = get_byte ();
+ if (val != RDP_RES_VALUE)
+ {
+ printf_unfiltered ("got bad res value of %d, %x\n", val, val);
+ }
+ break;
+ case 'V':
+ pstat = va_arg (alist, int *);
+ pi = va_arg (alist, int *);
+
+ *pstat = get_byte ();
+ /* Check the result was zero, if not read the syndrome */
+ if (*pstat)
+ {
+ *pi = get_word ();
+ }
+ break;
+ case 'Z':
+ /* Check the result code */
+ switch (get_byte ())
+ {
+ case 0:
+ /* Success */
+ break;
+ case 253:
+ /* Target can't do it; never mind */
+ printf_unfiltered ("RDP: Insufficient privilege\n");
+ return;
+ case 254:
+ /* Target can't do it; never mind */
+ printf_unfiltered ("RDP: Unimplemented message\n");
+ return;
+ case 255:
+ error ("Command garbled");
+ break;
+ default:
+ error ("Corrupt reply from target");
+ break;
+ }
+ break;
+ case 'W':
+ /* Read a word from the target */
+ pi = va_arg (alist, int *);
+ *pi = get_word ();
+ break;
+ case 'P':
+ /* Read in some bytes from the target. */
+ pc = va_arg (alist, char *);
+ val = va_arg (alist, int);
+ for (i = 0; i < val; i++)
+ {
+ pc[i] = get_byte ();
+ }
+ break;
+ case 'p':
+ /* send what's being pointed at */
+ pc = va_arg (alist, char *);
+ val = va_arg (alist, int);
+ dst = buf;
+ SERIAL_WRITE (io, pc, val);
+ break;
+ case '-':
+ /* Send whats in the queue */
+ if (dst != buf)
+ {
+ SERIAL_WRITE (io, buf, dst - buf);
+ dst = buf;
+ }
+ break;
+ case 'B':
+ pi = va_arg (alist, int *);
+ *pi = get_byte ();
+ break;
+ default:
+ abort ();
+ }
+ }
+ va_end (args);
+
+ if (dst != buf)
+ abort ();
+}
+
+
+static int
+rdp_write (memaddr, buf, len)
+ CORE_ADDR memaddr;
+ char *buf;
+ int len;
+{
+ int res;
+ int val;
+
+ send_rdp ("bww-p-SV", RDP_MEM_WRITE, memaddr, len, buf, len, &res, &val);
+
+ if (res)
+ {
+ return val;
+ }
+ return len;
+}
+
+
+static int
+rdp_read (memaddr, buf, len)
+ CORE_ADDR memaddr;
+ char *buf;
+ int len;
+{
+ int res;
+ int val;
+ send_rdp ("bww-S-P-V",
+ RDP_MEM_READ, memaddr, len,
+ buf, len,
+ &res, &val);
+ if (res)
+ {
+ return val;
+ }
+ return len;
+}
+
+static void
+rdp_fetch_one_register (mask, buf)
+ int mask;
+ char *buf;
+{
+ int val;
+ send_rdp ("bbw-SWZ", RDP_CPU_READ, RDP_CPU_READWRITE_MODE_CURRENT, mask, &val);
+ store_signed_integer (buf, 4, val);
+}
+
+static void
+rdp_fetch_one_fpu_register (mask, buf)
+ int mask;
+ char *buf;
+{
+#if 0
+ /* !!! Since the PIE board doesn't work as documented,
+ and it doesn't have FPU hardware anyway and since it
+ slows everything down, I've disabled this. */
+ int val;
+ if (mask == RDP_FPU_READWRITE_MASK_FPS)
+ {
+ /* this guy is only a word */
+ send_rdp ("bbw-SWZ", RDP_COPRO_READ, FPU_COPRO_NUMBER, mask, &val);
+ store_signed_integer (buf, 4, val);
+ }
+ else
+ {
+ /* There are 12 bytes long
+ !! fixme about endianness
+ */
+ int dummy; /* I've seen these come back as four words !! */
+ send_rdp ("bbw-SWWWWZ", RDP_COPRO_READ, FPU_COPRO_NUMBER, mask, buf + 0, buf + 4, buf + 8, &dummy);
+ }
+#endif
+ memset (buf, 0, MAX_REGISTER_RAW_SIZE);
+}
+
+
+static void
+rdp_store_one_register (mask, buf)
+ int mask;
+ char *buf;
+{
+ int val = extract_unsigned_integer (buf, 4);
+
+ send_rdp ("bbww-SZ",
+ RDP_CPU_WRITE, RDP_CPU_READWRITE_MODE_CURRENT, mask, val);
+}
+
+
+static void
+rdp_store_one_fpu_register (mask, buf)
+ int mask;
+ char *buf;
+{
+#if 0
+ /* See comment in fetch_one_fpu_register */
+ if (mask == RDP_FPU_READWRITE_MASK_FPS)
+ {
+ int val = extract_unsigned_integer (buf, 4);
+ /* this guy is only a word */
+ send_rdp ("bbww-SZ", RDP_COPRO_WRITE,
+ FPU_COPRO_NUMBER,
+ mask, val);
+ }
+ else
+ {
+ /* There are 12 bytes long
+ !! fixme about endianness
+ */
+ int dummy = 0;
+ /* I've seen these come as four words, not the three advertized !! */
+ printf ("Sending mask %x\n", mask);
+ send_rdp ("bbwwwww-SZ",
+ RDP_COPRO_WRITE,
+ FPU_COPRO_NUMBER,
+ mask,
+ *(int *) (buf + 0),
+ *(int *) (buf + 4),
+ *(int *) (buf + 8),
+ 0);
+
+ printf ("done mask %x\n", mask);
+ }
+#endif
+}
+
+
+/* Convert between GDB requests and the RDP layer. */
+
+static void
+remote_rdp_fetch_register (regno)
+ int regno;
+{
+ if (regno == -1)
+ {
+ for (regno = 0; regno < NUM_REGS; regno++)
+ remote_rdp_fetch_register (regno);
+ }
+ else
+ {
+ char buf[MAX_REGISTER_RAW_SIZE];
+ if (regno < 15)
+ rdp_fetch_one_register (1 << regno, buf);
+ else if (regno == PC_REGNUM)
+ rdp_fetch_one_register (RDP_CPU_READWRITE_MASK_PC, buf);
+ else if (regno == PS_REGNUM)
+ rdp_fetch_one_register (RDP_CPU_READWRITE_MASK_CPSR, buf);
+ else if (regno == FPS_REGNUM)
+ rdp_fetch_one_fpu_register (RDP_FPU_READWRITE_MASK_FPS, buf);
+ else if (regno >= F0_REGNUM && regno <= F7_REGNUM)
+ rdp_fetch_one_fpu_register (1 << (regno - F0_REGNUM), buf);
+ else
+ {
+ printf ("Help me with fetch reg %d\n", regno);
+ }
+ supply_register (regno, buf);
+ }
+}
+
+
+static void
+remote_rdp_store_register (regno)
+ int regno;
+{
+ if (regno == -1)
+ {
+ for (regno = 0; regno < NUM_REGS; regno++)
+ remote_rdp_store_register (regno);
+ }
+ else
+ {
+ char tmp[MAX_REGISTER_RAW_SIZE];
+ read_register_gen (regno, tmp);
+ if (regno < 15)
+ rdp_store_one_register (1 << regno, tmp);
+ else if (regno == PC_REGNUM)
+ rdp_store_one_register (RDP_CPU_READWRITE_MASK_PC, tmp);
+ else if (regno == PS_REGNUM)
+ rdp_store_one_register (RDP_CPU_READWRITE_MASK_CPSR, tmp);
+ else if (regno >= F0_REGNUM && regno <= F7_REGNUM)
+ rdp_store_one_fpu_register (1 << (regno - F0_REGNUM), tmp);
+ else
+ {
+ printf ("Help me with reg %d\n", regno);
+ }
+ }
+}
+
+static void
+remote_rdp_kill ()
+{
+ callback->shutdown (callback);
+}
+
+
+static void
+rdp_info ()
+{
+ send_rdp ("bw-S-W-Z", RDP_INFO, RDP_INFO_ABOUT_STEP,
+ &ds.step_info);
+ send_rdp ("bw-S-W-Z", RDP_INFO, RDP_INFO_ABOUT_BREAK,
+ &ds.break_info);
+ send_rdp ("bw-S-WW-Z", RDP_INFO, RDP_INFO_ABOUT_TARGET,
+ &ds.target_info,
+ &ds.model_info);
+
+ ds.can_step = ds.step_info & RDP_INFO_ABOUT_STEP_1;
+
+ ds.rdi_level = (ds.target_info >> 5) & 3;
+}
+
+
+static void
+rdp_execute_start ()
+{
+ /* Start it off, but don't wait for it */
+ send_rdp ("bb-", RDP_EXEC, RDP_EXEC_TYPE_SYNC);
+}
+
+
+static void
+rdp_set_command_line (command, args)
+ char * command;
+ char * args;
+{
+ /*
+ ** We could use RDP_INFO_SET_CMDLINE to send this, but EmbeddedICE systems
+ ** don't implement that, and get all confused at the unexpected text.
+ ** Instead, just keep a copy, and send it when the target does a SWI_GetEnv
+ */
+
+ if (commandline != NULL)
+ free (commandline);
+
+ commandline = malloc (strlen (command) + strlen (args) + 2);
+ if (commandline != NULL)
+ {
+ strcpy (commandline, command);
+ strcat (commandline, " ");
+ strcat (commandline, args);
+ }
+}
+
+static void
+rdp_catch_vectors ()
+{
+ /*
+ ** We want the target monitor to intercept the abort vectors
+ ** i.e. stop the program if any of these are used.
+ */
+ send_rdp ("bww-SZ", RDP_INFO, RDP_INFO_VECTOR_CATCH,
+ /*
+ ** Specify a bitmask including
+ ** the reset vector
+ ** the undefined instruction vector
+ ** the prefetch abort vector
+ ** the data abort vector
+ ** the address exception vector
+ */
+ (1<<0)|(1<<1)|(1<<3)|(1<<4)|(1<<5)
+ );
+}
+
+
+
+#define a_byte 1
+#define a_word 2
+#define a_string 3
+
+
+typedef struct
+{
+ CORE_ADDR n;
+ const char *s;
+}
+argsin;
+
+#define ABYTE 1
+#define AWORD 2
+#define ASTRING 3
+#define ADDRLEN 4
+
+#define SWI_WriteC 0x0
+#define SWI_Write0 0x2
+#define SWI_ReadC 0x4
+#define SWI_CLI 0x5
+#define SWI_GetEnv 0x10
+#define SWI_Exit 0x11
+#define SWI_EnterOS 0x16
+
+#define SWI_GetErrno 0x60
+#define SWI_Clock 0x61
+
+#define SWI_Time 0x63
+#define SWI_Remove 0x64
+#define SWI_Rename 0x65
+#define SWI_Open 0x66
+
+#define SWI_Close 0x68
+#define SWI_Write 0x69
+#define SWI_Read 0x6a
+#define SWI_Seek 0x6b
+#define SWI_Flen 0x6c
+
+#define SWI_IsTTY 0x6e
+#define SWI_TmpNam 0x6f
+#define SWI_InstallHandler 0x70
+#define SWI_GenerateError 0x71
+
+
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
+
+static int translate_open_mode[] =
+{
+ O_RDONLY, /* "r" */
+ O_RDONLY+O_BINARY, /* "rb" */
+ O_RDWR, /* "r+" */
+ O_RDWR +O_BINARY, /* "r+b" */
+ O_WRONLY +O_CREAT+O_TRUNC, /* "w" */
+ O_WRONLY+O_BINARY+O_CREAT+O_TRUNC, /* "wb" */
+ O_RDWR +O_CREAT+O_TRUNC, /* "w+" */
+ O_RDWR +O_BINARY+O_CREAT+O_TRUNC, /* "w+b" */
+ O_WRONLY +O_APPEND+O_CREAT,/* "a" */
+ O_WRONLY+O_BINARY+O_APPEND+O_CREAT,/* "ab" */
+ O_RDWR +O_APPEND+O_CREAT,/* "a+" */
+ O_RDWR +O_BINARY+O_APPEND+O_CREAT /* "a+b" */
+};
+
+static int
+exec_swi (swi, args)
+ int swi;
+ argsin *args;
+{
+ int i;
+ char c;
+ switch (swi)
+ {
+ case SWI_WriteC:
+ callback->write_stdout (callback, &c, 1);
+ return 0;
+ case SWI_Write0:
+ for (i = 0; i < args->n; i++)
+ callback->write_stdout (callback, args->s, strlen (args->s));
+ return 0;
+ case SWI_ReadC:
+ callback->read_stdin (callback, &c, 1);
+ args->n = c;
+ return 1;
+ case SWI_CLI:
+ args->n = callback->system (callback, args->s);
+ return 1;
+ case SWI_GetErrno:
+ args->n = callback->get_errno (callback);
+ return 1;
+ case SWI_Time:
+ args->n = callback->time (callback, NULL);
+ return 1;
+
+ case SWI_Clock :
+ /* return number of centi-seconds... */
+ args->n =
+#ifdef CLOCKS_PER_SEC
+ (CLOCKS_PER_SEC >= 100)
+ ? (clock() / (CLOCKS_PER_SEC / 100))
+ : ((clock() * 100) / CLOCKS_PER_SEC) ;
+#else
+ /* presume unix... clock() returns microseconds */
+ clock() / 10000 ;
+#endif
+ return 1 ;
+
+ case SWI_Remove:
+ args->n = callback->unlink (callback, args->s);
+ return 1;
+ case SWI_Rename:
+ args->n = callback->rename (callback, args[0].s, args[1].s);
+ return 1;
+
+ case SWI_Open:
+ /* Now we need to decode the Demon open mode */
+ i = translate_open_mode[args[1].n];
+
+ /* Filename ":tt" is special: it denotes stdin/out */
+ if (strcmp(args->s,":tt")==0)
+ {
+ if (i == O_RDONLY ) /* opening tty "r" */
+ args->n = 0 /* stdin */ ;
+ else
+ args->n = 1 /* stdout */ ;
+ }
+ else
+ args->n = callback->open (callback, args->s, i);
+ return 1;
+
+ case SWI_Close:
+ args->n = callback->close (callback, args->n);
+ return 1;
+
+ case SWI_Write:
+ /* Return the number of bytes *not* written */
+ args->n = args[1].n -
+ callback->write (callback, args[0].n, args[1].s, args[1].n);
+ return 1;
+
+ case SWI_Read:
+ {
+ char *copy = alloca (args[2].n);
+ int done = callback->read (callback, args[0].n, copy, args[2].n);
+ if (done > 0)
+ remote_rdp_xfer_inferior_memory (args[1].n, copy, done, 1, 0);
+ args->n = args[2].n-done;
+ return 1;
+ }
+
+ case SWI_Seek:
+ /* Return non-zero on failure */
+ args->n = callback->lseek (callback, args[0].n, args[1].n, 0) < 0;
+ return 1;
+
+ case SWI_Flen:
+ {
+ long old = callback->lseek (callback, args->n, 0, SEEK_CUR);
+ args->n = callback->lseek (callback, args->n, 0, SEEK_END);
+ callback->lseek (callback, args->n, old, 0);
+ return 1;
+ }
+
+ case SWI_IsTTY:
+ args->n = callback->isatty (callback, args->n);
+ return 1;
+
+ case SWI_GetEnv:
+ if (commandline != NULL)
+ {
+ int len = strlen (commandline);
+ if (len > 255)
+ {
+ len = 255;
+ commandline [255]='\0';
+ }
+ remote_rdp_xfer_inferior_memory (args[0].n,
+ commandline, len+1, 1, 0);
+ }
+ else
+ remote_rdp_xfer_inferior_memory (args[0].n, "", 1, 1, 0);
+ return 1;
+
+ default:
+ return 0;
+ }
+}
+
+
+static void
+handle_swi ()
+{
+ argsin args[3];
+ char *buf;
+ int len;
+ int count = 0;
+
+ int swino = get_word ();
+ int type = get_byte ();
+ while (type != 0)
+ {
+ switch (type & 0x3)
+ {
+ case ABYTE:
+ args[count].n = get_byte ();
+ break;
+
+ case AWORD:
+ args[count].n = get_word ();
+ break;
+
+ case ASTRING:
+ /* If the word is under 32 bytes it will be sent otherwise
+ an address to it is passed. Also: Special case of 255 */
+
+ len = get_byte ();
+ if (len > 32)
+ {
+ if (len == 255)
+ {
+ len = get_word ();
+ }
+ buf = alloca (len);
+ remote_rdp_xfer_inferior_memory (get_word (),
+ buf,
+ len,
+ 0,
+ 0);
+ }
+ else
+ {
+ int i;
+ buf = alloca (len + 1);
+ for (i = 0; i < len; i++)
+ buf[i] = get_byte ();
+ buf[i] = 0;
+ }
+ args[count].n = len;
+ args[count].s = buf;
+ break;
+
+ default:
+ error ("Unimplented SWI argument");
+ }
+
+ type = type >> 2;
+ count++;
+ }
+
+ if (exec_swi (swino, args))
+ {
+ /* We have two options here reply with either a byte or a word
+ which is stored in args[0].n. There is no harm in replying with
+ a word all the time, so thats what I do! */
+ send_rdp ("bbw-", RDP_OSOpReply, RDP_OSOpWord, args[0].n);
+ }
+ else
+ {
+ send_rdp ("bb-", RDP_OSOpReply, RDP_OSOpNothing);
+ }
+}
+
+static void
+rdp_execute_finish ()
+{
+ int running = 1;
+
+ while (running)
+ {
+ int res;
+ res = SERIAL_READCHAR (io, 1);
+ while (res == SERIAL_TIMEOUT)
+ {
+ QUIT;
+ printf_filtered ("Waiting for target..\n");
+ res = SERIAL_READCHAR (io, 1);
+ }
+
+ switch (res)
+ {
+ case RDP_RES_SWI:
+ handle_swi ();
+ break;
+ case RDP_RES_VALUE:
+ send_rdp ("B", &ds.rdi_stopped_status);
+ running = 0;
+ break;
+ case RDP_RESET:
+ printf_filtered ("Target reset\n");
+ running = 0;
+ break;
+ default:
+ printf_filtered ("Ignoring %x\n", res);
+ break;
+ }
+ }
+}
+
+
+static void
+rdp_execute ()
+{
+ rdp_execute_start ();
+ rdp_execute_finish ();
+}
+
+static int
+remote_rdp_insert_breakpoint (addr, save)
+ CORE_ADDR addr;
+ char *save;
+{
+ int res;
+ if (ds.rdi_level > 0)
+ {
+ send_rdp ("bwb-SWB",
+ RDP_SET_BREAK,
+ addr,
+ RDP_SET_BREAK_TYPE_PC_EQUAL | RDP_SET_BREAK_TYPE_GET_HANDLE,
+ save,
+ &res);
+ }
+ else
+ {
+ send_rdp ("bwb-SB",
+ RDP_SET_BREAK,
+ addr,
+ RDP_SET_BREAK_TYPE_PC_EQUAL,
+ &res);
+ }
+ return res;
+}
+
+static int
+remote_rdp_remove_breakpoint (addr, save)
+ CORE_ADDR addr;
+ char *save;
+{
+ int res;
+ if (ds.rdi_level > 0)
+ {
+ send_rdp ("b-p-S-B",
+ RDP_CLEAR_BREAK,
+ save, 4,
+ &res);
+ }
+ else
+ {
+ send_rdp ("bw-S-B",
+ RDP_CLEAR_BREAK,
+ addr,
+ &res);
+ }
+ return res;
+}
+
+static void
+rdp_step ()
+{
+ if (ds.can_step && 0)
+ {
+ /* The pie board can't do steps so I can't test this, and
+ the other code will always work. */
+ int status;
+ send_rdp ("bbw-S-B",
+ RDP_STEP, 0, 1,
+ &status);
+ }
+ else
+ {
+ char handle[4];
+ CORE_ADDR pc = read_register (PC_REGNUM);
+ pc = arm_get_next_pc (pc);
+ remote_rdp_insert_breakpoint (pc, &handle);
+ rdp_execute ();
+ remote_rdp_remove_breakpoint (pc, &handle);
+ }
+}
+
+static void
+remote_rdp_open (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ int not_icebreaker;
+
+ if (!args)
+ error_no_arg ("serial port device name");
+
+ baud_rate = 9600;
+
+ target_preopen (from_tty);
+
+ io = SERIAL_OPEN (args);
+
+ if (!io)
+ perror_with_name (args);
+
+ SERIAL_RAW (io);
+
+ rdp_init (1, from_tty);
+
+
+ if (from_tty)
+ {
+ printf_unfiltered ("Remote RDP debugging using %s at %d baud\n", args, baud_rate);
+ }
+
+ rdp_info ();
+
+ /* Need to set up the vector interception state */
+ rdp_catch_vectors();
+
+ /*
+ ** If it's an EmbeddedICE, we need to set the processor config.
+ ** Assume we can always have ARM7TDI...
+ */
+ send_rdp ("bw-SB", RDP_INFO, RDP_INFO_ICEBREAKER, & not_icebreaker);
+ if (!not_icebreaker)
+ {
+ const char * CPU = "ARM7TDI";
+ int ICEversion;
+ int len = strlen (CPU);
+
+ send_rdp ("bbbbw-p-SWZ",
+ RDP_SELECT_CONFIG,
+ RDI_ConfigCPU, /* Aspect: set the CPU */
+ len, /* The number of bytes in the name */
+ RDI_MatchAny, /* We'll take whatever we get */
+ 0, /* We'll take whatever version's there */
+ CPU,len,
+ & ICEversion);
+ }
+
+ /* command line initialised on 'run'*/
+
+ push_target (& remote_rdp_ops);
+
+ callback->init (callback);
+ flush_cached_frames ();
+ registers_changed ();
+ stop_pc = read_pc ();
+ set_current_frame (create_new_frame (read_fp (), stop_pc));
+ select_frame (get_current_frame (), 0);
+ print_stack_frame (selected_frame, -1, 1);
+}
+
+
+
+/* Close out all files and local state before this target loses control. */
+
+static void
+remote_rdp_close (quitting)
+ int quitting;
+{
+ callback->shutdown (callback);
+ if (io)
+ SERIAL_CLOSE (io);
+ io = 0;
+}
+
+
+/* Resume execution of the target process. STEP says whether to single-step
+ or to run free; SIGGNAL is the signal value (e.g. SIGINT) to be given
+ to the target, or zero for no signal. */
+
+static void
+remote_rdp_resume (pid, step, siggnal)
+ int pid, step;
+ enum target_signal siggnal;
+{
+ if (step)
+ rdp_step ();
+ else
+ rdp_execute ();
+}
+
+/* Wait for inferior process to do something. Return pid of child,
+ or -1 in case of error; store status through argument pointer STATUS,
+ just as `wait' would. */
+
+static int
+remote_rdp_wait (pid, status)
+ int pid;
+ struct target_waitstatus *status;
+{
+ switch (ds.rdi_stopped_status)
+ {
+ default:
+ case RDP_RES_RESET:
+ case RDP_RES_SWI:
+ status->kind = TARGET_WAITKIND_EXITED;
+ status->value.integer = read_register (0);
+ break;
+ case RDP_RES_AT_BREAKPOINT:
+ status->kind = TARGET_WAITKIND_STOPPED;
+ /* The signal in sigrc is a host signal. That probably
+ should be fixed. */
+ status->value.sig = TARGET_SIGNAL_TRAP;
+ break;
+#if 0
+ case rdp_signalled:
+ status->kind = TARGET_WAITKIND_SIGNALLED;
+ /* The signal in sigrc is a host signal. That probably
+ should be fixed. */
+ status->value.sig = target_signal_from_host (sigrc);
+ break;
+#endif
+ }
+
+ return inferior_pid;
+}
+
+/* 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
+remote_rdp_prepare_to_store ()
+{
+ /* Do nothing, since we can store individual regs */
+}
+
+static int
+remote_rdp_xfer_inferior_memory (memaddr, myaddr, len, write, target)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+ int write;
+ struct target_ops *target; /* ignored */
+{
+ /* I infer from D Taylor's code that there's a limit on the amount
+ we can transfer in one chunk.. */
+ int done = 0;
+ while (done < len)
+ {
+ int justdone;
+ int thisbite = len - done;
+ if (thisbite > RDP_MOUTHFULL)
+ thisbite = RDP_MOUTHFULL;
+
+ QUIT;
+
+ if (write)
+ {
+ justdone = rdp_write (memaddr + done, myaddr + done, thisbite);
+ }
+ else
+ {
+ justdone = rdp_read (memaddr + done, myaddr + done, thisbite);
+ }
+
+ done += justdone;
+
+ if (justdone != thisbite)
+ break;
+ }
+ return done;
+}
+
+
+
+struct yn
+{
+ const char *name;
+ int bit;
+};
+static struct yn stepinfo[] =
+{
+ {"Step more than one instruction", RDP_INFO_ABOUT_STEP_GT_1},
+ {"Step to jump", RDP_INFO_ABOUT_STEP_TO_JMP},
+ {"Step one instruction", RDP_INFO_ABOUT_STEP_1},
+ {0}
+};
+
+static struct yn breakinfo[] =
+{
+ {"comparison breakpoints supported", RDP_INFO_ABOUT_BREAK_COMP},
+ {"range breakpoints supported", RDP_INFO_ABOUT_BREAK_RANGE},
+ {"watchpoints for byte reads supported", RDP_INFO_ABOUT_BREAK_BYTE_READ},
+ {"watchpoints for half-word reads supported", RDP_INFO_ABOUT_BREAK_HALFWORD_READ},
+ {"watchpoints for word reads supported", RDP_INFO_ABOUT_BREAK_WORD_READ},
+ {"watchpoints for byte writes supported", RDP_INFO_ABOUT_BREAK_BYTE_WRITE},
+ {"watchpoints for half-word writes supported", RDP_INFO_ABOUT_BREAK_HALFWORD_WRITE},
+ {"watchpoints for word writes supported", RDP_INFO_ABOUT_BREAK_WORD_WRITE},
+ {"mask break/watch-points supported", RDP_INFO_ABOUT_BREAK_MASK},
+{"thread-specific breakpoints supported", RDP_INFO_ABOUT_BREAK_THREAD_BREAK},
+{"thread-specific watchpoints supported", RDP_INFO_ABOUT_BREAK_THREAD_WATCH},
+ {"conditional breakpoints supported", RDP_INFO_ABOUT_BREAK_COND},
+ {0}
+};
+
+
+static void
+dump_bits (t, info)
+ struct yn *t;
+ int info;
+{
+ while (t->name)
+ {
+ printf_unfiltered (" %-45s : %s\n", t->name, (info & t->bit) ? "Yes" : "No");
+ t++;
+ }
+}
+
+static void
+remote_rdp_files_info (target)
+ struct target_ops *target;
+{
+ printf_filtered ("Target capabilities:\n");
+ dump_bits (stepinfo, ds.step_info);
+ dump_bits (breakinfo, ds.break_info);
+ printf_unfiltered ("target level RDI %x\n", (ds.target_info >> 5) & 3);
+}
+
+
+static void
+remote_rdp_create_inferior (exec_file, allargs, env)
+ char * exec_file;
+ char * allargs;
+ char ** env;
+{
+ CORE_ADDR entry_point;
+
+ if (exec_file == 0 || exec_bfd == 0)
+ error ("No executable file specified.");
+
+ entry_point = (CORE_ADDR) bfd_get_start_address (exec_bfd);
+
+ remote_rdp_kill ();
+ remove_breakpoints ();
+ init_wait_for_inferior ();
+
+ /* This gives us a chance to set up the command line */
+ rdp_set_command_line (exec_file, allargs);
+
+ inferior_pid = 42;
+ insert_breakpoints (); /* Needed to get correct instruction in cache */
+
+ /*
+ ** RDP targets don't provide any facility to set the top of memory,
+ ** so we don't bother to look for MEMSIZE in the environment.
+ */
+
+ /* Let's go! */
+ proceed (entry_point, TARGET_SIGNAL_DEFAULT, 0);
+}
+
+/* Accept any stray run/attach commands */
+static int
+remote_rdp_can_run()
+{
+ return 1;
+}
+
+/* Attach doesn't need to do anything */
+static void
+remote_rdp_attach(args, from_tty)
+ char * args;
+ int from_tty;
+{
+ return;
+}
+
+/* Define the target subroutine names */
+
+struct target_ops remote_rdp_ops ;
+
+static void
+init_remote_rdp_ops(void)
+{
+ remote_rdp_ops.to_shortname = "rdp";
+ remote_rdp_ops.to_longname = "Remote Target using the RDProtocol";
+ remote_rdp_ops.to_doc = "Use a remote ARM system which uses the ARM Remote Debugging Protocol";
+ remote_rdp_ops.to_open = remote_rdp_open;
+ remote_rdp_ops.to_close = remote_rdp_close;
+ remote_rdp_ops.to_attach = remote_rdp_attach;
+ remote_rdp_ops.to_post_attach = NULL;
+ remote_rdp_ops.to_require_attach = NULL;
+ remote_rdp_ops.to_detach = NULL;
+ remote_rdp_ops.to_require_detach = NULL;
+ remote_rdp_ops.to_resume = remote_rdp_resume;
+ remote_rdp_ops.to_wait = remote_rdp_wait;
+ remote_rdp_ops.to_post_wait = NULL;
+ remote_rdp_ops.to_fetch_registers = remote_rdp_fetch_register;
+ remote_rdp_ops.to_store_registers = remote_rdp_store_register;
+ remote_rdp_ops.to_prepare_to_store = remote_rdp_prepare_to_store;
+ remote_rdp_ops.to_xfer_memory = remote_rdp_xfer_inferior_memory;
+ remote_rdp_ops.to_files_info = remote_rdp_files_info;
+ remote_rdp_ops.to_insert_breakpoint = remote_rdp_insert_breakpoint;
+ remote_rdp_ops.to_remove_breakpoint = remote_rdp_remove_breakpoint;
+ remote_rdp_ops.to_terminal_init = NULL;
+ remote_rdp_ops.to_terminal_inferior = NULL;
+ remote_rdp_ops.to_terminal_ours_for_output = NULL;
+ remote_rdp_ops.to_terminal_ours = NULL;
+ remote_rdp_ops.to_terminal_info = NULL;
+ remote_rdp_ops.to_kill = remote_rdp_kill;
+ remote_rdp_ops.to_load = generic_load;
+ remote_rdp_ops.to_lookup_symbol = NULL;
+ remote_rdp_ops.to_create_inferior = remote_rdp_create_inferior;
+ remote_rdp_ops.to_post_startup_inferior = NULL;
+ remote_rdp_ops.to_acknowledge_created_inferior = NULL;
+ remote_rdp_ops.to_clone_and_follow_inferior = NULL;
+ remote_rdp_ops.to_post_follow_inferior_by_clone = NULL;
+ remote_rdp_ops.to_insert_fork_catchpoint = NULL;
+ remote_rdp_ops.to_remove_fork_catchpoint = NULL;
+ remote_rdp_ops.to_insert_vfork_catchpoint = NULL;
+ remote_rdp_ops.to_remove_vfork_catchpoint = NULL;
+ remote_rdp_ops.to_has_forked = NULL;
+ remote_rdp_ops.to_has_vforked = NULL;
+ remote_rdp_ops.to_can_follow_vfork_prior_to_exec = NULL;
+ remote_rdp_ops.to_post_follow_vfork = NULL;
+ remote_rdp_ops.to_insert_exec_catchpoint = NULL;
+ remote_rdp_ops.to_remove_exec_catchpoint = NULL;
+ remote_rdp_ops.to_has_execd = NULL;
+ remote_rdp_ops.to_reported_exec_events_per_exec_call = NULL;
+ remote_rdp_ops.to_has_exited = NULL;
+ remote_rdp_ops.to_mourn_inferior = generic_mourn_inferior;
+ remote_rdp_ops.to_can_run = remote_rdp_can_run;
+ remote_rdp_ops.to_notice_signals = 0;
+ remote_rdp_ops.to_thread_alive = 0;
+ remote_rdp_ops.to_stop = 0;
+ remote_rdp_ops.to_pid_to_exec_file = NULL;
+ remote_rdp_ops.to_core_file_to_sym_file = NULL;
+ remote_rdp_ops.to_stratum = process_stratum;
+ remote_rdp_ops.DONT_USE = NULL;
+ remote_rdp_ops.to_has_all_memory = 1;
+ remote_rdp_ops.to_has_memory = 1;
+ remote_rdp_ops.to_has_stack = 1;
+ remote_rdp_ops.to_has_registers = 1;
+ remote_rdp_ops.to_has_execution = 1;
+ remote_rdp_ops.to_sections = NULL;
+ remote_rdp_ops.to_sections_end = NULL;
+ remote_rdp_ops.to_magic = OPS_MAGIC;
+}
+
+void
+_initialize_remote_rdp ()
+{
+ init_remote_rdp_ops() ;
+ add_target (&remote_rdp_ops);
+}
diff --git a/gdb/remote-sds.c b/gdb/remote-sds.c
new file mode 100644
index 00000000000..3ab5f44bbef
--- /dev/null
+++ b/gdb/remote-sds.c
@@ -0,0 +1,1206 @@
+/* Remote target communications for serial-line targets using SDS' protocol.
+ Copyright 1997 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* This interface was written by studying the behavior of the SDS
+ monitor on an ADS 821/860 board, and by consulting the
+ documentation of the monitor that is available on Motorola's web
+ site. -sts 8/13/97 */
+
+#include "defs.h"
+#include "gdb_string.h"
+#include <fcntl.h>
+#include "frame.h"
+#include "inferior.h"
+#include "bfd.h"
+#include "symfile.h"
+#include "target.h"
+#include "wait.h"
+#include "gdbcmd.h"
+#include "objfiles.h"
+#include "gdb-stabs.h"
+#include "gdbthread.h"
+#include "gdbcore.h"
+#include "dcache.h"
+
+#ifdef USG
+#include <sys/types.h>
+#endif
+
+#include <signal.h>
+#include "serial.h"
+
+extern void _initialize_remote_sds PARAMS ((void));
+
+/* Declarations of local functions. */
+
+static int sds_write_bytes PARAMS ((CORE_ADDR, char *, int));
+
+static int sds_read_bytes PARAMS ((CORE_ADDR, char *, int));
+
+static void sds_files_info PARAMS ((struct target_ops *ignore));
+
+static int sds_xfer_memory PARAMS ((CORE_ADDR, char *,
+ int, int, struct target_ops *));
+
+static void sds_prepare_to_store PARAMS ((void));
+
+static void sds_fetch_registers PARAMS ((int));
+
+static void sds_resume PARAMS ((int, int, enum target_signal));
+
+static int sds_start_remote PARAMS ((PTR));
+
+static void sds_open PARAMS ((char *, int));
+
+static void sds_close PARAMS ((int));
+
+static void sds_store_registers PARAMS ((int));
+
+static void sds_mourn PARAMS ((void));
+
+static void sds_create_inferior PARAMS ((char *, char *, char **));
+
+static void sds_load PARAMS ((char *, int));
+
+static int getmessage PARAMS ((unsigned char *, int));
+
+static int putmessage PARAMS ((unsigned char *, int));
+
+static int sds_send PARAMS ((unsigned char *, int));
+
+static int readchar PARAMS ((int));
+
+static int sds_wait PARAMS ((int, struct target_waitstatus *));
+
+static void sds_kill PARAMS ((void));
+
+static int tohex PARAMS ((int));
+
+static int fromhex PARAMS ((int));
+
+static void sds_detach PARAMS ((char *, int));
+
+static void sds_interrupt PARAMS ((int));
+
+static void sds_interrupt_twice PARAMS ((int));
+
+static void interrupt_query PARAMS ((void));
+
+static int read_frame PARAMS ((char *));
+
+static int sds_insert_breakpoint PARAMS ((CORE_ADDR, char *));
+
+static int sds_remove_breakpoint PARAMS ((CORE_ADDR, char *));
+
+static void init_sds_ops PARAMS ((void));
+
+static void sds_command PARAMS ((char *args, int from_tty));
+
+/* Define the target operations vector. */
+
+static struct target_ops sds_ops;
+
+/* 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 sds_timeout = 2;
+
+/* Descriptor for I/O to remote machine. Initialize it to NULL so
+ that sds_open knows that we don't have a file open when the program
+ starts. */
+
+static serial_t sds_desc = NULL;
+
+/* This limit comes from the monitor. */
+
+#define PBUFSIZ 250
+
+/* Maximum number of bytes to read/write at once. The value here
+ is chosen to fill up a packet (the headers account for the 32). */
+#define MAXBUFBYTES ((PBUFSIZ-32)/2)
+
+static int next_msg_id;
+
+static int just_started;
+
+static int message_pending;
+
+
+/* Clean up connection to a remote debugger. */
+
+/* ARGSUSED */
+static void
+sds_close (quitting)
+ int quitting;
+{
+ if (sds_desc)
+ SERIAL_CLOSE (sds_desc);
+ sds_desc = NULL;
+}
+
+/* Stub for catch_errors. */
+
+static int
+sds_start_remote (dummy)
+ PTR dummy;
+{
+ char c;
+ unsigned char buf[200];
+
+ immediate_quit = 1; /* Allow user to interrupt it */
+
+ /* Ack any packet which the remote side has already sent. */
+ SERIAL_WRITE (sds_desc, "{#*\r\n", 5);
+ SERIAL_WRITE (sds_desc, "{#}\r\n", 5);
+
+ while ((c = readchar (1)) >= 0)
+ printf_unfiltered ("%c", c);
+ printf_unfiltered ("\n");
+
+ next_msg_id = 251;
+
+ buf[0] = 26;
+ sds_send (buf, 1);
+
+ buf[0] = 0;
+ sds_send (buf, 1);
+
+ 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 *sds_dcache;
+
+static void
+sds_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 (&sds_ops);
+
+ sds_dcache = dcache_init (sds_read_bytes, sds_write_bytes);
+
+ sds_desc = SERIAL_OPEN (name);
+ if (!sds_desc)
+ perror_with_name (name);
+
+ if (baud_rate != -1)
+ {
+ if (SERIAL_SETBAUDRATE (sds_desc, baud_rate))
+ {
+ SERIAL_CLOSE (sds_desc);
+ perror_with_name (name);
+ }
+ }
+
+
+ SERIAL_RAW (sds_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 (sds_desc);
+
+ if (from_tty)
+ {
+ puts_filtered ("Remote debugging using ");
+ puts_filtered (name);
+ puts_filtered ("\n");
+ }
+ push_target (&sds_ops); /* Switch to using remote target now */
+
+ just_started = 1;
+
+ /* 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 (sds_start_remote, NULL,
+ "Couldn't establish connection to remote target\n",
+ RETURN_MASK_ALL))
+ pop_target ();
+}
+
+/* This takes a program previously attached to and detaches it. After
+ this is done, GDB can be used to debug some other program. We
+ better not have left any breakpoints in the target program or it'll
+ die when it hits one. */
+
+static void
+sds_detach (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ char buf[PBUFSIZ];
+
+ if (args)
+ error ("Argument given to \"detach\" when remotely debugging.");
+
+#if 0
+ /* Tell the remote target to detach. */
+ strcpy (buf, "D");
+ sds_send (buf, 1);
+#endif
+
+ 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 %d", a);
+}
+
+/* Convert number NIB to a hex digit. */
+
+static int
+tohex (nib)
+ int nib;
+{
+ if (nib < 10)
+ return '0'+nib;
+ else
+ return 'a'+nib-10;
+}
+
+static int
+tob64 (inbuf, outbuf, len)
+ unsigned char *inbuf;
+ char *outbuf;
+ int len;
+{
+ int i, sum;
+ char *p;
+
+ if (len % 3 != 0)
+ error ("bad length");
+
+ p = outbuf;
+ for (i = 0; i < len; i += 3)
+ {
+ /* Collect the next three bytes into a number. */
+ sum = ((long) *inbuf++) << 16;
+ sum |= ((long) *inbuf++) << 8;
+ sum |= ((long) *inbuf++);
+
+ /* Spit out 4 6-bit encodings. */
+ *p++ = ((sum >> 18) & 0x3f) + '0';
+ *p++ = ((sum >> 12) & 0x3f) + '0';
+ *p++ = ((sum >> 6) & 0x3f) + '0';
+ *p++ = (sum & 0x3f) + '0';
+ }
+ return (p - outbuf);
+}
+
+static int
+fromb64 (inbuf, outbuf, len)
+ char *inbuf, *outbuf;
+ int len;
+{
+ int i, sum;
+
+ if (len % 4 != 0)
+ error ("bad length");
+
+ for (i = 0; i < len; i += 4)
+ {
+ /* Collect 4 6-bit digits. */
+ sum = (*inbuf++ - '0') << 18;
+ sum |= (*inbuf++ - '0') << 12;
+ sum |= (*inbuf++ - '0') << 6;
+ sum |= (*inbuf++ - '0');
+
+ /* Now take the resulting 24-bit number and get three bytes out
+ of it. */
+ *outbuf++ = (sum >> 16) & 0xff;
+ *outbuf++ = (sum >> 8) & 0xff;
+ *outbuf++ = sum & 0xff;
+ }
+
+ return (len / 4) * 3;
+}
+
+
+/* Tell the remote machine to resume. */
+
+static enum target_signal last_sent_signal = TARGET_SIGNAL_0;
+int last_sent_step;
+
+static void
+sds_resume (pid, step, siggnal)
+ int pid, step;
+ enum target_signal siggnal;
+{
+ unsigned char buf[PBUFSIZ];
+
+ dcache_flush (sds_dcache);
+
+ last_sent_signal = siggnal;
+ last_sent_step = step;
+
+ buf[0] = (step ? 21 : 20);
+ buf[1] = 0; /* (should be signal?) */
+
+ sds_send (buf, 2);
+}
+
+/* Send a message to target to halt it. Target will respond, and send
+ us a message pending notice. */
+
+static void
+sds_interrupt (signo)
+ int signo;
+{
+ unsigned char buf[PBUFSIZ];
+
+ /* If this doesn't work, try more severe steps. */
+ signal (signo, sds_interrupt_twice);
+
+ if (remote_debug)
+ printf_unfiltered ("sds_interrupt called\n");
+
+ buf[0] = 25;
+ sds_send (buf, 1);
+}
+
+static void (*ofunc)();
+
+/* The user typed ^C twice. */
+
+static void
+sds_interrupt_twice (signo)
+ int signo;
+{
+ signal (signo, ofunc);
+
+ interrupt_query ();
+
+ signal (signo, sds_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 ();
+}
+
+/* If nonzero, ignore the next kill. */
+int kill_kludge;
+
+/* 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
+sds_wait (pid, status)
+ int pid;
+ struct target_waitstatus *status;
+{
+ unsigned char buf[PBUFSIZ];
+ int retlen;
+
+ status->kind = TARGET_WAITKIND_EXITED;
+ status->value.integer = 0;
+
+ ofunc = (void (*)()) signal (SIGINT, sds_interrupt);
+
+ signal (SIGINT, ofunc);
+
+ if (just_started)
+ {
+ just_started = 0;
+ status->kind = TARGET_WAITKIND_STOPPED;
+ return inferior_pid;
+ }
+
+ while (1)
+ {
+ getmessage (buf, 1);
+
+ if (message_pending)
+ {
+ buf[0] = 26;
+ retlen = sds_send (buf, 1);
+ if (remote_debug)
+ {
+ fprintf_unfiltered (gdb_stderr, "Signals: %04x %02x %02x\n",
+ ((int) buf[0]) << 8 + buf[1],
+ buf[2], buf[3]);
+ }
+ message_pending = 0;
+ status->kind = TARGET_WAITKIND_STOPPED;
+ status->value.sig = TARGET_SIGNAL_TRAP;
+ goto got_status;
+ }
+ }
+ got_status:
+ return inferior_pid;
+}
+
+static unsigned char sprs[16];
+
+/* Read the remote registers into the block REGS. */
+/* Currently we just read all the registers, so we don't use regno. */
+
+/* ARGSUSED */
+static void
+sds_fetch_registers (regno)
+ int regno;
+{
+ unsigned char buf[PBUFSIZ];
+ int i, retlen;
+ char *p;
+ char regs[REGISTER_BYTES];
+
+ /* Unimplemented registers read as all bits zero. */
+ memset (regs, 0, REGISTER_BYTES);
+
+ buf[0] = 18;
+ buf[1] = 1;
+ buf[2] = 0;
+ retlen = sds_send (buf, 3);
+
+ for (i = 0; i < 4 * 6; ++i)
+ regs[i + 4 * 32 + 8 * 32] = buf[i];
+ for (i = 0; i < 4 * 4; ++i)
+ sprs[i] = buf[i + 4 * 7];
+
+ buf[0] = 18;
+ buf[1] = 2;
+ buf[2] = 0;
+ retlen = sds_send (buf, 3);
+
+ for (i = 0; i < retlen; i++)
+ regs[i] = buf[i];
+
+ /* (should warn about reply too short) */
+
+ for (i = 0; i < NUM_REGS; i++)
+ supply_register (i, &regs[REGISTER_BYTE(i)]);
+}
+
+/* Prepare to store registers. Since we may send them all, we have to
+ read out the ones we don't want to change first. */
+
+static void
+sds_prepare_to_store ()
+{
+ /* Make sure the entire registers array is valid. */
+ read_register_bytes (0, (char *)NULL, REGISTER_BYTES);
+}
+
+/* Store register REGNO, or all registers if REGNO == -1, from the contents
+ of REGISTERS. FIXME: ignores errors. */
+
+static void
+sds_store_registers (regno)
+ int regno;
+{
+ unsigned char *p, buf[PBUFSIZ];
+ int i;
+
+ /* Store all the special-purpose registers. */
+ p = buf;
+ *p++ = 19;
+ *p++ = 1;
+ *p++ = 0;
+ *p++ = 0;
+ for (i = 0; i < 4 * 6; i++)
+ *p++ = registers[i + 4 * 32 + 8 * 32];
+ for (i = 0; i < 4 * 1; i++)
+ *p++ = 0;
+ for (i = 0; i < 4 * 4; i++)
+ *p++ = sprs[i];
+
+ sds_send (buf, p - buf);
+
+ /* Store all the general-purpose registers. */
+ p = buf;
+ *p++ = 19;
+ *p++ = 2;
+ *p++ = 0;
+ *p++ = 0;
+ for (i = 0; i < 4 * 32; i++)
+ *p++ = registers[i];
+
+ sds_send (buf, p - buf);
+
+}
+
+/* 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
+sds_write_bytes (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+{
+ int max_buf_size; /* Max size of packet output buffer */
+ int origlen;
+ unsigned char buf[PBUFSIZ];
+ int todo;
+ int i;
+
+ /* Chop the transfer down if necessary */
+
+ max_buf_size = 150;
+
+ origlen = len;
+ while (len > 0)
+ {
+ todo = min (len, max_buf_size);
+
+ buf[0] = 13;
+ buf[1] = 0;
+ buf[2] = (int) (memaddr >> 24) & 0xff;
+ buf[3] = (int) (memaddr >> 16) & 0xff;
+ buf[4] = (int) (memaddr >> 8) & 0xff;
+ buf[5] = (int) (memaddr ) & 0xff;
+ buf[6] = 1;
+ buf[7] = 0;
+
+ for (i = 0; i < todo; i++)
+ buf[i + 8] = myaddr[i];
+
+ sds_send (buf, 8 + todo);
+
+ /* (should look at result) */
+
+ myaddr += todo;
+ memaddr += todo;
+ len -= todo;
+ }
+ return origlen;
+}
+
+/* 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
+sds_read_bytes (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+{
+ int max_buf_size; /* Max size of packet output buffer */
+ int origlen, retlen;
+ unsigned char buf[PBUFSIZ];
+ int todo;
+ int i;
+
+ /* Chop the transfer down if necessary */
+
+ max_buf_size = 150;
+
+ origlen = len;
+ while (len > 0)
+ {
+ todo = min (len, max_buf_size);
+
+ buf[0] = 12;
+ buf[1] = 0;
+ buf[2] = (int) (memaddr >> 24) & 0xff;
+ buf[3] = (int) (memaddr >> 16) & 0xff;
+ buf[4] = (int) (memaddr >> 8) & 0xff;
+ buf[5] = (int) (memaddr ) & 0xff;
+ buf[6] = (int) (todo >> 8) & 0xff;
+ buf[7] = (int) (todo ) & 0xff;
+ buf[8] = 1;
+
+ retlen = sds_send (buf, 9);
+
+ if (retlen - 2 != todo)
+ {
+ return 0;
+ }
+
+ /* Reply describes memory byte by byte. */
+
+ for (i = 0; i < todo; i++)
+ myaddr[i] = buf[i + 2];
+
+ myaddr += todo;
+ memaddr += todo;
+ len -= todo;
+ }
+
+ return origlen;
+}
+
+/* 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
+sds_xfer_memory(memaddr, myaddr, len, should_write, target)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+ int should_write;
+ struct target_ops *target; /* ignored */
+{
+ return dcache_xfer_memory (sds_dcache, memaddr, myaddr, len, should_write);
+}
+
+
+static void
+sds_files_info (ignore)
+ struct target_ops *ignore;
+{
+ puts_filtered ("Debugging over a serial connection, using SDS protocol.\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 (timeout)
+ int timeout;
+{
+ int ch;
+
+ ch = SERIAL_READCHAR (sds_desc, timeout);
+
+ if (remote_debug > 1 && ch >= 0)
+ printf_unfiltered("%c(%x)", ch, ch);
+
+ switch (ch)
+ {
+ case SERIAL_EOF:
+ error ("Remote connection closed");
+ case SERIAL_ERROR:
+ perror_with_name ("Remote communication error");
+ case SERIAL_TIMEOUT:
+ return ch;
+ default:
+ return ch & 0x7f;
+ }
+}
+
+/* An SDS-style checksum is a sum of the bytes modulo 253. (Presumably
+ because 253, 254, and 255 are special flags in the protocol.) */
+
+static int
+compute_checksum (csum, buf, len)
+ int csum, len;
+ char *buf;
+{
+ int i;
+
+ for (i = 0; i < len; ++i)
+ csum += (unsigned char) buf[i];
+
+ csum %= 253;
+ return csum;
+}
+
+/* Send the command in BUF to the remote machine, and read the reply
+ into BUF also. */
+
+static int
+sds_send (buf, len)
+ unsigned char *buf;
+ int len;
+{
+ putmessage (buf, len);
+
+ return getmessage (buf, 0);
+}
+
+/* Send a message to the remote machine. */
+
+static int
+putmessage (buf, len)
+ unsigned char *buf;
+ int len;
+{
+ int i, enclen;
+ unsigned char csum = 0;
+ char buf2[PBUFSIZ], buf3[PBUFSIZ];
+ unsigned char header[3];
+ int ch;
+ int tcount = 0;
+ char *p;
+
+ /* Copy the packet into buffer BUF2, encapsulating it
+ and giving it a checksum. */
+
+ if (len > 170) /* Prosanity check */
+ abort();
+
+ if (remote_debug)
+ {
+ fprintf_unfiltered (gdb_stderr, "Message to send: \"");
+ for (i = 0; i < len; ++i)
+ fprintf_unfiltered (gdb_stderr, "%02x", buf[i]);
+ fprintf_unfiltered (gdb_stderr, "\"\n");
+ }
+
+ p = buf2;
+ *p++ = '$';
+
+ if (len % 3 != 0)
+ {
+ buf[len] = '\0';
+ buf[len+1] = '\0';
+ }
+
+ header[1] = next_msg_id;
+
+ header[2] = len;
+
+ csum = compute_checksum (csum, buf, len);
+ csum = compute_checksum (csum, header + 1, 2);
+
+ header[0] = csum;
+
+ tob64 (header, p, 3);
+ p += 4;
+ enclen = tob64 (buf, buf3, ((len + 2) / 3) * 3);
+
+ for (i = 0; i < enclen; ++i)
+ *p++ = buf3[i];
+ *p++ = '\r';
+ *p++ = '\n';
+
+ next_msg_id = (next_msg_id + 3) % 245;
+
+ /* Send it over and over until we get a positive ack. */
+
+ while (1)
+ {
+ int started_error_output = 0;
+
+ if (remote_debug)
+ {
+ *p = '\0';
+ printf_unfiltered ("Sending encoded: \"%s\"", buf2);
+ printf_unfiltered (" (Checksum %d, id %d, length %d)\n",
+ header[0], header[1], header[2]);
+ gdb_flush (gdb_stdout);
+ }
+ if (SERIAL_WRITE (sds_desc, buf2, p - buf2))
+ perror_with_name ("putmessage: write failed");
+
+ return 1;
+
+ }
+
+}
+
+/* Come here after finding the start of the frame. Collect the rest
+ into BUF. Returns 0 on any error, 1 on success. */
+
+static int
+read_frame (buf)
+ char *buf;
+{
+ char *bp;
+ int c;
+
+ bp = buf;
+
+ while (1)
+ {
+ c = readchar (sds_timeout);
+
+ switch (c)
+ {
+ case SERIAL_TIMEOUT:
+ if (remote_debug)
+ puts_filtered ("Timeout in mid-message, retrying\n");
+ return 0;
+ case '$':
+ if (remote_debug)
+ puts_filtered ("Saw new packet start in middle of old one\n");
+ return 0; /* Start a new packet, count retries */
+ case '\r':
+ break;
+
+ case '\n':
+ {
+ *bp = '\000';
+ if (remote_debug)
+ fprintf_unfiltered (gdb_stderr, "Received encoded: \"%s\"\n",
+ buf);
+ return 1;
+ }
+
+ default:
+ if (bp < buf + PBUFSIZ - 1)
+ {
+ *bp++ = c;
+ continue;
+ }
+
+ *bp = '\0';
+ puts_filtered ("Message too long: ");
+ puts_filtered (buf);
+ puts_filtered ("\n");
+
+ return 0;
+ }
+ }
+}
+
+/* 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 int
+getmessage (buf, forever)
+ unsigned char *buf;
+ int forever;
+{
+ int c, c2, c3;
+ int tries;
+ int timeout;
+ int val, i, len, csum;
+ unsigned char header[3];
+ unsigned char inbuf[500];
+
+ strcpy (buf, "timeout");
+
+ if (forever)
+ {
+#ifdef MAINTENANCE_CMDS
+ timeout = watchdog > 0 ? watchdog : -1;
+#else
+ timeout = -1;
+#endif
+ }
+
+ else
+ timeout = sds_timeout;
+
+#define MAX_TRIES 3
+
+ for (tries = 1; tries <= MAX_TRIES; tries++)
+ {
+ /* 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. */
+
+ /* Note that we will only wait forever prior to the start of a packet.
+ After that, we expect characters to arrive at a brisk pace. They
+ should show up within sds_timeout intervals. */
+
+ do
+ {
+ c = readchar (timeout);
+
+ if (c == SERIAL_TIMEOUT)
+ {
+#ifdef MAINTENANCE_CMDS
+ if (forever) /* Watchdog went off. Kill the target. */
+ {
+ target_mourn_inferior ();
+ error ("Watchdog has expired. Target detached.\n");
+ }
+#endif
+ if (remote_debug)
+ puts_filtered ("Timed out.\n");
+ goto retry;
+ }
+ }
+ while (c != '$' && c != '{');
+
+ /* We might have seen a "trigraph", a sequence of three characters
+ that indicate various sorts of communication state. */
+
+ if (c == '{')
+ {
+ /* Read the other two chars of the trigraph. */
+ c2 = readchar (timeout);
+ c3 = readchar (timeout);
+ if (remote_debug)
+ fprintf_unfiltered (gdb_stderr, "Trigraph %c%c%c received\n",
+ c, c2, c3);
+ if (c3 == '+')
+ {
+ message_pending = 1;
+ return 0; /*????*/
+ }
+ continue;
+ }
+
+ val = read_frame (inbuf);
+
+ if (val == 1)
+ {
+ fromb64 (inbuf, header, 4);
+ /* (should check out other bits) */
+ fromb64 (inbuf + 4, buf, strlen (inbuf) - 4);
+
+ len = header[2];
+
+ csum = 0;
+ csum = compute_checksum (csum, buf, len);
+ csum = compute_checksum (csum, header + 1, 2);
+
+ if (csum != header[0])
+ fprintf_unfiltered (gdb_stderr,
+ "Checksum mismatch: computed %d, received %d\n",
+ csum, header[0]);
+
+ if (header[2] == 0xff)
+ fprintf_unfiltered (gdb_stderr, "Requesting resend...\n");
+
+ if (remote_debug)
+ {
+ fprintf_unfiltered (gdb_stderr,
+ "... (Got checksum %d, id %d, length %d)\n",
+ header[0], header[1], header[2]);
+ fprintf_unfiltered (gdb_stderr, "Message received: \"");
+ for (i = 0; i < len; ++i)
+ {
+ fprintf_unfiltered (gdb_stderr, "%02x", (unsigned char) buf[i]);
+ }
+ fprintf_unfiltered (gdb_stderr, "\"\n");
+ }
+
+ /* no ack required? */
+ return len;
+ }
+
+ /* Try the whole thing again. */
+ retry:
+ /* need to do something here */
+ }
+
+ /* We have tried hard enough, and just can't receive the packet. Give up. */
+
+ printf_unfiltered ("Ignoring packet error, continuing...\n");
+ return 0;
+}
+
+static void
+sds_kill ()
+{
+ /* Don't try to do anything to the target. */
+}
+
+static void
+sds_mourn ()
+{
+ unpush_target (&sds_ops);
+ generic_mourn_inferior ();
+}
+
+static void
+sds_create_inferior (exec_file, args, env)
+ char *exec_file;
+ char *args;
+ char **env;
+{
+ inferior_pid = 42000;
+
+ /* Clean up from the last time we were running. */
+ clear_proceed_status ();
+
+ /* Let the remote process run. */
+ proceed (bfd_get_start_address (exec_bfd), TARGET_SIGNAL_0, 0);
+}
+
+static void
+sds_load (filename, from_tty)
+ char *filename;
+ int from_tty;
+{
+ generic_load (filename, from_tty);
+
+ inferior_pid = 0;
+}
+
+/* The SDS monitor has commands for breakpoint insertion, although it
+ it doesn't actually manage the breakpoints, it just returns the
+ replaced instruction back to the debugger. */
+
+static int
+sds_insert_breakpoint (addr, contents_cache)
+ CORE_ADDR addr;
+ char *contents_cache;
+{
+ int i, retlen;
+ unsigned char *p, buf[PBUFSIZ];
+
+ p = buf;
+ *p++ = 16;
+ *p++ = 0;
+ *p++ = (int) (addr >> 24) & 0xff;
+ *p++ = (int) (addr >> 16) & 0xff;
+ *p++ = (int) (addr >> 8) & 0xff;
+ *p++ = (int) (addr ) & 0xff;
+
+ retlen = sds_send (buf, p - buf);
+
+ for (i = 0; i < 4; ++i)
+ contents_cache[i] = buf[i + 2];
+
+ return 0;
+}
+
+static int
+sds_remove_breakpoint (addr, contents_cache)
+ CORE_ADDR addr;
+ char *contents_cache;
+{
+ int i, retlen;
+ unsigned char *p, buf[PBUFSIZ];
+
+ p = buf;
+ *p++ = 17;
+ *p++ = 0;
+ *p++ = (int) (addr >> 24) & 0xff;
+ *p++ = (int) (addr >> 16) & 0xff;
+ *p++ = (int) (addr >> 8) & 0xff;
+ *p++ = (int) (addr ) & 0xff;
+ for (i = 0; i < 4; ++i)
+ *p++ = contents_cache[i];
+
+ retlen = sds_send (buf, p - buf);
+
+ return 0;
+}
+
+static void
+init_sds_ops ()
+{
+ sds_ops.to_shortname = "sds";
+ sds_ops.to_longname = "Remote serial target with SDS protocol";
+ sds_ops.to_doc = "Use a remote computer via a serial line; using the SDS protocol.\n\
+Specify the serial device it is connected to (e.g. /dev/ttya).";
+ sds_ops.to_open = sds_open;
+ sds_ops.to_close = sds_close;
+ sds_ops.to_detach = sds_detach;
+ sds_ops.to_resume = sds_resume;
+ sds_ops.to_wait = sds_wait;
+ sds_ops.to_fetch_registers = sds_fetch_registers;
+ sds_ops.to_store_registers = sds_store_registers;
+ sds_ops.to_prepare_to_store = sds_prepare_to_store;
+ sds_ops.to_xfer_memory = sds_xfer_memory;
+ sds_ops.to_files_info = sds_files_info;
+ sds_ops.to_insert_breakpoint = sds_insert_breakpoint;
+ sds_ops.to_remove_breakpoint = sds_remove_breakpoint;
+ sds_ops.to_kill = sds_kill;
+ sds_ops.to_load = sds_load;
+ sds_ops.to_create_inferior = sds_create_inferior;
+ sds_ops.to_mourn_inferior = sds_mourn;
+ sds_ops.to_stratum = process_stratum;
+ sds_ops.to_has_all_memory = 1;
+ sds_ops.to_has_memory = 1;
+ sds_ops.to_has_stack = 1;
+ sds_ops.to_has_registers = 1;
+ sds_ops.to_has_execution = 1;
+ sds_ops.to_magic = OPS_MAGIC;
+}
+
+/* Put a command string, in args, out to the monitor and display the
+ reply message. */
+
+static void
+sds_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ char *p;
+ int i, len, retlen;
+ unsigned char buf[1000];
+
+ /* Convert hexadecimal chars into a byte buffer. */
+ p = args;
+ len = 0;
+ while (*p != '\0')
+ {
+ buf[len++] = fromhex (p[0]) * 16 + fromhex (p[1]);
+ if (p[1] == '\0')
+ break;
+ p += 2;
+ }
+
+ retlen = sds_send (buf, len);
+
+ printf_filtered ("Reply is ");
+ for (i = 0; i < retlen; ++i)
+ {
+ printf_filtered ("%02x", buf[i]);
+ }
+ printf_filtered ("\n");
+}
+
+void
+_initialize_remote_sds ()
+{
+ init_sds_ops ();
+ add_target (&sds_ops);
+
+ add_show_from_set (add_set_cmd ("sdstimeout", no_class,
+ var_integer, (char *)&sds_timeout,
+ "Set timeout value for sds read.\n", &setlist),
+ &showlist);
+
+ add_com ("sds", class_obscure, sds_command,
+ "Send a command to the SDS monitor.");
+}
diff --git a/gdb/remote-sim.c b/gdb/remote-sim.c
new file mode 100644
index 00000000000..e10fcedd6b7
--- /dev/null
+++ b/gdb/remote-sim.c
@@ -0,0 +1,1003 @@
+/* Generic remote debugging interface for simulators.
+ Copyright 1993, 1994, 1996, 1997 Free Software Foundation, Inc.
+ Contributed by Cygnus Support.
+ Steve Chamberlain (sac@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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "inferior.h"
+#include "wait.h"
+#include "value.h"
+#include "gdb_string.h"
+#include <ctype.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <setjmp.h>
+#include <errno.h>
+#include "terminal.h"
+#include "target.h"
+#include "gdbcore.h"
+#include "callback.h"
+#include "remote-sim.h"
+#include "remote-utils.h"
+#include "command.h"
+
+/* Prototypes */
+
+static void dump_mem PARAMS ((char *buf, int len));
+
+static void init_callbacks PARAMS ((void));
+
+static void end_callbacks PARAMS ((void));
+
+static int gdb_os_write_stdout PARAMS ((host_callback *, const char *, int));
+
+static void gdb_os_flush_stdout PARAMS ((host_callback *));
+
+static int gdb_os_write_stderr PARAMS ((host_callback *, const char *, int));
+
+static void gdb_os_flush_stderr PARAMS ((host_callback *));
+
+static int gdb_os_poll_quit PARAMS ((host_callback *));
+
+/* printf_filtered is depreciated */
+static void gdb_os_printf_filtered PARAMS ((host_callback *, const char *, ...));
+
+static void gdb_os_vprintf_filtered PARAMS ((host_callback *, const char *, va_list));
+
+static void gdb_os_evprintf_filtered PARAMS ((host_callback *, const char *, va_list));
+
+static void gdb_os_error PARAMS ((host_callback *, const char *, ...));
+
+static void gdbsim_fetch_register PARAMS ((int regno));
+
+static void gdbsim_store_register PARAMS ((int regno));
+
+static void gdbsim_kill PARAMS ((void));
+
+static void gdbsim_load PARAMS ((char *prog, int fromtty));
+
+static void gdbsim_create_inferior PARAMS ((char *exec_file, char *args, char **env));
+
+static void gdbsim_open PARAMS ((char *args, int from_tty));
+
+static void gdbsim_close PARAMS ((int quitting));
+
+static void gdbsim_detach PARAMS ((char *args, int from_tty));
+
+static void gdbsim_resume PARAMS ((int pid, int step, enum target_signal siggnal));
+
+static int gdbsim_wait PARAMS ((int pid, struct target_waitstatus *status));
+
+static void gdbsim_prepare_to_store PARAMS ((void));
+
+static int gdbsim_xfer_inferior_memory PARAMS ((CORE_ADDR memaddr,
+ char *myaddr, int len,
+ int write,
+ struct target_ops *target));
+
+static void gdbsim_files_info PARAMS ((struct target_ops *target));
+
+static void gdbsim_mourn_inferior PARAMS ((void));
+
+static void gdbsim_stop PARAMS ((void));
+
+void simulator_command PARAMS ((char *args, int from_tty));
+
+/* Naming convention:
+
+ sim_* are the interface to the simulator (see remote-sim.h).
+ gdbsim_* are stuff which is internal to gdb. */
+
+/* Forward data declarations */
+extern struct target_ops gdbsim_ops;
+
+static int program_loaded = 0;
+
+/* We must keep track of whether the simulator has been opened or not because
+ GDB can call a target's close routine twice, but sim_close doesn't allow
+ this. We also need to record the result of sim_open so we can pass it
+ back to the other sim_foo routines. */
+static SIM_DESC gdbsim_desc = 0;
+
+static void
+dump_mem (buf, len)
+ char *buf;
+ int len;
+{
+ if (len <= 8)
+ {
+ if (len == 8 || len == 4)
+ {
+ long l[2];
+ memcpy (l, buf, len);
+ printf_filtered ("\t0x%x", l[0]);
+ printf_filtered (len == 8 ? " 0x%x\n" : "\n", l[1]);
+ }
+ else
+ {
+ int i;
+ printf_filtered ("\t");
+ for (i = 0; i < len; i++)
+ printf_filtered ("0x%x ", buf[i]);
+ printf_filtered ("\n");
+ }
+ }
+}
+
+static host_callback gdb_callback;
+static int callbacks_initialized = 0;
+
+/* Initialize gdb_callback. */
+
+static void
+init_callbacks ()
+{
+ if (! callbacks_initialized)
+ {
+ gdb_callback = default_callback;
+ gdb_callback.init (&gdb_callback);
+ gdb_callback.write_stdout = gdb_os_write_stdout;
+ gdb_callback.flush_stdout = gdb_os_flush_stdout;
+ gdb_callback.write_stderr = gdb_os_write_stderr;
+ gdb_callback.flush_stderr = gdb_os_flush_stderr;
+ gdb_callback.printf_filtered = gdb_os_printf_filtered;
+ gdb_callback.vprintf_filtered = gdb_os_vprintf_filtered;
+ gdb_callback.evprintf_filtered = gdb_os_evprintf_filtered;
+ gdb_callback.error = gdb_os_error;
+ gdb_callback.poll_quit = gdb_os_poll_quit;
+ gdb_callback.magic = HOST_CALLBACK_MAGIC;
+ callbacks_initialized = 1;
+ }
+}
+
+/* Release callbacks (free resources used by them). */
+
+static void
+end_callbacks ()
+{
+ if (callbacks_initialized)
+ {
+ gdb_callback.shutdown (&gdb_callback);
+ callbacks_initialized = 0;
+ }
+}
+
+/* GDB version of os_write_stdout callback. */
+
+static int
+gdb_os_write_stdout (p, buf, len)
+ host_callback *p;
+ const char *buf;
+ int len;
+{
+ int i;
+ char b[2];
+
+ for (i = 0; i < len; i++)
+ {
+ b[0] = buf[i];
+ b[1] = 0;
+ if (target_output_hook)
+ target_output_hook (b);
+ else
+ fputs_filtered (b, gdb_stdout);
+ }
+ return len;
+}
+
+/* GDB version of os_flush_stdout callback. */
+
+static void
+gdb_os_flush_stdout (p)
+ host_callback *p;
+{
+ gdb_flush (gdb_stdout);
+}
+
+/* GDB version of os_write_stderr callback. */
+
+static int
+gdb_os_write_stderr (p, buf, len)
+ host_callback *p;
+ const char *buf;
+ int len;
+{
+ int i;
+ char b[2];
+
+ for (i = 0; i < len; i++)
+ {
+ b[0] = buf[i];
+ b[1] = 0;
+ if (target_output_hook)
+ target_output_hook (b);
+ else
+ fputs_filtered (b, gdb_stderr);
+ }
+ return len;
+}
+
+/* GDB version of os_flush_stderr callback. */
+
+static void
+gdb_os_flush_stderr (p)
+ host_callback *p;
+{
+ gdb_flush (gdb_stderr);
+}
+
+/* GDB version of printf_filtered callback. */
+
+/* VARARGS */
+static void
+#ifdef ANSI_PROTOTYPES
+gdb_os_printf_filtered (host_callback *p, const char *format, ...)
+#else
+gdb_os_printf_filtered (p, va_alist)
+ host_callback *p;
+ va_dcl
+#endif
+{
+ va_list args;
+#ifdef ANSI_PROTOTYPES
+ va_start (args, format);
+#else
+ char *format;
+
+ va_start (args);
+ format = va_arg (args, char *);
+#endif
+
+ vfprintf_filtered (gdb_stdout, format, args);
+
+ va_end (args);
+}
+
+/* GDB version of error vprintf_filtered. */
+
+/* VARARGS */
+static void
+#ifdef ANSI_PROTOTYPES
+gdb_os_vprintf_filtered (host_callback *p, const char *format, va_list ap)
+#else
+gdb_os_vprintf_filtered (p, format, ap)
+ host_callback *p;
+ char *format;
+ va_list ap;
+#endif
+{
+ vfprintf_filtered (gdb_stdout, format, ap);
+}
+
+/* GDB version of error evprintf_filtered. */
+
+/* VARARGS */
+static void
+#ifdef ANSI_PROTOTYPES
+gdb_os_evprintf_filtered (host_callback *p, const char *format, va_list ap)
+#else
+gdb_os_evprintf_filtered (p, format, ap)
+ host_callback *p;
+ char *format;
+ va_list ap;
+#endif
+{
+ vfprintf_filtered (gdb_stderr, format, ap);
+}
+
+/* GDB version of error callback. */
+
+/* VARARGS */
+static void
+#ifdef ANSI_PROTOTYPES
+gdb_os_error (host_callback *p, const char *format, ...)
+#else
+gdb_os_error (p, va_alist)
+ host_callback *p;
+ va_dcl
+#endif
+{
+ if (error_hook)
+ (*error_hook) ();
+ else
+ {
+ va_list args;
+#ifdef ANSI_PROTOTYPES
+ va_start (args, format);
+#else
+ char *format;
+
+ va_start (args);
+ format = va_arg (args, char *);
+#endif
+
+ error_begin ();
+ vfprintf_filtered (gdb_stderr, format, args);
+ fprintf_filtered (gdb_stderr, "\n");
+ va_end (args);
+ return_to_top_level (RETURN_ERROR);
+ }
+}
+
+static void
+gdbsim_fetch_register (regno)
+ int regno;
+{
+ static int warn_user = 1;
+ if (regno == -1)
+ {
+ for (regno = 0; regno < NUM_REGS; regno++)
+ gdbsim_fetch_register (regno);
+ }
+ else if (REGISTER_NAME (regno) != NULL && *REGISTER_NAME (regno) != '\0')
+ {
+ char buf[MAX_REGISTER_RAW_SIZE];
+ int nr_bytes = sim_fetch_register (gdbsim_desc, regno, buf, REGISTER_RAW_SIZE (regno));
+ if (nr_bytes == 0)
+ /* register not applicable, supply zero's */
+ memset (buf, 0, MAX_REGISTER_RAW_SIZE);
+ else if (nr_bytes > 0 && nr_bytes != REGISTER_RAW_SIZE (regno)
+ && warn_user)
+ {
+ printf_unfiltered ("Size of register %s (%d) incorrect (%d instead of %d))",
+ REGISTER_NAME (regno), regno,
+ nr_bytes, REGISTER_RAW_SIZE (regno));
+ warn_user = 0;
+ }
+ supply_register (regno, buf);
+ if (sr_get_debug ())
+ {
+ printf_filtered ("gdbsim_fetch_register: %d", regno);
+ /* FIXME: We could print something more intelligible. */
+ dump_mem (buf, REGISTER_RAW_SIZE (regno));
+ }
+ }
+}
+
+
+static void
+gdbsim_store_register (regno)
+ int regno;
+{
+ if (regno == -1)
+ {
+ for (regno = 0; regno < NUM_REGS; regno++)
+ gdbsim_store_register (regno);
+ }
+ else if (REGISTER_NAME (regno) != NULL && *REGISTER_NAME (regno) != '\0')
+ {
+ char tmp[MAX_REGISTER_RAW_SIZE];
+ int nr_bytes;
+ read_register_gen (regno, tmp);
+ nr_bytes = sim_store_register (gdbsim_desc, regno, tmp, REGISTER_RAW_SIZE (regno));
+ if (nr_bytes > 0 && nr_bytes != REGISTER_RAW_SIZE (regno))
+ fatal ("Register size different to expected");
+ if (sr_get_debug ())
+ {
+ printf_filtered ("gdbsim_store_register: %d", regno);
+ /* FIXME: We could print something more intelligible. */
+ dump_mem (tmp, REGISTER_RAW_SIZE (regno));
+ }
+ }
+}
+
+/* Kill the running program. This may involve closing any open files
+ and releasing other resources acquired by the simulated program. */
+
+static void
+gdbsim_kill ()
+{
+ if (sr_get_debug ())
+ printf_filtered ("gdbsim_kill\n");
+
+ /* There is no need to `kill' running simulator - the simulator is
+ not running */
+ inferior_pid = 0;
+}
+
+/* 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. */
+
+static void
+gdbsim_load (prog, fromtty)
+ char *prog;
+ int fromtty;
+{
+ if (sr_get_debug ())
+ printf_filtered ("gdbsim_load: prog \"%s\"\n", prog);
+
+ inferior_pid = 0;
+
+ /* FIXME: We will print two messages on error.
+ Need error to either not print anything if passed NULL or need
+ another routine that doesn't take any arguments. */
+ if (sim_load (gdbsim_desc, prog, NULL, fromtty) == SIM_RC_FAIL)
+ error ("unable to load program");
+
+ /* FIXME: If a load command should reset the targets registers then
+ a call to sim_create_inferior() should go here. */
+
+ program_loaded = 1;
+}
+
+
+/* Start an inferior process and set inferior_pid to its pid.
+ EXEC_FILE is the file to run.
+ ARGS 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. */
+/* This is called not only when we first attach, but also when the
+ user types "run" after having attached. */
+
+static void
+gdbsim_create_inferior (exec_file, args, env)
+ char *exec_file;
+ char *args;
+ char **env;
+{
+ int len;
+ char *arg_buf,**argv;
+
+ if (exec_file == 0 || exec_bfd == 0)
+ warning ("No executable file specified.");
+ if (! program_loaded)
+ warning ("No program loaded.");
+
+ if (sr_get_debug ())
+ printf_filtered ("gdbsim_create_inferior: exec_file \"%s\", args \"%s\"\n",
+ (exec_file ? exec_file: "(NULL)"),
+ args);
+
+ gdbsim_kill ();
+ remove_breakpoints ();
+ init_wait_for_inferior ();
+
+ if (exec_file != NULL)
+ {
+ len = strlen (exec_file) + 1 + strlen (args) + 1 + /*slop*/ 10;
+ arg_buf = (char *) alloca (len);
+ arg_buf[0] = '\0';
+ strcat (arg_buf, exec_file);
+ strcat (arg_buf, " ");
+ strcat (arg_buf, args);
+ argv = buildargv (arg_buf);
+ make_cleanup ((make_cleanup_func) freeargv, argv);
+ }
+ else
+ argv = NULL;
+ sim_create_inferior (gdbsim_desc, exec_bfd, argv, env);
+
+ inferior_pid = 42;
+ insert_breakpoints (); /* Needed to get correct instruction in cache */
+
+ clear_proceed_status ();
+
+ /* NB: Entry point already set by sim_create_inferior. */
+ proceed ((CORE_ADDR)-1, TARGET_SIGNAL_DEFAULT, 0);
+}
+
+/* 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. */
+/* Called when selecting the simulator. EG: (gdb) target sim name. */
+
+static void
+gdbsim_open (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ int len;
+ char *arg_buf;
+ char **argv;
+
+ if (sr_get_debug ())
+ printf_filtered ("gdbsim_open: args \"%s\"\n", args ? args : "(null)");
+
+ /* Remove current simulator if one exists. Only do this if the simulator
+ has been opened because sim_close requires it.
+ This is important because the call to push_target below will cause
+ sim_close to be called if the simulator is already open, but push_target
+ is called after sim_open! We can't move the call to push_target before
+ the call to sim_open because sim_open may invoke `error'. */
+ if (gdbsim_desc != NULL)
+ unpush_target (&gdbsim_ops);
+
+ len = (7 + 1 /* gdbsim */
+ + strlen (" -E little")
+ + strlen (" --architecture=xxxxxxxxxx")
+ + (args ? strlen (args) : 0)
+ + 50) /* slack */;
+ arg_buf = (char *) alloca (len);
+ strcpy (arg_buf, "gdbsim"); /* 7 */
+ /* Specify the byte order for the target when it is both selectable
+ and explicitly specified by the user (not auto detected). */
+ if (TARGET_BYTE_ORDER_SELECTABLE_P
+ && !TARGET_BYTE_ORDER_AUTO)
+ {
+ switch (TARGET_BYTE_ORDER)
+ {
+ case BIG_ENDIAN:
+ strcat (arg_buf, " -E big");
+ break;
+ case LITTLE_ENDIAN:
+ strcat (arg_buf, " -E little");
+ break;
+ default:
+ fatal ("Value of TARGET_BYTE_ORDER unknown");
+ }
+ }
+ /* Specify the architecture of the target when it has been
+ explicitly specified */
+ if (!TARGET_ARCHITECTURE_AUTO)
+ {
+ strcat (arg_buf, " --architecture=");
+ strcat (arg_buf, TARGET_ARCHITECTURE->printable_name);
+ }
+ /* finally, any explicit args */
+ if (args)
+ {
+ strcat (arg_buf, " "); /* 1 */
+ strcat (arg_buf, args);
+ }
+ argv = buildargv (arg_buf);
+ if (argv == NULL)
+ error ("Insufficient memory available to allocate simulator arg list.");
+ make_cleanup ((make_cleanup_func) freeargv, argv);
+
+ init_callbacks ();
+ gdbsim_desc = sim_open (SIM_OPEN_DEBUG, &gdb_callback, exec_bfd, argv);
+
+ if (gdbsim_desc == 0)
+ error ("unable to create simulator instance");
+
+ push_target (&gdbsim_ops);
+ target_fetch_registers (-1);
+ printf_filtered ("Connected to the simulator.\n");
+}
+
+/* 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. */
+/* Close out all files and local state before this target loses control. */
+
+static void
+gdbsim_close (quitting)
+ int quitting;
+{
+ if (sr_get_debug ())
+ printf_filtered ("gdbsim_close: quitting %d\n", quitting);
+
+ program_loaded = 0;
+
+ if (gdbsim_desc != NULL)
+ {
+ sim_close (gdbsim_desc, quitting);
+ gdbsim_desc = NULL;
+ }
+
+ end_callbacks ();
+}
+
+/* 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. */
+/* Terminate the open connection to the remote debugger.
+ Use this when you want to detach and do something else with your gdb. */
+
+static void
+gdbsim_detach (args,from_tty)
+ char *args;
+ int from_tty;
+{
+ if (sr_get_debug ())
+ printf_filtered ("gdbsim_detach: args \"%s\"\n", args);
+
+ pop_target (); /* calls gdbsim_close to do the real work */
+ if (from_tty)
+ printf_filtered ("Ending simulator %s debugging\n", target_shortname);
+}
+
+/* Resume execution of the target process. STEP says whether to single-step
+ or to run free; SIGGNAL is the signal value (e.g. SIGINT) to be given
+ to the target, or zero for no signal. */
+
+static enum target_signal resume_siggnal;
+static int resume_step;
+
+static void
+gdbsim_resume (pid, step, siggnal)
+ int pid, step;
+ enum target_signal siggnal;
+{
+ if (inferior_pid != 42)
+ error ("The program is not being run.");
+
+ if (sr_get_debug ())
+ printf_filtered ("gdbsim_resume: step %d, signal %d\n", step, siggnal);
+
+ resume_siggnal = siggnal;
+ resume_step = step;
+}
+
+/* Notify the simulator of an asynchronous request to stop.
+
+ The simulator shall ensure that the stop request is eventually
+ delivered to the simulator. If the call is made while the
+ simulator is not running then the stop request is processed when
+ the simulator is next resumed.
+
+ For simulators that do not support this operation, just abort */
+
+static void
+gdbsim_stop ()
+{
+ if (! sim_stop (gdbsim_desc))
+ {
+ quit ();
+ }
+}
+
+/* GDB version of os_poll_quit callback.
+ Taken from gdb/util.c - should be in a library */
+
+static int
+gdb_os_poll_quit (p)
+ host_callback *p;
+{
+ notice_quit ();
+ if (quit_flag) /* gdb's idea of quit */
+ {
+ quit_flag = 0; /* we've stolen it */
+ return 1;
+ }
+ else if (immediate_quit)
+ {
+ return 1;
+ }
+ return 0;
+}
+
+/* Wait for inferior process to do something. Return pid of child,
+ or -1 in case of error; store status through argument pointer STATUS,
+ just as `wait' would. */
+
+static void
+gdbsim_cntrl_c (signo)
+ int signo;
+{
+ gdbsim_stop ();
+}
+
+static int
+gdbsim_wait (pid, status)
+ int pid;
+ struct target_waitstatus *status;
+{
+ static RETSIGTYPE (*prev_sigint) ();
+ int sigrc = 0;
+ enum sim_stop reason = sim_running;
+
+ if (sr_get_debug ())
+ printf_filtered ("gdbsim_wait\n");
+
+#if defined (HAVE_SIGACTION) && defined (SA_RESTART)
+ {
+ struct sigaction sa, osa;
+ sa.sa_handler = gdbsim_cntrl_c;
+ sigemptyset (&sa.sa_mask);
+ sa.sa_flags = 0;
+ sigaction (SIGINT, &sa, &osa);
+ prev_sigint = osa.sa_handler;
+ }
+#else
+ prev_sigint = signal (SIGINT, gdbsim_cntrl_c);
+#endif
+ sim_resume (gdbsim_desc, resume_step,
+ target_signal_to_host (resume_siggnal));
+ signal (SIGINT, prev_sigint);
+ resume_step = 0;
+
+ sim_stop_reason (gdbsim_desc, &reason, &sigrc);
+
+ switch (reason)
+ {
+ case sim_exited:
+ status->kind = TARGET_WAITKIND_EXITED;
+ status->value.integer = sigrc;
+ break;
+ case sim_stopped:
+ switch (sigrc)
+ {
+ case SIGABRT:
+ quit ();
+ break;
+ case SIGINT:
+ case SIGTRAP:
+ default:
+ status->kind = TARGET_WAITKIND_STOPPED;
+ /* The signal in sigrc is a host signal. That probably
+ should be fixed. */
+ status->value.sig = target_signal_from_host (sigrc);
+ break;
+ }
+ break;
+ case sim_signalled:
+ status->kind = TARGET_WAITKIND_SIGNALLED;
+ /* The signal in sigrc is a host signal. That probably
+ should be fixed. */
+ status->value.sig = target_signal_from_host (sigrc);
+ break;
+ case sim_running:
+ case sim_polling:
+ /* FIXME: Is this correct? */
+ break;
+ }
+
+ return inferior_pid;
+}
+
+/* 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
+gdbsim_prepare_to_store ()
+{
+ /* Do nothing, since we can store individual regs */
+}
+
+static int
+gdbsim_xfer_inferior_memory (memaddr, myaddr, len, write, target)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+ int write;
+ struct target_ops *target; /* ignored */
+{
+ if (! program_loaded)
+ error ("No program loaded.");
+
+ if (sr_get_debug ())
+ {
+ printf_filtered ("gdbsim_xfer_inferior_memory: myaddr 0x%x, memaddr 0x%x, len %d, write %d\n",
+ myaddr, memaddr, len, write);
+ if (sr_get_debug () && write)
+ dump_mem(myaddr, len);
+ }
+
+ if (write)
+ {
+ len = sim_write (gdbsim_desc, memaddr, myaddr, len);
+ }
+ else
+ {
+ len = sim_read (gdbsim_desc, memaddr, myaddr, len);
+ if (sr_get_debug () && len > 0)
+ dump_mem(myaddr, len);
+ }
+ return len;
+}
+
+static void
+gdbsim_files_info (target)
+ struct target_ops *target;
+{
+ char *file = "nothing";
+
+ if (exec_bfd)
+ file = bfd_get_filename (exec_bfd);
+
+ if (sr_get_debug ())
+ printf_filtered ("gdbsim_files_info: file \"%s\"\n", file);
+
+ if (exec_bfd)
+ {
+ printf_filtered ("\tAttached to %s running program %s\n",
+ target_shortname, file);
+ sim_info (gdbsim_desc, 0);
+ }
+}
+
+/* Clear the simulator's notion of what the break points are. */
+
+static void
+gdbsim_mourn_inferior ()
+{
+ if (sr_get_debug ())
+ printf_filtered ("gdbsim_mourn_inferior:\n");
+
+ remove_breakpoints ();
+ generic_mourn_inferior ();
+}
+
+static int
+gdbsim_insert_breakpoint (addr, contents_cache)
+ CORE_ADDR addr;
+ char *contents_cache;
+{
+#ifdef SIM_HAS_BREAKPOINTS
+ SIM_RC retcode;
+
+ retcode = sim_set_breakpoint (gdbsim_desc, addr);
+
+ switch (retcode)
+ {
+ case SIM_RC_OK:
+ return 0;
+ case SIM_RC_INSUFFICIENT_RESOURCES:
+ return ENOMEM;
+ default:
+ return EIO;
+ }
+#else
+ return memory_insert_breakpoint (addr, contents_cache);
+#endif
+}
+
+static int
+gdbsim_remove_breakpoint (addr, contents_cache)
+ CORE_ADDR addr;
+ char *contents_cache;
+{
+#ifdef SIM_HAS_BREAKPOINTS
+ SIM_RC retcode;
+
+ retcode = sim_clear_breakpoint (gdbsim_desc, addr);
+
+ switch (retcode)
+ {
+ case SIM_RC_OK:
+ case SIM_RC_UNKNOWN_BREAKPOINT:
+ return 0;
+ case SIM_RC_INSUFFICIENT_RESOURCES:
+ return ENOMEM;
+ default:
+ return EIO;
+ }
+#else
+ return memory_remove_breakpoint (addr, contents_cache);
+#endif
+}
+
+/* Pass the command argument through to the simulator verbatim. The
+ simulator must do any command interpretation work. */
+
+void
+simulator_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ if (gdbsim_desc == NULL)
+ {
+
+ /* PREVIOUSLY: The user may give a command before the simulator
+ is opened. [...] (??? assuming of course one wishes to
+ continue to allow commands to be sent to unopened simulators,
+ which isn't entirely unreasonable). */
+
+ /* The simulator is a builtin abstraction of a remote target.
+ Consistent with that model, access to the simulator, via sim
+ commands, is restricted to the period when the channel to the
+ simulator is open. */
+
+ error ("Not connected to the simulator target");
+ }
+
+ sim_do_command (gdbsim_desc, args);
+
+ /* Invalidate the register cache, in case the simulator command does
+ something funny. */
+ registers_changed ();
+}
+
+/* Define the target subroutine names */
+
+struct target_ops gdbsim_ops ;
+
+static void
+init_gdbsim_ops(void)
+{
+ gdbsim_ops.to_shortname = "sim";
+ gdbsim_ops.to_longname = "simulator";
+ gdbsim_ops.to_doc = "Use the compiled-in simulator.";
+ gdbsim_ops.to_open = gdbsim_open;
+ gdbsim_ops.to_close = gdbsim_close;
+ gdbsim_ops.to_attach = NULL;
+ gdbsim_ops.to_post_attach = NULL;
+ gdbsim_ops.to_require_attach = NULL;
+ gdbsim_ops.to_detach = gdbsim_detach;
+ gdbsim_ops.to_require_detach = NULL;
+ gdbsim_ops.to_resume = gdbsim_resume;
+ gdbsim_ops.to_wait = gdbsim_wait;
+ gdbsim_ops.to_post_wait = NULL;
+ gdbsim_ops.to_fetch_registers = gdbsim_fetch_register;
+ gdbsim_ops.to_store_registers = gdbsim_store_register;
+ gdbsim_ops.to_prepare_to_store = gdbsim_prepare_to_store;
+ gdbsim_ops.to_xfer_memory = gdbsim_xfer_inferior_memory;
+ gdbsim_ops.to_files_info = gdbsim_files_info;
+ gdbsim_ops.to_insert_breakpoint = gdbsim_insert_breakpoint;
+ gdbsim_ops.to_remove_breakpoint = gdbsim_remove_breakpoint;
+ gdbsim_ops.to_terminal_init = NULL;
+ gdbsim_ops.to_terminal_inferior = NULL;
+ gdbsim_ops.to_terminal_ours_for_output = NULL;
+ gdbsim_ops.to_terminal_ours = NULL;
+ gdbsim_ops.to_terminal_info = NULL;
+ gdbsim_ops.to_kill = gdbsim_kill;
+ gdbsim_ops.to_load = gdbsim_load;
+ gdbsim_ops.to_lookup_symbol = NULL;
+ gdbsim_ops.to_create_inferior = gdbsim_create_inferior;
+ gdbsim_ops.to_post_startup_inferior = NULL;
+ gdbsim_ops.to_acknowledge_created_inferior = NULL;
+ gdbsim_ops.to_clone_and_follow_inferior = NULL;
+ gdbsim_ops.to_post_follow_inferior_by_clone = NULL;
+ gdbsim_ops.to_insert_fork_catchpoint = NULL;
+ gdbsim_ops.to_remove_fork_catchpoint = NULL;
+ gdbsim_ops.to_insert_vfork_catchpoint = NULL;
+ gdbsim_ops.to_remove_vfork_catchpoint = NULL;
+ gdbsim_ops.to_has_forked = NULL;
+ gdbsim_ops.to_has_vforked = NULL;
+ gdbsim_ops.to_can_follow_vfork_prior_to_exec = NULL;
+ gdbsim_ops.to_post_follow_vfork = NULL;
+ gdbsim_ops.to_insert_exec_catchpoint = NULL;
+ gdbsim_ops.to_remove_exec_catchpoint = NULL;
+ gdbsim_ops.to_has_execd = NULL;
+ gdbsim_ops.to_reported_exec_events_per_exec_call = NULL;
+ gdbsim_ops.to_has_exited = NULL;
+ gdbsim_ops.to_mourn_inferior = gdbsim_mourn_inferior;
+ gdbsim_ops.to_can_run = 0;
+ gdbsim_ops.to_notice_signals = 0;
+ gdbsim_ops.to_thread_alive = 0;
+ gdbsim_ops.to_stop = gdbsim_stop;
+ gdbsim_ops.to_pid_to_exec_file = NULL;
+ gdbsim_ops.to_core_file_to_sym_file = NULL;
+ gdbsim_ops.to_stratum = process_stratum;
+ gdbsim_ops.DONT_USE = NULL;
+ gdbsim_ops.to_has_all_memory = 1;
+ gdbsim_ops.to_has_memory = 1;
+ gdbsim_ops.to_has_stack = 1;
+ gdbsim_ops.to_has_registers = 1;
+ gdbsim_ops.to_has_execution = 1;
+ gdbsim_ops.to_sections = NULL;
+ gdbsim_ops.to_sections_end = NULL;
+ gdbsim_ops.to_magic = OPS_MAGIC;
+
+#ifdef TARGET_REDEFINE_DEFAULT_OPS
+ TARGET_REDEFINE_DEFAULT_OPS (&gdbsim_ops);
+#endif
+}
+
+void
+_initialize_remote_sim ()
+{
+ init_gdbsim_ops() ;
+ add_target (&gdbsim_ops);
+
+ add_com ("sim <command>", class_obscure, simulator_command,
+ "Send a command to the simulator.");
+}
diff --git a/gdb/remote-st.c b/gdb/remote-st.c
new file mode 100644
index 00000000000..1efdbfac027
--- /dev/null
+++ b/gdb/remote-st.c
@@ -0,0 +1,879 @@
+/* Remote debugging interface for Tandem ST2000 phone switch, for GDB.
+ Copyright 1990, 1991, 1992 Free Software Foundation, Inc.
+ Contributed by Cygnus Support. Written by Jim Kingdon for Cygnus.
+
+This file is part of GDB.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* This file was derived from remote-eb.c, which did a similar job, but for
+ an AMD-29K running EBMON. That file was in turn derived from remote.c
+ as mentioned in the following comment (left in for comic relief):
+
+ "This is like remote.c but is for an esoteric situation--
+ having an a29k board in a PC hooked up to a unix machine with
+ a serial line, and running ctty com1 on the PC, through which
+ the unix machine can run ebmon. Not to mention that the PC
+ has PC/NFS, so it can access the same executables that gdb can,
+ over the net in real time."
+
+ In reality, this module talks to a debug monitor called 'STDEBUG', which
+ runs in a phone switch. We communicate with STDEBUG via either a direct
+ serial line, or a TCP (or possibly TELNET) stream to a terminal multiplexor,
+ which in turn talks to the phone switch. */
+
+#include "defs.h"
+#include "gdbcore.h"
+#include "target.h"
+#include "wait.h"
+#ifdef ANSI_PROTOTYPES
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+#include <signal.h>
+#include "gdb_string.h"
+#include <sys/types.h>
+#include "serial.h"
+
+extern struct target_ops st2000_ops; /* Forward declaration */
+
+static void st2000_close();
+static void st2000_fetch_register();
+static void st2000_store_register();
+
+#define LOG_FILE "st2000.log"
+#if defined (LOG_FILE)
+FILE *log_file;
+#endif
+
+static int timeout = 24;
+
+/* Descriptor for I/O to remote machine. Initialize it to -1 so that
+ st2000_open knows that we don't have a file open when the program
+ starts. */
+
+static serial_t st2000_desc;
+
+/* Send data to stdebug. Works just like printf. */
+
+static void
+#ifdef ANSI_PROTOTYPES
+printf_stdebug(char *pattern, ...)
+#else
+printf_stdebug(va_alist)
+ va_dcl
+#endif
+{
+ va_list args;
+ char buf[200];
+
+#ifdef ANSI_PROTOTYPES
+ va_start(args, pattern);
+#else
+ char *pattern;
+ va_start(args);
+ pattern = va_arg(args, char *);
+#endif
+
+ vsprintf(buf, pattern, args);
+ va_end(args);
+
+ if (SERIAL_WRITE(st2000_desc, buf, strlen(buf)))
+ fprintf(stderr, "SERIAL_WRITE failed: %s\n", safe_strerror(errno));
+}
+
+/* Read a character from the remote system, doing all the fancy timeout
+ stuff. */
+
+static int
+readchar(timeout)
+ int timeout;
+{
+ int c;
+
+ c = SERIAL_READCHAR(st2000_desc, timeout);
+
+#ifdef LOG_FILE
+ putc(c & 0x7f, log_file);
+#endif
+
+ if (c >= 0)
+ return c & 0x7f;
+
+ if (c == SERIAL_TIMEOUT)
+ {
+ if (timeout == 0)
+ return c; /* Polls shouldn't generate timeout errors */
+
+ error("Timeout reading from remote system.");
+ }
+
+ perror_with_name("remote-st2000");
+}
+
+/* Scan input from the remote system, until STRING is found. If DISCARD is
+ non-zero, then discard non-matching input, else print it out.
+ Let the user break out immediately. */
+static void
+expect(string, discard)
+ char *string;
+ int discard;
+{
+ char *p = string;
+ int c;
+
+ immediate_quit = 1;
+ while (1)
+ {
+ c = readchar(timeout);
+ if (c == *p++)
+ {
+ if (*p == '\0')
+ {
+ immediate_quit = 0;
+ return;
+ }
+ }
+ else
+ {
+ if (!discard)
+ {
+ fwrite(string, 1, (p - 1) - string, stdout);
+ putchar((char)c);
+ fflush(stdout);
+ }
+ p = string;
+ }
+ }
+}
+
+/* Keep discarding input until we see the STDEBUG prompt.
+
+ The convention for dealing with the prompt is that you
+ o give your command
+ o *then* wait for the prompt.
+
+ Thus the last thing that a procedure does with the serial line
+ will be an expect_prompt(). Exception: st2000_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 st2000_wait which does wait for the prompt.
+ Note that this includes abnormal exit, e.g. error(). This is
+ necessary to prevent getting into states from which we can't
+ recover. */
+static void
+expect_prompt(discard)
+ int discard;
+{
+#if defined (LOG_FILE)
+ /* This is a convenient place to do this. The idea is to do it often
+ enough that we never lose much data if we terminate abnormally. */
+ fflush(log_file);
+#endif
+ expect ("dbug> ", discard);
+}
+
+/* Get a hex digit from the remote system & return its value.
+ If ignore_space is nonzero, ignore spaces (not newline, tab, etc). */
+static int
+get_hex_digit(ignore_space)
+ int ignore_space;
+{
+ int ch;
+ while (1)
+ {
+ ch = readchar(timeout);
+ if (ch >= '0' && ch <= '9')
+ return ch - '0';
+ else if (ch >= 'A' && ch <= 'F')
+ return ch - 'A' + 10;
+ else if (ch >= 'a' && ch <= 'f')
+ return ch - 'a' + 10;
+ else if (ch == ' ' && ignore_space)
+ ;
+ else
+ {
+ expect_prompt(1);
+ error("Invalid hex digit from remote system.");
+ }
+ }
+}
+
+/* Get a byte from stdebug and put it in *BYT. Accept any number
+ leading spaces. */
+static void
+get_hex_byte (byt)
+ char *byt;
+{
+ int val;
+
+ val = get_hex_digit (1) << 4;
+ val |= get_hex_digit (0);
+ *byt = val;
+}
+
+/* Get N 32-bit words from remote, each preceded by a space,
+ and put them in registers starting at REGNO. */
+static void
+get_hex_regs (n, regno)
+ int n;
+ int regno;
+{
+ long val;
+ int i;
+
+ for (i = 0; i < n; i++)
+ {
+ int j;
+
+ val = 0;
+ for (j = 0; j < 8; j++)
+ val = (val << 4) + get_hex_digit (j == 0);
+ supply_register (regno++, (char *) &val);
+ }
+}
+
+/* This is called not only when we first attach, but also when the
+ user types "run" after having attached. */
+static void
+st2000_create_inferior (execfile, args, env)
+ char *execfile;
+ char *args;
+ char **env;
+{
+ int entry_pt;
+
+ if (args && *args)
+ error("Can't pass arguments to remote STDEBUG process");
+
+ if (execfile == 0 || exec_bfd == 0)
+ error("No executable file specified");
+
+ entry_pt = (int) bfd_get_start_address (exec_bfd);
+
+/* The "process" (board) is already stopped awaiting our commands, and
+ the program is already downloaded. We just set its PC and go. */
+
+ clear_proceed_status ();
+
+ /* Tell wait_for_inferior that we've started a new process. */
+ init_wait_for_inferior ();
+
+ /* Set up the "saved terminal modes" of the inferior
+ based on what modes we are starting it with. */
+ target_terminal_init ();
+
+ /* Install inferior's terminal modes. */
+ target_terminal_inferior ();
+
+ /* insert_step_breakpoint (); FIXME, do we need this? */
+ /* Let 'er rip... */
+ proceed ((CORE_ADDR)entry_pt, TARGET_SIGNAL_DEFAULT, 0);
+}
+
+/* Open a connection to a remote debugger.
+ NAME is the filename used for communication. */
+
+static int baudrate = 9600;
+static char dev_name[100];
+
+static void
+st2000_open(args, from_tty)
+ char *args;
+ int from_tty;
+{
+ int n;
+ char junk[100];
+
+ target_preopen(from_tty);
+
+ n = sscanf(args, " %s %d %s", dev_name, &baudrate, junk);
+
+ if (n != 2)
+ error("Bad arguments. Usage: target st2000 <device> <speed>\n\
+or target st2000 <host> <port>\n");
+
+ st2000_close(0);
+
+ st2000_desc = SERIAL_OPEN(dev_name);
+
+ if (!st2000_desc)
+ perror_with_name(dev_name);
+
+ SERIAL_SETBAUDRATE(st2000_desc, baudrate);
+
+ SERIAL_RAW(st2000_desc);
+
+ push_target(&st2000_ops);
+
+#if defined (LOG_FILE)
+ log_file = fopen (LOG_FILE, "w");
+ if (log_file == NULL)
+ perror_with_name (LOG_FILE);
+#endif
+
+ /* Hello? Are you there? */
+ printf_stdebug("\003"); /* ^C wakes up dbug */
+
+ expect_prompt(1);
+
+ if (from_tty)
+ printf("Remote %s connected to %s\n", target_shortname,
+ dev_name);
+}
+
+/* Close out all files and local state before this target loses control. */
+
+static void
+st2000_close (quitting)
+ int quitting;
+{
+ SERIAL_CLOSE(st2000_desc);
+
+#if defined (LOG_FILE)
+ if (log_file) {
+ if (ferror(log_file))
+ fprintf(stderr, "Error writing log file.\n");
+ if (fclose(log_file) != 0)
+ fprintf(stderr, "Error closing log file.\n");
+ }
+#endif
+}
+
+/* Terminate the open connection to the remote debugger.
+ Use this when you want to detach and do something else
+ with your gdb. */
+static void
+st2000_detach (from_tty)
+ int from_tty;
+{
+ pop_target(); /* calls st2000_close to do the real work */
+ if (from_tty)
+ printf ("Ending remote %s debugging\n", target_shortname);
+}
+
+/* Tell the remote machine to resume. */
+
+static void
+st2000_resume (pid, step, sig)
+ int pid, step;
+ enum target_signal sig;
+{
+ if (step)
+ {
+ printf_stdebug ("ST\r");
+ /* Wait for the echo. */
+ expect ("ST\r", 1);
+ }
+ else
+ {
+ printf_stdebug ("GO\r");
+ /* Swallow the echo. */
+ expect ("GO\r", 1);
+ }
+}
+
+/* Wait until the remote machine stops, then return,
+ storing status in STATUS just as `wait' would. */
+
+static int
+st2000_wait (status)
+ struct target_waitstatus *status;
+{
+ int old_timeout = timeout;
+
+ status->kind = TARGET_WAITKIND_EXITED;
+ status->value.integer = 0;
+
+ timeout = 0; /* Don't time out -- user program is running. */
+
+ expect_prompt(0); /* Wait for prompt, outputting extraneous text */
+
+ status->kind = TARGET_WAITKIND_STOPPED;
+ status->value.sig = TARGET_SIGNAL_TRAP;
+
+ timeout = old_timeout;
+
+ return 0;
+}
+
+/* Return the name of register number REGNO in the form input and output by
+ STDEBUG. Currently, REGISTER_NAMES just happens to contain exactly what
+ STDEBUG wants. Lets take advantage of that just as long as possible! */
+
+static char *
+get_reg_name (regno)
+ int regno;
+{
+ static char buf[50];
+ const char *p;
+ char *b;
+
+ b = buf;
+
+ for (p = REGISTER_NAME (regno); *p; p++)
+ *b++ = toupper(*p);
+ *b = '\000';
+
+ return buf;
+}
+
+/* Read the remote registers into the block REGS. */
+
+static void
+st2000_fetch_registers ()
+{
+ int regno;
+
+ /* Yeah yeah, I know this is horribly inefficient. But it isn't done
+ very often... I'll clean it up later. */
+
+ for (regno = 0; regno <= PC_REGNUM; regno++)
+ st2000_fetch_register(regno);
+}
+
+/* Fetch register REGNO, or all registers if REGNO is -1.
+ Returns errno value. */
+static void
+st2000_fetch_register (regno)
+ int regno;
+{
+ if (regno == -1)
+ st2000_fetch_registers ();
+ else
+ {
+ char *name = get_reg_name (regno);
+ printf_stdebug ("DR %s\r", name);
+ expect (name, 1);
+ expect (" : ", 1);
+ get_hex_regs (1, regno);
+ expect_prompt (1);
+ }
+ return;
+}
+
+/* Store the remote registers from the contents of the block REGS. */
+
+static void
+st2000_store_registers ()
+{
+ int regno;
+
+ for (regno = 0; regno <= PC_REGNUM; regno++)
+ st2000_store_register(regno);
+
+ registers_changed ();
+}
+
+/* Store register REGNO, or all if REGNO == 0.
+ Return errno value. */
+static void
+st2000_store_register (regno)
+ int regno;
+{
+ if (regno == -1)
+ st2000_store_registers ();
+ else
+ {
+ printf_stdebug ("PR %s %x\r", get_reg_name (regno),
+ read_register (regno));
+
+ expect_prompt (1);
+ }
+}
+
+/* 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
+st2000_prepare_to_store ()
+{
+ /* Do nothing, since we can store individual regs */
+}
+
+static void
+st2000_files_info ()
+{
+ printf ("\tAttached to %s at %d baud.\n",
+ dev_name, baudrate);
+}
+
+/* Copy LEN bytes of data from debugger memory at MYADDR
+ to inferior's memory at MEMADDR. Returns length moved. */
+static int
+st2000_write_inferior_memory (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ unsigned char *myaddr;
+ int len;
+{
+ int i;
+
+ for (i = 0; i < len; i++)
+ {
+ printf_stdebug ("PM.B %x %x\r", memaddr + i, myaddr[i]);
+ expect_prompt (1);
+ }
+ return len;
+}
+
+/* Read LEN bytes from inferior memory at MEMADDR. Put the result
+ at debugger address MYADDR. Returns length moved. */
+static int
+st2000_read_inferior_memory(memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+{
+ int i;
+
+ /* Number of bytes read so far. */
+ int count;
+
+ /* Starting address of this pass. */
+ unsigned long startaddr;
+
+ /* Number of bytes to read in this pass. */
+ int len_this_pass;
+
+ /* Note that this code works correctly if startaddr is just less
+ than UINT_MAX (well, really CORE_ADDR_MAX if there was such a
+ thing). That is, something like
+ st2000_read_bytes (CORE_ADDR_MAX - 4, foo, 4)
+ works--it never adds len to memaddr and gets 0. */
+ /* However, something like
+ st2000_read_bytes (CORE_ADDR_MAX - 3, foo, 4)
+ doesn't need to work. Detect it and give up if there's an attempt
+ to do that. */
+ if (((memaddr - 1) + len) < memaddr) {
+ errno = EIO;
+ return 0;
+ }
+
+ startaddr = memaddr;
+ count = 0;
+ while (count < len)
+ {
+ len_this_pass = 16;
+ if ((startaddr % 16) != 0)
+ len_this_pass -= startaddr % 16;
+ if (len_this_pass > (len - count))
+ len_this_pass = (len - count);
+
+ printf_stdebug ("DI.L %x %x\r", startaddr, len_this_pass);
+ expect (": ", 1);
+
+ for (i = 0; i < len_this_pass; i++)
+ get_hex_byte (&myaddr[count++]);
+
+ expect_prompt (1);
+
+ startaddr += len_this_pass;
+ }
+ return len;
+}
+
+/* FIXME-someday! Merge these two. */
+static int
+st2000_xfer_inferior_memory (memaddr, myaddr, len, write, target)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+ int write;
+ struct target_ops *target; /* ignored */
+{
+ if (write)
+ return st2000_write_inferior_memory (memaddr, myaddr, len);
+ else
+ return st2000_read_inferior_memory (memaddr, myaddr, len);
+}
+
+static void
+st2000_kill (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ return; /* Ignore attempts to kill target system */
+}
+
+/* Clean up when a program exits.
+
+ The program actually lives on in the remote processor's RAM, and may be
+ run again without a download. Don't leave it full of breakpoint
+ instructions. */
+
+static void
+st2000_mourn_inferior ()
+{
+ remove_breakpoints ();
+ unpush_target (&st2000_ops);
+ generic_mourn_inferior (); /* Do all the proper things now */
+}
+
+#define MAX_STDEBUG_BREAKPOINTS 16
+
+static CORE_ADDR breakaddr[MAX_STDEBUG_BREAKPOINTS] = {0};
+
+static int
+st2000_insert_breakpoint (addr, shadow)
+ CORE_ADDR addr;
+ char *shadow;
+{
+ int i;
+ CORE_ADDR bp_addr = addr;
+ int bp_size = 0;
+
+ BREAKPOINT_FROM_PC (&bp_addr, &bp_size);
+
+ for (i = 0; i <= MAX_STDEBUG_BREAKPOINTS; i++)
+ if (breakaddr[i] == 0)
+ {
+ breakaddr[i] = addr;
+
+ st2000_read_inferior_memory (bp_addr, shadow, bp_size);
+ printf_stdebug("BR %x H\r", addr);
+ expect_prompt(1);
+ return 0;
+ }
+
+ fprintf(stderr, "Too many breakpoints (> 16) for STDBUG\n");
+ return 1;
+}
+
+static int
+st2000_remove_breakpoint (addr, shadow)
+ CORE_ADDR addr;
+ char *shadow;
+{
+ int i;
+
+ for (i = 0; i < MAX_STDEBUG_BREAKPOINTS; i++)
+ if (breakaddr[i] == addr)
+ {
+ breakaddr[i] = 0;
+
+ printf_stdebug("CB %d\r", i);
+ expect_prompt(1);
+ return 0;
+ }
+
+ fprintf(stderr, "Can't find breakpoint associated with 0x%x\n", addr);
+ return 1;
+}
+
+
+/* Put a command string, in args, out to STDBUG. Output from STDBUG is placed
+ on the users terminal until the prompt is seen. */
+
+static void
+st2000_command (args, fromtty)
+ char *args;
+ int fromtty;
+{
+ if (!st2000_desc)
+ error("st2000 target not open.");
+
+ if (!args)
+ error("Missing command.");
+
+ printf_stdebug("%s\r", args);
+ expect_prompt(0);
+}
+
+/* Connect the user directly to STDBUG. This command acts just like the
+ 'cu' or 'tip' command. Use <CR>~. or <CR>~^D to break out. */
+
+/*static struct ttystate ttystate;*/
+
+static void
+cleanup_tty()
+{
+ printf("\r\n[Exiting connect mode]\r\n");
+/* SERIAL_RESTORE(0, &ttystate);*/
+}
+
+#if 0
+/* This all should now be in serial.c */
+
+static void
+connect_command (args, fromtty)
+ char *args;
+ int fromtty;
+{
+ fd_set readfds;
+ int numfds;
+ int c;
+ char cur_esc = 0;
+
+ dont_repeat();
+
+ if (st2000_desc < 0)
+ error("st2000 target not open.");
+
+ if (args)
+ fprintf("This command takes no args. They have been ignored.\n");
+
+ printf("[Entering connect mode. Use ~. or ~^D to escape]\n");
+
+ serial_raw(0, &ttystate);
+
+ make_cleanup(cleanup_tty, 0);
+
+ FD_ZERO(&readfds);
+
+ while (1)
+ {
+ do
+ {
+ FD_SET(0, &readfds);
+ FD_SET(st2000_desc, &readfds);
+ numfds = select(sizeof(readfds)*8, &readfds, 0, 0, 0);
+ }
+ while (numfds == 0);
+
+ if (numfds < 0)
+ perror_with_name("select");
+
+ if (FD_ISSET(0, &readfds))
+ { /* tty input, send to stdebug */
+ c = getchar();
+ if (c < 0)
+ perror_with_name("connect");
+
+ printf_stdebug("%c", c);
+ 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 (FD_ISSET(st2000_desc, &readfds))
+ {
+ while (1)
+ {
+ c = readchar(0);
+ if (c < 0)
+ break;
+ putchar(c);
+ }
+ fflush(stdout);
+ }
+ }
+}
+#endif /* 0 */
+
+/* Define the target subroutine names */
+
+struct target_ops st2000_ops ;
+
+static void
+init_st2000_ops(void)
+{
+ st2000_ops.to_shortname = "st2000";
+ st2000_ops.to_longname = "Remote serial Tandem ST2000 target";
+ st2000_ops.to_doc = "Use a remote computer running STDEBUG connected by a serial line;\n\
+or a network connection.\n\
+Arguments are the name of the device for the serial line,\n\
+the speed to connect at in bits per second." ;
+ st2000_ops.to_open = st2000_open;
+ st2000_ops.to_close = st2000_close;
+ st2000_ops.to_attach = 0;
+ st2000_run_ops.to_post_attach = NULL;
+ st2000_ops.to_require_attach = NULL;
+ st2000_ops.to_detach = st2000_detach;
+ st2000_ops.to_require_detach = NULL;
+ st2000_ops.to_resume = st2000_resume;
+ st2000_ops.to_wait = st2000_wait;
+ st2000_ops.to_post_wait = NULL;
+ st2000_ops.to_fetch_registers = st2000_fetch_register;
+ st2000_ops.to_store_registers = st2000_store_register;
+ st2000_ops.to_prepare_to_store = st2000_prepare_to_store;
+ st2000_ops.to_xfer_memory = st2000_xfer_inferior_memory;
+ st2000_ops.to_files_info = st2000_files_info;
+ st2000_ops.to_insert_breakpoint = st2000_insert_breakpoint;
+ st2000_ops.to_remove_breakpoint = st2000_remove_breakpoint; /* Breakpoints */
+ st2000_ops.to_terminal_init = 0;
+ st2000_ops.to_terminal_inferior = 0;
+ st2000_ops.to_terminal_ours_for_output = 0;
+ st2000_ops.to_terminal_ours = 0;
+ st2000_ops.to_terminal_info = 0; /* Terminal handling */
+ st2000_ops.to_kill = st2000_kill;
+ st2000_ops.to_load = 0; /* load */
+ st2000_ops.to_lookup_symbol = 0; /* lookup_symbol */
+ st2000_ops.to_create_inferior = st2000_create_inferior;
+ st2000_ops.to_post_startup_inferior = NULL;
+ st2000_ops.to_acknowledge_created_inferior = NULL;
+ st2000_ops.to_clone_and_follow_inferior = NULL;
+ st2000_ops.to_post_follow_inferior_by_clone = NULL;
+ st2000_run_ops.to_insert_fork_catchpoint = NULL;
+ st2000_run_ops.to_remove_fork_catchpoint = NULL;
+ st2000_run_ops.to_insert_vfork_catchpoint = NULL;
+ st2000_run_ops.to_remove_vfork_catchpoint = NULL;
+ st2000_ops.to_has_forked = NULL;
+ st2000_ops.to_has_vforked = NULL;
+ st2000_run_ops.to_can_follow_vfork_prior_to_exec = NULL;
+ st2000_ops.to_post_follow_vfork = NULL;
+ st2000_run_ops.to_insert_exec_catchpoint = NULL;
+ st2000_run_ops.to_remove_exec_catchpoint = NULL;
+ st2000_run_ops.to_has_execd = NULL;
+ st2000_run_ops.to_reported_exec_events_per_exec_call = NULL;
+ st2000_run_ops.to_has_exited = NULL;
+ st2000_ops.to_mourn_inferior = st2000_mourn_inferior;
+ st2000_ops.to_can_run = 0; /* can_run */
+ st2000_ops.to_notice_signals = 0; /* notice_signals */
+ st2000_ops.to_thread_alive = 0; /* thread alive */
+ st2000_ops.to_stop = 0; /* to_stop */
+ st2000_ops.to_pid_to_exec_file = NULL;
+ st2000_run_ops.to_core_file_to_sym_file = NULL;
+ st2000_ops.to_stratum = process_stratum;
+ st2000_ops.DONT_USE = 0; /* next */
+ st2000_ops.to_has_all_memory = 1;
+ st2000_ops.to_has_memory = 1;
+ st2000_ops.to_has_stack = 1;
+ st2000_ops.to_has_registers = 1;
+ st2000_ops.to_has_execution = 1; /* all mem, mem, stack, regs, exec */
+ st2000_ops.to_sections = 0;
+ st2000_ops.to_sections_end = 0; /* Section pointers */
+ st2000_ops.to_magic = OPS_MAGIC; /* Always the last thing */
+} ;
+
+void
+_initialize_remote_st2000 ()
+{
+ init_st2000_ops() ;
+ add_target (&st2000_ops);
+ add_com ("st2000 <command>", class_obscure, st2000_command,
+ "Send a command to the STDBUG monitor.");
+ add_com ("connect", class_obscure, connect_command,
+ "Connect the terminal directly up to the STDBUG command monitor.\n\
+Use <CR>~. or <CR>~^D to break out.");
+}
diff --git a/gdb/remote-udi.c b/gdb/remote-udi.c
new file mode 100644
index 00000000000..6397bca5d16
--- /dev/null
+++ b/gdb/remote-udi.c
@@ -0,0 +1,1694 @@
+/* Remote debugging interface for AMD 29k interfaced via UDI, for GDB.
+ Copyright 1990, 1992, 1995 Free Software Foundation, Inc.
+ Written by Daniel Mann. Contributed by AMD.
+
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* This is like remote.c but uses the Universal Debug Interface (UDI) to
+ talk to the target hardware (or simulator). UDI is a TCP/IP based
+ protocol; for hardware that doesn't run TCP, an interface adapter
+ daemon talks UDI on one side, and talks to the hardware (typically
+ over a serial port) on the other side.
+
+ - Originally written by Daniel Mann at AMD for MiniMON and gdb 3.91.6.
+ - David Wood (wood@lab.ultra.nyu.edu) at New York University adapted this
+ file to gdb 3.95. I was unable to get this working on sun3os4
+ with termio, only with sgtty.
+ - Daniel Mann at AMD took the 3.95 adaptions above and replaced
+ MiniMON interface with UDI-p interface. */
+
+#include "defs.h"
+#include "frame.h"
+#include "inferior.h"
+#include "wait.h"
+#include "value.h"
+#include <ctype.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <errno.h>
+#include "gdb_string.h"
+#include "terminal.h"
+#include "target.h"
+#include "29k-share/udi/udiproc.h"
+#include "gdbcmd.h"
+#include "bfd.h"
+#include "gdbcore.h" /* For download function */
+
+/* access the register store directly, without going through
+ the normal handler functions. This avoids an extra data copy. */
+
+extern int stop_soon_quietly; /* for wait_for_inferior */
+extern struct value *call_function_by_hand();
+static void udi_resume PARAMS ((int pid, int step, enum target_signal sig));
+static void udi_fetch_registers PARAMS ((int regno));
+static void udi_load PARAMS ((char *args, int from_tty));
+static void fetch_register PARAMS ((int regno));
+static void udi_store_registers PARAMS ((int regno));
+static int store_register PARAMS ((int regno));
+static int regnum_to_srnum PARAMS ((int regno));
+static void udi_close PARAMS ((int quitting));
+static CPUSpace udi_memory_space PARAMS ((CORE_ADDR addr));
+static int udi_write_inferior_memory PARAMS ((CORE_ADDR memaddr, char *myaddr,
+ int len));
+static int udi_read_inferior_memory PARAMS ((CORE_ADDR memaddr, char *myaddr,
+ int len));
+static void download PARAMS ((char *load_arg_string, int from_tty));
+char CoffFileName[100] = "";
+
+#define FREEZE_MODE (read_register(CPS_REGNUM) & 0x400)
+#define USE_SHADOW_PC ((processor_type == a29k_freeze_mode) && FREEZE_MODE)
+
+static int timeout = 5;
+extern struct target_ops udi_ops; /* Forward declaration */
+
+/* Special register enumeration.
+*/
+
+/******************************************************************* UDI DATA*/
+#define MAXDATA 2*1024 /* max UDI[read/write] byte size */
+/* Descriptor for I/O to remote machine. Initialize it to -1 so that
+ udi_open knows that we don't have a file open when the program
+ starts. */
+
+UDISessionId udi_session_id = -1;
+static char *udi_config_id;
+
+CPUOffset IMemStart = 0;
+CPUSizeT IMemSize = 0;
+CPUOffset DMemStart = 0;
+CPUSizeT DMemSize = 0;
+CPUOffset RMemStart = 0;
+CPUSizeT RMemSize = 0;
+UDIUInt32 CPUPRL;
+UDIUInt32 CoProcPRL;
+
+UDIMemoryRange address_ranges[2]; /* Text and data */
+UDIResource entry = {0, 0}; /* Entry point */
+CPUSizeT stack_sizes[2]; /* Regular and memory stacks */
+
+#define SBUF_MAX 1024 /* maximum size of string handling buffer */
+char sbuf[SBUF_MAX];
+
+typedef struct bkpt_entry_str
+{
+ UDIResource Addr;
+ UDIUInt32 PassCount;
+ UDIBreakType Type;
+ unsigned int BreakId;
+} bkpt_entry_t;
+#define BKPT_TABLE_SIZE 40
+static bkpt_entry_t bkpt_table[BKPT_TABLE_SIZE];
+extern char dfe_errmsg[]; /* error string */
+
+/* malloc'd name of the program on the remote system. */
+static char *prog_name = NULL;
+
+/* This is called not only when we first attach, but also when the
+ user types "run" after having attached. */
+
+static void
+udi_create_inferior (execfile, args, env)
+ char *execfile;
+ char *args;
+ char **env;
+{
+ char *args1;
+
+ if (execfile)
+ {
+ if (prog_name != NULL)
+ free (prog_name);
+ prog_name = savestring (execfile, strlen (execfile));
+ }
+ else if (entry.Offset)
+ execfile = "";
+ else
+ error ("No image loaded into target.");
+
+ if (udi_session_id < 0)
+ {
+ /* If the TIP is not open, open it. */
+ if (UDIConnect (udi_config_id, &udi_session_id))
+ error("UDIConnect() failed: %s\n", dfe_errmsg);
+ /* We will need to download the program. */
+ entry.Offset = 0;
+ }
+
+ inferior_pid = 40000;
+
+ if (!entry.Offset)
+ download(execfile, 0);
+
+ args1 = alloca (strlen(execfile) + strlen(args) + 2);
+
+ if (execfile[0] == '\0')
+
+ /* It is empty. We need to quote it somehow, or else the target
+ will think there is no argument being passed here. According
+ to the UDI spec it is quoted "according to TIP OS rules" which
+ I guess means quoting it like the Unix shell should work
+ (sounds pretty bogus to me...). In fact it doesn't work (with
+ isstip anyway), but passing in two quotes as the argument seems
+ like a reasonable enough behavior anyway (I guess). */
+
+ strcpy (args1, "''");
+ else
+ strcpy (args1, execfile);
+ strcat (args1, " ");
+ strcat (args1, args);
+
+ UDIInitializeProcess (address_ranges, /* ProcessMemory[] */
+ (UDIInt)2, /* NumberOfRanges */
+ entry, /* EntryPoint */
+ stack_sizes, /* *StackSizes */
+ (UDIInt)2, /* NumberOfStacks */
+ args1); /* ArgString */
+
+ init_wait_for_inferior ();
+ clear_proceed_status ();
+ proceed (-1, TARGET_SIGNAL_DEFAULT, 0);
+}
+
+static void
+udi_mourn()
+{
+#if 0
+ /* Requiring "target udi" each time you run is a major pain. I suspect
+ this was just blindy copied from remote.c, in which "target" and
+ "run" are combined. Having a udi target without an inferior seems
+ to work between "target udi" and "run", so why not now? */
+ pop_target (); /* Pop back to no-child state */
+#endif
+ /* But if we're going to want to run it again, we better remove the
+ breakpoints... */
+ remove_breakpoints ();
+ generic_mourn_inferior ();
+}
+
+/******************************************************************** UDI_OPEN
+** Open a connection to remote TIP.
+ NAME is the socket domain used for communication with the TIP,
+ then a space and the socket name or TIP-host name.
+ '<udi_udi_config_id>' for example.
+ */
+
+/* XXX - need cleanups for udiconnect for various failures!!! */
+
+static void
+udi_open (name, from_tty)
+ char *name;
+ int from_tty;
+{
+ unsigned int prl;
+ char *p;
+ int cnt;
+ UDIMemoryRange KnownMemory[10];
+ UDIUInt32 ChipVersions[10];
+ UDIInt NumberOfRanges = 10;
+ UDIInt NumberOfChips = 10;
+ UDIPId PId;
+ UDIUInt32 TIPId, TargetId, DFEId, DFE, TIP, DFEIPCId, TIPIPCId;
+
+ target_preopen(from_tty);
+
+ entry.Offset = 0;
+
+ for (cnt = 0; cnt < BKPT_TABLE_SIZE; cnt++)
+ bkpt_table[cnt].Type = 0;
+
+ if (udi_config_id)
+ free (udi_config_id);
+
+ if (!name)
+ error("Usage: target udi config_id, where config_id appears in udi_soc file");
+
+ udi_config_id = strdup (strtok (name, " \t"));
+
+ if (UDIConnect (udi_config_id, &udi_session_id))
+ /* FIXME: Should set udi_session_id to -1 here. */
+ error("UDIConnect() failed: %s\n", dfe_errmsg);
+
+ push_target (&udi_ops);
+
+ /*
+ ** Initialize target configuration structure (global)
+ */
+ if (UDIGetTargetConfig (KnownMemory, &NumberOfRanges,
+ ChipVersions, &NumberOfChips))
+ error ("UDIGetTargetConfig() failed");
+ if (NumberOfChips > 2)
+ fprintf_unfiltered(gdb_stderr,"Target has more than one processor\n");
+ for (cnt=0; cnt < NumberOfRanges; cnt++)
+ {
+ switch(KnownMemory[cnt].Space)
+ {
+ default:
+ fprintf_unfiltered(gdb_stderr, "UDIGetTargetConfig() unknown memory space\n");
+ break;
+ case UDI29KCP_S:
+ break;
+ case UDI29KIROMSpace:
+ RMemStart = KnownMemory[cnt].Offset;
+ RMemSize = KnownMemory[cnt].Size;
+ break;
+ case UDI29KIRAMSpace:
+ IMemStart = KnownMemory[cnt].Offset;
+ IMemSize = KnownMemory[cnt].Size;
+ break;
+ case UDI29KDRAMSpace:
+ DMemStart = KnownMemory[cnt].Offset;
+ DMemSize = KnownMemory[cnt].Size;
+ break;
+ }
+ }
+
+ a29k_get_processor_type ();
+
+ if (UDICreateProcess (&PId))
+ fprintf_unfiltered(gdb_stderr, "UDICreateProcess() failed\n");
+
+ /* Print out some stuff, letting the user now what's going on */
+ if (UDICapabilities (&TIPId, &TargetId, DFEId, DFE, &TIP, &DFEIPCId,
+ &TIPIPCId, sbuf))
+ error ("UDICapabilities() failed");
+ if (from_tty)
+ {
+ printf_filtered ("Connected via UDI socket,\n\
+ DFE-IPC version %x.%x.%x TIP-IPC version %x.%x.%x TIP version %x.%x.%x\n %s\n",
+ (DFEIPCId>>8)&0xf, (DFEIPCId>>4)&0xf, DFEIPCId&0xf,
+ (TIPIPCId>>8)&0xf, (TIPIPCId>>4)&0xf, TIPIPCId&0xf,
+ (TargetId>>8)&0xf, (TargetId>>4)&0xf, TargetId&0xf,
+ sbuf);
+ }
+}
+
+/******************************************************************* UDI_CLOSE
+ Close the open connection to the TIP process.
+ Use this when you want to detach and do something else
+ with your gdb. */
+static void
+udi_close (quitting) /*FIXME: how is quitting used */
+ int quitting;
+{
+ if (udi_session_id < 0)
+ return;
+
+ /* We should never get here if there isn't something valid in
+ udi_session_id. */
+
+ if (UDIDisconnect (udi_session_id, UDITerminateSession))
+ {
+ if (quitting)
+ warning ("UDIDisconnect() failed in udi_close");
+ else
+ error ("UDIDisconnect() failed in udi_close");
+ }
+
+ /* Do not try to close udi_session_id again, later in the program. */
+ udi_session_id = -1;
+ inferior_pid = 0;
+
+ printf_filtered (" Ending remote debugging\n");
+}
+
+/**************************************************************** UDI_ATACH */
+/* Attach to a program that is already loaded and running
+ * Upon exiting the process's execution is stopped.
+ */
+static void
+udi_attach (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ UDIResource From;
+ UDIInt32 PC_adds;
+ UDICount Count = 1;
+ UDISizeT Size = 4;
+ UDICount CountDone;
+ UDIBool HostEndian = 0;
+ UDIError err;
+
+ if (args == NULL)
+ error_no_arg ("program to attach");
+
+ if (udi_session_id < 0)
+ error ("UDI connection not opened yet, use the 'target udi' command.\n");
+
+ if (from_tty)
+ printf_unfiltered ("Attaching to remote program %s...\n", prog_name);
+
+ UDIStop();
+ From.Space = UDI29KSpecialRegs;
+ From.Offset = 11;
+ if (err = UDIRead(From, &PC_adds, Count, Size, &CountDone, HostEndian))
+ error ("UDIRead failed in udi_attach");
+ printf_unfiltered ("Remote process is now halted, pc1 = 0x%x.\n", PC_adds);
+}
+/************************************************************* UDI_DETACH */
+/* Terminate the open connection to the TIP process.
+ Use this when you want to detach and do something else
+ with your gdb. Leave remote process running (with no breakpoints set). */
+static void
+udi_detach (args,from_tty)
+ char *args;
+ int from_tty;
+{
+
+ remove_breakpoints(); /* Just in case there were any left in */
+
+ if (UDIDisconnect (udi_session_id, UDIContinueSession))
+ error ("UDIDisconnect() failed in udi_detach");
+
+ /* Don't try to UDIDisconnect it again in udi_close, which is called from
+ pop_target. */
+ udi_session_id = -1;
+ inferior_pid = 0;
+
+ pop_target();
+
+ if (from_tty)
+ printf_unfiltered ("Detaching from TIP\n");
+}
+
+
+/****************************************************************** UDI_RESUME
+** Tell the remote machine to resume. */
+
+static void
+udi_resume (pid, step, sig)
+ int pid, step;
+ enum target_signal sig;
+{
+ UDIError tip_error;
+ UDIUInt32 Steps = 1;
+ UDIStepType StepType = UDIStepNatural;
+ UDIRange Range;
+
+ if (step) /* step 1 instruction */
+ {
+ tip_error = UDIStep (Steps, StepType, Range);
+ if (!tip_error)
+ return;
+
+ fprintf_unfiltered (gdb_stderr, "UDIStep() error = %d\n", tip_error);
+ error ("failed in udi_resume");
+ }
+
+ if (UDIExecute())
+ error ("UDIExecute() failed in udi_resume");
+}
+
+/******************************************************************** UDI_WAIT
+** Wait until the remote machine stops, then return,
+ storing status in STATUS just as `wait' would. */
+
+static int
+udi_wait (pid, status)
+ int pid;
+ struct target_waitstatus *status;
+{
+ UDIInt32 MaxTime;
+ UDIPId PId;
+ UDIInt32 StopReason;
+ UDISizeT CountDone;
+ int old_timeout = timeout;
+ int old_immediate_quit = immediate_quit;
+ int i;
+
+ status->kind = TARGET_WAITKIND_EXITED;
+ status->value.integer = 0;
+
+/* wait for message to arrive. It should be:
+ If the target stops executing, udi_wait() should return.
+*/
+ timeout = 0; /* Wait indefinetly for a message */
+ immediate_quit = 1; /* Helps ability to QUIT */
+
+ while(1)
+ {
+ i = 0;
+ MaxTime = UDIWaitForever;
+ UDIWait(MaxTime, &PId, &StopReason);
+ QUIT; /* Let user quit if they want */
+
+ switch (StopReason & UDIGrossState)
+ {
+ case UDIStdoutReady:
+ if (UDIGetStdout (sbuf, (UDISizeT)SBUF_MAX, &CountDone))
+ /* This is said to happen if the program tries to output
+ a whole bunch of output (more than SBUF_MAX, I would
+ guess). It doesn't seem to happen with the simulator. */
+ warning ("UDIGetStdout() failed in udi_wait");
+ fwrite (sbuf, 1, CountDone, stdout);
+ gdb_flush(gdb_stdout);
+ continue;
+
+ case UDIStderrReady:
+ UDIGetStderr (sbuf, (UDISizeT)SBUF_MAX, &CountDone);
+ fwrite (sbuf, 1, CountDone, stderr);
+ gdb_flush(gdb_stderr);
+ continue;
+
+ case UDIStdinNeeded:
+ {
+ int ch;
+ i = 0;
+ do
+ {
+ ch = getchar ();
+ if (ch == EOF)
+ break;
+ sbuf[i++] = ch;
+ } while (i < SBUF_MAX && ch != '\n');
+ UDIPutStdin (sbuf, (UDISizeT)i, &CountDone);
+ continue;
+ }
+
+ case UDIRunning:
+ /* In spite of the fact that we told UDIWait to wait forever, it will
+ return spuriously sometimes. */
+ case UDIStdinModeX:
+ continue;
+ default:
+ break;
+ }
+ break;
+ }
+
+ switch (StopReason & UDIGrossState)
+ {
+ case UDITrapped:
+ printf_unfiltered("Am290*0 received vector number %d\n", StopReason >> 24);
+
+ switch ((StopReason >> 8 ) & 0xff)
+ {
+ case 0: /* Illegal opcode */
+ printf_unfiltered(" (break point)\n");
+ status->kind = TARGET_WAITKIND_STOPPED;
+ status->value.sig = TARGET_SIGNAL_TRAP;
+ break;
+ case 1: /* Unaligned Access */
+ status->kind = TARGET_WAITKIND_STOPPED;
+ status->value.sig = TARGET_SIGNAL_BUS;
+ break;
+ case 3:
+ case 4:
+ status->kind = TARGET_WAITKIND_STOPPED;
+ status->value.sig = TARGET_SIGNAL_FPE;
+ break;
+ case 5: /* Protection Violation */
+ status->kind = TARGET_WAITKIND_STOPPED;
+ /* Why not SEGV? What is a Protection Violation? */
+ status->value.sig = TARGET_SIGNAL_ILL;
+ break;
+ case 6:
+ case 7:
+ case 8: /* User Instruction Mapping Miss */
+ case 9: /* User Data Mapping Miss */
+ case 10: /* Supervisor Instruction Mapping Miss */
+ case 11: /* Supervisor Data Mapping Miss */
+ status->kind = TARGET_WAITKIND_STOPPED;
+ status->value.sig = TARGET_SIGNAL_SEGV;
+ break;
+ case 12:
+ case 13:
+ status->kind = TARGET_WAITKIND_STOPPED;
+ status->value.sig = TARGET_SIGNAL_ILL;
+ break;
+ case 14: /* Timer */
+ status->kind = TARGET_WAITKIND_STOPPED;
+ status->value.sig = TARGET_SIGNAL_ALRM;
+ break;
+ case 15: /* Trace */
+ status->kind = TARGET_WAITKIND_STOPPED;
+ status->value.sig = TARGET_SIGNAL_TRAP;
+ break;
+ case 16: /* INTR0 */
+ case 17: /* INTR1 */
+ case 18: /* INTR2 */
+ case 19: /* INTR3/Internal */
+ case 20: /* TRAP0 */
+ case 21: /* TRAP1 */
+ status->kind = TARGET_WAITKIND_STOPPED;
+ status->value.sig = TARGET_SIGNAL_INT;
+ break;
+ case 22: /* Floating-Point Exception */
+ status->kind = TARGET_WAITKIND_STOPPED;
+ /* Why not FPE? */
+ status->value.sig = TARGET_SIGNAL_ILL;
+ break;
+ case 77: /* assert 77 */
+ status->kind = TARGET_WAITKIND_STOPPED;
+ status->value.sig = TARGET_SIGNAL_TRAP;
+ break;
+ default:
+ status->kind = TARGET_WAITKIND_EXITED;
+ status->value.integer = 0;
+ }
+ break;
+ case UDINotExecuting:
+ status->kind = TARGET_WAITKIND_STOPPED;
+ status->value.sig = TARGET_SIGNAL_TERM;
+ break;
+ case UDIStopped:
+ status->kind = TARGET_WAITKIND_STOPPED;
+ status->value.sig = TARGET_SIGNAL_TSTP;
+ break;
+ case UDIWarned:
+ status->kind = TARGET_WAITKIND_STOPPED;
+ status->value.sig = TARGET_SIGNAL_URG;
+ break;
+ case UDIStepped:
+ case UDIBreak:
+ status->kind = TARGET_WAITKIND_STOPPED;
+ status->value.sig = TARGET_SIGNAL_TRAP;
+ break;
+ case UDIWaiting:
+ status->kind = TARGET_WAITKIND_STOPPED;
+ status->value.sig = TARGET_SIGNAL_STOP;
+ break;
+ case UDIHalted:
+ status->kind = TARGET_WAITKIND_STOPPED;
+ status->value.sig = TARGET_SIGNAL_KILL;
+ break;
+ case UDIExited:
+ default:
+ status->kind = TARGET_WAITKIND_EXITED;
+ status->value.integer = 0;
+ }
+
+ timeout = old_timeout; /* Restore original timeout value */
+ immediate_quit = old_immediate_quit;
+ return inferior_pid;
+}
+
+#if 0
+/* Handy for debugging */
+udi_pc()
+{
+ UDIResource From;
+ UDIUInt32 *To;
+ UDICount Count;
+ UDISizeT Size = 4;
+ UDICount CountDone;
+ UDIBool HostEndian = 0;
+ UDIError err;
+ int pc[2];
+ unsigned long myregs[256];
+ int i;
+
+ From.Space = UDI29KPC;
+ From.Offset = 0;
+ To = (UDIUInt32 *)pc;
+ Count = 2;
+
+ err = UDIRead(From, To, Count, Size, &CountDone, HostEndian);
+
+ printf_unfiltered ("err = %d, CountDone = %d, pc[0] = 0x%x, pc[1] = 0x%x\n",
+ err, CountDone, pc[0], pc[1]);
+
+ udi_fetch_registers(-1);
+
+ printf_unfiltered("other pc1 = 0x%x, pc0 = 0x%x\n", *(int *)&registers[4 * PC_REGNUM],
+ *(int *)&registers[4 * NPC_REGNUM]);
+
+ /* Now, read all the registers globally */
+
+ From.Space = UDI29KGlobalRegs;
+ From.Offset = 0;
+ err = UDIRead(From, myregs, 256, 4, &CountDone, HostEndian);
+
+ printf ("err = %d, CountDone = %d\n", err, CountDone);
+
+ printf("\n");
+
+ for (i = 0; i < 256; i += 2)
+ printf("%d:\t%#10x\t%11d\t%#10x\t%11d\n", i, myregs[i], myregs[i],
+ myregs[i+1], myregs[i+1]);
+ printf("\n");
+
+ return pc[0];
+}
+#endif
+
+/********************************************************** UDI_FETCH_REGISTERS
+ * Read a remote register 'regno'.
+ * If regno==-1 then read all the registers.
+ */
+static void
+udi_fetch_registers (regno)
+int regno;
+{
+ UDIResource From;
+ UDIUInt32 *To;
+ UDICount Count;
+ UDISizeT Size = 4;
+ UDICount CountDone;
+ UDIBool HostEndian = 0;
+ UDIError err;
+ int i;
+
+ if (regno >= 0) {
+ fetch_register(regno);
+ return;
+ }
+
+/* Gr1/rsp */
+
+ From.Space = UDI29KGlobalRegs;
+ From.Offset = 1;
+ To = (UDIUInt32 *)&registers[4 * GR1_REGNUM];
+ Count = 1;
+ if (err = UDIRead(From, To, Count, Size, &CountDone, HostEndian))
+ error("UDIRead() failed in udi_fetch_registers");
+
+ register_valid[GR1_REGNUM] = 1;
+
+#if defined(GR64_REGNUM) /* Read gr64-127 */
+
+/* Global Registers gr64-gr95 */
+
+ From.Space = UDI29KGlobalRegs;
+ From.Offset = 64;
+ To = (UDIUInt32 *)&registers[4 * GR64_REGNUM];
+ Count = 32;
+ if (err = UDIRead(From, To, Count, Size, &CountDone, HostEndian))
+ error("UDIRead() failed in udi_fetch_registers");
+
+ for (i = GR64_REGNUM; i < GR64_REGNUM + 32; i++)
+ register_valid[i] = 1;
+
+#endif /* GR64_REGNUM */
+
+/* Global Registers gr96-gr127 */
+
+ From.Space = UDI29KGlobalRegs;
+ From.Offset = 96;
+ To = (UDIUInt32 *)&registers[4 * GR96_REGNUM];
+ Count = 32;
+ if (err = UDIRead(From, To, Count, Size, &CountDone, HostEndian))
+ error("UDIRead() failed in udi_fetch_registers");
+
+ for (i = GR96_REGNUM; i < GR96_REGNUM + 32; i++)
+ register_valid[i] = 1;
+
+/* Local Registers */
+
+ From.Space = UDI29KLocalRegs;
+ From.Offset = 0;
+ To = (UDIUInt32 *)&registers[4 * LR0_REGNUM];
+ Count = 128;
+ if (err = UDIRead(From, To, Count, Size, &CountDone, HostEndian))
+ error("UDIRead() failed in udi_fetch_registers");
+
+ for (i = LR0_REGNUM; i < LR0_REGNUM + 128; i++)
+ register_valid[i] = 1;
+
+/* Protected Special Registers */
+
+ From.Space = UDI29KSpecialRegs;
+ From.Offset = 0;
+ To = (UDIUInt32 *)&registers[4 * SR_REGNUM(0)];
+ Count = 15;
+ if (err = UDIRead(From, To, Count, Size, &CountDone, HostEndian))
+ error("UDIRead() failed in udi_fetch_registers");
+
+ for (i = SR_REGNUM(0); i < SR_REGNUM(0) + 15; i++)
+ register_valid[i] = 1;
+
+ if (USE_SHADOW_PC) { /* Let regno_to_srnum() handle the register number */
+ fetch_register(NPC_REGNUM);
+ fetch_register(PC_REGNUM);
+ fetch_register(PC2_REGNUM);
+
+/* Unprotected Special Registers sr128-sr135 */
+
+ From.Space = UDI29KSpecialRegs;
+ From.Offset = 128;
+ To = (UDIUInt32 *)&registers[4 * SR_REGNUM(128)];
+ Count = 135-128 + 1;
+ if (err = UDIRead(From, To, Count, Size, &CountDone, HostEndian))
+ error("UDIRead() failed in udi_fetch_registers");
+
+ for (i = SR_REGNUM(128); i < SR_REGNUM(128) + 135-128+1; i++)
+ register_valid[i] = 1;
+ }
+
+ if (remote_debug)
+ {
+ printf_unfiltered("Fetching all registers\n");
+ printf_unfiltered("Fetching PC0 = 0x%x, PC1 = 0x%x, PC2 = 0x%x\n",
+ read_register(NPC_REGNUM), read_register(PC_REGNUM),
+ read_register(PC2_REGNUM));
+ }
+
+ /* There doesn't seem to be any way to get these. */
+ {
+ int val = -1;
+ supply_register (FPE_REGNUM, (char *) &val);
+ supply_register (INTE_REGNUM, (char *) &val);
+ supply_register (FPS_REGNUM, (char *) &val);
+ supply_register (EXO_REGNUM, (char *) &val);
+ }
+}
+
+
+/********************************************************* UDI_STORE_REGISTERS
+** Store register regno into the target.
+ * If regno==-1 then store all the registers.
+ */
+
+static void
+udi_store_registers (regno)
+int regno;
+{
+ UDIUInt32 *From;
+ UDIResource To;
+ UDICount Count;
+ UDISizeT Size = 4;
+ UDICount CountDone;
+ UDIBool HostEndian = 0;
+
+ if (regno >= 0)
+ {
+ store_register(regno);
+ return;
+ }
+
+ if (remote_debug)
+ {
+ printf_unfiltered("Storing all registers\n");
+ printf_unfiltered("PC0 = 0x%x, PC1 = 0x%x, PC2 = 0x%x\n", read_register(NPC_REGNUM),
+ read_register(PC_REGNUM), read_register(PC2_REGNUM));
+ }
+
+/* Gr1/rsp */
+
+ From = (UDIUInt32 *)&registers[4 * GR1_REGNUM];
+ To.Space = UDI29KGlobalRegs;
+ To.Offset = 1;
+ Count = 1;
+ if(UDIWrite(From, To, Count, Size, &CountDone, HostEndian))
+ error("UDIWrite() failed in udi_store_regisetrs");
+
+#if defined(GR64_REGNUM)
+
+/* Global registers gr64-gr95 */
+
+ From = (UDIUInt32 *)&registers[4 * GR64_REGNUM];
+ To.Space = UDI29KGlobalRegs;
+ To.Offset = 64;
+ Count = 32;
+ if(UDIWrite(From, To, Count, Size, &CountDone, HostEndian))
+ error("UDIWrite() failed in udi_store_regisetrs");
+
+#endif /* GR64_REGNUM */
+
+/* Global registers gr96-gr127 */
+
+ From = (UDIUInt32 *)&registers[4 * GR96_REGNUM];
+ To.Space = UDI29KGlobalRegs;
+ To.Offset = 96;
+ Count = 32;
+ if(UDIWrite(From, To, Count, Size, &CountDone, HostEndian))
+ error("UDIWrite() failed in udi_store_regisetrs");
+
+/* Local Registers */
+
+ From = (UDIUInt32 *)&registers[4 * LR0_REGNUM];
+ To.Space = UDI29KLocalRegs;
+ To.Offset = 0;
+ Count = 128;
+ if(UDIWrite(From, To, Count, Size, &CountDone, HostEndian))
+ error("UDIWrite() failed in udi_store_regisetrs");
+
+
+/* Protected Special Registers */ /* VAB through TMR */
+
+ From = (UDIUInt32 *)&registers[4 * SR_REGNUM(0)];
+ To.Space = UDI29KSpecialRegs;
+ To.Offset = 0;
+ Count = 10;
+ if(UDIWrite(From, To, Count, Size, &CountDone, HostEndian))
+ error("UDIWrite() failed in udi_store_regisetrs");
+
+/* PC0, PC1, PC2 possibly as shadow registers */
+
+ From = (UDIUInt32 *)&registers[4 * SR_REGNUM(10)];
+ To.Space = UDI29KSpecialRegs;
+ Count = 3;
+ if (USE_SHADOW_PC)
+ To.Offset = 20; /* SPC0 */
+ else
+ To.Offset = 10; /* PC0 */
+ if(UDIWrite(From, To, Count, Size, &CountDone, HostEndian))
+ error("UDIWrite() failed in udi_store_regisetrs");
+
+/* PC1 via UDI29KPC */
+
+ From = (UDIUInt32 *)&registers[4 * PC_REGNUM];
+ To.Space = UDI29KPC;
+ To.Offset = 0; /* PC1 */
+ Count = 1;
+ if (UDIWrite (From, To, Count, Size, &CountDone, HostEndian))
+ error ("UDIWrite() failed in udi_store_regisetrs");
+
+ /* LRU and MMU */
+
+ From = (UDIUInt32 *)&registers[4 * SR_REGNUM(13)];
+ To.Space = UDI29KSpecialRegs;
+ To.Offset = 13;
+ Count = 2;
+ if(UDIWrite(From, To, Count, Size, &CountDone, HostEndian))
+ error("UDIWrite() failed in udi_store_regisetrs");
+
+/* Unprotected Special Registers */
+
+ From = (UDIUInt32 *)&registers[4 * SR_REGNUM(128)];
+ To.Space = UDI29KSpecialRegs;
+ To.Offset = 128;
+ Count = 135-128 +1;
+ if(UDIWrite(From, To, Count, Size, &CountDone, HostEndian))
+ error("UDIWrite() failed in udi_store_regisetrs");
+
+ registers_changed ();
+}
+
+/****************************************************** UDI_PREPARE_TO_STORE */
+/* 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
+udi_prepare_to_store ()
+{
+ /* Do nothing, since we can store individual regs */
+}
+
+/********************************************************** TRANSLATE_ADDR */
+static CORE_ADDR
+translate_addr(addr)
+CORE_ADDR addr;
+{
+#if defined(ULTRA3) && defined(KERNEL_DEBUGGING)
+ /* Check for a virtual address in the kernel */
+ /* Assume physical address of ublock is in paddr_u register */
+ /* FIXME: doesn't work for user virtual addresses */
+ if (addr >= UVADDR) {
+ /* PADDR_U register holds the physical address of the ublock */
+ CORE_ADDR i = (CORE_ADDR)read_register(PADDR_U_REGNUM);
+ return(i + addr - (CORE_ADDR)UVADDR);
+ } else {
+ return(addr);
+ }
+#else
+ return(addr);
+#endif
+}
+/************************************************* UDI_XFER_INFERIOR_MEMORY */
+/* FIXME! Merge these two. */
+static int
+udi_xfer_inferior_memory (memaddr, myaddr, len, write)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+ int write;
+{
+
+ memaddr = translate_addr(memaddr);
+
+ if (write)
+ return udi_write_inferior_memory (memaddr, myaddr, len);
+ else
+ return udi_read_inferior_memory (memaddr, myaddr, len);
+}
+
+/********************************************************** UDI_FILES_INFO */
+static void
+udi_files_info ()
+{
+ printf_unfiltered ("\tAttached to UDI socket to %s", udi_config_id);
+ if (prog_name != NULL)
+ printf_unfiltered ("and running program %s", prog_name);
+ printf_unfiltered (".\n");
+}
+
+/**************************************************** UDI_INSERT_BREAKPOINT */
+static int
+udi_insert_breakpoint (addr, contents_cache)
+ CORE_ADDR addr;
+ char *contents_cache;
+{
+ int cnt;
+ UDIError err;
+
+ for (cnt = 0; cnt < BKPT_TABLE_SIZE; cnt++)
+ if (bkpt_table[cnt].Type == 0) /* Find first free slot */
+ break;
+
+ if(cnt >= BKPT_TABLE_SIZE)
+ error("Too many breakpoints set");
+
+ bkpt_table[cnt].Addr.Offset = addr;
+ bkpt_table[cnt].Addr.Space = UDI29KIRAMSpace;
+ bkpt_table[cnt].PassCount = 1;
+ bkpt_table[cnt].Type = UDIBreakFlagExecute;
+
+ err = UDISetBreakpoint(bkpt_table[cnt].Addr,
+ bkpt_table[cnt].PassCount,
+ bkpt_table[cnt].Type,
+ &bkpt_table[cnt].BreakId);
+
+ if (err == 0) return 0; /* Success */
+
+ bkpt_table[cnt].Type = 0;
+ error("UDISetBreakpoint returned error code %d\n", err);
+}
+
+/**************************************************** UDI_REMOVE_BREAKPOINT */
+static int
+udi_remove_breakpoint (addr, contents_cache)
+ CORE_ADDR addr;
+ char *contents_cache;
+{
+ int cnt;
+ UDIError err;
+
+ for (cnt = 0; cnt < BKPT_TABLE_SIZE; cnt++)
+ if (bkpt_table[cnt].Addr.Offset == addr) /* Find matching breakpoint */
+ break;
+
+ if(cnt >= BKPT_TABLE_SIZE)
+ error("Can't find breakpoint in table");
+
+ bkpt_table[cnt].Type = 0;
+
+ err = UDIClearBreakpoint(bkpt_table[cnt].BreakId);
+ if (err == 0) return 0; /* Success */
+
+ error("UDIClearBreakpoint returned error code %d\n", err);
+}
+
+static void
+udi_kill(arg,from_tty)
+ char *arg;
+ int from_tty;
+{
+
+#if 0
+/*
+UDIStop does not really work as advertised. It causes the TIP to close it's
+connection, which usually results in GDB dying with a SIGPIPE. For now, we
+just invoke udi_close, which seems to get things right.
+*/
+ UDIStop();
+
+ udi_session_id = -1;
+ inferior_pid = 0;
+
+ if (from_tty)
+ printf_unfiltered("Target has been stopped.");
+#endif /* 0 */
+#if 0
+ udi_close(0);
+ pop_target();
+#endif /* 0 */
+
+ /* Keep the target around, e.g. so "run" can do the right thing when
+ we are already debugging something. */
+
+ if (UDIDisconnect (udi_session_id, UDITerminateSession))
+ {
+ warning ("UDIDisconnect() failed");
+ }
+
+ /* Do not try to close udi_session_id again, later in the program. */
+ udi_session_id = -1;
+ inferior_pid = 0;
+}
+
+/*
+ Load a program into the target. Args are: `program {options}'. The options
+ are used to control loading of the program, and are NOT passed onto the
+ loaded code as arguments. (You need to use the `run' command to do that.)
+
+ The options are:
+ -ms %d Set mem stack size to %d
+ -rs %d Set regular stack size to %d
+ -i send init info (default)
+ -noi don't send init info
+ -[tT] Load Text section
+ -[dD] Load Data section
+ -[bB] Load BSS section
+ -[lL] Load Lit section
+ */
+
+static void
+download(load_arg_string, from_tty)
+ char *load_arg_string;
+ int from_tty;
+{
+#define DEFAULT_MEM_STACK_SIZE 0x6000
+#define DEFAULT_REG_STACK_SIZE 0x2000
+
+ char *token;
+ char *filename;
+ asection *section;
+ bfd *pbfd;
+ UDIError err;
+ int load_text = 1, load_data = 1, load_bss = 1, load_lit = 1;
+
+ address_ranges[0].Space = UDI29KIRAMSpace;
+ address_ranges[0].Offset = 0xffffffff;
+ address_ranges[0].Size = 0;
+
+ address_ranges[1].Space = UDI29KDRAMSpace;
+ address_ranges[1].Offset = 0xffffffff;
+ address_ranges[1].Size = 0;
+
+ stack_sizes[0] = DEFAULT_REG_STACK_SIZE;
+ stack_sizes[1] = DEFAULT_MEM_STACK_SIZE;
+
+ dont_repeat ();
+
+ filename = strtok(load_arg_string, " \t");
+ if (!filename)
+ error ("Must specify at least a file name with the load command");
+
+ filename = tilde_expand (filename);
+ make_cleanup ((make_cleanup_func) free, filename);
+
+ while (token = strtok (NULL, " \t"))
+ {
+ if (token[0] == '-')
+ {
+ token++;
+
+ if (STREQ (token, "ms"))
+ stack_sizes[1] = atol (strtok (NULL, " \t"));
+ else if (STREQ (token, "rs"))
+ stack_sizes[0] = atol (strtok (NULL, " \t"));
+ else
+ {
+ load_text = load_data = load_bss = load_lit = 0;
+
+ while (*token)
+ {
+ switch (*token++)
+ {
+ case 't':
+ case 'T':
+ load_text = 1;
+ break;
+ case 'd':
+ case 'D':
+ load_data = 1;
+ break;
+ case 'b':
+ case 'B':
+ load_bss = 1;
+ break;
+ case 'l':
+ case 'L':
+ load_lit = 1;
+ break;
+ default:
+ error ("Unknown UDI load option -%s", token-1);
+ }
+ }
+ }
+ }
+ }
+
+ pbfd = bfd_openr (filename, gnutarget);
+
+ if (!pbfd)
+ /* FIXME: should be using bfd_errmsg, not assuming it was
+ bfd_error_system_call. */
+ perror_with_name (filename);
+
+ /* FIXME: should be checking for errors from bfd_close (for one thing,
+ on error it does not free all the storage associated with the
+ bfd). */
+ make_cleanup ((make_cleanup_func) bfd_close, pbfd);
+
+ QUIT;
+ immediate_quit++;
+
+ if (!bfd_check_format (pbfd, bfd_object))
+ error ("It doesn't seem to be an object file");
+
+ for (section = pbfd->sections; section; section = section->next)
+ {
+ if (bfd_get_section_flags (pbfd, section) & SEC_ALLOC)
+ {
+ UDIResource To;
+ UDICount Count;
+ unsigned long section_size, section_end;
+ const char *section_name;
+
+ section_name = bfd_get_section_name (pbfd, section);
+ if (STREQ (section_name, ".text") && !load_text)
+ continue;
+ else if (STREQ (section_name, ".data") && !load_data)
+ continue;
+ else if (STREQ (section_name, ".bss") && !load_bss)
+ continue;
+ else if (STREQ (section_name, ".lit") && !load_lit)
+ continue;
+
+ To.Offset = bfd_get_section_vma (pbfd, section);
+ section_size = bfd_section_size (pbfd, section);
+ section_end = To.Offset + section_size;
+
+ if (section_size == 0)
+ /* This is needed at least in the BSS case, where the code
+ below starts writing before it even checks the size. */
+ continue;
+
+ printf_unfiltered("[Loading section %s at %x (%d bytes)]\n",
+ section_name,
+ To.Offset,
+ section_size);
+
+ if (bfd_get_section_flags (pbfd, section) & SEC_CODE)
+ {
+ To.Space = UDI29KIRAMSpace;
+
+ address_ranges[0].Offset = min (address_ranges[0].Offset,
+ To.Offset);
+ address_ranges[0].Size = max (address_ranges[0].Size,
+ section_end
+ - address_ranges[0].Offset);
+ }
+ else
+ {
+ To.Space = UDI29KDRAMSpace;
+
+ address_ranges[1].Offset = min (address_ranges[1].Offset,
+ To.Offset);
+ address_ranges[1].Size = max (address_ranges[1].Size,
+ section_end
+ - address_ranges[1].Offset);
+ }
+
+ if (bfd_get_section_flags (pbfd, section) & SEC_LOAD) /* Text, data or lit */
+ {
+ file_ptr fptr;
+
+ fptr = 0;
+
+ while (section_size > 0)
+ {
+ char buffer[1024];
+
+ Count = min (section_size, 1024);
+
+ bfd_get_section_contents (pbfd, section, buffer, fptr,
+ Count);
+
+ err = UDIWrite ((UDIHostMemPtr)buffer, /* From */
+ To, /* To */
+ Count, /* Count */
+ (UDISizeT)1, /* Size */
+ &Count, /* CountDone */
+ (UDIBool)0); /* HostEndian */
+ if (err)
+ error ("UDIWrite failed, error = %d", err);
+
+ To.Offset += Count;
+ fptr += Count;
+ section_size -= Count;
+ }
+ }
+ else /* BSS */
+ {
+ UDIResource From;
+ unsigned long zero = 0;
+
+ /* Write a zero byte at the vma */
+ /* FIXME: Broken for sections of 1-3 bytes (we test for
+ zero above). */
+ err = UDIWrite ((UDIHostMemPtr)&zero, /* From */
+ To, /* To */
+ (UDICount)1, /* Count */
+ (UDISizeT)4, /* Size */
+ &Count, /* CountDone */
+ (UDIBool)0); /* HostEndian */
+ if (err)
+ error ("UDIWrite failed, error = %d", err);
+
+ From = To;
+ To.Offset+=4;
+
+ /* Now, duplicate it for the length of the BSS */
+ err = UDICopy (From, /* From */
+ To, /* To */
+ (UDICount)(section_size/4 - 1), /* Count */
+ (UDISizeT)4, /* Size */
+ &Count, /* CountDone */
+ (UDIBool)1); /* Direction */
+ if (err)
+ {
+ char message[100];
+ int xerr;
+
+ xerr = UDIGetErrorMsg(err, 100, message, &Count);
+ if (!xerr)
+ fprintf_unfiltered (gdb_stderr, "Error is %s\n", message);
+ else
+ fprintf_unfiltered (gdb_stderr, "xerr is %d\n", xerr);
+ error ("UDICopy failed, error = %d", err);
+ }
+ }
+
+ }
+ }
+
+ entry.Space = UDI29KIRAMSpace;
+ entry.Offset = bfd_get_start_address (pbfd);
+
+ immediate_quit--;
+}
+
+/* Function to download an image into the remote target. */
+
+static void
+udi_load (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ download (args, from_tty);
+
+ /* As a convenience, pick up any symbol info that is in the program
+ being loaded. Note that we assume that the program is the``mainline'';
+ if this is not always true, then this code will need to be augmented. */
+ symbol_file_add (strtok (args, " \t"), from_tty, 0, 1, 0, 0, 0, 0);
+
+ /* Getting new symbols may change our opinion about what is
+ frameless. */
+ reinit_frame_cache ();
+}
+
+/*************************************************** UDI_WRITE_INFERIOR_MEMORY
+** Copy LEN bytes of data from debugger memory at MYADDR
+ to inferior's memory at MEMADDR. Returns number of bytes written. */
+static int
+udi_write_inferior_memory (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+{
+ int nwritten = 0;
+ UDIUInt32 *From;
+ UDIResource To;
+ UDICount Count;
+ UDISizeT Size = 1;
+ UDICount CountDone = 0;
+ UDIBool HostEndian = 0;
+
+ To.Space = udi_memory_space(memaddr);
+ From = (UDIUInt32*)myaddr;
+
+ while (nwritten < len)
+ { Count = len - nwritten;
+ if (Count > MAXDATA) Count = MAXDATA;
+ To.Offset = memaddr + nwritten;
+ if(UDIWrite(From, To, Count, Size, &CountDone, HostEndian))
+ { error("UDIWrite() failed in udi_write_inferior_memory");
+ break;
+ }
+ else
+ { nwritten += CountDone;
+ From += CountDone;
+ }
+ }
+ return(nwritten);
+}
+
+/**************************************************** UDI_READ_INFERIOR_MEMORY
+** Read LEN bytes from inferior memory at MEMADDR. Put the result
+ at debugger address MYADDR. Returns number of bytes read. */
+static int
+udi_read_inferior_memory(memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+{
+ int nread = 0;
+ UDIResource From;
+ UDIUInt32 *To;
+ UDICount Count;
+ UDISizeT Size = 1;
+ UDICount CountDone = 0;
+ UDIBool HostEndian = 0;
+ UDIError err;
+
+ From.Space = udi_memory_space(memaddr);
+ To = (UDIUInt32*)myaddr;
+
+ while (nread < len)
+ { Count = len - nread;
+ if (Count > MAXDATA) Count = MAXDATA;
+ From.Offset = memaddr + nread;
+ if(err = UDIRead(From, To, Count, Size, &CountDone, HostEndian))
+ { error("UDIRead() failed in udi_read_inferior_memory");
+ break;
+ }
+ else
+ { nread += CountDone;
+ To += CountDone;
+ }
+ }
+ return(nread);
+}
+
+/********************************************************************* WARNING
+*/
+udi_warning(num)
+int num;
+{
+ error ("ERROR while loading program into remote TIP: $d\n", num);
+}
+
+
+/*****************************************************************************/
+/* Fetch a single register indicatated by 'regno'.
+ * Returns 0/-1 on success/failure.
+ */
+static void
+fetch_register (regno)
+ int regno;
+{
+ UDIResource From;
+ UDIUInt32 To;
+ UDICount Count = 1;
+ UDISizeT Size = 4;
+ UDICount CountDone;
+ UDIBool HostEndian = 0;
+ UDIError err;
+ int result;
+
+ if (regno == GR1_REGNUM)
+ {
+ From.Space = UDI29KGlobalRegs;
+ From.Offset = 1;
+ }
+ else if (regno >= GR96_REGNUM && regno < GR96_REGNUM + 32)
+ {
+ From.Space = UDI29KGlobalRegs;
+ From.Offset = (regno - GR96_REGNUM) + 96;;
+ }
+
+#if defined(GR64_REGNUM)
+
+ else if (regno >= GR64_REGNUM && regno < GR64_REGNUM + 32 )
+ {
+ From.Space = UDI29KGlobalRegs;
+ From.Offset = (regno - GR64_REGNUM) + 64;
+ }
+
+#endif /* GR64_REGNUM */
+
+ else if (regno >= LR0_REGNUM && regno < LR0_REGNUM + 128)
+ {
+ From.Space = UDI29KLocalRegs;
+ From.Offset = (regno - LR0_REGNUM);
+ }
+ else if (regno>=FPE_REGNUM && regno<=EXO_REGNUM)
+ {
+ int val = -1;
+ /*supply_register(160 + (regno - FPE_REGNUM),(char *) &val);*/
+ supply_register(regno, (char *) &val);
+ return; /* Pretend Success */
+ }
+ else
+ {
+ From.Space = UDI29KSpecialRegs;
+ From.Offset = regnum_to_srnum(regno);
+ }
+
+ if (err = UDIRead(From, &To, Count, Size, &CountDone, HostEndian))
+ error("UDIRead() failed in udi_fetch_registers");
+
+ supply_register(regno, (char *) &To);
+
+ if (remote_debug)
+ printf_unfiltered("Fetching register %s = 0x%x\n", REGISTER_NAME (regno), To);
+}
+/*****************************************************************************/
+/* Store a single register indicated by 'regno'.
+ * Returns 0/-1 on success/failure.
+ */
+static int
+store_register (regno)
+ int regno;
+{
+ int result;
+ UDIUInt32 From;
+ UDIResource To;
+ UDICount Count = 1;
+ UDISizeT Size = 4;
+ UDICount CountDone;
+ UDIBool HostEndian = 0;
+
+ From = read_register (regno); /* get data value */
+
+ if (remote_debug)
+ printf_unfiltered("Storing register %s = 0x%x\n", REGISTER_NAME (regno), From);
+
+ if (regno == GR1_REGNUM)
+ {
+ To.Space = UDI29KGlobalRegs;
+ To.Offset = 1;
+ result = UDIWrite(&From, To, Count, Size, &CountDone, HostEndian);
+ /* Setting GR1 changes the numbers of all the locals, so invalidate the
+ * register cache. Do this *after* calling read_register, because we want
+ * read_register to return the value that write_register has just stuffed
+ * into the registers array, not the value of the register fetched from
+ * the inferior.
+ */
+ registers_changed ();
+ }
+#if defined(GR64_REGNUM)
+ else if (regno >= GR64_REGNUM && regno < GR64_REGNUM + 32 )
+ {
+ To.Space = UDI29KGlobalRegs;
+ To.Offset = (regno - GR64_REGNUM) + 64;
+ result = UDIWrite(&From, To, Count, Size, &CountDone, HostEndian);
+ }
+#endif /* GR64_REGNUM */
+ else if (regno >= GR96_REGNUM && regno < GR96_REGNUM + 32)
+ {
+ To.Space = UDI29KGlobalRegs;
+ To.Offset = (regno - GR96_REGNUM) + 96;
+ result = UDIWrite(&From, To, Count, Size, &CountDone, HostEndian);
+ }
+ else if (regno >= LR0_REGNUM && regno < LR0_REGNUM + 128)
+ {
+ To.Space = UDI29KLocalRegs;
+ To.Offset = (regno - LR0_REGNUM);
+ result = UDIWrite(&From, To, Count, Size, &CountDone, HostEndian);
+ }
+ else if (regno >= FPE_REGNUM && regno <= EXO_REGNUM)
+ return 0; /* Pretend Success */
+ else if (regno == PC_REGNUM)
+ {
+ /* PC1 via UDI29KPC */
+
+ To.Space = UDI29KPC;
+ To.Offset = 0; /* PC1 */
+ result = UDIWrite (&From, To, Count, Size, &CountDone, HostEndian);
+
+ /* Writing to this loc actually changes the values of pc0 & pc1 */
+
+ register_valid[PC_REGNUM] = 0; /* pc1 */
+ register_valid[NPC_REGNUM] = 0; /* pc0 */
+ }
+ else /* An unprotected or protected special register */
+ {
+ To.Space = UDI29KSpecialRegs;
+ To.Offset = regnum_to_srnum(regno);
+ result = UDIWrite(&From, To, Count, Size, &CountDone, HostEndian);
+ }
+
+ if (result != 0)
+ error("UDIWrite() failed in store_registers");
+
+ return 0;
+}
+/********************************************************** REGNUM_TO_SRNUM */
+/*
+ * Convert a gdb special register number to a 29000 special register number.
+ */
+static int
+regnum_to_srnum(regno)
+int regno;
+{
+ switch(regno) {
+ case VAB_REGNUM: return(0);
+ case OPS_REGNUM: return(1);
+ case CPS_REGNUM: return(2);
+ case CFG_REGNUM: return(3);
+ case CHA_REGNUM: return(4);
+ case CHD_REGNUM: return(5);
+ case CHC_REGNUM: return(6);
+ case RBP_REGNUM: return(7);
+ case TMC_REGNUM: return(8);
+ case TMR_REGNUM: return(9);
+ case NPC_REGNUM: return(USE_SHADOW_PC ? (20) : (10));
+ case PC_REGNUM: return(USE_SHADOW_PC ? (21) : (11));
+ case PC2_REGNUM: return(USE_SHADOW_PC ? (22) : (12));
+ case MMU_REGNUM: return(13);
+ case LRU_REGNUM: return(14);
+ case IPC_REGNUM: return(128);
+ case IPA_REGNUM: return(129);
+ case IPB_REGNUM: return(130);
+ case Q_REGNUM: return(131);
+ case ALU_REGNUM: return(132);
+ case BP_REGNUM: return(133);
+ case FC_REGNUM: return(134);
+ case CR_REGNUM: return(135);
+ case FPE_REGNUM: return(160);
+ case INTE_REGNUM: return(161);
+ case FPS_REGNUM: return(162);
+ case EXO_REGNUM:return(164);
+ default:
+ return(255); /* Failure ? */
+ }
+}
+/****************************************************************************/
+/*
+ * Determine the Target memory space qualifier based on the addr.
+ * FIXME: Can't distinguis I_ROM/D_ROM.
+ * FIXME: Doesn't know anything about I_CACHE/D_CACHE.
+ */
+static CPUSpace
+udi_memory_space(addr)
+CORE_ADDR addr;
+{
+ UDIUInt32 tstart = IMemStart;
+ UDIUInt32 tend = tstart + IMemSize;
+ UDIUInt32 dstart = DMemStart;
+ UDIUInt32 dend = tstart + DMemSize;
+ UDIUInt32 rstart = RMemStart;
+ UDIUInt32 rend = tstart + RMemSize;
+
+ if (((UDIUInt32)addr >= tstart) && ((UDIUInt32)addr < tend)) {
+ return UDI29KIRAMSpace;
+ } else if (((UDIUInt32)addr >= dstart) && ((UDIUInt32)addr < dend)) {
+ return UDI29KDRAMSpace;
+ } else if (((UDIUInt32)addr >= rstart) && ((UDIUInt32)addr < rend)) {
+ /* FIXME: how do we determine between D_ROM and I_ROM */
+ return UDI29KIROMSpace;
+ } else /* FIXME: what do me do now? */
+ return UDI29KDRAMSpace; /* Hmmm! */
+}
+/*********************************************************************** STUBS
+*/
+
+void convert16() {;}
+void convert32() {;}
+GDB_FILE * EchoFile = 0; /* used for debugging */
+int QuietMode = 0; /* used for debugging */
+
+#ifdef NO_HIF_SUPPORT
+service_HIF(msg)
+ union msg_t *msg;
+{
+ return(0); /* Emulate a failure */
+}
+#endif
+
+/* Target_ops vector. Not static because there does not seem to be
+ any portable way to do a forward declaration of a static variable.
+ The RS/6000 doesn't like "extern" followed by "static"; SunOS
+ /bin/cc doesn't like "static" twice. */
+
+struct target_ops udi_ops;
+
+static void
+init_udi_ops(void)
+{
+ udi_ops.to_shortname = "udi";
+ udi_ops.to_longname = "Remote UDI connected TIP";
+ udi_ops.to_doc = "Remote debug an AMD 29k using UDI socket connection to TIP process.\n\
+Arguments are\n\
+`configuration-id AF_INET hostname port-number'\n\
+To connect via the network, where hostname and port-number specify the\n\
+host and port where you can connect via UDI.\n\
+configuration-id is unused.\n\
+\n\
+`configuration-id AF_UNIX socket-name tip-program'\n\
+To connect using a local connection to the \"tip.exe\" program which is\n\
+ supplied by AMD. If socket-name specifies an AF_UNIX socket then the\n\
+ tip program must already be started; connect to it using that socket.\n\
+ If not, start up tip-program, which should be the name of the tip\n\
+ program. If appropriate, the PATH environment variable is searched.\n\
+ configuration-id is unused.\n\
+\n\
+`configuration-id'\n\
+ Look up the configuration in ./udi_soc or /etc/udi_soc, which\n\
+ are files containing lines in the above formats. configuration-id is\n\
+ used to pick which line of the file to use." ;
+ udi_ops.to_open = udi_open;
+ udi_ops.to_close = udi_close;
+ udi_ops.to_attach = udi_attach;
+ udi_ops.to_detach = udi_detach;
+ udi_ops.to_resume = udi_resume;
+ udi_ops.to_wait = udi_wait;
+ udi_ops.to_fetch_registers = udi_fetch_registers;
+ udi_ops.to_store_registers = udi_store_registers;
+ udi_ops.to_prepare_to_store = udi_prepare_to_store;
+ udi_ops.to_xfer_memory = udi_xfer_inferior_memory;
+ udi_ops.to_files_info = udi_files_info;
+ udi_ops.to_insert_breakpoint = udi_insert_breakpoint;
+ udi_ops.to_remove_breakpoint = udi_remove_breakpoint;
+ udi_ops.to_terminal_init = 0;
+ udi_ops.to_terminal_inferior = 0;
+ udi_ops.to_terminal_ours_for_output = 0;
+ udi_ops.to_terminal_ours = 0;
+ udi_ops.to_terminal_info = 0;
+ udi_ops.to_kill = udi_kill;
+ udi_ops.to_load = udi_load;
+ udi_ops.to_lookup_symbol = 0;
+ udi_ops.to_create_inferior = udi_create_inferior;
+ udi_ops.to_mourn_inferior = udi_mourn;
+ udi_ops.to_can_run = 0;
+ udi_ops.to_notice_signals = 0;
+ udi_ops.to_thread_alive = 0;
+ udi_ops.to_stop = 0;
+ udi_ops.to_stratum = process_stratum;
+ udi_ops.DONT_USE = 0;
+ udi_ops.to_has_all_memory = 1;
+ udi_ops.to_has_memory = 1;
+ udi_ops.to_has_stack = 1;
+ udi_ops.to_has_registers = 1;
+ udi_ops.to_has_execution = 1;
+ udi_ops.to_sections = 0;
+ udi_ops.to_sections_end = 0;
+ udi_ops.to_magic = OPS_MAGIC;
+};
+
+void
+_initialize_remote_udi ()
+{
+ init_udi_ops() ;
+ add_target (&udi_ops);
+}
diff --git a/gdb/remote-utils.c b/gdb/remote-utils.c
new file mode 100644
index 00000000000..7219255bb6a
--- /dev/null
+++ b/gdb/remote-utils.c
@@ -0,0 +1,654 @@
+/* Generic support for remote debugging interfaces.
+
+ Copyright 1993, 1994, 1998 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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.
+ */
+
+#include <ctype.h>
+
+#include "defs.h"
+#include "gdb_string.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"
+
+
+void _initialize_sr_support PARAMS ((void));
+
+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 PARAMS ((char *, char *));
+static void sr_com PARAMS ((char *, int));
+
+static void
+usage(proto, junk)
+ char *proto;
+ char *junk;
+{
+ if (junk != NULL)
+ fprintf_unfiltered(gdb_stderr, "Unrecognized arguments: `%s'.\n", junk);
+
+ error ("Usage: target %s [DEVICE [SPEED [DEBUG]]]\n\
+where DEVICE is the name of a device or HOST:PORT", 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;
+
+ /* 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);
+ 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);
+
+ /* If no args are specified, then we use the device specified by a
+ previous command or "set remotedevice". But if there is no
+ device, better stop now, not dump core. */
+
+ if (sr_get_device () == NULL)
+ usage (gr->ops->to_shortname, NULL);
+
+ sr_set_desc(SERIAL_OPEN (sr_get_device()));
+ if (!sr_get_desc())
+ perror_with_name((char *) sr_get_device());
+
+ if (baud_rate != -1)
+ {
+ if (SERIAL_SETBAUDRATE(sr_get_desc(), 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'", sr_get_device ());
+ if (baud_rate != -1)
+ printf_filtered (" at baud rate of %d",
+ baud_rate);
+ printf_filtered ("\n");
+ }
+
+ 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_unfiltered ("%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_unfiltered ("%c", buf);
+ else
+ printf_unfiltered ("<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_unfiltered ("%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. */
+
+static 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);
+ registers_changed ();
+ 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;
+{
+#ifdef __GO32__
+ printf_filtered ("\tAttached to DOS asynctsr\n");
+#else
+ printf_filtered ("\tAttached to %s", sr_get_device());
+ if (baud_rate != -1)
+ printf_filtered ("at %d baud", baud_rate);
+ printf_filtered ("\n");
+#endif
+
+ if (exec_bfd)
+ {
+ printf_filtered ("\tand running program %s\n",
+ bfd_get_filename (exec_bfd));
+ }
+ 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 executable 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)
+ fputc_unfiltered (*p, gdb_stdout);
+
+ fputc_unfiltered (ch, gdb_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... */
+ 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/gdb/remote-utils.h b/gdb/remote-utils.h
new file mode 100644
index 00000000000..d4fcd0eded3
--- /dev/null
+++ b/gdb/remote-utils.h
@@ -0,0 +1,142 @@
+/* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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;
+
+/* get and set debug value. */
+#define sr_get_debug() (remote_debug)
+#define sr_set_debug(newval) (remote_debug = (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));
+void gr_load_image PARAMS((char*, int from_tty));
+#endif /* REMOTE_UTILS_H */
diff --git a/gdb/remote-vx.c b/gdb/remote-vx.c
new file mode 100644
index 00000000000..9ad86d4562e
--- /dev/null
+++ b/gdb/remote-vx.c
@@ -0,0 +1,1467 @@
+/* Memory-access and commands for remote VxWorks processes, for GDB.
+ Copyright (C) 1990-95, 1997-98, 1999 Free Software Foundation, Inc.
+ Contributed by Wind River Systems and 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "frame.h"
+#include "inferior.h"
+#include "wait.h"
+#include "target.h"
+#include "gdbcore.h"
+#include "command.h"
+#include "symtab.h"
+#include "complaints.h"
+#include "gdbcmd.h"
+#include "bfd.h" /* Required by objfiles.h. */
+#include "symfile.h" /* Required by objfiles.h. */
+#include "objfiles.h"
+#include "gdb-stabs.h"
+
+#include "gdb_string.h"
+#include <errno.h>
+#include <signal.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#define malloc bogon_malloc /* Sun claims "char *malloc()" not void * */
+#define free bogon_free /* Sun claims "int free()" not void */
+#define realloc bogon_realloc /* Sun claims "char *realloc()", not void * */
+#include <rpc/rpc.h>
+#undef malloc
+#undef free
+#undef realloc
+#include <sys/time.h> /* UTek's <rpc/rpc.h> doesn't #incl this */
+#include <netdb.h>
+#include "vx-share/ptrace.h"
+#include "vx-share/xdr_ptrace.h"
+#include "vx-share/xdr_ld.h"
+#include "vx-share/xdr_rdb.h"
+#include "vx-share/dbgRpcLib.h"
+
+#include <symtab.h>
+
+/* Maximum number of bytes to transfer in a single
+ PTRACE_{READ,WRITE}DATA request. */
+#define VX_MEMXFER_MAX 4096
+
+extern void vx_read_register ();
+extern void vx_write_register ();
+extern void symbol_file_command ();
+extern int stop_soon_quietly; /* for wait_for_inferior */
+
+static int net_step ();
+static int net_ptrace_clnt_call (); /* Forward decl */
+static enum clnt_stat net_clnt_call (); /* Forward decl */
+
+/* Target ops structure for accessing memory and such over the net */
+
+static struct target_ops vx_ops;
+
+/* Target ops structure for accessing VxWorks child processes over the net */
+
+static struct target_ops vx_run_ops;
+
+/* Saved name of target host and called function for "info files".
+ Both malloc'd. */
+
+static char *vx_host;
+static char *vx_running; /* Called function */
+
+/* Nonzero means target that is being debugged remotely has a floating
+ point processor. */
+
+int target_has_fp;
+
+/* Default error message when the network is forking up. */
+
+static const char rpcerr[] = "network target debugging: rpc error";
+
+CLIENT *pClient; /* client used in net debugging */
+static int ptraceSock = RPC_ANYSOCK;
+
+enum clnt_stat net_clnt_call();
+static void parse_args ();
+
+static struct timeval rpcTimeout = { 10, 0 };
+
+static char *skip_white_space ();
+static char *find_white_space ();
+
+/* Tell the VxWorks target system to download a file.
+ The load addresses of the text, data, and bss segments are
+ stored in *pTextAddr, *pDataAddr, and *pBssAddr (respectively).
+ Returns 0 for success, -1 for failure. */
+
+static int
+net_load (filename, pTextAddr, pDataAddr, pBssAddr)
+ char *filename;
+ CORE_ADDR *pTextAddr;
+ CORE_ADDR *pDataAddr;
+ CORE_ADDR *pBssAddr;
+{
+ enum clnt_stat status;
+ struct ldfile ldstruct;
+ struct timeval load_timeout;
+
+ memset ((char *) &ldstruct, '\0', sizeof (ldstruct));
+
+ /* We invoke clnt_call () here directly, instead of through
+ net_clnt_call (), because we need to set a large timeout value.
+ The load on the target side can take quite a while, easily
+ more than 10 seconds. The user can kill this call by typing
+ CTRL-C if there really is a problem with the load.
+
+ Do not change the tv_sec value without checking -- select() imposes
+ a limit of 10**8 on it for no good reason that I can see... */
+
+ load_timeout.tv_sec = 99999999; /* A large number, effectively inf. */
+ load_timeout.tv_usec = 0;
+
+ status = clnt_call (pClient, VX_LOAD, xdr_wrapstring, &filename, xdr_ldfile,
+ &ldstruct, load_timeout);
+
+ if (status == RPC_SUCCESS)
+ {
+ if (*ldstruct.name == 0) /* load failed on VxWorks side */
+ return -1;
+ *pTextAddr = ldstruct.txt_addr;
+ *pDataAddr = ldstruct.data_addr;
+ *pBssAddr = ldstruct.bss_addr;
+ return 0;
+ }
+ else
+ return -1;
+}
+
+/* returns 0 if successful, errno if RPC failed or VxWorks complains. */
+
+static int
+net_break (addr, procnum)
+ int addr;
+ u_long procnum;
+{
+ enum clnt_stat status;
+ int break_status;
+ Rptrace ptrace_in; /* XXX This is stupid. It doesn't need to be a ptrace
+ structure. How about something smaller? */
+
+ memset ((char *) &ptrace_in, '\0', sizeof (ptrace_in));
+ break_status = 0;
+
+ ptrace_in.addr = addr;
+ ptrace_in.pid = inferior_pid;
+
+ status = net_clnt_call (procnum, xdr_rptrace, &ptrace_in, xdr_int,
+ &break_status);
+
+ if (status != RPC_SUCCESS)
+ return errno;
+
+ if (break_status == -1)
+ return ENOMEM;
+ return break_status; /* probably (FIXME) zero */
+}
+
+/* returns 0 if successful, errno otherwise */
+
+static int
+vx_insert_breakpoint (addr)
+ int addr;
+{
+ return net_break (addr, VX_BREAK_ADD);
+}
+
+/* returns 0 if successful, errno otherwise */
+
+static int
+vx_remove_breakpoint (addr)
+ int addr;
+{
+ return net_break (addr, VX_BREAK_DELETE);
+}
+
+/* Start an inferior process and sets inferior_pid to its pid.
+ EXEC_FILE is the file to run.
+ ALLARGS is a string containing the arguments to the program.
+ ENV is the environment vector to pass.
+ Returns process id. Errors reported with error().
+ On VxWorks, we ignore exec_file. */
+
+static void
+vx_create_inferior (exec_file, args, env)
+ char *exec_file;
+ char *args;
+ char **env;
+{
+ enum clnt_stat status;
+ arg_array passArgs;
+ TASK_START taskStart;
+
+ memset ((char *) &passArgs, '\0', sizeof (passArgs));
+ memset ((char *) &taskStart, '\0', sizeof (taskStart));
+
+ /* parse arguments, put them in passArgs */
+
+ parse_args (args, &passArgs);
+
+ if (passArgs.arg_array_len == 0)
+ error ("You must specify a function name to run, and arguments if any");
+
+ status = net_clnt_call (PROCESS_START, xdr_arg_array, &passArgs,
+ xdr_TASK_START, &taskStart);
+
+ if ((status != RPC_SUCCESS) || (taskStart.status == -1))
+ error ("Can't create process on remote target machine");
+
+ /* Save the name of the running function */
+ vx_running = savestring (passArgs.arg_array_val[0],
+ strlen (passArgs.arg_array_val[0]));
+
+ push_target (&vx_run_ops);
+ inferior_pid = taskStart.pid;
+
+ /* We will get a trace trap after one instruction.
+ Insert breakpoints and continue. */
+
+ init_wait_for_inferior ();
+
+ /* Set up the "saved terminal modes" of the inferior
+ based on what modes we are starting it with. */
+ target_terminal_init ();
+
+ /* Install inferior's terminal modes. */
+ target_terminal_inferior ();
+
+ stop_soon_quietly = 1;
+ wait_for_inferior (); /* Get the task spawn event */
+ stop_soon_quietly = 0;
+
+ /* insert_step_breakpoint (); FIXME, do we need this? */
+ proceed (-1, TARGET_SIGNAL_DEFAULT, 0);
+}
+
+/* Fill ARGSTRUCT in argc/argv form with the arguments from the
+ argument string ARGSTRING. */
+
+static void
+parse_args (arg_string, arg_struct)
+ register char *arg_string;
+ arg_array *arg_struct;
+{
+ register int arg_count = 0; /* number of arguments */
+ register int arg_index = 0;
+ register char *p0;
+
+ memset ((char *) arg_struct, '\0', sizeof (arg_array));
+
+ /* first count how many arguments there are */
+
+ p0 = arg_string;
+ while (*p0 != '\0')
+ {
+ if (*(p0 = skip_white_space (p0)) == '\0')
+ break;
+ p0 = find_white_space (p0);
+ arg_count++;
+ }
+
+ arg_struct->arg_array_len = arg_count;
+ arg_struct->arg_array_val = (char **) xmalloc ((arg_count + 1)
+ * sizeof (char *));
+
+ /* now copy argument strings into arg_struct. */
+
+ while (*(arg_string = skip_white_space (arg_string)))
+ {
+ p0 = find_white_space (arg_string);
+ arg_struct->arg_array_val[arg_index++] = savestring (arg_string,
+ p0 - arg_string);
+ arg_string = p0;
+ }
+
+ arg_struct->arg_array_val[arg_count] = NULL;
+}
+
+/* Advance a string pointer across whitespace and return a pointer
+ to the first non-white character. */
+
+static char *
+skip_white_space (p)
+ register char *p;
+{
+ while (*p == ' ' || *p == '\t')
+ p++;
+ return p;
+}
+
+/* Search for the first unquoted whitespace character in a string.
+ Returns a pointer to the character, or to the null terminator
+ if no whitespace is found. */
+
+static char *
+find_white_space (p)
+ register char *p;
+{
+ register int c;
+
+ while ((c = *p) != ' ' && c != '\t' && c)
+ {
+ if (c == '\'' || c == '"')
+ {
+ while (*++p != c && *p)
+ {
+ if (*p == '\\')
+ p++;
+ }
+ if (!*p)
+ break;
+ }
+ p++;
+ }
+ return p;
+}
+
+/* Poll the VxWorks target system for an event related
+ to the debugged task.
+ Returns -1 if remote wait failed, task status otherwise. */
+
+static int
+net_wait (pEvent)
+ RDB_EVENT *pEvent;
+{
+ int pid;
+ enum clnt_stat status;
+
+ memset ((char *) pEvent, '\0', sizeof (RDB_EVENT));
+
+ pid = inferior_pid;
+ status = net_clnt_call (PROCESS_WAIT, xdr_int, &pid, xdr_RDB_EVENT,
+ pEvent);
+
+ /* return (status == RPC_SUCCESS)? pEvent->status: -1; */
+ if (status == RPC_SUCCESS)
+ return ((pEvent->status) ? 1 : 0);
+ else if (status == RPC_TIMEDOUT)
+ return (1);
+ else
+ return (-1);
+}
+
+/* Suspend the remote task.
+ Returns -1 if suspend fails on target system, 0 otherwise. */
+
+static int
+net_quit ()
+{
+ int pid;
+ int quit_status;
+ enum clnt_stat status;
+
+ quit_status = 0;
+
+ /* don't let rdbTask suspend itself by passing a pid of 0 */
+
+ if ((pid = inferior_pid) == 0)
+ return -1;
+
+ status = net_clnt_call (VX_TASK_SUSPEND, xdr_int, &pid, xdr_int,
+ &quit_status);
+
+ return (status == RPC_SUCCESS)? quit_status: -1;
+}
+
+/* Read a register or registers from the remote system. */
+
+void
+net_read_registers (reg_buf, len, procnum)
+ char *reg_buf;
+ int len;
+ u_long procnum;
+{
+ int status;
+ Rptrace ptrace_in;
+ Ptrace_return ptrace_out;
+ C_bytes out_data;
+ char message[100];
+
+ memset ((char *) &ptrace_in, '\0', sizeof (ptrace_in));
+ memset ((char *) &ptrace_out, '\0', sizeof (ptrace_out));
+
+ /* Initialize RPC input argument structure. */
+
+ ptrace_in.pid = inferior_pid;
+ ptrace_in.info.ttype = NOINFO;
+
+ /* Initialize RPC return value structure. */
+
+ out_data.bytes = reg_buf;
+ out_data.len = len;
+ ptrace_out.info.more_data = (caddr_t) &out_data;
+
+ /* Call RPC; take an error exit if appropriate. */
+
+ status = net_ptrace_clnt_call (procnum, &ptrace_in, &ptrace_out);
+ if (status)
+ error (rpcerr);
+ if (ptrace_out.status == -1)
+ {
+ errno = ptrace_out.errno_num;
+ sprintf (message, "reading %s registers", (procnum == PTRACE_GETREGS)
+ ? "general-purpose"
+ : "floating-point");
+ perror_with_name (message);
+ }
+}
+
+/* Write register values to a VxWorks target. REG_BUF points to a buffer
+ containing the raw register values, LEN is the length of REG_BUF in
+ bytes, and PROCNUM is the RPC procedure number (PTRACE_SETREGS or
+ PTRACE_SETFPREGS). An error exit is taken if the RPC call fails or
+ if an error status is returned by the remote debug server. This is
+ a utility routine used by vx_write_register (). */
+
+void
+net_write_registers (reg_buf, len, procnum)
+ char *reg_buf;
+ int len;
+ u_long procnum;
+{
+ int status;
+ Rptrace ptrace_in;
+ Ptrace_return ptrace_out;
+ C_bytes in_data;
+ char message[100];
+
+ memset ((char *) &ptrace_in, '\0', sizeof (ptrace_in));
+ memset ((char *) &ptrace_out, '\0', sizeof (ptrace_out));
+
+ /* Initialize RPC input argument structure. */
+
+ in_data.bytes = reg_buf;
+ in_data.len = len;
+
+ ptrace_in.pid = inferior_pid;
+ ptrace_in.info.ttype = DATA;
+ ptrace_in.info.more_data = (caddr_t) &in_data;
+
+ /* Call RPC; take an error exit if appropriate. */
+
+ status = net_ptrace_clnt_call (procnum, &ptrace_in, &ptrace_out);
+ if (status)
+ error (rpcerr);
+ if (ptrace_out.status == -1)
+ {
+ errno = ptrace_out.errno_num;
+ sprintf (message, "writing %s registers", (procnum == PTRACE_SETREGS)
+ ? "general-purpose"
+ : "floating-point");
+ perror_with_name (message);
+ }
+}
+
+/* Prepare to store registers. Since we will store all of them,
+ read out their current values now. */
+
+static void
+vx_prepare_to_store ()
+{
+ /* Fetch all registers, if any of them are not yet fetched. */
+ read_register_bytes (0, NULL, REGISTER_BYTES);
+}
+
+/* Copy LEN bytes to or from remote inferior's memory starting at MEMADDR
+ to debugger memory starting at MYADDR. WRITE is true if writing to the
+ inferior.
+ Result is the number of bytes written or read (zero if error). The
+ protocol allows us to return a negative count, indicating that we can't
+ handle the current address but can handle one N bytes further, but
+ vxworks doesn't give us that information. */
+
+static int
+vx_xfer_memory (memaddr, myaddr, len, write, target)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+ int write;
+ struct target_ops *target; /* ignored */
+{
+ int status;
+ Rptrace ptrace_in;
+ Ptrace_return ptrace_out;
+ C_bytes data;
+ enum ptracereq request;
+ int nleft, nxfer;
+
+ memset ((char *) &ptrace_in, '\0', sizeof (ptrace_in));
+ memset ((char *) &ptrace_out, '\0', sizeof (ptrace_out));
+
+ ptrace_in.pid = inferior_pid; /* XXX pid unnecessary for READDATA */
+ ptrace_in.addr = (int) memaddr; /* Where from */
+ ptrace_in.data = len; /* How many bytes */
+
+ if (write)
+ {
+ ptrace_in.info.ttype = DATA;
+ ptrace_in.info.more_data = (caddr_t) &data;
+
+ data.bytes = (caddr_t) myaddr; /* Where from */
+ data.len = len; /* How many bytes (again, for XDR) */
+ request = PTRACE_WRITEDATA;
+ }
+ else
+ {
+ ptrace_out.info.more_data = (caddr_t) &data;
+ request = PTRACE_READDATA;
+ }
+ /* Loop until the entire request has been satisfied, transferring
+ at most VX_MEMXFER_MAX bytes per iteration. Break from the loop
+ if an error status is returned by the remote debug server. */
+
+ nleft = len;
+ status = 0;
+
+ while (nleft > 0 && status == 0)
+ {
+ nxfer = min (nleft, VX_MEMXFER_MAX);
+
+ ptrace_in.addr = (int) memaddr;
+ ptrace_in.data = nxfer;
+ data.bytes = (caddr_t) myaddr;
+ data.len = nxfer;
+
+ /* Request a block from the remote debug server; if RPC fails,
+ report an error and return to debugger command level. */
+
+ if (net_ptrace_clnt_call (request, &ptrace_in, &ptrace_out))
+ error (rpcerr);
+
+ status = ptrace_out.status;
+ if (status == 0)
+ {
+ memaddr += nxfer;
+ myaddr += nxfer;
+ nleft -= nxfer;
+ }
+ else
+ {
+ /* A target-side error has ocurred. Set errno to the error
+ code chosen by the target so that a later perror () will
+ say something meaningful. */
+
+ errno = ptrace_out.errno_num;
+ }
+ }
+
+ /* Return the number of bytes transferred. */
+
+ return (len - nleft);
+}
+
+static void
+vx_files_info ()
+{
+ printf_unfiltered ("\tAttached to host `%s'", vx_host);
+ printf_unfiltered (", which has %sfloating point", target_has_fp? "": "no ");
+ printf_unfiltered (".\n");
+}
+
+static void
+vx_run_files_info ()
+{
+ printf_unfiltered ("\tRunning %s VxWorks process %s",
+ vx_running ? "child" : "attached",
+ local_hex_string (inferior_pid));
+ if (vx_running)
+ printf_unfiltered (", function `%s'", vx_running);
+ printf_unfiltered(".\n");
+}
+
+static void
+vx_resume (pid, step, siggnal)
+ int pid;
+ int step;
+ enum target_signal siggnal;
+{
+ int status;
+ Rptrace ptrace_in;
+ Ptrace_return ptrace_out;
+ CORE_ADDR cont_addr;
+
+ if (pid == -1)
+ pid = inferior_pid;
+
+ if (siggnal != 0 && siggnal != stop_signal)
+ error ("Cannot send signals to VxWorks processes");
+
+ /* Set CONT_ADDR to the address at which we are continuing,
+ or to 1 if we are continuing from where the program stopped.
+ This conforms to traditional ptrace () usage, but at the same
+ time has special meaning for the VxWorks remote debug server.
+ If the address is not 1, the server knows that the target
+ program is jumping to a new address, which requires special
+ handling if there is a breakpoint at the new address. */
+
+ cont_addr = read_register (PC_REGNUM);
+ if (cont_addr == stop_pc)
+ cont_addr = 1;
+
+ memset ((char *) &ptrace_in, '\0', sizeof (ptrace_in));
+ memset ((char *) &ptrace_out, '\0', sizeof (ptrace_out));
+
+ ptrace_in.pid = pid;
+ ptrace_in.addr = cont_addr; /* Target side insists on this, or it panics. */
+
+ if (step)
+ status = net_step();
+ else
+ status = net_ptrace_clnt_call (PTRACE_CONT, &ptrace_in, &ptrace_out);
+
+ if (status)
+ error (rpcerr);
+ if (ptrace_out.status == -1)
+ {
+ errno = ptrace_out.errno_num;
+ perror_with_name ("Resuming remote process");
+ }
+}
+
+static void
+vx_mourn_inferior ()
+{
+ pop_target (); /* Pop back to no-child state */
+ generic_mourn_inferior ();
+}
+
+
+static void vx_add_symbols PARAMS ((char *, int, CORE_ADDR, CORE_ADDR,
+ CORE_ADDR));
+
+struct find_sect_args {
+ CORE_ADDR text_start;
+ CORE_ADDR data_start;
+ CORE_ADDR bss_start;
+};
+
+static void find_sect PARAMS ((bfd *, asection *, void *));
+
+static void
+find_sect (abfd, sect, obj)
+ bfd *abfd;
+ asection *sect;
+ PTR obj;
+{
+ struct find_sect_args *args = (struct find_sect_args *)obj;
+
+ if (bfd_get_section_flags (abfd, sect) & (SEC_CODE & SEC_READONLY))
+ args->text_start = bfd_get_section_vma (abfd, sect);
+ else if (bfd_get_section_flags (abfd, sect) & SEC_ALLOC)
+ {
+ if (bfd_get_section_flags (abfd, sect) & SEC_LOAD)
+ {
+ /* Exclude .ctor and .dtor sections which have SEC_CODE set but not
+ SEC_DATA. */
+ if (bfd_get_section_flags (abfd, sect) & SEC_DATA)
+ args->data_start = bfd_get_section_vma (abfd, sect);
+ }
+ else
+ args->bss_start = bfd_get_section_vma (abfd, sect);
+ }
+}
+
+static void
+vx_add_symbols (name, from_tty, text_addr, data_addr, bss_addr)
+ char *name;
+ int from_tty;
+ CORE_ADDR text_addr;
+ CORE_ADDR data_addr;
+ CORE_ADDR bss_addr;
+{
+ struct section_offsets *offs;
+ struct objfile *objfile;
+ struct find_sect_args ss;
+
+ /* It might be nice to suppress the breakpoint_re_set which happens here
+ because we are going to do one again after the objfile_relocate. */
+ objfile = symbol_file_add (name, from_tty, 0, 0, 0, 0, 0, 0);
+
+ /* This is a (slightly cheesy) way of superceding the old symbols. A less
+ cheesy way would be to find the objfile with the same name and
+ free_objfile it. */
+ objfile_to_front (objfile);
+
+ offs = (struct section_offsets *)
+ alloca (sizeof (struct section_offsets)
+ + objfile->num_sections * sizeof (offs->offsets));
+ memcpy (offs, objfile->section_offsets,
+ sizeof (struct section_offsets)
+ + objfile->num_sections * sizeof (offs->offsets));
+
+ ss.text_start = 0;
+ ss.data_start = 0;
+ ss.bss_start = 0;
+ bfd_map_over_sections (objfile->obfd, find_sect, &ss);
+
+ /* Both COFF and b.out frontends use these SECT_OFF_* values. */
+ ANOFFSET (offs, SECT_OFF_TEXT) = text_addr - ss.text_start;
+ ANOFFSET (offs, SECT_OFF_DATA) = data_addr - ss.data_start;
+ ANOFFSET (offs, SECT_OFF_BSS) = bss_addr - ss.bss_start;
+ objfile_relocate (objfile, offs);
+}
+
+/* This function allows the addition of incrementally linked object files. */
+
+static void
+vx_load_command (arg_string, from_tty)
+ char *arg_string;
+ int from_tty;
+{
+ CORE_ADDR text_addr;
+ CORE_ADDR data_addr;
+ CORE_ADDR bss_addr;
+
+ if (arg_string == 0)
+ error ("The load command takes a file name");
+
+ arg_string = tilde_expand (arg_string);
+ make_cleanup (free, arg_string);
+
+ dont_repeat ();
+
+ /* Refuse to load the module if a debugged task is running. Doing so
+ can have a number of unpleasant consequences to the running task. */
+
+ if (inferior_pid != 0 && target_has_execution)
+ {
+ if (query ("You may not load a module while the target task is running.\n\
+Kill the target task? "))
+ target_kill ();
+ else
+ error ("Load cancelled.");
+ }
+
+ QUIT;
+ immediate_quit++;
+ if (net_load (arg_string, &text_addr, &data_addr, &bss_addr) == -1)
+ error ("Load failed on target machine");
+ immediate_quit--;
+
+ vx_add_symbols (arg_string, from_tty, text_addr, data_addr, bss_addr);
+
+ /* Getting new symbols may change our opinion about what is
+ frameless. */
+ reinit_frame_cache ();
+}
+
+/* Single step the target program at the source or machine level.
+ Takes an error exit if rpc fails.
+ Returns -1 if remote single-step operation fails, else 0. */
+
+static int
+net_step ()
+{
+ enum clnt_stat status;
+ int step_status;
+ SOURCE_STEP source_step;
+
+ source_step.taskId = inferior_pid;
+
+ if (step_range_end)
+ {
+ source_step.startAddr = step_range_start;
+ source_step.endAddr = step_range_end;
+ }
+ else
+ {
+ source_step.startAddr = 0;
+ source_step.endAddr = 0;
+ }
+
+ status = net_clnt_call (VX_SOURCE_STEP, xdr_SOURCE_STEP, &source_step,
+ xdr_int, &step_status);
+
+ if (status == RPC_SUCCESS)
+ return step_status;
+ else
+ error (rpcerr);
+}
+
+/* Emulate ptrace using RPC calls to the VxWorks target system.
+ Returns nonzero (-1) if RPC status to VxWorks is bad, 0 otherwise. */
+
+static int
+net_ptrace_clnt_call (request, pPtraceIn, pPtraceOut)
+ enum ptracereq request;
+ Rptrace *pPtraceIn;
+ Ptrace_return *pPtraceOut;
+{
+ enum clnt_stat status;
+
+ status = net_clnt_call (request, xdr_rptrace, pPtraceIn, xdr_ptrace_return,
+ pPtraceOut);
+
+ if (status != RPC_SUCCESS)
+ return -1;
+
+ return 0;
+}
+
+/* Query the target for the name of the file from which VxWorks was
+ booted. pBootFile is the address of a pointer to the buffer to
+ receive the file name; if the pointer pointed to by pBootFile is
+ NULL, memory for the buffer will be allocated by XDR.
+ Returns -1 if rpc failed, 0 otherwise. */
+
+static int
+net_get_boot_file (pBootFile)
+ char **pBootFile;
+{
+ enum clnt_stat status;
+
+ status = net_clnt_call (VX_BOOT_FILE_INQ, xdr_void, (char *) 0,
+ xdr_wrapstring, pBootFile);
+ return (status == RPC_SUCCESS) ? 0 : -1;
+}
+
+/* Fetch a list of loaded object modules from the VxWorks target.
+ Returns -1 if rpc failed, 0 otherwise
+ There's no way to check if the returned loadTable is correct.
+ VxWorks doesn't check it. */
+
+static int
+net_get_symbols (pLoadTable)
+ ldtabl *pLoadTable; /* return pointer to ldtabl here */
+{
+ enum clnt_stat status;
+
+ memset ((char *) pLoadTable, '\0', sizeof (struct ldtabl));
+
+ status = net_clnt_call (VX_STATE_INQ, xdr_void, 0, xdr_ldtabl, pLoadTable);
+ return (status == RPC_SUCCESS) ? 0 : -1;
+}
+
+/* Look up a symbol in the VxWorks target's symbol table.
+ Returns status of symbol read on target side (0=success, -1=fail)
+ Returns -1 and complain()s if rpc fails. */
+
+struct complaint cant_contact_target =
+ {"Lost contact with VxWorks target", 0, 0};
+
+static int
+vx_lookup_symbol (name, pAddr)
+ char *name; /* symbol name */
+ CORE_ADDR *pAddr;
+{
+ enum clnt_stat status;
+ SYMBOL_ADDR symbolAddr;
+
+ *pAddr = 0;
+ memset ((char *) &symbolAddr, '\0', sizeof (symbolAddr));
+
+ status = net_clnt_call (VX_SYMBOL_INQ, xdr_wrapstring, &name,
+ xdr_SYMBOL_ADDR, &symbolAddr);
+ if (status != RPC_SUCCESS)
+ {
+ complain (&cant_contact_target);
+ return -1;
+ }
+
+ *pAddr = symbolAddr.addr;
+ return symbolAddr.status;
+}
+
+/* Check to see if the VxWorks target has a floating point coprocessor.
+ Returns 1 if target has floating point processor, 0 otherwise.
+ Calls error() if rpc fails. */
+
+static int
+net_check_for_fp ()
+{
+ enum clnt_stat status;
+ bool_t fp = 0; /* true if fp processor is present on target board */
+
+ status = net_clnt_call (VX_FP_INQUIRE, xdr_void, 0, xdr_bool, &fp);
+ if (status != RPC_SUCCESS)
+ error (rpcerr);
+
+ return (int) fp;
+}
+
+/* Establish an RPC connection with the VxWorks target system.
+ Calls error () if unable to establish connection. */
+
+static void
+net_connect (host)
+ char *host;
+{
+ struct sockaddr_in destAddr;
+ struct hostent *destHost;
+ unsigned long addr;
+
+ /* Get the internet address for the given host. Allow a numeric
+ IP address or a hostname. */
+
+ addr = inet_addr (host);
+ if (addr == -1)
+ {
+ destHost = (struct hostent *) gethostbyname (host);
+ if (destHost == NULL)
+ /* FIXME: Probably should include hostname here in quotes.
+ For example if the user types "target vxworks vx960 " it should
+ say "Invalid host `vx960 '." not just "Invalid hostname". */
+ error ("Invalid hostname. Couldn't find remote host address.");
+ addr = * (unsigned long *) destHost->h_addr;
+ }
+
+ memset (&destAddr, '\0', sizeof (destAddr));
+
+ destAddr.sin_addr.s_addr = addr;
+ destAddr.sin_family = AF_INET;
+ destAddr.sin_port = 0; /* set to actual port that remote
+ ptrace is listening on. */
+
+ /* Create a tcp client transport on which to issue
+ calls to the remote ptrace server. */
+
+ ptraceSock = RPC_ANYSOCK;
+ pClient = clnttcp_create (&destAddr, RDBPROG, RDBVERS, &ptraceSock, 0, 0);
+ /* FIXME, here is where we deal with different version numbers of the
+ proto */
+
+ if (pClient == NULL)
+ {
+ clnt_pcreateerror ("\tnet_connect");
+ error ("Couldn't connect to remote target.");
+ }
+}
+
+/* Sleep for the specified number of milliseconds
+ * (assumed to be less than 1000).
+ * If select () is interrupted, returns immediately;
+ * takes an error exit if select () fails for some other reason.
+ */
+
+static void
+sleep_ms (ms)
+ long ms;
+{
+ struct timeval select_timeout;
+ int status;
+
+ select_timeout.tv_sec = 0;
+ select_timeout.tv_usec = ms * 1000;
+
+ status = select (0, (fd_set *) 0, (fd_set *) 0, (fd_set *) 0,
+ &select_timeout);
+
+ if (status < 0 && errno != EINTR)
+ perror_with_name ("select");
+}
+
+static int
+vx_wait (pid_to_wait_for, status)
+ int pid_to_wait_for;
+ struct target_waitstatus *status;
+{
+ register int pid;
+ RDB_EVENT rdbEvent;
+ int quit_failed;
+
+ do
+ {
+ /* If CTRL-C is hit during this loop,
+ suspend the inferior process. */
+
+ quit_failed = 0;
+ if (quit_flag)
+ {
+ quit_failed = (net_quit () == -1);
+ quit_flag = 0;
+ }
+
+ /* If a net_quit () or net_wait () call has failed,
+ allow the user to break the connection with the target.
+ We can't simply error () out of this loop, since the
+ data structures representing the state of the inferior
+ are in an inconsistent state. */
+
+ if (quit_failed || net_wait (&rdbEvent) == -1)
+ {
+ terminal_ours ();
+ if (query ("Can't %s. Disconnect from target system? ",
+ (quit_failed) ? "suspend remote task"
+ : "get status of remote task"))
+ {
+ target_mourn_inferior();
+ error ("Use the \"target\" command to reconnect.");
+ }
+ else
+ {
+ terminal_inferior ();
+ continue;
+ }
+ }
+
+ pid = rdbEvent.taskId;
+ if (pid == 0)
+ {
+ sleep_ms (200); /* FIXME Don't kill the network too badly */
+ }
+ else if (pid != inferior_pid)
+ fatal ("Bad pid for debugged task: %s\n",
+ local_hex_string((unsigned long) pid));
+ } while (pid == 0);
+
+ /* The mostly likely kind. */
+ status->kind = TARGET_WAITKIND_STOPPED;
+
+ switch (rdbEvent.eventType)
+ {
+ case EVENT_EXIT:
+ status->kind = TARGET_WAITKIND_EXITED;
+ /* FIXME is it possible to distinguish between a
+ normal vs abnormal exit in VxWorks? */
+ status->value.integer = 0;
+ break;
+
+ case EVENT_START:
+ /* Task was just started. */
+ status->value.sig = TARGET_SIGNAL_TRAP;
+ break;
+
+ case EVENT_STOP:
+ status->value.sig = TARGET_SIGNAL_TRAP;
+ /* XXX was it stopped by a signal? act accordingly */
+ break;
+
+ case EVENT_BREAK: /* Breakpoint was hit. */
+ status->value.sig = TARGET_SIGNAL_TRAP;
+ break;
+
+ case EVENT_SUSPEND: /* Task was suspended, probably by ^C. */
+ status->value.sig = TARGET_SIGNAL_INT;
+ break;
+
+ case EVENT_BUS_ERR: /* Task made evil nasty reference. */
+ status->value.sig = TARGET_SIGNAL_BUS;
+ break;
+
+ case EVENT_ZERO_DIV: /* Division by zero */
+ status->value.sig = TARGET_SIGNAL_FPE;
+ break;
+
+ case EVENT_SIGNAL:
+#ifdef I80960
+ status->value.sig = i960_fault_to_signal (rdbEvent.sigType);
+#else
+ /* Back in the old days, before enum target_signal, this code used
+ to add NSIG to the signal number and claim that PRINT_RANDOM_SIGNAL
+ would take care of it. But PRINT_RANDOM_SIGNAL has never been
+ defined except on the i960, so I don't really know what we are
+ supposed to do on other architectures. */
+ status->value.sig = TARGET_SIGNAL_UNKNOWN;
+#endif
+ break;
+ } /* switch */
+ return pid;
+}
+
+static int
+symbol_stub (arg)
+ char *arg;
+{
+ symbol_file_command (arg, 0);
+ return 1;
+}
+
+static int
+add_symbol_stub (arg)
+ char *arg;
+{
+ struct ldfile *pLoadFile = (struct ldfile *)arg;
+
+ printf_unfiltered("\t%s: ", pLoadFile->name);
+ vx_add_symbols (pLoadFile->name, 0, pLoadFile->txt_addr,
+ pLoadFile->data_addr, pLoadFile->bss_addr);
+ printf_unfiltered ("ok\n");
+ return 1;
+}
+/* Target command for VxWorks target systems.
+
+ Used in vxgdb. Takes the name of a remote target machine
+ running vxWorks and connects to it to initialize remote network
+ debugging. */
+
+static void
+vx_open (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ extern int close ();
+ char *bootFile;
+ extern char *source_path;
+ struct ldtabl loadTable;
+ struct ldfile *pLoadFile;
+ int i;
+ extern CLIENT *pClient;
+ int symbols_added = 0;
+
+ if (!args)
+ error_no_arg ("target machine name");
+
+ target_preopen (from_tty);
+
+ unpush_target (&vx_ops);
+ printf_unfiltered ("Attaching remote machine across net...\n");
+ gdb_flush (gdb_stdout);
+
+ /* Allow the user to kill the connect attempt by typing ^C.
+ Wait until the call to target_has_fp () completes before
+ disallowing an immediate quit, since even if net_connect ()
+ is successful, the remote debug server might be hung. */
+
+ immediate_quit++;
+
+ net_connect (args);
+ target_has_fp = net_check_for_fp ();
+ printf_filtered ("Connected to %s.\n", args);
+
+ immediate_quit--;
+
+ push_target (&vx_ops);
+
+ /* Save a copy of the target host's name. */
+ vx_host = savestring (args, strlen (args));
+
+ /* Find out the name of the file from which the target was booted
+ and load its symbol table. */
+
+ printf_filtered ("Looking in Unix path for all loaded modules:\n");
+ bootFile = NULL;
+ if (!net_get_boot_file (&bootFile))
+ {
+ if (*bootFile)
+ {
+ printf_filtered ("\t%s: ", bootFile);
+ /* This assumes that the kernel is never relocated. Hope that is an
+ accurate assumption. */
+ if (catch_errors
+ (symbol_stub,
+ bootFile,
+ "Error while reading symbols from boot file:\n",
+ RETURN_MASK_ALL))
+ puts_filtered ("ok\n");
+ }
+ else if (from_tty)
+ printf_unfiltered ("VxWorks kernel symbols not loaded.\n");
+ }
+ else
+ error ("Can't retrieve boot file name from target machine.");
+
+ clnt_freeres (pClient, xdr_wrapstring, &bootFile);
+
+ if (net_get_symbols (&loadTable) != 0)
+ error ("Can't read loaded modules from target machine");
+
+ i = 0-1;
+ while (++i < loadTable.tbl_size)
+ {
+ QUIT; /* FIXME, avoids clnt_freeres below: mem leak */
+ pLoadFile = &loadTable.tbl_ent [i];
+#ifdef WRS_ORIG
+ {
+ register int desc;
+ struct cleanup *old_chain;
+ char *fullname = NULL;
+
+ desc = openp (source_path, 0, pLoadFile->name, O_RDONLY, 0, &fullname);
+ if (desc < 0)
+ perror_with_name (pLoadFile->name);
+ old_chain = make_cleanup (close, desc);
+ add_file_at_addr (fullname, desc, pLoadFile->txt_addr, pLoadFile->data_addr,
+ pLoadFile->bss_addr);
+ do_cleanups (old_chain);
+ }
+#else
+ /* FIXME: Is there something better to search than the PATH? (probably
+ not the source path, since source might be in different directories
+ than objects. */
+
+ if (catch_errors (add_symbol_stub, (char *)pLoadFile, (char *)0,
+ RETURN_MASK_ALL))
+ symbols_added = 1;
+#endif
+ }
+ printf_filtered ("Done.\n");
+
+ clnt_freeres (pClient, xdr_ldtabl, &loadTable);
+
+ /* Getting new symbols may change our opinion about what is
+ frameless. */
+ if (symbols_added)
+ reinit_frame_cache ();
+}
+
+/* Takes a task started up outside of gdb and ``attaches'' to it.
+ This stops it cold in its tracks and allows us to start tracing it. */
+
+static void
+vx_attach (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ unsigned long pid;
+ char *cptr = 0;
+ Rptrace ptrace_in;
+ Ptrace_return ptrace_out;
+ int status;
+
+ if (!args)
+ error_no_arg ("process-id to attach");
+
+ pid = strtoul (args, &cptr, 0);
+ if ((cptr == args) || (*cptr != '\0'))
+ error ("Invalid process-id -- give a single number in decimal or 0xhex");
+
+ if (from_tty)
+ printf_unfiltered ("Attaching pid %s.\n",
+ local_hex_string((unsigned long) pid));
+
+ memset ((char *)&ptrace_in, '\0', sizeof (ptrace_in));
+ memset ((char *)&ptrace_out, '\0', sizeof (ptrace_out));
+ ptrace_in.pid = pid;
+
+ status = net_ptrace_clnt_call (PTRACE_ATTACH, &ptrace_in, &ptrace_out);
+ if (status == -1)
+ error (rpcerr);
+ if (ptrace_out.status == -1)
+ {
+ errno = ptrace_out.errno_num;
+ perror_with_name ("Attaching remote process");
+ }
+
+ /* It worked... */
+
+ inferior_pid = pid;
+ push_target (&vx_run_ops);
+
+ if (vx_running)
+ free (vx_running);
+ vx_running = 0;
+}
+
+/* detach_command --
+ takes a program previously attached to and detaches it.
+ The program resumes execution and will no longer stop
+ on signals, etc. We better not have left any breakpoints
+ in the program or it'll die when it hits one. For this
+ to work, it may be necessary for the process to have been
+ previously attached. It *might* work if the program was
+ started via the normal ptrace (PTRACE_TRACEME). */
+
+static void
+vx_detach (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ Rptrace ptrace_in;
+ Ptrace_return ptrace_out;
+ int signal = 0;
+ int status;
+
+ if (args)
+ error ("Argument given to VxWorks \"detach\".");
+
+ if (from_tty)
+ printf_unfiltered ("Detaching pid %s.\n",
+ local_hex_string((unsigned long) inferior_pid));
+
+ if (args) /* FIXME, should be possible to leave suspended */
+ signal = atoi (args);
+
+ memset ((char *)&ptrace_in, '\0', sizeof (ptrace_in));
+ memset ((char *)&ptrace_out, '\0', sizeof (ptrace_out));
+ ptrace_in.pid = inferior_pid;
+
+ status = net_ptrace_clnt_call (PTRACE_DETACH, &ptrace_in, &ptrace_out);
+ if (status == -1)
+ error (rpcerr);
+ if (ptrace_out.status == -1)
+ {
+ errno = ptrace_out.errno_num;
+ perror_with_name ("Detaching VxWorks process");
+ }
+
+ inferior_pid = 0;
+ pop_target (); /* go back to non-executing VxWorks connection */
+}
+
+/* vx_kill -- takes a running task and wipes it out. */
+
+static void
+vx_kill ()
+{
+ Rptrace ptrace_in;
+ Ptrace_return ptrace_out;
+ int status;
+
+ printf_unfiltered ("Killing pid %s.\n", local_hex_string((unsigned long) inferior_pid));
+
+ memset ((char *)&ptrace_in, '\0', sizeof (ptrace_in));
+ memset ((char *)&ptrace_out, '\0', sizeof (ptrace_out));
+ ptrace_in.pid = inferior_pid;
+
+ status = net_ptrace_clnt_call (PTRACE_KILL, &ptrace_in, &ptrace_out);
+ if (status == -1)
+ warning (rpcerr);
+ else if (ptrace_out.status == -1)
+ {
+ errno = ptrace_out.errno_num;
+ perror_with_name ("Killing VxWorks process");
+ }
+
+ /* If it gives good status, the process is *gone*, no events remain.
+ If the kill failed, assume the process is gone anyhow. */
+ inferior_pid = 0;
+ pop_target (); /* go back to non-executing VxWorks connection */
+}
+
+/* Clean up from the VxWorks process target as it goes away. */
+
+static void
+vx_proc_close (quitting)
+ int quitting;
+{
+ inferior_pid = 0; /* No longer have a process. */
+ if (vx_running)
+ free (vx_running);
+ vx_running = 0;
+}
+
+/* Make an RPC call to the VxWorks target.
+ Returns RPC status. */
+
+static enum clnt_stat
+net_clnt_call (procNum, inProc, in, outProc, out)
+ enum ptracereq procNum;
+ xdrproc_t inProc;
+ char *in;
+ xdrproc_t outProc;
+ char *out;
+{
+ enum clnt_stat status;
+
+ status = clnt_call (pClient, procNum, inProc, in, outProc, out, rpcTimeout);
+
+ if (status != RPC_SUCCESS)
+ clnt_perrno (status);
+
+ return status;
+}
+
+/* Clean up before losing control. */
+
+static void
+vx_close (quitting)
+ int quitting;
+{
+ if (pClient)
+ clnt_destroy (pClient); /* The net connection */
+ pClient = 0;
+
+ if (vx_host)
+ free (vx_host); /* The hostname */
+ vx_host = 0;
+}
+
+/* A vxprocess target should be started via "run" not "target". */
+/*ARGSUSED*/
+static void
+vx_proc_open (name, from_tty)
+ char *name;
+ int from_tty;
+{
+ error ("Use the \"run\" command to start a VxWorks process.");
+}
+
+static void
+init_vx_ops ()
+{
+ vx_ops.to_shortname = "vxworks";
+ vx_ops.to_longname = "VxWorks target memory via RPC over TCP/IP";
+ vx_ops.to_doc = "Use VxWorks target memory. \n\
+Specify the name of the machine to connect to.";
+ vx_ops.to_open = vx_open;
+ vx_ops.to_close = vx_close;
+ vx_ops.to_attach = vx_attach;
+ vx_ops.to_xfer_memory = vx_xfer_memory;
+ vx_ops.to_files_info = vx_files_info;
+ vx_ops.to_load = vx_load_command;
+ vx_ops.to_lookup_symbol = vx_lookup_symbol;
+ vx_ops.to_create_inferior = vx_create_inferior;
+ vx_ops.to_stratum = core_stratum;
+ vx_ops.to_has_all_memory = 1;
+ vx_ops.to_has_memory = 1;
+ vx_ops.to_magic = OPS_MAGIC; /* Always the last thing */
+};
+
+static void
+init_vx_run_ops ()
+{
+ vx_run_ops.to_shortname = "vxprocess";
+ vx_run_ops.to_longname = "VxWorks process";
+ vx_run_ops.to_doc = "VxWorks process; started by the \"run\" command.";
+ vx_run_ops.to_open = vx_proc_open;
+ vx_run_ops.to_close = vx_proc_close;
+ vx_run_ops.to_detach = vx_detach;
+ vx_run_ops.to_resume = vx_resume;
+ vx_run_ops.to_wait = vx_wait;
+ vx_run_ops.to_fetch_registers = vx_read_register;
+ vx_run_ops.to_store_registers = vx_write_register;
+ vx_run_ops.to_prepare_to_store = vx_prepare_to_store;
+ vx_run_ops.to_xfer_memory = vx_xfer_memory;
+ vx_run_ops.to_files_info = vx_run_files_info;
+ vx_run_ops.to_insert_breakpoint = vx_insert_breakpoint;
+ vx_run_ops.to_remove_breakpoint = vx_remove_breakpoint;
+ vx_run_ops.to_kill = vx_kill;
+ vx_run_ops.to_load = vx_load_command;
+ vx_run_ops.to_lookup_symbol = vx_lookup_symbol;
+ vx_run_ops.to_mourn_inferior = vx_mourn_inferior ;
+ vx_run_ops.to_stratum = process_stratum;
+ vx_run_ops.to_has_memory = 1;
+ vx_run_ops.to_has_stack = 1;
+ vx_run_ops.to_has_registers = 1;
+ vx_run_ops.to_has_execution = 1;
+ vx_run_ops.to_magic = OPS_MAGIC;
+}
+
+void
+_initialize_vx ()
+{
+ init_vx_ops ();
+ add_target (&vx_ops);
+ init_vx_run_ops ();
+ add_target (&vx_run_ops);
+
+ add_show_from_set
+ (add_set_cmd ("vxworks-timeout", class_support, var_uinteger,
+ (char *) &rpcTimeout.tv_sec,
+ "Set seconds to wait for rpc calls to return.\n\
+Set the number of seconds to wait for rpc calls to return.", &setlist),
+ &showlist);
+}
diff --git a/gdb/remote-vx29k.c b/gdb/remote-vx29k.c
new file mode 100644
index 00000000000..e6fc2c79495
--- /dev/null
+++ b/gdb/remote-vx29k.c
@@ -0,0 +1,188 @@
+/* Am29k-dependent portions of the RPC protocol
+ used with a VxWorks target
+
+Contributed by Wind River Systems.
+
+This file is part of GDB.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include <stdio.h>
+#include "defs.h"
+
+#include "vx-share/regPacket.h"
+#include "frame.h"
+#include "inferior.h"
+#include "wait.h"
+#include "target.h"
+#include "gdbcore.h"
+#include "command.h"
+#include "symtab.h"
+#include "symfile.h" /* for struct complaint */
+
+#include "gdb_string.h"
+#include <errno.h>
+#include <signal.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+
+#ifdef _AIX /* IBM claims "void *malloc()" not char * */
+#define malloc bogon_malloc
+#endif
+
+#include <rpc/rpc.h>
+#include <sys/time.h> /* UTek's <rpc/rpc.h> doesn't #incl this */
+#include <netdb.h>
+#include "vx-share/ptrace.h"
+#include "vx-share/xdr_ptrace.h"
+#include "vx-share/xdr_ld.h"
+#include "vx-share/xdr_rdb.h"
+#include "vx-share/dbgRpcLib.h"
+
+/* get rid of value.h if possible */
+#include <value.h>
+#include <symtab.h>
+
+/* Flag set if target has fpu */
+
+extern int target_has_fp;
+
+/* Generic register read/write routines in remote-vx.c. */
+
+extern void net_read_registers ();
+extern void net_write_registers ();
+
+/* Read a register or registers from the VxWorks target.
+ REGNO is the register to read, or -1 for all; currently,
+ it is ignored. FIXME look at regno to improve efficiency. */
+
+void
+vx_read_register (regno)
+ int regno;
+{
+ char am29k_greg_packet[AM29K_GREG_PLEN];
+ char am29k_fpreg_packet[AM29K_FPREG_PLEN];
+
+ /* Get general-purpose registers. When copying values into
+ registers [], don't assume that a location in registers []
+ is properly aligned for the target data type. */
+
+ net_read_registers (am29k_greg_packet, AM29K_GREG_PLEN, PTRACE_GETREGS);
+
+ /* Now copy the register values into registers[].
+ Note that this code depends on the ordering of the REGNUMs
+ as defined in "tm-29k.h". */
+
+ bcopy (&am29k_greg_packet[AM29K_R_GR96],
+ &registers[REGISTER_BYTE (GR96_REGNUM)], 160 * AM29K_GREG_SIZE);
+ bcopy (&am29k_greg_packet[AM29K_R_VAB],
+ &registers[REGISTER_BYTE (VAB_REGNUM)], 15 * AM29K_GREG_SIZE);
+ registers[REGISTER_BYTE (INTE_REGNUM)] = am29k_greg_packet[AM29K_R_INTE];
+ bcopy (&am29k_greg_packet[AM29K_R_RSP],
+ &registers[REGISTER_BYTE (GR1_REGNUM)], 5 * AM29K_GREG_SIZE);
+
+ /* PAD For now, don't care about exop register */
+
+ memset (&registers[REGISTER_BYTE (EXO_REGNUM)], '\0', AM29K_GREG_SIZE);
+
+ /* If the target has floating point registers, fetch them.
+ Otherwise, zero the floating point register values in
+ registers[] for good measure, even though we might not
+ need to. */
+
+ if (target_has_fp)
+ {
+ net_read_registers (am29k_fpreg_packet, AM29K_FPREG_PLEN,
+ PTRACE_GETFPREGS);
+ registers[REGISTER_BYTE (FPE_REGNUM)] = am29k_fpreg_packet[AM29K_R_FPE];
+ registers[REGISTER_BYTE (FPS_REGNUM)] = am29k_fpreg_packet[AM29K_R_FPS];
+
+ /* PAD For now, don't care about registers (?) AI0 to q */
+
+ memset (&registers[REGISTER_BYTE (161)], '\0', 21 * AM29K_FPREG_SIZE);
+ }
+ else
+ {
+ memset (&registers[REGISTER_BYTE (FPE_REGNUM)], '\0', AM29K_FPREG_SIZE);
+ memset (&registers[REGISTER_BYTE (FPS_REGNUM)], '\0', AM29K_FPREG_SIZE);
+
+ /* PAD For now, don't care about registers (?) AI0 to q */
+
+ memset (&registers[REGISTER_BYTE (161)], '\0', 21 * AM29K_FPREG_SIZE);
+ }
+
+ /* Mark the register cache valid. */
+
+ registers_fetched ();
+}
+
+/* Store a register or registers into the VxWorks target.
+ REGNO is the register to store, or -1 for all; currently,
+ it is ignored. FIXME look at regno to improve efficiency. */
+
+void
+vx_write_register (regno)
+ int regno;
+{
+ char am29k_greg_packet[AM29K_GREG_PLEN];
+ char am29k_fpreg_packet[AM29K_FPREG_PLEN];
+
+ /* Store general purpose registers. When copying values from
+ registers [], don't assume that a location in registers []
+ is properly aligned for the target data type. */
+
+ bcopy (&registers[REGISTER_BYTE (GR96_REGNUM)],
+ &am29k_greg_packet[AM29K_R_GR96], 160 * AM29K_GREG_SIZE);
+ bcopy (&registers[REGISTER_BYTE (VAB_REGNUM)],
+ &am29k_greg_packet[AM29K_R_VAB], 15 * AM29K_GREG_SIZE);
+ am29k_greg_packet[AM29K_R_INTE] = registers[REGISTER_BYTE (INTE_REGNUM)];
+ bcopy (&registers[REGISTER_BYTE (GR1_REGNUM)],
+ &am29k_greg_packet[AM29K_R_RSP], 5 * AM29K_GREG_SIZE);
+
+ net_write_registers (am29k_greg_packet, AM29K_GREG_PLEN, PTRACE_SETREGS);
+
+ /* Store floating point registers if the target has them. */
+
+ if (target_has_fp)
+ {
+ am29k_fpreg_packet[AM29K_R_FPE] = registers[REGISTER_BYTE (FPE_REGNUM)];
+ am29k_fpreg_packet[AM29K_R_FPS] = registers[REGISTER_BYTE (FPS_REGNUM)];
+
+ net_write_registers (am29k_fpreg_packet, AM29K_FPREG_PLEN,
+ PTRACE_SETFPREGS);
+ }
+}
+
+/* VxWorks zeroes fp when the task is initialized; we use this
+ to terminate the frame chain. Chain means here the nominal address of
+ a frame, that is, the return address (lr0) address in the stack. To
+ obtain the frame pointer (lr1) contents, we must add 4 bytes.
+ Note : may be we should modify init_frame_info() to get the frame pointer
+ and store it into the frame_info struct rather than reading its
+ contents when FRAME_CHAIN_VALID is invoked. */
+
+int
+vx29k_frame_chain_valid (chain, thisframe)
+ CORE_ADDR chain;
+ struct frame_info *thisframe; /* not used here */
+{
+ int fp_contents;
+
+ read_memory ((CORE_ADDR)(chain + 4), (char *) &fp_contents, 4);
+ return (fp_contents != 0);
+}
+
diff --git a/gdb/remote-vx68.c b/gdb/remote-vx68.c
new file mode 100644
index 00000000000..c6ceda18e05
--- /dev/null
+++ b/gdb/remote-vx68.c
@@ -0,0 +1,158 @@
+/* 68k-dependent portions of the RPC protocol
+ used with a VxWorks target
+
+Contributed by Wind River Systems.
+
+This file is part of GDB.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include <stdio.h>
+#include "defs.h"
+
+#include "vx-share/regPacket.h"
+#include "frame.h"
+#include "inferior.h"
+#include "wait.h"
+#include "target.h"
+#include "gdbcore.h"
+#include "command.h"
+#include "symtab.h"
+#include "symfile.h" /* for struct complaint */
+
+#include "gdb_string.h"
+#include <errno.h>
+#include <signal.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+
+#ifdef _AIX /* IBM claims "void *malloc()" not char * */
+#define malloc bogon_malloc
+#endif
+
+#include <rpc/rpc.h>
+
+#ifdef _AIX
+#undef malloc
+#endif
+
+#include <sys/time.h> /* UTek's <rpc/rpc.h> doesn't #incl this */
+#include <netdb.h>
+#include "vx-share/ptrace.h"
+#include "vx-share/xdr_ptrace.h"
+#include "vx-share/xdr_ld.h"
+#include "vx-share/xdr_rdb.h"
+#include "vx-share/dbgRpcLib.h"
+
+/* get rid of value.h if possible */
+#include <value.h>
+#include <symtab.h>
+
+/* Flag set if target has fpu */
+
+extern int target_has_fp;
+
+/* Generic register read/write routines in remote-vx.c. */
+
+extern void net_read_registers ();
+extern void net_write_registers ();
+
+/* Read a register or registers from the VxWorks target.
+ REGNO is the register to read, or -1 for all; currently,
+ it is ignored. FIXME look at regno to improve efficiency. */
+
+void
+vx_read_register (regno)
+ int regno;
+{
+ char mc68k_greg_packet[MC68K_GREG_PLEN];
+ char mc68k_fpreg_packet[MC68K_FPREG_PLEN];
+
+ /* Get general-purpose registers. */
+
+ net_read_registers (mc68k_greg_packet, MC68K_GREG_PLEN, PTRACE_GETREGS);
+
+ bcopy (&mc68k_greg_packet[MC68K_R_D0], registers, 16 * MC68K_GREG_SIZE);
+ bcopy (&mc68k_greg_packet[MC68K_R_SR], &registers[REGISTER_BYTE (PS_REGNUM)],
+ MC68K_GREG_SIZE);
+ bcopy (&mc68k_greg_packet[MC68K_R_PC], &registers[REGISTER_BYTE (PC_REGNUM)],
+ MC68K_GREG_SIZE);
+
+ /* Get floating-point registers, if the target system has them.
+ Otherwise, zero them. */
+
+ if (target_has_fp)
+ {
+ net_read_registers (mc68k_fpreg_packet, MC68K_FPREG_PLEN,
+ PTRACE_GETFPREGS);
+
+ bcopy (&mc68k_fpreg_packet[MC68K_R_FP0],
+ &registers[REGISTER_BYTE (FP0_REGNUM)],
+ MC68K_FPREG_SIZE * 8);
+ bcopy (&mc68k_fpreg_packet[MC68K_R_FPCR],
+ &registers[REGISTER_BYTE (FPC_REGNUM)],
+ MC68K_FPREG_PLEN - (MC68K_FPREG_SIZE * 8));
+ }
+ else
+ {
+ bzero (&registers[REGISTER_BYTE (FP0_REGNUM)],
+ MC68K_FPREG_SIZE * 8);
+ bzero (&registers[REGISTER_BYTE (FPC_REGNUM)],
+ MC68K_FPREG_PLEN - (MC68K_FPREG_SIZE * 8));
+ }
+
+ /* Mark the register cache valid. */
+
+ registers_fetched ();
+}
+
+/* Store a register or registers into the VxWorks target.
+ REGNO is the register to store, or -1 for all; currently,
+ it is ignored. FIXME look at regno to improve efficiency. */
+
+void
+vx_write_register (regno)
+ int regno;
+{
+ char mc68k_greg_packet[MC68K_GREG_PLEN];
+ char mc68k_fpreg_packet[MC68K_FPREG_PLEN];
+
+ /* Store general-purpose registers. */
+
+ bcopy (registers, &mc68k_greg_packet[MC68K_R_D0], 16 * MC68K_GREG_SIZE);
+ bcopy (&registers[REGISTER_BYTE (PS_REGNUM)],
+ &mc68k_greg_packet[MC68K_R_SR], MC68K_GREG_SIZE);
+ bcopy (&registers[REGISTER_BYTE (PC_REGNUM)],
+ &mc68k_greg_packet[MC68K_R_PC], MC68K_GREG_SIZE);
+
+ net_write_registers (mc68k_greg_packet, MC68K_GREG_PLEN, PTRACE_SETREGS);
+
+ /* Store floating point registers if the target has them. */
+
+ if (target_has_fp)
+ {
+ bcopy (&registers[REGISTER_BYTE (FP0_REGNUM)],
+ &mc68k_fpreg_packet[MC68K_R_FP0],
+ MC68K_FPREG_SIZE * 8);
+ bcopy (&registers[REGISTER_BYTE (FPC_REGNUM)],
+ &mc68k_fpreg_packet[MC68K_R_FPCR],
+ MC68K_FPREG_PLEN - (MC68K_FPREG_SIZE * 8));
+
+ net_write_registers (mc68k_fpreg_packet, MC68K_FPREG_PLEN,
+ PTRACE_SETFPREGS);
+ }
+}
diff --git a/gdb/remote-vx960.c b/gdb/remote-vx960.c
new file mode 100644
index 00000000000..bb4fbee6167
--- /dev/null
+++ b/gdb/remote-vx960.c
@@ -0,0 +1,163 @@
+/* i80960-dependent portions of the RPC protocol
+ used with a VxWorks target
+
+Contributed by Wind River Systems.
+
+This file is part of GDB.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include <stdio.h>
+#include "defs.h"
+
+#include "vx-share/regPacket.h"
+#include "frame.h"
+#include "inferior.h"
+#include "wait.h"
+#include "target.h"
+#include "gdbcore.h"
+#include "command.h"
+#include "symtab.h"
+#include "symfile.h" /* for struct complaint */
+
+#include "gdb_string.h"
+#include <errno.h>
+#include <signal.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+
+#ifdef _AIX /* IBM claims "void *malloc()" not char * */
+#define malloc bogon_malloc
+#endif
+
+#include <rpc/rpc.h>
+#include <sys/time.h> /* UTek's <rpc/rpc.h> doesn't #incl this */
+#include <netdb.h>
+#include "vx-share/ptrace.h"
+#include "vx-share/xdr_ptrace.h"
+#include "vx-share/xdr_ld.h"
+#include "vx-share/xdr_rdb.h"
+#include "vx-share/dbgRpcLib.h"
+
+/* get rid of value.h if possible */
+#include <value.h>
+#include <symtab.h>
+
+/* Flag set if target has fpu */
+
+extern int target_has_fp;
+
+/* 960 floating point format descriptor, from "i960-tdep.c." */
+
+extern struct ext_format ext_format_i960;
+
+/* Generic register read/write routines in remote-vx.c. */
+
+extern void net_read_registers ();
+extern void net_write_registers ();
+
+/* Read a register or registers from the VxWorks target.
+ REGNO is the register to read, or -1 for all; currently,
+ it is ignored. FIXME look at regno to improve efficiency. */
+
+void
+vx_read_register (regno)
+ int regno;
+{
+ char i960_greg_packet[I960_GREG_PLEN];
+ char i960_fpreg_packet[I960_FPREG_PLEN];
+
+ /* Get general-purpose registers. When copying values into
+ registers [], don't assume that a location in registers []
+ is properly aligned for the target data type. */
+
+ net_read_registers (i960_greg_packet, I960_GREG_PLEN, PTRACE_GETREGS);
+
+ bcopy (&i960_greg_packet[I960_R_R0],
+ &registers[REGISTER_BYTE (R0_REGNUM)], 16 * I960_GREG_SIZE);
+ bcopy (&i960_greg_packet[I960_R_G0],
+ &registers[REGISTER_BYTE (G0_REGNUM)], 16 * I960_GREG_SIZE);
+ bcopy (&i960_greg_packet[I960_R_PCW],
+ &registers[REGISTER_BYTE (PCW_REGNUM)], sizeof (int));
+ bcopy (&i960_greg_packet[I960_R_ACW],
+ &registers[REGISTER_BYTE (ACW_REGNUM)], sizeof (int));
+ bcopy (&i960_greg_packet[I960_R_TCW],
+ &registers[REGISTER_BYTE (TCW_REGNUM)], sizeof (int));
+
+ /* If the target has floating point registers, fetch them.
+ Otherwise, zero the floating point register values in
+ registers[] for good measure, even though we might not
+ need to. */
+
+ if (target_has_fp)
+ {
+ net_read_registers (i960_fpreg_packet, I960_FPREG_PLEN,
+ PTRACE_GETFPREGS);
+ bcopy (&i960_fpreg_packet[I960_R_FP0],
+ &registers[REGISTER_BYTE (FP0_REGNUM)],
+ REGISTER_RAW_SIZE (FP0_REGNUM) * 4);
+ }
+ else
+ bzero (&registers[REGISTER_BYTE (FP0_REGNUM)],
+ REGISTER_RAW_SIZE (FP0_REGNUM) * 4);
+
+ /* Mark the register cache valid. */
+
+ registers_fetched ();
+}
+
+/* Store a register or registers into the VxWorks target.
+ REGNO is the register to store, or -1 for all; currently,
+ it is ignored. FIXME look at regno to improve efficiency. */
+
+void
+vx_write_register (regno)
+ int regno;
+{
+ char i960_greg_packet[I960_GREG_PLEN];
+ char i960_fpreg_packet[I960_FPREG_PLEN];
+
+ /* Store floating-point registers. When copying values from
+ registers [], don't assume that a location in registers []
+ is properly aligned for the target data type. */
+
+ bcopy (&registers[REGISTER_BYTE (R0_REGNUM)],
+ &i960_greg_packet[I960_R_R0], 16 * I960_GREG_SIZE);
+ bcopy (&registers[REGISTER_BYTE (G0_REGNUM)],
+ &i960_greg_packet[I960_R_G0], 16 * I960_GREG_SIZE);
+ bcopy (&registers[REGISTER_BYTE (PCW_REGNUM)],
+ &i960_greg_packet[I960_R_PCW], sizeof (int));
+ bcopy (&registers[REGISTER_BYTE (ACW_REGNUM)],
+ &i960_greg_packet[I960_R_ACW], sizeof (int));
+ bcopy (&registers[REGISTER_BYTE (TCW_REGNUM)],
+ &i960_greg_packet[I960_R_TCW], sizeof (int));
+
+ net_write_registers (i960_greg_packet, I960_GREG_PLEN, PTRACE_SETREGS);
+
+ /* Store floating point registers if the target has them. */
+
+ if (target_has_fp)
+ {
+ bcopy (&registers[REGISTER_BYTE (FP0_REGNUM)],
+ &i960_fpreg_packet[I960_R_FP0],
+ REGISTER_RAW_SIZE (FP0_REGNUM) * 4);
+
+ net_write_registers (i960_fpreg_packet, I960_FPREG_PLEN,
+ PTRACE_SETFPREGS);
+ }
+}
+
diff --git a/gdb/remote-vxmips.c b/gdb/remote-vxmips.c
new file mode 100644
index 00000000000..c65ac015ead
--- /dev/null
+++ b/gdb/remote-vxmips.c
@@ -0,0 +1,201 @@
+/* MIPS-dependent portions of the RPC protocol
+ used with a VxWorks target
+
+Contributed by Wind River Systems.
+
+This file is part of GDB.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include <stdio.h>
+#include "defs.h"
+
+#include "vx-share/regPacket.h"
+#include "frame.h"
+#include "inferior.h"
+#include "wait.h"
+#include "target.h"
+#include "gdbcore.h"
+#include "command.h"
+#include "symtab.h"
+#include "symfile.h" /* for struct complaint */
+
+#include "gdb_string.h"
+#include <errno.h>
+#include <signal.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <rpc/rpc.h>
+#include <sys/time.h> /* UTek's <rpc/rpc.h> doesn't #incl this */
+#include <netdb.h>
+#include "vx-share/ptrace.h"
+#include "vx-share/xdr_ptrace.h"
+#include "vx-share/xdr_ld.h"
+#include "vx-share/xdr_rdb.h"
+#include "vx-share/dbgRpcLib.h"
+
+/* get rid of value.h if possible */
+#include <value.h>
+#include <symtab.h>
+
+/* Flag set if target has fpu */
+
+extern int target_has_fp;
+
+/* Generic register read/write routines in remote-vx.c. */
+
+extern void net_read_registers ();
+extern void net_write_registers ();
+
+/* Read a register or registers from the VxWorks target.
+ REGNO is the register to read, or -1 for all; currently,
+ it is ignored. FIXME look at regno to improve efficiency. */
+
+void
+vx_read_register (regno)
+ int regno;
+{
+ char mips_greg_packet[MIPS_GREG_PLEN];
+ char mips_fpreg_packet[MIPS_FPREG_PLEN];
+
+ /* Get general-purpose registers. */
+
+ net_read_registers (mips_greg_packet, MIPS_GREG_PLEN, PTRACE_GETREGS);
+
+ /* this code copies the registers obtained by RPC
+ stored in a structure(s) like this :
+
+ Register(s) Offset(s)
+ gp 0-31 0x00
+ hi 0x80
+ lo 0x84
+ sr 0x88
+ pc 0x8c
+
+ into a stucture like this:
+
+ 0x00 GP 0-31
+ 0x80 SR
+ 0x84 LO
+ 0x88 HI
+ 0x8C BAD --- Not available currently
+ 0x90 CAUSE --- Not available currently
+ 0x94 PC
+ 0x98 FP 0-31
+ 0x118 FCSR
+ 0x11C FIR --- Not available currently
+ 0x120 FP --- Not available currently
+
+ structure is 0x124 (292) bytes in length */
+
+ /* Copy the general registers. */
+
+ bcopy (&mips_greg_packet[MIPS_R_GP0], &registers[0], 32 * MIPS_GREG_SIZE);
+
+ /* Copy SR, LO, HI, and PC. */
+
+ bcopy (&mips_greg_packet[MIPS_R_SR],
+ &registers[REGISTER_BYTE (PS_REGNUM)], MIPS_GREG_SIZE);
+ bcopy (&mips_greg_packet[MIPS_R_LO],
+ &registers[REGISTER_BYTE (LO_REGNUM)], MIPS_GREG_SIZE);
+ bcopy (&mips_greg_packet[MIPS_R_HI],
+ &registers[REGISTER_BYTE (HI_REGNUM)], MIPS_GREG_SIZE);
+ bcopy (&mips_greg_packet[MIPS_R_PC],
+ &registers[REGISTER_BYTE (PC_REGNUM)], MIPS_GREG_SIZE);
+
+ /* If the target has floating point registers, fetch them.
+ Otherwise, zero the floating point register values in
+ registers[] for good measure, even though we might not
+ need to. */
+
+ if (target_has_fp)
+ {
+ net_read_registers (mips_fpreg_packet, MIPS_FPREG_PLEN,
+ PTRACE_GETFPREGS);
+
+ /* Copy the floating point registers. */
+
+ bcopy (&mips_fpreg_packet[MIPS_R_FP0],
+ &registers[REGISTER_BYTE (FP0_REGNUM)],
+ REGISTER_RAW_SIZE (FP0_REGNUM) * 32);
+
+ /* Copy the floating point control/status register (fpcsr). */
+
+ bcopy (&mips_fpreg_packet[MIPS_R_FPCSR],
+ &registers[REGISTER_BYTE (FCRCS_REGNUM)],
+ REGISTER_RAW_SIZE (FCRCS_REGNUM));
+ }
+ else
+ {
+ bzero ((char *) &registers[REGISTER_BYTE (FP0_REGNUM)],
+ REGISTER_RAW_SIZE (FP0_REGNUM) * 32);
+ bzero ((char *) &registers[REGISTER_BYTE (FCRCS_REGNUM)],
+ REGISTER_RAW_SIZE (FCRCS_REGNUM));
+ }
+
+ /* Mark the register cache valid. */
+
+ registers_fetched ();
+}
+
+/* Store a register or registers into the VxWorks target.
+ REGNO is the register to store, or -1 for all; currently,
+ it is ignored. FIXME look at regno to improve efficiency. */
+
+vx_write_register (regno)
+ int regno;
+{
+ char mips_greg_packet[MIPS_GREG_PLEN];
+ char mips_fpreg_packet[MIPS_FPREG_PLEN];
+
+ /* Store general registers. */
+
+ bcopy (&registers[0], &mips_greg_packet[MIPS_R_GP0], 32 * MIPS_GREG_SIZE);
+
+ /* Copy SR, LO, HI, and PC. */
+
+ bcopy (&registers[REGISTER_BYTE (PS_REGNUM)],
+ &mips_greg_packet[MIPS_R_SR], MIPS_GREG_SIZE);
+ bcopy (&registers[REGISTER_BYTE (LO_REGNUM)],
+ &mips_greg_packet[MIPS_R_LO], MIPS_GREG_SIZE);
+ bcopy (&registers[REGISTER_BYTE (HI_REGNUM)],
+ &mips_greg_packet[MIPS_R_HI], MIPS_GREG_SIZE);
+ bcopy (&registers[REGISTER_BYTE (PC_REGNUM)],
+ &mips_greg_packet[MIPS_R_PC], MIPS_GREG_SIZE);
+
+ net_write_registers (mips_greg_packet, MIPS_GREG_PLEN, PTRACE_SETREGS);
+
+ /* Store floating point registers if the target has them. */
+
+ if (target_has_fp)
+ {
+ /* Copy the floating point data registers. */
+
+ bcopy (&registers[REGISTER_BYTE (FP0_REGNUM)],
+ &mips_fpreg_packet[MIPS_R_FP0],
+ REGISTER_RAW_SIZE (FP0_REGNUM) * 32);
+
+ /* Copy the floating point control/status register (fpcsr). */
+
+ bcopy (&registers[REGISTER_BYTE (FCRCS_REGNUM)],
+ &mips_fpreg_packet[MIPS_R_FPCSR],
+ REGISTER_RAW_SIZE (FCRCS_REGNUM));
+
+ net_write_registers (mips_fpreg_packet, MIPS_FPREG_PLEN,
+ PTRACE_SETFPREGS);
+ }
+}
diff --git a/gdb/remote-vxsparc.c b/gdb/remote-vxsparc.c
new file mode 100644
index 00000000000..068254240fa
--- /dev/null
+++ b/gdb/remote-vxsparc.c
@@ -0,0 +1,196 @@
+/* sparc-dependent portions of the RPC protocol
+ used with a VxWorks target
+
+Contributed by Wind River Systems.
+
+This file is part of GDB.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include <stdio.h>
+#include "defs.h"
+
+#include "vx-share/regPacket.h"
+#include "frame.h"
+#include "inferior.h"
+#include "wait.h"
+#include "target.h"
+#include "gdbcore.h"
+#include "command.h"
+#include "symtab.h"
+#include "symfile.h" /* for struct complaint */
+
+#include "gdb_string.h"
+#include <errno.h>
+#include <signal.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+
+#ifdef _AIX /* IBM claims "void *malloc()" not char * */
+#define malloc bogon_malloc
+#endif
+
+#include <rpc/rpc.h>
+#include <sys/time.h> /* UTek's <rpc/rpc.h> doesn't #incl this */
+#include <netdb.h>
+#include "vx-share/ptrace.h"
+#include "vx-share/xdr_ptrace.h"
+#include "vx-share/xdr_ld.h"
+#include "vx-share/xdr_rdb.h"
+#include "vx-share/dbgRpcLib.h"
+
+/* get rid of value.h if possible */
+#include <value.h>
+#include <symtab.h>
+
+/* Flag set if target has fpu */
+
+extern int target_has_fp;
+
+/* sparc floating point format descriptor, from "sparc-tdep.c." */
+
+extern struct ext_format ext_format_sparc;
+
+/* Generic register read/write routines in remote-vx.c. */
+
+extern void net_read_registers ();
+extern void net_write_registers ();
+
+/* Read a register or registers from the VxWorks target.
+ REGNO is the register to read, or -1 for all; currently,
+ it is ignored. FIXME look at regno to improve efficiency. */
+
+void
+vx_read_register (regno)
+ int regno;
+{
+ char sparc_greg_packet[SPARC_GREG_PLEN];
+ char sparc_fpreg_packet[SPARC_FPREG_PLEN];
+ CORE_ADDR sp;
+
+ /* Get general-purpose registers. When copying values into
+ registers [], don't assume that a location in registers []
+ is properly aligned for the target data type. */
+
+ net_read_registers (sparc_greg_packet, SPARC_GREG_PLEN, PTRACE_GETREGS);
+
+ /* Now copy the register values into registers[].
+ Note that this code depends on the ordering of the REGNUMs
+ as defined in "tm-sparc.h". */
+
+ bcopy (&sparc_greg_packet[SPARC_R_G0],
+ &registers[REGISTER_BYTE (G0_REGNUM)], 32 * SPARC_GREG_SIZE);
+ bcopy (&sparc_greg_packet[SPARC_R_Y],
+ &registers[REGISTER_BYTE (Y_REGNUM)], 6 * SPARC_GREG_SIZE);
+
+ /* Now write the local and in registers to the register window
+ spill area in the frame. VxWorks does not do this for the
+ active frame automatically; it greatly simplifies debugging
+ (FRAME_FIND_SAVED_REGS, in particular, depends on this). */
+
+ sp = extract_address (&registers[REGISTER_BYTE (SP_REGNUM)],
+ REGISTER_RAW_SIZE (CORE_ADDR));
+ write_memory (sp, &registers[REGISTER_BYTE (L0_REGNUM)],
+ 16 * REGISTER_RAW_SIZE (L0_REGNUM));
+
+ /* If the target has floating point registers, fetch them.
+ Otherwise, zero the floating point register values in
+ registers[] for good measure, even though we might not
+ need to. */
+
+ if (target_has_fp)
+ {
+ net_read_registers (sparc_fpreg_packet, SPARC_FPREG_PLEN,
+ PTRACE_GETFPREGS);
+ bcopy (&sparc_fpreg_packet[SPARC_R_FP0],
+ &registers[REGISTER_BYTE (FP0_REGNUM)], 32 * SPARC_FPREG_SIZE);
+ bcopy (&sparc_fpreg_packet[SPARC_R_FSR],
+ &registers[REGISTER_BYTE (FPS_REGNUM)], 1 * SPARC_FPREG_SIZE);
+ }
+ else
+ {
+ bzero (&registers[REGISTER_BYTE (FP0_REGNUM)], 32 * SPARC_FPREG_SIZE);
+ bzero (&registers[REGISTER_BYTE (FPS_REGNUM)], 1 * SPARC_FPREG_SIZE);
+ }
+
+ /* Mark the register cache valid. */
+
+ registers_fetched ();
+}
+
+/* Store a register or registers into the VxWorks target.
+ REGNO is the register to store, or -1 for all; currently,
+ it is ignored. FIXME look at regno to improve efficiency. */
+
+void
+vx_write_register (regno)
+ int regno;
+{
+ char sparc_greg_packet[SPARC_GREG_PLEN];
+ char sparc_fpreg_packet[SPARC_FPREG_PLEN];
+ int in_gp_regs;
+ int in_fp_regs;
+ CORE_ADDR sp;
+
+ /* Store general purpose registers. When copying values from
+ registers [], don't assume that a location in registers []
+ is properly aligned for the target data type. */
+
+ in_gp_regs = 1;
+ in_fp_regs = 1;
+ if (regno >= 0)
+ {
+ if ((G0_REGNUM <= regno && regno <= I7_REGNUM)
+ || (Y_REGNUM <= regno && regno <= NPC_REGNUM))
+ in_fp_regs = 0;
+ else
+ in_gp_regs = 0;
+ }
+ if (in_gp_regs)
+ {
+ bcopy (&registers[REGISTER_BYTE (G0_REGNUM)],
+ &sparc_greg_packet[SPARC_R_G0], 32 * SPARC_GREG_SIZE);
+ bcopy (&registers[REGISTER_BYTE (Y_REGNUM)],
+ &sparc_greg_packet[SPARC_R_Y], 6 * SPARC_GREG_SIZE);
+
+ net_write_registers (sparc_greg_packet, SPARC_GREG_PLEN, PTRACE_SETREGS);
+
+ /* If this is a local or in register, or we're storing all
+ registers, update the register window spill area. */
+
+ if (regno < 0 || (L0_REGNUM <= regno && regno <= I7_REGNUM))
+ {
+ sp = extract_address (&registers[REGISTER_BYTE (SP_REGNUM)],
+ REGISTER_RAW_SIZE (CORE_ADDR));
+ write_memory (sp, &registers[REGISTER_BYTE (L0_REGNUM)],
+ 16 * REGISTER_RAW_SIZE (L0_REGNUM));
+ }
+ }
+
+ /* Store floating point registers if the target has them. */
+
+ if (in_fp_regs && target_has_fp)
+ {
+ bcopy (&registers[REGISTER_BYTE (FP0_REGNUM)],
+ &sparc_fpreg_packet[SPARC_R_FP0], 32 * SPARC_FPREG_SIZE);
+ bcopy (&registers[REGISTER_BYTE (FPS_REGNUM)],
+ &sparc_fpreg_packet[SPARC_R_FSR], 1 * SPARC_FPREG_SIZE);
+
+ net_write_registers (sparc_fpreg_packet, SPARC_FPREG_PLEN,
+ PTRACE_SETFPREGS);
+ }
+}
diff --git a/gdb/remote.c b/gdb/remote.c
new file mode 100644
index 00000000000..f5b6f7ca14b
--- /dev/null
+++ b/gdb/remote.c
@@ -0,0 +1,3473 @@
+/* Remote target communications for serial-line targets in custom GDB protocol
+ Copyright 1988, 91, 92, 93, 94, 95, 96, 97, 1998
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 '#'. If <data> starts with two characters followed by
+ ':', then the existing stubs interpret this as a sequence number.
+
+ 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:
+ Most values are encoded in ascii hex digits. Signal numbers are according
+ to the numbering in target.h.
+
+ Request Packet
+
+ set thread Hct... Set thread for subsequent operations.
+ c = 'c' for thread used in step and
+ continue; t... can be -1 for all
+ threads.
+ c = 'g' for thread used in other
+ operations. If zero, pick a thread,
+ any thread.
+ reply OK for success
+ ENN for an error.
+
+ 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
+
+ write reg Pn...=r... Write register n... with value r...,
+ which contains two hex digits for each
+ byte in the register (target byte
+ order).
+ reply OK for success
+ ENN for an error
+ (not supported by all stubs).
+
+ 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).
+
+ write mem XAA..AA,LLLL:XX..XX
+ (binary) AA..AA is address,
+ LLLL is number of bytes,
+ XX..XX is binary data
+ reply OK for success
+ ENN for an error
+
+ continue 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.
+
+ continue with Csig;AA..AA Continue with signal sig (hex signal
+ signal number). If ;AA..AA is omitted,
+ resume at same address.
+
+ step with Ssig;AA..AA Like 'C' but step not continue.
+ signal
+
+ 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.
+
+ detach D Reply OK.
+
+ 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 (hex)
+ r... = register contents
+ n... = `thread'
+ r... = thread process ID. This is
+ a hex integer.
+ n... = other string not starting
+ with valid hex digit.
+ gdb should ignore this n,r pair
+ and go on to the next. This way
+ we can extend the protocol.
+ or... WAA The process exited, and AA is
+ the exit status. This is only
+ applicable for certains sorts of
+ targets.
+ or... XAA The process terminated with signal
+ AA.
+ or... OXX..XX XX..XX is hex encoding of ASCII data. This
+ can happen at any time while the
+ program is running and the debugger
+ should continue to wait for
+ 'W', 'T', etc.
+
+ thread alive TXX Find out if the thread XX is alive.
+ reply OK thread is still alive
+ ENN thread is dead
+
+ remote restart RXX Restart the remote server
+
+ extended ops ! Use the extended remote protocol.
+ Sticky -- only needs to be set once.
+
+ 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.
+ search tAA:PP,MM Search backwards starting at address
+ AA for a match with pattern PP and
+ mask MM. PP and MM are 4 bytes.
+ Not supported by all stubs.
+
+ general query qXXXX Request info about XXXX.
+ general set QXXXX=yyyy Set value of XXXX to yyyy.
+ query sect offs qOffsets Get section offsets. Reply is
+ Text=xxx;Data=yyy;Bss=zzz
+
+ Responses can be run-length encoded to save space. A '*' means that
+ the next character is an ASCII encoding giving a repeat count which
+ stands for that many repititions of the character preceding the '*'.
+ The encoding is n+29, yielding a printable character where n >=3
+ (which is where rle starts to win). Don't use an n > 126.
+
+ So
+ "0* " means the same as "0000". */
+
+#include "defs.h"
+#include "gdb_string.h"
+#include <ctype.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 "gdbthread.h"
+
+#include "dcache.h"
+
+#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,
+ char *myaddr, int len));
+
+static int remote_read_bytes PARAMS ((CORE_ADDR memaddr,
+ 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,
+ enum target_signal siggnal));
+
+static int remote_start_remote PARAMS ((PTR));
+
+static void remote_open PARAMS ((char *name, int from_tty));
+
+static void extended_remote_open PARAMS ((char *name, int from_tty));
+
+static void remote_open_1 PARAMS ((char *, int, struct target_ops *,
+ int extended_p));
+
+static void remote_close PARAMS ((int quitting));
+
+static void remote_store_registers PARAMS ((int regno));
+
+static void remote_mourn PARAMS ((void));
+
+static void extended_remote_restart PARAMS ((void));
+
+static void extended_remote_mourn PARAMS ((void));
+
+static void extended_remote_create_inferior PARAMS ((char *, char *, char **));
+
+static void remote_mourn_1 PARAMS ((struct target_ops *));
+
+static void remote_send PARAMS ((char *buf));
+
+static int readchar PARAMS ((int timeout));
+
+static int remote_wait PARAMS ((int pid, struct target_waitstatus * status));
+
+static void remote_kill PARAMS ((void));
+
+static int tohex PARAMS ((int nib));
+
+static void remote_detach PARAMS ((char *args, int from_tty));
+
+static void remote_interrupt PARAMS ((int signo));
+
+static void interrupt_query PARAMS ((void));
+
+static void set_thread PARAMS ((int, int));
+
+static int remote_thread_alive PARAMS ((int));
+
+static void get_offsets PARAMS ((void));
+
+static int read_frame PARAMS ((char *));
+
+static int remote_insert_breakpoint PARAMS ((CORE_ADDR, char *));
+
+static int remote_remove_breakpoint PARAMS ((CORE_ADDR, char *));
+
+static int hexnumlen PARAMS ((ULONGEST num));
+
+static void init_remote_ops PARAMS ((void));
+
+static void init_extended_remote_ops PARAMS ((void));
+
+static void remote_stop PARAMS ((void));
+
+static int ishex PARAMS ((int ch, int *val));
+
+static int stubhex PARAMS ((int ch));
+
+static int remote_query PARAMS ((int/*char*/, char *, char *, int *));
+
+static int hexnumstr PARAMS ((char *, ULONGEST));
+
+static CORE_ADDR remote_address_masked PARAMS ((CORE_ADDR));
+
+static void print_packet PARAMS ((char *));
+
+static unsigned long crc32 PARAMS ((unsigned char *, int, unsigned int));
+
+static void compare_sections_command PARAMS ((char *, int));
+
+static void packet_command PARAMS ((char *, int));
+
+static int stub_unpack_int PARAMS ((char *buff, int fieldlength));
+
+char *unpack_varlen_hex PARAMS ((char *buff, int *result));
+
+static char *unpack_nibble PARAMS ((char *buf, int *val));
+
+static char *pack_nibble PARAMS ((char *buf, int nibble));
+
+static char *pack_hex_byte PARAMS ((char *pkt, int/*unsigned char*/ byte));
+
+static char *unpack_byte PARAMS ((char *buf, int *value));
+
+static char *pack_int PARAMS ((char *buf, int value));
+
+static char *unpack_int PARAMS ((char *buf, int *value));
+
+static char *unpack_string PARAMS ((char *src, char *dest, int length));
+
+static char *pack_threadid PARAMS ((char *pkt, threadref *id));
+
+static char *unpack_threadid PARAMS ((char *inbuf, threadref *id));
+
+void int_to_threadref PARAMS ((threadref *id, int value));
+
+static int threadref_to_int PARAMS ((threadref *ref));
+
+static void copy_threadref PARAMS ((threadref *dest, threadref *src));
+
+static int threadmatch PARAMS ((threadref *dest, threadref *src));
+
+static char *pack_threadinfo_request PARAMS ((char *pkt, int mode,
+ threadref *id));
+
+static int remote_unpack_thread_info_response PARAMS ((char *pkt,
+ threadref *expectedref,
+ struct gdb_ext_thread_info *info));
+
+
+static int remote_get_threadinfo PARAMS ((threadref *threadid,
+ int fieldset, /*TAG mask */
+ struct gdb_ext_thread_info *info));
+
+static int adapt_remote_get_threadinfo PARAMS ((gdb_threadref *ref,
+ int selection,
+ struct gdb_ext_thread_info *info));
+
+static char *pack_threadlist_request PARAMS ((char *pkt, int startflag,
+ int threadcount,
+ threadref *nextthread));
+
+static int parse_threadlist_response PARAMS ((char *pkt,
+ int result_limit,
+ threadref *original_echo,
+ threadref *resultlist,
+ int *doneflag));
+
+static int remote_get_threadlist PARAMS ((int startflag,
+ threadref *nextthread,
+ int result_limit,
+ int *done,
+ int *result_count,
+ threadref *threadlist));
+
+typedef int (*rmt_thread_action) (threadref *ref, void *context);
+
+static int remote_threadlist_iterator PARAMS ((rmt_thread_action stepfunction,
+ void *context, int looplimit));
+
+static int remote_newthread_step PARAMS ((threadref *ref, void *context));
+
+static int remote_current_thread PARAMS ((int oldpid));
+
+int remote_find_new_threads PARAMS ((void));
+
+static void record_currthread PARAMS ((int currthread));
+
+static void init_remote_threads PARAMS ((void));
+
+/* exported functions */
+
+extern int fromhex PARAMS ((int a));
+
+extern void getpkt PARAMS ((char *buf, int forever));
+
+extern int putpkt PARAMS ((char *buf));
+
+static int putpkt_binary PARAMS ((char *buf, int cnt));
+
+void remote_console_output PARAMS ((char *));
+
+static void check_binary_download PARAMS ((CORE_ADDR addr));
+
+/* Define the target subroutine names */
+
+void open_remote_target PARAMS ((char *, int, struct target_ops *, int));
+
+void _initialize_remote PARAMS ((void));
+
+/* */
+
+static struct target_ops remote_ops;
+
+static struct target_ops extended_remote_ops;
+
+static struct target_thread_vector remote_thread_vec;
+
+/* 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. */
+
+/* Changed to allow option to set timeout value.
+ was static int remote_timeout = 2; */
+extern int remote_timeout;
+
+/* This variable chooses whether to send a ^C or a break when the user
+ requests program interruption. Although ^C is usually what remote
+ systems expect, and that is the default here, sometimes a break is
+ preferable instead. */
+
+static int remote_break;
+
+/* Has the user attempted to interrupt the target? If so, then offer
+ the user the opportunity to bail out completely if he interrupts
+ again. */
+static int interrupted_already = 0;
+
+/* 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. */
+static serial_t remote_desc = NULL;
+
+/* This variable (available to the user via "set remotebinarydownload")
+ dictates whether downloads are sent in binary (via the 'X' packet).
+ We assume that the stub can, and attempt to do it. This will be cleared if
+ the stub does not understand it. This switch is still needed, though
+ in cases when the packet is supported in the stub, but the connection
+ does not allow it (i.e., 7-bit serial connection only). */
+static int remote_binary_download = 1;
+
+/* Have we already checked whether binary downloads work? */
+static int remote_binary_checked;
+
+/* Having this larger than 400 causes us to be incompatible with m68k-stub.c
+ and i386-stub.c. Normally, no one would notice because it only matters
+ for writing large chunks of memory (e.g. in downloads). Also, this needs
+ to be more than 400 if required to hold the registers (see below, where
+ we round it up based on REGISTER_BYTES). */
+#define PBUFSIZ 400
+
+/* Maximum number of bytes to read/write at once. The value here
+ is chosen to fill up a packet (the headers account for the 32). */
+#define MAXBUFBYTES ((PBUFSIZ-32)/2)
+
+/* Round up PBUFSIZ to hold all the registers, at least. */
+/* The blank line after the #if seems to be required to work around a
+ bug in HP's PA compiler. */
+#if REGISTER_BYTES > MAXBUFBYTES
+
+#undef PBUFSIZ
+#define PBUFSIZ (REGISTER_BYTES * 2 + 32)
+#endif
+
+
+/* This variable sets the number of bytes to be written to the target
+ in a single packet. Normally PBUFSIZ is satisfactory, but some
+ targets need smaller values (perhaps because the receiving end
+ is slow). */
+
+static int remote_write_size = PBUFSIZ;
+
+/* This variable sets the number of bits in an address that are to be
+ sent in a memory ("M" or "m") packet. Normally, after stripping
+ leading zeros, the entire address would be sent. This variable
+ restricts the address to REMOTE_ADDRESS_SIZE bits. HISTORY: The
+ initial implementation of remote.c restricted the address sent in
+ memory packets to ``host::sizeof long'' bytes - (typically 32
+ bits). Consequently, for 64 bit targets, the upper 32 bits of an
+ address was never sent. Since fixing this bug may cause a break in
+ some remote targets this variable is principly provided to
+ facilitate backward compatibility. */
+
+static int remote_address_size;
+
+/* This is the size (in chars) of the first response to the `g' command. This
+ is used to limit the size of the memory read and write commands to prevent
+ stub buffers from overflowing. The size does not include headers and
+ trailers, it is only the payload size. */
+
+static int remote_register_buf_size = 0;
+
+/* Should we try the 'P' request? If this is set to one when the stub
+ doesn't support 'P', the only consequence is some unnecessary traffic. */
+static int stub_supports_P = 1;
+
+/* These are pointers to hook functions that may be set in order to
+ modify resume/wait behavior for a particular architecture. */
+
+void (*target_resume_hook) PARAMS ((void));
+void (*target_wait_loop_hook) PARAMS ((void));
+
+
+
+/* These are the threads which we last sent to the remote system.
+ -1 for all or -2 for not sent yet. */
+static int general_thread;
+static int cont_thread;
+
+/* Call this function as a result of
+ 1) A halt indication (T packet) containing a thread id
+ 2) A direct query of currthread
+ 3) Successful execution of set thread
+ */
+
+static void
+record_currthread (currthread)
+ int currthread;
+{
+#if 0 /* target_wait must not modify inferior_pid! */
+ inferior_pid = currthread;
+#endif
+ general_thread = currthread;
+#if 0 /* setting cont_thread has a different meaning
+ from having the target report its thread id. */
+ cont_thread = currthread;
+#endif
+ /* If this is a new thread, add it to GDB's thread list.
+ If we leave it up to WFI to do this, bad things will happen. */
+ if (!in_thread_list (currthread))
+ add_thread (currthread);
+}
+
+#define MAGIC_NULL_PID 42000
+
+static void
+set_thread (th, gen)
+ int th;
+ int gen;
+{
+ char buf[PBUFSIZ];
+ int state = gen ? general_thread : cont_thread;
+
+ if (state == th)
+ return;
+
+ buf[0] = 'H';
+ buf[1] = gen ? 'g' : 'c';
+ if (th == MAGIC_NULL_PID)
+ {
+ buf[2] = '0';
+ buf[3] = '\0';
+ }
+ else if (th < 0)
+ sprintf (&buf[2], "-%x", -th);
+ else
+ sprintf (&buf[2], "%x", th);
+ putpkt (buf);
+ getpkt (buf, 0);
+ if (gen)
+ general_thread = th;
+ else
+ cont_thread = th;
+}
+
+/* Return nonzero if the thread TH is still alive on the remote system. */
+
+static int
+remote_thread_alive (th)
+ int th;
+{
+ char buf[PBUFSIZ];
+
+ buf[0] = 'T';
+ if (th < 0)
+ sprintf (&buf[1], "-%08x", -th);
+ else
+ sprintf (&buf[1], "%08x", th);
+ putpkt (buf);
+ getpkt (buf, 0);
+ return (buf[0] == 'O' && buf[1] == 'K');
+}
+
+/* About these extended threadlist and threadinfo packets. They are
+ variable length packets but, the fields within them are often fixed
+ length. They are redundent enough to send over UDP as is the
+ remote protocol in general. There is a matching unit test module
+ in libstub. */
+
+#define BUF_THREAD_ID_SIZE (OPAQUETHREADBYTES*2)
+
+/* encode 64 bits in 16 chars of hex */
+
+static const char hexchars[] = "0123456789abcdef";
+
+static int
+ishex (ch, val)
+ int ch;
+ int *val;
+{
+ if ((ch >= 'a') && (ch <= 'f'))
+ {
+ *val = ch - 'a' + 10;
+ return 1;
+ }
+ if ((ch >= 'A') && (ch <= 'F'))
+ {
+ *val = ch - 'A' + 10;
+ return 1;
+ }
+ if ((ch >= '0') && (ch <= '9'))
+ {
+ *val = ch - '0';
+ return 1;
+ }
+ return 0;
+}
+
+static int
+stubhex (ch)
+ int ch;
+{
+ if (ch >= 'a' && ch <= 'f')
+ return ch - 'a' + 10;
+ if (ch >= '0' && ch <= '9')
+ return ch - '0';
+ if (ch >= 'A' && ch <= 'F')
+ return ch - 'A' + 10;
+ return -1;
+}
+
+static int
+stub_unpack_int (buff, fieldlength)
+ char *buff;
+ int fieldlength;
+{
+ int nibble;
+ int retval = 0;
+
+ while (fieldlength)
+ {
+ nibble = stubhex (*buff++);
+ retval |= nibble;
+ fieldlength--;
+ if (fieldlength)
+ retval = retval << 4;
+ }
+ return retval;
+}
+
+char *
+unpack_varlen_hex (buff, result)
+ char *buff; /* packet to parse */
+ int *result;
+{
+ int nibble;
+ int retval = 0;
+
+ while (ishex (*buff, &nibble))
+ {
+ buff++;
+ retval = retval << 4;
+ retval |= nibble & 0x0f;
+ }
+ *result = retval;
+ return buff;
+}
+
+static char *
+unpack_nibble (buf, val)
+ char *buf;
+ int *val;
+{
+ ishex (*buf++, val);
+ return buf;
+}
+
+static char *
+pack_nibble (buf, nibble)
+ char *buf;
+ int nibble;
+{
+ *buf++ = hexchars[(nibble & 0x0f)];
+ return buf;
+}
+
+static char *
+pack_hex_byte (pkt, byte)
+ char *pkt;
+ int byte;
+{
+ *pkt++ = hexchars[(byte >> 4) & 0xf];
+ *pkt++ = hexchars[(byte & 0xf)];
+ return pkt;
+}
+
+static char *
+unpack_byte (buf, value)
+ char *buf;
+ int *value;
+{
+ *value = stub_unpack_int (buf, 2);
+ return buf + 2;
+}
+
+static char *
+pack_int (buf, value)
+ char *buf;
+ int value;
+{
+ buf = pack_hex_byte (buf, (value >> 24) & 0xff);
+ buf = pack_hex_byte (buf, (value >> 16) & 0xff);
+ buf = pack_hex_byte (buf, (value >> 8) & 0x0ff);
+ buf = pack_hex_byte (buf, (value & 0xff));
+ return buf;
+}
+
+static char *
+unpack_int (buf, value)
+ char *buf;
+ int *value;
+{
+ *value = stub_unpack_int (buf, 8);
+ return buf + 8;
+}
+
+#if 0 /* currently unused, uncomment when needed */
+static char *pack_string PARAMS ((char *pkt, char *string));
+
+static char *
+pack_string (pkt, string)
+ char *pkt;
+ char *string;
+{
+ char ch;
+ int len;
+
+ len = strlen (string);
+ if (len > 200)
+ len = 200; /* Bigger than most GDB packets, junk??? */
+ pkt = pack_hex_byte (pkt, len);
+ while (len-- > 0)
+ {
+ ch = *string++;
+ if ((ch == '\0') || (ch == '#'))
+ ch = '*'; /* Protect encapsulation */
+ *pkt++ = ch;
+ }
+ return pkt;
+}
+#endif /* 0 (unused) */
+
+static char *
+unpack_string (src, dest, length)
+ char *src;
+ char *dest;
+ int length;
+{
+ while (length--)
+ *dest++ = *src++;
+ *dest = '\0';
+ return src;
+}
+
+static char *
+pack_threadid (pkt, id)
+ char *pkt;
+ threadref *id;
+{
+ char *limit;
+ unsigned char *altid;
+
+ altid = (unsigned char *) id;
+ limit = pkt + BUF_THREAD_ID_SIZE;
+ while (pkt < limit)
+ pkt = pack_hex_byte (pkt, *altid++);
+ return pkt;
+}
+
+
+static char *
+unpack_threadid (inbuf, id)
+ char *inbuf;
+ threadref *id;
+{
+ char *altref;
+ char *limit = inbuf + BUF_THREAD_ID_SIZE;
+ int x, y;
+
+ altref = (char *) id;
+
+ while (inbuf < limit)
+ {
+ x = stubhex (*inbuf++);
+ y = stubhex (*inbuf++);
+ *altref++ = (x << 4) | y;
+ }
+ return inbuf;
+}
+
+/* Externally, threadrefs are 64 bits but internally, they are still
+ ints. This is due to a mismatch of specifications. We would like
+ to use 64bit thread references internally. This is an adapter
+ function. */
+
+void
+int_to_threadref (id, value)
+ threadref *id;
+ int value;
+{
+ unsigned char *scan;
+
+ scan = (unsigned char *) id;
+ {
+ int i = 4;
+ while (i--)
+ *scan++ = 0;
+ }
+ *scan++ = (value >> 24) & 0xff;
+ *scan++ = (value >> 16) & 0xff;
+ *scan++ = (value >> 8) & 0xff;
+ *scan++ = (value & 0xff);
+}
+
+static int
+threadref_to_int (ref)
+ threadref *ref;
+{
+ int i, value = 0;
+ unsigned char *scan;
+
+ scan = (char *) ref;
+ scan += 4;
+ i = 4;
+ while (i-- > 0)
+ value = (value << 8) | ((*scan++) & 0xff);
+ return value;
+}
+
+static void
+copy_threadref (dest, src)
+ threadref *dest;
+ threadref *src;
+{
+ int i;
+ unsigned char *csrc, *cdest;
+
+ csrc = (unsigned char *) src;
+ cdest = (unsigned char *) dest;
+ i = 8;
+ while (i--)
+ *cdest++ = *csrc++;
+}
+
+static int
+threadmatch (dest, src)
+ threadref *dest;
+ threadref *src;
+{
+ /* things are broken right now, so just assume we got a match */
+#if 0
+ unsigned char *srcp, *destp;
+ int i, result;
+ srcp = (char *) src;
+ destp = (char *) dest;
+
+ result = 1;
+ while (i-- > 0)
+ result &= (*srcp++ == *destp++) ? 1 : 0;
+ return result;
+#endif
+ return 1;
+}
+
+/*
+ threadid:1, # always request threadid
+ context_exists:2,
+ display:4,
+ unique_name:8,
+ more_display:16
+*/
+
+/* Encoding: 'Q':8,'P':8,mask:32,threadid:64 */
+
+static char *
+pack_threadinfo_request (pkt, mode, id)
+ char *pkt;
+ int mode;
+ threadref *id;
+{
+ *pkt++ = 'q'; /* Info Query */
+ *pkt++ = 'P'; /* process or thread info */
+ pkt = pack_int (pkt, mode); /* mode */
+ pkt = pack_threadid (pkt, id); /* threadid */
+ *pkt = '\0'; /* terminate */
+ return pkt;
+}
+
+/* These values tag the fields in a thread info response packet */
+/* Tagging the fields allows us to request specific fields and to
+ add more fields as time goes by */
+
+#define TAG_THREADID 1 /* Echo the thread identifier */
+#define TAG_EXISTS 2 /* Is this process defined enough to
+ fetch registers and its stack */
+#define TAG_DISPLAY 4 /* A short thing maybe to put on a window */
+#define TAG_THREADNAME 8 /* string, maps 1-to-1 with a thread is */
+#define TAG_MOREDISPLAY 16 /* Whatever the kernel wants to say about
+ the process*/
+
+static int
+remote_unpack_thread_info_response (pkt, expectedref, info)
+ char *pkt;
+ threadref *expectedref;
+ struct gdb_ext_thread_info *info;
+{
+ int mask, length;
+ unsigned int tag;
+ threadref ref;
+ char *limit = pkt + PBUFSIZ; /* plausable parsing limit */
+ int retval = 1;
+
+ /* info->threadid = 0; FIXME: implement zero_threadref */
+ info->active = 0;
+ info->display[0] = '\0';
+ info->shortname[0] = '\0';
+ info->more_display[0] = '\0';
+
+ /* Assume the characters indicating the packet type have been stripped */
+ pkt = unpack_int (pkt, &mask); /* arg mask */
+ pkt = unpack_threadid (pkt, &ref);
+
+ if (mask == 0)
+ warning ("Incomplete response to threadinfo request\n");
+ if (!threadmatch (&ref, expectedref))
+ { /* This is an answer to a different request */
+ warning ("ERROR RMT Thread info mismatch\n");
+ return 0;
+ }
+ copy_threadref (&info->threadid, &ref);
+
+ /* Loop on tagged fields , try to bail if somthing goes wrong */
+
+ while ((pkt < limit) && mask && *pkt) /* packets are terminated with nulls */
+ {
+ pkt = unpack_int (pkt, &tag); /* tag */
+ pkt = unpack_byte (pkt, &length); /* length */
+ if (!(tag & mask)) /* tags out of synch with mask */
+ {
+ warning ("ERROR RMT: threadinfo tag mismatch\n");
+ retval = 0;
+ break;
+ }
+ if (tag == TAG_THREADID)
+ {
+ if (length != 16)
+ {
+ warning ("ERROR RMT: length of threadid is not 16\n");
+ retval = 0;
+ break;
+ }
+ pkt = unpack_threadid (pkt, &ref);
+ mask = mask & ~TAG_THREADID;
+ continue;
+ }
+ if (tag == TAG_EXISTS)
+ {
+ info->active = stub_unpack_int (pkt, length);
+ pkt += length;
+ mask = mask & ~(TAG_EXISTS);
+ if (length > 8)
+ {
+ warning ("ERROR RMT: 'exists' length too long\n");
+ retval = 0;
+ break;
+ }
+ continue;
+ }
+ if (tag == TAG_THREADNAME)
+ {
+ pkt = unpack_string (pkt, &info->shortname[0], length);
+ mask = mask & ~TAG_THREADNAME;
+ continue;
+ }
+ if (tag == TAG_DISPLAY)
+ {
+ pkt = unpack_string (pkt, &info->display[0], length);
+ mask = mask & ~TAG_DISPLAY;
+ continue;
+ }
+ if (tag == TAG_MOREDISPLAY)
+ {
+ pkt = unpack_string (pkt, &info->more_display[0], length);
+ mask = mask & ~TAG_MOREDISPLAY;
+ continue;
+ }
+ warning ("ERROR RMT: unknown thread info tag\n");
+ break; /* Not a tag we know about */
+ }
+ return retval;
+}
+
+static int
+remote_get_threadinfo (threadid, fieldset, info)
+ threadref *threadid;
+ int fieldset; /* TAG mask */
+ struct gdb_ext_thread_info *info;
+{
+ int result;
+ char threadinfo_pkt[PBUFSIZ];
+
+ pack_threadinfo_request (threadinfo_pkt, fieldset, threadid);
+ putpkt (threadinfo_pkt);
+ getpkt (threadinfo_pkt, 0);
+ result = remote_unpack_thread_info_response (threadinfo_pkt + 2, threadid,
+ info);
+ return result;
+}
+
+/* Unfortunately, 61 bit thread-ids are bigger than the internal
+ representation of a threadid. */
+
+static int
+adapt_remote_get_threadinfo (ref, selection, info)
+ gdb_threadref *ref;
+ int selection;
+ struct gdb_ext_thread_info *info;
+{
+ threadref lclref;
+
+ int_to_threadref (&lclref, *ref);
+ return remote_get_threadinfo (&lclref, selection, info);
+}
+
+/* Format: i'Q':8,i"L":8,initflag:8,batchsize:16,lastthreadid:32 */
+
+static char *
+pack_threadlist_request (pkt, startflag, threadcount, nextthread)
+ char *pkt;
+ int startflag;
+ int threadcount;
+ threadref *nextthread;
+{
+ *pkt++ = 'q'; /* info query packet */
+ *pkt++ = 'L'; /* Process LIST or threadLIST request */
+ pkt = pack_nibble (pkt, startflag); /* initflag 1 bytes */
+ pkt = pack_hex_byte (pkt, threadcount); /* threadcount 2 bytes */
+ pkt = pack_threadid (pkt, nextthread); /* 64 bit thread identifier */
+ *pkt = '\0';
+ return pkt;
+}
+
+/* Encoding: 'q':8,'M':8,count:16,done:8,argthreadid:64,(threadid:64)* */
+
+static int
+parse_threadlist_response (pkt, result_limit, original_echo, resultlist,
+ doneflag)
+ char *pkt;
+ int result_limit;
+ threadref *original_echo;
+ threadref *resultlist;
+ int *doneflag;
+{
+ char *limit;
+ int count, resultcount, done;
+
+ resultcount = 0;
+ /* Assume the 'q' and 'M chars have been stripped. */
+ limit = pkt + (PBUFSIZ - BUF_THREAD_ID_SIZE); /* done parse past here */
+ pkt = unpack_byte (pkt, &count); /* count field */
+ pkt = unpack_nibble (pkt, &done);
+ /* The first threadid is the argument threadid. */
+ pkt = unpack_threadid (pkt, original_echo); /* should match query packet */
+ while ((count-- > 0) && (pkt < limit))
+ {
+ pkt = unpack_threadid (pkt, resultlist++);
+ if (resultcount++ >= result_limit)
+ break;
+ }
+ if (doneflag)
+ *doneflag = done;
+ return resultcount;
+}
+
+static int
+remote_get_threadlist (startflag, nextthread, result_limit,
+ done, result_count, threadlist)
+ int startflag;
+ threadref *nextthread;
+ int result_limit;
+ int *done;
+ int *result_count;
+ threadref *threadlist;
+
+{
+ static threadref echo_nextthread;
+ char threadlist_packet[PBUFSIZ];
+ char t_response[PBUFSIZ];
+ int result = 1;
+
+ /* Trancate result limit to be smaller than the packet size */
+ if ((((result_limit + 1) * BUF_THREAD_ID_SIZE) + 10) >= PBUFSIZ)
+ result_limit = (PBUFSIZ / BUF_THREAD_ID_SIZE) - 2;
+
+ pack_threadlist_request (threadlist_packet,
+ startflag, result_limit, nextthread);
+ putpkt (threadlist_packet);
+ getpkt (t_response, 0);
+
+ *result_count =
+ parse_threadlist_response (t_response + 2, result_limit, &echo_nextthread,
+ threadlist, done);
+
+ if (!threadmatch (&echo_nextthread, nextthread))
+ {
+ /* FIXME: This is a good reason to drop the packet */
+ /* Possably, there is a duplicate response */
+ /* Possabilities :
+ retransmit immediatly - race conditions
+ retransmit after timeout - yes
+ exit
+ wait for packet, then exit
+ */
+ warning ("HMM: threadlist did not echo arg thread, dropping it\n");
+ return 0; /* I choose simply exiting */
+ }
+ if (*result_count <= 0)
+ {
+ if (*done != 1)
+ {
+ warning ("RMT ERROR : failed to get remote thread list\n");
+ result = 0;
+ }
+ return result; /* break; */
+ }
+ if (*result_count > result_limit)
+ {
+ *result_count = 0;
+ warning ("RMT ERROR: threadlist response longer than requested\n");
+ return 0;
+ }
+ return result;
+}
+
+/* This is the interface between remote and threads, remotes upper interface */
+
+/* remote_find_new_threads retrieves the thread list and for each
+ thread in the list, looks up the thread in GDB's internal list,
+ ading the thread if it does not already exist. This involves
+ getting partial thread lists from the remote target so, polling the
+ quit_flag is required. */
+
+
+/* About this many threadisds fit in a packet. */
+
+#define MAXTHREADLISTRESULTS 32
+
+static int
+remote_threadlist_iterator (stepfunction, context, looplimit)
+ rmt_thread_action stepfunction;
+ void *context;
+ int looplimit;
+{
+ int done, i, result_count;
+ int startflag = 1;
+ int result = 1;
+ int loopcount = 0;
+ static threadref nextthread;
+ static threadref resultthreadlist[MAXTHREADLISTRESULTS];
+
+ done = 0;
+ while (!done)
+ {
+ if (loopcount++ > looplimit)
+ {
+ result = 0;
+ warning ("Remote fetch threadlist -infinite loop-\n");
+ break;
+ }
+ if (!remote_get_threadlist (startflag, &nextthread, MAXTHREADLISTRESULTS,
+ &done, &result_count, resultthreadlist))
+ {
+ result = 0;
+ break;
+ }
+ /* clear for later iterations */
+ startflag = 0;
+ /* Setup to resume next batch of thread references, set nextthread. */
+ if (result_count >= 1)
+ copy_threadref (&nextthread, &resultthreadlist[result_count - 1]);
+ i = 0;
+ while (result_count--)
+ if (!(result = (*stepfunction) (&resultthreadlist[i++], context)))
+ break;
+ }
+ return result;
+}
+
+static int
+remote_newthread_step (ref, context)
+ threadref *ref;
+ void *context;
+{
+ int pid;
+
+ pid = threadref_to_int (ref);
+ if (!in_thread_list (pid))
+ add_thread (pid);
+ return 1; /* continue iterator */
+}
+
+#define CRAZY_MAX_THREADS 1000
+
+static int
+remote_current_thread (oldpid)
+ int oldpid;
+{
+ char buf[PBUFSIZ];
+
+ putpkt ("qC");
+ getpkt (buf, 0);
+ if (buf[0] == 'Q' && buf[1] == 'C')
+ return strtol (&buf[2], NULL, 16);
+ else
+ return oldpid;
+}
+
+int
+remote_find_new_threads ()
+{
+ int ret;
+
+ ret = remote_threadlist_iterator (remote_newthread_step, 0,
+ CRAZY_MAX_THREADS);
+ if (inferior_pid == MAGIC_NULL_PID) /* ack ack ack */
+ inferior_pid = remote_current_thread (inferior_pid);
+ return ret;
+}
+
+/* Initialize the thread vector which is used by threads.c */
+/* The thread stub is a package, it has an initializer */
+
+static void
+init_remote_threads ()
+{
+ remote_thread_vec.find_new_threads = remote_find_new_threads;
+ remote_thread_vec.get_thread_info = adapt_remote_get_threadinfo;
+}
+
+
+/* Restart the remote side; this is an extended protocol operation. */
+
+static void
+extended_remote_restart ()
+{
+ char buf[PBUFSIZ];
+
+ /* Send the restart command; for reasons I don't understand the
+ remote side really expects a number after the "R". */
+ buf[0] = 'R';
+ sprintf (&buf[1], "%x", 0);
+ putpkt (buf);
+
+ /* Now query for status so this looks just like we restarted
+ gdbserver from scratch. */
+ putpkt ("?");
+ getpkt (buf, 0);
+}
+
+/* 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;
+}
+
+/* Query the remote side for the text, data and bss offsets. */
+
+static void
+get_offsets ()
+{
+ char buf[PBUFSIZ], *ptr;
+ int lose;
+ CORE_ADDR text_addr, data_addr, bss_addr;
+ struct section_offsets *offs;
+
+ putpkt ("qOffsets");
+
+ getpkt (buf, 0);
+
+ if (buf[0] == '\000')
+ return; /* Return silently. Stub doesn't support
+ this command. */
+ if (buf[0] == 'E')
+ {
+ warning ("Remote failure reply: %s", buf);
+ return;
+ }
+
+ /* Pick up each field in turn. This used to be done with scanf, but
+ scanf will make trouble if CORE_ADDR size doesn't match
+ conversion directives correctly. The following code will work
+ with any size of CORE_ADDR. */
+ text_addr = data_addr = bss_addr = 0;
+ ptr = buf;
+ lose = 0;
+
+ if (strncmp (ptr, "Text=", 5) == 0)
+ {
+ ptr += 5;
+ /* Don't use strtol, could lose on big values. */
+ while (*ptr && *ptr != ';')
+ text_addr = (text_addr << 4) + fromhex (*ptr++);
+ }
+ else
+ lose = 1;
+
+ if (!lose && strncmp (ptr, ";Data=", 6) == 0)
+ {
+ ptr += 6;
+ while (*ptr && *ptr != ';')
+ data_addr = (data_addr << 4) + fromhex (*ptr++);
+ }
+ else
+ lose = 1;
+
+ if (!lose && strncmp (ptr, ";Bss=", 5) == 0)
+ {
+ ptr += 5;
+ while (*ptr && *ptr != ';')
+ bss_addr = (bss_addr << 4) + fromhex (*ptr++);
+ }
+ else
+ lose = 1;
+
+ if (lose)
+ error ("Malformed response to offset query, %s", buf);
+
+ if (symfile_objfile == NULL)
+ return;
+
+ 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;
+
+ /* This is a temporary kludge to force data and bss to use the same offsets
+ because that's what nlmconv does now. The real solution requires changes
+ to the stub and remote.c that I don't have time to do right now. */
+
+ ANOFFSET (offs, SECT_OFF_DATA) = data_addr;
+ ANOFFSET (offs, SECT_OFF_BSS) = data_addr;
+
+ objfile_relocate (symfile_objfile, offs);
+}
+
+/* Stub for catch_errors. */
+
+static int
+remote_start_remote (dummy)
+ PTR dummy;
+{
+ immediate_quit = 1; /* Allow user to interrupt it */
+
+ /* Ack any packet which the remote side has already sent. */
+ SERIAL_WRITE (remote_desc, "+", 1);
+
+ /* Let the stub know that we want it to return the thread. */
+ set_thread (-1, 0);
+
+ inferior_pid = remote_current_thread (inferior_pid);
+
+ get_offsets (); /* Get text, data & bss offsets */
+
+ 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 void
+remote_open (name, from_tty)
+ char *name;
+ int from_tty;
+{
+ remote_open_1 (name, from_tty, &remote_ops, 0);
+}
+
+/* Open a connection to a remote debugger using the extended
+ remote gdb protocol. NAME is the filename used for communication. */
+
+static void
+extended_remote_open (name, from_tty)
+ char *name;
+ int from_tty;
+{
+ remote_open_1 (name, from_tty, &extended_remote_ops, 1/*extended_p*/);
+}
+
+/* Generic code for opening a connection to a remote target. */
+
+static DCACHE *remote_dcache;
+
+static void
+remote_open_1 (name, from_tty, target, extended_p)
+ char *name;
+ int from_tty;
+ struct target_ops *target;
+ int extended_p;
+{
+ if (name == 0)
+ error ("To open a remote debug connection, you need to specify what\n\
+serial device is attached to the remote system (e.g. /dev/ttya).");
+
+ target_preopen (from_tty);
+
+ unpush_target (target);
+
+ remote_dcache = dcache_init (remote_read_bytes, remote_write_bytes);
+
+ remote_desc = SERIAL_OPEN (name);
+ if (!remote_desc)
+ perror_with_name (name);
+
+ if (baud_rate != -1)
+ {
+ 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 (target); /* Switch to using remote target now */
+
+ /* The target vector does not have the thread functions in it yet,
+ so we use this function to call back into the thread module and
+ register the thread vector and its contained functions. */
+ bind_target_thread_vector (&remote_thread_vec);
+
+ /* Start out by trying the 'P' request to set registers. We set
+ this each time that we open a new target so that if the user
+ switches from one stub to another, we can (if the target is
+ closed and reopened) cope. */
+ stub_supports_P = 1;
+
+ general_thread = -2;
+ cont_thread = -2;
+
+ /* Force remote_write_bytes to check whether target supports
+ binary downloading. */
+ remote_binary_checked = 0;
+
+ /* Without this, some commands which require an active target (such
+ as kill) won't work. This variable serves (at least) double duty
+ as both the pid of the target process (if it has such), and as a
+ flag indicating that a target is active. These functions should
+ be split out into seperate variables, especially since GDB will
+ someday have a notion of debugging several processes. */
+
+ inferior_pid = MAGIC_NULL_PID;
+ /* 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, NULL,
+ "Couldn't establish connection to remote target\n",
+ RETURN_MASK_ALL))
+ {
+ pop_target ();
+ return;
+ }
+
+ if (extended_p)
+ {
+ /* tell the remote that we're using the extended protocol. */
+ char buf[PBUFSIZ];
+ putpkt ("!");
+ getpkt (buf, 0);
+ }
+}
+
+/* This takes a program previously attached to and detaches it. After
+ this is done, GDB can be used to debug some other program. We
+ better not have left any breakpoints in the target program or it'll
+ die when it hits one. */
+
+static void
+remote_detach (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ char buf[PBUFSIZ];
+
+ if (args)
+ error ("Argument given to \"detach\" when remotely debugging.");
+
+ /* Tell the remote target to detach. */
+ strcpy (buf, "D");
+ remote_send (buf);
+
+ pop_target ();
+ if (from_tty)
+ puts_filtered ("Ending remote debugging.\n");
+}
+
+/* Convert hex digit A to a number. */
+
+int
+fromhex (a)
+ int a;
+{
+ if (a >= '0' && a <= '9')
+ return a - '0';
+ else if (a >= 'a' && a <= 'f')
+ return a - 'a' + 10;
+ else if (a >= 'A' && a <= 'F')
+ return a - 'A' + 10;
+ else
+ error ("Reply contains invalid hex digit %d", a);
+}
+
+/* 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 enum target_signal last_sent_signal = TARGET_SIGNAL_0;
+
+static int last_sent_step;
+
+static void
+remote_resume (pid, step, siggnal)
+ int pid, step;
+ enum target_signal siggnal;
+{
+ char buf[PBUFSIZ];
+
+ if (pid == -1)
+ set_thread (0, 0); /* run any thread */
+ else
+ set_thread (pid, 0); /* run this thread */
+
+ dcache_flush (remote_dcache);
+
+ last_sent_signal = siggnal;
+ last_sent_step = step;
+
+ /* A hook for when we need to do something at the last moment before
+ resumption. */
+ if (target_resume_hook)
+ (*target_resume_hook) ();
+
+ if (siggnal != TARGET_SIGNAL_0)
+ {
+ buf[0] = step ? 'S' : 'C';
+ buf[1] = tohex (((int)siggnal >> 4) & 0xf);
+ buf[2] = tohex ((int)siggnal & 0xf);
+ buf[3] = '\0';
+ }
+ else
+ strcpy (buf, step ? "s": "c");
+
+ putpkt (buf);
+}
+
+/* Send ^C to target to halt it. Target will respond, and send us a
+ packet. */
+
+static void (*ofunc) PARAMS ((int));
+
+static void
+remote_interrupt (signo)
+ int signo;
+{
+ remote_stop ();
+ signal (signo, remote_interrupt);
+}
+
+static void
+remote_stop ()
+{
+ if (!interrupted_already)
+ {
+ /* Send a break or a ^C, depending on user preference. */
+ interrupted_already = 1;
+
+ if (remote_debug)
+ printf_unfiltered ("remote_stop called\n");
+
+ if (remote_break)
+ SERIAL_SEND_BREAK (remote_desc);
+ else
+ SERIAL_WRITE (remote_desc, "\003", 1);
+ }
+ else
+ {
+ signal (SIGINT, ofunc);
+ interrupt_query ();
+ signal (SIGINT, remote_interrupt);
+ interrupted_already = 0;
+ }
+}
+
+/* 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 ();
+}
+
+/* If nonzero, ignore the next kill. */
+
+int kill_kludge;
+
+void
+remote_console_output (msg)
+ char *msg;
+{
+ char *p;
+
+ for (p = msg; *p; p +=2)
+ {
+ char tb[2];
+ char c = fromhex (p[0]) * 16 + fromhex (p[1]);
+ tb[0] = c;
+ tb[1] = 0;
+ if (target_output_hook)
+ target_output_hook (tb);
+ else
+ fputs_filtered (tb, gdb_stdout);
+ }
+}
+
+/* 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;
+ struct target_waitstatus *status;
+{
+ unsigned char buf[PBUFSIZ];
+ int thread_num = -1;
+
+ status->kind = TARGET_WAITKIND_EXITED;
+ status->value.integer = 0;
+
+ while (1)
+ {
+ unsigned char *p;
+
+ interrupted_already = 0;
+ ofunc = signal (SIGINT, remote_interrupt);
+ getpkt ((char *) buf, 1);
+ signal (SIGINT, ofunc);
+
+ /* This is a hook for when we need to do something (perhaps the
+ collection of trace data) every time the target stops. */
+ if (target_wait_loop_hook)
+ (*target_wait_loop_hook) ();
+
+ switch (buf[0])
+ {
+ case 'E': /* Error of some sort */
+ warning ("Remote failure reply: %s", buf);
+ continue;
+ case 'T': /* Status with PC, SP, FP, ... */
+ {
+ 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;
+ char *p_temp;
+
+ /* Read the register number */
+ regno = strtol ((const char *) p, &p_temp, 16);
+ p1 = (unsigned char *)p_temp;
+
+ if (p1 == p) /* No register number present here */
+ {
+ p1 = (unsigned char *) strchr ((const char *) p, ':');
+ if (p1 == NULL)
+ warning ("Malformed packet(a) (missing colon): %s\n\
+Packet: '%s'\n",
+ p, buf);
+ if (strncmp ((const char *) p, "thread", p1 - p) == 0)
+ {
+ p_temp = unpack_varlen_hex (++p1, &thread_num);
+ record_currthread (thread_num);
+ p = (unsigned char *) p_temp;
+ }
+ }
+ else
+ {
+ p = p1;
+
+ if (*p++ != ':')
+ warning ("Malformed packet(b) (missing colon): %s\n\
+Packet: '%s'\n",
+ p, buf);
+
+ if (regno >= NUM_REGS)
+ warning ("Remote sent bad register number %ld: %s\n\
+Packet: '%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;
+ }
+ supply_register (regno, regs);
+ }
+
+ if (*p++ != ';')
+ {
+ warning ("Remote register badly formatted: %s", buf);
+ warning (" here: %s",p);
+ }
+ }
+ }
+ /* fall through */
+ case 'S': /* Old style status, just signal only */
+ status->kind = TARGET_WAITKIND_STOPPED;
+ status->value.sig = (enum target_signal)
+ (((fromhex (buf[1])) << 4) + (fromhex (buf[2])));
+
+ goto got_status;
+ case 'W': /* Target exited */
+ {
+ /* The remote process exited. */
+ status->kind = TARGET_WAITKIND_EXITED;
+ status->value.integer = (fromhex (buf[1]) << 4) + fromhex (buf[2]);
+ goto got_status;
+ }
+ case 'X':
+ status->kind = TARGET_WAITKIND_SIGNALLED;
+ status->value.sig = (enum target_signal)
+ (((fromhex (buf[1])) << 4) + (fromhex (buf[2])));
+ kill_kludge = 1;
+
+ goto got_status;
+ case 'O': /* Console output */
+ remote_console_output (buf + 1);
+ continue;
+ case '\0':
+ if (last_sent_signal != TARGET_SIGNAL_0)
+ {
+ /* Zero length reply means that we tried 'S' or 'C' and
+ the remote system doesn't support it. */
+ target_terminal_ours_for_output ();
+ printf_filtered
+ ("Can't send signals to this remote system. %s not sent.\n",
+ target_signal_to_name (last_sent_signal));
+ last_sent_signal = TARGET_SIGNAL_0;
+ target_terminal_inferior ();
+
+ strcpy ((char *) buf, last_sent_step ? "s" : "c");
+ putpkt ((char *) buf);
+ continue;
+ }
+ /* else fallthrough */
+ default:
+ warning ("Invalid remote reply: %s", buf);
+ continue;
+ }
+ }
+ got_status:
+ if (thread_num != -1)
+ {
+ /* Initial thread value can only be acquired via wait, so deal with
+ this marker which is used before the first thread value is
+ acquired. */
+ if (inferior_pid == MAGIC_NULL_PID)
+ {
+ inferior_pid = thread_num;
+ if (!in_thread_list (inferior_pid))
+ add_thread (inferior_pid);
+ }
+ return thread_num;
+ }
+ return inferior_pid;
+}
+
+/* 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];
+
+ set_thread (inferior_pid, 1);
+
+ sprintf (buf, "g");
+ remote_send (buf);
+
+ if (remote_register_buf_size == 0)
+ remote_register_buf_size = strlen (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')
+ && buf[0] != 'x') /* New: unavailable register value */
+ {
+ if (remote_debug)
+ printf_unfiltered ("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;
+ }
+ if (p[0] == 'x' && p[1] == 'x')
+ regs[i] = 0; /* 'x' */
+ else
+ 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)]);
+ if (buf[REGISTER_BYTE(i) * 2] == 'x')
+ register_valid[i] = -1; /* register value not available */
+ }
+}
+
+/* Prepare to store registers. Since we may send them all (using a
+ 'G' request), 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 register REGNO, or all registers if REGNO == -1, from the contents
+ of REGISTERS. FIXME: ignores errors. */
+
+static void
+remote_store_registers (regno)
+ int regno;
+{
+ char buf[PBUFSIZ];
+ int i;
+ char *p;
+
+ set_thread (inferior_pid, 1);
+
+ if (regno >= 0 && stub_supports_P)
+ {
+ /* Try storing a single register. */
+ char *regp;
+
+ sprintf (buf, "P%x=", regno);
+ p = buf + strlen (buf);
+ regp = &registers[REGISTER_BYTE (regno)];
+ for (i = 0; i < REGISTER_RAW_SIZE (regno); ++i)
+ {
+ *p++ = tohex ((regp[i] >> 4) & 0xf);
+ *p++ = tohex (regp[i] & 0xf);
+ }
+ *p = '\0';
+ remote_send (buf);
+ if (buf[0] != '\0')
+ {
+ /* The stub understands the 'P' request. We are done. */
+ return;
+ }
+
+ /* The stub does not support the 'P' request. Use 'G' instead,
+ and don't try using 'P' in the future (it will just waste our
+ time). */
+ stub_supports_P = 0;
+ }
+
+ 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);
+}
+
+/* Use of the data cache *used* to be 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. Another idea would be to use the
+ executable file for the text segment (for all SEC_CODE sections?
+ For all SEC_READONLY sections?). This has problems if you want to
+ actually see what the memory contains (e.g. self-modifying code,
+ clobbered memory, user downloaded the wrong thing).
+
+ Because it speeds so much up, it's now enabled, if you're playing
+ with registers you turn it of (set remotecache 0). */
+
+/* Read a word from remote address ADDR and return it.
+ This goes through the data cache. */
+
+#if 0 /* unused? */
+static int
+remote_fetch_word (addr)
+ CORE_ADDR addr;
+{
+ 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 (unused?) */
+
+
+
+/* Return the number of hex digits in num. */
+
+static int
+hexnumlen (num)
+ ULONGEST num;
+{
+ int i;
+
+ for (i = 0; num != 0; i++)
+ num >>= 4;
+
+ return max (i, 1);
+}
+
+/* Set BUF to the hex digits representing NUM. */
+
+static int
+hexnumstr (buf, num)
+ char *buf;
+ ULONGEST num;
+{
+ int i;
+ int len = hexnumlen (num);
+
+ buf[len] = '\0';
+
+ for (i = len - 1; i >= 0; i--)
+ {
+ buf[i] = "0123456789abcdef" [(num & 0xf)];
+ num >>= 4;
+ }
+
+ return len;
+}
+
+/* Mask all but the least significant REMOTE_ADDRESS_SIZE bits. */
+
+static CORE_ADDR
+remote_address_masked (addr)
+ CORE_ADDR addr;
+{
+ if (remote_address_size > 0
+ && remote_address_size < (sizeof (ULONGEST) * 8))
+ {
+ /* Only create a mask when that mask can safely be constructed
+ in a ULONGEST variable. */
+ ULONGEST mask = 1;
+ mask = (mask << remote_address_size) - 1;
+ addr &= mask;
+ }
+ return addr;
+}
+
+/* Determine whether the remote target supports binary downloading.
+ This is accomplished by sending a no-op memory write of zero length
+ to the target at the specified address. It does not suffice to send
+ the whole packet, since many stubs strip the eighth bit and subsequently
+ compute a wrong checksum, which causes real havoc with remote_write_bytes. */
+static void
+check_binary_download (addr)
+ CORE_ADDR addr;
+{
+ if (remote_binary_download && !remote_binary_checked)
+ {
+ char buf[PBUFSIZ], *p;
+ remote_binary_checked = 1;
+
+ p = buf;
+ *p++ = 'X';
+ p += hexnumstr (p, (ULONGEST) addr);
+ *p++ = ',';
+ p += hexnumstr (p, (ULONGEST) 0);
+ *p++ = ':';
+ *p = '\0';
+
+ putpkt_binary (buf, (int) (p - buf));
+ getpkt (buf, 0);
+
+ if (buf[0] == '\0')
+ remote_binary_download = 0;
+ }
+
+ if (remote_debug)
+ {
+ if (remote_binary_download)
+ printf_unfiltered ("binary downloading suppported by target\n");
+ else
+ printf_unfiltered ("binary downloading NOT suppported by target\n");
+ }
+}
+
+/* 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;
+ char *myaddr;
+ int len;
+{
+ int max_buf_size; /* Max size of packet output buffer */
+ int origlen;
+
+ /* Verify that the target can support a binary download */
+ check_binary_download (memaddr);
+
+ /* Chop the transfer down if necessary */
+
+ max_buf_size = min (remote_write_size, PBUFSIZ);
+ if (remote_register_buf_size != 0)
+ max_buf_size = min (max_buf_size, remote_register_buf_size);
+
+ /* Subtract header overhead from max payload size - $M<memaddr>,<len>:#nn */
+ max_buf_size -= 2 + hexnumlen (memaddr + len - 1) + 1 + hexnumlen (len) + 4;
+
+ origlen = len;
+ while (len > 0)
+ {
+ unsigned char buf[PBUFSIZ];
+ unsigned char *p, *plen;
+ int todo;
+ int i;
+
+ /* construct "M"<memaddr>","<len>":" */
+ /* sprintf (buf, "M%lx,%x:", (unsigned long) memaddr, todo); */
+ memaddr = remote_address_masked (memaddr);
+ p = buf;
+ if (remote_binary_download)
+ {
+ *p++ = 'X';
+ todo = min (len, max_buf_size);
+ }
+ else
+ {
+ *p++ = 'M';
+ todo = min (len, max_buf_size / 2); /* num bytes that will fit */
+ }
+
+ p += hexnumstr (p, (ULONGEST) memaddr);
+ *p++ = ',';
+
+ plen = p; /* remember where len field goes */
+ p += hexnumstr (p, (ULONGEST) todo);
+ *p++ = ':';
+ *p = '\0';
+
+ /* We send target system values byte by byte, in increasing byte
+ addresses, each byte encoded as two hex characters (or one
+ binary character). */
+ if (remote_binary_download)
+ {
+ int escaped = 0;
+ for (i = 0;
+ (i < todo) && (i + escaped) < (max_buf_size - 2);
+ i++)
+ {
+ switch (myaddr[i] & 0xff)
+ {
+ case '$':
+ case '#':
+ case 0x7d:
+ /* These must be escaped */
+ escaped++;
+ *p++ = 0x7d;
+ *p++ = (myaddr[i] & 0xff) ^ 0x20;
+ break;
+ default:
+ *p++ = myaddr[i] & 0xff;
+ break;
+ }
+ }
+
+ if (i < todo)
+ {
+ /* Escape chars have filled up the buffer prematurely,
+ and we have actually sent fewer bytes than planned.
+ Fix-up the length field of the packet. */
+
+ /* FIXME: will fail if new len is a shorter string than
+ old len. */
+
+ plen += hexnumstr (plen, (ULONGEST) i);
+ *plen++ = ':';
+ }
+ }
+ else
+ {
+ for (i = 0; i < todo; i++)
+ {
+ *p++ = tohex ((myaddr[i] >> 4) & 0xf);
+ *p++ = tohex (myaddr[i] & 0xf);
+ }
+ *p = '\0';
+ }
+
+ putpkt_binary (buf, (int) (p - 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;
+ }
+
+ /* Increment by i, not by todo, in case escape chars
+ caused us to send fewer bytes than we'd planned. */
+ myaddr += i;
+ memaddr += i;
+ len -= i;
+ }
+ return origlen;
+}
+
+/* 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;
+ char *myaddr;
+ int len;
+{
+ int max_buf_size; /* Max size of packet output buffer */
+ int origlen;
+
+ /* Chop the transfer down if necessary */
+
+ max_buf_size = min (remote_write_size, PBUFSIZ);
+ if (remote_register_buf_size != 0)
+ max_buf_size = min (max_buf_size, remote_register_buf_size);
+
+ origlen = len;
+ while (len > 0)
+ {
+ char buf[PBUFSIZ];
+ char *p;
+ int todo;
+ int i;
+
+ todo = min (len, max_buf_size / 2); /* num bytes that will fit */
+
+ /* construct "m"<memaddr>","<len>" */
+ /* sprintf (buf, "m%lx,%x", (unsigned long) memaddr, todo); */
+ memaddr = remote_address_masked (memaddr);
+ p = buf;
+ *p++ = 'm';
+ p += hexnumstr (p, (ULONGEST) memaddr);
+ *p++ = ',';
+ p += hexnumstr (p, (ULONGEST) todo);
+ *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;
+ }
+
+ /* Reply describes memory byte by byte,
+ each byte encoded as two hex characters. */
+
+ p = buf;
+ for (i = 0; i < todo; 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. */
+ return i + (origlen - len);
+ myaddr[i] = fromhex (p[0]) * 16 + fromhex (p[1]);
+ p += 2;
+ }
+ myaddr += todo;
+ memaddr += todo;
+ len -= todo;
+ }
+ return origlen;
+}
+
+/* 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 */
+{
+#ifdef REMOTE_TRANSLATE_XFER_ADDRESS
+ CORE_ADDR targaddr;
+ int targlen;
+ REMOTE_TRANSLATE_XFER_ADDRESS (memaddr, len, targaddr, targlen);
+ if (targlen == 0)
+ return 0;
+ memaddr = targaddr;
+ len = targlen;
+#endif
+
+ return dcache_xfer_memory (remote_dcache, memaddr, myaddr,
+ len, should_write);
+}
+
+
+#if 0
+/* Enable after 4.12. */
+
+void
+remote_search (len, data, mask, startaddr, increment, lorange, hirange
+ addr_found, data_found)
+ int len;
+ char *data;
+ char *mask;
+ CORE_ADDR startaddr;
+ int increment;
+ CORE_ADDR lorange;
+ CORE_ADDR hirange;
+ CORE_ADDR *addr_found;
+ char *data_found;
+{
+ if (increment == -4 && len == 4)
+ {
+ long mask_long, data_long;
+ long data_found_long;
+ CORE_ADDR addr_we_found;
+ char buf[PBUFSIZ];
+ long returned_long[2];
+ char *p;
+
+ mask_long = extract_unsigned_integer (mask, len);
+ data_long = extract_unsigned_integer (data, len);
+ sprintf (buf, "t%x:%x,%x", startaddr, data_long, mask_long);
+ putpkt (buf);
+ getpkt (buf, 0);
+ if (buf[0] == '\0')
+ {
+ /* The stub doesn't support the 't' request. We might want to
+ remember this fact, but on the other hand the stub could be
+ switched on us. Maybe we should remember it only until
+ the next "target remote". */
+ generic_search (len, data, mask, startaddr, increment, lorange,
+ hirange, addr_found, data_found);
+ return;
+ }
+
+ 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 use EIO. */
+ memory_error (EIO, startaddr);
+ p = buf;
+ addr_we_found = 0;
+ while (*p != '\0' && *p != ',')
+ addr_we_found = (addr_we_found << 4) + fromhex (*p++);
+ if (*p == '\0')
+ error ("Protocol error: short return for search");
+
+ data_found_long = 0;
+ while (*p != '\0' && *p != ',')
+ data_found_long = (data_found_long << 4) + fromhex (*p++);
+ /* Ignore anything after this comma, for future extensions. */
+
+ if (addr_we_found < lorange || addr_we_found >= hirange)
+ {
+ *addr_found = 0;
+ return;
+ }
+
+ *addr_found = addr_we_found;
+ *data_found = store_unsigned_integer (data_we_found, len);
+ return;
+ }
+ generic_search (len, data, mask, startaddr, increment, lorange,
+ hirange, addr_found, data_found);
+}
+#endif /* 0 */
+
+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 (timeout)
+ int timeout;
+{
+ int ch;
+
+ ch = SERIAL_READCHAR (remote_desc, timeout);
+
+ switch (ch)
+ {
+ case SERIAL_EOF:
+ error ("Remote connection closed");
+ case SERIAL_ERROR:
+ perror_with_name ("Remote communication error");
+ case SERIAL_TIMEOUT:
+ return ch;
+ default:
+ 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);
+}
+
+/* Display a null-terminated packet on stdout, for debugging, using C
+ string notation. */
+
+static void
+print_packet (buf)
+ char *buf;
+{
+ puts_filtered ("\"");
+ while (*buf)
+ gdb_printchar (*buf++, gdb_stdout, '"');
+ puts_filtered ("\"");
+}
+
+int
+putpkt (buf)
+ char *buf;
+{
+ return putpkt_binary (buf, strlen (buf));
+}
+
+/* Send a packet to the remote machine, with error checking. The data
+ of the packet is in BUF. The string in BUF can be at most PBUFSIZ - 5
+ to account for the $, # and checksum, and for a possible /0 if we are
+ debugging (remote_debug) and want to print the sent packet as a string */
+
+static int
+putpkt_binary (buf, cnt)
+ char *buf;
+ int cnt;
+{
+ int i;
+ unsigned char csum = 0;
+ char buf2[PBUFSIZ];
+ int ch;
+ int tcount = 0;
+ char *p;
+
+ /* Copy the packet into buffer BUF2, encapsulating it
+ and giving it a checksum. */
+
+ if (cnt > (int) 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)
+ {
+ int started_error_output = 0;
+
+ if (remote_debug)
+ {
+ *p = '\0';
+ printf_unfiltered ("Sending packet: %s...", buf2);
+ gdb_flush (gdb_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 (remote_timeout);
+
+ if (remote_debug)
+ {
+ switch (ch)
+ {
+ case '+':
+ case SERIAL_TIMEOUT:
+ case '$':
+ if (started_error_output)
+ {
+ putchar_unfiltered ('\n');
+ started_error_output = 0;
+ }
+ }
+ }
+
+ switch (ch)
+ {
+ case '+':
+ if (remote_debug)
+ printf_unfiltered ("Ack\n");
+ return 1;
+ case SERIAL_TIMEOUT:
+ tcount ++;
+ if (tcount > 3)
+ return 0;
+ break; /* Retransmit buffer */
+ case '$':
+ {
+ char junkbuf[PBUFSIZ];
+
+ /* It's probably an old response, and we're out of sync.
+ Just gobble up the packet and ignore it. */
+ getpkt (junkbuf, 0);
+ continue; /* Now, go look for + */
+ }
+ default:
+ if (remote_debug)
+ {
+ if (!started_error_output)
+ {
+ started_error_output = 1;
+ printf_unfiltered ("putpkt: Junk: ");
+ }
+ putchar_unfiltered (ch & 0177);
+ }
+ continue;
+ }
+ break; /* Here to retransmit */
+ }
+
+#if 0
+ /* This is wrong. If doing a long backtrace, the user should be
+ able to get out next time we call QUIT, without anything as
+ violent as interrupt_query. If we want to provide a way out of
+ here without getting to the next QUIT, it should be based on
+ hitting ^C twice as in remote_wait. */
+ if (quit_flag)
+ {
+ quit_flag = 0;
+ interrupt_query ();
+ }
+#endif
+ }
+}
+
+/* Come here after finding the start of the frame. Collect the rest
+ into BUF, verifying the checksum, length, and handling run-length
+ compression. Returns 0 on any error, 1 on success. */
+
+static int
+read_frame (buf)
+ char *buf;
+{
+ unsigned char csum;
+ char *bp;
+ int c;
+
+ csum = 0;
+ bp = buf;
+
+ while (1)
+ {
+ c = readchar (remote_timeout);
+
+ switch (c)
+ {
+ case SERIAL_TIMEOUT:
+ if (remote_debug)
+ puts_filtered ("Timeout in mid-packet, retrying\n");
+ return 0;
+ case '$':
+ if (remote_debug)
+ puts_filtered ("Saw new packet start in middle of old one\n");
+ return 0; /* Start a new packet, count retries */
+ case '#':
+ {
+ unsigned char pktcsum;
+
+ *bp = '\000';
+
+ pktcsum = fromhex (readchar (remote_timeout)) << 4;
+ pktcsum |= fromhex (readchar (remote_timeout));
+
+ if (csum == pktcsum)
+ return 1;
+
+ if (remote_debug)
+ {
+ printf_filtered ("Bad checksum, sentsum=0x%x, csum=0x%x, buf=",
+ pktcsum, csum);
+ puts_filtered (buf);
+ puts_filtered ("\n");
+ }
+ return 0;
+ }
+ case '*': /* Run length encoding */
+ csum += c;
+ c = readchar (remote_timeout);
+ csum += c;
+ c = c - ' ' + 3; /* Compute repeat count */
+
+
+ if (c > 0 && c < 255 && bp + c - 1 < buf + PBUFSIZ - 1)
+ {
+ memset (bp, *(bp - 1), c);
+ bp += c;
+ continue;
+ }
+
+ *bp = '\0';
+ printf_filtered ("Repeat count %d too large for buffer: ", c);
+ puts_filtered (buf);
+ puts_filtered ("\n");
+ return 0;
+
+ default:
+ if (bp < buf + PBUFSIZ - 1)
+ {
+ *bp++ = c;
+ csum += c;
+ continue;
+ }
+
+ *bp = '\0';
+ puts_filtered ("Remote packet too long: ");
+ puts_filtered (buf);
+ puts_filtered ("\n");
+
+ return 0;
+ }
+ }
+}
+
+/* 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. */
+
+void
+getpkt (buf, forever)
+ char *buf;
+ int forever;
+{
+ int c;
+ int tries;
+ int timeout;
+ int val;
+
+ strcpy (buf,"timeout");
+
+ if (forever)
+ {
+#ifdef MAINTENANCE_CMDS
+ timeout = watchdog > 0 ? watchdog : -1;
+#else
+ timeout = -1;
+#endif
+ }
+
+ else
+ timeout = remote_timeout;
+
+#define MAX_TRIES 3
+
+ for (tries = 1; tries <= MAX_TRIES; tries++)
+ {
+ /* 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. */
+
+ /* Note that we will only wait forever prior to the start of a packet.
+ After that, we expect characters to arrive at a brisk pace. They
+ should show up within remote_timeout intervals. */
+
+ do
+ {
+ c = readchar (timeout);
+
+ if (c == SERIAL_TIMEOUT)
+ {
+#ifdef MAINTENANCE_CMDS
+ if (forever) /* Watchdog went off. Kill the target. */
+ {
+ target_mourn_inferior ();
+ error ("Watchdog has expired. Target detached.\n");
+ }
+#endif
+ if (remote_debug)
+ puts_filtered ("Timed out.\n");
+ goto retry;
+ }
+ }
+ while (c != '$');
+
+ /* We've found the start of a packet, now collect the data. */
+
+ val = read_frame (buf);
+
+ if (val == 1)
+ {
+ if (remote_debug)
+ fprintf_unfiltered (gdb_stdout, "Packet received: %s\n", buf);
+ SERIAL_WRITE (remote_desc, "+", 1);
+ return;
+ }
+
+ /* Try the whole thing again. */
+ retry:
+ SERIAL_WRITE (remote_desc, "-", 1);
+ }
+
+ /* We have tried hard enough, and just can't receive the packet. Give up. */
+
+ printf_unfiltered ("Ignoring packet error, continuing...\n");
+ SERIAL_WRITE (remote_desc, "+", 1);
+}
+
+static void
+remote_kill ()
+{
+ /* For some mysterious reason, wait_for_inferior calls kill instead of
+ mourn after it gets TARGET_WAITKIND_SIGNALLED. Work around it. */
+ if (kill_kludge)
+ {
+ kill_kludge = 0;
+ target_mourn_inferior ();
+ return;
+ }
+
+ /* Use catch_errors so the user can quit from gdb even when we aren't on
+ speaking terms with the remote system. */
+ catch_errors ((catch_errors_ftype *) putpkt, "k", "", RETURN_MASK_ERROR);
+
+ /* 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 ()
+{
+ remote_mourn_1 (&remote_ops);
+}
+
+static void
+extended_remote_mourn ()
+{
+ /* We do _not_ want to mourn the target like this; this will
+ remove the extended remote target from the target stack,
+ and the next time the user says "run" it'll fail.
+
+ FIXME: What is the right thing to do here? */
+#if 0
+ remote_mourn_1 (&extended_remote_ops);
+#endif
+}
+
+/* Worker function for remote_mourn. */
+static void
+remote_mourn_1 (target)
+ struct target_ops *target;
+{
+ unpush_target (target);
+ generic_mourn_inferior ();
+}
+
+/* In the extended protocol we want to be able to do things like
+ "run" and have them basically work as expected. So we need
+ a special create_inferior function.
+
+ FIXME: One day add support for changing the exec file
+ we're debugging, arguments and an environment. */
+
+static void
+extended_remote_create_inferior (exec_file, args, env)
+ char *exec_file;
+ char *args;
+ char **env;
+{
+ /* Rip out the breakpoints; we'll reinsert them after restarting
+ the remote server. */
+ remove_breakpoints ();
+
+ /* Now restart the remote server. */
+ extended_remote_restart ();
+
+ /* Now put the breakpoints back in. This way we're safe if the
+ restart function works via a unix fork on the remote side. */
+ insert_breakpoints ();
+
+ /* Clean up from the last time we were running. */
+ clear_proceed_status ();
+
+ /* Let the remote process run. */
+ proceed (-1, TARGET_SIGNAL_0, 0);
+}
+
+
+/* On some machines, e.g. 68k, we may use a different breakpoint instruction
+ than other targets; in those use REMOTE_BREAKPOINT instead of just
+ BREAKPOINT. Also, bi-endian targets may define LITTLE_REMOTE_BREAKPOINT
+ and BIG_REMOTE_BREAKPOINT. If none of these are defined, we just call
+ the standard routines that are in mem-break.c. */
+
+/* FIXME, these ought to be done in a more dynamic fashion. For instance,
+ the choice of breakpoint instruction affects target program design and
+ vice versa, and by making it user-tweakable, the special code here
+ goes away and we need fewer special GDB configurations. */
+
+#if defined (LITTLE_REMOTE_BREAKPOINT) && defined (BIG_REMOTE_BREAKPOINT) && !defined(REMOTE_BREAKPOINT)
+#define REMOTE_BREAKPOINT
+#endif
+
+#ifdef REMOTE_BREAKPOINT
+
+/* If the target isn't bi-endian, just pretend it is. */
+#if !defined (LITTLE_REMOTE_BREAKPOINT) && !defined (BIG_REMOTE_BREAKPOINT)
+#define LITTLE_REMOTE_BREAKPOINT REMOTE_BREAKPOINT
+#define BIG_REMOTE_BREAKPOINT REMOTE_BREAKPOINT
+#endif
+
+static unsigned char big_break_insn[] = BIG_REMOTE_BREAKPOINT;
+static unsigned char little_break_insn[] = LITTLE_REMOTE_BREAKPOINT;
+
+#endif /* 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;
+{
+#ifdef REMOTE_BREAKPOINT
+ int val;
+
+ val = target_read_memory (addr, contents_cache, sizeof big_break_insn);
+
+ if (val == 0)
+ {
+ if (TARGET_BYTE_ORDER == BIG_ENDIAN)
+ val = target_write_memory (addr, (char *) big_break_insn,
+ sizeof big_break_insn);
+ else
+ val = target_write_memory (addr, (char *) little_break_insn,
+ sizeof little_break_insn);
+ }
+
+ return val;
+#else
+ return memory_insert_breakpoint (addr, contents_cache);
+#endif /* REMOTE_BREAKPOINT */
+}
+
+static int
+remote_remove_breakpoint (addr, contents_cache)
+ CORE_ADDR addr;
+ char *contents_cache;
+{
+#ifdef REMOTE_BREAKPOINT
+ return target_write_memory (addr, contents_cache, sizeof big_break_insn);
+#else
+ return memory_remove_breakpoint (addr, contents_cache);
+#endif /* REMOTE_BREAKPOINT */
+}
+
+/* Some targets are only capable of doing downloads, and afterwards
+ they switch to the remote serial protocol. This function provides
+ a clean way to get from the download target to the remote target.
+ It's basically just a wrapper so that we don't have to expose any
+ of the internal workings of remote.c.
+
+ Prior to calling this routine, you should shutdown the current
+ target code, else you will get the "A program is being debugged
+ already..." message. Usually a call to pop_target() suffices. */
+
+void
+push_remote_target (name, from_tty)
+ char *name;
+ int from_tty;
+{
+ printf_filtered ("Switching to remote protocol\n");
+ remote_open (name, from_tty);
+}
+
+/* Other targets want to use the entire remote serial module but with
+ certain remote_ops overridden. */
+
+void
+open_remote_target (name, from_tty, target, extended_p)
+ char *name;
+ int from_tty;
+ struct target_ops *target;
+ int extended_p;
+{
+ printf_filtered ("Selecting the %sremote protocol\n",
+ (extended_p ? "extended-" : ""));
+ remote_open_1 (name, from_tty, target, extended_p);
+}
+
+/* Table used by the crc32 function to calcuate the checksum. */
+
+static unsigned long crc32_table[256] = {0, 0};
+
+static unsigned long
+crc32 (buf, len, crc)
+ unsigned char *buf;
+ int len;
+ unsigned int crc;
+{
+ if (! crc32_table[1])
+ {
+ /* Initialize the CRC table and the decoding table. */
+ int i, j;
+ unsigned int c;
+
+ for (i = 0; i < 256; i++)
+ {
+ for (c = i << 24, j = 8; j > 0; --j)
+ c = c & 0x80000000 ? (c << 1) ^ 0x04c11db7 : (c << 1);
+ crc32_table[i] = c;
+ }
+ }
+
+ while (len--)
+ {
+ crc = (crc << 8) ^ crc32_table[((crc >> 24) ^ *buf) & 255];
+ buf++;
+ }
+ return crc;
+}
+
+/* compare-sections command
+
+ With no arguments, compares each loadable section in the exec bfd
+ with the same memory range on the target, and reports mismatches.
+ Useful for verifying the image on the target against the exec file.
+ Depends on the target understanding the new "qCRC:" request. */
+
+static void
+compare_sections_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ asection *s;
+ unsigned long host_crc, target_crc;
+ extern bfd *exec_bfd;
+ struct cleanup *old_chain;
+ char *tmp, *sectdata, *sectname, buf[PBUFSIZ];
+ bfd_size_type size;
+ bfd_vma lma;
+ int matched = 0;
+ int mismatched = 0;
+
+ if (!exec_bfd)
+ error ("command cannot be used without an exec file");
+ if (!current_target.to_shortname ||
+ strcmp (current_target.to_shortname, "remote") != 0)
+ error ("command can only be used with remote target");
+
+ for (s = exec_bfd->sections; s; s = s->next)
+ {
+ if (!(s->flags & SEC_LOAD))
+ continue; /* skip non-loadable section */
+
+ size = bfd_get_section_size_before_reloc (s);
+ if (size == 0)
+ continue; /* skip zero-length section */
+
+ sectname = (char *) bfd_get_section_name (exec_bfd, s);
+ if (args && strcmp (args, sectname) != 0)
+ continue; /* not the section selected by user */
+
+ matched = 1; /* do this section */
+ lma = s->lma;
+ /* FIXME: assumes lma can fit into long */
+ sprintf (buf, "qCRC:%lx,%lx", (long) lma, (long) size);
+ putpkt (buf);
+
+ /* be clever; compute the host_crc before waiting for target reply */
+ sectdata = xmalloc (size);
+ old_chain = make_cleanup (free, sectdata);
+ bfd_get_section_contents (exec_bfd, s, sectdata, 0, size);
+ host_crc = crc32 ((unsigned char *) sectdata, size, 0xffffffff);
+
+ getpkt (buf, 0);
+ if (buf[0] == 'E')
+ error ("target memory fault, section %s, range 0x%08x -- 0x%08x",
+ sectname, lma, lma + size);
+ if (buf[0] != 'C')
+ error ("remote target does not support this operation");
+
+ for (target_crc = 0, tmp = &buf[1]; *tmp; tmp++)
+ target_crc = target_crc * 16 + fromhex (*tmp);
+
+ printf_filtered ("Section %s, range 0x%08x -- 0x%08x: ",
+ sectname, lma, lma + size);
+ if (host_crc == target_crc)
+ printf_filtered ("matched.\n");
+ else
+ {
+ printf_filtered ("MIS-MATCHED!\n");
+ mismatched++;
+ }
+
+ do_cleanups (old_chain);
+ }
+ if (mismatched > 0)
+ warning ("One or more sections of the remote executable does not match\n\
+the loaded file\n");
+ if (args && !matched)
+ printf_filtered ("No loaded section named '%s'.\n", args);
+}
+
+static int
+remote_query (query_type, buf, outbuf, bufsiz)
+ int query_type;
+ char *buf;
+ char *outbuf;
+ int *bufsiz;
+{
+ int i;
+ char buf2[PBUFSIZ];
+ char *p2 = &buf2[0];
+ char *p = buf;
+
+ if (! bufsiz)
+ error ("null pointer to remote bufer size specified");
+
+ /* minimum outbuf size is PBUFSIZE - if bufsiz is not large enough let
+ the caller know and return what the minimum size is */
+ /* Note: a zero bufsiz can be used to query the minimum buffer size */
+ if ( *bufsiz < PBUFSIZ )
+ {
+ *bufsiz = PBUFSIZ;
+ return -1;
+ }
+
+ /* except for querying the minimum buffer size, target must be open */
+ if (! remote_desc)
+ error ("remote query is only available after target open");
+
+ /* we only take uppercase letters as query types, at least for now */
+ if ( (query_type < 'A') || (query_type > 'Z') )
+ error ("invalid remote query type");
+
+ if (! buf)
+ error ("null remote query specified");
+
+ if (! outbuf)
+ error ("remote query requires a buffer to receive data");
+
+ outbuf[0] = '\0';
+
+ *p2++ = 'q';
+ *p2++ = query_type;
+
+ /* we used one buffer char for the remote protocol q command and another
+ for the query type. As the remote protocol encapsulation uses 4 chars
+ plus one extra in case we are debugging (remote_debug),
+ we have PBUFZIZ - 7 left to pack the query string */
+ i = 0;
+ while ( buf[i] && (i < (PBUFSIZ - 8)) )
+ {
+ /* bad caller may have sent forbidden characters */
+ if ( (!isprint(buf[i])) || (buf[i] == '$') || (buf[i] == '#') )
+ error ("illegal characters in query string");
+
+ *p2++ = buf[i];
+ i++;
+ }
+ *p2 = buf[i];
+
+ if ( buf[i] )
+ error ("query larger than available buffer");
+
+ i = putpkt (buf2);
+ if ( i < 0 ) return i;
+
+ getpkt (outbuf, 0);
+
+ return 0;
+}
+
+static void
+packet_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ char buf[PBUFSIZ];
+
+ if (! remote_desc)
+ error ("command can only be used with remote target");
+
+ if (! args)
+ error ("remote-packet command requires packet text as argument");
+
+ puts_filtered ("sending: ");
+ print_packet (args);
+ puts_filtered ("\n");
+ putpkt (args);
+
+ getpkt (buf, 0);
+ puts_filtered ("received: ");
+ print_packet (buf);
+ puts_filtered ("\n");
+}
+
+#if 0
+/* --------- UNIT_TEST for THREAD oriented PACKETS ------------------------- */
+
+static void display_thread_info PARAMS ((struct gdb_ext_thread_info *info));
+
+static void threadset_test_cmd PARAMS ((char *cmd, int tty));
+
+static void threadalive_test PARAMS ((char *cmd, int tty));
+
+static void threadlist_test_cmd PARAMS ((char *cmd, int tty));
+
+int get_and_display_threadinfo PARAMS ((threadref *ref));
+
+static void threadinfo_test_cmd PARAMS ((char *cmd, int tty));
+
+static int thread_display_step PARAMS ((threadref *ref, void *context));
+
+static void threadlist_update_test_cmd PARAMS ((char *cmd, int tty));
+
+static void init_remote_threadtests PARAMS ((void));
+
+#define SAMPLE_THREAD 0x05060708 /* Truncated 64 bit threadid */
+
+static void
+threadset_test_cmd (cmd, tty)
+ char *cmd;
+ int tty;
+{
+ int sample_thread = SAMPLE_THREAD;
+
+ printf_filtered ("Remote threadset test\n");
+ set_thread (sample_thread, 1);
+}
+
+
+static void
+threadalive_test (cmd, tty)
+ char *cmd;
+ int tty;
+{
+ int sample_thread = SAMPLE_THREAD;
+
+ if (remote_thread_alive (sample_thread))
+ printf_filtered ("PASS: Thread alive test\n");
+ else
+ printf_filtered ("FAIL: Thread alive test\n");
+}
+
+void output_threadid PARAMS ((char *title, threadref * ref));
+
+void
+output_threadid (title, ref)
+ char *title;
+ threadref *ref;
+{
+ char hexid[20];
+
+ pack_threadid (&hexid[0], ref); /* Convert threead id into hex */
+ hexid[16] = 0;
+ printf_filtered ("%s %s\n", title, (&hexid[0]));
+}
+
+static void
+threadlist_test_cmd (cmd, tty)
+ char *cmd;
+ int tty;
+{
+ int startflag = 1;
+ threadref nextthread;
+ int done, result_count;
+ threadref threadlist[3];
+
+ printf_filtered ("Remote Threadlist test\n");
+ if (!remote_get_threadlist (startflag, &nextthread, 3, &done,
+ &result_count, &threadlist[0]))
+ printf_filtered ("FAIL: threadlist test\n");
+ else
+ {
+ threadref *scan = threadlist;
+ threadref *limit = scan + result_count;
+
+ while (scan < limit)
+ output_threadid (" thread ", scan++);
+ }
+}
+
+void
+display_thread_info (info)
+ struct gdb_ext_thread_info *info;
+{
+ output_threadid ("Threadid: ", &info->threadid);
+ printf_filtered ("Name: %s\n ", info->shortname);
+ printf_filtered ("State: %s\n", info->display);
+ printf_filtered ("other: %s\n\n", info->more_display);
+}
+
+int
+get_and_display_threadinfo (ref)
+ threadref *ref;
+{
+ int result;
+ int set;
+ struct gdb_ext_thread_info threadinfo;
+
+ set = TAG_THREADID | TAG_EXISTS | TAG_THREADNAME
+ | TAG_MOREDISPLAY | TAG_DISPLAY;
+ if (0 != (result = remote_get_threadinfo (ref, set, &threadinfo)))
+ display_thread_info (&threadinfo);
+ return result;
+}
+
+static void
+threadinfo_test_cmd (cmd, tty)
+ char *cmd;
+ int tty;
+{
+ int athread = SAMPLE_THREAD;
+ threadref thread;
+ int set;
+
+ int_to_threadref (&thread, athread);
+ printf_filtered ("Remote Threadinfo test\n");
+ if (!get_and_display_threadinfo (&thread))
+ printf_filtered ("FAIL cannot get thread info\n");
+}
+
+static int
+thread_display_step (ref, context)
+ threadref *ref;
+ void *context;
+{
+ /* output_threadid(" threadstep ",ref); *//* simple test */
+ return get_and_display_threadinfo (ref);
+}
+
+static void
+threadlist_update_test_cmd (cmd, tty)
+ char *cmd;
+ int tty;
+{
+ printf_filtered ("Remote Threadlist update test\n");
+ remote_threadlist_iterator (thread_display_step, 0, CRAZY_MAX_THREADS);
+}
+
+static void
+init_remote_threadtests (void)
+{
+ add_com ("tlist", class_obscure, threadlist_test_cmd,
+ "Fetch and print the remote list of thread identifiers, one pkt only");
+ add_com ("tinfo", class_obscure, threadinfo_test_cmd,
+ "Fetch and display info about one thread");
+ add_com ("tset", class_obscure, threadset_test_cmd,
+ "Test setting to a different thread");
+ add_com ("tupd", class_obscure, threadlist_update_test_cmd,
+ "Iterate through updating all remote thread info");
+ add_com ("talive", class_obscure, threadalive_test,
+ " Remote thread alive test ");
+}
+
+#endif /* 0 */
+
+static void
+init_remote_ops ()
+{
+ remote_ops.to_shortname = "remote";
+ remote_ops.to_longname = "Remote serial target in gdb-specific protocol";
+ remote_ops.to_doc =
+ "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).";
+ remote_ops.to_open = remote_open;
+ remote_ops.to_close = remote_close;
+ remote_ops.to_detach = remote_detach;
+ remote_ops.to_resume = remote_resume;
+ remote_ops.to_wait = remote_wait;
+ remote_ops.to_fetch_registers = remote_fetch_registers;
+ remote_ops.to_store_registers = remote_store_registers;
+ remote_ops.to_prepare_to_store = remote_prepare_to_store;
+ remote_ops.to_xfer_memory = remote_xfer_memory;
+ remote_ops.to_files_info = remote_files_info;
+ remote_ops.to_insert_breakpoint = remote_insert_breakpoint;
+ remote_ops.to_remove_breakpoint = remote_remove_breakpoint;
+ remote_ops.to_kill = remote_kill;
+ remote_ops.to_load = generic_load;
+ remote_ops.to_mourn_inferior = remote_mourn;
+ remote_ops.to_thread_alive = remote_thread_alive;
+ remote_ops.to_stop = remote_stop;
+ remote_ops.to_query = remote_query;
+ remote_ops.to_stratum = process_stratum;
+ remote_ops.to_has_all_memory = 1;
+ remote_ops.to_has_memory = 1;
+ remote_ops.to_has_stack = 1;
+ remote_ops.to_has_registers = 1;
+ remote_ops.to_has_execution = 1;
+ remote_ops.to_has_thread_control = tc_schedlock; /* can lock scheduler */
+ remote_ops.to_magic = OPS_MAGIC;
+}
+
+/* Set up the extended remote vector by making a copy of the standard
+ remote vector and adding to it. */
+
+static void
+init_extended_remote_ops ()
+{
+ extended_remote_ops = remote_ops;
+
+ extended_remote_ops.to_shortname = "extended-remote";
+ extended_remote_ops.to_longname =
+ "Extended remote serial target in gdb-specific protocol";
+ extended_remote_ops.to_doc =
+ "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).",
+ extended_remote_ops.to_open = extended_remote_open;
+ extended_remote_ops.to_create_inferior = extended_remote_create_inferior;
+ extended_remote_ops.to_mourn_inferior = extended_remote_mourn;
+}
+
+void
+_initialize_remote ()
+{
+ init_remote_ops ();
+ add_target (&remote_ops);
+
+ init_extended_remote_ops ();
+ add_target (&extended_remote_ops);
+ init_remote_threads ();
+#if 0
+ init_remote_threadtests ();
+#endif
+
+ add_cmd ("compare-sections", class_obscure, compare_sections_command,
+ "Compare section data on target to the exec file.\n\
+Argument is a single section name (default: all loaded sections).",
+ &cmdlist);
+
+ add_cmd ("packet", class_maintenance, packet_command,
+ "Send an arbitrary packet to a remote target.\n\
+ maintenance packet TEXT\n\
+If GDB is talking to an inferior via the GDB serial protocol, then\n\
+this command sends the string TEXT to the inferior, and displays the\n\
+response packet. GDB supplies the initial `$' character, and the\n\
+terminating `#' character and checksum.",
+ &maintenancelist);
+
+ add_show_from_set
+ (add_set_cmd ("remotetimeout", no_class,
+ var_integer, (char *)&remote_timeout,
+ "Set timeout value for remote read.\n",
+ &setlist),
+ &showlist);
+
+ add_show_from_set
+ (add_set_cmd ("remotebreak", no_class,
+ var_integer, (char *)&remote_break,
+ "Set whether to send break if interrupted.\n",
+ &setlist),
+ &showlist);
+
+ add_show_from_set
+ (add_set_cmd ("remotewritesize", no_class,
+ var_integer, (char *)&remote_write_size,
+ "Set the maximum number of bytes per memory write packet.\n",
+ &setlist),
+ &showlist);
+
+ remote_address_size = TARGET_PTR_BIT;
+ add_show_from_set
+ (add_set_cmd ("remoteaddresssize", class_obscure,
+ var_integer, (char *)&remote_address_size,
+ "Set the maximum size of the address (in bits) \
+in a memory packet.\n",
+ &setlist),
+ &showlist);
+
+ add_show_from_set (add_set_cmd ("remotebinarydownload", no_class,
+ var_boolean, (char *) &remote_binary_download,
+ "Set binary downloads.\n", &setlist),
+ &showlist);
+}
diff --git a/gdb/reply_mig_hack.awk b/gdb/reply_mig_hack.awk
new file mode 100644
index 00000000000..310a40cbb9b
--- /dev/null
+++ b/gdb/reply_mig_hack.awk
@@ -0,0 +1,123 @@
+# Reply server mig-output massager
+#
+# Copyright (C) 1995 Free Software Foundation, Inc.
+#
+# Written by Miles Bader <miles@gnu.ai.mit.edu>
+#
+# This program is free software; you can redistribute 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.
+#
+# This awk script hacks the output of mig-generated reply server code
+# so that it allows replies with just the error-code in them (as this is
+# how mig returns errors).
+#
+# It is highly, highly, dependent on the exact format of mig output. Ick.
+#
+
+BEGIN { parse_phase = 0; }
+
+/^}/ { parse_phase = 0; }
+
+parse_phase == 0 && /^mig_internal void _X[a-zA-Z0-9_]*_reply/ {
+ # The start of a mig server routine. Reset everything. Note that we only
+ # mess with rpcs that have the suffix `_reply'.
+ num_args = 0;
+ num_checks = 0;
+ parse_phase = 1;
+ print; next;
+}
+
+parse_phase == 1 && /^[\t ]*typedef struct/ {
+ # The first structure in the server routine should describe the arguments
+ parse_phase = 2;
+ print; next;
+}
+
+parse_phase == 2 {
+ # The message header field in the args structure, which skip.
+ parse_phase = 3;
+ print; next;
+}
+
+parse_phase == 3 && /}/ {
+ # The args structure is over.
+ if (num_args > 1)
+ parse_phase = 5;
+ else
+ # There's no extra args that could screw up the normal mechanism for
+ # error returns, so we don't have to insert any new code.
+ parse_phase = 0;
+ print; next;
+}
+
+parse_phase == 3 {
+ # The type field for an argument.
+ arg_type_code_name[num_args] = $2;
+ sub (/;$/, "", arg_type_code_name[num_args]) # Get rid of the semi-colon
+ parse_phase = 4;
+ print; next;
+}
+
+parse_phase == 4 {
+ # The value field for an argument.
+ arg_name[num_args] = $2;
+ sub (/;$/, "", arg_name[num_args]) # Get rid of the semi-colon
+ arg_type[num_args] = $1;
+ num_args++;
+ parse_phase = 3;
+ print; next;
+}
+
+parse_phase == 5 && /^[ \t]*static const mach_msg_type_t/ {
+ # The type check structure for an argument.
+ arg_check_name[num_checks] = $4;
+ num_checks++;
+ print; next;
+}
+
+parse_phase == 5 && /^[ \t]*mig_external kern_return_t/ {
+ # The declaration of the user server function for this rpc.
+ user_function_name = $3;
+ print; next;
+}
+
+parse_phase == 5 && /^#if[ \t]TypeCheck/ {
+ # The first args type checking statement; we need to insert our chunk of
+ # code that bypasses all the type checks if this is an error return, after
+ # which we're done until we get to the next function. Handily, the size
+ # of mig's Reply structure is also the size of the alternate Request
+ # structure that we want to check for.
+ print "\tif (In0P->Head.msgh_size == sizeof (Reply)";
+ print "\t && ! (In0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX)";
+ print "\t && *(int *)&In0P->" arg_type_code_name[0] " == *(int *)&" arg_check_name[0];
+ print "\t && In0P->" arg_name[0] " != 0)";
+ print "\t /* Error return, only the error code argument is passed. */";
+ print "\t {";
+ # Force the function into a type that only takes the first two args, via
+ # the temp variable SFUN (is there another way to correctly do this cast?).
+ # This is possibly bogus, but easier than supplying bogus values for all
+ # the other args (we can't just pass 0 for them, as they might not be scalar).
+ printf ("\t kern_return_t (*sfun)(mach_port_t");
+ for (i = 0; i < num_args; i++)
+ printf (", %s", arg_type[i]);
+ printf (") = %s;\n", user_function_name);
+ print "\t OutP->RetCode = (*(kern_return_t (*)(mach_port_t, kern_return_t))sfun) (In0P->Head.msgh_request_port, In0P->" arg_name[0] ");";
+ print "\t return;";
+ print "\t }";
+ print "";
+ parse_phase = 0;
+ print; next;
+}
+
+{ print; }
diff --git a/gdb/rom68k-rom.c b/gdb/rom68k-rom.c
new file mode 100644
index 00000000000..831d299652a
--- /dev/null
+++ b/gdb/rom68k-rom.c
@@ -0,0 +1,169 @@
+/* Remote target glue for the ROM68K ROM monitor.
+ Copyright 1988, 1991, 1992, 1993, 1994, 1995 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "gdbcore.h"
+#include "target.h"
+#include "monitor.h"
+#include "serial.h"
+
+static void rom68k_open PARAMS ((char *args, int from_tty));
+
+static void
+rom68k_supply_register (regname, regnamelen, val, vallen)
+ char *regname;
+ int regnamelen;
+ char *val;
+ int vallen;
+{
+ int numregs;
+ int regno;
+
+ numregs = 1;
+ regno = -1;
+
+ if (regnamelen == 2)
+ switch (regname[0])
+ {
+ case 'S':
+ if (regname[1] == 'R')
+ regno = PS_REGNUM;
+ break;
+ case 'P':
+ if (regname[1] == 'C')
+ regno = PC_REGNUM;
+ break;
+ case 'D':
+ if (regname[1] != 'R')
+ break;
+ regno = D0_REGNUM;
+ numregs = 8;
+ break;
+ case 'A':
+ if (regname[1] != 'R')
+ break;
+ regno = A0_REGNUM;
+ numregs = 7;
+ break;
+ }
+ else if (regnamelen == 3)
+ switch (regname[0])
+ {
+ case 'I':
+ if (regname[1] == 'S' && regname[2] == 'P')
+ regno = SP_REGNUM;
+ }
+
+ if (regno >= 0)
+ while (numregs-- > 0)
+ val = monitor_supply_register (regno++, val);
+}
+
+/* This array of registers need to match the indexes used by GDB.
+ This exists because the various ROM monitors use different strings
+ than does GDB, and don't necessarily support all the registers
+ either. So, typing "info reg sp" becomes a "r30". */
+
+static char *rom68k_regnames[NUM_REGS] = {
+ "D0", "D1", "D2", "D3", "D4", "D5", "D6", "D7",
+ "A0", "A1", "A2", "A3", "A4", "A5", "A6", "ISP",
+ "SR", "PC" };
+
+/* Define the monitor command strings. Since these are passed directly
+ through to a printf style function, we may include formatting
+ strings. We also need a CR or LF on the end. */
+
+static struct target_ops rom68k_ops;
+
+static char *rom68k_inits[] = {".\r\r", NULL}; /* Exits pm/pr & download cmds */
+
+static struct monitor_ops rom68k_cmds ;
+
+static void
+init_rom68k_cmds(void)
+{
+ rom68k_cmds.flags = 0;
+ rom68k_cmds.init = rom68k_inits; /* monitor init string */
+ rom68k_cmds.cont = "go\r";
+ rom68k_cmds.step = "st\r";
+ rom68k_cmds.stop = NULL;
+ rom68k_cmds.set_break = "db %x\r";
+ rom68k_cmds.clr_break = "cb %x\r";
+ rom68k_cmds.clr_all_break = "cb *\r";
+ rom68k_cmds.fill = "fm %x %x %x\r";
+ rom68k_cmds.setmem.cmdb = "pm %x %x\r";
+ rom68k_cmds.setmem.cmdw = "pm;w %x %x\r";
+ rom68k_cmds.setmem.cmdl = "pm;l %x %x\r";
+ rom68k_cmds.setmem.cmdll = NULL;
+ rom68k_cmds.setmem.resp_delim = NULL;
+ rom68k_cmds.setmem.term = NULL;
+ rom68k_cmds.setmem.term_cmd = NULL;
+ rom68k_cmds.getmem.cmdb = "dm %x %x\r";
+ rom68k_cmds.getmem.cmdw = "dm;w %x %x\r";
+ rom68k_cmds.getmem.cmdl = "dm;l %x %x\r";
+ rom68k_cmds.getmem.cmdll = NULL;
+ rom68k_cmds.getmem.resp_delim = " ";
+ rom68k_cmds.getmem.term = NULL;
+ rom68k_cmds.getmem.term_cmd = NULL;
+ rom68k_cmds.setreg.cmd = "pr %s %x\r";
+ rom68k_cmds.setreg.resp_delim = NULL;
+ rom68k_cmds.setreg.term = NULL;
+ rom68k_cmds.setreg.term_cmd = NULL ;
+ rom68k_cmds.getreg.cmd = "pr %s\r" ;
+ rom68k_cmds.getreg.resp_delim = ": " ;
+ rom68k_cmds.getreg.term = "= " ;
+ rom68k_cmds.getreg.term_cmd = ";\r" ;
+ rom68k_cmds.dump_registers = "dr\r" ;
+ rom68k_cmds.register_pattern =
+ "\\(\\w+\\)=\\([0-9a-fA-F]+\\( +[0-9a-fA-F]+\\b\\)*\\)" ;
+ rom68k_cmds.supply_register = rom68k_supply_register;
+ rom68k_cmds.load_routine = NULL;
+ rom68k_cmds.load = "dc\r";
+ rom68k_cmds.loadresp = "Waiting for S-records from host;.. ";
+ rom68k_cmds.prompt = "ROM68K :-> ";
+ rom68k_cmds.line_term = "\r";
+ rom68k_cmds.cmd_end = ";\r";
+ rom68k_cmds.target = &rom68k_ops;
+ rom68k_cmds.stopbits = SERIAL_1_STOPBITS;
+ rom68k_cmds.regnames = rom68k_regnames;
+ rom68k_cmds.magic = MONITOR_OPS_MAGIC ;
+} /* init_rom68k_cmds */
+
+static void
+rom68k_open (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ monitor_open (args, &rom68k_cmds, from_tty);
+}
+
+void
+_initialize_rom68k ()
+{
+ init_rom68k_cmds() ;
+ init_monitor_ops (&rom68k_ops);
+
+ rom68k_ops.to_shortname = "rom68k";
+ rom68k_ops.to_longname = "Rom68k debug monitor for the IDP Eval board";
+ rom68k_ops.to_doc = "Debug on a Motorola IDP eval board running the ROM68K monitor.\n\
+Specify the serial device it is connected to (e.g. /dev/ttya).";
+ rom68k_ops.to_open = rom68k_open;
+
+ add_target (&rom68k_ops);
+}
diff --git a/gdb/rs6000-nat.c b/gdb/rs6000-nat.c
new file mode 100644
index 00000000000..c74a36f1f97
--- /dev/null
+++ b/gdb/rs6000-nat.c
@@ -0,0 +1,845 @@
+/* IBM RS/6000 native-dependent code for GDB, the GNU debugger.
+ Copyright 1986, 1987, 1989, 1991, 1992, 1994, 1995, 1996, 1997, 1998
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "inferior.h"
+#include "target.h"
+#include "gdbcore.h"
+#include "xcoffsolib.h"
+#include "symfile.h"
+#include "objfiles.h"
+#include "libbfd.h" /* For bfd_cache_lookup (FIXME) */
+#include "bfd.h"
+#include "gdb-stabs.h"
+
+#include <sys/ptrace.h>
+#include <sys/reg.h>
+
+#include <sys/param.h>
+#include <sys/dir.h>
+#include <sys/user.h>
+#include <signal.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+
+#include <a.out.h>
+#include <sys/file.h>
+#include "gdb_stat.h"
+#include <sys/core.h>
+#include <sys/ldr.h>
+
+extern int errno;
+
+extern struct vmap * map_vmap PARAMS ((bfd *bf, bfd *arch));
+
+extern struct target_ops exec_ops;
+
+static void
+vmap_exec PARAMS ((void));
+
+static void
+vmap_ldinfo PARAMS ((struct ld_info *));
+
+static struct vmap *
+add_vmap PARAMS ((struct ld_info *));
+
+static int
+objfile_symbol_add PARAMS ((char *));
+
+static void
+vmap_symtab PARAMS ((struct vmap *));
+
+static void
+fetch_core_registers PARAMS ((char *, unsigned int, int, CORE_ADDR));
+
+static void
+exec_one_dummy_insn PARAMS ((void));
+
+extern void
+fixup_breakpoints PARAMS ((CORE_ADDR low, CORE_ADDR high, CORE_ADDR delta));
+
+/* Conversion from gdb-to-system special purpose register numbers.. */
+
+static int special_regs[] = {
+ IAR, /* PC_REGNUM */
+ MSR, /* PS_REGNUM */
+ CR, /* CR_REGNUM */
+ LR, /* LR_REGNUM */
+ CTR, /* CTR_REGNUM */
+ XER, /* XER_REGNUM */
+ MQ /* MQ_REGNUM */
+};
+
+void
+fetch_inferior_registers (regno)
+ int regno;
+{
+ int ii;
+ extern char registers[];
+
+ if (regno < 0) { /* for all registers */
+
+ /* read 32 general purpose registers. */
+
+ for (ii=0; ii < 32; ++ii)
+ *(int*)&registers[REGISTER_BYTE (ii)] =
+ ptrace (PT_READ_GPR, inferior_pid, (PTRACE_ARG3_TYPE) ii, 0, 0);
+
+ /* read general purpose floating point registers. */
+
+ for (ii=0; ii < 32; ++ii)
+ ptrace (PT_READ_FPR, inferior_pid,
+ (PTRACE_ARG3_TYPE) &registers [REGISTER_BYTE (FP0_REGNUM+ii)],
+ FPR0+ii, 0);
+
+ /* read special registers. */
+ for (ii=0; ii <= LAST_UISA_SP_REGNUM-FIRST_UISA_SP_REGNUM; ++ii)
+ *(int*)&registers[REGISTER_BYTE (FIRST_UISA_SP_REGNUM+ii)] =
+ ptrace (PT_READ_GPR, inferior_pid, (PTRACE_ARG3_TYPE) special_regs[ii],
+ 0, 0);
+
+ registers_fetched ();
+ return;
+ }
+
+ /* else an individual register is addressed. */
+
+ else if (regno < FP0_REGNUM) { /* a GPR */
+ *(int*)&registers[REGISTER_BYTE (regno)] =
+ ptrace (PT_READ_GPR, inferior_pid, (PTRACE_ARG3_TYPE) regno, 0, 0);
+ }
+ else if (regno <= FPLAST_REGNUM) { /* a FPR */
+ ptrace (PT_READ_FPR, inferior_pid,
+ (PTRACE_ARG3_TYPE) &registers [REGISTER_BYTE (regno)],
+ (regno-FP0_REGNUM+FPR0), 0);
+ }
+ else if (regno <= LAST_UISA_SP_REGNUM) { /* a special register */
+ *(int*)&registers[REGISTER_BYTE (regno)] =
+ ptrace (PT_READ_GPR, inferior_pid,
+ (PTRACE_ARG3_TYPE) special_regs[regno-FIRST_UISA_SP_REGNUM],
+ 0, 0);
+ }
+ else
+ fprintf_unfiltered (gdb_stderr,
+ "gdb error: register no %d not implemented.\n",
+ regno);
+
+ register_valid [regno] = 1;
+}
+
+/* Store our register values back into the inferior.
+ If REGNO is -1, do this for all registers.
+ Otherwise, REGNO specifies which register (so we can save time). */
+
+void
+store_inferior_registers (regno)
+ int regno;
+{
+ extern char registers[];
+
+ errno = 0;
+
+ if (regno == -1)
+ { /* for all registers.. */
+ int ii;
+
+ /* execute one dummy instruction (which is a breakpoint) in inferior
+ process. So give kernel a chance to do internal house keeping.
+ Otherwise the following ptrace(2) calls will mess up user stack
+ since kernel will get confused about the bottom of the stack (%sp) */
+
+ exec_one_dummy_insn ();
+
+ /* write general purpose registers first! */
+ for ( ii=GPR0; ii<=GPR31; ++ii)
+ {
+ ptrace (PT_WRITE_GPR, inferior_pid, (PTRACE_ARG3_TYPE) ii,
+ *(int*)&registers[REGISTER_BYTE (ii)], 0);
+ if (errno)
+ {
+ perror ("ptrace write_gpr");
+ errno = 0;
+ }
+ }
+
+ /* write floating point registers now. */
+ for ( ii=0; ii < 32; ++ii)
+ {
+ ptrace (PT_WRITE_FPR, inferior_pid,
+ (PTRACE_ARG3_TYPE) &registers[REGISTER_BYTE (FP0_REGNUM+ii)],
+ FPR0+ii, 0);
+ if (errno)
+ {
+ perror ("ptrace write_fpr");
+ errno = 0;
+ }
+ }
+
+ /* write special registers. */
+ for (ii=0; ii <= LAST_UISA_SP_REGNUM-FIRST_UISA_SP_REGNUM; ++ii)
+ {
+ ptrace (PT_WRITE_GPR, inferior_pid,
+ (PTRACE_ARG3_TYPE) special_regs[ii],
+ *(int*)&registers[REGISTER_BYTE (FIRST_UISA_SP_REGNUM+ii)],
+ 0);
+ if (errno)
+ {
+ perror ("ptrace write_gpr");
+ errno = 0;
+ }
+ }
+ }
+
+ /* else, a specific register number is given... */
+
+ else if (regno < FP0_REGNUM) /* a GPR */
+ {
+ ptrace (PT_WRITE_GPR, inferior_pid, (PTRACE_ARG3_TYPE) regno,
+ *(int*)&registers[REGISTER_BYTE (regno)], 0);
+ }
+
+ else if (regno <= FPLAST_REGNUM) /* a FPR */
+ {
+ ptrace (PT_WRITE_FPR, inferior_pid,
+ (PTRACE_ARG3_TYPE) &registers[REGISTER_BYTE (regno)],
+ regno - FP0_REGNUM + FPR0, 0);
+ }
+
+ else if (regno <= LAST_UISA_SP_REGNUM) /* a special register */
+ {
+ ptrace (PT_WRITE_GPR, inferior_pid,
+ (PTRACE_ARG3_TYPE) special_regs [regno-FIRST_UISA_SP_REGNUM],
+ *(int*)&registers[REGISTER_BYTE (regno)], 0);
+ }
+
+ else
+ fprintf_unfiltered (gdb_stderr,
+ "Gdb error: register no %d not implemented.\n",
+ regno);
+
+ if (errno)
+ {
+ perror ("ptrace write");
+ errno = 0;
+ }
+}
+
+/* Execute one dummy breakpoint instruction. This way we give the kernel
+ a chance to do some housekeeping and update inferior's internal data,
+ including u_area. */
+
+static void
+exec_one_dummy_insn ()
+{
+#define DUMMY_INSN_ADDR (TEXT_SEGMENT_BASE)+0x200
+
+ char shadow_contents[BREAKPOINT_MAX]; /* Stash old bkpt addr contents */
+ int status, pid;
+ CORE_ADDR prev_pc;
+
+ /* We plant one dummy breakpoint into DUMMY_INSN_ADDR address. We
+ assume that this address will never be executed again by the real
+ code. */
+
+ target_insert_breakpoint (DUMMY_INSN_ADDR, shadow_contents);
+
+ errno = 0;
+
+ /* You might think this could be done with a single ptrace call, and
+ you'd be correct for just about every platform I've ever worked
+ on. However, rs6000-ibm-aix4.1.3 seems to have screwed this up --
+ the inferior never hits the breakpoint (it's also worth noting
+ powerpc-ibm-aix4.1.3 works correctly). */
+ prev_pc = read_pc ();
+ write_pc (DUMMY_INSN_ADDR);
+ ptrace (PT_CONTINUE, inferior_pid, (PTRACE_ARG3_TYPE)1, 0, 0);
+
+ if (errno)
+ perror ("pt_continue");
+
+ do {
+ pid = wait (&status);
+ } while (pid != inferior_pid);
+
+ write_pc (prev_pc);
+ target_remove_breakpoint (DUMMY_INSN_ADDR, shadow_contents);
+}
+
+static void
+fetch_core_registers (core_reg_sect, core_reg_size, which, reg_addr)
+ char *core_reg_sect;
+ unsigned core_reg_size;
+ int which;
+ CORE_ADDR reg_addr; /* Unused in this version */
+{
+ /* fetch GPRs and special registers from the first register section
+ in core bfd. */
+ if (which == 0)
+ {
+ /* copy GPRs first. */
+ memcpy (registers, core_reg_sect, 32 * 4);
+
+ /* gdb's internal register template and bfd's register section layout
+ should share a common include file. FIXMEmgo */
+ /* then comes special registes. They are supposed to be in the same
+ order in gdb template and bfd `.reg' section. */
+ core_reg_sect += (32 * 4);
+ memcpy (&registers [REGISTER_BYTE (FIRST_UISA_SP_REGNUM)],
+ core_reg_sect,
+ (LAST_UISA_SP_REGNUM - FIRST_UISA_SP_REGNUM + 1) * 4);
+ }
+
+ /* fetch floating point registers from register section 2 in core bfd. */
+ else if (which == 2)
+ memcpy (&registers [REGISTER_BYTE (FP0_REGNUM)], core_reg_sect, 32 * 8);
+
+ else
+ fprintf_unfiltered
+ (gdb_stderr,
+ "Gdb error: unknown parameter to fetch_core_registers().\n");
+}
+
+/* handle symbol translation on vmapping */
+
+static void
+vmap_symtab (vp)
+ register struct vmap *vp;
+{
+ register struct objfile *objfile;
+ struct section_offsets *new_offsets;
+ int i;
+
+ objfile = vp->objfile;
+ if (objfile == NULL)
+ {
+ /* OK, it's not an objfile we opened ourselves.
+ Currently, that can only happen with the exec file, so
+ relocate the symbols for the symfile. */
+ if (symfile_objfile == NULL)
+ return;
+ objfile = symfile_objfile;
+ }
+
+ new_offsets = alloca
+ (sizeof (struct section_offsets)
+ + sizeof (new_offsets->offsets) * objfile->num_sections);
+
+ for (i = 0; i < objfile->num_sections; ++i)
+ ANOFFSET (new_offsets, i) = ANOFFSET (objfile->section_offsets, i);
+
+ /* The symbols in the object file are linked to the VMA of the section,
+ relocate them VMA relative. */
+ ANOFFSET (new_offsets, SECT_OFF_TEXT) = vp->tstart - vp->tvma;
+ ANOFFSET (new_offsets, SECT_OFF_DATA) = vp->dstart - vp->dvma;
+ ANOFFSET (new_offsets, SECT_OFF_BSS) = vp->dstart - vp->dvma;
+
+ objfile_relocate (objfile, new_offsets);
+}
+
+/* Add symbols for an objfile. */
+
+static int
+objfile_symbol_add (arg)
+ char *arg;
+{
+ struct objfile *obj = (struct objfile *) arg;
+
+ syms_from_objfile (obj, 0, 0, 0);
+ new_symfile_objfile (obj, 0, 0);
+ return 1;
+}
+
+/* Add a new vmap entry based on ldinfo() information.
+
+ If ldi->ldinfo_fd is not valid (e.g. this struct ld_info is from a
+ core file), the caller should set it to -1, and we will open the file.
+
+ Return the vmap new entry. */
+
+static struct vmap *
+add_vmap (ldi)
+ register struct ld_info *ldi;
+{
+ bfd *abfd, *last;
+ register char *mem, *objname;
+ struct objfile *obj;
+ struct vmap *vp;
+
+ /* This ldi structure was allocated using alloca() in
+ xcoff_relocate_symtab(). Now we need to have persistent object
+ and member names, so we should save them. */
+
+ mem = ldi->ldinfo_filename + strlen (ldi->ldinfo_filename) + 1;
+ mem = savestring (mem, strlen (mem));
+ objname = savestring (ldi->ldinfo_filename, strlen (ldi->ldinfo_filename));
+
+ if (ldi->ldinfo_fd < 0)
+ /* Note that this opens it once for every member; a possible
+ enhancement would be to only open it once for every object. */
+ abfd = bfd_openr (objname, gnutarget);
+ else
+ abfd = bfd_fdopenr (objname, gnutarget, ldi->ldinfo_fd);
+ if (!abfd)
+ error ("Could not open `%s' as an executable file: %s",
+ objname, bfd_errmsg (bfd_get_error ()));
+
+ /* make sure we have an object file */
+
+ if (bfd_check_format (abfd, bfd_object))
+ vp = map_vmap (abfd, 0);
+
+ else if (bfd_check_format (abfd, bfd_archive))
+ {
+ last = 0;
+ /* FIXME??? am I tossing BFDs? bfd? */
+ while ((last = bfd_openr_next_archived_file (abfd, last)))
+ if (STREQ (mem, last->filename))
+ break;
+
+ if (!last)
+ {
+ bfd_close (abfd);
+ /* FIXME -- should be error */
+ warning ("\"%s\": member \"%s\" missing.", abfd->filename, mem);
+ return 0;
+ }
+
+ if (!bfd_check_format(last, bfd_object))
+ {
+ bfd_close (last); /* XXX??? */
+ goto obj_err;
+ }
+
+ vp = map_vmap (last, abfd);
+ }
+ else
+ {
+ obj_err:
+ bfd_close (abfd);
+ error ("\"%s\": not in executable format: %s.",
+ objname, bfd_errmsg (bfd_get_error ()));
+ /*NOTREACHED*/
+ }
+ obj = allocate_objfile (vp->bfd, 0, 0, 0);
+ vp->objfile = obj;
+
+#ifndef SOLIB_SYMBOLS_MANUAL
+ if (catch_errors (objfile_symbol_add, (char *)obj,
+ "Error while reading shared library symbols:\n",
+ RETURN_MASK_ALL))
+ {
+ /* Note this is only done if symbol reading was successful. */
+ vmap_symtab (vp);
+ vp->loaded = 1;
+ }
+#endif
+ return vp;
+}
+
+/* update VMAP info with ldinfo() information
+ Input is ptr to ldinfo() results. */
+
+static void
+vmap_ldinfo (ldi)
+ register struct ld_info *ldi;
+{
+ struct stat ii, vi;
+ register struct vmap *vp;
+ int got_one, retried;
+ int got_exec_file = 0;
+
+ /* For each *ldi, see if we have a corresponding *vp.
+ If so, update the mapping, and symbol table.
+ If not, add an entry and symbol table. */
+
+ do {
+ char *name = ldi->ldinfo_filename;
+ char *memb = name + strlen(name) + 1;
+
+ retried = 0;
+
+ if (fstat (ldi->ldinfo_fd, &ii) < 0)
+ {
+ /* The kernel sets ld_info to -1, if the process is still using the
+ object, and the object is removed. Keep the symbol info for the
+ removed object and issue a warning. */
+ warning ("%s (fd=%d) has disappeared, keeping its symbols",
+ name, ldi->ldinfo_fd);
+ continue;
+ }
+ retry:
+ for (got_one = 0, vp = vmap; vp; vp = vp->nxt)
+ {
+ struct objfile *objfile;
+
+ /* First try to find a `vp', which is the same as in ldinfo.
+ If not the same, just continue and grep the next `vp'. If same,
+ relocate its tstart, tend, dstart, dend values. If no such `vp'
+ found, get out of this for loop, add this ldi entry as a new vmap
+ (add_vmap) and come back, find its `vp' and so on... */
+
+ /* The filenames are not always sufficient to match on. */
+
+ if ((name[0] == '/' && !STREQ(name, vp->name))
+ || (memb[0] && !STREQ(memb, vp->member)))
+ continue;
+
+ /* See if we are referring to the same file.
+ We have to check objfile->obfd, symfile.c:reread_symbols might
+ have updated the obfd after a change. */
+ objfile = vp->objfile == NULL ? symfile_objfile : vp->objfile;
+ if (objfile == NULL
+ || objfile->obfd == NULL
+ || bfd_stat (objfile->obfd, &vi) < 0)
+ {
+ warning ("Unable to stat %s, keeping its symbols", name);
+ continue;
+ }
+
+ if (ii.st_dev != vi.st_dev || ii.st_ino != vi.st_ino)
+ continue;
+
+ if (!retried)
+ close (ldi->ldinfo_fd);
+
+ ++got_one;
+
+ /* Found a corresponding VMAP. Remap! */
+
+ /* We can assume pointer == CORE_ADDR, this code is native only. */
+ vp->tstart = (CORE_ADDR) ldi->ldinfo_textorg;
+ vp->tend = vp->tstart + ldi->ldinfo_textsize;
+ vp->dstart = (CORE_ADDR) ldi->ldinfo_dataorg;
+ vp->dend = vp->dstart + ldi->ldinfo_datasize;
+
+ /* The run time loader maps the file header in addition to the text
+ section and returns a pointer to the header in ldinfo_textorg.
+ Adjust the text start address to point to the real start address
+ of the text section. */
+ vp->tstart += vp->toffs;
+
+ /* The objfile is only NULL for the exec file. */
+ if (vp->objfile == NULL)
+ got_exec_file = 1;
+
+ /* relocate symbol table(s). */
+ vmap_symtab (vp);
+
+ /* There may be more, so we don't break out of the loop. */
+ }
+
+ /* if there was no matching *vp, we must perforce create the sucker(s) */
+ if (!got_one && !retried)
+ {
+ add_vmap (ldi);
+ ++retried;
+ goto retry;
+ }
+ } while (ldi->ldinfo_next
+ && (ldi = (void *) (ldi->ldinfo_next + (char *) ldi)));
+
+ /* If we don't find the symfile_objfile anywhere in the ldinfo, it
+ is unlikely that the symbol file is relocated to the proper
+ address. And we might have attached to a process which is
+ running a different copy of the same executable. */
+ if (symfile_objfile != NULL && !got_exec_file)
+ {
+ warning_begin ();
+ fputs_unfiltered ("Symbol file ", gdb_stderr);
+ fputs_unfiltered (symfile_objfile->name, gdb_stderr);
+ fputs_unfiltered ("\nis not mapped; discarding it.\n\
+If in fact that file has symbols which the mapped files listed by\n\
+\"info files\" lack, you can load symbols with the \"symbol-file\" or\n\
+\"add-symbol-file\" commands (note that you must take care of relocating\n\
+symbols to the proper address).\n", gdb_stderr);
+ free_objfile (symfile_objfile);
+ symfile_objfile = NULL;
+ }
+ breakpoint_re_set ();
+}
+
+/* As well as symbol tables, exec_sections need relocation. After
+ the inferior process' termination, there will be a relocated symbol
+ table exist with no corresponding inferior process. At that time, we
+ need to use `exec' bfd, rather than the inferior process's memory space
+ to look up symbols.
+
+ `exec_sections' need to be relocated only once, as long as the exec
+ file remains unchanged.
+*/
+
+static void
+vmap_exec ()
+{
+ static bfd *execbfd;
+ int i;
+
+ if (execbfd == exec_bfd)
+ return;
+
+ execbfd = exec_bfd;
+
+ if (!vmap || !exec_ops.to_sections)
+ error ("vmap_exec: vmap or exec_ops.to_sections == 0\n");
+
+ for (i=0; &exec_ops.to_sections[i] < exec_ops.to_sections_end; i++)
+ {
+ if (STREQ(".text", exec_ops.to_sections[i].the_bfd_section->name))
+ {
+ exec_ops.to_sections[i].addr += vmap->tstart - vmap->tvma;
+ exec_ops.to_sections[i].endaddr += vmap->tstart - vmap->tvma;
+ }
+ else if (STREQ(".data", exec_ops.to_sections[i].the_bfd_section->name))
+ {
+ exec_ops.to_sections[i].addr += vmap->dstart - vmap->dvma;
+ exec_ops.to_sections[i].endaddr += vmap->dstart - vmap->dvma;
+ }
+ else if (STREQ(".bss", exec_ops.to_sections[i].the_bfd_section->name))
+ {
+ exec_ops.to_sections[i].addr += vmap->dstart - vmap->dvma;
+ exec_ops.to_sections[i].endaddr += vmap->dstart - vmap->dvma;
+ }
+ }
+}
+
+/* xcoff_relocate_symtab - hook for symbol table relocation.
+ also reads shared libraries.. */
+
+void
+xcoff_relocate_symtab (pid)
+ unsigned int pid;
+{
+#define MAX_LOAD_SEGS 64 /* maximum number of load segments */
+
+ struct ld_info *ldi;
+
+ ldi = (void *) alloca(MAX_LOAD_SEGS * sizeof (*ldi));
+
+ /* According to my humble theory, AIX has some timing problems and
+ when the user stack grows, kernel doesn't update stack info in time
+ and ptrace calls step on user stack. That is why we sleep here a little,
+ and give kernel to update its internals. */
+
+ usleep (36000);
+
+ errno = 0;
+ ptrace (PT_LDINFO, pid, (PTRACE_ARG3_TYPE) ldi,
+ MAX_LOAD_SEGS * sizeof(*ldi), (int *) ldi);
+ if (errno)
+ perror_with_name ("ptrace ldinfo");
+
+ vmap_ldinfo (ldi);
+
+ /* relocate the exec and core sections as well. */
+ vmap_exec ();
+}
+
+/* Core file stuff. */
+
+/* Relocate symtabs and read in shared library info, based on symbols
+ from the core file. */
+
+void
+xcoff_relocate_core (target)
+ struct target_ops *target;
+{
+/* Offset of member MEMBER in a struct of type TYPE. */
+#ifndef offsetof
+#define offsetof(TYPE, MEMBER) ((int) &((TYPE *)0)->MEMBER)
+#endif
+
+/* Size of a struct ld_info except for the variable-length filename. */
+#define LDINFO_SIZE (offsetof (struct ld_info, ldinfo_filename))
+
+ sec_ptr ldinfo_sec;
+ int offset = 0;
+ struct ld_info *ldip;
+ struct vmap *vp;
+
+ /* Allocated size of buffer. */
+ int buffer_size = LDINFO_SIZE;
+ char *buffer = xmalloc (buffer_size);
+ struct cleanup *old = make_cleanup (free_current_contents, &buffer);
+
+ /* FIXME, this restriction should not exist. For now, though I'll
+ avoid coredumps with error() pending a real fix. */
+ if (vmap == NULL)
+ error
+ ("Can't debug a core file without an executable file (on the RS/6000)");
+
+ ldinfo_sec = bfd_get_section_by_name (core_bfd, ".ldinfo");
+ if (ldinfo_sec == NULL)
+ {
+ bfd_err:
+ fprintf_filtered (gdb_stderr, "Couldn't get ldinfo from core file: %s\n",
+ bfd_errmsg (bfd_get_error ()));
+ do_cleanups (old);
+ return;
+ }
+ do
+ {
+ int i;
+ int names_found = 0;
+
+ /* Read in everything but the name. */
+ if (bfd_get_section_contents (core_bfd, ldinfo_sec, buffer,
+ offset, LDINFO_SIZE) == 0)
+ goto bfd_err;
+
+ /* Now the name. */
+ i = LDINFO_SIZE;
+ do
+ {
+ if (i == buffer_size)
+ {
+ buffer_size *= 2;
+ buffer = xrealloc (buffer, buffer_size);
+ }
+ if (bfd_get_section_contents (core_bfd, ldinfo_sec, &buffer[i],
+ offset + i, 1) == 0)
+ goto bfd_err;
+ if (buffer[i++] == '\0')
+ ++names_found;
+ } while (names_found < 2);
+
+ ldip = (struct ld_info *) buffer;
+
+ /* Can't use a file descriptor from the core file; need to open it. */
+ ldip->ldinfo_fd = -1;
+
+ /* The first ldinfo is for the exec file, allocated elsewhere. */
+ if (offset == 0)
+ vp = vmap;
+ else
+ vp = add_vmap (ldip);
+
+ offset += ldip->ldinfo_next;
+
+ /* We can assume pointer == CORE_ADDR, this code is native only. */
+ vp->tstart = (CORE_ADDR) ldip->ldinfo_textorg;
+ vp->tend = vp->tstart + ldip->ldinfo_textsize;
+ vp->dstart = (CORE_ADDR) ldip->ldinfo_dataorg;
+ vp->dend = vp->dstart + ldip->ldinfo_datasize;
+
+ /* The run time loader maps the file header in addition to the text
+ section and returns a pointer to the header in ldinfo_textorg.
+ Adjust the text start address to point to the real start address
+ of the text section. */
+ vp->tstart += vp->toffs;
+
+ /* Unless this is the exec file,
+ add our sections to the section table for the core target. */
+ if (vp != vmap)
+ {
+ int count;
+ struct section_table *stp;
+ int update_coreops;
+
+ /* We must update the to_sections field in the core_ops structure
+ now to avoid dangling pointer dereferences. */
+ update_coreops = core_ops.to_sections == target->to_sections;
+
+ count = target->to_sections_end - target->to_sections;
+ count += 2;
+ target->to_sections = (struct section_table *)
+ xrealloc (target->to_sections,
+ sizeof (struct section_table) * count);
+ target->to_sections_end = target->to_sections + count;
+
+ /* Update the to_sections field in the core_ops structure
+ if needed. */
+ if (update_coreops)
+ {
+ core_ops.to_sections = target->to_sections;
+ core_ops.to_sections_end = target->to_sections_end;
+ }
+ stp = target->to_sections_end - 2;
+
+ stp->bfd = vp->bfd;
+ stp->the_bfd_section = bfd_get_section_by_name (stp->bfd, ".text");
+ stp->addr = vp->tstart;
+ stp->endaddr = vp->tend;
+ stp++;
+
+ stp->bfd = vp->bfd;
+ stp->the_bfd_section = bfd_get_section_by_name (stp->bfd, ".data");
+ stp->addr = vp->dstart;
+ stp->endaddr = vp->dend;
+ }
+
+ vmap_symtab (vp);
+ } while (ldip->ldinfo_next != 0);
+ vmap_exec ();
+ breakpoint_re_set ();
+ do_cleanups (old);
+}
+
+int
+kernel_u_size ()
+{
+ return (sizeof (struct user));
+}
+
+/* Under AIX, we have to pass the correct TOC pointer to a function
+ when calling functions in the inferior.
+ We try to find the relative toc offset of the objfile containing PC
+ and add the current load address of the data segment from the vmap. */
+
+static CORE_ADDR
+find_toc_address (pc)
+ CORE_ADDR pc;
+{
+ struct vmap *vp;
+
+ for (vp = vmap; vp; vp = vp->nxt)
+ {
+ if (pc >= vp->tstart && pc < vp->tend)
+ {
+ /* vp->objfile is only NULL for the exec file. */
+ return vp->dstart + get_toc_offset (vp->objfile == NULL
+ ? symfile_objfile
+ : vp->objfile);
+ }
+ }
+ error ("Unable to find TOC entry for pc 0x%x\n", pc);
+}
+
+/* Register that we are able to handle rs6000 core file formats. */
+
+static struct core_fns rs6000_core_fns =
+{
+ bfd_target_coff_flavour,
+ fetch_core_registers,
+ NULL
+};
+
+void
+_initialize_core_rs6000 ()
+{
+ /* Initialize hook in rs6000-tdep.c for determining the TOC address when
+ calling functions in the inferior. */
+ find_toc_address_hook = &find_toc_address;
+
+ /* For native configurations, where this module is included, inform
+ the xcoffsolib module where it can find the function for symbol table
+ relocation at runtime. */
+ xcoff_relocate_symtab_hook = &xcoff_relocate_symtab;
+ add_core_fns (&rs6000_core_fns);
+}
diff --git a/gdb/rs6000-tdep.c b/gdb/rs6000-tdep.c
new file mode 100644
index 00000000000..57f1df100de
--- /dev/null
+++ b/gdb/rs6000-tdep.c
@@ -0,0 +1,1800 @@
+/* Target-dependent code for GDB, the GNU debugger.
+ Copyright 1986, 1987, 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1997
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "frame.h"
+#include "inferior.h"
+#include "symtab.h"
+#include "target.h"
+#include "gdbcore.h"
+#include "gdbcmd.h"
+#include "symfile.h"
+#include "objfiles.h"
+#include "xcoffsolib.h"
+
+extern int errno;
+
+/* Breakpoint shadows for the single step instructions will be kept here. */
+
+static struct sstep_breaks {
+ /* Address, or 0 if this is not in use. */
+ CORE_ADDR address;
+ /* Shadow contents. */
+ char data[4];
+} stepBreaks[2];
+
+/* Hook for determining the TOC address when calling functions in the
+ inferior under AIX. The initialization code in rs6000-nat.c sets
+ this hook to point to find_toc_address. */
+
+CORE_ADDR (*find_toc_address_hook) PARAMS ((CORE_ADDR)) = NULL;
+
+/* Static function prototypes */
+
+static CORE_ADDR branch_dest PARAMS ((int opcode, int instr, CORE_ADDR pc,
+ CORE_ADDR safety));
+
+static void frame_get_saved_regs PARAMS ((struct frame_info *fi,
+ struct rs6000_framedata *fdatap));
+
+static void pop_dummy_frame PARAMS ((void));
+
+static CORE_ADDR frame_initial_stack_address PARAMS ((struct frame_info *));
+
+/* Fill in fi->saved_regs */
+
+struct frame_extra_info
+{
+ /* Functions calling alloca() change the value of the stack
+ pointer. We need to use initial stack pointer (which is saved in
+ r31 by gcc) in such cases. If a compiler emits traceback table,
+ then we should use the alloca register specified in traceback
+ table. FIXME. */
+ CORE_ADDR initial_sp; /* initial stack pointer. */
+};
+
+void
+rs6000_init_extra_frame_info (fromleaf, fi)
+ int fromleaf;
+ struct frame_info *fi;
+{
+ fi->extra_info = (struct frame_extra_info*)
+ frame_obstack_alloc (sizeof (struct frame_extra_info));
+ fi->extra_info->initial_sp = 0;
+ if (fi->next != (CORE_ADDR) 0
+ && fi->pc < TEXT_SEGMENT_BASE)
+ /* We're in get_prev_frame_info */
+ /* and this is a special signal frame. */
+ /* (fi->pc will be some low address in the kernel, */
+ /* to which the signal handler returns). */
+ fi->signal_handler_caller = 1;
+}
+
+
+void
+rs6000_frame_init_saved_regs (fi)
+ struct frame_info *fi;
+{
+ frame_get_saved_regs (fi, NULL);
+}
+
+CORE_ADDR
+rs6000_frame_args_address (fi)
+ struct frame_info *fi;
+{
+ if (fi->extra_info->initial_sp != 0)
+ return fi->extra_info->initial_sp;
+ else
+ return frame_initial_stack_address (fi);
+}
+
+
+/* Calculate the destination of a branch/jump. Return -1 if not a branch. */
+
+static CORE_ADDR
+branch_dest (opcode, instr, pc, safety)
+ int opcode;
+ int instr;
+ CORE_ADDR pc;
+ CORE_ADDR safety;
+{
+ CORE_ADDR dest;
+ int immediate;
+ int absolute;
+ int ext_op;
+
+ absolute = (int) ((instr >> 1) & 1);
+
+ switch (opcode) {
+ case 18 :
+ immediate = ((instr & ~3) << 6) >> 6; /* br unconditional */
+ if (absolute)
+ dest = immediate;
+ else
+ dest = pc + immediate;
+ break;
+
+ case 16 :
+ immediate = ((instr & ~3) << 16) >> 16; /* br conditional */
+ if (absolute)
+ dest = immediate;
+ else
+ dest = pc + immediate;
+ break;
+
+ case 19 :
+ ext_op = (instr>>1) & 0x3ff;
+
+ if (ext_op == 16) /* br conditional register */
+ {
+ dest = read_register (LR_REGNUM) & ~3;
+
+ /* If we are about to return from a signal handler, dest is
+ something like 0x3c90. The current frame is a signal handler
+ caller frame, upon completion of the sigreturn system call
+ execution will return to the saved PC in the frame. */
+ if (dest < TEXT_SEGMENT_BASE)
+ {
+ struct frame_info *fi;
+
+ fi = get_current_frame ();
+ if (fi != NULL)
+ dest = read_memory_integer (fi->frame + SIG_FRAME_PC_OFFSET,
+ 4);
+ }
+ }
+
+ else if (ext_op == 528) /* br cond to count reg */
+ {
+ dest = read_register (CTR_REGNUM) & ~3;
+
+ /* If we are about to execute a system call, dest is something
+ like 0x22fc or 0x3b00. Upon completion the system call
+ will return to the address in the link register. */
+ if (dest < TEXT_SEGMENT_BASE)
+ dest = read_register (LR_REGNUM) & ~3;
+ }
+ else return -1;
+ break;
+
+ default: return -1;
+ }
+ return (dest < TEXT_SEGMENT_BASE) ? safety : dest;
+}
+
+
+/* Sequence of bytes for breakpoint instruction. */
+
+#define BIG_BREAKPOINT { 0x7d, 0x82, 0x10, 0x08 }
+#define LITTLE_BREAKPOINT { 0x08, 0x10, 0x82, 0x7d }
+
+unsigned char *
+rs6000_breakpoint_from_pc (bp_addr, bp_size)
+ CORE_ADDR *bp_addr;
+ int *bp_size;
+{
+ static unsigned char big_breakpoint[] = BIG_BREAKPOINT;
+ static unsigned char little_breakpoint[] = LITTLE_BREAKPOINT;
+ *bp_size = 4;
+ if (TARGET_BYTE_ORDER == BIG_ENDIAN)
+ return big_breakpoint;
+ else
+ return little_breakpoint;
+}
+
+
+/* AIX does not support PT_STEP. Simulate it. */
+
+void
+rs6000_software_single_step (signal, insert_breakpoints_p)
+ unsigned int signal;
+ int insert_breakpoints_p;
+{
+#define INSNLEN(OPCODE) 4
+
+ static char le_breakp[] = LITTLE_BREAKPOINT;
+ static char be_breakp[] = BIG_BREAKPOINT;
+ char *breakp = TARGET_BYTE_ORDER == BIG_ENDIAN ? be_breakp : le_breakp;
+ int ii, insn;
+ CORE_ADDR loc;
+ CORE_ADDR breaks[2];
+ int opcode;
+
+ if (insert_breakpoints_p) {
+
+ loc = read_pc ();
+
+ insn = read_memory_integer (loc, 4);
+
+ breaks[0] = loc + INSNLEN(insn);
+ opcode = insn >> 26;
+ breaks[1] = branch_dest (opcode, insn, loc, breaks[0]);
+
+ /* Don't put two breakpoints on the same address. */
+ if (breaks[1] == breaks[0])
+ breaks[1] = -1;
+
+ stepBreaks[1].address = 0;
+
+ for (ii=0; ii < 2; ++ii) {
+
+ /* ignore invalid breakpoint. */
+ if ( breaks[ii] == -1)
+ continue;
+
+ read_memory (breaks[ii], stepBreaks[ii].data, 4);
+
+ write_memory (breaks[ii], breakp, 4);
+ stepBreaks[ii].address = breaks[ii];
+ }
+
+ } else {
+
+ /* remove step breakpoints. */
+ for (ii=0; ii < 2; ++ii)
+ if (stepBreaks[ii].address != 0)
+ write_memory
+ (stepBreaks[ii].address, stepBreaks[ii].data, 4);
+
+ }
+ errno = 0; /* FIXME, don't ignore errors! */
+ /* What errors? {read,write}_memory call error(). */
+}
+
+
+/* return pc value after skipping a function prologue and also return
+ information about a function frame.
+
+ in struct rs6000_framedata fdata:
+ - frameless is TRUE, if function does not have a frame.
+ - nosavedpc is TRUE, if function does not save %pc value in its frame.
+ - offset is the initial size of this stack frame --- the amount by
+ which we decrement the sp to allocate the frame.
+ - saved_gpr is the number of the first saved gpr.
+ - saved_fpr is the number of the first saved fpr.
+ - alloca_reg is the number of the register used for alloca() handling.
+ Otherwise -1.
+ - gpr_offset is the offset of the first saved gpr from the previous frame.
+ - fpr_offset is the offset of the first saved fpr from the previous frame.
+ - lr_offset is the offset of the saved lr
+ - cr_offset is the offset of the saved cr
+*/
+
+#define SIGNED_SHORT(x) \
+ ((sizeof (short) == 2) \
+ ? ((int)(short)(x)) \
+ : ((int)((((x) & 0xffff) ^ 0x8000) - 0x8000)))
+
+#define GET_SRC_REG(x) (((x) >> 21) & 0x1f)
+
+CORE_ADDR
+skip_prologue (pc, fdata)
+ CORE_ADDR pc;
+ struct rs6000_framedata *fdata;
+{
+ CORE_ADDR orig_pc = pc;
+ char buf[4];
+ unsigned long op;
+ long offset = 0;
+ int lr_reg = 0;
+ int cr_reg = 0;
+ int reg;
+ int framep = 0;
+ int minimal_toc_loaded = 0;
+ static struct rs6000_framedata zero_frame;
+
+ *fdata = zero_frame;
+ fdata->saved_gpr = -1;
+ fdata->saved_fpr = -1;
+ fdata->alloca_reg = -1;
+ fdata->frameless = 1;
+ fdata->nosavedpc = 1;
+
+ if (target_read_memory (pc, buf, 4))
+ return pc; /* Can't access it -- assume no prologue. */
+
+ /* Assume that subsequent fetches can fail with low probability. */
+ pc -= 4;
+ for (;;)
+ {
+ pc += 4;
+ op = read_memory_integer (pc, 4);
+
+ if ((op & 0xfc1fffff) == 0x7c0802a6) { /* mflr Rx */
+ lr_reg = (op & 0x03e00000) | 0x90010000;
+ continue;
+
+ } else if ((op & 0xfc1fffff) == 0x7c000026) { /* mfcr Rx */
+ cr_reg = (op & 0x03e00000) | 0x90010000;
+ continue;
+
+ } else if ((op & 0xfc1f0000) == 0xd8010000) { /* stfd Rx,NUM(r1) */
+ reg = GET_SRC_REG (op);
+ if (fdata->saved_fpr == -1 || fdata->saved_fpr > reg) {
+ fdata->saved_fpr = reg;
+ fdata->fpr_offset = SIGNED_SHORT (op) + offset;
+ }
+ continue;
+
+ } else if (((op & 0xfc1f0000) == 0xbc010000) || /* stm Rx, NUM(r1) */
+ ((op & 0xfc1f0000) == 0x90010000 && /* st rx,NUM(r1),
+ rx >= r13 */
+ (op & 0x03e00000) >= 0x01a00000)) {
+
+ reg = GET_SRC_REG (op);
+ if (fdata->saved_gpr == -1 || fdata->saved_gpr > reg) {
+ fdata->saved_gpr = reg;
+ fdata->gpr_offset = SIGNED_SHORT (op) + offset;
+ }
+ continue;
+
+ } else if ((op & 0xffff0000) == 0x3c000000) { /* addis 0,0,NUM, used
+ for >= 32k frames */
+ fdata->offset = (op & 0x0000ffff) << 16;
+ fdata->frameless = 0;
+ continue;
+
+ } else if ((op & 0xffff0000) == 0x60000000) { /* ori 0,0,NUM, 2nd ha
+ lf of >= 32k frames */
+ fdata->offset |= (op & 0x0000ffff);
+ fdata->frameless = 0;
+ continue;
+
+ } else if ((op & 0xffff0000) == lr_reg) { /* st Rx,NUM(r1)
+ where Rx == lr */
+ fdata->lr_offset = SIGNED_SHORT (op) + offset;
+ fdata->nosavedpc = 0;
+ lr_reg = 0;
+ continue;
+
+ } else if ((op & 0xffff0000) == cr_reg) { /* st Rx,NUM(r1)
+ where Rx == cr */
+ fdata->cr_offset = SIGNED_SHORT (op) + offset;
+ cr_reg = 0;
+ continue;
+
+ } else if (op == 0x48000005) { /* bl .+4 used in
+ -mrelocatable */
+ continue;
+
+ } else if (op == 0x48000004) { /* b .+4 (xlc) */
+ break;
+
+ } else if (((op & 0xffff0000) == 0x801e0000 || /* lwz 0,NUM(r30), used
+ in V.4 -mrelocatable */
+ op == 0x7fc0f214) && /* add r30,r0,r30, used
+ in V.4 -mrelocatable */
+ lr_reg == 0x901e0000) {
+ continue;
+
+ } else if ((op & 0xffff0000) == 0x3fc00000 || /* addis 30,0,foo@ha, used
+ in V.4 -mminimal-toc */
+ (op & 0xffff0000) == 0x3bde0000) { /* addi 30,30,foo@l */
+ continue;
+
+ } else if ((op & 0xfc000000) == 0x48000000) { /* bl foo,
+ to save fprs??? */
+
+ fdata->frameless = 0;
+ /* Don't skip over the subroutine call if it is not within the first
+ three instructions of the prologue. */
+ if ((pc - orig_pc) > 8)
+ break;
+
+ op = read_memory_integer (pc+4, 4);
+
+ /* At this point, make sure this is not a trampoline function
+ (a function that simply calls another functions, and nothing else).
+ If the next is not a nop, this branch was part of the function
+ prologue. */
+
+ if (op == 0x4def7b82 || op == 0) /* crorc 15, 15, 15 */
+ break; /* don't skip over
+ this branch */
+ continue;
+
+ /* update stack pointer */
+ } else if ((op & 0xffff0000) == 0x94210000) { /* stu r1,NUM(r1) */
+ fdata->frameless = 0;
+ fdata->offset = SIGNED_SHORT (op);
+ offset = fdata->offset;
+ continue;
+
+ } else if (op == 0x7c21016e) { /* stwux 1,1,0 */
+ fdata->frameless = 0;
+ offset = fdata->offset;
+ continue;
+
+ /* Load up minimal toc pointer */
+ } else if ((op >> 22) == 0x20f
+ && ! minimal_toc_loaded) { /* l r31,... or l r30,... */
+ minimal_toc_loaded = 1;
+ continue;
+
+ /* store parameters in stack */
+ } else if ((op & 0xfc1f0000) == 0x90010000 || /* st rx,NUM(r1) */
+ (op & 0xfc1f0000) == 0xd8010000 || /* stfd Rx,NUM(r1) */
+ (op & 0xfc1f0000) == 0xfc010000) { /* frsp, fp?,NUM(r1) */
+ continue;
+
+ /* store parameters in stack via frame pointer */
+ } else if (framep &&
+ ((op & 0xfc1f0000) == 0x901f0000 || /* st rx,NUM(r1) */
+ (op & 0xfc1f0000) == 0xd81f0000 || /* stfd Rx,NUM(r1) */
+ (op & 0xfc1f0000) == 0xfc1f0000)) { /* frsp, fp?,NUM(r1) */
+ continue;
+
+ /* Set up frame pointer */
+ } else if (op == 0x603f0000 /* oril r31, r1, 0x0 */
+ || op == 0x7c3f0b78) { /* mr r31, r1 */
+ fdata->frameless = 0;
+ framep = 1;
+ fdata->alloca_reg = 31;
+ continue;
+
+ /* Another way to set up the frame pointer. */
+ } else if ((op & 0xfc1fffff) == 0x38010000) { /* addi rX, r1, 0x0 */
+ fdata->frameless = 0;
+ framep = 1;
+ fdata->alloca_reg = (op & ~0x38010000) >> 21;
+ continue;
+
+ } else {
+ break;
+ }
+ }
+
+#if 0
+/* I have problems with skipping over __main() that I need to address
+ * sometime. Previously, I used to use misc_function_vector which
+ * didn't work as well as I wanted to be. -MGO */
+
+ /* If the first thing after skipping a prolog is a branch to a function,
+ this might be a call to an initializer in main(), introduced by gcc2.
+ We'd like to skip over it as well. Fortunately, xlc does some extra
+ work before calling a function right after a prologue, thus we can
+ single out such gcc2 behaviour. */
+
+
+ if ((op & 0xfc000001) == 0x48000001) { /* bl foo, an initializer function? */
+ op = read_memory_integer (pc+4, 4);
+
+ if (op == 0x4def7b82) { /* cror 0xf, 0xf, 0xf (nop) */
+
+ /* check and see if we are in main. If so, skip over this initializer
+ function as well. */
+
+ tmp = find_pc_misc_function (pc);
+ if (tmp >= 0 && STREQ (misc_function_vector [tmp].name, "main"))
+ return pc + 8;
+ }
+ }
+#endif /* 0 */
+
+ fdata->offset = - fdata->offset;
+ return pc;
+}
+
+
+/*************************************************************************
+ Support for creating pushind a dummy frame into the stack, and popping
+ frames, etc.
+*************************************************************************/
+
+/* The total size of dummy frame is 436, which is;
+
+ 32 gpr's - 128 bytes
+ 32 fpr's - 256 "
+ 7 the rest - 28 "
+ and 24 extra bytes for the callee's link area. The last 24 bytes
+ for the link area might not be necessary, since it will be taken
+ care of by push_arguments(). */
+
+#define DUMMY_FRAME_SIZE 436
+
+#define DUMMY_FRAME_ADDR_SIZE 10
+
+/* Make sure you initialize these in somewhere, in case gdb gives up what it
+ was debugging and starts debugging something else. FIXMEibm */
+
+static int dummy_frame_count = 0;
+static int dummy_frame_size = 0;
+static CORE_ADDR *dummy_frame_addr = 0;
+
+extern int stop_stack_dummy;
+
+/* push a dummy frame into stack, save all register. Currently we are saving
+ only gpr's and fpr's, which is not good enough! FIXMEmgo */
+
+void
+push_dummy_frame ()
+{
+ /* stack pointer. */
+ CORE_ADDR sp;
+ /* Same thing, target byte order. */
+ char sp_targ[4];
+
+ /* link register. */
+ CORE_ADDR pc;
+ /* Same thing, target byte order. */
+ char pc_targ[4];
+
+ /* Needed to figure out where to save the dummy link area.
+ FIXME: There should be an easier way to do this, no? tiemann 9/9/95. */
+ struct rs6000_framedata fdata;
+
+ int ii;
+
+ target_fetch_registers (-1);
+
+ if (dummy_frame_count >= dummy_frame_size) {
+ dummy_frame_size += DUMMY_FRAME_ADDR_SIZE;
+ if (dummy_frame_addr)
+ dummy_frame_addr = (CORE_ADDR*) xrealloc
+ (dummy_frame_addr, sizeof(CORE_ADDR) * (dummy_frame_size));
+ else
+ dummy_frame_addr = (CORE_ADDR*)
+ xmalloc (sizeof(CORE_ADDR) * (dummy_frame_size));
+ }
+
+ sp = read_register(SP_REGNUM);
+ pc = read_register(PC_REGNUM);
+ store_address (pc_targ, 4, pc);
+
+ skip_prologue (get_pc_function_start (pc), &fdata);
+
+ dummy_frame_addr [dummy_frame_count++] = sp;
+
+ /* Be careful! If the stack pointer is not decremented first, then kernel
+ thinks he is free to use the space underneath it. And kernel actually
+ uses that area for IPC purposes when executing ptrace(2) calls. So
+ before writing register values into the new frame, decrement and update
+ %sp first in order to secure your frame. */
+
+ /* FIXME: We don't check if the stack really has this much space.
+ This is a problem on the ppc simulator (which only grants one page
+ (4096 bytes) by default. */
+
+ write_register (SP_REGNUM, sp-DUMMY_FRAME_SIZE);
+
+ /* gdb relies on the state of current_frame. We'd better update it,
+ otherwise things like do_registers_info() wouldn't work properly! */
+
+ flush_cached_frames ();
+
+ /* save program counter in link register's space. */
+ write_memory (sp + (fdata.lr_offset ? fdata.lr_offset : DEFAULT_LR_SAVE),
+ pc_targ, 4);
+
+ /* save all floating point and general purpose registers here. */
+
+ /* fpr's, f0..f31 */
+ for (ii = 0; ii < 32; ++ii)
+ write_memory (sp-8-(ii*8), &registers[REGISTER_BYTE (31-ii+FP0_REGNUM)], 8);
+
+ /* gpr's r0..r31 */
+ for (ii=1; ii <=32; ++ii)
+ write_memory (sp-256-(ii*4), &registers[REGISTER_BYTE (32-ii)], 4);
+
+ /* so far, 32*2 + 32 words = 384 bytes have been written.
+ 7 extra registers in our register set: pc, ps, cnd, lr, cnt, xer, mq */
+
+ for (ii=1; ii <= (LAST_UISA_SP_REGNUM-FIRST_UISA_SP_REGNUM+1); ++ii) {
+ write_memory (sp-384-(ii*4),
+ &registers[REGISTER_BYTE (FPLAST_REGNUM + ii)], 4);
+ }
+
+ /* Save sp or so called back chain right here. */
+ store_address (sp_targ, 4, sp);
+ write_memory (sp-DUMMY_FRAME_SIZE, sp_targ, 4);
+ sp -= DUMMY_FRAME_SIZE;
+
+ /* And finally, this is the back chain. */
+ write_memory (sp+8, pc_targ, 4);
+}
+
+
+/* Pop a dummy frame.
+
+ In rs6000 when we push a dummy frame, we save all of the registers. This
+ is usually done before user calls a function explicitly.
+
+ After a dummy frame is pushed, some instructions are copied into stack,
+ and stack pointer is decremented even more. Since we don't have a frame
+ pointer to get back to the parent frame of the dummy, we start having
+ trouble poping it. Therefore, we keep a dummy frame stack, keeping
+ addresses of dummy frames as such. When poping happens and when we
+ detect that was a dummy frame, we pop it back to its parent by using
+ dummy frame stack (`dummy_frame_addr' array).
+
+FIXME: This whole concept is broken. You should be able to detect
+a dummy stack frame *on the user's stack itself*. When you do,
+then you know the format of that stack frame -- including its
+saved SP register! There should *not* be a separate stack in the
+GDB process that keeps track of these dummy frames! -- gnu@cygnus.com Aug92
+ */
+
+static void
+pop_dummy_frame ()
+{
+ CORE_ADDR sp, pc;
+ int ii;
+ sp = dummy_frame_addr [--dummy_frame_count];
+
+ /* restore all fpr's. */
+ for (ii = 1; ii <= 32; ++ii)
+ read_memory (sp-(ii*8), &registers[REGISTER_BYTE (32-ii+FP0_REGNUM)], 8);
+
+ /* restore all gpr's */
+ for (ii=1; ii <= 32; ++ii) {
+ read_memory (sp-256-(ii*4), &registers[REGISTER_BYTE (32-ii)], 4);
+ }
+
+ /* restore the rest of the registers. */
+ for (ii=1; ii <=(LAST_UISA_SP_REGNUM-FIRST_UISA_SP_REGNUM+1); ++ii)
+ read_memory (sp-384-(ii*4),
+ &registers[REGISTER_BYTE (FPLAST_REGNUM + ii)], 4);
+
+ read_memory (sp-(DUMMY_FRAME_SIZE-8),
+ &registers [REGISTER_BYTE(PC_REGNUM)], 4);
+
+ /* when a dummy frame was being pushed, we had to decrement %sp first, in
+ order to secure astack space. Thus, saved %sp (or %r1) value, is not the
+ one we should restore. Change it with the one we need. */
+
+ memcpy (&registers [REGISTER_BYTE(FP_REGNUM)], (char *) &sp, sizeof (int));
+
+ /* Now we can restore all registers. */
+
+ target_store_registers (-1);
+ pc = read_pc ();
+ flush_cached_frames ();
+}
+
+
+/* pop the innermost frame, go back to the caller. */
+
+void
+pop_frame ()
+{
+ CORE_ADDR pc, lr, sp, prev_sp; /* %pc, %lr, %sp */
+ struct rs6000_framedata fdata;
+ struct frame_info *frame = get_current_frame ();
+ int addr, ii;
+
+ pc = read_pc ();
+ sp = FRAME_FP (frame);
+
+ if (stop_stack_dummy)
+ {
+#ifdef USE_GENERIC_DUMMY_FRAMES
+ generic_pop_dummy_frame ();
+ flush_cached_frames ();
+ return;
+#else
+ if (dummy_frame_count)
+ pop_dummy_frame ();
+ return;
+#endif
+ }
+
+ /* Make sure that all registers are valid. */
+ read_register_bytes (0, NULL, REGISTER_BYTES);
+
+ /* figure out previous %pc value. If the function is frameless, it is
+ still in the link register, otherwise walk the frames and retrieve the
+ saved %pc value in the previous frame. */
+
+ addr = get_pc_function_start (frame->pc);
+ (void) skip_prologue (addr, &fdata);
+
+ if (fdata.frameless)
+ prev_sp = sp;
+ else
+ prev_sp = read_memory_integer (sp, 4);
+ if (fdata.lr_offset == 0)
+ lr = read_register (LR_REGNUM);
+ else
+ lr = read_memory_integer (prev_sp + fdata.lr_offset, 4);
+
+ /* reset %pc value. */
+ write_register (PC_REGNUM, lr);
+
+ /* reset register values if any was saved earlier. */
+
+ if (fdata.saved_gpr != -1)
+ {
+ addr = prev_sp + fdata.gpr_offset;
+ for (ii = fdata.saved_gpr; ii <= 31; ++ii) {
+ read_memory (addr, &registers [REGISTER_BYTE (ii)], 4);
+ addr += 4;
+ }
+ }
+
+ if (fdata.saved_fpr != -1)
+ {
+ addr = prev_sp + fdata.fpr_offset;
+ for (ii = fdata.saved_fpr; ii <= 31; ++ii) {
+ read_memory (addr, &registers [REGISTER_BYTE (ii+FP0_REGNUM)], 8);
+ addr += 8;
+ }
+ }
+
+ write_register (SP_REGNUM, prev_sp);
+ target_store_registers (-1);
+ flush_cached_frames ();
+}
+
+/* fixup the call sequence of a dummy function, with the real function address.
+ its argumets will be passed by gdb. */
+
+void
+rs6000_fix_call_dummy (dummyname, pc, fun, nargs, args, type, gcc_p)
+ char *dummyname;
+ CORE_ADDR pc;
+ CORE_ADDR fun;
+ int nargs;
+ value_ptr *args;
+ struct type *type;
+ int gcc_p;
+{
+#define TOC_ADDR_OFFSET 20
+#define TARGET_ADDR_OFFSET 28
+
+ int ii;
+ CORE_ADDR target_addr;
+
+ if (find_toc_address_hook != NULL)
+ {
+ CORE_ADDR tocvalue;
+
+ tocvalue = (*find_toc_address_hook) (fun);
+ ii = *(int*)((char*)dummyname + TOC_ADDR_OFFSET);
+ ii = (ii & 0xffff0000) | (tocvalue >> 16);
+ *(int*)((char*)dummyname + TOC_ADDR_OFFSET) = ii;
+
+ ii = *(int*)((char*)dummyname + TOC_ADDR_OFFSET+4);
+ ii = (ii & 0xffff0000) | (tocvalue & 0x0000ffff);
+ *(int*)((char*)dummyname + TOC_ADDR_OFFSET+4) = ii;
+ }
+
+ target_addr = fun;
+ ii = *(int*)((char*)dummyname + TARGET_ADDR_OFFSET);
+ ii = (ii & 0xffff0000) | (target_addr >> 16);
+ *(int*)((char*)dummyname + TARGET_ADDR_OFFSET) = ii;
+
+ ii = *(int*)((char*)dummyname + TARGET_ADDR_OFFSET+4);
+ ii = (ii & 0xffff0000) | (target_addr & 0x0000ffff);
+ *(int*)((char*)dummyname + TARGET_ADDR_OFFSET+4) = ii;
+}
+
+/* Pass the arguments in either registers, or in the stack. In RS6000,
+ the first eight words of the argument list (that might be less than
+ eight parameters if some parameters occupy more than one word) are
+ passed in r3..r11 registers. float and double parameters are
+ passed in fpr's, in addition to that. Rest of the parameters if any
+ are passed in user stack. There might be cases in which half of the
+ parameter is copied into registers, the other half is pushed into
+ stack.
+
+ If the function is returning a structure, then the return address is passed
+ in r3, then the first 7 words of the parameters can be passed in registers,
+ starting from r4. */
+
+CORE_ADDR
+push_arguments (nargs, args, sp, struct_return, struct_addr)
+ int nargs;
+ value_ptr *args;
+ CORE_ADDR sp;
+ int struct_return;
+ CORE_ADDR struct_addr;
+{
+ int ii;
+ int len = 0;
+ int argno; /* current argument number */
+ int argbytes; /* current argument byte */
+ char tmp_buffer [50];
+ int f_argno = 0; /* current floating point argno */
+
+ value_ptr arg = 0;
+ struct type *type;
+
+ CORE_ADDR saved_sp;
+
+#ifndef USE_GENERIC_DUMMY_FRAMES
+ if ( dummy_frame_count <= 0)
+ printf_unfiltered ("FATAL ERROR -push_arguments()! frame not found!!\n");
+#endif /* GENERIC_DUMMY_FRAMES */
+
+ /* The first eight words of ther arguments are passed in registers. Copy
+ them appropriately.
+
+ If the function is returning a `struct', then the first word (which
+ will be passed in r3) is used for struct return address. In that
+ case we should advance one word and start from r4 register to copy
+ parameters. */
+
+ ii = struct_return ? 1 : 0;
+
+/*
+effectively indirect call... gcc does...
+
+return_val example( float, int);
+
+eabi:
+ float in fp0, int in r3
+ offset of stack on overflow 8/16
+ for varargs, must go by type.
+power open:
+ float in r3&r4, int in r5
+ offset of stack on overflow different
+both:
+ return in r3 or f0. If no float, must study how gcc emulates floats;
+ pay attention to arg promotion.
+ User may have to cast\args to handle promotion correctly
+ since gdb won't know if prototype supplied or not.
+*/
+
+ for (argno=0, argbytes=0; argno < nargs && ii<8; ++ii) {
+
+ arg = args[argno];
+ type = check_typedef (VALUE_TYPE (arg));
+ len = TYPE_LENGTH (type);
+
+ if (TYPE_CODE (type) == TYPE_CODE_FLT) {
+
+ /* floating point arguments are passed in fpr's, as well as gpr's.
+ There are 13 fpr's reserved for passing parameters. At this point
+ there is no way we would run out of them. */
+
+ if (len > 8)
+ printf_unfiltered (
+"Fatal Error: a floating point parameter #%d with a size > 8 is found!\n", argno);
+
+ memcpy (&registers[REGISTER_BYTE(FP0_REGNUM + 1 + f_argno)],
+ VALUE_CONTENTS (arg),
+ len);
+ ++f_argno;
+ }
+
+ if (len > 4) {
+
+ /* Argument takes more than one register. */
+ while (argbytes < len) {
+ memset (&registers[REGISTER_BYTE(ii+3)], 0, sizeof(int));
+ memcpy (&registers[REGISTER_BYTE(ii+3)],
+ ((char*)VALUE_CONTENTS (arg))+argbytes,
+ (len - argbytes) > 4 ? 4 : len - argbytes);
+ ++ii, argbytes += 4;
+
+ if (ii >= 8)
+ goto ran_out_of_registers_for_arguments;
+ }
+ argbytes = 0;
+ --ii;
+ }
+ else { /* Argument can fit in one register. No problem. */
+ memset (&registers[REGISTER_BYTE(ii+3)], 0, sizeof(int));
+ memcpy (&registers[REGISTER_BYTE(ii+3)], VALUE_CONTENTS (arg), len);
+ }
+ ++argno;
+ }
+
+ran_out_of_registers_for_arguments:
+
+#ifdef USE_GENERIC_DUMMY_FRAMES
+ saved_sp = read_sp ();
+#else
+ /* location for 8 parameters are always reserved. */
+ sp -= 4 * 8;
+
+ /* another six words for back chain, TOC register, link register, etc. */
+ sp -= 24;
+#endif /* GENERIC_DUMMY_FRAMES */
+ /* if there are more arguments, allocate space for them in
+ the stack, then push them starting from the ninth one. */
+
+ if ((argno < nargs) || argbytes) {
+ int space = 0, jj;
+
+ if (argbytes) {
+ space += ((len - argbytes + 3) & -4);
+ jj = argno + 1;
+ }
+ else
+ jj = argno;
+
+ for (; jj < nargs; ++jj) {
+ value_ptr val = args[jj];
+ space += ((TYPE_LENGTH (VALUE_TYPE (val))) + 3) & -4;
+ }
+
+ /* add location required for the rest of the parameters */
+ space = (space + 7) & -8;
+ sp -= space;
+
+ /* This is another instance we need to be concerned about securing our
+ stack space. If we write anything underneath %sp (r1), we might conflict
+ with the kernel who thinks he is free to use this area. So, update %sp
+ first before doing anything else. */
+
+ write_register (SP_REGNUM, sp);
+
+ /* if the last argument copied into the registers didn't fit there
+ completely, push the rest of it into stack. */
+
+ if (argbytes) {
+ write_memory (sp+24+(ii*4),
+ ((char*)VALUE_CONTENTS (arg))+argbytes,
+ len - argbytes);
+ ++argno;
+ ii += ((len - argbytes + 3) & -4) / 4;
+ }
+
+ /* push the rest of the arguments into stack. */
+ for (; argno < nargs; ++argno) {
+
+ arg = args[argno];
+ type = check_typedef (VALUE_TYPE (arg));
+ len = TYPE_LENGTH (type);
+
+
+ /* float types should be passed in fpr's, as well as in the stack. */
+ if (TYPE_CODE (type) == TYPE_CODE_FLT && f_argno < 13) {
+
+ if (len > 8)
+ printf_unfiltered (
+"Fatal Error: a floating point parameter #%d with a size > 8 is found!\n", argno);
+
+ memcpy (&registers[REGISTER_BYTE(FP0_REGNUM + 1 + f_argno)],
+ VALUE_CONTENTS (arg),
+ len);
+ ++f_argno;
+ }
+
+ write_memory (sp+24+(ii*4), (char *) VALUE_CONTENTS (arg), len);
+ ii += ((len + 3) & -4) / 4;
+ }
+ }
+ else
+ /* Secure stack areas first, before doing anything else. */
+ write_register (SP_REGNUM, sp);
+
+#ifndef USE_GENERIC_DUMMY_FRAMES
+/* we want to copy 24 bytes of target's frame to dummy's frame,
+ then set back chain to point to new frame. */
+
+ saved_sp = dummy_frame_addr [dummy_frame_count - 1];
+ read_memory (saved_sp, tmp_buffer, 24);
+ write_memory (sp, tmp_buffer, 24);
+#endif /* GENERIC_DUMMY_FRAMES */
+
+ /* set back chain properly */
+ store_address (tmp_buffer, 4, saved_sp);
+ write_memory (sp, tmp_buffer, 4);
+
+ target_store_registers (-1);
+ return sp;
+}
+#ifdef ELF_OBJECT_FORMAT
+
+/* Function: ppc_push_return_address (pc, sp)
+ Set up the return address for the inferior function call. */
+
+CORE_ADDR
+ppc_push_return_address (pc, sp)
+ CORE_ADDR pc;
+ CORE_ADDR sp;
+{
+ write_register (LR_REGNUM, CALL_DUMMY_ADDRESS ());
+ return sp;
+}
+
+#endif
+
+/* a given return value in `regbuf' with a type `valtype', extract and copy its
+ value into `valbuf' */
+
+void
+extract_return_value (valtype, regbuf, valbuf)
+ struct type *valtype;
+ char regbuf[REGISTER_BYTES];
+ char *valbuf;
+{
+ int offset = 0;
+
+ if (TYPE_CODE (valtype) == TYPE_CODE_FLT) {
+
+ double dd; float ff;
+ /* floats and doubles are returned in fpr1. fpr's have a size of 8 bytes.
+ We need to truncate the return value into float size (4 byte) if
+ necessary. */
+
+ if (TYPE_LENGTH (valtype) > 4) /* this is a double */
+ memcpy (valbuf,
+ &regbuf[REGISTER_BYTE (FP0_REGNUM + 1)],
+ TYPE_LENGTH (valtype));
+ else { /* float */
+ memcpy (&dd, &regbuf[REGISTER_BYTE (FP0_REGNUM + 1)], 8);
+ ff = (float)dd;
+ memcpy (valbuf, &ff, sizeof(float));
+ }
+ }
+ else {
+ /* return value is copied starting from r3. */
+ if (TARGET_BYTE_ORDER == BIG_ENDIAN
+ && TYPE_LENGTH (valtype) < REGISTER_RAW_SIZE (3))
+ offset = REGISTER_RAW_SIZE (3) - TYPE_LENGTH (valtype);
+
+ memcpy (valbuf,
+ regbuf + REGISTER_BYTE (3) + offset,
+ TYPE_LENGTH (valtype));
+ }
+}
+
+
+/* keep structure return address in this variable.
+ FIXME: This is a horrid kludge which should not be allowed to continue
+ living. This only allows a single nested call to a structure-returning
+ function. Come on, guys! -- gnu@cygnus.com, Aug 92 */
+
+CORE_ADDR rs6000_struct_return_address;
+
+
+/* Indirect function calls use a piece of trampoline code to do context
+ switching, i.e. to set the new TOC table. Skip such code if we are on
+ its first instruction (as when we have single-stepped to here).
+ Also skip shared library trampoline code (which is different from
+ indirect function call trampolines).
+ Result is desired PC to step until, or NULL if we are not in
+ trampoline code. */
+
+CORE_ADDR
+skip_trampoline_code (pc)
+ CORE_ADDR pc;
+{
+ register unsigned int ii, op;
+ CORE_ADDR solib_target_pc;
+
+ static unsigned trampoline_code[] = {
+ 0x800b0000, /* l r0,0x0(r11) */
+ 0x90410014, /* st r2,0x14(r1) */
+ 0x7c0903a6, /* mtctr r0 */
+ 0x804b0004, /* l r2,0x4(r11) */
+ 0x816b0008, /* l r11,0x8(r11) */
+ 0x4e800420, /* bctr */
+ 0x4e800020, /* br */
+ 0
+ };
+
+ /* If pc is in a shared library trampoline, return its target. */
+ solib_target_pc = find_solib_trampoline_target (pc);
+ if (solib_target_pc)
+ return solib_target_pc;
+
+ for (ii=0; trampoline_code[ii]; ++ii) {
+ op = read_memory_integer (pc + (ii*4), 4);
+ if (op != trampoline_code [ii])
+ return 0;
+ }
+ ii = read_register (11); /* r11 holds destination addr */
+ pc = read_memory_integer (ii, 4); /* (r11) value */
+ return pc;
+}
+
+/* Determines whether the function FI has a frame on the stack or not. */
+
+int
+frameless_function_invocation (fi)
+ struct frame_info *fi;
+{
+ CORE_ADDR func_start;
+ struct rs6000_framedata fdata;
+
+ /* Don't even think about framelessness except on the innermost frame
+ or if the function was interrupted by a signal. */
+ if (fi->next != NULL && !fi->next->signal_handler_caller)
+ return 0;
+
+ func_start = get_pc_function_start (fi->pc);
+
+ /* If we failed to find the start of the function, it is a mistake
+ to inspect the instructions. */
+
+ if (!func_start)
+ {
+ /* A frame with a zero PC is usually created by dereferencing a NULL
+ function pointer, normally causing an immediate core dump of the
+ inferior. Mark function as frameless, as the inferior has no chance
+ of setting up a stack frame. */
+ if (fi->pc == 0)
+ return 1;
+ else
+ return 0;
+ }
+
+ (void) skip_prologue (func_start, &fdata);
+ return fdata.frameless;
+}
+
+/* Return the PC saved in a frame */
+
+unsigned long
+frame_saved_pc (fi)
+ struct frame_info *fi;
+{
+ CORE_ADDR func_start;
+ struct rs6000_framedata fdata;
+
+ if (fi->signal_handler_caller)
+ return read_memory_integer (fi->frame + SIG_FRAME_PC_OFFSET, 4);
+
+#ifdef USE_GENERIC_DUMMY_FRAMES
+ if (PC_IN_CALL_DUMMY (fi->pc, fi->frame, fi->frame))
+ return generic_read_register_dummy(fi->pc, fi->frame, PC_REGNUM);
+#endif /* GENERIC_DUMMY_FRAMES */
+
+ func_start = get_pc_function_start (fi->pc);
+
+ /* If we failed to find the start of the function, it is a mistake
+ to inspect the instructions. */
+ if (!func_start)
+ return 0;
+
+ (void) skip_prologue (func_start, &fdata);
+
+ if (fdata.lr_offset == 0 && fi->next != NULL)
+ {
+ if (fi->next->signal_handler_caller)
+ return read_memory_integer (fi->next->frame + SIG_FRAME_LR_OFFSET, 4);
+ else
+ return read_memory_integer (rs6000_frame_chain (fi) + DEFAULT_LR_SAVE,
+ 4);
+ }
+
+ if (fdata.lr_offset == 0)
+ return read_register (LR_REGNUM);
+
+ return read_memory_integer (rs6000_frame_chain (fi) + fdata.lr_offset, 4);
+}
+
+/* If saved registers of frame FI are not known yet, read and cache them.
+ &FDATAP contains rs6000_framedata; TDATAP can be NULL,
+ in which case the framedata are read. */
+
+static void
+frame_get_saved_regs (fi, fdatap)
+ struct frame_info *fi;
+ struct rs6000_framedata *fdatap;
+{
+ int ii;
+ CORE_ADDR frame_addr;
+ struct rs6000_framedata work_fdata;
+
+ if (fi->saved_regs)
+ return;
+
+ if (fdatap == NULL)
+ {
+ fdatap = &work_fdata;
+ (void) skip_prologue (get_pc_function_start (fi->pc), fdatap);
+ }
+
+ frame_saved_regs_zalloc (fi);
+
+ /* If there were any saved registers, figure out parent's stack
+ pointer. */
+ /* The following is true only if the frame doesn't have a call to
+ alloca(), FIXME. */
+
+ if (fdatap->saved_fpr == 0 && fdatap->saved_gpr == 0
+ && fdatap->lr_offset == 0 && fdatap->cr_offset == 0)
+ frame_addr = 0;
+ else if (fi->prev && fi->prev->frame)
+ frame_addr = fi->prev->frame;
+ else
+ frame_addr = read_memory_integer (fi->frame, 4);
+
+ /* if != -1, fdatap->saved_fpr is the smallest number of saved_fpr.
+ All fpr's from saved_fpr to fp31 are saved. */
+
+ if (fdatap->saved_fpr >= 0)
+ {
+ int i;
+ int fpr_offset = frame_addr + fdatap->fpr_offset;
+ for (i = fdatap->saved_fpr; i < 32; i++)
+ {
+ fi->saved_regs [FP0_REGNUM + i] = fpr_offset;
+ fpr_offset += 8;
+ }
+ }
+
+ /* if != -1, fdatap->saved_gpr is the smallest number of saved_gpr.
+ All gpr's from saved_gpr to gpr31 are saved. */
+
+ if (fdatap->saved_gpr >= 0)
+ {
+ int i;
+ int gpr_offset = frame_addr + fdatap->gpr_offset;
+ for (i = fdatap->saved_gpr; i < 32; i++)
+ {
+ fi->saved_regs [i] = gpr_offset;
+ gpr_offset += 4;
+ }
+ }
+
+ /* If != 0, fdatap->cr_offset is the offset from the frame that holds
+ the CR. */
+ if (fdatap->cr_offset != 0)
+ fi->saved_regs [CR_REGNUM] = frame_addr + fdatap->cr_offset;
+
+ /* If != 0, fdatap->lr_offset is the offset from the frame that holds
+ the LR. */
+ if (fdatap->lr_offset != 0)
+ fi->saved_regs [LR_REGNUM] = frame_addr + fdatap->lr_offset;
+}
+
+/* Return the address of a frame. This is the inital %sp value when the frame
+ was first allocated. For functions calling alloca(), it might be saved in
+ an alloca register. */
+
+static CORE_ADDR
+frame_initial_stack_address (fi)
+ struct frame_info *fi;
+{
+ CORE_ADDR tmpaddr;
+ struct rs6000_framedata fdata;
+ struct frame_info *callee_fi;
+
+ /* if the initial stack pointer (frame address) of this frame is known,
+ just return it. */
+
+ if (fi->extra_info->initial_sp)
+ return fi->extra_info->initial_sp;
+
+ /* find out if this function is using an alloca register.. */
+
+ (void) skip_prologue (get_pc_function_start (fi->pc), &fdata);
+
+ /* if saved registers of this frame are not known yet, read and cache them. */
+
+ if (!fi->saved_regs)
+ frame_get_saved_regs (fi, &fdata);
+
+ /* If no alloca register used, then fi->frame is the value of the %sp for
+ this frame, and it is good enough. */
+
+ if (fdata.alloca_reg < 0)
+ {
+ fi->extra_info->initial_sp = fi->frame;
+ return fi->extra_info->initial_sp;
+ }
+
+ /* This function has an alloca register. If this is the top-most frame
+ (with the lowest address), the value in alloca register is good. */
+
+ if (!fi->next)
+ return fi->extra_info->initial_sp = read_register (fdata.alloca_reg);
+
+ /* Otherwise, this is a caller frame. Callee has usually already saved
+ registers, but there are exceptions (such as when the callee
+ has no parameters). Find the address in which caller's alloca
+ register is saved. */
+
+ for (callee_fi = fi->next; callee_fi; callee_fi = callee_fi->next) {
+
+ if (!callee_fi->saved_regs)
+ frame_get_saved_regs (callee_fi, NULL);
+
+ /* this is the address in which alloca register is saved. */
+
+ tmpaddr = callee_fi->saved_regs [fdata.alloca_reg];
+ if (tmpaddr) {
+ fi->extra_info->initial_sp = read_memory_integer (tmpaddr, 4);
+ return fi->extra_info->initial_sp;
+ }
+
+ /* Go look into deeper levels of the frame chain to see if any one of
+ the callees has saved alloca register. */
+ }
+
+ /* If alloca register was not saved, by the callee (or any of its callees)
+ then the value in the register is still good. */
+
+ fi->extra_info->initial_sp = read_register (fdata.alloca_reg);
+ return fi->extra_info->initial_sp;
+}
+
+CORE_ADDR
+rs6000_frame_chain (thisframe)
+ struct frame_info *thisframe;
+{
+ CORE_ADDR fp;
+
+#ifdef USE_GENERIC_DUMMY_FRAMES
+ if (PC_IN_CALL_DUMMY (thisframe->pc, thisframe->frame, thisframe->frame))
+ return thisframe->frame; /* dummy frame same as caller's frame */
+#endif /* GENERIC_DUMMY_FRAMES */
+
+ if (inside_entry_file (thisframe->pc) ||
+ thisframe->pc == entry_point_address ())
+ return 0;
+
+ if (thisframe->signal_handler_caller)
+ fp = read_memory_integer (thisframe->frame + SIG_FRAME_FP_OFFSET, 4);
+ else if (thisframe->next != NULL
+ && thisframe->next->signal_handler_caller
+ && frameless_function_invocation (thisframe))
+ /* A frameless function interrupted by a signal did not change the
+ frame pointer. */
+ fp = FRAME_FP (thisframe);
+ else
+ fp = read_memory_integer ((thisframe)->frame, 4);
+
+#ifdef USE_GENERIC_DUMMY_FRAMES
+ {
+ CORE_ADDR fpp, lr;
+
+ lr = read_register (LR_REGNUM);
+ if (lr == entry_point_address ())
+ if (fp != 0 && (fpp = read_memory_integer (fp, 4)) != 0)
+ if (PC_IN_CALL_DUMMY (lr, fpp, fpp))
+ return fpp;
+ }
+#endif /* GENERIC_DUMMY_FRAMES */
+ return fp;
+}
+
+/* Return nonzero if ADDR (a function pointer) is in the data space and
+ is therefore a special function pointer. */
+
+int
+is_magic_function_pointer (addr)
+ CORE_ADDR addr;
+{
+ struct obj_section *s;
+
+ s = find_pc_section (addr);
+ if (s && s->the_bfd_section->flags & SEC_CODE)
+ return 0;
+ else
+ return 1;
+}
+
+#ifdef GDB_TARGET_POWERPC
+int
+gdb_print_insn_powerpc (memaddr, info)
+ bfd_vma memaddr;
+ disassemble_info *info;
+{
+ if (TARGET_BYTE_ORDER == BIG_ENDIAN)
+ return print_insn_big_powerpc (memaddr, info);
+ else
+ return print_insn_little_powerpc (memaddr, info);
+}
+#endif
+
+/* Function: get_saved_register
+ Just call the generic_get_saved_register function. */
+
+#ifdef USE_GENERIC_DUMMY_FRAMES
+void
+get_saved_register (raw_buffer, optimized, addrp, frame, regnum, lval)
+ char *raw_buffer;
+ int *optimized;
+ CORE_ADDR *addrp;
+ struct frame_info *frame;
+ int regnum;
+ enum lval_type *lval;
+{
+ generic_get_saved_register (raw_buffer, optimized, addrp,
+ frame, regnum, lval);
+}
+#endif
+
+
+
+/* Handling the various PowerPC/RS6000 variants. */
+
+
+/* The arrays here called register_names_MUMBLE hold names that
+ the rs6000_register_name function returns.
+
+ For each family of PPC variants, I've tried to isolate out the
+ common registers and put them up front, so that as long as you get
+ the general family right, GDB will correctly identify the registers
+ common to that family. The common register sets are:
+
+ For the 60x family: hid0 hid1 iabr dabr pir
+
+ For the 505 and 860 family: eie eid nri
+
+ For the 403 and 403GC: icdbdr esr dear evpr cdbcr tsr tcr pit tbhi
+ tblo srr2 srr3 dbsr dbcr iac1 iac2 dac1 dac2 dccr iccr pbl1
+ pbu1 pbl2 pbu2
+
+ Most of these register groups aren't anything formal. I arrived at
+ them by looking at the registers that occurred in more than one
+ processor. */
+
+/* UISA register names common across all architectures, including POWER. */
+
+#define COMMON_UISA_REG_NAMES \
+ /* 0 */ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", \
+ /* 8 */ "r8", "r9", "r10","r11","r12","r13","r14","r15", \
+ /* 16 */ "r16","r17","r18","r19","r20","r21","r22","r23", \
+ /* 24 */ "r24","r25","r26","r27","r28","r29","r30","r31", \
+ /* 32 */ "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", \
+ /* 40 */ "f8", "f9", "f10","f11","f12","f13","f14","f15", \
+ /* 48 */ "f16","f17","f18","f19","f20","f21","f22","f23", \
+ /* 56 */ "f24","f25","f26","f27","f28","f29","f30","f31", \
+ /* 64 */ "pc", "ps"
+
+/* UISA-level SPR names for PowerPC. */
+#define PPC_UISA_SPR_NAMES \
+ /* 66 */ "cr", "lr", "ctr", "xer", ""
+
+/* Segment register names, for PowerPC. */
+#define PPC_SEGMENT_REG_NAMES \
+ /* 71 */ "sr0", "sr1", "sr2", "sr3", "sr4", "sr5", "sr6", "sr7", \
+ /* 79 */ "sr8", "sr9", "sr10", "sr11", "sr12", "sr13", "sr14", "sr15"
+
+/* OEA SPR names for 32-bit PowerPC implementations.
+ The blank space is for "asr", which is only present on 64-bit
+ implementations. */
+#define PPC_32_OEA_SPR_NAMES \
+ /* 87 */ "pvr", \
+ /* 88 */ "ibat0u", "ibat0l", "ibat1u", "ibat1l", \
+ /* 92 */ "ibat2u", "ibat2l", "ibat3u", "ibat3l", \
+ /* 96 */ "dbat0u", "dbat0l", "dbat1u", "dbat1l", \
+ /* 100 */ "dbat2u", "dbat2l", "dbat3u", "dbat3l", \
+ /* 104 */ "sdr1", "", "dar", "dsisr", "sprg0", "sprg1", "sprg2", "sprg3",\
+ /* 112 */ "srr0", "srr1", "tbl", "tbu", "dec", "dabr", "ear"
+
+/* For the RS6000, we only cover user-level SPR's. */
+char *register_names_rs6000[] =
+{
+ COMMON_UISA_REG_NAMES,
+ /* 66 */ "cnd", "lr", "cnt", "xer", "mq"
+};
+
+/* a UISA-only view of the PowerPC. */
+char *register_names_uisa[] =
+{
+ COMMON_UISA_REG_NAMES,
+ PPC_UISA_SPR_NAMES
+};
+
+char *register_names_403[] =
+{
+ COMMON_UISA_REG_NAMES,
+ PPC_UISA_SPR_NAMES,
+ PPC_SEGMENT_REG_NAMES,
+ PPC_32_OEA_SPR_NAMES,
+ /* 119 */ "icdbdr", "esr", "dear", "evpr", "cdbcr", "tsr", "tcr", "pit",
+ /* 127 */ "tbhi", "tblo", "srr2", "srr3", "dbsr", "dbcr", "iac1", "iac2",
+ /* 135 */ "dac1", "dac2", "dccr", "iccr", "pbl1", "pbu1", "pbl2", "pbu2"
+};
+
+char *register_names_403GC[] =
+{
+ COMMON_UISA_REG_NAMES,
+ PPC_UISA_SPR_NAMES,
+ PPC_SEGMENT_REG_NAMES,
+ PPC_32_OEA_SPR_NAMES,
+ /* 119 */ "icdbdr", "esr", "dear", "evpr", "cdbcr", "tsr", "tcr", "pit",
+ /* 127 */ "tbhi", "tblo", "srr2", "srr3", "dbsr", "dbcr", "iac1", "iac2",
+ /* 135 */ "dac1", "dac2", "dccr", "iccr", "pbl1", "pbu1", "pbl2", "pbu2",
+ /* 143 */ "zpr", "pid", "sgr", "dcwr", "tbhu", "tblu"
+};
+
+char *register_names_505[] =
+{
+ COMMON_UISA_REG_NAMES,
+ PPC_UISA_SPR_NAMES,
+ PPC_SEGMENT_REG_NAMES,
+ PPC_32_OEA_SPR_NAMES,
+ /* 119 */ "eie", "eid", "nri"
+};
+
+char *register_names_860[] =
+{
+ COMMON_UISA_REG_NAMES,
+ PPC_UISA_SPR_NAMES,
+ PPC_SEGMENT_REG_NAMES,
+ PPC_32_OEA_SPR_NAMES,
+ /* 119 */ "eie", "eid", "nri", "cmpa", "cmpb", "cmpc", "cmpd", "icr",
+ /* 127 */ "der", "counta", "countb", "cmpe", "cmpf", "cmpg", "cmph",
+ /* 134 */ "lctrl1", "lctrl2", "ictrl", "bar", "ic_cst", "ic_adr", "ic_dat",
+ /* 141 */ "dc_cst", "dc_adr", "dc_dat", "dpdr", "dpir", "immr", "mi_ctr",
+ /* 148 */ "mi_ap", "mi_epn", "mi_twc", "mi_rpn", "md_ctr", "m_casid",
+ /* 154 */ "md_ap", "md_epn", "md_twb", "md_twc", "md_rpn", "m_tw",
+ /* 160 */ "mi_dbcam", "mi_dbram0", "mi_dbram1", "md_dbcam", "md_dbram0",
+ /* 165 */ "md_dbram1"
+};
+
+/* Note that the 601 has different register numbers for reading and
+ writing RTCU and RTCL. However, how one reads and writes a
+ register is the stub's problem. */
+char *register_names_601[] =
+{
+ COMMON_UISA_REG_NAMES,
+ PPC_UISA_SPR_NAMES,
+ PPC_SEGMENT_REG_NAMES,
+ PPC_32_OEA_SPR_NAMES,
+ /* 119 */ "hid0", "hid1", "iabr", "dabr", "pir", "mq", "rtcu",
+ /* 126 */ "rtcl"
+};
+
+char *register_names_602[] =
+{
+ COMMON_UISA_REG_NAMES,
+ PPC_UISA_SPR_NAMES,
+ PPC_SEGMENT_REG_NAMES,
+ PPC_32_OEA_SPR_NAMES,
+ /* 119 */ "hid0", "hid1", "iabr", "", "", "tcr", "ibr", "esassr", "sebr",
+ /* 128 */ "ser", "sp", "lt"
+};
+
+char *register_names_603[] =
+{
+ COMMON_UISA_REG_NAMES,
+ PPC_UISA_SPR_NAMES,
+ PPC_SEGMENT_REG_NAMES,
+ PPC_32_OEA_SPR_NAMES,
+ /* 119 */ "hid0", "hid1", "iabr", "", "", "dmiss", "dcmp", "hash1",
+ /* 127 */ "hash2", "imiss", "icmp", "rpa"
+};
+
+char *register_names_604[] =
+{
+ COMMON_UISA_REG_NAMES,
+ PPC_UISA_SPR_NAMES,
+ PPC_SEGMENT_REG_NAMES,
+ PPC_32_OEA_SPR_NAMES,
+ /* 119 */ "hid0", "hid1", "iabr", "dabr", "pir", "mmcr0", "pmc1", "pmc2",
+ /* 127 */ "sia", "sda"
+};
+
+char *register_names_750[] =
+{
+ COMMON_UISA_REG_NAMES,
+ PPC_UISA_SPR_NAMES,
+ PPC_SEGMENT_REG_NAMES,
+ PPC_32_OEA_SPR_NAMES,
+ /* 119 */ "hid0", "hid1", "iabr", "dabr", "", "ummcr0", "upmc1", "upmc2",
+ /* 127 */ "usia", "ummcr1", "upmc3", "upmc4", "mmcr0", "pmc1", "pmc2",
+ /* 134 */ "sia", "mmcr1", "pmc3", "pmc4", "l2cr", "ictc", "thrm1", "thrm2",
+ /* 142 */ "thrm3"
+};
+
+
+/* Information about a particular processor variant. */
+struct variant
+{
+ /* Name of this variant. */
+ char *name;
+
+ /* English description of the variant. */
+ char *description;
+
+ /* Table of register names; registers[R] is the name of the register
+ number R. */
+ int num_registers;
+ char **registers;
+};
+
+#define num_registers(list) (sizeof (list) / sizeof((list)[0]))
+
+
+/* Information in this table comes from the following web sites:
+ IBM: http://www.chips.ibm.com:80/products/embedded/
+ Motorola: http://www.mot.com/SPS/PowerPC/
+
+ I'm sure I've got some of the variant descriptions not quite right.
+ Please report any inaccuracies you find to GDB's maintainer.
+
+ If you add entries to this table, please be sure to allow the new
+ value as an argument to the --with-cpu flag, in configure.in. */
+
+static struct variant
+variants[] =
+{
+ { "ppc-uisa", "PowerPC UISA - a PPC processor as viewed by user-level code",
+ num_registers (register_names_uisa), register_names_uisa },
+ { "rs6000", "IBM RS6000 (\"POWER\") architecture, user-level view",
+ num_registers (register_names_rs6000), register_names_rs6000 },
+ { "403", "IBM PowerPC 403",
+ num_registers (register_names_403), register_names_403 },
+ { "403GC", "IBM PowerPC 403GC",
+ num_registers (register_names_403GC), register_names_403GC },
+ { "505", "Motorola PowerPC 505",
+ num_registers (register_names_505), register_names_505 },
+ { "860", "Motorola PowerPC 860 or 850",
+ num_registers (register_names_860), register_names_860 },
+ { "601", "Motorola PowerPC 601",
+ num_registers (register_names_601), register_names_601 },
+ { "602", "Motorola PowerPC 602",
+ num_registers (register_names_602), register_names_602 },
+ { "603", "Motorola/IBM PowerPC 603 or 603e",
+ num_registers (register_names_603), register_names_603 },
+ { "604", "Motorola PowerPC 604 or 604e",
+ num_registers (register_names_604), register_names_604 },
+ { "750", "Motorola/IBM PowerPC 750 or 750",
+ num_registers (register_names_750), register_names_750 },
+ { 0, 0, 0, 0 }
+};
+
+
+static struct variant *current_variant;
+
+char *
+rs6000_register_name (int i)
+{
+ if (i < 0 || i >= NUM_REGS)
+ error ("GDB bug: rs6000-tdep.c (rs6000_register_name): strange register number");
+
+ return ((i < current_variant->num_registers)
+ ? current_variant->registers[i]
+ : "");
+}
+
+
+static void
+install_variant (struct variant *v)
+{
+ current_variant = v;
+}
+
+
+/* Look up the variant named NAME in the `variants' table. Return a
+ pointer to the struct variant, or null if we couldn't find it. */
+static struct variant *
+find_variant_by_name (char *name)
+{
+ int i;
+
+ for (i = 0; variants[i].name; i++)
+ if (! strcmp (name, variants[i].name))
+ return &variants[i];
+
+ return 0;
+}
+
+
+/* Install the PPC/RS6000 variant named NAME in the `variants' table.
+ Return zero if we installed it successfully, or a non-zero value if
+ we couldn't do it.
+
+ This might be useful to code outside this file, which doesn't want
+ to depend on the exact indices of the entries in the `variants'
+ table. Just make it non-static if you want that. */
+static int
+install_variant_by_name (char *name)
+{
+ struct variant *v = find_variant_by_name (name);
+
+ if (v)
+ {
+ install_variant (v);
+ return 0;
+ }
+ else
+ return 1;
+}
+
+
+static void
+list_variants ()
+{
+ int i;
+
+ printf_filtered ("GDB knows about the following PowerPC and RS6000 variants:\n");
+
+ for (i = 0; variants[i].name; i++)
+ printf_filtered (" %-8s %s\n",
+ variants[i].name, variants[i].description);
+}
+
+
+static void
+show_current_variant ()
+{
+ printf_filtered ("PowerPC / RS6000 processor variant is set to `%s'.\n",
+ current_variant->name);
+}
+
+
+static void
+set_processor (char *arg, int from_tty)
+{
+ int i;
+
+ if (! arg || arg[0] == '\0')
+ {
+ list_variants ();
+ return;
+ }
+
+ if (install_variant_by_name (arg))
+ {
+ error_begin ();
+ fprintf_filtered (gdb_stderr,
+ "`%s' is not a recognized PowerPC / RS6000 variant name.\n\n", arg);
+ list_variants ();
+ return_to_top_level (RETURN_ERROR);
+ }
+
+ show_current_variant ();
+}
+
+static void
+show_processor (char *arg, int from_tty)
+{
+ show_current_variant ();
+}
+
+
+
+/* Initialization code. */
+
+void
+_initialize_rs6000_tdep ()
+{
+ /* FIXME, this should not be decided via ifdef. */
+#ifdef GDB_TARGET_POWERPC
+ tm_print_insn = gdb_print_insn_powerpc;
+#else
+ tm_print_insn = print_insn_rs6000;
+#endif
+
+ /* I don't think we should use the set/show command arrangement
+ here, because the way that's implemented makes it hard to do the
+ error checking we want in a reasonable way. So we just add them
+ as two separate commands. */
+ add_cmd ("processor", class_support, set_processor,
+ "`set processor NAME' sets the PowerPC/RS6000 variant to NAME.\n\
+If you set this, GDB will know about the special-purpose registers that are\n\
+available on the given variant.\n\
+Type `set processor' alone for a list of recognized variant names.",
+ &setlist);
+ add_cmd ("processor", class_support, show_processor,
+ "Show the variant of the PowerPC or RS6000 processor in use.\n\
+Use `set processor' to change this.",
+ &showlist);
+
+ /* Set the current PPC processor variant. */
+ {
+ int status = 1;
+
+#ifdef TARGET_CPU_DEFAULT
+ status = install_variant_by_name (TARGET_CPU_DEFAULT);
+#endif
+
+ if (status)
+ {
+#ifdef GDB_TARGET_POWERPC
+ install_variant_by_name ("ppc-uisa");
+#else
+ install_variant_by_name ("rs6000");
+#endif
+ }
+ }
+}
diff --git a/gdb/saber.suppress b/gdb/saber.suppress
new file mode 100644
index 00000000000..6dda1c5f2da
--- /dev/null
+++ b/gdb/saber.suppress
@@ -0,0 +1,451 @@
+
+
+/* Options for project */
+unsetopt ansi
+setopt auto_compile
+unsetopt auto_reload
+setopt auto_replace
+unsetopt batch_load
+unsetopt batch_run
+unsetopt cc_prog
+setopt ccargs -g
+unsetopt create_file
+unsetopt debug_child
+unsetopt echo
+setopt edit_jobs 5
+unsetopt eight_bit
+setopt line_edit
+setopt line_meta
+setopt lint_load 2
+setopt lint_run 2
+setopt list_action
+setopt load_flags -I. -g -I.. -I../vx-share
+unsetopt long_not_int
+unsetopt make_args
+setopt make_hfiles
+unsetopt make_offset
+unsetopt make_prog
+setopt make_symbol #
+setopt mem_config 16384
+unsetopt mem_trace
+setopt num_proc 1
+unsetopt page_cmds
+setopt page_list 19
+unsetopt page_load
+unsetopt path
+setopt proto_path . /s2/saber_dir30/sun4-40/proto /s2/saber_dir30/sun4-40/../common/proto
+unsetopt preprocessor
+setopt program_name a.out
+unsetopt print_custom
+setopt print_pointer
+setopt print_string 20
+unsetopt save_memory
+setopt sbrk_size 1048576
+setopt src_err 3
+setopt src_step 1
+setopt src_stop 3
+setopt sys_load_flags -L/lib -L/usr/lib -L/usr/local/lib -I/usr/include -Dunix -Dsun -Dsparc
+unsetopt tab_stop
+unsetopt terse_suppress
+unsetopt terse_where
+setopt unset_value 191
+unsetopt win_fork_nodup
+setopt win_no_raise
+unsetopt win_message_list
+unsetopt win_project_list
+/* Suppressions for project */
+suppress 6 in read_huge_number
+/* Over/underflow <plus> */
+suppress 8 in read_huge_number
+/* Over/underflow <multiply> */
+suppress 22
+/* Pointer subtraction */
+suppress 22 in free_all_psymtabs
+/* Pointer subtraction */
+suppress 22 in free_all_symtabs
+/* Pointer subtraction */
+suppress 56 in print_string
+/* Information lost <function> */
+suppress 65 "../bfd/bfd.c":379
+/* Too many function arguments */
+suppress 65 on printf_filtered
+/* Too many function arguments */
+suppress 65 on fprintf_filtered
+/* Too many function arguments */
+suppress 65 on vfprintf_filtered
+/* Too many function arguments */
+suppress 65 on query
+/* Too many function arguments */
+suppress 65 on fatal_dump_core
+/* Too many function arguments */
+suppress 65 on fatal
+/* Too many function arguments */
+suppress 65 on error
+/* Too many function arguments */
+suppress 65 on noprocess
+/* Too many function arguments */
+suppress 65
+/* Too many function arguments */
+suppress 66 on say
+/* Too few function arguments */
+suppress 66 on printf_filtered
+/* Too few function arguments */
+suppress 66 on fprintf_filtered
+/* Too few function arguments */
+suppress 66 on vfprintf_filtered
+/* Too few function arguments */
+suppress 66 on query
+/* Too few function arguments */
+suppress 66 on fatal_dump_core
+/* Too few function arguments */
+suppress 66 on fatal
+/* Too few function arguments */
+suppress 66 on error
+/* Too few function arguments */
+suppress 67 on printf_filtered
+/* Signed/unsigned argument mismatch */
+suppress 67 on fprintf_filtered
+/* Signed/unsigned argument mismatch */
+suppress 67 on vfprintf_filtered
+/* Signed/unsigned argument mismatch */
+suppress 67 on query
+/* Signed/unsigned argument mismatch */
+suppress 67 on fatal_dump_core
+/* Signed/unsigned argument mismatch */
+suppress 67 on fatal
+/* Signed/unsigned argument mismatch */
+suppress 67 on error
+/* Signed/unsigned argument mismatch */
+suppress 67
+/* Signed/unsigned argument mismatch */
+suppress 68 on bfd_get_section_contents
+/* Benign argument mismatch */
+suppress 68 on _do_getblong
+/* Benign argument mismatch */
+suppress 68 on supply_register
+/* Benign argument mismatch */
+suppress 68 on target_write_memory
+/* Benign argument mismatch */
+suppress 68 on write_register_bytes
+/* Benign argument mismatch */
+suppress 68 on read_register_bytes
+/* Benign argument mismatch */
+suppress 68 on read_memory
+/* Benign argument mismatch */
+suppress 68 on say
+/* Benign argument mismatch */
+suppress 68 on printf_filtered
+/* Benign argument mismatch */
+suppress 68 on fprintf_filtered
+/* Benign argument mismatch */
+suppress 68 on vfprintf_filtered
+/* Benign argument mismatch */
+suppress 68 on query
+/* Benign argument mismatch */
+suppress 68 on fatal_dump_core
+/* Benign argument mismatch */
+suppress 68 on fatal
+/* Benign argument mismatch */
+suppress 68 on error
+/* Benign argument mismatch */
+suppress 68 in find_solib
+/* Benign argument mismatch */
+suppress 68 on child_wait
+/* Benign argument mismatch */
+suppress 68 on xrealloc
+/* Benign argument mismatch */
+suppress 68 on myread
+/* Benign argument mismatch */
+suppress 68 in do_cleanups
+/* Benign argument mismatch */
+suppress 68 on make_cleanup
+/* Benign argument mismatch */
+suppress 68 on target_read_memory
+/* Benign argument mismatch */
+suppress 69 on printf_filtered
+/* Serious argument mismatch */
+suppress 69 on fprintf_filtered
+/* Serious argument mismatch */
+suppress 69 on vfprintf_filtered
+/* Serious argument mismatch */
+suppress 69 on query
+/* Serious argument mismatch */
+suppress 69 on fatal_dump_core
+/* Serious argument mismatch */
+suppress 69 on fatal
+/* Serious argument mismatch */
+suppress 69 on error
+/* Serious argument mismatch */
+suppress 70 on printf_filtered
+/* Passing illegal enumeration value */
+suppress 70 on fprintf_filtered
+/* Passing illegal enumeration value */
+suppress 70 on vfprintf_filtered
+/* Passing illegal enumeration value */
+suppress 70 on query
+/* Passing illegal enumeration value */
+suppress 70 on fatal_dump_core
+/* Passing illegal enumeration value */
+suppress 70 on fatal
+/* Passing illegal enumeration value */
+suppress 70 on error
+/* Passing illegal enumeration value */
+suppress 80 on first_link_map_member
+/* Returning invalid pointer */
+suppress 110 in printf_filtered
+/* Signed/unsigned memory retrieval */
+suppress 110 in fprintf_filtered
+/* Signed/unsigned memory retrieval */
+suppress 110 in vfprintf_filtered
+/* Signed/unsigned memory retrieval */
+suppress 110 in query
+/* Signed/unsigned memory retrieval */
+suppress 110 in fatal_dump_core
+/* Signed/unsigned memory retrieval */
+suppress 110 in fatal
+/* Signed/unsigned memory retrieval */
+suppress 110 in error
+/* Signed/unsigned memory retrieval */
+suppress 112 in printf_filtered
+/* Memory retrieval */
+suppress 112 in fprintf_filtered
+/* Memory retrieval */
+suppress 112 in vfprintf_filtered
+/* Memory retrieval */
+suppress 112 in query
+/* Memory retrieval */
+suppress 112 in fatal_dump_core
+/* Memory retrieval */
+suppress 112 in fatal
+/* Memory retrieval */
+suppress 112 in error
+/* Memory retrieval */
+suppress 112
+/* Memory retrieval */
+suppress 112 ../symtab.c
+/* Memory retrieval */
+suppress 112 in child_xfer_memory
+/* Memory retrieval */
+suppress 165 in frame_saved_pc
+/* Dereference */
+suppress 165 in get_prev_frame_info
+/* Dereference */
+suppress 167 in get_prev_frame_info
+/* Selection */
+suppress 167 in frame_saved_pc
+/* Selection */
+suppress 442 in try_baudrate
+/* Escape has null value */
+suppress 529 in read_range_type
+/* Statement not reached */
+suppress 529 in process_one_symbol
+/* Statement not reached */
+suppress 529 in unpack_double
+/* Statement not reached */
+suppress 529 in wait_for_inferior
+/* Statement not reached */
+suppress 529 in do_registers_info
+/* Statement not reached */
+suppress 529 in value_from_register
+/* Statement not reached */
+suppress 529 in solib_create_inferior_hook
+/* Constant in conditional */
+suppress 530
+/* Empty body of statement */
+suppress 546 in net_quit
+/* Function exits through bottom */
+suppress 546 in net_wait
+/* Function exits through bottom */
+suppress 546 in vx_remove_breakpoint
+/* Function exits through bottom */
+suppress 546 in vx_insert_breakpoint
+/* Function exits through bottom */
+suppress 546 in value_less
+/* Function exits through bottom */
+suppress 546 in value_equal
+/* Function exits through bottom */
+suppress 546 in unpack_long
+/* Function exits through bottom */
+suppress 558 in solib_create_inferior_hook
+/* Constant in conditional */
+suppress 558 in read_range_type
+/* Constant in conditional */
+suppress 558 in process_one_symbol
+/* Constant in conditional */
+suppress 558 in read_dbx_symtab
+/* Constant in conditional */
+suppress 558 in vx_write_register
+/* Constant in conditional */
+suppress 558 in vx_read_register
+/* Constant in conditional */
+suppress 558 in unpack_double
+/* Constant in conditional */
+suppress 558 in wait_for_inferior
+/* Constant in conditional */
+suppress 558 in do_registers_info
+/* Constant in conditional */
+suppress 558 in value_from_register
+/* Constant in conditional */
+suppress 558 in add_enum_psymbol
+/* Constant in conditional */
+suppress 558 in add_partial_symbol
+/* Constant in conditional */
+suppress 558 mfree.c
+/* Constant in conditional */
+suppress 558 mmalloc.c
+/* Constant in conditional */
+suppress 558 mrealloc.c
+/* Constant in conditional */
+suppress 560 in solib_address
+/* Assignment within conditional */
+suppress 560 in solib_info
+/* Assignment within conditional */
+suppress 560 in solib_add
+/* Assignment within conditional */
+suppress 560 in read_type
+/* Assignment within conditional */
+suppress 560 in type_print_base
+/* Assignment within conditional */
+suppress 560 in type_print_derivation_info
+/* Assignment within conditional */
+suppress 560 in block_depth
+/* Assignment within conditional */
+suppress 560 in select_source_symtab
+/* Assignment within conditional */
+suppress 560 in clear_value_history
+/* Assignment within conditional */
+suppress 560 in clear_displays
+/* Assignment within conditional */
+suppress 560 in initialize_main
+/* Assignment within conditional */
+suppress 560 in echo_command
+/* Assignment within conditional */
+suppress 560 in unset_in_environ
+/* Assignment within conditional */
+suppress 560 in set_in_environ
+/* Assignment within conditional */
+suppress 560 in get_in_environ
+/* Assignment within conditional */
+suppress 560 in do_setshow_command
+/* Assignment within conditional */
+suppress 560 in breakpoint_1
+/* Assignment within conditional */
+suppress 590 on sig
+/* Unused formal parameter */
+suppress 590 in nindy_create_inferior
+/* Unused formal parameter */
+suppress 590 in add_to_section_table
+/* Unused formal parameter */
+suppress 590 in vx_create_inferior
+/* Unused formal parameter */
+suppress 590 in host_convert_from_virtual
+/* Unused formal parameter */
+suppress 590 in host_convert_to_virtual
+/* Unused formal parameter */
+suppress 590 on siggnal
+/* Unused formal parameter */
+suppress 590 in init_sig
+/* Unused formal parameter */
+suppress 590 in nindy_resume
+/* Unused formal parameter */
+suppress 590 in set_history_size_command
+/* Unused formal parameter */
+suppress 590 in not_just_help_class_command
+/* Unused formal parameter */
+suppress 590 on regno
+/* Unused formal parameter */
+suppress 590 on from_tty
+/* Unused formal parameter */
+suppress 590 on args
+/* Unused formal parameter */
+suppress 590 in process_symbol_pair
+/* Unused formal parameter */
+suppress 591 in print_scalar_formatted
+/* Unused automatic variable */
+suppress 592 on rcsid
+/* Unused static */
+suppress 594 in call_function_by_hand
+/* Set but not used */
+suppress 594 in record_latest_value
+/* Set but not used */
+suppress 594 in bpstat_stop_status
+/* Set but not used */
+suppress 595 in coffstrip
+/* Used before set */
+suppress 652 ../include/bfd.h
+/* Declaration has no effect */
+suppress 652 /usr/include/machine/reg.h
+/* Declaration has no effect */
+suppress 652 /usr/include/sun4/reg.h
+/* Declaration has no effect */
+suppress 68 on complain
+/* Benign type mismatch */
+suppress 3 in read_range_type
+/* Over/underflow unary minus */
+suppress 442 ../bfd/archive.c
+/* \0 in string */
+suppress 558 ../bfd/b.out.c
+/* Conditional if always true */
+suppress 558 ../bfd/coffswap.c
+/* Conditional if always true -- bfd_h_put_x */
+suppress 529 ../bfd/coffswap.c
+/* Stmt unreach -- bfd_h_put_x */
+suppress 590 ../bfd/ecoff.c
+/* Formal parameter not used */
+suppress 590 on ignore
+/* Formal param not used */
+suppress 590 on ignore_exec_bfd
+/* Formal param not used */
+suppress 590 on ignore_core_bfd
+/* Formal param not used */
+suppress 590 on ignore_input_section
+/* Formal param not used */
+suppress 590 on ignore_newsect
+/* Formal param not used */
+suppress 590 on ignore_abfd
+/* Formal param not used */
+suppress 590 on ignore_symbol
+/* Formal param not used */
+suppress 590 on ignore_symbols
+/* Formal param not used */
+suppress 590 on signo
+/* Formal param not used */
+suppress 652
+/* The declaration has no effect */
+suppress 442 in ../bfd/archive.c
+/* Escape sequence in string literal has null value */
+
+/* Signals caught and ignored */
+catch HUP
+catch QUIT
+catch ILL
+catch TRAP
+catch IOT
+catch EMT
+catch FPE
+catch KILL
+catch BUS
+catch SEGV
+catch SYS
+catch PIPE
+catch TERM
+catch URG
+catch STOP
+catch TSTP
+catch TTIN
+catch TTOU
+catch IO
+catch XCPU
+catch XFSZ
+catch VTALRM
+catch PROF
+catch LOST
+catch USR1
+catch USR2
+ignore INT
+ignore ALRM
+ignore CONT
+ignore CHLD
+ignore WINCH
+
+/* Status of project */
diff --git a/gdb/scm-exp.c b/gdb/scm-exp.c
new file mode 100644
index 00000000000..63995639dcf
--- /dev/null
+++ b/gdb/scm-exp.c
@@ -0,0 +1,423 @@
+/* Scheme/Guile language support routines for GDB, the GNU debugger.
+ Copyright 1995 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "symtab.h"
+#include "gdbtypes.h"
+#include "expression.h"
+#include "parser-defs.h"
+#include "language.h"
+#include "value.h"
+#include "c-lang.h"
+#include "scm-lang.h"
+#include "scm-tags.h"
+
+#define USE_EXPRSTRING 0
+
+static void scm_lreadparen PARAMS ((int));
+static int scm_skip_ws PARAMS ((void));
+static void scm_read_token PARAMS ((int, int));
+static LONGEST scm_istring2number PARAMS ((char *, int, int));
+static LONGEST scm_istr2int PARAMS ((char *, int, int));
+static void scm_lreadr PARAMS ((int));
+
+static LONGEST
+scm_istr2int(str, len, radix)
+ char *str;
+ int len;
+ int radix;
+{
+ int i = 0;
+ LONGEST inum = 0;
+ int c;
+ int sign = 0;
+
+ if (0 >= len) return SCM_BOOL_F; /* zero scm_length */
+ switch (str[0])
+ { /* leading sign */
+ case '-':
+ case '+':
+ sign = str[0];
+ if (++i==len)
+ return SCM_BOOL_F; /* bad if lone `+' or `-' */
+ }
+ do {
+ switch (c = str[i++]) {
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ c = c - '0';
+ goto accumulate;
+ case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
+ c = c-'A'+10;
+ goto accumulate;
+ case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
+ c = c-'a'+10;
+ accumulate:
+ if (c >= radix) return SCM_BOOL_F; /* bad digit for radix */
+ inum *= radix;
+ inum += c;
+ break;
+ default:
+ return SCM_BOOL_F; /* not a digit */
+ }
+ } while (i < len);
+ if (sign == '-')
+ inum = -inum;
+ return SCM_MAKINUM (inum);
+}
+
+static LONGEST
+scm_istring2number(str, len, radix)
+ char *str;
+ int len;
+ int radix;
+{
+ int i = 0;
+ char ex = 0;
+ char ex_p = 0, rx_p = 0; /* Only allow 1 exactness and 1 radix prefix */
+#if 0
+ SCM res;
+#endif
+ if (len==1)
+ if (*str=='+' || *str=='-') /* Catches lone `+' and `-' for speed */
+ return SCM_BOOL_F;
+
+ while ((len-i) >= 2 && str[i]=='#' && ++i)
+ switch (str[i++]) {
+ case 'b': case 'B': if (rx_p++) return SCM_BOOL_F; radix = 2; break;
+ case 'o': case 'O': if (rx_p++) return SCM_BOOL_F; radix = 8; break;
+ case 'd': case 'D': if (rx_p++) return SCM_BOOL_F; radix = 10; break;
+ case 'x': case 'X': if (rx_p++) return SCM_BOOL_F; radix = 16; break;
+ case 'i': case 'I': if (ex_p++) return SCM_BOOL_F; ex = 2; break;
+ case 'e': case 'E': if (ex_p++) return SCM_BOOL_F; ex = 1; break;
+ default: return SCM_BOOL_F;
+ }
+
+ switch (ex) {
+ case 1:
+ return scm_istr2int(&str[i], len-i, radix);
+ case 0:
+ return scm_istr2int(&str[i], len-i, radix);
+#if 0
+ if NFALSEP(res) return res;
+#ifdef FLOATS
+ case 2: return scm_istr2flo(&str[i], len-i, radix);
+#endif
+#endif
+ }
+ return SCM_BOOL_F;
+}
+
+static void
+scm_read_token (c, weird)
+ int c;
+ int weird;
+{
+ while (1)
+ {
+ c = *lexptr++;
+ switch (c)
+ {
+ case '[':
+ case ']':
+ case '(':
+ case ')':
+ case '\"':
+ case ';':
+ case ' ': case '\t': case '\r': case '\f':
+ case '\n':
+ if (weird)
+ goto default_case;
+ case '\0': /* End of line */
+ eof_case:
+ --lexptr;
+ return;
+ case '\\':
+ if (!weird)
+ goto default_case;
+ else
+ {
+ c = *lexptr++;
+ if (c == '\0')
+ goto eof_case;
+ else
+ goto default_case;
+ }
+ case '}':
+ if (!weird)
+ goto default_case;
+
+ c = *lexptr++;
+ if (c == '#')
+ return;
+ else
+ {
+ --lexptr;
+ c = '}';
+ goto default_case;
+ }
+
+ default:
+ default_case:
+ ;
+ }
+ }
+}
+
+static int
+scm_skip_ws ()
+{
+ register int c;
+ while (1)
+ switch ((c = *lexptr++))
+ {
+ case '\0':
+ goteof:
+ return c;
+ case ';':
+ lp:
+ switch ((c = *lexptr++))
+ {
+ case '\0':
+ goto goteof;
+ default:
+ goto lp;
+ case '\n':
+ break;
+ }
+ case ' ': case '\t': case '\r': case '\f': case '\n':
+ break;
+ default:
+ return c;
+ }
+}
+
+static void
+scm_lreadparen (skipping)
+ int skipping;
+{
+ for (;;)
+ {
+ int c = scm_skip_ws ();
+ if (')' == c || ']' == c)
+ return;
+ --lexptr;
+ if (c == '\0')
+ error ("missing close paren");
+ scm_lreadr (skipping);
+ }
+}
+
+static void
+scm_lreadr (skipping)
+ int skipping;
+{
+ int c, j;
+ struct stoken str;
+ LONGEST svalue = 0;
+ tryagain:
+ c = *lexptr++;
+ switch (c)
+ {
+ case '\0':
+ lexptr--;
+ return;
+ case '[':
+ case '(':
+ scm_lreadparen (skipping);
+ return;
+ case ']':
+ case ')':
+ error ("unexpected #\\%c", c);
+ goto tryagain;
+ case '\'':
+ case '`':
+ str.ptr = lexptr - 1;
+ scm_lreadr (skipping);
+ if (!skipping)
+ {
+ value_ptr val = scm_evaluate_string (str.ptr, lexptr - str.ptr);
+ if (!is_scmvalue_type (VALUE_TYPE (val)))
+ error ("quoted scm form yields non-SCM value");
+ svalue = extract_signed_integer (VALUE_CONTENTS (val),
+ TYPE_LENGTH (VALUE_TYPE (val)));
+ goto handle_immediate;
+ }
+ return;
+ case ',':
+ c = *lexptr++;
+ if ('@' != c)
+ lexptr--;
+ scm_lreadr (skipping);
+ return;
+ case '#':
+ c = *lexptr++;
+ switch (c)
+ {
+ case '[':
+ case '(':
+ scm_lreadparen (skipping);
+ return;
+ case 't': case 'T':
+ svalue = SCM_BOOL_T;
+ goto handle_immediate;
+ case 'f': case 'F':
+ svalue = SCM_BOOL_F;
+ goto handle_immediate;
+ case 'b': case 'B':
+ case 'o': case 'O':
+ case 'd': case 'D':
+ case 'x': case 'X':
+ case 'i': case 'I':
+ case 'e': case 'E':
+ lexptr--;
+ c = '#';
+ goto num;
+ case '*': /* bitvector */
+ scm_read_token (c, 0);
+ return;
+ case '{':
+ scm_read_token (c, 1);
+ return;
+ case '\\': /* character */
+ c = *lexptr++;
+ scm_read_token (c, 0);
+ return;
+ case '|':
+ j = 1; /* here j is the comment nesting depth */
+ lp:
+ c = *lexptr++;
+ lpc:
+ switch (c)
+ {
+ case '\0':
+ error ("unbalanced comment");
+ default:
+ goto lp;
+ case '|':
+ if ('#' != (c = *lexptr++))
+ goto lpc;
+ if (--j)
+ goto lp;
+ break;
+ case '#':
+ if ('|' != (c = *lexptr++))
+ goto lpc;
+ ++j;
+ goto lp;
+ }
+ goto tryagain;
+ case '.':
+ default:
+#if 0
+ callshrp:
+#endif
+ scm_lreadr (skipping);
+ return;
+ }
+ case '\"':
+ while ('\"' != (c = *lexptr++))
+ {
+ if (c == '\\')
+ switch (c = *lexptr++)
+ {
+ case '\0':
+ error ("non-terminated string literal");
+ case '\n':
+ continue;
+ case '0':
+ case 'f':
+ case 'n':
+ case 'r':
+ case 't':
+ case 'a':
+ case 'v':
+ break;
+ }
+ }
+ return;
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ case '.':
+ case '-':
+ case '+':
+ num:
+ {
+ str.ptr = lexptr-1;
+ scm_read_token (c, 0);
+ if (!skipping)
+ {
+ svalue = scm_istring2number (str.ptr, lexptr - str.ptr, 10);
+ if (svalue != SCM_BOOL_F)
+ goto handle_immediate;
+ goto tok;
+ }
+ }
+ return;
+ case ':':
+ scm_read_token ('-', 0);
+ return;
+#if 0
+ do_symbol:
+#endif
+ default:
+ str.ptr = lexptr-1;
+ scm_read_token (c, 0);
+ tok:
+ if (!skipping)
+ {
+ str.length = lexptr - str.ptr;
+ if (str.ptr[0] == '$')
+ {
+ write_dollar_variable (str);
+ return;
+ }
+ write_exp_elt_opcode (OP_NAME);
+ write_exp_string (str);
+ write_exp_elt_opcode (OP_NAME);
+ }
+ return;
+ }
+ handle_immediate:
+ if (!skipping)
+ {
+ write_exp_elt_opcode (OP_LONG);
+ write_exp_elt_type (builtin_type_scm);
+ write_exp_elt_longcst (svalue);
+ write_exp_elt_opcode (OP_LONG);
+ }
+}
+
+int
+scm_parse ()
+{
+ char* start;
+ while (*lexptr == ' ')
+ lexptr++;
+ start = lexptr;
+ scm_lreadr (USE_EXPRSTRING);
+#if USE_EXPRSTRING
+ str.length = lexptr - start;
+ str.ptr = start;
+ write_exp_elt_opcode (OP_EXPRSTRING);
+ write_exp_string (str);
+ write_exp_elt_opcode (OP_EXPRSTRING);
+#endif
+ return 0;
+}
diff --git a/gdb/scm-lang.c b/gdb/scm-lang.c
new file mode 100644
index 00000000000..7f31ba43483
--- /dev/null
+++ b/gdb/scm-lang.c
@@ -0,0 +1,274 @@
+/* Scheme/Guile language support routines for GDB, the GNU debugger.
+ Copyright 1995 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "symtab.h"
+#include "gdbtypes.h"
+#include "expression.h"
+#include "parser-defs.h"
+#include "language.h"
+#include "value.h"
+#include "c-lang.h"
+#include "scm-lang.h"
+#include "scm-tags.h"
+#include "gdb_string.h"
+#include "gdbcore.h"
+
+static value_ptr evaluate_subexp_scm PARAMS ((struct type *, struct expression *,
+ int *, enum noside));
+static value_ptr scm_lookup_name PARAMS ((char *));
+static int in_eval_c PARAMS ((void));
+static void scm_printstr PARAMS ((GDB_FILE *stream, char *string, unsigned int length, int width, int force_ellipses));
+
+extern struct type ** CONST_PTR (c_builtin_types[]);
+
+struct type *builtin_type_scm;
+
+void
+scm_printchar (c, stream)
+ int c;
+ GDB_FILE *stream;
+{
+ fprintf_filtered (stream, "#\\%c", c);
+}
+
+static void
+scm_printstr (stream, string, length, width, force_ellipses)
+ GDB_FILE *stream;
+ char *string;
+ unsigned int length;
+ int width;
+ int force_ellipses;
+{
+ fprintf_filtered (stream, "\"%s\"", string);
+}
+
+int
+is_scmvalue_type (type)
+ struct type *type;
+{
+ if (TYPE_CODE (type) == TYPE_CODE_INT
+ && TYPE_NAME (type) && strcmp (TYPE_NAME (type), "SCM") == 0)
+ {
+ return 1;
+ }
+ return 0;
+}
+
+/* Get the INDEX'th SCM value, assuming SVALUE is the address
+ of the 0'th one. */
+
+LONGEST
+scm_get_field (svalue, index)
+ LONGEST svalue;
+ int index;
+{
+ char buffer[20];
+ read_memory (SCM2PTR (svalue) + index * TYPE_LENGTH (builtin_type_scm),
+ buffer, TYPE_LENGTH (builtin_type_scm));
+ return extract_signed_integer (buffer, TYPE_LENGTH (builtin_type_scm));
+}
+
+/* Unpack a value of type TYPE in buffer VALADDR as an integer
+ (if CONTEXT == TYPE_CODE_IN), a pointer (CONTEXT == TYPE_CODE_PTR),
+ or Boolean (CONTEXT == TYPE_CODE_BOOL). */
+
+LONGEST
+scm_unpack (type, valaddr, context)
+ struct type *type;
+ char *valaddr;
+ enum type_code context;
+{
+ if (is_scmvalue_type (type))
+ {
+ LONGEST svalue = extract_signed_integer (valaddr, TYPE_LENGTH (type));
+ if (context == TYPE_CODE_BOOL)
+ {
+ if (svalue == SCM_BOOL_F)
+ return 0;
+ else
+ return 1;
+ }
+ switch (7 & (int) svalue)
+ {
+ case 2: case 6: /* fixnum */
+ return svalue >> 2;
+ case 4: /* other immediate value */
+ if (SCM_ICHRP (svalue)) /* character */
+ return SCM_ICHR (svalue);
+ else if (SCM_IFLAGP (svalue))
+ {
+ switch ((int) svalue)
+ {
+#ifndef SICP
+ case SCM_EOL:
+#endif
+ case SCM_BOOL_F:
+ return 0;
+ case SCM_BOOL_T:
+ return 1;
+ }
+ }
+ error ("Value can't be converted to integer.");
+ default:
+ return svalue;
+ }
+ }
+ else
+ return unpack_long (type, valaddr);
+}
+
+/* True if we're correctly in Guile's eval.c (the evaluator and apply). */
+
+static int
+in_eval_c ()
+{
+ if (current_source_symtab && current_source_symtab->filename)
+ {
+ char *filename = current_source_symtab->filename;
+ int len = strlen (filename);
+ if (len >= 6 && strcmp (filename + len - 6, "eval.c") == 0)
+ return 1;
+ }
+ return 0;
+}
+
+/* Lookup a value for the variable named STR.
+ First lookup in Scheme context (using the scm_lookup_cstr inferior
+ function), then try lookup_symbol for compiled variables. */
+
+static value_ptr
+scm_lookup_name (str)
+ char *str;
+{
+ value_ptr args[3];
+ int len = strlen (str);
+ value_ptr func, val;
+ struct symbol *sym;
+ args[0] = value_allocate_space_in_inferior (len);
+ args[1] = value_from_longest (builtin_type_int, len);
+ write_memory (value_as_long (args[0]), str, len);
+
+ if (in_eval_c ()
+ && (sym = lookup_symbol ("env",
+ expression_context_block,
+ VAR_NAMESPACE, (int *) NULL,
+ (struct symtab **) NULL)) != NULL)
+ args[2] = value_of_variable (sym, expression_context_block);
+ else
+ /* FIXME in this case, we should try lookup_symbol first */
+ args[2] = value_from_longest (builtin_type_scm, SCM_EOL);
+
+ func = find_function_in_inferior ("scm_lookup_cstr");
+ val = call_function_by_hand (func, 3, args);
+ if (!value_logical_not (val))
+ return value_ind (val);
+
+ sym = lookup_symbol (str,
+ expression_context_block,
+ VAR_NAMESPACE, (int *) NULL,
+ (struct symtab **) NULL);
+ if (sym)
+ return value_of_variable (sym, NULL);
+ error ("No symbol \"%s\" in current context.");
+}
+
+value_ptr
+scm_evaluate_string (str, len)
+ char *str; int len;
+{
+ value_ptr func;
+ value_ptr addr = value_allocate_space_in_inferior (len + 1);
+ LONGEST iaddr = value_as_long (addr);
+ write_memory (iaddr, str, len);
+ /* FIXME - should find and pass env */
+ write_memory (iaddr + len, "", 1);
+ func = find_function_in_inferior ("scm_evstr");
+ return call_function_by_hand (func, 1, &addr);
+}
+
+static value_ptr
+evaluate_subexp_scm (expect_type, exp, pos, noside)
+ struct type *expect_type;
+ register struct expression *exp;
+ register int *pos;
+ enum noside noside;
+{
+ enum exp_opcode op = exp->elts[*pos].opcode;
+ int len, pc; char *str;
+ switch (op)
+ {
+ case OP_NAME:
+ pc = (*pos)++;
+ len = longest_to_int (exp->elts[pc + 1].longconst);
+ (*pos) += 3 + BYTES_TO_EXP_ELEM (len + 1);
+ if (noside == EVAL_SKIP)
+ goto nosideret;
+ str = &exp->elts[pc + 2].string;
+ return scm_lookup_name (str);
+ case OP_EXPRSTRING:
+ pc = (*pos)++;
+ len = longest_to_int (exp->elts[pc + 1].longconst);
+ (*pos) += 3 + BYTES_TO_EXP_ELEM (len + 1);
+ if (noside == EVAL_SKIP)
+ goto nosideret;
+ str = &exp->elts[pc + 2].string;
+ return scm_evaluate_string (str, len);
+ default: ;
+ }
+ return evaluate_subexp_standard (expect_type, exp, pos, noside);
+ nosideret:
+ return value_from_longest (builtin_type_long, (LONGEST) 1);
+}
+
+const struct language_defn scm_language_defn = {
+ "scheme", /* Language name */
+ language_scm,
+ c_builtin_types,
+ range_check_off,
+ type_check_off,
+ scm_parse,
+ c_error,
+ evaluate_subexp_scm,
+ scm_printchar, /* Print a character constant */
+ scm_printstr, /* Function to print string constant */
+ NULL, /* Function to print a single character */
+ NULL, /* Create fundamental type in this language */
+ c_print_type, /* Print a type using appropriate syntax */
+ scm_val_print, /* Print a value using appropriate syntax */
+ scm_value_print, /* Print a top-level value */
+ {"", "", "", ""}, /* Binary format info */
+ {"#o%lo", "#o", "o", ""}, /* Octal format info */
+ {"%ld", "", "d", ""}, /* Decimal format info */
+ {"#x%lX", "#X", "X", ""}, /* Hex format info */
+ NULL, /* expression operators for printing */
+ 1, /* c-style arrays */
+ 0, /* String lower bound */
+ &builtin_type_char, /* Type of string elements */
+ LANG_MAGIC
+};
+
+void
+_initialize_scheme_language ()
+{
+ add_language (&scm_language_defn);
+ builtin_type_scm = init_type (TYPE_CODE_INT,
+ TARGET_LONG_BIT / TARGET_CHAR_BIT,
+ 0, "SCM", (struct objfile *) NULL);
+}
diff --git a/gdb/scm-lang.h b/gdb/scm-lang.h
new file mode 100644
index 00000000000..878a2ab20ea
--- /dev/null
+++ b/gdb/scm-lang.h
@@ -0,0 +1,50 @@
+#define SICP
+#include "scm-tags.h"
+#undef SCM_NCELLP
+#define SCM_NCELLP(x) ((SCM_SIZE-1) & (int)(x))
+#define SCM_ITAG8_DATA(X) ((X)>>8)
+#define SCM_ICHR(x) ((unsigned char)SCM_ITAG8_DATA(x))
+#define SCM_ICHRP(x) (SCM_ITAG8(x) == scm_tc8_char)
+#define scm_tc8_char 0xf4
+#define SCM_IFLAGP(n) ((0x87 & (int)(n))==4)
+#define SCM_ISYMNUM(n) ((int)((n)>>9))
+#define SCM_ISYMCHARS(n) (scm_isymnames[SCM_ISYMNUM(n)])
+#define SCM_ILOCP(n) ((0xff & (int)(n))==0xfc)
+#define SCM_ITAG8(X) ((int)(X) & 0xff)
+#define SCM_TYP7(x) (0x7f & (int)SCM_CAR(x))
+#define SCM_LENGTH(x) (((unsigned long)SCM_CAR(x))>>8)
+#define SCM_NCONSP(x) (1 & (int)SCM_CAR(x))
+#define SCM_NECONSP(x) (SCM_NCONSP(x) && (1 != SCM_TYP3(x)))
+#define SCM_CAR(x) scm_get_field (x, 0)
+#define SCM_CDR(x) scm_get_field (x, 1)
+#define SCM_VELTS(x) ((SCM *)SCM_CDR(x))
+#define SCM_CLOSCAR(x) (SCM_CAR(x)-scm_tc3_closure)
+#define SCM_CODE(x) SCM_CAR(SCM_CLOSCAR (x))
+#define SCM_MAKINUM(x) (((x)<<2)+2L)
+
+#ifdef __STDC__ /* Forward decls for prototypes */
+struct value;
+#endif
+
+extern int scm_value_print PARAMS ((struct value *, GDB_FILE*,
+ int, enum val_prettyprint));
+
+extern int scm_val_print PARAMS ((struct type*, char*, int, CORE_ADDR, GDB_FILE*,
+ int, int, int, enum val_prettyprint));
+
+extern LONGEST scm_get_field PARAMS ((LONGEST, int));
+
+extern void scm_scmval_print PARAMS ((LONGEST, GDB_FILE *,
+ int, int, int, enum val_prettyprint));
+
+extern int is_scmvalue_type PARAMS ((struct type*));
+
+extern void scm_printchar PARAMS ((int, GDB_FILE*));
+
+extern struct value * scm_evaluate_string PARAMS ((char*, int));
+
+extern struct type *builtin_type_scm;
+
+extern int scm_parse PARAMS ((void));
+
+extern LONGEST scm_unpack PARAMS ((struct type *, char *, enum type_code));
diff --git a/gdb/scm-tags.h b/gdb/scm-tags.h
new file mode 100644
index 00000000000..fbe45cc1890
--- /dev/null
+++ b/gdb/scm-tags.h
@@ -0,0 +1,385 @@
+/* This is a minimally edited version of Guile's tags.h. */
+/* classes: h_files */
+
+#ifndef TAGSH
+#define TAGSH
+/* Copyright (C) 1995 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * As a special exception, the Free Software Foundation gives permission
+ * for additional uses of the text contained in its release of GUILE.
+ *
+ * The exception is that, if you link the GUILE library with other files
+ * to produce an executable, this does not by itself cause the
+ * resulting executable to be covered by the GNU General Public License.
+ * Your use of that executable is in no way restricted on account of
+ * linking the GUILE library code into it.
+ *
+ * This exception does not however invalidate any other reasons why
+ * the executable file might be covered by the GNU General Public License.
+ *
+ * This exception applies only to the code released by the
+ * Free Software Foundation under the name GUILE. If you copy
+ * code from other Free Software Foundation releases into a copy of
+ * GUILE, as the General Public License permits, the exception does
+ * not apply to the code that you add in this way. To avoid misleading
+ * anyone as to the status of such modified files, you must delete
+ * this exception notice from them.
+ *
+ * If you write modifications of your own for GUILE, it is your choice
+ * whether to permit this exception to apply to your modifications.
+ * If you do not wish that, delete this exception notice.
+ */
+
+
+/** This file defines the format of SCM values and cons pairs.
+ ** It is here that tag bits are assigned for various purposes.
+ **/
+
+
+/* Three Bit Tags
+ *
+ * 000 -- a non-immediate value. Points into the pair heap.
+ *
+ * 001 -- a gloc (i.e., a resolved global variable in a CAR in a code graph)
+ * or the CAR of an object handle (i.e., the tagged pointer to the
+ * vtable part of a user-defined object).
+ *
+ * If X has this tag, the value at CDAR(X - 1) distinguishes
+ * glocs from object handles. The distinction only needs
+ * to be made in a few places. Only a few parts of the code know
+ * about glocs. In most cases, when a value in the CAR of a pair
+ * has the tag 001, it means that the pair is an object handle.
+ *
+ * 010 -- the tag for immediate, exact integers.
+ *
+ * 011 -- in the CAR of a pair, this tag indicates that the pair is a closure.
+ * The remaining bits of the CAR are a pointer into the pair heap
+ * to the code graph for the closure.
+ *
+ * 1xy -- an extension tag which means that there is a five or six bit
+ * tag to the left of the low three bits. See the nice diagrams
+ * in ../doc/code.doc if you want to know what the bits mean.
+ */
+
+
+
+
+
+#define scm_tc3_cons 0
+#define scm_tc3_cons_gloc 1
+#define scm_tc3_closure 3
+
+#define scm_tc7_ssymbol 5
+#define scm_tc7_msymbol 7
+#define scm_tc7_string 13
+#define scm_tc7_bvect 15
+#define scm_tc7_vector 21
+#define scm_tc7_lvector 23
+#define scm_tc7_ivect 29
+#define scm_tc7_uvect 31
+/* spare 37 39 */
+#define scm_tc7_fvect 45
+#define scm_tc7_dvect 47
+#define scm_tc7_cvect 53
+#define scm_tc7_port 55
+#define scm_tc7_contin 61
+#define scm_tc7_cclo 63
+/* spare 69 71 77 79 */
+#define scm_tc7_subr_0 85
+#define scm_tc7_subr_1 87
+#define scm_tc7_cxr 93
+#define scm_tc7_subr_3 95
+#define scm_tc7_subr_2 101
+#define scm_tc7_asubr 103
+#define scm_tc7_subr_1o 109
+#define scm_tc7_subr_2o 111
+#define scm_tc7_lsubr_2 117
+#define scm_tc7_lsubr 119
+#define scm_tc7_rpsubr 125
+
+#define scm_tc7_smob 127
+#define scm_tc_free_cell 127
+
+#define scm_tc16_flo 0x017f
+#define scm_tc_flo 0x017fL
+
+#define SCM_REAL_PART (1L<<16)
+#define SCM_IMAG_PART (2L<<16)
+#define scm_tc_dblr (scm_tc16_flo|REAL_PART)
+#define scm_tc_dblc (scm_tc16_flo|REAL_PART|IMAG_PART)
+
+#define scm_tc16_bigpos 0x027f
+#define scm_tc16_bigneg 0x037f
+
+#define scm_tc16_fport (scm_tc7_port + 0*256L)
+#define scm_tc16_pipe (scm_tc7_port + 1*256L)
+#define scm_tc16_strport (scm_tc7_port + 2*256L)
+#define scm_tc16_sfport (scm_tc7_port + 3*256L)
+
+
+
+/* For cons pairs with immediate values in the CAR */
+#define scm_tcs_cons_imcar 2:case 4:case 6:case 10:\
+ case 12:case 14:case 18:case 20:\
+ case 22:case 26:case 28:case 30:\
+ case 34:case 36:case 38:case 42:\
+ case 44:case 46:case 50:case 52:\
+ case 54:case 58:case 60:case 62:\
+ case 66:case 68:case 70:case 74:\
+ case 76:case 78:case 82:case 84:\
+ case 86:case 90:case 92:case 94:\
+ case 98:case 100:case 102:case 106:\
+ case 108:case 110:case 114:case 116:\
+ case 118:case 122:case 124:case 126
+
+/* For cons pairs with non-immediate values in the CAR */
+#define scm_tcs_cons_nimcar 0:case 8:case 16:case 24:\
+ case 32:case 40:case 48:case 56:\
+ case 64:case 72:case 80:case 88:\
+ case 96:case 104:case 112:case 120
+
+/* A CONS_GLOC occurs in code. It's CAR is a pointer to the
+ * CDR of a variable. The low order bits of the CAR are 001.
+ * The CDR of the gloc is the code continuation.
+ */
+#define scm_tcs_cons_gloc 1:case 9:case 17:case 25:\
+ case 33:case 41:case 49:case 57:\
+ case 65:case 73:case 81:case 89:\
+ case 97:case 105:case 113:case 121
+
+#define scm_tcs_closures 3:case 11:case 19:case 27:\
+ case 35:case 43:case 51:case 59:\
+ case 67:case 75:case 83:case 91:\
+ case 99:case 107:case 115:case 123
+
+#define scm_tcs_subrs scm_tc7_asubr:case scm_tc7_subr_0:case scm_tc7_subr_1:case scm_tc7_cxr:\
+ case scm_tc7_subr_3:case scm_tc7_subr_2:case scm_tc7_rpsubr:case scm_tc7_subr_1o:\
+ case scm_tc7_subr_2o:case scm_tc7_lsubr_2:case scm_tc7_lsubr
+
+#define scm_tcs_symbols scm_tc7_ssymbol:case scm_tc7_msymbol
+
+#define scm_tcs_bignums tc16_bigpos:case tc16_bigneg
+
+
+
+/* References to objects are of type SCM. Values may be non-immediate
+ * (pointers) or immediate (encoded, immutable, scalar values that fit
+ * in an SCM variable).
+ */
+
+typedef long SCM;
+
+/* Cray machines have pointers that are incremented once for each word,
+ * rather than each byte, the 3 most significant bits encode the byte
+ * within the word. The following macros deal with this by storing the
+ * native Cray pointers like the ones that looks like scm expects. This
+ * is done for any pointers that might appear in the car of a scm_cell, pointers
+ * to scm_vector elts, functions, &c are not munged.
+ */
+#ifdef _UNICOS
+# define SCM2PTR(x) ((int)(x) >> 3)
+# define PTR2SCM(x) (((SCM)(x)) << 3)
+# define SCM_POINTERS_MUNGED
+#else
+# define SCM2PTR(x) (x)
+# define PTR2SCM(x) ((SCM)(x))
+#endif /* def _UNICOS */
+
+
+
+/* Immediate? Predicates
+ */
+#define SCM_IMP(x) (6 & (int)(x))
+#define SCM_NIMP(x) (!SCM_IMP(x))
+
+
+
+enum scm_tags
+{
+ scm_tc8_char = 0xf4
+};
+
+#define SCM_ITAG8(X) ((int)(X) & 0xff)
+#define SCM_MAKE_ITAG8(X, TAG) (((X)<<8) + TAG)
+#define SCM_ITAG8_DATA(X) ((X)>>8)
+
+
+
+/* Local Environment Structure
+ */
+#define SCM_ILOCP(n) ((0xff & (int)(n))==0xfc)
+#define SCM_ILOC00 (0x000000fcL)
+#define SCM_IDINC (0x00100000L)
+#define SCM_ICDR (0x00080000L)
+#define SCM_IFRINC (0x00000100L)
+#define SCM_IDSTMSK (-SCM_IDINC)
+#define SCM_IFRAME(n) ((int)((SCM_ICDR-SCM_IFRINC)>>8) & ((int)(n)>>8))
+#define SCM_IDIST(n) (((unsigned long)(n))>>20)
+#define SCM_ICDRP(n) (SCM_ICDR & (n))
+
+
+/* Immediate Symbols, Special Symbols, Flags (various constants).
+ */
+
+/* ISYMP tests for ISPCSYM and ISYM */
+#define SCM_ISYMP(n) ((0x187 & (int)(n))==4)
+
+/* IFLAGP tests for ISPCSYM, ISYM and IFLAG */
+#define SCM_IFLAGP(n) ((0x87 & (int)(n))==4)
+#define SCM_ISYMNUM(n) ((int)((n)>>9))
+#define SCM_ISYMCHARS(n) (scm_isymnames[SCM_ISYMNUM(n)])
+#define SCM_MAKSPCSYM(n) (((n)<<9)+((n)<<3)+4L)
+#define SCM_MAKISYM(n) (((n)<<9)+0x74L)
+#define SCM_MAKIFLAG(n) (((n)<<9)+0x174L)
+
+/* This table must agree with the declarations
+ * in repl.c: {Names of immediate symbols}.
+ *
+ * These are used only in eval but their values
+ * have to be allocated here.
+ *
+ */
+
+#define SCM_IM_AND SCM_MAKSPCSYM(0)
+#define SCM_IM_BEGIN SCM_MAKSPCSYM(1)
+#define SCM_IM_CASE SCM_MAKSPCSYM(2)
+#define SCM_IM_COND SCM_MAKSPCSYM(3)
+#define SCM_IM_DO SCM_MAKSPCSYM(4)
+#define SCM_IM_IF SCM_MAKSPCSYM(5)
+#define SCM_IM_LAMBDA SCM_MAKSPCSYM(6)
+#define SCM_IM_LET SCM_MAKSPCSYM(7)
+#define SCM_IM_LETSTAR SCM_MAKSPCSYM(8)
+#define SCM_IM_LETREC SCM_MAKSPCSYM(9)
+#define SCM_IM_OR SCM_MAKSPCSYM(10)
+#define SCM_IM_QUOTE SCM_MAKSPCSYM(11)
+#define SCM_IM_SET SCM_MAKSPCSYM(12)
+#define SCM_IM_DEFINE SCM_MAKSPCSYM(13)
+#define SCM_IM_APPLY SCM_MAKISYM(14)
+#define SCM_IM_CONT SCM_MAKISYM(15)
+#define SCM_NUM_ISYMS 16
+
+/* Important immediates
+ */
+
+#define SCM_BOOL_F SCM_MAKIFLAG(SCM_NUM_ISYMS+0)
+#define SCM_BOOL_T SCM_MAKIFLAG(SCM_NUM_ISYMS+1)
+#define SCM_UNDEFINED SCM_MAKIFLAG(SCM_NUM_ISYMS+2)
+#define SCM_EOF_VAL SCM_MAKIFLAG(SCM_NUM_ISYMS+3)
+
+#ifdef SICP
+#define SCM_EOL SCM_BOOL_F
+#else
+#define SCM_EOL SCM_MAKIFLAG(SCM_NUM_ISYMS+4)
+#endif
+
+#define SCM_UNSPECIFIED SCM_MAKIFLAG(SCM_NUM_ISYMS+5)
+
+
+
+/* Heap Pairs and the Empty List Predicates
+ */
+#define SCM_NULLP(x) (SCM_EOL == (x))
+#define SCM_NNULLP(x) (SCM_EOL != (x))
+#define SCM_CELLP(x) (!SCM_NCELLP(x))
+#define SCM_NCELLP(x) ((sizeof(scm_cell)-1) & (int)(x))
+
+
+
+#define SCM_UNBNDP(x) (SCM_UNDEFINED==(x))
+
+
+
+/* Testing and Changing GC Marks in Various Standard Positions
+ */
+#define SCM_GCMARKP(x) (1 & (int)SCM_CDR(x))
+#define SCM_GC8MARKP(x) (0x80 & (int)SCM_CAR(x))
+#define SCM_SETGCMARK(x) (SCM_CDR(x) |= 1)
+#define SCM_CLRGCMARK(x) (SCM_CDR(x) &= ~1L)
+#define SCM_SETGC8MARK(x) (SCM_CAR(x) |= 0x80)
+#define SCM_CLRGC8MARK(x) (SCM_CAR(x) &= ~0x80L)
+
+
+/* Extracting Tag Bits, With or Without GC Safety and Optional Bits
+ */
+#define SCM_TYP3(x) (7 & (int)SCM_CAR(x))
+#define SCM_TYP7(x) (0x7f & (int)SCM_CAR(x))
+#define SCM_TYP7S(x) (0x7d & (int)SCM_CAR(x))
+#define SCM_TYP16(x) (0xffff & (int)SCM_CAR(x))
+#define SCM_TYP16S(x) (0xfeff & (int)SCM_CAR(x))
+#define SCM_GCTYP16(x) (0xff7f & (int)SCM_CAR(x))
+
+
+/* Two slightly extensible types: smobs and ptobs.
+ *
+ */
+#define SCM_SMOBNUM(x) (0x0ff & (CAR(x)>>8));
+#define SCM_PTOBNUM(x) (0x0ff & (CAR(x)>>8));
+
+
+
+
+#define SCM_DIRP(x) (SCM_NIMP(x) && (TYP16(x)==(scm_tc16_dir)))
+#define SCM_OPDIRP(x) (SCM_NIMP(x) && (CAR(x)==(scm_tc16_dir | OPN)))
+
+
+
+/* Lvectors
+ */
+#define SCM_LVECTORP(x) (TYP7(x)==tc7_lvector)
+
+
+#if 0
+
+/* Sockets
+ */
+#define tc_socket (tc7_port | OPN)
+#define SCM_SOCKP(x) (((0x7f | OPN | RDNG | WRTNG) & CAR(x))==(tc_socket))
+#define SCM_SOCKTYP(x) (CAR(x)>>24)
+
+
+
+extern int scm_tc16_key_vector;
+#define SCM_KEYVECP(X) (scm_tc16_key_vector == TYP16 (X))
+#define SCM_KEYVECLEN(OBJ) (((unsigned long)CAR (obj)) >> 16)
+
+
+#define SCM_MALLOCDATA(obj) ((char *)CDR(obj))
+#define SCM_MALLOCLEN(obj) (((unsigned long)CAR (obj)) >> 16)
+#define SCM_WORDDATA(obj) (CDR (obj))
+
+
+#define SCM_BYTECODEP(X) ((TYP7 (X) == tc7_cclo) && (CCLO_SUBR (X) == rb_proc))
+#define SCM_BYTECODE_CONSTANTS(X) (VELTS(X)[1])
+#define SCM_BYTECODE_CODE(X) (VELTS(X)[2])
+#define SCM_BYTECODE_NAME(X) (VELTS(X)[3])
+#define SCM_BYTECODE_BCODE(X) (VELTS(X)[4])
+#define SCM_BYTECODE_ELTS 5
+
+
+#define SCM_FREEP(x) (CAR(x)==tc_free_cell)
+#define SCM_NFREEP(x) (!FREEP(x))
+
+#endif /* 0*/
+
+#ifdef __STDC__
+
+#else /* STDC */
+
+#endif /* STDC */
+
+
+#endif /* TAGSH */
diff --git a/gdb/scm-valprint.c b/gdb/scm-valprint.c
new file mode 100644
index 00000000000..71acc69d351
--- /dev/null
+++ b/gdb/scm-valprint.c
@@ -0,0 +1,422 @@
+/* Scheme/Guile language support routines for GDB, the GNU debugger.
+ Copyright 1995 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "symtab.h"
+#include "gdbtypes.h"
+#include "expression.h"
+#include "parser-defs.h"
+#include "language.h"
+#include "value.h"
+#include "scm-lang.h"
+#include "valprint.h"
+#include "gdbcore.h"
+
+/* FIXME: Should be in a header file that we import. */
+extern int
+c_val_print PARAMS ((struct type *, char *, int, CORE_ADDR, GDB_FILE *, int, int,
+ int, enum val_prettyprint));
+
+static void scm_ipruk PARAMS ((char *, LONGEST, GDB_FILE *));
+static void scm_scmlist_print PARAMS ((LONGEST, GDB_FILE *, int, int,
+ int, enum val_prettyprint));
+static int scm_inferior_print PARAMS ((LONGEST, GDB_FILE *, int, int,
+ int, enum val_prettyprint));
+
+/* Prints the SCM value VALUE by invoking the inferior, if appropraite.
+ Returns >= 0 on succes; retunr -1 if the inferior cannot/should not
+ print VALUE. */
+
+static int
+scm_inferior_print (value, stream, format, deref_ref, recurse, pretty)
+ LONGEST value;
+ GDB_FILE *stream;
+ int format;
+ int deref_ref;
+ int recurse;
+ enum val_prettyprint pretty;
+{
+ return -1;
+}
+
+/* {Names of immediate symbols}
+ * This table must agree with the declarations in scm.h: {Immediate Symbols}.*/
+
+static char *scm_isymnames[] =
+{
+ /* This table must agree with the declarations */
+ "and",
+ "begin",
+ "case",
+ "cond",
+ "do",
+ "if",
+ "lambda",
+ "let",
+ "let*",
+ "letrec",
+ "or",
+ "quote",
+ "set!",
+ "define",
+#if 0
+ "literal-variable-ref",
+ "literal-variable-set!",
+#endif
+ "apply",
+ "call-with-current-continuation",
+
+ /* user visible ISYMS */
+ /* other keywords */
+ /* Flags */
+
+ "#f",
+ "#t",
+ "#<undefined>",
+ "#<eof>",
+ "()",
+ "#<unspecified>"
+};
+
+static void
+scm_scmlist_print (svalue, stream, format, deref_ref, recurse, pretty)
+ LONGEST svalue;
+ GDB_FILE *stream;
+ int format;
+ int deref_ref;
+ int recurse;
+ enum val_prettyprint pretty;
+{
+ unsigned int more = print_max;
+ if (recurse > 6)
+ {
+ fputs_filtered ("...", stream);
+ return;
+ }
+ scm_scmval_print (SCM_CAR (svalue), stream, format,
+ deref_ref, recurse + 1, pretty);
+ svalue = SCM_CDR (svalue);
+ for (; SCM_NIMP (svalue); svalue = SCM_CDR (svalue))
+ {
+ if (SCM_NECONSP (svalue))
+ break;
+ fputs_filtered (" ", stream);
+ if (--more == 0)
+ {
+ fputs_filtered ("...", stream);
+ return;
+ }
+ scm_scmval_print (SCM_CAR (svalue), stream, format,
+ deref_ref, recurse + 1, pretty);
+ }
+ if (SCM_NNULLP (svalue))
+ {
+ fputs_filtered (" . ", stream);
+ scm_scmval_print (svalue, stream, format,
+ deref_ref, recurse + 1, pretty);
+ }
+}
+
+static void
+scm_ipruk (hdr, ptr, stream)
+ char *hdr;
+ LONGEST ptr;
+ GDB_FILE *stream;
+{
+ fprintf_filtered (stream, "#<unknown-%s", hdr);
+#define SCM_SIZE TYPE_LENGTH (builtin_type_scm)
+ if (SCM_CELLP (ptr))
+ fprintf_filtered (stream, " (0x%lx . 0x%lx) @",
+ (long) SCM_CAR (ptr), (long) SCM_CDR (ptr));
+ fprintf_filtered (stream, " 0x%x>", ptr);
+}
+
+void
+scm_scmval_print (svalue, stream, format, deref_ref, recurse, pretty)
+ LONGEST svalue;
+ GDB_FILE *stream;
+ int format;
+ int deref_ref;
+ int recurse;
+ enum val_prettyprint pretty;
+{
+ taloop:
+ switch (7 & (int) svalue)
+ {
+ case 2:
+ case 6:
+ print_longest (stream, format ? format : 'd', 1, svalue >> 2);
+ break;
+ case 4:
+ if (SCM_ICHRP (svalue))
+ {
+ svalue = SCM_ICHR (svalue);
+ scm_printchar (svalue, stream);
+ break;
+ }
+ else if (SCM_IFLAGP (svalue)
+ && (SCM_ISYMNUM (svalue)
+ < (sizeof scm_isymnames / sizeof (char *))))
+ {
+ fputs_filtered (SCM_ISYMCHARS (svalue), stream);
+ break;
+ }
+ else if (SCM_ILOCP (svalue))
+ {
+ fprintf_filtered (stream, "#@%ld%c%ld",
+ (long) SCM_IFRAME (svalue),
+ SCM_ICDRP (svalue) ? '-' : '+',
+ (long) SCM_IDIST (svalue));
+ break;
+ }
+ else
+ goto idef;
+ break;
+ case 1:
+ /* gloc */
+ svalue = SCM_CAR (svalue - 1);
+ goto taloop;
+ default:
+ idef:
+ scm_ipruk ("immediate", svalue, stream);
+ break;
+ case 0:
+
+ switch (SCM_TYP7 (svalue))
+ {
+ case scm_tcs_cons_gloc:
+ if (SCM_CDR (SCM_CAR (svalue) - 1L) == 0)
+ {
+#if 0
+ SCM name;
+#endif
+ fputs_filtered ("#<latte ", stream);
+#if 1
+ fputs_filtered ("???", stream);
+#else
+ name = ((SCM n*)(STRUCT_TYPE( exp)))[struct_i_name];
+ scm_lfwrite (CHARS (name),
+ (sizet) sizeof (char),
+ (sizet) LENGTH (name),
+ port);
+#endif
+ fprintf_filtered (stream, " #X%lX>", svalue);
+ break;
+ }
+ case scm_tcs_cons_imcar:
+ case scm_tcs_cons_nimcar:
+ fputs_filtered ("(", stream);
+ scm_scmlist_print (svalue, stream, format,
+ deref_ref, recurse + 1, pretty);
+ fputs_filtered (")", stream);
+ break;
+ case scm_tcs_closures:
+ fputs_filtered ("#<CLOSURE ", stream);
+ scm_scmlist_print (SCM_CODE (svalue), stream, format,
+ deref_ref, recurse + 1, pretty);
+ fputs_filtered (">", stream);
+ break;
+ case scm_tc7_string:
+ {
+ int len = SCM_LENGTH (svalue);
+ CORE_ADDR addr = (CORE_ADDR) SCM_CDR (svalue);
+ int i;
+ int done = 0;
+ int buf_size;
+ char buffer[64];
+ int truncate = print_max && len > (int) print_max;
+ if (truncate)
+ len = print_max;
+ fputs_filtered ("\"", stream);
+ for (; done < len; done += buf_size)
+ {
+ buf_size = min (len - done, 64);
+ read_memory (addr + done, buffer, buf_size);
+
+ for (i = 0; i < buf_size; ++i)
+ switch (buffer[i])
+ {
+ case '\"':
+ case '\\':
+ fputs_filtered ("\\", stream);
+ default:
+ fprintf_filtered (stream, "%c", buffer[i]);
+ }
+ }
+ fputs_filtered (truncate ? "...\"" : "\"", stream);
+ break;
+ }
+ break;
+ case scm_tcs_symbols:
+ {
+ int len = SCM_LENGTH (svalue);
+
+ char * str = (char*) alloca (len);
+ read_memory (SCM_CDR (svalue), str, len + 1);
+ /* Should handle weird characters FIXME */
+ str[len] = '\0';
+ fputs_filtered (str, stream);
+ break;
+ }
+ case scm_tc7_vector:
+ {
+ int len = SCM_LENGTH (svalue);
+ int i;
+ LONGEST elements = SCM_CDR(svalue);
+ fputs_filtered ("#(", stream);
+ for (i = 0; i < len; ++i)
+ {
+ if (i > 0)
+ fputs_filtered (" ", stream);
+ scm_scmval_print (scm_get_field (elements, i), stream, format,
+ deref_ref, recurse + 1, pretty);
+ }
+ fputs_filtered (")", stream);
+ }
+ break;
+#if 0
+ case tc7_lvector:
+ {
+ SCM result;
+ SCM hook;
+ hook = scm_get_lvector_hook (exp, LV_PRINT_FN);
+ if (hook == BOOL_F)
+ {
+ scm_puts ("#<locked-vector ", port);
+ scm_intprint(CDR(exp), 16, port);
+ scm_puts (">", port);
+ }
+ else
+ {
+ result
+ = scm_apply (hook,
+ scm_listify (exp, port, (writing ? BOOL_T : BOOL_F),
+ SCM_UNDEFINED),
+ EOL);
+ if (result == BOOL_F)
+ goto punk;
+ }
+ break;
+ }
+ break;
+ case tc7_bvect:
+ case tc7_ivect:
+ case tc7_uvect:
+ case tc7_fvect:
+ case tc7_dvect:
+ case tc7_cvect:
+ scm_raprin1 (exp, port, writing);
+ break;
+#endif
+ case scm_tcs_subrs:
+ {
+ int index = SCM_CAR (svalue) >> 8;
+#if 1
+ char str[20];
+ sprintf (str, "#%d", index);
+#else
+ char *str = index ? SCM_CHARS (scm_heap_org+index) : "";
+#define SCM_CHARS(x) ((char *)(SCM_CDR(x)))
+ char *str = CHARS (SNAME (exp));
+#endif
+ fprintf_filtered (stream, "#<primitive-procedure %s>",
+ str);
+ }
+ break;
+#if 0
+#ifdef CCLO
+ case tc7_cclo:
+ scm_puts ("#<compiled-closure ", port);
+ scm_iprin1 (CCLO_SUBR (exp), port, writing);
+ scm_putc ('>', port);
+ break;
+#endif
+ case tc7_contin:
+ fprintf_filtered (stream, "#<continuation %d @ #X%lx >",
+ LENGTH (svalue),
+ (long) CHARS (svalue));
+ break;
+ case tc7_port:
+ i = PTOBNUM (exp);
+ if (i < scm_numptob && scm_ptobs[i].print && (scm_ptobs[i].print) (exp, port, writing))
+ break;
+ goto punk;
+ case tc7_smob:
+ i = SMOBNUM (exp);
+ if (i < scm_numsmob && scm_smobs[i].print
+ && (scm_smobs[i].print) (exp, port, writing))
+ break;
+ goto punk;
+#endif
+ default:
+#if 0
+ punk:
+#endif
+ scm_ipruk ("type", svalue, stream);
+ }
+ break;
+ }
+}
+
+int
+scm_val_print (type, valaddr, embedded_offset, address,
+ stream, format, deref_ref, recurse, pretty)
+ struct type *type;
+ char *valaddr;
+ int embedded_offset;
+ CORE_ADDR address;
+ GDB_FILE *stream;
+ int format;
+ int deref_ref;
+ int recurse;
+ enum val_prettyprint pretty;
+{
+ if (is_scmvalue_type (type))
+ {
+ LONGEST svalue = extract_signed_integer (valaddr, TYPE_LENGTH (type));
+ if (scm_inferior_print (svalue, stream, format,
+ deref_ref, recurse, pretty) >= 0)
+ {
+ }
+ else
+ {
+ scm_scmval_print (svalue, stream, format,
+ deref_ref, recurse, pretty);
+ }
+
+ gdb_flush (stream);
+ return (0);
+ }
+ else
+ {
+ return c_val_print (type, valaddr, 0, address, stream, format,
+ deref_ref, recurse, pretty);
+ }
+}
+
+int
+scm_value_print (val, stream, format, pretty)
+ value_ptr val;
+ GDB_FILE *stream;
+ int format;
+ enum val_prettyprint pretty;
+{
+ return (val_print (VALUE_TYPE (val), VALUE_CONTENTS (val), 0,
+ VALUE_ADDRESS (val), stream, format, 1, 0, pretty));
+}
diff --git a/gdb/ser-e7kpc.c b/gdb/ser-e7kpc.c
new file mode 100644
index 00000000000..8be5db9b691
--- /dev/null
+++ b/gdb/ser-e7kpc.c
@@ -0,0 +1,470 @@
+/* Remote serial interface using Hitachi E7000 PC ISA card in a PC
+ Copyright 1994, 1999 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#if defined __GO32__ || defined _WIN32
+#include "defs.h"
+#include "serial.h"
+#include "gdb_string.h"
+
+/* MSVC uses strnicmp instead of strncasecmp */
+#ifdef _MSC_VER
+#define strncasecmp strnicmp
+#define WIN32_LEAN_AND_MEAN
+#endif
+
+#ifdef _WIN32
+#include <windows.h>
+#endif
+
+#ifdef __GO32__
+#include <sys/dos.h>
+#endif
+
+static int e7000pc_open PARAMS ((serial_t scb, const char *name));
+static void e7000pc_raw PARAMS ((serial_t scb));
+static int e7000pc_readchar PARAMS ((serial_t scb, int timeout));
+static int e7000pc_setbaudrate PARAMS ((serial_t scb, int rate));
+static int e7000pc_write PARAMS ((serial_t scb, const char *str, int len));
+static void e7000pc_close PARAMS ((serial_t scb));
+static serial_ttystate e7000pc_get_tty_state PARAMS ((serial_t scb));
+static int e7000pc_set_tty_state PARAMS ((serial_t scb, serial_ttystate state));
+
+#define OFF_DPD 0x0000
+#define OFF_DDP 0x1000
+#define OFF_CPD 0x2000
+#define OFF_CDP 0x2400
+#define OFF_FA 0x3000
+#define OFF_FB 0x3002
+#define OFF_FC 0x3004
+#define OFF_IRQTOD 0x3008
+#define OFF_IRQTOP 0x300a
+#define OFF_READY 0x300c
+#define OFF_PON 0x300e
+
+#define IDLE 0x0000
+#define CMD_CI 0x4349
+#define CMD_CO 0x434f
+#define CMD_LO 0x4c4f
+#define CMD_LS 0x4c53
+#define CMD_SV 0x5356
+#define CMD_SS 0x5353
+#define CMD_OK 0x4f4b
+#define CMD_ER 0x4552
+#define CMD_NF 0x4e46
+#define CMD_AB 0x4142
+#define CMD_ED 0x4544
+#define CMD_CE 0x4345
+
+static unsigned long fa;
+static unsigned long irqtod;
+static unsigned long ready;
+static unsigned long fb;
+static unsigned long cpd ;
+static unsigned long cdp ;
+static unsigned long ready;
+static unsigned long pon;
+static unsigned long irqtop;
+static unsigned long board_at;
+
+#ifdef __GO32__
+
+#define SET_BYTE(x,y) { char _buf = y;dosmemput(&_buf,1, x);}
+#define SET_WORD(x,y) { short _buf = y;dosmemput(&_buf,2, x);}
+#define GET_BYTE(x) ( dosmemget(x,1,&bb), bb)
+#define GET_WORD(x) ( dosmemget(x,2,&sb), sb)
+static unsigned char bb;
+static unsigned short sb;
+
+#else /* win32 */
+
+#define SET_BYTE(x,y) *(volatile unsigned char *)(x) = (y)
+#define SET_WORD(x,y) *(volatile unsigned short *)(x) = (y)
+#define GET_BYTE(x) (*(volatile unsigned char *)(x))
+#define GET_WORD(x) (*(volatile unsigned short *)(x))
+#define dosmemget(FROM, LEN, TO) memcpy ((void *)(TO), (void *)(FROM), (LEN))
+#define dosmemput(FROM, LEN, TO) memcpy ((void *)(TO), (void *)(FROM), (LEN))
+#endif
+
+static struct sw
+{
+ int sw;
+ int addr;
+} sigs[] = {
+ {0x14, 0xd0000},
+ {0x15, 0xd4000},
+ {0x16, 0xd8000},
+ {0x17, 0xdc000},
+ 0};
+
+#ifdef _MSC_VER
+/* Get the base of the data segment. This is needed to calculate the offset
+ between data segment addresses and the base of linear memory, which is where
+ device registers reside. Note that this is really only necessary for
+ Win32s, since Win95 and NT keep the data segment at linear 0. */
+
+static unsigned long
+get_ds_base (void)
+{
+ unsigned short dsval;
+ LDT_ENTRY ldt;
+ unsigned long dsbase;
+
+ __asm
+ {
+ mov dsval,ds
+ }
+
+ dsbase = 0;
+
+ GetThreadSelectorEntry (GetCurrentThread(), dsval, &ldt);
+
+ dsbase = ldt.HighWord.Bits.BaseHi << 24 | ldt.HighWord.Bits.BaseMid << 16
+ | ldt.BaseLow;
+
+ return dsbase;
+}
+#else /* !_MSC_VER */
+#define get_ds_base() 0
+#endif /* _MSC_VER */
+
+static int
+e7000pc_init ()
+{
+ int try;
+ unsigned long dsbase;
+
+ dsbase = get_ds_base ();
+
+ /* Look around in memory for the board's signature */
+
+ for (try = 0; sigs[try].sw; try++)
+ {
+ int val;
+ board_at = sigs[try].addr - dsbase;
+ fa = board_at + OFF_FA;
+ fb = board_at + OFF_FB;
+ cpd = board_at + OFF_CPD;
+ cdp = board_at + OFF_CDP;
+ ready =board_at + OFF_READY;
+ pon = board_at + OFF_PON;
+ irqtop = board_at + OFF_IRQTOP;
+ irqtod = board_at + OFF_IRQTOD;
+
+ val = GET_WORD (ready);
+
+ if (val == (0xaaa0 | sigs[try].sw))
+ {
+ if (GET_WORD (pon) & 0xf)
+ {
+ SET_WORD (fa, 0);
+ SET_WORD (fb, 0);
+
+ SET_WORD (irqtop, 1); /* Disable interrupts from e7000 */
+ SET_WORD (ready, 1);
+ printf_filtered ("\nConnected to the E7000PC at address 0x%x\n",
+ sigs[try].addr);
+ return 1;
+ }
+ error ("The E7000 PC board is working, but the E7000 is turned off.\n");
+ return 0;
+ }
+ }
+
+ error ("GDB cannot connect to the E7000 PC board, check that it is installed\n\
+and that the switch settings are correct. Some other DOS programs can \n\
+stop the board from working. Try starting from a very minimal boot, \n\
+perhaps you need to disable EMM386 over the region where the board has\n\
+its I/O space, remove other unneeded cards, etc etc\n");
+ return 0;
+
+}
+
+static int pbuf_size;
+static int pbuf_index;
+
+/* Return next byte from cdp. If no more, then return -1. */
+
+static int
+e7000_get (void)
+{
+ static char pbuf[1000];
+ char tmp[1000];
+ int x;
+
+ if (pbuf_index < pbuf_size)
+ {
+ x = pbuf[pbuf_index++];
+ }
+ else if ((GET_WORD (fb) & 1))
+ {
+ int i;
+ pbuf_size = GET_WORD (cdp + 2);
+
+ dosmemget (cdp + 8, pbuf_size + 1, tmp);
+
+ /* Tell the E7000 we've eaten */
+ SET_WORD (fb, 0);
+ /* Swap it around */
+ for (i = 0; i < pbuf_size; i++)
+ {
+ pbuf[i] = tmp[i^1];
+ }
+ pbuf_index = 0;
+ x = pbuf[pbuf_index++];
+ }
+ else
+ {
+ x = -1;
+ }
+ return x;
+}
+
+/* Works just like read(), except that it takes a TIMEOUT in seconds. Note
+ that TIMEOUT == 0 is a poll, and TIMEOUT == -1 means wait forever. */
+
+static int
+dosasync_read (fd, buf, len, timeout)
+ int fd;
+ char *buf;
+ int len;
+ int timeout;
+
+{
+ long now;
+ long then;
+ int i = 0;
+
+ /* Then look for some more if we're still hungry */
+ time (&now);
+ then = now + timeout;
+ while (i < len)
+ {
+ int ch = e7000_get();
+
+ /* While there's room in the buffer, and we've already
+ read the stuff in, suck it over */
+ if (ch != -1)
+ {
+ buf[i++] = ch;
+ while (i < len && pbuf_index < pbuf_size )
+ {
+ ch = e7000_get();
+ if (ch == -1)
+ break;
+ buf[i++] = ch;
+ }
+ }
+
+ time (&now);
+
+ if (timeout == 0)
+ return i;
+ if (now >= then && timeout > 0)
+ {
+ return i;
+ }
+ }
+ return len;
+}
+
+
+static int
+dosasync_write (fd, buf, len)
+ int fd;
+ const char *buf;
+ int len;
+{
+ int i;
+ char dummy[1000];
+
+ /* Construct copy locally */
+ ((short *)dummy)[0] = CMD_CI;
+ ((short *)dummy)[1] = len;
+ ((short *)dummy)[2] = 0;
+ ((short *)dummy)[3] = 0;
+ for (i = 0; i < len ; i++)
+ {
+ dummy[8 + i ^ 1] = buf[i];
+ }
+
+ /* Wait for the card to get ready */
+ while (GET_WORD (fa) & 1) ;
+
+ /* Blast onto the ISA card */
+ dosmemput (dummy, 8 + len + 1, cpd);
+
+ SET_WORD (fa, 1);
+ SET_WORD (irqtod, 1); /* Interrupt the E7000 */
+
+ return len;
+}
+
+static int
+e7000pc_open (scb, name)
+ serial_t scb;
+ const char *name;
+{
+ if (strncasecmp (name, "pc", 2) != 0)
+ {
+ errno = ENOENT;
+ return -1;
+ }
+
+ scb->fd = e7000pc_init ();
+
+ if (!scb->fd)
+ return -1;
+
+ return 0;
+}
+
+static int
+e7000pc_noop (scb)
+ serial_t scb;
+{
+ return 0;
+}
+
+static void
+e7000pc_raw (scb)
+ serial_t scb;
+{
+ /* Always in raw mode */
+}
+
+static int
+e7000pc_readchar (scb, timeout)
+ serial_t scb;
+ int timeout;
+{
+ char buf;
+
+ top:
+
+ if (dosasync_read (scb->fd, &buf, 1, timeout))
+ {
+ if (buf == 0) goto top;
+ return buf;
+ }
+ else
+ return SERIAL_TIMEOUT;
+}
+
+struct e7000pc_ttystate {
+ int dummy;
+};
+
+/* e7000pc_{get set}_tty_state() are both dummys to fill out the function
+ vector. Someday, they may do something real... */
+
+static serial_ttystate
+e7000pc_get_tty_state (scb)
+ serial_t scb;
+{
+ struct e7000pc_ttystate *state;
+
+ state = (struct e7000pc_ttystate *) xmalloc (sizeof *state);
+
+ return (serial_ttystate) state;
+}
+
+static int
+e7000pc_set_tty_state (scb, ttystate)
+ serial_t scb;
+ serial_ttystate ttystate;
+{
+ return 0;
+}
+
+static int
+e7000pc_noflush_set_tty_state (scb, new_ttystate, old_ttystate)
+ serial_t scb;
+ serial_ttystate new_ttystate;
+ serial_ttystate old_ttystate;
+{
+ return 0;
+}
+
+static void
+e7000pc_print_tty_state (scb, ttystate)
+ serial_t scb;
+ serial_ttystate ttystate;
+{
+ /* Nothing to print. */
+ return;
+}
+
+static int
+e7000pc_setbaudrate (scb, rate)
+ serial_t scb;
+ int rate;
+{
+ return 0;
+}
+
+static int
+e7000pc_write (scb, str, len)
+ serial_t scb;
+ const char *str;
+ int len;
+{
+ dosasync_write (scb->fd, str, len);
+
+ return 0;
+}
+
+static void
+e7000pc_close (scb)
+ serial_t scb;
+{
+}
+
+static struct serial_ops e7000pc_ops =
+{
+ "pc",
+ 0,
+ e7000pc_open,
+ e7000pc_close,
+ e7000pc_readchar,
+ e7000pc_write,
+ e7000pc_noop, /* flush output */
+ e7000pc_noop, /* flush input */
+ e7000pc_noop, /* send break -- currently used only for nindy */
+ e7000pc_raw,
+ e7000pc_get_tty_state,
+ e7000pc_set_tty_state,
+ e7000pc_print_tty_state,
+ e7000pc_noflush_set_tty_state,
+ e7000pc_setbaudrate,
+ e7000pc_noop, /* wait for output to drain */
+};
+
+void
+_initialize_ser_e7000pc ()
+{
+ serial_add_interface (&e7000pc_ops);
+}
+#else
+
+void
+_initialize_ser_e7000pc ()
+{
+
+}
+#endif
diff --git a/gdb/ser-go32.c b/gdb/ser-go32.c
new file mode 100644
index 00000000000..f776161964a
--- /dev/null
+++ b/gdb/ser-go32.c
@@ -0,0 +1,958 @@
+/* Remote serial interface for local (hardwired) serial ports for
+ GO32. Copyright 1992, 1993 Free Software Foundation, Inc.
+
+ Contributed by Nigel Stephens, Algorithmics Ltd. (nigel@algor.co.uk).
+
+ This version uses DPMI interrupts to handle buffered i/o
+ without the separate "asynctsr" program.
+
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "gdbcmd.h"
+#include "serial.h"
+
+
+/*
+ * NS16550 UART registers
+ */
+
+#define COM1ADDR 0x3f8
+#define COM2ADDR 0x2f8
+#define COM3ADDR 0x3e8
+#define COM4ADDR 0x3e0
+
+#define com_data 0 /* data register (R/W) */
+#define com_dlbl 0 /* divisor latch low (W) */
+#define com_ier 1 /* interrupt enable (W) */
+#define com_dlbh 1 /* divisor latch high (W) */
+#define com_iir 2 /* interrupt identification (R) */
+#define com_fifo 2 /* FIFO control (W) */
+#define com_lctl 3 /* line control register (R/W) */
+#define com_cfcr 3 /* line control register (R/W) */
+#define com_mcr 4 /* modem control register (R/W) */
+#define com_lsr 5 /* line status register (R/W) */
+#define com_msr 6 /* modem status register (R/W) */
+
+/*
+ * Constants for computing 16 bit baud rate divisor (lower byte
+ * in com_dlbl, upper in com_dlbh) from 1.8432MHz crystal. Divisor is
+ * 1.8432 MHz / (16 * X) for X bps. If the baud rate can't be set
+ * to within +- (desired_rate*SPEED_TOLERANCE/1000) bps, we fail.
+ */
+#define COMTICK (1843200/16)
+#define SPEED_TOLERANCE 30 /* thousandths; real == desired +- 3.0% */
+
+/* interrupt enable register */
+#define IER_ERXRDY 0x1 /* int on rx ready */
+#define IER_ETXRDY 0x2 /* int on tx ready */
+#define IER_ERLS 0x4 /* int on line status change */
+#define IER_EMSC 0x8 /* int on modem status change */
+
+/* interrupt identification register */
+#define IIR_FIFO_MASK 0xc0 /* set if FIFOs are enabled */
+#define IIR_IMASK 0xf /* interrupt cause mask */
+#define IIR_NOPEND 0x1 /* nothing pending */
+#define IIR_RLS 0x6 /* receive line status */
+#define IIR_RXRDY 0x4 /* receive ready */
+#define IIR_RXTOUT 0xc /* receive timeout */
+#define IIR_TXRDY 0x2 /* transmit ready */
+#define IIR_MLSC 0x0 /* modem status */
+
+
+/* fifo control register */
+#define FIFO_ENABLE 0x01 /* enable fifo */
+#define FIFO_RCV_RST 0x02 /* reset receive fifo */
+#define FIFO_XMT_RST 0x04 /* reset transmit fifo */
+#define FIFO_DMA_MODE 0x08 /* enable dma mode */
+#define FIFO_TRIGGER_1 0x00 /* trigger at 1 char */
+#define FIFO_TRIGGER_4 0x40 /* trigger at 4 chars */
+#define FIFO_TRIGGER_8 0x80 /* trigger at 8 chars */
+#define FIFO_TRIGGER_14 0xc0 /* trigger at 14 chars */
+
+/* character format control register */
+#define CFCR_DLAB 0x80 /* divisor latch */
+#define CFCR_SBREAK 0x40 /* send break */
+#define CFCR_PZERO 0x30 /* zero parity */
+#define CFCR_PONE 0x20 /* one parity */
+#define CFCR_PEVEN 0x10 /* even parity */
+#define CFCR_PODD 0x00 /* odd parity */
+#define CFCR_PENAB 0x08 /* parity enable */
+#define CFCR_STOPB 0x04 /* 2 stop bits */
+#define CFCR_8BITS 0x03 /* 8 data bits */
+#define CFCR_7BITS 0x02 /* 7 data bits */
+#define CFCR_6BITS 0x01 /* 6 data bits */
+#define CFCR_5BITS 0x00 /* 5 data bits */
+
+/* modem control register */
+#define MCR_LOOPBACK 0x10 /* loopback */
+#define MCR_IENABLE 0x08 /* output 2 = int enable */
+#define MCR_DRS 0x04 /* output 1 = xxx */
+#define MCR_RTS 0x02 /* enable RTS */
+#define MCR_DTR 0x01 /* enable DTR */
+
+/* line status register */
+#define LSR_RCV_FIFO 0x80 /* error in receive fifo */
+#define LSR_TSRE 0x40 /* transmitter empty */
+#define LSR_TXRDY 0x20 /* transmitter ready */
+#define LSR_BI 0x10 /* break detected */
+#define LSR_FE 0x08 /* framing error */
+#define LSR_PE 0x04 /* parity error */
+#define LSR_OE 0x02 /* overrun error */
+#define LSR_RXRDY 0x01 /* receiver ready */
+#define LSR_RCV_MASK 0x1f
+
+/* modem status register */
+#define MSR_DCD 0x80
+#define MSR_RI 0x40
+#define MSR_DSR 0x20
+#define MSR_CTS 0x10
+#define MSR_DDCD 0x08
+#define MSR_TERI 0x04
+#define MSR_DDSR 0x02
+#define MSR_DCTS 0x01
+
+#include <sys/dos.h>
+#include <sys/go32.h>
+#include <sys/dpmi.h>
+
+/* DPMI Communication */
+static union REGS dpmi_regs;
+static struct SREGS dpmi_sregs;
+
+/* 16550 rx fifo trigger point */
+#define FIFO_TRIGGER FIFO_TRIGGER_4
+
+/* input buffer size */
+#define CBSIZE 4096
+
+/* return raw 18Hz clock count */
+extern long rawclock (void);
+
+#define RAWHZ 18
+
+#ifdef DOS_STATS
+#define CNT_RX 16
+#define CNT_TX 17
+#define CNT_STRAY 18
+#define CNT_ORUN 19
+#define NCNT 20
+
+static int intrcnt;
+static int cnts[NCNT];
+static char *cntnames[NCNT] = {
+ /* h/w interrupt counts. */
+ "mlsc", "nopend", "txrdy", "?3",
+ "rxrdy", "?5", "rls", "?7",
+ "?8", "?9", "?a", "?b",
+ "rxtout", "?d", "?e", "?f",
+ /* s/w counts. */
+ "rxcnt", "txcnt", "stray", "swoflo"
+};
+
+#define COUNT(x) cnts[x]++
+#else
+#define COUNT(x)
+#endif
+
+/* Main interrupt controller port addresses. */
+#define ICU_BASE 0x20
+#define ICU_OCW2 (ICU_BASE + 0)
+#define ICU_MASK (ICU_BASE + 1)
+
+/* Original interrupt controller mask register. */
+unsigned char icu_oldmask;
+
+/* Maximum of 8 interrupts (we don't handle the slave icu yet). */
+#define NINTR 8
+
+static struct intrupt
+{
+ char inuse;
+ struct dos_ttystate *port;
+ _go32_dpmi_seginfo old_rmhandler;
+ _go32_dpmi_seginfo old_pmhandler;
+ _go32_dpmi_seginfo new_rmhandler;
+ _go32_dpmi_seginfo new_pmhandler;
+ _go32_dpmi_registers regs;
+} intrupts[NINTR];
+
+
+static struct dos_ttystate
+{
+ int base;
+ int irq;
+ int refcnt;
+ struct intrupt *intrupt;
+ int fifo;
+ int baudrate;
+ unsigned char cbuf[CBSIZE];
+ unsigned int first;
+ unsigned int count;
+ int txbusy;
+ unsigned char old_mcr;
+ int ferr;
+ int perr;
+ int oflo;
+ int msr;
+} ports[4] = {
+ {COM1ADDR, 4},
+ {COM2ADDR, 3},
+ {COM3ADDR, 4},
+ {COM4ADDR, 3}
+};
+
+static int dos_open PARAMS ((serial_t scb, const char *name));
+static void dos_raw PARAMS ((serial_t scb));
+static int dos_readchar PARAMS ((serial_t scb, int timeout));
+static int dos_setbaudrate PARAMS ((serial_t scb, int rate));
+static int dos_write PARAMS ((serial_t scb, const char *str, int len));
+static void dos_close PARAMS ((serial_t scb));
+static serial_ttystate dos_get_tty_state PARAMS ((serial_t scb));
+static int dos_set_tty_state PARAMS ((serial_t scb, serial_ttystate state));
+static int dos_baudconv PARAMS ((int rate));
+
+#define inb(p,a) inportb((p)->base + (a))
+#define outb(p,a,v) outportb((p)->base + (a), (v))
+#define disable() asm volatile ("cli");
+#define enable() asm volatile ("sti");
+
+
+static int
+dos_getc (port)
+ volatile struct dos_ttystate *port;
+{
+ int c;
+
+ if (port->count == 0)
+ return -1;
+
+ c = port->cbuf[port->first];
+ disable ();
+ port->first = (port->first + 1) & (CBSIZE - 1);
+ port->count--;
+ enable ();
+ return c;
+}
+
+
+static int
+dos_putc (c, port)
+ int c;
+ struct dos_ttystate *port;
+{
+ if (port->count >= CBSIZE - 1)
+ return -1;
+ port->cbuf[(port->first + port->count) & (CBSIZE - 1)] = c;
+ port->count++;
+ return 0;
+}
+
+
+
+static void
+dos_comisr (irq)
+ int irq;
+{
+ struct dos_ttystate *port;
+ unsigned char iir, lsr, c;
+
+ disable (); /* Paranoia */
+ outportb (ICU_OCW2, 0x20); /* End-Of-Interrupt */
+#ifdef DOS_STATS
+ ++intrcnt;
+#endif
+
+ port = intrupts[irq].port;
+ if (!port)
+ {
+ COUNT (CNT_STRAY);
+ return; /* not open */
+ }
+
+ while (1)
+ {
+ iir = inb (port, com_iir) & IIR_IMASK;
+ switch (iir)
+ {
+
+ case IIR_RLS:
+ lsr = inb (port, com_lsr);
+ goto rx;
+
+ case IIR_RXTOUT:
+ case IIR_RXRDY:
+ lsr = 0;
+
+ rx:
+ do
+ {
+ c = inb (port, com_data);
+ if (lsr & (LSR_BI | LSR_FE | LSR_PE | LSR_OE))
+ {
+ if (lsr & (LSR_BI | LSR_FE))
+ port->ferr++;
+ else if (lsr & LSR_PE)
+ port->perr++;
+ if (lsr & LSR_OE)
+ port->oflo++;
+ }
+
+ if (dos_putc (c, port) < 0)
+ {
+ COUNT (CNT_ORUN);
+ }
+ else
+ {
+ COUNT (CNT_RX);
+ }
+ }
+ while ((lsr = inb (port, com_lsr)) & LSR_RXRDY);
+ break;
+
+ case IIR_MLSC:
+ /* could be used to flowcontrol Tx */
+ port->msr = inb (port, com_msr);
+ break;
+
+ case IIR_TXRDY:
+ port->txbusy = 0;
+ break;
+
+ case IIR_NOPEND:
+ /* no more pending interrupts, all done */
+ return;
+
+ default:
+ /* unexpected interrupt, ignore */
+ break;
+ }
+ COUNT (iir);
+ }
+}
+
+#ifdef __STDC__
+#define ISRNAME(x) dos_comisr##x
+#else
+#define ISRNAME(x) dos_comisr/**/x
+#endif
+#define ISR(x) static void ISRNAME(x)() {dos_comisr(x);}
+
+ISR(0) ISR(1) ISR(2) ISR(3)
+ISR(4) ISR(5) ISR(6) ISR(7)
+
+typedef void (*isr_t)();
+
+static isr_t isrs[NINTR] = {
+ ISRNAME(0), ISRNAME(1), ISRNAME(2), ISRNAME(3),
+ ISRNAME(4), ISRNAME(5), ISRNAME(6), ISRNAME(7)
+};
+
+
+
+static struct intrupt *
+dos_hookirq (irq)
+ unsigned int irq;
+{
+ struct intrupt *intr;
+ unsigned int vec;
+ isr_t isr;
+
+ if (irq >= NINTR)
+ return 0;
+
+ intr = &intrupts[irq];
+ if (intr->inuse)
+ return 0;
+
+ vec = 0x08 + irq;
+ isr = isrs[irq];
+
+ /* setup real mode handler */
+ _go32_dpmi_get_real_mode_interrupt_vector (vec, &intr->old_rmhandler);
+
+ intr->new_rmhandler.pm_selector = _go32_my_cs();
+ intr->new_rmhandler.pm_offset = (u_long)isr;
+ if (_go32_dpmi_allocate_real_mode_callback_iret (&intr->new_rmhandler,
+ &intr->regs))
+ {
+ return 0;
+ }
+
+ if (_go32_dpmi_set_real_mode_interrupt_vector (vec, &intr->new_rmhandler))
+ {
+ return 0;
+ }
+
+ /* setup protected mode handler */
+ _go32_dpmi_get_protected_mode_interrupt_vector(vec, &intr->old_pmhandler);
+
+ intr->new_pmhandler.pm_selector = _go32_my_cs();
+ intr->new_pmhandler.pm_offset = (u_long)isr;
+ _go32_dpmi_allocate_iret_wrapper (&intr->new_pmhandler);
+
+ if (_go32_dpmi_set_protected_mode_interrupt_vector(vec, &intr->new_pmhandler))
+ {
+ return 0;
+ }
+
+ /* setup interrupt controller mask */
+ disable ();
+ outportb (ICU_MASK, inportb (ICU_MASK) & ~(1 << irq));
+ enable ();
+
+ intr->inuse = 1;
+ return intr;
+}
+
+
+static void
+dos_unhookirq (intr)
+ struct intrupt *intr;
+{
+ unsigned int irq, vec;
+ unsigned char mask;
+
+ irq = intr - intrupts;
+ vec = 0x08 + irq;
+
+ /* restore old interrupt mask bit */
+ mask = 1 << irq;
+ disable ();
+ outportb (ICU_MASK, inportb (ICU_MASK) | (mask & icu_oldmask));
+ enable ();
+
+ /* remove real mode handler */
+ _go32_dpmi_set_real_mode_interrupt_vector (vec, &intr->old_rmhandler);
+ _go32_dpmi_free_real_mode_callback (&intr->new_rmhandler);
+
+ /* remove protected mode handler */
+ _go32_dpmi_set_protected_mode_interrupt_vector (vec, &intr->old_pmhandler);
+ _go32_dpmi_free_iret_wrapper (&intr->new_pmhandler);
+ intr->inuse = 0;
+}
+
+
+
+static int
+dos_open (scb, name)
+ serial_t scb;
+ const char *name;
+{
+ struct dos_ttystate *port;
+ int fd, i;
+
+ if (strncasecmp (name, "/dev/", 5) == 0)
+ name += 5;
+ else if (strncasecmp (name, "\\dev\\", 5) == 0)
+ name += 5;
+
+ if (strlen (name) != 4 || strncasecmp (name, "com", 3) != 0)
+ {
+ errno = ENOENT;
+ return -1;
+ }
+
+ if (name[3] < '1' || name[3] > '4')
+ {
+ errno = ENOENT;
+ return -1;
+ }
+
+ fd = name[3] - '1';
+ port = &ports[fd];
+ if (port->refcnt++ > 0)
+ {
+ /* Device already opened another user. Just point at it. */
+ scb->fd = fd;
+ return 0;
+ }
+
+ /* force access to ID reg */
+ outb(port, com_cfcr, 0);
+ outb(port, com_iir, 0);
+ for (i = 0; i < 17; i++) {
+ if ((inb(port, com_iir) & 0x38) == 0)
+ goto ok;
+ (void) inb(port, com_data); /* clear recv */
+ }
+ errno = ENODEV;
+ return -1;
+
+ok:
+ /* disable all interrupts in chip */
+ outb(port, com_ier, 0);
+
+ /* tentatively enable 16550 fifo, and see if it responds */
+ outb(port, com_fifo, FIFO_ENABLE|FIFO_RCV_RST|FIFO_XMT_RST|FIFO_TRIGGER);
+ sleep(1);
+ port->fifo = ((inb(port, com_iir) & IIR_FIFO_MASK) == IIR_FIFO_MASK);
+
+ /* clear pending status reports. */
+ (void) inb(port, com_lsr);
+ (void) inb(port, com_msr);
+
+ /* enable external interrupt gate (to avoid floating IRQ) */
+ outb(port, com_mcr, MCR_IENABLE);
+
+ /* hook up interrupt handler and initialise icu */
+ port->intrupt = dos_hookirq (port->irq);
+ if (!port->intrupt)
+ {
+ outb(port, com_mcr, 0);
+ outb(port, com_fifo, 0);
+ errno = ENODEV;
+ return -1;
+ }
+
+ disable ();
+
+ /* record port */
+ port->intrupt->port = port;
+ scb->fd = fd;
+
+ /* clear rx buffer, tx busy flag and overflow count */
+ port->first = port->count = 0;
+ port->txbusy = 0;
+ port->oflo = 0;
+
+ /* set default baud rate and mode: 9600,8,n,1 */
+ i = dos_baudconv (port->baudrate = 9600);
+ outb(port, com_cfcr, CFCR_DLAB);
+ outb(port, com_dlbl, i & 0xff);
+ outb(port, com_dlbh, i >> 8);
+ outb(port, com_cfcr, CFCR_8BITS);
+
+ /* enable all interrupts */
+ outb(port, com_ier, IER_ETXRDY | IER_ERXRDY | IER_ERLS | IER_EMSC);
+
+ /* enable DTR & RTS */
+ outb(port, com_mcr, MCR_DTR | MCR_RTS | MCR_IENABLE);
+
+ enable ();
+
+ return 0;
+}
+
+
+static void
+dos_close (scb)
+ serial_t scb;
+{
+ struct dos_ttystate *port;
+ struct intrupt *intrupt;
+
+ if (!scb)
+ return;
+
+ port = &ports[scb->fd];
+
+ if (port->refcnt-- > 1)
+ return;
+
+ if (!(intrupt = port->intrupt))
+ return;
+
+ /* disable interrupts, fifo, flow control */
+ disable ();
+ port->intrupt = 0;
+ intrupt->port = 0;
+ outb(port, com_fifo, 0);
+ outb(port, com_ier, 0);
+ enable ();
+
+ /* unhook handler, and disable interrupt gate */
+ dos_unhookirq (intrupt);
+ outb(port, com_mcr, 0);
+
+ /* Check for overflow errors */
+ if (port->oflo)
+ {
+ fprintf_unfiltered (gdb_stderr,
+ "Serial input overruns occurred.\n");
+ fprintf_unfiltered (gdb_stderr, "This system %s handle %d baud.\n",
+ port->fifo ? "cannot" : "needs a 16550 to",
+ port->baudrate);
+ }
+}
+
+
+
+static int
+dos_noop (scb)
+ serial_t scb;
+{
+ return 0;
+}
+
+static void
+dos_raw (scb)
+ serial_t scb;
+{
+ /* Always in raw mode */
+}
+
+static int
+dos_readchar (scb, timeout)
+ serial_t scb;
+ int timeout;
+{
+ struct dos_ttystate *port = &ports[scb->fd];
+ long then;
+ int c;
+
+ then = rawclock() + (timeout * RAWHZ);
+ while ((c = dos_getc (port)) < 0)
+ {
+ if (timeout >= 0 && (rawclock () - then) >= 0)
+ return SERIAL_TIMEOUT;
+ notice_quit ();
+ }
+
+ return c;
+}
+
+
+static serial_ttystate
+dos_get_tty_state (scb)
+ serial_t scb;
+{
+ struct dos_ttystate *port = &ports[scb->fd];
+ struct dos_ttystate *state;
+
+ state = (struct dos_ttystate *) xmalloc (sizeof *state);
+ *state = *port;
+ return (serial_ttystate) state;
+}
+
+static int
+dos_set_tty_state (scb, ttystate)
+ serial_t scb;
+ serial_ttystate ttystate;
+{
+ struct dos_ttystate *state;
+
+ state = (struct dos_ttystate *) ttystate;
+ dos_setbaudrate (scb, state->baudrate);
+ return 0;
+}
+
+static int
+dos_noflush_set_tty_state (scb, new_ttystate, old_ttystate)
+ serial_t scb;
+ serial_ttystate new_ttystate;
+ serial_ttystate old_ttystate;
+{
+ struct dos_ttystate *state;
+
+ state = (struct dos_ttystate *) new_ttystate;
+ dos_setbaudrate (scb, state->baudrate);
+ return 0;
+}
+
+static int
+dos_flush_input (scb)
+ serial_t scb;
+{
+ struct dos_ttystate *port = &ports[scb->fd];
+ disable();
+ port->first = port->count = 0;
+ if (port->fifo)
+ outb(port, com_fifo, FIFO_ENABLE|FIFO_RCV_RST|FIFO_TRIGGER);
+ enable();
+}
+
+static void
+dos_print_tty_state (scb, ttystate)
+ serial_t scb;
+ serial_ttystate ttystate;
+{
+ /* Nothing to print */
+ return;
+}
+
+static int
+dos_baudconv (rate)
+ int rate;
+{
+ long x, err;
+
+ if (rate <= 0)
+ return -1;
+
+#define divrnd(n, q) (((n) * 2 / (q) + 1) / 2) /* divide and round off */
+ x = divrnd(COMTICK, rate);
+ if (x <= 0)
+ return -1;
+
+ err = divrnd(1000 * COMTICK, x * rate) - 1000;
+ if (err < 0)
+ err = -err;
+ if (err > SPEED_TOLERANCE)
+ return -1;
+#undef divrnd
+ return x;
+}
+
+
+static int
+dos_setbaudrate (scb, rate)
+ serial_t scb;
+ int rate;
+{
+ struct dos_ttystate *port = &ports[scb->fd];
+
+ if (port->baudrate != rate)
+ {
+ int x;
+ unsigned char cfcr;
+
+ x = dos_baudconv (rate);
+ if (x <= 0)
+ {
+ fprintf_unfiltered (gdb_stderr, "%d: impossible baudrate\n", rate);
+ errno = EINVAL;
+ return -1;
+ }
+
+ disable ();
+ cfcr = inb (port, com_cfcr);
+
+ outb(port, com_cfcr, CFCR_DLAB);
+ outb(port, com_dlbl, x & 0xff);
+ outb(port, com_dlbh, x >> 8);
+ outb(port, com_cfcr, cfcr);
+ port->baudrate = rate;
+ enable ();
+ }
+
+ return 0;
+}
+
+static int
+dos_setstopbits (scb, num)
+ serial_t scb;
+ int num;
+{
+ struct dos_ttystate *port = &ports[scb->fd];
+ unsigned char cfcr;
+
+ disable ();
+ cfcr = inb (port, com_cfcr);
+
+ switch (num)
+ {
+ case SERIAL_1_STOPBITS:
+ outb (port, com_cfcr, cfcr & ~CFCR_STOPB);
+ break;
+ case SERIAL_1_AND_A_HALF_STOPBITS:
+ case SERIAL_2_STOPBITS:
+ outb (port, com_cfcr, cfcr | CFCR_STOPB);
+ break;
+ default:
+ enable ();
+ return 1;
+ }
+ enable ();
+
+ return 0;
+}
+
+static int
+dos_write (scb, str, len)
+ serial_t scb;
+ const char *str;
+ int len;
+{
+ volatile struct dos_ttystate *port = &ports[scb->fd];
+ int fifosize = port->fifo ? 16 : 1;
+ long then;
+ int cnt;
+
+ while (len > 0)
+ {
+ /* send the data, fifosize bytes at a time */
+ cnt = fifosize > len ? len : fifosize;
+ port->txbusy = 1;
+ outportsb (port->base + com_data, str, cnt);
+ str += cnt;
+ len -= cnt;
+#ifdef DOS_STATS
+ cnts[CNT_TX] += cnt;
+#endif
+ /* wait for transmission to complete (max 1 sec) */
+ then = rawclock() + RAWHZ;
+ while (port->txbusy)
+ {
+ if ((rawclock () - then) >= 0)
+ {
+ errno = EIO;
+ return SERIAL_ERROR;
+ }
+ }
+ }
+ return 0;
+}
+
+
+static int
+dos_sendbreak (scb)
+ serial_t scb;
+{
+ volatile struct dos_ttystate *port = &ports[scb->fd];
+ unsigned char cfcr;
+ long then;
+
+ cfcr = inb(port, com_cfcr);
+ outb(port, com_cfcr, cfcr | CFCR_SBREAK);
+
+ /* 0.25 sec delay */
+ then = rawclock () + RAWHZ / 4;
+ while ((rawclock () - then) < 0)
+ continue;
+
+ outb(port, com_cfcr, cfcr);
+ return 0;
+}
+
+
+static struct serial_ops dos_ops =
+{
+ "hardwire",
+ 0,
+ dos_open,
+ dos_close,
+ dos_readchar,
+ dos_write,
+ dos_noop, /* flush output */
+ dos_flush_input,
+ dos_sendbreak,
+ dos_raw,
+ dos_get_tty_state,
+ dos_set_tty_state,
+ dos_print_tty_state,
+ dos_noflush_set_tty_state,
+ dos_setbaudrate,
+ dos_setstopbits,
+ dos_noop, /* wait for output to drain */
+};
+
+
+static void
+dos_info (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ struct dos_ttystate *port;
+ int i;
+
+ for (port = ports; port < &ports[4]; port++)
+ {
+ if (port->baudrate == 0)
+ continue;
+ printf_filtered ("Port:\tCOM%d (%sactive)\n", port - ports + 1,
+ port->intrupt ? "" : "not ");
+ printf_filtered ("Addr:\t0x%03x (irq %d)\n", port->base, port->irq);
+ printf_filtered ("16550:\t%s\n", port->fifo ? "yes" : "no");
+ printf_filtered ("Speed:\t%d baud\n", port->baudrate);
+ printf_filtered ("Errs:\tframing %d parity %d overflow %d\n\n",
+ port->ferr, port->perr, port->oflo);
+ }
+
+#ifdef DOS_STATS
+ printf_filtered ("\nTotal interrupts: %d\n", intrcnt);
+ for (i = 0; i < NCNT; i++)
+ if (cnts[i])
+ printf_filtered ("%s:\t%d\n", cntnames[i], cnts[i]);
+#endif
+}
+
+
+void
+_initialize_ser_dos ()
+{
+ struct cmd_list_element *c;
+
+ serial_add_interface (&dos_ops);
+
+ /* Save original interrupt mask register. */
+ icu_oldmask = inportb (ICU_MASK);
+
+ /* Mark fixed motherboard irqs as inuse. */
+ intrupts[0].inuse = /* timer tick */
+ intrupts[1].inuse = /* keyboard */
+ intrupts[2].inuse = 1; /* slave icu */
+
+ add_show_from_set (
+ add_set_cmd ("com1base", class_obscure, var_zinteger,
+ (char *) &ports[0].base,
+ "Set COM1 base i/o port address.",
+ &setlist),
+ &showlist);
+
+ add_show_from_set (
+ add_set_cmd ("com1irq", class_obscure, var_zinteger,
+ (char *) &ports[0].irq,
+ "Set COM1 interrupt request.",
+ &setlist),
+ &showlist);
+
+ add_show_from_set (
+ add_set_cmd ("com2base", class_obscure, var_zinteger,
+ (char *) &ports[1].base,
+ "Set COM2 base i/o port address.",
+ &setlist),
+ &showlist);
+
+ add_show_from_set (
+ add_set_cmd ("com2irq", class_obscure, var_zinteger,
+ (char *) &ports[1].irq,
+ "Set COM2 interrupt request.",
+ &setlist),
+ &showlist);
+
+ add_show_from_set (
+ add_set_cmd ("com3base", class_obscure, var_zinteger,
+ (char *) &ports[2].base,
+ "Set COM3 base i/o port address.",
+ &setlist),
+ &showlist);
+
+ add_show_from_set (
+ add_set_cmd ("com3irq", class_obscure, var_zinteger,
+ (char *) &ports[2].irq,
+ "Set COM3 interrupt request.",
+ &setlist),
+ &showlist);
+
+ add_show_from_set (
+ add_set_cmd ("com4base", class_obscure, var_zinteger,
+ (char *) &ports[3].base,
+ "Set COM4 base i/o port address.",
+ &setlist),
+ &showlist);
+
+ add_show_from_set (
+ add_set_cmd ("com4irq", class_obscure, var_zinteger,
+ (char *) &ports[3].irq,
+ "Set COM4 interrupt request.",
+ &setlist),
+ &showlist);
+
+ add_info ("serial", dos_info,
+ "Print DOS serial port status.");
+}
diff --git a/gdb/ser-mac.c b/gdb/ser-mac.c
new file mode 100644
index 00000000000..df0040edbf2
--- /dev/null
+++ b/gdb/ser-mac.c
@@ -0,0 +1,362 @@
+/* Remote serial interface for local (hardwired) serial ports for Macintosh.
+ Copyright 1994 Free Software Foundation, Inc.
+ Contributed by Cygnus Support. Written by Stan Shebs.
+
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "serial.h"
+
+#include <Types.h>
+#include <Devices.h>
+/* This is the regular Mac Serial.h, but copied to a different name
+ so as not to get confused with the GDB serial.h above. */
+#include "MacSerial.h"
+
+/* This is unused for now. We just return a placeholder. */
+
+struct mac_ttystate
+ {
+ int bogus;
+ };
+
+static int mac_open PARAMS ((serial_t scb, const char *name));
+static void mac_raw PARAMS ((serial_t scb));
+static int mac_readchar PARAMS ((serial_t scb, int timeout));
+static int mac_setbaudrate PARAMS ((serial_t scb, int rate));
+static int mac_write PARAMS ((serial_t scb, const char *str, int len));
+static void mac_close PARAMS ((serial_t scb));
+static serial_ttystate mac_get_tty_state PARAMS ((serial_t scb));
+static int mac_set_tty_state PARAMS ((serial_t scb, serial_ttystate state));
+static char *aptr PARAMS ((short p));
+
+short input_refnum;
+short output_refnum;
+
+char *mac_input_buffer;
+char *mac_output_buffer;
+
+static int
+mac_open (scb, name)
+ serial_t scb;
+ const char *name;
+{
+ OSErr err;
+
+ /* Alloc buffer space first - that way any allocation failures are
+ intercepted before the serial driver gets involved. */
+ if (mac_input_buffer == NULL)
+ mac_input_buffer = (char *) xmalloc (4096);
+ /* Match on a name and open a port. */
+ if (strcmp (name, "modem") == 0)
+ {
+ err = OpenDriver ("\p.AIn", &input_refnum);
+ if (err != 0)
+ {
+ return (-1);
+ }
+ err = OpenDriver ("\p.AOut", &output_refnum);
+ if (err != 0)
+ {
+ CloseDriver (input_refnum);
+ return (-1);
+ }
+ }
+ else if (strcmp (name, "printer") == 0)
+ {
+ err = OpenDriver ("\p.BIn", &input_refnum);
+ if (err != 0)
+ {
+ return (-1);
+ }
+ err = OpenDriver ("\p.BOut", &output_refnum);
+ if (err != 0)
+ {
+ CloseDriver (input_refnum);
+ return (-1);
+ }
+ /* fake */
+ scb->fd = 1;
+ return 0;
+ }
+ else
+ {
+ error ("You must specify a valid serial port name; your choices are `modem' or `printer'.");
+ errno = ENOENT;
+ return (-1);
+ }
+ /* We got something open. */
+ if (1 /* using custom buffer */)
+ SerSetBuf (input_refnum, mac_input_buffer, 4096);
+ /* Set to a GDB-preferred state. */
+ SerReset (input_refnum, stop10|noParity|data8|baud9600);
+ SerReset (output_refnum, stop10|noParity|data8|baud9600);
+ {
+ CntrlParam cb;
+ struct SerShk *handshake;
+
+ cb.ioCRefNum = output_refnum;
+ cb.csCode = 14;
+ handshake = (struct SerShk *) &cb.csParam[0];
+ handshake->fXOn = 0;
+ handshake->fCTS = 0;
+ handshake->xOn = 0;
+ handshake->xOff = 0;
+ handshake->errs = 0;
+ handshake->evts = 0;
+ handshake->fInX = 0;
+ handshake->fDTR = 0;
+ err = PBControl ((ParmBlkPtr) &cb, 0);
+ if (err < 0)
+ return (-1);
+ }
+ /* fake */
+ scb->fd = 1;
+ return 0;
+}
+
+static int
+mac_noop (scb)
+ serial_t scb;
+{
+ return 0;
+}
+
+static void
+mac_raw (scb)
+ serial_t scb;
+{
+ /* Always effectively in raw mode. */
+}
+
+/* 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 -2 if timeout expired, EOF if line dropped
+ dead, or -3 for any other error (see errno in that case). */
+
+static int
+mac_readchar (scb, timeout)
+ serial_t scb;
+ int timeout;
+{
+ int status, n;
+ /* time_t */ unsigned long start_time, now;
+ OSErr err;
+ CntrlParam cb;
+ IOParam pb;
+
+ if (scb->bufcnt-- > 0)
+ return *scb->bufp++;
+
+ time (&start_time);
+
+ while (1)
+ {
+ cb.ioCRefNum = input_refnum;
+ cb.csCode = 2;
+ err = PBStatus ((ParmBlkPtr) &cb, 0);
+ if (err < 0)
+ return SERIAL_ERROR;
+ n = *((long *) &cb.csParam[0]);
+ if (n > 0)
+ {
+ pb.ioRefNum = input_refnum;
+ pb.ioBuffer = (Ptr) (scb->buf);
+ pb.ioReqCount = (n > 64 ? 64 : n);
+ err = PBRead ((ParmBlkPtr) &pb, 0);
+ if (err < 0)
+ return SERIAL_ERROR;
+ scb->bufcnt = pb.ioReqCount;
+ scb->bufcnt--;
+ scb->bufp = scb->buf;
+ return *scb->bufp++;
+ }
+ else if (timeout == 0)
+ return SERIAL_TIMEOUT;
+ else if (timeout == -1)
+ ;
+ else
+ {
+ time (&now);
+ if (now > start_time + timeout)
+ return SERIAL_TIMEOUT;
+ }
+ PROGRESS (1);
+ }
+}
+
+/* mac_{get set}_tty_state() are both dummys to fill out the function
+ vector. Someday, they may do something real... */
+
+static serial_ttystate
+mac_get_tty_state (scb)
+ serial_t scb;
+{
+ struct mac_ttystate *state;
+
+ state = (struct mac_ttystate *) xmalloc (sizeof *state);
+
+ return (serial_ttystate) state;
+}
+
+static int
+mac_set_tty_state (scb, ttystate)
+ serial_t scb;
+ serial_ttystate ttystate;
+{
+ return 0;
+}
+
+static int
+mac_noflush_set_tty_state (scb, new_ttystate, old_ttystate)
+ serial_t scb;
+ serial_ttystate new_ttystate;
+ serial_ttystate old_ttystate;
+{
+ return 0;
+}
+
+static void
+mac_print_tty_state (scb, ttystate)
+ serial_t scb;
+ serial_ttystate ttystate;
+{
+ /* Nothing to print. */
+ return;
+}
+
+/* If there is a tricky formula to relate real baud rates
+ to what the serial driver wants, we should use it. Until
+ we get one, this table will have to do. */
+
+static struct {
+ int real_rate;
+ int bits;
+} mac_baud_rate_table[] = {
+ { 57600, baud57600 },
+ { 38400, 1 },
+ { 19200, baud19200 },
+ { 9600, baud9600 },
+ { 7200, baud7200 },
+ { 4800, baud4800 },
+ { 3600, baud3600 },
+ { 2400, baud2400 },
+ { 1800, baud1800 },
+ { 1200, baud1200 },
+ { 600, baud600 },
+ { 300, baud300 },
+ { 0, 0 }
+};
+
+static int
+mac_set_baud_rate (scb, rate)
+ serial_t scb;
+ int rate;
+{
+ int i, bits;
+
+ for (i = 0; mac_baud_rate_table[i].real_rate != 0; ++i)
+ {
+ if (mac_baud_rate_table[i].real_rate == rate)
+ {
+ bits = mac_baud_rate_table[i].bits;
+ break;
+ }
+ }
+ SerReset (input_refnum, stop10|noParity|data8|bits);
+ SerReset (output_refnum, stop10|noParity|data8|bits);
+}
+
+static int
+mac_set_stop_bits (scb, num)
+ serial_t scb;
+ int num;
+{
+ return 0;
+}
+
+int first_mac_write = 0;
+
+static int
+mac_write (scb, str, len)
+ serial_t scb;
+ const char *str;
+ int len;
+{
+ OSErr err;
+ IOParam pb;
+
+ if (first_mac_write++ < 4)
+ {
+ sleep (1);
+ }
+ pb.ioRefNum = output_refnum;
+ pb.ioBuffer = (Ptr) str;
+ pb.ioReqCount = len;
+ err = PBWrite ((ParmBlkPtr) &pb, 0);
+ if (err < 0)
+ {
+ return 1;
+ }
+ return 0;
+}
+
+static void
+mac_close (serial_t scb)
+{
+ if (input_refnum)
+ {
+ if (1 /* custom buffer */)
+ SerSetBuf (input_refnum, mac_input_buffer, 0);
+ CloseDriver (input_refnum);
+ input_refnum = 0;
+ }
+ if (output_refnum)
+ {
+ if (0 /* custom buffer */)
+ SerSetBuf (input_refnum, mac_output_buffer, 0);
+ CloseDriver (output_refnum);
+ output_refnum = 0;
+ }
+}
+
+static struct serial_ops mac_ops =
+{
+ "hardwire",
+ 0,
+ mac_open,
+ mac_close,
+ mac_readchar,
+ mac_write,
+ mac_noop, /* flush output */
+ mac_noop, /* flush input */
+ mac_noop, /* send break -- currently only for nindy */
+ mac_raw,
+ mac_get_tty_state,
+ mac_set_tty_state,
+ mac_print_tty_state,
+ mac_noflush_set_tty_state,
+ mac_set_baud_rate,
+ mac_set_stop_bits,
+ mac_noop, /* wait for output to drain */
+};
+
+void
+_initialize_ser_mac ()
+{
+ serial_add_interface (&mac_ops);
+}
diff --git a/gdb/ser-ocd.c b/gdb/ser-ocd.c
new file mode 100644
index 00000000000..971f84e049c
--- /dev/null
+++ b/gdb/ser-ocd.c
@@ -0,0 +1,209 @@
+/* Remote serial interface for Macraigor Systems implementation of
+ On-Chip Debugging using serial target box or serial wiggler
+
+ Copyright 1994, 1997 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "serial.h"
+
+#ifdef _WIN32
+#include <windows.h>
+#endif
+
+static int ser_ocd_open PARAMS ((serial_t scb, const char *name));
+static void ser_ocd_raw PARAMS ((serial_t scb));
+static int ser_ocd_readchar PARAMS ((serial_t scb, int timeout));
+static int ser_ocd_setbaudrate PARAMS ((serial_t scb, int rate));
+static int ser_ocd_write PARAMS ((serial_t scb, const char *str, int len));
+static void ser_ocd_close PARAMS ((serial_t scb));
+static serial_ttystate ser_ocd_get_tty_state PARAMS ((serial_t scb));
+static int ser_ocd_set_tty_state PARAMS ((serial_t scb, serial_ttystate state));
+
+#ifdef _WIN32
+/* On Windows, this function pointer is initialized to a function in
+ the wiggler DLL. */
+static int (*dll_do_command) PARAMS ((const char *, char *));
+#endif
+
+static int
+ocd_open (scb, name)
+ serial_t scb;
+ const char *name;
+{
+#ifdef _WIN32
+ /* Find the wiggler DLL which talks to the board. */
+ if (dll_do_command == NULL)
+ {
+ HINSTANCE handle;
+
+ /* FIXME: Should the user be able to configure this? */
+ handle = LoadLibrary ("Wigglers.dll");
+ if (handle == NULL)
+ error ("Can't load Wigglers.dll");
+
+ dll_do_command = ((int (*) PARAMS ((const char *, char *)))
+ GetProcAddress (handle, "do_command"));
+ if (dll_do_command == NULL)
+ error ("Can't find do_command function in Wigglers.dll");
+ }
+#else
+ /* No wiggler DLLs on Unix yet, fail. */
+ error ("Wiggler library not available for this type of host.");
+#endif /* _WIN32 */
+ return 0;
+}
+
+static int
+ocd_noop (scb)
+ serial_t scb;
+{
+ return 0;
+}
+
+static void
+ocd_raw (scb)
+ serial_t scb;
+{
+ /* Always in raw mode */
+}
+
+static void
+ocd_readremote ()
+{
+}
+
+/* We need a buffer to store responses from the Wigglers.dll */
+#define WIGGLER_BUFF_SIZE 512
+unsigned char from_wiggler_buffer[WIGGLER_BUFF_SIZE];
+unsigned char * wiggler_buffer_ptr; /* curr spot in buffer */
+
+static int
+ocd_readchar (scb, timeout)
+ serial_t scb;
+ int timeout;
+{
+ /* Catch attempts at reading past the end of the buffer */
+ if (wiggler_buffer_ptr >
+ (from_wiggler_buffer + (sizeof (char *) * WIGGLER_BUFF_SIZE)))
+ error ("ocd_readchar asked to read past the end of the buffer!");
+
+ return (int) *wiggler_buffer_ptr++; /* return curr char and increment ptr */
+}
+
+struct ocd_ttystate {
+ int dummy;
+};
+
+/* ocd_{get set}_tty_state() are both dummys to fill out the function
+ vector. Someday, they may do something real... */
+
+static serial_ttystate
+ocd_get_tty_state (scb)
+ serial_t scb;
+{
+ struct ocd_ttystate *state;
+
+ state = (struct ocd_ttystate *) xmalloc (sizeof *state);
+
+ return (serial_ttystate) state;
+}
+
+static int
+ocd_set_tty_state (scb, ttystate)
+ serial_t scb;
+ serial_ttystate ttystate;
+{
+ return 0;
+}
+
+static int
+ocd_noflush_set_tty_state (scb, new_ttystate, old_ttystate)
+ serial_t scb;
+ serial_ttystate new_ttystate;
+ serial_ttystate old_ttystate;
+{
+ return 0;
+}
+
+static void
+ocd_print_tty_state (scb, ttystate)
+ serial_t scb;
+ serial_ttystate ttystate;
+{
+ /* Nothing to print. */
+ return;
+}
+
+static int
+ocd_setbaudrate (scb, rate)
+ serial_t scb;
+ int rate;
+{
+ return 0;
+}
+
+static int
+ocd_write (scb, str, len)
+ serial_t scb;
+ const char *str;
+ int len;
+{
+ char c;
+
+#ifdef _WIN32
+ /* send packet to Wigglers.dll and store response so we can give it to
+ remote-wiggler.c when get_packet is run */
+ dll_do_command (str, from_wiggler_buffer);
+ wiggler_buffer_ptr = from_wiggler_buffer;
+#endif
+
+ return 0;
+}
+
+static void
+ocd_close (scb)
+ serial_t scb;
+{
+}
+
+static struct serial_ops ocd_ops =
+{
+ "ocd",
+ 0,
+ ocd_open,
+ ocd_close,
+ ocd_readchar,
+ ocd_write,
+ ocd_noop, /* flush output */
+ ocd_noop, /* flush input */
+ ocd_noop, /* send break -- currently used only for nindy */
+ ocd_raw,
+ ocd_get_tty_state,
+ ocd_set_tty_state,
+ ocd_print_tty_state,
+ ocd_noflush_set_tty_state,
+ ocd_setbaudrate,
+ ocd_noop, /* wait for output to drain */
+};
+
+void
+_initialize_ser_ocd_bdm ()
+{
+ serial_add_interface (&ocd_ops);
+}
diff --git a/gdb/ser-tcp.c b/gdb/ser-tcp.c
new file mode 100644
index 00000000000..c55133760fa
--- /dev/null
+++ b/gdb/ser-tcp.c
@@ -0,0 +1,358 @@
+/* Serial interface for raw TCP connections on Un*x like systems
+ Copyright 1992, 1993, 1998 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "serial.h"
+#include <sys/types.h>
+#include <sys/time.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <sys/socket.h>
+
+#ifndef __CYGWIN32__
+#include <netinet/tcp.h>
+#endif
+
+#include "signals.h"
+#include "gdb_string.h"
+
+struct tcp_ttystate
+{
+ int bogus;
+};
+
+static int tcp_open PARAMS ((serial_t scb, const char *name));
+static void tcp_raw PARAMS ((serial_t scb));
+static int wait_for PARAMS ((serial_t scb, int timeout));
+static int tcp_readchar PARAMS ((serial_t scb, int timeout));
+static int tcp_setbaudrate PARAMS ((serial_t scb, int rate));
+static int tcp_setstopbits PARAMS ((serial_t scb, int num));
+static int tcp_write PARAMS ((serial_t scb, const char *str, int len));
+/* FIXME: static void tcp_restore PARAMS ((serial_t scb)); */
+static void tcp_close PARAMS ((serial_t scb));
+static serial_ttystate tcp_get_tty_state PARAMS ((serial_t scb));
+static int tcp_set_tty_state PARAMS ((serial_t scb, serial_ttystate state));
+static int tcp_return_0 PARAMS ((serial_t));
+static int tcp_noflush_set_tty_state PARAMS ((serial_t, serial_ttystate,
+ serial_ttystate));
+static void tcp_print_tty_state PARAMS ((serial_t, serial_ttystate));
+
+void _initialize_ser_tcp PARAMS ((void));
+
+/* Open up a raw tcp socket */
+
+static int
+tcp_open(scb, name)
+ serial_t scb;
+ const char *name;
+{
+ char *port_str;
+ int port;
+ struct hostent *hostent;
+ struct sockaddr_in sockaddr;
+ int tmp;
+ char hostname[100];
+ struct protoent *protoent;
+ int i;
+
+ port_str = strchr (name, ':');
+
+ if (!port_str)
+ error ("tcp_open: No colon in host name!"); /* Shouldn't ever happen */
+
+ tmp = min (port_str - name, (int) sizeof hostname - 1);
+ strncpy (hostname, name, tmp); /* Don't want colon */
+ hostname[tmp] = '\000'; /* Tie off host name */
+ port = atoi (port_str + 1);
+
+ hostent = gethostbyname (hostname);
+
+ if (!hostent)
+ {
+ fprintf_unfiltered (gdb_stderr, "%s: unknown host\n", hostname);
+ errno = ENOENT;
+ return -1;
+ }
+
+ for (i = 1; i <= 15; i++)
+ {
+ scb->fd = socket (PF_INET, SOCK_STREAM, 0);
+ if (scb->fd < 0)
+ return -1;
+
+ /* Allow rapid reuse of this port. */
+ tmp = 1;
+ setsockopt (scb->fd, SOL_SOCKET, SO_REUSEADDR, (char *)&tmp, sizeof(tmp));
+
+ /* Enable TCP keep alive process. */
+ tmp = 1;
+ setsockopt (scb->fd, SOL_SOCKET, SO_KEEPALIVE, (char *)&tmp, sizeof(tmp));
+
+ sockaddr.sin_family = PF_INET;
+ sockaddr.sin_port = htons(port);
+ memcpy (&sockaddr.sin_addr.s_addr, hostent->h_addr,
+ sizeof (struct in_addr));
+
+ if (!connect (scb->fd, (struct sockaddr *) &sockaddr, sizeof(sockaddr)))
+ break;
+
+ close (scb->fd);
+ scb->fd = -1;
+
+/* We retry for ECONNREFUSED because that is often a temporary condition, which
+ happens when the server is being restarted. */
+
+ if (errno != ECONNREFUSED)
+ return -1;
+
+ sleep (1);
+ }
+
+ protoent = getprotobyname ("tcp");
+ if (!protoent)
+ return -1;
+
+ tmp = 1;
+ if (setsockopt (scb->fd, protoent->p_proto, TCP_NODELAY,
+ (char *)&tmp, sizeof(tmp)))
+ return -1;
+
+ signal(SIGPIPE, SIG_IGN); /* If we don't do this, then GDB simply exits
+ when the remote side dies. */
+
+ return 0;
+}
+
+static serial_ttystate
+tcp_get_tty_state(scb)
+ serial_t scb;
+{
+ struct tcp_ttystate *state;
+
+ state = (struct tcp_ttystate *)xmalloc(sizeof *state);
+
+ return (serial_ttystate)state;
+}
+
+static int
+tcp_set_tty_state(scb, ttystate)
+ serial_t scb;
+ serial_ttystate ttystate;
+{
+ struct tcp_ttystate *state;
+
+ state = (struct tcp_ttystate *)ttystate;
+
+ return 0;
+}
+
+static int
+tcp_return_0 (scb)
+ serial_t scb;
+{
+ return 0;
+}
+
+static void
+tcp_raw(scb)
+ serial_t scb;
+{
+ return; /* Always in raw mode */
+}
+
+/* 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 tcp_read().
+ */
+
+static int
+wait_for (scb, timeout)
+ serial_t scb;
+ int timeout;
+{
+ int numfds;
+ struct timeval tv;
+ fd_set readfds, exceptfds;
+
+ FD_ZERO (&readfds);
+ FD_ZERO (&exceptfds);
+
+ tv.tv_sec = timeout;
+ tv.tv_usec = 0;
+
+ FD_SET(scb->fd, &readfds);
+ FD_SET(scb->fd, &exceptfds);
+
+ while (1)
+ {
+ if (timeout >= 0)
+ numfds = select(scb->fd+1, &readfds, 0, &exceptfds, &tv);
+ else
+ numfds = select(scb->fd+1, &readfds, 0, &exceptfds, 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;
+ }
+}
+
+/* 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 -2 if timeout expired, EOF if line dropped
+ dead, or -3 for any other error (see errno in that case). */
+
+static int
+tcp_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;
+
+ while (1)
+ {
+ scb->bufcnt = read(scb->fd, scb->buf, BUFSIZ);
+ if (scb->bufcnt != -1 || errno != EINTR)
+ break;
+ }
+
+ 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++;
+}
+
+static int
+tcp_noflush_set_tty_state (scb, new_ttystate, old_ttystate)
+ serial_t scb;
+ serial_ttystate new_ttystate;
+ serial_ttystate old_ttystate;
+{
+ return 0;
+}
+
+static void
+tcp_print_tty_state (scb, ttystate)
+ serial_t scb;
+ serial_ttystate ttystate;
+{
+ /* Nothing to print. */
+ return;
+}
+
+static int
+tcp_setbaudrate(scb, rate)
+ serial_t scb;
+ int rate;
+{
+ return 0; /* Never fails! */
+}
+
+static int
+tcp_setstopbits(scb, num)
+ serial_t scb;
+ int num;
+{
+ return 0; /* Never fails! */
+}
+
+static int
+tcp_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
+tcp_close(scb)
+ serial_t scb;
+{
+ if (scb->fd < 0)
+ return;
+
+ close(scb->fd);
+ scb->fd = -1;
+}
+
+static struct serial_ops tcp_ops =
+{
+ "tcp",
+ 0,
+ tcp_open,
+ tcp_close,
+ tcp_readchar,
+ tcp_write,
+ tcp_return_0, /* flush output */
+ tcp_return_0, /* flush input */
+ tcp_return_0, /* send break */
+ tcp_raw,
+ tcp_get_tty_state,
+ tcp_set_tty_state,
+ tcp_print_tty_state,
+ tcp_noflush_set_tty_state,
+ tcp_setbaudrate,
+ tcp_setstopbits,
+ tcp_return_0, /* wait for output to drain */
+};
+
+void
+_initialize_ser_tcp ()
+{
+ serial_add_interface (&tcp_ops);
+}
diff --git a/gdb/ser-unix.c b/gdb/ser-unix.c
new file mode 100644
index 00000000000..f279c94cfdb
--- /dev/null
+++ b/gdb/ser-unix.c
@@ -0,0 +1,808 @@
+/* Serial interface for local (hardwired) serial ports on Un*x like systems
+ Copyright 1992, 1993, 1994, 1998 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "serial.h"
+#include <fcntl.h>
+#include <sys/types.h>
+#include "terminal.h"
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#ifdef HAVE_TERMIOS
+
+struct hardwire_ttystate
+{
+ struct termios termios;
+};
+#endif /* termios */
+
+#ifdef HAVE_TERMIO
+
+/* 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>
+
+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));
+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));
+static int hardwire_noflush_set_tty_state PARAMS ((serial_t, serial_ttystate,
+ serial_ttystate));
+static void hardwire_print_tty_state PARAMS ((serial_t, serial_ttystate));
+static int hardwire_drain_output PARAMS ((serial_t));
+static int hardwire_flush_output PARAMS ((serial_t));
+static int hardwire_flush_input PARAMS ((serial_t));
+static int hardwire_send_break PARAMS ((serial_t));
+static int hardwire_setstopbits PARAMS ((serial_t, int));
+
+void _initialize_ser_hardwire PARAMS ((void));
+
+#ifdef __CYGWIN32__
+extern void (*ui_loop_hook) PARAMS ((int));
+#endif
+
+/* 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
+ 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;
+ if (ioctl (scb->fd, TIOCSETC, &state->tc) < 0)
+ return -1;
+ if (ioctl (scb->fd, TIOCSLTC, &state->ltc) < 0)
+ return -1;
+ if (ioctl (scb->fd, TIOCLSET, &state->lmode) < 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;
+#ifdef HAVE_SGTTY
+ struct hardwire_ttystate *state = (struct hardwire_ttystate *) old_ttystate;
+#endif
+
+ new_state = *(struct hardwire_ttystate *)new_ttystate;
+
+ /* Don't change in or out of raw mode; we don't want to flush input.
+ termio and termios have no such restriction; for them flushing input
+ is separate from setting the attributes. */
+
+#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
+}
+
+/* Wait for the output to drain away, as opposed to flushing (discarding) it */
+
+static int
+hardwire_drain_output (scb)
+ serial_t scb;
+{
+#ifdef HAVE_TERMIOS
+ return tcdrain (scb->fd);
+#endif
+
+#ifdef HAVE_TERMIO
+ return ioctl (scb->fd, TCSBRK, 1);
+#endif
+
+#ifdef HAVE_SGTTY
+ /* Get the current state and then restore it using TIOCSETP,
+ which should cause the output to drain and pending input
+ to be discarded. */
+ {
+ struct hardwire_ttystate state;
+ if (get_tty_state (scb, &state))
+ {
+ return (-1);
+ }
+ else
+ {
+ return (ioctl (scb->fd, TIOCSETP, &state.sgttyb));
+ }
+ }
+#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;
+{
+ scb->bufcnt = 0;
+ scb->bufp = scb->buf;
+
+#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_unfiltered(gdb_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 |= CLOCAL | 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 |= CLOCAL | 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_unfiltered(gdb_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;
+{
+#ifndef __CYGWIN32__
+ scb->timeout_remaining = 0;
+#endif
+
+#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;
+
+ scb->current_timeout = timeout;
+
+ {
+ struct hardwire_ttystate state;
+
+ if (get_tty_state(scb, &state))
+ fprintf_unfiltered(gdb_stderr, "get_tty_state failed: %s\n", safe_strerror(errno));
+
+#ifdef HAVE_TERMIOS
+ if (timeout < 0)
+ {
+ /* No timeout. */
+ state.termios.c_cc[VTIME] = 0;
+ state.termios.c_cc[VMIN] = 1;
+ }
+ else
+ {
+ state.termios.c_cc[VMIN] = 0;
+ state.termios.c_cc[VTIME] = timeout * 10;
+ if (state.termios.c_cc[VTIME] != timeout * 10)
+ {
+
+ /* If c_cc is an 8-bit signed character, we can't go
+ bigger than this. If it is always unsigned, we could use
+ 25. */
+
+ scb->current_timeout = 12;
+ state.termios.c_cc[VTIME] = scb->current_timeout * 10;
+ scb->timeout_remaining = timeout - scb->current_timeout;
+ }
+ }
+#endif
+
+#ifdef HAVE_TERMIO
+ if (timeout < 0)
+ {
+ /* No timeout. */
+ state.termio.c_cc[VTIME] = 0;
+ state.termio.c_cc[VMIN] = 1;
+ }
+ else
+ {
+ state.termio.c_cc[VMIN] = 0;
+ state.termio.c_cc[VTIME] = timeout * 10;
+ if (state.termio.c_cc[VTIME] != timeout * 10)
+ {
+ /* If c_cc is an 8-bit signed character, we can't go
+ bigger than this. If it is always unsigned, we could use
+ 25. */
+
+ scb->current_timeout = 12;
+ state.termio.c_cc[VTIME] = scb->current_timeout * 10;
+ scb->timeout_remaining = timeout - scb->current_timeout;
+ }
+ }
+#endif
+
+ if (set_tty_state (scb, &state))
+ fprintf_unfiltered(gdb_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;
+#ifdef __CYGWIN32__
+ int t;
+#endif
+
+ if (scb->bufcnt-- > 0)
+ return *scb->bufp++;
+
+#ifdef __CYGWIN32__
+ if (timeout > 0)
+ timeout++;
+#endif
+
+ while (1)
+ {
+#ifdef __CYGWIN32__
+ t = timeout == 0 ? 0 : 1;
+ scb->timeout_remaining = timeout < 0 ? timeout : timeout - t;
+ status = wait_for (scb, t);
+
+ /* -2 means disable timer */
+ if (ui_loop_hook)
+ ui_loop_hook (-2);
+#else
+ status = wait_for (scb, timeout);
+#endif
+ if (status < 0)
+ return status;
+
+ scb->bufcnt = read (scb->fd, scb->buf, BUFSIZ);
+
+ if (scb->bufcnt <= 0)
+ {
+ if (scb->bufcnt == 0)
+ {
+ /* Zero characters means timeout (it could also be EOF, but
+ we don't (yet at least) distinguish). */
+ if (scb->timeout_remaining > 0)
+ {
+ timeout = scb->timeout_remaining;
+ continue;
+ }
+#ifdef __CYGWIN32__
+ else if (scb->timeout_remaining < 0)
+ continue;
+#endif
+ else
+ return SERIAL_TIMEOUT;
+ }
+ else if (errno == EINTR)
+ continue;
+ 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},
+#ifdef B57600
+ {57600, B57600},
+#endif
+#ifdef B115200
+ {115200, B115200},
+#endif
+#ifdef B230400
+ {230400, B230400},
+#endif
+#ifdef B460800
+ {460800, B460800},
+#endif
+ {-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_setstopbits(scb, num)
+ serial_t scb;
+ int num;
+{
+ struct hardwire_ttystate state;
+ int newbit;
+
+ if (get_tty_state(scb, &state))
+ return -1;
+
+ switch (num)
+ {
+ case SERIAL_1_STOPBITS:
+ newbit = 0;
+ break;
+ case SERIAL_1_AND_A_HALF_STOPBITS:
+ case SERIAL_2_STOPBITS:
+ newbit = 1;
+ break;
+ default:
+ return 1;
+ }
+
+#ifdef HAVE_TERMIOS
+ if (!newbit)
+ state.termios.c_cflag &= ~CSTOPB;
+ else
+ state.termios.c_cflag |= CSTOPB; /* two bits */
+#endif
+
+#ifdef HAVE_TERMIO
+ if (!newbit)
+ state.termio.c_cflag &= ~CSTOPB;
+ else
+ state.termio.c_cflag |= CSTOPB; /* two bits */
+#endif
+
+#ifdef HAVE_SGTTY
+ return 0; /* sgtty doesn't support this */
+#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,
+ hardwire_setstopbits,
+ hardwire_drain_output, /* wait for output to drain */
+};
+
+void
+_initialize_ser_hardwire ()
+{
+ serial_add_interface (&hardwire_ops);
+}
diff --git a/gdb/serial.c b/gdb/serial.c
new file mode 100644
index 00000000000..ce420eeadd2
--- /dev/null
+++ b/gdb/serial.c
@@ -0,0 +1,526 @@
+/* Generic serial interface routines
+ Copyright 1992, 1993, 1996, 1997 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include <ctype.h>
+#include "serial.h"
+#include "gdb_string.h"
+#include "gdbcmd.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;
+
+/* Pointer to list of scb's. */
+
+static serial_t scb_base;
+
+/* Non-NULL gives filename which contains a recording of the remote session,
+ suitable for playback by gdbserver. */
+
+static char *serial_logfile = NULL;
+static GDB_FILE *serial_logfp = NULL;
+
+static struct serial_ops *serial_interface_lookup PARAMS ((char *));
+static void serial_logchar PARAMS ((int, int, int));
+static char logbase_hex[] = "hex";
+static char logbase_octal[] = "octal";
+static char logbase_ascii[] = "ascii";
+static char *logbase_enums[] = {logbase_hex, logbase_octal, logbase_ascii, NULL};
+static char *serial_logbase = logbase_ascii;
+
+
+static int serial_current_type = 0;
+
+/* Log char CH of type CHTYPE, with TIMEOUT */
+
+/* Define bogus char to represent a BREAK. Should be careful to choose a value
+ that can't be confused with a normal char, or an error code. */
+#define SERIAL_BREAK 1235
+
+static void
+serial_logchar (ch_type, ch, timeout)
+ int ch_type;
+ int ch;
+ int timeout;
+{
+ if (ch_type != serial_current_type)
+ {
+ fprintf_unfiltered (serial_logfp, "\n%c ", ch_type);
+ serial_current_type = ch_type;
+ }
+
+ if (serial_logbase != logbase_ascii)
+ fputc_unfiltered (' ', serial_logfp);
+
+ switch (ch)
+ {
+ case SERIAL_TIMEOUT:
+ fprintf_unfiltered (serial_logfp, "<Timeout: %d seconds>", timeout);
+ return;
+ case SERIAL_ERROR:
+ fprintf_unfiltered (serial_logfp, "<Error: %s>", safe_strerror (errno));
+ return;
+ case SERIAL_EOF:
+ fputs_unfiltered ("<Eof>", serial_logfp);
+ return;
+ case SERIAL_BREAK:
+ fputs_unfiltered ("<Break>", serial_logfp);
+ return;
+ default:
+ if (serial_logbase == logbase_hex)
+ fprintf_unfiltered (serial_logfp, "%02x", ch & 0xff);
+ else if (serial_logbase == logbase_octal)
+ fprintf_unfiltered (serial_logfp, "%03o", ch & 0xff);
+ else
+ switch (ch)
+ {
+ case '\\': fputs_unfiltered ("\\\\", serial_logfp); break;
+ case '\b': fputs_unfiltered ("\\b", serial_logfp); break;
+ case '\f': fputs_unfiltered ("\\f", serial_logfp); break;
+ case '\n': fputs_unfiltered ("\\n", serial_logfp); break;
+ case '\r': fputs_unfiltered ("\\r", serial_logfp); break;
+ case '\t': fputs_unfiltered ("\\t", serial_logfp); break;
+ case '\v': fputs_unfiltered ("\\v", serial_logfp); break;
+ default: fprintf_unfiltered (serial_logfp, isprint (ch) ? "%c" : "\\x%02x", ch & 0xFF); break;
+ }
+ }
+}
+
+void
+serial_log_command (cmd)
+ const char *cmd;
+{
+ if (!serial_logfp)
+ return;
+
+ serial_current_type = 'c';
+
+ fputs_unfiltered ("\nc ", serial_logfp);
+ fputs_unfiltered (cmd, serial_logfp);
+
+ /* Make sure that the log file is as up-to-date as possible,
+ in case we are getting ready to dump core or something. */
+ gdb_flush (serial_logfp);
+}
+
+int
+serial_write (scb, str, len)
+ serial_t scb;
+ const char *str;
+ int len;
+{
+ if (serial_logfp != NULL)
+ {
+ int count;
+
+ for (count = 0; count < len; count++)
+ serial_logchar ('w', str[count] & 0xff, 0);
+
+ /* Make sure that the log file is as up-to-date as possible,
+ in case we are getting ready to dump core or something. */
+ gdb_flush (serial_logfp);
+ }
+
+ return (scb -> ops -> write (scb, str, len));
+}
+
+int
+serial_readchar (scb, timeout)
+ serial_t scb;
+ int timeout;
+{
+ int ch;
+
+ ch = scb -> ops -> readchar (scb, timeout);
+ if (serial_logfp != NULL)
+ {
+ serial_logchar ('r', ch, timeout);
+
+ /* Make sure that the log file is as up-to-date as possible,
+ in case we are getting ready to dump core or something. */
+ gdb_flush (serial_logfp);
+ }
+
+ return (ch);
+}
+
+int
+serial_send_break (scb)
+ serial_t scb;
+{
+ if (serial_logfp != NULL)
+ serial_logchar ('w', SERIAL_BREAK, 0);
+
+ return (scb -> ops -> send_break (scb));
+}
+
+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;
+
+ for (scb = scb_base; scb; scb = scb->next)
+ if (scb->name && strcmp (scb->name, name) == 0)
+ {
+ scb->refcnt++;
+ return scb;
+ }
+
+ if (strcmp (name, "ocd") == 0)
+ ops = serial_interface_lookup ("ocd");
+ else if (strcmp (name, "pc") == 0)
+ ops = serial_interface_lookup ("pc");
+ else if (strchr (name, ':'))
+ ops = serial_interface_lookup ("tcp");
+ else if (strncmp (name, "lpt", 3) == 0)
+ ops = serial_interface_lookup ("parallel");
+ 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;
+ }
+
+ scb->name = strsave (name);
+ scb->next = scb_base;
+ scb->refcnt = 1;
+ scb_base = scb;
+
+ last_serial_opened = scb;
+
+ if (serial_logfile != NULL)
+ {
+ serial_logfp = gdb_fopen (serial_logfile, "w");
+ if (serial_logfp == NULL)
+ perror_with_name (serial_logfile);
+ }
+
+ return scb;
+}
+
+serial_t
+serial_fdopen (fd)
+ const int fd;
+{
+ serial_t scb;
+ struct serial_ops *ops;
+
+ for (scb = scb_base; scb; scb = scb->next)
+ if (scb->fd == fd)
+ {
+ scb->refcnt++;
+ return scb;
+ }
+
+ 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;
+
+ scb->name = NULL;
+ scb->next = scb_base;
+ scb->refcnt = 1;
+ scb_base = scb;
+
+ last_serial_opened = scb;
+
+ return scb;
+}
+
+void
+serial_close (scb, really_close)
+ serial_t scb;
+ int really_close;
+{
+ serial_t tmp_scb;
+
+ last_serial_opened = NULL;
+
+ if (serial_logfp)
+ {
+ fputs_unfiltered ("\nEnd of log\n", serial_logfp);
+ serial_current_type = 0;
+
+ /* XXX - What if serial_logfp == gdb_stdout or gdb_stderr? */
+ gdb_fclose (&serial_logfp);
+ serial_logfp = 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->refcnt--;
+ if (scb->refcnt > 0)
+ return;
+
+ if (really_close)
+ scb->ops->close (scb);
+
+ if (scb->name)
+ free (scb->name);
+
+ if (scb_base == scb)
+ scb_base = scb_base->next;
+ else
+ for (tmp_scb = scb_base; tmp_scb; tmp_scb = tmp_scb->next)
+ {
+ if (tmp_scb->next != scb)
+ continue;
+
+ tmp_scb->next = tmp_scb->next->next;
+ break;
+ }
+
+ 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_unfiltered ("\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_unfiltered(gdb_stderr, "This command takes no args. They have been ignored.\n");
+
+ printf_unfiltered("[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);
+ }
+ }
+ }
+}
+#endif /* 0 */
+
+/* VARARGS */
+void
+#ifdef ANSI_PROTOTYPES
+serial_printf (serial_t desc, const char *format, ...)
+#else
+serial_printf (va_alist)
+ va_dcl
+#endif
+{
+ va_list args;
+ char *buf;
+#ifdef ANSI_PROTOTYPES
+ va_start (args, format);
+#else
+ serial_t desc;
+ char *format;
+
+ va_start (args);
+ desc = va_arg (args, serial_t);
+ format = va_arg (args, char *);
+#endif
+
+ vasprintf (&buf, format, args);
+ SERIAL_WRITE (desc, buf, strlen (buf));
+
+ free (buf);
+ va_end (args);
+}
+
+void
+_initialize_serial ()
+{
+#if 0
+ 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 */
+
+ add_show_from_set
+ (add_set_cmd ("remotelogfile", no_class,
+ var_filename, (char *) &serial_logfile,
+ "Set filename for remote session recording.\n\
+This file is used to record the remote session for future playback\n\
+by gdbserver.",
+ &setlist),
+ &showlist);
+
+ add_show_from_set
+ (add_set_enum_cmd ("remotelogbase", no_class,
+ logbase_enums, (char *) &serial_logbase,
+ "Set numerical base for remote session logging",
+ &setlist),
+ &showlist);
+}
diff --git a/gdb/serial.h b/gdb/serial.h
new file mode 100644
index 00000000000..04332bcb11f
--- /dev/null
+++ b/gdb/serial.h
@@ -0,0 +1,191 @@
+/* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 */
+ /* ser-unix.c termio{,s} only, we still need to wait for this many more
+ seconds. */
+ int timeout_remaining;
+ char *name; /* The name of the device or host */
+ struct _serial_t *next; /* Pointer to the next serial_t */
+ int refcnt; /* Number of pointers to this block */
+};
+
+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));
+ /* Discard pending output */
+ int (*flush_output) PARAMS ((serial_t));
+ /* Discard pending input */
+ 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));
+ int (*setstopbits) PARAMS ((serial_t, int num));
+ /* Wait for output to drain */
+ int (*drain_output) PARAMS ((serial_t));
+};
+
+/* 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 ((const 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)
+
+/* Allow pending output to drain. */
+
+#define SERIAL_DRAIN_OUTPUT(SERIAL_T) \
+ ((SERIAL_T)->ops->drain_output((SERIAL_T)))
+
+/* Flush (discard) 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. */
+
+extern int serial_send_break PARAMS ((serial_t scb));
+
+#define SERIAL_SEND_BREAK(SERIAL_T) serial_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.
+ Returns 0 for success, negative value for error (in which case errno
+ contains the error). */
+#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
+
+extern int serial_readchar PARAMS ((serial_t scb, int timeout));
+
+#define SERIAL_READCHAR(SERIAL_T, TIMEOUT) serial_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))
+
+/* Set the number of stop bits to the value specified. Returns 0 for success,
+ -1 for failure. */
+
+#define SERIAL_1_STOPBITS 1
+#define SERIAL_1_AND_A_HALF_STOPBITS 2 /* 1.5 bits, snicker... */
+#define SERIAL_2_STOPBITS 3
+
+#define SERIAL_SETSTOPBITS(SERIAL_T, NUM) ((SERIAL_T)->ops->setstopbits((SERIAL_T), NUM))
+
+/* Write LEN chars from STRING to the port SERIAL_T. Returns 0 for
+ success, non-zero for failure. */
+
+extern int serial_write PARAMS ((serial_t scb, const char *str, int len));
+
+#define SERIAL_WRITE(SERIAL_T, STRING,LEN) serial_write (SERIAL_T, STRING, LEN)
+
+/* Push out all buffers, close the device and destroy SERIAL_T. */
+
+extern void serial_close PARAMS ((serial_t, int));
+
+#define SERIAL_CLOSE(SERIAL_T) serial_close(SERIAL_T, 1)
+
+/* Push out all buffers and destroy SERIAL_T without closing the device. */
+
+#define SERIAL_UN_FDOPEN(SERIAL_T) serial_close(SERIAL_T, 0)
+
+extern void serial_printf PARAMS ((serial_t desc, const char *, ...))
+ ATTR_FORMAT(printf, 2, 3);
+
+/* File in which to record the remote debugging session */
+
+extern void serial_log_command PARAMS ((const char *));
+
+#endif /* SERIAL_H */
diff --git a/gdb/sh-stub.c b/gdb/sh-stub.c
new file mode 100644
index 00000000000..a036cff6062
--- /dev/null
+++ b/gdb/sh-stub.c
@@ -0,0 +1,1549 @@
+/* sh-stub.c -- debugging stub for the Hitachi-SH.
+
+ NOTE!! This code has to be compiled with optimization, otherwise the
+ function inlining which generates the exception handlers won't work.
+
+*/
+
+/* This is originally based on an m68k software stub written by Glenn
+ Engel at HP, but has changed quite a bit.
+
+ Modifications for the SH by Ben Lee and Steve Chamberlain
+
+*/
+
+/****************************************************************************
+
+ THIS SOFTWARE IS NOT COPYRIGHTED
+
+ HP offers the following for use in the public domain. HP makes no
+ warranty with regard to the software or it's performance and the
+ user accepts the software "AS IS" with all faults.
+
+ HP DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD
+ TO THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+
+****************************************************************************/
+
+
+/* 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 '#'. If <data> starts with two characters followed by
+ ':', then the existing stubs interpret this as a sequence number.
+
+ 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
+
+ write reg Pn...=r... Write register n... with value r...,
+ which contains two hex digits for each
+ byte in the register (target byte
+ order).
+ reply OK for success
+ ENN for an error
+ (not supported by all stubs).
+
+ 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 exited, and AA is
+ the exit status. This is only
+ applicable for certains sorts of
+ targets.
+ 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.
+ search tAA:PP,MM Search backwards starting at address
+ AA for a match with pattern PP and
+ mask MM. PP and MM are 4 bytes.
+ Not supported by all stubs.
+
+ general query qXXXX Request info about XXXX.
+ general set QXXXX=yyyy Set value of XXXX to yyyy.
+ query sect offs qOffsets Get section offsets. Reply is
+ Text=xxx;Data=yyy;Bss=zzz
+ console output Otext Send text to stdout. Only comes from
+ remote target.
+
+ Responses can be run-length encoded to save space. A '*' means that
+ the next character is an ASCII encoding giving a repeat count which
+ stands for that many repititions of the character preceding the '*'.
+ The encoding is n+29, yielding a printable character where n >=3
+ (which is where rle starts to win). Don't use an n > 126.
+
+ So
+ "0* " means the same as "0000". */
+
+#include <string.h>
+#include <setjmp.h>
+
+
+
+#define COND_BR_MASK 0xff00
+#define UCOND_DBR_MASK 0xe000
+#define UCOND_RBR_MASK 0xf0df
+#define TRAPA_MASK 0xff00
+
+#define COND_DISP 0x00ff
+#define UCOND_DISP 0x0fff
+#define UCOND_REG 0x0f00
+
+#define BF_INSTR 0x8b00
+#define BT_INSTR 0x8900
+#define BRA_INSTR 0xa000
+#define BSR_INSTR 0xb000
+#define JMP_INSTR 0x402b
+#define JSR_INSTR 0x400b
+#define RTS_INSTR 0x000b
+#define RTE_INSTR 0x002b
+#define TRAPA_INSTR 0xc300
+
+#define SSTEP_INSTR 0xc3ff
+
+#define T_BIT_MASK 0x0001
+/*
+ * BUFMAX defines the maximum number of characters in inbound/outbound
+ * buffers at least NUMREGBYTES*2 are needed for register packets
+ */
+#define BUFMAX 1024
+
+/*
+ * Number of bytes for registers
+ */
+#define NUMREGBYTES 112 /* 92 */
+
+/*
+ * typedef
+ */
+typedef void (*Function) ();
+
+/*
+ * Forward declarations
+ */
+
+static int hex (char);
+static char *mem2hex (char *, char *, int);
+static char *hex2mem (char *, char *, int);
+static int hexToInt (char **, int *);
+static void getpacket (char *);
+static void putpacket (char *);
+static void handle_buserror (void);
+static int computeSignal (int exceptionVector);
+static void handle_exception (int exceptionVector);
+void init_serial();
+
+void putDebugChar (char);
+char getDebugChar (void);
+
+/* These are in the file but in asm statements so the compiler can't see them */
+void catch_exception_4 (void);
+void catch_exception_6 (void);
+void catch_exception_9 (void);
+void catch_exception_10 (void);
+void catch_exception_11 (void);
+void catch_exception_32 (void);
+void catch_exception_33 (void);
+void catch_exception_255 (void);
+
+
+
+#define catch_exception_random catch_exception_255 /* Treat all odd ones like 255 */
+
+void breakpoint (void);
+
+
+#define init_stack_size 8*1024 /* if you change this you should also modify BINIT */
+#define stub_stack_size 8*1024
+
+int init_stack[init_stack_size] __attribute__ ((section ("stack"))) = {0};
+int stub_stack[stub_stack_size] __attribute__ ((section ("stack"))) = {0};
+
+typedef struct
+ {
+ void (*func_cold) ();
+ int *stack_cold;
+ void (*func_warm) ();
+ int *stack_warm;
+ void (*(handler[256 - 4])) ();
+ }
+vec_type;
+
+
+void INIT ();
+void BINIT ();
+
+/* When you link take care that this is at address 0 -
+ or wherever your vbr points */
+
+#define CPU_BUS_ERROR_VEC 9
+#define DMA_BUS_ERROR_VEC 10
+#define NMI_VEC 11
+#define INVALID_INSN_VEC 4
+#define INVALID_SLOT_VEC 6
+#define TRAP_VEC 32
+#define IO_VEC 33
+#define USER_VEC 255
+
+
+#define BCR (*(volatile short *)(0x05FFFFA0)) /* Bus control register */
+#define BAS (0x800) /* Byte access select */
+#define WCR1 (*(volatile short *)(0x05ffffA2)) /* Wait state control register */
+
+const vec_type vectable =
+{
+ &BINIT, /* 0: Power-on reset PC */
+ init_stack + init_stack_size, /* 1: Power-on reset SP */
+ &BINIT, /* 2: Manual reset PC */
+ init_stack + init_stack_size, /* 3: Manual reset SP */
+{
+ &catch_exception_4, /* 4: General invalid instruction */
+ &catch_exception_random, /* 5: Reserved for system */
+ &catch_exception_6, /* 6: Invalid slot instruction */
+ &catch_exception_random, /* 7: Reserved for system */
+ &catch_exception_random, /* 8: Reserved for system */
+ &catch_exception_9, /* 9: CPU bus error */
+ &catch_exception_10, /* 10: DMA bus error */
+ &catch_exception_11, /* 11: NMI */
+ &catch_exception_random, /* 12: User break */
+ &catch_exception_random, /* 13: Reserved for system */
+ &catch_exception_random, /* 14: Reserved for system */
+ &catch_exception_random, /* 15: Reserved for system */
+ &catch_exception_random, /* 16: Reserved for system */
+ &catch_exception_random, /* 17: Reserved for system */
+ &catch_exception_random, /* 18: Reserved for system */
+ &catch_exception_random, /* 19: Reserved for system */
+ &catch_exception_random, /* 20: Reserved for system */
+ &catch_exception_random, /* 21: Reserved for system */
+ &catch_exception_random, /* 22: Reserved for system */
+ &catch_exception_random, /* 23: Reserved for system */
+ &catch_exception_random, /* 24: Reserved for system */
+ &catch_exception_random, /* 25: Reserved for system */
+ &catch_exception_random, /* 26: Reserved for system */
+ &catch_exception_random, /* 27: Reserved for system */
+ &catch_exception_random, /* 28: Reserved for system */
+ &catch_exception_random, /* 29: Reserved for system */
+ &catch_exception_random, /* 30: Reserved for system */
+ &catch_exception_random, /* 31: Reserved for system */
+ &catch_exception_32, /* 32: Trap instr (user vectors) */
+ &catch_exception_33, /* 33: Trap instr (user vectors) */
+ &catch_exception_random, /* 34: Trap instr (user vectors) */
+ &catch_exception_random, /* 35: Trap instr (user vectors) */
+ &catch_exception_random, /* 36: Trap instr (user vectors) */
+ &catch_exception_random, /* 37: Trap instr (user vectors) */
+ &catch_exception_random, /* 38: Trap instr (user vectors) */
+ &catch_exception_random, /* 39: Trap instr (user vectors) */
+ &catch_exception_random, /* 40: Trap instr (user vectors) */
+ &catch_exception_random, /* 41: Trap instr (user vectors) */
+ &catch_exception_random, /* 42: Trap instr (user vectors) */
+ &catch_exception_random, /* 43: Trap instr (user vectors) */
+ &catch_exception_random, /* 44: Trap instr (user vectors) */
+ &catch_exception_random, /* 45: Trap instr (user vectors) */
+ &catch_exception_random, /* 46: Trap instr (user vectors) */
+ &catch_exception_random, /* 47: Trap instr (user vectors) */
+ &catch_exception_random, /* 48: Trap instr (user vectors) */
+ &catch_exception_random, /* 49: Trap instr (user vectors) */
+ &catch_exception_random, /* 50: Trap instr (user vectors) */
+ &catch_exception_random, /* 51: Trap instr (user vectors) */
+ &catch_exception_random, /* 52: Trap instr (user vectors) */
+ &catch_exception_random, /* 53: Trap instr (user vectors) */
+ &catch_exception_random, /* 54: Trap instr (user vectors) */
+ &catch_exception_random, /* 55: Trap instr (user vectors) */
+ &catch_exception_random, /* 56: Trap instr (user vectors) */
+ &catch_exception_random, /* 57: Trap instr (user vectors) */
+ &catch_exception_random, /* 58: Trap instr (user vectors) */
+ &catch_exception_random, /* 59: Trap instr (user vectors) */
+ &catch_exception_random, /* 60: Trap instr (user vectors) */
+ &catch_exception_random, /* 61: Trap instr (user vectors) */
+ &catch_exception_random, /* 62: Trap instr (user vectors) */
+ &catch_exception_random, /* 63: Trap instr (user vectors) */
+ &catch_exception_random, /* 64: IRQ0 */
+ &catch_exception_random, /* 65: IRQ1 */
+ &catch_exception_random, /* 66: IRQ2 */
+ &catch_exception_random, /* 67: IRQ3 */
+ &catch_exception_random, /* 68: IRQ4 */
+ &catch_exception_random, /* 69: IRQ5 */
+ &catch_exception_random, /* 70: IRQ6 */
+ &catch_exception_random, /* 71: IRQ7 */
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_random,
+ &catch_exception_255}};
+
+
+char in_nmi; /* Set when handling an NMI, so we don't reenter */
+int dofault; /* Non zero, bus errors will raise exception */
+
+int *stub_sp;
+
+/* debug > 0 prints ill-formed commands in valid packets & checksum errors */
+int remote_debug;
+
+/* jump buffer used for setjmp/longjmp */
+jmp_buf remcomEnv;
+
+enum regnames
+ {
+ R0, R1, R2, R3, R4, R5, R6, R7,
+ R8, R9, R10, R11, R12, R13, R14,
+ R15, PC, PR, GBR, VBR, MACH, MACL, SR,
+ TICKS, STALLS, CYCLES, INSTS, PLR
+ };
+
+typedef struct
+ {
+ short *memAddr;
+ short oldInstr;
+ }
+stepData;
+
+int registers[NUMREGBYTES / 4];
+stepData instrBuffer;
+char stepped;
+static const char hexchars[] = "0123456789abcdef";
+char remcomInBuffer[BUFMAX];
+char remcomOutBuffer[BUFMAX];
+
+char highhex(int x)
+{
+ return hexchars[(x >> 4) & 0xf];
+}
+
+char lowhex(int x)
+{
+ return hexchars[x & 0xf];
+}
+
+/*
+ * Assembly macros
+ */
+
+#define BREAKPOINT() asm("trapa #0x20"::);
+
+
+/*
+ * Routines to handle hex data
+ */
+
+static int
+hex (char ch)
+{
+ if ((ch >= 'a') && (ch <= 'f'))
+ return (ch - 'a' + 10);
+ if ((ch >= '0') && (ch <= '9'))
+ return (ch - '0');
+ if ((ch >= 'A') && (ch <= 'F'))
+ return (ch - 'A' + 10);
+ return (-1);
+}
+
+/* convert the memory, pointed to by mem into hex, placing result in buf */
+/* return a pointer to the last char put in buf (null) */
+static char *
+mem2hex (char *mem, char *buf, int count)
+{
+ int i;
+ int ch;
+ for (i = 0; i < count; i++)
+ {
+ ch = *mem++;
+ *buf++ = highhex (ch);
+ *buf++ = lowhex (ch);
+ }
+ *buf = 0;
+ return (buf);
+}
+
+/* convert the hex array pointed to by buf into binary, to be placed in mem */
+/* return a pointer to the character after the last byte written */
+
+static char *
+hex2mem (char *buf, char *mem, int count)
+{
+ int i;
+ unsigned char ch;
+ for (i = 0; i < count; i++)
+ {
+ ch = hex (*buf++) << 4;
+ ch = ch + hex (*buf++);
+ *mem++ = ch;
+ }
+ return (mem);
+}
+
+/**********************************************/
+/* WHILE WE FIND NICE HEX CHARS, BUILD AN INT */
+/* RETURN NUMBER OF CHARS PROCESSED */
+/**********************************************/
+static int
+hexToInt (char **ptr, int *intValue)
+{
+ int numChars = 0;
+ int hexValue;
+
+ *intValue = 0;
+
+ while (**ptr)
+ {
+ hexValue = hex (**ptr);
+ if (hexValue >= 0)
+ {
+ *intValue = (*intValue << 4) | hexValue;
+ numChars++;
+ }
+ else
+ break;
+
+ (*ptr)++;
+ }
+
+ return (numChars);
+}
+
+/*
+ * Routines to get and put packets
+ */
+
+/* scan for the sequence $<data>#<checksum> */
+
+static
+void
+getpacket (char *buffer)
+{
+ unsigned char checksum;
+ unsigned char xmitcsum;
+ int i;
+ int count;
+ char ch;
+ do
+ {
+ /* wait around for the start character, ignore all other characters */
+ while ((ch = getDebugChar ()) != '$');
+ checksum = 0;
+ xmitcsum = -1;
+
+ count = 0;
+
+ /* now, read until a # or end of buffer is found */
+ while (count < BUFMAX)
+ {
+ ch = getDebugChar ();
+ if (ch == '#')
+ break;
+ checksum = checksum + ch;
+ buffer[count] = ch;
+ count = count + 1;
+ }
+ buffer[count] = 0;
+
+ if (ch == '#')
+ {
+ xmitcsum = hex (getDebugChar ()) << 4;
+ xmitcsum += hex (getDebugChar ());
+ if (checksum != xmitcsum)
+ putDebugChar ('-'); /* failed checksum */
+ else
+ {
+ putDebugChar ('+'); /* successful transfer */
+ /* if a sequence char is present, reply the sequence ID */
+ if (buffer[2] == ':')
+ {
+ putDebugChar (buffer[0]);
+ putDebugChar (buffer[1]);
+ /* remove sequence chars from buffer */
+ count = strlen (buffer);
+ for (i = 3; i <= count; i++)
+ buffer[i - 3] = buffer[i];
+ }
+ }
+ }
+ }
+ while (checksum != xmitcsum);
+
+}
+
+
+/* send the packet in buffer. The host get's one chance to read it.
+ This routine does not wait for a positive acknowledge. */
+
+static void
+putpacket (register char *buffer)
+{
+ register int checksum;
+ register int count;
+
+ /* $<packet info>#<checksum>. */
+ do
+ {
+ char *src = buffer;
+ putDebugChar ('$');
+ checksum = 0;
+
+ while (*src)
+ {
+ int runlen;
+
+ /* Do run length encoding */
+ for (runlen = 0; runlen < 100; runlen ++)
+ {
+ if (src[0] != src[runlen])
+ {
+ if (runlen > 3)
+ {
+ int encode;
+ /* Got a useful amount */
+ putDebugChar (*src);
+ checksum += *src;
+ putDebugChar ('*');
+ checksum += '*';
+ checksum += (encode = runlen + ' ' - 4);
+ putDebugChar (encode);
+ src += runlen;
+ }
+ else
+ {
+ putDebugChar (*src);
+ checksum += *src;
+ src++;
+ }
+ break;
+ }
+ }
+ }
+
+
+ putDebugChar ('#');
+ putDebugChar (highhex(checksum));
+ putDebugChar (lowhex(checksum));
+ }
+ while (getDebugChar() != '+');
+
+}
+
+
+/* a bus error has occurred, perform a longjmp
+ to return execution and allow handling of the error */
+
+void
+handle_buserror (void)
+{
+ longjmp (remcomEnv, 1);
+}
+
+/*
+ * this function takes the SH-1 exception number and attempts to
+ * translate this number into a unix compatible signal value
+ */
+static int
+computeSignal (int exceptionVector)
+{
+ int sigval;
+ switch (exceptionVector)
+ {
+ case INVALID_INSN_VEC:
+ sigval = 4;
+ break;
+ case INVALID_SLOT_VEC:
+ sigval = 4;
+ break;
+ case CPU_BUS_ERROR_VEC:
+ sigval = 10;
+ break;
+ case DMA_BUS_ERROR_VEC:
+ sigval = 10;
+ break;
+ case NMI_VEC:
+ sigval = 2;
+ break;
+
+ case TRAP_VEC:
+ case USER_VEC:
+ sigval = 5;
+ break;
+
+ default:
+ sigval = 7; /* "software generated"*/
+ break;
+ }
+ return (sigval);
+}
+
+void
+doSStep (void)
+{
+ short *instrMem;
+ int displacement;
+ int reg;
+ unsigned short opcode;
+
+ instrMem = (short *) registers[PC];
+
+ opcode = *instrMem;
+ stepped = 1;
+
+ if ((opcode & COND_BR_MASK) == BT_INSTR)
+ {
+ if (registers[SR] & T_BIT_MASK)
+ {
+ displacement = (opcode & COND_DISP) << 1;
+ if (displacement & 0x80)
+ displacement |= 0xffffff00;
+ /*
+ * Remember PC points to second instr.
+ * after PC of branch ... so add 4
+ */
+ instrMem = (short *) (registers[PC] + displacement + 4);
+ }
+ else
+ instrMem += 1;
+ }
+ else if ((opcode & COND_BR_MASK) == BF_INSTR)
+ {
+ if (registers[SR] & T_BIT_MASK)
+ instrMem += 1;
+ else
+ {
+ displacement = (opcode & COND_DISP) << 1;
+ if (displacement & 0x80)
+ displacement |= 0xffffff00;
+ /*
+ * Remember PC points to second instr.
+ * after PC of branch ... so add 4
+ */
+ instrMem = (short *) (registers[PC] + displacement + 4);
+ }
+ }
+ else if ((opcode & UCOND_DBR_MASK) == BRA_INSTR)
+ {
+ displacement = (opcode & UCOND_DISP) << 1;
+ if (displacement & 0x0800)
+ displacement |= 0xfffff000;
+
+ /*
+ * Remember PC points to second instr.
+ * after PC of branch ... so add 4
+ */
+ instrMem = (short *) (registers[PC] + displacement + 4);
+ }
+ else if ((opcode & UCOND_RBR_MASK) == JSR_INSTR)
+ {
+ reg = (char) ((opcode & UCOND_REG) >> 8);
+
+ instrMem = (short *) registers[reg];
+ }
+ else if (opcode == RTS_INSTR)
+ instrMem = (short *) registers[PR];
+ else if (opcode == RTE_INSTR)
+ instrMem = (short *) registers[15];
+ else if ((opcode & TRAPA_MASK) == TRAPA_INSTR)
+ instrMem = (short *) ((opcode & ~TRAPA_MASK) << 2);
+ else
+ instrMem += 1;
+
+ instrBuffer.memAddr = instrMem;
+ instrBuffer.oldInstr = *instrMem;
+ *instrMem = SSTEP_INSTR;
+}
+
+
+/* Undo the effect of a previous doSStep. If we single stepped,
+ restore the old instruction. */
+
+void
+undoSStep (void)
+{
+ if (stepped)
+ { short *instrMem;
+ instrMem = instrBuffer.memAddr;
+ *instrMem = instrBuffer.oldInstr;
+ }
+ stepped = 0;
+}
+
+/*
+This function does all exception handling. It only does two things -
+it figures out why it was called and tells gdb, and then it reacts
+to gdb's requests.
+
+When in the monitor mode we talk a human on the serial line rather than gdb.
+
+*/
+
+
+void
+gdb_handle_exception (int exceptionVector)
+{
+ int sigval;
+ int addr, length;
+ char *ptr;
+
+ /* reply to host that an exception has occurred */
+ sigval = computeSignal (exceptionVector);
+ remcomOutBuffer[0] = 'S';
+ remcomOutBuffer[1] = highhex(sigval);
+ remcomOutBuffer[2] = lowhex (sigval);
+ remcomOutBuffer[3] = 0;
+
+ putpacket (remcomOutBuffer);
+
+ /*
+ * exception 255 indicates a software trap
+ * inserted in place of code ... so back up
+ * PC by one instruction, since this instruction
+ * will later be replaced by its original one!
+ */
+ if (exceptionVector == 0xff
+ || exceptionVector == 0x20)
+ registers[PC] -= 2;
+
+ /*
+ * Do the thangs needed to undo
+ * any stepping we may have done!
+ */
+ undoSStep ();
+
+ while (1)
+ {
+ remcomOutBuffer[0] = 0;
+ getpacket (remcomInBuffer);
+
+ switch (remcomInBuffer[0])
+ {
+ case '?':
+ remcomOutBuffer[0] = 'S';
+ remcomOutBuffer[1] = highhex (sigval);
+ remcomOutBuffer[2] = lowhex (sigval);
+ remcomOutBuffer[3] = 0;
+ break;
+ case 'd':
+ remote_debug = !(remote_debug); /* toggle debug flag */
+ break;
+ case 'g': /* return the value of the CPU registers */
+ mem2hex ((char *) registers, remcomOutBuffer, NUMREGBYTES);
+ break;
+ case 'G': /* set the value of the CPU registers - return OK */
+ hex2mem (&remcomInBuffer[1], (char *) registers, NUMREGBYTES);
+ strcpy (remcomOutBuffer, "OK");
+ break;
+
+ /* mAA..AA,LLLL Read LLLL bytes at address AA..AA */
+ case 'm':
+ if (setjmp (remcomEnv) == 0)
+ {
+ dofault = 0;
+ /* TRY, TO READ %x,%x. IF SUCCEED, SET PTR = 0 */
+ ptr = &remcomInBuffer[1];
+ if (hexToInt (&ptr, &addr))
+ if (*(ptr++) == ',')
+ if (hexToInt (&ptr, &length))
+ {
+ ptr = 0;
+ mem2hex ((char *) addr, remcomOutBuffer, length);
+ }
+ if (ptr)
+ strcpy (remcomOutBuffer, "E01");
+ }
+ else
+ strcpy (remcomOutBuffer, "E03");
+
+ /* restore handler for bus error */
+ dofault = 1;
+ break;
+
+ /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
+ case 'M':
+ if (setjmp (remcomEnv) == 0)
+ {
+ dofault = 0;
+
+ /* TRY, TO READ '%x,%x:'. IF SUCCEED, SET PTR = 0 */
+ ptr = &remcomInBuffer[1];
+ if (hexToInt (&ptr, &addr))
+ if (*(ptr++) == ',')
+ if (hexToInt (&ptr, &length))
+ if (*(ptr++) == ':')
+ {
+ hex2mem (ptr, (char *) addr, length);
+ ptr = 0;
+ strcpy (remcomOutBuffer, "OK");
+ }
+ if (ptr)
+ strcpy (remcomOutBuffer, "E02");
+ }
+ else
+ strcpy (remcomOutBuffer, "E03");
+
+ /* restore handler for bus error */
+ dofault = 1;
+ break;
+
+ /* cAA..AA Continue at address AA..AA(optional) */
+ /* sAA..AA Step one instruction from AA..AA(optional) */
+ case 'c':
+ case 's':
+ {
+ /* tRY, to read optional parameter, pc unchanged if no parm */
+ ptr = &remcomInBuffer[1];
+ if (hexToInt (&ptr, &addr))
+ registers[PC] = addr;
+
+ if (remcomInBuffer[0] == 's')
+ doSStep ();
+ }
+ return;
+ break;
+
+ /* kill the program */
+ case 'k': /* do nothing */
+ break;
+ } /* switch */
+
+ /* reply to the request */
+ putpacket (remcomOutBuffer);
+ }
+}
+
+
+#define GDBCOOKIE 0x5ac
+static int ingdbmode;
+/* We've had an exception - choose to go into the monitor or
+ the gdb stub */
+void handle_exception(int exceptionVector)
+{
+#ifdef MONITOR
+ if (ingdbmode != GDBCOOKIE)
+ monitor_handle_exception (exceptionVector);
+ else
+#endif
+ gdb_handle_exception (exceptionVector);
+
+}
+
+void
+gdb_mode()
+{
+ ingdbmode = GDBCOOKIE;
+ breakpoint();
+}
+/* This function will generate a breakpoint exception. It is used at the
+ beginning of a program to sync up with a debugger and can be used
+ otherwise as a quick means to stop program execution and "break" into
+ the debugger. */
+
+void
+breakpoint (void)
+{
+ BREAKPOINT ();
+}
+
+asm ("_BINIT: mov.l L1,r15");
+asm ("bra _INIT");
+asm ("nop");
+asm ("L1: .long _init_stack + 8*1024*4");
+void
+INIT (void)
+{
+ /* First turn on the ram */
+ WCR1 = 0; /* Never sample wait */
+ BCR = BAS; /* use lowbyte/high byte */
+
+ init_serial();
+
+#ifdef MONITOR
+ reset_hook ();
+#endif
+
+
+ in_nmi = 0;
+ dofault = 1;
+ stepped = 0;
+
+ stub_sp = stub_stack + stub_stack_size;
+ breakpoint ();
+
+ while (1)
+ ;
+}
+
+
+static void sr()
+{
+
+
+ /* Calling Reset does the same as pressing the button */
+ asm (".global _Reset
+ .global _WarmReset
+_Reset:
+_WarmReset:
+ mov.l L_sp,r15
+ bra _INIT
+ nop
+ .align 2
+L_sp: .long _init_stack + 8000");
+
+ asm("saveRegisters:
+ mov.l @(L_reg, pc), r0
+ mov.l @r15+, r1 ! pop R0
+ mov.l r2, @(0x08, r0) ! save R2
+ mov.l r1, @r0 ! save R0
+ mov.l @r15+, r1 ! pop R1
+ mov.l r3, @(0x0c, r0) ! save R3
+ mov.l r1, @(0x04, r0) ! save R1
+ mov.l r4, @(0x10, r0) ! save R4
+ mov.l r5, @(0x14, r0) ! save R5
+ mov.l r6, @(0x18, r0) ! save R6
+ mov.l r7, @(0x1c, r0) ! save R7
+ mov.l r8, @(0x20, r0) ! save R8
+ mov.l r9, @(0x24, r0) ! save R9
+ mov.l r10, @(0x28, r0) ! save R10
+ mov.l r11, @(0x2c, r0) ! save R11
+ mov.l r12, @(0x30, r0) ! save R12
+ mov.l r13, @(0x34, r0) ! save R13
+ mov.l r14, @(0x38, r0) ! save R14
+ mov.l @r15+, r4 ! save arg to handleException
+ add #8, r15 ! hide PC/SR values on stack
+ mov.l r15, @(0x3c, r0) ! save R15
+ add #-8, r15 ! save still needs old SP value
+ add #92, r0 ! readjust register pointer
+ mov r15, r2
+ add #4, r2
+ mov.l @r2, r2 ! R2 has SR
+ mov.l @r15, r1 ! R1 has PC
+ mov.l r2, @-r0 ! save SR
+ sts.l macl, @-r0 ! save MACL
+ sts.l mach, @-r0 ! save MACH
+ stc.l vbr, @-r0 ! save VBR
+ stc.l gbr, @-r0 ! save GBR
+ sts.l pr, @-r0 ! save PR
+ mov.l @(L_stubstack, pc), r2
+ mov.l @(L_hdl_except, pc), r3
+ mov.l @r2, r15
+ jsr @r3
+ mov.l r1, @-r0 ! save PC
+ mov.l @(L_stubstack, pc), r0
+ mov.l @(L_reg, pc), r1
+ bra restoreRegisters
+ mov.l r15, @r0 ! save __stub_stack
+
+ .align 2
+L_reg:
+ .long _registers
+L_stubstack:
+ .long _stub_sp
+L_hdl_except:
+ .long _handle_exception");
+
+}
+
+static void rr()
+{
+asm("
+ .align 2
+ .global _resume
+_resume:
+ mov r4,r1
+restoreRegisters:
+ add #8, r1 ! skip to R2
+ mov.l @r1+, r2 ! restore R2
+ mov.l @r1+, r3 ! restore R3
+ mov.l @r1+, r4 ! restore R4
+ mov.l @r1+, r5 ! restore R5
+ mov.l @r1+, r6 ! restore R6
+ mov.l @r1+, r7 ! restore R7
+ mov.l @r1+, r8 ! restore R8
+ mov.l @r1+, r9 ! restore R9
+ mov.l @r1+, r10 ! restore R10
+ mov.l @r1+, r11 ! restore R11
+ mov.l @r1+, r12 ! restore R12
+ mov.l @r1+, r13 ! restore R13
+ mov.l @r1+, r14 ! restore R14
+ mov.l @r1+, r15 ! restore programs stack
+ mov.l @r1+, r0
+ add #-8, r15 ! uncover PC/SR on stack
+ mov.l r0, @r15 ! restore PC onto stack
+ lds.l @r1+, pr ! restore PR
+ ldc.l @r1+, gbr ! restore GBR
+ ldc.l @r1+, vbr ! restore VBR
+ lds.l @r1+, mach ! restore MACH
+ lds.l @r1+, macl ! restore MACL
+ mov.l @r1, r0
+ add #-88, r1 ! readjust reg pointer to R1
+ mov.l r0, @(4, r15) ! restore SR onto stack+4
+ mov.l r2, @-r15
+ mov.l L_in_nmi, r0
+ mov #0, r2
+ mov.b r2, @r0
+ mov.l @r15+, r2
+ mov.l @r1+, r0 ! restore R0
+ rte
+ mov.l @r1, r1 ! restore R1
+
+");
+}
+
+
+static __inline__ void code_for_catch_exception(int n)
+{
+ asm(" .globl _catch_exception_%O0" : : "i" (n) );
+ asm(" _catch_exception_%O0:" :: "i" (n) );
+
+ asm(" add #-4, r15 ! reserve spot on stack ");
+ asm(" mov.l r1, @-r15 ! push R1 ");
+
+ if (n == NMI_VEC)
+ {
+ /* Special case for NMI - make sure that they don't nest */
+ asm(" mov.l r0, @-r15 ! push R0");
+ asm(" mov.l L_in_nmi, r0");
+ asm(" tas.b @r0 ! Fend off against addtnl NMIs");
+ asm(" bt noNMI");
+ asm(" mov.l @r15+, r0");
+ asm(" mov.l @r15+, r1");
+ asm(" add #4, r15");
+ asm(" rte");
+ asm(" nop");
+ asm(".align 2");
+ asm("L_in_nmi: .long _in_nmi");
+ asm("noNMI:");
+ }
+ else
+ {
+
+ if (n == CPU_BUS_ERROR_VEC)
+ {
+ /* Exception 9 (bus errors) are disasbleable - so that you
+ can probe memory and get zero instead of a fault.
+ Because the vector table may be in ROM we don't revector
+ the interrupt like all the other stubs, we check in here
+ */
+ asm("mov.l L_dofault,r1");
+ asm("mov.l @r1,r1");
+ asm("tst r1,r1");
+ asm("bf faultaway");
+ asm("bsr _handle_buserror");
+ asm(".align 2");
+ asm("L_dofault: .long _dofault");
+ asm("faultaway:");
+ }
+ asm(" mov #15<<4, r1 ");
+ asm(" ldc r1, sr ! disable interrupts ");
+ asm(" mov.l r0, @-r15 ! push R0 ");
+ }
+
+ /* Prepare for saving context, we've already pushed r0 and r1, stick exception number
+ into the frame */
+ asm(" mov r15, r0 ");
+ asm(" add #8, r0 ");
+ asm(" mov %0,r1" :: "i" (n) );
+ asm(" extu.b r1,r1 ");
+ asm(" bra saveRegisters ! save register values ");
+ asm(" mov.l r1, @r0 ! save exception # ");
+}
+
+
+static void
+exceptions()
+{
+ code_for_catch_exception (CPU_BUS_ERROR_VEC);
+ code_for_catch_exception (DMA_BUS_ERROR_VEC);
+ code_for_catch_exception (INVALID_INSN_VEC);
+ code_for_catch_exception (INVALID_SLOT_VEC);
+ code_for_catch_exception (NMI_VEC);
+ code_for_catch_exception (TRAP_VEC);
+ code_for_catch_exception (USER_VEC);
+ code_for_catch_exception (IO_VEC);
+}
+
+
+
+
+
+
+/* Support for Serial I/O using on chip uart */
+
+#define SMR0 (*(volatile char *)(0x05FFFEC0)) /* Channel 0 serial mode register */
+#define BRR0 (*(volatile char *)(0x05FFFEC1)) /* Channel 0 bit rate register */
+#define SCR0 (*(volatile char *)(0x05FFFEC2)) /* Channel 0 serial control register */
+#define TDR0 (*(volatile char *)(0x05FFFEC3)) /* Channel 0 transmit data register */
+#define SSR0 (*(volatile char *)(0x05FFFEC4)) /* Channel 0 serial status register */
+#define RDR0 (*(volatile char *)(0x05FFFEC5)) /* Channel 0 receive data register */
+
+#define SMR1 (*(volatile char *)(0x05FFFEC8)) /* Channel 1 serial mode register */
+#define BRR1 (*(volatile char *)(0x05FFFEC9)) /* Channel 1 bit rate register */
+#define SCR1 (*(volatile char *)(0x05FFFECA)) /* Channel 1 serial control register */
+#define TDR1 (*(volatile char *)(0x05FFFECB)) /* Channel 1 transmit data register */
+#define SSR1 (*(volatile char *)(0x05FFFECC)) /* Channel 1 serial status register */
+#define RDR1 (*(volatile char *)(0x05FFFECD)) /* Channel 1 receive data register */
+
+/*
+ * Serial mode register bits
+ */
+
+#define SYNC_MODE 0x80
+#define SEVEN_BIT_DATA 0x40
+#define PARITY_ON 0x20
+#define ODD_PARITY 0x10
+#define STOP_BITS_2 0x08
+#define ENABLE_MULTIP 0x04
+#define PHI_64 0x03
+#define PHI_16 0x02
+#define PHI_4 0x01
+
+/*
+ * Serial control register bits
+ */
+#define SCI_TIE 0x80 /* Transmit interrupt enable */
+#define SCI_RIE 0x40 /* Receive interrupt enable */
+#define SCI_TE 0x20 /* Transmit enable */
+#define SCI_RE 0x10 /* Receive enable */
+#define SCI_MPIE 0x08 /* Multiprocessor interrupt enable */
+#define SCI_TEIE 0x04 /* Transmit end interrupt enable */
+#define SCI_CKE1 0x02 /* Clock enable 1 */
+#define SCI_CKE0 0x01 /* Clock enable 0 */
+
+/*
+ * Serial status register bits
+ */
+#define SCI_TDRE 0x80 /* Transmit data register empty */
+#define SCI_RDRF 0x40 /* Receive data register full */
+#define SCI_ORER 0x20 /* Overrun error */
+#define SCI_FER 0x10 /* Framing error */
+#define SCI_PER 0x08 /* Parity error */
+#define SCI_TEND 0x04 /* Transmit end */
+#define SCI_MPB 0x02 /* Multiprocessor bit */
+#define SCI_MPBT 0x01 /* Multiprocessor bit transfer */
+
+
+/*
+ * Port B IO Register (PBIOR)
+ */
+#define PBIOR (*(volatile char *)(0x05FFFFC6))
+#define PB15IOR 0x8000
+#define PB14IOR 0x4000
+#define PB13IOR 0x2000
+#define PB12IOR 0x1000
+#define PB11IOR 0x0800
+#define PB10IOR 0x0400
+#define PB9IOR 0x0200
+#define PB8IOR 0x0100
+#define PB7IOR 0x0080
+#define PB6IOR 0x0040
+#define PB5IOR 0x0020
+#define PB4IOR 0x0010
+#define PB3IOR 0x0008
+#define PB2IOR 0x0004
+#define PB1IOR 0x0002
+#define PB0IOR 0x0001
+
+/*
+ * Port B Control Register (PBCR1)
+ */
+#define PBCR1 (*(volatile short *)(0x05FFFFCC))
+#define PB15MD1 0x8000
+#define PB15MD0 0x4000
+#define PB14MD1 0x2000
+#define PB14MD0 0x1000
+#define PB13MD1 0x0800
+#define PB13MD0 0x0400
+#define PB12MD1 0x0200
+#define PB12MD0 0x0100
+#define PB11MD1 0x0080
+#define PB11MD0 0x0040
+#define PB10MD1 0x0020
+#define PB10MD0 0x0010
+#define PB9MD1 0x0008
+#define PB9MD0 0x0004
+#define PB8MD1 0x0002
+#define PB8MD0 0x0001
+
+#define PB15MD PB15MD1|PB14MD0
+#define PB14MD PB14MD1|PB14MD0
+#define PB13MD PB13MD1|PB13MD0
+#define PB12MD PB12MD1|PB12MD0
+#define PB11MD PB11MD1|PB11MD0
+#define PB10MD PB10MD1|PB10MD0
+#define PB9MD PB9MD1|PB9MD0
+#define PB8MD PB8MD1|PB8MD0
+
+#define PB_TXD1 PB11MD1
+#define PB_RXD1 PB10MD1
+#define PB_TXD0 PB9MD1
+#define PB_RXD0 PB8MD1
+
+/*
+ * Port B Control Register (PBCR2)
+ */
+#define PBCR2 0x05FFFFCE
+#define PB7MD1 0x8000
+#define PB7MD0 0x4000
+#define PB6MD1 0x2000
+#define PB6MD0 0x1000
+#define PB5MD1 0x0800
+#define PB5MD0 0x0400
+#define PB4MD1 0x0200
+#define PB4MD0 0x0100
+#define PB3MD1 0x0080
+#define PB3MD0 0x0040
+#define PB2MD1 0x0020
+#define PB2MD0 0x0010
+#define PB1MD1 0x0008
+#define PB1MD0 0x0004
+#define PB0MD1 0x0002
+#define PB0MD0 0x0001
+
+#define PB7MD PB7MD1|PB7MD0
+#define PB6MD PB6MD1|PB6MD0
+#define PB5MD PB5MD1|PB5MD0
+#define PB4MD PB4MD1|PB4MD0
+#define PB3MD PB3MD1|PB3MD0
+#define PB2MD PB2MD1|PB2MD0
+#define PB1MD PB1MD1|PB1MD0
+#define PB0MD PB0MD1|PB0MD0
+
+
+#ifdef MHZ
+#define BPS 32 * 9600 * MHZ / ( BAUD * 10)
+#else
+#define BPS 32 /* 9600 for 10 Mhz */
+#endif
+
+void handleError (char theSSR);
+
+void
+nop ()
+{
+
+}
+void
+init_serial()
+{
+ int i;
+
+ /* Clear TE and RE in Channel 1's SCR */
+ SCR1 &= ~(SCI_TE | SCI_RE);
+
+ /* Set communication to be async, 8-bit data, no parity, 1 stop bit and use internal clock */
+
+ SMR1 = 0;
+ BRR1 = BPS;
+
+ SCR1 &= ~(SCI_CKE1 | SCI_CKE0);
+
+ /* let the hardware settle */
+
+ for (i = 0; i < 1000; i++)
+ nop ();
+
+ /* Turn on in and out */
+ SCR1 |= SCI_RE | SCI_TE;
+
+ /* Set the PFC to make RXD1 (pin PB8) an input pin and TXD1 (pin PB9) an output pin */
+ PBCR1 &= ~(PB_TXD1 | PB_RXD1);
+ PBCR1 |= PB_TXD1 | PB_RXD1;
+}
+
+
+int
+getDebugCharReady (void)
+{
+ char mySSR;
+ mySSR = SSR1 & ( SCI_PER | SCI_FER | SCI_ORER );
+ if ( mySSR )
+ handleError ( mySSR );
+ return SSR1 & SCI_RDRF ;
+}
+
+char
+getDebugChar (void)
+{
+ char ch;
+ char mySSR;
+
+ while ( ! getDebugCharReady())
+ ;
+
+ ch = RDR1;
+ SSR1 &= ~SCI_RDRF;
+
+ mySSR = SSR1 & (SCI_PER | SCI_FER | SCI_ORER);
+
+ if (mySSR)
+ handleError (mySSR);
+
+ return ch;
+}
+
+int
+putDebugCharReady()
+{
+ return (SSR1 & SCI_TDRE);
+}
+
+void
+putDebugChar (char ch)
+{
+ while (!putDebugCharReady())
+ ;
+
+ /*
+ * Write data into TDR and clear TDRE
+ */
+ TDR1 = ch;
+ SSR1 &= ~SCI_TDRE;
+}
+
+void
+handleError (char theSSR)
+{
+ SSR1 &= ~(SCI_ORER | SCI_PER | SCI_FER);
+}
+
diff --git a/gdb/sh-tdep.c b/gdb/sh-tdep.c
new file mode 100644
index 00000000000..dd94506ab44
--- /dev/null
+++ b/gdb/sh-tdep.c
@@ -0,0 +1,728 @@
+/* Target-dependent code for Hitachi Super-H, for GDB.
+ Copyright 1993, 1994, 1995, 1996, 1997, 1998 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/*
+ Contributed by Steve Chamberlain
+ sac@cygnus.com
+ */
+
+#include "defs.h"
+#include "frame.h"
+#include "obstack.h"
+#include "symtab.h"
+#include "symfile.h"
+#include "gdbtypes.h"
+#include "gdbcmd.h"
+#include "gdbcore.h"
+#include "value.h"
+#include "dis-asm.h"
+#include "inferior.h" /* for BEFORE_TEXT_END etc. */
+#include "gdb_string.h"
+
+/* A set of original names, to be used when restoring back to generic
+ registers from a specific set. */
+
+static char *sh_generic_reg_names[] = {
+ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
+ "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
+ "pc", "pr", "gbr", "vbr", "mach", "macl", "sr",
+ "fpul", "fpscr",
+ "fr0", "fr1", "fr2", "fr3", "fr4", "fr5", "fr6", "fr7",
+ "fr8", "fr9", "fr10", "fr11", "fr12", "fr13", "fr14", "fr15",
+ "ssr", "spc",
+ "r0b0", "r1b0", "r2b0", "r3b0", "r4b0", "r5b0", "r6b0", "r7b0",
+ "r0b1", "r1b1", "r2b1", "r3b1", "r4b1", "r5b1", "r6b1", "r7b1",
+};
+
+static char *sh_reg_names[] = {
+ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
+ "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
+ "pc", "pr", "gbr", "vbr", "mach", "macl", "sr",
+ "", "",
+ "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "",
+ "", "",
+ "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "",
+};
+
+static char *sh3_reg_names[] = {
+ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
+ "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
+ "pc", "pr", "gbr", "vbr", "mach", "macl", "sr",
+ "", "",
+ "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "",
+ "ssr", "spc",
+ "r0b0", "r1b0", "r2b0", "r3b0", "r4b0", "r5b0", "r6b0", "r7b0",
+ "r0b1", "r1b1", "r2b1", "r3b1", "r4b1", "r5b1", "r6b1", "r7b1"
+};
+
+static char *sh3e_reg_names[] = {
+ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
+ "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
+ "pc", "pr", "gbr", "vbr", "mach", "macl", "sr",
+ "fpul", "fpscr",
+ "fr0", "fr1", "fr2", "fr3", "fr4", "fr5", "fr6", "fr7",
+ "fr8", "fr9", "fr10", "fr11", "fr12", "fr13", "fr14", "fr15",
+ "ssr", "spc",
+ "r0b0", "r1b0", "r2b0", "r3b0", "r4b0", "r5b0", "r6b0", "r7b0",
+ "r0b1", "r1b1", "r2b1", "r3b1", "r4b1", "r5b1", "r6b1", "r7b1",
+};
+
+char **sh_register_names = sh_generic_reg_names;
+
+
+struct {
+ char **regnames;
+ int mach;
+} sh_processor_type_table[] = {
+ { sh_reg_names, bfd_mach_sh },
+ { sh3_reg_names, bfd_mach_sh3 },
+ { sh3e_reg_names, bfd_mach_sh3e },
+ { NULL, 0 }
+};
+
+/* Prologue looks like
+ [mov.l <regs>,@-r15]...
+ [sts.l pr,@-r15]
+ [mov.l r14,@-r15]
+ [mov r15,r14]
+*/
+
+#define IS_STS(x) ((x) == 0x4f22)
+#define IS_PUSH(x) (((x) & 0xff0f) == 0x2f06)
+#define GET_PUSHED_REG(x) (((x) >> 4) & 0xf)
+#define IS_MOV_SP_FP(x) ((x) == 0x6ef3)
+#define IS_ADD_SP(x) (((x) & 0xff00) == 0x7f00)
+#define IS_MOV_R3(x) (((x) & 0xff00) == 0x1a00)
+#define IS_SHLL_R3(x) ((x) == 0x4300)
+#define IS_ADD_R3SP(x) ((x) == 0x3f3c)
+#define IS_FMOV(x) (((x) & 0xf00f) == 0xf00b)
+#define FPSCR_SZ (1 << 20)
+
+
+/* Should call_function allocate stack space for a struct return? */
+int
+sh_use_struct_convention (gcc_p, type)
+ int gcc_p;
+ struct type *type;
+{
+ return (TYPE_LENGTH (type) > 1);
+}
+
+
+/* Skip any prologue before the guts of a function */
+
+CORE_ADDR
+sh_skip_prologue (start_pc)
+ CORE_ADDR start_pc;
+{
+ int w;
+
+ w = read_memory_integer (start_pc, 2);
+ while (IS_STS (w)
+ || IS_FMOV (w)
+ || IS_PUSH (w)
+ || IS_MOV_SP_FP (w)
+ || IS_MOV_R3 (w)
+ || IS_ADD_R3SP (w)
+ || IS_ADD_SP (w)
+ || IS_SHLL_R3 (w))
+ {
+ start_pc += 2;
+ w = read_memory_integer (start_pc, 2);
+ }
+
+ return start_pc;
+}
+
+/* Disassemble an instruction. */
+
+int
+gdb_print_insn_sh (memaddr, info)
+ bfd_vma memaddr;
+ disassemble_info *info;
+{
+ if (TARGET_BYTE_ORDER == BIG_ENDIAN)
+ return print_insn_sh (memaddr, info);
+ else
+ return print_insn_shl (memaddr, info);
+}
+
+/* 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
+ INIT_EXTRA_FRAME_INFO and INIT_FRAME_PC will be called for the new frame.
+
+ For us, the frame address is its stack pointer value, so we look up
+ the function prologue to determine the caller's sp value, and return it. */
+
+CORE_ADDR
+sh_frame_chain (frame)
+ struct frame_info *frame;
+{
+ if (PC_IN_CALL_DUMMY (frame->pc, frame->frame, frame->frame))
+ return frame->frame; /* dummy frame same as caller's frame */
+ if (!inside_entry_file (frame->pc))
+ return read_memory_integer (FRAME_FP (frame) + frame->f_offset, 4);
+ else
+ return 0;
+}
+
+/* Find REGNUM on the stack. Otherwise, it's in an active register. One thing
+ we might want to do here is to check REGNUM against the clobber mask, and
+ somehow flag it as invalid if it isn't saved on the stack somewhere. This
+ would provide a graceful failure mode when trying to get the value of
+ caller-saves registers for an inner frame. */
+
+CORE_ADDR
+sh_find_callers_reg (fi, regnum)
+ struct frame_info *fi;
+ int regnum;
+{
+ struct frame_saved_regs fsr;
+
+ for (; fi; fi = fi->next)
+ if (PC_IN_CALL_DUMMY (fi->pc, fi->frame, fi->frame))
+ /* When the caller requests PR from the dummy frame, we return PC because
+ that's where the previous routine appears to have done a call from. */
+ return generic_read_register_dummy (fi->pc, fi->frame, regnum);
+ else
+ {
+ FRAME_FIND_SAVED_REGS(fi, fsr);
+ if (fsr.regs[regnum] != 0)
+ return read_memory_integer (fsr.regs[regnum],
+ REGISTER_RAW_SIZE(regnum));
+ }
+ return read_register (regnum);
+}
+
+/* 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. */
+
+void
+sh_frame_find_saved_regs (fi, fsr)
+ struct frame_info *fi;
+ struct frame_saved_regs *fsr;
+{
+ int where[NUM_REGS];
+ int rn;
+ int have_fp = 0;
+ int depth;
+ int pc;
+ int opc;
+ int insn;
+ int r3_val = 0;
+ char * dummy_regs = generic_find_dummy_frame (fi->pc, fi->frame);
+
+ if (dummy_regs)
+ {
+ /* DANGER! This is ONLY going to work if the char buffer format of
+ the saved registers is byte-for-byte identical to the
+ CORE_ADDR regs[NUM_REGS] format used by struct frame_saved_regs! */
+ memcpy (&fsr->regs, dummy_regs, sizeof(fsr));
+ return;
+ }
+
+ opc = pc = get_pc_function_start (fi->pc);
+
+ insn = read_memory_integer (pc, 2);
+
+ fi->leaf_function = 1;
+ fi->f_offset = 0;
+
+ for (rn = 0; rn < NUM_REGS; rn++)
+ where[rn] = -1;
+
+ depth = 0;
+
+ /* Loop around examining the prologue insns until we find something
+ that does not appear to be part of the prologue. But give up
+ after 20 of them, since we're getting silly then. */
+
+ while (pc < opc + 20 * 2)
+ {
+ /* See where the registers will be saved to */
+ if (IS_PUSH (insn))
+ {
+ pc += 2;
+ rn = GET_PUSHED_REG (insn);
+ where[rn] = depth;
+ insn = read_memory_integer (pc, 2);
+ depth += 4;
+ }
+ else if (IS_STS (insn))
+ {
+ pc += 2;
+ where[PR_REGNUM] = depth;
+ insn = read_memory_integer (pc, 2);
+ /* If we're storing the pr then this isn't a leaf */
+ fi->leaf_function = 0;
+ depth += 4;
+ }
+ else if (IS_MOV_R3 (insn))
+ {
+ r3_val = ((insn & 0xff) ^ 0x80) - 0x80;
+ pc += 2;
+ insn = read_memory_integer (pc, 2);
+ }
+ else if (IS_SHLL_R3 (insn))
+ {
+ r3_val <<= 1;
+ pc += 2;
+ insn = read_memory_integer (pc, 2);
+ }
+ else if (IS_ADD_R3SP (insn))
+ {
+ depth += -r3_val;
+ pc += 2;
+ insn = read_memory_integer (pc, 2);
+ }
+ else if (IS_ADD_SP (insn))
+ {
+ pc += 2;
+ depth -= ((insn & 0xff) ^ 0x80) - 0x80;
+ insn = read_memory_integer (pc, 2);
+ }
+ else if (IS_FMOV (insn))
+ {
+ pc += 2;
+ insn = read_memory_integer (pc, 2);
+ if (read_register (FPSCR_REGNUM) & FPSCR_SZ)
+ {
+ depth += 8;
+ }
+ else
+ {
+ depth += 4;
+ }
+ }
+ else
+ break;
+ }
+
+ /* Now we know how deep things are, we can work out their addresses */
+
+ for (rn = 0; rn < NUM_REGS; rn++)
+ {
+ if (where[rn] >= 0)
+ {
+ if (rn == FP_REGNUM)
+ have_fp = 1;
+
+ fsr->regs[rn] = fi->frame - where[rn] + depth - 4;
+ }
+ else
+ {
+ fsr->regs[rn] = 0;
+ }
+ }
+
+ if (have_fp)
+ {
+ fsr->regs[SP_REGNUM] = read_memory_integer (fsr->regs[FP_REGNUM], 4);
+ }
+ else
+ {
+ fsr->regs[SP_REGNUM] = fi->frame - 4;
+ }
+
+ fi->f_offset = depth - where[FP_REGNUM] - 4;
+ /* Work out the return pc - either from the saved pr or the pr
+ value */
+}
+
+/* initialize the extra info saved in a FRAME */
+
+void
+sh_init_extra_frame_info (fromleaf, fi)
+ int fromleaf;
+ struct frame_info *fi;
+{
+ struct frame_saved_regs fsr;
+
+ if (fi->next)
+ fi->pc = FRAME_SAVED_PC (fi->next);
+
+ if (PC_IN_CALL_DUMMY (fi->pc, fi->frame, fi->frame))
+ {
+ /* We need to setup fi->frame here because run_stack_dummy gets it wrong
+ by assuming it's always FP. */
+ fi->frame = generic_read_register_dummy (fi->pc, fi->frame,
+ SP_REGNUM);
+ fi->return_pc = generic_read_register_dummy (fi->pc, fi->frame,
+ PC_REGNUM);
+ fi->f_offset = -(CALL_DUMMY_LENGTH + 4);
+ fi->leaf_function = 0;
+ return;
+ }
+ else
+ {
+ FRAME_FIND_SAVED_REGS (fi, fsr);
+ fi->return_pc = sh_find_callers_reg (fi, PR_REGNUM);
+ }
+}
+
+/* Discard from the stack the innermost frame,
+ restoring all saved registers. */
+
+void
+sh_pop_frame ()
+{
+ register struct frame_info *frame = get_current_frame ();
+ register CORE_ADDR fp;
+ register int regnum;
+ struct frame_saved_regs fsr;
+
+ if (PC_IN_CALL_DUMMY (frame->pc, frame->frame, frame->frame))
+ generic_pop_dummy_frame ();
+ else
+ {
+ fp = FRAME_FP (frame);
+ get_frame_saved_regs (frame, &fsr);
+
+ /* Copy regs from where they were saved in the frame */
+ for (regnum = 0; regnum < NUM_REGS; regnum++)
+ if (fsr.regs[regnum])
+ write_register (regnum, read_memory_integer (fsr.regs[regnum], 4));
+
+ write_register (PC_REGNUM, frame->return_pc);
+ write_register (SP_REGNUM, fp + 4);
+ }
+ flush_cached_frames ();
+}
+
+/* Function: push_arguments
+ Setup the function arguments for calling a function in the inferior.
+
+ On the Hitachi SH architecture, there are four registers (R4 to R7)
+ which are dedicated for passing function arguments. Up to the first
+ four arguments (depending on size) may go into these registers.
+ The rest go on the stack.
+
+ Arguments that are smaller than 4 bytes will still take up a whole
+ register or a whole 32-bit word on the stack, and will be
+ right-justified in the register or the stack word. This includes
+ chars, shorts, and small aggregate types.
+
+ Arguments that are larger than 4 bytes may be split between two or
+ more registers. If there are not enough registers free, an argument
+ may be passed partly in a register (or registers), and partly on the
+ stack. This includes doubles, long longs, and larger aggregates.
+ As far as I know, there is no upper limit to the size of aggregates
+ that will be passed in this way; in other words, the convention of
+ passing a pointer to a large aggregate instead of a copy is not used.
+
+ An exceptional case exists for struct arguments (and possibly other
+ aggregates such as arrays) if the size is larger than 4 bytes but
+ not a multiple of 4 bytes. In this case the argument is never split
+ between the registers and the stack, but instead is copied in its
+ entirety onto the stack, AND also copied into as many registers as
+ there is room for. In other words, space in registers permitting,
+ two copies of the same argument are passed in. As far as I can tell,
+ only the one on the stack is used, although that may be a function
+ of the level of compiler optimization. I suspect this is a compiler
+ bug. Arguments of these odd sizes are left-justified within the
+ word (as opposed to arguments smaller than 4 bytes, which are
+ right-justified).
+
+
+ If the function is to return an aggregate type such as a struct, it
+ is either returned in the normal return value register R0 (if its
+ size is no greater than one byte), or else the caller must allocate
+ space into which the callee will copy the return value (if the size
+ is greater than one byte). In this case, a pointer to the return
+ value location is passed into the callee in register R2, which does
+ not displace any of the other arguments passed in via registers R4
+ to R7. */
+
+CORE_ADDR
+sh_push_arguments (nargs, args, sp, struct_return, struct_addr)
+ int nargs;
+ value_ptr *args;
+ CORE_ADDR sp;
+ unsigned char struct_return;
+ CORE_ADDR struct_addr;
+{
+ int stack_offset, stack_alloc;
+ int argreg;
+ int argnum;
+ struct type *type;
+ CORE_ADDR regval;
+ char *val;
+ char valbuf[4];
+ int len;
+ int odd_sized_struct;
+
+ /* first force sp to a 4-byte alignment */
+ sp = sp & ~3;
+
+ /* The "struct return pointer" pseudo-argument has its own dedicated
+ register */
+ if (struct_return)
+ write_register (STRUCT_RETURN_REGNUM, struct_addr);
+
+ /* Now make sure there's space on the stack */
+ for (argnum = 0, stack_alloc = 0;
+ argnum < nargs; argnum++)
+ stack_alloc += ((TYPE_LENGTH(VALUE_TYPE(args[argnum])) + 3) & ~3);
+ sp -= stack_alloc; /* make room on stack for args */
+
+
+ /* Now load as many as possible of the first arguments into
+ registers, and push the rest onto the stack. There are 16 bytes
+ in four registers available. Loop thru args from first to last. */
+
+ argreg = ARG0_REGNUM;
+ for (argnum = 0, stack_offset = 0; argnum < nargs; argnum++)
+ {
+ type = VALUE_TYPE (args[argnum]);
+ len = TYPE_LENGTH (type);
+ memset(valbuf, 0, sizeof(valbuf));
+ if (len < 4)
+ { /* value gets right-justified in the register or stack word */
+ memcpy(valbuf + (4 - len),
+ (char *) VALUE_CONTENTS (args[argnum]), len);
+ val = valbuf;
+ }
+ else
+ val = (char *) VALUE_CONTENTS (args[argnum]);
+
+ if (len > 4 && (len & 3) != 0)
+ odd_sized_struct = 1; /* such structs go entirely on stack */
+ else
+ odd_sized_struct = 0;
+ while (len > 0)
+ {
+ if (argreg > ARGLAST_REGNUM || odd_sized_struct)
+ { /* must go on the stack */
+ write_memory (sp + stack_offset, val, 4);
+ stack_offset += 4;
+ }
+ /* NOTE WELL!!!!! This is not an "else if" clause!!!
+ That's because some *&^%$ things get passed on the stack
+ AND in the registers! */
+ if (argreg <= ARGLAST_REGNUM)
+ { /* there's room in a register */
+ regval = extract_address (val, REGISTER_RAW_SIZE(argreg));
+ write_register (argreg++, regval);
+ }
+ /* Store the value 4 bytes at a time. This means that things
+ larger than 4 bytes may go partly in registers and partly
+ on the stack. */
+ len -= REGISTER_RAW_SIZE(argreg);
+ val += REGISTER_RAW_SIZE(argreg);
+ }
+ }
+ return sp;
+}
+
+/* Function: push_return_address (pc)
+ Set up the return address for the inferior function call.
+ Needed for targets where we don't actually execute a JSR/BSR instruction */
+
+CORE_ADDR
+sh_push_return_address (pc, sp)
+ CORE_ADDR pc;
+ CORE_ADDR sp;
+{
+ write_register (PR_REGNUM, CALL_DUMMY_ADDRESS ());
+ return sp;
+}
+
+/* Function: fix_call_dummy
+ Poke the callee function's address into the destination part of
+ the CALL_DUMMY. The address is actually stored in a data word
+ following the actualy CALL_DUMMY instructions, which will load
+ it into a register using PC-relative addressing. This function
+ expects the CALL_DUMMY to look like this:
+
+ mov.w @(2,PC), R8
+ jsr @R8
+ nop
+ trap
+ <destination>
+ */
+
+#if 0
+void
+sh_fix_call_dummy (dummy, pc, fun, nargs, args, type, gcc_p)
+ char *dummy;
+ CORE_ADDR pc;
+ CORE_ADDR fun;
+ int nargs;
+ value_ptr *args;
+ struct type *type;
+ int gcc_p;
+{
+ *(unsigned long *) (dummy + 8) = fun;
+}
+#endif
+
+/* Function: get_saved_register
+ Just call the generic_get_saved_register function. */
+
+void
+get_saved_register (raw_buffer, optimized, addrp, frame, regnum, lval)
+ char *raw_buffer;
+ int *optimized;
+ CORE_ADDR *addrp;
+ struct frame_info *frame;
+ int regnum;
+ enum lval_type *lval;
+{
+ generic_get_saved_register (raw_buffer, optimized, addrp,
+ frame, regnum, lval);
+}
+
+
+/* Modify the actual processor type. */
+
+int
+sh_target_architecture_hook (ap)
+ const bfd_arch_info_type *ap;
+{
+ int i, j;
+
+ if (ap->arch != bfd_arch_sh)
+ return 0;
+
+ for (i = 0; sh_processor_type_table[i].regnames != NULL; i++)
+ {
+ if (sh_processor_type_table[i].mach == ap->mach)
+ {
+ sh_register_names = sh_processor_type_table[i].regnames;
+ return 1;
+ }
+ }
+
+ fatal ("Architecture `%s' unreconized", ap->printable_name);
+}
+
+/* Print the registers in a form similar to the E7000 */
+
+static void
+sh_show_regs (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ int cpu;
+ if (TARGET_ARCHITECTURE->arch == bfd_arch_sh)
+ cpu = TARGET_ARCHITECTURE->mach;
+ else
+ cpu = 0;
+
+ printf_filtered ("PC=%08x SR=%08x PR=%08x MACH=%08x MACHL=%08x\n",
+ read_register (PC_REGNUM),
+ read_register (SR_REGNUM),
+ read_register (PR_REGNUM),
+ read_register (MACH_REGNUM),
+ read_register (MACL_REGNUM));
+
+ printf_filtered ("GBR=%08x VBR=%08x",
+ read_register (GBR_REGNUM),
+ read_register (VBR_REGNUM));
+ if (cpu == bfd_mach_sh3 || cpu == bfd_mach_sh3e)
+ {
+ printf_filtered (" SSR=%08x SPC=%08x",
+ read_register (SSR_REGNUM),
+ read_register (SPC_REGNUM));
+ if (cpu == bfd_mach_sh3e)
+ {
+ printf_filtered (" FPUL=%08x FPSCR=%08x",
+ read_register (FPUL_REGNUM),
+ read_register (FPSCR_REGNUM));
+ }
+ }
+
+ printf_filtered ("\nR0-R7 %08x %08x %08x %08x %08x %08x %08x %08x\n",
+ read_register (0),
+ read_register (1),
+ read_register (2),
+ read_register (3),
+ read_register (4),
+ read_register (5),
+ read_register (6),
+ read_register (7));
+ printf_filtered ("R8-R15 %08x %08x %08x %08x %08x %08x %08x %08x\n",
+ read_register (8),
+ read_register (9),
+ read_register (10),
+ read_register (11),
+ read_register (12),
+ read_register (13),
+ read_register (14),
+ read_register (15));
+ if (cpu == bfd_mach_sh3e)
+ {
+ printf_filtered ("FP0-FP7 %08x %08x %08x %08x %08x %08x %08x %08x\n",
+ read_register (FP0_REGNUM + 0),
+ read_register (FP0_REGNUM + 1),
+ read_register (FP0_REGNUM + 2),
+ read_register (FP0_REGNUM + 3),
+ read_register (FP0_REGNUM + 4),
+ read_register (FP0_REGNUM + 5),
+ read_register (FP0_REGNUM + 6),
+ read_register (FP0_REGNUM + 7));
+ printf_filtered ("FP8-FP15 %08x %08x %08x %08x %08x %08x %08x %08x\n",
+ read_register (FP0_REGNUM + 8),
+ read_register (FP0_REGNUM + 9),
+ read_register (FP0_REGNUM + 10),
+ read_register (FP0_REGNUM + 11),
+ read_register (FP0_REGNUM + 12),
+ read_register (FP0_REGNUM + 13),
+ read_register (FP0_REGNUM + 14),
+ read_register (FP0_REGNUM + 15));
+ }
+}
+
+/* Function: extract_return_value
+ Find a function's return value in the appropriate registers (in regbuf),
+ and copy it into valbuf. */
+
+void
+sh_extract_return_value (type, regbuf, valbuf)
+ struct type *type;
+ void *regbuf;
+ void *valbuf;
+{
+ int len = TYPE_LENGTH(type);
+
+ if (len <= 4)
+ memcpy (valbuf, ((char *) regbuf) + 4 - len, len);
+ else if (len <= 8)
+ memcpy (valbuf, ((char *) regbuf) + 8 - len, len);
+ else
+ error ("bad size for return value");
+}
+
+void
+_initialize_sh_tdep ()
+{
+ struct cmd_list_element *c;
+
+ tm_print_insn = gdb_print_insn_sh;
+
+ target_architecture_hook = sh_target_architecture_hook;
+
+ add_com ("regs", class_vars, sh_show_regs, "Print all registers");
+}
diff --git a/gdb/sh3-rom.c b/gdb/sh3-rom.c
new file mode 100644
index 00000000000..ab4aa692427
--- /dev/null
+++ b/gdb/sh3-rom.c
@@ -0,0 +1,392 @@
+/* Remote target glue for the Hitachi SH-3 ROM monitor.
+ Copyright 1995, 1996 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "gdbcore.h"
+#include "target.h"
+#include "monitor.h"
+#include "serial.h"
+#include "srec.h"
+
+static serial_t parallel;
+static int parallel_in_use;
+
+static void sh3_open PARAMS ((char *args, int from_tty));
+
+static void
+sh3_supply_register (regname, regnamelen, val, vallen)
+ char *regname;
+ int regnamelen;
+ char *val;
+ int vallen;
+{
+ int numregs;
+ int regno;
+
+ numregs = 1;
+ regno = -1;
+
+ if (regnamelen == 2)
+ {
+ switch (regname[0])
+ {
+ case 'S':
+ if (regname[1] == 'R')
+ regno = SR_REGNUM;
+ break;
+ case 'P':
+ if (regname[1] == 'C')
+ regno = PC_REGNUM;
+ else if (regname[1] == 'R')
+ regno = PR_REGNUM;
+ break;
+ }
+ }
+ else if (regnamelen == 3)
+ {
+ switch (regname[0])
+ {
+ case 'G':
+ case 'V':
+ if (regname[1] == 'B' && regname[2] == 'R')
+ if (regname[0] == 'G')
+ regno = VBR_REGNUM;
+ else
+ regno = GBR_REGNUM;
+ break;
+ case 'S':
+ if (regname[1] == 'S' && regname[2] == 'R')
+ regno = SSR_REGNUM;
+ else if (regname[1] == 'P' && regname[2] == 'C')
+ regno = SPC_REGNUM;
+ break;
+ }
+ }
+ else if (regnamelen == 4)
+ {
+ switch (regname[0])
+ {
+ case 'M':
+ if (regname[1] == 'A' && regname[2] == 'C')
+ if (regname[3] == 'H')
+ regno = MACH_REGNUM;
+ else if (regname[3] == 'L')
+ regno = MACL_REGNUM;
+ break;
+ case 'R':
+ if (regname[1] == '0' && regname[2] == '-' && regname[3] == '7')
+ {
+ regno = R0_REGNUM;
+ numregs = 8;
+ }
+ }
+ }
+ else if (regnamelen == 5)
+ {
+ if (regname[1] == '8' && regname[2] == '-' && regname[3] == '1'
+ && regname[4] =='5')
+ {
+ regno = R0_REGNUM + 8;
+ numregs = 8;
+ }
+ }
+ else if (regnamelen == 17)
+ {
+ }
+
+ if (regno >= 0)
+ while (numregs-- > 0)
+ val = monitor_supply_register (regno++, val);
+}
+
+static void
+sh3_load (desc, file, hashmark)
+ serial_t desc;
+ char *file;
+ int hashmark;
+{
+ if (parallel_in_use)
+ {
+ monitor_printf("pl;s\r");
+ load_srec (parallel, file, 0, 80, SREC_ALL, hashmark, NULL);
+ monitor_expect_prompt (NULL, 0);
+ }
+ else
+ {
+ monitor_printf ("il;s:x\r");
+ monitor_expect ("\005", NULL, 0); /* Look for ENQ */
+ SERIAL_WRITE (desc, "\006", 1); /* Send ACK */
+ monitor_expect ("LO x\r", NULL, 0); /* Look for filename */
+
+ load_srec (desc, file, 0, 80, SREC_ALL, hashmark, NULL);
+
+ monitor_expect ("\005", NULL, 0); /* Look for ENQ */
+ SERIAL_WRITE (desc, "\006", 1); /* Send ACK */
+ monitor_expect_prompt (NULL, 0);
+ }
+}
+
+/* This array of registers need to match the indexes used by GDB.
+ This exists because the various ROM monitors use different strings
+ than does GDB, and don't necessarily support all the registers
+ either. So, typing "info reg sp" becomes a "r30". */
+
+static char *sh3_regnames[NUM_REGS] = {
+ "R0", "R1", "R2", "R3", "R4", "R5", "R6", "R7",
+ "R8", "R9", "R10", "R11","R12", "R13", "R14", "R15",
+ "PC", "PR", "GBR", "VBR","MACH","MACL", "SR",
+ NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ "SSR", "SPC",
+ "R0_BANK0", "R1_BANK0", "R2_BANK0", "R3_BANK0",
+ "R4_BANK0", "R5_BANK0", "R6_BANK0", "R7_BANK0",
+ "R0_BANK1", "R1_BANK1", "R2_BANK1", "R3_BANK1",
+ "R4_BANK1", "R5_BANK1", "R6_BANK1", "R7_BANK1"
+};
+
+static char *sh3e_regnames[NUM_REGS] = {
+ "R0", "R1", "R2", "R3", "R4", "R5", "R6", "R7",
+ "R8", "R9", "R10", "R11","R12", "R13", "R14", "R15",
+ "PC", "PR", "GBR", "VBR","MACH","MACL", "SR",
+ "FPUL", "FPSCR",
+ "FR0", "FR1", "FR2", "FR3", "FR4", "FR5", "FR6", "FR7",
+ "FR8", "FR9", "FR10", "FR11", "FR12", "FR13", "FR14", "FR15",
+ "SSR","SPC",
+ "R0_BANK0", "R1_BANK0", "R2_BANK0", "R3_BANK0",
+ "R4_BANK0", "R5_BANK0", "R6_BANK0", "R7_BANK0",
+ "R0_BANK1", "R1_BANK1", "R2_BANK1", "R3_BANK1",
+ "R4_BANK1", "R5_BANK1", "R6_BANK1", "R7_BANK1"
+};
+
+/* Define the monitor command strings. Since these are passed directly
+ through to a printf style function, we may include formatting
+ strings. We also need a CR or LF on the end. */
+
+static struct target_ops sh3_ops, sh3e_ops;
+
+static char *sh3_inits[] = {"\003", NULL}; /* Exits sub-command mode & download cmds */
+
+static struct monitor_ops sh3_cmds ;
+
+static void
+init_sh3_cmds(void)
+{
+ sh3_cmds.flags = MO_CLR_BREAK_USES_ADDR | MO_GETMEM_READ_SINGLE ; /* flags */
+ sh3_cmds.init = sh3_inits; /* monitor init string */
+ sh3_cmds.cont = "g\r"; /* continue command */
+ sh3_cmds.step = "s\r"; /* single step */
+ sh3_cmds.stop = "\003"; /* Interrupt program */
+ sh3_cmds.set_break = "b %x\r"; /* set a breakpoint */
+ sh3_cmds.clr_break = "b -%x\r"; /* clear a breakpoint */
+ sh3_cmds.clr_all_break = "b -\r"; /* clear all breakpoints */
+ sh3_cmds.fill = "f %x @%x %x\r"; /* fill (start len val) */
+ sh3_cmds.setmem.cmdb = "m %x %x\r"; /* setmem.cmdb (addr, value) */
+ sh3_cmds.setmem.cmdw = "m %x %x;w\r"; /* setmem.cmdw (addr, value) */
+ sh3_cmds.setmem.cmdl = "m %x %x;l\r"; /* setmem.cmdl (addr, value) */
+ sh3_cmds.setmem.cmdll = NULL; /* setmem.cmdll (addr, value) */
+ sh3_cmds.setmem.resp_delim = NULL; /* setreg.resp_delim */
+ sh3_cmds.setmem.term = NULL; /* setreg.term */
+ sh3_cmds.setmem.term_cmd = NULL; /* setreg.term_cmd */
+ sh3_cmds.getmem.cmdb = "m %x\r"; /* getmem.cmdb (addr, len) */
+ sh3_cmds.getmem.cmdw = "m %x;w\r"; /* getmem.cmdw (addr, len) */
+ sh3_cmds.getmem.cmdl = "m %x;l\r"; /* getmem.cmdl (addr, len) */
+ sh3_cmds.getmem.cmdll = NULL; /* getmem.cmdll (addr, len) */
+ sh3_cmds.getmem.resp_delim = "^ [0-9A-F]+ "; /* getmem.resp_delim */
+ sh3_cmds.getmem.term = "? "; /* getmem.term */
+ sh3_cmds.getmem.term_cmd = ".\r"; /* getmem.term_cmd */
+ sh3_cmds.setreg.cmd = ".%s %x\r"; /* setreg.cmd (name, value) */
+ sh3_cmds.setreg.resp_delim = NULL; /* setreg.resp_delim */
+ sh3_cmds.setreg.term = NULL; /* setreg.term */
+ sh3_cmds.setreg.term_cmd = NULL; /* setreg.term_cmd */
+ sh3_cmds.getreg.cmd = ".%s\r"; /* getreg.cmd (name) */
+ sh3_cmds.getreg.resp_delim = "="; /* getreg.resp_delim */
+ sh3_cmds.getreg.term = "? "; /* getreg.term */
+ sh3_cmds.getreg.term_cmd = ".\r" ; /* getreg.term_cmd */
+ sh3_cmds.dump_registers = "r\r"; /* dump_registers */
+ sh3_cmds.register_pattern = "\\(\\w+\\)=\\([0-9a-fA-F]+\\( +[0-9a-fA-F]+\\b\\)*\\)";
+ sh3_cmds.supply_register = sh3_supply_register ; /* supply_register */
+ sh3_cmds.load_routine = sh3_load; /* load_routine */
+ sh3_cmds.load = NULL; /* download command */
+ sh3_cmds.loadresp = NULL; /* Load response */
+ sh3_cmds.prompt = "\n:"; /* monitor command prompt */
+ sh3_cmds.line_term = "\r"; /* end-of-line terminator */
+ sh3_cmds.cmd_end = ".\r"; /* optional command terminator */
+ sh3_cmds.target = &sh3_ops; /* target operations */
+ sh3_cmds.stopbits = SERIAL_1_STOPBITS; /* number of stop bits */
+ sh3_cmds.regnames = sh3_regnames; /* registers names */
+ sh3_cmds.magic = MONITOR_OPS_MAGIC ; /* magic */
+} /* init_sh3_cmds */
+
+/* This monitor structure is identical except for a couple slots, so
+ we will fill it in from the base structure when needed. */
+
+static struct monitor_ops sh3e_cmds;
+
+static void
+sh3_open (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ char *serial_port_name = args;
+ char *parallel_port_name = 0;
+
+ if (args)
+ {
+ char *cursor = serial_port_name = strsave (args);
+
+ while (*cursor && *cursor != ' ')
+ cursor++;
+
+ if (*cursor)
+ *cursor++ = 0;
+
+ while (*cursor == ' ')
+ cursor++;
+
+ if (*cursor)
+ parallel_port_name = cursor;
+ }
+
+ monitor_open (serial_port_name, &sh3_cmds, from_tty);
+
+ if (parallel_port_name)
+ {
+ parallel = SERIAL_OPEN (parallel_port_name);
+
+ if (!parallel)
+ perror_with_name ("Unable to open parallel port.");
+
+ parallel_in_use = 1;
+ }
+
+ /* If we connected successfully, we know the processor is an SH3. */
+ set_architecture_from_arch_mach (bfd_arch_sh, bfd_mach_sh3);
+}
+
+
+static void
+sh3e_open (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ char *serial_port_name = args;
+ char *parallel_port_name = 0;
+
+ if (args)
+ {
+ char *cursor = serial_port_name = strsave (args);
+
+ while (*cursor && *cursor != ' ')
+ cursor++;
+
+ if (*cursor)
+ *cursor++ = 0;
+
+ while (*cursor == ' ')
+ cursor++;
+
+ if (*cursor)
+ parallel_port_name = cursor;
+ }
+
+ /* Set up the SH-3E monitor commands structure. */
+
+ memcpy (&sh3e_cmds, &sh3_cmds, sizeof (struct monitor_ops));
+
+ sh3e_cmds.target = &sh3e_ops;
+ sh3e_cmds.regnames = sh3e_regnames;
+
+ monitor_open (serial_port_name, &sh3e_cmds, from_tty);
+
+ if (parallel_port_name)
+ {
+ parallel = SERIAL_OPEN (parallel_port_name);
+
+ if (!parallel)
+ perror_with_name ("Unable to open parallel port.");
+
+ parallel_in_use = 1;
+ }
+
+ /* If we connected successfully, we know the processor is an SH3E. */
+ set_architecture_from_arch_mach (bfd_arch_sh, bfd_mach_sh3);
+}
+
+static void
+sh3_close (quitting)
+ int quitting;
+{
+ monitor_close (quitting);
+ if (parallel_in_use) {
+ SERIAL_CLOSE (parallel);
+ parallel_in_use = 0;
+ }
+}
+
+void
+_initialize_sh3_rom ()
+{
+ init_sh3_cmds() ;
+ init_monitor_ops (&sh3_ops);
+
+ sh3_ops.to_shortname = "sh3";
+ sh3_ops.to_longname = "Hitachi SH-3 rom monitor";
+
+ sh3_ops.to_doc =
+#ifdef _WINDOWS
+ /* On windows we can talk through the parallel port too. */
+ "Debug on a Hitachi eval board running the SH-3 rom monitor.\n"
+ "Specify the serial device it is connected to (e.g. com2).\n"
+ "If you want to use the parallel port to download to it, specify that\n"
+ "as the second argument. (e.g. lpt1)";
+#else
+ "Debug on a Hitachi eval board running the SH-3 rom monitor.\n\
+Specify the serial device it is connected to (e.g. /dev/ttya).";
+#endif
+
+ sh3_ops.to_open = sh3_open;
+ sh3_ops.to_close = sh3_close;
+
+ add_target (&sh3_ops);
+
+ /* Setup the SH3e, which has float registers. */
+
+ init_monitor_ops (&sh3e_ops);
+
+ sh3e_ops.to_shortname = "sh3e";
+ sh3e_ops.to_longname = "Hitachi SH-3E rom monitor";
+
+ sh3e_ops.to_doc =
+#ifdef _WINDOWS
+ /* On windows we can talk through the parallel port too. */
+ "Debug on a Hitachi eval board running the SH-3E rom monitor.\n"
+ "Specify the serial device it is connected to (e.g. com2).\n"
+ "If you want to use the parallel port to download to it, specify that\n"
+ "as the second argument. (e.g. lpt1)";
+#else
+ "Debug on a Hitachi eval board running the SH-3E rom monitor.\n\
+Specify the serial device it is connected to (e.g. /dev/ttya).";
+#endif
+
+ sh3e_ops.to_open = sh3e_open;
+ sh3e_ops.to_close = sh3_close;
+
+ add_target (&sh3e_ops);
+}
diff --git a/gdb/signals.h b/gdb/signals.h
new file mode 100644
index 00000000000..a1348b63733
--- /dev/null
+++ b/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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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/gdb/sol-thread.c b/gdb/sol-thread.c
new file mode 100644
index 00000000000..3fe6268bf31
--- /dev/null
+++ b/gdb/sol-thread.c
@@ -0,0 +1,1673 @@
+/* Low level interface for debugging Solaris threads for GDB, the GNU debugger.
+ Copyright 1996, 1997, 1998 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* This module implements a sort of half target that sits between the
+ machine-independent parts of GDB and the /proc interface (procfs.c) to
+ provide access to the Solaris user-mode thread implementation.
+
+ Solaris threads are true user-mode threads, which are invoked via the thr_*
+ and pthread_* (native and Posix respectivly) interfaces. These are mostly
+ implemented in user-space, with all thread context kept in various
+ structures that live in the user's heap. These should not be confused with
+ lightweight processes (LWPs), which are implemented by the kernel, and
+ scheduled without explicit intervention by the process.
+
+ Just to confuse things a little, Solaris threads (both native and Posix) are
+ actually implemented using LWPs. In general, there are going to be more
+ threads than LWPs. There is no fixed correspondence between a thread and an
+ LWP. When a thread wants to run, it gets scheduled onto the first available
+ LWP and can therefore migrate from one LWP to another as time goes on. A
+ sleeping thread may not be associated with an LWP at all!
+
+ To make it possible to mess with threads, Sun provides a library called
+ libthread_db.so.1 (not to be confused with libthread_db.so.0, which doesn't
+ have a published interface). This interface has an upper part, which it
+ provides, and a lower part which I provide. The upper part consists of the
+ td_* routines, which allow me to find all the threads, query their state,
+ etc... The lower part consists of all of the ps_*, which are used by the
+ td_* routines to read/write memory, manipulate LWPs, lookup symbols, etc...
+ The ps_* routines actually do most of their work by calling functions in
+ procfs.c. */
+
+#include "defs.h"
+#include <thread.h>
+#include <proc_service.h>
+#include <thread_db.h>
+#include "gdbthread.h"
+#include "target.h"
+#include "inferior.h"
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <dlfcn.h>
+#include "gdbcmd.h"
+
+extern struct target_ops sol_thread_ops; /* Forward declaration */
+extern struct target_ops sol_core_ops; /* Forward declaration */
+
+/* place to store core_ops before we overwrite it */
+static struct target_ops orig_core_ops;
+
+struct target_ops sol_thread_ops;
+struct target_ops sol_core_ops;
+
+extern int procfs_suppress_run;
+extern struct target_ops procfs_ops; /* target vector for procfs.c */
+extern struct target_ops core_ops; /* target vector for corelow.c */
+extern char *procfs_pid_to_str PARAMS ((int pid));
+
+/* Note that these prototypes differ slightly from those used in procfs.c
+ for of two reasons. One, we can't use gregset_t, as that's got a whole
+ different meaning under Solaris (also, see above). Two, we can't use the
+ pointer form here as these are actually arrays of ints (for Sparc's at
+ least), and are automatically coerced into pointers to ints when used as
+ parameters. That makes it impossible to avoid a compiler warning when
+ passing pr{g fp}regset_t's from a parameter to an argument of one of
+ these functions. */
+
+extern void supply_gregset PARAMS ((const prgregset_t));
+extern void fill_gregset PARAMS ((prgregset_t, int));
+extern void supply_fpregset PARAMS ((const prfpregset_t *));
+extern void fill_fpregset PARAMS ((prfpregset_t *, int));
+
+/* This struct is defined by us, but mainly used for the proc_service interface.
+ We don't have much use for it, except as a handy place to get a real pid
+ for memory accesses. */
+
+struct ps_prochandle
+{
+ pid_t pid;
+};
+
+struct string_map
+{
+ int num;
+ char *str;
+};
+
+static struct ps_prochandle main_ph;
+static td_thragent_t *main_ta;
+static int sol_thread_active = 0;
+
+static struct cleanup * save_inferior_pid PARAMS ((void));
+static void restore_inferior_pid PARAMS ((int pid));
+static char *td_err_string PARAMS ((td_err_e errcode));
+static char *td_state_string PARAMS ((td_thr_state_e statecode));
+static int thread_to_lwp PARAMS ((int thread_id, int default_lwp));
+static void sol_thread_resume PARAMS ((int pid, int step,
+ enum target_signal signo));
+static int lwp_to_thread PARAMS ((int lwp));
+static int sol_thread_alive PARAMS ((int pid));
+static void sol_core_close PARAMS ((int quitting));
+
+static void init_sol_thread_ops PARAMS ((void));
+static void init_sol_core_ops PARAMS ((void));
+
+#define THREAD_FLAG 0x80000000
+#define is_thread(ARG) (((ARG) & THREAD_FLAG) != 0)
+#define is_lwp(ARG) (((ARG) & THREAD_FLAG) == 0)
+#define GET_LWP(LWP_ID) (TIDGET(LWP_ID))
+#define GET_THREAD(THREAD_ID) (((THREAD_ID) >> 16) & 0x7fff)
+#define BUILD_LWP(LWP_ID, PID) ((LWP_ID) << 16 | (PID))
+#define BUILD_THREAD(THREAD_ID, PID) (THREAD_FLAG | BUILD_LWP (THREAD_ID, PID))
+
+/* Pointers to routines from lithread_db resolved by dlopen() */
+
+static void
+ (*p_td_log) (const int on_off);
+static td_err_e
+ (*p_td_ta_new) (const struct ps_prochandle *ph_p, td_thragent_t **ta_pp);
+static td_err_e
+ (*p_td_ta_delete) (td_thragent_t *ta_p);
+static td_err_e
+ (*p_td_init) (void);
+static td_err_e
+ (*p_td_ta_get_ph) (const td_thragent_t *ta_p, struct ps_prochandle **ph_pp);
+static td_err_e
+ (*p_td_ta_get_nthreads) (const td_thragent_t *ta_p, int *nthread_p);
+static td_err_e
+ (*p_td_ta_tsd_iter) (const td_thragent_t *ta_p, td_key_iter_f *cb, void *cbdata_p);
+static td_err_e
+ (*p_td_ta_thr_iter) (const td_thragent_t *ta_p, td_thr_iter_f *cb, void *cbdata_p, td_thr_state_e state,
+ int ti_pri, sigset_t *ti_sigmask_p, unsigned ti_user_flags);
+static td_err_e
+ (*p_td_thr_validate) (const td_thrhandle_t *th_p);
+static td_err_e
+ (*p_td_thr_tsd) (const td_thrhandle_t *th_p, const thread_key_t key, void **data_pp);
+static td_err_e
+ (*p_td_thr_get_info) (const td_thrhandle_t *th_p, td_thrinfo_t *ti_p);
+static td_err_e
+ (*p_td_thr_getfpregs) (const td_thrhandle_t *th_p, prfpregset_t *fpregset);
+static td_err_e
+ (*p_td_thr_getxregsize) (const td_thrhandle_t *th_p, int *xregsize);
+static td_err_e
+ (*p_td_thr_getxregs) (const td_thrhandle_t *th_p, const caddr_t xregset);
+static td_err_e
+ (*p_td_thr_sigsetmask) (const td_thrhandle_t *th_p, const sigset_t ti_sigmask);
+static td_err_e
+ (*p_td_thr_setprio) (const td_thrhandle_t *th_p, const int ti_pri);
+static td_err_e
+ (*p_td_thr_setsigpending) (const td_thrhandle_t *th_p, const uchar_t ti_pending_flag, const sigset_t ti_pending);
+static td_err_e
+ (*p_td_thr_setfpregs) (const td_thrhandle_t *th_p, const prfpregset_t *fpregset);
+static td_err_e
+ (*p_td_thr_setxregs) (const td_thrhandle_t *th_p, const caddr_t xregset);
+static td_err_e
+ (*p_td_ta_map_id2thr) (const td_thragent_t *ta_p, thread_t tid, td_thrhandle_t *th_p);
+static td_err_e
+ (*p_td_ta_map_lwp2thr) (const td_thragent_t *ta_p, lwpid_t lwpid, td_thrhandle_t *th_p);
+static td_err_e
+ (*p_td_thr_getgregs) (const td_thrhandle_t *th_p, prgregset_t regset);
+static td_err_e
+ (*p_td_thr_setgregs) (const td_thrhandle_t *th_p, const prgregset_t regset);
+
+/*
+
+LOCAL FUNCTION
+
+ td_err_string - Convert a thread_db error code to a string
+
+SYNOPSIS
+
+ char * td_err_string (errcode)
+
+DESCRIPTION
+
+ Return the thread_db error string associated with errcode. If errcode
+ is unknown, then return a message.
+
+ */
+
+static char *
+td_err_string (errcode)
+ td_err_e errcode;
+{
+ static struct string_map
+ td_err_table[] = {
+ {TD_OK, "generic \"call succeeded\""},
+ {TD_ERR, "generic error."},
+ {TD_NOTHR, "no thread can be found to satisfy query"},
+ {TD_NOSV, "no synch. variable can be found to satisfy query"},
+ {TD_NOLWP, "no lwp can be found to satisfy query"},
+ {TD_BADPH, "invalid process handle"},
+ {TD_BADTH, "invalid thread handle"},
+ {TD_BADSH, "invalid synchronization handle"},
+ {TD_BADTA, "invalid thread agent"},
+ {TD_BADKEY, "invalid key"},
+ {TD_NOMSG, "td_thr_event_getmsg() called when there was no message"},
+ {TD_NOFPREGS, "FPU register set not available for given thread"},
+ {TD_NOLIBTHREAD, "application not linked with libthread"},
+ {TD_NOEVENT, "requested event is not supported"},
+ {TD_NOCAPAB, "capability not available"},
+ {TD_DBERR, "Debugger service failed"},
+ {TD_NOAPLIC, "Operation not applicable to"},
+ {TD_NOTSD, "No thread specific data for this thread"},
+ {TD_MALLOC, "Malloc failed"},
+ {TD_PARTIALREG, "Only part of register set was writen/read"},
+ {TD_NOXREGS, "X register set not available for given thread"}
+ };
+ const int td_err_size = sizeof td_err_table / sizeof (struct string_map);
+ int i;
+ static char buf[50];
+
+ for (i = 0; i < td_err_size; i++)
+ if (td_err_table[i].num == errcode)
+ return td_err_table[i].str;
+
+ sprintf (buf, "Unknown thread_db error code: %d", errcode);
+
+ return buf;
+}
+
+/*
+
+LOCAL FUNCTION
+
+ td_state_string - Convert a thread_db state code to a string
+
+SYNOPSIS
+
+ char * td_state_string (statecode)
+
+DESCRIPTION
+
+ Return the thread_db state string associated with statecode. If
+ statecode is unknown, then return a message.
+
+ */
+
+static char *
+td_state_string (statecode)
+ td_thr_state_e statecode;
+{
+ static struct string_map
+ td_thr_state_table[] = {
+ {TD_THR_ANY_STATE, "any state"},
+ {TD_THR_UNKNOWN, "unknown"},
+ {TD_THR_STOPPED, "stopped"},
+ {TD_THR_RUN, "run"},
+ {TD_THR_ACTIVE, "active"},
+ {TD_THR_ZOMBIE, "zombie"},
+ {TD_THR_SLEEP, "sleep"},
+ {TD_THR_STOPPED_ASLEEP, "stopped asleep"}
+ };
+ const int td_thr_state_table_size = sizeof td_thr_state_table / sizeof (struct string_map);
+ int i;
+ static char buf[50];
+
+ for (i = 0; i < td_thr_state_table_size; i++)
+ if (td_thr_state_table[i].num == statecode)
+ return td_thr_state_table[i].str;
+
+ sprintf (buf, "Unknown thread_db state code: %d", statecode);
+
+ return buf;
+}
+
+/*
+
+LOCAL FUNCTION
+
+ thread_to_lwp - Convert a Posix or Solaris thread id to a LWP id.
+
+SYNOPSIS
+
+ int thread_to_lwp (thread_id, default_lwp)
+
+DESCRIPTION
+
+ This function converts a Posix or Solaris thread id to a lightweight
+ process id. If thread_id is non-existent, that's an error. If it's
+ an inactive thread, then we return default_lwp.
+
+NOTES
+
+ This function probably shouldn't call error()...
+
+ */
+
+static int
+thread_to_lwp (thread_id, default_lwp)
+ int thread_id;
+ int default_lwp;
+{
+ td_thrinfo_t ti;
+ td_thrhandle_t th;
+ td_err_e val;
+
+ if (is_lwp (thread_id))
+ return thread_id; /* It's already an LWP id */
+
+ /* It's a thread. Convert to lwp */
+
+ val = p_td_ta_map_id2thr (main_ta, GET_THREAD (thread_id), &th);
+ if (val == TD_NOTHR)
+ return -1; /* thread must have terminated */
+ else if (val != TD_OK)
+ error ("thread_to_lwp: td_ta_map_id2thr %s", td_err_string (val));
+
+ val = p_td_thr_get_info (&th, &ti);
+ if (val == TD_NOTHR)
+ return -1; /* thread must have terminated */
+ else if (val != TD_OK)
+ error ("thread_to_lwp: td_thr_get_info: %s", td_err_string (val));
+
+ if (ti.ti_state != TD_THR_ACTIVE)
+ {
+ if (default_lwp != -1)
+ return default_lwp;
+ error ("thread_to_lwp: thread state not active: %s",
+ td_state_string (ti.ti_state));
+ }
+
+ return BUILD_LWP (ti.ti_lid, PIDGET (thread_id));
+}
+
+/*
+
+LOCAL FUNCTION
+
+ lwp_to_thread - Convert a LWP id to a Posix or Solaris thread id.
+
+SYNOPSIS
+
+ int lwp_to_thread (lwp_id)
+
+DESCRIPTION
+
+ This function converts a lightweight process id to a Posix or Solaris
+ thread id. If thread_id is non-existent, that's an error.
+
+NOTES
+
+ This function probably shouldn't call error()...
+
+ */
+
+static int
+lwp_to_thread (lwp)
+ int lwp;
+{
+ td_thrinfo_t ti;
+ td_thrhandle_t th;
+ td_err_e val;
+
+ if (is_thread (lwp))
+ return lwp; /* It's already a thread id */
+
+ /* It's an lwp. Convert it to a thread id. */
+
+ if (!sol_thread_alive (lwp))
+ return -1; /* defunct lwp */
+
+ val = p_td_ta_map_lwp2thr (main_ta, GET_LWP (lwp), &th);
+ if (val == TD_NOTHR)
+ return -1; /* thread must have terminated */
+ else if (val != TD_OK)
+ error ("lwp_to_thread: td_ta_map_lwp2thr: %s.", td_err_string (val));
+
+ val = p_td_thr_validate (&th);
+ if (val == TD_NOTHR)
+ return lwp; /* libthread doesn't know about it, just return lwp */
+ else if (val != TD_OK)
+ error ("lwp_to_thread: td_thr_validate: %s.", td_err_string (val));
+
+ val = p_td_thr_get_info (&th, &ti);
+ if (val == TD_NOTHR)
+ return -1; /* thread must have terminated */
+ else if (val != TD_OK)
+ error ("lwp_to_thread: td_thr_get_info: %s.", td_err_string (val));
+
+ return BUILD_THREAD (ti.ti_tid, PIDGET (lwp));
+}
+
+/*
+
+LOCAL FUNCTION
+
+ save_inferior_pid - Save inferior_pid on the cleanup list
+ restore_inferior_pid - Restore inferior_pid from the cleanup list
+
+SYNOPSIS
+
+ struct cleanup *save_inferior_pid ()
+ void restore_inferior_pid (int pid)
+
+DESCRIPTION
+
+ These two functions act in unison to restore inferior_pid in
+ case of an error.
+
+NOTES
+
+ inferior_pid is a global variable that needs to be changed by many of
+ these routines before calling functions in procfs.c. In order to
+ guarantee that inferior_pid gets restored (in case of errors), you
+ need to call save_inferior_pid before changing it. At the end of the
+ function, you should invoke do_cleanups to restore it.
+
+ */
+
+
+static struct cleanup *
+save_inferior_pid ()
+{
+ return make_cleanup (restore_inferior_pid, inferior_pid);
+}
+
+static void
+restore_inferior_pid (pid)
+ int pid;
+{
+ inferior_pid = pid;
+}
+
+
+/* Most target vector functions from here on actually just pass through to
+ procfs.c, as they don't need to do anything specific for threads. */
+
+
+/* ARGSUSED */
+static void
+sol_thread_open (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ procfs_ops.to_open (arg, from_tty);
+}
+
+/* Attach to process PID, then initialize for debugging it
+ and wait for the trace-trap that results from attaching. */
+
+static void
+sol_thread_attach (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ procfs_ops.to_attach (args, from_tty);
+ /* Must get symbols from solibs before libthread_db can run! */
+ SOLIB_ADD ((char *)0, from_tty, (struct target_ops *)0);
+ if (sol_thread_active)
+ {
+ printf_filtered ("sol-thread active.\n");
+ main_ph.pid = inferior_pid; /* Save for xfer_memory */
+ push_target (&sol_thread_ops);
+ inferior_pid = lwp_to_thread (inferior_pid);
+ if (inferior_pid == -1)
+ inferior_pid = main_ph.pid;
+ else
+ add_thread (inferior_pid);
+ }
+ /* XXX - might want to iterate over all the threads and register them. */
+}
+
+/* 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
+sol_thread_detach (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ unpush_target (&sol_thread_ops);
+ procfs_ops.to_detach (args, from_tty);
+}
+
+/* Resume execution of process PID. If STEP is nozero, then
+ just single step it. If SIGNAL is nonzero, restart it with that
+ signal activated. We may have to convert pid from a thread-id to an LWP id
+ for procfs. */
+
+static void
+sol_thread_resume (pid, step, signo)
+ int pid;
+ int step;
+ enum target_signal signo;
+{
+ struct cleanup *old_chain;
+
+ old_chain = save_inferior_pid ();
+
+ inferior_pid = thread_to_lwp (inferior_pid, main_ph.pid);
+ if (inferior_pid == -1)
+ inferior_pid = procfs_first_available ();
+
+ if (pid != -1)
+ {
+ int save_pid = pid;
+
+ pid = thread_to_lwp (pid, -2);
+ if (pid == -2) /* Inactive thread */
+ error ("This version of Solaris can't start inactive threads.");
+ if (info_verbose && pid == -1)
+ warning ("Specified thread %d seems to have terminated",
+ GET_THREAD (save_pid));
+ }
+
+ procfs_ops.to_resume (pid, step, signo);
+
+ do_cleanups (old_chain);
+}
+
+/* Wait for any threads to stop. We may have to convert PID from a thread id
+ to a LWP id, and vice versa on the way out. */
+
+static int
+sol_thread_wait (pid, ourstatus)
+ int pid;
+ struct target_waitstatus *ourstatus;
+{
+ int rtnval;
+ int save_pid;
+ struct cleanup *old_chain;
+
+ save_pid = inferior_pid;
+ old_chain = save_inferior_pid ();
+
+ inferior_pid = thread_to_lwp (inferior_pid, main_ph.pid);
+ if (inferior_pid == -1)
+ inferior_pid = procfs_first_available ();
+
+ if (pid != -1)
+ {
+ int save_pid = pid;
+
+ pid = thread_to_lwp (pid, -2);
+ if (pid == -2) /* Inactive thread */
+ error ("This version of Solaris can't start inactive threads.");
+ if (info_verbose && pid == -1)
+ warning ("Specified thread %d seems to have terminated",
+ GET_THREAD (save_pid));
+ }
+
+ rtnval = procfs_ops.to_wait (pid, ourstatus);
+
+ if (ourstatus->kind != TARGET_WAITKIND_EXITED)
+ {
+ /* Map the LWP of interest back to the appropriate thread ID */
+ rtnval = lwp_to_thread (rtnval);
+ if (rtnval == -1)
+ rtnval = save_pid;
+
+ /* See if we have a new thread */
+ if (is_thread (rtnval)
+ && rtnval != save_pid
+ && !in_thread_list (rtnval))
+ {
+ printf_filtered ("[New %s]\n", target_pid_to_str (rtnval));
+ add_thread (rtnval);
+ }
+ }
+
+ /* During process initialization, we may get here without the thread package
+ being initialized, since that can only happen after we've found the shared
+ libs. */
+
+ do_cleanups (old_chain);
+
+ return rtnval;
+}
+
+static void
+sol_thread_fetch_registers (regno)
+ int regno;
+{
+ thread_t thread;
+ td_thrhandle_t thandle;
+ td_err_e val;
+ prgregset_t gregset;
+ prfpregset_t fpregset;
+#if 0
+ int xregsize;
+ caddr_t xregset;
+#endif
+
+ if (!is_thread (inferior_pid))
+ { /* LWP: pass the request on to procfs.c */
+ if (target_has_execution)
+ procfs_ops.to_fetch_registers (regno);
+ else
+ orig_core_ops.to_fetch_registers (regno);
+ return;
+ }
+
+ /* Solaris thread: convert inferior_pid into a td_thrhandle_t */
+
+ thread = GET_THREAD (inferior_pid);
+
+ if (thread == 0)
+ error ("sol_thread_fetch_registers: thread == 0");
+
+ val = p_td_ta_map_id2thr (main_ta, thread, &thandle);
+ if (val != TD_OK)
+ error ("sol_thread_fetch_registers: td_ta_map_id2thr: %s",
+ td_err_string (val));
+
+ /* Get the integer regs */
+
+ val = p_td_thr_getgregs (&thandle, gregset);
+ if (val != TD_OK
+ && val != TD_PARTIALREG)
+ error ("sol_thread_fetch_registers: td_thr_getgregs %s",
+ td_err_string (val));
+
+ /* For the sparc, TD_PARTIALREG means that only i0->i7, l0->l7, pc and sp
+ are saved (by a thread context switch). */
+
+ /* And, now the fp regs */
+
+ val = p_td_thr_getfpregs (&thandle, &fpregset);
+ if (val != TD_OK
+ && val != TD_NOFPREGS)
+ error ("sol_thread_fetch_registers: td_thr_getfpregs %s",
+ td_err_string (val));
+
+/* Note that we must call supply_{g fp}regset *after* calling the td routines
+ because the td routines call ps_lget* which affect the values stored in the
+ registers array. */
+
+ supply_gregset (gregset);
+ supply_fpregset (&fpregset);
+
+#if 0
+/* thread_db doesn't seem to handle this right */
+ val = td_thr_getxregsize (&thandle, &xregsize);
+ if (val != TD_OK && val != TD_NOXREGS)
+ error ("sol_thread_fetch_registers: td_thr_getxregsize %s",
+ td_err_string (val));
+
+ if (val == TD_OK)
+ {
+ xregset = alloca (xregsize);
+ val = td_thr_getxregs (&thandle, xregset);
+ if (val != TD_OK)
+ error ("sol_thread_fetch_registers: td_thr_getxregs %s",
+ td_err_string (val));
+ }
+#endif
+}
+
+static void
+sol_thread_store_registers (regno)
+ int regno;
+{
+ thread_t thread;
+ td_thrhandle_t thandle;
+ td_err_e val;
+ prgregset_t regset;
+ prfpregset_t fpregset;
+#if 0
+ int xregsize;
+ caddr_t xregset;
+#endif
+
+ if (!is_thread (inferior_pid))
+ { /* LWP: pass the request on to procfs.c */
+ procfs_ops.to_store_registers (regno);
+ return;
+ }
+
+ /* Solaris thread: convert inferior_pid into a td_thrhandle_t */
+
+ thread = GET_THREAD (inferior_pid);
+
+ val = p_td_ta_map_id2thr (main_ta, thread, &thandle);
+ if (val != TD_OK)
+ error ("sol_thread_store_registers: td_ta_map_id2thr %s",
+ td_err_string (val));
+
+ if (regno != -1)
+ { /* Not writing all the regs */
+ /* save new register value */
+ char old_value[REGISTER_SIZE];
+ memcpy(old_value, & registers[REGISTER_BYTE(regno)], REGISTER_SIZE);
+
+ val = p_td_thr_getgregs (&thandle, regset);
+ if (val != TD_OK)
+ error ("sol_thread_store_registers: td_thr_getgregs %s",
+ td_err_string (val));
+ val = p_td_thr_getfpregs (&thandle, &fpregset);
+ if (val != TD_OK)
+ error ("sol_thread_store_registers: td_thr_getfpregs %s",
+ td_err_string (val));
+
+ /* restore new register value */
+ memcpy(& registers[REGISTER_BYTE(regno)], old_value, REGISTER_SIZE);
+
+#if 0
+/* thread_db doesn't seem to handle this right */
+ val = td_thr_getxregsize (&thandle, &xregsize);
+ if (val != TD_OK && val != TD_NOXREGS)
+ error ("sol_thread_store_registers: td_thr_getxregsize %s",
+ td_err_string (val));
+
+ if (val == TD_OK)
+ {
+ xregset = alloca (xregsize);
+ val = td_thr_getxregs (&thandle, xregset);
+ if (val != TD_OK)
+ error ("sol_thread_store_registers: td_thr_getxregs %s",
+ td_err_string (val));
+ }
+#endif
+ }
+
+ fill_gregset (regset, regno);
+ fill_fpregset (&fpregset, regno);
+
+ val = p_td_thr_setgregs (&thandle, regset);
+ if (val != TD_OK)
+ error ("sol_thread_store_registers: td_thr_setgregs %s",
+ td_err_string (val));
+ val = p_td_thr_setfpregs (&thandle, &fpregset);
+ if (val != TD_OK)
+ error ("sol_thread_store_registers: td_thr_setfpregs %s",
+ td_err_string (val));
+
+#if 0
+/* thread_db doesn't seem to handle this right */
+ val = td_thr_getxregsize (&thandle, &xregsize);
+ if (val != TD_OK && val != TD_NOXREGS)
+ error ("sol_thread_store_registers: td_thr_getxregsize %s",
+ td_err_string (val));
+
+ /* Should probably do something about writing the xregs here, but what are
+ they? */
+#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
+sol_thread_prepare_to_store ()
+{
+ procfs_ops.to_prepare_to_store ();
+}
+
+static int
+sol_thread_xfer_memory (memaddr, myaddr, len, dowrite, target)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+ int dowrite;
+ struct target_ops *target; /* ignored */
+{
+ int retval;
+ struct cleanup *old_chain;
+
+ old_chain = save_inferior_pid ();
+
+ if (is_thread (inferior_pid) || /* A thread */
+ !target_thread_alive (inferior_pid)) /* An lwp, but not alive */
+ inferior_pid = procfs_first_available (); /* Find any live lwp. */
+ /* Note: don't need to call switch_to_thread; we're just reading memory. */
+
+ if (target_has_execution)
+ retval = procfs_ops.to_xfer_memory (memaddr, myaddr, len, dowrite, target);
+ else
+ retval = orig_core_ops.to_xfer_memory (memaddr, myaddr, len,
+ dowrite, target);
+
+ do_cleanups (old_chain);
+
+ return retval;
+}
+
+/* Print status information about what we're accessing. */
+
+static void
+sol_thread_files_info (ignore)
+ struct target_ops *ignore;
+{
+ procfs_ops.to_files_info (ignore);
+}
+
+static void
+sol_thread_kill_inferior ()
+{
+ procfs_ops.to_kill ();
+}
+
+static void
+sol_thread_notice_signals (pid)
+ int pid;
+{
+ procfs_ops.to_notice_signals (PIDGET (pid));
+}
+
+/* Fork an inferior process, and start debugging it with /proc. */
+
+static void
+sol_thread_create_inferior (exec_file, allargs, env)
+ char *exec_file;
+ char *allargs;
+ char **env;
+{
+ procfs_ops.to_create_inferior (exec_file, allargs, env);
+
+ if (sol_thread_active && inferior_pid != 0)
+ {
+ main_ph.pid = inferior_pid; /* Save for xfer_memory */
+
+ push_target (&sol_thread_ops);
+
+ inferior_pid = lwp_to_thread (inferior_pid);
+ if (inferior_pid == -1)
+ inferior_pid = main_ph.pid;
+
+ add_thread (inferior_pid);
+ }
+}
+
+/* This routine is called whenever a new symbol table is read in, or when all
+ symbol tables are removed. libthread_db can only be initialized when it
+ finds the right variables in libthread.so. Since it's a shared library,
+ those variables don't show up until the library gets mapped and the symbol
+ table is read in. */
+
+void
+sol_thread_new_objfile (objfile)
+ struct objfile *objfile;
+{
+ td_err_e val;
+
+ if (!objfile)
+ {
+ sol_thread_active = 0;
+
+ return;
+ }
+
+ /* don't do anything if init failed to resolve the libthread_db library */
+ if (!procfs_suppress_run)
+ return;
+
+ /* Now, initialize the thread debugging library. This needs to be done after
+ the shared libraries are located because it needs information from the
+ user's thread library. */
+
+ val = p_td_init ();
+ if (val != TD_OK)
+ error ("target_new_objfile: td_init: %s", td_err_string (val));
+
+ val = p_td_ta_new (&main_ph, &main_ta);
+ if (val == TD_NOLIBTHREAD)
+ return;
+ else if (val != TD_OK)
+ error ("target_new_objfile: td_ta_new: %s", td_err_string (val));
+
+ sol_thread_active = 1;
+}
+
+/* Clean up after the inferior dies. */
+
+static void
+sol_thread_mourn_inferior ()
+{
+ unpush_target (&sol_thread_ops);
+ procfs_ops.to_mourn_inferior ();
+}
+
+/* Mark our target-struct as eligible for stray "run" and "attach" commands. */
+
+static int
+sol_thread_can_run ()
+{
+ return procfs_suppress_run;
+}
+
+/*
+
+LOCAL FUNCTION
+
+ sol_thread_alive - test thread for "aliveness"
+
+SYNOPSIS
+
+ static bool sol_thread_alive (int pid);
+
+DESCRIPTION
+
+ returns true if thread still active in inferior.
+
+ */
+
+static int
+sol_thread_alive (pid)
+ int pid;
+{
+ if (is_thread (pid)) /* non-kernel thread */
+ {
+ td_err_e val;
+ td_thrhandle_t th;
+
+ pid = GET_THREAD (pid);
+ if ((val = p_td_ta_map_id2thr (main_ta, pid, &th)) != TD_OK)
+ return 0; /* thread not found */
+ if ((val = p_td_thr_validate (&th)) != TD_OK)
+ return 0; /* thread not valid */
+ return 1; /* known thread: return true */
+ }
+ else /* kernel thread (LWP): let procfs test it */
+ {
+ if (target_has_execution)
+ return procfs_ops.to_thread_alive (pid);
+ else
+ return orig_core_ops.to_thread_alive (pid);
+ }
+}
+
+static void
+sol_thread_stop ()
+{
+ procfs_ops.to_stop ();
+}
+
+/* These routines implement the lower half of the thread_db interface. Ie: the
+ ps_* routines. */
+
+/* Various versions of <proc_service.h> have slightly
+ different function prototypes. In particular, we have
+
+ NEWER OLDER
+ struct ps_prochandle * const struct ps_prochandle *
+ void* char*
+ const void* char*
+ int size_t
+
+ Which one you have depends on solaris version and what
+ patches you've applied. On the theory that there are
+ only two major variants, we have configure check the
+ prototype of ps_pdwrite (), and use that info to make
+ appropriate typedefs here. */
+
+#ifdef PROC_SERVICE_IS_OLD
+typedef const struct ps_prochandle * gdb_ps_prochandle_t;
+typedef char * gdb_ps_read_buf_t;
+typedef char * gdb_ps_write_buf_t;
+typedef int gdb_ps_size_t;
+#else
+typedef struct ps_prochandle * gdb_ps_prochandle_t;
+typedef void * gdb_ps_read_buf_t;
+typedef const void * gdb_ps_write_buf_t;
+typedef size_t gdb_ps_size_t;
+#endif
+
+
+/* The next four routines are called by thread_db to tell us to stop and stop
+ a particular process or lwp. Since GDB ensures that these are all stopped
+ by the time we call anything in thread_db, these routines need to do
+ nothing. */
+
+ps_err_e
+ps_pstop (gdb_ps_prochandle_t ph)
+{
+ return PS_OK;
+}
+
+ps_err_e
+ps_pcontinue (gdb_ps_prochandle_t ph)
+{
+ return PS_OK;
+}
+
+ps_err_e
+ps_lstop (gdb_ps_prochandle_t ph, lwpid_t lwpid)
+{
+ return PS_OK;
+}
+
+ps_err_e
+ps_lcontinue (gdb_ps_prochandle_t ph, lwpid_t lwpid)
+{
+ return PS_OK;
+}
+
+ps_err_e
+ps_pglobal_lookup (gdb_ps_prochandle_t ph, const char *ld_object_name,
+ const char *ld_symbol_name, paddr_t *ld_symbol_addr)
+{
+ struct minimal_symbol *ms;
+
+ ms = lookup_minimal_symbol (ld_symbol_name, NULL, NULL);
+
+ if (!ms)
+ return PS_NOSYM;
+
+ *ld_symbol_addr = SYMBOL_VALUE_ADDRESS (ms);
+
+ return PS_OK;
+}
+
+/* Common routine for reading and writing memory. */
+
+static ps_err_e
+rw_common (int dowrite, const struct ps_prochandle *ph, paddr_t addr,
+ char *buf, int size)
+{
+ struct cleanup *old_chain;
+
+ old_chain = save_inferior_pid ();
+
+ if (is_thread (inferior_pid) || /* A thread */
+ !target_thread_alive (inferior_pid)) /* An lwp, but not alive */
+ inferior_pid = procfs_first_available (); /* Find any live lwp. */
+ /* Note: don't need to call switch_to_thread; we're just reading memory. */
+
+ while (size > 0)
+ {
+ int cc;
+
+ if (target_has_execution)
+ cc = procfs_ops.to_xfer_memory (addr, buf, size, dowrite, &procfs_ops);
+ else
+ cc = orig_core_ops.to_xfer_memory (addr, buf, size, dowrite, &core_ops);
+
+ if (cc < 0)
+ {
+ if (dowrite == 0)
+ print_sys_errmsg ("rw_common (): read", errno);
+ else
+ print_sys_errmsg ("rw_common (): write", errno);
+
+ do_cleanups (old_chain);
+
+ return PS_ERR;
+ }
+ size -= cc;
+ buf += cc;
+ }
+
+ do_cleanups (old_chain);
+
+ return PS_OK;
+}
+
+ps_err_e
+ps_pdread (gdb_ps_prochandle_t ph, paddr_t addr,
+ gdb_ps_read_buf_t buf, gdb_ps_size_t size)
+{
+ return rw_common (0, ph, addr, buf, size);
+}
+
+ps_err_e
+ps_pdwrite (gdb_ps_prochandle_t ph, paddr_t addr,
+ gdb_ps_write_buf_t buf, gdb_ps_size_t size)
+{
+ return rw_common (1, ph, addr, (char*) buf, size);
+}
+
+ps_err_e
+ps_ptread (gdb_ps_prochandle_t ph, paddr_t addr,
+ gdb_ps_read_buf_t buf, gdb_ps_size_t size)
+{
+ return rw_common (0, ph, addr, buf, size);
+}
+
+ps_err_e
+ps_ptwrite (gdb_ps_prochandle_t ph, paddr_t addr,
+ gdb_ps_write_buf_t buf, gdb_ps_size_t size)
+{
+ return rw_common (1, ph, addr, (char*) buf, size);
+}
+
+/* Get integer regs */
+
+ps_err_e
+ps_lgetregs (gdb_ps_prochandle_t ph, lwpid_t lwpid,
+ prgregset_t gregset)
+{
+ struct cleanup *old_chain;
+
+ old_chain = save_inferior_pid ();
+
+ inferior_pid = BUILD_LWP (lwpid, PIDGET (inferior_pid));
+
+ if (target_has_execution)
+ procfs_ops.to_fetch_registers (-1);
+ else
+ orig_core_ops.to_fetch_registers (-1);
+ fill_gregset (gregset, -1);
+
+ do_cleanups (old_chain);
+
+ return PS_OK;
+}
+
+/* Set integer regs */
+
+ps_err_e
+ps_lsetregs (gdb_ps_prochandle_t ph, lwpid_t lwpid,
+ const prgregset_t gregset)
+{
+ struct cleanup *old_chain;
+
+ old_chain = save_inferior_pid ();
+
+ inferior_pid = BUILD_LWP (lwpid, PIDGET (inferior_pid));
+
+ supply_gregset (gregset);
+ if (target_has_execution)
+ procfs_ops.to_store_registers (-1);
+ else
+ orig_core_ops.to_store_registers (-1);
+
+ do_cleanups (old_chain);
+
+ return PS_OK;
+}
+
+void
+ps_plog (const char *fmt, ...)
+{
+ va_list args;
+
+ va_start (args, fmt);
+
+ vfprintf_filtered (gdb_stderr, fmt, args);
+}
+
+/* Get size of extra register set. Currently a noop. */
+
+ps_err_e
+ps_lgetxregsize (gdb_ps_prochandle_t ph, lwpid_t lwpid, int *xregsize)
+{
+#if 0
+ int lwp_fd;
+ int regsize;
+ ps_err_e val;
+
+ val = get_lwp_fd (ph, lwpid, &lwp_fd);
+ if (val != PS_OK)
+ return val;
+
+ if (ioctl (lwp_fd, PIOCGXREGSIZE, &regsize))
+ {
+ if (errno == EINVAL)
+ return PS_NOFREGS; /* XXX Wrong code, but this is the closest
+ thing in proc_service.h */
+
+ print_sys_errmsg ("ps_lgetxregsize (): PIOCGXREGSIZE", errno);
+ return PS_ERR;
+ }
+#endif
+
+ return PS_OK;
+}
+
+/* Get extra register set. Currently a noop. */
+
+ps_err_e
+ps_lgetxregs (gdb_ps_prochandle_t ph, lwpid_t lwpid, caddr_t xregset)
+{
+#if 0
+ int lwp_fd;
+ ps_err_e val;
+
+ val = get_lwp_fd (ph, lwpid, &lwp_fd);
+ if (val != PS_OK)
+ return val;
+
+ if (ioctl (lwp_fd, PIOCGXREG, xregset))
+ {
+ print_sys_errmsg ("ps_lgetxregs (): PIOCGXREG", errno);
+ return PS_ERR;
+ }
+#endif
+
+ return PS_OK;
+}
+
+/* Set extra register set. Currently a noop. */
+
+ps_err_e
+ps_lsetxregs (gdb_ps_prochandle_t ph, lwpid_t lwpid, caddr_t xregset)
+{
+#if 0
+ int lwp_fd;
+ ps_err_e val;
+
+ val = get_lwp_fd (ph, lwpid, &lwp_fd);
+ if (val != PS_OK)
+ return val;
+
+ if (ioctl (lwp_fd, PIOCSXREG, xregset))
+ {
+ print_sys_errmsg ("ps_lsetxregs (): PIOCSXREG", errno);
+ return PS_ERR;
+ }
+#endif
+
+ return PS_OK;
+}
+
+/* Get floating-point regs. */
+
+ps_err_e
+ps_lgetfpregs (gdb_ps_prochandle_t ph, lwpid_t lwpid,
+ prfpregset_t *fpregset)
+{
+ struct cleanup *old_chain;
+
+ old_chain = save_inferior_pid ();
+
+ inferior_pid = BUILD_LWP (lwpid, PIDGET (inferior_pid));
+
+ if (target_has_execution)
+ procfs_ops.to_fetch_registers (-1);
+ else
+ orig_core_ops.to_fetch_registers (-1);
+ fill_fpregset (fpregset, -1);
+
+ do_cleanups (old_chain);
+
+ return PS_OK;
+}
+
+/* Set floating-point regs. */
+
+ps_err_e
+ps_lsetfpregs (gdb_ps_prochandle_t ph, lwpid_t lwpid,
+ const prfpregset_t *fpregset)
+{
+ struct cleanup *old_chain;
+
+ old_chain = save_inferior_pid ();
+
+ inferior_pid = BUILD_LWP (lwpid, PIDGET (inferior_pid));
+
+ supply_fpregset (fpregset);
+ if (target_has_execution)
+ procfs_ops.to_store_registers (-1);
+ else
+ orig_core_ops.to_store_registers (-1);
+
+ do_cleanups (old_chain);
+
+ return PS_OK;
+}
+
+#ifdef TM_I386SOL2_H
+
+/* Get local descriptor table. */
+
+#include <sys/procfs.h>
+#include <sys/reg.h>
+#include <sys/sysi86.h>
+
+static int nldt_allocated = 0;
+static struct ssd *ldt_bufp = NULL;
+
+ps_err_e
+ps_lgetLDT (gdb_ps_prochandle_t ph, lwpid_t lwpid,
+ struct ssd *pldt)
+{
+ gregset_t gregset;
+ int lwp_fd;
+ ps_err_e val;
+ int nldt;
+ int i;
+
+ /* Get procfs file descriptor for the LWP. */
+ lwp_fd = procfs_get_pid_fd (BUILD_LWP (lwpid, PIDGET (inferior_pid)));
+ if (lwp_fd < 0)
+ return PS_BADLID;
+
+ /* Fetch registers und LDT descriptors. */
+ if (ioctl (lwp_fd, PIOCGREG, &gregset) == -1)
+ return PS_ERR;
+
+ if (ioctl (lwp_fd, PIOCNLDT, &nldt) == -1)
+ return PS_ERR;
+
+ if (nldt_allocated < nldt)
+ {
+ ldt_bufp
+ = (struct ssd *) xrealloc (ldt_bufp, (nldt + 1) * sizeof (struct ssd));
+ nldt_allocated = nldt;
+ }
+
+ if (ioctl (lwp_fd, PIOCLDT, ldt_bufp) == -1)
+ return PS_ERR;
+
+ /* Search LDT for the LWP via register GS. */
+ for (i = 0; i < nldt; i++)
+ {
+ if (ldt_bufp[i].sel == (gregset[GS] & 0xffff))
+ {
+ *pldt = ldt_bufp[i];
+ return PS_OK;
+ }
+ }
+
+ /* LDT not found. */
+ return PS_ERR;
+}
+#endif /* TM_I386SOL2_H */
+
+/* Convert a pid to printable form. */
+
+char *
+solaris_pid_to_str (pid)
+ int pid;
+{
+ static char buf[100];
+
+ /* in case init failed to resolve the libthread_db library */
+ if (!procfs_suppress_run)
+ return procfs_pid_to_str (pid);
+
+ if (is_thread (pid))
+ {
+ int lwp;
+
+ lwp = thread_to_lwp (pid, -2);
+
+ if (lwp == -1)
+ sprintf (buf, "Thread %d (defunct)", GET_THREAD (pid));
+ else if (lwp != -2)
+ sprintf (buf, "Thread %d (LWP %d)", GET_THREAD (pid), GET_LWP (lwp));
+ else
+ sprintf (buf, "Thread %d ", GET_THREAD (pid));
+ }
+ else if (GET_LWP (pid) != 0)
+ sprintf (buf, "LWP %d ", GET_LWP (pid));
+ else
+ sprintf (buf, "process %d ", PIDGET (pid));
+
+ return buf;
+}
+
+
+/* Worker bee for find_new_threads
+ Callback function that gets called once per USER thread (i.e., not
+ kernel) thread. */
+
+static int
+sol_find_new_threads_callback(th, ignored)
+ const td_thrhandle_t *th;
+ void *ignored;
+{
+ td_err_e retval;
+ td_thrinfo_t ti;
+ int pid;
+
+ if ((retval = p_td_thr_get_info(th, &ti)) != TD_OK)
+ {
+ return -1;
+ }
+ pid = BUILD_THREAD(ti.ti_tid, PIDGET(inferior_pid));
+ if (!in_thread_list(pid))
+ add_thread(pid);
+
+ return 0;
+}
+
+void
+sol_find_new_threads()
+{
+ /* don't do anything if init failed to resolve the libthread_db library */
+ if (!procfs_suppress_run)
+ return;
+
+ if (inferior_pid == -1)
+ {
+ printf_filtered("No process.\n");
+ return;
+ }
+ p_td_ta_thr_iter (main_ta, sol_find_new_threads_callback, (void *)0,
+ TD_THR_ANY_STATE, TD_THR_LOWEST_PRIORITY,
+ TD_SIGNO_MASK, TD_THR_ANY_USER_FLAGS);
+}
+
+static void
+sol_core_open (filename, from_tty)
+ char *filename;
+ int from_tty;
+{
+ orig_core_ops.to_open (filename, from_tty);
+}
+
+static void
+sol_core_close (quitting)
+ int quitting;
+{
+ orig_core_ops.to_close (quitting);
+}
+
+static void
+sol_core_detach (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ unpush_target (&core_ops);
+ orig_core_ops.to_detach (args, from_tty);
+}
+
+static void
+sol_core_files_info (t)
+ struct target_ops *t;
+{
+ orig_core_ops.to_files_info (t);
+}
+
+#ifdef MAINTENANCE_CMDS
+/* Worker bee for info sol-thread command. This is a callback function that
+ gets called once for each Solaris thread (ie. not kernel thread) in the
+ inferior. Print anything interesting that we can think of. */
+
+static int
+info_cb (th, s)
+ const td_thrhandle_t *th;
+ void *s;
+{
+ td_err_e ret;
+ td_thrinfo_t ti;
+ struct minimal_symbol *msym;
+
+ if ((ret = p_td_thr_get_info (th, &ti)) == TD_OK)
+ {
+ printf_filtered ("%s thread #%d, lwp %d, ",
+ ti.ti_type == TD_THR_SYSTEM ? "system" : "user ",
+ ti.ti_tid, ti.ti_lid);
+ switch (ti.ti_state) {
+ default:
+ case TD_THR_UNKNOWN: printf_filtered ("<unknown state>"); break;
+ case TD_THR_STOPPED: printf_filtered ("(stopped)"); break;
+ case TD_THR_RUN: printf_filtered ("(run) "); break;
+ case TD_THR_ACTIVE: printf_filtered ("(active) "); break;
+ case TD_THR_ZOMBIE: printf_filtered ("(zombie) "); break;
+ case TD_THR_SLEEP: printf_filtered ("(asleep) "); break;
+ case TD_THR_STOPPED_ASLEEP:
+ printf_filtered ("(stopped asleep)"); break;
+ }
+ /* Print thr_create start function: */
+ if (ti.ti_startfunc != 0)
+ if (msym = lookup_minimal_symbol_by_pc (ti.ti_startfunc))
+ printf_filtered (" startfunc: %s\n", SYMBOL_NAME (msym));
+ else
+ printf_filtered (" startfunc: 0x%08x\n", ti.ti_startfunc);
+
+ /* If thread is asleep, print function that went to sleep: */
+ if (ti.ti_state == TD_THR_SLEEP)
+ if (msym = lookup_minimal_symbol_by_pc (ti.ti_pc))
+ printf_filtered (" - Sleep func: %s\n", SYMBOL_NAME (msym));
+ else
+ printf_filtered (" - Sleep func: 0x%08x\n", ti.ti_startfunc);
+
+ /* Wrap up line, if necessary */
+ if (ti.ti_state != TD_THR_SLEEP && ti.ti_startfunc == 0)
+ printf_filtered ("\n"); /* don't you hate counting newlines? */
+ }
+ else
+ warning ("info sol-thread: failed to get info for thread.");
+
+ return 0;
+}
+
+/* List some state about each Solaris user thread in the inferior. */
+
+static void
+info_solthreads (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ p_td_ta_thr_iter (main_ta, info_cb, args,
+ TD_THR_ANY_STATE, TD_THR_LOWEST_PRIORITY,
+ TD_SIGNO_MASK, TD_THR_ANY_USER_FLAGS);
+}
+#endif /* MAINTENANCE_CMDS */
+
+static int
+ignore (addr, contents)
+ CORE_ADDR addr;
+ char *contents;
+{
+ return 0;
+}
+
+
+static void
+init_sol_thread_ops ()
+{
+ sol_thread_ops.to_shortname = "solaris-threads";
+ sol_thread_ops.to_longname = "Solaris threads and pthread.";
+ sol_thread_ops.to_doc = "Solaris threads and pthread support.";
+ sol_thread_ops.to_open = sol_thread_open;
+ sol_thread_ops.to_close = 0;
+ sol_thread_ops.to_attach = sol_thread_attach;
+ sol_thread_ops.to_detach = sol_thread_detach;
+ sol_thread_ops.to_resume = sol_thread_resume;
+ sol_thread_ops.to_wait = sol_thread_wait;
+ sol_thread_ops.to_fetch_registers = sol_thread_fetch_registers;
+ sol_thread_ops.to_store_registers = sol_thread_store_registers;
+ sol_thread_ops.to_prepare_to_store = sol_thread_prepare_to_store;
+ sol_thread_ops.to_xfer_memory = sol_thread_xfer_memory;
+ sol_thread_ops.to_files_info = sol_thread_files_info;
+ sol_thread_ops.to_insert_breakpoint = memory_insert_breakpoint;
+ sol_thread_ops.to_remove_breakpoint = memory_remove_breakpoint;
+ sol_thread_ops.to_terminal_init = terminal_init_inferior;
+ sol_thread_ops.to_terminal_inferior = terminal_inferior;
+ sol_thread_ops.to_terminal_ours_for_output = terminal_ours_for_output;
+ sol_thread_ops.to_terminal_ours = terminal_ours;
+ sol_thread_ops.to_terminal_info = child_terminal_info;
+ sol_thread_ops.to_kill = sol_thread_kill_inferior;
+ sol_thread_ops.to_load = 0;
+ sol_thread_ops.to_lookup_symbol = 0;
+ sol_thread_ops.to_create_inferior = sol_thread_create_inferior;
+ sol_thread_ops.to_mourn_inferior = sol_thread_mourn_inferior;
+ sol_thread_ops.to_can_run = sol_thread_can_run;
+ sol_thread_ops.to_notice_signals = sol_thread_notice_signals;
+ sol_thread_ops.to_thread_alive = sol_thread_alive;
+ sol_thread_ops.to_stop = sol_thread_stop;
+ sol_thread_ops.to_stratum = process_stratum;
+ sol_thread_ops.to_has_all_memory = 1;
+ sol_thread_ops.to_has_memory = 1;
+ sol_thread_ops.to_has_stack = 1;
+ sol_thread_ops.to_has_registers = 1;
+ sol_thread_ops.to_has_execution = 1;
+ sol_thread_ops.to_has_thread_control = tc_none;
+ sol_thread_ops.to_sections = 0;
+ sol_thread_ops.to_sections_end = 0;
+ sol_thread_ops.to_magic = OPS_MAGIC;
+}
+
+
+static void
+init_sol_core_ops ()
+{
+ sol_core_ops.to_shortname = "solaris-core";
+ sol_core_ops.to_longname = "Solaris core threads and pthread.";
+ sol_core_ops.to_doc = "Solaris threads and pthread support for core files.";
+ sol_core_ops.to_open = sol_core_open;
+ sol_core_ops.to_close = sol_core_close;
+ sol_core_ops.to_attach = sol_thread_attach;
+ sol_core_ops.to_detach = sol_core_detach;
+ /* sol_core_ops.to_resume = 0; */
+ /* sol_core_ops.to_wait = 0; */
+ sol_core_ops.to_fetch_registers = sol_thread_fetch_registers;
+ /* sol_core_ops.to_store_registers = 0; */
+ /* sol_core_ops.to_prepare_to_store = 0; */
+ sol_core_ops.to_xfer_memory = sol_thread_xfer_memory;
+ sol_core_ops.to_files_info = sol_core_files_info;
+ sol_core_ops.to_insert_breakpoint = ignore;
+ sol_core_ops.to_remove_breakpoint = ignore;
+ /* sol_core_ops.to_terminal_init = 0; */
+ /* sol_core_ops.to_terminal_inferior = 0; */
+ /* sol_core_ops.to_terminal_ours_for_output = 0; */
+ /* sol_core_ops.to_terminal_ours = 0; */
+ /* sol_core_ops.to_terminal_info = 0; */
+ /* sol_core_ops.to_kill = 0; */
+ /* sol_core_ops.to_load = 0; */
+ /* sol_core_ops.to_lookup_symbol = 0; */
+ sol_core_ops.to_create_inferior = sol_thread_create_inferior;
+ sol_core_ops.to_stratum = core_stratum;
+ sol_core_ops.to_has_all_memory = 0;
+ sol_core_ops.to_has_memory = 1;
+ sol_core_ops.to_has_stack = 1;
+ sol_core_ops.to_has_registers = 1;
+ sol_core_ops.to_has_execution = 0;
+ sol_core_ops.to_has_thread_control = tc_none;
+ sol_core_ops.to_sections = 0;
+ sol_core_ops.to_sections_end = 0;
+ sol_core_ops.to_magic = OPS_MAGIC;
+}
+
+/* we suppress the call to add_target of core_ops in corelow because
+ if there are two targets in the stratum core_stratum, find_core_target
+ won't know which one to return. see corelow.c for an additonal
+ comment on coreops_suppress_target. */
+int coreops_suppress_target = 1;
+
+void
+_initialize_sol_thread ()
+{
+ void *dlhandle;
+
+ init_sol_thread_ops ();
+ init_sol_core_ops ();
+
+ dlhandle = dlopen ("libthread_db.so.1", RTLD_NOW);
+ if (!dlhandle)
+ goto die;
+
+#define resolve(X) \
+ if (!(p_##X = dlsym (dlhandle, #X))) \
+ goto die;
+
+ resolve (td_log);
+ resolve (td_ta_new);
+ resolve (td_ta_delete);
+ resolve (td_init);
+ resolve (td_ta_get_ph);
+ resolve (td_ta_get_nthreads);
+ resolve (td_ta_tsd_iter);
+ resolve (td_ta_thr_iter);
+ resolve (td_thr_validate);
+ resolve (td_thr_tsd);
+ resolve (td_thr_get_info);
+ resolve (td_thr_getfpregs);
+ resolve (td_thr_getxregsize);
+ resolve (td_thr_getxregs);
+ resolve (td_thr_sigsetmask);
+ resolve (td_thr_setprio);
+ resolve (td_thr_setsigpending);
+ resolve (td_thr_setfpregs);
+ resolve (td_thr_setxregs);
+ resolve (td_ta_map_id2thr);
+ resolve (td_ta_map_lwp2thr);
+ resolve (td_thr_getgregs);
+ resolve (td_thr_setgregs);
+
+ add_target (&sol_thread_ops);
+
+ procfs_suppress_run = 1;
+
+#ifdef MAINTENANCE_CMDS
+ add_cmd ("sol-threads", class_maintenance, info_solthreads,
+ "Show info on Solaris user threads.\n", &maintenanceinfolist);
+#endif /* MAINTENANCE_CMDS */
+
+ memcpy(&orig_core_ops, &core_ops, sizeof (struct target_ops));
+ memcpy(&core_ops, &sol_core_ops, sizeof (struct target_ops));
+ add_target (&core_ops);
+
+ return;
+
+ die:
+
+ fprintf_unfiltered (gdb_stderr, "[GDB will not be able to debug user-mode threads: %s]\n", dlerror ());
+
+ if (dlhandle)
+ dlclose (dlhandle);
+
+ /* allow the user to debug non-threaded core files */
+ add_target(&core_ops);
+
+ return;
+}
diff --git a/gdb/solib.c b/gdb/solib.c
new file mode 100644
index 00000000000..6d6fd4a3a84
--- /dev/null
+++ b/gdb/solib.c
@@ -0,0 +1,1888 @@
+/* Handle SunOS and SVR4 shared libraries for GDB, the GNU Debugger.
+ Copyright 1990, 91, 92, 93, 94, 95, 96, 98, 1999
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+
+#include "defs.h"
+
+/* This file is only compilable if link.h is available. */
+
+#ifdef HAVE_LINK_H
+
+#include <sys/types.h>
+#include <signal.h>
+#include "gdb_string.h"
+#include <sys/param.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#ifndef SVR4_SHARED_LIBS
+ /* SunOS shared libs need the nlist structure. */
+#include <a.out.h>
+#else
+#include "elf/external.h"
+#endif
+
+#include <link.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 "gnu-regex.h"
+#include "inferior.h"
+#include "environ.h"
+#include "language.h"
+#include "gdbcmd.h"
+
+#define MAX_PATH_SIZE 512 /* FIXME: Should be dynamic */
+
+/* On SVR4 systems, a list of symbols in the dynamic linker where
+ GDB can try to place a breakpoint to monitor shared library
+ events.
+
+ If none of these symbols are found, or other errors occur, then
+ SVR4 systems will fall back to using a symbol as the "startup
+ mapping complete" breakpoint address. */
+
+#ifdef SVR4_SHARED_LIBS
+static char *solib_break_names[] = {
+ "r_debug_state",
+ "_r_debug_state",
+ "_dl_debug_state",
+ "rtld_db_dlactivity",
+ NULL
+};
+#endif
+
+#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
+
+/* Symbols which are used to locate the base of the link map structures. */
+
+#ifndef SVR4_SHARED_LIBS
+static char *debug_base_symbols[] = {
+ "_DYNAMIC",
+ "_DYNAMIC__MGC",
+ NULL
+};
+#endif
+
+static char *main_name_list[] = {
+ "main_$main",
+ NULL
+};
+
+/* local data declarations */
+
+#ifndef SVR4_SHARED_LIBS
+
+#define LM_ADDR(so) ((so) -> lm.lm_addr)
+#define LM_NEXT(so) ((so) -> lm.lm_next)
+#define LM_NAME(so) ((so) -> lm.lm_name)
+/* Test for first link map entry; first entry is a shared library. */
+#define IGNORE_FIRST_LINK_MAP_ENTRY(x) (0)
+static struct link_dynamic dynamic_copy;
+static struct link_dynamic_2 ld_2_copy;
+static struct ld_debug debug_copy;
+static CORE_ADDR debug_addr;
+static CORE_ADDR flag_addr;
+
+#else /* SVR4_SHARED_LIBS */
+
+#define LM_ADDR(so) ((so) -> lm.l_addr)
+#define LM_NEXT(so) ((so) -> lm.l_next)
+#define LM_NAME(so) ((so) -> lm.l_name)
+/* Test for first link map entry; first entry is the exec-file. */
+#define IGNORE_FIRST_LINK_MAP_ENTRY(x) ((x).l_prev == NULL)
+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 */
+ struct link_map lm; /* copy of link map from inferior */
+ struct link_map *lmaddr; /* addr in inferior lm was read from */
+ 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 */
+
+static int solib_cleanup_queued = 0; /* make_run_cleanup called */
+
+extern int
+fdmatch PARAMS ((int, int)); /* In libiberty */
+
+/* Local function prototypes */
+
+static void
+do_clear_solib PARAMS ((PTR));
+
+static int
+match_main PARAMS ((char *));
+
+static void
+special_symbol_handling PARAMS ((struct so_list *));
+
+static void
+sharedlibrary_command PARAMS ((char *, int));
+
+static int
+enable_break PARAMS ((void));
+
+static void
+info_sharedlibrary_command PARAMS ((char *, int));
+
+static int symbol_add_stub PARAMS ((PTR));
+
+static struct so_list *
+find_solib PARAMS ((struct so_list *));
+
+static struct link_map *
+first_link_map_member PARAMS ((void));
+
+static CORE_ADDR
+locate_base PARAMS ((void));
+
+static int solib_map_sections PARAMS ((PTR));
+
+#ifdef SVR4_SHARED_LIBS
+
+static CORE_ADDR
+elf_locate_base PARAMS ((void));
+
+#else
+
+static int
+disable_break PARAMS ((void));
+
+static void
+allocate_rt_common_objfile PARAMS ((void));
+
+static void
+solib_add_common_symbols PARAMS ((struct rtc_symb *));
+
+#endif
+
+void _initialize_solib PARAMS ((void));
+
+/* If non-zero, this is a prefix that will be added to the front of the name
+ shared libraries with an absolute filename for loading. */
+static char *solib_absolute_prefix = NULL;
+
+/* If non-empty, this is a search path for loading non-absolute shared library
+ symbol files. This takes precedence over the environment variables PATH
+ and LD_LIBRARY_PATH. */
+static char *solib_search_path = NULL;
+
+/*
+
+LOCAL FUNCTION
+
+ solib_map_sections -- open bfd and build sections for shared lib
+
+SYNOPSIS
+
+ static int 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 int
+solib_map_sections (arg)
+ PTR arg;
+{
+ struct so_list *so = (struct so_list *) arg; /* catch_errors bogon */
+ char *filename;
+ char *scratch_pathname;
+ int scratch_chan;
+ struct section_table *p;
+ struct cleanup *old_chain;
+ bfd *abfd;
+
+ filename = tilde_expand (so -> so_name);
+
+ if (solib_absolute_prefix && ROOTED_P (filename))
+ /* Prefix shared libraries with absolute filenames with
+ SOLIB_ABSOLUTE_PREFIX. */
+ {
+ char *pfxed_fn;
+ int pfx_len;
+
+ pfx_len = strlen (solib_absolute_prefix);
+
+ /* Remove trailing slashes. */
+ while (pfx_len > 0 && SLASH_P (solib_absolute_prefix[pfx_len - 1]))
+ pfx_len--;
+
+ pfxed_fn = xmalloc (pfx_len + strlen (filename) + 1);
+ strcpy (pfxed_fn, solib_absolute_prefix);
+ strcat (pfxed_fn, filename);
+ free (filename);
+
+ filename = pfxed_fn;
+ }
+
+ old_chain = make_cleanup (free, filename);
+
+ scratch_chan = -1;
+
+ if (solib_search_path)
+ scratch_chan = openp (solib_search_path,
+ 1, filename, O_RDONLY, 0, &scratch_pathname);
+ if (scratch_chan < 0)
+ scratch_chan = openp (get_in_environ (inferior_environ, "PATH"),
+ 1, filename, O_RDONLY, 0, &scratch_pathname);
+ if (scratch_chan < 0)
+ {
+ scratch_chan = openp (get_in_environ
+ (inferior_environ, "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_get_error ()));
+ }
+ /* Leave bfd open, core_xfer_memory and "info files" need it. */
+ so -> abfd = abfd;
+ abfd -> cacheable = true;
+
+ /* copy full path name into so_name, so that later symbol_file_add can find
+ it */
+ if (strlen (scratch_pathname) >= MAX_PATH_SIZE)
+ error ("Full path name length of shared library exceeds MAX_PATH_SIZE in so_list structure.");
+ strcpy (so->so_name, scratch_pathname);
+
+ if (!bfd_check_format (abfd, bfd_object))
+ {
+ error ("\"%s\": not in executable format: %s.",
+ scratch_pathname, bfd_errmsg (bfd_get_error ()));
+ }
+ if (build_section_table (abfd, &so -> sections, &so -> sections_end))
+ {
+ error ("Can't find the file sections in `%s': %s",
+ bfd_get_filename (abfd), bfd_errmsg (bfd_get_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 -> the_bfd_section -> name, ".text"))
+ {
+ so -> textsection = p;
+ }
+ }
+
+ /* Free the file names, close the file now. */
+ do_cleanups (old_chain);
+
+ return (1);
+}
+
+#ifndef SVR4_SHARED_LIBS
+
+/* Allocate the runtime common object file. */
+
+static void
+allocate_rt_common_objfile ()
+{
+ struct objfile *objfile;
+ struct objfile *last_one;
+
+ objfile = (struct objfile *) xmalloc (sizeof (struct objfile));
+ memset (objfile, 0, sizeof (struct objfile));
+ objfile -> md = NULL;
+ obstack_specify_allocation (&objfile -> psymbol_cache.cache, 0, 0,
+ xmalloc, free);
+ 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);
+ objfile -> name = mstrsave (objfile -> md, "rt_common");
+
+ /* Add this file onto the tail of the linked list of other such files. */
+
+ objfile -> next = NULL;
+ if (object_files == NULL)
+ object_files = objfile;
+ else
+ {
+ for (last_one = object_files;
+ last_one -> next;
+ last_one = last_one -> next);
+ last_one -> next = objfile;
+ }
+
+ rt_common_objfile = objfile;
+}
+
+/* Read all dynamically loaded common symbol definitions from the inferior
+ and put them into the minimal symbol table for the runtime common
+ objfile. */
+
+static void
+solib_add_common_symbols (rtc_symp)
+ struct rtc_symb *rtc_symp;
+{
+ struct rtc_symb inferior_rtc_symb;
+ struct nlist inferior_rtc_nlist;
+ int len;
+ char *name;
+
+ /* Remove any runtime common symbols from previous runs. */
+
+ if (rt_common_objfile != NULL && rt_common_objfile -> minimal_symbol_count)
+ {
+ obstack_free (&rt_common_objfile -> symbol_obstack, 0);
+ obstack_specify_allocation (&rt_common_objfile -> symbol_obstack, 0, 0,
+ xmalloc, free);
+ rt_common_objfile -> minimal_symbol_count = 0;
+ rt_common_objfile -> msymbols = NULL;
+ }
+
+ init_minimal_symbol_collection ();
+ make_cleanup ((make_cleanup_func) 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.rtc_sp,
+ (char *) &inferior_rtc_nlist,
+ sizeof(inferior_rtc_nlist));
+ if (inferior_rtc_nlist.n_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_nlist.n_value - inferior_rtc_nlist.n_un.n_strx;
+
+ name = xmalloc (len);
+ read_memory ((CORE_ADDR) inferior_rtc_nlist.n_un.n_name, name, len);
+
+ /* Allocate the runtime common objfile if necessary. */
+ if (rt_common_objfile == NULL)
+ allocate_rt_common_objfile ();
+
+ prim_record_minimal_symbol (name, inferior_rtc_nlist.n_value,
+ mst_bss, rt_common_objfile);
+ free (name);
+ }
+ rtc_symp = inferior_rtc_symb.rtc_next;
+ }
+
+ /* Install any minimal symbols that have been collected as the current
+ minimal symbols for the runtime common objfile. */
+
+ install_minimal_symbols (rt_common_objfile);
+}
+
+#endif /* SVR4_SHARED_LIBS */
+
+
+#ifdef SVR4_SHARED_LIBS
+
+static CORE_ADDR
+bfd_lookup_symbol PARAMS ((bfd *, char *));
+
+/*
+
+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).
+*/
+
+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 = bfd_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);
+}
+
+#ifdef HANDLE_SVR4_EXEC_EMULATORS
+
+/*
+ Solaris BCP (the part of Solaris which allows it to run SunOS4
+ a.out files) throws in another wrinkle. Solaris does not fill
+ in the usual a.out link map structures when running BCP programs,
+ the only way to get at them is via groping around in the dynamic
+ linker.
+ 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.
+
+ Note that we can assume nothing about the process state at the time
+ we need to find these structures. We may be stopped on the first
+ instruction 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 char *debug_base_symbols[] = {
+ "r_debug", /* Solaris 2.3 */
+ "_r_debug", /* Solaris 2.1, 2.2 */
+ NULL
+};
+
+static int
+look_for_base PARAMS ((int, CORE_ADDR));
+
+/*
+
+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 debug base symbol 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 = 0;
+ char **symbolp;
+
+ /* 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
+ || (exec_bfd != NULL
+ && 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))
+ {
+ /* FIXME-leak: on failure, might not free all memory associated with
+ interp_bfd. */
+ 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. */
+
+ for (symbolp = debug_base_symbols; *symbolp != NULL; symbolp++)
+ {
+ address = bfd_lookup_symbol (interp_bfd, *symbolp);
+ if (address != 0)
+ {
+ break;
+ }
+ }
+ if (address == 0)
+ {
+ /* FIXME-leak: on failure, might not free all memory associated with
+ interp_bfd. */
+ 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;
+ /* FIXME-leak: on failure, might not free all memory associated with
+ interp_bfd. */
+ bfd_close (interp_bfd);
+ return (1);
+}
+#endif /* HANDLE_SVR4_EXEC_EMULATORS */
+
+/*
+
+LOCAL FUNCTION
+
+ elf_locate_base -- locate the base address of dynamic linker structs
+ for SVR4 elf targets.
+
+SYNOPSIS
+
+ CORE_ADDR elf_locate_base (void)
+
+DESCRIPTION
+
+ For SVR4 elf targets the address of the dynamic linker's runtime
+ structure is contained within the dynamic info section in the
+ executable file. The dynamic section is also mapped into the
+ inferior address space. Because the runtime loader fills in the
+ real address before starting the inferior, we have to read in the
+ dynamic info section from the inferior address space.
+ If there are any errors while trying to find the address, we
+ silently return 0, otherwise the found address is returned.
+
+ */
+
+static CORE_ADDR
+elf_locate_base ()
+{
+ sec_ptr dyninfo_sect;
+ int dyninfo_sect_size;
+ CORE_ADDR dyninfo_addr;
+ char *buf;
+ char *bufend;
+
+ /* Find the start address of the .dynamic section. */
+ dyninfo_sect = bfd_get_section_by_name (exec_bfd, ".dynamic");
+ if (dyninfo_sect == NULL)
+ return 0;
+ dyninfo_addr = bfd_section_vma (exec_bfd, dyninfo_sect);
+
+ /* Read in .dynamic section, silently ignore errors. */
+ dyninfo_sect_size = bfd_section_size (exec_bfd, dyninfo_sect);
+ buf = alloca (dyninfo_sect_size);
+ if (target_read_memory (dyninfo_addr, buf, dyninfo_sect_size))
+ return 0;
+
+ /* Find the DT_DEBUG entry in the the .dynamic section.
+ For mips elf we look for DT_MIPS_RLD_MAP, mips elf apparently has
+ no DT_DEBUG entries. */
+#ifndef TARGET_ELF64
+ for (bufend = buf + dyninfo_sect_size;
+ buf < bufend;
+ buf += sizeof (Elf32_External_Dyn))
+ {
+ Elf32_External_Dyn *x_dynp = (Elf32_External_Dyn *)buf;
+ long dyn_tag;
+ CORE_ADDR dyn_ptr;
+
+ dyn_tag = bfd_h_get_32 (exec_bfd, (bfd_byte *) x_dynp->d_tag);
+ if (dyn_tag == DT_NULL)
+ break;
+ else if (dyn_tag == DT_DEBUG)
+ {
+ dyn_ptr = bfd_h_get_32 (exec_bfd, (bfd_byte *) x_dynp->d_un.d_ptr);
+ return dyn_ptr;
+ }
+#ifdef DT_MIPS_RLD_MAP
+ else if (dyn_tag == DT_MIPS_RLD_MAP)
+ {
+ char pbuf[TARGET_PTR_BIT / HOST_CHAR_BIT];
+
+ /* DT_MIPS_RLD_MAP contains a pointer to the address
+ of the dynamic link structure. */
+ dyn_ptr = bfd_h_get_32 (exec_bfd, (bfd_byte *) x_dynp->d_un.d_ptr);
+ if (target_read_memory (dyn_ptr, pbuf, sizeof (pbuf)))
+ return 0;
+ return extract_unsigned_integer (pbuf, sizeof (pbuf));
+ }
+#endif
+ }
+#else /* ELF64 */
+ for (bufend = buf + dyninfo_sect_size;
+ buf < bufend;
+ buf += sizeof (Elf64_External_Dyn))
+ {
+ Elf64_External_Dyn *x_dynp = (Elf64_External_Dyn *)buf;
+ long dyn_tag;
+ CORE_ADDR dyn_ptr;
+
+ dyn_tag = bfd_h_get_64 (exec_bfd, (bfd_byte *) x_dynp->d_tag);
+ if (dyn_tag == DT_NULL)
+ break;
+ else if (dyn_tag == DT_DEBUG)
+ {
+ dyn_ptr = bfd_h_get_64 (exec_bfd, (bfd_byte *) x_dynp->d_un.d_ptr);
+ return dyn_ptr;
+ }
+ }
+#endif
+
+ /* DT_DEBUG entry not found. */
+ return 0;
+}
+
+#endif /* SVR4_SHARED_LIBS */
+
+/*
+
+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 debug base symbol. 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 a bit more complicated because the address
+ is contained somewhere in the dynamic info section. We have to go
+ to a lot more work to discover the address of the debug base symbol.
+ 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.
+
+ */
+
+static CORE_ADDR
+locate_base ()
+{
+
+#ifndef SVR4_SHARED_LIBS
+
+ struct minimal_symbol *msymbol;
+ CORE_ADDR address = 0;
+ char **symbolp;
+
+ /* For SunOS, we want to limit the search for the debug base symbol to the
+ executable being debugged, since there is a duplicate named symbol in the
+ shared library. We don't want the shared library versions. */
+
+ for (symbolp = debug_base_symbols; *symbolp != NULL; symbolp++)
+ {
+ msymbol = lookup_minimal_symbol (*symbolp, NULL, symfile_objfile);
+ if ((msymbol != NULL) && (SYMBOL_VALUE_ADDRESS (msymbol) != 0))
+ {
+ address = SYMBOL_VALUE_ADDRESS (msymbol);
+ return (address);
+ }
+ }
+ return (0);
+
+#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, try to locate it in the dynamic info
+ section for ELF executables. */
+
+ if (debug_base == 0)
+ {
+ if (exec_bfd != NULL
+ && bfd_get_flavour (exec_bfd) == bfd_target_elf_flavour)
+ debug_base = elf_locate_base ();
+#ifdef HANDLE_SVR4_EXEC_EMULATORS
+ /* Try it the hard way for emulated executables. */
+ else if (inferior_pid != 0 && target_has_execution)
+ proc_iterate_over_mappings (look_for_base);
+#endif
+ }
+ 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.
+*/
+
+static struct link_map *
+first_link_map_member ()
+{
+ struct link_map *lm = NULL;
+
+#ifndef SVR4_SHARED_LIBS
+
+ read_memory (debug_base, (char *) &dynamic_copy, sizeof (dynamic_copy));
+ 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 /* 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;
+ struct link_map *lm = NULL;
+ 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),
+ sizeof (struct link_map));
+ 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;
+
+ if (! solib_cleanup_queued)
+ {
+ make_run_cleanup (do_clear_solib, NULL);
+ solib_cleanup_queued = 1;
+ }
+
+ }
+ so_list_next = new;
+ read_memory ((CORE_ADDR) lm, (char *) &(new -> lm),
+ sizeof (struct link_map));
+ /* For SVR4 versions, the first entry in the link map is for the
+ inferior executable, so we must ignore it. For some versions of
+ SVR4, it has no name. For others (Solaris 2.3 for example), it
+ does have a name, so we can no longer use a missing name to
+ decide when to ignore it. */
+ if (!IGNORE_FIRST_LINK_MAP_ENTRY (new -> lm))
+ {
+ int errcode;
+ char *buffer;
+ target_read_string ((CORE_ADDR) LM_NAME (new), &buffer,
+ MAX_PATH_SIZE - 1, &errcode);
+ if (errcode != 0)
+ {
+ warning ("find_solib: Can't read pathname for load map: %s\n",
+ safe_strerror (errcode));
+ return (so_list_next);
+ }
+ strncpy (new -> so_name, buffer, MAX_PATH_SIZE - 1);
+ new -> so_name[MAX_PATH_SIZE - 1] = '\0';
+ free (buffer);
+ catch_errors (solib_map_sections, new,
+ "Error while mapping shared library sections:\n",
+ RETURN_MASK_ALL);
+ }
+ }
+ return (so_list_next);
+}
+
+/* A small stub to get us past the arg-passing pinhole of catch_errors. */
+
+static int
+symbol_add_stub (arg)
+ PTR arg;
+{
+ register struct so_list *so = (struct so_list *) arg; /* catch_errs bogon */
+ CORE_ADDR text_addr = 0;
+
+ if (so -> textsection)
+ text_addr = so -> textsection -> addr;
+ else if (so -> abfd != NULL)
+ {
+ asection *lowest_sect;
+
+ /* If we didn't find a mapped non zero sized .text section, set up
+ text_addr so that the relocation in symbol_file_add does no harm. */
+
+ lowest_sect = bfd_get_section_by_name (so -> abfd, ".text");
+ if (lowest_sect == NULL)
+ bfd_map_over_sections (so -> abfd, find_lowest_section,
+ (PTR) &lowest_sect);
+ if (lowest_sect)
+ text_addr = bfd_section_vma (so -> abfd, lowest_sect)
+ + (CORE_ADDR) LM_ADDR (so);
+ }
+
+ ALL_OBJFILES (so -> objfile)
+ {
+ if (strcmp (so -> objfile -> name, so -> so_name) == 0)
+ return 1;
+ }
+ so -> objfile =
+ symbol_file_add (so -> so_name, so -> from_tty,
+ text_addr,
+ 0, 0, 0, 0, 1);
+ return (1);
+}
+
+/* This function will check the so name to see if matches the main list.
+ In some system the main object is in the list, which we want to exclude */
+
+static int match_main (soname)
+ char *soname;
+{
+ char **mainp;
+
+ for (mainp = main_name_list; *mainp != NULL; mainp++)
+ {
+ if (strcmp (soname, *mainp) == 0)
+ return (1);
+ }
+
+ return (0);
+}
+
+/*
+
+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);
+ }
+
+ /* 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] && !match_main (so -> so_name))
+ {
+ count += so -> sections_end - so -> sections;
+ }
+ }
+
+ if (count)
+ {
+ int update_coreops;
+
+ /* We must update the to_sections field in the core_ops structure
+ here, otherwise we dereference a potential dangling pointer
+ for each call to target_read/write_memory within this routine. */
+ update_coreops = core_ops.to_sections == target->to_sections;
+
+ /* 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);
+
+ /* Update the to_sections field in the core_ops structure
+ if needed. */
+ if (update_coreops)
+ {
+ core_ops.to_sections = target->to_sections;
+ core_ops.to_sections_end = target->to_sections_end;
+ }
+
+ /* 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;
+ }
+ }
+ }
+ }
+
+ /* Now add the symbol files. */
+ while ((so = find_solib (so)) != NULL)
+ {
+ if (so -> so_name[0] && re_exec (so -> so_name) &&
+ !match_main (so -> so_name))
+ {
+ so -> from_tty = from_tty;
+ if (so -> symbols_loaded)
+ {
+ if (from_tty)
+ {
+ printf_unfiltered ("Symbols already loaded for %s\n", so -> so_name);
+ }
+ }
+ else if (catch_errors
+ (symbol_add_stub, so,
+ "Error while reading shared library symbols:\n",
+ RETURN_MASK_ALL))
+ {
+ so_last = so;
+ so -> symbols_loaded = 1;
+ }
+ }
+ }
+
+ /* Getting new symbols may change our opinion about what is
+ frameless. */
+ if (so_last)
+ reinit_frame_cache ();
+
+ 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;
+ int addr_width;
+ char *addr_fmt;
+
+ if (exec_bfd == NULL)
+ {
+ printf_unfiltered ("No exec file.\n");
+ return;
+ }
+
+#ifndef TARGET_ELF64
+ addr_width = 8+4;
+ addr_fmt = "08l";
+#else
+ addr_width = 16+4;
+ addr_fmt = "016l";
+#endif
+
+ while ((so = find_solib (so)) != NULL)
+ {
+ if (so -> so_name[0])
+ {
+ if (!header_done)
+ {
+ printf_unfiltered("%-*s%-*s%-12s%s\n", addr_width, "From",
+ addr_width, "To", "Syms Read",
+ "Shared Object Library");
+ header_done++;
+ }
+
+ printf_unfiltered ("%-*s", addr_width,
+ local_hex_string_custom ((unsigned long) LM_ADDR (so),
+ addr_fmt));
+ printf_unfiltered ("%-*s", addr_width,
+ local_hex_string_custom ((unsigned long) so -> lmend,
+ addr_fmt));
+ printf_unfiltered ("%-12s", so -> symbols_loaded ? "Yes" : "No");
+ printf_unfiltered ("%s\n", so -> so_name);
+ }
+ }
+ if (so_list_head == NULL)
+ {
+ printf_unfiltered ("No shared libraries loaded at this time.\n");
+ }
+}
+
+/*
+
+GLOBAL FUNCTION
+
+ solib_address -- check to see if an address is in a shared lib
+
+SYNOPSIS
+
+ char * 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.
+ */
+
+char *
+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 (so->so_name);
+ }
+ }
+ 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);
+ if (!bfd_close (so_list_head -> abfd))
+ warning ("cannot close \"%s\": %s",
+ bfd_filename, bfd_errmsg (bfd_get_error ()));
+ }
+ 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;
+}
+
+static void
+do_clear_solib (dummy)
+ PTR dummy;
+{
+ solib_cleanup_queued = 0;
+ clear_solib ();
+}
+
+#ifdef SVR4_SHARED_LIBS
+
+/* Return 1 if PC lies in the dynamic symbol resolution code of the
+ SVR4 run time loader. */
+
+static CORE_ADDR interp_text_sect_low;
+static CORE_ADDR interp_text_sect_high;
+static CORE_ADDR interp_plt_sect_low;
+static CORE_ADDR interp_plt_sect_high;
+
+int
+in_svr4_dynsym_resolve_code (pc)
+ CORE_ADDR pc;
+{
+ return ((pc >= interp_text_sect_low && pc < interp_text_sect_high)
+ || (pc >= interp_plt_sect_low && pc < interp_plt_sect_high)
+ || in_plt_section (pc, NULL));
+}
+#endif
+
+/*
+
+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.
+
+*/
+
+#ifndef SVR4_SHARED_LIBS
+
+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));
+
+ 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 /* 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);
+}
+
+#endif /* #ifdef SVR4_SHARED_LIBS */
+
+/*
+
+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 */
+
+ debug_addr = (CORE_ADDR) dynamic_copy.ldd;
+
+ /* Calc address of `in_debugger' member of debugger interface structure */
+
+ flag_addr = debug_addr + (CORE_ADDR) ((char *) &debug_copy.ldd_in_debugger -
+ (char *) &debug_copy);
+
+ /* 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;
+ asection *interp_sect;
+
+ /* First, remove all the solib event breakpoints. Their addresses
+ may have changed since the last time we ran the program. */
+ remove_solib_event_breakpoints ();
+
+#ifdef SVR4_SHARED_LIBS
+ interp_text_sect_low = interp_text_sect_high = 0;
+ interp_plt_sect_low = interp_plt_sect_high = 0;
+
+ /* Find the .interp section; if not found, warn the user and drop
+ into the old breakpoint at symbol code. */
+ interp_sect = bfd_get_section_by_name (exec_bfd, ".interp");
+ if (interp_sect)
+ {
+ unsigned int interp_sect_size;
+ char *buf;
+ CORE_ADDR load_addr;
+ bfd *tmp_bfd;
+ CORE_ADDR sym_addr = 0;
+
+ /* Read the contents of the .interp section into a local buffer;
+ the contents specify the dynamic linker this program uses. */
+ interp_sect_size = bfd_section_size (exec_bfd, interp_sect);
+ buf = alloca (interp_sect_size);
+ bfd_get_section_contents (exec_bfd, interp_sect,
+ buf, 0, interp_sect_size);
+
+ /* Now we need to figure out where the dynamic linker was
+ loaded so that we can load its symbols and place a breakpoint
+ in the dynamic linker itself.
+
+ This address is stored on the stack. However, I've been unable
+ to find any magic formula to find it for Solaris (appears to
+ be trivial on GNU/Linux). Therefore, we have to try an alternate
+ mechanism to find the dynamic linker's base address. */
+ tmp_bfd = bfd_openr (buf, gnutarget);
+ if (tmp_bfd == NULL)
+ goto bkpt_at_symbol;
+
+ /* Make sure the dynamic linker's really a useful object. */
+ if (!bfd_check_format (tmp_bfd, bfd_object))
+ {
+ warning ("Unable to grok dynamic linker %s as an object file", buf);
+ bfd_close (tmp_bfd);
+ goto bkpt_at_symbol;
+ }
+
+ /* We find the dynamic linker's base address by examining the
+ current pc (which point at the entry point for the dynamic
+ linker) and subtracting the offset of the entry point. */
+ load_addr = read_pc () - tmp_bfd->start_address;
+
+ /* Record the relocated start and end address of the dynamic linker
+ text and plt section for in_svr4_dynsym_resolve_code. */
+ interp_sect = bfd_get_section_by_name (tmp_bfd, ".text");
+ if (interp_sect)
+ {
+ interp_text_sect_low =
+ bfd_section_vma (tmp_bfd, interp_sect) + load_addr;
+ interp_text_sect_high =
+ interp_text_sect_low + bfd_section_size (tmp_bfd, interp_sect);
+ }
+ interp_sect = bfd_get_section_by_name (tmp_bfd, ".plt");
+ if (interp_sect)
+ {
+ interp_plt_sect_low =
+ bfd_section_vma (tmp_bfd, interp_sect) + load_addr;
+ interp_plt_sect_high =
+ interp_plt_sect_low + bfd_section_size (tmp_bfd, interp_sect);
+ }
+
+ /* Now try to set a breakpoint in the dynamic linker. */
+ for (bkpt_namep = solib_break_names; *bkpt_namep != NULL; bkpt_namep++)
+ {
+ sym_addr = bfd_lookup_symbol (tmp_bfd, *bkpt_namep);
+ if (sym_addr != 0)
+ break;
+ }
+
+ /* We're done with the temporary bfd. */
+ bfd_close (tmp_bfd);
+
+ if (sym_addr != 0)
+ {
+ create_solib_event_breakpoint (load_addr + sym_addr);
+ return 1;
+ }
+
+ /* For whatever reason we couldn't set a breakpoint in the dynamic
+ linker. Warn and drop into the old code. */
+bkpt_at_symbol:
+ warning ("Unable to find dynamic linker breakpoint function.\nGDB will be unable to debug shared library initializers\nand track explicitly loaded dynamic code.");
+ }
+#endif
+
+ /* 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, NULL, symfile_objfile);
+ if ((msymbol != NULL) && (SYMBOL_VALUE_ADDRESS (msymbol) != 0))
+ {
+ create_solib_event_breakpoint (SYMBOL_VALUE_ADDRESS (msymbol));
+ return 1;
+ }
+ }
+
+ /* Nothing good happened. */
+ success = 0;
+
+#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;
+ }
+
+#if !defined(SVR4_SHARED_LIBS) || defined(_SCO_DS)
+ /* SCO and SunOS need the loop below, other systems should be using the
+ special shared library breakpoints and the shared library breakpoint
+ service routine.
+
+ 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 = TARGET_SIGNAL_0;
+ do
+ {
+ target_resume (-1, 0, stop_signal);
+ wait_for_inferior ();
+ }
+ while (stop_signal != TARGET_SIGNAL_TRAP);
+ stop_soon_quietly = 0;
+
+#if !defined(_SCO_DS)
+ /* 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");
+ }
+
+ if (auto_solib_add)
+ solib_add ((char *) 0, 0, (struct target_ops *) 0);
+#endif /* ! _SCO_DS */
+#endif
+}
+
+/*
+
+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 SunOS4, 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 runtime common
+ 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). */
+
+ debug_addr = (CORE_ADDR) dynamic_copy.ldd;
+ }
+
+ /* 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. */
+
+ if (debug_copy.ldd_cp)
+ {
+ solib_add_common_symbols (debug_copy.ldd_cp);
+ }
+
+#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);
+}
+
+#endif /* HAVE_LINK_H */
+
+void
+_initialize_solib()
+{
+#ifdef HAVE_LINK_H
+
+ 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.");
+
+ add_show_from_set
+ (add_set_cmd ("auto-solib-add", class_support, var_zinteger,
+ (char *) &auto_solib_add,
+ "Set autoloading of shared library symbols.\n\
+If nonzero, symbols from all shared object libraries will be loaded\n\
+automatically when the inferior begins execution or when the dynamic linker\n\
+informs gdb that a new library has been loaded. Otherwise, symbols\n\
+must be loaded manually, using `sharedlibrary'.",
+ &setlist),
+ &showlist);
+
+ add_show_from_set
+ (add_set_cmd ("solib-absolute-prefix", class_support, var_filename,
+ (char *) &solib_absolute_prefix,
+ "Set prefix for loading absolute shared library symbol files.\n\
+For other (relative) files, you can add values using `set solib-search-path'.",
+ &setlist),
+ &showlist);
+ add_show_from_set
+ (add_set_cmd ("solib-search-path", class_support, var_string,
+ (char *) &solib_search_path,
+ "Set the search path for loading non-absolute shared library symbol files.\n\
+This takes precedence over the environment variables PATH and LD_LIBRARY_PATH.",
+ &setlist),
+ &showlist);
+
+#endif /* HAVE_LINK_H */
+}
diff --git a/gdb/solib.h b/gdb/solib.h
new file mode 100644
index 00000000000..eafef48b2b9
--- /dev/null
+++ b/gdb/solib.h
@@ -0,0 +1,203 @@
+/* Shared library declarations for GDB, the GNU Debugger.
+ Copyright (C) 1992, 1998 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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()
+
+/* Function to be called to remove the connection between debugger and
+ dynamic linker that was established by SOLIB_CREATE_INFERIOR_HOOK.
+ (This operation does not remove shared library information from
+ the debugger, as CLEAR_SOLIB does.)
+
+ This functionality is presently not implemented for this target.
+ */
+#define SOLIB_REMOVE_INFERIOR_HOOK(PID) (0)
+
+extern void
+solib_create_inferior_hook PARAMS((void)); /* solib.c */
+
+/* This function is called by the "catch load" command. It allows
+ the debugger to be notified by the dynamic linker when a specified
+ library file (or any library file, if filename is NULL) is loaded.
+
+ Presently, this functionality is not implemented.
+ */
+#define SOLIB_CREATE_CATCH_LOAD_HOOK(pid,tempflag,filename,cond_string) \
+ error("catch of library loads/unloads not yet implemented on this platform")
+
+/* This function is called by the "catch unload" command. It allows
+ the debugger to be notified by the dynamic linker when a specified
+ library file (or any library file, if filename is NULL) is unloaded.
+
+ Presently, this functionality is not implemented.
+ */
+#define SOLIB_CREATE_CATCH_UNLOAD_HOOK(pid,tempflag,filename,cond_string) \
+ error("catch of library loads/unloads not yet implemented on this platform")
+
+/* This function returns TRUE if the dynamic linker has just reported
+ a load of a library.
+
+ This function must be used only when the inferior has stopped in
+ the dynamic linker hook, or undefined results are guaranteed.
+
+ Presently, this functionality is not implemented.
+ */
+
+/*
+#define SOLIB_HAVE_LOAD_EVENT(pid) \
+ error("catch of library loads/unloads not yet implemented on this platform")
+*/
+
+#define SOLIB_HAVE_LOAD_EVENT(pid) \
+(0)
+
+/* This function returns a pointer to the string representation of the
+ pathname of the dynamically-linked library that has just been loaded.
+
+ This function must be used only when SOLIB_HAVE_LOAD_EVENT is TRUE,
+ or undefined results are guaranteed.
+
+ This string's contents are only valid immediately after the inferior
+ has stopped in the dynamic linker hook, and becomes invalid as soon
+ as the inferior is continued. Clients should make a copy of this
+ string if they wish to continue the inferior and then access the string.
+
+ Presently, this functionality is not implemented.
+ */
+
+/*
+#define SOLIB_LOADED_LIBRARY_PATHNAME(pid) \
+ error("catch of library loads/unloads not yet implemented on this platform")
+*/
+
+#define SOLIB_LOADED_LIBRARY_PATHNAME(pid) \
+(0)
+
+/* This function returns TRUE if the dynamic linker has just reported
+ an unload of a library.
+
+ This function must be used only when the inferior has stopped in
+ the dynamic linker hook, or undefined results are guaranteed.
+
+ Presently, this functionality is not implemented.
+ */
+/*
+#define SOLIB_HAVE_UNLOAD_EVENT(pid) \
+ error("catch of library loads/unloads not yet implemented on this platform")
+*/
+
+#define SOLIB_HAVE_UNLOAD_EVENT(pid) \
+(0)
+
+/* This function returns a pointer to the string representation of the
+ pathname of the dynamically-linked library that has just been unloaded.
+
+ This function must be used only when SOLIB_HAVE_UNLOAD_EVENT is TRUE,
+ or undefined results are guaranteed.
+
+ This string's contents are only valid immediately after the inferior
+ has stopped in the dynamic linker hook, and becomes invalid as soon
+ as the inferior is continued. Clients should make a copy of this
+ string if they wish to continue the inferior and then access the string.
+
+ Presently, this functionality is not implemented.
+ */
+/*
+#define SOLIB_UNLOADED_LIBRARY_PATHNAME(pid) \
+ error("catch of library loads/unloads not yet implemented on this platform")
+*/
+
+#define SOLIB_UNLOADED_LIBRARY_PATHNAME(pid) \
+(0)
+
+/* This function returns TRUE if pc is the address of an instruction that
+ lies within the dynamic linker (such as the event hook, or the dld
+ itself).
+
+ This function must be used only when a dynamic linker event has been
+ caught, and the inferior is being stepped out of the hook, or undefined
+ results are guaranteed.
+
+ Presently, this functionality is not implemented.
+ */
+
+/*
+#define SOLIB_IN_DYNAMIC_LINKER(pid,pc) \
+ error("catch of library loads/unloads not yet implemented on this platform")
+*/
+
+#define SOLIB_IN_DYNAMIC_LINKER(pid,pc) \
+(0)
+
+/* This function must be called when the inferior is killed, and the program
+ restarted. This is not the same as CLEAR_SOLIB, in that it doesn't discard
+ any symbol tables.
+
+ Presently, this functionality is not implemented.
+ */
+#define SOLIB_RESTART() \
+ (0)
+
+/* 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) != NULL)
+
+extern char *
+solib_address PARAMS ((CORE_ADDR)); /* solib.c */
+
+/* If ADDR lies in a shared library, return its name. */
+
+#define PC_SOLIB(addr) solib_address (addr)
+
+#ifdef SVR4_SHARED_LIBS
+
+/* Return 1 if PC lies in the dynamic symbol resolution code of the
+ SVR4 run time loader. */
+
+#define IN_SOLIB_DYNSYM_RESOLVE_CODE(pc) in_svr4_dynsym_resolve_code (pc)
+
+extern int
+in_svr4_dynsym_resolve_code PARAMS ((CORE_ADDR));
+
+#endif
diff --git a/gdb/somread.c b/gdb/somread.c
new file mode 100644
index 00000000000..c03abd01832
--- /dev/null
+++ b/gdb/somread.c
@@ -0,0 +1,803 @@
+/* Read HP PA/Risc object files for GDB.
+ Copyright 1991, 1992, 1996 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "bfd.h"
+#include <syms.h>
+#include "symtab.h"
+#include "symfile.h"
+#include "objfiles.h"
+#include "buildsym.h"
+#include "stabsread.h"
+#include "gdb-stabs.h"
+#include "complaints.h"
+#include "gdb_string.h"
+#include "demangle.h"
+#include "som.h"
+#include "libhppa.h"
+
+/* Various things we might complain about... */
+
+static void
+som_symfile_init PARAMS ((struct objfile *));
+
+static void
+som_new_init PARAMS ((struct objfile *));
+
+static void
+som_symfile_read PARAMS ((struct objfile *, struct section_offsets *, int));
+
+static void
+som_symfile_finish PARAMS ((struct objfile *));
+
+static void
+som_symtab_read PARAMS ((bfd *, struct objfile *,
+ struct section_offsets *));
+
+static struct section_offsets *
+som_symfile_offsets PARAMS ((struct objfile *, CORE_ADDR));
+
+/* FIXME: These should really be in a common header somewhere */
+
+extern void
+hpread_build_psymtabs PARAMS ((struct objfile *, struct section_offsets *, int));
+
+extern void
+hpread_symfile_finish PARAMS ((struct objfile *));
+
+extern void
+hpread_symfile_init PARAMS ((struct objfile *));
+
+extern void
+do_pxdb PARAMS ((bfd *));
+
+/*
+
+LOCAL FUNCTION
+
+ som_symtab_read -- read the symbol table of a SOM file
+
+SYNOPSIS
+
+ void som_symtab_read (bfd *abfd, struct objfile *objfile,
+ struct section_offsets *section_offsets)
+
+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
+som_symtab_read (abfd, objfile, section_offsets)
+ bfd *abfd;
+ struct objfile *objfile;
+ struct section_offsets *section_offsets;
+{
+ unsigned int number_of_symbols;
+ int val, dynamic;
+ char *stringtab;
+ asection *shlib_info;
+ struct symbol_dictionary_record *buf, *bufp, *endbufp;
+ char *symname;
+ CONST int symsize = sizeof (struct symbol_dictionary_record);
+ CORE_ADDR text_offset, data_offset;
+
+
+ text_offset = ANOFFSET (section_offsets, 0);
+ data_offset = ANOFFSET (section_offsets, 1);
+
+ number_of_symbols = bfd_get_symcount (abfd);
+
+ buf = alloca (symsize * number_of_symbols);
+ bfd_seek (abfd, obj_som_sym_filepos (abfd), SEEK_SET);
+ val = bfd_read (buf, symsize * number_of_symbols, 1, abfd);
+ if (val != symsize * number_of_symbols)
+ error ("Couldn't read symbol dictionary!");
+
+ stringtab = alloca (obj_som_stringtab_size (abfd));
+ bfd_seek (abfd, obj_som_str_filepos (abfd), SEEK_SET);
+ val = bfd_read (stringtab, obj_som_stringtab_size (abfd), 1, abfd);
+ if (val != obj_som_stringtab_size (abfd))
+ error ("Can't read in HP string table.");
+
+ /* We need to determine if objfile is a dynamic executable (so we
+ can do the right thing for ST_ENTRY vs ST_CODE symbols).
+
+ There's nothing in the header which easily allows us to do
+ this. The only reliable way I know of is to check for the
+ existance of a $SHLIB_INFO$ section with a non-zero size. */
+ /* The code below is not a reliable way to check whether an
+ * executable is dynamic, so I commented it out - RT
+ * shlib_info = bfd_get_section_by_name (objfile->obfd, "$SHLIB_INFO$");
+ * if (shlib_info)
+ * dynamic = (bfd_section_size (objfile->obfd, shlib_info) != 0);
+ * else
+ * dynamic = 0;
+ */
+ /* I replaced the code with a simple check for text offset not being
+ * zero. Still not 100% reliable, but a more reliable way of asking
+ * "is this a dynamic executable?" than the above. RT
+ */
+ dynamic = (text_offset != 0);
+
+ endbufp = buf + number_of_symbols;
+ for (bufp = buf; bufp < endbufp; ++bufp)
+ {
+ enum minimal_symbol_type ms_type;
+
+ QUIT;
+
+ switch (bufp->symbol_scope)
+ {
+ case SS_UNIVERSAL:
+ case SS_EXTERNAL:
+ switch (bufp->symbol_type)
+ {
+ case ST_SYM_EXT:
+ case ST_ARG_EXT:
+ continue;
+
+ case ST_CODE:
+ case ST_PRI_PROG:
+ case ST_SEC_PROG:
+ case ST_MILLICODE:
+ symname = bufp->name.n_strx + stringtab;
+ ms_type = mst_text;
+ bufp->symbol_value += text_offset;
+#ifdef SMASH_TEXT_ADDRESS
+ SMASH_TEXT_ADDRESS (bufp->symbol_value);
+#endif
+ break;
+
+ case ST_ENTRY:
+ symname = bufp->name.n_strx + stringtab;
+ /* For a dynamic executable, ST_ENTRY symbols are
+ the stubs, while the ST_CODE symbol is the real
+ function. */
+ if (dynamic)
+ ms_type = mst_solib_trampoline;
+ else
+ ms_type = mst_text;
+ bufp->symbol_value += text_offset;
+#ifdef SMASH_TEXT_ADDRESS
+ SMASH_TEXT_ADDRESS (bufp->symbol_value);
+#endif
+ break;
+
+ case ST_STUB:
+ symname = bufp->name.n_strx + stringtab;
+ ms_type = mst_solib_trampoline;
+ bufp->symbol_value += text_offset;
+#ifdef SMASH_TEXT_ADDRESS
+ SMASH_TEXT_ADDRESS (bufp->symbol_value);
+#endif
+ break;
+
+ case ST_DATA:
+ symname = bufp->name.n_strx + stringtab;
+ bufp->symbol_value += data_offset;
+ ms_type = mst_data;
+ break;
+ default:
+ continue;
+ }
+ break;
+
+#if 0
+ /* SS_GLOBAL and SS_LOCAL are two names for the same thing (!). */
+ case SS_GLOBAL:
+#endif
+ case SS_LOCAL:
+ switch (bufp->symbol_type)
+ {
+ case ST_SYM_EXT:
+ case ST_ARG_EXT:
+ continue;
+
+ case ST_CODE:
+ symname = bufp->name.n_strx + stringtab;
+ ms_type = mst_file_text;
+ bufp->symbol_value += text_offset;
+#ifdef SMASH_TEXT_ADDRESS
+ SMASH_TEXT_ADDRESS (bufp->symbol_value);
+#endif
+
+ check_strange_names:
+ /* Utah GCC 2.5, FSF GCC 2.6 and later generate correct local
+ label prefixes for stabs, constant data, etc. So we need
+ only filter out L$ symbols which are left in due to
+ limitations in how GAS generates SOM relocations.
+
+ When linking in the HPUX C-library the HP linker has
+ the nasty habit of placing section symbols from the literal
+ subspaces in the middle of the program's text. Filter
+ those out as best we can. Check for first and last character
+ being '$'.
+
+ And finally, the newer HP compilers emit crud like $PIC_foo$N
+ in some circumstance (PIC code I guess). It's also claimed
+ that they emit D$ symbols too. What stupidity. */
+ if ((symname[0] == 'L' && symname[1] == '$')
+ || (symname[0] == '$' && symname[strlen(symname) - 1] == '$')
+ || (symname[0] == 'D' && symname[1] == '$')
+ || (strncmp (symname, "$PIC", 4) == 0))
+ continue;
+ break;
+
+ case ST_PRI_PROG:
+ case ST_SEC_PROG:
+ case ST_MILLICODE:
+ symname = bufp->name.n_strx + stringtab;
+ ms_type = mst_file_text;
+ bufp->symbol_value += text_offset;
+#ifdef SMASH_TEXT_ADDRESS
+ SMASH_TEXT_ADDRESS (bufp->symbol_value);
+#endif
+ break;
+
+ case ST_ENTRY:
+ symname = bufp->name.n_strx + stringtab;
+ /* For a dynamic executable, ST_ENTRY symbols are
+ the stubs, while the ST_CODE symbol is the real
+ function. */
+ if (dynamic)
+ ms_type = mst_solib_trampoline;
+ else
+ ms_type = mst_file_text;
+ bufp->symbol_value += text_offset;
+#ifdef SMASH_TEXT_ADDRESS
+ SMASH_TEXT_ADDRESS (bufp->symbol_value);
+#endif
+ break;
+
+ case ST_STUB:
+ symname = bufp->name.n_strx + stringtab;
+ ms_type = mst_solib_trampoline;
+ bufp->symbol_value += text_offset;
+#ifdef SMASH_TEXT_ADDRESS
+ SMASH_TEXT_ADDRESS (bufp->symbol_value);
+#endif
+ break;
+
+
+ case ST_DATA:
+ symname = bufp->name.n_strx + stringtab;
+ bufp->symbol_value += data_offset;
+ ms_type = mst_file_data;
+ goto check_strange_names;
+
+ default:
+ continue;
+ }
+ break;
+
+ /* This can happen for common symbols when -E is passed to the
+ final link. No idea _why_ that would make the linker force
+ common symbols to have an SS_UNSAT scope, but it does.
+
+ This also happens for weak symbols, but their type is
+ ST_DATA. */
+ case SS_UNSAT:
+ switch (bufp->symbol_type)
+ {
+ case ST_STORAGE:
+ case ST_DATA:
+ symname = bufp->name.n_strx + stringtab;
+ bufp->symbol_value += data_offset;
+ ms_type = mst_data;
+ break;
+
+ default:
+ continue;
+ }
+ break;
+
+ default:
+ continue;
+ }
+
+ if (bufp->name.n_strx > obj_som_stringtab_size (abfd))
+ error ("Invalid symbol data; bad HP string table offset: %d",
+ bufp->name.n_strx);
+
+ prim_record_minimal_symbol (symname, bufp->symbol_value, ms_type,
+ objfile);
+ }
+}
+
+/* Scan and build partial symbols for a symbol file.
+ We have been initialized by a call to som_symfile_init, which
+ currently does nothing.
+
+ SECTION_OFFSETS is a set of offsets to apply to relocate the symbols
+ in each section. This is ignored, as it isn't needed for SOM.
+
+ 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!!!
+
+ somstab_build_psymtabs() handles STABS symbols.
+
+ Note that SOM files have a "minimal" symbol table, which is vaguely
+ reminiscent of 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
+som_symfile_read (objfile, section_offsets, mainline)
+ struct objfile *objfile;
+ struct section_offsets *section_offsets;
+ int mainline;
+{
+ bfd *abfd = objfile->obfd;
+ struct cleanup *back_to;
+
+ do_pxdb (symfile_bfd_open (objfile->name));
+
+ init_minimal_symbol_collection ();
+ back_to = make_cleanup ((make_cleanup_func) discard_minimal_symbols, 0);
+
+ /* Read in the import list and the export list. Currently
+ the export list isn't used; the import list is used in
+ hp-symtab-read.c to handle static vars declared in other
+ shared libraries. */
+ init_import_symbols (objfile);
+#if 0 /* Export symbols not used today 1997-08-05 */
+ init_export_symbols (objfile);
+#else
+ objfile->export_list = NULL;
+ objfile->export_list_size = 0;
+#endif
+
+ /* Process the normal SOM symbol table first.
+ This reads in the DNTT and string table, but doesn't
+ actually scan the DNTT. It does scan the linker symbol
+ table and thus build up a "minimal symbol table". */
+
+ som_symtab_read (abfd, objfile, section_offsets);
+
+ /* Now read information from the stabs debug sections.
+ This is a no-op for SOM.
+ Perhaps it is intended for some kind of mixed STABS/SOM
+ situation? */
+ stabsect_build_psymtabs (objfile, section_offsets, mainline,
+ "$GDB_SYMBOLS$", "$GDB_STRINGS$", "$TEXT$");
+
+ /* Now read the native debug information.
+ This builds the psymtab. This used to be done via a scan of
+ the DNTT, but is now done via the PXDB-built quick-lookup tables
+ together with a scan of the GNTT. See hp-psymtab-read.c. */
+ hpread_build_psymtabs (objfile, section_offsets, mainline);
+
+ /* Install any minimal symbols that have been collected as the current
+ minimal symbols for this objfile.
+ Further symbol-reading is done incrementally, file-by-file,
+ in a step known as "psymtab-to-symtab" expansion. hp-symtab-read.c
+ contains the code to do the actual DNTT scanning and symtab building. */
+ install_minimal_symbols (objfile);
+
+ /* Force hppa-tdep.c to re-read the unwind descriptors. */
+ objfile->obj_private = NULL;
+ 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).
+
+ We reinitialize buildsym, since we may be reading stabs from a SOM file. */
+
+static void
+som_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
+som_symfile_finish (objfile)
+ struct objfile *objfile;
+{
+ if (objfile -> sym_stab_info != NULL)
+ {
+ mfree (objfile -> md, objfile -> sym_stab_info);
+ }
+ hpread_symfile_finish (objfile);
+}
+
+/* SOM specific initialization routine for reading symbols. */
+
+static void
+som_symfile_init (objfile)
+ struct objfile *objfile;
+{
+ /* SOM objects may be reordered, so set OBJF_REORDERED. If we
+ find this causes a significant slowdown in gdb then we could
+ set it in the debug symbol readers only when necessary. */
+ objfile->flags |= OBJF_REORDERED;
+ hpread_symfile_init (objfile);
+}
+
+/* SOM specific parsing routine for section offsets.
+
+ Plain and simple for now. */
+
+static struct section_offsets *
+som_symfile_offsets (objfile, addr)
+ struct objfile *objfile;
+ CORE_ADDR addr;
+{
+ struct section_offsets *section_offsets;
+ int i;
+
+ objfile->num_sections = SECT_OFF_MAX;
+ section_offsets = (struct section_offsets *)
+ obstack_alloc (&objfile -> psymbol_obstack, SIZEOF_SECTION_OFFSETS);
+
+ /* First see if we're a shared library. If so, get the section
+ offsets from the library, else get them from addr. */
+ if (!som_solib_section_offsets (objfile, section_offsets))
+ {
+ for (i = 0; i < SECT_OFF_MAX; i++)
+ ANOFFSET (section_offsets, i) = addr;
+ }
+
+ return section_offsets;
+}
+
+
+
+/* Check if a given symbol NAME is in the import list
+ of OBJFILE.
+ 1 => true, 0 => false
+ This is used in hp_symtab_read.c to deal with static variables
+ that are defined in a different shared library than the one
+ whose symbols are being processed. */
+
+int is_in_import_list (name, objfile)
+ char * name;
+ struct objfile * objfile;
+{
+ register int i;
+
+ if (!objfile ||
+ !name ||
+ !*name)
+ return 0;
+
+ for (i=0; i < objfile->import_list_size; i++)
+ if (objfile->import_list[i] && STREQ (name, objfile->import_list[i]))
+ return 1;
+ return 0;
+}
+
+
+/* Read in and initialize the SOM import list which is present
+ for all executables and shared libraries. The import list
+ consists of the symbols that are referenced in OBJFILE but
+ not defined there. (Variables that are imported are dealt
+ with as "loc_indirect" vars.)
+ Return value = number of import symbols read in. */
+int
+init_import_symbols (objfile)
+ struct objfile * objfile;
+{
+ unsigned int import_list;
+ unsigned int import_list_size;
+ unsigned int string_table;
+ unsigned int string_table_size;
+ char * string_buffer;
+ register int i;
+ register int j;
+ register int k;
+ asection * text_section; /* section handle */
+ unsigned int dl_header[12]; /* SOM executable header */
+
+ /* A struct for an entry in the SOM import list */
+ typedef struct {
+ int name; /* index into the string table */
+ short dont_care1; /* we don't use this */
+ unsigned char type; /* 0 = NULL, 2 = Data, 3 = Code, 7 = Storage, 13 = Plabel */
+ unsigned int reserved2 : 8; /* not used */
+ } SomImportEntry;
+
+ /* We read 100 entries in at a time from the disk file. */
+# define SOM_READ_IMPORTS_NUM 100
+# define SOM_READ_IMPORTS_CHUNK_SIZE (sizeof (SomImportEntry) * SOM_READ_IMPORTS_NUM)
+ SomImportEntry buffer[SOM_READ_IMPORTS_NUM];
+
+ /* Initialize in case we error out */
+ objfile->import_list = NULL;
+ objfile->import_list_size = 0;
+
+#if 0 /* DEBUGGING */
+ printf ("Processing import list for %s\n", objfile->name);
+#endif
+
+ /* It doesn't work, for some reason, to read in space $TEXT$;
+ the subspace $SHLIB_INFO$ has to be used. Some BFD quirk? pai/1997-08-05 */
+ text_section = bfd_get_section_by_name (objfile->obfd, "$SHLIB_INFO$");
+ if (!text_section)
+ return 0;
+ /* Get the SOM executable header */
+ bfd_get_section_contents (objfile->obfd, text_section, dl_header, 0, 12 * sizeof (int));
+
+ /* Check header version number for 10.x HP-UX */
+ /* Currently we deal only with 10.x systems; on 9.x the version # is 89060912.
+ FIXME: Change for future HP-UX releases and mods to the SOM executable format */
+ if (dl_header[0] != 93092112)
+ return 0;
+
+ import_list = dl_header[4];
+ import_list_size = dl_header[5];
+ if (!import_list_size)
+ return 0;
+ string_table = dl_header[10];
+ string_table_size = dl_header[11];
+ if (!string_table_size)
+ return 0;
+
+ /* Suck in SOM string table */
+ string_buffer = (char *) xmalloc (string_table_size);
+ bfd_get_section_contents (objfile->obfd, text_section, string_buffer,
+ string_table, string_table_size);
+
+ /* Allocate import list in the psymbol obstack; this has nothing
+ to do with psymbols, just a matter of convenience. We want the
+ import list to be freed when the objfile is deallocated */
+ objfile->import_list
+ = (ImportEntry *) obstack_alloc (&objfile->psymbol_obstack,
+ import_list_size * sizeof (ImportEntry));
+
+ /* Read in the import entries, a bunch at a time */
+ for (j=0, k=0;
+ j < (import_list_size / SOM_READ_IMPORTS_NUM);
+ j++)
+ {
+ bfd_get_section_contents (objfile->obfd, text_section, buffer,
+ import_list + j * SOM_READ_IMPORTS_CHUNK_SIZE,
+ SOM_READ_IMPORTS_CHUNK_SIZE);
+ for (i=0; i < SOM_READ_IMPORTS_NUM; i++, k++)
+ {
+ if (buffer[i].type != (unsigned char) 0)
+ {
+ objfile->import_list[k]
+ = (char *) obstack_alloc (&objfile->psymbol_obstack, strlen (string_buffer + buffer[i].name) + 1);
+ strcpy (objfile->import_list[k], string_buffer + buffer[i].name);
+ /* Some day we might want to record the type and other information too */
+ }
+ else /* null type */
+ objfile->import_list[k] = NULL;
+
+#if 0 /* DEBUGGING */
+ printf ("Import String %d:%d (%d), type %d is %s\n", j, i, k,
+ (int) buffer[i].type, objfile->import_list[k]);
+#endif
+ }
+ }
+
+ /* Get the leftovers */
+ if (k < import_list_size)
+ bfd_get_section_contents (objfile->obfd, text_section, buffer,
+ import_list + k * sizeof (SomImportEntry),
+ (import_list_size - k) * sizeof (SomImportEntry));
+ for (i=0; k < import_list_size; i++, k++)
+ {
+ if (buffer[i].type != (unsigned char) 0)
+ {
+ objfile->import_list[k]
+ = (char *) obstack_alloc (&objfile->psymbol_obstack, strlen (string_buffer + buffer[i].name) + 1);
+ strcpy (objfile->import_list[k], string_buffer + buffer[i].name);
+ /* Some day we might want to record the type and other information too */
+ }
+ else
+ objfile->import_list[k] = NULL;
+#if 0 /* DEBUGGING */
+ printf ("Import String F:%d (%d), type %d, is %s\n", i, k,
+ (int) buffer[i].type, objfile->import_list[k]);
+#endif
+ }
+
+ objfile->import_list_size = import_list_size;
+ free (string_buffer);
+ return import_list_size;
+}
+
+/* Read in and initialize the SOM export list which is present
+ for all executables and shared libraries. The import list
+ consists of the symbols that are referenced in OBJFILE but
+ not defined there. (Variables that are imported are dealt
+ with as "loc_indirect" vars.)
+ Return value = number of import symbols read in. */
+int
+init_export_symbols (objfile)
+ struct objfile * objfile;
+{
+ unsigned int export_list;
+ unsigned int export_list_size;
+ unsigned int string_table;
+ unsigned int string_table_size;
+ char * string_buffer;
+ register int i;
+ register int j;
+ register int k;
+ asection * text_section; /* section handle */
+ unsigned int dl_header[12]; /* SOM executable header */
+
+ /* A struct for an entry in the SOM export list */
+ typedef struct {
+ int next; /* for hash table use -- we don't use this */
+ int name; /* index into string table */
+ int value; /* offset or plabel */
+ int dont_care1; /* not used */
+ unsigned char type; /* 0 = NULL, 2 = Data, 3 = Code, 7 = Storage, 13 = Plabel */
+ char dont_care2; /* not used */
+ short dont_care3; /* not used */
+ } SomExportEntry;
+
+ /* We read 100 entries in at a time from the disk file. */
+# define SOM_READ_EXPORTS_NUM 100
+# define SOM_READ_EXPORTS_CHUNK_SIZE (sizeof (SomExportEntry) * SOM_READ_EXPORTS_NUM)
+ SomExportEntry buffer[SOM_READ_EXPORTS_NUM];
+
+ /* Initialize in case we error out */
+ objfile->export_list = NULL;
+ objfile->export_list_size = 0;
+
+#if 0 /* DEBUGGING */
+ printf ("Processing export list for %s\n", objfile->name);
+#endif
+
+ /* It doesn't work, for some reason, to read in space $TEXT$;
+ the subspace $SHLIB_INFO$ has to be used. Some BFD quirk? pai/1997-08-05 */
+ text_section = bfd_get_section_by_name (objfile->obfd, "$SHLIB_INFO$");
+ if (!text_section)
+ return 0;
+ /* Get the SOM executable header */
+ bfd_get_section_contents (objfile->obfd, text_section, dl_header, 0, 12 * sizeof (int));
+
+ /* Check header version number for 10.x HP-UX */
+ /* Currently we deal only with 10.x systems; on 9.x the version # is 89060912.
+ FIXME: Change for future HP-UX releases and mods to the SOM executable format */
+ if (dl_header[0] != 93092112)
+ return 0;
+
+ export_list = dl_header[8];
+ export_list_size = dl_header[9];
+ if (!export_list_size)
+ return 0;
+ string_table = dl_header[10];
+ string_table_size = dl_header[11];
+ if (!string_table_size)
+ return 0;
+
+ /* Suck in SOM string table */
+ string_buffer = (char *) xmalloc (string_table_size);
+ bfd_get_section_contents (objfile->obfd, text_section, string_buffer,
+ string_table, string_table_size);
+
+ /* Allocate export list in the psymbol obstack; this has nothing
+ to do with psymbols, just a matter of convenience. We want the
+ export list to be freed when the objfile is deallocated */
+ objfile->export_list
+ = (ExportEntry *) obstack_alloc (&objfile->psymbol_obstack,
+ export_list_size * sizeof (ExportEntry));
+
+ /* Read in the export entries, a bunch at a time */
+ for (j=0, k=0;
+ j < (export_list_size / SOM_READ_EXPORTS_NUM);
+ j++)
+ {
+ bfd_get_section_contents (objfile->obfd, text_section, buffer,
+ export_list + j * SOM_READ_EXPORTS_CHUNK_SIZE,
+ SOM_READ_EXPORTS_CHUNK_SIZE);
+ for (i=0; i < SOM_READ_EXPORTS_NUM; i++, k++)
+ {
+ if (buffer[i].type != (unsigned char) 0)
+ {
+ objfile->export_list[k].name
+ = (char *) obstack_alloc (&objfile->psymbol_obstack, strlen (string_buffer + buffer[i].name) + 1);
+ strcpy (objfile->export_list[k].name, string_buffer + buffer[i].name);
+ objfile->export_list[k].address = buffer[i].value;
+ /* Some day we might want to record the type and other information too */
+ }
+ else /* null type */
+ {
+ objfile->export_list[k].name = NULL;
+ objfile->export_list[k].address = 0;
+ }
+#if 0 /* DEBUGGING */
+ printf ("Export String %d:%d (%d), type %d is %s\n", j, i, k,
+ (int) buffer[i].type, objfile->export_list[k].name);
+#endif
+ }
+ }
+
+ /* Get the leftovers */
+ if (k < export_list_size)
+ bfd_get_section_contents (objfile->obfd, text_section, buffer,
+ export_list + k * sizeof (SomExportEntry),
+ (export_list_size - k) * sizeof (SomExportEntry));
+ for (i=0; k < export_list_size; i++, k++)
+ {
+ if (buffer[i].type != (unsigned char) 0)
+ {
+ objfile->export_list[k].name
+ = (char *) obstack_alloc (&objfile->psymbol_obstack, strlen (string_buffer + buffer[i].name) + 1);
+ strcpy (objfile->export_list[k].name, string_buffer + buffer[i].name);
+ /* Some day we might want to record the type and other information too */
+ objfile->export_list[k].address = buffer[i].value;
+ }
+ else
+ {
+ objfile->export_list[k].name = NULL;
+ objfile->export_list[k].address = 0;
+ }
+#if 0 /* DEBUGGING */
+ printf ("Export String F:%d (%d), type %d, value %x is %s\n", i, k,
+ (int) buffer[i].type, buffer[i].value, objfile->export_list[k].name);
+#endif
+ }
+
+ objfile->export_list_size = export_list_size;
+ free (string_buffer);
+ return export_list_size;
+}
+
+
+
+/* Register that we are able to handle SOM object file formats. */
+
+static struct sym_fns som_sym_fns =
+{
+ bfd_target_som_flavour,
+ som_new_init, /* sym_new_init: init anything gbl to entire symtab */
+ som_symfile_init, /* sym_init: read initial info, setup for sym_read() */
+ som_symfile_read, /* sym_read: read a symbol file into symtab */
+ som_symfile_finish, /* sym_finish: finished with file, cleanup */
+ som_symfile_offsets, /* sym_offsets: Translate ext. to int. relocation */
+ NULL /* next: pointer to next struct sym_fns */
+};
+
+void
+_initialize_somread ()
+{
+ add_symtab_fns (&som_sym_fns);
+}
diff --git a/gdb/somsolib.c b/gdb/somsolib.c
new file mode 100644
index 00000000000..870177cd33e
--- /dev/null
+++ b/gdb/somsolib.c
@@ -0,0 +1,1640 @@
+/* Handle HP SOM shared libraries for GDB, the GNU Debugger.
+ Copyright 1993, 1996, 1999 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+Written by the Center for Software Science at the Univerity of Utah
+and by Cygnus Support. */
+
+
+#include "defs.h"
+
+#include "frame.h"
+#include "bfd.h"
+#include "som.h"
+#include "libhppa.h"
+#include "gdbcore.h"
+#include "symtab.h"
+#include "breakpoint.h"
+#include "symfile.h"
+#include "objfiles.h"
+#include "inferior.h"
+#include "gdb-stabs.h"
+#include "gdb_stat.h"
+#include "gdbcmd.h"
+#include "assert.h"
+#include "language.h"
+
+#include <fcntl.h>
+
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
+
+/* Uncomment this to turn on some debugging output.
+ */
+
+/* #define SOLIB_DEBUG
+ */
+
+/* Defined in exec.c; used to prevent dangling pointer bug.
+ */
+extern struct target_ops exec_ops;
+
+/* This lives in hppa-tdep.c. */
+extern struct unwind_table_entry *find_unwind_entry PARAMS ((CORE_ADDR pc));
+
+/* These ought to be defined in some public interface, but aren't. They
+ define the meaning of the various bits in the distinguished __dld_flags
+ variable that is declared in every debuggable a.out on HP-UX, and that
+ is shared between the debugger and the dynamic linker.
+ */
+#define DLD_FLAGS_MAPPRIVATE 0x1
+#define DLD_FLAGS_HOOKVALID 0x2
+#define DLD_FLAGS_LISTVALID 0x4
+#define DLD_FLAGS_BOR_ENABLE 0x8
+
+/* TODO:
+
+ * Most of this code should work for hp300 shared libraries. Does
+ anyone care enough to weed out any SOM-isms.
+
+ * Support for hpux8 dynamic linker. */
+
+/* The basic structure which describes a dynamically loaded object. This
+ data structure is private to the dynamic linker and isn't found in
+ any HPUX include file. */
+
+struct som_solib_mapped_entry
+{
+ /* The name of the library. */
+ char *name;
+
+ /* Version of this structure (it is expected to change again in hpux10). */
+ unsigned char struct_version;
+
+ /* Binding mode for this library. */
+ unsigned char bind_mode;
+
+ /* Version of this library. */
+ short library_version;
+
+ /* Start of text address,
+ * link-time text location (length of text area),
+ * end of text address. */
+ CORE_ADDR text_addr;
+ CORE_ADDR text_link_addr;
+ CORE_ADDR text_end;
+
+ /* Start of data, start of bss and end of data. */
+ CORE_ADDR data_start;
+ CORE_ADDR bss_start;
+ CORE_ADDR data_end;
+
+ /* Value of linkage pointer (%r19). */
+ CORE_ADDR got_value;
+
+ /* Next entry. */
+ struct som_solib_mapped_entry *next;
+
+ /* There are other fields, but I don't have information as to what is
+ contained in them. */
+
+ /* For versions from HPUX-10.30 and up */
+
+ /* Address in target of offset from thread-local register of
+ * start of this thread's data. I.e., the first thread-local
+ * variable in this shared library starts at *(tsd_start_addr)
+ * from that area pointed to by cr27 (mpsfu_hi).
+ *
+ * We do the indirection as soon as we read it, so from then
+ * on it's the offset itself.
+ */
+ CORE_ADDR tsd_start_addr;
+
+ /* Following this are longwords holding:
+ *
+ * ?, ?, ?, ptr to -1, ptr to-1, ptr to lib name (leaf name),
+ * ptr to __data_start, ptr to __data_end
+ */
+
+
+};
+
+/* A structure to keep track of all the known shared objects. */
+struct so_list
+{
+ struct som_solib_mapped_entry som_solib;
+ struct objfile *objfile;
+ bfd *abfd;
+ struct section_table *sections;
+ struct section_table *sections_end;
+/* elz: added this field to store the address in target space (in the
+ library) of the library descriptor (handle) which we read into
+ som_solib_mapped_entry structure*/
+ CORE_ADDR solib_addr;
+ struct so_list *next;
+
+};
+
+static struct so_list *so_list_head;
+
+
+/* This is the cumulative size in bytes of the symbol tables of all
+ shared objects on the so_list_head list. (When we say size, here
+ we mean of the information before it is brought into memory and
+ potentially expanded by GDB.) When adding a new shlib, this value
+ is compared against the threshold size, held by auto_solib_add
+ (in megabytes). If adding symbols for the new shlib would cause
+ the total size to exceed the threshold, then the new shlib's symbols
+ are not loaded.
+ */
+static LONGEST som_solib_total_st_size;
+
+/* When the threshold is reached for any shlib, we refuse to add
+ symbols for subsequent shlibs, even if those shlibs' symbols would
+ be small enough to fit under the threshold. (Although this may
+ result in one, early large shlib preventing the loading of later,
+ smalller shlibs' symbols, it allows us to issue one informational
+ message. The alternative, to issue a message for each shlib whose
+ symbols aren't loaded, could be a big annoyance where the threshold
+ is exceeded due to a very large number of shlibs.)
+ */
+static int som_solib_st_size_threshold_exceeded;
+
+/* These addresses should be filled in by som_solib_create_inferior_hook.
+ They are also used elsewhere in this module.
+ */
+typedef struct {
+ CORE_ADDR address;
+ struct unwind_table_entry * unwind;
+} addr_and_unwind_t;
+
+/* When adding fields, be sure to clear them in _initialize_som_solib. */
+static struct {
+ boolean is_valid;
+ addr_and_unwind_t hook;
+ addr_and_unwind_t hook_stub;
+ addr_and_unwind_t load;
+ addr_and_unwind_t load_stub;
+ addr_and_unwind_t unload;
+ addr_and_unwind_t unload2;
+ addr_and_unwind_t unload_stub;
+} dld_cache;
+
+
+
+static void som_sharedlibrary_info_command PARAMS ((char *, int));
+
+static void som_solib_sharedlibrary_command PARAMS ((char *, int));
+
+static LONGEST
+som_solib_sizeof_symbol_table (filename)
+ char * filename;
+{
+ bfd * abfd;
+ int desc;
+ char * absolute_name;
+ LONGEST st_size = (LONGEST) 0;
+ asection * sect;
+
+ /* We believe that filename was handed to us by the dynamic linker, and
+ is therefore always an absolute path.
+ */
+ desc = openp (getenv ("PATH"), 1, filename, O_RDONLY | O_BINARY, 0, &absolute_name);
+ if (desc < 0)
+ {
+ perror_with_name (filename);
+ }
+ filename = absolute_name;
+
+ abfd = bfd_fdopenr (filename, gnutarget, desc);
+ if (! abfd)
+ {
+ close (desc);
+ make_cleanup (free, filename);
+ error ("\"%s\": can't open to read symbols: %s.", filename,
+ bfd_errmsg (bfd_get_error ()));
+ }
+
+ if (!bfd_check_format (abfd, bfd_object)) /* Reads in section info */
+ {
+ bfd_close (abfd); /* This also closes desc */
+ make_cleanup (free, filename);
+ error ("\"%s\": can't read symbols: %s.", filename,
+ bfd_errmsg (bfd_get_error ()));
+ }
+
+ /* Sum the sizes of the various sections that compose debug info. */
+
+ /* This contains non-DOC information. */
+ sect = bfd_get_section_by_name (abfd, "$DEBUG$");
+ if (sect)
+ st_size += (LONGEST) bfd_section_size (abfd, sect);
+
+ /* This contains DOC information. */
+ sect = bfd_get_section_by_name (abfd, "$PINFO$");
+ if (sect)
+ st_size += (LONGEST) bfd_section_size (abfd, sect);
+
+ bfd_close (abfd); /* This also closes desc */
+ free (filename);
+
+ /* Unfortunately, just summing the sizes of various debug info
+ sections isn't a very accurate measurement of how much heap
+ space the debugger will need to hold them. It also doesn't
+ account for space needed by linker (aka "minimal") symbols.
+
+ Anecdotal evidence suggests that just summing the sizes of
+ debug-info-related sections understates the heap space needed
+ to represent it internally by about an order of magnitude.
+
+ Since it's not exactly brain surgery we're doing here, rather
+ than attempt to more accurately measure the size of a shlib's
+ symbol table in GDB's heap, we'll just apply a 10x fudge-
+ factor to the debug info sections' size-sum. No, this doesn't
+ account for minimal symbols in non-debuggable shlibs. But it
+ all roughly washes out in the end.
+ */
+ return st_size * (LONGEST) 10;
+}
+
+
+static void
+som_solib_add_solib_objfile (so, name, from_tty, text_addr)
+ struct so_list * so;
+ char * name;
+ int from_tty;
+ CORE_ADDR text_addr;
+{
+ obj_private_data_t *obj_private;
+
+ so->objfile = symbol_file_add (name, from_tty, text_addr, 0, 0, 0, 0, 1);
+ so->abfd = so->objfile->obfd;
+
+ /* Mark this as a shared library and save private data.
+ */
+ so->objfile->flags |= OBJF_SHARED;
+
+ if( so->objfile->obj_private == NULL )
+ {
+ obj_private = (obj_private_data_t *)
+ obstack_alloc( &so->objfile->psymbol_obstack,
+ sizeof( obj_private_data_t ));
+ obj_private->unwind_info = NULL;
+ obj_private->so_info = NULL;
+ so->objfile->obj_private = (PTR) obj_private;
+ }
+
+ obj_private = (obj_private_data_t *) so->objfile->obj_private;
+ obj_private->so_info = so;
+
+ if (!bfd_check_format (so->abfd, bfd_object))
+ {
+ error ("\"%s\": not in executable format: %s.",
+ name, bfd_errmsg (bfd_get_error ()));
+ }
+}
+
+
+static void
+som_solib_load_symbols (so, name, from_tty, text_addr, target)
+ struct so_list * so;
+ char * name;
+ int from_tty;
+ CORE_ADDR text_addr;
+ struct target_ops * target;
+{
+ struct section_table * p;
+ int status;
+ char buf[4];
+ CORE_ADDR presumed_data_start;
+
+#ifdef SOLIB_DEBUG
+ printf( "--Adding symbols for shared library \"%s\"\n", name );
+#endif
+
+ som_solib_add_solib_objfile (so, name, from_tty, text_addr);
+
+ /* Now we need to build a section table for this library since
+ we might be debugging a core file from a dynamically linked
+ executable in which the libraries were not privately mapped. */
+ if (build_section_table (so->abfd,
+ &so->sections,
+ &so->sections_end))
+ {
+ error ("Unable to build section table for shared library\n.");
+ return;
+ }
+
+ /* Relocate all the sections based on where they got loaded. */
+ for (p = so->sections; p < so->sections_end; p++)
+ {
+ if (p->the_bfd_section->flags & SEC_CODE)
+ {
+ p->addr += ANOFFSET (so->objfile->section_offsets, SECT_OFF_TEXT);
+ p->endaddr += ANOFFSET (so->objfile->section_offsets, SECT_OFF_TEXT);
+ }
+ else if (p->the_bfd_section->flags & SEC_DATA)
+ {
+ p->addr += ANOFFSET (so->objfile->section_offsets, SECT_OFF_DATA);
+ p->endaddr += ANOFFSET (so->objfile->section_offsets, SECT_OFF_DATA);
+ }
+ }
+
+ /* Now see if we need to map in the text and data for this shared
+ library (for example debugging a core file which does not use
+ private shared libraries.).
+
+ Carefully peek at the first text address in the library. If the
+ read succeeds, then the libraries were privately mapped and were
+ included in the core dump file.
+
+ If the peek failed, then the libraries were not privately mapped
+ and are not in the core file, we'll have to read them in ourselves. */
+ status = target_read_memory (text_addr, buf, 4);
+ if (status != 0)
+ {
+ int old, new;
+ int update_coreops;
+ int update_execops;
+
+ /* We must update the to_sections field in the core_ops structure
+ here, otherwise we dereference a potential dangling pointer
+ for each call to target_read/write_memory within this routine. */
+ update_coreops = core_ops.to_sections == target->to_sections;
+
+ /* Ditto exec_ops (this was a bug).
+ */
+ update_execops = exec_ops.to_sections == target->to_sections;
+
+ new = so->sections_end - so->sections;
+ /* Add sections from the shared library to the core target. */
+ 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)) * (old + new)));
+ }
+ else
+ {
+ old = 0;
+ target->to_sections = (struct section_table *)
+ xmalloc ((sizeof (struct section_table)) * new);
+ }
+ target->to_sections_end = (target->to_sections + old + new);
+
+ /* Update the to_sections field in the core_ops structure
+ if needed, ditto exec_ops. */
+ if (update_coreops)
+ {
+ core_ops.to_sections = target->to_sections;
+ core_ops.to_sections_end = target->to_sections_end;
+ }
+
+ if (update_execops)
+ {
+ exec_ops.to_sections = target->to_sections;
+ exec_ops.to_sections_end = target->to_sections_end;
+ }
+
+ /* Copy over the old data before it gets clobbered. */
+ memcpy ((char *)(target->to_sections + old),
+ so->sections,
+ ((sizeof (struct section_table)) * new));
+ }
+}
+
+
+/* Add symbols from shared libraries into the symtab list, unless the
+ size threshold (specified by auto_solib_add, in megabytes) would
+ be exceeded. */
+
+void
+som_solib_add (arg_string, from_tty, target)
+ char *arg_string;
+ int from_tty;
+ struct target_ops *target;
+{
+ struct minimal_symbol *msymbol;
+ struct so_list *so_list_tail;
+ CORE_ADDR addr;
+ asection *shlib_info;
+ int status;
+ unsigned int dld_flags;
+ char buf[4], *re_err;
+ int threshold_warning_given = 0;
+
+ /* First validate our arguments. */
+ if ((re_err = re_comp (arg_string ? arg_string : ".")) != NULL)
+ {
+ error ("Invalid regexp: %s", re_err);
+ }
+
+ /* If we're debugging a core file, or have attached to a running
+ process, then som_solib_create_inferior_hook will not have been
+ called.
+
+ We need to first determine if we're dealing with a dynamically
+ linked executable. If not, then return without an error or warning.
+
+ We also need to examine __dld_flags to determine if the shared library
+ list is valid and to determine if the libraries have been privately
+ mapped. */
+ if (symfile_objfile == NULL)
+ return;
+
+ /* First see if the objfile was dynamically linked. */
+ shlib_info = bfd_get_section_by_name (symfile_objfile->obfd, "$SHLIB_INFO$");
+ if (!shlib_info)
+ return;
+
+ /* It's got a $SHLIB_INFO$ section, make sure it's not empty. */
+ if (bfd_section_size (symfile_objfile->obfd, shlib_info) == 0)
+ return;
+
+ msymbol = lookup_minimal_symbol ("__dld_flags", NULL, NULL);
+ if (msymbol == NULL)
+ {
+ error ("Unable to find __dld_flags symbol in object file.\n");
+ return;
+ }
+
+ addr = SYMBOL_VALUE_ADDRESS (msymbol);
+ /* Read the current contents. */
+ status = target_read_memory (addr, buf, 4);
+ if (status != 0)
+ {
+ error ("Unable to read __dld_flags\n");
+ return;
+ }
+ dld_flags = extract_unsigned_integer (buf, 4);
+
+ /* __dld_list may not be valid. If not, then we punt, warning the user if
+ we were called as a result of the add-symfile command.
+ */
+ if ((dld_flags & DLD_FLAGS_LISTVALID) == 0)
+ {
+ if (from_tty)
+ error ("__dld_list is not valid according to __dld_flags.\n");
+ return;
+ }
+
+ /* If the libraries were not mapped private, warn the user. */
+ if ((dld_flags & DLD_FLAGS_MAPPRIVATE) == 0)
+ warning ("The shared libraries were not privately mapped; setting a\nbreakpoint in a shared library will not work until you rerun the program.\n");
+
+ msymbol = lookup_minimal_symbol ("__dld_list", NULL, NULL);
+ if (!msymbol)
+ {
+ /* Older crt0.o files (hpux8) don't have __dld_list as a symbol,
+ but the data is still available if you know where to look. */
+ msymbol = lookup_minimal_symbol ("__dld_flags", NULL, NULL);
+ if (!msymbol)
+ {
+ error ("Unable to find dynamic library list.\n");
+ return;
+ }
+ addr = SYMBOL_VALUE_ADDRESS (msymbol) - 8;
+ }
+ else
+ addr = SYMBOL_VALUE_ADDRESS (msymbol);
+
+ status = target_read_memory (addr, buf, 4);
+ if (status != 0)
+ {
+ error ("Unable to find dynamic library list.\n");
+ return;
+ }
+
+ addr = extract_unsigned_integer (buf, 4);
+
+ /* If addr is zero, then we're using an old dynamic loader which
+ doesn't maintain __dld_list. We'll have to use a completely
+ different approach to get shared library information. */
+ if (addr == 0)
+ goto old_dld;
+
+ /* Using the information in __dld_list is the preferred method
+ to get at shared library information. It doesn't depend on
+ any functions in /opt/langtools/lib/end.o and has a chance of working
+ with hpux10 when it is released. */
+ status = target_read_memory (addr, buf, 4);
+ if (status != 0)
+ {
+ error ("Unable to find dynamic library list.\n");
+ return;
+ }
+
+ /* addr now holds the address of the first entry in the dynamic
+ library list. */
+ addr = extract_unsigned_integer (buf, 4);
+
+ /* Now that we have a pointer to the dynamic library list, walk
+ through it and add the symbols for each library. */
+
+ so_list_tail = so_list_head;
+ /* Find the end of the list of shared objects. */
+ while (so_list_tail && so_list_tail->next)
+ so_list_tail = so_list_tail->next;
+
+#ifdef SOLIB_DEBUG
+ printf( "--About to read shared library list data\n" );
+#endif
+
+ /* "addr" will always point to the base of the
+ * current data entry describing the current
+ * shared library.
+ */
+ while (1)
+ {
+ CORE_ADDR name_addr, text_addr;
+ unsigned int name_len;
+ char *name;
+ struct so_list *new_so;
+ struct so_list *so_list = so_list_head;
+ struct stat statbuf;
+ LONGEST st_size;
+ int is_main_program;
+
+ if (addr == 0)
+ break;
+
+ /* Get a pointer to the name of this library. */
+ status = target_read_memory (addr, buf, 4);
+ if (status != 0)
+ goto err;
+
+ name_addr = extract_unsigned_integer (buf, 4);
+ name_len = 0;
+ while (1)
+ {
+ target_read_memory (name_addr + name_len, buf, 1);
+ if (status != 0)
+ goto err;
+
+ name_len++;
+ if (*buf == '\0')
+ break;
+ }
+ name = alloca (name_len);
+ status = target_read_memory (name_addr, name, name_len);
+ if (status != 0)
+ goto err;
+
+ /* See if we've already loaded something with this name. */
+ while (so_list)
+ {
+ if (!strcmp (so_list->som_solib.name, name))
+ break;
+ so_list = so_list->next;
+ }
+
+ /* See if the file exists. If not, give a warning, but don't
+ die. */
+ status = stat (name, &statbuf);
+ if (status == -1)
+ {
+ warning ("Can't find file %s referenced in dld_list.", name);
+
+ status = target_read_memory (addr + 36, buf, 4);
+ if (status != 0)
+ goto err;
+
+ addr = (CORE_ADDR) extract_unsigned_integer (buf, 4);
+ continue;
+ }
+
+ /* If we've already loaded this one or it's the main program, skip it. */
+ is_main_program = (strcmp (name, symfile_objfile->name) == 0);
+ if (so_list || is_main_program)
+ {
+ /* This is the "next" pointer in the strcuture.
+ */
+ status = target_read_memory (addr + 36, buf, 4);
+ if (status != 0)
+ goto err;
+
+ addr = (CORE_ADDR) extract_unsigned_integer (buf, 4);
+
+ /* Record the main program's symbol table size. */
+ if (is_main_program && !so_list)
+ {
+ st_size = som_solib_sizeof_symbol_table (name);
+ som_solib_total_st_size += st_size;
+ }
+
+ /* Was this a shlib that we noted but didn't load the symbols for?
+ If so, were we invoked this time from the command-line, via
+ a 'sharedlibrary' or 'add-symbol-file' command? If yes to
+ both, we'd better load the symbols this time.
+ */
+ if (from_tty && so_list && !is_main_program && (so_list->objfile == NULL))
+ som_solib_load_symbols (so_list,
+ name,
+ from_tty,
+ so_list->som_solib.text_addr,
+ target);
+
+ continue;
+ }
+
+ name = obsavestring (name, name_len - 1,
+ &symfile_objfile->symbol_obstack);
+
+ status = target_read_memory (addr + 8, buf, 4);
+ if (status != 0)
+ goto err;
+
+ text_addr = extract_unsigned_integer (buf, 4);
+
+ new_so = (struct so_list *) xmalloc (sizeof (struct so_list));
+ memset ((char *)new_so, 0, sizeof (struct so_list));
+ if (so_list_head == NULL)
+ {
+ so_list_head = new_so;
+ so_list_tail = new_so;
+ }
+ else
+ {
+ so_list_tail->next = new_so;
+ so_list_tail = new_so;
+ }
+
+ /* Fill in all the entries in GDB's shared library list.
+ */
+
+ new_so->solib_addr = addr;
+ new_so->som_solib.name = name;
+ status = target_read_memory (addr + 4, buf, 4);
+ if (status != 0)
+ goto err;
+
+ new_so->som_solib.struct_version = extract_unsigned_integer (buf + 3, 1);
+ new_so->som_solib.bind_mode = extract_unsigned_integer (buf + 2, 1);
+ /* Following is "high water mark", highest version number
+ * seen, rather than plain version number.
+ */
+ new_so->som_solib.library_version = extract_unsigned_integer (buf, 2);
+ new_so->som_solib.text_addr = text_addr;
+
+ /* Q: What about longword at "addr + 8"?
+ * A: It's read above, out of order, into "text_addr".
+ */
+
+ status = target_read_memory (addr + 12, buf, 4);
+ if (status != 0)
+ goto err;
+
+ new_so->som_solib.text_link_addr = extract_unsigned_integer (buf, 4);
+
+ status = target_read_memory (addr + 16, buf, 4);
+ if (status != 0)
+ goto err;
+
+ new_so->som_solib.text_end = extract_unsigned_integer (buf, 4);
+
+ status = target_read_memory (addr + 20, buf, 4);
+ if (status != 0)
+ goto err;
+
+ new_so->som_solib.data_start = extract_unsigned_integer (buf, 4);
+
+ status = target_read_memory (addr + 24, buf, 4);
+ if (status != 0)
+ goto err;
+
+ new_so->som_solib.bss_start = extract_unsigned_integer (buf, 4);
+
+ status = target_read_memory (addr + 28, buf, 4);
+ if (status != 0)
+ goto err;
+
+ new_so->som_solib.data_end = extract_unsigned_integer (buf, 4);
+
+ status = target_read_memory (addr + 32, buf, 4);
+ if (status != 0)
+ goto err;
+
+ new_so->som_solib.got_value = extract_unsigned_integer (buf, 4);
+
+ status = target_read_memory (addr + 36, buf, 4);
+ if (status != 0)
+ goto err;
+
+ new_so->som_solib.next = (void *)extract_unsigned_integer (buf, 4);
+
+ /* Note that we don't re-set "addr" to the next pointer
+ * until after we've read the trailing data.
+ */
+
+ status = target_read_memory (addr + 40, buf, 4);
+ new_so->som_solib.tsd_start_addr = extract_unsigned_integer (buf, 4);
+ if (status != 0)
+ goto err;
+
+ /* Now indirect via that value!
+ */
+ status = target_read_memory (new_so->som_solib.tsd_start_addr, buf, 4);
+ new_so->som_solib.tsd_start_addr = extract_unsigned_integer (buf, 4);
+ if (status != 0)
+ goto err;
+#ifdef SOLIB_DEBUG
+ printf( "\n+ library \"%s\" is described at 0x%x\n", name, addr );
+ printf( " 'version' is %d\n", new_so->som_solib.struct_version );
+ printf( " 'bind_mode' is %d\n", new_so->som_solib.bind_mode );
+ printf( " 'library_version' is %d\n", new_so->som_solib.library_version );
+ printf( " 'text_addr' is 0x%x\n", new_so->som_solib.text_addr );
+ printf( " 'text_link_addr' is 0x%x\n", new_so->som_solib.text_link_addr );
+ printf( " 'text_end' is 0x%x\n", new_so->som_solib.text_end );
+ printf( " 'data_start' is 0x%x\n", new_so->som_solib.data_start );
+ printf( " 'bss_start' is 0x%x\n", new_so->som_solib.bss_start );
+ printf( " 'data_end' is 0x%x\n", new_so->som_solib.data_end );
+ printf( " 'got_value' is %x\n", new_so->som_solib.got_value );
+ printf( " 'next' is 0x%x\n", new_so->som_solib.next );
+ printf( " 'tsd_start_addr' is 0x%x\n", new_so->som_solib.tsd_start_addr );
+#endif
+
+ /* Go on to the next shared library descriptor.
+ */
+ addr = (CORE_ADDR)new_so->som_solib.next;
+
+
+
+ /* At this point, we have essentially hooked the shlib into the
+ "info share" command. However, we haven't yet loaded its
+ symbol table. We must now decide whether we ought to, i.e.,
+ whether doing so would exceed the symbol table size threshold.
+
+ If the threshold has just now been exceeded, then we'll issue
+ a warning message (which explains how to load symbols manually,
+ if the user so desires).
+
+ If the threshold has just now or previously been exceeded,
+ we'll just add the shlib to the list of object files, but won't
+ actually load its symbols. (This is more useful than it might
+ sound, for it allows us to e.g., still load and use the shlibs'
+ unwind information for stack tracebacks.)
+ */
+
+ /* Note that we DON'T want to preclude the user from using the
+ add-symbol-file command! Thus, we only worry about the threshold
+ when we're invoked for other reasons.
+ */
+ st_size = som_solib_sizeof_symbol_table (name);
+ som_solib_st_size_threshold_exceeded =
+ !from_tty &&
+ ((st_size + som_solib_total_st_size) > (auto_solib_add * (LONGEST)1000000));
+
+ if (som_solib_st_size_threshold_exceeded)
+ {
+ if (! threshold_warning_given)
+ warning ("Symbols for some libraries have not been loaded, because\ndoing so would exceed the size threshold specified by auto-solib-add.\nTo manually load symbols, use the 'sharedlibrary' command.\nTo raise the threshold, set auto-solib-add to a larger value and rerun\nthe program.\n");
+ threshold_warning_given = 1;
+
+ /* We'll still make note of this shlib, even if we don't
+ read its symbols. This allows us to use its unwind
+ information well enough to know how to e.g., correctly
+ do a traceback from a PC within the shlib, even if we
+ can't symbolize those PCs...
+ */
+ som_solib_add_solib_objfile (new_so, name, from_tty, text_addr);
+ continue;
+ }
+
+ som_solib_total_st_size += st_size;
+
+ /* This fills in new_so->objfile, among others. */
+ som_solib_load_symbols (new_so, name, from_tty, text_addr, target);
+ }
+
+#ifdef SOLIB_DEBUG
+ printf( "--Done reading shared library data\n" );
+#endif
+
+ /* Getting new symbols may change our opinion about what is
+ frameless. */
+ reinit_frame_cache ();
+ return;
+
+old_dld:
+ error ("Debugging dynamic executables loaded via the hpux8 dld.sl is not supported.\n");
+ return;
+
+err:
+ error ("Error while reading dynamic library list.\n");
+ return;
+}
+
+
+/* This hook gets called just before the first instruction in the
+ inferior process is executed.
+
+ This is our opportunity to set magic flags in the inferior so
+ that GDB can be notified when a shared library is mapped in and
+ to tell the dynamic linker that a private copy of the library is
+ needed (so GDB can set breakpoints in the library).
+
+ __dld_flags is the location of the magic flags; as of this implementation
+ there are 3 flags of interest:
+
+ bit 0 when set indicates that private copies of the libraries are needed
+ bit 1 when set indicates that the callback hook routine is valid
+ bit 2 when set indicates that the dynamic linker should maintain the
+ __dld_list structure when loading/unloading libraries.
+
+ Note that shared libraries are not mapped in at this time, so we have
+ run the inferior until the libraries are mapped in. Typically this
+ means running until the "_start" is called. */
+
+void
+som_solib_create_inferior_hook()
+{
+ struct minimal_symbol *msymbol;
+ unsigned int dld_flags, status, have_endo;
+ asection *shlib_info;
+ char buf[4];
+ struct objfile *objfile;
+ CORE_ADDR anaddr;
+
+ /* First, remove all the solib event breakpoints. Their addresses
+ may have changed since the last time we ran the program. */
+ remove_solib_event_breakpoints ();
+
+ if (symfile_objfile == NULL)
+ return;
+
+ /* First see if the objfile was dynamically linked. */
+ shlib_info = bfd_get_section_by_name (symfile_objfile->obfd, "$SHLIB_INFO$");
+ if (!shlib_info)
+ return;
+
+ /* It's got a $SHLIB_INFO$ section, make sure it's not empty. */
+ if (bfd_section_size (symfile_objfile->obfd, shlib_info) == 0)
+ return;
+
+ have_endo = 0;
+ /* Slam the pid of the process into __d_pid; failing is only a warning! */
+ msymbol = lookup_minimal_symbol ("__d_pid", NULL, symfile_objfile);
+ if (msymbol == NULL)
+ {
+ warning ("Unable to find __d_pid symbol in object file.");
+ warning ("Suggest linking with /opt/langtools/lib/end.o.");
+ warning ("GDB will be unable to track shl_load/shl_unload calls");
+ goto keep_going;
+ }
+
+ anaddr = SYMBOL_VALUE_ADDRESS (msymbol);
+ store_unsigned_integer (buf, 4, inferior_pid);
+ status = target_write_memory (anaddr, buf, 4);
+ if (status != 0)
+ {
+ warning ("Unable to write __d_pid");
+ warning ("Suggest linking with /opt/langtools/lib/end.o.");
+ warning ("GDB will be unable to track shl_load/shl_unload calls");
+ goto keep_going;
+ }
+
+ /* Get the value of _DLD_HOOK (an export stub) and put it in __dld_hook;
+ This will force the dynamic linker to call __d_trap when significant
+ events occur.
+
+ Note that the above is the pre-HP-UX 9.0 behaviour. At 9.0 and above,
+ the dld provides an export stub named "__d_trap" as well as the
+ function named "__d_trap" itself, but doesn't provide "_DLD_HOOK".
+ We'll look first for the old flavor and then the new.
+ */
+ msymbol = lookup_minimal_symbol ("_DLD_HOOK", NULL, symfile_objfile);
+ if (msymbol == NULL)
+ msymbol = lookup_minimal_symbol ("__d_trap", NULL, symfile_objfile);
+ if (msymbol == NULL)
+ {
+ warning ("Unable to find _DLD_HOOK symbol in object file.");
+ warning ("Suggest linking with /opt/langtools/lib/end.o.");
+ warning ("GDB will be unable to track shl_load/shl_unload calls");
+ goto keep_going;
+ }
+ anaddr = SYMBOL_VALUE_ADDRESS (msymbol);
+ dld_cache.hook.address = anaddr;
+
+ /* Grrr, this might not be an export symbol! We have to find the
+ export stub. */
+ ALL_OBJFILES (objfile)
+ {
+ struct unwind_table_entry *u;
+ struct minimal_symbol *msymbol2;
+
+ /* What a crock. */
+ msymbol2 = lookup_minimal_symbol_solib_trampoline (SYMBOL_NAME (msymbol),
+ NULL, objfile);
+ /* Found a symbol with the right name. */
+ if (msymbol2)
+ {
+ struct unwind_table_entry *u;
+ /* It must be a shared library trampoline. */
+ if (SYMBOL_TYPE (msymbol2) != mst_solib_trampoline)
+ continue;
+
+ /* It must also be an export stub. */
+ u = find_unwind_entry (SYMBOL_VALUE (msymbol2));
+ if (!u || u->stub_unwind.stub_type != EXPORT)
+ continue;
+
+ /* OK. Looks like the correct import stub. */
+ anaddr = SYMBOL_VALUE (msymbol2);
+ dld_cache.hook_stub.address = anaddr;
+ }
+ }
+ store_unsigned_integer (buf, 4, anaddr);
+
+ msymbol = lookup_minimal_symbol ("__dld_hook", NULL, symfile_objfile);
+ if (msymbol == NULL)
+ {
+ warning ("Unable to find __dld_hook symbol in object file.");
+ warning ("Suggest linking with /opt/langtools/lib/end.o.");
+ warning ("GDB will be unable to track shl_load/shl_unload calls");
+ goto keep_going;
+ }
+ anaddr = SYMBOL_VALUE_ADDRESS (msymbol);
+ status = target_write_memory (anaddr, buf, 4);
+
+ /* Now set a shlib_event breakpoint at __d_trap so we can track
+ significant shared library events. */
+ msymbol = lookup_minimal_symbol ("__d_trap", NULL, symfile_objfile);
+ if (msymbol == NULL)
+ {
+ warning ("Unable to find __dld_d_trap symbol in object file.");
+ warning ("Suggest linking with /opt/langtools/lib/end.o.");
+ warning ("GDB will be unable to track shl_load/shl_unload calls");
+ goto keep_going;
+ }
+ create_solib_event_breakpoint (SYMBOL_VALUE_ADDRESS (msymbol));
+
+ /* We have all the support usually found in end.o, so we can track
+ shl_load and shl_unload calls. */
+ have_endo = 1;
+
+keep_going:
+
+ /* Get the address of __dld_flags, if no such symbol exists, then we can
+ not debug the shared code. */
+ msymbol = lookup_minimal_symbol ("__dld_flags", NULL, NULL);
+ if (msymbol == NULL)
+ {
+ error ("Unable to find __dld_flags symbol in object file.\n");
+ }
+
+ anaddr = SYMBOL_VALUE_ADDRESS (msymbol);
+
+ /* Read the current contents. */
+ status = target_read_memory (anaddr, buf, 4);
+ if (status != 0)
+ {
+ error ("Unable to read __dld_flags\n");
+ }
+ dld_flags = extract_unsigned_integer (buf, 4);
+
+ /* Turn on the flags we care about. */
+ dld_flags |= DLD_FLAGS_MAPPRIVATE;
+ if (have_endo)
+ dld_flags |= DLD_FLAGS_HOOKVALID;
+ store_unsigned_integer (buf, 4, dld_flags);
+ status = target_write_memory (anaddr, buf, 4);
+ if (status != 0)
+ {
+ error ("Unable to write __dld_flags\n");
+ }
+
+ /* Now find the address of _start and set a breakpoint there.
+ We still need this code for two reasons:
+
+ * Not all sites have /opt/langtools/lib/end.o, so it's not always
+ possible to track the dynamic linker's events.
+
+ * At this time no events are triggered for shared libraries
+ loaded at startup time (what a crock). */
+
+ msymbol = lookup_minimal_symbol ("_start", NULL, symfile_objfile);
+ if (msymbol == NULL)
+ {
+ error ("Unable to find _start symbol in object file.\n");
+ }
+
+ anaddr = SYMBOL_VALUE_ADDRESS (msymbol);
+
+ /* Make the breakpoint at "_start" a shared library event breakpoint. */
+ create_solib_event_breakpoint (anaddr);
+
+ /* Wipe out all knowledge of old shared libraries since their
+ mapping can change from one exec to another! */
+ while (so_list_head)
+ {
+ struct so_list *temp;
+
+ temp = so_list_head;
+ free (so_list_head);
+ so_list_head = temp->next;
+ }
+ clear_symtab_users ();
+}
+
+
+static void
+reset_inferior_pid (saved_inferior_pid)
+ int saved_inferior_pid;
+{
+ inferior_pid = saved_inferior_pid;
+}
+
+
+/* This operation removes the "hook" between GDB and the dynamic linker,
+ which causes the dld to notify GDB of shared library events.
+
+ After this operation completes, the dld will no longer notify GDB of
+ shared library events. To resume notifications, GDB must call
+ som_solib_create_inferior_hook.
+
+ This operation does not remove any knowledge of shared libraries which
+ GDB may already have been notified of.
+ */
+void
+som_solib_remove_inferior_hook (pid)
+ int pid;
+{
+ CORE_ADDR addr;
+ struct minimal_symbol * msymbol;
+ int status;
+ char dld_flags_buffer [TARGET_INT_BIT/TARGET_CHAR_BIT];
+ unsigned int dld_flags_value;
+ int saved_inferior_pid = inferior_pid;
+ struct cleanup * old_cleanups = make_cleanup (reset_inferior_pid, saved_inferior_pid);
+
+ /* Ensure that we're really operating on the specified process. */
+ inferior_pid = pid;
+
+ /* We won't bother to remove the solib breakpoints from this process.
+
+ In fact, on PA64 the breakpoint is hard-coded into the dld callback,
+ and thus we're not supposed to remove it.
+
+ Rather, we'll merely clear the dld_flags bit that enables callbacks.
+ */
+ msymbol = lookup_minimal_symbol ("__dld_flags", NULL, NULL);
+
+ addr = SYMBOL_VALUE_ADDRESS (msymbol);
+ status = target_read_memory (addr, dld_flags_buffer, TARGET_INT_BIT/TARGET_CHAR_BIT);
+
+ dld_flags_value = extract_unsigned_integer (dld_flags_buffer,
+ sizeof (dld_flags_value));
+
+ dld_flags_value &= ~DLD_FLAGS_HOOKVALID;
+ store_unsigned_integer (dld_flags_buffer,
+ sizeof (dld_flags_value),
+ dld_flags_value);
+ status = target_write_memory (addr, dld_flags_buffer, TARGET_INT_BIT/TARGET_CHAR_BIT);
+
+ do_cleanups (old_cleanups);
+}
+
+
+/* This function creates a breakpoint on the dynamic linker hook, which
+ is called when e.g., a shl_load or shl_unload call is made. This
+ breakpoint will only trigger when a shl_load call is made.
+
+ If filename is NULL, then loads of any dll will be caught. Else,
+ only loads of the file whose pathname is the string contained by
+ filename will be caught.
+
+ Undefined behaviour is guaranteed if this function is called before
+ som_solib_create_inferior_hook.
+ */
+void
+som_solib_create_catch_load_hook (pid, tempflag, filename, cond_string)
+ int pid;
+ int tempflag;
+ char * filename;
+ char * cond_string;
+{
+ create_solib_load_event_breakpoint ("__d_trap", tempflag, filename, cond_string);
+}
+
+/* This function creates a breakpoint on the dynamic linker hook, which
+ is called when e.g., a shl_load or shl_unload call is made. This
+ breakpoint will only trigger when a shl_unload call is made.
+
+ If filename is NULL, then unloads of any dll will be caught. Else,
+ only unloads of the file whose pathname is the string contained by
+ filename will be caught.
+
+ Undefined behaviour is guaranteed if this function is called before
+ som_solib_create_inferior_hook.
+ */
+void
+som_solib_create_catch_unload_hook (pid, tempflag, filename, cond_string)
+ int pid;
+ int tempflag;
+ char * filename;
+ char * cond_string;
+{
+ create_solib_unload_event_breakpoint ("__d_trap", tempflag, filename, cond_string);
+}
+
+int
+som_solib_have_load_event (pid)
+ int pid;
+{
+ CORE_ADDR event_kind;
+
+ event_kind = read_register (ARG0_REGNUM);
+ return (event_kind == SHL_LOAD);
+}
+
+int
+som_solib_have_unload_event (pid)
+ int pid;
+{
+ CORE_ADDR event_kind;
+
+ event_kind = read_register (ARG0_REGNUM);
+ return (event_kind == SHL_UNLOAD);
+}
+
+static char *
+som_solib_library_pathname (pid)
+ int pid;
+{
+ CORE_ADDR dll_handle_address;
+ CORE_ADDR dll_pathname_address;
+ struct som_solib_mapped_entry dll_descriptor;
+ char * p;
+ static char dll_pathname [1024];
+
+ /* Read the descriptor of this newly-loaded library. */
+ dll_handle_address = read_register (ARG1_REGNUM);
+ read_memory (dll_handle_address, (char *) &dll_descriptor, sizeof (dll_descriptor));
+
+ /* We can find a pointer to the dll's pathname within the descriptor. */
+ dll_pathname_address = (CORE_ADDR) dll_descriptor.name;
+
+ /* Read the pathname, one byte at a time. */
+ p = dll_pathname;
+ for (;;)
+ {
+ char b;
+ read_memory (dll_pathname_address++, (char *) &b, 1);
+ *p++ = b;
+ if (b == '\0')
+ break;
+ }
+
+ return dll_pathname;
+}
+
+char *
+som_solib_loaded_library_pathname (pid)
+ int pid;
+{
+ if (! som_solib_have_load_event (pid))
+ error ("Must have a load event to use this query");
+
+ return som_solib_library_pathname (pid);
+}
+
+char *
+som_solib_unloaded_library_pathname (pid)
+ int pid;
+{
+ if (! som_solib_have_unload_event (pid))
+ error ("Must have an unload event to use this query");
+
+ return som_solib_library_pathname (pid);
+}
+
+static void
+som_solib_desire_dynamic_linker_symbols ()
+{
+ struct objfile *objfile;
+ struct unwind_table_entry *u;
+ struct minimal_symbol * dld_msymbol;
+
+ /* Do we already know the value of these symbols? If so, then
+ we've no work to do.
+
+ (If you add clauses to this test, be sure to likewise update the
+ test within the loop.)
+ */
+ if (dld_cache.is_valid)
+ return;
+
+ ALL_OBJFILES (objfile)
+ {
+ dld_msymbol = lookup_minimal_symbol ("shl_load", NULL, objfile);
+ if (dld_msymbol != NULL)
+ {
+ dld_cache.load.address = SYMBOL_VALUE (dld_msymbol);
+ dld_cache.load.unwind = find_unwind_entry (dld_cache.load.address);
+ }
+
+ dld_msymbol = lookup_minimal_symbol_solib_trampoline ("shl_load",
+ NULL,
+ objfile);
+ if (dld_msymbol != NULL)
+ {
+ if (SYMBOL_TYPE (dld_msymbol) == mst_solib_trampoline)
+ {
+ u = find_unwind_entry (SYMBOL_VALUE (dld_msymbol));
+ if ((u != NULL) && (u->stub_unwind.stub_type == EXPORT))
+ {
+ dld_cache.load_stub.address = SYMBOL_VALUE (dld_msymbol);
+ dld_cache.load_stub.unwind = u;
+ }
+ }
+ }
+
+ dld_msymbol = lookup_minimal_symbol ("shl_unload", NULL, objfile);
+ if (dld_msymbol != NULL)
+ {
+ dld_cache.unload.address = SYMBOL_VALUE (dld_msymbol);
+ dld_cache.unload.unwind = find_unwind_entry (dld_cache.unload.address);
+
+ /* ??rehrauer: I'm not sure exactly what this is, but it appears
+ that on some HPUX 10.x versions, there's two unwind regions to
+ cover the body of "shl_unload", the second being 4 bytes past
+ the end of the first. This is a large hack to handle that
+ case, but since I don't seem to have any legitimate way to
+ look for this thing via the symbol table...
+ */
+ if (dld_cache.unload.unwind != NULL)
+ {
+ u = find_unwind_entry (dld_cache.unload.unwind->region_end + 4);
+ if (u != NULL)
+ {
+ dld_cache.unload2.address = u->region_start;
+ dld_cache.unload2.unwind = u;
+ }
+ }
+ }
+
+ dld_msymbol = lookup_minimal_symbol_solib_trampoline ("shl_unload",
+ NULL,
+ objfile);
+ if (dld_msymbol != NULL)
+ {
+ if (SYMBOL_TYPE (dld_msymbol) == mst_solib_trampoline)
+ {
+ u = find_unwind_entry (SYMBOL_VALUE (dld_msymbol));
+ if ((u != NULL) && (u->stub_unwind.stub_type == EXPORT))
+ {
+ dld_cache.unload_stub.address = SYMBOL_VALUE (dld_msymbol);
+ dld_cache.unload_stub.unwind = u;
+ }
+ }
+ }
+
+ /* Did we find everything we were looking for? If so, stop. */
+ if ((dld_cache.load.address != NULL) && (dld_cache.load_stub.address != NULL)
+ && (dld_cache.unload.address != NULL) && (dld_cache.unload_stub.address != NULL))
+ {
+ dld_cache.is_valid = 1;
+ break;
+ }
+ }
+
+ dld_cache.hook.unwind = find_unwind_entry (dld_cache.hook.address);
+ dld_cache.hook_stub.unwind = find_unwind_entry (dld_cache.hook_stub.address);
+
+ /* We're prepared not to find some of these symbols, which is why
+ this function is a "desire" operation, and not a "require".
+ */
+}
+
+int
+som_solib_in_dynamic_linker (pid, pc)
+ int pid;
+ CORE_ADDR pc;
+{
+ struct unwind_table_entry * u_pc;
+
+ /* Are we in the dld itself?
+
+ ??rehrauer: Large hack -- We'll assume that any address in a
+ shared text region is the dld's text. This would obviously
+ fall down if the user attached to a process, whose shlibs
+ weren't mapped to a (writeable) private region. However, in
+ that case the debugger probably isn't able to set the fundamental
+ breakpoint in the dld callback anyways, so this hack should be
+ safe.
+ */
+ if ((pc & (CORE_ADDR) 0xc0000000) == (CORE_ADDR) 0xc0000000)
+ return 1;
+
+ /* Cache the address of some symbols that are part of the dynamic
+ linker, if not already known.
+ */
+ som_solib_desire_dynamic_linker_symbols ();
+
+ /* Are we in the dld callback? Or its export stub? */
+ u_pc = find_unwind_entry (pc);
+ if (u_pc == NULL)
+ return 0;
+
+ if ((u_pc == dld_cache.hook.unwind) || (u_pc == dld_cache.hook_stub.unwind))
+ return 1;
+
+ /* Or the interface of the dld (i.e., "shl_load" or friends)? */
+ if ((u_pc == dld_cache.load.unwind)
+ || (u_pc == dld_cache.unload.unwind)
+ || (u_pc == dld_cache.unload2.unwind)
+ || (u_pc == dld_cache.load_stub.unwind)
+ || (u_pc == dld_cache.unload_stub.unwind))
+ return 1;
+
+ /* Apparently this address isn't part of the dld's text. */
+ return 0;
+}
+
+
+/* Return the GOT value for the shared library in which ADDR belongs. If
+ ADDR isn't in any known shared library, return zero. */
+
+CORE_ADDR
+som_solib_get_got_by_pc (addr)
+ CORE_ADDR addr;
+{
+ struct so_list *so_list = so_list_head;
+ CORE_ADDR got_value = 0;
+
+ while (so_list)
+ {
+ if (so_list->som_solib.text_addr <= addr
+ && so_list->som_solib.text_end > addr)
+ {
+ got_value = so_list->som_solib.got_value;
+ break;
+ }
+ so_list = so_list->next;
+ }
+ return got_value;
+}
+
+/* elz:
+ Return the address of the handle of the shared library
+ in which ADDR belongs. If
+ ADDR isn't in any known shared library, return zero. */
+/* this function is used in hppa_fix_call_dummy in hppa-tdep.c*/
+
+CORE_ADDR
+som_solib_get_solib_by_pc (addr)
+ CORE_ADDR addr;
+{
+ struct so_list *so_list = so_list_head;
+
+ while (so_list)
+ {
+ if (so_list->som_solib.text_addr <= addr
+ && so_list->som_solib.text_end > addr)
+ {
+ break;
+ }
+ so_list = so_list->next;
+ }
+ if (so_list)
+ return so_list->solib_addr;
+ else
+ return 0;
+}
+
+
+int
+som_solib_section_offsets (objfile, offsets)
+ struct objfile *objfile;
+ struct section_offsets *offsets;
+{
+ struct so_list *so_list = so_list_head;
+
+ while (so_list)
+ {
+ /* Oh what a pain! We need the offsets before so_list->objfile
+ is valid. The BFDs will never match. Make a best guess. */
+ if (strstr (objfile->name, so_list->som_solib.name))
+ {
+ asection *private_section;
+
+ /* The text offset is easy. */
+ ANOFFSET (offsets, SECT_OFF_TEXT)
+ = (so_list->som_solib.text_addr
+ - so_list->som_solib.text_link_addr);
+ ANOFFSET (offsets, SECT_OFF_RODATA)
+ = ANOFFSET (offsets, SECT_OFF_TEXT);
+
+ /* We should look at presumed_dp in the SOM header, but
+ that's not easily available. This should be OK though. */
+ private_section = bfd_get_section_by_name (objfile->obfd,
+ "$PRIVATE$");
+ if (!private_section)
+ {
+ warning ("Unable to find $PRIVATE$ in shared library!");
+ ANOFFSET (offsets, SECT_OFF_DATA) = 0;
+ ANOFFSET (offsets, SECT_OFF_BSS) = 0;
+ return 1;
+ }
+ ANOFFSET (offsets, SECT_OFF_DATA)
+ = (so_list->som_solib.data_start - private_section->vma);
+ ANOFFSET (offsets, SECT_OFF_BSS)
+ = ANOFFSET (offsets, SECT_OFF_DATA);
+ return 1;
+ }
+ so_list = so_list->next;
+ }
+ return 0;
+}
+
+/* Dump information about all the currently loaded shared libraries. */
+
+static void
+som_sharedlibrary_info_command (ignore, from_tty)
+ char *ignore;
+ int from_tty;
+{
+ struct so_list *so_list = so_list_head;
+
+ if (exec_bfd == NULL)
+ {
+ printf_unfiltered ("no exec file.\n");
+ return;
+ }
+
+ if (so_list == NULL)
+ {
+ printf_unfiltered ("No shared libraries loaded at this time.\n");
+ return;
+ }
+
+ printf_unfiltered ("Shared Object Libraries\n");
+ printf_unfiltered (" %-12s%-12s%-12s%-12s%-12s%-12s\n",
+ " flags", " tstart", " tend", " dstart", " dend", " dlt");
+ while (so_list)
+ {
+ unsigned int flags;
+
+ flags = so_list->som_solib.struct_version << 24;
+ flags |= so_list->som_solib.bind_mode << 16;
+ flags |= so_list->som_solib.library_version;
+ printf_unfiltered ("%s", so_list->som_solib.name);
+ if (so_list->objfile == NULL)
+ printf_unfiltered (" (symbols not loaded)");
+ printf_unfiltered ("\n");
+ printf_unfiltered (" %-12s", local_hex_string_custom (flags, "08l"));
+ printf_unfiltered ("%-12s",
+ local_hex_string_custom (so_list->som_solib.text_addr, "08l"));
+ printf_unfiltered ("%-12s",
+ local_hex_string_custom (so_list->som_solib.text_end, "08l"));
+ printf_unfiltered ("%-12s",
+ local_hex_string_custom (so_list->som_solib.data_start, "08l"));
+ printf_unfiltered ("%-12s",
+ local_hex_string_custom (so_list->som_solib.data_end, "08l"));
+ printf_unfiltered ("%-12s\n",
+ local_hex_string_custom (so_list->som_solib.got_value, "08l"));
+ so_list = so_list->next;
+ }
+}
+
+static void
+som_solib_sharedlibrary_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ dont_repeat ();
+ som_solib_add (args, from_tty, (struct target_ops *) 0);
+}
+
+
+
+char *
+som_solib_address (addr)
+ CORE_ADDR addr;
+{
+ struct so_list * so = so_list_head;
+
+ while (so)
+ {
+ /* Is this address within this shlib's text range? If so,
+ return the shlib's name.
+ */
+ if ((addr >= so->som_solib.text_addr) && (addr <= so->som_solib.text_end))
+ return so->som_solib.name;
+
+ /* Nope, keep looking... */
+ so = so->next;
+ }
+
+ /* No, we couldn't prove that the address is within a shlib. */
+ return NULL;
+}
+
+
+void
+som_solib_restart ()
+{
+ struct so_list * sl = so_list_head;
+
+ /* Before the shlib info vanishes, use it to disable any breakpoints
+ that may still be active in those shlibs.
+ */
+ disable_breakpoints_in_shlibs (0);
+
+ /* Discard all the shlib descriptors.
+ */
+ while (sl)
+ {
+ struct so_list * next_sl = sl->next;
+ free (sl);
+ sl = next_sl;
+ }
+ so_list_head = NULL;
+
+ som_solib_total_st_size = (LONGEST) 0;
+ som_solib_st_size_threshold_exceeded = 0;
+
+ dld_cache.is_valid = 0;
+
+ dld_cache.hook.address = 0;
+ dld_cache.hook.unwind = NULL;
+
+ dld_cache.hook_stub.address = 0;
+ dld_cache.hook_stub.unwind = NULL;
+
+ dld_cache.load.address = 0;
+ dld_cache.load.unwind = NULL;
+
+ dld_cache.load_stub.address = 0;
+ dld_cache.load_stub.unwind = NULL;
+
+ dld_cache.unload.address = 0;
+ dld_cache.unload.unwind = NULL;
+
+ dld_cache.unload2.address = 0;
+ dld_cache.unload2.unwind = NULL;
+
+ dld_cache.unload_stub.address = 0;
+ dld_cache.unload_stub.unwind = NULL;
+}
+
+
+
+void
+_initialize_som_solib ()
+{
+ add_com ("sharedlibrary", class_files, som_solib_sharedlibrary_command,
+ "Load shared object library symbols for files matching REGEXP.");
+ add_info ("sharedlibrary", som_sharedlibrary_info_command,
+ "Status of loaded shared object libraries.");
+ add_show_from_set
+ (add_set_cmd ("auto-solib-add", class_support, var_zinteger,
+ (char *) &auto_solib_add,
+ "Set autoloading size threshold (in megabytes) of shared library symbols.\n\
+If nonzero, symbols from all shared object libraries will be loaded\n\
+automatically when the inferior begins execution or when the dynamic linker\n\
+informs gdb that a new library has been loaded, until the symbol table\n\
+of the program and libraries exceeds this threshold.\n\
+Otherwise, symbols must be loaded manually, using `sharedlibrary'.",
+ &setlist),
+ &showlist);
+
+ /* ??rehrauer: On HP-UX, the kernel parameter MAXDSIZ limits how much
+ data space a process can use. We ought to be reading MAXDSIZ and
+ setting auto_solib_add to some large fraction of that value. If
+ not that, we maybe ought to be setting it smaller than the default
+ for MAXDSIZ (that being 64Mb, I believe). However, [1] this threshold
+ is only crudely approximated rather than actually measured, and [2]
+ 50 Mbytes is too small for debugging gdb itself. Thus, the arbitrary
+ 100 figure.
+ */
+ auto_solib_add = 100; /* Megabytes */
+
+ som_solib_restart ();
+}
+
+/* Get some HPUX-specific data from a shared lib.
+ */
+CORE_ADDR
+so_lib_thread_start_addr( so )
+ struct so_list *so;
+{
+ return so->som_solib.tsd_start_addr;
+}
diff --git a/gdb/somsolib.h b/gdb/somsolib.h
new file mode 100644
index 00000000000..b96916921f1
--- /dev/null
+++ b/gdb/somsolib.h
@@ -0,0 +1,177 @@
+/* HP SOM 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+Written by the Center for Software Science at the Univerity of Utah
+and by Cygnus Support. */
+
+#ifdef __STDC__ /* Forward decl's for prototypes */
+struct target_ops;
+struct objfile;
+struct section_offsets;
+#endif
+
+/* Called to add symbols from a shared library to gdb's symbol table. */
+
+#define SOLIB_ADD(filename, from_tty, targ) \
+ som_solib_add (filename, from_tty, targ)
+
+extern void
+som_solib_add PARAMS ((char *, int, struct target_ops *));
+
+extern CORE_ADDR
+som_solib_get_got_by_pc PARAMS ((CORE_ADDR));
+
+extern int
+som_solib_section_offsets PARAMS ((struct objfile *, struct section_offsets *));
+
+/* 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) som_solib_create_inferior_hook()
+
+extern void
+som_solib_create_inferior_hook PARAMS((void));
+
+/* Function to be called to remove the connection between debugger and
+ dynamic linker that was established by SOLIB_CREATE_INFERIOR_HOOK.
+ (This operation does not remove shared library information from
+ the debugger, as CLEAR_SOLIB does.)
+ */
+#define SOLIB_REMOVE_INFERIOR_HOOK(PID) som_solib_remove_inferior_hook(PID)
+
+extern void
+som_solib_remove_inferior_hook PARAMS((int));
+
+/* This function is called by the "catch load" command. It allows
+ the debugger to be notified by the dynamic linker when a specified
+ library file (or any library file, if filename is NULL) is loaded.
+ */
+#define SOLIB_CREATE_CATCH_LOAD_HOOK(pid,tempflag, filename,cond_string) \
+ som_solib_create_catch_load_hook (pid, tempflag, filename, cond_string)
+
+extern void
+som_solib_create_catch_load_hook PARAMS((int, int, char *, char *));
+
+/* This function is called by the "catch unload" command. It allows
+ the debugger to be notified by the dynamic linker when a specified
+ library file (or any library file, if filename is NULL) is unloaded.
+ */
+#define SOLIB_CREATE_CATCH_UNLOAD_HOOK(pid,tempflag,filename, cond_string) \
+ som_solib_create_catch_unload_hook (pid, tempflag, filename, cond_string)
+
+extern void
+som_solib_create_catch_unload_hook PARAMS((int, int, char *, char *));
+
+/* This function returns TRUE if the dynamic linker has just reported
+ a load of a library.
+
+ This function must be used only when the inferior has stopped in
+ the dynamic linker hook, or undefined results are guaranteed.
+ */
+#define SOLIB_HAVE_LOAD_EVENT(pid) \
+ som_solib_have_load_event (pid)
+
+extern int
+som_solib_have_load_event PARAMS((int));
+
+/* This function returns a pointer to the string representation of the
+ pathname of the dynamically-linked library that has just been loaded.
+
+ This function must be used only when SOLIB_HAVE_LOAD_EVENT is TRUE,
+ or undefined results are guaranteed.
+
+ This string's contents are only valid immediately after the inferior
+ has stopped in the dynamic linker hook, and becomes invalid as soon
+ as the inferior is continued. Clients should make a copy of this
+ string if they wish to continue the inferior and then access the string.
+ */
+#define SOLIB_LOADED_LIBRARY_PATHNAME(pid) \
+ som_solib_loaded_library_pathname (pid)
+
+extern char *
+som_solib_loaded_library_pathname PARAMS((int));
+
+/* This function returns TRUE if the dynamic linker has just reported
+ an unload of a library.
+
+ This function must be used only when the inferior has stopped in
+ the dynamic linker hook, or undefined results are guaranteed.
+ */
+#define SOLIB_HAVE_UNLOAD_EVENT(pid) \
+ som_solib_have_unload_event (pid)
+
+extern int
+som_solib_have_unload_event PARAMS((int));
+
+/* This function returns a pointer to the string representation of the
+ pathname of the dynamically-linked library that has just been unloaded.
+
+ This function must be used only when SOLIB_HAVE_UNLOAD_EVENT is TRUE,
+ or undefined results are guaranteed.
+
+ This string's contents are only valid immediately after the inferior
+ has stopped in the dynamic linker hook, and becomes invalid as soon
+ as the inferior is continued. Clients should make a copy of this
+ string if they wish to continue the inferior and then access the string.
+ */
+#define SOLIB_UNLOADED_LIBRARY_PATHNAME(pid) \
+ som_solib_unloaded_library_pathname (pid)
+
+extern char *
+som_solib_unloaded_library_pathname PARAMS((int));
+
+/* This function returns TRUE if pc is the address of an instruction that
+ lies within the dynamic linker (such as the event hook, or the dld
+ itself).
+
+ This function must be used only when a dynamic linker event has been
+ caught, and the inferior is being stepped out of the hook, or undefined
+ results are guaranteed.
+ */
+#define SOLIB_IN_DYNAMIC_LINKER(pid,pc) \
+ som_solib_in_dynamic_linker (pid, pc)
+
+extern int
+som_solib_in_dynamic_linker PARAMS((int, CORE_ADDR));
+
+/* This function must be called when the inferior is killed, and the program
+ restarted. This is not the same as CLEAR_SOLIB, in that it doesn't discard
+ any symbol tables.
+
+ Presently, this functionality is not implemented.
+ */
+#define SOLIB_RESTART() \
+ som_solib_restart ()
+
+extern void
+som_solib_restart PARAMS((void));
+
+/* If we can't set a breakpoint, and it's in a shared library, just
+ disable it. */
+
+#define DISABLE_UNSETTABLE_BREAK(addr) (som_solib_address(addr) != NULL)
+
+extern char *
+som_solib_address PARAMS ((CORE_ADDR)); /* somsolib.c */
+
+/* If ADDR lies in a shared library, return its name. */
+
+#define PC_SOLIB(addr) som_solib_address (addr)
diff --git a/gdb/source.c b/gdb/source.c
new file mode 100644
index 00000000000..9fe97425aa4
--- /dev/null
+++ b/gdb/source.c
@@ -0,0 +1,1724 @@
+/* List lines of source files for GDB, the GNU debugger.
+ Copyright 1986, 87, 88, 89, 91, 92, 93, 94, 95, 96, 97, 1998
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "symtab.h"
+#include "expression.h"
+#include "language.h"
+#include "command.h"
+#include "gdbcmd.h"
+#include "frame.h"
+#include "value.h"
+
+#include <sys/types.h>
+#include "gdb_string.h"
+#include "gdb_stat.h"
+#include <fcntl.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include "gdbcore.h"
+#include "gnu-regex.h"
+#include "symfile.h"
+#include "objfiles.h"
+#include "annotate.h"
+#include "gdbtypes.h"
+
+#ifdef CRLF_SOURCE_FILES
+
+/* Define CRLF_SOURCE_FILES in an xm-*.h file if source files on the
+ host use \r\n rather than just \n. Defining CRLF_SOURCE_FILES is
+ much faster than defining LSEEK_NOT_LINEAR. */
+
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
+
+#define OPEN_MODE (O_RDONLY | O_BINARY)
+#define FDOPEN_MODE FOPEN_RB
+
+#else /* ! defined (CRLF_SOURCE_FILES) */
+
+#define OPEN_MODE O_RDONLY
+#define FDOPEN_MODE FOPEN_RT
+
+#endif /* ! defined (CRLF_SOURCE_FILES) */
+
+/* Forward declarations */
+
+int open_source_file PARAMS ((struct symtab *));
+
+void find_source_lines PARAMS ((struct symtab *, int));
+
+/* Prototypes for exported functions. */
+
+void _initialize_source PARAMS ((void));
+
+/* Prototypes for local functions. */
+
+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));
+
+/* 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;
+
+/* Saves the name of the last source file visited and a possible error code.
+ Used to prevent repeating annoying "No such file or directories" msgs */
+
+static struct symtab *last_source_visited = NULL;
+static int last_source_error = 0;
+
+
+/* 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);
+ }
+ }
+ if (current_source_symtab)
+ return;
+
+ 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 ()
+{
+ char buf[20];
+
+ sprintf (buf, "$cdir%c$cwd", DIRNAME_SEPARATOR);
+ source_path = strsave (buf);
+ 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);
+ last_source_visited = NULL;
+ }
+ 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 *separator = strchr (name, DIRNAME_SEPARATOR);
+ char *space = strchr (name, ' ');
+ char *tab = strchr (name, '\t');
+
+ if (separator == 0 && space == 0 && tab == 0)
+ p = dirname = name + strlen (name);
+ else
+ {
+ p = 0;
+ if (separator != 0 && (p == 0 || separator < p))
+ p = separator;
+ if (space != 0 && (p == 0 || space < p))
+ p = space;
+ if (tab != 0 && (p == 0 || tab < p))
+ p = tab;
+ dirname = p + 1;
+ while (*dirname == DIRNAME_SEPARATOR
+ || *dirname == ' '
+ || *dirname == '\t')
+ ++dirname;
+ }
+ }
+
+#ifndef _WIN32
+ /* On win32 h:\ is different to h: */
+ if (SLASH_P (p[-1]))
+ /* Sigh. "foo/" => "foo" */
+ --p;
+#endif
+ *p = '\0';
+
+ while (p[-1] == '.')
+ {
+ if (p - name == 1)
+ {
+ /* "." => getwd (). */
+ name = current_directory;
+ goto append;
+ }
+ else if (SLASH_P (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 (!ROOTED_P (name) && name[0] != '$')
+ name = concat (current_directory, SLASH_STRING, 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_unfiltered (gdb_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] == DIRNAME_SEPARATOR))
+ {
+ /* Found it in the search path, remove old copy */
+ if (p > *which_path)
+ p--; /* Back over leading separator */
+ 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, DIRNAME_SEPARATOR);
+ if (p != 0)
+ ++p;
+ else
+ break;
+ }
+ if (p == 0)
+ {
+ char tinybuf[2];
+
+ tinybuf[0] = DIRNAME_SEPARATOR;
+ tinybuf[1] = '\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, tinybuf, name, NULL);
+ old[prefix] = c;
+ *which_path = concat (temp, "", &old[prefix], NULL);
+ prefix = strlen (temp);
+ free (temp);
+ }
+ else
+ {
+ *which_path = concat (name, (old[0] ? tinybuf : 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));
+ printf_filtered ("Compiled with %s debugging format.\n", s->debugformat);
+}
+
+
+
+/* Open a file named STRING, searching path PATH (dir names sep by some char)
+ 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 = ".";
+
+#ifdef _WIN32
+ mode |= O_BINARY;
+#endif
+
+ if (try_cwd_first || SLASH_P (string[0]))
+ {
+ int i;
+ filename = string;
+ fd = open (filename, mode, prot);
+ if (fd >= 0)
+ goto done;
+ for (i = 0; string[i]; i++)
+ if (SLASH_P (string[i]))
+ goto done;
+ }
+
+ /* ./foo => foo */
+ while (string[0] == '.' && SLASH_P (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, DIRNAME_SEPARATOR);
+ 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 && SLASH_P (filename[len-1]))
+ filename[--len] = 0;
+
+ strcat (filename+len, SLASH_STRING);
+ strcat (filename, string);
+
+ fd = open (filename, mode);
+ if (fd >= 0) break;
+ }
+
+ done:
+ if (filename_opened)
+ {
+ if (fd < 0)
+ *filename_opened = (char *) 0;
+ else if (ROOTED_P (filename))
+ *filename_opened = savestring (filename, strlen (filename));
+ else
+ {
+ /* Beware the // my son, the Emacs barfs, the botch that catch... */
+
+ *filename_opened = concat (current_directory,
+ SLASH_CHAR
+ == current_directory[strlen(current_directory)-1]
+ ? "": SLASH_STRING,
+ filename, NULL);
+ }
+ }
+#ifdef MPW
+ /* This is a debugging hack that can go away when all combinations
+ of Mac and Unix names are handled reasonably. */
+ {
+ extern int debug_openp;
+
+ if (debug_openp)
+ {
+ printf("openp on %s, path %s mode %d prot %d\n returned %d",
+ string, path, mode, prot, fd);
+ if (*filename_opened)
+ printf(" (filename is %s)", *filename_opened);
+ printf("\n");
+ }
+ }
+#endif /* MPW */
+
+ return fd;
+}
+
+
+/* This is essentially a convenience, for clients that want the behaviour
+ of openp, using source_path, but that really don't want the file to be
+ opened but want instead just to know what the full pathname is (as
+ qualified against source_path).
+
+ The current working directory is searched first.
+
+ If the file was found, this function returns 1, and FULL_PATHNAME is
+ set to the fully-qualified pathname.
+
+ Else, this functions returns 0, and FULL_PATHNAME is set to NULL.
+ */
+int
+source_full_path_of (filename, full_pathname)
+ char * filename;
+ char ** full_pathname;
+{
+ int fd;
+
+ fd = openp (source_path, 1, filename, O_RDONLY, 0, full_pathname);
+ if (fd < 0)
+ {
+ *full_pathname = NULL;
+ return 0;
+ }
+
+ close (fd);
+ return 1;
+}
+
+
+/* Open a source file given a symtab S. Returns a file descriptor or
+ negative number for error. */
+
+int
+open_source_file (s)
+ struct symtab *s;
+{
+ char *path = source_path;
+ char *p;
+ int result;
+ char *fullname;
+
+ /* Quick way out if we already know its full name */
+ if (s->fullname)
+ {
+ result = open (s->fullname, OPEN_MODE);
+ 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] == DIRNAME_SEPARATOR)
+ && (p[cdir_len] == DIRNAME_SEPARATOR || 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, OPEN_MODE, 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, OPEN_MODE, 0, &s->fullname);
+ }
+#ifdef MPW
+ if (result < 0)
+ {
+ /* Didn't work. Try using just the MPW basename. */
+ p = (char *) mpw_basename (s->filename);
+ if (p != s->filename)
+ result = openp (path, 0, p, OPEN_MODE, 0, &s->fullname);
+ }
+ if (result < 0)
+ {
+ /* Didn't work. Try using the mixed Unix/MPW basename. */
+ p = (char *) mpw_mixed_basename (s->filename);
+ if (p != s->filename)
+ result = openp (path, 0, p, OPEN_MODE, 0, &s->fullname);
+ }
+#endif /* MPW */
+
+ if (result >= 0)
+ {
+ fullname = s->fullname;
+ s->fullname = mstrsave (s->objfile->md, s->fullname);
+ free (fullname);
+ }
+ return result;
+}
+
+/* Return the path to the source file associated with symtab. Returns NULL
+ if no symtab. */
+
+char *
+symtab_to_filename (s)
+ struct symtab *s;
+{
+ int fd;
+
+ if (!s)
+ return NULL;
+
+ /* If we've seen the file before, just return fullname. */
+
+ if (s->fullname)
+ return s->fullname;
+
+ /* Try opening the file to setup fullname */
+
+ fd = open_source_file (s);
+ if (fd < 0)
+ return s->filename; /* File not found. Just use short name */
+
+ /* Found the file. Cleanup and return the full name */
+
+ close (fd);
+ return s->fullname;
+}
+
+
+/* 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. */
+
+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 mtime = 0;
+ int size;
+
+ line_charpos = (int *) xmmalloc (s -> objfile -> md,
+ lines_allocated * sizeof (int));
+ if (fstat (desc, &st) < 0)
+ perror_with_name (s->filename);
+
+ if (s && s->objfile && s->objfile->obfd)
+ mtime = bfd_get_mtime(s->objfile->obfd);
+ else if (exec_bfd)
+ mtime = bfd_get_mtime(exec_bfd);
+
+ if (mtime && mtime < st.st_mtime)
+ {
+ if (tui_version)
+ printf_filtered ("\n");
+ warning("Source file is more recent than executable.\n");
+ }
+
+#ifdef LSEEK_NOT_LINEAR
+ {
+ char c;
+
+ /* Have to read it byte by byte to find out where the chars live */
+
+ line_charpos[0] = lseek (desc, 0, SEEK_CUR);
+ 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++] = lseek (desc, 0, SEEK_CUR);
+ }
+ }
+ }
+#else /* lseek linear. */
+ {
+ struct cleanup *old_cleanups;
+
+ /* st_size might be a large type, but we only support source files whose
+ size fits in an int. */
+ size = (int) st.st_size;
+
+ /* Use malloc, not alloca, because this may be pretty large, and we may
+ run into various kinds of limits on stack size. */
+ data = (char *) xmalloc (size);
+ old_cleanups = make_cleanup (free, data);
+
+ /* Reassign `size' to result of read for systems where \r\n -> \n. */
+ size = myread (desc, data, size);
+ if (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;
+ }
+ }
+ do_cleanups (old_cleanups);
+ }
+#endif /* lseek linear. */
+ 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;
+ annotate_source (s->fullname, line, s->line_charpos[line - 1],
+ mid_statement, 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. */
+
+static void
+print_source_lines_base (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;
+
+
+ /* Only prints "No such file or directory" once */
+ if ((s != last_source_visited) || (! last_source_error))
+ {
+ last_source_visited = s;
+ desc = open_source_file (s);
+ }
+ else
+ {
+ desc = last_source_error;
+ noerror = 1;
+ }
+
+ if (desc < 0)
+ {
+ last_source_error = desc;
+
+ if (! noerror)
+ {
+ char *name = alloca (strlen (s->filename) + 100);
+ sprintf (name, "%d\t%s", line, s->filename);
+ print_sys_errmsg (name, errno);
+ }
+ else
+ printf_filtered ("%d\tin %s\n", line, s->filename);
+
+ return;
+ }
+
+ last_source_error = 0;
+
+ 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, FDOPEN_MODE);
+ 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 ("^?");
+#ifdef CRLF_SOURCE_FILES
+ else if (c == '\r')
+ {
+ /* Just skip \r characters. */
+ }
+#endif
+ else
+ printf_filtered ("%c", c);
+ } while (c != '\n' && (c = fgetc (stream)) >= 0);
+ }
+
+ fclose (stream);
+}
+
+/* Show source lines from the file of symtab S, starting with line
+ number LINE and stopping before line number STOPLINE. If this is the
+ not the command line version, then the source is shown in the source
+ window otherwise it is simply printed */
+
+void
+print_source_lines (s, line, stopline, noerror)
+ struct symtab *s;
+ int line, stopline, noerror;
+{
+#if defined(TUI)
+ if (!tui_version ||
+ m_winPtrIsNull(srcWin) || !srcWin->generic.isVisible )
+ print_source_lines_base(s, line, stopline, noerror);
+ else
+ {
+ TuiGenWinInfoPtr locator = locatorWinInfoPtr();
+ extern void tui_vAddWinToLayout PARAMS ((va_list));
+ extern void tui_vUpdateSourceWindowsWithLine PARAMS ((va_list));
+
+ /* Regardless of whether we can open the file,
+ set current_source_symtab. */
+ current_source_symtab = s;
+ current_source_line = line;
+ first_line_listed = line;
+
+ /* make sure that the source window is displayed */
+ tuiDo((TuiOpaqueFuncPtr)tui_vAddWinToLayout, SRC_WIN);
+
+ tuiDo((TuiOpaqueFuncPtr)tui_vUpdateSourceWindowsWithLine, s, line);
+ tuiDo((TuiOpaqueFuncPtr)tui_vUpdateLocatorFilename, s->filename);
+ }
+#else
+ print_source_lines_base(s, line, stopline, noerror);
+#endif
+}
+
+
+
+/* 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)
+ /* FIXME-32x64--assumes sal.pc fits in long. */
+ error ("No source file for address %s.",
+ local_hex_string((unsigned long) sal.pc));
+ sym = find_pc_function (sal.pc);
+ if (sym)
+ {
+ print_address_numeric (sal.pc, 1, gdb_stdout);
+ printf_filtered (" is in ");
+ fputs_filtered (SYMBOL_SOURCE_NAME (sym), gdb_stdout);
+ printf_filtered (" (%s:%d).\n", sal.symtab->filename, sal.line);
+ }
+ else
+ {
+ print_address_numeric (sal.pc, 1, gdb_stdout);
+ printf_filtered (" is at %s:%d.\n",
+ 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)
+ if (lines_to_list % 2 == 0)
+ print_source_lines (sal.symtab,
+ max (sal.line - (lines_to_list / 2), 1),
+ sal.line + (lines_to_list / 2), 0);
+ else
+ /* If lines_to_list is odd, then we round down in
+ * one of the lines_to_list/2 computations, round up in
+ * the other, so the total window size around the specified
+ * line comes out right.
+ */
+ print_source_lines (sal.symtab,
+ max (sal.line - (lines_to_list / 2), 1),
+ sal.line + ((1+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;
+
+ INIT_SAL (&sal); /* initialize to zeroes */
+
+ 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, gdb_stdout);
+ }
+ else
+ printf_filtered (".");
+ printf_filtered ("\n");
+ }
+ else if (sal.line > 0
+ && find_line_pc_range (sal, &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, gdb_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, gdb_stdout);
+ wrap_here (" ");
+ printf_filtered (" and ends at ");
+ print_address (end_pc, gdb_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 (annotation_level && 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;
+ char *msg;
+
+#if defined(TUI)
+ /*
+ ** If this is the TUI, search from the first line displayed in
+ ** the source window, otherwise, search from last_line_listed+1
+ ** in current_source_symtab
+ */
+ if (!tui_version)
+ line = last_line_listed;
+ else
+ {
+ if (srcWin->generic.isVisible && srcWin->generic.contentSize > 0)
+ line = ((TuiWinContent)
+ srcWin->generic.content)[0]->whichElement.source.lineOrAddr.lineNo;
+ else
+ {
+ printf_filtered("No source displayed.\nExpression not found.\n");
+ return;
+ }
+ }
+ line++;
+#else
+ line = last_line_listed + 1;
+#endif
+
+ msg = (char *) re_comp (regex);
+ if (msg)
+ error (msg);
+
+ if (current_source_symtab == 0)
+ select_source_symtab (0);
+
+ 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, FDOPEN_MODE);
+ clearerr (stream);
+ while (1) {
+ static char *buf = NULL;
+ register char *p;
+ int cursize, newsize;
+
+ cursize = 256;
+ buf = xmalloc (cursize);
+ p = buf;
+
+ c = getc (stream);
+ if (c == EOF)
+ break;
+ do {
+ *p++ = c;
+ if (p - buf == cursize)
+ {
+ newsize = cursize + cursize / 2;
+ buf = xrealloc (buf, newsize);
+ p = buf + cursize;
+ cursize = newsize;
+ }
+ } 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);
+ if (tui_version)
+ print_source_lines_base (current_source_symtab, line, line+1, 0);
+ print_source_lines (current_source_symtab, line, line+1, 0);
+ set_internalvar (lookup_internalvar ("_"),
+ value_from_longest (builtin_type_int,
+ (LONGEST) line));
+ 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;
+ char *msg;
+#if defined(TUI)
+ /*
+ ** If this is the TUI, search from the first line displayed in
+ ** the source window, otherwise, search from last_line_listed-1
+ ** in current_source_symtab
+ */
+ if (!tui_version)
+ line = last_line_listed;
+ else
+ {
+ if (srcWin->generic.isVisible && srcWin->generic.contentSize > 0)
+ line = ((TuiWinContent)
+ srcWin->generic.content)[0]->whichElement.source.lineOrAddr.lineNo;
+ else
+ {
+ printf_filtered("No source displayed.\nExpression not found.\n");
+ return;
+ }
+ }
+ line--;
+#else
+ line = last_line_listed - 1;
+#endif
+
+ msg = (char *) re_comp (regex);
+ if (msg)
+ error (msg);
+
+ if (current_source_symtab == 0)
+ select_source_symtab (0);
+
+ 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, FDOPEN_MODE);
+ 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);
+ if (tui_version)
+ print_source_lines_base (current_source_symtab, line, line+1, 0);
+ print_source_lines (current_source_symtab, line, line+1, 0);
+ set_internalvar (lookup_internalvar ("_"),
+ value_from_longest (builtin_type_int,
+ (LONGEST) line));
+ 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);
+
+ if (dbx_commands)
+ add_com_alias("use", "directory", class_files, 0);
+
+ 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);
+
+ if (xdb_commands)
+ {
+ add_com_alias("D", "directory", class_files, 0);
+ add_cmd ("ld", 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.",
+ &cmdlist);
+ }
+
+ add_info ("source", source_info,
+ "Information about the current source file.");
+
+ add_info ("line", line_info,
+ concat ("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 \"$_\".", NULL));
+
+ add_com ("forward-search", class_files, forward_search_command,
+ "Search for regular expression (see regex(3)) from last line listed.\n\
+The matching line number is also stored as the value of \"$_\".");
+ 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.\n\
+The matching line number is also stored as the value of \"$_\".");
+
+ if (xdb_commands)
+ {
+ add_com_alias("/", "forward-search", class_files, 0);
+ add_com_alias("?", "reverse-search", class_files, 0);
+ }
+
+ add_com ("list", class_files, list_command,
+ concat ("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.", NULL));
+
+ if (!xdb_commands)
+ add_com_alias ("l", "list", class_files, 1);
+ else
+ add_com_alias ("v", "list", class_files, 1);
+
+ if (dbx_commands)
+ add_com_alias ("file", "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/gdb/sparc-nat.c b/gdb/sparc-nat.c
new file mode 100644
index 00000000000..3f5f8bf748c
--- /dev/null
+++ b/gdb/sparc-nat.c
@@ -0,0 +1,328 @@
+/* Functions specific to running gdb native on a SPARC running SunOS4.
+ Copyright 1989, 1992, 1993, 1994, 1996 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "inferior.h"
+#include "target.h"
+#include "gdbcore.h"
+
+#include <signal.h>
+#include <sys/ptrace.h>
+#include <sys/wait.h>
+#ifdef __linux__
+#include <asm/reg.h>
+#else
+#include <machine/reg.h>
+#endif
+#include <sys/user.h>
+
+/* We don't store all registers immediately when requested, since they
+ get sent over in large chunks anyway. Instead, we accumulate most
+ of the changes and send them over once. "deferred_stores" keeps
+ track of which sets of registers we have locally-changed copies of,
+ so we only need send the groups that have changed. */
+
+#define INT_REGS 1
+#define STACK_REGS 2
+#define FP_REGS 4
+
+static void
+fetch_core_registers PARAMS ((char *, unsigned int, int, CORE_ADDR));
+
+/* Fetch one or more registers from the inferior. REGNO == -1 to get
+ them all. We actually fetch more than requested, when convenient,
+ marking them as valid so we won't fetch them again. */
+
+void
+fetch_inferior_registers (regno)
+ int regno;
+{
+ struct regs inferior_registers;
+ struct fp_status inferior_fp_registers;
+ int i;
+
+ /* We should never be called with deferred stores, because a prerequisite
+ for writing regs is to have fetched them all (PREPARE_TO_STORE), sigh. */
+ if (deferred_stores) abort();
+
+ DO_DEFERRED_STORES;
+
+ /* Global and Out regs are fetched directly, as well as the control
+ registers. If we're getting one of the in or local regs,
+ and the stack pointer has not yet been fetched,
+ we have to do that first, since they're found in memory relative
+ to the stack pointer. */
+ if (regno < O7_REGNUM /* including -1 */
+ || regno >= Y_REGNUM
+ || (!register_valid[SP_REGNUM] && regno < I7_REGNUM))
+ {
+ if (0 != ptrace (PTRACE_GETREGS, inferior_pid,
+ (PTRACE_ARG3_TYPE) &inferior_registers, 0))
+ perror("ptrace_getregs");
+
+ registers[REGISTER_BYTE (0)] = 0;
+ memcpy (&registers[REGISTER_BYTE (1)], &inferior_registers.r_g1,
+ 15 * REGISTER_RAW_SIZE (G0_REGNUM));
+ *(int *)&registers[REGISTER_BYTE (PS_REGNUM)] = inferior_registers.r_ps;
+ *(int *)&registers[REGISTER_BYTE (PC_REGNUM)] = inferior_registers.r_pc;
+ *(int *)&registers[REGISTER_BYTE (NPC_REGNUM)] = inferior_registers.r_npc;
+ *(int *)&registers[REGISTER_BYTE (Y_REGNUM)] = inferior_registers.r_y;
+
+ for (i = G0_REGNUM; i <= O7_REGNUM; i++)
+ register_valid[i] = 1;
+ register_valid[Y_REGNUM] = 1;
+ register_valid[PS_REGNUM] = 1;
+ register_valid[PC_REGNUM] = 1;
+ register_valid[NPC_REGNUM] = 1;
+ /* If we don't set these valid, read_register_bytes() rereads
+ all the regs every time it is called! FIXME. */
+ register_valid[WIM_REGNUM] = 1; /* Not true yet, FIXME */
+ register_valid[TBR_REGNUM] = 1; /* Not true yet, FIXME */
+ register_valid[CPS_REGNUM] = 1; /* Not true yet, FIXME */
+ }
+
+ /* Floating point registers */
+ if (regno == -1 ||
+ regno == FPS_REGNUM ||
+ (regno >= FP0_REGNUM && regno <= FP0_REGNUM + 31))
+ {
+ if (0 != ptrace (PTRACE_GETFPREGS, inferior_pid,
+ (PTRACE_ARG3_TYPE) &inferior_fp_registers,
+ 0))
+ perror("ptrace_getfpregs");
+ memcpy (&registers[REGISTER_BYTE (FP0_REGNUM)], &inferior_fp_registers,
+ sizeof inferior_fp_registers.fpu_fr);
+ memcpy (&registers[REGISTER_BYTE (FPS_REGNUM)],
+ &inferior_fp_registers.Fpu_fsr,
+ sizeof (FPU_FSR_TYPE));
+ for (i = FP0_REGNUM; i <= FP0_REGNUM+31; i++)
+ register_valid[i] = 1;
+ register_valid[FPS_REGNUM] = 1;
+ }
+
+ /* These regs are saved on the stack by the kernel. Only read them
+ all (16 ptrace calls!) if we really need them. */
+ if (regno == -1)
+ {
+ target_read_memory (*(CORE_ADDR*)&registers[REGISTER_BYTE (SP_REGNUM)],
+ &registers[REGISTER_BYTE (L0_REGNUM)],
+ 16*REGISTER_RAW_SIZE (L0_REGNUM));
+ for (i = L0_REGNUM; i <= I7_REGNUM; i++)
+ register_valid[i] = 1;
+ }
+ else if (regno >= L0_REGNUM && regno <= I7_REGNUM)
+ {
+ CORE_ADDR sp = *(CORE_ADDR*)&registers[REGISTER_BYTE (SP_REGNUM)];
+ i = REGISTER_BYTE (regno);
+ if (register_valid[regno])
+ printf_unfiltered("register %d valid and read\n", regno);
+ target_read_memory (sp + i - REGISTER_BYTE (L0_REGNUM),
+ &registers[i], REGISTER_RAW_SIZE (regno));
+ register_valid[regno] = 1;
+ }
+}
+
+/* Store our register values back into the inferior.
+ If REGNO is -1, do this for all registers.
+ Otherwise, REGNO specifies which register (so we can save time). */
+
+void
+store_inferior_registers (regno)
+ int regno;
+{
+ struct regs inferior_registers;
+ struct fp_status inferior_fp_registers;
+ int wanna_store = INT_REGS + STACK_REGS + FP_REGS;
+
+ /* First decide which pieces of machine-state we need to modify.
+ Default for regno == -1 case is all pieces. */
+ if (regno >= 0)
+ if (FP0_REGNUM <= regno && regno < FP0_REGNUM + 32)
+ {
+ wanna_store = FP_REGS;
+ }
+ else
+ {
+ if (regno == SP_REGNUM)
+ wanna_store = INT_REGS + STACK_REGS;
+ else if (regno < L0_REGNUM || regno > I7_REGNUM)
+ wanna_store = INT_REGS;
+ else if (regno == FPS_REGNUM)
+ wanna_store = FP_REGS;
+ else
+ wanna_store = STACK_REGS;
+ }
+
+ /* See if we're forcing the stores to happen now, or deferring. */
+ if (regno == -2)
+ {
+ wanna_store = deferred_stores;
+ deferred_stores = 0;
+ }
+ else
+ {
+ if (wanna_store == STACK_REGS)
+ {
+ /* Fall through and just store one stack reg. If we deferred
+ it, we'd have to store them all, or remember more info. */
+ }
+ else
+ {
+ deferred_stores |= wanna_store;
+ return;
+ }
+ }
+
+ if (wanna_store & STACK_REGS)
+ {
+ CORE_ADDR sp = *(CORE_ADDR *)&registers[REGISTER_BYTE (SP_REGNUM)];
+
+ if (regno < 0 || regno == SP_REGNUM)
+ {
+ if (!register_valid[L0_REGNUM+5]) abort();
+ target_write_memory (sp,
+ &registers[REGISTER_BYTE (L0_REGNUM)],
+ 16*REGISTER_RAW_SIZE (L0_REGNUM));
+ }
+ else
+ {
+ if (!register_valid[regno]) abort();
+ target_write_memory (sp + REGISTER_BYTE (regno) - REGISTER_BYTE (L0_REGNUM),
+ &registers[REGISTER_BYTE (regno)],
+ REGISTER_RAW_SIZE (regno));
+ }
+
+ }
+
+ if (wanna_store & INT_REGS)
+ {
+ if (!register_valid[G1_REGNUM]) abort();
+
+ memcpy (&inferior_registers.r_g1, &registers[REGISTER_BYTE (G1_REGNUM)],
+ 15 * REGISTER_RAW_SIZE (G1_REGNUM));
+
+ inferior_registers.r_ps =
+ *(int *)&registers[REGISTER_BYTE (PS_REGNUM)];
+ inferior_registers.r_pc =
+ *(int *)&registers[REGISTER_BYTE (PC_REGNUM)];
+ inferior_registers.r_npc =
+ *(int *)&registers[REGISTER_BYTE (NPC_REGNUM)];
+ inferior_registers.r_y =
+ *(int *)&registers[REGISTER_BYTE (Y_REGNUM)];
+
+ if (0 != ptrace (PTRACE_SETREGS, inferior_pid,
+ (PTRACE_ARG3_TYPE) &inferior_registers, 0))
+ perror("ptrace_setregs");
+ }
+
+ if (wanna_store & FP_REGS)
+ {
+ if (!register_valid[FP0_REGNUM+9]) abort();
+ memcpy (&inferior_fp_registers, &registers[REGISTER_BYTE (FP0_REGNUM)],
+ sizeof inferior_fp_registers.fpu_fr);
+ memcpy (&inferior_fp_registers.Fpu_fsr,
+ &registers[REGISTER_BYTE (FPS_REGNUM)], sizeof (FPU_FSR_TYPE));
+ if (0 !=
+ ptrace (PTRACE_SETFPREGS, inferior_pid,
+ (PTRACE_ARG3_TYPE) &inferior_fp_registers, 0))
+ perror("ptrace_setfpregs");
+ }
+}
+
+
+static void
+fetch_core_registers (core_reg_sect, core_reg_size, which, ignore)
+ char *core_reg_sect;
+ unsigned core_reg_size;
+ int which;
+ CORE_ADDR ignore; /* reg addr, unused in this version */
+{
+
+ if (which == 0) {
+
+ /* Integer registers */
+
+#define gregs ((struct regs *)core_reg_sect)
+ /* G0 *always* holds 0. */
+ *(int *)&registers[REGISTER_BYTE (0)] = 0;
+
+ /* The globals and output registers. */
+ memcpy (&registers[REGISTER_BYTE (G1_REGNUM)], &gregs->r_g1,
+ 15 * REGISTER_RAW_SIZE (G1_REGNUM));
+ *(int *)&registers[REGISTER_BYTE (PS_REGNUM)] = gregs->r_ps;
+ *(int *)&registers[REGISTER_BYTE (PC_REGNUM)] = gregs->r_pc;
+ *(int *)&registers[REGISTER_BYTE (NPC_REGNUM)] = gregs->r_npc;
+ *(int *)&registers[REGISTER_BYTE (Y_REGNUM)] = gregs->r_y;
+
+ /* My best guess at where to get the locals and input
+ registers is exactly where they usually are, right above
+ the stack pointer. If the core dump was caused by a bus error
+ from blowing away the stack pointer (as is possible) then this
+ won't work, but it's worth the try. */
+ {
+ int sp;
+
+ sp = *(int *)&registers[REGISTER_BYTE (SP_REGNUM)];
+ if (0 != target_read_memory (sp, &registers[REGISTER_BYTE (L0_REGNUM)],
+ 16 * REGISTER_RAW_SIZE (L0_REGNUM)))
+ {
+ /* fprintf_unfiltered so user can still use gdb */
+ fprintf_unfiltered (gdb_stderr,
+ "Couldn't read input and local registers from core file\n");
+ }
+ }
+ } else if (which == 2) {
+
+ /* Floating point registers */
+
+#define fpuregs ((struct fpu *) core_reg_sect)
+ if (core_reg_size >= sizeof (struct fpu))
+ {
+ memcpy (&registers[REGISTER_BYTE (FP0_REGNUM)], fpuregs->fpu_regs,
+ sizeof (fpuregs->fpu_regs));
+ memcpy (&registers[REGISTER_BYTE (FPS_REGNUM)], &fpuregs->fpu_fsr,
+ sizeof (FPU_FSR_TYPE));
+ }
+ else
+ fprintf_unfiltered (gdb_stderr, "Couldn't read float regs from core file\n");
+ }
+}
+
+int
+kernel_u_size ()
+{
+ return (sizeof (struct user));
+}
+
+
+/* Register that we are able to handle sparc core file formats.
+ FIXME: is this really bfd_target_unknown_flavour? */
+
+static struct core_fns sparc_core_fns =
+{
+ bfd_target_unknown_flavour,
+ fetch_core_registers,
+ NULL
+};
+
+void
+_initialize_core_sparc ()
+{
+ add_core_fns (&sparc_core_fns);
+}
diff --git a/gdb/sparc-stub.c b/gdb/sparc-stub.c
new file mode 100644
index 00000000000..7da65c21080
--- /dev/null
+++ b/gdb/sparc-stub.c
@@ -0,0 +1,846 @@
+/****************************************************************************
+
+ THIS SOFTWARE IS NOT COPYRIGHTED
+
+ HP offers the following for use in the public domain. HP makes no
+ warranty with regard to the software or it's performance and the
+ user accepts the software "AS IS" with all faults.
+
+ HP DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD
+ TO THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+
+****************************************************************************/
+
+/****************************************************************************
+ * Header: remcom.c,v 1.34 91/03/09 12:29:49 glenne Exp $
+ *
+ * Module name: remcom.c $
+ * Revision: 1.34 $
+ * Date: 91/03/09 12:29:49 $
+ * Contributor: Lake Stevens Instrument Division$
+ *
+ * Description: low level support for gdb debugger. $
+ *
+ * Considerations: only works on target hardware $
+ *
+ * Written by: Glenn Engel $
+ * ModuleState: Experimental $
+ *
+ * NOTES: See Below $
+ *
+ * Modified for SPARC by Stu Grossman, Cygnus Support.
+ *
+ * This code has been extensively tested on the Fujitsu SPARClite demo board.
+ *
+ * To enable debugger support, two things need to happen. One, a
+ * call to set_debug_traps() is necessary in order to allow any breakpoints
+ * or error conditions to be properly intercepted and reported to gdb.
+ * Two, a breakpoint needs to be generated to begin communication. This
+ * is most easily accomplished by a call to breakpoint(). Breakpoint()
+ * simulates a breakpoint by executing a trap #1.
+ *
+ *************
+ *
+ * The following gdb commands are supported:
+ *
+ * command function Return value
+ *
+ * g return the value of the CPU registers hex data or ENN
+ * G set the value of the CPU registers OK or ENN
+ *
+ * mAA..AA,LLLL Read LLLL bytes at address AA..AA hex data or ENN
+ * MAA..AA,LLLL: Write LLLL bytes at address AA.AA OK or ENN
+ *
+ * c Resume at current address SNN ( signal NN)
+ * cAA..AA Continue at address AA..AA SNN
+ *
+ * s Step one instruction SNN
+ * sAA..AA Step one instruction from AA..AA SNN
+ *
+ * k kill
+ *
+ * ? What was the last sigval ? SNN (signal NN)
+ *
+ * bBB..BB Set baud rate to BB..BB OK or BNN, then sets
+ * baud rate
+ *
+ * All commands and responses are sent with a packet which includes a
+ * checksum. A packet consists of
+ *
+ * $<packet info>#<checksum>.
+ *
+ * where
+ * <packet info> :: <characters representing the command or response>
+ * <checksum> :: < two hex digits computed as modulo 256 sum of <packetinfo>>
+ *
+ * When a packet is received, it is first acknowledged with either '+' or '-'.
+ * '+' indicates a successful transfer. '-' indicates a failed transfer.
+ *
+ * Example:
+ *
+ * Host: Reply:
+ * $m0,10#2a +$00010203040506070809101112131415#42
+ *
+ ****************************************************************************/
+
+#include <string.h>
+#include <signal.h>
+
+/************************************************************************
+ *
+ * external low-level support routines
+ */
+
+extern void putDebugChar(); /* write a single character */
+extern int getDebugChar(); /* read and return a single char */
+
+/************************************************************************/
+/* BUFMAX defines the maximum number of characters in inbound/outbound buffers*/
+/* at least NUMREGBYTES*2 are needed for register packets */
+#define BUFMAX 2048
+
+static int initialized = 0; /* !0 means we've been initialized */
+
+static void set_mem_fault_trap();
+
+static const char hexchars[]="0123456789abcdef";
+
+#define NUMREGS 72
+
+/* Number of bytes of registers. */
+#define NUMREGBYTES (NUMREGS * 4)
+enum regnames {G0, G1, G2, G3, G4, G5, G6, G7,
+ O0, O1, O2, O3, O4, O5, SP, O7,
+ L0, L1, L2, L3, L4, L5, L6, L7,
+ I0, I1, I2, I3, I4, I5, FP, I7,
+
+ F0, F1, F2, F3, F4, F5, F6, F7,
+ F8, F9, F10, F11, F12, F13, F14, F15,
+ F16, F17, F18, F19, F20, F21, F22, F23,
+ F24, F25, F26, F27, F28, F29, F30, F31,
+ Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR };
+
+/*************************** ASSEMBLY CODE MACROS *************************/
+/* */
+
+extern void trap_low();
+
+asm("
+ .reserve trapstack, 1000 * 4, \"bss\", 8
+
+ .data
+ .align 4
+
+in_trap_handler:
+ .word 0
+
+ .text
+ .align 4
+
+! This function is called when any SPARC trap (except window overflow or
+! underflow) occurs. It makes sure that the invalid register window is still
+! available before jumping into C code. It will also restore the world if you
+! return from handle_exception.
+
+ .globl _trap_low
+_trap_low:
+ mov %psr, %l0
+ mov %wim, %l3
+
+ srl %l3, %l0, %l4 ! wim >> cwp
+ cmp %l4, 1
+ bne window_fine ! Branch if not in the invalid window
+ nop
+
+! Handle window overflow
+
+ mov %g1, %l4 ! Save g1, we use it to hold the wim
+ srl %l3, 1, %g1 ! Rotate wim right
+ tst %g1
+ bg good_wim ! Branch if new wim is non-zero
+ nop
+
+! At this point, we need to bring a 1 into the high order bit of the wim.
+! Since we don't want to make any assumptions about the number of register
+! windows, we figure it out dynamically so as to setup the wim correctly.
+
+ not %g1 ! Fill g1 with ones
+ mov %g1, %wim ! Fill the wim with ones
+ nop
+ nop
+ nop
+ mov %wim, %g1 ! Read back the wim
+ inc %g1 ! Now g1 has 1 just to left of wim
+ srl %g1, 1, %g1 ! Now put 1 at top of wim
+ mov %g0, %wim ! Clear wim so that subsequent save
+ nop ! won't trap
+ nop
+ nop
+
+good_wim:
+ save %g0, %g0, %g0 ! Slip into next window
+ mov %g1, %wim ! Install the new wim
+
+ std %l0, [%sp + 0 * 4] ! save L & I registers
+ std %l2, [%sp + 2 * 4]
+ std %l4, [%sp + 4 * 4]
+ std %l6, [%sp + 6 * 4]
+
+ std %i0, [%sp + 8 * 4]
+ std %i2, [%sp + 10 * 4]
+ std %i4, [%sp + 12 * 4]
+ std %i6, [%sp + 14 * 4]
+
+ restore ! Go back to trap window.
+ mov %l4, %g1 ! Restore %g1
+
+window_fine:
+ sethi %hi(in_trap_handler), %l4
+ ld [%lo(in_trap_handler) + %l4], %l5
+ tst %l5
+ bg recursive_trap
+ inc %l5
+
+ set trapstack+1000*4, %sp ! Switch to trap stack
+
+recursive_trap:
+ st %l5, [%lo(in_trap_handler) + %l4]
+ sub %sp,(16+1+6+1+72)*4,%sp ! Make room for input & locals
+ ! + hidden arg + arg spill
+ ! + doubleword alignment
+ ! + registers[72] local var
+
+ std %g0, [%sp + (24 + 0) * 4] ! registers[Gx]
+ std %g2, [%sp + (24 + 2) * 4]
+ std %g4, [%sp + (24 + 4) * 4]
+ std %g6, [%sp + (24 + 6) * 4]
+
+ std %i0, [%sp + (24 + 8) * 4] ! registers[Ox]
+ std %i2, [%sp + (24 + 10) * 4]
+ std %i4, [%sp + (24 + 12) * 4]
+ std %i6, [%sp + (24 + 14) * 4]
+ ! F0->F31 not implemented
+ mov %y, %l4
+ mov %tbr, %l5
+ st %l4, [%sp + (24 + 64) * 4] ! Y
+ st %l0, [%sp + (24 + 65) * 4] ! PSR
+ st %l3, [%sp + (24 + 66) * 4] ! WIM
+ st %l5, [%sp + (24 + 67) * 4] ! TBR
+ st %l1, [%sp + (24 + 68) * 4] ! PC
+ st %l2, [%sp + (24 + 69) * 4] ! NPC
+
+ ! CPSR and FPSR not impl
+
+ or %l0, 0xf20, %l4
+ mov %l4, %psr ! Turn on traps, disable interrupts
+
+ call _handle_exception
+ add %sp, 24 * 4, %o0 ! Pass address of registers
+
+! Reload all of the registers that aren't on the stack
+
+ ld [%sp + (24 + 1) * 4], %g1 ! registers[Gx]
+ ldd [%sp + (24 + 2) * 4], %g2
+ ldd [%sp + (24 + 4) * 4], %g4
+ ldd [%sp + (24 + 6) * 4], %g6
+
+ ldd [%sp + (24 + 8) * 4], %i0 ! registers[Ox]
+ ldd [%sp + (24 + 10) * 4], %i2
+ ldd [%sp + (24 + 12) * 4], %i4
+ ldd [%sp + (24 + 14) * 4], %i6
+
+ ldd [%sp + (24 + 64) * 4], %l0 ! Y & PSR
+ ldd [%sp + (24 + 68) * 4], %l2 ! PC & NPC
+
+ restore ! Ensure that previous window is valid
+ save %g0, %g0, %g0 ! by causing a window_underflow trap
+
+ mov %l0, %y
+ mov %l1, %psr ! Make sure that traps are disabled
+ ! for rett
+
+ sethi %hi(in_trap_handler), %l4
+ ld [%lo(in_trap_handler) + %l4], %l5
+ dec %l5
+ st %l5, [%lo(in_trap_handler) + %l4]
+
+ jmpl %l2, %g0 ! Restore old PC
+ rett %l3 ! Restore old nPC
+");
+
+/* Convert ch from a hex digit to an int */
+
+static int
+hex(ch)
+ unsigned char ch;
+{
+ if (ch >= 'a' && ch <= 'f')
+ return ch-'a'+10;
+ if (ch >= '0' && ch <= '9')
+ return ch-'0';
+ if (ch >= 'A' && ch <= 'F')
+ return ch-'A'+10;
+ return -1;
+}
+
+/* scan for the sequence $<data>#<checksum> */
+
+static void
+getpacket(buffer)
+ char *buffer;
+{
+ unsigned char checksum;
+ unsigned char xmitcsum;
+ int i;
+ int count;
+ unsigned char ch;
+
+ do
+ {
+ /* wait around for the start character, ignore all other characters */
+ while ((ch = (getDebugChar() & 0x7f)) != '$') ;
+
+ checksum = 0;
+ xmitcsum = -1;
+
+ count = 0;
+
+ /* now, read until a # or end of buffer is found */
+ while (count < BUFMAX)
+ {
+ ch = getDebugChar() & 0x7f;
+ if (ch == '#')
+ break;
+ checksum = checksum + ch;
+ buffer[count] = ch;
+ count = count + 1;
+ }
+
+ if (count >= BUFMAX)
+ continue;
+
+ buffer[count] = 0;
+
+ if (ch == '#')
+ {
+ xmitcsum = hex(getDebugChar() & 0x7f) << 4;
+ xmitcsum |= hex(getDebugChar() & 0x7f);
+#if 0
+ /* Humans shouldn't have to figure out checksums to type to it. */
+ putDebugChar ('+');
+ return;
+#endif
+ if (checksum != xmitcsum)
+ putDebugChar('-'); /* failed checksum */
+ else
+ {
+ putDebugChar('+'); /* successful transfer */
+ /* if a sequence char is present, reply the sequence ID */
+ if (buffer[2] == ':')
+ {
+ putDebugChar(buffer[0]);
+ putDebugChar(buffer[1]);
+ /* remove sequence chars from buffer */
+ count = strlen(buffer);
+ for (i=3; i <= count; i++)
+ buffer[i-3] = buffer[i];
+ }
+ }
+ }
+ }
+ while (checksum != xmitcsum);
+}
+
+/* send the packet in buffer. */
+
+static void
+putpacket(buffer)
+ unsigned char *buffer;
+{
+ unsigned char checksum;
+ int count;
+ unsigned char ch;
+
+ /* $<packet info>#<checksum>. */
+ do
+ {
+ putDebugChar('$');
+ checksum = 0;
+ count = 0;
+
+ while (ch = buffer[count])
+ {
+ putDebugChar(ch);
+ checksum += ch;
+ count += 1;
+ }
+
+ putDebugChar('#');
+ putDebugChar(hexchars[checksum >> 4]);
+ putDebugChar(hexchars[checksum & 0xf]);
+
+ }
+ while ((getDebugChar() & 0x7f) != '+');
+}
+
+static char remcomInBuffer[BUFMAX];
+static char remcomOutBuffer[BUFMAX];
+
+/* Indicate to caller of mem2hex or hex2mem that there has been an
+ error. */
+static volatile int mem_err = 0;
+
+/* Convert the memory pointed to by mem into hex, placing result in buf.
+ * Return a pointer to the last char put in buf (null), in case of mem fault,
+ * return 0.
+ * If MAY_FAULT is non-zero, then we will handle memory faults by returning
+ * a 0, else treat a fault like any other fault in the stub.
+ */
+
+static unsigned char *
+mem2hex(mem, buf, count, may_fault)
+ unsigned char *mem;
+ unsigned char *buf;
+ int count;
+ int may_fault;
+{
+ unsigned char ch;
+
+ set_mem_fault_trap(may_fault);
+
+ while (count-- > 0)
+ {
+ ch = *mem++;
+ if (mem_err)
+ return 0;
+ *buf++ = hexchars[ch >> 4];
+ *buf++ = hexchars[ch & 0xf];
+ }
+
+ *buf = 0;
+
+ set_mem_fault_trap(0);
+
+ return buf;
+}
+
+/* convert the hex array pointed to by buf into binary to be placed in mem
+ * return a pointer to the character AFTER the last byte written */
+
+static char *
+hex2mem(buf, mem, count, may_fault)
+ unsigned char *buf;
+ unsigned char *mem;
+ int count;
+ int may_fault;
+{
+ int i;
+ unsigned char ch;
+
+ set_mem_fault_trap(may_fault);
+
+ for (i=0; i<count; i++)
+ {
+ ch = hex(*buf++) << 4;
+ ch |= hex(*buf++);
+ *mem++ = ch;
+ if (mem_err)
+ return 0;
+ }
+
+ set_mem_fault_trap(0);
+
+ return mem;
+}
+
+/* This table contains the mapping between SPARC hardware trap types, and
+ signals, which are primarily what GDB understands. It also indicates
+ which hardware traps we need to commandeer when initializing the stub. */
+
+static struct hard_trap_info
+{
+ unsigned char tt; /* Trap type code for SPARClite */
+ unsigned char signo; /* Signal that we map this trap into */
+} hard_trap_info[] = {
+ {1, SIGSEGV}, /* instruction access error */
+ {2, SIGILL}, /* privileged instruction */
+ {3, SIGILL}, /* illegal instruction */
+ {4, SIGEMT}, /* fp disabled */
+ {36, SIGEMT}, /* cp disabled */
+ {7, SIGBUS}, /* mem address not aligned */
+ {9, SIGSEGV}, /* data access exception */
+ {10, SIGEMT}, /* tag overflow */
+ {128+1, SIGTRAP}, /* ta 1 - normal breakpoint instruction */
+ {0, 0} /* Must be last */
+};
+
+/* Set up exception handlers for tracing and breakpoints */
+
+void
+set_debug_traps()
+{
+ struct hard_trap_info *ht;
+
+ for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
+ exceptionHandler(ht->tt, trap_low);
+
+ /* In case GDB is started before us, ack any packets (presumably
+ "$?#xx") sitting there. */
+
+ putDebugChar ('+');
+
+ initialized = 1;
+}
+
+asm ("
+! Trap handler for memory errors. This just sets mem_err to be non-zero. It
+! assumes that %l1 is non-zero. This should be safe, as it is doubtful that
+! 0 would ever contain code that could mem fault. This routine will skip
+! past the faulting instruction after setting mem_err.
+
+ .text
+ .align 4
+
+_fltr_set_mem_err:
+ sethi %hi(_mem_err), %l0
+ st %l1, [%l0 + %lo(_mem_err)]
+ jmpl %l2, %g0
+ rett %l2+4
+");
+
+static void
+set_mem_fault_trap(enable)
+ int enable;
+{
+ extern void fltr_set_mem_err();
+ mem_err = 0;
+
+ if (enable)
+ exceptionHandler(9, fltr_set_mem_err);
+ else
+ exceptionHandler(9, trap_low);
+}
+
+/* Convert the SPARC hardware trap type code to a unix signal number. */
+
+static int
+computeSignal(tt)
+ int tt;
+{
+ struct hard_trap_info *ht;
+
+ for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
+ if (ht->tt == tt)
+ return ht->signo;
+
+ return SIGHUP; /* default for things we don't know about */
+}
+
+/*
+ * While we find nice hex chars, build an int.
+ * Return number of chars processed.
+ */
+
+static int
+hexToInt(char **ptr, int *intValue)
+{
+ int numChars = 0;
+ int hexValue;
+
+ *intValue = 0;
+
+ while (**ptr)
+ {
+ hexValue = hex(**ptr);
+ if (hexValue < 0)
+ break;
+
+ *intValue = (*intValue << 4) | hexValue;
+ numChars ++;
+
+ (*ptr)++;
+ }
+
+ return (numChars);
+}
+
+/*
+ * This function does all command procesing for interfacing to gdb. It
+ * returns 1 if you should skip the instruction at the trap address, 0
+ * otherwise.
+ */
+
+extern void breakinst();
+
+static void
+handle_exception (registers)
+ unsigned long *registers;
+{
+ int tt; /* Trap type */
+ int sigval;
+ int addr;
+ int length;
+ char *ptr;
+ unsigned long *sp;
+
+/* First, we must force all of the windows to be spilled out */
+
+ asm(" save %sp, -64, %sp
+ save %sp, -64, %sp
+ save %sp, -64, %sp
+ save %sp, -64, %sp
+ save %sp, -64, %sp
+ save %sp, -64, %sp
+ save %sp, -64, %sp
+ save %sp, -64, %sp
+ restore
+ restore
+ restore
+ restore
+ restore
+ restore
+ restore
+ restore
+");
+
+ if (registers[PC] == (unsigned long)breakinst)
+ {
+ registers[PC] = registers[NPC];
+ registers[NPC] += 4;
+ }
+
+ sp = (unsigned long *)registers[SP];
+
+ tt = (registers[TBR] >> 4) & 0xff;
+
+ /* reply to host that an exception has occurred */
+ sigval = computeSignal(tt);
+ ptr = remcomOutBuffer;
+
+ *ptr++ = 'T';
+ *ptr++ = hexchars[sigval >> 4];
+ *ptr++ = hexchars[sigval & 0xf];
+
+ *ptr++ = hexchars[PC >> 4];
+ *ptr++ = hexchars[PC & 0xf];
+ *ptr++ = ':';
+ ptr = mem2hex((char *)&registers[PC], ptr, 4, 0);
+ *ptr++ = ';';
+
+ *ptr++ = hexchars[FP >> 4];
+ *ptr++ = hexchars[FP & 0xf];
+ *ptr++ = ':';
+ ptr = mem2hex(sp + 8 + 6, ptr, 4, 0); /* FP */
+ *ptr++ = ';';
+
+ *ptr++ = hexchars[SP >> 4];
+ *ptr++ = hexchars[SP & 0xf];
+ *ptr++ = ':';
+ ptr = mem2hex((char *)&sp, ptr, 4, 0);
+ *ptr++ = ';';
+
+ *ptr++ = hexchars[NPC >> 4];
+ *ptr++ = hexchars[NPC & 0xf];
+ *ptr++ = ':';
+ ptr = mem2hex((char *)&registers[NPC], ptr, 4, 0);
+ *ptr++ = ';';
+
+ *ptr++ = hexchars[O7 >> 4];
+ *ptr++ = hexchars[O7 & 0xf];
+ *ptr++ = ':';
+ ptr = mem2hex((char *)&registers[O7], ptr, 4, 0);
+ *ptr++ = ';';
+
+ *ptr++ = 0;
+
+ putpacket(remcomOutBuffer);
+
+ while (1)
+ {
+ remcomOutBuffer[0] = 0;
+
+ getpacket(remcomInBuffer);
+ switch (remcomInBuffer[0])
+ {
+ case '?':
+ remcomOutBuffer[0] = 'S';
+ remcomOutBuffer[1] = hexchars[sigval >> 4];
+ remcomOutBuffer[2] = hexchars[sigval & 0xf];
+ remcomOutBuffer[3] = 0;
+ break;
+
+ case 'd':
+ /* toggle debug flag */
+ break;
+
+ case 'g': /* return the value of the CPU registers */
+ {
+ ptr = remcomOutBuffer;
+ ptr = mem2hex((char *)registers, ptr, 16 * 4, 0); /* G & O regs */
+ ptr = mem2hex(sp + 0, ptr, 16 * 4, 0); /* L & I regs */
+ memset(ptr, '0', 32 * 8); /* Floating point */
+ mem2hex((char *)&registers[Y],
+ ptr + 32 * 4 * 2,
+ 8 * 4,
+ 0); /* Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR */
+ }
+ break;
+
+ case 'G': /* set the value of the CPU registers - return OK */
+ {
+ unsigned long *newsp, psr;
+
+ psr = registers[PSR];
+
+ ptr = &remcomInBuffer[1];
+ hex2mem(ptr, (char *)registers, 16 * 4, 0); /* G & O regs */
+ hex2mem(ptr + 16 * 4 * 2, sp + 0, 16 * 4, 0); /* L & I regs */
+ hex2mem(ptr + 64 * 4 * 2, (char *)&registers[Y],
+ 8 * 4, 0); /* Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR */
+
+ /* See if the stack pointer has moved. If so, then copy the saved
+ locals and ins to the new location. This keeps the window
+ overflow and underflow routines happy. */
+
+ newsp = (unsigned long *)registers[SP];
+ if (sp != newsp)
+ sp = memcpy(newsp, sp, 16 * 4);
+
+ /* Don't allow CWP to be modified. */
+
+ if (psr != registers[PSR])
+ registers[PSR] = (psr & 0x1f) | (registers[PSR] & ~0x1f);
+
+ strcpy(remcomOutBuffer,"OK");
+ }
+ break;
+
+ case 'm': /* mAA..AA,LLLL Read LLLL bytes at address AA..AA */
+ /* Try to read %x,%x. */
+
+ ptr = &remcomInBuffer[1];
+
+ if (hexToInt(&ptr, &addr)
+ && *ptr++ == ','
+ && hexToInt(&ptr, &length))
+ {
+ if (mem2hex((char *)addr, remcomOutBuffer, length, 1))
+ break;
+
+ strcpy (remcomOutBuffer, "E03");
+ }
+ else
+ strcpy(remcomOutBuffer,"E01");
+ break;
+
+ case 'M': /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
+ /* Try to read '%x,%x:'. */
+
+ ptr = &remcomInBuffer[1];
+
+ if (hexToInt(&ptr, &addr)
+ && *ptr++ == ','
+ && hexToInt(&ptr, &length)
+ && *ptr++ == ':')
+ {
+ if (hex2mem(ptr, (char *)addr, length, 1))
+ strcpy(remcomOutBuffer, "OK");
+ else
+ strcpy(remcomOutBuffer, "E03");
+ }
+ else
+ strcpy(remcomOutBuffer, "E02");
+ break;
+
+ case 'c': /* cAA..AA Continue at address AA..AA(optional) */
+ /* try to read optional parameter, pc unchanged if no parm */
+
+ ptr = &remcomInBuffer[1];
+ if (hexToInt(&ptr, &addr))
+ {
+ registers[PC] = addr;
+ registers[NPC] = addr + 4;
+ }
+
+/* Need to flush the instruction cache here, as we may have deposited a
+ breakpoint, and the icache probably has no way of knowing that a data ref to
+ some location may have changed something that is in the instruction cache.
+ */
+
+ flush_i_cache();
+ return;
+
+ /* kill the program */
+ case 'k' : /* do nothing */
+ break;
+#if 0
+ case 't': /* Test feature */
+ asm (" std %f30,[%sp]");
+ break;
+#endif
+ case 'r': /* Reset */
+ asm ("call 0
+ nop ");
+ break;
+
+#if 0
+Disabled until we can unscrew this properly
+
+ case 'b': /* bBB... Set baud rate to BB... */
+ {
+ int baudrate;
+ extern void set_timer_3();
+
+ ptr = &remcomInBuffer[1];
+ if (!hexToInt(&ptr, &baudrate))
+ {
+ strcpy(remcomOutBuffer,"B01");
+ break;
+ }
+
+ /* Convert baud rate to uart clock divider */
+ switch (baudrate)
+ {
+ case 38400:
+ baudrate = 16;
+ break;
+ case 19200:
+ baudrate = 33;
+ break;
+ case 9600:
+ baudrate = 65;
+ break;
+ default:
+ strcpy(remcomOutBuffer,"B02");
+ goto x1;
+ }
+
+ putpacket("OK"); /* Ack before changing speed */
+ set_timer_3(baudrate); /* Set it */
+ }
+x1: break;
+#endif
+ } /* switch */
+
+ /* reply to the request */
+ putpacket(remcomOutBuffer);
+ }
+}
+
+/* This function will generate a breakpoint exception. It is used at the
+ beginning of a program to sync up with a debugger and can be used
+ otherwise as a quick means to stop program execution and "break" into
+ the debugger. */
+
+void
+breakpoint()
+{
+ if (!initialized)
+ return;
+
+ asm(" .globl _breakinst
+
+ _breakinst: ta 1
+ ");
+}
diff --git a/gdb/sparc-tdep.c b/gdb/sparc-tdep.c
new file mode 100644
index 00000000000..113b32cd7cc
--- /dev/null
+++ b/gdb/sparc-tdep.c
@@ -0,0 +1,2120 @@
+/* Target-dependent code for the SPARC for GDB, the GNU debugger.
+ Copyright 1986, 1987, 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1997
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* ??? Support for calling functions from gdb in sparc64 is unfinished. */
+
+#include "defs.h"
+#include "frame.h"
+#include "inferior.h"
+#include "obstack.h"
+#include "target.h"
+#include "value.h"
+#include "bfd.h"
+#include "gdb_string.h"
+
+#ifdef USE_PROC_FS
+#include <sys/procfs.h>
+#endif
+
+#include "gdbcore.h"
+
+#if defined(TARGET_SPARCLET) || defined(TARGET_SPARCLITE)
+#define SPARC_HAS_FPU 0
+#else
+#define SPARC_HAS_FPU 1
+#endif
+
+#ifdef GDB_TARGET_IS_SPARC64
+#define FP_REGISTER_BYTES (64 * 4)
+#else
+#define FP_REGISTER_BYTES (32 * 4)
+#endif
+
+/* If not defined, assume 32 bit sparc. */
+#ifndef FP_MAX_REGNUM
+#define FP_MAX_REGNUM (FP0_REGNUM + 32)
+#endif
+
+#define SPARC_INTREG_SIZE (REGISTER_RAW_SIZE (G0_REGNUM))
+
+/* From infrun.c */
+extern int stop_after_trap;
+
+/* We don't store all registers immediately when requested, since they
+ get sent over in large chunks anyway. Instead, we accumulate most
+ of the changes and send them over once. "deferred_stores" keeps
+ track of which sets of registers we have locally-changed copies of,
+ so we only need send the groups that have changed. */
+
+int deferred_stores = 0; /* Cumulates stores we want to do eventually. */
+
+
+/* Some machines, such as Fujitsu SPARClite 86x, have a bi-endian mode
+ where instructions are big-endian and data are little-endian.
+ This flag is set when we detect that the target is of this type. */
+
+int bi_endian = 0;
+
+
+/* Fetch a single instruction. Even on bi-endian machines
+ such as sparc86x, instructions are always big-endian. */
+
+static unsigned long
+fetch_instruction (pc)
+ CORE_ADDR pc;
+{
+ unsigned long retval;
+ int i;
+ unsigned char buf[4];
+
+ read_memory (pc, buf, sizeof (buf));
+
+ /* Start at the most significant end of the integer, and work towards
+ the least significant. */
+ retval = 0;
+ for (i = 0; i < sizeof (buf); ++i)
+ retval = (retval << 8) | buf[i];
+ return retval;
+}
+
+
+/* Branches with prediction are treated like their non-predicting cousins. */
+/* FIXME: What about floating point branches? */
+
+/* Macros to extract fields from sparc instructions. */
+#define X_OP(i) (((i) >> 30) & 0x3)
+#define X_RD(i) (((i) >> 25) & 0x1f)
+#define X_A(i) (((i) >> 29) & 1)
+#define X_COND(i) (((i) >> 25) & 0xf)
+#define X_OP2(i) (((i) >> 22) & 0x7)
+#define X_IMM22(i) ((i) & 0x3fffff)
+#define X_OP3(i) (((i) >> 19) & 0x3f)
+#define X_RS1(i) (((i) >> 14) & 0x1f)
+#define X_I(i) (((i) >> 13) & 1)
+#define X_IMM13(i) ((i) & 0x1fff)
+/* Sign extension macros. */
+#define X_SIMM13(i) ((X_IMM13 (i) ^ 0x1000) - 0x1000)
+#define X_DISP22(i) ((X_IMM22 (i) ^ 0x200000) - 0x200000)
+#define X_CC(i) (((i) >> 20) & 3)
+#define X_P(i) (((i) >> 19) & 1)
+#define X_DISP19(i) ((((i) & 0x7ffff) ^ 0x40000) - 0x40000)
+#define X_RCOND(i) (((i) >> 25) & 7)
+#define X_DISP16(i) ((((((i) >> 6) && 0xc000) | ((i) & 0x3fff)) ^ 0x8000) - 0x8000)
+#define X_FCN(i) (((i) >> 25) & 31)
+
+typedef enum
+{
+ Error, not_branch, bicc, bicca, ba, baa, ticc, ta,
+#ifdef GDB_TARGET_IS_SPARC64
+ done_retry
+#endif
+} branch_type;
+
+/* Simulate single-step ptrace call for sun4. Code written by Gary
+ Beihl (beihl@mcc.com). */
+
+/* npc4 and next_pc describe the situation at the time that the
+ step-breakpoint was set, not necessary the current value of NPC_REGNUM. */
+static CORE_ADDR next_pc, npc4, target;
+static int brknpc4, brktrg;
+typedef char binsn_quantum[BREAKPOINT_MAX];
+static binsn_quantum break_mem[3];
+
+static branch_type isbranch PARAMS ((long, CORE_ADDR, CORE_ADDR *));
+
+/* single_step() is called just before we want to resume the inferior,
+ if we want to single-step it but there is no hardware or kernel single-step
+ support (as on all SPARCs). We find all the possible targets of the
+ coming instruction and breakpoint them.
+
+ single_step is also called just after the inferior stops. If we had
+ set up a simulated single-step, we undo our damage. */
+
+void
+sparc_software_single_step (ignore, insert_breakpoints_p)
+ enum target_signal ignore; /* pid, but we don't need it */
+ int insert_breakpoints_p;
+{
+ branch_type br;
+ CORE_ADDR pc;
+ long pc_instruction;
+
+ if (insert_breakpoints_p)
+ {
+ /* Always set breakpoint for NPC. */
+ next_pc = read_register (NPC_REGNUM);
+ npc4 = next_pc + 4; /* branch not taken */
+
+ target_insert_breakpoint (next_pc, break_mem[0]);
+ /* printf_unfiltered ("set break at %x\n",next_pc); */
+
+ pc = read_register (PC_REGNUM);
+ pc_instruction = fetch_instruction (pc);
+ br = isbranch (pc_instruction, pc, &target);
+ brknpc4 = brktrg = 0;
+
+ if (br == bicca)
+ {
+ /* Conditional annulled branch will either end up at
+ npc (if taken) or at npc+4 (if not taken).
+ Trap npc+4. */
+ brknpc4 = 1;
+ target_insert_breakpoint (npc4, break_mem[1]);
+ }
+ else if (br == baa && target != next_pc)
+ {
+ /* Unconditional annulled branch will always end up at
+ the target. */
+ brktrg = 1;
+ target_insert_breakpoint (target, break_mem[2]);
+ }
+#ifdef GDB_TARGET_IS_SPARC64
+ else if (br == done_retry)
+ {
+ brktrg = 1;
+ target_insert_breakpoint (target, break_mem[2]);
+ }
+#endif
+ }
+ else
+ {
+ /* Remove breakpoints */
+ target_remove_breakpoint (next_pc, break_mem[0]);
+
+ if (brknpc4)
+ target_remove_breakpoint (npc4, break_mem[1]);
+
+ if (brktrg)
+ target_remove_breakpoint (target, break_mem[2]);
+ }
+}
+
+/* Call this for each newly created frame. For SPARC, we need to calculate
+ the bottom of the frame, and do some extra work if the prologue
+ has been generated via the -mflat option to GCC. In particular,
+ we need to know where the previous fp and the pc have been stashed,
+ since their exact position within the frame may vary. */
+
+void
+sparc_init_extra_frame_info (fromleaf, fi)
+ int fromleaf;
+ struct frame_info *fi;
+{
+ char *name;
+ CORE_ADDR prologue_start, prologue_end;
+ int insn;
+
+ fi->bottom =
+ (fi->next ?
+ (fi->frame == fi->next->frame ? fi->next->bottom : fi->next->frame) :
+ read_sp ());
+
+ /* If fi->next is NULL, then we already set ->frame by passing read_fp()
+ to create_new_frame. */
+ if (fi->next)
+ {
+ char buf[MAX_REGISTER_RAW_SIZE];
+
+ /* Compute ->frame as if not flat. If it is flat, we'll change
+ it later. */
+ if (fi->next->next != NULL
+ && (fi->next->next->signal_handler_caller
+ || frame_in_dummy (fi->next->next))
+ && frameless_look_for_prologue (fi->next))
+ {
+ /* A frameless function interrupted by a signal did not change
+ the frame pointer, fix up frame pointer accordingly. */
+ fi->frame = FRAME_FP (fi->next);
+ fi->bottom = fi->next->bottom;
+ }
+ else
+ {
+ /* Should we adjust for stack bias here? */
+ get_saved_register (buf, 0, 0, fi, FP_REGNUM, 0);
+ fi->frame = extract_address (buf, REGISTER_RAW_SIZE (FP_REGNUM));
+#ifdef GDB_TARGET_IS_SPARC64
+ if (fi->frame & 1)
+ fi->frame += 2047;
+#endif
+
+ }
+ }
+
+ /* Decide whether this is a function with a ``flat register window''
+ frame. For such functions, the frame pointer is actually in %i7. */
+ fi->flat = 0;
+ fi->in_prologue = 0;
+ if (find_pc_partial_function (fi->pc, &name, &prologue_start, &prologue_end))
+ {
+ /* See if the function starts with an add (which will be of a
+ negative number if a flat frame) to the sp. FIXME: Does not
+ handle large frames which will need more than one instruction
+ to adjust the sp. */
+ insn = fetch_instruction (prologue_start, 4);
+ if (X_OP (insn) == 2 && X_RD (insn) == 14 && X_OP3 (insn) == 0
+ && X_I (insn) && X_SIMM13 (insn) < 0)
+ {
+ int offset = X_SIMM13 (insn);
+
+ /* Then look for a save of %i7 into the frame. */
+ insn = fetch_instruction (prologue_start + 4);
+ if (X_OP (insn) == 3
+ && X_RD (insn) == 31
+ && X_OP3 (insn) == 4
+ && X_RS1 (insn) == 14)
+ {
+ char buf[MAX_REGISTER_RAW_SIZE];
+
+ /* We definitely have a flat frame now. */
+ fi->flat = 1;
+
+ fi->sp_offset = offset;
+
+ /* Overwrite the frame's address with the value in %i7. */
+ get_saved_register (buf, 0, 0, fi, I7_REGNUM, 0);
+ fi->frame = extract_address (buf, REGISTER_RAW_SIZE (I7_REGNUM));
+#ifdef GDB_TARGET_IS_SPARC64
+ if (fi->frame & 1)
+ fi->frame += 2047;
+#endif
+ /* Record where the fp got saved. */
+ fi->fp_addr = fi->frame + fi->sp_offset + X_SIMM13 (insn);
+
+ /* Also try to collect where the pc got saved to. */
+ fi->pc_addr = 0;
+ insn = fetch_instruction (prologue_start + 12);
+ if (X_OP (insn) == 3
+ && X_RD (insn) == 15
+ && X_OP3 (insn) == 4
+ && X_RS1 (insn) == 14)
+ fi->pc_addr = fi->frame + fi->sp_offset + X_SIMM13 (insn);
+ }
+ }
+ else
+ {
+ /* Check if the PC is in the function prologue before a SAVE
+ instruction has been executed yet. If so, set the frame
+ to the current value of the stack pointer and set
+ the in_prologue flag. */
+ CORE_ADDR addr;
+ struct symtab_and_line sal;
+
+ sal = find_pc_line (prologue_start, 0);
+ if (sal.line == 0) /* no line info, use PC */
+ prologue_end = fi->pc;
+ else if (sal.end < prologue_end)
+ prologue_end = sal.end;
+ if (fi->pc < prologue_end)
+ {
+ for (addr = prologue_start; addr < fi->pc; addr += 4)
+ {
+ insn = read_memory_integer (addr, 4);
+ if (X_OP (insn) == 2 && X_OP3 (insn) == 0x3c)
+ break; /* SAVE seen, stop searching */
+ }
+ if (addr >= fi->pc)
+ {
+ fi->in_prologue = 1;
+ fi->frame = read_register (SP_REGNUM);
+ }
+ }
+ }
+ }
+ if (fi->next && fi->frame == 0)
+ {
+ /* Kludge to cause init_prev_frame_info to destroy the new frame. */
+ fi->frame = fi->next->frame;
+ fi->pc = fi->next->pc;
+ }
+}
+
+CORE_ADDR
+sparc_frame_chain (frame)
+ struct frame_info *frame;
+{
+ /* Value that will cause FRAME_CHAIN_VALID to not worry about the chain
+ value. If it realy is zero, we detect it later in
+ sparc_init_prev_frame. */
+ return (CORE_ADDR)1;
+}
+
+CORE_ADDR
+sparc_extract_struct_value_address (regbuf)
+ char regbuf[REGISTER_BYTES];
+{
+ return extract_address (regbuf + REGISTER_BYTE (O0_REGNUM),
+ REGISTER_RAW_SIZE (O0_REGNUM));
+}
+
+/* Find the pc saved in frame FRAME. */
+
+CORE_ADDR
+sparc_frame_saved_pc (frame)
+ struct frame_info *frame;
+{
+ char buf[MAX_REGISTER_RAW_SIZE];
+ CORE_ADDR addr;
+
+ if (frame->signal_handler_caller)
+ {
+ /* This is the signal trampoline frame.
+ Get the saved PC from the sigcontext structure. */
+
+#ifndef SIGCONTEXT_PC_OFFSET
+#define SIGCONTEXT_PC_OFFSET 12
+#endif
+
+ CORE_ADDR sigcontext_addr;
+ char scbuf[TARGET_PTR_BIT / HOST_CHAR_BIT];
+ int saved_pc_offset = SIGCONTEXT_PC_OFFSET;
+ char *name = NULL;
+
+ /* Solaris2 ucbsigvechandler passes a pointer to a sigcontext
+ as the third parameter. The offset to the saved pc is 12. */
+ find_pc_partial_function (frame->pc, &name,
+ (CORE_ADDR *)NULL,(CORE_ADDR *)NULL);
+ if (name && STREQ (name, "ucbsigvechandler"))
+ saved_pc_offset = 12;
+
+ /* The sigcontext address is contained in register O2. */
+ get_saved_register (buf, (int *)NULL, (CORE_ADDR *)NULL,
+ frame, O0_REGNUM + 2, (enum lval_type *)NULL);
+ sigcontext_addr = extract_address (buf, REGISTER_RAW_SIZE (O0_REGNUM + 2));
+
+ /* 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 + saved_pc_offset,
+ scbuf, sizeof (scbuf));
+ return extract_address (scbuf, sizeof (scbuf));
+ }
+ else if (frame->in_prologue ||
+ (frame->next != NULL
+ && (frame->next->signal_handler_caller
+ || frame_in_dummy (frame->next))
+ && frameless_look_for_prologue (frame)))
+ {
+ /* A frameless function interrupted by a signal did not save
+ the PC, it is still in %o7. */
+ get_saved_register (buf, (int *)NULL, (CORE_ADDR *)NULL,
+ frame, O7_REGNUM, (enum lval_type *)NULL);
+ return PC_ADJUST (extract_address (buf, SPARC_INTREG_SIZE));
+ }
+ if (frame->flat)
+ addr = frame->pc_addr;
+ else
+ addr = frame->bottom + FRAME_SAVED_I0 +
+ SPARC_INTREG_SIZE * (I7_REGNUM - I0_REGNUM);
+
+ if (addr == 0)
+ /* A flat frame leaf function might not save the PC anywhere,
+ just leave it in %o7. */
+ return PC_ADJUST (read_register (O7_REGNUM));
+
+ read_memory (addr, buf, SPARC_INTREG_SIZE);
+ return PC_ADJUST (extract_address (buf, SPARC_INTREG_SIZE));
+}
+
+/* Since an individual frame in the frame cache is defined by two
+ arguments (a frame pointer and a stack pointer), we need two
+ arguments to get info for an arbitrary stack frame. This routine
+ takes two arguments and makes the cached frames look as if these
+ two arguments defined a frame on the cache. This allows the rest
+ of info frame to extract the important arguments without
+ difficulty. */
+
+struct frame_info *
+setup_arbitrary_frame (argc, argv)
+ int argc;
+ CORE_ADDR *argv;
+{
+ struct frame_info *frame;
+
+ if (argc != 2)
+ error ("Sparc frame specifications require two arguments: fp and sp");
+
+ frame = create_new_frame (argv[0], 0);
+
+ if (!frame)
+ fatal ("internal: create_new_frame returned invalid frame");
+
+ frame->bottom = argv[1];
+ frame->pc = FRAME_SAVED_PC (frame);
+ return frame;
+}
+
+/* Given a pc value, skip it forward past the function prologue by
+ disassembling instructions that appear to be a prologue.
+
+ If FRAMELESS_P is set, we are only testing to see if the function
+ is frameless. This allows a quicker answer.
+
+ This routine should be more specific in its actions; making sure
+ that it uses the same register in the initial prologue section. */
+
+static CORE_ADDR examine_prologue PARAMS ((CORE_ADDR, int, struct frame_info *,
+ struct frame_saved_regs *));
+
+static CORE_ADDR
+examine_prologue (start_pc, frameless_p, fi, saved_regs)
+ CORE_ADDR start_pc;
+ int frameless_p;
+ struct frame_info *fi;
+ struct frame_saved_regs *saved_regs;
+{
+ int insn;
+ int dest = -1;
+ CORE_ADDR pc = start_pc;
+ int is_flat = 0;
+
+ insn = fetch_instruction (pc);
+
+ /* Recognize the `sethi' insn and record its destination. */
+ if (X_OP (insn) == 0 && X_OP2 (insn) == 4)
+ {
+ dest = X_RD (insn);
+ pc += 4;
+ insn = fetch_instruction (pc);
+ }
+
+ /* Recognize an add immediate value to register to either %g1 or
+ the destination register recorded above. Actually, this might
+ well recognize several different arithmetic operations.
+ It doesn't check that rs1 == rd because in theory "sub %g0, 5, %g1"
+ followed by "save %sp, %g1, %sp" is a valid prologue (Not that
+ I imagine any compiler really does that, however). */
+ if (X_OP (insn) == 2
+ && X_I (insn)
+ && (X_RD (insn) == 1 || X_RD (insn) == dest))
+ {
+ pc += 4;
+ insn = fetch_instruction (pc);
+ }
+
+ /* Recognize any SAVE insn. */
+ if (X_OP (insn) == 2 && X_OP3 (insn) == 60)
+ {
+ pc += 4;
+ if (frameless_p) /* If the save is all we care about, */
+ return pc; /* return before doing more work */
+ insn = fetch_instruction (pc);
+ }
+ /* Recognize add to %sp. */
+ else if (X_OP (insn) == 2 && X_RD (insn) == 14 && X_OP3 (insn) == 0)
+ {
+ pc += 4;
+ if (frameless_p) /* If the add is all we care about, */
+ return pc; /* return before doing more work */
+ is_flat = 1;
+ insn = fetch_instruction (pc);
+ /* Recognize store of frame pointer (i7). */
+ if (X_OP (insn) == 3
+ && X_RD (insn) == 31
+ && X_OP3 (insn) == 4
+ && X_RS1 (insn) == 14)
+ {
+ pc += 4;
+ insn = fetch_instruction (pc);
+
+ /* Recognize sub %sp, <anything>, %i7. */
+ if (X_OP (insn) == 2
+ && X_OP3 (insn) == 4
+ && X_RS1 (insn) == 14
+ && X_RD (insn) == 31)
+ {
+ pc += 4;
+ insn = fetch_instruction (pc);
+ }
+ else
+ return pc;
+ }
+ else
+ return pc;
+ }
+ else
+ /* Without a save or add instruction, it's not a prologue. */
+ return start_pc;
+
+ while (1)
+ {
+ /* Recognize stores into the frame from the input registers.
+ This recognizes all non alternate stores of input register,
+ into a location offset from the frame pointer. */
+ if ((X_OP (insn) == 3
+ && (X_OP3 (insn) & 0x3c) == 4 /* Store, non-alternate. */
+ && (X_RD (insn) & 0x18) == 0x18 /* Input register. */
+ && X_I (insn) /* Immediate mode. */
+ && X_RS1 (insn) == 30 /* Off of frame pointer. */
+ /* Into reserved stack space. */
+ && X_SIMM13 (insn) >= 0x44
+ && X_SIMM13 (insn) < 0x5b))
+ ;
+ else if (is_flat
+ && X_OP (insn) == 3
+ && X_OP3 (insn) == 4
+ && X_RS1 (insn) == 14
+ )
+ {
+ if (saved_regs && X_I (insn))
+ saved_regs->regs[X_RD (insn)] =
+ fi->frame + fi->sp_offset + X_SIMM13 (insn);
+ }
+ else
+ break;
+ pc += 4;
+ insn = fetch_instruction (pc);
+ }
+
+ return pc;
+}
+
+CORE_ADDR
+skip_prologue (start_pc, frameless_p)
+ CORE_ADDR start_pc;
+ int frameless_p;
+{
+ return examine_prologue (start_pc, frameless_p, NULL, NULL);
+}
+
+/* Check instruction at ADDR to see if it is a branch.
+ All non-annulled instructions will go to NPC or will trap.
+ Set *TARGET if we find a candidate branch; set to zero if not.
+
+ This isn't static as it's used by remote-sa.sparc.c. */
+
+static branch_type
+isbranch (instruction, addr, target)
+ long instruction;
+ CORE_ADDR addr, *target;
+{
+ branch_type val = not_branch;
+ long int offset = 0; /* Must be signed for sign-extend. */
+
+ *target = 0;
+
+ if (X_OP (instruction) == 0
+ && (X_OP2 (instruction) == 2
+ || X_OP2 (instruction) == 6
+ || X_OP2 (instruction) == 1
+ || X_OP2 (instruction) == 3
+ || X_OP2 (instruction) == 5
+#ifndef GDB_TARGET_IS_SPARC64
+ || X_OP2 (instruction) == 7
+#endif
+ ))
+ {
+ if (X_COND (instruction) == 8)
+ val = X_A (instruction) ? baa : ba;
+ else
+ val = X_A (instruction) ? bicca : bicc;
+ switch (X_OP2 (instruction))
+ {
+ case 2:
+ case 6:
+#ifndef GDB_TARGET_IS_SPARC64
+ case 7:
+#endif
+ offset = 4 * X_DISP22 (instruction);
+ break;
+ case 1:
+ case 5:
+ offset = 4 * X_DISP19 (instruction);
+ break;
+ case 3:
+ offset = 4 * X_DISP16 (instruction);
+ break;
+ }
+ *target = addr + offset;
+ }
+#ifdef GDB_TARGET_IS_SPARC64
+ else if (X_OP (instruction) == 2
+ && X_OP3 (instruction) == 62)
+ {
+ if (X_FCN (instruction) == 0)
+ {
+ /* done */
+ *target = read_register (TNPC_REGNUM);
+ val = done_retry;
+ }
+ else if (X_FCN (instruction) == 1)
+ {
+ /* retry */
+ *target = read_register (TPC_REGNUM);
+ val = done_retry;
+ }
+ }
+#endif
+
+ return val;
+}
+
+/* Find register number REGNUM relative to FRAME and put its
+ (raw) contents in *RAW_BUFFER. Set *OPTIMIZED if the variable
+ was optimized out (and thus can't be fetched). If the variable
+ was fetched from memory, set *ADDRP to where it was fetched from,
+ otherwise it was fetched from a register.
+
+ The argument RAW_BUFFER must point to aligned memory. */
+
+void
+get_saved_register (raw_buffer, optimized, addrp, frame, regnum, lval)
+ char *raw_buffer;
+ int *optimized;
+ CORE_ADDR *addrp;
+ struct frame_info *frame;
+ int regnum;
+ enum lval_type *lval;
+{
+ struct frame_info *frame1;
+ CORE_ADDR addr;
+
+ if (!target_has_registers)
+ error ("No registers.");
+
+ if (optimized)
+ *optimized = 0;
+
+ addr = 0;
+
+ /* FIXME This code extracted from infcmd.c; should put elsewhere! */
+ if (frame == NULL)
+ {
+ /* error ("No selected frame."); */
+ if (!target_has_registers)
+ error ("The program has no registers now.");
+ if (selected_frame == NULL)
+ error ("No selected frame.");
+ /* Try to use selected frame */
+ frame = get_prev_frame (selected_frame);
+ if (frame == 0)
+ error ("Cmd not meaningful in the outermost frame.");
+ }
+
+
+ frame1 = frame->next;
+
+ /* Get saved PC from the frame info if not in innermost frame. */
+ if (regnum == PC_REGNUM && frame1 != NULL)
+ {
+ if (lval != NULL)
+ *lval = not_lval;
+ if (raw_buffer != NULL)
+ {
+ /* Put it back in target format. */
+ store_address (raw_buffer, REGISTER_RAW_SIZE (regnum), frame->pc);
+ }
+ if (addrp != NULL)
+ *addrp = 0;
+ return;
+ }
+
+ while (frame1 != NULL)
+ {
+ if (frame1->pc >= (frame1->bottom ? frame1->bottom :
+ read_sp ())
+ && frame1->pc <= FRAME_FP (frame1))
+ {
+ /* Dummy frame. All but the window regs are in there somewhere.
+ The window registers are saved on the stack, just like in a
+ normal frame. */
+ if (regnum >= G1_REGNUM && regnum < G1_REGNUM + 7)
+ addr = frame1->frame + (regnum - G0_REGNUM) * SPARC_INTREG_SIZE
+ - (FP_REGISTER_BYTES + 8 * SPARC_INTREG_SIZE);
+ else if (regnum >= I0_REGNUM && regnum < I0_REGNUM + 8)
+ addr = (frame1->prev->bottom
+ + (regnum - I0_REGNUM) * SPARC_INTREG_SIZE
+ + FRAME_SAVED_I0);
+ else if (regnum >= L0_REGNUM && regnum < L0_REGNUM + 8)
+ addr = (frame1->prev->bottom
+ + (regnum - L0_REGNUM) * SPARC_INTREG_SIZE
+ + FRAME_SAVED_L0);
+ else if (regnum >= O0_REGNUM && regnum < O0_REGNUM + 8)
+ addr = frame1->frame + (regnum - O0_REGNUM) * SPARC_INTREG_SIZE
+ - (FP_REGISTER_BYTES + 16 * SPARC_INTREG_SIZE);
+#ifdef FP0_REGNUM
+ else if (regnum >= FP0_REGNUM && regnum < FP0_REGNUM + 32)
+ addr = frame1->frame + (regnum - FP0_REGNUM) * 4
+ - (FP_REGISTER_BYTES);
+#ifdef GDB_TARGET_IS_SPARC64
+ else if (regnum >= FP0_REGNUM + 32 && regnum < FP_MAX_REGNUM)
+ addr = frame1->frame + 32 * 4 + (regnum - FP0_REGNUM - 32) * 8
+ - (FP_REGISTER_BYTES);
+#endif
+#endif /* FP0_REGNUM */
+ else if (regnum >= Y_REGNUM && regnum < NUM_REGS)
+ addr = frame1->frame + (regnum - Y_REGNUM) * SPARC_INTREG_SIZE
+ - (FP_REGISTER_BYTES + 24 * SPARC_INTREG_SIZE);
+ }
+ else if (frame1->flat)
+ {
+
+ if (regnum == RP_REGNUM)
+ addr = frame1->pc_addr;
+ else if (regnum == I7_REGNUM)
+ addr = frame1->fp_addr;
+ else
+ {
+ CORE_ADDR func_start;
+ struct frame_saved_regs regs;
+ memset (&regs, 0, sizeof (regs));
+
+ find_pc_partial_function (frame1->pc, NULL, &func_start, NULL);
+ examine_prologue (func_start, 0, frame1, &regs);
+ addr = regs.regs[regnum];
+ }
+ }
+ else
+ {
+ /* Normal frame. Local and In registers are saved on stack. */
+ if (regnum >= I0_REGNUM && regnum < I0_REGNUM + 8)
+ addr = (frame1->prev->bottom
+ + (regnum - I0_REGNUM) * SPARC_INTREG_SIZE
+ + FRAME_SAVED_I0);
+ else if (regnum >= L0_REGNUM && regnum < L0_REGNUM + 8)
+ addr = (frame1->prev->bottom
+ + (regnum - L0_REGNUM) * SPARC_INTREG_SIZE
+ + FRAME_SAVED_L0);
+ else if (regnum >= O0_REGNUM && regnum < O0_REGNUM + 8)
+ {
+ /* Outs become ins. */
+ get_saved_register (raw_buffer, optimized, addrp, frame1,
+ (regnum - O0_REGNUM + I0_REGNUM), lval);
+ return;
+ }
+ }
+ if (addr != 0)
+ break;
+ frame1 = frame1->next;
+ }
+ 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;
+}
+
+/* Push an empty stack frame, and record in it the current PC, regs, etc.
+
+ We save the non-windowed registers and the ins. The locals and outs
+ are new; they don't need to be saved. The i's and l's of
+ the last frame were already saved on the stack. */
+
+/* Definitely see tm-sparc.h for more doc of the frame format here. */
+
+#ifdef GDB_TARGET_IS_SPARC64
+#define DUMMY_REG_SAVE_OFFSET (128 + 16)
+#else
+#define DUMMY_REG_SAVE_OFFSET 0x60
+#endif
+
+/* See tm-sparc.h for how this is calculated. */
+#ifdef FP0_REGNUM
+#define DUMMY_STACK_REG_BUF_SIZE \
+(((8+8+8) * SPARC_INTREG_SIZE) + FP_REGISTER_BYTES)
+#else
+#define DUMMY_STACK_REG_BUF_SIZE \
+(((8+8+8) * SPARC_INTREG_SIZE) )
+#endif /* FP0_REGNUM */
+#define DUMMY_STACK_SIZE (DUMMY_STACK_REG_BUF_SIZE + DUMMY_REG_SAVE_OFFSET)
+
+void
+sparc_push_dummy_frame ()
+{
+ CORE_ADDR sp, old_sp;
+ char register_temp[DUMMY_STACK_SIZE];
+
+ old_sp = sp = read_sp ();
+
+#ifdef GDB_TARGET_IS_SPARC64
+ /* PC, NPC, CCR, FSR, FPRS, Y, ASI */
+ read_register_bytes (REGISTER_BYTE (PC_REGNUM), &register_temp[0],
+ REGISTER_RAW_SIZE (PC_REGNUM) * 7);
+ read_register_bytes (REGISTER_BYTE (PSTATE_REGNUM), &register_temp[8],
+ REGISTER_RAW_SIZE (PSTATE_REGNUM));
+ /* FIXME: not sure what needs to be saved here. */
+#else
+ /* Y, PS, WIM, TBR, PC, NPC, FPS, CPS regs */
+ read_register_bytes (REGISTER_BYTE (Y_REGNUM), &register_temp[0],
+ REGISTER_RAW_SIZE (Y_REGNUM) * 8);
+#endif
+
+ read_register_bytes (REGISTER_BYTE (O0_REGNUM),
+ &register_temp[8 * SPARC_INTREG_SIZE],
+ SPARC_INTREG_SIZE * 8);
+
+ read_register_bytes (REGISTER_BYTE (G0_REGNUM),
+ &register_temp[16 * SPARC_INTREG_SIZE],
+ SPARC_INTREG_SIZE * 8);
+
+#ifdef FP0_REGNUM
+ read_register_bytes (REGISTER_BYTE (FP0_REGNUM),
+ &register_temp[24 * SPARC_INTREG_SIZE],
+ FP_REGISTER_BYTES);
+#endif /* FP0_REGNUM */
+
+ sp -= DUMMY_STACK_SIZE;
+
+ write_sp (sp);
+
+ write_memory (sp + DUMMY_REG_SAVE_OFFSET, &register_temp[0],
+ DUMMY_STACK_REG_BUF_SIZE);
+
+ if (strcmp (target_shortname, "sim") != 0)
+ {
+ write_fp (old_sp);
+
+ /* Set return address register for the call dummy to the current PC. */
+ write_register (I7_REGNUM, read_pc() - 8);
+ }
+ else
+ {
+ /* The call dummy will write this value to FP before executing
+ the 'save'. This ensures that register window flushes work
+ correctly in the simulator. */
+ write_register (G0_REGNUM+1, read_register (FP_REGNUM));
+
+ /* The call dummy will write this value to FP after executing
+ the 'save'. */
+ write_register (G0_REGNUM+2, old_sp);
+
+ /* The call dummy will write this value to the return address (%i7) after
+ executing the 'save'. */
+ write_register (G0_REGNUM+3, read_pc() - 8);
+
+ /* Set the FP that the call dummy will be using after the 'save'.
+ This makes backtraces from an inferior function call work properly. */
+ write_register (FP_REGNUM, old_sp);
+ }
+}
+
+/* sparc_frame_find_saved_regs (). This function is here only because
+ pop_frame uses it. Note there is an interesting corner case which
+ I think few ports of GDB get right--if you are popping a frame
+ which does not save some register that *is* saved by a more inner
+ frame (such a frame will never be a dummy frame because dummy
+ frames save all registers). Rewriting pop_frame to use
+ get_saved_register would solve this problem and also get rid of the
+ ugly duplication between sparc_frame_find_saved_regs and
+ get_saved_register.
+
+ Stores, into a struct frame_saved_regs,
+ the addresses of the saved registers of frame described by FRAME_INFO.
+ This includes special registers such as pc and fp saved in special
+ ways in the stack frame. sp is even more special:
+ the address we return for it IS the sp for the next frame.
+
+ Note that on register window machines, we are currently making the
+ assumption that window registers are being saved somewhere in the
+ frame in which they are being used. If they are stored in an
+ inferior frame, find_saved_register will break.
+
+ On the Sun 4, the only time all registers are saved is when
+ a dummy frame is involved. Otherwise, the only saved registers
+ are the LOCAL and IN registers which are saved as a result
+ of the "save/restore" opcodes. This condition is determined
+ by address rather than by value.
+
+ The "pc" is not stored in a frame on the SPARC. (What is stored
+ is a return address minus 8.) sparc_pop_frame knows how to
+ deal with that. Other routines might or might not.
+
+ See tm-sparc.h (PUSH_DUMMY_FRAME and friends) for CRITICAL information
+ about how this works. */
+
+static void sparc_frame_find_saved_regs PARAMS ((struct frame_info *,
+ struct frame_saved_regs *));
+
+static void
+sparc_frame_find_saved_regs (fi, saved_regs_addr)
+ struct frame_info *fi;
+ struct frame_saved_regs *saved_regs_addr;
+{
+ register int regnum;
+ CORE_ADDR frame_addr = FRAME_FP (fi);
+
+ if (!fi)
+ fatal ("Bad frame info struct in FRAME_FIND_SAVED_REGS");
+
+ memset (saved_regs_addr, 0, sizeof (*saved_regs_addr));
+
+ if (fi->pc >= (fi->bottom ? fi->bottom :
+ read_sp ())
+ && fi->pc <= FRAME_FP(fi))
+ {
+ /* Dummy frame. All but the window regs are in there somewhere. */
+ for (regnum = G1_REGNUM; regnum < G1_REGNUM+7; regnum++)
+ saved_regs_addr->regs[regnum] =
+ frame_addr + (regnum - G0_REGNUM) * SPARC_INTREG_SIZE
+ - DUMMY_STACK_REG_BUF_SIZE + 16 * SPARC_INTREG_SIZE;
+ for (regnum = I0_REGNUM; regnum < I0_REGNUM+8; regnum++)
+ saved_regs_addr->regs[regnum] =
+ frame_addr + (regnum - I0_REGNUM) * SPARC_INTREG_SIZE
+ - DUMMY_STACK_REG_BUF_SIZE + 8 * SPARC_INTREG_SIZE;
+#ifdef FP0_REGNUM
+ for (regnum = FP0_REGNUM; regnum < FP0_REGNUM + 32; regnum++)
+ saved_regs_addr->regs[regnum] =
+ frame_addr + (regnum - FP0_REGNUM) * 4
+ - DUMMY_STACK_REG_BUF_SIZE + 24 * SPARC_INTREG_SIZE;
+#ifdef GDB_TARGET_IS_SPARC64
+ for (regnum = FP0_REGNUM + 32; regnum < FP_MAX_REGNUM; regnum++)
+ saved_regs_addr->regs[regnum] =
+ frame_addr + 32 * 4 + (regnum - FP0_REGNUM - 32) * 4
+ - DUMMY_STACK_REG_BUF_SIZE + 24 * SPARC_INTREG_SIZE;
+#endif
+#endif /* FP0_REGNUM */
+#ifdef GDB_TARGET_IS_SPARC64
+ for (regnum = PC_REGNUM; regnum < PC_REGNUM + 7; regnum++)
+ {
+ saved_regs_addr->regs[regnum] =
+ frame_addr + (regnum - PC_REGNUM) * SPARC_INTREG_SIZE
+ - DUMMY_STACK_REG_BUF_SIZE;
+ }
+ saved_regs_addr->regs[PSTATE_REGNUM] =
+ frame_addr + 8 * SPARC_INTREG_SIZE - DUMMY_STACK_REG_BUF_SIZE;
+#else
+ for (regnum = Y_REGNUM; regnum < NUM_REGS; regnum++)
+ saved_regs_addr->regs[regnum] =
+ frame_addr + (regnum - Y_REGNUM) * SPARC_INTREG_SIZE
+ - DUMMY_STACK_REG_BUF_SIZE;
+#endif
+ frame_addr = fi->bottom ?
+ fi->bottom : read_sp ();
+ }
+ else if (fi->flat)
+ {
+ CORE_ADDR func_start;
+ find_pc_partial_function (fi->pc, NULL, &func_start, NULL);
+ examine_prologue (func_start, 0, fi, saved_regs_addr);
+
+ /* Flat register window frame. */
+ saved_regs_addr->regs[RP_REGNUM] = fi->pc_addr;
+ saved_regs_addr->regs[I7_REGNUM] = fi->fp_addr;
+ }
+ else
+ {
+ /* Normal frame. Just Local and In registers */
+ frame_addr = fi->bottom ?
+ fi->bottom : read_sp ();
+ for (regnum = L0_REGNUM; regnum < L0_REGNUM+8; regnum++)
+ saved_regs_addr->regs[regnum] =
+ (frame_addr + (regnum - L0_REGNUM) * SPARC_INTREG_SIZE
+ + FRAME_SAVED_L0);
+ for (regnum = I0_REGNUM; regnum < I0_REGNUM+8; regnum++)
+ saved_regs_addr->regs[regnum] =
+ (frame_addr + (regnum - I0_REGNUM) * SPARC_INTREG_SIZE
+ + FRAME_SAVED_I0);
+ }
+ if (fi->next)
+ {
+ if (fi->flat)
+ {
+ saved_regs_addr->regs[O7_REGNUM] = fi->pc_addr;
+ }
+ else
+ {
+ /* Pull off either the next frame pointer or the stack pointer */
+ CORE_ADDR next_next_frame_addr =
+ (fi->next->bottom ?
+ fi->next->bottom :
+ read_sp ());
+ for (regnum = O0_REGNUM; regnum < O0_REGNUM+8; regnum++)
+ saved_regs_addr->regs[regnum] =
+ (next_next_frame_addr
+ + (regnum - O0_REGNUM) * SPARC_INTREG_SIZE
+ + FRAME_SAVED_I0);
+ }
+ }
+ /* Otherwise, whatever we would get from ptrace(GETREGS) is accurate */
+ /* FIXME -- should this adjust for the sparc64 offset? */
+ saved_regs_addr->regs[SP_REGNUM] = FRAME_FP (fi);
+}
+
+/* Discard from the stack the innermost frame, restoring all saved registers.
+
+ Note that the values stored in fsr by get_frame_saved_regs are *in
+ the context of the called frame*. What this means is that the i
+ regs of fsr must be restored into the o regs of the (calling) frame that
+ we pop into. We don't care about the output regs of the calling frame,
+ since unless it's a dummy frame, it won't have any output regs in it.
+
+ We never have to bother with %l (local) regs, since the called routine's
+ locals get tossed, and the calling routine's locals are already saved
+ on its stack. */
+
+/* Definitely see tm-sparc.h for more doc of the frame format here. */
+
+void
+sparc_pop_frame ()
+{
+ register struct frame_info *frame = get_current_frame ();
+ register CORE_ADDR pc;
+ struct frame_saved_regs fsr;
+ char raw_buffer[REGISTER_BYTES];
+ int regnum;
+
+ sparc_frame_find_saved_regs (frame, &fsr);
+#ifdef FP0_REGNUM
+ if (fsr.regs[FP0_REGNUM])
+ {
+ read_memory (fsr.regs[FP0_REGNUM], raw_buffer, FP_REGISTER_BYTES);
+ write_register_bytes (REGISTER_BYTE (FP0_REGNUM),
+ raw_buffer, FP_REGISTER_BYTES);
+ }
+#ifndef GDB_TARGET_IS_SPARC64
+ if (fsr.regs[FPS_REGNUM])
+ {
+ read_memory (fsr.regs[FPS_REGNUM], raw_buffer, 4);
+ write_register_bytes (REGISTER_BYTE (FPS_REGNUM), raw_buffer, 4);
+ }
+ if (fsr.regs[CPS_REGNUM])
+ {
+ read_memory (fsr.regs[CPS_REGNUM], raw_buffer, 4);
+ write_register_bytes (REGISTER_BYTE (CPS_REGNUM), raw_buffer, 4);
+ }
+#endif
+#endif /* FP0_REGNUM */
+ if (fsr.regs[G1_REGNUM])
+ {
+ read_memory (fsr.regs[G1_REGNUM], raw_buffer, 7 * SPARC_INTREG_SIZE);
+ write_register_bytes (REGISTER_BYTE (G1_REGNUM), raw_buffer,
+ 7 * SPARC_INTREG_SIZE);
+ }
+
+ if (frame->flat)
+ {
+ /* Each register might or might not have been saved, need to test
+ individually. */
+ for (regnum = L0_REGNUM; regnum < L0_REGNUM + 8; ++regnum)
+ if (fsr.regs[regnum])
+ write_register (regnum, read_memory_integer (fsr.regs[regnum],
+ SPARC_INTREG_SIZE));
+ for (regnum = I0_REGNUM; regnum < I0_REGNUM + 8; ++regnum)
+ if (fsr.regs[regnum])
+ write_register (regnum, read_memory_integer (fsr.regs[regnum],
+ SPARC_INTREG_SIZE));
+
+ /* Handle all outs except stack pointer (o0-o5; o7). */
+ for (regnum = O0_REGNUM; regnum < O0_REGNUM + 6; ++regnum)
+ if (fsr.regs[regnum])
+ write_register (regnum, read_memory_integer (fsr.regs[regnum],
+ SPARC_INTREG_SIZE));
+ if (fsr.regs[O0_REGNUM + 7])
+ write_register (O0_REGNUM + 7,
+ read_memory_integer (fsr.regs[O0_REGNUM + 7],
+ SPARC_INTREG_SIZE));
+
+ write_sp (frame->frame);
+ }
+ else if (fsr.regs[I0_REGNUM])
+ {
+ CORE_ADDR sp;
+
+ char reg_temp[REGISTER_BYTES];
+
+ read_memory (fsr.regs[I0_REGNUM], raw_buffer, 8 * SPARC_INTREG_SIZE);
+
+ /* Get the ins and locals which we are about to restore. Just
+ moving the stack pointer is all that is really needed, except
+ store_inferior_registers is then going to write the ins and
+ locals from the registers array, so we need to muck with the
+ registers array. */
+ sp = fsr.regs[SP_REGNUM];
+#ifdef GDB_TARGET_IS_SPARC64
+ if (sp & 1)
+ sp += 2047;
+#endif
+ read_memory (sp, reg_temp, SPARC_INTREG_SIZE * 16);
+
+ /* Restore the out registers.
+ Among other things this writes the new stack pointer. */
+ write_register_bytes (REGISTER_BYTE (O0_REGNUM), raw_buffer,
+ SPARC_INTREG_SIZE * 8);
+
+ write_register_bytes (REGISTER_BYTE (L0_REGNUM), reg_temp,
+ SPARC_INTREG_SIZE * 16);
+ }
+#ifndef GDB_TARGET_IS_SPARC64
+ if (fsr.regs[PS_REGNUM])
+ write_register (PS_REGNUM, read_memory_integer (fsr.regs[PS_REGNUM], 4));
+#endif
+ if (fsr.regs[Y_REGNUM])
+ write_register (Y_REGNUM, read_memory_integer (fsr.regs[Y_REGNUM], REGISTER_RAW_SIZE (Y_REGNUM)));
+ if (fsr.regs[PC_REGNUM])
+ {
+ /* Explicitly specified PC (and maybe NPC) -- just restore them. */
+ write_register (PC_REGNUM, read_memory_integer (fsr.regs[PC_REGNUM],
+ REGISTER_RAW_SIZE (PC_REGNUM)));
+ if (fsr.regs[NPC_REGNUM])
+ write_register (NPC_REGNUM,
+ read_memory_integer (fsr.regs[NPC_REGNUM],
+ REGISTER_RAW_SIZE (NPC_REGNUM)));
+ }
+ else if (frame->flat)
+ {
+ if (frame->pc_addr)
+ pc = PC_ADJUST ((CORE_ADDR)
+ read_memory_integer (frame->pc_addr,
+ REGISTER_RAW_SIZE (PC_REGNUM)));
+ else
+ {
+ /* I think this happens only in the innermost frame, if so then
+ it is a complicated way of saying
+ "pc = read_register (O7_REGNUM);". */
+ char buf[MAX_REGISTER_RAW_SIZE];
+ get_saved_register (buf, 0, 0, frame, O7_REGNUM, 0);
+ pc = PC_ADJUST (extract_address
+ (buf, REGISTER_RAW_SIZE (O7_REGNUM)));
+ }
+
+ write_register (PC_REGNUM, pc);
+ write_register (NPC_REGNUM, pc + 4);
+ }
+ else if (fsr.regs[I7_REGNUM])
+ {
+ /* Return address in %i7 -- adjust it, then restore PC and NPC from it */
+ pc = PC_ADJUST ((CORE_ADDR) read_memory_integer (fsr.regs[I7_REGNUM],
+ SPARC_INTREG_SIZE));
+ write_register (PC_REGNUM, pc);
+ write_register (NPC_REGNUM, pc + 4);
+ }
+ flush_cached_frames ();
+}
+
+/* On the Sun 4 under SunOS, the compile will leave a fake insn which
+ encodes the structure size being returned. If we detect such
+ a fake insn, step past it. */
+
+CORE_ADDR
+sparc_pc_adjust(pc)
+ CORE_ADDR pc;
+{
+ unsigned long insn;
+ char buf[4];
+ int err;
+
+ err = target_read_memory (pc + 8, buf, 4);
+ insn = extract_unsigned_integer (buf, 4);
+ if ((err == 0) && (insn & 0xffc00000) == 0)
+ return pc+12;
+ else
+ return pc+8;
+}
+
+/* If pc is in a shared library trampoline, return its target.
+ The SunOs 4.x linker rewrites the jump table entries for PIC
+ compiled modules in the main executable to bypass the dynamic linker
+ with jumps of the form
+ sethi %hi(addr),%g1
+ jmp %g1+%lo(addr)
+ and removes the corresponding jump table relocation entry in the
+ dynamic relocations.
+ find_solib_trampoline_target relies on the presence of the jump
+ table relocation entry, so we have to detect these jump instructions
+ by hand. */
+
+CORE_ADDR
+sunos4_skip_trampoline_code (pc)
+ CORE_ADDR pc;
+{
+ unsigned long insn1;
+ char buf[4];
+ int err;
+
+ err = target_read_memory (pc, buf, 4);
+ insn1 = extract_unsigned_integer (buf, 4);
+ if (err == 0 && (insn1 & 0xffc00000) == 0x03000000)
+ {
+ unsigned long insn2;
+
+ err = target_read_memory (pc + 4, buf, 4);
+ insn2 = extract_unsigned_integer (buf, 4);
+ if (err == 0 && (insn2 & 0xffffe000) == 0x81c06000)
+ {
+ CORE_ADDR target_pc = (insn1 & 0x3fffff) << 10;
+ int delta = insn2 & 0x1fff;
+
+ /* Sign extend the displacement. */
+ if (delta & 0x1000)
+ delta |= ~0x1fff;
+ return target_pc + delta;
+ }
+ }
+ return find_solib_trampoline_target (pc);
+}
+
+#ifdef USE_PROC_FS /* Target dependent support for /proc */
+
+/* The /proc interface divides the target machine's register set up into
+ two different sets, the general register set (gregset) and the floating
+ point register set (fpregset). For each set, there is an ioctl to get
+ the current register set and another ioctl to set the current values.
+
+ The actual structure passed through the ioctl interface is, of course,
+ naturally machine dependent, and is different for each set of registers.
+ For the sparc for example, the general register set is typically defined
+ by:
+
+ typedef int gregset_t[38];
+
+ #define R_G0 0
+ ...
+ #define R_TBR 37
+
+ and the floating point set by:
+
+ typedef struct prfpregset {
+ union {
+ u_long pr_regs[32];
+ double pr_dregs[16];
+ } pr_fr;
+ void * pr_filler;
+ u_long pr_fsr;
+ u_char pr_qcnt;
+ u_char pr_q_entrysize;
+ u_char pr_en;
+ u_long pr_q[64];
+ } prfpregset_t;
+
+ These routines provide the packing and unpacking of gregset_t and
+ fpregset_t formatted data.
+
+ */
+
+/* Given a pointer to a general register set in /proc format (gregset_t *),
+ unpack the register contents and supply them as gdb's idea of the current
+ register values. */
+
+void
+supply_gregset (gregsetp)
+prgregset_t *gregsetp;
+{
+ register int regi;
+ register prgreg_t *regp = (prgreg_t *) gregsetp;
+ static char zerobuf[MAX_REGISTER_RAW_SIZE] = {0};
+
+ /* GDB register numbers for Gn, On, Ln, In all match /proc reg numbers. */
+ for (regi = G0_REGNUM ; regi <= I7_REGNUM ; regi++)
+ {
+ supply_register (regi, (char *) (regp + regi));
+ }
+
+ /* These require a bit more care. */
+ supply_register (PS_REGNUM, (char *) (regp + R_PS));
+ supply_register (PC_REGNUM, (char *) (regp + R_PC));
+ supply_register (NPC_REGNUM,(char *) (regp + R_nPC));
+ supply_register (Y_REGNUM, (char *) (regp + R_Y));
+
+ /* Fill inaccessible registers with zero. */
+ supply_register (WIM_REGNUM, zerobuf);
+ supply_register (TBR_REGNUM, zerobuf);
+ supply_register (CPS_REGNUM, zerobuf);
+}
+
+void
+fill_gregset (gregsetp, regno)
+prgregset_t *gregsetp;
+int regno;
+{
+ int regi;
+ register prgreg_t *regp = (prgreg_t *) gregsetp;
+
+ for (regi = 0 ; regi <= R_I7 ; regi++)
+ {
+ if ((regno == -1) || (regno == regi))
+ {
+ *(regp + regi) = *(int *) &registers[REGISTER_BYTE (regi)];
+ }
+ }
+ if ((regno == -1) || (regno == PS_REGNUM))
+ {
+ *(regp + R_PS) = *(int *) &registers[REGISTER_BYTE (PS_REGNUM)];
+ }
+ if ((regno == -1) || (regno == PC_REGNUM))
+ {
+ *(regp + R_PC) = *(int *) &registers[REGISTER_BYTE (PC_REGNUM)];
+ }
+ if ((regno == -1) || (regno == NPC_REGNUM))
+ {
+ *(regp + R_nPC) = *(int *) &registers[REGISTER_BYTE (NPC_REGNUM)];
+ }
+ if ((regno == -1) || (regno == Y_REGNUM))
+ {
+ *(regp + R_Y) = *(int *) &registers[REGISTER_BYTE (Y_REGNUM)];
+ }
+}
+
+#if defined (FP0_REGNUM)
+
+/* Given a pointer to a floating point register set in /proc format
+ (fpregset_t *), unpack the register contents and supply them as gdb's
+ idea of the current floating point register values. */
+
+void
+supply_fpregset (fpregsetp)
+prfpregset_t *fpregsetp;
+{
+ register int regi;
+ char *from;
+
+ for (regi = FP0_REGNUM ; regi < FP_MAX_REGNUM ; regi++)
+ {
+ from = (char *) &fpregsetp->pr_fr.pr_regs[regi-FP0_REGNUM];
+ supply_register (regi, from);
+ }
+ supply_register (FPS_REGNUM, (char *) &(fpregsetp->pr_fsr));
+}
+
+/* Given a pointer to a floating point register set in /proc format
+ (fpregset_t *), update the register specified by REGNO from gdb's idea
+ of the current floating point register set. If REGNO is -1, update
+ them all. */
+/* ??? This will probably need some changes for sparc64. */
+
+void
+fill_fpregset (fpregsetp, regno)
+prfpregset_t *fpregsetp;
+int regno;
+{
+ int regi;
+ char *to;
+ char *from;
+
+ for (regi = FP0_REGNUM ; regi < FP_MAX_REGNUM ; regi++)
+ {
+ if ((regno == -1) || (regno == regi))
+ {
+ from = (char *) &registers[REGISTER_BYTE (regi)];
+ to = (char *) &fpregsetp->pr_fr.pr_regs[regi-FP0_REGNUM];
+ memcpy (to, from, REGISTER_RAW_SIZE (regi));
+ }
+ }
+ if ((regno == -1) || (regno == FPS_REGNUM))
+ {
+ fpregsetp->pr_fsr = *(int *) &registers[REGISTER_BYTE (FPS_REGNUM)];
+ }
+}
+
+#endif /* defined (FP0_REGNUM) */
+
+#endif /* USE_PROC_FS */
+
+
+#ifdef GET_LONGJMP_TARGET
+
+/* Figure out where the longjmp will land. We expect that we have just entered
+ longjmp and haven't yet setup the stack frame, so the args are still in the
+ output regs. %o0 (O0_REGNUM) points at the jmp_buf structure from which we
+ extract the pc (JB_PC) that we will land at. The pc is copied into ADDR.
+ This routine returns true on success */
+
+int
+get_longjmp_target (pc)
+ CORE_ADDR *pc;
+{
+ CORE_ADDR jb_addr;
+#define LONGJMP_TARGET_SIZE 4
+ char buf[LONGJMP_TARGET_SIZE];
+
+ jb_addr = read_register (O0_REGNUM);
+
+ if (target_read_memory (jb_addr + JB_PC * JB_ELEMENT_SIZE, buf,
+ LONGJMP_TARGET_SIZE))
+ return 0;
+
+ *pc = extract_address (buf, LONGJMP_TARGET_SIZE);
+
+ return 1;
+}
+#endif /* GET_LONGJMP_TARGET */
+
+#ifdef STATIC_TRANSFORM_NAME
+/* SunPRO (3.0 at least), encodes the static variables. This is not
+ related to C++ mangling, it is done for C too. */
+
+char *
+sunpro_static_transform_name (name)
+ char *name;
+{
+ char *p;
+ if (name[0] == '$')
+ {
+ /* For file-local statics there will be a dollar sign, a bunch
+ of junk (the contents of which match a string given in the
+ N_OPT), a period and the name. For function-local statics
+ there will be a bunch of junk (which seems to change the
+ second character from 'A' to 'B'), a period, the name of the
+ function, and the name. So just skip everything before the
+ last period. */
+ p = strrchr (name, '.');
+ if (p != NULL)
+ name = p + 1;
+ }
+ return name;
+}
+#endif /* STATIC_TRANSFORM_NAME */
+
+
+/* Utilities for printing registers.
+ Page numbers refer to the SPARC Architecture Manual. */
+
+static void dump_ccreg PARAMS ((char *, int));
+
+static void
+dump_ccreg (reg, val)
+ char *reg;
+ int val;
+{
+ /* page 41 */
+ printf_unfiltered ("%s:%s,%s,%s,%s", reg,
+ val & 8 ? "N" : "NN",
+ val & 4 ? "Z" : "NZ",
+ val & 2 ? "O" : "NO",
+ val & 1 ? "C" : "NC"
+ );
+}
+
+static char *
+decode_asi (val)
+ int val;
+{
+ /* page 72 */
+ switch (val)
+ {
+ case 4 : return "ASI_NUCLEUS";
+ case 0x0c : return "ASI_NUCLEUS_LITTLE";
+ case 0x10 : return "ASI_AS_IF_USER_PRIMARY";
+ case 0x11 : return "ASI_AS_IF_USER_SECONDARY";
+ case 0x18 : return "ASI_AS_IF_USER_PRIMARY_LITTLE";
+ case 0x19 : return "ASI_AS_IF_USER_SECONDARY_LITTLE";
+ case 0x80 : return "ASI_PRIMARY";
+ case 0x81 : return "ASI_SECONDARY";
+ case 0x82 : return "ASI_PRIMARY_NOFAULT";
+ case 0x83 : return "ASI_SECONDARY_NOFAULT";
+ case 0x88 : return "ASI_PRIMARY_LITTLE";
+ case 0x89 : return "ASI_SECONDARY_LITTLE";
+ case 0x8a : return "ASI_PRIMARY_NOFAULT_LITTLE";
+ case 0x8b : return "ASI_SECONDARY_NOFAULT_LITTLE";
+ default : return NULL;
+ }
+}
+
+/* PRINT_REGISTER_HOOK routine.
+ Pretty print various registers. */
+/* FIXME: Would be nice if this did some fancy things for 32 bit sparc. */
+
+void
+sparc_print_register_hook (regno)
+ int regno;
+{
+ ULONGEST val;
+
+ /* Handle double/quad versions of lower 32 fp regs. */
+ if (regno >= FP0_REGNUM && regno < FP0_REGNUM + 32
+ && (regno & 1) == 0)
+ {
+ char value[16];
+
+ if (!read_relative_register_raw_bytes (regno, value)
+ && !read_relative_register_raw_bytes (regno + 1, value + 4))
+ {
+ printf_unfiltered ("\t");
+ print_floating (value, builtin_type_double, gdb_stdout);
+ }
+#if 0 /* FIXME: gdb doesn't handle long doubles */
+ if ((regno & 3) == 0)
+ {
+ if (!read_relative_register_raw_bytes (regno + 2, value + 8)
+ && !read_relative_register_raw_bytes (regno + 3, value + 12))
+ {
+ printf_unfiltered ("\t");
+ print_floating (value, builtin_type_long_double, gdb_stdout);
+ }
+ }
+#endif
+ return;
+ }
+
+#if 0 /* FIXME: gdb doesn't handle long doubles */
+ /* Print upper fp regs as long double if appropriate. */
+ if (regno >= FP0_REGNUM + 32 && regno < FP_MAX_REGNUM
+ /* We test for even numbered regs and not a multiple of 4 because
+ the upper fp regs are recorded as doubles. */
+ && (regno & 1) == 0)
+ {
+ char value[16];
+
+ if (!read_relative_register_raw_bytes (regno, value)
+ && !read_relative_register_raw_bytes (regno + 1, value + 8))
+ {
+ printf_unfiltered ("\t");
+ print_floating (value, builtin_type_long_double, gdb_stdout);
+ }
+ return;
+ }
+#endif
+
+ /* FIXME: Some of these are priviledged registers.
+ Not sure how they should be handled. */
+
+#define BITS(n, mask) ((int) (((val) >> (n)) & (mask)))
+
+ val = read_register (regno);
+
+ /* pages 40 - 60 */
+ switch (regno)
+ {
+#ifdef GDB_TARGET_IS_SPARC64
+ case CCR_REGNUM :
+ printf_unfiltered("\t");
+ dump_ccreg ("xcc", val >> 4);
+ printf_unfiltered(", ");
+ dump_ccreg ("icc", val & 15);
+ break;
+ case FPRS_REGNUM :
+ printf ("\tfef:%d, du:%d, dl:%d",
+ BITS (2, 1), BITS (1, 1), BITS (0, 1));
+ break;
+ case FSR_REGNUM :
+ {
+ static char *fcc[4] = { "=", "<", ">", "?" };
+ static char *rd[4] = { "N", "0", "+", "-" };
+ /* Long, yes, but I'd rather leave it as is and use a wide screen. */
+ printf ("\t0:%s, 1:%s, 2:%s, 3:%s, rd:%s, tem:%d, ns:%d, ver:%d, ftt:%d, qne:%d, aexc:%d, cexc:%d",
+ fcc[BITS (10, 3)], fcc[BITS (32, 3)],
+ fcc[BITS (34, 3)], fcc[BITS (36, 3)],
+ rd[BITS (30, 3)], BITS (23, 31), BITS (22, 1), BITS (17, 7),
+ BITS (14, 7), BITS (13, 1), BITS (5, 31), BITS (0, 31));
+ break;
+ }
+ case ASI_REGNUM :
+ {
+ char *asi = decode_asi (val);
+ if (asi != NULL)
+ printf ("\t%s", asi);
+ break;
+ }
+ case VER_REGNUM :
+ printf ("\tmanuf:%d, impl:%d, mask:%d, maxtl:%d, maxwin:%d",
+ BITS (48, 0xffff), BITS (32, 0xffff),
+ BITS (24, 0xff), BITS (8, 0xff), BITS (0, 31));
+ break;
+ case PSTATE_REGNUM :
+ {
+ static char *mm[4] = { "tso", "pso", "rso", "?" };
+ printf ("\tcle:%d, tle:%d, mm:%s, red:%d, pef:%d, am:%d, priv:%d, ie:%d, ag:%d",
+ BITS (9, 1), BITS (8, 1), mm[BITS (6, 3)], BITS (5, 1),
+ BITS (4, 1), BITS (3, 1), BITS (2, 1), BITS (1, 1),
+ BITS (0, 1));
+ break;
+ }
+ case TSTATE_REGNUM :
+ /* FIXME: print all 4? */
+ break;
+ case TT_REGNUM :
+ /* FIXME: print all 4? */
+ break;
+ case TPC_REGNUM :
+ /* FIXME: print all 4? */
+ break;
+ case TNPC_REGNUM :
+ /* FIXME: print all 4? */
+ break;
+ case WSTATE_REGNUM :
+ printf ("\tother:%d, normal:%d", BITS (3, 7), BITS (0, 7));
+ break;
+ case CWP_REGNUM :
+ printf ("\t%d", BITS (0, 31));
+ break;
+ case CANSAVE_REGNUM :
+ printf ("\t%-2d before spill", BITS (0, 31));
+ break;
+ case CANRESTORE_REGNUM :
+ printf ("\t%-2d before fill", BITS (0, 31));
+ break;
+ case CLEANWIN_REGNUM :
+ printf ("\t%-2d before clean", BITS (0, 31));
+ break;
+ case OTHERWIN_REGNUM :
+ printf ("\t%d", BITS (0, 31));
+ break;
+#else
+ case PS_REGNUM:
+ printf ("\ticc:%c%c%c%c, pil:%d, s:%d, ps:%d, et:%d, cwp:%d",
+ BITS (23, 1) ? 'N' : '-', BITS (22, 1) ? 'Z' : '-',
+ BITS (21, 1) ? 'V' : '-', BITS (20, 1) ? 'C' : '-',
+ BITS (8, 15), BITS (7, 1), BITS (6, 1), BITS (5, 1),
+ BITS (0, 31));
+ break;
+ case FPS_REGNUM:
+ {
+ static char *fcc[4] = { "=", "<", ">", "?" };
+ static char *rd[4] = { "N", "0", "+", "-" };
+ /* Long, yes, but I'd rather leave it as is and use a wide screen. */
+ printf ("\trd:%s, tem:%d, ns:%d, ver:%d, ftt:%d, qne:%d, "
+ "fcc:%s, aexc:%d, cexc:%d",
+ rd[BITS (30, 3)], BITS (23, 31), BITS (22, 1), BITS (17, 7),
+ BITS (14, 7), BITS (13, 1), fcc[BITS (10, 3)], BITS (5, 31),
+ BITS (0, 31));
+ break;
+ }
+
+#endif /* GDB_TARGET_IS_SPARC64 */
+ }
+
+#undef BITS
+}
+
+int
+gdb_print_insn_sparc (memaddr, info)
+ bfd_vma memaddr;
+ disassemble_info *info;
+{
+ /* It's necessary to override mach again because print_insn messes it up. */
+ info->mach = TM_PRINT_INSN_MACH;
+ return print_insn_sparc (memaddr, info);
+}
+
+/* The SPARC passes the arguments on the stack; arguments smaller
+ than an int are promoted to an int. */
+
+CORE_ADDR
+sparc_push_arguments (nargs, args, sp, struct_return, struct_addr)
+ int nargs;
+ value_ptr *args;
+ CORE_ADDR sp;
+ int struct_return;
+ CORE_ADDR struct_addr;
+{
+ int i;
+ int accumulate_size = 0;
+ struct sparc_arg
+ {
+ char *contents;
+ int len;
+ int offset;
+ };
+ struct sparc_arg *sparc_args =
+ (struct sparc_arg*)alloca (nargs * sizeof (struct sparc_arg));
+ struct sparc_arg *m_arg;
+
+ /* Promote arguments if necessary, and calculate their stack offsets
+ and sizes. */
+ for (i = 0, m_arg = sparc_args; i < nargs; i++, m_arg++)
+ {
+ value_ptr arg = args[i];
+ struct type *arg_type = check_typedef (VALUE_TYPE (arg));
+ /* Cast argument to long if necessary as the compiler does it too. */
+ switch (TYPE_CODE (arg_type))
+ {
+ case TYPE_CODE_INT:
+ case TYPE_CODE_BOOL:
+ case TYPE_CODE_CHAR:
+ case TYPE_CODE_RANGE:
+ case TYPE_CODE_ENUM:
+ if (TYPE_LENGTH (arg_type) < TYPE_LENGTH (builtin_type_long))
+ {
+ arg_type = builtin_type_long;
+ arg = value_cast (arg_type, arg);
+ }
+ break;
+ default:
+ break;
+ }
+ m_arg->len = TYPE_LENGTH (arg_type);
+ m_arg->offset = accumulate_size;
+ accumulate_size = (accumulate_size + m_arg->len + 3) & ~3;
+ m_arg->contents = VALUE_CONTENTS(arg);
+ }
+
+ /* Make room for the arguments on the stack. */
+ accumulate_size += CALL_DUMMY_STACK_ADJUST;
+ sp = ((sp - accumulate_size) & ~7) + CALL_DUMMY_STACK_ADJUST;
+
+ /* `Push' arguments on the stack. */
+ for (i = nargs; m_arg--, --i >= 0; )
+ write_memory(sp + m_arg->offset, m_arg->contents, m_arg->len);
+
+ return sp;
+}
+
+
+/* Extract from an array REGBUF containing the (raw) register state
+ a function return value of type TYPE, and copy that, in virtual format,
+ into VALBUF. */
+
+void
+sparc_extract_return_value (type, regbuf, valbuf)
+ struct type *type;
+ char *regbuf;
+ char *valbuf;
+{
+ int typelen = TYPE_LENGTH (type);
+ int regsize = REGISTER_RAW_SIZE (O0_REGNUM);
+
+ if (TYPE_CODE (type) == TYPE_CODE_FLT && SPARC_HAS_FPU)
+ memcpy (valbuf, &regbuf [REGISTER_BYTE (FP0_REGNUM)], typelen);
+ else
+ memcpy (valbuf,
+ &regbuf [O0_REGNUM * regsize +
+ (typelen >= regsize
+ || TARGET_BYTE_ORDER == LITTLE_ENDIAN ? 0
+ : regsize - typelen)],
+ typelen);
+}
+
+
+/* Write into appropriate registers a function return value
+ of type TYPE, given in virtual format. On SPARCs with FPUs,
+ float values are returned in %f0 (and %f1). In all other cases,
+ values are returned in register %o0. */
+
+void
+sparc_store_return_value (type, valbuf)
+ struct type *type;
+ char *valbuf;
+{
+ int regno;
+ char buffer[MAX_REGISTER_RAW_SIZE];
+
+ if (TYPE_CODE (type) == TYPE_CODE_FLT && SPARC_HAS_FPU)
+ /* Floating-point values are returned in the register pair */
+ /* formed by %f0 and %f1 (doubles are, anyway). */
+ regno = FP0_REGNUM;
+ else
+ /* Other values are returned in register %o0. */
+ regno = O0_REGNUM;
+
+ /* Add leading zeros to the value. */
+ if (TYPE_LENGTH (type) < REGISTER_RAW_SIZE(regno))
+ {
+ bzero (buffer, REGISTER_RAW_SIZE(regno));
+ memcpy (buffer + REGISTER_RAW_SIZE(regno) - TYPE_LENGTH (type), valbuf,
+ TYPE_LENGTH (type));
+ write_register_bytes (REGISTER_BYTE (regno), buffer,
+ REGISTER_RAW_SIZE(regno));
+ }
+ else
+ write_register_bytes (REGISTER_BYTE (regno), valbuf, TYPE_LENGTH (type));
+}
+
+
+/* Insert the function address into a call dummy instruction sequence
+ stored at DUMMY.
+
+ For structs and unions, if the function was compiled with Sun cc,
+ it expects 'unimp' after the call. But gcc doesn't use that
+ (twisted) convention. So leave a nop there for gcc (FIX_CALL_DUMMY
+ can assume it is operating on a pristine CALL_DUMMY, not one that
+ has already been customized for a different function). */
+
+void
+sparc_fix_call_dummy (dummy, pc, fun, value_type, using_gcc)
+ char *dummy;
+ CORE_ADDR pc;
+ CORE_ADDR fun;
+ struct type *value_type;
+ int using_gcc;
+{
+ int i;
+
+ /* Store the relative adddress of the target function into the
+ 'call' instruction. */
+ store_unsigned_integer (dummy + CALL_DUMMY_CALL_OFFSET, 4,
+ (0x40000000
+ | (((fun - (pc + CALL_DUMMY_CALL_OFFSET)) >> 2)
+ & 0x3fffffff)));
+
+ /* Comply with strange Sun cc calling convention for struct-returning
+ functions. */
+ if (!using_gcc
+ && (TYPE_CODE (value_type) == TYPE_CODE_STRUCT
+ || TYPE_CODE (value_type) == TYPE_CODE_UNION))
+ store_unsigned_integer (dummy + CALL_DUMMY_CALL_OFFSET + 8, 4,
+ TYPE_LENGTH (value_type) & 0x1fff);
+
+#ifndef GDB_TARGET_IS_SPARC64
+ /* If this is not a simulator target, change the first four instructions
+ of the call dummy to NOPs. Those instructions include a 'save'
+ instruction and are designed to work around problems with register
+ window flushing in the simulator. */
+ if (strcmp (target_shortname, "sim") != 0)
+ {
+ for (i = 0; i < 4; i++)
+ store_unsigned_integer (dummy + (i * 4), 4, 0x01000000);
+ }
+#endif
+
+ /* If this is a bi-endian target, GDB has written the call dummy
+ in little-endian order. We must byte-swap it back to big-endian. */
+ if (bi_endian)
+ {
+ for (i = 0; i < CALL_DUMMY_LENGTH; i += 4)
+ {
+ char tmp = dummy [i];
+ dummy [i] = dummy [i+3];
+ dummy [i+3] = tmp;
+ tmp = dummy [i+1];
+ dummy [i+1] = dummy [i+2];
+ dummy [i+2] = tmp;
+ }
+ }
+}
+
+
+/* Set target byte order based on machine type. */
+
+static int
+sparc_target_architecture_hook (ap)
+ const bfd_arch_info_type *ap;
+{
+ int i, j;
+
+ if (ap->mach == bfd_mach_sparc_sparclite_le)
+ {
+ if (TARGET_BYTE_ORDER_SELECTABLE_P)
+ {
+ target_byte_order = LITTLE_ENDIAN;
+ bi_endian = 1;
+ }
+ else
+ {
+ warning ("This GDB does not support little endian sparclite.");
+ }
+ }
+ else
+ bi_endian = 0;
+ return 1;
+}
+
+
+void
+_initialize_sparc_tdep ()
+{
+ tm_print_insn = gdb_print_insn_sparc;
+ tm_print_insn_info.mach = TM_PRINT_INSN_MACH; /* Selects sparc/sparclite */
+ target_architecture_hook = sparc_target_architecture_hook;
+}
+
+
+#ifdef GDB_TARGET_IS_SPARC64
+
+/* Compensate for stack bias. Note that we currently don't handle mixed
+ 32/64 bit code. */
+CORE_ADDR
+sparc64_read_sp ()
+{
+ CORE_ADDR sp = read_register (SP_REGNUM);
+
+ if (sp & 1)
+ sp += 2047;
+ return sp;
+}
+
+CORE_ADDR
+sparc64_read_fp ()
+{
+ CORE_ADDR fp = read_register (FP_REGNUM);
+
+ if (fp & 1)
+ fp += 2047;
+ return fp;
+}
+
+void
+sparc64_write_sp (val)
+ CORE_ADDR val;
+{
+ CORE_ADDR oldsp = read_register (SP_REGNUM);
+ if (oldsp & 1)
+ write_register (SP_REGNUM, val - 2047);
+ else
+ write_register (SP_REGNUM, val);
+}
+
+void
+sparc64_write_fp (val)
+ CORE_ADDR val;
+{
+ CORE_ADDR oldfp = read_register (FP_REGNUM);
+ if (oldfp & 1)
+ write_register (FP_REGNUM, val - 2047);
+ else
+ write_register (FP_REGNUM, val);
+}
+
+/* The SPARC 64 ABI passes floating-point arguments in FP0-31. They are
+ also copied onto the stack in the correct places. */
+
+CORE_ADDR
+sp64_push_arguments (nargs, args, sp, struct_return, struct_retaddr)
+ int nargs;
+ value_ptr *args;
+ CORE_ADDR sp;
+ unsigned char struct_return;
+ CORE_ADDR struct_retaddr;
+{
+ int x;
+ int regnum = 0;
+ CORE_ADDR tempsp;
+
+ sp = (sp & ~(((unsigned long)TYPE_LENGTH (builtin_type_long)) - 1UL));
+
+ /* Figure out how much space we'll need. */
+ for (x = nargs - 1; x >= 0; x--)
+ {
+ int len = TYPE_LENGTH (check_typedef (VALUE_TYPE (args[x])));
+ value_ptr copyarg = args[x];
+ int copylen = len;
+
+ /* This code is, of course, no longer correct. */
+ if (copylen < TYPE_LENGTH (builtin_type_long))
+ {
+ copyarg = value_cast(builtin_type_long, copyarg);
+ copylen = TYPE_LENGTH (builtin_type_long);
+ }
+ sp -= copylen;
+ }
+
+ /* Round down. */
+ sp = sp & ~7;
+ tempsp = sp;
+
+ /* Now write the arguments onto the stack, while writing FP arguments
+ into the FP registers. */
+ for (x = 0; x < nargs; x++)
+ {
+ int len = TYPE_LENGTH (check_typedef (VALUE_TYPE (args[x])));
+ value_ptr copyarg = args[x];
+ int copylen = len;
+
+ /* This code is, of course, no longer correct. */
+ if (copylen < TYPE_LENGTH (builtin_type_long))
+ {
+ copyarg = value_cast(builtin_type_long, copyarg);
+ copylen = TYPE_LENGTH (builtin_type_long);
+ }
+ write_memory (tempsp, VALUE_CONTENTS (copyarg), copylen);
+ tempsp += copylen;
+ if (TYPE_CODE (VALUE_TYPE (args[x])) == TYPE_CODE_FLT && regnum < 32)
+ {
+ /* This gets copied into a FP register. */
+ int nextreg = regnum + 2;
+ char *data = VALUE_CONTENTS (args[x]);
+ /* Floats go into the lower half of a FP register pair; quads
+ use 2 pairs. */
+
+ if (len == 16)
+ nextreg += 2;
+ else if (len == 4)
+ regnum++;
+
+ write_register_bytes (REGISTER_BYTE (FP0_REGNUM + regnum),
+ data,
+ len);
+ regnum = nextreg;
+ }
+ }
+ return sp;
+}
+
+/* Values <= 32 bytes are returned in o0-o3 (floating-point values are
+ returned in f0-f3). */
+void
+sparc64_extract_return_value (type, regbuf, valbuf, bitoffset)
+ struct type *type;
+ char *regbuf;
+ char *valbuf;
+ int bitoffset;
+{
+ int typelen = TYPE_LENGTH (type);
+ int regsize = REGISTER_RAW_SIZE (O0_REGNUM);
+
+ if (TYPE_CODE (type) == TYPE_CODE_FLT && SPARC_HAS_FPU)
+ {
+ memcpy (valbuf, &regbuf [REGISTER_BYTE (FP0_REGNUM)], typelen);
+ return;
+ }
+
+ if (TYPE_CODE (type) != TYPE_CODE_STRUCT
+ || (TYPE_LENGTH (type) > 32))
+ {
+ memcpy (valbuf,
+ &regbuf [O0_REGNUM * regsize +
+ (typelen >= regsize ? 0 : regsize - typelen)],
+ typelen);
+ return;
+ }
+ else
+ {
+ char *o0 = &regbuf[O0_REGNUM * regsize];
+ char *f0 = &regbuf[FP0_REGNUM * regsize];
+ int x;
+
+ for (x = 0; x < TYPE_NFIELDS (type); x++)
+ {
+ struct field *f = &TYPE_FIELDS(type)[x];
+ /* FIXME: We may need to handle static fields here. */
+ int whichreg = (f->loc.bitpos + bitoffset) / 32;
+ int remainder = ((f->loc.bitpos + bitoffset) % 32) / 8;
+ int where = (f->loc.bitpos + bitoffset) / 8;
+ int size = TYPE_LENGTH (f->type);
+ int typecode = TYPE_CODE (f->type);
+
+ if (typecode == TYPE_CODE_STRUCT)
+ {
+ sparc64_extract_return_value (f->type,
+ regbuf,
+ valbuf,
+ bitoffset + f->loc.bitpos);
+ }
+ else if (typecode == TYPE_CODE_FLT)
+ {
+ memcpy (valbuf + where, &f0[whichreg * 4] + remainder, size);
+ }
+ else
+ {
+ memcpy (valbuf + where, &o0[whichreg * 4] + remainder, size);
+ }
+ }
+ }
+}
+#endif
diff --git a/gdb/sparcl-stub.c b/gdb/sparcl-stub.c
new file mode 100644
index 00000000000..c7994fe5d52
--- /dev/null
+++ b/gdb/sparcl-stub.c
@@ -0,0 +1,1024 @@
+/****************************************************************************
+
+ THIS SOFTWARE IS NOT COPYRIGHTED
+
+ HP offers the following for use in the public domain. HP makes no
+ warranty with regard to the software or it's performance and the
+ user accepts the software "AS IS" with all faults.
+
+ HP DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD
+ TO THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+
+****************************************************************************/
+
+/****************************************************************************
+ * Header: remcom.c,v 1.34 91/03/09 12:29:49 glenne Exp $
+ *
+ * Module name: remcom.c $
+ * Revision: 1.34 $
+ * Date: 91/03/09 12:29:49 $
+ * Contributor: Lake Stevens Instrument Division$
+ *
+ * Description: low level support for gdb debugger. $
+ *
+ * Considerations: only works on target hardware $
+ *
+ * Written by: Glenn Engel $
+ * ModuleState: Experimental $
+ *
+ * NOTES: See Below $
+ *
+ * Modified for SPARC by Stu Grossman, Cygnus Support.
+ * Based on sparc-stub.c, it's modified for SPARClite Debug Unit hardware
+ * breakpoint support to create sparclite-stub.c, by Kung Hsu, Cygnus Support.
+ *
+ * This code has been extensively tested on the Fujitsu SPARClite demo board.
+ *
+ * To enable debugger support, two things need to happen. One, a
+ * call to set_debug_traps() is necessary in order to allow any breakpoints
+ * or error conditions to be properly intercepted and reported to gdb.
+ * Two, a breakpoint needs to be generated to begin communication. This
+ * is most easily accomplished by a call to breakpoint(). Breakpoint()
+ * simulates a breakpoint by executing a trap #1.
+ *
+ *************
+ *
+ * The following gdb commands are supported:
+ *
+ * command function Return value
+ *
+ * g return the value of the CPU registers hex data or ENN
+ * G set the value of the CPU registers OK or ENN
+ *
+ * mAA..AA,LLLL Read LLLL bytes at address AA..AA hex data or ENN
+ * MAA..AA,LLLL: Write LLLL bytes at address AA.AA OK or ENN
+ *
+ * c Resume at current address SNN ( signal NN)
+ * cAA..AA Continue at address AA..AA SNN
+ *
+ * s Step one instruction SNN
+ * sAA..AA Step one instruction from AA..AA SNN
+ *
+ * k kill
+ *
+ * ? What was the last sigval ? SNN (signal NN)
+ *
+ * bBB..BB Set baud rate to BB..BB OK or BNN, then sets
+ * baud rate
+ *
+ * All commands and responses are sent with a packet which includes a
+ * checksum. A packet consists of
+ *
+ * $<packet info>#<checksum>.
+ *
+ * where
+ * <packet info> :: <characters representing the command or response>
+ * <checksum> :: < two hex digits computed as modulo 256 sum of <packetinfo>>
+ *
+ * When a packet is received, it is first acknowledged with either '+' or '-'.
+ * '+' indicates a successful transfer. '-' indicates a failed transfer.
+ *
+ * Example:
+ *
+ * Host: Reply:
+ * $m0,10#2a +$00010203040506070809101112131415#42
+ *
+ ****************************************************************************/
+
+#include <string.h>
+#include <signal.h>
+#include <sparclite.h>
+
+/************************************************************************
+ *
+ * external low-level support routines
+ */
+
+extern void putDebugChar (int c); /* write a single character */
+extern int getDebugChar (void); /* read and return a single char */
+
+/************************************************************************/
+/* BUFMAX defines the maximum number of characters in inbound/outbound buffers*/
+/* at least NUMREGBYTES*2 are needed for register packets */
+#define BUFMAX 2048
+
+static int initialized = 0; /* !0 means we've been initialized */
+
+extern void breakinst ();
+static void set_mem_fault_trap (int enable);
+static void get_in_break_mode (void);
+
+static const char hexchars[]="0123456789abcdef";
+
+#define NUMREGS 80
+
+/* Number of bytes of registers. */
+#define NUMREGBYTES (NUMREGS * 4)
+enum regnames {G0, G1, G2, G3, G4, G5, G6, G7,
+ O0, O1, O2, O3, O4, O5, SP, O7,
+ L0, L1, L2, L3, L4, L5, L6, L7,
+ I0, I1, I2, I3, I4, I5, FP, I7,
+
+ F0, F1, F2, F3, F4, F5, F6, F7,
+ F8, F9, F10, F11, F12, F13, F14, F15,
+ F16, F17, F18, F19, F20, F21, F22, F23,
+ F24, F25, F26, F27, F28, F29, F30, F31,
+ Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR,
+ DIA1, DIA2, DDA1, DDA2, DDV1, DDV2, DCR, DSR };
+
+/*************************** ASSEMBLY CODE MACROS *************************/
+/* */
+
+extern void trap_low();
+
+/* Create private copies of common functions used by the stub. This prevents
+ nasty interactions between app code and the stub (for instance if user steps
+ into strlen, etc..) */
+
+static int
+strlen (const char *s)
+{
+ const char *s1 = s;
+
+ while (*s1++ != '\000');
+
+ return s1 - s;
+}
+
+static char *
+strcpy (char *dst, const char *src)
+{
+ char *retval = dst;
+
+ while ((*dst++ = *src++) != '\000');
+
+ return retval;
+}
+
+static void *
+memcpy (void *vdst, const void *vsrc, int n)
+{
+ char *dst = vdst;
+ const char *src = vsrc;
+ char *retval = dst;
+
+ while (n-- > 0)
+ *dst++ = *src++;
+
+ return retval;
+}
+
+asm("
+ .reserve trapstack, 1000 * 4, \"bss\", 8
+
+ .data
+ .align 4
+
+in_trap_handler:
+ .word 0
+
+ .text
+ .align 4
+
+! This function is called when any SPARC trap (except window overflow or
+! underflow) occurs. It makes sure that the invalid register window is still
+! available before jumping into C code. It will also restore the world if you
+! return from handle_exception.
+!
+! On entry, trap_low expects l1 and l2 to contain pc and npc respectivly.
+! Register usage throughout the routine is as follows:
+!
+! l0 - psr
+! l1 - pc
+! l2 - npc
+! l3 - wim
+! l4 - scratch and y reg
+! l5 - scratch and tbr
+! l6 - unused
+! l7 - unused
+
+ .globl _trap_low
+_trap_low:
+ mov %psr, %l0
+ mov %wim, %l3
+
+ srl %l3, %l0, %l4 ! wim >> cwp
+ cmp %l4, 1
+ bne window_fine ! Branch if not in the invalid window
+ nop
+
+! Handle window overflow
+
+ mov %g1, %l4 ! Save g1, we use it to hold the wim
+ srl %l3, 1, %g1 ! Rotate wim right
+ tst %g1
+ bg good_wim ! Branch if new wim is non-zero
+ nop
+
+! At this point, we need to bring a 1 into the high order bit of the wim.
+! Since we don't want to make any assumptions about the number of register
+! windows, we figure it out dynamically so as to setup the wim correctly.
+
+ not %g1 ! Fill g1 with ones
+ mov %g1, %wim ! Fill the wim with ones
+ nop
+ nop
+ nop
+ mov %wim, %g1 ! Read back the wim
+ inc %g1 ! Now g1 has 1 just to left of wim
+ srl %g1, 1, %g1 ! Now put 1 at top of wim
+ mov %g0, %wim ! Clear wim so that subsequent save
+ nop ! won't trap
+ nop
+ nop
+
+good_wim:
+ save %g0, %g0, %g0 ! Slip into next window
+ mov %g1, %wim ! Install the new wim
+
+ std %l0, [%sp + 0 * 4] ! save L & I registers
+ std %l2, [%sp + 2 * 4]
+ std %l4, [%sp + 4 * 4]
+ std %l6, [%sp + 6 * 4]
+
+ std %i0, [%sp + 8 * 4]
+ std %i2, [%sp + 10 * 4]
+ std %i4, [%sp + 12 * 4]
+ std %i6, [%sp + 14 * 4]
+
+ restore ! Go back to trap window.
+ mov %l4, %g1 ! Restore %g1
+
+window_fine:
+ sethi %hi(in_trap_handler), %l4
+ ld [%lo(in_trap_handler) + %l4], %l5
+ tst %l5
+ bg recursive_trap
+ inc %l5
+
+ set trapstack+1000*4, %sp ! Switch to trap stack
+
+recursive_trap:
+ st %l5, [%lo(in_trap_handler) + %l4]
+ sub %sp,(16+1+6+1+80)*4,%sp ! Make room for input & locals
+ ! + hidden arg + arg spill
+ ! + doubleword alignment
+ ! + registers[72] local var
+
+ std %g0, [%sp + (24 + 0) * 4] ! registers[Gx]
+ std %g2, [%sp + (24 + 2) * 4]
+ std %g4, [%sp + (24 + 4) * 4]
+ std %g6, [%sp + (24 + 6) * 4]
+
+ std %i0, [%sp + (24 + 8) * 4] ! registers[Ox]
+ std %i2, [%sp + (24 + 10) * 4]
+ std %i4, [%sp + (24 + 12) * 4]
+ std %i6, [%sp + (24 + 14) * 4]
+
+ mov %y, %l4
+ mov %tbr, %l5
+ st %l4, [%sp + (24 + 64) * 4] ! Y
+ st %l0, [%sp + (24 + 65) * 4] ! PSR
+ st %l3, [%sp + (24 + 66) * 4] ! WIM
+ st %l5, [%sp + (24 + 67) * 4] ! TBR
+ st %l1, [%sp + (24 + 68) * 4] ! PC
+ st %l2, [%sp + (24 + 69) * 4] ! NPC
+
+ or %l0, 0xf20, %l4
+ mov %l4, %psr ! Turn on traps, disable interrupts
+
+ set 0x1000, %l1
+ btst %l1, %l0 ! FP enabled?
+ be no_fpstore
+ nop
+
+! Must save fsr first, to flush the FQ. This may cause a deferred fp trap, so
+! traps must be enabled to allow the trap handler to clean things up.
+
+ st %fsr, [%sp + (24 + 70) * 4]
+
+ std %f0, [%sp + (24 + 32) * 4]
+ std %f2, [%sp + (24 + 34) * 4]
+ std %f4, [%sp + (24 + 36) * 4]
+ std %f6, [%sp + (24 + 38) * 4]
+ std %f8, [%sp + (24 + 40) * 4]
+ std %f10, [%sp + (24 + 42) * 4]
+ std %f12, [%sp + (24 + 44) * 4]
+ std %f14, [%sp + (24 + 46) * 4]
+ std %f16, [%sp + (24 + 48) * 4]
+ std %f18, [%sp + (24 + 50) * 4]
+ std %f20, [%sp + (24 + 52) * 4]
+ std %f22, [%sp + (24 + 54) * 4]
+ std %f24, [%sp + (24 + 56) * 4]
+ std %f26, [%sp + (24 + 58) * 4]
+ std %f28, [%sp + (24 + 60) * 4]
+ std %f30, [%sp + (24 + 62) * 4]
+no_fpstore:
+
+ call _handle_exception
+ add %sp, 24 * 4, %o0 ! Pass address of registers
+
+! Reload all of the registers that aren't on the stack
+
+ ld [%sp + (24 + 1) * 4], %g1 ! registers[Gx]
+ ldd [%sp + (24 + 2) * 4], %g2
+ ldd [%sp + (24 + 4) * 4], %g4
+ ldd [%sp + (24 + 6) * 4], %g6
+
+ ldd [%sp + (24 + 8) * 4], %i0 ! registers[Ox]
+ ldd [%sp + (24 + 10) * 4], %i2
+ ldd [%sp + (24 + 12) * 4], %i4
+ ldd [%sp + (24 + 14) * 4], %i6
+
+
+ ldd [%sp + (24 + 64) * 4], %l0 ! Y & PSR
+ ldd [%sp + (24 + 68) * 4], %l2 ! PC & NPC
+
+ set 0x1000, %l5
+ btst %l5, %l1 ! FP enabled?
+ be no_fpreload
+ nop
+
+ ldd [%sp + (24 + 32) * 4], %f0
+ ldd [%sp + (24 + 34) * 4], %f2
+ ldd [%sp + (24 + 36) * 4], %f4
+ ldd [%sp + (24 + 38) * 4], %f6
+ ldd [%sp + (24 + 40) * 4], %f8
+ ldd [%sp + (24 + 42) * 4], %f10
+ ldd [%sp + (24 + 44) * 4], %f12
+ ldd [%sp + (24 + 46) * 4], %f14
+ ldd [%sp + (24 + 48) * 4], %f16
+ ldd [%sp + (24 + 50) * 4], %f18
+ ldd [%sp + (24 + 52) * 4], %f20
+ ldd [%sp + (24 + 54) * 4], %f22
+ ldd [%sp + (24 + 56) * 4], %f24
+ ldd [%sp + (24 + 58) * 4], %f26
+ ldd [%sp + (24 + 60) * 4], %f28
+ ldd [%sp + (24 + 62) * 4], %f30
+
+ ld [%sp + (24 + 70) * 4], %fsr
+no_fpreload:
+
+ restore ! Ensure that previous window is valid
+ save %g0, %g0, %g0 ! by causing a window_underflow trap
+
+ mov %l0, %y
+ mov %l1, %psr ! Make sure that traps are disabled
+ ! for rett
+ sethi %hi(in_trap_handler), %l4
+ ld [%lo(in_trap_handler) + %l4], %l5
+ dec %l5
+ st %l5, [%lo(in_trap_handler) + %l4]
+
+ jmpl %l2, %g0 ! Restore old PC
+ rett %l3 ! Restore old nPC
+");
+
+/* Convert ch from a hex digit to an int */
+
+static int
+hex(ch)
+ unsigned char ch;
+{
+ if (ch >= 'a' && ch <= 'f')
+ return ch-'a'+10;
+ if (ch >= '0' && ch <= '9')
+ return ch-'0';
+ if (ch >= 'A' && ch <= 'F')
+ return ch-'A'+10;
+ return -1;
+}
+
+/* scan for the sequence $<data>#<checksum> */
+
+static void
+getpacket(buffer)
+ char *buffer;
+{
+ unsigned char checksum;
+ unsigned char xmitcsum;
+ int i;
+ int count;
+ unsigned char ch;
+
+ do
+ {
+ /* wait around for the start character, ignore all other characters */
+ while ((ch = (getDebugChar() & 0x7f)) != '$') ;
+
+ checksum = 0;
+ xmitcsum = -1;
+
+ count = 0;
+
+ /* now, read until a # or end of buffer is found */
+ while (count < BUFMAX)
+ {
+ ch = getDebugChar() & 0x7f;
+ if (ch == '#')
+ break;
+ checksum = checksum + ch;
+ buffer[count] = ch;
+ count = count + 1;
+ }
+
+ if (count >= BUFMAX)
+ continue;
+
+ buffer[count] = 0;
+
+ if (ch == '#')
+ {
+ xmitcsum = hex(getDebugChar() & 0x7f) << 4;
+ xmitcsum |= hex(getDebugChar() & 0x7f);
+#if 0
+ /* Humans shouldn't have to figure out checksums to type to it. */
+ putDebugChar ('+');
+ return;
+#endif
+ if (checksum != xmitcsum)
+ putDebugChar('-'); /* failed checksum */
+ else
+ {
+ putDebugChar('+'); /* successful transfer */
+ /* if a sequence char is present, reply the sequence ID */
+ if (buffer[2] == ':')
+ {
+ putDebugChar(buffer[0]);
+ putDebugChar(buffer[1]);
+ /* remove sequence chars from buffer */
+ count = strlen(buffer);
+ for (i=3; i <= count; i++)
+ buffer[i-3] = buffer[i];
+ }
+ }
+ }
+ }
+ while (checksum != xmitcsum);
+}
+
+/* send the packet in buffer. */
+
+static void
+putpacket(buffer)
+ unsigned char *buffer;
+{
+ unsigned char checksum;
+ int count;
+ unsigned char ch;
+
+ /* $<packet info>#<checksum>. */
+ do
+ {
+ putDebugChar('$');
+ checksum = 0;
+ count = 0;
+
+ while (ch = buffer[count])
+ {
+ putDebugChar (ch);
+ checksum += ch;
+ count += 1;
+ }
+
+ putDebugChar('#');
+ putDebugChar(hexchars[checksum >> 4]);
+ putDebugChar(hexchars[checksum & 0xf]);
+
+ }
+ while ((getDebugChar() & 0x7f) != '+');
+}
+
+static char remcomInBuffer[BUFMAX];
+static char remcomOutBuffer[BUFMAX];
+
+/* Indicate to caller of mem2hex or hex2mem that there has been an
+ error. */
+static volatile int mem_err = 0;
+
+/* Convert the memory pointed to by mem into hex, placing result in buf.
+ * Return a pointer to the last char put in buf (null), in case of mem fault,
+ * return 0.
+ * If MAY_FAULT is non-zero, then we will handle memory faults by returning
+ * a 0, else treat a fault like any other fault in the stub.
+ */
+
+static unsigned char *
+mem2hex(mem, buf, count, may_fault)
+ unsigned char *mem;
+ unsigned char *buf;
+ int count;
+ int may_fault;
+{
+ unsigned char ch;
+
+ set_mem_fault_trap(may_fault);
+
+ while (count-- > 0)
+ {
+ ch = *mem++;
+ if (mem_err)
+ return 0;
+ *buf++ = hexchars[ch >> 4];
+ *buf++ = hexchars[ch & 0xf];
+ }
+
+ *buf = 0;
+
+ set_mem_fault_trap(0);
+
+ return buf;
+}
+
+/* convert the hex array pointed to by buf into binary to be placed in mem
+ * return a pointer to the character AFTER the last byte written */
+
+static char *
+hex2mem(buf, mem, count, may_fault)
+ unsigned char *buf;
+ unsigned char *mem;
+ int count;
+ int may_fault;
+{
+ int i;
+ unsigned char ch;
+
+ set_mem_fault_trap(may_fault);
+
+ for (i=0; i<count; i++)
+ {
+ ch = hex(*buf++) << 4;
+ ch |= hex(*buf++);
+ *mem++ = ch;
+ if (mem_err)
+ return 0;
+ }
+
+ set_mem_fault_trap(0);
+
+ return mem;
+}
+
+/* This table contains the mapping between SPARC hardware trap types, and
+ signals, which are primarily what GDB understands. It also indicates
+ which hardware traps we need to commandeer when initializing the stub. */
+
+static struct hard_trap_info
+{
+ unsigned char tt; /* Trap type code for SPARClite */
+ unsigned char signo; /* Signal that we map this trap into */
+} hard_trap_info[] = {
+ {0x01, SIGSEGV}, /* instruction access error */
+ {0x02, SIGILL}, /* privileged instruction */
+ {0x03, SIGILL}, /* illegal instruction */
+ {0x04, SIGEMT}, /* fp disabled */
+ {0x07, SIGBUS}, /* mem address not aligned */
+ {0x09, SIGSEGV}, /* data access exception */
+ {0x0a, SIGEMT}, /* tag overflow */
+ {0x20, SIGBUS}, /* r register access error */
+ {0x21, SIGBUS}, /* instruction access error */
+ {0x24, SIGEMT}, /* cp disabled */
+ {0x29, SIGBUS}, /* data access error */
+ {0x2a, SIGFPE}, /* divide by zero */
+ {0x2b, SIGBUS}, /* data store error */
+ {0x80+1, SIGTRAP}, /* ta 1 - normal breakpoint instruction */
+ {0xff, SIGTRAP}, /* hardware breakpoint */
+ {0, 0} /* Must be last */
+};
+
+/* Set up exception handlers for tracing and breakpoints */
+
+void
+set_debug_traps()
+{
+ struct hard_trap_info *ht;
+
+/* Only setup fp traps if the FP is disabled. */
+
+ for (ht = hard_trap_info;
+ ht->tt != 0 && ht->signo != 0;
+ ht++)
+ if (ht->tt != 4 || ! (read_psr () & 0x1000))
+ exceptionHandler(ht->tt, trap_low);
+
+ /* In case GDB is started before us, ack any packets (presumably
+ "$?#xx") sitting there. */
+
+ putDebugChar ('+');
+
+ initialized = 1;
+}
+
+asm ("
+! Trap handler for memory errors. This just sets mem_err to be non-zero. It
+! assumes that %l1 is non-zero. This should be safe, as it is doubtful that
+! 0 would ever contain code that could mem fault. This routine will skip
+! past the faulting instruction after setting mem_err.
+
+ .text
+ .align 4
+
+_fltr_set_mem_err:
+ sethi %hi(_mem_err), %l0
+ st %l1, [%l0 + %lo(_mem_err)]
+ jmpl %l2, %g0
+ rett %l2+4
+");
+
+static void
+set_mem_fault_trap(enable)
+ int enable;
+{
+ extern void fltr_set_mem_err();
+ mem_err = 0;
+
+ if (enable)
+ exceptionHandler(9, fltr_set_mem_err);
+ else
+ exceptionHandler(9, trap_low);
+}
+
+asm ("
+ .text
+ .align 4
+
+_dummy_hw_breakpoint:
+ jmpl %l2, %g0
+ rett %l2+4
+ nop
+ nop
+");
+
+static void
+get_in_break_mode()
+{
+ extern void dummy_hw_breakpoint();
+
+ exceptionHandler (255, dummy_hw_breakpoint);
+
+ asm ("ta 255");
+
+ exceptionHandler (255, trap_low);
+}
+
+/* Convert the SPARC hardware trap type code to a unix signal number. */
+
+static int
+computeSignal(tt)
+ int tt;
+{
+ struct hard_trap_info *ht;
+
+ for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
+ if (ht->tt == tt)
+ return ht->signo;
+
+ return SIGHUP; /* default for things we don't know about */
+}
+
+/*
+ * While we find nice hex chars, build an int.
+ * Return number of chars processed.
+ */
+
+static int
+hexToInt(char **ptr, int *intValue)
+{
+ int numChars = 0;
+ int hexValue;
+
+ *intValue = 0;
+
+ while (**ptr)
+ {
+ hexValue = hex(**ptr);
+ if (hexValue < 0)
+ break;
+
+ *intValue = (*intValue << 4) | hexValue;
+ numChars ++;
+
+ (*ptr)++;
+ }
+
+ return (numChars);
+}
+
+/*
+ * This function does all command procesing for interfacing to gdb. It
+ * returns 1 if you should skip the instruction at the trap address, 0
+ * otherwise.
+ */
+
+static void
+handle_exception (registers)
+ unsigned long *registers;
+{
+ int tt; /* Trap type */
+ int sigval;
+ int addr;
+ int length;
+ char *ptr;
+ unsigned long *sp;
+ unsigned long dsr;
+
+/* First, we must force all of the windows to be spilled out */
+
+ asm(" save %sp, -64, %sp
+ save %sp, -64, %sp
+ save %sp, -64, %sp
+ save %sp, -64, %sp
+ save %sp, -64, %sp
+ save %sp, -64, %sp
+ save %sp, -64, %sp
+ save %sp, -64, %sp
+ restore
+ restore
+ restore
+ restore
+ restore
+ restore
+ restore
+ restore
+");
+
+ get_in_break_mode (); /* Enable DSU register writes */
+
+ registers[DIA1] = read_asi (1, 0xff00);
+ registers[DIA2] = read_asi (1, 0xff04);
+ registers[DDA1] = read_asi (1, 0xff08);
+ registers[DDA2] = read_asi (1, 0xff0c);
+ registers[DDV1] = read_asi (1, 0xff10);
+ registers[DDV2] = read_asi (1, 0xff14);
+ registers[DCR] = read_asi (1, 0xff18);
+ registers[DSR] = read_asi (1, 0xff1c);
+
+ if (registers[PC] == (unsigned long)breakinst)
+ {
+ registers[PC] = registers[NPC];
+ registers[NPC] += 4;
+ }
+ sp = (unsigned long *)registers[SP];
+
+ dsr = (unsigned long)registers[DSR];
+ if (dsr & 0x3c)
+ tt = 255;
+ else
+ tt = (registers[TBR] >> 4) & 0xff;
+
+ /* reply to host that an exception has occurred */
+ sigval = computeSignal(tt);
+ ptr = remcomOutBuffer;
+
+ *ptr++ = 'T';
+ *ptr++ = hexchars[sigval >> 4];
+ *ptr++ = hexchars[sigval & 0xf];
+
+ *ptr++ = hexchars[PC >> 4];
+ *ptr++ = hexchars[PC & 0xf];
+ *ptr++ = ':';
+ ptr = mem2hex((char *)&registers[PC], ptr, 4, 0);
+ *ptr++ = ';';
+
+ *ptr++ = hexchars[FP >> 4];
+ *ptr++ = hexchars[FP & 0xf];
+ *ptr++ = ':';
+ ptr = mem2hex(sp + 8 + 6, ptr, 4, 0); /* FP */
+ *ptr++ = ';';
+
+ *ptr++ = hexchars[SP >> 4];
+ *ptr++ = hexchars[SP & 0xf];
+ *ptr++ = ':';
+ ptr = mem2hex((char *)&sp, ptr, 4, 0);
+ *ptr++ = ';';
+
+ *ptr++ = hexchars[NPC >> 4];
+ *ptr++ = hexchars[NPC & 0xf];
+ *ptr++ = ':';
+ ptr = mem2hex((char *)&registers[NPC], ptr, 4, 0);
+ *ptr++ = ';';
+
+ *ptr++ = hexchars[O7 >> 4];
+ *ptr++ = hexchars[O7 & 0xf];
+ *ptr++ = ':';
+ ptr = mem2hex((char *)&registers[O7], ptr, 4, 0);
+ *ptr++ = ';';
+
+ *ptr++ = 0;
+
+ putpacket(remcomOutBuffer);
+
+ while (1)
+ {
+ remcomOutBuffer[0] = 0;
+
+ getpacket(remcomInBuffer);
+ switch (remcomInBuffer[0])
+ {
+ case '?':
+ remcomOutBuffer[0] = 'S';
+ remcomOutBuffer[1] = hexchars[sigval >> 4];
+ remcomOutBuffer[2] = hexchars[sigval & 0xf];
+ remcomOutBuffer[3] = 0;
+ break;
+
+ case 'd':
+ /* toggle debug flag */
+ break;
+
+ case 'g': /* return the value of the CPU registers */
+ memcpy (&registers[L0], sp, 16 * 4); /* Copy L & I regs from stack */
+ mem2hex ((char *)registers, remcomOutBuffer, NUMREGBYTES, 0);
+ break;
+
+ case 'G': /* Set the value of all registers */
+ case 'P': /* Set the value of one register */
+ {
+ unsigned long *newsp, psr;
+
+ psr = registers[PSR];
+
+ ptr = &remcomInBuffer[1];
+
+ if (remcomInBuffer[0] == 'P')
+ {
+ int regno;
+
+ if (hexToInt (&ptr, &regno)
+ && *ptr++ == '=')
+ if (regno >= L0 && regno <= I7)
+ hex2mem (ptr, sp + regno - L0, 4, 0);
+ else
+ hex2mem (ptr, (char *)&registers[regno], 4, 0);
+ else
+ {
+ strcpy (remcomOutBuffer, "P01");
+ break;
+ }
+ }
+ else
+ {
+ hex2mem (ptr, (char *)registers, NUMREGBYTES, 0);
+ memcpy (sp, &registers[L0], 16 * 4); /* Copy L & I regs to stack */
+ }
+
+ /* See if the stack pointer has moved. If so, then copy the saved
+ locals and ins to the new location. This keeps the window
+ overflow and underflow routines happy. */
+
+ newsp = (unsigned long *)registers[SP];
+ if (sp != newsp)
+ sp = memcpy(newsp, sp, 16 * 4);
+
+ /* Don't allow CWP to be modified. */
+
+ if (psr != registers[PSR])
+ registers[PSR] = (psr & 0x1f) | (registers[PSR] & ~0x1f);
+
+ strcpy(remcomOutBuffer,"OK");
+ }
+ break;
+
+ case 'm': /* mAA..AA,LLLL Read LLLL bytes at address AA..AA */
+ /* Try to read %x,%x. */
+
+ ptr = &remcomInBuffer[1];
+
+ if (hexToInt(&ptr, &addr)
+ && *ptr++ == ','
+ && hexToInt(&ptr, &length))
+ {
+ if (mem2hex((char *)addr, remcomOutBuffer, length, 1))
+ break;
+
+ strcpy (remcomOutBuffer, "E03");
+ }
+ else
+ strcpy(remcomOutBuffer,"E01");
+ break;
+
+ case 'M': /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
+ /* Try to read '%x,%x:'. */
+
+ ptr = &remcomInBuffer[1];
+
+ if (hexToInt(&ptr, &addr)
+ && *ptr++ == ','
+ && hexToInt(&ptr, &length)
+ && *ptr++ == ':')
+ {
+ if (hex2mem(ptr, (char *)addr, length, 1))
+ strcpy(remcomOutBuffer, "OK");
+ else
+ strcpy(remcomOutBuffer, "E03");
+ }
+ else
+ strcpy(remcomOutBuffer, "E02");
+ break;
+
+ case 'c': /* cAA..AA Continue at address AA..AA(optional) */
+ /* try to read optional parameter, pc unchanged if no parm */
+
+ ptr = &remcomInBuffer[1];
+ if (hexToInt(&ptr, &addr))
+ {
+ registers[PC] = addr;
+ registers[NPC] = addr + 4;
+ }
+
+/* Need to flush the instruction cache here, as we may have deposited a
+ breakpoint, and the icache probably has no way of knowing that a data ref to
+ some location may have changed something that is in the instruction cache.
+ */
+
+ flush_i_cache ();
+
+ if (!(registers[DSR] & 0x1) /* DSU enabled? */
+ && !(registers[DCR] & 0x200)) /* Are we in break state? */
+ { /* Yes, set the DSU regs */
+ write_asi (1, 0xff00, registers[DIA1]);
+ write_asi (1, 0xff04, registers[DIA2]);
+ write_asi (1, 0xff08, registers[DDA1]);
+ write_asi (1, 0xff0c, registers[DDA2]);
+ write_asi (1, 0xff10, registers[DDV1]);
+ write_asi (1, 0xff14, registers[DDV2]);
+ write_asi (1, 0xff1c, registers[DSR]);
+ write_asi (1, 0xff18, registers[DCR] | 0x200); /* Clear break */
+ }
+
+ return;
+
+ /* kill the program */
+ case 'k' : /* do nothing */
+ break;
+#if 0
+ case 't': /* Test feature */
+ asm (" std %f30,[%sp]");
+ break;
+#endif
+ case 'r': /* Reset */
+ asm ("call 0
+ nop ");
+ break;
+
+#if 0
+Disabled until we can unscrew this properly
+
+ case 'b': /* bBB... Set baud rate to BB... */
+ {
+ int baudrate;
+ extern void set_timer_3();
+
+ ptr = &remcomInBuffer[1];
+ if (!hexToInt(&ptr, &baudrate))
+ {
+ strcpy(remcomOutBuffer,"B01");
+ break;
+ }
+
+ /* Convert baud rate to uart clock divider */
+ switch (baudrate)
+ {
+ case 38400:
+ baudrate = 16;
+ break;
+ case 19200:
+ baudrate = 33;
+ break;
+ case 9600:
+ baudrate = 65;
+ break;
+ default:
+ strcpy(remcomOutBuffer,"B02");
+ goto x1;
+ }
+
+ putpacket("OK"); /* Ack before changing speed */
+ set_timer_3(baudrate); /* Set it */
+ }
+x1: break;
+#endif
+ } /* switch */
+
+ /* reply to the request */
+ putpacket(remcomOutBuffer);
+ }
+}
+
+/* This function will generate a breakpoint exception. It is used at the
+ beginning of a program to sync up with a debugger and can be used
+ otherwise as a quick means to stop program execution and "break" into
+ the debugger. */
+
+void
+breakpoint()
+{
+ if (!initialized)
+ return;
+
+ asm(" .globl _breakinst
+
+ _breakinst: ta 1
+ ");
+}
diff --git a/gdb/sparcl-tdep.c b/gdb/sparcl-tdep.c
new file mode 100644
index 00000000000..e39bf306ec9
--- /dev/null
+++ b/gdb/sparcl-tdep.c
@@ -0,0 +1,970 @@
+/* Target dependent code for the Fujitsu SPARClite for GDB, the GNU debugger.
+ Copyright 1994, 1995, 1996 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "gdbcore.h"
+#include "breakpoint.h"
+#include "target.h"
+#include "serial.h"
+#include <sys/types.h>
+
+#if (!defined(__GO32__) && !defined(_WIN32)) || defined(__CYGWIN32__)
+#define HAVE_SOCKETS
+#include <sys/time.h>
+#include <unistd.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#endif
+
+extern struct target_ops sparclite_ops; /* Forward decl */
+extern struct target_ops remote_ops;
+
+static char *remote_target_name = NULL;
+static serial_t remote_desc = NULL;
+static int serial_flag;
+#ifdef HAVE_SOCKETS
+static int udp_fd = -1;
+#endif
+
+static serial_t open_tty PARAMS ((char *name));
+static int send_resp PARAMS ((serial_t desc, char c));
+static void close_tty PARAMS ((int ignore));
+#ifdef HAVE_SOCKETS
+static int recv_udp_buf PARAMS ((int fd, unsigned char *buf, int len, int timeout));
+static int send_udp_buf PARAMS ((int fd, unsigned char *buf, int len));
+#endif
+static void sparclite_open PARAMS ((char *name, int from_tty));
+static void sparclite_close PARAMS ((int quitting));
+static void download PARAMS ((char *target_name, char *args, int from_tty,
+ void (*write_routine) (bfd *from_bfd,
+ asection *from_sec,
+ file_ptr from_addr,
+ bfd_vma to_addr, int len),
+ void (*start_routine) (bfd_vma entry)));
+static void sparclite_serial_start PARAMS ((bfd_vma entry));
+static void sparclite_serial_write PARAMS ((bfd *from_bfd, asection *from_sec,
+ file_ptr from_addr,
+ bfd_vma to_addr, int len));
+#ifdef HAVE_SOCKETS
+static unsigned short calc_checksum PARAMS ((unsigned char *buffer,
+ int count));
+static void sparclite_udp_start PARAMS ((bfd_vma entry));
+static void sparclite_udp_write PARAMS ((bfd *from_bfd, asection *from_sec,
+ file_ptr from_addr, bfd_vma to_addr,
+ int len));
+#endif
+static void sparclite_download PARAMS ((char *filename, int from_tty));
+
+#define DDA2_SUP_ASI 0xb000000
+#define DDA1_SUP_ASI 0xb0000
+
+#define DDA2_ASI_MASK 0xff000000
+#define DDA1_ASI_MASK 0xff0000
+#define DIA2_SUP_MODE 0x8000
+#define DIA1_SUP_MODE 0x4000
+#define DDA2_ENABLE 0x100
+#define DDA1_ENABLE 0x80
+#define DIA2_ENABLE 0x40
+#define DIA1_ENABLE 0x20
+#define DSINGLE_STEP 0x10 /* not used */
+#define DDV_TYPE_MASK 0xc
+#define DDV_TYPE_LOAD 0x0
+#define DDV_TYPE_STORE 0x4
+#define DDV_TYPE_ACCESS 0x8
+#define DDV_TYPE_ALWAYS 0xc
+#define DDV_COND 0x2
+#define DDV_MASK 0x1
+
+int
+sparclite_insert_watchpoint (addr, len, type)
+ CORE_ADDR addr;
+ int len;
+ int type;
+{
+ CORE_ADDR dcr;
+
+ dcr = read_register (DCR_REGNUM);
+
+ if (!(dcr & DDA1_ENABLE))
+ {
+ write_register (DDA1_REGNUM, addr);
+ dcr &= ~(DDA1_ASI_MASK | DDV_TYPE_MASK);
+ dcr |= (DDA1_SUP_ASI | DDA1_ENABLE);
+ if (type == 1)
+ {
+ write_register (DDV1_REGNUM, 0);
+ write_register (DDV2_REGNUM, 0xffffffff);
+ dcr |= (DDV_TYPE_LOAD & (~DDV_COND & ~DDV_MASK));
+ }
+ else if (type == 0)
+ {
+ write_register (DDV1_REGNUM, 0);
+ write_register (DDV2_REGNUM, 0xffffffff);
+ dcr |= (DDV_TYPE_STORE & (~DDV_COND & ~DDV_MASK));
+ }
+ else
+ {
+ write_register (DDV1_REGNUM, 0);
+ write_register (DDV2_REGNUM, 0xffffffff);
+ dcr |= (DDV_TYPE_ACCESS);
+ }
+ write_register (DCR_REGNUM, dcr);
+ }
+ else if (!(dcr & DDA2_ENABLE))
+ {
+ write_register (DDA2_REGNUM, addr);
+ dcr &= ~(DDA2_ASI_MASK & DDV_TYPE_MASK);
+ dcr |= (DDA2_SUP_ASI | DDA2_ENABLE);
+ if (type == 1)
+ {
+ write_register (DDV1_REGNUM, 0);
+ write_register (DDV2_REGNUM, 0xffffffff);
+ dcr |= (DDV_TYPE_LOAD & ~DDV_COND & ~DDV_MASK);
+ }
+ else if (type == 0)
+ {
+ write_register (DDV1_REGNUM, 0);
+ write_register (DDV2_REGNUM, 0xffffffff);
+ dcr |= (DDV_TYPE_STORE & ~DDV_COND & ~DDV_MASK);
+ }
+ else
+ {
+ write_register (DDV1_REGNUM, 0);
+ write_register (DDV2_REGNUM, 0xffffffff);
+ dcr |= (DDV_TYPE_ACCESS);
+ }
+ write_register (DCR_REGNUM, dcr);
+ }
+ else
+ return -1;
+
+ return 0;
+}
+
+int
+sparclite_remove_watchpoint (addr, len, type)
+ CORE_ADDR addr;
+ int len;
+ int type;
+{
+ CORE_ADDR dcr, dda1, dda2;
+
+ dcr = read_register (DCR_REGNUM);
+ dda1 = read_register (DDA1_REGNUM);
+ dda2 = read_register (DDA2_REGNUM);
+
+ if ((dcr & DDA1_ENABLE) && addr == dda1)
+ write_register (DCR_REGNUM, (dcr & ~DDA1_ENABLE));
+ else if ((dcr & DDA2_ENABLE) && addr == dda2)
+ write_register (DCR_REGNUM, (dcr & ~DDA2_ENABLE));
+ else
+ return -1;
+
+ return 0;
+}
+
+int
+sparclite_insert_hw_breakpoint (addr, len)
+ CORE_ADDR addr;
+ int len;
+{
+ CORE_ADDR dcr;
+
+ dcr = read_register (DCR_REGNUM);
+
+ if (!(dcr & DIA1_ENABLE))
+ {
+ write_register (DIA1_REGNUM, addr);
+ write_register (DCR_REGNUM, (dcr | DIA1_ENABLE | DIA1_SUP_MODE));
+ }
+ else if (!(dcr & DIA2_ENABLE))
+ {
+ write_register (DIA2_REGNUM, addr);
+ write_register (DCR_REGNUM, (dcr | DIA2_ENABLE | DIA2_SUP_MODE));
+ }
+ else
+ return -1;
+
+ return 0;
+}
+
+int
+sparclite_remove_hw_breakpoint (addr, shadow)
+ CORE_ADDR addr;
+ int shadow;
+{
+ CORE_ADDR dcr, dia1, dia2;
+
+ dcr = read_register (DCR_REGNUM);
+ dia1 = read_register (DIA1_REGNUM);
+ dia2 = read_register (DIA2_REGNUM);
+
+ if ((dcr & DIA1_ENABLE) && addr == dia1)
+ write_register (DCR_REGNUM, (dcr & ~DIA1_ENABLE));
+ else if ((dcr & DIA2_ENABLE) && addr == dia2)
+ write_register (DCR_REGNUM, (dcr & ~DIA2_ENABLE));
+ else
+ return -1;
+
+ return 0;
+}
+
+int
+sparclite_check_watch_resources (type, cnt, ot)
+ int type;
+ int cnt;
+ int ot;
+{
+ /* Watchpoints not supported on simulator. */
+ if (strcmp (target_shortname, "sim") == 0)
+ return 0;
+
+ if (type == bp_hardware_breakpoint)
+ {
+ if (TARGET_HW_BREAK_LIMIT == 0)
+ return 0;
+ else if (cnt <= TARGET_HW_BREAK_LIMIT)
+ return 1;
+ }
+ else
+ {
+ if (TARGET_HW_WATCH_LIMIT == 0)
+ return 0;
+ else if (ot)
+ return -1;
+ else if (cnt <= TARGET_HW_WATCH_LIMIT)
+ return 1;
+ }
+ return -1;
+}
+
+CORE_ADDR
+sparclite_stopped_data_address ()
+{
+ CORE_ADDR dsr, dda1, dda2;
+
+ dsr = read_register (DSR_REGNUM);
+ dda1 = read_register (DDA1_REGNUM);
+ dda2 = read_register (DDA2_REGNUM);
+
+ if (dsr & 0x10)
+ return dda1;
+ else if (dsr & 0x20)
+ return dda2;
+ else
+ return 0;
+}
+
+static serial_t
+open_tty (name)
+ char *name;
+{
+ serial_t desc;
+
+ desc = SERIAL_OPEN (name);
+ if (!desc)
+ perror_with_name (name);
+
+ if (baud_rate != -1)
+ {
+ if (SERIAL_SETBAUDRATE (desc, baud_rate))
+ {
+ SERIAL_CLOSE (desc);
+ perror_with_name (name);
+ }
+ }
+
+ SERIAL_RAW (desc);
+
+ SERIAL_FLUSH_INPUT (desc);
+
+ return desc;
+}
+
+/* Read a single character from the remote end, masking it down to 7 bits. */
+
+static int
+readchar (desc, timeout)
+ serial_t desc;
+ int timeout;
+{
+ int ch;
+ char s[10];
+
+ ch = SERIAL_READCHAR (desc, timeout);
+
+ switch (ch)
+ {
+ case SERIAL_EOF:
+ error ("SPARClite remote connection closed");
+ case SERIAL_ERROR:
+ perror_with_name ("SPARClite communication error");
+ case SERIAL_TIMEOUT:
+ error ("SPARClite remote timeout");
+ default:
+ if (remote_debug > 0)
+ {
+ sprintf (s, "[%02x]", ch & 0xff);
+ puts_debug ("read -->", s, "<--");
+ }
+ return ch;
+ }
+}
+
+static void
+debug_serial_write (desc, buf, len)
+ serial_t desc;
+ char *buf;
+ int len;
+{
+ char s[10];
+
+ SERIAL_WRITE (desc, buf, len);
+ if (remote_debug > 0)
+ {
+ while (len-- > 0)
+ {
+ sprintf (s, "[%02x]", *buf & 0xff);
+ puts_debug ("Sent -->", s, "<--");
+ buf++;
+ }
+ }
+}
+
+
+static int
+send_resp (desc, c)
+ serial_t desc;
+ char c;
+{
+ debug_serial_write (desc, &c, 1);
+ return readchar (desc, remote_timeout);
+}
+
+static void
+close_tty (ignore)
+ int ignore;
+{
+ if (!remote_desc)
+ return;
+
+ SERIAL_CLOSE (remote_desc);
+
+ remote_desc = NULL;
+}
+
+#ifdef HAVE_SOCKETS
+static int
+recv_udp_buf (fd, buf, len, timeout)
+ int fd, len;
+ unsigned char *buf;
+ int timeout;
+{
+ int cc;
+ fd_set readfds;
+
+ FD_ZERO (&readfds);
+ FD_SET (fd, &readfds);
+
+ if (timeout >= 0)
+ {
+ struct timeval timebuf;
+
+ timebuf.tv_sec = timeout;
+ timebuf.tv_usec = 0;
+ cc = select (fd + 1, &readfds, 0, 0, &timebuf);
+ }
+ else
+ cc = select (fd + 1, &readfds, 0, 0, 0);
+
+ if (cc == 0)
+ return 0;
+
+ if (cc != 1)
+ perror_with_name ("recv_udp_buf: Bad return value from select:");
+
+ cc = recv (fd, buf, len, 0);
+
+ if (cc < 0)
+ perror_with_name ("Got an error from recv: ");
+}
+
+static int
+send_udp_buf (fd, buf, len)
+ int fd, len;
+ unsigned char *buf;
+{
+ int cc;
+
+ cc = send (fd, buf, len, 0);
+
+ if (cc == len)
+ return;
+
+ if (cc < 0)
+ perror_with_name ("Got an error from send: ");
+
+ error ("Short count in send: tried %d, sent %d\n", len, cc);
+}
+#endif /* HAVE_SOCKETS */
+
+static void
+sparclite_open (name, from_tty)
+ char *name;
+ int from_tty;
+{
+ struct cleanup *old_chain;
+ int c;
+ char *p;
+
+ if (!name)
+ error ("You need to specify what device or hostname is associated with the SparcLite board.");
+
+ target_preopen (from_tty);
+
+ unpush_target (&sparclite_ops);
+
+ if (remote_target_name)
+ free (remote_target_name);
+
+ remote_target_name = strsave (name);
+
+ /* We need a 'serial' or 'udp' keyword to disambiguate host:port, which can
+ mean either a serial port on a terminal server, or the IP address of a
+ SPARClite demo board. If there's no colon, then it pretty much has to be
+ a local device (except for DOS... grrmble) */
+
+ p = strchr (name, ' ');
+
+ if (p)
+ {
+ *p++ = '\000';
+ while ((*p != '\000') && isspace (*p)) p++;
+
+ if (strncmp (name, "serial", strlen (name)) == 0)
+ serial_flag = 1;
+ else if (strncmp (name, "udp", strlen (name)) == 0)
+ serial_flag = 0;
+ else
+ error ("Must specify either `serial' or `udp'.");
+ }
+ else
+ {
+ p = name;
+
+ if (!strchr (name, ':'))
+ serial_flag = 1; /* No colon is unambiguous (local device) */
+ else
+ error ("Usage: target sparclite serial /dev/ttyb\n\
+or: target sparclite udp host");
+ }
+
+ if (serial_flag)
+ {
+ remote_desc = open_tty (p);
+
+ old_chain = make_cleanup ((make_cleanup_func) close_tty, 0);
+
+ c = send_resp (remote_desc, 0x00);
+
+ if (c != 0xaa)
+ error ("Unknown response (0x%x) from SparcLite. Try resetting the board.",
+ c);
+
+ c = send_resp (remote_desc, 0x55);
+
+ if (c != 0x55)
+ error ("Sparclite appears to be ill.");
+ }
+ else
+ {
+#ifdef HAVE_SOCKETS
+ struct hostent *he;
+ struct sockaddr_in sockaddr;
+ unsigned char buffer[100];
+ int cc;
+
+ /* Setup the socket. Must be raw UDP. */
+
+ he = gethostbyname (p);
+
+ if (!he)
+ error ("No such host %s.", p);
+
+ udp_fd = socket (PF_INET, SOCK_DGRAM, 0);
+
+ old_chain = make_cleanup (close, udp_fd);
+
+ sockaddr.sin_family = PF_INET;
+ sockaddr.sin_port = htons(7000);
+ memcpy (&sockaddr.sin_addr.s_addr, he->h_addr, sizeof (struct in_addr));
+
+ if (connect (udp_fd, &sockaddr, sizeof(sockaddr)))
+ perror_with_name ("Connect failed");
+
+ buffer[0] = 0x5;
+ buffer[1] = 0;
+
+ send_udp_buf (udp_fd, buffer, 2); /* Request version */
+ cc = recv_udp_buf (udp_fd, buffer, sizeof(buffer), 5); /* Get response */
+ if (cc == 0)
+ error ("SPARClite isn't responding.");
+
+ if (cc < 3)
+ error ("SPARClite appears to be ill.");
+#else
+ error ("UDP downloading is not supported for DOS hosts.");
+#endif /* HAVE_SOCKETS */
+ }
+
+ printf_unfiltered ("[SPARClite appears to be alive]\n");
+
+ push_target (&sparclite_ops);
+
+ discard_cleanups (old_chain);
+
+ return;
+}
+
+static void
+sparclite_close (quitting)
+ int quitting;
+{
+ if (serial_flag)
+ close_tty (0);
+#ifdef HAVE_SOCKETS
+ else
+ if (udp_fd != -1)
+ close (udp_fd);
+#endif
+}
+
+#define LOAD_ADDRESS 0x40000000
+
+static void
+download (target_name, args, from_tty, write_routine, start_routine)
+ char *target_name;
+ char *args;
+ int from_tty;
+ void (*write_routine) PARAMS ((bfd *from_bfd, asection *from_sec,
+ file_ptr from_addr, bfd_vma to_addr, int len));
+ void (*start_routine) PARAMS ((bfd_vma entry));
+{
+ struct cleanup *old_chain;
+ asection *section;
+ bfd *pbfd;
+ bfd_vma entry;
+ int i;
+#define WRITESIZE 1024
+ char *filename;
+ int quiet;
+ int nostart;
+
+ quiet = 0;
+ nostart = 0;
+ filename = NULL;
+
+ while (*args != '\000')
+ {
+ char *arg;
+
+ while (isspace (*args)) args++;
+
+ arg = args;
+
+ while ((*args != '\000') && !isspace (*args)) args++;
+
+ if (*args != '\000')
+ *args++ = '\000';
+
+ if (*arg != '-')
+ filename = arg;
+ else if (strncmp (arg, "-quiet", strlen (arg)) == 0)
+ quiet = 1;
+ else if (strncmp (arg, "-nostart", strlen (arg)) == 0)
+ nostart = 1;
+ else
+ error ("unknown option `%s'", arg);
+ }
+
+ if (!filename)
+ filename = get_exec_file (1);
+
+ pbfd = bfd_openr (filename, gnutarget);
+ if (pbfd == NULL)
+ {
+ perror_with_name (filename);
+ return;
+ }
+ old_chain = make_cleanup ((make_cleanup_func) bfd_close, pbfd);
+
+ if (!bfd_check_format (pbfd, bfd_object))
+ error ("\"%s\" is not an object file: %s", filename,
+ bfd_errmsg (bfd_get_error ()));
+
+ for (section = pbfd->sections; section; section = section->next)
+ {
+ if (bfd_get_section_flags (pbfd, section) & SEC_LOAD)
+ {
+ bfd_vma section_address;
+ bfd_size_type section_size;
+ file_ptr fptr;
+ const char *section_name;
+
+ section_name = bfd_get_section_name(pbfd, section);
+
+ section_address = bfd_get_section_vma (pbfd, section);
+
+ /* Adjust sections from a.out files, since they don't
+ carry their addresses with. */
+ if (bfd_get_flavour (pbfd) == bfd_target_aout_flavour)
+ {
+ if (strcmp (section_name, ".text") == 0)
+ section_address = bfd_get_start_address (pbfd);
+ else if (strcmp (section_name, ".data") == 0)
+ {
+ /* Read the first 8 bytes of the data section.
+ There should be the string 'DaTa' followed by
+ a word containing the actual section address. */
+ struct data_marker
+ {
+ char signature[4]; /* 'DaTa' */
+ unsigned char sdata[4]; /* &sdata */
+ } marker;
+ bfd_get_section_contents (pbfd, section, &marker, 0,
+ sizeof (marker));
+ if (strncmp (marker.signature, "DaTa", 4) == 0)
+ {
+ if (TARGET_BYTE_ORDER == BIG_ENDIAN)
+ section_address = bfd_getb32 (marker.sdata);
+ else
+ section_address = bfd_getl32 (marker.sdata);
+ }
+ }
+ }
+
+ section_size = bfd_get_section_size_before_reloc (section);
+
+ if (!quiet)
+ printf_filtered ("[Loading section %s at 0x%x (%d bytes)]\n",
+ bfd_get_section_name (pbfd, section),
+ section_address,
+ section_size);
+
+ fptr = 0;
+ while (section_size > 0)
+ {
+ int count;
+ static char inds[] = "|/-\\";
+ static int k = 0;
+
+ QUIT;
+
+ count = min (section_size, WRITESIZE);
+
+ write_routine (pbfd, section, fptr, section_address, count);
+
+ if (!quiet)
+ {
+ printf_unfiltered ("\r%c", inds[k++ % 4]);
+ gdb_flush (gdb_stdout);
+ }
+
+ section_address += count;
+ fptr += count;
+ section_size -= count;
+ }
+ }
+ }
+
+ if (!nostart)
+ {
+ entry = bfd_get_start_address (pbfd);
+
+ if (!quiet)
+ printf_unfiltered ("[Starting %s at 0x%x]\n", filename, entry);
+
+ start_routine (entry);
+ }
+
+ do_cleanups (old_chain);
+}
+
+static void
+sparclite_serial_start (entry)
+ bfd_vma entry;
+{
+ char buffer[5];
+ int i;
+
+ buffer[0] = 0x03;
+ store_unsigned_integer (buffer + 1, 4, entry);
+
+ debug_serial_write (remote_desc, buffer, 1 + 4);
+ i = readchar (remote_desc, remote_timeout);
+ if (i != 0x55)
+ error ("Can't start SparcLite. Error code %d\n", i);
+}
+
+static void
+sparclite_serial_write (from_bfd, from_sec, from_addr, to_addr, len)
+ bfd *from_bfd;
+ asection *from_sec;
+ file_ptr from_addr;
+ bfd_vma to_addr;
+ int len;
+{
+ char buffer[4 + 4 + WRITESIZE]; /* addr + len + data */
+ unsigned char checksum;
+ int i;
+
+ store_unsigned_integer (buffer, 4, to_addr); /* Address */
+ store_unsigned_integer (buffer + 4, 4, len); /* Length */
+
+ bfd_get_section_contents (from_bfd, from_sec, buffer + 8, from_addr, len);
+
+ checksum = 0;
+ for (i = 0; i < len; i++)
+ checksum += buffer[8 + i];
+
+ i = send_resp (remote_desc, 0x01);
+
+ if (i != 0x5a)
+ error ("Bad response from load command (0x%x)", i);
+
+ debug_serial_write (remote_desc, buffer, 4 + 4 + len);
+ i = readchar (remote_desc, remote_timeout);
+
+ if (i != checksum)
+ error ("Bad checksum from load command (0x%x)", i);
+}
+
+#ifdef HAVE_SOCKETS
+
+static unsigned short
+calc_checksum (buffer, count)
+ unsigned char *buffer;
+ int count;
+{
+ unsigned short checksum;
+
+ checksum = 0;
+ for (; count > 0; count -= 2, buffer += 2)
+ checksum += (*buffer << 8) | *(buffer + 1);
+
+ if (count != 0)
+ checksum += *buffer << 8;
+
+ return checksum;
+}
+
+static void
+sparclite_udp_start (entry)
+ bfd_vma entry;
+{
+ unsigned char buffer[6];
+ int i;
+
+ buffer[0] = 0x3;
+ buffer[1] = 0;
+ buffer[2] = entry >> 24;
+ buffer[3] = entry >> 16;
+ buffer[4] = entry >> 8;
+ buffer[5] = entry;
+
+ send_udp_buf (udp_fd, buffer, 6); /* Send start addr */
+ i = recv_udp_buf (udp_fd, buffer, sizeof(buffer), -1); /* Get response */
+
+ if (i < 1 || buffer[0] != 0x55)
+ error ("Failed to take start address.");
+}
+
+static void
+sparclite_udp_write (from_bfd, from_sec, from_addr, to_addr, len)
+ bfd *from_bfd;
+ asection *from_sec;
+ file_ptr from_addr;
+ bfd_vma to_addr;
+ int len;
+{
+ unsigned char buffer[2000];
+ unsigned short checksum;
+ static int pkt_num = 0;
+ static unsigned long old_addr = -1;
+ int i;
+
+ while (1)
+ {
+ if (to_addr != old_addr)
+ {
+ buffer[0] = 0x1; /* Load command */
+ buffer[1] = 0x1; /* Loading address */
+ buffer[2] = to_addr >> 24;
+ buffer[3] = to_addr >> 16;
+ buffer[4] = to_addr >> 8;
+ buffer[5] = to_addr;
+
+ checksum = 0;
+ for (i = 0; i < 6; i++)
+ checksum += buffer[i];
+ checksum &= 0xff;
+
+ send_udp_buf (udp_fd, buffer, 6);
+ i = recv_udp_buf (udp_fd, buffer, sizeof buffer, -1);
+
+ if (i < 1)
+ error ("Got back short checksum for load addr.");
+
+ if (checksum != buffer[0])
+ error ("Got back bad checksum for load addr.");
+
+ pkt_num = 0; /* Load addr resets packet seq # */
+ old_addr = to_addr;
+ }
+
+ bfd_get_section_contents (from_bfd, from_sec, buffer + 6, from_addr,
+ len);
+
+ checksum = calc_checksum (buffer + 6, len);
+
+ buffer[0] = 0x1; /* Load command */
+ buffer[1] = 0x2; /* Loading data */
+ buffer[2] = pkt_num >> 8;
+ buffer[3] = pkt_num;
+ buffer[4] = checksum >> 8;
+ buffer[5] = checksum;
+
+ send_udp_buf (udp_fd, buffer, len + 6);
+ i = recv_udp_buf (udp_fd, buffer, sizeof buffer, 3);
+
+ if (i == 0)
+ {
+ fprintf_unfiltered (gdb_stderr, "send_data: timeout sending %d bytes to address 0x%x retrying\n", len, to_addr);
+ continue;
+ }
+
+ if (buffer[0] != 0xff)
+ error ("Got back bad response for load data.");
+
+ old_addr += len;
+ pkt_num++;
+
+ return;
+ }
+}
+
+#endif /* HAVE_SOCKETS */
+
+static void
+sparclite_download (filename, from_tty)
+ char *filename;
+ int from_tty;
+{
+ if (!serial_flag)
+#ifdef HAVE_SOCKETS
+ download (remote_target_name, filename, from_tty, sparclite_udp_write,
+ sparclite_udp_start);
+#else
+ abort (); /* sparclite_open should prevent this! */
+#endif
+ else
+ download (remote_target_name, filename, from_tty, sparclite_serial_write,
+ sparclite_serial_start);
+}
+
+/* Define the target subroutine names */
+
+static struct target_ops sparclite_ops ;
+
+static void
+init_sparclite_ops(void)
+{
+ sparclite_ops.to_shortname = "sparclite";
+ sparclite_ops.to_longname = "SPARClite remote target";
+ sparclite_ops.to_doc = "Use a remote SPARClite target board via a serial line; using a gdb-specific protocol.\n\
+Specify the serial device it is connected to (e.g. /dev/ttya).";
+ sparclite_ops.to_open = sparclite_open;
+ sparclite_ops.to_close = sparclite_close;
+ sparclite_ops.to_attach = 0;
+ sparclite_ops.to_post_attach = NULL;
+ sparclite_ops.to_require_attach = NULL;
+ sparclite_ops.to_detach = 0;
+ sparclite_ops.to_require_detach = NULL;
+ sparclite_ops.to_resume = 0;
+ sparclite_ops.to_wait = 0;
+ sparclite_ops.to_post_wait = NULL;
+ sparclite_ops.to_fetch_registers = 0;
+ sparclite_ops.to_store_registers = 0;
+ sparclite_ops.to_prepare_to_store = 0;
+ sparclite_ops.to_xfer_memory = 0;
+ sparclite_ops.to_files_info = 0;
+ sparclite_ops.to_insert_breakpoint = 0;
+ sparclite_ops.to_remove_breakpoint = 0;
+ sparclite_ops.to_terminal_init = 0;
+ sparclite_ops.to_terminal_inferior = 0;
+ sparclite_ops.to_terminal_ours_for_output = 0;
+ sparclite_ops.to_terminal_ours = 0;
+ sparclite_ops.to_terminal_info = 0;
+ sparclite_ops.to_kill = 0;
+ sparclite_ops.to_load = sparclite_download;
+ sparclite_ops.to_lookup_symbol = 0;
+ sparclite_ops.to_create_inferior = 0;
+ sparclite_ops.to_post_startup_inferior = NULL;
+ sparclite_ops.to_acknowledge_created_inferior = NULL;
+ sparclite_ops.to_clone_and_follow_inferior = NULL;
+ sparclite_ops.to_post_follow_inferior_by_clone = NULL;
+ sparclite_ops.to_insert_fork_catchpoint = NULL;
+ sparclite_ops.to_remove_fork_catchpoint = NULL;
+ sparclite_ops.to_insert_vfork_catchpoint = NULL;
+ sparclite_ops.to_remove_vfork_catchpoint = NULL;
+ sparclite_ops.to_has_forked = NULL;
+ sparclite_ops.to_has_vforked = NULL;
+ sparclite_ops.to_can_follow_vfork_prior_to_exec = NULL;
+ sparclite_ops.to_post_follow_vfork = NULL;
+ sparclite_ops.to_insert_exec_catchpoint = NULL;
+ sparclite_ops.to_remove_exec_catchpoint = NULL;
+ sparclite_ops.to_has_execd = NULL;
+ sparclite_ops.to_reported_exec_events_per_exec_call = NULL;
+ sparclite_ops.to_has_exited = NULL;
+ sparclite_ops.to_mourn_inferior = 0;
+ sparclite_ops.to_can_run = 0;
+ sparclite_ops.to_notice_signals = 0;
+ sparclite_ops.to_thread_alive = 0;
+ sparclite_ops.to_stop = 0;
+ sparclite_ops.to_pid_to_exec_file = NULL;
+ sparclite_ops.to_core_file_to_sym_file = NULL;
+ sparclite_ops.to_stratum = download_stratum;
+ sparclite_ops.DONT_USE = 0;
+ sparclite_ops.to_has_all_memory = 0;
+ sparclite_ops.to_has_memory = 0;
+ sparclite_ops.to_has_stack = 0;
+ sparclite_ops.to_has_registers = 0;
+ sparclite_ops.to_has_execution = 0;
+ sparclite_ops.to_sections = 0;
+ sparclite_ops.to_sections_end = 0;
+ sparclite_ops.to_magic = OPS_MAGIC ;
+} /* init_sparclite_ops */
+
+void
+_initialize_sparcl_tdep ()
+{
+ init_sparclite_ops() ;
+ add_target (&sparclite_ops);
+}
diff --git a/gdb/sparclet-rom.c b/gdb/sparclet-rom.c
new file mode 100644
index 00000000000..992cca1ab51
--- /dev/null
+++ b/gdb/sparclet-rom.c
@@ -0,0 +1,296 @@
+/* Remote target glue for the SPARC Sparclet ROM monitor.
+ Copyright 1995, 1996 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+
+#include "defs.h"
+#include "gdbcore.h"
+#include "target.h"
+#include "monitor.h"
+#include "serial.h"
+#include "srec.h"
+#include "symtab.h"
+#include "symfile.h" /* for generic_load */
+#include <time.h>
+
+extern void report_transfer_performance PARAMS ((unsigned long, time_t, time_t));
+
+static struct target_ops sparclet_ops;
+
+static void sparclet_open PARAMS ((char *args, int from_tty));
+
+/* This array of registers need to match the indexes used by GDB.
+ This exists because the various ROM monitors use different strings
+ than does GDB, and don't necessarily support all the registers
+ either. So, typing "info reg sp" becomes a "r30". */
+
+/*PSR 0x00000080 impl ver icc AW LE EE EC EF PIL S PS ET CWP WIM
+ 0x0 0x0 0x0 0 0 0 0 0 0x0 1 0 0 0x00 0x2
+ 0000010
+ INS LOCALS OUTS GLOBALS
+ 0 0x00000000 0x00000000 0x00000000 0x00000000
+ 1 0x00000000 0x00000000 0x00000000 0x00000000
+ 2 0x00000000 0x00000000 0x00000000 0x00000000
+ 3 0x00000000 0x00000000 0x00000000 0x00000000
+ 4 0x00000000 0x00000000 0x00000000 0x00000000
+ 5 0x00000000 0x00001000 0x00000000 0x00000000
+ 6 0x00000000 0x00000000 0x123f0000 0x00000000
+ 7 0x00000000 0x00000000 0x00000000 0x00000000
+pc: 0x12010000 0x00000000 unimp
+npc: 0x12010004 0x00001000 unimp 0x1000
+tbr: 0x00000000
+y: 0x00000000
+*/
+/* these correspond to the offsets from tm-* files from config directories */
+
+/* is wim part of psr?? */
+/* monitor wants lower case */
+static char *sparclet_regnames[NUM_REGS] = REGISTER_NAMES;
+
+
+/* Function: sparclet_supply_register
+ Just returns with no action.
+ This function is required, because parse_register_dump (monitor.c)
+ expects to be able to call it. If we don't supply something, it will
+ call a null pointer and core-dump. Since this function does not
+ actually do anything, GDB will request the registers individually. */
+
+static void
+sparclet_supply_register (regname, regnamelen, val, vallen)
+ char *regname;
+ int regnamelen;
+ char *val;
+ int vallen;
+{
+ return;
+}
+
+static void
+sparclet_load (desc, file, hashmark)
+ serial_t desc;
+ char *file;
+ int hashmark;
+{
+ bfd *abfd;
+ asection *s;
+ int i;
+ CORE_ADDR load_offset;
+ time_t start_time, end_time;
+ unsigned long data_count = 0;
+
+ /* enable user to specify address for downloading as 2nd arg to load */
+
+ i = sscanf(file, "%*s 0x%lx", &load_offset);
+ if (i >= 1 )
+ {
+ char *p;
+
+ for (p = file; *p != '\000' && !isspace (*p); p++);
+
+ *p = '\000';
+ }
+ else
+ load_offset = 0;
+
+ abfd = bfd_openr (file, 0);
+ if (!abfd)
+ {
+ printf_filtered ("Unable to open file %s\n", file);
+ return;
+ }
+
+ if (bfd_check_format (abfd, bfd_object) == 0)
+ {
+ printf_filtered ("File is not an object file\n");
+ return;
+ }
+
+ start_time = time (NULL);
+
+ for (s = abfd->sections; s; s = s->next)
+ if (s->flags & SEC_LOAD)
+ {
+ bfd_size_type section_size;
+ bfd_vma vma;
+
+ vma = bfd_get_section_vma (abfd, s) + load_offset;
+ section_size = bfd_section_size (abfd, s);
+
+ data_count += section_size;
+
+ printf_filtered ("%s\t: 0x%4x .. 0x%4x ",
+ bfd_get_section_name (abfd, s), vma,
+ vma + section_size);
+ gdb_flush (gdb_stdout);
+
+ monitor_printf ("load c r %x %x\r", vma, section_size);
+
+ monitor_expect ("load: loading ", NULL, 0);
+ monitor_expect ("\r", NULL, 0);
+
+ for (i = 0; i < section_size; i += 2048)
+ {
+ int numbytes;
+ char buf[2048];
+
+ numbytes = min (sizeof buf, section_size - i);
+
+ bfd_get_section_contents (abfd, s, buf, i, numbytes);
+
+ SERIAL_WRITE (desc, buf, numbytes);
+
+ if (hashmark)
+ {
+ putchar_unfiltered ('#');
+ gdb_flush (gdb_stdout);
+ }
+ } /* Per-packet (or S-record) loop */
+
+ monitor_expect_prompt (NULL, 0);
+
+ putchar_unfiltered ('\n');
+ } /* Loadable sections */
+
+ monitor_printf ("reg pc %x\r", bfd_get_start_address (abfd));
+ monitor_expect_prompt (NULL, 0);
+ monitor_printf ("reg npc %x\r", bfd_get_start_address (abfd) + 4);
+ monitor_expect_prompt (NULL, 0);
+
+ monitor_printf ("run\r");
+
+ end_time = time (NULL);
+
+ if (hashmark)
+ putchar_unfiltered ('\n');
+
+ report_transfer_performance (data_count, start_time, end_time);
+
+ pop_target ();
+ push_remote_target (monitor_get_dev_name (), 1);
+
+ return_to_top_level (RETURN_QUIT);
+}
+
+/* Define the monitor command strings. Since these are passed directly
+ through to a printf style function, we may include formatting
+ strings. We also need a CR or LF on the end. */
+
+/* need to pause the monitor for timing reasons, so slow it down */
+
+static char *sparclet_inits[] = {"\n\r\r\n", NULL};
+
+static struct monitor_ops sparclet_cmds ;
+
+static void
+init_sparclet_cmds(void)
+{
+ sparclet_cmds.flags = MO_CLR_BREAK_USES_ADDR |
+ MO_HEX_PREFIX |
+ MO_NO_ECHO_ON_OPEN |
+ MO_NO_ECHO_ON_SETMEM |
+ MO_RUN_FIRST_TIME |
+ MO_GETMEM_READ_SINGLE ; /* flags */
+ sparclet_cmds.init = sparclet_inits; /* Init strings */
+ sparclet_cmds.cont = "cont\r"; /* continue command */
+ sparclet_cmds.step = "step\r"; /* single step */
+ sparclet_cmds.stop = "\r"; /* break interrupts the program */
+ sparclet_cmds.set_break = "+bp %x\r"; /* set a breakpoint */
+ sparclet_cmds.clr_break = "-bp %x\r" ; /* can't use "br" because only 2 hw bps are supported */
+ sparclet_cmds.clr_all_break = "-bp %x\r"; /* clear a breakpoint */
+ "-bp\r" ; /* clear all breakpoints */
+ sparclet_cmds.fill = "fill %x -n %x -v %x -b\r"; /* fill (start length val) */
+ /* can't use "fi" because it takes words, not bytes */
+ /* ex [addr] [-n count] [-b|-s|-l] default: ex cur -n 1 -b */
+ sparclet_cmds.setmem.cmdb = "ex %x -b\r%x\rq\r"; /* setmem.cmdb (addr, value) */
+ sparclet_cmds.setmem.cmdw = "ex %x -s\r%x\rq\r"; /* setmem.cmdw (addr, value) */
+ sparclet_cmds.setmem.cmdl = "ex %x -l\r%x\rq\r"; /* setmem.cmdl (addr, value) */
+ sparclet_cmds.setmem.cmdll = NULL; /* setmem.cmdll (addr, value) */
+ sparclet_cmds.setmem.resp_delim = NULL; /*": " */ /* setmem.resp_delim */
+ sparclet_cmds.setmem.term = NULL; /*"? " */ /* setmem.term */
+ sparclet_cmds.setmem.term_cmd = NULL; /*"q\r" */ /* setmem.term_cmd */
+ /* since the parsing of multiple bytes is difficult due to
+ interspersed addresses, we'll only read 1 value at a time,
+ even tho these can handle a count */
+ /* we can use -n to set count to read, but may have to parse? */
+ sparclet_cmds.getmem.cmdb = "ex %x -n 1 -b\r"; /* getmem.cmdb (addr, #bytes) */
+ sparclet_cmds.getmem.cmdw = "ex %x -n 1 -s\r"; /* getmem.cmdw (addr, #swords) */
+ sparclet_cmds.getmem.cmdl = "ex %x -n 1 -l\r"; /* getmem.cmdl (addr, #words) */
+ sparclet_cmds.getmem.cmdll = NULL; /* getmem.cmdll (addr, #dwords) */
+ sparclet_cmds.getmem.resp_delim = ": "; /* getmem.resp_delim */
+ sparclet_cmds.getmem.term = NULL; /* getmem.term */
+ sparclet_cmds.getmem.term_cmd = NULL; /* getmem.term_cmd */
+ sparclet_cmds.setreg.cmd = "reg %s 0x%x\r"; /* setreg.cmd (name, value) */
+ sparclet_cmds.setreg.resp_delim = NULL; /* setreg.resp_delim */
+ sparclet_cmds.setreg.term = NULL; /* setreg.term */
+ sparclet_cmds.setreg.term_cmd = NULL ; /* setreg.term_cmd */
+ sparclet_cmds.getreg.cmd = "reg %s\r"; /* getreg.cmd (name) */
+ sparclet_cmds.getreg.resp_delim = " "; /* getreg.resp_delim */
+ sparclet_cmds.getreg.term = NULL; /* getreg.term */
+ sparclet_cmds.getreg.term_cmd = NULL; /* getreg.term_cmd */
+ sparclet_cmds.dump_registers = "reg\r"; /* dump_registers */
+ sparclet_cmds.register_pattern = "\\(\\w+\\)=\\([0-9a-fA-F]+\\)"; /* register_pattern */
+ sparclet_cmds.supply_register = sparclet_supply_register; /* supply_register */
+ sparclet_cmds.load_routine = sparclet_load; /* load_routine */
+ sparclet_cmds.load = NULL; /* download command (srecs on console) */
+ sparclet_cmds.loadresp = NULL; /* load response */
+ sparclet_cmds.prompt = "monitor>"; /* monitor command prompt */
+ /* yikes! gdb core dumps without this delimitor!! */
+ sparclet_cmds.line_term = "\r"; /* end-of-command delimitor */
+ sparclet_cmds.cmd_end = NULL; /* optional command terminator */
+ sparclet_cmds.target = &sparclet_ops; /* target operations */
+ sparclet_cmds.stopbits = SERIAL_1_STOPBITS; /* number of stop bits */
+ sparclet_cmds.regnames = sparclet_regnames; /* registers names */
+ sparclet_cmds.magic = MONITOR_OPS_MAGIC ; /* magic */
+};
+
+static void
+sparclet_open (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ monitor_open (args, &sparclet_cmds, from_tty);
+}
+
+void
+_initialize_sparclet ()
+{
+ int i;
+ init_sparclet_cmds() ;
+
+ for (i = 0; i < NUM_REGS; i++)
+ if (sparclet_regnames[i][0] == 'c' ||
+ sparclet_regnames[i][0] == 'a')
+ sparclet_regnames[i] = 0; /* mon can't report c* or a* regs */
+
+ sparclet_regnames[0] = 0; /* mon won't report %G0 */
+
+ init_monitor_ops (&sparclet_ops);
+ sparclet_ops.to_shortname = "sparclet"; /* for the target command */
+ sparclet_ops.to_longname = "SPARC Sparclet monitor";
+ /* use SW breaks; target only supports 2 HW breakpoints */
+ sparclet_ops.to_insert_breakpoint = memory_insert_breakpoint;
+ sparclet_ops.to_remove_breakpoint = memory_remove_breakpoint;
+
+ sparclet_ops.to_doc =
+ "Use a board running the Sparclet debug monitor.\n\
+Specify the serial device it is connected to (e.g. /dev/ttya).";
+
+ sparclet_ops.to_open = sparclet_open;
+ add_target (&sparclet_ops);
+}
+
diff --git a/gdb/sparclet-stub.c b/gdb/sparclet-stub.c
new file mode 100644
index 00000000000..ecf670b1152
--- /dev/null
+++ b/gdb/sparclet-stub.c
@@ -0,0 +1,1232 @@
+/****************************************************************************
+
+ THIS SOFTWARE IS NOT COPYRIGHTED
+
+ HP offers the following for use in the public domain. HP makes no
+ warranty with regard to the software or it's performance and the
+ user accepts the software "AS IS" with all faults.
+
+ HP DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD
+ TO THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+
+****************************************************************************/
+
+/****************************************************************************
+ * Header: remcom.c,v 1.34 91/03/09 12:29:49 glenne Exp $
+ *
+ * Module name: remcom.c $
+ * Revision: 1.34 $
+ * Date: 91/03/09 12:29:49 $
+ * Contributor: Lake Stevens Instrument Division$
+ *
+ * Description: low level support for gdb debugger. $
+ *
+ * Considerations: only works on target hardware $
+ *
+ * Written by: Glenn Engel $
+ * ModuleState: Experimental $
+ *
+ * NOTES: See Below $
+ *
+ * Modified for SPARC by Stu Grossman, Cygnus Support.
+ * Based on sparc-stub.c, it's modified for SPARClite Debug Unit hardware
+ * breakpoint support to create sparclite-stub.c, by Kung Hsu, Cygnus Support.
+ *
+ * This code has been extensively tested on the Fujitsu SPARClite demo board.
+ *
+ * To enable debugger support, two things need to happen. One, a
+ * call to set_debug_traps() is necessary in order to allow any breakpoints
+ * or error conditions to be properly intercepted and reported to gdb.
+ * Two, a breakpoint needs to be generated to begin communication. This
+ * is most easily accomplished by a call to breakpoint(). Breakpoint()
+ * simulates a breakpoint by executing a trap #1.
+ *
+ *************
+ *
+ * The following gdb commands are supported:
+ *
+ * command function Return value
+ *
+ * g return the value of the CPU registers hex data or ENN
+ * G set the value of the CPU registers OK or ENN
+ * P set the value of a single CPU register OK or P01 (???)
+ *
+ * mAA..AA,LLLL Read LLLL bytes at address AA..AA hex data or ENN
+ * MAA..AA,LLLL: Write LLLL bytes at address AA.AA OK or ENN
+ *
+ * c Resume at current address SNN ( signal NN)
+ * cAA..AA Continue at address AA..AA SNN
+ *
+ * s Step one instruction SNN
+ * sAA..AA Step one instruction from AA..AA SNN
+ *
+ * k kill
+ *
+ * ? What was the last sigval ? SNN (signal NN)
+ *
+ * bBB..BB Set baud rate to BB..BB OK or BNN, then sets
+ * baud rate
+ *
+ * All commands and responses are sent with a packet which includes a
+ * checksum. A packet consists of
+ *
+ * $<packet info>#<checksum>.
+ *
+ * where
+ * <packet info> :: <characters representing the command or response>
+ * <checksum> :: <two hex digits computed as modulo 256 sum of <packetinfo>>
+ *
+ * When a packet is received, it is first acknowledged with either '+' or '-'.
+ * '+' indicates a successful transfer. '-' indicates a failed transfer.
+ *
+ * Example:
+ *
+ * Host: Reply:
+ * $m0,10#2a +$00010203040506070809101112131415#42
+ *
+ ****************************************************************************/
+
+#include <string.h>
+#include <signal.h>
+
+/************************************************************************
+ *
+ * external low-level support routines
+ */
+
+extern void putDebugChar(); /* write a single character */
+extern int getDebugChar(); /* read and return a single char */
+
+/************************************************************************/
+/* BUFMAX defines the maximum number of characters in inbound/outbound buffers*/
+/* at least NUMREGBYTES*2 are needed for register packets */
+#define BUFMAX 2048
+
+static int initialized = 0; /* !0 means we've been initialized */
+static int remote_debug = 0; /* turn on verbose debugging */
+
+extern void breakinst();
+void _cprint();
+static void hw_breakpoint();
+static void set_mem_fault_trap();
+static void get_in_break_mode();
+static unsigned char *mem2hex();
+
+static const char hexchars[]="0123456789abcdef";
+
+#define NUMREGS 121
+
+static unsigned long saved_stack_pointer;
+
+/* Number of bytes of registers. */
+#define NUMREGBYTES (NUMREGS * 4)
+enum regnames { G0, G1, G2, G3, G4, G5, G6, G7,
+ O0, O1, O2, O3, O4, O5, SP, O7,
+ L0, L1, L2, L3, L4, L5, L6, L7,
+ I0, I1, I2, I3, I4, I5, FP, I7,
+
+ F0, F1, F2, F3, F4, F5, F6, F7,
+ F8, F9, F10, F11, F12, F13, F14, F15,
+ F16, F17, F18, F19, F20, F21, F22, F23,
+ F24, F25, F26, F27, F28, F29, F30, F31,
+
+ Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR,
+ CCSR, CCPR, CCCRCR, CCOR, CCOBR, CCIBR, CCIR, UNUSED1,
+
+ ASR1, ASR15, ASR17, ASR18, ASR19, ASR20, ASR21, ASR22,
+ /* the following not actually implemented */
+ AWR0, AWR1, AWR2, AWR3, AWR4, AWR5, AWR6, AWR7,
+ AWR8, AWR9, AWR10, AWR11, AWR12, AWR13, AWR14, AWR15,
+ AWR16, AWR17, AWR18, AWR19, AWR20, AWR21, AWR22, AWR23,
+ AWR24, AWR25, AWR26, AWR27, AWR28, AWR29, AWR30, AWR31,
+ APSR
+};
+
+/*************************** ASSEMBLY CODE MACROS *************************/
+/* */
+
+extern void trap_low();
+
+asm("
+ .reserve trapstack, 1000 * 4, \"bss\", 8
+
+ .data
+ .align 4
+
+in_trap_handler:
+ .word 0
+
+ .text
+ .align 4
+
+! This function is called when any SPARC trap (except window overflow or
+! underflow) occurs. It makes sure that the invalid register window is still
+! available before jumping into C code. It will also restore the world if you
+! return from handle_exception.
+!
+! On entry, trap_low expects l1 and l2 to contain pc and npc respectivly.
+
+ .globl _trap_low
+_trap_low:
+ mov %psr, %l0
+ mov %wim, %l3
+
+ srl %l3, %l0, %l4 ! wim >> cwp
+ and %l4, 0xff, %l4 ! Mask off windows 28, 29
+ cmp %l4, 1
+ bne window_fine ! Branch if not in the invalid window
+ nop
+
+! Handle window overflow
+
+ mov %g1, %l4 ! Save g1, we use it to hold the wim
+ srl %l3, 1, %g1 ! Rotate wim right
+ and %g1, 0xff, %g1 ! Mask off windows 28, 29
+ tst %g1
+ bg good_wim ! Branch if new wim is non-zero
+ nop
+
+! At this point, we need to bring a 1 into the high order bit of the wim.
+! Since we don't want to make any assumptions about the number of register
+! windows, we figure it out dynamically so as to setup the wim correctly.
+
+ ! The normal way doesn't work on the sparclet as register windows
+ ! 28 and 29 are special purpose windows.
+ !not %g1 ! Fill g1 with ones
+ !mov %g1, %wim ! Fill the wim with ones
+ !nop
+ !nop
+ !nop
+ !mov %wim, %g1 ! Read back the wim
+ !inc %g1 ! Now g1 has 1 just to left of wim
+ !srl %g1, 1, %g1 ! Now put 1 at top of wim
+
+ mov 0x80, %g1 ! Hack for sparclet
+
+ ! This doesn't work on the sparclet.
+ !mov %g0, %wim ! Clear wim so that subsequent save
+ ! won't trap
+ andn %l3, 0xff, %l5 ! Clear wim but not windows 28, 29
+ mov %l5, %wim
+ nop
+ nop
+ nop
+
+good_wim:
+ save %g0, %g0, %g0 ! Slip into next window
+ mov %g1, %wim ! Install the new wim
+
+ std %l0, [%sp + 0 * 4] ! save L & I registers
+ std %l2, [%sp + 2 * 4]
+ std %l4, [%sp + 4 * 4]
+ std %l6, [%sp + 6 * 4]
+
+ std %i0, [%sp + 8 * 4]
+ std %i2, [%sp + 10 * 4]
+ std %i4, [%sp + 12 * 4]
+ std %i6, [%sp + 14 * 4]
+
+ restore ! Go back to trap window.
+ mov %l4, %g1 ! Restore %g1
+
+window_fine:
+ sethi %hi(in_trap_handler), %l4
+ ld [%lo(in_trap_handler) + %l4], %l5
+ tst %l5
+ bg recursive_trap
+ inc %l5
+
+ set trapstack+1000*4, %sp ! Switch to trap stack
+
+recursive_trap:
+ st %l5, [%lo(in_trap_handler) + %l4]
+ sub %sp,(16+1+6+1+88)*4,%sp ! Make room for input & locals
+ ! + hidden arg + arg spill
+ ! + doubleword alignment
+ ! + registers[121]
+
+ std %g0, [%sp + (24 + 0) * 4] ! registers[Gx]
+ std %g2, [%sp + (24 + 2) * 4]
+ std %g4, [%sp + (24 + 4) * 4]
+ std %g6, [%sp + (24 + 6) * 4]
+
+ std %i0, [%sp + (24 + 8) * 4] ! registers[Ox]
+ std %i2, [%sp + (24 + 10) * 4]
+ std %i4, [%sp + (24 + 12) * 4]
+ std %i6, [%sp + (24 + 14) * 4]
+
+ ! FP regs (sparclet doesn't have fpu)
+
+ mov %y, %l4
+ mov %tbr, %l5
+ st %l4, [%sp + (24 + 64) * 4] ! Y
+ st %l0, [%sp + (24 + 65) * 4] ! PSR
+ st %l3, [%sp + (24 + 66) * 4] ! WIM
+ st %l5, [%sp + (24 + 67) * 4] ! TBR
+ st %l1, [%sp + (24 + 68) * 4] ! PC
+ st %l2, [%sp + (24 + 69) * 4] ! NPC
+ ! CPSR and FPSR not impl
+ or %l0, 0xf20, %l4
+ mov %l4, %psr ! Turn on traps, disable interrupts
+ nop
+ nop
+ nop
+
+! Save coprocessor state.
+! See SK/demo/hdlc_demo/ldc_swap_context.S.
+
+ mov %psr, %l0
+ sethi %hi(0x2000), %l5 ! EC bit in PSR
+ or %l5, %l0, %l5
+ mov %l5, %psr ! enable coprocessor
+ nop ! 3 nops after write to %psr (needed?)
+ nop
+ nop
+ crdcxt %ccsr, %l1 ! capture CCSR
+ mov 0x6, %l2
+ cwrcxt %l2, %ccsr ! set CCP state machine for CCFR
+ crdcxt %ccfr, %l2 ! capture CCOR
+ cwrcxt %l2, %ccfr ! tickle CCFR
+ crdcxt %ccfr, %l3 ! capture CCOBR
+ cwrcxt %l3, %ccfr ! tickle CCFR
+ crdcxt %ccfr, %l4 ! capture CCIBR
+ cwrcxt %l4, %ccfr ! tickle CCFR
+ crdcxt %ccfr, %l5 ! capture CCIR
+ cwrcxt %l5, %ccfr ! tickle CCFR
+ crdcxt %ccpr, %l6 ! capture CCPR
+ crdcxt %cccrcr, %l7 ! capture CCCRCR
+ st %l1, [%sp + (24 + 72) * 4] ! save CCSR
+ st %l2, [%sp + (24 + 75) * 4] ! save CCOR
+ st %l3, [%sp + (24 + 76) * 4] ! save CCOBR
+ st %l4, [%sp + (24 + 77) * 4] ! save CCIBR
+ st %l5, [%sp + (24 + 78) * 4] ! save CCIR
+ st %l6, [%sp + (24 + 73) * 4] ! save CCPR
+ st %l7, [%sp + (24 + 74) * 4] ! save CCCRCR
+ mov %l0, %psr ! restore original PSR
+ nop ! 3 nops after write to %psr (needed?)
+ nop
+ nop
+
+! End of saving coprocessor state.
+! Save asr regs
+
+! Part of this is silly -- we should not display ASR15 or ASR19 at all.
+
+ sethi %hi(0x01000000), %l6
+ st %l6, [%sp + (24 + 81) * 4] ! ASR15 == NOP
+ sethi %hi(0xdeadc0de), %l6
+ or %l6, %lo(0xdeadc0de), %l6
+ st %l6, [%sp + (24 + 84) * 4] ! ASR19 == DEADC0DE
+
+ rd %asr1, %l4
+ st %l4, [%sp + (24 + 80) * 4]
+! rd %asr15, %l4 ! must not read ASR15
+! st %l4, [%sp + (24 + 81) * 4] ! (illegal instr trap)
+ rd %asr17, %l4
+ st %l4, [%sp + (24 + 82) * 4]
+ rd %asr18, %l4
+ st %l4, [%sp + (24 + 83) * 4]
+! rd %asr19, %l4 ! must not read asr19
+! st %l4, [%sp + (24 + 84) * 4] ! (halts the CPU)
+ rd %asr20, %l4
+ st %l4, [%sp + (24 + 85) * 4]
+ rd %asr21, %l4
+ st %l4, [%sp + (24 + 86) * 4]
+ rd %asr22, %l4
+ st %l4, [%sp + (24 + 87) * 4]
+
+! End of saving asr regs
+
+ call _handle_exception
+ add %sp, 24 * 4, %o0 ! Pass address of registers
+
+! Reload all of the registers that aren't on the stack
+
+ ld [%sp + (24 + 1) * 4], %g1 ! registers[Gx]
+ ldd [%sp + (24 + 2) * 4], %g2
+ ldd [%sp + (24 + 4) * 4], %g4
+ ldd [%sp + (24 + 6) * 4], %g6
+
+ ldd [%sp + (24 + 8) * 4], %i0 ! registers[Ox]
+ ldd [%sp + (24 + 10) * 4], %i2
+ ldd [%sp + (24 + 12) * 4], %i4
+ ldd [%sp + (24 + 14) * 4], %i6
+
+ ! FP regs (sparclet doesn't have fpu)
+
+! Update the coprocessor registers.
+! See SK/demo/hdlc_demo/ldc_swap_context.S.
+
+ mov %psr, %l0
+ sethi %hi(0x2000), %l5 ! EC bit in PSR
+ or %l5, %l0, %l5
+ mov %l5, %psr ! enable coprocessor
+ nop ! 3 nops after write to %psr (needed?)
+ nop
+ nop
+
+ mov 0x6, %l2
+ cwrcxt %l2, %ccsr ! set CCP state machine for CCFR
+
+ ld [%sp + (24 + 72) * 4], %l1 ! saved CCSR
+ ld [%sp + (24 + 75) * 4], %l2 ! saved CCOR
+ ld [%sp + (24 + 76) * 4], %l3 ! saved CCOBR
+ ld [%sp + (24 + 77) * 4], %l4 ! saved CCIBR
+ ld [%sp + (24 + 78) * 4], %l5 ! saved CCIR
+ ld [%sp + (24 + 73) * 4], %l6 ! saved CCPR
+ ld [%sp + (24 + 74) * 4], %l7 ! saved CCCRCR
+
+ cwrcxt %l2, %ccfr ! restore CCOR
+ cwrcxt %l3, %ccfr ! restore CCOBR
+ cwrcxt %l4, %ccfr ! restore CCIBR
+ cwrcxt %l5, %ccfr ! restore CCIR
+ cwrcxt %l6, %ccpr ! restore CCPR
+ cwrcxt %l7, %cccrcr ! restore CCCRCR
+ cwrcxt %l1, %ccsr ! restore CCSR
+
+ mov %l0, %psr ! restore PSR
+ nop ! 3 nops after write to %psr (needed?)
+ nop
+ nop
+
+! End of coprocessor handling stuff.
+! Update asr regs
+
+ ld [%sp + (24 + 80) * 4], %l4
+ wr %l4, %asr1
+! ld [%sp + (24 + 81) * 4], %l4 ! can't write asr15
+! wr %l4, %asr15
+ ld [%sp + (24 + 82) * 4], %l4
+ wr %l4, %asr17
+ ld [%sp + (24 + 83) * 4], %l4
+ wr %l4, %asr18
+! ld [%sp + (24 + 84) * 4], %l4 ! can't write asr19
+! wr %l4, %asr19
+! ld [%sp + (24 + 85) * 4], %l4 ! can't write asr20
+! wr %l4, %asr20
+! ld [%sp + (24 + 86) * 4], %l4 ! can't write asr21
+! wr %l4, %asr21
+ ld [%sp + (24 + 87) * 4], %l4
+ wr %l4, %asr22
+
+! End of restoring asr regs
+
+
+ ldd [%sp + (24 + 64) * 4], %l0 ! Y & PSR
+ ldd [%sp + (24 + 68) * 4], %l2 ! PC & NPC
+
+ restore ! Ensure that previous window is valid
+ save %g0, %g0, %g0 ! by causing a window_underflow trap
+
+ mov %l0, %y
+ mov %l1, %psr ! Make sure that traps are disabled
+ ! for rett
+ nop ! 3 nops after write to %psr (needed?)
+ nop
+ nop
+
+ sethi %hi(in_trap_handler), %l4
+ ld [%lo(in_trap_handler) + %l4], %l5
+ dec %l5
+ st %l5, [%lo(in_trap_handler) + %l4]
+
+ jmpl %l2, %g0 ! Restore old PC
+ rett %l3 ! Restore old nPC
+");
+
+/* Convert ch from a hex digit to an int */
+
+static int
+hex(ch)
+ unsigned char ch;
+{
+ if (ch >= 'a' && ch <= 'f')
+ return ch-'a'+10;
+ if (ch >= '0' && ch <= '9')
+ return ch-'0';
+ if (ch >= 'A' && ch <= 'F')
+ return ch-'A'+10;
+ return -1;
+}
+
+/* scan for the sequence $<data>#<checksum> */
+
+static void
+getpacket(buffer)
+ char *buffer;
+{
+ unsigned char checksum;
+ unsigned char xmitcsum;
+ int i;
+ int count;
+ unsigned char ch;
+
+ do
+ {
+ /* wait around for the start character, ignore all other characters */
+ while ((ch = (getDebugChar() & 0x7f)) != '$')
+ ;
+
+ checksum = 0;
+ xmitcsum = -1;
+
+ count = 0;
+
+ /* now, read until a # or end of buffer is found */
+ while (count < BUFMAX)
+ {
+ ch = getDebugChar() & 0x7f;
+ if (ch == '#')
+ break;
+ checksum = checksum + ch;
+ buffer[count] = ch;
+ count = count + 1;
+ }
+
+ if (count >= BUFMAX)
+ continue;
+
+ buffer[count] = 0;
+
+ if (ch == '#')
+ {
+ xmitcsum = hex(ch = getDebugChar() & 0x7f) << 4;
+ xmitcsum |= hex(ch = getDebugChar() & 0x7f);
+
+ if (checksum != xmitcsum)
+ putDebugChar('-'); /* failed checksum */
+ else
+ {
+ putDebugChar('+'); /* successful transfer */
+ /* if a sequence char is present, reply the sequence ID */
+ if (buffer[2] == ':')
+ {
+ putDebugChar(buffer[0]);
+ putDebugChar(buffer[1]);
+ /* remove sequence chars from buffer */
+ count = strlen(buffer);
+ for (i=3; i <= count; i++)
+ buffer[i-3] = buffer[i];
+ }
+ }
+ }
+ }
+ while (checksum != xmitcsum);
+}
+
+/* send the packet in buffer. */
+
+static void
+putpacket(buffer)
+ unsigned char *buffer;
+{
+ unsigned char checksum;
+ int count;
+ unsigned char ch;
+
+ /* $<packet info>#<checksum>. */
+ do
+ {
+ putDebugChar('$');
+ checksum = 0;
+ count = 0;
+
+ while (ch = buffer[count])
+ {
+ putDebugChar(ch);
+ checksum += ch;
+ count += 1;
+ }
+
+ putDebugChar('#');
+ putDebugChar(hexchars[checksum >> 4]);
+ putDebugChar(hexchars[checksum & 0xf]);
+
+ }
+ while ((getDebugChar() & 0x7f) != '+');
+}
+
+static char remcomInBuffer[BUFMAX];
+static char remcomOutBuffer[BUFMAX];
+
+/* Indicate to caller of mem2hex or hex2mem that there has been an
+ error. */
+static volatile int mem_err = 0;
+
+/* Convert the memory pointed to by mem into hex, placing result in buf.
+ * Return a pointer to the last char put in buf (null), in case of mem fault,
+ * return 0.
+ * If MAY_FAULT is non-zero, then we will handle memory faults by returning
+ * a 0, else treat a fault like any other fault in the stub.
+ */
+
+static unsigned char *
+mem2hex(mem, buf, count, may_fault)
+ unsigned char *mem;
+ unsigned char *buf;
+ int count;
+ int may_fault;
+{
+ unsigned char ch;
+
+ set_mem_fault_trap(may_fault);
+
+ while (count-- > 0)
+ {
+ ch = *mem++;
+ if (mem_err)
+ return 0;
+ *buf++ = hexchars[ch >> 4];
+ *buf++ = hexchars[ch & 0xf];
+ }
+
+ *buf = 0;
+
+ set_mem_fault_trap(0);
+
+ return buf;
+}
+
+/* convert the hex array pointed to by buf into binary to be placed in mem
+ * return a pointer to the character AFTER the last byte written */
+
+static char *
+hex2mem(buf, mem, count, may_fault)
+ unsigned char *buf;
+ unsigned char *mem;
+ int count;
+ int may_fault;
+{
+ int i;
+ unsigned char ch;
+
+ set_mem_fault_trap(may_fault);
+
+ for (i=0; i<count; i++)
+ {
+ ch = hex(*buf++) << 4;
+ ch |= hex(*buf++);
+ *mem++ = ch;
+ if (mem_err)
+ return 0;
+ }
+
+ set_mem_fault_trap(0);
+
+ return mem;
+}
+
+/* This table contains the mapping between SPARC hardware trap types, and
+ signals, which are primarily what GDB understands. It also indicates
+ which hardware traps we need to commandeer when initializing the stub. */
+
+static struct hard_trap_info
+{
+ unsigned char tt; /* Trap type code for SPARClite */
+ unsigned char signo; /* Signal that we map this trap into */
+} hard_trap_info[] = {
+ {1, SIGSEGV}, /* instruction access exception */
+ {0x3b, SIGSEGV}, /* instruction access error */
+ {2, SIGILL}, /* illegal instruction */
+ {3, SIGILL}, /* privileged instruction */
+ {4, SIGEMT}, /* fp disabled */
+ {0x24, SIGEMT}, /* cp disabled */
+ {7, SIGBUS}, /* mem address not aligned */
+ {0x29, SIGSEGV}, /* data access exception */
+ {10, SIGEMT}, /* tag overflow */
+ {128+1, SIGTRAP}, /* ta 1 - normal breakpoint instruction */
+ {0, 0} /* Must be last */
+};
+
+/* Set up exception handlers for tracing and breakpoints */
+
+void
+set_debug_traps()
+{
+ struct hard_trap_info *ht;
+
+ for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
+ exceptionHandler(ht->tt, trap_low);
+
+ /* In case GDB is started before us, ack any packets (presumably
+ "$?#xx") sitting there. */
+ putDebugChar ('+');
+
+ initialized = 1;
+}
+
+asm ("
+! Trap handler for memory errors. This just sets mem_err to be non-zero. It
+! assumes that %l1 is non-zero. This should be safe, as it is doubtful that
+! 0 would ever contain code that could mem fault. This routine will skip
+! past the faulting instruction after setting mem_err.
+
+ .text
+ .align 4
+
+_fltr_set_mem_err:
+ sethi %hi(_mem_err), %l0
+ st %l1, [%l0 + %lo(_mem_err)]
+ jmpl %l2, %g0
+ rett %l2+4
+");
+
+static void
+set_mem_fault_trap(enable)
+ int enable;
+{
+ extern void fltr_set_mem_err();
+ mem_err = 0;
+
+ if (enable)
+ exceptionHandler(0x29, fltr_set_mem_err);
+ else
+ exceptionHandler(0x29, trap_low);
+}
+
+asm ("
+ .text
+ .align 4
+
+_dummy_hw_breakpoint:
+ jmpl %l2, %g0
+ rett %l2+4
+ nop
+ nop
+");
+
+static void
+set_hw_breakpoint_trap(enable)
+ int enable;
+{
+ extern void dummy_hw_breakpoint();
+
+ if (enable)
+ exceptionHandler(255, dummy_hw_breakpoint);
+ else
+ exceptionHandler(255, trap_low);
+}
+
+static void
+get_in_break_mode()
+{
+#if 0
+ int x;
+ mesg("get_in_break_mode, sp = ");
+ phex(&x);
+#endif
+ set_hw_breakpoint_trap(1);
+
+ asm("
+ sethi %hi(0xff10), %l4
+ or %l4, %lo(0xff10), %l4
+ sta %g0, [%l4]0x1
+ nop
+ nop
+ nop
+ ");
+
+ set_hw_breakpoint_trap(0);
+}
+
+/* Convert the SPARC hardware trap type code to a unix signal number. */
+
+static int
+computeSignal(tt)
+ int tt;
+{
+ struct hard_trap_info *ht;
+
+ for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
+ if (ht->tt == tt)
+ return ht->signo;
+
+ return SIGHUP; /* default for things we don't know about */
+}
+
+/*
+ * While we find nice hex chars, build an int.
+ * Return number of chars processed.
+ */
+
+static int
+hexToInt(char **ptr, int *intValue)
+{
+ int numChars = 0;
+ int hexValue;
+
+ *intValue = 0;
+
+ while (**ptr)
+ {
+ hexValue = hex(**ptr);
+ if (hexValue < 0)
+ break;
+
+ *intValue = (*intValue << 4) | hexValue;
+ numChars ++;
+
+ (*ptr)++;
+ }
+
+ return (numChars);
+}
+
+/*
+ * This function does all command procesing for interfacing to gdb. It
+ * returns 1 if you should skip the instruction at the trap address, 0
+ * otherwise.
+ */
+
+static void
+handle_exception (registers)
+ unsigned long *registers;
+{
+ int tt; /* Trap type */
+ int sigval;
+ int addr;
+ int length;
+ char *ptr;
+ unsigned long *sp;
+ unsigned long dsr;
+
+/* First, we must force all of the windows to be spilled out */
+
+ asm("
+ ! Ugh. sparclet has broken save
+ !save %sp, -64, %sp
+ save
+ add %fp,-64,%sp
+ !save %sp, -64, %sp
+ save
+ add %fp,-64,%sp
+ !save %sp, -64, %sp
+ save
+ add %fp,-64,%sp
+ !save %sp, -64, %sp
+ save
+ add %fp,-64,%sp
+ !save %sp, -64, %sp
+ save
+ add %fp,-64,%sp
+ !save %sp, -64, %sp
+ save
+ add %fp,-64,%sp
+ !save %sp, -64, %sp
+ save
+ add %fp,-64,%sp
+ !save %sp, -64, %sp
+ save
+ add %fp,-64,%sp
+ restore
+ restore
+ restore
+ restore
+ restore
+ restore
+ restore
+ restore
+");
+
+ if (registers[PC] == (unsigned long)breakinst)
+ {
+ registers[PC] = registers[NPC];
+ registers[NPC] += 4;
+ }
+ sp = (unsigned long *)registers[SP];
+
+ tt = (registers[TBR] >> 4) & 0xff;
+
+ /* reply to host that an exception has occurred */
+ sigval = computeSignal(tt);
+ ptr = remcomOutBuffer;
+
+ *ptr++ = 'T';
+ *ptr++ = hexchars[sigval >> 4];
+ *ptr++ = hexchars[sigval & 0xf];
+
+ *ptr++ = hexchars[PC >> 4];
+ *ptr++ = hexchars[PC & 0xf];
+ *ptr++ = ':';
+ ptr = mem2hex((char *)&registers[PC], ptr, 4, 0);
+ *ptr++ = ';';
+
+ *ptr++ = hexchars[FP >> 4];
+ *ptr++ = hexchars[FP & 0xf];
+ *ptr++ = ':';
+ ptr = mem2hex(sp + 8 + 6, ptr, 4, 0); /* FP */
+ *ptr++ = ';';
+
+ *ptr++ = hexchars[SP >> 4];
+ *ptr++ = hexchars[SP & 0xf];
+ *ptr++ = ':';
+ ptr = mem2hex((char *)&sp, ptr, 4, 0);
+ *ptr++ = ';';
+
+ *ptr++ = hexchars[NPC >> 4];
+ *ptr++ = hexchars[NPC & 0xf];
+ *ptr++ = ':';
+ ptr = mem2hex((char *)&registers[NPC], ptr, 4, 0);
+ *ptr++ = ';';
+
+ *ptr++ = hexchars[O7 >> 4];
+ *ptr++ = hexchars[O7 & 0xf];
+ *ptr++ = ':';
+ ptr = mem2hex((char *)&registers[O7], ptr, 4, 0);
+ *ptr++ = ';';
+
+ *ptr++ = 0;
+
+ putpacket(remcomOutBuffer);
+
+ while (1)
+ {
+ remcomOutBuffer[0] = 0;
+
+ getpacket(remcomInBuffer);
+ switch (remcomInBuffer[0])
+ {
+ case '?':
+ remcomOutBuffer[0] = 'S';
+ remcomOutBuffer[1] = hexchars[sigval >> 4];
+ remcomOutBuffer[2] = hexchars[sigval & 0xf];
+ remcomOutBuffer[3] = 0;
+ break;
+
+ case 'd':
+ remote_debug = !(remote_debug); /* toggle debug flag */
+ break;
+
+ case 'g': /* return the value of the CPU registers */
+ {
+ ptr = remcomOutBuffer;
+ ptr = mem2hex((char *)registers, ptr, 16 * 4, 0); /* G & O regs */
+ ptr = mem2hex(sp + 0, ptr, 16 * 4, 0); /* L & I regs */
+ memset(ptr, '0', 32 * 8); /* Floating point */
+ ptr = mem2hex((char *)&registers[Y],
+ ptr + 32 * 4 * 2,
+ 8 * 4,
+ 0); /* Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR */
+ ptr = mem2hex((char *)&registers[CCSR],
+ ptr,
+ 8 * 4,
+ 0); /* CCSR, CCPR, CCCRCR, CCOR, CCOBR, CCIBR, CCIR */
+ ptr = mem2hex((char *)&registers[ASR1],
+ ptr,
+ 8 * 4,
+ 0); /* ASR1,ASR15,ASR17,ASR18,ASR19,ASR20,ASR21,ASR22 */
+#if 0 /* not implemented */
+ ptr = mem2hex((char *) &registers[AWR0],
+ ptr,
+ 32 * 4,
+ 0); /* Alternate Window Registers */
+#endif
+ }
+ break;
+
+ case 'G': /* set value of all the CPU registers - return OK */
+ case 'P': /* set value of one CPU register - return OK */
+ {
+ unsigned long *newsp, psr;
+
+ psr = registers[PSR];
+
+ ptr = &remcomInBuffer[1];
+
+ if (remcomInBuffer[0] == 'P') /* do a single register */
+ {
+ int regno;
+
+ if (hexToInt (&ptr, &regno)
+ && *ptr++ == '=')
+ if (regno >= L0 && regno <= I7)
+ hex2mem (ptr, sp + regno - L0, 4, 0);
+ else
+ hex2mem (ptr, (char *)&registers[regno], 4, 0);
+ else
+ {
+ strcpy (remcomOutBuffer, "P01");
+ break;
+ }
+ }
+ else
+ {
+ hex2mem(ptr, (char *)registers, 16 * 4, 0); /* G & O regs */
+ hex2mem(ptr + 16 * 4 * 2, sp + 0, 16 * 4, 0); /* L & I regs */
+ hex2mem(ptr + 64 * 4 * 2, (char *)&registers[Y],
+ 8 * 4, 0); /* Y,PSR,WIM,TBR,PC,NPC,FPSR,CPSR */
+ hex2mem(ptr + 72 * 4 * 2, (char *)&registers[CCSR],
+ 8 * 4, 0); /* CCSR,CCPR,CCCRCR,CCOR,CCOBR,CCIBR,CCIR */
+ hex2mem(ptr + 80 * 4 * 2, (char *)&registers[ASR1],
+ 8 * 4, 0); /* ASR1 ... ASR22 */
+#if 0 /* not implemented */
+ hex2mem(ptr + 88 * 4 * 2, (char *)&registers[AWR0],
+ 8 * 4, 0); /* Alternate Window Registers */
+#endif
+ }
+ /* See if the stack pointer has moved. If so, then copy the saved
+ locals and ins to the new location. This keeps the window
+ overflow and underflow routines happy. */
+
+ newsp = (unsigned long *)registers[SP];
+ if (sp != newsp)
+ sp = memcpy(newsp, sp, 16 * 4);
+
+ /* Don't allow CWP to be modified. */
+
+ if (psr != registers[PSR])
+ registers[PSR] = (psr & 0x1f) | (registers[PSR] & ~0x1f);
+
+ strcpy(remcomOutBuffer,"OK");
+ }
+ break;
+
+ case 'm': /* mAA..AA,LLLL Read LLLL bytes at address AA..AA */
+ /* Try to read %x,%x. */
+
+ ptr = &remcomInBuffer[1];
+
+ if (hexToInt(&ptr, &addr)
+ && *ptr++ == ','
+ && hexToInt(&ptr, &length))
+ {
+ if (mem2hex((char *)addr, remcomOutBuffer, length, 1))
+ break;
+
+ strcpy (remcomOutBuffer, "E03");
+ }
+ else
+ strcpy(remcomOutBuffer,"E01");
+ break;
+
+ case 'M': /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
+ /* Try to read '%x,%x:'. */
+
+ ptr = &remcomInBuffer[1];
+
+ if (hexToInt(&ptr, &addr)
+ && *ptr++ == ','
+ && hexToInt(&ptr, &length)
+ && *ptr++ == ':')
+ {
+ if (hex2mem(ptr, (char *)addr, length, 1))
+ strcpy(remcomOutBuffer, "OK");
+ else
+ strcpy(remcomOutBuffer, "E03");
+ }
+ else
+ strcpy(remcomOutBuffer, "E02");
+ break;
+
+ case 'c': /* cAA..AA Continue at address AA..AA(optional) */
+ /* try to read optional parameter, pc unchanged if no parm */
+
+ ptr = &remcomInBuffer[1];
+ if (hexToInt(&ptr, &addr))
+ {
+ registers[PC] = addr;
+ registers[NPC] = addr + 4;
+ }
+
+/* Need to flush the instruction cache here, as we may have deposited a
+ breakpoint, and the icache probably has no way of knowing that a data ref to
+ some location may have changed something that is in the instruction cache.
+ */
+
+ flush_i_cache();
+ return;
+
+ /* kill the program */
+ case 'k' : /* do nothing */
+ break;
+#if 0
+ case 't': /* Test feature */
+ asm (" std %f30,[%sp]");
+ break;
+#endif
+ case 'r': /* Reset */
+ asm ("call 0
+ nop ");
+ break;
+
+#if 0
+Disabled until we can unscrew this properly
+
+ case 'b': /* bBB... Set baud rate to BB... */
+ {
+ int baudrate;
+ extern void set_timer_3();
+
+ ptr = &remcomInBuffer[1];
+ if (!hexToInt(&ptr, &baudrate))
+ {
+ strcpy(remcomOutBuffer,"B01");
+ break;
+ }
+
+ /* Convert baud rate to uart clock divider */
+ switch (baudrate)
+ {
+ case 38400:
+ baudrate = 16;
+ break;
+ case 19200:
+ baudrate = 33;
+ break;
+ case 9600:
+ baudrate = 65;
+ break;
+ default:
+ strcpy(remcomOutBuffer,"B02");
+ goto x1;
+ }
+
+ putpacket("OK"); /* Ack before changing speed */
+ set_timer_3(baudrate); /* Set it */
+ }
+x1: break;
+#endif
+ } /* switch */
+
+ /* reply to the request */
+ putpacket(remcomOutBuffer);
+ }
+}
+
+/* This function will generate a breakpoint exception. It is used at the
+ beginning of a program to sync up with a debugger and can be used
+ otherwise as a quick means to stop program execution and "break" into
+ the debugger. */
+
+void
+breakpoint()
+{
+ if (!initialized)
+ return;
+
+ asm(" .globl _breakinst
+
+ _breakinst: ta 1
+ ");
+}
+
+static void
+hw_breakpoint()
+{
+ asm("
+ ta 127
+ ");
+}
+
+#if 0 /* experimental and never finished, left here for reference */
+static void
+splet_temp(void)
+{
+ asm(" sub %sp,(16+1+6+1+121)*4,%sp ! Make room for input & locals
+ ! + hidden arg + arg spill
+ ! + doubleword alignment
+ ! + registers[121]
+
+! Leave a trail of breadcrumbs! (save register save area for debugging)
+ mov %sp, %l0
+ add %l0, 24*4, %l0
+ sethi %hi(_debug_registers), %l1
+ st %l0, [%lo(_debug_registers) + %l1]
+
+! Save the Alternate Register Set: (not implemented yet)
+! To save the Alternate Register set, we must:
+! 1) Save the current SP in some global location.
+! 2) Swap the register sets.
+! 3) Save the Alternate SP in the Y register
+! 4) Fetch the SP that we saved in step 1.
+! 5) Use that to save the rest of the regs (not forgetting ASP in Y)
+! 6) Restore the Alternate SP from Y
+! 7) Swap the registers back.
+
+! 1) Copy the current stack pointer to global _SAVED_STACK_POINTER:
+ sethi %hi(_saved_stack_pointer), %l0
+ st %sp, [%lo(_saved_stack_pointer) + %l0]
+
+! 2) Swap the register sets:
+ mov %psr, %l1
+ sethi %hi(0x10000), %l2
+ xor %l1, %l2, %l1
+ mov %l1, %psr
+ nop ! 3 nops after write to %psr (needed?)
+ nop
+ nop
+
+! 3) Save Alternate L0 in Y
+ wr %l0, 0, %y
+
+! 4) Load former SP into alternate SP, using L0
+ sethi %hi(_saved_stack_pointer), %l0
+ or %lo(_saved_stack_pointer), %l0, %l0
+ swap [%l0], %sp
+
+! 4.5) Restore alternate L0
+ rd %y, %l0
+
+! 5) Save the Alternate Window Registers
+ st %r0, [%sp + (24 + 88) * 4] ! AWR0
+ st %r1, [%sp + (24 + 89) * 4] ! AWR1
+ st %r2, [%sp + (24 + 90) * 4] ! AWR2
+ st %r3, [%sp + (24 + 91) * 4] ! AWR3
+ st %r4, [%sp + (24 + 92) * 4] ! AWR4
+ st %r5, [%sp + (24 + 93) * 4] ! AWR5
+ st %r6, [%sp + (24 + 94) * 4] ! AWR6
+ st %r7, [%sp + (24 + 95) * 4] ! AWR7
+ st %r8, [%sp + (24 + 96) * 4] ! AWR8
+ st %r9, [%sp + (24 + 97) * 4] ! AWR9
+ st %r10, [%sp + (24 + 98) * 4] ! AWR10
+ st %r11, [%sp + (24 + 99) * 4] ! AWR11
+ st %r12, [%sp + (24 + 100) * 4] ! AWR12
+ st %r13, [%sp + (24 + 101) * 4] ! AWR13
+! st %r14, [%sp + (24 + 102) * 4] ! AWR14 (SP)
+ st %r15, [%sp + (24 + 103) * 4] ! AWR15
+ st %r16, [%sp + (24 + 104) * 4] ! AWR16
+ st %r17, [%sp + (24 + 105) * 4] ! AWR17
+ st %r18, [%sp + (24 + 106) * 4] ! AWR18
+ st %r19, [%sp + (24 + 107) * 4] ! AWR19
+ st %r20, [%sp + (24 + 108) * 4] ! AWR20
+ st %r21, [%sp + (24 + 109) * 4] ! AWR21
+ st %r22, [%sp + (24 + 110) * 4] ! AWR22
+ st %r23, [%sp + (24 + 111) * 4] ! AWR23
+ st %r24, [%sp + (24 + 112) * 4] ! AWR24
+ st %r25, [%sp + (24 + 113) * 4] ! AWR25
+ st %r26, [%sp + (24 + 114) * 4] ! AWR26
+ st %r27, [%sp + (24 + 115) * 4] ! AWR27
+ st %r28, [%sp + (24 + 116) * 4] ! AWR28
+ st %r29, [%sp + (24 + 117) * 4] ! AWR29
+ st %r30, [%sp + (24 + 118) * 4] ! AWR30
+ st %r31, [%sp + (24 + 119) * 4] ! AWR21
+
+! Get the Alternate PSR (I hope...)
+
+ rd %psr, %l2
+ st %l2, [%sp + (24 + 120) * 4] ! APSR
+
+! Don't forget the alternate stack pointer
+
+ rd %y, %l3
+ st %l3, [%sp + (24 + 102) * 4] ! AWR14 (SP)
+
+! 6) Restore the Alternate SP (saved in Y)
+
+ rd %y, %o6
+
+
+! 7) Swap the registers back:
+
+ mov %psr, %l1
+ sethi %hi(0x10000), %l2
+ xor %l1, %l2, %l1
+ mov %l1, %psr
+ nop ! 3 nops after write to %psr (needed?)
+ nop
+ nop
+");
+}
+
+#endif
diff --git a/gdb/srec.h b/gdb/srec.h
new file mode 100644
index 00000000000..8253e030956
--- /dev/null
+++ b/gdb/srec.h
@@ -0,0 +1,36 @@
+/* S-record download support for GDB, the GNU debugger.
+ Copyright 1995, 1996 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+void load_srec PARAMS ((serial_t desc, const char *file, bfd_vma load_offset,
+ int maxrecsize, int flags, int hashmark,
+ int (*waitack)(void)));
+
+/* S-record capability flags */
+
+/* Which record types are supported */
+#define SREC_2_BYTE_ADDR 0x00000001
+#define SREC_3_BYTE_ADDR 0x00000002
+#define SREC_4_BYTE_ADDR 0x00000004
+#define SREC_TERM_SHIFT 3
+
+#define SREC_ALL (SREC_2_BYTE_ADDR | SREC_3_BYTE_ADDR | SREC_4_BYTE_ADDR \
+ | ((SREC_2_BYTE_ADDR | SREC_3_BYTE_ADDR | SREC_4_BYTE_ADDR) \
+ << SREC_TERM_SHIFT))
+
+#define SREC_BINARY 0x00000040 /* Supports binary form of S-records */
diff --git a/gdb/stabsread.c b/gdb/stabsread.c
new file mode 100644
index 00000000000..c5d31e190af
--- /dev/null
+++ b/gdb/stabsread.c
@@ -0,0 +1,5207 @@
+/* Support routines for decoding "stabs" debugging information format.
+ Copyright 1986, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 1998
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 "gdb_string.h"
+#include "bfd.h"
+#include "obstack.h"
+#include "symtab.h"
+#include "gdbtypes.h"
+#include "expression.h"
+#include "symfile.h"
+#include "objfiles.h"
+#include "aout/stab_gnu.h" /* We always use GNU stabs, not native */
+#include "libaout.h"
+#include "aout/aout64.h"
+#include "gdb-stabs.h"
+#include "buildsym.h"
+#include "complaints.h"
+#include "demangle.h"
+#include "language.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;
+
+ /* This is the raw visibility from the stab. It is not checked
+ for being one of the visibilities we recognize, so code which
+ examines this field better be able to deal. */
+ int visibility;
+
+ struct field field;
+ } *list;
+ struct next_fnfieldlist
+ {
+ struct next_fnfieldlist *next;
+ struct fn_fieldlist fn_fieldlist;
+ } *fnlist;
+};
+
+static void
+read_one_struct_field PARAMS ((struct field_info *, char **, char *,
+ struct type *, struct objfile *));
+
+static char *
+get_substring PARAMS ((char **, int));
+
+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 **, struct objfile *));
+
+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 *));
+
+/* new functions added for cfront support */
+
+static int
+copy_cfront_struct_fields PARAMS ((struct field_info *, struct type *,
+ struct objfile *));
+
+static char *
+get_cfront_method_physname PARAMS ((char *));
+
+static int
+read_cfront_baseclasses PARAMS ((struct field_info *, char **,
+ struct type *, struct objfile *));
+
+static int
+read_cfront_static_fields PARAMS ((struct field_info *, char**,
+ struct type *, struct objfile *));
+static int
+read_cfront_member_functions PARAMS ((struct field_info *, char **,
+ struct type *, struct objfile *));
+
+/* end new functions added for cfront support */
+
+static void
+add_live_range PARAMS ((struct objfile *, struct symbol *,
+ CORE_ADDR, CORE_ADDR));
+
+static int
+resolve_live_range PARAMS ((struct objfile *, struct symbol *, char *));
+
+static int
+process_reference PARAMS ((char **string));
+
+static CORE_ADDR
+ref_search_value PARAMS ((int refnum));
+
+static int
+resolve_symbol_reference PARAMS ((struct objfile *, struct symbol *, char *));
+
+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
+
+static struct complaint invalid_cpp_abbrev_complaint =
+ {"invalid C++ abbreviation `%s'", 0, 0};
+
+static struct complaint invalid_cpp_type_complaint =
+ {"C++ abbreviated type name unknown at symtab pos %d", 0, 0};
+
+static struct complaint member_fn_complaint =
+ {"member function type missing, got '%c'", 0, 0};
+
+static struct complaint const_vol_complaint =
+ {"const/volatile indicator missing, got '%c'", 0, 0};
+
+static struct complaint error_type_complaint =
+ {"debug info mismatch between compiler and debugger", 0, 0};
+
+static struct complaint invalid_member_complaint =
+ {"invalid (minimal) member type data format at symtab pos %d.", 0, 0};
+
+static struct complaint range_type_base_complaint =
+ {"base type %d of range type is not defined", 0, 0};
+
+static struct complaint reg_value_complaint =
+ {"register number %d too large (max %d) in symbol %s", 0, 0};
+
+static struct complaint vtbl_notfound_complaint =
+ {"virtual function table pointer not found when defining class `%s'", 0, 0};
+
+static struct complaint unrecognized_cplus_name_complaint =
+ {"Unknown C++ symbol name `%s'", 0, 0};
+
+static struct complaint rs6000_builtin_complaint =
+ {"Unknown builtin type %d", 0, 0};
+
+static struct complaint unresolved_sym_chain_complaint =
+ {"%s: common block `%s' from global_sym_chain unresolved", 0, 0};
+
+static struct complaint stabs_general_complaint =
+ {"%s", 0, 0};
+
+static struct complaint lrs_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;
+static struct symbol *current_symbol = NULL;
+
+/* Check for and handle cretinous stabs symbol name continuation! */
+#define STABS_CONTINUE(pp,objfile) \
+ do { \
+ if (**(pp) == '\\' || (**(pp) == '?' && (*(pp))[1] == '\0')) \
+ *(pp) = next_symbol_text (objfile); \
+ } while (0)
+
+/* FIXME: These probably should be our own types (like rs6000_builtin_type
+ has its own types) rather than builtin_type_*. */
+static struct type **os9k_type_vector[] = {
+ 0,
+ &builtin_type_int,
+ &builtin_type_char,
+ &builtin_type_long,
+ &builtin_type_short,
+ &builtin_type_unsigned_char,
+ &builtin_type_unsigned_short,
+ &builtin_type_unsigned_long,
+ &builtin_type_unsigned_int,
+ &builtin_type_float,
+ &builtin_type_double,
+ &builtin_type_void,
+ &builtin_type_long_double
+};
+
+static void os9k_init_type_vector PARAMS ((struct type **));
+
+static void
+os9k_init_type_vector(tv)
+ struct type **tv;
+{
+ int i;
+ for (i=0; i<sizeof(os9k_type_vector)/sizeof(struct type **); i++)
+ tv[i] = (os9k_type_vector[i] == 0 ? 0 : *(os9k_type_vector[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. */
+
+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 **)
+ xmalloc (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 *));
+
+ if (os9k_stabs)
+ /* Deal with OS9000 fundamental types. */
+ os9k_init_type_vector (type_vector);
+ }
+ return (&type_vector[index]);
+ }
+ else
+ {
+ real_filenum = this_object_header_files[filenum];
+
+ if (real_filenum >= N_HEADER_FILES (current_objfile))
+ {
+ 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 (current_objfile) + 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, ':');
+ while (pp[1] == ':')
+ {
+ pp += 2;
+ pp = (char *)strchr(pp, ':');
+ }
+ sym = find_symbol_in_list (symbols, name, pp-name);
+ if (!sym)
+ {
+ /* FIXME-maybe: it would be nice if we noticed whether
+ the variable was defined *anywhere*, not just whether
+ it is defined in this compilation unit. But neither
+ xlc or GCC seem to need such a definition, and until
+ we do psymtabs (so that the minimal symbols from all
+ compilation units are available now), I'm not sure
+ how to get the information. */
+
+ /* 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) =
+ obsavestring (name, pp - name, &objfile->symbol_obstack);
+ 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;
+}
+
+
+#if !defined (REG_STRUCT_HAS_ADDR)
+#define REG_STRUCT_HAS_ADDR(gcc_p,type) 0
+#endif
+
+#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 */
+#define VISIBILITY_IGNORE '9' /* Optimized out or zero length */
+
+#define CFRONT_VISIBILITY_PRIVATE '2' /* Stabs character for private field */
+#define CFRONT_VISIBILITY_PUBLIC '1' /* Stabs character for public field */
+
+/* This code added to support parsing of ARM/Cfront stabs strings */
+
+/* Get substring from string up to char c, advance string pointer past
+ suibstring. */
+
+static char *
+get_substring (p, c)
+ char ** p;
+ int c;
+{
+ char *str;
+ str = *p;
+ *p = strchr (*p, c);
+ if (*p)
+ {
+ **p = 0;
+ (*p)++;
+ }
+ else
+ str = 0;
+ return str;
+}
+
+/* Physname gets strcat'd onto sname in order to recreate the mangled
+ name (see funtion gdb_mangle_name in gdbtypes.c). For cfront, make
+ the physname look like that of g++ - take out the initial mangling
+ eg: for sname="a" and fname="foo__1aFPFs_i" return "FPFs_i" */
+
+static char *
+get_cfront_method_physname (fname)
+ char *fname;
+{
+ int len = 0;
+ /* FIXME would like to make this generic for g++ too, but
+ that is already handled in read_member_funcctions */
+ char * p = fname;
+
+ /* search ahead to find the start of the mangled suffix */
+ if (*p == '_' && *(p+1)=='_') /* compiler generated; probably a ctor/dtor */
+ p += 2;
+ while (p && (unsigned) ((p+1) - fname) < strlen (fname) && *(p+1) != '_')
+ p = strchr (p, '_');
+ if (!(p && *p == '_' && *(p+1) == '_'))
+ error ("Invalid mangled function name %s",fname);
+ p += 2; /* advance past '__' */
+
+ /* struct name length and name of type should come next; advance past it */
+ while (isdigit (*p))
+ {
+ len = len * 10 + (*p - '0');
+ p++;
+ }
+ p += len;
+
+ return p;
+}
+
+/* Read base classes within cfront class definition.
+ eg: A:ZcA;1@Bpub v2@Bvirpri;__ct__1AFv func__1AFv *sfunc__1AFv ;as__1A ;;
+ ^^^^^^^^^^^^^^^^^^
+
+ A:ZcA;;foopri__1AFv foopro__1AFv __ct__1AFv __ct__1AFRC1A foopub__1AFv ;;;
+ ^
+ */
+
+static int
+read_cfront_baseclasses (fip, pp, type, objfile)
+ struct field_info *fip;
+ struct objfile *objfile;
+ char ** pp;
+ struct type *type;
+{
+ static struct complaint msg_unknown = {"\
+ Unsupported token in stabs string %s.\n",
+ 0, 0};
+ static struct complaint msg_notfound = {"\
+ Unable to find base type for %s.\n",
+ 0, 0};
+ int bnum = 0;
+ char * p;
+ int i;
+ struct nextfield *new;
+
+ if (**pp == ';') /* no base classes; return */
+ {
+ ++(*pp);
+ return 1;
+ }
+
+ /* first count base classes so we can allocate space before parsing */
+ for (p = *pp; p && *p && *p != ';'; p++)
+ {
+ if (*p == ' ')
+ bnum++;
+ }
+ bnum++; /* add one more for last one */
+
+ /* now parse the base classes until we get to the start of the methods
+ (code extracted and munged from read_baseclasses) */
+ ALLOCATE_CPLUS_STRUCT_TYPE (type);
+ TYPE_N_BASECLASSES(type) = bnum;
+
+ /* allocate space */
+ {
+ 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;
+ }
+ 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;
+ FIELD_BITSIZE (new->field) = 0; /* this should be an unpacked field! */
+
+ STABS_CONTINUE (pp, objfile);
+
+ /* virtual? eg: v2@Bvir */
+ if (**pp=='v')
+ {
+ SET_TYPE_FIELD_VIRTUAL (type, i);
+ ++(*pp);
+ }
+
+ /* access? eg: 2@Bvir */
+ /* Note: protected inheritance not supported in cfront */
+ switch (*(*pp)++)
+ {
+ case CFRONT_VISIBILITY_PRIVATE:
+ new -> visibility = VISIBILITY_PRIVATE;
+ break;
+ case CFRONT_VISIBILITY_PUBLIC:
+ new -> visibility = VISIBILITY_PUBLIC;
+ break;
+ default:
+ /* Bad visibility format. Complain and treat it as
+ public. */
+ {
+ static struct complaint msg = {
+ "Unknown visibility `%c' for baseclass", 0, 0};
+ complain (&msg, new -> visibility);
+ new -> visibility = VISIBILITY_PUBLIC;
+ }
+ }
+
+ /* "@" comes next - eg: @Bvir */
+ if (**pp!='@')
+ {
+ complain (&msg_unknown, *pp);
+ return 1;
+ }
+ ++(*pp);
+
+
+ /* Set the bit offset of the portion of the object corresponding
+ to this baseclass. Always zero in the absence of
+ multiple inheritance. */
+ /* Unable to read bit position from stabs;
+ Assuming no multiple inheritance for now FIXME! */
+ /* We may have read this in the structure definition;
+ now we should fixup the members to be the actual base classes */
+ FIELD_BITPOS (new->field) = 0;
+
+ /* Get the base class name and type */
+ {
+ char * bname; /* base class name */
+ struct symbol * bsym; /* base class */
+ char * p1, * p2;
+ p1 = strchr (*pp,' ');
+ p2 = strchr (*pp,';');
+ if (p1<p2)
+ bname = get_substring (pp,' ');
+ else
+ bname = get_substring (pp,';');
+ if (!bname || !*bname)
+ {
+ complain (&msg_unknown, *pp);
+ return 1;
+ }
+ /* FIXME! attach base info to type */
+ bsym = lookup_symbol (bname, 0, STRUCT_NAMESPACE, 0, 0); /*demangled_name*/
+ if (bsym)
+ {
+ new -> field.type = SYMBOL_TYPE(bsym);
+ new -> field.name = type_name_no_tag (new -> field.type);
+ }
+ else
+ {
+ complain (&msg_notfound, *pp);
+ return 1;
+ }
+ }
+
+ /* If more base classes to parse, loop again.
+ We ate the last ' ' or ';' in get_substring,
+ so on exit we will have skipped the trailing ';' */
+ /* if invalid, return 0; add code to detect - FIXME! */
+ }
+ return 1;
+}
+
+/* read cfront member functions.
+ pp points to string starting with list of functions
+ eg: A:ZcA;1@Bpub v2@Bvirpri;__ct__1AFv func__1AFv *sfunc__1AFv ;as__1A ;;
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ A:ZcA;;foopri__1AFv foopro__1AFv __ct__1AFv __ct__1AFRC1A foopub__1AFv ;;;
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+*/
+
+static int
+read_cfront_member_functions (fip, pp, type, objfile)
+ struct field_info *fip;
+ char **pp;
+ struct type *type;
+ struct objfile *objfile;
+{
+ /* This code extracted from read_member_functions
+ so as to do the similar thing for our funcs */
+
+ 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;
+ char * fname;
+ struct symbol * ref_func = 0;
+
+ /* Process each list until we find the end of the member functions.
+ eg: p = "__ct__1AFv foo__1AFv ;;;" */
+
+ STABS_CONTINUE (pp, objfile); /* handle \\ */
+
+ while (**pp != ';' && (fname = get_substring (pp, ' '), fname))
+ {
+ int is_static = 0;
+ int sublist_count = 0;
+ char * pname;
+ if (fname[0] == '*') /* static member */
+ {
+ is_static=1;
+ sublist_count++;
+ fname++;
+ }
+ ref_func = lookup_symbol (fname, 0, VAR_NAMESPACE, 0, 0); /* demangled name */
+ if (!ref_func)
+ {
+ static struct complaint msg = {"\
+ Unable to find function symbol for %s\n",
+ 0, 0};
+ complain (&msg, fname);
+ continue;
+ }
+ 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));
+
+ /* The following is code to work around cfront generated stabs.
+ The stabs contains full mangled name for each field.
+ We try to demangle the name and extract the field name out of it. */
+ {
+ char *dem, *dem_p, *dem_args;
+ int dem_len;
+ dem = cplus_demangle (fname, DMGL_ANSI | DMGL_PARAMS);
+ if (dem != NULL)
+ {
+ dem_p = strrchr (dem, ':');
+ if (dem_p != 0 && *(dem_p-1) == ':')
+ dem_p++;
+ /* get rid of args */
+ dem_args = strchr (dem_p, '(');
+ if (dem_args == NULL)
+ dem_len = strlen (dem_p);
+ else
+ dem_len = dem_args - dem_p;
+ main_fn_name =
+ obsavestring (dem_p, dem_len, &objfile -> type_obstack);
+ }
+ else
+ {
+ main_fn_name =
+ obsavestring (fname, strlen (fname), &objfile -> type_obstack);
+ }
+ } /* end of code for cfront work around */
+
+ new_fnlist -> fn_fieldlist.name = main_fn_name;
+
+ /*-------------------------------------------------*/
+ /* Set up the sublists
+ Sublists are stuff like args, static, visibility, etc.
+ so in ARM, we have to set that info some other way.
+ Multiple sublists happen if overloading
+ eg: foo::26=##1;:;2A.;
+ In g++, we'd loop here thru all the sublists... */
+
+ new_sublist =
+ (struct next_fnfield *) xmalloc (sizeof (struct next_fnfield));
+ make_cleanup (free, new_sublist);
+ memset (new_sublist, 0, sizeof (struct next_fnfield));
+
+ /* eat 1; from :;2A.; */
+ new_sublist -> fn_field.type = SYMBOL_TYPE(ref_func); /* normally takes a read_type */
+ /* Make this type look like a method stub for gdb */
+ TYPE_FLAGS (new_sublist -> fn_field.type) |= TYPE_FLAG_STUB;
+ TYPE_CODE (new_sublist -> fn_field.type) = TYPE_CODE_METHOD;
+
+ /* 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;
+ }
+
+ /* physname used later in mangling; eg PFs_i,5 for foo__1aFPFs_i
+ physname gets strcat'd in order to recreate the onto mangled name */
+ pname = get_cfront_method_physname (fname);
+ new_sublist -> fn_field.physname = savestring (pname, strlen (pname));
+
+
+ /* Set this member function's visibility fields.
+ Unable to distinguish access from stabs definition!
+ Assuming public for now. FIXME!
+ (for private, set new_sublist->fn_field.is_private = 1,
+ for public, set new_sublist->fn_field.is_protected = 1) */
+
+ /* Unable to distinguish const/volatile from stabs definition!
+ Assuming normal for now. FIXME! */
+
+ new_sublist -> fn_field.is_const = 0;
+ new_sublist -> fn_field.is_volatile = 0; /* volatile not implemented in cfront */
+
+ /* Set virtual/static function info
+ How to get vtable offsets ?
+ Assuming normal for now FIXME!!
+ For vtables, figure out from whence this virtual function came.
+ It may belong to virtual function table of
+ one of its baseclasses.
+ set:
+ new_sublist -> fn_field.voffset = vtable offset,
+ new_sublist -> fn_field.fcontext = look_ahead_type;
+ where look_ahead_type is type of baseclass */
+ if (is_static)
+ new_sublist -> fn_field.voffset = VOFFSET_STATIC;
+ else /* normal member function. */
+ new_sublist -> fn_field.voffset = 0;
+ new_sublist -> fn_field.fcontext = 0;
+
+
+ /* Prepare new sublist */
+ new_sublist -> next = sublist;
+ sublist = new_sublist;
+ length++;
+
+ /* In g++, we loop thu sublists - now we set from functions. */
+ 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, objfile); /* handle \\ */
+ } /* end of loop */
+
+ if (nfn_fields)
+ {
+ /* type should already have space */
+ 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;
+ }
+
+ /* end of scope for reading member func */
+
+ /* eg: ";;" */
+
+ /* Skip trailing ';' and bump count of number of fields seen */
+ if (**pp == ';')
+ (*pp)++;
+ else
+ return 0;
+ return 1;
+}
+
+/* This routine fixes up partial cfront types that were created
+ while parsing the stabs. The main need for this function is
+ to add information such as methods to classes.
+ Examples of "p": "sA;;__ct__1AFv foo__1AFv ;;;" */
+int
+resolve_cfront_continuation (objfile, sym, p)
+ struct objfile * objfile;
+ struct symbol * sym;
+ char * p;
+{
+ struct symbol * ref_sym=0;
+ char * sname;
+ /* snarfed from read_struct_type */
+ struct field_info fi;
+ struct type *type;
+ struct cleanup *back_to;
+
+ /* Need to make sure that fi isn't gunna conflict with struct
+ in case struct already had some fnfs */
+ fi.list = NULL;
+ fi.fnlist = NULL;
+ back_to = make_cleanup (null_cleanup, 0);
+
+ /* We only accept structs, classes and unions at the moment.
+ Other continuation types include t (typedef), r (long dbl), ...
+ We may want to add support for them as well;
+ right now they are handled by duplicating the symbol information
+ into the type information (see define_symbol) */
+ if (*p != 's' /* structs */
+ && *p != 'c' /* class */
+ && *p != 'u') /* union */
+ return 0; /* only handle C++ types */
+ p++;
+
+ /* Get symbol typs name and validate
+ eg: p = "A;;__ct__1AFv foo__1AFv ;;;" */
+ sname = get_substring (&p, ';');
+ if (!sname || strcmp (sname, SYMBOL_NAME(sym)))
+ error ("Internal error: base symbol type name does not match\n");
+
+ /* Find symbol's internal gdb reference using demangled_name.
+ This is the real sym that we want;
+ sym was a temp hack to make debugger happy */
+ ref_sym = lookup_symbol (SYMBOL_NAME(sym), 0, STRUCT_NAMESPACE, 0, 0);
+ type = SYMBOL_TYPE(ref_sym);
+
+
+ /* 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_cfront_baseclasses (&fi, &p, type, objfile)
+ /* g++ does this next, but cfront already did this:
+ || !read_struct_fields (&fi, &p, type, objfile) */
+ || !copy_cfront_struct_fields (&fi, type, objfile)
+ || !read_cfront_member_functions (&fi, &p, type, objfile)
+ || !read_cfront_static_fields (&fi, &p, type, objfile)
+ || !attach_fields_to_type (&fi, type, objfile)
+ || !attach_fn_fields_to_type (&fi, type)
+ /* g++ does this next, but cfront doesn't seem to have this:
+ || !read_tilde_fields (&fi, &p, type, objfile) */
+ )
+ {
+ type = error_type (&p, objfile);
+ }
+
+ do_cleanups (back_to);
+ return 0;
+}
+/* End of code added to support parsing of ARM/Cfront stabs strings */
+
+
+/* This routine fixes up symbol references/aliases to point to the original
+ symbol definition. Returns 0 on failure, non-zero on success. */
+
+static int
+resolve_symbol_reference (objfile, sym, p)
+ struct objfile *objfile;
+ struct symbol *sym;
+ char *p;
+{
+ int refnum;
+ struct symbol *ref_sym=0;
+ struct alias_list *alias;
+
+ /* If this is not a symbol reference return now. */
+ if (*p != '#')
+ return 0;
+
+ /* Use "#<num>" as the name; we'll fix the name later.
+ We stored the original symbol name as "#<id>=<name>"
+ so we can now search for "#<id>" to resolving the reference.
+ We'll fix the names later by removing the "#<id>" or "#<id>=" */
+
+ /*---------------------------------------------------------*/
+ /* Get the reference id number, and
+ advance p past the names so we can parse the rest.
+ eg: id=2 for p : "2=", "2=z:r(0,1)" "2:r(0,1);l(#5,#6),l(#7,#4)" */
+ /*---------------------------------------------------------*/
+
+ /* This gets reference name from string. sym may not have a name. */
+
+ /* Get the reference number associated with the reference id in the
+ gdb stab string. From that reference number, get the main/primary
+ symbol for this alias. */
+ refnum = process_reference (&p);
+ ref_sym = ref_search (refnum);
+ if (!ref_sym)
+ {
+ complain (&lrs_general_complaint, "symbol for reference not found");
+ return 0;
+ }
+
+ /* Parse the stab of the referencing symbol
+ now that we have the referenced symbol.
+ Add it as a new symbol and a link back to the referenced symbol.
+ eg: p : "=", "=z:r(0,1)" ":r(0,1);l(#5,#6),l(#7,#4)" */
+
+
+ /* If the stab symbol table and string contain:
+ RSYM 0 5 00000000 868 #15=z:r(0,1)
+ LBRAC 0 0 00000000 899 #5=
+ SLINE 0 16 00000003 923 #6=
+ Then the same symbols can be later referenced by:
+ RSYM 0 5 00000000 927 #15:r(0,1);l(#5,#6)
+ This is used in live range splitting to:
+ 1) specify that a symbol (#15) is actually just a new storage
+ class for a symbol (#15=z) which was previously defined.
+ 2) specify that the beginning and ending ranges for a symbol
+ (#15) are the values of the beginning (#5) and ending (#6)
+ symbols. */
+
+ /* Read number as reference id.
+ eg: p : "=", "=z:r(0,1)" ":r(0,1);l(#5,#6),l(#7,#4)" */
+ /* FIXME! Might I want to use SYMBOL_CLASS (sym) = LOC_OPTIMIZED_OUT;
+ in case of "l(0,0)"? */
+
+ /*--------------------------------------------------*/
+ /* Add this symbol to the reference list. */
+ /*--------------------------------------------------*/
+
+ alias = (struct alias_list *) obstack_alloc (&objfile->type_obstack,
+ sizeof (struct alias_list));
+ if (!alias)
+ {
+ complain (&lrs_general_complaint, "Unable to allocate alias list memory");
+ return 0;
+ }
+
+ alias->next = 0;
+ alias->sym = sym;
+
+ if (!SYMBOL_ALIASES (ref_sym))
+ {
+ SYMBOL_ALIASES (ref_sym) = alias;
+ }
+ else
+ {
+ struct alias_list *temp;
+
+ /* Get to the end of the list. */
+ for (temp = SYMBOL_ALIASES (ref_sym);
+ temp->next;
+ temp = temp->next)
+ ;
+ temp->next = alias;
+ }
+
+ /* Want to fix up name so that other functions (eg. valops)
+ will correctly print the name.
+ Don't add_symbol_to_list so that lookup_symbol won't find it.
+ nope... needed for fixups. */
+ SYMBOL_NAME (sym) = SYMBOL_NAME (ref_sym);
+
+ /* Done! */
+ return 1;
+}
+
+/* Structure for storing pointers to reference definitions for fast lookup
+ during "process_later". */
+
+struct ref_map
+{
+ char *stabs;
+ CORE_ADDR value;
+ struct symbol *sym;
+};
+
+#define MAX_CHUNK_REFS 100
+#define REF_CHUNK_SIZE (MAX_CHUNK_REFS * sizeof (struct ref_map))
+#define REF_MAP_SIZE(ref_chunk) ((ref_chunk) * REF_CHUNK_SIZE)
+
+static struct ref_map *ref_map;
+
+/* Ptr to free cell in chunk's linked list. */
+static int ref_count = 0;
+
+/* Number of chunks malloced. */
+static int ref_chunk = 0;
+
+/* Create array of pointers mapping refids to symbols and stab strings.
+ Add pointers to reference definition symbols and/or their values as we
+ find them, using their reference numbers as our index.
+ These will be used later when we resolve references. */
+void
+ref_add (refnum, sym, stabs, value)
+ int refnum;
+ struct symbol *sym;
+ char *stabs;
+ CORE_ADDR value;
+{
+ if (ref_count == 0)
+ ref_chunk = 0;
+ if (refnum >= ref_count)
+ ref_count = refnum + 1;
+ if (ref_count > ref_chunk * MAX_CHUNK_REFS)
+ {
+ int new_slots = ref_count - ref_chunk * MAX_CHUNK_REFS;
+ int new_chunks = new_slots / MAX_CHUNK_REFS + 1;
+ ref_map = (struct ref_map *)
+ xrealloc (ref_map, REF_MAP_SIZE (ref_chunk + new_chunks));
+ memset (ref_map + ref_chunk * MAX_CHUNK_REFS, 0, new_chunks * REF_CHUNK_SIZE);
+ ref_chunk += new_chunks;
+ }
+ ref_map[refnum].stabs = stabs;
+ ref_map[refnum].sym = sym;
+ ref_map[refnum].value = value;
+}
+
+/* Return defined sym for the reference REFNUM. */
+struct symbol *
+ref_search (refnum)
+ int refnum;
+{
+ if (refnum < 0 || refnum > ref_count)
+ return 0;
+ return ref_map[refnum].sym;
+}
+
+/* Return value for the reference REFNUM. */
+
+static CORE_ADDR
+ref_search_value (refnum)
+ int refnum;
+{
+ if (refnum < 0 || refnum > ref_count)
+ return 0;
+ return ref_map[refnum].value;
+}
+
+/* Parse a reference id in STRING and return the resulting
+ reference number. Move STRING beyond the reference id. */
+
+static int
+process_reference (string)
+ char **string;
+{
+ char *p;
+ int refnum = 0;
+
+ if (**string != '#')
+ return 0;
+
+ /* Advance beyond the initial '#'. */
+ p = *string + 1;
+
+ /* Read number as reference id. */
+ while (*p && isdigit (*p))
+ {
+ refnum = refnum * 10 + *p - '0';
+ p++;
+ }
+ *string = p;
+ return refnum;
+}
+
+/* If STRING defines a reference, store away a pointer to the reference
+ definition for later use. Return the reference number. */
+
+int
+symbol_reference_defined (string)
+ char **string;
+{
+ char *p = *string;
+ int refnum = 0;
+
+ refnum = process_reference (&p);
+
+ /* Defining symbols end in '=' */
+ if (*p == '=')
+ {
+ /* Symbol is being defined here. */
+ *string = p + 1;
+ return refnum;
+ }
+ else
+ {
+ /* Must be a reference. Either the symbol has already been defined,
+ or this is a forward reference to it. */
+ *string = p;
+ return -1;
+ }
+}
+
+/* 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;
+
+ while (p[1] == ':')
+ {
+ p += 2;
+ p = strchr (p, ':');
+ }
+
+ /* 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] == ':')));
+
+ current_symbol = sym = (struct symbol *)
+ obstack_alloc (&objfile -> symbol_obstack, sizeof (struct symbol));
+ memset (sym, 0, sizeof (struct symbol));
+
+ switch (type & N_TYPE)
+ {
+ case N_TEXT:
+ SYMBOL_SECTION(sym) = SECT_OFF_TEXT;
+ break;
+ case N_DATA:
+ SYMBOL_SECTION(sym) = SECT_OFF_DATA;
+ break;
+ case N_BSS:
+ SYMBOL_SECTION(sym) = SECT_OFF_BSS;
+ break;
+ }
+
+ 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 (is_cplus_marker (string[0]))
+ {
+ /* 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;
+
+#ifdef STATIC_TRANSFORM_NAME
+ case 'X':
+ /* SunPRO (3.0 at least) static variable encoding. */
+ goto normal;
+#endif
+
+ default:
+ complain (&unrecognized_cplus_name_complaint, string);
+ goto normal; /* Do *something* with it */
+ }
+ }
+ else if (string[0] == '#')
+ {
+ /* Special GNU C extension for referencing symbols. */
+ char *s;
+ int refnum, nlen;
+
+ /* If STRING defines a new reference id, then add it to the
+ reference map. Else it must be referring to a previously
+ defined symbol, so add it to the alias list of the previously
+ defined symbol. */
+ s = string;
+ refnum = symbol_reference_defined (&s);
+ if (refnum >= 0)
+ ref_add (refnum, sym, string, SYMBOL_VALUE (sym));
+ else
+ if (!resolve_symbol_reference (objfile, sym, string))
+ return NULL;
+
+ /* S..P contains the name of the symbol. We need to store
+ the correct name into SYMBOL_NAME. */
+ nlen = p - s;
+ if (refnum >= 0)
+ {
+ if (nlen > 0)
+ {
+ SYMBOL_NAME (sym) = (char *)
+ obstack_alloc (&objfile -> symbol_obstack, nlen);
+ strncpy (SYMBOL_NAME (sym), s, nlen);
+ SYMBOL_NAME (sym)[nlen] = '\0';
+ SYMBOL_INIT_DEMANGLED_NAME (sym, &objfile->symbol_obstack);
+ }
+ else
+ /* FIXME! Want SYMBOL_NAME (sym) = 0;
+ Get error if leave name 0. So give it something. */
+ {
+ nlen = p - string;
+ SYMBOL_NAME (sym) = (char *)
+ obstack_alloc (&objfile -> symbol_obstack, nlen);
+ strncpy (SYMBOL_NAME (sym), string, nlen);
+ SYMBOL_NAME (sym)[nlen] = '\0';
+ SYMBOL_INIT_DEMANGLED_NAME (sym, &objfile->symbol_obstack);
+ }
+ }
+ /* Advance STRING beyond the reference id. */
+ string = s;
+ }
+ 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, objfile);
+ 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-if-picky-about-floating-accuracy: Should be using
+ target arithmetic to get the value. real.c in GCC
+ probably has the necessary code. */
+
+ /* 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?
+
+ 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,
+ TYPE_LENGTH (SYMBOL_TYPE (sym)));
+ store_floating (dbl_valu, TYPE_LENGTH (SYMBOL_TYPE (sym)), d);
+ 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, objfile);
+ 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, objfile);
+ }
+ }
+ 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)
+ SYMBOL_TYPE (sym) = lookup_function_type (SYMBOL_TYPE (sym));
+
+ /* All functions in C++ have prototypes. */
+ if (SYMBOL_LANGUAGE (sym) == language_cplus)
+ TYPE_FLAGS (SYMBOL_TYPE (sym)) |= TYPE_FLAG_PROTOTYPED;
+
+ /* fall into process_prototype_types */
+
+ process_prototype_types:
+ /* Sun acc puts declared types of arguments here. */
+ if (*p == ';')
+ {
+ struct type *ftype = SYMBOL_TYPE (sym);
+ int nsemi = 0;
+ int nparams = 0;
+ char *p1 = p;
+
+ /* Obtain a worst case guess for the number of arguments
+ by counting the semicolons. */
+ while (*p1)
+ {
+ if (*p1++ == ';')
+ nsemi++;
+ }
+
+ /* Allocate parameter information fields and fill them in. */
+ TYPE_FIELDS (ftype) = (struct field *)
+ TYPE_ALLOC (ftype, nsemi * sizeof (struct field));
+ while (*p++ == ';')
+ {
+ struct type *ptype;
+
+ /* A type number of zero indicates the start of varargs.
+ FIXME: GDB currently ignores vararg functions. */
+ if (p[0] == '0' && p[1] == '\0')
+ break;
+ ptype = read_type (&p, objfile);
+
+ /* The Sun compilers mark integer arguments, which should
+ be promoted to the width of the calling conventions, with
+ a type which references itself. This type is turned into
+ a TYPE_CODE_VOID type by read_type, and we have to turn
+ it back into builtin_type_int here.
+ FIXME: Do we need a new builtin_type_promoted_int_arg ? */
+ if (TYPE_CODE (ptype) == TYPE_CODE_VOID)
+ ptype = builtin_type_int;
+ TYPE_FIELD_TYPE (ftype, nparams++) = ptype;
+ }
+ TYPE_NFIELDS (ftype) = nparams;
+ TYPE_FLAGS (ftype) |= TYPE_FLAG_PROTOTYPED;
+ }
+ 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);
+ SYMBOL_CLASS (sym) = LOC_STATIC;
+ SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
+ /* Don't add symbol references to global_sym_chain.
+ Symbol references don't have valid names and wont't match up with
+ minimal symbols when the global_sym_chain is relocated.
+ We'll fixup symbol references when we fixup the defining symbol. */
+ if (SYMBOL_NAME (sym) && SYMBOL_NAME (sym)[0] != '#')
+ {
+ i = hashname (SYMBOL_NAME (sym));
+ SYMBOL_VALUE_CHAIN (sym) = global_sym_chain[i];
+ global_sym_chain[i] = sym;
+ }
+ 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 's':
+ 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;
+ add_symbol_to_list (sym, &local_symbols);
+
+ if (TARGET_BYTE_ORDER != BIG_ENDIAN)
+ {
+ /* On little-endian machines, this crud is never necessary,
+ and, if the extra bytes contain garbage, is harmful. */
+ break;
+ }
+
+ /* 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).
+
+ 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 little 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. */
+
+ case 'P':
+ /* acc seems to use P to declare 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)
+ {
+ SYMBOL_TYPE (sym) = 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_VALUE (sym), NUM_REGS,
+ 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_VALUE (sym), NUM_REGS,
+ 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. For Sun cc we need to do this
+ regardless of REG_STRUCT_HAS_ADDR, because the compiler puts out
+ the 'p' symbol even if it never saves the argument onto the stack.
+
+ On most machines, we want to preserve both symbols, so that
+ we can still get information about what is going on with the
+ stack (VAX for computing args_printed, using stack slots instead
+ of saved registers in backtraces, etc.).
+
+ Note that this code illegally combines
+ main(argc) struct foo argc; { register struct foo argc; }
+ but this case is considered pathological and causes a warning
+ from a decent compiler. */
+
+ if (local_symbols
+ && local_symbols->nsyms > 0
+#ifndef USE_REGISTER_NOT_ARG
+ && REG_STRUCT_HAS_ADDR (processing_gcc_compilation,
+ SYMBOL_TYPE (sym))
+ && (TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_STRUCT
+ || TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_UNION
+ || TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_SET
+ || TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_BITSTRING)
+#endif
+ )
+ {
+ struct symbol *prev_sym;
+ prev_sym = local_symbols->symbol[local_symbols->nsyms - 1];
+ if ((SYMBOL_CLASS (prev_sym) == LOC_REF_ARG
+ || SYMBOL_CLASS (prev_sym) == LOC_ARG)
+ && STREQ (SYMBOL_NAME (prev_sym), SYMBOL_NAME(sym)))
+ {
+ SYMBOL_CLASS (prev_sym) = LOC_REGPARM;
+ /* Use the type from the LOC_REGISTER; that is the type
+ that is actually in that register. */
+ SYMBOL_TYPE (prev_sym) = SYMBOL_TYPE (sym);
+ 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;
+#ifdef STATIC_TRANSFORM_NAME
+ if (IS_STATIC_TRANSFORM_NAME (SYMBOL_NAME (sym)))
+ {
+ struct minimal_symbol *msym;
+ msym = lookup_minimal_symbol (SYMBOL_NAME (sym), NULL, objfile);
+ if (msym != NULL)
+ {
+ SYMBOL_NAME (sym) = STATIC_TRANSFORM_NAME (SYMBOL_NAME (sym));
+ SYMBOL_VALUE_ADDRESS (sym) = SYMBOL_VALUE_ADDRESS (msym);
+ }
+ }
+#endif
+ SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
+ add_symbol_to_list (sym, &file_symbols);
+ break;
+
+ case 't':
+ 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)
+ {
+ /* gcc-2.6 or later (when using -fvtable-thunks)
+ emits a unique named type for a vtable entry.
+ Some gdb code depends on that specific name. */
+ extern const char vtbl_ptr_name[];
+
+ if ((TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_PTR
+ && strcmp (SYMBOL_NAME (sym), vtbl_ptr_name))
+ || 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++;
+ /* The semantics of C++ state that "struct foo { ... }" also defines
+ a typedef for "foo". Unfortunately, cfront never makes the typedef
+ when translating C++ into C. We make the typedef here so that
+ "ptype foo" works as expected for cfront translated code. */
+ else if (current_subfile->language == language_cplus)
+ synonym = 1;
+
+ 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;
+#ifdef STATIC_TRANSFORM_NAME
+ if (IS_STATIC_TRANSFORM_NAME (SYMBOL_NAME (sym)))
+ {
+ struct minimal_symbol *msym;
+ msym = lookup_minimal_symbol (SYMBOL_NAME (sym), NULL, objfile);
+ if (msym != NULL)
+ {
+ SYMBOL_NAME (sym) = STATIC_TRANSFORM_NAME (SYMBOL_NAME (sym));
+ SYMBOL_VALUE_ADDRESS (sym) = SYMBOL_VALUE_ADDRESS (msym);
+ }
+ }
+#endif
+ SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
+ if (os9k_stabs)
+ add_symbol_to_list (sym, &global_symbols);
+ else
+ 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 'a':
+ /* Reference parameter which is in a register. */
+ SYMBOL_TYPE (sym) = read_type (&p, objfile);
+ SYMBOL_CLASS (sym) = LOC_REGPARM_ADDR;
+ SYMBOL_VALUE (sym) = STAB_REG_TO_REGNUM (valu);
+ if (SYMBOL_VALUE (sym) >= NUM_REGS)
+ {
+ complain (&reg_value_complaint, SYMBOL_VALUE (sym), NUM_REGS,
+ 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 '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;
+
+ /* New code added to support cfront stabs strings.
+ Note: case 'P' already handled above */
+ case 'Z':
+ /* Cfront type continuation coming up!
+ Find the original definition and add to it.
+ We'll have to do this for the typedef too,
+ since we cloned the symbol to define a type in read_type.
+ Stabs info examples:
+ __1C :Ztl
+ foo__1CFv :ZtF (first def foo__1CFv:F(0,3);(0,24))
+ C:ZsC;;__ct__1CFv func1__1CFv func2__1CFv ... ;;;
+ where C is the name of the class.
+ Unfortunately, we can't lookup the original symbol yet 'cuz
+ we haven't finished reading all the symbols.
+ Instead, we save it for processing later */
+ process_later (sym, p, resolve_cfront_continuation);
+ SYMBOL_TYPE (sym) = error_type (&p, objfile); /* FIXME! change later */
+ SYMBOL_CLASS (sym) = LOC_CONST;
+ SYMBOL_VALUE (sym) = 0;
+ SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
+ /* Don't add to list - we'll delete it later when
+ we add the continuation to the real sym */
+ return sym;
+ /* End of new code added to support cfront stabs strings */
+
+ default:
+ SYMBOL_TYPE (sym) = error_type (&p, objfile);
+ 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 (processing_gcc_compilation, SYMBOL_TYPE (sym))
+ && (SYMBOL_CLASS (sym) == LOC_REGPARM || SYMBOL_CLASS (sym) == LOC_ARG))
+ {
+ struct type *symbol_type = check_typedef (SYMBOL_TYPE (sym));
+
+ if ((TYPE_CODE (symbol_type) == TYPE_CODE_STRUCT)
+ || (TYPE_CODE (symbol_type) == TYPE_CODE_UNION)
+ || (TYPE_CODE (symbol_type) == TYPE_CODE_BITSTRING)
+ || (TYPE_CODE (symbol_type) == TYPE_CODE_SET))
+ {
+ /* If REG_STRUCT_HAS_ADDR yields non-zero we have to convert
+ LOC_REGPARM to LOC_REGPARM_ADDR for structures and unions. */
+ if (SYMBOL_CLASS (sym) == LOC_REGPARM)
+ SYMBOL_CLASS (sym) = LOC_REGPARM_ADDR;
+ /* Likewise for converting LOC_ARG to LOC_REF_ARG (for the 7th
+ and subsequent arguments on the sparc, for example). */
+ else if (SYMBOL_CLASS (sym) == LOC_ARG)
+ SYMBOL_CLASS (sym) = LOC_REF_ARG;
+ }
+ }
+
+ /* Is there more to parse? For example LRS/alias information? */
+ while (*p && *p == ';')
+ {
+ p++;
+ if (*p && *p == 'l')
+ {
+ /* GNU extensions for live range splitting may be appended to
+ the end of the stab string. eg. "l(#1,#2);l(#3,#5)" */
+
+ /* Resolve the live range and add it to SYM's live range list. */
+ if (!resolve_live_range (objfile, sym, p))
+ return NULL;
+
+ /* Find end of live range info. */
+ p = strchr (p, ')');
+ if (!*p || *p != ')')
+ {
+ complain (&lrs_general_complaint, "live range format not recognized");
+ return NULL;
+ }
+ p++;
+ }
+ }
+ return sym;
+}
+
+/* Add the live range found in P to the symbol SYM in objfile OBJFILE. Returns
+ non-zero on success, zero otherwise. */
+
+static int
+resolve_live_range (objfile, sym, p)
+ struct objfile *objfile;
+ struct symbol *sym;
+ char *p;
+{
+ int refnum;
+ CORE_ADDR start, end;
+
+ /* Sanity check the beginning of the stabs string. */
+ if (!*p || *p != 'l')
+ {
+ complain (&lrs_general_complaint, "live range string 1");
+ return 0;
+ }
+ p++;
+
+ if (!*p || *p != '(')
+ {
+ complain (&lrs_general_complaint, "live range string 2");
+ return 0;
+ }
+ p++;
+
+ /* Get starting value of range and advance P past the reference id.
+
+ ?!? In theory, the process_reference should never fail, but we should
+ catch that case just in case the compiler scrogged the stabs. */
+ refnum = process_reference (&p);
+ start = ref_search_value (refnum);
+ if (!start)
+ {
+ complain (&lrs_general_complaint, "Live range symbol not found 1");
+ return 0;
+ }
+
+ if (!*p || *p != ',')
+ {
+ complain (&lrs_general_complaint, "live range string 3");
+ return 0;
+ }
+ p++;
+
+ /* Get ending value of range and advance P past the reference id.
+
+ ?!? In theory, the process_reference should never fail, but we should
+ catch that case just in case the compiler scrogged the stabs. */
+ refnum = process_reference (&p);
+ end = ref_search_value (refnum);
+ if (!end)
+ {
+ complain (&lrs_general_complaint, "Live range symbol not found 2");
+ return 0;
+ }
+
+ if (!*p || *p != ')')
+ {
+ complain (&lrs_general_complaint, "live range string 4");
+ return 0;
+ }
+
+ /* Now that we know the bounds of the range, add it to the
+ symbol. */
+ add_live_range (objfile, sym, start, end);
+
+ return 1;
+}
+
+/* Add a new live range defined by START and END to the symbol SYM
+ in objfile OBJFILE. */
+
+static void
+add_live_range (objfile, sym, start, end)
+ struct objfile *objfile;
+ struct symbol *sym;
+ CORE_ADDR start, end;
+{
+ struct range_list *r, *rs;
+
+ if (start >= end)
+ {
+ complain (&lrs_general_complaint, "end of live range follows start");
+ return;
+ }
+
+ /* Alloc new live range structure. */
+ r = (struct range_list *)
+ obstack_alloc (&objfile->type_obstack,
+ sizeof (struct range_list));
+ r->start = start;
+ r->end = end;
+ r->next = 0;
+
+ /* Append this range to the symbol's range list. */
+ if (!SYMBOL_RANGES (sym))
+ SYMBOL_RANGES (sym) = r;
+ else
+ {
+ /* Get the last range for the symbol. */
+ for (rs = SYMBOL_RANGES (sym); rs->next; rs = rs->next)
+ ;
+ rs->next = r;
+ }
+}
+
+
+/* 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, objfile);
+
+ 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, objfile);
+ ++*pp;
+
+ or
+
+ if (**pp != ';')
+ foo = error_type (pp, objfile);
+ 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, objfile)
+ char **pp;
+ struct objfile *objfile;
+{
+ 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)[-1] == '?')
+ {
+ *pp = next_symbol_text (objfile);
+ }
+ 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];
+ 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;
+
+ /* Used to distinguish string and bitstring from char-array and set. */
+ int is_string = 0;
+
+ /* 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, objfile);
+
+ /* 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 '='.
+ Also skip the type descriptor - we get it below with (*pp)[-1]. */
+ (*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)++;
+ }
+
+ again:
+ 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, *p, *q1, *q2;
+
+ /* 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:
+ {
+ /* Complain and keep going, so compilers can invent new
+ cross-reference types. */
+ static struct complaint msg =
+ {"Unrecognized cross-reference type `%c'", 0, 0};
+ complain (&msg, (*pp)[0]);
+ code = TYPE_CODE_STRUCT;
+ break;
+ }
+ }
+
+ q1 = strchr (*pp, '<');
+ p = strchr (*pp, ':');
+ if (p == NULL)
+ return error_type (pp, objfile);
+ if (q1 && p > q1 && p[1] == ':')
+ {
+ int nesting_level = 0;
+ for (q2 = q1; *q2; q2++)
+ {
+ if (*q2 == '<')
+ nesting_level++;
+ else if (*q2 == '>')
+ nesting_level--;
+ else if (*q2 == ':' && nesting_level == 0)
+ break;
+ }
+ p = q2;
+ if (*p != ':')
+ return error_type (pp, objfile);
+ }
+ to = type_name =
+ (char *)obstack_alloc (&objfile->type_obstack, p - *pp + 1);
+
+ /* Copy the name. */
+ from = *pp + 1;
+ while (from < p)
+ *to++ = *from++;
+ *to = '\0';
+
+ /* Set the pointer ahead of the name which we just read, and
+ the colon. */
+ *pp = from + 1;
+ }
+
+ /* Now check to see whether the type has already been
+ declared. This was written for arrays of cross-referenced
+ types before we had TYPE_CODE_TARGET_STUBBED, so I'm pretty
+ sure it is not necessary anymore. But it might be a good
+ idea, to save a little memory. */
+
+ 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)--;
+
+ /* We deal with something like t(1,2)=(3,4)=... which
+ the Lucid compiler and recent gcc versions (post 2.7.3) use. */
+
+ /* Allocate and enter the typedef type first.
+ This handles recursive types. */
+ type = dbx_alloc_type (typenums, objfile);
+ TYPE_CODE (type) = TYPE_CODE_TYPEDEF;
+ { struct type *xtype = read_type (pp, objfile);
+ if (type == xtype)
+ {
+ /* It's being defined as itself. That means it is "void". */
+ TYPE_CODE (type) = TYPE_CODE_VOID;
+ TYPE_LENGTH (type) = 1;
+ }
+ else if (type_size >= 0 || is_string)
+ {
+ *type = *xtype;
+ TYPE_NAME (type) = NULL;
+ TYPE_TAG_NAME (type) = NULL;
+ }
+ else
+ {
+ TYPE_FLAGS (type) |= TYPE_FLAG_TARGET_STUB;
+ TYPE_TARGET_TYPE (type) = xtype;
+ }
+ }
+ 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 */
+ if (os9k_stabs && **pp == '(')
+ {
+ /* Function prototype; parse it.
+ We must conditionalize this on os9k_stabs because otherwise
+ it could be confused with a Sun-style (1,3) typenumber
+ (I think). */
+ struct type *t;
+ ++*pp;
+ while (**pp != ')')
+ {
+ t = read_type (pp, objfile);
+ if (**pp == ',') ++*pp;
+ }
+ }
+ type1 = read_type (pp, objfile);
+ type = make_function_type (type1, dbx_lookup_type (typenums));
+ break;
+
+ case 'k': /* Const qualifier on some type (Sun) */
+ case 'c': /* Const qualifier on some type (OS9000) */
+ /* Because 'c' means other things to AIX and 'k' is perfectly good,
+ only accept 'c' in the os9k_stabs case. */
+ if (type_descriptor == 'c' && !os9k_stabs)
+ return error_type (pp, objfile);
+ type = read_type (pp, objfile);
+ /* FIXME! For now, we ignore const and volatile qualifiers. */
+ break;
+
+ case 'B': /* Volatile qual on some type (Sun) */
+ case 'i': /* Volatile qual on some type (OS9000) */
+ /* Because 'i' means other things to AIX and 'B' is perfectly good,
+ only accept 'i' in the os9k_stabs case. */
+ if (type_descriptor == 'i' && !os9k_stabs)
+ return error_type (pp, objfile);
+ type = read_type (pp, objfile);
+ /* FIXME! For now, we ignore const and volatile qualifiers. */
+ break;
+
+ case '@':
+ if (isdigit (**pp) || **pp == '(' || **pp == '-')
+ { /* Member (class & variable) type */
+ /* FIXME -- we should be doing smash_to_XXX types here. */
+
+ struct type *domain = read_type (pp, objfile);
+ struct type *memtype;
+
+ if (**pp != ',')
+ /* Invalid member type data format. */
+ return error_type (pp, objfile);
+ ++*pp;
+
+ memtype = read_type (pp, objfile);
+ type = dbx_alloc_type (typenums, objfile);
+ smash_to_member_type (type, domain, memtype);
+ }
+ else /* type attribute */
+ {
+ char *attr = *pp;
+ /* Skip to the semicolon. */
+ while (**pp != ';' && **pp != '\0')
+ ++(*pp);
+ if (**pp == '\0')
+ return error_type (pp, objfile);
+ else
+ ++*pp; /* Skip the semicolon. */
+
+ switch (*attr)
+ {
+ case 's':
+ type_size = atoi (attr + 1);
+ if (type_size <= 0)
+ type_size = -1;
+ break;
+
+ case 'S':
+ is_string = 1;
+ break;
+
+ default:
+ /* Ignore unrecognized type attributes, so future compilers
+ can invent new ones. */
+ break;
+ }
+ ++*pp;
+ goto again;
+ }
+ 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, objfile);
+ 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':
+ if (os9k_stabs)
+ /* Const and volatile qualified type. */
+ type = read_type (pp, objfile);
+ else
+ {
+ /* 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);
+ 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, objfile);
+ ++*pp;
+
+ type = dbx_alloc_type (typenums, objfile);
+ type = read_array_type (pp, type, objfile);
+ if (is_string)
+ TYPE_CODE (type) = TYPE_CODE_STRING;
+ break;
+
+ case 'S':
+ type1 = read_type (pp, objfile);
+ type = create_set_type ((struct type*) NULL, type1);
+ if (is_string)
+ TYPE_CODE (type) = TYPE_CODE_BITSTRING;
+ if (typenums[0] != -1)
+ *dbx_lookup_type (typenums) = type;
+ break;
+
+ default:
+ --*pp; /* Go back to the symbol in error */
+ /* Particularly important if it was \0! */
+ return error_type (pp, objfile);
+ }
+
+ if (type == 0)
+ {
+ warning ("GDB internal error, type is NULL in stabsread.c\n");
+ return error_type (pp, objfile);
+ }
+
+ /* Size specified in a type attribute overrides any other size. */
+ if (type_size != -1)
+ TYPE_LENGTH (type) = (type_size + TARGET_CHAR_BIT - 1) / 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 34
+ /* 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, 1, 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, TYPE_FLAG_UNSIGNED,
+ "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_COMPLEX, 8, 0, "complex", NULL);
+ break;
+ case 26:
+ /* Complex type consisting of two IEEE double precision values. */
+ rettype = init_type (TYPE_CODE_COMPLEX, 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;
+ case 31:
+ rettype = init_type (TYPE_CODE_INT, 8, 0, "long long", NULL);
+ break;
+ case 32:
+ rettype = init_type (TYPE_CODE_INT, 8, TYPE_FLAG_UNSIGNED,
+ "unsigned long long", NULL);
+ break;
+ case 33:
+ rettype = init_type (TYPE_CODE_INT, 8, TYPE_FLAG_UNSIGNED,
+ "logical*8", NULL);
+ break;
+ case 34:
+ rettype = init_type (TYPE_CODE_INT, 8, 0, "integer*8", NULL);
+ break;
+ }
+ negative_types[-typenum] = rettype;
+ return rettype;
+}
+
+/* This page contains subroutines of read_type. */
+
+/* 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' && is_cplus_marker ((*pp)[2]))
+ {
+ /* 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, objfile);
+ 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, objfile);
+
+ 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, objfile);
+ 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, objfile);
+ 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, objfile);
+ }
+ 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, objfile);
+ }
+
+ 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;
+ FIELD_BITPOS (fip->list->field) = read_huge_number (pp, ';', &nbits);
+ if (nbits != 0)
+ return 0;
+ }
+ /* This field is unpacked. */
+ FIELD_BITSIZE (fip->list->field) = 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;
+{
+ /* The following is code to work around cfront generated stabs.
+ The stabs contains full mangled name for each field.
+ We try to demangle the name and extract the field name out of it.
+ */
+ if (ARM_DEMANGLING && current_subfile->language == language_cplus)
+ {
+ char save_p;
+ char *dem, *dem_p;
+ save_p = *p;
+ *p = '\0';
+ dem = cplus_demangle (*pp, DMGL_ANSI | DMGL_PARAMS);
+ if (dem != NULL)
+ {
+ dem_p = strrchr (dem, ':');
+ if (dem_p != 0 && *(dem_p-1)==':')
+ dem_p++;
+ FIELD_NAME (fip->list->field) =
+ obsavestring (dem_p, strlen (dem_p), &objfile -> type_obstack);
+ }
+ else
+ {
+ FIELD_NAME (fip->list->field) =
+ obsavestring (*pp, p - *pp, &objfile -> type_obstack);
+ }
+ *p = save_p;
+ }
+ /* end of code for cfront work around */
+
+ else
+ 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)++;
+ }
+ 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
+ while (*p != ';')
+ {
+ p++;
+ }
+ /* Static class member. */
+ SET_FIELD_PHYSNAME (fip->list->field, 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;
+ FIELD_BITPOS (fip->list->field) = read_huge_number (pp, ',', &nbits);
+ if (nbits != 0)
+ {
+ complain (&stabs_general_complaint, "bad structure-type format");
+ return;
+ }
+ FIELD_BITSIZE (fip->list->field) = read_huge_number (pp, ';', &nbits);
+ if (nbits != 0)
+ {
+ complain (&stabs_general_complaint, "bad structure-type format");
+ return;
+ }
+ }
+
+ if (FIELD_BITPOS (fip->list->field) == 0
+ && FIELD_BITSIZE (fip->list->field) == 0)
+ {
+ /* This can happen in two cases: (1) at least for gcc 2.4.5 or so,
+ it is a field which has been optimized out. The correct stab for
+ this case is to use VISIBILITY_IGNORE, but that is a recent
+ invention. (2) It is a 0-size array. For example
+ union { int num; char str[0]; } foo. Printing "<no value>" for
+ str in "p foo" is OK, since foo.str (and thus foo.str[3])
+ will continue to work, and a 0-size array as a whole doesn't
+ have any contents to print.
+
+ I suspect this probably could also happen with gcc -gstabs (not
+ -gstabs+) for static fields, and perhaps other C++ extensions.
+ Hopefully few people use -gstabs with gdb, since it is intended
+ for dbx compatibility. */
+
+ /* Ignore this field. */
+ fip -> list-> visibility = VISIBILITY_IGNORE;
+ }
+ else
+ {
+ /* 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. */
+
+ struct type *field_type = check_typedef (FIELD_TYPE (fip->list->field));
+
+ if (TYPE_CODE (field_type) != TYPE_CODE_INT
+ && TYPE_CODE (field_type) != TYPE_CODE_RANGE
+ && TYPE_CODE (field_type) != TYPE_CODE_BOOL
+ && TYPE_CODE (field_type) != TYPE_CODE_ENUM)
+ {
+ FIELD_BITSIZE (fip->list->field) = 0;
+ }
+ if ((FIELD_BITSIZE (fip->list->field)
+ == TARGET_CHAR_BIT * TYPE_LENGTH (field_type)
+ || (TYPE_CODE (field_type) == TYPE_CODE_ENUM
+ && FIELD_BITSIZE (fip->list->field) == TARGET_INT_BIT )
+ )
+ &&
+ FIELD_BITPOS (fip->list->field) % 8 == 0)
+ {
+ FIELD_BITSIZE (fip->list->field) = 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)
+ '/9' (VISIBILITY_IGNORE)
+
+ 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 != ';')
+ {
+ if (os9k_stabs && **pp == ',') break;
+ STABS_CONTINUE (pp, objfile);
+ /* 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 (is_cplus_marker (p[0]) && 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[0] == ':' && 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;
+ FIELD_BITSIZE (new->field) = 0; /* this should be an unpacked field! */
+
+ STABS_CONTINUE (pp, objfile);
+ switch (**pp)
+ {
+ case '0':
+ /* Nothing to do. */
+ break;
+ case '1':
+ SET_TYPE_FIELD_VIRTUAL (type, i);
+ break;
+ default:
+ /* Unknown character. Complain and treat it as non-virtual. */
+ {
+ static struct complaint msg = {
+ "Unknown virtual character `%c' for baseclass", 0, 0};
+ complain (&msg, **pp);
+ }
+ }
+ ++(*pp);
+
+ new -> visibility = *(*pp)++;
+ switch (new -> visibility)
+ {
+ case VISIBILITY_PRIVATE:
+ case VISIBILITY_PROTECTED:
+ case VISIBILITY_PUBLIC:
+ break;
+ default:
+ /* Bad visibility format. Complain and treat it as
+ public. */
+ {
+ static struct complaint msg = {
+ "Unknown visibility `%c' for baseclass", 0, 0};
+ complain (&msg, new -> visibility);
+ new -> visibility = VISIBILITY_PUBLIC;
+ }
+ }
+
+ {
+ 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. */
+
+ FIELD_BITPOS (new->field) = 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, objfile);
+
+ /* 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 = 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;
+}
+
+/* read cfront class static data.
+ pp points to string starting with the list of static data
+ eg: A:ZcA;1@Bpub v2@Bvirpri;__ct__1AFv func__1AFv *sfunc__1AFv ;as__1A ;;
+ ^^^^^^^^
+
+ A:ZcA;;foopri__1AFv foopro__1AFv __ct__1AFv __ct__1AFRC1A foopub__1AFv ;;;
+ ^
+ */
+
+static int
+read_cfront_static_fields (fip, pp, type, objfile)
+ struct field_info *fip;
+ char **pp;
+ struct type *type;
+ struct objfile *objfile;
+{
+ struct nextfield * new;
+ struct type *stype;
+ char * sname;
+ struct symbol * ref_static=0;
+
+ if (**pp==';') /* no static data; return */
+ {
+ ++(*pp);
+ return 1;
+ }
+
+ /* Process each field in the list until we find the terminating ";" */
+
+ /* eg: p = "as__1A ;;;" */
+ STABS_CONTINUE (pp, objfile); /* handle \\ */
+ while (**pp!=';' && (sname = get_substring (pp, ' '), sname))
+ {
+ ref_static = lookup_symbol (sname, 0, VAR_NAMESPACE, 0, 0); /*demangled_name*/
+ if (!ref_static)
+ {
+ static struct complaint msg = {"\
+ Unable to find symbol for static data field %s\n",
+ 0, 0};
+ complain (&msg, sname);
+ continue;
+ }
+ stype = SYMBOL_TYPE(ref_static);
+
+ /* allocate a new fip */
+ new = (struct nextfield *) xmalloc (sizeof (struct nextfield));
+ make_cleanup (free, new);
+ memset (new, 0, sizeof (struct nextfield));
+ new -> next = fip -> list;
+ fip -> list = new;
+
+ /* set visibility */
+ /* FIXME! no way to tell visibility from stabs??? */
+ new -> visibility = VISIBILITY_PUBLIC;
+
+ /* set field info into fip */
+ fip -> list -> field.type = stype;
+
+ /* set bitpos & bitsize */
+ SET_FIELD_PHYSNAME (fip->list->field, savestring (sname, strlen (sname)));
+
+ /* set name field */
+ /* The following is code to work around cfront generated stabs.
+ The stabs contains full mangled name for each field.
+ We try to demangle the name and extract the field name out of it.
+ */
+ if (ARM_DEMANGLING)
+ {
+ char *dem, *dem_p;
+ dem = cplus_demangle (sname, DMGL_ANSI | DMGL_PARAMS);
+ if (dem != NULL)
+ {
+ dem_p = strrchr (dem, ':');
+ if (dem_p != 0 && *(dem_p-1)==':')
+ dem_p++;
+ fip->list->field.name =
+ obsavestring (dem_p, strlen (dem_p), &objfile -> type_obstack);
+ }
+ else
+ {
+ fip->list->field.name =
+ obsavestring (sname, strlen (sname), &objfile -> type_obstack);
+ }
+ } /* end of code for cfront work around */
+ } /* loop again for next static field */
+ return 1;
+}
+
+/* Copy structure fields to fip so attach_fields_to_type will work.
+ type has already been created with the initial instance data fields.
+ Now we want to be able to add the other members to the class,
+ so we want to add them back to the fip and reattach them again
+ once we have collected all the class members. */
+
+static int
+copy_cfront_struct_fields (fip, type, objfile)
+ struct field_info *fip;
+ struct type *type;
+ struct objfile *objfile;
+{
+ int nfields = TYPE_NFIELDS(type);
+ int i;
+ struct nextfield * new;
+
+ /* Copy the fields into the list of fips and reset the types
+ to remove the old fields */
+
+ for (i=0; i<nfields; i++)
+ {
+ /* allocate a new fip */
+ new = (struct nextfield *) xmalloc (sizeof (struct nextfield));
+ make_cleanup (free, new);
+ memset (new, 0, sizeof (struct nextfield));
+ new -> next = fip -> list;
+ fip -> list = new;
+
+ /* copy field info into fip */
+ new -> field = TYPE_FIELD (type, i);
+ /* set visibility */
+ if (TYPE_FIELD_PROTECTED (type, i))
+ new -> visibility = VISIBILITY_PROTECTED;
+ else if (TYPE_FIELD_PRIVATE (type, i))
+ new -> visibility = VISIBILITY_PRIVATE;
+ else
+ new -> visibility = VISIBILITY_PUBLIC;
+ }
+ /* Now delete the fields from the type since we will be
+ allocing new space once we get the rest of the fields
+ in attach_fields_to_type.
+ The pointer TYPE_FIELDS(type) is left dangling but should
+ be freed later by objstack_free */
+ TYPE_FIELDS (type)=0;
+ TYPE_NFIELDS (type) = 0;
+
+ 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);
+
+ TYPE_FIELD_IGNORE_BITS (type) =
+ (B_TYPE *) TYPE_ALLOC (type, B_BYTES (nfields));
+ B_CLRALL (TYPE_FIELD_IGNORE_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_IGNORE:
+ SET_TYPE_FIELD_IGNORE (type, nfields);
+ break;
+
+ case VISIBILITY_PUBLIC:
+ break;
+
+ default:
+ /* Unknown visibility. Complain and treat it as public. */
+ {
+ static struct complaint msg = {
+ "Unknown visibility `%c' for field", 0, 0};
+ complain (&msg, fip -> list -> 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, objfile);
+ }
+
+ /* 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))
+ {
+ type = error_type (pp, objfile);
+ }
+
+ 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>".
+ OS9000: "arlower,upper;<array_contents_type>".
+
+ Fortran adjustable arrays use Adigits or Tdigits for lower or upper;
+ for these, produce a type like float[][]. */
+
+ if (os9k_stabs)
+ index_type = builtin_type_int;
+ else
+ {
+ index_type = read_type (pp, objfile);
+ if (**pp != ';')
+ /* Improper format of array type decl. */
+ return error_type (pp, objfile);
+ ++*pp;
+ }
+
+ if (!(**pp >= '0' && **pp <= '9') && **pp != '-')
+ {
+ (*pp)++;
+ adjustable = 1;
+ }
+ lower = read_huge_number (pp, os9k_stabs ? ',' : ';', &nbits);
+ if (nbits != 0)
+ return error_type (pp, objfile);
+
+ if (!(**pp >= '0' && **pp <= '9') && **pp != '-')
+ {
+ (*pp)++;
+ adjustable = 1;
+ }
+ upper = read_huge_number (pp, ';', &nbits);
+ if (nbits != 0)
+ return error_type (pp, objfile);
+
+ 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);
+
+ 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;
+ int nbits;
+ int unsigned_enum = 1;
+
+#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;
+
+ if (os9k_stabs)
+ {
+ /* Size. Perhaps this does not have to be conditionalized on
+ os9k_stabs (assuming the name of an enum constant can't start
+ with a digit). */
+ read_huge_number (pp, 0, &nbits);
+ if (nbits != 0)
+ return error_type (pp, objfile);
+ }
+
+ /* The aix4 compiler emits an extra field before the enum members;
+ my guess is it's a type of some sort. Just ignore it. */
+ if (**pp == '-')
+ {
+ /* Skip over the type. */
+ while (**pp != ':')
+ (*pp)++;
+
+ /* Skip over the colon. */
+ (*pp)++;
+ }
+
+ /* Read the value-names and their values.
+ The input syntax is NAME:VALUE,NAME:VALUE, and so on.
+ A semicolon or comma instead of a NAME means the end. */
+ while (**pp && **pp != ';' && **pp != ',')
+ {
+ STABS_CONTINUE (pp, objfile);
+ 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, objfile);
+
+ 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;
+ if (n < 0)
+ unsigned_enum = 0;
+ 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) = TARGET_INT_BIT / HOST_CHAR_BIT;
+ TYPE_CODE (type) = TYPE_CODE_ENUM;
+ TYPE_FLAGS (type) &= ~TYPE_FLAG_STUB;
+ if (unsigned_enum)
+ TYPE_FLAGS (type) |= TYPE_FLAG_UNSIGNED;
+ 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 = nsyms - 1; syms; syms = syms->next)
+ {
+ int last = syms == osyms ? o_nsyms : 0;
+ int j = syms->nsyms;
+ for (; --j >= last; --n)
+ {
+ struct symbol *xsym = syms->symbol[j];
+ SYMBOL_TYPE (xsym) = type;
+ TYPE_FIELD_NAME (type, n) = SYMBOL_NAME (xsym);
+ TYPE_FIELD_BITPOS (type, n) = SYMBOL_VALUE (xsym);
+ TYPE_FIELD_BITSIZE (type, n) = 0;
+ }
+ if (syms == osyms)
+ break;
+ }
+
+ 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> <format type>; <offset>; <nbits>
+ signed = u or s.
+ optional format type = c or b for char or boolean.
+ 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;
+ enum type_code code = TYPE_CODE_INT;
+
+ switch (**pp)
+ {
+ case 's':
+ signed_type = 1;
+ break;
+ case 'u':
+ signed_type = 0;
+ break;
+ default:
+ return error_type (pp, objfile);
+ }
+ (*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.
+ Boolean forms, e.g Fortran logical*X, put a b here. */
+
+ if (**pp == 'c')
+ (*pp)++;
+ else if (**pp == 'b')
+ {
+ code = TYPE_CODE_BOOL;
+ (*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, objfile);
+
+ /* The second number is always 0, so ignore it too. */
+ read_huge_number (pp, ';', &nbits);
+ if (nbits != 0)
+ return error_type (pp, objfile);
+
+ /* 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, objfile);
+ /* The type *should* end with a semicolon. If it are embedded
+ in a larger type the semicolon may be the only way to know where
+ the type ends. If this type is at the end of the stabstring we
+ can deal with the omitted semicolon (but we don't have to like
+ it). Don't bother to complain(), Sun's compiler omits the semicolon
+ for "void". */
+ if (**pp == ';')
+ ++(*pp);
+
+ if (type_bits == 0)
+ return init_type (TYPE_CODE_VOID, 1,
+ signed_type ? 0 : TYPE_FLAG_UNSIGNED, (char *)NULL,
+ objfile);
+ else
+ return init_type (code,
+ type_bits / TARGET_CHAR_BIT,
+ signed_type ? 0 : TYPE_FLAG_UNSIGNED, (char *)NULL,
+ objfile);
+}
+
+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, objfile);
+
+ /* 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, objfile);
+
+ 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_COMPLEX, 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++;
+ }
+
+ if (os9k_stabs)
+ upper_limit = ULONG_MAX / radix;
+ else
+ 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;
+{
+ char *orig_pp = *pp;
+ int rangenums[2];
+ long n2, n3;
+ int n2bits, n3bits;
+ int self_subrange;
+ struct type *result_type;
+ struct type *index_type = NULL;
+
+ /* First comes a type we are a subrange of.
+ In C it is usually 0, 1 or the type being defined. */
+ if (read_type_number (pp, rangenums) != 0)
+ return error_type (pp, objfile);
+ self_subrange = (rangenums[0] == typenums[0] &&
+ rangenums[1] == typenums[1]);
+
+ if (**pp == '=')
+ {
+ *pp = orig_pp;
+ index_type = read_type (pp, objfile);
+ }
+
+ /* 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, objfile);
+
+ if (index_type)
+ goto handle_true_range;
+
+ /* 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, objfile);
+ }
+
+ /* 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, 1, 0, NULL, objfile);
+
+ /* If n3 is zero and n2 is positive, we want a floating type, and n2
+ is the width in bytes.
+
+ Fortran programs appear to use this for complex types also. To
+ distinguish between floats and complex, g77 (and others?) seem
+ to use self-subranges for the complexes, and subranges of int for
+ the floats.
+
+ Also note that for complexes, g77 sets n2 to the size of one of
+ the member floats, not the whole complex beast. My guess is that
+ this was to work well with pre-COMPLEX versions of gdb. */
+
+ if (n3 == 0 && n2 > 0)
+ {
+ if (self_subrange)
+ {
+ return init_type (TYPE_CODE_COMPLEX, 2 * n2, 0, NULL, objfile);
+ }
+ else
+ {
+ 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);
+
+ else if (current_symbol && SYMBOL_LANGUAGE (current_symbol) == language_chill
+ && !self_subrange)
+ goto handle_true_range;
+
+ /* 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. */
+ handle_true_range:
+
+ if (self_subrange)
+ index_type = builtin_type_int;
+ else
+ 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, objfile);
+ 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));
+ /* Note: common_block_name already saved on symbol_obstack */
+ 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_TYPE (sym) = (struct type *) 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_TYPE (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. Need to do this here
+ as well as in check_typedef to deal with the (legitimate in
+ C though not C++) case of several types with the same name
+ in different source files. */
+ 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;
+
+ default:
+ {
+ 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, *rsym;
+ struct objfile *resolve_objfile;
+
+ /* SVR4 based linkers copy referenced global symbols from shared
+ libraries to the main executable.
+ If we are scanning the symbols for a shared library, try to resolve
+ them from the minimal symbols of the main executable first. */
+
+ if (symfile_objfile && objfile != symfile_objfile)
+ resolve_objfile = symfile_objfile;
+ else
+ resolve_objfile = objfile;
+
+ while (1)
+ {
+ /* Avoid expensive loop through all minimal symbols if there are
+ no unresolved symbols. */
+ for (hash = 0; hash < HASHSIZE; hash++)
+ {
+ if (global_sym_chain[hash])
+ break;
+ }
+ if (hash >= HASHSIZE)
+ return;
+
+ for (msymbol = resolve_objfile -> msymbols;
+ msymbol && SYMBOL_NAME (msymbol) != NULL;
+ msymbol++)
+ {
+ QUIT;
+
+ /* Skip static symbols. */
+ switch (MSYMBOL_TYPE (msymbol))
+ {
+ case mst_file_text:
+ case mst_file_data:
+ case mst_file_bss:
+ continue;
+ default:
+ break;
+ }
+
+ 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))
+ {
+
+ struct alias_list *aliases;
+
+ /* 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 has aliases, do minimal symbol fixups for each.
+ These live aliases/references weren't added to
+ global_sym_chain hash but may also need to be fixed up. */
+ /* FIXME: Maybe should have added aliases to the global chain, resolved symbol name, then treated aliases as normal
+ symbols? Still, we wouldn't want to add_to_list. */
+ /* Now do the same for each alias of this symbol */
+ rsym = sym;
+ aliases = SYMBOL_ALIASES (sym);
+ while (rsym)
+ {
+ if (SYMBOL_CLASS (rsym) == LOC_BLOCK)
+ {
+ fix_common_block (rsym,
+ SYMBOL_VALUE_ADDRESS (msymbol));
+ }
+ else
+ {
+ SYMBOL_VALUE_ADDRESS (rsym)
+ = SYMBOL_VALUE_ADDRESS (msymbol);
+ }
+ SYMBOL_SECTION (rsym) = SYMBOL_SECTION (msymbol);
+ if (aliases)
+ {
+ rsym = aliases->sym;
+ aliases = aliases->next;
+ }
+ else
+ rsym = NULL;
+ }
+
+
+ if (prev)
+ {
+ sym = SYMBOL_VALUE_CHAIN (prev);
+ }
+ else
+ {
+ sym = global_sym_chain[hash];
+ }
+ }
+ else
+ {
+ prev = sym;
+ sym = SYMBOL_VALUE_CHAIN (sym);
+ }
+ }
+ }
+ if (resolve_objfile == objfile)
+ break;
+ resolve_objfile = objfile;
+ }
+
+ /* Change the storage class of any remaining unresolved globals to
+ LOC_UNRESOLVED and remove them from the chain. */
+ for (hash = 0; hash < HASHSIZE; hash++)
+ {
+ sym = global_sym_chain[hash];
+ while (sym)
+ {
+ prev = sym;
+ sym = SYMBOL_VALUE_CHAIN (sym);
+
+ /* Change the symbol address from the misleading chain value
+ to address zero. */
+ SYMBOL_VALUE_ADDRESS (prev) = 0;
+
+ /* Complain about unresolved common block symbols. */
+ if (SYMBOL_CLASS (prev) == LOC_STATIC)
+ SYMBOL_CLASS (prev) = LOC_UNRESOLVED;
+ else
+ complain (&unresolved_sym_chain_complaint,
+ objfile -> name, SYMBOL_NAME (prev));
+ }
+ }
+ memset (global_sym_chain, 0, sizeof (global_sym_chain));
+}
+
+/* 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;
+
+ os9k_stabs = 0;
+}
+
+/* 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/gdb/stabsread.h b/gdb/stabsread.h
new file mode 100644
index 00000000000..77ea2912b85
--- /dev/null
+++ b/gdb/stabsread.h
@@ -0,0 +1,249 @@
+/* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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, and
+ the such LOC_BLOCK symbols use their fields in nonstandard ways. */
+
+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;
+
+};
+
+/* The table of header_files of this OBJFILE. */
+#define HEADER_FILES(OBJFILE) (DBX_SYMFILE_INFO (OBJFILE)->header_files)
+
+/* The actual length of HEADER_FILES. */
+#define N_HEADER_FILES(OBJFILE) (DBX_SYMFILE_INFO (OBJFILE)->n_header_files)
+
+/* The allocated lengh of HEADER_FILES. */
+#define N_ALLOCATED_HEADER_FILES(OBJFILE) \
+ (DBX_SYMFILE_INFO (OBJFILE)->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 == 0 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));
+
+
+EXTERN int os9k_stabs;
+
+/* COFF files can have multiple .stab sections, if they are linked
+ using --split-by-reloc. This linked list is used to pass the
+ information into the functions in dbxread.c. */
+struct stab_section_list
+{
+ /* Next in list. */
+ struct stab_section_list *next;
+
+ /* Stab section. */
+ asection *section;
+};
+
+/* Functions exported by dbxread.c. These are not in stabsread.c 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 *pst,
+ char **include_list,
+ int num_includes,
+ int capping_symbol_offset,
+ CORE_ADDR capping_text,
+ struct partial_symtab **dependency_list,
+ int number_dependencies,
+ int textlow_not_set));
+
+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 coffstab_build_psymtabs
+ PARAMS ((struct objfile *objfile,
+ struct section_offsets *section_offsets,
+ int mainline,
+ CORE_ADDR textaddr, unsigned int textsize,
+ struct stab_section_list *stabs,
+ file_ptr stabstroffset,
+ unsigned int stabstrsize));
+
+extern void stabsect_build_psymtabs
+ PARAMS ((struct objfile *objfile,
+ struct section_offsets *section_offsets,
+ int mainline,
+ char *stab_name,
+ char *stabstr_name,
+ char *text_name));
+
+extern void elfstab_offset_sections PARAMS ((struct objfile *,
+ struct partial_symtab *));
+
+extern void process_later
+ PARAMS ((struct symbol *, char *,
+ int (*f) PARAMS ((struct objfile *, struct symbol *, char *))));
+
+extern int symbol_reference_defined PARAMS ((char **));
+
+extern void ref_add PARAMS ((int, struct symbol *, char *, CORE_ADDR));
+
+extern struct symbol * ref_search PARAMS ((int));
+
+extern int resolve_cfront_continuation
+ PARAMS ((struct objfile * objfile, struct symbol * sym, char * p));
+
+#undef EXTERN
diff --git a/gdb/stack.c b/gdb/stack.c
new file mode 100644
index 00000000000..e36316e3229
--- /dev/null
+++ b/gdb/stack.c
@@ -0,0 +1,2019 @@
+/* Print and select stack frames for GDB, the GNU debugger.
+ Copyright 1986, 87, 89, 91, 92, 93, 94, 95, 96, 98, 1999
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include <ctype.h>
+#include "defs.h"
+#include "gdb_string.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"
+#include "annotate.h"
+#include "symfile.h"
+#include "objfiles.h"
+
+/* Prototypes for exported functions. */
+
+void args_info PARAMS ((char *, int));
+
+void locals_info PARAMS ((char *, int));
+
+void (*selected_frame_level_changed_hook) PARAMS ((int));
+
+void _initialize_stack PARAMS ((void));
+
+/* Prototypes for local functions. */
+
+static void return_command PARAMS ((char *, int));
+
+static void down_command PARAMS ((char *, int));
+
+static void down_silently_base PARAMS ((char *));
+
+static void down_silently_command PARAMS ((char *, int));
+
+static void up_command PARAMS ((char *, int));
+
+static void up_silently_base PARAMS ((char *));
+
+static void up_silently_command PARAMS ((char *, int));
+
+void frame_command PARAMS ((char *, int));
+
+static void select_frame_command PARAMS ((char *, int));
+
+static void print_frame_arg_vars PARAMS ((struct frame_info *, GDB_FILE *));
+
+static void catch_info PARAMS ((char *, int));
+
+static void args_plus_locals_info PARAMS ((char *, int));
+
+static void print_frame_label_vars PARAMS ((struct frame_info *,
+ int,
+ GDB_FILE *));
+
+static void print_frame_local_vars PARAMS ((struct frame_info *,
+ int,
+ GDB_FILE *));
+
+static int print_block_frame_labels PARAMS ((struct block *, int *,
+ GDB_FILE *));
+
+static int print_block_frame_locals PARAMS ((struct block *,
+ struct frame_info *,
+ int,
+ GDB_FILE *));
+
+static void print_frame_info_base PARAMS ((struct frame_info *, int, int, int));
+
+static void print_stack_frame_base PARAMS ((struct frame_info *, int, int));
+
+static void backtrace_command PARAMS ((char *, int));
+
+struct frame_info *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. */
+
+struct frame_info *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;
+
+/* Zero means do things normally; we are interacting directly with the
+ user. One means print the full filename and linenumber when a
+ frame is printed, and do so in a format emacs18/emacs19.22 can
+ parse. Two means print similar annotations, but in many more
+ cases and in a slightly different syntax. */
+
+int annotation_level = 0;
+
+
+struct print_stack_frame_args {
+ struct frame_info *fi;
+ int level;
+ int source;
+ int args;
+};
+
+static int print_stack_frame_base_stub PARAMS ((char *));
+
+/* Show and print the frame arguments.
+ Pass the args the way catch_errors wants them. */
+static int
+show_and_print_stack_frame_stub (args)
+ char *args;
+{
+ struct print_stack_frame_args *p = (struct print_stack_frame_args *)args;
+
+ /* Reversed order of these so tuiDo() doesn't occur
+ * in the middle of "Breakpoint 1 ... [location]" printing = RT
+ */
+ if (tui_version)
+ print_frame_info_base (p->fi, p->level, p->source, p->args);
+ print_frame_info (p->fi, p->level, p->source, p->args);
+
+ return 0;
+}
+
+/* Show or print the frame arguments.
+ 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;
+
+ if (tui_version)
+ print_frame_info (p->fi, p->level, p->source, p->args);
+ else
+ print_frame_info_base (p->fi, p->level, p->source, p->args);
+ return 0;
+}
+
+/* Print a stack frame briefly. FRAME_INFI should be the frame info
+ and LEVEL should be its level in the stack (or -1 for level not
+ defined). */
+
+/* Pass the args the way catch_errors wants them. */
+static int
+print_stack_frame_base_stub (args)
+ char *args;
+{
+ struct print_stack_frame_args *p = (struct print_stack_frame_args *)args;
+
+ print_frame_info_base (p->fi, p->level, p->source, p->args);
+ return 0;
+}
+
+/* print the frame arguments to the terminal.
+ Pass the args the way catch_errors wants them. */
+static int
+print_only_stack_frame_stub (args)
+ char *args;
+{
+ struct print_stack_frame_args *p = (struct print_stack_frame_args *)args;
+
+ print_frame_info_base (p->fi, p->level, p->source, p->args);
+ return 0;
+}
+
+/* Print a stack frame briefly. FRAME_INFI should be the frame info
+ 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_base (fi, level, source)
+ struct frame_info *fi;
+ int level;
+ int source;
+{
+ struct print_stack_frame_args args;
+
+ args.fi = fi;
+ args.level = level;
+ args.source = source;
+ args.args = 1;
+
+ catch_errors (print_stack_frame_stub, (char *)&args, "", RETURN_MASK_ALL);
+}
+
+/* Show and print a stack frame briefly. FRAME_INFI should be the frame info
+ 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
+show_and_print_stack_frame (fi, level, source)
+ struct frame_info *fi;
+ int level;
+ int source;
+{
+ struct print_stack_frame_args args;
+
+ args.fi = fi;
+ args.level = level;
+ args.source = source;
+ args.args = 1;
+
+ catch_errors (show_and_print_stack_frame_stub, (char *)&args, "", RETURN_MASK_ALL);
+}
+
+
+/* Show or print a stack frame briefly. FRAME_INFI should be the frame info
+ 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 (fi, level, source)
+ struct frame_info *fi;
+ int level;
+ int source;
+{
+ struct print_stack_frame_args args;
+
+ args.fi = fi;
+ args.level = level;
+ args.source = source;
+ args.args = 1;
+
+ catch_errors (print_stack_frame_stub, (char *)&args, "", RETURN_MASK_ALL);
+}
+
+/* Print a stack frame briefly. FRAME_INFI should be the frame info
+ 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_only_stack_frame (fi, level, source)
+ struct frame_info *fi;
+ int level;
+ int source;
+{
+ struct print_stack_frame_args args;
+
+ args.fi = fi;
+ args.level = level;
+ args.source = source;
+ args.args = 1;
+
+ catch_errors (print_only_stack_frame_stub,
+ (char *)&args, "", RETURN_MASK_ALL);
+}
+
+struct print_args_args {
+ struct symbol *func;
+ struct frame_info *fi;
+};
+
+static int print_args_stub PARAMS ((PTR));
+
+/* Pass the args the way catch_errors wants them. */
+
+static int
+print_args_stub (args)
+ PTR 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, gdb_stdout);
+ return 0;
+}
+
+/* Print information about a frame for frame "fi" at level "level".
+ * Used in "where" output, also used to emit breakpoint or step messages.
+ * LEVEL is the level of the frame, or -1 if it is the innermost frame
+ * but we don't want to print the level.
+ * The meaning of the SOURCE argument is:
+ * -1: Print only source line
+ * 0: Print only location
+ * 1: Print location and source line
+ */
+
+static void
+print_frame_info_base (fi, level, source, args)
+ struct frame_info *fi;
+ int level;
+ int source;
+ int args;
+{
+ struct symtab_and_line sal;
+ struct symbol *func;
+ register char *funname = 0;
+ enum language funlang = language_unknown;
+
+#if 0
+ char buf[MAX_REGISTER_RAW_SIZE];
+ CORE_ADDR sp;
+
+ /* On the 68k, this spends too much time in m68k_find_saved_regs. */
+
+ /* 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))
+#else
+ if (frame_in_dummy (fi))
+#endif
+ {
+ annotate_frame_begin (level == -1 ? 0 : level, fi->pc);
+
+ /* Do this regardless of SOURCE because we don't have any source
+ to list for this frame. */
+ if (level >= 0)
+ printf_filtered ("#%-2d ", level);
+ annotate_function_call ();
+ printf_filtered ("<function called from gdb>\n");
+ annotate_frame_end ();
+ return;
+ }
+ if (fi->signal_handler_caller)
+ {
+ annotate_frame_begin (level == -1 ? 0 : level, fi->pc);
+
+ /* Do this regardless of SOURCE because we don't have any source
+ to list for this frame. */
+ if (level >= 0)
+ printf_filtered ("#%-2d ", level);
+ annotate_signal_handler_caller ();
+ printf_filtered ("<signal handler called>\n");
+ annotate_frame_end ();
+ 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 or a dummy 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
+ && !frame_in_dummy (fi->next));
+
+ 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))))
+ {
+#if 0
+ /* There is no particular reason to think the line number
+ information is wrong. Someone might have just put in
+ a label with asm() but left the line numbers alone. */
+ /* In this case we have no way of knowing the source file
+ and line number, so don't print them. */
+ sal.symtab = 0;
+#endif
+ /* 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
+ {
+ /* I'd like to use SYMBOL_SOURCE_NAME() here, to display
+ * the demangled name that we already have stored in
+ * the symbol table, but we stored a version with
+ * DMGL_PARAMS turned on, and here we don't want
+ * to display parameters. So call the demangler again,
+ * with DMGL_ANSI only. RT
+ * (Yes, I know that printf_symbol_filtered() will
+ * again try to demangle the name on the fly, but
+ * the issue is that if cplus_demangle() fails here,
+ * it'll fail there too. So we want to catch the failure
+ * ("demangled==NULL" case below) here, while we still
+ * have our hands on the function symbol.)
+ */
+ char * demangled;
+ funname = SYMBOL_NAME (func);
+ funlang = SYMBOL_LANGUAGE (func);
+ if (funlang == language_cplus) {
+ demangled = cplus_demangle (funname, DMGL_ANSI);
+ if (demangled == NULL)
+ /* If the demangler fails, try the demangled name
+ * from the symbol table. This'll have parameters,
+ * but that's preferable to diplaying a mangled name.
+ */
+ funname = SYMBOL_SOURCE_NAME (func);
+ }
+ }
+ }
+ else
+ {
+ 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)
+ {
+ annotate_frame_begin (level == -1 ? 0 : level, fi->pc);
+
+ if (level >= 0)
+ printf_filtered ("#%-2d ", level);
+ if (addressprint)
+ if (fi->pc != sal.pc || !sal.symtab)
+ {
+ annotate_frame_address ();
+ print_address_numeric (fi->pc, 1, gdb_stdout);
+ annotate_frame_address_end ();
+ printf_filtered (" in ");
+ }
+ annotate_frame_function_name ();
+ fprintf_symbol_filtered (gdb_stdout, funname ? funname : "??", funlang,
+ DMGL_ANSI);
+ wrap_here (" ");
+ annotate_frame_args ();
+ fputs_filtered (" (", gdb_stdout);
+ if (args)
+ {
+ struct print_args_args args;
+ args.fi = fi;
+ args.func = func;
+ catch_errors (print_args_stub, &args, "", RETURN_MASK_ALL);
+ QUIT;
+ }
+ printf_filtered (")");
+ if (sal.symtab && sal.symtab->filename)
+ {
+ annotate_frame_source_begin ();
+ wrap_here (" ");
+ printf_filtered (" at ");
+ annotate_frame_source_file ();
+ printf_filtered ("%s", sal.symtab->filename);
+ annotate_frame_source_file_end ();
+ printf_filtered (":");
+ annotate_frame_source_line ();
+ printf_filtered ("%d", sal.line);
+ annotate_frame_source_end ();
+ }
+
+#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)
+ {
+ annotate_frame_where ();
+ wrap_here (" ");
+ printf_filtered (" from %s", PC_LOAD_SEGMENT (fi->pc));
+ }
+#endif
+#ifdef PC_SOLIB
+ if (!funname || (!sal.symtab || !sal.symtab->filename))
+ {
+ char *lib = PC_SOLIB (fi->pc);
+ if (lib)
+ {
+ annotate_frame_where ();
+ wrap_here (" ");
+ printf_filtered (" from %s", lib);
+ }
+ }
+#endif
+ printf_filtered ("\n");
+ }
+
+ if ((source != 0) && sal.symtab)
+ {
+ int done = 0;
+ int mid_statement = source < 0 && fi->pc != sal.pc;
+ if (annotation_level)
+ done = identify_source_line (sal.symtab, sal.line, mid_statement,
+ fi->pc);
+ if (!done)
+ {
+ if (addressprint && mid_statement && !tui_version)
+ {
+ print_address_numeric (fi->pc, 1, gdb_stdout);
+ printf_filtered ("\t");
+ }
+ if (print_frame_info_listing_hook)
+ print_frame_info_listing_hook (sal.symtab, sal.line, sal.line + 1, 0);
+ else if (!tui_version)
+ 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);
+
+ annotate_frame_end ();
+
+ gdb_flush (gdb_stdout);
+}
+
+
+void
+stack_publish_stopped_with_no_frame()
+{
+ TUIDO(((TuiOpaqueFuncPtr)tuiUpdateOnEnd));
+
+ return;
+}
+
+/* Show or print the frame info. If this is the tui, it will be shown in
+ the source display */
+void
+print_frame_info(fi, level, source, args)
+ struct frame_info *fi;
+ register int level;
+ int source;
+ int args;
+{
+ if (!tui_version)
+ print_frame_info_base(fi, level, source, args);
+ else
+ {
+ if (fi && (frame_in_dummy(fi) || fi->signal_handler_caller))
+ print_frame_info_base(fi, level, source, args);
+ else
+ {
+ TUIDO(((TuiOpaqueFuncPtr)tui_vShowFrameInfo, fi));
+ }
+ }
+}
+
+/* Show the frame info. If this is the tui, it will be shown in
+ the source display otherwise, nothing is done */
+void
+show_stack_frame(fi)
+ struct frame_info *fi;
+{
+ TUIDO(((TuiOpaqueFuncPtr)tui_vShowFrameInfo, fi));
+}
+
+
+/* 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). */
+
+struct frame_info *
+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];
+ struct frame_info *fid =
+ find_relative_frame (get_current_frame (), &level);
+ struct frame_info *tfid;
+
+ if (level == 0)
+ /* find_relative_frame was successful */
+ return fid;
+
+ /* If SETUP_ARBITRARY_FRAME is defined, then frame specifications
+ take at least 2 addresses. It is important to detect this case
+ here so that "frame 100" does not give a confusing error message
+ like "frame specification requires two addresses". This of course
+ does not solve the "frame 100" problem for machines on which
+ a frame specification can be made with one address. To solve
+ that, we need a new syntax for a specifying a frame by address.
+ I think the cleanest syntax is $frame(0x45) ($frame(0x23,0x45) for
+ two args, etc.), but people might think that is too much typing,
+ so I guess *0x23,0x45 would be a possible alternative (commas
+ really should be used instead of spaces to delimit; using spaces
+ normally works in an expression). */
+#ifdef SETUP_ARBITRARY_FRAME
+ error ("No frame %d", args[0]);
+#endif
+
+ /* 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 && fid->frame != args[0];
+ fid = get_prev_frame (fid))
+ ;
+
+ if (fid)
+ while ((tfid = get_prev_frame (fid)) &&
+ (tfid->frame == args[0]))
+ fid = tfid;
+
+ /* We couldn't identify the frame as an existing frame, but
+ perhaps we can create one with a single argument. */
+ }
+
+ 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;
+{
+ struct frame_info *fi;
+ struct symtab_and_line sal;
+ struct symbol *func;
+ struct symtab *s;
+ struct frame_info *calling_frame_info;
+ int i, count, numregs;
+ char *funname = 0;
+ enum language funlang = language_unknown;
+
+ if (!target_has_stack)
+ error ("No stack.");
+
+ fi = parse_frame_specification (addr_exp);
+ if (fi == NULL)
+ error ("Invalid frame specified.");
+
+ sal = find_pc_line (fi->pc,
+ fi->next != NULL
+ && !fi->next->signal_handler_caller
+ && !frame_in_dummy (fi->next));
+ func = get_frame_function (fi);
+ s = find_pc_symtab(fi->pc);
+ if (func)
+ {
+ /* I'd like to use SYMBOL_SOURCE_NAME() here, to display
+ * the demangled name that we already have stored in
+ * the symbol table, but we stored a version with
+ * DMGL_PARAMS turned on, and here we don't want
+ * to display parameters. So call the demangler again,
+ * with DMGL_ANSI only. RT
+ * (Yes, I know that printf_symbol_filtered() will
+ * again try to demangle the name on the fly, but
+ * the issue is that if cplus_demangle() fails here,
+ * it'll fail there too. So we want to catch the failure
+ * ("demangled==NULL" case below) here, while we still
+ * have our hands on the function symbol.)
+ */
+ char * demangled;
+ funname = SYMBOL_NAME (func);
+ funlang = SYMBOL_LANGUAGE (func);
+ if (funlang == language_cplus)
+ {
+ demangled = cplus_demangle (funname, DMGL_ANSI);
+ /* If the demangler fails, try the demangled name
+ * from the symbol table. This'll have parameters,
+ * but that's preferable to diplaying a mangled name.
+ */
+ if (demangled == NULL)
+ funname = SYMBOL_SOURCE_NAME (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_info = get_prev_frame (fi);
+
+ if (!addr_exp && selected_frame_level >= 0)
+ {
+ printf_filtered ("Stack level %d, frame at ", selected_frame_level);
+ print_address_numeric (fi->frame, 1, gdb_stdout);
+ printf_filtered (":\n");
+ }
+ else
+ {
+ printf_filtered ("Stack frame at ");
+ print_address_numeric (fi->frame, 1, gdb_stdout);
+ printf_filtered (":\n");
+ }
+ printf_filtered (" %s = ", REGISTER_NAME (PC_REGNUM));
+ print_address_numeric (fi->pc, 1, gdb_stdout);
+
+ wrap_here (" ");
+ if (funname)
+ {
+ printf_filtered (" in ");
+ fprintf_symbol_filtered (gdb_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 ", REGISTER_NAME (PC_REGNUM));
+ print_address_numeric (FRAME_SAVED_PC (fi), 1, gdb_stdout);
+ printf_filtered ("\n");
+
+ {
+ int frameless = 0;
+#ifdef FRAMELESS_FUNCTION_INVOCATION
+ FRAMELESS_FUNCTION_INVOCATION (fi, frameless);
+#endif
+ if (frameless)
+ printf_filtered (" (FRAMELESS),");
+ }
+
+ if (calling_frame_info)
+ {
+ printf_filtered (" called by frame at ");
+ print_address_numeric (calling_frame_info->frame, 1, gdb_stdout);
+ }
+ if (fi->next && calling_frame_info)
+ puts_filtered (",");
+ wrap_here (" ");
+ if (fi->next)
+ {
+ printf_filtered (" caller of frame at ");
+ print_address_numeric (fi->next->frame, 1, gdb_stdout);
+ }
+ if (fi->next || calling_frame_info)
+ 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 ");
+ print_address_numeric (arg_list, 1, gdb_stdout);
+ printf_filtered (",");
+
+ 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, gdb_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 ");
+ print_address_numeric (arg_list, 1, gdb_stdout);
+ printf_filtered (",");
+ }
+ }
+
+ FRAME_INIT_SAVED_REGS (fi);
+ if (fi->saved_regs != NULL)
+ {
+ /* 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 ");
+ print_address_numeric (fi->saved_regs[SP_REGNUM], 1, gdb_stdout);
+ printf_filtered ("\n");
+ count = 0;
+ numregs = ARCH_NUM_REGS;
+ for (i = 0; i < numregs; i++)
+ if (fi->saved_regs[i] && i != SP_REGNUM)
+ {
+ if (count == 0)
+ puts_filtered (" Saved registers:\n ");
+ else
+ puts_filtered (",");
+ wrap_here (" ");
+ printf_filtered (" %s at ", REGISTER_NAME (i));
+ print_address_numeric (fi->saved_regs[i], 1, gdb_stdout);
+ count++;
+ }
+ if (count)
+ puts_filtered ("\n");
+ }
+ else
+ {
+ /* We could get some information about saved registers by
+ calling get_saved_register on each register. Which info goes
+ with which frame is necessarily lost, however, and I suspect
+ that the users don't care whether they get the info. */
+ puts_filtered ("\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_unfiltered ("Backtrace limit: %d.\n", backtrace_limit);
+}
+#endif
+
+/* Print briefly all stack frames or just the innermost COUNT frames. */
+
+static void
+backtrace_command_1 (count_exp, show_locals, from_tty)
+ char *count_exp;
+ int show_locals;
+ int from_tty;
+{
+ struct frame_info *fi;
+ register int count;
+ register int i;
+ register struct frame_info *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)
+ {
+ struct frame_info *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 (fi = trailing;
+ fi != NULL && i--;
+ fi = get_prev_frame (fi))
+ {
+ QUIT;
+ ps = find_pc_psymtab (fi->pc);
+ if (ps)
+ PSYMTAB_TO_SYMTAB (ps); /* Force syms to come in */
+ }
+ }
+
+ for (i = 0, fi = trailing;
+ fi && count--;
+ i++, fi = get_prev_frame (fi))
+ {
+ QUIT;
+
+ /* 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_base (fi, trailing_level + i, 0, 1);
+ if (show_locals)
+ print_frame_local_vars(fi, 1, gdb_stdout);
+ }
+
+ /* If we've stopped before the end, mention that. */
+ if (fi && from_tty)
+ printf_filtered ("(More stack frames follow...)\n");
+}
+
+static void
+backtrace_command (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ struct cleanup *old_chain = (struct cleanup *)NULL;
+ char **argv = (char **)NULL;
+ int argIndicatingFullTrace = (-1), totArgLen = 0, argc = 0;
+ char *argPtr = arg;
+
+ if (arg != (char *)NULL)
+ {
+ int i;
+
+ argv = buildargv(arg);
+ old_chain = make_cleanup ((make_cleanup_func) freeargv, (char *)argv);
+ argc = 0;
+ for (i = 0; (argv[i] != (char *)NULL); i++)
+ {
+ int j;
+
+ for (j = 0; (j < strlen(argv[i])); j++)
+ argv[i][j] = tolower(argv[i][j]);
+
+ if (argIndicatingFullTrace < 0 && subsetCompare(argv[i], "full"))
+ argIndicatingFullTrace = argc;
+ else
+ {
+ argc++;
+ totArgLen += strlen(argv[i]);
+ }
+ }
+ totArgLen += argc;
+ if (argIndicatingFullTrace >= 0)
+ {
+ if (totArgLen > 0)
+ {
+ argPtr = (char *)xmalloc(totArgLen + 1);
+ if (!argPtr)
+ nomem(0);
+ else
+ {
+ memset(argPtr, 0, totArgLen + 1);
+ for (i = 0; (i < (argc + 1)); i++)
+ {
+ if (i != argIndicatingFullTrace)
+ {
+ strcat(argPtr, argv[i]);
+ strcat(argPtr, " ");
+ }
+ }
+ }
+ }
+ else
+ argPtr = (char *)NULL;
+ }
+ }
+
+ backtrace_command_1 (argPtr, (argIndicatingFullTrace >= 0), from_tty);
+
+ if (argIndicatingFullTrace >= 0 && totArgLen > 0)
+ free(argPtr);
+
+ if (old_chain)
+ do_cleanups(old_chain);
+}
+
+static void
+backtrace_full_command (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ backtrace_command_1 (arg, 1, from_tty);
+}
+
+
+/* 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, fi, num_tabs, stream)
+ struct block *b;
+ register struct frame_info *fi;
+ int num_tabs;
+ register GDB_FILE *stream;
+{
+ int nsyms;
+ register int i, j;
+ register struct symbol *sym;
+ register int values_printed = 0;
+
+ nsyms = BLOCK_NSYMS (b);
+
+ for (i = 0; i < nsyms; i++)
+ {
+ sym = BLOCK_SYM (b, i);
+ switch (SYMBOL_CLASS (sym))
+ {
+ case LOC_LOCAL:
+ case LOC_REGISTER:
+ case LOC_STATIC:
+ case LOC_BASEREG:
+ values_printed = 1;
+ for (j = 0; j < num_tabs; j++)
+ fputs_filtered("\t", stream);
+ fputs_filtered (SYMBOL_SOURCE_NAME (sym), stream);
+ fputs_filtered (" = ", stream);
+ print_variable_value (sym, fi, stream);
+ fprintf_filtered (stream, "\n");
+ break;
+
+ default:
+ /* Ignore symbols which are not locals. */
+ break;
+ }
+ }
+ return values_printed;
+}
+
+/* Same, but print labels. */
+
+static int
+print_block_frame_labels (b, have_default, stream)
+ struct block *b;
+ int *have_default;
+ register GDB_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, " ");
+ print_address_numeric (SYMBOL_VALUE_ADDRESS (sym), 1, stream);
+ }
+ 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 (fi, num_tabs, stream)
+ register struct frame_info *fi;
+ register int num_tabs;
+ register GDB_FILE *stream;
+{
+ register struct block *block = get_frame_block (fi);
+ 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, fi, num_tabs, 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 (fi, this_level_only, stream)
+ register struct frame_info *fi;
+ int this_level_only;
+ register GDB_FILE *stream;
+{
+ register struct blockvector *bl;
+ register struct block *block = get_frame_block (fi);
+ register int values_printed = 0;
+ int index, have_default = 0;
+ char *blocks_printed;
+ 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 */
+void
+locals_info (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ if (!selected_frame)
+ error ("No frame selected.");
+ print_frame_local_vars (selected_frame, 0, gdb_stdout);
+}
+
+static void
+catch_info (ignore, from_tty)
+ char *ignore;
+ int from_tty;
+{
+ struct symtab_and_line * sal;
+
+ /* Check for target support for exception handling */
+ sal = target_enable_exception_callback (EX_EVENT_CATCH, 1);
+ if (sal)
+ {
+ /* Currently not handling this */
+ /* Ideally, here we should interact with the C++ runtime
+ system to find the list of active handlers, etc. */
+ fprintf_filtered (gdb_stdout, "Info catch not supported with this target/compiler combination.\n");
+#if 0
+ if (!selected_frame)
+ error ("No frame selected.");
+#endif
+ }
+ else
+ {
+ /* Assume g++ compiled code -- old v 4.16 behaviour */
+ if (!selected_frame)
+ error ("No frame selected.");
+
+ print_frame_label_vars (selected_frame, 0, gdb_stdout);
+ }
+}
+
+static void
+print_frame_arg_vars (fi, stream)
+ register struct frame_info *fi;
+ register GDB_FILE *stream;
+{
+ struct symbol *func = get_frame_function (fi);
+ 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, fi, 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");
+ }
+}
+
+void
+args_info (ignore, from_tty)
+ char *ignore;
+ int from_tty;
+{
+ if (!selected_frame)
+ error ("No frame selected.");
+ print_frame_arg_vars (selected_frame, gdb_stdout);
+}
+
+
+static void
+args_plus_locals_info (ignore, from_tty)
+ char *ignore;
+ int from_tty;
+{
+ args_info(ignore, from_tty);
+ locals_info(ignore, from_tty);
+}
+
+
+/* Select frame FI, and note that its stack level is LEVEL.
+ LEVEL may be -1 if an actual level number is not known. */
+
+void
+select_frame (fi, level)
+ struct frame_info *fi;
+ int level;
+{
+ register struct symtab *s;
+
+ selected_frame = fi;
+ selected_frame_level = level;
+ if (selected_frame_level_changed_hook)
+ selected_frame_level_changed_hook (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 (fi)
+ {
+ s = find_pc_symtab (fi->pc);
+ if (s
+ && s->language != current_language->la_language
+ && s->language != language_unknown
+ && language_mode == language_mode_auto) {
+ set_language(s->language);
+ }
+ /* elz: this if here fixes the problem with the pc not being displayed
+ in the tui asm layout, with no debug symbols. The value of s
+ would be 0 here, and select_source_symtab would abort the
+ command by calling the 'error' function*/
+ if (s)
+ {
+ TUIDO(((TuiOpaqueFuncPtr)tui_vSelectSourceSymtab, s));
+ }
+ }
+}
+
+
+/* Select frame FI, noting that its stack level is LEVEL. Also print
+ the stack frame and show the source if this is the tui version. */
+void
+select_and_print_frame(fi, level)
+ struct frame_info *fi;
+ int level;
+{
+ select_frame(fi, level);
+ if (fi)
+ {
+ print_stack_frame(fi, level, 1);
+ TUIDO(((TuiOpaqueFuncPtr)tui_vCheckDataValues, fi));
+ }
+}
+
+
+/* Select frame FI, noting that its stack level is LEVEL. Be silent if
+ not the TUI */
+void
+select_and_maybe_print_frame (fi, level)
+ struct frame_info *fi;
+ int level;
+{
+ if (!tui_version)
+ select_frame(fi, level);
+ else
+ select_and_print_frame(fi, level);
+}
+
+
+/* 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)
+ CORE_ADDR *frameaddrp;
+ int *levelp;
+{
+ *frameaddrp = selected_frame ? selected_frame->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. */
+
+struct frame_info *
+find_relative_frame (frame, level_offset_ptr)
+ register struct frame_info *frame;
+ register int *level_offset_ptr;
+{
+ register struct frame_info *prev;
+ register struct frame_info *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 struct frame_info *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. */
+
+void
+frame_command (level_exp, from_tty)
+ char *level_exp;
+ int from_tty;
+{
+ select_frame_command (level_exp, from_tty);
+ show_and_print_stack_frame (selected_frame, selected_frame_level, 1);
+}
+
+/* The XDB Compatibility command to print the current frame. */
+
+void
+current_frame_command (level_exp, from_tty)
+ char *level_exp;
+ int from_tty;
+{
+ if (target_has_stack == 0 || selected_frame == 0)
+ error ("No stack.");
+ print_only_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_base (count_exp)
+ char *count_exp;
+{
+ register struct frame_info *fi;
+ 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.");
+
+ fi = find_relative_frame (selected_frame, &count1);
+ if (count1 != 0 && count_exp == 0)
+ error ("Initial frame selected; you cannot go up.");
+ select_frame (fi, selected_frame_level + count - count1);
+}
+
+static void
+up_silently_command (count_exp, from_tty)
+ char *count_exp;
+ int from_tty;
+{
+ up_silently_base(count_exp);
+ if (tui_version)
+ print_stack_frame (selected_frame, selected_frame_level, 1);
+}
+
+static void
+up_command (count_exp, from_tty)
+ char *count_exp;
+ int from_tty;
+{
+ up_silently_base (count_exp);
+ show_and_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_base (count_exp)
+ char *count_exp;
+{
+ register struct frame_info *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)
+ {
+
+ /* We only do this if count_exp is not specified. That way "down"
+ means to really go down (and let me know if that is
+ impossible), but "down 9999" can be used to mean go all the way
+ down without getting an error. */
+
+ error ("Bottom (i.e., innermost) frame selected; you cannot go down.");
+ }
+
+ select_frame (frame, selected_frame_level + count - count1);
+}
+
+/* ARGSUSED */
+static void
+down_silently_command (count_exp, from_tty)
+ char *count_exp;
+ int from_tty;
+{
+ down_silently_base (count_exp);
+ if (tui_version)
+ print_stack_frame (selected_frame, selected_frame_level, 1);
+}
+
+static void
+down_command (count_exp, from_tty)
+ char *count_exp;
+ int from_tty;
+{
+ down_silently_base (count_exp);
+ show_and_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;
+ CORE_ADDR selected_frame_addr;
+ CORE_ADDR selected_frame_pc;
+ struct frame_info *frame;
+ value_ptr 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 = selected_frame->pc;
+
+ /* Compute the return value (if any -- possibly getting errors here). */
+
+ if (retval_exp)
+ {
+ struct type *return_type = NULL;
+
+ return_value = parse_and_eval (retval_exp);
+
+ /* Cast return value to the return type of the function. */
+ if (thisfun != NULL)
+ return_type = TYPE_TARGET_TYPE (SYMBOL_TYPE (thisfun));
+ if (return_type == NULL)
+ return_type = builtin_type_int;
+ return_value = value_cast (return_type, return_value);
+
+ /* 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 = get_current_frame())->frame
+ || selected_frame_pc != 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);
+ else
+ select_frame_command ("0", 0);
+}
+
+/* Sets the scope to input function name, provided that the
+ function is within the current stack frame */
+
+struct function_bounds
+{
+ CORE_ADDR low, high;
+};
+
+static void
+func_command (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ struct frame_info *fp;
+ int found = 0;
+ struct symtabs_and_lines sals;
+ int i;
+ int level = 1;
+ struct function_bounds *func_bounds = (struct function_bounds *) NULL;
+
+ if (arg != (char *) NULL)
+ return;
+
+ fp = parse_frame_specification ("0");
+ sals = decode_line_spec (arg, 1);
+ func_bounds = (struct function_bounds *) xmalloc (
+ sizeof (struct function_bounds) * sals.nelts);
+ for (i = 0; (i < sals.nelts && !found); i++)
+ {
+ if (sals.sals[i].pc == (CORE_ADDR) 0 ||
+ find_pc_partial_function (sals.sals[i].pc,
+ (char **) NULL,
+ &func_bounds[i].low,
+ &func_bounds[i].high) == 0)
+ {
+ func_bounds[i].low =
+ func_bounds[i].high = (CORE_ADDR) NULL;
+ }
+ }
+
+ do
+ {
+ for (i = 0; (i < sals.nelts && !found); i++)
+ found = (fp->pc >= func_bounds[i].low &&
+ fp->pc < func_bounds[i].high);
+ if (!found)
+ {
+ level = 1;
+ fp = find_relative_frame (fp, &level);
+ }
+ }
+ while (!found && level == 0);
+
+ if (func_bounds)
+ free (func_bounds);
+
+ if (!found)
+ printf_filtered ("'%s' not within current stack frame.\n", arg);
+ else if (fp != selected_frame)
+ select_and_print_frame (fp, level);
+}
+
+/* Gets the language of the current frame. */
+
+enum language
+get_frame_language ()
+{
+ register struct symtab *s;
+ enum language flang; /* The language of the current frame */
+
+ if (selected_frame)
+ {
+ s = find_pc_symtab(selected_frame->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);
+
+ if (xdb_commands)
+ {
+ add_com("L", class_stack, current_frame_command,
+ "Print the current stack frame.\n");
+ add_com_alias ("V", "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.\n\
+Use of the 'full' qualifier also prints the values of the local variables.\n");
+ add_com_alias ("bt", "backtrace", class_stack, 0);
+ if (xdb_commands)
+ {
+ add_com_alias ("t", "backtrace", class_stack, 0);
+ add_com ("T", class_stack, backtrace_full_command,
+ "Print backtrace of all stack frames, or innermost COUNT frames \n\
+and the values of the local variables.\n\
+With a negative argument, print outermost -COUNT frames.\n\
+Usage: T <count>\n");
+ }
+
+ 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 (xdb_commands)
+ add_com("l", class_info, args_plus_locals_info,
+ "Argument and local variables of current stack frame.");
+
+ if (dbx_commands)
+ add_com("func", class_stack, func_command,
+ "Select the stack frame that contains <func>.\nUsage: func <name>\n");
+
+ add_info ("catch", catch_info,
+ "Exceptions that can be caught in the current stack frame.");
+
+#if 0
+ add_cmd ("backtrace-limit", class_stack, set_backtrace_limit_command,
+ "Specify maximum number of frames for \"backtrace\" to print by default.",
+ &setlist);
+ add_info ("backtrace-limit", backtrace_limit_info,
+ "The maximum number of frames for \"backtrace\" to print by default.");
+#endif
+}
diff --git a/gdb/standalone.c b/gdb/standalone.c
new file mode 100644
index 00000000000..13fc4768b4e
--- /dev/null
+++ b/gdb/standalone.c
@@ -0,0 +1,593 @@
+/* Interface to bare machine for GDB running as kernel debugger.
+ Copyright (C) 1986, 1989, 1991 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include <stdio.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+#include <sys/types.h>
+#include "gdb_stat.h"
+
+#if defined (SIGTSTP) && defined (SIGIO)
+#include <sys/time.h>
+#include <sys/resource.h>
+#endif /* SIGTSTP and SIGIO defined (must be 4.2) */
+
+#include "defs.h"
+#include "signals.h"
+#include "symtab.h"
+#include "frame.h"
+#include "inferior.h"
+#include "wait.h"
+
+
+/* Random system calls, mostly no-ops to prevent link problems */
+
+ioctl (desc, code, arg)
+{}
+
+int (* signal ()) ()
+{}
+
+kill ()
+{}
+
+getpid ()
+{
+ return 0;
+}
+
+sigsetmask ()
+{}
+
+chdir ()
+{}
+
+char *
+getcwd (buf, len)
+ char *buf;
+ unsigned int len;
+{
+ buf[0] = '/';
+ buf[1] = 0;
+ return buf;
+}
+
+/* Used to check for existence of .gdbinit. Say no. */
+
+access ()
+{
+ return -1;
+}
+
+exit ()
+{
+ error ("Fatal error; restarting.");
+}
+
+/* Reading "files". The contents of some files are written into kdb's
+ data area before it is run. These files are used to contain the
+ symbol table for kdb to load, and the source files (in case the
+ kdb user wants to print them). The symbols are stored in a file
+ named "kdb-symbols" in a.out format (except that all the text and
+ data have been stripped to save room).
+
+ The files are stored in the following format:
+ int number of bytes of data for this file, including these four.
+ char[] name of the file, ending with a null.
+ padding to multiple of 4 boundary.
+ char[] file contents. The length can be deduced from what was
+ specified before. There is no terminating null here.
+
+ If the int at the front is zero, it means there are no more files.
+
+ Opening a file in kdb returns a nonzero value to indicate success,
+ but the value does not matter. Only one file can be open, and only
+ for reading. All the primitives for input from the file know
+ which file is open and ignore what is specified for the descriptor
+ or for the stdio stream.
+
+ Input with fgetc can be done either on the file that is open
+ or on stdin (which reads from the terminal through tty_input () */
+
+/* Address of data for the files stored in format described above. */
+char *files_start;
+
+/* The file stream currently open: */
+
+char *sourcebeg; /* beginning of contents */
+int sourcesize; /* size of contents */
+char *sourceptr; /* current read pointer */
+int sourceleft; /* number of bytes to eof */
+
+/* "descriptor" for the file now open.
+ Incremented at each close.
+ If specified descriptor does not match this,
+ it means the program is trying to use a closed descriptor.
+ We report an error for that. */
+
+int sourcedesc;
+
+open (filename, modes)
+ char *filename;
+ int modes;
+{
+ register char *next;
+
+ if (modes)
+ {
+ errno = EROFS;
+ return -1;
+ }
+
+ if (sourceptr)
+ {
+ errno = EMFILE;
+ return -1;
+ }
+
+ for (next = files_start; * (int *) next; next += * (int *) next)
+ {
+ if (!STRCMP (next + 4, filename))
+ {
+ sourcebeg = next + 4 + strlen (next + 4) + 1;
+ sourcebeg = (char *) (((int) sourcebeg + 3) & (-4));
+ sourceptr = sourcebeg;
+ sourcesize = next + * (int *) next - sourceptr;
+ sourceleft = sourcesize;
+ return sourcedesc;
+ }
+ }
+ return 0;
+}
+
+close (desc)
+ int desc;
+{
+ sourceptr = 0;
+ sourcedesc++;
+ /* Don't let sourcedesc get big enough to be confused with stdin. */
+ if (sourcedesc == 100)
+ sourcedesc = 5;
+}
+
+FILE *
+fopen (filename, modes)
+ char *filename;
+ char *modes;
+{
+ return (FILE *) open (filename, *modes == 'w');
+}
+
+FILE *
+fdopen (desc)
+ int desc;
+{
+ return (FILE *) desc;
+}
+
+fclose (desc)
+ int desc;
+{
+ close (desc);
+}
+
+fstat (desc, statbuf)
+ struct stat *statbuf;
+{
+ if (desc != sourcedesc)
+ {
+ errno = EBADF;
+ return -1;
+ }
+ statbuf->st_size = sourcesize;
+}
+
+myread (desc, destptr, size, filename)
+ int desc;
+ char *destptr;
+ int size;
+ char *filename;
+{
+ int len = min (sourceleft, size);
+
+ if (desc != sourcedesc)
+ {
+ errno = EBADF;
+ return -1;
+ }
+
+ memcpy (destptr, sourceptr, len);
+ sourceleft -= len;
+ return len;
+}
+
+int
+fread (bufp, numelts, eltsize, stream)
+{
+ register int elts = min (numelts, sourceleft / eltsize);
+ register int len = elts * eltsize;
+
+ if (stream != sourcedesc)
+ {
+ errno = EBADF;
+ return -1;
+ }
+
+ memcpy (bufp, sourceptr, len);
+ sourceleft -= len;
+ return elts;
+}
+
+int
+fgetc (desc)
+ int desc;
+{
+
+ if (desc == (int) stdin)
+ return tty_input ();
+
+ if (desc != sourcedesc)
+ {
+ errno = EBADF;
+ return -1;
+ }
+
+ if (sourceleft-- <= 0)
+ return EOF;
+ return *sourceptr++;
+}
+
+lseek (desc, pos)
+ int desc;
+ int pos;
+{
+
+ if (desc != sourcedesc)
+ {
+ errno = EBADF;
+ return -1;
+ }
+
+ if (pos < 0 || pos > sourcesize)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
+ sourceptr = sourcebeg + pos;
+ sourceleft = sourcesize - pos;
+}
+
+/* Output in kdb can go only to the terminal, so the stream
+ specified may be ignored. */
+
+printf (a1, a2, a3, a4, a5, a6, a7, a8, a9)
+{
+ char buffer[1024];
+ sprintf (buffer, a1, a2, a3, a4, a5, a6, a7, a8, a9);
+ display_string (buffer);
+}
+
+fprintf (ign, a1, a2, a3, a4, a5, a6, a7, a8, a9)
+{
+ char buffer[1024];
+ sprintf (buffer, a1, a2, a3, a4, a5, a6, a7, a8, a9);
+ display_string (buffer);
+}
+
+fwrite (buf, numelts, size, stream)
+ register char *buf;
+ int numelts, size;
+{
+ register int i = numelts * size;
+ while (i-- > 0)
+ fputc (*buf++, stream);
+}
+
+fputc (c, ign)
+{
+ char buf[2];
+ buf[0] = c;
+ buf[1] = 0;
+ display_string (buf);
+}
+
+/* sprintf refers to this, but loading this from the
+ library would cause fflush to be loaded from it too.
+ In fact there should be no need to call this (I hope). */
+
+_flsbuf ()
+{
+ error ("_flsbuf was actually called.");
+}
+
+fflush (ign)
+{
+}
+
+/* Entries into core and inflow, needed only to make things link ok. */
+
+exec_file_command ()
+{}
+
+core_file_command ()
+{}
+
+char *
+get_exec_file (err)
+ int err;
+{
+ /* Makes one printout look reasonable; value does not matter otherwise. */
+ return "run";
+}
+
+/* Nonzero if there is a core file. */
+
+have_core_file_p ()
+{
+ return 0;
+}
+
+kill_command ()
+{
+ inferior_pid = 0;
+}
+
+terminal_inferior ()
+{}
+
+terminal_ours ()
+{}
+
+terminal_init_inferior ()
+{}
+
+write_inferior_register ()
+{}
+
+read_inferior_register ()
+{}
+
+read_memory (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+{
+ memcpy (myaddr, memaddr, len);
+}
+
+/* Always return 0 indicating success. */
+
+write_memory (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+{
+ memcpy (memaddr, myaddr, len);
+ return 0;
+}
+
+static REGISTER_TYPE saved_regs[NUM_REGS];
+
+REGISTER_TYPE
+read_register (regno)
+ int regno;
+{
+ if (regno < 0 || regno >= NUM_REGS)
+ error ("Register number %d out of range.", regno);
+ return saved_regs[regno];
+}
+
+void
+write_register (regno, value)
+ int regno;
+ REGISTER_TYPE value;
+{
+ if (regno < 0 || regno >= NUM_REGS)
+ error ("Register number %d out of range.", regno);
+ saved_regs[regno] = value;
+}
+
+/* System calls needed in relation to running the "inferior". */
+
+vfork ()
+{
+ /* Just appear to "succeed". Say the inferior's pid is 1. */
+ return 1;
+}
+
+/* These are called by code that normally runs in the inferior
+ that has just been forked. That code never runs, when standalone,
+ and these definitions are so it will link without errors. */
+
+ptrace ()
+{}
+
+setpgrp ()
+{}
+
+execle ()
+{}
+
+_exit ()
+{}
+
+/* Malloc calls these. */
+
+malloc_warning (str)
+ char *str;
+{
+ printf ("\n%s.\n\n", str);
+}
+
+char *next_free;
+char *memory_limit;
+
+char *
+sbrk (amount)
+ int amount;
+{
+ if (next_free + amount > memory_limit)
+ return (char *) -1;
+ next_free += amount;
+ return next_free - amount;
+}
+
+/* Various ways malloc might ask where end of memory is. */
+
+char *
+ulimit ()
+{
+ return memory_limit;
+}
+
+int
+vlimit ()
+{
+ return memory_limit - next_free;
+}
+
+getrlimit (addr)
+ struct rlimit *addr;
+{
+ addr->rlim_cur = memory_limit - next_free;
+}
+
+/* Context switching to and from program being debugged. */
+
+/* GDB calls here to run the user program.
+ The frame pointer for this function is saved in
+ gdb_stack by save_frame_pointer; then we restore
+ all of the user program's registers, including PC and PS. */
+
+static int fault_code;
+static REGISTER_TYPE gdb_stack;
+
+resume ()
+{
+ REGISTER_TYPE restore[NUM_REGS];
+
+ PUSH_FRAME_PTR;
+ save_frame_pointer ();
+
+ memcpy (restore, saved_regs, sizeof restore);
+ POP_REGISTERS;
+ /* Control does not drop through here! */
+}
+
+save_frame_pointer (val)
+ CORE_ADDR val;
+{
+ gdb_stack = val;
+}
+
+/* Fault handlers call here, running in the user program stack.
+ They must first push a fault code,
+ old PC, old PS, and any other info about the fault.
+ The exact format is machine-dependent and is known only
+ in the definition of PUSH_REGISTERS. */
+
+fault ()
+{
+ /* Transfer all registers and fault code to the stack
+ in canonical order: registers in order of GDB register number,
+ followed by fault code. */
+ PUSH_REGISTERS;
+
+ /* Transfer them to saved_regs and fault_code. */
+ save_registers ();
+
+ restore_gdb ();
+ /* Control does not reach here */
+}
+
+restore_gdb ()
+{
+ CORE_ADDR new_fp = gdb_stack;
+ /* Switch to GDB's stack */
+ POP_FRAME_PTR;
+ /* Return from the function `resume'. */
+}
+
+/* Assuming register contents and fault code have been pushed on the stack as
+ arguments to this function, copy them into the standard place
+ for the program's registers while GDB is running. */
+
+save_registers (firstreg)
+ int firstreg;
+{
+ memcpy (saved_regs, &firstreg, sizeof saved_regs);
+ fault_code = (&firstreg)[NUM_REGS];
+}
+
+/* Store into the structure such as `wait' would return
+ the information on why the program faulted,
+ converted into a machine-independent signal number. */
+
+static int fault_table[] = FAULT_TABLE;
+
+int
+wait (w)
+ WAITTYPE *w;
+{
+ WSETSTOP (*w, fault_table[fault_code / FAULT_CODE_UNITS]);
+ return inferior_pid;
+}
+
+/* Allocate a big space in which files for kdb to read will be stored.
+ Whatever is left is where malloc can allocate storage.
+
+ Initialize it, so that there will be space in the executable file
+ for it. Then the files can be put into kdb by writing them into
+ kdb's executable file. */
+
+/* The default size is as much space as we expect to be available
+ for kdb to use! */
+
+#ifndef HEAP_SIZE
+#define HEAP_SIZE 400000
+#endif
+
+char heap[HEAP_SIZE] = {0};
+
+#ifndef STACK_SIZE
+#define STACK_SIZE 100000
+#endif
+
+int kdb_stack_beg[STACK_SIZE / sizeof (int)];
+int kdb_stack_end;
+
+_initialize_standalone ()
+{
+ register char *next;
+
+ /* Find start of data on files. */
+
+ files_start = heap;
+
+ /* Find the end of the data on files. */
+
+ for (next = files_start; * (int *) next; next += * (int *) next) {}
+
+ /* That is where free storage starts for sbrk to give out. */
+ next_free = next;
+
+ memory_limit = heap + sizeof heap;
+}
+
diff --git a/gdb/stop-gdb.c b/gdb/stop-gdb.c
new file mode 100644
index 00000000000..8f22bf91957
--- /dev/null
+++ b/gdb/stop-gdb.c
@@ -0,0 +1,110 @@
+/* A client to make GDB return to command level in Mach 3.
+ Copyright (C) 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Authors: Jukka Virtanen <jtv@hut.fi> and Peter Stout <pds@cs.cmu.edu>.
+
+ A simple client to make GDB (versions 4.4 and later) on Mach 3 return
+ to the command level when it is waiting for the inferior to stop.
+
+ Actions: Lookup the send right to the GDB message port from the
+ NetMsgServer.
+
+ Send an asynchronous message with msgh_id
+ GDB_MESSAGE_ID_STOP to that port.
+ */
+
+#include <stdio.h>
+
+#include "defs.h"
+
+#include <mach.h>
+#include <mach/message.h>
+#include <mach_error.h>
+#include <servers/netname.h>
+#include <servers/netname_defs.h>
+
+void
+main (argc, argv)
+ int argc;
+ char **argv;
+{
+ kern_return_t kr;
+ mach_msg_header_t msg;
+ mach_port_t gdb_port;
+ char *host;
+ char *name;
+
+ if (argc == 1)
+ argv[argc++] = GDB_DEF_NAME;
+
+ if (argc != 2)
+ {
+ fprintf (stderr, "Usage : %s <GDB name>\n", argv[0]);
+ exit (1);
+ }
+
+ /* Allow the user to specify a remote host. */
+ host = strchr (argv[1], '@');
+ if (host)
+ *(host++) = '\0';
+ else
+ host = (char *) "";
+
+ name = malloc (strlen (argv[1]) + sizeof(GDB_NAME_PREFIX));
+ if (name == NULL)
+ {
+ fprintf (stderr, "Unable to allocate memory for name.");
+ exit (1);
+ }
+
+ strcpy (name, GDB_NAME_PREFIX);
+ strcat (name, argv[1]);
+
+ /* Look up the GDB service port. For convenience, add the
+ GDB_NAME_PREFIX the argument before looking up the name.
+ For backwards compatibility, do it without. */
+
+ kr = netname_look_up (name_server_port, host, name, &gdb_port);
+ if (kr == NETNAME_NOT_CHECKED_IN)
+ kr = netname_look_up (name_server_port, host, argv[1], &gdb_port);
+ if (kr != KERN_SUCCESS)
+ {
+ fprintf (stderr, "Unable to lookup the GDB service port: %s.\n",
+ mach_error_string(kr));
+ exit(1);
+ }
+
+ /* Code generated by mig stub generator, with minor cleanups :-)
+
+ simpleroutine stop_inferior(gdb_port : mach_port_t); */
+
+ msg.msgh_bits = MACH_MSGH_BITS (MACH_MSG_TYPE_COPY_SEND, 0);
+ msg.msgh_remote_port = gdb_port;
+ msg.msgh_local_port = MACH_PORT_NULL;
+ msg.msgh_size = sizeof(msg);
+ msg.msgh_seqno = 0;
+ msg.msgh_id = GDB_MESSAGE_ID_STOP;
+
+ kr = mach_msg_send (&msg);
+ if (kr != KERN_SUCCESS)
+ fprintf (stderr, "Message not sent, return code %d : %s\n", kr,
+ mach_error_string (kr));
+
+ exit (kr != KERN_SUCCESS);
+}
diff --git a/gdb/stuff.c b/gdb/stuff.c
new file mode 100644
index 00000000000..eedbeab9998
--- /dev/null
+++ b/gdb/stuff.c
@@ -0,0 +1,174 @@
+/* Program to stuff files into a specially prepared space in kdb.
+ Copyright (C) 1986, 1989, 1991 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Written 13-Mar-86 by David Bridgham. */
+
+#include <stdio.h>
+#include <a.out.h>
+#include <sys/types.h>
+#include "gdb_stat.h"
+#include <sys/file.h>
+#include <varargs.h>
+
+main (argc, argv)
+ int argc;
+ char *argv[];
+{
+ register char *cp;
+ char *outfile;
+ register int i;
+ int offset;
+ int out_fd, in_fd;
+ struct stat stat_buf;
+ int size, pad;
+ char buf[1024];
+ static char zeros[4] = {0};
+
+ if (argc < 4)
+ err("Not enough arguments\nUsage: %s -o kdb file1 file2 ...\n",
+ argv[0]);
+
+ outfile = 0;
+ for (i = 1; i < argc; i++)
+ {
+ if (STREQ (argv[i], "-o"))
+ outfile = argv[++i];
+ }
+ if (outfile == 0)
+ err("Output file not specified\n");
+
+ offset = get_offset (outfile, "_heap");
+
+ out_fd = open (outfile, O_WRONLY);
+ if (out_fd < 0)
+ err ("Error opening %s for write: %s\n", outfile, strerror (errno));
+ if (lseek (out_fd, offset, 0) < 0)
+ err ("Error seeking to heap in %s: %s\n", outfile, strerror (errno));
+
+ /* For each file listed on the command line, write it into the
+ * 'heap' of the output file. Make sure to skip the arguments
+ * that name the output file. */
+ for (i = 1; i < argc; i++)
+ {
+ if (STREQ (argv[i], "-o"))
+ continue;
+ if ((in_fd = open (argv[i], O_RDONLY)) < 0)
+ err ("Error opening %s for read: %s\n", argv[i],
+ strerror (errno));
+ if (fstat (in_fd, &stat_buf) < 0)
+ err ("Error stat'ing %s: %s\n", argv[i], strerror (errno));
+ size = strlen (argv[i]);
+ pad = 4 - (size & 3);
+ size += pad + stat_buf.st_size + sizeof (int);
+ write (out_fd, &size, sizeof (int));
+ write (out_fd, argv[i], strlen (argv[i]));
+ write (out_fd, zeros, pad);
+ while ((size = read (in_fd, buf, sizeof (buf))) > 0)
+ write (out_fd, buf, size);
+ close (in_fd);
+ }
+ size = 0;
+ write (out_fd, &size, sizeof (int));
+ close (out_fd);
+ return (0);
+}
+
+/* Read symbol table from file and returns the offset into the file
+ * where symbol sym_name is located. If error, print message and
+ * exit. */
+get_offset (file, sym_name)
+ char *file;
+ char *sym_name;
+{
+ int f;
+ struct exec file_hdr;
+ struct nlist *symbol_table;
+ int size;
+ char *strings;
+
+ f = open (file, O_RDONLY);
+ if (f < 0)
+ err ("Error opening %s: %s\n", file, strerror (errno));
+ if (read (f, &file_hdr, sizeof (file_hdr)) < 0)
+ err ("Error reading exec structure: %s\n", strerror (errno));
+ if (N_BADMAG (file_hdr))
+ err ("File %s not an a.out file\n", file);
+
+ /* read in symbol table */
+ if ((symbol_table = (struct nlist *)malloc (file_hdr.a_syms)) == 0)
+ err ("Couldn't allocate space for symbol table\n");
+ if (lseek (f, N_SYMOFF (file_hdr), 0) == -1)
+ err ("lseek error: %s\n", strerror (errno));
+ if (read (f, symbol_table, file_hdr.a_syms) == -1)
+ err ("Error reading symbol table from %s: %s\n", file,
+ strerror (errno));
+
+ /* read in string table */
+ if (read (f, &size, 4) == -1)
+ err ("reading string table size: %s\n", strerror (errno));
+ if ((strings = (char *)malloc (size)) == 0)
+ err ("Couldn't allocate memory for string table\n");
+ if (read (f, strings, size - 4) == -1)
+ err ("reading string table: %s\n", strerror (errno));
+
+ /* Find the core address at which the first byte of kdb text segment
+ should be loaded into core when kdb is run. */
+ origin = find_symbol ("_etext", symbol_table, file_hdr.a_syms, strings)
+ - file_hdr.a_text;
+ /* Find the core address at which the heap will appear. */
+ coreaddr = find_symbol (sym_name, symbol_table, file_hdr.a_syms, strings);
+ /* Return address in file of the heap data space. */
+ return (N_TXTOFF (file_hdr) + core_addr - origin);
+}
+
+find_symbol (sym_name, symbol_table, length, strings)
+ char *sym_name;
+ struct nlist *symbol_table;
+ int length;
+ char *strings;
+{
+ register struct nlist *sym;
+
+ /* Find symbol in question */
+ for (sym = symbol_table;
+ sym != (struct nlist *)((char *)symbol_table + length);
+ sym++)
+ {
+ if ((sym->n_type & N_TYPE) != N_DATA) continue;
+ if (sym->n_un.n_strx == 0) continue;
+ if (STREQ (sym_name, strings + sym->n_un.n_strx - 4))
+ return sym->n_value;
+ }
+ err ("Data symbol %s not found in %s\n", sym_name, file);
+}
+
+/* VARARGS */
+void
+err (va_alist)
+ va_dcl
+{
+ va_list args;
+ char *string;
+
+ va_start (args);
+ string = va_arg (args, char *);
+ vfprintf (gdb_stderr, string, args);
+ va_end (args);
+ exit (-1);
+}
diff --git a/gdb/sun3-nat.c b/gdb/sun3-nat.c
new file mode 100644
index 00000000000..30f4a44e139
--- /dev/null
+++ b/gdb/sun3-nat.c
@@ -0,0 +1,157 @@
+/* Host-dependent code for Sun-3 for GDB, the GNU debugger.
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "inferior.h"
+#include "gdbcore.h"
+
+#include <sys/ptrace.h>
+#define KERNEL /* To get floating point reg definitions */
+#include <machine/reg.h>
+
+static void fetch_core_registers PARAMS ((char *, unsigned, int, CORE_ADDR));
+
+void
+fetch_inferior_registers (regno)
+ int regno;
+{
+ struct regs inferior_registers;
+#ifdef FP0_REGNUM
+ struct fp_status inferior_fp_registers;
+#endif
+ extern char registers[];
+
+ registers_fetched ();
+
+ ptrace (PTRACE_GETREGS, inferior_pid,
+ (PTRACE_ARG3_TYPE) &inferior_registers);
+#ifdef FP0_REGNUM
+ ptrace (PTRACE_GETFPREGS, inferior_pid,
+ (PTRACE_ARG3_TYPE) &inferior_fp_registers);
+#endif
+
+ memcpy (registers, &inferior_registers, 16 * 4);
+#ifdef FP0_REGNUM
+ memcpy (&registers[REGISTER_BYTE (FP0_REGNUM)], &inferior_fp_registers,
+ sizeof inferior_fp_registers.fps_regs);
+#endif
+ *(int *)&registers[REGISTER_BYTE (PS_REGNUM)] = inferior_registers.r_ps;
+ *(int *)&registers[REGISTER_BYTE (PC_REGNUM)] = inferior_registers.r_pc;
+#ifdef FP0_REGNUM
+ memcpy (&registers[REGISTER_BYTE (FPC_REGNUM)],
+ &inferior_fp_registers.fps_control,
+ sizeof inferior_fp_registers - sizeof inferior_fp_registers.fps_regs);
+#endif
+}
+
+/* Store our register values back into the inferior.
+ If REGNO is -1, do this for all registers.
+ Otherwise, REGNO specifies which register (so we can save time). */
+
+void
+store_inferior_registers (regno)
+ int regno;
+{
+ struct regs inferior_registers;
+#ifdef FP0_REGNUM
+ struct fp_status inferior_fp_registers;
+#endif
+ extern char registers[];
+
+ memcpy (&inferior_registers, registers, 16 * 4);
+#ifdef FP0_REGNUM
+ memcpy (&inferior_fp_registers, &registers[REGISTER_BYTE (FP0_REGNUM)],
+ sizeof inferior_fp_registers.fps_regs);
+#endif
+ inferior_registers.r_ps = *(int *)&registers[REGISTER_BYTE (PS_REGNUM)];
+ inferior_registers.r_pc = *(int *)&registers[REGISTER_BYTE (PC_REGNUM)];
+
+#ifdef FP0_REGNUM
+ memcpy (&inferior_fp_registers.fps_control,
+ &registers[REGISTER_BYTE (FPC_REGNUM)],
+ sizeof inferior_fp_registers - sizeof inferior_fp_registers.fps_regs);
+#endif
+
+ ptrace (PTRACE_SETREGS, inferior_pid,
+ (PTRACE_ARG3_TYPE) &inferior_registers);
+#if FP0_REGNUM
+ ptrace (PTRACE_SETFPREGS, inferior_pid,
+ (PTRACE_ARG3_TYPE) &inferior_fp_registers);
+#endif
+}
+
+
+/* All of this stuff is only relevant if both host and target are sun3. */
+/* Machine-dependent code for pulling registers out of a Sun-3 core file. */
+
+static void
+fetch_core_registers (core_reg_sect, core_reg_size, which, reg_addr)
+ char *core_reg_sect;
+ unsigned core_reg_size;
+ int which;
+ CORE_ADDR reg_addr; /* Unused in this version */
+{
+ extern char registers[];
+ struct regs *regs = (struct regs *) core_reg_sect;
+
+ if (which == 0) {
+ if (core_reg_size < sizeof (struct regs))
+ error ("Can't find registers in core file");
+
+ memcpy (registers, (char *)regs, 16 * 4);
+ supply_register (PS_REGNUM, (char *)&regs->r_ps);
+ supply_register (PC_REGNUM, (char *)&regs->r_pc);
+
+ } else if (which == 2) {
+
+#define fpustruct ((struct fpu *) core_reg_sect)
+
+ if (core_reg_size >= sizeof (struct fpu))
+ {
+#ifdef FP0_REGNUM
+ memcpy (&registers[REGISTER_BYTE (FP0_REGNUM)],
+ fpustruct->f_fpstatus.fps_regs,
+ sizeof fpustruct->f_fpstatus.fps_regs);
+ memcpy (&registers[REGISTER_BYTE (FPC_REGNUM)],
+ &fpustruct->f_fpstatus.fps_control,
+ sizeof fpustruct->f_fpstatus -
+ sizeof fpustruct->f_fpstatus.fps_regs);
+#endif
+ }
+ else
+ fprintf_unfiltered (gdb_stderr, "Couldn't read float regs from core file\n");
+ }
+}
+
+
+/* Register that we are able to handle sun3 core file formats.
+ FIXME: is this really bfd_target_unknown_flavour? */
+
+static struct core_fns sun3_core_fns =
+{
+ bfd_target_unknown_flavour,
+ fetch_core_registers,
+ NULL
+};
+
+void
+_initialize_core_sun3 ()
+{
+ add_core_fns (&sun3_core_fns);
+}
diff --git a/gdb/sun386-nat.c b/gdb/sun386-nat.c
new file mode 100644
index 00000000000..1abb4bb1df0
--- /dev/null
+++ b/gdb/sun386-nat.c
@@ -0,0 +1,258 @@
+/* Native support for Sun 386i's for GDB, the GNU debugger.
+ Copyright (C) 1986, 1987, 1989, 1991, 1992 Free Software Foundation, Inc.
+ Changes for sun386i by Jean Daniel Fekete (jdf@litp.univ-p6-7.fr),
+ C2V Paris, April 89.
+
+This file is part of GDB.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "frame.h"
+#include "inferior.h"
+#include "gdbcore.h"
+
+#include <sys/param.h>
+#include <sys/dir.h>
+#include <sys/user.h>
+#include <signal.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+
+#include <sys/ptrace.h>
+#include <machine/reg.h>
+
+#include <sys/file.h>
+#include "gdb_stat.h"
+#include <sys/core.h>
+
+
+/* Machine-dependent code which would otherwise be in corefile.c */
+/* Work with core files, for GDB. */
+
+
+void
+core_file_command (filename, from_tty)
+ char *filename;
+ int from_tty;
+{
+ int val;
+ extern char registers[];
+
+ /* Discard all vestiges of any previous core file
+ and mark data and stack spaces as empty. */
+
+ if (corefile)
+ free (corefile);
+ corefile = 0;
+
+ if (corechan >= 0)
+ close (corechan);
+ corechan = -1;
+
+ data_start = 0;
+ data_end = 0;
+ stack_start = STACK_END_ADDR;
+ stack_end = STACK_END_ADDR;
+
+ /* Now, if a new core file was specified, open it and digest it. */
+
+ if (filename)
+ {
+ filename = tilde_expand (filename);
+ make_cleanup (free, filename);
+
+ if (have_inferior_p ())
+ error ("To look at a core file, you must kill the program with \"kill\".");
+ corechan = open (filename, O_RDONLY, 0);
+ if (corechan < 0)
+ perror_with_name (filename);
+
+ {
+ struct core corestr;
+
+ val = myread (corechan, &corestr, sizeof corestr);
+ if (val < 0)
+ perror_with_name (filename);
+ if (corestr.c_magic != CORE_MAGIC)
+ error ("\"%s\" does not appear to be a core dump file (magic 0x%x, expected 0x%x)",
+ filename, corestr.c_magic, (int) CORE_MAGIC);
+ else if (sizeof (struct core) != corestr.c_len)
+ error ("\"%s\" has an invalid struct core length (%d, expected %d)",
+ filename, corestr.c_len, (int) sizeof (struct core));
+
+ data_start = exec_data_start;
+ data_end = data_start + corestr.c_dsize;
+ stack_start = stack_end - corestr.c_ssize;
+ data_offset = sizeof corestr;
+ stack_offset = sizeof corestr + corestr.c_dsize;
+
+ memcpy (registers, &corestr.c_regs, sizeof corestr.c_regs);
+
+ memcpy (&registers[REGISTER_BYTE (FP0_REGNUM)],
+ corestr.c_fpu.f_fpstatus.f_st,
+ sizeof corestr.c_fpu.f_fpstatus.f_st);
+ memcpy (&registers[REGISTER_BYTE (FPC_REGNUM)],
+ &corestr.c_fpu.f_fpstatus.f_ctrl,
+ sizeof corestr.c_fpu.f_fpstatus -
+ sizeof corestr.c_fpu.f_fpstatus.f_st);
+
+ /* the struct aouthdr of sun coff is not the struct exec stored
+ in the core file. */
+ memcpy (&core_aouthdr, &corestr.c_aouthdr, sizeof (struct exec));
+#ifndef COFF_ENCAPSULATE
+ core_aouthdr.magic = corestr.c_aouthdr.a_info;
+ core_aouthdr.vstamp = /*SUNVERSION*/ 31252;
+#endif
+ printf_unfiltered ("Core file is from \"%s\".\n", corestr.c_cmdname);
+ if (corestr.c_signo > 0)
+ printf_unfiltered ("Program terminated with signal %d, %s.\n",
+ corestr.c_signo, safe_strsignal (corestr.c_signo));
+ }
+ if (filename[0] == '/')
+ corefile = savestring (filename, strlen (filename));
+ else
+ {
+ corefile = concat (current_directory, "/", filename, NULL);
+ }
+
+ flush_cached_frames ();
+ select_frame (get_current_frame (), 0);
+
+ validate_files ();
+ }
+ else if (from_tty)
+ printf_unfiltered ("No core file now.\n");
+}
+
+i387_to_double (from, to)
+ char *from;
+ char *to;
+{
+ long *lp;
+ /* push extended mode on 387 stack, then pop in double mode
+ *
+ * first, set exception masks so no error is generated -
+ * number will be rounded to inf or 0, if necessary
+ */
+ asm ("pushl %eax"); /* grab a stack slot */
+ asm ("fstcw (%esp)"); /* get 387 control word */
+ asm ("movl (%esp),%eax"); /* save old value */
+ asm ("orl $0x3f,%eax"); /* mask all exceptions */
+ asm ("pushl %eax");
+ asm ("fldcw (%esp)"); /* load new value into 387 */
+
+ asm ("movl 8(%ebp),%eax");
+ asm ("fldt (%eax)"); /* push extended number on 387 stack */
+ asm ("fwait");
+ asm ("movl 12(%ebp),%eax");
+ asm ("fstpl (%eax)"); /* pop double */
+ asm ("fwait");
+
+ asm ("popl %eax"); /* flush modified control word */
+ asm ("fnclex"); /* clear exceptions */
+ asm ("fldcw (%esp)"); /* restore original control word */
+ asm ("popl %eax"); /* flush saved copy */
+}
+
+double_to_i387 (from, to)
+ char *from;
+ char *to;
+{
+ /* push double mode on 387 stack, then pop in extended mode
+ * no errors are possible because every 64-bit pattern
+ * can be converted to an extended
+ */
+ asm ("movl 8(%ebp),%eax");
+ asm ("fldl (%eax)");
+ asm ("fwait");
+ asm ("movl 12(%ebp),%eax");
+ asm ("fstpt (%eax)");
+ asm ("fwait");
+}
+
+void
+fetch_inferior_registers (regno)
+ int regno;
+{
+ struct regs inferior_registers;
+ struct fp_state inferior_fp_registers;
+ extern char registers[];
+
+ registers_fetched ();
+
+ ptrace (PTRACE_GETREGS, inferior_pid,
+ (PTRACE_ARG3_TYPE) &inferior_registers);
+ ptrace (PTRACE_GETFPREGS, inferior_pid,
+ (PTRACE_ARG3_TYPE) &inferior_fp_registers);
+
+ memcpy (registers, &inferior_registers, sizeof inferior_registers);
+
+ memcpy (&registers[REGISTER_BYTE (FP0_REGNUM)],inferior_fp_registers.f_st,
+ sizeof inferior_fp_registers.f_st);
+ memcpy (&registers[REGISTER_BYTE (FPC_REGNUM)],
+ &inferior_fp_registers.f_ctrl,
+ sizeof inferior_fp_registers - sizeof inferior_fp_registers.f_st);
+}
+
+/* Store our register values back into the inferior.
+ If REGNO is -1, do this for all registers.
+ Otherwise, REGNO specifies which register (so we can save time). */
+
+void
+store_inferior_registers (regno)
+ int regno;
+{
+ struct regs inferior_registers;
+ struct fp_state inferior_fp_registers;
+ extern char registers[];
+
+ memcpy (&inferior_registers, registers, 20 * 4);
+
+ memcpy (inferior_fp_registers.f_st,
+ &registers[REGISTER_BYTE (FP0_REGNUM)],
+ sizeof inferior_fp_registers.f_st);
+ memcpy (&inferior_fp_registers.f_ctrl,
+ &registers[REGISTER_BYTE (FPC_REGNUM)],
+ sizeof inferior_fp_registers - sizeof inferior_fp_registers.f_st);
+
+#ifdef PTRACE_FP_BUG
+ if (regno == FP_REGNUM || regno == -1)
+ /* Storing the frame pointer requires a gross hack, in which an
+ instruction that moves eax into ebp gets single-stepped. */
+ {
+ int stack = inferior_registers.r_reg[SP_REGNUM];
+ int stuff = ptrace (PTRACE_PEEKDATA, inferior_pid,
+ (PTRACE_ARG3_TYPE) stack);
+ int reg = inferior_registers.r_reg[EAX];
+ inferior_registers.r_reg[EAX] =
+ inferior_registers.r_reg[FP_REGNUM];
+ ptrace (PTRACE_SETREGS, inferior_pid,
+ (PTRACE_ARG3_TYPE) &inferior_registers);
+ ptrace (PTRACE_POKEDATA, inferior_pid, (PTRACE_ARG3_TYPE) stack,
+ 0xc589);
+ ptrace (PTRACE_SINGLESTEP, inferior_pid, (PTRACE_ARG3_TYPE) stack,
+ 0);
+ wait (0);
+ ptrace (PTRACE_POKEDATA, inferior_pid, (PTRACE_ARG3_TYPE) stack,
+ stuff);
+ inferior_registers.r_reg[EAX] = reg;
+ }
+#endif
+ ptrace (PTRACE_SETREGS, inferior_pid,
+ (PTRACE_ARG3_TYPE) &inferior_registers);
+ ptrace (PTRACE_SETFPREGS, inferior_pid,
+ (PTRACE_ARG3_TYPE) &inferior_fp_registers);
+}
diff --git a/gdb/symfile.c b/gdb/symfile.c
new file mode 100644
index 00000000000..ee60c9392e4
--- /dev/null
+++ b/gdb/symfile.c
@@ -0,0 +1,3021 @@
+/* Generic symbol file reading for the GNU debugger, GDB.
+ Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1998
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 "gdb-stabs.h"
+#include "obstack.h"
+
+#include <assert.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include "gdb_string.h"
+#include "gdb_stat.h"
+#include <ctype.h>
+#include <time.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
+
+#ifdef HPUXHPPA
+
+/* Some HP-UX related globals to clear when a new "main"
+ symbol file is loaded. HP-specific. */
+
+extern int hp_som_som_object_present;
+extern int hp_cxx_exception_support_initialized;
+#define RESET_HP_UX_GLOBALS() do {\
+ hp_som_som_object_present = 0; /* indicates HP-compiled code */ \
+ hp_cxx_exception_support_initialized = 0; /* must reinitialize exception stuff */ \
+ } while (0)
+#endif
+
+int (*ui_load_progress_hook) PARAMS ((char *, unsigned long));
+void (*pre_add_symbol_hook) PARAMS ((char *));
+void (*post_add_symbol_hook) PARAMS ((void));
+
+/* 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;
+
+extern void report_transfer_performance PARAMS ((unsigned long,
+ time_t, time_t));
+
+/* Functions this file defines */
+
+#if 0
+static int simple_read_overlay_region_table PARAMS ((void));
+static void simple_free_overlay_region_table PARAMS ((void));
+#endif
+
+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 add_shared_symbol_files_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 *));
+
+bfd *symfile_bfd_open PARAMS ((char *));
+
+static void find_sym_fns PARAMS ((struct objfile *));
+
+static void decrement_reading_symtab PARAMS ((void *));
+
+static void overlay_invalidate_all PARAMS ((void));
+
+static int overlay_is_mapped PARAMS ((struct obj_section *));
+
+void list_overlays_command PARAMS ((char *, int));
+
+void map_overlay_command PARAMS ((char *, int));
+
+void unmap_overlay_command PARAMS ((char *, int));
+
+static void overlay_auto_command PARAMS ((char *, int));
+
+static void overlay_manual_command PARAMS ((char *, int));
+
+static void overlay_off_command PARAMS ((char *, int));
+
+static void overlay_load_command PARAMS ((char *, int));
+
+static void overlay_command PARAMS ((char *, int));
+
+static void simple_free_overlay_table PARAMS ((void));
+
+static void read_target_long_array PARAMS ((CORE_ADDR, unsigned int *, int));
+
+static int simple_read_overlay_table PARAMS ((void));
+
+static int simple_overlay_update_1 PARAMS ((struct obj_section *));
+
+void _initialize_symfile PARAMS ((void));
+
+/* 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;
+
+/* 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
+
+/* If non-zero, then on HP-UX (i.e., platforms that use somsolib.c),
+ this variable is interpreted as a threshhold. If adding a new
+ library's symbol table to those already known to the debugger would
+ exceed this threshhold, then the shlib's symbols are not added.
+
+ If non-zero on other platforms, shared library symbols will be added
+ automatically when the inferior is created, new libraries are loaded,
+ or when attaching to the inferior. This is almost always what users
+ will want to have happen; but for very large programs, the startup
+ time will be excessive, and so if this is a problem, the user can
+ clear this flag and then add the shared library symbols as needed.
+ Note that there is a potential for confusion, since if the shared
+ library symbols are not loaded, commands like "info fun" will *not*
+ report all the functions that are actually present.
+
+ Note that HP-UX interprets this variable to mean, "threshhold size
+ in megabytes, where zero means never add". Other platforms interpret
+ this variable to mean, "always add if non-zero, never add if zero."
+ */
+
+int auto_solib_add = 1;
+
+
+/* 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 pointers to pointers 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
+ {
+ /* Note: I replaced the STRCMP line (commented out below)
+ * with a simpler "strcmp()" which compares the 2 strings
+ * from the beginning. (STRCMP is a macro which first compares
+ * the initial characters, then falls back on strcmp).
+ * The reason is that the STRCMP line was tickling a C compiler
+ * bug on HP-UX 10.30, which is avoided with the simpler
+ * code. The performance gain from the more complicated code
+ * is negligible, given that we have already checked the
+ * initial 2 characters above. I reported the compiler bug,
+ * and once it is fixed the original line can be put back. RT
+ */
+ /* return ( STRCMP (st1 + 2, st2 + 2)); */
+ return ( strcmp (st1, st2));
+ }
+}
+
+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);
+ }
+}
+
+/* Make a null terminated copy of the string at PTR with SIZE characters in
+ the obstack pointed to by OBSTACKP . Returns the address of the copy.
+ Note that the string at PTR does not have to be null terminated, I.E. it
+ may be part of a larger string and we are only saving a substring. */
+
+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. FIXME: Is this really still true with a compiler that can
+ inline memcpy? */
+ {
+ 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 obstack pointed to by OBSTACKP. */
+
+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;
+}
+
+/* True if we are nested inside psymtab_to_symtab. */
+
+int currently_reading_symtab = 0;
+
+static void
+decrement_reading_symtab (dummy)
+ void *dummy;
+{
+ currently_reading_symtab--;
+}
+
+/* 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)
+ {
+ struct cleanup *back_to = make_cleanup (decrement_reading_symtab, NULL);
+ currently_reading_symtab++;
+ (*pst->read_symtab) (pst);
+ do_cleanups (back_to);
+ }
+
+ 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. */
+ objfile -> ei.entry_point = INVALID_ENTRY_POINT;
+ }
+ objfile -> ei.entry_file_lowpc = INVALID_ENTRY_LOWPC;
+ objfile -> ei.entry_file_highpc = INVALID_ENTRY_HIGHPC;
+ objfile -> ei.entry_func_lowpc = INVALID_ENTRY_LOWPC;
+ objfile -> ei.entry_func_highpc = INVALID_ENTRY_HIGHPC;
+ objfile -> ei.main_func_lowpc = INVALID_ENTRY_LOWPC;
+ objfile -> ei.main_func_highpc = INVALID_ENTRY_HIGHPC;
+}
+
+/* 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.
+
+ In case of equal vmas, the section with the largest size becomes the
+ lowest-addressed loadable section.
+
+ If the vmas and sizes are equal, the last section is considered the
+ lowest-addressed loadable section. */
+
+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 */
+ else if (bfd_section_vma (abfd, *lowest) == bfd_section_vma (abfd, sect)
+ && (bfd_section_size (abfd, (*lowest))
+ <= bfd_section_size (abfd, sect)))
+ *lowest = sect;
+}
+
+/* Parse the user's idea of an offset for dynamic linking, into our idea
+ of how to represent it for fast symbol reading. This is the default
+ version of the sym_fns.sym_offsets function for symbol readers that
+ don't need to do anything special. It allocates a section_offsets table
+ for the objectfile OBJFILE and stuffs ADDR into all of the offsets. */
+
+struct section_offsets *
+default_symfile_offsets (objfile, addr)
+ struct objfile *objfile;
+ CORE_ADDR addr;
+{
+ struct section_offsets *section_offsets;
+ int i;
+
+ objfile->num_sections = SECT_OFF_MAX;
+ section_offsets = (struct section_offsets *)
+ obstack_alloc (&objfile -> psymbol_obstack, SIZEOF_SECTION_OFFSETS);
+
+ for (i = 0; i < SECT_OFF_MAX; i++)
+ ANOFFSET (section_offsets, i) = addr;
+
+ return section_offsets;
+}
+
+
+/* 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 ((make_cleanup_func) 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 ((make_cleanup_func) 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;
+ }
+
+ /* Currently we keep symbols from the add-symbol-file command.
+ If the user wants to get rid of them, they should do "symbol-file"
+ without arguments first. Not sure this is the best behavior
+ (PR 2207). */
+
+ (*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 a text segment. */
+
+ if (mainline)
+ {
+ addr = 0; /* No offset from objfile addresses. */
+ }
+ else
+ {
+ lowest_sect = bfd_get_section_by_name (objfile->obfd, ".text");
+ if (lowest_sect == NULL)
+ bfd_map_over_sections (objfile->obfd, find_lowest_section,
+ (PTR) &lowest_sect);
+
+ if (lowest_sect == NULL)
+ warning ("no loadable sections found in added symbol-file %s",
+ objfile->name);
+ else if ((bfd_get_section_flags (objfile->obfd, lowest_sect) & SEC_CODE)
+ == 0)
+ /* FIXME-32x64--assumes bfd_vma fits in long. */
+ 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);
+
+ 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);
+
+ if (!have_partial_symbols () && !have_full_symbols ())
+ {
+ wrap_here ("");
+ printf_filtered ("(no debugging symbols found)...");
+ wrap_here ("");
+ }
+
+ /* Don't allow char * to have a typename (else would get caddr_t).
+ Ditto void *. FIXME: Check whether this is now done by all the
+ symbol readers themselves (many of them now do), and if so remove
+ it from here. */
+
+ 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);
+
+/* Call this after reading in a new symbol table to give target dependant code
+ a crack at the new symbols. For instance, this could be used to update the
+ values of target-specific symbols GDB needs to keep track of (such as
+ _sigtramp, or whatever). */
+
+ TARGET_SYMFILE_POSTREAD (objfile);
+}
+
+/* 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.
+
+ USER_LOADED is TRUE if the add-symbol-file command was how this
+ symbol file came to be processed.
+
+ IS_SOLIB is TRUE if this symbol file represents a solib, as discovered
+ by the target's implementation of the solib package.
+
+ 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, user_loaded, is_solib)
+ char *name;
+ int from_tty;
+ CORE_ADDR addr;
+ int mainline;
+ int mapped;
+ int readnow;
+ int user_loaded;
+ int is_solib;
+{
+ 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, user_loaded, is_solib);
+
+ /* 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 ("");
+ gdb_flush (gdb_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)
+ {
+ if (pre_add_symbol_hook)
+ pre_add_symbol_hook (name);
+ else
+ {
+ printf_filtered ("Reading symbols from %s...", name);
+ wrap_here ("");
+ gdb_flush (gdb_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 ("");
+ gdb_flush (gdb_stdout);
+ }
+
+ for (psymtab = objfile -> psymtabs;
+ psymtab != NULL;
+ psymtab = psymtab -> next)
+ {
+ psymtab_to_symtab (psymtab);
+ }
+ }
+
+ if (from_tty || info_verbose)
+ {
+ if (post_add_symbol_hook)
+ post_add_symbol_hook ();
+ else
+ {
+ printf_filtered ("done.\n");
+ gdb_flush (gdb_stdout);
+ }
+ }
+
+ new_symfile_objfile (objfile, mainline, from_tty);
+
+ target_new_objfile (objfile);
+
+ return (objfile);
+}
+
+/* This is the symbol-file command. Read the file, analyze its
+ symbols, and add a struct symtab to a symtab list. The syntax of
+ the command is rather bizarre--(1) buildargv implements various
+ quoting conventions which are undocumented and have little or
+ nothing in common with the way things are quoted (or not quoted)
+ elsewhere in GDB, (2) options are used, which are not generally
+ used in GDB (perhaps "set mapped on", "set readnow on" would be
+ better), (3) the order of options matters, which is contrary to GNU
+ conventions (because it is confusing and inconvenient). */
+
+void
+symbol_file_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ char **argv;
+ char *name = NULL;
+ CORE_ADDR text_relocation = 0; /* text_relocation */
+ 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 ();
+
+ /* solib descriptors may have handles to objfiles. Since their
+ storage has just been released, we'd better wipe the solib
+ descriptors as well.
+ */
+#if defined(SOLIB_RESTART)
+ SOLIB_RESTART ();
+#endif
+
+ symfile_objfile = NULL;
+ if (from_tty)
+ {
+ printf_unfiltered ("No symbol file now.\n");
+ }
+#ifdef HPUXHPPA
+ RESET_HP_UX_GLOBALS ();
+#endif
+ }
+ else
+ {
+ if ((argv = buildargv (args)) == NULL)
+ {
+ nomem (0);
+ }
+ cleanups = make_cleanup ((make_cleanup_func) 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
+ {
+ char *p;
+
+ name = *argv;
+
+ /* this is for rombug remote only, to get the text relocation by
+ using link command */
+ p = strrchr(name, '/');
+ if (p != NULL) p++;
+ else p = name;
+
+ target_link(p, &text_relocation);
+
+ if (text_relocation == (CORE_ADDR)0)
+ return;
+ else if (text_relocation == (CORE_ADDR)-1)
+ {
+ symbol_file_add (name, from_tty, (CORE_ADDR)0,
+ 1, mapped, readnow, 1, 0);
+#ifdef HPUXHPPA
+ RESET_HP_UX_GLOBALS ();
+#endif
+ }
+ else
+ symbol_file_add (name, from_tty, (CORE_ADDR)text_relocation,
+ 0, mapped, readnow, 1, 0);
+
+ /* Getting new symbols may change our opinion about what is
+ frameless. */
+ reinit_frame_cache ();
+
+ set_initial_language ();
+ }
+ argv++;
+ }
+
+ if (name == NULL)
+ {
+ error ("no symbol file name was specified");
+ }
+ TUIDO(((TuiOpaqueFuncPtr)tuiDisplayMainFunction));
+ 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. */
+
+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 defined(__GO32__) || defined(_WIN32)
+ if (desc < 0)
+ {
+ char *exename = alloca (strlen (name) + 5);
+ strcat (strcpy (exename, name), ".exe");
+ desc = openp (getenv ("PATH"), 1, exename, O_RDONLY | O_BINARY,
+ 0, &absolute_name);
+ }
+#endif
+ 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_get_error ()));
+ }
+ sym_bfd->cacheable = true;
+
+ if (!bfd_check_format (sym_bfd, bfd_object))
+ {
+ /* FIXME: should be checking for errors from bfd_close (for one thing,
+ on error it does not free all the storage associated with the
+ bfd). */
+ bfd_close (sym_bfd); /* This also closes desc */
+ make_cleanup (free, name);
+ error ("\"%s\": can't read symbols: %s.", name,
+ bfd_errmsg (bfd_get_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;
+ enum bfd_flavour our_flavour = bfd_get_flavour (objfile -> obfd);
+ char *our_target = bfd_get_target (objfile -> obfd);
+
+ /* Special kludge for RS/6000 and PowerMac. See xcoffread.c. */
+ if (STREQ (our_target, "aixcoff-rs6000") ||
+ STREQ (our_target, "xcoff-powermac"))
+ our_flavour = (enum bfd_flavour)-1;
+
+ /* Special kludge for apollo. See dstread.c. */
+ if (STREQN (our_target, "apollo", 6))
+ our_flavour = (enum bfd_flavour)-2;
+
+ for (sf = symtab_fns; sf != NULL; sf = sf -> next)
+ {
+ if (our_flavour == sf -> sym_flavour)
+ {
+ 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;
+{
+ if (arg == NULL)
+ arg = get_exec_file (1);
+ 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. */
+#define GENERIC_LOAD_CHUNK 256
+#define VALIDATE_DOWNLOAD 0
+void
+generic_load (filename, from_tty)
+ char *filename;
+ int from_tty;
+{
+ struct cleanup *old_cleanups;
+ asection *s;
+ bfd *loadfile_bfd;
+ time_t start_time, end_time; /* Start and end times of download */
+ unsigned long data_count = 0; /* Number of bytes transferred to memory */
+ int n;
+ unsigned long load_offset = 0; /* offset to add to vma for each section */
+ char buf[GENERIC_LOAD_CHUNK+8];
+#if VALIDATE_DOWNLOAD
+ char verify_buffer[GENERIC_LOAD_CHUNK+8] ;
+#endif
+
+ /* enable user to specify address for downloading as 2nd arg to load */
+ n = sscanf(filename, "%s 0x%lx", buf, &load_offset);
+ if (n > 1 )
+ filename = buf;
+ else
+ load_offset = 0;
+
+ loadfile_bfd = bfd_openr (filename, gnutarget);
+ if (loadfile_bfd == NULL)
+ {
+ perror_with_name (filename);
+ return;
+ }
+ /* FIXME: should be checking for errors from bfd_close (for one thing,
+ on error it does not free all the storage associated with the
+ bfd). */
+ old_cleanups = make_cleanup ((make_cleanup_func) bfd_close, loadfile_bfd);
+
+ if (!bfd_check_format (loadfile_bfd, bfd_object))
+ {
+ error ("\"%s\" is not an object file: %s", filename,
+ bfd_errmsg (bfd_get_error ()));
+ }
+
+ start_time = time (NULL);
+
+ 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 lma;
+ unsigned long l = size ;
+ int err;
+ char *sect;
+ unsigned long sent;
+ unsigned long len;
+
+ l = l > GENERIC_LOAD_CHUNK ? GENERIC_LOAD_CHUNK : l ;
+
+ buffer = xmalloc (size);
+ old_chain = make_cleanup (free, buffer);
+
+ lma = s->lma;
+ lma += load_offset;
+
+ /* 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 lma ",
+ bfd_get_section_name (loadfile_bfd, s),
+ (unsigned long) size);
+ print_address_numeric (lma, 1, gdb_stdout);
+ printf_filtered ("\n");
+
+ bfd_get_section_contents (loadfile_bfd, s, buffer, 0, size);
+
+ sect = (char *) bfd_get_section_name (loadfile_bfd, s);
+ sent = 0;
+ do
+ {
+ len = (size - sent) < l ? (size - sent) : l;
+ sent += len;
+ err = target_write_memory (lma, buffer, len);
+ if (ui_load_progress_hook)
+ if (ui_load_progress_hook (sect, sent))
+ error ("Canceled the download");
+#if VALIDATE_DOWNLOAD
+ /* Broken memories and broken monitors manifest themselves
+ here when bring new computers to life.
+ This doubles already slow downloads.
+ */
+ if (err) break ;
+ {
+ target_read_memory(lma,verify_buffer,len) ;
+ if (0 != bcmp(buffer,verify_buffer,len))
+ error("Download verify failed at %08x",
+ (unsigned long)lma) ;
+ }
+
+#endif
+ data_count += len ;
+ lma += len;
+ buffer += len;
+ } /* od */
+ while (err == 0 && sent < size);
+
+ if (err != 0)
+ error ("Memory access error while loading section %s.",
+ bfd_get_section_name (loadfile_bfd, s));
+
+ do_cleanups (old_chain);
+ }
+ }
+ }
+
+ end_time = time (NULL);
+ {
+ unsigned long entry ;
+ entry = bfd_get_start_address(loadfile_bfd) ;
+ printf_filtered ("Start address 0x%lx , load size %d\n", entry,data_count);
+ /* We were doing this in remote-mips.c, I suspect it is right
+ for other targets too. */
+ write_pc (entry);
+ }
+
+ /* 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. */
+
+ report_transfer_performance (data_count, start_time, end_time);
+
+ do_cleanups (old_cleanups);
+}
+
+/* Report how fast the transfer went. */
+
+void
+report_transfer_performance (data_count, start_time, end_time)
+unsigned long data_count;
+time_t start_time, end_time;
+{
+ printf_filtered ("Transfer rate: ");
+ if (end_time != start_time)
+ printf_filtered ("%d bits/sec",
+ (data_count * 8) / (end_time - start_time));
+ else
+ printf_filtered ("%d bits in <1 sec", (data_count * 8));
+ printf_filtered (".\n");
+}
+
+/* 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)
+ {
+ error ("add-symbol-file takes a file name");
+ }
+ name = tilde_expand (name);
+ make_cleanup (free, name);
+
+ if (*args != '\000')
+ {
+ text_addr = parse_and_eval_address (args);
+ }
+ else
+ {
+ target_link(name, &text_addr);
+ if (text_addr == (CORE_ADDR)-1)
+ error("Don't know how to get text start location for this file");
+ }
+
+ /* FIXME-32x64: Assumes text_addr fits in a long. */
+ if ((from_tty)
+ && (!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, from_tty, text_addr, 0, mapped, readnow,
+ 1, /* user_loaded */
+ 0); /* We'll guess it's ! is_solib */
+
+ /* Getting new symbols may change our opinion about what is
+ frameless. */
+ reinit_frame_cache ();
+}
+
+static void
+add_shared_symbol_files_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+#ifdef ADD_SHARED_SYMBOL_FILES
+ ADD_SHARED_SYMBOL_FILES (args, from_tty);
+#else
+ error ("This command is not available in this configuration of GDB.");
+#endif
+}
+
+/* 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 */
+
+ 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)
+ {
+ struct cleanup *old_cleanups;
+ struct section_offsets *offsets;
+ int num_offsets;
+ int section_offsets_size;
+ char *obfd_filename;
+
+ printf_filtered ("`%s' has changed; re-reading symbols.\n",
+ objfile->name);
+
+ /* There are various functions like symbol_file_add,
+ symfile_bfd_open, syms_from_objfile, etc., which might
+ appear to do what we want. But they have various other
+ effects which we *don't* want. So we just do stuff
+ ourselves. We don't worry about mapped files (for one thing,
+ any mapped file will be out of date). */
+
+ /* If we get an error, blow away this objfile (not sure if
+ that is the correct response for things like shared
+ libraries). */
+ old_cleanups = make_cleanup ((make_cleanup_func) free_objfile,
+ objfile);
+ /* We need to do this whenever any symbols go away. */
+ make_cleanup ((make_cleanup_func) clear_symtab_users, 0);
+
+ /* Clean up any state BFD has sitting around. We don't need
+ to close the descriptor but BFD lacks a way of closing the
+ BFD without closing the descriptor. */
+ obfd_filename = bfd_get_filename (objfile->obfd);
+ if (!bfd_close (objfile->obfd))
+ error ("Can't close BFD for %s: %s", objfile->name,
+ bfd_errmsg (bfd_get_error ()));
+ objfile->obfd = bfd_openr (obfd_filename, gnutarget);
+ if (objfile->obfd == NULL)
+ error ("Can't open %s to read symbols.", objfile->name);
+ /* bfd_openr sets cacheable to true, which is what we want. */
+ if (!bfd_check_format (objfile->obfd, bfd_object))
+ error ("Can't read symbols from %s: %s.", objfile->name,
+ bfd_errmsg (bfd_get_error ()));
+
+ /* Save the offsets, we will nuke them with the rest of the
+ psymbol_obstack. */
+ num_offsets = objfile->num_sections;
+ section_offsets_size =
+ sizeof (struct section_offsets)
+ + sizeof (objfile->section_offsets->offsets) * num_offsets;
+ offsets = (struct section_offsets *) alloca (section_offsets_size);
+ memcpy (offsets, objfile->section_offsets, section_offsets_size);
+
+ /* Nuke all the state that we will re-read. Much of the following
+ code which sets things to NULL really is necessary to tell
+ other parts of GDB that there is nothing currently there. */
+
+ /* FIXME: Do we have to free a whole linked list, or is this
+ enough? */
+ if (objfile->global_psymbols.list)
+ mfree (objfile->md, objfile->global_psymbols.list);
+ memset (&objfile -> global_psymbols, 0,
+ sizeof (objfile -> global_psymbols));
+ if (objfile->static_psymbols.list)
+ mfree (objfile->md, objfile->static_psymbols.list);
+ memset (&objfile -> static_psymbols, 0,
+ sizeof (objfile -> static_psymbols));
+
+ /* Free the obstacks for non-reusable objfiles */
+ obstack_free (&objfile -> psymbol_cache.cache, 0);
+ memset (&objfile -> psymbol_cache, 0,
+ sizeof (objfile -> psymbol_cache));
+ obstack_free (&objfile -> psymbol_obstack, 0);
+ obstack_free (&objfile -> symbol_obstack, 0);
+ obstack_free (&objfile -> type_obstack, 0);
+ objfile->sections = NULL;
+ objfile->symtabs = NULL;
+ objfile->psymtabs = NULL;
+ objfile->free_psymtabs = NULL;
+ objfile->msymbols = NULL;
+ objfile->minimal_symbol_count= 0;
+ objfile->fundamental_types = NULL;
+ if (objfile -> sf != NULL)
+ {
+ (*objfile -> sf -> sym_finish) (objfile);
+ }
+
+ /* We never make this a mapped file. */
+ objfile -> md = NULL;
+ /* obstack_specify_allocation also initializes the obstack so
+ it is empty. */
+ obstack_specify_allocation (&objfile -> psymbol_cache.cache, 0, 0,
+ xmalloc, free);
+ 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);
+ if (build_objfile_section_table (objfile))
+ {
+ error ("Can't find the file sections in `%s': %s",
+ objfile -> name, bfd_errmsg (bfd_get_error ()));
+ }
+
+ /* We use the same section offsets as from last time. I'm not
+ sure whether that is always correct for shared libraries. */
+ objfile->section_offsets = (struct section_offsets *)
+ obstack_alloc (&objfile -> psymbol_obstack, section_offsets_size);
+ memcpy (objfile->section_offsets, offsets, section_offsets_size);
+ objfile->num_sections = num_offsets;
+
+ /* What the hell is sym_new_init for, anyway? The concept of
+ distinguishing between the main file and additional files
+ in this way seems rather dubious. */
+ if (objfile == symfile_objfile)
+ {
+ (*objfile->sf->sym_new_init) (objfile);
+#ifdef HPUXHPPA
+ RESET_HP_UX_GLOBALS ();
+#endif
+ }
+
+ (*objfile->sf->sym_init) (objfile);
+ clear_complaints (1, 1);
+ /* The "mainline" parameter is a hideous hack; I think leaving it
+ zero is OK since dbxread.c also does what it needs to do if
+ objfile->global_psymbols.size is 0. */
+ (*objfile->sf->sym_read) (objfile, objfile->section_offsets, 0);
+ if (!have_partial_symbols () && !have_full_symbols ())
+ {
+ wrap_here ("");
+ printf_filtered ("(no debugging symbols found)\n");
+ wrap_here ("");
+ }
+ objfile -> flags |= OBJF_SYMS;
+
+ /* We're done reading the symbol file; finish off complaints. */
+ clear_complaints (0, 1);
+
+ /* Getting new symbols may change our opinion about what is
+ frameless. */
+
+ reinit_frame_cache ();
+
+ /* Discard cleanups as symbol reading was successful. */
+ discard_cleanups (old_cleanups);
+
+ /* If the mtime has changed between the time we set new_modtime
+ and now, we *want* this to be out of date, so don't call stat
+ again now. */
+ objfile->mtime = new_modtime;
+ reread_one = 1;
+
+ /* Call this after reading in a new symbol table to give target
+ dependant code a crack at the new symbols. For instance, this
+ could be used to update the values of target-specific symbols GDB
+ needs to keep track of (such as _sigtramp, or whatever). */
+
+ TARGET_SYMFILE_POSTREAD (objfile);
+ }
+ }
+ }
+
+ if (reread_one)
+ clear_symtab_users ();
+}
+
+
+
+typedef struct {
+ char *ext;
+ enum language lang;
+} filename_language;
+
+static filename_language * filename_language_table;
+static int fl_table_size, fl_table_next;
+
+static void
+add_filename_language (ext, lang)
+ char *ext;
+ enum language lang;
+{
+ if (fl_table_next >= fl_table_size)
+ {
+ fl_table_size += 10;
+ filename_language_table = realloc (filename_language_table,
+ fl_table_size);
+ }
+
+ filename_language_table[fl_table_next].ext = strsave (ext);
+ filename_language_table[fl_table_next].lang = lang;
+ fl_table_next++;
+}
+
+static char *ext_args;
+
+static void
+set_ext_lang_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ int i;
+ char *cp = ext_args;
+ enum language lang;
+
+ /* First arg is filename extension, starting with '.' */
+ if (*cp != '.')
+ error ("'%s': Filename extension must begin with '.'", ext_args);
+
+ /* Find end of first arg. */
+ while (*cp && !isspace (*cp))
+ cp++;
+
+ if (*cp == '\0')
+ error ("'%s': two arguments required -- filename extension and language",
+ ext_args);
+
+ /* Null-terminate first arg */
+ *cp++ = '\0';
+
+ /* Find beginning of second arg, which should be a source language. */
+ while (*cp && isspace (*cp))
+ cp++;
+
+ if (*cp == '\0')
+ error ("'%s': two arguments required -- filename extension and language",
+ ext_args);
+
+ /* Lookup the language from among those we know. */
+ lang = language_enum (cp);
+
+ /* Now lookup the filename extension: do we already know it? */
+ for (i = 0; i < fl_table_next; i++)
+ if (0 == strcmp (ext_args, filename_language_table[i].ext))
+ break;
+
+ if (i >= fl_table_next)
+ {
+ /* new file extension */
+ add_filename_language (ext_args, lang);
+ }
+ else
+ {
+ /* redefining a previously known filename extension */
+
+ /* if (from_tty) */
+ /* query ("Really make files of type %s '%s'?", */
+ /* ext_args, language_str (lang)); */
+
+ free (filename_language_table[i].ext);
+ filename_language_table[i].ext = strsave (ext_args);
+ filename_language_table[i].lang = lang;
+ }
+}
+
+static void
+info_ext_lang_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ int i;
+
+ printf_filtered ("Filename extensions and the languages they represent:");
+ printf_filtered ("\n\n");
+ for (i = 0; i < fl_table_next; i++)
+ printf_filtered ("\t%s\t- %s\n",
+ filename_language_table[i].ext,
+ language_str (filename_language_table[i].lang));
+}
+
+static void
+init_filename_language_table ()
+{
+ if (fl_table_size == 0) /* protect against repetition */
+ {
+ fl_table_size = 20;
+ fl_table_next = 0;
+ filename_language_table =
+ xmalloc (fl_table_size * sizeof (*filename_language_table));
+ add_filename_language (".c", language_c);
+ add_filename_language (".C", language_cplus);
+ add_filename_language (".cc", language_cplus);
+ add_filename_language (".cp", language_cplus);
+ add_filename_language (".cpp", language_cplus);
+ add_filename_language (".cxx", language_cplus);
+ add_filename_language (".c++", language_cplus);
+ add_filename_language (".java", language_java);
+ add_filename_language (".class", language_java);
+ add_filename_language (".ch", language_chill);
+ add_filename_language (".c186", language_chill);
+ add_filename_language (".c286", language_chill);
+ add_filename_language (".f", language_fortran);
+ add_filename_language (".F", language_fortran);
+ add_filename_language (".s", language_asm);
+ add_filename_language (".S", language_asm);
+ }
+}
+
+enum language
+deduce_language_from_filename (filename)
+ char *filename;
+{
+ int i;
+ char *cp;
+
+ if (filename != NULL)
+ if ((cp = strrchr (filename, '.')) != NULL)
+ for (i = 0; i < fl_table_next; i++)
+ if (strcmp (cp, filename_language_table[i].ext) == 0)
+ return filename_language_table[i].lang;
+
+ return language_unknown;
+}
+
+/* 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
+ 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);
+ symtab -> debugformat = obsavestring ("unknown", 7,
+ &objfile -> symbol_obstack);
+
+ /* Hook it to the objfile it comes from */
+
+ symtab -> objfile = objfile;
+ symtab -> next = objfile -> symtabs;
+ objfile -> symtabs = symtab;
+
+ /* FIXME: This should go away. It is only defined for the Z8000,
+ and the Z8000 definition of this macro doesn't have anything to
+ do with the now-nonexistent EXTRA_SYMTAB_INFO macro, it's just
+ here for convenience. */
+#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;
+
+ /* Prepend it to the psymtab list for the objfile it belongs to.
+ Psymtabs are searched in most recent inserted -> least recent
+ inserted order. */
+
+ psymtab -> objfile = objfile;
+ psymtab -> next = objfile -> psymtabs;
+ objfile -> psymtabs = psymtab;
+#if 0
+ {
+ struct partial_symtab **prev_pst;
+ psymtab -> objfile = objfile;
+ psymtab -> next = NULL;
+ prev_pst = &(objfile -> psymtabs);
+ while ((*prev_pst) != NULL)
+ prev_pst = &((*prev_pst) -> next);
+ (*prev_pst) = psymtab;
+ }
+#endif
+
+ return (psymtab);
+}
+
+void
+discard_psymtab (pst)
+ struct partial_symtab *pst;
+{
+ struct partial_symtab **prev_pst;
+
+ /* From dbxread.c:
+ Empty psymtabs happen as a result of header files which don't
+ have any symbols in them. There can be a lot of them. But this
+ check is wrong, in that a psymtab with N_SLINE entries but
+ nothing else is not empty, but we don't realize that. Fixing
+ that without slowing things down might be tricky. */
+
+ /* First, snip it out of the psymtab chain */
+
+ prev_pst = &(pst->objfile->psymtabs);
+ while ((*prev_pst) != pst)
+ prev_pst = &((*prev_pst)->next);
+ (*prev_pst) = pst->next;
+
+ /* Next, put it on a free list for recycling */
+
+ pst->next = pst->objfile->free_psymtabs;
+ pst->objfile->free_psymtabs = pst;
+}
+
+
+/* Reset all data structures in gdb which may contain references to symbol
+ table data. */
+
+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_pc_function_cache ();
+ target_new_objfile (NULL);
+}
+
+/* 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);
+}
+
+/* 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, coreaddr,
+ language, objfile)
+ char *name;
+ int namelength;
+ namespace_enum namespace;
+ enum address_class class;
+ struct psymbol_allocation_list *list;
+ long val; /* Value as a long */
+ CORE_ADDR coreaddr; /* Value as a CORE_ADDR */
+ enum language language;
+ struct objfile *objfile;
+{
+ register struct partial_symbol *psym;
+ char *buf = alloca (namelength + 1);
+ /* psymbol is static so that there will be no uninitialized gaps in the
+ structure which might contain random data, causing cache misses in
+ bcache. */
+ static struct partial_symbol psymbol;
+
+ /* Create local copy of the partial symbol */
+ memcpy (buf, name, namelength);
+ buf[namelength] = '\0';
+ SYMBOL_NAME (&psymbol) = bcache (buf, namelength + 1, &objfile->psymbol_cache);
+ /* val and coreaddr are mutually exclusive, one of them *will* be zero */
+ if (val != 0)
+ {
+ SYMBOL_VALUE (&psymbol) = val;
+ }
+ else
+ {
+ SYMBOL_VALUE_ADDRESS (&psymbol) = coreaddr;
+ }
+ SYMBOL_SECTION (&psymbol) = 0;
+ SYMBOL_LANGUAGE (&psymbol) = language;
+ PSYMBOL_NAMESPACE (&psymbol) = namespace;
+ PSYMBOL_CLASS (&psymbol) = class;
+ SYMBOL_INIT_LANGUAGE_SPECIFIC (&psymbol, language);
+
+ /* Stash the partial symbol away in the cache */
+ psym = bcache (&psymbol, sizeof (struct partial_symbol), &objfile->psymbol_cache);
+
+ /* Save pointer to partial symbol in psymtab, growing symtab if needed. */
+ if (list->next >= list->list + list->size)
+ {
+ extend_psymbol_list (list, objfile);
+ }
+ *list->next++ = psym;
+ OBJSTAT (objfile, n_psyms++);
+}
+
+/* Add a symbol with a long value to a psymtab. This differs from
+ * add_psymbol_to_list above in taking both a mangled and a demangled
+ * name. */
+
+void
+add_psymbol_with_dem_name_to_list (name, namelength, dem_name, dem_namelength,
+ namespace, class, list, val, coreaddr, language, objfile)
+ char *name;
+ int namelength;
+ char *dem_name;
+ int dem_namelength;
+ namespace_enum namespace;
+ enum address_class class;
+ struct psymbol_allocation_list *list;
+ long val; /* Value as a long */
+ CORE_ADDR coreaddr; /* Value as a CORE_ADDR */
+ enum language language;
+ struct objfile *objfile;
+{
+ register struct partial_symbol *psym;
+ char *buf = alloca (namelength + 1);
+ /* psymbol is static so that there will be no uninitialized gaps in the
+ structure which might contain random data, causing cache misses in
+ bcache. */
+ static struct partial_symbol psymbol;
+
+ /* Create local copy of the partial symbol */
+
+ memcpy (buf, name, namelength);
+ buf[namelength] = '\0';
+ SYMBOL_NAME (&psymbol) = bcache (buf, namelength + 1, &objfile->psymbol_cache);
+
+ buf = alloca (dem_namelength + 1);
+ memcpy (buf, dem_name, dem_namelength);
+ buf[dem_namelength] = '\0';
+
+ switch (language)
+ {
+ case language_c:
+ case language_cplus:
+ SYMBOL_CPLUS_DEMANGLED_NAME (&psymbol) =
+ bcache (buf, dem_namelength + 1, &objfile->psymbol_cache);
+ break;
+ case language_chill:
+ SYMBOL_CHILL_DEMANGLED_NAME (&psymbol) =
+ bcache (buf, dem_namelength + 1, &objfile->psymbol_cache);
+
+ /* FIXME What should be done for the default case? Ignoring for now. */
+ }
+
+ /* val and coreaddr are mutually exclusive, one of them *will* be zero */
+ if (val != 0)
+ {
+ SYMBOL_VALUE (&psymbol) = val;
+ }
+ else
+ {
+ SYMBOL_VALUE_ADDRESS (&psymbol) = coreaddr;
+ }
+ SYMBOL_SECTION (&psymbol) = 0;
+ SYMBOL_LANGUAGE (&psymbol) = language;
+ PSYMBOL_NAMESPACE (&psymbol) = namespace;
+ PSYMBOL_CLASS (&psymbol) = class;
+ SYMBOL_INIT_LANGUAGE_SPECIFIC (&psymbol, language);
+
+ /* Stash the partial symbol away in the cache */
+ psym = bcache (&psymbol, sizeof (struct partial_symbol), &objfile->psymbol_cache);
+
+ /* Save pointer to partial symbol in psymtab, growing symtab if needed. */
+ if (list->next >= list->list + list->size)
+ {
+ extend_psymbol_list (list, objfile);
+ }
+ *list->next++ = psym;
+ OBJSTAT (objfile, n_psyms++);
+}
+
+/* Initialize storage for partial symbols. */
+
+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 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;
+
+ if (objfile -> global_psymbols.size > 0)
+ {
+ objfile -> global_psymbols.next =
+ objfile -> global_psymbols.list = (struct partial_symbol **)
+ xmmalloc (objfile -> md, (objfile -> global_psymbols.size
+ * sizeof (struct partial_symbol *)));
+ }
+ if (objfile -> static_psymbols.size > 0)
+ {
+ objfile -> static_psymbols.next =
+ objfile -> static_psymbols.list = (struct partial_symbol **)
+ xmmalloc (objfile -> md, (objfile -> static_psymbols.size
+ * sizeof (struct partial_symbol *)));
+ }
+}
+
+/* OVERLAYS:
+ The following code implements an abstraction for debugging overlay sections.
+
+ The target model is as follows:
+ 1) The gnu linker will permit multiple sections to be mapped into the
+ same VMA, each with its own unique LMA (or load address).
+ 2) It is assumed that some runtime mechanism exists for mapping the
+ sections, one by one, from the load address into the VMA address.
+ 3) This code provides a mechanism for gdb to keep track of which
+ sections should be considered to be mapped from the VMA to the LMA.
+ This information is used for symbol lookup, and memory read/write.
+ For instance, if a section has been mapped then its contents
+ should be read from the VMA, otherwise from the LMA.
+
+ Two levels of debugger support for overlays are available. One is
+ "manual", in which the debugger relies on the user to tell it which
+ overlays are currently mapped. This level of support is
+ implemented entirely in the core debugger, and the information about
+ whether a section is mapped is kept in the objfile->obj_section table.
+
+ The second level of support is "automatic", and is only available if
+ the target-specific code provides functionality to read the target's
+ overlay mapping table, and translate its contents for the debugger
+ (by updating the mapped state information in the obj_section tables).
+
+ The interface is as follows:
+ User commands:
+ overlay map <name> -- tell gdb to consider this section mapped
+ overlay unmap <name> -- tell gdb to consider this section unmapped
+ overlay list -- list the sections that GDB thinks are mapped
+ overlay read-target -- get the target's state of what's mapped
+ overlay off/manual/auto -- set overlay debugging state
+ Functional interface:
+ find_pc_mapped_section(pc): if the pc is in the range of a mapped
+ section, return that section.
+ find_pc_overlay(pc): find any overlay section that contains
+ the pc, either in its VMA or its LMA
+ overlay_is_mapped(sect): true if overlay is marked as mapped
+ section_is_overlay(sect): true if section's VMA != LMA
+ pc_in_mapped_range(pc,sec): true if pc belongs to section's VMA
+ pc_in_unmapped_range(...): true if pc belongs to section's LMA
+ overlay_mapped_address(...): map an address from section's LMA to VMA
+ overlay_unmapped_address(...): map an address from section's VMA to LMA
+ symbol_overlayed_address(...): Return a "current" address for symbol:
+ either in VMA or LMA depending on whether
+ the symbol's section is currently mapped
+ */
+
+/* Overlay debugging state: */
+
+int overlay_debugging = 0; /* 0 == off, 1 == manual, -1 == auto */
+int overlay_cache_invalid = 0; /* True if need to refresh mapped state */
+
+/* Target vector for refreshing overlay mapped state */
+static void simple_overlay_update PARAMS ((struct obj_section *));
+void (*target_overlay_update) PARAMS ((struct obj_section *))
+ = simple_overlay_update;
+
+/* Function: section_is_overlay (SECTION)
+ Returns true if SECTION has VMA not equal to LMA, ie.
+ SECTION is loaded at an address different from where it will "run". */
+
+int
+section_is_overlay (section)
+ asection *section;
+{
+ if (overlay_debugging)
+ if (section && section->lma != 0 &&
+ section->vma != section->lma)
+ return 1;
+
+ return 0;
+}
+
+/* Function: overlay_invalidate_all (void)
+ Invalidate the mapped state of all overlay sections (mark it as stale). */
+
+static void
+overlay_invalidate_all ()
+{
+ struct objfile *objfile;
+ struct obj_section *sect;
+
+ ALL_OBJSECTIONS (objfile, sect)
+ if (section_is_overlay (sect->the_bfd_section))
+ sect->ovly_mapped = -1;
+}
+
+/* Function: overlay_is_mapped (SECTION)
+ Returns true if section is an overlay, and is currently mapped.
+ Private: public access is thru function section_is_mapped.
+
+ Access to the ovly_mapped flag is restricted to this function, so
+ that we can do automatic update. If the global flag
+ OVERLAY_CACHE_INVALID is set (by wait_for_inferior), then call
+ overlay_invalidate_all. If the mapped state of the particular
+ section is stale, then call TARGET_OVERLAY_UPDATE to refresh it. */
+
+static int
+overlay_is_mapped (osect)
+ struct obj_section *osect;
+{
+ if (osect == 0 || !section_is_overlay (osect->the_bfd_section))
+ return 0;
+
+ switch (overlay_debugging)
+ {
+ default:
+ case 0: return 0; /* overlay debugging off */
+ case -1: /* overlay debugging automatic */
+ /* Unles there is a target_overlay_update function,
+ there's really nothing useful to do here (can't really go auto) */
+ if (target_overlay_update)
+ {
+ if (overlay_cache_invalid)
+ {
+ overlay_invalidate_all ();
+ overlay_cache_invalid = 0;
+ }
+ if (osect->ovly_mapped == -1)
+ (*target_overlay_update) (osect);
+ }
+ /* fall thru to manual case */
+ case 1: /* overlay debugging manual */
+ return osect->ovly_mapped == 1;
+ }
+}
+
+/* Function: section_is_mapped
+ Returns true if section is an overlay, and is currently mapped. */
+
+int
+section_is_mapped (section)
+ asection *section;
+{
+ struct objfile *objfile;
+ struct obj_section *osect;
+
+ if (overlay_debugging)
+ if (section && section_is_overlay (section))
+ ALL_OBJSECTIONS (objfile, osect)
+ if (osect->the_bfd_section == section)
+ return overlay_is_mapped (osect);
+
+ return 0;
+}
+
+/* Function: pc_in_unmapped_range
+ If PC falls into the lma range of SECTION, return true, else false. */
+
+CORE_ADDR
+pc_in_unmapped_range (pc, section)
+ CORE_ADDR pc;
+ asection *section;
+{
+ int size;
+
+ if (overlay_debugging)
+ if (section && section_is_overlay (section))
+ {
+ size = bfd_get_section_size_before_reloc (section);
+ if (section->lma <= pc && pc < section->lma + size)
+ return 1;
+ }
+ return 0;
+}
+
+/* Function: pc_in_mapped_range
+ If PC falls into the vma range of SECTION, return true, else false. */
+
+CORE_ADDR
+pc_in_mapped_range (pc, section)
+ CORE_ADDR pc;
+ asection *section;
+{
+ int size;
+
+ if (overlay_debugging)
+ if (section && section_is_overlay (section))
+ {
+ size = bfd_get_section_size_before_reloc (section);
+ if (section->vma <= pc && pc < section->vma + size)
+ return 1;
+ }
+ return 0;
+}
+
+/* Function: overlay_unmapped_address (PC, SECTION)
+ Returns the address corresponding to PC in the unmapped (load) range.
+ May be the same as PC. */
+
+CORE_ADDR
+overlay_unmapped_address (pc, section)
+ CORE_ADDR pc;
+ asection *section;
+{
+ if (overlay_debugging)
+ if (section && section_is_overlay (section) &&
+ pc_in_mapped_range (pc, section))
+ return pc + section->lma - section->vma;
+
+ return pc;
+}
+
+/* Function: overlay_mapped_address (PC, SECTION)
+ Returns the address corresponding to PC in the mapped (runtime) range.
+ May be the same as PC. */
+
+CORE_ADDR
+overlay_mapped_address (pc, section)
+ CORE_ADDR pc;
+ asection *section;
+{
+ if (overlay_debugging)
+ if (section && section_is_overlay (section) &&
+ pc_in_unmapped_range (pc, section))
+ return pc + section->vma - section->lma;
+
+ return pc;
+}
+
+
+/* Function: symbol_overlayed_address
+ Return one of two addresses (relative to the VMA or to the LMA),
+ depending on whether the section is mapped or not. */
+
+CORE_ADDR
+symbol_overlayed_address (address, section)
+ CORE_ADDR address;
+ asection *section;
+{
+ if (overlay_debugging)
+ {
+ /* If the symbol has no section, just return its regular address. */
+ if (section == 0)
+ return address;
+ /* If the symbol's section is not an overlay, just return its address */
+ if (!section_is_overlay (section))
+ return address;
+ /* If the symbol's section is mapped, just return its address */
+ if (section_is_mapped (section))
+ return address;
+ /*
+ * HOWEVER: if the symbol is in an overlay section which is NOT mapped,
+ * then return its LOADED address rather than its vma address!!
+ */
+ return overlay_unmapped_address (address, section);
+ }
+ return address;
+}
+
+/* Function: find_pc_overlay (PC)
+ Return the best-match overlay section for PC:
+ If PC matches a mapped overlay section's VMA, return that section.
+ Else if PC matches an unmapped section's VMA, return that section.
+ Else if PC matches an unmapped section's LMA, return that section. */
+
+asection *
+find_pc_overlay (pc)
+ CORE_ADDR pc;
+{
+ struct objfile *objfile;
+ struct obj_section *osect, *best_match = NULL;
+
+ if (overlay_debugging)
+ ALL_OBJSECTIONS (objfile, osect)
+ if (section_is_overlay (osect->the_bfd_section))
+ {
+ if (pc_in_mapped_range (pc, osect->the_bfd_section))
+ {
+ if (overlay_is_mapped (osect))
+ return osect->the_bfd_section;
+ else
+ best_match = osect;
+ }
+ else if (pc_in_unmapped_range (pc, osect->the_bfd_section))
+ best_match = osect;
+ }
+ return best_match ? best_match->the_bfd_section : NULL;
+}
+
+/* Function: find_pc_mapped_section (PC)
+ If PC falls into the VMA address range of an overlay section that is
+ currently marked as MAPPED, return that section. Else return NULL. */
+
+asection *
+find_pc_mapped_section (pc)
+ CORE_ADDR pc;
+{
+ struct objfile *objfile;
+ struct obj_section *osect;
+
+ if (overlay_debugging)
+ ALL_OBJSECTIONS (objfile, osect)
+ if (pc_in_mapped_range (pc, osect->the_bfd_section) &&
+ overlay_is_mapped (osect))
+ return osect->the_bfd_section;
+
+ return NULL;
+}
+
+/* Function: list_overlays_command
+ Print a list of mapped sections and their PC ranges */
+
+void
+list_overlays_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ int nmapped = 0;
+ struct objfile *objfile;
+ struct obj_section *osect;
+
+ if (overlay_debugging)
+ ALL_OBJSECTIONS (objfile, osect)
+ if (overlay_is_mapped (osect))
+ {
+ const char *name;
+ bfd_vma lma, vma;
+ int size;
+
+ vma = bfd_section_vma (objfile->obfd, osect->the_bfd_section);
+ lma = bfd_section_lma (objfile->obfd, osect->the_bfd_section);
+ size = bfd_get_section_size_before_reloc (osect->the_bfd_section);
+ name = bfd_section_name (objfile->obfd, osect->the_bfd_section);
+
+ printf_filtered ("Section %s, loaded at ", name);
+ print_address_numeric (lma, 1, gdb_stdout);
+ puts_filtered (" - ");
+ print_address_numeric (lma + size, 1, gdb_stdout);
+ printf_filtered (", mapped at ");
+ print_address_numeric (vma, 1, gdb_stdout);
+ puts_filtered (" - ");
+ print_address_numeric (vma + size, 1, gdb_stdout);
+ puts_filtered ("\n");
+
+ nmapped ++;
+ }
+ if (nmapped == 0)
+ printf_filtered ("No sections are mapped.\n");
+}
+
+/* Function: map_overlay_command
+ Mark the named section as mapped (ie. residing at its VMA address). */
+
+void
+map_overlay_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ struct objfile *objfile, *objfile2;
+ struct obj_section *sec, *sec2;
+ asection *bfdsec;
+
+ if (!overlay_debugging)
+ error ("Overlay debugging not enabled. Use the 'OVERLAY ON' command.");
+
+ if (args == 0 || *args == 0)
+ error ("Argument required: name of an overlay section");
+
+ /* First, find a section matching the user supplied argument */
+ ALL_OBJSECTIONS (objfile, sec)
+ if (!strcmp (bfd_section_name (objfile->obfd, sec->the_bfd_section), args))
+ {
+ /* Now, check to see if the section is an overlay. */
+ bfdsec = sec->the_bfd_section;
+ if (!section_is_overlay (bfdsec))
+ continue; /* not an overlay section */
+
+ /* Mark the overlay as "mapped" */
+ sec->ovly_mapped = 1;
+
+ /* Next, make a pass and unmap any sections that are
+ overlapped by this new section: */
+ ALL_OBJSECTIONS (objfile2, sec2)
+ if (sec2->ovly_mapped &&
+ sec != sec2 &&
+ sec->the_bfd_section != sec2->the_bfd_section &&
+ (pc_in_mapped_range (sec2->addr, sec->the_bfd_section) ||
+ pc_in_mapped_range (sec2->endaddr, sec->the_bfd_section)))
+ {
+ if (info_verbose)
+ printf_filtered ("Note: section %s unmapped by overlap\n",
+ bfd_section_name (objfile->obfd,
+ sec2->the_bfd_section));
+ sec2->ovly_mapped = 0; /* sec2 overlaps sec: unmap sec2 */
+ }
+ return;
+ }
+ error ("No overlay section called %s", args);
+}
+
+/* Function: unmap_overlay_command
+ Mark the overlay section as unmapped
+ (ie. resident in its LMA address range, rather than the VMA range). */
+
+void
+unmap_overlay_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ struct objfile *objfile;
+ struct obj_section *sec;
+
+ if (!overlay_debugging)
+ error ("Overlay debugging not enabled. Use the 'OVERLAY ON' command.");
+
+ if (args == 0 || *args == 0)
+ error ("Argument required: name of an overlay section");
+
+ /* First, find a section matching the user supplied argument */
+ ALL_OBJSECTIONS (objfile, sec)
+ if (!strcmp (bfd_section_name (objfile->obfd, sec->the_bfd_section), args))
+ {
+ if (!sec->ovly_mapped)
+ error ("Section %s is not mapped", args);
+ sec->ovly_mapped = 0;
+ return;
+ }
+ error ("No overlay section called %s", args);
+}
+
+/* Function: overlay_auto_command
+ A utility command to turn on overlay debugging.
+ Possibly this should be done via a set/show command. */
+
+static void
+overlay_auto_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ overlay_debugging = -1;
+ if (info_verbose)
+ printf_filtered ("Automatic overlay debugging enabled.");
+}
+
+/* Function: overlay_manual_command
+ A utility command to turn on overlay debugging.
+ Possibly this should be done via a set/show command. */
+
+static void
+overlay_manual_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ overlay_debugging = 1;
+ if (info_verbose)
+ printf_filtered ("Overlay debugging enabled.");
+}
+
+/* Function: overlay_off_command
+ A utility command to turn on overlay debugging.
+ Possibly this should be done via a set/show command. */
+
+static void
+overlay_off_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ overlay_debugging = 0;
+ if (info_verbose)
+ printf_filtered ("Overlay debugging disabled.");
+}
+
+static void
+overlay_load_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ if (target_overlay_update)
+ (*target_overlay_update) (NULL);
+ else
+ error ("This target does not know how to read its overlay state.");
+}
+
+/* Function: overlay_command
+ A place-holder for a mis-typed command */
+
+/* Command list chain containing all defined "overlay" subcommands. */
+struct cmd_list_element *overlaylist;
+
+static void
+overlay_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ printf_unfiltered
+ ("\"overlay\" must be followed by the name of an overlay command.\n");
+ help_list (overlaylist, "overlay ", -1, gdb_stdout);
+}
+
+
+/* Target Overlays for the "Simplest" overlay manager:
+
+ This is GDB's default target overlay layer. It works with the
+ minimal overlay manager supplied as an example by Cygnus. The
+ entry point is via a function pointer "target_overlay_update",
+ so targets that use a different runtime overlay manager can
+ substitute their own overlay_update function and take over the
+ function pointer.
+
+ The overlay_update function pokes around in the target's data structures
+ to see what overlays are mapped, and updates GDB's overlay mapping with
+ this information.
+
+ In this simple implementation, the target data structures are as follows:
+ unsigned _novlys; /# number of overlay sections #/
+ unsigned _ovly_table[_novlys][4] = {
+ {VMA, SIZE, LMA, MAPPED}, /# one entry per overlay section #/
+ {..., ..., ..., ...},
+ }
+ unsigned _novly_regions; /# number of overlay regions #/
+ unsigned _ovly_region_table[_novly_regions][3] = {
+ {VMA, SIZE, MAPPED_TO_LMA}, /# one entry per overlay region #/
+ {..., ..., ...},
+ }
+ These functions will attempt to update GDB's mappedness state in the
+ symbol section table, based on the target's mappedness state.
+
+ To do this, we keep a cached copy of the target's _ovly_table, and
+ attempt to detect when the cached copy is invalidated. The main
+ entry point is "simple_overlay_update(SECT), which looks up SECT in
+ the cached table and re-reads only the entry for that section from
+ the target (whenever possible).
+ */
+
+/* Cached, dynamically allocated copies of the target data structures: */
+static unsigned (*cache_ovly_table)[4] = 0;
+#if 0
+static unsigned (*cache_ovly_region_table)[3] = 0;
+#endif
+static unsigned cache_novlys = 0;
+#if 0
+static unsigned cache_novly_regions = 0;
+#endif
+static CORE_ADDR cache_ovly_table_base = 0;
+#if 0
+static CORE_ADDR cache_ovly_region_table_base = 0;
+#endif
+enum ovly_index { VMA, SIZE, LMA, MAPPED};
+#define TARGET_LONG_BYTES (TARGET_LONG_BIT / TARGET_CHAR_BIT)
+
+/* Throw away the cached copy of _ovly_table */
+static void
+simple_free_overlay_table ()
+{
+ if (cache_ovly_table)
+ free(cache_ovly_table);
+ cache_novlys = 0;
+ cache_ovly_table = NULL;
+ cache_ovly_table_base = 0;
+}
+
+#if 0
+/* Throw away the cached copy of _ovly_region_table */
+static void
+simple_free_overlay_region_table ()
+{
+ if (cache_ovly_region_table)
+ free(cache_ovly_region_table);
+ cache_novly_regions = 0;
+ cache_ovly_region_table = NULL;
+ cache_ovly_region_table_base = 0;
+}
+#endif
+
+/* Read an array of ints from the target into a local buffer.
+ Convert to host order. int LEN is number of ints */
+static void
+read_target_long_array (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ unsigned int *myaddr;
+ int len;
+{
+ char *buf = alloca (len * TARGET_LONG_BYTES);
+ int i;
+
+ read_memory (memaddr, buf, len * TARGET_LONG_BYTES);
+ for (i = 0; i < len; i++)
+ myaddr[i] = extract_unsigned_integer (TARGET_LONG_BYTES * i + buf,
+ TARGET_LONG_BYTES);
+}
+
+/* Find and grab a copy of the target _ovly_table
+ (and _novlys, which is needed for the table's size) */
+static int
+simple_read_overlay_table ()
+{
+ struct minimal_symbol *msym;
+
+ simple_free_overlay_table ();
+ msym = lookup_minimal_symbol ("_novlys", 0, 0);
+ if (msym != NULL)
+ cache_novlys = read_memory_integer (SYMBOL_VALUE_ADDRESS (msym), 4);
+ else
+ return 0; /* failure */
+ cache_ovly_table = (void *) xmalloc (cache_novlys * sizeof(*cache_ovly_table));
+ if (cache_ovly_table != NULL)
+ {
+ msym = lookup_minimal_symbol ("_ovly_table", 0, 0);
+ if (msym != NULL)
+ {
+ cache_ovly_table_base = SYMBOL_VALUE_ADDRESS (msym);
+ read_target_long_array (cache_ovly_table_base,
+ (int *) cache_ovly_table,
+ cache_novlys * 4);
+ }
+ else
+ return 0; /* failure */
+ }
+ else
+ return 0; /* failure */
+ return 1; /* SUCCESS */
+}
+
+#if 0
+/* Find and grab a copy of the target _ovly_region_table
+ (and _novly_regions, which is needed for the table's size) */
+static int
+simple_read_overlay_region_table ()
+{
+ struct minimal_symbol *msym;
+
+ simple_free_overlay_region_table ();
+ msym = lookup_minimal_symbol ("_novly_regions", 0, 0);
+ if (msym != NULL)
+ cache_novly_regions = read_memory_integer (SYMBOL_VALUE_ADDRESS (msym), 4);
+ else
+ return 0; /* failure */
+ cache_ovly_region_table = (void *) xmalloc (cache_novly_regions * 12);
+ if (cache_ovly_region_table != NULL)
+ {
+ msym = lookup_minimal_symbol ("_ovly_region_table", 0, 0);
+ if (msym != NULL)
+ {
+ cache_ovly_region_table_base = SYMBOL_VALUE_ADDRESS (msym);
+ read_target_long_array (cache_ovly_region_table_base,
+ (int *) cache_ovly_region_table,
+ cache_novly_regions * 3);
+ }
+ else
+ return 0; /* failure */
+ }
+ else
+ return 0; /* failure */
+ return 1; /* SUCCESS */
+}
+#endif
+
+/* Function: simple_overlay_update_1
+ A helper function for simple_overlay_update. Assuming a cached copy
+ of _ovly_table exists, look through it to find an entry whose vma,
+ lma and size match those of OSECT. Re-read the entry and make sure
+ it still matches OSECT (else the table may no longer be valid).
+ Set OSECT's mapped state to match the entry. Return: 1 for
+ success, 0 for failure. */
+
+static int
+simple_overlay_update_1 (osect)
+ struct obj_section *osect;
+{
+ int i, size;
+
+ size = bfd_get_section_size_before_reloc (osect->the_bfd_section);
+ for (i = 0; i < cache_novlys; i++)
+ if (cache_ovly_table[i][VMA] == osect->the_bfd_section->vma &&
+ cache_ovly_table[i][LMA] == osect->the_bfd_section->lma /* &&
+ cache_ovly_table[i][SIZE] == size */)
+ {
+ read_target_long_array (cache_ovly_table_base + i * TARGET_LONG_BYTES,
+ (int *) cache_ovly_table[i], 4);
+ if (cache_ovly_table[i][VMA] == osect->the_bfd_section->vma &&
+ cache_ovly_table[i][LMA] == osect->the_bfd_section->lma /* &&
+ cache_ovly_table[i][SIZE] == size */)
+ {
+ osect->ovly_mapped = cache_ovly_table[i][MAPPED];
+ return 1;
+ }
+ else /* Warning! Warning! Target's ovly table has changed! */
+ return 0;
+ }
+ return 0;
+}
+
+/* Function: simple_overlay_update
+ If OSECT is NULL, then update all sections' mapped state
+ (after re-reading the entire target _ovly_table).
+ If OSECT is non-NULL, then try to find a matching entry in the
+ cached ovly_table and update only OSECT's mapped state.
+ If a cached entry can't be found or the cache isn't valid, then
+ re-read the entire cache, and go ahead and update all sections. */
+
+static void
+simple_overlay_update (osect)
+ struct obj_section *osect;
+{
+ struct objfile *objfile;
+
+ /* Were we given an osect to look up? NULL means do all of them. */
+ if (osect)
+ /* Have we got a cached copy of the target's overlay table? */
+ if (cache_ovly_table != NULL)
+ /* Does its cached location match what's currently in the symtab? */
+ if (cache_ovly_table_base ==
+ SYMBOL_VALUE_ADDRESS (lookup_minimal_symbol ("_ovly_table", 0, 0)))
+ /* Then go ahead and try to look up this single section in the cache */
+ if (simple_overlay_update_1 (osect))
+ /* Found it! We're done. */
+ return;
+
+ /* Cached table no good: need to read the entire table anew.
+ Or else we want all the sections, in which case it's actually
+ more efficient to read the whole table in one block anyway. */
+
+ if (simple_read_overlay_table () == 0) /* read failed? No table? */
+ {
+ warning ("Failed to read the target overlay mapping table.");
+ return;
+ }
+ /* Now may as well update all sections, even if only one was requested. */
+ ALL_OBJSECTIONS (objfile, osect)
+ if (section_is_overlay (osect->the_bfd_section))
+ {
+ int i, size;
+
+ size = bfd_get_section_size_before_reloc (osect->the_bfd_section);
+ for (i = 0; i < cache_novlys; i++)
+ if (cache_ovly_table[i][VMA] == osect->the_bfd_section->vma &&
+ cache_ovly_table[i][LMA] == osect->the_bfd_section->lma /* &&
+ cache_ovly_table[i][SIZE] == size */)
+ { /* obj_section matches i'th entry in ovly_table */
+ osect->ovly_mapped = cache_ovly_table[i][MAPPED];
+ break; /* finished with inner for loop: break out */
+ }
+ }
+}
+
+
+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,
+ "Usage: add-symbol-file FILE ADDR\n\
+Load the symbols from FILE, assuming FILE has been dynamically loaded.\n\
+ADDR is the starting address of the file's text.",
+ &cmdlist);
+ c->completer = filename_completer;
+
+ c = add_cmd ("add-shared-symbol-files", class_files,
+ add_shared_symbol_files_command,
+ "Load the symbols from shared objects in the dynamic linker's link map.",
+ &cmdlist);
+ c = add_alias_cmd ("assf", "add-shared-symbol-files", class_files, 1,
+ &cmdlist);
+
+ 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);
+
+ add_prefix_cmd ("overlay", class_support, overlay_command,
+ "Commands for debugging overlays.", &overlaylist,
+ "overlay ", 0, &cmdlist);
+
+ add_com_alias ("ovly", "overlay", class_alias, 1);
+ add_com_alias ("ov", "overlay", class_alias, 1);
+
+ add_cmd ("map-overlay", class_support, map_overlay_command,
+ "Assert that an overlay section is mapped.", &overlaylist);
+
+ add_cmd ("unmap-overlay", class_support, unmap_overlay_command,
+ "Assert that an overlay section is unmapped.", &overlaylist);
+
+ add_cmd ("list-overlays", class_support, list_overlays_command,
+ "List mappings of overlay sections.", &overlaylist);
+
+ add_cmd ("manual", class_support, overlay_manual_command,
+ "Enable overlay debugging.", &overlaylist);
+ add_cmd ("off", class_support, overlay_off_command,
+ "Disable overlay debugging.", &overlaylist);
+ add_cmd ("auto", class_support, overlay_auto_command,
+ "Enable automatic overlay debugging.", &overlaylist);
+ add_cmd ("load-target", class_support, overlay_load_command,
+ "Read the overlay mapping state from the target.", &overlaylist);
+
+ /* Filename extension to source language lookup table: */
+ init_filename_language_table ();
+ c = add_set_cmd ("extension-language", class_files, var_string_noescape,
+ (char *) &ext_args,
+ "Set mapping between filename extension and source language.\n\
+Usage: set extension-language .foo bar",
+ &setlist);
+ c->function.cfunc = set_ext_lang_command;
+
+ add_info ("extensions", info_ext_lang_command,
+ "All filename extensions associated with a source language.");
+}
diff --git a/gdb/symfile.h b/gdb/symfile.h
new file mode 100644
index 00000000000..0363e1e1d28
--- /dev/null
+++ b/gdb/symfile.h
@@ -0,0 +1,300 @@
+/* Definitions for reading symbol files into GDB.
+ Copyright (C) 1990, 1991, 1992, 1993, 1994, 1996
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#if !defined (SYMFILE_H)
+#define SYMFILE_H
+
+/* This file requires that you first include "bfd.h". */
+
+/* Partial symbols are stored in the psymbol_cache and pointers to them
+ are kept in a dynamically grown array that is obtained from malloc and
+ grown as necessary via realloc. Each objfile typically has two of these,
+ one for global symbols and one for static symbols. Although this adds
+ a level of indirection for storing or accessing the partial symbols,
+ it allows us to throw away duplicate psymbols and set all pointers
+ to the single saved instance. */
+
+struct psymbol_allocation_list {
+
+ /* Pointer to beginning of dynamically allocated array of pointers to
+ partial symbols. The array is dynamically expanded as necessary to
+ accommodate more pointers. */
+
+ struct partial_symbol **list;
+
+ /* Pointer to next available slot in which to store a pointer to a partial
+ symbol. */
+
+ struct partial_symbol **next;
+
+ /* Number of allocated pointer slots in current dynamic array (not the
+ number of bytes of storage). The "next" pointer will always point
+ somewhere between list[0] and list[size], and when at list[size] the
+ array will be expanded on the next attempt to store a pointer. */
+
+ int size;
+};
+
+/* Structure to keep track of symbol reading functions for various
+ object file types. */
+
+struct sym_fns {
+
+ /* BFD flavour that we handle, or (as a special kludge, see xcoffread.c,
+ (enum bfd_flavour)-1 for xcoff). */
+
+ enum bfd_flavour sym_flavour;
+
+ /* 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;
+
+};
+
+/* The default version of sym_fns.sym_offsets for readers that don't
+ do anything special. */
+
+extern struct section_offsets *
+default_symfile_offsets PARAMS ((struct objfile *objfile, CORE_ADDR addr));
+
+
+extern void
+extend_psymbol_list PARAMS ((struct psymbol_allocation_list *,
+ struct objfile *));
+
+/* Add any kind of symbol to a psymbol_allocation_list. */
+
+/* #include "demangle.h" */
+
+extern void
+add_psymbol_to_list PARAMS ((char *, int, namespace_enum, enum address_class,
+ struct psymbol_allocation_list *, long, CORE_ADDR,
+ enum language, struct objfile *));
+
+extern void
+add_psymbol_with_dem_name_to_list PARAMS ((char *, int, char *, int, namespace_enum,
+ enum address_class,
+ struct psymbol_allocation_list *,
+ long, CORE_ADDR,
+ enum language, struct objfile *));
+
+
+extern void init_psymbol_list PARAMS ((struct objfile *, int));
+
+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 *));
+
+/* 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 */
+
+/* whether to auto load solibs at startup time: 0/1.
+
+ On all platforms, 0 means "don't auto load".
+
+ On HP-UX, > 0 means a threshhold, in megabytes, of symbol table which will
+ be auto loaded. When the cumulative size of solib symbol table exceeds
+ this threshhold, solibs' symbol tables will not be loaded.
+
+ On other platforms, > 0 means, "always auto load".
+ */
+
+extern int auto_solib_add;
+
+/* From symfile.c */
+
+extern CORE_ADDR
+entry_point_address PARAMS ((void));
+
+extern struct partial_symtab *
+allocate_psymtab PARAMS ((char *, struct objfile *));
+
+extern void
+discard_psymtab PARAMS ((struct partial_symtab *));
+
+extern void find_lowest_section PARAMS ((bfd *, asection *, PTR));
+
+extern bfd * symfile_bfd_open PARAMS ((char *));
+
+/* Remote targets may wish to use this as their load function. */
+extern void generic_load PARAMS ((char *name, int from_tty));
+
+/* Utility functions for overlay sections: */
+extern int overlay_debugging;
+extern int overlay_cache_invalid;
+
+/* return the "mapped" overlay section containing the PC */
+extern asection *
+find_pc_mapped_section PARAMS ((CORE_ADDR));
+
+/* return any overlay section containing the PC (even in its LMA region) */
+extern asection *
+find_pc_overlay PARAMS ((CORE_ADDR));
+
+/* return true if the section is an overlay */
+extern int
+section_is_overlay PARAMS ((asection *));
+
+/* return true if the overlay section is currently "mapped" */
+extern int
+section_is_mapped PARAMS ((asection *));
+
+/* return true if pc belongs to section's VMA */
+extern CORE_ADDR
+pc_in_mapped_range PARAMS ((CORE_ADDR, asection *));
+
+/* return true if pc belongs to section's LMA */
+extern CORE_ADDR
+pc_in_unmapped_range PARAMS ((CORE_ADDR, asection *));
+
+/* map an address from a section's LMA to its VMA */
+extern CORE_ADDR
+overlay_mapped_address PARAMS ((CORE_ADDR, asection *));
+
+/* map an address from a section's VMA to its LMA */
+extern CORE_ADDR
+overlay_unmapped_address PARAMS ((CORE_ADDR, asection *));
+
+/* convert an address in an overlay section (force into VMA range) */
+extern CORE_ADDR
+symbol_overlayed_address PARAMS ((CORE_ADDR, asection *));
+
+/* From dwarfread.c */
+
+extern void
+dwarf_build_psymtabs PARAMS ((struct objfile *, struct section_offsets *, int,
+ file_ptr, unsigned int, file_ptr, unsigned int));
+
+/* From dwarf2read.c */
+
+extern int dwarf2_has_info PARAMS ((bfd *abfd));
+
+extern void dwarf2_build_psymtabs PARAMS ((struct objfile *,
+ struct section_offsets *,
+ int));
+/* From mdebugread.c */
+
+/* Hack to force structures to exist before use in parameter list. */
+struct ecoff_debug_hack
+{
+ struct ecoff_debug_swap *a;
+ struct ecoff_debug_info *b;
+};
+extern void
+mdebug_build_psymtabs PARAMS ((struct objfile *,
+ const struct ecoff_debug_swap *,
+ struct ecoff_debug_info *,
+ struct section_offsets *));
+
+extern void
+elfmdebug_build_psymtabs PARAMS ((struct objfile *,
+ const struct ecoff_debug_swap *,
+ asection *,
+ struct section_offsets *));
+
+#endif /* !defined(SYMFILE_H) */
diff --git a/gdb/symm-nat.c b/gdb/symm-nat.c
new file mode 100644
index 00000000000..04610660cd5
--- /dev/null
+++ b/gdb/symm-nat.c
@@ -0,0 +1,846 @@
+/* Sequent Symmetry host interface, for GDB when running under Unix.
+ Copyright 1986, 1987, 1989, 1991, 1992, 1994 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* FIXME, some 387-specific items of use taken from i387-tdep.c -- ought to be
+ merged back in. */
+
+#include "defs.h"
+#include "frame.h"
+#include "inferior.h"
+#include "symtab.h"
+#include "target.h"
+
+/* FIXME: What is the _INKERNEL define for? */
+#define _INKERNEL
+#include <signal.h>
+#undef _INKERNEL
+#include <sys/wait.h>
+#include <sys/param.h>
+#include <sys/user.h>
+#include <sys/proc.h>
+#include <sys/dir.h>
+#include <sys/ioctl.h>
+#include "gdb_stat.h"
+#ifdef _SEQUENT_
+#include <sys/ptrace.h>
+#else
+/* Dynix has only machine/ptrace.h, which is already included by sys/user.h */
+/* Dynix has no mptrace call */
+#define mptrace ptrace
+#endif
+#include "gdbcore.h"
+#include <fcntl.h>
+#include <sgtty.h>
+#define TERMINAL struct sgttyb
+
+#include "gdbcore.h"
+
+void
+store_inferior_registers(regno)
+int regno;
+{
+ struct pt_regset regs;
+ int i;
+ extern char registers[];
+
+ /* FIXME: Fetching the registers is a kludge to initialize all elements
+ in the fpu and fpa status. This works for normal debugging, but
+ might cause problems when calling functions in the inferior.
+ At least fpu_control and fpa_pcr (probably more) should be added
+ to the registers array to solve this properly. */
+ mptrace (XPT_RREGS, inferior_pid, (PTRACE_ARG3_TYPE) &regs, 0);
+
+ regs.pr_eax = *(int *)&registers[REGISTER_BYTE(0)];
+ regs.pr_ebx = *(int *)&registers[REGISTER_BYTE(5)];
+ regs.pr_ecx = *(int *)&registers[REGISTER_BYTE(2)];
+ regs.pr_edx = *(int *)&registers[REGISTER_BYTE(1)];
+ regs.pr_esi = *(int *)&registers[REGISTER_BYTE(6)];
+ regs.pr_edi = *(int *)&registers[REGISTER_BYTE(7)];
+ regs.pr_esp = *(int *)&registers[REGISTER_BYTE(14)];
+ regs.pr_ebp = *(int *)&registers[REGISTER_BYTE(15)];
+ regs.pr_eip = *(int *)&registers[REGISTER_BYTE(16)];
+ regs.pr_flags = *(int *)&registers[REGISTER_BYTE(17)];
+ for (i = 0; i < 31; i++)
+ {
+ regs.pr_fpa.fpa_regs[i] =
+ *(int *)&registers[REGISTER_BYTE(FP1_REGNUM+i)];
+ }
+ memcpy (regs.pr_fpu.fpu_stack[0], &registers[REGISTER_BYTE(ST0_REGNUM)], 10);
+ memcpy (regs.pr_fpu.fpu_stack[1], &registers[REGISTER_BYTE(ST1_REGNUM)], 10);
+ memcpy (regs.pr_fpu.fpu_stack[2], &registers[REGISTER_BYTE(ST2_REGNUM)], 10);
+ memcpy (regs.pr_fpu.fpu_stack[3], &registers[REGISTER_BYTE(ST3_REGNUM)], 10);
+ memcpy (regs.pr_fpu.fpu_stack[4], &registers[REGISTER_BYTE(ST4_REGNUM)], 10);
+ memcpy (regs.pr_fpu.fpu_stack[5], &registers[REGISTER_BYTE(ST5_REGNUM)], 10);
+ memcpy (regs.pr_fpu.fpu_stack[6], &registers[REGISTER_BYTE(ST6_REGNUM)], 10);
+ memcpy (regs.pr_fpu.fpu_stack[7], &registers[REGISTER_BYTE(ST7_REGNUM)], 10);
+ mptrace (XPT_WREGS, inferior_pid, (PTRACE_ARG3_TYPE) &regs, 0);
+}
+
+void
+fetch_inferior_registers (regno)
+ int regno;
+{
+ int i;
+ struct pt_regset regs;
+ extern char registers[];
+
+ registers_fetched ();
+
+ mptrace (XPT_RREGS, inferior_pid, (PTRACE_ARG3_TYPE) &regs, 0);
+ *(int *)&registers[REGISTER_BYTE(EAX_REGNUM)] = regs.pr_eax;
+ *(int *)&registers[REGISTER_BYTE(EBX_REGNUM)] = regs.pr_ebx;
+ *(int *)&registers[REGISTER_BYTE(ECX_REGNUM)] = regs.pr_ecx;
+ *(int *)&registers[REGISTER_BYTE(EDX_REGNUM)] = regs.pr_edx;
+ *(int *)&registers[REGISTER_BYTE(ESI_REGNUM)] = regs.pr_esi;
+ *(int *)&registers[REGISTER_BYTE(EDI_REGNUM)] = regs.pr_edi;
+ *(int *)&registers[REGISTER_BYTE(EBP_REGNUM)] = regs.pr_ebp;
+ *(int *)&registers[REGISTER_BYTE(ESP_REGNUM)] = regs.pr_esp;
+ *(int *)&registers[REGISTER_BYTE(EIP_REGNUM)] = regs.pr_eip;
+ *(int *)&registers[REGISTER_BYTE(EFLAGS_REGNUM)] = regs.pr_flags;
+ for (i = 0; i < FPA_NREGS; i++)
+ {
+ *(int *)&registers[REGISTER_BYTE(FP1_REGNUM+i)] =
+ regs.pr_fpa.fpa_regs[i];
+ }
+ memcpy (&registers[REGISTER_BYTE(ST0_REGNUM)], regs.pr_fpu.fpu_stack[0], 10);
+ memcpy (&registers[REGISTER_BYTE(ST1_REGNUM)], regs.pr_fpu.fpu_stack[1], 10);
+ memcpy (&registers[REGISTER_BYTE(ST2_REGNUM)], regs.pr_fpu.fpu_stack[2], 10);
+ memcpy (&registers[REGISTER_BYTE(ST3_REGNUM)], regs.pr_fpu.fpu_stack[3], 10);
+ memcpy (&registers[REGISTER_BYTE(ST4_REGNUM)], regs.pr_fpu.fpu_stack[4], 10);
+ memcpy (&registers[REGISTER_BYTE(ST5_REGNUM)], regs.pr_fpu.fpu_stack[5], 10);
+ memcpy (&registers[REGISTER_BYTE(ST6_REGNUM)], regs.pr_fpu.fpu_stack[6], 10);
+ memcpy (&registers[REGISTER_BYTE(ST7_REGNUM)], regs.pr_fpu.fpu_stack[7], 10);
+}
+
+/* FIXME: This should be merged with i387-tdep.c as well. */
+static
+print_fpu_status(ep)
+struct pt_regset ep;
+{
+ int i;
+ int bothstatus;
+ int top;
+ int fpreg;
+ unsigned char *p;
+
+ printf_unfiltered("80387:");
+ if (ep.pr_fpu.fpu_ip == 0) {
+ printf_unfiltered(" not in use.\n");
+ return;
+ } else {
+ printf_unfiltered("\n");
+ }
+ if (ep.pr_fpu.fpu_status != 0) {
+ print_387_status_word (ep.pr_fpu.fpu_status);
+ }
+ print_387_control_word (ep.pr_fpu.fpu_control);
+ printf_unfiltered ("last exception: ");
+ printf_unfiltered ("opcode 0x%x; ", ep.pr_fpu.fpu_rsvd4);
+ printf_unfiltered ("pc 0x%x:0x%x; ", ep.pr_fpu.fpu_cs, ep.pr_fpu.fpu_ip);
+ printf_unfiltered ("operand 0x%x:0x%x\n", ep.pr_fpu.fpu_data_offset, ep.pr_fpu.fpu_op_sel);
+
+ top = (ep.pr_fpu.fpu_status >> 11) & 7;
+
+ printf_unfiltered ("regno tag msb lsb value\n");
+ for (fpreg = 7; fpreg >= 0; fpreg--)
+ {
+ double val;
+
+ printf_unfiltered ("%s %d: ", fpreg == top ? "=>" : " ", fpreg);
+
+ switch ((ep.pr_fpu.fpu_tag >> (fpreg * 2)) & 3)
+ {
+ case 0: printf_unfiltered ("valid "); break;
+ case 1: printf_unfiltered ("zero "); break;
+ case 2: printf_unfiltered ("trap "); break;
+ case 3: printf_unfiltered ("empty "); break;
+ }
+ for (i = 9; i >= 0; i--)
+ printf_unfiltered ("%02x", ep.pr_fpu.fpu_stack[fpreg][i]);
+
+ i387_to_double ((char *)ep.pr_fpu.fpu_stack[fpreg], (char *)&val);
+ printf_unfiltered (" %g\n", val);
+ }
+ if (ep.pr_fpu.fpu_rsvd1)
+ warning ("rsvd1 is 0x%x\n", ep.pr_fpu.fpu_rsvd1);
+ if (ep.pr_fpu.fpu_rsvd2)
+ warning ("rsvd2 is 0x%x\n", ep.pr_fpu.fpu_rsvd2);
+ if (ep.pr_fpu.fpu_rsvd3)
+ warning ("rsvd3 is 0x%x\n", ep.pr_fpu.fpu_rsvd3);
+ if (ep.pr_fpu.fpu_rsvd5)
+ warning ("rsvd5 is 0x%x\n", ep.pr_fpu.fpu_rsvd5);
+}
+
+
+print_1167_control_word(pcr)
+unsigned int pcr;
+
+{
+ int pcr_tmp;
+
+ pcr_tmp = pcr & FPA_PCR_MODE;
+ printf_unfiltered("\tMODE= %#x; RND= %#x ", pcr_tmp, pcr_tmp & 12);
+ switch (pcr_tmp & 12) {
+ case 0:
+ printf_unfiltered("RN (Nearest Value)");
+ break;
+ case 1:
+ printf_unfiltered("RZ (Zero)");
+ break;
+ case 2:
+ printf_unfiltered("RP (Positive Infinity)");
+ break;
+ case 3:
+ printf_unfiltered("RM (Negative Infinity)");
+ break;
+ }
+ printf_unfiltered("; IRND= %d ", pcr_tmp & 2);
+ if (0 == pcr_tmp & 2) {
+ printf_unfiltered("(same as RND)\n");
+ } else {
+ printf_unfiltered("(toward zero)\n");
+ }
+ pcr_tmp = pcr & FPA_PCR_EM;
+ printf_unfiltered("\tEM= %#x", pcr_tmp);
+ if (pcr_tmp & FPA_PCR_EM_DM) printf_unfiltered(" DM");
+ if (pcr_tmp & FPA_PCR_EM_UOM) printf_unfiltered(" UOM");
+ if (pcr_tmp & FPA_PCR_EM_PM) printf_unfiltered(" PM");
+ if (pcr_tmp & FPA_PCR_EM_UM) printf_unfiltered(" UM");
+ if (pcr_tmp & FPA_PCR_EM_OM) printf_unfiltered(" OM");
+ if (pcr_tmp & FPA_PCR_EM_ZM) printf_unfiltered(" ZM");
+ if (pcr_tmp & FPA_PCR_EM_IM) printf_unfiltered(" IM");
+ printf_unfiltered("\n");
+ pcr_tmp = FPA_PCR_CC;
+ printf_unfiltered("\tCC= %#x", pcr_tmp);
+ if (pcr_tmp & FPA_PCR_20MHZ) printf_unfiltered(" 20MHZ");
+ if (pcr_tmp & FPA_PCR_CC_Z) printf_unfiltered(" Z");
+ if (pcr_tmp & FPA_PCR_CC_C2) printf_unfiltered(" C2");
+
+ /* Dynix defines FPA_PCR_CC_C0 to 0x100 and ptx defines
+ FPA_PCR_CC_C1 to 0x100. Use whichever is defined and assume
+ the OS knows what it is doing. */
+#ifdef FPA_PCR_CC_C1
+ if (pcr_tmp & FPA_PCR_CC_C1) printf_unfiltered(" C1");
+#else
+ if (pcr_tmp & FPA_PCR_CC_C0) printf_unfiltered(" C0");
+#endif
+
+ switch (pcr_tmp)
+ {
+ case FPA_PCR_CC_Z:
+ printf_unfiltered(" (Equal)");
+ break;
+#ifdef FPA_PCR_CC_C1
+ case FPA_PCR_CC_C1:
+#else
+ case FPA_PCR_CC_C0:
+#endif
+ printf_unfiltered(" (Less than)");
+ break;
+ case 0:
+ printf_unfiltered(" (Greater than)");
+ break;
+ case FPA_PCR_CC_Z |
+#ifdef FPA_PCR_CC_C1
+ FPA_PCR_CC_C1
+#else
+ FPA_PCR_CC_C0
+#endif
+ | FPA_PCR_CC_C2:
+ printf_unfiltered(" (Unordered)");
+ break;
+ default:
+ printf_unfiltered(" (Undefined)");
+ break;
+ }
+ printf_unfiltered("\n");
+ pcr_tmp = pcr & FPA_PCR_AE;
+ printf_unfiltered("\tAE= %#x", pcr_tmp);
+ if (pcr_tmp & FPA_PCR_AE_DE) printf_unfiltered(" DE");
+ if (pcr_tmp & FPA_PCR_AE_UOE) printf_unfiltered(" UOE");
+ if (pcr_tmp & FPA_PCR_AE_PE) printf_unfiltered(" PE");
+ if (pcr_tmp & FPA_PCR_AE_UE) printf_unfiltered(" UE");
+ if (pcr_tmp & FPA_PCR_AE_OE) printf_unfiltered(" OE");
+ if (pcr_tmp & FPA_PCR_AE_ZE) printf_unfiltered(" ZE");
+ if (pcr_tmp & FPA_PCR_AE_EE) printf_unfiltered(" EE");
+ if (pcr_tmp & FPA_PCR_AE_IE) printf_unfiltered(" IE");
+ printf_unfiltered("\n");
+}
+
+print_1167_regs(regs)
+long regs[FPA_NREGS];
+
+{
+ int i;
+
+ union {
+ double d;
+ long l[2];
+ } xd;
+ union {
+ float f;
+ long l;
+ } xf;
+
+
+ for (i = 0; i < FPA_NREGS; i++) {
+ xf.l = regs[i];
+ printf_unfiltered("%%fp%d: raw= %#x, single= %f", i+1, regs[i], xf.f);
+ if (!(i & 1)) {
+ printf_unfiltered("\n");
+ } else {
+ xd.l[1] = regs[i];
+ xd.l[0] = regs[i+1];
+ printf_unfiltered(", double= %f\n", xd.d);
+ }
+ }
+}
+
+print_fpa_status(ep)
+struct pt_regset ep;
+
+{
+
+ printf_unfiltered("WTL 1167:");
+ if (ep.pr_fpa.fpa_pcr !=0) {
+ printf_unfiltered("\n");
+ print_1167_control_word(ep.pr_fpa.fpa_pcr);
+ print_1167_regs(ep.pr_fpa.fpa_regs);
+ } else {
+ printf_unfiltered(" not in use.\n");
+ }
+}
+
+#if 0 /* disabled because it doesn't go through the target vector. */
+i386_float_info ()
+{
+ char ubuf[UPAGES*NBPG];
+ struct pt_regset regset;
+
+ if (have_inferior_p())
+ {
+ PTRACE_READ_REGS (inferior_pid, (PTRACE_ARG3_TYPE) &regset);
+ }
+ else
+ {
+ int corechan = bfd_cache_lookup (core_bfd);
+ if (lseek (corechan, 0, 0) < 0)
+ {
+ perror ("seek on core file");
+ }
+ if (myread (corechan, ubuf, UPAGES*NBPG) < 0)
+ {
+ perror ("read on core file");
+ }
+ /* only interested in the floating point registers */
+ regset.pr_fpu = ((struct user *) ubuf)->u_fpusave;
+ regset.pr_fpa = ((struct user *) ubuf)->u_fpasave;
+ }
+ print_fpu_status(regset);
+ print_fpa_status(regset);
+}
+#endif
+
+static volatile int got_sigchld;
+
+/*ARGSUSED*/
+/* This will eventually be more interesting. */
+void
+sigchld_handler(signo)
+ int signo;
+{
+ got_sigchld++;
+}
+
+/*
+ * Signals for which the default action does not cause the process
+ * to die. See <sys/signal.h> for where this came from (alas, we
+ * can't use those macros directly)
+ */
+#ifndef sigmask
+#define sigmask(s) (1 << ((s) - 1))
+#endif
+#define SIGNALS_DFL_SAFE sigmask(SIGSTOP) | sigmask(SIGTSTP) | \
+ sigmask(SIGTTIN) | sigmask(SIGTTOU) | sigmask(SIGCHLD) | \
+ sigmask(SIGCONT) | sigmask(SIGWINCH) | sigmask(SIGPWR) | \
+ sigmask(SIGURG) | sigmask(SIGPOLL)
+
+#ifdef ATTACH_DETACH
+/*
+ * Thanks to XPT_MPDEBUGGER, we have to mange child_wait().
+ */
+int
+child_wait(pid, status)
+ int pid;
+ struct target_waitstatus *status;
+{
+ int save_errno, rv, xvaloff, saoff, sa_hand;
+ struct pt_stop pt;
+ struct user u;
+ sigset_t set;
+ /* Host signal number for a signal which the inferior terminates with, or
+ 0 if it hasn't terminated due to a signal. */
+ static int death_by_signal = 0;
+#ifdef SVR4_SHARED_LIBS /* use this to distinguish ptx 2 vs ptx 4 */
+ prstatus_t pstatus;
+#endif
+
+ do {
+ set_sigint_trap(); /* Causes SIGINT to be passed on to the
+ attached process. */
+ save_errno = errno;
+
+ got_sigchld = 0;
+
+ sigemptyset(&set);
+
+ while (got_sigchld == 0) {
+ sigsuspend(&set);
+ }
+
+ clear_sigint_trap();
+
+ rv = mptrace(XPT_STOPSTAT, 0, (char *)&pt, 0);
+ if (-1 == rv) {
+ printf("XPT_STOPSTAT: errno %d\n", errno); /* DEBUG */
+ continue;
+ }
+
+ pid = pt.ps_pid;
+
+ if (pid != inferior_pid) {
+ /* NOTE: the mystery fork in csh/tcsh needs to be ignored.
+ * We should not return new children for the initial run
+ * of a process until it has done the exec.
+ */
+ /* inferior probably forked; send it on its way */
+ rv = mptrace(XPT_UNDEBUG, pid, 0, 0);
+ if (-1 == rv) {
+ printf("child_wait: XPT_UNDEBUG: pid %d: %s\n", pid,
+ safe_strerror(errno));
+ }
+ continue;
+ }
+ /* FIXME: Do we deal with fork notification correctly? */
+ switch (pt.ps_reason) {
+ case PTS_FORK:
+ /* multi proc: treat like PTS_EXEC */
+ /*
+ * Pretend this didn't happen, since gdb isn't set up
+ * to deal with stops on fork.
+ */
+ rv = ptrace(PT_CONTSIG, pid, 1, 0);
+ if (-1 == rv) {
+ printf("PTS_FORK: PT_CONTSIG: error %d\n", errno);
+ }
+ continue;
+ case PTS_EXEC:
+ /*
+ * Pretend this is a SIGTRAP.
+ */
+ status->kind = TARGET_WAITKIND_STOPPED;
+ status->value.sig = TARGET_SIGNAL_TRAP;
+ break;
+ case PTS_EXIT:
+ /*
+ * Note: we stop before the exit actually occurs. Extract
+ * the exit code from the uarea. If we're stopped in the
+ * exit() system call, the exit code will be in
+ * u.u_ap[0]. An exit due to an uncaught signal will have
+ * something else in here, see the comment in the default:
+ * case, below. Finally,let the process exit.
+ */
+ if (death_by_signal)
+ {
+ status->kind = TARGET_WAITKIND_SIGNALED;
+ status->value.sig = target_signal_from_host (death_by_signal);
+ death_by_signal = 0;
+ break;
+ }
+ xvaloff = (unsigned long)&u.u_ap[0] - (unsigned long)&u;
+ errno = 0;
+ rv = ptrace(PT_RUSER, pid, (char *)xvaloff, 0);
+ status->kind = TARGET_WAITKIND_EXITED;
+ status->value.integer = rv;
+ /*
+ * addr & data to mptrace() don't matter here, since
+ * the process is already dead.
+ */
+ rv = mptrace(XPT_UNDEBUG, pid, 0, 0);
+ if (-1 == rv) {
+ printf("child_wait: PTS_EXIT: XPT_UNDEBUG: pid %d error %d\n", pid,
+ errno);
+ }
+ break;
+ case PTS_WATCHPT_HIT:
+ fatal("PTS_WATCHPT_HIT\n");
+ break;
+ default:
+ /* stopped by signal */
+ status->kind = TARGET_WAITKIND_STOPPED;
+ status->value.sig = target_signal_from_host (pt.ps_reason);
+ death_by_signal = 0;
+
+ if (0 == (SIGNALS_DFL_SAFE & sigmask(pt.ps_reason))) {
+ break;
+ }
+ /* else default action of signal is to die */
+#ifdef SVR4_SHARED_LIBS
+ rv = ptrace(PT_GET_PRSTATUS, pid, (char *)&pstatus, 0);
+ if (-1 == rv)
+ error("child_wait: signal %d PT_GET_PRSTATUS: %s\n",
+ pt.ps_reason, safe_strerror(errno));
+ if (pstatus.pr_cursig != pt.ps_reason) {
+ printf("pstatus signal %d, pt signal %d\n",
+ pstatus.pr_cursig, pt.ps_reason);
+ }
+ sa_hand = (int)pstatus.pr_action.sa_handler;
+#else
+ saoff = (unsigned long)&u.u_sa[0] - (unsigned long)&u;
+ saoff += sizeof(struct sigaction) * (pt.ps_reason - 1);
+ errno = 0;
+ sa_hand = ptrace(PT_RUSER, pid, (char *)saoff, 0);
+ if (errno)
+ error("child_wait: signal %d: RUSER: %s\n",
+ pt.ps_reason, safe_strerror(errno));
+#endif
+ if ((int)SIG_DFL == sa_hand) {
+ /* we will be dying */
+ death_by_signal = pt.ps_reason;
+ }
+ break;
+ }
+
+ } while (pid != inferior_pid); /* Some other child died or stopped */
+
+ return pid;
+}
+#else /* !ATTACH_DETACH */
+/*
+ * Simple child_wait() based on inftarg.c child_wait() for use until
+ * the MPDEBUGGER child_wait() works properly. This will go away when
+ * that is fixed.
+ */
+child_wait (pid, ourstatus)
+ int pid;
+ struct target_waitstatus *ourstatus;
+{
+ int save_errno;
+ int status;
+
+ do {
+ pid = wait (&status);
+ save_errno = errno;
+
+ if (pid == -1)
+ {
+ if (save_errno == EINTR)
+ continue;
+ fprintf (stderr, "Child process unexpectedly missing: %s.\n",
+ safe_strerror (save_errno));
+ ourstatus->kind = TARGET_WAITKIND_SIGNALLED;
+ ourstatus->value.sig = TARGET_SIGNAL_UNKNOWN;
+ return -1;
+ }
+ } while (pid != inferior_pid); /* Some other child died or stopped */
+ store_waitstatus (ourstatus, status);
+ return pid;
+}
+#endif /* ATTACH_DETACH */
+
+
+
+/* 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);
+}
+
+int
+call_mptrace(request, pid, addr, data)
+ int request, pid;
+ PTRACE_ARG3_TYPE addr;
+ int data;
+{
+ return mptrace(request, pid, addr, data);
+}
+
+#if defined (DEBUG_PTRACE)
+/* For the rest of the file, use an extra level of indirection */
+/* This lets us breakpoint usefully on call_ptrace. */
+#define ptrace call_ptrace
+#define mptrace call_mptrace
+#endif
+
+void
+kill_inferior ()
+{
+ if (inferior_pid == 0)
+ return;
+
+ /* For MPDEBUGGER, don't use PT_KILL, since the child will stop
+ again with a PTS_EXIT. Just hit him with SIGKILL (so he stops)
+ and detach. */
+
+ kill (inferior_pid, SIGKILL);
+#ifdef ATTACH_DETACH
+ detach(SIGKILL);
+#else /* ATTACH_DETACH */
+ ptrace(PT_KILL, inferior_pid, 0, 0);
+ wait((int *)NULL);
+#endif /* ATTACH_DETACH */
+ 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;
+ enum target_signal 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_SSTEP, 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_SSTEP, pid, (PTRACE_ARG3_TYPE) 1, signal);
+ else
+ ptrace (PT_CONTSIG, 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;
+{
+ sigset_t set;
+ int rv;
+
+ rv = mptrace(XPT_DEBUG, pid, 0, 0);
+ if (-1 == rv) {
+ error("mptrace(XPT_DEBUG): %s", safe_strerror(errno));
+ }
+ rv = mptrace(XPT_SIGNAL, pid, 0, SIGSTOP);
+ if (-1 == rv) {
+ error("mptrace(XPT_SIGNAL): %s", safe_strerror(errno));
+ }
+ attach_flag = 1;
+ return pid;
+}
+
+void
+detach (signo)
+ int signo;
+{
+ int rv;
+
+ rv = mptrace(XPT_UNDEBUG, inferior_pid, 1, signo);
+ if (-1 == rv) {
+ error("mptrace(XPT_UNDEBUG): %s", safe_strerror(errno));
+ }
+ 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
+
+
+/* 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_RTEXT, inferior_pid, (PTRACE_ARG3_TYPE) addr,
+ 0);
+ }
+
+ if (count > 1) /* FIXME, avoid if even boundary */
+ {
+ buffer[count - 1]
+ = ptrace (PT_RTEXT, 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_WDATA, 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_WTEXT, 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_RTEXT, 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;
+}
+
+
+void
+_initialize_symm_nat ()
+{
+#ifdef ATTACH_DETACH
+/*
+ * the MPDEBUGGER is necessary for process tree debugging and attach
+ * to work, but it alters the behavior of debugged processes, so other
+ * things (at least child_wait()) will have to change to accomodate
+ * that.
+ *
+ * Note that attach is not implemented in dynix 3, and not in ptx
+ * until version 2.1 of the OS.
+ */
+ int rv;
+ sigset_t set;
+ struct sigaction sact;
+
+ rv = mptrace(XPT_MPDEBUGGER, 0, 0, 0);
+ if (-1 == rv) {
+ fatal("_initialize_symm_nat(): mptrace(XPT_MPDEBUGGER): %s",
+ safe_strerror(errno));
+ }
+
+ /*
+ * Under MPDEBUGGER, we get SIGCLHD when a traced process does
+ * anything of interest.
+ */
+
+ /*
+ * Block SIGCHLD. We leave it blocked all the time, and then
+ * call sigsuspend() in child_wait() to wait for the child
+ * to do something. None of these ought to fail, but check anyway.
+ */
+ sigemptyset(&set);
+ rv = sigaddset(&set, SIGCHLD);
+ if (-1 == rv) {
+ fatal("_initialize_symm_nat(): sigaddset(SIGCHLD): %s",
+ safe_strerror(errno));
+ }
+ rv = sigprocmask(SIG_BLOCK, &set, (sigset_t *)NULL);
+ if (-1 == rv) {
+ fatal("_initialize_symm_nat(): sigprocmask(SIG_BLOCK): %s",
+ safe_strerror(errno));
+ }
+
+ sact.sa_handler = sigchld_handler;
+ sigemptyset(&sact.sa_mask);
+ sact.sa_flags = SA_NOCLDWAIT; /* keep the zombies away */
+ rv = sigaction(SIGCHLD, &sact, (struct sigaction *)NULL);
+ if (-1 == rv) {
+ fatal("_initialize_symm_nat(): sigaction(SIGCHLD): %s",
+ safe_strerror(errno));
+ }
+#endif
+}
diff --git a/gdb/symm-tdep.c b/gdb/symm-tdep.c
new file mode 100644
index 00000000000..aaf73e94a74
--- /dev/null
+++ b/gdb/symm-tdep.c
@@ -0,0 +1,93 @@
+/* Sequent Symmetry target interface, for GDB.
+ Copyright (C) 1986, 1987, 1989, 1991, 1994 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* many 387-specific items of use taken from i386-dep.c */
+
+#include "defs.h"
+#include "frame.h"
+#include "inferior.h"
+#include "symtab.h"
+
+#include <signal.h>
+#include <sys/param.h>
+#include <sys/user.h>
+#include <sys/dir.h>
+#include <sys/ioctl.h>
+#include "gdb_stat.h"
+#include "gdbcore.h"
+#include <fcntl.h>
+
+void
+symmetry_extract_return_value(type, regbuf, valbuf)
+ struct type *type;
+ char *regbuf;
+ char *valbuf;
+{
+ union {
+ double d;
+ int l[2];
+ } xd;
+ struct minimal_symbol *msymbol;
+ float f;
+
+ if (TYPE_CODE_FLT == TYPE_CODE(type)) {
+ msymbol = lookup_minimal_symbol ("1167_flt", NULL, NULL);
+ if (msymbol != NULL) {
+ /* found "1167_flt" means 1167, %fp2-%fp3 */
+ /* float & double; 19= %fp2, 20= %fp3 */
+ /* no single precision on 1167 */
+ xd.l[1] = *((int *)&regbuf[REGISTER_BYTE(19)]);
+ xd.l[0] = *((int *)&regbuf[REGISTER_BYTE(20)]);
+ switch (TYPE_LENGTH(type)) {
+ case 4:
+ /* FIXME: broken for cross-debugging. */
+ f = (float) xd.d;
+ memcpy (valbuf, &f, TYPE_LENGTH(type));
+ break;
+ case 8:
+ /* FIXME: broken for cross-debugging. */
+ memcpy (valbuf, &xd.d, TYPE_LENGTH(type));
+ break;
+ default:
+ error("Unknown floating point size");
+ break;
+ }
+ } else {
+ /* 387 %st(0), gcc uses this */
+ i387_to_double(((int *)&regbuf[REGISTER_BYTE(3)]),
+ &xd.d);
+ switch (TYPE_LENGTH(type)) {
+ case 4: /* float */
+ f = (float) xd.d;
+ /* FIXME: broken for cross-debugging. */
+ memcpy (valbuf, &f, 4);
+ break;
+ case 8: /* double */
+ /* FIXME: broken for cross-debugging. */
+ memcpy (valbuf, &xd.d, 8);
+ break;
+ default:
+ error("Unknown floating point size");
+ break;
+ }
+ }
+ } else {
+ memcpy (valbuf, regbuf, TYPE_LENGTH (type));
+ }
+}
diff --git a/gdb/symmisc.c b/gdb/symmisc.c
new file mode 100644
index 00000000000..97d2f6e83cd
--- /dev/null
+++ b/gdb/symmisc.c
@@ -0,0 +1,1098 @@
+/* Do various things to symbol tables (other than lookup), for GDB.
+ Copyright 1986, 87, 89, 91, 92, 93, 94, 95, 96, 1998
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 "bcache.h"
+
+#include "gdb_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 *,
+ GDB_FILE *));
+
+static void dump_psymtab PARAMS ((struct objfile *, struct partial_symtab *,
+ GDB_FILE *));
+
+static void dump_msymbols PARAMS ((struct objfile *, GDB_FILE *));
+
+static void dump_objfile PARAMS ((struct objfile *));
+
+static int block_depth PARAMS ((struct block *));
+
+static void print_partial_symbols PARAMS ((struct partial_symbol **, int,
+ char *, GDB_FILE *));
+
+static void free_symtab_block PARAMS ((struct objfile *, struct block *));
+
+void _initialize_symmisc PARAMS ((void));
+
+struct print_symbol_args {
+ struct symbol *symbol;
+ int depth;
+ GDB_FILE *outfile;
+};
+
+static int print_symbol PARAMS ((PTR));
+
+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);
+ if (s -> debugformat != NULL)
+ mfree (s -> objfile -> md, s -> debugformat);
+ mfree (s -> objfile -> md, (PTR) s);
+}
+
+#if MAINTENANCE_CMDS
+
+void
+print_symbol_bcache_statistics ()
+{
+ struct objfile *objfile;
+
+ immediate_quit++;
+ ALL_OBJFILES (objfile)
+ {
+ printf_filtered ("Byte cache statistics for '%s':\n", objfile -> name);
+ print_bcache_statistics (&objfile -> psymbol_cache, "partial symbol cache");
+ }
+ immediate_quit--;
+}
+
+void
+print_objfile_statistics ()
+{
+ struct objfile *objfile;
+
+ immediate_quit++;
+ ALL_OBJFILES (objfile)
+ {
+ printf_filtered ("Statistics for '%s':\n", objfile -> name);
+ if (OBJSTAT (objfile, n_stabs) > 0)
+ printf_filtered (" Number of \"stab\" symbols read: %d\n",
+ OBJSTAT (objfile, n_stabs));
+ if (OBJSTAT (objfile, n_minsyms) > 0)
+ printf_filtered (" Number of \"minimal\" symbols read: %d\n",
+ OBJSTAT (objfile, n_minsyms));
+ if (OBJSTAT (objfile, n_psyms) > 0)
+ printf_filtered (" Number of \"partial\" symbols read: %d\n",
+ OBJSTAT (objfile, n_psyms));
+ if (OBJSTAT (objfile, n_syms) > 0)
+ printf_filtered (" Number of \"full\" symbols read: %d\n",
+ OBJSTAT (objfile, n_syms));
+ if (OBJSTAT (objfile, n_types) > 0)
+ printf_filtered (" Number of \"types\" defined: %d\n",
+ OBJSTAT (objfile, n_types));
+ if (OBJSTAT (objfile, sz_strtab) > 0)
+ printf_filtered (" Space used by a.out string tables: %d\n",
+ OBJSTAT (objfile, sz_strtab));
+ printf_filtered (" Total memory used for psymbol obstack: %d\n",
+ obstack_memory_used (&objfile -> psymbol_obstack));
+ printf_filtered (" Total memory used for psymbol cache: %d\n",
+ obstack_memory_used (&objfile -> psymbol_cache.cache));
+ printf_filtered (" Total memory used for symbol obstack: %d\n",
+ obstack_memory_used (&objfile -> symbol_obstack));
+ printf_filtered (" Total memory used for type obstack: %d\n",
+ obstack_memory_used (&objfile -> type_obstack));
+ }
+ immediate_quit--;
+}
+
+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 ");
+ gdb_print_address (objfile, gdb_stdout);
+ printf_filtered (", bfd at ");
+ gdb_print_address (objfile->obfd, gdb_stdout);
+ printf_filtered (", %d minsyms\n\n",
+ objfile->minimal_symbol_count);
+
+ if (objfile -> psymtabs)
+ {
+ printf_filtered ("Psymtabs:\n");
+ for (psymtab = objfile -> psymtabs;
+ psymtab != NULL;
+ psymtab = psymtab -> next)
+ {
+ printf_filtered ("%s at ",
+ psymtab -> filename);
+ gdb_print_address (psymtab, gdb_stdout);
+ printf_filtered (", ");
+ 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 ", symtab -> filename);
+ gdb_print_address (symtab, gdb_stdout);
+ printf_filtered (", ");
+ 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;
+ GDB_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_solib_trampoline:
+ ms_type = 'S';
+ 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 ", index, ms_type);
+ print_address_numeric (SYMBOL_VALUE_ADDRESS (msymbol), 1, outfile);
+ fprintf_filtered (outfile, " %s", SYMBOL_NAME (msymbol));
+ if (SYMBOL_BFD_SECTION (msymbol))
+ fprintf_filtered (outfile, " section %s",
+ bfd_section_name (objfile->obfd,
+ SYMBOL_BFD_SECTION (msymbol)));
+ if (SYMBOL_DEMANGLED_NAME (msymbol) != NULL)
+ {
+ fprintf_filtered (outfile, " %s", SYMBOL_DEMANGLED_NAME (msymbol));
+ }
+#ifdef SOFUN_ADDRESS_MAYBE_MISSING
+ if (msymbol->filename)
+ fprintf_filtered (outfile, " %s", msymbol->filename);
+#endif
+ 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;
+ GDB_FILE *outfile;
+{
+ int i;
+
+ fprintf_filtered (outfile, "\nPartial symtab for source file %s ",
+ psymtab -> filename);
+ fprintf_filtered (outfile, "(object ");
+ gdb_print_address (psymtab, outfile);
+ fprintf_filtered (outfile, ")\n\n");
+ fprintf_unfiltered (outfile, " Read from object file %s (",
+ objfile -> name);
+ gdb_print_address (objfile, outfile);
+ fprintf_unfiltered (outfile, ")\n");
+
+ if (psymtab -> readin)
+ {
+ fprintf_filtered (outfile,
+ " Full symtab was read (at ");
+ gdb_print_address (psymtab->symtab, outfile);
+ fprintf_filtered (outfile, " by function at ");
+ gdb_print_address ((PTR)psymtab->read_symtab, outfile);
+ fprintf_filtered (outfile, ")\n");
+ }
+
+ fprintf_filtered (outfile, " Relocate symbols by ");
+ for (i = 0; i < psymtab->objfile->num_sections; ++i)
+ {
+ if (i != 0)
+ fprintf_filtered (outfile, ", ");
+ wrap_here (" ");
+ print_address_numeric (ANOFFSET (psymtab->section_offsets, i),
+ 1,
+ outfile);
+ }
+ fprintf_filtered (outfile, "\n");
+
+ fprintf_filtered (outfile, " Symbols cover text addresses ");
+ print_address_numeric (psymtab->textlow, 1, outfile);
+ fprintf_filtered (outfile, "-");
+ print_address_numeric (psymtab->texthigh, 1, outfile);
+ fprintf_filtered (outfile, "\n");
+ 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 ", i);
+ gdb_print_address (psymtab -> dependencies[i], outfile);
+ fprintf_filtered (outfile, " %s\n",
+ psymtab -> dependencies[i] -> filename);
+ }
+ if (psymtab -> n_global_syms > 0)
+ {
+ print_partial_symbols (objfile -> global_psymbols.list
+ + psymtab -> globals_offset,
+ psymtab -> n_global_syms, "Global", outfile);
+ }
+ if (psymtab -> n_static_syms > 0)
+ {
+ print_partial_symbols (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;
+ GDB_FILE *outfile;
+{
+ register int i, j;
+ int len, blen;
+ register struct linetable *l;
+ struct blockvector *bv;
+ register struct block *b;
+ int depth;
+
+ fprintf_filtered (outfile, "\nSymtab for file %s\n", symtab->filename);
+ if (symtab->dirname)
+ fprintf_filtered (outfile, "Compilation directory is %s\n",
+ symtab->dirname);
+ fprintf_filtered (outfile, "Read from object file %s (", objfile->name);
+ gdb_print_address (objfile, outfile);
+ fprintf_filtered (outfile, ")\n");
+ fprintf_filtered (outfile, "Language: %s\n", language_str (symtab->language));
+
+ /* First print the line table. */
+ l = LINETABLE (symtab);
+ if (l)
+ {
+ fprintf_filtered (outfile, "\nLine table:\n\n");
+ len = l->nitems;
+ for (i = 0; i < len; i++)
+ {
+ fprintf_filtered (outfile, " line %d at ", l->item[i].line);
+ print_address_numeric (l->item[i].pc, 1, outfile);
+ fprintf_filtered (outfile, "\n");
+ }
+ }
+ /* Now print the block info, but only for primary symtabs since we will
+ print lots of duplicate info otherwise. */
+ if (symtab -> primary)
+ {
+ fprintf_filtered (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_filtered (outfile, "block #%03d, object at ", i);
+ gdb_print_address (b, outfile);
+ if (BLOCK_SUPERBLOCK (b))
+ {
+ fprintf_filtered (outfile, " under ");
+ gdb_print_address (BLOCK_SUPERBLOCK (b), outfile);
+ }
+ blen = BLOCK_NSYMS (b);
+ fprintf_filtered (outfile, ", %d syms in ", blen);
+ print_address_numeric (BLOCK_START (b), 1, outfile);
+ fprintf_filtered (outfile, "..");
+ print_address_numeric (BLOCK_END (b), 1, outfile);
+ if (BLOCK_FUNCTION (b))
+ {
+ fprintf_filtered (outfile, ", function %s", SYMBOL_NAME (BLOCK_FUNCTION (b)));
+ if (SYMBOL_DEMANGLED_NAME (BLOCK_FUNCTION (b)) != NULL)
+ {
+ fprintf_filtered (outfile, ", %s",
+ SYMBOL_DEMANGLED_NAME (BLOCK_FUNCTION (b)));
+ }
+ }
+ if (BLOCK_GCC_COMPILED(b))
+ fprintf_filtered (outfile, ", compiled with gcc%d", BLOCK_GCC_COMPILED(b));
+ fprintf_filtered (outfile, "\n");
+ /* Now print each symbol in this block */
+ 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_ALL);
+ }
+ }
+ fprintf_filtered (outfile, "\n");
+ }
+ else
+ {
+ fprintf_filtered (outfile, "\nBlockvector same as previous symtab\n\n");
+ }
+}
+
+void
+maintenance_print_symbols (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ char **argv;
+ GDB_FILE *outfile;
+ struct cleanup *cleanups;
+ char *symname = NULL;
+ char *filename = DEV_TTY;
+ struct objfile *objfile;
+ struct symtab *s;
+
+ dont_repeat ();
+
+ if (args == NULL)
+ {
+ error ("\
+Arguments missing: an output file name and an optional symbol file name");
+ }
+ else if ((argv = buildargv (args)) == NULL)
+ {
+ nomem (0);
+ }
+ cleanups = make_cleanup ((make_cleanup_func) 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 = gdb_fopen (filename, FOPEN_WT);
+ if (outfile == 0)
+ perror_with_name (filename);
+ make_cleanup ((make_cleanup_func) gdb_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)
+ PTR args;
+{
+ struct symbol *symbol = ((struct print_symbol_args *)args)->symbol;
+ int depth = ((struct print_symbol_args *)args)->depth;
+ GDB_FILE *outfile = ((struct print_symbol_args *)args)->outfile;
+
+ print_spaces (depth, outfile);
+ if (SYMBOL_NAMESPACE (symbol) == LABEL_NAMESPACE)
+ {
+ fprintf_filtered (outfile, "label %s at ", SYMBOL_SOURCE_NAME (symbol));
+ print_address_numeric (SYMBOL_VALUE_ADDRESS (symbol), 1, outfile);
+ if (SYMBOL_BFD_SECTION (symbol))
+ fprintf_filtered (outfile, " section %s\n",
+ bfd_section_name (SYMBOL_BFD_SECTION (symbol)->owner,
+ SYMBOL_BFD_SECTION (symbol)));
+ else
+ fprintf_filtered (outfile, "\n");
+ 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_filtered (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_filtered (outfile, ";\n");
+ }
+ else
+ {
+ if (SYMBOL_CLASS (symbol) == LOC_TYPEDEF)
+ fprintf_filtered (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_filtered (outfile, "; ");
+ }
+ else
+ fprintf_filtered (outfile, "%s ", SYMBOL_SOURCE_NAME (symbol));
+
+ switch (SYMBOL_CLASS (symbol))
+ {
+ case LOC_CONST:
+ fprintf_filtered (outfile, "const %ld (0x%lx)",
+ SYMBOL_VALUE (symbol),
+ SYMBOL_VALUE (symbol));
+ break;
+
+ case LOC_CONST_BYTES:
+ {
+ unsigned i;
+ struct type *type = check_typedef (SYMBOL_TYPE (symbol));
+ fprintf_filtered (outfile, "const %u hex bytes:",
+ TYPE_LENGTH (type));
+ for (i = 0; i < TYPE_LENGTH (type); i++)
+ fprintf_filtered (outfile, " %02x",
+ (unsigned)SYMBOL_VALUE_BYTES (symbol) [i]);
+ }
+ break;
+
+ case LOC_STATIC:
+ fprintf_filtered (outfile, "static at ");
+ print_address_numeric (SYMBOL_VALUE_ADDRESS (symbol), 1,outfile);
+ if (SYMBOL_BFD_SECTION (symbol))
+ fprintf_filtered (outfile, " section %s",
+ bfd_section_name
+ (SYMBOL_BFD_SECTION (symbol)->owner,
+ SYMBOL_BFD_SECTION (symbol)));
+ break;
+
+ case LOC_INDIRECT:
+ fprintf_filtered (outfile, "extern global at *(");
+ print_address_numeric (SYMBOL_VALUE_ADDRESS (symbol), 1,outfile);
+ fprintf_filtered (outfile, "),");
+ break;
+
+ case LOC_REGISTER:
+ fprintf_filtered (outfile, "register %ld", SYMBOL_VALUE (symbol));
+ break;
+
+ case LOC_ARG:
+ fprintf_filtered (outfile, "arg at offset 0x%lx",
+ SYMBOL_VALUE (symbol));
+ break;
+
+ case LOC_LOCAL_ARG:
+ fprintf_filtered (outfile, "arg at offset 0x%lx from fp",
+ SYMBOL_VALUE (symbol));
+ break;
+
+ case LOC_REF_ARG:
+ fprintf_filtered (outfile, "reference arg at 0x%lx", SYMBOL_VALUE (symbol));
+ break;
+
+ case LOC_REGPARM:
+ fprintf_filtered (outfile, "parameter register %ld", SYMBOL_VALUE (symbol));
+ break;
+
+ case LOC_REGPARM_ADDR:
+ fprintf_filtered (outfile, "address parameter register %ld", SYMBOL_VALUE (symbol));
+ break;
+
+ case LOC_LOCAL:
+ fprintf_filtered (outfile, "local at offset 0x%lx",
+ SYMBOL_VALUE (symbol));
+ break;
+
+ case LOC_BASEREG:
+ fprintf_filtered (outfile, "local at 0x%lx from register %d",
+ SYMBOL_VALUE (symbol), SYMBOL_BASEREG (symbol));
+ break;
+
+ case LOC_BASEREG_ARG:
+ fprintf_filtered (outfile, "arg at 0x%lx from register %d",
+ SYMBOL_VALUE (symbol), SYMBOL_BASEREG (symbol));
+ break;
+
+ case LOC_TYPEDEF:
+ break;
+
+ case LOC_LABEL:
+ fprintf_filtered (outfile, "label at ");
+ print_address_numeric (SYMBOL_VALUE_ADDRESS (symbol), 1, outfile);
+ if (SYMBOL_BFD_SECTION (symbol))
+ fprintf_filtered (outfile, " section %s",
+ bfd_section_name
+ (SYMBOL_BFD_SECTION (symbol)->owner,
+ SYMBOL_BFD_SECTION (symbol)));
+ break;
+
+ case LOC_BLOCK:
+ fprintf_filtered (outfile, "block object ");
+ gdb_print_address (SYMBOL_BLOCK_VALUE (symbol), outfile);
+ fprintf_filtered (outfile, ", ");
+ print_address_numeric (BLOCK_START (SYMBOL_BLOCK_VALUE (symbol)),
+ 1,
+ outfile);
+ fprintf_filtered (outfile, "..");
+ print_address_numeric (BLOCK_END (SYMBOL_BLOCK_VALUE (symbol)),
+ 1,
+ outfile);
+ if (SYMBOL_BFD_SECTION (symbol))
+ fprintf_filtered (outfile, " section %s",
+ bfd_section_name
+ (SYMBOL_BFD_SECTION (symbol)->owner,
+ SYMBOL_BFD_SECTION (symbol)));
+ break;
+
+ case LOC_UNRESOLVED:
+ fprintf_filtered (outfile, "unresolved");
+ break;
+
+ case LOC_OPTIMIZED_OUT:
+ fprintf_filtered (outfile, "optimized out");
+ break;
+
+ default:
+ fprintf_filtered (outfile, "botched symbol class %x",
+ SYMBOL_CLASS (symbol));
+ break;
+ }
+ }
+ fprintf_filtered (outfile, "\n");
+ return 1;
+}
+
+void
+maintenance_print_psymbols (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ char **argv;
+ GDB_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 ((make_cleanup_func) 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 = gdb_fopen (filename, FOPEN_WT);
+ if (outfile == 0)
+ perror_with_name (filename);
+ make_cleanup ((make_cleanup_func) gdb_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_symbols (p, count, what, outfile)
+ struct partial_symbol **p;
+ int count;
+ char *what;
+ GDB_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_INDIRECT:
+ fputs_filtered ("extern global", 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_UNRESOLVED:
+ fputs_filtered ("unresolved", outfile);
+ break;
+ case LOC_OPTIMIZED_OUT:
+ fputs_filtered ("optimized out", outfile);
+ break;
+ default:
+ fputs_filtered ("<invalid location>", outfile);
+ break;
+ }
+ fputs_filtered (", ", outfile);
+ print_address_numeric (SYMBOL_VALUE_ADDRESS (*p), 1, outfile);
+ fprintf_filtered (outfile, "\n");
+ p++;
+ }
+}
+
+void
+maintenance_print_msymbols (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ char **argv;
+ GDB_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 ((make_cleanup_func) 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 = gdb_fopen (filename, FOPEN_WT);
+ if (outfile == 0)
+ perror_with_name (filename);
+ make_cleanup ((make_cleanup_func) gdb_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--;
+}
+
+/* Check consistency of psymtabs and symtabs. */
+
+void
+maintenance_check_symtabs (ignore, from_tty)
+ char *ignore;
+ int from_tty;
+{
+ register struct symbol *sym;
+ register struct partial_symbol **psym;
+ register struct symtab *s = NULL;
+ register struct partial_symtab *ps;
+ struct blockvector *bv;
+ register struct objfile *objfile;
+ register struct block *b;
+ int length;
+
+ ALL_PSYMTABS (objfile, ps)
+ {
+ s = PSYMTAB_TO_SYMTAB(ps);
+ if (s == NULL)
+ continue;
+ bv = BLOCKVECTOR (s);
+ b = BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK);
+ psym = ps->objfile->static_psymbols.list + ps->statics_offset;
+ length = ps->n_static_syms;
+ while (length--)
+ {
+ sym = lookup_block_symbol (b, SYMBOL_NAME (*psym),
+ SYMBOL_NAMESPACE (*psym));
+ if (!sym)
+ {
+ printf_filtered ("Static symbol `");
+ puts_filtered (SYMBOL_NAME (*psym));
+ printf_filtered ("' only found in ");
+ puts_filtered (ps->filename);
+ printf_filtered (" psymtab\n");
+ }
+ psym++;
+ }
+ b = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
+ psym = ps->objfile->global_psymbols.list + ps->globals_offset;
+ length = ps->n_global_syms;
+ while (length--)
+ {
+ sym = lookup_block_symbol (b, SYMBOL_NAME (*psym),
+ SYMBOL_NAMESPACE (*psym));
+ if (!sym)
+ {
+ printf_filtered ("Global symbol `");
+ puts_filtered (SYMBOL_NAME (*psym));
+ printf_filtered ("' only found in ");
+ puts_filtered (ps->filename);
+ printf_filtered (" psymtab\n");
+ }
+ psym++;
+ }
+ if (ps->texthigh < ps->textlow)
+ {
+ printf_filtered ("Psymtab ");
+ puts_filtered (ps->filename);
+ printf_filtered (" covers bad range ");
+ print_address_numeric (ps->textlow, 1, gdb_stdout);
+ printf_filtered (" - ");
+ print_address_numeric (ps->texthigh, 1, gdb_stdout);
+ printf_filtered ("\n");
+ continue;
+ }
+ if (ps->texthigh == 0)
+ continue;
+ if (ps->textlow < BLOCK_START (b) || ps->texthigh > BLOCK_END (b))
+ {
+ printf_filtered ("Psymtab ");
+ puts_filtered (ps->filename);
+ printf_filtered (" covers ");
+ print_address_numeric (ps->textlow, 1, gdb_stdout);
+ printf_filtered (" - ");
+ print_address_numeric (ps->texthigh, 1, gdb_stdout);
+ printf_filtered (" but symtab covers only ");
+ print_address_numeric (BLOCK_START (b), 1, gdb_stdout);
+ printf_filtered (" - ");
+ print_address_numeric (BLOCK_END (b), 1, gdb_stdout);
+ printf_filtered ("\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)) != NULL)
+ {
+ i++;
+ }
+ return i;
+}
+
+#endif /* MAINTENANCE_CMDS */
+
+
+/* Increase the space allocated for LISTP, which is probably
+ global_psymbols or static_psymbols. 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/gdb/symtab.c b/gdb/symtab.c
new file mode 100644
index 00000000000..fb3c8f77ba2
--- /dev/null
+++ b/gdb/symtab.c
@@ -0,0 +1,4518 @@
+/* Symbol table lookup for the GNU debugger, GDB.
+ Copyright 1986, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 1998
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 "gnu-regex.h"
+#include "expression.h"
+#include "language.h"
+#include "demangle.h"
+#include "inferior.h"
+
+#include "obstack.h"
+
+#include <sys/types.h>
+#include <fcntl.h>
+#include "gdb_string.h"
+#include "gdb_stat.h"
+#include <ctype.h>
+
+/* Prototype for one function in parser-defs.h,
+ instead of including that entire file. */
+
+extern char * find_template_name_end PARAMS ((char *));
+
+/* Prototypes for local functions */
+
+static 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 output_source_filename PARAMS ((char *, int *));
+
+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, namespace_enum));
+
+static struct partial_symbol *fixup_psymbol_section PARAMS ((struct
+ partial_symbol *, struct objfile *));
+
+static struct symtab *lookup_symtab_1 PARAMS ((char *));
+
+static void cplusplus_hint PARAMS ((char *));
+
+static struct symbol *find_active_alias PARAMS ((struct symbol *sym,
+ CORE_ADDR addr));
+
+/* This flag is used in hppa-tdep.c, and set in hp-symtab-read.c */
+/* Signals the presence of objects compiled by HP compilers */
+int hp_som_som_object_present = 0;
+
+static void fixup_section PARAMS ((struct general_symbol_info *,
+ struct objfile *));
+
+static int file_matches PARAMS ((char *, char **, int));
+
+static void print_symbol_info PARAMS ((namespace_enum,
+ struct symtab *, struct symbol *,
+ int, char *));
+
+static void print_msymbol_info PARAMS ((struct minimal_symbol *));
+
+static void symtab_symbol_info PARAMS ((char *, namespace_enum, int));
+
+void _initialize_symtab PARAMS ((void));
+
+/* */
+
+/* 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 */
+
+static void
+cplusplus_hint (name)
+ char *name;
+{
+ while (*name == '\'')
+ name++;
+ printf_filtered ("Hint: try '%s<TAB> or '%s<ESC-?>\n", name, name);
+ printf_filtered ("(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;
+#if 0
+ register char *copy;
+#endif
+
+ s = lookup_symtab_1 (name);
+ if (s) return s;
+
+#if 0
+ /* This screws c-exp.y:yylex if there is both a type "tree" and a symtab
+ "tree.c". */
+
+ /* 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;
+#endif /* 0 */
+
+ /* 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);
+}
+
+/* Mangle a GDB method stub type. This actually reassembles the pieces of the
+ full method name, which consist of the class name (from T), the unadorned
+ method name from METHOD_ID, and the signature for the specific overload,
+ specified by SIGNATURE_ID. Note that this function is g++ specific. */
+
+char *
+gdb_mangle_name (type, method_id, signature_id)
+ struct type *type;
+ int method_id, signature_id;
+{
+ int mangled_name_len;
+ char *mangled_name;
+ struct fn_field *f = TYPE_FN_FIELDLIST1 (type, method_id);
+ struct fn_field *method = &f[signature_id];
+ char *field_name = TYPE_FN_FIELDLIST_NAME (type, method_id);
+ char *physname = TYPE_FN_FIELD_PHYSNAME (f, signature_id);
+ char *newname = type_name_no_tag (type);
+
+ /* Does the form of physname indicate that it is the full mangled name
+ of a constructor (not just the args)? */
+ int is_full_physname_constructor;
+
+ 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));
+
+ is_full_physname_constructor =
+ ((physname[0]=='_' && physname[1]=='_' &&
+ (isdigit(physname[2]) || physname[2]=='Q' || physname[2]=='t'))
+ || (strncmp(physname, "__ct", 4) == 0));
+
+ is_constructor =
+ is_full_physname_constructor || (newname && STREQ(field_name, newname));
+
+ if (!is_destructor)
+ is_destructor = (strncmp(physname, "__dt", 4) == 0);
+
+ if (is_destructor || is_full_physname_constructor)
+ {
+ 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);
+ }
+ else if (physname[0] == 't' || physname[0] == 'Q')
+ {
+ /* The physname for template and qualified methods already includes
+ the class name. */
+ sprintf (buf, "__%s%s", const_prefix, volatile_prefix);
+ newname = NULL;
+ len = 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))
+ {
+ const 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);
+
+ strcat (mangled_name, physname);
+ return (mangled_name);
+}
+
+
+
+/* Find which partial symtab on contains PC and SECTION. Return 0 if none. */
+
+struct partial_symtab *
+find_pc_sect_psymtab (pc, section)
+ CORE_ADDR pc;
+ asection *section;
+{
+ register struct partial_symtab *pst;
+ register struct objfile *objfile;
+
+ ALL_PSYMTABS (objfile, pst)
+ {
+#if defined(HPUXHPPA)
+ if (pc >= pst->textlow && pc <= pst->texthigh)
+#else
+ if (pc >= pst->textlow && pc < pst->texthigh)
+#endif
+ {
+ struct minimal_symbol *msymbol;
+ struct partial_symtab *tpst;
+
+ /* An objfile that has its functions reordered might have
+ many partial symbol tables containing the PC, but
+ we want the partial symbol table that contains the
+ function containing the PC. */
+ if (!(objfile->flags & OBJF_REORDERED) &&
+ section == 0) /* can't validate section this way */
+ return (pst);
+
+ msymbol = lookup_minimal_symbol_by_pc_section (pc, section);
+ if (msymbol == NULL)
+ return (pst);
+
+ for (tpst = pst; tpst != NULL; tpst = tpst->next)
+ {
+#if defined(HPUXHPPA)
+ if (pc >= tpst->textlow && pc <= tpst->texthigh)
+#else
+ if (pc >= tpst->textlow && pc < tpst->texthigh)
+#endif
+ {
+ struct partial_symbol *p;
+
+ p = find_pc_sect_psymbol (tpst, pc, section);
+ if (p != NULL
+ && SYMBOL_VALUE_ADDRESS(p)
+ == SYMBOL_VALUE_ADDRESS (msymbol))
+ return (tpst);
+ }
+ }
+ return (pst);
+ }
+ }
+ return (NULL);
+}
+
+/* Find which partial symtab contains PC. Return 0 if none.
+ Backward compatibility, no section */
+
+struct partial_symtab *
+find_pc_psymtab (pc)
+ CORE_ADDR pc;
+{
+ return find_pc_sect_psymtab (pc, find_pc_mapped_section (pc));
+}
+
+/* Find which partial symbol within a psymtab matches PC and SECTION.
+ Return 0 if none. Check all psymtabs if PSYMTAB is 0. */
+
+struct partial_symbol *
+find_pc_sect_psymbol (psymtab, pc, section)
+ struct partial_symtab *psymtab;
+ CORE_ADDR pc;
+ asection *section;
+{
+ struct partial_symbol *best = NULL, *p, **pp;
+ CORE_ADDR best_pc;
+
+ if (!psymtab)
+ psymtab = find_pc_sect_psymtab (pc, section);
+ if (!psymtab)
+ return 0;
+
+ /* Cope with programs that start at address 0 */
+ best_pc = (psymtab->textlow != 0) ? psymtab->textlow - 1 : 0;
+
+ /* Search the global symbols as well as the static symbols, so that
+ find_pc_partial_function doesn't use a minimal symbol and thus
+ cache a bad endaddr. */
+ for (pp = psymtab->objfile->global_psymbols.list + psymtab->globals_offset;
+ (pp - (psymtab->objfile->global_psymbols.list + psymtab->globals_offset)
+ < psymtab->n_global_syms);
+ pp++)
+ {
+ p = *pp;
+ if (SYMBOL_NAMESPACE (p) == VAR_NAMESPACE
+ && SYMBOL_CLASS (p) == LOC_BLOCK
+ && pc >= SYMBOL_VALUE_ADDRESS (p)
+ && (SYMBOL_VALUE_ADDRESS (p) > best_pc
+ || (psymtab->textlow == 0
+ && best_pc == 0 && SYMBOL_VALUE_ADDRESS (p) == 0)))
+ {
+ if (section) /* match on a specific section */
+ {
+ fixup_psymbol_section (p, psymtab->objfile);
+ if (SYMBOL_BFD_SECTION (p) != section)
+ continue;
+ }
+ best_pc = SYMBOL_VALUE_ADDRESS (p);
+ best = p;
+ }
+ }
+
+ for (pp = psymtab->objfile->static_psymbols.list + psymtab->statics_offset;
+ (pp - (psymtab->objfile->static_psymbols.list + psymtab->statics_offset)
+ < psymtab->n_static_syms);
+ pp++)
+ {
+ p = *pp;
+ if (SYMBOL_NAMESPACE (p) == VAR_NAMESPACE
+ && SYMBOL_CLASS (p) == LOC_BLOCK
+ && pc >= SYMBOL_VALUE_ADDRESS (p)
+ && (SYMBOL_VALUE_ADDRESS (p) > best_pc
+ || (psymtab->textlow == 0
+ && best_pc == 0 && SYMBOL_VALUE_ADDRESS (p) == 0)))
+ {
+ if (section) /* match on a specific section */
+ {
+ fixup_psymbol_section (p, psymtab->objfile);
+ if (SYMBOL_BFD_SECTION (p) != section)
+ continue;
+ }
+ best_pc = SYMBOL_VALUE_ADDRESS (p);
+ best = p;
+ }
+ }
+
+ return best;
+}
+
+/* Find which partial symbol within a psymtab matches PC. Return 0 if none.
+ Check all psymtabs if PSYMTAB is 0. Backwards compatibility, no section. */
+
+struct partial_symbol *
+find_pc_psymbol (psymtab, pc)
+ struct partial_symtab *psymtab;
+ CORE_ADDR pc;
+{
+ return find_pc_sect_psymbol (psymtab, pc, find_pc_mapped_section (pc));
+}
+
+/* Debug symbols usually don't have section information. We need to dig that
+ out of the minimal symbols and stash that in the debug symbol. */
+
+static void
+fixup_section (ginfo, objfile)
+ struct general_symbol_info *ginfo;
+ struct objfile *objfile;
+{
+ struct minimal_symbol *msym;
+ msym = lookup_minimal_symbol (ginfo->name, NULL, objfile);
+
+ if (msym)
+ ginfo->bfd_section = SYMBOL_BFD_SECTION (msym);
+}
+
+struct symbol *
+fixup_symbol_section (sym, objfile)
+ struct symbol *sym;
+ struct objfile *objfile;
+{
+ if (!sym)
+ return NULL;
+
+ if (SYMBOL_BFD_SECTION (sym))
+ return sym;
+
+ fixup_section (&sym->ginfo, objfile);
+
+ return sym;
+}
+
+static struct partial_symbol *
+fixup_psymbol_section (psym, objfile)
+ struct partial_symbol *psym;
+ struct objfile *objfile;
+{
+ if (!psym)
+ return NULL;
+
+ if (SYMBOL_BFD_SECTION (psym))
+ return psym;
+
+ fixup_section (&psym->ginfo, objfile);
+
+ return psym;
+}
+
+/* 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.) */
+
+/* This function has a bunch of loops in it and it would seem to be
+ attractive to put in some QUIT's (though I'm not really sure
+ whether it can run long enough to be really important). But there
+ are a few calls for which it would appear to be bad news to quit
+ out of here: find_proc_desc in alpha-tdep.c and mips-tdep.c, and
+ nindy_frame_chain_valid in nindy-tdep.c. (Note that there is C++
+ code below which can error(), but that probably doesn't affect
+ these calls since they are looking for a known variable and thus
+ can probably assume it will never hit the C++ code). */
+
+struct symbol *
+lookup_symbol (name, block, namespace, is_a_field_of_this, symtab)
+ const char *name;
+ register const struct block *block;
+ const namespace_enum 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 = NULL;
+ 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 fixup_symbol_section (sym, objfile);
+ }
+ 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. */
+ /* Note (RT): The following never-executed code looks unnecessary to me also.
+ * If we change the code to use the original (passed-in)
+ * value of 'block', we could cause it to execute, but then what
+ * would it do? The STATIC_BLOCK of the symtab containing the passed-in
+ * 'block' was already searched by the above code. And the STATIC_BLOCK's
+ * of *other* symtabs (those files not containing 'block' lexically)
+ * should not contain 'block' address-wise. So we wouldn't expect this
+ * code to find any 'sym''s that were not found above. I vote for
+ * deleting the following paragraph of code.
+ */
+ 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 fixup_symbol_section (sym, objfile);
+ }
+ }
+ }
+ }
+
+
+ /* 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 NULL;
+ }
+ }
+
+ /* Now search all global blocks. Do the symtab's first, then
+ check the psymtab's. If a psymtab indicates the existence
+ of the desired name as a global, then do psymtab-to-symtab
+ conversion on the fly and return the found symbol. */
+
+ 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 fixup_symbol_section (sym, objfile);
+ }
+ }
+
+#ifndef HPUXHPPA
+
+ /* Check for the possibility of the symbol being a function or
+ a mangled variable 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, NULL, NULL);
+ if (msymbol != NULL)
+ {
+ s = find_pc_sect_symtab (SYMBOL_VALUE_ADDRESS (msymbol),
+ SYMBOL_BFD_SECTION (msymbol));
+ if (s != NULL)
+ {
+ /* This is a function which has a symtab for its address. */
+ 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 fixup_symbol_section (sym, objfile);
+ }
+ else if (MSYMBOL_TYPE (msymbol) != mst_text
+ && MSYMBOL_TYPE (msymbol) != mst_file_text
+ && !STREQ (name, SYMBOL_NAME (msymbol)))
+ {
+ /* This is a mangled variable, look it up by its
+ mangled name. */
+ return lookup_symbol (SYMBOL_NAME (msymbol), block,
+ namespace, is_a_field_of_this, symtab);
+ }
+ /* There are no debug symbols for this file, or we are looking
+ for an unmangled variable.
+ Try to find a matching static symbol below. */
+ }
+ }
+
+#endif
+
+ 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)
+ {
+ /* This shouldn't be necessary, but as a last resort
+ * try looking in the statics even though the psymtab
+ * claimed the symbol was global. It's possible that
+ * the psymtab gets it wrong in some cases.
+ */
+ block = BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK);
+ sym = lookup_block_symbol (block, name, namespace);
+ if (!sym)
+ error ("Internal: global symbol `%s' found in %s psymtab but not in symtab.\n\
+%s may be an inlined function, or may be a template function\n\
+(if a template, try specifying an instantiation: %s<type>).",
+ name, ps->filename, name, name);
+ }
+ if (symtab != NULL)
+ *symtab = s;
+ return fixup_symbol_section (sym, objfile);
+ }
+ }
+
+ /* Now search all static file-level symbols.
+ Not strictly correct, but more useful than an error.
+ Do the symtabs first, then check the psymtabs.
+ If a psymtab indicates the existence
+ of the desired name as a file-level static, then do psymtab-to-symtab
+ conversion on the fly and return the found symbol. */
+
+ 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 fixup_symbol_section (sym, objfile);
+ }
+ }
+
+ 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)
+ {
+ /* This shouldn't be necessary, but as a last resort
+ * try looking in the globals even though the psymtab
+ * claimed the symbol was static. It's possible that
+ * the psymtab gets it wrong in some cases.
+ */
+ block = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
+ sym = lookup_block_symbol (block, name, namespace);
+ if (!sym)
+ error ("Internal: static symbol `%s' found in %s psymtab but not in symtab.\n\
+%s may be an inlined function, or may be a template function\n\
+(if a template, try specifying an instantiation: %s<type>).",
+ name, ps->filename, name, name);
+ }
+ if (symtab != NULL)
+ *symtab = s;
+ return fixup_symbol_section (sym, objfile);
+ }
+ }
+
+#ifdef HPUXHPPA
+
+ /* Check for the possibility of the symbol being a function or
+ a global variable that is stored in one of the minimal symbol tables.
+ The "minimal symbol table" is built from linker-supplied info.
+
+ RT: I moved this check to last, after the complete search of
+ the global (p)symtab's and static (p)symtab's. For HP-generated
+ symbol tables, this check was causing a premature exit from
+ lookup_symbol with NULL return, and thus messing up symbol lookups
+ of things like "c::f". It seems to me a check of the minimal
+ symbol table ought to be a last resort in any case. I'm vaguely
+ worried about the comment below which talks about FORTRAN routines "foo_"
+ though... is it saying we need to do the "minsym" check before
+ the static check in this case?
+ */
+
+ if (namespace == VAR_NAMESPACE)
+ {
+ msymbol = lookup_minimal_symbol (name, NULL, NULL);
+ if (msymbol != NULL)
+ {
+ /* OK, we found a minimal symbol in spite of not
+ * finding any symbol. There are various possible
+ * explanations for this. One possibility is the symbol
+ * exists in code not compiled -g. Another possibility
+ * is that the 'psymtab' isn't doing its job.
+ * A third possibility, related to #2, is that we were confused
+ * by name-mangling. For instance, maybe the psymtab isn't
+ * doing its job because it only know about demangled
+ * names, but we were given a mangled name...
+ */
+
+ /* We first use the address in the msymbol to try to
+ * locate the appropriate symtab. Note that find_pc_symtab()
+ * has a side-effect of doing psymtab-to-symtab expansion,
+ * for the found symtab.
+ */
+ s = find_pc_symtab (SYMBOL_VALUE_ADDRESS (msymbol));
+ 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);
+ }
+ /* If we found one, return it */
+ if (sym) {
+ if (symtab != NULL)
+ *symtab = s;
+ return sym;
+ }
+
+ /* If we get here with sym == 0, the symbol was
+ found in the minimal symbol table
+ but not in the symtab.
+ Fall through and return 0 to use the msymbol
+ definition of "foo_".
+ (Note that outer code generally follows up a call
+ to this routine with a call to lookup_minimal_symbol(),
+ so a 0 return means we'll just flow into that other routine).
+
+ 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 the lookup-by-address fails, try repeating the
+ * entire lookup process with the symbol name from
+ * the msymbol (if different from the original symbol name).
+ */
+ else if (MSYMBOL_TYPE (msymbol) != mst_text
+ && MSYMBOL_TYPE (msymbol) != mst_file_text
+ && !STREQ (name, SYMBOL_NAME (msymbol)))
+ {
+ return lookup_symbol (SYMBOL_NAME (msymbol), block,
+ namespace, is_a_field_of_this, symtab);
+ }
+ }
+ }
+
+#endif
+
+ 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;
+ namespace_enum 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;
+ if (!(center < top))
+ abort ();
+ if (!do_linear_search
+ && (SYMBOL_LANGUAGE (*center) == language_cplus
+ || SYMBOL_LANGUAGE (*center) == language_java
+ ))
+ {
+ do_linear_search = 1;
+ }
+ if (STRCMP (SYMBOL_NAME (*center), name) >= 0)
+ {
+ top = center;
+ }
+ else
+ {
+ bottom = center + 1;
+ }
+ }
+ if (!(top == bottom))
+ abort ();
+ 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);
+}
+
+/* Look up a type named NAME in the struct_namespace. The type returned
+ must not be opaque -- i.e., must have at least one field defined
+
+ This code was modelled on lookup_symbol -- the parts not relevant to looking
+ up types were just left out. In particular it's assumed here that types
+ are available in struct_namespace and only at file-static or global blocks. */
+
+
+struct type *
+lookup_transparent_type (name)
+ const char *name;
+{
+ register struct symbol *sym;
+ register struct symtab *s = NULL;
+ register struct partial_symtab *ps;
+ struct blockvector *bv;
+ register struct objfile *objfile;
+ register struct block *block;
+ register struct minimal_symbol *msymbol;
+
+ /* Now search all the global symbols. Do the symtab's first, then
+ check the psymtab's. If a psymtab indicates the existence
+ of the desired name as a global, then do psymtab-to-symtab
+ conversion on the fly and return the found symbol. */
+
+ ALL_SYMTABS (objfile, s)
+ {
+ bv = BLOCKVECTOR (s);
+ block = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
+ sym = lookup_block_symbol (block, name, STRUCT_NAMESPACE);
+ if (sym && !TYPE_IS_OPAQUE (SYMBOL_TYPE (sym)))
+ {
+ return SYMBOL_TYPE (sym);
+ }
+ }
+
+ ALL_PSYMTABS (objfile, ps)
+ {
+ if (!ps->readin && lookup_partial_symbol (ps, name, 1, STRUCT_NAMESPACE))
+ {
+ s = PSYMTAB_TO_SYMTAB(ps);
+ bv = BLOCKVECTOR (s);
+ block = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
+ sym = lookup_block_symbol (block, name, STRUCT_NAMESPACE);
+ if (!sym)
+ {
+ /* This shouldn't be necessary, but as a last resort
+ * try looking in the statics even though the psymtab
+ * claimed the symbol was global. It's possible that
+ * the psymtab gets it wrong in some cases.
+ */
+ block = BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK);
+ sym = lookup_block_symbol (block, name, STRUCT_NAMESPACE);
+ if (!sym)
+ error ("Internal: global symbol `%s' found in %s psymtab but not in symtab.\n\
+%s may be an inlined function, or may be a template function\n\
+(if a template, try specifying an instantiation: %s<type>).",
+ name, ps->filename, name, name);
+ }
+ if (!TYPE_IS_OPAQUE (SYMBOL_TYPE (sym)))
+ return SYMBOL_TYPE (sym);
+ }
+ }
+
+ /* Now search the static file-level symbols.
+ Not strictly correct, but more useful than an error.
+ Do the symtab's first, then
+ check the psymtab's. If a psymtab indicates the existence
+ of the desired name as a file-level static, then do psymtab-to-symtab
+ conversion on the fly and return the found symbol.
+ */
+
+ ALL_SYMTABS (objfile, s)
+ {
+ bv = BLOCKVECTOR (s);
+ block = BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK);
+ sym = lookup_block_symbol (block, name, STRUCT_NAMESPACE);
+ if (sym && !TYPE_IS_OPAQUE (SYMBOL_TYPE (sym)))
+ {
+ return SYMBOL_TYPE (sym);
+ }
+ }
+
+ ALL_PSYMTABS (objfile, ps)
+ {
+ if (!ps->readin && lookup_partial_symbol (ps, name, 0, STRUCT_NAMESPACE))
+ {
+ s = PSYMTAB_TO_SYMTAB(ps);
+ bv = BLOCKVECTOR (s);
+ block = BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK);
+ sym = lookup_block_symbol (block, name, STRUCT_NAMESPACE);
+ if (!sym)
+ {
+ /* This shouldn't be necessary, but as a last resort
+ * try looking in the globals even though the psymtab
+ * claimed the symbol was static. It's possible that
+ * the psymtab gets it wrong in some cases.
+ */
+ block = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
+ sym = lookup_block_symbol (block, name, STRUCT_NAMESPACE);
+ if (!sym)
+ error ("Internal: static symbol `%s' found in %s psymtab but not in symtab.\n\
+%s may be an inlined function, or may be a template function\n\
+(if a template, try specifying an instantiation: %s<type>).",
+ name, ps->filename, name, name);
+ }
+ if (!TYPE_IS_OPAQUE (SYMBOL_TYPE (sym)))
+ return SYMBOL_TYPE (sym);
+ }
+ }
+ return (struct type *) 0;
+}
+
+
+/* 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 namespace_enum 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
+ || SYMBOL_LANGUAGE (sym) == language_java
+ ))
+ {
+ 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))
+ {
+ /* If SYM has aliases, then use any alias that is active
+ at the current PC. If no alias is active at the current
+ PC, then use the main symbol.
+
+ ?!? Is checking the current pc correct? Is this routine
+ ever called to look up a symbol from another context? */
+ if (SYMBOL_ALIASES (sym))
+ sym = find_active_alias (sym, read_pc ());
+
+ 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. */
+}
+
+/* Given a main symbol SYM and ADDR, search through the alias
+ list to determine if an alias is active at ADDR and return
+ the active alias.
+
+ If no alias is active, then return SYM. */
+
+static struct symbol *
+find_active_alias (sym, addr)
+ struct symbol *sym;
+ CORE_ADDR addr;
+{
+ struct range_list *r;
+ struct alias_list *aliases;
+
+ /* If we have aliases, check them first. */
+ aliases = SYMBOL_ALIASES (sym);
+
+ while (aliases)
+ {
+ if (!SYMBOL_RANGES (aliases->sym))
+ return aliases->sym;
+ for (r = SYMBOL_RANGES (aliases->sym); r; r = r->next)
+ {
+ if (r->start <= addr && r->end > addr)
+ return aliases->sym;
+ }
+ aliases = aliases->next;
+ }
+
+ /* Nothing found, return the main symbol. */
+ return sym;
+}
+
+
+/* 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 and SECTION. Look through the
+ psymtabs and read in another symtab if necessary. */
+
+struct symtab *
+find_pc_sect_symtab (pc, section)
+ CORE_ADDR pc;
+ asection *section;
+{
+ 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;
+ CORE_ADDR 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 happens for native ecoff format, where code from included files
+ gets its own symtab. The symtab for the included file should have
+ been read in already via the dependency mechanism.
+ It might be swifter to create several symtabs with the same name
+ like xcoff does (I'm not sure).
+
+ It also happens for objfiles that have their functions reordered.
+ For these, the symtab we are looking for is not necessarily read in. */
+
+ ALL_SYMTABS (objfile, s)
+ {
+ bv = BLOCKVECTOR (s);
+ b = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
+
+ if (BLOCK_START (b) <= pc
+#if defined(HPUXHPPA)
+ && BLOCK_END (b) >= pc
+#else
+ && BLOCK_END (b) > pc
+#endif
+ && (distance == 0
+ || BLOCK_END (b) - BLOCK_START (b) < distance))
+ {
+ /* For an objfile that has its functions reordered,
+ find_pc_psymtab will find the proper partial symbol table
+ and we simply return its corresponding symtab. */
+ /* In order to better support objfiles that contain both
+ stabs and coff debugging info, we continue on if a psymtab
+ can't be found. */
+ if ((objfile->flags & OBJF_REORDERED) && objfile->psymtabs)
+ {
+ ps = find_pc_sect_psymtab (pc, section);
+ if (ps)
+ return PSYMTAB_TO_SYMTAB (ps);
+ }
+ if (section != 0)
+ {
+ int i;
+
+ for (i = 0; i < b->nsyms; i++)
+ {
+ fixup_symbol_section (b->sym[i], objfile);
+ if (section == SYMBOL_BFD_SECTION (b->sym[i]))
+ break;
+ }
+ if (i >= b->nsyms)
+ continue; /* no symbol in this symtab matches section */
+ }
+ distance = BLOCK_END (b) - BLOCK_START (b);
+ best_s = s;
+ }
+ }
+
+ if (best_s != NULL)
+ return(best_s);
+
+ s = NULL;
+ ps = find_pc_sect_psymtab (pc, section);
+ 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. */
+ /* FIXME-32x64: assumes pc fits in a long */
+ 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 symtab associated with PC. Look through the psymtabs and
+ read in another symtab if necessary. Backward compatibility, no section */
+
+struct symtab *
+find_pc_symtab (pc)
+ CORE_ADDR pc;
+{
+ return find_pc_sect_symtab (pc, find_pc_mapped_section (pc));
+}
+
+
+#if 0
+
+/* Find the closest symbol value (of any sort -- function or variable)
+ for a given address value. Slow but complete. (currently unused,
+ mainly because it is too slow. We could fix it if each symtab and
+ psymtab had contained in it the addresses ranges of each of its
+ sections, which also would be required to make things like "info
+ line *0x2345" cause psymtabs to be converted to symtabs). */
+
+struct symbol *
+find_addr_symbol (addr, symtabp, symaddrp)
+ CORE_ADDR addr;
+ struct symtab **symtabp;
+ CORE_ADDR *symaddrp;
+{
+ struct symtab *symtab, *best_symtab;
+ struct objfile *objfile;
+ register int bot, top;
+ register struct symbol *sym;
+ register CORE_ADDR sym_addr;
+ struct block *block;
+ int blocknum;
+
+ /* Info on best symbol seen so far */
+
+ register CORE_ADDR best_sym_addr = 0;
+ struct symbol *best_sym = 0;
+
+ /* FIXME -- we should pull in all the psymtabs, too! */
+ ALL_SYMTABS (objfile, symtab)
+ {
+ /* Search the global and static blocks in this symtab for
+ the closest symbol-address to the desired address. */
+
+ for (blocknum = GLOBAL_BLOCK; blocknum <= STATIC_BLOCK; blocknum++)
+ {
+ QUIT;
+ block = BLOCKVECTOR_BLOCK (BLOCKVECTOR (symtab), blocknum);
+ top = BLOCK_NSYMS (block);
+ for (bot = 0; bot < top; bot++)
+ {
+ sym = BLOCK_SYM (block, bot);
+ switch (SYMBOL_CLASS (sym))
+ {
+ case LOC_STATIC:
+ case LOC_LABEL:
+ sym_addr = SYMBOL_VALUE_ADDRESS (sym);
+ break;
+
+ case LOC_INDIRECT:
+ sym_addr = SYMBOL_VALUE_ADDRESS (sym);
+ /* An indirect symbol really lives at *sym_addr,
+ * so an indirection needs to be done.
+ * However, I am leaving this commented out because it's
+ * expensive, and it's possible that symbolization
+ * could be done without an active process (in
+ * case this read_memory will fail). RT
+ sym_addr = read_memory_unsigned_integer
+ (sym_addr, TARGET_PTR_BIT / TARGET_CHAR_BIT);
+ */
+ break;
+
+ case LOC_BLOCK:
+ sym_addr = BLOCK_START (SYMBOL_BLOCK_VALUE (sym));
+ break;
+
+ default:
+ continue;
+ }
+
+ if (sym_addr <= addr)
+ if (sym_addr > best_sym_addr)
+ {
+ /* Quit if we found an exact match. */
+ best_sym = sym;
+ best_sym_addr = sym_addr;
+ best_symtab = symtab;
+ if (sym_addr == addr)
+ goto done;
+ }
+ }
+ }
+ }
+
+ done:
+ if (symtabp)
+ *symtabp = best_symtab;
+ if (symaddrp)
+ *symaddrp = best_sym_addr;
+ return best_sym;
+}
+#endif /* 0 */
+
+/* Find the source file and line number for a given PC value and section.
+ 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_sect_line (pc, section, notcurrent)
+ CORE_ADDR pc;
+ struct sec *section;
+ 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;
+ struct minimal_symbol *msymbol;
+ struct minimal_symbol *mfunsym;
+
+ /* 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. */
+
+ INIT_SAL (&val); /* initialize to zeroes */
+
+ if (notcurrent)
+ pc -= 1;
+
+ /* elz: added this because this function returned the wrong
+ information if the pc belongs to a stub (import/export)
+ to call a shlib function. This stub would be anywhere between
+ two functions in the target, and the line info was erroneously
+ taken to be the one of the line before the pc.
+ */
+ /* RT: Further explanation:
+ *
+ * We have stubs (trampolines) inserted between procedures.
+ *
+ * Example: "shr1" exists in a shared library, and a "shr1" stub also
+ * exists in the main image.
+ *
+ * In the minimal symbol table, we have a bunch of symbols
+ * sorted by start address. The stubs are marked as "trampoline",
+ * the others appear as text. E.g.:
+ *
+ * Minimal symbol table for main image
+ * main: code for main (text symbol)
+ * shr1: stub (trampoline symbol)
+ * foo: code for foo (text symbol)
+ * ...
+ * Minimal symbol table for "shr1" image:
+ * ...
+ * shr1: code for shr1 (text symbol)
+ * ...
+ *
+ * So the code below is trying to detect if we are in the stub
+ * ("shr1" stub), and if so, find the real code ("shr1" trampoline),
+ * and if found, do the symbolization from the real-code address
+ * rather than the stub address.
+ *
+ * Assumptions being made about the minimal symbol table:
+ * 1. lookup_minimal_symbol_by_pc() will return a trampoline only
+ * if we're really in the trampoline. If we're beyond it (say
+ * we're in "foo" in the above example), it'll have a closer
+ * symbol (the "foo" text symbol for example) and will not
+ * return the trampoline.
+ * 2. lookup_minimal_symbol_text() will find a real text symbol
+ * corresponding to the trampoline, and whose address will
+ * be different than the trampoline address. I put in a sanity
+ * check for the address being the same, to avoid an
+ * infinite recursion.
+ */
+ msymbol = lookup_minimal_symbol_by_pc(pc);
+ if (msymbol != NULL)
+ if (MSYMBOL_TYPE (msymbol) == mst_solib_trampoline)
+ {
+ mfunsym = lookup_minimal_symbol_text (SYMBOL_NAME (msymbol), NULL, NULL);
+ if (mfunsym == NULL)
+ /* I eliminated this warning since it is coming out
+ * in the following situation:
+ * gdb shmain // test program with shared libraries
+ * (gdb) break shr1 // function in shared lib
+ * Warning: In stub for ...
+ * In the above situation, the shared lib is not loaded yet,
+ * so of course we can't find the real func/line info,
+ * but the "break" still works, and the warning is annoying.
+ * So I commented out the warning. RT */
+ /* warning ("In stub for %s; unable to find real function/line info", SYMBOL_NAME(msymbol)) */;
+ /* fall through */
+ else if (SYMBOL_VALUE(mfunsym) == SYMBOL_VALUE(msymbol))
+ /* Avoid infinite recursion */
+ /* See above comment about why warning is commented out */
+ /* warning ("In stub for %s; unable to find real function/line info", SYMBOL_NAME(msymbol)) */;
+ /* fall through */
+ else
+ return find_pc_line( SYMBOL_VALUE (mfunsym), 0);
+ }
+
+
+ s = find_pc_sect_symtab (pc, section);
+ if (!s)
+ {
+ /* if no symbol information, return previous pc */
+ if (notcurrent)
+ pc++;
+ val.pc = pc;
+ 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++)
+ {
+ /* Leave prev pointing to the linetable entry for the last line
+ that started at or before 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.pc = pc;
+ }
+ else
+ {
+ val.symtab = alt_symtab;
+ val.line = alt->line - 1;
+
+ /* Don't return line 0, that means that we didn't find the line. */
+ if (val.line == 0) ++val.line;
+
+ 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));
+ }
+ val.section = section;
+ return val;
+}
+
+/* Backward compatibility (no section) */
+
+struct symtab_and_line
+find_pc_line (pc, notcurrent)
+ CORE_ADDR pc;
+ int notcurrent;
+{
+ asection *section;
+
+ section = find_pc_overlay (pc);
+ if (pc_in_unmapped_range (pc, section))
+ pc = overlay_mapped_address (pc, section);
+ return find_pc_sect_line (pc, section, notcurrent);
+}
+
+
+static struct symtab* find_line_symtab PARAMS ((struct symtab *, int,
+ int *, int *));
+
+/* Find line number LINE in any symtab whose name is the same as
+ SYMTAB.
+
+ If found, return the symtab that contains 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 NULL. */
+
+static struct symtab*
+find_line_symtab (symtab, line, index, exact_match)
+ struct symtab *symtab;
+ int line;
+ 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;
+ struct symtab *best_symtab;
+
+ /* First try looking it up in the given symtab. */
+ best_linetable = LINETABLE (symtab);
+ best_symtab = 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;
+ best_symtab = s;
+ goto done;
+ }
+ if (best == 0 || l->item[ind].line < best)
+ {
+ best = l->item[ind].line;
+ best_index = ind;
+ best_linetable = l;
+ best_symtab = s;
+ }
+ }
+ }
+ }
+ done:
+ if (best_index < 0)
+ return NULL;
+
+ if (index)
+ *index = best_index;
+ if (exact_match)
+ *exact_match = exact;
+
+ return best_symtab;
+}
+
+/* Set the PC value for a given source file and line number and return true.
+ Returns zero for invalid line number (and sets the PC to 0).
+ The source file is specified with a struct symtab. */
+
+int
+find_line_pc (symtab, line, pc)
+ struct symtab *symtab;
+ int line;
+ CORE_ADDR *pc;
+{
+ struct linetable *l;
+ int ind;
+
+ *pc = 0;
+ if (symtab == 0)
+ return 0;
+
+ symtab = find_line_symtab (symtab, line, &ind, NULL);
+ if (symtab != NULL)
+ {
+ l = LINETABLE (symtab);
+ *pc = l->item[ind].pc;
+ return 1;
+ }
+ 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 (sal, startptr, endptr)
+ struct symtab_and_line sal;
+ CORE_ADDR *startptr, *endptr;
+{
+ CORE_ADDR startaddr;
+ struct symtab_and_line found_sal;
+
+ startaddr = sal.pc;
+ if (startaddr==0 && !find_line_pc (sal.symtab, sal.line, &startaddr))
+ return 0;
+
+ /* This whole function is based on address. For example, if line 10 has
+ two parts, one from 0x100 to 0x200 and one from 0x300 to 0x400, then
+ "info line *0x123" should say the line goes from 0x100 to 0x200
+ and "info line *0x355" should say the line goes from 0x300 to 0x400.
+ This also insures that we never give a range like "starts at 0x134
+ and ends at 0x12c". */
+
+ found_sal = find_pc_sect_line (startaddr, sal.section, 0);
+ if (found_sal.line != sal.line)
+ {
+ /* The specified line (sal) has zero bytes. */
+ *startptr = found_sal.pc;
+ *endptr = found_sal.pc;
+ }
+ else
+ {
+ *startptr = found_sal.pc;
+ *endptr = found_sal.end;
+ }
+ return 1;
+}
+
+/* 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;
+}
+
+/* Given a function symbol SYM, find the symtab and line for the start
+ of the function.
+ If the argument FUNFIRSTLINE is nonzero, we want the first line
+ of real code inside the function. */
+
+static struct symtab_and_line
+find_function_start_sal PARAMS ((struct symbol *sym, int));
+
+static struct symtab_and_line
+find_function_start_sal (sym, funfirstline)
+ struct symbol *sym;
+ int funfirstline;
+{
+ CORE_ADDR pc;
+ struct symtab_and_line sal;
+
+ pc = BLOCK_START (SYMBOL_BLOCK_VALUE (sym));
+ fixup_symbol_section (sym, NULL);
+ if (funfirstline)
+ { /* skip "first line" of function (which is actually its prologue) */
+ asection *section = SYMBOL_BFD_SECTION (sym);
+ /* If function is in an unmapped overlay, use its unmapped LMA
+ address, so that SKIP_PROLOGUE has something unique to work on */
+ if (section_is_overlay (section) &&
+ !section_is_mapped (section))
+ pc = overlay_unmapped_address (pc, section);
+
+ pc += FUNCTION_START_OFFSET;
+ SKIP_PROLOGUE (pc);
+
+ /* For overlays, map pc back into its mapped VMA range */
+ pc = overlay_mapped_address (pc, section);
+ }
+ sal = find_pc_sect_line (pc, SYMBOL_BFD_SECTION (sym), 0);
+
+#ifdef PROLOGUE_FIRSTLINE_OVERLAP
+ /* Convex: no need to suppress code on first line, if any */
+ sal.pc = pc;
+#else
+ /* Check if SKIP_PROLOGUE left us in mid-line, and the next
+ line is still part of the same function. */
+ if (sal.pc != pc
+ && BLOCK_START (SYMBOL_BLOCK_VALUE (sym)) <= sal.end
+ && sal.end < BLOCK_END (SYMBOL_BLOCK_VALUE (sym)))
+ {
+ /* First pc of next line */
+ pc = sal.end;
+ /* Recalculate the line number (might not be N+1). */
+ sal = find_pc_sect_line (pc, SYMBOL_BFD_SECTION (sym), 0);
+ }
+ sal.pc = pc;
+#endif
+
+ return sal;
+}
+
+/* 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 "". */
+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;
+}
+
+/* Return the number of methods described for TYPE, including the
+ methods from types it derives from. This can't be done in the symbol
+ reader because the type of the baseclass might still be stubbed
+ when the definition of the derived class is parsed. */
+
+static int total_number_of_methods PARAMS ((struct type *type));
+
+static int
+total_number_of_methods (type)
+ struct type *type;
+{
+ int n;
+ int count;
+
+ CHECK_TYPEDEF (type);
+ if (TYPE_CPLUS_SPECIFIC (type) == NULL)
+ return 0;
+ count = TYPE_NFN_FIELDS_TOTAL (type);
+
+ for (n = 0; n < TYPE_N_BASECLASSES (type); n++)
+ count += total_number_of_methods (TYPE_BASECLASS (type, n));
+
+ return count;
+}
+
+/* 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 should have been allocated with
+ a size of total_number_of_methods (T) * sizeof (struct symbol *).
+ Note that this function is g++ specific. */
+
+static 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_TYPEDEF (t)? */
+ t = SYMBOL_TYPE (sym_class);
+
+ /* Loop over each method name. At this level, all overloads of a name
+ are counted as a single name. There is an inner loop which loops over
+ each overload. */
+
+ for (method_counter = TYPE_NFN_FIELDS (t) - 1;
+ method_counter >= 0;
+ --method_counter)
+ {
+ int field_counter;
+ char *method_name = TYPE_FN_FIELDLIST_NAME (t, method_counter);
+ char dem_opname[64];
+
+ if (strncmp (method_name, "__", 2) == 0 ||
+ strncmp (method_name, "op", 2) == 0 ||
+ strncmp (method_name, "type", 4) == 0)
+ {
+ if (cplus_demangle_opname (method_name, dem_opname, DMGL_ANSI))
+ method_name = dem_opname;
+ else if (cplus_demangle_opname (method_name, dem_opname, 0))
+ method_name = dem_opname;
+ }
+
+ if (STREQ (name, method_name))
+ /* Find all the overloaded methods with that name. */
+ for (field_counter = TYPE_FN_FIELDLIST_LENGTH (t, method_counter) - 1;
+ field_counter >= 0;
+ --field_counter)
+ {
+ struct fn_field *f;
+ char *phys_name;
+
+ f = TYPE_FN_FIELDLIST1 (t, method_counter);
+
+ if (TYPE_FN_FIELD_STUB (f, field_counter))
+ {
+ char *tmp_name;
+
+ tmp_name = gdb_mangle_name (t,
+ method_counter,
+ field_counter);
+ phys_name = alloca (strlen (tmp_name) + 1);
+ strcpy (phys_name, tmp_name);
+ free (tmp_name);
+ }
+ else
+ 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;
+
+ sym_arr[i1] = lookup_symbol (phys_name,
+ NULL, VAR_NAMESPACE,
+ (int *) NULL,
+ (struct symtab **) NULL);
+ if (sym_arr[i1])
+ i1++;
+ else
+ {
+ /* This error message gets printed, but the method
+ still seems to be found
+ fputs_filtered("(Cannot find method ", gdb_stdout);
+ fprintf_symbol_filtered (gdb_stdout, phys_name,
+ language_cplus,
+ DMGL_PARAMS | DMGL_ANSI);
+ fputs_filtered(" - possibly inlined.)\n", gdb_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 == 0)
+ 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, and it is
+ not OK to specify a variable or type to get its line number.
+
+ 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. */
+
+/* We allow single quotes in various places. This is a hideous
+ kludge, which exists because the completer can't yet deal with the
+ lack of single quotes. FIXME: write a linespec_completer which we
+ can use as appropriate instead of make_symbol_completion_list. */
+
+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, *pp, *ii, *p2;
+#if 0
+ char *q1;
+#endif
+ 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;
+ int has_parens;
+ int has_if = 0;
+ struct symbol **sym_arr;
+ struct type *t;
+ char *saved_arg = *argptr;
+ extern char *gdb_completer_quote_characters;
+
+ INIT_SAL (&val); /* initialize to zeroes */
+
+ /* Defaults have defaults. */
+
+ if (default_symtab == 0)
+ {
+ default_symtab = current_source_symtab;
+ default_line = current_source_line;
+ }
+
+ /* See if arg is *PC */
+
+ if (**argptr == '*')
+ {
+ (*argptr)++;
+ pc = parse_and_eval_address_1 (argptr);
+
+ values.sals = (struct symtab_and_line *)
+ xmalloc (sizeof (struct symtab_and_line));
+
+ values.nelts = 1;
+ values.sals[0] = find_pc_line (pc, 0);
+ values.sals[0].pc = pc;
+ values.sals[0].section = find_pc_overlay (pc);
+
+ return values;
+ }
+
+ /* 'has_if' is for the syntax:
+ * (gdb) break foo if (a==b)
+ */
+ if ((ii = strstr(*argptr, " if ")) != NULL ||
+ (ii = strstr(*argptr, "\tif ")) != NULL ||
+ (ii = strstr(*argptr, " if\t")) != NULL ||
+ (ii = strstr(*argptr, "\tif\t")) != NULL ||
+ (ii = strstr(*argptr, " if(")) != NULL ||
+ (ii = strstr(*argptr, "\tif( ")) != NULL)
+ has_if = 1;
+ /* Temporarily zap out "if (condition)" to not
+ * confuse the parenthesis-checking code below.
+ * This is undone below. Do not change ii!!
+ */
+ if (has_if) {
+ *ii = '\0';
+ }
+
+ /* Set various flags.
+ * 'has_parens' is important for overload checking, where
+ * we allow things like:
+ * (gdb) break c::f(int)
+ */
+
+ /* Maybe arg is FILE : LINENUM or FILE : FUNCTION */
+
+ is_quoted = (**argptr
+ && strchr (gdb_completer_quote_characters, **argptr) != NULL);
+
+ has_parens = ((pp = strchr (*argptr, '(')) != NULL
+ && (pp = strchr (pp, ')')) != NULL);
+
+ /* Now that we're safely past the has_parens check,
+ * put back " if (condition)" so outer layers can see it
+ */
+ if (has_if)
+ *ii = ' ';
+
+ /* Maybe arg is FILE : LINENUM or FILE : FUNCTION */
+ /* May also be CLASS::MEMBER, or NAMESPACE::NAME */
+ /* Look for ':', but ignore inside of <> */
+
+ s = NULL;
+ for (p = *argptr; *p; p++)
+ {
+ if (p[0] == '<')
+ {
+ char * temp_end = find_template_name_end (p);
+ if (!temp_end)
+ error ("malformed template specification in command");
+ p = temp_end;
+ }
+ if (p[0] == ':' || p[0] == ' ' || p[0] == '\t' || !*p)
+ break;
+ if (p[0] == '.' && strchr (p, ':') == NULL) /* Java qualified method. */
+ {
+ /* Find the *last* '.', since the others are package qualifiers. */
+ for (p1 = p; *p1; p1++)
+ {
+ if (*p1 == '.')
+ p = p1;
+ }
+ break;
+ }
+ }
+ while (p[0] == ' ' || p[0] == '\t') p++;
+
+ if ((p[0] == ':' || p[0] == '.') && !has_parens)
+ {
+ /* C++ */
+ /* ... or Java */
+ if (is_quoted) *argptr = *argptr+1;
+ if (p[0] == '.' || p[1] ==':')
+ {
+ int ix;
+ char * saved_arg2 = *argptr;
+ char * temp_end;
+ /* First check for "global" namespace specification,
+ of the form "::foo". If found, skip over the colons
+ and jump to normal symbol processing */
+ if ((*argptr == p) || (p[-1] == ' ') || (p[-1] == '\t'))
+ saved_arg2 += 2;
+
+ /* We have what looks like a class or namespace
+ scope specification (A::B), possibly with many
+ levels of namespaces or classes (A::B::C::D).
+
+ Some versions of the HP ANSI C++ compiler (as also possibly
+ other compilers) generate class/function/member names with
+ embedded double-colons if they are inside namespaces. To
+ handle this, we loop a few times, considering larger and
+ larger prefixes of the string as though they were single
+ symbols. So, if the initially supplied string is
+ A::B::C::D::foo, we have to look up "A", then "A::B",
+ then "A::B::C", then "A::B::C::D", and finally
+ "A::B::C::D::foo" as single, monolithic symbols, because
+ A, B, C or D may be namespaces.
+
+ Note that namespaces can nest only inside other
+ namespaces, and not inside classes. So we need only
+ consider *prefixes* of the string; there is no need to look up
+ "B::C" separately as a symbol in the previous example. */
+
+ p2 = p; /* save for restart */
+ while (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 + (p1[0] == ':' ? 2 : 1);
+ while (*p == ' ' || *p == '\t') p++;
+ *argptr = p;
+
+ sym_class = lookup_symbol (copy, 0, STRUCT_NAMESPACE, 0,
+ (struct symtab **)NULL);
+
+ if (sym_class &&
+ (t = check_typedef (SYMBOL_TYPE (sym_class)),
+ (TYPE_CODE (t) == TYPE_CODE_STRUCT
+ || TYPE_CODE (t) == TYPE_CODE_UNION)))
+ {
+ /* Arg token is not digits => try it as a function name
+ Find the next token(everything up to end or next blank). */
+ if (**argptr
+ && strchr (gdb_completer_quote_characters, **argptr) != NULL)
+ {
+ p = skip_quoted(*argptr);
+ *argptr = *argptr + 1;
+ }
+ else
+ {
+ 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)
+ {
+ error_begin ();
+ printf_filtered ("no mangling for \"%s\"\n", 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 );
+ memcpy (copy, *argptr, p - *argptr);
+ copy[p - *argptr] = '\0';
+ if (p != *argptr
+ && copy[p - *argptr - 1]
+ && strchr (gdb_completer_quote_characters,
+ copy[p - *argptr - 1]) != NULL)
+ copy[p - *argptr - 1] = '\0';
+ }
+
+ /* no line number may be specified */
+ while (*p == ' ' || *p == '\t') p++;
+ *argptr = p;
+
+ sym = 0;
+ i1 = 0; /* counter for the symbol array */
+ sym_arr = (struct symbol **) alloca(total_number_of_methods (t)
+ * sizeof(struct symbol *));
+
+ if (destructor_name_p (copy, t))
+ {
+ /* Destructors are a special case. */
+ int m_index, f_index;
+
+ if (get_destructor_fn_field (t, &m_index, &f_index))
+ {
+ struct fn_field *f = TYPE_FN_FIELDLIST1 (t, m_index);
+
+ sym_arr[i1] =
+ lookup_symbol (TYPE_FN_FIELD_PHYSNAME (f, f_index),
+ NULL, VAR_NAMESPACE, (int *) NULL,
+ (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)
+ {
+ values.sals = (struct symtab_and_line *)
+ xmalloc (sizeof (struct symtab_and_line));
+ values.nelts = 1;
+ values.sals[0] = find_function_start_sal (sym,
+ funfirstline);
+ }
+ 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;
+ error_begin ();
+ if (tmp[0] == '~')
+ printf_filtered
+ ("the class `%s' does not have destructor defined\n",
+ SYMBOL_SOURCE_NAME(sym_class));
+ else
+ printf_filtered
+ ("the class %s does not have any method named %s\n",
+ SYMBOL_SOURCE_NAME(sym_class), tmp);
+ cplusplus_hint (saved_arg);
+ return_to_top_level (RETURN_ERROR);
+ }
+ }
+
+ /* Move pointer up to next possible class/namespace token */
+ p = p2 + 1; /* restart with old value +1 */
+ /* Move pointer ahead to next double-colon */
+ while (*p && (p[0] != ' ') && (p[0] != '\t') && (p[0] != '\'')) {
+ if (p[0] == '<') {
+ temp_end = find_template_name_end (p);
+ if (!temp_end)
+ error ("malformed template specification in command");
+ p = temp_end;
+ }
+ else if ((p[0] == ':') && (p[1] == ':'))
+ break; /* found double-colon */
+ else
+ p++;
+ }
+
+ if (*p != ':')
+ break; /* out of the while (1) */
+
+ p2 = p; /* save restart for next time around */
+ *argptr = saved_arg2; /* restore argptr */
+ } /* while (1) */
+
+ /* Last chance attempt -- check entire name as a symbol */
+ /* Use "copy" in preparation for jumping out of this block,
+ to be consistent with usage following the jump target */
+ copy = (char *) alloca (p - saved_arg2 + 1);
+ memcpy (copy, saved_arg2, p - saved_arg2);
+ /* Note: if is_quoted should be true, we snuff out quote here anyway */
+ copy[p-saved_arg2] = '\000';
+ /* Set argptr to skip over the name */
+ *argptr = (*p == '\'') ? p + 1 : p;
+ /* Look up entire name */
+ sym = lookup_symbol (copy, 0, VAR_NAMESPACE, 0, &sym_symtab);
+ s = (struct symtab *) 0;
+ /* Prepare to jump: restore the " if (condition)" so outer layers see it */
+ if (has_if)
+ *ii = ' ';
+ /* Symbol was found --> jump to normal symbol processing.
+ Code following "symbol_found" expects "copy" to have the
+ symbol name, "sym" to have the symbol pointer, "s" to be
+ a specified file's symtab, and sym_symtab to be the symbol's
+ symtab. */
+ /* By jumping there we avoid falling through the FILE:LINE and
+ FILE:FUNC processing stuff below */
+ if (sym)
+ goto symbol_found;
+
+ /* Couldn't find any interpretation as classes/namespaces, so give up */
+ error_begin ();
+ /* The quotes are important if copy is empty. */
+ printf_filtered
+ ("Can't find member of namespace, class, struct, or union named \"%s\"\n", 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;
+ }
+ else {
+ /* Check if what we have till now is a symbol name */
+
+ /* We may be looking at a template instantiation such
+ as "foo<int>". Check here whether we know about it,
+ instead of falling through to the code below which
+ handles ordinary function names, because that code
+ doesn't like seeing '<' and '>' in a name -- the
+ skip_quoted call doesn't go past them. So see if we
+ can figure it out right now. */
+
+ copy = (char *) alloca (p - *argptr + 1);
+ memcpy (copy, *argptr, p - *argptr);
+ copy[p - *argptr] = '\000';
+ sym = lookup_symbol (copy, 0, VAR_NAMESPACE, 0, &sym_symtab);
+ if (sym) {
+ /* Yes, we have a symbol; jump to symbol processing */
+ /* Code after symbol_found expects S, SYM_SYMTAB, SYM,
+ and COPY to be set correctly */
+ if (has_if)
+ *ii = ' ';
+ *argptr = (*p == '\'') ? p + 1 : p;
+ s = (struct symtab *) 0;
+ goto symbol_found;
+ }
+ /* Otherwise fall out from here and go to file/line spec
+ processing, etc. */
+ }
+
+ /* 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) */
+
+ q = *argptr;
+ if (*q == '-' || *q == '+') q++;
+ while (*q >= '0' && *q <= '9')
+ q++;
+
+ if (q != *argptr && (*q == 0 || *q == ' ' || *q == '\t' || *q == ','))
+ {
+ /* 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 (q == *argptr)
+ val.line = 5;
+ if (s == 0)
+ val.line = default_line + val.line;
+ break;
+ case minus:
+ if (q == *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 (*q == ' ' || *q == '\t') q++;
+ *argptr = q;
+ if (s == 0)
+ s = default_symtab;
+
+ /* It is possible that this source file has more than one symtab,
+ and that the new line number specification has moved us from the
+ default (in s) to a new one. */
+ val.symtab = find_line_symtab (s, val.line, NULL, NULL);
+ if (val.symtab == 0)
+ 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). */
+
+ if (**argptr == '$') /* May be a convenience variable */
+ p = skip_quoted (*argptr + (((*argptr)[1] == '$') ? 2 : 1)); /* One or two $ chars possible */
+ else if (is_quoted)
+ {
+ p = skip_quoted (*argptr);
+ if (p[-1] != '\'')
+ error ("Unmatched single quote.");
+ }
+ else if (has_parens)
+ {
+ p = pp+1;
+ }
+ else
+ {
+ p = skip_quoted(*argptr);
+ }
+
+ copy = (char *) alloca (p - *argptr + 1);
+ memcpy (copy, *argptr, p - *argptr);
+ copy[p - *argptr] = '\0';
+ if (p != *argptr
+ && copy[0]
+ && 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;
+
+ /* If it starts with $: may be a legitimate variable or routine name
+ (e.g. HP-UX millicode routines such as $$dyncall), or it may
+ be history value, or it may be a convenience variable */
+
+ if (*copy == '$')
+ {
+ value_ptr valx;
+ int index = 0;
+ int need_canonical = 0;
+
+ p = (copy[1] == '$') ? copy + 2 : copy + 1;
+ while (*p >= '0' && *p <= '9')
+ p++;
+ if (!*p) /* reached end of token without hitting non-digit */
+ {
+ /* We have a value history reference */
+ sscanf ((copy[1] == '$') ? copy + 2 : copy + 1, "%d", &index);
+ valx = access_value_history ((copy[1] == '$') ? -index : index);
+ if (TYPE_CODE (VALUE_TYPE (valx)) != TYPE_CODE_INT)
+ error ("History values used in line specs must have integer values.");
+ }
+ else
+ {
+ /* Not all digits -- may be user variable/function or a
+ convenience variable */
+
+ /* Look up entire name as a symbol first */
+ sym = lookup_symbol (copy, 0, VAR_NAMESPACE, 0, &sym_symtab);
+ s = (struct symtab *) 0;
+ need_canonical = 1;
+ /* Symbol was found --> jump to normal symbol processing.
+ Code following "symbol_found" expects "copy" to have the
+ symbol name, "sym" to have the symbol pointer, "s" to be
+ a specified file's symtab, and sym_symtab to be the symbol's
+ symtab. */
+ if (sym)
+ goto symbol_found;
+
+ /* If symbol was not found, look in minimal symbol tables */
+ msymbol = lookup_minimal_symbol (copy, 0, 0);
+ /* Min symbol was found --> jump to minsym processing. */
+ if (msymbol)
+ goto minimal_symbol_found;
+
+ /* Not a user variable or function -- must be convenience variable */
+ need_canonical = (s == 0) ? 1 : 0;
+ valx = value_of_internalvar (lookup_internalvar (copy + 1));
+ if (TYPE_CODE (VALUE_TYPE (valx)) != TYPE_CODE_INT)
+ error ("Convenience variables used in line specs must have integer values.");
+ }
+
+ /* Either history value or convenience value from above, in valx */
+ val.symtab = s ? s : default_symtab;
+ val.line = value_as_long (valx);
+ val.pc = 0;
+
+ values.sals = (struct symtab_and_line *)xmalloc (sizeof val);
+ values.sals[0] = val;
+ values.nelts = 1;
+
+ if (need_canonical)
+ build_canonical_line_spec (values.sals, NULL, canonical);
+
+ return values;
+ }
+
+
+ /* 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);
+
+symbol_found: /* We also jump here from inside the C++ class/namespace
+ code on finding a symbol of the form "A::B::C" */
+
+ if (sym != NULL)
+ {
+ if (SYMBOL_CLASS (sym) == LOC_BLOCK)
+ {
+ /* Arg is the name of a function */
+ values.sals = (struct symtab_and_line *)
+ xmalloc (sizeof (struct symtab_and_line));
+ values.sals[0] = find_function_start_sal (sym, funfirstline);
+ values.nelts = 1;
+
+ /* Don't use the SYMBOL_LINE; if used at all it points to
+ the line containing the parameters or thereabouts, not
+ the first line of code. */
+
+ /* 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 (funfirstline)
+ error ("\"%s\" is not a function", copy);
+ 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, NULL, NULL);
+
+minimal_symbol_found: /* We also jump here from the case for variables
+ that begin with '$' */
+
+ if (msymbol != NULL)
+ {
+ values.sals = (struct symtab_and_line *)
+ xmalloc (sizeof (struct symtab_and_line));
+ values.sals[0] = find_pc_sect_line ( SYMBOL_VALUE_ADDRESS (msymbol),
+ (struct sec *)0,0 );
+ values.sals[0].section = SYMBOL_BFD_SECTION (msymbol);
+ if (funfirstline)
+ {
+ values.sals[0].pc += FUNCTION_START_OFFSET;
+ SKIP_PROLOGUE (values.sals[0].pc);
+ }
+ 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;
+ 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_unfiltered("[0] cancel\n[1] all\n");
+ while (i < nelts)
+ {
+ INIT_SAL (&return_values.sals[i]); /* initialize to zeroes */
+ INIT_SAL (&values.sals[i]);
+ if (sym_arr[i] && SYMBOL_CLASS (sym_arr[i]) == LOC_BLOCK)
+ {
+ values.sals[i] = find_function_start_sal (sym_arr[i], funfirstline);
+ printf_unfiltered ("[%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_unfiltered ("?HERE\n");
+ i++;
+ }
+
+ if ((prompt = getenv ("PS2")) == NULL)
+ {
+ prompt = "> ";
+ }
+ args = command_line_input (prompt, 0, "overload-choice");
+
+ 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_unfiltered ("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_unfiltered ("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, gdb_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");
+}
+
+static int
+file_matches (file, files, nfiles)
+ char *file;
+ char *files[];
+ int nfiles;
+{
+ int i;
+
+ if (file != NULL && nfiles != 0)
+ {
+ for (i = 0; i < nfiles; i++)
+ {
+ if (strcmp (files[i], basename (file)) == 0)
+ return 1;
+ }
+ }
+ else if (nfiles == 0)
+ return 1;
+ return 0;
+}
+
+/* Free any memory associated with a search. */
+void
+free_search_symbols (symbols)
+ struct symbol_search *symbols;
+{
+ struct symbol_search *p;
+ struct symbol_search *next;
+
+ for (p = symbols; p != NULL; p = next)
+ {
+ next = p->next;
+ free (p);
+ }
+}
+
+/* Search the symbol table for matches to the regular expression REGEXP,
+ returning the results in *MATCHES.
+
+ Only symbols of KIND are searched:
+ FUNCTIONS_NAMESPACE - search all functions
+ TYPES_NAMESPACE - search all type names
+ METHODS_NAMESPACE - search all methods NOT IMPLEMENTED
+ VARIABLES_NAMESPACE - search all symbols, excluding functions, type names,
+ and constants (enums)
+
+ free_search_symbols should be called when *MATCHES is no longer needed.
+*/
+void
+search_symbols (regexp, kind, nfiles, files, matches)
+ char *regexp;
+ namespace_enum kind;
+ int nfiles;
+ char *files[];
+ struct symbol_search **matches;
+
+{
+ 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 = 0;
+ register int j;
+ register struct symbol *sym;
+ struct partial_symbol **psym;
+ struct objfile *objfile;
+ struct minimal_symbol *msymbol;
+ char *val;
+ 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_file_text, mst_abs, mst_unknown};
+ static enum minimal_symbol_type types3[]
+ = {mst_file_data, mst_solib_trampoline, mst_abs, mst_unknown};
+ static enum minimal_symbol_type types4[]
+ = {mst_file_bss, mst_text, mst_abs, mst_unknown};
+ enum minimal_symbol_type ourtype;
+ enum minimal_symbol_type ourtype2;
+ enum minimal_symbol_type ourtype3;
+ enum minimal_symbol_type ourtype4;
+ struct symbol_search *sr;
+ struct symbol_search *psr;
+ struct symbol_search *tail;
+ struct cleanup *old_chain = NULL;
+
+ if (kind < LABEL_NAMESPACE)
+ error ("must search on specific namespace");
+
+ ourtype = types[(int) (kind - LABEL_NAMESPACE)];
+ ourtype2 = types2[(int) (kind - LABEL_NAMESPACE)];
+ ourtype3 = types3[(int) (kind - LABEL_NAMESPACE)];
+ ourtype4 = types4[(int) (kind - LABEL_NAMESPACE)];
+
+ sr = *matches = NULL;
+ tail = NULL;
+
+ 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 (file_matches (ps->filename, files, nfiles)
+ && ((regexp == NULL || SYMBOL_MATCHES_REGEXP (*psym))
+ && ((kind == VARIABLES_NAMESPACE && SYMBOL_CLASS (*psym) != LOC_TYPEDEF
+ && SYMBOL_CLASS (*psym) != LOC_BLOCK)
+ || (kind == FUNCTIONS_NAMESPACE && SYMBOL_CLASS (*psym) == LOC_BLOCK)
+ || (kind == TYPES_NAMESPACE && SYMBOL_CLASS (*psym) == LOC_TYPEDEF)
+ || (kind == METHODS_NAMESPACE && SYMBOL_CLASS (*psym) == LOC_BLOCK))))
+ {
+ PSYMTAB_TO_SYMTAB(ps);
+ keep_going = 0;
+ }
+ }
+ psym++;
+ }
+ }
+
+ /* Here, we search through the minimal symbol tables for functions
+ and variables that match, and force their symbols to be read.
+ This is in particular necessary for demangled variable names,
+ which are no longer put into the partial symbol tables.
+ The symbol will then be found during the scan of symtabs below.
+
+ For functions, find_pc_symtab should succeed if we have debug info
+ for the function, for variables we have to call lookup_symbol
+ to determine if the variable has debug info.
+ If the lookup fails, set found_misc so that we will rescan to print
+ any matching symbols without debug info.
+ */
+
+ if (nfiles == 0 && (kind == VARIABLES_NAMESPACE || kind == FUNCTIONS_NAMESPACE))
+ {
+ ALL_MSYMBOLS (objfile, msymbol)
+ {
+ if (MSYMBOL_TYPE (msymbol) == ourtype ||
+ MSYMBOL_TYPE (msymbol) == ourtype2 ||
+ MSYMBOL_TYPE (msymbol) == ourtype3 ||
+ MSYMBOL_TYPE (msymbol) == ourtype4)
+ {
+ if (regexp == NULL || SYMBOL_MATCHES_REGEXP (msymbol))
+ {
+ if (0 == find_pc_symtab (SYMBOL_VALUE_ADDRESS (msymbol)))
+ {
+ if (kind == FUNCTIONS_NAMESPACE
+ || lookup_symbol (SYMBOL_NAME (msymbol),
+ (struct block *) NULL,
+ VAR_NAMESPACE,
+ 0, (struct symtab **) NULL) == NULL)
+ found_misc = 1;
+ }
+ }
+ }
+ }
+ }
+
+ ALL_SYMTABS (objfile, s)
+ {
+ 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 (file_matches (s->filename, files, nfiles)
+ && ((regexp == NULL || SYMBOL_MATCHES_REGEXP (sym))
+ && ((kind == VARIABLES_NAMESPACE && SYMBOL_CLASS (sym) != LOC_TYPEDEF
+ && SYMBOL_CLASS (sym) != LOC_BLOCK
+ && SYMBOL_CLASS (sym) != LOC_CONST)
+ || (kind == FUNCTIONS_NAMESPACE && SYMBOL_CLASS (sym) == LOC_BLOCK)
+ || (kind == TYPES_NAMESPACE && SYMBOL_CLASS (sym) == LOC_TYPEDEF)
+ || (kind == METHODS_NAMESPACE && SYMBOL_CLASS (sym) == LOC_BLOCK))))
+ {
+ /* match */
+ psr = (struct symbol_search *) xmalloc (sizeof (struct symbol_search));
+ psr->block = i;
+ psr->symtab = s;
+ psr->symbol = sym;
+ psr->msymbol = NULL;
+ psr->next = NULL;
+ if (tail == NULL)
+ {
+ sr = psr;
+ old_chain = make_cleanup ((make_cleanup_func)
+ free_search_symbols, sr);
+ }
+ else
+ tail->next = psr;
+ tail = psr;
+ }
+ }
+ }
+ 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 || kind != FUNCTIONS_NAMESPACE)
+ {
+ ALL_MSYMBOLS (objfile, msymbol)
+ {
+ if (MSYMBOL_TYPE (msymbol) == ourtype ||
+ MSYMBOL_TYPE (msymbol) == ourtype2 ||
+ MSYMBOL_TYPE (msymbol) == ourtype3 ||
+ MSYMBOL_TYPE (msymbol) == ourtype4)
+ {
+ if (regexp == NULL || SYMBOL_MATCHES_REGEXP (msymbol))
+ {
+ /* Functions: Look up by address. */
+ if (kind != FUNCTIONS_NAMESPACE ||
+ (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)
+ {
+ /* match */
+ psr = (struct symbol_search *) xmalloc (sizeof (struct symbol_search));
+ psr->block = i;
+ psr->msymbol = msymbol;
+ psr->symtab = NULL;
+ psr->symbol = NULL;
+ psr->next = NULL;
+ if (tail == NULL)
+ {
+ sr = psr;
+ old_chain = make_cleanup ((make_cleanup_func)
+ free_search_symbols, &sr);
+ }
+ else
+ tail->next = psr;
+ tail = psr;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ *matches = sr;
+ if (sr != NULL)
+ discard_cleanups (old_chain);
+}
+
+/* Helper function for symtab_symbol_info, this function uses
+ the data returned from search_symbols() to print information
+ regarding the match to gdb_stdout.
+*/
+static void
+print_symbol_info (kind, s, sym, block, last)
+ namespace_enum kind;
+ struct symtab *s;
+ struct symbol *sym;
+ int block;
+ char *last;
+{
+ if (last == NULL || strcmp (last, s->filename) != 0)
+ {
+ fputs_filtered ("\nFile ", gdb_stdout);
+ fputs_filtered (s->filename, gdb_stdout);
+ fputs_filtered (":\n", gdb_stdout);
+ }
+
+ if (kind != TYPES_NAMESPACE && block == STATIC_BLOCK)
+ printf_filtered ("static ");
+
+ /* Typedef that is not a C++ class */
+ if (kind == TYPES_NAMESPACE
+ && SYMBOL_NAMESPACE (sym) != STRUCT_NAMESPACE)
+ c_typedef_print (SYMBOL_TYPE(sym), sym, gdb_stdout);
+ /* variable, func, or typedef-that-is-c++-class */
+ else if (kind < TYPES_NAMESPACE ||
+ (kind == TYPES_NAMESPACE &&
+ SYMBOL_NAMESPACE(sym) == STRUCT_NAMESPACE))
+ {
+ type_print (SYMBOL_TYPE (sym),
+ (SYMBOL_CLASS (sym) == LOC_TYPEDEF
+ ? "" : SYMBOL_SOURCE_NAME (sym)),
+ gdb_stdout, 0);
+
+ printf_filtered (";\n");
+ }
+ else
+ {
+# if 0
+ /* Tiemann says: "info methods was never implemented." */
+ char *demangled_name;
+ c_type_print_base (TYPE_FN_FIELD_TYPE(t, block),
+ gdb_stdout, 0, 0);
+ c_type_print_varspec_prefix (TYPE_FN_FIELD_TYPE(t, block),
+ gdb_stdout, 0);
+ if (TYPE_FN_FIELD_STUB (t, block))
+ check_stub_method (TYPE_DOMAIN_TYPE (type), j, block);
+ demangled_name =
+ cplus_demangle (TYPE_FN_FIELD_PHYSNAME (t, block),
+ DMGL_ANSI | DMGL_PARAMS);
+ if (demangled_name == NULL)
+ fprintf_filtered (stream, "<badly mangled name %s>",
+ TYPE_FN_FIELD_PHYSNAME (t, block));
+ else
+ {
+ fputs_filtered (demangled_name, stream);
+ free (demangled_name);
+ }
+# endif
+ }
+}
+
+/* This help function for symtab_symbol_info() prints information
+ for non-debugging symbols to gdb_stdout.
+*/
+static void
+print_msymbol_info (msymbol)
+ struct minimal_symbol *msymbol;
+{
+ printf_filtered (" %08lx %s\n",
+ (unsigned long) SYMBOL_VALUE_ADDRESS (msymbol),
+ SYMBOL_SOURCE_NAME (msymbol));
+}
+
+/* This is the guts of the commands "info functions", "info types", and
+ "info variables". It calls search_symbols to find all matches and then
+ print_[m]symbol_info to print out some useful information about the
+ matches.
+*/
+static void
+symtab_symbol_info (regexp, kind, from_tty)
+ char *regexp;
+ namespace_enum kind;
+ int from_tty;
+{
+ static char *classnames[]
+ = {"variable", "function", "type", "method"};
+ struct symbol_search *symbols;
+ struct symbol_search *p;
+ struct cleanup *old_chain;
+ char *last_filename = NULL;
+ int first = 1;
+
+ /* must make sure that if we're interrupted, symbols gets freed */
+ search_symbols (regexp, kind, 0, (char **) NULL, &symbols);
+ old_chain = make_cleanup ((make_cleanup_func) free_search_symbols, symbols);
+
+ printf_filtered (regexp
+ ? "All %ss matching regular expression \"%s\":\n"
+ : "All defined %ss:\n",
+ classnames[(int) (kind - LABEL_NAMESPACE - 1)], regexp);
+
+ for (p = symbols; p != NULL; p = p->next)
+ {
+ QUIT;
+
+ if (p->msymbol != NULL)
+ {
+ if (first)
+ {
+ printf_filtered ("\nNon-debugging symbols:\n");
+ first = 0;
+ }
+ print_msymbol_info (p->msymbol);
+ }
+ else
+ {
+ print_symbol_info (kind,
+ p->symtab,
+ p->symbol,
+ p->block,
+ last_filename);
+ last_filename = p->symtab->filename;
+ }
+ }
+
+ do_cleanups (old_chain);
+}
+
+static void
+variables_info (regexp, from_tty)
+ char *regexp;
+ int from_tty;
+{
+ symtab_symbol_info (regexp, VARIABLES_NAMESPACE, from_tty);
+}
+
+static void
+functions_info (regexp, from_tty)
+ char *regexp;
+ int from_tty;
+{
+ symtab_symbol_info (regexp, FUNCTIONS_NAMESPACE, from_tty);
+}
+
+static void
+types_info (regexp, from_tty)
+ char *regexp;
+ int from_tty;
+{
+ symtab_symbol_info (regexp, TYPES_NAMESPACE, from_tty);
+}
+
+#if 0
+/* Tiemann says: "info methods was never implemented." */
+static void
+methods_info (regexp)
+ char *regexp;
+{
+ symtab_symbol_info (regexp, METHODS_NAMESPACE, 0, from_tty);
+}
+#endif /* 0 */
+
+/* Breakpoint all functions matching regular expression. */
+static void
+rbreak_command (regexp, from_tty)
+ char *regexp;
+ int from_tty;
+{
+ struct symbol_search *ss;
+ struct symbol_search *p;
+ struct cleanup *old_chain;
+
+ search_symbols (regexp, FUNCTIONS_NAMESPACE, 0, (char **) NULL, &ss);
+ old_chain = make_cleanup ((make_cleanup_func) free_search_symbols, ss);
+
+ for (p = ss; p != NULL; p = p->next)
+ {
+ if (p->msymbol == NULL)
+ {
+ char *string = (char *) alloca (strlen (p->symtab->filename)
+ + strlen (SYMBOL_NAME (p->symbol))
+ + 4);
+ strcpy (string, p->symtab->filename);
+ strcat (string, ":'");
+ strcat (string, SYMBOL_NAME (p->symbol));
+ strcat (string, "'");
+ break_command (string, from_tty);
+ print_symbol_info (FUNCTIONS_NAMESPACE,
+ p->symtab,
+ p->symbol,
+ p->block,
+ p->symtab->filename);
+ }
+ else
+ {
+ break_command (SYMBOL_NAME (p->msymbol), from_tty);
+ printf_filtered ("<function, no debug info> %s;\n",
+ SYMBOL_SOURCE_NAME (p->msymbol));
+ }
+ }
+
+ do_cleanups (old_chain);
+}
+
+
+/* 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);
+ }
+
+ /* Recheck for duplicates if we intend to add a modified symbol. */
+ if (word != sym_text)
+ {
+ for (i = 0; i < return_val_index; ++i)
+ {
+ if (STREQ (new, return_val[i]))
+ {
+ free (new);
+ return;
+ }
+ }
+ }
+
+ 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);
+}
+
+/* Determine if PC is in the prologue of a function. The prologue is the area
+ between the first instruction of a function, and the first executable line.
+ Returns 1 if PC *might* be in prologue, 0 if definately *not* in prologue.
+
+ If non-zero, func_start is where we think the prologue starts, possibly
+ by previous examination of symbol table information.
+ */
+
+int
+in_prologue (pc, func_start)
+ CORE_ADDR pc;
+ CORE_ADDR func_start;
+{
+ struct symtab_and_line sal;
+ CORE_ADDR func_addr, func_end;
+
+ if (!find_pc_partial_function (pc, NULL, &func_addr, &func_end))
+ goto nosyms; /* Might be in prologue */
+
+ sal = find_pc_line (func_addr, 0);
+
+ if (sal.line == 0)
+ goto nosyms;
+
+ /* sal.end is the address of the first instruction past sal.line. */
+ if (sal.end > func_addr
+ && sal.end <= func_end) /* Is prologue in function? */
+ return pc < sal.end; /* Yes, is pc in prologue? */
+
+ /* The line after the prologue seems to be outside the function. In this
+ case, tell the caller to find the prologue the hard way. */
+
+ return 1;
+
+/* Come here when symtabs don't contain line # info. In this case, it is
+ likely that the user has stepped into a library function w/o symbols, or
+ is doing a stepi/nexti through code without symbols. */
+
+ nosyms:
+
+/* If func_start is zero (meaning unknown) then we don't know whether pc is
+ in the prologue or not. I.E. it might be. */
+
+ if (!func_start) return 1;
+
+/* We need to call the target-specific prologue skipping functions with the
+ function's start address because PC may be pointing at an instruction that
+ could be mistakenly considered part of the prologue. */
+
+ SKIP_PROLOGUE (func_start);
+
+ return pc < func_start;
+}
+
+
+/* Begin overload resolution functions */
+/* Helper routine for make_symbol_completion_list. */
+
+static int sym_return_val_size;
+static int sym_return_val_index;
+static struct symbol **sym_return_val;
+
+/* 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
+overload_list_add_symbol (sym, oload_name)
+ struct symbol * sym;
+ char * oload_name;
+{
+ int newsize;
+ int i;
+
+ /* Get the demangled name without parameters */
+ char * sym_name = cplus_demangle (SYMBOL_NAME (sym), DMGL_ARM | DMGL_ANSI);
+ if (!sym_name)
+ {
+ sym_name = (char *) xmalloc (strlen (SYMBOL_NAME (sym)) + 1);
+ strcpy (sym_name, SYMBOL_NAME (sym));
+ }
+
+ /* skip symbols that cannot match */
+ if (strcmp (sym_name, oload_name) != 0)
+ return;
+
+ /* If there is no type information, we can't do anything, so skip */
+ if (SYMBOL_TYPE (sym) == NULL)
+ return;
+
+ /* skip any symbols that we've already considered. */
+ for (i = 0; i < sym_return_val_index; ++i)
+ if (!strcmp (SYMBOL_NAME (sym), SYMBOL_NAME (sym_return_val[i])))
+ return;
+
+ /* We have a match for an overload instance, so add SYM to the current list
+ * of overload instances */
+ if (sym_return_val_index + 3 > sym_return_val_size)
+ {
+ newsize = (sym_return_val_size *= 2) * sizeof (struct symbol *);
+ sym_return_val = (struct symbol **) xrealloc ((char *) sym_return_val, newsize);
+ }
+ sym_return_val[sym_return_val_index++] = sym;
+ sym_return_val[sym_return_val_index] = NULL;
+
+ free (sym_name);
+}
+
+/* Return a null-terminated list of pointers to function symbols that
+ * match name of the supplied symbol FSYM.
+ * This is used in finding all overloaded instances of a function name.
+ * This has been modified from make_symbol_completion_list. */
+
+
+struct symbol **
+make_symbol_overload_list (fsym)
+ struct symbol * fsym;
+{
+ 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 name we are completing on. */
+ char *oload_name = NULL;
+ /* Length of name. */
+ int oload_name_len = 0;
+
+ /* Look for the symbol we are supposed to complete on.
+ * FIXME: This should be language-specific. */
+
+ oload_name = cplus_demangle (SYMBOL_NAME (fsym), DMGL_ARM | DMGL_ANSI);
+ if (!oload_name)
+ {
+ oload_name = (char *) xmalloc (strlen (SYMBOL_NAME (fsym)) + 1);
+ strcpy (oload_name, SYMBOL_NAME (fsym));
+ }
+ oload_name_len = strlen (oload_name);
+
+ sym_return_val_size = 100;
+ sym_return_val_index = 0;
+ sym_return_val = (struct symbol **) xmalloc ((sym_return_val_size + 1) * sizeof (struct symbol *));
+ sym_return_val[0] = NULL;
+
+ /* Look through the partial symtabs for all symbols which begin
+ by matching OLOAD_NAME. 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;
+ overload_list_add_symbol (*psym, oload_name);
+ }
+
+ for (psym = objfile->static_psymbols.list + ps->statics_offset;
+ psym < (objfile->static_psymbols.list + ps->statics_offset
+ + ps->n_static_syms);
+ psym++)
+ {
+ QUIT;
+ overload_list_add_symbol (*psym, oload_name);
+ }
+ }
+
+ /* 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;
+ overload_list_add_symbol (msymbol, oload_name);
+ }
+
+ /* 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 elimination 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);
+ overload_list_add_symbol (sym, oload_name);
+ }
+ }
+
+ /* 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);
+ overload_list_add_symbol (sym, oload_name);
+ }
+ }
+
+ 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);
+ overload_list_add_symbol (sym, oload_name);
+ }
+ }
+
+ free (oload_name);
+
+ return (sym_return_val);
+}
+
+/* End of overload resolution functions */
+
+
+void
+_initialize_symtab ()
+{
+ add_info ("variables", variables_info,
+ "All global and static variable names, or those matching REGEXP.");
+ if (dbx_commands)
+ add_com("whereis", class_info, 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", class_breakpoint, rbreak_command,
+ "Set a breakpoint for all functions matching REGEXP.");
+
+ if (xdb_commands)
+ {
+ add_com ("lf", class_info, sources_info, "Source files in the program");
+ add_com ("lg", class_info, variables_info,
+ "All global and static variable names, or those 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/gdb/symtab.h b/gdb/symtab.h
new file mode 100644
index 00000000000..67e6bedb25a
--- /dev/null
+++ b/gdb/symtab.h
@@ -0,0 +1,1477 @@
+/* Symbol table definitions for GDB.
+ Copyright 1986, 89, 91, 92, 93, 94, 95, 96, 1998
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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
+#include "bcache.h"
+
+/* Don't do this; it means that if some .o's are compiled with GNU C
+ and some are not (easy to do accidentally the way we configure
+ things; also it is a pain to have to "make clean" every time you
+ want to switch compilers), then GDB dies a horrible death. */
+/* GNU C supports enums that are bitfields. Some compilers don't. */
+#if 0 && defined(__GNUC__) && !defined(BYTE_BITFIELD)
+#define BYTE_BITFIELD :8;
+#else
+#define BYTE_BITFIELD /*nothing*/
+#endif
+
+/* 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.
+
+ These fields are ordered to encourage good packing, since we frequently
+ have tens or hundreds of thousands of these. */
+
+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
+ {
+ /* The fact that this is a long not a LONGEST mainly limits the
+ range of a LOC_CONST. Since LOC_CONST_BYTES exists, I'm not
+ sure that is a big deal. */
+ long ivalue;
+
+ struct block *block;
+
+ char *bytes;
+
+ CORE_ADDR address;
+
+ /* for opaque typedef struct chain */
+
+ struct symbol *chain;
+ }
+ value;
+
+ /* Since one and only one language can apply, wrap the language specific
+ information inside a union. */
+
+ union
+ {
+ struct cplus_specific /* For C++ */
+ /* and Java */
+ {
+ char *demangled_name;
+ } cplus_specific;
+ struct chill_specific /* For Chill */
+ {
+ char *demangled_name;
+ } chill_specific;
+ } language_specific;
+
+ /* Record the source code language that applies to this symbol.
+ This is used to select one of the fields from the language specific
+ union above. */
+
+ enum language language BYTE_BITFIELD;
+
+ /* 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). */
+
+ short section;
+
+ /* The bfd section associated with this symbol. */
+
+ asection *bfd_section;
+};
+
+extern CORE_ADDR symbol_overlayed_address PARAMS((CORE_ADDR, asection *));
+
+#define SYMBOL_NAME(symbol) (symbol)->ginfo.name
+#define SYMBOL_VALUE(symbol) (symbol)->ginfo.value.ivalue
+#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_BFD_SECTION(symbol) (symbol)->ginfo.bfd_section
+
+#define SYMBOL_CPLUS_DEMANGLED_NAME(symbol) \
+ (symbol)->ginfo.language_specific.cplus_specific.demangled_name
+
+/* 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_LANGUAGE (symbol) == language_java \
+ ) \
+ { \
+ 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 (SYMBOL_LANGUAGE (symbol) == language_java) \
+ { \
+ demangled = \
+ cplus_demangle (SYMBOL_NAME (symbol), \
+ DMGL_PARAMS | DMGL_ANSI | DMGL_JAVA); \
+ if (demangled != NULL) \
+ { \
+ SYMBOL_LANGUAGE (symbol) = language_java; \
+ 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_LANGUAGE (symbol) == language_java \
+ ? 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))
+
+/* 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
+ 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 allo-
+ cated 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.
+
+ Currently, the AMD 29000 tdep.c uses it to remember things it has decoded
+ from the instructions in the function header, and the MIPS-16 code uses
+ it to identify 16-bit procedures. */
+
+ char *info;
+
+#ifdef SOFUN_ADDRESS_MAYBE_MISSING
+ /* Which source file is this symbol in? Only relevant for mst_file_*. */
+ char *filename;
+#endif
+
+ /* 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) */
+ /* GDB uses mst_solib_trampoline for the start address of a shared
+ library trampoline entry. Breakpoints for shared library functions
+ are put there if the shared library is not yet loaded.
+ After the shared library is loaded, lookup_minimal_symbol will
+ prefer the minimal symbol from the shared library (usually
+ a mst_text symbol) over the mst_solib_trampoline symbol, and the
+ breakpoints will be moved to their true address in the shared
+ library via breakpoint_re_set. */
+ mst_solib_trampoline, /* Shared library trampoline code */
+ /* 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 BYTE_BITFIELD;
+};
+
+#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. */
+
+typedef enum
+{
+ /* 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,
+
+ /* Searching namespaces. These overlap with VAR_NAMESPACE, providing
+ some granularity with the search_symbols function. */
+
+ /* Everything in VAR_NAMESPACE minus FUNCTIONS_-, TYPES_-, and
+ METHODS_NAMESPACE */
+ VARIABLES_NAMESPACE,
+
+ /* All functions -- for some reason not methods, though. */
+ FUNCTIONS_NAMESPACE,
+
+ /* All defined types */
+ TYPES_NAMESPACE,
+
+ /* All class methods -- why is this separated out? */
+ METHODS_NAMESPACE
+
+} namespace_enum;
+
+/* 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,
+
+ /* Value is at fixed address, but the address of the variable has
+ to be determined from the minimal symbol table whenever the
+ variable is referenced.
+ This happens if debugging information for a global symbol is
+ emitted and the corresponding minimal symbol is defined
+ in another object file or runtime common storage.
+ The linker might even remove the minimal symbol if the global
+ symbol is never referenced, in which case the symbol remains
+ unresolved. */
+
+ LOC_UNRESOLVED,
+
+ /* Value is at a thread-specific location calculated by a
+ target-specific method. */
+
+ LOC_THREAD_LOCAL_STATIC,
+
+ /* The variable does not actually exist in the program.
+ The value is ignored. */
+
+ LOC_OPTIMIZED_OUT,
+
+ /* The variable is static, but actually lives at * (address).
+ * I.e. do an extra indirection to get to it.
+ * This is used on HP-UX to get at globals that are allocated
+ * in shared libraries, where references from images other
+ * than the one where the global was allocated are done
+ * with a level of indirection.
+ */
+
+ LOC_INDIRECT
+
+};
+
+/* Linked list of symbol's live ranges. */
+
+struct range_list
+{
+ CORE_ADDR start;
+ CORE_ADDR end;
+ struct range_list *next;
+};
+
+/* Linked list of aliases for a particular main/primary symbol. */
+struct alias_list
+ {
+ struct symbol *sym;
+ struct alias_list *next;
+ };
+
+struct symbol
+{
+
+ /* The general symbol info required for all types of symbols. */
+
+ struct general_symbol_info ginfo;
+
+ /* Data type of value */
+
+ struct type *type;
+
+ /* Name space code. */
+
+#ifdef __MFC4__
+ /* FIXME: don't conflict with C++'s namespace */
+ /* would be safer to do a global change for all namespace identifiers. */
+ #define namespace _namespace
+#endif
+ namespace_enum namespace BYTE_BITFIELD;
+
+ /* Address class */
+
+ enum address_class aclass BYTE_BITFIELD;
+
+ /* 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;
+
+
+ /* Link to a list of aliases for this symbol.
+ Only a "primary/main symbol may have aliases. */
+ struct alias_list *aliases;
+
+ /* List of ranges where this symbol is active. This is only
+ used by alias symbols at the current time. */
+ struct range_list *ranges;
+};
+
+
+#define SYMBOL_NAMESPACE(symbol) (symbol)->namespace
+#define SYMBOL_CLASS(symbol) (symbol)->aclass
+#define SYMBOL_TYPE(symbol) (symbol)->type
+#define SYMBOL_LINE(symbol) (symbol)->line
+#define SYMBOL_BASEREG(symbol) (symbol)->aux_value.basereg
+#define SYMBOL_ALIASES(symbol) (symbol)->aliases
+#define SYMBOL_RANGES(symbol) (symbol)->ranges
+
+/* 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. */
+
+ namespace_enum namespace BYTE_BITFIELD;
+
+ /* Address class (for info_symbols) */
+
+ enum address_class aclass BYTE_BITFIELD;
+
+};
+
+#define PSYMBOL_NAMESPACE(psymbol) (psymbol)->namespace
+#define PSYMBOL_CLASS(psymbol) (psymbol)->aclass
+
+
+/* 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])
+
+/* The maximum possible size of a section_offsets table. */
+
+#define SIZEOF_SECTION_OFFSETS \
+ (sizeof (struct section_offsets) \
+ + sizeof (((struct section_offsets *) 0)->offsets) * (SECT_OFF_MAX-1))
+
+
+/* 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. Probably always SECT_OFF_TEXT. */
+
+ 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 that identifies the format of the debugging information, such
+ as "stabs", "dwarf 1", "dwarf 2", "coff", etc. This is mostly useful
+ for automated testing of gdb but may also be information that is
+ useful to the user. */
+
+ char *debugformat;
+
+ /* 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;
+
+ };
+
+#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' && is_cplus_marker ((NAME)[2]))
+
+/* Macro that yields non-zero value iff NAME is the prefix for C++ vtbl
+ names. Note that this macro is g++ specific (FIXME).
+ '_vt$' is the old cfront-style vtables; '_VT$' is the new
+ style, using thunks (where '$' is really CPLUS_MARKER). */
+
+#define VTBL_PREFIX_P(NAME) \
+ ((NAME)[0] == '_' \
+ && (((NAME)[1] == 'V' && (NAME)[2] == 'T') \
+ || ((NAME)[1] == 'v' && (NAME)[2] == 't')) \
+ && is_cplus_marker ((NAME)[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] == '_' && is_cplus_marker ((NAME)[1]) && (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;
+
+/* True if we are nested inside psymtab_to_symtab. */
+
+extern int currently_reading_symtab;
+
+/* From utils.c. */
+extern int demangle;
+extern int asm_demangle;
+
+/* symtab.c lookup functions */
+
+/* lookup a symbol table by source file name */
+
+extern struct symtab *
+lookup_symtab PARAMS ((char *));
+
+/* lookup a symbol by name (optional block, optional symtab) */
+
+extern struct symbol *
+lookup_symbol PARAMS ((const char *, const struct block *,
+ const namespace_enum, int *, struct symtab **));
+
+/* lookup a symbol by name, within a specified block */
+
+extern struct symbol *
+lookup_block_symbol PARAMS ((const struct block *, const char *,
+ const namespace_enum));
+
+/* lookup a [struct, union, enum] by name, within a specified block */
+
+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 *));
+
+/* lookup the function corresponding to the block */
+
+extern struct symbol *
+block_function PARAMS ((struct block *));
+
+/* from blockframe.c: */
+
+/* lookup the function symbol corresponding to the address */
+
+extern struct symbol *
+find_pc_function PARAMS ((CORE_ADDR));
+
+/* lookup the function corresponding to the address and section */
+
+extern struct symbol *
+find_pc_sect_function PARAMS ((CORE_ADDR, asection *));
+
+/* lookup function from address, return name, start addr and end addr */
+
+extern int
+find_pc_partial_function PARAMS ((CORE_ADDR, char **,
+ CORE_ADDR *, CORE_ADDR *));
+
+extern void
+clear_pc_function_cache PARAMS ((void));
+
+extern int
+find_pc_sect_partial_function PARAMS ((CORE_ADDR, asection *,
+ char **, CORE_ADDR *, CORE_ADDR *));
+
+/* from symtab.c: */
+
+/* lookup partial symbol table by filename */
+
+extern struct partial_symtab *
+lookup_partial_symtab PARAMS ((char *));
+
+/* lookup partial symbol table by address */
+
+extern struct partial_symtab *
+find_pc_psymtab PARAMS ((CORE_ADDR));
+
+/* lookup partial symbol table by address and section */
+
+extern struct partial_symtab *
+find_pc_sect_psymtab PARAMS ((CORE_ADDR, asection *));
+
+/* lookup full symbol table by address */
+
+extern struct symtab *
+find_pc_symtab PARAMS ((CORE_ADDR));
+
+/* lookup full symbol table by address and section */
+
+extern struct symtab *
+find_pc_sect_symtab PARAMS ((CORE_ADDR, asection *));
+
+/* lookup partial symbol by address */
+
+extern struct partial_symbol *
+find_pc_psymbol PARAMS ((struct partial_symtab *, CORE_ADDR));
+
+/* lookup partial symbol by address and section */
+
+extern struct partial_symbol *
+find_pc_sect_psymbol PARAMS ((struct partial_symtab *, CORE_ADDR, asection *));
+
+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));
+
+extern struct type *
+lookup_transparent_type PARAMS ((const char *));
+
+
+/* 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
+
+/* 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,
+ struct objfile *));
+
+extern struct minimal_symbol *prim_record_minimal_symbol_and_info
+ PARAMS ((const char *, CORE_ADDR,
+ enum minimal_symbol_type,
+ char *info, int section,
+ asection *bfd_section,
+ struct objfile *));
+
+#ifdef SOFUN_ADDRESS_MAYBE_MISSING
+extern CORE_ADDR find_stab_function_addr PARAMS ((char *,
+ struct partial_symtab *,
+ struct objfile *));
+#endif
+
+extern struct minimal_symbol *
+lookup_minimal_symbol PARAMS ((const char *, const char *, struct objfile *));
+
+extern struct minimal_symbol *
+lookup_minimal_symbol_text PARAMS ((const char *, const char *, struct objfile *));
+
+struct minimal_symbol *
+lookup_minimal_symbol_solib_trampoline PARAMS ((const char *,
+ const char *,
+ struct objfile *));
+
+extern struct minimal_symbol *
+lookup_minimal_symbol_by_pc PARAMS ((CORE_ADDR));
+
+extern struct minimal_symbol *
+lookup_minimal_symbol_by_pc_section PARAMS ((CORE_ADDR, asection *));
+
+extern struct minimal_symbol *
+lookup_solib_trampoline_symbol_by_pc PARAMS ((CORE_ADDR));
+
+extern CORE_ADDR
+find_solib_trampoline_target 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 *));
+
+/* Sort all the minimal symbols in OBJFILE. */
+
+extern void msymbols_sort PARAMS ((struct objfile *objfile));
+
+struct symtab_and_line
+{
+ struct symtab *symtab;
+ asection *section;
+ /* 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;
+};
+
+#define INIT_SAL(sal) { \
+ (sal)->symtab = 0; \
+ (sal)->section = 0; \
+ (sal)->line = 0; \
+ (sal)->pc = 0; \
+ (sal)->end = 0; \
+}
+
+struct symtabs_and_lines
+{
+ struct symtab_and_line *sals;
+ int nelts;
+};
+
+
+
+/* Some types and macros needed for exception catchpoints.
+ Can't put these in target.h because symtab_and_line isn't
+ known there. This file will be included by breakpoint.c,
+ hppa-tdep.c, etc. */
+
+/* Enums for exception-handling support */
+enum exception_event_kind {
+ EX_EVENT_THROW,
+ EX_EVENT_CATCH
+};
+
+/* Type for returning info about an exception */
+struct exception_event_record {
+ enum exception_event_kind kind;
+ struct symtab_and_line throw_sal;
+ struct symtab_and_line catch_sal;
+ /* This may need to be extended in the future, if
+ some platforms allow reporting more information,
+ such as point of rethrow, type of exception object,
+ type expected by catch clause, etc. */
+};
+
+#define CURRENT_EXCEPTION_KIND (current_exception_event->kind)
+#define CURRENT_EXCEPTION_CATCH_SAL (current_exception_event->catch_sal)
+#define CURRENT_EXCEPTION_CATCH_LINE (current_exception_event->catch_sal.line)
+#define CURRENT_EXCEPTION_CATCH_FILE (current_exception_event->catch_sal.symtab->filename)
+#define CURRENT_EXCEPTION_CATCH_PC (current_exception_event->catch_sal.pc)
+#define CURRENT_EXCEPTION_THROW_SAL (current_exception_event->throw_sal)
+#define CURRENT_EXCEPTION_THROW_LINE (current_exception_event->throw_sal.line)
+#define CURRENT_EXCEPTION_THROW_FILE (current_exception_event->throw_sal.symtab->filename)
+#define CURRENT_EXCEPTION_THROW_PC (current_exception_event->throw_sal.pc)
+
+
+/* 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));
+
+/* Same function, but specify a section as well as an address */
+
+extern struct symtab_and_line
+find_pc_sect_line PARAMS ((CORE_ADDR, asection *, int));
+
+/* Given an address, return the nearest symbol at or below it in memory.
+ Optionally return the symtab it's from through 2nd arg, and the
+ address in inferior memory of the symbol through 3rd arg. */
+
+extern struct symbol *
+find_addr_symbol PARAMS ((CORE_ADDR, struct symtab **, CORE_ADDR *));
+
+/* Given a symtab and line number, return the pc there. */
+
+extern int
+find_line_pc PARAMS ((struct symtab *, int, CORE_ADDR *));
+
+extern int
+find_line_pc_range PARAMS ((struct symtab_and_line,
+ 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 ***));
+
+#if MAINTENANCE_CMDS
+
+/* Symmisc.c */
+
+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));
+
+void
+maintenance_check_symtabs PARAMS ((char *, int));
+
+/* maint.c */
+
+void
+maintenance_print_statistics 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, int, int));
+
+/* source.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 *));
+
+extern struct symbol **
+make_symbol_overload_list PARAMS ((struct symbol *));
+
+/* symtab.c */
+
+extern struct partial_symtab *
+find_main_psymtab PARAMS ((void));
+
+/* blockframe.c */
+
+extern struct blockvector *
+blockvector_for_pc PARAMS ((CORE_ADDR, int *));
+
+extern struct blockvector *
+blockvector_for_pc_sect PARAMS ((CORE_ADDR, asection *, int *,
+ struct symtab *));
+
+/* symfile.c */
+
+extern void
+clear_symtab_users PARAMS ((void));
+
+extern enum language
+deduce_language_from_filename PARAMS ((char *));
+
+/* symtab.c */
+
+extern int
+in_prologue PARAMS ((CORE_ADDR pc, CORE_ADDR func_start));
+
+extern struct symbol *
+fixup_symbol_section PARAMS ((struct symbol *, struct objfile *));
+
+/* Symbol searching */
+
+/* When using search_symbols, a list of the following structs is returned.
+ Callers must free the search list using free_symbol_search! */
+struct symbol_search
+{
+ /* The block in which the match was found. Could be, for example,
+ STATIC_BLOCK or GLOBAL_BLOCK. */
+ int block;
+
+ /* Information describing what was found.
+
+ If symtab abd symbol are NOT NULL, then information was found
+ for this match. */
+ struct symtab *symtab;
+ struct symbol *symbol;
+
+ /* If msymbol is non-null, then a match was made on something for
+ which only minimal_symbols exist. */
+ struct minimal_symbol *msymbol;
+
+ /* A link to the next match, or NULL for the end. */
+ struct symbol_search *next;
+};
+
+extern void search_symbols PARAMS ((char *, namespace_enum, int, char **, struct symbol_search **));
+extern void free_search_symbols PARAMS ((struct symbol_search *));
+
+#endif /* !defined(SYMTAB_H) */
diff --git a/gdb/tahoe-tdep.c b/gdb/tahoe-tdep.c
new file mode 100644
index 00000000000..ea8a752af6d
--- /dev/null
+++ b/gdb/tahoe-tdep.c
@@ -0,0 +1,234 @@
+/* Print instructions for Tahoe target machines, for GDB.
+ Copyright 1986, 1989, 1991, 1992 Free Software Foundation, Inc.
+ Contributed by the State University of New York at Buffalo, by the
+ Distributed Computer Systems Lab, Department of Computer Science, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "symtab.h"
+#include "opcode/tahoe.h"
+
+/* Tahoe instructions are never longer than this. */
+#define MAXLEN 62
+
+/* Number of elements in the opcode table. */
+#define NOPCODES (sizeof votstrs / sizeof votstrs[0])
+
+static unsigned char *print_insn_arg ();
+
+/* Print the Tahoe instruction at address MEMADDR in debugged memory,
+ on STREAM. Returns length of the instruction, in bytes. */
+
+int
+tahoe_print_insn (memaddr, stream)
+ CORE_ADDR memaddr;
+ GDB_FILE *stream;
+{
+ unsigned char buffer[MAXLEN];
+ register int i;
+ register unsigned char *p;
+ register char *d;
+
+ read_memory (memaddr, buffer, MAXLEN);
+
+ for (i = 0; i < NOPCODES; i++)
+ if (votstrs[i].detail.code == buffer[0]
+ || votstrs[i].detail.code == *(unsigned short *)buffer)
+ break;
+
+ /* Handle undefined instructions. */
+ if (i == NOPCODES)
+ {
+ fprintf_unfiltered (stream, "0%o", buffer[0]);
+ return 1;
+ }
+
+ fprintf_unfiltered (stream, "%s", votstrs[i].name);
+
+ /* Point at first byte of argument data,
+ and at descriptor for first argument. */
+ p = buffer + 1 + (votstrs[i].detail.code >= 0x100);
+ d = votstrs[i].detail.args;
+
+ if (*d)
+ fputc_unfiltered ('\t', stream);
+
+ while (*d)
+ {
+ p = print_insn_arg (d, p, memaddr + (p - buffer), stream);
+ d += 2;
+ if (*d)
+ fprintf_unfiltered (stream, ",");
+ }
+ return p - buffer;
+}
+/*******************************************************************/
+static unsigned char *
+print_insn_arg (d, p, addr, stream)
+ char *d;
+ register char *p;
+ CORE_ADDR addr;
+ GDB_FILE *stream;
+{
+ int temp1 = 0;
+ register int regnum = *p & 0xf;
+ float floatlitbuf;
+
+ if (*d == 'b')
+ {
+ if (d[1] == 'b')
+ fprintf_unfiltered (stream, "0x%x", addr + *p++ + 1);
+ else
+ {
+
+ temp1 = *p;
+ temp1 <<= 8;
+ temp1 |= *(p + 1);
+ fprintf_unfiltered (stream, "0x%x", addr + temp1 + 2);
+ p += 2;
+ }
+ }
+ else
+ switch ((*p++ >> 4) & 0xf)
+ {
+ case 0:
+ case 1:
+ case 2:
+ case 3: /* Literal (short immediate byte) mode */
+ if (d[1] == 'd' || d[1] == 'f' || d[1] == 'g' || d[1] == 'h')
+ {
+ *(int *)&floatlitbuf = 0x4000 + ((p[-1] & 0x3f) << 4);
+ fprintf_unfiltered (stream, "$%f", floatlitbuf);
+ }
+ else
+ fprintf_unfiltered (stream, "$%d", p[-1] & 0x3f);
+ break;
+
+ case 4: /* Indexed */
+ p = (char *) print_insn_arg (d, p, addr + 1, stream);
+ fprintf_unfiltered (stream, "[%s]", REGISTER_NAME (regnum));
+ break;
+
+ case 5: /* Register */
+ fprintf_unfiltered (stream, REGISTER_NAME (regnum));
+ break;
+
+ case 7: /* Autodecrement */
+ fputc_unfiltered ('-', stream);
+ case 6: /* Register deferred */
+ fprintf_unfiltered (stream, "(%s)", REGISTER_NAME (regnum));
+ break;
+
+ case 9: /* Absolute Address & Autoincrement deferred */
+ fputc_unfiltered ('*', stream);
+ if (regnum == PC_REGNUM)
+ {
+ temp1 = *p;
+ temp1 <<= 8;
+ temp1 |= *(p +1);
+
+ fputc_unfiltered ('$', stream);
+ print_address (temp1, stream);
+ p += 4;
+ break;
+ }
+ case 8: /*Immediate & Autoincrement SP */
+ if (regnum == 8) /*88 is Immediate Byte Mode*/
+ fprintf_unfiltered (stream, "$%d", *p++);
+
+ else if (regnum == 9) /*89 is Immediate Word Mode*/
+ {
+ temp1 = *p;
+ temp1 <<= 8;
+ temp1 |= *(p +1);
+ fprintf_unfiltered (stream, "$%d", temp1);
+ p += 2;
+ }
+
+ else if (regnum == PC_REGNUM) /*8F is Immediate Long Mode*/
+ {
+ temp1 = *p;
+ temp1 <<=8;
+ temp1 |= *(p +1);
+ temp1 <<=8;
+ temp1 |= *(p +2);
+ temp1 <<= 8;
+ temp1 |= *(p +3);
+ fprintf_unfiltered (stream, "$%d", temp1);
+ p += 4;
+ }
+
+ else /*8E is Autoincrement SP Mode*/
+ fprintf_unfiltered (stream, "(%s)+", REGISTER_NAME (regnum));
+ break;
+
+ case 11: /* Register + Byte Displacement Deferred Mode*/
+ fputc_unfiltered ('*', stream);
+ case 10: /* Register + Byte Displacement Mode*/
+ if (regnum == PC_REGNUM)
+ print_address (addr + *p + 2, stream);
+ else
+ fprintf_unfiltered (stream, "%d(%s)", *p, REGISTER_NAME (regnum));
+ p += 1;
+ break;
+
+ case 13: /* Register + Word Displacement Deferred Mode*/
+ fputc_unfiltered ('*', stream);
+ case 12: /* Register + Word Displacement Mode*/
+ temp1 = *p;
+ temp1 <<= 8;
+ temp1 |= *(p +1);
+ if (regnum == PC_REGNUM)
+ print_address (addr + temp1 + 3, stream);
+ else
+ fprintf_unfiltered (stream, "%d(%s)", temp1, REGISTER_NAME (regnum));
+ p += 2;
+ break;
+
+ case 15: /* Register + Long Displacement Deferred Mode*/
+ fputc_unfiltered ('*', stream);
+ case 14: /* Register + Long Displacement Mode*/
+ temp1 = *p;
+ temp1 <<= 8;
+ temp1 |= *(p +1);
+ temp1 <<= 8;
+ temp1 |= *(p +2);
+ temp1 <<= 8;
+ temp1 |= *(p +3);
+ if (regnum == PC_REGNUM)
+ print_address (addr + temp1 + 5, stream);
+ else
+ fprintf_unfiltered (stream, "%d(%s)", temp1, REGISTER_NAME (regnum));
+ p += 4;
+ }
+
+ return (unsigned char *) p;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/gdb/target.c b/gdb/target.c
new file mode 100644
index 00000000000..808eb8fc16d
--- /dev/null
+++ b/gdb/target.c
@@ -0,0 +1,2581 @@
+/* Select target systems and architectures at runtime for GDB.
+ Copyright 1990, 1992-1995, 1998, 1999 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include <errno.h>
+#include <ctype.h>
+#include "gdb_string.h"
+#include "target.h"
+#include "gdbcmd.h"
+#include "symtab.h"
+#include "inferior.h"
+#include "bfd.h"
+#include "symfile.h"
+#include "objfiles.h"
+#include "wait.h"
+#include <signal.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
+default_clone_and_follow_inferior PARAMS ((int, int *));
+
+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, struct target_ops *));
+
+static int
+return_zero PARAMS ((void));
+
+static int
+return_one PARAMS ((void));
+
+void
+target_ignore PARAMS ((void));
+
+static void
+target_command PARAMS ((char *, int));
+
+static struct target_ops *
+find_default_run_target PARAMS ((char *));
+
+static void
+update_current_target PARAMS ((void));
+
+/* 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). */
+
+static int
+target_xfer_memory PARAMS ((CORE_ADDR memaddr, char *myaddr, int len,
+ int write, asection *bfd_section));
+
+static void init_dummy_target PARAMS ((void));
+
+static void
+debug_to_open PARAMS ((char *, int));
+
+static void
+debug_to_close PARAMS ((int));
+
+static void
+debug_to_attach PARAMS ((char *, int));
+
+static void
+debug_to_detach PARAMS ((char *, int));
+
+static void
+debug_to_resume PARAMS ((int, int, enum target_signal));
+
+static int
+debug_to_wait PARAMS ((int, struct target_waitstatus *));
+
+static void
+debug_to_fetch_registers PARAMS ((int));
+
+static void
+debug_to_store_registers PARAMS ((int));
+
+static void
+debug_to_prepare_to_store PARAMS ((void));
+
+static int
+debug_to_xfer_memory PARAMS ((CORE_ADDR, char *, int, int, struct target_ops *));
+
+static void
+debug_to_files_info PARAMS ((struct target_ops *));
+
+static int
+debug_to_insert_breakpoint PARAMS ((CORE_ADDR, char *));
+
+static int
+debug_to_remove_breakpoint PARAMS ((CORE_ADDR, char *));
+
+static void
+debug_to_terminal_init PARAMS ((void));
+
+static void
+debug_to_terminal_inferior PARAMS ((void));
+
+static void
+debug_to_terminal_ours_for_output PARAMS ((void));
+
+static void
+debug_to_terminal_ours PARAMS ((void));
+
+static void
+debug_to_terminal_info PARAMS ((char *, int));
+
+static void
+debug_to_kill PARAMS ((void));
+
+static void
+debug_to_load PARAMS ((char *, int));
+
+static int
+debug_to_lookup_symbol PARAMS ((char *, CORE_ADDR *));
+
+static void
+debug_to_create_inferior PARAMS ((char *, char *, char **));
+
+static void
+debug_to_mourn_inferior PARAMS ((void));
+
+static int
+debug_to_can_run PARAMS ((void));
+
+static void
+debug_to_notice_signals PARAMS ((int));
+
+static int
+debug_to_thread_alive PARAMS ((int));
+
+static void
+debug_to_stop PARAMS ((void));
+
+static int debug_to_query PARAMS ((int/*char*/, char *, char *, int *));
+
+/* 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. */
+
+static struct target_ops dummy_target;
+
+/* Top of target stack. */
+
+struct target_stack_item *target_stack;
+
+/* The target structure we are currently using to talk to a process
+ or file or whatever "inferior" we have. */
+
+struct target_ops current_target;
+
+/* Command list for target. */
+
+static struct cmd_list_element *targetlist = NULL;
+
+/* Nonzero if we are debugging an attached outside process
+ rather than an inferior. */
+
+int attach_flag;
+
+#ifdef MAINTENANCE_CMDS
+/* Non-zero if we want to see trace of target level stuff. */
+
+static int targetdebug = 0;
+
+static void setup_target_debug PARAMS ((void));
+
+#endif
+
+/* 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",
+ gdb_stdout);
+}
+
+/* Add a possible target architecture to the list. */
+
+void
+add_target (t)
+ struct target_ops *t;
+{
+ 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 */
+
+void
+target_ignore ()
+{
+}
+
+/* ARGSUSED */
+static int
+nomemory (memaddr, myaddr, len, write, t)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+ int write;
+ struct target_ops *t;
+{
+ 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 */
+void
+nosupport_runtime ()
+{
+ if (!inferior_pid)
+ noprocess ();
+ else
+ error ("No run-time support for this");
+}
+
+
+/* ARGSUSED */
+static void
+default_terminal_info (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ printf_unfiltered("No saved terminal information.\n");
+}
+
+/* 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_unfiltered ("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);
+}
+
+static void
+default_clone_and_follow_inferior (child_pid, followed_child)
+ int child_pid;
+ int *followed_child;
+{
+ target_clone_and_follow_inferior (child_pid, followed_child);
+}
+
+/* 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;
+{
+
+#define de_fault(field, value) \
+ if (!t->field) t->field = value
+
+ /* FIELD DEFAULT VALUE */
+
+ de_fault (to_open, (void (*) PARAMS((char *, int))) tcomplain);
+ de_fault (to_close, (void (*) PARAMS((int))) target_ignore);
+ de_fault (to_attach, maybe_kill_then_attach);
+ de_fault (to_post_attach, (void (*) PARAMS ((int))) target_ignore);
+ de_fault (to_require_attach, maybe_kill_then_attach);
+ de_fault (to_detach, (void (*) PARAMS((char *, int))) target_ignore);
+ de_fault (to_require_detach, (void (*) PARAMS((int, char *, int))) target_ignore);
+ de_fault (to_resume, (void (*) PARAMS((int, int, enum target_signal))) noprocess);
+ de_fault (to_wait, (int (*) PARAMS((int, struct target_waitstatus *))) noprocess);
+ de_fault (to_post_wait, (void (*) PARAMS ((int, int))) target_ignore);
+ de_fault (to_fetch_registers, (void (*) PARAMS((int))) target_ignore);
+ de_fault (to_store_registers, (void (*) PARAMS((int))) noprocess);
+ de_fault (to_prepare_to_store, (void (*) PARAMS((void))) noprocess);
+ de_fault (to_xfer_memory, (int (*) PARAMS((CORE_ADDR, char *, int, int, struct target_ops *))) nomemory);
+ de_fault (to_files_info, (void (*) PARAMS((struct target_ops *))) target_ignore);
+ de_fault (to_insert_breakpoint, memory_insert_breakpoint);
+ de_fault (to_remove_breakpoint, memory_remove_breakpoint);
+ de_fault (to_terminal_init, (void (*) PARAMS((void))) target_ignore);
+ de_fault (to_terminal_inferior, (void (*) PARAMS ((void))) target_ignore);
+ de_fault (to_terminal_ours_for_output,(void (*) PARAMS ((void))) target_ignore);
+ de_fault (to_terminal_ours, (void (*) PARAMS ((void))) target_ignore);
+ de_fault (to_terminal_info, default_terminal_info);
+ de_fault (to_kill, (void (*) PARAMS((void))) noprocess);
+ de_fault (to_load, (void (*) PARAMS((char *, int))) tcomplain);
+ de_fault (to_lookup_symbol, (int (*) PARAMS ((char *, CORE_ADDR *))) nosymbol);
+ de_fault (to_create_inferior, maybe_kill_then_create_inferior);
+ de_fault (to_post_startup_inferior, (void (*) PARAMS ((int))) target_ignore);
+ de_fault (to_acknowledge_created_inferior, (void (*) PARAMS((int))) target_ignore);
+ de_fault (to_clone_and_follow_inferior, default_clone_and_follow_inferior);
+ de_fault (to_post_follow_inferior_by_clone, (void (*) PARAMS ((void))) target_ignore);
+ de_fault (to_insert_fork_catchpoint, (int (*) PARAMS ((int))) tcomplain);
+ de_fault (to_remove_fork_catchpoint, (int (*) PARAMS ((int))) tcomplain);
+ de_fault (to_insert_vfork_catchpoint, (int (*) PARAMS ((int))) tcomplain);
+ de_fault (to_remove_vfork_catchpoint, (int (*) PARAMS ((int))) tcomplain);
+ de_fault (to_has_forked, (int (*) PARAMS ((int, int *))) return_zero);
+ de_fault (to_has_vforked, (int (*) PARAMS ((int, int *))) return_zero);
+ de_fault (to_can_follow_vfork_prior_to_exec, (int (*) PARAMS ((void ))) return_zero);
+ de_fault (to_post_follow_vfork, (void (*) PARAMS ((int, int, int, int))) target_ignore);
+ de_fault (to_insert_exec_catchpoint, (int (*) PARAMS ((int))) tcomplain);
+ de_fault (to_remove_exec_catchpoint, (int (*) PARAMS ((int))) tcomplain);
+ de_fault (to_has_execd, (int (*) PARAMS ((int, char **))) return_zero);
+ de_fault (to_reported_exec_events_per_exec_call, (int (*) PARAMS ((void))) return_one);
+ de_fault (to_has_syscall_event, (int (*) PARAMS ((int, enum target_waitkind *, int *))) return_zero);
+ de_fault (to_has_exited, (int (*) PARAMS ((int, int, int *))) return_zero);
+ de_fault (to_mourn_inferior, (void (*) PARAMS ((void))) noprocess);
+ de_fault (to_can_run, return_zero);
+ de_fault (to_notice_signals, (void (*) PARAMS((int))) target_ignore);
+ de_fault (to_thread_alive, (int (*) PARAMS((int))) target_ignore);
+ de_fault (to_stop, (void (*) PARAMS((void))) target_ignore);
+ de_fault (to_query, (int (*) PARAMS((int/*char*/, char*, char *, int *))) target_ignore);
+ de_fault (to_enable_exception_callback, (struct symtab_and_line * (*) PARAMS((enum exception_event_kind, int))) nosupport_runtime);
+ de_fault (to_get_current_exception_event, (struct exception_event_record * (*) PARAMS((void))) nosupport_runtime);
+
+ de_fault (to_pid_to_exec_file, (char* (*) PARAMS((int))) return_zero);
+ de_fault (to_core_file_to_sym_file, (char* (*) PARAMS ((char *))) return_zero);
+#undef de_fault
+}
+
+/* Go through the target stack from top to bottom, copying over zero entries in
+ current_target. In effect, we are doing class inheritance through the
+ pushed target vectors. */
+
+static void
+update_current_target ()
+{
+ struct target_stack_item *item;
+ struct target_ops *t;
+
+ /* First, reset current_target */
+ memset (&current_target, 0, sizeof current_target);
+
+ for (item = target_stack; item; item = item->next)
+ {
+ t = item->target_ops;
+
+#define INHERIT(FIELD, TARGET) \
+ if (!current_target.FIELD) \
+ current_target.FIELD = TARGET->FIELD
+
+ INHERIT (to_shortname, t);
+ INHERIT (to_longname, t);
+ INHERIT (to_doc, t);
+ INHERIT (to_open, t);
+ INHERIT (to_close, t);
+ INHERIT (to_attach, t);
+ INHERIT (to_post_attach, t);
+ INHERIT (to_require_attach, t);
+ INHERIT (to_detach, t);
+ INHERIT (to_require_detach, t);
+ INHERIT (to_resume, t);
+ INHERIT (to_wait, t);
+ INHERIT (to_post_wait, t);
+ INHERIT (to_fetch_registers, t);
+ INHERIT (to_store_registers, t);
+ INHERIT (to_prepare_to_store, t);
+ INHERIT (to_xfer_memory, t);
+ INHERIT (to_files_info, t);
+ INHERIT (to_insert_breakpoint, t);
+ INHERIT (to_remove_breakpoint, t);
+ INHERIT (to_terminal_init, t);
+ INHERIT (to_terminal_inferior, t);
+ INHERIT (to_terminal_ours_for_output, t);
+ INHERIT (to_terminal_ours, t);
+ INHERIT (to_terminal_info, t);
+ INHERIT (to_kill, t);
+ INHERIT (to_load, t);
+ INHERIT (to_lookup_symbol, t);
+ INHERIT (to_create_inferior, t);
+ INHERIT (to_post_startup_inferior, t);
+ INHERIT (to_acknowledge_created_inferior, t);
+ INHERIT (to_clone_and_follow_inferior, t);
+ INHERIT (to_post_follow_inferior_by_clone, t);
+ INHERIT (to_insert_fork_catchpoint, t);
+ INHERIT (to_remove_fork_catchpoint, t);
+ INHERIT (to_insert_vfork_catchpoint, t);
+ INHERIT (to_remove_vfork_catchpoint, t);
+ INHERIT (to_has_forked, t);
+ INHERIT (to_has_vforked, t);
+ INHERIT (to_can_follow_vfork_prior_to_exec, t);
+ INHERIT (to_post_follow_vfork, t);
+ INHERIT (to_insert_exec_catchpoint, t);
+ INHERIT (to_remove_exec_catchpoint, t);
+ INHERIT (to_has_execd, t);
+ INHERIT (to_reported_exec_events_per_exec_call, t);
+ INHERIT (to_has_syscall_event, t);
+ INHERIT (to_has_exited, t);
+ INHERIT (to_mourn_inferior, t);
+ INHERIT (to_can_run, t);
+ INHERIT (to_notice_signals, t);
+ INHERIT (to_thread_alive, t);
+ INHERIT (to_stop, t);
+ INHERIT (to_query, t);
+ INHERIT (to_enable_exception_callback, t);
+ INHERIT (to_get_current_exception_event, t);
+ INHERIT (to_pid_to_exec_file, t);
+ INHERIT (to_core_file_to_sym_file, t);
+ INHERIT (to_stratum, t);
+ INHERIT (DONT_USE, t);
+ INHERIT (to_has_all_memory, t);
+ INHERIT (to_has_memory, t);
+ INHERIT (to_has_stack, t);
+ INHERIT (to_has_registers, t);
+ INHERIT (to_has_execution, t);
+ INHERIT (to_has_thread_control, t);
+ INHERIT (to_sections, t);
+ INHERIT (to_sections_end, t);
+ INHERIT (to_magic, t);
+
+#undef INHERIT
+ }
+}
+
+/* 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_stack_item *cur, *prev, *tmp;
+
+ /* 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_unfiltered(gdb_stderr,
+ "Magic number of %s target struct wrong\n",
+ t->to_shortname);
+ abort();
+ }
+
+ /* Find the proper stratum to install this target in. */
+
+ for (prev = NULL, cur = target_stack; cur; prev = cur, cur = cur->next)
+ {
+ if ((int)(t->to_stratum) >= (int)(cur->target_ops->to_stratum))
+ break;
+ }
+
+ /* If there's already targets at this stratum, remove them. */
+
+ if (cur)
+ while (t->to_stratum == cur->target_ops->to_stratum)
+ {
+ /* There's already something on this stratum. Close it off. */
+ if (cur->target_ops->to_close)
+ (cur->target_ops->to_close) (0);
+ if (prev)
+ prev->next = cur->next; /* Unchain old target_ops */
+ else
+ target_stack = cur->next; /* Unchain first on list */
+ tmp = cur->next;
+ free (cur);
+ cur = tmp;
+ }
+
+ /* We have removed all targets in our stratum, now add the new one. */
+
+ tmp = (struct target_stack_item *)
+ xmalloc (sizeof (struct target_stack_item));
+ tmp->next = cur;
+ tmp->target_ops = t;
+
+ if (prev)
+ prev->next = tmp;
+ else
+ target_stack = tmp;
+
+ update_current_target ();
+
+ cleanup_target (&current_target); /* Fill in the gaps */
+
+#ifdef MAINTENANCE_CMDS
+ if (targetdebug)
+ setup_target_debug ();
+#endif
+
+ 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). */
+
+int
+unpush_target (t)
+ struct target_ops *t;
+{
+ struct target_stack_item *cur, *prev;
+
+ if (t->to_close)
+ t->to_close (0); /* Let it clean up */
+
+ /* Look for the specified target. Note that we assume that a target
+ can only occur once in the target stack. */
+
+ for (cur = target_stack, prev = NULL; cur; prev = cur, cur = cur->next)
+ if (cur->target_ops == t)
+ break;
+
+ if (!cur)
+ return 0; /* Didn't find target_ops, quit now */
+
+ /* Unchain the target */
+
+ if (!prev)
+ target_stack = cur->next;
+ else
+ prev->next = cur->next;
+
+ free (cur); /* Release the target_stack_item */
+
+ update_current_target ();
+ cleanup_target (&current_target);
+
+ return 1;
+}
+
+void
+pop_target ()
+{
+ (current_target.to_close)(0); /* Let it clean up */
+ if (unpush_target (target_stack->target_ops) == 1)
+ return;
+
+ fprintf_unfiltered(gdb_stderr,
+ "pop_target couldn't find target %s\n",
+ current_target.to_shortname);
+ abort();
+}
+
+#undef MIN
+#define MIN(A, B) (((A) <= (B)) ? (A) : (B))
+
+/* target_read_string -- read a null terminated string, up to LEN bytes,
+ from MEMADDR in target. Set *ERRNOP to the errno code, or 0 if successful.
+ Set *STRING to a pointer to malloc'd memory containing the data; the caller
+ is responsible for freeing it. Return the number of bytes successfully
+ read. */
+
+int
+target_read_string (memaddr, string, len, errnop)
+ CORE_ADDR memaddr;
+ char **string;
+ int len;
+ int *errnop;
+{
+ int tlen, origlen, offset, i;
+ char buf[4];
+ int errcode = 0;
+ char *buffer;
+ int buffer_allocated;
+ char *bufptr;
+ unsigned int nbytes_read = 0;
+
+ /* Small for testing. */
+ buffer_allocated = 4;
+ buffer = xmalloc (buffer_allocated);
+ bufptr = buffer;
+
+ origlen = len;
+
+ while (len > 0)
+ {
+ tlen = MIN (len, 4 - (memaddr & 3));
+ offset = memaddr & 3;
+
+ errcode = target_xfer_memory (memaddr & ~3, buf, 4, 0, NULL);
+ if (errcode != 0)
+ {
+ /* The transfer request might have crossed the boundary to an
+ unallocated region of memory. Retry the transfer, requesting
+ a single byte. */
+ tlen = 1;
+ offset = 0;
+ errcode = target_xfer_memory (memaddr, buf, 1, 0, NULL);
+ if (errcode != 0)
+ goto done;
+ }
+
+ if (bufptr - buffer + tlen > buffer_allocated)
+ {
+ unsigned int bytes;
+ bytes = bufptr - buffer;
+ buffer_allocated *= 2;
+ buffer = xrealloc (buffer, buffer_allocated);
+ bufptr = buffer + bytes;
+ }
+
+ for (i = 0; i < tlen; i++)
+ {
+ *bufptr++ = buf[i + offset];
+ if (buf[i + offset] == '\000')
+ {
+ nbytes_read += i + 1;
+ goto done;
+ }
+ }
+
+ memaddr += tlen;
+ len -= tlen;
+ nbytes_read += tlen;
+ }
+ done:
+ if (errnop != NULL)
+ *errnop = errcode;
+ if (string != NULL)
+ *string = buffer;
+ return nbytes_read;
+}
+
+/* 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, NULL);
+}
+
+int
+target_read_memory_section (memaddr, myaddr, len, bfd_section)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+ asection *bfd_section;
+{
+ return target_xfer_memory (memaddr, myaddr, len, 0, bfd_section);
+}
+
+/* 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, NULL);
+ 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, NULL);
+ }
+ /* 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, NULL);
+}
+
+/* This variable is used to pass section information down to targets. This
+ *should* be done by adding an argument to the target_xfer_memory function
+ of all the targets, but I didn't feel like changing 50+ files. */
+
+asection *target_memory_bfd_section = NULL;
+
+/* 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. */
+
+static int
+target_xfer_memory (memaddr, myaddr, len, write, bfd_section)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+ int write;
+ asection *bfd_section;
+{
+ int curlen;
+ int res;
+ struct target_ops *t;
+ struct target_stack_item *item;
+
+ /* Zero length requests are ok and require no work. */
+ if (len == 0)
+ return 0;
+
+ target_memory_bfd_section = bfd_section;
+
+ /* 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 (item = target_stack; item; item = item->next)
+ {
+ t = item->target_ops;
+ if (!t->to_has_memory)
+ continue;
+
+ res = t->to_xfer_memory (memaddr, myaddr, curlen, write, t);
+ if (res > 0)
+ break; /* Handled all or part of xfer */
+ if (t->to_has_all_memory)
+ break;
+ }
+
+ 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;
+ struct target_stack_item *item;
+ int has_all_mem = 0;
+
+ if (symfile_objfile != NULL)
+ printf_unfiltered ("Symbols from \"%s\".\n", symfile_objfile->name);
+
+#ifdef FILES_INFO_HOOK
+ if (FILES_INFO_HOOK ())
+ return;
+#endif
+
+ for (item = target_stack; item; item = item->next)
+ {
+ t = item->target_ops;
+
+ if (!t->to_has_memory)
+ continue;
+
+ if ((int)(t->to_stratum) <= (int)dummy_stratum)
+ continue;
+ if (has_all_mem)
+ printf_unfiltered("\tWhile running this, GDB does not access memory from...\n");
+ printf_unfiltered("%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.");
+ }
+
+ /* Calling target_kill may remove the target from the stack. But if
+ it doesn't (which seems like a win for UDI), remove it now. */
+
+ if (target_has_execution)
+ pop_target ();
+}
+
+/* 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);
+}
+
+void
+target_link (modname, t_reloc)
+ char *modname;
+ CORE_ADDR *t_reloc;
+{
+ if (STREQ(current_target.to_shortname, "rombug"))
+ {
+ (current_target.to_lookup_symbol) (modname, t_reloc);
+ if (*t_reloc == 0)
+ error("Unable to link to %s and get relocation in rombug", modname);
+ }
+ else
+ *t_reloc = (CORE_ADDR)-1;
+}
+
+/* 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 ((*t)->to_can_run && 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_require_attach (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ struct target_ops *t;
+
+ t = find_default_run_target("require_attach");
+ (t->to_require_attach) (args, from_tty);
+ return;
+}
+
+void
+find_default_require_detach (pid, args, from_tty)
+ int pid;
+ char * args;
+ int from_tty;
+{
+ struct target_ops *t;
+
+ t = find_default_run_target("require_detach");
+ (t->to_require_detach) (pid, 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;
+}
+
+void
+find_default_clone_and_follow_inferior (child_pid, followed_child)
+ int child_pid;
+ int *followed_child;
+{
+ struct target_ops *t;
+
+ t = find_default_run_target("run");
+ (t->to_clone_and_follow_inferior) (child_pid, followed_child);
+ return;
+}
+
+static int
+return_zero ()
+{
+ return 0;
+}
+
+static int
+return_one ()
+{
+ return 1;
+}
+
+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);
+}
+
+/* The inferior process has died. Long live the inferior! */
+
+void
+generic_mourn_inferior ()
+{
+ extern int show_breakpoint_hit_counts;
+
+ inferior_pid = 0;
+ attach_flag = 0;
+ breakpoint_init_inferior (inf_exited);
+ 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. */
+ /* However, it is more confusing for the ignore counts to disappear when
+ using hit counts. So don't clear them if we're counting hits. */
+ if (!show_breakpoint_hit_counts)
+ breakpoint_clear_ignore_counts ();
+}
+
+/* This table must match in order and size the signals in enum target_signal
+ in target.h. */
+static struct {
+ char *name;
+ char *string;
+ } signals [] =
+{
+ {"0", "Signal 0"},
+ {"SIGHUP", "Hangup"},
+ {"SIGINT", "Interrupt"},
+ {"SIGQUIT", "Quit"},
+ {"SIGILL", "Illegal instruction"},
+ {"SIGTRAP", "Trace/breakpoint trap"},
+ {"SIGABRT", "Aborted"},
+ {"SIGEMT", "Emulation trap"},
+ {"SIGFPE", "Arithmetic exception"},
+ {"SIGKILL", "Killed"},
+ {"SIGBUS", "Bus error"},
+ {"SIGSEGV", "Segmentation fault"},
+ {"SIGSYS", "Bad system call"},
+ {"SIGPIPE", "Broken pipe"},
+ {"SIGALRM", "Alarm clock"},
+ {"SIGTERM", "Terminated"},
+ {"SIGURG", "Urgent I/O condition"},
+ {"SIGSTOP", "Stopped (signal)"},
+ {"SIGTSTP", "Stopped (user)"},
+ {"SIGCONT", "Continued"},
+ {"SIGCHLD", "Child status changed"},
+ {"SIGTTIN", "Stopped (tty input)"},
+ {"SIGTTOU", "Stopped (tty output)"},
+ {"SIGIO", "I/O possible"},
+ {"SIGXCPU", "CPU time limit exceeded"},
+ {"SIGXFSZ", "File size limit exceeded"},
+ {"SIGVTALRM", "Virtual timer expired"},
+ {"SIGPROF", "Profiling timer expired"},
+ {"SIGWINCH", "Window size changed"},
+ {"SIGLOST", "Resource lost"},
+ {"SIGUSR1", "User defined signal 1"},
+ {"SIGUSR2", "User defined signal 2"},
+ {"SIGPWR", "Power fail/restart"},
+ {"SIGPOLL", "Pollable event occurred"},
+ {"SIGWIND", "SIGWIND"},
+ {"SIGPHONE", "SIGPHONE"},
+ {"SIGWAITING", "Process's LWPs are blocked"},
+ {"SIGLWP", "Signal LWP"},
+ {"SIGDANGER", "Swap space dangerously low"},
+ {"SIGGRANT", "Monitor mode granted"},
+ {"SIGRETRACT", "Need to relinquish monitor mode"},
+ {"SIGMSG", "Monitor mode data available"},
+ {"SIGSOUND", "Sound completed"},
+ {"SIGSAK", "Secure attention"},
+ {"SIGPRIO", "SIGPRIO"},
+ {"SIG33", "Real-time event 33"},
+ {"SIG34", "Real-time event 34"},
+ {"SIG35", "Real-time event 35"},
+ {"SIG36", "Real-time event 36"},
+ {"SIG37", "Real-time event 37"},
+ {"SIG38", "Real-time event 38"},
+ {"SIG39", "Real-time event 39"},
+ {"SIG40", "Real-time event 40"},
+ {"SIG41", "Real-time event 41"},
+ {"SIG42", "Real-time event 42"},
+ {"SIG43", "Real-time event 43"},
+ {"SIG44", "Real-time event 44"},
+ {"SIG45", "Real-time event 45"},
+ {"SIG46", "Real-time event 46"},
+ {"SIG47", "Real-time event 47"},
+ {"SIG48", "Real-time event 48"},
+ {"SIG49", "Real-time event 49"},
+ {"SIG50", "Real-time event 50"},
+ {"SIG51", "Real-time event 51"},
+ {"SIG52", "Real-time event 52"},
+ {"SIG53", "Real-time event 53"},
+ {"SIG54", "Real-time event 54"},
+ {"SIG55", "Real-time event 55"},
+ {"SIG56", "Real-time event 56"},
+ {"SIG57", "Real-time event 57"},
+ {"SIG58", "Real-time event 58"},
+ {"SIG59", "Real-time event 59"},
+ {"SIG60", "Real-time event 60"},
+ {"SIG61", "Real-time event 61"},
+ {"SIG62", "Real-time event 62"},
+ {"SIG63", "Real-time event 63"},
+
+#if defined(MACH) || defined(__MACH__)
+ /* Mach exceptions */
+ {"EXC_BAD_ACCESS", "Could not access memory"},
+ {"EXC_BAD_INSTRUCTION", "Illegal instruction/operand"},
+ {"EXC_ARITHMETIC", "Arithmetic exception"},
+ {"EXC_EMULATION", "Emulation instruction"},
+ {"EXC_SOFTWARE", "Software generated exception"},
+ {"EXC_BREAKPOINT", "Breakpoint"},
+#endif
+ {NULL, "Unknown signal"},
+ {NULL, "Internal error: printing TARGET_SIGNAL_DEFAULT"},
+
+ /* Last entry, used to check whether the table is the right size. */
+ {NULL, "TARGET_SIGNAL_MAGIC"}
+};
+
+/* Return the string for a signal. */
+char *
+target_signal_to_string (sig)
+ enum target_signal sig;
+{
+ return signals[sig].string;
+}
+
+/* Return the name for a signal. */
+char *
+target_signal_to_name (sig)
+ enum target_signal sig;
+{
+ if (sig == TARGET_SIGNAL_UNKNOWN)
+ /* I think the code which prints this will always print it along with
+ the string, so no need to be verbose. */
+ return "?";
+ return signals[sig].name;
+}
+
+/* Given a name, return its signal. */
+enum target_signal
+target_signal_from_name (name)
+ char *name;
+{
+ enum target_signal sig;
+
+ /* It's possible we also should allow "SIGCLD" as well as "SIGCHLD"
+ for TARGET_SIGNAL_SIGCHLD. SIGIOT, on the other hand, is more
+ questionable; seems like by now people should call it SIGABRT
+ instead. */
+
+ /* This ugly cast brought to you by the native VAX compiler. */
+ for (sig = TARGET_SIGNAL_HUP;
+ signals[sig].name != NULL;
+ sig = (enum target_signal)((int)sig + 1))
+ if (STREQ (name, signals[sig].name))
+ return sig;
+ return TARGET_SIGNAL_UNKNOWN;
+}
+
+/* The following functions are to help certain targets deal
+ with the signal/waitstatus stuff. They could just as well be in
+ a file called native-utils.c or unixwaitstatus-utils.c or whatever. */
+
+/* Convert host signal to our signals. */
+enum target_signal
+target_signal_from_host (hostsig)
+ int hostsig;
+{
+ /* A switch statement would make sense but would require special kludges
+ to deal with the cases where more than one signal has the same number. */
+
+ if (hostsig == 0) return TARGET_SIGNAL_0;
+
+#if defined (SIGHUP)
+ if (hostsig == SIGHUP) return TARGET_SIGNAL_HUP;
+#endif
+#if defined (SIGINT)
+ if (hostsig == SIGINT) return TARGET_SIGNAL_INT;
+#endif
+#if defined (SIGQUIT)
+ if (hostsig == SIGQUIT) return TARGET_SIGNAL_QUIT;
+#endif
+#if defined (SIGILL)
+ if (hostsig == SIGILL) return TARGET_SIGNAL_ILL;
+#endif
+#if defined (SIGTRAP)
+ if (hostsig == SIGTRAP) return TARGET_SIGNAL_TRAP;
+#endif
+#if defined (SIGABRT)
+ if (hostsig == SIGABRT) return TARGET_SIGNAL_ABRT;
+#endif
+#if defined (SIGEMT)
+ if (hostsig == SIGEMT) return TARGET_SIGNAL_EMT;
+#endif
+#if defined (SIGFPE)
+ if (hostsig == SIGFPE) return TARGET_SIGNAL_FPE;
+#endif
+#if defined (SIGKILL)
+ if (hostsig == SIGKILL) return TARGET_SIGNAL_KILL;
+#endif
+#if defined (SIGBUS)
+ if (hostsig == SIGBUS) return TARGET_SIGNAL_BUS;
+#endif
+#if defined (SIGSEGV)
+ if (hostsig == SIGSEGV) return TARGET_SIGNAL_SEGV;
+#endif
+#if defined (SIGSYS)
+ if (hostsig == SIGSYS) return TARGET_SIGNAL_SYS;
+#endif
+#if defined (SIGPIPE)
+ if (hostsig == SIGPIPE) return TARGET_SIGNAL_PIPE;
+#endif
+#if defined (SIGALRM)
+ if (hostsig == SIGALRM) return TARGET_SIGNAL_ALRM;
+#endif
+#if defined (SIGTERM)
+ if (hostsig == SIGTERM) return TARGET_SIGNAL_TERM;
+#endif
+#if defined (SIGUSR1)
+ if (hostsig == SIGUSR1) return TARGET_SIGNAL_USR1;
+#endif
+#if defined (SIGUSR2)
+ if (hostsig == SIGUSR2) return TARGET_SIGNAL_USR2;
+#endif
+#if defined (SIGCLD)
+ if (hostsig == SIGCLD) return TARGET_SIGNAL_CHLD;
+#endif
+#if defined (SIGCHLD)
+ if (hostsig == SIGCHLD) return TARGET_SIGNAL_CHLD;
+#endif
+#if defined (SIGPWR)
+ if (hostsig == SIGPWR) return TARGET_SIGNAL_PWR;
+#endif
+#if defined (SIGWINCH)
+ if (hostsig == SIGWINCH) return TARGET_SIGNAL_WINCH;
+#endif
+#if defined (SIGURG)
+ if (hostsig == SIGURG) return TARGET_SIGNAL_URG;
+#endif
+#if defined (SIGIO)
+ if (hostsig == SIGIO) return TARGET_SIGNAL_IO;
+#endif
+#if defined (SIGPOLL)
+ if (hostsig == SIGPOLL) return TARGET_SIGNAL_POLL;
+#endif
+#if defined (SIGSTOP)
+ if (hostsig == SIGSTOP) return TARGET_SIGNAL_STOP;
+#endif
+#if defined (SIGTSTP)
+ if (hostsig == SIGTSTP) return TARGET_SIGNAL_TSTP;
+#endif
+#if defined (SIGCONT)
+ if (hostsig == SIGCONT) return TARGET_SIGNAL_CONT;
+#endif
+#if defined (SIGTTIN)
+ if (hostsig == SIGTTIN) return TARGET_SIGNAL_TTIN;
+#endif
+#if defined (SIGTTOU)
+ if (hostsig == SIGTTOU) return TARGET_SIGNAL_TTOU;
+#endif
+#if defined (SIGVTALRM)
+ if (hostsig == SIGVTALRM) return TARGET_SIGNAL_VTALRM;
+#endif
+#if defined (SIGPROF)
+ if (hostsig == SIGPROF) return TARGET_SIGNAL_PROF;
+#endif
+#if defined (SIGXCPU)
+ if (hostsig == SIGXCPU) return TARGET_SIGNAL_XCPU;
+#endif
+#if defined (SIGXFSZ)
+ if (hostsig == SIGXFSZ) return TARGET_SIGNAL_XFSZ;
+#endif
+#if defined (SIGWIND)
+ if (hostsig == SIGWIND) return TARGET_SIGNAL_WIND;
+#endif
+#if defined (SIGPHONE)
+ if (hostsig == SIGPHONE) return TARGET_SIGNAL_PHONE;
+#endif
+#if defined (SIGLOST)
+ if (hostsig == SIGLOST) return TARGET_SIGNAL_LOST;
+#endif
+#if defined (SIGWAITING)
+ if (hostsig == SIGWAITING) return TARGET_SIGNAL_WAITING;
+#endif
+#if defined (SIGLWP)
+ if (hostsig == SIGLWP) return TARGET_SIGNAL_LWP;
+#endif
+#if defined (SIGDANGER)
+ if (hostsig == SIGDANGER) return TARGET_SIGNAL_DANGER;
+#endif
+#if defined (SIGGRANT)
+ if (hostsig == SIGGRANT) return TARGET_SIGNAL_GRANT;
+#endif
+#if defined (SIGRETRACT)
+ if (hostsig == SIGRETRACT) return TARGET_SIGNAL_RETRACT;
+#endif
+#if defined (SIGMSG)
+ if (hostsig == SIGMSG) return TARGET_SIGNAL_MSG;
+#endif
+#if defined (SIGSOUND)
+ if (hostsig == SIGSOUND) return TARGET_SIGNAL_SOUND;
+#endif
+#if defined (SIGSAK)
+ if (hostsig == SIGSAK) return TARGET_SIGNAL_SAK;
+#endif
+#if defined (SIGPRIO)
+ if (hostsig == SIGPRIO) return TARGET_SIGNAL_PRIO;
+#endif
+
+ /* Mach exceptions. Assumes that the values for EXC_ are positive! */
+#if defined (EXC_BAD_ACCESS) && defined (_NSIG)
+ if (hostsig == _NSIG + EXC_BAD_ACCESS) return TARGET_EXC_BAD_ACCESS;
+#endif
+#if defined (EXC_BAD_INSTRUCTION) && defined (_NSIG)
+ if (hostsig == _NSIG + EXC_BAD_INSTRUCTION) return TARGET_EXC_BAD_INSTRUCTION;
+#endif
+#if defined (EXC_ARITHMETIC) && defined (_NSIG)
+ if (hostsig == _NSIG + EXC_ARITHMETIC) return TARGET_EXC_ARITHMETIC;
+#endif
+#if defined (EXC_EMULATION) && defined (_NSIG)
+ if (hostsig == _NSIG + EXC_EMULATION) return TARGET_EXC_EMULATION;
+#endif
+#if defined (EXC_SOFTWARE) && defined (_NSIG)
+ if (hostsig == _NSIG + EXC_SOFTWARE) return TARGET_EXC_SOFTWARE;
+#endif
+#if defined (EXC_BREAKPOINT) && defined (_NSIG)
+ if (hostsig == _NSIG + EXC_BREAKPOINT) return TARGET_EXC_BREAKPOINT;
+#endif
+
+#if defined (REALTIME_LO)
+ if (hostsig >= REALTIME_LO && hostsig < REALTIME_HI)
+ return (enum target_signal)
+ (hostsig - 33 + (int) TARGET_SIGNAL_REALTIME_33);
+#endif
+ return TARGET_SIGNAL_UNKNOWN;
+}
+
+int
+target_signal_to_host (oursig)
+ enum target_signal oursig;
+{
+ switch (oursig)
+ {
+ case TARGET_SIGNAL_0: return 0;
+
+#if defined (SIGHUP)
+ case TARGET_SIGNAL_HUP: return SIGHUP;
+#endif
+#if defined (SIGINT)
+ case TARGET_SIGNAL_INT: return SIGINT;
+#endif
+#if defined (SIGQUIT)
+ case TARGET_SIGNAL_QUIT: return SIGQUIT;
+#endif
+#if defined (SIGILL)
+ case TARGET_SIGNAL_ILL: return SIGILL;
+#endif
+#if defined (SIGTRAP)
+ case TARGET_SIGNAL_TRAP: return SIGTRAP;
+#endif
+#if defined (SIGABRT)
+ case TARGET_SIGNAL_ABRT: return SIGABRT;
+#endif
+#if defined (SIGEMT)
+ case TARGET_SIGNAL_EMT: return SIGEMT;
+#endif
+#if defined (SIGFPE)
+ case TARGET_SIGNAL_FPE: return SIGFPE;
+#endif
+#if defined (SIGKILL)
+ case TARGET_SIGNAL_KILL: return SIGKILL;
+#endif
+#if defined (SIGBUS)
+ case TARGET_SIGNAL_BUS: return SIGBUS;
+#endif
+#if defined (SIGSEGV)
+ case TARGET_SIGNAL_SEGV: return SIGSEGV;
+#endif
+#if defined (SIGSYS)
+ case TARGET_SIGNAL_SYS: return SIGSYS;
+#endif
+#if defined (SIGPIPE)
+ case TARGET_SIGNAL_PIPE: return SIGPIPE;
+#endif
+#if defined (SIGALRM)
+ case TARGET_SIGNAL_ALRM: return SIGALRM;
+#endif
+#if defined (SIGTERM)
+ case TARGET_SIGNAL_TERM: return SIGTERM;
+#endif
+#if defined (SIGUSR1)
+ case TARGET_SIGNAL_USR1: return SIGUSR1;
+#endif
+#if defined (SIGUSR2)
+ case TARGET_SIGNAL_USR2: return SIGUSR2;
+#endif
+#if defined (SIGCHLD) || defined (SIGCLD)
+ case TARGET_SIGNAL_CHLD:
+#if defined (SIGCHLD)
+ return SIGCHLD;
+#else
+ return SIGCLD;
+#endif
+#endif /* SIGCLD or SIGCHLD */
+#if defined (SIGPWR)
+ case TARGET_SIGNAL_PWR: return SIGPWR;
+#endif
+#if defined (SIGWINCH)
+ case TARGET_SIGNAL_WINCH: return SIGWINCH;
+#endif
+#if defined (SIGURG)
+ case TARGET_SIGNAL_URG: return SIGURG;
+#endif
+#if defined (SIGIO)
+ case TARGET_SIGNAL_IO: return SIGIO;
+#endif
+#if defined (SIGPOLL)
+ case TARGET_SIGNAL_POLL: return SIGPOLL;
+#endif
+#if defined (SIGSTOP)
+ case TARGET_SIGNAL_STOP: return SIGSTOP;
+#endif
+#if defined (SIGTSTP)
+ case TARGET_SIGNAL_TSTP: return SIGTSTP;
+#endif
+#if defined (SIGCONT)
+ case TARGET_SIGNAL_CONT: return SIGCONT;
+#endif
+#if defined (SIGTTIN)
+ case TARGET_SIGNAL_TTIN: return SIGTTIN;
+#endif
+#if defined (SIGTTOU)
+ case TARGET_SIGNAL_TTOU: return SIGTTOU;
+#endif
+#if defined (SIGVTALRM)
+ case TARGET_SIGNAL_VTALRM: return SIGVTALRM;
+#endif
+#if defined (SIGPROF)
+ case TARGET_SIGNAL_PROF: return SIGPROF;
+#endif
+#if defined (SIGXCPU)
+ case TARGET_SIGNAL_XCPU: return SIGXCPU;
+#endif
+#if defined (SIGXFSZ)
+ case TARGET_SIGNAL_XFSZ: return SIGXFSZ;
+#endif
+#if defined (SIGWIND)
+ case TARGET_SIGNAL_WIND: return SIGWIND;
+#endif
+#if defined (SIGPHONE)
+ case TARGET_SIGNAL_PHONE: return SIGPHONE;
+#endif
+#if defined (SIGLOST)
+ case TARGET_SIGNAL_LOST: return SIGLOST;
+#endif
+#if defined (SIGWAITING)
+ case TARGET_SIGNAL_WAITING: return SIGWAITING;
+#endif
+#if defined (SIGLWP)
+ case TARGET_SIGNAL_LWP: return SIGLWP;
+#endif
+#if defined (SIGDANGER)
+ case TARGET_SIGNAL_DANGER: return SIGDANGER;
+#endif
+#if defined (SIGGRANT)
+ case TARGET_SIGNAL_GRANT: return SIGGRANT;
+#endif
+#if defined (SIGRETRACT)
+ case TARGET_SIGNAL_RETRACT: return SIGRETRACT;
+#endif
+#if defined (SIGMSG)
+ case TARGET_SIGNAL_MSG: return SIGMSG;
+#endif
+#if defined (SIGSOUND)
+ case TARGET_SIGNAL_SOUND: return SIGSOUND;
+#endif
+#if defined (SIGSAK)
+ case TARGET_SIGNAL_SAK: return SIGSAK;
+#endif
+#if defined (SIGPRIO)
+ case TARGET_SIGNAL_PRIO: return SIGPRIO;
+#endif
+
+ /* Mach exceptions. Assumes that the values for EXC_ are positive! */
+#if defined (EXC_BAD_ACCESS) && defined (_NSIG)
+ case TARGET_EXC_BAD_ACCESS: return _NSIG + EXC_BAD_ACCESS;
+#endif
+#if defined (EXC_BAD_INSTRUCTION) && defined (_NSIG)
+ case TARGET_EXC_BAD_INSTRUCTION: return _NSIG + EXC_BAD_INSTRUCTION;
+#endif
+#if defined (EXC_ARITHMETIC) && defined (_NSIG)
+ case TARGET_EXC_ARITHMETIC: return _NSIG + EXC_ARITHMETIC;
+#endif
+#if defined (EXC_EMULATION) && defined (_NSIG)
+ case TARGET_EXC_EMULATION: return _NSIG + EXC_EMULATION;
+#endif
+#if defined (EXC_SOFTWARE) && defined (_NSIG)
+ case TARGET_EXC_SOFTWARE: return _NSIG + EXC_SOFTWARE;
+#endif
+#if defined (EXC_BREAKPOINT) && defined (_NSIG)
+ case TARGET_EXC_BREAKPOINT: return _NSIG + EXC_BREAKPOINT;
+#endif
+
+ default:
+#if defined (REALTIME_LO)
+ if (oursig >= TARGET_SIGNAL_REALTIME_33
+ && oursig <= TARGET_SIGNAL_REALTIME_63)
+ {
+ int retsig =
+ (int)oursig - (int)TARGET_SIGNAL_REALTIME_33 + REALTIME_LO;
+ if (retsig < REALTIME_HI)
+ return retsig;
+ }
+#endif
+ /* The user might be trying to do "signal SIGSAK" where this system
+ doesn't have SIGSAK. */
+ warning ("Signal %s does not exist on this system.\n",
+ target_signal_to_name (oursig));
+ return 0;
+ }
+}
+
+/* Helper function for child_wait and the Lynx derivatives of child_wait.
+ HOSTSTATUS is the waitstatus from wait() or the equivalent; store our
+ translation of that in OURSTATUS. */
+void
+store_waitstatus (ourstatus, hoststatus)
+ struct target_waitstatus *ourstatus;
+ int hoststatus;
+{
+#ifdef CHILD_SPECIAL_WAITSTATUS
+ /* CHILD_SPECIAL_WAITSTATUS should return nonzero and set *OURSTATUS
+ if it wants to deal with hoststatus. */
+ if (CHILD_SPECIAL_WAITSTATUS (ourstatus, hoststatus))
+ return;
+#endif
+
+ if (WIFEXITED (hoststatus))
+ {
+ ourstatus->kind = TARGET_WAITKIND_EXITED;
+ ourstatus->value.integer = WEXITSTATUS (hoststatus);
+ }
+ else if (!WIFSTOPPED (hoststatus))
+ {
+ ourstatus->kind = TARGET_WAITKIND_SIGNALLED;
+ ourstatus->value.sig = target_signal_from_host (WTERMSIG (hoststatus));
+ }
+ else
+ {
+ ourstatus->kind = TARGET_WAITKIND_STOPPED;
+ ourstatus->value.sig = target_signal_from_host (WSTOPSIG (hoststatus));
+ }
+}
+
+/* In some circumstances we allow a command to specify a numeric
+ signal. The idea is to keep these circumstances limited so that
+ users (and scripts) develop portable habits. For comparison,
+ POSIX.2 `kill' requires that 1,2,3,6,9,14, and 15 work (and using a
+ numeric signal at all is obscelescent. We are slightly more
+ lenient and allow 1-15 which should match host signal numbers on
+ most systems. Use of symbolic signal names is strongly encouraged. */
+
+enum target_signal
+target_signal_from_command (num)
+ int num;
+{
+ if (num >= 1 && num <= 15)
+ return (enum target_signal)num;
+ error ("Only signals 1-15 are valid as numeric signals.\n\
+Use \"info signals\" for a list of symbolic signals.");
+}
+
+/* Returns zero to leave the inferior alone, one to interrupt it. */
+int (*target_activity_function) PARAMS ((void));
+int target_activity_fd;
+
+/* 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];
+
+ if (STREQ (current_target.to_shortname, "remote"))
+ sprintf (buf, "thread %d\0", pid);
+ else
+ sprintf (buf, "process %d\0", pid);
+
+ return buf;
+}
+
+/* Some targets (such as ttrace-based HPUX) don't allow us to request
+ notification of inferior events such as fork and vork immediately
+ after the inferior is created. (This because of how gdb gets an
+ inferior created via invoking a shell to do it. In such a scenario,
+ if the shell init file has commands in it, the shell will fork and
+ exec for each of those commands, and we will see each such fork
+ event. Very bad.)
+
+ This function is used by all targets that allow us to request
+ notification of forks, etc at inferior creation time; e.g., in
+ target_acknowledge_forked_child.
+ */
+void
+normal_target_post_startup_inferior (pid)
+ int pid;
+{
+ /* This space intentionally left blank. */
+}
+
+/* Set up the handful of non-empty slots needed by the dummy target
+ vector. */
+
+static void
+init_dummy_target ()
+{
+ dummy_target.to_shortname = "None";
+ dummy_target.to_longname = "None";
+ dummy_target.to_doc = "";
+ dummy_target.to_attach = find_default_attach;
+ dummy_target.to_require_attach = find_default_require_attach;
+ dummy_target.to_require_detach = find_default_require_detach;
+ dummy_target.to_create_inferior = find_default_create_inferior;
+ dummy_target.to_clone_and_follow_inferior = find_default_clone_and_follow_inferior;
+ dummy_target.to_stratum = dummy_stratum;
+ dummy_target.to_magic = OPS_MAGIC;
+}
+
+
+#ifdef MAINTENANCE_CMDS
+static struct target_ops debug_target;
+
+static void
+debug_to_open (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ debug_target.to_open (args, from_tty);
+
+ fprintf_unfiltered (gdb_stderr, "target_open (%s, %d)\n", args, from_tty);
+}
+
+static void
+debug_to_close (quitting)
+ int quitting;
+{
+ debug_target.to_close (quitting);
+
+ fprintf_unfiltered (gdb_stderr, "target_close (%d)\n", quitting);
+}
+
+static void
+debug_to_attach (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ debug_target.to_attach (args, from_tty);
+
+ fprintf_unfiltered (gdb_stderr, "target_attach (%s, %d)\n", args, from_tty);
+}
+
+
+static void
+debug_to_post_attach (pid)
+ int pid;
+{
+ debug_target.to_post_attach (pid);
+
+ fprintf_unfiltered (gdb_stderr, "target_post_attach (%d)\n", pid);
+}
+
+static void
+debug_to_require_attach (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ debug_target.to_require_attach (args, from_tty);
+
+ fprintf_unfiltered (gdb_stderr,
+ "target_require_attach (%s, %d)\n", args, from_tty);
+}
+
+static void
+debug_to_detach (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ debug_target.to_detach (args, from_tty);
+
+ fprintf_unfiltered (gdb_stderr, "target_detach (%s, %d)\n", args, from_tty);
+}
+
+static void
+debug_to_require_detach (pid, args, from_tty)
+ int pid;
+ char * args;
+ int from_tty;
+{
+ debug_target.to_require_detach (pid, args, from_tty);
+
+ fprintf_unfiltered (gdb_stderr,
+ "target_require_detach (%d, %s, %d)\n", pid, args, from_tty);
+}
+
+static void
+debug_to_resume (pid, step, siggnal)
+ int pid;
+ int step;
+ enum target_signal siggnal;
+{
+ debug_target.to_resume (pid, step, siggnal);
+
+ fprintf_unfiltered (gdb_stderr, "target_resume (%d, %s, %s)\n", pid,
+ step ? "step" : "continue",
+ target_signal_to_name (siggnal));
+}
+
+static int
+debug_to_wait (pid, status)
+ int pid;
+ struct target_waitstatus *status;
+{
+ int retval;
+
+ retval = debug_target.to_wait (pid, status);
+
+ fprintf_unfiltered (gdb_stderr,
+ "target_wait (%d, status) = %d, ", pid, retval);
+ fprintf_unfiltered (gdb_stderr, "status->kind = ");
+ switch (status->kind)
+ {
+ case TARGET_WAITKIND_EXITED:
+ fprintf_unfiltered (gdb_stderr, "exited, status = %d\n",
+ status->value.integer);
+ break;
+ case TARGET_WAITKIND_STOPPED:
+ fprintf_unfiltered (gdb_stderr, "stopped, signal = %s\n",
+ target_signal_to_name (status->value.sig));
+ break;
+ case TARGET_WAITKIND_SIGNALLED:
+ fprintf_unfiltered (gdb_stderr, "signalled, signal = %s\n",
+ target_signal_to_name (status->value.sig));
+ break;
+ case TARGET_WAITKIND_LOADED:
+ fprintf_unfiltered (gdb_stderr, "loaded\n");
+ break;
+ case TARGET_WAITKIND_FORKED:
+ fprintf_unfiltered (gdb_stderr, "forked\n");
+ break;
+ case TARGET_WAITKIND_VFORKED:
+ fprintf_unfiltered (gdb_stderr, "vforked\n");
+ break;
+ case TARGET_WAITKIND_EXECD:
+ fprintf_unfiltered (gdb_stderr, "execd\n");
+ break;
+ case TARGET_WAITKIND_SPURIOUS:
+ fprintf_unfiltered (gdb_stderr, "spurious\n");
+ break;
+ default:
+ fprintf_unfiltered (gdb_stderr, "unknown???\n");
+ break;
+ }
+
+ return retval;
+}
+
+static void
+debug_to_post_wait (pid, status)
+ int pid;
+ int status;
+{
+ debug_target.to_post_wait (pid, status);
+
+ fprintf_unfiltered (gdb_stderr, "target_post_wait (%d, %d)\n",
+ pid, status);
+}
+
+static void
+debug_to_fetch_registers (regno)
+ int regno;
+{
+ debug_target.to_fetch_registers (regno);
+
+ fprintf_unfiltered (gdb_stderr, "target_fetch_registers (%s)",
+ regno != -1 ? REGISTER_NAME (regno) : "-1");
+ if (regno != -1)
+ fprintf_unfiltered (gdb_stderr, " = 0x%x %d",
+ (unsigned long) read_register (regno),
+ read_register (regno));
+ fprintf_unfiltered (gdb_stderr, "\n");
+}
+
+static void
+debug_to_store_registers (regno)
+ int regno;
+{
+ debug_target.to_store_registers (regno);
+
+ if (regno >= 0 && regno < NUM_REGS)
+ fprintf_unfiltered (gdb_stderr, "target_store_registers (%s) = 0x%x %d\n",
+ REGISTER_NAME (regno),
+ (unsigned long) read_register (regno),
+ (unsigned long) read_register (regno));
+ else
+ fprintf_unfiltered (gdb_stderr, "target_store_registers (%d)\n", regno);
+}
+
+static void
+debug_to_prepare_to_store ()
+{
+ debug_target.to_prepare_to_store ();
+
+ fprintf_unfiltered (gdb_stderr, "target_prepare_to_store ()\n");
+}
+
+static int
+debug_to_xfer_memory (memaddr, myaddr, len, write, target)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+ int write;
+ struct target_ops *target;
+{
+ int retval;
+
+ retval = debug_target.to_xfer_memory (memaddr, myaddr, len, write, target);
+
+ fprintf_unfiltered (gdb_stderr,
+ "target_xfer_memory (0x%x, xxx, %d, %s, xxx) = %d",
+ (unsigned int) memaddr, /* possable truncate long long */
+ len, write ? "write" : "read", retval);
+
+
+
+ if (retval > 0)
+ {
+ int i;
+
+ fputs_unfiltered (", bytes =", gdb_stderr);
+ for (i = 0; i < retval; i++)
+ {
+ if ((((long) &(myaddr[i])) & 0xf) == 0)
+ fprintf_unfiltered (gdb_stderr, "\n");
+ fprintf_unfiltered (gdb_stderr, " %02x", myaddr[i] & 0xff);
+ }
+ }
+
+ fputc_unfiltered ('\n', gdb_stderr);
+
+ return retval;
+}
+
+static void
+debug_to_files_info (target)
+ struct target_ops *target;
+{
+ debug_target.to_files_info (target);
+
+ fprintf_unfiltered (gdb_stderr, "target_files_info (xxx)\n");
+}
+
+static int
+debug_to_insert_breakpoint (addr, save)
+ CORE_ADDR addr;
+ char *save;
+{
+ int retval;
+
+ retval = debug_target.to_insert_breakpoint (addr, save);
+
+ fprintf_unfiltered (gdb_stderr,
+ "target_insert_breakpoint (0x%x, xxx) = %d\n",
+ (unsigned long) addr, retval);
+ return retval;
+}
+
+static int
+debug_to_remove_breakpoint (addr, save)
+ CORE_ADDR addr;
+ char *save;
+{
+ int retval;
+
+ retval = debug_target.to_remove_breakpoint (addr, save);
+
+ fprintf_unfiltered (gdb_stderr,
+ "target_remove_breakpoint (0x%x, xxx) = %d\n",
+ (unsigned long)addr, retval);
+ return retval;
+}
+
+static void
+debug_to_terminal_init ()
+{
+ debug_target.to_terminal_init ();
+
+ fprintf_unfiltered (gdb_stderr, "target_terminal_init ()\n");
+}
+
+static void
+debug_to_terminal_inferior ()
+{
+ debug_target.to_terminal_inferior ();
+
+ fprintf_unfiltered (gdb_stderr, "target_terminal_inferior ()\n");
+}
+
+static void
+debug_to_terminal_ours_for_output ()
+{
+ debug_target.to_terminal_ours_for_output ();
+
+ fprintf_unfiltered (gdb_stderr, "target_terminal_ours_for_output ()\n");
+}
+
+static void
+debug_to_terminal_ours ()
+{
+ debug_target.to_terminal_ours ();
+
+ fprintf_unfiltered (gdb_stderr, "target_terminal_ours ()\n");
+}
+
+static void
+debug_to_terminal_info (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ debug_target.to_terminal_info (arg, from_tty);
+
+ fprintf_unfiltered (gdb_stderr, "target_terminal_info (%s, %d)\n", arg,
+ from_tty);
+}
+
+static void
+debug_to_kill ()
+{
+ debug_target.to_kill ();
+
+ fprintf_unfiltered (gdb_stderr, "target_kill ()\n");
+}
+
+static void
+debug_to_load (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ debug_target.to_load (args, from_tty);
+
+ fprintf_unfiltered (gdb_stderr, "target_load (%s, %d)\n", args, from_tty);
+}
+
+static int
+debug_to_lookup_symbol (name, addrp)
+ char *name;
+ CORE_ADDR *addrp;
+{
+ int retval;
+
+ retval = debug_target.to_lookup_symbol (name, addrp);
+
+ fprintf_unfiltered (gdb_stderr, "target_lookup_symbol (%s, xxx)\n", name);
+
+ return retval;
+}
+
+static void
+debug_to_create_inferior (exec_file, args, env)
+ char *exec_file;
+ char *args;
+ char **env;
+{
+ debug_target.to_create_inferior (exec_file, args, env);
+
+ fprintf_unfiltered (gdb_stderr, "target_create_inferior (%s, %s, xxx)\n",
+ exec_file, args);
+}
+
+static void
+debug_to_post_startup_inferior (pid)
+ int pid;
+{
+ debug_target.to_post_startup_inferior (pid);
+
+ fprintf_unfiltered (gdb_stderr, "target_post_startup_inferior (%d)\n",
+ pid);
+}
+
+static void
+debug_to_acknowledge_created_inferior (pid)
+ int pid;
+{
+ debug_target.to_acknowledge_created_inferior (pid);
+
+ fprintf_unfiltered (gdb_stderr, "target_acknowledge_created_inferior (%d)\n",
+ pid);
+}
+
+static void
+debug_to_clone_and_follow_inferior (child_pid, followed_child)
+ int child_pid;
+ int *followed_child;
+{
+ debug_target.to_clone_and_follow_inferior (child_pid, followed_child);
+
+ fprintf_unfiltered (gdb_stderr,
+ "target_clone_and_follow_inferior (%d, %d)\n",
+ child_pid, *followed_child);
+}
+
+static void
+debug_to_post_follow_inferior_by_clone ()
+{
+ debug_target.to_post_follow_inferior_by_clone ();
+
+ fprintf_unfiltered (gdb_stderr, "target_post_follow_inferior_by_clone ()\n");
+}
+
+static int
+debug_to_insert_fork_catchpoint (pid)
+ int pid;
+{
+ int retval;
+
+ retval = debug_target.to_insert_fork_catchpoint (pid);
+
+ fprintf_unfiltered (gdb_stderr, "target_insert_fork_catchpoint (%d) = %d\n",
+ pid, retval);
+
+ return retval;
+}
+
+static int
+debug_to_remove_fork_catchpoint (pid)
+ int pid;
+{
+ int retval;
+
+ retval = debug_target.to_remove_fork_catchpoint (pid);
+
+ fprintf_unfiltered (gdb_stderr, "target_remove_fork_catchpoint (%d) = %d\n",
+ pid, retval);
+
+ return retval;
+}
+
+static int
+debug_to_insert_vfork_catchpoint (pid)
+ int pid;
+{
+ int retval;
+
+ retval = debug_target.to_insert_vfork_catchpoint (pid);
+
+ fprintf_unfiltered (gdb_stderr, "target_insert_vfork_catchpoint (%d)= %d\n",
+ pid, retval);
+
+ return retval;
+}
+
+static int
+debug_to_remove_vfork_catchpoint (pid)
+ int pid;
+{
+ int retval;
+
+ retval = debug_target.to_remove_vfork_catchpoint (pid);
+
+ fprintf_unfiltered (gdb_stderr, "target_remove_vfork_catchpoint (%d) = %d\n",
+ pid, retval);
+
+ return retval;
+}
+
+static int
+debug_to_has_forked (pid, child_pid)
+ int pid;
+ int * child_pid;
+{
+ int has_forked;
+
+ has_forked = debug_target.to_has_forked (pid, child_pid);
+
+ fprintf_unfiltered (gdb_stderr, "target_has_forked (%d, %d) = %d\n",
+ pid, *child_pid, has_forked);
+
+ return has_forked;
+}
+
+static int
+debug_to_has_vforked (pid, child_pid)
+ int pid;
+ int * child_pid;
+{
+ int has_vforked;
+
+ has_vforked = debug_target.to_has_vforked (pid, child_pid);
+
+ fprintf_unfiltered (gdb_stderr, "target_has_vforked (%d, %d) = %d\n",
+ pid, *child_pid, has_vforked);
+
+ return has_vforked;
+}
+
+static int
+debug_to_can_follow_vfork_prior_to_exec ()
+{
+ int can_immediately_follow_vfork;
+
+ can_immediately_follow_vfork = debug_target.to_can_follow_vfork_prior_to_exec ();
+
+ fprintf_unfiltered (gdb_stderr, "target_can_follow_vfork_prior_to_exec () = %d\n",
+ can_immediately_follow_vfork);
+
+ return can_immediately_follow_vfork;
+}
+
+static void
+debug_to_post_follow_vfork (parent_pid, followed_parent, child_pid, followed_child)
+ int parent_pid;
+ int followed_parent;
+ int child_pid;
+ int followed_child;
+{
+ debug_target.to_post_follow_vfork (parent_pid, followed_parent, child_pid, followed_child);
+
+ fprintf_unfiltered (gdb_stderr,
+ "target_post_follow_vfork (%d, %d, %d, %d)\n",
+ parent_pid, followed_parent, child_pid, followed_child);
+}
+
+static int
+debug_to_insert_exec_catchpoint (pid)
+ int pid;
+{
+ int retval;
+
+ retval = debug_target.to_insert_exec_catchpoint (pid);
+
+ fprintf_unfiltered (gdb_stderr, "target_insert_exec_catchpoint (%d) = %d\n",
+ pid, retval);
+
+ return retval;
+}
+
+static int
+debug_to_remove_exec_catchpoint (pid)
+ int pid;
+{
+ int retval;
+
+ retval = debug_target.to_remove_exec_catchpoint (pid);
+
+ fprintf_unfiltered (gdb_stderr, "target_remove_exec_catchpoint (%d) = %d\n",
+ pid, retval);
+
+ return retval;
+}
+
+static int
+debug_to_has_execd (pid, execd_pathname)
+ int pid;
+ char ** execd_pathname;
+{
+ int has_execd;
+
+ has_execd = debug_target.to_has_execd (pid, execd_pathname);
+
+ fprintf_unfiltered (gdb_stderr, "target_has_execd (%d, %s) = %d\n",
+ pid, *execd_pathname, has_execd);
+
+ return has_execd;
+}
+
+static int
+debug_to_reported_exec_events_per_exec_call ()
+{
+ int reported_exec_events;
+
+ reported_exec_events = debug_target.to_reported_exec_events_per_exec_call ();
+
+ fprintf_unfiltered (gdb_stderr,
+ "target_reported_exec_events_per_exec_call () = %d\n",
+ reported_exec_events);
+
+ return reported_exec_events;
+}
+
+static int
+debug_to_has_syscall_event (pid, kind, syscall_id)
+ int pid;
+ enum target_waitkind * kind;
+ int * syscall_id;
+{
+ int has_syscall_event;
+ char * kind_spelling = "??";
+
+ has_syscall_event = debug_target.to_has_syscall_event (pid, kind, syscall_id);
+ if (has_syscall_event)
+ {
+ switch (*kind)
+ {
+ case TARGET_WAITKIND_SYSCALL_ENTRY:
+ kind_spelling = "SYSCALL_ENTRY";
+ break;
+ case TARGET_WAITKIND_SYSCALL_RETURN:
+ kind_spelling = "SYSCALL_RETURN";
+ break;
+ default:
+ break;
+ }
+ }
+
+ fprintf_unfiltered (gdb_stderr,
+ "target_has_syscall_event (%d, %s, %d) = %d\n",
+ pid, kind_spelling, *syscall_id, has_syscall_event);
+
+ return has_syscall_event;
+}
+
+static int
+debug_to_has_exited (pid, wait_status, exit_status)
+ int pid;
+ int wait_status;
+ int * exit_status;
+{
+ int has_exited;
+
+ has_exited = debug_target.to_has_exited (pid, wait_status, exit_status);
+
+ fprintf_unfiltered (gdb_stderr, "target_has_exited (%d, %d, %d) = %d\n",
+ pid, wait_status, *exit_status, has_exited);
+
+ return has_exited;
+}
+
+static void
+debug_to_mourn_inferior ()
+{
+ debug_target.to_mourn_inferior ();
+
+ fprintf_unfiltered (gdb_stderr, "target_mourn_inferior ()\n");
+}
+
+static int
+debug_to_can_run ()
+{
+ int retval;
+
+ retval = debug_target.to_can_run ();
+
+ fprintf_unfiltered (gdb_stderr, "target_can_run () = %d\n", retval);
+
+ return retval;
+}
+
+static void
+debug_to_notice_signals (pid)
+ int pid;
+{
+ debug_target.to_notice_signals (pid);
+
+ fprintf_unfiltered (gdb_stderr, "target_notice_signals (%d)\n", pid);
+}
+
+static int
+debug_to_thread_alive (pid)
+ int pid;
+{
+ int retval;
+
+ retval = debug_target.to_thread_alive (pid);
+
+ fprintf_unfiltered (gdb_stderr, "target_thread_alive (%d) = %d\n",
+ pid, retval);
+
+ return retval;
+}
+
+static void
+debug_to_stop ()
+{
+ debug_target.to_stop ();
+
+ fprintf_unfiltered (gdb_stderr, "target_stop ()\n");
+}
+
+static int
+debug_to_query (type, req, resp, siz)
+ int type;
+ char *req;
+ char *resp;
+ int *siz;
+{
+ int retval;
+
+ retval = debug_target.to_query (type, req, resp, siz);
+
+ fprintf_unfiltered (gdb_stderr, "target_query (%c, %s, %s, %d) = %d\n", type, req, resp, *siz, retval);
+
+ return retval;
+}
+
+static struct symtab_and_line *
+debug_to_enable_exception_callback (kind, enable)
+ enum exception_event_kind kind;
+ int enable;
+{
+ debug_target.to_enable_exception_callback (kind, enable);
+
+ fprintf_unfiltered (gdb_stderr,
+ "target get_exception_callback_sal (%d, %d)\n",
+ kind, enable);
+}
+
+static struct exception_event_record *
+debug_to_get_current_exception_event ()
+{
+ debug_target.to_get_current_exception_event();
+
+ fprintf_unfiltered (gdb_stderr, "target get_current_exception_event ()\n");
+}
+
+static char *
+debug_to_pid_to_exec_file (pid)
+ int pid;
+{
+ char * exec_file;
+
+ exec_file = debug_target.to_pid_to_exec_file (pid);
+
+ fprintf_unfiltered (gdb_stderr, "target_pid_to_exec_file (%d) = %s\n",
+ pid, exec_file);
+
+ return exec_file;
+}
+
+static char *
+debug_to_core_file_to_sym_file (core)
+ char * core;
+{
+ char * sym_file;
+
+ sym_file = debug_target.to_core_file_to_sym_file (core);
+
+ fprintf_unfiltered (gdb_stderr, "target_core_file_to_sym_file (%s) = %s\n",
+ core, sym_file);
+
+ return sym_file;
+}
+
+static void
+setup_target_debug ()
+{
+ memcpy (&debug_target, &current_target, sizeof debug_target);
+
+ current_target.to_open = debug_to_open;
+ current_target.to_close = debug_to_close;
+ current_target.to_attach = debug_to_attach;
+ current_target.to_post_attach = debug_to_post_attach;
+ current_target.to_require_attach = debug_to_require_attach;
+ current_target.to_detach = debug_to_detach;
+ current_target.to_require_detach = debug_to_require_detach;
+ current_target.to_resume = debug_to_resume;
+ current_target.to_wait = debug_to_wait;
+ current_target.to_post_wait = debug_to_post_wait;
+ current_target.to_fetch_registers = debug_to_fetch_registers;
+ current_target.to_store_registers = debug_to_store_registers;
+ current_target.to_prepare_to_store = debug_to_prepare_to_store;
+ current_target.to_xfer_memory = debug_to_xfer_memory;
+ current_target.to_files_info = debug_to_files_info;
+ current_target.to_insert_breakpoint = debug_to_insert_breakpoint;
+ current_target.to_remove_breakpoint = debug_to_remove_breakpoint;
+ current_target.to_terminal_init = debug_to_terminal_init;
+ current_target.to_terminal_inferior = debug_to_terminal_inferior;
+ current_target.to_terminal_ours_for_output = debug_to_terminal_ours_for_output;
+ current_target.to_terminal_ours = debug_to_terminal_ours;
+ current_target.to_terminal_info = debug_to_terminal_info;
+ current_target.to_kill = debug_to_kill;
+ current_target.to_load = debug_to_load;
+ current_target.to_lookup_symbol = debug_to_lookup_symbol;
+ current_target.to_create_inferior = debug_to_create_inferior;
+ current_target.to_post_startup_inferior = debug_to_post_startup_inferior;
+ current_target.to_acknowledge_created_inferior = debug_to_acknowledge_created_inferior;
+ current_target.to_clone_and_follow_inferior = debug_to_clone_and_follow_inferior;
+ current_target.to_post_follow_inferior_by_clone = debug_to_post_follow_inferior_by_clone;
+ current_target.to_insert_fork_catchpoint = debug_to_insert_fork_catchpoint;
+ current_target.to_remove_fork_catchpoint = debug_to_remove_fork_catchpoint;
+ current_target.to_insert_vfork_catchpoint = debug_to_insert_vfork_catchpoint;
+ current_target.to_remove_vfork_catchpoint = debug_to_remove_vfork_catchpoint;
+ current_target.to_has_forked = debug_to_has_forked;
+ current_target.to_has_vforked = debug_to_has_vforked;
+ current_target.to_can_follow_vfork_prior_to_exec = debug_to_can_follow_vfork_prior_to_exec;
+ current_target.to_post_follow_vfork = debug_to_post_follow_vfork;
+ current_target.to_insert_exec_catchpoint = debug_to_insert_exec_catchpoint;
+ current_target.to_remove_exec_catchpoint = debug_to_remove_exec_catchpoint;
+ current_target.to_has_execd = debug_to_has_execd;
+ current_target.to_reported_exec_events_per_exec_call = debug_to_reported_exec_events_per_exec_call;
+ current_target.to_has_syscall_event = debug_to_has_syscall_event;
+ current_target.to_has_exited = debug_to_has_exited;
+ current_target.to_mourn_inferior = debug_to_mourn_inferior;
+ current_target.to_can_run = debug_to_can_run;
+ current_target.to_notice_signals = debug_to_notice_signals;
+ current_target.to_thread_alive = debug_to_thread_alive;
+ current_target.to_stop = debug_to_stop;
+ current_target.to_query = debug_to_query;
+ current_target.to_enable_exception_callback = debug_to_enable_exception_callback;
+ current_target.to_get_current_exception_event = debug_to_get_current_exception_event;
+ current_target.to_pid_to_exec_file = debug_to_pid_to_exec_file;
+ current_target.to_core_file_to_sym_file = debug_to_core_file_to_sym_file;
+
+}
+#endif /* MAINTENANCE_CMDS */
+
+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 ()
+{
+ init_dummy_target ();
+ push_target (&dummy_target);
+
+ add_info ("target", target_info, targ_desc);
+ add_info ("files", target_info, targ_desc);
+
+#ifdef MAINTENANCE_CMDS
+ add_show_from_set (
+ add_set_cmd ("targetdebug", class_maintenance, var_zinteger,
+ (char *)&targetdebug,
+ "Set target debugging.\n\
+When non-zero, target debugging is enabled.", &setlist),
+ &showlist);
+#endif
+
+ if (!STREQ (signals[TARGET_SIGNAL_LAST].string, "TARGET_SIGNAL_MAGIC"))
+ abort ();
+}
diff --git a/gdb/target.h b/gdb/target.h
new file mode 100644
index 00000000000..21c3babddba
--- /dev/null
+++ b/gdb/target.h
@@ -0,0 +1,1264 @@
+/* Interface between GDB and target environments, including files and processes
+ Copyright 1990, 91, 92, 93, 94, 1999 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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"
+#include "symtab.h"
+
+enum strata {
+ dummy_stratum, /* The lowest of the low */
+ file_stratum, /* Executable files, etc */
+ core_stratum, /* Core dump files */
+ download_stratum, /* Downloading of remote targets */
+ process_stratum /* Executing processes */
+};
+
+enum thread_control_capabilities {
+ tc_none = 0, /* Default: can't control thread execution. */
+ tc_schedlock = 1, /* Can lock the thread scheduler. */
+ tc_switch = 2 /* Can switch the running thread on demand. */
+};
+
+/* Stuff for target_wait. */
+
+/* Generally, what has the program done? */
+enum target_waitkind {
+ /* The program has exited. The exit status is in value.integer. */
+ TARGET_WAITKIND_EXITED,
+
+ /* The program has stopped with a signal. Which signal is in value.sig. */
+ TARGET_WAITKIND_STOPPED,
+
+ /* The program has terminated with a signal. Which signal is in
+ value.sig. */
+ TARGET_WAITKIND_SIGNALLED,
+
+ /* The program is letting us know that it dynamically loaded something
+ (e.g. it called load(2) on AIX). */
+ TARGET_WAITKIND_LOADED,
+
+ /* The program has forked. A "related" process' ID is in value.related_pid.
+ I.e., if the child forks, value.related_pid is the parent's ID.
+ */
+ TARGET_WAITKIND_FORKED,
+
+ /* The program has vforked. A "related" process's ID is in value.related_pid.
+ */
+ TARGET_WAITKIND_VFORKED,
+
+ /* The program has exec'ed a new executable file. The new file's pathname
+ is pointed to by value.execd_pathname.
+ */
+ TARGET_WAITKIND_EXECD,
+
+ /* The program has entered or returned from a system call. On HP-UX, this
+ is used in the hardware watchpoint implementation. The syscall's unique
+ integer ID number is in value.syscall_id;
+ */
+ TARGET_WAITKIND_SYSCALL_ENTRY,
+ TARGET_WAITKIND_SYSCALL_RETURN,
+
+ /* Nothing happened, but we stopped anyway. This perhaps should be handled
+ within target_wait, but I'm not sure target_wait should be resuming the
+ inferior. */
+ TARGET_WAITKIND_SPURIOUS
+ };
+
+/* The numbering of these signals is chosen to match traditional unix
+ signals (insofar as various unices use the same numbers, anyway).
+ It is also the numbering of the GDB remote protocol. Other remote
+ protocols, if they use a different numbering, should make sure to
+ translate appropriately. */
+
+/* This is based strongly on Unix/POSIX signals for several reasons:
+ (1) This set of signals represents a widely-accepted attempt to
+ represent events of this sort in a portable fashion, (2) we want a
+ signal to make it from wait to child_wait to the user intact, (3) many
+ remote protocols use a similar encoding. However, it is
+ recognized that this set of signals has limitations (such as not
+ distinguishing between various kinds of SIGSEGV, or not
+ distinguishing hitting a breakpoint from finishing a single step).
+ So in the future we may get around this either by adding additional
+ signals for breakpoint, single-step, etc., or by adding signal
+ codes; the latter seems more in the spirit of what BSD, System V,
+ etc. are doing to address these issues. */
+
+/* For an explanation of what each signal means, see
+ target_signal_to_string. */
+
+enum target_signal {
+ /* Used some places (e.g. stop_signal) to record the concept that
+ there is no signal. */
+ TARGET_SIGNAL_0 = 0,
+ TARGET_SIGNAL_FIRST = 0,
+ TARGET_SIGNAL_HUP = 1,
+ TARGET_SIGNAL_INT = 2,
+ TARGET_SIGNAL_QUIT = 3,
+ TARGET_SIGNAL_ILL = 4,
+ TARGET_SIGNAL_TRAP = 5,
+ TARGET_SIGNAL_ABRT = 6,
+ TARGET_SIGNAL_EMT = 7,
+ TARGET_SIGNAL_FPE = 8,
+ TARGET_SIGNAL_KILL = 9,
+ TARGET_SIGNAL_BUS = 10,
+ TARGET_SIGNAL_SEGV = 11,
+ TARGET_SIGNAL_SYS = 12,
+ TARGET_SIGNAL_PIPE = 13,
+ TARGET_SIGNAL_ALRM = 14,
+ TARGET_SIGNAL_TERM = 15,
+ TARGET_SIGNAL_URG = 16,
+ TARGET_SIGNAL_STOP = 17,
+ TARGET_SIGNAL_TSTP = 18,
+ TARGET_SIGNAL_CONT = 19,
+ TARGET_SIGNAL_CHLD = 20,
+ TARGET_SIGNAL_TTIN = 21,
+ TARGET_SIGNAL_TTOU = 22,
+ TARGET_SIGNAL_IO = 23,
+ TARGET_SIGNAL_XCPU = 24,
+ TARGET_SIGNAL_XFSZ = 25,
+ TARGET_SIGNAL_VTALRM = 26,
+ TARGET_SIGNAL_PROF = 27,
+ TARGET_SIGNAL_WINCH = 28,
+ TARGET_SIGNAL_LOST = 29,
+ TARGET_SIGNAL_USR1 = 30,
+ TARGET_SIGNAL_USR2 = 31,
+ TARGET_SIGNAL_PWR = 32,
+ /* Similar to SIGIO. Perhaps they should have the same number. */
+ TARGET_SIGNAL_POLL = 33,
+ TARGET_SIGNAL_WIND = 34,
+ TARGET_SIGNAL_PHONE = 35,
+ TARGET_SIGNAL_WAITING = 36,
+ TARGET_SIGNAL_LWP = 37,
+ TARGET_SIGNAL_DANGER = 38,
+ TARGET_SIGNAL_GRANT = 39,
+ TARGET_SIGNAL_RETRACT = 40,
+ TARGET_SIGNAL_MSG = 41,
+ TARGET_SIGNAL_SOUND = 42,
+ TARGET_SIGNAL_SAK = 43,
+ TARGET_SIGNAL_PRIO = 44,
+ TARGET_SIGNAL_REALTIME_33 = 45,
+ TARGET_SIGNAL_REALTIME_34 = 46,
+ TARGET_SIGNAL_REALTIME_35 = 47,
+ TARGET_SIGNAL_REALTIME_36 = 48,
+ TARGET_SIGNAL_REALTIME_37 = 49,
+ TARGET_SIGNAL_REALTIME_38 = 50,
+ TARGET_SIGNAL_REALTIME_39 = 51,
+ TARGET_SIGNAL_REALTIME_40 = 52,
+ TARGET_SIGNAL_REALTIME_41 = 53,
+ TARGET_SIGNAL_REALTIME_42 = 54,
+ TARGET_SIGNAL_REALTIME_43 = 55,
+ TARGET_SIGNAL_REALTIME_44 = 56,
+ TARGET_SIGNAL_REALTIME_45 = 57,
+ TARGET_SIGNAL_REALTIME_46 = 58,
+ TARGET_SIGNAL_REALTIME_47 = 59,
+ TARGET_SIGNAL_REALTIME_48 = 60,
+ TARGET_SIGNAL_REALTIME_49 = 61,
+ TARGET_SIGNAL_REALTIME_50 = 62,
+ TARGET_SIGNAL_REALTIME_51 = 63,
+ TARGET_SIGNAL_REALTIME_52 = 64,
+ TARGET_SIGNAL_REALTIME_53 = 65,
+ TARGET_SIGNAL_REALTIME_54 = 66,
+ TARGET_SIGNAL_REALTIME_55 = 67,
+ TARGET_SIGNAL_REALTIME_56 = 68,
+ TARGET_SIGNAL_REALTIME_57 = 69,
+ TARGET_SIGNAL_REALTIME_58 = 70,
+ TARGET_SIGNAL_REALTIME_59 = 71,
+ TARGET_SIGNAL_REALTIME_60 = 72,
+ TARGET_SIGNAL_REALTIME_61 = 73,
+ TARGET_SIGNAL_REALTIME_62 = 74,
+ TARGET_SIGNAL_REALTIME_63 = 75,
+#if defined(MACH) || defined(__MACH__)
+ /* Mach exceptions */
+ TARGET_EXC_BAD_ACCESS = 76,
+ TARGET_EXC_BAD_INSTRUCTION = 77,
+ TARGET_EXC_ARITHMETIC = 78,
+ TARGET_EXC_EMULATION = 79,
+ TARGET_EXC_SOFTWARE = 80,
+ TARGET_EXC_BREAKPOINT = 81,
+#endif
+ /* Some signal we don't know about. */
+ TARGET_SIGNAL_UNKNOWN,
+
+ /* Use whatever signal we use when one is not specifically specified
+ (for passing to proceed and so on). */
+ TARGET_SIGNAL_DEFAULT,
+
+ /* Last and unused enum value, for sizing arrays, etc. */
+ TARGET_SIGNAL_LAST
+};
+
+struct target_waitstatus {
+ enum target_waitkind kind;
+
+ /* Forked child pid, execd pathname, exit status or signal number. */
+ union {
+ int integer;
+ enum target_signal sig;
+ int related_pid;
+ char * execd_pathname;
+ int syscall_id;
+ } value;
+};
+
+/* Return the string for a signal. */
+extern char *target_signal_to_string PARAMS ((enum target_signal));
+
+/* Return the name (SIGHUP, etc.) for a signal. */
+extern char *target_signal_to_name PARAMS ((enum target_signal));
+
+/* Given a name (SIGHUP, etc.), return its signal. */
+enum target_signal target_signal_from_name PARAMS ((char *));
+
+
+/* If certain kinds of activity happen, target_wait should perform
+ callbacks. */
+/* Right now we just call (*TARGET_ACTIVITY_FUNCTION) if I/O is possible
+ on TARGET_ACTIVITY_FD. */
+extern int target_activity_fd;
+/* Returns zero to leave the inferior alone, one to interrupt it. */
+extern int (*target_activity_function) PARAMS ((void));
+
+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_post_attach) PARAMS ((int));
+ void (*to_require_attach) PARAMS ((char *, int));
+ void (*to_detach) PARAMS ((char *, int));
+ void (*to_require_detach) PARAMS ((int, char *, int));
+ void (*to_resume) PARAMS ((int, int, enum target_signal));
+ int (*to_wait) PARAMS ((int, struct target_waitstatus *));
+ void (*to_post_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));
+
+#if 0
+ /* Enable this after 4.12. */
+
+ /* Search target memory. Start at STARTADDR and take LEN bytes of
+ target memory, and them with MASK, and compare to DATA. If they
+ match, set *ADDR_FOUND to the address we found it at, store the data
+ we found at LEN bytes starting at DATA_FOUND, and return. If
+ not, add INCREMENT to the search address and keep trying until
+ the search address is outside of the range [LORANGE,HIRANGE).
+
+ If we don't find anything, set *ADDR_FOUND to (CORE_ADDR)0 and return. */
+ void (*to_search) PARAMS ((int len, char *data, char *mask,
+ CORE_ADDR startaddr, int increment,
+ CORE_ADDR lorange, CORE_ADDR hirange,
+ CORE_ADDR *addr_found, char *data_found));
+
+#define target_search(len, data, mask, startaddr, increment, lorange, hirange, addr_found, data_found) \
+ (*current_target.to_search) (len, data, mask, startaddr, increment, \
+ lorange, hirange, addr_found, data_found)
+#endif /* 0 */
+
+ 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_post_startup_inferior) PARAMS ((int));
+ void (*to_acknowledge_created_inferior) PARAMS ((int));
+ void (*to_clone_and_follow_inferior) PARAMS ((int, int *));
+ void (*to_post_follow_inferior_by_clone) PARAMS ((void));
+ int (*to_insert_fork_catchpoint) PARAMS ((int));
+ int (*to_remove_fork_catchpoint) PARAMS ((int));
+ int (*to_insert_vfork_catchpoint) PARAMS ((int));
+ int (*to_remove_vfork_catchpoint) PARAMS ((int));
+ int (*to_has_forked) PARAMS ((int, int *));
+ int (*to_has_vforked) PARAMS ((int, int *));
+ int (*to_can_follow_vfork_prior_to_exec) PARAMS ((void));
+ void (*to_post_follow_vfork) PARAMS ((int, int, int, int));
+ int (*to_insert_exec_catchpoint) PARAMS ((int));
+ int (*to_remove_exec_catchpoint) PARAMS ((int));
+ int (*to_has_execd) PARAMS ((int, char **));
+ int (*to_reported_exec_events_per_exec_call) PARAMS ((void));
+ int (*to_has_syscall_event) PARAMS ((int, enum target_waitkind *, int *));
+ int (*to_has_exited) PARAMS ((int, int, int *));
+ void (*to_mourn_inferior) PARAMS ((void));
+ int (*to_can_run) PARAMS ((void));
+ void (*to_notice_signals) PARAMS ((int pid));
+ int (*to_thread_alive) PARAMS ((int pid));
+ void (*to_stop) PARAMS ((void));
+ int (*to_query) PARAMS ((int/*char*/, char *, char *, int *));
+ struct symtab_and_line * (*to_enable_exception_callback) PARAMS ((enum exception_event_kind, int));
+ struct exception_event_record * (*to_get_current_exception_event) PARAMS ((void));
+ char * (*to_pid_to_exec_file) PARAMS ((int pid));
+ char * (*to_core_file_to_sym_file) PARAMS ((char *));
+ enum strata to_stratum;
+ struct target_ops
+ *DONT_USE; /* formerly to_next */
+ int to_has_all_memory;
+ int to_has_memory;
+ int to_has_stack;
+ int to_has_registers;
+ int to_has_execution;
+ int to_has_thread_control; /* control thread 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;
+
+/* An item on the target stack. */
+
+struct target_stack_item
+{
+ struct target_stack_item *next;
+ struct target_ops *target_ops;
+};
+
+/* The target stack. */
+
+extern struct target_stack_item *target_stack;
+
+/* 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)
+
+/* The target_attach operation places a process under debugger control,
+ and stops the process.
+
+ This operation provides a target-specific hook that allows the
+ necessary bookkeeping to be performed after an attach completes.
+ */
+#define target_post_attach(pid) \
+ (*current_target.to_post_attach) (pid)
+
+/* Attaches to a process on the target side, if not already attached.
+ (If already attached, takes no action.)
+
+ This operation can be used to follow the child process of a fork.
+ On some targets, such child processes of an original inferior process
+ are automatically under debugger control, and thus do not require an
+ actual attach operation. */
+
+#define target_require_attach(args, from_tty) \
+ (*current_target.to_require_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));
+
+/* Detaches from a process on the target side, if not already dettached.
+ (If already detached, takes no action.)
+
+ This operation can be used to follow the parent process of a fork.
+ On some targets, such child processes of an original inferior process
+ are automatically under debugger control, and thus do require an actual
+ detach operation.
+
+ PID is the process id of the child to detach from.
+ ARGS is arguments typed by the user (e.g. a signal to send the process).
+ FROM_TTY says whether to be verbose or not. */
+
+#define target_require_detach(pid, args, from_tty) \
+ (*current_target.to_require_detach) (pid, args, from_tty)
+
+/* Resume execution of the target process PID. STEP says whether to
+ single-step or to run free; SIGGNAL is the signal to be given to
+ the target, or TARGET_SIGNAL_0 for no signal. The caller may not
+ pass TARGET_SIGNAL_DEFAULT. */
+
+#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. Note that it is
+ *not* OK to return_to_top_level out of target_wait without popping
+ the debugging target from the stack; GDB isn't prepared to get back
+ to the prompt with a debugging target but without the frame cache,
+ stop_pc, etc., set up. */
+
+#define target_wait(pid, status) \
+ (*current_target.to_wait) (pid, status)
+
+/* The target_wait operation waits for a process event to occur, and
+ thereby stop the process.
+
+ On some targets, certain events may happen in sequences. gdb's
+ correct response to any single event of such a sequence may require
+ knowledge of what earlier events in the sequence have been seen.
+
+ This operation provides a target-specific hook that allows the
+ necessary bookkeeping to be performed to track such sequences.
+ */
+
+#define target_post_wait(pid, status) \
+ (*current_target.to_post_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, int *));
+
+extern int
+target_read_memory PARAMS ((CORE_ADDR memaddr, char *myaddr, int len));
+
+extern int
+target_read_memory_section PARAMS ((CORE_ADDR memaddr, char *myaddr, int len,
+ asection *bfd_section));
+
+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 *));
+
+extern char *
+child_pid_to_exec_file PARAMS ((int));
+
+extern char *
+child_core_file_to_sym_file PARAMS ((char *));
+
+#if defined(CHILD_POST_ATTACH)
+extern void
+child_post_attach PARAMS ((int));
+#endif
+
+extern void
+child_post_wait PARAMS ((int, int));
+
+extern void
+child_post_startup_inferior PARAMS ((int));
+
+extern void
+child_acknowledge_created_inferior PARAMS ((int));
+
+extern void
+child_clone_and_follow_inferior PARAMS ((int, int *));
+
+extern void
+child_post_follow_inferior_by_clone PARAMS ((void));
+
+extern int
+child_insert_fork_catchpoint PARAMS ((int));
+
+extern int
+child_remove_fork_catchpoint PARAMS ((int));
+
+extern int
+child_insert_vfork_catchpoint PARAMS ((int));
+
+extern int
+child_remove_vfork_catchpoint PARAMS ((int));
+
+extern int
+child_has_forked PARAMS ((int, int *));
+
+extern int
+child_has_vforked PARAMS ((int, int *));
+
+extern void
+child_acknowledge_created_inferior PARAMS ((int));
+
+extern int
+child_can_follow_vfork_prior_to_exec PARAMS ((void));
+
+extern void
+child_post_follow_vfork PARAMS ((int, int, int, int));
+
+extern int
+child_insert_exec_catchpoint PARAMS ((int));
+
+extern int
+child_remove_exec_catchpoint PARAMS ((int));
+
+extern int
+child_has_execd PARAMS ((int, char **));
+
+extern int
+child_reported_exec_events_per_exec_call PARAMS ((void));
+
+extern int
+child_has_syscall_event PARAMS ((int, enum target_waitkind *, int *));
+
+extern int
+child_has_exited PARAMS ((int, int, int *));
+
+extern int
+child_thread_alive PARAMS ((int));
+
+/* 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)
+
+
+/* Some targets (such as ttrace-based HPUX) don't allow us to request
+ notification of inferior events such as fork and vork immediately
+ after the inferior is created. (This because of how gdb gets an
+ inferior created via invoking a shell to do it. In such a scenario,
+ if the shell init file has commands in it, the shell will fork and
+ exec for each of those commands, and we will see each such fork
+ event. Very bad.)
+
+ Such targets will supply an appropriate definition for this function.
+ */
+#define target_post_startup_inferior(pid) \
+ (*current_target.to_post_startup_inferior) (pid)
+
+/* On some targets, the sequence of starting up an inferior requires
+ some synchronization between gdb and the new inferior process, PID.
+ */
+#define target_acknowledge_created_inferior(pid) \
+ (*current_target.to_acknowledge_created_inferior) (pid)
+
+/* An inferior process has been created via a fork() or similar
+ system call. This function will clone the debugger, then ensure
+ that CHILD_PID is attached to by that debugger.
+
+ FOLLOWED_CHILD is set TRUE on return *for the clone debugger only*,
+ and FALSE otherwise. (The original and clone debuggers can use this
+ to determine which they are, if need be.)
+
+ (This is not a terribly useful feature without a GUI to prevent
+ the two debuggers from competing for shell input.)
+ */
+#define target_clone_and_follow_inferior(child_pid,followed_child) \
+ (*current_target.to_clone_and_follow_inferior) (child_pid, followed_child)
+
+/* This operation is intended to be used as the last in a sequence of
+ steps taken when following both parent and child of a fork. This
+ is used by a clone of the debugger, which will follow the child.
+
+ The original debugger has detached from this process, and the
+ clone has attached to it.
+
+ On some targets, this requires a bit of cleanup to make it work
+ correctly.
+ */
+#define target_post_follow_inferior_by_clone() \
+ (*current_target.to_post_follow_inferior_by_clone) ()
+
+/* On some targets, we can catch an inferior fork or vfork event when it
+ occurs. These functions insert/remove an already-created catchpoint for
+ such events.
+ */
+#define target_insert_fork_catchpoint(pid) \
+ (*current_target.to_insert_fork_catchpoint) (pid)
+
+#define target_remove_fork_catchpoint(pid) \
+ (*current_target.to_remove_fork_catchpoint) (pid)
+
+#define target_insert_vfork_catchpoint(pid) \
+ (*current_target.to_insert_vfork_catchpoint) (pid)
+
+#define target_remove_vfork_catchpoint(pid) \
+ (*current_target.to_remove_vfork_catchpoint) (pid)
+
+/* Returns TRUE if PID has invoked the fork() system call. And,
+ also sets CHILD_PID to the process id of the other ("child")
+ inferior process that was created by that call.
+ */
+#define target_has_forked(pid,child_pid) \
+ (*current_target.to_has_forked) (pid,child_pid)
+
+/* Returns TRUE if PID has invoked the vfork() system call. And,
+ also sets CHILD_PID to the process id of the other ("child")
+ inferior process that was created by that call.
+ */
+#define target_has_vforked(pid,child_pid) \
+ (*current_target.to_has_vforked) (pid,child_pid)
+
+/* Some platforms (such as pre-10.20 HP-UX) don't allow us to do
+ anything to a vforked child before it subsequently calls exec().
+ On such platforms, we say that the debugger cannot "follow" the
+ child until it has vforked.
+
+ This function should be defined to return 1 by those targets
+ which can allow the debugger to immediately follow a vforked
+ child, and 0 if they cannot.
+ */
+#define target_can_follow_vfork_prior_to_exec() \
+ (*current_target.to_can_follow_vfork_prior_to_exec) ()
+
+/* An inferior process has been created via a vfork() system call.
+ The debugger has followed the parent, the child, or both. The
+ process of setting up for that follow may have required some
+ target-specific trickery to track the sequence of reported events.
+ If so, this function should be defined by those targets that
+ require the debugger to perform cleanup or initialization after
+ the vfork follow.
+ */
+#define target_post_follow_vfork(parent_pid,followed_parent,child_pid,followed_child) \
+ (*current_target.to_post_follow_vfork) (parent_pid,followed_parent,child_pid,followed_child)
+
+/* On some targets, we can catch an inferior exec event when it
+ occurs. These functions insert/remove an already-created catchpoint
+ for such events.
+ */
+#define target_insert_exec_catchpoint(pid) \
+ (*current_target.to_insert_exec_catchpoint) (pid)
+
+#define target_remove_exec_catchpoint(pid) \
+ (*current_target.to_remove_exec_catchpoint) (pid)
+
+/* Returns TRUE if PID has invoked a flavor of the exec() system call.
+ And, also sets EXECD_PATHNAME to the pathname of the executable file
+ that was passed to exec(), and is now being executed.
+ */
+#define target_has_execd(pid,execd_pathname) \
+ (*current_target.to_has_execd) (pid,execd_pathname)
+
+/* Returns the number of exec events that are reported when a process
+ invokes a flavor of the exec() system call on this target, if exec
+ events are being reported.
+ */
+#define target_reported_exec_events_per_exec_call() \
+ (*current_target.to_reported_exec_events_per_exec_call) ()
+
+/* Returns TRUE if PID has reported a syscall event. And, also sets
+ KIND to the appropriate TARGET_WAITKIND_, and sets SYSCALL_ID to
+ the unique integer ID of the syscall.
+ */
+#define target_has_syscall_event(pid,kind,syscall_id) \
+ (*current_target.to_has_syscall_event) (pid,kind,syscall_id)
+
+/* Returns TRUE if PID has exited. And, also sets EXIT_STATUS to the
+ exit code of PID, if any.
+ */
+#define target_has_exited(pid,wait_status,exit_status) \
+ (*current_target.to_has_exited) (pid,wait_status,exit_status)
+
+/* The debugger has completed a blocking wait() call. There is now
+ some process event that must be processed. This function should
+ be defined by those targets that require the debugger to perform
+ cleanup or internal state changes in response to the process event.
+ */
+
+/* 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)
+
+/* Check to see if a thread is still alive. */
+
+#define target_thread_alive(pid) \
+ (*current_target.to_thread_alive) (pid)
+
+/* Make target stop in a continuable fashion. (For instance, under Unix, this
+ should act like SIGSTOP). This function is normally used by GUIs to
+ implement a stop button. */
+
+#define target_stop current_target.to_stop
+
+/* Queries the target side for some information. The first argument is a
+ letter specifying the type of the query, which is used to determine who
+ should process it. The second argument is a string that specifies which
+ information is desired and the third is a buffer that carries back the
+ response from the target side. The fourth parameter is the size of the
+ output buffer supplied. */
+
+#define target_query(query_type, query, resp_buffer, bufffer_size) \
+ (*current_target.to_query) (query_type, query, resp_buffer, bufffer_size)
+
+/* Get the symbol information for a breakpointable routine called when
+ an exception event occurs.
+ Intended mainly for C++, and for those
+ platforms/implementations where such a callback mechanism is available,
+ e.g. HP-UX with ANSI C++ (aCC). Some compilers (e.g. g++) support
+ different mechanisms for debugging exceptions. */
+
+#define target_enable_exception_callback(kind, enable) \
+ (*current_target.to_enable_exception_callback) (kind, enable)
+
+/* Get the current exception event kind -- throw or catch, etc. */
+
+#define target_get_current_exception_event() \
+ (*current_target.to_get_current_exception_event) ()
+
+/* 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)
+
+/* Can the target support the debugger control of thread execution?
+ a) Can it lock the thread scheduler?
+ b) Can it switch the currently running thread? */
+
+#define target_can_lock_scheduler \
+ (current_target.to_has_thread_control & tc_schedlock)
+
+#define target_can_switch_threads \
+ (current_target.to_has_thread_control & tc_switch)
+
+extern void target_link PARAMS ((char *, CORE_ADDR *));
+
+/* 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
+
+#ifndef target_tid_to_str
+#define target_tid_to_str(PID) \
+ normal_pid_to_str (PID)
+extern char *normal_pid_to_str PARAMS ((int pid));
+#endif
+
+
+#ifndef target_new_objfile
+#define target_new_objfile(OBJFILE)
+#endif
+
+#ifndef target_pid_or_tid_to_str
+#define target_pid_or_tid_to_str(ID) \
+ normal_pid_to_str (ID)
+#endif
+
+/* Attempts to find the pathname of the executable file
+ that was run to create a specified process.
+
+ The process PID must be stopped when this operation is used.
+
+ If the executable file cannot be determined, NULL is returned.
+
+ Else, a pointer to a character string containing the pathname
+ is returned. This string should be copied into a buffer by
+ the client if the string will not be immediately used, or if
+ it must persist.
+ */
+
+#define target_pid_to_exec_file(pid) \
+ (current_target.to_pid_to_exec_file) (pid)
+
+/* Hook to call target-dependant code after reading in a new symbol table. */
+
+#ifndef TARGET_SYMFILE_POSTREAD
+#define TARGET_SYMFILE_POSTREAD(OBJFILE)
+#endif
+
+/* Hook to call target dependant code just after inferior target process has
+ started. */
+
+#ifndef TARGET_CREATE_INFERIOR_HOOK
+#define TARGET_CREATE_INFERIOR_HOOK(PID)
+#endif
+
+/* Hardware watchpoint interfaces. */
+
+/* Returns non-zero if we were stopped by a hardware watchpoint (memory read or
+ write). */
+
+#ifndef STOPPED_BY_WATCHPOINT
+#define STOPPED_BY_WATCHPOINT(w) 0
+#endif
+
+/* HP-UX supplies these operations, which respectively disable and enable
+ the memory page-protections that are used to implement hardware watchpoints
+ on that platform. See wait_for_inferior's use of these.
+ */
+#if !defined(TARGET_DISABLE_HW_WATCHPOINTS)
+#define TARGET_DISABLE_HW_WATCHPOINTS(pid)
+#endif
+
+#if !defined(TARGET_ENABLE_HW_WATCHPOINTS)
+#define TARGET_ENABLE_HW_WATCHPOINTS(pid)
+#endif
+
+/* Provide defaults for systems that don't support hardware watchpoints. */
+
+#ifndef TARGET_HAS_HARDWARE_WATCHPOINTS
+
+/* Returns non-zero if we can set a hardware watchpoint of type TYPE. TYPE is
+ one of bp_hardware_watchpoint, bp_read_watchpoint, bp_write_watchpoint, or
+ bp_hardware_breakpoint. CNT is the number of such watchpoints used so far
+ (including this one?). OTHERTYPE is who knows what... */
+
+#define TARGET_CAN_USE_HARDWARE_WATCHPOINT(TYPE,CNT,OTHERTYPE) 0
+
+#if !defined(TARGET_REGION_SIZE_OK_FOR_HW_WATCHPOINT)
+#define TARGET_REGION_SIZE_OK_FOR_HW_WATCHPOINT(byte_count) \
+ (LONGEST)(byte_count) <= REGISTER_SIZE
+#endif
+
+/* However, some addresses may not be profitable to use hardware to watch,
+ or may be difficult to understand when the addressed object is out of
+ scope, and hence should be unwatched. On some targets, this may have
+ severe performance penalties, such that we might as well use regular
+ watchpoints, and save (possibly precious) hardware watchpoints for other
+ locations.
+ */
+#if !defined(TARGET_RANGE_PROFITABLE_FOR_HW_WATCHPOINT)
+#define TARGET_RANGE_PROFITABLE_FOR_HW_WATCHPOINT(pid,start,len) 0
+#endif
+
+
+/* Set/clear a hardware watchpoint starting at ADDR, for LEN bytes. TYPE is 0
+ for write, 1 for read, and 2 for read/write accesses. Returns 0 for
+ success, non-zero for failure. */
+
+#define target_remove_watchpoint(ADDR,LEN,TYPE) -1
+#define target_insert_watchpoint(ADDR,LEN,TYPE) -1
+
+#endif /* TARGET_HAS_HARDWARE_WATCHPOINTS */
+
+#ifndef target_insert_hw_breakpoint
+#define target_remove_hw_breakpoint(ADDR,SHADOW) -1
+#define target_insert_hw_breakpoint(ADDR,SHADOW) -1
+#endif
+
+#ifndef target_stopped_data_address
+#define target_stopped_data_address() 0
+#endif
+
+/* If defined, then we need to decr pc by this much after a hardware break-
+ point. Presumably this overrides DECR_PC_AFTER_BREAK... */
+
+#ifndef DECR_PC_AFTER_HW_BREAK
+#define DECR_PC_AFTER_HW_BREAK 0
+#endif
+
+/* Sometimes gdb may pick up what appears to be a valid target address
+ from a minimal symbol, but the value really means, essentially,
+ "This is an index into a table which is populated when the inferior
+ is run. Therefore, do not attempt to use this as a PC."
+ */
+#if !defined(PC_REQUIRES_RUN_BEFORE_USE)
+#define PC_REQUIRES_RUN_BEFORE_USE(pc) (0)
+#endif
+
+/* This will only be defined by a target that supports catching vfork events,
+ such as HP-UX.
+
+ On some targets (such as HP-UX 10.20 and earlier), resuming a newly vforked
+ child process after it has exec'd, causes the parent process to resume as
+ well. To prevent the parent from running spontaneously, such targets should
+ define this to a function that prevents that from happening.
+ */
+#if !defined(ENSURE_VFORKING_PARENT_REMAINS_STOPPED)
+#define ENSURE_VFORKING_PARENT_REMAINS_STOPPED(PID) (0)
+#endif
+
+/* This will only be defined by a target that supports catching vfork events,
+ such as HP-UX.
+
+ On some targets (such as HP-UX 10.20 and earlier), a newly vforked child
+ process must be resumed when it delivers its exec event, before the parent
+ vfork event will be delivered to us.
+ */
+#if !defined(RESUME_EXECD_VFORKING_CHILD_TO_GET_PARENT_VFORK)
+#define RESUME_EXECD_VFORKING_CHILD_TO_GET_PARENT_VFORK() (0)
+#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 the_bfd_section;
+
+ 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 *));
+
+extern breakpoint_from_pc_fn memory_breakpoint_from_pc;
+#ifndef BREAKPOINT_FROM_PC
+#define BREAKPOINT_FROM_PC(pcptr, lenptr) memory_breakpoint_from_pc (pcptr, lenptr)
+#endif
+
+
+/* From target.c */
+
+extern void
+initialize_targets PARAMS ((void));
+
+extern void
+noprocess PARAMS ((void));
+
+extern void
+find_default_attach PARAMS ((char *, int));
+
+void
+find_default_require_attach PARAMS ((char *, int));
+
+void
+find_default_require_detach PARAMS ((int, char *, int));
+
+extern void
+find_default_create_inferior PARAMS ((char *, char *, char **));
+
+void
+find_default_clone_and_follow_inferior PARAMS ((int, int *));
+
+extern struct target_ops *
+find_core_target PARAMS ((void));
+
+/* Stuff that should be shared among the various remote targets. */
+
+/* Debugging level. 0 is off, and non-zero values mean to print some debug
+ information (higher values, more information). */
+extern int remote_debug;
+
+/* Speed in bits per second, or -1 which means don't mess with the speed. */
+extern int baud_rate;
+/* Timeout limit for response from target. */
+extern int remote_timeout;
+
+extern asection *target_memory_bfd_section;
+
+/* Functions for helping to write a native target. */
+
+/* This is for native targets which use a unix/POSIX-style waitstatus. */
+extern void store_waitstatus PARAMS ((struct target_waitstatus *, int));
+
+/* Convert between host signal numbers and enum target_signal's. */
+extern enum target_signal target_signal_from_host PARAMS ((int));
+extern int target_signal_to_host PARAMS ((enum target_signal));
+
+/* Convert from a number used in a GDB command to an enum target_signal. */
+extern enum target_signal target_signal_from_command PARAMS ((int));
+
+/* Any target can call this to switch to remote protocol (in remote.c). */
+extern void push_remote_target PARAMS ((char *name, int from_tty));
+
+/* Imported from machine dependent code */
+
+#ifndef SOFTWARE_SINGLE_STEP_P
+#define SOFTWARE_SINGLE_STEP_P 0
+#define SOFTWARE_SINGLE_STEP(sig,bp_p) abort ()
+#endif /* SOFTWARE_SINGLE_STEP_P */
+
+/* Blank target vector entries are initialized to target_ignore. */
+void target_ignore PARAMS ((void));
+
+/* Macro for getting target's idea of a frame pointer.
+ FIXME: GDB's whole scheme for dealing with "frames" and
+ "frame pointers" needs a serious shakedown. */
+#ifndef TARGET_VIRTUAL_FRAME_POINTER
+#define TARGET_VIRTUAL_FRAME_POINTER(ADDR, REGP, OFFP) \
+ do { *(REGP) = FP_REGNUM; *(OFFP) = 0; } while (0)
+#endif /* TARGET_VIRTUAL_FRAME_POINTER */
+
+#endif /* !defined (TARGET_H) */
diff --git a/gdb/terminal.h b/gdb/terminal.h
new file mode 100644
index 00000000000..e7fb2cb4cde
--- /dev/null
+++ b/gdb/terminal.h
@@ -0,0 +1,92 @@
+/* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#if !defined (TERMINAL_H)
+#define TERMINAL_H 1
+
+
+/* If we're using autoconf, it will define HAVE_TERMIOS_H,
+ HAVE_TERMIO_H and HAVE_SGTTY_H for us. One day we can rewrite
+ ser-unix.c and inflow.c to inspect those names instead of
+ HAVE_TERMIOS, HAVE_TERMIO and the implicit HAVE_SGTTY (when neither
+ HAVE_TERMIOS or HAVE_TERMIO is set). Until then, make sure that
+ nothing has already defined the one of the names, and do the right
+ thing. */
+
+/* nothing works with go32, and the headers aren't complete */
+#if !defined (__GO32__)
+#if !defined (HAVE_TERMIOS) && !defined(HAVE_TERMIO) && !defined(HAVE_SGTTY)
+#if defined(HAVE_TERMIOS_H)
+#define HAVE_TERMIOS
+#else /* ! defined (HAVE_TERMIOS_H) */
+#if defined(HAVE_TERMIO_H)
+#define HAVE_TERMIO
+#else /* ! defined (HAVE_TERMIO_H) */
+#if defined(HAVE_SGTTY_H)
+#define HAVE_SGTTY
+#endif /* ! defined (HAVE_SGTTY_H) */
+#endif /* ! defined (HAVE_TERMIO_H) */
+#endif /* ! defined (HAVE_TERMIOS_H) */
+#endif /* !defined (HAVE_TERMIOS) && !defined(HAVE_TERMIO) && !defined(HAVE_SGTTY) */
+#endif /* ! defined (__GO32__) */
+
+#if defined(HAVE_TERMIOS)
+#include <termios.h>
+#endif
+
+#if !defined(__GO32__) && !defined(_WIN32) && !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
+
+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/gdb/testsuite/.gdbinit b/gdb/testsuite/.gdbinit
new file mode 100644
index 00000000000..62bcb743093
--- /dev/null
+++ b/gdb/testsuite/.gdbinit
@@ -0,0 +1 @@
+set height 400
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
new file mode 100644
index 00000000000..77a96b0f961
--- /dev/null
+++ b/gdb/testsuite/ChangeLog
@@ -0,0 +1,5930 @@
+1999-03-23 Stan Shebs <shebs@andros.cygnus.com>
+
+ * gdb.c++/overload.cc: Pass string instead of char addr, always
+ init ccpfoo.
+ * gdb.c++/templates.cc: Fix syntax error.
+
+1999-03-09 Jim Blandy <jimb@zwingli.cygnus.com>
+
+ * gdb.base/call-ar-st.c (main): Terminate char_array with a null
+ character, so GDB won't print garbage after its end.
+
+ * gdb.base/call-ar-st.exp: Don't step into sum_array_print; set a
+ breakpoint there instead. Sometimes GCC emits memcpy to handle
+ the large structures being passed by value, so we step into that
+ instead of sum_array_print, which obscures what we're really testing.
+ * gdb.base/step-test.exp: However, we do want a test that notices
+ the bizarre steps into memcpy, so do that here. Add check for
+ stepping into function calls that pass large structures by value.
+ ("Is that a noun clause, or are you just happy to see me?")
+ Remove all references to specific line numbers.
+ * gdb.base/step-test.c (struct rhomboidal, large_struct_by_value):
+ New type and function.
+ (main): Call large_struct_by_value, passing it a large struct by value.
+ * lib/gdb.exp (gdb_get_line_number): New function.
+
+ * gdb.base/step-test.exp: Rewrite `stepi' and `nexti' tests to be
+ more portable.
+
+ * lib/gdb.exp: Doc fixes.
+
+ * gdb.base/display.exp: Don't exercise the "detach" and "kill"
+ commands. They're not germane to this test, and they don't work
+ that way on remote targets.
+
+1999-02-25 Jason Molenda (jsm@bugshack.cygnus.com)
+
+ * gdb.base/call-ar-st.c: Include string.h, not strings.h.
+ * gdb.base/call-rt-st.c: Ditto.
+
+1999-02-23 Jim Blandy <jimb@zwingli.cygnus.com>
+
+ * configure.in: Formatting fix.
+ * configure: Regenerated.
+
+1999-02-13 Jim Blandy <jimb@zwingli.cygnus.com>
+
+ * gdb.threads/pthreads.exp (horiz): New variable.
+ (test_startup): Fix regexps that capture thread numbers.
+
+1999-02-10 Jason Molenda (jsm@bugshack.cygnus.com)
+
+ * gdb.base/smoke.exp: Disambiguate two test case names (both
+ called ``print'').
+
+Fri Feb 5 12:42:56 1999 Stan Shebs <shebs@andros.cygnus.com>
+
+ * gdb.base/volatile.exp: Use gdb_test, add xfails for GCC
+ compilation.
+
+1999-02-04 Jason Molenda (jsm@bugshack.cygnus.com)
+
+ * gdb.base/miscexprs.exp: Change patterns to match GDB's
+ actual output formatting.
+ * gdb.base/smoke.exp: GDB removes leading 0's.
+ * gdb.base/volatile.exp: Don't check type of remuneration;
+ that variable is no longer defined in constvars.c.
+ * gdb.base/step-test.c (main): Exit with explicit exit code.
+ * gdb.base/step-test.exp: Remove two nexti checks--they are
+ not portable.
+
+1999-02-04 Jason Molenda (jsm@bugshack.cygnus.com)
+
+ * gdb.base/help.exp ("help delete display"): Fix test to match
+ gdb's output.
+
+ * gdb.base/long_long.c (known_types): Initialize values to zero.
+ * gdb.base/long_long.exp: Step one more line
+ so 'dec' is initialized in "get to known place". GDB removes
+ leading zeros. Explicitly ask for hex formatting. Use
+ unique test case names.
+
+Tue Feb 2 10:16:08 1999 Elena Zannoni <ezannoni@kwikemart.cygnus.com>
+
+ * lib/gdb.exp (gdb_preprocess): Remove 'puts' statement.
+
+ * gdb.c++/method.exp: Add missing close brace.
+
+1999-01-30 Jim Blandy <jimb@zwingli.cygnus.com>
+
+ * gdb.base/maint.exp: Use 'set height 0' to disable page
+ prompting, not 'set height 400'.
+
+ Fix a bunch of timeouts.
+ * gdb.base/maint.exp ("maint print objfiles"): Break this up into
+ four separate tests, so expect doesn't take forever to match a ton
+ of text against a regexp with lots of .* forms.
+ ("maint print psymbols", "maint print symbols"): Make some of
+ these greps more selective, so that expect doesn't try to wade
+ through huge piles of output and time out.
+
+ * gdb.base/maint.exp ("maint print msymbols"): Fix pattern.
+
+ * gdb.base/maint.exp ("maint info breakpoints"): Split into two
+ tests: one which doesn't expect shlib events to be reported, and
+ another which does, but is XFAIL for all platforms other than
+ HP/UX.
+
+ * gdb.base/break.exp: Teach the test suite that the `catch
+ fork', `catch vfork', and `catch exec' commands produce error
+ messages on platforms that don't provide these features.
+
+Mon Jan 25 18:35:56 1999 Stan Shebs <shebs@andros.cygnus.com>
+
+ * gdb.hp/gen-so-thresh.c, so-thresh.sh, so-thresh.exp,
+ so-thresh.linkopts, so-thresh.mk: Move to gdb.hp from gdb.base
+ (shortening names from solib_threshold.exp etc), won't run on
+ anything but HP-UX for the foreseeable future.
+ * gdb.hp/Makefile.in, gdb.base/Makefile.in (clean): Adjust to
+ reflect move.
+
+Thu Jan 21 15:46:49 1999 Stan Shebs <shebs@andros.cygnus.com>
+
+ * gdb.base/Makefile.in, gdb.c++/Makefile.in,
+ gdb.trace/Makefile.in (clean): Remove all test executables.
+
+Tue Jan 19 17:20:09 1999 David Taylor <taylor@texas.cygnus.com>
+
+ * gdb.base/shlib-call.exp: add test cases to verify that gdb
+ successfully re-sets breakpoints in shared libraries.
+ * gdb.base/shmain.c (main): return 0, don't fall off the end.
+
+Fri Jan 15 14:04:57 1999 Elena Zannoni <ezannoni@kwikemart.cygnus.com>
+
+ * gdb.hp/xdb3.exp: do not execute unless on hppa-hpux platform
+ and compiled w/o GCC.
+
+ * gdb.hp/watch-cmd.exp: ditto.
+
+ * gdb.hp/watch-hp.exp: ditto.
+
+ * gdb.hp/xdb1.exp: ditto.
+
+ * gdb.hp/xdb2.exp: ditto.
+
+ * gdb.hp/dbx.exp: ditto.
+
+Thu Jan 14 18:36:48 1999 Stan Shebs <shebs@andros.cygnus.com>
+
+ * constvars.c: Remove C++-isms.
+ * constvars.exp: Use gdb_test everywhere, add xfails if compiled
+ with GCC.
+
+Mon Jan 11 10:08:03 1999 David Taylor <taylor@texas.cygnus.com>
+
+ The following changes are part of the HP merge.
+
+ * gdb.base/break.exp: new tests to verify that catchpoints for
+ fork, vfork, and exec don't trigger inappropriately.
+
+ * gdb.base/opaque.exp: compile one file at a time, then link.
+
+ * gdb.base/signals.exp: be more restrictive about which hppa
+ systems receive a setup_xfail. new tests.
+
+ * gdb.base/solib_threshold.build: new file.
+ * gdb.base/solib_threshold.exp: new file.
+ * gdb.base/solib_threshold.link_opts: new file.
+ * gdb.base/solib_threshold.mk: new file.
+ * gdb.base/gen_solib_threshold.c: new file.
+
+ * gdb.c++/classes.exp: if on HPUX and not using gcc, skip the
+ tests. New tests for enums inside classes.
+
+ * gdb.c++/compiler.cc: indicate support of template debugging.
+
+ * gdb.c++/demangle.exp: run hp style demangling tests.
+
+ * gdb.c++/inherit.exp: if on HPUX and not using gcc, skip the
+ tests.
+
+ * gdb.c++/misc.cc: changes to support new tests.
+
+ * gdb.c++/templates.cc: changes to support HP's compiler; changes
+ to support new tests.
+
+ * gdb.c++/virtfunc.exp: if we are on HPUX and we are not using
+ gcc, then skip these tests.
+
+Sun Jan 10 23:44:11 1999 David Taylor <taylor@texas.cygnus.com>
+
+ The following files are part of the HP merge; some had longer
+ names at HP, but have been renamed to be no more than 14
+ characters in length.
+
+ * gdb.hp/ambiguous.cc: new file.
+ * gdb.hp/ambiguous.exp: new file.
+ * gdb.hp/attach.exp: new file.
+ * gdb.hp/attach2.exp: new file.
+ * gdb.hp/classes-hp.exp: new file.
+ * gdb.hp/ctti.exp: new file.
+ * gdb.hp/ctti-add.cc: new file.
+ * gdb.hp/ctti-add1.cc: new file.
+ * gdb.hp/ctti-add2.cc: new file.
+ * gdb.hp/ctti-add3.cc: new file.
+ * gdb.hp/dbx.exp: new file.
+ * gdb.hp/exception.cc: new file.
+ * gdb.hp/exception.exp: new file.
+ * gdb.hp/foll-exec.c: new file.
+ * gdb.hp/foll-exec.exp: new file.
+ * gdb.hp/foll-fork.c: new file.
+ * gdb.hp/foll-fork.exp: new file.
+ * gdb.hp/foll-vfork.c: new file.
+ * gdb.hp/foll-vfork.exp: new file.
+ * gdb.hp/inherit-hp.exp: new file.
+ * gdb.hp/more-steps.exp: new file.
+ * gdb.hp/namespace.cc: new file.
+ * gdb.hp/namespace.exp: new file.
+ * gdb.hp/optimize.exp: new file.
+ * gdb.hp/pxdb.c: new file.
+ * gdb.hp/pxdb.exp: new file.
+ * gdb.hp/quicksort.exp: new file.
+ * gdb.hp/reg-test.exp: new file.
+ * gdb.hp/reg-test.s: new file.
+ * gdb.hp/sized-enum.c: new file.
+ * gdb.hp/sized-enum.exp: new file.
+ * gdb.hp/start-stop.exp: new file.
+ * gdb.hp/templ-hp.cc: new file.
+ * gdb.hp/templ-hp.exp: new file.
+ * gdb.hp/thr-lib.c: new file.
+ * gdb.hp/thr-lib.exp: new file.
+ * gdb.hp/thr-lib.h: new file.
+ * gdb.hp/thr-liblib.c: new file.
+ * gdb.hp/virtfun-hp.c: new file.
+ * gdb.hp/virtfun-hp.exp: new file.
+ * gdb.hp/watch-cmd.exp: new file.
+ * gdb.hp/watch-hp.exp: new file.
+ * gdb.hp/xdb1.exp: new file.
+ * gdb.hp/xdb2.exp: new file.
+ * gdb.hp/xdb3.exp: new file.
+
+Wed Jan 6 18:41:15 1999 David Taylor <taylor@texas.cygnus.com>
+
+ The following files are part of the HP merge; some had longer
+ names at HP, but have been renamed to be no more than 14
+ characters in length.
+
+ * gdb.base/ss.h: new file.
+ * gdb.base/call-ar-st.c: new file.
+ * gdb.base/call-ar-st.exp: new file.
+ * gdb.base/call-rt-st.c: new file.
+ * gdb.base/call-rt-st-exp: new file.
+ * gdb.base/call-strs.exp: new file.
+ * gdb.base/ena-dis-br.exp: new file.
+ * gdb.base/environ.exp: new file.
+ * gdb.base/long_long.exp: new file.
+ * gdb.base/sect-cmd.exp: new file.
+ * gdb.base/shlib-cl2.exp: new file.
+ * gdb.base/smoke.exp: new file.
+ * gdb.base/so-impl-ld.c: new file.
+ * gdb.base/so-impl-ld.exp: new file.
+ * gdb.base/so-indr-cl.c: new file.
+ * gdb.base/so-indr-cl.exp: new file.
+ * gdb.base/varargs.exp: new file.
+ * gdb.base/volatile.exp: new file.
+ * gdb.base/whatis-exp.exp: new file.
+ * gdb.c++/derivation.exp: new file.
+ * gdb.c++/local.exp: new file.
+ * gdb.c++/member-ptr.exp: new file.
+ * gdb.c++/overload.exp: new file.
+ * gdb.c++/ovldbreak.exp: new file.
+ * gdb.c++/ref-types.exp: new file.
+ * gdb.c++/ref-types2.exp: new file.
+ * gdb.c++/userdef.exp: new file.
+
+Wed Jan 6 13:50:57 1999 Stan Shebs <shebs@andros.cygnus.com>
+
+ * gdb.base/default.exp: Reflect wording change in remote.c.
+
+Tue Jan 5 19:14:51 1999 Michael Snyder <msnyder@cleaver.cygnus.com>
+
+ * gdb.base/help.exp: Update to reflect current text.
+
+Tue Jan 5 13:05:32 1999 David Taylor <taylor@texas.cygnus.com>
+
+ * gdb.c++/anon-union.cc: make foo and bar global, otherwise
+ they're stack variables and contain garbage.
+ * gdb.c++/anon-union.exp: new file.
+
+ The following changes were made by David Taylor
+ <taylor@cygnus.com>, Elena Zannoni <ezannoni@cygnus.com>, and
+ Edith Epstein <eepstein@cygnus.com> as part of a project to merge
+ in changes by HP.
+
+ * gdb.base/bitops.exp: new file.
+ * gdb.base/default.exp: change expected messages for catch and
+ info catch tests to reflect HP merge changes.
+ * gdb.base/enable-disable-break.exp
+ * gdb.base/ending-run.c: new file.
+ * gdb.base/long_long.c: new file.
+ * gdb.base/maint.exp: new file.
+ * gdb.base/pointers2.exp: new file.
+ * gdb.base/shlib-call2.exp: new file.
+ * gdb.base/solib.exp: new file.
+ * gdb.base/step-test.c: new file.
+ * gdb.c++/anon-union.cc: new file.
+ * gdb.c++/local.cc: new file.
+ * gdb.c++/member-pointer.cc: new file.
+ * gdb.c++/method.cc: new file.
+ * gdb.c++/ref-types.cc: new file.
+ * gdb.c++/ref-types2.cc: new file.
+ * gdb.c++/userdef.cc: new file.
+
+ * gdb.base/scope.exp: compile one file at a time, then link.
+ * gdb.base/langs.exp: ditto.
+ * gdb.base/list.exp: ditto.
+
+Mon Jan 4 10:06:43 1999 David Taylor <taylor@texas.cygnus.com>
+
+ The following changes were made by David Taylor
+ <taylor@cygnus.com>, Elena Zannoni <ezannoni@cygnus.com>, and
+ Edith Epstein <eepstein@cygnus.com> as part of a project to merge
+ in changes by HP.
+
+ * gdb.c++/inherit.exp: if on hppa*-*-hpux* and not using gcc,
+ skip tests. When compiling pass c++ flag to gdb_compile.
+ * gdb.c++/
+
+ * lib/gdb.exp (get_compiler_info): new, optional argument -- args;
+ test for on hppa*-*-hpux*; use args to see if c++ was specified.
+ (skip_hp_tests): new function.
+ (gdb_preprocess): new function.
+
+ * configure.in (hpdir): decide whether to configure gdb.hp.
+ * configure: regenerated.
+
+ * gdb.base/Makefile.in (MISCELLANEOUS): new macros -- extra things
+ to delete on clean.
+ (EXECUTABLES): update to reflect new additions.
+ * gdb.base/commands.exp: update message expected.
+ * gdb.base/default.exp: add copyright notice.
+ * gdb.base/funcargs.exp (timeout): if hpux, increase timeout.
+ * gdb.base/help.exp: update messages to reflect current text.
+ * gdb.base/recurse.exp: add hpppa*-*-bsd* to 'list' of enabled
+ targets for recurse tests.
+ * gdb.base/watchpoint.exp: if on hpux and not gcc compiled, then
+ skip this file.
+
+ * gdb.c++/Makefile.in (PROGS): update to reflect new executables.
+ * gdb.c++/cplusfuncs.exp: tell gdb_compile that it's a c++
+ compilation.
+ * gdb.c++/misc.exp: ditto.
+ * gdb.c++/templates.exp: if we're on hpux and it's not gcc, don't
+ run the tests. tell gdb_compile that it's a c++ compilation.
+
+ * gdb.threads/pthreads.exp: fix typo in message.
+
+ * gdb.base/all-bin.exp: new file.
+ * gdb.base/arithmet.exp: new file.
+ * gdb.base/assign.exp: new file.
+ * gdb.base/completion.exp: new file.
+ * gdb.base/cond-expr.exp: new file.
+ * gdb.base/condbreak.exp: new file.
+ * gdb.base/define.exp: new file.
+ * gdb.base/dollar.exp: new file.
+ * gdb.base/environment.exp: new file.
+ * gdb.base/eval-skip.exp: new file.
+ * gdb.base/jump.exp: new file.
+ * gdb.base/logical.exp: new file.
+ * gdb.base/pointers.exp: new file.
+ * gdb.base/relational.exp: new file.
+ * gdb.base/section_command.exp: new file.
+ * gdb.base/whatis-expr.exp: new file.
+
+ * gdb.base/all-types.c: new file.
+ * gdb.base/call-array-struct.c: new file.
+ * gdb.base/call-return-struct.c: new file.
+ * gdb.base/call-strings.c: new file.
+ * gdb.base/callfuncs2.c: new file.
+ * gdb.base/condbreak.c: new file.
+ * gdb.base/constvars.c: new file.
+ * gdb.base/display.c: new file.
+ * gdb.base/int-type.c: new file.
+ * gdb.base/jump.c: new file.
+ * gdb.base/miscexprs.c: new file.
+ * gdb.base/pointers.c: new file.
+ * gdb.base/pointers2.c: new file.
+ * gdb.base/shmain.c: new file.
+ * gdb.base/shr1.c: new file.
+ * gdb.base/shr2.c: new file.
+ * gdb.base/solib.c: new file.
+ * gdb.base/solib1.c: new file.
+ * gdb.base/solib2.c: new file.
+ * gdb.base/varargs.c: new file.
+ * gdb.c++/derivation.cc: new file.
+ * gdb.c++/overload.cc: new file.
+ * gdb.c++/ovldbreak.cc: new file.
+ * gdb.hp/attach.c: new file.
+ * gdb.hp/attach2.c: new file.
+ * gdb.hp/average.c: new file.
+ * gdb.hp/compiler.c: new file.
+ * gdb.hp/compiler.cc: new file.
+ * gdb.hp/execd-program.c: new file.
+ * gdb.hp/follow-exec.c: new file.
+ * gdb.hp/follow-fork.c: new file.
+ * gdb.hp/follow-vfork-and-exec.c: new file.
+ * gdb.hp/misc-hp.cc: new file.
+ * gdb.hp/more-steps.c: new file.
+ * gdb.hp/optimize.c: new file.
+ * gdb.hp/quicksort.c: new file.
+ * gdb.hp/run-hp.c: new file.
+ * gdb.hp/start-stop.c: new file.
+ * gdb.hp/sum.c: new file.
+ * gdb.hp/templates-hp.cc: new file.
+ * gdb.hp/thread-local-in-lib.c: new file.
+ * gdb.hp/thread-local-in-lib.h: new file.
+ * gdb.hp/thread-local-in-lib.lib.c: new file.
+ * gdb.hp/vforked-program.c: new file.
+ * gdb.hp/virtfunc-hp.cc: new file.
+ * gdb.hp/watchpoint-hp.c: new file.
+ * gdb.hp/xdb.c: new file.
+ * gdb.hp/xdb0.c: new file.
+ * gdb.hp/xdb0.h: new file.
+ * gdb.hp/xdb1.c: new file.
+
+Mon Dec 21 14:08:38 1998 David Taylor <taylor@texas.cygnus.com>
+
+ The following change was made by Edith Epstein
+ <eepstein@cygnus.com> as part of a project to merge in changes
+ originally made by HP; HP did not create ChangeLog entries.
+
+ * gdb.c++/demangle.exp: changed the expected output for some
+ ARM-style mangling -- removed second reference to datatype.
+ For example, maint demangle __dt__11T1__pt__2_cFv
+ T1<char>::~T1<char>(void)
+ becomes,
+ maint demangle __dt__11T1__pt__2_cFv
+ T1<char>::~T1(void)
+
+ (test_hp_style_demangling): new hp specific demangling test cases.
+
+Mon Dec 14 15:07:03 1998 Jeffrey A Law (law@cygnus.com)
+
+ * gdb.trace/actions.exp: Ignore compiler warnings compiling actions.c
+ * gdb.trace/backtrace.exp: Likewise.
+ * gdb.trace/circ.exp: Likewise.
+ * gdb.trace/collection.exp: Likewise.
+ * gdb.trace/deltrace.exp: Likewise.
+ * gdb.trace/infotrace.exp: Likewise.
+ * gdb.trace/limits.exp: Likewise.
+ * gdb.trace/packetlen.exp: Likewise.
+ * gdb.trace/passc-dyn.exp: Likewise.
+ * gdb.trace/passcount.exp: Likewise.
+ * gdb.trace/report.exp: Likewise.
+ * gdb.trace/save-trace.exp: Likewise.
+ * gdb.trace/tfind.exp: Likewise.
+ * gdb.trace/tracecmd.exp: Likewise.
+ * gdb.trace/while-dyn.exp: Likewise.
+ * gdb.trace/while-stepping.exp: Likewise.
+
+1998-12-07 Jim Blandy <jimb@zwingli.cygnus.com>
+
+ * gdb.base/restore.exp, gdb.base/restore.c: New tests.
+
+Wed Dec 2 20:03:53 1998 Stan Shebs <shebs@andros.cygnus.com>
+
+ From Brendan Kehoe:
+ * gdb.c++/cplusfuncs.cc, misc.cc, virtfunc.cc: Add now-required
+ int return types.
+
+Sat Oct 24 18:04:22 1998 Felix Lee <flee@cygnus.com>
+
+ * config/slite.exp (gdb_load): use gdb_file_cmd, so we can do
+ remote dos host testing right.
+
+Mon Oct 19 01:31:59 1998 Felix Lee <flee@cygnus.com>
+
+ * gdb.base/corefile.exp: remove some xfails.
+
+Thu Oct 15 10:04:38 1998 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * gdb.base/reread.exp: Sleep 1 - ensures that the two executables
+ have different timestamps.
+
+Thu Oct 1 20:56:14 1998 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * lib/gdb.exp, gdb.base/default.exp, config/monitor.exp,
+ gdb.base/default.exp: Replace "exec" with "executable".
+
+Tue Sep 29 15:06:29 1998 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * gdb.base/default.exp: Change else if to elseif from previous
+ delta.
+
+Mon Sep 28 13:21:43 1998 Nick Clifton <nickc@cygnus.com>
+
+ * gdb.base/default.exp: Add brace missing from previous delta.
+
+Mon Sep 21 14:39:27 1998 Nick Clifton <nickc@cygnus.com>
+
+ * gdb.base/default.exp: Support test for info float for all
+ varieties of arm toolchain.
+
+Fri Sep 18 14:07:44 1998 Michael Snyder <msnyder@cleaver.cygnus.com>
+
+ * gdb.trace/*.exp: remove "remote_download" command.
+
+Wed Sep 16 11:38:21 1998 Michael Snyder <msnyder@cleaver.cygnus.com>
+
+ * gdb.trace/*.exp: remove -gdwarf from compile.
+
+Wed Sep 16 01:23:11 1998 Felix Lee <flee@cygnus.com>
+
+ * gdb.trace/configure.in(AC_INIT): typo
+ * gdb.trace/configure: regenerated
+
+Mon Sep 14 20:00:04 1998 Michael Snyder <msnyder@cleaver.cygnus.com>
+
+ * config/m68k-emc.exp: New file.
+ * lib/<emc-support.exp trace-support.exp}: New files.
+ * configure.in: add new test directory gdb.trace.
+ * gdb.trace/{configure configure.in Makefile.in}: New files.
+ * gdb.trace/{actions.c actions.exp gdb_c_test.c}: New files.
+ * gdb.trace/{circ.c circ.exp limits.c limits.exp}: New files.
+ * gdb.trace/{collection.c collection.exp tfind.exp }: New files.
+ * gdb.trace/{backtrace.exp deltrace.exp infotrace.exp}: New files.
+ * gdb.trace/{packetlen.exp passc-dyn.exp passcount.exp}: New files.
+ * gdb.trace/{report.exp save-trace.exp tracecmd.exp}: New files.
+ * gdb.trace/{while-dyn.exp while-stepping.exp}: New files.
+
+Fri Sep 11 13:58:02 1998 Michael Snyder <msnyder@cleaver.cygnus.com>
+
+ * gdb.c++/classes.exp: Change all regular expressions to match
+ arbitrary combinations of newline/carriage-return, so that they
+ will work equally well on Unix and Windows.
+ * gdb.c++/inherit.exp: ditto.
+ * gdb.c++/virtfunc.exp: ditto.
+
+1998-08-11 Dawn Perchik <dawn@cygnus.com>
+
+ * gdb.base/setshow.exp: Fix error introduced by call to runto_main.
+
+1998-07-11 Felix Lee <flee@cygnus.com>
+
+ * gdb.base/callfuncs.exp: add cmp10 test.
+ * gdb.base/callfuncs.c (cmp10): new function.
+
+Thurs Jul 9 11:08:31 1998 Dawn Perchik <dawn@cygnus.com>
+
+ * gdb.base/commands.exp: Break up infrun_breakpoint_command_test
+ into two parts to get around a synchronization problem in expect.
+
+Fri Jun 26 14:52:47 1998 Peter Schauer <pes@regent.e-technik.tu-muenchen.de>
+
+ * gdb.fortran/types.exp: Escape brackets in expect patterns
+ for test_float_literal_types_accepted tests.
+ * gdb.base/scope.exp: Remove extraneous newline in filelocal_bss
+ before run test.
+
+1998-06-25 Felix Lee <flee@cygnus.com>
+
+ * gdb.base/setshow.exp: make sure $pc is sane.
+
+ * gdb.stabs/weird.exp: split expect patterns properly.
+
+Tue Jun 23 11:45:01 1998 Michael Snyder <msnyder@cleaver.cygnus.com>
+
+ * gdb.base/funcargs.exp: simplify expect strings to ease pattern
+ match processing (and eliminate spurious timeouts when running).
+
+Fri Jun 12 17:28:22 1998 Michael Snyder <msnyder@cleaver.cygnus.com>
+
+ * gdb.base/signals.exp (test_handle_all_print): put back Mach
+ exception test, but conditionalize it on target [mach | gnu].
+
+Wed Jun 10 10:40:03 1998 Michael Snyder <msnyder@cleaver.cygnus.com>
+
+ * gdb.base/overlays.exp: fixup compile line for linker script.
+
+Thu Jun 4 21:54:15 1998 Felix Lee <flee@zog.cygnus.com>
+
+ * gdb.fortran/types.exp: don't guess at float size.
+
+Thu May 21 02:28:37 1998 Felix Lee <flee@zog.cygnus.com>
+
+ * gdb.base/exprs.exp: delete test that depends on int size.
+
+Sun May 17 17:10:22 1998 Bob Manson <manson@charmed.cygnus.com>
+
+ * config/sim.exp: Removed checks for target triplets.
+ (gdb_target_sim): Use gdb,target_sim_options.
+
+Sat May 16 23:43:35 1998 Mark Alexander <marka@cygnus.com>
+
+ * gdb.base/reread.exp: New file.
+ * gdb.base/reread1.c: New file.
+ * gdb.base/reread2.c: New file.
+
+Sat May 16 23:22:09 1998 Mark Alexander <marka@cygnus.com>
+
+ * config/sim.exp: Use 'target sim -sparclite' when running
+ SPARClite programs.
+
+Sat May 16 18:48:08 1998 Doug Evans <devans@canuck.cygnus.com>
+
+ * gdb.base/structs2.exp: New file.
+ * gdb.base/structs2.c: New file.
+
+Wed May 13 13:36:14 1998 Doug Evans <devans@canuck.cygnus.com>
+
+ * gdb.asm/common.inc: New file.
+ * gdb.asm/d10v.inc: New file.
+ * asm-source.exp: Pass -I's to gas to find .inc files.
+ Update line numbers in expected output.
+ * asmsrc1.s: Rewrite.
+ * asmsrc2.s: Rewrite.
+ * configure.in: Create arch.inc symlink.
+ * configure: Regenerate.
+ * Makefile.in (distclean): Delete arch.inc.
+
+Wed May 6 10:30:54 1998 John Metzler <jmetzler@cygnus.com>
+
+ * callfuncs.c (t_enum_value1) : Cleanup return value warnings
+ (t_enum_value2): ditto
+ (t_enum_value3): ditto
+ (main): ditto
+Fri May 1 09:33:37 1998 Peter Schauer <pes@regent.e-technik.tu-muenchen.de>
+
+ * gdb.base/break.exp: Remove xfail for `deleting all breakpoints
+ when none' unexpected prompt case, fixed by breakpoint.c:delete_command
+ change.
+ Use gdb_test instead of send_gdb/gdb_expect sequences.
+
+Thu Apr 23 12:56:19 1998 Jason Molenda (crash@bugshack.cygnus.com)
+
+ * gdb.c++/virtfunc.cc: Declare extern "C" printf to return int,
+ not void.
+
+Thu Apr 16 10:52:34 1998 John Metzler <jmetzler@cygnus.com>
+
+ * gdb.base/branches.c: Code with lots of loops and
+ subroutines. Used to test gdbs ability to single step through PC
+ changes, especially to test mips-tdep.c:mips_next_pc
+
+Mon Apr 13 22:32:51 1998 Frank Ch. Eigler <fche@cygnus.com>
+
+ * gdb.c++/virtfunc.cc: Make extern "C" printf declaration pass
+ more rigorous EGCS C++ error checking.
+
+Fri Apr 10 22:38:12 1998 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * gdb.base/help.exp: Clean up `help set args' and `help show args'
+ tests.
+ * gdb.base/interrupt.exp: Add "i*86-*-solaris2*" xfail for calling
+ function when asleep.
+ * gdb.base/signals.exp: Add "i*86-*-solaris2*" xfails. Add comment
+ for i*86 Linux and SVR4 signal handling problems.
+ Remove linux xfail for `next to handler in signals_tests_1', fixed
+ by recent infrun.c change.
+ Limit backtrace to 10 frames to avoid timeout problems with infinite
+ stack backtraces.
+ Adjust expect pattern in `handle all print' test to match Apr 28 1997
+ target.[ch] change.
+
+Tue Mar 31 00:40:32 1998 Bob Manson <manson@charmed.cygnus.com>
+
+ * lib/gdb.exp(gdb_test): Send multiline commands one at a time; wait
+ for a newline from gdb before continuing.
+ (default_gdb_exit): Just look for y or n.
+ (gdb_test): Detect abnormal exit from GDB running on DOS; if
+ it does, fail the rests of the tests in the file.
+
+Tue Mar 24 22:44:52 1998 Bob Manson <manson@charmed.cygnus.com>
+
+ * config/cygmon.exp: New file.
+
+Mon Mar 16 21:39:11 1998 Bob Manson <manson@charmed.cygnus.com>
+
+ * gdb.base/list.exp: Fix problem with "list default lines around
+ main" test on remote targets.
+
+ * gdb.base/scope.exp: Fix problem with filelocal_bss before
+ run test on remote targets.
+
+Thu Mar 12 16:23:00 1998 Doug Evans <devans@canuck.cygnus.com>
+
+ * gdb.asm: New directory.
+ * configure.in: Configure it.
+ * configure: Regenerate.
+ * gdb.asm/{Makefile.in,configure.in,configure}: New files.
+ * gdb.asm/{asm-source.exp,asmsrc1.s,asmsrc2.s}: New files.
+
+Mon Feb 23 08:22:44 1998 Mark Alexander <marka@cygnus.com>
+
+ * config/mn10300-eval.exp: New file to support MN10300 eval board.
+
+Wed Feb 18 16:43:46 1998 Michael Snyder (msnyder@cleaver.cygnus.com)
+
+ * gdb.base/overlays (several files): Merge the two overlay
+ managers into one. Change variables (foox, barx, bazx, grbxx)
+ back into ints but force them to load in their proper sections.
+
+Thu Feb 12 13:49:30 1998 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * gdb.base/d10vovly.c (D10VTranslate): Map IMAP0 to low 128k of
+ on-chip insn memory and IMAP1 to upper 128k.
+ (D10VCopy): Handle memory regions crossing 16k boundaries.
+ (D10VCopy): Transfer data in 32 bit chunks.
+
+Tue Feb 10 17:23:22 1998 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * gdb.base/overlays.c (main): Exit normally when result is
+ correct.
+
+ * gdb.base/d10v.ld: Update LMAs to reflect current d10v address
+ map. Include space for printf in .text segment.
+
+ * gdb.base/d10vovly.c (D10VTranslate): New function, handle
+ updated d10v memory VMA/LMA map.
+ (D10VCopy): Call D10VTranslate.
+
+Fri Feb 6 14:13:12 1998 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * gdb.base/m32rovly.c: Force variable _novlys into .data section.
+
+ * gdb.base/bar.c (barx, bar): Change variable to small array so
+ that it won't be put into the .sdata - small data -
+ section. Update reference.
+ * gdb.base/baz.c (bazx, baz): Ditto.
+ * gdb.base/foo.c (foox, foo): Ditto.
+ * gdb.base/grbx.c (grbxx, grbx): Ditto.
+
+ * gdb.base/overlays.exp: Expect variables barx, bazx, foox, grbxx
+ to be arrays.
+
+Thu Jan 29 14:48:19 1998 Michael Snyder (msnyder@cleaver.cygnus.com)
+
+ * gdb.base/overlays.exp: fix up and get working again.
+ Add tests for backtraces from an overlay function.
+
+Fri Jan 23 07:52:45 1998 Fred Fish <fnf@cygnus.com>
+
+ * gdb.base/watchpoint.exp: Set "d10v*-*-*" clear_xfail for
+ "calling function with watchpoint enabled".
+
+Thu Jan 22 14:23:29 1998 Fred Fish <fnf@cygnus.com>
+
+ * gdb.base/break.exp (test_next_with_recursion): Remove
+ gdb_suppress_tests for d10v-*-*.
+ * lib/gdb.exp (gdb_suppress_tests): Disable this function
+ pending review of whether it is useful or not.
+
+Tue Jan 20 13:02:09 1998 Mark Alexander <marka@cygnus.com>
+
+ * gdb.base/funcargs.exp: Increase timeout for slow TX39 boards.
+
+Mon Jan 19 08:53:04 1998 Mark Alexander <marka@cygnus.com>
+
+ * gdb.base/break.exp: Increase timeout for slow TX39 boards.
+ * config/dve.exp: New file to support Densan boards.
+
+Mon Dec 15 22:38:05 1997 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * gdb.base/interrupt.exp: Document problem of simulators, signals,
+ reads and BSD.
+
+Wed Nov 26 22:29:18 1997 Bob Manson <manson@charmed.cygnus.com>
+
+ * config/monitor.exp: Be a bit less picky about the "Remote debugging"
+ response.
+
+ * gdb.c++/misc.exp: Call runto_main instead of doint it manually.
+
+Tue Nov 25 12:46:36 1997 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * gdb.base/mips_pro.exp: Add "mips64*-*-elf" xfail for backtrace
+ test.
+
+ * gdb.base/funcargs.exp: Query GDB for target_sizeof_int,
+ target_sizeof_long and target_bigendian_p.
+ (structs_by_value, structs_by_reference): Check values according
+ to targets word size and endianess.
+
+Mon Nov 24 16:37:06 1997 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * gdb.base/langs.exp: For "continue to exit" ignore any trailing
+ output.
+
+Fri Oct 17 13:24:43 1997 Stan Shebs <shebs@andros.cygnus.com>
+
+ * gdb.base/default.exp, gdb.base/help.exp, gdb.base/setshow.exp:
+ Update test of set args help to match source change.
+
+Fri Sep 26 17:36:20 1997 Jason Molenda (crash@pern.cygnus.com)
+
+ * gdb.base/default.exp: Expect help system output to be in
+ alphabetical order.
+ * gdb.base/help.exp: Ditto.
+
+Wed Sep 24 13:08:14 1997 Bob Manson <manson@charmed.cygnus.com>
+
+ * gdb.base/signals.exp: Change "i*86-pc-linux-gnu" to
+ "i*86-pc-linux-gnu*".
+ * gdb.base/interrupt.exp: Ditto.
+ * gdb.base/corefile.exp: Ditto.
+
+ * lib/gdb.exp(gdb_compile): If is_vxworks target feature is set,
+ define vxworks when building the testcase.
+
+ * gdb.base/ptype.exp: Fix testnames to be unique.
+ * gdb.base/radix.exp: Ditto.
+ * gdb.base/term.exp: Ditto.
+ * gdb.base/whatis.exp: Ditto.
+ * gdb.c++/classes.exp: Ditto.
+
+Tue Sep 16 22:21:48 1997 Bob Manson <manson@charmed.cygnus.com>
+
+ * gdb.base/callfuncs.exp: Fix indentation.
+
+ * lib/gdb.exp(gdb_expect): Set remote_suppress_flag if
+ suppress_flag has been set.
+ (gdb_step_for_stub): Check for gdb,use_breakpoint_for_stub
+ target feature.
+
+Mon Sep 15 15:43:17 1997 Bob Manson <manson@charmed.cygnus.com>
+
+ * gdb.stabs/weird.exp: Don't start gdb 'til after we've compiled
+ the testcase.
+
+ * gdb.c++/cplusfuncs.cc(main): Add extern "C" declaration for
+ set_debug_traps() and breakpoint().
+ * gdb.c++/misc.cc (main): Ditto.
+ * gdb.c++/templates.cc (main): Ditto.
+ * gdb.c++/virtfunc.cc (main): Ditto.
+
+Fri Sep 12 16:56:38 1997 Bob Manson <manson@charmed.cygnus.com>
+
+ * lib/gdb.exp(gdb_step_for_stub): New function.
+ (gdb_run_cmd): Look for gdb,do_reload_on_run target feature--if it
+ exists, reload the executable and do a "continue" instead of
+ doing a jump.
+ (runto_main): Use gdb_step_for_stub.
+
+ * gdb.base/break.exp: Use gdb_step_for_stub. Also, rename certain
+ tests to have unique names.
+ * gdb.base/callfuncs.exp: Ditto.
+ * gdb.base/commands.exp: Ditto.
+ * gdb.base/default.exp: Ditto.
+ * gdb.base/help.exp: Ditto.
+ * gdb.base/list.exp: Ditto.
+ * gdb.base/opaque.exp: Ditto.
+ * gdb.base/printcmds.exp: Ditto. Use a loop to emit multiple
+ similar tests.
+
+ * gdb.base/setshow.c: Add set_debug_traps/breakpoint calls.
+ * gdb.c++/cplusfuncs.cc: Ditto.
+ * gdb.c++/virtfunc.cc: Ditto.
+
+ * config/monitor.exp: Keep track of the last file we saw, rather
+ than trying to get the info from gdb.
+
+ * gdb.fortran/types.exp: Move comment to previous line.
+
+Tue Sep 2 19:55:34 1997 Bob Manson <manson@charmed.cygnus.com>
+
+ * config/sparclet.exp: Detect gratuitous change to sparclet gdb
+ target mode.
+
+Mon Jul 28 12:14:47 1997 Stan Shebs <shebs@andros.cygnus.com>
+
+ From Bob Manson:
+ * config/monitor.exp (gdb_target_monitor): Look for "Connected to"
+ string from GDB when it connects.
+
+ * lib/gdb.exp: Look for $TOOL_EXECUTABLE.
+
+Thu Jul 3 15:35:12 1997 Bob Manson <manson@charmed.cygnus.com>
+
+ * lib/gdb.exp(get_debug_format): Don't cause the testsuite to fail
+ if we can't get a debug format from GDB (we may be testing an
+ older GDB). Use a 10 second timeout when checking for the format.
+
+ * gdb.stabs/weird.exp: Fix quoting.
+
+ * config/sparclet.exp: Renamed sparclet-loader.c to stub-loader.c.
+
+Mon Jun 30 18:31:43 1997 Bob Manson <manson@charmed.cygnus.com>
+
+ * config/arm-ice.exp: New file.
+
+Sun Jun 29 16:43:30 1997 Bob Manson <manson@charmed.cygnus.com>
+
+ * gdb.base/overlays.exp: Preliminary fixes; temporarily disabled
+ until it has been modified to work with the new testsuite.
+
+ * gdb.*/*.exp: Instead of causing 1 unresolved test when the
+ testcase won't compile, cause all of the testcases in the file to
+ fail instead.
+
+ * lib/gdb.exp(gdb_suppress_entire_file): New procedure.
+ (gdb_clear_suppressed): New procedure.
+ (gdb_stop_suppressing_tests): Only clear suppress_flag if
+ it contains a positive value.
+
+Sat Jun 28 13:31:11 1997 Bob Manson <manson@charmed.cygnus.com>
+
+ * lib/gdb.exp(default_gdb_start): Use gdb_opts host feature.
+
+ * gdb.c++/virtfunc.exp: Remove setting of libs variable.
+
+Fri Jun 27 07:44:25 1997 Fred Fish <fnf@cygnus.com>
+
+ * lib/gdb.exp (setup_xfail_format): New function.
+ (get_debug_format): New function to get debug format.
+ (debug_format): New global variable to hold last value set
+ by get_debug_format.
+ * gdb.base/list.exp: Call get_debug_format and expect some
+ tests to fail for DWARF 1 and COFF formats.
+ * gdb.c++/ptype.exp: Ditto.
+ * gdb.c++/classes.exp: Ditto.
+ * gdb.c++/cplusfuncs.exp: Ditto.
+ * gdb.c++/inherit.exp: Ditto.
+ * gdb.c++/templates.exp: Ditto.
+ * gdb.c++/virtfunc.exp: Ditto.
+
+Wed Jun 25 09:08:51 1997 Bob Manson <manson@charmed.cygnus.com>
+
+ * lib/gdb.exp(default_gdb_exit): Don't give an error if the remote
+ host doesn't have a currently-open connection.
+
+ * config/sparclet.exp: Cleanups and fixes to make it generic for
+ any gdb stub target. Handle cases where gdb doesn't respond when
+ interrupted in a sane fashion.
+
+ * config/m32r-stub.exp: Load sparclet.exp instead of trying to do the
+ same thing in a totally different way.
+
+ * config/monitor.exp: Pass in timeouts to gdb_expect instead of
+ setting "timeout".
+ (gdb_start): We set the global gdb_prompt variable in
+ default_gdb_init now.
+
+Sun Jun 22 09:11:02 1997 Fred Fish <fnf@cygnus.com>
+
+ * gdb.base/printcmds.exp: Fix "check for floating addition"
+ regexp to accept results within approx +/- .01 of exact value.
+ * lib/gdb.exp (gdb_test): Remove unused expect_out global decl.
+
+Wed Jun 18 11:11:39 1997 Bob Manson <manson@charmed.cygnus.com>
+
+ * lib/gdb.exp(gdb_init): Pass our arguments to default_gdb_init
+ properly.
+ (gdb_expect): Add optional timeout parameter, and add timeout
+ value to various calls.
+ (gdb_suppress_tests): Only give one warning message per group.
+
+Tue Jun 17 13:10:10 1997 Bob Manson <manson@charmed.cygnus.com>
+
+ * lib/gdb.exp(gdb_expect): Declare errorInfo and errorCode as
+ global variables. Handle getting a value for $timeout more
+ gracefully.
+
+Sat Jun 14 09:23:26 1997 Bob Manson <manson@charmed.cygnus.com>
+
+ * lib/gdb.exp: Close connection to remote host if gdb doesn't
+ initialize.
+ (default_gdb_init): New procedure; allow gdb_init to be overridden
+ by a target configuration file.
+ (gdb_expect): Pass the timeout to remote_expect.
+
+ * config/monitor.exp(gdb_load): Fix typo in regexp.
+
+Thu Jun 12 20:57:12 1997 Bob Manson <manson@charmed.cygnus.com>
+
+ * gdb.base/funcargs.exp: Remove spurious suppress tests call.
+
+Tue Jun 3 15:20:20 1997 Bob Manson <manson@charmed.cygnus.com>
+
+ * config/monitor.exp(gdb_target_monitor): Call gdb_file_cmd
+ here. Call gdb_target_exec before rebooting the target, to make
+ sure the connection to the target is closed.
+ (gdb_load): Pass the name of the executable to gdb_target_monitor.
+ Don't call gdb_file_cmd here; let gdb_target_monitor do it.
+ Also detect "Timeout reading from remote" error.
+
+ * config/gdbserver.exp: Pass the executable being loaded to
+ gdb_target_monitor. Don't call gdb_file_cmd here; let
+ gdb_target_monitor do it.
+
+ * gdb.disasm/hppa.exp: Don't use exec_output.
+
+Fri May 23 13:28:29 1997 Bob Manson <manson@charmed.cygnus.com>
+
+ * gdb.base/list.exp: If we're debugging a non-native target,
+ try to set the pc register to point to the start of the
+ program before doing the first list command.
+
+ * gdb.c++/virtfunc.exp(gdb_virtfunc_restart): Make sure we run
+ test_calls after restarting.
+
+ * lib/gdb.exp(gdb_run_cmd): Send jump command again after
+ reloading.
+
+ * gdb.base/watchpoint.exp: Fix typo.
+
+ * gdb.base/setshow.exp: Check for use_gdb_stub.
+
+ * gdb.base/break.exp: Fix continue until exit test for the gdb
+ stub case.
+ * gdb.base/langs.exp: Ditto.
+
+ * config/monitor.exp(gdb_load): Handle gdb_sect_offset and
+ gdb_load_offset. If we weren't given a file to load, figure out
+ what the current file is and use it.
+
+ * config/i386-bozo.exp: New file.
+
+Thu May 22 18:51:32 1997 Bob Manson <manson@charmed.cygnus.com>
+
+ * lib/gdb.exp(gdb_expect): Look for gdb,timeout target
+ feature.
+
+ * config/proelf.exp: New entry.
+
+Wed May 21 21:23:16 1997 Bob Manson <manson@charmed.cygnus.com>
+
+ * lib/gdb.exp: Remove spurious .* patterns at the beginning
+ of regexps.
+
+ * gdb.base/watchpoint.exp: Don't run the test_stepping
+ tests if gdb can't call functions on the target.
+
+ * gdb.base/setshow.exp: Don't run the set prompt tests if
+ the board has gdb_prompt set.
+
+Tue May 20 08:58:49 1997 Jeffrey A Law (law@cygnus.com)
+
+ * gdb.base/a2-run.exp: Change "gdb,noargs" to just "noargs".
+ * gdb.base/commands.exp: Likewise.
+ * gdb.base/setshow.exp: Likewise.
+
+Mon May 19 15:37:50 1997 Bob Manson <manson@charmed.cygnus.com>
+
+ * config/monitor.exp(gdb_start): Look for gdb_prompt target
+ feature.
+
+ * config/i960.exp: New file.
+
+Thu May 1 18:01:50 1997 Bob Manson <manson@charmed.cygnus.com>
+
+ * gdb.base/funcargs.exp: Check for gdb,short_int target
+ feature instead of looking for explicit target triplets.
+
+Mon Apr 28 17:27:40 1997 Michael Snyder <msnyder@cleaver.cygnus.com>
+
+ * gdb.base/printcmds.exp: add a couple more tests a la
+ "p 123DEADBEEF", to check parse_number.
+ * top.c: change "to enable to enable" to "to enable" in a couple
+ of help strings.
+
+Thu Apr 24 14:38:18 1997 Jeffrey A Law (law@cygnus.com)
+
+ * gdb.base/callfuncs.exp: Mark some tests as expected to fail
+ on the mn10300.
+
+Mon Apr 21 15:05:42 1997 Fred Fish <fnf@cygnus.com>
+
+ * gdb.base/a2-run.exp: Add arm-*-coff setup_xfails for cases
+ where the test executable is run with explicit args.
+ * gdb.base/default.exp: Handle arm-*-coff case for "info float".
+
+Mon Apr 21 13:38:58 1997 Fred Fish <fnf@cygnus.com>
+
+ * gdb.base/run.c: Use FAKEARGV to build test executable that
+ does not require a command line arg, since most simulators
+ don't currently support passing such an arg into the simulated
+ program.
+ * gdb.base/commands.exp: Change tests to insert the proper
+ value as the arg to the first recursive factorial call. Change
+ compilation line to define FAKEARGV at compile time.
+
+Wed Apr 9 11:12:36 1997 Jeffrey A Law (law@cygnus.com)
+
+ * gdb.base/recurse.exp: Enable these tests for the mn10300.
+ * gdb.base/watchpoint.exp: Don't expect a failure for an "calling
+ function with watchpoint enabled" test.
+
+Tue Apr 8 19:33:20 1997 Bob Manson <manson@charmed.cygnus.com>
+
+ * gdb.base/watchpoint.exp(test_watchpoint_triggered_in_syscall):
+ Don't call gdb_test when the command doesn't return to a gdb prompt.
+
+ * lib/gdb.exp(gdb_stop_suppressing_tests): Don't print gratuitous
+ "Tests restarted" messages.
+
+Tue Apr 8 16:38:46 1997 Jeffrey A Law (law@cygnus.com)
+
+ * gdb.disasm/mn10300.exp: Fix buglets in "other" tests.
+
+Thu Apr 3 15:21:26 1997 Michael Snyder <msnyder@cleaver.cygnus.com>
+
+ * gdb.base/help.exp: update help msg for INFO ADDR; add help test
+ for INFO SYMBOL; add help tests for OVERLAY commands.
+ * gdb.base/default.exp: add tests for INFO SYMBOL command;
+ add tests for OVERLAY commands
+ * gdb.base/overlays.c overlays.exp foo.c bar.c baz.c grbx.c ovlymgr.h
+ d10v.ld m32r.ld d10vovly.c m32rovly.c: add test case for overlays.
+ * gdb.base/sigall.c: add usestubs code frag
+ * gdb.base/watchpoint.exp: turn on complex watchpoint test for M32R.
+
+Thu Apr 3 09:38:53 1997 Bob Manson <manson@charmed.cygnus.com>
+
+ * lib/gdb.exp(gdb_suppress_tests): Add explanation for subsequent
+ failures.
+ (gdb_stop_suppressing_tests): Note that tests have restarted.
+
+Wed Apr 2 19:04:20 1997 Bob Manson <manson@charmed.cygnus.com>
+
+ * config/h8300.exp: New file.
+
+Sun Mar 30 13:38:25 1997 Bob Manson <manson@charmed.cygnus.com>
+
+ * gdb.base/setshow.exp: Check for the existence of a
+ feature, not its value.
+
+Sat Mar 29 11:19:46 1997 Bob Manson <manson@charmed.cygnus.com>
+
+ * gdb.c++/virtfunc.exp: Restart gdb in a sane fashion.
+
+ * gdb.base/scope.exp: It's now init0(), not init().
+
+ * gdb.base/scope0.c: For now, change init() to be init0().
+
+ * config/monitor.exp: Use gdb_serial in preference to serial
+ or netport.
+
+ * lib/gdb.exp: Set GDB to [transform gdb] if we're using a remote host
+ and it's not already set.
+
+Fri Mar 28 19:54:18 1997 Bob Manson <manson@charmed.cygnus.com>
+
+ * gdb.base/setshow.exp: Only test the run command if the target
+ isn't using a stub and if it supports argument passing.
+
+Sat Mar 22 19:50:25 1997 Bob Manson <manson@charmed.cygnus.com>
+
+ * config/udi.exp(gdb_start): Make sure UDICONF is set
+ properly before starting gdb.
+
+Mon Mar 24 14:40:33 1997 Jeffrey A Law (law@cygnus.com)
+
+ * gdb.disasm/mn10300.s: New test file for mn10300 disassembler.
+ * gdb.disasm/mn10300.exp: Run mn10300 disassembler tests.
+ * gdb.disasm/Makefile.in: Remove "mn10300" when cleaning.
+
+Tue Mar 11 11:42:58 1997 Bob Manson <manson@charmed.cygnus.com>
+
+ * config/vx.exp: Use remote_ld, not vxworks_ld. Don't use
+ specialized code to reboot the board, use remote_reboot instead.
+
+ * config/vxworks29k.exp: Use vx.exp, not vx-gdb.exp.
+
+ * lib/gdb.exp: Add GDB_TESTCASE_OPTIONS.
+
+ * config/monitor.exp: Make sure we disconnect from the target.
+ Also, try a reboot/reload cycle instead of failing if the
+ load fails.
+
+Fri Mar 7 13:48:30 1997 Bob Manson <manson@charmed.cygnus.com>
+
+ * gdb.base/default.exp: Don't set match_max.
+ * gdb.base/help.exp: Ditto.
+ * gdb.base/list.exp: Ditto.
+ * gdb.base/signals.exp: Ditto.
+
+ * config/monitor.exp(gdb_load): If gdb,use_standard_load is
+ set, use remote_ld to download the testcase instead of
+ the GDB loader.
+
+Wed Mar 5 00:00:43 1997 Bob Manson <manson@charmed.cygnus.com>
+
+ * config/vr5000.exp: New file.
+
+ * config/monitor.exp(gdb_target_monitor): Add pattern for
+ "Ending remote" to detect errors in connecting.
+
+ * gdb.base/setshow.exp: Add .* within auto language test.
+
+ * lib/gdb.exp(gdb_run_cmd): Add check for gdb_init_command
+ target feature.
+
+ * config/monitor.exp(gdb_load): Check for a failure when loading,
+ and reboot the board if necessary.
+
+ * gdb.base/setvar.exp(test_set): Handle multiple prints within
+ a set of tests. Remove print.* from the patterns being checked.
+
+Mon Mar 3 11:57:43 1997 Bob Manson <manson@charmed.cygnus.com>
+
+ * gdb.base/a1-selftest.exp: Use send_gdb consistently. Don't
+ refer to gdb_spawn_id.
+
+ * config/m32r-stub.exp: Remove references to gdb_spawn_id, no
+ longer used.
+ * config/sparclet.exp: Ditto.
+ * config/sparclet-old.exp: Ditto.
+ * config/slite.exp: Ditto.
+ * config/sim.exp: Ditto.
+ * gdb.base/funcargs.exp: Ditto.
+
+ * lib/gdb.exp:Remove references to gdb_spawn_id.
+ (gdb_expect): Move to remote.exp.
+
+Fri Feb 28 20:47:39 1997 Bob Manson <manson@charmed.cygnus.com>
+
+ * config/monitor.exp: Detect the "Couldn't establish connection"
+ message from GDB.
+
+Tue Feb 25 14:08:55 1997 Bob Manson <manson@charmed.cygnus.com>
+
+ * gdb.base/bitfields.exp: Use runto instead of explicit
+ gdb_run_cmd/gdb_expect sequences.
+
+ * gdb.base/break.exp(text_next_with_recursion): Add match for
+ gdb_expect call.
+
+ * config/monitor.exp(gdb_target_monitor): Calling exit loses big.
+ We also need to handle the "A program is being debugged already"
+ prompt from gdb. Use gdb_test to set the baud rate.
+
+ * lib/gdb.exp(gdb_init): Increase the default expect buffer size
+ to 20000. Really. I mean it.
+
+Mon Feb 24 13:23:26 1997 Bob Manson <manson@charmed.cygnus.com>
+
+ * lib/gdb.exp(gdb_test): Generate a FAIL message when send_gdb
+ fails. If suppress_flag is set, skip perror message about not
+ being able to send to GDB.
+ (send_gdb): If suppress_flag is set, don't try to send commands to
+ GDB.
+ (gdb_expect): If suppress_flag is set, always fail immediately.
+ (gdb_suppress_tests, gdb_stop_suppressing_tests): New functions.
+ (gdb_init): Call gdb_stop_suppressing_tests.
+ (default_gdb_exit): Ditto.
+ (default_gdb_start): Ditto.
+
+ * gdb.base/bitfields.exp: Call gdb_suppress_tests and
+ gdb_stop_suppressing_tests as appropriate.
+ * gdb.base/break.exp: Ditto.
+ * gdb.base/callfuncs.exp: Ditto.
+ * gdb.base/commands.exp: Ditto.
+ * gdb.base/exprs.exp: Ditto.
+ * gdb.base/funcargs.exp: Ditto.
+ * gdb.base/list.exp: Ditto.
+ * gdb.base/recurse.exp: Ditto.
+ * gdb.base/scope.exp: Ditto.
+ * gdb.base/structs.exp: Ditto.
+ * gdb.c++/inherit.exp: Ditto.
+
+Sun Feb 23 19:56:02 1997 Bob Manson <manson@charmed.cygnus.com>
+
+ * config/vr4300.exp: New file.
+
+ * gdb.*/*.exp: Call gdb_expect instead of expect.
+
+ * lib/gdb.exp(gdb_expect): New function.
+
+Thu Feb 20 13:57:01 1997 Bob Manson <manson@charmed.cygnus.com>
+
+ * lib/gdb.exp(gdb_init): New function.
+
+ * gdb.base/setvar.exp(test_set): Don't bother printing a PASS/FAIL
+ for each individual variable set.
+
+ * gdb.base/exprs.exp(test_expr): Make sure each test gets a unique
+ name.
+
+ * gdb.base/help.exp: Fix the syntax of a few gdb_test calls.
+
+ * gdb.base/scope.exp: Use gdb_test.
+
+ * gdb.base/ptype.exp: Don't call "gdb_exit; gdb_start" if we're
+ aborting; the testsuite driver will do that for us (see
+ gdb_finish). Also, use gdb_test in a few more places.
+
+Thu Feb 20 13:32:24 1997 Stan Shebs <shebs@andros.cygnus.com>
+
+ * gdb.base/help.exp: Fix syntax of "help info all-registers" test.
+
+Thu Feb 20 10:34:21 1997 Jeffrey A Law (law@cygnus.com)
+
+ * gdb.disasm/mn10200.s: Add "nop" after "main" so that "main"
+ and "add_tests" are not at the same address.
+
+Fri Feb 14 18:47:23 1997 Bob Manson <manson@charmed.cygnus.com>
+
+ * gdb.base/ptype.exp: Use gdb_test.
+
+Thu Feb 13 16:09:36 1997 Jeffrey A Law (law@cygnus.com)
+
+ * gdb.disasm/mn10200.s (misc_tests): Fix targets for "jsr" insns.
+ * gdb.disasm/mn10200.exp (misc_tests): Remove bogus line accidentally
+ left in. No longer expect them to fail.
+
+ * gdb.stabs/*.mt; Deleted, no longer used.
+ * gdb.stabs/configure.in: Remove references to target makefile
+ frags.
+ * gdb.stabs/configure: Rebuilt.
+
+ * gdb.disasm/*.mt: Deleted, no longer used.
+ * gdb.disasm/configure.in: Remove references to target makefile
+ frags. Use "sh3.s" as the unique filename for this directory.
+ * gdb.disasm/configure: Rebuilt.
+
+ * gdb.disasm/mn10200.s: New test file for mn10200 disassembler.
+ * gdb.disasm/mn10200.exp: Run mn10200 disassembler tests.
+ * gdb.disasm/Makefile.in: Remove "mn10200" when cleaning.
+
+Tue Feb 11 16:57:58 1997 Bob Manson <manson@charmed.cygnus.com>
+
+ * config/udi.exp: Use mondfe,name instead of remote_host.
+
+Tue Feb 11 11:22:36 1997 Jeffrey A Law (law@cygnus.com)
+
+ * gdb.base/watchpoint.exp: Don't expect a failure when calling
+ a function with a watchpoint enabled on the mn10200.
+
+ * gdb.stabs/weird.exp: Don't quit if "weird.s" doesn't exist
+ before trying to create it!
+
+Mon Feb 10 16:40:47 1997 Bob Manson <manson@charmed.cygnus.com>
+
+ * config/vx.exp: Use hostname instead of netport.
+
+ * config/vxworks.exp: New file.
+
+ * gdb.base/a2-run.exp: Change vxworks cases to use gdb_spawn_id.
+
+ * config/monitor.exp(gdb_target_monitor): Look for a prompt from
+ gdb before assuming everything worked. Send a ^C if a timeout
+ occurs.
+
+ * lib/gdb.exp(gdb_test): Check the result of send_gdb. Use
+ $gdb_spawn_id directly.
+ (gdb_run_cmd): Try _start as well as start. Use the target feature
+ gdb,start_symbol as the symbol to start from when jumping.
+
+Mon Feb 10 11:26:59 1997 Jeffrey A Law (law@cygnus.com)
+
+ * gdb.base/exprs.exp: Delete bogus/incorrect (and probably
+ redundant) test.
+
+ * gdb.base/recurse.exp: Relax final value test for 'b' so that
+ it doesn't lose for 16bit integer systems.
+
+Fri Feb 7 09:31:21 1997 Jeffrey A Law (law@cygnus.com)
+
+ * gdb.fortran/types.exp: If the target doesn't support "double"
+ data types, then expect "real" types to only be 4 bytes.
+
+ * gdb.c++/virtfunc.exp: Expect failure for virtual function
+ call tests if the target doesn't support inferior function calls.
+
+ * gdb.base/printcmds.exp: Allow minor deviation in FP values
+ in printf tests.
+
+Thu Feb 6 12:46:14 1997 Jeffrey A Law (law@cygnus.com)
+
+ * gdb.base/help.exp: Disable "help set", "help show", and
+ "help support". Simplify regexp for "help stack".
+
+ * gdb.base/default.exp: Set match_max to 5000 and the timeout
+ to 60 seconds. Temporarily set match_max to 15000 around the
+ "info copying" test.
+
+ * gdb.base/nodebug.exp: Don't try to do an inferior function
+ call if the target doesn't support them.
+ * gdb.base/printcmds.exp: Likewise.
+ * gdb.base/setvar.exp: Likewise.
+ * gdb.base/structs.exp: Likewise.
+ * gdb.c++/templates.exp: Likewise.
+ * gdb.base/ptype.exp: Likewise. Remove UDI specific stuff.
+
+ * gdb.base/recurse.exp: Enable for the mn10200.
+
+ * configure.in: Do configure gdb.stabs directory for *-*-elf
+ targets.
+ * configure: Rebuilt.
+
+ * gdb.base/break.exp: Check for gdb,noresults before testing
+ exit status and/or results from the target.
+ * gdb.base/watchpoint.exp, gdb.base/langs.exp: Likewise.
+ * lib/gdb.exp: Remove old (now bogus) initialization of
+ noinferior, noargs, noresults and nosignals.
+
+Tue Feb 4 21:52:17 1997 Bob Manson <manson@charmed.cygnus.com>
+
+ * config/sh.exp: New file.
+
+ * config/slite.exp: Try to connect multiple times to the board
+ before rebooting. Only send a "monitor run" if need_monitor_run
+ is set.
+
+ * gdb.base/break.exp: Don't do the "stub continue" test if
+ the target has gdb_stub set.
+
+ * gdb.base/callfuncs.exp: Increase the timeout.
+
+ * gdb.base/interrupt.exp: Don't even try to compile the testcase
+ if the target has gdb,noinferiorio set.
+
+ * gdb.base/list.exp: Increase match_max to 10000 characters.
+
+ * gdb.base/sigall.exp: Check for gdb,nosignals on the target.
+
+ * gdb.base/watchpoint.exp: Check for gdb,noinferiorio on the
+ target.
+
+ * lib/gdb.exp(gdb_run_cmd): Fix for targets that use stubs.
+
+Mon Feb 3 12:09:37 1997 Bob Manson <manson@charmed.cygnus.com>
+
+ * gdb.base/a1-selftest.exp: Make sure we call gdb_exit before
+ trying to delete the copy of gdb. Catch the file delete so we
+ don't die if the delete fails; also, the file should be copied to
+ the host, not to the build.
+
+Sun Feb 2 00:55:14 1997 Bob Manson <manson@charmed.cygnus.com>
+
+ * lib/gdb.exp(gdb_test): Surround the result pattern with
+ parenthesis in case it contains multiple regexps separated
+ with |.
+
+ * gdb.base/watchpoint.exp: Use gdb_test.
+ * gdb.base/default.exp: Ditto.
+
+Sat Feb 1 23:51:01 1997 Bob Manson <manson@charmed.cygnus.com>
+
+ * gdb.*/*.exp: Replace $prompt with $gdb_prompt.
+
+ * gdb.base/scope.exp: Use gdb_test.
+ * gdb.c++/classes.exp: Ditto.
+ * gdb.c++/inherit.exp: Ditto.
+
+Fri Jan 31 13:09:12 1997 Bob Manson <manson@charmed.cygnus.com>
+
+ * gdb.base/crossload.exp: Don't use execute_anywhere, use
+ remote_exec instead.
+ * gdb.base/corefile.exp: Don't be ridiculous.
+ * gdb.base/*.c: Add missing stub invocations.
+
+Thu Jan 30 16:49:25 1997 Bob Manson <manson@charmed.cygnus.com>
+
+ * config/slite.exp: Miscellaneous fixes.
+
+ * lib/gdb.exp: Fix runto.
+
+ * gdb.base/signals.exp: Check for a gdb,nosignals feature of
+ the target.
+
+ * gdb.base/watchpoint.exp: Fix regexp.
+
+ * lib/gdb.exp(default_gdb_exit): Add a catch to the
+ close and wait commands, as the descriptor may now be
+ invalid. Always call "remote_close host".
+
+Tue Jan 28 14:42:31 1997 Bob Manson <manson@charmed.cygnus.com>
+
+ Major rewrite for testsuite revision.
+
+ * lib/gdb.exp: Remove references to global CC, CXX, B_OPTIONS,
+ TARGET_INCLUDES, LDFLAGS and target_alias. Use gdb_spawn_id
+ instead of relying on spawn_id to always contain a valid
+ spawn id.
+ (get_compiler_info): New procedure to build the ${binfile}.ci
+ file, instead of replicating this in N different places.
+ (gdb_compile): New procedure.
+
+ gdb.*/*.exp: Use gdb_compile and get_compiler_info (with
+ appropriate arguments) instead of compile. Use gdb_test in a lot
+ more places. Use send_gdb instead of send. Always run gdb_start
+ at the start of a testcase, as this is no longer done magically.
+
+ config/*-gdb.exp: Rename without the -gdb suffix.
+
+ config/mips.exp: Use remote_close instead of exit_remote_shell.
+ config/monitor.exp: Use target_info instead of looking at
+ baud, timeout, etc.
+ config/sim.exp: Use gdb_spawn_id instead of relying on spawn_id.
+
+Sat Dec 14 00:43:57 1996 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * gdb.c++/templates.exp (test_ptype_of_templates),
+ gdb.c++/inherit.exp (test_ptype_si, test_print_anon_union):
+ Update expect patterns for destructors and assignment operators
+ to match corresponding c-typeprint.c changes.
+ * gdb.c++/templates.exp (test_template_breakpoints): Revert change
+ to destructor breakpoint test, GDB should be able to set the
+ destructor breakpoint without specifying arguments.
+
+Tue Dec 3 20:17:52 1996 Fred Fish <fnf@cygnus.com>
+
+ * gdb.threads/pthreads.exp: Change result for failure to compile due
+ to lack of pthreads runtime support from an error to simply an
+ unsupported test, per dejagnu standards.
+
+Sun Dec 1 00:18:59 1996 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * lib/gdb.exp (gdb_test): Simplify expect pattern for the case
+ where GDB exits to reduce pattern match time.
+ (skip_chill_tests): Skip chill tests for mips*-sgi-irix6*.
+
+ * gdb.base/nodebug.exp: Add mips*-sgi-irix6* xfails.
+
+Tue Nov 26 18:29:23 1996 Michael Snyder <msnyder@cleaver.cygnus.com>
+
+ * gdb.base/callfuncs.exp: Turn on function call tests for h8300.
+ * gdb.base/default.exp: ditto.
+ * gdb.base/nodebug.exp: ditto.
+ * gdb.base/printcmds.exp: ditto.
+ * gdb.base/ptype.exp: ditto.
+ * gdb.base/setvar.exp: ditto.
+ * gdb.base/structs.exp: ditto.
+ * gdb.base/setshow.c: Guard against uninitialized values of argc.
+
+Tue Nov 26 17:23:28 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * configure, */configure: Rebuild with autoconf 2.12.
+
+Sat Nov 23 13:32:15 1996 Fred Fish <fnf@cygnus.com>
+
+ * gdb.base/a1-selftest.exp: Change x86 linux setup_xfails to
+ use new i*86-pc-linux*-gnu quads.
+ * gdb.base/corefile.exp: Ditto.
+ * gdb.base/signals.exp: Ditto.
+ * gdb.base/sigall.exp: Ditto.
+ * gdb.base/interrupt.exp: Ditto.
+
+ * gdb.base/signals.exp (signal_tests_1): Remove setup_xfail
+ "i*86-*-linux" for "signal SIGUSR1". Now works, at least with
+ RedHat 4.0.
+
+ * gdb.threads/pthreads.c (_MIT_POSIX_THREADS): Define if target is
+ linux. This allows the test case to at least compile on latest
+ linux, but still not run due to missing the threads runtime library.
+
+Fri Nov 22 10:13:29 1996 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * gdb.base/a1-selftest.exp (do_steps_and_nexts): Reinitialize source
+ directory to search gdb directory. Accept and step over conditional
+ stack alignment code. Consume $prompt in failure cases.
+ Reset timeout to $oldtimeout instead of some arbitrary value.
+ * gdb.base/nodebug.exp: Limit backtrace to 10 frames to avoid
+ timeout problems with infinite stack backtraces.
+ * gdb.base/ptype.exp (ptype struct link, union tu_link):
+ Accept function parameters for linkfunc member.
+
+Thu Nov 21 09:17:19 1996 Fred Fish <fnf@cygnus.com>
+
+ * lib/gdb.exp (CFLAGS): Remove, unreferenced.
+ (CXXFLAGS): Remove, unreferenced.
+ (B_OPTIONS): Add for -B options and add code to initialize with
+ previous -B options and also add -B option to pick up cross compiled
+ runtime.
+ (TARGET_INCLUDES): Add for -I options and add code to initialize when
+ doing cross compiles.
+ (target_alias): Declare global.
+ (xgcc): Set variable to full path of gcc in build tree. Use findfile
+ to verify that gcc exists in build tree, and if so set CC to that
+ gcc and to use B_OPTIONS and TARGET_INCLUDES.
+
+Tue Nov 12 16:20:13 1996 Fred Fish <fnf@cygnus.com>
+
+ * gdb.c++/inherit.exp (test_print_anon_union): Reenable
+ ptype test for anonymous union. Fixup testcase to match
+ current gcc debug output.
+
+Mon Nov 11 14:12:06 1996 Jeffrey A Law (law@cygnus.com)
+
+ * gdb.base/funcargs.c: Use cast rather than "UL" suffix to
+ force argument to an unsigned long type.
+
+Mon Nov 11 10:27:55 1996 Fred Fish <fnf@cygnus.com>
+
+ * gdb.c++/inherit.exp (test_ptype_si): Fix tagless struct ptype
+ tests and anonymous union print/ptype tests.
+ * gdb.base/list.exp (test_forward-search): Increase timeout by
+ 5 minutes for the "search extremely long line" case.
+ * lib/gdb.exp (gdb_test): Document that the third arg to gdb_test is
+ completely optional and that the pass/fail messages use the command as
+ the message if that third arg is a null string.
+ (gdb_test_exact): Arrange that a null string pattern means match a
+ null string output rather than any output, which might include random
+ errors.
+ * gdb.base/mips_pro.exp: Add "mips*-sgi-irix4*" xfail for
+ backtrace test.
+ * gdb.c++/demangle.exp: Add a "*-*-*" xfail for test that was
+ always failing and failure is now exposed by gdb.exp changes.
+
+Sat Nov 9 11:13:24 1996 Fred Fish <fnf@cygnus.com>
+
+ * gdb.c++/inherit.exp (test_ptype_vi): Log some passes that
+ weren't being noted.
+
+Sat Nov 9 01:05:10 1996 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * gdb.base/corefile.exp: Consume $prompt in mmap fail cases.
+ * gdb.stabs/weird.exp: Remove v_comb xfails.
+
+Tue Nov 5 10:44:23 1996 Michael Snyder <msnyder@cleaver.cygnus.com>
+
+ * gdb.base/[bitfields.exp crossload.exp funcargs.exp interrupt.exp
+ list.exp scope.exp watchpoint.exp]
+ Make all timeout error msgs explicitly say "(timeout)".
+
+Mon Nov 4 12:03:06 1996 Michael Snyder <msnyder@cleaver.cygnus.com>
+
+ * config/monitor.exp: Increase download timeout to 1000 seconds.
+
+Mon Nov 4 12:02:26 1996 Michael Snyder <msnyder@cleaver.cygnus.com>
+
+ * config/m32r.exp: Increase timeout to 120 seconds.
+
+Sun Nov 3 14:37:05 1996 Fred Fish <fnf@cygnus.com>
+
+ * gdb.c++/classes.exp: Modify to handle current gcc C++ member ordering
+ and accept older ordering as obsolescent gcc or gdb.
+ * gdb.c++/templates.exp: Ditto.
+ * gdb.c++/virtfunc.exp: Ditto.
+
+Fri Nov 1 11:56:09 1996 Fred Fish <fnf@cygnus.com>
+
+ * gdb.base/coremaker.c: Add code to mmap some data so we
+ can check that it ends up in the core file.
+ * gdb.base/corefile.exp: Add test to read mmapped data
+ from core file.
+
+Wed Oct 30 18:19:16 1996 Michael Snyder <msnyder@cleaver.cygnus.com>
+
+ * config/m32r.exp: New file.
+
+Mon Oct 21 14:40:50 1996 Stu Grossman (grossman@critters.cygnus.com)
+
+ * testsuite/gdb.base/nodebug.exp: Whack out -g options by hand so
+ that cflags can contains -gstabs, and work correctly for other tests.
+
+Mon Oct 21 14:00:37 1996 Michael Snyder <msnyder@cleaver.cygnus.com>
+
+ * gdb.base/setshow.exp: New file, tests show and set.
+ * gdb.base/setshow.c: New file, tests show and set.
+ * gdb.base/help.exp: Add test for help set|show annotate.
+ * gdb.base/default.exp: Add test for set|show annotate.
+
+Wed Oct 16 19:03:54 1996 Stu Grossman (grossman@critters.cygnus.com)
+
+ * testsuite/gdb.base/break.exp: Make backtrace from factorial
+ errors unique.
+ * testsuite/gdb.base/nodebug.exp: Whack out all -g options
+ explicitly.
+
+Tue Oct 15 16:45:02 1996 Stu Grossman (grossman@critters.cygnus.com)
+
+ * config/sim-gdb.exp (gdb_target_sim): Remove setting of height
+ and width commands. This is done elsewhere.
+ * (gdb_start): Don't call gdb_start_sim here. That's already
+ done in gdb_load. This fixes lots of failures in default.exp.
+
+Sun Oct 13 10:40:23 1996 Fred Fish <fnf@cygnus.com>
+
+ From Peter Schauer <Peter.Schauer@Regent.E-Technik.TU-Muenchen.DE>:
+ * gdb.base/mips_pro.exp: Fix misplaced gdb_exit/gdb_start/gdb_load.
+ * lib/gdb.exp (gdb_test): Treat failures due to program exiting
+ in the same we we treat other failures (since it may be an expected
+ condition), rather than as an error.
+ * gdb.base/signals.exp (test_handle_all_print): Revert back to
+ old test format.
+
+Fri Oct 11 17:05:22 1996 Fred Fish <fnf@cygnus.com>
+
+ * Makefile.in (clean mostlyclean): Also remove chill *.grt files.
+ (distclean maintainer-clean realclean): No need to remove files
+ twice. Nuke the duplicates.
+ * gdb.base/Makefile.in (EXECUTABLES): Add "structs".
+ * gdb.threads/Makefile.in (distclean maintainer-clean realclean):
+ Remove config.h along with other config files.
+
+Mon Sep 30 20:16:22 1996 Fred Fish <fnf@cygnus.com>
+
+ * gdb.base/interrupt.exp: Add i*86-*-linux* setup_xfail for
+ "p func1 ()" and note that rests of tests are skipped.
+ * gdb.base/corefile.exp: Add i*86-*-linux* and m68*-*-hpux*
+ setup_xfails for "print func2::coremaker_local".
+ Add i*86-*-linux* setup_xfail for "backtrace in corefile.exp".
+ * gdb.base/mips_pro.exp: Restart gdb in this test so it isn't
+ affected by the previous run test.
+ * gdb.chill/misc.exp: Add m68*-*-hpux* setup_xfails for
+ "print array () ubyte (foo)" and "print/x array () byte (\$i)"
+ * gdb.chill/pr-8742.exp: Add m68*-*-hpux* setup_xfails for
+ "pass int powerset tuple" and "pass modeless int powerset tuple".
+ * gdb.chill/tests2.exp: Add m68*-*-hpux* setup xfails for
+ "real write 4" and "real write 8".
+ * gdb.shill/tuples.exp: Add i*86-*-linux* and m68*-*-hpux*
+ setup_xfails for "print vs1 after tuple assign 2",
+ "print \$i after tuple assign 2", and
+ "print vs2 after tuple assign 2".
+ * lib/gdb.exp (gdb_test): When a gdb aborts, print a more
+ meaningful error message and return -1 so the caller can
+ suppress further tests and avoid a cascade of errors.
+
+Fri Sep 27 10:34:51 1996 Fred Fish <fnf@cygnus.com>
+
+ * gdb.base/a1-selftest.exp: Tweak tests to account for new
+ format for printing version.
+ * gdb.base/default.exp: Ditto.
+ * gdb.base/interrupt.exp: Fix problem with cascade of
+ errors if child process dies while calling a function.
+
+Fri Sep 13 21:43:48 1996 Fred Fish <fnf@cygnus.com>
+
+ * Makefile.in (VPATH): Add
+ * Makefile.in (Makefile, config.status): Fix rules so things get
+ remade when necessary.
+
+Fri Sep 13 18:16:10 1996 Fred Fish <fnf@cygnus.com>
+
+ * Makefile.in (just-check): Add path to sibling expect dir
+ to environment variable specified by RPATH_ENVVAR.
+
+Fri Sep 13 12:05:34 1996 Fred Fish <fnf@cygnus.com>
+
+ * Makefile.in (RPATH_ENVVAR): New var, set to @RPATH_ENVVAR@.
+ (just-check): Add shared library paths for libstdc++, tk,
+ tcl, bfd, and opcodes to the environment variable specified
+ in RPATH_ENVVAR.
+ * configure.in: Add support to recognize --enable-shared flag
+ and generate correct value for RPATH_ENVVAR.
+ * configure: Regenerated with autoconf.
+
+Mon Sep 2 06:36:02 1996 Fred Fish <fnf@cygnus.com>
+
+ * gdb.base/break.exp: Expand "Delete all breakpoints" xfail to
+ include all osf versions.
+ * gdb.threads/pthreads.exp: Expand "run to main" xfail to include
+ all osf versions. Add -D_MIT_POSIX_THREADS to compilation command
+ when target is linux. When failing to build pthreads test
+ executable, give more meaningful message.
+ * gdb.threads/pthreads.c: Hpux also uses old definition of second
+ arg for pthread_create.
+
+Mon Aug 19 09:58:59 1996 Fred Fish <fnf@cygnus.com>
+
+ * gdb.threads/pthreads.c (PTHREAD_CREATE_ARG2,
+ PTHREAD_CREATE_NULL_ARG2): Accomodate old pthreads implementations.
+ * gdb.threads/pthreads.exp: Try linking with both -lpthread (Solaris)
+ and -lpthreads (everybody else).
+ (test_startup): Fail gracefully if threads are not supported.
+ * gdb.base/nodebug.exp: Add setup_xfail hppa*-*-hpux* for
+ "p/c array_index("abcdef",2)" when not gcc compiled.
+ * gdb.base/corefile.exp: Add setup_xfail hppa*-*-hpux* for
+ "print func2::coremaker_local" when not gcc compiled.
+ * gdb.base/opaque.exp: Remove setup_xfail hppa*-*-hpux* for
+ "ptype on opaque struct tagname (statically)",
+ "ptype on opaque struct tagname (dynamically) 1", and
+ "ptype on opaque struct tagname (dynamically) 2"
+ for not compiled with gcc.
+ * gdb.base/mips_pro.exp: Only do setup_xfail hppa*-*-* for
+ backtrace when compiled with gcc.
+ * lib/gdb.exp (runto_main): Return result of "runto main" rather
+ than always return success.
+
+Sat Aug 17 13:28:00 1996 Fred Fish <fnf@cygnus.com>
+
+ * gdb.c++/virtfunc.exp: Remove setup_xfail for "mips-*-irix5*".
+
+Tue Aug 13 10:26:10 1996 Jeffrey A Law (law@cygnus.com)
+
+ * gdb.base/structs.exp: Undo last change.
+
+Mon Aug 12 15:29:08 1996 Fred Fish <fnf@cygnus.com>
+
+ * gdb.base/a1-selftest.exp (do_steps_and_nexts): New routine to
+ encapsulate all the steps/nexts done during self test, starting
+ at main, and makes them less sensitive to optimization issues.
+ Add "hppa*-*-hpux*" to setup_xfail for "backtrace through
+ signal handler" test.
+ * gdb.threads/pthreads.exp: Only run this for native configs.
+ * gdb.base/structs.exp (do_function_calls): Add hppa*-*-hpux9*"
+ setup_xfails for "p fun5()", "p fun6()", "p fun7()", and "p fun8"
+ tests.
+ gdb.c++/virtfunc.exp (do_tests): Add "mips-*-irix5*" setup_xfail
+ for "runto test_calls(void)" test.
+
+Sun Aug 11 13:11:24 1996 Fred Fish <fnf@cygnus.com>
+
+ * gdb.base/term.exp: Set 7-bit strings, address off, width to 0,
+ and don't expect address info in breakpoint confirmations.
+
+Wed Aug 7 20:47:43 1996 Fred Fish <fnf@cygnus.com>
+
+ * gdb.base/list.exp (test_forward_search): Increase timeout
+ temporarily by 60 seconds for searching extremely long line,
+ and then reset to old value when done. Increase expect input
+ buffer to 10000.
+
+Wed Aug 7 15:34:22 1996 Fred Fish <fnf@cygnus.com>
+
+ * gdb.base/list.exp (test_forward_search): Fix to handle very
+ long source line without overflowing expect's input buffer.
+
+Wed Aug 7 12:03:25 1996 Tom Tromey <tromey@creche.cygnus.com>
+
+ * config/slite-gdb.exp (gdb_start): Use "full_buffer", not
+ "buffer_full".
+
+ * config/nind-gdb.exp (gdb_start): Use "full_buffer", not
+ "buffer_full".
+
+ * config/mips-gdb.exp (gdb_start): Use "full_buffer", not
+ "buffer_full".
+
+ * lib/gdb.exp (gdb_test): Correct pattern is "full_buffer", not
+ "buffer_full".
+
+Wed Aug 7 11:05:47 1996 Fred Fish <fnf@cygnus.com>
+
+ * configure.in (configdirs): Add gdb.threads.
+ * configure: Regenerated with autoconf.
+ * gdb.threads/{config.in, pthreads.c, pthreads.exp}: New.
+ * gdb.threads/{Makefile.in, configure.in}: Complete rewrites.
+ * gdb.threads/configure: New, generated with autoconf.
+
+Tue Aug 6 10:23:04 1996 Tom Tromey <tromey@rtl.cygnus.com>
+
+ * lib/gdb.exp (gdb_test_exact): Turn \n in pattern into \r\n.
+
+Mon Aug 5 18:11:53 1996 Fred Fish <fnf@cygnus.com>
+
+ * gdb.base/signals.exp (test_handle_all_print): Test separately for
+ each signal's status in the output of "handle all print".
+ * lib/gdb.exp (gdb_test): Document that the pattern must NOT include
+ the \r\n sequence that immediately precedes the gdb prompt.
+ * gdb.base/a1-selftest.exp: Save original timeout and restore
+ after test.
+
+Sun Aug 4 10:20:50 1996 Jeffrey A Law (law@cygnus.com)
+
+ * gdb.disasm/hppa.s: Export fmemLRbug_tests_4 as a ST_CODE
+ symbol.
+
+Fri Aug 2 17:37:26 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
+
+ * config/vx-gdb.exp (gdb_start): Fix syntax of `$shell_id < 0'.
+
+Thu Jun 27 20:41:40 1996 Fred Fish <fnf@cygnus.com>
+
+ * gdb.base/signals.exp (test_handle_all_print): Temporarily increase
+ timeout by 60 seconds.
+
+Thu Jun 27 18:13:57 1996 Fred Fish <fnf@cygnus.com>
+
+ * config/unix-gdb.exp: Increase default timeout from 30 to 60 sec.
+ * config/netware.exp (gdb_run_cmd): Restore old timeout before doing
+ error return.
+
+Thu Jun 27 10:54:58 1996 Fred Fish <fnf@cygnus.com>
+
+ * lib/gdb.exp (default_gdb_start): When reporting a timeout during
+ gdb initialization, also report how long dejagnu waited. Restore
+ old timeout before doing error return. Temporarily increase timeout
+ by 3 minutes to allow for slow startups over heavy NFS use.
+
+Tue Jun 25 19:59:17 1996 Fred Fish <fnf@cygnus.com>
+
+ * lib/gdb.exp: Report timeout value for verbosity level 2.
+ * config/gdbserver.exp: Ditto.
+ * config/hppro.exp: Ditto.
+ * config/mips-gdb.exp: Ditto.
+ * config/monitor.exp: Ditto.
+ * config/netware.exp: Ditto.
+ * config/sim-gdb.exp: Ditto.
+ * config/slite-gdb.exp: Ditto.
+ * config/udi-gdb.exp: Ditto.
+ * config/unix-gdb.exp: Ditto.
+ * config/vx-gdb.exp: Ditto.
+ * gdb.base/a1-selftest.exp: Ditto.
+ * gdb.base/a2-run.exp: Ditto.
+ * gdb.base/break.exp: Ditto.
+ * gdb.base/corefile.exp: Ditto.
+ * gdb.base/list.exp: Ditto.
+ * gdb.base/recurse.exp: Ditto.
+ * gdb.base/scope.exp: Ditto.
+ * gdb.base/signals.exp: Ditto.
+
+Tue Jun 25 23:16:58 1996 Jason Molenda (crash@godzilla.cygnus.co.jp)
+
+ * gdb.threads/Makefile.in (docdir): Removed.
+
+Tue Jun 25 17:02:39 1996 Jason Molenda (crash@godzilla.cygnus.co.jp)
+
+ * configure.in (AC_PREREQ): autoconf 2.5 or higher.
+ * gdb.{base,c++,chill,disasm,stabs}/Makefile.in (VPATH): set to
+ @srcdir@.
+ * gdb.{base,c++,chill,disasm,stabs}/configure.in (AC_PREREQ):
+ autoconf 2.5 or higher.
+ * gdb.{base,c++,chill,disasm,stabs}/configure: Rebuilt.
+
+Thu Jun 13 11:16:10 1996 Tom Tromey <tromey@thepub.cygnus.com>
+
+ * configure: Regenerated.
+ * aclocal.m4 (CY_AC_PATH_TCLH, CY_AC_PATH_TKH): Use odd names to
+ avoid name clashes with SunOS headers.
+
+Wed Jun 5 16:43:27 1996 Jeffrey A Law (law@cygnus.com)
+
+ * gdb.c++/virtfunc.exp: Search $objdir/../../libstdc++ for libstdc++.
+
+Thu May 30 11:35:11 1996 Jeffrey A Law (law@cygnus.com)
+
+ * gdb.base/callfuncs.exp: Finish last change -- make sure the
+ prototype information ends up in the compiler info file.
+
+Thu May 23 12:48:41 1996 Fred Fish <fnf@cygnus.com>
+
+ * gdb.base/callfuncs.exp: Remove the compiler info file prior to
+ attempting to regenerate it. Eliminate use of a temporary file
+ and just generate the info file directly. Source it immediately,
+ for consistency of use.
+ * gdb.base/corefile.exp: Ditto
+ * gdb.base/exprs.exp: Ditto.
+ * gdb.base/funcargs.exp: Ditto.
+ * gdb.base/langs.exp: Ditto.
+ * gdb.base/list.exp: Ditto.
+ * gdb.base/mips_pro.exp: Ditto.
+ * gdb.base/nodebug.exp: Ditto.
+ * gdb.base/opaque.exp: Ditto.
+ * gdb.base/ptype.exp: Ditto.
+ * gdb.base/scope.exp: Ditto.
+ * gdb.base/setvar.exp: Ditto.
+ * gdb.base/signals.exp: Ditto.
+ * gdb.base/whatis.exp: Ditto.
+ * gdb.c++/templates.exp: Ditto.
+ * gdb.c++/virtfunc.exp: Ditto.
+ * gdb.c++/virtfunc.exp: Use contents of gcc_compiled to decide
+ whether or not to add -lstdc++ to the compile command line args.
+
+Sat May 18 02:43:58 1996 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * gdb.base/recurse.exp: Remove setup_xfail for "sparc*-*-sunos4*",
+ it got fixed by the recent lookup_minimal_symbol_by_pc change.
+ Increase timeout, a lot of single stepping might be needed if the
+ target has no hardware watchpoints.
+
+Wed May 15 08:47:42 1996 Jeffrey A Law (law@cygnus.com)
+
+ * gdb.base/break.exp: Ignore compiler warnings when compiling
+ break.c.
+ * gdb.base/callfuncs.exp: Don't run these tests on the h8300.
+ * gdb.base/default.exp: Add h8300 xfails. Handle messages
+ from remote-sim.
+ * gdb.base/exprs.exp: Add h8300 xfails.
+ * gdb.base/funcargs.exp: Likewise.
+ * gdb.base/nodebug.exp: Likewise.
+ * gdb.base/printcmds.exp: Likewise.
+ * gdb.base/ptype.exp: Likewise.
+ * gdb.base/setvar.exp: Handle sizeof (int) != 4 for h8300. Add
+ h8300 xfails.
+ * gdb.base/return.exp: Handle float/double precision problems
+ on the h8300.
+ * gdb.base/funcargs.c: Explicitly make last constant argument to
+ call_after_alloca_subr an unsigned long type.
+ * gdb.base/return.c: Include stdio.h.
+
+Tue May 7 22:01:12 1996 Rob Savoye <rob@chinadoll.cygnus.com>
+
+ * config/abug.exp: New file for the older Motorola Bug monitor
+ that runs on the mvme13x series VME boards.
+ * config/monitor.exp: Use the new config array for target settings
+ if they exist.
+
+Fri May 3 16:02:55 1996 Stan Shebs <shebs@andros.cygnus.com>
+
+ * sim-gdb.exp: Make the SH simulator allocate less space when
+ it is targeted.
+
+Thu May 2 12:31:56 1996 Jeffrey A Law (law@cygnus.com)
+
+ * gdb.base/mips_pro.exp: Expect failure for hppa*-*-* in backtrace
+ test.
+
+Wed Mar 20 08:48:03 1996 Fred Fish <fnf@cygnus.com>
+
+ * gdb.base/list.exp (test_list_function): Remove setup_xfail for
+ "rs6000-*-*" for "list function in include file" when gcc compiled.
+ * gdb.base/printcmds.exp: Remove setup_xfail for "rs6000-*-aix*"
+ for "p ctable1[120]".
+ * gdb.base/scope.exp: Remove setup_xfail for "rs6000-*-*" for
+ "print 'scope0.c'::filelocal_bss before run" when gcc compiled.
+ Remove setup_xfail for "rs6000-*-*" for
+ "print 'scope0.c'::filelocal before run".
+ * gdb.base/{langs.exp, lists.exp, opaque.exp, scope.exp},
+ gdb.stabs/weird.exp: Remove use of compiler options "-c -o ..."
+ since some compilers don't allow both options to be given
+ on the same command line. Create object file and move it.
+
+Tue Mar 19 23:49:31 1996 Fred Fish <fnf@cygnus.com>
+
+ * gdb.base/corefile.exp: Always regenerate the core file, since
+ we always regenerate the coremaker program. Detect special case
+ where registers cannot be read from core file.
+
+Tue Mar 19 16:52:49 1996 Fred Fish <fnf@cygnus.com>
+
+ From Peter Schauer <Peter.Schauer@Regent.E-Technik.TU-Muenchen.DE>
+ * gdb.base/funcargs.c: Patch for SPARCworks alloca compatibility
+ * gdb.c++/templates.exp: Only match on basename of file since
+ some formats like xcoff don't encode directory information.
+ * gdb.stabs/weird.exp: Use the right sed script for powerpc
+ and rs6000 AIX xcoff targets.
+ * configure.in: Add stabsdirs to configdirs for powerpc-*-aix*.
+ * configure: Regenerate.
+ * gdb.base/Makefile.in (clean): Remove generated file twice-tmp.c
+ here, rather than in distclean.
+
+Sun Mar 17 13:35:31 1996 Fred Fish <fnf@cygnus.com>
+
+ * gdb.base/mips_pro.exp: Create mips_pro.ci to get gcc_compiled
+ defined, and use it to compile the test case with -O2. The
+ native compilation still uses no optimization.
+ * gdb.base/mips_pro.c: Remove inline assembly code since
+ it is compiled PIC by default, which results in assembler
+ warnings that make the testsuite think the compilation
+ was unsuccessful.
+
+Sat Mar 16 15:02:24 1996 Fred Fish <fnf@cygnus.com>
+
+ * gdb.c++/misc.exp: Add note to message for
+ "print s.a for foo struct" that this is a known gcc 2.7.2
+ and earlier bug.
+
+Fri Mar 15 17:49:57 1996 Fred Fish (fnf@cygnus.com)
+
+ * gdb.base/break.exp: Fix pattern for matching "Delete all
+ breakpoints (y or n) ". Add "mips-dec-ultrix*" to
+ setup_xfail for deleting all breakpoints test. Fix various
+ timeout messages to include "(timeout)".
+ * gdb.base/callfuncs.exp: Add "i*86-*-sysv4*" to setup_xfail
+ for "p t_float_values2(3.14159,float_val2)".
+ * gdb.base/funcargs.exp: Remove "mips-sgi-irix4*" setup_xfail
+ for "continue to call2g" when gcc compiled.
+ * gdb.base/langs.exp: Remove "i*86-*-sysv4*" setup_xfail for
+ "up to foo in langs.exp", "show language at foo in langs.exp",
+ "show language at cppsub_ in langs.exp", "up to fsub in langs.exp",
+ and "show language at fsub in langs.exp".
+ * gdb.base/list.exp: Remove "*-*-sysv4*" setup_xfail for
+ "list line 1 in include file", "list message for lines past EOF",
+ "list function in include file", "list list0.h:foo", and
+ "list filename:function; nonexistant function".
+ * gdb.base/ptype.exp: Change "i*86-*-sysv4*" setup_xfail for
+ "whatis unnamed typedef'd enum (compiler bug in IBM's xlc)"
+ and "ptype t_char_array" to be for native cc only.
+
+Fri Mar 15 16:17:22 1996 Fred Fish <fnf@cygnus.com>
+
+ * gdb.base/corefile.exp: Remove "alpha-dec-osf2*" native compiled
+ setup_xfail for "print coremaker_bss", "print coremaker_ro",
+ "print func2::coremaker_local", and "backtrace in corefile.exp".
+
+Wed Mar 13 14:54:11 1996 Fred Fish <fnf@cygnus.com>
+
+ * gdb.base/signals.exp: Remove "alpha-*-osf2*" setup_xfail for
+ "bt in signals.exp". This problem only appears when running
+ the testsuite, and then only intermittently.
+
+Tue Mar 12 15:00:16 1996 Stan Shebs <shebs@andros.cygnus.com>
+
+ * gdb.base/return.exp (return_tests): Differentiate between
+ two tests of continuing.
+
+Tue Mar 5 14:33:33 1996 Stan Shebs <shebs@andros.cygnus.com>
+
+ * */Makefile.in (maintainer-clean): Remove config.log.
+ * gdb.base/Makefile.in (EXECUTABLES): Replace twice with twice-tmp.
+ * gdb.c++/Makefile.in (PROGS): Add inherit.
+ (clean): Remove *.ci.
+
+Tue Feb 20 16:36:10 1996 Fred Fish <fnf@cygnus.com>
+
+ * gdb.c++/misc.cc: Add test code from Mike Stump.
+ * gdb.c++/misc.exp: Add test to print s.a, for Mike Stump.
+
+Sun Feb 18 11:39:12 1996 Fred Fish <fnf@cygnus.com>
+
+ * gdb.base/signals.exp: Change setup_xfail for "alpha-*-osf2"
+ to "alpha-*-osf2*" and add comment.
+ * gdb.base/a1-selftest.exp (test_with_self): Remove "alpha-dec-osf2*"
+ setup_xfail for "step over execarg initialization" and
+ "step over corearg initialization".
+ * gdb.base/callfuncs.exp (do_function_calls): Restore setup_xfail
+ for "hppa*-*-*", "sparc-*-*", "mips*-*-*", and "alpha-dec-osf2*".
+ * gdb.base/corefile.exp: Add "alpha-dec-osf2*" setup_xfail when not
+ gcc compiled for "print coremaker_bss", "print coremaker_ro",
+ "print func2::coremaker_local", and "backtrace in corefile.exp".
+ * gdb.base/signals.exp: Build and source signals.ci.
+ Change "alpha-dec-osf2*" setup_xfail for "bt in signals.exp"
+ to be for gcc only.
+ * lib/gdb.exp: Move verbose statements outside conditionals.
+
+Sat Feb 17 02:22:14 1996 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * gdb.base/sigall.exp: Remove setup_xfail for irix4. Fixed by
+ Feb 3 procfs.c change.
+
+Fri Feb 16 13:25:31 1996 Fred Fish <fnf@cygnus.com>
+
+ * config/unix-gdb.exp: Remove extraneous newlines from end of file.
+
+Thu Feb 15 08:12:55 1996 Fred Fish <fnf@cygnus.com>
+
+ * config/unix-gdb.exp: Default timeout in UNIX case to 30 seconds, up
+ from dejagnu's apparent default of 10 seconds, which gives random
+ results when running the tests over NFS on moderately loaded systems.
+ * lib/gdb.exp (gdb_run_cmd): Add "(timeout)" in timeout case.
+
+Mon Feb 12 16:50:28 1996 Fred Fish <fnf@cygnus.com>
+
+ * gdb.base/callfuncs.exp: Remove setup_xfail for PR 5318. Now fixed.
+ * gdb.base/a2-run.exp: Replace $binfile with $testfile in test
+ result reports.
+
+Fri Feb 9 15:56:51 1996 Fred Fish <fnf@cygnus.com>
+
+ * configure.in (CY_AC_PATH_TCLH): Remove.
+ * configure: Regenerate.
+
+Fri Feb 9 08:21:31 1996 Fred Fish <fnf@cygnus.com>
+
+ * gdb.c++/Makefile.in (clean): Add missing '{'.
+
+Fri Feb 2 10:19:40 1996 Jeffrey A Law (law@cygnus.com)
+
+ * lib/gdb.exp: Provide a default value for noinferior.
+
+ * lib/gdb.exp: Fix typos (LDLAGS -> LDFLAGS).
+ Load libgloss.exp.
+
+Thu Feb 1 20:20:14 1996 Jeffrey A Law (law@cygnus.com)
+
+ * gdb.disasm/hppa.exp: Compile directly into an executable, use
+ the executable, not the .o to run the tests from.
+
+Wed Jan 31 14:21:09 1996 Jeffrey A Law (law@cygnus.com)
+
+ * gdb.base/break.exp: Don't test for program exit or exit status
+ if $noresults if nonzero.
+ * gdb.base/langs.exp: Likewise.
+ * gdb.base/watchpoint.exp: Likewise.
+
+ * gdb.base/default.exp: Remove extraneous call to load gdb.exp.
+ * gdb.chill/pr-8405.exp: Move skip_chill_tests check to just before
+ trying to compile the testcase.
+
+Wed Jan 24 23:42:39 1996 Doug Evans <dje@charmed.cygnus.com>
+
+ * gdb.base/interrupt.exp (p func1): xfail sparc64-*-solaris2.
+ * gdb.base/signals.exp (continue to handler): Likewise.
+
+Tue Jan 23 16:28:22 1996 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * gdb.c++/classes.exp: Now = returns false/true, not 1/0.
+
+ * gdb.fortran/exprs.exp: .LT. and .GT. now return .TRUE. or .FALSE..
+
+Tue Jan 23 15:41:57 1996 Jeffrey A Law (law@cygnus.com)
+
+ * gdb.base/corefile.exp: Recognize "not found" as failure
+ when trying to determine if a core file was generated.
+ If no core file was generate the first time, try again without
+ the ulimit -c to work around braindamaged shells.
+
+Mon Jan 15 09:33:00 1996 Fred Fish <fnf@cygnus.com>
+
+ * gdb.stabs/configure.in (alpha-*-*,mips-*-*): Replace
+ [] tests with "test" and enclose string in quotes.
+ * gdb.stabs/configure: Rebuild
+
+Thu Jan 11 09:43:14 1996 Tom Tromey <tromey@creche.cygnus.com>
+
+ Changes in sync with expect:
+ * aclocal.m4 (CY_AC_PATH_TCLH): Handle Tcl 7.5 and greater.
+ (CY_AC_PATH_TCLLIB): Handle Tcl 7.5 and greater.
+ (CY_AC_PATH_TKH): Handle Tk 4.1 and greater.
+ (CY_AC_PATH_TKLIB): Handle Tk 4.1 and greater. Properly quote
+ argument to AC_REQUIRE.
+ * configure: Regenerated.
+
+Thu Jan 4 08:17:22 1996 Fred Fish <fnf@cygnus.com>
+
+ * gdb.base/corefile.exp: When generating a core, discard any
+ error messages about ulimit not found and the "core dumped"
+ message from the shell that runs the coredumper.
+
+Wed Jan 3 01:30:41 1996 Jeffrey A Law (law@cygnus.com)
+
+ * lib/gdb.exp (skip_chill_tests): Skip them on the PA too.
+
+ * gdb.stabs/weird.exp: Use ${target_triplet} to determine
+ which sed script to run. Expect failure for v_comb test
+ on PA targets too.
+
+Sat Dec 30 16:09:04 1995 Fred Fish <fnf@rtl.cygnus.com>
+
+ * gdb.base/corefile.exp: Remove "i*86-*-linux" xfail for
+ "print func2::coremaker_local" and for "backtrace in corefile.exp"
+
+Sat Dec 30 12:59:12 1995 Fred Fish <fnf@cygnus.com>
+
+ * lib/gdb.exp: Fix typo and rewrite skip_chill_tests.
+ * gdb.stabs/weird.exp: Setup "sparc-sun-sunos4*" and
+ "sparc-sun-solaris*" xfails for "p v_comb".
+ * lib/gdb.exp (default_gdb_start): Fix typo.
+ * gdb.base/corefile.exp: Allow "Core was generated by ..."
+ messages to not include the full program name that caused
+ the core dump since some systems (such as solaris) apparently
+ truncate this path to about 80 characters.
+ When generating a core file first try increasing the core file
+ size limit to unlimited since some systems may default it to
+ zero, and it is harmless to try it. Move the test for failing
+ to generate a core file to where it will actually get executed.
+ * gdb.c++/templates.exp (test_ptype_of_templates): Accept
+ new gdb result from g++ debug info improvements and make old
+ pattern obsolescent. Also account for size_t differences
+ (may be int or long).
+ * gdb.base/a1-selftest.exp (test_with_self): Check for case where
+ initialization before function call is placed in the delay slot
+ and thus appears to be skipped over by commands such as "next".
+
+Fri Dec 29 16:09:20 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ * gdb.base/a1-selftest.exp (test_with_self): Run without windows.
+
+Wed Dec 6 10:45:42 1995 Jeffrey A. Law <law@sethra.cygnus.com>
+
+ * gdb.base/*.exp: Make ${srcfile} only be the basename of the
+ input source file; fix code to compile test to deal with this
+ convention.
+ * gdb.c++/*.exp: Likewise.
+
+Mon Nov 27 11:40:16 1995 Fred Fish <fnf@cygnus.com>
+
+ * gdb.base/signals.exp: Setup "alpha-*-osf2*" xfail for
+ "bt in signals.exp".
+
+Sat Nov 25 20:52:15 1995 Fred Fish <fnf@phydeaux.cygnus.com>
+
+ * gdb.base/a1-selftest.exp: Add alpha-dec-osf2 setup_xfail for
+ "step over execarg initialization" and
+ "step over corearg initialization".
+
+Sat Nov 25 18:20:14 1995 Fred Fish <fnf@cygnus.com>
+
+ * gdb.base/ptype.c (main): Declare malloc as a "char *" for systems
+ with sizeof(pointer) > sizeof(int). Avoid "void *" or include files.
+
+Sat Nov 25 11:03:42 1995 Fred Fish <fnf@cygnus.com>
+
+ From Rob Savoye (rob@poseidon.cygnus.com)
+ * Makefile.in, configure.in, gdb.base/{Makefile.in, configure.in},
+ gdb.c++/{Makefile.in, configure.in}, gdb.chill/{Makefile.in,
+ configure.in}, gdb.disasm/{Makefile.in, configure.in},
+ gdb.stabs/{Makefile.in, configure.in}, gdb.threads/{Makefile.in,
+ configure.in}: Major reworking for autoconfig.
+ * aclocal.m4, configure, gdb.base/configure, gdb.c++/configure,
+ gdb.disasm/configure, gdb.stabs/configure, gdb.stabs/default.mt :
+ New files.
+ * config/unix-gdb.exp: Make GDB global.
+ * gdb.base/{a1-selftest.exp, a2-run.exp,bitfields.exp, break.exp,
+ callfuncs.exp, commands.exp, corefile.exp, crossload.exp, exprs.exp,
+ funcargs.exp, interrupt.exp, langs.exp, list.exp, mips_pro.exp,
+ nodebug.exp, opaque.exp, printcmds.exp, ptype.exp, recurse.exp,
+ regs.exp, return.exp, scope.exp, setvar.exp, sigall.exp, signals.exp,
+ term.exp, twice.exp, watchpoint.exp, whatis.exp},
+ gdb.c++/{classes.exp, callfuncs.exp, inherit.exp, misc.exp,
+ templates.exp, virtfunc.exp}, gdb.chill/{callch.exp, chillvars.exp,
+ misc.exp, pr-4975.exp, pr-5016.exp, pr-5020.exp, pr-5022.exp,
+ pr-5646.exp, pr-5984.exp, pr-6292.exp, pr-6632.exp, pr-8134.exp,
+ pr-8136.exp, result.exp, string.exp, tuples.exp},
+ gdb.disasm/{hppa.exp, sh3.exp}, gdb.stabs/weird.exp: Change continues
+ to returns as necessary, arrange for test to compile own testcase
+ executable.
+ * lib/gdb.exp: Changes for testsuite to compile own test cases.
+
+Tue Nov 21 16:15:45 1995 Fred Fish <fnf@cygnus.com>
+
+ * gdb.c++/classes.exp (test_pointers_to_class_members): Add
+ clear_xfail at end of test which might not call either pass or fail.
+ * gdb.base/a1-selftest.exp: Add i*86-*-linuxaout xfail for
+ "backtrace through signal handler".
+
+Sat Nov 18 04:09:31 1995 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * gdb.base/sigall.exp: Work around OSF/1-3.x kernel bug when
+ continuing from a job control stop signal.
+ * gdb.stabs/alpha.mt: Use $(CFLAGS) when building weird.o.
+
+Wed Nov 15 00:28:03 1995 Jeffrey A Law (law@cygnus.com)
+
+ * gdb.base/callfuncs.exp: Remove bogus hppa xfails.
+ * gdb.base/corefile.exp: Likewise.
+ * gdb.base/funcargs.exp: Likewise.
+
+Tue Nov 14 15:18:10 1995 Stu Grossman (grossman@cygnus.com)
+
+ * config/hmsirom.exp: Setup for talking to hmsi ROM monitor.
+ * config/monitor.exp: Add support for setting baud rate.
+
+Sat Nov 4 15:35:52 1995 Fred Fish <fnf@cygnus.com>
+
+ * gdb.base/a1-selftest.exp: Remove i*86-*-sysv4* and
+ i*86-*-linux* xfails for "backtrace through signal handler".
+ * gdb.base/corefile.exp: Add i*86-*-sysv4* xfail for
+ "print func2::coremaker_local".
+ * gdb.base/break.exp: Add i*86-*-sysv4*, sparc-sun-sunos4,
+ alpha-dec-osf2* xfail for
+ "delete all breakpoints when none".
+
+Wed Nov 1 15:57:16 1995 Fred Fish <fnf@cygnus.com>
+
+ * gdb.base/break.exp: Change test that deletes all breakpoints
+ when no user breakpoints are installed. A post 4.15 change
+ causes gdb to no longer prompt in this case.
+
+Tue Oct 31 15:13:43 1995 Fred Fish <fnf@cygnus.com>
+
+ * gdb.base/return.exp (return_tests): Change xfail for test
+ "correct value returned double test" to stop xfailing at
+ Solaris 2.5. Apparently the bug has been fixed.
+
+Sun Oct 29 12:18:16 1995 Fred Fish <fnf@cygnus.com>
+
+ * gdb.stabs/ecoff.sed: Remove comment lines except for first one.
+ IRIX 4.0 /bin/sed chokes on them, though they work fine elsewhere.
+
+Tue Oct 24 11:12:12 1995 Jeffrey A Law (law@cygnus.com)
+
+ * gdb.disasm/hppa.exp: Test lci and syncdma instructions.
+ * gdb.disasm/hppa.s: Corresponding changes.
+
+Wed Oct 18 11:27:47 1995 Jeffrey A Law (law@cygnus.com)
+
+ * gdb.base/configure.in (hppa*-*-hpux*): No longer needs target
+ makefile fragment.
+ * config/mt-hpux: Deleted.
+
+Tue Oct 17 23:02:12 1995 Jeffrey A Law (law@cygnus.com)
+
+ * Many files: When warning about suppressed tests due to a
+ nonexistant test binary, avoid incrementing the warning count.
+
+Tue Oct 10 11:00:41 1995 Fred Fish <fnf@cygnus.com>
+
+ * Makefile.in (TARGET_FLAGS_TO_PASS): Remove BISON.
+
+Sun Oct 8 04:23:14 1995 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * gdb.base/return.exp: Change xfail from "sparc-*-solaris2.*" to
+ "sparc-*-solaris2*".
+
+Sat Sep 23 01:22:23 1995 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * gdb.base/coremaker.c: Produce a full core dump for AIX targets.
+ Add global and local variables and initialize them.
+ * gdb.base/corefile.exp: Test correct mapping of corefile sections
+ by printing variables. Remove rs6000 and powerpc xfails, BFD now
+ extracts the file name and terminating signal from the core file.
+ * TODO: Remove note about tests for correct mapping of corefile.
+ * gdb.base/ptype.c (main): Use boolean2 to inhibit AIX 4.1 xlc
+ from optimizing it away.
+ * gdb.stabs/weird.exp: Remove rs6000 xfail, xcoffread.c now
+ handles common blocks.
+
+Thu Sep 21 01:28:10 1995 Jeff Law (law@snake.cs.utah.edu)
+
+ * gdb.disasm/sh3.s (fmac): Update for new assembler syntax
+ * gdb.disasm/sh3.exp (fmac): Corresponding changes.
+
+Wed Sep 20 13:15:05 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * Makefile.in (maintainer-clean): New target, synonym for
+ realclean.
+ * gdb.base/Makefile.in (maintainer-clean): Likewise.
+ * gdb.c++/Makefile.in (maintainer-clean): Likewise.
+ * gdb.chill/Makefile.in (maintainer-clean): Likewise.
+ * gdb.disasm/Makefile.in (maintainer-clean): Likewise.
+ * gdb.stabs/Makefile.in (maintainer-clean): Likewise.
+ * gdb.threads/Makefile.in (maintainer-clean): Likewise.
+
+Sun Sep 10 13:14:01 1995 Fred Fish <fnf@cygnus.com>
+
+ * gdb.base/scope.exp (text_at_main): Add "hppa*-*-hpux*"
+ xfails when not gcc compiled for "print foo::funclocal".
+ (test_at_foo): Add "hppa*-*-hpux*" xfails when not gcc compiled for:
+ "print foo::funclocal at foo",
+ "print 'scope1.c'::foo::funclocal at foo",
+ "print foo::funclocal_bss at foo",
+ "print 'scope1.c'::foo::funclocal_bss at foo",
+ "print foo::funclocal_ro at foo",
+ "print 'scope1.c'::foo::funclocal_ro at foo",
+ "print bar::funclocal at foo" and
+ "print 'scope1.c'::bar::funclocal at foo".
+ (test_at_bar): Add "hppa*-*-hpux*" xfails when not
+ gcc compiled for "print foo::funclocal at bar".
+ Expand all messages to ensure that they identify that
+ the test is at bar().
+ * gdb.base/opaque.exp: Add "hppa*-*-hpux*" xfails when not
+ gcc compiled for:
+ "ptype on opaque struct pointer (statically)",
+ "ptype on opaque struct tagname (statically)",
+ "ptype on opaque struct pointer (dynamically) 1",
+ "ptype on opaque struct tagname (dynamically) 1",
+ "ptype on opaque struct pointer (dynamically) 2" and
+ "ptype on opaque struct tagname (dynamically) 2
+ * gdb.base/nodebug.exp: Add "hppa*-*-hpux*" xfails when not
+ gcc compiled for:
+ "p datalocal"
+ "whatis datalocal",
+ "ptype datalocal",
+ "p bsslocal",
+ "whatis bsslocal", and
+ "ptype bsslocal".
+ * gdb.base/langs.exp: Add "hppa*-*-hpux*" xfails for
+ "backtrace in langs.exp" and "up to langs0__2do in langs.exp"
+ when not gcc compiled.
+ * gdb.base/funcargs.exp (float_and_integral_args): Add
+ "hppa*-*-hpux*" xfail for "run to call2a" when not gcc
+ compiled.
+ (discard_and_shuffle): Add "hppa*-*-hpux*" xfail for
+ "backtrace from call6a" when not gcc compiled.
+ (shuffle_round_robin): Add "hppa*-*-hpux*" xfail for
+ "backtrace from call7a" when not gcc compiled.
+ * gdb.base/callfuncs.exp (do_function_calls):
+ Add "hppa*-*-hpux*" xfail when not gcc compiled for
+ "p t_char_array_values(char_array_val2,char_array_val1)",
+ "p t_char_array_values(char_array_val1,char_array_val2)",
+ "p t_char_array_values("carray 1","carray 2")",
+ "p t_char_array_values("carray 1",char_array_val2)",
+ "p t_char_array_values(char_array_val1,"carray 2")",
+ "p sum_args(1,{2})",
+ "p sum_args(2,{2,3})",
+ "p sum_args(3,{2,3,4})",
+ "p sum_args(4,{2,3,4,5})"
+ * gdb.base/corefile.exp: Add "hppa*-*-hpux*" xfail for
+ "backtrace in corefile.exp" when not gcc compiled.
+
+Sat Sep 9 01:35:39 1995 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * gdb.base/signals.exp: Rewrite `handle all print' test as
+ a procedure. Accept blanks or TABs as whitespace, increase
+ timeout and expect input buffer size for the large output
+ from the command. Remove "i*86-*-bsdi2.0" xfail.
+
+Sat Sep 2 06:41:26 1995 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * gdb.base/setvar.exp: Add new testcases for truncation when
+ assigning invalid values to bitfields.
+
+Sat Sep 2 00:17:31 1995 Fred Fish <fnf@cygnus.com>
+
+ * gdb.base/callfuncs.exp (do_function_calls): Remove
+ mips-sgi-irix* xfail for
+ "call inferior func with struct - returns char *"
+ and fix test so that an optional (unsigned char *) cast is
+ accepted in the result.
+
+Fri Sep 1 13:42:01 1995 Fred Fish <fnf@cygnus.com>
+
+ * gdb.base/funcargs.exp (float_and_integral_args): Remove
+ sparc-sun-solaris2* xfail for "print f1 after run to call2a".
+ * gdb.c++/Makefile.in (SUFFIXES): Add .SUFFIXES and ".cc" suffix.
+ * gdb.base/signals.exp: Remove duplicate "handle all print" test
+ that accidentally got checked in.
+
+Sun Aug 27 23:35:35 1995 Fred Fish <fnf@cygnus.com>
+
+ * gdb.base/callfuncs.exp (do_function_calls): Add alpha-dec-osf2*
+ clear_xfail for "p t_float_values2(3.14159,float_val2)" for gcc
+ compiled test.
+ * gdb.base/opaque.exp (setup_xfail_on_opaque_pointer):
+ Add mips-sgi-irix5* xfail for not gcc compiled.
+ * gdb.base/Makefile.in (nodebug.o): Also create nodebug.ci.
+ * gdb.base/nodebug.exp: Add mips-sgi-irix5 xfail when not gcc compiled for
+ "p top", "whatis top", "p middle", and "whatis middle".
+ * gdb.base/whatis.exp: Add mips-sgi-irix* xfail for
+ "whatis signed char" for not gcc compiled.
+ * gdb.base/setvar.exp: Add mips-sgi-irix4* xfail (works on irix5) for
+ "set variable signed char=-1 (-1)" and
+ "set variable signed char=0xFF (0xFF)" for not gcc compiled.
+ * gdb.base/funcargs.exp (float_and_integral_args):
+ Add mips-sgi-irix5* xfail for "run to call2a" for not gcc compiled.
+ Add mips-sgi-irix* xfail when not gcc compiled for
+ "continue to call2b".
+ Add mips-sgi-irix4* xfail (works with irix5) when gcc compiled for
+ "continue to call2g".
+ (discard_and_shuffle): Add mips-sgi-irix5* xfail whn not gcc compiled for
+ "backtrace from call6a"
+ (shuffle_round_robin): Add mips-sgi-irix* xfail when not gcc compiled for
+ "backtrace from call7k".
+ Add mips-sgi-irix5* xfail when not gcc compiled for
+ "backtrace from call7a".
+ (localvars_after_alloca): Fix gdb_test cmds for
+ "print * after runto ...".
+ Remove rs6000-*-* xfails for
+ "print i after runto localvars_after_alloca" and
+ "print l after runto localvars_after_alloca"
+ for all compilers.
+ * gdb.base/exprs.exp: Add mips-sgi-irix4* xfails (works with irix5),
+ when not compiled with gcc, for:
+ "print signed char == (minus)",
+ "print signed char != (minus)",
+ "print signed char < (minus)",
+ "print signed char > (minus)".
+ * gdb.base/callfuncs.exp (do_function_calls):
+ Add mips-sgi-irix* xfail, when compiled with native compiler, for
+ "call inferior func with struct - returns char *".
+ * gdb.base/return.exp (return_tests): Change xfail for
+ "correct value returned double test" to include Solaris 2.4.
+ * gdb.base/funcargs.exp (float_and_integral_args):
+ Add sparc-sun-solaris2* xfail for "print f1 after run to call2a".
+
+Sat Aug 26 00:26:11 1995 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * gdb.base/setvar.c, gdb.base/setvar.exp: Add new tests for
+ enumeration bitfields if compiling with GNU C.
+ * lib/gdb.exp: Consume `(y or n) ' in `Reinitialize source path
+ to empty' prompt.
+
+Tue Aug 22 00:30:37 1995 Jeff Law (law@snake.cs.utah.edu)
+
+ * gdb.base/scope.exp: xfail 'scope0.c'::filelocal_bss before run
+ test for PRO targets.
+
+ * gdb.base/funcargs.exp: Avoid ever setting more than 8
+ breakpoints in the inferior at any given time by making
+ two groups of breakpoints for call2*, call6* and call7*
+ tests.
+
+Sun Aug 20 06:58:25 1995 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * gdb.base/funcargs.exp: Fix typos introduced by Aug 15 change.
+ * gdb.base/callfuncs.c (main): Use struct_val1 to inhibit xlc
+ from optimizing it away.
+ * gdb.base/callfuncs.exp: Remove rs6000-*-* xfails for
+ "call inferior func with struct".
+
+Wed Aug 16 11:57:15 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ * configure.in: Only configure gdb.chill for particular targets.
+
+Tue Aug 15 09:42:44 1995 Fred Fish <fnf@cygnus.com>
+
+ * gdb.base/Makefile.in: Add action to .c.o transformation
+ rule that generates a .ci file for each .o file and remove
+ explicit .c.o rules except for callfuncs.o.
+ * gdb.c++/Makefile.in: Add .cc.o transformation rule that
+ generates a .ci file for each .o file and remove explicit
+ .cc.o rules.
+ (clean): Remove *.tmp *.ci files.
+ (EXECUTABLES): Remove templ-info.exp.
+ * gdb.base/compiler.c: New file.
+ * gdb.c++/compiler.cc: New file
+ * gdb.base/scope.exp: Source gdb.base/scope.ci.
+ Change rs6000-*-* xfail for
+ "print 'scope0.c'::filelocal_ro" and
+ "print 'scope1.c'::filelocal" and
+ "print 'scope1.c'::filelocal_bss" and
+ "print 'scope1.c'::filelocal_ro" and
+ "print 'scope1.c'::foo::funclocal" and
+ "print 'scope1.c'::foo::funclocal_ro" and
+ "print 'scope1.c'::bar::funclocal" and
+ "print 'scope0.c'::filelocal_ro" and
+ "print 'scope1.c'::filelocal at foo" and
+ "print 'scope1.c'::filelocal_bss at foo" and
+ "print 'scope1.c'::filelocal_ro at foo" and
+ "print 'scope1.c'::foo::funclocal at foo" and
+ "print 'scope1.c'::foo::funclocal_bss at foo" and
+ "print 'scope1.c'::foo::funclocal_ro at foo" and
+ "print 'scope1.c'::bar::funclocal at foo" and
+ "print 'scope0.c'::filelocal_ro" and
+ "print 'scope1.c'::filelocal" and
+ "print 'scope1.c'::filelocal_bss" and
+ "print 'scope1.c'::filelocal_ro" and
+ "print 'scope1.c'::foo::funclocal" and
+ "print 'scope1.c'::foo::funclocal_bss" and
+ "print 'scope1.c'::foo::funclocal_ro" and
+ "print 'scope1.c'::bar::funclocal" and
+ "print 'scope1.c'::bar::funclocal_bss"
+ to only be xfail'd when not compiled with gcc.
+ Add rs6000-*-* xfail for
+ "print 'scope0.c'::filelocal_bss before run"
+ when compiled with gcc.
+ (test_at_main): Add rs6000-*-* xfail for
+ "print filelocal_ro in test_at_main"
+ when compiled with gcc.
+ * gdb.base/ptype.exp: Source gdb.base/ptype.ci.
+ Add rs6000-*-aix* xfail for
+ "whatis unnamed typedef'd enum (compiler bug in IBM's xlc)" and
+ "ptype t_char_array", not compiled with gcc.
+ * gdb.base/list.exp (test_list_function): Add rs6000-*-*
+ xfail for "list foo (in include file)" when gcc compiled.
+ * gdb.base/funcargs.exp: Source gdb.base/funcargs.ci
+ (integral_args): Add rs6000-*-* xfail for
+ "run to call0a" if not compiled with gcc.
+ (unsigned_integral_args): Add rs6000-*-* xfail for
+ "run to call1a" if not compiled with gcc.
+ (float_and_integral_args): Add rs6000-*-* xfail for
+ "run to call2a" if not compiled with gcc and for
+ "continue to call2b" for any compiler.
+ Add rs6000-*-* xfail to
+ "print f1 after run to call2a" for gcc compiled.
+ (discard_and_shuffle): Add rs6000-*-* xfail for
+ "run to call6a".
+ (shuffle_round_robin): Add rs6000-*-* xfail for
+ "backtrace from call7a" if not compiled with gcc.
+ Add rs6000-*-* xfail for
+ "backtrace from call7b" if compiled with gcc.
+ (call_after_alloca): Add rs6000-*-* xfail for
+ "print c in call_after_alloca" and
+ "print s in call_after_alloca" and
+ "backtrace from call_after_alloca_subr"
+ if not compiled with gcc.
+ (localvars_in_indirect_call): Add rs6000-*-* xfail for
+ "print c in localvars_in_indirect_call" and
+ "print c in localvars_in_indirect_call" and
+ "backtrace in indirectly called function" and
+ "stepping into indirectly called function"
+ if not compiled with gcc.
+ (localvars_after_alloca): Add rs6000-*-* xfail for
+ "print c after runto localvars_after_alloca" and
+ "print s after runto localvars_after_alloca" and
+ "print i after runto localvars_after_alloca" and
+ "print l after runto localvars_after_alloca"
+ for all compilers.
+ * gdb.base/whatis.exp: Source gdb.base/whatis.ci rather
+ than whatis-info.exp.
+ * gdb.base/opaque.exp: Source gdb.base/opaque0.ci rather
+ than opaque-info.exp.
+ Setup rs6000-*-* xfail for
+ "ptype on opaque struct pointer (statically)" and
+ "ptype on opaque struct pointer (dynamically)" when
+ not compiled with gcc.
+ * gdb.base/callfuncs.exp: Source gdb.base/callfuncs.ci
+ rather than callf-info.exp.
+ (do_function_calls): Add clear_xfail for rs6000-*-* for
+ "p t_float_values2(3.14159,float_val2)". Seems to work
+ fine there, both with xlc and gcc. Need to find out what
+ it is doing right and fix other platforms.
+ * gdb.base/callfuncs.exp: Add rs6000-*-* xfail for
+ "call inferior func with struct - returns int",
+ "call inferior func with struct - returns long",
+ "call inferior func with struct - returns float",
+ "call inferior func with struct - returns double",
+ "call inferior func with struct - returns char *",
+ but only if not gcc compiled (presumes xlc compiled).
+ Change rs6000-*-* xfails for
+ "call inferior func with struct - returns char" and
+ " call inferior func with struct - returns short" to only
+ xfail if not using gcc.
+ (clean mostlyclean): Remove *.ci and *.tmp files.
+ * gdb.c++/templates.exp: Source gdb.c++/templates.ci rather
+ than templ-info.exp.
+ * gdb.base/langs.exp: Source gdb.base/langs.ci.
+ Add rs6000-*-* xfail for "up to foo in langs.exp"
+ "up to cppsub_ in langs.exp" and "up to fsub in langs.exp"
+ when not gcc compiled.
+
+Sat Aug 12 15:05:36 1995 Jeffrey A. Law <law@rtl.cygnus.com>
+
+ * gdb.base/callfuncs.exp: Add xfails for the powerpc.
+ * gdb.base/corefile.exp: Likewise.
+ * gdb.base/list.exp: Likewise.
+ * gdb.base/scope.exp: Likewise.
+ * gdb.base/siganls.exp: Likewise.
+
+ * gdb.base/nodebug.exp: Add xfails for the powerpc. Handle aix4
+ compiler output.
+ * gdb.base/whatis.exp: Likewise.
+
+Fri Aug 11 13:36:20 1995 Jeff Law (law@snake.cs.utah.edu)
+
+ * gdb.disasm/sh3.exp (all_fp_misc_tests): No longer expect a
+ failure (opcode table has been fixed to match reality).
+
+Mon Aug 14 09:01:59 1995 Fred Fish <fnf@cygnus.com>
+
+ * gdb.base/callfuncs.exp: Add rs6000-*-* xfails for
+ "call inferior func with struct - returns char",
+ "call inferior func with struct - returns short"
+
+ * gdb.base/scope.exp: Remove rs6000-*-* xfails for
+ "print 'scope0.c'::filelocal at main",
+ "print 'scope0.c'::filelocal_bss in test_at_main",
+ "print 'scope0.c'::filelocal at foo",
+ "print 'scope0.c'::filelocal_bss in test_at_foo",
+ "print 'scope0.c'::filelocal at bar",
+ "print 'scope0.c'::filelocal_bss in test_at_bar"
+
+ * gdb.base/list.exp: Remove rs6000-*-* xfail for "list function
+ in source file 1". This bug seems to have been fixed with both
+ gcc and native cc (was native assembler bug?).
+
+Wed Aug 9 08:04:12 1995 Fred Fish (fnf@cygnus.com)
+
+ * gdb.base/a1-selftest.exp: Change "i*86-*-sysv4" xfail for
+ "backtrace through signal handler" to "i*86-*-sysv4*".
+ * gdb.base/signals.exp: Add xfail for "'next' behaved as
+ continue" case. Add "known SVR4 bug" to fail message.
+ Add "i*86-*-bsdi2.0" xfail for "handle all print".
+ Add "i*86-*-bsdi2.0" xfail for "backtrace in signals_tests_1".
+ * gdb.base/ptype.exp: Add "i*86-*-sysv4*" xfail for
+ "whatis unnamed typedef'd enum..." and "ptype t_char_array".
+ * gdb.base/langs.exp: Add "i*86-*-sysv4*" xfail for
+ "up to foo in langs.exp", "show language at foo in
+ langs.exp", "up to cppsub_ in langs.exp", "show
+ language at cppsub_ in langs.exp", "up to fsub in
+ langs.exp", and "show language at fsub in langs.exp".
+ * gdb.base/corefile.exp: Add "i*86-*-sysv4*" to xfail for
+ "bactrace in corefile.exp".
+ * gdb.base/callfuncs.exp: Change xfail to "i*86-*-*" for
+ "call inferior function with struct - returns float" and
+ "call inferior function with struct - returns double".
+
+Mon Aug 7 02:43:28 1995 Jeff Law (law@snake.cs.utah.edu)
+
+ * gdb.disasm/sh3.s: Source for sh3 disassembler tests.
+ * gdb.disasm/sh3.exp: Run the sh3 disassembler tests.
+ * gdb.disasm/configure.in (sh-*-*): Use sh3.mt makefile fragment.
+ * gdb.disasm/sh3.mt: Makefile fragment for sh3 ests.
+
+Mon Aug 7 08:09:37 1995 Fred Fish <fnf@cygnus.com>
+
+ * Makefile.in (CHILL_FOR_TARGET): Use previously defined
+ (or overriden) "CHILL" macro rather then bare "gcc".
+ Also look for ../../gcc/xgcc since that is what we will
+ actually need, not "Makefile". Remove following assignment
+ of CHILL to CHILL_FOR_TARGET because that results in
+ recursive definition.
+
+Sun Aug 6 16:52:29 1995 Fred Fish <fnf@cygnus.com>
+
+ * gdb.base/corefile.exp: Change xfail for backtrace in
+ corefile.exp from linuxaout to all linux.
+ * gdb.base/sigall.exp (test_one_sig): Specifically deal with
+ cases where we miss the breakpoint at the signal handler
+ for some reason. Setup xfail for linuxoldld/linuxaout and
+ getting SIGIO. Setup xfail for linuxoldld/linuxaout for
+ hitting SIGURG breakpoint.
+ * gdb.base/signals.exp: Setup xfail for "next" acting like
+ continue to add linuxoldld. Setup xfail for all linux for
+ "next to handler in signals_tests_1", "backtrace in
+ signals_tests_1", "continue to func1", "pass SIGUSR1",
+ and continue to handler".
+
+Thu Aug 3 10:45:37 1995 Fred Fish <fnf@cygnus.com>
+
+ * Update all FSF addresses except those in COPYING* files.
+
+Sun Jul 30 17:50:35 1995 Fred Fish <fnf@cygnus.com>
+
+ * gdb.base/a2-run.exp: Change messages to be more explicit about
+ the status of args, and quote binfile in results.
+
+Sun Jul 30 10:24:20 1995 Fred Fish <fnf@cygnus.com>
+
+ * gdb.base/callfuncs.exp: Add tests for passing structs to
+ inferior functions and return various types.
+ * gdb.base/callfuncs.c: Add functions to receive a struct
+ and return a member of the struct, in various types.
+
+Sat Jul 29 14:22:33 1995 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * gdb.base/Makefile.in (clean): Remove callf-info.exp.
+
+Fri Jul 28 13:36:11 1995 Brendan Kehoe <brendan@lisa.cygnus.com>
+
+ * config/vxworks29k.exp: New file, sources vxworks.exp.
+
+Fri Jul 28 00:28:36 1995 Jeffrey A. Law <law@rtl.cygnus.com>
+
+ * config/gdbremote.exp: New file. Testing framework using
+ gdbserver.
+
+Thu Jul 27 12:17:14 1995 Fred Fish (fnf@cygnus.com)
+
+ * gdb.base/interrupt.exp: Setup "i*86-*-linux" xfail for
+ "call function when asleep" and "send end of file".
+ * gdb.base/corefile.exp: Add "i*86-*-linuxaout" to xfail list
+ for "backtrace in corefile.exp".
+ * gdb.base/a1-selftest.exp: Add "i*86-*-linux*" to xfail list
+ for "backtrace through signal handler".
+ * gdb.base/corefile.exp: Make sure we actually generate a core file
+ before trying the core tests. Some systems allow the user to suppress
+ generation of core files and default to that (linux for example).
+ * gdb.base/signals.exp: Change xfail for "next" acting like "continue"
+ from "i*86-*-linux" to "i*86-*-linuxaout". Works with ELF beta.
+
+Tue Jul 25 17:30:10 1995 Jeffrey A. Law <law@rtl.cygnus.com>
+
+ * gdb.threads: New directory with some crude multi-threaded
+ gdb tests (step.exp and step2.exp).
+ * config/mt-lynx (STEP_EXECUTABLE): Define.
+ (THREADFLAGS): Define.
+
+Tue Jul 25 01:03:52 1995 Jeff Law (law@snake.cs.utah.edu)
+
+ * gdb.base/sigall.exp: Avoid losing in SIGPRIO test on lynx.
+
+ * gdb.base/signals.exp: Disable whole file for lynx until
+ further notice.
+
+ * gdb.base/signals.exp: xfail test where "next" acts like
+ "continue" for lynx.
+
+ * gdb.base/interrupt.exp: xfail test for calling function while
+ inferior is asleep for lynx.
+
+ * gdb.base/watchpoint.exp: Handle more cases of gdb echoing more
+ than one cr-lf after each command.
+
+Sun Jul 23 23:33:18 1995 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * configure.in: Reinstate setting of stabsdirs variable, fix
+ typo in setting up configdirs for native builds.
+
+ * gdb.base/return.exp: Fix typo in return double test.
+ * gdb.base/return.c (tmp2, tmp3): Made global to inhibit the
+ compiler from optimizing them away.
+
+Fri Jul 21 11:39:34 1995 Jeff Law (law@snake.cs.utah.edu)
+
+ * gdb.base/gdbvars.exp: Expect zero or more additional cr-lf
+ sequences to be echo'd by gdb when using gdb_test.
+ * gdb.chill/chexp.exp: Likewise.
+ * gdb.fortran/exprs.exp: Likewise
+
+Thu Jul 20 13:28:36 1995 Jeffrey A. Law <law@rtl.cygnus.com>
+
+ * gdb.base/a1-selftest.exp: Reset the timeout value to 30 seconds
+ after the inferior gdb has started.
+
+ * gdb.base/a2-run.exp: Handle gdb echoing more than one cr-lf
+ after each command.
+ * gdb.base/funcargs.exp: Likewise.
+ * gdb.base/gdbvars.exp: Likewise.
+ * gdb.base/interrupt.exp: Likewise.
+ * gdb.base/list.exp: Likewise.
+ * gdb.base/watchpoint.exp: Likewise.
+ * gdb.c++/demangle.exp: Likewise.
+ * gdb.c++/inherit.exp: Likewise.
+ * gdb.chill/chexp.exp: Likewise.
+ * gdb.fortran/exprs.exp: Likewise.
+
+ * gdb.base/watchpoint.exp: Disable watchpoint triggered in syscall
+ test if we can't handle IO to/from the inferior.
+
+ * gdb.c++/misc.exp: Always check for a program already being
+ started after sending a "run" command to gdb.
+
+ * gdb.base/twice.exp: Start with a fresh gdb.
+
+ * gdb.chill/chexp.exp: Remove skip_chill_tests check; these tests
+ only depend on gdb's expression code, not the chill runtime.
+
+ * gdb.base/return.c: Put return values into variables so we
+ can have gdb print them rather than depending on the program
+ to print them.
+ * gdb.base/return.exp: Corresponding changes.
+
+ * lib/gdb.exp: Provide default value for noinferiorio.
+ * gdb.base/interrupt.exp: Skip tests if we can't handle IO to/from
+ the inferior.
+
+ * gdb.base/break.exp: Always check for a program already being
+ started after sending a "run" command to gdb.
+ (text_next_with_recursion): Don't check the output from the
+ program's printf statement. Instead just make sure the program
+ exited.
+
+ * gdb.base/commands.exp: Protect tests which need arguments with
+ $noargs conditionals.
+
+Wed Jul 19 22:42:43 1995 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * gdb.base/printcmds.exp: Adjust expect patterns for addresses
+ of structure member arrays to match gdb/valops.c:value_addr change.
+
+Mon Jul 17 10:12:27 1995 Jeff Law (law@snake.cs.utah.edu)
+
+ * gdb.base/a1-selftest.exp: Fix unmatched quotes in many timeout
+ cases.
+
+Wed Jul 12 10:20:08 1995 Fred Fish (fnf@cygnus.com)
+
+ * configure.in (configdirs): Remove gdb.chill from default list
+ of subdirs and then add it back in only if doing a native build.
+ The current chill compiler does not yet work in any cross build.
+ * Revert all signal changes from Jul 6.
+ * gdb.base/{sigall.c signals.c}: Define away signal() and alarm()
+ for sh-hms targets, allowing these tests to link, with no other
+ changes. Testing is suppressed by setting "nosignals" in site.exp.
+
+Thu Jul 6 20:58:30 1995 Fred Fish (fnf@cygnus.com)
+
+ * configure.in (signaldirs): Define and add to configdirs for all
+ targets except some specific ones that are known to not support signals.
+ Also clean up formatting.
+ * gdb.base/Makefile.in (EXECUTABLES): Remove sigall and signals.
+ (signals, sigall): Remove rules to build.
+ * gdb.base/{sigall.c, sigall.exp, signals.c, signals.exp}:
+ Moved to new gdb.signals directory.
+ * gdb.signals: New test directory.
+ * gdb.signals/{Makefile.in, configure.in, sigall.c, sigall.exp,
+ signals.c signals.exp}: New or moved files.
+
+Sun Jun 25 12:55:18 1995 Jeff Law (law@snake.cs.utah.edu)
+
+ * gdb.base/interrupt.exp: Don't choke if $nointerrupts doesn't exist.
+
+Wed Jun 21 16:35:55 1995 Fred Fish <fnf@cygnus.com>
+
+ * gdb.base/return.exp: Xfail `return double' test failure
+ on at least Solaris 2.3 and handle future/past versions on
+ a case by case basis as appropriate. Also update message
+ to include i*86 failures.
+
+Wed May 24 07:10:10 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * Makefile.in: Change variable CFLAGS to TESTSUITE_CFLAGS.
+
+ * lib/gdb.exp: Fix comment which erroneously identified
+ gdb_file_cmd as gdb_load (the 19 May change was in fact to
+ gdb_file_cmd not gdb_load).
+ * config/unix-gdb.exp (gdb_load): Add "upvar timeout timeout".
+
+ * gdb.base/setvar.exp: Make test names consistent between pass and
+ fail cases. Use gdb_test more.
+
+Fri May 19 07:22:58 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * lib/gdb.exp (gdb_load): Add "upvar timeout timeout".
+
+Mon May 15 23:50:51 1995 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * gdb.base/help.exp: Fix expected help string for `show commands'.
+
+Thu May 11 07:55:11 1995 Jim Kingdon <kingdon@deneb.cygnus.com>
+
+ * gdb.stabs/xcoff.sed: Change N_LSYM to C_DECL not C_LSYM.
+
+ * gdb.stabs/weird.exp: Remove xfail for xcoff bitching about lack
+ of a text section.
+
+Thu May 11 15:02:24 1995 Stu Grossman (grossman@andros.cygnus.com)
+
+ * config/monitor.exp (gdb_target_monitor): Fix loop interator so
+ that loop eventually terminates. Fix Connection refused logic so
+ that testsuite will expire nicely.
+
+Wed May 10 17:57:35 1995 Stu Grossman (grossman@andros.cygnus.com)
+
+ * config/cpu32bug.exp, config/est.exp, config/hppro.exp,
+ config/rom68k.exp: New tcl glue for the appropriate monitors.
+ These all just end up calling monitor.exp.
+ * config/monitor.exp (gdb_target_monitor): Handle `Connection
+ refused' by retrying. Cleanup some timeout issues.
+ * (gdb_load): Reduce timeout. Cleanup some timeout issues.
+ * lib/gdb.exp (gdb_test gdb_test_exact): Upvar timeout so that
+ callers don't have to set/restore global timeout variable.
+
+ * The following set of changes centralizes management of the global
+ timeout variable. This way, it can be set in one target dependent
+ place instead of dozens of places scattered throughout the test suite.
+ If you need to lengthen a timeout, then you should either set timeout
+ in one of the config/{target}.exp files, or multiply it by a factor.
+ Setting it to an absolute value is always going to lose for some
+ targets.
+ * gdb.base/a1-selftest.exp (test_with_self): Only use local timeout.
+ * gdb.base/callfuncs.exp (do_function_calls): Don't set timeout.
+ * gdb.base/funcargs.exp: Don't set timeout.
+ * gdb.base/list.exp (test_forward_search): Only use local timeout.
+ * gdb.base/printcmds.exp (test_print_string_constants
+ test_print_array_constants): Don't set timeout.
+ * gdb.base/ptype.exp: Don't set timeout.
+ * gdb.base/recurse.exp: Don't set timeout.
+ * gdb.base/return.exp: Don't set timeout.
+ * gdb.base/watchpoint.exp: Don't set timeout.
+ * gdb.c++/classes.exp (do_tests): Don't set timeout.
+ * gdb.c++/virtfunc.exp (test_virtual_calls): Don't set timeout.
+
+Wed May 10 16:03:23 1995 Torbjorn Granlund <tege@adder.cygnus.com>
+
+ * Makefile.in: Make clean targets work also when SUBDIRS is empty.
+
+Mon May 1 07:32:48 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * lib/gdb.exp: Disable chill tests for irix5.
+
+Wed Apr 26 07:36:03 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.base/scope.exp: Make test names unique. Use gdb_test. Make
+ each test pass or fail.
+
+Sun Apr 23 21:32:32 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.base/opaque.exp: Remove xfails for aix; print a warning if
+ xlc not gcc.
+
+Fri Apr 21 15:44:02 1995 Stu Grossman (grossman@rtl.cygnus.com)
+
+ * cpu32bug.exp est.exp rom68k.exp: Delete. Unify into monitor.exp.
+
+Wed Apr 19 17:41:21 1995 Stu Grossman (grossman@cygnus.com)
+
+ * config/est.exp: Fix copyright and comments. Remove dead code.
+ Use targetname, serialport and baud variables instead of fixed
+ constants.
+ * config/rom68k.exp: Fix copyright and comments. Remove dead code.
+ * config/cpu32bug.exp: New file to support cpu32bug monitors.
+
+Wed Apr 19 13:47:16 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.base/watchpoint.exp: Don't run
+ test_watchpoint_triggered_in_syscall for sunos.
+
+Mon Apr 17 12:48:52 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.base/{break.c,run.c}: Don't include vxWorks.h or stdioLib.h;
+ they don't seem to exist. Do include stdio.h.
+
+Fri Apr 14 09:40:22 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.base/a1-selftest.exp: Add alpha xfail.
+
+Mon Apr 10 13:07:50 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.base/watchpoint.c (main): Prompt before calling read().
+ * gdb.base/watchpoint.exp (test_watchpoint_triggered_in_syscall):
+ Revise accordingly. Remove cruft about sending "123" several
+ times, until it gets noticed. Clean up the "print buf[0]" stuff
+ so that it passes or fails, and waits for prompts in the usual way.
+
+Sun Apr 9 09:02:36 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.base/recurse.exp: Fix comment.
+
+ * TODO: Remove item about printing variables in nodebug.exp. Add
+ item about enabling tests which are only run on some targets.
+
+ * gdb.base/watchpoint.exp: Various cleanups (make each test pass or
+ fail, make test names unique, use new gdb_test convention
+ regarding pattern, use gdb_test more, etc.).
+
+ * gdb.base/bitfields.exp: Various cleanups (make each test pass or
+ fail, make test names unique, etc.).
+
+Sat Apr 8 02:47:45 1995 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * gdb.base/nodebug.c: Change return type of top and middle to
+ short.
+ * gdb.base/nodebug.exp: Remove xfails for ecoff systems, they
+ are fixed by the recent mdebugread.c changes. Allow `short ()'
+ as type for top and middle.
+
+Thu Apr 6 08:54:18 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.base/break.exp: Remove commented out if $usestubs {}. As
+ nearly as I can tell, the whole thing was an accident in Stu's
+ change of 24 Mar 1995 (logged in ../ChangeLog), in which he meant
+ to replace a send/expect pair with gdb_test, but ended up only
+ adding the gdb_test. My change of 24 Mar 1995 and Kung's change
+ of 30 Mar 1995 took care of it, but left this vestigial comment
+ which I am now nuking.
+
+Mon Apr 3 09:00:27 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.base/break.exp: Look for different line number for
+ breakpoint at main depending on usestubs.
+
+Sun Apr 2 08:15:45 1995 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * gdb.base/list.exp: Adjust some alternate expect patterns to
+ match recent list0.c change. Add alternate expect pattern for
+ output from `list default lines around main' for optimizing
+ compilers.
+
+Sat Apr 1 07:23:22 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * lib/gdb.exp: If nosignals is not set, set it to 0.
+
+Fri Mar 31 16:13:48 1995 Kung Hsu <kung@mexican.cygnus.com>
+
+ * config/slite-gdb.exp: Responds to load symbol table prompt.
+ * gdb.base/break.exp: Adjust line number, fix rerun.
+ * gdb.base/langs0.c: Add #ifdef usestubs.
+
+Thu Mar 30 15:36:55 1995 Kung Hsu <kung@mexican.cygnus.com>
+
+ * gdb.base/list.exp: Adjust line contents after adding new lines in
+ list0.c. Also fix a syntax error.
+
+ * lib/gdb.exp (gdb_run_cmd): Special handling for targets use stubs.
+ * gdb.base/break.exp: ditto.
+ * gdb.base/list.exp: ditto.
+ * gdb.base/bitfields.c: Add #ifdef usestubs in main().
+ * gdb.base/run.c: ditto.
+ * gdb.base/list0.c: ditto.
+ * gdb.base/funcargs.c: ditto.
+
+Wed Mar 29 17:09:29 1995 Stu Grossman (grossman@cygnus.com)
+
+ * testsuite/config/rom68k.exp (gdb_target_rom68k): Use
+ $targetname, $serialport and $baud instead of hardwired variables.
+ * testsuite/gdb.base/{sigall.exp signals.exp}: Skip these if the
+ target doesn't support signals.
+
+Wed Mar 29 12:29:34 1995 Kung Hsu <kung@mexican.cygnus.com>
+
+ * lib/gdb.exp (runto_main): Fix regular expression bug, add return 1.
+
+Tue Mar 28 08:46:45 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.base/recurse.exp: Make test names unique. Change \\(+ to \\(.
+ Don't rely on the value of an auto variable before it has been
+ initialized. Use gdb_test more.
+
+Mon Mar 27 08:00:34 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * lib/gdb.exp (default_gdb_version): A version number must start
+ with a digit, but other than that contains all characters up to
+ the first whitespace character.
+
+Sun Mar 26 13:19:32 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.base/commands.exp (breakpoint_command_test): New tests.
+
+Sat Mar 25 15:38:06 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.c++/*.exp: Warn if executable does not exist. The original
+ reason for skipping the warning was that configure.in sometimes
+ intentionally skipped building the executables but the tcl code
+ had no way of knowing. That (a) was always bogus with respect to
+ error handling, (b) is no longer true (right now there is no way
+ to skip C++ tests).
+
+ * gdb.c++/demangle.exp: Remove unused binfile and srcfile variables.
+
+Sat Mar 25 01:16:10 1995 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * gdb.base/list.exp: Add expect patterns for output from
+ SunPRO compiled executables.
+ * gdb.base/whatis.exp: Allow leading `signed' for all v_signed_*
+ types.
+
+Fri Mar 24 06:11:05 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.base/break.exp (test_next_with_recursion): Accept any line
+ number (we are already testing that the correct source line text
+ gets printed).
+
+ * gdb.base/break.exp: Make one test if $usestubs. I'm not sure
+ that is what is intended, but something needed to be done to get
+ sunos4 native working again.
+
+ * gdb.c++/misc.cc (main): Fix typo (#iffef -> #ifdef).
+
+ * gdb.base/a1-selftest.exp (test_with_self): Remove comment which
+ apparently went with a (very) old xfail.
+
+Fri Mar 24 13:41:09 1995 Kung Hsu <kung@mexican.cygnus.com>
+
+ * gdb.base/callfuncs.exp: call runto_main instead of runto main.
+ runto_main is a proc in gdb.exp that will do 'step' for target use
+ stubs.
+ * gdb.base/exprs.exp: ditto.
+ * gdb.base/interrupt.exp: ditto.
+ * gdb.base/opaque.exp: ditto.
+ * gdb.base/printcmds.exp: ditto.
+ * gdb.base/ptype.exp: ditto.
+ * gdb.base/scope.exp: ditto.
+ * gdb.base/setvar.exp: ditto.
+ * gdb.base/signals.exp: ditto.
+ * gdb.base/twice.exp: ditto.
+ * gdb.c++/classes.exp: ditto.
+ * gdb.c++/inherit.exp: ditto.
+ * gdb.c++/templates.exp: ditto.
+ * gdb.base/break.exp: no run and hit main for stubs. Change line
+ numbers for breakpoints and info breakpoint.
+ * gdb.base/break.c: Add #ifdef usestubs for set_debug_traps() and
+ breakpoint().
+ * gdb.base/callfuncs.c: ditto.
+ * gdb.base/exprs: ditto.
+ * gdb.base/interrupt.c: ditto.
+ * gdb.base/opaque0.c: ditto.
+ * gdb.base/printcmds.c: ditto.
+ * gdb.base/ptype.c: ditto.
+ * gdb.base/scope0.c: ditto.
+ * gdb.base/setvar.c: ditto.
+ * gdb.base/signals.c: ditto.
+ * gdb.base/twice.c: ditto.
+ * gdb.c++/misc.cc: ditto.
+ * gdb.c++/templates.cc: ditto.
+
+Fri Mar 24 06:11:05 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * config/vx-gdb.exp, lib/gdb.exp: Regexp cleanups (\[(\] -> \\(, etc.).
+
+ * gdb.base/a1-selftest.exp: Don't check for # followed by a digit
+ somewhere between `read' and `main.c'. I'm pretty sure the
+ pattern ".*#\[0-9\].*" was slowing down pattern matching a lot,
+ and it isn't particularly useful.
+
+ * gdb.base/scope.exp: Make test names unique. \[(\] -> \\(.
+
+Thu Mar 23 14:58:35 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.base/commands.exp (infrun_breakpoint_command_test): New test.
+
+Wed Mar 22 18:36:05 1995 Kung Hsu <kung@mexican.cygnus.com>
+
+ * config/mt-slite: add LIBS and -nostdlib.
+ * config/slite-gdb.exp: add this new file to support sparclite target.
+
+Tue Mar 21 21:41:04 1995 Doug Evans <dje@canuck.cygnus.com>
+
+ * config/vx-gdb.exp (gdb_load): Update test of vxworks_ld return code.
+
+ * gdb.base/a2-run.exp: Change argument to istarget from
+ "*-*-vxworks" to "*-*-vxworks*".
+ * gdb.base/{break.exp,default.exp,scope.exp}: Likewise.
+
+Tue Mar 21 17:08:47 1995 Kung Hsu <kung@mexican.cygnus.com>
+
+ * lib/gdb.exp: add proc runto_main, for targets that use stubs, this
+ will not runto main but do a 'step' to step out of breakpoint().
+ * config/mt-slite: add -Dusestubs.
+
+Tue Mar 21 12:14:12 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.base/printcmds.exp (test_artificial_arrays): Send ^V@
+ instead of just @.
+
+ * gdb.base/signals.exp: Add test for "handle all print".
+ * TODO: Remove "handle all print". Also remove item about
+ checking copyright date (I don't like the idea of a spurious FAIL
+ based on when we run the tests).
+
+ * gdb.base/recurse.exp: Enable test for SunOS4. xfail one test
+ for SunOS4 (reason for failure not investigated). Remove
+ redundant test for $binfile.
+
+ * gdb.base/nodebug.c (array_index): Call malloc.
+
+ * gdb.base/{corefile.exp,default.exp}: Make names of "up" tests unique.
+
+Mon Mar 20 10:08:17 1995 Jeff Law (law@snake.cs.utah.edu)
+
+ * gdb.base/recurse.exp: Update gdb_test invocation to use new
+ conventions and slightly simplify the matching regexp.
+
+Fri Mar 17 05:43:28 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.base/break.exp: Update gdb_test invocation to use new
+ convention.
+
+ * lib/gdb.exp: If noargs is not set, set it to 0.
+
+ * gdb.base/nodebug.exp: Comment out redundant test. Make name of
+ tests unique.
+
+ * lib/gdb.exp: Skip CHILL for AIX and Solaris.
+
+Thu Mar 16 16:27:07 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.base/nodebug.exp: It is OK if GDB thinks top and middle have
+ one argument of type "<non-float parameter>".
+
+Wed Mar 15 15:54:56 1995 Stu Grossman (grossman@cygnus.com)
+
+ * config/rom68k.exp: New file to support Motorola IDP board.
+ * gdb.base/a2-run.exp: Skip this file if noargs is set.
+ * gdb.base/break.c: Change things around so that this program
+ doesn't depend upon args. This is necessary to make remote
+ targets work (in general, they can't take args).
+ * gdb.base/break.exp: Don't try to send args to program. Don't
+ expect output. Also, replace lots of code with gdb_test.
+
+Wed Mar 15 04:11:14 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.base/printcmds.exp (test_character_literals_accepted): Test
+ printing of '\'' (which is what the comment says we are testing,
+ even though we were not), not '''.
+ (test_integer_literals_rejected): Test that printing ''' is an error.
+
+ * gdb.fortran/exprs.exp, gdb.fortran/types.exp,
+ gdb.chill/chexp.exp, gdb.base/printcmds.exp,
+ gdb.c++/cplusfuncs.exp, gdb.chill/callch.exp, gdb.chill/misc.exp,
+ gdb.chill/pr-6292.exp, gdb.chill/string.exp, gdb.chill/tuples.exp:
+ Use gdb_test not test_print_accept.
+ * lib/gdb.exp: Remove test_print_accept.
+
+ * gdb.base/signals.exp (signal_tests_1): Make pass message
+ consistent with fail message.
+
+ * gdb.base/whatis.exp: Remove xfails for printing char vs.
+ unsigned char; the bug (PR 1821) is fixed.
+
+ * gdb.base/scope.exp: Remove xfails for PRs 1843 and 1868.
+
+ * gdb.base/scope.exp (test_at_localscopes): Call pass for
+ successful tests--makes xfailing them work right.
+
+Tue Mar 14 07:39:19 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * lib/gdb.exp (gdb_test): Between $pattern and $prompt, expect
+ only \r\n, not .*. The test can pass .* as the last thing in
+ $pattern if that is what it wants. In addition to providing this
+ flexibility, this change should speed up pattern matching in cases
+ where the pattern already ended with .* (there were a number of
+ them). This change also helps catch bad patterns--in the old
+ scheme the typo "char \*" instead of "char \\*" would pass. Now
+ it is caught.
+ * Many .exp files: Update callers.
+
+ * gdb.base/funcargs.exp: Replace \[(\]+ with \\(. The latter is
+ clearer and does not spuriously match multiple ('s. Likewise for
+ ) and *.
+
+ * gdb.base/nodebug.exp: Test ability to call a function and pass
+ it a string (even with no debugging info).
+
+ * gdb.base/printcmds.exp (test_integer_literals_rejected): Change
+ "p '\'", which is the same as "p ''" once tcl gets done with
+ quoting, to "p '\\'", which I suspect is what is intended (one
+ backslash gets sent to GDB).
+
+ * gdb.base/printcmds.exp (test_artificial_arrays): New tests.
+
+Fri Mar 10 13:31:46 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.base/a1-selftest.exp: Remove xfail for solaris. The bug (PR
+ 1817) was fixed literally years ago.
+
+Fri Mar 10 02:49:40 1995 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * gdb.base/funcargs.exp (call_after_alloca): Remove `next'
+ test, it causes stepping out of call_after_alloca_subr with
+ optimizing compilers.
+ (localvars_in_indirect_call): Consume GDB prompt if `finish'
+ fails.
+
+ * gdb.c++/templates.exp: Source templ-info.exp only if
+ the templates executable exists.
+
+ * gdb.c++/misc.cc (class Contains_static_instance,
+ class Contains_nested_static_instance),
+ gdb.c++/classes.exp (test_static_members): Test printing of
+ a class that contains a static instance of the class.
+
+Thu Mar 9 11:43:55 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.base/langs2.c (cppsub_): Don't prototype.
+ * gdb.base/langs2.cxx (cppsub_): Fix prototype (cosmetic value
+ only, I believe).
+
+Wed Mar 8 10:29:33 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * lib/gdb.exp (skip_chill_tests): New procedure.
+
+ * gdb.base/signals.exp (signal_tests_1): xfail for irix.
+
+Mon Mar 6 10:44:06 1995 Jeff Law (law@snake.cs.utah.edu)
+
+ * gdb.disasm/hppa.exp: Delete redundant ".*" at the beginning of
+ each expect pattern. Cuts runtime from 12 to about 4 seconds.
+
+Thu Mar 2 05:31:34 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.base/langs.exp: Don't insist that foo__Fi be demangled.
+
+ * gdb.disasm/hppa.exp (all_fpu_comparison_tests): Only
+ disassemble 8, not 16, instructions for part 4.
+
+ * config/vx-gdb.exp (gdb_start): Use \030, not \CX. tcl doesn't
+ support the latter anymore.
+
+ * gdb.base/Makefile.in: Try compiling callfuncs.c, if that fails try
+ -DNO_PROTOTYPES.
+ * gdb.base/callfuncs.c: Control use of prototypes based on
+ NO_PROTOTYPES, not __STDC__.
+ * gdb.base/callfuncs.exp (do_function_calls): xfail one of the
+ t_float_values2 tests if prototypes in use.
+
+ * gdb.base/callfuncs.c (t_float_values, t_float_values2,
+ t_double_values): When checking differences against DELTA, check
+ that difference is within the range (-DELTA,DELTA), not just
+ (-infinity,DELTA).
+
+Tue Feb 28 16:28:54 1995 Kung Hsu <kung@mexican.cygnus.com>
+
+ * config/mips-gdb.exp (gdb_load): In every test case, we need to do
+ 'file' command firts, then 'target', then 'load', this is due to gdb
+ target set up.
+ * config/mips-gdb.exp: Fix a couple regular exp bugs.
+
+Thu Feb 23 17:44:55 1995 Jeff Law (law@snake.cs.utah.edu)
+
+ * gdb.disasm/hppa.s (fmemLRbug_tests): Add tests for the indexing
+ FP load/store variants.
+ * gdb.disasm/hppa.exp (fmemLRbug_tests): Test new variants.
+
+Wed Feb 22 18:29:08 1995 Jim Kingdon <kingdon@rtl.cygnus.com>
+
+ * gdb.base/term.exp: Do not give a warning if not native, it is
+ not an abnormal condition.
+
+Tue Feb 21 13:08:47 1995 Jim Kingdon <kingdon@cygnus.com>
+
+ * gdb.base/ptype.exp: Accept char[0] as well as char[] for "ptype
+ t_char_array".
+
+Sun Feb 19 13:10:06 1995 Jim Kingdon <kingdon@rtl.cygnus.com>
+
+ * lib/gdb.exp (default_gdb_version): Pass GDBFLAGS to gdb when we
+ are getting the version number.
+
+ * gdb.base/{a1-selftest.exp,corefile.exp}: Do not give a warning
+ if not native, it is not an abnormal condition.
+
+Thu Feb 16 15:56:56 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * lib/gdb.exp: Just use "file exists", rather than undocumented
+ dejagnu procedure "findfile".
+
+Thu Feb 16 10:30:24 1995 J.T. Conklin <jtc@rtl.cygnus.com>
+
+ * config/mt-vxworks (CFLAGS): Set to -g -Dvxworks.
+ (LDFLAGS): Set to -Xlinker -Ur.
+
+ * Makefile.in, gdb.{base,c++,chill}/Makefile.in (GDB, GDBFLAGS):
+ Removed, these values are set by lib/gdb.exp.
+
+ * lib/gdb.exp: If GDBFLAGS is unset, set it to -nx.
+
+Wed Feb 15 14:23:28 1995 J.T. Conklin <jtc@rtl.cygnus.com>
+
+ * config/vx-gdb.exp (spawn_vxgdb): Use default_gdb_start instead
+ of replicating gdb startup code.
+
+ * config/mt-vxworks (LDFLAGS): Set to -r.
+ (CFLAGS_FOR_TARGET): Removed.
+
+ * config/vx-gdb.exp: always set prompt; gdb.exp sets it to
+ (gdb) and gdb for vxworks uses (vxgdb).
+
+ * Makefile.in, gdb.{base,c++,chill}/Makefile.in (GDB): If a gdb
+ executable is not in the tree and host != target, use sed and
+ program_transform_name to determine the gdb name used by the
+ target.
+
+ * configure.in, gdb.{base,c++,chill}/configure.in: changed so
+ *-*-vxworks* matches vxworks and *-*-netware* matches NetWare.
+
+Sun Feb 12 08:11:58 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.base/{callfuncs.exp,callfuncs.c}: Add tests for passing
+ floats, chars, and shorts where there are ANSI-style function
+ definitions.
+
+ * gdb.base/langs.exp, gdb.base/langs*: New test.
+ * gdb.base/Makefile.in: Build it.
+ * TODO: Remove item about checking that C names don't get C++
+ demangling applied; this test tests it.
+
+Thu Feb 9 12:43:56 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.stabs/weird.exp: Remove "Haven't examined" comment which
+ went with the const70 xfail. The xfail went away a year ago.
+
+ * gdb.base/signals.exp: Rename a bunch of tests to give unique names.
+
+ * gdb.base/corefile.exp: Give backtrace test unique name. xfail
+ for hp300.
+
+ * gdb.base/interrupt.exp: Also xfail hpux (for hp300).
+
+ * gdb.base/a1-selftest.exp: Don't run on hp300.
+
+Sat Feb 4 15:04:32 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * Makefile.in (site.exp): Set host_alias and target_alias as well
+ as host_triplet and target_triplet.
+
+Wed Feb 1 08:03:48 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.base/a1-selftest.exp: Invoke stty before starting inferior.
+
+ * gdb.base/nodebug.exp: Add xfails for ultrix and irix5 (same
+ places as other ecoff systems).
+
+ * gdb.base/a1-selftest.exp (test_with_self): Don't invoke stty on
+ ultrix.
+
+Mon Jan 30 11:44:52 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.base/nodebug.c (inner): Use variables so AIX linker doesn't
+ remove them.
+ * gdb.base/nodebug.exp: Accept "function" in addition to "text
+ variable and "variable" in addition to "data variable".
+ * gdb.base/nodebug.exp: xfail datalocal and bsslocal tests for AIX.
+
+ * gdb.base/list.exp (test_forward_search): Set listsize to 4 not
+ 2.
+ * gdb.base/list1.c (long_line): Add additional statement at start
+ of function.
+ * gdb.base/list.exp (test_forward_search): Update line number to
+ reflect new statement.
+
+Sun Jan 29 13:34:25 1995 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * gdb.base/signals.exp: Reinitialize searched source directories
+ after gdb_start call.
+
+Sat Jan 28 01:34:44 1995 Jeff Law (law@snake.cs.utah.edu)
+
+ * gdb.disasm/Makefile.in (clean): Delete "errs" file.
+ * gdb.stabs/Makefile.in: Likewise.
+
+ * gdb.disasm/hppa.exp (all_fpu_comparison_tests): Revert last
+ change. Instead split the tests into smaller pieces.
+ * gdb.disasm/hppa.s: Corresponding changes.
+
+Fri Jan 27 09:24:51 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.base/a1-selftest.exp (test_with_self), gdb.base/interrupt.exp:
+ Quote ^C when passing it to stty. For some shells ^ is a pipe.
+
+ * gdb.base/funcargs.exp: Modify many tests so that every test
+ either passes or fails. Make some test names unique.
+
+Thu Jan 26 19:20:34 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.base/a1-selftest.exp (test_with_self), gdb.base/interrupt.exp:
+ Call stty to set interrupt character.
+
+ * gdb.disasm/hppa.mt (hppa), gdb.stabs/hppa.mt (weird.o): Check
+ for HP assembler versus GNU assembler based on actual behavior of
+ $(CC), rather than assuming that $(AS) is always the GNU assembler.
+
+ * TODO: Suggest a few more stepping tests.
+
+Wed Jan 25 14:52:41 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ * gdb.base/default.exp: xfail no-stack backtraces for h8300,
+ restart GDB for h8300 after a continue.
+ (return): Add pattern to match a29k-udi behavior.
+ * gdb.base/nodebug.exp: Remove obsolete comment.
+ * gdb.base/regs.exp: New file, testing of register displays.
+ * gdb.base/return.exp: Fix typo in reference to $objdir.
+ * gdb.base/whatis.exp: Always start with a fresh GDB.
+
+Wed Jan 25 11:12:07 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.disasm/hppa.exp (all_fpu_comparison_tests): Set timeout
+ higher, these tests generate a lot of output.
+
+Tue Jan 24 07:58:44 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * lib/gdb.exp (gdb_test): Remove catch from around the send. The
+ code following the catch silently ignored some errors; without the
+ catch they should be thrown like any other tcl error. Also, the
+ catch used "" instead of {} which meant all the callers who wanted
+ to include one of the characters "[]$ had to quote it an extra time.
+ * gdb.base/{callfuncs.exp,commands.exp,gdbvars.exp,printcmds.exp,
+ ptype.exp,signals.exp,watchpoint.exp}, gdb.c++/{cplusfuncs.exp,
+ demangle.exp}, gdb.chill/chexp.exp, gdb.fortran/exprs.exp:
+ Remove extra quoting.
+
+Mon Jan 23 21:57:54 1995 Jeff Law (law@snake.cs.utah.edu)
+
+ * gdb.base/commands.exp: Make test names unique; every test either
+ passes or fails. Update some comments.
+
+ * gdb.disasm/hppa.exp (do_system_control_tests): Update.
+
+Sat Jan 21 15:34:52 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ The following fixes a FAIL caused by the fact that the alpha stabs
+ configuration didn't use the ".if alpha" code in weird.def.
+ * gdb.stabs/weird.def (v_comb): Use type attribute to specify 32
+ bit pointer, so the 32 bit version works even on the alpha.
+ * gdb.stabs/{alpha.mt,ecoff.mt,aout.sed,hppa.sed,xcoff.sed,weird.def}:
+ Remove the stuff which allowed us to have separate versions for
+ alpha and everything else.
+
+ * gdb.c++/cplusfuncs.exp (test_lookup_operator_functions): Fix
+ regexp which "info func operator\[\](" is supposed to match. Fix
+ string to send to GDB. Note that GDB still doesn't work right. Add a
+ new test for "info func .perator\[\](" which GDB does handle correctly.
+
+ * gdb.base/nodebug.exp: xfail most of the new tests for ecoff systems.
+
+Fri Jan 20 12:14:23 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.c++/classes.exp, gdb.c++/cplusfuncs.exp,
+ gdb.c++/inherit.exp, gdb.c++/templates.exp, gdb.c++/virtfunc.exp,
+ gdb.fortran/exprs.exp, gdb.fortran/types.exp, gdb.chill/chexp.exp,
+ gdb.base/printcmds.exp: Remove passcount, failcount, etc., stuff;
+ it makes the tests harder to understand and confuses test-o-matic.
+ The preferred style is that each test provides a PASS or a FAIL,
+ and has a unique message (e.g. "continue #54" not just "continue")
+ which is the same for the pass and the fail.
+ * gdb.fortran/exprs.exp, gdb.fortran/types.exp,
+ gdb.chill/chexp.exp: Move test_print_accept and test_print_reject
+ to lib/gdb.exp.
+ * gdb.base/printcmds.exp: Use test_print_accept. Remove
+ prt_accept which was basically the same thing. Likewise for
+ test_print_reject and prt_reject.
+ * lib/gdb.exp (test_print_reject): Add some more error message
+ patterns to match from the former printcmds.exp (prt_reject).
+ * gdb.c++/classes.exp, gdb.base/scope.exp: Remove spurious xfails.
+ One defect of the passcount stuff is that some of it failed to
+ report XPASS where appropriate.
+ * gdb.c++/cplusfuncs.exp (print_addr_of): No longer accept extra
+ stuff before and after arg in expected pattern.
+ (test_paddr_operator_functions): Re-do test without print_addr_of;
+ this is the only test which seems to want extra stuff there.
+
+Tue Jan 17 10:47:53 1995 Jim Kingdon <kingdon@lioth.cygnus.com>
+
+ * gdb.base/nodebug.exp: Update new tests to reflect improved
+ wording of gdb output.
+
+ * gdb.base/nodebug.exp: Add tests to check that "print", "whatis"
+ and "ptype" work on variables in files compiled without -g.
+ Replaces commented out "maint print msymbol" tests.
+
+Mon Jan 16 12:13:28 1995 Jim Kingdon <kingdon@lioth.cygnus.com>
+
+ * gdb.base/setvar.c (dummy): Call malloc.
+
+ * gdb.stabs/aout.sed: Enclose comments within a sed command to avoid
+ losing with the irix4 sed.
+
+ * gdb.base/sigall.exp (test_one_sig): Add xfail for "get signal
+ ALRM" on irix4.
+
+Sun Jan 15 21:58:26 1995 Jim Kingdon <kingdon@lioth.cygnus.com>
+
+ * TODO: Remove items about corefile.exp testing new exec-file and
+ backtrace; both are now done. Add items about printing enums.
+
+Sat Jan 14 11:25:28 1995 Jim Kingdon <kingdon@lioth.cygnus.com>
+
+ * gdb.base/sigall.exp (test_one_sig): Attempt to recover if
+ "get signal $thissig" test fails.
+
+ * gdb.base/setvar.exp: Check for and reject crazy expected type hacks.
+
+Thu Jan 12 01:14:53 1995 Jim Kingdon <kingdon@lioth.cygnus.com>
+
+ * gdb.base/sigall.c (gen_*): Pass argument to handle_* to avoid
+ compiler warning with dec alpha compiler.
+
+ * gdb.base/commands.exp (if_while_breakpoint_command_test): Remove
+ extra \n from gdb_test call (this explains why the prompt test
+ that I removed yesterday was there).
+ (user_defined_command_test): Remove extra \n and prompt test.
+
+ * gdb.base/sigall.c: If SIGABRT == SIGLOST, just act as if SIGLOST
+ doesn't exist. Likewise if SIGIO == SIGPOLL, pretend SIGPOLL
+ doesn't exist.
+ * gdb.base/sigall.exp: Remove special handling for SIGIO and SIGPOLL.
+ Also remove alpha workaround, which turns out to be because
+ SIGABRT == SIGLOST.
+
+ * gdb.base/sigall.exp: Add workaround for alpha weirdness.
+
+ * gdb.base/help.exp: Don't test "help show".
+
+Wed Jan 11 14:37:04 1995 Jim Kingdon <kingdon@lioth.cygnus.com>
+
+ * gdb.base/commands.exp: Call gdb_exit and gdb_start so that
+ "set print address" is on.
+ * gdb.base/commands.exp (if_while_breakpoint_command_test): Don't
+ pass prompt to gdb_test; gdb_test already looks for the prompt.
+
+ * gdb.base/help.exp: Replace most of docstring for "define" with ".*".
+
+ * gdb.base/a1-selftest.exp: Don't test "maint dump-me". That test
+ was a vestige of the manual TESTSTRATEGY, and the purpose of it
+ was to make sure that gdb can read a core file. But (a) the "read
+ the corefile" part didn't make it to a1-selftest.exp, we just
+ delete the corefile after creating it, and (b) we test reading
+ corefiles in corefile.exp anyway. Also, this test left around a
+ xgdb process on Solaris.
+
+ * gdb.base/corefile.exp: Also test backtrace.
+
+Wed Jan 11 00:14:40 1995 Jeff Law (law@snake.cs.utah.edu)
+
+ * gdb.base/commands.exp: Test a simple user defined command with
+ arguments and if/while statements; verify the full user command is
+ printed by "show user".
+
+ * gdb.base/commands.exp: Test if/while commands as part of a
+ breakpoint command list; verify they appear in breakpoint
+ information.
+
+Wed Jan 11 00:47:58 1995 Jim Kingdon <kingdon@lioth.cygnus.com>
+
+ * gdb.base/sigall.c (gen_FPE): Generate SIGFPE with kill() rather
+ than by dividing by zero.
+
+Tue Jan 10 21:38:05 1995 Jeff Law (law@snake.cs.utah.edu)
+
+ * gdb.base/watchpoint.exp: hppa*-*-*bsd* no longer has problems
+ performing an inferior call with watchpoints enabled.
+ * gdb.base/watchpoint.c (main): Delete second unnecessary read
+ call.
+
+Tue Jan 10 18:42:07 1995 Jim Kingdon <kingdon@lioth.cygnus.com>
+
+ * gdb.stabs/weird.exp: Allow spaces followed by backspaces in echo
+ of "file" command.
+
+ * gdb.c++/classes.exp (test_ptype_class_objects, ptype class Foo):
+ Add additional pattern for when "int operator int(void);" appears
+ in a different order.
+
+Mon Jan 9 16:22:46 1995 Jim Kingdon <kingdon@lioth.cygnus.com>
+
+ * gdb.base/signals.exp: Call gdb_exit and gdb_start.
+
+ * gdb.base/help.exp: Replace most of docstrings for "info signals"
+ and "signal" with ".*".
+
+Wed Jan 4 11:35:19 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * TODO: Add note about "handle all nostop".
+
+ * gdb.base/{sigall.c, sigall.exp}: New test.
+ * gdb.base/Makefile.in: Add it.
+
+Thu Jan 5 17:34:03 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ * lib/gdb.exp, gdb.base/corefile.exp: Supply -nw as argument
+ when invoking GDB, suppresses any windowing interface.
+
+Mon Jan 2 17:40:21 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ * config/sim-gdb: New file, simulator testing support.
+
+Wed Dec 28 12:21:50 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * gdb.base/interrupt.exp: Test calling func1 twice.
+
+Wed Dec 21 12:51:37 1994 Jim Kingdon <kingdon@deneb.cygnus.com>
+
+ * gdb.base/list.exp (test_forward_search): Set timeout higher
+ when we'll be getting lots of output from gdb.
+
+ * gdb.base/a1-selftest.exp: Move code that was inside expect -re
+ "init_malloc" to after the expect statement. Run it if that
+ regexp is taken, but also for two others which happen if source
+ cannot be found.
+
+Tue Dec 20 12:35:21 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.base/printcmds.exp: New test, for printing register before
+ program is running.
+
+Mon Dec 19 00:32:55 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * gdb.base/list.exp: Correct some alternate expect patterns
+ to reflect changes in list1.c.
+
+Sat Dec 17 14:20:03 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * TODO: Add item regarding large frames.
+
+ * gdb.base/{funcargs.exp, funcargs.c} (call_after_alloca): New test.
+
+ * TODO: Remove item about enabling return.exp; it
+ is enabled. Suggest a few more "return" tests.
+
+Sat Dec 17 02:33:37 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * gdb.c++/misc.cc, gdb.c++/inherit.exp: Add testcases for
+ anonymous unions.
+
+Tue Dec 13 11:26:00 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.chill/Makefile.in: Put all rule before rules for pr-4975.o
+ and pr-5646.o, so "make" is the same as "make all", not "make
+ pr-4975.o".
+
+Wed Dec 7 19:02:02 1994 Stan Shebs <shebs@andros.cygnus.com>
+
+ * gdb.base/list.exp: Adjust expectations to reflect changes in
+ list1.c.
+ (test_forward_search): New test proc.
+ * gdb.base/list1.c (long_line): New function, has long source line.
+
+Thu Dec 1 23:14:49 1994 Stan Shebs <shebs@andros.cygnus.com>
+
+ * gdb.base/a1-selftest.exp: Change initial stepping to know about
+ additional line of code that was added.
+
+Wed Nov 30 19:43:14 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * gdb.disasm/hppa.s: Break the large branching tests into smaller
+ tests so as not to overflow expect's input buffers.
+ * gdb.disasm/hppa.exp: Corresponding changes.
+
+Fri Nov 25 13:37:10 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ Beginnings of template debugging tests.
+ * gdb.c++/templ-info.cc: New file to test for template
+ debugging capability of the compiler.
+ * gdb.c++/Makefile.in: Add rule to build templ-info.exp from
+ templ-info.cc.
+ * gdb.c++/templates.cc: Add explicit template instantiations
+ to enable compiling with -fno-implicit-templates. Add destructor
+ and 'value' method to T5 class for template tests.
+ * gdb.c++/templates.exp: Add testcases for printing of template
+ types, setting breakpoints on template methods and calling a
+ template method.
+
+Sat Nov 5 00:20:17 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * gdb.disasm/hppa.exp (branch_tests): Allow any symbol as the
+ branch target since some assemblers (gas-2.5) may emit a
+ relocation for the branch instead of resolving it in the
+ assembler.
+
+Sat Oct 29 02:40:40 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * gdb.base/a1-selftest.exp: Remove RS/6000 xfail for backtrace
+ through signal handler.
+
+Fri Oct 21 11:10:16 1994 J.T. Conklin (jtc@phishhead.cygnus.com)
+
+ * configure.in (*-*-netware): Use config/mt-netware.
+
+ * config/mt-netware: New file.
+ * config/mt-i386-netware: Removed, separate configs for different
+ netware architectures are no longer needed now that we have
+ --with-headers.
+
+Sat Oct 15 03:43:00 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * gdb.base/exprs.exp: Remove xfail for alpha, it is fixed
+ by the recent changes to use ANSI C arithmetic conversions.
+
+Sun Oct 9 07:44:06 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.base/corefile.exp: Add (xfail'd) test for reinit_frame_cache
+ bug involving using inferior_pid to figure out whether to select a
+ frame.
+
+Wed Sep 28 23:12:02 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * gdb.disasm/hppa.exp: Change arg[0..3] to r[26..23] to
+ match the current disassembler output.
+
+Fri Sep 16 11:42:41 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * gdb.fortran/exprs.exp: Expect VOID instead of void.
+ * gdb.fortran/types.exp: Escape the expected '*'s in Fortran
+ types, expect "int" as type of integer values (for now).
+
+Wed Sep 7 23:33:51 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * gdb.base/commands.exp: New tests for if/while commands.
+
+Tue Sep 6 13:16:11 1994 Per Bothner (bothner@kalessin.cygnus.com)
+
+ * lib/gdb.exp (runto): Replace sub-pattern for hex value
+ by .*, since hex values have different syntax in Chill mode.
+
+Tue Sep 6 02:15:51 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * gdb.c++/demangle.exp (test_arm_style_demangling): Remove
+ linefeed from expect pattern for repeated types with indices > 9.
+
+Mon Aug 29 14:20:44 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ First part of Fortran test suite.
+ * gdb.fortran: New directory.
+ * gdb.fortran/exprs.exp, gdb.fortran/types.exp: New files.
+
+Sat Aug 27 23:32:43 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * gdb.base/default.exp: Update expect pattern for load command
+ without arguments.
+
+Wed Aug 24 13:15:02 1994 Ian Lance Taylor (ian@sanguine.cygnus.com)
+
+ * configure.in: Change i386 to i[345]86.
+ * gdb.base/configure.in: Likewise.
+ * gdb.c++/configure.in: Likewise.
+ * gdb.chill/configure.in: Likewise.
+
+Tue Aug 23 19:14:06 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * lib/gdb.exp (gdb_run_cmd): Move comment out from between expect
+ patterns, since that is not a valid context for comments.
+
+Fri Aug 19 15:07:30 1994 Kung Hsu (kung@mexican.cygnus.com)
+
+ * gdb.c++/demangle.exp (test_arm_style_demangling): Add tests for
+ repeated types and repeated types with indices > 9.
+
+Tue Aug 16 15:57:52 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * gdb.base/printcmds.exp: Remove all the a29k XFAILs tagged with
+ 2417; old bug has been fixed.
+
+Fri Aug 12 19:35:41 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * gdb.base/interrupt.exp: When trying to wake up the inferior,
+ send the newline ourselves instead of assuming gdb_test will do
+ so when passed an empty input string.
+
+ * gdb.stabs/hppa.mt: Use $(AS), not $(CC) to assemble the
+ stabs testcode.
+
+Fri Aug 5 17:01:07 1994 J.T. Conklin (jtc@phishhead.cygnus.com)
+
+ * lib/gdb.exp (gdb_test): Don't send anything if the first
+ argument is an empty string. This makes cases where we want to
+ match output that is already in expect's buffers (for example,
+ matching a breakpoint after gdb_run_cmd has been called) work
+ reliably.
+
+Tue Aug 2 10:24:08 1994 J.T. Conklin (jtc@phishhead.cygnus.com)
+
+ * config/netware.exp: New file.
+
+Thu Jul 28 12:54:07 1994 J.T. Conklin (jtc@phishhead.cygnus.com)
+
+ * config/mt-slite (LDFLAGS): If using the newlib in the tree, set
+ the -B and -L prefixes so we can find the debugging stub.
+
+ * Makefile.in (CC_FOR_TARGET, CXX_FOR_TARGET): Use newlib if it is
+ there and we are using the gcc from the tree.
+
+ * gdb.base/types.c: Removed.
+
+ * gdb.base/configure.in: Look for makefile fragments in ../config.
+ Recognize i386-*-netware.
+ * gdb.c++/configure.in: Likewise.
+
+Mon Jul 25 23:48:50 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * gdb.base/corefile.exp: Change `else if' to `elseif', which is
+ the correct TCL syntax.
+
+Mon Jul 25 15:35:56 1994 J.T. Conklin (jtc@phishhead.cygnus.com)
+
+ * gdb.base/opaque.exp: use runto instead of messing around with
+ breakpoints. Simplify by using gdb_test.
+
+ * gdb.base/bitfields.exp: restart between tests on netware targets
+ because breakpoints aren't relocated after target death. Run
+ processes to completion.
+
+ * gdb.base/{opaque,watchpoint}.exp: Use gdb_run_cmd.
+
+Sun Jul 24 09:55:51 1994 Fred Fish (fnf@cygnus.com)
+
+ * Makefile.in: Remove extra tabs that confuse some versions
+ of "make". Use the newly built gdb to test with by default,
+ rather than the first one in the tester's search path.
+
+Sat Jul 23 15:05:47 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * gdb.base/whatis.exp (v_signed_short_array): Fix a typo.
+
+ * gdb.base/help.exp: Update expected add-symbol-file, ignore, and
+ condition help.
+
+Tue Jul 19 10:26:32 1994 J.T. Conklin (jtc@phishhead.cygnus.com)
+
+ * lib/gdb.exp (runto): Rewrite in terms of gdb_run_cmd.
+
+ * lib/gdb.exp (gdb_run_cmd): New function, used to start program
+ running.
+ * gdb.base/bitfields.exp: Use gdb_run_cmd to start program.
+ * gdb.base/funcargs.exp: Likewise.
+
+ * gdb.base/bitfields.exp: Simplify by using gdb_test.
+ * gdb.base/funcargs.exp: Likewise.
+
+ * lib/gdb.exp (gdb_test): if match times out, don't call fail if
+ message is "".
+
+Mon Jul 18 12:18:07 1994 J.T. Conklin (jtc@phishhead.cygnus.com)
+
+ * gdb.base/{a2-run,callfuncs,funcargs,interrupt,mips_pro,nodebug,
+ return,signals,twice}.exp: Handle non-existant binaries
+ consistantly.
+
+ * gdb.base/corefile.exp: Execute coremaker to generate core dump.
+ * gdb.base/Makefile.in: Don't try to generate a core dump, we
+ might testing a cross development system.
+
+Thu Jul 14 18:13:56 1994 J.T. Conklin (jtc@phishhead.cygnus.com)
+
+ * Makefile.in (RUNTEST_FOR_TARGET): Fix relative pathname, the
+ runtest script is relative to ${srcdir}, not ${rootdir}.
+
+Thu Jul 14 14:56:59 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * gdb.base/signals.exp: Allow for optionality of breakpoint
+ address.
+
+Thu Jul 14 11:21:27 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.base/{ptype.exp,ptype.c}: Add t_char_array test.
+
+Tue Jul 12 12:22:32 1994 J.T. Conklin (jtc@phishhead.cygnus.com)
+
+ * gdb.c++/cplusfuncs.cc: Include <stddef.h>, not <sys/types.h>,
+ for size_t definition.
+ * gdb.c++/templates.cc: Likewise
+
+ * config/mt-i386-netware: New file.
+
+ * gdb.base/interrupt.c: Do not test if errno == EINTR if it's not
+ defined.
+
+ * gdb.base/Makefile.in: Added support for systems that name core
+ files by appending "core" to the program name.
+ * gdb.base/a1-selftest.exp: Likewise.
+
+Mon Jul 11 23:59:18 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * gdb.base/return.exp: Add comment and message for `return double'
+ test failure on Sparc Solaris.
+
+Mon Jul 4 12:10:48 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * lib/gdb.exp (runto): Allow for optionality of breakpoint address.
+
+Wed Jun 29 00:26:17 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * gdb.c++/misc.cc: Instantiate classes to inhibit the compiler
+ from optimizing them away.
+ * gdb.c++/classes.exp, gdb.c++/inherit.exp: Update ptype expect
+ patterns to include default constructors and assignment operators,
+ to match gcc versions beyond 2.5.8. Accept any cplus demangling
+ character in the output of the virtual base pointer.
+
+Fri Jun 24 08:15:42 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * gdb.c++/cplusfuncs.exp: Use string_to_regexp and a regular
+ expression match in print_addr_of to avoid unintented matches.
+ * gdb.c++/virtfunc.exp: Accept alternate ptype output of g++
+ versions up to 2.5.8.
+
+Mon Jun 20 23:54:37 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * gdb.base/list.exp: Tweak alternate pattern for listing of an
+ included file to run under newer versions of expect.
+ * gdb.c++/demangle.exp: Add spaces to the expect patterns between
+ consecutive >'s in templates to accomodate recent cplus-dem.c change.
+ Remove xfail for the virtual table of BDDHookV.
+
+Sat Jun 18 12:51:34 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * lib/gdb.exp (string_to_regexp): Set a default result.
+ (default_gdb_start): Fix misleading message.
+
+Wed Jun 15 12:10:10 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * config/mt-a29k-udi, config/mt-i960-nindy, config/mt-sparc-aout:
+ Remove all CC, etc definitions.
+ * config/mt-hpux: New file.
+ * config/mt-mips-ecoff (CFLAGS_FOR_TARGET): Remove:
+ (CFLAGS, LDFLAGS): Define.
+ * config/mt-slite (CFLAGS_FOR_TARGET): Change to LDFLAGS.
+
+ * Makefile.in (site.exp): Don't insert host_os, etc.
+ (just-check): Just use RUNTEST with RUNTESTFLAGS only.
+ (distclean): Check existence of subdir.
+ * gdb.base/configure.in (hppa*-*-hpux*): Recognize.
+ * gdb.base/Makefile.in: General cleanup and simplification.
+ Use CC, CFLAGS, and LDFLAGS instead of ..._FOR_TARGET versions
+ to build executables. Use default rule to build .o files.
+ (EXPECT, RUNTEST, CC): Fix relative pathname.
+ (site.exp): Don't insert host_os, etc.
+ * gdb.base/signals.c (main): Don't call signal unless SIGALRM
+ and/or SIGUSR1 defined.
+ * gdb.base/watchpoint.c: Don't include stdio.h a second time.
+ * gdb.c++/Makefile.in: General cleanup and simplification.
+ Use CC, CFLAGS, and LDFLAGS instead of ..._FOR_TARGET versions
+ (CFLAGS): Remove.
+ (EXPECT, RUNTEST_FOR_TARGET, CXX): Fix relative pathname.
+
+Fri Jun 10 10:55:09 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * gdb.base/recurse.exp: Misc changes to get tests running again
+ after Kung's changes to the watchpoint code.
+ * gdb.base/watchpoint.exp: Likewise.
+
+Thu Jun 9 15:16:55 1994 Per Bothner (bothner@kalessin.cygnus.com)
+
+ * lib/gdb.exp (string_to_regexp): Convert {\} also.
+
+Wed Jun 8 12:12:17 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * config/udi-gdb.exp, config/unix-gdb.exp: Call default_gdb_start.
+ * lib/gdb.exp (default_gdb_start): Define.
+ * gdb.base/bitfields.exp, gdb.base/break.exp, gdb.base/exprs.exp,
+ gdb.base/funcargs.exp, gdb.base/opaque.exp,
+ gdb.base/printcmds.exp, gdb.base/ptype.exp, gdb.base/recurse.exp,
+ gdb.base/scope.exp, gdb.base/setvar.exp, gdb.base/watchpoint.exp,
+ gdb.c++/classes.exp, gdb.c++/misc.exp, gdb.c++/virtfunc.exp:
+ Don't call gdb_target_udi in between tests.
+
+Tue Jun 7 08:30:15 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.c++/demangle.exp: Use gdb_test_exact, rather than demangle
+ (which was basically just a local version of the same thing). In
+ addition to avoiding duplication, gdb_test_exact is faster.
+ * lib/gdb.exp (gdb_test_exact): Fix typo.
+
+ * lib/gdb.exp (delete_breakpoints): If there were no breakpoints,
+ don't give an error.
+
+ * gdb.base/term.exp: Call delete_breakpoints before starting.
+
+ * gdb.base/Makefile.in (EXECUTABLES): Remove t10.
+ (t10): Add comment.
+
+Mon Jun 6 18:26:50 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ Reorganization of the GDB Test Suite.
+
+ * gdb.base: New directory, contains all the basic tests.
+ * gdb.c++: New directory, tests specific to C++.
+ * gdb.chill: New directory, tests specific to Chill.
+ * gdb.t00, gdb.t01, gdb.t02, gdb.t03, gdb.t04, gdb.t05, gdb.t06,
+ gdb.t07, gdb.t08, gdb.t09, gdb.t10, gdb.t11, gdb.t12, gdb.t13,
+ gdb.t15, gdb.t16, gdb.t17, gdb.t20, gdb.t21, gdb.t22, gdb.t23,
+ gdb.t24, gdb.t30, gdb.t31: Removed directories, contents moved
+ into appropriate new directories (t00-t17 to base, t20-t23 to c++,
+ t30-31 to chill).
+ * */gdbme.*: Rename to match appropriate expect scripts.
+ * gdb.base/bitfields.c, gdb.base/break.c, gdb.base/callfuncs.c,
+ gdb.base/coremaker.c, gdb.base/exprs.c, gdb.base/funcargs.c,
+ gdb.base/interrupt.c, gdb.base/list0.c, gdb.base/list0.h,
+ gdb.base/list1.c, gdb.base/mips_pro.c, gdb.base/nodebug.c,
+ gdb.base/opaque-info.c, gdb.base/opaque0.c, gdb.base/opaque1.c,
+ gdb.base/printcmds.c, gdb.base/ptype.c, gdb.base/recurse.c,
+ gdb.base/return.c, gdb.base/run.c, gdb.base/scope0.c,
+ gdb.base/scope1.c, gdb.base/setvar.c, gdb.base/signals.c,
+ gdb.base/types.c, gdb.base/twice.c, gdb.base/watchpoint.c,
+ gdb.base/whatis-info.c, gdb.base/whatis.c: New names of C files.
+ * gdb.c++/cplusfuncs.cc, gdb.c++/templates.cc, gdb.c++/misc.cc,
+ gdb.c++/virtfunc.cc: New names of C++ files.
+ * gdb.chill/chillvars.ch: New name of Chill file.
+ * gdb.base/configure.in, gdb.c++/configure.in,
+ gdb.chill/configure.in: Merge in contents of gdb.t*/configure.in.
+ * gdb.base/Makefile.in, gdb.c++/Makefile.in,
+ gdb.chill/Makefile.in: Merge in contents of gdb.t*/Makefile.in.
+ * configure.in (configdirs): Update to reflect directory changes.
+ (target_abbrev): No longer define for any configuration.
+ * Makefile.in: Cosmetic improvements to header comments.
+
+Fri Jun 3 18:56:06 1994 Per Bothner (bothner@kalessin.cygnus.com)
+
+ Various changes to gdb.t31:
+
+ * Makefile.in (gdbme.o): Compile with -fspecial_UC.
+ * gdbme.ch: Make all key-words and predefineds be upper-case.
+ * chillvars.exp: Expect key-words and predefinds in upper-case.
+
+ * chillvars.exp: Use gdb_test_exact many places.
+ Change expected output for arrays (which now includes index labels).
+
+ * pr-5020.exp, gdme.ch (module PR_5020):
+ New test, for PR-5020.
+
+Thu Jun 2 16:02:41 1994 Per Bothner (bothner@kalessin.cygnus.com)
+
+ * lib/gdb.exp (string_to_regexp, gdb_test_exact): New procedures.
+ * Makefile.in (CHILL_LIB): Remove bogus redundant definitions.
+
+Sun May 29 22:31:42 1994 Per Bothner (bothner@kalessin.cygnus.com)
+
+ * Makefile.in: Fix bit-rot in definitions of CHILL,
+ CHILL_FOR_TARGET and Chill_LIB.
+ * gdb.t31/gdbme.ch: Fix syntax of nested array tuples.
+ * gdb.t31/Makefile.in: Add definitions for CHILLFLAGS,
+ CHILL, and CHILL_LIB.
+
+Sat May 21 10:05:08 1994 Bill Cox (bill@rtl.cygnus.com)
+
+ * Revert the previous changes. Please see Rob's directory
+ /lisa/test/rob/progressive/gdb/testsuite for these fixes.
+
+Thu May 19 12:51:00 1994 Bill Cox (bill@rtl.cygnus.com)
+
+ * Makefile.in, configure.in, config/mips-gdb.exp,
+ config/mt-a29k-udi, config/mt-i386-aout, config/mt-i960-nindy,
+ config/mt-sparc-aout, config/udi-gdb.exp, config/unix-gdb.exp,
+ config/unknown.exp, gdb.t00/default.exp, gdb.t00/help.exp,,
+ gdb.t00/teststrategy.exp, gdb.t01/Makefile.in, gdb.t02/Makefile.in,
+ gdb.t02/whatis.exp, gdb.t03/Makefile.in, gdb.t03/gdbme.c,
+ gdb.t04/Makefile.in, gdb.t05/Makefile.in, gdb.t06/Makefile.in,
+ gdb.t06/break.exp, gdb.t06/signals.c, gdb.t06/signals.exp,
+ gdb.t08/Makefile.in, gdb.t08/opaque.exp, gdb.t09/Makefile.in,
+ gdb.t10/Makefile.in, gdb.t11/Makefile.in, gdb.t12/Makefile.in,
+ gdb.t13/Makefile.in, gdb.t15/Makefile.in, gdb.t15/funcargs.exp,
+ gdb.t15/gdbme.c, gdb.t15/return.exp, gdb.t16/Makefile.in,
+ gdb.t17/Makefile.in, gdb.t17/callfuncs.exp, gdb.t17/gdbme.c,
+ gdb.t20/Makefile.in, gdb.t21/Makefile.in, gdb.t21/cplusfuncs.exp,
+ gdb.t22/Makefile.in, gdb.t22/virtfunc.exp, gdb.t23/Makefile.in,
+ gdb.t24/demangle.exp, lib/gdb.exp: Check in Rob's testing
+ changes from 94Q1.
+
+Wed May 18 17:04:03 1994 Bill Cox (bill@rtl.cygnus.com),
+
+ * config/mt-lynx, config/mt-m68k, config/mt-mips-ecoff,
+ config/mt-slite, config/mt-unix, config/mt-vxworks: Add
+ Rob's new testing fragments.
+
+Tue May 17 15:04:14 1994 Bill Cox (bill@rtl.cygnus.com)
+
+ * config/mips-gdb.exp, config/udi-gdb.exp, config/vx-gdb.exp,
+ lib/gdb.exp: Replace error proc calls with perror.
+
+Mon May 16 19:00:50 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * gdb.t00/teststrategy.exp: Reorder so that AIX gdb can print the
+ version also, match on casted version strings, and match on
+ gdb startup case where the line numbers might be messed up.
+
+Fri May 13 18:00:27 1994 Bill Cox (bill@rtl.cygnus.com)
+
+ * config/mt-i960-vx (LDFLAGS): Add '-r' option for test links.
+ (CFLAGS): Delete it from here.
+
+Tue May 3 16:08:09 1994 Kung Hsu (kung@mexican.cygnus.com)
+
+ * gdb.t22/virtfunc.exp: Fix g++ ptype expected outputs.
+
+Fri Apr 29 14:26:35 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * Makefile.in (RUNTEST): Default to just "runtest".
+
+Tue Apr 26 22:21:40 1994 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * gdb.t17/callfuncs.exp: More comments about t_func_values tests.
+ * gdb.t17/gdbme.c (t_func_values): Add comments about how and why
+ the code has been restructured.
+
+Thu Apr 21 12:48:07 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.t00/default.exp (set write): Allow any number of \r and/or
+ \n, not just one of each.
+
+ * gdb.t07/gdbme.c (main): Don't take address of an array; SunOS4
+ /bin/cc gives a warning if you do.
+
+Thu Apr 21 11:54:04 1994 Kung Hsu (kung@mexican.cygnus.com)
+
+ * gdb.t24/demangle.exp: change expect pattern of
+ __t10ListS_link1ZUiRCUiPT0
+
+Wed Apr 13 15:05:00 1994 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * gdb.t07/{recurse.exp, recurse.c}: New tests for watchpoints
+ on local variables in recursive functions.
+
+ * gdb.t07/Makefile.in: Build the new test.
+
+Tue Apr 12 20:45:25 1994 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * gdb.t17/gdbme.c (t_func_values): Do not compare function pointers
+ directly. Instead compare the return values from actual calls.
+
+Mon Apr 11 10:31:00 1994 Bill Cox (bill@rtl.cygnus.com)
+
+ * Makefile.in (check): Set TCL_LIBRARY for runtest.
+
+Mon Apr 11 09:15:30 1994 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * From Peter Schauer with minor modifications.
+ * gdb.t15/return.exp (return_tests): Handle targets where "return"
+ stops in mid-line in the caller. Add xfail for returning a float
+ value on X86 targets.
+
+Tue Apr 5 15:16:33 1994 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * gdb.disasm/hppa.exp (fcmp_tests): Break up into two halves
+ to avoid expect lossage.
+ (fmem_LRbug_tests): Likewise.
+ * gdb.disasm/hppa.s: Corresponding changes.
+
+ * gdb.disasm/hppa.exp: Rework escape sequences and end-of-line
+ conditions to work with latest dejagnu/expect.
+
+ * gdb.t15/funcargs.exp (finish from indirect call): No longer
+ expected to fail on the PA.
+ (backtrace in call with trampolines): Explicitly require main
+ to be frame #1 (no trampolines should show up in backtrace).
+
+ * gdb.t00/default.exp: Use "exp_continue" rather than obsolete
+ "continue -expect".
+ * gdb.t06/break.exp: Likewise.
+ * gdb.t07/watchpoint.exp: Likewise.
+ * gdb.t13/bitfields.exp: Likewise.
+ * gdb.t15/{funcargs,return}.exp: Likewise.
+ * gdb.stabs/weird.exp: Likewise.
+ * config/{mips,udi}-gdb.exp: Likewise.
+
+ * hppa.sed: Enclose comments within a sed command to avoid
+ losing with the old OSF1 sed.
+
+Wed Mar 30 00:31:49 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * gdb.t02/whatis.exp, gdb.t08/opaque.exp: Add XFAILs for
+ sequent dynix.
+ * gdb.t06/signals.exp: Add clear_xfail for sequent dynix.
+ * gdb.t15/funcargs.exp: Conditionally step again to really
+ finish from marker_call_with_trampolines. Handle the case where
+ the first step from within call_with_trampolines already steps
+ us back to main.
+ * gdb.t15/gdbme.c: Add comment to closing brace of
+ call_with_trampolines for funcargs.exp.
+
+Tue Mar 29 23:55:27 1994 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * gdb.t07/watchpoint.exp (test_watchpoint_triggered_in_syscall):
+ Fix typo(s).
+
+Sun Mar 27 16:53:14 1994 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * gdb.t07/gdbme.c: More code for watchpoint testing.
+
+ * gdb.t07/watchpoint.exp: Accept both "Watchpoint" and
+ "Hardware watchpoint" throughout file.
+ (test_watchpoint_triggered_in_syscall): New test.
+ (test_complex_watchpoint): New test.
+
+Fri Mar 25 17:05:31 1994 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * gdbme.c (call_with_trampolines): New function to try and step
+ into. Tests trampoline problems on the PA.
+
+ * funcargs.exp (localvars_in_indirect_call): No longer expect
+ stepping into indirect call to fail on PAs.
+ (test_stepping_over_trampolines): New test.
+
+Wed Mar 23 07:43:33 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * TODO: Add suggestions for static member function tests, and
+ completion tests.
+
+Wed Mar 16 08:28:28 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * TODO: Add suggestions for "p/a" tests.
+
+ * lib/gdb.exp: Set prompt to (gdb) if it isn't already set.
+ (default_gdb_exit): Replace all the hair with sending "quit" to
+ the process with a simple close.
+
+Tue Mar 15 08:45:50 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * TODO: Add suggestions for shared library tests.
+
+Sun Mar 13 10:45:22 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * TODO: Add suggestions for x/s tests.
+
+Fri Mar 11 08:22:00 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.t00/help.exp: Replace most of docstrings for "tbreak",
+ "enable once", and "enable breakpoints once" with ".*".
+
+Thu Mar 10 08:34:27 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * TODO: Add suggestions about structure passing tests.
+
+Mon Mar 7 13:45:54 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * gdb.t03/gdbme.c: gcc version 1 puts out the wrong stabs for
+ the primary1 test, use work around if __GNUC__ < 2.
+ * gdb.t06/signals.c: Add comments for signals.exp pattern matching.
+ * gdb.t06/signals.exp: Add XFAILs for i386 bsd and vax ultrix.
+ Test for bad output rather than waiting for timeout. Issue
+ second continue only if first continue failed.
+
+Wed Mar 2 10:08:01 1994 Jim Kingdon (kingdon@deneb.cygnus.com)
+
+ * gdb.t21/cplusfuncs.exp (test_paddr_operator_functions): Do
+ operator[] test with gdb_test because the old code didn't seem to
+ be getting the quoting right with the new dejagnu.
+
+Thu Feb 24 19:49:25 1994 Rob Savoye (rob@poseidon.cygnus.com)
+
+ * lib/gdb.exp: Set GDB to a fresh gdb if there is one, else use
+ one from the path.
+ * Makefile.in: Use a fresh expect if there is one, use runtest
+ from the src tree if there is one.
+
+Thu Feb 24 18:49:37 1994 Jim Kingdon (kingdon@deneb.cygnus.com)
+
+ * gdb.t06/break.exp (test_next_with_recursion): Remove xfail for
+ next over recursive call. Revise the tests from that point on
+ (which had been skipped) to match GDB's actual (correct) output.
+
+ * gdb.t07/watchpoint.exp (test_stepping): Remove xfail for bug
+ with next over a breakpoint whose condition is false.
+
+ * gdb.t00/help.exp: Comment out "help set print" tests just like
+ (and for same reason as) "help set" test.
+
+Mon Feb 14 09:58:23 1994 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * gdb.disasm/hppa.s (fmemLRbug_tests): New tests.
+ * gdb.disasm/hppa.exp (fmemLRbug_tests): Run them.
+
+Sun Feb 6 15:36:13 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.t06/break.exp (test_next_with_recursion): Remove no longer
+ necessary gdb_target_udi.
+
+ * gdb.t03/ptype.exp: For UDI, skip tests which call malloc.
+
+ * gdb.t02/whatis.exp, gdb.t03/ptype.exp: Remove xfails for PRs
+ 1838 and 2417; they are fixed.
+
+ * gdb.t02/whatis.exp (v_char_array, v_signed_char_array),
+ gdb.t03/ptype.exp (ptype structure, ptype union):
+ Remove xfails; the test is looser than when the xfails were added.
+
+ * gdb.t00/{help.exp,default.exp}: Don't test "target remote" on UDI.
+ * gdb.t00/help.exp: Don't expect remote to be in "help target" output.
+
+ * gdb.t01/run.exp: Only run shell test if isnative.
+
+ * config/udi-gdb.exp (gdb_load): Use "file", not "load" command,
+ since "run" automatically loads if necessary. Call gdb_target_udi
+ after the "file" since "file" kills any execution target.
+
+ * config/udi-gdb.exp (gdb_start): Don't send "set args main" to
+ GDB. GDB doesn't work that way (not anymore at least) on UDI.
+ * gdb.t01/run.exp, gdb.t06/break.exp: Don't pass extra first
+ argument for UDI.
+
+Fri Feb 4 12:19:32 1994 Jim Kingdon (kingdon@deneb.cygnus.com)
+
+ * gdb.t17/interrupt.c: If we get EINTR, don't print an error message.
+
+ * gdb.t17/callfuncs.exp: Add xfails for rs6000.
+
+Sat Feb 5 09:11:56 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.t24/demangle.exp: Re-write demangle to just call gdb_test,
+ properly quoting regexps. This makes the second argument to
+ demangle a fixed string, which matches the callers, instead of a
+ shell-style pattern which is what the previous implementation
+ used. Update some of the callers.
+
+Sat Feb 5 10:19:09 1994 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * gdb.disasm/hppa.s (comib_tests): Add missing instruction.
+ (comib_nullified_tests): Fix typo.
+ * gdb.disasm/hppa.exp (all comb tests): Fix thinkos in expect
+ strings. No longer expected to fail.
+
+ * gdb.disasm/hppa.s (addib_tests): Fix typo.
+ * gdb.disasm/hppa.exp (all addb tests): Fix thinkos in expect
+ strings. No longer expected to fail.
+
+ * gdb.disasm/hppa.exp (fmpy_addsub_tests): Fix typo in expect
+ string. No longer expected to fail.
+
+Fri Feb 4 23:45:11 1994 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * gdb.disasm/hppa.exp (fcmp_tests): Fix thinko in expect string.
+ No longer expected to fail.
+
+ * gdb.disasm/hppa.exp (xmpyu_tests): Fix buglet in expect
+ string. No longer expected to fail.
+
+Fri Feb 4 10:35:42 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.t24/demangle.exp: Remove a bunch more tests which differ
+ only in the names (I probably got most of them). I was even
+ generous with some which differed in underscores in names, and
+ probably missed a few, and I *still* was able to remove almost a
+ third of the file with almost no impact on testsuite coverage.
+
+Thu Feb 3 12:04:49 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.t00/default.exp: Match udi_attach error message as well as
+ the one from child_attach.
+
+ * gdb.t00/default.exp: Use "." instead of "?" to match a question mark.
+
+ * gdb.stabs/weird.exp: Remove xfail for const70; just fixed in GDB.
+
+ * gdb.stabs/weird.def (bad_neg0type): Size of this type is 16, not 8.
+ * gdb.stabs/weird.exp: Remove xfail for "p bad_neg0"; this fixes it.
+
+ * Move test with enums and partial symbols back to
+ gdb.t03/{ptype.exp,gdbme.c} from gdb.stabs/{weird.def,weird.exp}.
+ Reverts the change of 26 May 93. Per today's change to
+ stabs.texinfo, the behavior that weird.exp was expecting was
+ unreasonable; what is important is that the compiler+gdb get
+ things right, which happens with a recent gcc. Also fix the test
+ to deal with native compilers which put out the stab gdb can't
+ deal with.
+
+Mon Jan 31 15:40:11 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.t24/demangle.exp: Remove a bunch of tests which differ only
+ in the names. The main thing these accomplish is to slow things down.
+ Many more such duplicates surely remain.
+
+ * gdb.t00/help.exp: Comment out "help support" test just like
+ (and for same reason as) "help set" test.
+
+Mon Jan 31 06:43:45 1994 Fred Fish (fnf@cygnus.com)
+
+ * gdb.t06/break.exp: Remove setup_xfails for
+ sparc-sun-solaris2.*, these tests now pass with latest gcc and gdb.
+ * gdb.t20/inherit.exp (test_ptype_si): Update warning message
+ about known bug in gcc to include up through 2.5.8.
+ * gdb.t20/inherit.exp (test_ptype_vi): Accept "_vb." as well as
+ well as "_vb$".
+ * gdb.t21/cplusfuncs.exp (test_lookup_operator_functions):
+ Remove setup_xfails for sparc-sun-solaris2.*, these tests now pass
+ with latest gcc and gdb.
+ * gdb.t22/virtfunc.exp (test_ptype_of_classes): Accept "_vb." as
+ well as "_vb$".
+
+Sat Jan 29 23:31:26 1994 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * configure.in (hppa*-*-*): Also configure and build stabs-only
+ tests.
+
+Thu Jan 27 08:21:16 1994 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * gdb.t10/hppa.mt: A makefile fragment for the PA.
+ * gdb.t10/configure.in (hppa*-*-*): Use it.
+
+Tue Jan 25 12:58:26 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * gdb.t09/corefile: Increase timeout when spawning gdb explicitly.
+
+Wed Jan 19 12:40:25 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * gdb.t06/signals.exp: Handle blocked SIGTRAP on sun3 for bash
+ versions prior to 1.13.5.
+
+Tue Jan 18 20:10:50 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.t00/default.exp (show prompt): In FAIL case, only match if
+ the prompt is at the start of a line.
+
+Mon Jan 17 20:07:51 1994 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * gdb.disasm/hppa.s: Add new tests for sfu and copr instructions.
+ Enable "diag" instruction. Delete copr from fpu_misc_tests, it's
+ in the copr tests now.
+ * gdb.disasm/hppa.exp: Run new sfu and copr tests. Do not expect
+ copr in the fpu_misc tests anymore. fpu_misc tests are no longer
+ expected to fail.
+
+Fri Jan 14 14:24:21 1994 Rob Savoye (rob@darkstar.cygnus.com)
+
+ * gdb.t00/teststrategy.exp, gdb.t07/watchpoint.exp,
+ gdb.t31/chillvars.exp, lib/gdb.exp:
+ Tweak to run under either version of expect.
+ * lib/gdb.exp (default_gdb_exit): Remove "catch" statement.
+ * gdb.t00/teststrategy.exp: Use isnative and verbose procedures.
+ * gdb.t11/list.exp: Remove extraneous whitespace.
+
+Sat Jan 15 09:57:22 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.t16/printcmds.exp (test_print_strings): Accept
+ "(unsigned char *) " before the string.
+
+ * TODO: Add notes about printing of fancy types and GDB expressions.
+
+Thu Jan 13 17:16:09 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * Makefile.in: Pass LDFLAGS and LIBS to sub-makes.
+ * gdb.t06/configure.in: Don't try to compile signals test program
+ if doing mips-idt-ecoff.
+
+Thu Jan 13 08:25:55 1994 Rob Savoye (rob@darkstar.cygnus.com)
+
+ * Most .exp files: Tweak to run under either version of expect.
+
+Tue Jan 11 15:21:13 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.t12/scope.exp: Add xfails for rs6000. Remove 1806 from existing
+ xfails; I'm not sure why they are failing, but not because of PR 1806.
+
+Mon Jan 10 22:14:20 1994 Rob Savoye (rob@darkstar.cygnus.com)
+
+ * config/unix-gdb.exp: Remove gdb_unload cause it's already
+ defined in lib/gdb.exp.
+
+Fri Jan 7 12:42:45 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * gdb.t07/watchpoint.exp: Clear xfail for calling function with
+ watchpoint enabled on mips, CALL_DUMMY_BREAKPOINT_OFFSET got defined.
+ * gdb.t20/gdbme.cc, gdb.t21/gdbme.cc: Conversion operator functions
+ have to be typeless.
+
+Tue Jan 4 09:32:22 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * TODO: Add suggestion for copyright year test.
+
+Mon Jan 3 11:35:26 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * configure.in (*-*-lynxos*): Add stabs tests.
+
+Wed Dec 1 21:54:05 1993 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * gdb.stabs/hppa.sed: Only lables should ever start in column zero,
+ so insert a tab before any assembler directive in column zero.
+
+ * gdb.disasm/hppa.exp (all_fpu_memory_tests): Test FP quadword
+ stores.
+ * gdb.disasm/hppa.s (fpu_memory_indexing_tests): Add FP quadword
+ stores.
+ (fpu_short_memory_tests): Likewise.
+
+Mon Nov 22 13:23:22 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * gdb.stabs/ecoff.mt: Delete alpha specific if block, fix typo.
+ * gdb.stabs/ecoff.sed: Escape inserted blanks with backslashes, embed
+ .stabs directives in comments.
+
+Fri Nov 19 14:09:02 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * TODO: New file, describing tests we could write.
+ * gdb.t09/corefile.exp: Move description of tests to write to TODO.
+
+Tue Nov 16 21:07:44 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.t06/signals.exp: Add kludge to force re-sync.
+
+ * gdb.t00/teststrategy.exp: If we accidently send the "maint dump-me"
+ to xgdb instead of gdb, get out of gdb.
+
+Tue Nov 16 10:21:57 1993 Rob Savoye (rob@cygnus.com)
+
+ * lib/gdb.exp: Make GDB and GDBFLAGS global so the scoping work
+ for info.
+
+Sat Nov 13 23:17:48 1993 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * gdb.stabs/hppa.mt: A makefile fragment for the PA.
+ * gdb.stabs/configure.in (hppa*-*-*): Use it.
+ * gdb.stabs/hppa.sed: New sed script for the PA.
+
+Sat Nov 13 22:50:29 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.stabs: Re-write weird.def and configuration to use sed
+ instead of cpp. sed is portable and POSIX; cpp is neither.
+
+Fri Nov 12 15:26:36 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.t06/signals.exp: Remove one sun3 XFAIL which has been fixed.
+
+Mon Nov 8 16:55:28 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.t20/gdbme.cc: Add comment about pmi being optimized out.
+
+Thu Nov 4 23:07:59 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.stabs/weird.exp, gdb.t22/virtfunc.exp: Accept "_vb." as well as
+ "_vb$".
+ * gdb.t00/teststrategy.exp: Add xfail for RS/6000.
+ * gdb.t03/ptype.exp: Add comments and messages about FAILs with xlc.
+
+Wed Nov 3 13:53:34 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * lib/gdb.exp: Comment out code which depends on non-existent
+ `transform' procedure.
+
+Wed Nov 3 11:23:11 1993 Rob Savoye (rob@darkstar.cygnus.com)
+
+ * lib/gdb.exp (default_gdb_exit): Remove `catch "close"'.
+ * lib/gdb.exp: Transform tool name.
+ * gdb.t*/*.exp: Change error to perror so it works with DejaGnu
+ 1.1's new error handling system.
+
+Mon Nov 1 10:36:29 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * Makefile.in, gdb.t2*/Makefile.in: Add -O to CXXFLAGS.
+
+Fri Oct 29 17:58:14 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.t00/default.exp: Avoid tests with a lot of .* in them.
+ They made pattern matching so slow that timeouts happened on
+ heavily loaded systems. Now any output from "show print" which
+ gets us back to the GDB prompt is a PASS.
+
+Mon Oct 25 14:36:50 1993 Stu Grossman (grossman at cygnus.com)
+
+ * gdb.disasm/hppa.mt: Use $(srcdir) in hppa.o make rule.
+
+Mon Oct 25 13:35:29 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.t06/signals.exp: Skip whole file with xfail for HPPA.
+
+ * gdb.t24/demangle.exp: Remove "3220" from the one remaining xfail.
+ It is not from PR 3220.
+
+Sun Oct 24 18:49:58 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.t00/{help.exp,default.exp}: Loosen up a few more tests which
+ just started failing because they depended on the order the
+ subcommands are presented, or exact docstring text. This kind of
+ test is a pain and has minimal benefit.
+
+Thu Oct 21 08:26:48 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.t09/corefile.exp: At end of test, use "core" command with
+ no arguments.
+
+Wed Oct 20 08:56:02 1993 Stu Grossman (grossman at cygnus.com)
+
+ * gdb.t{01 02 03 04 05 06 07 08 09 10 11 12 13 15 16
+ 17}/Makefile.in: Make it possible to run the testsuite with Sun
+ make and CC = cross gcc by adding explicit build rules for .o
+ files.
+
+Tue Oct 19 14:57:38 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.t15/funcargs.exp: Don't put comments on same line as
+ setup_xfail (@#$*%& tcl braindamage!).
+
+Mon Oct 18 21:50:08 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.disasm/hppa.exp: Use $objdir/$subdir/$binfile not just $binfile.
+
+Fri Oct 15 15:39:54 1993 Kung Hsu (kung@cirdan.cygnus.com)
+
+ * gdb.t20/classes.exp: 'const xxx &' becomes 'xxx const &'.
+ * gdb.t20/inherit.exp: remove three dumplicate entries.
+
+Fri Oct 15 13:45:25 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * gdb.t06/break.exp: For "next over recursive call", fail on any
+ incorrect output, not just on "factorial (value=2)".
+
+Fri Oct 15 11:52:56 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * gdb.t12/scope.exp: Remove xfails, filename::var syntax should be
+ working now. Add an xfail if accesing a bss variable causes
+ a memory error if the target is not yet run.
+
+Thu Oct 14 19:16:56 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.t24/demangle.exp: Clean up spacing (2 strings), inclusion of
+ constructor name (2 string), name of _GLOBAL_ demangling (2 strings),
+ name of __st* demangling (2 strings). Did Kung really get the
+ more than 95 others right without testing them?
+
+Thu Oct 14 16:27:08 1993 Kung Hsu (kung@cirdan.cygnus.com)
+
+ * gdb.t24/demangle.exp: clean up XFAILS, more than 100
+
+Thu Oct 14 11:40:30 1993 Jeffrey Law (law@cs.uah.edu)
+
+ * configure.in (configdirs): Add gdb.disasm
+ * gdb.disasm: New directory for GDB disassembler tests.
+ * gdb.disasm/hppa.{exp,s,mt}: Disassembly tests for the HPPA.
+
+Thu Oct 14 11:40:30 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.t00/help.exp: Don't test "help set".
+
+ * gdb.t20/inherit.exp, gdb.t22/virtfunc.exp: Remove all xfails
+ from within expect statements. None of these happen anymore and
+ they cause regressions to be silently unnoticed.
+
+ * gdb.t20/inherit.exp, gdb.t22/virtfunc.exp: Add notes (in failure
+ messages) about known failures with gcc cygnus-2.4.5-930417.
+
+ * gdb.t02/Makefile.in, gdb.t08/Makefile.in: Make all depend on
+ comp-info.exp so it gets built if it doesn't exist.
+
+ * gdb.t13/{Makefile.in,bitfields.exp}: Remove comp-info.exp stuff;
+ it is no longer used.
+ * gdb.t13/comp-info.c: Removed.
+
+Wed Oct 13 22:54:06 1993 Jim Kingdon (kingdon@deneb.cygnus.com)
+
+ * gdb.t06/signals.exp: Add xfail for sun3.
+
+Thu Oct 7 12:01:03 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.t17/interrupt.exp: Add xfail for Irix (currently not really
+ relevant because ^C doesn't get sent but failure can be reproduced
+ interactively).
+
+Tue Oct 5 10:43:11 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * gdb.stabs/alpha.mt: New configuration file for alpha.
+ * gdb.stabs/configure.in: Use it.
+ * gdb.stabs/ecoff.mt, weird-ecoff.sed: Change sed script to enable
+ sharing with alpha.mt, redefine long to word via preprocessor.
+ * gdb.stabs/weird.def: Conditionally adapt storage layout of v_comb
+ for alpha.
+ * gdb.stabs/weird.exp: Handle compilation of weird.s by alpha
+ native cc.
+ * gdb.t00/teststrategy.exp: Change expect string so that we
+ consume the `(xgdb)' from the command echo and from the gdb prompt.
+ * gdb.t05/expr.exp: xfail "print unsigned int == (~0)" on the alpha.
+ gdb currently compares all values as long, so this failure probably
+ applies to any configuration where LONGEST is bigger than a target int.
+ * gdb.t08/comp-info.c: New file to determine if gdbme is compiled
+ with gcc.
+ * gdb.t08/Makefile.in, opaque.exp: Use it. Alpha native cc is unable
+ to handle opaque pointers, gcc is.
+ * gdb.t21/gdbme.cc, gdb.t23/gdbme.cc: operator new takes a size_t
+ as first argument. Include <sys/types.h> and change all operator
+ new definitions to use size_t.
+ * gdb.t21/cplusfuncs.exp: Handle changes in output for operator new
+ now that we use size_t.
+
+Wed Sep 29 00:55:49 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * gdb.t03/ptype.exp, gdb.t15/printcmds.exp: When constructing
+ a long or float array cast all array members to the same type.
+ * gdb.t04/setvar.exp: Handle the decimal output of an unsigned long
+ with 64 bit longs.
+ * gdb.t07/watchpoint.exp: Add finish and until variations encountered
+ on alpha.
+ * gdb.t08/opaque.exp, gdb.t17/interrupt.exp: Add xfails for alpha.
+
+Tue Sep 28 17:26:47 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.t24 (demangle.exp): Constructors of templates have names like
+ vector<int>::vector(int) not vector<int>::vector<int>(int). See
+ section 14.6 of the ARM.
+
+ * gdb.t24 (demangle.exp): Remove a whole bunch of tests of the form
+ "_vt$MoveCmd"; these differ only in name from "_vt$foo", so they
+ accomplish little and slow down the testsuite.
+
+ * gdb.t24 (demangle.exp): Accept "XXX const" as well as "const XXX".
+ Accept spaces various places.
+
+Tue Sep 21 17:28:45 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.t07/watchpoint.exp: On sparc, clear xfail for calling function
+ with watchpoint enabled.
+
+ * Makefile.in: Remove definition of CC and remove the second
+ definition of CXX (the "CXX = gcc" one remains). These definitions
+ were causing backquotes to be expanded within backquotes, which
+ doesn't work.
+
+Sat Sep 18 09:43:21 1993 Jim Kingdon (kingdon@poseidon.cygnus.com)
+
+ * gdb.t17/callfuncs.exp: Add "return 0" to end.
+
+Fri Sep 17 04:41:17 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * gdb.stabs/ecoff.mt: Remove STABSCC hack.
+ * gdb.stabs/weird.exp: Handle the case where weird.o is compiled
+ by mips cc and contains no stabs entries.
+
+Thu Sep 16 17:22:12 1993 Rob Savoye (rob@darkstar.cygnus.com)
+
+ * config/vx-gdb.exp: Use fake device to load files rather than
+ NFS.
+ * lib/gdb.exp: New proc to do "file" command.
+ * config/unix-gdb.exp: Use new "file" proc.
+
+Thu Sep 16 13:45:44 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * config/mips-gdb.exp (gdb_load): Increase timeout to 2400.
+ Rework board rebooting slightly.
+ (gdb_exit): Don't exit from the remote shell; there isn't one.
+ * gdb.stabs/weird.exp: If a program is being debugged already,
+ kill it.
+ * gdb.t04/setvar.exp: Stop and restart gdb.
+ * gdb.t05/expr.exp: Likewise.
+ * gdb.t07/watchpoint.exp: If target is mips-idt-*, stop and
+ restart gdb and reload the program.
+ * gdb.t08/opaque.exp: Likewise.
+ * gdb.t12/scope.exp: Likewise.
+ * gdb.t13/bitfields.exp: Likewise.
+ * gdb.t15/funcargs.exp: Likewise.
+ * gdb.t20/classes.exp: Likewise.
+ * gdb.t03/ptype.exp: Increase timeout.
+ * gdb.t16/printcmds.exp (test_print_string_constants,
+ test_print_array_constants): Likewise.
+ * gdb.t17/callfuncs.exp (do_function_calls): Likewise.
+ * gdb.t20/classes.exp (do_tests): Likewise.
+ * gdb.t22/virtfunc.exp (test_virtual_calls): Likewise.
+
+Wed Sep 15 14:24:36 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * gdb.stabs: Renamed *wierd* to *weird*.
+
+Wed Sep 15 10:36:50 1993 Jim Kingdon (kingdon@cirdan.cygnus.com)
+
+ * gdb.t13/bitfields.exp: Test for bad output rather than waiting
+ for timeout. Add "known gcc 2.4.5 bug" to failure message.
+
+Tue Sep 14 17:16:44 1993 Jim Kingdon (kingdon@cirdan.cygnus.com)
+
+ * gdb.stabs/wierd.exp (print_wierd_var): Test size, not type name.
+ (do_tests): Remove xfail for whatis on one_var and two_var.
+
+Wed Sep 8 23:14:23 1993 Rob Savoye (rob@darkstar.cygnus.com)
+
+ * Makefile.in: Made cross building work better by adding
+ {RUNTEST,CC}_FOR_TARGET and using TARGET_FLAGS_TO_PASS.
+
+Tue Sep 7 14:11:52 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.t15/{return.c,return.exp,Makefile.in}:
+ New test, currently commented out.
+
+Tue Aug 31 16:51:29 1993 Rob Savoye (rob@darkstar.cygnus.com)
+
+ * config/udi-gdb.exp: gdb_exit now kills any isstip processes
+ still running and removes the leftover named socket so GDb can do
+ clean restarts.
+
+Mon Aug 30 17:55:16 1993 Rob Savoye (rob@darkstar.cygnus.com)
+
+ * gdb.t01/run.exp: Add match for VxWorks, cause I/O comes out the
+ console, not GDB.
+ * config/mt-*: Added default values for RUNTEST and RUNTESTFLAGS so
+ cross testing works better with "make check"
+ * config/unix-gdb: Use default procedures for exit and version.
+ * config/vx-gdb.exp: Cleaned up and massaged back to working order
+ with the newest VxWorks.
+
+Thu Aug 26 17:50:28 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.t20/classes.exp: For "ptype class Base1", continue to accept
+ old form.
+
+ * gdb.t22/virtfunc.exp: If it prints `struct' (not `class') with a
+ name (e.g. devo gdb with gcc 2.4.5), it is still a pass.
+
+ * gdb.t10/crossload.exp: Skip whole file (for now, until we fix it).
+
+ * config/unix-gdb.exp: Remove this version of gdb_exit
+ * lib/gdb.exp: Merge in all the crap from config/unix-gdb.exp.
+ Rob says he'll look at it when he gets back to testing boards.
+
+Thu Aug 26 07:20:00 1993 Fred Fish (fnf@deneb.cygnus.com)
+
+ * gdb.t22/virtfunc.exp: Accept missing struct/class names as
+ an expected fail for certain ptype commands.
+
+ * gdb.t20/classes.exp: Update expected results of "ptype class
+ Base1" to account for the constructor that now appears in the type.
+
+Wed Aug 25 16:48:05 1993 Fred Fish (fnf@deneb.cygnus.com)
+
+ * configure.in (configdirs): Restore gdb.t04, which mysteriously
+ disappeared from list.
+ * config/{udi-gdb.exp, gdb-unix.exp}: Replace calls to obsolete
+ "alldone" proc with call to cleanup and exit.
+ * {gdb.t01/run.exp, gdb.t01/term.exp, gdb.t02/whatis.exp,
+ gdb.t03/ptype.exp, gdb.t04/setvar.exp, gdb.t05/expr.exp,
+ gdb.t06/break.exp, gdb.t07/watchpoint.exp, gdb.t08/opaque.exp,
+ gdb.t09/corefile.exp, gdb.t10/crossload.exp, gdb.t11/list.exp,
+ gdb.t12/scope.exp, gdb.t13/bitfields.exp}: Replace calls to
+ "alldone" proc with simple returns that suppress remaining
+ tests. The alldone proc went away many months ago.
+
+Tue Aug 24 11:04:06 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.t10/nodebug.exp: Comment out "maint print msymbols" tests.
+
+ * gdb.t12/gdbme0.c (localscopes, autovars): Modify to foil gcc -O.
+
+Thu Aug 19 22:08:41 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * gdb.t15/funcargs.exp: Allow arguments for main in backtraces
+ as vax gdb will display them.
+
+Thu Aug 19 18:18:59 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.t20/gdbme.cc: Do some calculation with v.x, to confound
+ optimizers.
+
+ * scope.exp: Change "bad value for localval" messages so each one
+ is unique.
+
+ * config/unix-gdb.exp (gdb_exit): Move info on this vs.
+ lib/gdb.exp (gdb_exit) from ChangeLog to comments.
+
+ * gdb.t06/signals.exp: Skip the whole file with xfail for delta68.
+
+Tue Aug 17 00:05:28 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.t00/teststrategy.exp: Deal with it if cmdsize = 1 line
+ doesn't exist (due to optimization).
+
+Mon Aug 16 21:05:49 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.stabs/wierd.exp: Deal with it if echo of "file" command
+ contains \r because the filename is long.
+
+ * gdb.t06/signals.exp: Revise comments regarding "'next' behaved as
+ 'continue'" bug, and change xfail back to i*86-univel-sysv4*.
+
+Mon Aug 16 03:05:17 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * gdb.t00/help.exp, gdb.t02/whatis.exp, gdb.t07/watchpoint.exp,
+ gdb.t08/opaque.exp, gdb.t17/interrupt.exp: Update for vax running
+ Ultrix.
+ * gdb.t02/whatis.exp: Use procedure to setup xfails on long versus
+ int tests.
+ * gdb.t08/opaque.exp: Use procedure to setup xfails for opaque tests.
+
+Thu Aug 12 15:24:28 1993 Fred Fish (fnf@deneb.cygnus.com)
+
+ * Makefile.in (distclean): Remove *.log *.plog *.sum *.psum site.*.
+
+ * gdb.t17/interrupt.exp: Fix 'missing Continuing' case so pattern
+ to match does not match the passing case but still matches the
+ failing case.
+
+Thu Aug 12 16:58:59 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * Makefile.in (distclean): Remove *.plog *.sum *.psum site.*.
+
+Wed Aug 11 19:47:27 1993 John Gilmore (gnu@rtl.cygnus.com)
+
+ * lib/gdb.exp (gdb_exit): Move the best version of gdb_exit
+ to here. Fix 'Quit anyway.*?' bug (? is a regexp metacharacter).
+ * config/{mips-gdb.exp, nind-gdb.exp, udi-gdb.exp, vx-gdb.exp}:
+ Remove various versions of gdb_exit.
+ * config/vx-gdb.exp: Remove quit_vxgdb, change a caller to call
+ gdb_exit.
+ * config/unix-gdb.exp: gdb_exit remains here, and should override
+ the generic version, since it's doing a lot of wierd stuff that
+ the other versions aren't. FIXME, fold it in, or abandon this
+ version.
+
+Wed Aug 11 12:09:32 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.t24/demangle.exp: Add tests for PR 3220.
+
+Tue Aug 10 15:49:35 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.t24/demangle.exp: Add lucid test for __vtbl__3foo__vt_cc_main_.
+
+Tue Aug 10 15:45:25 1993 Fred Fish (fnf@deneb.cygnus.com)
+
+ * gdb.t07/watchpoint.exp: Clear xfail with "i*86-*-*", not just
+ "i386-*-*". Works for i486 as well.
+
+ * gdb.t06/signals.exp: Rework code that recognizes known SVR4
+ bug, and expand domain of xfail to all SVR4 systems, since the
+ actual problem is likely to be in generic SVR4 /proc support.
+
+Tue Aug 10 15:49:35 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * config/unix-gdb.exp (gdb_load): Add eof to expect statement.
+
+Tue Aug 10 09:56:56 1993 Fred Fish (fnf@deneb.cygnus.com)
+
+ * gdb.t17/interrupt.exp: Set up xfail for *-*-sysv4*, in chain of
+ xfails for other systems. Match a missing 'Continuing.' as an
+ explicit fail for i*86-*-sysv4*, so it doesn't hose other tests.
+
+ * gdb.t20 {classes.exp, inherit.exp, misc.exp}, gdb.t21/cplusfuncs.exp,
+ gdb.t22/virtfunc.exp, gdb.t23/templates.exp, gdb.t31/chillvars.exp:
+ Only issue warning for missing executables if -all option is used.
+
+ * gdb.stabs/wierd.exp: Only issue warning for missing wierd.o
+ file if -all option is used. It's like an unpredictable XFAIL.
+
+Mon Aug 9 10:13:34 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.t15/funcargs.exp: Add comments that hppa xfails are only
+ for dynamically linked binaries.
+
+ * gdb.t10/crossload.exp: Add `set gnutarget auto' at end of tests.
+
+Sun Aug 8 14:21:29 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.t20/inherit.exp: Change message for "print tagless struct"
+ to state that this is a known bug in old versions of g++.
+
+Fri Aug 6 21:40:30 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * gdb.t17/interrupt.exp: Add xfail for 386 bsd. Accept echoed newline
+ while waiting for `Continuing'.
+
+Fri Aug 6 13:38:08 1993 Fred Fish (fnf@deneb.cygnus.com)
+
+ * gdb.t10/nodebug.exp: Expect to find local/global minimal symbols
+ in text, data, and bss.
+ * gdb.t10/nodebug.c: Add local and global test variables for
+ initialized and uninitialized data.
+
+Thu Aug 5 12:18:40 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * config/unix-gdb.exp (gdb_exit): Add "wait".
+
+Thu Aug 5 18:14:06 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * gdb.t06/signals.exp: xfail the continue from the handler for all
+ targets.
+
+ * gdb.t07/watchpoint.exp: clear_xfail for i386 when calling a
+ function with watchpoints enabled, the i386 call dummy starts with
+ a call.
+
+ * gdb.t00/teststrategy.exp, gdb.t09/Makefile.in: Handle the way
+ 386 bsd names its corefiles.
+
+Wed Aug 4 08:53:41 1993 Fred Fish (fnf@cygnus.com)
+
+ * gdb.t10/Makefile.in (nodebug.o): Don't use "-c -o", many
+ compilers don't grok it.
+ * gdb.t16/gdbme.c (ctable1): Initialize unsigned char array
+ with small octal ints rather than character constants, which
+ are signed and might not fit if first promoted to int.
+
+Tue Aug 3 18:28:25 1993 Fred Fish (fnf@cygnus.com)
+
+ * gdb.t09/Makefile.in (clean): Remove corefile.
+
+Mon Aug 2 12:47:44 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.t07/watchpoint.exp: Add missing `$prompt $'.
+
+Mon Aug 2 12:30:14 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+ and Jim Kingdon (kingdon@cygnus.com)
+
+ * gdb.t06/signals.exp: Change xfail from "*-*-*" to be only for
+ NO_SINGLE_STEP machines. Fix comment about its cause. Uncomment
+ the `continue' test right after it (also xfailed if NO_SINGLE_STEP).
+
+Fri Jul 30 19:46:55 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.t17/interrupt.exp: Add xfail for hppa.
+
+Fri Jul 30 12:54:11 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * gdb.t02/whatis.exp, gdb.t03/ptype.exp, gdb.t08/opaque.exp,
+ gdb.t09/corefile.exp: Cleanup xfails for fixed mips bugs.
+ * gdb.t13/bitfields.exp, gdbme.c: Examine a variable in the inferior
+ to determine signed-ness of bitfields and use the result to setup
+ the xfail.
+ * gdb.t15/gdbme.c: Add comments to the two indirect call0a lines.
+ * gdb.t15/funcargs.exp: Use them to step until the second indirect
+ call line is reached if necessary.
+
+Thu Jul 29 20:33:08 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.stabs/wierd.exp: New test, for nameless baseclasses.
+
+Mon Jul 26 00:15:02 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.t06/break.exp: Also test `clear' command.
+
+Wed Jul 21 18:03:38 1993 Jim Kingdon (kingdon@deneb.cygnus.com)
+
+ * gdb.t00/teststrategy.exp: Remove extra quote.
+
+ * gdb.t07/watchpoint.exp: Change xfail for calling function with
+ watchpoint enabled to be for all non-68k machines.
+
+ * gdb.t15/{mips_pro.{c,exp},Makefile.in}: New test.
+
+Mon Jul 19 23:59:26 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * gdb.stabs/configure.in: If configured -with-gnu-as for mips-*-*
+ targets use aout.mt instead of ecoff.mt as gas understands
+ standard aout format.
+
+Mon Jul 19 18:14:06 1993 Jim Kingdon (kingdon@deneb.cygnus.com)
+
+ * lib/gdb.exp (runto): Don't insist that function we are running to
+ was compiled with -g.
+
+ * gdb.t10/{nodebug.{c,exp},Makefile.in}: New test.
+
+ * gdb.t17/interrupt.exp: Before sending ^C, give the inferior time
+ to get back into the read system call.
+ Accept leading newline in case where we woke it up.
+
+Sun Jul 18 08:40:45 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * gdb.stabs/{ecoff.mt,wierd-ecoff.S,wierd-ecoff.sed}: New files
+ to make the stabs test work on ecoff systems using gcc and -with-stabs.
+ * gdb.stabs/{Makefile.in,configure.in,aout.mt,xcoff.mt}: Modify to
+ enable ecoff configuration.
+
+Thu Jul 15 11:54:58 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.t15/funcargs.exp (localvars_in_indirect_call): New test.
+
+Wed Jul 14 09:36:42 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.t16/printcmds.exp: Add another printf test.
+
+Wed Jul 14 15:37:13 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * configure.in: If configured -with-stabs on any target, add
+ stabsdirs to configdirs.
+
+Wed Jul 14 09:36:42 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.t16/printcmds.exp: Change printf "%f\n" to printf "%f is
+ fun" so pattern does not match the command itself.
+
+Mon Jul 12 11:22:06 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.t15/{gdbme.c,funcargs.exp}: Test for alloca-influenced frames.
+
+Sun Jul 11 12:03:24 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.t17/interrupt.exp: Test for more things.
+
+Fri Jul 9 14:11:17 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.t07/watchpoint.exp: In until test, deal with the way the DEC
+ compiler arranges the code and line numbers.
+
+ * gdb.t17/interrupt.exp: Don't send \n after ^C.
+
+Fri Jul 9 09:47:02 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * gdb.t00/help.exp: Increase expect input buffer size.
+
+Thu Jul 8 14:26:50 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.t06/signals.exp: Remove sparc xfail; bug fixed.
+
+ * gdb.t07/watchpoint.exp: Add xfail for hppa.
+
+ * gdb.t17/{gdbme.c,callfuncs.exp}: Add sum10 function, to test pa bug.
+
+ * gdb.t06/signals.exp: At "p func1 ()" test, check for breakpoint
+ [0-9]*, not just [0-9].
+
+Wed Jul 7 17:52:28 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.t20/{gdbme.cc,classes.exp}: Add xfail for gdb/2972.
+
+ * gdb.t2*: Set CXXFLAGS, not CFLAGS, since that's what we use.
+
+Tue Jul 6 13:54:49 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.t00/help.exp: Replace most of docstring for "continue" with .*.
+
+Mon Jul 5 22:03:45 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.t06/signals.c: Add xfails for sun3.
+
+ * gdb.t07/watchpoint.exp: Comment out xfail for fixed bug 1836.
+
+ * gdb.t07/{gdbme.c,watchpoint.exp}: Add test for 2597. Also add
+ test_stepping tests.
+
+Fri Jul 2 09:08:10 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.t{06,17}/Makefile.in (clean): Remove all executables.
+
+ * gdb.t17/{interrupt.{c,exp},Makefile.in}: New test for solaris bug.
+
+ * gdb.t06/twice.exp, Makefile.in: Just use an include of twice.c
+ rather than actually putting it through cpp twice.
+
+ * gdb.t06/signals.exp: Add xfails for unixware and rs6000.
+
+Fri Jul 2 10:48:03 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * config/mips-gdb.exp (gdb_exit): Removed close statement which is
+ no longer needed.
+
+Fri Jul 2 09:08:10 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.t06/signals.exp: Add test for sparc bug with do_save_insn.
+
+ * gdb.t20/{classes,inherit}.exp: If a class which doesn't use any
+ C++ features prints as "struct", make it a pass, not an xfail.
+
+Thu Jul 1 22:03:33 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.t22/virtfunc.exp: Remove a bunch of xfails.
+ Don't require VA to print as "class" rather than "struct".
+
+Thu Jul 1 18:27:40 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * gdb.t06/twice.exp: Don't care about the file name GDB prints.
+
+Wed Jun 30 18:01:00 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.t{02,13}/comp-info.c, gdb.t06/twice.exp: Add "return 0" to end.
+
+Tue Jun 29 13:15:42 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * gdb.t12/scope.exp: Remove xfail for parameter printing in wrong
+ order.
+
+Tue Jun 29 09:22:29 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.t16/printcmds.exp: Add printf tests.
+
+ * gdb.t06/{twice.{c,exp},Makefile.in}: New test.
+
+ * gdb.t10/Makefile.in (clean): Remove $(EXECUTABLES) too.
+
+Mon Jun 28 11:25:59 1993 Fred Fish (fnf@cygnus.com)
+
+ * gdb.t20/classes.exp: Add clear_xfail's before printing summary
+ pass counts, to counteract any existing or future setup_xfails.
+
+Mon Jun 28 09:15:17 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.stabs/wierd{.def,-aout.S,-xcoff.S}: Use new macros
+ {BEGIN,END}_COMMON for common block instead of STAB.
+ * gdb.stabs/wierd.exp: Add xfail for rs6000.
+
+ * gdb.stabs/wierd.def: Make value of N_GSYM's 0.
+ intp_var should be N_GSYM not N_LSYM.
+ wierd-aout.S: Use a label for the value of the N_SO.
+ wierd.def: Remove all backslashes.
+ wierd-{aout,xcoff}.S: Put a few tests with backslashes here.
+
+Mon Jun 28 07:21:51 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * gdb.t20/gdbme.cc (main): Move variable initialization for AIX to
+ get the expected next to inheritance3.
+
+Sun Jun 27 12:29:53 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * gdb.t00/teststrategy.exp: Remove expected failure for mips-*-*
+ now that gcc-2.4 gets it right.
+
+Fri Jun 25 12:00:46 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.stabs/wierd{.def,.exp,-aout.S,-xcoff.S}: Add common block test.
+
+ * gdb.t{02,13}/{Makefile.in,gdbme.c,comp-info.c}: New way of
+ generating comp-info.exp which works for cross-compilation.
+
+Thu Jun 24 16:55:05 1993 Fred Fish (fnf@cygnus.com)
+
+ * gdb.t11/list.exp: For SVR4 xfails, match "*-*-sysv4*", not
+ "*-*-sysv4.*".
+
+Tue Jun 22 21:17:26 1993 Fred Fish (fnf@cygnus.com)
+
+ * gdb.t01/run.exp: Start with a fresh gdb.
+ * gdb.t11/list.exp: For SVR4 xfails, match on all versions of
+ SVR4.x.
+
+Mon Jun 21 15:23:22 1993 Fred Fish (fnf@cygnus.com)
+
+ * {gdb.t01, gdb.t02, gdb.t03, gdb.t04, gdb.t05, gdb.t06, gdb.t07,
+ gdb.t08, gdb.t09, gdb.t10, gdb.t11, gdb.t12, gdb.t13, gdb.t15,
+ gdb.t16, gdb.t17, gdb.t20, gdb.t21, gdb.t22, gdb.t23, gdb.t30}/
+ Makefile.in (distclean, realclean): Remove gdbme.c from list of
+ things to remove.
+
+Sat Jun 19 07:49:10 1993 Fred Fish (fnf@cygnus.com)
+
+ * gdb.t24/demangle.exp (test_gnu_style_demangling): Add some new
+ test cases from bug reports.
+
+Fri Jun 18 10:38:49 1993 Fred Fish (fnf@cygnus.com)
+
+ * gdb.t06/break.exp: Add xfails for sparc-sun-solaris2.*.
+ * gdb.t12/scope.exp: Add clear_xfails at appropriate places to
+ avoid spurious xfails.
+ * gdb.t20/classes.exp: Add xfails for longstanding C++ problems.
+ * gdb.t21/cplusfuncs.exp: Add xfails for sparc-sun-solaris2.*.
+ * gdb.t22/virtfunc.exp: Add xfails for longstanding C++ problems.
+
+Wed Jun 16 10:11:57 1993 Fred Fish (fnf@cygnus.com)
+
+ * gdb.t00/teststrategy.exp: Rework to provide more useful
+ description of each test, fix problem with systems that define
+ ALIGN_STACK_ON_STARTUP code, other misc cleanups.
+ * gdb.t06/break.exp (test_next_with_recursion): Fix expected
+ results for "next over recursive call" so timeouts aren't taken
+ by error.
+
+Mon Jun 14 09:09:04 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * gdb.t12/scope.exp: Test printing of variables before run.
+
+ * gdb.t12/{gdbme0.c,scope.exp}: Test for bug where parameters are
+ printed in wrong order due to sorting.
+
+Sat Jun 12 15:03:58 1993 Fred Fish (fnf@cygnus.com)
+
+ * gdb.t00/teststrategy.exp: Fix expected results for printing
+ user entered string constant. Is array of char, prints with no
+ address.
+
+ * gdb.t00/{default.exp, help.exp}: Account for changes to radix
+ commands.
+ * gdb.t16/gdbme.c: Add and use struct containing arrays of char.
+ * gdb.t16/printcmds.exp: Fix all lines that match "unsigned char *".
+ * gdb.t16/printcmds.exp (test_print_char_arrays): Test printing
+ of struct of char arrays.
+ * gdb.t00/radix.exp: New tests for radix commands.
+
+Fri Jun 11 13:12:27 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * gdb.t16/printcmd.exp: Print a variable before running program
+ (with xfail for AIX).
+
+Thu Jun 10 11:04:04 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * gdb.t06/{signals.exp,signals.c,Makefile.in}: New test.
+
+ * gdb.t16/printcmd.exp: Don't print variables before running program.
+
+ * gdb.t06/break.exp: Don't require envp argument to main.
+
+ * gdb.t0{2,3,4,5}/gdbme.c [_AIX]: Use signed keyword.
+
+ * gdb.t02/whatis.exp, gdb.t11/list.exp:
+ Add xfails for rs6000.
+
+ * gdb.t02/whatis.exp: Change other tests not to re-test something
+ we already tested.
+
+ * gdb.t{03,15,16}/gdbme.c: Reference all variables and make sure
+ each type used has a variable of that type.
+
+Tue Jun 8 16:45:20 1993 Jim Kingdon (kingdon@rtl.cygnus.com)
+
+ * gdb.t20/{inherit.exp,gdbme.cc}: Test tagless structure.
+
+Fri Jun 4 11:07:19 1993 david d `zoo' zuhn (zoo at cirdan.cygnus.com)
+
+ * configure.in: change srctrigger to be a file, not a directory
+
+Fri Jun 4 08:23:57 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * configure.in (mips-idt-ecoff*): Added trailing '*'.
+
+ * gdb.t11/list.exp: Fixed a couple of typos.
+
+Tue Jun 1 21:28:06 1993 Fred Fish (fnf@cygnus.com)
+
+ * gdb.t00 (teststrategy.exp): Remove notice about PR 1823. Bug
+ is fixed and PR is closed.
+ * gdb.t16 (gdbme.c): Add simple test string variable.
+ * gdb.t16 (printcmds.exp): Add tests with simple test string
+ variable, primarily for boundaries on "set print elements".
+
+Mon May 31 11:36:08 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * gdb.stabs/wierd.exp: Remove xfail for printing big integer.
+ Make leading 0's optional and don't expect a tab in the middle
+ of the number.
+
+ * gdb.t00/teststrategy.exp: Remove xgdb before trying the copy.
+
+ * gdb.stabs/wierd.def: Type attributes must be preceded by number=.
+ * gdb.stabs/wierd.exp: Remove xfails for type attributes. Also
+ don't end command passed to gdb_test with newline.
+
+ * gdb.t13/{Makefile.in,gdbme.c,bitfields.exp}: If we #defined the
+ signed keyword away, don't expect signed bitfields to be signed.
+
+ * gdb.t13/bitfields.exp (bitfield containment): Accept the fields
+ printing with only as many 1's as are in the field as well as printing
+ with 32 1's (see comment).
+
+Sat May 29 17:57:01 1993 Fred Fish (fnf@cygnus.com)
+
+ * gdb.t00/default.exp: Start with a fresh gdb.
+ * configure.in (configdirs): Remove gdb.t31 until the chill
+ compiler works again. It no longer is able to find chillrt0
+ since it isn't in libchill.a anymore.
+ * gdb.stabs/wierd.exp: Rewrite to properly handling a missing
+ wierd.o, make more modular.
+ * gdb.stabs/wierd.def (bad_neg0type, bad_neg0const): Remove
+ spurious newlines that caused problems.
+
+Wed May 26 09:57:19 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * Move test with enums and partial symbols from gdb.t03/ptype.exp
+ to gdb.stabs/wierd.exp since GCC has worked around the bug.
+ gdb.stabs/wierd.{exp,def}: Many new tests.
+
+ * gdb.t00/default.exp: update info line for new message.
+
+ * gdb.t02/{whatis.exp,gdbme.c}:
+ Test that "char *" doesn't print as "caddr_t".
+
+Tue May 25 13:28:27 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.t00/help.exp: Use .* in place of some help messages which
+ just changed.
+ gdb.t00/default.exp: Update "info frame" test for new message.
+ * gdb.stabs/wierd.exp: Check for eof, directly or via gdb_test.
+ Remove some xfails
+
+Mon May 24 00:24:47 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.t03/{gdbme.c,ptype.exp}:
+ Add tests for typedef'd struct and union without tags.
+ Also check "whatis" on a variable of a typedef'd enum without a tag.
+
+ * gdb.t00/teststrategy.exp: For p "foo", remove sun4 XFAIL (see
+ PRMS 1823; the bug still exists but isn't reproduced by this test
+ anymore), and remove rs6000 XFAIL (the bug is fixed).
+
+ * gdb.t03/ptype.exp: Comment out a lot of tests which are basically
+ duplicated from whatis.exp. For those that are left, accept
+ "long", "long int", or "int" for long variables (whatis.exp already
+ has an XFAIL for "int", so no need to fail it here).
+
+ * gdb.t02/whatis.exp, gdb.t10/crossload.exp:
+ Deal with GCC's names for types now that GDB uses the compiler's names.
+
+ * gdb.t02/{Makefile.in,gdbme.c,whatis.exp}: If not GCC, do some
+ setup_xfail's for sunos4. If we #defined the signed keyword away,
+ don't expect GDB to know that char it is signed.
+
+ * gdb.t00/teststrategy.exp: Update for symbolic signal names.
+
+Sun May 23 08:44:55 1993 Fred Fish (fnf@cygnus.com)
+
+ * configure.in (configdirs): Add gdb.t24 for C++ tests that
+ should work on any system, regardless of debugging format.
+ * gdb.t21/demangle.exp: Move to gdb.t24.
+ * gdb.t24/demangle.exp: Move from gdb.t21.
+ * gdb.t24/{Makefile.in, configure.in}: New files.
+
+Thu May 20 19:39:03 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * configure.in: Do gdb.stabs and C++ tests only for stabs.
+ * gdb.stabs: New directory.
+
+Tue May 18 21:12:09 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * config/{mips,nind,udi,unix,vx}-gdb.exp: Look for "Quit anyway.*?"
+ not just "Quit anyway?".
+
+Tue May 18 17:13:20 1993 Fred Fish (fnf@cygnus.com)
+
+ * gdb.t21/demangle.exp: Add a couple of new patterns. Ensure
+ that all setup_xfails are immediately followed by clear_xfails.
+
+Tue May 11 09:10:47 1993 Fred Fish (fnf@cygnus.com)
+
+ * config/unix-gdb.exp, gdb.t00/echo.exp, gdb.t00/help.exp,
+ gdb.t00/teststrategy.exp, gdb.t00/gdbvars.exp, gdb.t01/run.exp,
+ gdb.t01/term.exp, gdb.t02/whatis.exp, gdb.t03/ptype.exp,
+ gdb.t04/setvar.exp, gdb.t05/expr.exp, gdb.t06/break.exp,
+ gdb.t07/watchpoint.exp, gdb.t08/opaque.exp, gdb.t09/corefile.exp,
+ gdb.t10/crossload.exp, gdb.t11/list.exp, gdb.t12/scope.exp,
+ gdb.t13/bitfields.exp, gdb.t15/funcargs.exp, gdb.t16/printcmds.exp,
+ gdb.t17/callfuncs.exp, gdb.t20/misc.exp, gdb.t20/inherit.exp,
+ gdb.t20/classes.exp, gdb.t21/demangle.exp, gdb.t21/cplusfuncs.exp,
+ gdb.t22/virtfunc.exp, gdb.t23/templates.exp, gdb.t30/chexp.exp,
+ gdb.t31/chillvars.exp, lib/gdb.exp:
+ Change place to report bugs from bug-dejagnu@prep.ai.mit.edu to
+ bug-gdb@prep.ai.mit.edu.
+
+Fri May 7 09:15:35 1993 Fred Fish (fnf@cygnus.com)
+
+ * gdb.t17/callfuncs.exp (do_function_calls): Call t_double_values
+ with 0.0, not integer 0.
+
+Fri Apr 30 13:17:24 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * gdb.t06/break.exp: Update for "Kill the program" message change.
+
+Fri Apr 30 09:42:57 1993 Fred Fish (fnf@cygnus.com)
+
+ * Makefile.in (GDBFLAGS): Set to -nx.
+ * Makefile.in (site.exp): Use GDBFLAGS.
+
+Wed Apr 28 13:19:07 1993 K. Richard Pixley (rich@rtl.cygnus.com)
+
+ * */Makefile.in (CFLAGS): add CFLAGS = -g to all subdirectory
+ Makefiles.
+ (check): depend on just-check.
+ (just-check): added so that tests can be run without a noop
+ build pass.
+
+Fri Apr 23 18:13:28 1993 K. Richard Pixley (rich@rtl.cygnus.com)
+
+ Switch to using configure's configdirs.
+ * Makefile.in (Makefile): add configure.in dependency.
+ (SUBDIRS): removed redundant assignment.
+ * configure.in: switch subdirs assignment to configdirs.
+ * gdb.t*/configure.in: new files.
+
+Thu Apr 22 08:27:53 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * gdb.t07/watchpoint.exp: Removed a29k expected failure which now
+ works.
+
+Tue Apr 20 13:38:40 1993 Fred Fish (fnf@cygnus.com)
+
+ * gdb.{t20,t21,t22,t23}/Makefile.in: Use $(srcdir) to avoid $<
+ in explicit rules. Apparently this is not supported by some makes.
+
+Mon Apr 19 01:54:53 1993 John Gilmore (gnu@cygnus.com)
+
+ * gdb.t31/Makefile.in: Use $(srcdir) when avoiding $<, sigh.
+
+Fri Apr 16 09:33:46 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * config/unix-gdb.exp: Add back missing return 0 which mysteriously
+ disappeared.
+
+Thu Apr 15 02:28:24 1993 John Gilmore (gnu@cacophony.cygnus.com)
+
+ * gdb.t31/Makefile.in: Avoid $< in explicit rule.
+
+Wed Apr 14 16:38:47 1993 Fred Fish (fnf@cygnus.com)
+
+ * gdb.t07/watchpoint.exp: Remove setup_xfail for i486
+ watchpoint problem that is now fixed.
+ * gdb.t30/chexp.exp: Remove setup_xfail for printing
+ uninitialized convenience variables.
+ * gdb.t31/chillvars.exp: Fix expected patterns for printing
+ structures.
+
+Wed Apr 14 12:55:58 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * gdb.t00/help.exp: Compensate for bug in mips-*-ultrix* OS
+ which causes expect to get out of sync with gdb on long output
+ from help set.
+ * gdb.t09/corefile.exp: Make expected pattern for core file
+ failing signal and frame output format less sun specific.
+
+Tue Apr 13 23:18:07 1993 Per Bothner (bothner@cygnus.com)
+
+ * gdb.t31/chillvars.exp: Add and remove initial dummy
+ breakpoint, so that symbol table is forced in.
+ (Needed at least on Sunos4, though it seems not SVR4.)
+ * gdb.t31/chillvars.exp: Update for changed output format.
+
+Sun Apr 11 17:21:45 1993 Rob Savoye (rob at darkstar.cygnus.com)
+
+ * config/unix-gdb.exp: Gracefully exits if $GDB is a bogus path.
+
+Wed Apr 7 21:28:21 1993 Rob Savoye (rob@cygnus.com)
+
+ * Makefile.in: Added --srcdir when invoking runtest, removed the
+ need for a local config file. (optional now)
+
+Wed Apr 7 14:13:41 1993 Fred Fish (fnf@cygnus.com)
+
+ * gdb.t21/demangle.exp: Only count real fails (not xfails) for
+ failure count used to force early termination. Add some more
+ expected failures for gnu style demangling.
+
+Thu Apr 1 09:50:30 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * Makefile.in (CXXFLAGS): Remove -O. It caused the debug info for the
+ pmi variable from gdb.t20/gdbme to get optimized away.
+ * gdb.t00/teststrategy.exp: Added expected failure for mips-*-*.
+ Check for written corefile upon timeout _and_ eof.
+
+Tue Mar 30 09:58:16 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * config/unix-gdb.exp: Add missing return 0.
+
+Tue Mar 30 08:34:25 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * gdb.t16/printcmds.exp: Remove misplaced xfail that caused an early
+ test termination.
+
+Mon Mar 29 17:37:25 1993 Fred Fish (fnf@cygnus.com)
+
+ * configure.in (subdirs): Put back gdb.t17 which mysteriously
+ disappeared.
+
+Thu Mar 25 21:05:16 1993 Fred Fish (fnf@cygnus.com)
+
+ * gdb.t10/crossload.exp: Disable the i860-elf test until such
+ time as i860 support works.
+
+ * gdb.t15/funcargs.exp: Fix expected outputs to include
+ "backtrace 100\r" rather than just "backtrace\r", to match last
+ change.
+
+Thu Mar 25 12:14:28 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * config/udi-gdb.exp (gdb_exit): Remove close command.
+ (gdb_target_udi): New procedure to set the UDI target.
+ (gdb_start): Don't remove *_soc files. Use gdb_target_udi.
+ * gdb.t00/default.exp: Added expected failures for a29k-*-udi.
+ Added waits for prompts after several question responses. Added
+ some more responses used by a29k-amd-udi-gdb.
+ * gdb.t01/run.exp, gdb.t06/break.exp: Added a29k-*-udi support:
+ pass different arguments, restart UDI connection after program
+ completion.
+ * gdb.t02/whatis.exp, gdb.t03/ptype.exp, gdb.t07/watchpoint.exp,
+ gdb.t08/opaque.exp, gdb.t11/list.exp, gdb.t12/scope.exp,
+ gdb.t15/funcargs.exp, gdb.t16/printcmds.exp, gdb.t20/misc.exp,
+ gdb.t21/cplusfuncs.exp: Added expected failures for a29k-*-*.
+ * gdb.t04/setvar.exp, gdb.t05/expr.exp, gdb.t07/watchpoint.exp,
+ gdb.t08/opaque.exp, gdb.t12/scope.exp, gdb.t13/bitfields.exp,
+ gdb.t15/funcargs.exp, gdb.t16/printcmds.exp,
+ gdb.t17/callfuncs.exp, gdb.t20/classes.exp, gdb.t20/inherit.exp,
+ gdb.t20/misc.exp, gdb.t22/virtfuncs.exp: Restart UDI connection
+ after program completion.
+ * gdb.t10/crossload.exp: Does not work for a29k-*-*, since BFD is
+ compiled with a SELECT_VECS setting.
+ * gdb.t15/funcargs.exp: Use argument to backtrace to prevent
+ infinite recursion.
+
+ * gdb.t20/classes.exp, gdb.t20/inherit.exp, gdb.t22/virtfuncs.exp:
+ Added checks for COFF results, and made them expected failures for
+ all targets. It would be better to make them expected failures
+ for COFF targets only.
+
+Wed Mar 24 14:43:38 1993 david d `zoo' zuhn (zoo at poseidon.cygnus.com)
+
+ * Makefile.in: add null dvi target, don't bother to recurse
+ through test directories for info and install-info; rename
+ $(datadir) to be dejagnu instead of deja-gnu
+
+Wed Mar 24 09:48:03 1993 Fred Fish (fnf@cygnus.com)
+
+ * gdb.t31/gdbme.ch: Re-enable code that previously caused
+ compiler to coredump.
+ * gdb.t31/chillvars.exp: Re-enable tests that depend on that
+ code.
+
+Tue Mar 23 08:53:42 1993 Fred Fish (fnf@cygnus.com)
+
+ * gdb.t31/gdbme.ch: Comment out code that causes chill compiler
+ coredump.
+ * gdb.t31/chillvars.exp: Comment out tests that depend on that
+ code.
+
+Sun Mar 21 17:56:47 1993 Rob Savoye (rob at darkstar.cygnus.com)
+
+ * gdb.t03/ptype.exp: tests for return code from gdb_test.
+ * gdb.t00/teststrategy.exp: Uses which proc rather than spawning
+ which in a shell. Deletes xgdb when done.
+ * config/unix-gdb.exp: Won't try to spawn $GDB unless it exists.
+ Tests the return from the "set height" or "set width" commands.
+ Added a few return codes where needed.
+
+Wed Mar 17 11:31:01 1993 Fred Fish (fnf@cygnus.com)
+
+ * Makefile.in (SUBDIRS): Add gdb.t17.
+ * configure.in (subdirs): Add gdb.t17.
+ * gdb.t17/{Makefile.in, callfuncs.exp, gdbme.c}: New test
+ files to test gdb's calling of functions in the inferior with
+ the correct arguments and gdb's ability to retrieve any
+ result returned.
+
+Tue Mar 16 15:37:11 1993 Fred Fish (fnf@cygnus.com)
+
+ * config/unix-gdb.exp (gdb_exit): Remove close commands that
+ may be called after gdb goes away. Previous versions of expect
+ needed these to avoid file descriptor leaks, but they cause
+ errors with the current revision of expect.
+ * gdb.t00/gdbvars.exp: Use -re on expected output after
+ setting sevenbit-strings.
+ * gdb.t04/setvar.exp, gdb.t13/bitfields.exp: Make commands
+ to set sevenbit-strings consistent across tests.
+ gdb.t30/chexp.exp, gdb.t31/chillvars.exp: Make commands to
+ set sevenbit-strings consistent across tests.
+
+Fri Mar 12 08:47:20 1993 Fred Fish (fnf@cygnus.com)
+
+ * gdb.t21/demangle.exp (proc demangle): Adjust quotes in an
+ expected output to match current "expect" expectations.
+
+Wed Mar 10 18:01:49 1993 Fred Fish (fnf@cygnus.com)
+
+ * gdb.t00/default.exp: Change expected output for default "source"
+ command, to match new gdb behavior which requires a filename to
+ source.
+
+Tue Mar 9 11:00:56 1993 Fred Fish (fnf@cygnus.com)
+
+ * gdb.t07/watchpoint.exp (test_simple_watchpoint): Set up
+ expected fail for i486-*-* that misses the marker2 function.
+ * gdb.t10/crossload.exp (bfddefault): Allow successful
+ recognition of a format to pass even if no symbols are found.
+ Explicitly catch failures where the format is not recognized
+ or is ambiguous, and add the reason to the fail message.
+ * gdb.t10/crossload.exp (bfdexplicit): Catch failure where
+ the cause is and invalid target and add reason to failure message.
+ * gdb.t10/crossload.exp: Fix bfd target names for elf32-m68k,
+ elf32-i386, elf32-sparc, and elf32-i860.
+ * gdb.t12/scope.exp (test_at_main, test_at_foo, test_at_bar):
+ Set up expected failure for 'filename'::variable scope resolution,
+ which is now apparently broken on all targets.
+ * gdb.t20/classes.exp, gdb.t20/inherit.exp, gdb.t20/misc.exp,
+ gdb.t21/cplusfuncs.exp, gdb.t22/virtfunc.exp,
+ gdb.t23/templates.exp: Change failure for missing binfile into
+ just a warning.
+ gdb.t21/demangle.exp: Change all cfront references to 'arm'
+ references.
+
+Mon Mar 8 19:20:28 1993 Fred Fish (fnf@cygnus.com)
+
+ * gdb.t00/default.exp: Add expected output for default "source"
+ command, to match new gdb behavior.
+ * gdb.t09/corefile.exp: Use GDBFLAGS when spawning GDB.
+
+Sun Mar 7 15:14:09 1993 Rob Savoye (rob@cygnus.com)
+
+ * config/*-gdb.exp: returns an error, rather than exiting on
+ internal errors.
+
+Tue Mar 2 18:09:32 1993 Fred Fish (fnf@cygnus.com)
+
+ * gdb.t03/gdbme.c: Add pointer to struct variable.
+ * gdb.t03/ptype.exp: Test equivalence of '.' and '->' for
+ referencing struct members.
+
+Thu Feb 25 10:39:06 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * configure.in (mips-idt-ecoff): New target.
+ * config/mips-gdb.exp: New file for remote board using MIPS remote
+ debugging protocol.
+
+ * Redid configuration scheme. Removed gdb.t*/configure.in.
+ Renamed gdb.t*/in-gdbme* to gdb.t*/gdbme*. Changed to use CC, CXX
+ instead of CC_FOR_TARGET, CXX_FOR_TARGET. Added mostlyclean and
+ distclean targets. Built executables via .o files. Adjusted
+ tests to account for source files in $(srcdir) rather than
+ $(objdir).
+ * lib/gdb.exp (runto): Don't expect () after the function name,
+ because it may have arguments.
+
+Wed Feb 24 08:05:38 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * gdb.t00/default.exp, gdb.t01/run.exp, gdb.t02/whatis.exp,
+ gdb.t03/ptype.exp, gdb.t06/break.exp, gdb.t12/scope.exp: Added
+ expected failures for mips-idt-* and mips-sgi-*.
+ * gdb.t00/default.exp (attach): Kill process if requested.
+ * gdb.t00/help.exp (help target core, help target): Accept a gdb
+ that does not read core files.
+ * gdb.t01/run.exp: Removed checks for exit status code.
+ * gdb.t03/in-gdbme.c: Make explicit call to malloc to ensure that
+ it is linked in.
+ * gdb.t03/ptype.exp: Increase timeout when calling malloc.
+ * gdb.t04/setvar.exp, gdb.t05/expr.exp: Use runto function where
+ appropriate, rather than doing it by hand.
+ * gdb.t07/watchpoint.exp: If mips-idt-*, reload file after first
+ execution.
+ * gdb.t10/crossload.exp: Kill existing program if needed.
+ * gdb.t15/funcargs.exp: Use delete_breakpoints function where
+ appropriate, rather than doing it by hand. Always increase
+ timeout for this test, not just for VxWorks.
+
+Wed Feb 24 08:03:38 1993 Fred Fish (fnf@cygnus.com)
+
+ * gdb.t31/chillvars.exp (test_structs): New proc to test printing
+ of Chill STRUCT types and STRUCT values.
+ * gdb.t31/chillvars.exp (test_strings): Expect "CHAR" now, rather
+ than "char".
+ * gdb.t31/in-gdbme.ch (simple_struct, nested_struct, struct1,
+ struct2): New struct definitions and initializations to test
+ simple Chill STRUCT types.
+
+Tue Feb 23 11:55:06 1993 Fred Fish (fnf@cygnus.com)
+
+ * gdb.t00/teststrategy.exp: Track reversion in gdb to not print
+ the null byte at the end of strings.
+ * gdb.t00/default.exp: Make show version insensitive to copyright
+ date.
+ * gdb.t16/in-gdbme.c (ctable1, ctable2): Make explicitly unsigned
+ to avoid dependencies on target char signedness.
+ * gdb.t16/printcmds.exp: Update expected results for explicitly
+ unsigned char.
+ * gdb.t16/printcmds.exp: Remove setup_xfails for i960 that should
+ now work.
+ * gdb.t21/demangle.exp: Add many more patterns for template
+ demangling, most of them being expected failures.
+ * gdb.t21/demangle.exp (proc demangle): Quote the demangled
+ string we are matching for, to match on the whole string.
+ * gdb.t21/demangle.exp: Add many new test strings to demangle,
+ and fix a whole bunch that had incorrect expected output but were
+ passing anyway because of the bug in "proc demangle".
+ * gdb.t31/chillvars.exp: Remove setup_xfail for printing string
+ type.
+ * gdb.t31/in-gdbme.ch: Uncomment string4, now compiles.
+
+Mon Feb 22 07:54:03 1993 Mike Werner (mtw@poseidon.cygnus.com)
+
+ * gdb/testsuite: made modifications to testcases, etc., to allow
+ them to work properly given the reorganization of deja-gnu and the
+ relocation of the testcases from deja-gnu to a "tool" subdirectory.
+
+Sun Feb 21 10:55:55 1993 Mike Werner (mtw@poseidon.cygnus.com)
+
+ * gdb/testsuite: Initial creation of gdb/testsuite.
+ Migrated dejagnu testcases and support files for testing nm to
+ gdb/testsuite from deja-gnu. These files were moved "as is"
+ with no modifications. This migration is part of a major overhaul
+ of dejagnu. The modifications to these testcases, etc., which
+ will allow them to work with the new version of dejagnu will be
+ made in a future update.
+
+Local Variables:
+mode: indented-text
+left-margin: 8
+fill-column: 74
+version-control: never
+End:
diff --git a/gdb/testsuite/Makefile.in b/gdb/testsuite/Makefile.in
new file mode 100644
index 00000000000..d763450e2eb
--- /dev/null
+++ b/gdb/testsuite/Makefile.in
@@ -0,0 +1,187 @@
+# Makefile for regression testing the GNU debugger.
+# Copyright (C) 1992, 1993, 1994, 1995, 1999 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 2, or (at your option)
+# any later version.
+
+# GDB is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+VPATH = @srcdir@
+srcdir = @srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+host_alias = @host_alias@
+target_alias = @target_alias@
+program_transform_name = @program_transform_name@
+build_canonical = @build@
+host_canonical = @host@
+target_canonical = @target@
+target_cpu = @gdb_target_cpu@
+
+SHELL = @SHELL@
+SUBDIRS = @subdirs@
+RPATH_ENVVAR = @RPATH_ENVVAR@
+
+EXPECT = `if [ -f $${rootme}/../../expect/expect ] ; then \
+ echo $${rootme}/../../expect/expect ; \
+ else echo expect ; fi`
+
+RUNTEST = $(RUNTEST_FOR_TARGET)
+
+RUNTESTFLAGS =
+
+RUNTEST_FOR_TARGET = `\
+ if [ -f $${srcdir}/../../dejagnu/runtest ]; then \
+ echo $${srcdir}/../../dejagnu/runtest; \
+ else \
+ if [ "$(host_canonical)" = "$(target_canonical)" ]; then \
+ echo runtest; \
+ else \
+ t='$(program_transform_name)'; echo runtest | sed -e '' $$t; \
+ fi; \
+ fi`
+
+#### host, target, and site specific Makefile frags come in here.
+
+# The use of $$(x_FOR_TARGET) reduces the command line length by not
+# duplicating the lengthy definition.
+
+TARGET_FLAGS_TO_PASS = \
+ "prefix=$(prefix)" \
+ "exec_prefix=$(exec_prefix)" \
+ "against=$(against)" \
+ 'CC=$$(CC_FOR_TARGET)' \
+ "CC_FOR_TARGET=$(CC_FOR_TARGET)" \
+ "CFLAGS=$(TESTSUITE_CFLAGS)" \
+ "CHILLFLAGS=$(CHILLFLAGS)" \
+ 'CHILL=$$(CHILL_FOR_TARGET)' \
+ "CHILL_FOR_TARGET=$(CHILL_FOR_TARGET)" \
+ "CHILL_LIB=$(CHILL_LIB)" \
+ 'CXX=$$(CXX_FOR_TARGET)' \
+ "CXX_FOR_TARGET=$(CXX_FOR_TARGET)" \
+ "CXXFLAGS=$(CXXFLAGS)" \
+ "MAKEINFO=$(MAKEINFO)" \
+ "INSTALL=$(INSTALL)" \
+ "INSTALL_PROGRAM=$(INSTALL_PROGRAM)" \
+ "INSTALL_DATA=$(INSTALL_DATA)" \
+ "LDFLAGS=$(LDFLAGS)" \
+ "LIBS=$(LIBS)" \
+ "RUNTEST=$(RUNTEST)" \
+ "RUNTESTFLAGS=$(RUNTESTFLAGS)"
+
+all:
+ @echo "Nothing to be done for all..."
+
+.NOEXPORT:
+INFODIRS=doc
+info:
+install-info:
+dvi:
+
+install:
+
+uninstall: force
+
+site.exp: ./config.status Makefile
+ @echo "Making a new config file..."
+ -@rm -f ./tmp?
+ @touch site.exp
+ -@mv site.exp site.bak
+ @echo "## these variables are automatically generated by make ##" > ./tmp0
+ @echo "# Do not edit here. If you wish to override these values" >> ./tmp0
+ @echo "# add them to the last section" >> ./tmp0
+ @echo "set host_alias $(host_alias)" >> ./tmp0
+ @echo "set host_triplet ${host_canonical}" >> ./tmp0
+ @echo "set target_alias $(target_alias)" >> ./tmp0
+ @echo "set target_triplet ${target_canonical}" >> ./tmp0
+ @echo "set build_triplet ${build_canonical}" >> ./tmp0
+ @echo "set srcdir ${srcdir}" >> ./tmp0
+ @echo "set tool gdb" >> ./tmp0
+ @echo "## All variables above are generated by configure. Do Not Edit ##" >> ./tmp0
+ @cat ./tmp0 > site.exp
+ @cat site.bak | sed \
+ -e '1,/^## All variables above are.*##/ d' >> site.exp
+ -@rm -f ./tmp?
+
+installcheck:
+
+check: site.exp all just-check
+
+just-check:
+ rootme=`pwd`; export rootme; \
+ srcdir=${srcdir} ; export srcdir ; \
+ EXPECT=${EXPECT} ; export EXPECT ; \
+ $(RPATH_ENVVAR)=$$rootme/../../expect:$$rootme/../../libstdc++:$$rootme/../../tk/unix:$$rootme/../../tcl/unix:$$rootme/../../bfd:$$rootme/../../opcodes:$$$(RPATH_ENVVAR); \
+ export $(RPATH_ENVVAR); \
+ if [ -f $${rootme}/../../expect/expect ] ; then \
+ TCL_LIBRARY=$${srcdir}/../../tcl/library ; \
+ export TCL_LIBRARY ; fi ; \
+ $(RUNTEST) $(RUNTESTFLAGS)
+
+subdir_do: force
+ @for i in $(DODIRS); do \
+ if [ -d ./$$i ] ; then \
+ if (rootme=`pwd`/ ; export rootme ; \
+ rootsrc=`cd $(srcdir); pwd`/ ; export rootsrc ; \
+ cd ./$$i; \
+ $(MAKE) $(TARGET_FLAGS_TO_PASS) $(DO)) ; then true ; \
+ else exit 1 ; fi ; \
+ else true ; fi ; \
+ done
+
+force:;
+
+subdirs:
+ for dir in ${SUBDIRS} ; \
+ do \
+ echo "$$dir:" ; \
+ if [ -d $$dir ] ; then \
+ (rootme=`pwd`/ ; export rootme ; \
+ rootsrc=`cd $(srcdir); pwd`/ ; export rootsrc ; \
+ cd $$dir; $(MAKE) $(TARGET_FLAGS_TO_PASS)); \
+ fi; \
+ done
+
+clean mostlyclean:
+ -rm -f *~ core *.o a.out xgdb *.x *.grt
+ if [ x"${SUBDIRS}" != x ] ; then \
+ for dir in ${SUBDIRS}; \
+ do \
+ echo "$$dir:"; \
+ if [ -d $$dir ]; then \
+ (cd $$dir; $(MAKE) clean); \
+ fi; \
+ done ; \
+ else true; fi
+
+distclean maintainer-clean realclean: clean
+ -rm -f *~ core
+ -rm -f Makefile config.status *-init.exp
+ -rm -fr *.log summary detail *.plog *.sum *.psum site.*
+ if [ x"${SUBDIRS}" != x ] ; then \
+ for dir in ${SUBDIRS}; \
+ do \
+ echo "$$dir:"; \
+ if [ -d $$dir ]; then \
+ (cd $$dir; $(MAKE) distclean); \
+ fi; \
+ done ; \
+ else true; fi
+
+Makefile : Makefile.in config.status $(host_makefile_frag) $(target_makefile_frag)
+ $(SHELL) config.status
+
+config.status: configure
+ $(SHELL) config.status --recheck
diff --git a/gdb/testsuite/TODO b/gdb/testsuite/TODO
new file mode 100644
index 00000000000..978991c77cd
--- /dev/null
+++ b/gdb/testsuite/TODO
@@ -0,0 +1,202 @@
+The highest priority item is not on this list: Fix bugs in the
+existing testsuite, fix the GDB/compiler/shell/etc bugs which it
+detects (particularly when they are hard to XFAIL), make it run
+reliably without unexpected failures on the "standard" machines, etc.
+This list exists largely as "tests we can add when we are ready to
+risk destabilizing it again".
+
+There are some tests which are only run on some platforms because they
+have not been tested on more platforms. Enable them and fix any
+problems. A partial list: recurse.exp, watchpoint.exp
+(test_watchpoint_triggered_in_syscall, test_complex_watchpoint).
+
+Test printing of structures passed by value, for the 7th, 8th, and 9th
+arguments (PR 1714). Test printing structure arguments of
+2,4,6,8,12,16,and 20 bytes. Same for structure return of all those
+sizes ("return", "finish", and call function).
+
+Get crossload tests to use --enable-targets and reenable them.
+
+corefile.exp:
+Test ability to run program when there is a core target, then go
+back to the core file when the program exits.
+
+Test handling of floating point variables
+1. float, double, or long double
+2. in register or saved register or memory. Also the case where a
+double is in two float registers and only one of them is saved.
+3. print them or set them
+4. (Alpha) integer (32 or 64 bit) in floating point register.
+
+Print registers--"p $r5", "p sizeof ($r5)". Test that they print
+appropriately (integer registers in decimal, registers which always
+contain addresses (pc, probably sp and fp, maybe others) in hex,
+floating point).
+
+Test completer. Test that it completes a variety of things correctly
+(see the list of test cases in main.c in the gdb source). Test TAB,
+M-?, and the "complete" command.
+
+Test "info line" with all kinds of linespecs. Test that the last line
+of the file works right.
+
+weird.exp--test that unrecognized cross-reference types or
+unrecognized visibility or virtual characters get skipped properly
+(see stabs.texinfo).
+
+Test C++ nested types (especially if PR 1954 is fixed; even if not
+*some* things already should work even in the presence of nested
+types). Test classes nested more than 9 levels deep (g++ mangles
+these differently) (both a demangle test and some tests which also
+test the compiler). Test calling a method of a class nested more than
+9 levels (for gdb_mangle_name and demangling).
+
+Test static member functions (C++). Test that "ptype" shows them
+correctly, both before and after they have been converted from stub
+methods. Test that we can call them.
+
+Test printing complicated types, including functions, pointers to
+arrays of pointers of functions, functions which return pointers to
+functions, etc.
+
+printcmd.exp--test printing enum values. Test printing an enum
+variable whose value is out of range. Test "p (int)enum_var", "p/x
+enum_var". Test that in something like "enum {FOO, LAST_THING=FOO}"
+we print FOO, not LAST_THING.
+
+Test GDB expressions--test all operators (and overloaded operators for
+C++). Test integer constants which are signed or unsigned int, long,
+or long long. Test detection of overflow of an integer constant.
+Here are a few integer constants to test (test they get the right
+types): 5, 5LL, 5LuL, 5L6u (invalid), 5LU. Maybe things like
+0x12345678, 0x87654321, etc., but their types depend on sizes of int,
+long, etc.
+
+Test that printing const-qualified versions of various types works.
+In particular, on the sparc and probably other machines, "double" is
+handled differently from most types because it requires more alignment
+and thus goes in a different section (there is a gcc 2.4.5 bug with
+"const double" on sparc).
+
+Test that GDB's "source" command works and that things work if stdin
+is redirected (to a file or a pipe). Test user defined command. Run
+an inferior each of these ways (to test that inflow.c works). Test
+that GDB works if the last line of stdin or a source'd file lacks a
+newline.
+
+Test that unmatched single quotes produce error messages, both in
+expressions and linespecs.
+
+Test "cd". "foo/bar/.." should get simplified to "foo". "/../.."
+should not get simplified (for Mach). "/.." should not get simplified
+(for other networked OSes; POSIX.1 section B.2.3.7). All these
+examples should continue to work with trailing slashes.
+
+Test scoping; here is a start
+ 1 int i=2;
+ 2 int j=3;
+ 3 main()
+ 4 {
+ 5 int i;
+ 6 for (i=600; i>0; i--)
+ 7 print_line(i);
+ 8 }
+ 9
+10 print_line(i)
+11 int i;
+12 {
+13 h();
+14 printf("%d\n",i);
+15 }
+16
+17 h()
+18 {
+19 printf("In h...");
+20 }
+Set a breakpoint in h, and print i, print_line::i, and main::i. Set a
+breakpoint in main (or don't run the program), and test that
+print_line::i is an error. But if i were static, "p main::i" should
+work even if the program is not being run.
+
+Write a test for the reentracy bug with rs6000_struct_return_address
+in rs6000-tdep.c.
+
+Test "return" from dummy frames. Test "return" from non-innermost
+frame. Test that "return" from a non-innermost frame restores
+registers which are saved not in that frame but in a frame more inner
+(I believe this currently works on few if any architectures).
+
+FORTRAN common blocks (a.out and xcoff--weird.exp has the start of
+one but it is not quite right as of 19 Nov 1993).
+
+Test that "x" command sets $_ and $__. Test $_ in general.
+
+Test that "p/a" works when given addresses in text, data, and bss
+segments. Test that it works if program is compiled with or without
+-g. Test that it works if preceding symbol is static or if it is
+extern.
+
+Given `char abc[] = "abc\0def";' test "x/s abc" followed by "x/s"
+(should display "abc" followed by "def"). Test this works with no
+error message even if this is the last thing in the section (tests
+that val_print_string ignores an error if the error occurs after the
+'\0').
+
+Test ability to process NMAGIC a.out files.
+
+Test shared libraries: "next" over printf, "step" into a function in
+a shared library which has line number info, breakpoint in a function
+in a shared library (either before or after the program is run and the
+shared libraries are loaded--also maybe write a test where the PLT
+will be in an unloaded state even though the shared library is loaded).
+
+If there are two breakpoints in the same place, and exactly one of
+them has its condition true, test that the correct breakpoint gets
+printed.
+
+Test "jump" including jump to a breakpoint (the latter will need an
+xfail for UDI and probably VxWorks (PR 1786 for vxworks; PR 2416
+contains some info for 29k).
+
+Set a watchpoint on a local variable (to be interesting, make a few
+calls, to be more interesting, make a recursive call). Test that it
+gets disabled when leaving that scope.
+
+Test calling a function, hitting a breakpoint in the called function,
+calling another function, and hitting a breakpoint. Test backtrace
+works in the presence of multiple dummy frames. Test that "continue"
+will get you out of the inner called function, and "continue" again
+will get you back to where you were when you called the first one.
+
+Test special longjmp handling in wait_for_inferior (need to figure out
+in detail what the proper behavior in each case is). Test longjmp to
+a place where there is a breakpoint (such that
+BPSTAT_WHAT_CLEAR_LONGJMP_RESUME_SINGLE happens). In general, test
+interactions between longjmp and watchpoints, breakpoints, stepping,
+call function, etc.
+
+Test jumping right past a breakpoint (the case where wait_for_inferior
+passes not_a_breakpoint to bpstat_stop_status). Might already be
+tested by some of the sun3 tests. Probably want a .s test to avoid
+compiler dependencies.
+
+Test more obscure wait_for_inferior cases, expanding on the tests in
+watchpoint.exp, signals.exp, etc.
+
+Test stepping into functions which are one line long and functions
+which are on line 1 of the source file. (there is a class of bugs in
+which gdb doesn't find the line number information, and thus doesn't
+step into the function).
+
+Test that prologue recognition, backtrace, printing locals, etc.,
+still work in the presence of large frames (the point being that at
+some point immediate fields in RISC instructions will overflow and
+prologues will need to look different. For sparc, the immediate field
+is 13 bits (signed), so I believe the threshold would be 4K bytes in a
+frame).
+
+
+(this is for editing this file with GNU emacs)
+Local Variables:
+mode: text
+End:
diff --git a/gdb/testsuite/aclocal.m4 b/gdb/testsuite/aclocal.m4
new file mode 100644
index 00000000000..c754fdcf2f7
--- /dev/null
+++ b/gdb/testsuite/aclocal.m4
@@ -0,0 +1,583 @@
+dnl This file is duplicated in four places:
+dnl * gdb/aclocal.m4
+dnl * gdb/testsuite/aclocal.m4
+dnl * expect/aclocal.m4
+dnl * dejagnu/aclocal.m4
+dnl Consider modifying all copies in parallel.
+dnl written by Rob Savoye <rob@cygnus.com> for Cygnus Support
+dnl CYGNUS LOCAL: This gets the right posix flag for gcc
+AC_DEFUN(CY_AC_TCL_LYNX_POSIX,
+[AC_REQUIRE([AC_PROG_CC])AC_REQUIRE([AC_PROG_CPP])
+AC_MSG_CHECKING([to see if this is LynxOS])
+AC_CACHE_VAL(ac_cv_os_lynx,
+[AC_EGREP_CPP(yes,
+[/*
+ * The old Lynx "cc" only defines "Lynx", but the newer one uses "__Lynx__"
+ */
+#if defined(__Lynx__) || defined(Lynx)
+yes
+#endif
+], ac_cv_os_lynx=yes, ac_cv_os_lynx=no)])
+#
+if test "$ac_cv_os_lynx" = "yes" ; then
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(LYNX)
+ AC_MSG_CHECKING([whether -mposix or -X is available])
+ AC_CACHE_VAL(ac_cv_c_posix_flag,
+ [AC_TRY_COMPILE(,[
+ /*
+ * This flag varies depending on how old the compiler is.
+ * -X is for the old "cc" and "gcc" (based on 1.42).
+ * -mposix is for the new gcc (at least 2.5.8).
+ */
+ #if defined(__GNUC__) && __GNUC__ >= 2
+ choke me
+ #endif
+ ], ac_cv_c_posix_flag=" -mposix", ac_cv_c_posix_flag=" -X")])
+ CC="$CC $ac_cv_c_posix_flag"
+ AC_MSG_RESULT($ac_cv_c_posix_flag)
+ else
+ AC_MSG_RESULT(no)
+fi
+])
+
+AC_DEFUN(CY_AC_PATH_TCLH, [
+#
+# Ok, lets find the tcl source trees so we can use the headers
+# Warning: transition of version 9 to 10 will break this algorithm
+# because 10 sorts before 9. We also look for just tcl. We have to
+# be careful that we don't match stuff like tclX by accident.
+# the alternative search directory is involked by --with-tclinclude
+#
+no_tcl=true
+AC_MSG_CHECKING(for Tcl private headers)
+AC_ARG_WITH(tclinclude, [ --with-tclinclude directory where tcl private headers are], with_tclinclude=${withval})
+AC_CACHE_VAL(ac_cv_c_tclh,[
+# first check to see if --with-tclinclude was specified
+if test x"${with_tclinclude}" != x ; then
+ if test -f ${with_tclinclude}/tclInt.h ; then
+ ac_cv_c_tclh=`(cd ${with_tclinclude}; pwd)`
+ else
+ AC_MSG_ERROR([${with_tclinclude} directory doesn't contain private headers])
+ fi
+fi
+# next check in private source directory
+#
+# since ls returns lowest version numbers first, reverse its output
+if test x"${ac_cv_c_tclh}" = x ; then
+ for i in \
+ ${srcdir}/../tcl \
+ `ls -dr ${srcdir}/../tcl[[0-9]]* 2>/dev/null` \
+ ${srcdir}/../../tcl \
+ `ls -dr ${srcdir}/../../tcl[[0-9]]* 2>/dev/null` \
+ ${srcdir}/../../../tcl \
+ `ls -dr ${srcdir}/../../../tcl[[0-9]]* 2>/dev/null ` ; do
+ if test -f $i/tclInt.h ; then
+ ac_cv_c_tclh=`(cd $i; pwd)`
+ break
+ fi
+ # Tcl 7.5 and greater puts headers in subdirectory.
+ if test -f $i/generic/tclInt.h ; then
+ ac_cv_c_tclh=`(cd $i; pwd)`/generic
+ break
+ fi
+ done
+fi
+# finally check in a few common install locations
+#
+# since ls returns lowest version numbers first, reverse its output
+if test x"${ac_cv_c_tclh}" = x ; then
+ for i in \
+ `ls -dr /usr/local/src/tcl[[0-9]]* 2>/dev/null` \
+ `ls -dr /usr/local/lib/tcl[[0-9]]* 2>/dev/null` \
+ /usr/local/src/tcl \
+ /usr/local/lib/tcl \
+ ${prefix}/include ; do
+ if test -f $i/tclInt.h ; then
+ ac_cv_c_tclh=`(cd $i; pwd)`
+ break
+ fi
+ done
+fi
+# see if one is installed
+if test x"${ac_cv_c_tclh}" = x ; then
+ AC_HEADER_CHECK(tclInt.h, ac_cv_c_tclh=installed, ac_cv_c_tclh="")
+fi
+])
+if test x"${ac_cv_c_tclh}" = x ; then
+ TCLHDIR="# no Tcl private headers found"
+ AC_MSG_ERROR([Can't find Tcl private headers])
+fi
+if test x"${ac_cv_c_tclh}" != x ; then
+ no_tcl=""
+ if test x"${ac_cv_c_tclh}" = x"installed" ; then
+ AC_MSG_RESULT([is installed])
+ TCLHDIR=""
+ else
+ AC_MSG_RESULT([found in ${ac_cv_c_tclh}])
+ # this hack is cause the TCLHDIR won't print if there is a "-I" in it.
+ TCLHDIR="-I${ac_cv_c_tclh}"
+ fi
+fi
+
+AC_MSG_CHECKING([Tcl version])
+orig_includes="$CPPFLAGS"
+
+if test x"${TCLHDIR}" != x ; then
+ CPPFLAGS="$CPPFLAGS $TCLHDIR"
+fi
+
+# Get major and minor versions of Tcl. Use funny names to avoid
+# clashes with eg SunOS.
+cat > conftest.c <<'EOF'
+#include "tcl.h"
+MaJor = TCL_MAJOR_VERSION
+MiNor = TCL_MINOR_VERSION
+EOF
+
+tclmajor=
+tclminor=
+if (eval "$CPP $CPPFLAGS conftest.c") 2>/dev/null >conftest.out; then
+ # Success.
+ tclmajor=`egrep '^MaJor = ' conftest.out | sed -e 's/^MaJor = *//' -e 's/ *$//'`
+ tclminor=`egrep '^MiNor = ' conftest.out | sed -e 's/^MiNor = *//' -e 's/ *$//'`
+fi
+rm -f conftest.c conftest.out
+
+if test -z "$tclmajor" || test -z "$tclminor"; then
+ AC_MSG_RESULT([fatal error: could not find major or minor version number of Tcl])
+ exit 1
+fi
+AC_MSG_RESULT(${tclmajor}.${tclminor})
+
+CPPFLAGS="${orig_includes}"
+
+AC_PROVIDE([$0])
+AC_SUBST(TCLHDIR)
+])
+AC_DEFUN(CY_AC_PATH_TCLLIB, [
+#
+# Ok, lets find the tcl library
+# First, look for one uninstalled.
+# the alternative search directory is invoked by --with-tcllib
+#
+
+if test $tclmajor -ge 7 -a $tclminor -ge 4 ; then
+ installedtcllibroot=tcl$tclversion
+else
+ installedtcllibroot=tcl
+fi
+
+if test x"${no_tcl}" = x ; then
+ # we reset no_tcl incase something fails here
+ no_tcl=true
+ AC_ARG_WITH(tcllib, [ --with-tcllib directory where the tcl library is],
+ with_tcllib=${withval})
+ AC_MSG_CHECKING([for Tcl library])
+ AC_CACHE_VAL(ac_cv_c_tcllib,[
+ # First check to see if --with-tcllib was specified.
+ # This requires checking for both the installed and uninstalled name-styles
+ # since we have no idea if it's installed or not.
+ if test x"${with_tcllib}" != x ; then
+ if test -f "${with_tcllib}/lib$installedtcllibroot.so" ; then
+ ac_cv_c_tcllib=`(cd ${with_tcllib}; pwd)`/lib$installedtcllibroot.so
+ elif test -f "${with_tcllib}/libtcl.so" ; then
+ ac_cv_c_tcllib=`(cd ${with_tcllib}; pwd)`/libtcl.so
+ # then look for a freshly built statically linked library
+ # if Makefile exists we assume its configured and libtcl will be built first.
+ elif test -f "${with_tcllib}/lib$installedtcllibroot.a" ; then
+ ac_cv_c_tcllib=`(cd ${with_tcllib}; pwd)`/lib$installedtcllibroot.a
+ elif test -f "${with_tcllib}/libtcl.a" ; then
+ ac_cv_c_tcllib=`(cd ${with_tcllib}; pwd)`/libtcl.a
+ else
+ AC_MSG_ERROR([${with_tcllib} directory doesn't contain libraries])
+ fi
+ fi
+ # then check for a private Tcl library
+ # Since these are uninstalled, use the simple lib name root.
+ if test x"${ac_cv_c_tcllib}" = x ; then
+ for i in \
+ ../tcl \
+ `ls -dr ../tcl[[0-9]]* 2>/dev/null` \
+ ../../tcl \
+ `ls -dr ../../tcl[[0-9]]* 2>/dev/null` \
+ ../../../tcl \
+ `ls -dr ../../../tcl[[0-9]]* 2>/dev/null` ; do
+ # Tcl 7.5 and greater puts library in subdir. Look there first.
+ if test -f "$i/unix/libtcl.so" ; then
+ ac_cv_c_tcllib=`(cd $i; pwd)`/unix/libtcl.so
+ break
+ elif test -f "$i/unix/libtcl.a" -o -f "$i/unix/Makefile"; then
+ ac_cv_c_tcllib=`(cd $i; pwd)`/unix/libtcl.a
+ break
+ # look for a freshly built dynamically linked library
+ elif test -f "$i/libtcl.so" ; then
+ ac_cv_c_tcllib=`(cd $i; pwd)`/libtcl.so
+ break
+
+ # then look for a freshly built statically linked library
+ # if Makefile exists we assume its configured and libtcl will be
+ # built first.
+ elif test -f "$i/libtcl.a" -o -f "$i/Makefile" ; then
+ ac_cv_c_tcllib=`(cd $i; pwd)`/libtcl.a
+ break
+ fi
+ done
+ fi
+ # check in a few common install locations
+ if test x"${ac_cv_c_tcllib}" = x ; then
+ for i in `ls -d ${prefix}/lib /usr/local/lib 2>/dev/null` ; do
+ # first look for a freshly built dynamically linked library
+ if test -f "$i/lib$installedtcllibroot.so" ; then
+ ac_cv_c_tcllib=`(cd $i; pwd)`/lib$installedtcllibroot.so
+ break
+ # then look for a freshly built statically linked library
+ # if Makefile exists we assume its configured and libtcl will be built first.
+ elif test -f "$i/lib$installedtcllibroot.a" -o -f "$i/Makefile" ; then
+ ac_cv_c_tcllib=`(cd $i; pwd)`/lib$installedtcllibroot.a
+ break
+ fi
+ done
+ fi
+ # check in a few other private locations
+ if test x"${ac_cv_c_tcllib}" = x ; then
+ for i in \
+ ${srcdir}/../tcl \
+ `ls -dr ${srcdir}/../tcl[[0-9]]* 2>/dev/null` ; do
+ # Tcl 7.5 and greater puts library in subdir. Look there first.
+ if test -f "$i/unix/libtcl.so" ; then
+ ac_cv_c_tcllib=`(cd $i; pwd)`/unix/libtcl.so
+ break
+ elif test -f "$i/unix/libtcl.a" -o -f "$i/unix/Makefile"; then
+ ac_cv_c_tcllib=`(cd $i; pwd)`/unix/libtcl.a
+ break
+ # look for a freshly built dynamically linked library
+ elif test -f "$i/libtcl.so" ; then
+ ac_cv_c_tcllib=`(cd $i; pwd)`/libtcl.so
+ break
+
+ # then look for a freshly built statically linked library
+ # if Makefile exists we assume its configured and libtcl will be
+ # built first.
+ elif test -f "$i/libtcl.a" -o -f "$i/Makefile" ; then
+ ac_cv_c_tcllib=`(cd $i; pwd)`/libtcl.a
+ break
+ fi
+ done
+ fi
+
+ # see if one is conveniently installed with the compiler
+ if test x"${ac_cv_c_tcllib}" = x ; then
+ orig_libs="$LIBS"
+ LIBS="$LIBS -l$installedtcllibroot -lm"
+ AC_TRY_RUN([
+ Tcl_AppInit()
+ { exit(0); }], ac_cv_c_tcllib="-l$installedtcllibroot", ac_cv_c_tcllib=""
+ , ac_cv_c_tclib="-l$installedtcllibroot")
+ LIBS="${orig_libs}"
+ fi
+ ])
+ if test x"${ac_cv_c_tcllib}" = x ; then
+ TCLLIB="# no Tcl library found"
+ AC_MSG_WARN(Can't find Tcl library)
+ else
+ TCLLIB=${ac_cv_c_tcllib}
+ AC_MSG_RESULT(found $TCLLIB)
+ no_tcl=
+ fi
+fi
+
+AC_PROVIDE([$0])
+AC_SUBST(TCLLIB)
+])
+AC_DEFUN(CY_AC_PATH_TKH, [
+#
+# Ok, lets find the tk source trees so we can use the headers
+# If the directory (presumably symlink) named "tk" exists, use that one
+# in preference to any others. Same logic is used when choosing library
+# and again with Tcl. The search order is the best place to look first, then in
+# decreasing significance. The loop breaks if the trigger file is found.
+# Note the gross little conversion here of srcdir by cd'ing to the found
+# directory. This converts the path from a relative to an absolute, so
+# recursive cache variables for the path will work right. We check all
+# the possible paths in one loop rather than many seperate loops to speed
+# things up.
+# the alternative search directory is invoked by --with-tkinclude
+#
+AC_MSG_CHECKING(for Tk private headers)
+AC_ARG_WITH(tkinclude, [ --with-tkinclude directory where the tk private headers are],
+ with_tkinclude=${withval})
+no_tk=true
+AC_CACHE_VAL(ac_cv_c_tkh,[
+# first check to see if --with-tkinclude was specified
+if test x"${with_tkinclude}" != x ; then
+ if test -f ${with_tkinclude}/tk.h ; then
+ ac_cv_c_tkh=`(cd ${with_tkinclude}; pwd)`
+ else
+ AC_MSG_ERROR([${with_tkinclude} directory doesn't contain private headers])
+ fi
+fi
+# next check in private source directory
+#
+# since ls returns lowest version numbers first, reverse the entire list
+# and search for the worst fit, overwriting it with better fits as we find them
+if test x"${ac_cv_c_tkh}" = x ; then
+ for i in \
+ ${srcdir}/../tk \
+ `ls -dr ${srcdir}/../tk[[0-9]]* 2>/dev/null` \
+ ${srcdir}/../../tk \
+ `ls -dr ${srcdir}/../../tk[[0-9]]* 2>/dev/null` \
+ ${srcdir}/../../../tk \
+ `ls -dr ${srcdir}/../../../tk[[0-9]]* 2>/dev/null ` ; do
+ if test -f $i/tk.h ; then
+ ac_cv_c_tkh=`(cd $i; pwd)`
+ break
+ fi
+ # Tk 4.1 and greater puts this in a subdir.
+ if test -f $i/generic/tk.h; then
+ ac_cv_c_tkh=`(cd $i; pwd)`/generic
+ fi
+ done
+fi
+# finally check in a few common install locations
+#
+# since ls returns lowest version numbers first, reverse the entire list
+# and search for the worst fit, overwriting it with better fits as we find them
+if test x"${ac_cv_c_tkh}" = x ; then
+ for i in \
+ `ls -dr /usr/local/src/tk[[0-9]]* 2>/dev/null` \
+ `ls -dr /usr/local/lib/tk[[0-9]]* 2>/dev/null` \
+ /usr/local/src/tk \
+ /usr/local/lib/tk \
+ ${prefix}/include ; do
+ if test -f $i/tk.h ; then
+ ac_cv_c_tkh=`(cd $i; pwd)`
+ break
+ fi
+ done
+fi
+# see if one is installed
+if test x"${ac_cv_c_tkh}" = x ; then
+ AC_HEADER_CHECK(tk.h, ac_cv_c_tkh=installed)
+fi
+])
+if test x"${ac_cv_c_tkh}" != x ; then
+ no_tk=""
+ if test x"${ac_cv_c_tkh}" = x"installed" ; then
+ AC_MSG_RESULT([is installed])
+ TKHDIR=""
+ else
+ AC_MSG_RESULT([found in $ac_cv_c_tkh])
+ # this hack is cause the TKHDIR won't print if there is a "-I" in it.
+ TKHDIR="-I${ac_cv_c_tkh}"
+ fi
+else
+ TKHDIR="# no Tk directory found"
+ AC_MSG_WARN([Can't find Tk private headers])
+ no_tk=true
+fi
+
+# if Tk is installed, extract the major/minor version
+if test x"${no_tk}" = x ; then
+AC_MSG_CHECKING([Tk version])
+orig_includes="$CPPFLAGS"
+
+if test x"${TCLHDIR}" != x ; then
+ CPPFLAGS="$CPPFLAGS $TCLHDIR"
+fi
+if test x"${TKHDIR}" != x ; then
+ CPPFLAGS="$CPPFLAGS $TKHDIR"
+fi
+if test x"${x_includes}" != x -a x"${x_includes}" != xNONE ; then
+ CPPFLAGS="$CPPFLAGS -I$x_includes"
+fi
+
+# Get major and minor versions of Tk. Use funny names to avoid
+# clashes with eg SunOS.
+cat > conftest.c <<'EOF'
+#include "tk.h"
+MaJor = TK_MAJOR_VERSION
+MiNor = TK_MINOR_VERSION
+EOF
+
+tkmajor=
+tkminor=
+if (eval "$CPP $CPPFLAGS conftest.c") 2>/dev/null >conftest.out; then
+ # Success.
+ tkmajor=`egrep '^MaJor = ' conftest.out | sed -e 's/^MaJor = *//' -e 's/ *$//'`
+ tkminor=`egrep '^MiNor = ' conftest.out | sed -e 's/^MiNor = *//' -e 's/ *$//'`
+fi
+rm -f conftest.c conftest.out
+
+if test -z "$tkmajor" || test -z "$tkminor"; then
+ AC_MSG_RESULT([fatal error: could not find major or minor version number of Tk])
+ exit 1
+fi
+AC_MSG_RESULT(${tkmajor}.${tkminor})
+
+CPPFLAGS="${orig_includes}"
+fi
+
+AC_PROVIDE([$0])
+AC_SUBST(TKHDIR)
+])
+AC_DEFUN(CY_AC_PATH_TKLIB, [
+AC_REQUIRE([CY_AC_PATH_TCL])
+#
+# Ok, lets find the tk library
+# First, look for the latest private (uninstalled) copy
+# Notice that the destinations in backwards priority since the tests have
+# no break.
+# Then we look for either .a, .so, or Makefile. A Makefile is acceptable
+# is it indicates the target has been configured and will (probably)
+# soon be built. This allows an entire tree of Tcl software to be
+# configured at once and then built.
+# the alternative search directory is invoked by --with-tklib
+#
+
+if test x"${no_tk}" = x ; then
+ # reset no_tk incase something fails here
+ no_tk="true"
+
+ if test $tkmajor -ge 4 ; then
+ installedtklibroot=tk$tkversion
+ else
+ installedtkllibroot=tk
+ fi
+
+ AC_ARG_WITH(tklib, [ --with-tklib directory where the tk library is],
+ with_tklib=${withval})
+ AC_MSG_CHECKING([for Tk library])
+ AC_CACHE_VAL(ac_cv_c_tklib,[
+ # first check to see if --with-tklib was specified
+ # This requires checking for both the installed and uninstalled name-styles
+ # since we have no idea if it's installed or not.
+ if test x"${with_tklib}" != x ; then
+ if test -f "${with_tklib}/lib$installedtklibroot.so" ; then
+ ac_cv_c_tklib=`(cd ${with_tklib}; pwd)`/lib$installedtklibroot.so
+ no_tk=""
+ elif test -f "${with_tklib}/libtk.so" ; then
+ ac_cv_c_tklib=`(cd ${with_tklib}; pwd)`/libtk.so
+ no_tk=""
+ # then look for a freshly built statically linked library
+ # if Makefile exists we assume its configured and libtk will be built
+ elif test -f "${with_tklib}/lib$installedtklibroot.a" ; then
+ ac_cv_c_tklib=`(cd ${with_tklib}; pwd)`/lib$installedtklibroot.a
+ no_tk=""
+ elif test -f "${with_tklib}/libtk.a" ; then
+ ac_cv_c_tklib=`(cd ${with_tklib}; pwd)`/libtk.a
+ no_tk=""
+ else
+ AC_MSG_ERROR([${with_tklib} directory doesn't contain libraries])
+ fi
+ fi
+ # then check for a private Tk library
+ # Since these are uninstalled, use the simple lib name root.
+ if test x"${ac_cv_c_tklib}" = x ; then
+ for i in \
+ ../tk \
+ `ls -dr ../tk[[0-9]]* 2>/dev/null` \
+ ../../tk \
+ `ls -dr ../../tk[[0-9]]* 2>/dev/null` \
+ ../../../tk \
+ `ls -dr ../../../tk[[0-9]]* 2>/dev/null` ; do
+ # Tk 4.1 and greater puts things in subdirs. Check these first.
+ if test -f "$i/unix/libtk.so" ; then
+ ac_cv_c_tklib=`(cd $i; pwd)`/unix/libtk.so
+ no_tk=
+ break
+ elif test -f "$i/unix/libtk.a" -o -f "$i/unix/Makefile"; then
+ ac_cv_c_tklib=`(cd $i; pwd)`/unix/libtk.a
+ no_tk=
+ break
+ # look for a freshly built dynamically linked library
+ elif test -f "$i/libtk.so" ; then
+ ac_cv_c_tklib=`(cd $i; pwd)`/libtk.so
+ no_tk=
+ break
+ # then look for a freshly built statically linked library
+ # if Makefile exists we assume its configured and libtk will be built
+ elif test -f "$i/libtk.a" -o -f "$i/Makefile" ; then
+ ac_cv_c_tklib=`(cd $i; pwd)`/libtk.a
+ no_tk=""
+ break
+ fi
+ done
+ fi
+ # finally check in a few common install locations
+ if test x"${ac_cv_c_tklib}" = x ; then
+ for i in `ls -d ${prefix}/lib /usr/local/lib 2>/dev/null` ; do
+ # first look for a freshly built dynamically linked library
+ if test -f "$i/lib$installedtklibroot.so" ; then
+ ac_cv_c_tklib=`(cd $i; pwd)`/lib$installedtklibroot.so
+ no_tk=""
+ break
+ # then look for a freshly built statically linked library
+ # if Makefile exists, we assume it's configured and libtcl will be built
+ elif test -f "$i/lib$installedtklibroot.a" -o -f "$i/Makefile" ; then
+ ac_cv_c_tklib=`(cd $i; pwd)`/lib$installedtklibroot.a
+ no_tk=""
+ break
+ fi
+ done
+ fi
+ # check in a few other private locations
+ if test x"${ac_cv_c_tklib}" = x ; then
+ for i in \
+ ${srcdir}/../tk \
+ `ls -dr ${srcdir}/../tk[[0-9]]* 2>/dev/null` ; do
+ # Tk 4.1 and greater puts things in subdirs. Check these first.
+ if test -f "$i/unix/libtk.so" ; then
+ ac_cv_c_tklib=`(cd $i; pwd)`/unix/libtk.so
+ no_tk=
+ break
+ elif test -f "$i/unix/libtk.a" -o -f "$i/unix/Makefile"; then
+ ac_cv_c_tcllib=`(cd $i; pwd)`/unix/libtk.a
+ no_tk=
+ break
+ # look for a freshly built dynamically linked library
+ elif test -f "$i/libtk.so" ; then
+ ac_cv_c_tklib=`(cd $i; pwd)`/libtk.so
+ no_tk=""
+ break
+ # then look for a freshly built statically linked library
+ # if Makefile exists, we assume it's configured and libtcl will be built
+ elif test -f "$i/libtk.a" -o -f "$i/Makefile" ; then
+ ac_cv_c_tklib=`(cd $i; pwd)`/libtk.a
+ no_tk=""
+ break
+ fi
+ done
+ fi
+ # see if one is conveniently installed with the compiler
+ if test x"${ac_cv_c_tklib}" = x ; then
+ AC_REQUIRE([AC_PATH_X])
+ orig_libs="$LIBS"
+ LIBS="$LIBS -l$installedtklibroot $x_libraries $ac_cv_c_tcllib -lm"
+ AC_TRY_RUN([
+ Tcl_AppInit()
+ { exit(0); }], ac_cv_c_tklib="-l$installedtklibroot", ac_cv_c_tklib=""
+ , ac_cv_c_tklib="-l$installedtklibroot")
+ LIBS="${orig_libs}"
+ fi
+ ])
+ if test x"${ac_cv_c_tklib}" = x ; then
+ TKLIB="# no Tk library found"
+ AC_MSG_WARN(Can't find Tk library)
+ else
+ TKLIB=$ac_cv_c_tklib
+ AC_MSG_RESULT(found $TKLIB)
+ no_tk=
+ fi
+fi
+AC_PROVIDE([$0])
+AC_SUBST(TKLIB)
+])
+AC_DEFUN(CY_AC_PATH_TK, [
+ CY_AC_PATH_TKH
+ CY_AC_PATH_TKLIB
+])
+AC_DEFUN(CY_AC_PATH_TCL, [
+ CY_AC_PATH_TCLH
+ CY_AC_PATH_TCLLIB
+])
diff --git a/gdb/testsuite/config/abug.exp b/gdb/testsuite/config/abug.exp
new file mode 100644
index 00000000000..e6ade13e5af
--- /dev/null
+++ b/gdb/testsuite/config/abug.exp
@@ -0,0 +1,20 @@
+# Copyright (C) 1997 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+load_lib ../config/monitor.exp
diff --git a/gdb/testsuite/config/arm-ice.exp b/gdb/testsuite/config/arm-ice.exp
new file mode 100644
index 00000000000..d9842743d94
--- /dev/null
+++ b/gdb/testsuite/config/arm-ice.exp
@@ -0,0 +1 @@
+load_lib "../config/monitor.exp";
diff --git a/gdb/testsuite/config/cpu32bug.exp b/gdb/testsuite/config/cpu32bug.exp
new file mode 100644
index 00000000000..e6ade13e5af
--- /dev/null
+++ b/gdb/testsuite/config/cpu32bug.exp
@@ -0,0 +1,20 @@
+# Copyright (C) 1997 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+load_lib ../config/monitor.exp
diff --git a/gdb/testsuite/config/cygmon.exp b/gdb/testsuite/config/cygmon.exp
new file mode 100644
index 00000000000..d9842743d94
--- /dev/null
+++ b/gdb/testsuite/config/cygmon.exp
@@ -0,0 +1 @@
+load_lib "../config/monitor.exp";
diff --git a/gdb/testsuite/config/d10v.exp b/gdb/testsuite/config/d10v.exp
new file mode 100644
index 00000000000..955288c7ff0
--- /dev/null
+++ b/gdb/testsuite/config/d10v.exp
@@ -0,0 +1,20 @@
+# Copyright (C) 1997 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+load_lib "../config/monitor.exp"
diff --git a/gdb/testsuite/config/dve.exp b/gdb/testsuite/config/dve.exp
new file mode 100644
index 00000000000..6aa46c1c834
--- /dev/null
+++ b/gdb/testsuite/config/dve.exp
@@ -0,0 +1,23 @@
+# Copyright (C) 1998 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+load_lib ../config/monitor.exp
+set timeout 1000
+verbose "Timeout is now $timeout seconds" 2
+
diff --git a/gdb/testsuite/config/est.exp b/gdb/testsuite/config/est.exp
new file mode 100644
index 00000000000..e6ade13e5af
--- /dev/null
+++ b/gdb/testsuite/config/est.exp
@@ -0,0 +1,20 @@
+# Copyright (C) 1997 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+load_lib ../config/monitor.exp
diff --git a/gdb/testsuite/config/gdbserver.exp b/gdb/testsuite/config/gdbserver.exp
new file mode 100644
index 00000000000..bb6f724f3b7
--- /dev/null
+++ b/gdb/testsuite/config/gdbserver.exp
@@ -0,0 +1,104 @@
+# Test Framework Driver for GDB using the extended gdb remote protocol
+# Copyright 1995, 1997 Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# For this to function correctly, you need to set a number of variables
+# in your gdb/site.exp file
+#
+# set noargs 1 -- we can't pass arguments (yet)
+# set noinferiorio 1 -- we can't get io to/from the inferior
+# set targethost <host> -- name of the remote system (runs gdbserver)
+# set debughost <host> -- name of the system running gdb
+# set port <number> -- starting port number for communication
+# set gdbserver <path> -- path (on the remote side) to find
+# gdbserver
+# set rsh <path> -- path (on debughost side) to rsh
+# set rcp <path> -- path (on debughost side) to rcp
+#
+# You will need to be able to spawn processes from gdbhost to run on
+# targethost via rsh (this is how we start gdbserver); similarly
+# you need to be able to rcp files from gdbhost to targethost.
+#
+# We don't do much error checking, if something goes wrong, you'll probably
+# just get a tcl error and everything will die. FIXME
+#
+
+# Load the basic gdb testing library
+load_lib gdb.exp
+load_lib monitor.exp
+
+#
+# gdb_load -- load a file into the debugger.
+# return a -1 if anything goes wrong.
+#
+# Loading a file in the gdbsrever framework is a little strange in that
+# we also create the inferior (which is stopped at the first instruction
+# in the program when we get control).
+#
+proc gdb_load { arg } {
+ global verbose
+ global loadpath
+ global loadfile
+ global GDB
+ global gdb_prompt
+ global debughost
+ global port
+
+ # bump the port number to avoid conflicts with hung ports
+ set targethost [target_info gdb_server_host];
+ set debughost [target_info gdb_debug_host];
+ if [target_info exists gdb_server_prog] {
+ set gdbserver [target_info gdb_server_prog];
+ } else {
+ set gdbserver "gdbserver";
+ }
+ incr port
+ set serialport $targethost:$port
+
+ # Copy the file down to the remote host.
+ set file [remote_download host $arg];
+
+ # now start gdbserver on the remote side
+ remote_spawn host "$gdbserver $debughost:$port $file >& /dev/null < /dev/null"
+
+ # give it plenty of time to get going (lynx)
+ sleep 30
+
+ # tell gdb we are remote debugging
+ if [gdb_target_monitor $arg] {
+ return -1;
+ }
+
+ return 1
+}
+
+#
+# gdb_start -- start GDB running.
+#
+proc gdb_start { } {
+ global gdb_prompt
+
+ # do the usual stuff
+ catch default_gdb_start
+
+ # FIXME: This shouldn't be necessary, but lots of PA tests fail
+ # without it.
+ send "set remotecache 0\n"
+ expect {
+ -re "set remotecache 0\[\r\n\]+.*$gdb_prompt $" {}
+ default { fail "gdb_start"}
+ }
+}
diff --git a/gdb/testsuite/config/h8300.exp b/gdb/testsuite/config/h8300.exp
new file mode 100644
index 00000000000..d9842743d94
--- /dev/null
+++ b/gdb/testsuite/config/h8300.exp
@@ -0,0 +1 @@
+load_lib "../config/monitor.exp";
diff --git a/gdb/testsuite/config/hmsirom.exp b/gdb/testsuite/config/hmsirom.exp
new file mode 100644
index 00000000000..75fc81da18a
--- /dev/null
+++ b/gdb/testsuite/config/hmsirom.exp
@@ -0,0 +1,22 @@
+# Copyright (C) 1997 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# Support for testing against a Hitachi SH3 target rom
+
+load_lib ../config/monitor.exp
diff --git a/gdb/testsuite/config/hppro.exp b/gdb/testsuite/config/hppro.exp
new file mode 100644
index 00000000000..0fca142235f
--- /dev/null
+++ b/gdb/testsuite/config/hppro.exp
@@ -0,0 +1,24 @@
+# Copyright (C) 1997 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+load_lib ../config/monitor.exp
+
+# Hppro monitor is very slow...
+set timeout 540
+verbose "Timeout is now $timeout seconds" 2
diff --git a/gdb/testsuite/config/i386-bozo.exp b/gdb/testsuite/config/i386-bozo.exp
new file mode 100644
index 00000000000..78090937380
--- /dev/null
+++ b/gdb/testsuite/config/i386-bozo.exp
@@ -0,0 +1 @@
+load_lib "../config/monitor.exp"
diff --git a/gdb/testsuite/config/i960.exp b/gdb/testsuite/config/i960.exp
new file mode 100644
index 00000000000..e6ade13e5af
--- /dev/null
+++ b/gdb/testsuite/config/i960.exp
@@ -0,0 +1,20 @@
+# Copyright (C) 1997 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+load_lib ../config/monitor.exp
diff --git a/gdb/testsuite/config/m32r-stub.exp b/gdb/testsuite/config/m32r-stub.exp
new file mode 100644
index 00000000000..cd04787ddb6
--- /dev/null
+++ b/gdb/testsuite/config/m32r-stub.exp
@@ -0,0 +1 @@
+load_lib "../../testsuite/config/sparclet.exp"
diff --git a/gdb/testsuite/config/m32r.exp b/gdb/testsuite/config/m32r.exp
new file mode 100644
index 00000000000..94dc6a24c4b
--- /dev/null
+++ b/gdb/testsuite/config/m32r.exp
@@ -0,0 +1,23 @@
+# Copyright (C) 1997 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+load_lib ../config/monitor.exp
+set timeout 120
+verbose "Timeout is now $timeout seconds" 2
+
diff --git a/gdb/testsuite/config/m68k-emc.exp b/gdb/testsuite/config/m68k-emc.exp
new file mode 100644
index 00000000000..70b8f5ef426
--- /dev/null
+++ b/gdb/testsuite/config/m68k-emc.exp
@@ -0,0 +1,17 @@
+load_lib gdb.exp
+load_lib "../config/monitor.exp"
+
+proc gdb_emclaptop_command { command } {
+ global board_info;
+ set tname [board_info target name];
+
+ if ![info exists board_info($tname,m68k_connected)] {
+ m68k_emc_board_connect target;
+ }
+ # This is about all we can do for now. *sigh*
+ set dos_host [board_info target dos_host];
+
+ remote_send $dos_host "${command}\n";
+ #remote_expect $dos_host {
+ #}
+}
diff --git a/gdb/testsuite/config/mips-idt.exp b/gdb/testsuite/config/mips-idt.exp
new file mode 100644
index 00000000000..72664dff1b1
--- /dev/null
+++ b/gdb/testsuite/config/mips-idt.exp
@@ -0,0 +1,22 @@
+# Copyright (C) 1993, 1997 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# DejaGnu@cygnus.com
+
+load_lib ../config/monitor.exp
+
+
diff --git a/gdb/testsuite/config/mips.exp b/gdb/testsuite/config/mips.exp
new file mode 100644
index 00000000000..72664dff1b1
--- /dev/null
+++ b/gdb/testsuite/config/mips.exp
@@ -0,0 +1,22 @@
+# Copyright (C) 1993, 1997 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# DejaGnu@cygnus.com
+
+load_lib ../config/monitor.exp
+
+
diff --git a/gdb/testsuite/config/mn10300-eval.exp b/gdb/testsuite/config/mn10300-eval.exp
new file mode 100644
index 00000000000..6aa46c1c834
--- /dev/null
+++ b/gdb/testsuite/config/mn10300-eval.exp
@@ -0,0 +1,23 @@
+# Copyright (C) 1998 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+load_lib ../config/monitor.exp
+set timeout 1000
+verbose "Timeout is now $timeout seconds" 2
+
diff --git a/gdb/testsuite/config/monitor.exp b/gdb/testsuite/config/monitor.exp
new file mode 100644
index 00000000000..0d381a22cfa
--- /dev/null
+++ b/gdb/testsuite/config/monitor.exp
@@ -0,0 +1,230 @@
+# Test Framework Driver for GDB driving a ROM monitor (via monitor.c).
+# Copyright 1995, 1997 Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+load_lib gdb.exp
+
+#
+# gdb_target_monitor
+# Set gdb to target the monitor
+#
+proc gdb_target_monitor { exec_file } {
+ global gdb_prompt
+ global exit_status
+ global timeout
+
+ if [target_info exists gdb_protocol] {
+ set targetname "[target_info gdb_protocol]"
+ } else {
+ perror "No protocol specified for [target_info name].";
+ return -1;
+ }
+ if [target_info exists baud] {
+ gdb_test "set remotebaud [target_info baud]" "" ""
+ }
+ if [target_info exists gdb_serial] {
+ set serialport "[target_info gdb_serial]";
+ } elseif [target_info exists netport] {
+ set serialport "[target_info netport]"
+ } else {
+ set serialport "[target_info serial]"
+ }
+
+ for {set j 1} {$j <= 2} {incr j} {
+ if [gdb_file_cmd $exec_file] { return -1; }
+
+ for {set i 1} {$i <= 3} {incr i} {
+ send_gdb "target $targetname $serialport\n"
+ gdb_expect 60 {
+ -re "A program is being debugged already.*ill it.*y or n. $" {
+ send_gdb "y\n";
+ exp_continue;
+ }
+ -re "Couldn't establish connection to remote.*$gdb_prompt" {
+ verbose "Connection failed";
+ }
+ -re "Remote MIPS debugging.*$gdb_prompt" {
+ verbose "Set target to $targetname";
+ return 0;
+ }
+ -re "Remote debugging using .*$serialport.*$gdb_prompt" {
+ verbose "Set target to $targetname";
+ return 0;
+ }
+ -re "Remote target $targetname connected to.*$gdb_prompt" {
+ verbose "Set target to $targetname";
+ return 0;
+ }
+ -re "Connected to.*$gdb_prompt" {
+ verbose "Set target to $targetname";
+ return 0;
+ }
+ -re "Ending remote.*$gdb_prompt" { }
+ -re "Connection refused.*$gdb_prompt" {
+ verbose "Connection refused by remote target. Pausing, and trying again."
+ sleep 30
+ continue
+ }
+ -re "Timeout reading from remote system.*$gdb_prompt" {
+ verbose "Got timeout error from gdb.";
+ }
+ timeout {
+ send_gdb "";
+ break
+ }
+ }
+ }
+
+ gdb_target_exec;
+
+ if { $j == 1 && ![reboot_target] } {
+ break;
+ }
+ }
+
+ perror "Couldn't set target for $targetname, port is $serialport.";
+ return -1;
+}
+
+proc gdb_target_exec { } {
+ gdb_test "target exec" "No executable file now." "" ".*Kill it.*y or n.*" "y"
+
+}
+#
+# gdb_load -- load a file into the debugger.
+# return a -1 if anything goes wrong.
+#
+proc gdb_load { arg } {
+ global verbose
+ global loadpath
+ global loadfile
+ global GDB
+ global gdb_prompt
+ global timeout
+ global last_gdb_file;
+
+ if { $arg == "" } {
+ if [info exists last_gdb_file] {
+ set arg $last_gdb_file;
+ } else {
+ send_gdb "info files\n";
+ gdb_expect 30 {
+ -re "Symbols from \"(\[^\"\]+)\"" {
+ set arg $expect_out(1,string);
+ exp_continue;
+ }
+ -re "Local exec file:\[\r\n\]+\[ \t\]*`(\[^'\]+)'," {
+ set arg $expect_out(1,string);
+ exp_continue;
+ }
+ -re "$gdb_prompt $" { }
+ }
+ }
+ }
+
+ set last_gdb_file $arg;
+
+ for { set j 1; } { $j <= 2 } {incr j; } {
+ if [target_info exists gdb,use_standard_load] {
+ gdb_target_exec;
+ if ![target_info exists gdb,no_push_conn] {
+ remote_push_conn host;
+ }
+ set state [remote_ld target $arg];
+ if ![target_info exists gdb,no_push_conn] {
+ remote_close target;
+ remote_pop_conn host;
+ }
+ if { $state == "pass" } {
+ if [gdb_target_monitor $arg] { return -1; }
+ gdb_test "list main" ".*" ""
+ verbose "Loaded $arg into $GDB\n";
+ return 0;
+ }
+ } else {
+
+ if [gdb_target_monitor $arg] { return -1 }
+
+ if [is_remote host] {
+ # FIXME: Multiple downloads. bleah.
+ set farg [remote_download host $arg];
+ } else {
+ set farg $arg;
+ }
+
+ if { $arg != "" && [target_info exists gdb_sect_offset] } {
+ set textoff [target_info gdb_sect_offset];
+ send_gdb "sect .text $textoff\n";
+ gdb_expect 30 {
+ -re "(0x\[0-9a-z]+) - 0x\[0-9a-z\]+ is \\.data" {
+ set dataoff $expect_out(1,string);
+ exp_continue;
+ }
+ -re "(0x\[0-9a-z\]+) - 0x\[0-9a-z\]+ is \\.bss" {
+ set bssoff $expect_out(1,string);
+ exp_continue;
+ }
+ -re "$gdb_prompt" { }
+ }
+ set dataoff [format 0x%x [expr $dataoff + $textoff]];
+ set bssoff [format 0x%x [expr $bssoff + $textoff]];
+ send_gdb "sect .data $dataoff\n";
+ gdb_expect 30 {
+ -re "$gdb_prompt" { }
+ }
+ send_gdb "sect .bss $bssoff\n";
+ gdb_expect 30 {
+ -re "$gdb_prompt" { }
+ }
+ }
+
+ verbose "Loading $farg"
+ if [target_info exists gdb_load_offset] {
+ set command "load $farg [target_info gdb_load_offset]\n";
+ } else {
+ set command "load $farg\n";
+ }
+ send_gdb $command;
+ gdb_expect 1600 {
+ -re "\[Ff\]ailed.*$gdb_prompt $" {
+ verbose "load failed";
+ }
+ -re "Timeout reading from remote.*$gdb_prompt" {
+ }
+ -re "$gdb_prompt $" {
+ verbose "Loaded $farg into $GDB\n"
+ return 0;
+ }
+ timeout {
+ if { $verbose > 1 } {
+ perror "Timed out trying to load $farg."
+ }
+ }
+ }
+ }
+
+ # Make sure we don't have an open connection to the target.
+ gdb_target_exec;
+
+ if { $j == 1 } {
+ if { ![reboot_target] } {
+ break;
+ }
+ }
+ }
+ perror "Couldn't load file into GDB.";
+ return -1;
+}
diff --git a/gdb/testsuite/config/mt-a29k-udi b/gdb/testsuite/config/mt-a29k-udi
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/gdb/testsuite/config/mt-a29k-udi
diff --git a/gdb/testsuite/config/mt-i386-aout b/gdb/testsuite/config/mt-i386-aout
new file mode 100644
index 00000000000..19b1cabe5e7
--- /dev/null
+++ b/gdb/testsuite/config/mt-i386-aout
@@ -0,0 +1,59 @@
+# compilers and assemblers
+CC = i386-aout-gcc
+CFLAGS = -g -D${target_os}
+C++ = ${CC}
+C++FLAGS = ${CFLAGS}
+CXX = ${CC}
+CXXFLAGS = ${CFLAGS}
+AS = i386-aout-as
+ASFLAGS =
+FC =
+FCFLAGS =
+LD = ld
+LDFLAGS =
+LIBS =
+
+# binutils
+
+RANLIB = i386-aout-ranlib
+RANLIBFLAGS =
+
+NM = i386-aout-nm
+NMFLAGS =
+
+SIZE = i386-aout-size
+SIZEFLAGS =
+
+STRIP = i386-aout-strip
+STRIPFLAGS =
+
+OBJDUMP = i386-aout-objdump
+OBJDUMPFLAGS =
+
+DEMANGLE = i386-aout-demangle
+DEMANGLEFLAGS =
+
+COPY = i386-aout-copy
+COPYFLAGS =
+
+# other utils
+LEX = flex
+LEXFLAGS =
+
+YACC = byacc
+YACCFLAGS =
+
+AR = i386-aout-ar
+ARFLAGS =
+
+CPP = ${CC} -E
+CPPFLAGS =
+
+GDB = i386-aout-gdb
+GDBFLAGS = -nx
+
+DIFF = diff
+DIFFFLAGS =
+
+RUNTEST=i386-aout-runtest
+RUNTESTFLAGS=
diff --git a/gdb/testsuite/config/mt-i960-nindy b/gdb/testsuite/config/mt-i960-nindy
new file mode 100644
index 00000000000..9786c51b3c3
--- /dev/null
+++ b/gdb/testsuite/config/mt-i960-nindy
@@ -0,0 +1 @@
+LDFLAGS_FOR_TARGET = -nostartfiles
diff --git a/gdb/testsuite/config/mt-lynx b/gdb/testsuite/config/mt-lynx
new file mode 100644
index 00000000000..1c153af7f82
--- /dev/null
+++ b/gdb/testsuite/config/mt-lynx
@@ -0,0 +1,4 @@
+CFLAGS_FOR_TARGET =
+STEP_EXECUTABLE = step
+THREADFLAGS = -mposix -mthreads
+#LDFLAGS= -L/usr/cygnus/progressive-95q1/H-sparc-sun-sunos4.1.3/i386-lynx/lib/thread
diff --git a/gdb/testsuite/config/mt-m68k b/gdb/testsuite/config/mt-m68k
new file mode 100644
index 00000000000..493d702da31
--- /dev/null
+++ b/gdb/testsuite/config/mt-m68k
@@ -0,0 +1 @@
+CFLAGS_FOR_TARGET = -Tidp.ld -nostartfiles
diff --git a/gdb/testsuite/config/mt-mips-ecoff b/gdb/testsuite/config/mt-mips-ecoff
new file mode 100644
index 00000000000..90dd031785e
--- /dev/null
+++ b/gdb/testsuite/config/mt-mips-ecoff
@@ -0,0 +1,2 @@
+CFLAGS = -I/s1/cygnus/dejagnu/mips-idt-ecoff/include -g
+LDFLAGS = -nostartfiles /s1/cygnus/dejagnu/mips-idt-ecoff/crt0.o -L/s1/cygnus/dejagnu/mips-idt-ecoff -g
diff --git a/gdb/testsuite/config/mt-netware b/gdb/testsuite/config/mt-netware
new file mode 100644
index 00000000000..10d1ce4935c
--- /dev/null
+++ b/gdb/testsuite/config/mt-netware
@@ -0,0 +1 @@
+LDFLAGS = -r
diff --git a/gdb/testsuite/config/mt-slite b/gdb/testsuite/config/mt-slite
new file mode 100644
index 00000000000..74e75a25c5c
--- /dev/null
+++ b/gdb/testsuite/config/mt-slite
@@ -0,0 +1,8 @@
+LIBS = -lc -lg -lgcc
+CFLAGS = -g -Dusestubs
+LDFLAGS = ` \
+ if [ -f $${rootme}/../../newlib/Makefile ]; then \
+ echo -L$${rootsrc}/../../libgloss/ex93x -L$${rootme}/../../libgloss/ex93x -Tex93x.ld -nostartfiles -nostdlib -N; \
+ else \
+ echo -Tex93x.ld -nostartfiles -nostdlib -N; \
+ fi`
diff --git a/gdb/testsuite/config/mt-sparc-aout b/gdb/testsuite/config/mt-sparc-aout
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/gdb/testsuite/config/mt-sparc-aout
diff --git a/gdb/testsuite/config/mt-unix b/gdb/testsuite/config/mt-unix
new file mode 100644
index 00000000000..d6e2c786f84
--- /dev/null
+++ b/gdb/testsuite/config/mt-unix
@@ -0,0 +1 @@
+CFLAGS_FOR_TARGET = -g
diff --git a/gdb/testsuite/config/mt-vxworks b/gdb/testsuite/config/mt-vxworks
new file mode 100644
index 00000000000..d18bcb0bc32
--- /dev/null
+++ b/gdb/testsuite/config/mt-vxworks
@@ -0,0 +1,2 @@
+CFLAGS = -g -Dvxworks
+LDFLAGS = -Xlinker -Ur
diff --git a/gdb/testsuite/config/netware.exp b/gdb/testsuite/config/netware.exp
new file mode 100644
index 00000000000..2538ccf49b6
--- /dev/null
+++ b/gdb/testsuite/config/netware.exp
@@ -0,0 +1,218 @@
+# Copyright (C) 1988, 1990, 1991, 1992, 1994, 1997 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file was written by J.T. Conklin. (jtc@cygnus.com)
+
+load_lib gdb.exp
+load_lib remote.exp
+
+global shell_id
+
+global LD
+if ![info exists LD] then {
+ set LD [findfile "$base_dir/../../ld/ld.new"]
+}
+
+global NLMCONV
+if ![info exists NLMCONV] then {
+ set NLMCONV [findfile "$base_dir/../../binutils/nlmconv"]
+}
+
+#
+# gdb_version -- extract and print the version number of gcc
+#
+proc gdb_version {} {
+ default_gdb_version
+}
+
+#
+# gdb_unload -- unload a file if one is loaded
+#
+
+#
+# gdb_load -- load a file into the debugger.
+# return a -1 if anything goes wrong.
+#
+proc gdb_load { arg } {
+ global gdb_prompt
+ global LD
+ global NLMCONV
+ global errorCode
+ global shell_id
+
+ # FIXME: this is wrong.
+ set targetname [target_info name];
+
+ set obj [file tail $arg]
+ set nlm "$obj.nlm"
+ set lnk "$obj.lnk"
+
+ # build *.lnk file
+ set fd [open $lnk w]
+ puts $fd "description \"[file tail $nlm]\""
+ puts $fd "screenname \"System Console\""
+ puts $fd "module clib.nlm"
+ puts $fd "module mathlib.nlm"
+ puts $fd "stack 32768"
+# puts $fd "stack 64512"
+ puts $fd "debug"
+ # FIXME: don't hardcode location of prelude.o
+ puts $fd "input /s1/cygnus/dejagnu/i386-netware/lib/prelude.o"
+ puts $fd "input $arg"
+ puts $fd "output $nlm"
+ close $fd
+
+ # run nlmconv
+ verbose "Executing: $NLMCONV -l$LD -T$lnk" 1
+ catch "exec $NLMCONV -l$LD -T$lnk" output
+ if ![string match "" $output] then {
+ verbose $output 1
+ }
+ if ![string match "NONE" $errorCode] {
+ warning "Can't link $arg"
+
+ return -1
+ }
+ catch "exec rm -f $lnk"
+
+ # download
+ verbose "Downloading $nlm" 1
+ catch "exec cp $nlm /.NetWare/$targetname.nws/sys.nwv/tmp/x.nlm" output
+ if ![string match "" $output] then {
+ verbose $output 1
+ return -1
+ }
+
+ gdb_file_cmd $nlm
+}
+
+proc gdb_run_cmd { } {
+ global shell_id
+ global gdb_prompt
+ global timeout
+
+ set connhost [target_info name];
+ if [board_info $connhost exists serial] {
+ set serialport [board_info $connhost serial];
+ } else {
+ set serialport [board_info $connhost netport];
+ }
+
+ if [board_info $connhost exists baud] {
+ set baud [board_info $connhost baud];
+ } else {
+ set baud 9600;
+ }
+ # FIXME: This is wrong.
+ send "kill\n"
+ gdb_expect {
+ -re ".*Kill the program being debugged.*y or n. $" {
+ send "y\n"
+ exp_continue
+ }
+ -re ".*$gdb_prompt $" {}
+ }
+
+ verbose "Starting GDB stub on [target_info name]" 1
+ send -i $shell_id "load nlmstub BAUD=$baud x.nlm\r\n"
+
+ send "set remotebaud $baud\n"
+ gdb_expect {
+ -re "$gdb_prompt" {}
+ timeout {
+ perror "Couldn't set remote baud rate"
+ return
+ }
+ }
+
+ set otimeout $timeout
+ set timeout 60
+ verbose "Timeout is now $timeout seconds" 2
+ send "target remote $serialport\n"
+ gdb_expect {
+ -re "Couldn't establish connection to remote target" {
+ send "target remote $serialport\n"
+ exp_continue
+ }
+ -re "$gdb_prompt" {}
+ timeout {
+ set timeout $otimeout
+ verbose "Timeout restored to $timeout seconds" 2
+ perror "Couldn't set remote target"
+ return
+ }
+ }
+ set timeout $otimeout
+ verbose "Timeout restored to $timeout seconds" 2
+
+ send "continue\n"
+ gdb_expect {
+ "Continuing.$" {}
+ }
+
+ return
+}
+
+
+
+#
+# start the remote shell
+#
+
+set shell_prompt "Password:"
+set shell_id [remote_open target]
+
+if $shell_id<0 then {
+ warning "Couldn't connect to target"
+ return -1
+}
+
+if [string match "" $passwd] then {
+ stty -echo
+ send_user "Password: "
+ expect_user -re "(.*)\n"
+ send_user "\n"
+ set passwd "$expect_out(1,string)"
+ stty echo
+}
+
+send -i $shell_id "$passwd\n"
+gdb_expect {
+ -i $shell_id ":" {
+ verbose "Got termtype prompt" 0
+ }
+
+ -i $shell_id timeout {
+ warning "Connection timed out"
+ return -1
+ }
+}
+
+
+# FIXME: this is wrong.
+set shell_prompt "[string toupper [target_info name]]:"
+send -i $shell_id "1\n"
+
+gdb_expect {
+ -i $shell_id -re "$shell_prompt" {}
+ -i $shell_id timeout {
+ warning "Connection timed out"
+ return -1
+ }
+}
diff --git a/gdb/testsuite/config/nind.exp b/gdb/testsuite/config/nind.exp
new file mode 100644
index 00000000000..d8aecdbc60a
--- /dev/null
+++ b/gdb/testsuite/config/nind.exp
@@ -0,0 +1,49 @@
+# Test Framework Driver
+# Copyright (C) 1988, 1990, 1991, 1992, 1997 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# DejaGnu@cygnus.com
+
+# This file was written by Rob Savoye. (rob@cygnus.com)
+
+load_lib gdb.exp
+
+#
+# gdb_load -- load a file into the debugger.
+#
+proc gdb_load { arg } {
+ global verbose
+ global loadpath
+ global loadfile
+ global gdb_prompt
+ global GDB
+ set loadfile [file tail $arg]
+ set loadpath [file dirname $arg]
+ send_user "Not implememted yet\n" ; return -1
+}
+
+#
+# gdb_start -- start GDB running
+#
+proc gdb_start { } {
+ global GDB
+ global GDBFLAGS
+ global spawn_id
+ global gdb_prompt
+ global verbose
+ send_user "Not implememted yet\n" ; return -1
+}
diff --git a/gdb/testsuite/config/proelf.exp b/gdb/testsuite/config/proelf.exp
new file mode 100644
index 00000000000..e6ade13e5af
--- /dev/null
+++ b/gdb/testsuite/config/proelf.exp
@@ -0,0 +1,20 @@
+# Copyright (C) 1997 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+load_lib ../config/monitor.exp
diff --git a/gdb/testsuite/config/rom68k.exp b/gdb/testsuite/config/rom68k.exp
new file mode 100644
index 00000000000..e6ade13e5af
--- /dev/null
+++ b/gdb/testsuite/config/rom68k.exp
@@ -0,0 +1,20 @@
+# Copyright (C) 1997 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+load_lib ../config/monitor.exp
diff --git a/gdb/testsuite/config/sh.exp b/gdb/testsuite/config/sh.exp
new file mode 100644
index 00000000000..e6ade13e5af
--- /dev/null
+++ b/gdb/testsuite/config/sh.exp
@@ -0,0 +1,20 @@
+# Copyright (C) 1997 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+load_lib ../config/monitor.exp
diff --git a/gdb/testsuite/config/sim.exp b/gdb/testsuite/config/sim.exp
new file mode 100644
index 00000000000..5d8a93d5311
--- /dev/null
+++ b/gdb/testsuite/config/sim.exp
@@ -0,0 +1,85 @@
+# Test Framework Driver for GDB driving a builtin simulator
+# Copyright 1994, 1997, 1998 Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+load_lib gdb.exp
+
+#
+# gdb_target_sim
+# Set gdb to target the simulator
+#
+proc gdb_target_sim { } {
+ global gdb_prompt
+ global exit_status
+
+ set target_sim_options "[board_info target gdb,target_sim_options]";
+
+ send_gdb "target sim $target_sim_options\n"
+ set timeout 60
+ verbose "Timeout is now $timeout seconds" 2
+ gdb_expect {
+ -re "Connected to the simulator.*$gdb_prompt $" {
+ verbose "Set target to sim"
+ }
+ timeout {
+ perror "Couldn't set target for simulator."
+ cleanup
+ exit $exit_status
+ }
+ }
+ set timeout 10
+ verbose "Timeout is now $timeout seconds" 2
+}
+
+#
+# gdb_load -- load a file into the debugger.
+# return a -1 if anything goes wrong.
+#
+proc gdb_load { arg } {
+ global verbose
+ global loadpath
+ global loadfile
+ global GDB
+ global gdb_prompt
+
+ if [gdb_file_cmd $arg] then { return -1 }
+
+ gdb_target_sim
+
+ send_gdb "load\n"
+ set timeout 2400
+ verbose "Timeout is now $timeout seconds" 2
+ gdb_expect {
+ -re ".*$gdb_prompt $" {
+ if $verbose>1 then {
+ send_user "Loaded $arg into $GDB\n"
+ }
+ set timeout 30
+ verbose "Timeout is now $timeout seconds" 2
+ return 1
+ }
+ -re "$gdb_prompt $" {
+ if $verbose>1 then {
+ perror "GDB couldn't load."
+ }
+ }
+ timeout {
+ if $verbose>1 then {
+ perror "Timed out trying to load $arg."
+ }
+ }
+ }
+}
diff --git a/gdb/testsuite/config/slite.exp b/gdb/testsuite/config/slite.exp
new file mode 100644
index 00000000000..c4cb1399150
--- /dev/null
+++ b/gdb/testsuite/config/slite.exp
@@ -0,0 +1,183 @@
+# Copyright (C) 1993, 1997, 1998 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# DejaGnu@cygnus.com
+
+# This file was written by Ian Lance Taylor <ian@cygnus.com>.
+
+# GDB support routines for a board using the MIPS remote debugging
+# protocol. These are actually pretty generic.
+
+# DejaGnu currently assumes that debugging is being done over the main
+# console port. It would probably be more convenient for people using
+# IDT boards to permit the debugging port and the connected port to be
+# different, since an IDT board has two ports. This would require
+# extending some of the tests in a fashion similar to that done for
+# VxWorks, because the test output would appear on the other port,
+# rather than being displayed by gdb.
+
+load_lib remote.exp
+load_lib gdb.exp
+set gdb_prompt "\\(gdb\\)"
+
+#
+# gdb_load -- load a file into the GDB.
+# Returns a 0 if there was an error,
+# 1 if it load successfully.
+#
+proc gdb_load { arg } {
+ global verbose
+ global loadpath
+ global loadfile
+ global gdb_prompt
+ global GDB
+ global expect_out
+
+ set loadfile [file tail $arg]
+ set loadpath [file dirname $arg]
+
+ gdb_file_cmd $arg
+
+ if [target_info exists gdb_protocol] {
+ set protocol [target_info gdb_protocol];
+ } else {
+ set protocol "sparclite"
+ }
+
+ if [target_info exists serial] {
+ set targetname [target_info serial];
+ set command "target $protocol [target_info serial]\n";
+ } else {
+ if ![target_info exists netport] {
+ perror "Need either netport or gdb_serial entry for [target_info name].";
+ return -1;
+ }
+ set targetname [target_info netport];
+ set command "target $protocol udp [target_info netport]\n";
+ }
+ set timeout 60
+ verbose "Timeout is now $timeout seconds" 2
+ set try_count 0;
+ send_gdb $command;
+ gdb_expect {
+ -re "Unknown response.*resetting the board.|remote timeout" {
+ incr try_count;
+ if { $try_count > 3 } {
+ set try_count 0;
+ reboot_target;
+ sleep 5;
+ }
+ sleep 1;
+ send_gdb $command;
+ exp_continue;
+ }
+ -re "Remote target.*$gdb_prompt $" { }
+ -re ".*SPARClite appears to be alive.*$gdb_prompt $" {
+ if $verbose>1 then {
+ send_user "Set target to $targetname\n"
+ }
+ }
+ timeout {
+ perror "Couldn't set SLITE target."
+ set timeout 10
+ verbose "Timeout is now $timeout seconds" 2
+ return -1
+ }
+ }
+
+ if [target_info exists gdb_load_offset] {
+ set offset "[target_info gdb_load_offset]";
+ } else {
+ set offset "";
+ }
+ if { 1 } {
+ if [is_remote host] {
+ set arg [remote_download host $arg];
+ if { $arg == "" } {
+ error "download failed"
+ return -1;
+ }
+ }
+ send_gdb "load $arg $offset\n"
+ verbose "Loading $arg into $GDB" 2
+ set timeout 2400
+ verbose "Timeout is now $timeout seconds" 2
+ gdb_expect {
+ -re "Loading.*$gdb_prompt $" {
+ verbose "Loaded $arg into $GDB" 1
+ set timeout 30
+ verbose "Timeout is now $timeout seconds" 2
+ }
+ -re "$gdb_prompt $" {
+ if $verbose>1 then {
+ perror "GDB couldn't load."
+ }
+ }
+ timeout {
+ if $verbose>1 then {
+ perror "Timed out trying to load $arg."
+ }
+ }
+ }
+ }
+ # Some SPARClite boards automagically do a run after the program is
+ # loaded.
+ if [target_info exists need_monitor_run] {
+ set timeout 10
+ verbose "Timeout is now $timeout seconds, doing monitor run" 2
+ send_gdb "monitor run\n";
+ sleep 2;
+ send_gdb "";
+ gdb_expect {
+ -re ".*$gdb_prompt $" { verbose "Run command succeded" }
+ default {
+ perror "error sending monitor run command";
+ }
+ }
+ } else {
+ sleep 2;
+ }
+
+ if [target_info exists gdb_serial] {
+ set serial [target_info gdb_serial];
+ } else {
+ set serial [target_info serial];
+ }
+ send_gdb "target remote $serial\n"
+ set timeout 60
+ verbose "Timeout is now $timeout seconds" 2
+ gdb_expect {
+ -re ".*Kill it?.*y or n.*" {
+ send_gdb "y\n";
+ exp_continue
+ }
+ -re ".*$gdb_prompt $" {
+ verbose "Set remote target to [target_info serial]" 2
+ }
+ timeout {
+ perror "Couldn't set remote target."
+ set timeout 10
+ verbose "Timeout is now $timeout seconds" 2
+ return -1
+ }
+ }
+
+ if [info exists expect_out(buffer)] then {
+ send_log $expect_out(buffer)
+ }
+ return 0
+}
diff --git a/gdb/testsuite/config/sparclet.exp b/gdb/testsuite/config/sparclet.exp
new file mode 100644
index 00000000000..1919aca4f86
--- /dev/null
+++ b/gdb/testsuite/config/sparclet.exp
@@ -0,0 +1,391 @@
+# Copyright (C) 1996, 1997 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# DejaGnu@cygnus.com
+
+# This file was written by Michael Snyder <msnyder@cygnus.com>.
+
+# GDB support routines for a board using the sparclet remote debugging
+# protocol.
+
+load_lib remote.exp
+load_lib gdb.exp
+
+#
+# Sparclet remote run command.
+#
+
+proc gdb_start { } {
+ global gdb_prompt
+
+ if ![file exists loader] {
+ global libdir
+ set loader loader;
+
+ if [target_info exists gdb_stub_offset] {
+ set result [target_compile "${libdir}/stub-loader.c" $loader executable "libs=-Wl,-Ttext,[target_info gdb_stub_offset]"];
+ } else {
+ set result [target_compile "${libdir}/stub-loader.c" $loader executable "ldscript=[target_info gdb_stub_ldscript]"];
+ }
+ }
+
+ verbose -log "$gdb_prompt is gdb prompt"
+
+ set result 0;
+ for { set y 0; } { $y < 4 } { incr y } {
+ if { [default_gdb_start] != 0 } {
+ return -1;
+ }
+
+ if [target_info exists baud] {
+ send_gdb "set remotebaud [target_info baud]\n"
+ gdb_expect {
+ -re "$gdb_prompt" { }
+ default {
+ perror "Error setting baud rate."
+ return -1;
+ }
+ }
+ }
+
+ for {set x 1;} { $x < 4 } {incr x} {
+ set result [gdb_sparclet_startup $result];
+ if { $result > 0 } {
+ return 1;
+ }
+ # mmmmm, magic numbers.
+ if { $result == -42 || $result == -43 } {
+ break;
+ } else {
+ reboot_target;
+ }
+ }
+ if { $x == 4 } {
+ return -1;
+ }
+ gdb_exit;
+ sleep 5;
+ }
+ return -1;
+}
+
+proc gdb_sparclet_startup { arg } {
+ global gdb_prompt
+ global GDB
+ global verbose
+
+ set is_running_stub 0;
+
+ if [target_info exists serial] {
+ set serial [target_info serial];
+ } else {
+ set serial [target_info netport];
+ }
+ set protocol [target_info gdb_protocol];
+ set check_stub 1;
+ if { $arg != -42 } {
+ send_gdb "target $protocol $serial\n";
+ # 10 seconds may be a bit short.
+ gdb_expect 10 {
+ -re "already.*y or n." {
+ gdb_send "y\n";
+ exp_continue;
+ }
+ -re "Remote target.*connected to.*$gdb_prompt" { set check_stub 0; }
+ -re "$gdb_prompt" { }
+ timeout { }
+ }
+ if { $check_stub } {
+ verbose "timed out, checking if stub is already running"
+ send_gdb "\003";
+ sleep 1;
+ send_gdb "\003";
+ gdb_expect 10 {
+ -re "$gdb_prompt" { }
+ default {
+ remote_close host;
+ return -42;
+ }
+ }
+ }
+ }
+ if [target_info exists gdb_serial] {
+ set gdb_serial [target_info gdb_serial];
+ } else {
+ set gdb_serial $serial;
+ }
+ if { $check_stub } {
+ send_gdb "target remote $gdb_serial\n";
+ gdb_expect 15 {
+ -re "Remote debugging.*$gdb_prompt" {
+ verbose "stub is already running"
+ set is_running_stub 1;
+ }
+ default {
+ warning "board isn't responding";
+ remote_close host;
+ remote_reboot target;
+ return -43;
+ }
+ }
+ }
+
+ if { $is_running_stub == 0 } {
+ global srcdir
+
+ if [is_remote host] {
+ set loader [remote_download host "loader"];
+ } else {
+ set loader "loader";
+ }
+ send_gdb "file $loader\n";
+ gdb_expect {
+ -re "A program is being debug.*Kill it.*y or n. $" {
+ send_gdb "y\n"
+ exp_continue
+ }
+ -re "Load new symbol table.*y or n. $" {
+ send_gdb "y\n"
+ exp_continue
+ }
+ -re "Reading symbols from.*done..*$gdb_prompt $" {}
+ -re "$gdb_prompt $" { perror "GDB couldn't find loader" }
+ timeout {
+ perror "(timeout) read symbol file" ;
+ return -1
+ }
+ }
+
+ send_gdb "target $protocol $serial\n";
+ gdb_expect {
+ -re "Remote target.*connected to.*$gdb_prompt" { }
+ default {
+ perror "Error reconnecting to board.";
+ return -1;
+ }
+ }
+
+ send_gdb "load $loader [target_info gdb_stub_offset]\n"
+ verbose "Loading $loader into $GDB" 2
+ set no_run_command 0;
+ gdb_expect 1200 {
+ -re "Loading.*$gdb_prompt $" {
+ verbose "Loaded $loader into $GDB" 1
+ }
+ -re "Transfer rate:.*Switching to remote protocol.*Remote debugging" {
+ set no_run_command 1;
+ }
+ -re "$gdb_prompt $" {
+ if $verbose>1 then {
+ perror "GDB couldn't load."
+ }
+ }
+ timeout {
+ if $verbose>1 then {
+ perror "Timed out trying to load $arg."
+ }
+ }
+ }
+
+ if !$no_run_command {
+ send_gdb "run\n";
+ gdb_expect 60 {
+ -re "A program is being debug.*Kill it.*y or n. $" {
+ send_gdb "y\n"
+ exp_continue
+ }
+ -re "The program being debugged .*y or n. $" {
+ send_gdb "y\n"
+ exp_continue
+ }
+ -re "Starting program:.*loader.*$" {
+ verbose "Starting loader succeeded"
+ }
+ timeout {
+ perror "(timeout) starting the loader" ;
+ return -1
+ }
+ default {
+ perror "error starting the loader";
+ }
+ }
+ }
+ sleep 2;
+ send_gdb ""
+ sleep 1;
+ send_gdb ""
+ verbose "Sent ^C^C"
+ gdb_expect 10 {
+ -re "Give up .and stop debugging it.*$" {
+ send_gdb "y\n"
+ exp_continue
+ }
+ -re "$gdb_prompt $" {
+ verbose "Running loader succeeded"
+ }
+ timeout {
+ warning "(timeout) interrupting the loader" ;
+ remote_close host;
+ }
+ default {
+ warning "error interrupting the loader";
+ }
+ }
+
+ gdb_exit;
+ return [gdb_start];
+ }
+ return 1;
+}
+
+proc gdb_run_cmd { args } {
+ global gdb_prompt
+
+ gdb_breakpoint exit;
+ send_gdb "set \$fp=0\n";
+ gdb_expect {
+ -re "$gdb_prompt" { }
+ }
+ # This is needed for the SparcLite. Whee.
+ if [target_info exists gdb,start_symbol] {
+ set start_comm "jump *[target_info gdb,start_symbol]\n";
+ } else {
+ set start_comm "jump *start\n";
+ }
+ send_gdb "break copyloop\n";
+ gdb_expect 10 {
+ -re "Breakpoint.*$gdb_prompt $" {
+ set start_comm "continue\n";
+ }
+ -re "$gdb_prompt $" { }
+ timeout { warning "break copyloop failed badly"; }
+ }
+ send_gdb $start_comm;
+ gdb_expect 10 {
+ -re "y or n. $" {
+ remote_send host "y\n"
+ exp_continue;
+ }
+ -re "Breakpoint.*in copyloop.*$gdb_prompt $" {
+ remote_send host "jump relocd\n";
+ exp_continue;
+ }
+ -re "Continuing at.*\[\r\n\]" { }
+ default {
+ return -1;
+ }
+ }
+
+ return "";
+}
+
+
+#
+# gdb_load -- load a file into the GDB.
+# Returns a 0 if there was an error,
+# 1 if it load successfully.
+#
+proc gdb_load { arg } {
+ global verbose
+ global loadpath
+ global loadfile
+ global gdb_prompt
+ global GDB
+ global expect_out
+
+ set loadfile [file tail $arg]
+ set loadpath [file dirname $arg]
+
+ set protocol [target_info gdb_protocol];
+
+ if [is_remote host] {
+ set arg [remote_download host $arg];
+ }
+ send_gdb "file $arg\n"
+ gdb_expect 30 {
+ -re "A program is being debug.*Kill it.*y or n. $" {
+ send_gdb "y\n"
+ exp_continue
+ }
+ -re "Load new symbol table.*y or n. $" {
+ send_gdb "y\n"
+ exp_continue
+ }
+ -re "Reading symbols from.*done..*$gdb_prompt $" {}
+ -re "$gdb_prompt $" { perror "GDB couldn't read file" }
+ timeout {
+ perror "(timeout) read symbol file" ;
+ return -1
+ }
+ }
+
+ if [target_info exists gdb_serial] {
+ set gdb_serial [target_info gdb_serial];
+ } else {
+ if [target_info exists serial] {
+ set gdb_serial [target_info serial];
+ } else {
+ set gdb_serial [target_info netport];
+ }
+ }
+ send_gdb "target remote $gdb_serial\n"
+ gdb_expect 30 {
+ -re "Kill it?.*y or n.*" {
+ send_gdb "y\n";
+ exp_continue
+ }
+ -re "$gdb_prompt $" {
+ verbose "Set remote target to $gdb_serial" 2
+ }
+ timeout {
+ perror "Couldn't set remote target."
+ return -1
+ }
+ }
+ if [target_info exists gdb_load_offset] {
+ set offset "[target_info gdb_load_offset]";
+ } else {
+ set offset "";
+ }
+ send_gdb "load $arg $offset\n"
+ verbose "Loading $arg into $GDB" 2
+ gdb_expect 1200 {
+ -re "Loading.*$gdb_prompt $" {
+ verbose "Loaded $arg into $GDB" 1
+ }
+ -re "$gdb_prompt $" {
+ if $verbose>1 then {
+ perror "GDB couldn't load."
+ }
+ }
+ timeout {
+ if $verbose>1 then {
+ perror "Timed out trying to load $arg."
+ }
+ }
+ }
+ send_gdb "list main\n";
+ gdb_expect 60 {
+ -re "$gdb_prompt" { }
+ default {
+ perror "command for list main never completed";
+ return -1;
+ }
+ }
+
+ return 0
+}
diff --git a/gdb/testsuite/config/udi.exp b/gdb/testsuite/config/udi.exp
new file mode 100644
index 00000000000..3a5d778b20b
--- /dev/null
+++ b/gdb/testsuite/config/udi.exp
@@ -0,0 +1,112 @@
+# Test Framework Driver for GDB driving Universal Debug Interface on 29K
+# Copyright 1988, 1990, 1991, 1992, 1993, 1994, 1997 Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# DejaGnu@cygnus.com
+
+# This file was written by Rob Savoye. (rob@cygnus.com)
+
+load_lib gdb.exp
+
+#
+# gdb_target_udi
+# Set gdb to the desired UDI target
+#
+proc gdb_target_udi { } {
+ global gdb_prompt
+ global verbose
+ global exit_status
+
+ set targetname [target_info mondfe,name];
+ # set targets hostname
+ send_gdb "target udi $targetname\n"
+ set timeout 60
+ verbose "Timeout is now $timeout seconds" 2
+ gdb_expect {
+ -re "target udi $targetname\[\r\n\]+" {
+ exp_continue
+ }
+ -re "TIP UDI 1.2 Conformant.*$gdb_prompt $" {
+ verbose "Set target to $targetname"
+ }
+ -re "TIP-ipc WARNING,.*failed:" {
+ warning "$expect_out(buffer)"
+ }
+ -re "TIP-ipc ERROR,.*failed:" {
+ perror "$expect_out(buffer)"
+ }
+ -re "A program is being debugged already. Kill it\? \(y or n\)" {
+ send "y\n"
+ exp_continue
+ }
+ timeout {
+ perror "Couldn't set target for UDI."
+ cleanup
+ exit $exit_status
+ }
+ }
+ set timeout 10
+ verbose "Timeout is now $timeout seconds" 2
+}
+
+#
+# gdb_load -- load a file into the debugger.
+# return a -1 if anything goes wrong.
+#
+
+proc gdb_load { arg } {
+ global verbose
+ global loadpath
+ global loadfile
+ global GDB
+ global gdb_prompt
+
+ if [gdb_file_cmd $arg] {
+ return -1
+ }
+
+ gdb_target_udi
+}
+
+#
+# gdb_start -- start GDB running. This assumes that there the
+# UDICONF enviroment variable is set.
+#
+proc gdb_start { } {
+ global env;
+
+ set env(UDICONF) [target_info mondfe,udi_soc];
+ default_gdb_start
+ verbose "Setting up target, Please wait..."
+ gdb_target_udi
+}
+
+#
+# gdb_exit -- exit gdb
+#
+proc gdb_exit { } {
+ catch default_gdb_exit
+ set in [open [concat "|ls -F"] r]
+ while {[gets $in line]>-1} {
+ if [regexp "=$" $line] then {
+ set line [string trimright $line "="]
+ verbose "Removing the $line named socket"
+ exec rm -f $line
+ }
+ }
+ close $in
+}
diff --git a/gdb/testsuite/config/unix.exp b/gdb/testsuite/config/unix.exp
new file mode 100644
index 00000000000..321ad542d7a
--- /dev/null
+++ b/gdb/testsuite/config/unix.exp
@@ -0,0 +1,29 @@
+# Copyright (C) 1988, 1990, 1991, 1992, 1994, 1997 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file was written by Rob Savoye. (rob@cygnus.com)
+
+# Set a default timeout to be used for the tests under UNIX, rather than
+# accepting whatever default dejagnu gives us (apparently 10 seconds).
+# When running the tests over NFS, under somewhat heavy load, 10 seconds
+# does not seem to be enough. Try starting with 60.
+set timeout 60
+verbose "Timeout is now $timeout seconds" 2
+
+load_lib gdb.exp
diff --git a/gdb/testsuite/config/unknown.exp b/gdb/testsuite/config/unknown.exp
new file mode 100644
index 00000000000..f3cfb79e94a
--- /dev/null
+++ b/gdb/testsuite/config/unknown.exp
@@ -0,0 +1,21 @@
+# Copyright (C) 1997 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+perror "Sorry, there is no support for this target"
+exit 1
diff --git a/gdb/testsuite/config/vr4300.exp b/gdb/testsuite/config/vr4300.exp
new file mode 100644
index 00000000000..e6ade13e5af
--- /dev/null
+++ b/gdb/testsuite/config/vr4300.exp
@@ -0,0 +1,20 @@
+# Copyright (C) 1997 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+load_lib ../config/monitor.exp
diff --git a/gdb/testsuite/config/vr5000.exp b/gdb/testsuite/config/vr5000.exp
new file mode 100644
index 00000000000..e6ade13e5af
--- /dev/null
+++ b/gdb/testsuite/config/vr5000.exp
@@ -0,0 +1,20 @@
+# Copyright (C) 1997 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+load_lib ../config/monitor.exp
diff --git a/gdb/testsuite/config/vx.exp b/gdb/testsuite/config/vx.exp
new file mode 100644
index 00000000000..9c90606f945
--- /dev/null
+++ b/gdb/testsuite/config/vx.exp
@@ -0,0 +1,130 @@
+# Copyright (C) 1988, 1990, 1991, 1992, 1995, 1997 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# DejaGnu@cygnus.com
+
+# This file was written by Rob Savoye. (rob@cygnus.com)
+
+#
+# load support libraries
+#
+load_lib remote.exp
+load_lib gdb.exp
+
+set shell_prompt "->"
+set gdb_prompt "\\(vxgdb\\)"
+
+#
+# gdb_version -- extract and print the version number of gcc
+#
+proc gdb_version {} {
+ default_gdb_version
+}
+
+#
+# gdb_load -- load a file into the debugger.
+# We have to stop and start gdb each time we do this, because when
+# vxgdb loads two files in a row, the symbols in the first file loaded
+# take precedence. Returns -1 on error, else 0.
+#
+proc gdb_load { arg } {
+ set result 0
+
+ if { [remote_ld target $arg] != 0 } {
+ perror "Couldn't load $arg"
+ return -1
+ }
+
+ return [gdb_file_cmd $arg]
+}
+
+#
+# gdb_start -- start gdb running
+#
+proc gdb_start { } {
+ global gdb_prompt
+ global verbose
+ global connectmode
+ global reboot
+
+ # get a connection to the board
+ for { set x 0; } { $x < 3 } { incr x } {
+ set shell_id [remote_open target]
+ if { $shell_id > 0 } {
+ verbose "Spawn id for remote shell is $shell_id"
+
+ set timeout 10
+ verbose "Timeout is now $timeout seconds" 2
+
+ set state [spawn_vxgdb];
+ if { $state == "pass" } {
+ return 0;
+ }
+ if { $state == "fail" } {
+ return -1;
+ }
+ }
+ remote_reboot target;
+ }
+}
+
+proc spawn_vxgdb { } {
+ global gdb_prompt
+
+ default_gdb_start
+
+ # set the default arguments to "main", so that "run" with no
+ # arguments will work correctly.
+ send_gdb "set args main\n"
+ gdb_expect -re ".*$gdb_prompt $" {}
+
+ verbose "Setting up target, Please wait..."
+ # set targets hostname
+ send_gdb "target vxworks [target_info hostname]\n"
+ set timeout 60
+ verbose "Timeout is now $timeout seconds" 2
+ gdb_expect {
+ -re "Done\..*$gdb_prompt $" {
+ verbose "Set target to [target_info hostname]" 1
+ set timeout 10;
+ return "pass";
+ }
+ -re "net_connect: RPC: (Program not registered|.*Timed out).*$" {
+ warning "Couldn't set GDB to target [target_info netport]."
+ }
+ timeout {
+ warning "Couldn't set target for vxworks."
+ }
+ }
+ return "retry";
+}
+
+proc gdb_exit { } {
+ remote_close target;
+ catch default_gdb_exit
+}
+
+#expect_after {
+# "<return>" { send "\n"; perror "Window too small." }
+# -re "\(y or n\) " { send "n\n"; perror "Got interactive prompt." }
+# buffer_full { perror "internal buffer is full." }
+# eof { perror "eof -- pty is hosed." }
+# timeout { perror "timeout." }
+# "virtual memory exhausted" { perror "virtual memory exhausted." }
+# "Undefined command" { perror "send string probably wrong." }
+#}
+
diff --git a/gdb/testsuite/config/vxworks.exp b/gdb/testsuite/config/vxworks.exp
new file mode 100644
index 00000000000..f9c50c8fb3f
--- /dev/null
+++ b/gdb/testsuite/config/vxworks.exp
@@ -0,0 +1,20 @@
+# Copyright (C) 1997 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+load_lib ../config/vx.exp
diff --git a/gdb/testsuite/config/vxworks29k.exp b/gdb/testsuite/config/vxworks29k.exp
new file mode 100644
index 00000000000..3d4c53cf52b
--- /dev/null
+++ b/gdb/testsuite/config/vxworks29k.exp
@@ -0,0 +1,27 @@
+# Copyright (C) 1995, 1997 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# DejaGnu@cygnus.com
+
+# This file was written by Brendan Kehoe (brendan@cygnus.com).
+
+# We need this file here because the targetname for the 29k board
+# is `vxworks29k', not `vxworks'. That way other tools (e.g., gcc)
+# can differentiate between the stuff run on that board and others.
+
+verbose "Loading ${srcdir}/config/vx.exp"
+source ${srcdir}/config/vx.exp
diff --git a/gdb/testsuite/configure b/gdb/testsuite/configure
new file mode 100755
index 00000000000..bf663a29943
--- /dev/null
+++ b/gdb/testsuite/configure
@@ -0,0 +1,1058 @@
+#! /bin/sh
+
+# Guess values for system-dependent variables and create Makefiles.
+# Generated automatically using autoconf version 2.13
+# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc.
+#
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+
+# Defaults:
+ac_help=
+ac_default_prefix=/usr/local
+# Any additions from configure.in:
+ac_help="$ac_help
+ --enable-shared use shared libraries"
+
+# Initialize some variables set by options.
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+build=NONE
+cache_file=./config.cache
+exec_prefix=NONE
+host=NONE
+no_create=
+nonopt=NONE
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+target=NONE
+verbose=
+x_includes=NONE
+x_libraries=NONE
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datadir='${prefix}/share'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+libdir='${exec_prefix}/lib'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+infodir='${prefix}/info'
+mandir='${prefix}/man'
+
+# Initialize some other variables.
+subdirs=
+MFLAGS= MAKEFLAGS=
+SHELL=${CONFIG_SHELL-/bin/sh}
+# Maximum number of lines to put in a shell here document.
+ac_max_here_lines=12
+
+ac_prev=
+for ac_option
+do
+
+ # If the previous option needs an argument, assign it.
+ if test -n "$ac_prev"; then
+ eval "$ac_prev=\$ac_option"
+ ac_prev=
+ continue
+ fi
+
+ case "$ac_option" in
+ -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
+ *) ac_optarg= ;;
+ esac
+
+ # Accept the important Cygnus configure options, so we can diagnose typos.
+
+ case "$ac_option" in
+
+ -bindir | --bindir | --bindi | --bind | --bin | --bi)
+ ac_prev=bindir ;;
+ -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+ bindir="$ac_optarg" ;;
+
+ -build | --build | --buil | --bui | --bu)
+ ac_prev=build ;;
+ -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+ build="$ac_optarg" ;;
+
+ -cache-file | --cache-file | --cache-fil | --cache-fi \
+ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+ ac_prev=cache_file ;;
+ -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+ cache_file="$ac_optarg" ;;
+
+ -datadir | --datadir | --datadi | --datad | --data | --dat | --da)
+ ac_prev=datadir ;;
+ -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \
+ | --da=*)
+ datadir="$ac_optarg" ;;
+
+ -disable-* | --disable-*)
+ ac_feature=`echo $ac_option|sed -e 's/-*disable-//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then
+ { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
+ fi
+ ac_feature=`echo $ac_feature| sed 's/-/_/g'`
+ eval "enable_${ac_feature}=no" ;;
+
+ -enable-* | --enable-*)
+ ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then
+ { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
+ fi
+ ac_feature=`echo $ac_feature| sed 's/-/_/g'`
+ case "$ac_option" in
+ *=*) ;;
+ *) ac_optarg=yes ;;
+ esac
+ eval "enable_${ac_feature}='$ac_optarg'" ;;
+
+ -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+ | --exec | --exe | --ex)
+ ac_prev=exec_prefix ;;
+ -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+ | --exec=* | --exe=* | --ex=*)
+ exec_prefix="$ac_optarg" ;;
+
+ -gas | --gas | --ga | --g)
+ # Obsolete; use --with-gas.
+ with_gas=yes ;;
+
+ -help | --help | --hel | --he)
+ # Omit some internal or obsolete options to make the list less imposing.
+ # This message is too long to be a string in the A/UX 3.1 sh.
+ cat << EOF
+Usage: configure [options] [host]
+Options: [defaults in brackets after descriptions]
+Configuration:
+ --cache-file=FILE cache test results in FILE
+ --help print this message
+ --no-create do not create output files
+ --quiet, --silent do not print \`checking...' messages
+ --version print the version of autoconf that created configure
+Directory and file names:
+ --prefix=PREFIX install architecture-independent files in PREFIX
+ [$ac_default_prefix]
+ --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
+ [same as prefix]
+ --bindir=DIR user executables in DIR [EPREFIX/bin]
+ --sbindir=DIR system admin executables in DIR [EPREFIX/sbin]
+ --libexecdir=DIR program executables in DIR [EPREFIX/libexec]
+ --datadir=DIR read-only architecture-independent data in DIR
+ [PREFIX/share]
+ --sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc]
+ --sharedstatedir=DIR modifiable architecture-independent data in DIR
+ [PREFIX/com]
+ --localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var]
+ --libdir=DIR object code libraries in DIR [EPREFIX/lib]
+ --includedir=DIR C header files in DIR [PREFIX/include]
+ --oldincludedir=DIR C header files for non-gcc in DIR [/usr/include]
+ --infodir=DIR info documentation in DIR [PREFIX/info]
+ --mandir=DIR man documentation in DIR [PREFIX/man]
+ --srcdir=DIR find the sources in DIR [configure dir or ..]
+ --program-prefix=PREFIX prepend PREFIX to installed program names
+ --program-suffix=SUFFIX append SUFFIX to installed program names
+ --program-transform-name=PROGRAM
+ run sed PROGRAM on installed program names
+EOF
+ cat << EOF
+Host type:
+ --build=BUILD configure for building on BUILD [BUILD=HOST]
+ --host=HOST configure for HOST [guessed]
+ --target=TARGET configure for TARGET [TARGET=HOST]
+Features and packages:
+ --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
+ --enable-FEATURE[=ARG] include FEATURE [ARG=yes]
+ --with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
+ --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
+ --x-includes=DIR X include files are in DIR
+ --x-libraries=DIR X library files are in DIR
+EOF
+ if test -n "$ac_help"; then
+ echo "--enable and --with options recognized:$ac_help"
+ fi
+ exit 0 ;;
+
+ -host | --host | --hos | --ho)
+ ac_prev=host ;;
+ -host=* | --host=* | --hos=* | --ho=*)
+ host="$ac_optarg" ;;
+
+ -includedir | --includedir | --includedi | --included | --include \
+ | --includ | --inclu | --incl | --inc)
+ ac_prev=includedir ;;
+ -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+ | --includ=* | --inclu=* | --incl=* | --inc=*)
+ includedir="$ac_optarg" ;;
+
+ -infodir | --infodir | --infodi | --infod | --info | --inf)
+ ac_prev=infodir ;;
+ -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+ infodir="$ac_optarg" ;;
+
+ -libdir | --libdir | --libdi | --libd)
+ ac_prev=libdir ;;
+ -libdir=* | --libdir=* | --libdi=* | --libd=*)
+ libdir="$ac_optarg" ;;
+
+ -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+ | --libexe | --libex | --libe)
+ ac_prev=libexecdir ;;
+ -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+ | --libexe=* | --libex=* | --libe=*)
+ libexecdir="$ac_optarg" ;;
+
+ -localstatedir | --localstatedir | --localstatedi | --localstated \
+ | --localstate | --localstat | --localsta | --localst \
+ | --locals | --local | --loca | --loc | --lo)
+ ac_prev=localstatedir ;;
+ -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+ | --localstate=* | --localstat=* | --localsta=* | --localst=* \
+ | --locals=* | --local=* | --loca=* | --loc=* | --lo=*)
+ localstatedir="$ac_optarg" ;;
+
+ -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+ ac_prev=mandir ;;
+ -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+ mandir="$ac_optarg" ;;
+
+ -nfp | --nfp | --nf)
+ # Obsolete; use --without-fp.
+ with_fp=no ;;
+
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c)
+ no_create=yes ;;
+
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+ no_recursion=yes ;;
+
+ -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+ | --oldin | --oldi | --old | --ol | --o)
+ ac_prev=oldincludedir ;;
+ -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+ oldincludedir="$ac_optarg" ;;
+
+ -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+ ac_prev=prefix ;;
+ -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+ prefix="$ac_optarg" ;;
+
+ -program-prefix | --program-prefix | --program-prefi | --program-pref \
+ | --program-pre | --program-pr | --program-p)
+ ac_prev=program_prefix ;;
+ -program-prefix=* | --program-prefix=* | --program-prefi=* \
+ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+ program_prefix="$ac_optarg" ;;
+
+ -program-suffix | --program-suffix | --program-suffi | --program-suff \
+ | --program-suf | --program-su | --program-s)
+ ac_prev=program_suffix ;;
+ -program-suffix=* | --program-suffix=* | --program-suffi=* \
+ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+ program_suffix="$ac_optarg" ;;
+
+ -program-transform-name | --program-transform-name \
+ | --program-transform-nam | --program-transform-na \
+ | --program-transform-n | --program-transform- \
+ | --program-transform | --program-transfor \
+ | --program-transfo | --program-transf \
+ | --program-trans | --program-tran \
+ | --progr-tra | --program-tr | --program-t)
+ ac_prev=program_transform_name ;;
+ -program-transform-name=* | --program-transform-name=* \
+ | --program-transform-nam=* | --program-transform-na=* \
+ | --program-transform-n=* | --program-transform-=* \
+ | --program-transform=* | --program-transfor=* \
+ | --program-transfo=* | --program-transf=* \
+ | --program-trans=* | --program-tran=* \
+ | --progr-tra=* | --program-tr=* | --program-t=*)
+ program_transform_name="$ac_optarg" ;;
+
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ silent=yes ;;
+
+ -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+ ac_prev=sbindir ;;
+ -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+ | --sbi=* | --sb=*)
+ sbindir="$ac_optarg" ;;
+
+ -sharedstatedir | --sharedstatedir | --sharedstatedi \
+ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+ | --sharedst | --shareds | --shared | --share | --shar \
+ | --sha | --sh)
+ ac_prev=sharedstatedir ;;
+ -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+ | --sha=* | --sh=*)
+ sharedstatedir="$ac_optarg" ;;
+
+ -site | --site | --sit)
+ ac_prev=site ;;
+ -site=* | --site=* | --sit=*)
+ site="$ac_optarg" ;;
+
+ -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+ ac_prev=srcdir ;;
+ -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+ srcdir="$ac_optarg" ;;
+
+ -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+ | --syscon | --sysco | --sysc | --sys | --sy)
+ ac_prev=sysconfdir ;;
+ -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+ sysconfdir="$ac_optarg" ;;
+
+ -target | --target | --targe | --targ | --tar | --ta | --t)
+ ac_prev=target ;;
+ -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+ target="$ac_optarg" ;;
+
+ -v | -verbose | --verbose | --verbos | --verbo | --verb)
+ verbose=yes ;;
+
+ -version | --version | --versio | --versi | --vers)
+ echo "configure generated by autoconf version 2.13"
+ exit 0 ;;
+
+ -with-* | --with-*)
+ ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then
+ { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
+ fi
+ ac_package=`echo $ac_package| sed 's/-/_/g'`
+ case "$ac_option" in
+ *=*) ;;
+ *) ac_optarg=yes ;;
+ esac
+ eval "with_${ac_package}='$ac_optarg'" ;;
+
+ -without-* | --without-*)
+ ac_package=`echo $ac_option|sed -e 's/-*without-//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then
+ { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
+ fi
+ ac_package=`echo $ac_package| sed 's/-/_/g'`
+ eval "with_${ac_package}=no" ;;
+
+ --x)
+ # Obsolete; use --with-x.
+ with_x=yes ;;
+
+ -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+ | --x-incl | --x-inc | --x-in | --x-i)
+ ac_prev=x_includes ;;
+ -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+ x_includes="$ac_optarg" ;;
+
+ -x-libraries | --x-libraries | --x-librarie | --x-librari \
+ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+ ac_prev=x_libraries ;;
+ -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+ x_libraries="$ac_optarg" ;;
+
+ -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; }
+ ;;
+
+ *)
+ if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then
+ echo "configure: warning: $ac_option: invalid host type" 1>&2
+ fi
+ if test "x$nonopt" != xNONE; then
+ { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; }
+ fi
+ nonopt="$ac_option"
+ ;;
+
+ esac
+done
+
+if test -n "$ac_prev"; then
+ { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; }
+fi
+
+trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
+
+# File descriptor usage:
+# 0 standard input
+# 1 file creation
+# 2 errors and warnings
+# 3 some systems may open it to /dev/tty
+# 4 used on the Kubota Titan
+# 6 checking for... messages and results
+# 5 compiler messages saved in config.log
+if test "$silent" = yes; then
+ exec 6>/dev/null
+else
+ exec 6>&1
+fi
+exec 5>./config.log
+
+echo "\
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+" 1>&5
+
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Also quote any args containing shell metacharacters.
+ac_configure_args=
+for ac_arg
+do
+ case "$ac_arg" in
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c) ;;
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;;
+ *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*)
+ ac_configure_args="$ac_configure_args '$ac_arg'" ;;
+ *) ac_configure_args="$ac_configure_args $ac_arg" ;;
+ esac
+done
+
+# NLS nuisances.
+# Only set these to C if already set. These must not be set unconditionally
+# because not all systems understand e.g. LANG=C (notably SCO).
+# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'!
+# Non-C LC_CTYPE values break the ctype check.
+if test "${LANG+set}" = set; then LANG=C; export LANG; fi
+if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi
+if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi
+if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -rf conftest* confdefs.h
+# AIX cpp loses on an empty file, so make sure it contains at least a newline.
+echo > confdefs.h
+
+# A filename unique to this package, relative to the directory that
+# configure is in, which we can look for to find out if srcdir is correct.
+ac_unique_file=gdb.base
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+ ac_srcdir_defaulted=yes
+ # Try the directory containing this script, then its parent.
+ ac_prog=$0
+ ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'`
+ test "x$ac_confdir" = "x$ac_prog" && ac_confdir=.
+ srcdir=$ac_confdir
+ if test ! -r $srcdir/$ac_unique_file; then
+ srcdir=..
+ fi
+else
+ ac_srcdir_defaulted=no
+fi
+if test ! -r $srcdir/$ac_unique_file; then
+ if test "$ac_srcdir_defaulted" = yes; then
+ { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; }
+ else
+ { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; }
+ fi
+fi
+srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'`
+
+# Prefer explicitly selected file to automatically selected ones.
+if test -z "$CONFIG_SITE"; then
+ if test "x$prefix" != xNONE; then
+ CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site"
+ else
+ CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
+ fi
+fi
+for ac_site_file in $CONFIG_SITE; do
+ if test -r "$ac_site_file"; then
+ echo "loading site script $ac_site_file"
+ . "$ac_site_file"
+ fi
+done
+
+if test -r "$cache_file"; then
+ echo "loading cache $cache_file"
+ . $cache_file
+else
+ echo "creating cache $cache_file"
+ > $cache_file
+fi
+
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+ac_exeext=
+ac_objext=o
+if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then
+ # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu.
+ if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then
+ ac_n= ac_c='
+' ac_t=' '
+ else
+ ac_n=-n ac_c= ac_t=
+ fi
+else
+ ac_n= ac_c='\c' ac_t=
+fi
+
+
+
+CC=${CC-cc}
+
+ac_aux_dir=
+for ac_dir in `cd $srcdir;pwd`/../.. $srcdir/`cd $srcdir;pwd`/../..; do
+ if test -f $ac_dir/install-sh; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install-sh -c"
+ break
+ elif test -f $ac_dir/install.sh; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install.sh -c"
+ break
+ fi
+done
+if test -z "$ac_aux_dir"; then
+ { echo "configure: error: can not find install-sh or install.sh in `cd $srcdir;pwd`/../.. $srcdir/`cd $srcdir;pwd`/../.." 1>&2; exit 1; }
+fi
+ac_config_guess=$ac_aux_dir/config.guess
+ac_config_sub=$ac_aux_dir/config.sub
+ac_configure=$ac_aux_dir/configure # This should be Cygnus configure.
+
+
+# Do some error checking and defaulting for the host and target type.
+# The inputs are:
+# configure --host=HOST --target=TARGET --build=BUILD NONOPT
+#
+# The rules are:
+# 1. You are not allowed to specify --host, --target, and nonopt at the
+# same time.
+# 2. Host defaults to nonopt.
+# 3. If nonopt is not specified, then host defaults to the current host,
+# as determined by config.guess.
+# 4. Target and build default to nonopt.
+# 5. If nonopt is not specified, then target and build default to host.
+
+# The aliases save the names the user supplied, while $host etc.
+# will get canonicalized.
+case $host---$target---$nonopt in
+NONE---*---* | *---NONE---* | *---*---NONE) ;;
+*) { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; } ;;
+esac
+
+
+# Make sure we can run config.sub.
+if ${CONFIG_SHELL-/bin/sh} $ac_config_sub sun4 >/dev/null 2>&1; then :
+else { echo "configure: error: can not run $ac_config_sub" 1>&2; exit 1; }
+fi
+
+echo $ac_n "checking host system type""... $ac_c" 1>&6
+echo "configure:577: checking host system type" >&5
+
+host_alias=$host
+case "$host_alias" in
+NONE)
+ case $nonopt in
+ NONE)
+ if host_alias=`${CONFIG_SHELL-/bin/sh} $ac_config_guess`; then :
+ else { echo "configure: error: can not guess host type; you must specify one" 1>&2; exit 1; }
+ fi ;;
+ *) host_alias=$nonopt ;;
+ esac ;;
+esac
+
+host=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $host_alias`
+host_cpu=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+host_vendor=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+host_os=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+echo "$ac_t""$host" 1>&6
+
+echo $ac_n "checking target system type""... $ac_c" 1>&6
+echo "configure:598: checking target system type" >&5
+
+target_alias=$target
+case "$target_alias" in
+NONE)
+ case $nonopt in
+ NONE) target_alias=$host_alias ;;
+ *) target_alias=$nonopt ;;
+ esac ;;
+esac
+
+target=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $target_alias`
+target_cpu=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+target_vendor=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+target_os=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+echo "$ac_t""$target" 1>&6
+
+echo $ac_n "checking build system type""... $ac_c" 1>&6
+echo "configure:616: checking build system type" >&5
+
+build_alias=$build
+case "$build_alias" in
+NONE)
+ case $nonopt in
+ NONE) build_alias=$host_alias ;;
+ *) build_alias=$nonopt ;;
+ esac ;;
+esac
+
+build=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $build_alias`
+build_cpu=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+build_vendor=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+build_os=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+echo "$ac_t""$build" 1>&6
+
+test "$host_alias" != "$target_alias" &&
+ test "$program_prefix$program_suffix$program_transform_name" = \
+ NONENONEs,x,x, &&
+ program_prefix=${target_alias}-
+
+
+# Directories to use in all configurations.
+configdirs="gdb.asm gdb.base gdb.c++ gdb.disasm gdb.chill gdb.threads gdb.trace"
+
+# Directories to use for a configuration which uses stabs.
+stabsdirs="gdb.stabs"
+
+ # this section is for targets that use stabs
+# add stabs tests for appropriate targets
+case "${target}" in
+ powerpc-*-aix*) configdirs="${configdirs} ${stabsdirs}" ;;
+ rs6000-*-aix*) configdirs="${configdirs} ${stabsdirs}" ;;
+ *-*-bsd*) configdirs="${configdirs} ${stabsdirs}" ;;
+ *-*-go32*) configdirs="${configdirs} ${stabsdirs}" ;;
+ *-*-linux*) configdirs="${configdirs} ${stabsdirs}" ;;
+ *-*-lynxos*) configdirs="${configdirs} ${stabsdirs}" ;;
+ *-sun-*) configdirs="${configdirs} ${stabsdirs}" ;;
+ hppa*-*-*) configdirs="${configdirs} ${stabsdirs}" ;;
+ *-*-elf*) configdirs="${configdirs} ${stabsdirs}" ;;
+ *) if test "x${with_stabs}" = x"yes" ; then
+ configdirs="${configdirs} ${stabsdirs}"
+ fi ;;
+esac
+
+# Directory with HP specific tests. They will run only with HP's compilers.
+# These tests will not work on other platforms and compilers.
+
+hpdir="gdb.hp"
+
+case "${target}" in
+ hppa*-*-hpux*) configdirs="${configdirs} ${hpdir}" ;;
+esac
+
+
+# Begin stuff to support --enable-shared
+# Check whether --enable-shared or --disable-shared was given.
+if test "${enable_shared+set}" = set; then
+ enableval="$enable_shared"
+ case "${enableval}" in
+ yes) shared=true ;;
+ no) shared=false ;;
+ *) shared=true ;;
+esac
+fi
+RPATH_ENVVAR=LD_LIBRARY_PATH
+# If we have shared libraries, try to set RPATH_ENVVAR reasonably.
+if test "${shared}" = "true"; then
+ case "${host}" in
+ *-*-hpux*)
+ RPATH_ENVVAR=SHLIB_PATH
+ ;;
+ esac
+fi
+
+# End stuff to support --enable-shared
+
+# configure the subdirectories too
+subdirs="$configdirs"
+
+
+trap '' 1 2 15
+cat > confcache <<\EOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs. It is not useful on other systems.
+# If it contains results you don't want to keep, you may remove or edit it.
+#
+# By default, configure uses ./config.cache as the cache file,
+# creating it if it does not exist already. You can give configure
+# the --cache-file=FILE option to use a different cache file; that is
+# what configure does when it calls configure scripts in
+# subdirectories, so they share the cache.
+# Giving --cache-file=/dev/null disables caching, for debugging configure.
+# config.status only pays attention to the cache file if you give it the
+# --recheck option to rerun configure.
+#
+EOF
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, don't put newlines in cache variables' values.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(set) 2>&1 |
+ case `(ac_space=' '; set | grep ac_space) 2>&1` in
+ *ac_space=\ *)
+ # `set' does not quote correctly, so add quotes (double-quote substitution
+ # turns \\\\ into \\, and sed turns \\ into \).
+ sed -n \
+ -e "s/'/'\\\\''/g" \
+ -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p"
+ ;;
+ *)
+ # `set' quotes correctly as required by POSIX, so do not add quotes.
+ sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p'
+ ;;
+ esac >> confcache
+if cmp -s $cache_file confcache; then
+ :
+else
+ if test -w $cache_file; then
+ echo "updating cache $cache_file"
+ cat confcache > $cache_file
+ else
+ echo "not updating unwritable cache $cache_file"
+ fi
+fi
+rm -f confcache
+
+trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+# Any assignment to VPATH causes Sun make to only execute
+# the first set of double-colon rules, so remove it if not needed.
+# If there is a colon in the path, we need to keep it.
+if test "x$srcdir" = x.; then
+ ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d'
+fi
+
+trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15
+
+# Transform confdefs.h into DEFS.
+# Protect against shell expansion while executing Makefile rules.
+# Protect against Makefile macro expansion.
+cat > conftest.defs <<\EOF
+s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%-D\1=\2%g
+s%[ `~#$^&*(){}\\|;'"<>?]%\\&%g
+s%\[%\\&%g
+s%\]%\\&%g
+s%\$%$$%g
+EOF
+DEFS=`sed -f conftest.defs confdefs.h | tr '\012' ' '`
+rm -f conftest.defs
+
+
+# Without the "./", some shells look in PATH for config.status.
+: ${CONFIG_STATUS=./config.status}
+
+echo creating $CONFIG_STATUS
+rm -f $CONFIG_STATUS
+cat > $CONFIG_STATUS <<EOF
+#! /bin/sh
+# Generated automatically by configure.
+# Run this file to recreate the current configuration.
+# This directory was configured as follows,
+# on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+#
+# $0 $ac_configure_args
+#
+# Compiler output produced by configure, useful for debugging
+# configure, is in ./config.log if it exists.
+
+ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]"
+for ac_option
+do
+ case "\$ac_option" in
+ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+ echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion"
+ exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;;
+ -version | --version | --versio | --versi | --vers | --ver | --ve | --v)
+ echo "$CONFIG_STATUS generated by autoconf version 2.13"
+ exit 0 ;;
+ -help | --help | --hel | --he | --h)
+ echo "\$ac_cs_usage"; exit 0 ;;
+ *) echo "\$ac_cs_usage"; exit 1 ;;
+ esac
+done
+
+ac_given_srcdir=$srcdir
+
+trap 'rm -fr `echo "Makefile" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15
+EOF
+cat >> $CONFIG_STATUS <<EOF
+
+# Protect against being on the right side of a sed subst in config.status.
+sed 's/%@/@@/; s/@%/@@/; s/%g\$/@g/; /@g\$/s/[\\\\&%]/\\\\&/g;
+ s/@@/%@/; s/@@/@%/; s/@g\$/%g/' > conftest.subs <<\\CEOF
+$ac_vpsub
+$extrasub
+s%@SHELL@%$SHELL%g
+s%@CFLAGS@%$CFLAGS%g
+s%@CPPFLAGS@%$CPPFLAGS%g
+s%@CXXFLAGS@%$CXXFLAGS%g
+s%@FFLAGS@%$FFLAGS%g
+s%@DEFS@%$DEFS%g
+s%@LDFLAGS@%$LDFLAGS%g
+s%@LIBS@%$LIBS%g
+s%@exec_prefix@%$exec_prefix%g
+s%@prefix@%$prefix%g
+s%@program_transform_name@%$program_transform_name%g
+s%@bindir@%$bindir%g
+s%@sbindir@%$sbindir%g
+s%@libexecdir@%$libexecdir%g
+s%@datadir@%$datadir%g
+s%@sysconfdir@%$sysconfdir%g
+s%@sharedstatedir@%$sharedstatedir%g
+s%@localstatedir@%$localstatedir%g
+s%@libdir@%$libdir%g
+s%@includedir@%$includedir%g
+s%@oldincludedir@%$oldincludedir%g
+s%@infodir@%$infodir%g
+s%@mandir@%$mandir%g
+s%@CC@%$CC%g
+s%@host@%$host%g
+s%@host_alias@%$host_alias%g
+s%@host_cpu@%$host_cpu%g
+s%@host_vendor@%$host_vendor%g
+s%@host_os@%$host_os%g
+s%@target@%$target%g
+s%@target_alias@%$target_alias%g
+s%@target_cpu@%$target_cpu%g
+s%@target_vendor@%$target_vendor%g
+s%@target_os@%$target_os%g
+s%@build@%$build%g
+s%@build_alias@%$build_alias%g
+s%@build_cpu@%$build_cpu%g
+s%@build_vendor@%$build_vendor%g
+s%@build_os@%$build_os%g
+s%@RPATH_ENVVAR@%$RPATH_ENVVAR%g
+s%@subdirs@%$subdirs%g
+
+CEOF
+EOF
+
+cat >> $CONFIG_STATUS <<\EOF
+
+# Split the substitutions into bite-sized pieces for seds with
+# small command number limits, like on Digital OSF/1 and HP-UX.
+ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script.
+ac_file=1 # Number of current file.
+ac_beg=1 # First line for current file.
+ac_end=$ac_max_sed_cmds # Line after last line for current file.
+ac_more_lines=:
+ac_sed_cmds=""
+while $ac_more_lines; do
+ if test $ac_beg -gt 1; then
+ sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file
+ else
+ sed "${ac_end}q" conftest.subs > conftest.s$ac_file
+ fi
+ if test ! -s conftest.s$ac_file; then
+ ac_more_lines=false
+ rm -f conftest.s$ac_file
+ else
+ if test -z "$ac_sed_cmds"; then
+ ac_sed_cmds="sed -f conftest.s$ac_file"
+ else
+ ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file"
+ fi
+ ac_file=`expr $ac_file + 1`
+ ac_beg=$ac_end
+ ac_end=`expr $ac_end + $ac_max_sed_cmds`
+ fi
+done
+if test -z "$ac_sed_cmds"; then
+ ac_sed_cmds=cat
+fi
+EOF
+
+cat >> $CONFIG_STATUS <<EOF
+
+CONFIG_FILES=\${CONFIG_FILES-"Makefile"}
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then
+ # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+ case "$ac_file" in
+ *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'`
+ ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
+ *) ac_file_in="${ac_file}.in" ;;
+ esac
+
+ # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories.
+
+ # Remove last slash and all that follows it. Not all systems have dirname.
+ ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
+ if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
+ # The file is in a subdirectory.
+ test ! -d "$ac_dir" && mkdir "$ac_dir"
+ ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`"
+ # A "../" for each directory in $ac_dir_suffix.
+ ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'`
+ else
+ ac_dir_suffix= ac_dots=
+ fi
+
+ case "$ac_given_srcdir" in
+ .) srcdir=.
+ if test -z "$ac_dots"; then top_srcdir=.
+ else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;;
+ /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;;
+ *) # Relative path.
+ srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix"
+ top_srcdir="$ac_dots$ac_given_srcdir" ;;
+ esac
+
+
+ echo creating "$ac_file"
+ rm -f "$ac_file"
+ configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure."
+ case "$ac_file" in
+ *Makefile*) ac_comsub="1i\\
+# $configure_input" ;;
+ *) ac_comsub= ;;
+ esac
+
+ ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"`
+ sed -e "$ac_comsub
+s%@configure_input@%$configure_input%g
+s%@srcdir@%$srcdir%g
+s%@top_srcdir@%$top_srcdir%g
+" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file
+fi; done
+rm -f conftest.s*
+
+EOF
+cat >> $CONFIG_STATUS <<EOF
+
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+
+exit 0
+EOF
+chmod +x $CONFIG_STATUS
+rm -fr confdefs* $ac_clean_files
+test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1
+
+if test "$no_recursion" != yes; then
+
+ # Remove --cache-file and --srcdir arguments so they do not pile up.
+ ac_sub_configure_args=
+ ac_prev=
+ for ac_arg in $ac_configure_args; do
+ if test -n "$ac_prev"; then
+ ac_prev=
+ continue
+ fi
+ case "$ac_arg" in
+ -cache-file | --cache-file | --cache-fil | --cache-fi \
+ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+ ac_prev=cache_file ;;
+ -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+ ;;
+ -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+ ac_prev=srcdir ;;
+ -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+ ;;
+ *) ac_sub_configure_args="$ac_sub_configure_args $ac_arg" ;;
+ esac
+ done
+
+ for ac_config_dir in $configdirs; do
+
+ # Do not complain, so a configure script can configure whichever
+ # parts of a large source tree are present.
+ if test ! -d $srcdir/$ac_config_dir; then
+ continue
+ fi
+
+ echo configuring in $ac_config_dir
+
+ case "$srcdir" in
+ .) ;;
+ *)
+ if test -d ./$ac_config_dir || mkdir ./$ac_config_dir; then :;
+ else
+ { echo "configure: error: can not create `pwd`/$ac_config_dir" 1>&2; exit 1; }
+ fi
+ ;;
+ esac
+
+ ac_popdir=`pwd`
+ cd $ac_config_dir
+
+ # A "../" for each directory in /$ac_config_dir.
+ ac_dots=`echo $ac_config_dir|sed -e 's%^\./%%' -e 's%[^/]$%&/%' -e 's%[^/]*/%../%g'`
+
+ case "$srcdir" in
+ .) # No --srcdir option. We are building in place.
+ ac_sub_srcdir=$srcdir ;;
+ /*) # Absolute path.
+ ac_sub_srcdir=$srcdir/$ac_config_dir ;;
+ *) # Relative path.
+ ac_sub_srcdir=$ac_dots$srcdir/$ac_config_dir ;;
+ esac
+
+ # Check for guested configure; otherwise get Cygnus style configure.
+ if test -f $ac_sub_srcdir/configure; then
+ ac_sub_configure=$ac_sub_srcdir/configure
+ elif test -f $ac_sub_srcdir/configure.in; then
+ ac_sub_configure=$ac_configure
+ else
+ echo "configure: warning: no configuration information is in $ac_config_dir" 1>&2
+ ac_sub_configure=
+ fi
+
+ # The recursion is here.
+ if test -n "$ac_sub_configure"; then
+
+ # Make the cache file name correct relative to the subdirectory.
+ case "$cache_file" in
+ /*) ac_sub_cache_file=$cache_file ;;
+ *) # Relative path.
+ ac_sub_cache_file="$ac_dots$cache_file" ;;
+ esac
+
+ echo "running ${CONFIG_SHELL-/bin/sh} $ac_sub_configure $ac_sub_configure_args --cache-file=$ac_sub_cache_file --srcdir=$ac_sub_srcdir"
+ # The eval makes quoting arguments work.
+ if eval ${CONFIG_SHELL-/bin/sh} $ac_sub_configure $ac_sub_configure_args --cache-file=$ac_sub_cache_file --srcdir=$ac_sub_srcdir
+ then :
+ else
+ { echo "configure: error: $ac_sub_configure failed for $ac_config_dir" 1>&2; exit 1; }
+ fi
+ fi
+
+ cd $ac_popdir
+ done
+fi
+
diff --git a/gdb/testsuite/configure.in b/gdb/testsuite/configure.in
new file mode 100644
index 00000000000..83356a9e0d1
--- /dev/null
+++ b/gdb/testsuite/configure.in
@@ -0,0 +1,72 @@
+dnl Process this file file with autoconf to produce a configure script.
+dnl This file is a shell script fragment that supplies the information
+dnl necessary to tailor a template configure script into the configure
+dnl script appropriate for this directory. For more information, check
+dnl any existing configure script.
+
+AC_PREREQ(2.12.1)
+AC_INIT(gdb.base)
+
+CC=${CC-cc}
+AC_SUBST(CC)
+AC_CONFIG_AUX_DIR(`cd $srcdir;pwd`/../..)
+AC_CANONICAL_SYSTEM
+
+# Directories to use in all configurations.
+configdirs="gdb.asm gdb.base gdb.c++ gdb.disasm gdb.chill gdb.threads gdb.trace"
+
+# Directories to use for a configuration which uses stabs.
+stabsdirs="gdb.stabs"
+
+ # this section is for targets that use stabs
+# add stabs tests for appropriate targets
+case "${target}" in
+ powerpc-*-aix*) configdirs="${configdirs} ${stabsdirs}" ;;
+ rs6000-*-aix*) configdirs="${configdirs} ${stabsdirs}" ;;
+ *-*-bsd*) configdirs="${configdirs} ${stabsdirs}" ;;
+ *-*-go32*) configdirs="${configdirs} ${stabsdirs}" ;;
+ *-*-linux*) configdirs="${configdirs} ${stabsdirs}" ;;
+ *-*-lynxos*) configdirs="${configdirs} ${stabsdirs}" ;;
+ *-sun-*) configdirs="${configdirs} ${stabsdirs}" ;;
+ hppa*-*-*) configdirs="${configdirs} ${stabsdirs}" ;;
+ *-*-elf*) configdirs="${configdirs} ${stabsdirs}" ;;
+ *) if test "x${with_stabs}" = x"yes" ; then
+ configdirs="${configdirs} ${stabsdirs}"
+ fi ;;
+esac
+
+# Directory with HP specific tests. They will run only with HP's compilers.
+# These tests will not work on other platforms and compilers.
+
+hpdir="gdb.hp"
+
+case "${target}" in
+ hppa*-*-hpux*) configdirs="${configdirs} ${hpdir}" ;;
+esac
+
+
+# Begin stuff to support --enable-shared
+AC_ARG_ENABLE(shared,
+[ --enable-shared use shared libraries],
+[case "${enableval}" in
+ yes) shared=true ;;
+ no) shared=false ;;
+ *) shared=true ;;
+esac])dnl
+RPATH_ENVVAR=LD_LIBRARY_PATH
+# If we have shared libraries, try to set RPATH_ENVVAR reasonably.
+if test "${shared}" = "true"; then
+ case "${host}" in
+ *-*-hpux*)
+ RPATH_ENVVAR=SHLIB_PATH
+ ;;
+ esac
+fi
+AC_SUBST(RPATH_ENVVAR)
+# End stuff to support --enable-shared
+
+# configure the subdirectories too
+AC_CONFIG_SUBDIRS($configdirs)
+
+dnl AC_SUBST(gdb_target_cpu)
+AC_OUTPUT(Makefile)
diff --git a/gdb/testsuite/gdb.asm/Makefile.in b/gdb/testsuite/gdb.asm/Makefile.in
new file mode 100644
index 00000000000..ce169b5c053
--- /dev/null
+++ b/gdb/testsuite/gdb.asm/Makefile.in
@@ -0,0 +1,33 @@
+VPATH = @srcdir@
+srcdir = @srcdir@
+
+EXECUTABLES =
+
+# uuencoded format to avoid SCCS/RCS problems with binary files.
+CROSS_EXECUTABLES =
+
+all:
+ @echo "Nothing to be done for all..."
+
+info:
+install-info:
+dvi:
+install:
+uninstall: force
+installcheck:
+check:
+
+clean mostlyclean:
+ -rm -f *~ *.o a.out xgdb *.x $(CROSS_EXECUTABLES) *.ci *.tmp
+ -rm -f core core.coremaker coremaker.core corefile $(EXECUTABLES)
+ -rm -f twice-tmp.c
+
+distclean maintainer-clean realclean: clean
+ -rm -f *~ core
+ -rm -f Makefile config.status config.log
+ -rm -f arch.inc
+ -rm -f *-init.exp
+ -rm -fr *.log summary detail *.plog *.sum *.psum site.*
+
+Makefile : $(srcdir)/Makefile.in $(srcdir)/configure.in
+ $(SHELL) ./config.status --recheck
diff --git a/gdb/testsuite/gdb.asm/asm-source.exp b/gdb/testsuite/gdb.asm/asm-source.exp
new file mode 100644
index 00000000000..6c2cab9472c
--- /dev/null
+++ b/gdb/testsuite/gdb.asm/asm-source.exp
@@ -0,0 +1,99 @@
+# Copyright (C) 1998 Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+#
+# This file was written by Kendra.
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+#
+# Test debugging assembly level programs.
+# This file uses asmsrc[12].s for input.
+#
+
+set prms_id 0
+set bug_id 0
+
+if [istarget "d10v-*-*"] then {
+ set asm-arch d10v
+} else {
+ verbose "Skipping assembly source test -- not implemented for this target."
+ return
+}
+
+set testfile "asm-source"
+set binfile ${objdir}/${subdir}/${testfile}
+set src1 ${srcdir}/${subdir}/asmsrc1.s
+set src2 ${srcdir}/${subdir}/asmsrc2.s
+
+set asm-flags "-Wa,-gstabs,-I${srcdir}/${subdir},-I${objdir}/${subdir}"
+
+if {[gdb_compile ${src1} asmsrc1.o object "additional_flags=${asm-flags}"] != ""} then {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+if {[gdb_compile ${src2} asmsrc2.o object "additional_flags=${asm-flags}"] != ""} then {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+if { [gdb_compile "asmsrc1.o asmsrc2.o" ${binfile} executable "ldflags=-nodefaultlibs"] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+remote_exec build "mv asmsrc1.o asmsrc2.o ${objdir}/${subdir}"
+
+
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+#
+# Run to `main' where we begin our tests.
+#
+
+if ![runto_main] then {
+ gdb_suppress_tests
+}
+
+# Execute the `f' command and see if the result includes source info.
+gdb_test "f" "asmsrc1\[.\]s:18.*several_nops" "f at main"
+
+# See if we properly `next' over a macro with several insns.
+gdb_test "n" "22\[ \]*.*foo2" "next over macro"
+
+# See if we can properly `step' into a subroutine call.
+gdb_test "s" "8\[ \]*.*" "step into foo2"
+
+# See if `f' prints the right source file.
+gdb_test "f" ".*asmsrc2\[.\]s:8.*" "f in foo2"
+
+# `next' one insn (or macro) to set up our stackframe (for the following bt).
+gdb_test "n" "12\[ \]*.*foo3" "n in foo2"
+
+# See if `bt' prints the right source files.
+gdb_test "bt" "\#0.*foo2.*asmsrc2\[.\]s:12.*\#1.*main.*asmsrc1\[.\]s:22" "bt in foo2"
+
+# Step into another subroutine which lives back in the first source file.
+gdb_test "s" "" "s 2"
+
+# Next over insns to set up the stack frame.
+gdb_test "n" "" "n 2"
+
+# Now see if `bt' is correct.
+gdb_test "bt" "\#0.*foo3.*asmsrc1\[.\]s:33.*\#1.*foo2.*asmsrc2\[.\]s:12.*\#2.*main.*asmsrc1\[.\]s:22" "bt in foo3"
diff --git a/gdb/testsuite/gdb.asm/asmsrc1.s b/gdb/testsuite/gdb.asm/asmsrc1.s
new file mode 100644
index 00000000000..be1028064a9
--- /dev/null
+++ b/gdb/testsuite/gdb.asm/asmsrc1.s
@@ -0,0 +1,37 @@
+ .include "common.inc"
+ .include "arch.inc"
+
+comment "main routine for assembly source debugging test"
+comment "This particular testcase uses macros in <arch>.inc to achieve"
+comment "machine independence. This file must be compiled with -Darch=foo."
+
+comment "WARNING: asm-source.exp checks for line numbers printed by gdb,"
+comment "therefore be careful about changing this file without also changing"
+comment "asm-source.exp."
+
+ .global main
+main:
+ enter
+
+comment "Call a macro that consists of several lines of assembler code."
+
+ several_nops
+
+comment "Call a subroutine in another file."
+
+ call foo2
+
+comment "All done."
+
+ exit0
+
+comment "A routine for foo2 to call."
+
+ .global foo3
+foo3:
+ enter
+ leave
+
+ .global exit
+exit:
+ exit0
diff --git a/gdb/testsuite/gdb.asm/asmsrc2.s b/gdb/testsuite/gdb.asm/asmsrc2.s
new file mode 100644
index 00000000000..3d48c6c02fb
--- /dev/null
+++ b/gdb/testsuite/gdb.asm/asmsrc2.s
@@ -0,0 +1,16 @@
+ .include "common.inc"
+ .include "arch.inc"
+
+comment "Second file in assembly source debugging testcase."
+
+ .global foo2
+foo2:
+ enter
+
+comment "Call someplace else."
+
+ call foo3
+
+comment "All done, return."
+
+ leave
diff --git a/gdb/testsuite/gdb.asm/common.inc b/gdb/testsuite/gdb.asm/common.inc
new file mode 100644
index 00000000000..7cca3abf04c
--- /dev/null
+++ b/gdb/testsuite/gdb.asm/common.inc
@@ -0,0 +1,18 @@
+ .macro comment text
+ .endm
+
+ comment "Can't rely on assembler comment character so do this."
+
+ .macro include arch file
+ .include "\arch\file"
+ .endm
+
+comment "arch.inc is responsible for defining the following macros:"
+comment "enter - subroutine prologue"
+comment "leave - subroutine epilogue"
+comment "call - call a named subroutine"
+comment "several_nops - execute several (typically 4) nops"
+comment "exit0 - exit (0)"
+
+comment "macros to label a subroutine may also eventually be needed"
+comment "i.e. .global foo\nfoo:\n"
diff --git a/gdb/testsuite/gdb.asm/configure b/gdb/testsuite/gdb.asm/configure
new file mode 100755
index 00000000000..fedef7398fd
--- /dev/null
+++ b/gdb/testsuite/gdb.asm/configure
@@ -0,0 +1,950 @@
+#! /bin/sh
+
+# Guess values for system-dependent variables and create Makefiles.
+# Generated automatically using autoconf version 2.12.1
+# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc.
+#
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+
+# Defaults:
+ac_help=
+ac_default_prefix=/usr/local
+# Any additions from configure.in:
+
+# Initialize some variables set by options.
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+build=NONE
+cache_file=./config.cache
+exec_prefix=NONE
+host=NONE
+no_create=
+nonopt=NONE
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+target=NONE
+verbose=
+x_includes=NONE
+x_libraries=NONE
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datadir='${prefix}/share'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+libdir='${exec_prefix}/lib'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+infodir='${prefix}/info'
+mandir='${prefix}/man'
+
+# Initialize some other variables.
+subdirs=
+MFLAGS= MAKEFLAGS=
+SHELL=${CONFIG_SHELL-/bin/sh}
+# Maximum number of lines to put in a shell here document.
+ac_max_here_lines=12
+
+ac_prev=
+for ac_option
+do
+
+ # If the previous option needs an argument, assign it.
+ if test -n "$ac_prev"; then
+ eval "$ac_prev=\$ac_option"
+ ac_prev=
+ continue
+ fi
+
+ case "$ac_option" in
+ -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
+ *) ac_optarg= ;;
+ esac
+
+ # Accept the important Cygnus configure options, so we can diagnose typos.
+
+ case "$ac_option" in
+
+ -bindir | --bindir | --bindi | --bind | --bin | --bi)
+ ac_prev=bindir ;;
+ -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+ bindir="$ac_optarg" ;;
+
+ -build | --build | --buil | --bui | --bu)
+ ac_prev=build ;;
+ -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+ build="$ac_optarg" ;;
+
+ -cache-file | --cache-file | --cache-fil | --cache-fi \
+ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+ ac_prev=cache_file ;;
+ -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+ cache_file="$ac_optarg" ;;
+
+ -datadir | --datadir | --datadi | --datad | --data | --dat | --da)
+ ac_prev=datadir ;;
+ -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \
+ | --da=*)
+ datadir="$ac_optarg" ;;
+
+ -disable-* | --disable-*)
+ ac_feature=`echo $ac_option|sed -e 's/-*disable-//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then
+ { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
+ fi
+ ac_feature=`echo $ac_feature| sed 's/-/_/g'`
+ eval "enable_${ac_feature}=no" ;;
+
+ -enable-* | --enable-*)
+ ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then
+ { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
+ fi
+ ac_feature=`echo $ac_feature| sed 's/-/_/g'`
+ case "$ac_option" in
+ *=*) ;;
+ *) ac_optarg=yes ;;
+ esac
+ eval "enable_${ac_feature}='$ac_optarg'" ;;
+
+ -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+ | --exec | --exe | --ex)
+ ac_prev=exec_prefix ;;
+ -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+ | --exec=* | --exe=* | --ex=*)
+ exec_prefix="$ac_optarg" ;;
+
+ -gas | --gas | --ga | --g)
+ # Obsolete; use --with-gas.
+ with_gas=yes ;;
+
+ -help | --help | --hel | --he)
+ # Omit some internal or obsolete options to make the list less imposing.
+ # This message is too long to be a string in the A/UX 3.1 sh.
+ cat << EOF
+Usage: configure [options] [host]
+Options: [defaults in brackets after descriptions]
+Configuration:
+ --cache-file=FILE cache test results in FILE
+ --help print this message
+ --no-create do not create output files
+ --quiet, --silent do not print \`checking...' messages
+ --version print the version of autoconf that created configure
+Directory and file names:
+ --prefix=PREFIX install architecture-independent files in PREFIX
+ [$ac_default_prefix]
+ --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
+ [same as prefix]
+ --bindir=DIR user executables in DIR [EPREFIX/bin]
+ --sbindir=DIR system admin executables in DIR [EPREFIX/sbin]
+ --libexecdir=DIR program executables in DIR [EPREFIX/libexec]
+ --datadir=DIR read-only architecture-independent data in DIR
+ [PREFIX/share]
+ --sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc]
+ --sharedstatedir=DIR modifiable architecture-independent data in DIR
+ [PREFIX/com]
+ --localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var]
+ --libdir=DIR object code libraries in DIR [EPREFIX/lib]
+ --includedir=DIR C header files in DIR [PREFIX/include]
+ --oldincludedir=DIR C header files for non-gcc in DIR [/usr/include]
+ --infodir=DIR info documentation in DIR [PREFIX/info]
+ --mandir=DIR man documentation in DIR [PREFIX/man]
+ --srcdir=DIR find the sources in DIR [configure dir or ..]
+ --program-prefix=PREFIX prepend PREFIX to installed program names
+ --program-suffix=SUFFIX append SUFFIX to installed program names
+ --program-transform-name=PROGRAM
+ run sed PROGRAM on installed program names
+EOF
+ cat << EOF
+Host type:
+ --build=BUILD configure for building on BUILD [BUILD=HOST]
+ --host=HOST configure for HOST [guessed]
+ --target=TARGET configure for TARGET [TARGET=HOST]
+Features and packages:
+ --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
+ --enable-FEATURE[=ARG] include FEATURE [ARG=yes]
+ --with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
+ --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
+ --x-includes=DIR X include files are in DIR
+ --x-libraries=DIR X library files are in DIR
+EOF
+ if test -n "$ac_help"; then
+ echo "--enable and --with options recognized:$ac_help"
+ fi
+ exit 0 ;;
+
+ -host | --host | --hos | --ho)
+ ac_prev=host ;;
+ -host=* | --host=* | --hos=* | --ho=*)
+ host="$ac_optarg" ;;
+
+ -includedir | --includedir | --includedi | --included | --include \
+ | --includ | --inclu | --incl | --inc)
+ ac_prev=includedir ;;
+ -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+ | --includ=* | --inclu=* | --incl=* | --inc=*)
+ includedir="$ac_optarg" ;;
+
+ -infodir | --infodir | --infodi | --infod | --info | --inf)
+ ac_prev=infodir ;;
+ -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+ infodir="$ac_optarg" ;;
+
+ -libdir | --libdir | --libdi | --libd)
+ ac_prev=libdir ;;
+ -libdir=* | --libdir=* | --libdi=* | --libd=*)
+ libdir="$ac_optarg" ;;
+
+ -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+ | --libexe | --libex | --libe)
+ ac_prev=libexecdir ;;
+ -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+ | --libexe=* | --libex=* | --libe=*)
+ libexecdir="$ac_optarg" ;;
+
+ -localstatedir | --localstatedir | --localstatedi | --localstated \
+ | --localstate | --localstat | --localsta | --localst \
+ | --locals | --local | --loca | --loc | --lo)
+ ac_prev=localstatedir ;;
+ -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+ | --localstate=* | --localstat=* | --localsta=* | --localst=* \
+ | --locals=* | --local=* | --loca=* | --loc=* | --lo=*)
+ localstatedir="$ac_optarg" ;;
+
+ -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+ ac_prev=mandir ;;
+ -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+ mandir="$ac_optarg" ;;
+
+ -nfp | --nfp | --nf)
+ # Obsolete; use --without-fp.
+ with_fp=no ;;
+
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c)
+ no_create=yes ;;
+
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+ no_recursion=yes ;;
+
+ -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+ | --oldin | --oldi | --old | --ol | --o)
+ ac_prev=oldincludedir ;;
+ -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+ oldincludedir="$ac_optarg" ;;
+
+ -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+ ac_prev=prefix ;;
+ -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+ prefix="$ac_optarg" ;;
+
+ -program-prefix | --program-prefix | --program-prefi | --program-pref \
+ | --program-pre | --program-pr | --program-p)
+ ac_prev=program_prefix ;;
+ -program-prefix=* | --program-prefix=* | --program-prefi=* \
+ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+ program_prefix="$ac_optarg" ;;
+
+ -program-suffix | --program-suffix | --program-suffi | --program-suff \
+ | --program-suf | --program-su | --program-s)
+ ac_prev=program_suffix ;;
+ -program-suffix=* | --program-suffix=* | --program-suffi=* \
+ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+ program_suffix="$ac_optarg" ;;
+
+ -program-transform-name | --program-transform-name \
+ | --program-transform-nam | --program-transform-na \
+ | --program-transform-n | --program-transform- \
+ | --program-transform | --program-transfor \
+ | --program-transfo | --program-transf \
+ | --program-trans | --program-tran \
+ | --progr-tra | --program-tr | --program-t)
+ ac_prev=program_transform_name ;;
+ -program-transform-name=* | --program-transform-name=* \
+ | --program-transform-nam=* | --program-transform-na=* \
+ | --program-transform-n=* | --program-transform-=* \
+ | --program-transform=* | --program-transfor=* \
+ | --program-transfo=* | --program-transf=* \
+ | --program-trans=* | --program-tran=* \
+ | --progr-tra=* | --program-tr=* | --program-t=*)
+ program_transform_name="$ac_optarg" ;;
+
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ silent=yes ;;
+
+ -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+ ac_prev=sbindir ;;
+ -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+ | --sbi=* | --sb=*)
+ sbindir="$ac_optarg" ;;
+
+ -sharedstatedir | --sharedstatedir | --sharedstatedi \
+ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+ | --sharedst | --shareds | --shared | --share | --shar \
+ | --sha | --sh)
+ ac_prev=sharedstatedir ;;
+ -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+ | --sha=* | --sh=*)
+ sharedstatedir="$ac_optarg" ;;
+
+ -site | --site | --sit)
+ ac_prev=site ;;
+ -site=* | --site=* | --sit=*)
+ site="$ac_optarg" ;;
+
+ -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+ ac_prev=srcdir ;;
+ -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+ srcdir="$ac_optarg" ;;
+
+ -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+ | --syscon | --sysco | --sysc | --sys | --sy)
+ ac_prev=sysconfdir ;;
+ -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+ sysconfdir="$ac_optarg" ;;
+
+ -target | --target | --targe | --targ | --tar | --ta | --t)
+ ac_prev=target ;;
+ -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+ target="$ac_optarg" ;;
+
+ -v | -verbose | --verbose | --verbos | --verbo | --verb)
+ verbose=yes ;;
+
+ -version | --version | --versio | --versi | --vers)
+ echo "configure generated by autoconf version 2.12.1"
+ exit 0 ;;
+
+ -with-* | --with-*)
+ ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then
+ { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
+ fi
+ ac_package=`echo $ac_package| sed 's/-/_/g'`
+ case "$ac_option" in
+ *=*) ;;
+ *) ac_optarg=yes ;;
+ esac
+ eval "with_${ac_package}='$ac_optarg'" ;;
+
+ -without-* | --without-*)
+ ac_package=`echo $ac_option|sed -e 's/-*without-//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then
+ { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
+ fi
+ ac_package=`echo $ac_package| sed 's/-/_/g'`
+ eval "with_${ac_package}=no" ;;
+
+ --x)
+ # Obsolete; use --with-x.
+ with_x=yes ;;
+
+ -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+ | --x-incl | --x-inc | --x-in | --x-i)
+ ac_prev=x_includes ;;
+ -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+ x_includes="$ac_optarg" ;;
+
+ -x-libraries | --x-libraries | --x-librarie | --x-librari \
+ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+ ac_prev=x_libraries ;;
+ -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+ x_libraries="$ac_optarg" ;;
+
+ -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; }
+ ;;
+
+ *)
+ if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then
+ echo "configure: warning: $ac_option: invalid host type" 1>&2
+ fi
+ if test "x$nonopt" != xNONE; then
+ { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; }
+ fi
+ nonopt="$ac_option"
+ ;;
+
+ esac
+done
+
+if test -n "$ac_prev"; then
+ { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; }
+fi
+
+trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
+
+# File descriptor usage:
+# 0 standard input
+# 1 file creation
+# 2 errors and warnings
+# 3 some systems may open it to /dev/tty
+# 4 used on the Kubota Titan
+# 6 checking for... messages and results
+# 5 compiler messages saved in config.log
+if test "$silent" = yes; then
+ exec 6>/dev/null
+else
+ exec 6>&1
+fi
+exec 5>./config.log
+
+echo "\
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+" 1>&5
+
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Also quote any args containing shell metacharacters.
+ac_configure_args=
+for ac_arg
+do
+ case "$ac_arg" in
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c) ;;
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;;
+ *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*)
+ ac_configure_args="$ac_configure_args '$ac_arg'" ;;
+ *) ac_configure_args="$ac_configure_args $ac_arg" ;;
+ esac
+done
+
+# NLS nuisances.
+# Only set these to C if already set. These must not be set unconditionally
+# because not all systems understand e.g. LANG=C (notably SCO).
+# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'!
+# Non-C LC_CTYPE values break the ctype check.
+if test "${LANG+set}" = set; then LANG=C; export LANG; fi
+if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi
+if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi
+if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -rf conftest* confdefs.h
+# AIX cpp loses on an empty file, so make sure it contains at least a newline.
+echo > confdefs.h
+
+# A filename unique to this package, relative to the directory that
+# configure is in, which we can look for to find out if srcdir is correct.
+ac_unique_file=asm-source.exp
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+ ac_srcdir_defaulted=yes
+ # Try the directory containing this script, then its parent.
+ ac_prog=$0
+ ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'`
+ test "x$ac_confdir" = "x$ac_prog" && ac_confdir=.
+ srcdir=$ac_confdir
+ if test ! -r $srcdir/$ac_unique_file; then
+ srcdir=..
+ fi
+else
+ ac_srcdir_defaulted=no
+fi
+if test ! -r $srcdir/$ac_unique_file; then
+ if test "$ac_srcdir_defaulted" = yes; then
+ { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; }
+ else
+ { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; }
+ fi
+fi
+srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'`
+
+# Prefer explicitly selected file to automatically selected ones.
+if test -z "$CONFIG_SITE"; then
+ if test "x$prefix" != xNONE; then
+ CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site"
+ else
+ CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
+ fi
+fi
+for ac_site_file in $CONFIG_SITE; do
+ if test -r "$ac_site_file"; then
+ echo "loading site script $ac_site_file"
+ . "$ac_site_file"
+ fi
+done
+
+if test -r "$cache_file"; then
+ echo "loading cache $cache_file"
+ . $cache_file
+else
+ echo "creating cache $cache_file"
+ > $cache_file
+fi
+
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then
+ # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu.
+ if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then
+ ac_n= ac_c='
+' ac_t=' '
+ else
+ ac_n=-n ac_c= ac_t=
+ fi
+else
+ ac_n= ac_c='\c' ac_t=
+fi
+
+
+
+CC=${CC-cc}
+
+ac_aux_dir=
+for ac_dir in `cd $srcdir;pwd`/../../.. $srcdir/`cd $srcdir;pwd`/../../..; do
+ if test -f $ac_dir/install-sh; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install-sh -c"
+ break
+ elif test -f $ac_dir/install.sh; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install.sh -c"
+ break
+ fi
+done
+if test -z "$ac_aux_dir"; then
+ { echo "configure: error: can not find install-sh or install.sh in `cd $srcdir;pwd`/../../.. $srcdir/`cd $srcdir;pwd`/../../.." 1>&2; exit 1; }
+fi
+ac_config_guess=$ac_aux_dir/config.guess
+ac_config_sub=$ac_aux_dir/config.sub
+ac_configure=$ac_aux_dir/configure # This should be Cygnus configure.
+
+
+# Do some error checking and defaulting for the host and target type.
+# The inputs are:
+# configure --host=HOST --target=TARGET --build=BUILD NONOPT
+#
+# The rules are:
+# 1. You are not allowed to specify --host, --target, and nonopt at the
+# same time.
+# 2. Host defaults to nonopt.
+# 3. If nonopt is not specified, then host defaults to the current host,
+# as determined by config.guess.
+# 4. Target and build default to nonopt.
+# 5. If nonopt is not specified, then target and build default to host.
+
+# The aliases save the names the user supplied, while $host etc.
+# will get canonicalized.
+case $host---$target---$nonopt in
+NONE---*---* | *---NONE---* | *---*---NONE) ;;
+*) { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; } ;;
+esac
+
+
+# Make sure we can run config.sub.
+if ${CONFIG_SHELL-/bin/sh} $ac_config_sub sun4 >/dev/null 2>&1; then :
+else { echo "configure: error: can not run $ac_config_sub" 1>&2; exit 1; }
+fi
+
+echo $ac_n "checking host system type""... $ac_c" 1>&6
+echo "configure:573: checking host system type" >&5
+
+host_alias=$host
+case "$host_alias" in
+NONE)
+ case $nonopt in
+ NONE)
+ if host_alias=`${CONFIG_SHELL-/bin/sh} $ac_config_guess`; then :
+ else { echo "configure: error: can not guess host type; you must specify one" 1>&2; exit 1; }
+ fi ;;
+ *) host_alias=$nonopt ;;
+ esac ;;
+esac
+
+host=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $host_alias`
+host_cpu=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+host_vendor=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+host_os=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+echo "$ac_t""$host" 1>&6
+
+echo $ac_n "checking target system type""... $ac_c" 1>&6
+echo "configure:594: checking target system type" >&5
+
+target_alias=$target
+case "$target_alias" in
+NONE)
+ case $nonopt in
+ NONE) target_alias=$host_alias ;;
+ *) target_alias=$nonopt ;;
+ esac ;;
+esac
+
+target=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $target_alias`
+target_cpu=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+target_vendor=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+target_os=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+echo "$ac_t""$target" 1>&6
+
+echo $ac_n "checking build system type""... $ac_c" 1>&6
+echo "configure:612: checking build system type" >&5
+
+build_alias=$build
+case "$build_alias" in
+NONE)
+ case $nonopt in
+ NONE) build_alias=$host_alias ;;
+ *) build_alias=$nonopt ;;
+ esac ;;
+esac
+
+build=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $build_alias`
+build_cpu=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+build_vendor=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+build_os=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+echo "$ac_t""$build" 1>&6
+
+test "$host_alias" != "$target_alias" &&
+ test "$program_prefix$program_suffix$program_transform_name" = \
+ NONENONEs,x,x, &&
+ program_prefix=${target_alias}-
+
+
+archinc=common.inc
+case ${target} in
+d10v-*-*) archinc=d10v.inc ;;
+esac
+
+
+trap '' 1 2 15
+cat > confcache <<\EOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs. It is not useful on other systems.
+# If it contains results you don't want to keep, you may remove or edit it.
+#
+# By default, configure uses ./config.cache as the cache file,
+# creating it if it does not exist already. You can give configure
+# the --cache-file=FILE option to use a different cache file; that is
+# what configure does when it calls configure scripts in
+# subdirectories, so they share the cache.
+# Giving --cache-file=/dev/null disables caching, for debugging configure.
+# config.status only pays attention to the cache file if you give it the
+# --recheck option to rerun configure.
+#
+EOF
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, don't put newlines in cache variables' values.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(set) 2>&1 |
+ case `(ac_space=' '; set) 2>&1 | grep ac_space` in
+ *ac_space=\ *)
+ # `set' does not quote correctly, so add quotes (double-quote substitution
+ # turns \\\\ into \\, and sed turns \\ into \).
+ sed -n \
+ -e "s/'/'\\\\''/g" \
+ -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p"
+ ;;
+ *)
+ # `set' quotes correctly as required by POSIX, so do not add quotes.
+ sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p'
+ ;;
+ esac >> confcache
+if cmp -s $cache_file confcache; then
+ :
+else
+ if test -w $cache_file; then
+ echo "updating cache $cache_file"
+ cat confcache > $cache_file
+ else
+ echo "not updating unwritable cache $cache_file"
+ fi
+fi
+rm -f confcache
+
+trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+# Any assignment to VPATH causes Sun make to only execute
+# the first set of double-colon rules, so remove it if not needed.
+# If there is a colon in the path, we need to keep it.
+if test "x$srcdir" = x.; then
+ ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d'
+fi
+
+trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15
+
+# Transform confdefs.h into DEFS.
+# Protect against shell expansion while executing Makefile rules.
+# Protect against Makefile macro expansion.
+cat > conftest.defs <<\EOF
+s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%-D\1=\2%g
+s%[ `~#$^&*(){}\\|;'"<>?]%\\&%g
+s%\[%\\&%g
+s%\]%\\&%g
+s%\$%$$%g
+EOF
+DEFS=`sed -f conftest.defs confdefs.h | tr '\012' ' '`
+rm -f conftest.defs
+
+
+# Without the "./", some shells look in PATH for config.status.
+: ${CONFIG_STATUS=./config.status}
+
+echo creating $CONFIG_STATUS
+rm -f $CONFIG_STATUS
+cat > $CONFIG_STATUS <<EOF
+#! /bin/sh
+# Generated automatically by configure.
+# Run this file to recreate the current configuration.
+# This directory was configured as follows,
+# on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+#
+# $0 $ac_configure_args
+#
+# Compiler output produced by configure, useful for debugging
+# configure, is in ./config.log if it exists.
+
+ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]"
+for ac_option
+do
+ case "\$ac_option" in
+ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+ echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion"
+ exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;;
+ -version | --version | --versio | --versi | --vers | --ver | --ve | --v)
+ echo "$CONFIG_STATUS generated by autoconf version 2.12.1"
+ exit 0 ;;
+ -help | --help | --hel | --he | --h)
+ echo "\$ac_cs_usage"; exit 0 ;;
+ *) echo "\$ac_cs_usage"; exit 1 ;;
+ esac
+done
+
+ac_given_srcdir=$srcdir
+
+trap 'rm -fr `echo "Makefile" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15
+EOF
+cat >> $CONFIG_STATUS <<EOF
+
+# Protect against being on the right side of a sed subst in config.status.
+sed 's/%@/@@/; s/@%/@@/; s/%g\$/@g/; /@g\$/s/[\\\\&%]/\\\\&/g;
+ s/@@/%@/; s/@@/@%/; s/@g\$/%g/' > conftest.subs <<\\CEOF
+$ac_vpsub
+$extrasub
+s%@SHELL@%$SHELL%g
+s%@CFLAGS@%$CFLAGS%g
+s%@CPPFLAGS@%$CPPFLAGS%g
+s%@CXXFLAGS@%$CXXFLAGS%g
+s%@DEFS@%$DEFS%g
+s%@LDFLAGS@%$LDFLAGS%g
+s%@LIBS@%$LIBS%g
+s%@exec_prefix@%$exec_prefix%g
+s%@prefix@%$prefix%g
+s%@program_transform_name@%$program_transform_name%g
+s%@bindir@%$bindir%g
+s%@sbindir@%$sbindir%g
+s%@libexecdir@%$libexecdir%g
+s%@datadir@%$datadir%g
+s%@sysconfdir@%$sysconfdir%g
+s%@sharedstatedir@%$sharedstatedir%g
+s%@localstatedir@%$localstatedir%g
+s%@libdir@%$libdir%g
+s%@includedir@%$includedir%g
+s%@oldincludedir@%$oldincludedir%g
+s%@infodir@%$infodir%g
+s%@mandir@%$mandir%g
+s%@CC@%$CC%g
+s%@host@%$host%g
+s%@host_alias@%$host_alias%g
+s%@host_cpu@%$host_cpu%g
+s%@host_vendor@%$host_vendor%g
+s%@host_os@%$host_os%g
+s%@target@%$target%g
+s%@target_alias@%$target_alias%g
+s%@target_cpu@%$target_cpu%g
+s%@target_vendor@%$target_vendor%g
+s%@target_os@%$target_os%g
+s%@build@%$build%g
+s%@build_alias@%$build_alias%g
+s%@build_cpu@%$build_cpu%g
+s%@build_vendor@%$build_vendor%g
+s%@build_os@%$build_os%g
+
+CEOF
+EOF
+
+cat >> $CONFIG_STATUS <<\EOF
+
+# Split the substitutions into bite-sized pieces for seds with
+# small command number limits, like on Digital OSF/1 and HP-UX.
+ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script.
+ac_file=1 # Number of current file.
+ac_beg=1 # First line for current file.
+ac_end=$ac_max_sed_cmds # Line after last line for current file.
+ac_more_lines=:
+ac_sed_cmds=""
+while $ac_more_lines; do
+ if test $ac_beg -gt 1; then
+ sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file
+ else
+ sed "${ac_end}q" conftest.subs > conftest.s$ac_file
+ fi
+ if test ! -s conftest.s$ac_file; then
+ ac_more_lines=false
+ rm -f conftest.s$ac_file
+ else
+ if test -z "$ac_sed_cmds"; then
+ ac_sed_cmds="sed -f conftest.s$ac_file"
+ else
+ ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file"
+ fi
+ ac_file=`expr $ac_file + 1`
+ ac_beg=$ac_end
+ ac_end=`expr $ac_end + $ac_max_sed_cmds`
+ fi
+done
+if test -z "$ac_sed_cmds"; then
+ ac_sed_cmds=cat
+fi
+EOF
+
+cat >> $CONFIG_STATUS <<EOF
+
+CONFIG_FILES=\${CONFIG_FILES-"Makefile"}
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then
+ # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+ case "$ac_file" in
+ *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'`
+ ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
+ *) ac_file_in="${ac_file}.in" ;;
+ esac
+
+ # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories.
+
+ # Remove last slash and all that follows it. Not all systems have dirname.
+ ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
+ if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
+ # The file is in a subdirectory.
+ test ! -d "$ac_dir" && mkdir "$ac_dir"
+ ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`"
+ # A "../" for each directory in $ac_dir_suffix.
+ ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'`
+ else
+ ac_dir_suffix= ac_dots=
+ fi
+
+ case "$ac_given_srcdir" in
+ .) srcdir=.
+ if test -z "$ac_dots"; then top_srcdir=.
+ else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;;
+ /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;;
+ *) # Relative path.
+ srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix"
+ top_srcdir="$ac_dots$ac_given_srcdir" ;;
+ esac
+
+
+ echo creating "$ac_file"
+ rm -f "$ac_file"
+ configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure."
+ case "$ac_file" in
+ *Makefile*) ac_comsub="1i\\
+# $configure_input" ;;
+ *) ac_comsub= ;;
+ esac
+
+ ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"`
+ sed -e "$ac_comsub
+s%@configure_input@%$configure_input%g
+s%@srcdir@%$srcdir%g
+s%@top_srcdir@%$top_srcdir%g
+" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file
+fi; done
+rm -f conftest.s*
+
+EOF
+
+cat >> $CONFIG_STATUS <<EOF
+ac_sources="$archinc"
+ac_dests="arch.inc"
+EOF
+
+cat >> $CONFIG_STATUS <<\EOF
+srcdir=$ac_given_srcdir
+while test -n "$ac_sources"; do
+ set $ac_dests; ac_dest=$1; shift; ac_dests=$*
+ set $ac_sources; ac_source=$1; shift; ac_sources=$*
+
+ echo "linking $srcdir/$ac_source to $ac_dest"
+
+ if test ! -r $srcdir/$ac_source; then
+ { echo "configure: error: $srcdir/$ac_source: File not found" 1>&2; exit 1; }
+ fi
+ rm -f $ac_dest
+
+ # Make relative symlinks.
+ # Remove last slash and all that follows it. Not all systems have dirname.
+ ac_dest_dir=`echo $ac_dest|sed 's%/[^/][^/]*$%%'`
+ if test "$ac_dest_dir" != "$ac_dest" && test "$ac_dest_dir" != .; then
+ # The dest file is in a subdirectory.
+ test ! -d "$ac_dest_dir" && mkdir "$ac_dest_dir"
+ ac_dest_dir_suffix="/`echo $ac_dest_dir|sed 's%^\./%%'`"
+ # A "../" for each directory in $ac_dest_dir_suffix.
+ ac_dots=`echo $ac_dest_dir_suffix|sed 's%/[^/]*%../%g'`
+ else
+ ac_dest_dir_suffix= ac_dots=
+ fi
+
+ case "$srcdir" in
+ [/$]*) ac_rel_source="$srcdir/$ac_source" ;;
+ *) ac_rel_source="$ac_dots$srcdir/$ac_source" ;;
+ esac
+
+ # Make a symlink if possible; otherwise try a hard link.
+ if ln -s $ac_rel_source $ac_dest 2>/dev/null ||
+ ln $srcdir/$ac_source $ac_dest; then :
+ else
+ { echo "configure: error: can not link $ac_dest to $srcdir/$ac_source" 1>&2; exit 1; }
+ fi
+done
+EOF
+cat >> $CONFIG_STATUS <<EOF
+
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+
+exit 0
+EOF
+chmod +x $CONFIG_STATUS
+rm -fr confdefs* $ac_clean_files
+test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1
+
diff --git a/gdb/testsuite/gdb.asm/configure.in b/gdb/testsuite/gdb.asm/configure.in
new file mode 100644
index 00000000000..8ff68efbdc5
--- /dev/null
+++ b/gdb/testsuite/gdb.asm/configure.in
@@ -0,0 +1,22 @@
+dnl Process this file file with autoconf to produce a configure script.
+dnl This file is a shell script fragment that supplies the information
+dnl necessary to tailor a template configure script into the configure
+dnl script appropriate for this directory. For more information, check
+dnl any existing configure script.
+
+AC_PREREQ(2.5)
+AC_INIT(asm-source.exp)
+
+CC=${CC-cc}
+AC_SUBST(CC)
+AC_CONFIG_AUX_DIR(`cd $srcdir;pwd`/../../..)
+AC_CANONICAL_SYSTEM
+
+dnl In default case we need to link with some file so use common.inc.
+archinc=common.inc
+case ${target} in
+d10v-*-*) archinc=d10v.inc ;;
+esac
+AC_LINK_FILES($archinc,arch.inc)
+
+AC_OUTPUT(Makefile)
diff --git a/gdb/testsuite/gdb.asm/d10v.inc b/gdb/testsuite/gdb.asm/d10v.inc
new file mode 100644
index 00000000000..e39a49839ec
--- /dev/null
+++ b/gdb/testsuite/gdb.asm/d10v.inc
@@ -0,0 +1,28 @@
+ comment "subroutine prologue"
+ .macro enter
+ st r13,@-sp
+ .endm
+
+ comment "subroutine epilogue"
+ .macro leave
+ ld r13,@sp+
+ jmp r13
+ .endm
+
+ .macro call subr
+ bl \subr
+ .endm
+
+ .macro several_nops
+ nop
+ nop
+ nop
+ nop
+ .endm
+
+ comment "exit (0)"
+ .macro exit0
+ ldi r4, 1
+ ldi r0, 0
+ trap 15
+ .endm
diff --git a/gdb/testsuite/gdb.base/Makefile.in b/gdb/testsuite/gdb.base/Makefile.in
new file mode 100644
index 00000000000..a5d637438bd
--- /dev/null
+++ b/gdb/testsuite/gdb.base/Makefile.in
@@ -0,0 +1,46 @@
+VPATH = @srcdir@
+srcdir = @srcdir@
+
+EXECUTABLES = all-types bitfields break \
+ call-ar-st call-rt-st call-strs callfuncs callfuncs2 commands \
+ compiler condbreak constvars coremaker display \
+ ending-run exprs funcargs int-type interrupt \
+ jump langs \
+ list long_long \
+ mips_pro miscexprs nodebug opaque pointers pointers2 printcmds ptype \
+ recurse reread reread1 restore return run \
+ scope section_command setshow setvar \
+ shmain sigall signals smoke \
+ solib so-impl-ld so-indr-cl \
+ step-test structs structs2 twice-tmp varargs watchpoint whatis
+
+# uuencoded format to avoid SCCS/RCS problems with binary files.
+CROSS_EXECUTABLES = i486-elf i860-elf m68k-elf m68k-aout m68k-aout2 \
+ mips-ecoff sparc-aout sparc-elf
+
+MISCELLANEOUS = coremmap.data shr1.sl shr2.sl solib1.sl solib2.sl
+
+all:
+ @echo "Nothing to be done for all..."
+
+info:
+install-info:
+dvi:
+install:
+uninstall: force
+installcheck:
+check:
+
+clean mostlyclean:
+ -rm -f *~ *.o a.out xgdb *.x $(CROSS_EXECUTABLES) *.ci *.tmp
+ -rm -f core core.coremaker coremaker.core corefile $(EXECUTABLES)
+ -rm -f $(MISCELLANEOUS) twice-tmp.c
+
+distclean maintainer-clean realclean: clean
+ -rm -f *~ core
+ -rm -f Makefile config.status config.log
+ -rm -f *-init.exp
+ -rm -fr *.log summary detail *.plog *.sum *.psum site.*
+
+Makefile : $(srcdir)/Makefile.in $(srcdir)/configure.in
+ $(SHELL) ./config.status --recheck
diff --git a/gdb/testsuite/gdb.base/README b/gdb/testsuite/gdb.base/README
new file mode 100644
index 00000000000..556fc755bf2
--- /dev/null
+++ b/gdb/testsuite/gdb.base/README
@@ -0,0 +1,13 @@
+Information about the various executables found in this test:
+
+ BFD CPU Objfile
+Executable Target Type Type Info about compilation machine
+---------- ------ ---- ------- -------------------------------
+i486-elf elf-little i486 ELF NCR 3000, /usr/ccs/ATT/cc
+i860-elf elf-big i860 ELF Stratus
+m68k-elf elf-big m68k ELF Amiga 3000 UX, /usr/ccs/bin/cc
+m68k-aout a.out-newsos3 m68k a.out Sony NEWS
+m68k-aout2 a.out-sunos-big m68k a.out SunOS 4.1, gcc cygnus-2.0.1
+sparc-aout a.out-sunos-big sparc a.out Sun 4, SunOS 4.1.1, gcc 2.1
+sparc-elf elf-big sparc ELF Sun 4, Solaris 1.0, gcc 2.0.2
+mips-ecoff ecoff-bigmips mips ecoff IRIX 4.0.1
diff --git a/gdb/testsuite/gdb.base/a1-selftest.exp b/gdb/testsuite/gdb.base/a1-selftest.exp
new file mode 100644
index 00000000000..bc3893a0ccc
--- /dev/null
+++ b/gdb/testsuite/gdb.base/a1-selftest.exp
@@ -0,0 +1,426 @@
+# Copyright (C) 1988, 1990, 1991, 1992, 1994, 1997 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file was written by Rob Savoye. (rob@cygnus.com)
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+set prms_id 0
+set bug_id 0
+
+# are we on a target board
+if [is_remote target] {
+ return
+}
+
+if [istarget "m68k*-*-hpux*"] then {
+ # The top-level makefile passes CFLAGS= (no -g) for hp300. This probably
+ # should be fixed (it is only needed for gcc bootstrapping, not gdb),
+ # but until then.....
+ setup_xfail "*-*-*"
+ fail "cannot test self if compiled without debug info"
+ return -1
+}
+
+# Not all of the lines of code near the start of main are executed for
+# every machine. Also, optimization may reorder some of the lines.
+# So all we do is try to step or next over everything until we get
+# to a line that we know is always executed.
+
+proc do_steps_and_nexts {} {
+ global gdb_prompt
+ global srcdir
+
+ gdb_reinitialize_dir $srcdir/..
+
+ for {set count 0} {$count < 20} {incr count} {
+ send_gdb "list\n"
+ gdb_expect {
+ -re ".*symarg = NULL.*$gdb_prompt $" {
+ set description "step over symarg initialization"
+ set command "step"
+ }
+ -re ".*execarg = NULL.*$gdb_prompt $" {
+ set description "step over execarg initialization"
+ set command "step"
+ }
+ -re ".*corearg = NULL.*$gdb_prompt $" {
+ set description "step over corearg initialization"
+ set command "step"
+ }
+ -re ".*cdarg = NULL.*$gdb_prompt $" {
+ set description "step over cdarg initialization"
+ set command "step"
+ }
+ -re ".*ttyarg = NULL.*$gdb_prompt $" {
+ set description "step over ttyarg initialization"
+ set command "step"
+ }
+ -re ".*time_at_startup = get_run_time.*$gdb_prompt $" {
+ set description "next over get_run_time and everything it calls"
+ set command "next"
+ }
+ -re ".*START_PROGRESS.*$gdb_prompt $" {
+ set description "next over START_PROGRESS and everything it calls"
+ set command "next"
+ }
+ -re ".*mac_init.*$gdb_prompt $" {
+ set description "next over mac_init and everything it calls"
+ set command "next"
+ }
+ -re ".*init_malloc.*$gdb_prompt $" {
+ set description "next over init_malloc and everything it calls"
+ set command "next"
+ }
+ -re ".*count . 0x3.*$gdb_prompt $" {
+ set description "next over conditional stack alignment code 1"
+ set command "next"
+ }
+ -re ".*if .i != 0.*$gdb_prompt $" {
+ set description "next over conditional stack alignment code 2"
+ set command "next"
+ }
+ -re ".*alloca .i - 4.*$gdb_prompt $" {
+ set description "next over conditional stack alignment alloca"
+ set command "next"
+ }
+ -re ".*SET_TOP_LEVEL.*$gdb_prompt $" {
+ set description "next over SET_TOP_LEVEL call"
+ set command "next"
+ }
+ -re ".*cmdsize = 1.*$gdb_prompt $" {
+ set description "step over cmdsize initialization"
+ set command "next"
+ }
+ -re ".*cmdarg = .* xmalloc.*$gdb_prompt $" {
+ set description "next over cmdarg initialization via xmalloc"
+ set command "next"
+ }
+ -re ".*ncmd = 0.*$gdb_prompt $" {
+ set description "next over ncmd initialization"
+ set command "next"
+ }
+ -re ".*dirsize = 1.*$gdb_prompt $" {
+ set description "next over dirsize initialization"
+ set command "next"
+ }
+ -re ".*dirarg = .* xmalloc.*$gdb_prompt $" {
+ return
+ }
+ -re "\[ \t\]+\{\r\n$gdb_prompt $" {
+ setup_xfail "mips-*-irix5*"
+ fail "$description ended up at odd location"
+ }
+ -re ".*main.c.*No such file or directory.*$gdb_prompt $" {
+ setup_xfail "rs6000-*-aix3*"
+ fail "must be able to list source lines"
+ return
+ }
+ -re ".*$gdb_prompt $" {
+ fail "unknown source line after $description"
+ return
+ }
+ default {
+ fail "unknown source line near main"
+ return
+ }
+ }
+ send_gdb "$command\n"
+ gdb_expect {
+ -re ".*No such file or directory.\r\n$gdb_prompt $" {
+ fail "$description (no source available)"
+ }
+ -re ".*A file or directory .* does not exist..\r\n$gdb_prompt $" {
+ fail "$description (no source available)"
+ }
+ -re ".*$gdb_prompt $" {
+ pass "$description"
+ }
+ timeout {
+ fail "$description (timeout)"
+ }
+ }
+ }
+}
+
+proc test_with_self { executable } {
+ global gdb_prompt
+ global tool
+ global det_file
+ global decimal
+ global timeout
+
+ # load yourself into the debugger
+ # This can take a relatively long time, particularly for testing where
+ # the executable is being accessed over a network, or where gdb does not
+ # support partial symbols for a particular target and has to load the
+ # entire symbol table. Set the timeout to 10 minutes, which should be
+ # adequate for most environments (it *has* timed out with 5 min on a
+ # SPARCstation SLC under moderate load, so this isn't unreasonable).
+ # After gdb is started, set the timeout to 30 seconds for the duration
+ # of this test, and then back to the original value.
+
+ set oldtimeout $timeout
+ set timeout 600
+ verbose "Timeout is now $timeout seconds" 2
+ if {[gdb_load $executable] <0} then {
+ set timeout $oldtimeout
+ verbose "Timeout is now $timeout seconds" 2
+ return -1
+ }
+ set timeout $oldtimeout
+ verbose "Timeout is now $timeout seconds" 2
+
+ # disassemble yourself
+ gdb_test "x/10i main" \
+ "x/10i.*main.*main.$decimal.*main.$decimal.*" \
+ "Disassemble main"
+
+ # Set a breakpoint at main
+ gdb_test "break main" \
+ "Breakpoint.*at.* file.*, line.*" \
+ "breakpoint in main"
+
+ # We'll need this when we send a ^C to GDB. Need to do it before we
+ # run the program and gdb starts saving and restoring tty states.
+ # On Ultrix, we don't need it and it is really slow (because shell_escape
+ # doesn't use vfork).
+ if ![istarget "*-*-ultrix*"] then {
+ gdb_test "shell stty intr '^C'" "" \
+ "set interrupt character in test_with_self"
+ }
+
+ # FIXME: If we put this after the run to main, the first list
+ # command doesn't print the same line as the current line where
+ # gdb is stopped.
+ gdb_test "set listsize 1" "" "set listsize to 1"
+
+ # run yourself
+ # It may take a very long time for the inferior gdb to start (lynx),
+ # so we bump it back up for the duration of this command.
+ set timeout 600
+
+ set description "run until breakpoint at main"
+ send_gdb "run -nw\n"
+ gdb_expect {
+ -re "Starting program.*Breakpoint \[0-9\]+,.*main .argc.*argv.* at .*main.c:.*$gdb_prompt $" {
+ pass "$description"
+ }
+ -re "Starting program.*Breakpoint \[0-9\]+,.*main .argc.*argv.*$gdb_prompt $" {
+ xfail "$description (line numbers scrambled?)"
+ }
+ -re "vfork: No more processes.*$gdb_prompt $" {
+ fail "$description (out of virtual memory)"
+ set timeout $oldtimeout
+ verbose "Timeout is now $timeout seconds" 2
+ return -1
+ }
+ -re ".*$gdb_prompt $" {
+ fail "$description"
+ set timeout $oldtimeout
+ verbose "Timeout is now $timeout seconds" 2
+ return -1
+ }
+ timeout {
+ fail "$description (timeout)"
+ }
+ }
+
+ set timeout $oldtimeout
+ verbose "Timeout is now $timeout seconds" 2
+
+ # do we have a version number ?
+ send_gdb "print version\n"
+ gdb_expect {
+ -re ".\[0-9\]+ = +0x.*\[0-9.\]+.*$gdb_prompt $" {
+ pass "printed version"
+ }
+ -re ".\[0-9\]+ = +.+ +0x.*\[0-9.\]+.*$gdb_prompt $" {
+ pass "printed version with cast"
+ }
+ -re ".*$gdb_prompt $" { fail "printed version" }
+ timeout { fail "(timeout) printed version" }
+ }
+
+ do_steps_and_nexts
+
+ gdb_test "print \"foo\"" ".\[0-9\]+ = \"foo\"" "print a string"
+
+ # do_steps_and_nexts left us ready to execute an xmalloc call,
+ # so give that a try.
+ # If we don't actually enter the xmalloc call when we give a
+ # step command that seems like a genuine bug. It seems to happen
+ # on most RISC processors.
+ setup_xfail "alpha-*-*" "hppa*-*-*" "mips-*-*"
+ set description "step into xmalloc call"
+ send_gdb "step\n"
+ gdb_expect {
+ -re "xmalloc.*size=.*at.*utils.c.*$gdb_prompt $" {
+ pass "$description"
+ }
+ -re ".*No such file or directory.\r\n$gdb_prompt $" {
+ pass "$description (no source available)"
+ }
+ -re "A file or directory .* does not exist..\r\n$gdb_prompt $" {
+ pass "$description (no source available)"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "$description"
+ }
+ timeout {
+ fail "$description (timeout)"
+ }
+ }
+
+ # start the "xgdb" process
+ send_gdb "continue\n"
+ gdb_expect {
+ -re "GNU gdb \[0-9\.\]*.*
+Copyright \[0-9\]* Free Software Foundation, Inc.*
+GDB is free software, covered by the GNU General Public License, and you are.*
+welcome to change it and/or 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.*
+This GDB was configured as .*$gdb_prompt $"\
+ { pass "xgdb is at prompt" }
+ -re "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.*Copyright \[0-9\]+ Free Software Foundation, Inc..*$gdb_prompt $"\
+ { pass "xgdb is at prompt (obsolescent gdb)" }
+ -re ".*$gdb_prompt $" { fail "xgdb is at prompt" }
+ timeout { fail "(timeout) xgdb is at prompt" }
+ }
+
+ # set xgdb prompt so we can tell which is which
+ send_gdb "set prompt (xgdb) \n"
+ gdb_expect {
+ -re "\[(\]xgdb\[)\].*\[(\]xgdb\[)\] $" { pass "Set xgdb prompt" }
+ -re ".*$gdb_prompt $" { fail "Set xgdb prompt" }
+ default { fail "(timeout) Set xgdb prompt" }
+ }
+
+ # kill the xgdb process
+ set description "send ^C to child process"
+ send_gdb "\003"
+ gdb_expect {
+ -re "Program received signal SIGINT.*$gdb_prompt $" {
+ pass "$description"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "$description"
+ }
+ timeout {
+ fail "$description (timeout)"
+ }
+ }
+
+ set description "send SIGINT signal to child process"
+ send_gdb "signal SIGINT\n"
+ gdb_expect {
+ -re "Continuing with signal SIGINT.*$gdb_prompt $" {
+ pass "$description"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "$description"
+ }
+ timeout {
+ fail "$description (timeout)"
+ }
+ }
+
+ # get a stack trace
+ #
+ # This fails on some linux systems for unknown reasons. On the
+ # systems where it fails, sometimes it works fine when run manually.
+ # The testsuite failures may not be limited to just aout systems.
+ setup_xfail "i*86-pc-linuxaout-gnu" "hppa*-*-hpux*"
+ set description "backtrace through signal handler"
+ send_gdb "backtrace\n"
+ gdb_expect {
+ -re "#0.*read.*in main \\(.*\\) at .*main\\.c.*$gdb_prompt $" {
+ pass "$description"
+ }
+ -re ".*$gdb_prompt $" {
+ # On the alpha, we hit the infamous problem about gdb
+ # being unable to get the frame pointer (mentioned in
+ # gdb/README). As it is intermittent, there is no way to
+ # XFAIL it which will give us an XPASS if the problem goes
+ # away.
+ setup_xfail "alpha*-*-osf*"
+ fail "$description"
+ }
+ timeout {
+ fail "$description (timeout)"
+ }
+ }
+
+
+ # Set the timeout back to the value it had when we were called.
+ set timeout $oldtimeout
+ verbose "Timeout is now $timeout seconds" 2
+
+ # Restart gdb in case next test expects it to be started already.
+ return 0
+}
+
+# Find a pathname to a file that we would execute if the shell was asked
+# to run $arg using the current PATH.
+
+proc find_gdb { arg } {
+
+ # If the arg directly specifies an existing executable file, then
+ # simply use it.
+
+ if [file executable $arg] then {
+ return $arg
+ }
+
+ set result [which $arg]
+ if [string match "/" [ string range $result 0 0 ]] then {
+ return $result
+ }
+
+ # If everything fails, just return the unqualified pathname as default
+ # and hope for best.
+
+ return $arg
+}
+
+# Run the test with self.
+# Copy the file executable file in case this OS doesn't like to edit its own
+# text space.
+
+set GDB_FULLPATH [find_gdb $GDB]
+
+# Remove any old copy lying around.
+remote_file host delete x$tool
+
+gdb_start
+set file [remote_download host $GDB_FULLPATH x$tool]
+set result [test_with_self $file];
+gdb_exit;
+catch "remote_file host delete $file";
+
+if {$result <0} then {
+ warning "Couldn't test self"
+ return -1
+}
diff --git a/gdb/testsuite/gdb.base/a2-run.exp b/gdb/testsuite/gdb.base/a2-run.exp
new file mode 100644
index 00000000000..87a0edf293d
--- /dev/null
+++ b/gdb/testsuite/gdb.base/a2-run.exp
@@ -0,0 +1,253 @@
+# Copyright (C) 1988, 1990, 1991, 1992, 1994, 1997 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file was written by Rob Savoye. (rob@cygnus.com)
+
+# These tests don't work for targets can't take arguments...
+
+if [target_info exists noargs] then {
+ verbose "Skipping a2-run.exp because of noargs."
+ return
+}
+
+if [target_info exists gdb,noinferiorio] {
+ verbose "Skipping a2-run.exp because of noinferiorio."
+ return
+}
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+#
+# test running programs
+#
+set prms_id 0
+set bug_id 0
+
+set testfile "run"
+set srcfile ${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+# Run with no arguments.
+# On VxWorks this justs make sure the program was run.
+gdb_run_cmd
+
+if [istarget "*-*-vxworks*"] then {
+ set timeout 120
+ verbose "Timeout is now $timeout seconds" 2
+ gdb_expect {
+ "Program exited normally" {
+ unresolved "run \"$testfile\" with no args"
+ }
+ -re "usage: factorial <number>" {
+ pass "run \"$testfile\" with no args"
+ }
+ timeout {
+ fail "(timeout) run \"$testfile\" with no args"
+ }
+ }
+ set timeout 10
+ verbose "Timeout is now $timeout seconds" 2
+ gdb_expect -re "$gdb_prompt $" {}
+} else {
+ gdb_expect {
+ -re ".*usage: factorial <number>.*Program exited with code 01.*$gdb_prompt $" {
+ pass "run \"$testfile\" with no args"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "run \"$testfile\" with no args"
+ verbose "expect_out is $expect_out(buffer)" 2
+ }
+ timeout {
+ fail "(timeout) run \"$testfile\" no args"
+ }
+ }
+}
+# Now run with some arguments
+if [istarget "*-*-vxworks*"] then {
+ send_gdb "run vxmain \"5\"\n"
+ gdb_expect -re "run vxmain \"5\"\r\n" {}
+ set timeout 120
+ verbose "Timeout is now $timeout seconds" 2
+ gdb_expect {
+ "Program exited normally" {
+ unresolved "run \"$testfile\" with arg"
+ }
+ "120" {
+ pass "run \"$testfile\" with arg"
+ }
+ timeout {
+ fail "(timeout) run \"$testfile\" with arg"
+ }
+ }
+ set timeout 10
+ verbose "Timeout is now $timeout seconds" 2
+ gdb_expect -re "$gdb_prompt $" {}
+} else {
+ setup_xfail "mips-idt-*" "arm-*-coff"
+ gdb_run_cmd 5
+ gdb_expect {
+ -re ".*120.*$gdb_prompt $"\
+ { pass "run \"$testfile\" with arg" }
+ -re ".*$gdb_prompt $" { fail "run \"$testfile\" with arg" }
+ timeout { fail "(timeout) run \"$testfile\" with arg" }
+ }
+}
+
+# Run again with same arguments.
+setup_xfail "mips-idt-*"
+gdb_run_cmd
+
+if [istarget "*-*-vxworks*"] then {
+ set timeout 120
+ verbose "Timeout is now $timeout seconds" 2
+ gdb_expect {
+ "Program exited normally" {
+ unresolved "run \"$testfile\" again with same args"
+ }
+ "120" { pass "run \"$testfile\" again with same args" }
+ timeout { fail "(timeout) run \"$testfile\" again with same args" }
+ }
+ set timeout 10
+ verbose "Timeout is now $timeout seconds" 2
+ gdb_expect -re "$gdb_prompt $" {}
+} else {
+ setup_xfail "arm-*-coff"
+ gdb_expect {
+ -re ".*120.*$gdb_prompt $"\
+ { pass "run \"$testfile\" again with same args" }
+ -re ".*$gdb_prompt $" { fail "run \"$testfile\" again with same args" }
+ timeout { fail "(timeout) run \"$testfile\" again with same args" }
+ }
+}
+
+# Use "set args" command to specify no arguments as default and run again.
+if [istarget "*-*-vxworks*"] then {
+ send_gdb "set args main\n"
+} else {
+ send_gdb "set args\n"
+}
+gdb_expect -re "$gdb_prompt $"
+
+gdb_run_cmd
+
+if [istarget "*-*-vxworks*"] then {
+ set timeout 120
+ verbose "Timeout is now $timeout seconds" 2
+ gdb_expect {
+ "Program exited normally" {
+ unresolved "run after setting args to nil"
+ }
+ "usage: factorial <number>" {
+ pass "run after setting args to nil"
+ }
+ timeout {
+ fail "(timeout) run after setting args to nil"
+ }
+ }
+ set timeout 10
+ verbose "Timeout is now $timeout seconds" 2
+ gdb_expect -re "$gdb_prompt $" {}
+} else {
+ gdb_expect {
+ -re ".*usage: factorial <number>.*$gdb_prompt $" {
+ pass "run after setting args to nil"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "run after setting args to nil"
+ }
+ timeout {
+ fail "(timeout) run after setting args to nil"
+ }
+ }
+}
+
+# Use "set args" command to specify an argument and run again.
+setup_xfail "mips-idt-*"
+if [istarget "*-*-vxworks*"] then {
+ send_gdb "set args vxmain \"6\"\n"
+} else {
+ send_gdb "set args 6\n"
+}
+gdb_expect -re "$gdb_prompt $"
+gdb_run_cmd
+
+if [istarget "*-*-vxworks*"] then {
+ set timeout 120
+ verbose "Timeout is now $timeout seconds" 2
+ gdb_expect {
+ "Program exited normally" {
+ unresolved "run \"$testfile\" again after setting args"
+ }
+ "720" {
+ pass "run \"$testfile\" again after setting args"
+ }
+ timeout {
+ fail "(timeout) run \"$testfile\" again after setting args"
+ }
+ }
+ set timeout 10
+ verbose "Timeout is now $timeout seconds" 2
+ gdb_expect -re "$gdb_prompt $" {}
+} else {
+ setup_xfail "arm-*-coff"
+ gdb_expect {
+ -re ".*720.*$gdb_prompt $" {
+ pass "run \"$testfile\" again after setting args"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "run \"$testfile\" again after setting args"
+ }
+ timeout {
+ fail "(timeout) run \"$testfile\" again after setting args"
+ }
+ }
+}
+
+# GOAL: Test that shell is being used with "run". For remote debugging
+# targets, there is no guarantee that a "shell" (whatever that is) is used.
+if [isnative] then {
+ send_gdb "run `echo 8`\n"
+ gdb_expect {
+ -re "Starting program.*40320.*$gdb_prompt $" {
+ pass "run \"$testfile\" with shell"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "run \"$testfile\" with shell"
+ }
+ timeout {
+ fail "(timeout) run \"$testfile\" with shell"
+ }
+ }
+}
+
+# Reset the default arguments for VxWorks
+if [istarget "*-*-vxworks*"] then {
+ send_gdb "set args main\n"
+ gdb_expect -re ".*$gdb_prompt $" {}
+}
diff --git a/gdb/testsuite/gdb.base/all-bin.exp b/gdb/testsuite/gdb.base/all-bin.exp
new file mode 100644
index 00000000000..4d6662b2581
--- /dev/null
+++ b/gdb/testsuite/gdb.base/all-bin.exp
@@ -0,0 +1,467 @@
+# Copyright (C) 1998 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file was written by Elena Zannoni (ezannoni@cygnus.com)
+
+# This file is part of the gdb testsuite
+#
+# tests for arithmetic, logical and relational operators
+# with mixed types
+#
+
+
+
+if $tracelevel then {
+ strace $tracelevel
+ }
+
+#
+# test running programs
+#
+set prms_id 0
+set bug_id 0
+
+set testfile "all-types"
+set srcfile ${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug additional_flags=-w}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+ }
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+
+#
+# set it up at a breakpoint so we can play with the variable values
+#
+
+if ![runto_main] then {
+ perror "couldn't run to breakpoint"
+ continue
+}
+
+gdb_test "next" "return 0;" "continuing after dummy()"
+
+send_gdb "print v_int+v_char\n"
+gdb_expect {
+ -re ".*71.*$gdb_prompt $" {
+ pass "print value of v_int+v_char"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of v_int+v_char" }
+ timeout { fail "(timeout) print value of v_int+v_char" }
+ }
+
+send_gdb "print v_int+v_short\n"
+gdb_expect {
+ -re ".*9.*$gdb_prompt $" {
+ pass "print value of v_int+v_short"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of v_int+v_short" }
+ timeout { fail "(timeout) print value of v_int+v_short" }
+ }
+
+
+send_gdb "print v_int+v_signed_char\n"
+gdb_expect {
+ -re ".*72.*$gdb_prompt $" {
+ pass "print value of v_int+v_signed_char"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of v_int+v_signed_char" }
+ timeout { fail "(timeout) print value of v_int+v_signed_char" }
+ }
+
+
+send_gdb "print v_int+v_unsigned_char\n"
+gdb_expect {
+ -re ".*73.*$gdb_prompt $" {
+ pass "print value of v_int+v_unsigned_char"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of v_int+v_unsigned_char" }
+ timeout { fail "(timeout) print value of v_int+v_unsigned_char" }
+ }
+
+
+send_gdb "print v_int+v_signed_short\n"
+gdb_expect {
+ -re ".*10.*$gdb_prompt $" {
+ pass "print value of v_int+v_signed_short"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of v_int+v_signed_short" }
+ timeout { fail "(timeout) print value of v_int+v_signed_short" }
+ }
+
+
+send_gdb "print v_int+v_unsigned_short\n"
+gdb_expect {
+ -re ".*11.*$gdb_prompt $" {
+ pass "print value of v_int+v_unsigned_short"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of v_int+v_unsigned_short" }
+ timeout { fail "(timeout) print value of v_int+v_unsigned_short" }
+ }
+
+
+send_gdb "print v_int+v_signed_int\n"
+gdb_expect {
+ -re ".*13.*$gdb_prompt $" {
+ pass "print value of v_int+v_signed_int"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of v_int+v_signed_int" }
+ timeout { fail "(timeout) print value of v_int+v_signed_int" }
+ }
+
+
+send_gdb "print v_int+v_unsigned_int\n"
+gdb_expect {
+ -re ".*14.*$gdb_prompt $" {
+ pass "print value of v_int+v_unsigned_int"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of v_int+v_unsigned_int" }
+ timeout { fail "(timeout) print value of v_int+v_unsigned_int" }
+ }
+
+
+send_gdb "print v_int+v_long\n"
+gdb_expect {
+ -re ".*15.*$gdb_prompt $" {
+ pass "print value of v_int+v_long"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of v_int+v_long" }
+ timeout { fail "(timeout) print value of v_int+v_long" }
+ }
+
+
+send_gdb "print v_int+v_signed_long\n"
+gdb_expect {
+ -re ".*16.*$gdb_prompt $" {
+ pass "print value of v_int+v_signed_long"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of v_int+v_signed_long" }
+ timeout { fail "(timeout) print value of v_int+v_signed_long" }
+ }
+
+
+send_gdb "print v_int+v_unsigned_long\n"
+gdb_expect {
+ -re ".*17.*$gdb_prompt $" {
+ pass "print value of v_int+v_unsigned_long"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of v_int+v_unsigned_long" }
+ timeout { fail "(timeout) print value of v_int+v_unsigned_long" }
+ }
+
+
+send_gdb "print v_int+v_float\n"
+gdb_expect {
+ -re ".*106.34343.*$gdb_prompt $" {
+ pass "print value of v_int+v_float"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of v_int+v_float" }
+ timeout { fail "(timeout) print value of v_int+v_float" }
+ }
+
+
+send_gdb "print v_int+v_double\n"
+gdb_expect {
+ -re ".*206.56565.*$gdb_prompt $" {
+ pass "print value of v_int+v_double"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of v_int+v_double" }
+ timeout { fail "(timeout) print value of v_int+" }
+ }
+
+
+#
+# test the relational operators with mixed types
+#
+
+send_gdb "print v_int <= v_char\n"
+gdb_expect {
+ -re ".*1.*$gdb_prompt $" {
+ pass "print value of v_int<=v_char"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of v_int<=v_char" }
+ timeout { fail "(timeout) print value of v_int<=v_char" }
+ }
+
+send_gdb "print v_int <= v_short\n"
+gdb_expect {
+ -re ".*0.*$gdb_prompt $" {
+ pass "print value of v_int<=v_short"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of v_int<=v_short" }
+ timeout { fail "(timeout) print value of v_int<=v_short" }
+ }
+
+
+send_gdb "print v_int <= v_signed_char\n"
+gdb_expect {
+ -re ".*1.*$gdb_prompt $" {
+ pass "print value of v_int<=v_signed_char"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of v_int<=v_signed_char" }
+ timeout { fail "(timeout) print value of v_int<=v_signed_char" }
+ }
+
+
+send_gdb "print v_int <= v_unsigned_char\n"
+gdb_expect {
+ -re ".*1.*$gdb_prompt $" {
+ pass "print value of v_int<=v_unsigned_char"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of v_int<=v_unsigned_char" }
+ timeout { fail "(timeout) print value of v_int<=v_unsigned_char" }
+ }
+
+
+send_gdb "print v_int <= v_signed_short\n"
+gdb_expect {
+ -re ".*0.*$gdb_prompt $" {
+ pass "print value of v_int<=v_signed_short"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of v_int<=v_signed_short" }
+ timeout { fail "(timeout) print value of v_int<=v_signed_short" }
+ }
+
+
+send_gdb "print v_int <= v_unsigned_short\n"
+gdb_expect {
+ -re ".*0.*$gdb_prompt $" {
+ pass "print value of v_int<=v_unsigned_short"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of v_int<=v_unsigned_short" }
+ timeout { fail "(timeout) print value of v_int<=v_unsigned_short" }
+ }
+
+
+send_gdb "print v_int <= v_signed_int\n"
+gdb_expect {
+ -re ".*1.*$gdb_prompt $" {
+ pass "print value of v_int<=v_signed_int"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of v_int<=v_signed_int" }
+ timeout { fail "(timeout) print value of v_int<=v_signed_int" }
+ }
+
+
+send_gdb "print v_int <= v_unsigned_int\n"
+gdb_expect {
+ -re ".*1.*$gdb_prompt $" {
+ pass "print value of v_int<=v_unsigned_int"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of v_int<=v_unsigned_int" }
+ timeout { fail "(timeout) print value of v_int<=v_unsigned_int" }
+ }
+
+
+send_gdb "print v_int <= v_long\n"
+gdb_expect {
+ -re ".*1.*$gdb_prompt $" {
+ pass "print value of v_int<=v_long"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of v_int<=v_long" }
+ timeout { fail "(timeout) print value of v_int<=v_long" }
+ }
+
+
+send_gdb "print v_int <= v_signed_long\n"
+gdb_expect {
+ -re ".*1.*$gdb_prompt $" {
+ pass "print value of v_int<=v_signed_long"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of v_int<=v_signed_long" }
+ timeout { fail "(timeout) print value of v_int<=v_signed_long" }
+ }
+
+
+send_gdb "print v_int <= v_unsigned_long\n"
+gdb_expect {
+ -re ".*1.*$gdb_prompt $" {
+ pass "print value of v_int<=v_unsigned_long"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of v_int<=v_unsigned_long" }
+ timeout { fail "(timeout) print value of v_int<=v_unsigned_long" }
+ }
+
+
+send_gdb "print v_int <= v_float\n"
+gdb_expect {
+ -re ".*1.*$gdb_prompt $" {
+ pass "print value of v_int<=v_float"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of v_int<=v_float" }
+ timeout { fail "(timeout) print value of v_int<=v_float" }
+ }
+
+
+send_gdb "print v_int <= v_double\n"
+gdb_expect {
+ -re ".*1.*$gdb_prompt $" {
+ pass "print value of v_int<=v_double"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of v_int<=v_double" }
+ timeout { fail "(timeout) print value of v_int<=v_double" }
+ }
+
+
+
+#
+# test the logical operators with mixed types
+#
+
+gdb_test "set variable v_char=0" "" "set v_char=0"
+gdb_test "set variable v_double=0.0" "" "set v_double=0"
+gdb_test "set variable v_unsigned_long=0" "" "set v_unsigned_long=0"
+
+send_gdb "print v_int && v_char\n"
+gdb_expect {
+ -re ".*0.*$gdb_prompt $" {
+ pass "print value of v_int&&v_char"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of v_int&&v_char" }
+ timeout { fail "(timeout) print value of v_int&&v_char" }
+ }
+
+send_gdb "print v_int && v_short\n"
+gdb_expect {
+ -re ".*1.*$gdb_prompt $" {
+ pass "print value of v_int&&v_short"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of v_int&&v_short" }
+ timeout { fail "(timeout) print value of v_int&&v_short" }
+ }
+
+
+send_gdb "print v_int && v_signed_char\n"
+gdb_expect {
+ -re ".*1.*$gdb_prompt $" {
+ pass "print value of v_int&&v_signed_char"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of v_int&&v_signed_char" }
+ timeout { fail "(timeout) print value of v_int&&v_signed_char" }
+ }
+
+
+send_gdb "print v_int && v_unsigned_char\n"
+gdb_expect {
+ -re ".*1.*$gdb_prompt $" {
+ pass "print value of v_int&&v_unsigned_char"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of v_int&&v_unsigned_char" }
+ timeout { fail "(timeout) print value of v_int&&v_unsigned_char" }
+ }
+
+
+send_gdb "print v_int && v_signed_short\n"
+gdb_expect {
+ -re ".*1.*$gdb_prompt $" {
+ pass "print value of v_int&&v_signed_short"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of v_int&&v_signed_short" }
+ timeout { fail "(timeout) print value of v_int&&v_signed_short" }
+ }
+
+
+send_gdb "print v_int && v_unsigned_short\n"
+gdb_expect {
+ -re ".*1.*$gdb_prompt $" {
+ pass "print value of v_int&&v_unsigned_short"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of v_int&&v_unsigned_short" }
+ timeout { fail "(timeout) print value of v_int&&v_unsigned_short" }
+ }
+
+
+send_gdb "print v_int && v_signed_int\n"
+gdb_expect {
+ -re ".*1.*$gdb_prompt $" {
+ pass "print value of v_int&&v_signed_int"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of v_int&&v_signed_int" }
+ timeout { fail "(timeout) print value of v_int&&v_signed_int" }
+ }
+
+
+send_gdb "print v_int && v_unsigned_int\n"
+gdb_expect {
+ -re ".*1.*$gdb_prompt $" {
+ pass "print value of v_int&&v_unsigned_int"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of v_int&&v_unsigned_int" }
+ timeout { fail "(timeout) print value of v_int&&v_unsigned_int" }
+ }
+
+
+send_gdb "print v_int && v_long\n"
+gdb_expect {
+ -re ".*1.*$gdb_prompt $" {
+ pass "print value of v_int&&v_long"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of v_int&&v_long" }
+ timeout { fail "(timeout) print value of v_int&&v_long" }
+ }
+
+
+send_gdb "print v_int && v_signed_long\n"
+gdb_expect {
+ -re ".*1.*$gdb_prompt $" {
+ pass "print value of v_int&&v_signed_long"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of v_int&&v_signed_long" }
+ timeout { fail "(timeout) print value of v_int&&v_signed_long" }
+ }
+
+
+send_gdb "print v_int && v_unsigned_long\n"
+gdb_expect {
+ -re ".*0.*$gdb_prompt $" {
+ pass "print value of v_int&&v_unsigned_long"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of v_int&&v_unsigned_long" }
+ timeout { fail "(timeout) print value of v_int&&v_unsigned_long" }
+ }
+
+
+send_gdb "print v_int && v_float\n"
+gdb_expect {
+ -re ".*1.*$gdb_prompt $" {
+ pass "print value of v_int&&v_float"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of v_int&&v_float" }
+ timeout { fail "(timeout) print value of v_int&&v_float" }
+ }
+
+
+send_gdb "print v_int && v_double\n"
+gdb_expect {
+ -re ".*0.*$gdb_prompt $" {
+ pass "print value of v_int&&v_double"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of v_int&&v_double" }
+ timeout { fail "(timeout) print value of v_int&&v_double" }
+ }
+
+
+
+
+
diff --git a/gdb/testsuite/gdb.base/all-types.c b/gdb/testsuite/gdb.base/all-types.c
new file mode 100644
index 00000000000..2f3a31f739b
--- /dev/null
+++ b/gdb/testsuite/gdb.base/all-types.c
@@ -0,0 +1,62 @@
+/*
+ * the basic C types.
+ */
+
+#if !defined (__STDC__) && !defined (_AIX)
+#define signed /**/
+#endif
+
+char v_char;
+signed char v_signed_char;
+unsigned char v_unsigned_char;
+
+short v_short;
+signed short v_signed_short;
+unsigned short v_unsigned_short;
+
+int v_int;
+signed int v_signed_int;
+unsigned int v_unsigned_int;
+
+long v_long;
+signed long v_signed_long;
+unsigned long v_unsigned_long;
+
+float v_float;
+double v_double;
+
+int main ()
+{
+ extern void dummy();
+#ifdef usestubs
+ set_debug_traps();
+ breakpoint();
+#endif
+ dummy();
+ return 0;
+
+}
+
+void dummy()
+{
+ /* Some linkers (e.g. on AIX) remove unreferenced variables,
+ so make sure to reference them. */
+ v_char = 'A';
+ v_signed_char = 'B';
+ v_unsigned_char = 'C';
+
+ v_short = 3;
+ v_signed_short = 4;
+ v_unsigned_short = 5;
+
+ v_int = 6;
+ v_signed_int = 7;
+ v_unsigned_int = 8;
+
+ v_long = 9;
+ v_signed_long = 10;
+ v_unsigned_long = 11;
+
+ v_float = 100.343434;
+ v_double = 200.565656;
+}
diff --git a/gdb/testsuite/gdb.base/arithmet.exp b/gdb/testsuite/gdb.base/arithmet.exp
new file mode 100644
index 00000000000..69b9f74aeaa
--- /dev/null
+++ b/gdb/testsuite/gdb.base/arithmet.exp
@@ -0,0 +1,375 @@
+# Copyright (C) 1998 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file was written by Elena Zannoni (ezannoni@cygnus.com)
+
+# This file is part of the gdb testsuite
+#
+# tests for correctness of arithmetic operators, associativity and precedence
+# with integer type variables
+#
+
+if $tracelevel then {
+ strace $tracelevel
+ }
+
+#
+# test running programs
+#
+set prms_id 0
+set bug_id 0
+
+set testfile "int-type"
+set srcfile ${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug additional_flags=-w}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+ }
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+
+#
+# set it up at a breakpoint so we can play with the variable values
+#
+
+if ![runto_main] then {
+ perror "couldn't run to breakpoint"
+ continue
+}
+
+#
+# test expressions with "int" types
+#
+
+gdb_test "set variable x=14" "" "set variable x=14"
+gdb_test "set variable y=2" "" "set variable y=2"
+gdb_test "set variable z=2" "" "set variable z=2"
+gdb_test "set variable w=3" "" "set variable w=3"
+
+send_gdb "print x\n"
+gdb_expect {
+ -re ".*14.*$gdb_prompt $" {
+ pass "print value of x"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of x" }
+ timeout { fail "(timeout) print value of x" }
+ }
+
+
+send_gdb "print y\n"
+gdb_expect {
+ -re ".*2.*$gdb_prompt $" {
+ pass "print value of y"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of y" }
+ timeout { fail "(timeout) print value of y" }
+ }
+
+send_gdb "print z\n"
+gdb_expect {
+ -re ".*2.*$gdb_prompt $" {
+ pass "print value of z"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of z" }
+ timeout { fail "(timeout) print value of z" }
+ }
+
+send_gdb "print w\n"
+gdb_expect {
+ -re ".*3.*$gdb_prompt $" {
+ pass "print value of w"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of w" }
+ timeout { fail "(timeout) print value of w" }
+ }
+
+
+
+send_gdb "print x+y\n"
+gdb_expect {
+ -re ".*16.*$gdb_prompt $" {
+ pass "print value of x+y"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of x+y" }
+ timeout { fail "(timeout) print value of x+y" }
+ }
+
+send_gdb "print x-y\n"
+gdb_expect {
+ -re ".*12.*$gdb_prompt $" {
+ pass "print value of x-y"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of x-y" }
+ timeout { fail "(timeout) print value of x-y" }
+ }
+
+send_gdb "print x*y\n"
+gdb_expect {
+ -re ".*28.*$gdb_prompt $" {
+ pass "print value of x*y"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of x*y" }
+ timeout { fail "(timeout) print value of x*y" }
+ }
+
+send_gdb "print x/y\n"
+gdb_expect {
+ -re ".*7.*$gdb_prompt $" {
+ pass "print value of x/y"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of x/y" }
+ timeout { fail "(timeout) print value of x/y" }
+ }
+
+send_gdb "print x%y\n"
+gdb_expect {
+ -re ".*0.*$gdb_prompt $" {
+ pass "print value of x%y"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of x%y" }
+ timeout { fail "(timeout) print value of x%y" }
+ }
+
+
+
+# Test associativity of +, -, *, % ,/
+
+
+send_gdb "print x+y+z\n"
+gdb_expect {
+ -re ".*18.*$gdb_prompt $" {
+ pass "print value of x+y"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of x+y" }
+ timeout { fail "(timeout) print value of x+y" }
+ }
+
+send_gdb "print x-y-z\n"
+gdb_expect {
+ -re ".*10.*$gdb_prompt $" {
+ pass "print value of x-y"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of x-y" }
+ timeout { fail "(timeout) print value of x-y" }
+ }
+
+send_gdb "print x*y*z\n"
+gdb_expect {
+ -re ".*56.*$gdb_prompt $" {
+ pass "print value of x*y"
+ }
+ -re 8".*$gdb_prompt $" { fail "print value of x*y" }
+ timeout { fail "(timeout) print value of x*y" }
+ }
+
+send_gdb "print x/y/z\n"
+gdb_expect {
+ -re ".*3.*$gdb_prompt $" {
+ pass "print value of x/y"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of x/y" }
+ timeout { fail "(timeout) print value of x/y" }
+ }
+
+send_gdb "print x%y%z\n"
+gdb_expect {
+ -re ".*0.*$gdb_prompt $" {
+ pass "print value of x%y"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of x%y" }
+ timeout { fail "(timeout) print value of x%y" }
+ }
+
+
+# test precedence rules on pairs of arithmetic operators
+
+gdb_test "set variable x=10" "" "set variable x"
+gdb_test "set variable y=4" "" "set variable y"
+gdb_test "set variable z=2" "" "set variable z"
+
+
+
+# x y z
+# 10 4 2
+send_gdb "print x+y-z\n"
+gdb_expect {
+ -re ".*12.*$gdb_prompt $" {
+ pass "print value of x+y-z"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of x+y-z" }
+ timeout { fail "(timeout) print value of x+y-z" }
+ }
+
+# 10 4 2
+send_gdb "print x+y*z\n"
+gdb_expect {
+ -re ".*18.*$gdb_prompt $" {
+ pass "print value of x+y*z"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of x+y*z" }
+ timeout { fail "(timeout) print value of x+y*z" }
+ }
+
+
+gdb_test "set variable z=3" "" "set variable z"
+
+
+# 10 4 3
+send_gdb "print x+y%z\n"
+gdb_expect {
+ -re ".*11.*$gdb_prompt $" {
+ pass "print value of x+y%z"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of x+y%z" }
+ timeout { fail "(timeout) print value of x+y%z" }
+ }
+
+
+# 10 4 3
+send_gdb "print x+y/z\n"
+gdb_expect {
+ -re ".*11.*$gdb_prompt $" {
+ pass "print value of x+y/z"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of x+y/z" }
+ timeout { fail "(timeout) print value of x+y/z" }
+ }
+
+gdb_test "set variable z=2" "" " set variable z"
+
+
+# 10 4 2
+send_gdb "print x-y*z\n"
+gdb_expect {
+ -re ".*2.*$gdb_prompt $" {
+ pass "print value of x-y*z"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of x-y*z" }
+ timeout { fail "(timeout) print value of x-y*z" }
+ }
+
+# 10 4 2
+send_gdb "print x-y%z\n"
+gdb_expect {
+ -re ".*10.*$gdb_prompt $" {
+ pass "print value of x-y%z"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of x-y%z" }
+ timeout { fail "(timeout) print value of x-y%z" }
+ }
+
+
+# 10 4 2
+send_gdb "print x-y/z\n"
+gdb_expect {
+ -re ".*8.*$gdb_prompt $" {
+ pass "print value of x-y/z"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of x-y/z" }
+ timeout { fail "(timeout) print value of x-y/z" }
+ }
+
+# 10 4 2
+send_gdb "print x*y/z\n"
+gdb_expect {
+ -re ".*20.*$gdb_prompt $" {
+ pass "print value of x*y/z"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of x*y/z" }
+ timeout { fail "(timeout) print value of x*y/z" }
+ }
+
+gdb_test "set variable z=3" "" "set z to 3"
+
+# 10 4 3
+send_gdb "print x*y%z\n"
+gdb_expect {
+ -re ".*1.*$gdb_prompt $" {
+ pass "print value of x*y%z"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of x*y%z" }
+ timeout { fail "(timeout) print value of x*y%z" }
+ }
+
+# 10 4 3
+send_gdb "print x/y%z\n"
+gdb_expect {
+ -re ".*2\r\n$gdb_prompt $" {
+ pass "print value of x/y%z"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of x/y%z" }
+ timeout { fail "(timeout) print value of x/y%z" }
+ }
+
+
+
+# test use of parenthesis to enforce different order of evaluation
+
+# 10 4 3
+send_gdb "print x-(y+z)\n"
+gdb_expect {
+ -re ".*3\r\n$gdb_prompt $" {
+ pass "print value of x-(y+z)"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of x-(y+z)" }
+ timeout { fail "(timeout) print value of x-(y+z)" }
+ }
+
+
+# 10 4 3
+send_gdb "print x/(y*z)\n"
+gdb_expect {
+ -re ".*0\r\n$gdb_prompt $" {
+ pass "print value of x/(y*z)"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of x/(y*z)" }
+ timeout { fail "(timeout) print value of x/(y*z)" }
+ }
+
+# 10 4 3
+send_gdb "print x-(y/z)\n"
+gdb_expect {
+ -re ".*9\r\n$gdb_prompt $" {
+ pass "print value of x-(y/z)"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of x-(y/z)" }
+ timeout { fail "(timeout) print value of x-(y/z)" }
+ }
+
+
+# 10 4 3
+send_gdb "print (x+y)*z\n"
+gdb_expect {
+ -re ".*42\r\n$gdb_prompt $" {
+ pass "print value of (x+y)*z"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of (x+y)*z" }
+ timeout { fail "(timeout) print value of (x+y)*z" }
+ }
+
+
+
+
+
+
diff --git a/gdb/testsuite/gdb.base/assign.exp b/gdb/testsuite/gdb.base/assign.exp
new file mode 100644
index 00000000000..059862c91b8
--- /dev/null
+++ b/gdb/testsuite/gdb.base/assign.exp
@@ -0,0 +1,446 @@
+# Copyright (C) 1998 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file was written by Elena Zannoni (ezannoni@cygnus.com)
+
+# This file is part of the gdb testsuite
+#
+# tests for all the assignemnt operators
+# with mixed types and with int type variables
+#
+
+if $tracelevel then {
+ strace $tracelevel
+ }
+
+#
+# test running programs
+#
+set prms_id 0
+set bug_id 0
+
+set testfile "all-types"
+set srcfile ${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug additional_flags=-w}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+ }
+
+
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+
+#
+# set it up at a breakpoint so we can play with the variable values
+#
+
+if ![runto_main] then {
+ perror "couldn't run to breakpoint"
+ continue
+}
+
+gdb_test "next" "return 0;" "continuing after dummy()"
+
+send_gdb "print v_int=57\n"
+gdb_expect {
+ -re ".*57.*$gdb_prompt $" {
+ send_gdb "print v_int\n"
+ gdb_expect {
+ -re ".*57.*$gdb_prompt $" {
+ pass "v_int=57"
+ }
+ -re ".*$gdb_prompt $" { fail "v_int=57" }
+ timeout { fail "(timeout) v_int=57" }
+ }
+ }
+ -re ".*$gdb_prompt $" { fail "v_int=57" }
+ timeout { fail "(timeout) v_int=57" }
+ }
+
+
+gdb_test "set variable v_int = 6" "" "set v_int to 6"
+
+
+send_gdb "print v_int+=57\n"
+gdb_expect {
+ -re ".*63.*$gdb_prompt $" {
+ send_gdb "print v_int\n"
+ gdb_expect {
+ -re ".*63.*$gdb_prompt $" {
+ pass "v_int+=57"
+ }
+ -re ".*$gdb_prompt $" { fail "v_int+=57" }
+ timeout { fail "(timeout) v_int+=57" }
+ }
+ }
+ -re ".*$gdb_prompt $" { fail "v_int+=57" }
+ timeout { fail "(timeout) v_int+=57" }
+ }
+
+gdb_test "set variable v_int = 6" "" "set v_int to 6"
+
+send_gdb "print v_int-=57\n"
+gdb_expect {
+ -re ".*-51.*$gdb_prompt $" {
+ send_gdb "print v_int\n"
+ gdb_expect {
+ -re ".*-51.*$gdb_prompt $" {
+ pass "v_int-=57"
+ }
+ -re ".*$gdb_prompt $" { fail "v_int-=57" }
+ timeout { fail "(timeout) v_int-=57" }
+ }
+ }
+ -re ".*$gdb_prompt $" { fail "v_int-=57" }
+ timeout { fail "(timeout) v_int-=57" }
+ }
+
+gdb_test "set variable v_int = 6" "" "set v_int to 6"
+
+send_gdb "print v_int*=5\n"
+gdb_expect {
+ -re ".*30.*$gdb_prompt $" {
+ send_gdb "print v_int\n"
+ gdb_expect {
+ -re ".*30.*$gdb_prompt $" {
+ pass "v_int*=5"
+ }
+ -re ".*$gdb_prompt $" { fail "v_int*=5" }
+ timeout { fail "(timeout) v_int*=5" }
+ }
+ }
+ -re ".*$gdb_prompt $" { fail "v_int*=5" }
+ timeout { fail "(timeout) v_int*=5" }
+ }
+
+gdb_test "set variable v_int = 6" "" "set v_int to 6"
+
+send_gdb "print v_int/=4\n"
+gdb_expect {
+ -re ".*1.*$gdb_prompt $" {
+ send_gdb "print v_int\n"
+ gdb_expect {
+ -re ".*1.*$gdb_prompt $" {
+ pass "v_int/=4"
+ }
+ -re ".*$gdb_prompt $" { fail "v_int/=4" }
+ timeout { fail "(timeout) v_int/=4" }
+ }
+ }
+ -re ".*$gdb_prompt $" { fail "v_int/=4" }
+ timeout { fail "(timeout) v_int/=4" }
+ }
+
+
+
+gdb_test "set variable v_int = 6" "" "set v_int to 6"
+
+send_gdb "print v_int%=4\n"
+gdb_expect {
+ -re ".*2.*$gdb_prompt $" {
+ send_gdb "print v_int\n"
+ gdb_expect {
+ -re ".*2.*$gdb_prompt $" {
+ pass "v_int%=4"
+ }
+ -re ".*$gdb_prompt $" { fail "v_int%=4" }
+ timeout { fail "(timeout) v_int%=4" }
+ }
+ }
+ -re ".*$gdb_prompt $" { fail "v_int%=4" }
+ timeout { fail "(timeout) v_int%=4" }
+ }
+
+
+
+gdb_test "set variable v_int = 6" "" "set v_int to 6"
+
+
+
+send_gdb "print v_int+=v_char\n"
+gdb_expect {
+ -re ".*71.*$gdb_prompt $" {
+ send_gdb "print v_int\n"
+ gdb_expect {
+ -re ".*71.*$gdb_prompt $" {
+ pass "v_int+=char"
+ }
+ -re ".*$gdb_prompt $" { fail "v_int+=v_char" }
+ timeout { fail "(timeout) v_int+=v_char" }
+ }
+ }
+ -re ".*$gdb_prompt $" { fail "v_int+=v_char" }
+ timeout { fail "(timeout) v_int+=v_char" }
+ }
+
+
+gdb_test "set variable v_int = 6" "" "set v_int to 6"
+
+
+
+send_gdb "print v_int+=v_signed_char\n"
+gdb_expect {
+ -re ".*72.*$gdb_prompt $" {
+ send_gdb "print v_int\n"
+ gdb_expect {
+ -re ".*72.*$gdb_prompt $" {
+ pass "v_int+=signed_char"
+ }
+ -re ".*$gdb_prompt $" { fail "v_int+=v_signed_char" }
+ timeout { fail "(timeout) v_int+=v_signed_char" }
+ }
+ }
+ -re ".*$gdb_prompt $" { fail "v_int+=v_signed_char" }
+ timeout { fail "(timeout) v_int+=v_signed_char" }
+ }
+
+
+gdb_test "set variable v_int = 6" "" "set v_int to 6"
+
+
+
+send_gdb "print v_int+=v_unsigned_char\n"
+gdb_expect {
+ -re ".*73.*$gdb_prompt $" {
+ send_gdb "print v_int\n"
+ gdb_expect {
+ -re ".*73.*$gdb_prompt $" {
+ pass "v_int+=unsigned_char"
+ }
+ -re ".*$gdb_prompt $" { fail "v_int+=v_unsigned_char" }
+ timeout { fail "(timeout) v_int+=v_unsigned_char" }
+ }
+ }
+ -re ".*$gdb_prompt $" { fail "v_int+=v_unsigned_char" }
+ timeout { fail "(timeout) v_int+=v_unsigned_char" }
+ }
+
+
+gdb_test "set variable v_int = 6" "" "set v_int to 6"
+
+
+
+send_gdb "print v_int+=v_short\n"
+gdb_expect {
+ -re ".*9.*$gdb_prompt $" {
+ send_gdb "print v_int\n"
+ gdb_expect {
+ -re ".*9.*$gdb_prompt $" {
+ pass "v_int+=short"
+ }
+ -re ".*$gdb_prompt $" { fail "v_int+=v_short" }
+ timeout { fail "(timeout) v_int+=v_short" }
+ }
+ }
+ -re ".*$gdb_prompt $" { fail "v_int+=v_short" }
+ timeout { fail "(timeout) v_int+=v_short" }
+ }
+
+
+gdb_test "set variable v_int = 6" "" "set v_int to 6"
+
+
+
+send_gdb "print v_int+=v_signed_short\n"
+gdb_expect {
+ -re ".*10.*$gdb_prompt $" {
+ send_gdb "print v_int\n"
+ gdb_expect {
+ -re ".*10.*$gdb_prompt $" {
+ pass "v_int+=signed_short"
+ }
+ -re ".*$gdb_prompt $" { fail "v_int+=v_signed_short" }
+ timeout { fail "(timeout) v_int+=v_signed_short" }
+ }
+ }
+ -re ".*$gdb_prompt $" { fail "v_int+=v_signed_short" }
+ timeout { fail "(timeout) v_int+=v_signed_short" }
+ }
+
+
+gdb_test "set variable v_int = 6" "" "set v_int to 6"
+
+
+
+send_gdb "print v_int+=v_unsigned_short\n"
+gdb_expect {
+ -re ".*11.*$gdb_prompt $" {
+ send_gdb "print v_int\n"
+ gdb_expect {
+ -re ".*11.*$gdb_prompt $" {
+ pass "v_int=+unsigned_short"
+ }
+ -re ".*$gdb_prompt $" { fail "v_int+=v_unsigned_short" }
+ timeout { fail "(timeout) v_int+=v_unsigned_short" }
+ }
+ }
+ -re ".*$gdb_prompt $" { fail "v_int+=v_unsigned_short" }
+ timeout { fail "(timeout) v_int+=v_unsigned_short" }
+ }
+
+
+gdb_test "set variable v_int = 6" "" "set v_int to 6"
+
+
+
+send_gdb "print v_int+=v_signed_int\n"
+gdb_expect {
+ -re ".*13.*$gdb_prompt $" {
+ send_gdb "print v_int\n"
+ gdb_expect {
+ -re ".*13.*$gdb_prompt $" {
+ pass "v_int+=signed_int"
+ }
+ -re ".*$gdb_prompt $" { fail "v_int+=v_signed_int" }
+ timeout { fail "(timeout) v_int+=v_signed_int" }
+ }
+ }
+ -re ".*$gdb_prompt $" { fail "v_int+=v_signed_int" }
+ timeout { fail "(timeout) v_int+=v_signed_int" }
+ }
+
+
+gdb_test "set variable v_int = 6" "" "set v_int to 6"
+
+
+
+send_gdb "print v_int+=v_unsigned_int\n"
+gdb_expect {
+ -re ".*14.*$gdb_prompt $" {
+ send_gdb "print v_int\n"
+ gdb_expect {
+ -re ".*14.*$gdb_prompt $" {
+ pass "v_int+=unsigned_int"
+ }
+ -re ".*$gdb_prompt $" { fail "v_int+=v_unsigned_int" }
+ timeout { fail "(timeout) v_int+=v_unsigned_int" }
+ }
+ }
+ -re ".*$gdb_prompt $" { fail "v_int+=v_unsigned_int" }
+ timeout { fail "(timeout) v_int+=v_unsigned_int" }
+ }
+
+
+gdb_test "set variable v_int = 6" "" "set v_int to 6"
+
+
+
+send_gdb "print v_int+=v_long\n"
+gdb_expect {
+ -re ".*15.*$gdb_prompt $" {
+ send_gdb "print v_int\n"
+ gdb_expect {
+ -re ".*15.*$gdb_prompt $" {
+ pass "v_int+=long"
+ }
+ -re ".*$gdb_prompt $" { fail "v_int+=v_long" }
+ timeout { fail "(timeout) v_int+=v_long" }
+ }
+ }
+ -re ".*$gdb_prompt $" { fail "v_int+=v_long" }
+ timeout { fail "(timeout) v_int+=v_long" }
+ }
+
+
+gdb_test "set variable v_int = 6" "" "set v_int to 6"
+
+
+
+send_gdb "print v_int+=v_signed_long\n"
+gdb_expect {
+ -re ".*16.*$gdb_prompt $" {
+ send_gdb "print v_int\n"
+ gdb_expect {
+ -re ".*16.*$gdb_prompt $" {
+ pass "v_int+=signed_long"
+ }
+ -re ".*$gdb_prompt $" { fail "v_int+=v_signed_long" }
+ timeout { fail "(timeout) v_int+=v_signed_long" }
+ }
+ }
+ -re ".*$gdb_prompt $" { fail "v_int+=v_signed_long" }
+ timeout { fail "(timeout) v_int+=v_signed_long" }
+ }
+
+
+gdb_test "set variable v_int = 6" "" "set v_int to 6"
+
+
+send_gdb "print v_int+=v_unsigned_long\n"
+gdb_expect {
+ -re ".*17.*$gdb_prompt $" {
+ send_gdb "print v_int\n"
+ gdb_expect {
+ -re ".*17.*$gdb_prompt $" {
+ pass "v_int+=unsigned_long"
+ }
+ -re ".*$gdb_prompt $" { fail "v_int+=v_unsigned_long" }
+ timeout { fail "(timeout) v_int+=v_unsigned_long" }
+ }
+ }
+ -re ".*$gdb_prompt $" { fail "v_int+=v_unsigned_long" }
+ timeout { fail "(timeout) v_int+=v_unsigned_long" }
+ }
+
+
+gdb_test "set variable v_int = 6" "" "set v_int to 6"
+
+
+send_gdb "print v_int+=v_float\n"
+gdb_expect {
+ -re ".*106\r\n$gdb_prompt $" {
+ send_gdb "print v_int\n"
+ gdb_expect {
+ -re ".*106\r\n$gdb_prompt $" {
+ pass "v_int+=v_float"
+ }
+ -re ".*$gdb_prompt $" { fail "v_int+=v_float" }
+ timeout { fail "(timeout) v_int+=v_float" }
+ }
+ }
+ -re ".*$gdb_prompt $" { fail "v_int+=v_float" }
+ timeout { fail "(timeout) v_int+=v_float" }
+ }
+
+
+gdb_test "set variable v_int = 6" "" "set v_int to 6"
+
+
+send_gdb "print v_int+=v_double\n"
+gdb_expect {
+ -re ".*206\r\n$gdb_prompt $" {
+ send_gdb "print v_int\n"
+ gdb_expect {
+ -re ".*206\r\n$gdb_prompt $" {
+ pass "v_int+=double"
+ }
+ -re ".*$gdb_prompt $" { fail "v_int+=v_double" }
+ timeout { fail "(timeout) v_int+=v_double" }
+ }
+ }
+ -re ".*$gdb_prompt $" { fail "v_int+=v_signed_long" }
+ timeout { fail "(timeout) v_int+=v_double" }
+ }
+
+
diff --git a/gdb/testsuite/gdb.base/bar.c b/gdb/testsuite/gdb.base/bar.c
new file mode 100644
index 00000000000..8a4da9802f8
--- /dev/null
+++ b/gdb/testsuite/gdb.base/bar.c
@@ -0,0 +1,9 @@
+static int barx __attribute__ ((section (".data01"))) = 'b' + 'a' + 'r';
+
+int bar (int x)
+{
+ if (x)
+ return barx;
+ else
+ return 0;
+}
diff --git a/gdb/testsuite/gdb.base/baz.c b/gdb/testsuite/gdb.base/baz.c
new file mode 100644
index 00000000000..a13cd16bbbe
--- /dev/null
+++ b/gdb/testsuite/gdb.base/baz.c
@@ -0,0 +1,9 @@
+static int bazx __attribute__ ((section (".data02"))) = 'b' + 'a' + 'z';
+
+int baz (int x)
+{
+ if (x)
+ return bazx;
+ else
+ return 0;
+}
diff --git a/gdb/testsuite/gdb.base/bitfields.c b/gdb/testsuite/gdb.base/bitfields.c
new file mode 100644
index 00000000000..930b244fcd1
--- /dev/null
+++ b/gdb/testsuite/gdb.base/bitfields.c
@@ -0,0 +1,194 @@
+/* Test program to test bit field operations */
+
+/* For non-ANSI compilers, use plain ints for the signed bit fields. However,
+ whether they actually end up signed or not is implementation defined, so
+ this may cause some tests to fail. But at least we can still compile
+ the test program and run the tests... */
+
+#ifndef __STDC__
+#define signed /**/
+#endif
+
+struct fields
+{
+ unsigned char uc ;
+ signed int s1 : 1;
+ unsigned int u1 : 1;
+ signed int s2 : 2;
+ unsigned int u2 : 2;
+ signed int s3 : 3;
+ unsigned int u3 : 3;
+ signed int s9 : 9;
+ unsigned int u9 : 9;
+ signed char sc ;
+} flags;
+
+void break1 ()
+{
+}
+
+void break2 ()
+{
+}
+
+void break3 ()
+{
+}
+
+void break4 ()
+{
+}
+
+void break5 ()
+{
+}
+
+void break6 ()
+{
+}
+
+void break7 ()
+{
+}
+
+void break8 ()
+{
+}
+
+void break9 ()
+{
+}
+
+void break10 ()
+{
+}
+
+/* This is used by bitfields.exp to determine if the target understands
+ signed bitfields. */
+int i;
+
+int main ()
+{
+ /* For each member, set that member to 1, allow gdb to verify that the
+ member (and only that member) is 1, and then reset it back to 0. */
+
+#ifdef usestubs
+ set_debug_traps();
+ breakpoint();
+#endif
+ flags.uc = 1;
+ break1 ();
+ flags.uc = 0;
+
+ flags.s1 = 1;
+ break1 ();
+ flags.s1 = 0;
+
+ flags.u1 = 1;
+ break1 ();
+ flags.u1 = 0;
+
+ flags.s2 = 1;
+ break1 ();
+ flags.s2 = 0;
+
+ flags.u2 = 1;
+ break1 ();
+ flags.u2 = 0;
+
+ flags.s3 = 1;
+ break1 ();
+ flags.s3 = 0;
+
+ flags.u3 = 1;
+ break1 ();
+ flags.u3 = 0;
+
+ flags.s9 = 1;
+ break1 ();
+ flags.s9 = 0;
+
+ flags.u9 = 1;
+ break1 ();
+ flags.u9 = 0;
+
+ flags.sc = 1;
+ break1 ();
+ flags.sc = 0;
+
+ /* Fill alternating fields with all 1's and verify that none of the bits
+ "bleed over" to the other fields. */
+
+ flags.uc = 0xFF;
+ flags.u1 = 0x1;
+ flags.u2 = 0x3;
+ flags.u3 = 0x7;
+ flags.u9 = 0x1FF;
+ break2 ();
+ flags.uc = 0;
+ flags.u1 = 0;
+ flags.u2 = 0;
+ flags.u3 = 0;
+ flags.u9 = 0;
+
+ flags.s1 = 0x1;
+ flags.s2 = 0x3;
+ flags.s3 = 0x7;
+ flags.s9 = 0x1FF;
+ flags.sc = 0xFF;
+ break2 ();
+ flags.s1 = 0;
+ flags.s2 = 0;
+ flags.s3 = 0;
+ flags.s9 = 0;
+ flags.sc = 0;
+
+ /* Fill the unsigned fields with the maximum positive value and verify
+ that the values are printed correctly. */
+
+ /* Maximum positive values */
+ flags.u1 = 0x1;
+ flags.u2 = 0x3;
+ flags.u3 = 0x7;
+ flags.u9 = 0x1FF;
+ break3 ();
+ flags.u1 = 0;
+ flags.u2 = 0;
+ flags.u3 = 0;
+ flags.u9 = 0;
+
+ /* Fill the signed fields with the maximum positive value, then the maximally
+ negative value, then -1, and verify in each case that the values are
+ printed correctly. */
+
+ /* Maximum positive values */
+ flags.s1 = 0x0;
+ flags.s2 = 0x1;
+ flags.s3 = 0x3;
+ flags.s9 = 0xFF;
+ break4 ();
+
+ /* Maximally negative values */
+ flags.s1 = 0x1;
+ flags.s2 = 0x2;
+ flags.s3 = 0x4;
+ flags.s9 = 0x100;
+ /* Extract bitfield value so that bitfield.exp can check if the target
+ understands signed bitfields. */
+ i = flags.s9;
+ break4 ();
+
+ /* -1 */
+ flags.s1 = 0x1;
+ flags.s2 = 0x3;
+ flags.s3 = 0x7;
+ flags.s9 = 0x1FF;
+ break4 ();
+
+ flags.s1 = 0;
+ flags.s2 = 0;
+ flags.s3 = 0;
+ flags.s9 = 0;
+
+ return 0;
+}
diff --git a/gdb/testsuite/gdb.base/bitfields.exp b/gdb/testsuite/gdb.base/bitfields.exp
new file mode 100644
index 00000000000..764e80c6504
--- /dev/null
+++ b/gdb/testsuite/gdb.base/bitfields.exp
@@ -0,0 +1,268 @@
+# Copyright (C) 1992, 1994, 1997 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file was written by Fred Fish. (fnf@cygnus.com)
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+set prms_id 0
+set bug_id 0
+
+set testfile "bitfields"
+set srcfile ${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+#
+# Test bitfield locating and uniqueness.
+# For each member, set that member to 1 and verify that the member (and only
+# that member) is 1, then reset it back to 0.
+#
+
+proc bitfield_uniqueness {} {
+ global decimal
+ global hex
+ global gdb_prompt
+ global srcfile
+
+ if { ! [runto break1] } {
+ gdb_suppress_tests;
+ }
+
+ if [gdb_test "print flags" ".*uc = 1 .*, s1 = 0, u1 = 0, s2 = 0, u2 = 0, s3 = 0, u3 = 0, s9 = 0, u9 = 0, sc = 0.*"] {
+ gdb_suppress_tests;
+ }
+ if [gdb_test "cont" "Break.*break1 \\(\\) at .*$srcfile:$decimal.*" "continuing to break1 #1"] {
+ gdb_suppress_tests;
+ }
+ # Note that we check for s1 as either 1 or -1, so that failure to
+ # treat it correctly as a signed 1bit field (values 0 or -1) while
+ # printing its value does not cause a spurious failure. We do the
+ # signedness preservation test later.
+ if [gdb_test "print flags" ".*uc = 0 .*, s1 = (1|-1), u1 = 0, s2 = 0, u2 = 0, s3 = 0, u3 = 0, s9 = 0, u9 = 0, sc = 0.*" "bitfield uniqueness (s1)"] {
+ gdb_suppress_tests;
+ }
+ if [gdb_test "cont" "Break.*break1 \\(\\) at .*$srcfile:$decimal.*" "continuing to break1 #2"] {
+ gdb_suppress_tests;
+ }
+ if [gdb_test "print flags" ".*uc = 0 .*, s1 = 0, u1 = 1, s2 = 0, u2 = 0, s3 = 0, u3 = 0, s9 = 0, u9 = 0, sc = 0.*" "bitfield uniqueness (u1)"] {
+ gdb_suppress_tests;
+ }
+ if [gdb_test "cont" "Break.*break1 \\(\\) at .*$srcfile:$decimal.*" "continuing to break1 #3"] {
+ gdb_suppress_tests;
+ }
+ if [gdb_test "print flags" ".*uc = 0 .*, s1 = 0, u1 = 0, s2 = 1, u2 = 0, s3 = 0, u3 = 0, s9 = 0, u9 = 0, sc = 0.*" "bitfield uniqueness (s2)"] {
+ gdb_suppress_tests;
+ }
+ if [gdb_test "cont" "Break.*break1 \\(\\) at .*$srcfile:$decimal.*" "continuing to break1 #4"] {
+ gdb_suppress_tests;
+ }
+ if [gdb_test "print flags" ".*uc = 0 .*, s1 = 0, u1 = 0, s2 = 0, u2 = 1, s3 = 0, u3 = 0, s9 = 0, u9 = 0, sc = 0.*" "bitfield uniqueness (u2)"] {
+ gdb_suppress_tests;
+ }
+ if [gdb_test "cont" "Break.*break1 \\(\\) at .*$srcfile:$decimal.*" "continuing to break1 #5"] {
+ gdb_suppress_tests;
+ }
+ if [gdb_test "print flags" ".*uc = 0 .*, s1 = 0, u1 = 0, s2 = 0, u2 = 0, s3 = 1, u3 = 0, s9 = 0, u9 = 0, sc = 0.*" "bitfield uniqueness (s3)"] {
+ gdb_suppress_tests;
+ }
+ if [gdb_test "cont" "Break.*break1 \\(\\) at .*$srcfile:$decimal.*" "continuing to break1 #6"] {
+ gdb_suppress_tests;
+ }
+ if [gdb_test "print flags" ".*uc = 0 .*, s1 = 0, u1 = 0, s2 = 0, u2 = 0, s3 = 0, u3 = 1, s9 = 0, u9 = 0, sc = 0.*" "bitfield uniqueness (u3)"] {
+ gdb_suppress_tests
+ }
+ if [gdb_test "cont" "Break.*break1 \\(\\) at .*$srcfile:$decimal.*" "continuing to break1 #7"] {
+ gdb_suppress_tests
+ }
+ if [gdb_test "print flags" ".*uc = 0 .*, s1 = 0, u1 = 0, s2 = 0, u2 = 0, s3 = 0, u3 = 0, s9 = 1, u9 = 0, sc = 0.*" "bitfield uniqueness (s9)"] {
+ gdb_suppress_tests
+ }
+ if [gdb_test "cont" "Break.*break1 \\(\\) at .*$srcfile:$decimal.*" "continuing to break1 #8"] {
+ gdb_suppress_tests
+ }
+ if [gdb_test "print flags" ".*uc = 0 .*, s1 = 0, u1 = 0, s2 = 0, u2 = 0, s3 = 0, u3 = 0, s9 = 0, u9 = 1, sc = 0.*" "bitfield uniqueness (u9)"] {
+ gdb_suppress_tests
+ }
+ if [gdb_test "cont" "Break.*break1 \\(\\) at .*$srcfile:$decimal.*" "continuing to break1 #9"] {
+ gdb_suppress_tests
+ }
+ if [gdb_test "print flags" ".*uc = 0 .*, s1 = 0, u1 = 0, s2 = 0, u2 = 0, s3 = 0, u3 = 0, s9 = 0, u9 = 0, sc = 1.*" "bitfield uniqueness (sc)"] {
+ gdb_suppress_tests
+ }
+ # Hmmmm?
+ gdb_stop_suppressing_tests;
+}
+
+
+#
+# Test bitfield containment.
+# Fill alternating fields with all 1's and verify that none of the bits
+# "bleed over" to the other fields.
+#
+
+proc bitfield_containment {} {
+ global decimal
+ global hex
+ global gdb_prompt
+ global srcfile
+
+ delete_breakpoints
+
+ if { ![runto break2] } {
+ gdb_suppress_tests
+ }
+
+ if [gdb_test "print/x flags" "= {uc = 0xff, s1 = 0x0, u1 = 0x1, s2 = 0x0, u2 = 0x3, s3 = 0x0, u3 = 0x7, s9 = 0x0, u9 = 0x1ff, sc = 0x0}" "bitfield containment #1"] {
+ gdb_suppress_tests
+ }
+
+ if [gdb_test "cont" "Break.*break2 \\(\\) at .*$srcfile:$decimal.*" "continuing to break2"] {
+ gdb_suppress_tests
+ }
+
+ # If program is compiled with Sun CC, then these print out as their
+ # actual sizes; if compiled with gcc, they print out as 0xffffffff
+ # (which strikes me as bogus, but accept it at least for now).
+ if [gdb_test "print/x flags" "= {uc = 0x0, s1 = 0x(1|f*), u1 = 0x0, s2 = 0x(3|f*), u2 = 0x0, s3 = 0x(7|f*), u3 = 0x0, s9 = 0x(1ff|f*), u9 = 0x0, sc = 0xff}" "bitfield containment #2"] {
+ gdb_suppress_tests
+ }
+ gdb_stop_suppressing_tests;
+}
+
+# Test unsigned bitfields for unsignedness and range.
+# Fill the unsigned fields with the maximum positive value and verify that
+# the values are printed correctly.
+
+proc bitfield_unsignedness {} {
+ global decimal
+ global hex
+ global gdb_prompt
+ global srcfile
+
+ delete_breakpoints
+
+ if { ![runto break3] } {
+ gdb_suppress_tests
+ }
+
+ if [gdb_test "print flags" ".*uc = 0 .*, s1 = 0, u1 = 1, s2 = 0, u2 = 3, s3 = 0, u3 = 7, s9 = 0, u9 = 511, sc = 0.*" "unsigned bitfield ranges"] {
+ gdb_suppress_tests
+ }
+ gdb_stop_suppressing_tests;
+}
+
+#
+# Test signed bitfields for signedness and range.
+# Fill the signed fields with the maximum positive value, then the maximally
+# negative value, then -1, and verify in each case that the values are
+# printed correctly.
+#
+
+proc bitfield_signedness {} {
+ global decimal
+ global hex
+ global gdb_prompt
+ global srcfile
+
+ delete_breakpoints
+
+ if { ! [runto break4] } {
+ gdb_suppress_tests
+ }
+
+ if [gdb_test "print flags" "= {uc = 0 .*, s1 = 0, u1 = 0, s2 = 1, u2 = 0, s3 = 3, u3 = 0, s9 = 255, u9 = 0, sc = 0 .*}" "signed bitfields, max positive values"] {
+ gdb_suppress_tests
+ }
+
+ if [gdb_test "cont" "Break.*break4 \\(\\) at .*$srcfile:$decimal.*" "continuing to break4 #1"] {
+ gdb_suppress_tests
+ }
+
+ # Determine if the target has signed bitfields so we can xfail the
+ # the signed bitfield tests if it doesn't.
+ send_gdb "print i\n"
+ gdb_expect {
+ -re ".* = -256.*$gdb_prompt $" {
+ pass "determining signed-ness of bitfields"
+ }
+ -re ".* = 256.*$gdb_prompt $" {
+ pass "determining signed-ness of bitfields"
+ setup_xfail "*-*-*"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "determining signed-ness of bitfields"
+ gdb_suppress_tests
+ }
+ default {
+ fail "determining signed-ness of bitfields" ;
+ gdb_suppress_tests;
+ }
+ }
+
+ if [gdb_test "print flags" ".*uc = 0 .*, s1 = -1, u1 = 0, s2 = -2, u2 = 0, s3 = -4, u3 = 0, s9 = -256, u9 = 0, sc = 0.*" "signed bitfields, max negative values"] {
+ gdb_suppress_tests
+ }
+
+ if [gdb_test "cont" "Break.*break4 \\(\\) at .*$srcfile:$decimal.*" "continuing to break4 #2"] {
+ gdb_suppress_tests
+ }
+
+ if [gdb_test "print flags" ".*uc = 0 .*, s1 = -1, u1 = 0, s2 = -1, u2 = 0, s3 = -1, u3 = 0, s9 = -1, u9 = 0, sc = 0.*" "signed bitfields with -1"] {
+ gdb_suppress_tests
+ }
+ # Hmmmm???
+ gdb_stop_suppressing_tests;
+}
+
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+send_gdb "set print sevenbit-strings\n" ; gdb_expect -re "$gdb_prompt $"
+
+bitfield_uniqueness
+if [istarget "mips-idt-*"] then {
+ # Restart because IDT/SIM runs out of file descriptors.
+ gdb_exit
+ gdb_start
+ gdb_reinitialize_dir $srcdir/$subdir
+ gdb_load ${binfile}
+}
+bitfield_containment
+if [istarget "mips-idt-*"] then {
+ # Restart because IDT/SIM runs out of file descriptors.
+ gdb_exit
+ gdb_start
+ gdb_reinitialize_dir $srcdir/$subdir
+ gdb_load ${binfile}
+}
+bitfield_unsignedness
+if [istarget "mips-idt-*"] then {
+ # Restart because IDT/SIM runs out of file descriptors.
+ gdb_exit
+ gdb_start
+ gdb_reinitialize_dir $srcdir/$subdir
+ gdb_load ${binfile}
+}
+bitfield_signedness
diff --git a/gdb/testsuite/gdb.base/bitops.exp b/gdb/testsuite/gdb.base/bitops.exp
new file mode 100644
index 00000000000..f1c578ec75d
--- /dev/null
+++ b/gdb/testsuite/gdb.base/bitops.exp
@@ -0,0 +1,365 @@
+# Copyright (C) 1998 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file was written by Elena Zannoni (ezannoni@cygnus.com)
+
+# This file is part of the gdb testsuite
+#
+# tests expressions with bitwise operators, and some
+# logical operators
+# Does not use a target program
+#
+
+
+if $tracelevel then {
+ strace $tracelevel
+ }
+
+#
+# test running programs
+#
+set prms_id 0
+set bug_id 0
+
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+
+
+send_gdb "print !1\n"
+gdb_expect {
+ -re ".\[0-9\]* = 0.*$gdb_prompt $" {
+ pass "print value of !1"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of !1" }
+ timeout { fail "(timeout) print value of !1" }
+ }
+
+
+send_gdb "print !0\n"
+gdb_expect {
+ -re ".\[0-9\]* = 1.*$gdb_prompt $" {
+ pass "print value of !0"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of !0" }
+ timeout { fail "(timeout) print value of !0" }
+ }
+
+
+send_gdb "print !100\n"
+gdb_expect {
+ -re ".\[0-9\]* = 0.*$gdb_prompt $" {
+ pass "print value of !100"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of !100" }
+ timeout { fail "(timeout) print value of !100" }
+ }
+
+
+send_gdb "print !1000\n"
+gdb_expect {
+ -re ".\[0-9\]* = 0.*$gdb_prompt $" {
+ pass "print value of !1000"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of !1000" }
+ timeout { fail "(timeout) print value of !1000" }
+ }
+
+
+send_gdb "print !10\n"
+gdb_expect {
+ -re ".\[0-9\]* = 0.*$gdb_prompt $" {
+ pass "print value of !10"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of !10" }
+ timeout { fail "(timeout) print value of !10" }
+ }
+
+
+send_gdb "print !2\n"
+gdb_expect {
+ -re ".\[0-9\]* = 0.*$gdb_prompt $" {
+ pass "print value of !2 "
+ }
+ -re ".*$gdb_prompt $" { fail "print value of !2" }
+ timeout { fail "(timeout) print value of !2" }
+ }
+
+
+send_gdb "print 10 | 5\n"
+gdb_expect {
+ -re ".\[0-9\]* = 15.*$gdb_prompt $" {
+ pass "print value of 10 | 5"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of 10 | 5" }
+ timeout { fail "(timeout) print value of 10 | 5" }
+ }
+
+
+send_gdb "print 10 & 5\n"
+gdb_expect {
+ -re ".\[0-9\]* = 0.*$gdb_prompt $" {
+ pass "print value of 10 & 5"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of 10 & 5" }
+ timeout { fail "(timeout) print value of 10 & 5" }
+ }
+
+
+send_gdb "print 10 ^ 5\n"
+gdb_expect {
+ -re ".\[0-9\]* = 15.*$gdb_prompt $" {
+ pass "print value of 10 ^ 5"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of 10 ^ 5" }
+ timeout { fail "(timeout) print value of 10 ^ 5" }
+ }
+
+
+send_gdb "print -!0\n"
+gdb_expect {
+ -re ".\[0-9\]* = -1.*$gdb_prompt $" {
+ pass "print value of -!0"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of -!0" }
+ timeout { fail "(timeout) print value of -!0" }
+ }
+
+
+send_gdb "print ~-!0\n"
+gdb_expect {
+ -re ".\[0-9\]* = 0.*$gdb_prompt $" {
+ pass "print value of ~-!0"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of ~-!0" }
+ timeout { fail "(timeout) print value of ~-!0" }
+ }
+
+
+
+send_gdb "print 3 * 2 / 4.0 * 2.0\n"
+gdb_expect {
+ -re ".\[0-9\]* = 3.*$gdb_prompt $" {
+ pass "print value of 3 * 2 / 4.0 * 2.0"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of 3 * 2 / 4.0 * 2.0" }
+ timeout { fail "(timeout) print value of 3 * 2 / 4.0 * 2.0" }
+ }
+
+
+send_gdb "print 8 << 2 >> 4\n"
+gdb_expect {
+ -re ".\[0-9\]* = 2.*$gdb_prompt $" {
+ pass "print value of 8 << 2 >> 4"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of 8 << 2 >> 4" }
+ timeout { fail "(timeout) print value of 8 << 2 >> 4" }
+ }
+
+
+send_gdb "print -1 < 0 > 1\n"
+gdb_expect {
+ -re ".\[0-9\]* = 0.*$gdb_prompt $" {
+ pass "print value of -1 < 0 > 1"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of -1 < 0 > 1" }
+ timeout { fail "(timeout) print value of -1 < 0 > 1" }
+ }
+
+
+send_gdb "print 15 ^ 10 ^ 5 ^ 7\n"
+gdb_expect {
+ -re ".\[0-9\]* = 7.*$gdb_prompt $" {
+ pass "print value of 15 ^ 10 ^ 5 ^ 7"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of 15 ^ 10 ^ 5 ^ 7" }
+ timeout { fail "(timeout) print value of 15 ^ 10 ^ 5 ^ 7" }
+ }
+
+
+send_gdb "print 3.5 < 4.0\n"
+gdb_expect {
+ -re ".\[0-9\]* = 1.*$gdb_prompt $" {
+ pass "print value of 3.5 < 4.0"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of 3.5 < 4.0" }
+ timeout { fail "(timeout) print value of 3.5 < 4.0" }
+ }
+
+
+send_gdb "print 3.5 < -4.0\n"
+gdb_expect {
+ -re ".\[0-9\]* = 0.*$gdb_prompt $" {
+ pass "print value of 3.5 < -4.0"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of 3.5 < -4.0" }
+ timeout { fail "(timeout) print value of 3.5 < -4.0" }
+ }
+
+
+send_gdb "print 2 > -3\n"
+gdb_expect {
+ -re ".\[0-9\]* = 1.*$gdb_prompt $" {
+ pass "print value of 2 > -3"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of 2 > -3" }
+ timeout { fail "(timeout) print value of 2 > -3" }
+ }
+
+
+send_gdb "print -3>4\n"
+gdb_expect {
+ -re ".\[0-9\]* = 0.*$gdb_prompt $" {
+ pass "print value of -3>4"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of -3>4" }
+ timeout { fail "(timeout) print value of -3>4" }
+ }
+
+
+send_gdb "print (-3 > 4)\n"
+gdb_expect {
+ -re ".\[0-9\]* = 0.*$gdb_prompt $" {
+ pass "print value of (-3 > 4)"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of (-3 > 4)" }
+ timeout { fail "(timeout) print value of (-3 > 4)" }
+ }
+
+
+send_gdb "print 3>=2.5\n"
+gdb_expect {
+ -re ".\[0-9\]* = 1.*$gdb_prompt $" {
+ pass "print value of 3>=2.5"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of 3>=2.5" }
+ timeout { fail "(timeout) print value of 3>=2.5" }
+ }
+
+
+send_gdb "print 3>=4.5\n"
+gdb_expect {
+ -re ".\[0-9\]* = 0.*$gdb_prompt $" {
+ pass "print value of 3>=4.5"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of 3>=4.5" }
+ timeout { fail "(timeout) print value of 3>=4.5" }
+ }
+
+
+send_gdb "print 3==3.0\n"
+gdb_expect {
+ -re ".\[0-9\]* = 1.*$gdb_prompt $" {
+ pass "print value of 3==3.0"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of 3==3.0" }
+ timeout { fail "(timeout) print value of 3==3.0" }
+ }
+
+
+send_gdb "print 3==4.0\n"
+gdb_expect {
+ -re ".\[0-9\]* = 0.*$gdb_prompt $" {
+ pass "print value of 3==4.0"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of 3==4.0" }
+ timeout { fail "(timeout) print value of 3==4.0" }
+ }
+
+
+send_gdb "print 3!=3.0\n"
+gdb_expect {
+ -re ".\[0-9\]* = 0.*$gdb_prompt $" {
+ pass "print value of 3!=3.0"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of 3!=3.0" }
+ timeout { fail "(timeout) print value of 3!=3.0" }
+ }
+
+
+send_gdb "print 3!=5.0\n"
+gdb_expect {
+ -re ".\[0-9\]* = 1.*$gdb_prompt $" {
+ pass "print value of 3!=5.0"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of 3!=5.0" }
+ timeout { fail "(timeout) print value of 3!=5.0" }
+ }
+
+
+send_gdb "print 0 || 1 && 0 | 0 ^ 0 == 8 > 128 >>1 +2 *2\n"
+gdb_expect {
+ -re ".\[0-9\]* = 0.*$gdb_prompt $" {
+ pass "print value of 0 || 1 && 0 | 0 ^ 0 == 8 > 128 >>1 +2 *2"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of 0 || 1 && 0 | 0 ^ 0 == 8 > 128 >>1 +2 *2" }
+ timeout { fail "(timeout) print value of 0 || 1 && 0 | 0 ^ 0 == 8 > 128 >>1 +2 *2" }
+ }
+
+
+send_gdb "print 1.0 || 0\n"
+gdb_expect {
+ -re ".\[0-9\]* = 1.*$gdb_prompt $" {
+ pass "print value of 1.0 || 0"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of 1.0 || 0" }
+ timeout { fail "(timeout) print value of 1.0 || 0" }
+ }
+
+
+send_gdb "print 0.0 || 1.0\n"
+gdb_expect {
+ -re ".\[0-9\]* = 1.*$gdb_prompt $" {
+ pass "print value of 0.0 || 1.0"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of 0.0 || 1.0" }
+ timeout { fail "(timeout) print value of 0.0 || 1.0" }
+ }
+
+
+send_gdb "print 0.0 || 0\n"
+gdb_expect {
+ -re ".\[0-9\]* = 0.*$gdb_prompt $" {
+ pass "print value of 0.0 || 0"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of 0.0 || 0" }
+ timeout { fail "(timeout) print value of 0.0 || 0" }
+ }
+
+
+send_gdb "print 0 || 1 && 0 | 0 ^ 0 == 8\n"
+gdb_expect {
+ -re ".\[0-9\]* = 0.*$gdb_prompt $" {
+ pass "print value of 0 || 1 && 0 | 0 ^ 0 == 8"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of 0 || 1 && 0 | 0 ^ 0 == 8" }
+ timeout { fail "(timeout) print value of 0 || 1 && 0 | 0 ^ 0 == 8" }
+ }
+
+
+send_gdb "print 0 == 8 > 128 >> 1 + 2 * 2\n"
+gdb_expect {
+ -re ".\[0-9\]* = 0.*$gdb_prompt $" {
+ pass "print value of 0 == 8 > 128 >> 1 + 2 * 2"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of 0 == 8 > 128 >> 1 + 2 * 2" }
+ timeout { fail "(timeout) print value of 0 == 8 > 128 >> 1 + 2 * 2" }
+ }
+
diff --git a/gdb/testsuite/gdb.base/branches.c b/gdb/testsuite/gdb.base/branches.c
new file mode 100644
index 00000000000..df3b7c052be
--- /dev/null
+++ b/gdb/testsuite/gdb.base/branches.c
@@ -0,0 +1,113 @@
+/* Tests for single stepping through various branch conditions */
+
+int noscramble(int a)
+{
+ return a ;
+}
+
+int echo(int a)
+{ return noscramble(a) ; }
+
+int equaltest(int a,int b)
+{ int retval ;
+ if (a == b)
+ retval = noscramble(1) ;
+ else retval = noscramble(0) ;
+ return retval ;
+}
+
+int neqtest(int a , int b)
+{ int retval ;
+ if (a != b)
+ retval = echo(1) ;
+ else retval = echo(2) ;
+ return retval ;
+}
+int zerotest(int a )
+{ int retval ;
+ a = echo(a) ;
+ if (a ==0)
+ retval = echo(1) ;
+ else
+ retval = echo(0) ;
+ retval = echo(retval) ;
+ return retval ;
+}
+
+int zerotest2(int a)
+{
+ return (a==0) ;
+}
+
+int nonzerotest(int a)
+{
+ int retval ;
+ if (a != 0)
+ retval = echo(0) ;
+ else retval = echo(1) ;
+ return retval ;
+}
+
+int whiletest(int a)
+{
+ while (a > 0)
+ {
+ a-- ;
+ }
+ return 0 ;
+}
+int whiletest2(int a)
+{
+ while (a > 0)
+ {
+ a = noscramble(a) ;
+ a-- ;
+ }
+ return a ;
+}
+
+int decr(int x) { return x - 1 ; }
+
+int while3(int a)
+{
+ int b = a ;
+ while (a == b)
+ {
+ a = echo(a) ;
+ b = decr(b) ;
+ }
+ return a ;
+}
+
+void done (int x) { }
+
+int main()
+{
+ int a,b,c,d ;
+ done(1) ;
+ a = echo(123456) ;
+ b = echo(123456) ;
+ c = echo(56789) ;
+ d = echo(0) ;
+#if 1
+ equaltest(a,b) ;
+ done(7) ;
+ equaltest(a,c) ;
+ done(8) ;
+ whiletest(3) ; /* worked */
+ done(3) ;
+ while3(3) ;
+ done(6) ;
+#endif
+ neqtest(a,b) ;
+ neqtest(a,b) ;
+ neqtest(a,c) ;
+ zerotest(d) ;
+ zerotest(a) ;
+ done(5) ;
+ nonzerotest(d) ;
+ done(4) ;
+ nonzerotest(a) ;
+ done(111) ;
+ return 1 ;
+}
diff --git a/gdb/testsuite/gdb.base/break.c b/gdb/testsuite/gdb.base/break.c
new file mode 100644
index 00000000000..491d6e5dd5d
--- /dev/null
+++ b/gdb/testsuite/gdb.base/break.c
@@ -0,0 +1,81 @@
+#ifdef vxworks
+
+# include <stdio.h>
+
+/* VxWorks does not supply atoi. */
+static int
+atoi (z)
+ char *z;
+{
+ int i = 0;
+
+ while (*z >= '0' && *z <= '9')
+ i = i * 10 + (*z++ - '0');
+ return i;
+}
+
+/* I don't know of any way to pass an array to VxWorks. This function
+ can be called directly from gdb. */
+
+vxmain (arg)
+char *arg;
+{
+ char *argv[2];
+
+ argv[0] = "";
+ argv[1] = arg;
+ main (2, argv, (char **) 0);
+}
+
+#else /* ! vxworks */
+# include <stdio.h>
+#endif /* ! vxworks */
+
+/*
+ * The following functions do nothing useful. They are included simply
+ * as places to try setting breakpoints at. They are explicitly
+ * "one-line functions" to verify that this case works (some versions
+ * of gcc have or have had problems with this).
+ */
+
+int marker1 () { return (0); }
+int marker2 (a) int a; { return (1); }
+void marker3 (a, b) char *a, *b; {}
+void marker4 (d) long d; {}
+
+/*
+ * This simple classical example of recursion is useful for
+ * testing stack backtraces and such.
+ */
+
+int
+main (argc, argv, envp)
+int argc;
+char *argv[], **envp;
+{
+#ifdef usestubs
+ set_debug_traps();
+ breakpoint();
+#endif
+ if (argc == 123456) {
+ fprintf (stderr, "usage: factorial <number>\n");
+ return 1;
+ }
+ printf ("%d\n", factorial (atoi ("6")));
+
+ marker1 ();
+ marker2 (43);
+ marker3 ("stack", "trace");
+ marker4 (177601976L);
+ return 0;
+}
+
+int factorial (value)
+int value;
+{
+ if (value > 1) {
+ value *= factorial (value - 1);
+ }
+ return (value);
+}
+
diff --git a/gdb/testsuite/gdb.base/break.exp b/gdb/testsuite/gdb.base/break.exp
new file mode 100644
index 00000000000..b8f1d7f8fcb
--- /dev/null
+++ b/gdb/testsuite/gdb.base/break.exp
@@ -0,0 +1,769 @@
+# Copyright (C) 1988, 1990, 1991, 1992, 1994, 1997, 1998
+# Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file was written by Rob Savoye. (rob@cygnus.com)
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+
+#
+# test running programs
+#
+set prms_id 0
+set bug_id 0
+
+set testfile "break"
+set srcfile ${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug additional_flags=-w}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+if [target_info exists gdb_stub] {
+ gdb_step_for_stub;
+}
+#
+# test simple breakpoint setting commands
+#
+
+# Test deleting all breakpoints when there are none installed,
+# GDB should not prompt for confirmation.
+# Note that gdb-init.exp provides a "delete_breakpoints" proc
+# for general use elsewhere.
+
+send_gdb "delete breakpoints\n"
+gdb_expect {
+ -re "Delete all breakpoints.*$" {
+ send_gdb "y\n"
+ gdb_expect {
+ -re "$gdb_prompt $" {
+ fail "Delete all breakpoints when none (unexpected prompt)"
+ }
+ timeout { fail "Delete all breakpoints when none (timeout after unexpected prompt)" }
+ }
+ }
+ -re ".*$gdb_prompt $" { pass "Delete all breakpoints when none" }
+ timeout { fail "Delete all breakpoints when none (timeout)" }
+}
+
+#
+# test break at function
+#
+gdb_test "break main" \
+ "Breakpoint.*at.* file .*$srcfile, line.*" \
+ "breakpoint function"
+
+#
+# test break at function in file
+#
+gdb_test "break $srcfile:factorial" \
+ "Breakpoint.*at.* file .*$srcfile, line.*" \
+ "breakpoint function in file"
+
+#
+# test break at line number
+#
+gdb_test "break 64" \
+ "Breakpoint.*at.* file .*$srcfile, line 64\\." \
+ "breakpoint line number"
+
+#
+# test duplicate breakpoint
+#
+gdb_test "break 64" \
+ "Note: breakpoint \[0-9\]+ also set at pc.*Breakpoint \[0-9\]+ at.* file .*$srcfile, line 64\\." \
+ "breakpoint duplicate"
+
+#
+# test break at line number in file
+#
+gdb_test "break $srcfile:70" \
+ "Breakpoint.*at.* file .*$srcfile, line 70\\." \
+ "breakpoint line number in file"
+
+
+#
+# check to see what breakpoints are set
+#
+if [target_info exists gdb_stub] {
+ set main_line 57
+} else {
+ set main_line 60
+}
+
+gdb_test "info break" \
+ "Num Type\[ \]+Disp Enb Address\[ \]+What.*
+\[0-9\]+\[\t \]+breakpoint keep y.* in main at .*$srcfile:$main_line.*
+\[0-9\]+\[\t \]+breakpoint keep y.* in factorial at .*$srcfile:76.*
+\[0-9\]+\[\t \]+breakpoint keep y.* in main at .*$srcfile:64.*
+\[0-9\]+\[\t \]+breakpoint keep y.* in main at .*$srcfile:64.*
+\[0-9\]+\[\t \]+breakpoint keep y.* in main at .*$srcfile:70" \
+ "breakpoint info"
+
+
+# FIXME: The rest of this test doesn't work with anything that can't
+# handle arguments.
+# Huh? There doesn't *appear* to be anything that passes arguments
+# below.
+if [istarget "mips-idt-*"] then {
+ return
+}
+
+#
+# run until the breakpoint at main is hit. For non-stubs-using targets.
+#
+if ![target_info exists use_gdb_stub] {
+ if [istarget "*-*-vxworks*"] then {
+ send_gdb "run vxmain \"2\"\n"
+ set timeout 120
+ verbose "Timeout is now $timeout seconds" 2
+ } else {
+ send_gdb "run\n"
+ }
+ gdb_expect {
+ -re "The program .* has been started already.*y or n. $" {
+ send_gdb "y\n"
+ exp_continue
+ }
+ -re "Starting program.*Breakpoint \[0-9\]+,.*main .*argc.*argv.* at .*$srcfile:60.*60\[\t \]+if .argc.* \{.*$gdb_prompt $"\
+ { pass "run until function breakpoint" }
+ -re ".*$gdb_prompt $" { fail "run until function breakpoint" }
+ timeout { fail "run until function breakpoint (timeout)" }
+ }
+} else {
+ if ![target_info exists gdb_stub] {
+ gdb_test continue "Continuing\\..*Breakpoint \[0-9\]+, main \\(argc=.*, argv=.*, envp=.*\\) at .*$srcfile:60.*60\[\t \]+if .argc.*\{" "stub continue"
+ }
+}
+
+#
+# run until the breakpoint at a line number
+#
+gdb_test continue "Continuing\\..*Breakpoint \[0-9\]+, main \\(argc=.*, argv=.*, envp=.*\\) at .*$srcfile:64.*64\[\t \]+printf.*factorial.*" \
+ "run until breakpoint set at a line number"
+
+#
+# Run until the breakpoint set in a function in a file
+#
+for {set i 6} {$i >= 1} {incr i -1} {
+ gdb_test continue "Continuing\\..*Breakpoint \[0-9\]+, factorial \\(value=$i\\) at .*$srcfile:76.*76\[\t \]+if .value > 1. \{" \
+ "run until file:function($i) breakpoint"
+}
+
+#
+# run until the file:function breakpoint at a line number in a file
+#
+gdb_test continue "Continuing\\..*Breakpoint \[0-9\]+, main \\(argc=.*, argv=.*, envp=.*\\) at .*$srcfile:70.*70\[\t \]+return 0;" \
+ "run until file:linenum breakpoint"
+
+#
+# delete all breakpoints so we can start over, course this can be a test too
+#
+delete_breakpoints
+
+#
+# test temporary breakpoint at function
+#
+
+gdb_test "tbreak main" "Breakpoint.*at.* file .*$srcfile, line.*" "Temporary breakpoint function"
+
+#
+# test break at function in file
+#
+
+gdb_test "tbreak $srcfile:factorial" "Breakpoint.*at.* file .*$srcfile, line.*" \
+ "Temporary breakpoint function in file"
+
+#
+# test break at line number
+#
+send_gdb "tbreak 64\n"
+gdb_expect {
+ -re "Breakpoint.*at.* file .*$srcfile, line 64.*$gdb_prompt $" { pass "Temporary breakpoint line number #1" }
+ -re ".*$gdb_prompt $" { pass "Temporary breakpoint line number #1" }
+ timeout { fail "breakpoint line number #1 (timeout)" }
+}
+
+gdb_test "tbreak 60" "Breakpoint.*at.* file .*$srcfile, line 60.*" "Temporary breakpoint line number #2"
+
+#
+# test break at line number in file
+#
+send_gdb "tbreak $srcfile:70\n"
+gdb_expect {
+ -re "Breakpoint.*at.* file .*$srcfile, line 70.*$gdb_prompt $" { pass "Temporary breakpoint line number in file #1" }
+ -re ".*$gdb_prompt $" { pass "Temporary breakpoint line number in file #1" }
+ timeout { fail "Temporary breakpoint line number in file #1 (timeout)" }
+}
+
+gdb_test "tbreak $srcfile:66" "Breakpoint.*at.* file .*$srcfile, line 66.*" "Temporary breakpoint line number in file #2"
+
+#
+# check to see what breakpoints are set (temporary this time)
+#
+gdb_test "info break" "Num Type.*Disp Enb Address.*What.*\[\r\n\]\[0-9\]+\[\t \]+breakpoint del.*y.*in main at .*$srcfile:$main_line.*\[\r\n\]\[0-9\]+\[\t \]+breakpoint del.*y.*in factorial at .*$srcfile:76.*\[\r\n\]\[0-9\]+\[\t \]+breakpoint del.*y.*in main at .*$srcfile:64.*\[\r\n\]\[0-9\]+\[\t \]+breakpoint del.*y.*in main at .*$srcfile:70.*" "Temporary breakpoint info"
+
+
+#***********
+
+# Verify that catchpoints for fork, vfork and exec don't trigger
+# inappropriately. (There are no calls to those system functions
+# in this test program.)
+#
+if ![runto_main] then { fail "break tests suppressed" }
+
+send_gdb "catch\n"
+gdb_expect {
+ -re "Catch requires an event name.*$gdb_prompt $"\
+ {pass "catch requires an event name"}
+ -re "$gdb_prompt $"\
+ {fail "catch requires an event name"}
+ timeout {fail "(timeout) catch requires an event name"}
+}
+
+
+set name "set catch fork, never expected to trigger"
+send_gdb "catch fork\n"
+gdb_expect {
+ -re "Catchpoint \[0-9\]* .fork..*$gdb_prompt $"
+ {pass $name}
+ -re "Catch of fork not yet implemented.*$gdb_prompt $"
+ {pass $name}
+ -re "$gdb_prompt $"
+ {fail $name}
+ timeout {fail "(timeout) $name"}
+}
+
+
+set name "set catch vfork, never expected to trigger"
+send_gdb "catch vfork\n"
+
+# If we are on HP-UX 10.20, we expect an error message to be
+# printed if we type "catch vfork" at the gdb gdb_prompt. This is
+# because on HP-UX 10.20, we cannot catch vfork events.
+
+if [istarget "hppa*-hp-hpux10.20"] then {
+ gdb_expect {
+ -re "Catch of vfork events not supported on HP-UX 10.20..*$gdb_prompt $"
+ {pass $name}
+ -re "$gdb_prompt $"
+ {fail $name}
+ timeout {fail "(timeout) $name"}
+ }
+} else {
+ gdb_expect {
+ -re "Catchpoint \[0-9\]* .vfork..*$gdb_prompt $"
+ {pass $name}
+ -re "Catch of vfork not yet implemented.*$gdb_prompt $"
+ {pass $name}
+ -re "$gdb_prompt $"
+ {fail $name}
+ timeout {fail "(timeout) $name"}
+ }
+}
+
+set name "set catch exec, never expected to trigger"
+send_gdb "catch exec\n"
+gdb_expect {
+ -re "Catchpoint \[0-9\]* .exec..*$gdb_prompt $"
+ {pass $name}
+ -re "Catch of exec not yet implemented.*$gdb_prompt $"
+ {pass $name}
+ -re "$gdb_prompt $" {fail $name}
+ timeout {fail "(timeout) $name"}
+}
+
+# Verify that "until <location>" works. (This is really just syntactic
+# sugar for "tbreak <location>; continue".)
+#
+send_gdb "until 64\n"
+gdb_expect {
+ -re "main .* at .*:64.*$gdb_prompt $"\
+ {pass "until 64"}
+ -re "$gdb_prompt $"\
+ {fail "until 64"}
+ timeout {fail "(timeout) until 64"}
+}
+
+# Verify that a malformed "until" is gracefully caught.
+#
+send_gdb "until 65 then stop\n"
+gdb_expect {
+ -re "Junk at end of arguments..*$gdb_prompt $"\
+ {pass "malformed until"}
+ -re "$gdb_prompt $"\
+ {fail "malformed until"}
+ timeout {fail "(timeout) malformed until"}
+}
+
+# Verify that GDB responds gracefully when asked to set a breakpoint
+# on a nonexistent source line.
+#
+send_gdb "break 999\n"
+gdb_expect {
+ -re "No line 999 in file .*$gdb_prompt $"\
+ {pass "break on non-existent source line"}
+ -re "$gdb_prompt $"\
+ {fail "break on non-existent source line"}
+ timeout {fail "(timeout) break on non-existent source line"}
+}
+
+# Verify that GDB allows one to just say "break", which is treated
+# as the "default" breakpoint. Note that GDB gets cute when printing
+# the informational message about other breakpoints at the same
+# location. We'll hit that bird with this stone too.
+#
+send_gdb "break\n"
+gdb_expect {
+ -re "Breakpoint \[0-9\]*.*$gdb_prompt $"\
+ {pass "break on default location, 1st time"}
+ -re "$gdb_prompt $"\
+ {fail "break on default location, 1st time"}
+ timeout {fail "(timeout) break on default location, 1st time"}
+}
+
+send_gdb "break\n"
+gdb_expect {
+ -re "Note: breakpoint \[0-9\]* also set at .*Breakpoint \[0-9\]*.*$gdb_prompt $"\
+ {pass "break on default location, 2nd time"}
+ -re "$gdb_prompt $"\
+ {fail "break on default location, 2nd time"}
+ timeout {fail "(timeout) break on default location, 2nd time"}
+}
+
+send_gdb "break\n"
+gdb_expect {
+ -re "Note: breakpoints \[0-9\]* and \[0-9\]* also set at .*Breakpoint \[0-9\]*.*$gdb_prompt $"\
+ {pass "break on default location, 3rd time"}
+ -re "$gdb_prompt $"\
+ {fail "break on default location, 3rd time"}
+ timeout {fail "(timeout) break on default location, 3rd time"}
+}
+
+send_gdb "break\n"
+gdb_expect {
+ -re "Note: breakpoints \[0-9\]*, \[0-9\]* and \[0-9\]* also set at .*Breakpoint \[0-9\]*.*$gdb_prompt $"\
+ {pass "break on default location, 4th time"}
+ -re "$gdb_prompt $"\
+ {fail "break on default location, 4th time"}
+ timeout {fail "(timeout) break on default location, 4th time"}
+}
+
+# Verify that a "silent" breakpoint can be set, and that GDB is indeed
+# "silent" about its triggering.
+#
+if ![runto_main] then { fail "break tests suppressed" }
+
+send_gdb "break 64\n"
+gdb_expect {
+ -re "Breakpoint (\[0-9\]*) at .*, line 64.*$gdb_prompt $"\
+ {pass "set to-be-silent break 64"}
+ -re "$gdb_prompt $"\
+ {fail "set to-be-silent break 64"}
+ timeout {fail "(timeout) set to-be-silent break 64"}
+}
+
+send_gdb "commands $expect_out(1,string)\n"
+send_gdb "silent\n"
+send_gdb "end\n"
+gdb_expect {
+ -re ".*$gdb_prompt $"\
+ {pass "set silent break 64"}
+ timeout {fail "(timeout) set silent break 64"}
+}
+
+send_gdb "info break $expect_out(1,string)\n"
+gdb_expect {
+ -re "\[0-9\]*\[ \t\]*breakpoint.*:64\r\n\[ \t\]*silent.*$gdb_prompt $"\
+ {pass "info silent break 64"}
+ -re "$gdb_prompt $"\
+ {fail "info silent break 64"}
+ timeout {fail "(timeout) info silent break 64"}
+}
+send_gdb "continue\n"
+gdb_expect {
+ -re "Continuing.\r\n$gdb_prompt $"\
+ {pass "hit silent break 64"}
+ -re "$gdb_prompt $"\
+ {fail "hit silent break 64"}
+ timeout {fail "(timeout) hit silent break 64"}
+}
+send_gdb "bt\n"
+gdb_expect {
+ -re "#0 main .* at .*:64.*$gdb_prompt $"\
+ {pass "stopped for silent break 64"}
+ -re "$gdb_prompt $"\
+ {fail "stopped for silent break 64"}
+ timeout {fail "(timeout) stopped for silent break 64"}
+}
+
+# Verify that GDB can at least parse a breakpoint with the
+# "thread" keyword. (We won't attempt to test here that a
+# thread-specific breakpoint really triggers appropriately.
+# The gdb.threads subdirectory contains tests for that.)
+#
+send_gdb "break 65 thread 999\n"
+gdb_expect {
+ -re "Unknown thread 999.*$gdb_prompt $"\
+ {pass "thread-specific breakpoint on non-existent thread disallowed"}
+ -re "$gdb_prompt $"\
+ {fail "thread-specific breakpoint on non-existent thread disallowed"}
+ timeout {fail "(timeout) thread-specific breakpoint on non-existent thread disallowed"}
+}
+send_gdb "break 65 thread foo\n"
+gdb_expect {
+ -re "Junk after thread keyword..*$gdb_prompt $"\
+ {pass "thread-specific breakpoint on bogus thread ID disallowed"}
+ -re "$gdb_prompt $"\
+ {fail "thread-specific breakpoint on bogus thread ID disallowed"}
+ timeout {fail "(timeout) thread-specific breakpoint on bogus thread ID disallowed"}
+}
+
+# Verify that GDB responds gracefully to a breakpoint command with
+# trailing garbage.
+#
+send_gdb "break 65 foo\n"
+gdb_expect {
+ -re "Junk at end of arguments..*$gdb_prompt $"\
+ {pass "breakpoint with trailing garbage disallowed"}
+ -re "$gdb_prompt $"\
+ {fail "breakpoint with trailing garbage disallowed"}
+ timeout {fail "(timeout) breakpoint with trailing garbage disallowed"}
+}
+
+# Verify that GDB responds gracefully to a "clear" command that has
+# no matching breakpoint. (First, get us off the current source line,
+# which we know has a breakpoint.)
+#
+send_gdb "next\n"
+gdb_expect {
+ -re ".*$gdb_prompt $"\
+ {pass "step over breakpoint"}
+ timeout {fail "(timeout) step over breakpoint"}
+}
+send_gdb "clear 66\n"
+gdb_expect {
+ -re "No breakpoint at 66..*$gdb_prompt $"\
+ {pass "clear line has no breakpoint disallowed"}
+ -re "$gdb_prompt $"\
+ {fail "clear line has no breakpoint disallowed"}
+ timeout {fail "(timeout) clear line has no breakpoint disallowed"}
+}
+send_gdb "clear\n"
+gdb_expect {
+ -re "No breakpoint at this line..*$gdb_prompt $"\
+ {pass "clear current line has no breakpoint disallowed"}
+ -re "$gdb_prompt $"\
+ {fail "clear current line has no breakpoint disallowed"}
+ timeout {fail "(timeout) clear current line has no breakpoint disallowed"}
+}
+
+# Verify that a breakpoint can be set via a convenience variable.
+#
+send_gdb "set \$foo=66\n"
+gdb_expect {
+ -re "$gdb_prompt $"\
+ {pass "set convenience variable \$foo to 66"}
+ timeout {fail "(timeout) set convenience variable \$foo to 66"}
+}
+send_gdb "break \$foo\n"
+gdb_expect {
+ -re "Breakpoint (\[0-9\]*) at .*, line 66.*$gdb_prompt $"\
+ {pass "set breakpoint via convenience variable"}
+ -re "$gdb_prompt $"\
+ {fail "set breakpoint via convenience variable"}
+ timeout {fail "(timeout) set breakpoint via convenience variable"}
+}
+
+# Verify that GDB responds gracefully to an attempt to set a
+# breakpoint via a convenience variable whose type is not integer.
+#
+send_gdb "set \$foo=66.5\n"
+gdb_expect {
+ -re "$gdb_prompt $"\
+ {pass "set convenience variable \$foo to 66.5"}
+ timeout {fail "(timeout) set convenience variable \$foo to 66.5"}
+}
+send_gdb "break \$foo\n"
+gdb_expect {
+ -re "Convenience variables used in line specs must have integer values..*$gdb_prompt $"\
+ {pass "set breakpoint via non-integer convenience variable disallowed"}
+ -re "$gdb_prompt $"\
+ {fail "set breakpoint via non-integer convenience variable disallowed"}
+ timeout {fail "(timeout) set breakpoint via non-integer convenience variable disallowed"}
+}
+
+# Verify that we can set and trigger a breakpoint in a user-called function.
+#
+send_gdb "break marker2\n"
+gdb_expect {
+ -re "Breakpoint (\[0-9\]*) at .*, line 42.*$gdb_prompt $"\
+ {pass "set breakpoint on to-be-called function"}
+ -re "$gdb_prompt $"\
+ {fail "set breakpoint on to-be-called function"}
+ timeout {fail "(timeout) set breakpoint on to-be-called function"}
+}
+send_gdb "print marker2(99)\n"
+gdb_expect {
+ -re "The program being debugged stopped while in a function called from GDB.\r\nWhen the function .marker2. is done executing, GDB will silently\r\nstop .instead of continuing to evaluate the expression containing\r\nthe function call...*$gdb_prompt $"\
+ {pass "hit breakpoint on called function"}
+ -re "$gdb_prompt $"\
+ {fail "hit breakpoint on called function"}
+ timeout {fail "(timeout) hit breakpoint on called function"}
+}
+
+# As long as we're stopped (breakpointed) in a called function,
+# verify that we can successfully backtrace & such from here.
+#
+if [istarget "hppa*-*-hpux*"] then {
+ send_gdb "bt\n"
+ gdb_expect {
+ -re "#0\[ \t\]*marker2.*:42\r\n#1.*_sr4export.*$gdb_prompt $"\
+ {pass "backtrace while in called function"}
+ -re "$gdb_prompt $"\
+ {fail "backtrace while in called function"}
+ timeout {fail "(timeout) backtrace while in called function"}
+ }
+ send_gdb "finish\n"
+ gdb_expect {
+ -re "Run till exit from .*marker2.* at .*42\r\n.* in _sr4export.*$gdb_prompt $"\
+ {pass "finish from called function"}
+ -re "$gdb_prompt $"\
+ {fail "finish from called function"}
+ timeout {fail "(timeout) finish from called function"}
+ }
+}
+
+# Verify that GDB responds gracefully to a "finish" command with
+# arguments.
+#
+if ![runto_main] then { fail "break tests suppressed" }
+
+send_gdb "finish 123\n"
+gdb_expect {
+ -re "The \"finish\" command does not take any arguments.\r\n$gdb_prompt $"\
+ {pass "finish with arguments disallowed"}
+ -re "$gdb_prompt $"\
+ {fail "finish with arguments disallowed"}
+ timeout {fail "(timeout) finish with arguments disallowed"}
+}
+
+# Verify that GDB responds gracefully to a request to "finish" from
+# the outermost frame.
+#
+send_gdb "finish\n"
+gdb_expect {
+ -re "\"finish\" not meaningful in the outermost frame.\r\n$gdb_prompt $"\
+ {pass "finish from outermost frame disallowed"}
+ -re "$gdb_prompt $"\
+ {fail "finish from outermost frame disallowed"}
+ timeout {fail "(timeout) finish from outermost frame disallowed"}
+}
+
+# Verify that we can explicitly ask GDB to stop on all shared library
+# events, and that it does so.
+#
+if [istarget "hppa*-*-hpux*"] then {
+ if ![runto_main] then { fail "break tests suppressed" }
+
+ send_gdb "set stop-on-solib-events 1\n"
+ gdb_expect {
+ -re "$gdb_prompt $"\
+ {pass "set stop-on-solib-events"}
+ timeout {fail "(timeout) set stop-on-solib-events"}
+ }
+
+ send_gdb "run\n"
+ gdb_expect {
+ -re ".*Start it from the beginning.*y or n. $"\
+ {send_gdb "y\n"
+ gdb_expect {
+ -re ".*Stopped due to shared library event.*$gdb_prompt $"\
+ {pass "triggered stop-on-solib-events"}
+ -re "$gdb_prompt $"\
+ {fail "triggered stop-on-solib-events"}
+ timeout {fail "(timeout) triggered stop-on-solib-events"}
+ }
+ }
+ -re "$gdb_prompt $"\
+ {fail "rerun for stop-on-solib-events"}
+ timeout {fail "(timeout) rerun for stop-on-solib-events"}
+ }
+
+ send_gdb "set stop-on-solib-events 0\n"
+ gdb_expect {
+ -re "$gdb_prompt $"\
+ {pass "reset stop-on-solib-events"}
+ timeout {fail "(timeout) reset stop-on-solib-events"}
+ }
+}
+
+# Hardware breakpoints are unsupported on HP-UX. Verify that GDB
+# gracefully responds to requests to create them.
+#
+if [istarget "hppa*-*-hpux*"] then {
+ if ![runto_main] then { fail "break tests suppressed" }
+
+ send_gdb "hbreak\n"
+ gdb_expect {
+ -re "No hardware breakpoint support in the target.*$gdb_prompt $"\
+ {pass "hw breaks disallowed"}
+ -re "$gdb_prompt $"\
+ {fail "hw breaks disallowed"}
+ timeout {fail "(timeout) hw breaks disallowed"}
+ }
+
+ send_gdb "thbreak\n"
+ gdb_expect {
+ -re "No hardware breakpoint support in the target.*$gdb_prompt $"\
+ {pass "temporary hw breaks disallowed"}
+ -re "$gdb_prompt $"\
+ {fail "temporary hw breaks disallowed"}
+ timeout {fail "(timeout) temporary hw breaks disallowed"}
+ }
+}
+
+#********
+
+
+proc test_clear_command {} {
+ gdb_test "break main" "Breakpoint.*at.*" "break main #1"
+ gdb_test "break main" "Breakpoint.*at.*" "break main #2"
+
+ # We don't test that it deletes the correct breakpoints. We do at
+ # least test that it deletes more than one breakpoint.
+ gdb_test "clear main" {Deleted breakpoints [0-9]+ [0-9]+.*}
+}
+
+#
+# Test "next" over recursive function call.
+#
+
+proc test_next_with_recursion {} {
+ global gdb_prompt
+ global decimal
+ global binfile
+
+ if [target_info exists use_gdb_stub] {
+ # Reload the program.
+ delete_breakpoints
+ gdb_load ${binfile};
+ } else {
+ # FIXME: should be using runto
+ gdb_test "kill" "" "kill program" "Kill the program being debugged.*y or n. $" "y"
+
+ delete_breakpoints
+ }
+
+ gdb_test "break factorial" "Breakpoint $decimal at .*" "break at factorial"
+
+ # Run until we call factorial with 6
+
+ if [istarget "*-*-vxworks*"] then {
+ send_gdb "run vxmain \"6\"\n"
+ } else {
+ gdb_run_cmd
+ }
+ gdb_expect {
+ -re "Break.* factorial .value=6. .*$gdb_prompt $" {}
+ -re ".*$gdb_prompt $" {
+ fail "run to factorial(6)";
+ gdb_suppress_tests;
+ }
+ timeout { fail "run to factorial(6) (timeout)" ; gdb_suppress_tests }
+ }
+
+ # Continue until we call factorial recursively with 5.
+
+ if [gdb_test "continue" \
+ "Continuing.*Break.* factorial .value=5. .*" \
+ "continue to factorial(5)"] then { gdb_suppress_tests }
+
+ # Do a backtrace just to confirm how many levels deep we are.
+
+ if [gdb_test "backtrace" \
+ "#0\[ \t\]+ factorial .value=5..*" \
+ "backtrace from factorial(5)"] then { gdb_suppress_tests }
+
+ # Now a "next" should position us at the recursive call, which
+ # we will be performing with 4.
+
+ if [gdb_test "next" \
+ ".* factorial .value - 1.;.*" \
+ "next to recursive call"] then { gdb_suppress_tests }
+
+ # Disable the breakpoint at the entry to factorial by deleting them all.
+ # The "next" should run until we return to the next line from this
+ # recursive call to factorial with 4.
+ # Buggy versions of gdb will stop instead at the innermost frame on
+ # the line where we are trying to "next" to.
+
+ delete_breakpoints
+
+ if [istarget "mips*tx39-*"] {
+ set timeout 60
+ } else {
+ set timeout 20
+ }
+
+ gdb_test next "\[0-9\]*\[\t \]+return \\(value\\);.*" \
+ "next over recursive call"
+
+ # OK, we should be back in the same stack frame we started from.
+ # Do a backtrace just to confirm.
+
+ set result [gdb_test "backtrace" \
+ "#0\[ \t\]+ factorial .value=120.*\r\n#1\[ \t\]+ \[0-9a-fx\]+ in factorial .value=6..*" \
+ "backtrace from factorial(5.1)"]
+ if { $result != 0 } { gdb_suppress_tests }
+
+ if [target_info exists gdb,noresults] { gdb_suppress_tests }
+ if [target_info exists use_gdb_stub] {
+ gdb_breakpoint "exit"
+ gdb_test "continue" "Continuing..*Breakpoint .*exit \[(\].*=0\[)\].*" "continue until exit in recursive next test"
+ } else {
+ # Continue until we exit. Should not stop again.
+ # Don't bother to check the output of the program, that may be
+ # extremely tough for some remote systems.
+ gdb_test "continue"\
+ "Continuing.\[\r\n0-9\]+Program exited normally\\..*"\
+ "continue until exit in recursive next test"
+ }
+ gdb_stop_suppressing_tests;
+}
+
+test_clear_command
+test_next_with_recursion
+
+# Reset the default arguments for VxWorks
+if [istarget "*-*-vxworks*"] {
+ set timeout 10
+ verbose "Timeout is now $timeout seconds" 2
+ send_gdb "set args main\n"
+ gdb_expect -re ".*$gdb_prompt $" {}
+}
diff --git a/gdb/testsuite/gdb.base/call-ar-st.c b/gdb/testsuite/gdb.base/call-ar-st.c
new file mode 100644
index 00000000000..c61977afb8e
--- /dev/null
+++ b/gdb/testsuite/gdb.base/call-ar-st.c
@@ -0,0 +1,1137 @@
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+/**************************************************************************
+ * TESTS :
+ * -- function arguments that are enumerated types
+ * -- small structure arguments ( <= 64 bits )
+ * -- stored in registers
+ * -- stored on the stack
+ * -- large structure arguments ( > 64 bits )
+ * -- stored in registers
+ * -- stored on the stack
+ * -- array arguments
+ * -- caller is a leaf routine :
+ * -- use the call command from within an init routine (i.e.
+ * init_bit_flags, init_bit_flags_combo, init_array_rep)
+ * -- caller doesn't have enough space for all the function arguments :
+ * -- call print_long_arg_list from inside print_small_structs
+ ***************************************************************************/
+
+/* Some enumerated types -- used to test that the structureal data type is
+ * retrieved for function arguments with typedef data types.
+ */
+typedef int id_int;
+
+typedef enum {
+ BLACK,
+ BLUE,
+ BROWN,
+ ECRUE,
+ GOLD,
+ GRAY,
+ GREEN,
+ IVORY,
+ MAUVE,
+ ORANGE,
+ PINK,
+ PURPLE,
+ RED,
+ SILVER,
+ TAN,
+ VIOLET,
+ WHITE,
+ YELLOW} colors;
+
+/* A large structure (> 64 bits) used to test passing large structures as
+ * parameters
+ */
+
+struct array_rep_info_t {
+ int next_index[10];
+ int values[10];
+ int head;
+};
+
+/*****************************************************************************
+ * Small structures ( <= 64 bits). These are used to test passing small
+ * structures as parameters and test argument size promotion.
+ *****************************************************************************/
+
+ /* 64 bits
+ */
+struct small_rep_info_t {
+ int value;
+ int head;
+};
+
+/* 6 bits : really fits in 8 bits and is promoted to 32 bits
+ */
+struct bit_flags_t {
+ unsigned alpha :1;
+ unsigned beta :1;
+ unsigned gamma :1;
+ unsigned delta :1;
+ unsigned epsilon :1;
+ unsigned omega :1;
+};
+
+/* 22 bits : really fits in 40 bits and is promoted to 64 bits
+ */
+struct bit_flags_combo_t {
+ unsigned alpha :1;
+ unsigned beta :1;
+ char ch1;
+ unsigned gamma :1;
+ unsigned delta :1;
+ char ch2;
+ unsigned epsilon :1;
+ unsigned omega :1;
+};
+
+/* 64 bits
+ */
+struct one_double_t {
+ double double1;
+};
+
+/* 64 bits
+ */
+struct two_floats_t {
+ float float1;
+ float float2;
+};
+
+/* 16 bits : promoted to 32 bits
+ */
+struct two_char_t {
+ char ch1;
+ char ch2;
+};
+
+/* 24 bits : promoted to 32 bits
+ */
+struct three_char_t {
+ char ch1;
+ char ch2;
+ char ch3;
+};
+
+/* 40 bits : promoted to 64 bits
+ */
+struct five_char_t {
+ char ch1;
+ char ch2;
+ char ch3;
+ char ch4;
+ char ch5;
+};
+
+/* 40 bits : promoted to 64 bits
+ */
+struct int_char_combo_t {
+ int int1;
+ char ch1;
+};
+
+/*****************************************************************
+ * PRINT_STUDENT_ID_SHIRT_COLOR :
+ * IN id_int student -- enumerated type
+ * IN colors shirt -- enumerated type
+ *****************************************************************/
+void print_student_id_shirt_color ( student, shirt )
+ id_int student;
+ colors shirt;
+{
+
+ printf("student id : %d\t", student);
+ printf("shirt color : ");
+ switch (shirt) {
+ case BLACK : printf("BLACK\n");
+ break;
+ case BLUE : printf("BLUE\n");
+ break;
+ case BROWN : printf("BROWN\n");
+ break;
+ case ECRUE : printf("ECRUE\n");
+ break;
+ case GOLD : printf("GOLD\n");
+ break;
+ case GRAY : printf("GRAY\n");
+ break;
+ case GREEN : printf("GREEN\n");
+ break;
+ case IVORY : printf("IVORY\n");
+ break;
+ case MAUVE : printf("MAUVE\n");
+ break;
+ case ORANGE : printf("ORANGE\n");
+ break;
+ case PINK : printf("PINK\n");
+ break;
+ case PURPLE : printf("PURPLE\n");
+ break;
+ case RED : printf("RED\n");
+ break;
+ case SILVER : printf("SILVER\n");
+ break;
+ case TAN : printf("TAN\n");
+ break;
+ case VIOLET : printf("VIOLET\n");
+ break;
+ case WHITE : printf("WHITE\n");
+ break;
+ case YELLOW : printf("YELLOW\n");
+ break;
+ }
+}
+
+/*****************************************************************
+ * PRINT_CHAR_ARRAY :
+ * IN char array_c[] -- character array
+ *****************************************************************/
+void print_char_array ( array_c )
+ char array_c[];
+
+{
+
+ int index;
+
+ printf("array_c :\n");
+ printf("=========\n\n");
+ for (index = 0; index < 120; index++) {
+ printf("%1c", array_c[index]);
+ if ((index%50) == 0) printf("\n");
+ }
+ printf("\n\n");
+}
+
+/*****************************************************************
+ * PRINT_DOUBLE_ARRAY :
+ * IN double array_d[] -- array of doubles
+ *****************************************************************/
+void print_double_array (array_d)
+ double array_d[];
+
+{
+
+ int index;
+
+ printf("array_d :\n");
+ printf("=========\n\n");
+ for (index = 0; index < 100; index++) {
+ printf("%f ", array_d[index]);
+ if ((index%8) == 0) printf("\n");
+ }
+ printf("\n\n");
+}
+
+/*****************************************************************
+ * PRINT_FLOAT_ARRAY:
+ * IN float array_f[] -- array of floats
+ *****************************************************************/
+void print_float_array ( array_f )
+ float array_f[];
+
+{
+
+ int index;
+
+ printf("array_f :\n");
+ printf("=========\n\n");
+ for (index = 0; index < 15; index++) {
+ printf("%f ", array_f[index]);
+ if ((index%8) == 0) printf("\n");
+
+ }
+ printf("\n\n");
+}
+
+/*****************************************************************
+ * PRINT_INT_ARRAY:
+ * IN int array_i[] -- array of integers
+ *****************************************************************/
+void print_int_array ( array_i )
+ int array_i[];
+
+{
+
+ int index;
+
+ printf("array_i :\n");
+ printf("=========\n\n");
+ for (index = 0; index < 50; index++) {
+ printf("%d ", array_i[index]);
+ if ((index%8) == 0) printf("\n");
+ }
+ printf("\n\n");
+
+}
+
+/*****************************************************************
+ * PRINT_ALL_ARRAYS:
+ * IN int array_i[] -- array of integers
+ * IN char array_c[] -- array of characters
+ * IN float array_f[] -- array of floats
+ * IN double array_d[] -- array of doubles
+ *****************************************************************/
+void print_all_arrays( array_i, array_c, array_f, array_d )
+ int array_i[];
+ char array_c[];
+ float array_f[];
+ double array_d[];
+
+{
+ print_int_array(array_i);
+ print_char_array(array_c);
+ print_float_array(array_f);
+ print_double_array(array_d);
+}
+
+/*****************************************************************
+ * LOOP_COUNT :
+ * A do nothing function. Used to provide a point at which calls can be made.
+ *****************************************************************/
+void loop_count () {
+
+ int index;
+
+ for (index=0; index<4; index++);
+}
+
+/*****************************************************************
+ * COMPUTE_WITH_SMALL_STRUCTS :
+ * A do nothing function. Used to provide a point at which calls can be made.
+ * IN int seed
+ *****************************************************************/
+void compute_with_small_structs ( seed )
+ int seed;
+{
+
+ struct small_rep_info_t array[4];
+ int index;
+
+ for (index = 0; index < 4; index++) {
+ array[index].value = index*seed;
+ array[index].head = (index+1)*seed;
+ }
+
+ for (index = 1; index < 4; index++) {
+ array[index].value = array[index].value + array[index-1].value;
+ array[index].head = array[index].head + array[index-1].head;
+ }
+}
+
+/*****************************************************************
+ * INIT_BIT_FLAGS :
+ * Initializes a bit_flags_t structure. Can call this function see
+ * the call command behavior when integer arguments do not fit into
+ * registers and must be placed on the stack.
+ * OUT struct bit_flags_t *bit_flags -- structure to be filled
+ * IN unsigned a -- 0 or 1
+ * IN unsigned b -- 0 or 1
+ * IN unsigned g -- 0 or 1
+ * IN unsigned d -- 0 or 1
+ * IN unsigned e -- 0 or 1
+ * IN unsigned o -- 0 or 1
+ *****************************************************************/
+void init_bit_flags ( bit_flags, a, b, g, d, e, o )
+struct bit_flags_t *bit_flags;
+unsigned a;
+unsigned b;
+unsigned g;
+unsigned d;
+unsigned e;
+unsigned o;
+{
+
+ bit_flags->alpha = a;
+ bit_flags->beta = b;
+ bit_flags->gamma = g;
+ bit_flags->delta = d;
+ bit_flags->epsilon = e;
+ bit_flags->omega = o;
+}
+
+/*****************************************************************
+ * INIT_BIT_FLAGS_COMBO :
+ * Initializes a bit_flags_combo_t structure. Can call this function
+ * to see the call command behavior when integer and character arguments
+ * do not fit into registers and must be placed on the stack.
+ * OUT struct bit_flags_combo_t *bit_flags_combo -- structure to fill
+ * IN unsigned a -- 0 or 1
+ * IN unsigned b -- 0 or 1
+ * IN char ch1
+ * IN unsigned g -- 0 or 1
+ * IN unsigned d -- 0 or 1
+ * IN char ch2
+ * IN unsigned e -- 0 or 1
+ * IN unsigned o -- 0 or 1
+ *****************************************************************/
+void init_bit_flags_combo ( bit_flags_combo, a, b, ch1, g, d, ch2, e, o )
+ struct bit_flags_combo_t *bit_flags_combo;
+ unsigned a;
+ unsigned b;
+ char ch1;
+ unsigned g;
+ unsigned d;
+ char ch2;
+ unsigned e;
+ unsigned o;
+{
+
+ bit_flags_combo->alpha = a;
+ bit_flags_combo->beta = b;
+ bit_flags_combo->ch1 = ch1;
+ bit_flags_combo->gamma = g;
+ bit_flags_combo->delta = d;
+ bit_flags_combo->ch2 = ch2;
+ bit_flags_combo->epsilon = e;
+ bit_flags_combo->omega = o;
+}
+
+
+/*****************************************************************
+ * INIT_ONE_DOUBLE :
+ * OUT struct one_double_t *one_double -- structure to fill
+ * IN double init_val
+ *****************************************************************/
+void init_one_double ( one_double, init_val )
+ struct one_double_t *one_double;
+ double init_val;
+{
+
+ one_double->double1 = init_val;
+}
+
+/*****************************************************************
+ * INIT_TWO_FLOATS :
+ * OUT struct two_floats_t *two_floats -- structure to be filled
+ * IN float init_val1
+ * IN float init_val2
+ *****************************************************************/
+void init_two_floats ( two_floats, init_val1, init_val2 )
+ struct two_floats_t *two_floats;
+ float init_val1;
+ float init_val2;
+{
+ two_floats->float1 = init_val1;
+ two_floats->float2 = init_val2;
+}
+
+/*****************************************************************
+ * INIT_TWO_CHARS :
+ * OUT struct two_char_t *two_char -- structure to be filled
+ * IN char init_val1
+ * IN char init_val2
+ *****************************************************************/
+void init_two_chars ( two_char, init_val1, init_val2 )
+ struct two_char_t *two_char;
+ char init_val1;
+ char init_val2;
+{
+
+ two_char->ch1 = init_val1;
+ two_char->ch2 = init_val2;
+}
+
+/*****************************************************************
+ * INIT_THREE_CHARS :
+ * OUT struct three_char_t *three_char -- structure to be filled
+ * IN char init_val1
+ * IN char init_val2
+ * IN char init_val3
+ *****************************************************************/
+void init_three_chars ( three_char, init_val1, init_val2, init_val3 )
+ struct three_char_t *three_char;
+ char init_val1;
+ char init_val2;
+ char init_val3;
+{
+
+ three_char->ch1 = init_val1;
+ three_char->ch2 = init_val2;
+ three_char->ch3 = init_val3;
+}
+
+/*****************************************************************
+ * INIT_FIVE_CHARS :
+ * OUT struct five_char_t *five_char -- structure to be filled
+ * IN char init_val1
+ * IN char init_val2
+ * IN char init_val3
+ * IN char init_val4
+ * IN char init_val5
+ *****************************************************************/
+void init_five_chars ( five_char, init_val1, init_val2, init_val3,init_val4,init_val5 )
+ struct five_char_t *five_char;
+ char init_val1;
+ char init_val2;
+ char init_val3;
+ char init_val4;
+ char init_val5;
+{
+ five_char->ch1 = init_val1;
+ five_char->ch2 = init_val2;
+ five_char->ch3 = init_val3;
+ five_char->ch4 = init_val4;
+ five_char->ch5 = init_val5;
+}
+
+/*****************************************************************
+ * INIT_INT_CHAR_COMBO :
+ * OUT struct int_char_combo_t *combo -- structure to be filled
+ * IN int init_val1
+ * IN char init_val2
+ *****************************************************************/
+void init_int_char_combo ( combo, init_val1, init_val2 )
+ struct int_char_combo_t *combo;
+ int init_val1;
+ char init_val2;
+{
+
+ combo->int1 = init_val1;
+ combo->ch1 = init_val2;
+}
+
+/*****************************************************************
+ * INIT_STRUCT_REP :
+ * OUT struct small_rep_into_t *small_struct -- structure to be filled
+ * IN int seed
+ *****************************************************************/
+void init_struct_rep( small_struct, seed )
+ struct small_rep_info_t *small_struct;
+ int seed;
+
+{
+
+ small_struct->value = 2 + (seed*2);
+ small_struct->head = 0;
+}
+
+/*****************************************************************
+ * INIT_SMALL_STRUCTS :
+ * Takes all the small structures as input and calls the appropriate
+ * initialization routine for each structure
+ *****************************************************************/
+void init_small_structs (struct1, struct2, struct3,struct4,flags,flags_combo,
+three_char, five_char,int_char_combo, d1, d2,d3,f1,f2,f3)
+ struct small_rep_info_t *struct1;
+ struct small_rep_info_t *struct2;
+ struct small_rep_info_t *struct3;
+ struct small_rep_info_t *struct4;
+ struct bit_flags_t *flags;
+ struct bit_flags_combo_t *flags_combo;
+ struct three_char_t *three_char;
+ struct five_char_t *five_char;
+ struct int_char_combo_t *int_char_combo;
+ struct one_double_t *d1;
+ struct one_double_t *d2;
+ struct one_double_t *d3;
+ struct two_floats_t *f1;
+ struct two_floats_t *f2;
+ struct two_floats_t *f3;
+
+{
+
+ init_bit_flags(flags, (unsigned)1, (unsigned)0, (unsigned)1,
+ (unsigned)0, (unsigned)1, (unsigned)0 );
+ init_bit_flags_combo(flags_combo, (unsigned)1, (unsigned)0, 'y',
+ (unsigned)1, (unsigned)0, 'n',
+ (unsigned)1, (unsigned)0 );
+ init_three_chars(three_char, 'a', 'b', 'c');
+ init_five_chars(five_char, 'l', 'm', 'n', 'o', 'p');
+ init_int_char_combo(int_char_combo, 123, 'z');
+ init_struct_rep(struct1, 2);
+ init_struct_rep(struct2, 4);
+ init_struct_rep(struct3, 5);
+ init_struct_rep(struct4, 6);
+ init_one_double ( d1, 10.5);
+ init_one_double ( d2, -3.34);
+ init_one_double ( d3, 675.09123);
+ init_two_floats ( f1, 45.234, 43.6);
+ init_two_floats ( f2, 78.01, 122.10);
+ init_two_floats ( f3, -1232.345, -199.21);
+}
+
+/*****************************************************************
+ * PRINT_TEN_DOUBLES :
+ * ?????????????????????????????
+ ****************************************************************/
+void print_ten_doubles ( d1, d2, d3, d4, d5, d6, d7, d8, d9, d10 )
+ double d1;
+ double d2;
+ double d3;
+ double d4;
+ double d5;
+ double d6;
+ double d7;
+ double d8;
+ double d9;
+ double d10;
+{
+
+ printf("Two Doubles : %f\t%f\n", d1, d2);
+ printf("Two Doubles : %f\t%f\n", d3, d4);
+ printf("Two Doubles : %f\t%f\n", d5, d6);
+ printf("Two Doubles : %f\t%f\n", d7, d8);
+ printf("Two Doubles : %f\t%f\n", d9, d10);
+}
+
+/*****************************************************************
+ * PRINT_BIT_FLAGS :
+ * IN struct bit_flags_t bit_flags
+ ****************************************************************/
+void print_bit_flags ( bit_flags )
+struct bit_flags_t bit_flags;
+{
+
+ if (bit_flags.alpha) printf("alpha\n");
+ if (bit_flags.beta) printf("beta\n");
+ if (bit_flags.gamma) printf("gamma\n");
+ if (bit_flags.delta) printf("delta\n");
+ if (bit_flags.epsilon) printf("epsilon\n");
+ if (bit_flags.omega) printf("omega\n");
+}
+
+/*****************************************************************
+ * PRINT_BIT_FLAGS_COMBO :
+ * IN struct bit_flags_combo_t bit_flags_combo
+ ****************************************************************/
+void print_bit_flags_combo ( bit_flags_combo )
+struct bit_flags_combo_t bit_flags_combo;
+{
+
+ if (bit_flags_combo.alpha) printf("alpha\n");
+ if (bit_flags_combo.beta) printf("beta\n");
+ if (bit_flags_combo.gamma) printf("gamma\n");
+ if (bit_flags_combo.delta) printf("delta\n");
+ if (bit_flags_combo.epsilon) printf("epsilon\n");
+ if (bit_flags_combo.omega) printf("omega\n");
+ printf("ch1: %c\tch2: %c\n", bit_flags_combo.ch1, bit_flags_combo.ch2);
+}
+
+/*****************************************************************
+ * PRINT_ONE_DOUBLE :
+ * IN struct one_double_t one_double
+ ****************************************************************/
+void print_one_double ( one_double )
+struct one_double_t one_double;
+{
+
+ printf("Contents of one_double_t: \n\n");
+ printf("%f\n", one_double.double1);
+}
+
+/*****************************************************************
+ * PRINT_TWO_FLOATS :
+ * IN struct two_floats_t two_floats
+ ****************************************************************/
+void print_two_floats ( two_floats )
+struct two_floats_t two_floats;
+{
+
+ printf("Contents of two_floats_t: \n\n");
+ printf("%f\t%f\n", two_floats.float1, two_floats.float2);
+}
+
+/*****************************************************************
+ * PRINT_TWO_CHARS :
+ * IN struct two_char_t two_char
+ ****************************************************************/
+void print_two_chars ( two_char )
+struct two_char_t two_char;
+{
+
+ printf("Contents of two_char_t: \n\n");
+ printf("%c\t%c\n", two_char.ch1, two_char.ch2);
+}
+
+/*****************************************************************
+ * PRINT_THREE_CHARS :
+ * IN struct three_char_t three_char
+ ****************************************************************/
+void print_three_chars ( three_char )
+struct three_char_t three_char;
+{
+
+ printf("Contents of three_char_t: \n\n");
+ printf("%c\t%c\t%c\n", three_char.ch1, three_char.ch2, three_char.ch3);
+}
+
+/*****************************************************************
+ * PRINT_FIVE_CHARS :
+ * IN struct five_char_t five_char
+ ****************************************************************/
+void print_five_chars ( five_char )
+struct five_char_t five_char;
+{
+
+ printf("Contents of five_char_t: \n\n");
+ printf("%c\t%c\t%c\t%c\t%c\n", five_char.ch1, five_char.ch2,
+ five_char.ch3, five_char.ch4,
+ five_char.ch5);
+}
+
+/*****************************************************************
+ * PRINT_INT_CHAR_COMBO :
+ * IN struct int_char_combo_t int_char_combo
+ ****************************************************************/
+void print_int_char_combo ( int_char_combo )
+struct int_char_combo_t int_char_combo;
+{
+
+ printf("Contents of int_char_combo_t: \n\n");
+ printf("%d\t%c\n", int_char_combo.int1, int_char_combo.ch1);
+}
+
+/*****************************************************************
+ * PRINT_STRUCT_REP :
+ * The last parameter must go onto the stack rather than into a register.
+ * This is a good function to call to test small structures.
+ * IN struct small_rep_info_t struct1
+ * IN struct small_rep_info_t struct2
+ * IN struct small_rep_info_t struct3
+ ****************************************************************/
+void print_struct_rep( struct1, struct2, struct3)
+ struct small_rep_info_t struct1;
+ struct small_rep_info_t struct2;
+ struct small_rep_info_t struct3;
+
+{
+
+
+ printf("Contents of struct1: \n\n");
+ printf("%10d%10d\n", struct1.value, struct1.head);
+ printf("Contents of struct2: \n\n");
+ printf("%10d%10d\n", struct2.value, struct2.head);
+ printf("Contents of struct3: \n\n");
+ printf("%10d%10d\n", struct3.value, struct3.head);
+
+}
+
+/*****************************************************************
+ * SUM_STRUCT_PRINT :
+ * The last two parameters must go onto the stack rather than into a register.
+ * This is a good function to call to test small structures.
+ * IN struct small_rep_info_t struct1
+ * IN struct small_rep_info_t struct2
+ * IN struct small_rep_info_t struct3
+ * IN struct small_rep_info_t struct4
+ ****************************************************************/
+void sum_struct_print ( seed, struct1, struct2, struct3, struct4)
+ int seed;
+ struct small_rep_info_t struct1;
+ struct small_rep_info_t struct2;
+ struct small_rep_info_t struct3;
+ struct small_rep_info_t struct4;
+
+{
+ int sum;
+
+ printf("Sum of the 4 struct values and seed : \n\n");
+ sum = seed + struct1.value + struct2.value + struct3.value + struct4.value;
+ printf("%10d\n", sum);
+}
+
+/*****************************************************************
+ * PRINT_SMALL_STRUCTS :
+ * This is a good function to call to test small structures.
+ * All of the small structures of odd sizes (40 bits, 8bits, etc.)
+ * are pushed onto the stack.
+ ****************************************************************/
+void print_small_structs ( struct1, struct2, struct3, struct4, flags,
+flags_combo, three_char, five_char, int_char_combo, d1, d2,d3,f1,f2,f3)
+ struct small_rep_info_t struct1;
+ struct small_rep_info_t struct2;
+ struct small_rep_info_t struct3;
+ struct small_rep_info_t struct4;
+ struct bit_flags_t flags;
+ struct bit_flags_combo_t flags_combo;
+ struct three_char_t three_char;
+ struct five_char_t five_char;
+ struct int_char_combo_t int_char_combo;
+ struct one_double_t d1;
+ struct one_double_t d2;
+ struct one_double_t d3;
+ struct two_floats_t f1;
+ struct two_floats_t f2;
+ struct two_floats_t f3;
+{
+ print_bit_flags(flags);
+ print_bit_flags_combo(flags_combo);
+ print_three_chars(three_char);
+ print_five_chars(five_char);
+ print_int_char_combo(int_char_combo);
+ sum_struct_print(10, struct1, struct2, struct3, struct4);
+ print_struct_rep(struct1, struct2, struct3);
+ print_one_double(d1);
+ print_one_double(d2);
+ print_one_double(d3);
+ print_two_floats(f1);
+ print_two_floats(f2);
+ print_two_floats(f3);
+}
+
+/*****************************************************************
+ * PRINT_LONG_ARG_LIST :
+ * This is a good function to call to test small structures.
+ * The first two parameters ( the doubles ) go into registers. The
+ * remaining arguments are pushed onto the stack. Depending on where
+ * print_long_arg_list is called from, the size of the argument list
+ * may force more space to be pushed onto the stack as part of the callers
+ * frame.
+ ****************************************************************/
+void print_long_arg_list ( a, b, c, d, e, f, struct1, struct2, struct3,
+struct4, flags, flags_combo, three_char, five_char, int_char_combo, d1,d2,d3,
+f1, f2, f3 )
+ double a;
+ double b;
+ int c;
+ int d;
+ int e;
+ int f;
+ struct small_rep_info_t struct1;
+ struct small_rep_info_t struct2;
+ struct small_rep_info_t struct3;
+ struct small_rep_info_t struct4;
+ struct bit_flags_t flags;
+ struct bit_flags_combo_t flags_combo;
+ struct three_char_t three_char;
+ struct five_char_t five_char;
+ struct int_char_combo_t int_char_combo;
+ struct one_double_t d1;
+ struct one_double_t d2;
+ struct one_double_t d3;
+ struct two_floats_t f1;
+ struct two_floats_t f2;
+ struct two_floats_t f3;
+
+{
+ printf("double : %f\n", a);
+ printf("double : %f\n", b);
+ printf("int : %d\n", c);
+ printf("int : %d\n", d);
+ printf("int : %d\n", e);
+ printf("int : %d\n", f);
+ print_small_structs( struct1, struct2, struct3, struct4, flags, flags_combo,
+ three_char, five_char, int_char_combo, d1, d2, d3,
+ f1, f2, f3);
+}
+
+
+void print_one_large_struct( linked_list1 )
+ struct array_rep_info_t linked_list1;
+
+{
+
+ /* printf("Contents of linked list1: \n\n");
+ printf("Element Value | Index of Next Element\n");
+ printf("-------------------------------------\n");
+ printf(" | \n");*/
+ /*for (index = 0; index < 10; index++) {*/
+
+ printf("%10d%10d\n", linked_list1.values[0],
+ linked_list1.next_index[0]);
+ /*}*/
+}
+
+/*****************************************************************
+ * PRINT_ARRAY_REP :
+ * The three structure parameters should fit into registers.
+ * IN struct array_rep_info_t linked_list1
+ * IN struct array_rep_info_t linked_list2
+ * IN struct array_rep_info_t linked_list3
+ ****************************************************************/
+void print_array_rep( linked_list1, linked_list2, linked_list3 )
+ struct array_rep_info_t linked_list1;
+ struct array_rep_info_t linked_list2;
+ struct array_rep_info_t linked_list3;
+
+{
+
+ int index;
+
+ printf("Contents of linked list1: \n\n");
+ printf("Element Value | Index of Next Element\n");
+ printf("-------------------------------------\n");
+ printf(" | \n");
+ for (index = 0; index < 10; index++) {
+
+ printf("%10d%10d\n", linked_list1.values[index],
+ linked_list1.next_index[index]);
+ }
+
+ printf("Contents of linked list2: \n\n");
+ printf("Element Value | Index of Next Element\n");
+ printf("-------------------------------------\n");
+ printf(" | \n");
+ for (index = 0; index < 10; index++) {
+
+ printf("%10d%10d\n", linked_list2.values[index],
+ linked_list2.next_index[index]);
+ }
+
+ printf("Contents of linked list3: \n\n");
+ printf("Element Value | Index of Next Element\n");
+ printf("-------------------------------------\n");
+ printf(" | \n");
+ for (index = 0; index < 10; index++) {
+
+ printf("%10d%10d\n", linked_list3.values[index],
+ linked_list3.next_index[index]);
+ }
+
+}
+
+/*****************************************************************
+ * SUM_ARRAY_PRINT :
+ * The last structure parameter must be pushed onto the stack
+ * IN int seed
+ * IN struct array_rep_info_t linked_list1
+ * IN struct array_rep_info_t linked_list2
+ * IN struct array_rep_info_t linked_list3
+ * IN struct array_rep_info_t linked_list4
+ ****************************************************************/
+void sum_array_print ( seed, linked_list1, linked_list2, linked_list3,linked_list4)
+ int seed;
+ struct array_rep_info_t linked_list1;
+ struct array_rep_info_t linked_list2;
+ struct array_rep_info_t linked_list3;
+ struct array_rep_info_t linked_list4;
+
+{
+ int index;
+ int sum;
+
+ printf("Sum of 4 arrays, by element (add in seed as well): \n\n");
+ printf("Seed: %d\n", seed);
+ printf("Element Index | Sum \n");
+ printf("-------------------------\n");
+ printf(" | \n");
+
+ for (index = 0; index < 10; index++) {
+
+ sum = seed + linked_list1.values[index] + linked_list2.values[index] +
+ linked_list3.values[index] + linked_list4.values[index];
+ printf("%10d%10d\n", index, sum);
+ }
+}
+
+/*****************************************************************
+ * INIT_ARRAY_REP :
+ * IN struct array_rep_info_t *linked_list
+ * IN int seed
+ ****************************************************************/
+void init_array_rep( linked_list, seed )
+ struct array_rep_info_t *linked_list;
+ int seed;
+
+{
+
+ int index;
+
+ for (index = 0; index < 10; index++) {
+
+ linked_list->values[index] = (2*index) + (seed*2);
+ linked_list->next_index[index] = index + 1;
+ }
+ linked_list->head = 0;
+}
+
+
+int main () {
+
+ /* variables for array and enumerated type testing
+ */
+ char char_array[121];
+ double double_array[100];
+ float float_array[15];
+ int integer_array[50];
+ int index;
+ id_int student_id = 23;
+ colors my_shirt = YELLOW;
+
+ /* variables for large structure testing
+ */
+ int number = 10;
+ struct array_rep_info_t *list1;
+ struct array_rep_info_t *list2;
+ struct array_rep_info_t *list3;
+ struct array_rep_info_t *list4;
+
+ /* variables for testing a very long argument list
+ */
+ double a;
+ double b;
+ int c;
+ int d;
+ int e;
+ int f;
+
+ /* variables for testing a small structures and a very long argument list
+ */
+ struct small_rep_info_t *struct1;
+ struct small_rep_info_t *struct2;
+ struct small_rep_info_t *struct3;
+ struct small_rep_info_t *struct4;
+ struct bit_flags_t *flags;
+ struct bit_flags_combo_t *flags_combo;
+ struct three_char_t *three_char;
+ struct five_char_t *five_char;
+ struct int_char_combo_t *int_char_combo;
+ struct one_double_t *d1;
+ struct one_double_t *d2;
+ struct one_double_t *d3;
+ struct two_floats_t *f1;
+ struct two_floats_t *f2;
+ struct two_floats_t *f3;
+
+ /* Initialize arrays
+ */
+ for (index = 0; index < 120; index++) {
+ if ((index%2) == 0) char_array[index] = 'Z';
+ else char_array[index] = 'a';
+ } /* call-ar-st.exp uses line numbers everywhere */ char_array[120] = '\0';
+
+ for (index = 0; index < 100; index++) {
+ double_array[index] = index*23.4567;
+ }
+
+ for (index = 0; index < 15; index++) {
+ float_array[index] = index/7.02;
+ }
+
+ for (index = 0; index < 50; index++) {
+ integer_array[index] = -index;
+ }
+
+ /* Print arrays
+ */
+ print_char_array(char_array);
+ print_double_array(double_array);
+ print_float_array(float_array);
+ print_student_id_shirt_color(student_id, my_shirt);
+ print_int_array(integer_array);
+ print_all_arrays(integer_array, char_array, float_array, double_array);
+
+ /* Allocate space for large structures
+ */
+ list1 = (struct array_rep_info_t *)malloc(sizeof(struct array_rep_info_t));
+ list2 = (struct array_rep_info_t *)malloc(sizeof(struct array_rep_info_t));
+ list3 = (struct array_rep_info_t *)malloc(sizeof(struct array_rep_info_t));
+ list4 = (struct array_rep_info_t *)malloc(sizeof(struct array_rep_info_t));
+
+ /* Initialize large structures
+ */
+ init_array_rep(list1, 2);
+ init_array_rep(list2, 4);
+ init_array_rep(list3, 5);
+ init_array_rep(list4, 10);
+ printf("HELLO WORLD\n");
+ printf("BYE BYE FOR NOW\n");
+ printf("VERY GREEN GRASS\n");
+
+ /* Print large structures
+ */
+ sum_array_print(10, *list1, *list2, *list3, *list4);
+ print_array_rep(*list1, *list2, *list3);
+ print_one_large_struct(*list1);
+
+ /* Allocate space for small structures
+ */
+ struct1 = (struct small_rep_info_t *)malloc(sizeof(struct small_rep_info_t));
+ struct2 = (struct small_rep_info_t *)malloc(sizeof(struct small_rep_info_t));
+ struct3 = (struct small_rep_info_t *)malloc(sizeof(struct small_rep_info_t));
+ struct4 = (struct small_rep_info_t *)malloc(sizeof(struct small_rep_info_t));
+ flags = (struct bit_flags_t *)malloc(sizeof(struct bit_flags_t));
+ flags_combo = (struct bit_flags_combo_t *)malloc(sizeof(struct bit_flags_combo_t));
+ three_char = (struct three_char_t *)malloc(sizeof(struct three_char_t));
+ five_char = (struct five_char_t *)malloc(sizeof(struct five_char_t));
+ int_char_combo = (struct int_char_combo_t *)malloc(sizeof(struct int_char_combo_t));
+
+ d1 = (struct one_double_t *)malloc(sizeof(struct one_double_t));
+ d2 = (struct one_double_t *)malloc(sizeof(struct one_double_t));
+ d3 = (struct one_double_t *)malloc(sizeof(struct one_double_t));
+
+ f1 = (struct two_floats_t *)malloc(sizeof(struct two_floats_t));
+ f2 = (struct two_floats_t *)malloc(sizeof(struct two_floats_t));
+ f3 = (struct two_floats_t *)malloc(sizeof(struct two_floats_t));
+
+ /* Initialize small structures
+ */
+ init_small_structs ( struct1, struct2, struct3, struct4, flags,
+ flags_combo, three_char, five_char, int_char_combo,
+ d1, d2, d3, f1, f2, f3);
+
+ /* Print small structures
+ */
+ print_small_structs ( *struct1, *struct2, *struct3, *struct4, *flags,
+ *flags_combo, *three_char, *five_char, *int_char_combo,
+ *d1, *d2, *d3, *f1, *f2, *f3);
+
+ /* Print a very long arg list
+ */
+ a = 22.22;
+ b = 33.333;
+ c = 0;
+ d = -25;
+ e = 100;
+ f = 2345;
+
+ print_long_arg_list ( a, b, c, d, e, f, *struct1, *struct2, *struct3, *struct4,
+ *flags, *flags_combo, *three_char, *five_char, *int_char_combo,
+ *d1, *d2, *d3, *f1, *f2, *f3);
+
+ /* Initialize small structures
+ */
+ init_one_double ( d1, 1.11111);
+ init_one_double ( d2, -345.34);
+ init_one_double ( d3, 546464.2);
+ init_two_floats ( f1, 0.234, 453.1);
+ init_two_floats ( f2, 78.345, 23.09);
+ init_two_floats ( f3, -2.345, 1.0);
+ init_bit_flags(flags, (unsigned)1, (unsigned)0, (unsigned)1,
+ (unsigned)0, (unsigned)1, (unsigned)0 );
+ init_bit_flags_combo(flags_combo, (unsigned)1, (unsigned)0, 'y',
+ (unsigned)1, (unsigned)0, 'n',
+ (unsigned)1, (unsigned)0 );
+ init_three_chars(three_char, 'x', 'y', 'z');
+ init_five_chars(five_char, 'h', 'e', 'l', 'l', 'o');
+ init_int_char_combo(int_char_combo, 13, '!');
+ init_struct_rep(struct1, 10);
+ init_struct_rep(struct2, 20);
+ init_struct_rep(struct3, 30);
+ init_struct_rep(struct4, 40);
+
+ compute_with_small_structs(35);
+ loop_count();
+ printf("HELLO WORLD\n");
+ printf("BYE BYE FOR NOW\n");
+ printf("VERY GREEN GRASS\n");
+
+ /* Print small structures
+ */
+ print_one_double(*d1);
+ print_one_double(*d2);
+ print_one_double(*d3);
+ print_two_floats(*f1);
+ print_two_floats(*f2);
+ print_two_floats(*f3);
+ print_bit_flags(*flags);
+ print_bit_flags_combo(*flags_combo);
+ print_three_chars(*three_char);
+ print_five_chars(*five_char);
+ print_int_char_combo(*int_char_combo);
+ sum_struct_print(10, *struct1, *struct2, *struct3, *struct4);
+ print_struct_rep(*struct1, *struct2, *struct3);
+
+ return 0;
+}
+
+
+
+
+
diff --git a/gdb/testsuite/gdb.base/call-ar-st.exp b/gdb/testsuite/gdb.base/call-ar-st.exp
new file mode 100644
index 00000000000..d8ed4fef7dd
--- /dev/null
+++ b/gdb/testsuite/gdb.base/call-ar-st.exp
@@ -0,0 +1,451 @@
+# Copyright (C) 1998
+# Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file was written by Elena Zannoni (ezannoni@cygnus.com)
+
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+set prms_id 0
+set bug_id 0
+
+set testfile "call-ar-st"
+set srcfile ${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+
+
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+
+# Create and source the file that provides information about the compiler
+# used to compile the test case.
+
+if [get_compiler_info ${binfile}] {
+ return -1;
+}
+
+# The a29k can't call functions, so don't even bother with this test.
+if [target_info exists gdb,cannot_call_functions] {
+ setup_xfail "*-*-*" 2416
+ fail "This target can not call functions"
+ continue
+}
+
+# Set the current language to C. This counts as a test. If it
+# fails, then we skip the other tests.
+
+proc set_lang_c {} {
+ global gdb_prompt
+
+ send_gdb "set language c\n"
+ gdb_expect {
+ -re ".*$gdb_prompt $" {}
+ timeout { fail "set language c (timeout)" ; return 0; }
+ }
+
+ send_gdb "show language\n"
+ gdb_expect {
+ -re ".* source language is \"c\".*$gdb_prompt $" {
+ pass "set language to \"c\""
+ return 1
+ }
+ -re ".*$gdb_prompt $" {
+ fail "setting language to \"c\""
+ return 0
+ }
+ timeout {
+ fail "can't show language (timeout)"
+ return 0
+ }
+ }
+}
+
+
+source ${binfile}.ci
+
+
+# Start with a fresh gdb.
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+send_gdb "set print sevenbit-strings\n" ; gdb_expect -re "$gdb_prompt $"
+send_gdb "set print address off\n" ; gdb_expect -re "$gdb_prompt $"
+send_gdb "set width 0\n" ; gdb_expect -re "$gdb_prompt $"
+
+
+if ![runto_main] then {
+ perror "couldn't run to breakpoint"
+ continue
+}
+
+#go -until 1007
+gdb_test "tbreak 1007" \
+ "Breakpoint \[0-9\]+.*file.*$srcfile, line 1007.*" \
+ "tbreakpoint line 1007"
+
+gdb_test continue \
+"Continuing\\..*main \\(\\) at.*$srcfile:1007.*" \
+"run until breakpoint set at a line"
+
+
+#call print_double_array(double_array)
+send_gdb "print print_double_array(double_array)\n"
+gdb_expect {
+ -re "array_d :\[ \t\r\n\]+=========\[ \t\r\n\]+\[ \t\r\n\]+0.000000\[ \t\r\n\]+23.456700 46.913400 70.370100 93.826800 117.283500 140.740200 164.196900 187.653600\[ \t\r\n\]+211.110300 234.567000 258.023700 281.480400 304.937100 328.393800 351.850500 375.307200\[ \t\r\n\]+398.763900 422.220600 445.677300 469.134000 492.590700 516.047400 539.504100 562.960800\[ \t\r\n\]+586.417500 609.874200 633.330900 656.787600 680.244300 703.701000 727.157700 750.614400\[ \t\r\n\]+774.071100 797.527800 820.984500 844.441200 867.897900 891.354600 914.811300 938.268000\[ \t\r\n\]+961.724700 985.181400 1008.638100 1032.094800 1055.551500 1079.008200 1102.464900 1125.921600\[ \t\r\n\]+1149.378300 1172.835000 1196.291700 1219.748400 1243.205100 1266.661800 1290.118500 1313.575200\[ \t\r\n\]+1337.031900 1360.488600 1383.945300 1407.402000 1430.858700 1454.315400 1477.772100 1501.228800\[ \t\r\n\]+1524.685500 1548.142200 1571.598900 1595.055600 1618.512300 1641.969000 1665.425700 1688.882400\[ \t\r\n\]+1712.339100 1735.795800 1759.252500 1782.709200 1806.165900 1829.622600 1853.079300 1876.536000\[ \t\r\n\]+1899.992700 1923.449400 1946.906100 1970.362800 1993.819500 2017.276200 2040.732900 2064.189600\[ \t\r\n\]+2087.646300 2111.103000 2134.559700 2158.016400 2181.473100 2204.929800 2228.386500 2251.843200\[ \t\r\n\]+2275.299900 2298.756600 2322.213300\[ \t\r\n\]+\[ \t\r\n\]+.*$gdb_prompt $" {
+ pass "print print_double_array(double_array)"
+ }
+ -re ".*$gdb_prompt $" { fail "print print_double_array(double_array)" }
+ timeout { fail "(timeout) print print_double_array(double_array)" }
+ }
+
+
+#call print_char_array(char_array)
+send_gdb "print print_char_array(char_array)\n"
+gdb_expect {
+ -re "array_c :\[ \t\r\n\]+=========\[ \t\r\n\]+\[ \t\r\n\]+Z\[ \t\r\n\]+aZaZaZaZaZaZaZaZaZaZaZaZaZaZaZaZaZaZaZaZaZaZaZaZaZ\[ \t\r\n\]+aZaZaZaZaZaZaZaZaZaZaZaZaZaZaZaZaZaZaZaZaZaZaZaZaZ\[ \t\r\n\]+aZaZaZaZaZaZaZaZaZa\[ \t\r\n\]+\[ \t\r\n\]+.*\[ \t\r\n\]+.*$gdb_prompt $" {
+ pass "print print_char_array(char_array)"
+ }
+ -re ".*$gdb_prompt $" { fail "print print_char_array(char_array)" }
+ timeout { fail "(timeout) print print_char_array(char_array)" }
+ }
+
+
+
+#go -until 1014
+gdb_test "tbreak 1014" \
+"Breakpoint.*file.*$srcfile, line 1014.*" \
+"tbreakpoint line 1014"
+
+send_gdb "continue\n"
+gdb_expect {
+ -re "array_c :\[ \t\r\n\]+=========\[ \t\r\n\]+\[ \t\r\n\]+Z\[ \t\r\n\]+aZaZaZaZaZaZaZaZaZaZaZaZaZaZaZaZaZaZaZaZaZaZaZaZaZ\[ \t\r\n\]+aZaZaZaZaZaZaZaZaZaZaZaZaZaZaZaZaZaZaZaZaZaZaZaZaZ\[ \t\r\n\]+aZaZaZaZaZaZaZaZaZa\[ \t\r\n\]+\[ \t\r\n\]+\[ \t\r\n\]+main.*at.*$srcfile:1014\[ \t\r\n\]+.*print_double_array\\(double_array\\).*$gdb_prompt $" {
+ pass "continue to 1014"
+ }
+ -re ".*$gdb_prompt $" { fail "continue to 1014" }
+ timeout { fail "(timeout) continue to 1014" }
+}
+
+# I am disabling this test, because it takes too long. I verified by
+# hand that it works, feel free to check for yourself.
+#call print_all_arrays(integer_array, char_array, float_array, double_array)
+#send_gdb "print print_all_arrays(integer_array, char_array, float_array, double_array)\n"
+#gdb_expect {
+# -re ".*array_i :\[ \t\r\n\]+=========\[ \t\r\n\]+\[ \t\r\n\]+0\[ \t\r\n\]+-1 -2 -3 -4 -5 -6 -7 -8\[ \t\r\n\]+-9 -10 -11 -12 -13 -14 -15 -16\[ \t\r\n\]+-17 -18 -19 -20 -21 -22 -23 -24\[ \t\r\n\]+-25 -26 -27 -28 -29 -30 -31 -32\[ \t\r\n\]+-33 -34 -35 -36 -37 -38 -39 -40\[ \t\r\n\]+-41 -42 -43 -44 -45 -46 -47 -48\[ \t\r\n\]+-49\[ \t\r\n\]+\[ \t\r\n\]+array_c :\[ \t\r\n\]+=========\[ \t\r\n\]+\[ \t\r\n\]+Z\[ \t\r\n\]+aZaZaZaZaZaZaZaZaZaZaZaZaZaZaZaZaZaZaZaZaZaZaZaZaZ\[ \t\r\n\]+aZaZaZaZaZaZaZaZaZaZaZaZaZaZaZaZaZaZaZaZaZaZaZaZaZ\[ \t\r\n\]+aZaZaZaZaZaZaZaZaZa\[ \t\r\n\]+\[ \t\r\n\]+array_f :\[ \t\r\n\]+=========\[ \t\r\n\]+\[ \t\r\n\]+0.000000\[ \t\r\n\]+0.142450 0.284900 0.427350 0.569801 0.712251 0.854701 0.997151 1.139601\[ \t\r\n\]+1.282051 1.424501 1.566952 1.709402 1.851852 1.994302\[ \t\r\n\]+\[ \t\r\n\]+array_d :\[ \t\r\n\]+=========\[ \t\r\n\]+\[ \t\r\n\]+0.000000\[ \t\r\n\]+23.456700 46.913400 70.370100 93.826800 117.283500 140.740200 164.196900 187.653600\[ \t\r\n\]+211.110300 234.567000 258.023700 281.480400 304.937100 328.393800 351.850500 375.307200\[ \t\r\n\]+398.763900 422.220600 445.677300 469.134000 492.590700 516.047400 539.504100 562.960800\[ \t\r\n\]+586.41750 609.874200 633.330900 656.787600 680.244300 703.701000 727.157700 750.614400\[ \t\r\n\]+774.071100 797.527800 820.984500 844.441200 867.897900 891.354600 914.811300 938.268000\[ \t\r\n\]+961.724700 985.181400 1008.638100 1032.094800 1055.551500 1079.008200 1102.464900 1125.921600\[ \t\r\n\]+1149.378300 1172.835000 1196.291700 1219.748400 1243.205100 1266.661800 1290.118500 1313.575200\[ \t\r\n\]+1337.031900 1360.488600 1383.945300 1407.402000 1430.858700 1454.315400 1477.772100 1501.228800\[ \t\r\n\]+1524.685500 1548.142200 1571.598900 1595.055600 1618.512300 1641.969000 1665.425700 1688.882400\[ \t\r\n\]+1712.339100 1735.795800 1759.252500 1782.709200 1806.165900 1829.622600 1853.079300 1876.536000\[ \t\r\n\]+1899.992700 1923.449400 1946.906100 1970.362800 1993.819500 2017.276200 2040.732900 2064.189600\[ \t\r\n\]+2087.646300 2111.103000 2134.559700 2158.016400 2181.473100 2204.929800 2228.386500 2251.843200\[ \t\r\n\]+2275.299900 2298.756600 2322.213300.*$gdb_prompt $" {
+# pass "print print_all_arrays(integer_array, char_array, float_array, double_array)"
+# }
+# -re ".*$gdb_prompt $" { fail "print print_all_arrays(integer_array, char_array, float_array, double_array)" }
+# timeout { fail "(timeout) print print_all_arrays(integer_array, char_array, float_array, double_array)" }
+# }
+
+#set timeout $oldtimeout
+#go -until 1018
+gdb_test "tbreak 1018" \
+ "Breakpoint.* file .*$srcfile, line 1018.*" \
+ "tbreakpoint line 1018"
+
+gdb_test continue \
+"Continuing\\..*array_d :.*array_f :.*student id :\[\t \]+.*YELLOW.*array_i :.*main \\(\\) at .*call-ar-st.c:1018\[ \t\r\n\]+.*print_all_arrays\\(integer_array, char_array, float_array, double_array\\)." \
+"continuing to breakpoint 1018"
+
+#step
+ send_gdb "step\n"
+ gdb_expect {
+ -re "print_all_arrays \\(array_i=, array_c=.ZaZaZaZaZaZaZaZaZaZaZaZaZaZaZaZaZaZaZaZaZaZaZaZaZaZaZaZaZaZaZaZaZaZaZaZaZaZaZaZaZaZaZaZaZaZaZaZaZaZaZaZaZaZaZaZaZaZaZaZa., array_f=, array_d=\\) at .*call-ar-st.c:287\[ \t\r\n\]+287.*print_int_array\\(array_i\\);.*$gdb_prompt $" {pass "step inside print_all_arrays"}
+ -re ".*$gdb_prompt $" { fail "step inside print_all_arrays" }
+ timeout { fail "step inside print_all_arrays (timeout)" }
+ }
+
+
+#step -over
+ send_gdb "next\n"
+ gdb_expect {
+ -re "array_i :.*288.*print_char_array\\(array_c\\);.*$gdb_prompt $" {pass "next over print_int_array in print-all_arrays"}
+ -re ".*$gdb_prompt $" { fail "next over print_int_array in print-all_arrays" }
+ timeout { fail "next over print_int_array in print-all_arrays (timeout)" }
+ }
+
+
+
+#call print_double_array(array_d)
+send_gdb "print print_double_array(array_d)\n"
+gdb_expect {
+ -re "array_d :\[ \t\r\n\]+=========\[ \t\r\n\]+\[ \t\r\n\]+0.000000\[ \t\r\n\]+23.456700 46.913400 70.370100 93.826800 117.283500 140.740200 164.196900 187.653600\[ \t\r\n\]+211.110300 234.567000 258.023700 281.480400 304.937100 328.393800 351.850500 375.307200\[ \t\r\n\]+398.763900 422.220600 445.677300 469.134000 492.590700 516.047400 539.504100 562.960800\[ \t\r\n\]+586.417500 609.874200 633.330900 656.787600 680.244300 703.701000 727.157700 750.614400\[ \t\r\n\]+774.071100 797.527800 820.984500 844.441200 867.897900 891.354600 914.811300 938.268000\[ \t\r\n\]+961.724700 985.181400 1008.638100 1032.094800 1055.551500 1079.008200 1102.464900 1125.921600\[ \t\r\n\]+1149.378300 1172.835000 1196.291700 1219.748400 1243.205100 1266.661800 1290.118500 1313.575200\[ \t\r\n\]+1337.031900 1360.488600 1383.945300 1407.402000 1430.858700 1454.315400 1477.772100 1501.228800\[ \t\r\n\]+1524.685500 1548.142200 1571.598900 1595.055600 1618.512300 1641.969000 1665.425700 1688.882400\[ \t\r\n\]+1712.339100 1735.795800 1759.252500 1782.709200 1806.165900 1829.622600 1853.079300 1876.536000\[ \t\r\n\]+1899.992700 1923.449400 1946.906100 1970.362800 1993.819500 2017.276200 2040.732900 2064.189600\[ \t\r\n\]+2087.646300 2111.103000 2134.559700 2158.016400 2181.473100 2204.929800 2228.386500 2251.843200\[ \t\r\n\]+2275.299900 2298.756600 2322.213300\[ \t\r\n\]+\[ \t\r\n\]+.*$gdb_prompt $" {
+ pass "print print_double_array(array_d)"
+ }
+ -re ".*$gdb_prompt $" { fail "print print_double_array(array_d)" }
+ timeout { fail "(timeout) print print_double_array(array_d)" }
+ }
+
+
+#go -until 1034
+gdb_test "tbreak 1034" \
+"Breakpoint.* file .*$srcfile, line 1034.*" \
+"tbreakpoint line 1034"
+
+gdb_test continue "Continuing\\..*array_c.*array_f.*array_d.*HELLO WORLD.*main \\(\\) at .*call-ar-st.c:1034.*printf\\(.BYE BYE FOR NOW.n.\\)." "continuing to 1034"
+
+
+#call sum_array_print(10, *list1, *list2, *list3, *list4)
+send_gdb "print sum_array_print(10, *list1, *list2, *list3, *list4)\n"
+gdb_expect {
+ -re ".*Sum of 4 arrays, by element \\(add in seed as well\\):\[ \t\r\n\]+Seed: 10\[ \t\r\n\]+Element Index . Sum\[ \t\r\n\]+-------------------------\[ \t\r\n\]+.*\[ \t\]+0\[ \t\]+52\[ \t\r\n\]+1\[ \t\]+60\[ \t\r\n\]+2\[ \t\]+68\[ \t\r\n\]+3\[ \t\]+76\[ \t\r\n\]+4\[ \t\]+84\[ \t\r\n\]+5\[ \t\]+92\[ \t\r\n\]+6\[ \t\]+100\[ \t\r\n\]+7\[ \t\]+108\[ \t\r\n\]+8\[ \t\]+116\[ \t\r\n\]+9\[ \t\]+124\[ \t\r\n\]+.*$gdb_prompt $" {
+ pass "print sum_array_print(10, *list1, *list2, *list3, *list4)"
+ }
+ -re ".*$gdb_prompt $" { fail "print sum_array_print(10, *list1, *list2, *list3, *list4)" }
+ timeout { fail "(timeout) print sum_array_print(10, *list1, *list2, *list3, *list4)" }
+ }
+
+
+#step -over
+ send_gdb "next\n"
+ gdb_expect {
+ -re "BYE BYE FOR NOW\[ \t\r\n\]+1035\[ \t\r\n\]+printf\\(.VERY GREEN GRASS.n.\\);\[ \t\r\n\]+.*$gdb_prompt $" { pass "next to 1035"}
+ -re ".*$gdb_prompt $" { fail "next to 1035" }
+ timeout { fail "next to 1035(timeout)" }
+ }
+
+#call print_array_rep(\*list1, \*list2, \*list3)
+
+send_gdb "print print_array_rep(\*list1, \*list2, \*list3)\n"
+gdb_expect {
+ -re ".*.*$gdb_prompt $" {
+ pass "print print_array_rep(*list1, *list2, *list3)"
+ }
+ -re ".*$gdb_prompt $" { fail "print print_array_rep(*list1, *list2, *list3)" }
+ timeout { fail "(timeout) print print_array_rep(*list1, *list2, *list3)"# }
+ }
+
+
+
+#go -until 1039
+gdb_test "tbreak 1039" \
+ "Breakpoint..* file .*$srcfile, line 1039.*" \
+ "tbreakpoint line 1039"
+
+send_gdb "continue\n"
+gdb_expect {
+ -re ".*main \\(\\) at .*call-ar-st.c:1039\r\n1039\t\[ \]+sum_array_print\\(10, \\*list1, \\*list2, \\*list3, \\*list4\\);.*$gdb_prompt $" {
+ pass "continue to 1039"}
+ -re ".*$gdb_prompt $" { fail "continue to 1039"}
+ timeout { fail "(timeout) continue to 1039"}
+}
+
+
+
+# Run into sum_array_print, and verify that the arguments were passed
+# accurately.
+#
+# Note that we shouldn't use a `step' here to get into
+# sum_array_print; GCC may emit calls to memcpy to put the arguments
+# in the right place, and a step may end up in memcpy instead. This
+# may itself be a bug, but it's not the one we're trying to catch
+# here. I've added something to step-test.exp for this.
+gdb_test "break sum_array_print" \
+ ".*Breakpoint ${decimal}: file .*call-ar-st.c, line.*" \
+ "set breakpoint in sum_array_print"
+gdb_test "continue" \
+ ".*Breakpoint ${decimal}, sum_array_print \\(seed=10, linked_list1=.next_index = .1, 2, 3, 4, 5, 6, 7, 8, 9, 10., values = .4, 6, 8, 10, 12, 14, 16, 18, 20, 22., head = 0., linked_list2=.next_index = .1, 2, 3, 4, 5, 6, 7, 8, 9, 10., values = .8, 10, 12, 14, 16, 18, 20, 22, 24, 26., head = 0., linked_list3=.next_index = .1, 2, 3, 4, 5, 6, 7, 8, 9, 10., values = .10, 12, 14, 16, 18, 20, 22, 24, 26, 28., head = 0., linked_list4=.next_index = .1, 2, 3, 4, 5, 6, 7, 8, 9, 10., values = .20, 22, 24, 26, 28, 30, 32, 34, 36, 38., head = 0.\\) at .*call-ar-st.c:909\[ \t\n\r\]+909.*printf\\(.Sum of 4 arrays, by element \\(add in seed as well\\).*\\);.*" \
+ "check args of sum_array_print"
+
+#call print_array_rep(linked_list1, linked_list2, linked_list3)
+# this calls works from gdb without gdb_expect. But it does seem to hang
+#from within gdb_expect.
+#I comment this out
+#send_gdb "print print_array_rep(linked_list1, linked_list2, linked_list3)\n"
+#gdb_expect {
+# -re ".*Contents of linked list1:\[ \t\n\r\]+Element Value . Index of Next Element\[ \t\n\r\]+-------------------------------------\[ \t\n\r\]+.*\[ \t\n\r\]+.*4.*1\[ \t\n\r\]+.*6.*2\[ \t\n\r\]+.*8.*3\[ \t\n\r\]+.*10.*4\[ \t\n\r\]+.*12.*5\[ \t\n\r\]+.*14.*6\[ \t\n\r\]+.*16.*7\[ \t\n\r\]+.*18.*8\[ \t\n\r\]+.*20.*9\[ \t\n\r\]+.*22.*10\[ \t\n\r\]+Contents of linked list2:\[ \t\n\r\]+Element Value | Index of Next Element\[ \t\n\r\]+-------------------------------------\[ \t\n\r\]+.*\[ \t\n\r\]+.*8.*1\[ \t\n\r\]+.*10.*2\[ \t\n\r\]+.*12.*3\[ \t\n\r\]+.*14.*4\[ \t\n\r\]+.*16.*5\[ \t\n\r\]+.*18.*6\[ \t\n\r\]+.*20.*7\[ \t\n\r\]+.*22.*8\[ \t\n\r\]+.*24.*9\[ \t\n\r\]+.*26.*10\[ \t\n\r\]+Contents of linked list3:\[ \t\n\r\]+Element Value | Index of Next Element\[ \t\n\r\]+-------------------------------------\[ \t\n\r\]+.*\[ \t\n\r\]+.*10.*1\[ \t\n\r\]+.*12.*2\[ \t\n\r\]+.*14.*3\[ \t\n\r\]+.*16.*4\[ \t\n\r\]+.*18.*5\[ \t\n\r\]+.*20.*6\[ \t\n\r\]+.*22.*7\[ \t\n\r\]+.*24.*8\[ \t\n\r\]+.*26.*9\[ \t\n\r\]+.*28.*10\[ \t\n\r\]+.*$gdb_prompt $" {
+# pass "print print_array_rep(linked_list1, linked_list2, linked_list3)"
+# }
+# -re ".*$gdb_prompt $" { fail "print print_array_rep(linked_list1, linked_list2, linked_list3)" }
+# timeout { fail "(timeout) print print_array_rep(linked_list1, linked_list2, linked_list3)" }
+#}
+
+
+#go -until 1079
+gdb_test "tbreak 1079" \
+ "Breakpoint.* file .*call-ar-st.c, line 1079.*" \
+ "tbreakpoint line 1079"
+
+send_gdb "continue\n"
+gdb_expect {
+ -re "Continuing\\..*Sum of 4 arrays.*Contents of linked list1.*Contents of two_floats_t.*main \\(\\) at .*call-ar-st.c:1079.*c = 0.*$gdb_prompt $" {
+ pass "continue to 1079"}
+ -re ".*$gdb_prompt $" { fail "continue to 1079"}
+ timeout { fail "(timeout) continue to 1079"}
+}
+
+#call print_small_structs(*struct1, *struct2, *struct3, *struct4,*flags, *flags_combo,
+#*three_char, *five_char, *int_char_combo, *d1, *d2, *d3, *f1, *f2, *f3)
+send_gdb "print print_small_structs(*struct1, *struct2, *struct3, *struct4, *flags, *flags_combo, *three_char, *five_char, *int_char_combo, *d1, *d2, *d3, *f1, *f2, *f3)\n"
+gdb_expect {
+ -re ".*alpha\[\t\r\n \]+gamma\[\t\r\n \]+epsilon\[\t\r\n \]+alpha\[\t\r\n \]+gamma\[\t\r\n \]+epsilon\[\t\r\n \]+ch1: y\tch2: n\[\t\r\n \]+Contents of three_char_t:\[\t\r\n \]+a\tb\tc\[\t\r\n \]+Contents of five_char_t:\[\t\r\n \]+l\tm\tn\to\tp\[\t\r\n \]+Contents of int_char_combo_t:\[\t\r\n \]+123.*z\[\t\r\n \]+Sum of the 4 struct values and seed :\[\t\r\n \]+52\[\t\r\n \]+Contents of struct1:\[\t\r\n \]+6.*0\[\t\r\n \]+Contents of struct2:\[\t\r\n \]+10.*0\[\t\r\n \]+Contents of struct3:\[\t\r\n \]+12.*0\[\t\r\n \]+Contents of one_double_t:\[\t\r\n \]+10.500000\[\t\r\n \]+Contents of one_double_t:.*-3.340000\[\t\r\n \]+Contents of one_double_t:.*675.091230\[\t\r\n \]+Contents of two_floats_t:.*45.234001.*43.599998\[\t\r\n \]+Contents of two_floats_t:.*78.010002.*122.099998\[\t\r\n \]+Contents of two_floats_t:.*-1232.344971.*-199.210007\[\t\r\n \]+.*$gdb_prompt $" {
+ pass "print print_small_structs"
+ }
+ -re ".*$gdb_prompt $" { fail "print print_small_structs" }
+ timeout { fail "(timeout) print_small_structs" }
+ }
+
+
+#call compute_with_small_structs(20)
+send_gdb "print compute_with_small_structs(20)\n"
+gdb_expect {
+ -re ".*\[0-9\]+ =.*$gdb_prompt $" {
+ pass "print compute_with_small_structs(20)"
+ }
+ -re ".*$gdb_prompt $" { fail "print compute_with_small_structs(20)" }
+ timeout { fail "(timeout) compute_with_small_structs(20)" }
+ }
+
+
+#call print_ten_doubles(123.456, 123.456, -0.12, -1.23, 343434.8, 89.098, 3.14, -5678.12345, -0.11111111, 216.97065)
+send_gdb "print print_ten_doubles(123.456, 123.456, -0.12, -1.23, 343434.8, 89.098, 3.14, -5678.12345, -0.11111111, 216.97065)\n"
+gdb_expect {
+ -re ".*Two Doubles : 123.456000.*123.456000\[\t\r\n \]+Two Doubles : -0.120000.*-1.230000\[\t\r\n \]+Two Doubles : 343434.800000.*89.098000\[\t\r\n \]+Two Doubles : 3.140000.*-5678.123450\[\t\r\n \]+Two Doubles : -0.111111.*216.970650\[\t\r\n \]+.*$gdb_prompt $" {
+ pass "print print_ten_doubles"
+ }
+ -re ".*$gdb_prompt $" { fail "print print_ten_doubles" }
+ timeout { fail "(timeout) print_ten_doubles" }
+ }
+
+#go -until 1084
+gdb_test "tbreak 1084" \
+ "Breakpoint .* file .*call-ar-st.c, line 1084.*" \
+ "tbreakpoint line 1084"
+
+gdb_test continue "Continuing\\..*main \\(.*\\) at.*call-ar-st.c:1084\[\t\r\n \]+1084.*print_long_arg_list \\( a, b, c, d, e, f, .struct1, .struct2, .struct3, .struct4,.*" "continue to 1084"
+
+
+ send_gdb "step\n"
+ gdb_expect {
+ -re ".*print_long_arg_list \\(a=22.219999999999999, b=33.332999999999998, c=0, d=-25, e=100, f=2345, struct1=\{value = 6, head = 0\}, struct2=\{value = 10, head = 0\}, struct3=\{value = 12, head = 0\}, struct4=\{value = 14, head = 0\}, flags=\{alpha = 1, beta = 0, gamma = 1, delta = 0, epsilon = 1, omega = 0\}, flags_combo=\{alpha = 1, beta = 0, ch1 = 121 \'y\', gamma = 1, delta = 0, ch2 = 110 \'n\', epsilon = 1, omega = 0\}, three_char=\{ch1 = 97 \'a\', ch2 = 98 \'b\', ch3 = 99 \'c\'\}, five_char=\{ch1 = 108 \'l\', ch2 = 109 \'m\', ch3 = 110 \'n\', ch4 = 111 \'o\', ch5 = 112 \'p\'\}, int_char_combo=\{int1 = 123, ch1 = 122 \'z\'\}, d1=\{double1 = 10.5\}, d2=\{double1 = -3.3399999999999999\}, d3=\{double1 = 675.09123\}, f1=\{float1 = 45.2340012, float2 = 43.5999985\}, f2=\{float1 = 78.0100021, float2 = 122.099998\}, f3=\{float1 = -1232.34497, float2 = -199.210007\}\\) at ${srcdir}/${subdir}/${srcfile}:813\[\r\n\]+813\[ \t\]+printf\\(\"double :.*\", a\\);.*$gdb_prompt $" {pass "step into print_long_arg_list"}
+ -re ".*$gdb_prompt $" { fail "step into print_long_arg_list" }
+ timeout { fail "step into print_long_arg_list (timeout)" }
+ }
+
+
+#call print_small_structs(struct1, struct2, struct3, struct4, flags, flags_combo, three_char, five_char, int_char_combo, d1, d2, d3, f1, f2, f3)
+send_gdb "print print_small_structs(struct1, struct2, struct3, struct4, flags, flags_combo, three_char, five_char, int_char_combo, d1, d2, d3, f1, f2, f3)\n"
+gdb_expect {
+ -re ".*alpha\[\t\r\n \]+gamma\[\t\r\n \]+epsilon\[\t\r\n \]+alpha\[\t\r\n \]+gamma\[\t\r\n \]+epsilon\[\t\r\n \]+ch1: y\tch2: n\[\t\r\n \]+Contents of three_char_t:\[\t\r\n \]+a\tb\tc\[\t\r\n \]+Contents of five_char_t:\[\t\r\n \]+l\tm\tn\to\tp\[\t\r\n \]+Contents of int_char_combo_t:\[\t\r\n \]+123.*z\[\t\r\n \]+Sum of the 4 struct values and seed :\[\t\r\n \]+52\[\t\r\n \]+Contents of struct1:\[\t\r\n \]+6.*0\[\t\r\n \]+Contents of struct2:\[\t\r\n \]+10.*0\[\t\r\n \]+Contents of struct3:\[\t\r\n \]+12.*0\[\t\r\n \]+Contents of one_double_t:\[\t\r\n \]+10.500000\[\t\r\n \]+Contents of one_double_t:\[\t\r\n \]+-3.340000\[\t\r\n \]+Contents of one_double_t:\[\t\r\n \]+675.091230\[\t\r\n \]+Contents of two_floats_t:\[\t\r\n \]+45.234001.*43.599998\[\t\r\n \]+Contents of two_floats_t:\[\t\r\n \]+78.010002.*122.099998\[\t\r\n \]+Contents of two_floats_t:\[\t\r\n \]+-1232.344971.*-199.210007\[\t\r\n \]+.*$gdb_prompt $" {
+ pass "print print_small_structs from print_long_arg_list "
+ }
+ -re ".*$gdb_prompt $" { fail "print print_small_structs from print_long_arg_list" }
+ timeout { fail "(timeout) print_small_structs from print_long_arg_list" }
+ }
+
+
+
+#go -until 1098
+gdb_test "tbreak 1098" \
+ "Breakpoint.* file .*call-ar-st.c, line 1098.*" \
+ "tbreakpoint line 1098"
+
+gdb_test continue "Continuing\\..*Contents of two_floats_t:.*-1232.344971.*-199.210007.*main \\(\\) at.*call-ar-st.c:1098.*1098.*init_bit_flags_combo\\(flags_combo, \\(unsigned\\)1, \\(unsigned\\)0, .y.,.*" \
+"continue to 1098"
+
+
+#step
+ send_gdb "step\n"
+ gdb_expect {
+ -re "
+init_bit_flags_combo \\(bit_flags_combo=, a=1, b=0, ch1=121 .y., g=1, d=0, ch2=110 .n., e=1, o=0\\) at .*call-ar-st.c:385\[ \t\n\r\]+385.*bit_flags_combo->alpha = a;.*$gdb_prompt $" {
+ pass "step into init_bit_flags_combo"}
+ -re ".*$gdb_prompt $" { fail "step into init_bit_flags_combo" }
+ timeout { fail "step into init_bit_flags_combo (timeout)" }
+ }
+
+#call print_bit_flags_combo(*bit_flags_combo)
+send_gdb "print print_bit_flags_combo(*bit_flags_combo)\n"
+gdb_expect {
+ -re ".*alpha.*gamma.*epsilon.*ch1: y\tch2: n.*$gdb_prompt $" {
+ pass "print print_bit_flags_combo from init_bit_flags_combo"
+ }
+ -re ".*$gdb_prompt $" { fail "print print_bit_flags_combo from init_bit_flags_combo" }
+ timeout { fail "(timeout) print_bit_flags_combo from init_bit_flags_combo" }
+ }
+
+
+#go -until 1103
+gdb_test "tbreak 1103" \
+ "Breakpoint.* file .*call-ar-st.c, line 1103.*" \
+ "tbreakpoint line 1103"
+
+gdb_test continue "Continuing\\..*main \\(\\) at .*call-ar-st.c:1103\[\r\n\t \]+1103.*init_int_char_combo\\(int_char_combo, 13, .!.\\);" \
+"continue to 1103"
+
+#call print_long_arg_list(a, b, c, d, e, f, *struct1, *struct2, *struct3, *struct4, *flags, *flags_combo, *three_char, *five_char, *int_char_combo, *d1, *d2, *d3, *f1, *f2, *f3)
+send_gdb "print print_long_arg_list(a, b, c, d, e, f, *struct1, *struct2, *struct3, *struct4, *flags, *flags_combo, *three_char, *five_char, *int_char_combo, *d1, *d2, *d3, *f1, *f2, *f3)\n"
+gdb_expect {
+ -re ".*double : 22.220000.*double : 33.333000.*int : 0.*int : -25.*int : 100.*int : 2345.*alpha.*gamma.*epsilon.*ch1: y\tch2: n.*Contents of three_char_t:.*x\ty\tz.*Contents of five_char_t:.*h\te\tl\tl\to.*Contents of int_char_combo_t:.*123\tz.*Sum of the 4 struct values and seed :.*52.*Contents of struct1:.*6\[ \]+0.*Contents of struct2:.*10\[ \]+0.*Contents of struct3:.*12.*0.*Contents of one_double_t:\[ \n\r\t\]+1.111110\[ \n\r\t\]+Contents of one_double_t:\[ \n\r\t\]+-345.340000\[ \n\r\t\]+Contents of one_double_t:\[ \n\r\t\]+546464.200000\[ \n\r\t\]+Contents of two_floats_t:\[ \n\r\t\]+0.234000\t453.100006\[ \n\r\t\]+Contents of two_floats_t:\[ \n\r\t\]+78.345001\t23.090000\[ \n\r\t\]+Contents of two_floats_t:\[ \n\r\t\]+-2.345000\t1.000000.*$gdb_prompt $" {
+ pass "print print_long_arg_list"
+ }
+ -re ".*$gdb_prompt $" { fail "print print_long_arg_list" }
+ timeout { fail "(timeout) print_long_arg_list" }
+ }
+
+
+#go -until 1109
+gdb_test "tbreak 1109" \
+ "Breakpoint.* file .*call-ar-st.c, line 1109.*" \
+ "tbreakpoint line 1109"
+
+gdb_test continue "Continuing\\..*main \\(\\) at .*call-ar-st.c:1109\[ \t\n\r\]+1109.*compute_with_small_structs\\(35\\);" \
+"continue to 1109"
+
+
+#call sum_struct_print(10, *struct1, *struct2, *struct3, *struct4)
+send_gdb "print sum_struct_print(10, *struct1, *struct2, *struct3, *struct4)\n"
+gdb_expect {
+ -re ".*Sum of the 4 struct values and seed :\[ \t\n\r\]+218.*$gdb_prompt $" {
+ pass "print sum_struct_print(10, *struct1, *struct2, *struct3, *struct4)"
+ }
+ -re ".*$gdb_prompt $" { fail "print sum_struct_print(10, *struct1, *struct2, *struct3, *struct4)" }
+ timeout { fail "(timeout) sum_struct_print(10, *struct1, *struct2, *struct3, *struct4)" }
+ }
+
+
+#call print_struct_rep(*struct1, *struct2, *struct3)
+send_gdb "print print_struct_rep(*struct1, *struct2, *struct3)\n"
+gdb_expect {
+ -re ".*Contents of struct1:\[ \t\n\r\]+ 22 0\[ \t\n\r\]+Contents of struct2:\[ \t\n\r\]+ 42 0\[ \t\n\r\]+Contents of struct3:\[ \t\n\r\]+ 62 0\[ \t\n\r\]+.*$gdb_prompt $" {
+ pass "print print_struct_rep(*struct1, *struct2, *struct3)"
+ }
+ -re ".*$gdb_prompt $" { fail "print print_struct_rep(*struct1, *struct2, *struct3)" }
+ timeout { fail "(timeout) print_struct_rep(*struct1, *struct2, *struct3)" }
+ }
+
+send_gdb "print print_one_large_struct(*list1)\n"
+gdb_expect {
+ -re ".* 4 1.*$gdb_prompt $" {
+ pass "print print_one_large_struct(*list1)"
+ }
+ -re ".*$gdb_prompt $" { fail "print print_one_large_struct(*list1)" }
+ timeout { fail "(timeout) print_one_large_struct(*list1)" }
+ }
+
+return
+
+~
diff --git a/gdb/testsuite/gdb.base/call-rt-st.c b/gdb/testsuite/gdb.base/call-rt-st.c
new file mode 100644
index 00000000000..ad40a70e7d4
--- /dev/null
+++ b/gdb/testsuite/gdb.base/call-rt-st.c
@@ -0,0 +1,530 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+/**************************************************************************
+ * TESTS :
+ * function returning large structures, which go on the stack
+ * functions returning varied sized structs which go on in the registers.
+ ***************************************************************************/
+
+
+/* A large structure (> 64 bits) used to test passing large structures as
+ * parameters
+ */
+
+struct array_rep_info_t {
+ int next_index[10];
+ int values[10];
+ int head;
+};
+
+/*****************************************************************************
+ * Small structures ( <= 64 bits). These are used to test passing small
+ * structures as parameters and test argument size promotion.
+ *****************************************************************************/
+
+ /* 64 bits
+ */
+struct small_rep_info_t {
+ int value;
+ int head;
+};
+
+/* 6 bits : really fits in 8 bits and is promoted to 32 bits
+ */
+struct bit_flags_t {
+ unsigned alpha :1;
+ unsigned beta :1;
+ unsigned gamma :1;
+ unsigned delta :1;
+ unsigned epsilon :1;
+ unsigned omega :1;
+};
+
+/* 22 bits : really fits in 40 bits and is promoted to 64 bits
+ */
+struct bit_flags_combo_t {
+ unsigned alpha :1;
+ unsigned beta :1;
+ char ch1;
+ unsigned gamma :1;
+ unsigned delta :1;
+ char ch2;
+ unsigned epsilon :1;
+ unsigned omega :1;
+};
+
+/* 64 bits
+ */
+struct one_double_t {
+ double double1;
+};
+
+/* 64 bits
+ */
+struct two_floats_t {
+ float float1;
+ float float2;
+};
+
+
+/* 24 bits : promoted to 32 bits
+ */
+struct three_char_t {
+ char ch1;
+ char ch2;
+ char ch3;
+};
+
+/* 40 bits : promoted to 64 bits
+ */
+struct five_char_t {
+ char ch1;
+ char ch2;
+ char ch3;
+ char ch4;
+ char ch5;
+};
+
+/* 40 bits : promoted to 64 bits
+ */
+struct int_char_combo_t {
+ int int1;
+ char ch1;
+};
+
+
+/*****************************************************************
+ * LOOP_COUNT :
+ * A do nothing function. Used to provide a point at which calls can be made.
+ *****************************************************************/
+void loop_count () {
+
+ int index;
+
+ for (index=0; index<4; index++);
+}
+
+/*****************************************************************
+ * INIT_BIT_FLAGS :
+ * Initializes a bit_flags_t structure. Can call this function see
+ * the call command behavior when integer arguments do not fit into
+ * registers and must be placed on the stack.
+ * OUT struct bit_flags_t *bit_flags -- structure to be filled
+ * IN unsigned a -- 0 or 1
+ * IN unsigned b -- 0 or 1
+ * IN unsigned g -- 0 or 1
+ * IN unsigned d -- 0 or 1
+ * IN unsigned e -- 0 or 1
+ * IN unsigned o -- 0 or 1
+ *****************************************************************/
+void init_bit_flags (bit_flags,a,b,g,d,e,o)
+struct bit_flags_t *bit_flags;
+unsigned a;
+unsigned b;
+unsigned g;
+unsigned d;
+unsigned e;
+unsigned o;
+{
+
+ bit_flags->alpha = a;
+ bit_flags->beta = b;
+ bit_flags->gamma = g;
+ bit_flags->delta = d;
+ bit_flags->epsilon = e;
+ bit_flags->omega = o;
+}
+
+/*****************************************************************
+ * INIT_BIT_FLAGS_COMBO :
+ * Initializes a bit_flags_combo_t structure. Can call this function
+ * to see the call command behavior when integer and character arguments
+ * do not fit into registers and must be placed on the stack.
+ * OUT struct bit_flags_combo_t *bit_flags_combo -- structure to fill
+ * IN unsigned a -- 0 or 1
+ * IN unsigned b -- 0 or 1
+ * IN char ch1
+ * IN unsigned g -- 0 or 1
+ * IN unsigned d -- 0 or 1
+ * IN char ch2
+ * IN unsigned e -- 0 or 1
+ * IN unsigned o -- 0 or 1
+ *****************************************************************/
+void init_bit_flags_combo (bit_flags_combo, a, b, ch1, g, d, ch2, e, o)
+struct bit_flags_combo_t *bit_flags_combo;
+unsigned a;
+unsigned b;
+char ch1;
+unsigned g;
+unsigned d;
+char ch2;
+unsigned e;
+unsigned o;
+{
+
+ bit_flags_combo->alpha = a;
+ bit_flags_combo->beta = b;
+ bit_flags_combo->ch1 = ch1;
+ bit_flags_combo->gamma = g;
+ bit_flags_combo->delta = d;
+ bit_flags_combo->ch2 = ch2;
+ bit_flags_combo->epsilon = e;
+ bit_flags_combo->omega = o;
+}
+
+
+/*****************************************************************
+ * INIT_ONE_DOUBLE :
+ * OUT struct one_double_t *one_double -- structure to fill
+ * IN double init_val
+ *****************************************************************/
+void init_one_double (one_double, init_val)
+struct one_double_t *one_double;
+double init_val;
+{
+
+ one_double->double1 = init_val;
+}
+
+/*****************************************************************
+ * INIT_TWO_FLOATS :
+ * OUT struct two_floats_t *two_floats -- structure to be filled
+ * IN float init_val1
+ * IN float init_val2
+ *****************************************************************/
+void init_two_floats (two_floats, init_val1, init_val2)
+struct two_floats_t *two_floats;
+float init_val1;
+float init_val2;
+{
+
+ two_floats->float1 = init_val1;
+ two_floats->float2 = init_val2;
+}
+
+/*****************************************************************
+ * INIT_THREE_CHARS :
+ * OUT struct three_char_t *three_char -- structure to be filled
+ * IN char init_val1
+ * IN char init_val2
+ * IN char init_val3
+ *****************************************************************/
+void init_three_chars ( three_char, init_val1, init_val2, init_val3)
+struct three_char_t *three_char;
+char init_val1;
+char init_val2;
+char init_val3;
+{
+
+ three_char->ch1 = init_val1;
+ three_char->ch2 = init_val2;
+ three_char->ch3 = init_val3;
+}
+
+/*****************************************************************
+ * INIT_FIVE_CHARS :
+ * OUT struct five_char_t *five_char -- structure to be filled
+ * IN char init_val1
+ * IN char init_val2
+ * IN char init_val3
+ * IN char init_val4
+ * IN char init_val5
+ *****************************************************************/
+void init_five_chars ( five_char, init_val1, init_val2, init_val3, init_val4, init_val5)
+struct five_char_t *five_char;
+char init_val1;
+char init_val2;
+char init_val3;
+char init_val4;
+char init_val5;
+{
+
+ five_char->ch1 = init_val1;
+ five_char->ch2 = init_val2;
+ five_char->ch3 = init_val3;
+ five_char->ch4 = init_val4;
+ five_char->ch5 = init_val5;
+}
+
+/*****************************************************************
+ * INIT_INT_CHAR_COMBO :
+ * OUT struct int_char_combo_t *combo -- structure to be filled
+ * IN int init_val1
+ * IN char init_val2
+ *****************************************************************/
+void init_int_char_combo ( combo, init_val1, init_val2)
+struct int_char_combo_t *combo;
+int init_val1;
+char init_val2;
+{
+
+ combo->int1 = init_val1;
+ combo->ch1 = init_val2;
+}
+
+/*****************************************************************
+ * INIT_STRUCT_REP :
+ * OUT struct small_rep_into_t *small_struct -- structure to be filled
+ * IN int seed
+ *****************************************************************/
+void init_struct_rep( small_struct, seed)
+struct small_rep_info_t *small_struct;
+int seed;
+
+{
+
+ small_struct->value = 2 + (seed*2);
+ small_struct->head = 0;
+}
+
+/*****************************************************************
+ * PRINT_BIT_FLAGS :
+ * IN struct bit_flags_t bit_flags
+ ****************************************************************/
+struct bit_flags_t print_bit_flags ( bit_flags)
+struct bit_flags_t bit_flags;
+{
+
+ if (bit_flags.alpha) printf("alpha\n");
+ if (bit_flags.beta) printf("beta\n");
+ if (bit_flags.gamma) printf("gamma\n");
+ if (bit_flags.delta) printf("delta\n");
+ if (bit_flags.epsilon) printf("epsilon\n");
+ if (bit_flags.omega) printf("omega\n");
+ return bit_flags;
+
+}
+
+/*****************************************************************
+ * PRINT_BIT_FLAGS_COMBO :
+ * IN struct bit_flags_combo_t bit_flags_combo
+ ****************************************************************/
+struct bit_flags_combo_t print_bit_flags_combo ( bit_flags_combo )
+struct bit_flags_combo_t bit_flags_combo;
+{
+
+ if (bit_flags_combo.alpha) printf("alpha\n");
+ if (bit_flags_combo.beta) printf("beta\n");
+ if (bit_flags_combo.gamma) printf("gamma\n");
+ if (bit_flags_combo.delta) printf("delta\n");
+ if (bit_flags_combo.epsilon) printf("epsilon\n");
+ if (bit_flags_combo.omega) printf("omega\n");
+ printf("ch1: %c\tch2: %c\n", bit_flags_combo.ch1, bit_flags_combo.ch2);
+ return bit_flags_combo;
+
+}
+
+/*****************************************************************
+ * PRINT_ONE_DOUBLE :
+ * IN struct one_double_t one_double
+ ****************************************************************/
+struct one_double_t print_one_double ( one_double )
+struct one_double_t one_double;
+{
+
+ printf("Contents of one_double_t: \n\n");
+ printf("%f\n", one_double.double1);
+ return one_double;
+
+}
+
+/*****************************************************************
+ * PRINT_TWO_FLOATS :
+ * IN struct two_floats_t two_floats
+ ****************************************************************/
+struct two_floats_t print_two_floats ( two_floats )
+struct two_floats_t two_floats;
+{
+
+ printf("Contents of two_floats_t: \n\n");
+ printf("%f\t%f\n", two_floats.float1, two_floats.float2);
+ return two_floats;
+
+}
+
+/*****************************************************************
+ * PRINT_THREE_CHARS :
+ * IN struct three_char_t three_char
+ ****************************************************************/
+struct three_char_t print_three_chars ( three_char )
+struct three_char_t three_char;
+{
+
+ printf("Contents of three_char_t: \n\n");
+ printf("%c\t%c\t%c\n", three_char.ch1, three_char.ch2, three_char.ch3);
+ return three_char;
+
+}
+
+/*****************************************************************
+ * PRINT_FIVE_CHARS :
+ * IN struct five_char_t five_char
+ ****************************************************************/
+struct five_char_t print_five_chars ( five_char )
+struct five_char_t five_char;
+{
+
+ printf("Contents of five_char_t: \n\n");
+ printf("%c\t%c\t%c\t%c\t%c\n", five_char.ch1, five_char.ch2,
+ five_char.ch3, five_char.ch4,
+ five_char.ch5);
+ return five_char;
+
+}
+
+/*****************************************************************
+ * PRINT_INT_CHAR_COMBO :
+ * IN struct int_char_combo_t int_char_combo
+ ****************************************************************/
+struct int_char_combo_t print_int_char_combo ( int_char_combo )
+struct int_char_combo_t int_char_combo;
+{
+
+ printf("Contents of int_char_combo_t: \n\n");
+ printf("%d\t%c\n", int_char_combo.int1, int_char_combo.ch1);
+ return int_char_combo;
+
+}
+
+/*****************************************************************
+ * PRINT_STRUCT_REP :
+ ****************************************************************/
+struct small_rep_info_t print_struct_rep( struct1 )
+struct small_rep_info_t struct1;
+
+{
+
+ printf("Contents of struct1: \n\n");
+ printf("%10d%10d\n", struct1.value, struct1.head);
+ struct1.value =+5;
+
+ return struct1;
+
+
+}
+
+
+struct array_rep_info_t print_one_large_struct( linked_list1 )
+struct array_rep_info_t linked_list1;
+{
+
+
+ printf("%10d%10d\n", linked_list1.values[0],
+ linked_list1.next_index[0]);
+
+ return linked_list1;
+
+}
+
+/*****************************************************************
+ * INIT_ARRAY_REP :
+ * IN struct array_rep_info_t *linked_list
+ * IN int seed
+ ****************************************************************/
+void init_array_rep( linked_list, seed )
+struct array_rep_info_t *linked_list;
+int seed;
+
+{
+
+ int index;
+
+ for (index = 0; index < 10; index++) {
+
+ linked_list->values[index] = (2*index) + (seed*2);
+ linked_list->next_index[index] = index + 1;
+ }
+ linked_list->head = 0;
+}
+
+
+int main () {
+
+ /* variables for large structure testing
+ */
+ int number = 10;
+ struct array_rep_info_t *list1;
+
+ /* variables for testing a small structures and a very long argument list
+ */
+ struct small_rep_info_t *struct1;
+ struct bit_flags_t *flags;
+ struct bit_flags_combo_t *flags_combo;
+ struct three_char_t *three_char;
+ struct five_char_t *five_char;
+ struct int_char_combo_t *int_char_combo;
+ struct one_double_t *d1;
+ struct two_floats_t *f3;
+
+
+ /* Allocate space for large structures
+ */
+ list1 = (struct array_rep_info_t *)malloc(sizeof(struct array_rep_info_t));
+
+ /* Initialize large structures
+ */
+ init_array_rep(list1, 2);
+
+ /* Print large structures
+ */
+ print_one_large_struct(*list1);
+
+ /* Allocate space for small structures
+ */
+ struct1 = (struct small_rep_info_t *)malloc(sizeof(struct small_rep_info_t));
+ flags = (struct bit_flags_t *)malloc(sizeof(struct bit_flags_t));
+ flags_combo = (struct bit_flags_combo_t *)malloc(sizeof(struct bit_flags_combo_t));
+ three_char = (struct three_char_t *)malloc(sizeof(struct three_char_t));
+ five_char = (struct five_char_t *)malloc(sizeof(struct five_char_t));
+ int_char_combo = (struct int_char_combo_t *)malloc(sizeof(struct int_char_combo_t));
+
+ d1 = (struct one_double_t *)malloc(sizeof(struct one_double_t));
+ f3 = (struct two_floats_t *)malloc(sizeof(struct two_floats_t));
+
+ /* Initialize small structures
+ */
+ init_one_double ( d1, 1.11111);
+ init_two_floats ( f3, -2.345, 1.0);
+ init_bit_flags(flags, (unsigned)1, (unsigned)0, (unsigned)1,
+ (unsigned)0, (unsigned)1, (unsigned)0 );
+ init_bit_flags_combo(flags_combo, (unsigned)1, (unsigned)0, 'y',
+ (unsigned)1, (unsigned)0, 'n',
+ (unsigned)1, (unsigned)0 );
+ init_three_chars(three_char, 'x', 'y', 'z');
+ init_five_chars(five_char, 'h', 'e', 'l', 'l', 'o');
+ init_int_char_combo(int_char_combo, 13, '!');
+ init_struct_rep(struct1, 10);
+
+
+ /* Print small structures
+ */
+ print_one_double(*d1);
+ print_two_floats(*f3);
+ print_bit_flags(*flags);
+ print_bit_flags_combo(*flags_combo);
+ print_three_chars(*three_char);
+ print_five_chars(*five_char);
+ print_int_char_combo(*int_char_combo);
+ print_struct_rep(*struct1);
+
+ loop_count();
+
+ return 0;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/gdb/testsuite/gdb.base/call-rt-st.exp b/gdb/testsuite/gdb.base/call-rt-st.exp
new file mode 100644
index 00000000000..12ca14caf57
--- /dev/null
+++ b/gdb/testsuite/gdb.base/call-rt-st.exp
@@ -0,0 +1,230 @@
+# Copyright (C) 1998 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file was written by Elena Zannoni (ezannoni@cygnus.com)
+
+# this file tests command line calls with functions returning structures
+# corresponding source file: call_return_struct.c
+
+
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+set prms_id 0
+set bug_id 0
+
+set testfile "call-rt-st"
+set srcfile ${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+
+
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug additional_flags=-w}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+ }
+
+
+
+# Create and source the file that provides information about the compiler
+# used to compile the test case.
+
+if [get_compiler_info ${binfile}] {
+ return -1;
+}
+
+# The a29k can't call functions, so don't even bother with this test.
+if [target_info exists gdb,cannot_call_functions] {
+ setup_xfail "*-*-*" 2416
+ fail "This target can not call functions"
+ continue
+}
+
+# Set the current language to C. This counts as a test. If it
+# fails, then we skip the other tests.
+
+proc set_lang_c {} {
+ global gdb_prompt
+
+ send_gdb "set language c\n"
+ gdb_expect {
+ -re ".*$gdb_prompt $" {}
+ timeout { fail "set language c (timeout)" ; return 0; }
+ }
+
+ send_gdb "show language\n"
+ gdb_expect {
+ -re ".* source language is \"c\".*$gdb_prompt $" {
+ pass "set language to \"c\""
+ return 1
+ }
+ -re ".*$gdb_prompt $" {
+ fail "setting language to \"c\""
+ return 0
+ }
+ timeout {
+ fail "can't show language (timeout)"
+ return 0
+ }
+ }
+}
+
+
+
+source ${binfile}.ci
+
+
+# Start with a fresh gdb.
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+send_gdb "set print sevenbit-strings\n" ; gdb_expect -re "$gdb_prompt $"
+send_gdb "set print address off\n" ; gdb_expect -re "$gdb_prompt $"
+send_gdb "set width 0\n" ; gdb_expect -re "$gdb_prompt $"
+
+
+if ![runto_main] then {
+ perror "couldn't run to breakpoint"
+ continue
+}
+
+
+gdb_test "break loop_count" \
+ "Breakpoint.* file .*call-rt-st.c, line 106\\." \
+ "breakpoint loop_count"
+
+
+send_gdb "continue\n"
+gdb_expect {
+ -re "Continuing\\..*Breakpoint.*loop_count \\(\\) at.*call-rt-st.c:106\[ \t\r\n\]+106\[\t \]+for \\(index=0; index.4; index..\\);\[\r\n \]+$gdb_prompt $" {
+ pass "continue to loop_count"}
+ -re ".*$gdb_prompt $" { fail "continue to loop_count"}
+ timeout { fail "(timeout) continue to loop_count"}
+}
+
+send_gdb "finish\n"
+gdb_expect {
+ -re "Run till exit from .0 loop_count \\(\\) at.*call-rt-st.c:106\[ \t\r\n\]+main \\(\\) at.*call-rt-st.c:514\[ \t\r\n\]+514\[\t \]+return 0;.*$gdb_prompt $" {
+ pass "finish out from loop_count"}
+ -re ".*$gdb_prompt $" { fail "finish out from loop_count"}
+ timeout { fail "(timeout)finish out from loop_count"}
+}
+
+
+send_gdb "print print_struct_rep(*struct1)\n"
+gdb_expect {
+ -re ".*Contents of struct1:\[ \t\n\r\]+22\[ \t\]+0\[ \t\n\r\]+.\[0-9\]+ = \{value = 5, head = 0\}.*$gdb_prompt $" {
+ pass "print print_struct_rep(*struct1, *struct2, *struct3)"
+ }
+ -re ".*$gdb_prompt $" { fail "print print_struct_rep(*struct1, *struct2, *struct3)" }
+ timeout { fail "(timeout) print_struct_rep(*struct1, *struct2, *struct3)" }
+ }
+
+send_gdb "print print_one_large_struct(*list1)\n"
+gdb_expect {
+ -re ".*\[ \t\]+4\[ \t\]+1\[ \r\n\]+.\[0-9\]+ = \{next_index = \{1, 2, 3, 4, 5, 6, 7, 8, 9, 10\}, values = \{4, 6, 8, 10, 12, 14, 16, 18, 20, 22\}, head = 0\}.*$gdb_prompt $" {
+ pass "print print_one_large_struct(*list1)"
+ }
+ -re ".*$gdb_prompt $" { fail "print print_one_large_struct(*list1)" }
+ timeout { fail "(timeout) print_one_large_struct(*list1)" }
+ }
+
+send_gdb "print print_one_double(*d1)\n"
+gdb_expect {
+ -re ".*Contents of one_double_t:\[ \r\n\]+1\\.111110\[ \r\n\]+.\[0-9\]+ = \{double1 = 1\\.11111\}.*$gdb_prompt $" {
+ pass "print print_one_double(*d1)"
+ }
+ -re ".*$gdb_prompt $" { fail "print print_one_double(*d1)" }
+ timeout { fail "(timeout) print_one_double(*d1)" }
+ }
+
+
+
+send_gdb "print print_two_floats(*f3)\n"
+gdb_expect {
+ -re ".*Contents of two_floats_t:\[ \r\n\]+-2\\.345000\[ \t]+1\\.000000\[ \r\n\]+.\[0-9\]+ = \{float1 = -2\\.34500003, float2 = 1\}.*$gdb_prompt $" {
+ pass "print print_two_floats(*f3)"
+ }
+ -re ".*$gdb_prompt $" { fail "print print_two_floats(*f3)" }
+ timeout { fail "(timeout) print_two_floats(*f3)" }
+ }
+
+send_gdb "print print_bit_flags(*flags)\n"
+gdb_expect {
+ -re ".*alpha\[ \r\n\]+gamma\[ \r\n\]+epsilon\[ \r\n\]+.\[0-9\]+ = \{alpha = 1, beta = 0, gamma = 1, delta = 0, epsilon = 1, omega = 0\}\[ \r\n\]+$gdb_prompt $" {
+ pass "print print_bit_flags(*flags)"
+ }
+ -re ".*$gdb_prompt $" { fail "print print_bit_flags(*flags)" }
+ timeout { fail "(timeout) print_bit_flags(*flags)" }
+ }
+
+send_gdb "print print_bit_flags_combo(*flags_combo)\n"
+gdb_expect {
+ -re ".*alpha\[ \r\n\]+gamma\[ \r\n\]+epsilon\[ \r\n\]+ch1: y\[ \t\]+ch2: n\[ \r\n\]+.\[0-9\]+ = \{alpha = 1, beta = 0, ch1 = 121 'y', gamma = 1, delta = 0, ch2 = 110 'n', epsilon = 1, omega = 0\}\[ \r\n\]+$gdb_prompt $" {
+ pass "print print_bit_flags_combo(*flags_combo)"
+ }
+ -re ".*$gdb_prompt $" { fail "print print_bit_flags_combo(*flags_combo)" }
+ timeout { fail "(timeout) print_bit_flags_combo(*flags_combo)" }
+ }
+
+send_gdb "print print_three_chars(*three_char)\n"
+gdb_expect {
+ -re ".*Contents of three_char_t:\[ \r\n\]+x\[ \t\]+y\[ \t\]+z\[ \r\n\]+.\[0-9\]+ = \{ch1 = 120 'x', ch2 = 121 'y', ch3 = 122 'z'\}\[ \r\n\]+$gdb_prompt $" {
+ pass "print print_three_chars(*three_char)"
+ }
+ -re ".*$gdb_prompt $" { fail "print print_three_chars(*three_char)" }
+ timeout { fail "(timeout) print_three_chars(*three_char)" }
+ }
+
+send_gdb "print print_five_chars(*five_char)\n"
+gdb_expect {
+ -re ".*Contents of five_char_t:\[ \r\n\]+h\[ \t\]+e\[ \t\]+l\[ \t\]+l\[ \t\]+o\[ \r\n\]+.\[0-9\]+ = \{ch1 = 104 'h', ch2 = 101 'e', ch3 = 108 'l', ch4 = 108 'l', ch5 = 111 'o'\}\[ \r\n\]+$gdb_prompt $" {
+ pass "print print_five_chars(*five_char)"
+ }
+ -re ".*$gdb_prompt $" { fail "print print_five_chars(*five_char)" }
+ timeout { fail "(timeout) print_five_chars(*five_char)" }
+ }
+
+send_gdb "print print_int_char_combo(*int_char_combo)\n"
+gdb_expect {
+ -re ".*Contents of int_char_combo_t:\[ \r\n\]+13\[ \t\]+!\[ \r\n\]+.\[0-9\]+ = \{int1 = 13, ch1 = 33 '!'\}\[ \r\n\]+$gdb_prompt $" {
+ pass "print print_int_char_combo(*int_char_combo)"
+ }
+ -re ".*$gdb_prompt $" { fail "print print_int_char_combo(*int_char_combo)" }
+ timeout { fail "(timeout) print_int_char_combo(*int_char_combo)" }
+ }
+
+return
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/gdb/testsuite/gdb.base/call-strs.c b/gdb/testsuite/gdb.base/call-strs.c
new file mode 100644
index 00000000000..9ba875b5d32
--- /dev/null
+++ b/gdb/testsuite/gdb.base/call-strs.c
@@ -0,0 +1,54 @@
+#include <stdio.h>
+char buf[100];
+char bigbuf[1000];
+char * s;
+
+char * str_func1(s1)
+char *s1;
+{
+ printf("first string arg is: %s\n", s1);
+ strcpy(bigbuf, s1);
+ return bigbuf;
+}
+
+char * str_func(s1,
+ s2,
+ s3,
+ s4,
+ s5,
+ s6,
+ s7)
+char * s1;
+char * s2;
+char * s3;
+char * s4;
+char * s5;
+char * s6;
+char * s7;
+{
+ printf("first string arg is: %s\n", s1);
+ printf("second string arg is: %s\n", s2);
+ printf("third string arg is: %s\n", s3);
+ printf("fourth string arg is: %s\n", s4);
+ printf("fifth string arg is: %s\n", s5);
+ printf("sixth string arg is: %s\n", s6);
+ printf("seventh string arg is: %s\n", s7);
+ strcpy(bigbuf, s1);
+ strcat(bigbuf, s2);
+ strcat(bigbuf, s3);
+ strcat(bigbuf, s4);
+ strcat(bigbuf, s5);
+ strcat(bigbuf, s6);
+ strcat(bigbuf, s7);
+ return bigbuf;
+}
+
+
+main()
+{
+ s = &buf[0];
+ strcpy(buf, "test string");
+ str_func("abcd", "efgh", "ijkl", "mnop", "qrst", "uvwx", "yz12");
+ str_func1("abcd");
+}
+
diff --git a/gdb/testsuite/gdb.base/call-strs.exp b/gdb/testsuite/gdb.base/call-strs.exp
new file mode 100644
index 00000000000..20f358a3b63
--- /dev/null
+++ b/gdb/testsuite/gdb.base/call-strs.exp
@@ -0,0 +1,242 @@
+# Copyright (C) 1998 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file was written by Elena Zannoni (ezannoni@cygnus.com)
+
+# This test deals with calling functions which have strings as parameters.
+# it plays around with constant strings.
+# the corresponding source file is call-strs.c
+#
+
+#debug strarg
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+set prms_id 0
+set bug_id 0
+
+set testfile "call-strs"
+set srcfile ${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+
+
+# The a29k can't call functions, so don't even bother with this test.
+if [target_info exists gdb,cannot_call_functions] {
+ setup_xfail "*-*-*" 2416
+ fail "This target can not call functions"
+ continue
+}
+
+# Set the current language to C. This counts as a test. If it
+# fails, then we skip the other tests.
+
+proc set_lang_c {} {
+ global gdb_prompt
+
+ send_gdb "set language c\n"
+ gdb_expect {
+ -re ".*$gdb_prompt $" {}
+ timeout { fail "set language c (timeout)" ; return 0; }
+ }
+
+ send_gdb "show language\n"
+ gdb_expect {
+ -re ".* source language is \"c\".*$gdb_prompt $" {
+ pass "set language to \"c\""
+ return 1
+ }
+ -re ".*$gdb_prompt $" {
+ fail "setting language to \"c\""
+ return 0
+ }
+ timeout {
+ fail "can't show language (timeout)"
+ return 0
+ }
+ }
+}
+
+
+
+# Start with a fresh gdb.
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+send_gdb "set print sevenbit-strings\n" ; gdb_expect -re "$gdb_prompt $"
+send_gdb "set print address off\n" ; gdb_expect -re "$gdb_prompt $"
+send_gdb "set width 0\n" ; gdb_expect -re "$gdb_prompt $"
+
+
+if ![runto_main] then {
+ perror "couldn't run to breakpoint"
+ continue
+}
+
+#step
+send_gdb "step\n"
+gdb_expect {
+ -re ".*strcpy\\(buf, \"test string\"\\);.*$gdb_prompt $" {pass "step after assignment to s"}
+ -re ".*$gdb_prompt $" { fail "step after assignment to s" }
+ timeout { fail "step after assignment to s (timeout)" }
+ }
+
+
+#step
+send_gdb "step\n"
+gdb_expect {
+ -re ".*str_func\\(\"abcd\", \"efgh\", \"ijkl\", \"mnop\", \"qrst\", \"uvwx\", \"yz12\"\\);.*$gdb_prompt $" {pass "step after strcpy"}
+ -re ".*$gdb_prompt $" { fail "step after strcpy" }
+ timeout { fail "step after strcpy (timeout)" }
+ }
+
+#print buf
+send_gdb "print buf\n"
+gdb_expect {
+ -re ".*\"test string\",.*repeats 88 times.*$gdb_prompt $" {
+ pass "print buf"
+ }
+ -re ".*$gdb_prompt $" { fail "print buf" }
+ timeout { fail "(timeout) print buf" }
+ }
+
+
+#print s
+send_gdb "print s\n"
+gdb_expect {
+ -re ".*= \"test string\".*$gdb_prompt $" {
+ pass "print s"
+ }
+ -re ".*$gdb_prompt $" { fail "print s" }
+ timeout { fail "(timeout) print sum_array_print(10, *list1, *list2, *list3, *list4)" }
+ }
+
+
+#print str_func1(s)
+send_gdb "print str_func1(s)\n"
+gdb_expect {
+ -re "first string arg is: test string.*\"test string\".*$gdb_prompt $" {
+ pass "print str_func1(s)"
+ }
+ -re ".*$gdb_prompt $" { fail "print str_func1(s)" }
+ timeout { fail "(timeout) print str_func1(s)" }
+ }
+
+
+#print str_func1("test string")
+send_gdb "print str_func1(\"test string\")\n"
+gdb_expect {
+ -re "first string arg is: test string.*\"test string\".*$gdb_prompt $" {
+ pass "print str_func1(\"test string\")"
+ }
+ -re ".*$gdb_prompt $" { fail "print str_func1(\"test string\")" }
+ timeout { fail "(timeout) print str_func1(\"test string\")" }
+ }
+
+#call str_func1(s)
+send_gdb "call str_func1(s)\n"
+gdb_expect {
+ -re "first string arg is: test string.*\"test string\".*$gdb_prompt $" {
+ pass "call str_func1(s)"
+ }
+ -re ".*$gdb_prompt $" { fail "call str_func1(s)" }
+ timeout { fail "(timeout) call str_func1(s)" }
+ }
+
+#call str_func1("test string")
+send_gdb "call str_func1(\"test string\")\n"
+gdb_expect {
+ -re "first string arg is: test string.*\"test string\".*$gdb_prompt $" {
+ pass "call str_func1(\"test string\")"
+ }
+ -re ".*$gdb_prompt $" { fail "call str_func1(\"test string\")" }
+ timeout { fail "(timeout) call str_func1(\"test string\")" }
+ }
+
+#print str_func1(buf)
+send_gdb "print str_func1(buf)\n"
+gdb_expect {
+ -re "first string arg is: test string.*\"test string\".*$gdb_prompt $" {
+ pass "print str_func1(buf)"
+ }
+ -re ".*$gdb_prompt $" { fail "print str_func1(buf)" }
+ timeout { fail "(timeout) print str_func1(buf)" }
+ }
+
+#call str_func1(buf)
+send_gdb "call str_func1(buf)\n"
+gdb_expect {
+ -re "first string arg is: test string.*\"test string\".*$gdb_prompt $" {
+ pass "call str_func1(buf)"
+ }
+ -re ".*$gdb_prompt $" { fail "call str_func1(buf)" }
+ timeout { fail "(timeout) call str_func1(buf)" }
+ }
+
+#print str_func("a","b","c","d","e","f","g")
+send_gdb "print str_func(\"a\",\"b\",\"c\",\"d\",\"e\",\"f\",\"g\")\n"
+gdb_expect {
+ -re "first string arg is: a\[ \t\r\n\]+second string arg is: b\[ \t\r\n\]+third string arg is: c\[ \t\r\n\]+fourth string arg is: d\[ \t\r\n\]+fifth string arg is: e\[ \t\r\n\]+sixth string arg is: f\[ \t\r\n\]+seventh string arg is: g\[ \t\r\n\]+.*= \"abcdefg\".*$gdb_prompt $" {
+ pass "print str_func(\"a\",\"b\",\"c\",\"d\",\"e\",\"f\",\"g\")"
+ }
+ -re ".*$gdb_prompt $" { fail "print str_func(\"a\",\"b\",\"c\",\"d\",\"e\",\"f\",\"g\")" }
+ timeout { fail "(timeout) print str_func(\"a\",\"b\",\"c\",\"d\",\"e\",\"f\",\"g\")" }
+ }
+
+#call str_func("a","b","c","d","e","f","g")
+send_gdb "call str_func(\"a\",\"b\",\"c\",\"d\",\"e\",\"f\",\"g\")\n"
+gdb_expect {
+ -re "first string arg is: a\[ \t\r\n\]+second string arg is: b\[ \t\r\n\]+third string arg is: c\[ \t\r\n\]+fourth string arg is: d\[ \t\r\n\]+fifth string arg is: e\[ \t\r\n\]+sixth string arg is: f\[ \t\r\n\]+seventh string arg is: g\[ \t\r\n\]+.*= \"abcdefg\".*$gdb_prompt $" {
+ pass "call str_func(\"a\",\"b\",\"c\",\"d\",\"e\",\"f\",\"g\")"
+ }
+ -re ".*$gdb_prompt $" { fail "call str_func(\"a\",\"b\",\"c\",\"d\",\"e\",\"f\",\"g\")" }
+ timeout { fail "(timeout) call str_func(\"a\",\"b\",\"c\",\"d\",\"e\",\"f\",\"g\")" }
+ }
+
+#print str_func(s,s,s,s,s,s,s,s)
+send_gdb "print str_func(s,s,s,s,s,s,s,s)\n"
+gdb_expect {
+ -re "first string arg is: test string\[ \t\r\n\]+second string arg is: test string\[ \t\r\n\]+third string arg is: test string\[ \t\r\n\]+fourth string arg is: test string\[ \t\r\n\]+fifth string arg is: test string\[ \t\r\n\]+sixth string arg is: test string\[ \t\r\n\]+seventh string arg is: test string\[ \t\r\n\]+.*\"test stringtest stringtest stringtest stringtest stringtest stringtest string\".*$gdb_prompt $" {
+ pass "print str_func(s,s,s,s,s,s,s,s)"
+ }
+ -re ".*$gdb_prompt $" { fail "print str_func(s,s,s,s,s,s,s,s)" }
+ timeout { fail "(timeout) print str_func(s,s,s,s,s,s,s,s)" }
+ }
+
+#call str_func(s,s,s,s,s,s,s,s)
+send_gdb "call str_func(s,s,s,s,s,s,s,s)\n"
+gdb_expect {
+ -re "first string arg is: test string\[ \t\r\n\]+second string arg is: test string\[ \t\r\n\]+third string arg is: test string\[ \t\r\n\]+fourth string arg is: test string\[ \t\r\n\]+fifth string arg is: test string\[ \t\r\n\]+sixth string arg is: test string\[ \t\r\n\]+seventh string arg is: test string\[ \t\r\n\]+.*\"test stringtest stringtest stringtest stringtest stringtest stringtest string\".*$gdb_prompt $" {
+ pass "call str_func(s,s,s,s,s,s,s,s)"
+ }
+ -re ".*$gdb_prompt $" { fail "call str_func(s,s,s,s,s,s,s,s)" }
+ timeout { fail "(timeout) call str_func(s,s,s,s,s,s,s,s)" }
+ }
+
+gdb_exit
+return 0
+~
diff --git a/gdb/testsuite/gdb.base/callfuncs.c b/gdb/testsuite/gdb.base/callfuncs.c
new file mode 100644
index 00000000000..56b9ba8153b
--- /dev/null
+++ b/gdb/testsuite/gdb.base/callfuncs.c
@@ -0,0 +1,280 @@
+/* Support program for testing gdb's ability to call functions
+ in the inferior, pass appropriate arguments to those functions,
+ and get the returned result. */
+
+#ifdef NO_PROTOTYPES
+#define PARAMS(paramlist) ()
+#else
+#define PARAMS(paramlist) paramlist
+#endif
+
+char char_val1 = 'a';
+char char_val2 = 'b';
+
+short short_val1 = 10;
+short short_val2 = -23;
+
+int int_val1 = 87;
+int int_val2 = -26;
+
+long long_val1 = 789;
+long long_val2 = -321;
+
+float float_val1 = 3.14159;
+float float_val2 = -2.3765;
+
+double double_val1 = 45.654;
+double double_val2 = -67.66;
+
+#define DELTA (0.001)
+
+char *string_val1 = "string 1";
+char *string_val2 = "string 2";
+
+char char_array_val1[] = "carray 1";
+char char_array_val2[] = "carray 2";
+
+struct struct1 {
+ char c;
+ short s;
+ int i;
+ long l;
+ float f;
+ double d;
+ char a[4];
+} struct_val1 = { 'x', 87, 76, 51, 2.1234, 9.876, "foo" };
+
+/* Some functions that can be passed as arguments to other test
+ functions, or called directly. */
+
+int add (a, b)
+int a, b;
+{
+ return (a + b);
+}
+
+int doubleit (a)
+int a;
+{
+ return (a + a);
+}
+
+int (*func_val1) PARAMS((int,int)) = add;
+int (*func_val2) PARAMS((int)) = doubleit;
+
+/* An enumeration and functions that test for specific values. */
+
+enum enumtype { enumval1, enumval2, enumval3 };
+enum enumtype enum_val1 = enumval1;
+enum enumtype enum_val2 = enumval2;
+enum enumtype enum_val3 = enumval3;
+
+int t_enum_value1 (enum_arg)
+enum enumtype enum_arg;
+{
+ return (enum_arg == enum_val1);
+}
+
+int t_enum_value2 (enum_arg)
+enum enumtype enum_arg;
+{
+ return (enum_arg == enum_val2);
+}
+
+int t_enum_value3 (enum_arg)
+enum enumtype enum_arg;
+{
+ return (enum_arg == enum_val3);
+}
+
+/* A function that takes a vector of integers (along with an explicit
+ count) and returns their sum. */
+
+int sum_args (argc, argv)
+int argc;
+int argv[];
+{
+ int sumval = 0;
+ int idx;
+
+ for (idx = 0; idx < argc; idx++)
+ {
+ sumval += argv[idx];
+ }
+ return (sumval);
+}
+
+/* Test that we can call functions that take structs and return
+ members from that struct */
+
+char t_structs_c (tstruct) struct struct1 tstruct; { return (tstruct.c); }
+short t_structs_s (tstruct) struct struct1 tstruct; { return (tstruct.s); }
+int t_structs_i (tstruct) struct struct1 tstruct; { return (tstruct.i); }
+long t_structs_l (tstruct) struct struct1 tstruct; { return (tstruct.l); }
+float t_structs_f (tstruct) struct struct1 tstruct; { return (tstruct.f); }
+double t_structs_d (tstruct) struct struct1 tstruct; { return (tstruct.d); }
+char *t_structs_a (tstruct) struct struct1 tstruct; { return (tstruct.a); }
+
+/* Test that calling functions works if there are a lot of arguments. */
+int
+sum10 (i0, i1, i2, i3, i4, i5, i6, i7, i8, i9)
+ int i0, i1, i2, i3, i4, i5, i6, i7, i8, i9;
+{
+ return i0 + i1 + i2 + i3 + i4 + i5 + i6 + i7 + i8 + i9;
+}
+
+/* Test that args are passed in the right order. */
+int
+cmp10 (i0, i1, i2, i3, i4, i5, i6, i7, i8, i9)
+ int i0, i1, i2, i3, i4, i5, i6, i7, i8, i9;
+{
+ return
+ (i0 == 0) && (i1 == 1) && (i2 == 2) && (i3 == 3) && (i4 == 4) &&
+ (i5 == 5) && (i6 == 6) && (i7 == 7) && (i8 == 8) && (i9 == 9);
+}
+
+
+/* Gotta have a main to be able to generate a linked, runnable
+ executable, and also provide a useful place to set a breakpoint. */
+extern void * malloc() ;
+int main ()
+{
+#ifdef usestubs
+ set_debug_traps();
+ breakpoint();
+#endif
+ malloc(1);
+ t_structs_c(struct_val1);
+ return 0 ;
+}
+
+/* Functions that expect specific values to be passed and return
+ either 0 or 1, depending upon whether the values were
+ passed incorrectly or correctly, respectively. */
+
+int t_char_values (char_arg1, char_arg2)
+char char_arg1, char_arg2;
+{
+ return ((char_arg1 == char_val1) && (char_arg2 == char_val2));
+}
+
+int
+#ifdef NO_PROTOTYPES
+t_small_values (arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10)
+ char arg1;
+ short arg2;
+ int arg3;
+ char arg4;
+ short arg5;
+ char arg6;
+ short arg7;
+ int arg8;
+ short arg9;
+ short arg10;
+#else
+t_small_values (char arg1, short arg2, int arg3, char arg4, short arg5,
+ char arg6, short arg7, int arg8, short arg9, short arg10)
+#endif
+{
+ return arg1 + arg2 + arg3 + arg4 + arg5 + arg6 + arg7 + arg8 + arg9 + arg10;
+}
+
+int t_short_values (short_arg1, short_arg2)
+short short_arg1, short_arg2;
+{
+ return ((short_arg1 == short_val1) && (short_arg2 == short_val2));
+}
+
+int t_int_values (int_arg1, int_arg2)
+int int_arg1, int_arg2;
+{
+ return ((int_arg1 == int_val1) && (int_arg2 == int_val2));
+}
+
+int t_long_values (long_arg1, long_arg2)
+long long_arg1, long_arg2;
+{
+ return ((long_arg1 == long_val1) && (long_arg2 == long_val2));
+}
+
+int t_float_values (float_arg1, float_arg2)
+float float_arg1, float_arg2;
+{
+ return ((float_arg1 - float_val1) < DELTA
+ && (float_arg1 - float_val1) > -DELTA
+ && (float_arg2 - float_val2) < DELTA
+ && (float_arg2 - float_val2) > -DELTA);
+}
+
+int
+#ifdef NO_PROTOTYPES
+/* In this case we are just duplicating t_float_values, but that is the
+ easiest way to deal with either ANSI or non-ANSI. */
+t_float_values2 (float_arg1, float_arg2)
+ float float_arg1, float_arg2;
+#else
+t_float_values2 (float float_arg1, float float_arg2)
+#endif
+{
+ return ((float_arg1 - float_val1) < DELTA
+ && (float_arg1 - float_val1) > -DELTA
+ && (float_arg2 - float_val2) < DELTA
+ && (float_arg2 - float_val2) > -DELTA);
+}
+
+int t_double_values (double_arg1, double_arg2)
+double double_arg1, double_arg2;
+{
+ return ((double_arg1 - double_val1) < DELTA
+ && (double_arg1 - double_val1) > -DELTA
+ && (double_arg2 - double_val2) < DELTA
+ && (double_arg2 - double_val2) > -DELTA);
+}
+
+int t_string_values (string_arg1, string_arg2)
+char *string_arg1, *string_arg2;
+{
+ return (!strcmp (string_arg1, string_val1) &&
+ !strcmp (string_arg2, string_val2));
+}
+
+int t_char_array_values (char_array_arg1, char_array_arg2)
+char char_array_arg1[], char_array_arg2[];
+{
+ return (!strcmp (char_array_arg1, char_array_val1) &&
+ !strcmp (char_array_arg2, char_array_val2));
+}
+
+
+/* This used to simply compare the function pointer arguments with
+ known values for func_val1 and func_val2. Doing so is valid ANSI
+ code, but on some machines (RS6000, HPPA, others?) it may fail when
+ called directly by GDB.
+
+ In a nutshell, it's not possible for GDB to determine when the address
+ of a function or the address of the function's stub/trampoline should
+ be passed.
+
+ So, to avoid GDB lossage in the common case, we perform calls through the
+ various function pointers and compare the return values. For the HPPA
+ at least, this allows the common case to work.
+
+ If one wants to try something more complicated, pass the address of
+ a function accepting a "double" as one of its first 4 arguments. Call
+ that function indirectly through the function pointer. This would fail
+ on the HPPA. */
+
+int t_func_values (func_arg1, func_arg2)
+int (*func_arg1) PARAMS ((int, int));
+int (*func_arg2) PARAMS ((int));
+{
+ return ((*func_arg1) (5,5) == (*func_val1) (5,5)
+ && (*func_arg2) (6) == (*func_val2) (6));
+}
+
+int t_call_add (func_arg1, a, b)
+int (*func_arg1) PARAMS ((int, int));
+int a, b;
+{
+ return ((*func_arg1)(a, b));
+}
diff --git a/gdb/testsuite/gdb.base/callfuncs.exp b/gdb/testsuite/gdb.base/callfuncs.exp
new file mode 100644
index 00000000000..19b5c965a94
--- /dev/null
+++ b/gdb/testsuite/gdb.base/callfuncs.exp
@@ -0,0 +1,269 @@
+# Copyright (C) 92, 96, 1997 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file was written by Fred Fish. (fnf@cygnus.com)
+# and modified by Bob Manson. (manson@cygnus.com)
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+set prms_id 0
+set bug_id 0
+
+set testfile "callfuncs"
+set srcfile ${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+
+set prototypes 1
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } {
+ set prototypes 0;
+ # built the second test case since we can't use prototypes
+ warning "Prototypes not supported, rebuilding with -DNO_PROTOTYPES"
+ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug additional_flags=-DNO_PROTOTYPES}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+ }
+}
+
+# Create and source the file that provides information about the compiler
+# used to compile the test case.
+
+if [get_compiler_info ${binfile}] {
+ return -1;
+}
+
+# The a29k can't call functions, so don't even bother with this test.
+if [target_info exists gdb,cannot_call_functions] {
+ setup_xfail "*-*-*" 2416
+ fail "This target can not call functions"
+ continue
+}
+
+# Set the current language to C. This counts as a test. If it
+# fails, then we skip the other tests.
+
+proc set_lang_c {} {
+ global gdb_prompt
+
+ send_gdb "set language c\n"
+ gdb_expect {
+ -re ".*$gdb_prompt $" {}
+ timeout { fail "set language c (timeout)" ; return 0; }
+ }
+
+ send_gdb "show language\n"
+ gdb_expect {
+ -re ".* source language is \"c\".*$gdb_prompt $" {
+ pass "set language to \"c\""
+ return 1
+ }
+ -re ".*$gdb_prompt $" {
+ fail "setting language to \"c\""
+ return 0
+ }
+ timeout {
+ fail "can't show language (timeout)"
+ return 0
+ }
+ }
+}
+
+# FIXME: Before calling this proc, we should probably verify that
+# we can call inferior functions and get a valid integral value
+# returned.
+# Note that it is OK to check for 0 or 1 as the returned values, because C
+# specifies that the numeric value of a relational or logical expression
+# (computed in the inferior) is 1 for true and 0 for false.
+
+proc do_function_calls {} {
+ global prototypes
+ global gcc_compiled
+ # We need to up this because this can be really slow on some boards.
+ set timeout 60;
+
+ gdb_test "p t_char_values(0,0)" " = 0"
+ gdb_test "p t_char_values('a','b')" " = 1"
+ gdb_test "p t_char_values(char_val1,char_val2)" " = 1"
+ gdb_test "p t_char_values('a',char_val2)" " = 1"
+ gdb_test "p t_char_values(char_val1,'b')" " = 1"
+
+ gdb_test "p t_short_values(0,0)" " = 0"
+ gdb_test "p t_short_values(10,-23)" " = 1"
+ gdb_test "p t_short_values(short_val1,short_val2)" " = 1"
+ gdb_test "p t_short_values(10,short_val2)" " = 1"
+ gdb_test "p t_short_values(short_val1,-23)" " = 1"
+
+ gdb_test "p t_int_values(0,0)" " = 0"
+ gdb_test "p t_int_values(87,-26)" " = 1"
+ gdb_test "p t_int_values(int_val1,int_val2)" " = 1"
+ gdb_test "p t_int_values(87,int_val2)" " = 1"
+ gdb_test "p t_int_values(int_val1,-26)" " = 1"
+
+ gdb_test "p t_long_values(0,0)" " = 0"
+ gdb_test "p t_long_values(789,-321)" " = 1"
+ gdb_test "p t_long_values(long_val1,long_val2)" " = 1"
+ gdb_test "p t_long_values(789,long_val2)" " = 1"
+ gdb_test "p t_long_values(long_val1,-321)" " = 1"
+
+ if ![target_info exists gdb,skip_float_tests] {
+ gdb_test "p t_float_values(0.0,0.0)" " = 0"
+
+ # These next four tests fail on the mn10300.
+ # The first value is passed in regs, the other in memory.
+ # Gcc emits different stabs for the two parameters; the first is
+ # claimed to be a float, the second a double.
+ # dbxout.c in gcc claims this is the desired behavior.
+ setup_xfail "mn10300-*-*"
+ gdb_test "p t_float_values(3.14159,-2.3765)" " = 1"
+ setup_xfail "mn10300-*-*"
+ gdb_test "p t_float_values(float_val1,float_val2)" " = 1"
+ setup_xfail "mn10300-*-*"
+ gdb_test "p t_float_values(3.14159,float_val2)" " = 1"
+ setup_xfail "mn10300-*-*"
+ gdb_test "p t_float_values(float_val1,-2.3765)" " = 1"
+
+ # Test passing of arguments which might not be widened.
+ gdb_test "p t_float_values2(0.0,0.0)" " = 0"
+
+ # Although PR 5318 mentions SunOS specifically, this seems
+ # to be a generic problem on quite a few platforms.
+ if $prototypes then {
+ setup_xfail "hppa*-*-*" "sparc-*-*" "mips*-*-*" 5318
+ if {!$gcc_compiled} then {
+ setup_xfail "alpha-dec-osf2*" "i*86-*-sysv4*" 5318
+ }
+ }
+ gdb_test "p t_float_values2(3.14159,float_val2)" " = 1"
+ gdb_test "p t_small_values(1,2,3,4,5,6,7,8,9,10)" " = 55"
+
+ gdb_test "p t_double_values(0.0,0.0)" " = 0"
+ gdb_test "p t_double_values(45.654,-67.66)" " = 1"
+ gdb_test "p t_double_values(double_val1,double_val2)" " = 1"
+ gdb_test "p t_double_values(45.654,double_val2)" " = 1"
+ gdb_test "p t_double_values(double_val1,-67.66)" " = 1"
+ }
+
+ gdb_test "p t_string_values(string_val2,string_val1)" " = 0"
+ gdb_test "p t_string_values(string_val1,string_val2)" " = 1"
+ gdb_test "p t_string_values(\"string 1\",\"string 2\")" " = 1"
+ gdb_test "p t_string_values(\"string 1\",string_val2)" " = 1"
+ gdb_test "p t_string_values(string_val1,\"string 2\")" " = 1"
+
+ gdb_test "p t_char_array_values(char_array_val2,char_array_val1)" " = 0"
+ gdb_test "p t_char_array_values(char_array_val1,char_array_val2)" " = 1"
+ gdb_test "p t_char_array_values(\"carray 1\",\"carray 2\")" " = 1"
+ gdb_test "p t_char_array_values(\"carray 1\",char_array_val2)" " = 1"
+ gdb_test "p t_char_array_values(char_array_val1,\"carray 2\")" " = 1"
+
+ gdb_test "p doubleit(4)" " = 8"
+ gdb_test "p add(4,5)" " = 9"
+ gdb_test "p t_func_values(func_val2,func_val1)" " = 0"
+ gdb_test "p t_func_values(func_val1,func_val2)" " = 1"
+
+ # On the rs6000, we need to pass the address of the trampoline routine,
+ # not the address of add itself. I don't know how to go from add to
+ # the address of the trampoline. Similar problems exist on the HPPA,
+ # and in fact can present an unsolvable problem as the stubs may not
+ # even exist in the user's program. We've slightly recoded t_func_values
+ # to avoid such problems in the common case. This may or may not help
+ # the RS6000.
+ setup_xfail "rs6000*-*-*"
+ setup_xfail "powerpc*-*-*"
+ if {!$gcc_compiled && [istarget hppa*-*-hpux*]} then {
+ gdb_test "p t_func_values(add,func_val2)" "You cannot.*ignored.*"
+ } else {
+ gdb_test "p t_func_values(add,func_val2)" " = 1"
+ }
+
+ setup_xfail "rs6000*-*-*"
+ setup_xfail "powerpc*-*-*"
+ if {!$gcc_compiled && [istarget hppa*-*-hpux*]} then {
+ gdb_test "p t_func_values(func_val1,doubleit)" "You cannot.*ignored.*"
+ } else {
+ gdb_test "p t_func_values(func_val1,doubleit)" " = 1"
+ }
+
+ gdb_test "p t_call_add(func_val1,3,4)" " = 7"
+
+ setup_xfail "rs6000*-*-*"
+ setup_xfail "powerpc*-*-*"
+ if {!$gcc_compiled && [istarget hppa*-*-hpux*]} then {
+ gdb_test "p t_call_add(add,3,4)" "You cannot.*ignored.*"
+ } else {
+ gdb_test "p t_call_add(add,3,4)" " = 7"
+ }
+
+ gdb_test "p t_enum_value1(enumval1)" " = 1"
+ gdb_test "p t_enum_value1(enum_val1)" " = 1"
+ gdb_test "p t_enum_value1(enum_val2)" " = 0"
+
+ gdb_test "p t_enum_value2(enumval2)" " = 1"
+ gdb_test "p t_enum_value2(enum_val2)" " = 1"
+ gdb_test "p t_enum_value2(enum_val1)" " = 0"
+
+ gdb_test "p sum_args(1,{2})" " = 2"
+ gdb_test "p sum_args(2,{2,3})" " = 5"
+ gdb_test "p sum_args(3,{2,3,4})" " = 9"
+ gdb_test "p sum_args(4,{2,3,4,5})" " = 14"
+
+ gdb_test "p sum10 (1, 2, 3, 4, 5, 6, 7, 8, 9, 10)" " = 55"
+
+ gdb_test "p cmp10 (0, 1, 2, 3, 4, 5, 6, 7, 8, 9)" " = 1"
+
+ gdb_test "p t_structs_c(struct_val1)" "= 120 'x'" \
+ "call inferior func with struct - returns char"
+ gdb_test "p t_structs_s(struct_val1)" "= 87" \
+ "call inferior func with struct - returns short"
+ gdb_test "p t_structs_i(struct_val1)" "= 76" \
+ "call inferior func with struct - returns int"
+ gdb_test "p t_structs_l(struct_val1)" "= 51" \
+ "call inferior func with struct - returns long"
+ setup_xfail "i*86-*-*"
+ gdb_test "p t_structs_f(struct_val1)" "= 2.12.*" \
+ "call inferior func with struct - returns float"
+ setup_xfail "i*86-*-*"
+ gdb_test "p t_structs_d(struct_val1)" "= 9.87.*" \
+ "call inferior func with struct - returns double"
+ gdb_test "p t_structs_a(struct_val1)" "= (.unsigned char .. )?\"foo\"" \
+ "call inferior func with struct - returns char *"
+}
+
+# Start with a fresh gdb.
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+gdb_test "set print sevenbit-strings" ""
+gdb_test "set print address off" ""
+gdb_test "set width 0" ""
+
+if { ![set_lang_c] } {
+ gdb_suppress_tests;
+} else {
+ if { ![runto_main] } {
+ gdb_suppress_tests;
+ }
+}
+
+gdb_test "next" ".*"
+do_function_calls
+
+return 0
diff --git a/gdb/testsuite/gdb.base/callfuncs2.c b/gdb/testsuite/gdb.base/callfuncs2.c
new file mode 100644
index 00000000000..ac14d457ae3
--- /dev/null
+++ b/gdb/testsuite/gdb.base/callfuncs2.c
@@ -0,0 +1,267 @@
+/* Support program for testing gdb's ability to call functions
+ in an inferior which doesn't itself call malloc, pass appropriate
+ arguments to those functions, and get the returned result. */
+
+#ifdef NO_PROTOTYPES
+#define PARAMS(paramlist) ()
+#else
+#define PARAMS(paramlist) paramlist
+#endif
+
+char char_val1 = 'a';
+char char_val2 = 'b';
+
+short short_val1 = 10;
+short short_val2 = -23;
+
+int int_val1 = 87;
+int int_val2 = -26;
+
+long long_val1 = 789;
+long long_val2 = -321;
+
+float float_val1 = 3.14159;
+float float_val2 = -2.3765;
+
+double double_val1 = 45.654;
+double double_val2 = -67.66;
+
+#define DELTA (0.001)
+
+char *string_val1 = "string 1";
+char *string_val2 = "string 2";
+
+char char_array_val1[] = "carray 1";
+char char_array_val2[] = "carray 2";
+
+struct struct1 {
+ char c;
+ short s;
+ int i;
+ long l;
+ float f;
+ double d;
+ char a[4];
+} struct_val1 = { 'x', 87, 76, 51, 2.1234, 9.876, "foo" };
+
+/* Some functions that can be passed as arguments to other test
+ functions, or called directly. */
+
+int add (a, b)
+int a, b;
+{
+ return (a + b);
+}
+
+int doubleit (a)
+int a;
+{
+ return (a + a);
+}
+
+int (*func_val1) PARAMS((int,int)) = add;
+int (*func_val2) PARAMS((int)) = doubleit;
+
+/* An enumeration and functions that test for specific values. */
+
+enum enumtype { enumval1, enumval2, enumval3 };
+enum enumtype enum_val1 = enumval1;
+enum enumtype enum_val2 = enumval2;
+enum enumtype enum_val3 = enumval3;
+
+t_enum_value1 (enum_arg)
+enum enumtype enum_arg;
+{
+ return (enum_arg == enum_val1);
+}
+
+t_enum_value2 (enum_arg)
+enum enumtype enum_arg;
+{
+ return (enum_arg == enum_val2);
+}
+
+t_enum_value3 (enum_arg)
+enum enumtype enum_arg;
+{
+ return (enum_arg == enum_val3);
+}
+
+/* A function that takes a vector of integers (along with an explicit
+ count) and returns their sum. */
+
+int sum_args (argc, argv)
+int argc;
+int argv[];
+{
+ int sumval = 0;
+ int idx;
+
+ for (idx = 0; idx < argc; idx++)
+ {
+ sumval += argv[idx];
+ }
+ return (sumval);
+}
+
+/* Test that we can call functions that take structs and return
+ members from that struct */
+
+char t_structs_c (tstruct) struct struct1 tstruct; { return (tstruct.c); }
+short t_structs_s (tstruct) struct struct1 tstruct; { return (tstruct.s); }
+int t_structs_i (tstruct) struct struct1 tstruct; { return (tstruct.i); }
+long t_structs_l (tstruct) struct struct1 tstruct; { return (tstruct.l); }
+float t_structs_f (tstruct) struct struct1 tstruct; { return (tstruct.f); }
+double t_structs_d (tstruct) struct struct1 tstruct; { return (tstruct.d); }
+char *t_structs_a (tstruct) struct struct1 tstruct; { return (tstruct.a); }
+
+/* Test that calling functions works if there are a lot of arguments. */
+int
+sum10 (i0, i1, i2, i3, i4, i5, i6, i7, i8, i9)
+ int i0, i1, i2, i3, i4, i5, i6, i7, i8, i9;
+{
+ return i0 + i1 + i2 + i3 + i4 + i5 + i6 + i7 + i8 + i9;
+}
+
+/* Gotta have a main to be able to generate a linked, runnable
+ executable, and also provide a useful place to set a breakpoint. */
+
+main ()
+{
+#ifdef usestubs
+ set_debug_traps();
+ breakpoint();
+#endif
+ t_structs_c(struct_val1);
+}
+
+/* Functions that expect specific values to be passed and return
+ either 0 or 1, depending upon whether the values were
+ passed incorrectly or correctly, respectively. */
+
+int t_char_values (char_arg1, char_arg2)
+char char_arg1, char_arg2;
+{
+ return ((char_arg1 == char_val1) && (char_arg2 == char_val2));
+}
+
+int
+#ifdef NO_PROTOTYPES
+t_small_values (arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10)
+ char arg1;
+ short arg2;
+ int arg3;
+ char arg4;
+ short arg5;
+ char arg6;
+ short arg7;
+ int arg8;
+ short arg9;
+ short arg10;
+#else
+t_small_values (char arg1, short arg2, int arg3, char arg4, short arg5,
+ char arg6, short arg7, int arg8, short arg9, short arg10)
+#endif
+{
+ return arg1 + arg2 + arg3 + arg4 + arg5 + arg6 + arg7 + arg8 + arg9 + arg10;
+}
+
+int t_short_values (short_arg1, short_arg2)
+short short_arg1, short_arg2;
+{
+ return ((short_arg1 == short_val1) && (short_arg2 == short_val2));
+}
+
+int t_int_values (int_arg1, int_arg2)
+int int_arg1, int_arg2;
+{
+ return ((int_arg1 == int_val1) && (int_arg2 == int_val2));
+}
+
+int t_long_values (long_arg1, long_arg2)
+long long_arg1, long_arg2;
+{
+ return ((long_arg1 == long_val1) && (long_arg2 == long_val2));
+}
+
+int t_float_values (float_arg1, float_arg2)
+float float_arg1, float_arg2;
+{
+ return ((float_arg1 - float_val1) < DELTA
+ && (float_arg1 - float_val1) > -DELTA
+ && (float_arg2 - float_val2) < DELTA
+ && (float_arg2 - float_val2) > -DELTA);
+}
+
+int
+#ifdef NO_PROTOTYPES
+/* In this case we are just duplicating t_float_values, but that is the
+ easiest way to deal with either ANSI or non-ANSI. */
+t_float_values2 (float_arg1, float_arg2)
+ float float_arg1, float_arg2;
+#else
+t_float_values2 (float float_arg1, float float_arg2)
+#endif
+{
+ return ((float_arg1 - float_val1) < DELTA
+ && (float_arg1 - float_val1) > -DELTA
+ && (float_arg2 - float_val2) < DELTA
+ && (float_arg2 - float_val2) > -DELTA);
+}
+
+int t_double_values (double_arg1, double_arg2)
+double double_arg1, double_arg2;
+{
+ return ((double_arg1 - double_val1) < DELTA
+ && (double_arg1 - double_val1) > -DELTA
+ && (double_arg2 - double_val2) < DELTA
+ && (double_arg2 - double_val2) > -DELTA);
+}
+
+int t_string_values (string_arg1, string_arg2)
+char *string_arg1, *string_arg2;
+{
+ return (!strcmp (string_arg1, string_val1) &&
+ !strcmp (string_arg2, string_val2));
+}
+
+int t_char_array_values (char_array_arg1, char_array_arg2)
+char char_array_arg1[], char_array_arg2[];
+{
+ return (!strcmp (char_array_arg1, char_array_val1) &&
+ !strcmp (char_array_arg2, char_array_val2));
+}
+
+
+/* This used to simply compare the function pointer arguments with
+ known values for func_val1 and func_val2. Doing so is valid ANSI
+ code, but on some machines (RS6000, HPPA, others?) it may fail when
+ called directly by GDB.
+
+ In a nutshell, it's not possible for GDB to determine when the address
+ of a function or the address of the function's stub/trampoline should
+ be passed.
+
+ So, to avoid GDB lossage in the common case, we perform calls through the
+ various function pointers and compare the return values. For the HPPA
+ at least, this allows the common case to work.
+
+ If one wants to try something more complicated, pass the address of
+ a function accepting a "double" as one of its first 4 arguments. Call
+ that function indirectly through the function pointer. This would fail
+ on the HPPA. */
+
+int t_func_values (func_arg1, func_arg2)
+int (*func_arg1) PARAMS ((int, int));
+int (*func_arg2) PARAMS ((int));
+{
+ return ((*func_arg1) (5,5) == (*func_val1) (5,5)
+ && (*func_arg2) (6) == (*func_val2) (6));
+}
+
+int t_call_add (func_arg1, a, b)
+int (*func_arg1) PARAMS ((int, int));
+int a, b;
+{
+ return ((*func_arg1)(a, b));
+}
diff --git a/gdb/testsuite/gdb.base/callfuncs2.exp b/gdb/testsuite/gdb.base/callfuncs2.exp
new file mode 100644
index 00000000000..8b17b6346bb
--- /dev/null
+++ b/gdb/testsuite/gdb.base/callfuncs2.exp
@@ -0,0 +1,276 @@
+# Copyright (C) 1997, 1998 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file was written by Fred Fish. (fnf@cygnus.com)
+
+# SAME tests as in callfuncs.exp but here the inferior program does not call malloc.
+
+
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+set prms_id 0
+set bug_id 0
+
+set testfile "callfuncs2"
+set srcfile ${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+
+set prototypes 1
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } {
+ set prototypes 0;
+ # built the second test case since we can't use prototypes
+ warning "Prototypes not supported, rebuilding with -DNO_PROTOTYPES"
+ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug additional_flags=-DNO_PROTOTYPES}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+ }
+}
+
+# Create and source the file that provides information about the compiler
+# used to compile the test case.
+
+if [get_compiler_info ${binfile}] {
+ return -1;
+}
+
+
+
+# The a29k can't call functions, so don't even bother with this test.
+if [target_info exists gdb,cannot_call_functions] {
+ setup_xfail "*-*-*" 2416
+ fail "This target can not call functions"
+ continue
+}
+
+# Set the current language to C. This counts as a test. If it
+# fails, then we skip the other tests.
+
+proc set_lang_c {} {
+ global gdb_prompt
+
+ send_gdb "set language c\n"
+ gdb_expect {
+ -re ".*$gdb_prompt $" {}
+ timeout { fail "set language c (timeout)" ; return 0 }
+ }
+
+ send_gdb "show language\n"
+ gdb_expect {
+ -re ".* source language is \"c\".*$gdb_prompt $" {
+ pass "set language to \"c\""
+ return 1
+ }
+ -re ".*$gdb_prompt $" {
+ fail "setting language to \"c\""
+ return 0
+ }
+ timeout {
+ fail "can't show language (timeout)"
+ return 0
+ }
+ }
+}
+
+# FIXME: Before calling this proc, we should probably verify that
+# we can call inferior functions and get a valid integral value
+# returned.
+# Note that it is OK to check for 0 or 1 as the returned values, because C
+# specifies that the numeric value of a relational or logical expression
+# (computed in the inferior) is 1 for true and 0 for false.
+
+proc do_function_calls {} {
+ global prototypes
+ global gcc_compiled
+ # We need to up this because this can be really slow on some boards.
+ set timeout 60;
+
+ gdb_test "p t_char_values(0,0)" " = 0"
+ gdb_test "p t_char_values('a','b')" " = 1"
+ gdb_test "p t_char_values(char_val1,char_val2)" " = 1"
+ gdb_test "p t_char_values('a',char_val2)" " = 1"
+ gdb_test "p t_char_values(char_val1,'b')" " = 1"
+
+ gdb_test "p t_short_values(0,0)" " = 0"
+ gdb_test "p t_short_values(10,-23)" " = 1"
+ gdb_test "p t_short_values(short_val1,short_val2)" " = 1"
+ gdb_test "p t_short_values(10,short_val2)" " = 1"
+ gdb_test "p t_short_values(short_val1,-23)" " = 1"
+
+ gdb_test "p t_int_values(0,0)" " = 0"
+ gdb_test "p t_int_values(87,-26)" " = 1"
+ gdb_test "p t_int_values(int_val1,int_val2)" " = 1"
+ gdb_test "p t_int_values(87,int_val2)" " = 1"
+ gdb_test "p t_int_values(int_val1,-26)" " = 1"
+
+ gdb_test "p t_long_values(0,0)" " = 0"
+ gdb_test "p t_long_values(789,-321)" " = 1"
+ gdb_test "p t_long_values(long_val1,long_val2)" " = 1"
+ gdb_test "p t_long_values(789,long_val2)" " = 1"
+ gdb_test "p t_long_values(long_val1,-321)" " = 1"
+
+ if ![target_info exists gdb,skip_float_tests] {
+ gdb_test "p t_float_values(0.0,0.0)" " = 0"
+
+ # These next four tests fail on the mn10300.
+ # The first value is passed in regs, the other in memory.
+ # Gcc emits different stabs for the two parameters; the first is
+ # claimed to be a float, the second a double.
+ # dbxout.c in gcc claims this is the desired behavior.
+ setup_xfail "mn10300-*-*"
+ gdb_test "p t_float_values(3.14159,-2.3765)" " = 1"
+ setup_xfail "mn10300-*-*"
+ gdb_test "p t_float_values(float_val1,float_val2)" " = 1"
+ setup_xfail "mn10300-*-*"
+ gdb_test "p t_float_values(3.14159,float_val2)" " = 1"
+ setup_xfail "mn10300-*-*"
+ gdb_test "p t_float_values(float_val1,-2.3765)" " = 1"
+
+ # Test passing of arguments which might not be widened.
+ gdb_test "p t_float_values2(0.0,0.0)" " = 0"
+
+ # Although PR 5318 mentions SunOS specifically, this seems
+ # to be a generic problem on quite a few platforms.
+ if $prototypes then {
+ setup_xfail "hppa*-*-*" "sparc-*-*" "mips*-*-*" 5318
+ if {!$gcc_compiled} then {
+ setup_xfail "alpha-dec-osf2*" "i*86-*-sysv4*" 5318
+ }
+ }
+ gdb_test "p t_float_values2(3.14159,float_val2)" " = 1"
+ gdb_test "p t_small_values(1,2,3,4,5,6,7,8,9,10)" " = 55"
+
+ gdb_test "p t_double_values(0.0,0.0)" " = 0"
+ gdb_test "p t_double_values(45.654,-67.66)" " = 1"
+ gdb_test "p t_double_values(double_val1,double_val2)" " = 1"
+ gdb_test "p t_double_values(45.654,double_val2)" " = 1"
+ gdb_test "p t_double_values(double_val1,-67.66)" " = 1"
+
+ }
+
+ gdb_test "p t_string_values(string_val2,string_val1)" " = 0"
+ gdb_test "p t_string_values(string_val1,string_val2)" " = 1"
+ gdb_test "p t_string_values(\"string 1\",\"string 2\")" " = 1"
+ gdb_test "p t_string_values(\"string 1\",string_val2)" " = 1"
+ gdb_test "p t_string_values(string_val1,\"string 2\")" " = 1"
+
+ gdb_test "p t_char_array_values(char_array_val2,char_array_val1)" " = 0"
+ gdb_test "p t_char_array_values(char_array_val1,char_array_val2)" " = 1"
+ gdb_test "p t_char_array_values(\"carray 1\",\"carray 2\")" " = 1"
+ gdb_test "p t_char_array_values(\"carray 1\",char_array_val2)" " = 1"
+ gdb_test "p t_char_array_values(char_array_val1,\"carray 2\")" " = 1"
+
+ gdb_test "p doubleit(4)" " = 8"
+ gdb_test "p add(4,5)" " = 9"
+ gdb_test "p t_func_values(func_val2,func_val1)" " = 0"
+ gdb_test "p t_func_values(func_val1,func_val2)" " = 1"
+
+ # On the rs6000, we need to pass the address of the trampoline routine,
+ # not the address of add itself. I don't know how to go from add to
+ # the address of the trampoline. Similar problems exist on the HPPA,
+ # and in fact can present an unsolvable problem as the stubs may not
+ # even exist in the user's program. We've slightly recoded t_func_values
+ # to avoid such problems in the common case. This may or may not help
+ # the RS6000.
+ setup_xfail "rs6000*-*-*"
+ setup_xfail "powerpc*-*-*"
+
+ if {!$gcc_compiled && [istarget hppa*-*-hpux*]} then {
+ gdb_test "p t_func_values(add,func_val2)" "You cannot.*ignored.*"
+ } else {
+ gdb_test "p t_func_values(add,func_val2)" " = 1"
+ }
+
+ setup_xfail "rs6000*-*-*"
+ setup_xfail "powerpc*-*-*"
+
+ if {!$gcc_compiled && [istarget hppa*-*-hpux*]} then {
+ gdb_test "p t_func_values(func_val1,doubleit)" "You cannot.*ignored.*"
+ } else {
+ gdb_test "p t_func_values(func_val1,doubleit)" " = 1"
+ }
+
+ gdb_test "p t_call_add(func_val1,3,4)" " = 7"
+
+ setup_xfail "rs6000*-*-*"
+ setup_xfail "powerpc*-*-*"
+
+ if {!$gcc_compiled && [istarget hppa*-*-hpux*]} then {
+ gdb_test "p t_call_add(add,3,4)" "You cannot.*ignored.*"
+ } else {
+ gdb_test "p t_call_add(add,3,4)" " = 7"
+ }
+
+ gdb_test "p t_enum_value1(enumval1)" " = 1"
+ gdb_test "p t_enum_value1(enum_val1)" " = 1"
+ gdb_test "p t_enum_value1(enum_val2)" " = 0"
+
+ gdb_test "p t_enum_value2(enumval2)" " = 1"
+ gdb_test "p t_enum_value2(enum_val2)" " = 1"
+ gdb_test "p t_enum_value2(enum_val1)" " = 0"
+
+ gdb_test "p sum_args(1,{2})" " = 2"
+ gdb_test "p sum_args(2,{2,3})" " = 5"
+ gdb_test "p sum_args(3,{2,3,4})" " = 9"
+ gdb_test "p sum_args(4,{2,3,4,5})" " = 14"
+ gdb_test "p sum10 (1, 2, 3, 4, 5, 6, 7, 8, 9, 10)" " = 55"
+
+ gdb_test "p t_structs_c(struct_val1)" "= 120 'x'" \
+ "call inferior func with struct - returns char"
+ gdb_test "p t_structs_s(struct_val1)" "= 87" \
+ "call inferior func with struct - returns short"
+ gdb_test "p t_structs_i(struct_val1)" "= 76" \
+ "call inferior func with struct - returns int"
+ gdb_test "p t_structs_l(struct_val1)" "= 51" \
+ "call inferior func with struct - returns long"
+ setup_xfail "i*86-*-*"
+ gdb_test "p t_structs_f(struct_val1)" "= 2.12.*" \
+ "call inferior func with struct - returns float"
+ setup_xfail "i*86-*-*"
+ gdb_test "p t_structs_d(struct_val1)" "= 9.87.*" \
+ "call inferior func with struct - returns double"
+ gdb_test "p t_structs_a(struct_val1)" "= (.unsigned char .. )?\"foo\"" \
+ "call inferior func with struct - returns char *"
+
+}
+
+# Start with a fresh gdb.
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+gdb_test "set print sevenbit-strings" ""
+gdb_test "set print address off" ""
+gdb_test "set width 0" ""
+
+if { ![set_lang_c] } {
+ gdb_suppress_tests;
+} else {
+ if { ![runto_main] } {
+ gdb_suppress_tests;
+ }
+}
+
+gdb_test "next" ".*"
+do_function_calls
+
+return 0
diff --git a/gdb/testsuite/gdb.base/commands.exp b/gdb/testsuite/gdb.base/commands.exp
new file mode 100644
index 00000000000..f70ac6b01d5
--- /dev/null
+++ b/gdb/testsuite/gdb.base/commands.exp
@@ -0,0 +1,248 @@
+# Copyright (C) 1988, 1990, 1991, 1992, 1997 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+#
+# test special commands (if, while, etc)
+#
+set prms_id 0
+set bug_id 0
+
+set testfile "run"
+set srcfile ${testfile}.c
+set binfile ${objdir}/${subdir}/commands
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug additional_flags=-DFAKEARGV}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+gdb_exit
+gdb_start
+delete_breakpoints
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+proc gdbvar_simple_if_test {} {
+ global gdb_prompt
+
+ gdb_test "set \$foo = 0" "" "set foo in gdbvar_simple_if_test"
+ # All this test should do is print 0xdeadbeef once.
+ gdb_test "if \$foo == 1\np/x 0xfeedface\nelse\np/x 0xdeadbeef\nend" "\\\$\[0-9\]* = 0xdeadbeef" "gdbvar_simple_if_test #1"
+ # All this test should do is print 0xfeedface once.
+ gdb_test "if \$foo == 0\np/x 0xfeedface\nelse\np/x 0xdeadbeef\nend" "\\\$\[0-9\]* = 0xfeedface" "gdbvar_simple_if_test #2"
+}
+
+proc gdbvar_simple_while_test {} {
+ global gdb_prompt
+
+ gdb_test "set \$foo = 5" "" "set foo in gdbvar_simple_while_test"
+ # This test should print 0xfeedface five times.
+ gdb_test "while \$foo > 0\np/x 0xfeedface\nset \$foo -= 1\nend" "\\\$\[0-9\]* = 0xfeedface\[^\n\]*\n\\\$\[0-9\]* = 0xfeedface\[^\n\]*\n\\\$\[0-9\]* = 0xfeedface\[^\n\]*\n\\\$\[0-9\]* = 0xfeedface\[^\n\]*\n\\\$\[0-9\]* = 0xfeedface" "gdbvar_simple_while_test #1"
+}
+
+proc gdbvar_complex_if_while_test {} {
+ global gdb_prompt
+
+ gdb_test "set \$foo = 4" "" "set foo in gdbvar complex_if_while_test"
+ # This test should alternate between 0xdeadbeef and 0xfeedface two times.
+ gdb_test "while \$foo > 0\nset \$foo -= 1\nif \(\$foo % 2\) == 1\np/x 0xdeadbeef\nelse\np/x 0xfeedface\nend\nend" "\\\$\[0-9\]* = 0xdeadbeef\[^\n\]*\n\\\$\[0-9\]* = 0xfeedface\[^\n\]*\n\\\$\[0-9\]* = 0xdeadbeef\[^\n\]*\n\\\$\[0-9\]* = 0xfeedface" "gdbvar_complex_if_while_test #1"
+}
+
+proc progvar_simple_if_test {} {
+ global gdb_prompt
+
+ if [target_info exists noargs] {
+ verbose "Skipping progvar_simple_if_test because of noargs."
+ return
+ }
+
+ if { ![runto factorial] } then { gdb_suppress_tests; }
+ # Don't depend upon argument passing, since most simulators don't currently
+ # support it. Bash value variable to be what we want.
+ gdb_test "p value=5" "" "set value to 5 in progvar_simple_if_test #1"
+ # All this test should do is print 0xdeadbeef once.
+ gdb_test "if value == 1\np/x 0xfeedface\nelse\np/x 0xdeadbeef\nend" "\\\$\[0-9\]* = 0xdeadbeef" "progvar_simple_if_test #1"
+ # All this test should do is print 0xfeedface once.
+ gdb_test "if value == 5\np/x 0xfeedface\nelse\np/x 0xdeadbeef\nend" "\\\$\[0-9\]* = 0xfeedface" "progvar_simple_if_test #2"
+ gdb_stop_suppressing_tests;
+}
+
+proc progvar_simple_while_test {} {
+ global gdb_prompt
+
+ if [target_info exists noargs] {
+ verbose "Skipping progvar_simple_while_test because of noargs."
+ return
+ }
+
+ if { ![runto factorial] } then { gdb_suppress_tests }
+ # Don't depend upon argument passing, since most simulators don't currently
+ # support it. Bash value variable to be what we want.
+ gdb_test "p value=5" "" "set value to 5 in progvar_simple_if_test #2"
+ # This test should print 0xfeedface five times.
+ gdb_test "while value > 0\np/x 0xfeedface\nset value -= 1\nend" "\\\$\[0-9\]* = 0xfeedface\[^\n\]*\n\\\$\[0-9\]* = 0xfeedface\[^\n\]*\n\\\$\[0-9\]* = 0xfeedface\[^\n\]*\n\\\$\[0-9\]* = 0xfeedface\[^\n\]*\n\\\$\[0-9\]* = 0xfeedface" "progvar_simple_while_test #1"
+ gdb_stop_suppressing_tests;
+}
+
+proc progvar_complex_if_while_test {} {
+ global gdb_prompt
+
+ if [target_info exists noargs] {
+ verbose "Skipping progvar_simple_if_while_test because of noargs."
+ return
+ }
+
+ if { ![runto factorial] } then { gdb_suppress_tests }
+ # Don't depend upon argument passing, since most simulators don't currently
+ # support it. Bash value variable to be what we want.
+ gdb_test "p value=4" "" "set value to 4 in progvar_simple_if_test"
+ # This test should alternate between 0xdeadbeef and 0xfeedface two times.
+ gdb_test "while value > 0\nset value -= 1\nif \(value % 2\) == 1\np/x 0xdeadbeef\nelse\np/x 0xfeedface\nend\nend" "\\\$\[0-9\]* = 0xdeadbeef\[^\n\]*\n\\\$\[0-9\]* = 0xfeedface\[^\n\]*\n\\\$\[0-9\]* = 0xdeadbeef\[^\n\]*\n\\\$\[0-9\]* = 0xfeedface" "progvar_complex_if_while_test #1"
+ gdb_stop_suppressing_tests;
+}
+
+proc if_while_breakpoint_command_test {} {
+ if [target_info exists noargs] {
+ verbose "Skipping if_while_breakpoint_command_test because of noargs."
+ return
+ }
+
+ if { ![runto factorial] } then { gdb_suppress_tests }
+ # Don't depend upon argument passing, since most simulators don't currently
+ # support it. Bash value variable to be what we want.
+ gdb_test "p value=5" "" "set value to 5 in progvar_simple_if_test"
+ delete_breakpoints
+ gdb_test "break factorial" "Breakpoint.*at.*" "break factorial #1"
+
+ send_gdb "commands\n"
+ gdb_expect {
+ -re "End with" {
+ pass "commands in if_while_breakpoint_command_test"
+ }
+ default {
+ fail "(timeout or eof) commands in if_while_breakpoint_command_test"
+ }
+ }
+ # This test should alternate between 0xdeadbeef and 0xfeedface two times.
+ gdb_test "while value > 0\nset value -= 1\nif \(value % 2\) == 1\np/x 0xdeadbeef\nelse\np/x 0xfeedface\nend\nend\nend" "" "commands part 2 in if_while_breakpoint_command_test"
+ gdb_test "continue" "\\\$\[0-9\]* = 0xdeadbeef\[^\n\]*\n\\\$\[0-9\]* = 0xfeedface\[^\n\]*\n\\\$\[0-9\]* = 0xdeadbeef\[^\n\]*\n\\\$\[0-9\]* = 0xfeedface" "if_while_breakpoint_command_test #1"
+ gdb_test "info break" "while.*set.*if.*p/x.*else.*p/x.*end.*" "info break in if_while_breakpoint_command_test"
+ gdb_stop_suppressing_tests;
+}
+
+# Test that we can run the inferior from breakpoint commands.
+proc infrun_breakpoint_command_test {} {
+ if [target_info exists noargs] {
+ verbose "Skipping infrun_breakpoint_command_test because of noargs."
+ return
+ }
+
+ if { ![runto factorial] } then { gdb_suppress_tests }
+ # Don't depend upon argument passing, since most simulators don't currently
+ # support it. Bash value variable to be what we want.
+ gdb_test "p value=6" "" "set value to 6 in progvar_simple_if_test #1"
+ delete_breakpoints
+ gdb_test "break factorial if value == 5" "Breakpoint.*at.*"
+
+# infrun_breakpoint_command_test - This test was broken into two parts
+# to get around a synchronization problem in expect.
+# part1: issue the gdb command "commands"
+# part2: send the list of commands
+ send_gdb "commands\n"
+ gdb_expect {
+ -re "End with" {
+ pass "commands in infrun_breakpoint_command_test #1"
+ }
+ default {
+ fail "(timeout or eof) commands in infrun_breakpoint_command_test"
+ }
+ }
+ gdb_test "step\nstep\nstep\nstep\nbt\nend" "" \
+ "commands in infrun_breakpoint_command_test #2"
+
+ gdb_test "continue" "Breakpoint \[0-9\]*, factorial \\(value=5\\).*at.*
+\[0-9\]*\[ \]*if \\(value > 1\\) \{.*
+\[0-9\]*\[ \]*value \\*= factorial \\(value - 1\\);.*
+factorial \\(value=4\\) at.*\[0-9\]*\[ \]*if \\(value > 1\\) \{.*
+\[0-9\]*\[ \]*value \\*= factorial \\(value - 1\\);.*
+factorial \\(value=3\\) at .*
+\[0-9\]*\[ \]*if \\(value > 1\\) \{.*
+#0 factorial \\(value=3\\).*
+#1 \[0-9a-fx\]* in factorial \\(value=4\\).*
+#2 \[0-9a-fx\]* in factorial \\(value=5\\).*
+#3 \[0-9a-fx\]* in factorial \\(value=6\\).*
+#4 \[0-9a-fx\]* in main \\(.*\\).*" \
+ "continue in infrun_breakpoint_command_test";
+ gdb_stop_suppressing_tests;
+}
+
+proc breakpoint_command_test {} {
+ if [target_info exists noargs] {
+ verbose "Skipping breakpoint_command_test because of noargs."
+ return
+ }
+
+ if { ![runto factorial] } then { gdb_suppress_tests; }
+ # Don't depend upon argument passing, since most simulators don't currently
+ # support it. Bash value variable to be what we want.
+ gdb_test "p value=6" "" "set value to 6 in progvar_simple_if_test #2"
+ delete_breakpoints
+ gdb_test "break factorial" "Breakpoint.*at.*" "break factorial #2"
+ gdb_test "commands\nprintf \"Now the value is %d\\n\", value\nend" \
+ "Type commands.*\nEnd with.*" "commands in breakpoint_command_test"
+ gdb_test "continue" "Breakpoint \[0-9\]*, factorial.*Now the value is 5" \
+ "continue in breakpoint_command_test"
+ gdb_test "print value" " = 5" "print value in breakpoint_command_test"
+ gdb_stop_suppressing_tests;
+}
+
+# Test a simple user defined command (with arguments)
+proc user_defined_command_test {} {
+ global gdb_prompt
+
+ gdb_test "set \$foo = 4" "" "set foo in user_defined_command_test"
+
+ send_gdb "define mycommand\n"
+ gdb_expect {
+ -re "End with" {
+ pass "define mycommand in user_defined_command_test"
+ }
+ default {
+ fail "(timeout or eof) define mycommand in user_defined_command_test"
+ }
+ }
+ # This test should alternate between 0xdeadbeef and 0xfeedface two times.
+ gdb_test "while \$arg0 > 0\nset \$arg0 -= 1\nif \(\$arg0 % 2\) == 1\np/x 0xdeadbeef\nelse\np/x 0xfeedface\nend\nend\nend" "" "enter commands in user_defined_command_test"
+
+ gdb_test "mycommand \$foo" "\\\$\[0-9\]* = 0xdeadbeef\[^\n\]*\n\\\$\[0-9\]* = 0xfeedface\[^\n\]*\n\\\$\[0-9\]* = 0xdeadbeef\[^\n\]*\n\\\$\[0-9\]* = 0xfeedface" "execute user defined command in user_defined_command_test"
+ gdb_test "show user mycommand" "while.*set.*if.*p/x.*else.*p/x.*end.*" "display user command in user_defined_command_test"
+}
+
+gdbvar_simple_if_test
+gdbvar_simple_while_test
+gdbvar_complex_if_while_test
+progvar_simple_if_test
+progvar_simple_while_test
+progvar_complex_if_while_test
+if_while_breakpoint_command_test
+infrun_breakpoint_command_test
+breakpoint_command_test
+user_defined_command_test
diff --git a/gdb/testsuite/gdb.base/compiler.c b/gdb/testsuite/gdb.base/compiler.c
new file mode 100644
index 00000000000..8eb0d47dd19
--- /dev/null
+++ b/gdb/testsuite/gdb.base/compiler.c
@@ -0,0 +1,31 @@
+/* Often the behavior of any particular test depends upon what compiler was
+ used to compile the test. As each test is compiled, this file is
+ preprocessed by the same compiler used to compile that specific test
+ (different tests might be compiled by different compilers, particularly
+ if compiled at different times), and used to generate a *.ci (compiler
+ info) file for that test.
+
+ I.E., when callfuncs is compiled, a callfuncs.ci file will be generated,
+ which can then be sourced by callfuncs.exp to give callfuncs.exp access
+ to information about the compilation environment.
+
+ TODO: It might be a good idea to add expect code that tests each
+ definition made with 'set" to see if one already exists, and if so
+ warn about conflicts if it is being set to something else. */
+
+/* This needs to be kept in sync with whatis.c and gdb.exp(get_compiler_info).
+ If this ends up being hairy, we could use a common header file. */
+
+#if defined (__STDC__) || defined (_AIX)
+set signed_keyword_not_used 0
+#else
+set signed_keyword_not_used 1
+#endif
+
+#if defined (__GNUC__)
+set gcc_compiled __GNUC__
+#else
+set gcc_compiled 0
+#endif
+
+return 0
diff --git a/gdb/testsuite/gdb.base/completion.exp b/gdb/testsuite/gdb.base/completion.exp
new file mode 100644
index 00000000000..b4d97f0bc5a
--- /dev/null
+++ b/gdb/testsuite/gdb.base/completion.exp
@@ -0,0 +1,568 @@
+# Copyright (C) 1998 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file was written by Elena Zannoni (ezannoni@cygnus.com)
+
+# This file is part of the gdb testsuite.
+
+#
+# tests for command completion
+#
+# Here are some useful test cases for completion.
+# 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/we" "ird" (needs to not break word at slash)
+#
+
+
+if $tracelevel then {
+ strace $tracelevel
+ }
+
+
+#skip all these tests for now (FIXME)
+
+continue
+
+global usestubs
+
+#
+# test running programs
+#
+set prms_id 0
+set bug_id 0
+
+set testfile "break"
+set srcfile ${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug additional_flags=-w}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+if ![runto_main] then {
+ perror "tests suppressed"
+}
+
+set oldtimeout1 $timeout
+set timeout [expr $timeout + 500]
+
+
+send_gdb "hfgfh\t"
+sleep 1
+gdb_expect {
+ -re "^hfgfh\\\x07$"\
+ { send_gdb "\n"
+ gdb_expect {
+ -re "Undefined command: \"hfgfh\"\\. Try \"help\"\\..*$gdb_prompt $"\
+ { pass "complete 'hfgfh'"}
+ -re ".*$gdb_prompt $" { fail "complete 'hfgfh'"}
+ timeout {fail "(timeout) complete 'hfgfh'"}
+ }
+ }
+ -re ".*$gdb_prompt $" { fail "complete 'hfgfh'" }
+ timeout { fail "(timeout) complete 'hfgfh'" }
+ }
+
+#exp_internal 0
+
+send_gdb "show output\t"
+sleep 1
+gdb_expect {
+ -re "^show output-radix $"\
+ { send_gdb "\n"
+ gdb_expect {
+ -re "Default output radix for printing of values is 10\\..*$gdb_prompt $"\
+ { pass "complete 'show output'"}
+ -re ".*$gdb_prompt $" { fail "complete 'show output'"}
+ timeout {fail "(timeout) complete 'show output'"}
+ }
+ }
+ -re "^show output$"\
+ { send_gdb "\n"
+ gdb_expect {
+ -re "Default output radix for printing of values is 10\\..*$gdb_prompt $"\
+ { fail "complete 'show output'"}
+ -re ".*$gdb_prompt $" { fail "complete 'show output'"}
+ timeout { fail "(timeout) complete 'show output'"}
+ }
+
+ }
+
+ -re ".*$gdb_prompt $" { fail "complete 'show output'" }
+ timeout { fail "(timeout) complete 'show output'" }
+ }
+
+
+send_gdb "show output-\t"
+sleep 1
+gdb_expect {
+ -re "^show output-radix $"\
+ { send_gdb "\n"
+ gdb_expect {
+ -re "Default output radix for printing of values is 10\\..*$gdb_prompt $"\
+ { pass "complete 'show output-'"}
+ -re ".*$gdb_prompt $" { fail "complete 'show output-'"}
+ timeout {fail "(timeout) complete 'show output-'"}
+ }
+ }
+ -re "^show output-$"\
+ { send_gdb "\n"
+ gdb_expect {
+ -re "Default output radix for printing of values is 10\\..*$gdb_prompt $"\
+ { fail "complete 'show output-'"}
+ -re ".*$gdb_prompt $" { fail "complete 'show output-'"}
+ timeout { fail "(timeout) complete 'show output-'"}
+ }
+
+ }
+
+ -re ".*$gdb_prompt $" { fail "complete 'show output-'" }
+ timeout { fail "(timeout) complete 'show output-'" }
+ }
+
+send_gdb "p\t"
+sleep 1
+gdb_expect {
+ -re "^p\\\x07$"\
+ { send_gdb "\n"
+ gdb_expect {
+ -re "The history is empty\\..*$gdb_prompt $"\
+ { pass "complete 'p'"}
+ -re ".*$gdb_prompt $" { fail "complete 'p'"}
+ timeout {fail "(timeout) complete 'p'"}
+ }
+ }
+ -re ".*$gdb_prompt $" { fail "complete 'p'" }
+ timeout { fail "(timeout) complete 'p'" }
+ }
+
+send_gdb "p \t"
+sleep 1
+gdb_expect {
+ -re "^p \\\x07$"\
+ { send_gdb "\n"
+ gdb_expect {
+ -re "The history is empty\\..*$gdb_prompt $"\
+ { pass "complete 'p '"}
+ -re ".*$gdb_prompt $" { fail "complete 'p '"}
+ timeout {fail "(timeout) complete 'p '"}
+ }
+ }
+ -re ".*$gdb_prompt $" { fail "complete 'p '" }
+ timeout { fail "(timeout) complete 'p '" }
+ }
+
+
+send_gdb "info t foo\t"
+sleep 1
+gdb_expect {
+ -re "^info t foo\\\x07$"\
+ { send_gdb "\n"
+ gdb_expect {
+ -re "Ambiguous info command \"t foo\": target, terminal, threads, tp, tracepoints, types\\..*$gdb_prompt $"\
+ { pass "complete 'info t foo'"}
+ -re ".*$gdb_prompt $" { fail "complete 'info t foo'"}
+ timeout {fail "(timeout) complete 'info t foo'"}
+ }
+ }
+ -re ".*$gdb_prompt $" { fail "complete 'info t foo'" }
+ timeout { fail "(timeout) complete 'info t foo'" }
+ }
+
+send_gdb "info t\t"
+sleep 1
+gdb_expect {
+ -re "^info t\\\x07$"\
+ { send_gdb "\n"
+ gdb_expect {
+ -re "Ambiguous info command \"t\": target, terminal, threads, tp, tracepoints, types\\..
+*$gdb_prompt $"\
+ { pass "complete 'info t'"}
+ -re ".*$gdb_prompt $" { fail "complete 'info t'"}
+ timeout {fail "(timeout) complete 'info t'"}
+ }
+ }
+ -re ".*$gdb_prompt $" { fail "complete 'info t'" }
+ timeout { fail "(timeout) complete 'info t'" }
+ }
+
+
+send_gdb "info t \t"
+sleep 1
+gdb_expect {
+ -re "^info t \\\x07$"\
+ { send_gdb "\n"
+ gdb_expect {
+ -re "Ambiguous info command \"t \": target, terminal, threads, tp, tracepoints, types\\..
+*$gdb_prompt $"\
+ { pass "complete 'info t '"}
+ -re ".*$gdb_prompt $" { fail "complete 'info t '"}
+ timeout {fail "(timeout) complete 'info t '"}
+ }
+ }
+ -re ".*$gdb_prompt $" { fail "complete 'info t '" }
+ timeout { fail "(timeout) complete 'info t '" }
+ }
+
+
+send_gdb "info asdfgh\t"
+sleep 1
+gdb_expect {
+ -re "^info asdfgh\\\x07$"\
+ { send_gdb "\n"
+ gdb_expect {
+ -re "Undefined info command: \"asdfgh\". Try \"help info\"\\..
+*$gdb_prompt $"\
+ { pass "complete 'info asdfgh'"}
+ -re ".*$gdb_prompt $" { fail "complete 'info asdfgh'"}
+ timeout {fail "(timeout) complete 'info asdfgh'"}
+ }
+ }
+ -re ".*$gdb_prompt $" { fail "complete 'info asdfgh'" }
+ timeout { fail "(timeout) complete 'info asdfgh'" }
+ }
+
+
+send_gdb "info asdfgh \t"
+sleep 1
+gdb_expect {
+ -re "^info asdfgh \\\x07$"\
+ { send_gdb "\n"
+ gdb_expect {
+ -re "Undefined info command: \"asdfgh \". Try \"help info\"\\..
+*$gdb_prompt $"\
+ { pass "complete 'info asdfgh '"}
+ -re ".*$gdb_prompt $" { fail "complete 'info asdfgh '"}
+ timeout {fail "(timeout) complete 'info asdfgh '"}
+ }
+ }
+ -re ".*$gdb_prompt $" { fail "complete 'info asdfgh '" }
+ timeout { fail "(timeout) complete 'info asdfgh '" }
+ }
+
+send_gdb "info\t"
+sleep 1
+gdb_expect {
+ -re "^info $"\
+ { send_gdb "\n"
+ gdb_expect {
+ -re "\"info\" must be followed by the name of an info command\\.\r\nList of info subcommands:\r\n\r\ninfo address.*info watchpoints.*\r\n\r\nType \"help info\" followed by info subcommand name for full documentation.\r\nCommand name abbreviations are allowed if unambiguous\\..*$gdb_prompt $"\
+ { pass "complete 'info'"}
+ -re ".*$gdb_prompt $" { fail "complete 'info'"}
+ timeout {fail "(timeout) complete 'info'"}
+ }
+ }
+ -re ".*$gdb_prompt $" { fail "complete 'info'" }
+ timeout { fail "(timeout) complete 'info'" }
+ }
+
+send_gdb "info \t"
+sleep 1
+gdb_expect {
+ -re "^info \\\x07$"\
+ { send_gdb "\n"
+ gdb_expect {
+ -re "\"info\" must be followed by the name of an info command\\.\r\nList of info subcommands:\r\n\r\ninfo address.*Type \"help info\" followed by info subcommand name for full documentation.\r\nCommand name abbreviations are allowed if unambiguous\\..*$gdb_prompt $"\
+ { pass "complete 'info '"}
+ -re ".*$gdb_prompt $" { fail "complete 'info '"}
+ timeout {fail "(timeout) complete 'info '"}
+ }
+ }
+ -re ".*$gdb_prompt $" { fail "complete 'info '" }
+ timeout { fail "(timeout) complete 'info '" }
+ }
+
+
+send_gdb "info \t"
+sleep 1
+gdb_expect {
+ -re "^info \0x7$"\
+ { send_gdb "\t"
+ gdb_expect {
+ -re "address.*types.*$gdb_prompt info $"\
+ { send_gdb "\n"
+ gdb_expect {
+ -re "\"info\".*unambiguous\\..*$gdb_prompt $"\
+ { pass "complete (2) 'info '"}
+ -re ".*$gdb_prompt $" { fail "complete (2) 'info '"}
+ timeout {fail "(timeout) complete (2) 'info '"}
+ }
+ }
+ -re ".*$gdb_prompt $" { fail "complete (2) 'info '"}
+ timeout {fail "(timeout) complete (2) 'info '"}
+ }
+ }
+ -re ".*$gdb_prompt $" { fail "complete (2) 'info '" }
+ timeout { fail "(timeout) complete (2) 'info '" }
+ }
+
+
+send_gdb "p \"a\t"
+sleep 1
+gdb_expect {
+ -re "^p \"a\\\x07$"\
+ { send_gdb "\n"
+ gdb_expect {
+ -re "Unterminated string in expression\\..*$gdb_prompt $"\
+ { pass "complete 'p a'"}
+ -re ".*$gdb_prompt $" { fail "complete 'p a'"}
+ timeout {fail "(timeout) complete 'p a'"}
+ }
+ }
+ -re ".*$gdb_prompt $" { fail "complete 'p \"a'" }
+ timeout { fail "(timeout) complete 'p \"a'" }
+ }
+
+send_gdb "p 'a\t"
+sleep 1
+gdb_expect {
+ -re "^p 'a\\\x07$"\
+ { send_gdb "\n"
+ gdb_expect {
+ -re "Invalid character constant\\..*$gdb_prompt $"\
+ { pass "complete 'p \'a'"}
+ -re ".*$gdb_prompt $" { fail "complete 'p \'a'"}
+ timeout {fail "(timeout) complete 'p \'a'"}
+ }
+ }
+ -re ".*$gdb_prompt $" { fail "complete 'p \'a'" }
+ timeout { fail "(timeout) complete 'p \'a'" }
+ }
+
+send_gdb "p 'a\t"
+sleep 1
+gdb_expect {
+ -re "^p 'a\\\x07$"\
+ { send_gdb "\t"
+ gdb_expect {
+ -re "a64l.*atol.*$gdb_prompt p .a$"\
+ { send_gdb "\n"
+ gdb_expect {
+ -re "Invalid character constant\\..*$gdb_prompt $"\
+ { pass "complete (2) 'p \'a'"}
+ -re ".*$gdb_prompt $" { fail "complete (2) 'p \'a'"}
+ timeout {fail "(timeout) complete (2) 'p \'a'"}
+ }
+ }
+ -re ".*$gdb_prompt $" { fail "complete (2) 'p \'a'"}
+ timeout {fail "(timeout) complete (2) 'p \'a'"}
+ }
+ }
+ -re ".*$gdb_prompt $" { fail "complete (2) 'p \'a'" }
+ timeout { fail "(timeout) complete (2) 'p \'a'" }
+ }
+
+
+send_gdb "p b-a\t"
+sleep 1
+gdb_expect {
+ -re "^p b-a\\\x07$"\
+ { send_gdb "\n"
+ gdb_expect {
+ -re "No symbol \"b\" in current context\\..*$gdb_prompt $"\
+ { pass "complete 'p b-a'"}
+ -re ".*$gdb_prompt $" { fail "complete 'p b-a'"}
+ timeout {fail "(timeout) complete 'p b-a'"}
+ }
+ }
+ -re ".*$gdb_prompt $" { fail "complete 'p b-a'" }
+ timeout { fail "(timeout) complete 'p b-a'" }
+ }
+
+send_gdb "p b-a\t"
+sleep 1
+gdb_expect {
+ -re "^p b-a\\\x07$"\
+ { send_gdb "\t"
+ gdb_expect {
+ -re "a64l.*atol.*$gdb_prompt p b-a$"\
+ { send_gdb "\n"
+ gdb_expect {
+ -re "No symbol \"b\" in current context\\..*$gdb_prompt $"\
+ { pass "complete (2) 'p b-a'"}
+ -re ".*$gdb_prompt $" { fail "complete (2) 'p b-a'"}
+ timeout {fail "(timeout) complete (2) 'p b-a'"}
+ }
+ }
+ -re ".*$gdb_prompt $" { fail "complete (2) 'p b-a'"}
+ timeout {fail "(timeout) complete (2) 'p b-a'"}
+ }
+ }
+ -re ".*$gdb_prompt $" { fail "complete (2) 'p b-a'" }
+ timeout { fail "(timeout) complete (2) 'p b-a'" }
+ }
+
+
+send_gdb "p b-\t"
+sleep 1
+gdb_expect {
+ -re "^p b-\\\x07$"\
+ { send_gdb "\t"
+ gdb_expect {
+ -re "There are $decimal possibilities\\. Do you really\r\nwish to see them all. \\(y or n\\)$"\
+ { send_gdb "n"
+ gdb_expect {
+ -re "\\(gdb\\) p b-$"\
+ { send_gdb "\n"
+ gdb_expect {
+ -re "No symbol \"b\" in current context\\..*$gdb_prompt $"\
+ { pass "complete (2) 'p b-'"}
+ -re ".*$gdb_prompt $" { fail "complete (2) 'p b-'"}
+ timeout {fail "(timeout) complete (2) 'p b-'"}
+ }
+ }
+ -re ".*$gdb_prompt $" { fail "complete (2) 'p b-'"}
+ timeout {fail "(timeout) complete (2) 'p b-'"}
+ }
+ }
+ -re ".*$gdb_prompt $" { fail "complete (2) 'p b-'"}
+ timeout {fail "(timeout) complete (2) 'p b-'"}
+ }
+ }
+ -re ".*$gdb_prompt $" { fail "complete (2) 'p b-'" }
+ timeout { fail "(timeout) complete (2) 'p b-'" }
+ }
+
+send_gdb "file ${objdir}/Make\t"
+sleep 1
+gdb_expect {
+ -re "file ${objdir}/Makefile.*$"\
+ { send_gdb "\n"
+ gdb_expect {
+ -re "\r\nA program is being debugged already\\. Kill it\\? \\(y or n\\) $"\
+ { send_gdb "n\n"
+ gdb_expect {
+ -re "\r\nProgram not killed\\.\r\n$gdb_prompt $"\
+ { pass "complete 'file Make'"}
+ -re ".*$gdb_prompt $" { fail "complete 'file Make'"}
+ timeout {fail "(timeout) complete 'file Make'"}
+ }
+ }
+ -re ".*$gdb_prompt $" { fail "complete 'file Make'"}
+ timeout {fail "(timeout) complete 'file Make'"}
+ }
+ }
+ -re ".*$gdb_prompt $" { fail "complete 'file Make'" }
+ timeout { fail "(timeout) complete 'file Make'" }
+ }
+
+
+send_gdb "file ${srcdir}/gdb.base/a1\t"
+sleep 1
+gdb_expect {
+ -re "^file ${srcdir}/gdb.base/.*'a1.*-selftest\\.exp' $"\
+ { send_gdb "\n"
+ gdb_expect {
+ -re "\r\nA program is being debugged already\\. Kill it\\? \\(y or n\\) $"
+\
+ { send_gdb "n\n"
+ gdb_expect {
+ -re "\r\nProgram not killed\\.\r\n$gdb_prompt $"\
+ { pass "complete 'file gdb.base/a1'"}
+ -re ".*$gdb_prompt $" { fail "complete 'file gdb.base/a1'"}
+ timeout {fail "(timeout) complete 'file gdb.base/a1'"}
+ }
+ }
+ -re ".*$gdb_prompt $" { fail "complete 'file gdb.base/a1'"}
+ timeout {fail "(timeout) complete 'file gdb.base/a1'"}
+ }
+ }
+ -re ".*$gdb_prompt $" { fail "complete 'file gdb.base/a1'" }
+ timeout { fail "(timeout) complete 'file gdb.base/a1'" }
+ }
+
+
+send_gdb "info func mark\t"
+sleep 1
+gdb_expect {
+ -re "^info func mark.*er$"\
+ { send_gdb "\t\t"
+ sleep 3
+ gdb_expect {
+ -re "marker1 marker2 marker3 marker4.*$gdb_prompt info func marker$"\
+ { send_gdb "\n"
+ gdb_expect {
+ -re "All functions matching regular expression \"marker\":\r\n\r\nFile.*break.c:\r\nint marker1\\(\\);\r\nint marker2\\(int\\).*marker3\\(char.*char.*\\);\r\n$gdb_prompt $"\
+ { pass "complete 'info func mar'"}
+ -re ".*$gdb_prompt $" { fail "complete 'info func mar'"}
+ timeout {fail "(timeout) complete 'info func mar'"}
+ }
+ }
+ -re ".*$gdb_prompt $" { fail "complete 'info func mar'"}
+ timeout {fail "(timeout) complete 'info func mar'"}
+ }
+ }
+ -re ".*$gdb_prompt $" { fail "complete 'info func mar'" }
+ timeout { fail "(timeout) complete 'info func mar'" }
+ }
+
+
+send_gdb "set follow-fork-mode \t\t"
+sleep 1
+gdb_expect {
+ -re "ask.*child.*parent.*$gdb_prompt set follow-fork-mode $"\
+ { send_gdb "\n"
+ gdb_expect {
+ -re "Ambiguous item \"\"\\..*$gdb_prompt $"\
+ { pass "complete 'set follow-fork-mode'"}
+ -re ".*$gdb_prompt $" { fail "complete 'set follow-fork-mode'"}
+ timeout {fail "(timeout) complete 'set follow-fork-mode'"}
+ }
+ }
+ -re ".*$gdb_prompt $" { fail "complete 'set follow-fork-mode'" }
+ timeout { fail "(timeout) complete 'set follow-fork-mode'" }
+ }
+
+set timeout $oldtimeout1
+return 0
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/gdb/testsuite/gdb.base/cond-expr.exp b/gdb/testsuite/gdb.base/cond-expr.exp
new file mode 100644
index 00000000000..0e78b427795
--- /dev/null
+++ b/gdb/testsuite/gdb.base/cond-expr.exp
@@ -0,0 +1,122 @@
+# Copyright (C) 1998 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file was written by Elena Zannoni (ezannoni@cygnus.com)
+
+# This file is part of the gdb testsuite
+
+#
+# test of evaluation of conditional expressions, with constants and
+# variables. Using the print and the whatis command
+# written with the only purpose in mind to cover the holes in the
+# eval.c file
+#
+# source file "int-type.c"
+#
+
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+# Check to see if we have an executable to test. If not, then either we
+# haven't tried to compile one, or the compilation failed for some reason.
+# In either case, just notify the user and skip the tests in this file.
+
+set testfile "int-type"
+set srcfile ${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug additional_flags=-w}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+ }
+
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+
+if ![runto_main] then {
+ perror "couldn't run to breakpoint"
+ continue
+}
+
+send_gdb "print (2 ? 3 : 4)\n"
+gdb_expect {
+ -re ".\[0-9\]* = 3.*$gdb_prompt $" {
+ pass "print value of cond expr (const true)"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of cond expr (const true)" }
+ timeout { fail "(timeout) print value of cond expr (const true)" }
+ }
+
+send_gdb "print (0 ? 3 : 4)\n"
+gdb_expect {
+ -re ".\[0-9\]* = 4.*$gdb_prompt $" {
+ pass "print value of cond expr (const false)"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of cond expr (const false)" }
+ timeout { fail "(timeout) print value of cond expr (const false)" }
+ }
+
+gdb_test "set variable x=14" "" "set variable x=14"
+gdb_test "set variable y=2" "" "set variable y=2"
+gdb_test "set variable z=3" "" "set variable z=3"
+
+send_gdb "print (x ? y : z)\n"
+gdb_expect {
+ -re ".\[0-9\]* = 2.*$gdb_prompt $" {
+ pass "print value of cond expr (var true)"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of cond expr (var true)" }
+ timeout { fail "(timeout) print value of cond expr (var true)" }
+ }
+
+gdb_test "set variable x=0" "" "set variable x=0"
+
+send_gdb "print (x ? y : z)\n"
+gdb_expect {
+ -re ".\[0-9\]* = 3.*$gdb_prompt $" {
+ pass "print value of cond expr (var false)"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of cond expr (var false)" }
+ timeout { fail "(timeout) print value of cond expr (var false)" }
+ }
+
+
+send_gdb "whatis (0 ? 3 : 4)\n"
+gdb_expect {
+ -re "type = int.*$gdb_prompt $" {
+ pass "print whatis of cond expr"
+ }
+ -re ".*$gdb_prompt $" { fail "print whatis of cond expr" }
+ timeout { fail "(timeout) print whatis of cond expr" }
+ }
+
+
+
+
+
+
+
+
+
+
+
diff --git a/gdb/testsuite/gdb.base/condbreak.c b/gdb/testsuite/gdb.base/condbreak.c
new file mode 100644
index 00000000000..491d6e5dd5d
--- /dev/null
+++ b/gdb/testsuite/gdb.base/condbreak.c
@@ -0,0 +1,81 @@
+#ifdef vxworks
+
+# include <stdio.h>
+
+/* VxWorks does not supply atoi. */
+static int
+atoi (z)
+ char *z;
+{
+ int i = 0;
+
+ while (*z >= '0' && *z <= '9')
+ i = i * 10 + (*z++ - '0');
+ return i;
+}
+
+/* I don't know of any way to pass an array to VxWorks. This function
+ can be called directly from gdb. */
+
+vxmain (arg)
+char *arg;
+{
+ char *argv[2];
+
+ argv[0] = "";
+ argv[1] = arg;
+ main (2, argv, (char **) 0);
+}
+
+#else /* ! vxworks */
+# include <stdio.h>
+#endif /* ! vxworks */
+
+/*
+ * The following functions do nothing useful. They are included simply
+ * as places to try setting breakpoints at. They are explicitly
+ * "one-line functions" to verify that this case works (some versions
+ * of gcc have or have had problems with this).
+ */
+
+int marker1 () { return (0); }
+int marker2 (a) int a; { return (1); }
+void marker3 (a, b) char *a, *b; {}
+void marker4 (d) long d; {}
+
+/*
+ * This simple classical example of recursion is useful for
+ * testing stack backtraces and such.
+ */
+
+int
+main (argc, argv, envp)
+int argc;
+char *argv[], **envp;
+{
+#ifdef usestubs
+ set_debug_traps();
+ breakpoint();
+#endif
+ if (argc == 123456) {
+ fprintf (stderr, "usage: factorial <number>\n");
+ return 1;
+ }
+ printf ("%d\n", factorial (atoi ("6")));
+
+ marker1 ();
+ marker2 (43);
+ marker3 ("stack", "trace");
+ marker4 (177601976L);
+ return 0;
+}
+
+int factorial (value)
+int value;
+{
+ if (value > 1) {
+ value *= factorial (value - 1);
+ }
+ return (value);
+}
+
diff --git a/gdb/testsuite/gdb.base/condbreak.exp b/gdb/testsuite/gdb.base/condbreak.exp
new file mode 100644
index 00000000000..76f752181ec
--- /dev/null
+++ b/gdb/testsuite/gdb.base/condbreak.exp
@@ -0,0 +1,157 @@
+# Copyright (C) 1997, 1998 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This test was written by Rich Title.
+# Purpose is to test conditional breakpoints.
+# Modeled after "break.exp".
+
+
+
+if $tracelevel then {
+ strace $tracelevel
+ }
+
+global usestubs
+
+#
+# test running programs
+#
+set prms_id 0
+set bug_id 0
+
+set testfile "condbreak"
+set srcfile ${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug additional_flags=-w}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+
+if [target_info exists gdb_stub] {
+ gdb_step_for_stub;
+}
+
+#
+# test break at function
+#
+gdb_test "break main" \
+ "Breakpoint.*at.* file .*$srcfile, line.*" \
+ "breakpoint function"
+
+#
+# test conditional break at function
+#
+gdb_test "break marker1 if 1==1" \
+ "Breakpoint.*at.* file .*$srcfile, line.*" \
+ "break function if condition"
+
+gdb_test "delete 2" \
+ "" \
+ "delete break"
+
+#
+# test conditional break at line number
+#
+gdb_test "break 64 if 1==1" \
+ "Breakpoint.*at.* file .*$srcfile, line 64\\." \
+ "break line if condition"
+
+gdb_test "delete 3" \
+ "" \
+ "delete break"
+
+#
+# test conditional break at function
+#
+gdb_test "break marker1 if (1==1)" \
+ "Breakpoint.*at.* file .*$srcfile, line.*" \
+ "break function if (condition)"
+
+#
+# test conditional break at line number
+#
+gdb_test "break 64 if (1==1)" \
+ "Breakpoint.*at.* file .*$srcfile, line 64\\." \
+ "break line if (condition)"
+
+gdb_test "break marker2 if (a==43)" \
+ "Breakpoint.*at.* file .*$srcfile, line.*" \
+ "break function if (condition)"
+
+#
+# check to see what breakpoints are set
+#
+
+set main_line 60
+gdb_test "info break" \
+ "Num Type\[ \]+Disp Enb Address\[ \]+What.*
+\[0-9\]+\[\t \]+breakpoint keep y.* in main at .*$srcfile:$main_line.*
+\[0-9\]+\[\t \]+breakpoint keep y.* in marker1 at .*$srcfile:41.*
+\[\t \]+stop only if 1 == 1.*
+\[0-9\]+\[\t \]+breakpoint keep y.* in main at .*$srcfile:64.*
+\[\t \]+stop only if 1 == 1.*
+\[0-9\]+\[\t \]+breakpoint keep y.* in marker2 at .*$srcfile:42.*
+\[\t \]+stop only if a == 43.*" \
+ "breakpoint info"
+
+
+#
+# run until the breakpoint at main is hit. For non-stubs-using targets.
+#
+gdb_test "run" \
+ "Starting program.*Breakpoint \[0-9\]+,.*main .*argc.*argv.* at .*$srcfile:60.*60\[\t \]+if .argc.* \{.*" \
+"run until function breakpoint"
+
+#
+# run until the breakpoint at a line number
+#
+gdb_test "continue" "Continuing\\..*Breakpoint \[0-9\]+, main \\(argc=.*, argv=.*, envp=.*\\) at .*$srcfile:64.*64\[\t \]+printf.*factorial.*" \
+ "run until breakpoint set at a line number"
+
+#
+# run until the breakpoint at marker1
+#
+gdb_test "continue" "Continuing\\..*Breakpoint \[0-9\]+, marker1 \\(\\) at .*$srcfile:41.*41\[\t \]+.*" \
+ "run until breakpoint at marker1"
+
+#
+# run until the breakpoint at marker2
+#
+gdb_test "continue" "Continuing\\..*Breakpoint \[0-9\]+, marker2 \\(a=43\\) at .*$srcfile:42.*42\[\t \]+.*" \
+ "run until breakpoint at marker2"
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/gdb/testsuite/gdb.base/configure b/gdb/testsuite/gdb.base/configure
new file mode 100644
index 00000000000..29e69bfe1a5
--- /dev/null
+++ b/gdb/testsuite/gdb.base/configure
@@ -0,0 +1,899 @@
+#! /bin/sh
+
+# Guess values for system-dependent variables and create Makefiles.
+# Generated automatically using autoconf version 2.12.1
+# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc.
+#
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+
+# Defaults:
+ac_help=
+ac_default_prefix=/usr/local
+# Any additions from configure.in:
+
+# Initialize some variables set by options.
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+build=NONE
+cache_file=./config.cache
+exec_prefix=NONE
+host=NONE
+no_create=
+nonopt=NONE
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+target=NONE
+verbose=
+x_includes=NONE
+x_libraries=NONE
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datadir='${prefix}/share'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+libdir='${exec_prefix}/lib'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+infodir='${prefix}/info'
+mandir='${prefix}/man'
+
+# Initialize some other variables.
+subdirs=
+MFLAGS= MAKEFLAGS=
+SHELL=${CONFIG_SHELL-/bin/sh}
+# Maximum number of lines to put in a shell here document.
+ac_max_here_lines=12
+
+ac_prev=
+for ac_option
+do
+
+ # If the previous option needs an argument, assign it.
+ if test -n "$ac_prev"; then
+ eval "$ac_prev=\$ac_option"
+ ac_prev=
+ continue
+ fi
+
+ case "$ac_option" in
+ -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
+ *) ac_optarg= ;;
+ esac
+
+ # Accept the important Cygnus configure options, so we can diagnose typos.
+
+ case "$ac_option" in
+
+ -bindir | --bindir | --bindi | --bind | --bin | --bi)
+ ac_prev=bindir ;;
+ -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+ bindir="$ac_optarg" ;;
+
+ -build | --build | --buil | --bui | --bu)
+ ac_prev=build ;;
+ -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+ build="$ac_optarg" ;;
+
+ -cache-file | --cache-file | --cache-fil | --cache-fi \
+ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+ ac_prev=cache_file ;;
+ -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+ cache_file="$ac_optarg" ;;
+
+ -datadir | --datadir | --datadi | --datad | --data | --dat | --da)
+ ac_prev=datadir ;;
+ -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \
+ | --da=*)
+ datadir="$ac_optarg" ;;
+
+ -disable-* | --disable-*)
+ ac_feature=`echo $ac_option|sed -e 's/-*disable-//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then
+ { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
+ fi
+ ac_feature=`echo $ac_feature| sed 's/-/_/g'`
+ eval "enable_${ac_feature}=no" ;;
+
+ -enable-* | --enable-*)
+ ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then
+ { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
+ fi
+ ac_feature=`echo $ac_feature| sed 's/-/_/g'`
+ case "$ac_option" in
+ *=*) ;;
+ *) ac_optarg=yes ;;
+ esac
+ eval "enable_${ac_feature}='$ac_optarg'" ;;
+
+ -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+ | --exec | --exe | --ex)
+ ac_prev=exec_prefix ;;
+ -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+ | --exec=* | --exe=* | --ex=*)
+ exec_prefix="$ac_optarg" ;;
+
+ -gas | --gas | --ga | --g)
+ # Obsolete; use --with-gas.
+ with_gas=yes ;;
+
+ -help | --help | --hel | --he)
+ # Omit some internal or obsolete options to make the list less imposing.
+ # This message is too long to be a string in the A/UX 3.1 sh.
+ cat << EOF
+Usage: configure [options] [host]
+Options: [defaults in brackets after descriptions]
+Configuration:
+ --cache-file=FILE cache test results in FILE
+ --help print this message
+ --no-create do not create output files
+ --quiet, --silent do not print \`checking...' messages
+ --version print the version of autoconf that created configure
+Directory and file names:
+ --prefix=PREFIX install architecture-independent files in PREFIX
+ [$ac_default_prefix]
+ --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
+ [same as prefix]
+ --bindir=DIR user executables in DIR [EPREFIX/bin]
+ --sbindir=DIR system admin executables in DIR [EPREFIX/sbin]
+ --libexecdir=DIR program executables in DIR [EPREFIX/libexec]
+ --datadir=DIR read-only architecture-independent data in DIR
+ [PREFIX/share]
+ --sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc]
+ --sharedstatedir=DIR modifiable architecture-independent data in DIR
+ [PREFIX/com]
+ --localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var]
+ --libdir=DIR object code libraries in DIR [EPREFIX/lib]
+ --includedir=DIR C header files in DIR [PREFIX/include]
+ --oldincludedir=DIR C header files for non-gcc in DIR [/usr/include]
+ --infodir=DIR info documentation in DIR [PREFIX/info]
+ --mandir=DIR man documentation in DIR [PREFIX/man]
+ --srcdir=DIR find the sources in DIR [configure dir or ..]
+ --program-prefix=PREFIX prepend PREFIX to installed program names
+ --program-suffix=SUFFIX append SUFFIX to installed program names
+ --program-transform-name=PROGRAM
+ run sed PROGRAM on installed program names
+EOF
+ cat << EOF
+Host type:
+ --build=BUILD configure for building on BUILD [BUILD=HOST]
+ --host=HOST configure for HOST [guessed]
+ --target=TARGET configure for TARGET [TARGET=HOST]
+Features and packages:
+ --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
+ --enable-FEATURE[=ARG] include FEATURE [ARG=yes]
+ --with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
+ --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
+ --x-includes=DIR X include files are in DIR
+ --x-libraries=DIR X library files are in DIR
+EOF
+ if test -n "$ac_help"; then
+ echo "--enable and --with options recognized:$ac_help"
+ fi
+ exit 0 ;;
+
+ -host | --host | --hos | --ho)
+ ac_prev=host ;;
+ -host=* | --host=* | --hos=* | --ho=*)
+ host="$ac_optarg" ;;
+
+ -includedir | --includedir | --includedi | --included | --include \
+ | --includ | --inclu | --incl | --inc)
+ ac_prev=includedir ;;
+ -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+ | --includ=* | --inclu=* | --incl=* | --inc=*)
+ includedir="$ac_optarg" ;;
+
+ -infodir | --infodir | --infodi | --infod | --info | --inf)
+ ac_prev=infodir ;;
+ -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+ infodir="$ac_optarg" ;;
+
+ -libdir | --libdir | --libdi | --libd)
+ ac_prev=libdir ;;
+ -libdir=* | --libdir=* | --libdi=* | --libd=*)
+ libdir="$ac_optarg" ;;
+
+ -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+ | --libexe | --libex | --libe)
+ ac_prev=libexecdir ;;
+ -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+ | --libexe=* | --libex=* | --libe=*)
+ libexecdir="$ac_optarg" ;;
+
+ -localstatedir | --localstatedir | --localstatedi | --localstated \
+ | --localstate | --localstat | --localsta | --localst \
+ | --locals | --local | --loca | --loc | --lo)
+ ac_prev=localstatedir ;;
+ -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+ | --localstate=* | --localstat=* | --localsta=* | --localst=* \
+ | --locals=* | --local=* | --loca=* | --loc=* | --lo=*)
+ localstatedir="$ac_optarg" ;;
+
+ -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+ ac_prev=mandir ;;
+ -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+ mandir="$ac_optarg" ;;
+
+ -nfp | --nfp | --nf)
+ # Obsolete; use --without-fp.
+ with_fp=no ;;
+
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c)
+ no_create=yes ;;
+
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+ no_recursion=yes ;;
+
+ -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+ | --oldin | --oldi | --old | --ol | --o)
+ ac_prev=oldincludedir ;;
+ -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+ oldincludedir="$ac_optarg" ;;
+
+ -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+ ac_prev=prefix ;;
+ -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+ prefix="$ac_optarg" ;;
+
+ -program-prefix | --program-prefix | --program-prefi | --program-pref \
+ | --program-pre | --program-pr | --program-p)
+ ac_prev=program_prefix ;;
+ -program-prefix=* | --program-prefix=* | --program-prefi=* \
+ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+ program_prefix="$ac_optarg" ;;
+
+ -program-suffix | --program-suffix | --program-suffi | --program-suff \
+ | --program-suf | --program-su | --program-s)
+ ac_prev=program_suffix ;;
+ -program-suffix=* | --program-suffix=* | --program-suffi=* \
+ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+ program_suffix="$ac_optarg" ;;
+
+ -program-transform-name | --program-transform-name \
+ | --program-transform-nam | --program-transform-na \
+ | --program-transform-n | --program-transform- \
+ | --program-transform | --program-transfor \
+ | --program-transfo | --program-transf \
+ | --program-trans | --program-tran \
+ | --progr-tra | --program-tr | --program-t)
+ ac_prev=program_transform_name ;;
+ -program-transform-name=* | --program-transform-name=* \
+ | --program-transform-nam=* | --program-transform-na=* \
+ | --program-transform-n=* | --program-transform-=* \
+ | --program-transform=* | --program-transfor=* \
+ | --program-transfo=* | --program-transf=* \
+ | --program-trans=* | --program-tran=* \
+ | --progr-tra=* | --program-tr=* | --program-t=*)
+ program_transform_name="$ac_optarg" ;;
+
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ silent=yes ;;
+
+ -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+ ac_prev=sbindir ;;
+ -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+ | --sbi=* | --sb=*)
+ sbindir="$ac_optarg" ;;
+
+ -sharedstatedir | --sharedstatedir | --sharedstatedi \
+ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+ | --sharedst | --shareds | --shared | --share | --shar \
+ | --sha | --sh)
+ ac_prev=sharedstatedir ;;
+ -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+ | --sha=* | --sh=*)
+ sharedstatedir="$ac_optarg" ;;
+
+ -site | --site | --sit)
+ ac_prev=site ;;
+ -site=* | --site=* | --sit=*)
+ site="$ac_optarg" ;;
+
+ -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+ ac_prev=srcdir ;;
+ -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+ srcdir="$ac_optarg" ;;
+
+ -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+ | --syscon | --sysco | --sysc | --sys | --sy)
+ ac_prev=sysconfdir ;;
+ -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+ sysconfdir="$ac_optarg" ;;
+
+ -target | --target | --targe | --targ | --tar | --ta | --t)
+ ac_prev=target ;;
+ -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+ target="$ac_optarg" ;;
+
+ -v | -verbose | --verbose | --verbos | --verbo | --verb)
+ verbose=yes ;;
+
+ -version | --version | --versio | --versi | --vers)
+ echo "configure generated by autoconf version 2.12.1"
+ exit 0 ;;
+
+ -with-* | --with-*)
+ ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then
+ { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
+ fi
+ ac_package=`echo $ac_package| sed 's/-/_/g'`
+ case "$ac_option" in
+ *=*) ;;
+ *) ac_optarg=yes ;;
+ esac
+ eval "with_${ac_package}='$ac_optarg'" ;;
+
+ -without-* | --without-*)
+ ac_package=`echo $ac_option|sed -e 's/-*without-//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then
+ { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
+ fi
+ ac_package=`echo $ac_package| sed 's/-/_/g'`
+ eval "with_${ac_package}=no" ;;
+
+ --x)
+ # Obsolete; use --with-x.
+ with_x=yes ;;
+
+ -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+ | --x-incl | --x-inc | --x-in | --x-i)
+ ac_prev=x_includes ;;
+ -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+ x_includes="$ac_optarg" ;;
+
+ -x-libraries | --x-libraries | --x-librarie | --x-librari \
+ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+ ac_prev=x_libraries ;;
+ -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+ x_libraries="$ac_optarg" ;;
+
+ -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; }
+ ;;
+
+ *)
+ if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then
+ echo "configure: warning: $ac_option: invalid host type" 1>&2
+ fi
+ if test "x$nonopt" != xNONE; then
+ { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; }
+ fi
+ nonopt="$ac_option"
+ ;;
+
+ esac
+done
+
+if test -n "$ac_prev"; then
+ { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; }
+fi
+
+trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
+
+# File descriptor usage:
+# 0 standard input
+# 1 file creation
+# 2 errors and warnings
+# 3 some systems may open it to /dev/tty
+# 4 used on the Kubota Titan
+# 6 checking for... messages and results
+# 5 compiler messages saved in config.log
+if test "$silent" = yes; then
+ exec 6>/dev/null
+else
+ exec 6>&1
+fi
+exec 5>./config.log
+
+echo "\
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+" 1>&5
+
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Also quote any args containing shell metacharacters.
+ac_configure_args=
+for ac_arg
+do
+ case "$ac_arg" in
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c) ;;
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;;
+ *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*)
+ ac_configure_args="$ac_configure_args '$ac_arg'" ;;
+ *) ac_configure_args="$ac_configure_args $ac_arg" ;;
+ esac
+done
+
+# NLS nuisances.
+# Only set these to C if already set. These must not be set unconditionally
+# because not all systems understand e.g. LANG=C (notably SCO).
+# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'!
+# Non-C LC_CTYPE values break the ctype check.
+if test "${LANG+set}" = set; then LANG=C; export LANG; fi
+if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi
+if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi
+if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -rf conftest* confdefs.h
+# AIX cpp loses on an empty file, so make sure it contains at least a newline.
+echo > confdefs.h
+
+# A filename unique to this package, relative to the directory that
+# configure is in, which we can look for to find out if srcdir is correct.
+ac_unique_file=a1-selftest.exp
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+ ac_srcdir_defaulted=yes
+ # Try the directory containing this script, then its parent.
+ ac_prog=$0
+ ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'`
+ test "x$ac_confdir" = "x$ac_prog" && ac_confdir=.
+ srcdir=$ac_confdir
+ if test ! -r $srcdir/$ac_unique_file; then
+ srcdir=..
+ fi
+else
+ ac_srcdir_defaulted=no
+fi
+if test ! -r $srcdir/$ac_unique_file; then
+ if test "$ac_srcdir_defaulted" = yes; then
+ { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; }
+ else
+ { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; }
+ fi
+fi
+srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'`
+
+# Prefer explicitly selected file to automatically selected ones.
+if test -z "$CONFIG_SITE"; then
+ if test "x$prefix" != xNONE; then
+ CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site"
+ else
+ CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
+ fi
+fi
+for ac_site_file in $CONFIG_SITE; do
+ if test -r "$ac_site_file"; then
+ echo "loading site script $ac_site_file"
+ . "$ac_site_file"
+ fi
+done
+
+if test -r "$cache_file"; then
+ echo "loading cache $cache_file"
+ . $cache_file
+else
+ echo "creating cache $cache_file"
+ > $cache_file
+fi
+
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then
+ # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu.
+ if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then
+ ac_n= ac_c='
+' ac_t=' '
+ else
+ ac_n=-n ac_c= ac_t=
+ fi
+else
+ ac_n= ac_c='\c' ac_t=
+fi
+
+
+
+CC=${CC-cc}
+
+ac_aux_dir=
+for ac_dir in `cd $srcdir;pwd`/../../.. $srcdir/`cd $srcdir;pwd`/../../..; do
+ if test -f $ac_dir/install-sh; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install-sh -c"
+ break
+ elif test -f $ac_dir/install.sh; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install.sh -c"
+ break
+ fi
+done
+if test -z "$ac_aux_dir"; then
+ { echo "configure: error: can not find install-sh or install.sh in `cd $srcdir;pwd`/../../.. $srcdir/`cd $srcdir;pwd`/../../.." 1>&2; exit 1; }
+fi
+ac_config_guess=$ac_aux_dir/config.guess
+ac_config_sub=$ac_aux_dir/config.sub
+ac_configure=$ac_aux_dir/configure # This should be Cygnus configure.
+
+
+# Do some error checking and defaulting for the host and target type.
+# The inputs are:
+# configure --host=HOST --target=TARGET --build=BUILD NONOPT
+#
+# The rules are:
+# 1. You are not allowed to specify --host, --target, and nonopt at the
+# same time.
+# 2. Host defaults to nonopt.
+# 3. If nonopt is not specified, then host defaults to the current host,
+# as determined by config.guess.
+# 4. Target and build default to nonopt.
+# 5. If nonopt is not specified, then target and build default to host.
+
+# The aliases save the names the user supplied, while $host etc.
+# will get canonicalized.
+case $host---$target---$nonopt in
+NONE---*---* | *---NONE---* | *---*---NONE) ;;
+*) { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; } ;;
+esac
+
+
+# Make sure we can run config.sub.
+if ${CONFIG_SHELL-/bin/sh} $ac_config_sub sun4 >/dev/null 2>&1; then :
+else { echo "configure: error: can not run $ac_config_sub" 1>&2; exit 1; }
+fi
+
+echo $ac_n "checking host system type""... $ac_c" 1>&6
+echo "configure:573: checking host system type" >&5
+
+host_alias=$host
+case "$host_alias" in
+NONE)
+ case $nonopt in
+ NONE)
+ if host_alias=`${CONFIG_SHELL-/bin/sh} $ac_config_guess`; then :
+ else { echo "configure: error: can not guess host type; you must specify one" 1>&2; exit 1; }
+ fi ;;
+ *) host_alias=$nonopt ;;
+ esac ;;
+esac
+
+host=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $host_alias`
+host_cpu=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+host_vendor=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+host_os=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+echo "$ac_t""$host" 1>&6
+
+echo $ac_n "checking target system type""... $ac_c" 1>&6
+echo "configure:594: checking target system type" >&5
+
+target_alias=$target
+case "$target_alias" in
+NONE)
+ case $nonopt in
+ NONE) target_alias=$host_alias ;;
+ *) target_alias=$nonopt ;;
+ esac ;;
+esac
+
+target=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $target_alias`
+target_cpu=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+target_vendor=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+target_os=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+echo "$ac_t""$target" 1>&6
+
+echo $ac_n "checking build system type""... $ac_c" 1>&6
+echo "configure:612: checking build system type" >&5
+
+build_alias=$build
+case "$build_alias" in
+NONE)
+ case $nonopt in
+ NONE) build_alias=$host_alias ;;
+ *) build_alias=$nonopt ;;
+ esac ;;
+esac
+
+build=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $build_alias`
+build_cpu=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+build_vendor=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+build_os=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+echo "$ac_t""$build" 1>&6
+
+test "$host_alias" != "$target_alias" &&
+ test "$program_prefix$program_suffix$program_transform_name" = \
+ NONENONEs,x,x, &&
+ program_prefix=${target_alias}-
+
+
+trap '' 1 2 15
+cat > confcache <<\EOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs. It is not useful on other systems.
+# If it contains results you don't want to keep, you may remove or edit it.
+#
+# By default, configure uses ./config.cache as the cache file,
+# creating it if it does not exist already. You can give configure
+# the --cache-file=FILE option to use a different cache file; that is
+# what configure does when it calls configure scripts in
+# subdirectories, so they share the cache.
+# Giving --cache-file=/dev/null disables caching, for debugging configure.
+# config.status only pays attention to the cache file if you give it the
+# --recheck option to rerun configure.
+#
+EOF
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, don't put newlines in cache variables' values.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(set) 2>&1 |
+ case `(ac_space=' '; set) 2>&1 | grep ac_space` in
+ *ac_space=\ *)
+ # `set' does not quote correctly, so add quotes (double-quote substitution
+ # turns \\\\ into \\, and sed turns \\ into \).
+ sed -n \
+ -e "s/'/'\\\\''/g" \
+ -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p"
+ ;;
+ *)
+ # `set' quotes correctly as required by POSIX, so do not add quotes.
+ sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p'
+ ;;
+ esac >> confcache
+if cmp -s $cache_file confcache; then
+ :
+else
+ if test -w $cache_file; then
+ echo "updating cache $cache_file"
+ cat confcache > $cache_file
+ else
+ echo "not updating unwritable cache $cache_file"
+ fi
+fi
+rm -f confcache
+
+trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+# Any assignment to VPATH causes Sun make to only execute
+# the first set of double-colon rules, so remove it if not needed.
+# If there is a colon in the path, we need to keep it.
+if test "x$srcdir" = x.; then
+ ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d'
+fi
+
+trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15
+
+# Transform confdefs.h into DEFS.
+# Protect against shell expansion while executing Makefile rules.
+# Protect against Makefile macro expansion.
+cat > conftest.defs <<\EOF
+s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%-D\1=\2%g
+s%[ `~#$^&*(){}\\|;'"<>?]%\\&%g
+s%\[%\\&%g
+s%\]%\\&%g
+s%\$%$$%g
+EOF
+DEFS=`sed -f conftest.defs confdefs.h | tr '\012' ' '`
+rm -f conftest.defs
+
+
+# Without the "./", some shells look in PATH for config.status.
+: ${CONFIG_STATUS=./config.status}
+
+echo creating $CONFIG_STATUS
+rm -f $CONFIG_STATUS
+cat > $CONFIG_STATUS <<EOF
+#! /bin/sh
+# Generated automatically by configure.
+# Run this file to recreate the current configuration.
+# This directory was configured as follows,
+# on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+#
+# $0 $ac_configure_args
+#
+# Compiler output produced by configure, useful for debugging
+# configure, is in ./config.log if it exists.
+
+ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]"
+for ac_option
+do
+ case "\$ac_option" in
+ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+ echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion"
+ exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;;
+ -version | --version | --versio | --versi | --vers | --ver | --ve | --v)
+ echo "$CONFIG_STATUS generated by autoconf version 2.12.1"
+ exit 0 ;;
+ -help | --help | --hel | --he | --h)
+ echo "\$ac_cs_usage"; exit 0 ;;
+ *) echo "\$ac_cs_usage"; exit 1 ;;
+ esac
+done
+
+ac_given_srcdir=$srcdir
+
+trap 'rm -fr `echo "Makefile" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15
+EOF
+cat >> $CONFIG_STATUS <<EOF
+
+# Protect against being on the right side of a sed subst in config.status.
+sed 's/%@/@@/; s/@%/@@/; s/%g\$/@g/; /@g\$/s/[\\\\&%]/\\\\&/g;
+ s/@@/%@/; s/@@/@%/; s/@g\$/%g/' > conftest.subs <<\\CEOF
+$ac_vpsub
+$extrasub
+s%@SHELL@%$SHELL%g
+s%@CFLAGS@%$CFLAGS%g
+s%@CPPFLAGS@%$CPPFLAGS%g
+s%@CXXFLAGS@%$CXXFLAGS%g
+s%@DEFS@%$DEFS%g
+s%@LDFLAGS@%$LDFLAGS%g
+s%@LIBS@%$LIBS%g
+s%@exec_prefix@%$exec_prefix%g
+s%@prefix@%$prefix%g
+s%@program_transform_name@%$program_transform_name%g
+s%@bindir@%$bindir%g
+s%@sbindir@%$sbindir%g
+s%@libexecdir@%$libexecdir%g
+s%@datadir@%$datadir%g
+s%@sysconfdir@%$sysconfdir%g
+s%@sharedstatedir@%$sharedstatedir%g
+s%@localstatedir@%$localstatedir%g
+s%@libdir@%$libdir%g
+s%@includedir@%$includedir%g
+s%@oldincludedir@%$oldincludedir%g
+s%@infodir@%$infodir%g
+s%@mandir@%$mandir%g
+s%@CC@%$CC%g
+s%@host@%$host%g
+s%@host_alias@%$host_alias%g
+s%@host_cpu@%$host_cpu%g
+s%@host_vendor@%$host_vendor%g
+s%@host_os@%$host_os%g
+s%@target@%$target%g
+s%@target_alias@%$target_alias%g
+s%@target_cpu@%$target_cpu%g
+s%@target_vendor@%$target_vendor%g
+s%@target_os@%$target_os%g
+s%@build@%$build%g
+s%@build_alias@%$build_alias%g
+s%@build_cpu@%$build_cpu%g
+s%@build_vendor@%$build_vendor%g
+s%@build_os@%$build_os%g
+
+CEOF
+EOF
+
+cat >> $CONFIG_STATUS <<\EOF
+
+# Split the substitutions into bite-sized pieces for seds with
+# small command number limits, like on Digital OSF/1 and HP-UX.
+ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script.
+ac_file=1 # Number of current file.
+ac_beg=1 # First line for current file.
+ac_end=$ac_max_sed_cmds # Line after last line for current file.
+ac_more_lines=:
+ac_sed_cmds=""
+while $ac_more_lines; do
+ if test $ac_beg -gt 1; then
+ sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file
+ else
+ sed "${ac_end}q" conftest.subs > conftest.s$ac_file
+ fi
+ if test ! -s conftest.s$ac_file; then
+ ac_more_lines=false
+ rm -f conftest.s$ac_file
+ else
+ if test -z "$ac_sed_cmds"; then
+ ac_sed_cmds="sed -f conftest.s$ac_file"
+ else
+ ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file"
+ fi
+ ac_file=`expr $ac_file + 1`
+ ac_beg=$ac_end
+ ac_end=`expr $ac_end + $ac_max_sed_cmds`
+ fi
+done
+if test -z "$ac_sed_cmds"; then
+ ac_sed_cmds=cat
+fi
+EOF
+
+cat >> $CONFIG_STATUS <<EOF
+
+CONFIG_FILES=\${CONFIG_FILES-"Makefile"}
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then
+ # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+ case "$ac_file" in
+ *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'`
+ ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
+ *) ac_file_in="${ac_file}.in" ;;
+ esac
+
+ # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories.
+
+ # Remove last slash and all that follows it. Not all systems have dirname.
+ ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
+ if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
+ # The file is in a subdirectory.
+ test ! -d "$ac_dir" && mkdir "$ac_dir"
+ ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`"
+ # A "../" for each directory in $ac_dir_suffix.
+ ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'`
+ else
+ ac_dir_suffix= ac_dots=
+ fi
+
+ case "$ac_given_srcdir" in
+ .) srcdir=.
+ if test -z "$ac_dots"; then top_srcdir=.
+ else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;;
+ /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;;
+ *) # Relative path.
+ srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix"
+ top_srcdir="$ac_dots$ac_given_srcdir" ;;
+ esac
+
+
+ echo creating "$ac_file"
+ rm -f "$ac_file"
+ configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure."
+ case "$ac_file" in
+ *Makefile*) ac_comsub="1i\\
+# $configure_input" ;;
+ *) ac_comsub= ;;
+ esac
+
+ ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"`
+ sed -e "$ac_comsub
+s%@configure_input@%$configure_input%g
+s%@srcdir@%$srcdir%g
+s%@top_srcdir@%$top_srcdir%g
+" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file
+fi; done
+rm -f conftest.s*
+
+EOF
+cat >> $CONFIG_STATUS <<EOF
+
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+
+exit 0
+EOF
+chmod +x $CONFIG_STATUS
+rm -fr confdefs* $ac_clean_files
+test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1
+
diff --git a/gdb/testsuite/gdb.base/configure.in b/gdb/testsuite/gdb.base/configure.in
new file mode 100644
index 00000000000..e5bcb19539b
--- /dev/null
+++ b/gdb/testsuite/gdb.base/configure.in
@@ -0,0 +1,15 @@
+dnl Process this file file with autoconf to produce a configure script.
+dnl This file is a shell script fragment that supplies the information
+dnl necessary to tailor a template configure script into the configure
+dnl script appropriate for this directory. For more information, check
+dnl any existing configure script.
+
+AC_PREREQ(2.5)
+AC_INIT(a1-selftest.exp)
+
+CC=${CC-cc}
+AC_SUBST(CC)
+AC_CONFIG_AUX_DIR(`cd $srcdir;pwd`/../../..)
+AC_CANONICAL_SYSTEM
+
+AC_OUTPUT(Makefile)
diff --git a/gdb/testsuite/gdb.base/constvars.c b/gdb/testsuite/gdb.base/constvars.c
new file mode 100644
index 00000000000..b0ce7529ecb
--- /dev/null
+++ b/gdb/testsuite/gdb.base/constvars.c
@@ -0,0 +1,183 @@
+void marker1 (void)
+{
+}
+
+/* misc. function params */
+
+int
+qux1 (const char cc, const char /*&*/ccr, const char *ccp, char *const cpc)
+{
+ return 33;
+}
+
+int
+qux2 (volatile unsigned char vuc, const volatile int cvi,
+ volatile short /*&*/vsr, volatile long *vlp, float *volatile fpv,
+ const volatile signed char *const volatile cvscpcv)
+{
+ return 400;
+}
+
+int
+main (void)
+{
+ char lave = 'B';
+ unsigned char lavish = 10;
+ short lax = 20;
+ unsigned short lecherous = 30;
+ long lechery = 40;
+ unsigned long lectern = 50;
+ float leeway = 60;
+ double legacy = 70;
+ signed char lemonade = 35;
+
+ const char laconic = 'A';
+ const unsigned char laggard = 1;
+ const short lagoon = 2;
+ const unsigned short laity = 3;
+ const long lambent = 4;
+ const unsigned long laminated = 5;
+ const float lampoon = 6;
+ const double languid = 7;
+
+ /* pointers to constant variables */
+
+ const char *legend = &lave;
+ const unsigned char *legerdemain = &lavish;
+ const short *leniency = &lax;
+ const unsigned short *leonine = &lecherous;
+ const long *lesion = &lechery;
+ const unsigned long *lethal = &lectern;
+ const float *lethargic = &leeway;
+ const double *levity = &legacy;
+
+ /* constant pointers to constant variables */
+
+ const char *const lewd = &laconic;
+ const unsigned char *const lexicographer = &laggard;
+ const short *const lexicon = &lagoon;
+ const unsigned short *const liaison = &laity;
+ const long *const libation = &lambent;
+ const unsigned long *const libelous = &laminated;
+ const float *const libertine = &lampoon;
+ const double *const libidinous = &languid;
+
+ /* this is the same as const char * legend .... */
+
+ char const *languish = &laconic;
+ unsigned char const *languor = &laggard;
+ short const *lank = &lagoon;
+ unsigned short const *lapidary = &laity;
+ long const *larceny = &lambent;
+ unsigned long const *largess = &laminated;
+ float const *lascivious = &lampoon;
+ double const *lassitude = &languid;
+
+ /* constant pointers to variable */
+
+ char *const lamprey = &lave;
+ unsigned char *const lariat = &lavish;
+ short *const laudanum = &lax;
+ unsigned short *const lecithin = &lecherous;
+ long *const leviathan = &lechery;
+ unsigned long *const libretto = &lectern;
+ float *const lissome = &leeway;
+ double *const locust = &legacy;
+
+ /* volatile variables */
+
+ volatile char vox = 'X';
+ volatile unsigned char victuals = 13;
+ volatile short vixen = 200;
+ volatile unsigned short vitriol = 300;
+ volatile long vellum = 1000;
+ volatile unsigned long valve = 2000;
+ volatile float vacuity = 3.0;
+ volatile double vertigo = 10.3;
+
+ /* pointers to volatile variables */
+
+ volatile char * vampire = &vox;
+ volatile unsigned char * viper = &victuals;
+ volatile short * vigour = &vixen;
+ volatile unsigned short * vapour = &vitriol;
+ volatile long * ventricle = &vellum;
+ volatile unsigned long * vigintillion = &valve;
+ volatile float * vocation = &vacuity;
+ volatile double * veracity = &vertigo;
+
+ /* volatile pointers to volatile variables */
+
+ volatile char * volatile vapidity = &vox;
+ volatile unsigned char * volatile velocity = &victuals;
+ volatile short * volatile veneer = &vixen;
+ volatile unsigned short * volatile video = &vitriol;
+ volatile long * volatile vacuum = &vellum;
+ volatile unsigned long * volatile veniality = &valve;
+ volatile float * volatile vitality = &vacuity;
+ volatile double * volatile voracity = &vertigo;
+
+ /* const volatile vars */
+
+ const volatile char victor = 'Y';
+ const volatile unsigned char vicar = 11;
+
+ /* pointers to const volatiles */
+
+ const volatile char * victory = &victor;
+ const volatile unsigned char * vicarage = &vicar;
+
+ /* const pointers to volatile vars */
+
+ volatile char * const vein = &vox;
+ volatile unsigned char * const vogue = &victuals;
+
+ /* const pointers to const volatile vars */
+
+ const volatile char * const cavern = &victor;
+ const volatile unsigned char * const coverlet = &vicar;
+
+ /* volatile pointers to const vars */
+
+ const char * volatile caveat = &laconic;
+ const unsigned char * volatile covenant = &laggard;
+
+ /* volatile pointers to const volatile vars */
+
+ const volatile char * volatile vizier = &victor;
+ const volatile unsigned char * volatile vanadium = &vicar;
+
+ /* const volatile pointers */
+
+ char * const volatile vane = &lave;
+ unsigned char * const volatile veldt = &lavish;
+
+ /* const volatile pointers to const vars */
+
+ const char * const volatile cove = &laconic;
+ const unsigned char * const volatile cavity = &laggard;
+
+ /* const volatile pointers to volatile vars */
+
+ volatile char * const volatile vagus = &vox;
+ volatile unsigned char * const volatile vagrancy = &victuals;
+
+ /* const volatile pointers to const volatile */
+
+ const volatile char * const volatile vagary = &victor;
+ const volatile unsigned char * const volatile vendor = &vicar;
+
+ /* misc. references */
+ /*
+ const char & radiation = laconic;
+ volatile signed char & remuneration = lemonade;
+ */
+#ifdef usestubs
+ set_debug_traps ();
+ breakpoint ();
+#endif
+ marker1 ();
+
+
+ return 0;
+}
diff --git a/gdb/testsuite/gdb.base/constvars.exp b/gdb/testsuite/gdb.base/constvars.exp
new file mode 100644
index 00000000000..518e5ca9b0d
--- /dev/null
+++ b/gdb/testsuite/gdb.base/constvars.exp
@@ -0,0 +1,251 @@
+# Copyright (C) 1997, 1998 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# written by Elena Zannoni (elz@apollo.hp.com)
+#
+# This file is part of the gdb testsuite
+#
+# tests for const variables
+# const pointers to vars
+# pointers to const variables
+# const pointers to const vars
+# with mixed types
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+#
+# test running programs
+#
+set prms_id 0
+set bug_id 0
+
+set testfile "constvars"
+set srcfile ${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+# Create and source the file that provides information about the compiler
+# used to compile the test case.
+
+if [get_compiler_info ${binfile}] {
+ return -1;
+}
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+
+#
+# set it up at a breakpoint so we can play with the variable values
+#
+if ![runto_main] then {
+ perror "couldn't run to breakpoint"
+ continue
+}
+
+send_gdb "break marker1\n" ; gdb_expect -re ".*$gdb_prompt $"
+
+ send_gdb "cont\n"
+ gdb_expect {
+ -re "Break.* marker1 \\(\\) at .*:$decimal.*$gdb_prompt $" {
+ send_gdb "up\n"
+ gdb_expect {
+ -re ".*$gdb_prompt $" {}
+ timeout { fail "up from marker1" }
+ }
+ }
+ -re "Break.* marker1__.* \\(\\) at .*:$decimal.*$gdb_prompt $" {
+ fail "continue to marker1 (demangling)"
+ send_gdb "up\n"
+ gdb_expect {
+ -re ".*$gdb_prompt $" {}
+ timeout { fail "up from marker1" }
+ }
+ }
+ -re "$gdb_prompt $" { fail "continue to marker1" }
+ timeout { fail "(timeout) continue to marker1" }
+ }
+
+# test function parameters
+
+if {$gcc_compiled} then { setup_xfail "*-*-*" }
+send_gdb "ptype qux1\n"
+gdb_expect {
+ -re "type = int \\(const char, const char &, const char *, char * const\\).*$gdb_prompt $" {
+ pass "ptype qux1"
+ }
+ -re ".*$gdb_prompt $" { fail "ptype qux1" }
+ timeout { fail "(timeout) ptype qux1" }
+}
+
+# test vars and pointers
+
+proc do_constvar_tests {} {
+ global gcc_compiled
+
+ gdb_test "print lave" " = 66 'B'"
+ gdb_test "ptype lave" "type = char"
+ gdb_test "print lavish" " = 10 '\\\\n'"
+ gdb_test "ptype lavish" "type = unsigned char"
+ gdb_test "print lax" " = 20"
+ gdb_test "ptype lax" "type = short.*"
+ gdb_test "print lecherous" " = 30"
+ if {$gcc_compiled} then { setup_xfail "*-*-*" }
+ gdb_test "ptype lecherous" "type = unsigned short.*"
+ gdb_test "print lechery" " = 40"
+ gdb_test "ptype lechery" "type = long.*"
+ gdb_test "print lectern" " = 50"
+ if {$gcc_compiled} then { setup_xfail "*-*-*" }
+ gdb_test "ptype lectern" "type = unsigned long.*"
+ gdb_test "print leeway" " = 60"
+ gdb_test "ptype leeway" "type = float"
+ gdb_test "print legacy" " = 70"
+ gdb_test "ptype legacy" "type = double"
+ gdb_test "print laconic" " = 65 'A'"
+ if {$gcc_compiled} then { setup_xfail "*-*-*" }
+ gdb_test "ptype laconic" "type = const char"
+ gdb_test "print laggard" " = 1 '.001'"
+ if {$gcc_compiled} then { setup_xfail "*-*-*" }
+ gdb_test "ptype laggard" "type = const unsigned char"
+ gdb_test "print lagoon" " = 2"
+ if {$gcc_compiled} then { setup_xfail "*-*-*" }
+ gdb_test "ptype lagoon" "type = const short"
+ gdb_test "print laity" " = 3"
+ if {$gcc_compiled} then { setup_xfail "*-*-*" }
+ gdb_test "ptype laity" "type = const unsigned short"
+ gdb_test "print lambent" " = 4"
+ if {$gcc_compiled} then { setup_xfail "*-*-*" }
+ gdb_test "ptype lambent" "type = const long"
+ gdb_test "print laminated" " = 5"
+ if {$gcc_compiled} then { setup_xfail "*-*-*" }
+ gdb_test "ptype laminated" "type = const unsigned long"
+ gdb_test "print lampoon" " = 6"
+ if {$gcc_compiled} then { setup_xfail "*-*-*" }
+ gdb_test "ptype lampoon" "type = const float"
+ gdb_test "print languid" " = 7"
+ if {$gcc_compiled} then { setup_xfail "*-*-*" }
+ gdb_test "ptype languid" "type = const double"
+ gdb_test "print *legend" " = 66 'B'"
+ if {$gcc_compiled} then { setup_xfail "*-*-*" }
+ gdb_test "ptype legend" "type = const char *"
+ gdb_test "print *legerdemain" " = 10 '\\\\n'"
+ if {$gcc_compiled} then { setup_xfail "*-*-*" }
+ gdb_test "ptype legerdemain" "type = const unsigned char *"
+ gdb_test "print *leniency" " = 20"
+ if {$gcc_compiled} then { setup_xfail "*-*-*" }
+ gdb_test "ptype leniency" "type = const short *"
+ gdb_test "print *leonine" " = 30"
+ if {$gcc_compiled} then { setup_xfail "*-*-*" }
+ gdb_test "ptype leonine" "type = const unsigned short *"
+ gdb_test "print *lesion" " = 40"
+ if {$gcc_compiled} then { setup_xfail "*-*-*" }
+ gdb_test "ptype lesion" "type = const long *"
+ gdb_test "print *lethal" " = 50"
+ if {$gcc_compiled} then { setup_xfail "*-*-*" }
+ gdb_test "ptype lethal" "type = const unsigned long *"
+ gdb_test "print *lethargic" " = 60"
+ if {$gcc_compiled} then { setup_xfail "*-*-*" }
+ gdb_test "ptype lethargic" "type = const float *"
+ gdb_test "print *levity" " = 70"
+ if {$gcc_compiled} then { setup_xfail "*-*-*" }
+ gdb_test "ptype levity" "type = const double *"
+ gdb_test "print *lewd" " = 65 'A'"
+ if {$gcc_compiled} then { setup_xfail "*-*-*" }
+ gdb_test "ptype lewd" "type = const char * const"
+ gdb_test "print *lexicographer" " = 1 '.001'"
+ if {$gcc_compiled} then { setup_xfail "*-*-*" }
+ gdb_test "ptype lexicographer" "type = const unsigned char * const"
+ gdb_test "print *lexicon" " = 2"
+ if {$gcc_compiled} then { setup_xfail "*-*-*" }
+ gdb_test "ptype lexicon" "type = const short * const"
+ gdb_test "print *liaison" " = 3"
+ if {$gcc_compiled} then { setup_xfail "*-*-*" }
+ gdb_test "ptype liaison" "type = const unsigned short * const"
+ gdb_test "print *libation" " = 4"
+ if {$gcc_compiled} then { setup_xfail "*-*-*" }
+ gdb_test "ptype libation" "type = const long * const"
+ gdb_test "print *libelous" " = 5"
+ if {$gcc_compiled} then { setup_xfail "*-*-*" }
+ gdb_test "ptype libelous" "type = const unsigned long * const"
+ gdb_test "print *libertine" " = 6"
+ if {$gcc_compiled} then { setup_xfail "*-*-*" }
+ gdb_test "ptype libertine" "type = const float * const"
+ gdb_test "print *libidinous" " = 7"
+ if {$gcc_compiled} then { setup_xfail "*-*-*" }
+ gdb_test "ptype libidinous" "type = const double * const"
+ gdb_test "print *languish" " = 65 'A'"
+ if {$gcc_compiled} then { setup_xfail "*-*-*" }
+ gdb_test "ptype languish" "type = const char *"
+ gdb_test "print *languor" " = 1 '.001'"
+ if {$gcc_compiled} then { setup_xfail "*-*-*" }
+ gdb_test "ptype languor" "type = const unsigned char *"
+ gdb_test "print *lank" " = 2"
+ if {$gcc_compiled} then { setup_xfail "*-*-*" }
+ gdb_test "ptype lank" "type = const short *"
+ gdb_test "print *lapidary" " = 3"
+ if {$gcc_compiled} then { setup_xfail "*-*-*" }
+ gdb_test "ptype lapidary" "type = const unsigned short *"
+ gdb_test "print *larceny" " = 4"
+ if {$gcc_compiled} then { setup_xfail "*-*-*" }
+ gdb_test "ptype larceny" "type = const long *"
+ gdb_test "print *largess" " = 5"
+ if {$gcc_compiled} then { setup_xfail "*-*-*" }
+ gdb_test "ptype largess" "type = const unsigned long *"
+ gdb_test "print *lascivious" " = 6"
+ if {$gcc_compiled} then { setup_xfail "*-*-*" }
+ gdb_test "ptype lascivious" "type = const float *"
+ gdb_test "print *lassitude" " = 7"
+ if {$gcc_compiled} then { setup_xfail "*-*-*" }
+ gdb_test "ptype lassitude" "type = const double *"
+ gdb_test "print *lamprey" " = 66 'B'"
+ if {$gcc_compiled} then { setup_xfail "*-*-*" }
+ gdb_test "ptype lamprey" "type = char * const"
+ gdb_test "print *lariat" " = 10 '\\\\n'"
+ if {$gcc_compiled} then { setup_xfail "*-*-*" }
+ gdb_test "ptype lariat" "type = unsigned char * const"
+ gdb_test "print *laudanum" " = 20"
+ if {$gcc_compiled} then { setup_xfail "*-*-*" }
+ gdb_test "ptype laudanum" "type = short * const"
+ gdb_test "print *lecithin" " = 30"
+ if {$gcc_compiled} then { setup_xfail "*-*-*" }
+ gdb_test "ptype lecithin" "type = unsigned short * const"
+ gdb_test "print *leviathan" " = 40"
+ if {$gcc_compiled} then { setup_xfail "*-*-*" }
+ gdb_test "ptype leviathan" "type = long * const"
+ gdb_test "print *libretto" " = 50"
+ if {$gcc_compiled} then { setup_xfail "*-*-*" }
+ gdb_test "ptype libretto" "type = unsigned long * const"
+ gdb_test "print *lissome" " = 60"
+ if {$gcc_compiled} then { setup_xfail "*-*-*" }
+ gdb_test "ptype lissome" "type = float * const"
+ gdb_test "print *locust" " = 70"
+ if {$gcc_compiled} then { setup_xfail "*-*-*" }
+ gdb_test "ptype locust" "type = double * const"
+ if {$gcc_compiled} then { setup_xfail "*-*-*" }
+ gdb_test "ptype radiation" "type = const char &"
+}
+
+do_constvar_tests
diff --git a/gdb/testsuite/gdb.base/corefile.exp b/gdb/testsuite/gdb.base/corefile.exp
new file mode 100644
index 00000000000..83b78c4be99
--- /dev/null
+++ b/gdb/testsuite/gdb.base/corefile.exp
@@ -0,0 +1,223 @@
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file was written by Fred Fish. (fnf@cygnus.com)
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+set prms_id 0
+set bug_id 0
+
+# are we on a target board
+if ![isnative] then {
+ return
+}
+
+set testfile "coremaker"
+set srcfile ${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+# Create and source the file that provides information about the compiler
+# used to compile the test case.
+if [get_compiler_info ${binfile}] {
+ return -1;
+}
+
+# Create a core file named "corefile" rather than just "core", to
+# avoid problems with sys admin types that like to regularly prune all
+# files named "core" from the system.
+#
+# Arbitrarily try setting the core size limit to "unlimited" since
+# this does not hurt on systems where the command does not work and
+# allows us to generate a core on systems where it does.
+#
+# Some systems append "core" to the name of the program; others append
+# the name of the program to "core".
+set found 0
+catch "system \"(cd ${objdir}/${subdir}; ulimit -c unlimited; ${binfile}; true) >/dev/null 2>&1\""
+# remote_exec host "${binfile}"
+foreach i "${objdir}/${subdir}/core ${objdir}/${subdir}/core.coremaker.c ${binfile}.core" {
+ if [remote_file build exists $i] {
+ remote_exec build "mv $i ${objdir}/${subdir}/corefile"
+ set found 1
+ }
+}
+if { $found == 0 } {
+ # The braindamaged HPUX shell quits after the ulimit -c above
+ # without executing ${binfile}. So we try again without the
+ # ulimit here if we didn't find a core file above.
+ # Oh, I should mention that any "braindamaged" non-Unix system has
+ # the same problem. I like the cd bit too, it's really neat'n stuff.
+ catch "system \"(cd ${objdir}/${subdir}; ${binfile}; true) >/dev/null 2>&1\""
+ foreach i "${objdir}/${subdir}/core ${objdir}/${subdir}/core.coremaker.c ${binfile}.core" {
+ if [remote_file build exists $i] {
+ remote_exec build "mv $i ${objdir}/${subdir}/corefile"
+ set found 1
+ }
+ }
+
+ if { $found == 0 } {
+ warning "can't generate a core file - core tests suppressed - check ulimit -c"
+ return 0
+ }
+}
+
+#
+# Test that we can simply startup with a "-core=corefile" command line arg
+# and recognize that the core file is a valid, usable core file.
+# To do this, we must shutdown the currently running gdb and restart
+# with the -core args. We can't use gdb_start because it looks for
+# the first gdb prompt, and the message we are looking for occurs
+# before the first prompt. Also, we can't include GDBFLAGS because
+# if it is empty, this confuses gdb with an empty argument that it
+# grumbles about (said grumbling currently being ignored in gdb_start).
+# **FIXME**
+#
+# Another problem is that on some systems (solaris for example), there
+# is apparently a limit on the length of a fully specified path to
+# the coremaker executable, at about 80 chars. For this case, consider
+# it a pass, but note that the program name is bad.
+
+gdb_exit
+if $verbose>1 then {
+ send_user "Spawning $GDB -nw $GDBFLAGS -core=$objdir/$subdir/corefile\n"
+}
+
+set oldtimeout $timeout
+set timeout [expr "$timeout + 60"]
+verbose "Timeout is now $timeout seconds" 2
+eval "spawn $GDB -nw $GDBFLAGS -core=$objdir/$subdir/corefile"
+expect {
+ -re "Core was generated by .*coremaker.*\r\n\#0 .*\(\).*\r\n$gdb_prompt $" {
+ pass "args: -core=corefile"
+ }
+ -re "Core was generated by .*\r\n\#0 .*\(\).*\r\n$gdb_prompt $" {
+ pass "args: -core=corefile (with bad program name)"
+ }
+ -re ".*registers from core file: File in wrong format.* $" {
+ fail "args: -core=corefile (could not read registers from core file)"
+ }
+ -re ".*$gdb_prompt $" { fail "args: -core=corefile" }
+ timeout { fail "(timeout) starting with -core" }
+}
+
+
+#
+# Test that startup with both an executable file and -core argument.
+# See previous comments above, they are still applicable.
+#
+
+close;
+
+if $verbose>1 then {
+ send_user "Spawning $GDB -nw $GDBFLAGS $binfile -core=$objdir/$subdir/corefile\n"
+}
+
+
+eval "spawn $GDB -nw $GDBFLAGS $binfile -core=$objdir/$subdir/corefile";
+expect {
+ -re "Core was generated by .*coremaker.*\r\n\#0 .*\(\).*\r\n$gdb_prompt $" {
+ pass "args: execfile -core=corefile"
+ }
+ -re "Core was generated by .*\r\n\#0 .*\(\).*\r\n$gdb_prompt $" {
+ pass "args: execfile -core=corefile (with bad program name)"
+ }
+ -re ".*registers from core file: File in wrong format.* $" {
+ fail "args: execfile -core=corefile (could not read registers from core file)"
+ }
+ -re ".*$gdb_prompt $" { fail "args: execfile -core=corefile" }
+ timeout { fail "(timeout) starting with -core" }
+}
+set timeout $oldtimeout
+verbose "Timeout is now $timeout seconds" 2
+
+close;
+
+# Now restart normally.
+
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+# Test basic corefile recognition via core-file command.
+
+send_gdb "core-file $objdir/$subdir/corefile\n"
+gdb_expect {
+ -re "Core was generated by .*coremaker.*\r\n\#0 .*\(\).*\r\n$gdb_prompt $" {
+ pass "core-file command"
+ }
+ -re "Core was generated by .*\r\n\#0 .*\(\).*\r\n$gdb_prompt $" {
+ pass "core-file command (with bad program name)"
+ }
+ -re ".*registers from core file: File in wrong format.* $" {
+ fail "core-file command (could not read registers from core file)"
+ }
+ -re ".*$gdb_prompt $" { fail "core-file command" }
+ timeout { fail "(timeout) core-file command" }
+}
+
+# Test correct mapping of corefile sections by printing some variables.
+
+gdb_test "print coremaker_data" "\\\$$decimal = 202"
+gdb_test "print coremaker_bss" "\\\$$decimal = 10"
+gdb_test "print coremaker_ro" "\\\$$decimal = 201"
+
+if {!$gcc_compiled} then { setup_xfail "hppa*-*-hpux*" }
+gdb_test "print func2::coremaker_local" "\\\$$decimal = {0, 1, 2, 3, 4}"
+
+# Somehow we better test the ability to read the registers out of the core
+# file correctly. I don't think the other tests do this.
+
+gdb_test "bt" "abort.*func2.*func1.*main.*" "backtrace in corefile.exp"
+
+# Test ability to read mmap'd data
+
+gdb_test "x/8bd buf1" ".*:.*0.*1.*2.*3.*4.*5.*6.*7" "accessing original mmap data in core file"
+setup_xfail "*-*-sunos*" "*-*-ultrix*" "*-*-aix*"
+send_gdb "x/8bd buf2\n"
+gdb_expect {
+ -re ".*:.*0.*1.*2.*3.*4.*5.*6.*7.*$gdb_prompt $" {
+ pass "accessing mmapped data in core file"
+ }
+ -re "0x\[f\]*:.*Cannot access memory at address 0x\[f\]*.*$gdb_prompt $" {
+ fail "accessing mmapped data (mapping failed at runtime)"
+ }
+ -re "0x.*:.*Cannot access memory at address 0x.*$gdb_prompt $" {
+ fail "accessing mmapped data (mapping address not found in core file)"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "accessing mmapped data (incorrect data found in core file)"
+ }
+ timeout {
+ fail "accessing mmapped data (timeout)"
+ }
+}
+
+# test reinit_frame_cache
+
+gdb_load ${binfile}
+setup_xfail "*-*-*"
+gdb_test "up" "#\[0-9\]* *\[0-9xa-fH'\]* in .* \\(\\)" "up in corefile.exp"
+
+gdb_test "core" "No core file now."
diff --git a/gdb/testsuite/gdb.base/coremaker.c b/gdb/testsuite/gdb.base/coremaker.c
new file mode 100644
index 00000000000..56239e9286f
--- /dev/null
+++ b/gdb/testsuite/gdb.base/coremaker.c
@@ -0,0 +1,120 @@
+/* Simple little program that just generates a core dump from inside some
+ nested function calls. */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <signal.h>
+
+#ifndef __STDC__
+#define const /**/
+#endif
+
+#define MAPSIZE (8 * 1024)
+
+/* Don't make these automatic vars or we will have to walk back up the
+ stack to access them. */
+
+char *buf1;
+char *buf2;
+
+int coremaker_data = 1; /* In Data section */
+int coremaker_bss; /* In BSS section */
+
+const int coremaker_ro = 201; /* In Read-Only Data section */
+
+/* Note that if the mapping fails for any reason, we set buf2
+ to -1 and the testsuite notices this and reports it as
+ a failure due to a mapping error. This way we don't have
+ to test for specific errors when running the core maker. */
+
+void
+mmapdata ()
+{
+ int j, fd;
+ extern void *malloc ();
+
+ /* Allocate and initialize a buffer that will be used to write
+ the file that is later mapped in. */
+
+ buf1 = (char *) malloc (MAPSIZE);
+ for (j = 0; j < MAPSIZE; ++j)
+ {
+ buf1[j] = j;
+ }
+
+ /* Write the file to map in */
+
+ fd = open ("coremmap.data", O_CREAT | O_RDWR, 0666);
+ if (fd == -1)
+ {
+ perror ("coremmap.data open failed");
+ buf2 = (char *) -1;
+ return;
+ }
+ write (fd, buf1, MAPSIZE);
+
+ /* Now map the file into our address space as buf2 */
+
+ buf2 = (char *) mmap (0, MAPSIZE, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
+ if (buf2 == (char *) -1)
+ {
+ perror ("mmap failed");
+ return;
+ }
+
+ /* Verify that the original data and the mapped data are identical.
+ If not, we'd rather fail now than when trying to access the mapped
+ data from the core file. */
+
+ for (j = 0; j < MAPSIZE; ++j)
+ {
+ if (buf1[j] != buf2[j])
+ {
+ fprintf (stderr, "mapped data is incorrect");
+ buf2 = (char *) -1;
+ return;
+ }
+ }
+}
+
+void
+func2 ()
+{
+ int coremaker_local[5];
+ int i;
+
+#ifdef SA_FULLDUMP
+ /* Force a corefile that includes the data section for AIX. */
+ {
+ struct sigaction sa;
+
+ sigaction (SIGABRT, (struct sigaction *)0, &sa);
+ sa.sa_flags |= SA_FULLDUMP;
+ sigaction (SIGABRT, &sa, (struct sigaction *)0);
+ }
+#endif
+
+ /* Make sure that coremaker_local doesn't get optimized away. */
+ for (i = 0; i < 5; i++)
+ coremaker_local[i] = i;
+ coremaker_bss = 0;
+ for (i = 0; i < 5; i++)
+ coremaker_bss += coremaker_local[i];
+ coremaker_data = coremaker_ro + 1;
+ abort ();
+}
+
+void
+func1 ()
+{
+ func2 ();
+}
+
+main ()
+{
+ mmapdata ();
+ func1 ();
+}
+
diff --git a/gdb/testsuite/gdb.base/crossload.exp b/gdb/testsuite/gdb.base/crossload.exp
new file mode 100644
index 00000000000..26bb7a1b0b2
--- /dev/null
+++ b/gdb/testsuite/gdb.base/crossload.exp
@@ -0,0 +1,380 @@
+# Copyright (C) 1992, 1997 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file was written by Fred Fish. (fnf@cygnus.com)
+# Rob Savoye changed it to use gdb_test (rob@cygnus.com)
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+set prms_id 0
+set bug_id 0
+
+# FIXME: The configure.in for this test should look for --with-targets
+# and deal accordingly. Until that has been done, skip the whole thing.
+# With a minimal bfd (the default), few if any of these tests work.
+
+verbose "FIXME: all the crossload tests ignored"
+return
+
+foreach i "m68k-elf m68k-aout m68k-aout2 mips-ecoff i486-elf sparc-aout i860-elf sparc-elf" {
+ remote_exec build "cd ${objdir}/${subdir} ; uudecode ${srcdir}/${subdir}/$i.u "
+}
+
+# FIXME: These tests don't work for the i960, because
+# bfd/config/i960-bout.mt sets SELECT_VECS. I could use setup_xfail
+# for each test, but rebooting the board between each one takes a long
+# time so I'm just punting the whole file.
+if [istarget "i960-*-*"] then {
+ if $verbose>1 then {
+ warning "FIXME: crossload test case doesn't run on the i960."
+ }
+ continue
+}
+
+# FIXME: These tests don't work for the a29k, because SELECT_VECS is
+# used when compiling bfd. It would be nice if there were some better
+# way of detecting this case.
+if [istarget "a29k-*-*"] then {
+ if $verbose>1 then {
+ warning "FIXME: crossload test case doesn't run on the a29k."
+ }
+ continue
+}
+
+# Test if gdb can automatically determine the bfd format of an
+# executable and read it's symbols.
+
+proc bfddefault {} {
+ global GDB
+ global GDBFLAGS
+ global gdb_prompt
+ global objdir
+ global subdir
+ global binfile
+ global bfdformat
+ global file_loaded
+
+ gdb_unload
+ set file_loaded 0
+ send_gdb "file $objdir/$subdir/$binfile\n"
+ gdb_expect {
+ -re "A program is being debugged already. Kill it.*y or n." {
+ send_gdb "y\n"
+ exp_continue
+ }
+ -re "Reading symbols from $objdir/$subdir/$binfile\[.\]+done\..*$gdb_prompt $" {
+ pass "$binfile ($bfdformat) auto format"
+ }
+ -re "Reading symbols from $objdir/$subdir/$binfile\[.\]+.no debugging symbols found.\[.\]+done\..*$gdb_prompt $" {
+ pass "$binfile ($bfdformat) auto format (but no symbols found)"
+ }
+ -re "File format not recognized.*$gdb_prompt $" {
+ fail "$binfile ($bfdformat) auto format (format not recognized)"
+ return
+ }
+ -re "File format is ambiguous.*$gdb_prompt $" {
+ fail "$binfile ($bfdformat) auto format (format is ambiguous)"
+ return
+ }
+ -re "$gdb_prompt $" {
+ fail "$binfile ($bfdformat) auto format"
+ return
+ }
+ timeout {
+ fail "(timeout) $binfile ($bfdformat) auto format"
+ return
+ }
+ }
+
+ if [gdb_test "info target" ".*file type $bfdformat" ""]==0 then {
+ set file_loaded 1
+ } else {
+ fail "$binfile ($bfdformat) wrong format found"
+ }
+}
+
+# Test if gdb can read symbols from an executable when the bfd format
+# is explicitly set via the environment variable GNUTARGET.
+
+proc bfdexplicit {} {
+ global GDB
+ global GDBFLAGS
+ global gdb_prompt
+ global subdir
+ global objdir
+ global det_file
+ global binfile
+ global bfdformat
+ global file_loaded
+
+ gdb_unload
+ set file_loaded 0
+
+ # Once GDB 4.10 (the last to lack `set gnutarget') is forgotten,
+ # change this to use set gnutarget.
+ if [gdb_test "set env GNUTARGET=$bfdformat" "" ""]!=0 then {
+ fail "setting GNUTARGET=$bfdformat in environment"
+ return
+ }
+
+ send_gdb "file $objdir/$subdir/$binfile\n"
+ gdb_expect {
+ -re "A program is being debugged already. Kill it.*y or n." {
+ send_gdb "y\n"
+ exp_continue
+ }
+ -re "Reading symbols from $objdir/$subdir/$binfile\[.\]+done\..*$gdb_prompt $" {
+ pass "$binfile ($bfdformat) explicit format"
+ }
+ -re "Invalid target.*$gdb_prompt $" {
+ fail "$binfile ($bfdformat) explicit format (invalid target)"
+ return
+ }
+ -re "$gdb_prompt $" {
+ fail "$binfile ($bfdformat) explicit format"
+ return
+ }
+ timeout {
+ fail "(timeout) $binfile ($bfdformat) explicit format"
+ return
+ }
+ }
+
+ set file_loaded 1
+}
+
+proc test_ptype_functions {} {
+ global gdb_prompt
+ global binfile
+ global bfdformat
+ global det_file
+ send_gdb "ptype main\n"
+ gdb_expect {
+ -re "type = int \[)(\]+\r\n$gdb_prompt $" {}
+ timeout { fail "(timeout) $binfile ($bfdformat) function main" ; return }
+ }
+
+ # set up a list of lists of command and patterns
+ set command [list { "ptype v_char_func" "type =(\ unsigned\ |\ signed\ |\ )char \[)(\]+" }\
+ { "ptype v_short_func" "type = (short|short int) \[)(\]+" } \
+ { "ptype v_int_func" "type = int \[)(\]+" } \
+ { "ptype v_long_func" "type = (long|long int|int) \[)(\]+" } \
+ { "ptype v_float_func" "type = float \[)(\]+" } \
+ { "ptype v_double_func" "type = double \[)(\]+" } ]
+
+ foreach i $command {
+ if [gdb_test [lindex $i 0] [lindex $i 1] ""] then {
+ fail "$binfile ($bfdformat) \"[lindex $i 0]\" function types"
+ return
+ }
+ }
+ pass "$binfile ($bfdformat) ptype function types"
+}
+
+# Note that plain chars can be either signed or unsigned.
+
+proc test_ptype_plain_types {} {
+ global gdb_prompt
+ global binfile
+ global bfdformat
+
+ # set up a list of lists of command and patterns
+ set command [list { "ptype v_char" "type =(\ unsigned\ |\ signed\ |\ )char" }\
+ { "ptype v_short" "type = short" } \
+ { "ptype v_int" "type = int" } \
+ { "ptype v_long" "type = long" } \
+ { "ptype v_float" "type = float" } \
+ { "ptype v_double" "type = double" } ]
+
+ foreach i $command {
+ if [gdb_test [lindex $i 0] [lindex $i 1] ""] then {
+ fail "$binfile ($bfdformat) \"[lindex $i 0]\" plain C types"
+ return
+ }
+ }
+ pass "$binfile ($bfdformat) ptype plain C types"
+}
+
+# Note that if compiled with pre-ANSI compilers, the "signed" keywords are
+# defined away and the variables default to plain types. So accept either.
+
+proc test_ptype_signed_types {} {
+ global gdb_prompt
+ global binfile
+ global bfdformat
+ global det_file
+
+ # set up a list of lists of command and patterns
+ set command [list { "ptype v_signed_char" "type =(\ signed\ |\ )char" }\
+ { "ptype v_signed_short" "type =(\ signed\ |\ )short" } \
+ { "ptype v_signed_int" "type =(\ signed\ |\ )int" } \
+ { "ptype v_signed_long" "type =(\ signed\ |\ )long" } ]
+
+ foreach i $command {
+ if [gdb_test [lindex $i 0] [lindex $i 1] ""] then {
+ if [expr [string match "ecoff-bigmips" $bfdformat]+[string match "ptype v_signed_char" [lindex $i 0]]]==2 then {
+ setup_xfail "*-*-*"
+ }
+ fail "$binfile ($bfdformat) \"[lindex $i 0]\" signed C types"
+ return
+ }
+ }
+ pass "$binfile ($bfdformat) ptype signed C types"
+}
+
+proc test_ptype_unsigned_types {} {
+ global gdb_prompt
+ global binfile
+ global bfdformat
+ global det_file
+
+ # set up a list of lists of command and patterns
+ set command [list { "ptype v_unsigned_char" "type = unsigned char" }\
+ { "ptype v_unsigned_short" \
+ "type = (unsigned short|short unsigned int)" } \
+ { "ptype v_unsigned_int" "type = unsigned int" } \
+ { "ptype v_unsigned_long" \
+ "type = (unsigned long|long unsigned int)" } ]
+
+ foreach i $command {
+ if [gdb_test [lindex $i 0] [lindex $i 1] ""] then {
+ fail "$binfile ($bfdformat) \"[lindex $i 0]\" unsigned C types"
+ return
+ }
+ }
+ pass "$binfile ($bfdformat) ptype unsigned C types"
+}
+
+# Note that plain chars can be either signed or unsigned.
+
+proc test_ptype_array_types {} {
+ global gdb_prompt
+ global binfile
+ global bfdformat
+ global det_file
+
+ # set up a list of lists of command and patterns
+ set command [list { "ptype v_char_array" "type =(\ unsigned\ |\ signed\ |\ )char \\\[2\\\]" }\
+ { "ptype v_short_array" \
+ "type = (short|short int) \\\[2\\\]" } \
+ { "ptype v_int_array" "type = int \\\[2\\\]" } \
+ { "ptype v_long_array" "type = (long|long int) \\\[2\\\]" } \
+ { "ptype v_float_array" "type = float \\\[2\\\]" } \
+ { "ptype v_double_array" "type = double \\\[2\\\]" } ]
+
+ foreach i $command {
+ if [gdb_test [lindex $i 0] [lindex $i 1] ""] then {
+ fail "$binfile ($bfdformat) \"[lindex $i 0]\" C array types"
+ return
+ }
+ }
+ pass "$binfile ($bfdformat) ptype C array types"
+}
+
+proc test_ptype_pointer_types {} {
+ global gdb_prompt
+ global binfile
+ global bfdformat
+ global det_file
+
+ # set up a list of lists of command and patterns
+ set command [list { "ptype v_char_pointer" "type =(\ unsigned\ |\ signed\ |\ )char \*" }\
+ { "ptype v_short_pointer" "type = (short|short int) \*" } \
+ { "ptype v_int_pointer" "type = int \*" } \
+ { "ptype v_long_pointer" "type = (long|long int) \*" } \
+ { "ptype v_float_pointer" "type = float \*" } \
+ { "ptype v_double_pointer" "type = double \*" } ]
+
+ foreach i $command {
+ if [gdb_test [lindex $i 0] [lindex $i 1] ""] then {
+ fail "$binfile ($bfdformat) \"[lindex $i 0]\" C pointer types"
+ return
+ }
+ }
+ pass "$binfile ($bfdformat) ptype C pointer types"
+}
+
+proc loadandtest { args } {
+ global verbose
+ global GDB
+ global GDBFLAGS
+ global gdb_prompt
+ global subdir
+ global objdir
+ global binfile
+ global bfdformat
+ global file_loaded
+
+ set binfile [ lindex $args 0 ]
+ set bfdformat [ lindex $args 1 ]
+ set fixme [ lindex $args 2 ]
+
+ if ![file exists $objdir/$subdir/$binfile] then {
+ perror "$objdir/$subdir/$binfile does not exist"
+ return 0
+ }
+ gdb_exit
+ gdb_start
+ if $fixme then { setup_xfail "*-*-*" }
+ bfddefault
+ if $fixme then { setup_xfail "*-*-*" }
+ if [string match $bfdformat "elf-big"] then {
+ if [string match $binfile "i860-elf"] then {
+ setup_xfail "*-*-*"
+ }
+ }
+ bfdexplicit
+ if $file_loaded==1 then {
+ test_ptype_functions
+ if $fixme then { setup_xfail "*-*-*" }
+ test_ptype_plain_types
+ if $fixme then { setup_xfail "*-*-*" }
+ test_ptype_signed_types
+ if $fixme then { setup_xfail "*-*-*" }
+ test_ptype_unsigned_types
+ if $fixme then { setup_xfail "*-*-*" }
+ test_ptype_array_types
+ if $fixme then { setup_xfail "*-*-*" }
+ test_ptype_pointer_types
+ }
+}
+
+# Run tests for each of the test executables.
+# If the third argument is 1, the tests will be expected to fail.
+# We should extract the information about available tests and bfd formats
+# from the makefile or some other control file (FIXME).
+
+loadandtest m68k-elf "elf32-m68k" 0
+
+# I'm getting an XPASS for explicit format on this one
+loadandtest m68k-aout "a.out-newsos3" 1
+
+loadandtest m68k-aout2 "a.out-sunos-big" 0
+loadandtest mips-ecoff "ecoff-bigmips" 0
+loadandtest i486-elf "elf32-i386" 0
+loadandtest sparc-aout "a.out-sunos-big" 0
+loadandtest sparc-elf "elf32-sparc" 0
+
+#FIXME: i860 support is unlikely to be working in the near future
+# so suppress this test until it is working. -fnf
+#loadandtest i860-elf "elf32-i860" 0
+
+gdb_test "set gnutarget auto" ""
diff --git a/gdb/testsuite/gdb.base/d10v.ld b/gdb/testsuite/gdb.base/d10v.ld
new file mode 100644
index 00000000000..3c4c38a3c9c
--- /dev/null
+++ b/gdb/testsuite/gdb.base/d10v.ld
@@ -0,0 +1,155 @@
+OUTPUT_FORMAT("elf32-d10v", "elf32-d10v",
+ "elf32-d10v")
+OUTPUT_ARCH(d10v)
+ENTRY(_start)
+ SEARCH_DIR(/usr/cygnus/d10v-961230/H-sparc-sun-sunos4.1//lib);
+/* Do we need any of these for elf?
+ __DYNAMIC = 0; */
+SECTIONS
+{
+ /* Overlay sections: */
+ .ovly0 0x01010000 : AT (0x12010000) { foo.o(.text) }
+ .ovly1 0x01010000 : AT (0x12011000) { bar.o(.text) }
+ .ovly2 0x01011000 : AT (0x12012000) { baz.o(.text) }
+ .ovly3 0x01011000 : AT (0x12013000) { grbx.o(.text) }
+ .data00 0x00001000 : AT (0x12014000) { foo.o(.data) }
+ .data01 0x00001000 : AT (0x12015000) { bar.o(.data) }
+ .data02 0x00002000 : AT (0x12016000) { baz.o(.data) }
+ .data03 0x00002000 : AT (0x12017000) { grbx.o(.data) }
+ /* Read-only sections, merged into data segment: */
+ . = 0x00000004;
+ .interp : { *(.interp) }
+ .hash : { *(.hash) }
+ .dynsym : { *(.dynsym) }
+ .dynstr : { *(.dynstr) }
+ .rel.text : { *(.rel.text) }
+ .rela.text : { *(.rela.text) }
+ .rel.data : { *(.rel.data) }
+ .rela.data : { *(.rela.data) }
+ .rel.rodata : { *(.rel.rodata) }
+ .rela.rodata : { *(.rela.rodata) }
+ .rel.got : { *(.rel.got) }
+ .rela.got : { *(.rela.got) }
+ .rel.ctors : { *(.rel.ctors) }
+ .rela.ctors : { *(.rela.ctors) }
+ .rel.dtors : { *(.rel.dtors) }
+ .rela.dtors : { *(.rela.dtors) }
+ .rel.init : { *(.rel.init) }
+ .rela.init : { *(.rela.init) }
+ .rel.fini : { *(.rel.fini) }
+ .rela.fini : { *(.rela.fini) }
+ .rel.bss : { *(.rel.bss) }
+ .rela.bss : { *(.rela.bss) }
+ .rel.plt : { *(.rel.plt) }
+ .rela.plt : { *(.rela.plt) }
+ .plt : { *(.plt) }
+ .rodata : { *(.rodata) *(.gnu.linkonce.r*) }
+ .rodata1 : { *(.rodata1) }
+ /* Adjust the address for the data segment. */
+ . = ALIGN(4);
+ .data :
+ {
+ *(.data)
+ *(.gnu.linkonce.d*)
+ _ovly_table = .;
+ LONG(ABSOLUTE(ADDR(.ovly0)));
+ LONG(SIZEOF(.ovly0));
+ LONG(LOADADDR(.ovly0));
+ LONG(0);
+ LONG(ABSOLUTE(ADDR(.ovly1)));
+ LONG(SIZEOF(.ovly1));
+ LONG(LOADADDR(.ovly1));
+ LONG(0);
+ LONG(ABSOLUTE(ADDR(.ovly2)));
+ LONG(SIZEOF(.ovly2));
+ LONG(LOADADDR(.ovly2));
+ LONG(0);
+ LONG(ABSOLUTE(ADDR(.ovly3)));
+ LONG(SIZEOF(.ovly3));
+ LONG(LOADADDR(.ovly3));
+ LONG(0);
+ LONG(ABSOLUTE(ADDR(.data00)));
+ LONG(SIZEOF(.data00));
+ LONG(LOADADDR(.data00));
+ LONG(0);
+ LONG(ABSOLUTE(ADDR(.data01)));
+ LONG(SIZEOF(.data01));
+ LONG(LOADADDR(.data01));
+ LONG(0);
+ LONG(ABSOLUTE(ADDR(.data02)));
+ LONG(SIZEOF(.data02));
+ LONG(LOADADDR(.data02));
+ LONG(0);
+ LONG(ABSOLUTE(ADDR(.data03)));
+ LONG(SIZEOF(.data03));
+ LONG(LOADADDR(.data03));
+ LONG(0);
+ _novlys = .;
+ LONG((_novlys - _ovly_table) / 16);
+ CONSTRUCTORS
+ }
+ .data1 : { *(.data1) }
+ .ctors :
+ {
+ *(.ctors)
+ }
+ .dtors :
+ {
+ *(.dtors)
+ }
+ .got : { *(.got.plt) *(.got) }
+ .dynamic : { *(.dynamic) }
+ /* We want the small data sections together, so single-instruction offsets
+ can access them all, and initialized data all before uninitialized, so
+ we can shorten the on-disk segment size. */
+ .sdata : { *(.sdata) }
+ _edata = .;
+ PROVIDE (edata = .);
+ __bss_start = .;
+ .sbss : { *(.sbss) *(.scommon) }
+ .bss :
+ {
+ *(.dynbss)
+ *(.bss)
+ *(COMMON)
+ }
+ _end = . ;
+ PROVIDE (end = .);
+ /* Stabs debugging sections. */
+ .stab 0 : { *(.stab) }
+ .stabstr 0 : { *(.stabstr) }
+ .stab.excl 0 : { *(.stab.excl) }
+ .stab.exclstr 0 : { *(.stab.exclstr) }
+ .stab.index 0 : { *(.stab.index) }
+ .stab.indexstr 0 : { *(.stab.indexstr) }
+ .comment 0 : { *(.comment) }
+ /* DWARF debug sections.
+ Symbols in the .debug DWARF section are relative to the beginning of the
+ section so we begin .debug at 0. It's not clear yet what needs to happen
+ for the others. */
+ .debug 0 : { *(.debug) }
+ .debug_info 0 : { *(.debug_info) }
+ .debug_abbrev 0 : { *(.debug_abbrev) }
+ .debug_line 0 : { *(.debug_line) }
+ .debug_frame 0 : { *(.debug_frame) }
+ .debug_srcinfo 0 : { *(.debug_srcinfo) }
+ .debug_aranges 0 : { *(.debug_aranges) }
+ .debug_pubnames 0 : { *(.debug_pubnames) }
+ .debug_sfnames 0 : { *(.debug_sfnames) }
+ .line 0 : { *(.line) }
+ /* These must appear regardless of . */
+ /* Hmmm, there's got to be a better way. This sets the stack to the
+ top of the simulator memory (i.e. top of 64K data space). */
+ .stack 0x00007FFE : { _stack = .; *(.stack) }
+ .text 0x1000000 :
+ {
+ *(.init)
+ *(.fini)
+ *(.text)
+ /* .gnu.warning sections are handled specially by elf32.em. */
+ *(.gnu.warning)
+ *(.gnu.linkonce.t*)
+ } =0
+ _etext = .;
+ PROVIDE (etext = .);
+}
diff --git a/gdb/testsuite/gdb.base/d10vovly.c b/gdb/testsuite/gdb.base/d10vovly.c
new file mode 100644
index 00000000000..bdb90feae6b
--- /dev/null
+++ b/gdb/testsuite/gdb.base/d10vovly.c
@@ -0,0 +1,225 @@
+
+/*
+ * Ovlymgr.c -- Runtime Overlay Manager for the GDB testsuite.
+ */
+
+#include "ovlymgr.h"
+
+/* Local functions and data: */
+
+extern unsigned long _ovly_table[][4];
+extern unsigned long _novlys __attribute__ ((section (".data")));
+enum ovly_index { VMA, SIZE, LMA, MAPPED};
+
+static void ovly_copy (unsigned long dst, unsigned long src, long size);
+
+/* Flush the data and instruction caches at address START for SIZE bytes.
+ Support for each new port must be added here. */
+/* FIXME: Might be better to have a standard libgloss function that
+ ports provide that we can then use. Use libgloss instead of newlib
+ since libgloss is the one intended to handle low level system issues.
+ I would suggest something like _flush_cache to avoid the user's namespace
+ but not be completely obscure as other things may need this facility. */
+
+static void
+FlushCache (void)
+{
+#ifdef __M32R__
+ volatile char *mspr = (char *) 0xfffffff7;
+ *mspr = 1;
+#endif
+}
+
+/* OverlayLoad:
+ * Copy the overlay into its runtime region,
+ * and mark the overlay as "mapped".
+ */
+
+bool
+OverlayLoad (unsigned long ovlyno)
+{
+ unsigned long i;
+
+ if (ovlyno < 0 || ovlyno >= _novlys)
+ exit (-1); /* fail, bad ovly number */
+
+ if (_ovly_table[ovlyno][MAPPED])
+ return TRUE; /* this overlay already mapped -- nothing to do! */
+
+ for (i = 0; i < _novlys; i++)
+ if (i == ovlyno)
+ _ovly_table[i][MAPPED] = 1; /* this one now mapped */
+ else if (_ovly_table[i][VMA] == _ovly_table[ovlyno][VMA])
+ _ovly_table[i][MAPPED] = 0; /* this one now un-mapped */
+
+ ovly_copy (_ovly_table[ovlyno][VMA],
+ _ovly_table[ovlyno][LMA],
+ _ovly_table[ovlyno][SIZE]);
+
+ FlushCache ();
+
+ return TRUE;
+}
+
+/* OverlayUnload:
+ * Copy the overlay back into its "load" region.
+ * Does NOT mark overlay as "unmapped", therefore may be called
+ * more than once for the same mapped overlay.
+ */
+
+bool
+OverlayUnload (unsigned long ovlyno)
+{
+ if (ovlyno < 0 || ovlyno >= _novlys)
+ exit (-1); /* fail, bad ovly number */
+
+ if (!_ovly_table[ovlyno][MAPPED])
+ exit (-1); /* error, can't copy out a segment that's not "in" */
+
+ ovly_copy (_ovly_table[ovlyno][LMA],
+ _ovly_table[ovlyno][VMA],
+ _ovly_table[ovlyno][SIZE]);
+
+ return TRUE;
+}
+
+#ifdef __D10V__
+#define IMAP0 (*(short *)(0xff00))
+#define IMAP1 (*(short *)(0xff02))
+#define DMAP (*(short *)(0xff04))
+
+static void
+D10VTranslate (unsigned long logical,
+ short *dmap,
+ unsigned long **addr)
+{
+ unsigned long physical;
+ unsigned long seg;
+ unsigned long off;
+
+ /* to access data, we use the following mapping
+ 0x00xxxxxx: Logical data address segment (DMAP translated memory)
+ 0x01xxxxxx: Logical instruction address segment (IMAP translated memory)
+ 0x10xxxxxx: Physical data memory segment (On-chip data memory)
+ 0x11xxxxxx: Physical instruction memory segment (On-chip insn memory)
+ 0x12xxxxxx: Phisical unified memory segment (Unified memory)
+ */
+
+ /* Addresses must be correctly aligned */
+ if (logical & (sizeof (**addr) - 1))
+ exit (-1);
+
+ /* If the address is in one of the two logical address spaces, it is
+ first translated into a physical address */
+ seg = (logical >> 24);
+ off = (logical & 0xffffffL);
+ switch (seg)
+ {
+ case 0x00: /* in logical data address segment */
+ if (off <= 0x7fffL)
+ physical = (0x10L << 24) + off;
+ else
+ /* Logical address out side of on-chip segment, not
+ supported */
+ exit (-1);
+ break;
+ case 0x01: /* in logical instruction address segment */
+ {
+ short map;
+ if (off <= 0x1ffffL)
+ map = IMAP0;
+ else if (off <= 0x3ffffL)
+ map = IMAP1;
+ else
+ /* Logical address outside of IMAP[01] segment, not
+ supported */
+ exit (-1);
+ if (map & 0x1000L)
+ {
+ /* Instruction memory */
+ physical = (0x11L << 24) | off;
+ }
+ else
+ {
+ /* Unified memory */
+ physical = ((map & 0x7fL) << 17) + (off & 0x1ffffL);
+ if (physical > 0xffffffL)
+ /* Address outside of unified address segment */
+ exit (-1);
+ physical |= (0x12L << 24);
+ }
+ break;
+ }
+ case 0x10:
+ case 0x11:
+ case 0x12:
+ physical = logical;
+ break;
+ default:
+ exit (-1); /* error */
+ }
+
+ seg = (physical >> 24);
+ off = (physical & 0xffffffL);
+ switch (seg)
+ {
+ case 0x10: /* dst is a 15 bit offset into the on-chip memory */
+ *dmap = 0;
+ *addr = (long *) (0x0000 + ((short)off & 0x7fff));
+ break;
+ case 0x11: /* dst is an 18-bit offset into the on-chip
+ instruction memory */
+ *dmap = 0x1000L | ((off & 0x3ffffL) >> 14);
+ *addr = (long *) (0x8000 + ((short)off & 0x3fff));
+ break;
+ case 0x12: /* dst is a 24-bit offset into unified memory */
+ *dmap = off >> 14;
+ *addr = (long *) (0x8000 + ((short)off & 0x3fff));
+ break;
+ default:
+ exit (-1); /* error */
+ }
+}
+#endif /* __D10V__ */
+
+static void
+ovly_copy (unsigned long dst, unsigned long src, long size)
+{
+#ifdef __M32R__
+ memcpy ((void *) dst, (void *) src, size);
+ return;
+#endif /* M32R */
+
+#ifdef __D10V__
+ unsigned long *s, *d, tmp;
+ short dmap_src, dmap_dst;
+ short dmap_save;
+
+ /* all section sizes should by multiples of 4 bytes */
+ dmap_save = DMAP;
+
+ D10VTranslate (src, &dmap_src, &s);
+ D10VTranslate (dst, &dmap_dst, &d);
+
+ while (size > 0)
+ {
+ /* NB: Transfer 4 byte (long) quantites, problems occure
+ when only two bytes are transfered */
+ DMAP = dmap_src;
+ tmp = *s;
+ DMAP = dmap_dst;
+ *d = tmp;
+ d++;
+ s++;
+ size -= sizeof (tmp);
+ src += sizeof (tmp);
+ dst += sizeof (tmp);
+ if ((src & 0x3fff) == 0)
+ D10VTranslate (src, &dmap_src, &s);
+ if ((dst & 0x3fff) == 0)
+ D10VTranslate (dst, &dmap_dst, &d);
+ }
+ DMAP = dmap_save;
+#endif /* D10V */
+}
+
diff --git a/gdb/testsuite/gdb.base/default.exp b/gdb/testsuite/gdb.base/default.exp
new file mode 100644
index 00000000000..8e1506aeb02
--- /dev/null
+++ b/gdb/testsuite/gdb.base/default.exp
@@ -0,0 +1,793 @@
+# Copyright (C) 1988, 1990, 1991, 1992, 1994, 1997, 1998
+# Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# Start with a fresh gdb
+
+gdb_exit
+gdb_start
+
+set timeout 60
+
+#
+# test default actions of gdb commands
+#
+
+#load_lib gdb.exp
+
+gdb_test "add-symbol-file" "add-symbol-file takes a file name and an address" "add-symbol-file"
+
+setup_xfail "mips-idt-*"
+send_gdb "attach\n"
+gdb_expect {
+ -re "Argument required .(process-id|program) to attach.*$gdb_prompt $"\
+ { pass "attach" }
+ -re "You can't do that when your target is `None'.*$gdb_prompt $"\
+ { pass "attach" }
+ -re "Don't know how to attach. Try \"help target\"..*$gdb_prompt $"\
+ { pass "attach" }
+ -re "Kill it. .y or n." {
+ send_gdb "y\n"
+ exp_continue
+ }
+ -re "$gdb_prompt $" { fail "attach" }
+ timeout { fail "(timeout) attach" }
+}
+
+# FIXME: attach kills the udi connection
+if { [istarget "a29k-*-udi"] } {
+ gdb_exit
+ gdb_start
+}
+
+if ![target_info exists use_gdb_stub] {
+ gdb_test "break" "No default breakpoint address now." "break"
+ foreach i "b br bre brea" {
+ gdb_test $i "No default breakpoint address now." "break \"$i\" abbreviation"
+ }
+
+
+ setup_xfail "mips-idt-*" "a29k-*-udi"
+ gdb_test "backtrace" "No stack."
+ foreach i "bt ba bac" {
+ setup_xfail "mips-idt-*" "a29k-*-udi"
+ gdb_test $i "No stack." "backtrace \"$i\" abbreviation"
+ }
+} else {
+ warning "Skipping backtrace and break tests because of GDB stub."
+}
+
+# This works on the MIPS IDT board, but confuses future tests.
+if ![istarget "mips-idt-*"] then {
+ setup_xfail "a29k-*-udi"
+ gdb_test "continue" "The program is not being run." "continue"
+ setup_xfail "a29k-*-udi"
+ gdb_test "c" "The program is not being run." "continue \"c\" abbreviation"
+}
+
+# FIXME: continue kills the udi connection
+if [istarget "a29k-*-udi"] then {
+ gdb_exit
+ gdb_start
+}
+
+#test call
+gdb_test "call" "The history is empty..*" "call"
+
+
+#test catch
+gdb_test "catch" "Catch requires an event name..*" "catch"
+
+#test cd
+gdb_test "cd" "Argument required .new working directory.*" "cd"
+
+#test clear
+gdb_test "clear" "No source file specified..*" "clear"
+
+#test commands
+gdb_test "commands" "No breakpoint number 0..*" "commands"
+
+#test condition
+gdb_test "condition" "Argument required .breakpoint number.*" "condition"
+
+#test core-file
+gdb_test "core-file" "No core file now.|GDB can't read core files on this machine." "core-file"
+#test delete "d" abbreviation
+gdb_test "d" "" "delete \"d\" abbreviation"
+#test delete
+gdb_test "delete" "" "delete"
+#test define
+gdb_test "define" "Argument required \[(\]name of command to define\[)\]." "define"
+#test delete breakpoints
+gdb_test "delete breakpoints" "" "delete breakpoints"
+#test delete display
+# FIXME -- need to dump full output to detailed log
+send_gdb "delete display\n"
+gdb_expect {
+ -re "Delete all auto-display expressions.*y or n. $" {
+ send_gdb "y\n"
+ gdb_expect {
+ -re "$gdb_prompt $" { pass "delete display prompt" }
+ timeout { fail "(timeout) delete display prompt" }
+ }
+ }
+ timeout { fail "(timeout) delete display prompt" }
+
+}
+
+#test detach
+gdb_test "detach" "" "detach"
+
+# FIXME: continue kills the udi connection
+if [istarget "a29k-*-udi"] then {
+ gdb_exit
+ gdb_start
+}
+if [istarget "h8300-*-hms"] then {
+ gdb_exit
+ gdb_start
+}
+
+#test directory
+# FIXME -- need to dump full output to detailed log
+
+send_gdb "directory\n"
+gdb_expect {
+ -re "Reinitialize source path to empty.*y or n. $" {
+ send_gdb "y\n"
+ gdb_expect {
+ -re "Source directories searched: .cdir:.cwd.*$gdb_prompt $"\
+ { pass "directory prompt" }
+ timeout { fail "(timeout) directory prompt" }
+ }
+ }
+}
+
+#test disable "dis" abbreviation
+gdb_test "dis" "" "disable \"dis\" abbreviation"
+#test disable "disa" abbreviation
+gdb_test "disa" "" "disable \"disa\" abbreviation"
+#test disable
+gdb_test "disable" "" "disable"
+#test disable breakpoints
+gdb_test "disable breakpoints" "" "disable breakpoints"
+#test disable display
+gdb_test "disable display" "" "disable display"
+#test disassemble
+gdb_test "disassemble" "No frame selected." "disassemble"
+#test display
+gdb_test "display" "" "display"
+#test do
+gdb_test "do" "No stack." "do"
+#test document
+gdb_test "document" "Argument required .name of command to define.*" "document"
+#test down
+gdb_test "down" "No stack.*" "down"
+#test down-silently
+gdb_test "down-silently" "No stack." "down-silently"
+#test echo
+gdb_test "echo" "" "echo"
+#test enable breakpoints delete
+gdb_test "enable breakpoints delete" "Argument required .one or more breakpoint numbers.*" "enable breakpoints delete"
+#test enable breakpoints once
+gdb_test "enable breakpoints once" "Argument required .one or more breakpoint numbers.*" "enable breakpoints once"
+#test enable breakpoints
+gdb_test "enable breakpoints" "" "enable breakpoints"
+#test enable delete
+gdb_test "enable delete" "Argument required .one or more breakpoint numbers.*" "enable delete"
+#test enable display
+gdb_test "enable display" "" "enable display"
+#test enable once
+gdb_test "enable once" "Argument required .one or more breakpoint numbers.*" "enable once"
+#test enable
+gdb_test "enable" "" "enable"
+#test exec-file
+send_gdb "exec-file\n"
+gdb_expect {
+ -re "No executable file now..*$gdb_prompt $" {
+ pass "exec-file"
+ }
+ -re "exec-file.*A program is being debugged already. Kill it. .y or n.*$" {
+ send_gdb "n\n"
+ if $verbose>1 then {
+ send_user "\tDidn't kill program being debugged\n"
+ }
+ gdb_expect -re "$gdb_prompt $" { }
+ pass "exec-file"
+ }
+ -re "$gdb_prompt $" { fail "exec-file" }
+ timeout { fail "(timeout) exec-file" }
+}
+
+#test frame "f" abbreviation
+setup_xfail "a29k-*-udi"
+gdb_test "f" "No stack." "frame \"f\" abbreviation"
+#test frame
+setup_xfail "a29k-*-udi"
+gdb_test "frame" "No stack." "frame"
+#test fg
+setup_xfail "a29k-*-udi"
+gdb_test "fg" "The program is not being run." "fg"
+# FIXME: fg kills the udi connection
+#test file
+send_gdb "file\n"
+gdb_expect {
+ -re "No executable file now..*$gdb_prompt $"\
+ { pass "file" }
+ -re ".*A program is being debugged already. Kill it. .y or n.*$" {
+ send_gdb "n\n"
+ if $verbose>1 then {
+ send_user "\t\tDidn't kill program being debugged\n"
+ }
+ gdb_expect -re "$gdb_prompt $" { }
+ pass "file"
+ }
+ -re ".*$gdb_prompt $" { fail "file" }
+ timeout { fail "(timeout) file" }
+}
+
+#test finish
+setup_xfail "a29k-*-udi"
+gdb_test "finish" "The program is not running." "finish"
+#test forward-search
+# The message here comes from the regexp library, not gdb, and so can
+# vary on different systems.
+gdb_test "forward-search" "No previous regular expression.*|There is no previous regular expression.*" "forward-search"
+#test help "h" abbreviation
+gdb_test "h" "List of classes of commands:.*\[\r\n\]+aliases -- Aliases of other commands.*\[\r\n\]+breakpoints -- Making program stop at certain points.*\[\r\n\]+data -- Examining data.*\[\r\n\]+files -- Specifying and examining files.*\[\r\n\]+obscure -- Obscure features.*\[\r\n\]+running -- Running the program.*\[\r\n\]+stack -- Examining the stack.*\[\r\n\]+status -- Status inquiries.*\[\r\n\]+support -- Support facilities.*\[\r\n\]+user-defined -- User-defined commands.*\[\r\n\]+Type \"help\" followed by a class name for a list of commands in that class..*\[\r\n\]+Type \"help\" followed by command name for full documentation..*\[\r\n\]+Command name abbreviations are allowed if unambiguous." "help \"h\" abbreviation"
+#test help
+gdb_test "help" "List of classes of commands:.*\[\r\n\]+aliases -- Aliases of other commands.*\[\r\n\]+breakpoints -- Making program stop at certain points.*\[\r\n\]+data -- Examining data.*\[\r\n\]+files -- Specifying and examining files.*\[\r\n\]+obscure -- Obscure features.*\[\r\n\]+running -- Running the program.*\[\r\n\]+stack -- Examining the stack.*\[\r\n\]+status -- Status inquiries.*\[\r\n\]+support -- Support facilities.*\[\r\n\]+user-defined -- User-defined commands.*\[\r\n\]+Type \"help\" followed by a class name for a list of commands in that class..*\[\r\n\]+Type \"help\" followed by command name for full documentation..*\[\r\n\]+Command name abbreviations are allowed if unambiguous." "help"
+#test handle
+gdb_test "handle" "Argument required .signal to handle.*" "handle"
+#test info "i" abbreviation
+gdb_test "i" "\"info\" must be followed by the name of an info command..*\[\r\n\]+List of info subcommands:.*\[\r\n\]+Type \"help info\" followed by info subcommand name for full documentation..*\[\r\n\]+Command name abbreviations are allowed if unambiguous." "info \"i\" abbreviation"
+#test info
+gdb_test "info" "\"info\" must be followed by the name of an info command..*\[\r\n\]+List of info subcommands:.*\[\r\n\]+Type \"help info\" followed by info subcommand name for full documentation..*\[\r\n\]+Command name abbreviations are allowed if unambiguous." "info"
+#test ignore
+gdb_test "ignore" "Argument required .a breakpoint number.*" "ignore"
+#test info address
+gdb_test "info address" "Argument required." "info address"
+#test info all-registers
+setup_xfail "a29k-*-udi"
+gdb_test "info all-registers" "The program has no registers now." "info all-registers"
+#test info args
+gdb_test "info args" "No frame selected." "info args"
+#test info bogus-gdb-command
+gdb_test "info bogus-gdb-command" "Undefined info command: \"bogus-gdb-command\". Try \"help info\".*" "info bogus-gdb-command"
+#test info breakpoints
+gdb_test "info breakpoints" "No breakpoints or watchpoints." "info breakpoints"
+#test info catch
+gdb_test "info catch" "You can't do that without a process to debug." "info catch"
+#test info copying
+# FIXME -- doesn't work worth a shit
+#send_gdb "info copying"
+# -re "GNU GENERAL PUBLIC LICENSE.*#of preserving the free status of all derivatives of our free software and.*#of promoting the sharing and reuse of software generally."#
+gdb_test "info copying"
+# }
+#
+#
+#test info display
+gdb_test "info display" "There are no auto-display expressions now." "info display"
+#test info frame "f" abbreviation
+gdb_test "info f" "No stack.*|No selected frame.*" "info frame \"f\" abbreviation"
+#test info frame
+gdb_test "info frame" "No stack.|No selected frame." "info frame"
+#test info files
+gdb_test "info files" "" "info files"
+#test info float
+if [istarget "arm-*-*"] then {
+ gdb_test "info float" "Software FPU type.*mask:.*flags:.*" "info float"
+} elseif [istarget "thumb-*-*"] then {
+ gdb_test "info float" "Software FPU type.*mask:.*flags:.*" "info float"
+} else {
+ gdb_test "info float" "No floating point info available for this processor." "info float"
+}
+#test info functions
+gdb_test "info functions" "All defined functions:" "info functions"
+#test info locals
+gdb_test "info locals" "No frame selected." "info locals"
+#test info program
+setup_xfail "a29k-*-udi"
+gdb_test "info program" "The program being debugged is not being run." "info program"
+#test info registers
+setup_xfail "a29k-*-udi"
+gdb_test "info registers" "The program has no registers now." "info registers"
+#test info stack "s" abbreviation
+setup_xfail "a29k-*-udi"
+gdb_test "info s" "No stack." "info stack \"s\" abbreviation"
+#test info stack
+setup_xfail "a29k-*-udi"
+gdb_test "info stack" "No stack." "info stack"
+#test info set
+# FIXME -- needs to match the entire output
+gdb_test "info set" "confirm: Whether to confirm potentially dangerous operations is o\[a-z\]*..*\[\r\n\]+history filename: The filename in which to record the command history is .*\[\r\n\]+listsize: Number of source lines gdb will list by default is 10.*" "info set"
+gdb_test "info symbol" "Argument required .address.."
+#test info source
+gdb_test "info source" "No current source file..*" "info source"
+#test info sources
+gdb_test "info sources" "No symbol table is loaded. Use the \"file\" command.*" "info sources"
+#test info target
+gdb_test "info target" "" "info target"
+#test info terminal
+gdb_test "info terminal" "No saved terminal information." "info terminal"
+#test info types
+gdb_test "info types" "All defined types:" "info types"
+#test info variables
+gdb_test "info variables" "All defined variables:" "info variables"
+#test info warranty
+gdb_test "info warranty" "NO WARRANTY.*\[\r\n\]+ *11. *BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY.*\[\r\n\]+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN.*\[\r\n\]+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES.*\[\r\n\]+PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED.*\[\r\n\]+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF.*\[\r\n\]+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS.*\[\r\n\]+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE.*\[\r\n\]+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,.*\[\r\n\]+REPAIR OR CORRECTION..*\[\r\n\]+ *12. *IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING.*\[\r\n\]+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR.*\[\r\n\]+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,.*\[\r\n\]+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING.*\[\r\n\]+OUT OF THE USE OR INABILITY TO USE THE PROGRAM .INCLUDING BUT NOT LIMITED.*\[\r\n\]+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY.*\[\r\n\]+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER.*\[\r\n\]+PROGRAMS., EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE.*\[\r\n\]+POSSIBILITY OF SUCH DAMAGES.*" "info warranty"
+#test info watchpoints
+gdb_test "info watchpoints" "No breakpoints or watchpoints." "info watchpoints"
+#test inspect
+gdb_test "inspect" "The history is empty." "inspect"
+#test jump
+setup_xfail "a29k-*-udi"
+gdb_test "jump" "The program is not being run." "jump"
+#test kill
+gdb_test "kill" "The program is not being run." "kill"
+#test list "l" abbreviation
+gdb_test "l" "No symbol table is loaded. Use the \"file\" command.*" "list \"l\" abbreviation"
+#test list
+gdb_test "list" "No symbol table is loaded. Use the \"file\" command.*" "list"
+#test load
+# The ``takes a file name'' case is for vxgdb.
+# The ``Use the "file" command'' case is for newer GDB versions which try
+# to deduce the filename from the exec file.
+gdb_test "load" "You can't do that when your target is `None'.*|The load command takes a file name.*|Must specify at least a file name with the load command.*|.*Use the .file. or .exec-file. command.*" "load"
+#test next "n" abbreviation
+setup_xfail "a29k-*-udi"
+gdb_test "n" "The program is not being run." "next \"n\" abbreviation"
+#test next
+setup_xfail "a29k-*-udi"
+gdb_test "next" "The program is not being run." "next"
+#test nexti "ni" abbreviation
+setup_xfail "a29k-*-udi"
+gdb_test "ni" "The program is not being run." "nexti \"ni\" abbreviation"
+#test nexti
+setup_xfail "a29k-*-udi"
+gdb_test "nexti" "The program is not being run." "nexti"
+#test output
+gdb_test "output" "Argument required .expression to compute.*" "output"
+
+#test overlay
+gdb_test "overlay" "\"overlay\" must be followed by the name of .*"
+#test a non-existant overlay subcommand
+gdb_test "overlay on" "Undefined overlay command.* Try \"help overlay\"."
+gdb_test "overlay manual" "" "overlay manual #1"
+gdb_test "overlay auto" ""
+gdb_test "overlay off" ""
+gdb_test "overlay list" "No sections are mapped."
+gdb_test "overlay map" "Overlay debugging not enabled.*" "overlay map #1"
+gdb_test "overlay unmap" "Overlay debugging not enabled.*" "overlay unmap #2"
+gdb_test "overlay manual" "" "overlay manual #2"
+gdb_test "overlay map" "Argument required: name of an overlay section." "overlay map #2"
+gdb_test "overlay unmap" "Argument required: name of an overlay section." "overlay unmap #2"
+
+#test print "p" abbreviation
+gdb_test "p" "The history is empty." "print \"p\" abbreviation"
+#test print
+gdb_test "print" "The history is empty." "print"
+#test printf
+gdb_test "printf" "Argument required .format-control string and values to print.*" "printf"
+#test ptype
+gdb_test "ptype" "The history is empty." "ptype"
+#test pwd
+gdb_test "pwd" "Working directory .*" "pwd"
+
+#test run "r" abbreviation
+if [istarget "*-*-vxworks*"] then {
+ gdb_test "set args" "" ""
+
+ gdb_test "r" "Starting program: .*
+You must specify a function name to run, and arguments if any"\
+ "run \"r\" abbreviation"
+ gdb_test "set args main" "" ""
+
+} else {
+ send_gdb "r\n"
+ gdb_expect {
+ -re "Starting program: .*
+You can't do that when your target is `None'.*$gdb_prompt $"\
+ { pass "run \"r\" abbreviation" }
+ -re "Starting program: .*
+No executable file specified.*
+Use the \"file\" or \"exec-file\" command.*$gdb_prompt $"\
+ { pass "run \"r\" abbreviation" }
+ -re "Starting program: .*
+No image loaded into target.*$gdb_prompt $"\
+ { pass "run \"r\" abbreviation" }
+ -re "Starting program: .*
+No program loaded.*$gdb_prompt $"\
+ { pass "run \"r\" abbreviation" }
+ -re "Don't know how to run. Try \"help target\"..*$gdb_prompt $"\
+ { pass "run \"r\" abbreviation" }
+ -re ".*$gdb_prompt $" { fail "run \"r\" abbreviation" }
+ timeout { fail "(timeout) run \"r\" abbreviation" }
+ }
+}
+
+#test run
+if [istarget "*-*-vxworks*"] then {
+ gdb_test "set args" "" ""
+
+ gdb_test "run" "Starting program: .*
+You must specify a function name to run, and arguments if any"
+ gdb_test "set args main" "" ""
+
+} else {
+ send_gdb "run\n"
+ gdb_expect {
+ -re "Starting program:.*You can't do that when your target is `None'.*$gdb_prompt $" { pass "run" }
+ -re "Starting program: .*
+No executable file specified.*
+Use the \"file\" or \"exec-file\" command.*$gdb_prompt $"\
+ { pass "run" }
+ -re "Starting program: .*
+No image loaded into target.*$gdb_prompt $"\
+ { pass "run" }
+ -re "Starting program: .*
+No program loaded.*$gdb_prompt $"\
+ { pass "run \"r\" abbreviation" }
+ -re "Don't know how to run. Try \"help target\"..*$gdb_prompt $"\
+ { pass "run" }
+ -re ".*$gdb_prompt $" { fail "run" }
+ timeout { fail "(timeout) run" }
+ }
+}
+
+#test rbreak
+gdb_test "rbreak" "" "rbreak"
+
+#test return
+# The middle case accommodates the a29k, where doing the "ni" above causes
+# an initial stack to be created.
+gdb_test "return" "No selected frame..*" "return" "Make .* return now.*y or n. $" "y"
+
+
+#test reverse-search
+gdb_test "reverse-search" "No previous regular expression.*|There is no previous regular expression.*" "reverse-search"
+#test step "s" abbreviation
+setup_xfail "a29k-*-udi"
+gdb_test "s" "The program is not being run." "step \"s\" abbreviation #1"
+#test step
+setup_xfail "a29k-*-udi"
+gdb_test "step" "The program is not being run." "step #1"
+#test search
+gdb_test "search" "No previous regular expression.*|There is no previous regular expression.*" "search"
+#test section
+gdb_test "section" "Must specify section name and its virtual address.*" "section"
+#test set annotate
+gdb_test "set annotate" "Argument required .integer to set it to.*" "set annotate"
+#test set args
+gdb_test "set args" "" "set args"
+#test set check "c" abbreviation
+gdb_test "set c" "\"set check\" must be followed by the name of a check subcommand..*\[\r\n\]+List of set check subcommands:.*\[\r\n\]+set check range -- Set range checking.*\[\r\n\]+set check type -- Set type checking.*\[\r\n\]+Type \"help set check\" followed by set check subcommand name for full documentation..*\[\r\n\]+Command name abbreviations are allowed if unambiguous." "set check \"c\" abbreviation"
+#test set check "ch" abbreviation
+gdb_test "set ch" "\"set check\" must be followed by the name of a check subcommand..*\[\r\n\]+List of set check subcommands:.*\[\r\n\]+set check range -- Set range checking.*\[\r\n\]+set check type -- Set type checking.*\[\r\n\]+Type \"help set check\" followed by set check subcommand name for full documentation..*\[\r\n\]+Command name abbreviations are allowed if unambiguous." "set check \"ch\" abbreviation"
+#test set check
+gdb_test "set check" "\"set check\" must be followed by the name of a check subcommand..*\[\r\n\]+List of set check subcommands:.*\[\r\n\]+set check range -- Set range checking.*\[\r\n\]+set check type -- Set type checking.*\[\r\n\]+Type \"help set check\" followed by set check subcommand name for full documentation..*\[\r\n\]+Command name abbreviations are allowed if unambiguous." "set check"
+#test set check range
+gdb_test "set check range" "" "set check range"
+#test set check type
+gdb_test "set check type" "" "set check type"
+#test set complaints
+gdb_test "set complaints" "Argument required .integer to set it to.*" "set complaints"
+#test set confirm
+gdb_test "set confirm" "" "set confirm"
+# Don't test set editing. What if we're talking to a gdb that
+# won't do editing correctly while we're talking to it?
+# gdb_test "set editing" "" "set editing"
+
+#test set environment
+gdb_test "set environment" "Argument required .environment variable and value.*" "set environment"
+#test set height
+gdb_test "set height" "Argument required .integer to set it to.*" "set height"
+#test set history expansion
+gdb_test "set history expansion" "" "set history expansion"
+#test set history filename
+gdb_test "set history filename" "Argument required .filename to set it to.*" "set history filename"
+#test set history save
+gdb_test "set history save" "" "set history save"
+#test set history size
+gdb_test "set history size" "Argument required .integer to set it to.*" "set history size"
+#test set history
+gdb_test "set history" "\"set history\" must be followed by the name of a history subcommand..*\[\r\n\]+List of set history subcommands:.*\[\r\n\]+set history expansion -- Set history expansion on command input.*\[\r\n\]+set history filename -- Set the filename in which to record the command history.*\[\r\n\]+set history save -- Set saving of the history record on exit.*\[\r\n\]+set history size -- Set the size of the command history.*\[\r\n\]+Type \"help set history\" followed by set history subcommand name for full documentation..*\[\r\n\]+Command name abbreviations are allowed if unambiguous." "set history"
+#test set language
+gdb_test "set language" "The currently understood settings are:.*\[\r\n\]+local or auto *Automatic setting based on source file.*\[\r\n\]+c *Use the C language.*\[\r\n\]+c\[+\]+ *Use the C\[+\]+ language.*\[\r\n\]+modula-2 *Use the Modula-2 language.*" "set language"
+#test set listsize
+gdb_test "set listsize" "Argument required .integer to set it to.*" "set listsize"
+#test set print "p" abbreviation
+gdb_test "set p" "\"set print\" must be followed by the name of a print subcommand..*\[\r\n\]+List of set print subcommands:.*\[\r\n\]+Type \"help set print\" followed by set print subcommand name for full documentation..*\[\r\n\]+Command name abbreviations are allowed if unambiguous." "set print \"p\" abbreviation"
+#test set print "pr" abbreviation
+gdb_test "set pr" "\"set print\" must be followed by the name of a print subcommand..*\[\r\n\]+List of set print subcommands:.*\[\r\n\]+Type \"help set print\" followed by set print subcommand name for full documentation..*\[\r\n\]+Command name abbreviations are allowed if unambiguous." "set print \"pr\" abbreviation"
+#test set print
+gdb_test "set print" "\"set print\" must be followed by the name of a print subcommand..*\[\r\n\]+List of set print subcommands:.*\[\r\n\]+Type \"help set print\" followed by set print subcommand name for full documentation..*\[\r\n\]+Command name abbreviations are allowed if unambiguous." "set print"
+#test set print address
+gdb_test "set print address" "" "set print address"
+#test set print array
+gdb_test "set print array" "" "set print array"
+#test set print asm-demangle
+gdb_test "set print asm-demangle" "" "set print asm-demangle"
+#test set print demangle
+gdb_test "set print demangle" "" "set print demangle"
+#test set print elements
+gdb_test "set print elements" "Argument required .integer to set it to.*" "set print elements"
+#test set print object
+gdb_test "set print object" "" "set print object"
+#test set print pretty
+gdb_test "set print pretty" "" "set print pretty"
+#test set print sevenbit-strings
+gdb_test "set print sevenbit-strings" "" "set print sevenbit-strings"
+#test set print union
+gdb_test "set print union" "" "set print union"
+#test set print vtbl
+gdb_test "set print vtbl" "" "set print vtbl"
+# FIXME -- need a test for "set prompt"
+#test set radix
+gdb_test "set radix" "Input and output radices now set to decimal 10, hex a, octal 12.*" "set radix"
+#test set symbol-reloading
+gdb_test "set symbol-reloading" "" "set symbol-reloading"
+#test set variable
+gdb_test "set variable" "Argument required .expression to compute.*" "set variable"
+#test set verbose
+gdb_test "set verbose" "" "set verbose"
+#test set width
+gdb_test "set width" "Argument required .integer to set it to.*" "set width"
+#test set write
+# This is only supported on targets which use exec.o.
+gdb_test "set write" "" "set write"
+#test set
+gdb_test "set" "Argument required .expression to compute.*" "set"
+#test shell echo Hi dad!
+gdb_test "shell echo Hi dad!" "Hi dad!" "shell echo Hi dad!"
+#test show annotate
+gdb_test "show annotate" "Annotation_level is 0." "show annotate"
+#test show args
+gdb_test "show args" "Argument list to give program being debugged when it is started is \"\"." "show args"
+#test show check "c" abbreviation
+gdb_test "show c" "range: *Range checking is \"auto; currently off\"..*\[\r\n\]+type: *Type checking is \"auto; currently off\".*" "show check \"c\" abbreviation"
+#test show check "ch" abbreviation
+gdb_test "show ch" "range: *Range checking is \"auto; currently off\"..*\[\r\n\]+type: *Type checking is \"auto; currently off\"." "show check \"ch\" abbreviation"
+#test show check
+gdb_test "show check" "range: *Range checking is \"auto; currently off\"..*\[\r\n\]+type: *Type checking is \"auto; currently off\"." "show check"
+#test show check range
+gdb_test "show check range" "Range checking is \"auto; currently off\"." "show check range"
+#test show check type
+gdb_test "show check type" "Type checking is \"auto; currently off\"." "show check type"
+#test show commands
+gdb_test "show commands" "" "show commands"
+#test show complaints
+gdb_test "show complaints" "Max number of complaints about incorrect symbols is 0." "show complaints"
+#test show confirm
+gdb_test "show confirm" "Whether to confirm potentially dangerous operations is o\[a-z\]*." "show confirm"
+#test show convenience
+gdb_test "show convenience" "No debugger convenience variables now defined..*\[\r\n\]+Convenience variables have names starting with \".\";.*\[\r\n\]+use \"set\" as in \"set .foo = 5\" to define them." "show convenience"
+#test show directories
+gdb_test "show directories" "Source directories searched: .cdir:.cwd" "show directories"
+#test show editing
+gdb_test "show editing" "Editing of command lines as they are typed is o\[a-z\]*." "show editing"
+#test show height
+gdb_test "show height" "Number of lines gdb thinks are in a page is.*" "show height"
+#test show history expansion
+gdb_test "show history expansion" "History expansion on command input is o\[a-z\]*.*" "show history expansion"
+#test show history filename
+gdb_test "show history filename" "The filename in which to record the command history is.*.gdb_history.*" "show history filename"
+#test show history save
+gdb_test "show history save" "Saving of the history record on exit is on." "show history save"
+#test show history size
+gdb_test "show history size" "The size of the command history is.*" "show history size"
+#test show history
+gdb_test "show history" "expansion: *History expansion on command input is o.*\[\r\n\]+filename: *The filename in which to record the command history is.*.gdb_history.*\[\r\n\]+save: *Saving of the history record on exit is o.*\[\r\n\]+size: * The size of the command history is.*" "show history"
+#test show language
+gdb_test "show language" "The current source language is \"auto; currently c\"." "show language"
+#test show listsize
+gdb_test "show listsize" "Number of source lines gdb will list by default is 10." "show listsize"
+#test show print "p" abbreviation
+gdb_test "show p" ".*" "show p"
+#test show print "pr" abbreviation
+gdb_test "show pr" ".*" "show pr"
+#test show print
+gdb_test "show print" "" "show print"
+#test show paths
+gdb_test "show paths" "Executable and object file path:.*" "show paths"
+#test show print address
+gdb_test "show print address" "Printing of addresses is on." "show print address"
+#test show print array
+gdb_test "show print array" "Prettyprinting of arrays is on." "show print array"
+#test show print asm-demangle
+gdb_test "show print asm-demangle" "Demangling of C\[+\]+ names in disassembly listings is on." "show print asm-demangle"
+#test show print demangle
+gdb_test "show print demangle" "Demangling of encoded C\[+\]+ names when displaying symbols is on." "show print demangle"
+#test show print elements
+gdb_test "show print elements" "Limit on string chars or array elements to print is 200." "show print elements"
+#test show print object
+gdb_test "show print object" "Printing of object's derived type based on vtable info is on." "show print object"
+#test show print pretty
+gdb_test "show print pretty" "Prettyprinting of structures is on." "show print pretty"
+#test show print sevenbit-strings
+gdb_test "show print sevenbit-strings" "Printing of 8-bit characters in strings as .nnn is on." "show print sevenbit-strings"
+#test show print union
+gdb_test "show print union" "Printing of unions interior to structures is on." "show print union"
+#test show print vtbl
+gdb_test "show print vtbl" "Printing of C\[+\]+ virtual function tables is on." "show print vtbl"
+#test show prompt
+# In the FAIL case, can't just look for $gdb_prompt because that will match
+# the output, rather than the prompt. So look for $gdb_prompt at the start
+# of a line.
+gdb_test "show prompt" "Gdb's prompt is \"$gdb_prompt \".*" "show prompt"
+#test show radix
+gdb_test "show radix" "Input and output radices set to decimal 10, hex a, octal 12." "show radix"
+#test show symbol-reloading
+gdb_test "show symbol-reloading" "Dynamic symbol table reloading multiple times in one run is on." "show symbol-reloading"
+#test show user
+gdb_test "show user" "" "show user"
+#test show values
+gdb_test "show values" "" "show values"
+#test show verbose
+gdb_test "show verbose" "Verbose printing of informational messages is o.*|Verbosity is off.*" "show verbose"
+#test show version
+
+gdb_test "show version" "GNU gdb \[0-9\.\]*.*\[\r\n\]+Copyright \[0-9\]* Free Software Foundation, Inc.*\[\r\n\]+GDB is free software, covered by the GNU General Public License, and you are.*\[\r\n\]+welcome to change it and/or distribute copies of it under certain conditions.*\[\r\n\]+Type \"show copying\" to see the conditions.*\[\r\n\]+There is absolutely no warranty for GDB. Type \"show warranty\" for details.*\[\r\n\]+This GDB was configured as .*|GDB is free software and you are welcome to distribute copies of it.*\[\r\n\]+ under certain conditions; type \"show copying\" to see the conditions..*\[\r\n\]+There is absolutely no warranty for GDB; type \"show warranty\" for details..*\[\r\n\]+GDB.*Copyright \[0-9\]* Free Software Foundation, Inc.*" "show version"
+#test show width
+gdb_test "show width" "Number of characters gdb thinks are in a line is.*" "show width"
+#test show write
+# This is only supported on targets which use exec.o.
+gdb_test "show write" "Writing into executable and core files is o.*" "show write"
+#test show
+gdb_test "show" "confirm: *Whether to confirm potentially dangerous operations is on..*\[\r\n\]+history filename: *The filename in which to record the command history is .*\[\r\n\]+history save: *Saving of the history record on exit is on..*\[\r\n\]+history size: *The size of the command history is.*\[\r\n\]+listsize: *Number of source lines gdb will list by default is 10.*\[\r\n\]+print elements: *Limit on string chars or array elements to print is 200..*" "show"
+#test stepi "si" abbreviation
+setup_xfail "a29k-*-udi"
+gdb_test "si" "The program is not being run." "stepi \"si\" abbreviation"
+#test stepi
+setup_xfail "a29k-*-udi"
+gdb_test "stepi" "The program is not being run." "stepi"
+#test signal
+setup_xfail "a29k-*-udi"
+gdb_test "signal" "The program is not being run." "signal"
+#test source
+gdb_test "source" "source command requires pathname of file to source..*|No such file or directory.*" "source"
+#test step "s" abbreviation
+setup_xfail "a29k-*-udi"
+gdb_test "s" "The program is not being run." "step \"s\" abbreviation #2"
+#test step
+setup_xfail "a29k-*-udi"
+gdb_test "step" "The program is not being run." "step #2"
+#test symbol-file
+gdb_test "symbol-file" "" "symbol-file"
+
+#test target child
+gdb_test "target child" "Use the \"run\" command to start a Unix child process.*|Undefined target command: \"child\". *Try \"help target\".*" "target child"
+
+#test target procfs
+gdb_test "target procfs" "Use the \"run\" command to start a Unix child process.*|Undefined target command: \"procfs\". *Try \"help target\".*" "target procfs"
+
+#test target core
+send_gdb "target core\n"
+gdb_expect {
+ -re "No core file specified..*$gdb_prompt $" { pass "target core" }
+ -re ".*A program is being debugged already. Kill it. .y or n.*$" {
+ send_gdb "n\n"
+ if $verbose>1 then {
+ send_user "\t\tDidn't kill program being debugged\n"
+ }
+ gdb_expect -re "$gdb_prompt $" { }
+ pass "target core"
+ }
+ -re "Undefined target command: \"core\". Try \"help target\"..*$gdb_prompt $" { pass "target core" }
+ -re ".*$gdb_prompt $" { fail "target core" }
+ timeout { fail "(timeout) target core" }
+}
+
+#test target exec
+send_gdb "target exec\n"
+gdb_expect {
+ -re "No executable file now..*$gdb_prompt $"\
+ { pass "target exec" }
+ -re ".*A program is being debugged already. Kill it. .y or n.*$" {
+ send_gdb "n\n"
+ if $verbose>1 then {
+ send_user "\t\tDidn't kill program being debugged\n"
+ }
+ gdb_expect -re "$gdb_prompt $" { }
+ pass "target exec"
+ }
+ -re ".*$gdb_prompt $" { fail "target exec" }
+ timeout { fail "(timeout) target exec" }
+ }
+
+#test target remote
+if ![istarget "*-*-udi*"] then {
+ send_gdb "target remote\n"
+ gdb_expect {
+ -re "To open a remote debug connection, you need to specify what.*
+serial device is attached to the remote system .e.g. /dev/ttya.*$gdb_prompt $"\
+ { pass "target remote" }
+ -re ".*A program is being debugged already. Kill it. .y or n.*$" {
+ send_gdb "n\n"
+ if $verbose>1 then {
+ send_user "\t\tDidn't kill program being debugged\n"
+ }
+ gdb_expect -re "$gdb_prompt $" { }
+ pass "target remote"
+ }
+ -re ".*$gdb_prompt $" { fail "target remote" }
+ timeout { fail "(timeout) target remote" }
+ }
+}
+
+#test target
+gdb_test "target" "Argument required .target name.*" "target"
+#test tbreak
+gdb_test "tbreak" "No default breakpoint address now." "tbreak"
+#test tty
+gdb_test "tty" "Argument required .terminal name for running target process.*" "tty"
+#test until "u" abbreviation
+setup_xfail "a29k-*-udi"
+gdb_test "u" "The program is not running." "until \"u\" abbreviation"
+#test until
+setup_xfail "a29k-*-udi"
+gdb_test "until" "The program is not running." "until"
+#test undisplay
+# FIXME -- need to dump full output to detailed log
+send_gdb "undisplay\n"
+gdb_expect {
+ -re "Delete all auto-display expressions.*y or n. $" {
+ send_gdb "y\n"
+ gdb_expect {
+ -re "$gdb_prompt $" { pass "undisplay prompt" }
+ timeout { fail "(timeout) (timeout) undisplay prompt" }
+ }
+ }
+ timeout { fail "(timeout) (timeout) undisplay prompt" }
+}
+
+#test unset environment
+send_gdb "unset environment\n"
+gdb_expect {
+ -re "Delete all environment variables?.*y or n. $" {
+ send_gdb "y\n"
+ gdb_expect {
+ -re "$gdb_prompt $" { pass "unset environmentprompt" }
+ timeout {
+ fail "(timeout) (timeout) unset environment prompt"
+ }
+ }
+ }
+ timeout {
+ fail "(timeout) (timeout) unset environment prompt"
+ }
+}
+
+#test unset
+gdb_test "unset" "\"unset\" must be followed by the name of an unset subcommand..*\[\r\n\]+List of unset subcommands:.*\[\r\n\]+unset environment -- Cancel environment variable VAR for the program.*\[\r\n\]+Type \"help unset\" followed by unset subcommand name for full documentation..*\[\r\n\]+Command name abbreviations are allowed if unambiguous." "unset"
+#test up
+#test up-silently
+gdb_test "up-silently" "No stack." "up-silently"
+#test watch
+gdb_test "watch" "Argument required .expression to compute.*" "watch"
+#test whatis
+gdb_test "whatis" "The history is empty." "whatis"
+#test where
+setup_xfail "a29k-*-udi"
+gdb_test "where" "No stack." "where"
+#test x
+#The case in which it prints a number is for vxgdb.
+gdb_test "x" "0x0:.*0x\[0-9\]*|0x0:.*Cannot access memory at address 0x0." "x"
+
+gdb_exit
diff --git a/gdb/testsuite/gdb.base/define.exp b/gdb/testsuite/gdb.base/define.exp
new file mode 100644
index 00000000000..1cd06a92710
--- /dev/null
+++ b/gdb/testsuite/gdb.base/define.exp
@@ -0,0 +1,304 @@
+# Copyright (C) 1998 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file was written by Elena Zannoni. (ezannoni@cygnus.com)
+
+if $tracelevel then {
+ strace $tracelevel
+ }
+
+global usestubs
+
+
+#
+# test running programs
+#
+set prms_id 0
+set bug_id 0
+
+set testfile "break"
+set srcfile ${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug additional_flags=-w}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+if ![runto_main] then { fail "define tests suppressed" }
+
+# Verify that GDB allows a user to define their very own commands.
+#
+send_gdb "define nextwhere\n"
+gdb_expect {
+ -re "Type commands for definition of \"nextwhere\".\r\nEnd with a line saying just \"end\".\r\n>$"\
+ {send_gdb "next\nbt\nend\n"
+ gdb_expect {
+ -re "$gdb_prompt $"\
+ {pass "define user command: nextwhere"}
+ timeout {fail "(timeout) define user command: nextwhere"}
+ }
+ }
+ -re "$gdb_prompt $"\
+ {fail "define user command: nextwhere"}
+ timeout {fail "(timeout) define user command: nextwhere"}
+}
+
+# Verify that those commands work as gdb_expected.
+#
+send_gdb "nextwhere\n"
+gdb_expect {
+ -re ".*64\[ \t\]*printf.*#0\[ \t\]*main.*:64.*$gdb_prompt $"\
+ {pass "use user command: nextwhere"}
+ -re "$gdb_prompt $"\
+ {fail "use user command: nextwhere"}
+ timeout {fail "(timeout) use user command: nextwhere"}
+}
+
+# Verify that a user can define a command whose spelling is a
+# proper substring of another user-defined command.
+#
+send_gdb "define nextwh\n"
+gdb_expect {
+ -re "Type commands for definition of \"nextwh\".\r\nEnd with a line saying just \"end\".\r\n>$"\
+ {send_gdb "next 2\nbt\nend\n"
+ gdb_expect {
+ -re "$gdb_prompt $"\
+ {pass "define user command: nextwh"}
+ timeout {fail "(timeout) define user command: nextwh"}
+ }
+ }
+ -re "$gdb_prompt $"\
+ {fail "define user command: nextwh"}
+ timeout {fail "(timeout) define user command: nextwh"}
+}
+
+# Verify that a user can redefine their commands. (Test both the
+# confirmed and unconfirmed cases.)
+#
+send_gdb "define nextwhere\n"
+gdb_expect {
+ -re "Redefine command \"nextwhere\".*y or n. $"\
+ {send_gdb "n\n"
+ gdb_expect {
+ -re "Command \"nextwhere\" not redefined.*$gdb_prompt $"\
+ {pass "redefine user command aborted: nextwhere"}
+ -re "$gdb_prompt $"\
+ {fail "redefine user command aborted: nextwhere"}
+ timeout {fail "(timeout) redefine user command aborted: nextwhere"}
+ }
+ }
+ -re "$gdb_prompt $"\
+ {fail "redefine user command aborted: nextwhere"}
+ timeout {fail "(timeout) redefine user command aborted: nextwhere"}
+}
+
+send_gdb "define nextwhere\n"
+gdb_expect {
+ -re "Redefine command \"nextwhere\".*y or n. $"\
+ {send_gdb "y\n"
+ gdb_expect {
+ -re "Type commands for definition of \"nextwhere\".\r\nEnd with a line saying just \"end\".\r\n>$"\
+ {send_gdb "bt\nnext\nend\n"
+ gdb_expect {
+ -re "$gdb_prompt $"\
+ {pass "redefine user command: nextwhere"}
+ timeout {fail "(timeout) redefine user command: nextwhere"}
+ }
+ }
+ timeout {fail "(timeout) redefine user command: nextwhere"}
+ }
+ }
+ -re "$gdb_prompt $"\
+ {fail "redefine user command: nextwhere"}
+ timeout {fail "(timeout) redefine user command: nextwhere"}
+}
+
+# Verify that GDB gracefully handles an attempt to redefine the
+# help text for a builtin command.
+#
+send_gdb "document step\n"
+gdb_expect {
+ -re "Command \"step\" is built-in..*$gdb_prompt $"\
+ {pass "redocumenting builtin command disallowed"}
+ -re "$gdb_prompt $"\
+ {fail "redocumenting builtin command disallowed"}
+ timeout {fail "(timeout) redocumenting builtin command disallowed"}
+}
+
+# Verify that a user can document their own commands. (And redocument
+# them.)
+#
+send_gdb "document nextwhere\n"
+gdb_expect {
+ -re "Type documentation for \"nextwhere\".\r\nEnd with a line saying just \"end\".\r\n>$"\
+ {send_gdb "A next command that frist shows you where you're stepping from.\nend\n"
+ gdb_expect {
+ -re "$gdb_prompt $"\
+ {pass "document user command: nextwhere"}
+ timeout {fail "(timeout) document user command: nextwhere"}
+ }
+ }
+ -re "$gdb_prompt $"\
+ {fail "documenting user command: nextwhere"}
+ timeout {fail "(timeout) documenting user command: nextwhere"}
+}
+
+send_gdb "document nextwhere\n"
+gdb_expect {
+ -re "Type documentation for \"nextwhere\".\r\nEnd with a line saying just \"end\".\r\n>$"\
+ {send_gdb "A next command that first shows you where you're stepping from.\nend\n"
+ gdb_expect {
+ -re "$gdb_prompt $"\
+ {pass "document user command: nextwhere"}
+ timeout {fail "(timeout) document user command: nextwhere"}
+ }
+ }
+ -re "$gdb_prompt $"\
+ {fail "documenting user command: nextwhere"}
+ timeout {fail "(timeout) documenting user command: nextwhere"}
+}
+
+send_gdb "help nextwhere\n"
+gdb_expect {
+ -re "A next command that first shows you where you're stepping from.\r\n$gdb_prompt $"\
+ {pass "help user command: nextwhere"}
+ -re "$gdb_prompt $"\
+ {fail "help user command: nextwhere"}
+ timeout {fail "(timeout) help user command: nextwhere"}
+}
+
+# Verify that the user can "hook" a builtin command. We choose to
+# hook the "stop" pseudo command, and we'll define it to use a user-
+# define command.
+#
+send_gdb "define user-bt\n"
+gdb_expect {
+ -re "Type commands for definition of \"user-bt\".\r\nEnd with a line saying just \"end\".\r\n>$"\
+ {send_gdb "bt\nend\n"
+ gdb_expect {
+ -re "$gdb_prompt $"\
+ {pass "define user command: user-bt"}
+ timeout {fail "(timeout) define user command: user-bt"}
+ }
+ }
+ -re "$gdb_prompt $"\
+ {fail "define user command: user-bt"}
+ timeout {fail "(timeout) define user command: user-bt"}
+}
+
+send_gdb "define hook-stop\n"
+gdb_expect {
+ -re "Type commands for definition of \"hook-stop\".\r\nEnd with a line saying just \"end\".\r\n>$"\
+ {send_gdb "user-b\nend\n"
+ gdb_expect {
+ -re "$gdb_prompt $"\
+ {pass "define hook-stop command"}
+ timeout {fail "(timeout) define hook-stop command"}
+ }
+ }
+ -re "$gdb_prompt $"\
+ {fail "define hook-stop command"}
+ timeout {fail "(timeout) define hook-stop command"}
+}
+
+send_gdb "next\n"
+gdb_expect {
+ -re "#0\[ \t\]*main.*:66.*$gdb_prompt $"\
+ {pass "use hook-stop command"}
+ -re "$gdb_prompt $"\
+ {fail "use hook-stop command"}
+ timeout {fail "(timeout) use hook-stop command"}
+}
+
+# Verify that GDB responds gracefully to an attempt to define a "hook
+# command" which doesn't exist. (Test both the confirmed and unconfirmed
+# cases.)
+#
+send_gdb "define hook-bar\n"
+gdb_expect {
+ -re "warning: Your new `hook-bar' command does not hook any existing command.\r\nProceed.*y or n. $"\
+ {send_gdb "n\n"
+ gdb_expect {
+ -re "Not confirmed.*$gdb_prompt $"\
+ {pass "define hook undefined command aborted: bar"}
+ -re "$gdb_prompt $"\
+ {fail "define hook undefined command aborted: bar"}
+ timeout {fail "(timeout) define hook undefined command aborted: bar"}
+ }
+ }
+ -re "$gdb_prompt $"\
+ {fail "define hook undefined command aborted: bar"}
+ timeout {fail "(timeout) define hook undefined command aborted: bar"}
+}
+
+send_gdb "define hook-bar\n"
+gdb_expect {
+ -re "warning: Your new `hook-bar' command does not hook any existing command.\r\nProceed.*y or n. $"\
+ {send_gdb "y\n"
+ gdb_expect {
+ -re "Type commands for definition of \"hook-bar\".\r\nEnd with a line saying just \"end\".\r\n>$"\
+ {send_gdb "nextwhere\nend\n"
+ gdb_expect {
+ -re "$gdb_prompt $"\
+ {pass "define hook undefined command: bar"}
+ timeout {fail "(timeout) define hook undefined command: bar"}
+ }
+ }
+ -re "$gdb_prompt $"\
+ {fail "define hook undefined command: bar"}
+ timeout {fail "(timeout) define hook undefined command: bar"}
+ }
+ }
+ -re "$gdb_prompt $"\
+ {fail "define hook undefined command: bar"}
+ timeout {fail "(timeout) define hook undefined command: bar"}
+}
+
+# This is a quasi-define command: Verify that the user can redefine
+# GDB's gdb_prompt.
+#
+send_gdb "set prompt \\(blah\\) \n"
+gdb_expect {
+ -re "\\(blah\\) $"\
+ {pass "set gdb_prompt"}
+ -re "$gdb_prompt $"\
+ {fail "set gdb_prompt"}
+ timeout {fail "(timeout) set gdb_prompt"}
+}
+
+send_gdb "set prompt \\(gdb\\) \n"
+gdb_expect {
+ -re "$gdb_prompt $"\
+ {pass "reset gdb_prompt"}
+ timeout {fail "(timeout) reset gdb_prompt"}
+}
+
+gdb_exit
+return 0
+
+
+
+
+
+
diff --git a/gdb/testsuite/gdb.base/display.c b/gdb/testsuite/gdb.base/display.c
new file mode 100644
index 00000000000..a85f0670f27
--- /dev/null
+++ b/gdb/testsuite/gdb.base/display.c
@@ -0,0 +1,52 @@
+/* Loop and vars for tests of display commands
+*/
+#include <stdio.h>
+#define LOOP 10
+
+int sum = 0;
+
+int do_loops()
+{
+ int i=0;
+ int k=0;
+ int j=0;
+
+ for( i = 0; i < LOOP; i++ ) {
+ for( j = 0; j < LOOP; j++ ) {
+ for( k = 0; k < LOOP; k++ ) {
+ sum++;
+ }
+ }
+ }
+ return i;
+}
+
+int do_vars()
+{
+ int j;
+ int i = 9;
+ float f = 1.234;
+ char c = 'Q';
+ int *p_i = &i;
+ float *p_f = &f;
+ char *p_c = "rubarb and fries";
+
+ /* Need some code here to set breaks on.
+ */
+ for( j = 0; j < LOOP; j++ ) {
+ if( p_c[j] == c ) {
+ j++;
+ }
+ else {
+ i++;
+ }
+ }
+
+ return *p_i;
+}
+
+main()
+{
+ do_loops();
+ do_vars();
+}
diff --git a/gdb/testsuite/gdb.base/display.exp b/gdb/testsuite/gdb.base/display.exp
new file mode 100644
index 00000000000..f5c2641226d
--- /dev/null
+++ b/gdb/testsuite/gdb.base/display.exp
@@ -0,0 +1,147 @@
+# Copyright (C) 1997, 1998
+# Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# display.exp Test display commands
+# Also do some printing stuff for coverage's sake.
+#
+if $tracelevel then {
+ strace $tracelevel
+}
+
+set testfile display
+set srcfile ${srcdir}/${subdir}/${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+
+
+
+if { [gdb_compile "${srcfile}" "${binfile}" executable {debug additional_flags=-w}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+if [target_info exists gdb_stub] {
+ gdb_step_for_stub;
+}
+
+
+# use this to debug:
+#log_user 1
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+# Ok, on to real life
+#
+gdb_test "b main" ".*Breakpoint 1.*" "break main"
+gdb_test "r" ".*Breakpoint 1, main.*" "get to main"
+gdb_test "b 14" ".*Breakpoint 2.*" "break do_loops"
+gdb_test "c" ".*Breakpoint 2, do_loops.*" "get to do_loops"
+
+# Create stopping points.
+#
+gdb_test "wat sum" ".*\[Ww\]atchpoint 3: sum.*" "set watch"
+gdb_test "b 19" ".*Breakpoint 4.*" "break 19"
+
+# Create displays for those points
+#
+gdb_test "info disp" ".*There are no auto-display expressions now..*" "inf disp"
+gdb_test "disp i" ".*1: i = 0.*" "display i"
+gdb_test "disp/x j" ".*2: /x j = 0x0.*" "display j"
+gdb_test "disp/i &k" ".*3: x/i &k $hex:.*" "display &k"
+gdb_test "disp/f sum" ".*4: /f sum = 0.*" "display/f sum"
+gdb_test "disp/s &sum" ".*5: x/s &sum $hex.*sum.:.*" "display/s &sum"
+
+# Hit the displays
+#
+gdb_test "c" ".*\[Ww\]atchpoint 3: sum.*\[1-9\]*: x/s &sum.*\[1-9\]*: /f sum = 1.40129846e.45\r\n\[1-9\]*: x/i &k.*\r\n\[1-9\]*: /x j = 0x0\r\n\[1-9\]*: i = 0.*" "first disp"
+gdb_test "c" ".*\[Ww\]atchpoint 3: sum.*\[1-9\]*: x/s &sum.*\[1-9\]*: /f sum = 2.80259693e.45\r\n\[1-9\]*: x/i &k.*\r\n\[1-9\]*: /x j = 0x0.*\[1-9\]*: i = 0.*" "second disp"
+
+gdb_test "enab disp 6" ".*No display number 6..*" "catch err"
+gdb_test "disab disp 1" ".*" "disab"
+gdb_test "disab disp 2" ".*" ""
+gdb_test "enab disp 1" ".*" "re-enab"
+gdb_test "enab disp 1" ".*" "re-enab of enab"
+gdb_test "undisp 5" ".*" "undisp"
+gdb_test "i disp" ".*Auto-display expressions now in effect.*y /f sum.*y /1bi &k.*n /x j.*y i.*" "info disp"
+
+gdb_test "c" ".*\[Ww\]atch.*4.20389539e-45.*.*i = 0.*" "next hit"
+
+send_gdb "undisp\n"
+gdb_expect {
+ -re ".*Delete all auto-display expressions.*y or n. $" {
+ send_gdb "y\n"
+ gdb_expect {
+ -re "y\r\n$gdb_prompt $" {
+ pass "undisp all"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "some un-helpful response"
+ }
+ -re ".*Delete all.*$" {
+ fail "re-ask question"
+ }
+ timeout { fail "timeout" }
+ }
+ }
+ -re ".*$gdb_prompt $" {
+ fail "undisp all"
+ }
+ timeout { fail "timeout" }
+}
+
+gdb_test "disab 3" ".*.*" ""
+gdb_test "c" ".*Breakpoint 4.*" "watch off"
+
+# Now the printf tests
+#
+gdb_test "fin" ".*Run till exit.*Value returned is.*= 10.*" "finish"
+gdb_test "s" ".*do_vars.*.*25" ""
+gdb_test "tb 35" ".*Breakpoint 5 a.*" ""
+gdb_test "c" ".*do_vars.*35.*35.*" ""
+
+# Beat on printf a bit
+#
+gdb_test "printf" ".*Argument required.*" ""
+gdb_test "printf %d" ".*Bad format string, missing.*" ""
+gdb_test "printf \"%d" ".*Bad format string, non-terminated.*" ""
+gdb_test "printf \"%d%d\",i" ".*Wrong number of arguments.*" ""
+gdb_test "printf \"\\\\!\\a\\f\\r\\t\\v\\b\"" ".*!.*" ""
+gdb_test "printf \"\"" ".*" "re-set term"
+gdb_test "printf \"\\w\"" ".*Unrecognized escape character.*" ""
+gdb_test "printf \"%d\" j" ".*Invalid argument syntax.*" ""
+
+# play with "p", too
+#
+gdb_test "p/r j" ".*Undefined output format.*" ""
+#gdb_test "x/rx j" ".*Cannot access memory.*" "no error!"
+gdb_test "x/0 j" ".*" "x/0 j"
+gdb_test "p/0 j" ".*Item count other than 1 is meaningless.*" "p/0 j"
+gdb_test "p/s sum" ".*Format letter.*is meaningless.*" " no s"
+gdb_test "p/i sum" ".*Format letter.*is meaningless.*.*" "no i"
+gdb_test "p/a &sum" ".*= 0x.*<sum>.*" ""
+gdb_test "p/a main+1000" ".*= 0x.*<.*>.*" ""
+gdb_test "p/a \\\$pc" ".*= 0x.*<do_vars+.*>.*" ""
+gdb_test "p/a &j" ".*= 0x.*<.*>.*" ""
+gdb_test "p/a &&j" ".*A syntax error.*" ""
+
+# Done!
+#
+gdb_exit
+return 0
diff --git a/gdb/testsuite/gdb.base/dollar.exp b/gdb/testsuite/gdb.base/dollar.exp
new file mode 100644
index 00000000000..50fac6abf04
--- /dev/null
+++ b/gdb/testsuite/gdb.base/dollar.exp
@@ -0,0 +1,128 @@
+# Copyright (C) 1997, 1998 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# GDB tests for names beginning with '$'
+
+# This is aimed at HP-UX systems where a lot of system
+# routines and names begin with '$' or '$$'. GDB 4.16 was
+# unable to deal with these names as they clashed with
+# convenience variables. Wildebeest should accept such
+# names in preference to convenience variables.
+
+# This file was written by Satish Pai <pai@apollo.hp.com>
+# 1997-09-24
+
+if ![ istarget "*-*-hpux*" ] then {
+ return
+}
+
+if $tracelevel then {
+ strace $tracelevel
+ }
+
+#
+# test running programs
+#
+set prms_id 0
+set bug_id 0
+
+set testfile "exprs"
+set srcfile ${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+#source ${binfile}.ci
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+#
+# set it up at a breakpoint so we can play with the variable values
+#
+
+if ![runto_main] then {
+ perror "couldn't run to breakpoint"
+ continue
+}
+
+# Test for millicode routines
+send_gdb "print \$\$dyncall\n"
+gdb_expect {
+ -re "\\$\[0-9\]* = \\{<text variable, no debug info>\\} $hex <>.*$gdb_prompt $" { pass "print \$\$dyncall" }
+ -re "\\$\[0-9\]* = void" { fail "print \$\$dyncall -- interpreted as convenience var" }
+ -re "$gdb_prompt $" { fail "print \$\$dyncall" }
+ timeout { fail "(timeout) print \$\$dyncall" }
+}
+send_gdb "print \$\$dyncall_external\n"
+gdb_expect {
+ -re "\\$\[0-9\]* = \\{<text variable, no debug info>\\} $hex <>.*$gdb_prompt $" { pass "print \$\$dyncall_external" }
+ -re "\\$\[0-9\]* = void" { fail "print \$\$dyncall_external -- interpreted as convenience var" }
+ -re "$gdb_prompt $" { fail "print \$\$dyncall_external" }
+ timeout { fail "(timeout) print \$\$dyncall_external" }
+}
+
+# Set a breakpoint on a millicode routine
+send_gdb "break \$\$dyncall\n"
+gdb_expect {
+ -re "Breakpoint \[0-9\]* at $hex.*$gdb_prompt $" { pass "break \$\$dyncall" }
+ -re "Function.*not defined.*$gdb_prompt $" {fail "break \$\$dyncall -- no \$\$dyncall?" }
+ -re "Convenience variables used in line specs must have integer values\\..*$gdb_prompt $" {
+ fail "break \$\$dyncall -- treated as convenince variable"
+ }
+ -re "$gdb_prompt $" { fail "print break \$\$dyncall" }
+ timeout { fail "(timeout) print break \$\$dyncall" }
+}
+
+# Disassemble $$dyncall
+send_gdb "disassemble \$\$dyncall\n"
+gdb_expect {
+ -re "Dump of assembler code for function.*$gdb_prompt $" { pass "disas \$\$dyncall" }
+ -re "$gdb_prompt $" { fail "disas \$\$dyncall" }
+ timeout { fail "(timeout) disas \$\$dyncall" }
+}
+
+# Try to set $$dyncall like a convenience var.
+send_gdb "set \$\$dyncall = 77\n"
+gdb_expect {
+ -re "Invalid cast.*$gdb_prompt $" { pass "set \$\$dyncall = 77" }
+ -re "$gdb_prompt $" { fail "set \$\$dyncall = 77" }
+ timeout { fail "(timeout) set \$\$dyncall = 77" }
+}
+
+# Try out some other $ name, not millicode
+send_gdb "print \$ARGV\n"
+gdb_expect {
+ -re "\\$\[0-9\]* = \[0-9\]*.*$gdb_prompt $" { pass "print \$ARGV" }
+ -re "\\$\[0-9\]* = void.*$gdb_prompt $" { fail "print \$ARGV (interpreted as convenience var)" }
+ -re "$gdb_prompt $" { fail "print \$ARGV" }
+ timeout { fail "(timeout) print \$ARGV" }
+}
+send_gdb "ptype \$ARGV\n"
+gdb_expect {
+ -re "type = <data variable, no debug info>.*$gdb_prompt $" { pass "ptype \$ARGV" }
+ -re "type = void.*$gdb_prompt $" { fail "ptype \$ARGV (interpreted as convenience var)" }
+ -re "$gdb_prompt $" { fail "ptype \$ARGV" }
+ timeout { fail "(timeout) ptype \$ARGV" }
+}
+
diff --git a/gdb/testsuite/gdb.base/echo.exp b/gdb/testsuite/gdb.base/echo.exp
new file mode 100644
index 00000000000..c8220ff2d65
--- /dev/null
+++ b/gdb/testsuite/gdb.base/echo.exp
@@ -0,0 +1,44 @@
+# Copyright (C) 1988, 1990, 1991, 1992, 1997 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file was written by Rob Savoye. (rob@cygnus.com)
+
+# Crank up gdb.
+gdb_start
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+#
+# test the echo command
+#
+
+# this sets the prms id number. This is the number that will appear
+# on all the output logs.
+# ex: set prms_id 643
+set prms_id 0
+
+# this sets the bug id id. This is the number that will appear
+# on all the output logs. This is optional and if it is not set
+# it will appear on all output logs as a 0.
+# ex: set bug_id 12
+set bug_id 0
+
+gdb_test "echo Hello world!\\n" "Hello world!" "Echo test"
diff --git a/gdb/testsuite/gdb.base/ena-dis-br.exp b/gdb/testsuite/gdb.base/ena-dis-br.exp
new file mode 100644
index 00000000000..6593d824294
--- /dev/null
+++ b/gdb/testsuite/gdb.base/ena-dis-br.exp
@@ -0,0 +1,525 @@
+# Copyright (C) 1997, 1998 Free Software Foundation, Inc.
+
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+if $tracelevel then {
+ strace $tracelevel
+ }
+
+global usestubs
+
+#
+# test running programs
+#
+set prms_id 0
+set bug_id 0
+
+set testfile "break"
+set srcfile ${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+if ![runto_main] then { fail "enable/disable break tests suppressed" }
+
+# Verify that we can set a breakpoint (the location is irrelevant),
+# then enable it (yes, it's already enabled by default), then hit it.
+#
+send_gdb "break marker1\n"
+gdb_expect {
+ -re "Breakpoint (\[0-9\]*) at .*, line 41.*$gdb_prompt $"\
+ {pass "break marker1"}
+ -re "$gdb_prompt $"\
+ {fail "break marker1"}
+ timeout {fail "(timeout) break marker1"}
+}
+
+send_gdb "enable $expect_out(1,string)\n"
+gdb_expect {
+ -re "$gdb_prompt $"\
+ {pass "enable break marker1"}
+ timeout {fail "(timeout) enable break marker1"}
+}
+
+send_gdb "info break $expect_out(1,string)\n"
+gdb_expect {
+ -re "\[0-9\]*\[ \t\]+breakpoint\[ \t\]+keep\[ \t\]+y.*$gdb_prompt $"\
+ {pass "info break marker1"}
+ -re "$gdb_prompt $"\
+ {fail "info break marker1"}
+ timeout {fail "(timeout) info break marker1"}
+}
+
+send_gdb "continue\n"
+gdb_expect {
+ -re "Breakpoint \[0-9\]*, marker1.*$gdb_prompt $"\
+ {pass "continue to break marker1"}
+ -re "$gdb_prompt $"\
+ {fail "continue to break marker1"}
+ timeout {fail "(timeout) continue to break marker1"}
+}
+
+send_gdb "delete $expect_out(1,string)\n"
+gdb_expect {
+ -re "$gdb_prompt $"\
+ {pass "delete break marker1"}
+ timeout {fail "(timeout) delete break marker1"}
+}
+
+# Verify that we can set a breakpoint to be self-disabling after
+# the first time it triggers.
+#
+send_gdb "break marker2\n"
+gdb_expect {
+ -re "Breakpoint (\[0-9\]*) at .*, line 42.*$gdb_prompt $"\
+ {pass "break marker2"}
+ -re "$gdb_prompt $"\
+ {fail "break marker2"}
+ timeout {fail "(timeout) break marker2"}
+}
+
+send_gdb "enable once $expect_out(1,string)\n"
+gdb_expect {
+ -re "$gdb_prompt $"\
+ {pass "enable once break marker2"}
+ timeout {fail "(timeout) enable once break marker2"}
+}
+
+send_gdb "info break $expect_out(1,string)\n"
+gdb_expect {
+ -re "\[0-9\]*\[ \t\]+breakpoint\[ \t\]+dis\[ \t\]+y.*$gdb_prompt $"\
+ {pass "info auto-disabled break marker2"}
+ -re "$gdb_prompt $"\
+ {fail "info auto-disabled break marker2"}
+ timeout {fail "(timeout) info auto-disabled break marker2"}
+}
+
+send_gdb "continue\n"
+gdb_expect {
+ -re "Breakpoint \[0-9\]*, marker2.*$gdb_prompt $"\
+ {pass "continue to auto-disabled break marker2"}
+ -re "$gdb_prompt $"\
+ {fail "continue to auto-disabled break marker2"}
+ timeout {fail "(timeout) continue to auto-disabled break marker2"}
+}
+
+send_gdb "info break $expect_out(1,string)\n"
+gdb_expect {
+ -re "\[0-9\]*\[ \t\]+breakpoint\[ \t\]+dis\[ \t\]+n.*$gdb_prompt $"\
+ {pass "info auto-disabled break marker2"}
+ -re "$gdb_prompt $"\
+ {fail "info auto-disabled break marker2"}
+ timeout {fail "(timeout) info auto-disabled break marker2"}
+}
+
+# Verify that we don't stop at a disabled breakpoint.
+#
+send_gdb "continue\n"
+gdb_expect {
+ -re ".*Program exited normally.*$gdb_prompt $"\
+ {pass "no stop"}
+ -re "$gdb_prompt $"\
+ {fail "no stop"}
+ timeout {fail "(timeout) no stop"}
+}
+
+send_gdb "run\n"
+gdb_expect {
+ -re "Starting program.*$gdb_prompt $"\
+ {pass "rerun to main"}
+ -re "$gdb_prompt $"\
+ {fail "rerun to main"}
+ timeout {fail "(timeout) rerun to main"}
+}
+
+send_gdb "continue\n"
+gdb_expect {
+ -re ".*Program exited normally.*$gdb_prompt $"\
+ {pass "no stop at auto-disabled break marker2"}
+ -re "$gdb_prompt $"\
+ {fail "no stop at auto-disabled break marker2"}
+ timeout {fail "(timeout) no stop at auto-disabled break marker2"}
+}
+
+# Verify that we can set a breakpoint to be self-deleting after
+# the first time it triggers.
+#
+if ![runto_main] then { fail "enable/disable break tests suppressed" }
+
+send_gdb "break marker3\n"
+gdb_expect {
+ -re "Breakpoint (\[0-9\]*) at .*, line 43.*$gdb_prompt $"\
+ {pass "break marker3"}
+ -re "$gdb_prompt $"\
+ {fail "break marker3"}
+ timeout {fail "(timeout) break marker3"}
+}
+
+send_gdb "enable del $expect_out(1,string)\n"
+gdb_expect {
+ -re "$gdb_prompt $"\
+ {pass "enable del break marker3"}
+ timeout {fail "(timeout) enable del break marker3"}
+}
+
+send_gdb "info break $expect_out(1,string)\n"
+gdb_expect {
+ -re "\[0-9\]*\[ \t\]+breakpoint\[ \t\]+del\[ \t\]+y.*$gdb_prompt $"\
+ {pass "info auto-deleted break marker2"}
+ -re "$gdb_prompt $"\
+ {fail "info auto-deleted break marker2"}
+ timeout {fail "(timeout) info auto-deleted break marker2"}
+}
+
+send_gdb "continue\n"
+gdb_expect {
+ -re ".*marker3 .*:43.*$gdb_prompt $"\
+ {pass "continue to auto-deleted break marker3"}
+ -re "Breakpoint \[0-9\]*, marker3.*$gdb_prompt $"\
+ {fail "continue to auto-deleted break marker3"}
+ -re "$gdb_prompt $"\
+ {fail "continue to auto-deleted break marker3"}
+ timeout {fail "(timeout) continue to break marker3"}
+}
+
+send_gdb "info break $expect_out(1,string)\n"
+gdb_expect {
+ -re ".*No breakpoint or watchpoint number.*$gdb_prompt $"\
+ {pass "info auto-deleted break marker3"}
+ -re "\[0-9\]*\[ \t\]+breakpoint\[ \t\].*$gdb_prompt $"\
+ {fail "info auto-deleted break marker3"}
+ -re "$gdb_prompt $"\
+ {fail "info auto-deleted break marker3"}
+ timeout {fail "(timeout) info auto-deleted break marker3"}
+}
+
+# Verify that we can set a breakpoint and manually disable it (we've
+# already proven that disabled bp's don't trigger).
+#
+send_gdb "break marker4\n"
+gdb_expect {
+ -re "Breakpoint (\[0-9\]*) at .*, line 44.*$gdb_prompt $"\
+ {pass "break marker4"}
+ -re "$gdb_prompt $"\
+ {fail "break marker4"}
+ timeout {fail "(timeout) break marker4"}
+}
+
+send_gdb "disable $expect_out(1,string)\n"
+gdb_expect {
+ -re "$gdb_prompt $"\
+ {pass "disable break marker4"}
+ timeout {fail "(timeout) disable break marker4"}
+}
+
+send_gdb "info break $expect_out(1,string)\n"
+gdb_expect {
+ -re "\[0-9\]*\[ \t\]+breakpoint\[ \t\]+keep\[ \t\]+n.*$gdb_prompt $"\
+ {pass "info break marker4"}
+ -re "$gdb_prompt $"\
+ {fail "info break marker4"}
+ timeout {fail "(timeout) info break marker4"}
+}
+
+# Verify that we can set a breakpoint with an ignore count N, which
+# should cause the next N triggers of the bp to be ignored. (This is
+# a flavor of enablement/disablement, after all.)
+#
+if ![runto_main] then { fail "enable/disable break tests suppressed" }
+
+send_gdb "break marker1\n"
+gdb_expect {
+ -re "Breakpoint (\[0-9\]*) at .*, line 41.*$gdb_prompt $"\
+ {pass "break marker1"}
+ -re "$gdb_prompt $"\
+ {fail "break marker1"}
+ timeout {fail "(timeout) break marker1"}
+}
+
+# Verify that an ignore of a non-existent breakpoint is gracefully
+# handled.
+#
+send_gdb "ignore 999 2\n"
+gdb_expect {
+ -re "No breakpoint number 999..*$gdb_prompt $"\
+ {pass "ignore non-existent break"}
+ -re "$gdb_prompt $"\
+ {fail "ignore non-existent break"}
+ timeout {fail "(timeout) ignore non-existent break"}
+}
+
+# Verify that a missing ignore count is gracefully handled.
+#
+send_gdb "ignore $expect_out(1,string) \n"
+gdb_expect {
+ -re "Second argument .specified ignore-count. is missing..*$gdb_prompt $"\
+ {pass "ignore break with missing ignore count"}
+ -re "$gdb_prompt $"\
+ {fail "ignore break with missing ignore count"}
+ timeout {fail "(timeout) ignore break with missing ignore count"}
+}
+
+# Verify that a negative or zero ignore count is handled gracefully
+# (they both are treated the same).
+#
+send_gdb "ignore $expect_out(1,string) -1\n"
+gdb_expect {
+ -re "Will stop next time breakpoint \[0-9\]* is reached..*$gdb_prompt $"\
+ {pass "ignore break marker1 -1"}
+ -re "$gdb_prompt $"\
+ {fail "ignore break marker1 -1"}
+ timeout {fail "(timeout) ignore break marker1 -1"}
+}
+
+send_gdb "ignore $expect_out(1,string) 0\n"
+gdb_expect {
+ -re "Will stop next time breakpoint \[0-9\]* is reached..*$gdb_prompt $"\
+ {pass "ignore break marker1 0"}
+ -re "$gdb_prompt $"\
+ {fail "ignore break marker1 0"}
+ timeout {fail "(timeout) ignore break marker1 0"}
+}
+
+send_gdb "ignore $expect_out(1,string) 1\n"
+gdb_expect {
+ -re "Will ignore next crossing of breakpoint \[0-9\]*.*$gdb_prompt $"\
+ {pass "ignore break marker1"}
+ -re "$gdb_prompt $"\
+ {fail "ignore break marker1"}
+ timeout {fail "(timeout) ignore break marker1"}
+}
+
+send_gdb "info break $expect_out(1,string)\n"
+gdb_expect {
+ -re "\[0-9\]*\[ \t\]+breakpoint\[ \t\]+keep\[ \t\]+y.*ignore next 1 hits.*$gdb_prompt $"\
+ {pass "info ignored break marker1"}
+ -re "$gdb_prompt $"\
+ {fail "info ignored break marker1"}
+ timeout {fail "(timeout) info ignored break marker1"}
+}
+
+send_gdb "continue\n"
+gdb_expect {
+ -re ".*Program exited normally.*$gdb_prompt $"\
+ {pass "no stop at ignored break marker1"}
+ -re "$gdb_prompt $"\
+ {fail "no stop at ignored break marker1"}
+ timeout {fail "(timeout) no stop at ignored break marker1"}
+}
+
+send_gdb "run\n"
+gdb_expect {
+ -re "Starting program.*$gdb_prompt $"\
+ {pass "rerun to main"}
+ -re "$gdb_prompt $"\
+ {fail "rerun to main"}
+ timeout {fail "(timeout) rerun to main"}
+}
+
+send_gdb "continue\n"
+gdb_expect {
+ -re "Breakpoint \[0-9\]*, marker1.*$gdb_prompt $"\
+ {pass "continue to break marker1"}
+ -re "$gdb_prompt $"\
+ {fail "continue to break marker1"}
+ timeout {fail "(timeout) continue to break marker1"}
+}
+
+# Verify that we can specify both an ignore count and an auto-delete.
+#
+if ![runto_main] then { fail "enable/disable break tests suppressed" }
+
+send_gdb "break marker1\n"
+gdb_expect {
+ -re "Breakpoint (\[0-9\]*) at .*, line 41.*$gdb_prompt $"\
+ {pass "break marker1"}
+ -re "$gdb_prompt $"\
+ {fail "break marker1"}
+ timeout {fail "(timeout) break marker1"}
+}
+
+send_gdb "ignore $expect_out(1,string) 1\n"
+gdb_expect {
+ -re "Will ignore next crossing of breakpoint \[0-9\]*.*$gdb_prompt $"\
+ {pass "ignore break marker1"}
+ -re "$gdb_prompt $"\
+ {fail "ignore break marker1"}
+ timeout {fail "(timeout) ignore break marker1"}
+}
+
+send_gdb "enable del $expect_out(1,string)\n"
+gdb_expect {
+ -re "$gdb_prompt $"\
+ {pass "enable del break marker1"}
+ timeout {fail "(timeout) enable del break marker1"}
+}
+
+send_gdb "info break $expect_out(1,string)\n"
+gdb_expect {
+ -re "\[0-9\]*\[ \t\]+breakpoint\[ \t\]+del\[ \t\]+y.*ignore next 1 hits.*$gdb_prompt $"\
+ {pass "info break marker1"}
+ -re "$gdb_prompt $"\
+ {fail "info break marker1"}
+ timeout {fail "(timeout) info break marker2"}
+}
+
+send_gdb "continue\n"
+gdb_expect {
+ -re ".*Program exited normally.*$gdb_prompt $"\
+ {pass "no stop at ignored & auto-deleted break marker1"}
+ -re "$gdb_prompt $"\
+ {fail "no stop at ignored & auto-deleted break marker1"}
+ timeout {fail "(timeout) no stop at ignored & auto-deleted break marker1"}
+}
+
+send_gdb "run\n"
+gdb_expect {
+ -re "Starting program.*$gdb_prompt $"\
+ {pass "rerun to main"}
+ -re "$gdb_prompt $"\
+ {fail "rerun to main"}
+ timeout {fail "(timeout) rerun to main"}
+}
+
+send_gdb "continue\n"
+gdb_expect {
+ -re ".*marker1 .*:41.*$gdb_prompt $"\
+ {pass "continue to ignored & auto-deleted break marker1"}
+ -re "Breakpoint \[0-9\]*, marker1.*$gdb_prompt $"\
+ {fail "continue to ignored & auto-deleted break marker1"}
+ -re "$gdb_prompt $"\
+ {fail "continue to ignored & auto-deleted break marker1"}
+ timeout {fail "(timeout) continue to ignored & auto-deleted break marker1"}
+}
+
+# Verify that a disabled breakpoint's ignore count isn't updated when
+# the bp is encountered.
+#
+if ![runto_main] then { fail "enable/disable break tests suppressed" }
+
+send_gdb "break marker1\n"
+gdb_expect {
+ -re "Breakpoint (\[0-9\]*) at .*, line 41.*$gdb_prompt $"\
+ {pass "break marker1"}
+ -re "$gdb_prompt $"\
+ {fail "break marker1"}
+ timeout {fail "(timeout) break marker1"}
+}
+
+send_gdb "ignore $expect_out(1,string) 10\n"
+gdb_expect {
+ -re "Will ignore next 10 crossings of breakpoint \[0-9\]*.*$gdb_prompt $"\
+ {pass "ignore break marker1"}
+ -re "$gdb_prompt $"\
+ {fail "ignore break marker1"}
+ timeout {fail "(timeout) ignore break marker1"}
+}
+
+send_gdb "disable $expect_out(1,string)\n"
+gdb_expect {
+ -re "$gdb_prompt $"\
+ {pass "disable break marker1"}
+ timeout {fail "(timeout) disable break marker1"}
+}
+
+send_gdb "continue\n"
+gdb_expect {
+ -re ".*Program exited normally.*$gdb_prompt $"\
+ {pass "no stop at ignored & disabled break marker1"}
+ -re "$gdb_prompt $"\
+ {fail "no stop at ignored & disabled break marker1"}
+ timeout {fail "(timeout) no stop at ignored & disabled break marker1"}
+}
+
+send_gdb "run\n"
+gdb_expect {
+ -re "Starting program.*$gdb_prompt $"\
+ {pass "rerun to main"}
+ -re "$gdb_prompt $"\
+ {fail "rerun to main"}
+ timeout {fail "(timeout) rerun to main"}
+}
+
+send_gdb "info break $expect_out(1,string)\n"
+gdb_expect {
+ -re "\[0-9\]*\[ \t\]+breakpoint\[ \t\]+keep\[ \t\]+n.*ignore next 10 hits.*$gdb_prompt $"\
+ {pass "info ignored & disabled break marker1"}
+ -re "$gdb_prompt $"\
+ {fail "info ignored & disabled break marker1"}
+ timeout {fail "(timeout) info ignored & disabled break marker1"}
+}
+
+# Verify that GDB correctly handles the "continue" command with an argument,
+# which is an ignore count to set on the currently stopped-at breakpoint.
+# (Also verify that GDB gracefully handles the case where the inferior
+# isn't stopped at a breakpoint.)
+#
+if ![runto_main] then { fail "enable/disable break tests suppressed" }
+
+send_gdb "break 64\n"
+gdb_expect {
+ -re "Breakpoint \[0-9\]*.*, line 64.*$gdb_prompt $"\
+ {pass "prepare to continue with ignore count"}
+ -re "$gdb_prompt $"\
+ {fail "prepare to continue with ignore count"}
+ timeout {fail "(timeout) prepare to continue with ignore count"}
+}
+send_gdb "continue 2\n"
+gdb_expect {
+ -re "Will ignore next crossing of breakpoint \[0-9\]*. Continuing..*$gdb_prompt $"\
+ {pass "continue with ignore count"}
+ -re "$gdb_prompt $"\
+ {fail "continue with ignore count"}
+ timeout {fail "(timeout) continue with ignore count"}
+}
+
+send_gdb "next\n"
+gdb_expect {
+ -re ".*66\[ \t\]*marker1.*$gdb_prompt $"\
+ {pass "step after continue with ignore count"}
+ -re "$gdb_prompt $"\
+ {fail "step after continue with ignore count"}
+ timeout {fail "(timeout) step after continue with ignore count"}
+}
+
+# ??rehrauer: Huh. This appears to be an actual bug. (No big
+# surprise, since this feature hasn't been tested...) Looks like
+# GDB is currently trying to set the ignore count of bp # -1!
+#
+setup_xfail hppa_*_*
+send_gdb "continue 2\n"
+gdb_expect {
+ -re "Not stopped at any breakpoint; argument ignored..*$gdb_prompt $"\
+ {pass "continue with ignore count, not stopped at bpt"}
+ -re "No breakpoint number -1.*$gdb_prompt $"\
+ {xfail "(DTS'd) continue with ignore count, not stopped at bpt"}
+ -re "$gdb_prompt $"\
+ {fail "continue with ignore count, not stopped at bpt"}
+ timeout {fail "(timeout) step after continue with ignore count, not stopped at bpt"}
+}
+
+gdb_exit
+return 0
diff --git a/gdb/testsuite/gdb.base/ending-run.c b/gdb/testsuite/gdb.base/ending-run.c
new file mode 100644
index 00000000000..56335cf1cd7
--- /dev/null
+++ b/gdb/testsuite/gdb.base/ending-run.c
@@ -0,0 +1,27 @@
+/* Test program for <next-at-end> and
+ * <leaves-core-file-on-quit> bugs.
+ */
+#include <stdio.h>
+
+int callee( x )
+int x;
+{
+ int y = x * x;
+ return (y - 2);
+}
+
+main()
+{
+
+ int *p;
+ int i;
+
+ p = (int *) malloc( 4 );
+
+ for (i = 1; i < 10; i++)
+ {
+ printf( "%d ", callee( i ));
+
+ }
+ printf( " Goodbye!\n" );
+}
diff --git a/gdb/testsuite/gdb.base/ending-run.exp b/gdb/testsuite/gdb.base/ending-run.exp
new file mode 100644
index 00000000000..61b42c75712
--- /dev/null
+++ b/gdb/testsuite/gdb.base/ending-run.exp
@@ -0,0 +1,176 @@
+# Copyright (C) 1997, 1998 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# use this to debug:
+#
+#log_user 1
+
+# ending-run.exp -- Expect script to test ending a test run in gdb
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+set testfile ending-run
+set srcfile ${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+
+remote_exec build "rm -f ${binfile}"
+remote_exec build "rm -f core"
+
+
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+# CHFts23469: Test that you can "clear" a bp set at
+# a line _before_ the routine (which will default to the
+# first line in the routine, which turns out to correspond
+# to the prolog--that's another bug...)
+#
+gdb_test "b 1" ".*Breakpoint.*line 1.*" "bpt at line before routine"
+gdb_test "b 8" ".*Note.*also.*Breakpoint.*2.*" ""
+
+# Set up to go to the next-to-last line of the program
+#
+gdb_test "b 26" ".*Breakpoint.*3.*" ""
+
+# Expect to hit the bp at line "1", but symbolize this
+# as line "8". Then try to clear it--this should work.
+#
+gdb_test "r" ".*Breakpoint.*1.*callee.*8.*" ""
+gdb_test "cle" ".*Deleted breakpoints 2 1.*" "clear worked"
+send_gdb "i b\n"
+gdb_expect {
+ -re ".*breakpoint.*breakpoint.*$gdb_prompt $" { fail "clear bp" }
+ -re ".*3.*main.*26.*$gdb_prompt $" { pass "cleared bp at line before routine" }
+ -re ".*$gdb_prompt $" { fail "info b" }
+}
+
+# Test some other "clear" combinations
+#
+gdb_test "b 1" ".*Breakpoint.*4.*" ""
+gdb_test "b 8" ".*Note.*also.*Breakpoint.*5.*" ""
+gdb_test "cle 8" ".*Deleted breakpoint 5.*" "Only cleared 1 by line"
+
+send_gdb "inf line 8\n"
+gdb_expect {
+ -re ".*address (0x\[0-9a-fA-F]*).*$gdb_prompt $" {
+ set line_eight $expect_out(1,string)
+ gdb_test "b 8" ".*Breakpoint.*6.*" ""
+ gdb_test "cle *$line_eight" ".*Deleted breakpoints 6 4.*" "Clear 2 by address"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "need to fix test for new compile outcome"
+ }
+}
+
+send_gdb "inf line 9\n"
+gdb_expect {
+ -re ".*address (0x\[0-9a-fA-F]*).*$gdb_prompt $" {
+ set line_nine $expect_out(1,string)
+ gdb_test "b 9" ".*Breakpoint.*7.*" ""
+ gdb_test "b *$line_nine" ".*Note.*also.*Breakpoint.*8.*" ""
+ gdb_test "c" ".*Breakpoint.*7.*callee.*9.*" ""
+ gdb_test "cle" ".*Deleted breakpoints 8 7.*" "Clear 2 by default"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "need to fix test for new compile outcome"
+ }
+}
+
+send_gdb "i b\n"
+gdb_expect {
+ -re ".*breakpoint.*breakpoint.*$gdb_prompt $" {
+ fail "didn't clear bps"
+ }
+ -re ".*3.*main.*26.*$gdb_prompt $" {
+ pass "all set to continue"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "missing bp at end"
+ }
+}
+
+
+# See if we can step out with control. The "1 2 3" stuff
+# is output from the program.
+#
+gdb_test "cont" ".*Breakpoint.*26.*" ""
+gdb_test "next" ".*1 2 7 14 23 34 47 62 79 Goodbye!.*27.*" "Step to return"
+
+set old_timeout $timeout
+set timeout 50
+send_gdb "next\n"
+gdb_expect {
+ -re "27.*$gdb_prompt $" {
+ # sometimes we stop at the closing brace, if so, do another next
+ send_gdb "next\n"
+ gdb_expect {
+ -re ".*Unable to find return pc for this frame.*$gdb_prompt $" {
+ fail "Old bug came back!"
+ gdb_test "n" ".*" ""
+ }
+ -re ".*in.*start.*$gdb_prompt $" {
+ pass "step out of main"
+ }
+ timeout { fail "hang or timeout on step at end 2" }
+ }
+ }
+ -re ".*Unable to find return pc for this frame.*$gdb_prompt $" {
+ fail "Old bug came back!"
+ gdb_test "n" ".*" ""
+ }
+ -re ".*in.*start.*$gdb_prompt $" {
+ pass "step out of main"
+ }
+ timeout { fail "hang or timeout on step at end 1" }
+}
+
+gdb_test "n" ".*Single.*Program exited.*" "step to end of run"
+set timeout $old_timeout
+
+gdb_test "n" ".*The program is not being run.*" "don't step after run"
+
+set exec_output [remote_exec host "ls core"]
+
+if [ regexp "core not found" $exec_output] {
+ pass "No core dumped on quit"
+} else {
+ if [ regexp "No such file or directory" $exec_output] {
+ pass "ls: core: No core dumped on quit"
+ } else {
+ remote_exec build "rm -f core"
+ fail "Core dumped on quit"
+ }
+}
+
+#remote_exec build "rm -f ${binfile}"
+return 0
+
+
+
+
diff --git a/gdb/testsuite/gdb.base/environ.exp b/gdb/testsuite/gdb.base/environ.exp
new file mode 100644
index 00000000000..0033917fb06
--- /dev/null
+++ b/gdb/testsuite/gdb.base/environ.exp
@@ -0,0 +1,329 @@
+# Copyright (C) 1997, 1998 Free Software Foundation, Inc.
+
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+if $tracelevel then {
+ strace $tracelevel
+ }
+
+global usestubs
+
+#
+# test running programs
+#
+set prms_id 0
+set bug_id 0
+
+# This test exists solely to exercise the "environment" commands for
+# code-coverage on HP-UX.
+#
+if ![istarget "hppa*-*-hpux*"] then {
+ return
+}
+
+set testfile "break"
+set srcfile ${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+
+
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+if ![runto_main] then { fail "environment command tests suppressed" }
+
+# (No, this is not really related to the environment commands. But it's
+# a convenient place to verify that this command works.)
+#
+send_gdb "info program\n"
+gdb_expect {
+ -re ".*Using the running image of child process \[0-9\]*.\r\nProgram stopped at 0x\[0-9a-fA-F\]*.\r\nIt stopped at breakpoint 1..*$gdb_prompt $"\
+ {pass "info program"}
+ -re "$gdb_prompt $"\
+ {fail "info program"}
+ timeout {fail "(timeout) info program"}
+}
+
+# We don't really care where this step lands, so long as it gets
+# the inferior pushed off the breakpoint it's currently on...
+#
+send_gdb "next\n"
+gdb_expect {
+ -re ".*$gdb_prompt $"\
+ {pass "step before info program"}
+ timeout {fail "(timeout) step before info program"}
+}
+send_gdb "info program\n"
+gdb_expect {
+ -re ".*Using the running image of child process \[0-9\]*.\r\nProgram stopped at 0x\[0-9a-fA-F\]*.\r\nIt stopped after being stepped..*$gdb_prompt $"\
+ {pass "info program after step"}
+ -re "$gdb_prompt $"\
+ {fail "info program after step"}
+ timeout {fail "(timeout) info program after step"}
+}
+
+if ![runto_main] then { fail "environment command tests suppressed" }
+
+send_gdb "delete\n"
+gdb_expect {
+ -re ".*y or n. $"\
+ {send_gdb "y\n"
+ gdb_expect {
+ -re ".*$gdb_prompt $"\
+ {pass "delete breakpoint before info program"}
+ timeout {fail "(timeout) delete breakpoint before info program"}
+ }
+ }
+ -re "$gdb_prompt $"\
+ {fail "delete breakpoint before info program"}
+ timeout {fail "(timeout) delete breakpoint before info program"}
+}
+send_gdb "info program\n"
+gdb_expect {
+ -re ".*Using the running image of child process \[0-9\]*.\r\nProgram stopped at 0x\[0-9a-fA-F\]*.\r\nIt stopped at a breakpoint that has since been deleted..*$gdb_prompt $"\
+ {pass "info program after deleted breakpoint"}
+ -re "$gdb_prompt $"\
+ {fail "info program after deleted breakpoint"}
+ timeout {fail "(timeout) info program after deleted breakpoint"}
+}
+
+# Verify that we can show all currently-set environment variables.
+# (It's a bit hacky, but nonetheless probably safe to check for at
+# least the SHELL variable.)
+#
+# need to increase timeout because of very long output
+set oldtimeout $timeout
+set timeout [expr "$timeout + 300"]
+
+send_gdb "show environment\n"
+gdb_expect {
+ -re ".*SHELL=(\[a-zA-Z0-9\]*).*$gdb_prompt $"\
+ {pass "show environment"}
+ -re "$gdb_prompt $"\
+ {fail "show environment"}
+ timeout {fail "(timeout) show environment"}
+}
+set timeout $oldtimeout
+
+# Verify that we can unset a specific environment variable.
+#
+send_gdb "unset environment EDITOR\n"
+gdb_expect {
+ -re "$gdb_prompt $"\
+ {pass "issue unset environment"}
+ timeout {fail "(timeout) issue unset environment"}
+}
+send_gdb "show environment EDITOR\n"
+gdb_expect {
+ -re "Environment variable \"EDITOR\" not defined.\r\n$gdb_prompt $"\
+ {pass "unset environment"}
+ -re "$gdb_prompt $"\
+ {fail "unset environment"}
+ timeout {fail "(timeout) unset environment"}
+}
+
+# Verify that we can unset all environment variables.
+#
+send_gdb "unset environment\n"
+gdb_expect {
+ -re "Delete all environment variables.*y or n. $"\
+ {send_gdb "y\n"
+ gdb_expect {
+ -re "$gdb_prompt $"\
+ {pass "unset entire environment"}
+ timeout {fail "(timeout) unset entire environment"}
+ }
+ }
+ -re "$gdb_prompt $"\
+ {fail "unset entire environment"}
+ timeout {fail "(timeout) unset entire environment"}
+}
+
+# Verify that we can set a specific environment variable.
+#
+send_gdb "set environment EDITOR emacs\n"
+gdb_expect {
+ -re "$gdb_prompt $"\
+ {pass "issue set environment"}
+ timeout {fail "(timeout) issue set environment"}
+}
+send_gdb "show environment EDITOR\n"
+gdb_expect {
+ -re "EDITOR = emacs\r\n$gdb_prompt $"\
+ {pass "set environment"}
+ -re "$gdb_prompt $"\
+ {fail "set environment"}
+ timeout {fail "(timeout) set environment"}
+}
+
+# Verify that GDB responds gracefully to a request to set environment,
+# with no variable name.
+#
+send_gdb "set environment\n"
+gdb_expect {
+ -re "Argument required .environment variable and value..*$gdb_prompt $"\
+ {pass "set environment without variable disallowed"}
+ -re "$gdb_prompt $"\
+ {fail "set environment without variable disallowed"}
+ timeout {fail "(timeout) set environment without variable disallowed"}
+}
+
+# I'm not sure just what GDB has in mind in explicitly checking
+# for this variant, but since GDB handles it, test it.
+#
+send_gdb "set environment =\n"
+gdb_expect {
+ -re "Argument required .environment variable to set..*$gdb_prompt $"\
+ {pass "set environment equals without variable disallowed"}
+ -re "$gdb_prompt $"\
+ {fail "set environment equals without variable disallowed"}
+ timeout {fail "(timeout) set environment equals without variable disallowed"}
+}
+
+# Setting an environment variable without a value sets it to a NULL
+# value.
+#
+send_gdb "set environment EDITOR\n"
+gdb_expect {
+ -re "Setting environment variable \"EDITOR\" to null value..*$gdb_prompt $"\
+ {pass "issue set environment without variable value"}
+ -re "$gdb_prompt $"\
+ {fail "issue set environment without variable value"}
+ timeout {fail "(timeout) issue set environment without variable value"}
+}
+send_gdb "show environment EDITOR\n"
+gdb_expect {
+ -re "EDITOR = \r\n$gdb_prompt $"\
+ {pass "set environment without variable value"}
+ -re "$gdb_prompt $"\
+ {fail "set environment without variable value"}
+ timeout {fail "(timeout) set environment without variable value"}
+}
+
+# Verify that GDB responds gracefully to an attempt to show a
+# non-existent environment variable. (We hope this variable is
+# undefined!)
+#
+send_gdb "show environment FOOBARBAZGRUNGESPAZBALL\n"
+gdb_expect {
+ -re "Environment variable \"FOOBARBAZGRUNGESPAZBALL\" not defined..*$gdb_prompt $"\
+ {pass "show non-existent environment variable disallowed"}
+ -re "$gdb_prompt $"\
+ {fail "show non-existent environment variable disallowed"}
+ timeout {fail "(timeout) show non-existent environment variable disallowed"}
+}
+
+# Verify that GDB can set an environment variable hitherto undefined.
+#
+send_gdb "set environment FOOBARBAZGRUNGESPAZBALL t\n"
+gdb_expect {
+ -re "$gdb_prompt $"\
+ {pass "issue set environment for previously undefined variable"}
+ timeout {fail "(timeout) issue set environment for previously undefined variable"}
+}
+send_gdb "show environment FOOBARBAZGRUNGESPAZBALL\n"
+gdb_expect {
+ -re "FOOBARBAZGRUNGESPAZBALL = t\r\n$gdb_prompt $"\
+ {pass "set environment for previously undefined variable"}
+ -re "$gdb_prompt $"\
+ {fail "set environment for previously undefined variable"}
+ timeout {fail "(timeout) set environment for previously undefined variable"}
+}
+
+# Verify that GDB can also set an environment variable using the "="
+# syntax.
+#
+send_gdb "set environment FOOBARBAZGRUNGESPAZBALL = t\n"
+gdb_expect {
+ -re "$gdb_prompt $"\
+ {pass "issue set environment with equals"}
+ timeout {fail "(timeout) issue set environment with equals"}
+}
+send_gdb "show environment FOOBARBAZGRUNGESPAZBALL\n"
+gdb_expect {
+ -re "FOOBARBAZGRUNGESPAZBALL = t\r\n$gdb_prompt $"\
+ {pass "set environment with equals"}
+ -re "$gdb_prompt $"\
+ {fail "set environment with equals"}
+ timeout {fail "(timeout) set environment with equals"}
+}
+
+# Verify that GDB can set an environment variable to a value that has
+# an embedded (trailing, in this case) equals.
+#
+send_gdb "set environment FOOBARBAZGRUNGESPAZBALL t=\n"
+gdb_expect {
+ -re "$gdb_prompt $"\
+ {pass "issue set environment with trailing equals"}
+ timeout {fail "(timeout) issue set environment with trailing equals"}
+}
+send_gdb "show environment FOOBARBAZGRUNGESPAZBALL\n"
+gdb_expect {
+ -re "FOOBARBAZGRUNGESPAZBALL = t=\r\n$gdb_prompt $"\
+ {pass "set environment with trailing equals"}
+ -re "$gdb_prompt $"\
+ {fail "set environment with trailing equals"}
+ timeout {fail "(timeout) set environment with trailing equals"}
+}
+
+# Verify that GDB can set an environment variable to a value preceded
+# by whitespace, and that such whitespace is ignored (not included
+# in the set value).
+#
+send_gdb "set environment FOOBARBAZGRUNGESPAZBALL = foo\n"
+gdb_expect {
+ -re "$gdb_prompt $"\
+ {pass "issue set environment with preceding whitespace"}
+ timeout {fail "(timeout) issue set environment with preceding whitespace"}
+}
+send_gdb "show environment FOOBARBAZGRUNGESPAZBALL\n"
+gdb_expect {
+ -re "FOOBARBAZGRUNGESPAZBALL = foo\r\n$gdb_prompt $"\
+ {pass "set environment with preceding whitespace"}
+ -re "$gdb_prompt $"\
+ {fail "set environment with preceding whitespace"}
+ timeout {fail "(timeout) set environment with preceding whitespace"}
+}
+
+# Verify that GDB can manipulate the distinguished PATH variable.
+#
+send_gdb "path /tmp/FOOBARBAZGRUNGESPAZBALL\n"
+gdb_expect {
+ -re ".*Executable and object file path: /tmp/FOOBARBAZGRUNGESPAZBALL.*$gdb_prompt $"\
+ {pass "issue path"}
+ -re "$gdb_prompt $"\
+ {fail "issue path"}
+ timeout {fail "(timeout) issue path"}
+}
+send_gdb "show paths\n"
+gdb_expect {
+ -re "Executable and object file path: /tmp/FOOBARBAZGRUNGESPAZBALL.*$gdb_prompt $"\
+ {pass "show paths"}
+ -re "$gdb_prompt $"\
+ {fail "show paths"}
+ timeout {fail "(timeout) show paths"}
+}
+
+gdb_exit
+return 0
diff --git a/gdb/testsuite/gdb.base/eval-skip.exp b/gdb/testsuite/gdb.base/eval-skip.exp
new file mode 100644
index 00000000000..4e17e611975
--- /dev/null
+++ b/gdb/testsuite/gdb.base/eval-skip.exp
@@ -0,0 +1,352 @@
+# Copyright (C) 1998 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file was written by Elena Zannoni (ezannoni@cygnus.com)
+
+# This file is part of the gdb testsuite
+
+#
+# tests to cover evaluate_subexp_standard with the EVAL_SKIP flag set.
+# this happens for instance when there is short circuit evaluation in the && and ||
+# operators, or in the non returned part of a (x ? y: z) expression.
+# the part that is not evaluated is parsed and evaluated anyway, but with
+# the EVAL_SKIP flag set
+#
+# source file "int-type.c"
+#
+
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+# Check to see if we have an executable to test. If not, then either we
+# haven't tried to compile one, or the compilation failed for some reason.
+# In either case, just notify the user and skip the tests in this file.
+
+set testfile "int-type"
+set srcfile ${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug additional_flags=-w}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+ }
+
+
+
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+
+if ![runto_main] then {
+ perror "couldn't run to breakpoint"
+ continue
+}
+
+gdb_test "set variable x=14" "" "set variable x=14"
+gdb_test "set variable y=2" "" "set variable y=2"
+gdb_test "set variable z=2" "" "set variable z=2"
+gdb_test "set variable w=3" "" "set variable w=3"
+
+
+send_gdb "print (0 && (x+y))\n"
+gdb_expect {
+ -re ".$decimal = 0\r\n$gdb_prompt $" {
+ pass "print value of (0 && (x+y))"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of (0 && (x+y))" }
+ timeout { fail "(timeout) print value of (0 && (x+y))" }
+ }
+
+
+send_gdb "print (0 && (x-y))\n"
+gdb_expect {
+ -re ".$decimal = 0\r\n$gdb_prompt $" {
+ pass "print value of (0 && (x-y))"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of (0 && (x-y))" }
+ timeout { fail "(timeout) print value of (0 && (x-y))" }
+ }
+
+
+send_gdb "print (0 && (x*y))\n"
+gdb_expect {
+ -re ".$decimal = 0\r\n$gdb_prompt $" {
+ pass "print value of (0 && (x*y))"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of (0 && (x*y))" }
+ timeout { fail "(timeout) print value of (0 && (x*y))" }
+ }
+
+
+
+send_gdb "print (0 && (x/y))\n"
+gdb_expect {
+ -re ".$decimal = 0\r\n$gdb_prompt $" {
+ pass "print value of (0 && (x/y))"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of (0 && (x/y))" }
+ timeout { fail "(timeout) print value of (0 && (x/y))" }
+ }
+
+
+send_gdb "print (0 && (x%y))\n"
+gdb_expect {
+ -re ".$decimal = 0\r\n$gdb_prompt $" {
+ pass "print value of (0 && (x%y))"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of (0 && (x%y))" }
+ timeout { fail "(timeout) print value of (0 && (x%y))" }
+ }
+
+
+send_gdb "print (0 && (x&&y))\n"
+gdb_expect {
+ -re ".$decimal = 0\r\n$gdb_prompt $" {
+ pass "print value of (0 && (x&&y))"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of (0 && (x&&y))" }
+ timeout { fail "(timeout) print value of (0 && (x&&y))" }
+ }
+
+
+
+send_gdb "print (0 && (x||y))\n"
+gdb_expect {
+ -re ".$decimal = 0\r\n$gdb_prompt $" {
+ pass "print value of (0 && (x||y))"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of (0 && (x||y))" }
+ timeout { fail "(timeout) print value of (0 && (x||y))" }
+ }
+
+
+
+send_gdb "print (0 && (x&y))\n"
+gdb_expect {
+ -re ".$decimal = 0\r\n$gdb_prompt $" {
+ pass "print value of (0 && (x&y))"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of (0 && (x&y))" }
+ timeout { fail "(timeout) print value of (0 && (x&y))" }
+ }
+
+
+send_gdb "print (0 && (x|y))\n"
+gdb_expect {
+ -re ".$decimal = 0\r\n$gdb_prompt $" {
+ pass "print value of (0 && (x|y))"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of (0 && (x|y))" }
+ timeout { fail "(timeout) print value of (0 && (x|y))" }
+ }
+
+
+send_gdb "print (0 && (x^y))\n"
+gdb_expect {
+ -re ".$decimal = 0\r\n$gdb_prompt $" {
+ pass "print value of (0 && (x^y))"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of (0 && (x^y))" }
+ timeout { fail "(timeout) print value of (0 && (x^y))" }
+ }
+
+
+
+send_gdb "print (0 && (x < y))\n"
+gdb_expect {
+ -re ".$decimal = 0\r\n$gdb_prompt $" {
+ pass "print value of (0 && (x < y))"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of (0 && (x < y))" }
+ timeout { fail "(timeout) print value of (0 && (x < y))" }
+ }
+
+
+send_gdb "print (0 && (x <= y))\n"
+gdb_expect {
+ -re ".$decimal = 0\r\n$gdb_prompt $" {
+ pass "print value of (0 && (x <= y))"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of (0 && (x <= y))" }
+ timeout { fail "(timeout) print value of (0 && (x <= y))" }
+ }
+
+
+
+send_gdb "print (0 && (x>y))\n"
+gdb_expect {
+ -re ".$decimal = 0\r\n$gdb_prompt $" {
+ pass "print value of (0 && (x>y))"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of (0 && (x>y))" }
+ timeout { fail "(timeout) print value of (0 && (x>y))" }
+ }
+
+
+send_gdb "print (0 && (x>=y))\n"
+gdb_expect {
+ -re ".$decimal = 0\r\n$gdb_prompt $" {
+ pass "print value of (0 && (x>=y))"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of (0 && (x>=y))" }
+ timeout { fail "(timeout) print value of (0 && (x>=y))" }
+ }
+
+
+
+send_gdb "print (0 && (x==y))\n"
+gdb_expect {
+ -re ".$decimal = 0\r\n$gdb_prompt $" {
+ pass "print value of (0 && (x==y))"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of (0 && (x==y))" }
+ timeout { fail "(timeout) print value of (0 && (x==y))" }
+ }
+
+
+send_gdb "print (0 && (x!=y))\n"
+gdb_expect {
+ -re ".$decimal = 0\r\n$gdb_prompt $" {
+ pass "print value of (0 && (x!=y))"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of (0 && (x!=y))" }
+ timeout { fail "(timeout) print value of (0 && (x!=y))" }
+ }
+
+
+send_gdb "print (0 && (x<<31))\n"
+gdb_expect {
+ -re ".$decimal = 0\r\n$gdb_prompt $" {
+ pass "print value of (0 && (x<<31))"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of (0 && (x<<31))" }
+ timeout { fail "(timeout) print value of (0 && (x<<31))" }
+ }
+
+
+send_gdb "print (0 && (x>>31))\n"
+gdb_expect {
+ -re ".$decimal = 0\r\n$gdb_prompt $" {
+ pass "print value of (0 && (x>>31))"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of (0 && (x>>31))" }
+ timeout { fail "(timeout) print value of (0 && (x>>31))" }
+ }
+
+
+
+send_gdb "print (0 && (!x))\n"
+gdb_expect {
+ -re ".$decimal = 0\r\n$gdb_prompt $" {
+ pass "print value of (0 && (!x))"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of (0 && (!x))" }
+ timeout { fail "(timeout) print value of (0 && (!x))" }
+ }
+
+
+send_gdb "print (0 && (~x))\n"
+gdb_expect {
+ -re ".$decimal = 0\r\n$gdb_prompt $" {
+ pass "print value of (0 && (~x))"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of (0 && (~x))" }
+ timeout { fail "(timeout) print value of (0 && (~x))" }
+ }
+
+send_gdb "print (0 && (-x))\n"
+gdb_expect {
+ -re ".$decimal = 0\r\n$gdb_prompt $" {
+ pass "print value of (0 && (-x))"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of (0 && (-x))" }
+ timeout { fail "(timeout) print value of (0 && (-x))" }
+ }
+
+
+send_gdb "print (0 && (x++))\n"
+gdb_expect {
+ -re ".$decimal = 0\r\n$gdb_prompt $" {
+ pass "print value of (0 && (x++))"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of (0 && (x++))" }
+ timeout { fail "(timeout) print value of (0 && (x++))" }
+ }
+
+
+send_gdb "print (0 && (++x))\n"
+gdb_expect {
+ -re ".$decimal = 0\r\n$gdb_prompt $" {
+ pass "print value of (0 && (++x))"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of (0 && (++x))" }
+ timeout { fail "(timeout) print value of (0 && (++x))" }
+ }
+
+
+send_gdb "print (0 && (x--))\n"
+gdb_expect {
+ -re ".$decimal = 0\r\n$gdb_prompt $" {
+ pass "print value of (0 && (x--))"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of (0 && (x--))" }
+ timeout { fail "(timeout) print value of (0 && (x--))" }
+ }
+
+
+send_gdb "print (0 && (--x))\n"
+gdb_expect {
+ -re ".$decimal = 0\r\n$gdb_prompt $" {
+ pass "print value of (0 && (--x))"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of (0 && (--x))" }
+ timeout { fail "(timeout) print value of (0 && (--x))" }
+ }
+
+send_gdb "print (0 && (x+=7))\n"
+gdb_expect {
+ -re ".$decimal = 0\r\n$gdb_prompt $" {
+ pass "print value of (0 && (x+=7))"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of (0 && (x+=7))" }
+ timeout { fail "(timeout) print value of (0 && (x+=7))" }
+ }
+
+send_gdb "print (0 && (x=y))\n"
+gdb_expect {
+ -re ".$decimal = 0\r\n$gdb_prompt $" {
+ pass "print value of (0 && (x=y))"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of (0 && (x=y))" }
+ timeout { fail "(timeout) print value of (0 && (x=y))" }
+ }
+
+gdb_exit
+return 0
+
+
+
+
+
+
+
diff --git a/gdb/testsuite/gdb.base/exprs.c b/gdb/testsuite/gdb.base/exprs.c
new file mode 100644
index 00000000000..e5c73512815
--- /dev/null
+++ b/gdb/testsuite/gdb.base/exprs.c
@@ -0,0 +1,253 @@
+main (argc, argv, envp)
+ int argc;
+ char **argv;
+ char **envp;
+{
+ extern void dummy();
+#ifdef usestubs
+ set_debug_traps();
+ breakpoint();
+#endif
+ dummy();
+}
+
+/* We put main() right up front so its line number doesn't keep changing. */
+
+/*
+ * Test file with lots of different types, for testing the
+ * "whatis" command.
+ */
+
+/*
+ * First the basic C types.
+ */
+
+#if !defined (__STDC__) && !defined (_AIX)
+#define signed /**/
+#endif
+
+char v_char;
+signed char v_signed_char;
+unsigned char v_unsigned_char;
+
+short v_short;
+signed short v_signed_short;
+unsigned short v_unsigned_short;
+
+int v_int;
+signed int v_signed_int;
+unsigned int v_unsigned_int;
+
+long v_long;
+signed long v_signed_long;
+unsigned long v_unsigned_long;
+
+float v_float;
+double v_double;
+
+/*
+ * Now some derived types, which are arrays, functions-returning,
+ * pointers, structures, unions, and enumerations.
+ */
+
+/**** arrays *******/
+
+char v_char_array[2];
+signed char v_signed_char_array[2];
+unsigned char v_unsigned_char_array[2];
+
+short v_short_array[2];
+signed short v_signed_short_array[2];
+unsigned short v_unsigned_short_array[2];
+
+int v_int_array[2];
+signed int v_signed_int_array[2];
+unsigned int v_unsigned_int_array[2];
+
+long v_long_array[2];
+signed long v_signed_long_array[2];
+unsigned long v_unsigned_long_array[2];
+
+float v_float_array[2];
+double v_double_array[2];
+
+/**** pointers *******/
+
+char *v_char_pointer;
+signed char *v_signed_char_pointer;
+unsigned char *v_unsigned_char_pointer;
+
+short *v_short_pointer;
+signed short *v_signed_short_pointer;
+unsigned short *v_unsigned_short_pointer;
+
+int *v_int_pointer;
+signed int *v_signed_int_pointer;
+unsigned int *v_unsigned_int_pointer;
+
+long *v_long_pointer;
+signed long *v_signed_long_pointer;
+unsigned long *v_unsigned_long_pointer;
+
+float *v_float_pointer;
+double *v_double_pointer;
+
+/**** structs *******/
+
+struct t_struct {
+ char v_char_member;
+ short v_short_member;
+ int v_int_member;
+ long v_long_member;
+ float v_float_member;
+ double v_double_member;
+} v_struct1;
+
+struct {
+ char v_char_member;
+ short v_short_member;
+ int v_int_member;
+ long v_long_member;
+ float v_float_member;
+ double v_double_member;
+} v_struct2;
+
+/**** unions *******/
+
+union t_union {
+ char v_char_member;
+ short v_short_member;
+ int v_int_member;
+ long v_long_member;
+ float v_float_member;
+ double v_double_member;
+} v_union;
+
+union {
+ char v_char_member;
+ short v_short_member;
+ int v_int_member;
+ long v_long_member;
+ float v_float_member;
+ double v_double_member;
+} v_union2;
+
+/*** Functions returning type ********/
+
+char v_char_func () { return(0); }
+signed char v_signed_char_func () { return (0); }
+unsigned char v_unsigned_char_func () { return (0); }
+
+short v_short_func () { return (0); }
+signed short v_signed_short_func () { return (0); }
+unsigned short v_unsigned_short_func () { return (0); }
+
+int v_int_func () { return (0); }
+signed int v_signed_int_func () { return (0); }
+unsigned int v_unsigned_int_func () { return (0); }
+
+long v_long_func () { return (0); }
+signed long v_signed_long_func () { return (0); }
+unsigned long v_unsigned_long_func () { return (0); }
+
+float v_float_func () { return (0.0); }
+double v_double_func () { return (0.0); }
+
+/**** Some misc more complicated things *******/
+
+struct link {
+ struct link *next;
+#ifdef __STDC__
+ struct link *(*linkfunc) (struct link *this, int flags);
+#else
+ struct link *(*linkfunc) ();
+#endif
+ struct t_struct stuff[1][2][3];
+} *s_link;
+
+union tu_link {
+ struct link *next;
+#ifdef __STDC__
+ struct link *(*linkfunc) (struct link *this, int flags);
+#else
+ struct link *(*linkfunc) ();
+#endif
+ struct t_struct stuff[1][2][3];
+} u_link;
+
+/**** Enumerations *******/
+
+enum colors {red, green, blue} color;
+enum cars {chevy, ford, porsche} clunker;
+
+
+void dummy()
+{
+ /* Some linkers (e.g. on AIX) remove unreferenced variables,
+ so make sure to reference them. */
+ v_char = 0;
+ v_signed_char = 1;
+ v_unsigned_char = 2;
+
+ v_short = 3;
+ v_signed_short = 4;
+ v_unsigned_short = 5;
+
+ v_int = 6;
+ v_signed_int = 7;
+ v_unsigned_int = 8;
+
+ v_long = 9;
+ v_signed_long = 10;
+ v_unsigned_long = 11;
+
+ v_float = 100.0;
+ v_double = 200.0;
+
+
+ v_char_array[0] = v_char;
+ v_signed_char_array[0] = v_signed_char;
+ v_unsigned_char_array[0] = v_unsigned_char;
+
+ v_short_array[0] = v_short;
+ v_signed_short_array[0] = v_signed_short;
+ v_unsigned_short_array[0] = v_unsigned_short;
+
+ v_int_array[0] = v_int;
+ v_signed_int_array[0] = v_signed_int;
+ v_unsigned_int_array[0] = v_unsigned_int;
+
+ v_long_array[0] = v_long;
+ v_signed_long_array[0] = v_signed_long;
+ v_unsigned_long_array[0] = v_unsigned_long;
+
+ v_float_array[0] = v_float;
+ v_double_array[0] = v_double;
+
+ v_char_pointer = &v_char;
+ v_signed_char_pointer = &v_signed_char;
+ v_unsigned_char_pointer = &v_unsigned_char;
+
+ v_short_pointer = &v_short;
+ v_signed_short_pointer = &v_signed_short;
+ v_unsigned_short_pointer = &v_unsigned_short;
+
+ v_int_pointer = &v_int;
+ v_signed_int_pointer = &v_signed_int;
+ v_unsigned_int_pointer = &v_unsigned_int;
+
+ v_long_pointer = &v_long;
+ v_signed_long_pointer = &v_signed_long;
+ v_unsigned_long_pointer = &v_unsigned_long;
+
+ v_float_pointer = &v_float;
+ v_double_pointer = &v_double;
+
+ color = red;
+ clunker = porsche;
+
+ u_link.next = s_link;
+
+ v_struct2.v_int_member = v_struct1.v_int_member;
+ v_union2.v_short_member = v_union.v_short_member;
+}
diff --git a/gdb/testsuite/gdb.base/exprs.exp b/gdb/testsuite/gdb.base/exprs.exp
new file mode 100644
index 00000000000..cdf33dc9435
--- /dev/null
+++ b/gdb/testsuite/gdb.base/exprs.exp
@@ -0,0 +1,222 @@
+# Copyright (C) 1988, 1990, 1991, 1992, 1994, 1997 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file was written by Rob Savoye. (rob@cygnus.com)
+
+if $tracelevel {
+ strace $tracelevel
+}
+
+#
+# test running programs
+#
+set prms_id 0
+set bug_id 0
+
+set testfile "exprs"
+set srcfile ${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+if [get_compiler_info ${binfile}] {
+ return -1;
+}
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+#
+# set it up at a breakpoint so we can play with the variable values
+#
+
+if ![runto_main] then {
+ perror "couldn't run to breakpoint"
+ continue
+}
+
+proc test_expr { args } {
+ if { [llength $args] % 2 } {
+ warning "an even # of arguments should be passed to test_expr"
+ }
+ set last_ent [expr [llength $args] - 1];
+ set testname [lindex $args $last_ent];
+ if [gdb_test [lindex $args 0] "" "$testname (setup)"] {
+ gdb_suppress_tests;
+ }
+ for {set x 1} {$x < $last_ent} {set x [expr $x + 2]} {
+ if [gdb_test [lindex $args $x] [lindex $args [expr $x + 1]] "$testname ([lindex $args $x])"] {
+ gdb_suppress_tests;
+ }
+ }
+ gdb_stop_suppressing_tests;
+}
+#
+# test expressions with "char" types
+#
+test_expr "set variable v_char=127" "print v_char == 0" "\\$\[0-9\]* = 0" "print v_char == 127" "\\$\[0-9\]* = 1" "print char =="
+test_expr "set variable v_char=127" "print v_char != 0" "\\$\[0-9\]* = 1" "print v_char != 127" "\\$\[0-9\]* = 0" "print char !="
+test_expr "set variable v_char=127" "print v_char < 0" "\\$\[0-9\]* = 0" "print v_char < 127" "\\$\[0-9\]* = 0" "print char <"
+test_expr "set variable v_char=127" "print v_char > 0" "\\$\[0-9\]* = 1" "print v_char > 127" "\\$\[0-9\]* = 0" "print char >"
+#
+# test expressions with "signed char" types
+#
+test_expr "set variable v_signed_char=127" "print v_signed_char == 0" "\\$\[0-9\]* = 0" "print v_signed_char == 127" "\\$\[0-9\]* = 1" "print signed char =="
+test_expr "set variable v_signed_char=127" "print v_signed_char != 0" "\\$\[0-9\]* = 1" "print v_signed_char != 127" "\\$\[0-9\]* = 0" "print signed char !="
+test_expr "set variable v_signed_char=127" "print v_signed_char < 0" "\\$\[0-9\]* = 0" "print v_signed_char < 127" "\\$\[0-9\]* = 0" "print signed char <"
+test_expr "set variable v_signed_char=127" "print v_signed_char > 0" "\\$\[0-9\]* = 1" "print v_signed_char > 127" "\\$\[0-9\]* = 0" "print signed char >"
+# make char a minus
+test_expr "set variable v_signed_char=-1" "print v_signed_char == 0" "\\$\[0-9\]* = 0" "print v_signed_char == -1" "\\$\[0-9\]* = 1" "print signed char == (minus)"
+test_expr "set variable v_signed_char=-1" "print v_signed_char != 0" "\\$\[0-9\]* = 1" "print v_signed_char != -1" "\\$\[0-9\]* = 0" "print signed char != (minus)"
+test_expr "set variable v_signed_char=-1" "print v_signed_char < 0" "\\$\[0-9\]* = 1" "print v_signed_char < 127" "\\$\[0-9\]* = 1" "print signed char < (minus)"
+test_expr "set variable v_signed_char=-1" "print v_signed_char > 0" "\\$\[0-9\]* = 0" "print v_signed_char > 127" "\\$\[0-9\]* = 0" "print signed char > (minus)"
+#
+# test expressions with "unsigned char" types
+#
+test_expr "set variable v_unsigned_char=127" "print v_unsigned_char == 0" "\\$\[0-9\]* = 0" "print v_unsigned_char == 127" "\\$\[0-9\]* = 1" "print unsigned char =="
+test_expr "set variable v_unsigned_char=127" "print v_unsigned_char != 0" "\\$\[0-9\]* = 1" "print v_unsigned_char != 127" "\\$\[0-9\]* = 0" "print unsigned char !="
+test_expr "set variable v_unsigned_char=127" "print v_unsigned_char < 0" "\\$\[0-9\]* = 0" "print v_unsigned_char < 127" "\\$\[0-9\]* = 0" "print unsigned char <"
+test_expr "set variable v_unsigned_char=127" "print v_unsigned_char > 0" "\\$\[0-9\]* = 1" "print v_unsigned_char > 127" "\\$\[0-9\]* = 0" "print unsigned char >"
+# make char a minus
+# FIXME: gdb mishandles the cast (unsigned char) on the i960, so I've
+# set up an expected failure for this case.
+setup_xfail "i960-*-*" 1821
+test_expr "set variable v_unsigned_char=~0" "print v_unsigned_char == 0" "\\$\[0-9\]* = 0" "print v_unsigned_char == ~0" "\\$\[0-9\]* = 0" "print v_unsigned_char == (unsigned char)~0" "\\$\[0-9\]* = 1" "print unsigned char == (~0)"
+# FIXME: gdb mishandles the cast (unsigned char) on the i960, so I've
+# set up an expected failure for this case.
+setup_xfail "i960-*-*" 1821
+test_expr "set variable v_unsigned_char=~0" "print v_unsigned_char != 0" "\\$\[0-9\]* = 1" "print v_unsigned_char != (unsigned char)~0" "\\$\[0-9\]* = 0" "print unsigned char != (~0)"
+test_expr "set variable v_unsigned_char=~0" "print v_unsigned_char < 0" "\\$\[0-9\]* = 0" "print v_unsigned_char < 127" "\\$\[0-9\]* = 0" "print unsigned char < (~0)"
+test_expr "set variable v_unsigned_char=~0" "print v_unsigned_char > 0" "\\$\[0-9\]* = 1" "print v_unsigned_char > 127" "\\$\[0-9\]* = 1" "print unsigned char > (~0)"
+#
+# test expressions with "short" types
+#
+test_expr "set variable v_short=0x7FFF" "print v_short == 0" "\\$\[0-9\]* = 0" "print v_short == 0x7FFF" "\\$\[0-9\]* = 1" "print signed short =="
+test_expr "set variable v_short=0x7FFF" "print v_short != 0" "\\$\[0-9\]* = 1" "print v_short != 0x7FFF" "\\$\[0-9\]* = 0" "print signed short !="
+test_expr "set variable v_short=0x7FFF" "print v_short < 0" "\\$\[0-9\]* = 0" "print v_short < 0x7FFF" "\\$\[0-9\]* = 0" "print signed short <"
+test_expr "set variable v_short=0x7FFF" "print v_short > 0" "\\$\[0-9\]* = 1" "print v_short > 0x7FFF" "\\$\[0-9\]* = 0" "print signed short >"
+# make short a minus
+test_expr "set variable v_short=-1" "print v_short == 0" "\\$\[0-9\]* = 0" "print v_short == -1" "\\$\[0-9\]* = 1" "print signed short == (minus)"
+test_expr "set variable v_short=-1" "print v_short != 0" "\\$\[0-9\]* = 1" "print v_short != -1" "\\$\[0-9\]* = 0" "print signed short != (minus)"
+test_expr "set variable v_short=-1" "print v_short < 0" "\\$\[0-9\]* = 1" "print v_short < 0x7FFF" "\\$\[0-9\]* = 1" "print signed short < (minus)"
+test_expr "set variable v_short=-1" "print v_short > 0" "\\$\[0-9\]* = 0" "print v_short > 0x7FFF" "\\$\[0-9\]* = 0" "print signed short > (minus)"
+#
+# test expressions with "signed short" types
+#
+test_expr "set variable v_signed_short=0x7FFF" "print v_signed_short == 0" "\\$\[0-9\]* = 0" "print v_signed_short == 0x7FFF" "\\$\[0-9\]* = 1" "print signed signed short =="
+test_expr "set variable v_signed_short=0x7FFF" "print v_signed_short != 0" "\\$\[0-9\]* = 1" "print v_signed_short != 0x7FFF" "\\$\[0-9\]* = 0" "print signed signed short !="
+test_expr "set variable v_signed_short=0x7FFF" "print v_signed_short < 0" "\\$\[0-9\]* = 0" "print v_signed_short < 0x7FFF" "\\$\[0-9\]* = 0" "print signed signed short <"
+test_expr "set variable v_signed_short=0x7FFF" "print v_signed_short > 0" "\\$\[0-9\]* = 1" "print v_signed_short > 0x7FFF" "\\$\[0-9\]* = 0" "print signed signed short >"
+# make short a minus
+test_expr "set variable v_signed_short=-1" "print v_signed_short == 0" "\\$\[0-9\]* = 0" "print v_signed_short == -1" "\\$\[0-9\]* = 1" "print signed signed short == (minus)"
+test_expr "set variable v_signed_short=-1" "print v_signed_short != 0" "\\$\[0-9\]* = 1" "print v_signed_short != -1" "\\$\[0-9\]* = 0" "print signed signed short != (minus)"
+test_expr "set variable v_signed_short=-1" "print v_signed_short < 0" "\\$\[0-9\]* = 1" "print v_signed_short < 0x7FFF" "\\$\[0-9\]* = 1" "print signed signed short < (minus)"
+test_expr "set variable v_signed_short=-1" "print v_signed_short > 0" "\\$\[0-9\]* = 0" "print v_signed_short > 0x7FFF" "\\$\[0-9\]* = 0" "print signed signed short > (minus)"
+#
+# test expressions with "unsigned short" types
+#
+test_expr "set variable v_unsigned_short=0x7FFF" "print v_unsigned_short == 0" "\\$\[0-9\]* = 0" "print v_unsigned_short == 0x7FFF" "\\$\[0-9\]* = 1" "print unsigned short =="
+test_expr "set variable v_unsigned_short=0x7FFF" "print v_unsigned_short != 0" "\\$\[0-9\]* = 1" "print v_unsigned_short != 0x7FFF" "\\$\[0-9\]* = 0" "print unsigned short !="
+test_expr "set variable v_unsigned_short=0x7FFF" "print v_unsigned_short < 0" "\\$\[0-9\]* = 0" "print v_unsigned_short < 0x7FFF" "\\$\[0-9\]* = 0" "print unsigned short <"
+test_expr "set variable v_unsigned_short=0x7FFF" "print v_unsigned_short > 0" "\\$\[0-9\]* = 1" "print v_unsigned_short > 0x7FFF" "\\$\[0-9\]* = 0" "print unsigned short >"
+# make short a minus
+# note that (unsigned short) ~0 == ~0 iff sizeof(short) == sizeof(int),
+# so we can't test v_unsigned_short != ~0
+test_expr "set variable v_unsigned_short=~0" \
+ "print v_unsigned_short == 0" "\\$\[0-9\]* = 0" \
+ "print v_unsigned_short == (unsigned short)~0" "\\$\[0-9\]* = 1" \
+ "print unsigned short == (~0)"
+test_expr "set variable v_unsigned_short=~0" "print v_unsigned_short != 0" "\\$\[0-9\]* = 1" "print v_unsigned_short != (unsigned short)~0" "\\$\[0-9\]* = 0" "print unsigned short != (~0)"
+test_expr "set variable v_unsigned_short=~0" "print v_unsigned_short < 0" "\\$\[0-9\]* = 0" "print v_unsigned_short < 0x7FFF" "\\$\[0-9\]* = 0" "print unsigned short < (~0)"
+test_expr "set variable v_unsigned_short=~0" "print v_unsigned_short > 0" "\\$\[0-9\]* = 1" "print v_unsigned_short > 0x7FFF" "\\$\[0-9\]* = 1" "print unsigned short > (~0)"
+#
+# test expressions with "int" types
+#
+test_expr "set variable v_int=0x7FFF" "print v_int == 0" "\\$\[0-9\]* = 0" "print v_int == 0x7FFF" "\\$\[0-9\]* = 1" "print signed int =="
+test_expr "set variable v_int=0x7FFF" "print v_int != 0" "\\$\[0-9\]* = 1" "print v_int != 0x7FFF" "\\$\[0-9\]* = 0" "print signed int !="
+test_expr "set variable v_int=0x7FFF" "print v_int < 0" "\\$\[0-9\]* = 0" "print v_int < 0x7FFF" "\\$\[0-9\]* = 0" "print signed int <"
+test_expr "set variable v_int=0x7FFF" "print v_int > 0" "\\$\[0-9\]* = 1" "print v_int > 0x7FFF" "\\$\[0-9\]* = 0" "print signed int >"
+# make int a minus
+test_expr "set variable v_int=-1" "print v_int == 0" "\\$\[0-9\]* = 0" "print v_int == -1" "\\$\[0-9\]* = 1" "print signed int == (minus)"
+test_expr "set variable v_int=-1" "print v_int != 0" "\\$\[0-9\]* = 1" "print v_int != -1" "\\$\[0-9\]* = 0" "print signed int != (minus)"
+test_expr "set variable v_int=-1" "print v_int < 0" "\\$\[0-9\]* = 1" "print v_int < 0x7FFF" "\\$\[0-9\]* = 1" "print signed int < (minus)"
+test_expr "set variable v_int=-1" "print v_int > 0" "\\$\[0-9\]* = 0" "print v_int > 0x7FFF" "\\$\[0-9\]* = 0" "print signed int > (minus)"
+#
+# test expressions with "signed int" types
+#
+test_expr "set variable v_signed_int=0x7FFF" "print v_signed_int == 0" "\\$\[0-9\]* = 0" "print v_signed_int == 0x7FFF" "\\$\[0-9\]* = 1" "print signed signed int =="
+test_expr "set variable v_signed_int=0x7FFF" "print v_signed_int != 0" "\\$\[0-9\]* = 1" "print v_signed_int != 0x7FFF" "\\$\[0-9\]* = 0" "print signed signed int !="
+test_expr "set variable v_signed_int=0x7FFF" "print v_signed_int < 0" "\\$\[0-9\]* = 0" "print v_signed_int < 0x7FFF" "\\$\[0-9\]* = 0" "print signed signed int <"
+test_expr "set variable v_signed_int=0x7FFF" "print v_signed_int > 0" "\\$\[0-9\]* = 1" "print v_signed_int > 0x7FFF" "\\$\[0-9\]* = 0" "print signed signed int >"
+# make int a minus
+test_expr "set variable v_signed_int=-1" "print v_signed_int == 0" "\\$\[0-9\]* = 0" "print v_signed_int == -1" "\\$\[0-9\]* = 1" "print signed signed int == (minus)"
+test_expr "set variable v_signed_int=-1" "print v_signed_int != 0" "\\$\[0-9\]* = 1" "print v_signed_int != -1" "\\$\[0-9\]* = 0" "print signed signed int != (minus)"
+test_expr "set variable v_signed_int=-1" "print v_signed_int < 0" "\\$\[0-9\]* = 1" "print v_signed_int < 0x7FFF" "\\$\[0-9\]* = 1" "print signed signed int < (minus)"
+test_expr "set variable v_signed_int=-1" "print v_signed_int > 0" "\\$\[0-9\]* = 0" "print v_signed_int > 0x7FFF" "\\$\[0-9\]* = 0" "print signed signed int > (minus)"
+#
+# test expressions with "unsigned int" types
+#
+test_expr "set variable v_unsigned_int=0x7FFF" "print v_unsigned_int == 0" "\\$\[0-9\]* = 0" "print v_unsigned_int == 0x7FFF" "\\$\[0-9\]* = 1" "print unsigned int =="
+test_expr "set variable v_unsigned_int=0x7FFF" "print v_unsigned_int != 0" "\\$\[0-9\]* = 1" "print v_unsigned_int != 0x7FFF" "\\$\[0-9\]* = 0" "print unsigned int !="
+test_expr "set variable v_unsigned_int=0x7FFF" "print v_unsigned_int < 0" "\\$\[0-9\]* = 0" "print v_unsigned_int < 0x7FFF" "\\$\[0-9\]* = 0" "print unsigned int <"
+test_expr "set variable v_unsigned_int=0x7FFF" "print v_unsigned_int > 0" "\\$\[0-9\]* = 1" "print v_unsigned_int > 0x7FFF" "\\$\[0-9\]* = 0" "print unsigned int >"
+# make int a minus
+test_expr "set variable v_unsigned_int=~0" "print v_unsigned_int == 0" "\\$\[0-9\]* = 0" "print v_unsigned_int == ~0" "\\$\[0-9\]* = 1" "print v_unsigned_int == (unsigned int)~0" "\\$\[0-9\]* = 1" "print unsigned int == (~0)"
+test_expr "set variable v_unsigned_int=~0" "print v_unsigned_int != 0" "\\$\[0-9\]* = 1" "print v_unsigned_int != (unsigned int)~0" "\\$\[0-9\]* = 0" "print unsigned int != (~0)"
+test_expr "set variable v_unsigned_int=~0" "print v_unsigned_int < 0" "\\$\[0-9\]* = 0" "print v_unsigned_int < 0x7FFF" "\\$\[0-9\]* = 0" "print unsigned int < (~0)"
+test_expr "set variable v_unsigned_int=~0" "print v_unsigned_int > 0" "\\$\[0-9\]* = 1" "print v_unsigned_int > 0x7FFF" "\\$\[0-9\]* = 1" "print unsigned int > (~0)"
+#
+# test expressions with "long" types
+#
+test_expr "set variable v_long=0x7FFF" "print v_long == 0" "\\$\[0-9\]* = 0" "print v_long == 0x7FFF" "\\$\[0-9\]* = 1" "print signed long =="
+test_expr "set variable v_long=0x7FFF" "print v_long != 0" "\\$\[0-9\]* = 1" "print v_long != 0x7FFF" "\\$\[0-9\]* = 0" "print signed long !="
+test_expr "set variable v_long=0x7FFF" "print v_long < 0" "\\$\[0-9\]* = 0" "print v_long < 0x7FFF" "\\$\[0-9\]* = 0" "print signed long <"
+test_expr "set variable v_long=0x7FFF" "print v_long > 0" "\\$\[0-9\]* = 1" "print v_long > 0x7FFF" "\\$\[0-9\]* = 0" "print signed long >"
+# make long a minus
+test_expr "set variable v_long=-1" "print v_long == 0" "\\$\[0-9\]* = 0" "print v_long == -1" "\\$\[0-9\]* = 1" "print signed long == (minus)"
+test_expr "set variable v_long=-1" "print v_long != 0" "\\$\[0-9\]* = 1" "print v_long != -1" "\\$\[0-9\]* = 0" "print signed long != (minus)"
+test_expr "set variable v_long=-1" "print v_long < 0" "\\$\[0-9\]* = 1" "print v_long < 0x7FFF" "\\$\[0-9\]* = 1" "print signed long < (minus)"
+test_expr "set variable v_long=-1" "print v_long > 0" "\\$\[0-9\]* = 0" "print v_long > 0x7FFF" "\\$\[0-9\]* = 0" "print signed long > (minus)"
+#
+# test expressions with "signed long" types
+#
+test_expr "set variable v_signed_long=0x7FFF" "print v_signed_long == 0" "\\$\[0-9\]* = 0" "print v_signed_long == 0x7FFF" "\\$\[0-9\]* = 1" "print signed signed long =="
+test_expr "set variable v_signed_long=0x7FFF" "print v_signed_long != 0" "\\$\[0-9\]* = 1" "print v_signed_long != 0x7FFF" "\\$\[0-9\]* = 0" "print signed signed long !="
+test_expr "set variable v_signed_long=0x7FFF" "print v_signed_long < 0" "\\$\[0-9\]* = 0" "print v_signed_long < 0x7FFF" "\\$\[0-9\]* = 0" "print signed signed long <"
+test_expr "set variable v_signed_long=0x7FFF" "print v_signed_long > 0" "\\$\[0-9\]* = 1" "print v_signed_long > 0x7FFF" "\\$\[0-9\]* = 0" "print signed signed long >"
+# make long a minus
+test_expr "set variable v_signed_long=-1" "print v_signed_long == 0" "\\$\[0-9\]* = 0" "print v_signed_long == -1" "\\$\[0-9\]* = 1" "print signed signed long == (minus)"
+test_expr "set variable v_signed_long=-1" "print v_signed_long != 0" "\\$\[0-9\]* = 1" "print v_signed_long != -1" "\\$\[0-9\]* = 0" "print signed signed long != (minus)"
+test_expr "set variable v_signed_long=-1" "print v_signed_long < 0" "\\$\[0-9\]* = 1" "print v_signed_long < 0x7FFF" "\\$\[0-9\]* = 1" "print signed signed long < (minus)"
+test_expr "set variable v_signed_long=-1" "print v_signed_long > 0" "\\$\[0-9\]* = 0" "print v_signed_long > 0x7FFF" "\\$\[0-9\]* = 0" "print signed signed long > (minus)"
+#
+# test expressions with "unsigned long" types
+#
+test_expr "set variable v_unsigned_long=0x7FFF" "print v_unsigned_long == 0" "\\$\[0-9\]* = 0" "print v_unsigned_long == 0x7FFF" "\\$\[0-9\]* = 1" "print unsigned long =="
+test_expr "set variable v_unsigned_long=0x7FFF" "print v_unsigned_long != 0" "\\$\[0-9\]* = 1" "print v_unsigned_long != 0x7FFF" "\\$\[0-9\]* = 0" "print unsigned long !="
+test_expr "set variable v_unsigned_long=0x7FFF" "print v_unsigned_long < 0" "\\$\[0-9\]* = 0" "print v_unsigned_long < 0x7FFF" "\\$\[0-9\]* = 0" "print unsigned long <"
+test_expr "set variable v_unsigned_long=0x7FFF" "print v_unsigned_long > 0" "\\$\[0-9\]* = 1" "print v_unsigned_long > 0x7FFF" "\\$\[0-9\]* = 0" "print unsigned long >"
+# make long a minus
+test_expr "set variable v_unsigned_long=~0" "print v_unsigned_long == 0" "\\$\[0-9\]* = 0" "print v_unsigned_long == ~0" "\\$\[0-9\]* = 1" "print v_unsigned_long == (unsigned long)~0" "\\$\[0-9\]* = 1" "print unsigned long == (~0)"
+test_expr "set variable v_unsigned_long=~0" "print v_unsigned_long != 0" "\\$\[0-9\]* = 1" "print v_unsigned_long != (unsigned long)~0" "\\$\[0-9\]* = 0" "print unsigned long != (~0)"
+test_expr "set variable v_unsigned_long=~0" "print v_unsigned_long < 0" "\\$\[0-9\]* = 0" "print v_unsigned_long < 0x7FFF" "\\$\[0-9\]* = 0" "print unsigned long < (~0)"
+test_expr "set variable v_unsigned_long=~0" "print v_unsigned_long > 0" "\\$\[0-9\]* = 1" "print v_unsigned_long > 0x7FFF" "\\$\[0-9\]* = 1" "print unsigned long > (~0)"
diff --git a/gdb/testsuite/gdb.base/foo.c b/gdb/testsuite/gdb.base/foo.c
new file mode 100644
index 00000000000..ada9cf471ee
--- /dev/null
+++ b/gdb/testsuite/gdb.base/foo.c
@@ -0,0 +1,9 @@
+static int foox __attribute__ ((section (".data00"))) = 'f' + 'o' + 'o';
+
+int foo (int x)
+{
+ if (x)
+ return foox;
+ else
+ return 0;
+}
diff --git a/gdb/testsuite/gdb.base/funcargs.c b/gdb/testsuite/gdb.base/funcargs.c
new file mode 100644
index 00000000000..ead67e551ee
--- /dev/null
+++ b/gdb/testsuite/gdb.base/funcargs.c
@@ -0,0 +1,582 @@
+/* Test passing of arguments to functions. Use various sorts of arguments,
+ including basic types, pointers to those types, structures, lots of
+ args, etc, in various combinations. */
+
+/* AIX requires this to be the first thing in the file. */
+#ifdef __GNUC__
+# define alloca __builtin_alloca
+# define HAVE_STACK_ALLOCA 1
+#else /* not __GNUC__ */
+# ifdef _AIX
+ #pragma alloca
+# define HAVE_STACK_ALLOCA 1
+# else /* Not AIX */
+# ifdef sparc
+# include <alloca.h>
+# define HAVE_STACK_ALLOCA 1
+# ifdef __STDC__
+ void *alloca ();
+# else
+ char *alloca ();
+# endif /* __STDC__ */
+# endif /* sparc */
+# endif /* Not AIX */
+#endif /* not __GNUC__ */
+
+char c = 'a';
+char *cp = &c;
+
+unsigned char uc = 'b';
+unsigned char *ucp = &uc;
+
+short s = 1;
+short *sp = &s;
+
+unsigned short us = 6;
+unsigned short *usp = &us;
+
+int i = 2;
+int *ip = &i;
+
+unsigned int ui = 7;
+unsigned int *uip = &ui;
+
+long l = 3;
+long *lp = &l;
+
+unsigned long ul = 8;
+unsigned long *ulp = &ul;
+
+float f = 4.0;
+float *fp = &f;
+
+double d = 5.0;
+double *dp = &d;
+
+struct stag {
+ int s1;
+ int s2;
+} st = { 101, 102 };
+struct stag *stp = &st;
+
+union utag {
+ int u1;
+ long u2;
+} un;
+union utag *unp = &un;
+
+char carray[] = {'a', 'n', ' ', 'a', 'r', 'r', 'a', 'y', '\0'};
+
+
+/* Test various permutations and interleaving of integral arguments */
+
+
+call0a (c, s, i, l)
+char c; short s; int i; long l;
+{
+ c = 'a';
+ s = 5;
+ i = 6;
+ l = 7;
+}
+
+call0b (s, i, l, c)
+short s; int i; long l; char c;
+{
+ s = 6; i = 7; l = 8; c = 'j';
+}
+
+call0c (i, l, c, s)
+int i; long l; char c; short s;
+{
+ i = 3; l = 4; c = 'k'; s = 5;
+}
+
+call0d (l, c, s, i)
+long l; char c; short s; int i;
+{
+ l = 7; c = 'z'; s = 8; i = 9;
+}
+
+call0e (c1, l, c2, i, c3, s, c4, c5)
+char c1; long l; char c2; int i; char c3; short s; char c4; char c5;
+{
+ c1 = 'a'; l = 5; c2 = 'b'; i = 7; c3 = 'c'; s = 7; c4 = 'f'; c5 = 'g';
+}
+
+
+/* Test various permutations and interleaving of unsigned integral arguments */
+
+
+call1a (uc, us, ui, ul)
+unsigned char uc; unsigned short us; unsigned int ui; unsigned long ul;
+{
+ uc = 5; us = 6; ui = 7; ul = 8;
+}
+
+call1b (us, ui, ul, uc)
+unsigned short us; unsigned int ui; unsigned long ul; unsigned char uc;
+{
+ uc = 5; us = 6; ui = 7; ul = 8;
+}
+
+call1c (ui, ul, uc, us)
+unsigned int ui; unsigned long ul; unsigned char uc; unsigned short us;
+{
+ uc = 5; us = 6; ui = 7; ul = 8;
+}
+
+call1d (ul, uc, us, ui)
+unsigned long ul; unsigned char uc; unsigned short us; unsigned int ui;
+{
+ uc = 5; us = 6; ui = 7; ul = 8;
+}
+
+call1e (uc1, ul, uc2, ui, uc3, us, uc4, uc5)
+unsigned char uc1; unsigned long ul; unsigned char uc2; unsigned int ui;
+unsigned char uc3; unsigned short us; unsigned char uc4; unsigned char uc5;
+{
+ uc1 = 5; ul = 7; uc2 = 8; ui = 9; uc3 = 10; us = 11; uc4 = 12; uc5 = 55;
+}
+
+/* Test various permutations and interleaving of integral arguments with
+ floating point arguments. */
+
+
+call2a (c, f1, s, d1, i, f2, l, d2)
+char c; float f1; short s; double d1; int i; float f2; long l; double d2;
+{
+ c = 'a'; f1 = 0.0; s = 5; d1 = 0.0; i = 6; f2 = 0.1; l = 7; d2 = 0.2;
+}
+
+call2b (f1, s, d1, i, f2, l, d2, c)
+float f1; short s; double d1; int i; float f2; long l; double d2; char c;
+{
+ c = 'a'; f1 = 0.0; s = 5; d1 = 0.0; i = 6; f2 = 0.1; l = 7; d2 = 0.2;
+}
+
+call2c (s, d1, i, f2, l, d2, c, f1)
+short s; double d1; int i; float f2; long l; double d2; char c; float f1;
+{
+ c = 'a'; f1 = 0.0; s = 5; d1 = 0.0; i = 6; f2 = 0.1; l = 7; d2 = 0.2;
+}
+
+call2d (d1, i, f2, l, d2, c, f1, s)
+double d1; int i; float f2; long l; double d2; char c; float f1; short s;
+{
+ c = 'a'; f1 = 0.0; s = 5; d1 = 0.0; i = 6; f2 = 0.1; l = 7; d2 = 0.2;
+}
+
+call2e (i, f2, l, d2, c, f1, s, d1)
+int i; float f2; long l; double d2; char c; float f1; short s; double d1;
+{
+ c = 'a'; f1 = 0.0; s = 5; d1 = 0.0; i = 6; f2 = 0.1; l = 7; d2 = 0.2;
+}
+
+call2f (f2, l, d2, c, f1, s, d1, i)
+float f2; long l; double d2; char c; float f1; short s; double d1; int i;
+{
+ c = 'a'; f1 = 0.0; s = 5; d1 = 0.0; i = 6; f2 = 0.1; l = 7; d2 = 0.2;
+}
+
+call2g (l, d2, c, f1, s, d1, i, f2)
+long l; double d2; char c; float f1; short s; double d1; int i; float f2;
+{
+ c = 'a'; f1 = 0.0; s = 5; d1 = 0.0; i = 6; f2 = 0.1; l = 7; d2 = 0.2;
+}
+
+call2h (d2, c, f1, s, d1, i, f2, l)
+double d2; char c; float f1; short s; double d1; int i; float f2; long l;
+{
+ c = 'a'; f1 = 0.0; s = 5; d1 = 0.0; i = 6; f2 = 0.1; l = 7; d2 = 0.2;
+}
+
+call2i (c1, f1, c2, c3, d1, c4, c5, c6, f2, s, c7, d2)
+char c1; float f1; char c2; char c3; double d1; char c4; char c5; char c6;
+float f2; short s; char c7; double d2;
+{
+ c1 = 'a'; f1 = 0.0; c2 = 5; d1 = 0.0; c3 = 6; f2 = 0.1; c4 = 7; d2 = 0.2;
+ c5 = 's'; c6 = 'f'; c7 = 'z'; s = 77;
+}
+
+
+/* Test pointers to various integral and floating types. */
+
+
+call3a (cp, sp, ip, lp)
+char *cp; short *sp; int *ip; long *lp;
+{
+ cp = 0; sp = 0; ip = 0; lp = 0;
+}
+
+call3b (ucp, usp, uip, ulp)
+unsigned char *ucp; unsigned short *usp; unsigned int *uip;
+unsigned long *ulp;
+{
+ ucp = 0; usp = 0; uip = 0; ulp = 0;
+}
+
+call3c (fp, dp)
+float *fp; double *dp;
+{
+ fp = 0; dp = 0;
+}
+
+
+/* Test passing structures and unions by reference. */
+
+
+call4a (stp)
+struct stag *stp; {
+stp = 0;}
+
+call4b (unp)
+union utag *unp;
+{
+ unp = 0;
+}
+
+
+/* Test passing structures and unions by value. */
+
+
+call5a (st)
+struct stag st; {st.s1 = 5;}
+
+call5b (un)
+union utag un; {un.u1 = 7;}
+
+
+/* Test shuffling of args */
+
+
+call6a (c, s, i, l, f, d, uc, us, ui, ul)
+char c; short s; int i; long l; float f; double d;
+unsigned char uc; unsigned short us; unsigned int ui; unsigned long ul;
+{
+ c = c;
+ call6b (s, i, l, f, d, uc, us, ui, ul);
+}
+
+call6b (s, i, l, f, d, uc, us, ui, ul)
+short s; int i; long l; float f; double d;
+unsigned char uc; unsigned short us; unsigned int ui; unsigned long ul;
+{
+ s = s;
+ call6c (i, l, f, d, uc, us, ui, ul);
+}
+
+call6c (i, l, f, d, uc, us, ui, ul)
+int i; long l; float f; double d;
+unsigned char uc; unsigned short us; unsigned int ui; unsigned long ul;
+{
+ i = i;
+ call6d (l, f, d, uc, us, ui, ul);
+}
+
+call6d (l, f, d, uc, us, ui, ul)
+long l; float f; double d;
+unsigned char uc; unsigned short us; unsigned int ui; unsigned long ul;
+{
+ l = l;
+ call6e (f, d, uc, us, ui, ul);
+}
+
+call6e (f, d, uc, us, ui, ul)
+float f; double d;
+unsigned char uc; unsigned short us; unsigned int ui; unsigned long ul;
+{
+ f = f;
+ call6f (d, uc, us, ui, ul);
+}
+
+call6f (d, uc, us, ui, ul)
+double d;
+unsigned char uc; unsigned short us; unsigned int ui; unsigned long ul;
+{
+ d = d;
+ call6g (uc, us, ui, ul);
+}
+
+call6g (uc, us, ui, ul)
+unsigned char uc; unsigned short us; unsigned int ui; unsigned long ul;
+{
+ uc = uc;
+ call6h (us, ui, ul);
+}
+
+call6h (us, ui, ul)
+unsigned short us; unsigned int ui; unsigned long ul;
+{
+ us = us;
+ call6i (ui, ul);
+}
+
+call6i (ui, ul)
+unsigned int ui; unsigned long ul;
+{
+ ui = ui;
+ call6j (ul);
+}
+
+call6j (ul)
+unsigned long ul;
+{
+ ul = ul;
+ call6k ();
+}
+
+call6k ()
+{
+}
+
+
+/* Test shuffling of args, round robin */
+
+
+call7a (c, i, s, l, f, uc, d, us, ul, ui)
+char c; int i; short s; long l; float f; unsigned char uc; double d; unsigned short us; unsigned long ul; unsigned int ui;
+{
+ call7b (i, s, l, f, uc, d, us, ul, ui, c);
+}
+
+call7b (i, s, l, f, uc, d, us, ul, ui, c)
+int i; short s; long l; float f; unsigned char uc; double d; unsigned short us; unsigned long ul; unsigned int ui; char c;
+{
+ call7c (s, l, f, uc, d, us, ul, ui, c, i);
+}
+
+call7c (s, l, f, uc, d, us, ul, ui, c, i)
+short s; long l; float f; unsigned char uc; double d; unsigned short us; unsigned long ul; unsigned int ui; char c; int i;
+{
+ call7d (l, f, uc, d, us, ul, ui, c, i, s);
+}
+
+call7d (l, f, uc, d, us, ul, ui, c, i, s)
+long l; float f; unsigned char uc; double d; unsigned short us; unsigned long ul; unsigned int ui; char c; int i; short s;
+{
+ call7e (f, uc, d, us, ul, ui, c, i, s, l);
+}
+
+call7e (f, uc, d, us, ul, ui, c, i, s, l)
+float f; unsigned char uc; double d; unsigned short us; unsigned long ul; unsigned int ui; char c; int i; short s; long l;
+{
+ call7f (uc, d, us, ul, ui, c, i, s, l, f);
+}
+
+call7f (uc, d, us, ul, ui, c, i, s, l, f)
+unsigned char uc; double d; unsigned short us; unsigned long ul; unsigned int ui; char c; int i; short s; long l; float f;
+{
+ call7g (d, us, ul, ui, c, i, s, l, f, uc);
+}
+
+call7g (d, us, ul, ui, c, i, s, l, f, uc)
+double d; unsigned short us; unsigned long ul; unsigned int ui; char c; int i; short s; long l; float f; unsigned char uc;
+{
+ call7h (us, ul, ui, c, i, s, l, f, uc, d);
+}
+
+call7h (us, ul, ui, c, i, s, l, f, uc, d)
+unsigned short us; unsigned long ul; unsigned int ui; char c; int i; short s; long l; float f; unsigned char uc; double d;
+{
+ call7i (ul, ui, c, i, s, l, f, uc, d, us);
+}
+
+call7i (ul, ui, c, i, s, l, f, uc, d, us)
+unsigned long ul; unsigned int ui; char c; int i; short s; long l; float f; unsigned char uc; double d; unsigned short us;
+{
+ call7j (ui, c, i, s, l, f, uc, d, us, ul);
+}
+
+call7j (ui, c, i, s, l, f, uc, d, us, ul)
+unsigned int ui; char c; int i; short s; long l; float f; unsigned char uc; double d; unsigned short us; unsigned long ul;
+{
+ call7k (c, i, s, l, f, uc, d, us, ul, ui);
+}
+
+call7k (c, i, s, l, f, uc, d, us, ul, ui)
+char c; int i; short s; long l; float f; unsigned char uc; double d; unsigned short us; unsigned long ul; unsigned int ui;
+{
+ c = 'a'; i = 7; s = 8; l = 7; f = 0.3; uc = 44; d = 0.44; us = 77;
+ ul = 43; ui = 33;
+}
+
+
+/* Test printing of structures passed as arguments to recursive functions. */
+
+
+typedef struct s
+{
+ short s;
+ int i;
+ long l;
+} SVAL;
+
+hitbottom ()
+{
+}
+
+void recurse (a, depth)
+SVAL a;
+int depth;
+{
+ a.s = a.i = a.l = --depth;
+ if (depth == 0)
+ hitbottom ();
+ else
+ recurse (a, depth);
+}
+
+test_struct_args ()
+{
+ SVAL s; s.s = 5; s.i = 5; s.l = 5;
+
+ recurse (s, 5);
+}
+
+/* On various machines (pa, 29k, and rs/6000, at least), a function which
+ calls alloca may do things differently with respect to frames. So give
+ it a try. */
+
+int
+localvars_after_alloca (c, s, i, l)
+ char c;
+ short s;
+ int i;
+ long l;
+{
+#ifdef HAVE_STACK_ALLOCA
+ /* No need to use the alloca.c alloca-on-top-of-malloc; it doesn't
+ test what we are looking for, so if we don't have an alloca which
+ allocates on the stack, just don't bother to call alloca at all. */
+
+ char *z = alloca (s + 50);
+#endif
+ c = 'a';
+ s = 5;
+ i = 6;
+ l = 7;
+}
+
+void
+call_after_alloca_subr (c, s, i, l, uc, us, ui, ul)
+char c; int i; short s; long l; unsigned char uc; unsigned short us; unsigned long ul; unsigned int ui;
+{
+ c = 'a';
+ i = 7; s = 8; l = 7; uc = 44; us = 77;
+ ul = 43; ui = 33;
+}
+
+int
+call_after_alloca (c, s, i, l)
+ char c;
+ short s;
+ int i;
+ long l;
+{
+#ifdef HAVE_STACK_ALLOCA
+ /* No need to use the alloca.c alloca-on-top-of-malloc; it doesn't
+ test what we are looking for, so if we don't have an alloca which
+ allocates on the stack, just don't bother to call alloca at all. */
+
+ char *z = alloca (s + 50);
+#endif
+ call_after_alloca_subr (c, s, i, l, 'b', 11, 12, (unsigned long)13);
+}
+
+
+
+/* The point behind this test is the PA will call this indirectly
+ through dyncall. Unlike the indirect calls to call0a, this test
+ will require a trampoline between dyncall and this function on the
+ call path, then another trampoline on between this function and main
+ on the return path. */
+double
+call_with_trampolines (d1)
+double d1;
+{
+ return d1;
+} /* End of call_with_trampolines, this comment is needed by funcargs.exp */
+
+/* Dummy functions which the testsuite can use to run to, etc. */
+
+void
+marker_indirect_call () {}
+
+void
+marker_call_with_trampolines () {}
+
+main ()
+{
+ int (*pointer_to_call0a) () = call0a;
+ double (*pointer_to_call_with_trampolines) () = call_with_trampolines;
+
+#ifdef usestubs
+ set_debug_traps();
+ breakpoint();
+#endif
+ /* Test calling with basic integer types */
+ call0a (c, s, i, l);
+ call0b (s, i, l, c);
+ call0c (i, l, c, s);
+ call0d (l, c, s, i);
+ call0e (c, l, c, i, c, s, c, c);
+
+ /* Test calling with unsigned integer types */
+ call1a (uc, us, ui, ul);
+ call1b (us, ui, ul, uc);
+ call1c (ui, ul, uc, us);
+ call1d (ul, uc, us, ui);
+ call1e (uc, ul, uc, ui, uc, us, uc, uc);
+
+ /* Test calling with integral types mixed with floating point types */
+ call2a (c, f, s, d, i, f, l, d);
+ call2b (f, s, d, i, f, l, d, c);
+ call2c (s, d, i, f, l, d, c, f);
+ call2d (d, i, f, l, d, c, f, s);
+ call2e (i, f, l, d, c, f, s, d);
+ call2f (f, l, d, c, f, s, d, i);
+ call2g (l, d, c, f, s, d, i, f);
+ call2h (d, c, f, s, d, i, f, l);
+ call2i (c, f, c, c, d, c, c, c, f, s, c, d);;
+
+ /* Test dereferencing pointers to various integral and floating types */
+
+ call3a (cp, sp, ip, lp);
+ call3b (ucp, usp, uip, ulp);
+ call3c (fp, dp);
+
+ /* Test dereferencing pointers to structs and unions */
+
+ call4a (stp);
+ un.u1 = 1;
+ call4b (unp);
+
+ /* Test calling with structures and unions. */
+
+ call5a (st);
+ un.u1 = 2;
+ call5b (un);
+
+ /* Test shuffling of args */
+
+ call6a (c, s, i, l, f, d, uc, us, ui, ul);
+ call7a (c, i, s, l, f, uc, d, us, ul, ui);
+
+ /* Test passing structures recursively. */
+
+ test_struct_args ();
+
+ localvars_after_alloca (c, s, i, l);
+
+ call_after_alloca (c, s, i, l);
+
+ /* This is for localvars_in_indirect_call. */
+ marker_indirect_call ();
+ /* The comment on the following two lines is used by funcargs.exp,
+ don't change it. */
+ (*pointer_to_call0a) (c, s, i, l); /* First step into call0a. */
+ (*pointer_to_call0a) (c, s, i, l); /* Second step into call0a. */
+ marker_call_with_trampolines ();
+ (*pointer_to_call_with_trampolines) (d); /* Test multiple trampolines. */
+}
diff --git a/gdb/testsuite/gdb.base/funcargs.exp b/gdb/testsuite/gdb.base/funcargs.exp
new file mode 100644
index 00000000000..e6245dcfce5
--- /dev/null
+++ b/gdb/testsuite/gdb.base/funcargs.exp
@@ -0,0 +1,1017 @@
+# Copyright (C) 1992, 1994, 1995, 1997 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file was written by Fred Fish. (fnf@cygnus.com)
+
+if $tracelevel {
+ strace $tracelevel
+}
+
+set prms_id 0
+set bug_id 0
+
+set testfile "funcargs"
+set srcfile ${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+# Create and source the file that provides information about the compiler
+# used to compile the test case.
+if [get_compiler_info ${binfile}] {
+ return -1;
+}
+
+#
+# Locate actual args; integral types.
+#
+
+proc integral_args {} {
+ global gdb_prompt
+ global det_file
+ global gcc_compiled
+
+ delete_breakpoints
+
+ gdb_breakpoint call0a
+ gdb_breakpoint call0b
+ gdb_breakpoint call0c
+ gdb_breakpoint call0d
+ gdb_breakpoint call0e
+
+ # Run; should stop at call0a and print actual arguments.
+ # The a29k fails all of these tests, perhaps because the prologue
+ # code is broken.
+ setup_xfail "a29k-*-udi"
+ if {!$gcc_compiled} then { setup_xfail "rs6000-*-*" }
+ gdb_run_cmd
+ gdb_expect {
+ -re ".* call0a \\(c=97 'a', s=1, i=2, l=3\\) .*$gdb_prompt $" {
+ pass "run to call0a"
+ }
+ -re "$gdb_prompt $" { fail "run to call0a" ; gdb_suppress_tests }
+ timeout { fail "(timeout) run to call0a" ; gdb_suppress_tests }
+ }
+
+ # Print each arg as a double check to see if we can print
+ # them here as well as with backtrace.
+ gdb_test "print c" ".* = 97 'a'" "print c after run to call0a"
+ gdb_test "print s" ".* = 1" "print s after run to call0a"
+ gdb_test "print i" ".* = 2" "print i after run to call0a"
+ gdb_test "print l " ".* = 3" "print l after run to call0a"
+
+ # Continue; should stop at call0b and print actual arguments.
+ if [gdb_test "cont" ".* call0b \\(s=1, i=2, l=3, c=97 'a'\\) .*" "continue to call0b"] {
+ gdb_suppress_tests;
+ }
+
+ # Continue; should stop at call0c and print actual arguments.
+ if [gdb_test "cont" ".* call0c \\(i=2, l=3, c=97 'a', s=1\\) .*" "continue to call0c"] {
+ gdb_suppress_tests;
+ }
+
+ # Continue; should stop at call0d and print actual arguments.
+ if [gdb_test "cont" ".* call0d \\(l=3, c=97 'a', s=1, i=2\\) .*" "continue to call0d";] {
+ gdb_suppress_tests;
+ }
+
+ # Continue; should stop at call0e and print actual arguments.
+ if [gdb_test "cont" ".* call0e \\(c1=97 'a', l=3, c2=97 'a', i=2, c3=97 'a', s=1, c4=97 'a', c5=97 'a'\\) .*" "continue to call0e" ] {
+ gdb_suppress_tests;
+ }
+ gdb_stop_suppressing_tests;
+}
+
+#
+# Locate actual args; unsigned integral types.
+#
+
+proc unsigned_integral_args {} {
+ global gdb_prompt
+ global det_file
+ global gcc_compiled
+
+ delete_breakpoints
+
+ gdb_breakpoint call1a;
+ gdb_breakpoint call1b;
+ gdb_breakpoint call1c;
+ gdb_breakpoint call1d;
+ gdb_breakpoint call1e;
+
+ # Run; should stop at call1a and print actual arguments.
+ # The a29k fails all of these tests, perhaps because the prologue
+ # code is broken.
+ setup_xfail "a29k-*-udi"
+ if {!$gcc_compiled} then { setup_xfail "rs6000-*-*" }
+ gdb_run_cmd
+ gdb_expect {
+ -re ".* call1a \\(uc=98 'b', us=6, ui=7, ul=8\\) .*$gdb_prompt $" {
+ pass "run to call1a"
+ }
+ -re "$gdb_prompt $" { fail "run to call1a" ; gdb_suppress_tests; }
+ timeout { fail "(timeout) run to call1a" ; gdb_suppress_tests; }
+ }
+
+ # Print each arg as a double check to see if we can print
+ # them here as well as with backtrace.
+ gdb_test "print uc" ".* = 98 'b'"
+ gdb_test "print us" ".* = 6"
+ gdb_test "print ui" ".* = 7"
+ gdb_test "print ul" ".* = 8"
+
+ # Continue; should stop at call1b and print actual arguments.
+ if [gdb_test "cont" ".* call1b \\(us=6, ui=7, ul=8, uc=98 'b'\\) .*" "continue to call1b"] {
+ gdb_suppress_tests;
+ }
+
+ # Continue; should stop at call1c and print actual arguments.
+ if [gdb_test "cont" ".* call1c \\(ui=7, ul=8, uc=98 'b', us=6\\) .*" "continue to call1c"] {
+ gdb_suppress_tests;
+ }
+
+ # Continue; should stop at call1d and print actual arguments.
+ if [gdb_test "cont" ".* call1d \\(ul=8, uc=98 'b', us=6, ui=7\\) .*" "continue to call1d"] {
+ gdb_suppress_tests;
+ }
+
+ # Continue; should stop at call1e and print actual arguments.
+ if [gdb_test "cont" ".* call1e \\(uc1=98 'b', ul=8, uc2=98 'b', ui=7, uc3=98 'b', us=6, uc4=98 'b', uc5=98 'b'\\) .*" "continue to call1e"] {
+ gdb_suppress_tests;
+ }
+ gdb_stop_suppressing_tests;
+}
+
+#
+# Locate actual args; integrals mixed with floating point.
+#
+
+proc float_and_integral_args {} {
+ global gdb_prompt
+ global det_file
+ global gcc_compiled
+
+ delete_breakpoints
+
+ gdb_breakpoint call2a
+ gdb_breakpoint call2b
+ gdb_breakpoint call2c
+ gdb_breakpoint call2d
+ gdb_breakpoint call2e
+ gdb_breakpoint call2f
+ gdb_breakpoint call2g
+ gdb_breakpoint call2h
+
+ # Run; should stop at call2a and print actual arguments.
+
+ setup_xfail "i960-*-*" 1813
+ # The a29k fails all of these tests, perhaps because the prologue
+ # code is broken.
+ setup_xfail "a29k-*-udi"
+ if {!$gcc_compiled} then { setup_xfail "rs6000-*-*" "mips-sgi-irix5*" }
+ gdb_run_cmd
+ gdb_expect {
+ -re ".* call2a \\(c=97 'a', f1=4, s=1, d1=5, i=2, f2=4, l=3, d2=5\\) .*$gdb_prompt $" { pass "run to call2a" }
+ -re "$gdb_prompt $" { fail "run to call2a" ; gdb_suppress_tests; }
+ timeout { fail "(timeout) run to call2a" ; gdb_suppress_tests; }
+ }
+
+ # Print each arg as a double check to see if we can print
+ gdb_test "print c" ".* = 97 'a'" "print c after run to call2a"
+ gdb_test "print f1" ".* = 4" "print f1 after run to call2a"
+ gdb_test "print s" ".* = 1" "print s after run to call2a"
+ gdb_test "print d1" ".* = 5" "print d1 after run to call2a"
+ gdb_test "print i" ".* = 2" "print i after run to call2a"
+ gdb_test "print f2" ".* = 4" "print f2 after run to call2a"
+ gdb_test "print l" ".* = 3" "print l after run to call2a"
+ gdb_test "print d2" ".* = 5" "print d2 after run to call2a"
+
+ setup_xfail "rs6000-*-*"
+ if {!$gcc_compiled} then { setup_xfail "mips-sgi-irix*" }
+ # Continue; should stop at call2b and print actual arguments.
+ if [gdb_test "cont" ".* call2b \\(f1=4, s=1, d1=5, i=2, f2=4, l=3, d2=5, c=97 'a'\\) .*" "continue to call2b"] {
+ gdb_suppress_tests;
+ }
+
+ # Continue; should stop at call2c and print actual arguments.
+ if [gdb_test "cont" ".* call2c \\(s=1, d1=5, i=2, f2=4, l=3, d2=5, c=97 'a', f1=4\\) .*" "continue to call2c"] {
+ gdb_suppress_tests;
+ }
+
+ # Continue; should stop at call2d and print actual arguments.
+ if [gdb_test "cont" ".* call2d \\(d1=5, i=2, f2=4, l=3, d2=5, c=97 'a', f1=4, s=1\\) .*" "continue to call2d"] {
+ gdb_suppress_tests;
+ }
+
+ # Continue; should stop at call2e and print actual arguments.
+ if [gdb_test "cont" ".* call2e \\(i=2, f2=4, l=3, d2=5, c=97 'a', f1=4, s=1, d1=5\\) .*" "continue to call2e"] {
+ gdb_suppress_tests;
+ }
+
+ # Continue; should stop at call2f and print actual arguments.
+ if [gdb_test "cont" ".* call2f \\(f2=4, l=3, d2=5, c=97 'a', f1=4, s=1, d1=5, i=2\\) .*" "continue to call2f"] {
+ gdb_suppress_tests;
+ }
+
+ # Continue; should stop at call2g and print actual arguments.
+ if [gdb_test "cont" ".* call2g \\(l=3, d2=5, c=97 'a', f1=4, s=1, d1=5, i=2, f2=4\\) .*" "continue to call2g"] {
+ gdb_suppress_tests;
+ }
+
+ # Continue; should stop at call2h and print actual arguments.
+ if [gdb_test "cont" ".* call2h \\(d2=5, c=97 'a', f1=4, s=1, d1=5, i=2, f2=4, l=3\\) .*" "continue to call2h"] {
+ gdb_suppress_tests;
+ }
+
+ # monitor only allows 8 breakpoints; w89k board allows 10, so
+ # break them up into two groups.
+ delete_breakpoints
+ gdb_breakpoint call2i
+
+ # Continue; should stop at call2i and print actual arguments.
+ if [gdb_test "cont" ".* call2i \\(c1=97 'a', f1=4, c2=97 'a', c3=97 'a', d1=5, c4=97 'a', c5=97 'a', c6=97 'a', f2=4, s=1, c7=97 'a', d2=5\\) .*" "continue to call2i"] {
+ gdb_suppress_tests;
+ }
+ gdb_stop_suppressing_tests;
+}
+
+#
+# Locate actual args; dereference pointers to ints and floats.
+#
+
+proc pointer_args {} {
+ global gdb_prompt
+ global hex
+ global det_file
+
+ delete_breakpoints
+
+ gdb_breakpoint call3a
+ gdb_breakpoint call3b
+ gdb_breakpoint call3c
+
+ # Run; should stop at call3a and print actual arguments.
+ # Try dereferencing the arguments.
+
+ # The a29k fails all of these tests, perhaps because the prologue
+ # code is broken.
+ setup_xfail "a29k-*-udi"
+ gdb_run_cmd
+ gdb_expect {
+ -re ".* call3a \\(cp=$hex \"a\", sp=$hex, ip=$hex, lp=$hex\\) .*$gdb_prompt $" { pass "run to call3a" }
+ -re "$gdb_prompt $" { fail "run to call3a" ; gdb_suppress_tests; }
+ timeout { fail "(timeout) run to call3a" ; gdb_suppress_tests; }
+ }
+
+ gdb_test "print *cp" ".* = 97 'a'"
+ gdb_test "print *sp" ".* = 1"
+ gdb_test "print *ip" ".* = 2"
+ gdb_test "print *lp" ".* = 3"
+
+ # Continue; should stop at call3b and print actual arguments.
+ # Try dereferencing the arguments.
+ if [gdb_test "cont" ".* call3b \\(ucp=$hex \"b\", usp=$hex, uip=$hex, ulp=$hex\\) .*" "continue to call3b"] {
+ gdb_suppress_tests;
+ }
+
+ gdb_test "print *ucp" ".* = 98 'b'"
+ gdb_test "print *usp" ".* = 6"
+ gdb_test "print *uip" ".* = 7"
+ gdb_test "print *ulp" ".* = 8"
+
+ # Continue; should stop at call3c and print actual arguments.
+ # Try dereferencing the arguments.
+ if [gdb_test "cont" ".* call3c \\(fp=$hex, dp=$hex\\) .*" "continue to call3c"] {
+ gdb_suppress_tests;
+ }
+
+ gdb_test "print *fp" ".* = 4"
+ gdb_test "print *dp" ".* = 5"
+
+# pass "locate actual args, pointer types"
+ gdb_stop_suppressing_tests;
+}
+
+#
+# Locate actual args; structures and unions passed by reference.
+#
+
+proc structs_by_reference {} {
+ global gdb_prompt
+ global hex
+ global det_file
+ global target_sizeof_int
+ global target_sizeof_long
+ global target_bigendian_p
+
+ delete_breakpoints
+
+ gdb_breakpoint call4a
+ gdb_breakpoint call4b
+
+ # Run; should stop at call4a and print actual arguments.
+ # Try dereferencing the arguments.
+
+ # The a29k fails all of these tests, perhaps because the prologue
+ # code is broken.
+ setup_xfail "a29k-*-udi"
+ gdb_run_cmd
+ gdb_expect {
+ -re ".* call4a \\(stp=$hex\\) .*$gdb_prompt $" {
+ pass "run to call4a"
+ }
+ -re "$gdb_prompt $" { fail "run to call4a" ; gdb_suppress_tests; }
+ timeout { fail "(timeout) run to call4a" ; gdb_suppress_tests; }
+ }
+
+ gdb_test "print *stp" ".* = \{s1 = 101, s2 = 102\}"
+
+ # Continue; should stop at call4b and print actual arguments.
+
+ gdb_test "cont" ".* call4b \\(unp=$hex\\) .*" "continue to call4b"
+
+ # Try dereferencing the arguments.
+ if { $target_sizeof_long == $target_sizeof_int } {
+ gdb_test "print *unp" ".* = \{u1 = 1, u2 = 1\}" \
+ "print *unp (sizeof long == sizeof int)"
+ } elseif { ! $target_bigendian_p } {
+ gdb_test "print *unp" ".* = \{u1 = 1, u2 = 1\}" \
+ "print *unp (little-endian, sizeof long != sizeof int)"
+ } elseif { $target_sizeof_long == 8 && $target_sizeof_int == 4 } {
+ gdb_test "print *unp" ".* = \{u1 = 1, u2 = 4294967296\}" \
+ "print *unp (big-endian, sizeof long == 8, sizeof int = 4)"
+ } elseif { $target_sizeof_long == 4 && $target_sizeof_int == 2 } {
+ gdb_test "print *unp" ".* = \{u1 = 1, u2 = 65536\}" \
+ "print *unp (big-endian, sizeof long == 4, sizeof int = 2)"
+ } else {
+ fail "print *unp (unknown case)"
+ }
+
+ pass "locate actual args, structs/unions passed by reference"
+ gdb_stop_suppressing_tests;
+}
+
+#
+# Locate actual args; structures and unions passed by value.
+#
+
+proc structs_by_value {} {
+ global gdb_prompt
+ global hex
+ global det_file
+ global target_sizeof_int
+ global target_sizeof_long
+ global target_bigendian_p
+
+ delete_breakpoints
+
+ gdb_breakpoint call5a
+ gdb_breakpoint call5b
+
+ # Run; should stop at call5a and print actual arguments.
+ # Try dereferencing the arguments.
+
+ # The a29k fails all of these tests, perhaps because the prologue
+ # code is broken.
+ setup_xfail "a29k-*-udi"
+ gdb_run_cmd
+ gdb_expect {
+ -re ".* call5a \\(st=\{s1 = 101, s2 = 102\}\\) .*$gdb_prompt $" {
+ pass "run to call5a"
+ }
+ -re "$gdb_prompt $" { fail "run to call5a" ; gdb_suppress_tests; }
+ timeout { fail "(timeout) run to call5a" ; gdb_suppress_tests; }
+ }
+
+ gdb_test "print st" ".* = \{s1 = 101, s2 = 102\}"
+
+ # Continue; should stop at call5b and print actual arguments.
+ if { $target_sizeof_long == $target_sizeof_int } {
+ gdb_test "cont" ".* call5b \\(un=\{u1 = 2, u2 = 2\}\\) .*" \
+ "continue to call5b (sizeof long == sizeof int)"
+ } elseif { ! $target_bigendian_p } {
+ gdb_test "cont" ".* call5b \\(un=\{u1 = 2, u2 = 2\}\\) .*" \
+ "continue to call5b (little-endian, sizeof long != sizeof int)"
+ } elseif { $target_sizeof_long == 8 && $target_sizeof_int == 4 } {
+ gdb_test "cont" ".* call5b \\(un=\{u1 = 2, u2 = 8589934592\}\\) .*" \
+ "continue to call5b (big-endian, sizeof long == 8, sizeof int = 4)"
+ } elseif { $target_sizeof_long == 4 && $target_sizeof_int == 2 } {
+ gdb_test "cont" ".* call5b \\(un=\{u1 = 2, u2 = 131072\}\\) .*" \
+ "continue to call5b (big-endian, sizeof long == 4, sizeof int = 2)"
+ } else {
+ fail "continue to call5b (unknown case)"
+ }
+
+ # Try dereferencing the arguments.
+ if { $target_sizeof_long == $target_sizeof_int } {
+ gdb_test "print un" ".* = \{u1 = 2, u2 = 2\}" \
+ "print un (sizeof long == sizeof int)"
+ } elseif { ! $target_bigendian_p } {
+ gdb_test "print un" ".* = \{u1 = 2, u2 = 2\}" \
+ "print un (little-endian, sizeof long != sizeof int)"
+ } elseif { $target_sizeof_long == 8 && $target_sizeof_int == 4 } {
+ gdb_test "print un" ".* = \{u1 = 2, u2 = 8589934592\}" \
+ "print un (big-endian, sizeof long == 8, sizeof int = 4)"
+ } elseif { $target_sizeof_long == 4 && $target_sizeof_int == 2 } {
+ gdb_test "print un" ".* = \{u1 = 2, u2 = 131072\}" \
+ "print un (big-endian, sizeof long == 4, sizeof int = 2)"
+ } else {
+ fail "print un (unknown case)"
+ }
+
+ gdb_stop_suppressing_tests;
+}
+
+#
+# Locate actual args; discard, shuffle, and call
+#
+
+proc discard_and_shuffle {} {
+ global gdb_prompt
+ global hex
+ global decimal
+ global det_file
+ global gcc_compiled
+
+ delete_breakpoints
+
+ gdb_breakpoint call6a
+ gdb_breakpoint call6b
+ gdb_breakpoint call6c
+ gdb_breakpoint call6d
+ gdb_breakpoint call6e
+ gdb_breakpoint call6f
+ gdb_breakpoint call6g
+ gdb_breakpoint call6h
+
+ # Run; should stop at call6a and print actual arguments.
+ # Print backtrace.
+
+ # The a29k fails all of these tests, perhaps because the prologue
+ # code is broken.
+ setup_xfail "a29k-*-udi"
+ gdb_run_cmd
+ gdb_expect {
+ -re ".*Breakpoint $decimal, call6a .*$gdb_prompt $" { pass "run to call6a" }
+ -re "$gdb_prompt $" { fail "run to call6a" ; gdb_suppress_tests; }
+ timeout { fail "(timeout) run to call6a" ; gdb_suppress_tests; }
+ }
+
+ setup_xfail "rs6000-*-*"
+
+ if {!$gcc_compiled} {
+ setup_xfail "mips-sgi-irix5*"
+ }
+
+ if [gdb_test "backtrace 100" " call6a \\(c=97 'a', s=1, i=2, l=3, f=4, d=5, uc=98 'b', us=6, ui=7, ul=8\\).* main \\(.*\\).*" "backtrace from call6a"] {
+ gdb_suppress_tests;
+ }
+
+ # Continue; should stop at call6b and print actual arguments.
+ # Print backtrace.
+
+ gdb_continue call6b
+
+ if [gdb_test "backtrace 100" " call6b \\(s=1, i=2, l=3, f=4, d=5, uc=98 'b', us=6, ui=7, ul=8\\).* call6a \\(c=97 'a', s=1, i=2, l=3, f=4, d=5, uc=98 'b', us=6, ui=7, ul=8\\).* main \\(.*\\).*" "backtrace from call6b"] {
+ gdb_suppress_tests;
+ }
+
+ # Continue; should stop at call6c and print actual arguments.
+ # Print backtrace.
+
+ gdb_continue call6c
+
+ if [gdb_test "backtrace 100" " call6c \\(i=2, l=3, f=4, d=5, uc=98 'b', us=6, ui=7, ul=8\\).* call6b \\(s=1, i=2, l=3, f=4, d=5, uc=98 'b', us=6, ui=7, ul=8\\).* call6a \\(c=97 'a', s=1, i=2, l=3, f=4, d=5, uc=98 'b', us=6, ui=7, ul=8\\).* main \\(.*\\).*" "backtrace from call6c"] {
+ gdb_suppress_tests;
+ }
+ # Continue; should stop at call6d and print actual arguments.
+ # Print backtrace.
+
+ gdb_continue call6d
+
+ if [gdb_test "backtrace 100" " call6d \\(l=3, f=4, d=5, uc=98 'b', us=6, ui=7, ul=8\\).* call6c \\(i=2, l=3, f=4, d=5, uc=98 'b', us=6, ui=7, ul=8\\).* call6b \\(s=1, i=2, l=3, f=4, d=5, uc=98 'b', us=6, ui=7, ul=8\\).* call6a \\(c=97 'a', s=1, i=2, l=3, f=4, d=5, uc=98 'b', us=6, ui=7, ul=8\\).* main \\(.*\\).*" "backtrace from call6d"] {
+ gdb_suppress_tests;
+ }
+
+ # Continue; should stop at call6e and print actual arguments.
+ # Print backtrace.
+
+ gdb_continue call6e
+
+ if [gdb_test "backtrace 100" " call6e \\(f=4, d=5, uc=98 'b', us=6, ui=7, ul=8\\).* call6d \\(l=3, f=4, d=5, uc=98 'b', us=6, ui=7, ul=8\\).* call6c \\(i=2, l=3, f=4, d=5, uc=98 'b', us=6, ui=7, ul=8\\).* call6b \\(s=1, i=2, l=3, f=4, d=5, uc=98 'b', us=6, ui=7, ul=8\\).* call6a \\(c=97 'a', s=1, i=2, l=3, f=4, d=5, uc=98 'b', us=6, ui=7, ul=8\\).* main \\(.*\\).*" "backtrace from call6e"] {
+ gdb_suppress_tests;
+ }
+
+ # Continue; should stop at call6f and print actual arguments.
+ # Print backtrace.
+
+ gdb_continue call6f
+
+ if [gdb_test "backtrace 100" " call6f \\(d=5, uc=98 'b', us=6, ui=7, ul=8\\).* call6e \\(f=4, d=5, uc=98 'b', us=6, ui=7, ul=8\\).* call6d \\(l=3, f=4, d=5, uc=98 'b', us=6, ui=7, ul=8\\).* call6c \\(i=2, l=3, f=4, d=5, uc=98 'b', us=6, ui=7, ul=8\\).* call6b \\(s=1, i=2, l=3, f=4, d=5, uc=98 'b', us=6, ui=7, ul=8\\).* call6a \\(c=97 'a', s=1, i=2, l=3, f=4, d=5, uc=98 'b', us=6, ui=7, ul=8\\).* main \\(.*\\).*" "backtrace from call6f"] {
+ gdb_suppress_tests;
+ }
+
+ # Continue; should stop at call6g and print actual arguments.
+ # Print backtrace.
+
+ gdb_continue call6g
+
+ if [gdb_test "backtrace 100" " call6g \\(uc=98 'b', us=6, ui=7, ul=8\\).* call6f \\(d=5, uc=98 'b', us=6, ui=7, ul=8\\).* call6e \\(f=4, d=5, uc=98 'b', us=6, ui=7, ul=8\\).* call6d \\(l=3, f=4, d=5, uc=98 'b', us=6, ui=7, ul=8\\).* call6c \\(i=2, l=3, f=4, d=5, uc=98 'b', us=6, ui=7, ul=8\\).* call6b \\(s=1, i=2, l=3, f=4, d=5, uc=98 'b', us=6, ui=7, ul=8\\).* call6a \\(c=97 'a', s=1, i=2, l=3, f=4, d=5, uc=98 'b', us=6, ui=7, ul=8\\).* main \\(.*\\).*" "backtrace from call6g"] {
+ gdb_suppress_tests;
+ }
+
+ # Continue; should stop at call6h and print actual arguments.
+ # Print backtrace.
+
+ gdb_continue call6h
+
+ if [gdb_test "backtrace 100" " call6h \\(us=6, ui=7, ul=8\\).* call6g \\(uc=98 'b', us=6, ui=7, ul=8\\).* call6f \\(d=5, uc=98 'b', us=6, ui=7, ul=8\\).* call6e \\(f=4, d=5, uc=98 'b', us=6, ui=7, ul=8\\).* call6d \\(l=3, f=4, d=5, uc=98 'b', us=6, ui=7, ul=8\\).* call6c \\(i=2, l=3, f=4, d=5, uc=98 'b', us=6, ui=7, ul=8\\).* call6b \\(s=1, i=2, l=3, f=4, d=5, uc=98 'b', us=6, ui=7, ul=8\\).* call6a \\(c=97 'a', s=1, i=2, l=3, f=4, d=5, uc=98 'b', us=6, ui=7, ul=8\\).* main \\(.*\\).*" "backtrace from call6h"] {
+ gdb_suppress_tests;
+ }
+
+ # monitor only allows 8 breakpoints; w89k board allows 10, so
+ # break them up into two groups.
+ delete_breakpoints
+ gdb_breakpoint call6i
+ gdb_breakpoint call6j
+ gdb_breakpoint call6k
+
+ # Continue; should stop at call6i and print actual arguments.
+ # Print backtrace.
+
+ gdb_continue call6i
+
+ if [gdb_test "backtrace 100" " call6i \\(ui=7, ul=8\\).* call6h \\(us=6, ui=7, ul=8\\).* call6g \\(uc=98 'b', us=6, ui=7, ul=8\\).* call6f \\(d=5, uc=98 'b', us=6, ui=7, ul=8\\).* call6e \\(f=4, d=5, uc=98 'b', us=6, ui=7, ul=8\\).* call6d \\(l=3, f=4, d=5, uc=98 'b', us=6, ui=7, ul=8\\).* call6c \\(i=2, l=3, f=4, d=5, uc=98 'b', us=6, ui=7, ul=8\\).* call6b \\(s=1, i=2, l=3, f=4, d=5, uc=98 'b', us=6, ui=7, ul=8\\).* call6a \\(c=97 'a', s=1, i=2, l=3, f=4, d=5, uc=98 'b', us=6, ui=7, ul=8\\).* main \\(.*\\).*" "backtrace from call6i"] {
+ gdb_suppress_tests;
+ }
+
+ # Continue; should stop at call6j and print actual arguments.
+ # Print backtrace.
+
+ gdb_continue call6j
+
+ if [gdb_test "backtrace 100" " call6j \\(ul=8\\).* call6i \\(ui=7, ul=8\\).* call6h \\(us=6, ui=7, ul=8\\).* call6g \\(uc=98 'b', us=6, ui=7, ul=8\\).* call6f \\(d=5, uc=98 'b', us=6, ui=7, ul=8\\).* call6e \\(f=4, d=5, uc=98 'b', us=6, ui=7, ul=8\\).* call6d \\(l=3, f=4, d=5, uc=98 'b', us=6, ui=7, ul=8\\).* call6c \\(i=2, l=3, f=4, d=5, uc=98 'b', us=6, ui=7, ul=8\\).* call6b \\(s=1, i=2, l=3, f=4, d=5, uc=98 'b', us=6, ui=7, ul=8\\).* call6a \\(c=97 'a', s=1, i=2, l=3, f=4, d=5, uc=98 'b', us=6, ui=7, ul=8\\).* main \\(.*\\).*" "backtrace from call6j"] {
+ gdb_suppress_tests;
+ }
+
+ # Continue; should stop at call6k and print actual arguments.
+ # Print backtrace.
+ # This fails on i960-*-vxworks because gdb gets confused by
+ # breakpoints on adjacent instructions.
+ setup_xfail "i960-*-vxworks" 1786
+ gdb_continue call6k
+
+ if [gdb_test "backtrace 100" " call6k \\(\\).* call6j \\(ul=8\\).* call6i \\(ui=7, ul=8\\).* call6h \\(us=6, ui=7, ul=8\\).* call6g \\(uc=98 'b', us=6, ui=7, ul=8\\).* call6f \\(d=5, uc=98 'b', us=6, ui=7, ul=8\\).* call6e \\(f=4, d=5, uc=98 'b', us=6, ui=7, ul=8\\).* call6d \\(l=3, f=4, d=5, uc=98 'b', us=6, ui=7, ul=8\\).* call6c \\(i=2, l=3, f=4, d=5, uc=98 'b', us=6, ui=7, ul=8\\).* call6b \\(s=1, i=2, l=3, f=4, d=5, uc=98 'b', us=6, ui=7, ul=8\\).* call6a \\(c=97 'a', s=1, i=2, l=3, f=4, d=5, uc=98 'b', us=6, ui=7, ul=8\\).* main \\(.*\\).*" "backtrace from call6k"] {
+ gdb_suppress_tests;
+ }
+ gdb_stop_suppressing_tests;
+}
+
+
+#
+# Locate actual args; shuffle round robin and call
+#
+
+proc shuffle_round_robin {} {
+ global gdb_prompt
+ global hex
+ global decimal
+ global det_file
+ global gcc_compiled
+
+ delete_breakpoints
+
+ gdb_breakpoint call7a
+ gdb_breakpoint call7b
+ gdb_breakpoint call7c
+ gdb_breakpoint call7d
+ gdb_breakpoint call7e
+ gdb_breakpoint call7f
+ gdb_breakpoint call7g
+ gdb_breakpoint call7h
+
+ # Run; should stop at call7a and print actual arguments.
+ # Print backtrace.
+
+ # The a29k fails all of these tests, perhaps because the prologue
+ # code is broken.
+ setup_xfail "a29k-*-udi"
+ gdb_run_cmd
+ gdb_expect {
+ -re ".*Breakpoint $decimal, call7a .*$gdb_prompt $" {
+ pass "run to call7a"
+ }
+ -re "$gdb_prompt $" { fail "run to call7a" ; gdb_suppress_tests; }
+ timeout { fail "(timeout) run to call7a" ; gdb_suppress_tests; }
+ }
+
+ setup_xfail "i960-*-*" 1813
+ if {!$gcc_compiled} then { setup_xfail "rs6000-*-*" "mips-sgi-irix5*" }
+ gdb_test "backtrace 100" " call7a \\(c=97 'a', i=2, s=1, l=3, f=4, uc=98 'b', d=5, us=6, ul=8, ui=7\\).* main \\(.*\\).*" "backtrace from call7a"
+
+ # Continue; should stop at call7b and print actual arguments.
+ # Print backtrace.
+
+ gdb_continue call7b
+
+ if {$gcc_compiled} then { setup_xfail "rs6000-*-*" }
+
+ gdb_test "backtrace 100" " call7b \\(i=2, s=1, l=3, f=4, uc=98 'b', d=5, us=6, ul=8, ui=7, c=97 'a'\\).* call7a \\(c=97 'a', i=2, s=1, l=3, f=4, uc=98 'b', d=5, us=6, ul=8, ui=7\\).* main \\(.*\\).*" "backtrace from call7b"
+
+ # Continue; should stop at call7c and print actual arguments.
+ # Print backtrace.
+
+ gdb_continue call7c
+
+ gdb_test "backtrace 100" " call7c \\(s=1, l=3, f=4, uc=98 'b', d=5, us=6, ul=8, ui=7, c=97 'a', i=2\\).* call7b \\(i=2, s=1, l=3, f=4, uc=98 'b', d=5, us=6, ul=8, ui=7, c=97 'a'\\).* call7a \\(c=97 'a', i=2, s=1, l=3, f=4, uc=98 'b', d=5, us=6, ul=8, ui=7\\).* main \\(.*\\).*" "backtrace from call7c"
+
+ # Continue; should stop at call7d and print actual arguments.
+ # Print backtrace.
+
+ gdb_continue call7d
+
+ gdb_test "backtrace 100" " call7d \\(l=3, f=4, uc=98 'b', d=5, us=6, ul=8, ui=7, c=97 'a', i=2, s=1\\).* call7c \\(s=1, l=3, f=4, uc=98 'b', d=5, us=6, ul=8, ui=7, c=97 'a', i=2\\).* call7b \\(i=2, s=1, l=3, f=4, uc=98 'b', d=5, us=6, ul=8, ui=7, c=97 'a'\\).* call7a \\(c=97 'a', i=2, s=1, l=3, f=4, uc=98 'b', d=5, us=6, ul=8, ui=7\\).* main \\(.*\\).*" "backtrace from call7d"
+
+ gdb_continue call7e
+
+ gdb_test "backtrace 100" " call7e \\(f=4, uc=98 'b', d=5, us=6, ul=8, ui=7, c=97 'a', i=2, s=1, l=3\\).* call7d \\(l=3, f=4, uc=98 'b', d=5, us=6, ul=8, ui=7, c=97 'a', i=2, s=1\\).* call7c \\(s=1, l=3, f=4, uc=98 'b', d=5, us=6, ul=8, ui=7, c=97 'a', i=2\\).* call7b \\(i=2, s=1, l=3, f=4, uc=98 'b', d=5, us=6, ul=8, ui=7, c=97 'a'\\).* call7a \\(c=97 'a', i=2, s=1, l=3, f=4, uc=98 'b', d=5, us=6, ul=8, ui=7\\).* main \\(.*\\).*" "backtrace from call7e"
+
+ # Continue; should stop at call7f and print actual arguments.
+ # Print backtrace.
+
+ gdb_continue call7f
+
+ gdb_test "backtrace 100" " call7f \\(uc=98 'b', d=5, us=6, ul=8, ui=7, c=97 'a', i=2, s=1, l=3, f=4\\).* call7e \\(f=4, uc=98 'b', d=5, us=6, ul=8, ui=7, c=97 'a', i=2, s=1, l=3\\).* call7d \\(l=3, f=4, uc=98 'b', d=5, us=6, ul=8, ui=7, c=97 'a', i=2, s=1\\).* call7c \\(s=1, l=3, f=4, uc=98 'b', d=5, us=6, ul=8, ui=7, c=97 'a', i=2\\).* call7b \\(i=2, s=1, l=3, f=4, uc=98 'b', d=5, us=6, ul=8, ui=7, c=97 'a'\\).* call7a \\(c=97 'a', i=2, s=1, l=3, f=4, uc=98 'b', d=5, us=6, ul=8, ui=7\\).* main \\(.*\\).*" "backtrace from call7f"
+
+ # Continue; should stop at call7g and print actual arguments.
+ # Print backtrace.
+
+ gdb_continue call7g
+
+ gdb_test "backtrace 100" " call7g \\(d=5, us=6, ul=8, ui=7, c=97 'a', i=2, s=1, l=3, f=4, uc=98 'b'\\).* call7f \\(uc=98 'b', d=5, us=6, ul=8, ui=7, c=97 'a', i=2, s=1, l=3, f=4\\).* call7e \\(f=4, uc=98 'b', d=5, us=6, ul=8, ui=7, c=97 'a', i=2, s=1, l=3\\).* call7d \\(l=3, f=4, uc=98 'b', d=5, us=6, ul=8, ui=7, c=97 'a', i=2, s=1\\).* call7c \\(s=1, l=3, f=4, uc=98 'b', d=5, us=6, ul=8, ui=7, c=97 'a', i=2\\).* call7b \\(i=2, s=1, l=3, f=4, uc=98 'b', d=5, us=6, ul=8, ui=7, c=97 'a'\\).* call7a \\(c=97 'a', i=2, s=1, l=3, f=4, uc=98 'b', d=5, us=6, ul=8, ui=7\\).* main \\(.*\\).*" "backtrace from call7g"
+
+ gdb_continue call7h
+
+ gdb_test "backtrace 100" " call7h \\(us=6, ul=8, ui=7, c=97 'a', i=2, s=1, l=3, f=4, uc=98 'b', d=5\\).* call7g \\(d=5, us=6, ul=8, ui=7, c=97 'a', i=2, s=1, l=3, f=4, uc=98 'b'\\).* call7f \\(uc=98 'b', d=5, us=6, ul=8, ui=7, c=97 'a', i=2, s=1, l=3, f=4\\).* call7e \\(f=4, uc=98 'b', d=5, us=6, ul=8, ui=7, c=97 'a', i=2, s=1, l=3\\).* call7d \\(l=3, f=4, uc=98 'b', d=5, us=6, ul=8, ui=7, c=97 'a', i=2, s=1\\).* call7c \\(s=1, l=3, f=4, uc=98 'b', d=5, us=6, ul=8, ui=7, c=97 'a', i=2\\).* call7b \\(i=2, s=1, l=3, f=4, uc=98 'b', d=5, us=6, ul=8, ui=7, c=97 'a'\\).* call7a \\(c=97 'a', i=2, s=1, l=3, f=4, uc=98 'b', d=5, us=6, ul=8, ui=7\\).* main \\(.*\\).*" "backtrace from call7h"
+
+ # monitor only allows 8 breakpoints; w89k board allows 10, so
+ # break them up into two groups.
+ delete_breakpoints
+ gdb_breakpoint call7i
+ gdb_breakpoint call7j
+ gdb_breakpoint call7k
+
+ # Continue; should stop at call7i and print actual arguments.
+ # Print backtrace.
+
+ gdb_continue call7i
+
+ gdb_test "backtrace 100" " call7i \\(ul=8, ui=7, c=97 'a', i=2, s=1, l=3, f=4, uc=98 'b', d=5, us=6\\).* call7h \\(us=6, ul=8, ui=7, c=97 'a', i=2, s=1, l=3, f=4, uc=98 'b', d=5\\).* call7g \\(d=5, us=6, ul=8, ui=7, c=97 'a', i=2, s=1, l=3, f=4, uc=98 'b'\\).* call7f \\(uc=98 'b', d=5, us=6, ul=8, ui=7, c=97 'a', i=2, s=1, l=3, f=4\\).* call7e \\(f=4, uc=98 'b', d=5, us=6, ul=8, ui=7, c=97 'a', i=2, s=1, l=3\\).* call7d \\(l=3, f=4, uc=98 'b', d=5, us=6, ul=8, ui=7, c=97 'a', i=2, s=1\\).* call7c \\(s=1, l=3, f=4, uc=98 'b', d=5, us=6, ul=8, ui=7, c=97 'a', i=2\\).* call7b \\(i=2, s=1, l=3, f=4, uc=98 'b', d=5, us=6, ul=8, ui=7, c=97 'a'\\).* call7a \\(c=97 'a', i=2, s=1, l=3, f=4, uc=98 'b', d=5, us=6, ul=8, ui=7\\).* main \\(.*\\).*" "backtrace from call7i"
+
+ # Continue; should stop at call7j and print actual arguments.
+ # Print backtrace.
+
+ gdb_continue call7j
+
+ gdb_test "backtrace 100" " call7j \\(ui=7, c=97 'a', i=2, s=1, l=3, f=4, uc=98 'b', d=5, us=6, ul=8\\).* call7i \\(ul=8, ui=7, c=97 'a', i=2, s=1, l=3, f=4, uc=98 'b', d=5, us=6\\).* call7h \\(us=6, ul=8, ui=7, c=97 'a', i=2, s=1, l=3, f=4, uc=98 'b', d=5\\).* call7g \\(d=5, us=6, ul=8, ui=7, c=97 'a', i=2, s=1, l=3, f=4, uc=98 'b'\\).* call7f \\(uc=98 'b', d=5, us=6, ul=8, ui=7, c=97 'a', i=2, s=1, l=3, f=4\\).* call7e \\(f=4, uc=98 'b', d=5, us=6, ul=8, ui=7, c=97 'a', i=2, s=1, l=3\\).* call7d \\(l=3, f=4, uc=98 'b', d=5, us=6, ul=8, ui=7, c=97 'a', i=2, s=1\\).* call7c \\(s=1, l=3, f=4, uc=98 'b', d=5, us=6, ul=8, ui=7, c=97 'a', i=2\\).* call7b \\(i=2, s=1, l=3, f=4, uc=98 'b', d=5, us=6, ul=8, ui=7, c=97 'a'\\).* call7a \\(c=97 'a', i=2, s=1, l=3, f=4, uc=98 'b', d=5, us=6, ul=8, ui=7\\).* main \\(.*\\).*" "backtrace from call7j"
+
+ # Continue; should stop at call7k and print actual arguments.
+ # Print backtrace.
+
+ gdb_continue call7k
+
+ if {!$gcc_compiled} then { setup_xfail "mips-sgi-irix*" }
+ gdb_test "backtrace 100" " call7k \\(c=97 'a', i=2, s=1, l=3, f=4, uc=98 'b', d=5, us=6, ul=8, ui=7\\).* call7j \\(ui=7, c=97 'a', i=2, s=1, l=3, f=4, uc=98 'b', d=5, us=6, ul=8\\).* call7i \\(ul=8, ui=7, c=97 'a', i=2, s=1, l=3, f=4, uc=98 'b', d=5, us=6\\).* call7h \\(us=6, ul=8, ui=7, c=97 'a', i=2, s=1, l=3, f=4, uc=98 'b', d=5\\).* call7g \\(d=5, us=6, ul=8, ui=7, c=97 'a', i=2, s=1, l=3, f=4, uc=98 'b'\\).* call7f \\(uc=98 'b', d=5, us=6, ul=8, ui=7, c=97 'a', i=2, s=1, l=3, f=4\\).* call7e \\(f=4, uc=98 'b', d=5, us=6, ul=8, ui=7, c=97 'a', i=2, s=1, l=3\\).* call7d \\(l=3, f=4, uc=98 'b', d=5, us=6, ul=8, ui=7, c=97 'a', i=2, s=1\\).* call7c \\(s=1, l=3, f=4, uc=98 'b', d=5, us=6, ul=8, ui=7, c=97 'a', i=2\\).* call7b \\(i=2, s=1, l=3, f=4, uc=98 'b', d=5, us=6, ul=8, ui=7, c=97 'a'\\).* call7a \\(c=97 'a', i=2, s=1, l=3, f=4, uc=98 'b', d=5, us=6, ul=8, ui=7\\).* main \\(.*\\).*" "backtrace from call7k"
+ gdb_stop_suppressing_tests;
+}
+
+#
+# Locate actual args; recursive passing of structs by value
+#
+
+proc recursive_structs_by_value {} {
+ global gdb_prompt
+ global hex
+ global decimal
+ global det_file
+
+ delete_breakpoints
+
+ gdb_breakpoint hitbottom
+
+ # Run; should stop at hitbottom and print actual arguments.
+ # Print backtrace.
+ gdb_run_cmd
+ gdb_expect {
+ -re ".*Breakpoint $decimal, hitbottom .*$gdb_prompt $" { pass "run to hitbottom" }
+ -re "$gdb_prompt $" { fail "run to hitbottom" ; gdb_suppress_tests; }
+ timeout { fail "(timeout) run to hitbottom" ; gdb_suppress_tests; }
+ }
+
+ if ![istarget sparclet-*-*] {
+ # The a29k fails all of these tests, perhaps because the prologue
+ # code is broken.
+ setup_xfail "a29k-*-udi"
+ gdb_test "backtrace 100" " hitbottom \\(\\).* recurse \\(a=\{s = 0, i = 0, l = 0\}, depth=0\\).* recurse \\(a=\{s = 1, i = 1, l = 1\}, depth=1\\).* recurse \\(a=\{s = 2, i = 2, l = 2\}, depth=2\\).* recurse \\(a=\{s = 3, i = 3, l = 3\}, depth=3\\).* recurse \\(a=\{s = 4, i = 4, l = 4\}, depth=4\\).* test_struct_args \\(\\).* main \\(.*\\).*" "recursive passing of structs by value"
+ } else {
+ fail "recursive passing of structs by value (sparclet)"
+ }
+ gdb_stop_suppressing_tests;
+}
+
+proc funcargs_reload { } {
+ global objdir
+ global subdir
+ global binfile
+ global srcdir
+
+ if [istarget "mips-idt-*"] {
+ # Restart because IDT/SIM runs out of file descriptors.
+ gdb_exit
+ gdb_start
+ gdb_reinitialize_dir $srcdir/$subdir
+ gdb_load ${binfile}
+ }
+}
+
+#
+# Test for accessing local stack variables in functions which call alloca
+#
+proc localvars_after_alloca { } {
+ global gdb_prompt
+ global hex
+ global decimal
+ global gcc_compiled
+
+ if { ! [ runto localvars_after_alloca ] } then { gdb_suppress_tests; }
+
+ # Print each arg as a double check to see if we can print
+ # them here as well as with backtrace.
+
+ if {!$gcc_compiled} then { setup_xfail "rs6000-*-*" }
+ gdb_test "print c" " = 97 'a'" "print c after runto localvars_after_alloca"
+ if {!$gcc_compiled} then { setup_xfail "rs6000-*-*" }
+ gdb_test "print s" " = 1" "print s after runto localvars_after_alloca"
+ gdb_test "print i" " = 2" "print i after runto localvars_after_alloca"
+ gdb_test "print l" " = 3" "print l after runto localvars_after_alloca"
+
+ # Lame regexp.
+ gdb_test "next" ".*" "next in localvars_after_alloca()"
+
+ # Print each arg as a double check to see if we can print
+ # them here as well as with backtrace.
+
+ gdb_test "print c" " = 97 'a'" "print c in localvars_after_alloca"
+ gdb_test "print s" " = 1" "print s in localvars_after_alloca"
+ gdb_test "print i" " = 2" "print i in localvars_after_alloca"
+ gdb_test "print l" " = 3" "print l in localvars_after_alloca"
+
+ gdb_test "backtrace 8" "#0.*localvars_after_alloca \\(c=97 'a', s=1, i=2, l=3\\).*#1.*main.*" "backtrace after alloca"
+ gdb_stop_suppressing_tests;
+}
+
+proc call_after_alloca { } {
+ global gdb_prompt
+ global hex
+ global decimal
+ global gcc_compiled
+
+ if { ! [ runto call_after_alloca_subr ] } then { gdb_suppress_tests; }
+
+ # Print each arg as a double check to see if we can print
+ # them here as well as with backtrace.
+
+ if {!$gcc_compiled} then { setup_xfail "rs6000-*-*" }
+ gdb_test "print c" " = 97 'a'" "print c in call_after_alloca"
+ if {!$gcc_compiled} then { setup_xfail "rs6000-*-*" }
+ gdb_test "print s" " = 1" "print s in call_after_alloca"
+ gdb_test "print i" " = 2" "print i in call_after_alloca"
+ gdb_test "print l" " = 3" "print l in call_after_alloca"
+
+ if {!$gcc_compiled} then { setup_xfail "rs6000-*-*" }
+ gdb_test "backtrace 8" "#0.*call_after_alloca_subr \\(c=97 'a', s=1, i=2, l=3, uc=98 'b', us=11, ui=12, ul=13\\).*#1.*call_after_alloca \\(c=97 'a', s=1, i=2, l=3\\).*#2.*main.*" "backtrace from call_after_alloca_subr"
+ gdb_stop_suppressing_tests;
+}
+
+#
+# Test for accessing local stack variables, backtraces, finish,
+# and finally stepping into indirect calls. The point is that on the PA
+# these use a funky `dyncall' mechanism which GDB needs to know about.
+#
+proc localvars_in_indirect_call { } {
+ global gdb_prompt
+ global hex
+ global decimal
+ global gcc_compiled
+
+ # Can not use "runto call0a" as call0a is called several times
+ # during single run. Instead stop in a marker function and
+ # take control from there.
+ if { ! [ runto marker_indirect_call ] } then { gdb_suppress_tests; }
+
+ # break on the next call to call0a, then delete all the breakpoints
+ # and start testing.
+ gdb_breakpoint call0a
+ gdb_continue call0a
+ delete_breakpoints
+
+ # Print each arg as a double check to see if we can print
+ # them here as well as with backtrace.
+
+ if {!$gcc_compiled} then { setup_xfail "rs6000-*-*" }
+ gdb_test "print c" " = 97 'a'" "print c in localvars_in_indirect_call"
+ if {!$gcc_compiled} then { setup_xfail "rs6000-*-*" }
+ gdb_test "print s" " = 1" "print s in localvars_in_indirect_call"
+ gdb_test "print i" " = 2" "print i in localvars_in_indirect_call"
+ gdb_test "print l" " = 3" "print l in localvars_in_indirect_call"
+
+ if {!$gcc_compiled} then { setup_xfail "rs6000-*-*" }
+ gdb_test "backtrace 8" \
+ "#0.*call0a \\(c=97 'a', s=1, i=2, l=3\\).*#1.*main.*" \
+ "backtrace in indirectly called function"
+
+ #
+ # "finish" brings us back to main. We then will try to step through
+ # the second indirect call.
+ # On some targets (e.g. m68k) gdb will stop from the finish in midline
+ # of the first indirect call. This is due to stack adjustment instructions
+ # after the indirect call. In these cases we will step till we hit the
+ # second indirect call.
+ #
+
+ send_gdb "finish\n"
+ gdb_expect {
+ -re "\\(\\*pointer_to_call0a\\) \\(c, s, i, l\\);.*First.*$gdb_prompt $" {
+ send_gdb "step\n"
+ exp_continue
+ }
+ -re "\\(\\*pointer_to_call0a\\) \\(c, s, i, l\\);.*Second.*$gdb_prompt $" {
+ pass "finish from indirectly called function"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "finish from indirectly called function"
+ gdb_suppress_tests;
+ }
+ default { fail "finish from indirectly called function" ; gdb_suppress_tests; }
+ }
+
+ if {!$gcc_compiled} then { setup_xfail "rs6000-*-*" }
+ gdb_test "step" "call0a \\(c=97 'a', s=1, i=2, l=3\\).*" \
+ "stepping into indirectly called function"
+ gdb_stop_suppressing_tests;
+}
+
+#
+# Test for stepping into indirect calls which may have trampolines (possibly
+# cascaded) on both the call path and the gdb_suppress_tests; path.
+# to handle trampolines.
+#
+proc test_stepping_over_trampolines { } {
+ global gdb_prompt
+ global hex
+ global decimal
+
+ # Stop in a marker function and take control from there.
+ if { ! [ runto marker_call_with_trampolines ] } then { gdb_suppress_tests; }
+
+ # Cater for gdb stopping in midline, see comment for finish above.
+ send_gdb "finish\n"
+ gdb_expect {
+ -re "marker_call_with_trampolines ..;.*$gdb_prompt $" {
+ send_gdb "step\n"
+ exp_continue
+ }
+ -re "pointer_to_call_with_trampolines.*$gdb_prompt $" {
+ pass "finish from marker_call_with_trampolines"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "finish from marker_call_with_trampolines"
+ }
+ default { fail "finish from marker_call_with_trampolines" ; gdb_suppress_tests; }
+ }
+
+ # Try to step into the target function.
+ gdb_test "step" "call_with_trampolines \\(d1=5\\).*" \
+ "stepping into function called with trampolines"
+
+ # Make we can backtrace and the argument looks correct. */
+ gdb_test "backtrace 8" "#0.*call_with_trampolines \\(d1=5\\).*1.*main.*" \
+ "backtrace through call with trampolines"
+
+ # Make sure we can get back to main.
+ # Stepping back to main might stop again after the gdb_suppress_tests; statement
+ # or immediately transfer control back to main if optimizations
+ # are performed.
+ send_gdb "step\n"
+ gdb_expect {
+ -re "main .* at.*$gdb_prompt $" {
+ pass "stepping back to main from function called with trampolines" ;
+ }
+ -re "\}.*End of call_with_trampolines.*$gdb_prompt $" {
+ send_gdb "step\n"
+ exp_continue
+ }
+ -re ".*$gdb_prompt $" {
+ fail "stepping back to main from function called with trampolines"
+ }
+ default { fail "stepping back to main from function called with trampolines" ; gdb_suppress_tests; }
+ }
+ gdb_stop_suppressing_tests;
+}
+
+# Start with a fresh gdb.
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+if [istarget "mips*tx39-*"] {
+ set timeout 300
+} elseif [istarget "hppa*-hp-hpux*"] then {
+ set timeout 240
+} else {
+ set timeout 60
+}
+
+# Determine expected output for unsigned long variables,
+# the output varies with sizeof (unsigned long).
+
+set target_sizeof_long 4
+send_gdb "print sizeof (long)\n"
+gdb_expect {
+ -re ".\[0-9\]* = 4.*$gdb_prompt $" { }
+ -re ".\[0-9\]* = 8.*$gdb_prompt $" { set target_sizeof_long 8 }
+ -re ".*$gdb_prompt $" {
+ fail "getting sizeof long"
+ }
+ default { fail "(timeout) getting sizeof long" }
+}
+
+set target_sizeof_int 4
+send_gdb "print sizeof (int)\n"
+gdb_expect {
+ -re ".\[0-9\]* = 2.*$gdb_prompt $" { set target_sizeof_int 2 }
+ -re ".\[0-9\]* = 4.*$gdb_prompt $" { }
+ -re ".\[0-9\]* = 8.*$gdb_prompt $" { set target_sizeof_int 8 }
+ -re ".*$gdb_prompt $" {
+ fail "getting sizeof unsigned long"
+ }
+ default { fail "(timeout) getting sizeof int" }
+}
+
+set target_bigendian_p 1
+send_gdb "show endian\n"
+gdb_expect {
+ -re ".*little endian.*$gdb_prompt $" { set target_bigendian_p 0 }
+ -re ".*big endian.*$gdb_prompt $" { }
+ -re ".*$gdb_prompt $" {
+ fail "getting target endian"
+ }
+ default { fail "(timeout) getting target endian" }
+}
+
+# Perform tests
+
+integral_args
+funcargs_reload
+unsigned_integral_args
+funcargs_reload
+float_and_integral_args
+funcargs_reload
+pointer_args
+funcargs_reload
+structs_by_reference
+funcargs_reload
+structs_by_value
+funcargs_reload
+discard_and_shuffle
+funcargs_reload
+shuffle_round_robin
+funcargs_reload
+recursive_structs_by_value
+funcargs_reload
+localvars_after_alloca
+funcargs_reload
+call_after_alloca
+funcargs_reload
+localvars_in_indirect_call
+funcargs_reload
+test_stepping_over_trampolines
diff --git a/gdb/testsuite/gdb.base/gdbvars.exp b/gdb/testsuite/gdb.base/gdbvars.exp
new file mode 100644
index 00000000000..2ab37e0222f
--- /dev/null
+++ b/gdb/testsuite/gdb.base/gdbvars.exp
@@ -0,0 +1,117 @@
+# Copyright (C) 1992, 1997 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file was written by Fred Fish. (fnf@cygnus.com)
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+set prms_id 0
+set bug_id 0
+
+proc test_convenience_variables {} {
+ global gdb_prompt
+
+ gdb_test "set \$foo = 101" "" \
+ "Set a new convenience variable"
+
+ gdb_test "print \$foo" " = 101" \
+ "Print contents of new convenience variable"
+
+ gdb_test "set \$foo = 301" "" \
+ "Set convenience variable to a new value"
+
+ gdb_test "print \$foo" " = 301" \
+ "Print new contents of convenience variable"
+
+ gdb_test "set \$_ = 11" "" \
+ "Set convenience variable \$_"
+
+ gdb_test "print \$_" " = 11" \
+ "Print contents of convenience variable \$_"
+
+ gdb_test "print \$foo + 10" " = 311" \
+ "Use convenience variable in arithmetic expression"
+
+ gdb_test "print (\$foo = 32) + 4" " = 36" \
+ "Use convenience variable assignment in arithmetic expression"
+
+ gdb_test "print \$bar" " = void" \
+ "Print contents of uninitialized convenience variable"
+}
+
+proc test_value_history {} {
+ global gdb_prompt
+
+ gdb_test "print 101" "\\\$1 = 101" \
+ "Set value-history\[1\] using \$1"
+
+ gdb_test "print 102" "\\\$2 = 102" \
+ "Set value-history\[2\] using \$2"
+
+ gdb_test "print 103" "\\\$3 = 103" \
+ "Set value-history\[3\] using \$3"
+
+ gdb_test "print \$\$" "\\\$4 = 102" \
+ "Print value-history\[MAX-1\] using inplicit index \$\$"
+
+ gdb_test "print \$\$" "\\\$5 = 103" \
+ "Print value-history\[MAX-1\] again using implicit index \$\$"
+
+ gdb_test "print \$" "\\\$6 = 103" \
+ "Print value-history\[MAX\] using implicit index \$"
+
+ gdb_test "print \$\$2" "\\\$7 = 102" \
+ "Print value-history\[MAX-2\] using explicit index \$\$2"
+
+ gdb_test "print \$0" "\\\$8 = 102" \
+ "Print value-history\[MAX\] using explicit index \$0"
+
+ gdb_test "print 108" "\\\$9 = 108" ""
+
+ gdb_test "print \$\$0" "\\\$10 = 108" \
+ "Print value-history\[MAX\] using explicit index \$\$0"
+
+ gdb_test "print \$1" "\\\$11 = 101" \
+ "Print value-history\[1\] using explicit index \$1"
+
+ gdb_test "print \$2" "\\\$12 = 102" \
+ "Print value-history\[2\] using explicit index \$2"
+
+ gdb_test "print \$3" "\\\$13 = 103" \
+ "Print value-history\[3\] using explicit index \$3"
+
+ gdb_test "print \$-3" "\\\$14 = 100" \
+ "Print (value-history\[MAX\] - 3) using implicit index \$"
+
+ gdb_test "print \$1 + 3" "\\\$15 = 104" \
+ "Use value-history element in arithmetic expression"
+}
+
+# Start with a fresh gdb.
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+
+send_gdb "set print sevenbit-strings\n" ; gdb_expect -re ".*$gdb_prompt $"
+
+test_value_history
+test_convenience_variables
diff --git a/gdb/testsuite/gdb.base/grbx.c b/gdb/testsuite/gdb.base/grbx.c
new file mode 100644
index 00000000000..92f732344a3
--- /dev/null
+++ b/gdb/testsuite/gdb.base/grbx.c
@@ -0,0 +1,10 @@
+static int grbxx __attribute__ ((section (".data03"))) = 'g' + 'r' + 'b' + 'x';
+
+int grbx (int x)
+{
+ if (x)
+ return grbxx;
+ else
+ return 0;
+}
+
diff --git a/gdb/testsuite/gdb.base/help.exp b/gdb/testsuite/gdb.base/help.exp
new file mode 100644
index 00000000000..54bfdb10c68
--- /dev/null
+++ b/gdb/testsuite/gdb.base/help.exp
@@ -0,0 +1,542 @@
+# Copyright (C) 1988, 1990, 1991, 1992, 1997, 1998
+# Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file was written by Rob Savoye. (rob@cygnus.com)
+
+#
+# test gdb help commands
+#
+
+set prms_id 0
+set bug_id 0
+
+gdb_start
+
+# force the height of the debugger to be pretty large so no pagers getused
+gdb_test "set height 400" "" "test set height"
+
+# use a larger expect input buffer for long help outputs.
+# test help add-symbol-file
+gdb_test "help add-symbol-file" "Usage: add-symbol-file FILE ADDR.*\[\r\n\]+Load the symbols from FILE, assuming FILE has been dynamically loaded..*\[\r\n\]+ADDR is the starting address of the file\'s text." "help add-symbol-file"
+# test help aliases
+gdb_test "help aliases" "Aliases of other commands..*\[\r\n\]+List of commands\:.*\[\r\n\]+Type \"help\" followed by command name for full documentation..*\[\r\n\]+Command name abbreviations are allowed if unambiguous." "help aliases"
+gdb_test "help attach" "Attach to a process or file outside of GDB..*\[\r\n\]+This command attaches to another target, of the same type as your last.*\[\r\n\]+\"target\" command .\"info files\" will show your target stack.*\[\r\n\]+The command may take as argument a process id or a device file..*\[\r\n\]+For a process id, you must have permission to send the process a signal,.*\[\r\n\]+and it must have the same effective uid as the debugger..*\[\r\n\]+When using \"attach\" with a process id, the debugger finds the.*\[\r\n\]+program running in the process, looking first in the current working.*\[\r\n\]+directory, or .if not found there. using the source file search path.*\[\r\n\]+\\(see the \"directory\" command\\). You can also use the \"file\" command.*\[\r\n\]+to specify the program, and to load its symbol table." "help attach"
+# test help breakpoint "b" abbreviation
+gdb_test "help b" "Set breakpoint at specified line or function..*\[\r\n\]+Argument may be line number, function name, or \"\[*\]\" and an address..*\[\r\n\]+If line number is specified, break at start of code for that line..*\[\r\n\]+If function is specified, break at start of code for that function..*\[\r\n\]+If an address is specified, break at that exact address..*\[\r\n\]+With no arg, uses current execution address of selected stack frame..*\[\r\n\]+This is useful for breaking on return to a stack frame..*\[\r\n\]+Multiple breakpoints at one place are permitted, and useful if conditional..*\[\r\n\]+Do \"help breakpoints\" for info on other commands dealing with breakpoints." "help breakpoint \"b\" abbreviation"
+# test help breakpoint "br" abbreviation
+gdb_test "help br" "Set breakpoint at specified line or function..*\[\r\n\]+Argument may be line number, function name, or \"\[*\]\" and an address..*\[\r\n\]+If line number is specified, break at start of code for that line..*\[\r\n\]+If function is specified, break at start of code for that function..*\[\r\n\]+If an address is specified, break at that exact address..*\[\r\n\]+With no arg, uses current execution address of selected stack frame..*\[\r\n\]+This is useful for breaking on return to a stack frame..*\[\r\n\]+Multiple breakpoints at one place are permitted, and useful if conditional..*\[\r\n\]+Do \"help breakpoints\" for info on other commands dealing with breakpoints." "help breakpoint \"br\" abbreviation"
+# test help breakpoint "bre" abbreviation
+gdb_test "help bre" "Set breakpoint at specified line or function..*\[\r\n\]+Argument may be line number, function name, or \"\[*\]\" and an address..*\[\r\n\]+If line number is specified, break at start of code for that line..*\[\r\n\]+If function is specified, break at start of code for that function..*\[\r\n\]+If an address is specified, break at that exact address..*\[\r\n\]+With no arg, uses current execution address of selected stack frame..*\[\r\n\]+This is useful for breaking on return to a stack frame..*\[\r\n\]+Multiple breakpoints at one place are permitted, and useful if conditional..*\[\r\n\]+Do \"help breakpoints\" for info on other commands dealing with breakpoints." "help breakpoint \"bre\" abbreviation"
+# test help breakpoint "brea" abbreviation
+gdb_test "help brea" "Set breakpoint at specified line or function..*\[\r\n\]+Argument may be line number, function name, or \"\[*\]\" and an address..*\[\r\n\]+If line number is specified, break at start of code for that line..*\[\r\n\]+If function is specified, break at start of code for that function..*\[\r\n\]+If an address is specified, break at that exact address..*\[\r\n\]+With no arg, uses current execution address of selected stack frame..*\[\r\n\]+This is useful for breaking on return to a stack frame..*\[\r\n\]+Multiple breakpoints at one place are permitted, and useful if conditional..*\[\r\n\]+Do \"help breakpoints\" for info on other commands dealing with breakpoints." "help breakpoint \"brea\" abbreviation"
+# test help breakpoint "break" abbreviation
+gdb_test "help break" "Set breakpoint at specified line or function..*\[\r\n\]+Argument may be line number, function name, or \"\[*\]\" and an address..*\[\r\n\]+If line number is specified, break at start of code for that line..*\[\r\n\]+If function is specified, break at start of code for that function..*\[\r\n\]+If an address is specified, break at that exact address..*\[\r\n\]+With no arg, uses current execution address of selected stack frame..*\[\r\n\]+This is useful for breaking on return to a stack frame..*\[\r\n\]+Multiple breakpoints at one place are permitted, and useful if conditional..*\[\r\n\]+Do \"help breakpoints\" for info on other commands dealing with breakpoints." "help breakpoint \"break\" abbreviation"
+# test help breakpoints
+gdb_test "help breakpoints" "Making program stop at certain points..*\[\r\n\]+List of commands\:.*\[\r\n\]+awatch -- Set a watchpoint for an expression.*\[\r\n\]+break -- Set breakpoint at specified line or function.*\[\r\n\]+catch -- Set catchpoints to catch events.*\[\r\n\]+clear -- Clear breakpoint at specified line or function.*\[\r\n\]+commands -- Set commands to be executed when a breakpoint is hit.*\[\r\n\]+condition -- Specify breakpoint number N to break only if COND is true.*\[\r\n\]+delete -- Delete some breakpoints or auto-display expressions.*\[\r\n\]+disable -- Disable some breakpoints.*\[\r\n\]+enable -- Enable some breakpoints.*\[\r\n\]+hbreak -- Set a hardware assisted breakpoint.*\[\r\n\]+ignore -- Set ignore-count of breakpoint number N to COUNT.*\[\r\n\]+rwatch -- Set a read watchpoint for an expression.*\[\r\n\]+tbreak -- Set a temporary breakpoint.*\[\r\n\]+tcatch -- Set temporary catchpoints to catch events.*\[\r\n\]+thbreak -- Set a temporary hardware assisted breakpoint.*\[\r\n\]+watch -- Set a watchpoint for an expression.*\[\r\n\]+Type \"help\" followed by command name for full documentation..*\[\r\n\]+Command name abbreviations are allowed if unambiguous." "help breakpoints"
+# test help backtrace "bt" abbreviation
+gdb_test "help bt" "Print backtrace of all stack frames, or innermost COUNT frames..*\[\r\n\]+With a negative argument, print outermost -COUNT frames..*\[\r\n\]+Use of the 'full' qualifier also prints the values of the local variables." "help backtrace \"bt\" abbreviation"
+# test help backtrace
+gdb_test "help backtrace" "Print backtrace of all stack frames, or innermost COUNT frames..*\[\r\n\]+With a negative argument, print outermost -COUNT frames..*\[\r\n\]+Use of the 'full' qualifier also prints the values of the local variables." "help backtrace"
+# test help continue "c" abbreviation
+gdb_test "help c" "Continue program being debugged.*" "help continue \"c\" abbreviation"
+# test help continue
+gdb_test "help continue" "Continue program being debugged.*" "help continue"
+# test help call
+gdb_test "help call" "Call a function.*" "help call"
+# test help catch
+gdb_test "help catch" "Set catchpoints to catch events.*Raised signals may be caught:.*catch signal.*all signals.*catch signal.*signame.*a particular signal.*Raised exceptions may be caught:.*catch throw.*all exceptions, when thrown.*catch throw.*exceptname.*a particular exception, when thrown.*catch catch.*all exceptions, when caught.*catch catch.*exceptname.*a particular exception, when caught.*Thread or process events may be caught:.*catch thread_start.*any threads, just after creation.*catch thread_exit.*any threads, just before expiration.*catch thread_join.*any threads, just after joins.*catch start.*any processes, just after creation.*catch exit.*any processes, just before expiration.*catch fork.*calls to fork.*catch vfork.*calls to vfork.*catch exec.*calls to exec.*Dynamically.linked library events may be caught:.*catch load.*loads of any library.*catch load.*libname.*loads of a particular library.*catch unload.*unloads of any library.*catch unload.*libname.*unloads of a particular library.*The act of your program's execution stopping may also be caught:.*catch stop.*Do.*help set follow-fork-mode.*for info on debugging your program.*after a fork or vfork is caught.*Do.*help breakpoints.*for info on other commands dealing with breakpoints." "help catch"
+# test help cd
+gdb_test "help cd" "Set working directory to DIR for debugger and program being debugged..*\[\r\n\]+The change does not take effect for the program being debugged.*\[\r\n\]+until the next time it is started." "help cd"
+# test help clear
+gdb_test "help clear" "Clear breakpoint at specified line or function.*\[\r\n\]+Argument may be line number, function name, or .* and an address.*\[\r\n\]+If line number is specified, all breakpoints in that line are cleared.*\[\r\n\]+If function is specified, breakpoints at beginning of function are cleared.*\[\r\n\]+If an address is specified, breakpoints at that address are cleared.*\[\r\n\]+With no argument, clears all breakpoints in the line that the selected frame.*\[\r\n\]+is executing in..*\[\r\n\]+See also the \"delete\" command which clears breakpoints by number." "help clear"
+# test help commands
+gdb_test "help commands" "Set commands to be executed when a breakpoint is hit..*\[\r\n\]+Give breakpoint number as argument after \"commands\"..*\[\r\n\]+With no argument, the targeted breakpoint is the last one set..*\[\r\n\]+The commands themselves follow starting on the next line..*\[\r\n\]+Type a line containing \"end\" to indicate the end of them..*\[\r\n\]+Give \"silent\" as the first line to make the breakpoint silent;.*\[\r\n\]+then no output is printed when it is hit, except what the commands print." "help commands"
+# test help condition
+gdb_test "help condition" "Specify breakpoint number N to break only if COND is true..*\[\r\n\]+Usage is `condition N COND', where N is an integer and COND is an.*\[\r\n\]+expression to be evaluated whenever breakpoint N is reached. " "help condition"
+# test help core-file
+gdb_test "help core-file" "Use FILE as core dump for examining memory and registers..*\[\r\n\]+No arg means have no core file. This command has been superseded by the.*\[\r\n\]+`target core' and `detach' commands." "help core-file"
+# test help delete "d" abbreviation
+gdb_test "help d" "Delete some breakpoints or auto-display expressions..*\[\r\n\]+Arguments are breakpoint numbers with spaces in between..*\[\r\n\]+To delete all breakpoints, give no argument..*\[\r\n\]+Also a prefix command for deletion of other GDB objects..*\[\r\n\]+The \"unset\" command is also an alias for \"delete\"..*\[\r\n\]+List of delete subcommands:.*\[\r\n\]+delete breakpoints -- Delete some breakpoints or auto-display expressions.*\[\r\n\]+delete display -- Cancel some expressions to be displayed when program stops.*\[\r\n\]+Type \"help delete\" followed by delete subcommand name for full documentation..*\[\r\n\]+Command name abbreviations are allowed if unambiguous." "help delete \"d\" abbreviation"
+# test help delete
+gdb_test "help delete" "Delete some breakpoints or auto-display expressions..*\[\r\n\]+Arguments are breakpoint numbers with spaces in between..*\[\r\n\]+To delete all breakpoints, give no argument..*\[\r\n\]+Also a prefix command for deletion of other GDB objects..*\[\r\n\]+The \"unset\" command is also an alias for \"delete\"..*\[\r\n\]+List of delete subcommands:.*\[\r\n\]+delete breakpoints -- Delete some breakpoints or auto-display expressions.*\[\r\n\]+delete display -- Cancel some expressions to be displayed when program stops.*\[\r\n\]+Type \"help delete\" followed by delete subcommand name for full documentation..*\[\r\n\]+Command name abbreviations are allowed if unambiguous." "help delete"
+# test help data
+gdb_test "help data" ".*\[\r\n\]+Examining data..*\[\r\n\]+List of commands:.*\[\r\n\]+Type \"help\" followed by command name for full documentation..*\[\r\n\]+Command name abbreviations are allowed if unambiguous." "help data"
+# test help define
+gdb_test "help define" "Define a new command.*" "help define"
+# test help delete breakpoints
+gdb_test "help delete breakpoints" "Delete some breakpoints or auto-display expressions..*\[\r\n\]+Arguments are breakpoint numbers with spaces in between..*\[\r\n\]+To delete all breakpoints, give no argument..*\[\r\n\]+This command may be abbreviated \"delete\"." "help delete breakpoints"
+# test help delete display
+gdb_test "help delete display" "Cancel some expressions to be displayed when program stops..*\[\r\n\]+Arguments are the code numbers of the expressions to stop displaying..*\[\r\n\]+No argument means cancel all automatic-display expressions..*\[\r\n\]+Do \"info display\" to see current list of code numbers." "help delete display"
+# test help detach
+gdb_test "help detach" "Detach a process or file previously attached.\[\r\n\]+If a process, it is no longer traced, and it continues its execution.\[ \r\n\]+If\[ \r\n\]+you were debugging a file, the file is closed and gdb no longer accesses it." "help detach"
+# test help directory
+gdb_test "help directory" "Add directory DIR to beginning of search path for source files..*\[\r\n\]+Forget cached info on source file locations and line positions..*\[\r\n\]+DIR can also be .cwd for the current working directory, or .cdir for the.*\[\r\n\]+directory in which the source file was compiled into object code..*\[\r\n\]+With no argument, reset the search path to .cdir:.cwd, the default." "help directory"
+# test help disable "dis" abbreviation
+gdb_test "help dis" "Disable some breakpoints..*\[\r\n\]+Arguments are breakpoint numbers with spaces in between..*\[\r\n\]+To disable all breakpoints, give no argument..*\[\r\n\]+A disabled breakpoint is not forgotten, but has no effect until reenabled..*\[\r\n\]+List of disable subcommands:.*\[\r\n\]+disable breakpoints -- Disable some breakpoints.*\[\r\n\]+disable display -- Disable some expressions to be displayed when program stops.*\[\r\n\]+Type \"help disable\" followed by disable subcommand name for full documentation..*\[\r\n\]+Command name abbreviations are allowed if unambiguous." "help disable \"dis\" abbreviation"
+# test help disable "disa" abbreviation
+gdb_test "help disa" "Disable some breakpoints..*\[\r\n\]+Arguments are breakpoint numbers with spaces in between..*\[\r\n\]+To disable all breakpoints, give no argument..*\[\r\n\]+A disabled breakpoint is not forgotten, but has no effect until reenabled..*\[\r\n\]+List of disable subcommands:.*\[\r\n\]+disable breakpoints -- Disable some breakpoints.*\[\r\n\]+disable display -- Disable some expressions to be displayed when program stops.*\[\r\n\]+Type \"help disable\" followed by disable subcommand name for full documentation..*\[\r\n\]+Command name abbreviations are allowed if unambiguous." "help disable \"disa\" abbreviation"
+# test help disable
+gdb_test "help disable" "Disable some breakpoints..*\[\r\n\]+Arguments are breakpoint numbers with spaces in between..*\[\r\n\]+To disable all breakpoints, give no argument..*\[\r\n\]+A disabled breakpoint is not forgotten, but has no effect until reenabled..*\[\r\n\]+List of disable subcommands:.*\[\r\n\]+disable breakpoints -- Disable some breakpoints.*\[\r\n\]+disable display -- Disable some expressions to be displayed when program stops.*\[\r\n\]+Type \"help disable\" followed by disable subcommand name for full documentation..*\[\r\n\]+Command name abbreviations are allowed if unambiguous." "help disable"
+# test help disable breakpoints
+gdb_test "help disable breakpoints" "Disable some breakpoints..*\[\r\n\]+Arguments are breakpoint numbers with spaces in between..*\[\r\n\]+To disable all breakpoints, give no argument..*\[\r\n\]+A disabled breakpoint is not forgotten, but has no effect until reenabled..*\[\r\n\]+This command may be abbreviated \"disable\"." "help disable breakpoints"
+# test help disable display
+gdb_test "help disable display" "Disable some expressions to be displayed when program stops..*\[\r\n\]+Arguments are the code numbers of the expressions to stop displaying..*\[\r\n\]+No argument means disable all automatic-display expressions..*\[\r\n\]+Do \"info display\" to see current list of code numbers." "help disable display"
+# test help disassemble
+gdb_test "help disassemble" "Disassemble a specified section of memory..*\[\r\n\]+Default is the function surrounding the pc of the selected frame..*\[\r\n\]+With a single argument, the function surrounding that address is dumped..*\[\r\n\]+Two arguments are taken as a range of memory to dump." "help disassemble"
+# test help display
+gdb_test "help display" "Print value of expression EXP each time the program stops..*\[\r\n\]+/FMT may be used before EXP as in the \"print\" command..*\[\r\n\]+/FMT \"i\" or \"s\" or including a size-letter is allowed,.*\[\r\n\]+as in the \"x\" command, and then EXP is used to get the address to examine.*\[\r\n\]+and examining is done as in the \"x\" command..*\[\r\n\]+With no argument, display all currently requested auto-display expressions..*\[\r\n\]+Use \"undisplay\" to cancel display requests previously made." "help display"
+# test help do
+gdb_test "help do" "Select and print stack frame called by this one..*\[\r\n\]+An argument says how many frames down to go." "help do"
+# test help document
+gdb_test "help document" "Document a user-defined command..*\[\r\n\]+Give command name as argument. Give documentation on following lines..*\[\r\n\]+End with a line of just \"end\"." "help document"
+# test help down
+gdb_test "help down" "Select and print stack frame called by this one..*\[\r\n\]+An argument says how many frames down to go." "help down"
+# test help down-silently
+gdb_test "help down-silently" "Same as the `down' command, but does not print anything..*\[\r\n\]+This is useful in command scripts." "help down-silently"
+# this command was removed from GDB 4.5.8
+# test help dump-me
+#send_gdb "help dump-me"
+# -re "Get fatal error; make debugger dump its core."
+#
+# }
+# test help echo
+gdb_test "help echo" "Print a constant string. Give string as argument..*\[\r\n\]+C escape sequences may be used in the argument..*\[\r\n\]+No newline is added at the end of the argument;.*\[\r\n\]+use \".n\" if you want a newline to be printed..*\[\r\n\]+Since leading and trailing whitespace are ignored in command arguments,.*\[\r\n\]+if you want to print some you must use \".\" before leading whitespace.*\[\r\n\]+to be printed or after trailing whitespace." "help echo"
+# test help enable breakpoints delete
+gdb_test "help enable breakpoints delete" "Enable breakpoints and delete when hit. Give breakpoint numbers..*\[\r\n\]+If a breakpoint is hit while enabled in this fashion, it is deleted." "help enable breakpoints delete"
+# test help enable breakpoints once
+gdb_test "help enable breakpoints once" "Enable breakpoints for one hit..*" "help enable breakpoints once"
+# test help enable breakpoints
+gdb_test "help enable breakpoints" "Enable some breakpoints..*\[\r\n\]+Give breakpoint numbers .separated by spaces. as arguments..*\[\r\n\]+This is used to cancel the effect of the \"disable\" command..*\[\r\n\]+May be abbreviated to simply \"enable\"..*.*\[\r\n\]+List of enable breakpoints subcommands:.*\[\r\n\]+enable breakpoints delete -- Enable breakpoints and delete when hit.*\[\r\n\]+enable breakpoints once -- Enable breakpoints for one hit.*\[\r\n\]+Type \"help enable breakpoints\" followed by enable breakpoints subcommand name for full documentation..*\[\r\n\]+Command name abbreviations are allowed if unambiguous." "help enable breakpoints"
+# test help enable delete
+gdb_test "help enable delete" "Enable breakpoints and delete when hit. Give breakpoint numbers..*\[\r\n\]+If a breakpoint is hit while enabled in this fashion, it is deleted." "help enable delete"
+# test help enable display
+gdb_test "help enable display" "Enable some expressions to be displayed when program stops..*\[\r\n\]+Arguments are the code numbers of the expressions to resume displaying..*\[\r\n\]+No argument means enable all automatic-display expressions..*\[\r\n\]+Do \"info display\" to see current list of code numbers." "help enable display"
+# test help enable once
+gdb_test "help enable once" "Enable breakpoints for one hit.*" "help enable once"
+# test help enable
+gdb_test "help enable" "Enable some breakpoints..*\[\r\n\]+Give breakpoint numbers .separated by spaces. as arguments..*\[\r\n\]+With no subcommand, breakpoints are enabled until you command otherwise..*\[\r\n\]+This is used to cancel the effect of the \"disable\" command..*\[\r\n\]+With a subcommand you can enable temporarily..*\[\r\n\]+List of enable subcommands:.*\[\r\n\]+enable delete -- Enable breakpoints and delete when hit.*\[\r\n\]+enable display -- Enable some expressions to be displayed when program stops.*\[\r\n\]+enable once -- Enable breakpoints for one hit.*\[\r\n\]+Type \"help enable\" followed by enable subcommand name for full documentation..*\[\r\n\]+Command name abbreviations are allowed if unambiguous." "help enable"
+# test help exec-file
+gdb_test "help exec-file" "Use FILE as program for getting contents of pure memory..*\[\r\n\]+If FILE cannot be found as specified, your execution directory path.*\[\r\n\]+is searched for a command of that name..*\[\r\n\]+No arg means have no executable file." "help exec-file"
+# test help frame "f" abbreviation
+gdb_test "help f" "Select and print a stack frame..*\[\r\n\]+With no argument, print the selected stack frame. .See also \"info frame\".*\[\r\n\]+An argument specifies the frame to select..*\[\r\n\]+It can be a stack frame number or the address of the frame..*\[\r\n\]+With argument, nothing is printed if input is coming from.*\[\r\n\]+a command file or a user-defined command." "help frame \"f\" abbreviation"
+# test help frame
+gdb_test "help frame" "Select and print a stack frame..*\[\r\n\]+With no argument, print the selected stack frame. .See also \"info frame\"...*\[\r\n\]+An argument specifies the frame to select..*\[\r\n\]+It can be a stack frame number or the address of the frame..*\[\r\n\]+With argument, nothing is printed if input is coming from.*\[\r\n\]+a command file or a user-defined command." "help frame"
+# test help fg
+gdb_test "help fg" "Continue program being debugged.*" "help fg"
+# test help file
+gdb_test "help file" "Use FILE as program to be debugged..*\[\r\n\]+It is read for its symbols, for getting the contents of pure memory,.*\[\r\n\]+and it is the program executed when you use the `run' command..*\[\r\n\]+If FILE cannot be found as specified, your execution directory path.*\[\r\n\]+..PATH. is searched for a command of that name..*\[\r\n\]+No arg means to have no executable file and no symbols." "help file"
+# test help files
+gdb_test "help files" "Specifying.*" "help files"
+# test help finish
+gdb_test "help finish" "Execute until selected stack frame returns..*\[\r\n\]+Upon return, the value returned is printed and put in the value history." "help finish"
+# test help forward-search
+gdb_test "help forward-search" "Search for regular expression .see regex.3.. from last line listed..*" "help forward-search"
+# test help help "h" abbreviation
+gdb_test "help h" "Print list of commands." "help help \"h\" abbreviation"
+# test help help
+gdb_test "help help" "Print list of commands." "help help"
+# test help handle
+gdb_test "help handle" "Specify how to handle a signal..*" "help handle"
+# test help info "i" abbreviation
+gdb_test "help i" "Generic command for showing things about the program being debugged..*\[\r\n\]+List of info subcommands:.*\[\r\n\]+Type \"help info\" followed by info subcommand name for full documentation..*\[\r\n\]+Command name abbreviations are allowed if unambiguous." "help info \"i\" abbreviation"
+# test help info
+gdb_test "help info" "Generic command for showing things about the program being debugged..*\[\r\n\]+List of info subcommands:.*\[\r\n\]+Type \"help info\" followed by info subcommand name for full documentation..*\[\r\n\]+Command name abbreviations are allowed if unambiguous." "help info"
+# test help ignore
+gdb_test "help ignore" "Set ignore-count of breakpoint number N to COUNT..*\[\r\n\]+Usage is `ignore N COUNT'." "help ignore"
+# test help info address
+gdb_test "help info address" "Describe where symbol SYM is stored." "help info address"
+# test help info all-registers
+gdb_test "help info all-registers" "List of all registers and their contents, for selected stack frame..*\[\r\n\]+Register name as argument means describe only that register." "help info all-registers"
+# test help info args
+gdb_test "help info args" "Argument variables of current stack frame." "help info args"
+# test help info breakpoints
+gdb_test "help info breakpoints" "Status of user-settable breakpoints, or breakpoint number NUMBER..*\[\r\n\]+breakpoint set." "help info breakpoints"
+# test help info catch
+gdb_test "help info catch" "Exceptions that can be caught in the current stack frame." "help info catch"
+# test help info copying
+gdb_test "help info copying" "Conditions for redistributing copies of GDB." "help info copying"
+# test help info display
+gdb_test "help info display" "Expressions to display when program stops, with code numbers." "help info display"
+# test help info frame "f" abbreviation
+gdb_test "help info f" "All about selected stack frame, or frame at ADDR." "help info frame \"f\" abbreviation"
+# test help info frame
+gdb_test "help info frame" "All about selected stack frame, or frame at ADDR." "help info frame"
+# test help info files
+gdb_test "help info files" "Names of targets and files being debugged..*\[\r\n\]+Shows the entire stack of targets currently in use .including the exec-file,.*\[\r\n\]+core-file, and process, if any., as well as the symbol file name." "help info files"
+# test help info float
+gdb_test "help info float" "Print the status of the floating point unit" "help info float"
+# test help info functions
+gdb_test "help info functions" "All function names, or those matching REGEXP." "help info functions"
+# test help info line
+gdb_test "help info line" "Core addresses of the code for a source line..*\[\r\n\]+Line can be specified as.*\[\r\n\]+ LINENUM, to list around that line in current file,.*\[\r\n\]+ FILE:LINENUM, to list around that line in that file,.*\[\r\n\]+ FUNCTION, to list around beginning of that function,.*\[\r\n\]+ FILE:FUNCTION, to distinguish among like-named static functions..*\[\r\n\]+Default is to describe the last source line that was listed..*\[\r\n\]+This sets the default address for \"x\" to the line's first instruction.*\[\r\n\]+so that \"x.i\" suffices to start examining the machine code..*\[\r\n\]+The address is also stored as the value of \"._\"." "help info line"
+# test help info locals
+gdb_test "help info locals" "Local variables of current stack frame." "help info locals"
+# test help info program
+gdb_test "help info program" "Execution status of the program." "help info program"
+# test help info registers
+gdb_test "help info registers" "List of integer registers and their contents, for selected stack frame..*\[\r\n\]+Register name as argument means describe only that register." "help info registers"
+# test help info stack "s" abbreviation
+gdb_test "help info s" "Backtrace of the stack, or innermost COUNT frames." "help info stack \"s\" abbreviation"
+# test help info stack
+gdb_test "help info stack" "Backtrace of the stack, or innermost COUNT frames." "help info stack"
+# test help info set
+gdb_test "help info set" "Show all GDB settings." "help info set"
+# test help info signals
+gdb_test "help info signals" "What debugger does when program gets various signals.*" "help info signals"
+# test help info source
+gdb_test "help info source" "Information about the current source file." "help info source"
+# test help info sources
+gdb_test "help info sources" "Source files in the program." "help info sources"
+# test help info symbol
+gdb_test "help info symbol" "Describe what symbol is at location ADDR.*"
+# test help info target
+gdb_test "help info target" "Names of targets and files being debugged..*\[\r\n\]+Shows the entire stack of targets currently in use .including the exec-file,.*\[\r\n\]+core-file, and process, if any., as well as the symbol file name." "help info target"
+# test help info terminal
+gdb_test "help info terminal" "Print inferior's saved terminal status." "help info terminal"
+# test help info types
+gdb_test "help info types" "All type names, or those matching REGEXP." "help info types"
+# test help info variables
+gdb_test "help info variables" "All global and static variable names, or those matching REGEXP." "help info variables"
+# test help info warranty
+gdb_test "help info warranty" "Various kinds of warranty you do not have." "help info warranty"
+# test help info watchpoints
+gdb_test "help info watchpoints" "Synonym for ``info breakpoints''." "help info watchpoints"
+# test help inspect
+gdb_test "help inspect" "Same as \"print\" command, except that if you are running in the epoch.*\[\r\n\]+environment, the value is printed in its own window." "help inspect"
+# test help jump
+gdb_test "help jump" "Continue program being debugged at specified line or address..*\[\r\n\]+Give as argument either LINENUM or \[*\]+ADDR, where ADDR is an expression.*\[\r\n\]+for an address to start at." "help jump"
+# test help kill
+gdb_test "help kill" "Kill execution of program being debugged." "help kill"
+# test help list "l" abbreviation
+gdb_test "help l" "List specified function or line..*\[\r\n\]+With no argument, lists ten more lines after or around previous listing..*\[\r\n\]+\"list -\" lists the ten lines before a previous ten-line listing..*\[\r\n\]+One argument specifies a line, and ten lines are listed around that line..*\[\r\n\]+Two arguments with comma between specify starting and ending lines to list..*\[\r\n\]+Lines can be specified in these ways:.*\[\r\n\]+ LINENUM, to list around that line in current file,.*\[\r\n\]+ FILE:LINENUM, to list around that line in that file,.*\[\r\n\]+ FUNCTION, to list around beginning of that function,.*\[\r\n\]+ FILE:FUNCTION, to distinguish among like-named static functions..*\[\r\n\]+ \[*\]+ADDRESS, to list around the line containing that address..*\[\r\n\]+With two args if one is empty it stands for ten lines away from the other arg." "help list \"l\" abbreviation"
+# test help list
+gdb_test "help list" "List specified function or line..*\[\r\n\]+With no argument, lists ten more lines after or around previous listing..*\[\r\n\]+\"list -\" lists the ten lines before a previous ten-line listing..*\[\r\n\]+One argument specifies a line, and ten lines are listed around that line..*\[\r\n\]+Two arguments with comma between specify starting and ending lines to list..*\[\r\n\]+Lines can be specified in these ways:.*\[\r\n\]+ LINENUM, to list around that line in current file,.*\[\r\n\]+ FILE:LINENUM, to list around that line in that file,.*\[\r\n\]+ FUNCTION, to list around beginning of that function,.*\[\r\n\]+ FILE:FUNCTION, to distinguish among like-named static functions..*\[\r\n\]+ \[*\]+ADDRESS, to list around the line containing that address..*\[\r\n\]+With two args if one is empty it stands for ten lines away from the other arg." "help list"
+# test help load
+gdb_test "help load" "Dynamically load FILE into the running program, and record its symbols.*\[\r\n\]+for access from GDB." "help load"
+# test help make
+gdb_test "help make" "Run the ``make'' program using the rest of the line as arguments." "help make"
+# test help next "n" abbreviation
+gdb_test "help n" "Step program, proceeding through subroutine calls..*\[\r\n\]+Like the \"step\" command as long as subroutine calls do not happen;.*\[\r\n\]+when they do, the call is treated as one instruction..*\[\r\n\]+Argument N means do this N times .or till program stops for another reason.." "help next \"n\" abbreviation"
+# test help next
+gdb_test "help next" "Step program, proceeding through subroutine calls..*\[\r\n\]+Like the \"step\" command as long as subroutine calls do not happen;.*\[\r\n\]+when they do, the call is treated as one instruction..*\[\r\n\]+Argument N means do this N times .or till program stops for another reason.." "help next"
+# test help nexti
+gdb_test "help ni" "Step one instruction, but proceed through subroutine calls..*\[\r\n\]+Argument N means do this N times .or till program stops for another reason.." "help nexti"
+# all the commands that used to be here are now in "maintainance" instead
+# test help obscure
+gdb_test "help obscure" "Obscure features..*\[\r\n\]+List of commands:.*\[\r\n\]+Type \"help\" followed by command name for full documentation..*\[\r\n\]+Command name abbreviations are allowed if unambiguous." "help obscure"
+# test help output
+gdb_test "help output" "Like \"print\" but don't put in value history and don't print newline..*\[\r\n\]+This is useful in user-defined commands." "help output"
+# test help overlay
+gdb_test "help overlay" "Commands for debugging overlays.*"
+gdb_test "help overlay off" "Disable overlay debugging."
+gdb_test "help overlay manual" "Enable overlay debugging."
+gdb_test "help overlay auto" "Enable automatic overlay debugging."
+gdb_test "help overlay list" "List mappings of overlay sections."
+gdb_test "help overlay map" "Assert that an overlay section is mapped."
+gdb_test "help overlay unmap" "Assert that an overlay section is unmapped."
+gdb_test "help overlay load" "Read the overlay mapping state from the target."
+# test help print "p" abbreviation
+gdb_test "help p" "Print value of expression EXP..*\[\r\n\]+Variables accessible are those of the lexical environment of the selected.*\[\r\n\]+EXP may be preceded with /FMT, where FMT is a format letter.*\[\r\n\]+but no count or size letter .see \"x\" command.." "help print \"p\" abbreviation"
+# test help print
+gdb_test "help print" "Print value of expression EXP..*\[\r\n\]+Variables accessible are those of the lexical environment of the selected.*\[\r\n\]+EXP may be preceded with /FMT, where FMT is a format letter.*\[\r\n\]+but no count or size letter .see \"x\" command.." "help print"
+# test help path
+gdb_test "help path" "Add directory DIR.s. to beginning of search path for object files..*\[\r\n\]+.cwd in the path means the current working directory..*\[\r\n\]+This path is equivalent to the .PATH shell variable. It is a list of.*\[\r\n\]+directories, separated by colons. These directories are searched to find.*\[\r\n\]+fully linked executable files and separately compiled object files as needed." "help path"
+# test help printcmds
+gdb_test "help printcmds" "Undefined command: \"printcmds\". Try \"help\"." "help printcmds"
+# test help printf
+gdb_test "help printf" "printf \"printf format string\", arg1, arg2, arg3, ..., argn.*\[\r\n\]+This is useful for formatted output in user-defined commands." "help printf"
+# test help ptype
+gdb_test "help ptype" "Print definition of type.*" "help ptype"
+# test help pwd
+gdb_test "help pwd" "Print working directory. This is used for your program as well." "help pwd"
+# test help quit "q" abbreviation
+gdb_test "help q" "Exit gdb." "help quit \"q\" abbreviation"
+# test help quit
+gdb_test "help quit" "Exit gdb." "help quit"
+# test help run "r" abbreviation
+gdb_test "help r" "Start debugged program. You may specify arguments to give it..*\[\r\n\]+Args may include .*, or .*; they are expanded using \"sh\"..*\[\r\n\]+Input and output redirection with \".\", \".\", or \"..\" are also allowed..*\[\r\n\]+With no arguments, uses arguments last specified .with \"run\" or \"set args\"...*\[\r\n\]+To cancel previous arguments and run with no arguments,.*\[\r\n\]+use \"set args\" without arguments." "help run \"r\" abbreviation"
+# test help run
+gdb_test "help run" "Start debugged program. You may specify arguments to give it..*\[\r\n\]+Args may include .*, or .*; they are expanded using \"sh\"..*\[\r\n\]+Input and output redirection with \".\", \".\", or \"..\" are also allowed..*\[\r\n\]+With no arguments, uses arguments last specified .with \"run\" or \"set args\"...*\[\r\n\]+To cancel previous arguments and run with no arguments,.*\[\r\n\]+use \"set args\" without arguments." "help run"
+# test help rbreak
+gdb_test "help rbreak" "Set a breakpoint for all functions matching REGEXP." "help rbreak"
+# test help return
+gdb_test "help return" "Make selected stack frame return to its caller..*\[\r\n\]+Control remains in the debugger, but when you continue.*\[\r\n\]+execution will resume in the frame above the one now selected..*\[\r\n\]+If an argument is given, it is an expression for the value to return." "help return"
+# test help reverse-search
+gdb_test "help reverse-search" "Search backward for regular expression .see regex.3.. from last line listed..*" "help reverse-search"
+# test help running
+gdb_test "help running" "Running the program..*\[\r\n\]+List of commands:.*\[\r\n\]+Type \"help\" followed by command name for full documentation..*\[\r\n\]+Command name abbreviations are allowed if unambiguous." "help running"
+# test help step "s" abbreviation
+gdb_test "help s" "Step program until it reaches a different source line..*\[\r\n\]+Argument N means do this N times .or till program stops for another reason.." "help step \"s\" abbreviation"
+# test help step
+gdb_test "help step" "Step program until it reaches a different source line..*\[\r\n\]+Argument N means do this N times .or till program stops for another reason.." "help step #1"
+# test help search
+gdb_test "help search" "Search for regular expression .see regex.3.. from last line listed..*" "help search"
+# test help section
+gdb_test "help section" "Change the base address of section SECTION of the exec file to ADDR..*\[\r\n\]+This can be used if the exec file does not contain section addresses,.*\[\r\n\]+.such as in the a.out format., or when the addresses specified in the.*\[\r\n\]+file itself are wrong. Each section must be changed separately. The.*\[\r\n\]+``info files'' command lists all the sections and their addresses." "help section"
+#test help set annotate
+gdb_test "help set annotate" "Set annotation_level.*\[\r\n\]+0 == normal; 1 == fullname \\(for use when running under emacs\\).*\[\r\n\]+2 == output annotated suitably for use by programs that control GDB." "help set annotate"
+# test help set args
+gdb_test "help set args" "Set argument list to give program being debugged when it is started..*\[\r\n\]+Follow this command with any number of args, to be passed to the program."
+# test help set check "c" abbreviation
+gdb_test "help set c" "Set the status of the type/range checker.*\[\r\n\]+List of set check subcommands:.*\[\r\n\]+set check range -- Set range checking.*\[\r\n\]+set check type -- Set type checking.*\[\r\n\]+Type \"help set check\" followed by set check subcommand name for full documentation..*\[\r\n\]+Command name abbreviations are allowed if unambiguous." "help set check \"c\" abbreviation"
+# test help set check "ch" abbreviation
+gdb_test "help set ch" "Set the status of the type/range checker.*\[\r\n\]+List of set check subcommands:.*\[\r\n\]+set check range -- Set range checking.*\[\r\n\]+set check type -- Set type checking.*\[\r\n\]+Type \"help set check\" followed by set check subcommand name for full documentation..*\[\r\n\]+Command name abbreviations are allowed if unambiguous." "help set check \"ch\" abbreviation"
+# test help set check
+gdb_test "help set check" "Set the status of the type/range checker.*\[\r\n\]+List of set check subcommands:.*\[\r\n\]+set check range -- Set range checking.*\[\r\n\]+set check type -- Set type checking.*\[\r\n\]+Type \"help set check\" followed by set check subcommand name for full documentation..*\[\r\n\]+Command name abbreviations are allowed if unambiguous." "help set check"
+# test help set check range
+gdb_test "help set check range" "Set range checking. .on/warn/off/auto." "help set check range"
+# test help set check type
+gdb_test "help set check type" "Set type checking. .on/warn/off/auto." "help set check type"
+# test help set complaints
+gdb_test "help set complaints" "Set max number of complaints about incorrect symbols." "help set complaints"
+# test help set confirm
+gdb_test "help set confirm" "Set whether to confirm potentially dangerous operations." "help set confirm"
+# test help set editing
+gdb_test "help set editing" "Set editing of command lines as they are typed..*\[\r\n\]+Use \"on\" to enable the editing, and \"off\" to disable it..*\[\r\n\]+Without an argument, command line editing is enabled. To edit, use.*\[\r\n\]+EMACS-like or VI-like commands like control-P or ESC." "help set editing"
+# test help set environment
+gdb_test "help set environment" "Set environment variable value to give the program..*\[\r\n\]+Arguments are VAR VALUE where VAR is variable name and VALUE is value..*\[\r\n\]+VALUES of environment variables are uninterpreted strings..*\[\r\n\]+This does not affect the program until the next \"run\" command." "help set environment"
+# test help set height
+gdb_test "help set height" "Set number of lines gdb thinks are in a page." "help set height"
+# test help set history expansion
+gdb_test "help set history expansion" "Set history expansion on command input..*\[\r\n\]+Without an argument, history expansion is enabled." "help set history expansion"
+# test help set history filename
+gdb_test "help set history filename" "Set the filename in which to record the command history.*\[\r\n\]+ .the list of previous commands of which a record is kept.." "help set history filename"
+# test help set history save
+gdb_test "help set history save" "Set saving of the history record on exit..*\[\r\n\]+Use \"on\" to enable the saving, and \"off\" to disable it..*\[\r\n\]+Without an argument, saving is enabled." "help set history save"
+# test help set history size
+gdb_test "help set history size" "Set the size of the command history, .*\[\r\n\]+ie. the number of previous commands to keep a record of." "help set history size"
+# test help set history
+gdb_test "help set history" "Generic command for setting command history parameters..*\[\r\n\]+List of set history subcommands:.*\[\r\n\]+set history expansion -- Set history expansion on command input.*\[\r\n\]+set history filename -- Set the filename in which to record the command history.*\[\r\n\]+set history save -- Set saving of the history record on exit.*\[\r\n\]+set history size -- Set the size of the command history.*\[\r\n\]+Type \"help set history\" followed by set history subcommand name for full documentation..*\[\r\n\]+Command name abbreviations are allowed if unambiguous." "help set history"
+# test help set language
+gdb_test "help set language" "Set the current source language." "help set language"
+# test help set listsize
+gdb_test "help set listsize" "Set number of source lines gdb will list by default." "help set listsize"
+# test help set print "p" abbreviation
+# FIXME -- Ultrix hangs randomly on this very long output from gdb and
+# continues with its output only if something is sent to gdb.
+# Also, if the system is slow, it may time out because the output is large.
+gdb_test "help set p" ".*\[\r\n\]+Generic command for setting how things print..*\[\r\n\]+List of set print subcommands:.*\[\r\n\]+Type \"help set print\" followed by set print subcommand name for full documentation..*\[\r\n\]+Command name abbreviations are allowed if unambiguous." "help set print \"p\" abbreviatio"
+# test help set print "pr" abbreviation
+gdb_test "help set pr" ".*\[\r\n\]+Generic command for setting how things print..*\[\r\n\]+List of set print subcommands:.*\[\r\n\]+Type \"help set print\" followed by set print subcommand name for full documentation..*\[\r\n\]+Command name abbreviations are allowed if unambiguous." "help set print \"pr\" abbreviation"
+# test help set print
+gdb_test "help set print" ".*\[\r\n\]+Generic command for setting how things print..*\[\r\n\]+List of set print subcommands:.*\[\r\n\]+Type \"help set print\" followed by set print subcommand name for full documentation..*\[\r\n\]+Command name abbreviations are allowed if unambiguous." "help set print"
+# test help set print address
+gdb_test "help set print address" "Set printing of addresses." "help set print address"
+# test help set print array
+gdb_test "help set print array" "Set prettyprinting of arrays." "help set print array"
+# test help set print asm-demangle
+gdb_test "help set print asm-demangle" "Set demangling of C\[+\]+ names in disassembly listings." "help set print asm-demangle"
+# test help set print demangle
+gdb_test "help set print demangle" "Set demangling of encoded C\[+\]+ names when displaying symbols." "help set print demangle"
+# test help set print elements
+gdb_test "help set print elements" "Set limit on string chars or array elements to print..*\[\r\n\]+\"set print elements 0\" causes there to be no limit." "help set print elements"
+# test help set print object
+gdb_test "help set print object" "Set printing of object's derived type based on vtable info." "help set print object"
+# test help set print pretty
+gdb_test "help set print pretty" "Set prettyprinting of structures." "help set print pretty"
+# test help set print sevenbit-strings
+gdb_test "help set print sevenbit-strings" "Set printing of 8-bit characters in strings as .nnn." "help set print sevenbit-strings"
+# test help set print union
+gdb_test "help set print union" "Set printing of unions interior to structures." "help set print union"
+# test help set print vtbl
+gdb_test "help set print vtbl" "Set printing of C\[+\]+ virtual function tables." "help set print vtbl"
+# test help set prompt
+gdb_test "help set prompt" "Set gdb's prompt" "help set prompt"
+# test help set radix
+gdb_test "help set radix" "Set default input and output number radices.*\[\r\n\]+Use \'set input-radix\' or \'set output-radix\' to independently set each..*\[\r\n\]+Without an argument, sets both radices back to the default value of 10..*\[\r\n\]+" "help set radix"
+# test help set symbol-reloading
+gdb_test "help set symbol-reloading" "Set dynamic symbol table reloading multiple times in one run." "help set symbol-reloading"
+# test help set variable
+gdb_test "help set variable" ".*\[\r\n\]+Evaluate expression EXP and assign result to variable VAR, using assignment.*\[\r\n\]+syntax appropriate for the current language .VAR = EXP or VAR := EXP for.*\[\r\n\]+example.. VAR may be a debugger \"convenience\" variable .names starting.*\[\r\n\]+with \\\$., a register .a few standard names starting with \\\$., or an actual.*\[\r\n\]+variable in the program being debugged. EXP is any valid expression.*\[\r\n\]+This may usually be abbreviated to simply \"set\"." "help set variable"
+# test help set verbose
+gdb_test "help set verbose" "Set verbosity." "help set verbose"
+#test help set width
+gdb_test "help set width" "Set number of characters gdb thinks are in a line." "help set width"
+# test help set write
+# This is only supported on targets which use exec.o.
+gdb_test "help set write" "Set writing into executable and core files." "help set write"
+# test help set
+# FIXME -- Ultrix hangs randomly on this very long output from gdb and
+# continues with its output only if something is sent to gdb.
+# Also, if the system is slow, it may time out because the output is large.
+#gdb_test "help set" ".*\[\r\n\]+Evaluate expression EXP and assign result to variable VAR, using assignment.*\[\r\n\]+syntax appropriate for the current language .VAR = EXP or VAR := EXP for.*\[\r\n\]+example.. VAR may be a debugger \"convenience\" variable .names starting.*\[\r\n\]+with \\\$., a register .a few standard names starting with \\\$., or an actual.*\[\r\n\]+variable in the program being debugged. EXP is any valid expression.*\[\r\n\]+set listsize -- Set number of source lines gdb will list by default.*\[\r\n\]+Type \"help set\" followed by set subcommand name for full documentation..*\[\r\n\]+Command name abbreviations are allowed if unambiguous..*\[\r\n\]+" "help set"
+# test help shell
+gdb_test "help shell" "Execute the rest of the line as a shell command. .*\[\r\n\]+With no arguments, run an inferior shell." "help shell"
+#test help show annotate
+gdb_test "help show annotate" "Show annotation_level.*\[\r\n\]+0 == normal; 1 == fullname \\(for use when running under emacs\\).*\[\r\n\]+2 == output annotated suitably for use by programs that control GDB." "help show annotate"
+# test help show args
+gdb_test "help show args" "Show argument list to give program being debugged when it is started..*\[\r\n\]+Follow this command with any number of args, to be passed to the program."
+# test help show check "c" abbreviation
+gdb_test "help show c" "Show the status of the type/range checker.*\[\r\n\]+List of show check subcommands:.*\[\r\n\]+show check range -- Show range checking.*\[\r\n\]+show check type -- Show type checking.*\[\r\n\]+Type \"help show check\" followed by show check subcommand name for full documentation..*\[\r\n\]+Command name abbreviations are allowed if unambiguous." "help show check \"c\" abbreviation"
+# test help show check
+gdb_test "help show check" "Show the status of the type/range checker.*\[\r\n\]+List of show check subcommands:.*\[\r\n\]+show check range -- Show range checking.*\[\r\n\]+show check type -- Show type checking.*\[\r\n\]+Type \"help show check\" followed by show check subcommand name for full documentation..*\[\r\n\]+Command name abbreviations are allowed if unambiguous." "help show check"
+# test help show check range
+gdb_test "help show check range" "Show range checking. .on/warn/off/auto." "help show check range"
+# test help show check type
+gdb_test "help show check type" "Show type checking. .on/warn/off/auto." "help show check type"
+# test help show commands
+gdb_test "help show commands" "Show the history of commands you typed..*\[\r\n\]+You can supply a command number to start with, or a `\[+\]' to start after.*\[\r\n\]+the previous command number shown." "help show commands"
+# test help show complaints
+gdb_test "help show complaints" "Show max number of complaints about incorrect symbols." "help show complaints"
+# test help show confirm
+gdb_test "help show confirm" "Show whether to confirm potentially dangerous operations." "help show confirm"
+# test help show convenience
+gdb_test "help show convenience" "Debugger convenience .\".foo\". variables..*\[\r\n\]+These variables are created when you assign them values;.*\[\r\n\]+thus, \"print .foo=1\" gives \".foo\" the value 1. Values may be any type..*\[\r\n\]+A few convenience variables are given values automatically:.*\[\r\n\]+\"._\"holds the last address examined with \"x\" or \"info lines\",.*\[\r\n\]+\".__\" holds the contents of the last address examined with \"x\"." "help show convenience"
+# test help show directories
+gdb_test "help show directories" "Current search path for finding source files..*\[\r\n\]+.cwd in the path means the current working directory..*\[\r\n\]+.cdir in the path means the compilation directory of the source file." "help show directories"
+# test help show editing
+gdb_test "help show editing" "Show editing of command lines as they are typed..*\[\r\n\]+Use \"on\" to enable the editing, and \"off\" to disable it..*\[\r\n\]+Without an argument, command line editing is enabled. To edit, use.*\[\r\n\]+EMACS-like or VI-like commands like control-P or ESC." "help show editing"
+# test help show environment
+gdb_test "help show environment" "The environment to give the program, or one variable's value..*\[\r\n\]+With an argument VAR, prints the value of environment variable VAR to.*\[\r\n\]+give the program being debugged. With no arguments, prints the entire.*\[\r\n\]+environment to be given to the program." "help show environment"
+# test help show height
+gdb_test "help show height" "Show number of lines gdb thinks are in a page." "help show height"
+# test help show history expansion
+gdb_test "help show history expansion" "Show history expansion on command input..*\[\r\n\]+Without an argument, history expansion is enabled." "help show history expansion"
+# test help show history filename
+gdb_test "help show history filename" "Show the filename in which to record the command history.*\[\r\n\]+ .the list of previous commands of which a record is kept.." "help show history filename"
+# test help show history save
+gdb_test "help show history save" "Show saving of the history record on exit..*\[\r\n\]+Use \"on\" to enable the saving, and \"off\" to disable it..*\[\r\n\]+Without an argument, saving is enabled." "help show history save"
+# test help show history size
+gdb_test "help show history size" "Show the size of the command history, .*\[\r\n\]+ie. the number of previous commands to keep a record of." "help show history size"
+# test help show history
+gdb_test "help show history" "Generic command for showing command history parameters..*\[\r\n\]+List of show history subcommands:.*\[\r\n\]+show history expansion -- Show history expansion on command input.*\[\r\n\]+show history filename -- Show the filename in which to record the command history.*\[\r\n\]+show history save -- Show saving of the history record on exit.*\[\r\n\]+show history size -- Show the size of the command history.*\[\r\n\]+Type \"help show history\" followed by show history subcommand name for full documentation..*\[\r\n\]+Command name abbreviations are allowed if unambiguous." "help show history"
+# test help show language
+gdb_test "help show language" "Show the current source language." "help show language"
+# test help show listsize
+gdb_test "help show listsize" "Show number of source lines gdb will list by default." "help show listsize"
+# test help show print "p" abbreviation
+gdb_test "help show p" "Generic command for showing print settings..*\[\r\n\]+List of show print subcommands:.*\[\r\n\]+Type \"help show print\" followed by show print subcommand name for full documentation..*\[\r\n\]+Command name abbreviations are allowed if unambiguous." "help show print \"p\" abbreviation"
+# test help show print "pr" abbreviation
+gdb_test "help show pr" "Generic command for showing print settings..*\[\r\n\]+List of show print subcommands:.*\[\r\n\]+Type \"help show print\" followed by show print subcommand name for full documentation..*\[\r\n\]+Command name abbreviations are allowed if unambiguous." "help show print \"pr\" abbreviation"
+# test help show print
+gdb_test "help show print" "Generic command for showing print settings..*\[\r\n\]+List of show print subcommands:.*\[\r\n\]+Type \"help show print\" followed by show print subcommand name for full documentation..*\[\r\n\]+Command name abbreviations are allowed if unambiguous." "help show print"
+# test help show paths
+gdb_test "help show paths" "Current search path for finding object files..*\[\r\n\]+.cwd in the path means the current working directory..*\[\r\n\]+This path is equivalent to the .PATH shell variable. It is a list of.*\[\r\n\]+directories, separated by colons. These directories are searched to find.*\[\r\n\]+fully linked executable files and separately compiled object files as needed." "help show paths"
+# test help show print address
+gdb_test "help show print address" "Show printing of addresses." "help show print address"
+# test help show print array
+gdb_test "help show print array" "Show prettyprinting of arrays." "help show print array"
+# test help show print asm-demangle
+gdb_test "help show print asm-demangle" "Show demangling of C\[+\]+ names in disassembly listings." "help show print asm-demangle"
+# test help show print demangle
+gdb_test "help show print demangle" "Show demangling of encoded C\[+\]+ names when displaying symbols." "help show print demangle"
+# test help show print elements
+gdb_test "help show print elements" "Show limit on string chars or array elements to print..*\[\r\n\]+\"set print elements 0\" causes there to be no limit." "help show print elements"
+# test help show print object
+gdb_test "help show print object" "Show printing of object's derived type based on vtable info." "help show print object"
+# test help show print pretty
+gdb_test "help show print pretty" "Show prettyprinting of structures." "help show print pretty"
+# test help show print sevenbit-strings
+gdb_test "help show print sevenbit-strings" "Show printing of 8-bit characters in strings as .nnn." "help show print sevenbit-strings"
+# test help show print union
+gdb_test "help show print union" "Show printing of unions interior to structures." "help show print union"
+# test help show print vtbl
+gdb_test "help show print vtbl" "Show printing of C\[+\]+ virtual function tables." "help show print vtbl"
+# test help show prompt
+gdb_test "help show prompt" "Show gdb's prompt" "help show prompt"
+# test help show radix
+gdb_test "help show radix" "Show the default input and output number radices.*\[\r\n\]+Use \'show input-radix\' or \'show output-radix\' to independently show each.*\[\r\n\]+" "help show radix"
+# test help show symbol-reloading
+gdb_test "help show symbol-reloading" "Show dynamic symbol table reloading multiple times in one run." "help show symbol-reloading"
+# test help show user
+gdb_test "help show user" "Show definitions of user defined commands..*\[\r\n\]+Argument is the name of the user defined command..*\[\r\n\]+With no argument, show definitions of all user defined commands." "help show user"
+# test help show values
+gdb_test "help show values" "Elements of value history around item number IDX .or last ten.." "help show values"
+# test help show verbose
+gdb_test "help show verbose" "Show verbosity..*" "help show verbose"
+# test help show version
+gdb_test "help show version" "Show what version of GDB this is." "help show version"
+# test help show width
+gdb_test "help show width" "Show number of characters gdb thinks are in a line." "help show width"
+# test help show write
+# This is only supported on targets which use exec.o.
+gdb_test "help show write" "Show writing into executable and core files." "help show write"
+# test help show
+# FIXME -- Ultrix hangs randomly on this very long output from gdb and
+# continues with its output only if something is sent to gdb.
+# Also, if the system is slow, it may time out because the output is large.
+#gdb_test "help show" "Generic command for showing things about the debugger..*\[\r\n\]+List of show subcommands:.*\[\r\n\]+show listsize -- Show number of source lines gdb will list by default.*\[\r\n\]+show directories -- Current search path for finding source files.*\[\r\n\]+Type \"help show\" followed by show subcommand name for full documentation..*\[\r\n\]+Command name abbreviations are allowed if unambiguous." "help show"
+# test help step
+gdb_test "help step" "Step program until it reaches a different source line..*\[\r\n\]+Argument N means do this N times .or till program stops for another reason.." "help step #2"
+# test help stepi "si" abbreviation
+gdb_test "help si" "Step one instruction exactly..*\[\r\n\]+Argument N means do this N times .or till program stops for another reason.." "help stepi \"si\" abbreviation"
+# test help stepi
+gdb_test "help stepi" "Step one instruction exactly..*\[\r\n\]+Argument N means do this N times .or till program stops for another reason.." "help stepi"
+# test help signal
+gdb_test "help signal" "Continue program giving it signal.*" "help signal"
+# test help source
+# vxgdb reads .vxgdbinit
+gdb_test "help source" "Read commands from a file named FILE..*\[\r\n\]+Note that the file \"\[^\"\]*\" is read automatically in this way.*\[\r\n\]+when gdb is started." "help source"
+# test help stack
+gdb_test "help stack" "Examining the stack..*\[\r\n\]+When the program being debugged stops, gdb selects the innermost frame..*\[\r\n\]+The commands below can be used to select other frames by number or address..*\[\r\n\]+List of commands:.*\[\r\n\]+backtrace -- Print backtrace of all stack frames.*\[\r\n\]+bt -- Print backtrace of all stack frames.*\[\r\n\]+down -- Select and print stack frame called by this one.*\[\r\n\]+frame -- Select and print a stack frame.*\[\r\n\]+return -- Make selected stack frame return to its caller.*\[\r\n\]+select-frame -- Select a stack frame without printing anything.*\[\r\n\]+up -- Select and print stack frame that called this one.*\[\r\n\]+Type \"help\" followed by command name for full documentation..*\[\r\n\]+Command name abbreviations are allowed if unambiguous." "help stack"
+# test help status
+gdb_test "help status" "Status inquiries..*\[\r\n\]+List of commands:.*\[\r\n\]+info -- Generic command for showing things about the program being debugged.*\[\r\n\]+show -- Generic command for showing things about the debugger.*\[\r\n\]+Type \"help\" followed by command name for full documentation..*\[\r\n\]+Command name abbreviations are allowed if unambiguous." "help status"
+# test help support
+# FIXME -- Ultrix hangs randomly on this very long output from gdb and
+# continues with its output only if something is sent to gdb.
+# Also, if the system is slow, it may time out because the output is large.
+#gdb_test "help support" "Support facilities..*\[\r\n\]+List of commands:.*\[\r\n\]+show confirm -- Show whether to confirm potentially dangerous operations.*\[\r\n\]+show history -- Generic command for showing command history parameters.*\[\r\n\]+down-silently -- Same as the `down' command.*\[\r\n\]+up-silently -- Same as the `up' command.*\[\r\n\]+Type \"help\" followed by command name for full documentation..*\[\r\n\]+Command name abbreviations are allowed if unambiguous." "help support"
+# test help symbol-file
+gdb_test "help symbol-file" "Load symbol table from executable file FILE..*\[\r\n\]+The `file' command can also load symbol tables, as well as setting the file.*\[\r\n\]+to execute." "help symbol-file"
+# test help target child
+gdb_test "help target child" "Unix child process .started by the \"run\" command..*|Undefined target command: \"child\". Try \"help target\"." "help target child"
+# test help target procfs
+gdb_test "help target procfs" "Unix /proc child process .started by the \"run\" command.*|Undefined target command: \"procfs\". Try \"help target\"." "help target procfs (procfs version)"
+# test help target core
+gdb_test "help target core" ".*Use a core file as a target.*Specify the filename of the core file.*|(Undefined target command: \"core\". Try \"help target\".)" "help target core"
+# test help target exec
+gdb_test "help target exec" "Use an executable file as a target..*\[\r\n\]+Specify the filename of the executable file." "help target exec"
+# test help target remote
+gdb_test "help target remote" "Use a remote computer via a serial line, using a gdb-specific protocol..*\[\r\n\]+Specify the serial device it is connected to .e.g. /dev/ttya..*" "help target remote"
+# test help target
+# the child process target may be "target child" or "target procfs"
+gdb_test "help target" "Connect to a target machine or process..*\[\r\n\]+The first argument is the type or protocol of the target machine..*\[\r\n\]+Remaining arguments are interpreted by the target protocol. For more.*\[\r\n\]+information on the arguments for a particular protocol, type.*\[\r\n\]+`help target ' followed by the protocol name..*\[\r\n\]+List of target subcommands:.*\[\r\n\]+target exec -- Use an executable file as a target.*\[\r\n\]+Type \"help target\" followed by target subcommand name for full documentation..*\[\r\n\]+Command name abbreviations are allowed if unambiguous." "help target"
+# test help tbreak
+gdb_test "help tbreak" "Set a temporary breakpoint.*" "help tbreak"
+# test help tty
+gdb_test "help tty" "Set terminal for future runs of program being debugged." "help tty"
+# test help until "u" abbreviation
+gdb_test "help u" "Execute until the program reaches a source line greater than the current.*\[\r\n\]+or a specified line or address or function .same args as break command...*\[\r\n\]+Execution will also stop upon exit from the current stack frame." "help until \"u\" abbreviation"
+# test help until
+gdb_test "help until" "Execute until the program reaches a source line greater than the current.*\[\r\n\]+or a specified line or address or function .same args as break command...*\[\r\n\]+Execution will also stop upon exit from the current stack frame." "help until"
+# test help undisplay
+gdb_test "help undisplay" "Cancel some expressions to be displayed when program stops..*\[\r\n\]+Arguments are the code numbers of the expressions to stop displaying..*\[\r\n\]+No argument means cancel all automatic-display expressions..*\[\r\n\]+\"delete display\" has the same effect as this command..*\[\r\n\]+Do \"info display\" to see current list of code numbers." "help undisplay"
+# test help unset environment
+gdb_test "help unset environment" "Cancel environment variable VAR for the program..*\[\r\n\]+This does not affect the program until the next \"run\" command." "help unset environment"
+# test help unset
+gdb_test "help unset" "Complement to certain \"set\" commands.*\[\r\n\]+List of unset subcommands:.*\[\r\n\]+unset environment -- Cancel environment variable VAR for the program.*\[\r\n\]+Type \"help unset\" followed by unset subcommand name for full documentation..*\[\r\n\]+Command name abbreviations are allowed if unambiguous." "help unset"
+# test help up
+gdb_test "help up" "Select and print stack frame that called this one..*\[\r\n\]+An argument says how many frames up to go." "help up"
+# test help up-silently
+gdb_test "help up-silently" "Same as the `up' command, but does not print anything..*\[\r\n\]+This is useful in command scripts." "help up-silently"
+# test help user-defined
+gdb_test "help user-defined" "User-defined commands..*\[\r\n\]+The commands in this class are those defined by the user..*\[\r\n\]+Use the \"define\" command to define a command..*\[\r\n\]+List of commands:.*\[\r\n\]+Type \"help\" followed by command name for full documentation..*\[\r\n\]+Command name abbreviations are allowed if unambiguous." "help user-defined"
+# test help watch
+gdb_test "help watch" "Set a watchpoint for an expression..*\[\r\n\]+A watchpoint stops execution of your program whenever the value of.*\[\r\n\]+an expression changes." "help watch"
+# test help whatis
+gdb_test "help whatis" "Print data type of expression EXP." "help whatis"
+# test help where
+gdb_test "help where" "Print backtrace of all stack frames, or innermost COUNT frames..*\[\r\n\]+With a negative argument, print outermost -COUNT frames..*\[\r\n\]+Use of the 'full' qualifier also prints the values of the local variables." "help where"
+# test help x
+gdb_test "help x" "Examine memory: x/FMT ADDRESS..*\[\r\n\]+ADDRESS is an expression for the memory address to examine..*\[\r\n\]+FMT is a repeat count followed by a format letter and a size letter..*\[\r\n\]+Defaults for format and size letters are those previously used..*\[\r\n\]+Default count is 1. Default address is following last thing printed.*\[\r\n\]+with this command or \"print\"." "help x"
+# test help info bogus-gdb-command
+gdb_test "help info bogus-gdb-command" "Undefined info command: \"bogus-gdb-command\". Try \"help info\"." "help info bogus-gdb-command"
+# test help gotcha
+gdb_test "help gotcha" "Undefined command: \"gotcha\". Try \"help\"." "help gotcha"
diff --git a/gdb/testsuite/gdb.base/i486-elf.u b/gdb/testsuite/gdb.base/i486-elf.u
new file mode 100644
index 00000000000..882338b9dea
--- /dev/null
+++ b/gdb/testsuite/gdb.base/i486-elf.u
@@ -0,0 +1,287 @@
+begin 777 i486-elf
+M?T5,1@$! 0 ( P ! W(($"#0 !\+@ #0 ( %
+M "@ %0 1 8 T -( $" "@ H 4 P -0
+M !, ! ! - #2 ! @ * 8
+M "@& % ! $ !<!@ 7)8$" "4 2 ( < $
+M @ ( & " E@0( ' !P O=7-R+VQI8B]L:6)C
+M+G-O+C$ , , !@ L * ! (
+M $ 4 # " D '
+M $ "<@@0(' !( * I)@$" 1 /'_#P &"6! @$
+M$0 + !@ !<A@0( !$ \?\? K(($"$ 2 )@ /"6! @
+M $0#Q_RT #,@@0( !( R /(8$" 0 1 H /P +R"
+M! @ $@ $D !DE@0( !$ \?]? @)8$" 1 /'_ %]C
+M;&5A;G5P %]E;F0 7V5N=FER;VX 7V5T97AT &%T97AI= !?961A=&$ 97AI
+M= !?;&EB7W9E<G-I;VX 7U]F<'-T87)T %]'3$]"04Q?3T9&4T547U1!0DQ%
+M7P!?1%E.04U)0P O=7-R+VQI8B]L:6)C+G-O+C$ '"6! @' 0 =)8$" <%
+M !XE@0(!PD 'R6! @'!P PP /\U:)8$"/\E;)8$" #_)7"6! AH
+M .G@_____R5TE@0(: @ #IT/____\E>)8$"&@0 Z<#_____)7R6
+M! AH& .FP____:@!J (OL4KB<@@0(A<!T#6B<@@0(Z+;___^#Q 2X@)8$
+M"(7 = 7HI?___V@XA@0(Z)O___^+10B-5(40B15@E@0(4HU5#%)0Z%_____H
+MCO___^@! 0 @\0,4.B0____:@"X 0 )H !P#TP^L&,\#K ,G#58OL
+MZ_60D)#K!C/ ZP#)PU6+[.OUD)"0ZP8SP.L R<-5B^SK]9"0D.L&,\#K ,G#
+M58OLZ_60D)#K!C/ ZP#)PU6+[.OUD)"0ZP8SP.L R<-5B^SK]9"0D.L&,\#K
+M ,G#58OLZ_60D)#K!C/ ZP#)PU6+[.OUD)"0ZP8SP.L R<-5B^SK]9"0D.L&
+M,\#K ,G#58OLZ_60D)#K!C/ ZP#)PU6+[.OUD)"0ZP8SP.L R<-5B^SK]9"0
+MD.L*W05 A@0(ZP#)PU6+[.OQD)"0ZPK=!4B&! CK ,G#58OLZ_&0D)#I\P$
+M )#&!?B7! @ Q@5TEP0( <8%.I<$" )FQP5LEP0( P!FQP5<EP0(! !FQP4$
+MEP0(!0#'!1"7! @& QP7PE@0(!P ,<%])8$" @ #'!6B7! @)
+MQP7\E@0("@ ,<%>)<$" L "A4(8$"*,\EP0(H5B&! BC#)<$"*%4A@0(
+MHPB7! B@^)<$"*+4EP0(H'27! BB.)<$"* ZEP0(HOB6! AFH6R7! AFHWR7
+M! AFH5R7! AFHTB7! AFH027! AFHX"7! BA$)<$"*,<EP0(H?"6! BCC)<$
+M"*'TE@0(HU"7! BA:)<$"*/PEP0(H?R6! BC0)<$"*%XEP0(HV"7! BA/)<$
+M"*/@EP0(H0R7! BC+)<$"*$(EP0(HRB7! C'!827! CXEP0(QP7LEP0(=)<$
+M",<%B)<$"#J7! C'!>B7! ALEP0(QP6<EP0(7)<$",<% )<$" 27! C'!4R7
+M! @0EP0(QP64EP0(\)8$",<%6)<$"/26! C'!7"7! AHEP0(QP7<EP0(_)8$
+M",<%&)<$"'B7! C'!=B7! @\EP0(QP6@EP0(")<$",<%))<$" ( #'!127
+M! @" QP60F 0( 0 ,<%_)<$" $ "AF)<$"*, F 0(9J&<F 0(9J.4
+MF 0(R<-5B^SI!O[__Y ## ,A"
+M :4 ("6! @ **"! BR@@0(PH($"-*"! @!
+M : P "(@@0(#0 #B&! @$ Z( $" 4 #L@00(!@ "R!
+M! @* >P L 0 %0 # 9)8$" ( @ %
+M !$ 7 :(($" $
+M 0 \?\ U( $" # $ .B ! @ P " L
+M@00( , P [($$" # 0 &B"! @ P %
+M "(@@0( , !@ C(($" # < -R"! @ P (
+M XA@0( , "0 /(8$" # H %R6! @
+M P + !DE@0( , # @)8$" # T /"6! @
+M P . , #P # !
+M P 1 , $@ # !,
+M P 4 H 0 \?\1 $ /'_
+M& ! #Q_R0 0 \?\L $
+M /'_-@ ! #Q_ST !,@P0(#0 !( " !) \)8$" 0
+M 1 X 5@ /26! @$ $0 . &4 XA@0( !( "0!K ^)8$
+M" ( 1 X @0 #2$! @! @ $@ ( (8 #\E@0(! !$ #@"4
+M )<$" 0 1 X K0 )R"! @< $@ +8 "DF 0( !$ \?^[
+M !)<$" ( 1 X S )R#! @- $@ ( .( (EP0(" !$
+M#@#K $)<$" 0 1 X \0 -R"! @ $@ ( /@ 4EP0(!
+M !$ #@ # 0 8)8$" 0 1 L # $ !B7! @$ $0 . "0! <EP0(
+M" !$ #@ P 0 ))<$" 0 1 X . $ %R#! @- $@ ( $L! H
+MEP0($ !$ #@!: 0 7(8$" 1 /'_80$ #B7! @" $0 . '4!
+M ZEP0( 0 !$ #@"% 0 /)<$" 0 1 X C0$ $"7! @( $0 .
+M *$! "L@@0(0 !( "H 0 8)8$" 0 A L L $ -R#! @-
+M$@ ( +P! #\@P0(#0 !( " #1 0 2)<$" 0 1 X Y@$ $R7! @$
+M $0 . /0! #PE@0( !$ \?_[ 0 ?(,$" T 2 @ " ( %"7
+M! @( $0 . !T" !8EP0(! !$ #@ T @ K(,$" T 2 @ /P(
+M %R7! @" $0 . $X" ,A 0($0 !( " !; @ S(($" 2
+M8 ( &"7! @( $0 . '8" !HEP0(! !$ #@!] @ ;)<$" ( 1
+M X A0( '"7! @$ $0 . )0" !TEP0( 0 !$ #@"B @ >)<$" 0
+M 1 X L@( 'R7! @$ $0 . , " " EP0(! !$ #@#7 @ /(8$
+M" 0 1 H Y ( $N#! @ $@ ( .P" "$EP0(! !$ #@#[ @
+MB)<$" 0 1 X $P, (R7! @( $0 . "8# "\@@0( !( P
+M P E)<$" 0 1 X 10, )B7! @$ $0 . $P# !DE@0( !$
+M\?]B P G)<$" 0 1 X >0, *"7! @$ $0 . (H# !<E@0(!
+M !$ "P"< P I)<$"!@ 1 X I@, +R7! @8 $0 . + # #4EP0(
+M @ !$ #@"] P V)<$" 0 1 X S0, -R7! @$ $0 . .,# @
+MA 0($0 !( " #Q P O(,$" T 2 @ P0 ("6! @ $0#Q_PP$
+M #@EP0(" !$ #@ :! Z)<$" 0 1 X *@0 .R#! @- $@ (
+M #T$ #LEP0(! !$ #@!3! \)<$" @ 1 X 8 0 (B"! @
+M$@ & &8$ #XEP0( 0 !$ #@!M! _)<$" 0 1 X =00 &R#! @-
+M $@ ( (H$ F 0(D !$ #@"1! C(,$" T 2 @ I00 )"8
+M! @$ $0 . *\$ "4F 0(" !$ #@"X! S(,$" T 2 @ S 0
+M )R8! @( $0 . !I-#@V+F5L9@!C<G0Q+G, 8W)T:2YS '9A;'5E<RU8
+M="YC &=D8FUE+F, <VA?9&%T82YC &-R=&XN<P!V7V-H87)?9G5N8P!V7W-I
+M9VYE9%]I;G0 =E]U;G-I9VYE9%]I;G0 7V9I;FD =E]U;G-I9VYE9%]C:&%R
+M7V%R<F%Y &UA:6X =E]S:6=N961?;&]N9P!V7W5N<VEG;F5D7W-H;W)T7W!O
+M:6YT97( 7V-L96%N=7 7V5N9 !V7W5N<VEG;F5D7W-H;W)T '9?=6YS:6=N
+M961?<VAO<G1?9G5N8P!V7V1O=6)L90!V7VEN= !?<W1A<G0 ;F]N<')I;6%R
+M>0!?96YV:7)O;@!V7W5N<VEG;F5D7VQO;F=?<&]I;G1E<@!V7VEN=%]A<G)A
+M>0!P<FEM87)Y '9?<VEG;F5D7V-H87)?9G5N8P!V7V1O=6)L95]A<G)A>0!?
+M971E>'0 =E]S:6=N961?8VAA<E]A<G)A>0!V7W5N<VEG;F5D7V-H87( =E]F
+M;&]A= !V7W-I9VYE9%]L;VYG7V%R<F%Y &%T97AI= !E;G9I<F]N '9?;&]N
+M9U]F=6YC '9?=6YS:6=N961?;&]N9U]F=6YC '9?<VEG;F5D7W-H;W)T7V%R
+M<F%Y '9?:6YT7W!O:6YT97( 7V5D871A '9?<VAO<G1?9G5N8P!V7W5N<VEG
+M;F5D7VEN=%]A<G)A>0!V7W5N<VEG;F5D7VEN=%]P;VEN=&5R '9?:6YT7V9U
+M;F, =E]S:6=N961?<VAO<G0 =E]F;&]A=%]F=6YC &5X:70 =E]U;G-I9VYE
+M9%]L;VYG7V%R<F%Y '9?;&]N9P!V7W-H;W)T '9?;&]N9U]P;VEN=&5R '9?
+M<VEG;F5D7V-H87( =E]U;G-I9VYE9%]L;VYG '9?<VAO<G1?87)R87D =E]U
+M;G-I9VYE9%]S:&]R=%]A<G)A>0!?;&EB7W9E<G-I;VX 7VUC;W5N= !V7V-H
+M87)?<&]I;G1E<@!V7W5N<VEG;F5D7V-H87)?<&]I;G1E<@!V7W-I9VYE9%]I
+M;G1?87)R87D 7U]F<'-T87)T '9?<VEG;F5D7VEN=%]P;VEN=&5R '-?;&EN
+M:P!?1TQ/0D%,7T]&1E-%5%]404),15\ =E]S:6=N961?<VAO<G1?<&]I;G1E
+M<@!V7V1O=6)L95]P;VEN=&5R %]?;&]N9V1O=6)L95]U<V5D '9?<W1R=6-T
+M,0!V7W-T<G5C=#( =E]C:&%R7V%R<F%Y '9?9FQO871?<&]I;G1E<@!V7W-I
+M9VYE9%]L;VYG7W!O:6YT97( =E]D;W5B;&5?9G5N8P!V7W-I9VYE9%]I;G1?
+M9G5N8P!?1%E.04U)0P!V7V9L;V%T7V%R<F%Y '9?<VAO<G1?<&]I;G1E<@!V
+M7W-I9VYE9%]L;VYG7V9U;F, =E]S:6=N961?8VAA<E]P;VEN=&5R '9?;&]N
+M9U]A<G)A>0!?:6YI= !V7V-H87( 8VQU;FME<@!V7W5N<VEG;F5D7V-H87)?
+M9G5N8P!U7VQI;FL =E]S:6=N961?<VAO<G1?9G5N8P!S<&]R='-C87( =E]U
+M;FEO;C( =E]U;G-I9VYE9%]I;G1?9G5N8P!V7W5N:6]N N:6YT97)P "YH
+M87-H "YD>6YS>6T +F1Y;G-T<@ N<F5L+G!L= N:6YI= N<&QT "YT97AT
+M "YF:6YI "YR;V1A=&$ +F1A=&$ +F=O= N9'EN86UI8P N8G-S "YS>6UT
+M86( +G-T<G1A8@ N<VAS=')T86( +F-O;6UE;G0 +F1E8G5G "YL:6YE $ H
+M(REL:6)C+6DS.#8Z;&EB8RUI,S@V+V-S=2]C<G0Q+G,),2XQ. !A<SH@*%-#
+M1$4I(#4N," @,#0O,3DO.3 0"@C*6QI8F,M:3,X-CIC<W4O8W)T:2YS"3$N
+M,@!A<SH@*%-#1$4I(#4N," @,#0O,3DO.3 0"@C*6QI8F,M<&]R=#IG96XO
+M=F%L=65S+5AT+F,),2XS $ H(REL:6)C.FEN8R]S>6YO;GEM<RYH"3$N,S,
+M0"@C*6AE860Z;6%T:"YH"3(N,3$N,2XR-P!A8V]M<#H@*%-#1$4I(#4N," @
+M,#0O,3DO.3 ;W!T:6TZ("A30T1%*2 U+C @(# T+S$Y+SDP &%S.B H4T-$
+M12D@-2XP(" P-"\Q.2\Y, !A8V]M<#H@*%-#1$4I(#4N," @,#0O,3DO.3
+M87,Z("A30T1%*2 U+C @(# T+S$Y+SDP $ H(REL:6)C+6DS.#8Z9V5N+W-H
+M7V1A=&$N8PDQ+C, 86-O;7 Z("A30T1%*2 U+C @(# T+S$Y+SDP &]P=&EM
+M.B H4T-$12D@-2XP(" P-"\Q.2\Y, !A<SH@*%-#1$4I(#4N," @,#0O,3DO
+M.3 0"@C*6QI8F,M:3,X-CIL:6)C+6DS.#8O8W-U+V-R=&XN<PDQ+C4 87,Z
+M("A30T1%*2 U+C @(# T+S$Y+SDP "!L9" Z("A30T1%*2 U+C @(# T+S$Y
+M+SDP +@ !$ $@!P%@ . !G9&)M92YC #8! 0 !$!3(,$""$!-88$
+M" 8! !T 3 !( 3@$ #@ =%]S=')U8W0 M@ 8 *@ T $@!U
+M . !V7V-H87)?;65M8F5R %4 0 C 8 ! '*P T $@"@
+M. !V7W-H;W)T7VUE;6)E<@!5 0 (P & 0" !RD - !( R0 #@
+M=E]I;G1?;65M8F5R %4 !P C 8 ! 0 '*@ T $@#S . !V7VQO
+M;F=?;65M8F5R %4 "@ C 8 ! @ '*P T $@ > 0 . !V7V9L;V%T
+M7VUE;6)E<@!5 X (P & 0, !RP - !( 2@$ #@ =E]D;W5B;&5?
+M;65M8F5R %4 #P C 8 !! '! !L 3 !( ; ( #@ +C!F86ME
+M +8 & "H - !( DP$ #@ =E]C:&%R7VUE;6)E<@!5 $ (P & 0
+M !RL - !( O@$ #@ =E]S:&]R=%]M96UB97( 50 $ ", !@ $ @
+M <I #0 2 .<! X '9?:6YT7VUE;6)E<@!5 < (P & 0$ !RH
+M - !( $0( #@ =E]L;VYG7VUE;6)E<@!5 H (P & 0( !RL -
+M !( / ( #@ =E]F;&]A=%]M96UB97( 50 . ", !@ $# <L #0 2
+M &@" X '9?9&]U8FQE7VUE;6)E<@!5 \ (P & 00 !P0 <
+M%P 2 (L# X '1?=6YI;VX M@ ( *@ T $@"R @ . !V7V-H87)?
+M;65M8F5R %4 0 C 8 ! '*P T $@#= @ . !V7W-H;W)T7VUE
+M;6)E<@!5 0 (P & 0 !RD - !( !@, #@ =E]I;G1?;65M8F5R
+M %4 !P C 8 ! '*@ T $@ P P . !V7VQO;F=?;65M8F5R %4
+M"@ C 8 ! '*P T $@!; P . !V7V9L;V%T7VUE;6)E<@!5 X
+M(P & 0 !RP - !( AP, #@ =E]D;W5B;&5?;65M8F5R %4 #P C
+M 8 ! '! !L 7 !( J00 #@ +C%F86ME +8 " "H -
+M !( T , #@ =E]C:&%R7VUE;6)E<@!5 $ (P & 0 !RL - !(
+M^P, #@ =E]S:&]R=%]M96UB97( 50 $ ", !@ $ <I #0 2 "0$
+M X '9?:6YT7VUE;6)E<@!5 < (P & 0 !RH - !( 3@0 #@
+M=E]L;VYG7VUE;6)E<@!5 H (P & 0 !RL - !( >00 #@ =E]F
+M;&]A=%]M96UB97( 50 . ", !@ $ <L #0 2 *4$ X '9?9&]U
+M8FQE7VUE;6)E<@!5 \ (P & 0 !P0 J !@ 2 -<$ X '9?
+M8VAA<E]F=6YC %4 0 1 4R#! @A 5F#! @$ ,0 8 $@ ,!0 . !V
+M7W-I9VYE9%]C:&%R7V9U;F, 50 " !$!7(,$""$!:8,$" 0 S !@ 2
+M $,% X '9?=6YS:6=N961?8VAA<E]F=6YC %4 P 1 6R#! @A 7F#! @$
+M *P 8 $@!R!0 . !V7W-H;W)T7V9U;F, 50 $ !$!?(,$""$!B8,$
+M" 0 R !@ 2 *@% X '9?<VEG;F5D7W-H;W)T7V9U;F, 50 % !$!
+MC(,$""$!F8,$" 0 T !@ 2 . % X '9?=6YS:6=N961?<VAO<G1?
+M9G5N8P!5 8 $0&<@P0((0&I@P0(! "D & !( #08 #@ =E]I;G1?
+M9G5N8P!5 < $0&L@P0((0&Y@P0(! # & !( 008 #@ =E]S:6=N
+M961?:6YT7V9U;F, 50 ( !$!O(,$""$!R8,$" 0 R !@ 2 '<& X
+M '9?=6YS:6=N961?:6YT7V9U;F, 50 ) !$!S(,$""$!V8,$" 0 J
+M!@ 2 *4& X '9?;&]N9U]F=6YC %4 "@ 1 =R#! @A >F#! @$ ,0
+M 8 $@#:!@ . !V7W-I9VYE9%]L;VYG7V9U;F, 50 + !$![(,$""$!^8,$
+M" 0 S !@ 2 !$' X '9?=6YS:6=N961?;&]N9U]F=6YC %4 # 1
+M ?R#! @A 0F$! @$ *P 8 $@! !P . !V7V9L;V%T7V9U;F, 50 .
+M !$!#(0$""$!'80$" 0 L !@ 2 ' ' X '9?9&]U8FQE7V9U;F,
+M50 / !$!((0$""$!,80$" 0 5 %0 2 *X' "# 4 >H' 5
+M!0 2 )H' "# 4 >H' 0 !0 2 *H' !5 < ! #P ! !(
+MZ@< )4 "C "@ @ " 0 ( "
+M"'( +@ !D 3 !( >P@ #@ ;&EN:P"V )@ F #0 2 "D( X
+M &YE>'0 @P % 'J!P (P & 0 !RH - !( 4P@ #@ ;&EN:V9U
+M;F, @P % %P!P (P & 0$ !R0 - !( =P@ #@ <W1U9F8 <@"N
+M!P (P & 0( !P0 5 %0 2 +D( "# 4 >H' 5 !0 2
+M *4( "# 4 >H' 0 !0 2 +4( !5 < ! #P ! !( ]0@
+M )4 "C "@ @ " 0 ( " "'(
+M+@ !P 7 !( B0D #@ ='5?;&EN:P"V ) F #0 2 #<) X
+M &YE>'0 @P % 'J!P (P & 0 !RH - !( 80D #@ ;&EN:V9U
+M;F, @P % %[" (P & 0 !R0 - !( A0D #@ <W1U9F8 <@"Y
+M" (P & 0 !P0 Z ! 2 ,<) X "XR9F%K90"V 0 #S
+M !L @ &)L=64 0 &=R965N !R960 ! #X $ !( "0H
+M #@ 8V]L;W)S +8 ! /, 'P " <&EN:P ! <'5R<&QE !Y
+M96QL;W< ! #( $ !( /PH #@ +C-F86ME +8 ! /, $P !
+M9F]R9 8VAE=GD ! #$ $ !( = H #@ 8V%R<P"V 0 #S
+M !0 0 '!O<G-C:&4 &)M=P $ ,@ 0 $@"J"@ . N-&9A
+M:V4 M@ $ \P 3 $ !44E5% !&04Q310 $ ' !8 $@#&
+M"@ . !B;V]L96%N '( = H #$ $ !( ^PH #@ 8G9A;', M@ $
+M\P 3 $ !T<G5E !F86QS90 $ '0 !8 $@ 8"P . !B;V]L
+M96%N,@!R ,8* !& ! 2 &(+ X &UI<V]R9&5R960 M@ $ \P C
+M , !T:')E90 >F5R;P ! ;VYE ( !T=V\ ! ", &
+M !( B0L #@ ;6%I;@!5 < $0$TA 0((0$UA@0(! "< ' !( L L
+M #@ <W!O<G1S8V%R '( /PH ", !0 #D)@$""4 ' !( U0L #@ 8VQU
+M;FME<@!R D* C 4 _R7! @H !P 2 /T+ X &YO;G!R:6UA<GD
+M<@#'"0 (P % ,4EP0()0 < $@ B# . !P<FEM87)Y '( B0D ",
+M!0 #))<$""0 ' !( 1@P #@ =5]L:6YK '( ]0@ ", !0 # )@$""<
+M ' !( ;0P #@ <U]L:6YK (, !0 !Z@< ", !0 #F)<$""8 ' !(
+MDPP #@ =E]U;FEO;C( <@"+ P (P % .4F 0()0 < $@"X# . !V
+M7W5N:6]N '( ; ( ", !0 #G)@$""< ' !( WPP #@ =E]S=')U8W0R
+M '( 3@$ ", !0 #O)<$""< ' !( !@T #@ =E]S=')U8W0Q '( +@
+M ", !0 #I)<$""\ ' !( -0T #@ =E]D;W5B;&5?<&]I;G1E<@!C ,
+M 0\ (P % .@EP0(+@ < $@!C#0 . !V7V9L;V%T7W!O:6YT97( 8P #
+M $. ", !0 #V)<$"#8 ' !( F0T #@ =E]U;G-I9VYE9%]L;VYG7W!O
+M:6YT97( 8P # $, ", !0 #&)<$"#0 ' !( S0T #@ =E]S:6=N961?
+M;&]N9U]P;VEN=&5R &, P !"P C 4 ]R7! @M !P 2 /H- X '9?
+M;&]N9U]P;VEN=&5R &, P !"@ C 4 W"7! @U !P 2 "\. X '9?
+M=6YS:6=N961?:6YT7W!O:6YT97( 8P # $) ", !0 #6)<$"#, ' !(
+M8@X #@ =E]S:6=N961?:6YT7W!O:6YT97( 8P # $( ", !0 #E)<$""P
+M ' !( C@X #@ =E]I;G1?<&]I;G1E<@!C , 0< (P % -,EP0(-P
+M < $@#%#@ . !V7W5N<VEG;F5D7W-H;W)T7W!O:6YT97( 8P # $& ",
+M!0 # )<$"#4 ' !( ^@X #@ =E]S:6=N961?<VAO<G1?<&]I;G1E<@!C
+M , 04 (P % .<EP0(+@ < $@ H#P . !V7W-H;W)T7W!O:6YT97(
+M8P # $$ ", !0 #Z)<$"#8 ' !( 7@\ #@ =E]U;G-I9VYE9%]C:&%R
+M7W!O:6YT97( 8P # $# ", !0 #B)<$"#0 ' !( D@\ #@ =E]S:6=N
+M961?8VAA<E]P;VEN=&5R &, P ! @ C 4 ^R7! @M !P 2 +\/ X
+M '9?8VAA<E]P;VEN=&5R &, P ! 0 C 4 X27! @D 0 2 .,/ "5
+M HP 0 ( ! "%4 #P L !P 2 \0 X '9?9&]U8FQE
+M7V%R<F%Y '( OP\ ", !0 #*)<$""0 ! !( ,Q )4 "C ! @
+M $ (50 . "L ' !( 7A #@ =E]F;&]A=%]A<G)A>0!R \0
+M C 4 ^"7! @D 0 2 ((0 "5 HP 0 ( ! "%4
+M# S !P 2 +40 X '9?=6YS:6=N961?;&]N9U]A<G)A>0!R %X0 C
+M 4 V"7! @D 0 2 -D0 "5 HP 0 ( ! "%4 "P Q
+M !P 2 H1 X '9?<VEG;F5D7VQO;F=?87)R87D <@"U$ (P % -
+MEP0() $ $@ N$0 E0 *, $ " 0 A5 H *@ <
+M$@!8$0 . !V7VQO;F=?87)R87D <@ *$0 (P % /PEP0() $ $@!\
+M$0 E0 *, $ " 0 A5 D ,@ < $@"N$0 . !V7W5N
+M<VEG;F5D7VEN=%]A<G)A>0!R %@1 C 4 U"7! @D 0 2 -(1 "5
+M HP 0 ( ! "%4 " P !P 2 (2 X '9?<VEG;F5D
+M7VEN=%]A<G)A>0!R *X1 C 4 XR7! @D 0 2 "82 "5 HP 0
+M ( ! "%4 !P I !P 2 $\2 X '9?:6YT7V%R<F%Y '(
+M A( ", !0 #')<$""0 ! !( <Q( )4 "C ! @ $ (
+M50 & #0 ' !( IQ( #@ =E]U;G-I9VYE9%]S:&]R=%]A<G)A>0!R $\2
+M C 4 X"7! @D 0 2 ,L2 "5 HP 0 ( ! "%4
+M!0 R !P 2 /T2 X '9?<VEG;F5D7W-H;W)T7V%R<F%Y '( IQ( ",
+M!0 #2)<$""0 ! !( (1, )4 "C ! @ $ (50 $ "L
+M ' !( 3!, #@ =E]S:&]R=%]A<G)A>0!R /T2 C 4 WR7! @D
+M 0 2 ' 3 "5 HP 0 ( ! "%4 P S !P 2 *,3 X
+M '9?=6YS:6=N961?8VAA<E]A<G)A>0!R $P3 C 4 _B6! @D 0 2
+M ,<3 "5 HP 0 ( ! "%4 @ Q !P 2 /@3 X '9?
+M<VEG;F5D7V-H87)?87)R87D <@"C$P (P % ,XEP0() $ $@ <%
+ME0 *, $ " 0 A5 $ *@ < $@!&% . !V7V-H87)?
+M87)R87D <@#X$P (P % /4EP0() < $@!J% . !V7V1O=6)L90!5
+M \ (P % ,(EP0((P < $@"-% . !V7V9L;V%T %4 #@ C 4 SR7
+M! @K !P 2 +@4 X '9?=6YS:6=N961?;&]N9P!5 P (P % -XEP0(
+M*0 < $@#A% . !V7W-I9VYE9%]L;VYG %4 "P C 4 _R6! @B
+M!P 2 ,5 X '9?;&]N9P!5 H (P % -HEP0(*@ < $@ M%0 . !V
+M7W5N<VEG;F5D7VEN= !5 D (P % /TE@0(* < $@!5%0 . !V7W-I
+M9VYE9%]I;G0 50 ( ", !0 #\)8$""$ ' !( =A4 #@ =E]I;G0 50 '
+M ", !0 #$)<$""P ' !( HA4 #@ =E]U;G-I9VYE9%]S:&]R= !5 8
+M(P % ,$EP0(*@ < $@#,%0 . !V7W-I9VYE9%]S:&]R= !5 4 (P %
+M -<EP0((P < $@#O%0 . !V7W-H;W)T %4 ! C 4 VR7! @K
+M!P 2 !H6 X '9?=6YS:6=N961?8VAA<@!5 , (P % ,ZEP0(*0 <
+M$@!#%@ . !V7W-I9VYE9%]C:&%R %4 @ C 4 W27! @B !P 2 &46
+M X '9?8VAA<@!5 $ (P % /XEP0(! < "2 @ 3(,$"'D
+M #__P !Z __\0 >P /__( 'T #__S !^ __]
+M ?P /__4 ($ #__V "" __]P @P /__@ (4
+M #__Y "& __^@ AP /__L (D #__\ "* ___4
+M L@ /__Z +4 #__^X "V ___U MP /___ +D
+M #__P,! "Z __\, 0 NP /__%0$ +T #__QX! "^ __\H
+M 0 OP /__,@$ ,$ #__SP! #" __]& 0 PP /__4 $ ,4
+M #__UH! #& __]D 0 R0 /__> $ ,H #__X(! #+ __^,
+M 0 S0 /__E@$ ,X #__Z(! #/ __^N 0 T0 /__N@$ -(
+M #__\0! #3 ___. 0 U0 /__V $ -8 #__^(! #7 ___L
+M 0 V0 /__]@$ -H #__P " #< __\4 @ W0 /__'@( -X
+M #__R@" #@ __\R @ X0 /__/ ( .( #__T8" #D __]0
+M @ Y0 /__6@( .8 #__V0" #H __]N @ Z0 /__> ( .H
+M #__X(" #L __^, @ [0 /__E@( .\ #__Z " #P __^J
+M @ \0 /__M ( /( #__[X" #T ___( @ ]@ /__T@( /<
+M #__]X" ___I @
+M 0 $ " U( $"-0 3
+M ! D % @ .B ! CH 1 , !
+M 0 / "P ( L@00(+ $ , $ 0 0 0
+M%P , " [($$".P! ![ ! !\ )
+M @ &B"! AH @ ( , ' ! @ H 0 8
+M "(@@0(B ( $ 0 +@ $ & C(($
+M"(P" !0 $ ! #, ! !@ -R"! C< @
+M60, ! Y 0 8 XA@0(. 8 $
+M 0 /P $ " /(8$"#P& @
+M $ $< ! P %R6! A<!@ " !
+M !- 0 , !DE@0(9 8 !P 0 $
+M4@ 8 # @)8$"( & !P ! $ " %L (
+M P /"6! CP!@ M $ ! !@ @
+M \ 8 ' 0 ' 0 0 : ,
+M / - #4! ! ' # #$$@
+MD 0 !Z 0 5!, "("
+M $ @P $ '@5 !P%@
+M $ (H ! #H*P D@( 0
+%
+
+end
diff --git a/gdb/testsuite/gdb.base/i860-elf.u b/gdb/testsuite/gdb.base/i860-elf.u
new file mode 100644
index 00000000000..216e83b5a2f
--- /dev/null
+++ b/gdb/testsuite/gdb.base/i860-elf.u
@@ -0,0 +1,314 @@
+begin 775 i860-elf
+M?T5,1@$" 0 " < ! 32 #0 #-4 T "
+M!0 H !4 $0 8 T 0- "@ H 4 P
+M -0 !, ! ! - $#0 (
+M\ "/ % 0 $ DD I) "8 "7 8 !
+M @ "4P "E, ' !P O=7-R+VQI8B]L:6)C
+M+G-O+C$ , , !P P + @
+M # !0 & ! D * "
+M ! 0 $M !,$@ H "N
+M !$ __$ / I* 01 + & &20 $0#_\0 !\
+M !+L F!( F IO 1 /_Q +0 $R0 $@
+M #( !D0 !!$ H _ 3" 2 20 *3 $0#_
+M\0 %\ "E, !$ __$ 7V-L96%N=7 7V5N9 !?96YV:7)O;@!?971E
+M>'0 871E>&ET %]E9&%T80!E>&ET %]L:6)?=F5R<VEO;@!?7V9P<W1A<G0
+M7T=,3T)!3%]/1D93151?5$%"3$5? %]$64Y!34E# "]U<W(O;&EB+VQI8F,N
+M<V\N,0 I/ @0 I0 !@0 I1 "@0 I
+M2 " 0 * ! @ H * 7_RDY[!\ !?>*35 /@
+M%_\I/>P? #D'0 0 #X &O___;OO0 [!\ .P> ! /@ %_\I0>^] #D
+M'0 ,[!X &O__^\7_RE%[!\ .0= !A /@ :___Z.^] #L'P [!X $
+M^ 7_RE)[[T .0= "3L'@ :___X: #( 4'$ 81"__"@0P '$
+M!>P0 #40@ /6@ N80$M"@ ;___X.??*4SL'@ ;___VUO@ +L$
+MH) .80&0!O___8H &___\>@ ;___VZ82 (4< 1AE( &()2& ?
+MY9$I[!\ &P )J$<0 4;___UZ "@$ H $?@^ "$'P !H\$ * _
+M "@ 0 #X * "@ H ,@ P<0!@!A$+_\* 0 "$0P %&,
+M 81_ !"GX@ 0 ( * #( ,'$ 8 81"__"@$ A$, !1C &$?P 0
+MI^( $ " "@ R #!Q & &$0O_PH! (1# 48P !A'\ $*?B !
+M @ H ,@ P<0!@!A$+_\* 0 "$0P %&, 81_ !"GX@ 0 ( *
+M #( ,'$ 8 81"__"@$ A$, !1C &$?P 0I^( $ " "@ R
+M#!Q & &$0O_PH! (1# 48P !A'\ $*?B ! @ H ,@ P<0!@!
+MA$+_\* 0 "$0P %&, 81_ !"GX@ 0 ( * #( ,'$ 8 81"__"@
+M$ A$, !1C &$?P 0I^( $ " "@ R #!Q & &$0O_PH! (1#
+M 48P !A'\ $*?B ! @ H ,@ P<0!@!A$+_\* 0 "$0P %&,
+M 81_ !"GX@ 0 ( * #( ,'$ 8 81"__"@$ A$, !1C &$?P 0
+MI^( $ " "@ R #!Q & &$0O_PH! (1# 48P !A'\ $*?B !
+M @ H ,@ P<0!@!A$+_\$@( <F$0P %&, 81_ !"GX@ 0 ( *
+M #( ,'$ 8 81"__!(" ')A$, !1C &$?P 0I^( $ " "@ R
+M#!Q & &$0O_P[!\ (1# "4' !#^4"S _EXD3L'P [!\ )0< *4' #
+M#^7B"A_EXCSL'P [!\ )0< 24' %'^7B+!_EX=3L'P [!\ )0< :4
+M' ''^7AX1_EX<7L'P [!\ )0< B4' )'^7AP1_EXCGL'P [!\ )0<
+M J4' +'^7AS1_EXDGL'P )_ 9(NP? O\"H.[!\ "?P&1CL'P +_ I
+MV.P? '_"K,[!\ _EXJCL'P !_PJ1.P? /Y>(([!\ ?\*@KL'P
+M#^7AR.P? 7_"H\[!\ !_EXDSL'P %_PJ+.P? ?Y>(8[!\ !?\*=3L
+M'P '^7B4.P? 7_"GA[!\ !_EX>WL'P %_PIQ>P? ?Y>)=[!\ !?\
+M*<'L'P '^7B(>P? 7_"HY[!\ !_EXL7L'P %_PIS>P? ?Y>(1[!\
+M !?\*DGL'P '^7B,>P? G\"H.[!\ "_P*K;L'P )_ IV.P? O\"GX
+M[!\ .?\*LSL'P '^7B5>P? #G_"I$[!\ !_EXL'L'P Y_PJ"NP? ?
+MY>)9[!\ .?\*CSL'P '^7BO>P? #G_"HL[!\ !_EXFWL'P Y_PIU.P?
+M ?Y>'1[!\ .?\*>#L'P '^7B'>P? #G_"G$[!\ !_EXF7L'P Y_PI
+MP.P? ?Y>(I[!\ .?\*CCL'P '^7B0>P? #G_"G,[!\ !_EXK'L'P
+MY_PJ2.P? ?Y>'I[!\ .?\*@SL'P '^7BK>P? #G_"G8[!\ !_EXG'L
+M'P [!\ )0< *4' "'^7A]1_EX>7L'P [!\ )0< &4' !'^7C:1_E
+MXM'L'P %_PJ:>P? ?Y>+9[!\ !?\*WCL'P '^7C<.P? 48P !A'\
+M$*?B ! @ H $ " "@ H 0&D !"R
+M I3 2W $O@ !,4 3, $
+M !H # $K - 9 0 !#H !0 $@ & 1,
+M H ![ "P ! 5 , "DP @ # 4
+M!P !< !)\ $
+M 0 __$ 0U # ! $.@ P @
+M !$P , , 2 # $ $GP P !0
+M !*P , 8 2P # ' $T P
+M" !D , D 9$ # * *20
+M P "P "DP , P I3 # - *<
+M P #@ , \ # 0
+M P $0 , !( # 3
+M P % < 0 __$ . $ /_Q
+M %0 ! #_\0 "$ 0 __$ I $
+M /_Q ,P ! #_\0 #H "G !!$ X !) IQ
+M 01 . 5@ $_@ @$@ " &( !D !( D !H I
+MR (1 . ?@ %B@ +8$@ " (, "G, !!$ X "1
+M IT 01 . J@ $X !,$@ +, "N !$ __$
+M "X IU (1 . R0 %, @$@ " -\ "G8 "!$
+M X #H IX 01 . [@ $T@ $@ " /4 "GD
+M!!$ X $ I* 01 + !"0 *>@ $$0 #@ 2$ "GL
+M "!$ X $M I] 01 . !-0 %" @$@ " 4@
+M "GX $!$ X %7 9) 1 /_Q !7@ *@@ "$0 #@
+M 7( "H* 1$ X &" J# 01 . !B@ *A ($0
+M#@ 9X !30 F!( &E I* 0A + !K0 %6 @
+M$@ " ;D "H8 !!$ X '. 5L " 2 ( !XP *AP
+M $$0 #@ ?$ "F\ !$ __$ 'X 4< " 2 ( "!0
+M*B ($0 #@ AH "HH !!$ X (Q 4Z " 2 ( "
+M/ *BP "$0 #@ DL !78 (!( @ )8 7< 2
+M "70 *C ($0 #@ G, "HX !!$ X )Z J/ (1
+M . "@@ *D $$0 #@ I$ "I$ 1$ X *? J2
+M 01 . "KP *DP $$0 #@ KT "I0 !!$ X +4 9
+M$ 01 * "X0 $]@ $@ " ND "I4 !!$ X +X
+M J6 01 . #$ *EP ($0 #@ R, !8@ !(
+M ,M J9 01 . #0@ *F@ $$0 #@ TD "DP !$
+M__$ -? J; 01 . #=@ *G $$0 #@ X< "DD
+M!!$ L .9 J> !@1 . #HP *I 8$0 #@ ZT "JH
+M A$ X .Z JK 01 . #R@ *K $$0 #@ ^
+M !8 (!( @ /N 5$ " 2 ( $ *4P $0#_\0
+M! D "JT "!$ X 07 JO 01 . $)P %8@ @$@
+M" !#H "K !!$ X 10 JQ @1 . $70 $K
+M$@ !@ !&, "K, 1$ X 1J JT 01 . $<@ %$@
+M @$@ " !(< "K8 D!$ X 2. K: 01 . $F
+M%)@ @$@ " !*P "MP "!$ X 2U K> @1 . $
+MO0 %3@ @$@ " !G9&)M90!C<G0Q+G, 8W)T:2YS '9A;'5E<RU8="YC
+M &=D8FUE+F, <VA?9&%T82YC &-R=&XN<P!V7W5N<VEG;F5D7VEN= !V7W-I
+M9VYE9%]I;G0 =E]C:&%R7V9U;F, 7V9I;FD =E]U;G-I9VYE9%]C:&%R7V%R
+M<F%Y &UA:6X =E]S:6=N961?;&]N9P!V7W5N<VEG;F5D7W-H;W)T7W!O:6YT
+M97( 7V-L96%N=7 7V5N9 !V7W5N<VEG;F5D7W-H;W)T '9?=6YS:6=N961?
+M<VAO<G1?9G5N8P!V7V1O=6)L90!V7VEN= !?<W1A<G0 ;F]N<')I;6%R>0!?
+M96YV:7)O;@!V7W5N<VEG;F5D7VQO;F=?<&]I;G1E<@!V7VEN=%]A<G)A>0!P
+M<FEM87)Y '9?<VEG;F5D7V-H87)?9G5N8P!V7V1O=6)L95]A<G)A>0!?971E
+M>'0 =E]S:6=N961?8VAA<E]A<G)A>0!V7W5N<VEG;F5D7V-H87( =E]F;&]A
+M= !V7W-I9VYE9%]L;VYG7V%R<F%Y &%T97AI= !E;G9I<F]N '9?;&]N9U]F
+M=6YC '9?<VEG;F5D7W-H;W)T7V%R<F%Y '9?=6YS:6=N961?;&]N9U]F=6YC
+M '9?:6YT7W!O:6YT97( 7V5D871A '9?<VAO<G1?9G5N8P!V7W5N<VEG;F5D
+M7VEN=%]A<G)A>0!V7W5N<VEG;F5D7VEN=%]P;VEN=&5R '9?:6YT7V9U;F,
+M=E]S:6=N961?<VAO<G0 =E]F;&]A=%]F=6YC &5X:70 =E]U;G-I9VYE9%]L
+M;VYG7V%R<F%Y '9?;&]N9P!V7W-H;W)T '9?;&]N9U]P;VEN=&5R '9?<VEG
+M;F5D7V-H87( =E]U;G-I9VYE9%]L;VYG '9?<VAO<G1?87)R87D =E]U;G-I
+M9VYE9%]S:&]R=%]A<G)A>0!?;&EB7W9E<G-I;VX 7VUC;W5N= !V7V-H87)?
+M<&]I;G1E<@!V7W5N<VEG;F5D7V-H87)?<&]I;G1E<@!V7W-I9VYE9%]I;G1?
+M87)R87D 7U]F<'-T87)T '9?<VEG;F5D7VEN=%]P;VEN=&5R '-?;&EN:P!?
+M1TQ/0D%,7T]&1E-%5%]404),15\ =E]S:6=N961?<VAO<G1?<&]I;G1E<@!V
+M7V1O=6)L95]P;VEN=&5R %]?;&]N9V1O=6)L95]U<V5D '9?<W1R=6-T,0!V
+M7W-T<G5C=#( =E]C:&%R7V%R<F%Y '9?9FQO871?<&]I;G1E<@!V7W-I9VYE
+M9%]L;VYG7W!O:6YT97( =E]D;W5B;&5?9G5N8P!V7W-I9VYE9%]I;G1?9G5N
+M8P!?1%E.04U)0P!V7V9L;V%T7V%R<F%Y '9?<VAO<G1?<&]I;G1E<@!V7W-I
+M9VYE9%]L;VYG7V9U;F, =E]S:6=N961?8VAA<E]P;VEN=&5R '9?;&]N9U]A
+M<G)A>0!?:6YI= !V7V-H87( 8VQU;FME<@!V7W5N<VEG;F5D7V-H87)?9G5N
+M8P!U7VQI;FL <W!O<G1S8V%R '9?<VEG;F5D7W-H;W)T7V9U;F, =E]U;FEO
+M;C( =E]U;FEO;@!V7W5N<VEG;F5D7VEN=%]F=6YC N:6YT97)P "YH87-H
+M "YD>6YS>6T +F1Y;G-T<@ N<F5L82YP;'0 +FEN:70 +G!L= N=&5X= N
+M9FEN:0 N<F]D871A "YD871A "YG;W0 +F1Y;F%M:6, +F)S<P N<WEM=&%B
+M "YS=')T86( +G-H<W1R=&%B "YC;VUM96YT "YD96)U9P N;&EN90 D2&5A
+M9&5R.B O<"]20U,O=71I;#(M,BXQ+W5S<B]S<F,O;&EB+VQI8F,O:3@V,"]C
+M<W4O8W)T,2YS+'8@,BXQ(#DR+S U+S$T(# W.C$V.C(P(&1A=FED;V9F($5X
+M<" D $ H(RE&5%@@,BXQ+C N,2!S8V1E.B]U<W(O8V-S+VQI8B]C<G0Q+F\
+M)$AE861E<CH@+W O4D-3+W5T:6PR+3(N,2]U<W(O<W)C+VQI8B]L:6)C+VDX
+M-C O8W-U+V-R=&DN<RQV(#(N,2 Y,B\P-2\Q-" P-SHQ-CHR,2!D879I9&]F
+M9B!%>' @) ! *",I1E18(#(N,2XP+C$@<V-D93HO=7-R+V-C<R]L:6(O8W)T
+M:2YO "1(96%D97(Z("]P+U)#4R]U=&EL,BTR+C$O=7-R+W-R8R]L:6(O;&EB
+M8R]P;W)T+V=E;B]V86QU97,M6'0N8RQV(#(N,2 Y,B\P-2\Q-" P-SHR-SHP
+M,B!D879I9&]F9B!%>' @) D2&5A9&5R.B O<"]20U,O=71I;#(M,BXQ+W5S
+M<B]S<F,O;&EB+VQI8F,O:6YC+W-Y;F]N>6US+F@L=B R+C$@.3(O,#4O,30@
+M,#<Z,C(Z,3D@9&%V:61O9F8@17AP("0 )$AE861E<CH@+W O4D-3+W5T:6PR
+M+3(N,2]U<W(O<W)C+VAE860O;6%T:"YH+'8@,BXQ(#DR+S U+S$T(# W.C$R
+M.C4W(&1A=FED;V9F($5X<" D &%C;VUP.B H4T-$12D@-2XP(#$R+S X+S@Y
+M &%S.B H4T-$12D@-2XP(#$R+S X+S@Y $ H(RE&5%@@,BXQ+C N,2!S8V1E
+M.B]U<W(O8V-S+VQI8B]V86QU97,M6'0N;P!A8V]M<#H@*%-#1$4I(#4N," Q
+M,B\P."\X.0!A<SH@*%-#1$4I(#4N," Q,B\P."\X.0 D2&5A9&5R.B O<"]2
+M0U,O=71I;#(M,BXQ+W5S<B]S<F,O;&EB+VQI8F,O:3@V,"]G96XO<VA?9&%T
+M82YC+'8@,BXQ(#DR+S U+S$T(# W.C$W.C4T(&1A=FED;V9F($5X<" D &%C
+M;VUP.B H4T-$12D@-2XP(#$R+S X+S@Y &%S.B H4T-$12D@-2XP(#$R+S X
+M+S@Y $ H(RE&5%@@,BXQ+C N,2!S8V1E.B]U<W(O8V-S+VQI8B]L:6)C+G-O
+M "1(96%D97(Z("]P+U)#4R]U=&EL,BTR+C$O=7-R+W-R8R]L:6(O;&EB8R]I
+M.#8P+V-S=2]C<G1N+G,L=B R+C$@.3(O,#4O,30@,#<Z,38Z,C(@9&%V:61O
+M9F8@17AP("0 0"@C*4946" R+C$N,"XQ('-C9&4Z+W5S<B]C8W,O;&EB+V-R
+M=&XN;P @;&0@.B H4T-$12D@-2XP(#$R+S X+S@Y "X $0 2 6< X
+M9V1B;64N8P !-@ $!$0 $_ !(0 &0 !!@ = !, $@ 4X
+M.'1?<W1R=6-T "V & "H #0 2 =0 X=E]C:&%R7VUE;6)E<@
+M50 ! ", !@0 !P "L #0 2 H X=E]S:&]R=%]M96UB97( %4
+M! C 8$ @< I T $@ ,D .'9?:6YT7VUE;6)E<@ 50 ' ",
+M!@0 $!P "H #0 2 \P X=E]L;VYG7VUE;6)E<@ 50 * ", !@0
+M (!P "L #0 2 !'@ X=E]F;&]A=%]M96UB97( %4 #@ C 8$
+M# < L T $@ 4H .'9?9&]U8FQE7VUE;6)E<@ 50 / ", !@0 0
+M!P 0 ; !, $@ FP ."XP9F%K90 M@ !@ J T $@ 9,
+M.'9?8VAA<E]M96UB97( %4 0 C 8$ < K T $@ ;X .'9?
+M<VAO<G1?;65M8F5R !5 0 (P &! (' *0 - !( 'G #AV7VEN
+M=%]M96UB97( %4 !P C 8$ ! < J T $@ A$ .'9?;&]N9U]M
+M96UB97( %4 "@ C 8$ " < K T $@ CP .'9?9FQO871?;65M
+M8F5R !5 X (P &! P' + - !( )H #AV7V1O=6)L95]M96UB
+M97( %4 #P C 8$ $ < $ ' 7 !( .+ #AT7W5N:6]N "V
+M " "H #0 2 "L@ X=E]C:&%R7VUE;6)E<@ 50 ! ", !@0
+M!P "L #0 2 "W0 X=E]S:&]R=%]M96UB97( %4 ! C 8$ <
+M I T $@ P8 .'9?:6YT7VUE;6)E<@ 50 ' ", !@0 !P "H
+M#0 2 #, X=E]L;VYG7VUE;6)E<@ 50 * ", !@0 !P "L #0 2
+M #6P X=E]F;&]A=%]M96UB97( %4 #@ C 8$ < L T $@
+M X< .'9?9&]U8FQE7VUE;6)E<@ 50 / ", !@0 !P 0 ; !<
+M$@ !*D ."XQ9F%K90 M@ @ J T $@ ] .'9?8VAA<E]M96UB
+M97( %4 0 C 8$ < K T $@ _L .'9?<VAO<G1?;65M8F5R
+M !5 0 (P &! ' *0 - !( 0D #AV7VEN=%]M96UB97( %4
+M!P C 8$ < J T $@ !$X .'9?;&]N9U]M96UB97( %4 "@ C
+M 8$ < K T $@ !'D .'9?9FQO871?;65M8F5R !5 X (P &
+M! ' + - !( 2E #AV7V1O=6)L95]M96UB97( %4 #P C 8$
+M < $ *@ & !( 37 #AV7V-H87)?9G5N8P 50 ! 1$ !/X
+M 2$ !08 ! #$ !@ 2 %# X=E]S:6=N961?8VAA<E]F=6YC !5
+M (!$0 %" !(0 %$ $ ,P & !( 5# #AV7W5N<VEG;F5D7V-H
+M87)?9G5N8P 50 # 1$ !1( 2$ !1H ! "L !@ 2 %<@ X=E]S
+M:&]R=%]F=6YC !5 0!$0 %' !(0 %) $ ,@ & !( 6H #AV
+M7W-I9VYE9%]S:&]R=%]F=6YC !5 4!$0 %)@!(0 %+@ $ - &
+M !( 7@ #AV7W5N<VEG;F5D7W-H;W)T7V9U;F, %4 !@$1 4P $A 4
+MX 0 I 8 $@ !@T .'9?:6YT7V9U;F, %4 !P$1 4Z $A 5
+M" 0 P 8 $@ !D$ .'9?<VEG;F5D7VEN=%]F=6YC !5 @!$0
+M%1 !(0 %3 $ ,@ & !( 9W #AV7W5N<VEG;F5D7VEN=%]F=6YC
+M !5 D!$0 %3@!(0 %5@ $ *@ & !( :E #AV7VQO;F=?9G5N
+M8P 50 * 1$ !5@ 2$ !6 ! #$ !@ 2 &V@ X=E]S:6=N961?
+M;&]N9U]F=6YC !5 L!$0 %8@!(0 %:@ $ ,P & !( <1 #AV
+M7W5N<VEG;F5D7VQO;F=?9G5N8P 50 , 1$ !6P 2$ !70 ! "L
+M!@ 2 '0 X=E]F;&]A=%]F=6YC !5 X!$0 %=@!(0 %?@ $
+M+ & !( =P #AV7V1O=6)L95]F=6YC !5 \!$0 %@ !(0 %B $
+M %0 5 !( >N (, !0$ ?J %0 % !( >: (, !0$ ?J
+M$ % !( >J %4 !P 0 \ $ $@ !^H E0 *, * "
+M ( $ @ @@ <@ "X 9 !, $@ "'L
+M.&QI;FL +8 "8 )@ - !( @I #AN97AT "# 4! 'Z@ C 8$
+M < J T $@ "%, .&QI;FMF=6YC "# 4! '< C 8$
+M! < D T $@ "'< .'-T=69F !R 'K@ C 8$ " < $
+M%0 5 !( BY (, !0$ ?J %0 % !( BE (, !0$ ?J $ %
+M !( BU %4 !P 0 \ $ $@ "/4 E0 *, * "
+M ( $ @ @@ <@ "X < !< $@ "8D .'1U
+M7VQI;FL +8 "0 )@ - !( DW #AN97AT "# 4! 'Z@ C 8$
+M < J T $@ "6$ .&QI;FMF=6YC "# 4! (>P C 8$
+M < D T $@ "84 .'-T=69F !R (N0 C 8$ < $
+M.@ $ !( G' #@N,F9A:V4 +8 $ /, &P )B;'5E %G<F5E
+M;@ <F5D 0 ^ 0 $@ "@D .&-O;&]R<P M@ 0 \P ?
+M G!I;FL 7!U<G!L90 >65L;&]W 0 R 0 $@
+M"C\ ."XS9F%K90 M@ 0 \P 3 69O<F0 &-H979Y 0
+M Q 0 $@ "G0 .&-A<G, +8 $ /, % %P;W)S8VAE !B
+M;7< ! #( ! 2 *J@ X+C1F86ME "V ! #S !, !5%)5
+M10 1D%,4T4 ! !P %@ 2 *Q@ X8F]O;&5A;@ <@ "G0
+M Q 0 $@ "OL .&)V86QS "V ! #S !, !=')U90 9F%L
+M<V4 ! !T %@ 2 +& X8F]O;&5A;C( '( K& 1@ $ !(
+M MB #AM:7-O<F1E<F5D "V ! #S ", #=&AR964 'IE<F\
+M 6]N90 "='=O 0 C 8 $@ "XD .&UA:6X %4 !P$1
+M 6* $A 9 0 G < $@ "[ .'-P;W)T<V-A<@ <@ "C\
+M(P % P *V@ E < $@ "]4 .&-L=6YK97( '( H) ", !0, "K0
+M * ' !( O] #AN;VYP<FEM87)Y !R )QP C 4# IY "4
+M!P 2 ,(@ X<')I;6%R>0 <@ "8D (P % P *?0 D < $@ #$8
+M.'5?;&EN:P <@ "/4 (P % P *M@ G < $@ #&T .'-?;&EN:P
+M@P % 0 !^H (P % P *F@ F < $@ #), .'9?=6YI;VXR !R #
+MBP C 4# K< "4 !P 2 ,N X=E]U;FEO;@ <@ FP (P % P
+M*W@ G < $@ #-\ .'9?<W1R=6-T,@ <@ 4X (P % P *I G
+M < $@ #08 .'9?<W1R=6-T,0 <@ "X (P % P *G@ O < $@
+M#34 .'9?9&]U8FQE7W!O:6YT97( &, P$ #P C 4# J< "X !P 2
+M -8P X=E]F;&]A=%]P;VEN=&5R !C ,! X (P % P *JP V <
+M$@ #9D .'9?=6YS:6=N961?;&]N9U]P;VEN=&5R !C ,! P (P % P
+M*>@ T < $@ #<T .'9?<VEG;F5D7VQO;F=?<&]I;G1E<@ 8P # 0 +
+M ", !0, "JP +0 ' !( WZ #AV7VQO;F=?<&]I;G1E<@ 8P # 0 *
+M ", !0, "I -0 ' !( XO #AV7W5N<VEG;F5D7VEN=%]P;VEN=&5R
+M !C ,! D (P % P *B@ S < $@ #F( .'9?<VEG;F5D7VEN=%]P
+M;VEN=&5R !C ,! @ (P % P *F0 L < $@ #HX .'9?:6YT7W!O
+M:6YT97( &, P$ !P C 4# J' #< !P 2 .Q0 X=E]U;G-I9VYE
+M9%]S:&]R=%]P;VEN=&5R !C ,! 8 (P % P *= U < $@ #OH
+M.'9?<VEG;F5D7W-H;W)T7W!O:6YT97( &, P$ !0 C 4# J; "X
+M!P 2 /* X=E]S:&]R=%]P;VEN=&5R !C ,! 0 (P % P *KP V
+M < $@ #UX .'9?=6YS:6=N961?8VAA<E]P;VEN=&5R !C ,! , (P %
+M P *E@ T < $@ #Y( .'9?<VEG;F5D7V-H87)?<&]I;G1E<@ 8P #
+M 0 " ", !0, "K +0 ' !( ^_ #AV7V-H87)?<&]I;G1E<@ 8P #
+M 0 ! ", !0, "I4 ) ! !( _C )4 "C ! @ 0@
+M50 / + ' !( ! / #AV7V1O=6)L95]A<G)A>0 <@ #[\ (P % P
+M*?@ D $ $@ $#, E0 *, $ " !" !5 X K <
+M$@ $%X .'9?9FQO871?87)R87D '( ! / ", !0, "JT ) ! !(
+M !"" )4 "C ! @ 0@ 50 , ,P ' !( !"U #AV7W5N
+M<VEG;F5D7VQO;F=?87)R87D '( !!> ", !0, "HP ) ! !( !#9
+M )4 "C ! @ 0@ 50 + ,0 ' !( !$* #AV7W-I9VYE
+M9%]L;VYG7V%R<F%Y !R 0M0 C 4# J$ "0 0 2 1+@"5
+MHP 0 ( $( %4 "@ "H !P 2 16 X=E]L;VYG7V%R<F%Y
+M !R 1"@ C 4# JQ "0 0 2 1? "5 HP 0 (
+M $( %4 "0 #( !P 2 1K@ X=E]U;G-I9VYE9%]I;G1?87)R87D '(
+M !%8 ", !0, "H@ ) ! !( !'2 )4 "C ! @ 0@
+M50 ( , ' !( !(" #AV7W-I9VYE9%]I;G1?87)R87D '( !&N ",
+M!0, "I< ) ! !( !(F )4 "C ! @ 0@ 50 '
+M*0 ' !( !)/ #AV7VEN=%]A<G)A>0 <@ $@( (P % P *>P D $
+M$@ $G, E0 *, $ " !" !5 8 T < $@ $J< .'9?
+M=6YS:6=N961?<VAO<G1?87)R87D '( !)/ ", !0, "I0 ) ! !(
+M !++ )4 "C ! @ 0@ 50 % ,@ ' !( !+] #AV7W-I
+M9VYE9%]S:&]R=%]A<G)A>0 <@ $J< (P % P *A@ D $ $@ $R$
+ME0 *, $ " !" !5 0 K < $@ $TP .'9?<VAO<G1?
+M87)R87D '( !+] ", !0, "I, ) ! !( !-P )4 "C ! @
+M 0@ 50 # ,P ' !( !.C #AV7W5N<VEG;F5D7V-H87)?87)R
+M87D '( !-, ", !0, "G( ) ! !( !/' )4 "C ! @
+M 0@ 50 " ,0 ' !( !/X #AV7W-I9VYE9%]C:&%R7V%R<F%Y !R
+M 3HP C 4# J" "0 0 2 4' "5 HP 0 ( $(
+M %4 0 "H !P 2 41@ X=E]C:&%R7V%R<F%Y !R 3^ C 4# J
+MJ "0 !P 2 4:@ X=E]D;W5B;&4 %4 #P C 4# IV ", !P 2
+M 4C0 X=E]F;&]A= 50 . ", !0, "H, *P ' !( !2X #AV7W5N
+M<VEG;F5D7VQO;F< %4 # C 4# J2 "D !P 2 4X0 X=E]S:6=N
+M961?;&]N9P 50 + ", !0, "G, (@ ' !( !4# #AV7VQO;F< %4
+M"@ C 4# J. "H !P 2 5+0 X=E]U;G-I9VYE9%]I;G0 %4 "0 C
+M 4# IP "@ !P 2 550 X=E]S:6=N961?:6YT !5 @ (P % P
+M*<0 A < $@ %78 .'9?:6YT !5 < (P % P *> L < $@
+M%:( .'9?=6YS:6=N961?<VAO<G0 %4 !@ C 4# IU "H !P 2 5
+MS X=E]S:6=N961?<VAO<G0 %4 !0 C 4# J+ ", !P 2 5[P X
+M=E]S:&]R= 50 $ ", !0, "H\ *P ' !( !8: #AV7W5N<VEG;F5D
+M7V-H87( %4 P C 4# J"@ "D !P 2 60P X=E]S:6=N961?8VAA
+M<@ 50 " ", !0, "I$ (@ ' !( !9E #AV7V-H87( %4 0 C 4#
+M JS 0 ' "D@ $_ !Y__\ ( >O__ ,
+M 'O__P %@ !]__\ " ?O__ J '___P - "!__\
+M #X @O__ !( (/__P 4@ "%__\ %P AO__ !F
+M (?__P < ")__\ 'H BO__ "$ ++__P C@ "U__\
+M )$ MO__ "3 +?__P E@ "Y__\ )D NO__ "<
+M +O__P GP "]__\ *( OO__ "E +___P J #!__\
+M *L PO__ "N ,/__P L0 #%__\ +0 QO__ "X
+M ,G__P O #*__\ , R___ #$ ,W__P R #.__\
+M ,P S___ #0 -'__P U #2__\ -@ T___ #<
+M -7__P X #6__\ .0 U___ #H -G__P [ #:__\
+M / W/__ #T -W__P ^ #>__\ /P X/__ $
+M .'__P !! #B__\ 0@ Y/__ $, .7__P !$ #F__\
+M 10 Z/__ $8 .G__P !' #J__\ 2 [/__ $D
+M .W__P !* #O__\ 2P \/__ $O /'__P !,@ #R__\
+M 34 ]/__ $X /;__P !/ #W__\ 3P /__ %$
+M $
+M ! @ $-0 #4 $P 0 ) !0
+M ( !#H Z $@ # 0 $ #P L " 1
+M, 3 #0 ! ( $ $ !< # @ $@ (
+M >P 0 ? ! ( !)\ "? #
+M # !P 0 , *0 P & 2L K 0
+M 0 " "\ , !@ $L + @
+M$ @ T # 8 !- #0 !< ! (
+M .@ P & 9 "0 0 0 " $
+M ! @ &1 D0 % " !( 0
+M , "DD )) @ 0 3@ $ # I
+M, "3 < 0 ! %, & P *4P E,
+M < 0 ! @ !< " , "G )P <
+M @ 80 ( "< < $
+M !P $ $ &D # !# $T0
+M 0 !Q P 5D0 )$ $
+M >P $ %B( 0N ! (0
+M ! !I0 6< ! "+ 0
+> PP I( $
+
+end
diff --git a/gdb/testsuite/gdb.base/int-type.c b/gdb/testsuite/gdb.base/int-type.c
new file mode 100644
index 00000000000..548ca9c36bb
--- /dev/null
+++ b/gdb/testsuite/gdb.base/int-type.c
@@ -0,0 +1,25 @@
+
+int x;
+int y;
+int z;
+int w;
+
+
+
+int main ()
+{
+
+#ifdef usestubs
+ set_debug_traps();
+ breakpoint();
+#endif
+
+ x = 14;
+ y = 3;
+ z = 2;
+ w = 2;
+
+ return 0;
+
+}
+
diff --git a/gdb/testsuite/gdb.base/interrupt.c b/gdb/testsuite/gdb.base/interrupt.c
new file mode 100644
index 00000000000..120697b77e5
--- /dev/null
+++ b/gdb/testsuite/gdb.base/interrupt.c
@@ -0,0 +1,37 @@
+#include <errno.h>
+#include <stdio.h>
+int
+main ()
+{
+ char x;
+ int nbytes;
+#ifdef usestubs
+ set_debug_traps();
+ breakpoint();
+#endif
+ printf ("talk to me baby\n");
+ while (1)
+ {
+ nbytes = read (0, &x, 1);
+ if (nbytes < 0)
+ {
+#ifdef EINTR
+ if (errno != EINTR)
+#endif
+ perror ("");
+ }
+ else if (nbytes == 0)
+ {
+ printf ("end of file\n");
+ exit (0);
+ }
+ else
+ write (1, &x, 1);
+ }
+}
+
+int
+func1 ()
+{
+ return 4;
+}
diff --git a/gdb/testsuite/gdb.base/interrupt.exp b/gdb/testsuite/gdb.base/interrupt.exp
new file mode 100644
index 00000000000..60cf83817cb
--- /dev/null
+++ b/gdb/testsuite/gdb.base/interrupt.exp
@@ -0,0 +1,175 @@
+# Copyright (C) 1994, 1995, 1997, 1998 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+if [host_info exists name] {
+ if [board_info host exists gdb,nointerrupts] {
+ verbose "Skipping interrupt.exp because of nointerrupts."
+ continue
+ }
+}
+
+if [target_info exists gdb,noinferiorio] {
+ verbose "Skipping interrupt.exp because of noinferiorio."
+ return
+}
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+set prms_id 0
+set bug_id 0
+
+set testfile interrupt
+set srcfile ${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+gdb_start
+
+
+if ![file exists $binfile] then {
+ perror "$binfile does not exist."
+ return 0
+} else {
+ gdb_reinitialize_dir $srcdir/$subdir
+ gdb_load $binfile
+ # Hope this is unix :-)
+ gdb_test "shell stty intr '^C'" "" \
+ "set interrupt character in interrupt.exp"
+ if [runto_main] then {
+ send_gdb "continue\n"
+ gdb_expect {
+ -re "\r\ntalk to me baby\r\n$" {
+ pass "child process is alive"
+ }
+ timeout { fail "run (timeout)" }
+ eof { fail "run (eof)" }
+ }
+ # This should appear twice, once for the echo and once for the
+ # program's output. Under dejagnu (but not interactively) for
+ # SunOS4, it only appears once. Don't worry about it, I imagine
+ # dejagnu has just done something to the tty modes.
+ send_gdb "a\n"
+ gdb_expect {
+ -re "^a\r\n(|a\r\n)$" {
+ pass "child process ate our char"
+ }
+ timeout { fail "echo a (timeout)" }
+ eof { fail "echo a (eof)" }
+ }
+ # Wait until the program is in the read system call again.
+ sleep 2
+
+ # Cntrl-c may fail for simulator targets running on a BSD host.
+ # This is the result of a combination of the read syscall
+ # being restarted and gdb capturing the cntrl-c signal.
+
+ # Cntrl-c may fail for simulator targets on slow hosts.
+ # This is because there is a race condition between entering
+ # the read and delivering the cntrl-c.
+
+ send_gdb "\003"
+ gdb_expect {
+ -re "Program received signal SIGINT.*$gdb_prompt $" {
+ pass "send_gdb control C"
+ }
+ -re ".*$gdb_prompt $" { fail "send_gdb control C" }
+ timeout { fail "send_gdb control C (timeout)" }
+ eof { fail "send_gdb control C (eof)" }
+ }
+
+ send_gdb "p func1 ()\n"
+ gdb_expect {
+ -re " = 4.*$gdb_prompt $" { pass "call function when asleep" }
+ -re ".*Program received signal SIGSEGV.*$gdb_prompt $" {
+ setup_xfail "i*86-pc-linux*-gnu*"
+ fail "child died when we called func1, skipped rest of tests"
+ return
+ }
+ -re "$gdb_prompt $" { fail "call function when asleep (wrong output)" }
+ default {
+
+ # This fail probably happens whenever we use /proc (we
+ # don't use PRSABORT), but apparently also happens on
+ # other machines as well.
+
+ setup_xfail "sparc*-*-solaris2*"
+ setup_xfail "mips-*-ultrix*"
+ setup_xfail "hppa*-*-*"
+ setup_xfail "i386*-*-bsd*"
+ setup_xfail "i*86-*-solaris2*"
+ setup_xfail "*-*-sysv4*"
+ setup_xfail "vax-*-*"
+ setup_xfail "alpha-*-*"
+ setup_xfail "*-*-irix*"
+ setup_xfail "*-*-hpux*"
+ setup_xfail "*-*-*lynx*"
+ fail "call function when asleep (stays asleep)"
+ # Send_Gdb a newline to wake it up
+ send_gdb "\n"
+ gdb_test "" " = 4" "call function after waking it"
+ }
+# eof { fail "call function when asleep (eof)" }
+ }
+
+ # Now try calling the function again.
+ gdb_test "p func1 ()" " = 4" "call function a second time"
+
+ # And the program should still be doing the same thing.
+ # The optional trailing \r\n is in case we sent a newline above
+ # to wake the program, in which case the program now sends it
+ # back. We check for it either here or in the next gdb_expect
+ # command, because which one it ends up in is timing dependent.
+ send_gdb "continue\n"
+ # For some reason, i386-*-sysv4 gdb fails to issue the Continuing
+ # message, but otherwise appears normal (FIXME).
+ gdb_expect {
+ -re "^continue\r\nContinuing.\r\n(\r\n|)$" { pass "continue" }
+ -re "^continue\r\n\r\n" { fail "continue (missing Continuing.)" }
+ -re "$gdb_prompt $" { fail "continue" }
+ timeout { fail "continue (timeout)" }
+ eof { fail "continue (eof)" }
+ }
+
+ send_gdb "data\n"
+ # The optional leading \r\n is in case we sent a newline above
+ # to wake the program, in which case the program now sends it
+ # back.
+ gdb_expect {
+ -re "^(\r\n|)data\r\n(|data\r\n)$" { pass "echo data" }
+ timeout { fail "echo data (timeout)" }
+ eof { fail "echo data (eof)" }
+ }
+
+ setup_xfail "i*86-pc-linux*-gnu*"
+ send_gdb "\004"
+ gdb_expect {
+ -re "end of file.*Program exited normally.*$gdb_prompt $" {
+ pass "send_gdb end of file"
+ }
+ -re "$gdb_prompt $" { fail "send end of file" }
+ timeout { fail "send end of file (timeout)" }
+ eof { fail "send end of file (eof)" }
+ }
+ }
+}
+return 0
diff --git a/gdb/testsuite/gdb.base/jump.c b/gdb/testsuite/gdb.base/jump.c
new file mode 100644
index 00000000000..e16d0fd384d
--- /dev/null
+++ b/gdb/testsuite/gdb.base/jump.c
@@ -0,0 +1,19 @@
+/* This program is used to test the "jump" command. There's nothing
+ particularly deep about the functionality nor names in here.
+ */
+
+static int square (x)
+ int x;
+{
+ return x*x;
+}
+
+
+main ()
+{
+ int i = 99;
+
+ i++;
+ i = square (i);
+ i--;
+}
diff --git a/gdb/testsuite/gdb.base/jump.exp b/gdb/testsuite/gdb.base/jump.exp
new file mode 100644
index 00000000000..c110e21cf04
--- /dev/null
+++ b/gdb/testsuite/gdb.base/jump.exp
@@ -0,0 +1,192 @@
+# Copyright (C) 1998 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+if $tracelevel then {
+ strace $tracelevel
+ }
+
+set prms_id 0
+set bug_id 0
+
+# are we on a target board
+if ![isnative] then {
+ return 0
+}
+
+clear_xfail "*-*-*"
+
+set testfile "jump"
+set srcfile ${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+
+# Build the test case
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug additional_flags=-w}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+ }
+
+
+# Start with a fresh gdb
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+if ![runto_main] then {
+ perror "Couldn't run to main"
+ return -1
+}
+
+# Set a breakpoint on the statement that we're about to jump to.
+# The statement doesn't contain a function call.
+#
+send_gdb "break 18\n"
+set bp_on_non_call 0
+gdb_expect {
+ -re "\[Bb\]reakpoint (\[0-9\]*) at 0x\[0-9a-fA-F\]*: file .*${srcfile}, line 18.*$gdb_prompt $"\
+ {set bp_on_non_call $expect_out(1,string)
+ pass "break before jump to non-call"}
+ -re "$gdb_prompt $"\
+ {fail "break before jump to non-call"}
+ timeout {fail "(timeout) break before jump to non-call"}
+}
+
+# Can we jump to the statement? Do we stop there?
+#
+send_gdb "jump 18\n"
+gdb_expect {
+ -re "Breakpoint \[0-9\]*, .*${srcfile}:18.*$gdb_prompt $"\
+ {pass "jump to non-call"}
+ -re "$gdb_prompt $"\
+ {fail "jump to non-call"}
+ timeout {fail "(timeout) jump to non-call"}
+}
+
+# Set a breakpoint on the statement that we're about to jump to.
+# The statement does contain a function call.
+#
+send_gdb "break 17\n"
+set bp_on_call 0
+gdb_expect {
+ -re "\[Bb\]reakpoint (\[0-9\]*) at 0x\[0-9a-fA-F\]*: file .*${srcfile}, line 17.*$gdb_prompt $"\
+ {set bp_on_call $expect_out(1,string)
+ pass "break before jump to call"}
+ -re "$gdb_prompt $"\
+ {fail "break before jump to call"}
+ timeout {fail "(timeout) break before jump to call"}
+}
+
+# Can we jump to the statement? Do we stop there?
+#
+send_gdb "jump 17\n"
+gdb_expect {
+ -re "Breakpoint \[0-9\]*, .*${srcfile}:17.*$gdb_prompt $"\
+ {pass "jump to call"}
+ -re "$gdb_prompt $"\
+ {fail "jump to call"}
+ timeout {fail "(timeout) jump to call"}
+}
+
+# If we disable the breakpoint at the function call, and then
+# if we jump to that statement, do we not stop there, but at
+# the following breakpoint?
+#
+send_gdb "disable $bp_on_call\n"
+gdb_expect {
+ -re "$gdb_prompt $"\
+ {pass "disable breakpoint on call"}
+ timeout {fail "(timeout) disable breakpoint on call"}
+}
+
+send_gdb "jump 17\n"
+gdb_expect {
+ -re "Breakpoint \[0-9\]*, .*${srcfile}:18.*$gdb_prompt $"\
+ {pass "jump to call with disabled breakpoint"}
+ -re "$gdb_prompt $"\
+ {fail "jump to call with disabled breakpoint"}
+ timeout {fail "(timeout) jump to call with disabled breakpoint"}
+}
+
+# Verify that GDB responds gracefully to the "jump" command without
+# an argument.
+#
+send_gdb "jump\n"
+gdb_expect {
+ -re "Argument required .starting address..*$gdb_prompt $"\
+ {pass "jump without argument disallowed"}
+ -re "$gdb_prompt $"\
+ {fail "jump without argument disallowed"}
+ timeout {fail "(timeout) jump without argument disallowed"}
+}
+
+# Verify that GDB responds gracefully to the "jump" command with
+# trailing junk.
+#
+send_gdb "jump 17 100\n"
+gdb_expect {
+ -re "Junk at end of line specification: 100.*$gdb_prompt $"\
+ {pass "jump with trailing argument junk"}
+ -re "$gdb_prompt $"\
+ {fail "jump with trailing argument junk"}
+ timeout {fail "(timeout) jump with trailing argument junk"}
+}
+
+# Verify that GDB responds gracefully to a request to jump out of
+# the current function. (Note that this will very likely cause the
+# inferior to die. Be prepared to rerun the inferior, if further
+# testing is desired.)
+#
+# Try it both ways: confirming and not confirming the jump.
+#
+send_gdb "jump 8\n"
+gdb_expect {
+ -re "Line 8 is not in `main'. Jump anyway.*y or n. $"\
+ {send_gdb "n\n"
+ gdb_expect {
+ -re "Not confirmed.*$gdb_prompt $"\
+ {pass "aborted jump out of current function"}
+ -re "$gdb_prompt $"\
+ {fail "aborted jump out of current function"}
+ timeout {fail "(timeout) aborted jump out of current function"}
+ }
+ }
+ -re "$gdb_prompt $"\
+ {fail "aborted jump out of current function"}
+ timeout {fail "(timeout) aborted jump out of current function"}
+}
+
+send_gdb "jump 8\n"
+gdb_expect {
+ -re "Line 8 is not in `main'. Jump anyway.*y or n. $"\
+ {send_gdb "y\n"
+ gdb_expect {
+ -re "Continuing at.*$gdb_prompt $"\
+ {pass "jump out of current function"}
+ -re "$gdb_prompt $"\
+ {fail "jump out of current function"}
+ timeout {fail "(timeout) jump out of current function"}
+ }
+ }
+ -re "$gdb_prompt $"\
+ {fail "jump out of current function"}
+ timeout {fail "(timeout) jump out of current function"}
+}
+
+gdb_exit
+return 0
diff --git a/gdb/testsuite/gdb.base/langs.exp b/gdb/testsuite/gdb.base/langs.exp
new file mode 100644
index 00000000000..464c79786e0
--- /dev/null
+++ b/gdb/testsuite/gdb.base/langs.exp
@@ -0,0 +1,122 @@
+# Copyright (C) 1997, 1998 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+set prms_id 0
+set bug_id 0
+
+set testfile langs
+set binfile ${objdir}/${subdir}/${testfile}
+
+if [is_remote host] {
+ remote_download host ${srcdir}/${subdir}/langs1.f
+ remote_download host ${srcdir}/${subdir}/langs2.cxx
+}
+
+
+if { [gdb_compile "${srcdir}/${subdir}/langs0.c" "${binfile}0.o" object {debug}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+if { [gdb_compile "${srcdir}/${subdir}/langs1.c" "${binfile}1.o" object {debug}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+if { [gdb_compile "${srcdir}/${subdir}/langs2.c" "${binfile}2.o" object {debug}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+if { [gdb_compile "${binfile}0.o ${binfile}1.o ${binfile}2.o" ${binfile} executable {debug}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+
+
+
+# Create and source the file that provides information about the compiler
+# used to compile the test case.
+if [get_compiler_info ${binfile}] {
+ return -1;
+}
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load $binfile
+
+gdb_test "b langs0" {Function "langs0" not defined\.} \
+ "break on nonexistent function in langs.exp"
+
+if [runto csub] then {
+
+ gdb_test "show language" "currently c\".*" \
+ "show language at csub in langs.exp"
+ # On some machines, foo doesn't get demangled because the N_SOL for
+ # langs2.cxx is seen only after the function stab for foo. So
+ # the following regexps are kludged to accept foo__Fi as well as foo,
+ # even though only the latter is correct. I haven't tried to xfail it
+ # because it depends on details of the compiler.
+
+ if {!$gcc_compiled} then { setup_xfail "hppa*-*-hpux*" }
+ gdb_test "bt" "#0.*csub.*#1.*(foo|foo__Fi) \\(.*#2.*cppsub_ .*#3.*fsub.*#4.*langs0__2do \\(.*#5 \[0-9a-fx\]* in main.*" "backtrace in langs.exp"
+
+ if {!$gcc_compiled} then { setup_xfail "rs6000-*-*" }
+ gdb_test "up" ".* in (foo|foo__Fi) .* at langs2\\.cxx.*return csub \\(.*" \
+ "up to foo in langs.exp"
+ gdb_test "show language" "currently c\\+\\+.*" \
+ "show language at foo in langs.exp"
+
+ if {!$gcc_compiled} then { setup_xfail "rs6000-*-*" }
+ gdb_test "up" ".* in cppsub_ .* at langs2\\.cxx.*return foo \\(.*" \
+ "up to cppsub_ in langs.exp"
+ gdb_test "show language" "currently c\\+\\+.*" \
+ "show language at cppsub_ in langs.exp"
+
+ if {!$gcc_compiled} then { setup_xfail "rs6000-*-*" }
+ gdb_test "up" ".* in fsub.* at langs1\\.f.*return \\(cppsub .*" \
+ "up to fsub in langs.exp"
+ gdb_test "show language" "currently fortran.*" \
+ "show language at fsub in langs.exp"
+
+ if {!$gcc_compiled} then { setup_xfail "hppa*-*-hpux*" }
+ gdb_test "up" ".* in langs0__2do .* at .*langs0\\.c.*return fsub.*" \
+ "up to langs0__2do in langs.exp"
+ gdb_test "show language" "currently c\".*" \
+ "show language at langs0__2do in langs.exp"
+
+ gdb_test "up" ".* in main .* at .*langs0\\.c.*if \\(langs0__2do \\(.*" \
+ "up to main in langs.exp"
+ gdb_test "show language" "currently c\".*" \
+ "show language at main in langs.exp"
+
+ if [target_info exists gdb,noresults] { return }
+
+ if [target_info exists use_gdb_stub] {
+ gdb_breakpoint "exit"
+ gdb_test "cont" "Breakpoint .*exit.*" "continue to exit in langs.exp"
+ } else {
+ gdb_test "cont" "Program exited normally\\..*" \
+ "continue to exit in langs.exp"
+ }
+}
+
+return 0
diff --git a/gdb/testsuite/gdb.base/langs0.c b/gdb/testsuite/gdb.base/langs0.c
new file mode 100644
index 00000000000..69c0ce8b0fa
--- /dev/null
+++ b/gdb/testsuite/gdb.base/langs0.c
@@ -0,0 +1,28 @@
+/* This file is actually in C, it is not supposed to simulate something
+ translated from another language or anything like that. */
+int
+csub (x)
+ int x;
+{
+ return x + 1;
+}
+
+int
+langs0__2do ()
+{
+ return fsub_ () + 2;
+}
+
+int
+main ()
+{
+#ifdef usestubs
+ set_debug_traps();
+ breakpoint();
+#endif
+ if (langs0__2do () == 5003)
+ /* Success. */
+ return 0;
+ else
+ return 1;
+}
diff --git a/gdb/testsuite/gdb.base/langs1.c b/gdb/testsuite/gdb.base/langs1.c
new file mode 100644
index 00000000000..784225902c4
--- /dev/null
+++ b/gdb/testsuite/gdb.base/langs1.c
@@ -0,0 +1,33 @@
+/* langs1.f -- translated by f2c (version of 5 May 1990 1:12:08). */
+
+/* f2c output hacked as follows for GDB testsuite:
+ 1. Change commented out "#" lines to #line directives.
+ I don't know why this behavior isn't the default for f2c -g.
+ 2. Remove include of f2c.h and put in just a typedef for "integer".
+ Additional notes:
+ 3. f2c was called as "f2c -g langs1.f".
+ 4. We don't need to use the fortran libraries. */
+
+typedef int integer;
+
+/* Table of constant values */
+
+static integer c__10000 = 10000;
+
+/* I am not sure whether there is a way to have a fortran program without */
+/* a MAIN, but it does not really harm us to have one. */
+/* Main program */ MAIN__()
+{
+} /* MAIN__ */
+
+#line 4 "langs1.f"
+/* Subroutine */ int fsub_()
+{
+ extern integer cppsub_();
+
+#line 5 "langs1.f"
+#line 6 "langs1.f"
+ return cppsub_(&c__10000);
+#line 7 "langs1.f"
+} /* fsub_ */
+
diff --git a/gdb/testsuite/gdb.base/langs1.f b/gdb/testsuite/gdb.base/langs1.f
new file mode 100644
index 00000000000..35ce6911472
--- /dev/null
+++ b/gdb/testsuite/gdb.base/langs1.f
@@ -0,0 +1,7 @@
+c I am not sure whether there is a way to have a fortran program without
+c a MAIN, but it does not really harm us to have one.
+ end
+ subroutine fsub
+ integer*4 cppsub
+ return (cppsub (10000))
+ end
diff --git a/gdb/testsuite/gdb.base/langs2.c b/gdb/testsuite/gdb.base/langs2.c
new file mode 100644
index 00000000000..be2a60cfbb8
--- /dev/null
+++ b/gdb/testsuite/gdb.base/langs2.c
@@ -0,0 +1,15 @@
+/* This is intended to be a vague simulation of cfront output. */
+#line 1 "langs2.cxx"
+extern int csub ();
+int
+foo__Fi (x) int x;
+{
+ return csub (x / 2);
+}
+
+extern int cppsub_ ();
+int
+cppsub_ (y) int *y;
+{
+ return foo__Fi (*y);
+}
diff --git a/gdb/testsuite/gdb.base/langs2.cxx b/gdb/testsuite/gdb.base/langs2.cxx
new file mode 100644
index 00000000000..5a2ca8a1568
--- /dev/null
+++ b/gdb/testsuite/gdb.base/langs2.cxx
@@ -0,0 +1,13 @@
+extern "C" int csub (int);
+int
+foo (int x)
+{
+ return csub (x / 2);
+}
+
+extern "C" int cppsub_ (int *);
+int
+cppsub_ (int *y)
+{
+ return foo (*y);
+}
diff --git a/gdb/testsuite/gdb.base/list.exp b/gdb/testsuite/gdb.base/list.exp
new file mode 100644
index 00000000000..f597b9ad2ce
--- /dev/null
+++ b/gdb/testsuite/gdb.base/list.exp
@@ -0,0 +1,521 @@
+# Copyright (C) 1992, 1994, 1995, 1997, 1998 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file was written by Fred Fish. (fnf@cygnus.com)
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+set prms_id 0
+set bug_id 0
+
+set testfile "list"
+set binfile ${objdir}/${subdir}/${testfile}
+
+# Need to download the header to the host.
+remote_download host ${srcdir}/${subdir}/list0.h list0.h
+
+
+if { [gdb_compile "${srcdir}/${subdir}/list0.c" "${binfile}0.o" object {debug}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+if { [gdb_compile "${srcdir}/${subdir}/list1.c" "${binfile}1.o" object {debug}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+if { [gdb_compile "${binfile}0.o ${binfile}1.o" ${binfile} executable {debug}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+
+
+# Create and source the file that provides information about the compiler
+# used to compile the test case.
+if [get_compiler_info ${binfile}] {
+ return -1;
+}
+
+#
+# Local utility proc just to set and verify listsize
+# Return 1 if success, 0 if fail.
+#
+
+set set_listsize_count 0;
+
+proc set_listsize { arg } {
+ global gdb_prompt
+ global set_listsize_count;
+
+ incr set_listsize_count;
+ if [gdb_test "set listsize $arg" "" "setting listsize to $arg #$set_listsize_count"] {
+ return 0;
+ }
+ if { $arg <= 0 } {
+ set arg "unlimited";
+ }
+
+ if [gdb_test "show listsize" "Number of source lines.* is ${arg}.*" "show listsize $arg #$set_listsize_count"] {
+ return 0;
+ }
+ return 1
+}
+
+#
+# Test display of listsize lines around a given line number.
+#
+
+proc test_listsize {} {
+ global gdb_prompt
+
+ # Show default size
+
+ gdb_test "show listsize" "Number of source lines gdb will list by default is 10.*" "show default list size"
+
+ # Show the default lines
+ # The second case is for optimized code, it is still correct.
+
+ if ![isnative] {
+ runto_main;
+ unsupported "list default lines around main";
+ } else {
+ gdb_test "list" "(1\[ \t\]+#include \"list0.h\".*10\[ \t\]+x = 0;|2.*11\[ \t\]+foo .x\[+)\]+;)" "list default lines around main"
+ }
+
+ # Ensure we can limit printouts to one line
+
+ if [ set_listsize 1 ] then {
+ setup_xfail "*-*-*"
+ gdb_test "list 1" "1\[ \t\]+#include \"list0.h\"" "list line 1 with listsize 1"
+ setup_xfail "*-*-*"
+ gdb_test "list 2" "2\[ \t\]+" "list line 2 with listsize 1"
+ }
+
+ # Try just two lines
+
+ if [ set_listsize 2 ] {
+ gdb_test "list 1" "1\[ \t\]+#include \"list0.h\"" "list line 1 with listsize 2"
+ gdb_test "list 2" "1\[ \t\]+#include \"list0.h\"\r\n2\[ \t\]+" "list line 2 with listsize 2"
+ gdb_test "list 3" "2\[ \t\]+\r\n3\[ \t\]+main \[)(\]+" "list line 3 with listsize 2"
+ }
+
+ # Try small listsize > 1 that is an odd number
+
+ if [ set_listsize 3 ] {
+ setup_xfail "*-*-*"
+ gdb_test "list 1" "1\[ \t\]+#include \"list0.h\"2\[ \t\]+" "list line 1 with listsize 3"
+ setup_xfail "*-*-*"
+ gdb_test "list 2" "1\[ \t\]+#include \"list0.h\".*3\[ \t\]+main \[)(\]+" "list line 2 with listsize 3"
+
+ setup_xfail "*-*-*"
+ gdb_test "list 3" "2\[ \t\]+\r\n3\[ \t\]+main \[(\]+\[)\]+\r\n4\[ \t\]+\{" "list line 3 with listsize 3"
+ }
+
+ # Try small listsize > 2 that is an even number.
+
+ if [ set_listsize 4 ] then {
+ gdb_test "list 1" "1\[ \t\]+#include \"list0.h\"\r\n2\[ \t\]+" "list line 1 with listsize 4"
+ gdb_test "list 2" "1\[ \t\]+#include \"list0.h\".*3\[ \t\]+main \[)(\]+" "list line 2 with listsize 4"
+
+ gdb_test "list 3" "1\[ \t\]+#include \"list0.h\".*4\[ \t\]+\{" "list line 3 with listsize 4"
+ gdb_test "list 4" "2\[ \t\]+\r\n.*5\[ \t\]+int x;.*" "list line 4 with listsize 4"
+ }
+
+ # Try a size larger than the entire file.
+
+ if [ set_listsize 100 ] then {
+ gdb_test "list 1" "1\[ \t\]+#include \"list0.h\".*\r\n42\[ \t\]+\}" "list line 1 with listsize 100"
+
+ gdb_test "list 10" "1\[ \t\]+#include \"list0.h\".*\r\n42\[ \t\]+\}" "list line 10 with listsize 100"
+ }
+
+ # Try listsize of 0 which suppresses printing.
+
+ set_listsize 0
+ gdb_test "list 1" "" "listsize of 0 suppresses output"
+
+ # Try listsize of -1 which is special, and means unlimited.
+
+ set_listsize -1
+ setup_xfail "*-*-*"
+ gdb_test "list 1" "1\[ \t\]+#include .*\r\n39\[ \t\]+\}" "list line 1 with unlimited listsize"
+}
+
+#
+# Test "list filename:number" for C include file
+#
+
+proc test_list_include_file {} {
+ global gdb_prompt
+
+ setup_xfail "a29k-*-udi"
+ setup_xfail_format "DWARF 1"
+ setup_xfail_format "COFF"
+ gdb_test "list list0.h:1" "1\[ \t\]+/\[*\]+ An include file .*5\[ \t\]+foo \[(\]+x\[)\]+" "list line 1 in include file"
+
+ setup_xfail "a29k-*-udi"
+ setup_xfail_format "DWARF 1"
+ setup_xfail_format "COFF"
+ gdb_test "list list0.h:100" "Line number 95 out of range; .*list0.h has 36 lines." "list message for lines past EOF"
+}
+
+#
+# Test "list filename:number" for C source file
+#
+
+proc test_list_filename_and_number {} {
+ global gdb_prompt
+
+ set testcnt 0
+
+ send_gdb "list list0.c:1\n"
+ gdb_expect {
+ -re "1\[ \t\]+#include \"list0.h\".*5\[ \t\]+int x;\r\n$gdb_prompt $" {
+ incr testcnt
+ }
+ -re ".*$gdb_prompt $" { fail "list list0.c:1" ; gdb_suppress_tests }
+ timeout { fail "list list0.c:1 (timeout)" ; gdb_suppress_tests }
+ }
+ send_gdb "list list0.c:10\n"
+ gdb_expect {
+ -re "5\[ \t\]+int x;.*14\[ \t\]+foo .x\[+)\]+;\r\n$gdb_prompt $" {
+ incr testcnt
+ }
+ -re ".*$gdb_prompt $" { fail "list list.c:10" ; gdb_suppress_tests }
+ timeout { fail "list list.c:10 (timeout)" ; gdb_suppress_tests }
+ }
+ send_gdb "list list1.c:1\n"
+ gdb_expect {
+ -re "1\[ \t\]+void.*5\[ \t\]+printf \[(\]+.*\[)\]+;\r\n$gdb_prompt $" {
+ incr testcnt
+ }
+ -re ".*$gdb_prompt $" { fail "list list1.c:1" ; gdb_suppress_tests }
+ timeout { fail "list list1.c:1 (timeout)" ; gdb_suppress_tests }
+ }
+ send_gdb "list list1.c:12\n"
+ gdb_expect {
+ -re "7\[ \t\]+long_line \[(\]+.*\[)\]+;.*14\[ \t\]+\}\r\n.*$gdb_prompt $" {
+ incr testcnt
+ }
+ -re ".*$gdb_prompt $" { fail "list list1.c:12" ; gdb_suppress_tests }
+ timeout { fail "list list1.c:12 (timeout)" ; gdb_suppress_tests }
+ }
+ pass "list filename:number ($testcnt tests)"
+ gdb_stop_suppressing_tests;
+}
+
+#
+# Test "list function" for C source file
+#
+
+proc test_list_function {} {
+ global gdb_prompt
+ global gcc_compiled
+
+ # gcc appears to generate incorrect debugging information for code
+ # in include files, which breaks this test.
+ # SunPRO cc is the second case below, it's also correct.
+ setup_xfail "a29k-*-udi"
+ gdb_test "list main" "(5\[ \t\]+int x;.*14\[ \t\]+foo \[(\]+.*\[)\]+;|1\[ \t\]+#include .*8\[ \t\]+breakpoint\[(\]\[)\]+;)" "list function in source file 1"
+
+ # Ultrix gdb takes the second case below; it's also correct.
+ # SunPRO cc is the third case.
+ gdb_test "list bar" "(1\[ \t\]+void.*7\[ \t\]*long_line ..;.*9\[ \t\]*|1\[ \t\]+void.*8\[ \t\]+\}|1\[ \t\]+void.*7\[ \t\]*long_line ..;)" "list function in source file 2"
+
+ # Test "list function" for C include file
+ # Ultrix gdb is the second case, still correct.
+ # SunPRO cc is the third case.
+ setup_xfail "powerpc-*-*"
+ setup_xfail_format "DWARF 1"
+ gdb_test "list foo" "(3\[ \t\]+.*12\[ \t\]+bar \[(\]+.*\[)\]+;|2\[ \t\]+including file.*11\[ \t\]+bar \[(\]+.*\[)\]+;|1\[ \t\]+/. An include file.*10\[ \t\]+bar \[(\]+.*\[)\]+;)" "list function in include file"
+}
+
+proc test_list_forward {} {
+ global gdb_prompt
+
+ set testcnt 0
+
+ send_gdb "list list0.c:10\n"
+ gdb_expect {
+ -re "5\[ \t\]+int x;.*14\[ \t\]+foo \[(\]+.*\[)\]+;\r\n$gdb_prompt $" { incr testcnt }
+ -re ".*$gdb_prompt $" { fail "list list0.c:10" ; gdb_suppress_tests }
+ timeout { fail "list list0.c:10 (timeout)" ; gdb_suppress_tests }
+ }
+
+ send_gdb "list\n"
+ gdb_expect {
+ -re "15\[ \t\]+foo \[(\]+.*\[)\]+;.*24\[ \t\]+foo \[(\]+.*\[)\]+;\r\n$gdb_prompt $" { incr testcnt }
+ -re ".*$gdb_prompt $" { fail "list 15-24" ; gdb_suppress_tests }
+ timeout { fail "list 15-24 (timeout)" ; gdb_suppress_tests }
+ }
+
+ send_gdb "list\n"
+ gdb_expect {
+ -re "25\[ \t\]+foo \[(\]+.*\[)\]+;.*34\[ \t\]+foo \[(\]+.*\[)\]+;\r\n$gdb_prompt $" { incr testcnt }
+ -re ".*$gdb_prompt $" { fail "list 25-34" ; gdb_suppress_tests }
+ timeout { fail "list 25-34 (timeout)" ; gdb_suppress_tests }
+ }
+
+ send_gdb "list\n"
+ gdb_expect {
+ -re "35\[ \t\]+foo \[(\]+.*\[)\]+;.*42\[ \t\]+\}\r\n$gdb_prompt $" { incr testcnt }
+ -re ".*$gdb_prompt $" { fail "list 35-42" ; gdb_suppress_tests }
+ timeout { fail "list 35-42 (timeout)" ; gdb_suppress_tests }
+ }
+
+ pass "successive list commands to page forward ($testcnt tests)"
+ gdb_stop_suppressing_tests;
+}
+
+proc test_list_backwards {} {
+ global gdb_prompt
+
+ set testcnt 0
+
+ send_gdb "list list0.c:33\n"
+ gdb_expect {
+ -re "28\[ \t\]+foo \[(\]+.*\[)\]+;.*37\[ \t\]+\r\n$gdb_prompt $" { incr testcnt }
+ -re ".*$gdb_prompt $" { fail "list list0.c:33" ; gdb_suppress_tests }
+ timeout { fail "list list0.c:33 (timeout)" ; gdb_suppress_tests }
+ }
+
+ send_gdb "list -\n"
+ gdb_expect {
+ -re "18\[ \t\]+foo \[(\]+.*\[)\]+;.*27\[ \t\]+foo \[(\]+.*\[)\]+;\r\n$gdb_prompt $" { incr testcnt }
+ -re ".*$gdb_prompt $" { fail "list 18-27" ; gdb_suppress_tests }
+ timeout { fail "list 18-27 (timeout)" ; gdb_suppress_tests }
+ }
+
+ send_gdb "list -\n"
+ gdb_expect {
+ -re "8\[ \t\]+breakpoint\[(\]\[)\];.*17\[ \t\]+foo \[(\]+.*\[)\]+;\r\n$gdb_prompt $" { incr testcnt }
+ -re ".*$gdb_prompt $" { fail "list 8-17" ; gdb_suppress_tests }
+ timeout { fail "list 8-17 (timeout)" ; gdb_suppress_tests }
+ }
+
+ send_gdb "list -\n"
+ gdb_expect {
+ -re "1\[ \t\]+#include .*7\[ \t\]+set_debug_traps\[(\]\[)\]+;\r\n$gdb_prompt $" { incr testcnt }
+ -re ".*$gdb_prompt $" { fail "list 1-7" ; gdb_suppress_tests }
+ timeout { fail "list 1-7 (timeout)" ; gdb_suppress_tests }
+ }
+
+ pass "$testcnt successive \"list -\" commands to page backwards"
+ gdb_stop_suppressing_tests;
+}
+
+#
+# Test "list first,last"
+#
+
+proc test_list_range {} {
+ global gdb_prompt
+
+ gdb_test "list list0.c:2,list0.c:5" "2\[ \t\]+\r\n3\[ \t\]+main \[)(\]+.*5\[ \t\]+int x;" "list range; filename:line1,filename:line2"
+
+ gdb_test "list 2,5" "2\[ \t\]+\r\n3\[ \t\]+main \[)(\]+.*5\[ \t\]+int x;" "list range; line1,line2"
+
+# gdb_test "list -1,6" "Line number 0 out of range; .*list0.c has 39 lines." "list range; lower bound negative"
+
+# gdb_test "list -100,-40" "Line number -60 out of range; .*list0.c has 39 lines." "list range; both bounds negative"
+
+ gdb_test "list 30,43" "30\[ \t\]+foo \[(\]+.*\[)\]+;.*42\[ \t\]+\}" "list range; upper bound past EOF"
+
+ gdb_test "list 43,100" "Line number 43 out of range; .*list0.c has 42 lines." "list range; both bounds past EOF"
+
+ gdb_test "list list0.c:2,list1.c:17" "Specified start and end are in different files." "list range, must be same files"
+}
+
+#
+# Test "list filename:function"
+#
+
+proc test_list_filename_and_function {} {
+ global gdb_prompt
+
+ set testcnt 0
+
+ # gcc appears to generate incorrect debugging information for code
+ # in include files, which breaks this test.
+ # SunPRO cc is the second case below, it's also correct.
+ setup_xfail "a29k-*-udi"
+ send_gdb "list list0.c:main\n"
+ gdb_expect {
+ -re "1\[ \t\]+#include .*8\[ \t\]+breakpoint\[(\]\[)\]+;\r\n$gdb_prompt $" {
+ incr testcnt
+ }
+ -re "5\[ \t\]+int x;.*14\[ \t\]+foo \[(\]+.*\[)\]+;\r\n$gdb_prompt $" {
+ pass "list function in source file 1"
+ }
+ -re ".*$gdb_prompt $" { fail "list list0.c:main" }
+ timeout { fail "list list0.c:main (timeout)" }
+ }
+
+ # The i960 and a29k-amd-udi are the second case
+
+ # Not sure what the point of having this function be unused is.
+ # AIX is legitimately removing it.
+ setup_xfail "rs6000-*-aix*"
+ send_gdb "list list0.c:unused\n"
+ gdb_expect {
+ -re "36\[ \t\]+\}.*42\[ \t\]+\}\r\n$gdb_prompt $" {
+ incr testcnt
+ }
+ -re "37.*42\[ \t\]+\}\r\n$gdb_prompt $" {
+ incr testcnt
+ }
+ -re ".*$gdb_prompt $" { fail "list list0.c:unused" }
+ timeout { fail "list list0.c:unused (timeout)" }
+ }
+ clear_xfail "rs6000-*-aix*"
+
+ # gcc appears to generate incorrect debugging information for code
+ # in include files, which breaks this test.
+ # Ultrix gdb is the second case, one line different but still correct.
+ # SunPRO cc is the third case.
+ setup_xfail "rs6000-*-*" 1804
+ setup_xfail "powerpc-*-*" 1804
+ setup_xfail "a29k-*-udi"
+ setup_xfail_format "DWARF 1"
+ setup_xfail_format "COFF"
+ send_gdb "list list0.h:foo\n"
+ gdb_expect {
+ -re "2\[ \t\]+including file. This.*11\[ \t\]+bar \[(\]+.*\[)\]+;\r\n$gdb_prompt $" {
+ incr testcnt
+ }
+ -re "1\[ \t\]+/. An include file.*10\[ \t\]+bar \[(\]+.*\[)\]+;\r\n$gdb_prompt $" {
+ incr testcnt
+ }
+ -re "3\[ \t\]+.*12\[ \t\]+bar \[(\]+.*\[)\]+;\r\n$gdb_prompt $" {
+ incr testcnt
+ }
+ -re "No source file named list0.h.\r\n$gdb_prompt $" {
+ fail "list list0.h:foo"
+ }
+ -re ".*$gdb_prompt $" { fail "list list0.h:foo" }
+ timeout { fail "list list0.h:foo (timeout)" }
+ }
+
+ # Ultrix gdb is the second case.
+ # a29k-amd-udi is the third case.
+ send_gdb "list list1.c:bar\n"
+ gdb_expect {
+ -re "1\[ \t\]+void.*8\[ \t\]+\}\r\n$gdb_prompt $" {
+ incr testcnt
+ }
+ -re "1\[ \t\]+void.*7\[ \t\]*long_line ..;\r\n$gdb_prompt $" {
+ incr testcnt
+ }
+ -re "1\[ \t\]+void.*9\[ \t\]*\r\n$gdb_prompt $" {
+ incr testcnt
+ }
+ -re ".*$gdb_prompt $" { fail "list list1.c:bar" }
+ timeout { fail "list list1.c:bar (timeout)" }
+ }
+
+ # The i960 and a29k-amd-udi are the second case
+
+ # Not sure what the point of having this function be unused is.
+ # AIX is legitimately removing it.
+ setup_xfail "rs6000-*-aix*"
+ send_gdb "list list1.c:unused\n"
+ gdb_expect {
+ -re "7\[ \t\]+long_line \[(\]\[)\];.*14\[ \t\]+\}\r\n.*$gdb_prompt $" {
+ incr testcnt
+ }
+ -re "9.*14\[ \t\]+\}\r\n.*$gdb_prompt $" {
+ incr testcnt
+ }
+ -re ".*$gdb_prompt $" { fail "list list1.c:unused" }
+ timeout { fail "list list1.c:unused (timeout)" }
+ }
+ clear_xfail "rs6000-*-aix*"
+
+ pass "list filename:function ($testcnt tests)"
+
+ # Test some invalid specs
+ # The following test takes the FIXME result on most systems using
+ # DWARF. It fails to notice that main() is not in the file requested.
+
+ setup_xfail "*-*-*"
+
+# Does this actually work ANYWHERE? I believe not, as this is an `aspect' of
+# lookup_symbol(), where, when it is given a specific symtab which does not
+# contain the requested symbol, it will subsequently search all of the symtabs
+# for the requested symbol.
+
+ gdb_test "list list0.c:foo" "Function \"foo\" not defined in .*list0.c" "list filename:function; wrong filename rejected"
+
+ gdb_test "list foobar.c:main" "No source file named foobar.c." "list filename:function; nonexistant file"
+
+ setup_xfail_format "DWARF 1"
+ gdb_test "list list0.h:foobar" "Function \"foobar\" not defined." "list filename:function; nonexistant function"
+
+}
+
+proc test_forward_search {} {
+ global timeout
+
+ gdb_test "set listsize 4" ""
+ # On SunOS4, this gives us lines 19-22. On AIX, it gives us
+ # lines 20-23. This depends on whether the line number of a function
+ # is considered to be the openbrace or the first statement--either one
+ # is acceptable.
+ gdb_test "list long_line" "20\[ \t\]+long_line .*"
+
+ gdb_test "search 4321" " not found"
+
+ gdb_test "search 6789" "24\[ \t\]+oof .6789.;"
+
+ # Test that GDB won't crash if the line being searched is extremely long.
+
+ set oldtimeout $timeout
+ set timeout [expr "$timeout + 300"]
+ verbose "Timeout is now $timeout seconds" 2
+ gdb_test "search 1234" ".*1234.*" "search extremely long line (> 5000 chars)"
+ set timeout $oldtimeout
+ verbose "Timeout is now $timeout seconds" 2
+}
+
+# Start with a fresh gdb.
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+if [target_info exists gdb_stub] {
+ gdb_step_for_stub;
+}
+
+gdb_test "set width 0" "" "set width 0"
+
+test_listsize
+get_debug_format
+if [ set_listsize 10 ] then {
+ test_list_include_file
+ test_list_filename_and_number
+ test_list_function
+ test_list_forward
+ test_list_backwards
+ test_list_range
+ test_list_filename_and_function
+ test_forward_search
+}
diff --git a/gdb/testsuite/gdb.base/list0.c b/gdb/testsuite/gdb.base/list0.c
new file mode 100644
index 00000000000..a5561a766a1
--- /dev/null
+++ b/gdb/testsuite/gdb.base/list0.c
@@ -0,0 +1,42 @@
+#include "list0.h"
+
+main ()
+{
+ int x;
+#ifdef usestubs
+ set_debug_traps();
+ breakpoint();
+#endif
+ x = 0;
+ foo (x++);
+ foo (x++);
+ foo (x++);
+ foo (x++);
+ foo (x++);
+ foo (x++);
+ foo (x++);
+ foo (x++);
+ foo (x++);
+ foo (x++);
+ foo (x++);
+ foo (x++);
+ foo (x++);
+ foo (x++);
+ foo (x++);
+ foo (x++);
+ foo (x++);
+ foo (x++);
+ foo (x++);
+ foo (x++);
+ foo (x++);
+ foo (x++);
+ foo (x++);
+ foo (x++);
+ foo (x++);
+}
+
+static void
+unused ()
+{
+ /* Not used for anything */
+}
diff --git a/gdb/testsuite/gdb.base/list0.h b/gdb/testsuite/gdb.base/list0.h
new file mode 100644
index 00000000000..c4d337c6770
--- /dev/null
+++ b/gdb/testsuite/gdb.base/list0.h
@@ -0,0 +1,36 @@
+/* An include file that actually causes code to be generated in the
+ including file. This is known to cause problems on some systems. */
+
+static void
+foo (x)
+int x;
+{
+ bar (x++);
+ bar (x++);
+ bar (x++);
+ bar (x++);
+ bar (x++);
+ bar (x++);
+ bar (x++);
+ bar (x++);
+ bar (x++);
+ bar (x++);
+ bar (x++);
+ bar (x++);
+ bar (x++);
+ bar (x++);
+ bar (x++);
+ bar (x++);
+ bar (x++);
+ bar (x++);
+ bar (x++);
+ bar (x++);
+ bar (x++);
+ bar (x++);
+ bar (x++);
+ bar (x++);
+ bar (x++);
+ bar (x++);
+ bar (x++);
+ bar (x++);
+}
diff --git a/gdb/testsuite/gdb.base/list1.c b/gdb/testsuite/gdb.base/list1.c
new file mode 100644
index 00000000000..51632b94d07
--- /dev/null
+++ b/gdb/testsuite/gdb.base/list1.c
@@ -0,0 +1,33 @@
+void
+bar (x)
+int x;
+{
+ printf ("%d\n", x);
+
+ long_line ();
+}
+
+static void
+unused ()
+{
+ /* Not used for anything */
+}
+
+
+/* This routine has a very long line that will break searching in older
+ versions of GDB. */
+
+long_line ()
+{
+ oof (67);
+
+ oof (6789);
+
+ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* 5 */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* 10 */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* 15 */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* 20 */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* 25 */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* 30 */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* 35 */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* 40 */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* 45 */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* 50 */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* 55 */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* 60 */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* 65 */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (1234); /* 70 */
+}
+
+oof (n)
+ int n;
+{
+ return n + 1;
+}
diff --git a/gdb/testsuite/gdb.base/logical.exp b/gdb/testsuite/gdb.base/logical.exp
new file mode 100644
index 00000000000..0458e61cb11
--- /dev/null
+++ b/gdb/testsuite/gdb.base/logical.exp
@@ -0,0 +1,575 @@
+# Copyright (C) 1998 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file was written by Elena Zannoni (ezannoni@cygnus.com)
+
+# This file is part of the gdb testsuite
+
+#
+# tests for correctenss of logical operators, associativity and precedence
+# with integer type variables
+#
+
+if $tracelevel then {
+ strace $tracelevel
+ }
+
+#
+# test running programs
+#
+set prms_id 0
+set bug_id 0
+
+set testfile "int-type"
+set srcfile ${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug additional_flags=-w}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+ }
+
+
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+
+#
+# set it up at a breakpoint so we can play with the variable values
+#
+
+if ![runto_main] then {
+ perror "couldn't run to breakpoint"
+ continue
+}
+
+#
+# test expressions with "int" types
+#
+
+gdb_test "set variable x=0" "" "set variable x=0"
+gdb_test "set variable y=0" "" "set variable y=0"
+gdb_test "set variable z=0" "" "set variable z=0"
+
+send_gdb "print x\n"
+gdb_expect {
+ -re ".*0.*$gdb_prompt $" {
+ pass "print value of x"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of x" }
+ timeout { fail "(timeout) print value of x" }
+ }
+
+
+send_gdb "print y\n"
+gdb_expect {
+ -re ".*0.*$gdb_prompt $" {
+ pass "print value of y"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of y" }
+ timeout { fail "(timeout) print value of y" }
+ }
+
+send_gdb "print z\n"
+gdb_expect {
+ -re ".*0.*$gdb_prompt $" {
+ pass "print value of z"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of z" }
+ timeout { fail "(timeout) print value of z" }
+ }
+
+
+# truth tables for && , || , !
+
+send_gdb "print x && y\n"
+gdb_expect {
+ -re ".*0.*$gdb_prompt $" {
+ pass "print value of x<y"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of x<y" }
+ timeout { fail "(timeout) print value of x<y" }
+ }
+
+
+
+send_gdb "print x || y\n"
+gdb_expect {
+ -re ".*0.*$gdb_prompt $" {
+ pass "print value of x<=y"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of x<=y" }
+ timeout { fail "(timeout) print value of x<=y" }
+ }
+
+send_gdb "print !x\n"
+gdb_expect {
+ -re ".*1.*$gdb_prompt $" {
+ pass "print value of x>y"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of x>y" }
+ timeout { fail "(timeout) print value of x>y" }
+ }
+
+gdb_test "set variable y=1" "" "set variable y=1"
+
+send_gdb "print x && y\n"
+gdb_expect {
+ -re ".*0.*$gdb_prompt $" {
+ pass "print value of x<y"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of x<y" }
+ timeout { fail "(timeout) print value of x<y" }
+ }
+
+
+
+send_gdb "print x || y\n"
+gdb_expect {
+ -re ".*1.*$gdb_prompt $" {
+ pass "print value of x<=y"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of x<=y" }
+ timeout { fail "(timeout) print value of x<=y" }
+ }
+
+gdb_test "set variable x=1" "" "set variable x=1"
+
+send_gdb "print x && y\n"
+gdb_expect {
+ -re ".*1.*$gdb_prompt $" {
+ pass "print value of x<y"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of x<y" }
+ timeout { fail "(timeout) print value of x<y" }
+ }
+
+
+
+send_gdb "print x || y\n"
+gdb_expect {
+ -re ".*1.*$gdb_prompt $" {
+ pass "print value of x<=y"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of x<=y" }
+ timeout { fail "(timeout) print value of x<=y" }
+ }
+
+send_gdb "print !x\n"
+gdb_expect {
+ -re ".*0.*$gdb_prompt $" {
+ pass "print value of x>y"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of x>y" }
+ timeout { fail "(timeout) print value of x>y" }
+ }
+
+gdb_test "set variable y=0" "" "set variable y=0"
+
+send_gdb "print x && y\n"
+gdb_expect {
+ -re ".*0.*$gdb_prompt $" {
+ pass "print value of x<y"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of x<y" }
+ timeout { fail "(timeout) print value of x<y" }
+ }
+
+
+
+send_gdb "print x || y\n"
+gdb_expect {
+ -re ".*1.*$gdb_prompt $" {
+ pass "print value of x<=y"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of x<=y" }
+ timeout { fail "(timeout) print value of x<=y" }
+ }
+
+
+# end truth tables for &&, ||, !
+
+
+# test associativity of && , || , !
+
+gdb_test "set variable x=0" "" "set variable x=0"
+gdb_test "set variable y=0" "" "set variable y=0"
+gdb_test "set variable z=0" "" "set variable z=0"
+
+send_gdb "print x && y && z\n"
+gdb_expect {
+ -re ".*0.*$gdb_prompt $" {
+ pass "print value of x && y && z (000)"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of x && y && z (000) " }
+ timeout { fail "(timeout) print value of x && y && z (000) " }
+ }
+
+send_gdb "print x || y || z\n"
+gdb_expect {
+ -re ".*0.*$gdb_prompt $" {
+ pass "print value of x || y || z (000)"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of x || y || z (000)" }
+ timeout { fail "(timeout) print value of x || y || z (000) " }
+ }
+
+send_gdb "print !!x\n"
+gdb_expect {
+ -re ".*0.*$gdb_prompt $" {
+ pass "print value of !!x (0)"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of !!x (0)" }
+ timeout { fail "(timeout) print value of !!x (0) " }
+ }
+
+
+gdb_test "set variable y=1" "" "set variable y=1"
+
+send_gdb "print x && y && z\n"
+gdb_expect {
+ -re ".*0.*$gdb_prompt $" {
+ pass "print value of x && y && z (010)"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of x && y && z (010) " }
+ timeout { fail "(timeout) print value of x && y && z (010) " }
+ }
+
+send_gdb "print x || y || z\n"
+gdb_expect {
+ -re ".*1.*$gdb_prompt $" {
+ pass "print value of x || y || z (010)"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of x || y || z (010)" }
+ timeout { fail "(timeout) print value of x || y || z (010) " }
+ }
+
+
+gdb_test "set variable z=1" "" "set variable z=1"
+
+send_gdb "print x && y && z\n"
+gdb_expect {
+ -re ".*0.*$gdb_prompt $" {
+ pass "print value of x && y && z (011)"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of x && y && z (011) " }
+ timeout { fail "(timeout) print value of x && y && z (011) " }
+ }
+
+send_gdb "print x || y || z\n"
+gdb_expect {
+ -re ".*1.*$gdb_prompt $" {
+ pass "print value of x || y || z (011)"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of x || y || z (011)" }
+ timeout { fail "(timeout) print value of x || y || z (011) " }
+ }
+
+
+gdb_test "set variable x=1" "" "set variable x=1"
+
+send_gdb "print x && y && z\n"
+gdb_expect {
+ -re ".*1.*$gdb_prompt $" {
+ pass "print value of x && y && z (111)"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of x && y && z (111) " }
+ timeout { fail "(timeout) print value of x && y && z (111) " }
+ }
+
+send_gdb "print x || y || z\n"
+gdb_expect {
+ -re ".*1.*$gdb_prompt $" {
+ pass "print value of x || y || z (111)"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of x || y || z (111)" }
+ timeout { fail "(timeout) print value of x || y || z (111) " }
+ }
+
+send_gdb "print !!x\n"
+gdb_expect {
+ -re ".*1.*$gdb_prompt $" {
+ pass "print value of !!x (1)"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of !!x (1)" }
+ timeout { fail "(timeout) print value of !!x (1) " }
+ }
+
+
+gdb_test "set variable z=0" "" "set variable z=0"
+
+send_gdb "print x && y && z\n"
+gdb_expect {
+ -re ".*0.*$gdb_prompt $" {
+ pass "print value of x && y && z (110)"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of x && y && z (110) " }
+ timeout { fail "(timeout) print value of x && y && z (110) " }
+ }
+
+send_gdb "print x || y || z\n"
+gdb_expect {
+ -re ".*1.*$gdb_prompt $" {
+ pass "print value of x || y || z (110)"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of x || y || z (110)" }
+ timeout { fail "(timeout) print value of x || y || z (110) " }
+ }
+
+
+
+
+gdb_test "set variable y=0" "" "set variable y=0"
+
+send_gdb "print x && y && z\n"
+gdb_expect {
+ -re ".*0.*$gdb_prompt $" {
+ pass "print value of x && y && z (100)"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of x && y && z (100) " }
+ timeout { fail "(timeout) print value of x && y && z (100) " }
+ }
+
+send_gdb "print x || y || z\n"
+gdb_expect {
+ -re ".*1.*$gdb_prompt $" {
+ pass "print value of x || y || z (100)"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of x || y || z (100)" }
+ timeout { fail "(timeout) print value of x || y || z (100) " }
+ }
+
+
+
+
+gdb_test "set variable z=1" "" "set variable z=1"
+
+send_gdb "print x && y && z\n"
+gdb_expect {
+ -re ".*0.*$gdb_prompt $" {
+ pass "print value of x && y && z (101)"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of x && y && z (101) " }
+ timeout { fail "(timeout) print value of x && y && z (101) " }
+ }
+
+send_gdb "print x || y || z\n"
+gdb_expect {
+ -re ".*1.*$gdb_prompt $" {
+ pass "print value of x || y || z (101)"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of x || y || z (101)" }
+ timeout { fail "(timeout) print value of x || y || z (101) " }
+ }
+
+
+gdb_test "set variable x=0" "" "set variable x=0"
+
+send_gdb "print x && y && z\n"
+gdb_expect {
+ -re ".*0.*$gdb_prompt $" {
+ pass "print value of x && y && z (001)"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of x && y && z (001) " }
+ timeout { fail "(timeout) print value of x && y && z (001) " }
+ }
+
+send_gdb "print x || y || z\n"
+gdb_expect {
+ -re ".*1.*$gdb_prompt $" {
+ pass "print value of x || y || z (001)"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of x || y || z (001)" }
+ timeout { fail "(timeout) print value of x || y || z (001) " }
+ }
+
+
+
+
+# test precedence of &&, || ,!
+
+
+send_gdb "print !x && y\n"
+gdb_expect {
+ -re ".*0.*$gdb_prompt $" {
+ pass "print value of !x && y (00)"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of !x && y (00)" }
+ timeout { fail "(timeout) print value of !x && y (00) " }
+ }
+
+
+gdb_test "set variable x=1" "" "set variable x=1"
+
+
+send_gdb "print !x && y\n"
+gdb_expect {
+ -re ".*0.*$gdb_prompt $" {
+ pass "print value of !x && y (10)"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of !x && y (10)" }
+ timeout { fail "(timeout) print value of !x && y (10) " }
+ }
+
+
+
+
+gdb_test "set variable y=1" "" "set variable y=1"
+
+send_gdb "print !x || y\n"
+gdb_expect {
+ -re ".*1.*$gdb_prompt $" {
+ pass "print value of !x || y (11)"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of !x || y (11)" }
+ timeout { fail "(timeout) print value of !x || y (11) " }
+ }
+
+
+gdb_test "set variable x=0" "" "set variable x=0"
+
+
+send_gdb "print !x || y\n"
+gdb_expect {
+ -re ".*1.*$gdb_prompt $" {
+ pass "print value of !x || y (01)"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of !x || y (01)" }
+ timeout { fail "(timeout) print value of !x || y (01) " }
+ }
+
+
+
+gdb_test "set variable x=1" "" "set variable x=1"
+gdb_test "set variable z=0" "" "set variable z=0"
+
+send_gdb "print x || y && z\n"
+gdb_expect {
+ -re ".*1.*$gdb_prompt $" {
+ pass "print value of x || y && z (110)"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of x || y && z (110)" }
+ timeout { fail "(timeout) print value of x || y && z (110) " }
+ }
+
+
+gdb_test "set variable y=0" "" "set variable y=0"
+
+
+send_gdb "print x || y && z\n"
+gdb_expect {
+ -re ".*1.*$gdb_prompt $" {
+ pass "print value of x || y && z (100)"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of x || y && z (100)" }
+ timeout { fail "(timeout) print value of x || y && z (100) " }
+ }
+
+
+
+gdb_test "set variable x=0" "" "set variable x=0"
+
+send_gdb "print x || !y && z\n"
+gdb_expect {
+ -re ".*0.*$gdb_prompt $" {
+
+ gdb_test "set variable x=1" "" "set variable x=1"
+ send_gdb "print x || !y && z\n"
+ gdb_expect {
+ -re ".*1.*$gdb_prompt $" {
+ pass "print value of x || !y && z "
+ }
+ -re ".*$gdb_prompt $" { fail "print value of x || !y && z" }
+ timeout { fail "(timeout) print value of x || !y && z " }
+ }
+ }
+ -re ".*$gdb_prompt $" { fail "print value of x || y && z " }
+ timeout { fail "(timeout) print value of x || y && z " }
+ }
+
+
+
+
+
+gdb_test "set variable x=1" "" "set variable x=1"
+gdb_test "set variable y=2" "" "set variable y=2"
+gdb_test "set variable w=3" "" "set variable w=3"
+gdb_test "set variable z=3" "" "set variable z=3"
+
+
+send_gdb "print x > y || w == z\n"
+gdb_expect {
+ -re ".*1.*$gdb_prompt $" {
+ pass "print value of x > y || w == z"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of x > y || w == z" }
+ timeout { fail "(timeout) print value of x > y || w == z " }
+ }
+
+
+gdb_test "set variable x=1" "" "set variable x=1"
+gdb_test "set variable y=2" "" "set variable y=2"
+gdb_test "set variable w=1" "" "set variable w=1"
+gdb_test "set variable z=3" "" "set variable z=3"
+
+
+send_gdb "print x >= y && w != z\n"
+gdb_expect {
+ -re ".*0.*$gdb_prompt $" {
+ pass "print value of x >= y || w != z"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of x >= y || w != z" }
+ timeout { fail "(timeout) print value of x >= y || w != z " }
+ }
+
+
+
+gdb_test "set variable x=2" "" "set variable x=2"
+gdb_test "set variable y=2" "" "set variable y=2"
+gdb_test "set variable w=2" "" "set variable w=2"
+gdb_test "set variable z=3" "" "set variable z=3"
+
+
+send_gdb "print ! x > y || w + z\n"
+gdb_expect {
+ -re ".*1.*$gdb_prompt $" {
+ pass "print value of x > y || w != z"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of x > y || w != z" }
+ timeout { fail "(timeout) print value of x > y || w != z " }
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/gdb/testsuite/gdb.base/long_long.c b/gdb/testsuite/gdb.base/long_long.c
new file mode 100644
index 00000000000..096528d1d20
--- /dev/null
+++ b/gdb/testsuite/gdb.base/long_long.c
@@ -0,0 +1,55 @@
+/* Test long long expression; test printing in general.
+ *
+ * /CLO/BUILD_ENV/Exports/cc -g +e -o long_long long_long.c
+ *
+ * or
+ *
+ * cc +e +DA2.0 -g -o long_long long_long.c
+ */
+
+long long callee( i )
+long long i;
+{
+ register long long result;
+
+ result = 0x12345678;
+ result = result << i;
+ result += 0x9abcdef0;
+
+ return result;
+}
+
+int known_types()
+{
+ long long bin = 0, oct = 0, dec = 0, hex = 0;
+
+ /* Known values, filling the full 64 bits.
+ */
+ bin = 0x123456789abcdefLL; /* 64 bits = 16 hex digits */
+ oct = 01234567123456701234567LL; /* = 21+ octal digits */
+ dec = 12345678901234567890LL; /* = 19+ decimal digits */
+
+ /* Stop here and look!
+ */
+ hex = bin - dec | oct;
+}
+
+int main() {
+
+ register long long x, y;
+ register long long i;
+
+ x = (long long) 0xfedcba9876543210LL;
+ y = x++;
+ x +=y;
+ i = 11;
+ x = callee( i );
+ y += x;
+
+ known_types();
+
+ return 0;
+}
+
+
+
diff --git a/gdb/testsuite/gdb.base/long_long.exp b/gdb/testsuite/gdb.base/long_long.exp
new file mode 100644
index 00000000000..aca59c2e546
--- /dev/null
+++ b/gdb/testsuite/gdb.base/long_long.exp
@@ -0,0 +1,163 @@
+# Copyright (C) 1997, 1998 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+
+# long_long.exp Test printing of 64-bit things in 32-bit gdb.
+# Also test differnet kinds of formats.
+#
+if $tracelevel then {
+ strace $tracelevel
+}
+
+set testfile long_long
+set srcfile ${srcdir}/${subdir}/${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+
+# What compiler are we using?
+#
+if [get_compiler_info ${binfile}] {
+ return -1
+}
+
+if {$gcc_compiled == 0} {
+ if [istarget "hppa*-hp-hpux*"] then {
+ ### FIXME +e only works with HP's compiler
+ set additional_flags "additional_flags=+e -w"
+ } else {
+ # don't know what the compiler is, hope it supports long long!
+ set additional_flags "additional_flags=-w"
+ }
+} else {
+ set additional_flags "additional_flags=-w"
+}
+
+if { [gdb_compile "${srcfile}" "${binfile}" executable [list debug $additional_flags]] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+# use this to debug:
+#log_user 1
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+if { ![runto known_types] } then {
+ fail "run to known_types"
+ return
+}
+
+gdb_test "n 4" ".*34.*" "get to known place"
+
+# Check the hack for long long prints.
+#
+gdb_test "p/x hex" ".*0x0.*" "default print hex"
+gdb_test "p/x dec" ".*0xab54a98ceb1f0ad2.*" "default print dec"
+gdb_test "p/x bin" ".*0x123456789abcdef.*" "default print bin"
+gdb_test "p/x oct" ".*0xa72ee53977053977.*" "default print oct"
+
+gdb_test "p/x hex" ".*0x0.*" "hex print"
+gdb_test "p/u dec" ".*12345678901234567890.*" "decimal print"
+gdb_test "p/t bin" ".*100100011010001010110011110001001101010111100110111101111.*" "binary print"
+gdb_test "p/o oct" ".*01234567123456701234567.*" "octal print"
+
+# Try all the combinations to bump up coverage.
+#
+gdb_test "p/d oct" ".*12046818088235383159.*" ""
+gdb_test "p/u oct" ".*0xa72ee53977053977.*" ""
+gdb_test "p/o oct" ".*.*" ""
+gdb_test "p/t oct" ".*1010011100101110111001010011100101110111000001010011100101110111.*" ""
+gdb_test "p/a oct" ".*That operation is not available.*" ""
+gdb_test "p/c oct" ".*0xa72ee53977053977.*" ""
+gdb_test "p/f oct" ".*-5.9822653797615723e-120.*" ""
+
+gdb_test "p/d *(int *)&oct" ".*-1490098887.*" ""
+gdb_test "p/u *(int *)&oct" ".*2804868409.*" ""
+gdb_test "p/o *(int *)&oct" ".*024713562471.*" ""
+gdb_test "p/t *(int *)&oct" ".*10100111001011101110010100111001.*" ""
+gdb_test "p/a *(int *)&oct" ".*0xa72ee539.*" ""
+gdb_test "p/c *(int *)&oct" ".*57 '9'.*" ""
+gdb_test "p/f *(int *)&oct" ".*-2.42716126e-15.*" ""
+
+gdb_test "p/d *(short *)&oct" ".*-22738.*" ""
+gdb_test "p/u *(short *)&oct" ".*42798.*" ""
+gdb_test "p/o *(short *)&oct" ".*0123456.*" ""
+gdb_test "p/t *(short *)&oct" ".*1010011100101110.*" ""
+gdb_test "p/a *(short *)&oct" ".*0xffffa72e.*" ""
+gdb_test "p/c *(short *)&oct" ".* 46 '.'.*" ""
+gdb_test "p/a **short *)&oct" ".*0xffffa72e <.*" ""
+gdb_test "p/f *(short *)&oct" ".*-22738.*" ""
+
+gdb_test "x/x &oct" ".*0xa72ee539.*" ""
+gdb_test "x/d &oct" ".*.-1490098887*" ""
+gdb_test "x/u &oct" ".*2804868409.*" ""
+gdb_test "x/o &oct" ".*024713562471.*" ""
+gdb_test "x/t &oct" ".*10100111001011101110010100111001.*" ""
+gdb_test "x/a &oct" ".*0xa72ee539 <.*" ""
+gdb_test "x/c &oct" ".*-89 'M-''.*" ""
+gdb_test "x/f &oct" ".*-5.9822653797615723e-120.*" ""
+
+gdb_test "x/2x &oct" ".*.*" ""
+gdb_test "x/2d &oct" ".*.*" ""
+gdb_test "x/2u &oct" ".*.*" ""
+gdb_test "x/2o &oct" ".*.*" ""
+gdb_test "x/2t &oct" ".*.*" ""
+gdb_test "x/2a &oct" ".*.*" ""
+gdb_test "x/2c &oct" ".*.*" ""
+gdb_test "x/2f &oct" ".*.*" ""
+
+gdb_test "x/2bx &oct" ".*.*" ""
+gdb_test "x/2bd &oct" ".*.*" ""
+gdb_test "x/2bu &oct" ".*.*" ""
+gdb_test "x/2bo &oct" ".*.*" ""
+gdb_test "x/2bt &oct" ".*.*" ""
+gdb_test "x/2ba &oct" ".*.*" ""
+gdb_test "x/2bc &oct" ".*.*" ""
+gdb_test "x/2bf &oct" ".*.*" ""
+
+gdb_test "x/2hx &oct" ".*.*" ""
+gdb_test "x/2hd &oct" ".*.*" ""
+gdb_test "x/2hu &oct" ".*.*" ""
+gdb_test "x/2ho &oct" ".*.*" ""
+gdb_test "x/2ht &oct" ".*.*" ""
+gdb_test "x/2ha &oct" ".*.*" ""
+gdb_test "x/2hc &oct" ".*.*" ""
+gdb_test "x/2hf &oct" ".*.*" ""
+
+gdb_test "x/2wx &oct" ".*.*" ""
+gdb_test "x/2wd &oct" ".*.*" ""
+gdb_test "x/2wu &oct" ".*.*" ""
+gdb_test "x/2wo &oct" ".*.*" ""
+gdb_test "x/2wt &oct" ".*.*" ""
+gdb_test "x/2wa &oct" ".*.*" ""
+gdb_test "x/2wc &oct" ".*.*" ""
+gdb_test "x/2wf &oct" ".*.*" ""
+
+gdb_test "x/2gx &oct" ".*.*" ""
+gdb_test "x/2gd &oct" ".*.*" ""
+gdb_test "x/2gu &oct" ".*.*" ""
+gdb_test "x/2go &oct" ".*.*" ""
+gdb_test "x/2gt &oct" ".*.*" ""
+gdb_test "x/2ga &oct" ".*.*" ""
+gdb_test "x/2gc &oct" ".*.*" ""
+gdb_test "x/2gf &oct" ".*.*" ""
+
+gdb_exit
+return 0
diff --git a/gdb/testsuite/gdb.base/m32r.ld b/gdb/testsuite/gdb.base/m32r.ld
new file mode 100644
index 00000000000..b96077adb6a
--- /dev/null
+++ b/gdb/testsuite/gdb.base/m32r.ld
@@ -0,0 +1,160 @@
+OUTPUT_FORMAT("elf32-m32r", "elf32-m32r",
+ "elf32-m32r")
+OUTPUT_ARCH(m32r)
+ENTRY(_start)
+ SEARCH_DIR(/usr/cygnus/m32r-961018/H-sparc-sun-sunos4.1//lib);
+/* Do we need any of these for elf?
+ __DYNAMIC = 0; */
+SECTIONS
+{
+ OVERLAY 0x300000 : AT (0x400000)
+ {
+ .ovly0 { foo.o(.text) }
+ .ovly1 { bar.o(.text) }
+ }
+ OVERLAY 0x380000 : AT (0x480000)
+ {
+ .ovly2 { baz.o(.text) }
+ .ovly3 { grbx.o(.text) }
+ }
+ OVERLAY 0x340000 : AT (0x440000)
+ {
+ .data00 { foo.o(.data) }
+ .data01 { bar.o(.data) }
+ }
+ OVERLAY 0x3C0000 : AT (0x4C0000)
+ {
+ .data02 { baz.o(.data) }
+ .data03 { grbx.o(.data) }
+ }
+
+ /* Read-only sections, merged into text segment: */
+ . = 0x208000;
+ .interp : { *(.interp) }
+ .hash : { *(.hash) }
+ .dynsym : { *(.dynsym) }
+ .dynstr : { *(.dynstr) }
+ .rel.text : { *(.rel.text) }
+ .rela.text : { *(.rela.text) }
+ .rel.data : { *(.rel.data) }
+ .rela.data : { *(.rela.data) }
+ .rel.rodata : { *(.rel.rodata) }
+ .rela.rodata : { *(.rela.rodata) }
+ .rel.got : { *(.rel.got) }
+ .rela.got : { *(.rela.got) }
+ .rel.ctors : { *(.rel.ctors) }
+ .rela.ctors : { *(.rela.ctors) }
+ .rel.dtors : { *(.rel.dtors) }
+ .rela.dtors : { *(.rela.dtors) }
+ .rel.init : { *(.rel.init) }
+ .rela.init : { *(.rela.init) }
+ .rel.fini : { *(.rel.fini) }
+ .rela.fini : { *(.rela.fini) }
+ .rel.bss : { *(.rel.bss) }
+ .rela.bss : { *(.rela.bss) }
+ .rel.plt : { *(.rel.plt) }
+ .rela.plt : { *(.rela.plt) }
+ .init : { *(.init) } =0
+ .plt : { *(.plt) }
+ .text :
+ {
+ *(.text)
+ /* .gnu.warning sections are handled specially by elf32.em. */
+ *(.gnu.warning)
+ *(.gnu.linkonce.t*)
+ } =0
+ _etext = .;
+ PROVIDE (etext = .);
+ .fini : { *(.fini) } =0
+ .rodata : { *(.rodata) *(.gnu.linkonce.r*) }
+ .rodata1 : { *(.rodata1) }
+ /* Adjust the address for the data segment. We want to adjust up to
+ the same address within the page on the next page up. */
+ . = ALIGN(32) + (ALIGN(8) & (32 - 1));
+ .data :
+ {
+ *(.data)
+ *(.gnu.linkonce.d*)
+ _ovly_table = .;
+ _ovly0_entry = .;
+ LONG(ABSOLUTE(ADDR(.ovly0)));
+ LONG(SIZEOF(.ovly0));
+ LONG(LOADADDR(.ovly0));
+ LONG(0);
+ _ovly1_entry = .;
+ LONG(ABSOLUTE(ADDR(.ovly1)));
+ LONG(SIZEOF(.ovly1));
+ LONG(LOADADDR(.ovly1));
+ LONG(0);
+ _ovly2_entry = .;
+ LONG(ABSOLUTE(ADDR(.ovly2)));
+ LONG(SIZEOF(.ovly2));
+ LONG(LOADADDR(.ovly2));
+ LONG(0);
+ _ovly3_entry = .;
+ LONG(ABSOLUTE(ADDR(.ovly3)));
+ LONG(SIZEOF(.ovly3));
+ LONG(LOADADDR(.ovly3));
+ LONG(0);
+ _data00_entry = .;
+ LONG(ABSOLUTE(ADDR(.data00)));
+ LONG(SIZEOF(.data00));
+ LONG(LOADADDR(.data00));
+ LONG(0);
+ _data01_entry = .;
+ LONG(ABSOLUTE(ADDR(.data01)));
+ LONG(SIZEOF(.data01));
+ LONG(LOADADDR(.data01));
+ LONG(0);
+ _data02_entry = .;
+ LONG(ABSOLUTE(ADDR(.data02)));
+ LONG(SIZEOF(.data02));
+ LONG(LOADADDR(.data02));
+ LONG(0);
+ _data03_entry = .;
+ LONG(ABSOLUTE(ADDR(.data03)));
+ LONG(SIZEOF(.data03));
+ LONG(LOADADDR(.data03));
+ LONG(0);
+ _novlys = .;
+ LONG((_novlys - _ovly_table) / 16);
+
+ CONSTRUCTORS
+ }
+ .data1 : { *(.data1) }
+ .ctors : { *(.ctors) }
+ .dtors : { *(.dtors) }
+ .got : { *(.got.plt) *(.got)}
+ .dynamic : { *(.dynamic) }
+ /* We want the small data sections together, so single-instruction offsets
+ can access them all, and initialized data all before uninitialized, so
+ we can shorten the on-disk segment size. */
+ .sdata : { *(.sdata) }
+ _edata = .;
+ PROVIDE (edata = .);
+ __bss_start = .;
+ .sbss : { *(.sbss) *(.scommon) }
+ .bss : { *(.dynbss) *(.bss) *(COMMON) }
+ _end = . ;
+ PROVIDE (end = .);
+ /* Stabs debugging sections. */
+ .stab 0 : { *(.stab) }
+ .stabstr 0 : { *(.stabstr) }
+ .stab.excl 0 : { *(.stab.excl) }
+ .stab.exclstr 0 : { *(.stab.exclstr) }
+ .stab.index 0 : { *(.stab.index) }
+ .stab.indexstr 0 : { *(.stab.indexstr) }
+ .comment 0 : { *(.comment) }
+ /* DWARF debug sections.
+ Symbols in the .debug DWARF section are relative to the beginning of the
+ section so we begin .debug at 0. It's not clear yet what needs to happen
+ for the others. */
+ .debug 0 : { *(.debug) }
+ .debug_srcinfo 0 : { *(.debug_srcinfo) }
+ .debug_aranges 0 : { *(.debug_aranges) }
+ .debug_pubnames 0 : { *(.debug_pubnames) }
+ .debug_sfnames 0 : { *(.debug_sfnames) }
+ .line 0 : { *(.line) }
+ .stack 0x5ffffc : { _stack = .; *(.stack) }
+ /* These must appear regardless of . */
+}
diff --git a/gdb/testsuite/gdb.base/m32rovly.c b/gdb/testsuite/gdb.base/m32rovly.c
new file mode 100644
index 00000000000..bdb90feae6b
--- /dev/null
+++ b/gdb/testsuite/gdb.base/m32rovly.c
@@ -0,0 +1,225 @@
+
+/*
+ * Ovlymgr.c -- Runtime Overlay Manager for the GDB testsuite.
+ */
+
+#include "ovlymgr.h"
+
+/* Local functions and data: */
+
+extern unsigned long _ovly_table[][4];
+extern unsigned long _novlys __attribute__ ((section (".data")));
+enum ovly_index { VMA, SIZE, LMA, MAPPED};
+
+static void ovly_copy (unsigned long dst, unsigned long src, long size);
+
+/* Flush the data and instruction caches at address START for SIZE bytes.
+ Support for each new port must be added here. */
+/* FIXME: Might be better to have a standard libgloss function that
+ ports provide that we can then use. Use libgloss instead of newlib
+ since libgloss is the one intended to handle low level system issues.
+ I would suggest something like _flush_cache to avoid the user's namespace
+ but not be completely obscure as other things may need this facility. */
+
+static void
+FlushCache (void)
+{
+#ifdef __M32R__
+ volatile char *mspr = (char *) 0xfffffff7;
+ *mspr = 1;
+#endif
+}
+
+/* OverlayLoad:
+ * Copy the overlay into its runtime region,
+ * and mark the overlay as "mapped".
+ */
+
+bool
+OverlayLoad (unsigned long ovlyno)
+{
+ unsigned long i;
+
+ if (ovlyno < 0 || ovlyno >= _novlys)
+ exit (-1); /* fail, bad ovly number */
+
+ if (_ovly_table[ovlyno][MAPPED])
+ return TRUE; /* this overlay already mapped -- nothing to do! */
+
+ for (i = 0; i < _novlys; i++)
+ if (i == ovlyno)
+ _ovly_table[i][MAPPED] = 1; /* this one now mapped */
+ else if (_ovly_table[i][VMA] == _ovly_table[ovlyno][VMA])
+ _ovly_table[i][MAPPED] = 0; /* this one now un-mapped */
+
+ ovly_copy (_ovly_table[ovlyno][VMA],
+ _ovly_table[ovlyno][LMA],
+ _ovly_table[ovlyno][SIZE]);
+
+ FlushCache ();
+
+ return TRUE;
+}
+
+/* OverlayUnload:
+ * Copy the overlay back into its "load" region.
+ * Does NOT mark overlay as "unmapped", therefore may be called
+ * more than once for the same mapped overlay.
+ */
+
+bool
+OverlayUnload (unsigned long ovlyno)
+{
+ if (ovlyno < 0 || ovlyno >= _novlys)
+ exit (-1); /* fail, bad ovly number */
+
+ if (!_ovly_table[ovlyno][MAPPED])
+ exit (-1); /* error, can't copy out a segment that's not "in" */
+
+ ovly_copy (_ovly_table[ovlyno][LMA],
+ _ovly_table[ovlyno][VMA],
+ _ovly_table[ovlyno][SIZE]);
+
+ return TRUE;
+}
+
+#ifdef __D10V__
+#define IMAP0 (*(short *)(0xff00))
+#define IMAP1 (*(short *)(0xff02))
+#define DMAP (*(short *)(0xff04))
+
+static void
+D10VTranslate (unsigned long logical,
+ short *dmap,
+ unsigned long **addr)
+{
+ unsigned long physical;
+ unsigned long seg;
+ unsigned long off;
+
+ /* to access data, we use the following mapping
+ 0x00xxxxxx: Logical data address segment (DMAP translated memory)
+ 0x01xxxxxx: Logical instruction address segment (IMAP translated memory)
+ 0x10xxxxxx: Physical data memory segment (On-chip data memory)
+ 0x11xxxxxx: Physical instruction memory segment (On-chip insn memory)
+ 0x12xxxxxx: Phisical unified memory segment (Unified memory)
+ */
+
+ /* Addresses must be correctly aligned */
+ if (logical & (sizeof (**addr) - 1))
+ exit (-1);
+
+ /* If the address is in one of the two logical address spaces, it is
+ first translated into a physical address */
+ seg = (logical >> 24);
+ off = (logical & 0xffffffL);
+ switch (seg)
+ {
+ case 0x00: /* in logical data address segment */
+ if (off <= 0x7fffL)
+ physical = (0x10L << 24) + off;
+ else
+ /* Logical address out side of on-chip segment, not
+ supported */
+ exit (-1);
+ break;
+ case 0x01: /* in logical instruction address segment */
+ {
+ short map;
+ if (off <= 0x1ffffL)
+ map = IMAP0;
+ else if (off <= 0x3ffffL)
+ map = IMAP1;
+ else
+ /* Logical address outside of IMAP[01] segment, not
+ supported */
+ exit (-1);
+ if (map & 0x1000L)
+ {
+ /* Instruction memory */
+ physical = (0x11L << 24) | off;
+ }
+ else
+ {
+ /* Unified memory */
+ physical = ((map & 0x7fL) << 17) + (off & 0x1ffffL);
+ if (physical > 0xffffffL)
+ /* Address outside of unified address segment */
+ exit (-1);
+ physical |= (0x12L << 24);
+ }
+ break;
+ }
+ case 0x10:
+ case 0x11:
+ case 0x12:
+ physical = logical;
+ break;
+ default:
+ exit (-1); /* error */
+ }
+
+ seg = (physical >> 24);
+ off = (physical & 0xffffffL);
+ switch (seg)
+ {
+ case 0x10: /* dst is a 15 bit offset into the on-chip memory */
+ *dmap = 0;
+ *addr = (long *) (0x0000 + ((short)off & 0x7fff));
+ break;
+ case 0x11: /* dst is an 18-bit offset into the on-chip
+ instruction memory */
+ *dmap = 0x1000L | ((off & 0x3ffffL) >> 14);
+ *addr = (long *) (0x8000 + ((short)off & 0x3fff));
+ break;
+ case 0x12: /* dst is a 24-bit offset into unified memory */
+ *dmap = off >> 14;
+ *addr = (long *) (0x8000 + ((short)off & 0x3fff));
+ break;
+ default:
+ exit (-1); /* error */
+ }
+}
+#endif /* __D10V__ */
+
+static void
+ovly_copy (unsigned long dst, unsigned long src, long size)
+{
+#ifdef __M32R__
+ memcpy ((void *) dst, (void *) src, size);
+ return;
+#endif /* M32R */
+
+#ifdef __D10V__
+ unsigned long *s, *d, tmp;
+ short dmap_src, dmap_dst;
+ short dmap_save;
+
+ /* all section sizes should by multiples of 4 bytes */
+ dmap_save = DMAP;
+
+ D10VTranslate (src, &dmap_src, &s);
+ D10VTranslate (dst, &dmap_dst, &d);
+
+ while (size > 0)
+ {
+ /* NB: Transfer 4 byte (long) quantites, problems occure
+ when only two bytes are transfered */
+ DMAP = dmap_src;
+ tmp = *s;
+ DMAP = dmap_dst;
+ *d = tmp;
+ d++;
+ s++;
+ size -= sizeof (tmp);
+ src += sizeof (tmp);
+ dst += sizeof (tmp);
+ if ((src & 0x3fff) == 0)
+ D10VTranslate (src, &dmap_src, &s);
+ if ((dst & 0x3fff) == 0)
+ D10VTranslate (dst, &dmap_dst, &d);
+ }
+ DMAP = dmap_save;
+#endif /* D10V */
+}
+
diff --git a/gdb/testsuite/gdb.base/m68k-aout.u b/gdb/testsuite/gdb.base/m68k-aout.u
new file mode 100644
index 00000000000..3095fc0727c
--- /dev/null
+++ b/gdb/testsuite/gdb.base/m68k-aout.u
@@ -0,0 +1,459 @@
+begin 777 m68k-aout
+M !"P $ ! #$@
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M $Y6__!(USB 2^X !$GM 0F3$J<9ORYTV4"68PCS $ 0O.0 $ 0O"R\5
+M8?\ %"WOP #"\ 8?\ -.6(],[CB __!.7DYU3E8 $Y>3G4 $@.
+M $C7 !P & ).7DYU2 X 2-< ' 8 DY>3G5(#@ !(UP
+M< !@ "3EY.=4@. $C7 !P & ).7DYU2 X 2-< ' 8
+M DY>3G5(#@ !(UP < !@ "3EY.=4@. $C7 !"@& ).7DYU
+M2 X 2-< $* 8 DY>3G5(#@ !(UP 0H!@ "3EY.=4@.
+M $C7 !"@& ).7DYU2 X 2-< $* 8 DY>3G5(#@ !(UP
+M0H!@ "3EY.=4@. $C7 #R %P/8 DY>3G5(#@ !(UP \@!<
+M#V ).7DYU2 X 2-< $(Y 0-!/\ $ ! V$_P @ $#@S_ #
+M 0.C/\ 0 ! \,_P !0 $#YP!B/ 00' '(\ !!$< @CP $$AP
+M"2/ 03' *(\ !!0< LCP $%0C_$+( !!8(_Q :0 07"/\
+M $& 3^0 $#0 !!D$_D ! V 09A/Y 0. $&@S^0 $#H
+M !!L,_D ! \ 0<#/Y 0/@ $'0C^0 $$ !!\(_D !!$ 0A"/Y
+M 02 $(PC^0 $$P !"4(_D !!0 0G"/Y 05 $*0C^0 $%@
+M !"L(_D !!< 0M"/Y 08 $+@C_ $#0 !#$(_P ! V 0R"/\
+M 0. $,PC_ $#H !#0(_P ! \ 0U"/\ 0/@ $-@C_ $$
+M !#<(_P !!$ 0X"/\ 02 $.0C_ $$P !#H(_P !!0 0["/\
+M 05 $/ C_ $%@ !#T(_P !!< 0^' "(\ !'4< (CP $=AP
+M 2/ 1X' !(\ !'<(_D !$\ 11#/Y 1+ $31.7DYU0"@C*61B
+M>'AX+G,)-2XR("A"97)K96QE>2D@-R\Q,B\X-0 2'D !'H('D !'D3I!8
+MCTYR"HQ.5@ 8?\ 6+RX "&'_ %%B/3EY.=0 3E8 $Y>3G5.5@
+M< %.0"/ 3Y'#_3EY.=0
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M ! , $YU ! *",I8W)T,"YC"30N-B H0F5R:V5L97DI(#,O,S O
+M.#, !
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M ! 0 &0 "P0 )( !4 $V0 !4 &X
+M /8 3X <H
+MC( IX Q8 WX
+M ^( !"8 !'( !*(
+M !,B $ !/" $ !32 $ !8"
+M ( !:R ( !?2 ( !D2 0 !
+MFB 0 !JB 0 !O" 0 !QB 0
+M !UR 0 !ZB 0 !]2 @ " B $
+M "'2 $ "-2 $ "62 ( "=2
+M ( "CB ( "LR 0 "S2 0 "
+MY" 0 #!R 0 #&" 0 #," 0
+M #2B 0 #9B @ #A" $ #FB $
+M #M" $ #TR ( #ZB ( $!2
+M ( $)2 0 $.B 0 $4R 0 $
+M<2 0 $A" 0 $GB 0 $NB 0
+M $T2 @ $ZH !C___L% %@R !@ %D2 !@
+M &*X C___L% &O" @ &R" @ '6B0
+M $ !4 $0 'D !> ':20 $ !H $0 'H !R '
+M?R0 $ !\ $0 'L "& 'ER0 ( "0 $0 'T ":
+M 'IR0 ( "D $0 'X "N 'OB0 ( "X $0 '\
+M #" 'UR0 0 #, $0 ($ #6 'Y20 0 #@ $0
+M (( #J '^B0 0 #T $0 (, #^ ($20 0 $(
+M $0 (4 $2 (("0 0 $< $0 (8 $F (-B0 0 $P
+M $0 (< $Z (3B0 0 %$ $0 (D %. (7B0 @
+M %: $0 (H %D (<( )C___L% (W" )@ (YX
+M )#___L% ))R ) ),B 0 )5H 3___L% )
+M?2 0 )C" 0 )JH 3___L% )QB 0
+M )U( 3___L% )\H 3___L% *#H 3___L% *&X 3_
+M__L% *2"0 0 %P $0 +( %Z $0 +, %Z $0
+M +0 %Z $0 +4 %Z $0 +8 & $0 +< &(
+M $0 +@ &0 $0 +D &0 $0 +H &8 $0 +L &@
+M $0 +P &H $0 +T &H $0 +X &P $0 +\
+M &X $0 , ' $0 ,$ ' $0 ,( '( $0
+M ,, '0 $0 ,0 '8 $0 ,4 '8 $0 ,8 'B
+M $0 ,< 'V $0 ,@ 'V $0 ,D 'V $0 ,H (
+M $0 ,L (* $0 ,P (4 $0 ,T (4 $0 ,X
+M (> $0 ,\ (H $0 - (R $0 -$ (R $0
+M -( (\ $0 -, )& $0 -0 )0 $0 -4 )0
+M $0 -8 ): $0 -< )D $0 -@ )N $0 -D )N
+M $0 -H )X $0 -L *, $0 -P *, $0 -T
+M *6 $0 -X *@ $0 -\ *J $0 . *J $0
+M .$ *T $0 .( *^ $0 ., +( $0 .0 +(
+M $0 .4 +2 $0 .8 +< $0 .< +F $0 .@ +F
+M $0 .D +P $0 .H +Z $0 .L ,$ $0 .P
+M ,$ $0 .T ,. $0 .X ,8 $0 .\ ,8 $0
+M / ,@ $0 /$ ,H $0 /( ,P $0 /, ,X
+M $0 /0 ,X $0 /4 -" $0 /8 -" $0 /< -,
+M *4 0 /< -0 *5 0 -0 *7 0 .( *8P0 !N(
+M .D *:P0 Y8 .L *<P0 !N( .T *? < !7( ! $ *A04
+M!0X *BP4 WX %P *D04 Z .( *EP4 !BX !* *
+MHP< )( ! ( *J@D !T8 ! T *L@D !^X ! V *P0D !&8 ! X
+M *T@D !YH ! Z *VPD $P ! \ *ZPD =H ! ^ *_0D !_
+M !! +! D "$0 !!$ +$@D !H !!( +(@D ![D !!, +*@D
+M"&$ !!0 +.0D !-D !!4 +2@D !L@ !!8 +4PD !6L !!< +
+M70D !W, !!D +:PD !ET !!F +@ D !&D !!H +EPD ID !!L
+M +I@D &T !!P +O D !2, !!T +U D !MT !!\ +X0D @,
+M !"$ +]0D 0D !", ,"PD ;L !"4 ,&0D *4 !"< ,+@D
+M!T\ !"D ,10D <T !"L ,5 D +D !"T ,9 D "%( !#$ ,
+M= D _H !#( ,BPD !,@ !#, ,I D !B8 !#0 ,M0D !A0 !#4
+M ,S0D !ZP !#8 ,YPD !?H !#< ,]@D \X !#@ -# D "(0
+M !#D -) D JX !#H -- D !O0 !#L -2PD !\( !#P -9 D
+M O8 !#T -=0D !T0 !#X -APD !RL !#\ -D@D !RP !$4 -
+MG0D !\8 !$L -I@D !R !$T -L 4 ZL !4 -O04 !V\ !H
+M -T04 !G4 !\ -YP4 !8T "0 -]04 !'< "D ."@4 H,
+M "X .(04 !Z\ #, .+04 /, #@ .0 4 !,4 #T .504
+M ,\ $( .8@4 !), $< .=@4 YD $P .C 4 !2< %$ .
+MF@4 !)T %: .J0D !T4 !$\ .L0D !X4 !%$ .N0D !\\ !'4
+M .P@D G< !'8 .S@D !)X !'< .UPD O@ !'@ .X@D 2<
+M !'D .ZP4 :D -T .] 4 ;0 .$ ._0< !,8 ! P /!P4
+M Y8 .D /$04 !N( .L /& 4 "!P .T /'PD !Y< !/D /
+M)F-R=# N;P!G9&)M92YO &=D8FUE+F, :6YT.G0Q/7(Q.RTR,30W-#@S-C0X
+M.S(Q-#<T.#,V-#<[ &-H87(Z=#(]<C([,#LQ,C<[ &QO;F<Z=#,]<C$[+3(Q
+M-#<T.#,V-#@[,C$T-S0X,S8T-SL <VAO<G0Z=#0]<C$[+3,R-S8X.S,R-S8W
+M.P!U;G-I9VYE9"!C:&%R.G0U/7(Q.S [,C4U.P!U;G-I9VYE9"!S:&]R=#IT
+M-CUR,3LP.S8U-3,U.P!U;G-I9VYE9"!L;VYG.G0W/7(Q.S [+3$[ '5N<VEG
+M;F5D(&EN=#IT.#UR,3LP.RTQ.P!F;&]A=#IT.3UR,3LT.S [ &1O=6)L93IT
+M,3 ]<C$[.#LP.P!V;VED.G0Q,3TQ,0 _/S\Z=#$R/3$ =E]C:&%R.D<R '9?
+M<VEG;F5D7V-H87(Z1S( =E]U;G-I9VYE9%]C:&%R.D<U '9?<VAO<G0Z1S0
+M=E]S:6=N961?<VAO<G0Z1S0 =E]U;G-I9VYE9%]S:&]R=#I'-@!V7VEN=#I'
+M,0!V7W-I9VYE9%]I;G0Z1S$ =E]U;G-I9VYE9%]I;G0Z1S@ =E]L;VYG.D<Q
+M '9?<VEG;F5D7VQO;F<Z1S$ =E]U;G-I9VYE9%]L;VYG.D<X '9?9FQO870Z
+M1SD =E]D;W5B;&4Z1S$P '9?8VAA<E]A<G)A>3I',3,]87(Q.S [,3LR '9?
+M<VEG;F5D7V-H87)?87)R87DZ1S$S '9?=6YS:6=N961?8VAA<E]A<G)A>3I'
+M,30]87(Q.S [,3LU '9?<VAO<G1?87)R87DZ1S$U/6%R,3LP.S$[- !V7W-I
+M9VYE9%]S:&]R=%]A<G)A>3I',34 =E]U;G-I9VYE9%]S:&]R=%]A<G)A>3I'
+M,38]87(Q.S [,3LV '9?:6YT7V%R<F%Y.D<Q-SUA<C$[,#LQ.S$ =E]S:6=N
+M961?:6YT7V%R<F%Y.D<Q-P!V7W5N<VEG;F5D7VEN=%]A<G)A>3I',3@]87(Q
+M.S [,3LX '9?;&]N9U]A<G)A>3I',3< =E]S:6=N961?;&]N9U]A<G)A>3I'
+M,3< =E]U;G-I9VYE9%]L;VYG7V%R<F%Y.D<Q. !V7V9L;V%T7V%R<F%Y.D<Q
+M.3UA<C$[,#LQ.SD =E]D;W5B;&5?87)R87DZ1S(P/6%R,3LP.S$[,3 =E]C
+M:&%R7W!O:6YT97(Z1S(Q/2HR '9?<VEG;F5D7V-H87)?<&]I;G1E<CI',C$
+M=E]U;G-I9VYE9%]C:&%R7W!O:6YT97(Z1S(R/2HU '9?<VAO<G1?<&]I;G1E
+M<CI',C,]*C0 =E]S:6=N961?<VAO<G1?<&]I;G1E<CI',C, =E]U;G-I9VYE
+M9%]S:&]R=%]P;VEN=&5R.D<R-#TJ-@!V7VEN=%]P;VEN=&5R.D<R-3TJ,0!V
+M7W-I9VYE9%]I;G1?<&]I;G1E<CI',C4 =E]U;G-I9VYE9%]I;G1?<&]I;G1E
+M<CI',C8]*C@ =E]L;VYG7W!O:6YT97(Z1S(U '9?<VEG;F5D7VQO;F=?<&]I
+M;G1E<CI',C4 =E]U;G-I9VYE9%]L;VYG7W!O:6YT97(Z1S(V '9?9FQO871?
+M<&]I;G1E<CI',C<]*CD =E]D;W5B;&5?<&]I;G1E<CI',C@]*C$P '1?<W1R
+M=6-T.E0R.3US,C1V7V-H87)?;65M8F5R.C(L,"PX.W9?<VAO<G1?;65M8F5R
+M.C0L,38L,38[=E]I;G1?;65M8F5R.C$L,S(L,S([=E]L;VYG7VUE;6)E<CHQ
+M+#8T+#,R.W9?9FQO871?;65M8F5R.CDL.38L,S([=E]D;W5B;&5?;65M8F5R
+M.C$P+#$R."PV-#L[ '9?<W1R=6-T,3I',CD =E]S=')U8W0R.D<S,#US,C1V
+M7V-H87)?;65M8F5R.C(L,"PX.W9?<VAO<G1?;65M8F5R.C0L,38L,38[=E]I
+M;G1?;65M8F5R.C$L,S(L,S([=E]L;VYG7VUE;6)E<CHQ+#8T+#,R.W9?9FQO
+M871?;65M8F5R.CDL.38L,S([=E]D;W5B;&5?;65M8F5R.C$P+#$R."PV-#L[
+M '1?=6YI;VXZ5#,Q/74X=E]C:&%R7VUE;6)E<CHR+# L.#MV7W-H;W)T7VUE
+M;6)E<CHT+# L,38[=E]I;G1?;65M8F5R.C$L,"PS,CMV7VQO;F=?;65M8F5R
+M.C$L,"PS,CMV7V9L;V%T7VUE;6)E<CHY+# L,S([=E]D;W5B;&5?;65M8F5R
+M.C$P+# L-C0[.P!V7W5N:6]N.D<S,0!V7W5N:6]N,CI',S(]=3AV7V-H87)?
+M;65M8F5R.C(L,"PX.W9?<VAO<G1?;65M8F5R.C0L,"PQ-CMV7VEN=%]M96UB
+M97(Z,2PP+#,R.W9?;&]N9U]M96UB97(Z,2PP+#,R.W9?9FQO871?;65M8F5R
+M.CDL,"PS,CMV7V1O=6)L95]M96UB97(Z,3 L,"PV-#L[ '9?8VAA<E]F=6YC
+M.D8R '9?<VEG;F5D7V-H87)?9G5N8SI&,@!V7W5N<VEG;F5D7V-H87)?9G5N
+M8SI&-0!V7W-H;W)T7V9U;F,Z1C0 =E]S:6=N961?<VAO<G1?9G5N8SI&- !V
+M7W5N<VEG;F5D7W-H;W)T7V9U;F,Z1C8 =E]I;G1?9G5N8SI&,0!V7W-I9VYE
+M9%]I;G1?9G5N8SI&,0!V7W5N<VEG;F5D7VEN=%]F=6YC.D8X '9?;&]N9U]F
+M=6YC.D8Q '9?<VEG;F5D7VQO;F=?9G5N8SI&,0!V7W5N<VEG;F5D7VQO;F=?
+M9G5N8SI&. !V7V9L;V%T7V9U;F,Z1CD =E]D;W5B;&5?9G5N8SI&,3 ;&EN
+M:SI4,S,]<S$U,FYE>'0Z,S0]*C,S+# L,S([;&EN:V9U;F,Z,S4]*C,V/68S
+M-"PS,BPS,CMS='5F9CHS-SUA<C$[,#LP.S,X/6%R,3LP.S$[,SD]87(Q.S [
+M,CLR.2PV-"PQ,34R.SL <U]L:6YK.D<S- !T=5]L:6YK.E0T,#UU,30T;F5X
+M=#HS-"PP+#,R.VQI;FMF=6YC.C,U+# L,S([<W1U9F8Z,S<L,"PQ,34R.SL
+M=5]L:6YK.D<T, !P<FEM87)Y.D<T,3UE<F5D.C L9W)E96XZ,2QB;'5E.C(L
+M.P!C;VQO<G,Z5#0R/65Y96QL;W<Z,"QP=7)P;&4Z,2QP:6YK.C(L.P!N;VYP
+M<FEM87)Y.D<T,@!C;'5N:V5R.D<T,SUE8VAE=GDZ,"QF;W)D.C$L.P!C87)S
+M.E0T-#UE8FUW.C L<&]R<V-H93HQ+#L <W!O<G1S8V%R.D<T- !B;V]L96%N
+M.G0T-3UE1D%,4T4Z,"Q44E5%.C$L.P!B=F%L<SI4-#8]969A;'-E.C L=')U
+M93HQ+#L 8F]O;&5A;C(Z=#0V &UI<V]R9&5R960Z5#0W/65T=V\Z,BQO;F4Z
+M,2QZ97)O.C L=&AR964Z,RP[ &UA:6XZ1C$ +6QG %]S8V-S:60 97AI="YO
+M &9A:V-U+F\ 7V5X:70N;P!C97)R;W(N;P!?96YV:7)O;@!S=&%R= !?;6%I
+M;@!?97AI= !?;6]N8V]N=')O; !M8V]U;G0 7W9?8VAA<@!?=E]S:6=N961?
+M8VAA<@!?=E]U;G-I9VYE9%]C:&%R %]V7W-H;W)T %]V7W-I9VYE9%]S:&]R
+M= !?=E]U;G-I9VYE9%]S:&]R= !?=E]I;G0 7W9?<VEG;F5D7VEN= !?=E]U
+M;G-I9VYE9%]I;G0 7W9?;&]N9P!?=E]S:6=N961?;&]N9P!?=E]U;G-I9VYE
+M9%]L;VYG %]V7V9L;V%T %]V7V1O=6)L90!?=E]C:&%R7V%R<F%Y %]V7W-I
+M9VYE9%]C:&%R7V%R<F%Y %]V7W5N<VEG;F5D7V-H87)?87)R87D 7W9?<VAO
+M<G1?87)R87D 7W9?<VEG;F5D7W-H;W)T7V%R<F%Y %]V7W5N<VEG;F5D7W-H
+M;W)T7V%R<F%Y %]V7VEN=%]A<G)A>0!?=E]S:6=N961?:6YT7V%R<F%Y %]V
+M7W5N<VEG;F5D7VEN=%]A<G)A>0!?=E]L;VYG7V%R<F%Y %]V7W-I9VYE9%]L
+M;VYG7V%R<F%Y %]V7W5N<VEG;F5D7VQO;F=?87)R87D 7W9?9FQO871?87)R
+M87D 7W9?9&]U8FQE7V%R<F%Y %]V7V-H87)?<&]I;G1E<@!?=E]S:6=N961?
+M8VAA<E]P;VEN=&5R %]V7W5N<VEG;F5D7V-H87)?<&]I;G1E<@!?=E]S:&]R
+M=%]P;VEN=&5R %]V7W-I9VYE9%]S:&]R=%]P;VEN=&5R %]V7W5N<VEG;F5D
+M7W-H;W)T7W!O:6YT97( 7W9?:6YT7W!O:6YT97( 7W9?<VEG;F5D7VEN=%]P
+M;VEN=&5R %]V7W5N<VEG;F5D7VEN=%]P;VEN=&5R %]V7VQO;F=?<&]I;G1E
+M<@!?=E]S:6=N961?;&]N9U]P;VEN=&5R %]V7W5N<VEG;F5D7VQO;F=?<&]I
+M;G1E<@!?=E]F;&]A=%]P;VEN=&5R %]V7V1O=6)L95]P;VEN=&5R %]V7W-T
+M<G5C=#$ 7W9?<W1R=6-T,@!?=E]U;FEO;@!?=E]U;FEO;C( 7W9?8VAA<E]F
+M=6YC %]V7W-I9VYE9%]C:&%R7V9U;F, 7W9?=6YS:6=N961?8VAA<E]F=6YC
+M %]V7W-H;W)T7V9U;F, 7W9?<VEG;F5D7W-H;W)T7V9U;F, 7W9?=6YS:6=N
+M961?<VAO<G1?9G5N8P!?=E]I;G1?9G5N8P!?=E]S:6=N961?:6YT7V9U;F,
+M7W9?=6YS:6=N961?:6YT7V9U;F, 7W9?;&]N9U]F=6YC %]V7W-I9VYE9%]L
+M;VYG7V9U;F, 7W9?=6YS:6=N961?;&]N9U]F=6YC %]V7V9L;V%T7V9U;F,
+M7W9?9&]U8FQE7V9U;F, 7W-?;&EN:P!?=5]L:6YK %]P<FEM87)Y %]N;VYP
+M<FEM87)Y %]C;'5N:V5R %]S<&]R='-C87( 7U]D8F%R9W, 7U]D8G-U8F,
+M7U]D8G-U8FX 7U]L9U]F;&%G %]?8VQE86YU< !?7V5X:70 8V5R<F]R %]E
+M<G)N;P
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+%
+
+end
diff --git a/gdb/testsuite/gdb.base/m68k-aout2.u b/gdb/testsuite/gdb.base/m68k-aout2.u
new file mode 100644
index 00000000000..b9209610c25
--- /dev/null
+++ b/gdb/testsuite/gdb.base/m68k-aout2.u
@@ -0,0 +1,2208 @@
+begin 777 m68k-aout2
+M 0(!"P @ , 'B0 " @ !-^ )!='[P $(@+E
+M@4GS& 0CS " !*N0 (@9G &80 *DA42%,O DZY BF$ZY C9M[\
+M PO $ZY F0%B/+P!.N0 )MA.5O_(2.<P $AZ :Q(> 2'H!BDZZ 3;?
+M_ @M0/_P2'@ ($AN_\@O $ZZ 3S?_ ! ,@ "!G"$'Z 79@ $T
+M#&X!"__*9O D/ '__4KO_, H+__@ !H( @ ( +0KO_0T*[_U$AZ 6)(
+M> +R[_\"\Z 9@O.@&@+P!(> 3KH S-_\ &"U _^@O+O_,+R[_\"\Z
+M 7@O.@%X+R[_T" "T*[_Z"\ 3KH HM_\ &"8 E*[_S"\"("[_Z-"N_\PO
+M $ZZ )#?_ Q(>@$B2'@ $AZ ,E.N@!F4(\M0/_L2J[_U&8$6(]@(DAX
+M O "\Z 1@O.@$8+R[_U-:N_] O TZZ $3?_ !Q!^O[(+4C__"UY (
+M /_X+7H ;/_T2&[_Z$AX $@;O_HT>[_W$Z04(],WP ,3EY.=2!O Q(> %
+M8!P@;P <2'@ 1V 2(&\ #$AX $E@""!O !!(> #3D!E DYU+QA(4$AX )(
+M> 2'@ !$Y +WP !_ 1(> !3D +W5S<B]L:6(O;&0N<V\ +V1E
+M=B]Z97)O 88W)T,#H@;F\@+W5S<B]L:6(O;&0N<V\* )6-R=# Z
+M("]U<W(O;&EB+VQD+G-O(&UA<'!I;F<@9F%I;'5R90H $V-R=# Z(&YO
+M("]D978O>F5R;PH @ H !( ' !0 $[Y ER 3E8
+M $* 8 DY>3G5.5@ 0H!@ "3EY.=4Y6 !"@& ).7DYU3E8 $*
+M8 DY>3G5.5@ 0H!@ "3EY.=4Y6 !"@& ).7DYU3E8 $* 8
+M DY>3G5.5@ 0H!@ "3EY.=4Y6 !"@& ).7DYU3E8 $* 8 DY>
+M3G5.5@ 0H!@ "3EY.=4Y6 !"@& ).7DYU3E8 ' 8 DY>3G5.
+M5@ < !R & ).7DYU3E8 &'_ "0D(Y *P4!/\ $ K!2$_P @ "
+ML%0S_ # *P5C/\ 0 K!8,_P !0 "L%IP!B/ *P7' '(\ K!@< @C
+MP "L&1P"2/ *P:' *(\ K!L< LCP "L' C_$+( K!T(_Q :0
+M *P>$*Y *P?!/Y *P4 "L( 3^0 "L%( K""$_D K!4 *PA#/Y *P
+M5@ "L(@S^0 "L%@ K",,_D K!: *PD"/Y *P7 "L)@C^0 "L& K"@
+M(_D K!D *PJ"/Y *P: "L+ C^0 "L&P K"X(_D K!P *PP"/Y *P
+M= "L,@C^0 "L'@ K#0(_D K!\ *PU"/\ *P4 "L. C_ "L%( K#D
+M(_P K!4 *PZ"/\ *P5@ "L.PC_ "L%@ K#P(_P K!: *P]"/\ *P
+M7 "L/@C_ "L& K#\(_P K!D *Q "/\ *P: "L00C_ "L&P K$(
+M(_P K!P *Q#"/\ *P= "L1 C_ "L'@ K$4< (CP "L1@CP "L1QP
+M 2/ *Q("/ *Q)"/Y *Q* "L3 S^0 "L< K'(3EY.=0 3E8 "\+
+M+PI"@$'Y *R#$J09PA82%* 2I!F^$J ;Q1'^0 "L@A%\PP (%).D%E*M\IM
+M]B1N__@F;O_\3EY.=4Y6 O"D7Y *R%$J29P@@6DZ02I)F^$*G2'D "5
+M8?\ #F)&[__$Y>3G5.5@ 2KD @ \9@IP 2/ ( /&&\3EY.=4CG@,!.
+MN0 *\A*0&<,3KD "MH3-\# 4YU2'@ /4AZ !9(> "3KD ";.2'@ 8TZY
+M FV$U#-C@X.#$@9FQO871I;F<@<&]I;G0@;F]T(&%V86EL86)L92 M+2!P
+M<F]G<F%M(')E<75I<F5S(&ET"@ $Y6__A(UR" +BX "& 4(^T " "
+MLA@O+0 $+P<@54Z04$\J>0 "LAA*C6;B3KD ";P+P=.N0 )MA83TSN((#_
+M^$Y>3G4 $Y6__PNC4AX Q.N0 +PA83RI 2HUF!'#_8!HJK@ (*VX # $
+M*WD K(8 @CS0 "LAAP "IN__Q.7DYU !.^0 )N!(> $3D!E\DYU2'@
+M 4Y CP " $1P_TYU 3E8 $AY G!DZY W(%A/3EY.=4Y6
+M__A(UR" *FX "'[_2HUG<# M ! "@ 0-G.C M ! ( &9C P+0 0"
+M F<$?@!@#$A53KD ">46$\N ! M !))P"\ 3KD #AV6$]*@&P"?O\P+0 0
+M" V<0+RT "$ZY P'EA/0JT "$)M !!"E2MM @ !$*M P@!TSN((#_
+M^$Y>3G5.5O_\+HTJ;@ (,"T $ @ %F)F \,"T $ @ %G)$JM AG'B M
+M 2PK0 (8Q1(54ZY I8EA/,"T $ @ )GTC M ! ( %9P1P_V "< J
+M;O_\3EY.=4Y6_^Q(UR# *FX #!PN LP+0 0 H "2#( ""9CP@+0 (
+MT*T #+"M 1C "\(&T !%)(*T@ !!%&__\,!@ *9@ !'DA53KD "EB6$]^
+M_["'9@ !#& 00P+0 0?A; AWX&L(=F,!U&__]"E4AX %(;O__$"T $DG
+M+P!.N0 )LY^ ;"'9P U@!M " $'#_8 SC M !!^$L"'?@*PAV8@2JT
+M"&<:("T !+"M AF)$J59B P+0 0 H "$9A1(54ZY IYEA/2H!G!G#_
+M8 C# M ! "@ (1F /\F2%5.N0 *6)83U.5;1 @;0 $4D@K2 $$4;_
+M_V!,,"T $ @ =G,B 51("PK0 ,;"@@;0 $$(8,!@ *9Q @;0 $4D@K2 $
+M$"C__V <2%4@;0 $< 0$& &2%5P ! &+P!.N0 )_!03S M ! ( %9P1P
+M_V $< 0!DSN(,#_[$Y>3G5.5O_P2-<PP"IN @H;0 (+"T !)R,*TP !# M
+M ! "@ (1G!'X 8 0N+0 ,*H=*E6P$?@!@ BX5("T "-"M R0K0 $L(=L
+M"DA53KD "M 6$]*AF\@+P9(5! M !))P"\ 3KD ";.O(!G"@!M " $'#_
+M8 )P $SN,,#_\$Y>3G5.5O_X2-<@@"IN @P+0 0?A+ AWX"L(=G'C M ! "
+M@ 0)F!'#_8&AP[\!M !!R H!!.T $# M ! ( &9DY*K0 (9@I(54ZY
+M J@EA/("T !+"M AF-# M ! "@ (1F*"JM Q*E6P$?@!@ BX5("T
+M"-"M R0K0 $L(=L"DA53KD "M 6$]P $SN((#_^$Y>3G5.5O^T2-<@P"IN
+M @0+0 22< L # M ! ( "9Q8@>0 " I1!\&X *T@ "'X(*T< #&!Z+P9.
+MN0 -7!83TJ 9PX ;0" ! N/ (!@'DAN_\0O!DZY XAE!/2H!M!BXN
+M__!N!BX\ $ " '4( O $ZY O"%A/*T "&<, &T " 0*T< #& @('D
+M @*40?!N "M( A^""M' P";?]_ ! ;0 $ ! K;0 ( 1,[B# _[1.7DYU
+M3E;_]")N @@:0 (T>D #" (D*D !&H&(T@ !& &L)%L B* 3EY.=4CGP, @
+M.0 " $P,0 $9@8P/ 28"0,0 #9@8P/ .8!@,0 "9@8P/ *8 P,0 !
+M9@8P/ &3G%!^0 "JZQ@!B-Q B)8L_P 9O!.0DS? P-.=0
+M $[Y KZ 3E8 '(!(\$ K(<(&X $%RH Q.7DYU3E;_Y"Z'2KD @!8
+M9QH,N0 ( @!89@ Q'X#(\< @!,8 N"U\ KT/_T0J[_^$*N__Q(
+M;O_H2&[_]$AX =.N0 -Z!/[P ,0KD K(<3KD #H82&[_]$AN_^A(> '
+M3KD #>@3^\ #$JY *R'&<$?@%@ GX"(\< @!8#+D " ( 6&9.?@,C
+MQP " $Q.N0 .C!*@&8V2'D "S@2'D @+$3KD #EP4$](>0 +2!(>0 "
+M L1.N0 .7!03TAY ("Q$ZY GE%A/3KD #H8#+D " ( 6&8$< %@
+M G +B[_Y$Y>3G4*(%!L96%S92!N;W1E.B!-0S8X.#@Q('5P9W)A9&4@=&\@
+M03DS3B!M87-K(&UA>2!B92!A9'9I<V%B;&4N( H 4V5E($9L;V%T:6YG+5!O
+M:6YT(%!R;V=R86UM97(G<R!'=6ED92X* $Y6_^Q(US#@*'P @"P*E0J+@ ,
+M+"X "& 0O*T "&0$*$U@!$GM 0J5$J-9@1^ & $+BT #+Z%9.!.N0 -(0N
+M &=$*(<@1T*00J@ !"%& @A10 ,($8@A2A'6(=*C6<>O*T "&,,*(U)[0 $
+M*FT !& (($<@C2X-*E5*C6;BF\T@1R"-*(U,[C#@_^Q.7DYU3E;_Z$C7,/ J
+M;@ (*%4L%&8$> !@!B!&*"@ #"XL 1F!'H 8 8@1RHH R\AV=TN(5E.$J&
+M9VA*A&8:($8@* (6( O $AY ( \$ZY U7%!/8$XJAEB&*D8L%68$> !@
+M/"!&*"@ #& T2H=G,$J%9AH@1R H A8@"\ 2'D @$$3KD #5<4$]@%BJ'
+M*D<N%68$>@!@!B!'*B@ #+R'9HQ"E4A43KD #5"6$],[C#P_^A.7DYU3E;_
+MY$C7,( J;@ ((%5*B&8$< !@!" H PH4")H 1*C&8$?@!@)BXL Q@(+Z!
+M918JC$OL 0H54J,9@1^ & 8+BP #& 2*HDJ22)52HEF!'( 8 0B*0 ,OH!B
+MT+* 8LPJB"",(4D !$SN,(#_Y$Y>3G5.5O_D2-<P^"@N A8A'X(N(=D!'@(
+M8 96A.2,Y8Q*N0 " +!F!'H 8 H@>0 " + J* ,NH1D%"\$3KD #/(6$]*
+M@&8&< !@ #"*'P @"P*E1@(+Z&8@R^A&042>T !"I#8!"\A&4(2>T !"I#
+M8 0H32I%*A4F+0 $2H5F!'X 8 8@12XH Q*@V8$? !@!B!#+"@ #+Z$9+J\
+MA&2V("T #)"$?@BPAV(0*BT "$A43KD "W:6$]@+BHM @N!=Z$($4F$):$
+M*T, #"!'((-2N0 " '0K1P (2%1.N0 +I183R!%((0@12 0T;D @"D4KD
+M @"HN+D @"89 92N0 " 'A8A2 %3.XP^/_D3EY.=4Y6_^!(US#\)"X "! "
+M?@/ AV<6+P)(>0 " 1A.N0 -5Q03W 8 \+2Y ( M&4(M+D @"X8PY^
+M%B/' ( 1' 8 TBP"688@1B@0F;D @"D4[D @"H*'P @"P*E1*C6<
+M *(N+0 ()BT #+R'9#@J!MJ$NH=F%-B#4[D @!T2%1.N0 +=I83V!PNH=C
+M%"\'+P9(>0 " 5=.N0 -5QP &!N*$U@5+R'8SPJ!]J#NH9F%BP'V(-3N0 "
+M '1(5$ZY MVEA/8#*ZAF,4+P)(>0 " 79.N0 -5Q03W 8#!)[0 $8!0O
+M DAY (!F$ZY U7%!/< !@%BI42HUF /]B+P0O!DZY M2%!/< %,[C#\
+M_^!.7DYU3E;_\$C7,, H;@ (+"X $"XN R>AG((OH%E($OT: JARB&4KD
+M @!T4KD @"H2&T !$ZY P'EA/6$P@#$SN,,#_\$Y>3G5.5O_@2-<X^"IN
+M @@#7X#P(=F$+OY ( M&4(N_D @"X8Q9(54AY (!NDZY U7%!/< !@
+M #T1^W__"@30?-( "P(2'@ 2\$2%-.N0 ,L!/[P ,?O^PAV8&< !@ #*
+M+BX #%B'>@B^A60$=@A@"%:'Y(_ECR8'N(-E$"\#+P1(4TZY Q0& )Z\
+MN0 " +AD8BA\ ( L"I4($8J$& *2>T !& "*$TJ5$J-9@1^ & $+BT #+Z%
+M93HN+0 (O(=EY+R'8MHN!-Z%OH-E)DA43KD "W:6$]3N0 " '3;N0 " *0F
+MAR\#+P=(4TZY Q0& R+RX #$ZY O"%A/*D!*C6<>6$M9A"\$2%5(4TZY
+M ]"$_O Q(4TZY P'EA/( U,[CCX_^!.7DYU3E;_Y$C7/. J+@ ,+"X
+M""1&U<4F? " +!@""9-8 1'[0 $*E-*C68$?@!@!"XM R^A64 ,8H;0 (
+MO(QF'$A33KD "W:6$_;N0 " *12N0 " *AP 6 *2\C&6\+@S>E+R'9+BU
+MQV,:2JX $&<0+P9(>0 " D=.N0 -5Q03W#_8'BUQV8N2%-.N0 +=I83U*Y
+M ( =-NY ( I%2Y ( J)N42&P !$ZY P'EA/< %@1DA33KD "W:6$]4
+MN0 " '0@%-&Y ( I%:Y ( J" 'D(:1E)Z*)(=(; $3KD # >6$](:@ $
+M3KD # >6$]P 6 "< !,[CS@_^1.7DYU3E;_]$C7(,!*N0 " &QF(DZY X
+MIB/ ( ;$ZY TA"I 2HUG.DA53KD #5"6$\N.0 " &Q3A]ZN A,>7 '
+M ( ;$PY< < @!L+ <O!DZY XX%A/*D!R_[O!9@1P &!,2KD @"T9@8C
+MS0 " +1!]6@ (\@ @"X*H<@.0 " +B0N0 " +0CP " '#?N0 " *12N0 "
+M '12N0 " *A(;0 $3KD # >6$]P 4SN(,#_]$Y>3G5.5O_X2-<@@$JY (
+MQ&<6*GD @#$('D @#$(] @#$8 CDJY ( P&YP+CP " $+P=.N0
+M..!83RI <O^P@6822'D @)Y3KD #5<6$]P &!<2KD @"T9@8CS0 " +0J
+MAT'M 0CR " +PC_ @ @# 0?5X "/( ( N" Y ( N)"Y ( M"/
+M ( <-^Y ( K%.Y ( P"IY ( O'X0W[D @"\( U,[B" __A.7DYU3E8
+M "!N @@N0 " ,0C[@ ( ( Q$Y>3G5.5@ <A8CP0 " $1.7DYU $Y6
+M_^@NARXY ( 1$AN_^Q(>4 25 $O+@ (3KD #BV2H!L"B/' ( 1' 8 )P
+M 2XN_^A.7DYU3E;__"Z-2KD JZL9C@J? " IPP+0 0 H $#9@0@#6!H
+M2^T %+O\ (%'&7D3KD #8\2H!F#'(,(\$ @!$< !@1BIY *NK$J59R0@
+M53 H ! "@ 0-G%EA-N_D JZP9>1R&"/! ( 1' 8!A*E6822'@ %$AX
+M %.N0 /9!03RJ (!4J;O_\3EY.=4Y6__A(UR" 3KD #B6+@!(> $+P=.
+MN0 /9!03R/ *NK$JY *NK&8$< !@7" 'YX O $ZY O"%A/(\ @*4
+M9A@O.0 "KJQ.N0 ,!Y83T*Y *NK' 8"X@>0 "KJQ!\'P (\@ JZP+CP
+M @*<*GD JZL8 8JQW(4WH$,AP "!1QE\G !3.X@@/_X3EY.=4Y6__PNC4JY
+M *NK&8*3KD #8\2H!G+BIY *NK+OY *NL&0@2I5F$DAX !1(> !3KD
+M #V04$\J@%A-N_D JZP9> J;O_\3EY.=4Y6__PNC4JN AG9DJY *NK&8J
+M*GP @*<,"T $ * ! V<*2%4@;@ (3I!83TOM !2[_ "!1QD-F#<*GD
+M JZLN_D JZP9"9*E6<8(%4P* 0 H $#9PHO%2!N A.D%A/6$V[^0 "
+MKK!EVBIN__Q.7DYU 3E;_V$C7/. N+@ (;P9\(+Z&;09^%F *8D
+M;@ 0+"X #" '4X!R >&A+P%.N0 .,983RH 2_D K(@2_5\ "952%(O!B\'
+M3KD #EF3^\ #$J :U9*AF<V0>[_]")&(-D@V2#92>[_]"P49PYR ;R!9P@J
+MABB\ Y&$*G2%0O!TZY Y9D_O Q*@&L<2HIG"@R2 Y&&8")(LO!4ZY
+M XUEA/< !@&BXY ( 1"\%3KD #C66$\JBR/' ( 1'#_3.X\X/_83EY.
+M=4[Y FX$AX 9.0&7R3G5.^0 )N!(> ^3D!E\DYU3OD ";@2'@ 64Y
+M9?).=4[Y FX$AX $!.0&7R3G5.^0 )N!(> V3D!E\DYU3OD ";@2'@
+M;4Y 9?).=4[Y FX$AX &Y.0&7R3G4@+P $5H!R_,"!T+D @4<+T !$AX
+M !%.0&40(#D @4<(^\ ! "!1Q.=4[Y FX $CGP,!.N0 .G @
+M+P$0Y8@@? "LB @< @ +R\!'"\O 1PO+P$<+R\!'$Z0W_P 03KD #JX
+M3-\# ]_\ "$AX (M.0$[Y FX$AX &Q.0&7R3G5.5OOX2-<@@"IN A!
+M[@ 0+@@P+0 0" 686,"T $ @ AG" !M ( $& $</]@:C M ! ( "
+M9TX";?_[ !!![OP *T@ "$'N_ K2 $*WP 0 Q(52\'+RX #$ZY ]
+MX$_O PN $A53KD ">46$\ ;0 $ !!"K0 (0JT #$*58!!(52\'+RX #$ZY
+M ]X"X ( =,[B" ^_A.7DYU #R.IP 1.=0 #R
+M.E04 "CR &0 #( E@ 9A;R.E0 ![R &0 #( @ 9@1P 6 "0H!.=3_P
+M !. ____X G_P #\+R\ _$'O 0@* $0(, ,0 (9RP@
+M.0 " $P@P Q 1F"$ZY [YF 6#$ V8(3KD #KZ8 @,0 "9@)A6DYU
+M0>\ !" 8#$ "&<J(!@,0 $9@A.N0 /&!@&@Q -F"$ZY [!F ,#$
+M F8&3KD #MV+U<! -_\ ! $YU\A#PP/(HO &$YU\AC0P/(0G !.=2)Y
+M (%U# I__X( .9P@Q?!!C "!@(DII__YJZ$AH " O/$ " O.0 "LJ!.
+MN0 .+;?_ PS?!!C__PS?!! __P@D2%1 0A40 ((5$ #"%1 ! A40 4
+M(5$ &"%1 !Q.=2)Y (%U# I__X( .9P)@(DII__YJ[DAH "0O/$ " O
+M.0 "LJ!.N0 .+;?_ PS?!!C__PS?!!!__PBD"*H 0BJ ((J@ #"*H
+M ! BJ 4(J@ &"*H !PP*?_^" #F?V,V@ (/_\3G7R$/# T?P 8\AB\
+M ")\X /%"#9(-D@V2#9(-D@V2#9(-D@V2#9(-DC_ #@ ^$(GS@ X
+M(-D@V2#9(-D@V2#9(-D@V2)\X "-\ \<(WP #Q0C? ((
+MT/(\B \CR0 !.=2/\ . #X3R&-# \AB< -'\ +")\
+MX , "+8(M@BV"+8(M@BV"+8(MB1_ $PB?. #Q0BV"+8(M@B?. @
+M* 8 H /(T (T"-H !P)6"-\ G$(!!!Z (3KD #S>("C__$'H
+M A.N0 /-Y.=4A " #V8: D ?_".0 !(0 @ ]F"@) '_PCJ $ !.
+M=0 "!O 0B;P (("\ #&],(@F2B&P 1$@;* ;0 0#((" $ &<$
+M$MA3@"()" $ &8>(@#DB& "(MA1R/_\0D!3@&3T( $"@ -@ A+84<C_
+M_$) 4X!D]$YUL\AN$& "$MA1R/_\0D!3@&3T3G71P-/ 8 (3(%'(__Q"0%.
+M9/1.=0 !.5O_X2-< P"PN A,+F & PO!DZY O"%A/+@!F!' 8 XO
+M!B\'3KD $_X4$\@!TSN ,#_^$Y>3G5.5@ +RX "$ZY P'EA/3EY.=4Y6
+M]H!(USS\3KD %XV($ @4!U0__]"KO_X?@$M1__T0J[_\"UN S_Y"UN_^3_
+MZ"UN_^C_["UN_^S_X"IN @<'6=&)FX $# K !!^$L"'?@*PAV8@2JL "&<:
+M("L !+"K AF*DJ39B8P*P 0 H "$9AI(4TZY IYEA/2H!G#'#_8 .
+M>' 8 .<G0 )&L !"X30>[VQ"U(]K!![O;$+4CVM$'N]L0M2/;4# 8 )6<
+M BA3AVHL,"L $ * A&<*( =$@+"K QM%B=* 1(4TZY I8EA/)&L
+M!"X34X<4QE*"8 -NB!N_^@H4%BN_^A*C&8&*'D @4D'!QG V@4X=J+# K
+M ! "@ (1G"B '1("PJP ,;18G2@ $2%-.N0 *6)83R1K 0N$U.'%,92
+M@F#$(&[_Z" 0' !8KO_H4X=J+# K ! "@ (1G"B '1("PJP ,;18G2@ $
+M2%-.N0 *6)83R1K 0N$U.'%,92@F #28@;O_H+!!8KO_H2H9J1%.':BPP
+M*P 0 H "$9PH@!T2 L*L #&T6)TH !$A33KD "EB6$\D:P $+A-3AQ3\
+M "U2@D2&8 H@;O_H+!!8KO_H*'D @4H2>[[WRHY (%*" &3'P 0 H@
+M11DP& !,?& & "F;F8 B"HY (%+"!N_^@L$%BN_^A)[OO?2H9G "X
+M2H9G:' /P(8@11DP" #HCF;R8%@J.0 "!2@@;O_H+!!8KO_H2>[[WTJ&9P
+MBDJ&9SIP#\"&($49, @ Z(YF\F J*CD @4H(&[_Z"P06*[_Z$GN^]]*AF=<
+M2H9G#G 'P(8@11DP" #FCF;R0>[[WR8(N<-D P4'!Q3AVHL,"L $ *
+MA&<*( =$@+"K QM%B=* 1(4TZY I8EA/)&L !"X34X<4QE*"N<-EQF
+M"]9\,& _G1536!.($U231 02<!\>+"&8NY!^@ P<@VP&%3)__QFX# [$@9.
+M^P "_H+_7O[*_P+^/OZ"_]S^@O_<_U[_,/WN_LK_,'AU<W!O;&EH9&-854]$
+M0B[[TT(N^])"+OO10B[[T$(N^\]"+OO.8"8=? !^])@'AU\ '[T6 6'7P
+M ?O08 X=? !^\]@!AU\ '[SE)-$!5)P'P@L(9GWGPCL(9GX'PKL(9GPGPM
+ML(9GQ'PPL(9GUF!<2J[_]&<:2&[[ "\N_^0O+@ (3KD $SJ3^\ #$*N__0,
+MK@ #+_\&X4("[_\$/V#2#Z_"U)]JHM4?_H8!PM;OO$_^@O+O_P2&[_Z"\N
+M A.N0 3GY/[P ,4DT,%0 J9@ HE)-2&[[R$A53KD $^>4$\J &=T2J[_
+M]&<:2&[[ "\N_^0O+@ (3KD $SJ3^\ #$*N__0,K@ #+[R&X4("[[R$/V
+M#2#Z_"U)]JHM4?_@8!PM;OO$_^ O+OO(2&[_X"\N A.N0 3GY/[P ,(&[_
+MX"P06*[_X$J&:@A$AAU\ '[T2I%8$@@;O_H+!!8KO_H2H9J.D2&'7P ?O1
+M8#!\ $*N__!@%A =2<!Z,)"%W(8B!N6!W('<@"U&__ 0%4B 0?D @7="#
+M @ 9M@,%0 N9@ O%)-#!4 *F8 (I234AN^OQ(54ZY !/GE!/* !G:$JN
+M__1G&DAN^P O+O_D+RX "$ZY !,ZD_O Q"KO_T#*X R^OQN%" N^OQ#
+M]@T@^OPM2?:J+5'_[& <+6[[Q/_L+R[Z_$AN_^PO+@ (3KD $Y^3^\ #"!N
+M_^PJ$%BN_^PJ1& V(&[_Z"H06*[_Z& J>@ 0%4B 0?D @7="# @ 9Q80
+M'4G >#"0A-J%(@7E@=J!VH!@VGK_#!4 )&< _@)"KOKX+7P @5$^O1"KOKP
+M+7P @5$^NQ@ 9H'7P ?O38 &7AU\ KZZV .'7P "/KK8 8=? 0^NM*
+MA6P">@$@;O_H*!!8KO_H#"X 9/KJ9Q ,+@!$^NIG" PN &GZZF8N2H1L#"U\
+M (%1?KT1(1@'DHN^])G"BU\ (%1_KT8 Y*+OO09P@M? "!4GZ]$HN^\YG
+M%B\N^O1.N0 4)!83RA&F<"YQ6\"*@P,+@!8^NIF""8Y (%+& &)CD @4H
+M2>[[WQ N^NM)P'((L(%G"'(0L(%G%F! 2H1G0' 'P(0@0QDP" #FC&;R8#!*
+MA&<L< _ A"!#&3 ( .B,9O)@'" $3'P 0 H@0QDP& !,?$ $ "DJ$
+M9N1![OO?)@@@#)"#T(4M0/KX2B[[SV< !;:YPV8R8 %K@RN ?KX; %
+MHGH!+47Z^& !9@M? "!4OZ]& !8PM? "!4[Z]& !8 0+OKJ2<!Z6+"%
+M9^AZ;["%9\!Z>+"%9]!@ 5D2H5L GH&2B[[TV8X(&[_Z"U0^N M: $^N10
+MKO_H2&[VV$AN^MA(;OK<( 52@"\ +R[ZY"\N^N!.N0 8?A/[P 88#8H;O;4
+M=A#6C"!N_^@HT%BN_^BYPV7R2&[VV$AN^MA(;OK<( 52@"\ 2&[VQ$ZY "(
+M<$_O !0H0$JN^MAG"BU\ (%4?KT8!Y*+OO29PHM? "!5/Z]& .2B[[T&<(
+M+7P @55^O0,+@ Y]MAO%DGN]MA![ !)@@@0TH09P SE*#8/1![OO4)@A*
+M%&<$&!Q@ G@P($,0A%*#2H5F!DHN^\]G""!#$*[__U*#+47Z\& .2A1G$%.N
+M^O @0Q"<4H-*KOKP;NQ)[OO4#"X ,/;89Q8J+OK<4X5J$$2%8 Q![O; *@AX
+M!& X>@!(;O:^< P!2\ 3KD 'B04$]"+O;">&2ZA&W8#(4 /H; I![O:_
+M*@AX!6 (0>[VOBH(> 8M1/:X4X4H!4JN^MQN" PN ##VV&8$>BM@ GHM($00
+MA5.$+43Z["!$$*[ZZDHN^]%F!'H!8 )Z ! N^\Y)P,"%9P #O"\N^O1.N0
+M4)!83T'N^]0B Y*(T('0KOKPT*[VN"(&DH M0?KX8 #DDJ%; )Z!DHN^]-F
+M-"!N_^@M4/K@+6@ !/KD4*[_Z$AN]MA(;OK82&[ZW"\%+R[ZY"\N^N!.N0
+M8LY/[P 88#(H;O:T=A#6C"!N_^@HT%BN_^BYPV7R2&[VV$AN^MA(;OK<+P5(
+M;O;$3KD (E&3^\ %"A 2J[ZV&<*+7P @57^O1@'DHN^])G"BU\ (%6?KT
+M8 Y*+OO09P@M? "!5OZ] PN #GVV&\62>[VV$'L $F""!#2A!G +64H-@
+M]$'N^]0F""@N^MQN"B!#$+P ,%*#8!9*%&8(($,0O P8 0@0Q"<4H-3A&;J
+M2B[[SV8$2H5O""!#$*[__U*#* 4@!9"%+4#Z\& <4J[ZW$JN^MQO!$H49@@@
+M0Q"\ #!@!"!#$)Q2@U.$:N!*+OO19@8X? !8 *9S! N^\Y)P"(,P(%G(B\N
+M^O1.N0 4)!83T'N^]0B Y*(T('0KOKP(@:2@"U!^OA)[OO48 ")$J%; 1Z
+M!F &2H5F GH!2B[[TV8T(&[_Z"U0^N M: $^N10KO_H2&[VV! N^\])P"\
+M+P4O+OKD+R[ZX$ZY !EKD_O !1@,BAN]K!V$-:,(&[_Z"C06*[_Z+G#9?)(
+M;O;8$"[[STG +P O!4AN]L1.N0 BCQ/[P 02>[VV PN "WVV&8,+7P @5=
+M^O123& >2B[[TF<*+7P @5?^O1@#DHN^]!G""U\ (%8?KT$"[ZZDB 0?D
+M @7="# 9RHF#& *($,,$ !E9PA2@R!#2A!F\"!##! 968$$+P 12!#
+M2A!G$%*#8/8F#& "4H,@0TH09OA"KOKP2B[[T68$>@%@ GH $"[[SDG P(5G
+M $.+R[Z]$ZY !0D%A/(@.2C-"!(@:2@"U!^OA@ #P(&[_Z" 0'4#[U%BN
+M_^A)[OO40>P 28(8 U"!N_^@H4%BN_^A*A6H&*CQ_____2HQF!BAY (%
+M)'@ 8 :XA6P(4H0=7/:O9O1*+OO19@1Z 6 ">@ 0+OO.2<# A6<(( :0A"U
+M^OA33"8,F<1@?GH!+47_^&!V2>[ZZD'L $F"&!J($U231U0^NH0+OKJ2<!X
+M>+"$8N!!^@ ^<A2P&%3)__QFTC [$@9.^P " G#Y>OK>_A[Y</F"^7KYBO]2
+M^7KZWORP_A[_UOEZ_];_POF"_V[Y>OF*>'5S;VYL:6AG9F5D8UA53TQ'140
+M $JN^O!L!'H 8 0J+OKP2J[Z^&P$> !@!"@N^O@O+OKT3KD %"06$\M0/:J
+M+R[Z[$ZY !0D%A/G(6<@" #D(R<@)R$G*[VJDHN^]%F>F V4X=J+# K ! "
+M@ (1G"B '1("PJP ,;18G2@ $2%-.N0 *6)83R1K 0N$U.'%/P (%*"
+M4X9JQF \4X=J+# K ! "@ (1G"B '1("PJP ,;18G2@ $2%-.N0 *6)8
+M3R1K 0N$U.'(&[Z]!304H)2KOKT(&[Z]$H09KQ@-E.':BPP*P 0 H "$
+M9PH@!T2 L*L #&T6)TH !$A33KD "EB6$\D:P $+A-3AQ3\ #!2@E.N^OAJ
+MQ+G#9'!3AVHL,"L $ * A&<*( =$@+"K QM%B=* 1(4TZY I8EA/
+M)&L !"X34X<4W%*"N<-ER& V4X=J+# K ! "@ (1G"B '1("PJP ,;18G
+M2@ $2%-.N0 *6)83R1K 0N$U.'%/P ,%*"4Z[Z\&K$8#Q3AVHL,"L $ *
+M A&<*( =$@+"K QM%B=* 1(4TZY I8EA/)&L !"X34X<@;OKL%-!2
+M@E*N^NP@;OKL2A!FO$HN^]%G/& V4X=J+# K ! "@ (1G"B '1("PJP ,
+M;18G2@ $2%-.N0 *6)83R1K 0N$U.'%/P (%*"4X9JQ@RN ?_X9A @
+M;O_H(%!8KO_H(()"KO_X'!UF /($)TH !":',"L $ * A&<P,"L $ @
+M )F')7K @O"DAX HO*P (3KD %*(3^\ #$J 9PI(4TZY I8EA/,"L
+M$ @ 5G!'#_8 (@ DSN//SV@$Y>3G5.5O\<2-<\X$AX ,A"ITAN_SA.N0
+M4#A/[P ,>O]\ "AN A(> E2%1.N0 80A03RX 9P _E*'*$<O.0 "!3!(
+M5$ZY !A6%!/+@ ,- D> !F$DA43KD %"P6$]3@"P 4H?9QWX ( ;E@$?V
+M"2#_."\Y (%-$A43KD &%84$_9P"1,4DP0$DG <G.P@6)@0?H :G(*L!A4
+MR?_\9E(P.Q(&3OL O]Z !P )@ F "8 )@ F !8 . R "P !P !8*X !P "
+M.GP 6 \.GP !& V.GP V P.GP !F J" < &<&.GP !V >.GP "& 8" <
+M &?0.GP F ,<W!N;&=F94=%*B4 2H9M#G(RO(%L"":-NH9L BH&4H982P@'
+M %G /[\"H< "8 #_0GX 2H5M4$ON_S@L+@ 0(D8BK@ ,2I5F$G(!*H%@
+M#%"N Q@*%BN Q@(B 54X!R!["!8A@P.PH&3OL O_H_^C_Z/_B_^+_Z/_H
+M_^A2AUB&6$V^A6^X3.X\X/\<3EY.=4Y6_]Q(USSX)&X "'HR+ 4J;@ ,)BX
+M$& ,NH-G #R6)52A5*&*$IX & "4H:Z@V< -A(> E2%1.N0 80A03RX
+M9P Q%*'*$<O.0 "!3A(5$ZY !A6%!/+@ ,- D> !F$$A43KD %"P6$\L
+M %*'V<>ZAF:R> %^ "\Y (%/$A43KD &%84$_9P"9,4DP0$TG <G.P@6)"
+M0?H 2'(*L!A4R?_\9C0P.Q(&3OL O]V !P ) D "0 ) D !8 + @ "
+M!P !8*X !P "6)5@' @' !0E6 4" < %B58 QS<&YL9V9E1T4J)0!2A5*&
+M" < 6< _S *AP )@ /]V2H1G /\,2H1F /\23.X\^/_<3EY.=4Y6__1(
+MUP# ?@!\ ")N A@%%*&WH<B!^6!WH$2&4G!WH%R,)Z!$!%(@$'Y (%W0@P
+M ( &;:2H9G$@P1 "1F#"!N P@AU))( E@ G 3.X P/_T3EY.=2)O 0@
+M+P (;S)"@0@O !V<$$L%3@"! Y(A@ B+!4<C__$) 4X!D]" (" 6<"
+M,L$( 9P(2P4YU B+P (9PX0 >&)$@#AB1( X8D2 ")O 0@+P ,;S (
+M+P =G!!+!4X @0.2(8 (BP5'(__Q"0%. 9/0@" @ %G C+!" &<"
+M$L$@+P $3G4 (&\ !")(<O]*&5?)__QF /_X4XF3R" )3G4 !.
+M5O_P2-< P")N AR ! 12< N $'Y (%W0@P )X &9$0?D @7="# W@
+M9Q9221 12< N &#H<@%221 12< N & .( =\*["&9^Y\+;"&9^9!^0 "!=T(
+M, "> !F!' 8#)\,)R'8 [<AB &Y8#<@' PD(?<@%))$!%)P"X 0?D @7=
+M"# G@ 9MQ*@68"1(8@!DSN ,#_\$Y>3G4 !.5O_\0?D @7=T>X
+M"! 0<@/ @4Y>3G5.5O_\0?D @7=T>X "! 0<@' @4Y>3G5.5O_\0?D @7=
+MT>X "! 0<@+ @4Y>3G5.5O_\0?D @7=T>X "! 0<@3 @4Y>3G5.5O_\0?D
+M @7=T>X "! 0<D# @4Y>3G5.5O_\0?D @7=T>X "! 0<@C @4Y>3G5.5O_\
+M0?D @7=T>X "! 0<A# @4Y>3G5.5O_\0?D @7=T>X "! 0<@? @4Y>3G5.
+M5O_\0?D @7=T>X "! 0 H "73EY.=4Y6__Q!^0 "!=W1[@ ($!!R%\"!
+M3EY.=4Y6__Q!^0 "!=W1[@ ($!!R(,"!3EY.=4Y6__QP RN ?P (4\!$
+M $Y>3G5.5O_\("X "')_P(%.7DYU3E;_\$C7 , @;@ ($BX #RXN !!3AVL,
+M'!B\ 6;V4T@@"& "< !,[@# __!.7DYU3E;]O$C7 /!*.0 "LM!F!DZY !@
+MDB@N @J+@ ,9@ $ DJ$9@ EG@ ?@ L/ "LM J/ "LM\O!2\&3KD &$H
+M4$]*@&824H=R#]J!W(%R!KZ!;>)*A&=82'D K+02'D J[$3KD (OX4$]^
+M#P:' *RT"P\ *S.4AY ((5$AY *NQ$ZY "+T%!/+P=(>0 "KL1.N0
+MB]!03WH/WH6^AF74(#P J[$8 #GB \ *RT& Y0@!"( Z8%$@-"!!H
+M K+!8 #@$AX "\O!4ZY !A"%!/2H!G $V+P5.N0 4)!83WYXL(=N ,8
+M+P5(>0 "KL1.N0 B_A03RX\ *NQ'P 2'D @A6+P=.N0 89!03RX 9@
+MMG 8 #)B\'2'@ 4ZY !2N%!/2H!F "Z< !@ ,,+P=(> "3KD %*X
+M4$]*@&8 *!P & O(O!TAX -.N0 4KA03TJ 9@ AG 8 "V"\'2'@
+M!$ZY !2N%!/2H!F;' 8 "P"\'2'@ !4ZY !2N%!/2H!F5' 8 "J"\'
+M2'@ !DZY !2N%!/2H!F/' 8 "D"\'2'@ !TZY !2N%!/2H!F)' 8 "
+M>" &<@:P@6(6,#L*!D[[ +_0O]<_W;_D/^H_\#_V'X 4H9R![R!;0#_#DAY
+M ((6$*G3KD &&04$]*@&8 .)(>0 "LM!(;OW\+P5.N0 5Q!/[P ,/@!M
+M ':2D=G,$AX 0%(;OW\2'D @7<3KD (M 3^\ #$AX 0%(;O[]2'D @<
+M3KD (M 3^\ #$J$9@ !UDAY *RWTAN_<PO!4ZY !7<D_O PN &=P($=*
+M$&=$2KD @A(9PXO.0 ""$A.N0 ,!Y83R/' ((2$AX #!![OW,3^__T")/
+M,#P "R+84<C__"\Y ((1$ZY "+0$_O #A*A&8 6Q(>0 "LNXO!4AX -(
+M>0 ""%I.N0 6Y9/[P 0/@!L!G 8 !4DI'9PQ(QR\'3KD #AV6$]*A&8
+M 3!(>0 "LOU(;OW,+P5.N0 6&1/[P ,+@!G #>($=*$&<T2KD @A,9PXO
+M.0 ""$Q.N0 ,!Y83R/' ((3$AX #!(;OW,+SD @A$3KD (M 3^\ #$J$
+M9@ U$AY *S#"\%2'@ !4AY ((8DZY !;ED_O ! ^ &P,0GD @@2< !@
+M "T2D=G$D)Y (($DC'+P=.N0 .'983TJ$9@ C$AY *S&R\%2'@ !DAY
+M ((:TZY !;ED_O ! ^ &TT2D=G#$C'+P=.N0 .'983TJ$9E9(>0 "LRHO
+M!4AX =(>0 ""'9.N0 6Y9/[P 0/@!L!' 8#Y*1V<N2,<O!TZY X=EA/
+M8" @!'X'L(=B&# ["@9.^P "_)[]YOX\_J;^XO\^_X;_ND*G+P1.N0 4KA0
+M3TSN /#]O$Y>3G5.5O_\+H<O+@ 0+RX "$AX %(>0 ""().N0 6Y9/[P 0
+M+@!O,DAX @(O+@ ,+P=.N0 BI9/[P ,#( ("9PPO!TZY X=EA/?O\O
+M!TZY X=EA/( <N+O_\3EY.=4Y6_[1(UR#@+RX $"\N A(> "2'D @B+
+M3KD %N63^\ $"H ;0 ODJ%9@H@/ "")9@ "R2&[_Q"\%3KD #B&4$]*
+M@&8 )P@+O_45( O $ZY O"%A/+@!G "&+R[_U"\'+P5.N0 BI9/[P ,
+ML*[_U&9B*FX #"P'W*[_U"!&$+P "E*&($9"$$A5+P=.N0 6C)03RP 9S)(
+M;0 $+P9.N0 6C)03RP 9R!(;0 (+P9.N0 6FA03TJ 9PXO!4ZY X=EA/
+M( =@%B\%3KD #AV6$\O!TZY P'EA/< !,[B#@_[1.7DYU3E;_M$C7(. O
+M+@ 0+RX "$AX 1(>0 "")=.N0 6Y9/[P 0+ !M &:2H9F"B \ ((HV
+M 8Y(;O_$+P9.N0 .(903TJ 9@ !>" N_]14@"\ 3KD "\(6$\J &< 6(O
+M+O_4+P4O!DZY "*ED_O RPKO_49@ !/BIN PN!=ZN_]0@1Q"\ I2AR!'
+M0A!(;0 ,+P5.N0 6C)03RX 9P !"DAM ! O!TZY !:,E!/+@!G #V2&T
+M%"\'3KD %HR4$\N &< .)(;0 8+P=.N0 6C)03RX 9P SDAM !PO!TZY
+M !::%!/+@!G "Z2&T ("\'3KD %HR4$\N &< *9(;0 D+P=.N0 6C)0
+M3RX 9P DDAM "DO!TZY !:N%!/+@!G?DAM "HO!TZY !;'%!/+@!G;$AM
+M "LO!TZY !;'%!/+@!G6DAM "PO!TZY !;'%!/+@!G2$AM "TO!TZY !;
+M'%!/+@!G-DAM "XO!TZY !:N%!/+@!G)$AM "\O!TZY !:N%!/2H!G$B\&
+M3KD #AV6$\@/ "LOU@%B\&3KD #AV6$\O!4ZY P'EA/< !,[B#@_[1.
+M7DYU3E;__"Z'+BX ""!N P@ATAX HO!TZY !A"%!/+@!F!' 8 @@1T(0
+M4H<@!RXN__Q.7DYU3E;_^"Z'(FX "$H19PP@;@ ,((E@(DJ'9@1P & J<C"^
+M@6T.<CF^@6X(<C">@1*'8 02O !_4DD0$4G +@!R"KZ!9M)"&2 )+B[_^$Y>
+M3G5.5O_T2-< P")N A*$6<@#!$ "F8*(&X #!"\ ']@-GP 8"!R,+Z!;09R
+M.;Z!;P1P & FW(8B!N6!W('<AWXPG(=221 12< N '(*OH%FU"!N P0AD(9
+M( E,[@# __1.7DYU3E;_]"Z-*FX "$H59UP@;@ ,#!4 "F80$+P ?V!0$+P
+M 6! 0A!@/")-4DT0$4G <D:P@6?N<DZP@6?H<E2P@6?<<EFP@6?6<F:P@6?6
+M<FZP@6?0<G2P@6?$<GFP@6>^< !@#@P5 IG!' 8 1"'2 -*F[_]$Y>3G5.
+M5OO<2-<@P"IN @N+@ 0($=*$&9J2%5.N0 C'!83RX 9P8@1TH09E9(>0 "
+M"*1.N0 C'!83RX 9P8@1TH09CY*.0 "KK1F,$AY ((J4ZY ",<%A/+@!G
+M!B!'2A!F"$AY ((M& "+P=(>0 "KK1.N0 B_A03RX\ *NM" N PB .F!
+M1(#0@0: *RP2\ +P=.N0 82A03TJ 9A0O!R\N !1.N0 B_A03W 8 !
+MR"\'3KD %"06$]\#K"&;P9P_V ;)(>0 ""+9(;OP 3KD (OX4$](54AN
+M_ !.N0 B]!03TAY ((PTAN_ !.N0 B]!03R\'2&[\ $ZY "+T%!/0J=(
+M;OP 3KD (LV4$\L &Q<#+D " ( 1&902'D @C%2&[\ $ZY "+^%!/
+M2%5(;OP 3KD (O04$](>0 ""-Q(;OP 3KD (O04$\O!TAN_ !.N0 B]!0
+M3T*G2&[\ $ZY "+-E!/+ !*AFT.+P<O+@ 43KD (OX4$\,K@ $ #&8
+M .1(>0 ""-Y(;OP 3KD (O04$]"ITAN_ !.N0 BS903RX <O^^@68*3KD
+M &!.8 LDAX !A(;OOH+P=.N0 BI9/[P ,<ABP@6<63KD &!.+P=.N0
+M.'983W#_8 A$AN^^A(>0 "!N1.N0 B_A03R/N^_@ @;T2KD @;X9PXO
+M.0 "!OA.N0 ,!Y83TJN^_QO5B\N^_Q.N0 +PA83RI +R[[_$A5+P=.N0
+MBI9/[P ,L*[[_&<4+P=.N0 .'983TZY !@3G#_8!(CS0 "!O@O!TZY X
+M=EA/( 9,[B# ^]Q.7DYU0KD @;X+P=.N0 .'983TZY !@3G#_8-Q.5O_\
+M(#D @A$3EY.=4Y6__!(UR# +#P @CB+CP @EH*GP @F]2KD @@"9@ !
+MV$AX +!.N0 +PA83R/ (( DJY (( F=Z+P9.N0 4)!83U* +P!.N0
+M+PA83R/ ((!F=<+P8O.0 "" 9.N0 B_A03R\'3KD %"06$]2@"\ 3KD
+M "\(6$\CP "" IG+B\'+SD @@*3KD (OX4$](54ZY !0D%A/4H O $ZY
+M O"%A/(\ @@.9@9P & 41(52\Y ((#DZY "+^%!/+#D @@&?@ @
+M>0 "" )(<'0 +P9.N0 6C)03RP 4D<,1P ,;>)^ "!Y (( DAP=# O!DZY
+M !:,E!/+ !21PQ' QMXBPY (("GX ('D @@"2'!T8"\&3KD %HR4$\L
+M %)'#$< !VWB?@ @>0 "" )(<'1\+P9.N0 6C)03RP 4D<,1P ';>(L.0 "
+M" X@.0 "" (&@ )@O "\&3KD %HR4$\L " Y (( @: G"\ +P9.
+MN0 6C)03RP (#D @@"!H "@+P O!DZY !:,E!/+ @.0 "" (&@
+M *0O "\&3KD %HR4$\L " Y (( @: J"\ +P9.N0 6C)03RP (#D
+M @@"!H "L+P O!DZY !:,E!/(#D @@"3.X@P/_P3EY.=4Y6 !(>0 "
+MKK1(>0 "!N1.N0 B_A03T*Y (&]$JY (&^&<.+SD @;X3KD # >6$]"
+MN0 "!OA"N0 "!OQ.7DYU3E;__"Z'?@!(>0 ""?8P!TC (@#I@42 T($&@ "
+MLM O $ZY "+^%!/4D<,1P ';=9(>0 ""?A(>0 "!N1.N0 B_A03TAY (*
+M $AY *RP$ZY "+^%!/(_P @H" *RL"/\ (*!@ "LK0N+O_\3EY.=4Y6
+M__0@;@ ($BX #[(09@0@"& &2AAF]' 3EY.=0 3E;_]"Z'(&X #")N @>
+M&+X19@A*&6;V< !@"A 12< 2($G!D($N+O_T3EY.=0 3E;_]"Z-(FX ""!N
+M Q@%BI(8 @0%; 19P9234H59O1*%6<&4DE*$6;FD^X "" )*F[_]$Y>3G5.
+M5O_X2-<@@"XN AF!BXY *O1$J'9Q8O+@ ,+P=.N0 85A03]"'*D!*%68$
+M< !@*"\N Q(54ZY "-"%!/+@!F"$*Y *O1& ,($="$%*'(\< J]$( U,
+M[B" __A.7DYU $Y6_<A(US#@+"X $"UY *S//_T?@$M1__X+4;__$AN
+M_=Q(;OW@2&[_]$AN A.N0 <E8@;@ 8(*[]Y"IN !0J+@ <("[]X'X%L(=B
+M?# ["@9.^P " "X # , $8 6 !8("[]Z-"&*H!*AF]62^[]["A%0?9I(/WL
+M+@@8W;O'9?I@0'X!*H=*AF\X*D4H1MG%&OP ,+O,9?A@*$*5+CD @H@<@B\
+M@6T,? A@"D*5+CD @H<? ,J1RA%WH88W;O'9?H@14(P: @!4SN,.#]R$Y>
+M3G5.5OW(2-<@\"HN ! M>0 "LSS_]$*N__@M1?_\2&[]W$AN_>!(;O_T2&X
+M"$ZY !R5B!N !@@KOWD*"X '"XN !0@+OW@? 6PAF( +(P.PH&3OL @!$
+M P # !R (8 ADJ%;0P@1R N__"0A2" 8 8@1R"N__!^ $ON_>PL!& (($80
+MG5*'4H:^KO_P;?(@1-'N__!"$&!D($="D"!$$+P ,#I\ &ZC6\6?@'>A-J$
+M+ 4@1Q"\ #!235*'OH9E\D(U2 !@-B!'0I L.0 ""B!^"+J';0YZ"& ,($="
+MD"PY (*''H#+@8J1-R%($<:T%*'OH9E]B!$0C!8 " $3.X@\/W(3EY.=4Y6
+M_^!(USS@*&X #"XN !1.N0 7C8@0"!0'! J1TJL 1G & ($<0O M4H<J
+M1V 7(:_ P2H5G &.&L:9S%-*+@JYQVP 8 :_ P4DQ@\GX(M<=L""AY
+M (*.& .*'D @HT8 8H>0 ""CQ*%&< 58:W&#V2JP "&X.( I6@$2 L*P
+M"&\ )H:[ ,&L8V? !?@%@!AK24DM2AT7T> Q*$F;R2H5F# PE #!G^KP5
+M9P)231K\ &4H; (V<M33$J,:P8:_ K8 H:_ M( Q$@"A 2&[__' , PO
+M $ZY !XD%!/?@!)[O_\8 12AU),#!0 ,&?V? *^AF\$?@)@"'P#OH9N "\
+M2?9X_$'N__Q62"X(&MRYQV/Z8 IG !D(JPK (;C9^ "9'8 @:]+@,4H=2
+M2R *T*P "+Z ;>X:QB9'2C2X#&= OHIL/"X+)DH:]'@,4H>^BVWV8"P:_ P
+M&L9^ & &&OP ,%*'("P "-"*1("^@&WN?@!@!!K34H=']'@,2A-F]$J%9C0,
+M)0 P9_J\%6<J4DU@)B1N @J+@ 0(!1^!;"'8@#^QC ["@9.^P "_G;^O/Z\
+M_I;^K/ZL0A5,[CS@_^!.7DYU3E;]W"UY *S//_T<@$M0?_X+6X $/_\2&[]
+MW$AN_>!(;O_T2&X "$ZY !R5D_O ! O+@ 8+RX %$AN_> O+@ 03KD &/8
+M("X &$Y>3G5.5O_\+RX %$*G+RX $"\N PO+@ (3KD &6N3EY.=0 3E;_
+M\$C7(, J;@ ,+"X &!XN !<,!P P9@9*AF< ,XB;@ 0<@&#D2!N @@$'(#
+ML(%B7C ["@9.^P " @ L !0 $@,!P U;0 H@P' #5N0$J&9CQ*K0(0;P
+MD$'M P@+0(0$# (_TG ?C"0AW(!2H!L"$2 P(%$@& "P(%*@& ,2JT !&9B
+M8 9*K0 $9UHN+0(04X<L!V ,2H=M$A*\ #!3AU.&0_5H# P1 #EGZDJ';092
+M-7@,8$(;? Q P@;@ (#*@ ! 1F!E*M A@*$JM A!O"B M A ;O P
+M" Q2K0(08!)*K0(0;@P;? P Q^ 2M' A @+0(00C4(#$SN(,#_\$Y>3G5.
+M5OLL2-<XP#U\ 0#]^#U\ 0#[\$AN^^Q(;OWX+RX "$ZY !^BD_O Q*KOOL
+M:B!(;OOJ("[[[$2 H /__+P!(;OWX3KD 'RV3^\ #$AN^_!(;OWX3KD
+M '_*4$]*KOOL;@I![OOP+4C[Y&!T2&[[Y"\N PO+OOL2'@ DAN^_!.N0
+M@3)/[P 4("[[Y&<H?@&PAV9*+R[[[$AY (*7$AN^Y1.N0 BO!/[P ,2&[[
+ME$AX ")@("\N^^Q(>0 ""G%(;OM$3KD (KP3^\ #$AN^T1(> ,3KD (#N
+M4$](;OM (&[[Y' ,"@ D'P"@9P # H__XO $ZY !XD%!/?@!+[OM 8 12
+MAU)-#!4 ,&?V)FX $)O-? .^AFX>0?9Y(/M +@@H2T'N^T!62"P(($<8T%*'
+M4DV^AF/T(&[[Y' ,"@ E6 +@!M)N.'0?/8 "P(+P8@;OOD< P,'@&+P!.
+MN0 >)!03UA-6(95AVKB0C/8 "!N !@@C2!N^^0P* $2, @;@ 4((!![OOP
+M("[[Y+"(9PHO $ZY " TEA/3.XXP/LL3EY.=4Y6^R1(UR#\*FX %"HN ! L
+M+@ ,+BX ""!N !A"D"!'2J@ !&8T?@ H#6 *($00O P4H=2A+Z%8_)!]7@
+M*@A@"B!%$+P ,%*'4H6^AF/R(&X '""'8 "=CU\ 0#]^#U\ 0#[\$AN^^Q(
+M;OWX+P=.N0 ?HI/[P ,/6[[[OW\=!&4KOOL<@ R+OWZZ8F4@4P\( ( $T1
+M<A#BJM2&M(5D B0%+@6\AV,"+@9,/'@' -2:@:' :DU'(0XJ=2AT2'2&[[
+MZ"\'+P)(> *2&[]^$ZY "!,D_O !0@+OOH9R9^ ;"'9D8O DAY (*ADAN
+M^YA.N0 BO!/[P ,2&[[F$AX ")@'B\"2'D @J<2&[[2$ZY "*\$_O Q(
+M;OM(2'@ #$ZY " [E!/(&[[Z QH__ !&YV,"@ !$C 1(!J!'X/T(?H@"@
+M?@!\ & .(&[[Z$IP: 9F"%*'5(:^A&WNOH1L"B!N^^@ < !2@8N!"P$XX8J
+M!..%( :0A2H 8! @;OOH,;!H!E@&4H=4A52&(&[[Z' ,"@ KZ 9>*9: "
+M(&[[Z.F$V6@ !"!N^^A*: $;#!(;OM&,"@ !$C 1( "@ __\O "\(3KD
+M 'RV3^\ #$IN^T9G"B!N^^@ : ! 9(;OOP+R[[Z$ZY !_RE!/?@ ^+OOR
+M4X<L!^.&0?9I(/OV+ A@!%.'588@1DI09_9(;OM < P-GL@^_8O $ZY !X
+MD%!/>@!![OM + A@!%*%4H8@1@P0 #!G]'P > .ZA&XB0?99(/M *@@H#4'N
+M^T!62"8(($0B11"14H52AE*$NH-C\%.':S+CAT'V>2#[]BX(0?5H "H(0>[[
+M]B@(+P4@1W ,! O $ZY !XD%!/6(98A56'OH1DY$(U: @;@ <((8@;@ 8
+ME(8@@D'N_?@@+OOHL(AG"B\ 3KD (#26$],[B#\^R1.7DYU3E;J0$C7./PF
+M;@ 0+BX "'8P0J[__"!')U !":H 0,J ( !&<,#*@ ! 1F 9>
+M*&X # RL " (;!0,K $ !&86#*P ! AL#"!N !1^"(^08 &
+M,$'N_]PB1S \ <@V5'(__Q![O_<0^[_O# \ <BV%'(__P,KO______Y&X(
+M0J[_X& 2P,K@ )__Y&T(0J[_P& -X@+O_D<A]*@&P(1(# @42 8 +
+M@7X?L(=F1" N_^12@&H"T(?J@"P ?@!+[O_(8 1"G5*'OH9E^'P%OH9L "2
+MY8=!]GCH+@A![O_H0>@ %"P(($="D%B'OH9E]F!R("[_Y%* :@1^']"'ZH L
+M 'X 2^[_R& $0IU2A[Z&9?@@+O_D<A]*@&P(1(# @42 8 + @7(?DH!P >.@
+M4X N!N6'P;9XR$: P;9XZ%*&+@9\!;Z&;!SEAT'V>.@N"$'N_^A!Z 4+ @@
+M1T*06(>^AF7V2&[_O$ZY !S:%A/2J[_X&<V#*P ! 1F""XL A2AV &
+M+CP !-$2&[L<$AN['1(;NQX+P=(;O_<3KD &<P3^\ %& (0J[L<$*N['0D
+M+NQPU*[L='@ 2JP !&8&2JP "&P4#*P ! 1F:B L A2@+"";V ,K
+M $ !&8:+BP "%2'GH(,AP @!C!BX\ " 'P!8!9^ "PL A4A@R& "
+M &,&+#P ( 2&[J:$ANZFQ(;NIP+P8O!TAN_[Q.N0 :.)/[P 8*"[J;-BN
+MZF@,K $ !&8 @ J+NQPNJP "&\$*BP "'X 2H5O'$OK Q![NQX+ A!
+M[NQXVH@@1AK04H=2AKR%9?0J;NQPV^[L=+OL AO!"IL B^C6P80>L #"P'
+MW(C;R"!&$+P ,%*'4H:\C67ROJP "&8 *0G1P(0( *0AR= B^@FQ,OJ[L
+M<&0*%C9Y(.QX4H=@ G8P0?9Y(.QX+ A@"KZN['!D#%*'4H8@1@P0 #!G[KZN
+M['!D!GX!+4?__$JN_\!G $N?@$M1__\8 !)$JN_\!G $<2J[J;&\&=C!\
+M & &%B[J<'P!+@9!]FD@ZG L"& (OH1L#%*'4H8@1@P0 #!G\+Z$; Z'X!
+M+4?__& -XJ+ (FH=*AV8>? !+[NIP8 12AE)-#!4 ,&?VVH;:KNILW*[J
+M;& "? "ZA&\"*@0@!42 )T "+JNZFQO!B@NZFQ@ B@%O(1L$DOK S;QQK\
+M #!2AU*&O(1M]+R%;!I+ZP ,V\<@!I"NZFP:]@D@ZG!2AU*&O(5M[)RNZFR\
+MKNIH;#I*AFP$=C!@!A8V:2#J<%*&:@)\ $OV:2#J<& *O*[J:&P*4H9230P5
+M #!G\+RNZFAL(GP!+4;__& :0>L #"P(W(=@"B!&$+P ,%*'4H:^K (;? G
+M1P(0+R[__$G#+P,O+@ 42%-(5$ZY !F(& C9*K (;0 !'B "T*P " R
+M " &P ^^1^ $OK Q![NQX+ A@""!&&M!2AU*&OJ[L<&7ROH)L&DOK Q!
+M]7@ + C;PB!&$+P ,%*'4H:\C67R*@2XK (;P0J+ (NJ[J;&\&*"[J;& "
+M* 5\ $J$;Q)+ZP ,V\<:_ P4H=2AKR$;?2\A6P:2^L #-O'( :0KNIL&O8)
+M(.IP4H=2AKR%;>Q+ZP ,V\=@"!K\ #!2AU*&O*P "&WR)T<"$)2')T( ")RN
+MZFPN!KZNZFAL/$J'; 1V,& &%C9Y(.IP4H=J GX 0?9Y(.IP+ A@"KZNZFAL
+M#%*'4H8@1@P0 #!G[KZNZFAL!GX!+4?__"\N__Q)PR\#+RX %$A32%1.N0
+M9B!@ $2+"P "$2&#(( ( ; #ZR R& " &P ^KZTAFXZM(9F"!8N['A^
+M 6 $=C!^ $OV>2#L>& *OJ[L<&0*4H=230P5 #!G\+ZN['!D!GX!+4?__$*K
+M A!@;GX 0>L #"@&2^[L>"H(8 @@11"=4H=2A2 N['"0A+Z 9>Y^ $OK R4
+MABH"8 8:_ P4H>^A6WV)T<"$+ZN['!D+!8V>2#L>%*'2_9Y(.QX8 J^KNQP
+M9 I2AU)-#!4 ,&?POJ[L<&0&?@$M1__\2J[_P&<&?@$M1__\+R[__$G#+P,O
+M+@ 42%-(5$ZY !F("XK A!)ZP ,V<=@!AC\ #!2AR K A#0AKZ ;?!"JP (
+M)T<"$$(S> Q,[CC\ZD!.7DYU3E;_U"Z-*FX $"!N !1"D"!N @M4/_X+6@
+M!/_\Z>X ?_X*T !"\N A.N0 =,!83RJ (!5R!;"!8A0P.PH&3OL @ P
+M P # P # ,$AN__A(;O_83KD '5X4$\O+@ 42%4O+@ ,2&[_V$ZY !K
+MNBIN_]1.7DYU3E;_O$C7., H;@ ((&X %$*0?@!+[O_P0>[_\$'H ! L""KT
+M> !8A[O&9?9@%# ["@9.^P " % +@ N % 4 !0)FX $.GN '_\"= 1(
+M5$ZY !VHEA/)H @$WX%L(=CRDA42&[_T$ZY !W1%!/+RX %$A3+RX #$AN
+M_]!.N0 :[I,[CC _[Q.7DYU $Y6_]A(UP#X(&X " RH @ $9@ !
+M(GX 8 @,1P %9 Q21W , =*L P,9^X,1P %90A"J $8 _DI'9UI"KO_\
+M>@ Z!W@%F(63R6 .W(4AL&P,F Q2KO_\6$DL+O_\O(1EZ@RN !?_\;!SE
+MABU&__0@+O_T0K (#%BN__0,K@ !3_]&WJ< P!^N(D:@ "& "4D=P # '
+M<@22@")!2K"<#&?N0F[_^BXH P,AP __]B"' 0X:\]0/_Z#(< ____8@;A
+MCU!N__H,AP____]B!NF/6&[_^@R'/____V(&Y8]4;O_Z#(=_____8@12;O_Z
+M< P+O_ZD:@ " QN '_^F4N? !*B6TH< P+O_Z=B"6@"X)Y8=#\'@,*A$R
+M+O_ZXZTH$>:LC(4BABP$68=JYDSN /C_V$Y>3G5.5@ < $R+@ *XZ"!N0 "
+MLT1.7DYU3E;_]"!N @M4/_X+6@ !/_\,"[_^ ) ?_!F&B N__@"@ /__]F
+M"DJN__QF!' 8$1P 6! ,"[_^ ) ?_ ,0'_P9C @+O_X H #___9@I*KO_\
+M9@1P V <("[_^ * ___PR 0 &4$< 1@!G %8 )P DY>3G5.5O_D2-<
+M\'P (BX #" N A^#-"'>""8@3!\ !#1P"X0XZ\J$.BMC(<@ABP%64BQP&3L
+M3.X \/_D3EY.=4Y6__!(UR" *FX ""!N PM4/_X+6@ !/_\Z>X ?_X*H K
+M;O_\ !!^"$*U> Q8AW(4OH%M]# N__@"0'_P9VPP+O_X D!_\ Q ?_!G "2
+MZ>X 2__X!( /_*T "'X"*T< !" N__@"@ /__\ @ 0 K0 ,2'@
+M"TA53KD '4Z4$]@&$JN__QF7'X#*T< !& *2J[__&8:0JT !$SN((#_\$Y>
+M3G4@+O_X H #___9^!^ BM' 0K?/___ T "" N__@"@ /__\K0 ,2%5.
+MN0 <VA83V#"("[_^ * ___V>>("[_^ * ___P@ !-G"'X$*T< !& 2
+M?@0K1P $2'@ !$ZY !TJEA/("[_^ * ___P" @ & _TY.5O_@2-<
+MP")N A\ $'N__ N"$'N__!!Z 0(@@@1R"Q: !8AEB'OH%E\C N__ "0'__
+M9THP+O_P D!__PQ ?_]G1G "8"YP!& J2J[_]&8^2J[_^&8X2J[__&8R< -@
+M%$JN__1F'DJN__AF&$JN__QF$G 3.X P/_@3EY.=4IN__)GW' !8.Q*;O_R
+M9[QP # N__(,@ @ !DJG %8-1.5O_<2-<PX"AN Q\ $'N__ N"$'N__!!
+MZ 0*@@@1R"T: !8AEB'OH5E\BIN CI[@ !__ J@"MN__0 $"MN__@ %"MN
+M__P &'X00K5X#%B'?!2^AFWT,"[_\ ) ?_]G8# N__ "0'__#$!__V< (IP
+M # N__ "0'__!( #__*T "'X"*T< !' ,"[_\@" $ "M Q(> /
+M2%5.N0 =3I03V ,?@,K1P $8 1"K0 $3.XPX/_<3EY.=7 ,"[_\H"N__2
+MKO_X@*[__&?>?@(K1P $*WS__\ 1 AP # N__(K0 ,2%5.N0 <VA83V"^
+M< P+O_R@*[_]("N__B KO_\9YX(+@ '__)G"'X$*T< !& 2?@0K1P $2'@
+M!$ZY !TJEA/< P+O_R $" "M Q(> 08 #_7 $Y6__1(UP#
+M? ,@;@ ,/BX "G , <N $Q\ $ *<##2@!&!8 !,?' ' "E'._^!,
+M[@# __1.7DYU3E;_W$C7./Q\ '@ >@ H;@ 0=@ V+@ *) -3@BIN Q@,"\&
+M( *0AS T"@ "@ __\O ' ,!4O $ZY !Y^$_O PN +Z&9 )21"P'4H54
+M32X%OH-ERB9N !0P//__P$8V@'(0XJXW1@ "-T0 !$SN./S_W$Y>3G5.5O_<
+M2-<X_'X > !\ "AN !!V #8N HD U."*FX #& X+P<@ I"%,#0* * #_
+M_R\ < P%2\ 3KD 'GX3^\ #"X #(>RT%X 90A21 2'LM!> %*&5$TJ!KJ#
+M9<(F;@ 4( =,? ! G$#:!3'QP!P )Q @!TQ\ $ "<0-T$ DQ\< <
+M "<0< P!$2 Y8@B -*!T('0AS= 1,[CC\_]Q.7DYU $Y6__PP+@ *
+MP.X #M"N !!.7DYU3E;_^$C7 (1^ #XN K>K@ ,( =,? G$'(0XZA,
+M?' " G$(""3.X A/_X3EY.=4Y6__@NARXN AG&"!N QP # 0WH P//__
+MP$<PP'(0XJ]F["XN__A.7DYU3E;_^$C7(( N+@ (9R0J;@ ,+P=P # 5+P!.
+MN0 >@Q03RX ,#S__\!'.L!R$.*O9N!,[B" __A.7DYU3E;_^$C7 (0P+@ *
+MP.X #M"N ! N $Q\ "<0<A#CJ$Q\< ( "<0@(),[@"$__A.7DYU3E;_
+M_# N K [@ .3EY.=4Y6__A(UP"$,"X "L#N XN $Q\ "<0<A#CJ$Q\
+M< ( "<0@(),[@"$__A.7DYU3E;_^$C7 (0^+@ .< P+@ *[ZC0K@ 0+@!,
+M? G$'(0XZA,?' " G$(""3.X A/_X3EY.=4Y6__PP+@ *P/PG$-"N
+M Q.7DYU3E;_^$C7 (1^ #XN IR$..OWJX #" '3'P )Q!R$..H3'QP
+M @ )Q" @DSN (3_^$Y>3G5.5O_X2-< A"XN @@!TQ\ "<0<A#CJ$Q\
+M< ( "<0@(),[@"$__A.7DYU3E;_Y$C7,/ H;@ (."P GX ? !+[ &>@ Z
+M+@ .< P!"@ 8"0O!R\%< P%2\ 3KD 'L@3^\ #"X ,#S__\!'.L!R$.*G
+M4H:\A&782H=G)DOL 8J!N.%V\4O!TZY ![IEA/+@ P//__P$<ZP%*&<A#B
+MIV;D.48 DSN,/#_Y$Y>3G5.5O_D2-< ^"!N @^* ">@!\ #8N Y#Z &
+M> X!V 8?@ ^$>>OWH4P//__P$<RP'(0XJ\J!U*&O(1EY$J%9PPP//__P$4Q
+M@&H&4H8Q1@ "3.X ^/_D3EY.=4Y6_^A(UP#T(FX "'P >@ Z*0 "4X5K.%Q)
+M+@EP # N YX$)B XX7:AR)%*@=^ #X1Z:]T$.6NWH8@!W(0XJ@R@ *' #_
+M_RP'54FSQ63>(&X $#"&3.X ]/_H3EY.=4Y6_^A(US#@?@!\ "AN A+[ &
+M>@ Z+@ .8"0O!R\%< P%2\ 3KD 'JH3^\ #"X ,#S__\!'.L!R$.*G4H9P
+M # L *\@&722H=G)DOL 8J!N.%V\4O!TZY ![IEA/+@ P//__P$<ZP%*&
+M<A#BIV;D.48 DSN,.#_Z$Y>3G5.5O_D2-<P^"AN @^+ "? J+@ 02^P
+M!G@ ."X #G8 -@=@)"\%+P1P # 5+P!.N0 >?A/[P ,*@ P//__P$4ZP'(0
+MXJU2AKR#9=A*A6<,,#S__\!%.8!J!E*&.48 DSN,/C_Y$Y>3G5.5O_D2-<P
+M\"AN @X+ "?@!\ $OL 9Z #HN YP # $* !@)"\'+P5P # 5+P!.N0
+M>R!/[P ,+@ P//__P$<ZP'(0XJ]2AKR$9=A*AV<F2^P !BH&XX7;Q2\'3KD
+M 'NF6$\N # \___ 1SK 4H9R$.*O9N0Y1@ "3.XP\/_D3EY.=4Y6_]A(USC
+M?@,B;@ (2^D #'P,+4;__-O&8 13AUE-2I5G^"9N Q*AVU 0>D #$*N__0@
+M!^. D*[_]"U __@J2"P'Y8;<B" N__A)\PH&(!4"@ __\X@" =<A#BJ#E
+M )5KO_XN\9CW..'5(<W1P "2FL !F8H.'P 3I\ )@#D'K 8QL]@&V/Y2
+M3%1-( QR #(K *P@67F4VL B I A2@'( ,BL NF)D($@;@ 0((!":P $
+M3.XXP/_83EY.=4Y6_^Q(US#@? H;@ (+BX #$OL 9@("\'< P%2\ 3KD
+M 'MN4$\N # \___ 1SK <A#BKU*&< P+ "O(!EUDJ'9R9+[ &*@;CA=O%
+M+P=.N0 >Z983RX ,#S__\!'.L!2AG(0XJ]FY#E& ),[C#@_^Q.7DYU3E;_
+M\$C7,, H;@ (*FX #$'L 8L"' ,"P B!&,# *_@* #__X#\)Q!(0#M
+M 9P # L (R+0 &LG *_F8(.WP 0 "8" [? " )P # L (@1C P"OX"
+M@ __^ _"<0.T "'X /BP E6':QSCA]Z&($=P # 0+P!(54ZY !_4%!/
+M58>^AF3H?@!@$$*G2%5.N0 ?U!03WP0WH8P+ $2,!\$)"&OH!OXC L 1(
+MP+"';QHP+ $2,"0AP* #__R\ 2%5.N0 >]103T)M 1,[C# __!.7DYU
+M !.5O_P,"X $G( 2D!G$"!N PB;@ (,MA20;) 9?A.7DYU3E;__"Z-*FX
+M"$A53KD # >6$\J;O_\3EY.=4Y6_V C[@ ( ( 1"\N Q(> O2'D @K>
+M2'D @JT2&[_8$ZY "*\$_O !1(;O]@3KD (S@6$].N0 C!!.7DYU3E;_
+M:$C7//PJ;@ (*"X %$)N__XM3?_X2H1M"G[_+4?_]& /1$A$*N__1@ #J
+M/7P "O_R/7D G9._^P]>0 "BM#_[CUY (PSO_P+7P G90_^ M? "BM+_
+MY"U\ (PT/_H0J[_U$*N_]A"KO_<+7P G9V_\@M? "H=;_S"U\ )V"/_0
+M( 12@&H"5H#D@%2 /4#_QF ) ]? "__(]>0 "=BS_[#UY )VFO_N/7D
+M @M4__ M? "=B[_X"U\ )VG/_D+7P @M6_^@M? "=CC_R"U\ *)8O_,
+M+7P C"0_] M? "=D3_U"U\ **&O_8+7P C"P_]P@!%* :@1^#]"'Z(!4
+M@#U _\9@%" N Q^ K"'9P#_#GX*L(=G /]T+"X $$'N_^PN"$'N_[@J"$'N
+M_^Q<2"@(($=P # 0(@9,0! ($4P@"!'< P$$Q 8 94A52'OH1EWGX"+4?_
+MM'@$0?9(N"@(8 P@1$I09@Q3KO^T581*KO^T;.Y*AF\R+P9P # N_[PO '
+M,"[_NB\ < P+O^X+P!(>0 ""N1.N0 BJ @;@ 8?@$@AV !78\+0 "0>[_
+MN"X(0>[_R"H(0>[_N%Q(* @@1W ,! @12!00? * ")'< P$2)%(E%#\0H
+M,"D I!0W$!4AUB%OH1EU+QN_\9D!#U&_\:\56(((&X &""-8'!X #@&!(0
+M $ XXP&A @8O!$ZY O"%A/* !F"B!N !A"D& !/(@;@ 8((1P # M
+M (O $AM 8@;@ 8(!!<@"\ 3KD ("P3^\ #"!N !@@4#%M ( B!N !@@
+M4#%M 0 !"!N !@J4#J&0J[_P$JN_[1K 1&< P+O_R+4#_D' ,"[_QBU
+M_Z!![O_@+4C_F$?N_[A%[O_(0>[_U"U(_Y1*4V< _AP # 3(%(P, H" H
+M /__<@ R$R!2,C : *! #__Y"!+4#_L' ,"T BU _ZQ*KO_T;"Q@.C M
+M 1(P$2 :@1^#]"'Z( M0/_T8"0P+0 $2,!$@&H"5H#D@"U __1@$" N_Y!^
+M K"'9\Q^"K"'9]P,;@ "__)F*G ,!,@;O^4(%!!\ H ,!#1;O_^< P$R!N
+M_Y0@4$'P"@ P$.E(T6T ! RN ?^P9UP,K@ '_K&=F("[_D'X"L(=G
+M #0?@JPAV< ,Y@ #0< P$R\ 2%5.N0 ?@103V Q1"IW ,!,@;O^8
+M(%!!\ H < P$"\ 2%5.N0 ?9A/[P ,8 "[B N_Y!^ K"'9]!^"K"'9[9@
+M +:/"T !B\N_[!P # 3(%(P, H H /__(&[_F"!02' * $AM 9.N0
+M@+!/[P ,.V[_L@ "("[_D'X"L(=G''X*L(=F *2< P!B\ 2%5.N0 ?190
+M3V GY"IW , 8O $A53KD 'V83^\ #& F9";O^J8 8]?"<0_ZH@+O^L
+ML*[_L&4$("[_L%: D6[_JB@N_ZS8KO^P0?5*!D)H__XL!%6&:P !M' ,"[_
+M_B(N__22@"U!_YPV!"0N_ZQ3@B@&XX0N!IZN_[!2ARH"< P$R!2,# * *
+M #__RAN_Y@H5$GT"@"\@FP"*@9*AVP -)^ & ,Q(;O^D( :0A4AT"@!(
+M=7H&FH=2A0*% #__R\%3KD 'C.3^\ $$IN_ZAG&$'U2 9(: $< P+O^H
+M+P!.N0 >D!03TIN_Z9G "20?5(!DAH )P # N_Z8O $ZY !Z0%!/8'9(
+M;O^D( :0A4AT"@!(=7H&FH=2A0*% #__R\%3KD 'E(3^\ $$IN_ZAG&$'U
+M2 9(: $< P+O^H+P!.N0 >FQ03TIN_Z9G+$'U2 9(: "< P+O^F+P!.
+MN0 >FQ03V 2("[_D'("L(%G /\L<@JP@6>*2?5(!CBN_Z0^ W , -!]0H&
+M2FC__F8$/@-31[YN_\9C#' , >0KO^@.@!@ GH ("[_P+"N_[1F0"X&5(=P
+M # %OH!B-# L *P;O^J8BIP # L )R #(4@(%G'#H'2J[_]&T&OJ[_G&X.
+M< P!0!U $*!CP%8 Q3AE6$2H9J /YL? @+O^LT*[_L#M )P # M )!
+M]0H&2FC__F8(4VT F "4D9P # &0?4*!BX(2E!G\$I&9T)X #@&< P+0 "
+MD(0O "\'2&T !DZY " L$_O R=;0 "("[_D'X"L(=G"'X*L(=G"& .( 3I
+MB& $( 3EB-%M 12KO_ 5$M8KO^46$I8KO^8("[_P+"N_[1O /OJ("[_^+"-
+M9U(@0# M *P4&)((&[_^#%M ( B!N__@Q;0 $ 1P # M (O $AM 8@
+M+O_X7( O $ZY " L$_O P@;@ 8+Q!.N0 @-)83R!N !@@KO_X3.X\_/]H
+M3EY.=0 3E;]R$C7,. L+@ ,+7D K,\__1^ 2U'__@M1O_\2&[]W$AN_>!(
+M;O_T+RX "$ZY !RU"!N !0@KOWD*FX $"HN !@@+OW@?@6PAV)\,#L*!D[[
+M ( +@ , P 1@!8 %@@+OWHT(8J@$J&;U9+[OWL*$5!]FD@_>PN"!C=N\=E
+M^F! ?@$JATJ&;S@J12A&V<4:_ PN\QE^& H0I4N.0 ""RAR"+R!;0Q\"& *
+M0I4N.0 ""R1\ RI'*$7>AAC=N\=E^B!%0C!H " %3.XPX/W(3EY.=4Y6_<Q(
+MUR#@+"X #"UY *S//_T0J[_^"U&__Q(;OW<2&[]X$AN__0O+@ (3KD '+4
+M(&X %""N_>0J+@ 8+BX $" N_>!R!;"!8@ GC ["@9.^P " $0 # , '
+MB@"*2H9M#"!'("[_\)"&((!@!B!'(*[_\'X 2^[]["P%8 @@1A"=4H=2AKZN
+M__!M\B!%T>[_\$(08% @1T*0($40O P.GP ;R-;Q1^ =Z%W(4@1Q"\ #!2
+M35*'OH9E\D(U6 !@)"!'0I!^"+R'; @J/ ""SE@$BH\ (+/6 *($="D"H\
+M (+1B %3.X@X/W,3EY.=4Y6_=PM>0 "LSS_]'(!+4'_^"UN S__$AN_=Q(
+M;OW@2&[_]"\N A.N0 <M1/[P 0+RX %"\N !!(;OW@+RX #$ZY !CV" N
+M !1.7DYU $[Y FX$AX -.0&7R3G5.5O_\+H=![@ ,+@@P.0 " L (
+M !9AHP.0 " L ( (9PH >0 " ("P& $</]@$DAY ("L"\'+RX "$ZY
+M ]X"XN__Q.7DYU $Y6_^@M?'______["UN C_\"UN__#_]#U\ $+_
+M_$AN_^Q(;@ 0+RX #$ZY ]X"!N__!"$" N A.7DYU !.^0 )N!(> %
+M3D!E\DYU(F\ !"!O @@+P ,;TPB"9*(; !$2!LH!M !$,@@( 0 9P02
+MV%. (@D( 0 9AXB .2(8 (BV%'(__Q"0%. 9/0@ 0* V "$MA1R/_\
+M0D!3@&3T("\ !$YUL\AN%& "$MA1R/_\0D!3@&3T("\ !$YUT<#3P& "$R!1
+MR/_\0D!3@&3T("\ !$YU(&\ !")O @@"'+_2AA7R?_\9@#_^%.(<O\0V5?)
+M__QF /_X3G4 "!O 0B;P (( AR_Q#95\G__&8 __A.=4Y6__PNAT*G2'@
+M!DZY "-4%!/+@!G$"\'2'@ !DZY "-4%!/8!A2N0 ""TP,N0 $ @M,
+M9@9.N0 )O!(> &3KD (U&+P!.N0 C>Y03RXN__Q.7DYU $Y6__1(
+MUS" *GD @ 2HUG'"AN A*E6<4+QU(5$ZY ",JE!/+@!G[" '8 )P $SN
+M,(#_]$Y>3G5.5O_T(&X #")N @2&+(19@H,&0 ]9O0@"& 22A%F# PH #W_
+M_V8$( A@ G 3EY.=0 !.5@ 2'D @+$3KD ">46$\O+@ (3KD (WX
+M6$].7DYU 3E;_\"Z-(&X #")N @J2& ($!6P$6<&4DU*%6;T2A5G
+M!" )8 9*&6;D< J;O_P3EY.=0 !.^0 )N!(> 43D!E\DYU3E;_W$C7
+M,( N+@ (+6X #/_T( ?E@"I !H J],*$ M5/_XV_P J_,+57__$AN_^A(
+M;O_T+P=.N0 -Z!/[P ,2H!K0" N__BPKO_L9@H@+O_\L*[_\&<P+6[_[/_X
+M**[_^" N__!R^\"!+4#__"JN__Q"ITAN__0O!TZY WH$J ; 1P_V $("[_
+MZ$SN,(#_W$Y>3G5.^0 )N!(> E3D!E\DYU3E;_V$C7, H;@ (2^[_X$J,
+M9R1*%&<@*HQ(5$ZY !0D%A/*T !%!-*KP J)L<@(K00 $4$T@.0 " $2P
+MN0 "H_!D$B Y ( 1$'Y *BA"AP# !@!BA\ *B;RJ,+Q5.N0 4)!83RM
+M 1032J\ *B?7(!*T$ !$'N_^ @#9"(YH!2@"\ 2&[_X$AX ).N0 CJ9,
+M[C _]A.7DYU 3OD ";@2'@ >4Y 9?).=0
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M $ H(RE-8W)T,2YS(#$N-B X."\P,B\P."!#;W!Y
+M<B Q.3@U(%-U;B!-:6-R;P " $
+M "
+M !D !
+M !I;G-E<G0Z(&)A9"!B
+M;&]C:R!S:7IE("@E9"D@870@)2-X"@!B;&]C:W-I>F4],"!A=" E(W@* &)L
+M;V-K<VEZ93TP(&%T("4C> H 9G)E93H@:6QL96=A;"!A9&1R97-S("@E(W@I
+M"@!F<F5E.B!B860@8FQO8VL@<VEZ92 H)60I(&%T("4C> H 9G)E93H@8FQO
+M8VMS("4C>"P@)2-X(&]V97)L87 * &9R964Z(&)L;V-K("4C>"!W87,@86QR
+M96%D>2!F<F5E"@!F<F5E.B!B;&]C:R E(W@@=V%S(&%L<F5A9'D@9G)E90H
+M<F5A;&QO8SH@:6QL96=A;"!A9&1R97-S("@E(W@I"@!R96%L;&]C.B!B860@
+M8FQO8VL@<VEZ92 H)60I(&%T("4C> H <F5A;&QO8SH@8F%D(&)L;V-K<VEZ
+M92@E9"D@870@)2-X"@!R96%L;&]C.B!B860@8FQO8VL@<VEZ92 H)60I(&%T
+M("4C> H <F5A;&QO8SH@8FQO8VL@)2-X('-T<F%D9&QE<R!F<F5E(&)L;V-K
+M(&)O=6YD87)Y"@!G971F<F5E:&1R.B!O=70@;V8@;65M;W)Y JVL
+M 0 " 0
+M 8"
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M K-, "!:0 @6K (%O "!6, @5O (%@@ "
+M!8X "T *P @ #!X #!8 "T *P @ "T *P @ "T *P @ # Q,C,T-38W
+M.#DP ",@*RTN,#$R,S0U-C<X.6A,) P,3(S-#4V-S@Y, C("LM+C Q,C,T
+M-38W.#EH) *&YU;&PI # Q,C,T-38W.#EA8F-D968 ,#$R,S0U-C<X
+M.4%"0T1%1@ (" @(" @(" @*"@H*"@@(" @(" @
+M(" @(" @(" @(""($! 0$! 0$! 0$! 0$! 01$1$1$1$1$1$1! 0$! 0$!!!
+M04%!04$! 0$! 0$! 0$! 0$! 0$! 0$! 1 0$! 0$$)"0D)"0@(" @(" @("
+M @(" @(" @(" @("$! 0$"
+M
+M
+M
+M ! @,$!08'" D*"PP-#@\0$1(3%!46%Q@9&AL<'1X?("$B(R0E)B<H*2HK
+M+"TN+S Q,C,T-38W.#DZ.SP]/C] 86)C9&5F9VAI:FML;6YO<'%R<W1U=G=X
+M>7I;7%U>7V!!0D-$149'2$E*2TQ-3D]045)35%565UA96GM\?7Y_
+M
+M
+M
+M ! (*# ""@X @H/ (*$ ""A$ @H2 (*$P ""A0 @H5 (*
+M%G]_?W]_?W]_ ((% "\ +P O $Q#7U1)344 3$%.1TE.
+M1D\ 3$-?0T],3$%410!,0U]-15-304=%4P!,0U]#5%E010!,0U].54U%4DE#
+M !,0U]-3TY%5$%260 3$%.1P!,0U]D969A=6QT $, +V5T8R]L;V-A;&4O
+M "\ +W5S<B]S:&%R92]L:6(O;&]C86QE+P O "YC:0!*86X*1F5B"DUA<@I!
+M<'(*36%Y"DIU;@I*=6P*075G"E-E< I/8W0*3F]V"D1E8PI*86YU87)Y"D9E
+M8G)U87)Y"DUA<F-H"D%P<FEL"DUA>0I*=6YE"DIU;'D*075G=7-T"E-E<'1E
+M;6)E<@I/8W1O8F5R"DYO=F5M8F5R"D1E8V5M8F5R %-U;@I-;VX*5'5E"E=E
+M9 I4:'4*1G)I"E-A= I3=6YD87D*36]N9&%Y"E1U97-D87D*5V5D;F5S9&%Y
+M"E1H=7)S9&%Y"D9R:61A>0I3871U<F1A>0 E2#HE33HE4PHE;2\E9"\E>0HE
+M82 E8B E92 E5" E6B E60I!30I030HE02P@)4(@)64L("59"@!# &1E9F%U
+M;'0 0P!Y97, ;F\ +@ ""B0 @HH3F%. $EN
+M9FEN:71Y ""D0 @I- (*40 !);F9I;FET>0!);F8 3F%.
+M @8FEN87)Y(&5X<&]N96YT("5D( @8FEN87)Y(&5X<&]N96YT("5D
+M( @9&5C:6UA;"!E>'!O;F5N=" E9" (&1E8VEM86P@97AP;VYE;G0@)60@
+M (&QI8F,@8F%S92!C;VYV97)S:6]N(&9I;&4@)7,@;&EN92 E9#H@)7,
+M7UA8+F, "B!?=&EM97-?<&]W97(@9F%I;&5D(&1U92!T;R!E>'!O;F5N=" E
+M9" E9" E9"!L969T;W9E<CH@)60@"@ ""RP @LP3F%. $EN9FEN:71Y
+M $EN9@!);F9I;FET>0!.84X 3L %A &>P"AK2 >' T 5S
+M.]L2+C^CGYWB8;+<XBIC!+R4)M6;87 EEL+C=;D4"RPA'QUJ8+@3.Z*)TGUS
+M8/'7W\;*WRL&:8<W)+@&[6:3;NL92=MODXV"=5YTFC;%;K<Q-I!"Q<@H>8XD
+MK@[>A,$;D\-GP5?#RZ;WM9#@[BPV3-FR7PT0EM1=L+=XT&,&92PRFI$L>;6R
+M23$ _B$HRQ&O9':DX48 (PEW4QW. $5WCL+>K<\"+?2%BI@W<X5[><Z4BIP6
+MYI'3M,T-X$,.74P^^_E4^MR=*>L9B2FOG?1H?'WU>D^'D0)E_IK=4.<3RO05
+M'9*K:&*D@&AC4$6S25MP*,WQ+QV0DT,>20"BWB80PD!J% P4GO"^;T@!R\"#
+M05[^X&C]_&:B0\"Z)J&Y]>9[+VJ]$ETM/?JAN2<,Q@#=(0#0_6;A>O&?_9ZW
+MOPW0T5#_.K06G=.1.$O6I.3T03_N!9(H-;]4CSYX']Y32L+\QM,I!/!J_2AA
+M-;L66 \>9'95LV0ON9>1WH]Q%":^I*_]!B92R719S%5#)/4S4;\BA&/'9)"K
+M8O0% -R+,2B^<IQ3JS4C CRJ\S]'J!H!3(FNR>6CGMS+X'^1,JU\!=WQK#60
+M'N&*M]#Y6 S,%6;E*> "G3EN0U1-, U\R@%F(;Y, =L9'$$4F\,AT*2%7H [
+MDQ+_3WH/A4BV2."13SAULF_&4P%X<9VUK*0@ HU=Y&(*#J^*(FX ;4;0'6&[
+M0>(^DIS5APH1(U18B6/!*@Q*CQM<"(.ASA839E]&2<10EL4->>Z[44>KY7"B
+M,Y\>Z<]#$82]V$,*B>$2E\ 6J??K%A;,>2=7SY[HUH, #)F!<'U,4"T9^@_-
+M;S8TYBE<@@?"WIU'3%+9@]'-0\?J"MY+EA?=D371>@OH!;79K<BI1G/2L46&
+M@N?&@+:!K^OC!FF=7OBRQ*>4]JQ P"WWL\\:A;CQ UJJK&4Q&^MRV&\(U$W+
+MM>Q^]O4>1<J,&RADHG,V4 :SB(!!:31)0=EU/-]2TGZY/J;LI*U))A3O;NA5
+MJ7C=8;U9.8QB=/6;0U#97)QZ1M$!C<*8:^KK.&+:E-XI[(J0FK<_)?/*&ZYK
+M:,/NHXFWLZJ[#X_[S-'K;AT#:Z8JY!=':B*=LN,JFXY\4<?#[_?$5VF)?U7U
+MXZ%KIYSK">@[^L\N?U<@9JMI&NH0")HU#5@WE_CDY4HBIV[CJ%9N=,+*K%;F
+M#VX.$S8X.1)S8O775'BZY-MS-54* ?!8FE#:]GIRDZ1C19A<ZZC."%>@R^HD
+MNB.2PXCB0C'00;J'%U#N3,EP9/G<N>]I@=#7V\1-BMZW6DI..F:4%$@T2L<Q
+M:"[%'CP^2^!V%CU2["U&/@SBCGGV-^#J(IPB!.84.63@M*6O6+=\:8GJI0^^
+MOM_A ;9^M8JN\WIWQJYBC&N_LK,_D2MLJ"=:$+D6< >RNFU)<Z[AJ<1A$OF
+MX9Q'@Y'U)C)0'>5*2J2"ZW:\.5_5'KD_TF_HV>\;#D-BFY2=J Q*)D)QC"=K
+M?-(J;0"N)N!UII3R)SII]MQ<G^>X"I8>9WD]UL4<XQ[1X6\=AQDNA-4M1ALF
+M)2O\#^OF:)#(#1+B=N$A:)VA?.Z&#*FNY;BM84&%%TCQ;.L7RT"G;?8@K/&@
+M_20K4L9922+/W]JDZR"Q45/_.L?( 5+P#G!9>G/NCW7U\=@AL).,^?!,1IMS
+M1V;:47\4< .NS$\%,1P!0!=;UVUB;-69&X^5<FC. GN%YTK+$*:0%ANY.AZN
+M*OKEQ^BRD%56 ^;OHYI0.P-MQHN2NI;6JZF]L-D_+;?*&-Q0T#E'C>26EG!T
+MTNK:K1JV!$K>\JO-8CKS[DD3MUBM.:-)0[EL>4$W=*2N5= -+:]SWVNY:F4D
+M[I)T>0 V_ -L!> !;=R=)QT0<FFD^A2.^) NA=^K E*NW(\PV_7P:\2NF"R
+MGP.XAR'L)DJ!$E\/Z$Z/UL,OD(!D;2?"!!/@#M_#)!2P#9E3NG^$\>TXBCUL
+M*6;Y#2 +X/F+^XOQU)4H*N8?M5,<\.B<W!53K4KAGG*&7G^#OEP)S FCE&[\
+M;.5(LX8R><]I\\H@0#_E#1;X:HE,#GGW8HS9TZ4+%3Y!4>K?W+/&RP9N1,'!
+M4XR=:-DEK1.G4@&._[-QLHT5Y0/9?3$><V$_[XUR;$Q$!$> -@-.8FIO SL/
+MVJ(83Q?)I 0ZGE52J(=]4$JKU.>)A=G8M@"!+P<^M=7]*J*XK^<(,P, []\U
+M7@^F9$R.2E&GB".>L0PQ=C?<7-</C_V@7-V[VN_IK^)ZV2+X-(O$'2.M!D9R
+M8T%OSB]E@FI"^\ ?*(S-_XM'<1H?Y%L*B/T#YM\N>CXR!SDU@$DAROKK=(%
+M-3*$*P.[U<IX(:?)',_P%]C!U#?ET'6R.&UJ]PGD[,XB/&I_44EQ]"GZ:V5*
+M2E-+"IO)LC6/1X']WO&[<YEUU)#.P_I%/_P[8U4A=Z:BHMIBG)51Y/F0]+<2
+MH><PI*#QMFB-@N.4&ICMC0VWI)0)H%$71$\GS#NF-[ID">,9XDL(G1DKDC<P
+M=>7=@@5 O3;W%KQ D>6<>U'-_DHPQ@>VC%&P$]2\V5?(6@'[)LNM5ZH!B&AT
+MJ#$N5#@4]\H\#CFT;_ZAV0>VTVI"EL:VY-85%D3^W2[0N<G#(GK%\VL7YGY[
+M[@O?.WD'!7?!\J9\W"R13#^TT<=2^1;),AI!;\2K,)WP;E%K.+)&5K4F<9HZ
+M)H>:N9\HEL6@*6_(@"92XR%O]BS>-P=^3A$E1"DZJX/%MY;I\;VX@^M,\/,T
+M2.MTFQV1+"U4OBG!VHEQJL[ ^W*L>$$1WP2IJF&6\$0(&@\<0&LS9R:C&!FF
+M94KTLTE:TQ!V"0O"Y!7W6'::B+A,2C+@RCO4;"5'#_(NN2Y;L9]V0YF6G]@B
+MZF.#X+'-'.+I7NA>6FH\?%[;#+?0LJ\W(- 7 *2A +5&Y[KON<DX48B"0*-X
+MJT"Y=419VF0(N-C,D)S*15>LDCP<[ MQX;T]X? 'BG;Q.8244>Z<AGXO7F6+
+M)Y%5*I ^^Q?!$"-S5 =0(2YM%I/57/[TK055&7F;([.[ZJTD@L=2H?$FA:Y-
+M5][\>#T='0#P31(26HJ$W2%&P*/B!(!_0YO>Y&XX:J'NF8UGZ7ZN,V[>UOHP
+MY.X\#;+&;Y4!U'?V_E#7L3@G\@S&8:+>0WKC1XI^<,J^@BOV(>:#="EQD[^!
+M$+IY3#M=['4DI7T3Q$GO!F!LAW.TN*7#T*-\?)8[G(;OU$I<=3Q;L@X@31LD
+M?VKL7.?1DI(YYVB4]*!9L& B%<E8AMV.QC_H;24=$(D<UBK]6S:M$QK2B],@
+MBW0J+F@7!/?!&620TF)YRCI' ZEUG]D Y5U#AI#9B'HF$6$ALQ&&)*C86#<7
+M9_T80?[&O$= ]S$3J,;^K%&7A8]3R,,B8C2.W"Y_"/ 'BZ;W<)$6Q<\66I0W
+M[!K)AZE)^LC\@>'UM;B-X:Z3%UC2KX >2'=WO$/8=@M%PW\9JYZN1*B:VG<;
+MSJW) 11"<DS#Z4638#5,^1M DLA!79G(R9PGDT"8UNVQ5YE2*R6+_4'7-$6Z
+M2]71DO&=6#@V]DE;H;AQ[%J[N:IB(Q+0)R"!+0OUQP8[U5>&$]_)#\L25'?2
+MI-U94$76?330G?@7)N1" !+&[1]_BJH]Y<J?'7=0*6S(OTQ?O.Z_M:J(>B<@
+M[R<)A4BLX"+I'6::?#I0U-"U_#Y0)@EYHI'A7O.8NQT CH5\%6F\H= Y,7>1
+MU+<5 )#.&HGS,PNB3?G.*")GBS+T[2-[F$[Z*PP7S'F5MR^? C/U@>$WKC5^
+M-V:LDTHZ*LFDW@M@[KA2#K9LK_$UW)1@[L,+:-*65E>VQXMK9Z;G+QGEE8R<
+MS80)L!F>AO=()C280I"P@URD+1VB&F1I\,;[1=&%EJA(Y#6-[U:\DF4 "7,!
+M) 6LD&A$[:Y\9W&B8ON,6E%L'VM%/65',^A_"1^^QE>OICP!)%O\Z1V\8+QS
+MY33SQK"M9[O3Y,VF/.\4^]TNTJ<FR\ZGR,\GT_Y//B) 5T7OI?D>-P#KUO4;
+M'.IBAVV4MOZWA"&A(W:#2=$!B'* R'=]@!2J@SI[16_?<S *\OU$VB7(>\OV
+M\,)&GET9 E7U=WLR_BA9?* ,9#4VLR*TW2C@.[U&&42 \5;?CY68L5R5/$;+
+M<08))I/Y*F9]7Q-[VNIE@",[LR(87+0IL4-)>F8_Q&I2Y\-K,EW_*!<EQ,^K
+M?Z03.V43Y:!-[@&G82T"-R$[E&R0? @*NW_O88<NJLINA)WNI=1 [\&NH,=_
+MS1R/@(R>?-U^D)93=5>:YR_OT&8+RFFPS#X0D0FE,2_?>!6CZ)+?O\C4$0_'
+M^O;XIW_@NQ79D L,EI .(H+EV<8P5C@+0_LV>&(J Q]P:TU^? $?97HBY%AN
+MI(O5GY2$TQZ$Z@F_44\S[^R71GV5%FJ\6_3NA49CHE1+<%+51[,018TCC3OV
+MB@2:$>+@+2FX_+ /)[VYA0BZ]2SG3E?J7R)10;.[W!2;F@OSVRYHV<&=LE;U
+M6K:1Y6/[K*>[.")[A%8I8'3%YC'9!_0^#=1P>[+,KCEW5UU<NL*\3Y2>LZG6
+MIZ6XDE-G2?HSG T^ ;QY1NF"87I<MIGA>)<%8XP+*&S?XHA]TIM?:Q?"&3'F
+MFP_3"B*3^DRQ(G;H$UJK,^C$9UJ)K1B$)HI,ED*;)W6GZS,H_A$MZNL4G\T@
+M?<V^A,CJ\%T'_'DJ,S:!HQ7-@]HV3&ES5P?;[9ZT#2Z-0GDB]!APJT)VI>MX
+M87WD+N<OV#[B]FA9(5./,??^-0P3 H@L^]!#FJF%E" ]]N>)#2?*Y5LBHO:V
+MK452U;-*>D*T=LX(S/=9+EDN-'D4]BTO $OU1PQJWUH*._0-H[9CR2./\(&(
+M,27W6-V5!QVKN)P]232^I:-R7C@^$M:XU]KQ/8"9)2'864C7O"UGI%E2"5?K
+MC0_*9"@)]4_^R:*CUSX]PNNCF,9Y';4ZS:Z4:$,1F-X2T.,"P,JA[RQR#L:I
+M& 5HI ?#12&@G!S)6S_11$*VT^+=NXY/80"(0TK$RP9,3@'MS%\S':P^TK,V
+M=U+-14TR"4*[NP>L>(Q2GU(3Z"'H)#ZN2)9HCDC(8;GP$?$1K@"5YZ*LBZ^D
+M8?:3Z#5.]D_C?I0FBP(I: V(SX)NT42Y#PQS*>G$:Q!J0-LI^FZ\S,0$39VZ
+M#=C6]E+X33K4=Z+Y<-S&M.2;06!SCD3:F8S?]MWMV,_@0,9217J"?.&<OO=W
+M*CB<Y'6UJT@IB94%-[[1=(R<'-%Y6#=8; @@<"39O8M(%8MDZ?FS7&&,.]T(
+M*F8@9 I[C7^4E99:TD6HOEW%FJ!\N45[X(3A35'U.;%"K$8B#'/9*SHA*E25
+M_]G5((BSLJYSQ[FQ?&?&L\X957F3;<6#S6%-D,DX'@SDM%1J^!PSWRCF9619
+M"CS'DO&ZH3=VZ@>5 +PEI_L'2CRK<M3W8!5EM.,<_/<Z)BU"16#6Z6;81Z@U
+MGPV;%WQQ-EHJ421FM62C@H.]"H6\;3YEF;<%:>P_']^/EJJ._]MV\(Z%-L<_
+M =TU*QTYA]UW[R@G(O'D0H_EO<?I&UHVR8<A+XHYV$#.IRK4UEH'GK3A(\$X
+MN/#=!HW]J36;'HU&PB:HCL6\RSHP$CHT8(]_,5NMW"OC.705]8P7&G9VD$<:
+M^"E/FFBK?[!%L@-1DRF2PQ3"\K:%@P0\0]827"(9%H4^;V%@8-?$YZ1&MQ^'
+M 5>VG*^;KJ^T^;'._ /1M<$RWY=I*_E)PTX 4KPBP(",S<X"U^[+C8\S;_C3
+M^I /'IV"]9?HJG,-+7N3F.Q/&.]BON*H%4R.B7$\BW44R<*U$$0L:L&A4^[
+MH@OW$:-2EB/XLYP#U=49NS?J"YDS'Q;PU[';,_19K(#"=:5@@^MV"GHC#\&G
+MSE1LH5>'5P<2<.6B3IT1+?D1ZE:F9X865W>P++PPE50H"T3V&0A,B[?'9VU"
+M-)#K_<IJY*>ZZHZJ>W[0%,W3":$E:>'=AZ,Y\!;A<V#3F\)TN?^XG76P\IOB
+M2WGVEGAEB@[O/6M HT.9PC&H6\F:H--<:H7(--]5YZI,9TKC,%R/#=B'VD9_
+MLS5';E\CQ]9H]^049]:ZPJ$3&Y(H]Y^$RFI/C\XG%FB"$.N^[F2!:59L"?F?
+MCL$2=?:@]GRB"-Q;3V;[95]B[U-N$PC0=N/XX.6;!%:\.&Z;0 HJ%M'F%X&Y
+M07\GX_ W(.J$0P"%7J0>0@SUF6*?.FT\@83>X9/#29._1K,NYX8%"^BPT7\<
+M&=NV4Y,"XA$76-4[3URQQX+;Q@A#-\$;^[7GRG/#J2<GVHT ]02'0HW(3JS"
+MR<"+D6.E$3,[K>9("O!_+9EG),]AF)CDWP%:;POVQH[GFP-CSVT;MTR;B].@
+M9"7*NV$Q 9?:<>TL^*$P^%UQ\,]O5 &85X.ETWLES)0<T53#81ESI)()Y(V\
+ME]"MU!%RV.O&0SR4 ))O5I>'5+AH_<NEUAMR?%_04/Y$ ,!&9UM$ ?TU$&B9
+M1OW3=.&#6XJ#D#3);X#P!EP8A]1L=;47,$+SS>^VXZ=EHQA[. 6VX@&L[12J
+M,=O8S)N8:EF\\/'BG/"=3A1F"ZEHZU634>+WIM8O[Z0LQFD*JS+$$>J"P_ZY
+MA\Q!+L.G:2#!:#Q<:2B+UM2>#V1\54#B<DTM2VMGX(4EY.T:>ERIR#QPJA2P
+M,V:ZS0-/0<#M7IWK#P%POT[H!'(.D5F M)J#]*%!FV&*-AF6V/VO ];(H>Q.
+M.;^4.[F8QG#;,>,F+C '4@"/&I\!\<HCVF.O5KO$/"EU%;]KB31- QZ<D]I]
+M<^2DMKZMX>(6/>\/856*1M<I;8PJM@'JKWJQ+^RM53 83^W6VHL]%$<:,6RW
+MF8.S!O@I&@RR6>+0KS+E.14X]O_8Q_$A%F@Y]V+_D7Z=Q^!]/-+WZNM$]="?
+M'_V'+O#X-AJ*CVP#D(WP.]CFVZ"B@.J( UFE/Y4,E,6NST#AU1"61S>:'WQY
+M@?A&'&5Y79!+I<$V)IVPD/]E /WY4$6.!?N-13"6K\*-Z+Y5]9WX2^3)"T)R
+MCD[EYPF4"H>N)+/Q>)GK=]:7A:A8I^2QO3@ZJFSO7%7V2Q&V-$+)DYU!S7P"
+ML\GS/:I4W#/>VAFMDGB-R%<7"2>CY>B4U3?619>[ &[I/A)1P/8*I]+>.@/3
+M/4&Z.9@*C/SA5OQ7@V%NLHAFX'G"R4A@U1C>S!QL*[[A'ED%/I$G2UK%5+&B
+M-+8S88&L<[\L\[H;YR2I*R;^%.(6WTBXU+&%"K[DYB6#I=9WYLM;<A9'')SM
+M9# 7?O YWH-EP.%[(H;R>"TR,;V,NGK*#P"WBX$= T#,0>RMG/LIPZ_=X(>*
+M&*QP+(])/% YDL"4/H^']<*\O-A[ P1"UZHL&)*?N)63G]E0R+Q/I.F69P+:
+M"P96[ZB!HWCCUEQV.P44N)$CKX##OJ\.!3EYRWL?T'E ):H+77VQO8,&.-2C
+M*A318 N-0S/D9BII8^1PUU-J$8LY3/9UY&&<Z.O "(P]SSUHE[^FK[F;BV.@
+M@&;%;OB/]<]]7@%.4JKRXYS(,T1L72:4#%US\6PB=Q27#Q*>O?(RH6B'T!89
+M<D$@1A@KI=0E2BM-Q/+6UUW]HX9]2Z^="%A:,FA)K]KCQ;TAQQ,RW-/,[$7T
+ME+0E/5X2+VG;=<O!!7NJ;I+QN!EZ*"^8*$.B/N(, 'HA "O0%5D4A#5[]3E@
+M5/AR+=[Y^F>E&#;[Q?SZ.JXM*.*/!4*H03%^<G.BW)W5+N,EUN-4R5,3P423
+MNT(T#;J;2&^L"1S+IWG]MI4MM[*>?@(9MV;0#UMY4!,Q3O8]5*J\T!1\KG]X
+M7%:3(U D)__0HFA';GHOE*J.F ;QHCM]Y[.1\5L4*TX)HN,Z>G-NQ+[?]5Y2
+MW*0I/1BN$]U,83#7JB&CL@7F1PAH0-<0&3HB RQ>-R$ENB4[E15,@K5$74U[
+M/63;>I/1Q#S2K=HE92&BDF)<H*)CI0'SEPQEO02)*S8^<E$SDIKL0VWA ]$%
+M=BP+Z7LNI$TGPB=8I)5,2Q6(5?M/7>V@LKI=-2)C'U@D5!_]W55+^9R(*)O*
+M:+$-5(J>J1$MGW_1; Z(:,!5W,%.33]OOWB[3YSGB?N.VZ>[C8# %XTY@T.6
+M')?8$$ 9;0$H0U"X9E&"7W.MN!D:L=\KE=7< G9/4DUSPD2)U#*V)N@X:=_V
+MSG9:OS&;VX8M-WHF^B0H+6E&8ZZ<>V0E[4*K"; I-\PFZ.H65UA3"PVYI!*/
+M[X,$IF^NGS3#Q /(FTWH8 "8*68E0Z1IAHA34HNIX G_9N\PNLI+Y!,=$+PO
+M*"F9<<>'#4%-I+KM8R)]!)W5K'!\_30C-O[Q>VNS?>5[/DE/F5/CZ83&=L$#
+MR#>0*3".3T^&^;C>57SW8C[)QSD5S28'>(:I@F?2<O##2HT$7%)12?I([SO+
+M7'39@U\_J'ZU&,W.#3U4FL2U/U^I&5-%)A$4P(.$Q-_Y6>O%TQ$,!PP)NM U
+MV-@\ >)MJ4O/.5#?=OW^H@<]G]4VI7[]_?;>T8^%IE$HO(&Q"2^J\ '"2"L0
+M-)]J!B:PD=8;)>!'0!"Y RYP'VO^Q4NGWW8/-)0J9/':ER,QMZ_RT673">;X
+M.;LL$[/P,-FJI5M:.+ARKA(3K%76V84\&&' ITE8P4^EQ8P;#U&^LO$0#M@>
+MB-S#!==R<"()C "J<VBX,TP_:0G!#*&O,+P0T=P'9@K'^&UU#/;YJ5;<=G3"
+M^DT(2+#-$1,YPJ'^1#K7=7[7]!Z4<EMO"WSA+*>7#[314PSVNW\4*7T=>!'3
+M-PG]Q@'/\HU/H %]K ]%2DCPN84_-T!A:$( ]6(P5.A!!U\"A?@Q0_ $6L-W
+M"GZ%RR7*5, SK)QDU;JXM@B&5H"O1'P.734M!53B#E%H"./(?4""\W8[GU^/
+M=-8 E.445",X^LU"@[RW@[VDT.<:JNN.;B^](B?Y4T&.;E"!*]#"_'E!O-'P
+M1DZ1-[H<XE '*!F .>FU20>Y0IZ-7SG)17JAN7*4-@H88.HC8^Q!5<-SJM"$
+M7HF-5M5A'9<_"^\+]>*0%^VCA'HAP,2V"R8DC"5UT,$"&[RZORG>%:&PZ8UD
+M?DO[7?$$%UT9^1C&"P;-Q5;NF7[C"HQ55R8&0SI8I]XQ4'HY!/(JH2!2DV'"
+M&95V7X?9(QL!Q(EV@=H)_=2ACLKD* )+4#3;79(]W[;Q!DZVFJ>,Y7:NJJ[,
+M6M(*<0IEW.-372+^ >,@?_W3W(OTM[&:UM1O8@RE&OT"04R/H=I$XBQT@,V
+MHFD$_WC:72]JTD\A0["ND0IX$9WQ0+^W[:_J%+9NK]ZM5Z@I>^=Z&LVB'/+7
+MX?00)8O_6+AJ.*2^MJ)H .]ZZITPD2>)&*F3O!=W[P T3V,GOX>7#*GQ.O']
+MXA,/*SY89Q@__]]MUH]'C%)0I);.@#DD$=M6!B_'F+$HZFP(0Z-H[,MS+&23
+MZ5/$)X)Y)C&"3!'!H-WKUCU*B1?Y9A L((0V4+X)BH ?M*2MQ!Z<?[,P':]*
+M$KTAFLE+N1P/F75CA7RNA1L+G4]0#QV?RQB+T"54/=80#!OW=TOD".OGS2<,
+MO'R^KM1)5H94;9T*JV28(/Q<&:-Y$@GYKW2F87)RD*ZPP2L1O$TDIT(6D]U^
+MFGK0<COKXX?HTT4<</SI&&*FMMEE'P[>*1,FSF2K>0)_)$#J:+8;?0MA^<ML
+M<3>XRO&.3$]?D**U9/.J*;Y5H1^OIM VJR8<QR3R-BUZ]#'?V2IX:/F_)> :
+M"WS_QLW7PJ>A3"@R4-58DS"X33V>I&N]NZ#EWDJL)4PF[^FZ"\':S*%+ZO_G
+M0;0*4\,7B4VHA UO_X\<3HZ_)J@-_B>E6\B*U0H6+ 6F)Z[?P^CR')J)W2&0
+MQ2".L$HW$)U6.PK!/]WH/1#4C?ICM6..<]"K*A0M :I<_01/2\T:152:D>O-
+M4P.%["F,K"AI&+,AJG=>_O'3'L:"Z3T ]@>T.!R15"N1:[6G81R]I54F5T8W
+M,U81S#?QH3^WQRV.A-S-7RG*&IB'K+5W1<.@S&- -;;)$N[U^(P6JW$*YT:_
+M/P:0>:H.!H(+FC!-EB :>:^!,GB'OA06 .^JBJ0W.;B))B57L"#0=)7:I=RH
+M[B#U/J"- =>97F?ID!^=C<"4_!>H?I$$>$&=7YI;BI1*=6'-]=LNX^2/PF#\
+MO8E+U612LUH -R^>IMGKXT'4^&EKU]?<;)K4SW(#(BR&,!1YL=3JD@&5MG"@
+M5F=MLT/J=LK @TNLK'=TZF1)5WY4;\ZQXK^5]X=:L\?@I^:@L/>R>>VHI9->
+M2Q9RNJUR3"=:@#!20S@]JKEU;+Q-<F\]%E=> Q/?B>E"#U#_T_$2A5KI-_R1
+M&T;_LCZ>-V%V1L$CKR4=53TQ)BN#]88!T#$<X%0TVV\]2%HI+6>)NDS0WV23
+MTA8TZ!_VLS.[_]:D<JA%.*A'2F'RZ_U&A "X(;_PE?V\=PHK=MG(Q6%U=^E7
+M8M'$59K_#G7 AJ)A025X )Y@)#5AE\OD65V_GXU*T#:\4MQ8T8XO('-P3 @,
+M':5#80%JHMPAI,IKY?419\^35.F1UQ7XYH*.XXU_D$1$B! 9H$AN+*_K]X9F
+MS1P#@\L1+_"FXA55 ._(36L(55)UA]ED;%A5MFBL%,G^6_!%SWW+(P:A0EAA
+M3PT_VU@E#V9C_KA*#J_X1%F&\S?'HBP&#S[3=11VY=\-'>JV;9^?#2,SE(@$
+M*D@G"2,D<YW<!Z=8++*BT&>/'7KB++1W6\[I=9(%1L'S0!#8XO"T'[$+U9E(
+MF51=B^OT7I,_72UEULWT8B$)X8;P*8(7TKM=>2?R<:N5]NTL*!CC'H'EBV-_
+MG,R-D\]2*W="_PY/NH&^A(?H]\DVU[GMXW_)V8!7FTGVQM78RT>FA>&]'3K3
+M!T!=E4;D:AOA $OL=<^=2?E3AW6^:(IRKLIJ 2G(PXO"&-D/NY5JTS"'SFO-
+M8QDGM#OBM/F7Q5D*3XLA.OV*'\OUA,[\%>LS8IW3+FHJ(1IHS2C%3.\$&F+?
+M*!(?'(K7G\ME*DE\$0I]DN^.>RS''# GMM[_13,8OY_L)!&2JJNR[!*<O2$H
+M9<"IW%/H6"/U]5Z9H'X8B[@<D6]&:AAYX&DVM*'@;UZ>/7;(_9*_W_64L+\1
+M\%IHHJNY+T6<P[8O+HZF:8! [U^>9ZX)9M3G<]+BQ2B.U(RZX&B!1]RDS>F1
+M B>F';(R"0:H=IS_GRPPK<0F"/H>"^WF/GG[&RT.3K;05\M,5LKCQ8GYI[Y^
+MYSA:T./3'Z.#B%%YZK'41XW5-QYYE(KLKJ;H1]-6?YK+<(G&:\T)V1YX/(X[
+M7WO$/?2H\8M67:QI8@;RYH&[6I&A).KM81]_^ZB.]-+9%+4])S7TSXJEO3]0
+M+T=-S)-[SZ7WCAIOMBO&&X+42%+1EY&>%_IQJT+P&HO'9JA+?-4BJ[6;?Q-(
+MG!A8T%8V]A1;<H>$X,UF).X\+)P%.7/55&4D1$D#V+W$?#=X4$&[(6X_EO^K
+MG4.TY,8)G#G+3=NIN7EYN0&$T(^2A^O1(,>'^8X% <K2&*X8@Q0V@K_^$['5
+M..N04AZC/(VEHDW^FYY=Q[<FFU-O@%U8JSA%FZ9DK/<^0=V:\4&S@ T_$D^)
+MP-B^I2X22&KFL+R:B'\]_V\*S^HN3[&6=:SMO&V7)#.H#;0.IHZ7U@4IV'"0
+MJK.+HXZ6B^MOHWAV3ZWT/+AH@)N+H7)O]GY4B@ZPT,^UFO@U.T!GN1+=[_M2
+ME778\8-_)0O),M^U^6CVR1*[F3*@06YCN@A;OG?)'&@+#IK!*+FWM>^+]=6M
+MO74WJ S+;7@%EB/A)D!.:;#]W$"VQ6E0#2:R4_2K=P%VK>/=P2 ?O/R?.#>Q
+MFNB'1J%%.X[SR[K0O-"0,1M 0(#A<J5)-IN[V \85#S VWWBZB/7<.$8"KF
+M_$\?,-'I,G.)R7$Q_J36TAY<$DVC\A(J,+PP8 T:[7M\X20I<G9*5L>K^'H?
+MAM:O\WZT+^:VK<V0/\$0$N;/U=_ #).\^@QK+F4/*\0[NFE1E@!1%_L\)97Z
+M%+<]4-/-IX)$+3A"JC:_P9Z>6OBP.F!0SYBB90"5?+L!=RD%VI#G-6TD3'>S
+MP)H+FH=S9]H1=C8Z\D*FESDZ?;-[[/@T&1:R%+[S/R]$1Q\NR(<.>5]_7P93
+M^<R38>9A/CYU#"7&O&I (<A]KDXE(@_OAI9: '7BZ[)Y7@6<%W=/"CC\\/2H
+M0/\.8:ZU)PR),*$)ND![20$OX'0T4#W/.$.]:R@H==3Y@L\.E4ETGW)88!(>
+M+4EYX(+8=>7#S",A?FZJ%>^[,2TW!3F374>N3N7I2ASKV/O<:-3.)=-W(A,,
+M+3$ARAP<!\Y7'!E(T@I)_""9#'</-(Q5>P(]@OBK2L">CY@''P-)D!(8R5OC
+M=6K+8YD&F\>B 1/PPKP9N^(:!?FXXK5H0!;?+*SO!Z]=IY7MA*6+:3DM%US:
+M/H#"XE>FXG(/#OV]#;^<OTXBL(&:/XGBU]^UZB'MVBB*Z$N];#LS G#D/D@>
+M")"=FX=U[J\^7"Z)G?5D"[1/[;> (RELY[R,M)/ J<$N^6KQ)]8*IYM<$V;>
+MT9;_4&.1&431KJ:SSMKH"A"+]WAA:[W][T)HML'=)BBEC=,=)M$OB),@$@?9
+M:@1C_T?K)+$(V_YWOD[K@;&BX:XN753^_5-/9,WPL.2D(IIP,S3OK\19R;PD
+M0_F^>O?G*:>?=*R;'@N0O 8I ! #8 GP$] @X#% 1.!;T'7PDV"T$-
+M@0_T$IP !8 +0!# %H < "' )T M #* .$ ]P$. 20 0: $1X!32
+M"F,*2@J, /$"X!?F"V811!"G T(>QQY&$9L,$24-)>T<V Y[#)X-&!XI$ZD)
+M9B.3#)P;'2)S!2T3W"2)).D)@QHP).40I0Q:%9@E3!+U%:\;\2&Z&I (#@ S
+M"A\1, M_!$L49P*;'#8/AB2#&98/H N_ BP%JP.((FP=UP=L$K,-5Q&?%^@$
+M#0NU &$!DQO\#_T48 RN% XA(!B3(K$/?"06"7L #B8P",TB\AFV$0X$SA=D
+M%VH3>@D<##TES!'%%?T1V"/;"]PC[1P!#"\F9!8&#M02"1D5%V8E&P(+%%,(
+M:!QZ&M\F51%9%R4#'AQ$#[,8HR#. )T)U!?_(<8=1"5O)M(4(!J_'T8"JP#T
+M'T8$K ZN)3P!Q &1%V@=&@75 O$F8P1F"Q,6:AX]#7,#<0B\!LT0B12?#E<+
+M?!2N'MHF?!U0(3P/<0G?#=H*F L?"^@<_ [7&G,@"A$"'!(?_A':&2@5AR%E
+M%"$5<A[N FP4>Q6G#R$8U"-V%0H&-QO'$#\)$" $&:D7L $B)OH NR,0(A(2
+M+P'B'Z\/Y@!,"T,EDQPQ&W,6K@S9'7D<2B"A"E0A! :0!&,?X1+P(;L#VQ9>
+M(V\,%@F$&4@%%PBP'(D%N LG)K(%M 3.&5$CD@)W#&X#QB8$#Y0>>A4;$5T(
+MK@JH#:$A>P#*$W !&1=\ !$BCQ*\#/@F< %G#[\0JB @$[ C,AG.(*H/'@KS
+M!1,*YA7%(3 = 0T!&U@!\0MN"T86LQQC$?0C1QAX#OP2@PLO#6@14"-M"7\+
+M+Q#7"KX2 0=,)FXA"P%K!Q$*%16 !^@8FA8J(]P2=2$F'?0*E0$A#2 !$PH9
+M")T0"0K2'P028B'-$/L;\@Y<&;$!5!D_"$D*<!BA'U8>H!7B)6,0V V*'U0'
+M? _F"ZP-@1D0)E0(?B+B(]47O"!X UD$2 2< FP2^P"8!$0=0Q*)#S$// HG
+M$3$.;!$,"K 0]0;A&D,5*QRS#'87922T"\T#EA^3'"@5501*&P4?AQ7P'BH;
+MQ"2T"R\%4B.))> 7" "D(LT"*P&R(/T361L)"4 !'09I&CD:6"<%&Q(F>@FK
+M $<3/12S$2PC& ^Z(+4%]P.L%L 4V1LY$(P+G0C;"?X:? "Z"'T4?!H/#ODE
+MEQ$7&+<8PQ\=%]H*>B,K)@L%(@ R#]@1(1\*!987T27R <$: Q;4!JL6>P@\
+M"Z4.\ CY(F<3.!5= S\+:B/I")(@:1?G""@+Y1GQ$W$*T1QR$O 8:P7%!KTF
+MG U( 'L1B2(K),X+=@CV)N(.;""Y!B(/JQPT#5L2RA5)",( 0'['R$4]!Z;
+M(L\@#B)J!>LDN1-,# \5U G8"TD L #5"B\FTP%5&I<3[@B?(8 FMA6E!MP,
+M'!;Y"LX&VAO] J8@1 HQ%($0%P./"R47. >C'E81+AT!%Y(+5@:&%(T:8"'X
+M(L4"TP@-!*$1"03$&)<D?@ZA"M((Q24M(:@"!P%&$R8)S@#P"P$7Y!QC%D 6
+M*1*6 9 >] F!"M ;RR:A'W@3" TS&,L O M4#BP"S@HI CD1C23_'D<:3A"%
+M'+81V@W3)NP<E@MM''43M ..!)(:]B4'%M81ZP@2)?8'Z"5^)CH:LB8\ VXA
+M0P'?#O,>)0FC$OX8QAD=!MLA?R6U'>H7L"$T#IL:,27M(A<<% ]0 H,-TB/L
+M!_P)T ^^$H8BF@KN%2TDZ1&-'O,>@Q] )/H#?0F3": "4P*($F@EU00M&2 6
+M4"26"/,@727) \,#'0ZO(AHF.PPN&!\:Z!RL%JP&^Q&3)#H5X"&O!] +Q!UE
+M#KP6R")(("DB<Q!:(H<$VPZM&<L )B,<!IDE PI@$-0*Q091(2,<^Q%0 :8-
+M,R2C'P42X!C]$P A!*($YH(R0QR'PLB!Q8=&^ 'G29C$"<=C@!J!OD8R!D^
+M%PPE5P;/(C<F5PK."J8BN02:%YH%.0DH O8(UB9])HX!0 ^-"N<.EP2H'R,8
+M.@?P$7X>(!Y_#]<$[AR6$*L")PEE'3@.2027$"4"9A-W#B8"V081#'(#]P1N
+M&2T,82:1$M4 $PN##/($,@B/#F,E/B;Y!/H8#!/X!UX3T1\\$J$5T!",!^\;
+M[ O2'H@.\Q0R'&$<M"8O&JH7Y2""%0T"TP\G'E8(8 9J%6@0PQB>!241!!1>
+M&B@%G@, (B 9A L@)#0%>P1/)5,(XA-\!/87VQ6+(K,)RP$3'_L2/@// *4:
+MU >U X8G"P6- $X9AAX( *L$?P $%0 +( P9'38E;1*? C0<^ M.)48"U@GG
+M&:@9(A:/((X:!!^M P 1'1\, T E_QI0$1,>!B%& 4P K2 Q(3( !!FB#:4,
+M*!.& I0%]!JG&&(92Q_R'OD@:B3?(\D($1.=#3P:YQEO&AL0-P2X'T40(@YL
+M&R0(C0,E!(( A1!)&>\'$P/>%80AM0$L"08-OA.9%.X6VB'?&:T ,160%9@?
+M@ UQ%R\4[!=+%@ 7(B1'":X&.R)[!+PF:Q+P"@TBEABM(&P;Z QY&% (^1B3
+M""XD.@[U)"(.&"0(&(X-YQNI% 8>+ LA'-XE' D#"UP"@17^!/<(=1VD$OTD
+MX1N6" X/#@$#%0\%Q0QH%L@-%P[##:<7Q28/!"P0-0Z:)@D*R1C[!B<7^"5B
+M :,BT!*' (L3\B35&-(9[P?@ " 99PJ /T, "#V!Q$.%1T%&0<-PPQZ#.4-
+M5Q^3'1( #1CH#@,F? R> Y,8R!^B(^@0'P5/#H$6>AK@"FL/C0:1 )L*Z1E!
+M&+X>MPG>#^L* !.G!)( 31D_!U45,Q\J"HL!+1,>"0P:/":# .L8K"9J%TT1
+M@2-[&),A;B22'XLFS!D%&O8.]1>H">$"LQIR!N$,<R*J'',7P!S\%CT1E06_
+M)FD8WA)'$H$,]A:[%&T4GQH#)H(!J!$Z ","A1__)"\6) G1%' 3XQ_Y!\(B
+M#!96':$,+ JL"$8<3P[!&/<4+14M(!\/P0[U%CDEI1,#$ID6X!$*)(@7#!]%
+M"@ ,P!_#%LH)YR"W#X<"41GT%L<&*1%,(/($M2*P#H /_1:> $H6>Q3L :4&
+M!0*, IP6,P=7#O$ >B*W&64EU ,]!3<&^ Y'&G<+Q1V@(PLB[Q'2#4X2R N:
+M#_4;[!7Y%UL+D05V"_L*50G.!"X*Y@-2(?H-L@3%'$@"JPJ\#OP6E@\Q$.@A
+M#A7:&B0*E!M'% \:G SY%KX'>P@] ?05=1;[&[\/:P-)(E\=[0)I"VD(QP!]
+M&F8@WP=E" (CR![['J8BY0,[#88? B**%B<@8PC" 8L?F@;B'Y$@I1K=!N\/
+ME@II$)0-TB:5%5T061P+!Z0B=!%:! H#MA/(%*H +1'3!L\=& ^Y(X,F\Q;U
+M'HL/8 ]D%]D .@) (QP"F ]/)+4AN1[<%@$#"@'A!V $M!/M'K8=I2/G)>X*
+M@1&%!PP8QQ#K# (@I1:U#+XF PY!"" +,!8J $TC>AB) ]4+WQ&\%!H&=A ?
+M#'\%=A1_!O<CRQ1! L(*OB#N)J@)\PK_"<T-3 IM#H$*H@<' (H#GB.>(4T1
+M9B'<&, F*B'M)4P#Y1;6'8<E"R"J!H$*S2.%(#T&O292 -4>S0LE!8,(Y!CP
+M((D3:12E",L9\R9I"Z8D%P.?&?4%L!\N(? 7LQZR"!P7V!1A H0-O1<S&]8=
+MDQ+Z$?H+/B22&B8$V R(.<7X14*(VT9W@A;!B@%$P[##^<:?Q! $V\#]PR0
+M%:42U@K '64"% /W#6P7X!LT!"$4V@6I%<< ?QU.&=4=A!3A!' 2-@;-"9T3
+M]"*P#^0=QB:V!UP:\@VZ%8 /"1,8!O0FA048#38'U1R3!DX>CA2;)4$$7@[V
+M!V$-#B$2&0 _@HZ);492A-@ 8T*$!T\)#L@* #'(78 H1C8&:T5J0>F"_L4
+MCP(O$UX!.P82(ID<$B&N#L8>/ S.!P(<9 I(%7TEDB(B#CL8A1=\#AH!(!!N
+M%J0-DQP&$S B-ABS#T$CP!\1$0D1;PP7#>(&DQ>.!XD<SQAR"&@9HA;6#-\/
+M0@)M#W\5B!LR%$ ?90G[&%$;GQU !+P3(@FI'* .A!;!)<@EIQO0 ;L=O"$1
+M%^(?PQ;!#( >1"0Z$-<DCA(\'(0B( ]M D@DUQ<B&FD6RP5Z)J8;L F:"$ 4
+M7P;R&;PG!R;D([P:3122#=@9)26?!E(50@][",$9?1/I&H@B/17_#\8&R RX
+M()\4PB;[&N07?P1B%'<A-1:0&?D3^AK@ <P!VP4Q"MD?8!FB'J8;:B:E)*\.
+MT29J$&</ P)S)=D(90"@!2\ERB%P)%,C!1RU'_L7@1N<'YT6?1VV"7< AP%T
+M&)X1_0?K(],%+!6'(XLBDB,B("@1=A\L'T4<,!&"%^P!*009&T0EE0$W(O<B
+MLQ=:#^TE;0G,$F<13 T-#<L""R.V'.D?0P.V#-\!HQX%"ND2% 6Z)( &GB80
+M E //1W(%+0"7PL.'*,,_!ST)'\#ZB1V 9 !Y2;B!.D -!M_#((*0A./#-L0
+MC23D&LP4VQU4!)<D#!,Q([D%/ $R"%$FQ!^P ]\;SA8K&OH8S FL!/4?=0**
+M#?H>30=5'8X"7 0,'_$?Z0;Q':(/UP;1"HP?10 ! 70#2PR=%ML62 ZH"6D@
+MI!+F Z(/ZQ_5"CP9IPSF&TP@3@+U#,L/.QZ8 >@<AB3O"<PB#AU=(<X;#0WG
+M(:D751^9(W$7"1=^"]\/Q@P[(Q,BU!X[": 12!YA T(6D"37 ?L/E")?%E<C
+M/ P;'6,/R0K5'NDA8A?*&6D8M *F%2@5OB0S%P,* @!J!Z(3F@N3)AD$/@(^
+M)" A"1Z9%!\E00VR)F4<: .8(8P3J"8+)7@BU2"-(-T>M X%(7X+X!Z%$2(
+M' 8Y$2H%3A-Y(J<CB!TF T0-@B0Q)"X,SP.0 2(%V1%,%Q\0,@^C%O(AQP"G
+M(*P)LQL4$XT9=PH@ A@*JP#!'.8+@1YZ Q$/_A!8!+TBE :6$;T9!0T=&1<%
+MXA?)!+T$;1/^#5<$-0>F&A,<_Q@)&WH6QP4Z!"H'CP)' & B30P$$L <A@4>
+M&LH7MB/>#T@-:!0= J4=30/I#FL%U L &WD/\Q0K"\X'Z!= #Y$A? HC%V$4
+MU0#4$:P*;Q4H')\BAPK"&JH@CQH4%A4DT@2A!W0&C1MF)14:G@??$$H=8".)
+M"A4<#1_?( P%K!K0)/L4XR9F$3,6X P/%YL<D! 3 ]X#>2"D'O,>' PC(&<B
+MJ1-P%I$.]Q!< T,@)PYJ#<0DKAMO!U0<1!%+ @(8SA.8 @< EP1?!X ;_0")
+M%F@D/0G>'T 2'AW[#'T?2AQ$(T,+[ &M$)L";1)/ D0EQB'4'JP8DR#Y$VD)
+M9P','*L::1ED)O\#)0.3(?@170 X)%<:_ ]-(&07V"8S#>\"M 3K 20#00QV
+M)+X.G $3!$L%RAK%!#@A;Q_+!703)@LZ)8T6L@#L(/L5*"#)(B\.( !F&+ /
+MI0,I"2T<7@0D Y\81 <U"049R0#J&V\$#1^,$+8B4P17"N$4XR/6$P(A7P>[
+M)>4B]PN+!D<!/0'\$?\ENA) &K@': 3K)F@<Y@"P 3T,<171"R %EP(A(4(D
+M+"->$E,2<@E<#_ %GAOY "8)10@A 6<6 B#<',8&4002)G(![ &J%5 DV!;'
+M&)4-?P-_) (!,P]O !(<M@="!PT!8!^5#>XFP0[_(PX=30XR(1,@LA!Q#*H"
+M:0 F%SL-,!GN!@<0SQAR!]@C!17G$JD671,L$-@5;!B$$TL+F0?%'^ )$PX=
+M%O 8,P0;"4 4"A/Z$#TBG0VQ(1L4@P4@)=XF2QD@ 5X;M"$[&1T3(!"@ [D6
+M[1+4%W84C"%+ XD(:!XO"SD0IB;7":09R@$K![<.H21T$;<0?1"Q&^@!*0^I
+M(5<!PPZ]"X07(A=$#^\5EP*O)"LD#AK4$W8?X087%RHBFPZA)((-MPYN!BP8
+M&0%#%;8.ER*((+D:Z 7X#6,EL!OV'90B=0P-!@84!Q%.&JH<ZB1+ C($WB&P
+M"NH8<!WG!#LB>A$^!;0(YAZU()4.70NH$E,!PPWH!BP=GQEM#\T?) %!$: &
+M?B/B 7,>[P38(Q8#Y0<L)104\!5(%XD03A.##9(?(@A;!Y\<^R+N&BD15@WG
+M"!PBM0C0&>,"'P"D%MT2^![B"%$&O [*(54,/PW3"/P;(1Q,$/8/XP-Z'A$E
+M;!X #T7=R*F'A0C)!H[#2H'R -Y#Q09OA7C!^0EJ0;A"U\"0!*&$-T'UQ;T
+M"MHBMPLL"#@'SB(]#!8"' Q[)*T5M W2$SX,=ATP F$5DB;N)D<6' =A $#
+MT!-S"^ C]@.[$2<+ 0.J!%@5DQ4+!1H70@>U(TPA+!=)(V$0[1#- D<0BPVU
+M(UL#F J%%1X#P1<Y"SP752#@!4$!"2-7!-D-(26Y%BL<$AB,$C@EZQ0Z(@H+
+M[R30'^ -U CM"[@ 4Q.#$!(( 0RW('X8(@5R!EH?P!5* ^@<G0.Z#"<CAQ@?
+M!F8<*A.$%2X(HB8H ($#N!M[#!<)\0!$"$D7!Q;0'V8862$&$M, *26[ O04
+M+A%C&!L#/!L] 7T5'2%,%IP?:!7X)MT/[Q]5)K45.B2>)4T1IPSS)G,+[0.H
+M"+,&&R,;$38,A@Y8%B,3/PY&#$<@LP\ #J<7Q1>Q',L+2Q4/ 50+ 1!5(#,*
+M"!"T$ZT5RP_W)ID,5!W" N(1T0=]%6,!9"!H AT#JP^I$U$=YB,V%$8'IB(Z
+M(5@)TQ>9!98@_Q[8$W 75@<X" T#4 A0(X@@D!:(!/0*N F-!\T"(Q22"!(*
+MX1DY&WL4^!W"!6T%&! 7 X,1QP\E#$0/)PWL#P0+^@CG'E,0/PZ"'K<7^P($
+M#^L.Y0&;&K4=D@-?&/T) B7M%T4'6PF<!(P>XR$.&(8)5P2U)9(AG!OD%FX6
+M_":?#=,F'!IU!O<,HAO8".T<GQ3T(S\0= /M!R,2WAM0&A<*R2$1(ML:*0A;
+M'VD'NB*9"^H/%A* 'B\DC!ML'X #2!Q7"6\#G1:*(:\BBP:Z&_ 3Q02I%O81
+M@R'.%GTC00/F'X,8>0- #\\,E1E"".\ERA60!0T=( V"%H<"\PZH&1 <\QD*
+M!IT-7R/V'K@7 "&F$4D2$Q8?%I@9_P*##&0'B2&3 :09NAM)"]P98!C*%'($
+MBR;9 2P#(!X$'WP:81IZ$?@9=@MQ%5P/[1; :\>9@-)"Y@$"!XD)*XG P@5
+M"%<21@!Q'(0-.")>$ T',1H-&B$6-P,;$N0BFR.J!'$"+0W?$&T/O@ID%P@'
+MUAG#!,@8F0H[%+H1J@(F"M@6S"8R!#0-&QC"(=X=S@Z!'30$Y!>F)405M@KS
+M(,P/;!7. &D+TB53 (H&=AYL)ELF70XB D89U@4M'CT"$@F\#3L#M@U@$M<=
+M$B:))?('!!/K"Y02!0Y$$L<: QU&$'\B3A_;!F0(D <2"E(.32.((%P>="4*
+M)L ;)QC3(QP!7@V8!\ # !9S$5,+4B!@ \<'2A%C(BL=R@YD&4P2D!G, BX)
+M42,I"9X4'A2+&=@)5A!8)387-0Q"#Q4-F@ 3&,4;?!CA .,5RB8Q$&@"&AH^
+M"L %.A"-" 6F1<+$B@*PPL#)10DZB5B!BT#N@SO#FLE)A)7)CX3*PG&&<4@
+MK1$L#&( 7 QA)+\#9B/0&\0 6A/O$+04X!,X&X4&CP7P&XLBO1L]&J()T (^
+M&",5\@#A!FP+AP4B)JT%VPH6#N8)M2("#6DEQ0\S =48UR"^%4\5IAIB$1P!
+M#P^N V,?GQI! Y(): A5'',D>!93)>T(N0V0#R$FHQ<6%5\8R@#>'_$E2P8'
+M'+,$9A-R">@;4A;U(Q4DQ08&)P@=2!R+&>L#/QB\#KD!B@=5 "41P0NF%/X>
+MU"-=&:((E1CL(3X(TP>@"XP@N@7.&<</% 0> 7T"C0]J(> B82;H%ED+U!II
+M%O &(@AU"0\9,QYL 0D5(!3Y $,B+ B:&043^@IG$5$8<@\K)8\/Z!VD#]L)
+M;Q".("L* 25N$+(0+188!U\BVB$$!P !\AH'"HD7$QA^)1X<1P/<%!P5V2-)
+M&J,*@!PL(= 0TPB''X<3#@-_%/ 9FP#A&HP;8P45!0$<K@0@&PP81B1\ ! 8
+M(!D>&[00"2(0%EL772:V%+$0#@Y#$WP6O1(($G<69A]J)1@%=1"J'0D!AP+B
+M#VD1]A"O'9H"$0'8&ATF/QJ2#)H<V1WN&I8'?R4U&DD?&A< )<4*3!VW'5PB
+M3!@Z#WT < 2Y%7,*4PF>%TL)TP3.$!D/U@M\ D84>" 2!#@D 00) EH=$0@1
+M&U8-,P'I I(=31@7#*H*L254!A( \@D3#1D#"Q2:#!$8Q0 8!3 @^03!"U4F
+MLR.)#L</ 0R,!0,4U![V$:\0!P8]'#44^2/$$,TBQ@]O)MX9?PA4&C\*!A4S
+M"=X3& =-!OD,+Q8,)KX&]Q._"YL80@GH&S,,]@>2!UP7)",1"7P@=PR9!+H+
+M'A,4'/$4J!<!#!\.P WV'I@&"@*H)=(FK02)$(P#?2,T)CP-!P)L&;4#K2'V
+M <X-PQG^!<DF=1T/'306O0[K(TX$>!E')O,5GR-8#WTDD078"\$;.0J%%GL)
+M&AJ:"3 %Z G;)?<=*!Y;(.\+V0+O'N <ZA(T"LD4[0HY%S$*Y!0A$F\BS@_N
+M"-4BO"&^ @L;( K,$+$@)@[4(. 9(1VP&$\-E20&((HA9P ](]<=$@_L(G<F
+MIA !'_LFD25E#3\1:0@L"3(FDA@B&%8ABP)'$!<(E"#&)1\@C"/[!CP,ZAT)
+M)+4 YQ[,)5, 4Q*+$-$5( [C$O(&[ EF!U4-^A@='ID #B"("B075Q1 %;H!
+M@Q:(#)8'50FM'X 6TAA $J,;+!6F'5DDI1ZD#<L*NQ9E LD(!0I?'3 3B!,G
+M(G,0<R;*#[X%/0L3!E8 #"&&%#H@P!A8$A D/02:'$ 2\0-W! T2^B%_&G07
+M7!Q_'1DF'B:* L4/F@,?!7@)71X;'MX$N R$'V<AI!W=!RLB_!89""@ O0D,
+M&'\ VA@)%3P 0#""J8E/Q%9#A,-1R3$$OXACR;X!<X(&0W7"0P#21.8#^D7
+M?AHA#T@<I2-K)M8B7!Y!).P?T0B?%O .DR2))MPCXQF((.DB?1H@%]0/MB2>
+M$QT6> -%CL(N1#N%?X89@&R!,4=)0EZ%@H29@K\! D1! P1!C,'R1G/$T,=
+MTP1*$X4 %PD=%G<<+PG'%D<!)02J!VL!JQ7_!#D.7 (L)B44B!W '0<BYQ5U
+M HP7?26[#FL9_ ;@$,H)W +V&D,EP0R%)&TFHAX9(HD,(A 4#10+DQQ" #\.
+M5Q!F!IL4:R<!&04B+ ,^&,P4Z0O0$Z@=@!WE!N@*D!B_$?< \R",#A(CH".$
+M$$,&4B5W(U@4!!?$(YT7XA'M <X"Z1QV&8 ;XQC+!R$#I 0K 24!NQH7 $$.
+MQ!#_ N\E@R('%8 BS!Y$(5T0FA[1)&4<4@A #&40JQ=B$L0$*A*X'#\%T *5
+M)4(042-R I )(A2P!T\0^R#"('D+1!3Z%&0=G@KM(8(?<18J#XDEW0D^ B$#
+M91JH(@(.]@AT$^$)J I$ ^P*C09F&\D?I1*, Z$B1R0X!A@B518@($(EC15N
+M$@4FAR,M$_@'!Q#Y(<4".B;O&60#0"&0 T8C1QZP%Q,!?0K+']D@S@/C%JD8
+MR@2^$X\4Q!L0 : 2V1<X!1$=?07; T<'B!;V%G$,R H,%( %M ]!$, :H@E4
+M'K,D* 2A"(4-(Q]R(+PFHP&W%< ?0Q;<!,TE@AZG%U$C8165 \H$I %T$T )
+M*"6^(^8$?R+O%&H$S G&(:$FPB )(A0=XP_.)=LFL 7_(#H/KQ=+)CH9M2!(
+M$(8>Z@B*)!,8EQ#^"NH,QPW@'5L83PA<$-H(R@>W G,1;A8Z#54.(Q$Y(6(*
+M^ADS'VH;11;7&@XAK!>I"ZD"" \.%&LCUQW0":\*YB5Z(@DF2!@\ R0@- (!
+M HHA& P?(H$+X02*!/,>S!^R%@ <20]1)=\)*0+T)?PE!0L$&UP+JP7K&.,<
+MEAU''^X%U 7>"#LF<26F'=HFCR&M&T\)+A+^))P&S287#P029";5 ZX#80K=
+M%4< #P(0#C 6]@%? %<1]<$E ?4AV %J8,00=; /$%8!'J#"8?K0,M"6T<
+MSA%K'<\B\A%F"9,"L!;K(#(-(2* $545CPOU 6P/K""5$(<@J!9<%Z<'HQT^
+M(1@)&"61!7,@$PH"#RD#)!8T!BP5]@#]"$0<P1B'(HXE$@P$&CH#6Q,Y =8&
+M( ]*#<X6Y0!$"-0F;@;1&D4ERPQ] 7$D4QL/&N('SQ#?!\H9S!_-"8@)*1T3
+M <$ R@_ >H4VB) '&$3E"'@%PP5I1,;%] 1'QBS%NX%]!W6#4@8WAA% :P'
+M4!/S&"H)=17(!UDB9"5D'C8/*25["D0>4!/"'O05L10D$ (CX@$-'_T-_2 I
+M&% +2QX #78?RAV0)G,@# ?"%^X-C"/N(,0%)"##)&$.D!KI)E41% >O(7$7
+MTQ^J$ 04H0\5))\CB27H'#@'J0H)#F,91 AY"2D65B'T%0D;D Q+![HDY1*:
+M%0X9C1H'(4HB1R U _X !!T;!E<12A4W"HP-E@#8(@DCNB/ )4<)+ #)%+<7
+M!A6O#>P'$P"4$YH6EPU7"EX1(Q<J'$D#-@$P%* 3"B&K#Q\9K0<2'[D7W03D
+M(K0D\0U>&\,2D!8\#DL(/P&6&P49_B:N%#<$6QNA%4@DW )]"]<2 @BE(8@9
+MT" =&U<6G24; '<1&R(/";\DV11]&$L9N06^'K@ $1_%!E<0ZR.@';$*Y!*1
+M!%D,Z"7?".TD22:F&Q(.# WA((<.=B%( [@9)0<")(0)11]J)9<23P-4'AX+
+M#@+(&R438AV, TT!12&6%QL>I@"&#_P@@ HB#2$-G@AD#R($CQXI"[42GA\4
+M"ZX.>AA6&_8(WAS7&_0 W '-$24::0T_'?4-S1!3$60'OP!@$OT3:0>C!L(6
+MK J" > 5D2!S)+\4DQ1H%=4!8A_K!XLD-A3:&44,/@CV'547S!ZP$M$EWB;2
+M!L8 MPP.(H<%8@:@&ET411HM!9$9'0NM&),1S0F)(+\,IA)H)+T+=@DO%6@<
+M#PGP'R\<OA!'!JX.EPZ&(B$>1@NI!! >5@K#&FX8NR.'%Y\5S!5]&*$&DB4"
+M <T/EA%*(AX* @]F)A0;&P"6&-<> @TS!3 ?P!=4&NP2_ @[#0(.> 2U ',6
+M$"! #.P!=B,S(C83MA0B$^060AJ:&_0E/0PI#N$/H!-D'.,:H 4")88D_R9F
+M)M$-[R'_"4@:[11B''T,CPU&(64)O@8S#MP+*B,[%U >FQ:]'3L;T0(@(T @
+MSQU6$=L(+@W2!BD;VA:^!\P%RP:D%9<".@,7"A(,"!,G$J,<F 8)).X=<Q#K
+M#Q@F2AK8(5 /G!O5%F0E8P,6'2XEP0#;'(L(EPD'(=T4D!_"%7D8LAO! CL+
+M:"!1'!(F/0] $](*N@8$(UX!BPV0#/$(X!7@![04_A3#'3\/+R+7!6,3 R:W
+M )\&[PG&%)X?_0;7 HD2VQ8$%R(?E1\J#R0#N0!;%)$"2B"Q!3,, 15!"F "
+M] ZF$\D-:!7A"VT0Y PE!C 0E"9W&H05J!I\ VL+G@5_$Z()M0Y\"(,6UA>9
+M&&,E$Q%9(8H$^Q@M(>( *!)@%@HF0P!8#6$7>B%=%!<?(217&I,*712=!,0*
+M)@7G FD77"#V :P)AR..$LT"%@2>(^(@:R5*&A,$%QJ4!I *>@R]'T@:<AVB
+M"Z$1/B3T ;(=7P)G(VP4.A[K"FH/:!,\'J\(KR%\%+(&$"#%$*\<[AC;'=X@
+MSA_@"!4"&Q.I';0%G!2; >(0_R.U'S\96@= #LP3;!03$0<:EP3B(*4-'PY!
+M&F(;C2)5#>H.T1 R #P7;A\K(7\"4!'H$ H-3!W!&N$*B0Q0(2@8N0OC&SHD
+M$ ==##H2^Q@L#RT$% ,V(3(9" >!&E$B)P&O&04<K!O!!-8:)R.,$7,4"!$G
+M$; 5'@0H(.0"\@P_ 6<">A0:'0\'#P1R%S4 - 82(!8A/0OA#[L0?@1.";4,
+MN@\@'8(:O QO#DP7?PAF!)L/]@N^%A $+AZ?)+(!H1%\%QH,41_7(C(1UARZ
+M"-H*(R7+)GD* 0\##L<1001#&LP<1P,((G89QP<$$V09X@:N$N &R1-Y)?P!
+M]")X$P81S0T="D<':B'3%Z<7KP50#R@7\1A+",@-8P[K)FH"$2'V$\\2:272
+M&] %> 5I"]DDR!\7 .@;\@4($\023AF6):(3@0RL#(4*;!*@'C03ZP6M(Q0!
+M&0"0%=T/XA9R"*P+%B9: XX.?!6](0\@40JV#VH!,!D&! 0C\PA<#FL)9@=:
+M :H+:@>A#6L9L #U&-06\PEV)<(8O0.W )8(81TU%TX%@@K+ 3,D[!:J%F$%
+M.PRZ" \F\A@@!MH2E0SA \8A7R*^ '4810CB$-DB(PU< K,761&9">@+M0\I
+M#? %YA9@&GTCIAY7!CDC.1ZX![@.HAZV%)D4B0SE(6<*WPE;'=T!.QDO'04)
+MB .O#>\'AQ(I(L\C-AP$!\H8#1 O(C4)]PY )=D6-QCS)(X/)@XP#Y <10GS
+M)>0#X0CF%J<(- ;4'-DEQ1YO']88KPBQ)HXEV@-T"G4.W M7"'\53!R^(P$=
+M%0(#)2,+<QOC(VH!% Y)$V,'<P?\ EL4!!P'&W<>(!%A)HD4CA;9(U$.>1A*
+M#_P$YP?7)<X.*!0\#=(B0Q_.$]\B-1JA# H.N1Q,$Q,2"Q!'!J,CFR/>!40+
+M6AM/%08-A2&T&W0D;0X#'!01'R;N'G8 :0N+'7(+A@^4([8:B13<#>,$711B
+M&,T;7@[))0@F;Q*['2@ETAM>#]H0#@_E!*80P E^(08,! 5S&<(CRQTW'X$2
+MDQ,* H<8. S&$ID%S2*<$OT)6P6H((<#"":K(%4D! TV"MX,,Q1*#H(3A08"
+M"C,CQB1?(ID)LQ!V"_83$!ZF(D0?G YO'74CB0*;'GX67PC5$^(57R.##4X!
+MI@^:&O84; 3 !ZT!=PK% ^00.P5;$]0=] .L"/<B'"-C(F@8U@JQ'_,4X!%"
+M&W,.+QO9!OT 8!P8!-X#>R(D"2 32 BE!88><0OA("<9@!NF 2L<?0:3(! ?
+MH0:&&?,<QA0:)9TF] NA)=0%I0D>'4($4!G5&GH(U@(%$;(1.Q]T"TL6E@W^
+M'G4*6AO()&P7O00, -D#U!9Y(WH$^QIN"ZT83PHS"/$G"P &U\.T@VS)+D<
+M A^!'5$5-1^L #D2T!BD QL4-"9' @(@L1G-"$TA(A+W%C\;S JF&<0520/Z
+M'!,AUQCO%3H58 !O!&T=.P(\"E(<S@Y8&;(&01.N!X\?K!^P -L4$2:;!+@1
+M)P-H$X4ENA@,$#@ ]QMN!K@-:PY5 WP- ]")A8ESPPZ!$@*)A^-%@PD(Q*V
+M&Z<2V #X&U #1"O 8$*@@L['S,9[20@&;,FH! S%0 1XA_J)"T<8B8+%98,
+MJP3W&(@ A@CV!)$7OP)U">T".P0R#^,82Q?]#]L>;QA]$1(!^ @Z$&P # &,
+M(&@:PQ2S![P(G1?3'68AJ03['(@0T@P''!4<RQ;6!UP$32 E $D16 (3%A$3
+M/R-G&8$8T 2O$O<$O"25!Y,2%B""!.0D&@CX&(4-M!LY(<\4VB),'%\"6R3X
+M'( 5NR;N#V$;80(1(6T*P!=D(U '4 (=(&<0, ER#A,!#2*:))()2 =: .$=
+M& E-!XL!J@@+#0D?+1A-(=D5XP@E HL:Q0<&%Q8B7P\P!WT3TQR#""<1417M
+M ;4BO0TN%: ?] EM#MT2KA3K'=(#00,\$-X7M0>7&RD- R7W!!\?-2*R'KP,
+M7P>5%E,DBB'&&9DAPPH5#*D:"0]@%BT#"",!"B0%?"$ #8H@MAD')40.&"&F
+M%X4"/0.U(. ;ZR&M"H,9'2'S'=(#! !9"N(< 1JG)0X>?P82!94@5@YH%.@2
+M,B*4(S4CRQ7X"3LC(!TX(XL5-1^/!-,$F2#Y).,BB07V X,24A\+)7X TA]]
+M%/,AN"'4#L\;WQ9P#V,41A+3(&,%ZQ[.#"H;* G"%GX ]010%Y\(" TS'S<;
+M41XH!M(16!YX#'H)T!#(# AU@>)'@ /\!.''%4:,@!!'] 5OPP[#:P?8 R*
+M(A$F!0#V#0<?RPH$"0,4"AX%%_\*@A-C(T0/?R#!&38+S \$!V4+216E(3@!
+M=AX)"!009QGH%W,001T#%/8._1TY$%@/VQH-"Z89K!\&&NP,$B.W#]0#W",D
+M'50)?@ON&,T/KA-5&!L*6";-! X+YB+[#JH0&PQG#V(*>@[W)2D$O0&* P\3
+MYA]K$V8,.Q>"(\X;=QOC%8X3=10[(:X*Q20N#C,+4Q/E)!8C#PE&$)0B;@ ?
+M&L,)E1W6 A 7G0W!$DX5)QHA$/82%0>("(8#R T0'>87R!2+)3L(2B":$$T"
+MWR/'$;4=11I9"DL8OA[C'NP*# '>'W\*=Q*I!) 5%16*!G\*$QG7!ZPAD15Z
+M%Y0=)R)O!+@3S11R F$C!A'(!(4(,P L ^DDL2 ^ ,0%[0!Q#>47!AH<%X0*
+M4 WM J 6RB*,#*T/2!"2 > /9 YT)#H10 G^$NX2W!7?(XT9$P6?%"P48POP
+M"CL5AAU9"2,+B!US"J@:X A< 98+V!3""B :Z1&*"KPBIP^<#((9=PF<'O<@
+MA C"',TE/AW*'=D390^$%/D/0 @%(B@AM@!\!9<&:Q3X'C(&W0HU'/8 X2/&
+M'BX Q0I8)3L;E@D.(PP!L0'*'LLB@ IF#/(?FQI<%D<4!!T7'T@D%1HH'L@
+M'"'7 @T+6AUA"8H<31XZ(MX ! ;P$'$ :R++%L4@8P[0&^0A\A9A![P@C1C'
+M$GD3&QG5!U0;T LI$5$1712;' , ,"1I'J0;TPLC' DB6R80):<)L0H!$2XB
+MZA=U#A,E0Q+S&.P8Z!5F(V8(TA^=$)(.&ACC!& C60&P(80F= &[$?83;0--
+M%T83Q1\,)2@CN2#"'"P ?@:(!)@DA1(N$?H#+AP7!]@1:Q9Q'68"AA=O)NLA
+M9B8_'FH!%1G&'; #A0T8'XH,50Y-&48#B0Y)$$T2Q!H;)H$1 01C(&4"G1K?
+M E(!8064#3L6(Q^5!)<0DP&)&%X!P1<K#T,%D RD ,T+SQ@; +P>*R.'!4\'
+M8@;_(,(!O "B"<T.K0T:"L4 YQH(&Q$9&B-! ZD$EQZ'%!(5)"-:(MDFIP.U
+M"GH#C266%)\'!1QJ$,,.M WW)$(910ND#*T2\AJ_#FH4K15G(*H!"",7"K(%
+MWQJ>!A4*GR0E%',DAP/U(;<=BAR>"@44WPU8#R0*O15()C -W DI'Y\5M1=J
+M ^D R1>,$R<4F1,+#3LF?A= ("\"%!,<$;PF.P5-"W<==!Q6 2<+S! Q)=T,
+MR!%'&8 >D".4(+\9X0Q4%30?FP=+&AH;>AV" W,0LP+[#_T"M!WA$:L*&R#[
+M"!$4J22I&#8<C!4,$!$.H@BF$2T1,AA"$/H QP/])JL4_Q=F(T,;L0T*%)8&
+M 266!V %UB4%'U0-;A(&%08G " 8$5X-Y UR!4H,BA:_%J@:C@TF"Y@&OAMI
+M%?06-1Y9!U8=3!KZ#ST9#A5G"L "QP/L(@00\B9^(C@$!PQ. N<#QP*L'RX5
+M+A?)'GD#^0QV!J07'Q5K&<<>\@G"#+X3#0@H!5X/MA_7!J$)F!M5'ST<&1(V
+M&YP9/PV.(=0,?QT+%4T$- &C"CL%?AF%)K<7;":5$W(=^ 48 S82RQTR)7<%
+MDB.E)N,%]1;*%DH77@V^%2\8; 0H"N,"70/]$7 &J1+F)8X!/PD3(,P-VP U
+M%ZDF<Q N)3\?=0BO%O<@_B L$ZP?R2-Q"9 A,AC&&,DD#Q(?)OX$P1;B!V0C
+MPR,5!3,5EB#M'+4CC"*U#M@C>A<2(@<A,Q46"1T)PP5.%101QA;N(205O"1.
+M)D :@@<L&BX&CR7" (<<_A7Z&)<>E!NH#1$ N0YW%\()OR*L%$ .[AUL(70*
+M?098%8LF+P$T)*<B'0P%''0<A@ C)6T3/QTF$NT- Q8]$FHA2@B0 \0?80AA
+M MP6H"-J U@**0)!(4\5EA=/(,<+]!#X U4,[QL&(+(6GQIC)"H'K \6')X*
+MPP8H!HL =P&""@L?_0TJ KT,T0+&(K47^R;I(MH?[B"W%_HF=Q+V%I$A9Q[Z
+M'.D-@0Q'!>06>0YN%VD4;!5H"=,::R"/(X 3<Q\S%H +WQ:&%NP'C UK(%(&
+M@R!Q)<X6;11))&HFV@F! Z -_B#U%#$=82:$)@T#2 :',0*/!S-!%H=L1N(
+M%*DAJ L )><."P@,$]X*<0W*!4\'11!\#G0#@P5(%:\#_!9_(2,#X" Z),,,
+M;!GJ U@8;A@R#TTD4"-+"2PCUA[ #2XBC0]$#(H@#@\]!#L)BAGB'7(%[P?2
+M%/\$NQ'U! ,BT0N:%,0']P[T)3HAX 4*&&,@SAWV D@A:B8V$E$)$@\S%<()
+MB0XD"[,='1U%'60CZ0<P(7(;KR*P!IPDK@A(&*8$H@[8$; *G0Z#$%P#4 \E
+M \TA\ "K#AH'%A""'^@1%@* !G0CO0>_'F 67!^5'=H2?!% &'H42!E9$#<6
+M60;R"I08IB'Z(L '8!_K#VX2E!#$!]41AQL<"],AZ!"X'^D<Z"&G U 23A$2
+M!1L&\!RH&$ 6Y!DD K<)C I?"180,!9M#U 6\1-S'E@5?QPC".L>; ?U(ZL+
+M9"(4$I(@= E;&E,!Y1^)'K4$IP/5!\X0M0D"%84++0*D$Z\1HQKT""4<[PN$
+M$LH<2Q^K%^P/<PV]! ,%NQ^F$!D.JB4F"XP+TP.P(KD@Q C=(DTB[0'W!C0=
+M'"8#&X4C?B*_ %H,2!7!!8</G"*B$B -S0XR$DXC 13>($,AG"-Y))@>]Q?E
+M'54BQPRX&V ,&PVT#,DE[22=!5XB\ XW(3D/R@ , A(D.1+! OD3,1G.&E,5
+MY18% L\;2 1J!#8B7!$['"0AW!1I!CPB8!^3%?0#CA]6(C$5)@Q;)D4)O @]
+M). F"0Y+"X@#D1#)#P\:ZQK3%1 F'221$-@5)PW-%VH" 0R8#9X!6A V"L 7
+M!PRO".,4$14P&L8FO@CA'0H9_PC=)?@/2R8Y(9P.UQ>Q#^8(G AA$G$:5R%5
+M$9@1H"%C( <A.@QP"PTA@A=+)9T,]P6# Q CR ]5"$4@&!_<%&X#_2$4)OL
+MQQ?T$<P-/!%?!=\C\P^\$AD1N29V&\ #QB8Z"6(8B"#)#;H.6Q/* "T5;!_Y
+M&.@8!PZ]'Z4@JQQ9"'0-W 2_$CL"+P'_%DL6FQV &;TBYPB#!$ (^0?Q!&T"
+M/B+ #,$*>0U@""H?)!&9!4T;Q"%?)1P-_ 1<%1@ [!U8$(4BU@2N B ;)P95
+M#-H@UA?W!7@ 3B.&!0DF>1">#>4"N 'C%1@)7PJ/ 9D%[@03(3D'51>L#9LD
+M P.2$4 (B1DH'.4'XQ,9([<:L@OW(*0.[1M[![0@> 76$J8E02*%%@T(R".1
+M"0,AE2&,!*8>^B ](G8:Q0!%&T <;"*:!,4F&1/<$64&T@H$%+H&+"5A!9D9
+M*"2&!2 HPHO&[0C>Q(0( LBUQY%#7 :IQ@F!^\=?!6K$AP3NA9^'O,2+P/R
+M)P,#!!T&'.4B;0E>(#L)N HK '8%#@#C)* FWP\<!#,4OQ[G$6T@( $2"U<D
+M-@T?"KH.5PG'':<:/A$%(R,3"0C]!]D>4Q&A$TD/F 3!#AX;SA8E%0($\05C
+M&[X>]04G!N@,HB(U"1\,*0:Z&O ",QTE$-DCC@1=(YXEPAH_!5D1W0W.#!(-
+MJAZ:"W\A$B3#&64D(PHL WP!TA(R&9D/;0%Y"BH!' !C"G,DY0B/%9 5+PP^
+M&]LAS1," 1P78B1A#>4%!@9"!%P*)!2!&H\AUP8-'#(?;13X(:P 52!Q'] 9
+M_1,Q QP6) '7(I4=V!4T#0T2,AX@%JD-30YS ,\:I0P1#W<7'04J'"X!MAW!
+M!@L1)P"W$V44-"+E$I !WR8% [8>@A8Q#?T00@_1#?0/+ 2['<L7TQ$Z'90>
+MO #E#7P&CQET PXC:!/I#]@4O &H T\@_P2^$=,"^QO^(3H'>!*\"M</!P C
+M%5\(%0W%#/D292!P"\<.,00#)0,/\0 /)+,=1Q2M!6D"PQ&_$;4 #PCJ%\ 9
+M.!ZC(D@(.!;R#E(/!A@B'5TC-04"%#D.DA/,"@($Z@$*$B D: BI!#8@:PQ+
+M%40(TA?>%>,2]!"L(+H%4!Y6#OH+$0N6 ?('%A3,(5</@!*N%Y84Y!4"(-<;
+M7 ]>%OX9;1%\"=8#K@&#'L@!-@B2 Q4E- ^:&6(21 B2&W4%OQX.(_X3?0,G
+M)N8+BP6 )>$DF0_+ K(@^0S8(/4%8!-X!0LB:"&))D AEQ\Q"T,A9R6 (:0?
+MT1^=%/0=G1JI WPCR1RY%*,;,A*?$CDAO2$_()\EBPS,(WD0Y0PX'$ C-B9D
+M&ZL(F U.$W ./A* $^P$[Q[O!5@ 4QSE'U,"<@2=(6HF"B3!%H8F/!K*&PT9
+MX28W%NP9^P^/(88)X".] +H?* $G$#X0#@['!(,'OQ !"F<.41.Y('8).1:2
+M(R4%L@F%#UH%LPRZ(M,6<2,S!#@B3@M0$PT-PAS('WLDJQ,'#5DCGA@%%<H+
+M+P%%$6T>5@XC&LH:P0/Y)P4=&@9C%FT7GA_9!JD<J04_$9P+? B!(&,.5 ^4
+M'#XF#20\!=0C9!;'!WL0XPS_%"0=TA8C %T&3QOJ 8 %>QT: H@!C0TT(#@%
+MT""["+4C\P'A(\$@,0+!)3T=40O'(VX ?1'[(.D4"R*O"Q<0+!?P%C@&$PJ,
+M%_@EZ" ^$D8#U0$()+D<5PW2'[0)% $8&VP0#Q2R)&,,4P^L(1P*; N/ A\?
+M805M#@@6^0^"!S4$0P0(%8$DD!N4 IL98B<"%XP7JPFY&.@:<R&'$'D/BAF)
+M"<PD#"9F"W4)FR#K!JHC(Q7^$ND47QCX&,86BA.&)!<87"-$%HX7X@QX%?4*
+M=@C*#RD*!R.D)64&C D(!5@;- RB$&,F#!/')&$@:P)C$C$9! 4_'L\B=B %
+M%G(>?!57!_$,'A>O".@9[00;":H2M CO'P$F5@VK'(T&91P9&OP52PRY"W<.
+MF0R&(5DF@0MK IL$P@Q&)'@72",C'6<( 1UB(!\6Y@3&)1@(A \:(0 : B3G
+M S,EC17&)&4'"@P["]8B.P_H#^P=KB';#V$&?!.N +L5V -((/\F[Q(;)!4=
+MKB9X"ET+Z0ZF%D,!]0X4"9@ASB3S#J8*K1PV%OL4NA0W(A<)@A(Z(LX>- FS
+M!&@@X"!4$S@4;@+< 0@2#A*($?\&Y1PR&)T4I!;7)$XF8QOP%%P?*QV_ 5HD
+MUR2N&KX1\ ^3(S(7V1MI"04&A"(<'O 3,P"]$&0*(!E=&/T=+B#W ?0<*!/B
+M'HD-4@0?#-T@#QM8#T@"<P'1%Q$92@HD">X#"@$L%O<!H!%@ -$8$A]_#JL<
+M&!:/#;,)V"9N'O<!5QTK'U@/" =;%#86,"+#'B<2"Q5[&IH:1!O3&)(&S"%J
+M%%<&R0+U(AP&)@;1!.0 :Q/# O<93PG+)8<8>QIK)0T'&@:4(*@8G!')'HX*
+M)0<^![<0CAR2(" :,2 '$G<>(PLG&@0&RPU.&8< *P3: 2@>20?9%*L#-0 2
+M!40:,!1J ;4,E0>J$; '0@$<&\(", D< : 9HADC"GL3OP7-#;HEFP2_&#T%
+MQ1F;$D\,N@ZC)EHF(@?"'%L ' F])HXC7 :X(<4'"!3/'5<"D@H]&UH?]2*B
+M!$ 5CP#1!LP><0O&!)<44P^W&9H(WA1/ UH$3P27)BD#00ME&U\*4PK/("(/
+MZ1A*%[H$MQLE#[$9[!87'Z C7PGH(^(BBP53%&0,ZPF(%WDEE!>B!%L21 [/
+M ]$FM1S#(M\8< ^ B\4T1AE%CP5CPEN%,PA3A@N)/H/'QD>%<(A1@P$$;0A
+M9 2)#TPE)P%D!=,'510_%[43'B2]#GL9 R*7%\T9%B7H(?<-I@M9!\0.#P.Q
+M GL24PQO"] EO@-#&PT+PP]$!^$4GR @$ F"@.%!2@(=@3O)BT&5A7J%R03
+M+QWO%>H"#!H"%4$ LP+M$&L/I18C)'D (2!Y 08)-R67(5P>U2'7&X<B4A'&
+M#EX-=P6 ')(@70Q_!RL6:1V$''XA_Q_ (V$@TQ ;&BP:7P7+).D!V1"4(LL8
+MUQ6Z![8+ZB#^(M4 ^QG6'MT$VR6C#&TAIQ2 %!0DAA06 $P9Z1]6$GH'?AG/
+M'Q0> 1^-!%P!#Q7'#R8!] FH&UD6ZAQ1!P4F,Q?#&QH89!>9%ET1\"90 5H=
+M6B&'$.41!0C_'8$("1[! ML.,A-'&=0#X0%5#^<CX2:<$DX'A 'G"$H-WQ_=
+M$*46K",O#Y\;D@MQ#N48>B0@#I0>* MT$NXC,16) 8(6ZAHU!*,+_1<[ _$&
+MB109 ^ (@ #X!? '8P$]$$L"]2$6 HP;JR"2&5T0TR"3!<T@4B4.%1H? P"E
+M&\DEK@MO&!470R64(^,1%1JW!>(96" E$P$:714K _P;7",,#*X<[ .G"QH'
+M0"39"!,8SB10 >PD>!]D'2 3:@TJ&E@D2P4["\\E,!L: >L='""G)(4:]".E
+M$(H0E1,6('<($2/E(O@!+Q=&'&H7R D)$:\>>PA]#+L@D!Z2"FT!;P0@$*X6
+M'"7;$R$/'1\H "D$5PK=&[$2 2', *0?""-'!A,5<PX!"[</#"#D'EP#R1^X
+M$^X1-@1P!9T+P AE E<;HB:D%<LF#Q;+(KL3CA7"",,!@!G1!&T<;R+("R\+
+M^@?>(BP1;0I:!TH!(!M6%8P/.02.)D4A4R Z'I<.< -F&V\!A1V&!\\@0@?^
+M'5D*^R N!)44" !Z$D,<11_V)-H,J" <'7H@IB8")?(B3@NP((0C,27^&V G
+M#18=!_$$J +Y#[4>L2,$&)P,!A(7#RTB?14D(5433R;% ?<2)@$H(:<'%@LH
+M'3,7UB+U :(E1 FP"%$<]B:K$3\)= E&(?DA "#%&\,$Y03<%S<>1Q</!^4%
+MPAW2'(4"S@QQ(B4*P0H=&\<:*PI""18.+"5/)L,(-!#9'50FT0-9!)L'/P)U
+M!Q@3EQ'W"H\)/!0="7 =I"#^)H@F$P-4!Z88]B/[ F4/F KP $\:UA:W'HTB
+M'2:Y$B\-9A9] ]HAK1SN(;4=Z2/8): &O05;"0T?R OI&QD23"8%!JX6I10Z
+M#,4 O0@O#0<3=144$2$2T06]"/$/^PJ&'FX?^ Y3$V\:YB0P LXAV0&$ L@(
+MTP=2"]<6#"6\(>LA*!/4):LE'0=@$]D&<Q'\$18?L EN&=0FR1AA%=P$: @W
+M$!(;%@X2!Q\(GQ6:"Z0*8A8!&A(>8!/M(5('CQY !9 @'!_ $T,%2QZE&!HF
+MBQFX&Q<:BQ0K'=T>NQ#Y 5@$ @HW"D$?U1.Z&IL<@R,;'-HA:1U]"V82C .V
+M(.()51UB"-4 _R+N'E<7>P,T(O45C0'J%/T##2:M&"$-;Q)?!N$4 1UN')\2
+M'1*S$-D,&0R"!DH*S ZF$2H@#0>+!#44'P2;$<44GR%*$F<,\Q(B%TP;'!M'
+M&P03S"27!(0EYAG0 IX PP3? 4@<% ^B%LH4NP*L(P(*RAZV$X\EUR;+'R08
+MP1"!%?,39"%5&&@<$1#8&'D6\AC$$YH9_"$*%O # @(J!18/VB X$082+!>(
+M WH3"PJ1%= =<@/0%<,!: <<#507EABK)&,9H1!E$E(DSB88#I4<!"54"^(2
+M)Q3:&6D4 0BK&? @400V(GL(*P)O&L47Y25&(3@7,0@6(L8/VR%;(; ?K1'N
+M!EP8?"3U&_TE$P_!$'P@Z@&,"G<'.R&T#T$$4A."".4:<1%4#;(48B*;'00;
+MUA!A&;P%\AH""'<1M0I(("(!U!0W(-DC0"5<!T<1F"/>")4AT2%1!@H0J",V
+M&J@ :A3M(!4C PT, GX&>";@$;T$(B)A)A\(K@MH!L<6^@%!!D(*AR(\"4\D
+MC1D0&<8+1A"!#P )J0A<"_8?(A^)).4(0"+5"B0 JQ73 @P@'A?[#S<F)PF&
+M"78'U16!$U,2;A2N"><?+ .W(Q@%?P6@#=8(5@SU$J( @"$"!YL%M U@%@$*
+M%@*) @<@#Q?I%_LFIB;\!JXF*11I 1P>%PI (&LBZPX,&@ +>!*B ),*LP>4
+M(J,25B4N V,+_22[)(0)N@21(3P#51]R (,.V0O4&6H52 C4(LX7'P*>!+@$
+MP@#D%]H)]B6J&&T%$ALA)F\=Y0^-(T01]1)#$QXD+!HL(T$7.!&]%#(/, ?J
+M!F\@Y!!W"EL%6A:M'?0EJ2!D$G$4;R" ,@_ @V!BT+]00*%5H#CB7U)GP:
+M;P$]"PH3/B6C!78DR 1S&CD$2"2!&E$")!O4$3,)AR)F))43G24X)8T8)1(9
+M)8H*.29D#'L,ZB04!G($3Q9%"%,+?16%%;0'/03?"Z<4"2*%"C\F?1^W%I(F
+M Q/R&KH?.P$M&J0(/AS-(5L.#QK %KT4P@O])AD4)R&8'C$7, .<#%@3;0\)
+M$XX-KB5/%-T&001$ ;$&)!<Z%Y8-V13*"6LFH1W9(L08,":"!!,2RPSL'F,)
+M\1\;&9X 2B,;%EH3H@M!$F\3W"0Z%7$%,@:6)/0152#^"!L2N!A+)=4"9!9S
+M$8H/6Q9)#?\2IQ5)!I\9*R"8(3TC^1EG"Y4;+PJF!EP!* F/!9X'>A4*(*H0
+M-!-S)+@@WB14(*(=:R;>% 4BD0M[!S<?&@1D U,+?R:0%A<#'1'('F$>*R$<
+M%.(#T0X\(Z <Q!+C(=TCQ27('HHASB-L'3H&:AFR'SX':B3> _<@>QO<!N0@
+M"A7V!;0B0 V! &\B61KX(<$$O!HC%<<*Y!Z' H8+V@Q?!@4.'@"B&V\,D2&B
+M$CT!6B83$" <\P U!S0)EA6($1D5K2/M"ZP6J!P^&'XFGQ%7!#$*D27@$B8;
+MPR0B$L8E?AFQ!1XD>R#B(4<7'0DV!$4G!1]$#2P7^!#A$C$7<!8]"9X/$ _Y
+M"=H8 "!+#3 FPR1P%<X*M"#M"^<!_R1$&&86-AO?$W $EQ 8(\4A31OV$!<@
+MJ0<2$=8"FAAA#S@2?0YP)8H4]29\(C\%%1;O(5L"JA."!#X>A0-3%UL*6 Q"
+M)PL1[P$'%'0B,1S$#Y\!S0H9&\0!,A0@"K4&VA&_)$@&B @*&$T2L0;% XT7
+MQ!PH'<$"H0OT(=4100BY()8E8QD\&ND*D@]9%"\#QQLV)KP9JQA&& $C\ /R
+M")8C=PL%&XD:^2 K&3T362') XD!ER7O"1,*:@@K! $5#P39&E$D("12(0(D
+M9P6V([X&1Q!*&8T>906[(.05 #"&?L<]P(!#?H+21JS$J@/]0(:']L,>B3[
+M"#DA.1S)$KD0>27V(KL.*@;K(A$ =!6D')X/3AKN'TP05!OB%'04MPHJ#>PC
+M+Q8>$GD;.1&-$T$%WA;A(>\ 80]($:<@&!5Z$'8??P;2(9 EYB,Y!?L$QQ"7
+M S00>@2B#@,F]0;&!1$@4P?H)L 7MQ<4$,H#?P\^"CL']R%O"9X!3!_!"H@;
+M]!.1%EX1#B),"EX*HQ,' /0#]R<#!O40* ! ! %8 _P'\ TX$] ;N
+M"3T+X [7$B(5PAFV'?XBFP ! ! H 9 /H ! ( P $
+M ! 0 " 0 " 0 " 0 " 0 " 0 " 0 " &/ 0K0
+M , $ @ # 0 !0 & < " ) H "P , T #@ 0 !( !: $G
+M$.$ !?40 -2E .AOP8;R "-C$%XM:\< !:$ S.T;SM/"$ "83XESEX@3^^!
+MA:Q!6RUM!.Z?$+-+!Q5[R9?. ,!A +GUOZM<I/'#8RD '1 1TD$.-_WU*6
+M<WOQ 1_0;$KEG"5U@Y#C06O*=L0LQJ2" Y4, V5?4<4&KHA $D-<]3'B/W_
+M:B24#PQX!!00 )#9E&5"+-=B10&:(B873R< GQ\!OVKM9&XXE^W:I_GTZ3]/
+M P 8%Q A6R]UC[FJH3*>[)U3$XC'M8X ^$ ]C3/9C'-1OY5Z;R).DKJ'0^^
+MD.00 '&5I?%W=2EYZ&6TJP=D%;41F<RG%AO.P2=D8Z(8RN^D>R7-T>]P:]\^
+M'YWJ U]3$-',[B)AT_H(>>#&VB9GVWFK98X:QP@ @Z$ /6PP(V:&YVWD)K8X
+M-<<L;#K-\<>^+AN. !00 &-18(_9N"%T+[ .4,D^0O3NEW9H"<1WY1%T ..
+M@>$7LCOD>- :'$8(#WGU]*=BYXI18LW5BW?9CQ"H+D,(JK(:?(XASD#SBLX+
+MA,0+)WSKE,.M)1))80":M((ITUJER^T:N:]>&++91["WLIUC%#^, UW[ LH0
+M "8->2O_?&GOX.QH':752NMF2J00!S?T]#A&,@T ]P!M7D$E?NX]+NL2Z@\B
+MX#.4_;8.P)OM>'Q94\ D9K@3H?4 $,L0F$$TB. *V\@C LI__069F\)W/.-X
+MS([YW2=KO8YFB;8 B$ B@P7NXZD5J^?J09'LC9=2U_@@-RJ"O#^V4"HCH#0
+M:QIC(Q ><D-P.G?*;/&RDW,7E5<X2P\H&$Z2=O2>,5,!M:XNT>7AP\@/@$N
+ME9D) ]\X_0\5Y"\C=/7LT\_<",0$L-J\S7\9IC,F ^D? DX'$*7&]JM.21MG
+M+0)N/0816"GK=AC1_=-AB"+,W5\[E.Z,4+PJ<@!:X0"'<Y#[*3-S8B).-:X(
+MXL)]OM.'_07Y]SM/H50_9P=%U]0F$7'"&@ -$ >A6%;;D\J:1A[XAP$4#0K
+M+]TG[F-0<9FFR>D6CDHN*!<(;F\:21EN (MP?=8_,JV9$LH:7R7@-!8L,7(
+M+6L7=[<<Y0333C$0-J^+TW/4:5SB4@%#$.1[N%W(TN94AS<(&(2>+QIXR5#[
+M;,?#E':86LQ)3B@IUOEETUR)53P,@Z$ #NO3K:=!3^3WE3XA71S[W#*_7QXI
+MR]79KU?2V(2ZS+]DL*+]MQF%WLHQ >@0 -1!F!9[7-/%.( .UQ\[3_5K7HN>
+MF#-R\%<1,$'!S/DP.CW*+5EN2] N?95: $HM@?O#T/12(BA0MP_R\U<3%!/<
+M0EU]UCD9F?A9.!P DA36AK-WN7JE_F$2MV%J M_$'@A8:IP L&(P!90'GM"
+M,WG5, 1K(-0)0!AXZZ5/K^=VLUV_'=^4O\8S0#][O(T 6$ G',2]%T'X9=X
+MY[$OSEFY7JK:M#=9[%D"T.GA"\?D?8B$(7@NHFE(?1%#O()-?T/5$ !:_7,?
+MY%0HH>'<3F*/F0=<_^F^@:X_Z]B;)-V07):O %PWF0DWYJN85#^8PDVSO",*
+M63U!^-(BT#/GI_/VEE2%CZE^K[8<F@' %E(\X*S%+OX@/R/]HI^YZ@?W'B;Z
+M-W\C"U%% 92[$)1X O=TP(P;70"P\,9UJ=NY%.+9<M]E#TM,=RC@%FWVD<)1
+M0\G/)Y6K5=;BYB><J+&F #TA *P+YQ>,<_" Y6"M,%5/&/BW*UC-28VK=U@K
+ME?UMCGN1NN=?;3)62QNN6O9$=#F%GGQ':>L "1 <KD,L&]SG6X:LD8 >%UD
+MA -_X\,A7..I*=GX1)'"X,?R2JY43>_67J<5VMH8(WV<J=-^IF^Y %= :R!
+M?A^IX>$E9!*[?G:=H$;QN#R _J?/3.:BT %SK8SLUCABB</$Q07]'OB4H6[5
+M6DY)/>,X'/<0?4"U0OA.SSLA>ODE<6O >3OT;.)DJZ^;-\%*0;6-U&8! "A
+M)TDQ+X'P.]_^SB1!)!Y_(L\Q"(_A +FR=3R"B!:3S3\Z:XFTA]X(GD5&:$VF
+M#/W;DY'?).P3,&A$)YFT0>ZV@<K#6 )1\=EH):)]=G&- 4X0 -MUE!7R8^(:
+M<&$3 1 J9..PF_^P2F%$JE0&=LR$Q,@\ H4ZTQ&F>%09'WT)[1#C?7L *4S7
+M'J;T"#, ,XS!E<Q1R#R<[Y!H-6N&Y:>V%.7RE!,[^33:C9(Z8+P"B=W2DFU9
+M4_%=3#-E5!1F_-*V.X0*+;P38:G)< ',Q"&.JM;FCKR/[K=,D;;V)!*6.A)
+M1L4HC,8?,%N:%PAE@'PIA+$&OW6/IXQ5%^"4]1;T9H;DI[WV0K7F,"P :$
+M06JG*Y/%U'A]QNKCK2ML*_R$2_!UKA1U6'LT8K9ZVX,1#%4"F2\B]]ZP[ "B
+M.\VD]<5/BEMEB[B-\]*!+FD0 %4Q":M8TJ8,)LM688.':ASTP76'Z'8L1$?/
+M0: %GLD(!CZ@NLCHY\_ 5>'Z1++O 7ZP)" E<]%R^8'DN 6N!Q7,@;2OC)E"
+M37,&,OO6GOG1PT .R)-/0[@,L83U=>/)6_2,8I/_!B27&Z]2^8N;(8O?>#54
+MX;-ZUE\%>9+_QJ4M 11O$!,D-"+U1"1]?CV#IY3/&AZ"2T Q6?K,9:0_!WF$
+MK;MYLX#I:G%9:84BR6-96OU$GD-9:%-IT,8.Y9\X[%37-G0 *F$ OS)S"[@T
+M>#PT8;ZSZ@9*E)6LC?&_:S<*_"#_GZ;S.L[4F]@#R"WLF]NIR=Y)^&G"SP@T
+M=ESKDP6Q**7)%Q\@,G#O 80 )_M^MR S</;'V@X+J=Y6/6:(:SF65@3U:IF
+M66B;,2A9[ZD5H'[&A3N=JI%DADTU:3BC8/>CL0%]0.\6F$0\I*=\V?N;'$%*
+M)VX7KE?L8HFJ[R+[W;:B[^07X;WR,V:(@#>T+#Z_N-Z1&:QD"-3T:DXU_VH.
+M9U:Y%$#;.\IX*IMH:S+%V?6O:;PF9*L0E[]MP#<\SKJDL34AC4T^CM8>Z:K
+MQ-U;#]?\%#Y?"D =4?"V?&J*@Z=>22C+'9^.K02&[8R%\;^@U6C6?.LB(&4]
+MLF(%VR$ KPHS)ZA_2@UAFW(QE^N@;_UKH4L+Y] :X#;/JH5F;80MH,G9$5JP
+M+-T"Q DG^;G>A)BD-A_F2F&E,S_JJZ\5#Z0%(Y+5Z #D$ ![J3XEZ+ZUA<'\
+MJ/1=' <>/"NH6P@,^7%=( +6 ! (FTJVLX;J;+EE.0'!28QY=?F-W)&;(6YQ
+M[B.)O=5ML+0B!H:0)[OMZN, (GP!F"Z'6[[3GW+8V2^'$A50QFO>;G#/2M@/
+MU95Q;B:R9K"MQC8D'1736CQ"5 YC_W/ S%7O%V7Y*/)5O,?W@-SMW/1N[\Y?
+MW%/W 7G$)?+:>@FUW(^M.2JAEN0.2*<,P=U2WKID2U'^7>:;D#G%@OXQ R2
+M\!#R7VP1)<.+0LGYD9US"WRO!?\MA;!#=6DM*X0LIE?O$- ?X0",\0VI/IF;
+MS1NN+?K#!<X8D.=B)4[#NY3)$[]8CO!7 !>7:YTM%7+KPY%]"R&MQ^.CSR.A
+M\^B%?4OV'#I (G!U<9K]I+J:>F'?:A_!$ "H9:\1.J4!752F^=GZ4Z=!7N+;
+M;+ I4422SWPNG#*%SX>VJ&D4NP*189F;AXCD&%/D<-H.F^^(!TV^I3<T;N09
+MH,CGE493B8DO3(4G!-CKP:'!Z 9)PI25N7IP3X%"=:4Y.F,+BR'"5MM&=!+]
+MQ4G*FD7B8D,Y:/185&'[/Q-:MN6[236I.^*AP$PB%1B0ITY$V"V&@DN=O$JG
+M2=$ O2,0IPF##DV'!Y%$3"H],T.1"7N3YFO(+%2:? <@E?$&B5@RDBNJ!1O%
+M@F%#:BKE(V[_YH?)79O;RN*[5'&G?C-:GT\'3.&8HI.A,X%_=.(3 !RA -3I
+M;%Q];YODV>?Y.V^A=V(T4<:+6>C>*]Y8SSS_6")&?!6H5W59)N=G4Q=WMV/K
+MY@I?X_TY:3/HH#6H!;F']C$/0R$?0]O86O66JQL9HF@_ 00 .8AZCS0>(UC
+MYSFQ[Z<7=2BN1YVK%,M]:&]F.:U]'_56^8K97OX_L5<@'Z@TCL3D6T+NS&6X
+M69]"'CM;PD,3]E].P,U$G[U%^E1C]"EB.R#9K"AK@>K=<ST*_S@CJS@-EH/_
+MQU "1U&_L:R3@@;/D[V"=\0/#?.>&WT[U?]T)N'J.'B3N#.&,\ >0?C]3KPD
+M,.DL49<\1.8BC?]EW8YP1?$KC=^#&D1?$&DWHJ::A=C=1!#-@!L"N203V35)
+M6SDA/ QR!]I>^YW8 AH T>C03 LM!]99\?A,';CJ@]S2]1]MM;Z? TQ%/@0L
+MLYE2W T>>@:+*\P^?//5(EH$ F$ O&$;@0A4&32%V)B'7L27VC0=I=JL46K
+M*C*UABWBT_XOM>1B/1^1-NT*^VX(-%&\0#W=]Y9NL@!2JX#K7Y.'XQFF&?+3
+M-9\SFE;1O])NN=@ U)-> )P0 /3="5)=14+AKK0T+J.SHV\_S7INM"AW]TO!
+MR-!GTOC@KJ@[9ZW)5K-LR)T+E9W! %M(BCU*OC;T4MGH37';(<7Y'($)2D78
+M:M>J3'P(X:6<=9N( .0\ !?[03A\6+R#2V%T7XB()CCJ4,!RG&TN.^TU7DB/
+MF<2]UZAY@A:$H,JT4;J.25S&)M3)\_R]LO>FIT3R3'2>(C"OVN>5DCL M_6!
+MI<RHX+L?&@_UD?)\@*5# .;$)(6.%ZO.M=(OUY:\TEF5*_Z$N9<ZGBQ!%H4
+M@U*UYA.'E16]V2M\D(X0" P6QVBJ'+6@]P#VOD:-?<4;RLP1YMVXAL;2VU!9
+M879(I^H)ZE</_X]>1)POCF<A ),)[BK2.8<\:+G18RY _R-L"X_H$J;0!\A"
+MP-Y\:>4QATH#3[BXL8).CAW24%@$+=/UB[:#D EVZA25T%Q--_,5FH=( U9^
+MAVHC-JQ>/[MSSSAG/OI2KT05NA E)E?#_;GM]//,CLJP_-./I2>9OR*511(
+ML=[^;N+]W0O=F%*4E $"3Z7VYQQR#"H2DO.5MSY1I7.NL3"WEJR21=@I;\MD
+M!'GR"GZN\H5'2I&8&@5^,N%V<LQ> U"; 5"<K?''W*TL.#U--W/&9]#J;:@&
+M49OR^,0#X:*@4B,ZUQ!SJ42%V;K/$A@#<(<ZFU+<4NCELOM.!Q>F+[Y-U^$*
+MJ^U/C&+L>\ZY0"'49H, H15UYLSC*?*$+P"!UQ#E9J)<'$JE/^D\/01R*#ZJ
+M4:>.)=!3 _/:0^8(I8TB%N9@&F"<]OP4T%@4R)T:5]NZL9,DA<:Y[!C(C06Y
+M*^(9V*#?D-A5FAL^I2B;VBE0:%A-@/1U+9QC<E;#.P 3X0 !,$S!(V;Q0=#V
+MC]9#S^(+E/^1Q;_@8_G9RKG-]NF4H@LS:2=-9N4SD_;D2LK+\JBO=\J\G-.G
+M*2#>EQ@U- S1#( *#IIMW[(DTS _Y\+_R4P42+E!?>T15SQ"(@/Z ,0 (55
+M,S[,%@!VKC"W0MOBV A+;38,-#Y+UW'A^0L)Z1W-CMZ%)7!K(__<6:$SO(7A
+M<3UV:H81'\E^^6$>@U9.K"Y)],3(0U@PL)12HHX1?+[M]$?&*RWH<@Z[[%UO
+M7[=URTK!NC@C,2"$,Q*<M$@6V@URQD!"OA^&:'"B3Q!#D!E3Q&P+'&@!*A=:
+M#OG/(^AJU//&&\#;,<Q\>\X#/4N(T@OEA<_(NX;E1LJ-X8$4C0Q[,I(4]E2]
+M2>'$)]R<ZK%82A'Y$Q VZ,9Z*9[T%C\*\TFFSW>E(Z.DOEN"S*)R+S401'^^
+MG1.XJ,(R3LE,,ZV\GOZZ=JPA,BY,S3(^$Y&T</[9-KM<EX5"%!K]1LS=^.8X
+MA])I!]$7&@+Q_CZUJZ[#N>YO' @"OJ$ R6@& ,HIH;F;WETN&P^VQ"%Q0U"?
+M0X86:RG2;*D(WT-@E1TB(* P;;2'X\)>9\6>PSM]T'@PY7^0N-@;WIW:Y-?F
+M1%Y$Y83>LDT-7IY!MBFB=@X'U=BC/$9QA,+MS1SA(B< :Q AQ%^N^)Z:6BH
+MC>RH""=,86GS:AHS==.M!@6K&NB;0OK>80[<;G*FRN#3Y:NZ,'I'3M>JRN8R
+MPT8VA+3%]<F,-ZG&N-$[OBIC]!9#%,T:N;4]*PHZ1Z1X8;;XY-\L$3E9%]A8
+MY@ 0"H%]3-#VD0X3Y7PXEXR.3J_7I\H:@)VJ0YRHBT#+:1ZW2).N1V1#>DNC
+MB?X6"Y'9P1A^IQLO 8"B#%>A%R5)\=O%???*$\1-H==B?M'<39M\!H+U=\]7
+M_DG>8MMZ_"M);D"< WZ0 )/$&I:G'Y2PC=R3HG?M-W_U"9==$&:Q*L5SL !
+M$V<MPWR*V-?(R-B$F7M=:B*^+^W/P7CF[T.<)?3Z&<DBKUF8RIBA^)EH'J7\
+M9'*1L,>6M;8WE3P9ZT0H?4V5]2+5YE2JFD8"\,YA;P 0 " 0 !P *
+M X $@ 7 !P (@ I #$ . ! $D 4P!= &@ <P!_ (L F "F +4 PP#2 .(
+M\P$$ 18!* $[ 4X!8@%W 8T!H@&X <\!YP'_ A@",0)+ F4"@ *< KD"U0+R
+M Q #+P-. VX#C@.O ] #\@05!#@$6P1_!*0$R@3P!18%/05E!8T%M@7@!@H&
+M- 9?!HL&N ;E!Q('0 =O!YX'S@?_"# (80B3",8(^@DN"6(
+M $ 0 ! $ @ " ( @ # , P # 0 ! $ 0 !0 % 4 !0 & 8
+M!@ & < !P ' < " ( @ " ) D "0 ) H "@ * H "P + L "P ,
+M P # , T #0 - T #@ . X #@ / \ #P / ! $ 0 ! $0 1 !$
+M$0 2 !( $@ 2 !, $P 3 !, % 4 !0 % 5 !4 %0 5 !8 %@ $8 16@
+M 8<@"48 "H"D!WW$HT!&090 [L"X1I8!S08(!TN&),EC@H5""D 0%0$2L7
+M+Q#Q!9(&620, < 8 MJ$V,A4@K*%.0:RB0- #,%L!JE$-T1_QC!$AH#JAHD
+M"P<!5 &@ E8.'PI8!R,4[0Q%"_8'P0+I"+8+H RV&9\+RP9<((<.9 <<(T4<
+MH@"C$@< 100#C\'GQ@;"5TB[R/L)<0921]U 9LE\1:4 D+4 U[$B 51 #K
+M$$$=\@D0'M8.^Q^,#QH&QQX> #X(T Z#);H@RAGP&K<890ZR&/D(]P\B$_$!
+M+0]=#K$!FR0 ! $# FQ#]D0@1OH',,8HAMK!>0:#B9"$\<:#R;:"H<F,"0M
+M!]P&1A:T&"T:VR#%(%(A0Q##$X\,X0N.#P,2JA)B'?0 2;0"Y,CJP^G%GX!
+MB@(T&:0F=@S% Q$:WQ.0&[H0BQ@S#I,#?!:@ L60"!<(< *(@GZ(MH3&0?0
+M =H&LQP6''HDFARX!<@,SQ4J"@<!:"*7 $L+\!V!%-4;9!<](N,/B _.' 8<
+MLQ/7$=$ 9 @D!;P(R!6B&14F.@XX#* !\1]0#6L+K0T[)94#[R7&$FX&]@ *
+M%7H+J@VF'@(!^1'&#!T+AQS4%#D810H/#+L9L"'U)90 %@_7'GXE_0BM%[X;
+M@1M2&7\)- '$%XL(0ALK&Y43G2 O(XP7("'_!4\ A* '7@,WA+K(;8"3B(X
+M(^H)02)J$T,D8!7;'B0@\PHJ&E(4G0GG#ZX&/@K+(:,!SR< TA,!(-$Z,)
+MB!S]"O D$!41$[,>"Q9Z#>$35@F1&DLFY"&Q'<\@FQ^X"Q,9*R&<)8(1;QSG
+M %L/$!UO)B$#$R'*)-L:,A@(#44!K1''&](96 !J(J4"$0RT!M,C,!MS'F0;
+M> ^""_< 90!W"-T"61J@(T88AP,F!APBD1AN!9(7XAPJ&^T<,1"5)'PE"AH+
+M&9 *D"8+ ?L7^@"/#ZH*YB/\).<'JP?6#V0-,!*-)?\,8PX&('H B130&342
+M%1 7 *@=Q@_@#>T"DP4#"+L+#0)##.$'4@$M!K@7'R,%(WT?EA-[%KX B5
+M"APF12#5$Z,F:0MH&C<B%2#U##0;A1E?(#\)K@8V&V$%6!=H#RT79!>W(:L/
+M-2*8(T<,] XY! 8,T"0. ! %$"6_#%80OQ'1(/8E7 36%<\10"8B!CX)O C*
+M"0@A)0C%(]\"J1GF$Z@@;1'>'\D)'@Y)&:<@>1<W$N B2"-K &X2, LM%X -
+MSAYQ"F4&1AAL%><-[05@ ?L8+PD<#XL?L0]8!PX QQ_5 EH<EA>T&0T1 0'%
+M(K .WQ-$(LD5Y@E](,,"UA7P(S$- Y$%%P)0B!$!CX%+@H> X<6C!HK @T+
+MUR6N(8,.LPVN$$D7O1C^ 9<(7 #P&,0*6PZD(3L!E QK#FD8TA &$IL L )U
+M"R4D2!V/$7\+3P*6!+X;$Q=>)>\-HP$R"_4 >!FB( 4&R@GI)7PCQ!/=)>\*
+M:"96'3T8H21D"/D&/0Q")L(!.Q+W!,$ Q#P#.$@BAN9!O<4W1>^#M\3M!\D
+M!N\D6"9=&O0>%Q$<'U0&/!2L&%, 4P'Z CL-8P8-'ED$_@W4$ET<41>C"8,B
+M-B*B)(8CJ1'J !00 )@&5H9(1M2)/D*^Q4,(5D7HB'((84 'PK1(TH?YAT%
+M'U(;0!RZ 2P&Y!$4%>X>*R1Y%R,6O!\ !/H6UB9< /DE9B7M)-$>^0,, (85
+M4 JK"D,5]0.S#_ .DAC\& B+Q-V!$<>LB2P 7(8)P'2&,0&EQTK(R<=,A-8
+M'DT%*@#Y YP@EP<Q$PT'$@<I"P@,Y@;H ;,:/@ Q&QT#;A% $=P#S1/2)-<,
+M$1>#"H\3[Q:M'AH1WR-K%>HFE 7N 2D%$@,.(+0<Z!.T#+L46B37&]P:\ M7
+M&34$=@A+)(D6+2"\)$DF% YS%*L611?0%GX;0"4\&5T7FPS%"=(%F@RX'O8F
+MQ"$.'AD3(QCP 3,@MQ R'?L=Z@G5!/,()A,5#U$00A'2"[H8/@L5$30!H A*
+M(]$BNB)Z%K$&$A1H%242U1AB'CL R.P$P4>*1G.&H<BXQ/M$@<ERP2Y J,!
+M5P55#U\%<1> &^876!-]$- "9!D!&W<AWQF#"<XC#!?,&*$CM <O 'D-HQ0+
+M(RL91P/[ /P"71&V'(X/KARB !@:\!(Q%/L%BR!2&7T=]@@;!!@9(1)Y#,@B
+MN PA'0T.>QUS)MD@4"6K&&$FW16](B()CA_G%440$!$Z 6P"8 =Z&SH?GA",
+M"9T.#@;: Z0071["),441@.( *(8<!C)$1P#$A!'&>$/+QTN%-,FY0=O$K05
+M)AUJ!C("M0#+$T(C#!ZY#3$A>POE "T@A2%C&X0E^0+'#Z@@5":@(0\/WPW9
+M!T82,PZ-!!D9#1[M![4-SB%S"L<$)@R0&P<D,@ $#E(,[0<\)+8%71KN 0DB
+MC@S3!APDZ!J^()X.X@45).(9W02H#-TC>1U( NX&0P99)E +B0B;$' 75R M
+M!M@$\Q%-"%8&CR0= AP101OW'ODFV!R6&S$.P!(T!X(+.A.0"ED1""3["=<0
+M7 BM#'T*929A$1L%7P'8&N<<CB3@%F<)!1ZX#YT<RP1K(Z@9:1XZ""84+R;'
+M%#HCZ OQ%=\<4 LB(N0%+ =%ZD$DP=(!Z =Q@_=%?@ ! ]@"<H"W@OW##0>
+M!A#C'L\</04""U@,3@C)(<$9A@+ !]8E-@S>'D<#/@#7 / BXP@')34 & 7>
+M ,TB;!_[)@<!U -5#M07V 97$_ 86B *) H&S@DO&GXA*!_Y!G $.R,L !TE
+MX",R)GD&*Q&Z *L)Q0, !9L1M1-6'0@$504E(I< JB9J(WH?3@1I%B\6- Q
+M#@43D@\A%*@4<Q)S$> #UAG<$BP4H0#V&=X311CP$PH;VB*\$%09G@(P#[ >
+M;QL^&)4,JB51 ,,;D M7#"X7" JB&/T: Q]F(^H/_ M<%VL?Q1_X)K<CP A?
+M"6 3I@IN&,P/ B%&(T0BL ZS)AD5\0-'#FP8R!*6&LD7VQE$ ^\)MA ]$-$.
+M*@L:(C<)MPQ%&&H<?R.E#JTB_AH""% %! ?@'%(!%0*T'=(&8A@%!]P"F@WS
+M%8<<U WZ)L@#IP&N#C$!P@<2#_8 '0.4 S\2XB*3 *D<:R6?!?$1/A'D!TH&
+M @S=&ML;Z".+).0E_ ;7&Z8A Q4\$Q "2A?"#N0A;A?C'.40EPA^(. "0"/\
+M ]H*K!C7%MX&*2(; *4-7@C[!P<8(1+]!,H9UA/R$Y$,)P>F')L$D!D3&48#
+M, X)%8D3'0TR%O8.X #"&<@ @ 8N$)(BMP93#WH<912I!&,C?04>%\$.TPP3
+M"!HB&":0)I ,'11J%"0 !2(@!7XBI ,S!3$DS"' %"("E!2?)=H0[!WO ](C
+M)0Q% *(,VQ3.)I<+D0_)#*LG!"8U&#<-NP[$"G8*O26,(N\BJ0=%(EL/[QA9
+M! 00F!ON'7@&.@>#!J0+OR,-&?H'@P<*(9$7S@<O!;D>NP7! "0)P -D":0(
+M-@J='I8*UR/5'78BJ"#T%5,"_!%/#MX=<QS^ "<8H!.Z&KH!@R8%$M<, P;K
+M)<@CGP"V%X$ ,06C)4<"BP4J(Q@*00=##E4 \ &]#O48(P[;'M80BPR')&,A
+M'@IB"HP"APCX!2(7QB+Z .P>L 9%(5H+'A/A$D\.A":_"D42V29T&*L4I1.B
+M(U\#41VR$<4C]!^Q 9L<:Q%,#TH2SA$[%J@8&QR8!1X"N2)%)2 930LP#_@#
+M;B&Y#K@*?A/G 00']@]!%]\:* :O(IP4B #_$A$E$!,A)(<"Q"0.%#P&$ ,P
+M&FT:ZP6#!5$"20G %S0COR#S'T81!"/ (7\%C23" /$,#0Q9#S(A%QNZ!#T;
+M$!=% T\>'P*=#WX B!P.!V@&9R,#'84FU1SH'VP841$K#<4*P _K!9P7R2.3
+M%UX L12B%_,6*A;V![<D$P,%!X8;.A;! *X 1S0&/,+7QD]#J,=. :: ,8B
+MHA?W&64<>0^X!)T+*PP&%M8 D24J%GT#MP N# L""PT<'V0.0A 7 *4BN &]
+M#/P7+B:V$,0+6P82 %<0X@7Q#(<?\!Q%&0,?M1AQ%Y<C>0D+%L@%IQYU"$T>
+MXR9['.\A7@L_!:,:& &#= :<QOV' D6: \ $O\<* V2!;@F%!&@$AT1*!0N
+M(6$.+00* <H,'PFG WP>;A6<",4D2B-J&C4!M!.\!N@1Z@EH HL55@4&!\X'
+M&AO[(80/4@T:'< 161W_!Y\+8P?-%.T$:2)N#EX3ZQNK&RPE]!N4$"$<F2;2
+M&U( *Q2P'04$*")3!?\6S!I1%/ D61TS$:P)#0 ($9@>4B,2& ,?3 C:!+HF
+M0!#3!0<8/1'C$#P!! &]'?8"W0+U)=8"YR7X!VL3Y"2/'788BQ; (.H-?! _
+M%*H -00H .<1D23A%(0&JB/4"'T3*Q+F#2<>GQ%"%^@2C0].#S(!'B'0!G,C
+M(@<1%.,?X1"W&\L=NPH8#Q(9I24#$&4FW0P'(;L2<ANO#5<9*QXM"_@D90 )
+M'<T9QQ1J#\0?VA6X&@$:1A*[&:4&XQ*\#PH(20L=$9P5>!K$"HH?CP*.%IT:
+M^A+O&R,BB1S/)FXDMA3/!8TB123/)#X"/@27 M B6 =4)9 :!P9)#? +)1#S
+M!^\:( 1G$RP2VR.E&>(:(Q0W B0-V1V@$><'8 -!'I,+=B,E W40<0@-$20=
+M?1M5#A E>R(^(_,4E NS"*83J!NR#NX31A49(?4$# O6#:0(DR53(#X!:21;
+M%S@%X@</!TT&)1GT#)<2H"$:(7<.)!P_#%,(_ !$% DJP1("[4=J"2[" 4?
+MD0M7'XX151W5!3P2Q@I>'=\B"B! !*@'V \8%F0/3QGA((0:K1QP%64 %A,$
+M%50%[06T%(\/?A+R&+\&?PR3$\0ES CA)G<(W0-K!B(1-P-C&FT*(Q<C&T(8
+M( UA(;,!>076%[<:=@SQ"9(91A'!#8\-F0)C @@D [7(Q$AA"+Y$IP;?":4
+M#X BAA@='5L@9!+"#\D$I ,U"1D+T! )$*@=_ Q/!I<3W":L&K<@PAX*)+,A
+M#@\Y"<D5H0$,%=L)*Q[0!08,N24;&E<>UA96(JP<5QT1(9(:1 #_&E,C0A>V
+M!/\%\@X<#+PBCP*+%"X3- ^*#<,4?@WN%+\@9@ T'Z 7!@8F'B( *PB("=LE
+ML@8G#&L&<PVM#K8@&PF3#+8+'"(5%^\3ZPEH".L0E":?%\$E]Q73)?H:D@1B
+M'"@D)@R8)",FT!8O);L-& /@(^$>@07>%049NA.6!ST#H!0B 886>")+"#0*
+M=0%*$%(7=P0((*<'?0RP(H 13"2Y$U(6?A/- 8@(MP%:)/ (P0CX$Y\AFP..
+M!FDBZ F+)#@# @DV!?$3RPHJ -063P#P&&X@'Q ,$7@F$PC&(_X0D@T"';TE
+M=1=7 TT<UR(+$CX8M0_B).@F^ YE$C<#,QAO(V@4\0*=!# E4R&R"P$5_R P
+M#$$..!%)!B0(50G:"(\<?@VH%'<%"PN1"FTB!"7Z#0<-/ !-"-T@X!_2%.0)
+M2".H$"\"(0'#"\06L V>(NP630-Q'L@"KQT_%[,.B VZ%I8/3R'^'C@-91 "
+M"GX<XA'V ;\;K!Z5$A$ [Q:S SX#"R-A%:@A3!'!"^HD41[=(A,C$PVQ& P%
+MJ0:3#=D!M09$ I$&.B&1%HL7$0]H!GL7A 4@ C 3?A-U'WX8AQZ6(1T&FA,&
+M $#T 6#)K\AC1_V%5X0M0$V'-P+"QFA$E$.'Q(<)/$3"@GK%UL.91[/"(<-
+MER;G#<<.0",M&9H#%0NK$GHFY!Y9%, -6P3Q"Y,?,Q(Q ZP44QM*$>\?]P-B
+M"0H3- GB"B 'VAF\& 8)H0HR'? A\@4.$=P>X@I^ $L=JPI](CH@=AU>#R8-
+M-A]C)P8%=P5Y'1T "0Q '@P#/PY^!S<5JPS]$&$'TB'R .,%& TN(8X0\!%<
+M'JP8\B2!&;D:>@_7%L$"Y2$!%=4'J0->!+<2^!SX$5(?V0EA%4H%M!5+#:D1
+M#2;S(9(&&@2<'G\78 "-(&L7!Q#\$/8E:!F4$_X3DA^$ ALC=AV;!><*^!D-
+M#UX/P08P$!(>RQ_K#U8<A %3$_<C'B'< #\#@ V( SP/JR1: 2H-XA"2 BD#
+MPPXH ;4;8AC0 8D!EAYW$046D!:O&!D+6 [# 6$A3!>["JD3%QVR M8:D11L
+M#^<4^AL<(%88HQ/\'8D?@ ;$#>@*HAQV(8PF11!?(Y0CSA:R!*H)N!@7(LD<
+M=!I])($:M1';$X,# P*.":H5415O'%(8L![2(581PQI""%<3:!7, :(! H0
+M&6X!1!#/ LX:]QM;(_H2NB)'"Z8 X@)E''$ PQ[U!;<1CQ4@):P;0"5K(P\$
+MFQN7'8H)$!HM(O\3ZAI[!2H3BQ.K";TF3PVZ!,P'0P2U)2P)$PQ! Y<)KQ73
+M)) *;!",'X(%=!JB(3$*&QR^(*P#;R:-".@#XA7@ 5X8%@<$!ZL3K0'/%S ?
+MO0KL#5@:O UO FP*MQPP"6T88ABY#<\+Z"7T#P<)FR;;)E\6Y@*L$[L&81Q%
+M#_($40])'],2% DF$\P@O1:((30E, P*!YD#K03>!Z@+SA2<&900F![5'F $
+MVR4""_<A&@F\!GX?T"8H%O8-^ 5Q'S,$<@1@#A(/ZQR: T\%+P/# B8:9AXT
+M'[,0S!QI"_DB[AX1&",2?2+&!W,D60,$#%<2_B1A'R@ 1Y@%AH%^B ]!-D:
+M\QY) IP@,@J5%,89#A.W&J8-/A*!%04/Q"6,'0P/HA8/!P<!KQFQ#MX@[1#[
+M'BP(3 ^X(A8*31X^$-(F= VC)<((I1A'(ID(7P3A' $7O2,]$A04D!/?%"L)
+M"!YG'TP*]@44&T0'(R:)!%<7!2'!%,0?,P7I%8,+NR/L'. )4PF^%7<3=Q*F
+M#-D:3R&Y&!P>A0 +'P .0!O](;X0IP/J%KXBG@@N! \@#PK%"+8ER ;7&&T!
+M!B%T(24A\P[B'U@8@AZ!#!D,+Q[3 .HA;B-^ Q0-M17U&U<B,Q( K0/%1&E
+M NT,# :A(4(6BB0G %8F! <O%_4630O_!S,50!F %$HF20 0$@H4' .G%$T7
+M>0-L('L:$ *[(B0)3 M""8 :"@=M!?0CZAEU&1P2I0R6"#< 30YP'*DDB!L.
+M&;83EQOY'_L!T18! OH9B@T9(F@;"Q^9!80'Z2-](QPCHA;.%4P&TA@=&ZT3
+MFAOD(;(8)0=_ ^(#50SH#> <901<(TH%AQ>U'O\2PQ(3(48-JQIA&PD1@Q#Z
+M%&(A&@NA'O 2-!IQ"4L*^Q3O)7@FK!I")ILBUQV@ JT-0R0)"XX!8PF)(M0=
+MQR1N'R0@KA^[%5(@5 S^ #@!^@0@!SX"]@XN#108)!@6 *4>VQRL%.0DE1._
+M"_H-?A? )G@ENAZ7&\0@;2+[ AD&-A0V"\@7Q";* 4L1R! !%/0B$QF&%941
+M<!:X)48*51Q?'OX%AAF:%U88DAUX(M(,L2*(%-08=QA"$ALEP@Z0$9P<>Q;7
+M&2(D,1[&&,L!90V:!TPC_@<Y%SL2/Q9($VTDD2'[$!,9&PZP(A@&KAM!!QH&
+M,0ST%X "F"#W H@@?A%'%6</#2;=%W82'"7=%N$9;@6@!>X@N 3/%E4$OP.<
+M)$8%]!:%#F0!Y0,9"3(=20?_ S@'I18T)+(D"B+4&>H*1A2*%+P X":Q"*<3
+MF0)3$LH<M!,7)4(6_QL%)8@ /05,!A8"U@G:&GD;(PR)#0,ALQ\0(?</XP.T
+M&3(2:QW/'Q<>Z!/B(S<=YQJ]'3H+)0ZR%OP K1E/'E0&Q " ! ,
+M!@ * \ %@ > "< ,0 \ $D 5P!F '8 AP": *X PP#9 / !"0$C 3X!6@%W
+M 98!M@'7 ?D"' )! F<"C@*V M\#"@,V V,#D0/ _$$(P16!(H$OP3V!2X%
+M9P6A!=T&&@98!I<&UP<9!UP'H ?E""L(<PB\"08)40F=">L*.@J*"ML++0N!
+M Z( !5;FMN;W=N(&5R<F]R H J/T *C_ "I 8
+M J0@ *D, "I$@ J12 *D; "I'X J20 *DH "I*P J2^ *DT "
+MI.( J3N *E! "I1 J4< *E+@ "I3T J5- *E7 "I6T J6! *E
+ME0 "I;0 J7# *ET@ "I>H J7W *F#0 "IAP J8H *F.P "IDP J9B
+M *F? "IIH J:Y *FU@ "IN< J<& *G)P "ISX J=8 *G>@ "IY@
+M J?( *GWP "I_X J@. *H)0 "J$D JAJ *H@P "J)T JBY *HT0 "
+MJ/( JD4 *I*0 "J3P JE> *I<0 "J7X JF2 *II@ "J;D JG( *I
+MW "J?( JH4 *J* "JC8 JI. *J:0 "JGP JJ/ *JLP "JLT JKK
+M *J_ "JQ( JLC *K,@ "JTX JM= *K< "JWP JN3 6T5R<F]R
+M(# 3F]T(&]W;F5R $YO('-U8V@@9FEL92!O<B!D:7)E8W1O<GD 3F\@<W5C
+M:"!P<F]C97-S $EN=&5R<G5P=&5D('-Y<W1E;2!C86QL $DO3R!E<G)O<@!.
+M;R!S=6-H(&1E=FEC92!O<B!A9&1R97-S $%R9R!L:7-T('1O;R!L;VYG $5X
+M96,@9F]R;6%T(&5R<F]R $)A9"!F:6QE(&YU;6)E<@!.;R!C:&EL9')E;@!.
+M;R!M;W)E('!R;V-E<W-E<P!.;W0@96YO=6=H(&UE;6]R>0!097)M:7-S:6]N
+M(&1E;FEE9 !"860@861D<F5S<P!";&]C:R!D979I8V4@<F5Q=6ER960 1&5V
+M:6-E(&)U<WD 1FEL92!E>&ES=', 0W)O<W,M9&5V:6-E(&QI;FL 3F\@<W5C
+M:"!D979I8V4 3F]T(&$@9&ER96-T;W)Y $ES(&$@9&ER96-T;W)Y $EN=F%L
+M:60@87)G=6UE;G0 1FEL92!T86)L92!O=F5R9FQO=P!4;V\@;6%N>2!O<&5N
+M(&9I;&5S $EN87!P<F]P<FEA=&4@:6]C=&P@9F]R(&1E=FEC90!497AT(&9I
+M;&4@8G5S>0!&:6QE('1O;R!L87)G90!.;R!S<&%C92!L969T(&]N(&1E=FEC
+M90!);&QE9V%L('-E96L 4F5A9"UO;FQY(&9I;&4@<WES=&5M %1O;R!M86YY
+M(&QI;FMS $)R;VME;B!P:7!E $%R9W5M96YT('1O;R!L87)G90!297-U;'0@
+M=&]O(&QA<F=E $]P97)A=&EO;B!W;W5L9"!B;&]C:P!/<&5R871I;VX@;F]W
+M(&EN('!R;V=R97-S $]P97)A=&EO;B!A;')E861Y(&EN('!R;V=R97-S %-O
+M8VME="!O<&5R871I;VX@;VX@;F]N+7-O8VME= !$97-T:6YA=&EO;B!A9&1R
+M97-S(')E<75I<F5D $UE<W-A9V4@=&]O(&QO;F< 4')O=&]C;VP@=W)O;F<@
+M='EP92!F;W(@<V]C:V5T $]P=&EO;B!N;W0@<W5P<&]R=&5D(&)Y('!R;W1O
+M8V]L %!R;W1O8V]L(&YO="!S=7!P;W)T960 4V]C:V5T('1Y<&4@;F]T('-U
+M<'!O<G1E9 !/<&5R871I;VX@;F]T('-U<'!O<G1E9"!O;B!S;V-K970 4')O
+M=&]C;VP@9F%M:6QY(&YO="!S=7!P;W)T960 061D<F5S<R!F86UI;'D@;F]T
+M('-U<'!O<G1E9"!B>2!P<F]T;V-O;"!F86UI;'D 061D<F5S<R!A;')E861Y
+M(&EN('5S90!#86XG="!A<W-I9VX@<F5Q=65S=&5D(&%D9')E<W, 3F5T=V]R
+M:R!I<R!D;W=N $YE='=O<FL@:7,@=6YR96%C:&%B;&4 3F5T=V]R:R!D<F]P
+M<&5D(&-O;FYE8W1I;VX@;VX@<F5S970 4V]F='=A<F4@8V%U<V5D(&-O;FYE
+M8W1I;VX@86)O<G0 0V]N;F5C=&EO;B!R97-E="!B>2!P965R $YO(&)U9F9E
+M<B!S<&%C92!A=F%I;&%B;&4 4V]C:V5T(&ES(&%L<F5A9'D@8V]N;F5C=&5D
+M %-O8VME="!I<R!N;W0@8V]N;F5C=&5D $-A;B=T('-E;F0@869T97(@<V]C
+M:V5T('-H=71D;W=N %1O;R!M86YY(')E9F5R96YC97,Z(&-A;B=T('-P;&EC
+M90!#;VYN96-T:6]N('1I;65D(&]U= !#;VYN96-T:6]N(')E9G5S960 5&]O
+M(&UA;GD@;&5V96QS(&]F('-Y;6)O;&EC(&QI;FMS $9I;&4@;F%M92!T;V\@
+M;&]N9P!(;W-T(&ES(&1O=VX 2&]S="!I<R!U;G)E86-H86)L90!$:7)E8W1O
+M<GD@;F]T(&5M<'1Y %1O;R!M86YY('!R;V-E<W-E<P!4;V\@;6%N>2!U<V5R
+M<P!$:7-C('%U;W1A(&5X8V5E9&5D %-T86QE($Y&4R!F:6QE(&AA;F1L90!4
+M;V\@;6%N>2!L979E;',@;V8@<F5M;W1E(&EN('!A=&@ 3F]T(&$@<W1R96%M
+M(&1E=FEC90!4:6UE<B!E>'!I<F5D $]U="!O9B!S=')E86T@<F5S;W5R8V5S
+M $YO(&UE<W-A9V4@;V8@9&5S:7)E9"!T>7!E $YO="!A(&1A=&$@;65S<V%G
+M90!)9&5N=&EF:65R(')E;6]V960 1&5A9&QO8VL@<VET=6%T:6]N(&1E=&5C
+M=&5D+V%V;VED960 3F\@<F5C;W)D(&QO8VMS(&%V86EL86)L90!-86-H:6YE
+M(&ES(&YO="!O;B!T:&4@;F5T=V]R:P!/8FIE8W0@:7,@<F5M;W1E $QI;FL@
+M:&%S(&)E96X@<V5V97)E9 !!9'9E<G1I<V4@97)R;W(@ %-R;6]U;G0@97)R
+M;W(@ $-O;6UU;FEC871I;VX@97)R;W(@;VX@<V5N9 !0<F]T;V-O;"!E<G)O
+M<@!-=6QT:6AO<"!A='1E;7!T960 141/5$1/5"$A(2$ 4F5M;W1E(&%D9')E
+M<W,@8VAA;F=E9 !&=6YC=&EO;B!N;W0@:6UP;&5M96YT960
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M $! (" 0! (I@
+M =! (J E! (J T9 (J !79
+M(J !?@ "!@ "3@ "Z@
+M #3@ #Q@ $/@ $I
+M@ %+@ %N@ &+@
+M &G@ &Y@ ',@ 'D@
+M 'P@ (M@ ):@ *.@
+M +(@ +S@ 1 >0 (J
+M1 >0 (J0 1 >0 (JH ,D) (J 1 >@ (JX
+M 1 >@ (K( 1 >@ (K@ ,S) (JX 1 >P
+M(KP 1 >P (L 1 >P (L8 -*) (KP 1
+M?0 (LH 1 ?0 (LX 1 ?0 (M0 -C) (LH
+M1 ?@ (M@ 1 ?@ (MP 1 ?@ (N( -S) (M@
+M 1 ?P (N8 1 ?P (NH 1 ?P (O .*)
+M(N8 1 @0 (O0 1 @0 (O@ 1 @0 (OX .C)
+M (O0 1 @@ (P( 1 @@ (P8 1 @@ (PP .Q
+M) (P( 1 @P (Q 1 @P (Q0 1 @P (QH
+M /&) (Q 1 A0 (QX 1 A0 (R( 1 A0
+M(R@ /=) (QX 1 A@ (RP 1 A@ (S 1
+MA@ (S8 /L) (RP 1 AP (SH 1 AP (SX
+M1 AP (T0 0") (SH 1 B0 (T@ 1 B0 (TP
+M 1 B0 (U( 0:) (T@ 1 B@ (U8 1 B@
+M(UH 1 B@ (V( 0K) (U8 0]@ 1W@
+M 2K@ 3;@ 3M@ 44
+M@ 4P@ 5.@ 5J@
+M 5W@ 1 L@ (V8 1 M0 (W 1 M@
+M(W8 1 MP (WX 1 N0 (X8 1 N@ (XX 1
+MNP (Y8 1 O0 (YX 1 O@ (Z8 1 OP (ZX
+M1 P0 ([8 1 P@ ([X 1 PP (\8 1 Q0 (\X
+M 1 Q@ (]@ 1 R0 (^@ 1 R@ (_( 1 RP
+M(_P 1 S0 ) 8 1 S@ )! 1 SP )!H 1
+MT0 )"0 1 T@ )"X 1 TP )#@ 1 U0 )$(
+M1 U@ )$P 1 UP )%8 1 V0 )& 1 V@ )&H
+M 1 W )'X 1 W0 )(@ 1 W@ ))( 1 X
+M))P 1 X0 )*8 1 X@ )+ 1 Y )+H 1
+MY0 ),0 1 Y@ ),X 1 Z )-@ 1 Z0 ).(
+M1 Z@ ).P 1 [ )/8 1 [0 )0 1 [P )0H
+M 1 \ )1( 1 \0 )1@ 1 \@ )2 1 ]
+M)28 1 ]@ )3 1 ]P )3H 1 ]P )3H 6D)
+M (V8 6L( 6V( 7(( 7<
+M( 7G( 7Y( 8-(
+M 86( 8F( 8X( 9"(
+M 93( 9F( 9R( 9_(
+M ::( :]( ;B( ;^
+M( <7( <\( =6(
+M =M( >0( >K( ?#(
+M ?G( @$( @B( @X(
+M A6( AV( B-( BH
+M( C(( C=( CV(
+M D4( DJ( E$( EC(
+M E[( F4( FB( G@(
+M H-( I!( I-( J(
+M( JS( KD( KO(
+M KZ( L>( LM( M+(
+M M9! )4 MB! )4 MQ9 )4 N:9
+M )4 NS@ O5@ OG@ P.
+M@ PG@ Q%@ QC@
+M Q]@ R?@ S"@ S?@
+M S[@ T-@ T@@ TX@
+M U$@ V"@ W&@ X4
+M@ Y+@ Y8@ YB@
+M YM@ Z6@ Z\@ [1)
+M)4 [G( [^) )8 \4!@ " #P \C)
+M ):X \N! )<@ \V! )<@ ]%9 )<@ ]N
+M9 )<@ ^'@ ^I@ ^[@
+M _B@ _[@ ! 9@ ! W@
+M !!1@ !!S@ !"6@ !"S@
+M !#/@ !#A@ !#T@ !$,
+M@ !$8@ !%6@ !&:@
+M !'H@ !(?@ !(L@ !(V@
+M !)!@ !)J@ !*0@ !*E(
+M !*Y( !+6( !+H! )<@ !+L
+M9 )<@ 1 #__P )<@ !+S! )<@ !+]! )D
+M !,$! )H@ !,.! )L@ !,6! )L@ !,:!
+M)M@ !,B! )N !,K! )O !,S! )O !,\!
+M *V@ !-+! *\@ !-3! *] !-@! *] !-J
+M! +4@ !-S! -7 !-\! -:@ !.&! -Z
+M !.,! -Z !.5! .' !.=! .' !.A!
+M.( !.I! .( !.M! .) !.]! .) !/!!
+M .* !//! .* !/3! .+ !/;! .+ !/?
+M! ., !/J! ., !/N! .- !/[! .-
+M !/_! .. !0&! .1@ !01! .6 !0;!
+M.7 !0E! .A@ !0P! .C !0X! .G !1"!
+M /0@ !1*! /9 !13! /> !1<! 3_@ !1I
+M! 3_@ !1Q! 4#@ !1Z! 4) !2#! 4+
+M !2*! 45@ !23! 4H@ !2<! 4K@ !2H!
+M80@ !2Q! 82@ !2Z! 85@ !3#! 89 !3,!
+M 8?@ !37! 8]@ !3B! 9B !3Q! <V@ !4
+M! >) !4*! >?@ !45! >J@ !4D! @+
+M !4S! B' !4_! BI !5&! BI !5*!
+MBJ !53! BO !5=! BS !5D! BS !5H!
+M BT !5Q! B] !5Z! B_@ !6#! C! !6+
+M! C' !64! C. !6=! C0@ !6G! C4
+M !6T! C4 !7#! C4 !7,! C4 !70!
+MC5 !79! C>@ !7@! C>@ !7D! C?@ !7N!
+M CJ !7W! CJ !8 ! CJ !8$! CK !8(
+M9 CK 1 #__P CK !8/!0 #H )D !85 P
+M !8?!0 %#@ (" !8E!0 (V8 !8K!0 #8@ (I@ !8W!0 &X@
+M)M@ !8^!P %<@ " !9'!0 $0 )<@ !9/!0 #I (I@ !9;!0
+M (J !9H!0 (JX !9\!0 (KP !:2!0 (LH !:@
+M!0 (M@ !:U!0 (N8 !;,!0 (O0 !;8!0 (P(
+M !;K!0 (Q !< !0 (QX !<-!0 (RP !<A!0
+M(SH !<W!0 (T@ !=%!0 (U8 !=4!0 ):X !=<"0
+M "L% !=D"0 "L%( !=S"0 "L%0 !>$"0 "L%8 !>-
+M"0 "L%@ !>="0 "L%H !>O"0 "L%P !>V"0 "L&
+M !?$"0 "L&0 !?4"0 "L&@ !?<"0 "L&P !?K"0 "
+ML' !?\"0 "L'0 !@%"0 "L'@ !@/"0 "L( !@="0
+M "L(( !@R"0 "L(0 !A)"0 "L(@ !A8"0 "L(P !AN
+M"0 "L) !B&"0 "L)@ !B3"0 "L* !BG"0 "L*@
+M !B]"0 "L+ !C+"0 "L+@ !C@"0 "L, !CW"0 "
+ML,@ !D&"0 "L- !D6"0 "L. !DF"0 "L.0 !D]"0
+M "L.@ !E6"0 "L.P !EG"0 "L/ !E_"0 "L/0 !F9
+M"0 "L/@ !FH"0 "L/P !F^"0 "L0 !G6"0 "L00
+M !GF"0 "L0@ !G]"0 "L0P !H6"0 "L1 !HG"0 "
+ML10 !HY"0 "L1@ !I""0 "L1P !I."0 "L2 !I9"0
+M "L20 !IB"0 "L2@ !IJ"0 "L3 !IR"0 "L< !I[
+M"0 "L<@ !J%"0 "L= !J0"0 "L? !J;!0 )4
+M !JN"0 "L@@ !J]!P " #@ !K.!P " $ !K@!0
+M)8 !KS"0 "LA !L"!0 &= )H@ !L+!0 )LX !L2!0 &
+MY0 )<@ !L>!0 "> *\@ !LD!0 %&@ *V@ !LQ!0 #E@ )O !L[
+M"0 'B0 "LA@ !M+!0 &JP +P@ !M3!0 (' )N !M:!P 'EP " $0
+M !MA!0 $W0 *>8 !MJ!0 "9@ )_ !MS!0 #>0 ,!X !MY!P %^@ "
+M I0 !N!!0 &3 )Y0 !N)!0 $9 *H( !N3!0 /@ *6( !N=!0
+M .(8 !ND!0 %)P *T !NN!0 .'8 !NU!0 ',P -7 !N]
+M!0 & 0 )P8 !O%!0 %:0 -R !O-"0 #( "JZP !O3!P #<@ " $P
+M !O>!0 $50 *^@ !OH!P &@P " %@ !OZ!P %50 " & !P!!P &J0 "
+M &0 !P*!P #RP " %P !P;!P #?@ " %0 !PL!P &;P " % !P_!0 '
+MUP -Z !Q'!0 #. *] !Q3!0 %I .7 !Q<!0 $*0 .C !QD
+M!0 "L@ .A@ !QN"0 #J "LAP !Q\!P #+@ " IP !R"!0 &-P ,8H
+M !R+!0 #P0 .. !R1!0 .*8 !R>!0 &\0 /0@ !RE!P #P@ "
+M +@ !RN!P #30 " ' !RZ!P ',@ " + !S!!P "H@ " +0 !S*!0
+M .+8 !S1!0 $?@ -:@ !S;!0 .)8 !SJ!0 "HP -CP !SX
+M!0 $5P -M( !T$!0 %:P /9 !T,"0 '?P "LB !T6!0 .-8
+M !TB!0 '> .1@ !TM!0 #HP .68 !TV!0 .,8 !U "0 "
+MLTP !U%!P /0 "!1P !U,!0 *0 .G !U4!0 $U0 .K@ !U?!0 "
+M?@ /> !UH"0 #^@ "LJ !UQ!P (>P "!=0 !U[!0 '>P 3_@ !V"
+M!0 &^P /<P !V)!0 #<0 4+ !V/!0 5@ 85@ !V7!P "QP "!=P
+M !V@!0 &T 4H@ !VH!0 '# 4#@ !VP!0 !&@ B48 !V[!0 (B
+M8LX !W%!0 "@ 80@ !W-!0 %4 7C8 !W9!0 #_ 3.H !WD!0
+M) 4) !WL!0 %QP >) !W^!0 !F@ BCP !X)!0 :@ 9:X !X3
+M!0 F@ B' !X>!0 (" 8?@ !XH!0 "%0 3GX !XQ P $6^
+M !X[!0 &\ 4>@ !Y$!0 &(@ 4C( !Y-!0 %Q0 4F( !Y6!0 (!0
+M4G@ !Y?"0 $S@ "LJ0 !YL!0 %> 4;@ !YV!0 &M0 4= !Y_!0 %
+MU0 4@ !Z(!0 '(@ 47 !Z1!0 &%@ 4DH !Z:!0 &V@ 4A@ !ZC
+M!0 %MP 45@ !ZL!0 %P 4: !ZU!0 &I@ 48@ !Z^!0 BI8
+M ![$!P 'B@ ""$0 ![+!0 %P0 5Q ![<"0 !Y0 "LK ![G!0 "_
+M7D0 ![T!0 (G B] ![\"0 'OP "LL !\&!0 %QP 4K@ !\1!0
+M50 89 !\9!0 &>0 8)( !\G!0 6P 5W( !\Z!0 &YP BT !]"
+M"0 %\0 "LM !],!0 $@ 82@ !]4!0 BS8 !]:!0 (10 6Y8
+M !]F!0 (0 B_@ !]N!P &Z "!N0 !]^!P #U "!P !^)!0 &8
+MC' !^1!P "7 "" ( !^:!0 SP C0@ !^C"0 H@ "LSP !^Q"0 '
+M= "LT !_("0 H0 "LT0 !_@"0 #D "LT@ !_W!0 $E@ <E8 " *
+M!0 #=@ 9?X " 0!0 &N 8]@ " 7!0 (B 9S " R!0 %70 ?+8
+M "!)!0 '^ 9B "!8!0 $H @3( "!P!0 &4@ :.( "",!0 #TP
+M<V@ "";!0 1@ BO ""D!0 !3 @-( ""U!0 & ?HH "#-!0 '
+M( @.X "#E!0 %PP =7@ "#U!0 $6P =, "$$!0 %G <M0 "$:
+M!0 'O :[H "$P!0 &C ?\H "%,!0 XP =T0 "%?!0 &WP =J(
+M "%Q!0 $. =3H "& !0 "G =*H "&3!0 '%0 >?@ "&:!0 "*
+M>,X "&U!0 Y >4@ "'0!0 !A0 >D "'F!0 !8 >FP "'\!0
+M2 >@P "(.!0 7 >J@ "(=!0 #00 ?9@ "(Q!0 &*0 ?%H ")'
+M!0 (+P ?@0 ")B!0 #' ?18 ")V!0 &! >]0 "*,!0 %+ >UH
+M "*@!0 %E >MX "*N!0 !. >Z8 "+!!0 #!@ >VX "+5!0 &*@
+M>R "+E!0 $_ >NX "+S!0 %O ?U ",$!0 (& BJ ",,!P '
+MY@ ",+ ",K!P #J "BAH "-,!P '8 "=D0 "-L!P (<@ ",) ".#
+M!P %X "B6( ".<!P (? "=C@ ".T!P !M@ ""U8 "/%!P $R@ "=IP
+M "/8!P #H@ "=BX "/J!P &S@ ""U0 "/_!P '[@ "=IH "06!P %- "
+M=BP "0L!0 #X0 @+ "1$!0 &V C! "1+!P (EP "=@@ "1B!P &
+M!0 "H=8 "1[!P P "=G8 "23!P !VP ",- "2D!P $[P "BM( "2W
+M!P #QP "=E "3)!P &\P ",,X "3>!P ($P "BM "3U!P %60 "=DX
+M "4+!0 'H@ C. "43!0 C>X "49!0 'N C5 "4A!0
+MC48 "4I!0 #;@ C?@ "4R!P %P@ "HH0 "4_!0 CJ8 "5'!P "
+MF@ "H_ "51!0 " "58!P "JZP "5?"0 "LTP "5E
+M+VQI8B]C<G0P+F\ +VQI8B]-8W)T,2YO &=D8FUE+F\ 9V-C,E]C;VUP:6QE
+M9"X +V-Y9VEN="]P;&%Y+V9N9B]D979O+V=D8G1E<W0O=#$P+P!G9&)M92YC
+M &EN=#IT,3UR,3LM,C$T-S0X,S8T.#LR,30W-#@S-C0W.P!C:&%R.G0R/7(R
+M.S [,3(W.P!L;VYG(&EN=#IT,SUR,3LM,C$T-S0X,S8T.#LR,30W-#@S-C0W
+M.P!U;G-I9VYE9"!I;G0Z=#0]<C$[,#LM,3L ;&]N9R!U;G-I9VYE9"!I;G0Z
+M=#4]<C$[,#LM,3L <VAO<G0@:6YT.G0V/7(Q.RTS,C<V.#LS,C<V-SL ;&]N
+M9R!L;VYG(&EN=#IT-SUR,3LP.RTQ.P!S:&]R="!U;G-I9VYE9"!I;G0Z=#@]
+M<C$[,#LV-34S-3L ;&]N9R!L;VYG('5N<VEG;F5D(&EN=#IT.3UR,3LP.RTQ
+M.P!S:6=N960@8VAA<CIT,3 ]<C$[+3$R.#LQ,C<[ '5N<VEG;F5D(&-H87(Z
+M=#$Q/7(Q.S [,C4U.P!F;&]A=#IT,3(]<C$[-#LP.P!D;W5B;&4Z=#$S/7(Q
+M.S@[,#L ;&]N9R!D;W5B;&4Z=#$T/7(Q.S@[,#L =F]I9#IT,34],34 =%]S
+M=')U8W0Z5#$V/7,R-'9?8VAA<E]M96UB97(Z,BPP+#@[=E]S:&]R=%]M96UB
+M97(Z-BPQ-BPQ-CM< '9?:6YT7VUE;6)E<CHQ+#,R+#,R.W9?;&]N9U]M96UB
+M97(Z,RPV-"PS,CM< '9?9FQO871?;65M8F5R.C$R+#DV+#,R.W9?9&]U8FQE
+M7VUE;6)E<CHQ,RPQ,C@L-C0[.P!T7W5N:6]N.E0Q-SUU.'9?8VAA<E]M96UB
+M97(Z,BPP+#@[=E]S:&]R=%]M96UB97(Z-BPP+#$V.UP =E]I;G1?;65M8F5R
+M.C$L,"PS,CMV7VQO;F=?;65M8F5R.C,L,"PS,CM< '9?9FQO871?;65M8F5R
+M.C$R+# L,S([=E]D;W5B;&5?;65M8F5R.C$S+# L-C0[.P!V7V-H87)?9G5N
+M8SI&,@!V7W-I9VYE9%]C:&%R7V9U;F,Z1C$P '9?=6YS:6=N961?8VAA<E]F
+M=6YC.D8Q,0!V7W-H;W)T7V9U;F,Z1C8 =E]S:6=N961?<VAO<G1?9G5N8SI&
+M-@!V7W5N<VEG;F5D7W-H;W)T7V9U;F,Z1C@ =E]I;G1?9G5N8SI&,0!V7W-I
+M9VYE9%]I;G1?9G5N8SI&,0!V7W5N<VEG;F5D7VEN=%]F=6YC.D8T '9?;&]N
+M9U]F=6YC.D8S '9?<VEG;F5D7VQO;F=?9G5N8SI&,P!V7W5N<VEG;F5D7VQO
+M;F=?9G5N8SI&-0!V7V9L;V%T7V9U;F,Z1C$R '9?9&]U8FQE7V9U;F,Z1C$S
+M &QI;FLZ5#$X/7,Q-3)N97AT.C$Y/2HQ."PP+#,R.VQI;FMF=6YC.C(P/2HR
+M,3UF,3DL,S(L,S([7 !S='5F9CHR,CUA<C$[,#LP.S(S/6%R,3LP.S$[,C0]
+M87(Q.S [,CLQ-BPV-"PQ,34R.SL ='5?;&EN:SI4,C4]=3$T-&YE>'0Z,3DL
+M,"PS,CML:6YK9G5N8SHR,"PP+#,R.UP <W1U9F8Z,C(L,"PQ,34R.SL 8V]L
+M;W)S.E0R-CUE>65L;&]W.C L<'5R<&QE.C$L<&EN:SHR+#L 8V%R<SI4,C<]
+M96)M=SHP+'!O<G-C:&4Z,2P[ &)O;VQE86XZ=#(X/65&04Q313HP+%12544Z
+M,2P[ &)V86QS.E0R.3UE9F%L<V4Z,"QT<G5E.C$L.P!B;V]L96%N,CIT,CD
+M;6ES;W)D97)E9#I4,S ]971W;SHR+&]N93HQ+'IE<F\Z,"QT:')E93HS+#L
+M;6%I;CI&,0!V7V-H87(Z1S( =E]S:6=N961?8VAA<CI',3 =E]U;G-I9VYE
+M9%]C:&%R.D<Q,0!V7W-H;W)T.D<V '9?<VEG;F5D7W-H;W)T.D<V '9?=6YS
+M:6=N961?<VAO<G0Z1S@ =E]I;G0Z1S$ =E]S:6=N961?:6YT.D<Q '9?=6YS
+M:6=N961?:6YT.D<T '9?;&]N9SI',P!V7W-I9VYE9%]L;VYG.D<S '9?=6YS
+M:6=N961?;&]N9SI'-0!V7V9L;V%T.D<Q,@!V7V1O=6)L93I',3, =E]C:&%R
+M7V%R<F%Y.D<S,3UA<C$[,#LQ.S( =E]S:6=N961?8VAA<E]A<G)A>3I',S(]
+M87(Q.S [,3LQ, !V7W5N<VEG;F5D7V-H87)?87)R87DZ1S,S/6%R,3LP.S$[
+M,3$ =E]S:&]R=%]A<G)A>3I',S0]87(Q.S [,3LV '9?<VEG;F5D7W-H;W)T
+M7V%R<F%Y.D<S- !V7W5N<VEG;F5D7W-H;W)T7V%R<F%Y.D<S-3UA<C$[,#LQ
+M.S@ =E]I;G1?87)R87DZ1S,V/6%R,3LP.S$[,0!V7W-I9VYE9%]I;G1?87)R
+M87DZ1S,V '9?=6YS:6=N961?:6YT7V%R<F%Y.D<S-SUA<C$[,#LQ.S0 =E]L
+M;VYG7V%R<F%Y.D<S.#UA<C$[,#LQ.S, =E]S:6=N961?;&]N9U]A<G)A>3I'
+M,S@ =E]U;G-I9VYE9%]L;VYG7V%R<F%Y.D<S.3UA<C$[,#LQ.S4 =E]F;&]A
+M=%]A<G)A>3I'-# ]87(Q.S [,3LQ,@!V7V1O=6)L95]A<G)A>3I'-#$]87(Q
+M.S [,3LQ,P!V7V-H87)?<&]I;G1E<CI'-#(]*C( =E]S:6=N961?8VAA<E]P
+M;VEN=&5R.D<T,STJ,3 =E]U;G-I9VYE9%]C:&%R7W!O:6YT97(Z1S0T/2HQ
+M,0!V7W-H;W)T7W!O:6YT97(Z1S0U/2HV '9?<VEG;F5D7W-H;W)T7W!O:6YT
+M97(Z1S0U '9?=6YS:6=N961?<VAO<G1?<&]I;G1E<CI'-#8]*C@ =E]I;G1?
+M<&]I;G1E<CI'-#<]*C$ =E]S:6=N961?:6YT7W!O:6YT97(Z1S0W '9?=6YS
+M:6=N961?:6YT7W!O:6YT97(Z1S0X/2HT '9?;&]N9U]P;VEN=&5R.D<T.3TJ
+M,P!V7W-I9VYE9%]L;VYG7W!O:6YT97(Z1S0Y '9?=6YS:6=N961?;&]N9U]P
+M;VEN=&5R.D<U,#TJ-0!V7V9L;V%T7W!O:6YT97(Z1S4Q/2HQ,@!V7V1O=6)L
+M95]P;VEN=&5R.D<U,CTJ,3, =E]S=')U8W0Q.D<Q-@!V7W-T<G5C=#(Z1S4S
+M/7,R-'9?8VAA<E]M96UB97(Z,BPP+#@[=E]S:&]R=%]M96UB97(Z-BPQ-BPQ
+M-CM< '9?:6YT7VUE;6)E<CHQ+#,R+#,R.W9?;&]N9U]M96UB97(Z,RPV-"PS
+M,CM< '9?9FQO871?;65M8F5R.C$R+#DV+#,R.W9?9&]U8FQE7VUE;6)E<CHQ
+M,RPQ,C@L-C0[.P!V7W5N:6]N.D<Q-P!V7W5N:6]N,CI'-30]=3AV7V-H87)?
+M;65M8F5R.C(L,"PX.W9?<VAO<G1?;65M8F5R.C8L,"PQ-CM< '9?:6YT7VUE
+M;6)E<CHQ+# L,S([=E]L;VYG7VUE;6)E<CHS+# L,S([7 !V7V9L;V%T7VUE
+M;6)E<CHQ,BPP+#,R.W9?9&]U8FQE7VUE;6)E<CHQ,RPP+#8T.SL <U]L:6YK
+M.D<Q.0!U7VQI;FLZ1S(U '!R:6UA<GDZ1S4U/65R960Z,"QG<F5E;CHQ+&)L
+M=64Z,BP[ &YO;G!R:6UA<GDZ1S(V &-L=6YK97(Z1S4V/65C:&5V>3HP+&9O
+M<F0Z,2P[ '-P;W)T<V-A<CI',C< 7U]M86EN+F\ 9V-C,E]C;VUP:6QE9"X
+M+W-E;F1A:2]A8F,O<FEC:"]L871E<W0O;V)J9&ER+7-U;C,O9V-C+P N+B\N
+M+B]D979O+V=C8R]L:6)G8V,R+F, :6YT.G0Q/7(Q.RTR,30W-#@S-C0X.S(Q
+M-#<T.#,V-#<[ &-H87(Z=#(]<C([,#LQ,C<[ &QO;F<@:6YT.G0S/7(Q.RTR
+M,30W-#@S-C0X.S(Q-#<T.#,V-#<[ '5N<VEG;F5D(&EN=#IT-#UR,3LP.RTQ
+M.P!L;VYG('5N<VEG;F5D(&EN=#IT-3UR,3LP.RTQ.P!S:&]R="!I;G0Z=#8]
+M<C$[+3,R-S8X.S,R-S8W.P!L;VYG(&QO;F<@:6YT.G0W/7(Q.S [+3$[ '-H
+M;W)T('5N<VEG;F5D(&EN=#IT.#UR,3LP.S8U-3,U.P!L;VYG(&QO;F<@=6YS
+M:6=N960@:6YT.G0Y/7(Q.S [+3$[ '-I9VYE9"!C:&%R.G0Q,#UR,3LM,3(X
+M.S$R-SL =6YS:6=N960@8VAA<CIT,3$]<C$[,#LR-34[ &9L;V%T.G0Q,CUR
+M,3LT.S [ &1O=6)L93IT,3,]<C$[.#LP.P!L;VYG(&1O=6)L93IT,30]<C$[
+M.#LP.P!V;VED.G0Q-3TQ-0!R96=?8VQA<W,Z5#$V/65.3U]214=3.C L3$]?
+M1E!!7U)%1U,Z,2Q&4$%?4D5'4SHR+$907U)%1U,Z,RQ< $907T]27T9005]2
+M14=3.C0L1$%405]214=3.C4L1$%405]/4E]&4$%?4D5'4SHV+$1!5$%?3U)?
+M1E!?4D5'4SHW+%P 1$%405]/4E]&4%]/4E]&4$%?4D5'4SHX+$%$1%)?4D5'
+M4SHY+$=%3D5204Q?4D5'4SHQ,"Q'14Y%4D%,7T]27T9005]214=3.C$Q+%P
+M1T5.15)!3%]/4E]&4%]214=3.C$R+$%,3%]214=3.C$S+$Q)35]214=?0TQ!
+M4U-%4SHQ-"P[ '!T<F1I9F9?=#IT,0!S:7IE7W0Z=#$ =V-H87)?=#IT. !L
+M;VYG;&]N9SI4,3<]<SAH:6=H.C,L,"PS,CML;W<Z,RPS,BPS,CL[ &QO;F=?
+M;&]N9SIT,3@]=3AS.C$W+# L-C0[;&PZ-RPP+#8T.SL 9G5N8U]P='(Z=#$Y
+M/2HR,#UF,34 7U]D;U]G;&]B86Q?9'1O<G,Z1C$U %]E>&ET7V1U;6UY7W)E
+M9CI',C$]*C$ 7U]D;U]G;&]B86Q?8W1O<G,Z1C$U %]I;FET:6%L:7IE9"XP
+M %]?;6%I;CI&,34 7V5X:70N;P!G8V,R7V-O;7!I;&5D+@ O<V5N9&%I+V%B
+M8R]R:6-H+VQA=&5S="]O8FID:7(M<W5N,R]G8V,O "XN+RXN+V1E=F\O9V-C
+M+VQI8F=C8S(N8P!I;G0Z=#$]<C$[+3(Q-#<T.#,V-#@[,C$T-S0X,S8T-SL
+M8VAA<CIT,CUR,CLP.S$R-SL ;&]N9R!I;G0Z=#,]<C$[+3(Q-#<T.#,V-#@[
+M,C$T-S0X,S8T-SL =6YS:6=N960@:6YT.G0T/7(Q.S [+3$[ &QO;F<@=6YS
+M:6=N960@:6YT.G0U/7(Q.S [+3$[ '-H;W)T(&EN=#IT-CUR,3LM,S(W-C@[
+M,S(W-C<[ &QO;F<@;&]N9R!I;G0Z=#<]<C$[,#LM,3L <VAO<G0@=6YS:6=N
+M960@:6YT.G0X/7(Q.S [-C4U,S4[ &QO;F<@;&]N9R!U;G-I9VYE9"!I;G0Z
+M=#D]<C$[,#LM,3L <VEG;F5D(&-H87(Z=#$P/7(Q.RTQ,C@[,3(W.P!U;G-I
+M9VYE9"!C:&%R.G0Q,3UR,3LP.S(U-3L 9FQO870Z=#$R/7(Q.S0[,#L 9&]U
+M8FQE.G0Q,SUR,3LX.S [ &QO;F<@9&]U8FQE.G0Q-#UR,3LX.S [ '9O:60Z
+M=#$U/3$U ')E9U]C;&%S<SI4,38]94Y/7U)%1U,Z,"Q,3U]&4$%?4D5'4SHQ
+M+$9005]214=3.C(L1E!?4D5'4SHS+%P 1E!?3U)?1E!!7U)%1U,Z-"Q$051!
+M7U)%1U,Z-2Q$051!7T]27T9005]214=3.C8L1$%405]/4E]&4%]214=3.C<L
+M7 !$051!7T]27T907T]27T9005]214=3.C@L041$4E]214=3.CDL1T5.15)!
+M3%]214=3.C$P+$=%3D5204Q?3U)?1E!!7U)%1U,Z,3$L7 !'14Y%4D%,7T]2
+M7T907U)%1U,Z,3(L04Q,7U)%1U,Z,3,L3$E-7U)%1U]#3$%34T53.C$T+#L
+M<'1R9&EF9E]T.G0Q '-I>F5?=#IT,0!W8VAA<E]T.G0X &QO;F=L;VYG.E0Q
+M-SUS.&AI9V@Z,RPP+#,R.VQO=SHS+#,R+#,R.SL ;&]N9U]L;VYG.G0Q.#UU
+M.',Z,3<L,"PV-#ML;#HW+# L-C0[.P!F=6YC7W!T<CIT,3D]*C(P/68Q-0!?
+M97AI=%]D=6UM>5]D96-L.D<Q %]?0U1/4E],25-47U\Z1S(Q/6%R,3LP.S$[
+M,3D 7U]$5$]27TQ)4U1?7SI',C$ +6QG &QI8F<N<P!-<W=I=&-H+F\ 97AI
+M="YO &]N7V5X:70N;P!W<FET92YO &5R<@!?97AI="YO &-E<G)O<BYO &5R
+M<FYO+F\ 9FQS8G5F+F\ 9FQO871?<W=I=&-H+F\ 36EN:70N;P!F<%]G;&]B
+M86QS+F\ ;6EN:71F<"YO &UA;&QO8RYO &ES871T>2YO &9I;F1I;W N;P!I
+M;V(N;P!S:6=V96,N;P!C;&]S92YO &5R<@!F<W1A="YO &5R<@!G971D=&%B
+M;&5S:7IE+F\ 97)R &=E='!A9V5S:7IE+F\ 97)R &EO8W1L+F\ 97)R '-I
+M9V)L;V-K+F\ 97)R '-I9W-E=&UA<VLN;P!E<G( <V)R:RYO '-I9W1R86UP
+M+F\ 7W-I9W9E8RYO &9P<FEN=&8N;P!-9&5F875L="YO &UA.3-N+F\ 9G!?
+M<V%V92YO &)C;W!Y+F\ 8V%L;&]C+F\ 9&]P<FYT+F\ 9G!?8V]M;6]N<RYO
+M &)Z97)O+F\ ;65M<V5T+F\ <W1R;&5N+F\ 871O:2YO &-T>7!E7RYO &UE
+M;6-H<BYO '-E=&QO8V%L92YO '-T<F-H<BYO '-T<F-M<"YO '-T<G-P;BYO
+M '-T<G1O:RYO &5C;VYV97)T+F\ 9V-O;G9E<G0N;P!D;W5B;&5?9&5C:6TN
+M;P!?=6YP86-K7V1B;&4N;P!?8F%S95]3+F\ 7V)A<V5?:6PN;P!?<W!R:6YT
+M9E]S=7 N;P!?=&EM97-?<&]W97(N;P!Q96-O;G9E<G0N;P!R96%D+F\ 97)R
+M '!R:6YT9BYO '-P<FEN=&8N;P!O<&5N+F\ 97)R &UE;6-P>2YO '-T<F-A
+M="YO '-T<F-P>2YO &%B;W)T+F\ 9V5T96YV+F\ <&5R<F]R+F\ <W1R<&)R
+M:RYO %]B:6=?<&]W97(N;P!?<VUA;&Q?<&]W97(N;P!G971P:60N;P!E<G(
+M<VEG;F%L+F\ :VEL;"YO &5R<@!?<&5R<F]R+F\ 97)R;'-T+F\ =W)I=&5V
+M+F\ 97)R "UL9P!L:6)G+G, 7V5X:70 7U]$64Y!34E# '-T87)T %]M86EN
+M '-T87)T7V9L;V%T %]?97AI= !?96YV:7)O;@!-<W=I=&-H &8V.#@X,5]U
+M<V5D %]V7V-H87)?9G5N8P!?=E]S:6=N961?8VAA<E]F=6YC %]V7W5N<VEG
+M;F5D7V-H87)?9G5N8P!?=E]S:&]R=%]F=6YC %]V7W-I9VYE9%]S:&]R=%]F
+M=6YC %]V7W5N<VEG;F5D7W-H;W)T7V9U;F, 7W9?:6YT7V9U;F, 7W9?<VEG
+M;F5D7VEN=%]F=6YC %]V7W5N<VEG;F5D7VEN=%]F=6YC %]V7VQO;F=?9G5N
+M8P!?=E]S:6=N961?;&]N9U]F=6YC %]V7W5N<VEG;F5D7VQO;F=?9G5N8P!?
+M=E]F;&]A=%]F=6YC %]V7V1O=6)L95]F=6YC %]?7VUA:6X 7W9?8VAA<@!?
+M=E]S:6=N961?8VAA<@!?=E]U;G-I9VYE9%]C:&%R %]V7W-H;W)T %]V7W-I
+M9VYE9%]S:&]R= !?=E]U;G-I9VYE9%]S:&]R= !?=E]I;G0 7W9?<VEG;F5D
+M7VEN= !?=E]U;G-I9VYE9%]I;G0 7W9?;&]N9P!?=E]S:6=N961?;&]N9P!?
+M=E]U;G-I9VYE9%]L;VYG %]V7V9L;V%T %]V7V1O=6)L90!?=E]C:&%R7V%R
+M<F%Y %]V7W-I9VYE9%]C:&%R7V%R<F%Y %]V7W5N<VEG;F5D7V-H87)?87)R
+M87D 7W9?<VAO<G1?87)R87D 7W9?<VEG;F5D7W-H;W)T7V%R<F%Y %]V7W5N
+M<VEG;F5D7W-H;W)T7V%R<F%Y %]V7VEN=%]A<G)A>0!?=E]S:6=N961?:6YT
+M7V%R<F%Y %]V7W5N<VEG;F5D7VEN=%]A<G)A>0!?=E]L;VYG7V%R<F%Y %]V
+M7W-I9VYE9%]L;VYG7V%R<F%Y %]V7W5N<VEG;F5D7VQO;F=?87)R87D 7W9?
+M9FQO871?87)R87D 7W9?9&]U8FQE7V%R<F%Y %]V7V-H87)?<&]I;G1E<@!?
+M=E]S:6=N961?8VAA<E]P;VEN=&5R %]V7W5N<VEG;F5D7V-H87)?<&]I;G1E
+M<@!?=E]S:&]R=%]P;VEN=&5R %]V7W-I9VYE9%]S:&]R=%]P;VEN=&5R %]V
+M7W5N<VEG;F5D7W-H;W)T7W!O:6YT97( 7W9?:6YT7W!O:6YT97( 7W9?<VEG
+M;F5D7VEN=%]P;VEN=&5R %]V7W5N<VEG;F5D7VEN=%]P;VEN=&5R %]V7VQO
+M;F=?<&]I;G1E<@!?=E]S:6=N961?;&]N9U]P;VEN=&5R %]V7W5N<VEG;F5D
+M7VQO;F=?<&]I;G1E<@!?=E]F;&]A=%]P;VEN=&5R %]V7V1O=6)L95]P;VEN
+M=&5R %]P<FEM87)Y %]N;VYP<FEM87)Y %]S<&]R='-C87( 7V-L=6YK97(
+M7W-?;&EN:P!?=5]L:6YK %]V7W5N:6]N %]V7W5N:6]N,@!?=E]S=')U8W0Q
+M %]V7W-T<G5C=#( 7U]?9&]?9VQO8F%L7V1T;W)S %]?7T143U)?3$E35%]?
+M %]?97AI=%]D=6UM>5]R968 7U]E>&ET7V1U;6UY7V1E8VP 7U]?9&]?9VQO
+M8F%L7V-T;W)S %]?7T-43U)?3$E35%]? %]O;E]E>&ET %]W<FET90!?;7-W
+M:71C:&9P7P!-:6YI= !F;&]A=%]S=VET8V@ 7U]C;&5A;G5P %]?97AI=%]H
+M86YD;&5R<P!?;6%L;&]C &-E<G)O<@!?97)R;F\ 7U]W<G1C:&L 7U]F;'-B
+M=68 7V9R964 7U]S;6)U9@!?9F9L=7-H %]?9FEN9&)U9@!?7WAF;'-B=68
+M7V9S=&%T %]?8G5F<WEN8P!?8VQO<V4 7VES871T>0!?9F-L;W-E %]?9G=A
+M;&L 5FQI<W0 7V9P7W-W:71C: !?;6EN:71F<%\ 7V9P7W-T871E7VUC-C@X
+M.#$ 7T9M;V1E %]&<W1A='5S %]F<%]S=&%T95]S=6YF<&$ 7V9P7W-T871E
+M7W-K>69F< !?9G!?<W1A=&5?<V]F='=A<F4 7W-I9W9E8P!?14U44W!E8VEA
+M; !?9G!R:6YT9@!?;6$Y,VY? %]-9&5F875L= !?14U44VEG;F%L;&5D %]?
+M:6]B %]R96%L;&]C %]S8G)K %]G971P86=E<VEZ90!?8F-O<'D 7U]U8F]U
+M;F0 7U]?;6%L;&EN9F\ 7U]R;V]T %]?;&)O=6YD %]I;V-T; !?7V9I;F1I
+M;W 7V=E=&1T86)L97-I>F4 7U]F7VUO<F5F:6QE<P!?9E]P<F5A;&QO8P!?
+M8V%L;&]C %]?<VEG9G5N8P!?<VEG<V5T;6%S:P!?7W-I9W1R86UP %]?<VEG
+M=F5C %]S:6=B;&]C:P!?96YD &-U<F)R:P!F<%]S879E &9P7W)E<W1O<F4
+M7U]D;W!R;G0 7U]S:WE?9F0 7U]S:WEB87-E %]B>F5R;P!?8V9R964 7V%T
+M;VD 7W-T<G-P;@!?7V-T>7!E7P!?;65M8VAR %]M96US970 7W%F8V]N=F5R
+M= !?9F-O;G9E<G0 7W-T<F-H<@!?;&]C86QE8V]N=@!?7VUK87)G;'-T %]S
+M=')L96X 7U]F;W5R9&EG:71S<75I8VL 7W%G8V]N=F5R= !?9V-O;G9E<G0
+M7W%E8V]N=F5R= !?96-O;G9E<G0 7U]G971A<F< 7U]F<&%B87-E %]I<W!U
+M;F-T %]I<V=R87!H %]I<V%S8VEI %]T;V%S8VEI %]?;6)?8W5R7VUA> !?
+M:7-X9&EG:70 7VES<W!A8V4 7VES86QN=6T 7VES=7!P97( 7VES8VYT<FP
+M7VES<')I;G0 7VES86QP:&$ 7VES9&EG:70 7VES;&]W97( 7W)E860 7VQC
+M;VYV %]G971L;V-A;&5?8W1Y<&4 7U]L86YG:6YF;P!?;&]C86QD=&-O;G8
+M7W-T<F-A= !?7VUY7W1I;64 7W-E=&QO8V%L90!?<W1R=&]K %]I;FET7W-T
+M871I8W, 7V=E=&QO8V%L95]N=6UE<FEC %]M96UC<'D 7U]L;V-A;&5S %]S
+M=')C;7 7V]P96X 7V]P96YL;V-A;&4 7W-T<F-P>0!?7V-O9&5?<V5T7VEN
+M9F\ 7U]C='EP95]U; !?9V5T96YV %]?9'1C;VYV %]S=')P8G)K %]F<%]D
+M:7)E8W1I;VX 7U]F<%]C=7)R96YT7V1I<F5C=&EO;@!?7V9P7V-U<G)E;G1?
+M97AC97!T:6]N<P!?7V9P7V-U<G)E;G1?<')E8VES:6]N %]D;W5B;&5?=&]?
+M9&5C:6UA; !?9V-V= !?7V=C=G0 7V)I;F%R>5]T;U]D96-I;6%L7VEN=&5G
+M97( 7U]R:6=H=%]S:&EF=%]B87-E7W1W;P!?9&5C:6UA;%]R;W5N9 !?7V)I
+M9U]F;&]A=%]T:6UE<U]P;W=E<@!?8FEN87)Y7W1O7V1E8VEM86Q?9G)A8W1I
+M;VX 7U]F<%]N;W)M86QI>F4 7W-P<FEN=&8 7U]F<F5E7V)I9U]F;&]A= !?
+M7W5N<&%C:V5D7W1O7V)I9U]F;&]A= !?7V)A<V5?8V]N=F5R<VEO;E]A8F]R
+M= !?7W5N<&%C:U]D;W5B;&4 7U]C;&%S<U]D;W5B;&4 7W%U861R=7!L95]T
+M;U]D96-I;6%L %]?=6YP86-K961?=&]?9&5C:6UA; !?7V)I9U]B:6YA<GE?
+M=&]?8FEG7V1E8VEM86P 7U]U;G!A8VM?<75A9')U<&QE %]?8VQA<W-?<75A
+M9')U<&QE %]?9G!?;&5F='-H:69T %]?9G!?<V5T7V5X8V5P=&EO;@!?7W5M
+M86, 7U]M=6QT:7!L>5]B87-E7W1W;U]V96-T;W( 7U]M=6QT:7!L>5]B87-E
+M7W1E;E]V96-T;W( 7U]C87)R>5]P<F]P86=A=&5?='=O %]?8V%R<GE?<')O
+M<&%G871E7W1E;@!?7V-A<G)Y7VEN7V(Q,# P, !?7W!R;V1C7V(Q,# P, !?
+M7VUU;'1I<&QY7V)A<V5?='=O %]?;&5F=%]S:&EF=%]B87-E7W1W;P!?7VUU
+M;'1I<&QY7V)A<V5?=&5N7V)Y7W1W;P!?7VUU;'1I<&QY7V)A<V5?=&5N %]?
+M;&5F=%]S:&EF=%]B87-E7W1E;@!?7W!R;V1?,3 P,#!?8C8U-3,V %]?<')O
+M9%]B-C4U,S8 7U]C87)R>5]O=71?8C$P,# P %]?<')O9%\V-34S-E]B,3 P
+M,# 7U]L<VAI9G1?8C$P,# P %]?<')O9%]B,3 P,# 7U]M=6Q?-C4U,S9S
+M:&]R= !?<')I;G1F %]?;&5A9&EN9U]Z97)O<U]B:6=?<&]W97)S7W1E;@!?
+M7VQE861I;F=?>F5R;W-?<VUA;&Q?<&]W97)S7W1E;@!?7VQE861I;F=?>F5R
+M;W-?=&EN>5]P;W=E<G-?=&5N %]?<W1A<G1?8FEG7W!O=V5R<U]T96X 7U]S
+M=&%R=%]S;6%L;%]P;W=E<G-?=&5N %]?<W1A<G1?=&EN>5]P;W=E<G-?=&5N
+M %]?8FEG7W!O=V5R<U]T96X 7U]S;6%L;%]P;W=E<G-?=&5N %]?=&EN>5]P
+M;W=E<G-?=&5N %]?;6%X7V)I9U]P;W=E<G-?=&5N %]?;6%X7W-M86QL7W!O
+M=V5R<U]T96X 7U]M87A?=&EN>5]P;W=E<G-?=&5N %]?8V]P>5]B:6=?9FQO
+M871?9&EG:71S %]A8F]R= !?7W-T87)T7V)I9U]P;W=E<G-?='=O %]?<W1A
+M<G1?<VUA;&Q?<&]W97)S7W1W;P!?7W-T87)T7W1I;GE?<&]W97)S7W1W;P!?
+M7V)I9U]P;W=E<G-?='=O %]?<VUA;&Q?<&]W97)S7W1W;P!?7W1I;GE?<&]W
+M97)S7W1W;P!?7VUA>%]B:6=?<&]W97)S7W1W;P!?7VUA>%]S;6%L;%]P;W=E
+M<G-?='=O %]?;6%X7W1I;GE?<&]W97)S7W1W;P!?<&5R<F]R %]K:6QL %]S
+M:6=N86P 7V=E='!I9 !?7W!E<G)O<@!?<WES7V5R<FQI<W0 7W=R:71E=@!?
+=<WES7VYE<G( 7V5T97AT %]E9&%T80!?7V5N9 !R
+
+end
diff --git a/gdb/testsuite/gdb.base/m68k-elf.u b/gdb/testsuite/gdb.base/m68k-elf.u
new file mode 100644
index 00000000000..e3d05e746c8
--- /dev/null
+++ b/gdb/testsuite/gdb.base/m68k-elf.u
@@ -0,0 +1,298 @@
+begin 777 m68k-elf
+M?T5,1@$" 0 " 0 !@ $> #0 #"0 T "
+M!0 H !4 $0 8 T@ - "@ H 4 P
+M -0 !, ! ! -( #0 )
+MC "8P % @ $ G @ IP "4 "6 < "
+M @ ">2 "GD ' !P O=7-R+VQI8B]L:6)C
+M+G-O+C$ &$ ,
+M 4 P !P 0
+M + ! @
+M
+M "@
+M ( )
+M
+M
+M
+M
+M!@ ! "02 "H +!@
+M$0#_\0 ^ "G$ !!$ H 8@ )P 1 /_Q 'P
+M !:$@ ": "I4 !$ __$ M 2 ,H
+M!-@ $$0 " #\ !( !)@ IR 1 /_Q
+M7X *>0 $0#_\0!?8VQE86YU< !?96YD %]E;G9I<F]N %]E=&5X= !A
+M=&5X:70 7V5D871A &5X:70 7VQI8E]V97)S:6]N %]?9G!S=&%R= !?1TQ/
+M0D%,7T]&1E-%5%]404),15\ 7T193D%-24, +W5S<B]L:6(O;&EB8RYS;RXQ
+M " "G4 %%0 " "G8 !%0 " "G< )%0 " "G@ '
+M%0 !.=4YQ+SL!< );9.^P%Q EL@ !.^P%Q EJB\\ &#_
+M____W$[[ 7$ "6:+SP ,8/_____(3OL!<0 )8HO/ !A@_____[1.
+M^P%Q E>B\\ )&#_____H"\\@ )O$ZY@ $*%A/(#R 0\9_\ .
+M+P!.N8 !"A83Y_\ #"Z60>X !"]( 1*F&;\(\B "G$+T@ "$ZY@ $
+M$$ZY@ $4$ZY@ 'K"Z 3KF 1D3G5.<0 !(#O____Q([P 3R-_
+M 7 $< !@_P 3R-] 7 $3.\ $3EY.=4@._____$CO
+M!/(W\ !< 1P &#_ !/(WT !< 1,[P 1.7DYU2 [____\
+M2.\ $\C?P %P !' 8/\ $\C?0 %P !$SO !$Y>3G5(
+M#O____Q([P 3R-_ 7 $< !@_P 3R-] 7 $3.\ $
+M3EY.=4@._____$CO !/(W\ !< 1P &#_ !/(WT !< 1,
+M[P 1.7DYU2 [____\2.\ $\C?P %P !' 8/\ $\C?0 %P
+M !$SO !$Y>3G5(#O____Q([P 3R-_ 7 $< !@_P 3R
+M-] 7 $3.\ $3EY.=4@._____$CO !/(W\ !< 1P &#_
+M !/(WT !< 1,[P 1.7DYU2 [____\2.\ $\C?P %P
+M!' 8/\ $\C?0 %P !$SO !$Y>3G5(#O____Q([P 3R-_
+M 7 $< !@_P 3R-] 7 $3.\ $3EY.=4@._____$CO
+M!/(W\ !< 1P &#_ !/(WT !< 1,[P 1.7DYU2 [____\
+M2.\ $\C?P %P !' 8/\ $\C?0 %P !$SO !$Y>3G5(
+M#O____Q([P 3R-_ 7 $\CQ4 8/\ $\C?0 %P
+M !$SO !$Y>3G5(#O____Q([P 3R-_ 7 $\CQ4
+M 8/\ $\C?0 %P !$SO !$Y>3G5(#O____Q([P 3R-_
+M 7 $0CF "MD$_P 8 *N 3_ "@ JI#/\ . "K8,_P !( *L@S
+M_ %@ J;"/\ !H *G@C_ > "I8(_P (@ J7"/\ "8
+M*M0C_ J "ID(_P +@ JY"/\0L@ ( *J@C_$!I " "IP(_P
+M @ J=!/Y@ K9( *T 3^8 *N" "J@$_F "JD@ J8#/Y@ JV(
+M*N@S^8 *LB "JT,_F "IL@ J["/Y@ J>( *H0C^8 *EB "KX(_F
+M "I<@ JO"/Y@ JU( *UPC^8 *F2 "JL(_F "KD@ JS"/Y@ JJ(
+M*TPC^8 *G" "J0(_F "IT@ JE"/\@ K9( *O C_( *N" "M8(_R
+M "JD@ J]"/\@ JV( *U0C_( *LB "L((_R "IL@ J:"/\@ J>(
+M*K@C_( *EB "L (_R "I<@ JQ"/\@ JU( *MPC_( *F2 "M((_R
+M "KD@ J@"/\@ JJ( *T0C_( *G" "L,(_P "@ JC"/\ H
+M*GPC_ & "P (_P !@ K:"/Y@ K!( *W S^8 +!" "P(\C?0
+M %P !$SO !$Y>3G5.=4YQ " "GD " 0P
+M@ $1( !%B 1L 0 &@ ,@ $$ V F\ !( .@
+M %@ #9 : *D "@ 'L + $ !4 X
+M*<@ " , !0 ' %X ^
+M 0 ! #_\0 " #4 , $
+M@ Z # " ( J0 P P " -D , 0
+M @ #X # % ( !! P !@ " 04 ,
+M < @ $> # ( ( ";P P "0 " "G
+M , H @ IR # + ( *>0 P # " "I8
+M , T # . P #P
+M , ! # 1 P $@
+M , !, # 4 "@ ! #_
+M\0 !$ 0 __$ 8 $ /_Q )
+M! #_\0 "P 0 __$ V $ /_Q /8 !-P
+M R$@ " $F "I8 !!$ T !6@ J7 01 - 98
+M";P $@ "0 &N "I@ A$ T "!@ 'K A 2 (
+MAH *F0 $$0 #0 )2 "IH !!$ T "M@ $/ "02
+M MH +!@ $0#_\0 +N "IL A$ T #,@ %U@ #(2
+M ( XH *G ($0 #0 .N "IX !!$ T #Q@ $>
+M 2 ( ^( *GP $$0 #0 0. "G$ !!$ H $,@ J
+M@ 01 - !)( *H0 ($0 #0 3" "J, !!$ T $X
+M@ %#@ #(2 ( !2X *I 0$0 #0 5J G !$ __$
+M %A@ JH (1 - !=8 *J0 !$0 #0 86 "JH !!$
+M T &-@ JK @1 - !H8 !"@ !:$@ :B "G$
+M!"$ H &P@ &G@ #(2 ( !O( !P( R$@ " =& "JT
+M !!$ T 'F@ JN 01 - !]( *E0 $0#_\0 ?N
+M 5R ,A( @ ((@ JO @1 - "'8 *L0 $$0 #0
+M C2 8( ,A( @ (_@ JR (1 - "3H !S0 \$@
+M" EN 1D !( )@@ JS @1 - "=H *M0 $
+M$0 #0 GV "K8 A$ T *%@ JW 01 - "E( *N
+M !$0 #0 J* "KD !!$ T *R@ JZ 01 - "P(
+M*NP $$0 #0 M> 38 !!$ @ +D@ $U 2 ( "
+M[( *O $$0 #0 ON "KT !!$ T ,3@ J^ @1 -
+M #)H !% $@ S" "L !!$ T -%@ K! 01
+M - #3( *<@ $0#_\0 V* "L( !!$ T -Y@ K#
+M 01 - #BH *< $$0 "@ YR "L0 &!$ T .F@ K
+M* !@1 - #L( *T "$0 #0 [V "M$ !!$ T /-
+M@ K2 01 - #XX !W \$@ " _& 8Z ,A( @
+M 0#@ IY 1 /_Q $#( *TP ($0 #0 !!J "M4 !!$
+M T 0J@ &T #(2 ( $/8 *U@ $$0 #0 !%. "M<
+M"!$ T 1@@ $$ 2 & $9H *V0 !$0 #0 !&V "MH
+M !!$ T 1U@ %0 #(2 ( $BH *W "0$0 #0 !)&
+M 6D ,A( @ 2E@ L 01 - $KX + @ ($0 #0
+M!+B 9L ,A( @ 3,@ L$ @1 - &TV.&LN96QF &-R=#$N
+M<P!C<G1I+G, =F%L=65S+5AT+F, 9V1B;64N8P!S:%]D871A+F, 8W)T;BYS
+M '9?8VAA<E]F=6YC '9?<VEG;F5D7VEN= !V7W5N<VEG;F5D7VEN= !?9FEN
+M:0!V7W5N<VEG;F5D7V-H87)?87)R87D ;6%I;@!V7W-I9VYE9%]L;VYG '9?
+M=6YS:6=N961?<VAO<G1?<&]I;G1E<@!?8VQE86YU< !?96YD '9?=6YS:6=N
+M961?<VAO<G0 =E]U;G-I9VYE9%]S:&]R=%]F=6YC '9?9&]U8FQE '9?:6YT
+M %]S=&%R= !N;VYP<FEM87)Y %]E;G9I<F]N '9?=6YS:6=N961?;&]N9U]P
+M;VEN=&5R '9?:6YT7V%R<F%Y '!R:6UA<GD =E]S:6=N961?8VAA<E]F=6YC
+M '9?9&]U8FQE7V%R<F%Y %]E=&5X= !V7W-I9VYE9%]C:&%R7V%R<F%Y '9?
+M=6YS:6=N961?8VAA<@!V7V9L;V%T '9?<VEG;F5D7VQO;F=?87)R87D 871E
+M>&ET &5N=FER;VX =E]L;VYG7V9U;F, =E]U;G-I9VYE9%]L;VYG7V9U;F,
+M=E]S:6=N961?<VAO<G1?87)R87D =E]I;G1?<&]I;G1E<@!?961A=&$ =E]S
+M:&]R=%]F=6YC '9?=6YS:6=N961?:6YT7V%R<F%Y '9?=6YS:6=N961?:6YT
+M7W!O:6YT97( =E]I;G1?9G5N8P!V7W-I9VYE9%]S:&]R= !V7V9L;V%T7V9U
+M;F, 97AI= !V7W5N<VEG;F5D7VQO;F=?87)R87D =E]L;VYG '9?<VAO<G0
+M=E]L;VYG7W!O:6YT97( =E]S:6=N961?8VAA<@!V7W5N<VEG;F5D7VQO;F<
+M=E]S:&]R=%]A<G)A>0!V7W5N<VEG;F5D7W-H;W)T7V%R<F%Y %]L:6)?=F5R
+M<VEO;@!?;6-O=6YT '9?8VAA<E]P;VEN=&5R '9?=6YS:6=N961?8VAA<E]P
+M;VEN=&5R '9?<VEG;F5D7VEN=%]A<G)A>0!?7V9P<W1A<G0 =E]S:6=N961?
+M:6YT7W!O:6YT97( <U]L:6YK %]'3$]"04Q?3T9&4T547U1!0DQ%7P!V7W-I
+M9VYE9%]S:&]R=%]P;VEN=&5R '9?9&]U8FQE7W!O:6YT97( 7U]L;VYG9&]U
+M8FQE7W5S960 =E]S=')U8W0Q '9?<W1R=6-T,@!V7V-H87)?87)R87D =E]F
+M;&]A=%]P;VEN=&5R '9?<VEG;F5D7VQO;F=?<&]I;G1E<@!V7V1O=6)L95]F
+M=6YC '9?<VEG;F5D7VEN=%]F=6YC %]$64Y!34E# '9?9FQO871?87)R87D
+M=E]S:&]R=%]P;VEN=&5R '9?<VEG;F5D7VQO;F=?9G5N8P!V7W-I9VYE9%]C
+M:&%R7W!O:6YT97( =E]L;VYG7V%R<F%Y %]I;FET '9?8VAA<@!C;'5N:V5R
+M '9?=6YS:6=N961?8VAA<E]F=6YC '5?;&EN:P!V7W-I9VYE9%]S:&]R=%]F
+M=6YC '-P;W)T<V-A<@!V7W5N:6]N,@!V7W5N<VEG;F5D7VEN=%]F=6YC '9?
+M=6YI;VX "YI;G1E<G +FAA<V@ +F1Y;G-Y;0 N9'EN<W1R "YR96QA+G!L
+M= N:6YI= N<&QT "YT97AT "YF:6YI "YD871A "YG;W0 +F1Y;F%M:6,
+M+F)S<P N<WEM=&%B "YS=')T86( +G!E<V5L "YS:'-T<G1A8@ N8V]M;65N
+M= N9&5B=6< +FQI;F4 0"@C*6QI8F,M;3,R.FTT+F1E9@DQ+C0 0"@C*6QI
+M8F,M;3,R.F-S=2]C<G0Q+G,),2XQ. ! *",I;&EB8RUM,S(Z;30N9&5F
+M"3$N- ! *",I;&EB8RUM,S(Z8W-U+V-R=&DN<PDQ+C, 87,Z("A#1%,I(#4N
+M," Q+S(O.3 0"@C*6QI8F,M;3,R.FTT+F1E9@DQ+C0 0"@C*6QI8F,M
+M;3,R.F-S=2]C<G1N+G,),2XV "!L9" Z("A#1%,I(#4N," Q+S(O.3
+M "X $0 2 6< X9V1B;64N8P !-@ $!$8 !-P!(8 ";P!!@
+M = !, $@ 4X .'1?<W1R=6-T "V & "H #0 2 =0 X=E]C
+M:&%R7VUE;6)E<@ 50 ! ", !@0 !P "L #0 2 H X=E]S:&]R
+M=%]M96UB97( %4 ! C 8$ @< I T $@ ,D .'9?:6YT7VUE
+M;6)E<@ 50 ' ", !@0 $!P "H #0 2 \P X=E]L;VYG7VUE;6)E
+M<@ 50 * ", !@0 (!P "L #0 2 !'@ X=E]F;&]A=%]M96UB97(
+M %4 #@ C 8$ # < L T $@ 4H .'9?9&]U8FQE7VUE;6)E<@
+M50 / ", !@0 0!P 0 ; !, $@ FP .'XP9F%K90 M@ !@
+M J T $@ 9, .'9?8VAA<E]M96UB97( %4 0 C 8$ < K
+M T $@ ;X .'9?<VAO<G1?;65M8F5R !5 0 (P &! (' *0 -
+M !( 'G #AV7VEN=%]M96UB97( %4 !P C 8$ ! < J T $@
+M A$ .'9?;&]N9U]M96UB97( %4 "@ C 8$ " < K T $@ CP
+M.'9?9FQO871?;65M8F5R !5 X (P &! P' + - !( )H #AV
+M7V1O=6)L95]M96UB97( %4 #P C 8$ $ < $ ' 7 !( .+
+M #AT7W5N:6]N "V " "H #0 2 "L@ X=E]C:&%R7VUE;6)E<@
+M50 ! ", !@0 !P "L #0 2 "W0 X=E]S:&]R=%]M96UB97( %4
+M! C 8$ < I T $@ P8 .'9?:6YT7VUE;6)E<@ 50 ' ",
+M!@0 !P "H #0 2 #, X=E]L;VYG7VUE;6)E<@ 50 * ", !@0
+M !P "L #0 2 #6P X=E]F;&]A=%]M96UB97( %4 #@ C 8$
+M < L T $@ X< .'9?9&]U8FQE7VUE;6)E<@ 50 / ", !@0
+M!P 0 ; !< $@ !*D .'XQ9F%K90 M@ @ J T $@ ]
+M.'9?8VAA<E]M96UB97( %4 0 C 8$ < K T $@ _L .'9?
+M<VAO<G1?;65M8F5R !5 0 (P &! ' *0 - !( 0D #AV7VEN
+M=%]M96UB97( %4 !P C 8$ < J T $@ !$X .'9?;&]N9U]M
+M96UB97( %4 "@ C 8$ < K T $@ !'D .'9?9FQO871?;65M
+M8F5R !5 X (P &! ' + - !( 2E #AV7V1O=6)L95]M96UB
+M97( %4 #P C 8$ < $ *@ & !( 37 #AV7V-H87)?9G5N
+M8P 50 ! 1& 3< 2& 4. ! #$ !@ 2 %# X=E]S:6=N961?
+M8VAA<E]F=6YC !5 (!$8 !0X!(8 !4 $ ,P & !( 5# #AV
+M7W5N<VEG;F5D7V-H87)?9G5N8P 50 # 1& 5 2& 5R ! "L
+M!@ 2 %<@ X=E]S:&]R=%]F=6YC !5 0!$8 !7(!(8 !:0 $
+M,@ & !( 6H #AV7W-I9VYE9%]S:&]R=%]F=6YC !5 4!$8 !:0!(8
+M!=8 $ - & !( 7@ #AV7W5N<VEG;F5D7W-H;W)T7V9U;F, %4
+M!@$1@ %U@$A@ &" 0 I 8 $@ !@T .'9?:6YT7V9U;F, %4
+M!P$1@ &" $A@ &.@ 0 P 8 $@ !D$ .'9?<VEG;F5D7VEN=%]F
+M=6YC !5 @!$8 !CH!(8 !FP $ ,@ & !( 9W #AV7W5N<VEG
+M;F5D7VEN=%]F=6YC !5 D!$8 !FP!(8 !IX $ *@ & !( :E
+M #AV7VQO;F=?9G5N8P 50 * 1& :> 2& ;0 ! #$ !@ 2 &
+MV@ X=E]S:6=N961?;&]N9U]F=6YC !5 L!$8 !M !(8 !P( $
+M,P & !( <1 #AV7W5N<VEG;F5D7VQO;F=?9G5N8P 50 , 1& <" 2&
+M <T ! "L !@ 2 '0 X=E]F;&]A=%]F=6YC !5 X!$8 !S0!
+M(8 !W $ + & !( =P #AV7V1O=6)L95]F=6YC !5 \!$8
+M!W !(8 !ZP $ %0 5 !( >N (, !0$ ?J %0 % !( >:
+M (, !0$ ?J $ % !( >J %4 !P 0 \ $ $@ !^H E0
+M *, * " ( $ @ @@ <@ "X
+M 9 !, $@ "'L .&QI;FL +8 "8 )@ - !( @I #AN97AT "#
+M 4! 'Z@ C 8$ < J T $@ "%, .&QI;FMF=6YC "# 4!
+M '< C 8$ ! < D T $@ "'< .'-T=69F !R 'K@ C 8$
+M " < $ %0 5 !( BY (, !0$ ?J %0 % !( BE (,
+M!0$ ?J $ % !( BU %4 !P 0 \ $ $@ "/4 E0 *,
+M* " ( $ @ @@ <@ "X <
+M !< $@ "8D .'1U7VQI;FL +8 "0 )@ - !( DW #AN97AT "#
+M 4! 'Z@ C 8$ < J T $@ "6$ .&QI;FMF=6YC "# 4!
+M (>P C 8$ < D T $@ "84 .'-T=69F !R (N0 C 8$
+M < $ .@ $ !( G' #A^,F9A:V4 +8 $ /, &P )B
+M;'5E %G<F5E;@ <F5D 0 ^ 0 $@ "@D .&-O;&]R
+M<P M@ 0 \P ? G!I;FL 7!U<G!L90 >65L;&]W
+M 0 R 0 $@ "C\ .'XS9F%K90 M@ 0 \P 3 69O<F0
+M &-H979Y 0 Q 0 $@ "G0 .&-A<G, +8 $ /, % %P
+M;W)S8VAE !B;7< ! #( ! 2 *J@ X?C1F86ME "V
+M! #S !, !5%)510 1D%,4T4 ! !P %@ 2 *Q@ X8F]O
+M;&5A;@ <@ "G0 Q 0 $@ "OL .&)V86QS "V ! #S !, !
+M=')U90 9F%L<V4 ! !T %@ 2 +& X8F]O;&5A;C( '(
+M K& 1@ $ !( MB #AM:7-O<F1E<F5D "V ! #S ", #=&AR
+M964 'IE<F\ 6]N90 "='=O 0 C 8 $@ "XD
+M.&UA:6X %4 !P$1@ 'K $A@ )O 0 G < $@ "[ .'-P;W)T
+M<V-A<@ <@ "C\ (P % X + E < $@ "]4 .&-L=6YK97( '(
+M H) ", !0. "MH * ' !( O] #AN;VYP<FEM87)Y !R )QP C
+M 4#@ J? "4 !P 2 ,(@ X<')I;6%R>0 <@ "8D (P % X *HP
+M D < $@ #$8 .'5?;&EN:P <@ "/4 (P % X *W G < $@
+M#&T .'-?;&EN:P @P % 0 !^H (P % X *P0 F < $@ #), .'9?
+M=6YI;VXR !R #BP C 4#@ L" "4 !P 2 ,N X=E]U;FEO;@
+M<@ FP (P % X +! G < $@ #-\ .'9?<W1R=6-T,@ <@ 4X
+M(P % X *R@ G < $@ #08 .'9?<W1R=6-T,0 <@ "X (P % X
+M*Q O < $@ #34 .'9?9&]U8FQE7W!O:6YT97( &, P$ #P C 4#
+M@ K# "X !P 2 -8P X=E]F;&]A=%]P;VEN=&5R !C ,! X (P %
+M X *T0 V < $@ #9D .'9?=6YS:6=N961?;&]N9U]P;VEN=&5R !C
+M ,! P (P % X *H T < $@ #<T .'9?<VEG;F5D7VQO;F=?<&]I
+M;G1E<@ 8P # 0 + ", !0. "M( +0 ' !( WZ #AV7VQO;F=?<&]I
+M;G1E<@ 8P # 0 * ", !0. "K< -0 ' !( XO #AV7W5N<VEG;F5D
+M7VEN=%]P;VEN=&5R !C ,! D (P % X *L0 S < $@ #F( .'9?
+M<VEG;F5D7VEN=%]P;VEN=&5R !C ,! @ (P % X *P L < $@
+M#HX .'9?:6YT7W!O:6YT97( &, P$ !P C 4#@ JN #< !P 2 .
+MQ0 X=E]U;G-I9VYE9%]S:&]R=%]P;VEN=&5R !C ,! 8 (P % X *F@
+M U < $@ #OH .'9?<VEG;F5D7W-H;W)T7W!O:6YT97( &, P$ !0 C
+M 4#@ K" "X !P 2 /* X=E]S:&]R=%]P;VEN=&5R !C ,! 0
+M(P % X *U0 V < $@ #UX .'9?=6YS:6=N961?8VAA<E]P;VEN=&5R
+M !C ,! , (P % X *O0 T < $@ #Y( .'9?<VEG;F5D7V-H87)?
+M<&]I;G1E<@ 8P # 0 " ", !0. "M8 +0 ' !( ^_ #AV7V-H87)?
+M<&]I;G1E<@ 8P # 0 ! ", !0. "KP ) ! !( _C )4 "C !
+M @ 0@ 50 / + ' !( ! / #AV7V1O=6)L95]A<G)A>0
+M<@ #[\ (P % X *I D $ $@ $#, E0 *, $ " !
+M" !5 X K < $@ $%X .'9?9FQO871?87)R87D '( ! / ", !0.
+M "M, ) ! !( !"" )4 "C ! @ 0@ 50 , ,P '
+M !( !"U #AV7W5N<VEG;F5D7VQO;F=?87)R87D '( !!> ", !0. "K,
+M ) ! !( !#9 )4 "C ! @ 0@ 50 + ,0 ' !(
+M !$* #AV7W-I9VYE9%]L;VYG7V%R<F%Y !R 0M0 C 4#@ JK "0
+M 0 2 1+@"5 HP 0 ( $( %4 "@ "H !P 2 16 X
+M=E]L;VYG7V%R<F%Y !R 1"@ C 4#@ K7 "0 0 2 1? "5
+MHP 0 ( $( %4 "0 #( !P 2 1K@ X=E]U;G-I9VYE9%]I
+M;G1?87)R87D '( !%8 ", !0. "J\ ) ! !( !'2 )4 "C !
+M @ 0@ 50 ( , ' !( !(" #AV7W-I9VYE9%]I;G1?87)R
+M87D '( !&N ", !0. "KX ) ! !( !(F )4 "C ! @
+M 0@ 50 ' *0 ' !( !)/ #AV7VEN=%]A<G)A>0 <@ $@( (P %
+M X *H0 D $ $@ $G, E0 *, $ " !" !5 8 T
+M < $@ $J< .'9?=6YS:6=N961?<VAO<G1?87)R87D '( !)/ ", !0.
+M "KL ) ! !( !++ )4 "C ! @ 0@ 50 % ,@ '
+M !( !+] #AV7W-I9VYE9%]S:&]R=%]A<G)A>0 <@ $J< (P % X *K0
+M D $ $@ $R$ E0 *, $ " !" !5 0 K < $@
+M$TP .'9?<VAO<G1?87)R87D '( !+] ", !0. "KH ) ! !( !-P
+M )4 "C ! @ 0@ 50 # ,P ' !( !.C #AV7W5N<VEG
+M;F5D7V-H87)?87)R87D '( !-, ", !0. "I@ ) ! !( !/' )4
+M "C ! @ 0@ 50 " ,0 ' !( !/X #AV7W-I9VYE9%]C
+M:&%R7V%R<F%Y !R 3HP C 4#@ JH "0 0 2 4' "5 HP 0
+M ( $( %4 0 "H !P 2 41@ X=E]C:&%R7V%R<F%Y !R
+M 3^ C 4#@ K0 "0 !P 2 4:@ X=E]D;W5B;&4 %4 #P C 4#
+M@ J< ", !P 2 4C0 X=E]F;&]A= 50 . ", !0. "JH *P '
+M !( !2X #AV7W5N<VEG;F5D7VQO;F< %4 # C 4#@ JY "D !P 2
+M 4X0 X=E]S:6=N961?;&]N9P 50 + ", !0. "ID (@ ' !( !4#
+M #AV7VQO;F< %4 "@ C 4#@ JU "H !P 2 5+0 X=E]U;G-I9VYE
+M9%]I;G0 %4 "0 C 4#@ J7 "@ !P 2 550 X=E]S:6=N961?:6YT
+M !5 @ (P % X *E@ A < $@ %78 .'9?:6YT !5 < (P % X
+M*G@ L < $@ %:( .'9?=6YS:6=N961?<VAO<G0 %4 !@ C 4#@ J
+M; "H !P 2 5S X=E]S:6=N961?<VAO<G0 %4 !0 C 4#@ JR
+M ", !P 2 5[P X=E]S:&]R= 50 $ ", !0. "K8 *P ' !( !8:
+M #AV7W5N<VEG;F5D7V-H87( %4 P C 4#@ JI "D !P 2 60P X
+M=E]S:6=N961?8VAA<@ 50 " ", !0. "K@ (@ ' !( !9E #AV7V-H
+M87( %4 0 C 4#@ K9 0 ' "DH !-P !Y__\
+M >O__ ,@ 'O__P &0 !]__\ "6 ?O__ R '__
+M_P /H "!__\ $L @O__ !7@ (/__P 9 "%__\ '"
+M AO__ !] (?__P B8 ")__\ )8 BO__ "E ++_
+M_P M "U__\ +F MO__ "[ +?__P O0 "Y__\ +\
+M NO__ #! +O__P PP "]__\ ,4 OO__ #'@ +__
+M_P R@ #!__\ ,R PO__ #/ ,/__P T8 #%__\ -0
+M QO__ #6@ ,G__P VX #*__\ -X R___ #@@ ,W_
+M_P XP #.__\ .6 S___ #H -'__P ZH #2__\ .T
+M T___ #O@ -7__P \@ #6__\ /2 U___ #W -G_
+M_P ^8 #:__\ /P W/__ $! -W__P ! X #>__\ 08
+M X/__ $(@ .'__P !"P #B__\ 0V Y/__ $0 .7_
+M_P !$H #F__\ 14 Z/__ $7@ .G__P !&@ #J__\ 1R
+M [/__ $? .W__P !(8 #O__\ 20 \/__ $F@ /'_
+M_P !*0 #R__\ 2N ]/__ $N /;__P !,( #W__\ 3,
+M /__ $X
+M $ ! H -0 #4 $P 0
+M ) !0 * #H Z ;P # 0 $
+M#P L "@ "I J0 # ! $ $ $ !< #
+M H V0 -D >P 0 ? ! *
+M /@ #X # # !P 0 , *0 $ &@ $$
+M!! $ $ "\ ! !H !!0 04
+M9 ! !0 T 0 : 1X $> !40
+M 0 .@ $ &@ )O ";P $
+M $ $ ! X *< G " !
+M !& 0 . "G( )R !P 0 $
+M2P 8 #@ IY ">0 !P ! $ " %0 (
+M X *E@ I8 !P " !9 @
+M *6 !P / ' 0 0 80 ,
+M$5@ 34 ! &D # !8L
+M ! !P P 6+ )
+M $ >@ $ %KP #/
+M $ (, ! !>, 6< !
+J "* 0 M_ I0 0
+
+end
diff --git a/gdb/testsuite/gdb.base/maint.exp b/gdb/testsuite/gdb.base/maint.exp
new file mode 100644
index 00000000000..ba59ed1db95
--- /dev/null
+++ b/gdb/testsuite/gdb.base/maint.exp
@@ -0,0 +1,578 @@
+# Copyright (C) 1998 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file was written by Elena Zannoni (ezannoni@cygnus.com)
+
+# this file tests maintenance commands and help on those.
+
+# source file used is break.c
+
+
+#maintenance check-symtabs -- Check consistency of psymtabs and symtabs
+#maintenance space -- Set the display of space usage
+#maintenance time -- Set the display of time usage
+#maintenance demangle -- Demangle a C++ mangled name
+#maintenance dump-me -- Get fatal error; make debugger dump its core
+#maintenance print -- Maintenance command for printing GDB internal state
+#maintenance info -- Commands for showing internal info about the program being debugged
+#
+#maintenance print statistics -- Print statistics about internal gdb state
+#maintenance print objfiles -- Print dump of current object file definitions
+#maintenance print psymbols -- Print dump of current partial symbol definitions
+#maintenance print msymbols -- Print dump of current minimal symbol definitions
+#maintenance print symbols -- Print dump of current symbol definitions
+#maintenance print type -- Print a type chain for a given symbol
+#maintenance print unwind -- Print unwind table entry at given address
+#
+#
+#maintenance info sections -- List the BFD sections of the exec and core files
+#maintenance info breakpoints -- Status of all breakpoints
+#
+
+
+
+if $tracelevel then {
+ strace $tracelevel
+ }
+
+global usestubs
+
+#
+# test running programs
+#
+set prms_id 0
+set bug_id 0
+
+set testfile "break"
+set srcfile ${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug additional_flags=-w}] != ""
+ } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+if ![runto_main] then {
+ perror "tests suppressed"
+}
+
+
+# The commands we test here produce many lines of output; disable "press
+# <return> to continue" prompts.
+send_gdb "set height 0\n"
+gdb_expect -re "$gdb_prompt $"
+
+# use a larger expect input buffer for long help outputs.
+match_max 6000
+
+#
+# this command does not produce any output
+# unless there is some problem with the symtabs and psymtabs
+# so that branch will really never be covered in this tests here!!
+#
+
+send_gdb "maint check-symtabs\n"
+gdb_expect {
+ -re "^maint check-symtabs.*$gdb_prompt $"\
+ { pass "maint check-symtabs" }
+ -re ".*$gdb_prompt $" { fail "maint check-symtabs" }
+ timeout { fail "(timeout) maint check-symtabs" }
+ }
+
+send_gdb "maint space\n"
+gdb_expect {
+ -re "\"maintenance space\" takes a numeric argument\\..*$gdb_prompt $"\
+ { pass "maint space" }
+ -re ".*$gdb_prompt $" { fail "maint space" }
+ timeout { fail "(timeout) maint space" }
+ }
+
+send_gdb "maint space 1\n"
+gdb_expect {
+ -re "Space used: $decimal \\(\\+$decimal for this command\\).*$gdb_prompt $"\
+ { pass "maint space 1" }
+ -re ".*$gdb_prompt $" { fail "maint space 1" }
+ timeout { fail "(timeout) maint space 1" }
+ }
+
+
+send_gdb "maint time\n"
+gdb_expect {
+ -re "\"maintenance time\" takes a numeric argument\\..*Space used: $decimal \\(\\+$decimal for this command\\).*$gdb_prompt $"\
+ { pass "maint time" }
+ -re ".*$gdb_prompt $" { fail "maint time" }
+ timeout { fail "(timeout) maint time" }
+ }
+
+send_gdb "maint time 1\n"
+gdb_expect {
+ -re "Command execution time: $decimal.*Space used: $decimal \\(\\+$decimal for this command\\).*$gdb_prompt $"\
+ { pass "maint time 1" }
+ -re ".*$gdb_prompt $" { fail "maint time 1" }
+ timeout { fail "(timeout) maint time 1" }
+ }
+
+send_gdb "maint time 0\n"
+gdb_expect {
+ -re "Space used: $decimal \\(\\+$decimal for this command\\).*$gdb_prompt $"\
+ { pass "maint time 0" }
+ -re ".*$gdb_prompt $" { fail "maint time 0" }
+ timeout { fail "(timeout) maint time 0" }
+ }
+
+
+send_gdb "maint space 0\n"
+gdb_expect {
+ -re "maint space 0\r\n$gdb_prompt $"\
+ { pass "maint space 0" }
+ -re ".*$gdb_prompt $" { fail "maint space 0" }
+ timeout { fail "(timeout) maint space 0" }
+ }
+
+send_gdb "maint demangle\n"
+gdb_expect {
+ -re "\"maintenance demangle\" takes an argument to demangle\\..*$gdb_prompt $"\
+ { pass "maint demangle" }
+ -re ".*$gdb_prompt $" { fail "maint demangle" }
+ timeout { fail "(timeout) maint demangle" }
+ }
+
+send_gdb "maint demangle main\n"
+gdb_expect {
+ -re "Can't demangle \"main\".*$gdb_prompt $"\
+ { pass "maint demangle" }
+ -re ".*$gdb_prompt $" { fail "maint demangle" }
+ timeout { fail "(timeout) maint demangle" }
+ }
+
+
+send_gdb "maint print statistics\n"
+gdb_expect {
+ -re "Statistics for.*break.*Number of \"minimal\" symbols read.*Number of \"partial\" symbols read.*Number of \"types\" defined.*Total memory used for psymbol obstack.*Total memory used for psymbol cache.*Total memory used for symbol obstack.*Total memory used for type obstack.*$gdb_prompt $"\
+ { pass "maint print statistics" }
+ -re ".*$gdb_prompt $" { fail "maint print statistics" }
+ timeout { fail "(timeout) maint print statistics" }
+ }
+
+send_gdb "maint print objfiles\n"
+# To avoid timeouts, we avoid expects with many .* patterns that match
+# many lines.
+gdb_expect {
+ -re ".*Object file.*break: Objfile at $hex, bfd at $hex, \[0-9\]* minsyms\[\r\t \]+\n"
+ { pass "maint print objfiles: header" }
+ -re ".*$gdb_prompt $" { fail "maint print objfiles: header" }
+ timeout { fail "(timeout) maint print objfiles: header" }
+}
+gdb_expect {
+ -re ".*Psymtabs:\[\r\t \]+\n" { pass "maint print objfiles: psymtabs" }
+ -re ".*$gdb_prompt $" { fail "maint print objfiles: psymtabs" }
+ timeout { fail "(timeout) maint print objfiles: psymtabs" }
+}
+gdb_expect {
+ -re ".*Symtabs:\[\r\t \]+\n" { pass "maint print objfiles: symtabs" }
+ -re ".*$gdb_prompt $" { fail "maint print objfiles: symtabs" }
+ timeout { fail "(timeout) maint print objfiles: symtabs" }
+}
+gdb_expect {
+ -re ".*$gdb_prompt $" { pass "maint print objfiles: prompt" }
+ timeout { fail "(timeout) maint print objfiles: prompt" }
+}
+
+send_gdb "maint print psymbols\n"
+gdb_expect {
+ -re "print-psymbols takes an output file name and optional symbol file name.*$gdb_prompt $"\
+ { pass "maint print psymbols w/o args" }
+ -re ".*$gdb_prompt $" { fail "maint print psymbols w/o args" }
+ timeout { fail "(timeout) maint print psymbols w/o args" }
+ }
+
+send_gdb "maint print psymbols psymbols_output\n"
+gdb_expect {
+ -re "^maint print psymbols psymbols_output\r\n$gdb_prompt $"\
+ {
+ send_gdb "shell ls psymbols_output\n"
+ gdb_expect {
+ -re "psymbols_output\r\n$gdb_prompt $"\
+ {
+ # We want this grep to be as specific as possible,
+ # so it's less likely to match symbol file names in
+ # psymbols_output. Yes, this actually happened;
+ # poor expect got tons of output, and timed out
+ # trying to match it. --- Jim Blandy <jimb@cygnus.com>
+ send_gdb "shell grep 'main.*function' psymbols_output\n"
+ gdb_expect {
+ -re ".main., function, $hex.*$gdb_prompt $"\
+ { pass "maint print psymbols" }
+ -re ".*$gdb_prompt $" { fail "maint print psymbols" }
+ timeout { fail "(timeout) maint print psymbols" }
+ }
+ gdb_test "shell rm -f psymbols_output" ""
+
+ }
+ -re ".*$gdb_prompt $" { fail "maint print psymbols" }
+ timeout { fail "(timeout) maint print psymbols" }
+ }
+ }
+ -re ".*$gdb_prompt $" { fail "maint print psymbols" }
+ timeout { fail "(timeout) maint print psymbols" }
+ }
+
+
+send_gdb "maint print msymbols\n"
+gdb_expect {
+ -re "print-msymbols takes an output file name and optional symbol file name.*$gdb_prompt $"\
+ { pass "maint print msymbols w/o args" }
+ -re ".*$gdb_prompt $" { fail "maint print msymbols w/o args" }
+ timeout { fail "(timeout) maint print msymbols w/o args" }
+ }
+
+send_gdb "maint print msymbols msymbols_output\n"
+gdb_expect {
+ -re "^maint print msymbols msymbols_output\r\n$gdb_prompt $"\
+ {
+ send_gdb "shell ls msymbols_output\n"
+ gdb_expect {
+ -re "msymbols_output\r\n$gdb_prompt $"\
+ {
+ send_gdb "shell grep factorial msymbols_output\n"
+ gdb_expect {
+ -re "\\\[ *$decimal\\\] T\[ \t\]+$hex factorial.*$gdb_prompt $"\
+ { pass "maint print msymbols" }
+ -re ".*$gdb_prompt $" { fail "maint print msymbols" }
+ timeout { fail "(timeout) maint print msymbols" }
+ }
+ gdb_test "shell rm -f msymbols_output" ""
+
+ }
+ -re ".*$gdb_prompt $" { fail "maint print msymbols" }
+ timeout { fail "(timeout) maint print msymbols" }
+ }
+ }
+ -re ".*$gdb_prompt $" { fail "maint print msymbols" }
+ timeout { fail "(timeout) maint print msymbols" }
+ }
+
+
+send_gdb "maint print symbols\n"
+gdb_expect {
+ -re "Arguments missing: an output file name and an optional symbol file name.*$gdb_prompt $"\
+ { pass "maint print symbols w/o args" }
+ -re ".*$gdb_prompt $" { fail "maint print symbols w/o args" }
+ timeout { fail "(timeout) maint print symbols w/o args" }
+ }
+
+send_gdb "maint print symbols symbols_output\n"
+gdb_expect {
+ -re "^maint print symbols symbols_output\r\n$gdb_prompt $"\
+ {
+ send_gdb "shell ls symbols_output\n"
+ gdb_expect {
+ -re "symbols_output\r\n$gdb_prompt $"\
+ {
+ # See comments for `maint print psymbols'.
+ send_gdb "shell grep 'main.*block' symbols_output\n"
+ gdb_expect {
+ -re "int main\\(int, char \\*\\*, char \\*\\*\\); block.*$gdb_prompt $"\
+ { pass "maint print symbols" }
+ -re ".*$gdb_prompt $" { fail "maint print symbols" }
+ timeout { fail "(timeout) maint print symbols" }
+ }
+ gdb_test "shell rm -f symbols_output" ""
+
+ }
+ -re ".*$gdb_prompt $" { fail "maint print symbols" }
+ timeout { fail "(timeout) maint print symbols" }
+ }
+ }
+ -re ".*$gdb_prompt $" { fail "maint print symbols" }
+ timeout { fail "(timeout) maint print symbols" }
+ }
+
+
+send_gdb "maint print type argc\n"
+gdb_expect {
+ -re "type node $hex\r\nname .int. \\($hex\\)\r\ncode $hex \\(TYPE_CODE_INT\\)\r\nlength 4\r\nobjfile $hex\r\ntarget_type $hex\r\npointer_type $hex\r\nreference_type $hex\r\nflags $hex\r\nnfields 0 $hex\r\nvptr_basetype $hex\r\nvptr_fieldno -1\r\ntype_specific $hex\r\n$gdb_prompt $"\
+ { pass "maint print type" }
+ -re ".*$gdb_prompt $" { fail "maint print type" }
+ timeout { fail "(timeout) maint print type" }
+ }
+
+#send_gdb "maint print unwind &main\n"
+#gdb_expect {
+# -re ".*unwind_table_entry \\($hex\\):\r\n\tregion_start = $hex <main>\r\n\tregion_end = $hex <main\\+220>\r\n\tflags = Args_stored Save_RP\r\n\tRegion_description = $hex\r\n\tEntry_FR = $hex\r\n\tEntry_GR = $hex\r\n\tTotal_frame_size = $hex\r\n$gdb_prompt $"\
+# { pass "maint print unwind" }
+# -re ".*$gdb_prompt $" { fail "maint print unwind" }
+# timeout { fail "(timeout) maint print unwind" }
+# }
+
+set oldtimeout $timeout
+set timeout [expr $timeout + 300]
+
+# It'd be nice to check for every possible section. However, that's
+# problematic, since the relative ordering wanders from release to
+# release of the compilers. Instead, we'll just check for two
+# sections which appear to always come out in the same relative
+# order. (If that changes, then we should just check for one
+# section.)
+#
+# And by the way: This testpoint will break for PA64, where a.out's
+# are ELF files.
+#
+send_gdb "maint info sections\n"
+gdb_expect {
+ -re "Exec file:\r\n.*break., file type.*$gdb_prompt $"\
+ { pass "maint info sections" }
+ -re ".*$gdb_prompt $" { fail "maint info sections" }
+ timeout { fail "(timeout) maint info sections" }
+ }
+
+send_gdb "maint info breakpoints\n"
+gdb_expect {
+ -re "Num\[ \t\]+Type\[ \t\]+Disp\[ \t\]+Enb\[ \t\]+Address\[ \t\]+What\r\n1\[ \t\]+breakpoint\[ \t\]+keep\[ \t\]+y\[ \t\]+$hex in main at.*break.c:60\r\n\[ \t\]+breakpoint already hit 1 time\r\n.*$gdb_prompt $"\
+ { pass "maint info breakpoints" }
+ -re ".*$gdb_prompt $" { fail "maint info breakpoints" }
+ timeout { fail "(timeout) maint info breakpoints" }
+}
+
+# Try it again, and check for shlib event info. Not supported everywhere.
+if {! [istarget "hppa*-*-hpux*"]} then {
+ setup_xfail "*-*-*"
+}
+send_gdb "maint info breakpoints\n"
+gdb_expect {
+ -re "Num\[ \t\]+Type\[ \t\]+Disp\[ \t\]+Enb\[ \t\]+Address\[ \t\]+What\r\n1\[ \t\]+breakpoint\[ \t\]+keep\[ \t\]+y\[ \t\]+$hex in main at.*break.c:60\r\n\[ \t\]+breakpoint already hit 1 time\r\n-1\[ \t\]+shlib events\[ \t\]+keep\[ \t\]+y\[ \t\]+$hex.*breakpoint already hit.*$gdb_prompt $"\
+ { pass "maint info breakpoints: shlib events" }
+ -re ".*$gdb_prompt $" {
+ fail "maint info breakpoints: shlib events"
+ }
+ timeout {
+ fail "(timeout) maint info breakpoints: shlib events"
+ }
+}
+
+
+send_gdb "maint print\n"
+gdb_expect {
+ -re "\"maintenance print\" must be followed by the name of a print command\\.\r\nList.*unambiguous\\..*$gdb_prompt $"\
+ { pass "maint print w/o args" }
+ -re ".*$gdb_prompt $" { fail "maint print w/o args" }
+ timeout { fail "(timeout) maint print w/o args" }
+ }
+
+send_gdb "maint info\n"
+gdb_expect {
+ -re "\"maintenance info\" must be followed by the name of an info command\\.\r\nList.*unambiguous\\..*$gdb_prompt $"\
+ { pass "maint info w/o args" }
+ -re ".*$gdb_prompt $" { fail "maint info w/o args" }
+ timeout { fail "(timeout) maint info w/o args" }
+ }
+
+send_gdb "maint\n"
+gdb_expect {
+ -re "\"maintenance\" must be followed by the name of a maintenance command\\.\r\nList.*unambiguous\\..*$gdb_prompt $"\
+ { pass "maint w/o args" }
+ -re ".*$gdb_prompt $" { fail "maint w/o args" }
+ timeout { fail "(timeout) maint w/o args" }
+ }
+
+
+set timeout $oldtimeout
+
+#============test help on maint commands
+
+send_gdb "help maint\n"
+gdb_expect {
+ -re "Commands for use by GDB maintainers\\..*Includes commands to dump specific internal GDB structures in.*a human readable form, to cause GDB to deliberately dump core,.*to test internal functions such as the C.. demangler, etc\\..*List of maintenance subcommands:.*maintenance check-symtabs.*maintenance demangle.*maintenance dump-me.*maintenance info.*maintenance print.*maintenance space.*maintenance time.*Type.*help maintenance.*followed by maintenance subcommand name for full documentation\\..*Command name abbreviations are allowed if unambiguous\\..*$gdb_prompt $"\
+ { pass "help maint" }
+ -re ".*$gdb_prompt $" { fail "help maint" }
+ timeout { fail "(timeout) help maint" }
+ }
+
+
+send_gdb "help maint check-symtabs\n"
+gdb_expect {
+ -re "Check consistency of psymtabs and symtabs\\..*$gdb_prompt $"\
+ { pass "help maint check-symtabs" }
+ -re ".*$gdb_prompt $" { fail "help maint check-symtabs" }
+ timeout { fail "(timeout) help maint check-symtabs" }
+ }
+
+send_gdb "help maint space\n"
+gdb_expect {
+ -re "Set the display of space usage\\.\r\nIf nonzero, will cause the execution space for each command to be\r\ndisplayed, following the command's output\\..*$gdb_prompt $"\
+ { pass "help maint space" }
+ -re ".*$gdb_prompt $" { fail "help maint space" }
+ timeout { fail "(timeout) help maint space" }
+ }
+
+send_gdb "help maint time\n"
+gdb_expect {
+ -re "Set the display of time usage\\.\r\nIf nonzero, will cause the execution time for each command to be\r\ndisplayed, following the command's output\\..*$gdb_prompt $"\
+ { pass "help maint time" }
+ -re ".*$gdb_prompt $" { fail "help maint time" }
+ timeout { fail "(timeout) help maint time" }
+ }
+
+send_gdb "help maint demangle\n"
+gdb_expect {
+ -re "Demangle a C\\+\\+ mangled name\\.\r\nCall internal GDB demangler routine to demangle a C\\+\\+ link name\r\nand prints the result\\..*$gdb_prompt $"\
+ { pass "help maint demangle" }
+ -re ".*$gdb_prompt $" { fail "help maint demangle" }
+ timeout { fail "(timeout) help maint demangle" }
+ }
+
+send_gdb "help maint dump-me\n"
+gdb_expect {
+ -re "Get fatal error; make debugger dump its core\\.\r\nGDB sets it's handling of SIGQUIT back to SIG_DFL and then sends\r\nitself a SIGQUIT signal\\..*$gdb_prompt $"\
+ { pass "help maint dump-me" }
+ -re ".*$gdb_prompt $" { fail "help maint dump-me" }
+ timeout { fail "(timeout) help maint dump-me" }
+ }
+
+send_gdb "help maint print statistics\n"
+gdb_expect {
+ -re "Print statistics about internal gdb state\\..*$gdb_prompt $"\
+ { pass "help maint print statistics" }
+ -re ".*$gdb_prompt $" { fail "help maint print statistics" }
+ timeout { fail "(timeout) help maint print statistics" }
+ }
+
+send_gdb "help maint print objfiles\n"
+gdb_expect {
+ -re "Print dump of current object file definitions\\..*$gdb_prompt $"\
+ { pass "help maint print objfiles" }
+ -re ".*$gdb_prompt $" { fail "help maint print objfiles" }
+ timeout { fail "(timeout) help maint print objfiles" }
+ }
+
+send_gdb "help maint print psymbols\n"
+gdb_expect {
+ -re "Print dump of current partial symbol definitions\\.\r\nEntries in the partial symbol table are dumped to file OUTFILE\\.\r\nIf a SOURCE file is specified, dump only that file's partial symbols\\..*$gdb_prompt $"\
+ { pass "help maint print psymbols" }
+ -re ".*$gdb_prompt $" { fail "help maint print psymbols" }
+ timeout { fail "(timeout) help maint print psymbols" }
+ }
+
+send_gdb "help maint print msymbols\n"
+gdb_expect {
+ -re "Print dump of current minimal symbol definitions\\.\r\nEntries in the minimal symbol table are dumped to file OUTFILE\\.\r\nIf a SOURCE file is specified, dump only that file's minimal symbols\\..*$gdb_prompt $"\
+ { pass "help maint print msymbols" }
+ -re ".*$gdb_prompt $" { fail "help maint print msymbols" }
+ timeout { fail "(timeout) help maint print msymbols" }
+ }
+
+send_gdb "help maint print symbols\n"
+gdb_expect {
+ -re "Print dump of current symbol definitions\\.\r\nEntries in the full symbol table are dumped to file OUTFILE\\.\r\nIf a SOURCE file is specified, dump only that file's symbols\\..*$gdb_prompt $"\
+ { pass "help maint print symbols" }
+ -re ".*$gdb_prompt $" { fail "help maint print symbols" }
+ timeout { fail "(timeout) help maint print symbols" }
+ }
+
+
+send_gdb "help maint print type\n"
+gdb_expect {
+ -re "Print a type chain for a given symbol\\.\r\nFor each node in a type chain, print the raw data for each member of\r\nthe type structure, and the interpretation of the data\\..*$gdb_prompt $"\
+ { pass "help maint print type" }
+ -re ".*$gdb_prompt $" { fail "help maint print type" }
+ timeout { fail "(timeout) help maint print type" }
+ }
+
+#send_gdb "help maint print unwind\n"
+#gdb_expect {
+# -re "Print unwind table entry at given address\\..*$gdb_prompt $"\
+# { pass "help maint print unwind" }
+# -re ".*$gdb_prompt $" { fail "help maint print unwind" }
+# timeout { fail "(timeout) help maint print unwind" }
+# }
+
+send_gdb "help maint info sections\n"
+gdb_expect {
+ -re "List the BFD sections of the exec and core files\\..*$gdb_prompt $"\
+ { pass "help maint info sections" }
+ -re ".*$gdb_prompt $" { fail "help maint info sections" }
+ timeout { fail "(timeout) help maint info sections" }
+ }
+
+
+send_gdb "help maint info breakpoints\n"
+gdb_expect {
+-re "Status of all breakpoints, or breakpoint number NUMBER.*$gdb_prompt $" { pass "help maint info breakpoints" }
+ -re ".*$gdb_prompt $" { fail "help maint info breakpoints" }
+ timeout { fail "(timeout) help maint info breakpoints" }
+ }
+
+#send_gdb "help maint info breakpoints\n"
+#expect {
+# -re "Status of all breakpoints, or breakpoint number NUMBER\\.\[ \r\n\t\]+The \"Type\" column indicates one of:\[ \r\n\t\]+breakpoint\[ \t\]+- normal breakpoint\[ \r\n\t\]+watchpoint\[ \t\]+- watchpoint\[ \r\n\t\]+longjmp\[ \t\]+- internal breakpoint used to step through longjmp\\(\\)\[ \r\n\t\]+longjmp resume - internal breakpoint at the target of longjmp\\(\\)\[ \r\n\t\]+until\[ \t\]+- internal breakpoint used by the \"until\" command\[ \r\n\t\]+finish\[ \t\]+- internal breakpoint used by the \"finish\" command\[ \r\n\t\]+The \"Disp\" column contains one of \"keep\", \"del\", or \"dis\" to indicate\[ \r\n\t\]+the disposition of the breakpoint after it gets hit\\. \"dis\" means that the\[ \r\n\t\]+breakpoint will be disabled\\. The \"Address\" and \"What\" columns indicate the\[ \r\n\t\]+address and file.line number respectively\\.\[ \r\n\t\]+Convenience variable \".*\" and default examine address for \"x\"\[ \r\n\t\]+are set to the address of the last breakpoint listed\\.\[ \r\n\t\]+Convenience variable \".bpnum\" contains the number of the last\[ \r\n\t\]+breakpoint set\\..*$gdb_prompt $"\
+# { pass "help maint info breakpoints" }
+# -re ".*$gdb_prompt $" { fail "help maint info breakpoints" }
+# timeout { fail "(timeout) help maint info breakpoints" }
+# }
+
+send_gdb "help maint info\n"
+gdb_expect {
+ -re "Commands for showing internal info about the program being debugged.*unambiguous\\..*$gdb_prompt $"\
+ { pass "help maint info" }
+ -re ".*$gdb_prompt $" { fail "help maint info" }
+ timeout { fail "(timeout) help maint info" }
+ }
+
+send_gdb "help maint print\n"
+gdb_expect {
+ -re "Maintenance command for printing GDB internal state\\.\[\r\n\]+List of maintenance print subcommands:\[\r\n\]+maintenance print msymbols -- Print dump of current minimal symbol definitions.*maintenance print objfiles -- Print dump of current object file definitions.*maintenance print psymbols -- Print dump of current partial symbol definitions.*maintenance print statistics -- Print statistics about internal gdb state.*maintenance print symbols -- Print dump of current symbol definitions.*maintenance print type -- Print a type chain for a given symbol.*Type .help maintenance print. followed by maintenance print subcommand name for full documentation\\.\[\r\n\]+Command name abbreviations are allowed if unambiguous\\..*$gdb_prompt $"\
+ { pass "help maint print" }
+ -re ".*$gdb_prompt $" { fail "help maint print" }
+ timeout { fail "(timeout) help maint print" }
+ }
+
+send_gdb "help maint\n"
+gdb_expect {
+ -re "Commands for use by GDB maintainers\\.\[\r\n\]+Includes commands to dump specific internal GDB structures in\[\r\n\]+a human readable form, to cause GDB to deliberately dump core,\[\r\n\]+to test internal functions such as the C\\+\\+ demangler, etc\\..*Type.*help maintenance.*followed by maintenance subcommand name for full documentation\\.\[\r\n\]+Command name abbreviations are allowed if unambiguous\\..*$gdb_prompt $"\
+ { pass "help maint" }
+ -re ".*$gdb_prompt $" { fail "help maint" }
+ timeout { fail "(timeout) help maint" }
+ }
+
+#set oldtimeout $timeout
+#set timeout [expr $timeout + 300]
+
+send_gdb "maint dump-me\n"
+gdb_expect {
+ -re "Should GDB dump core.*\\(y or n\\) $"\
+ { send_gdb "n\n"
+ gdb_expect {
+ -re ".*$gdb_prompt $" { pass "maint dump-me" }
+ timeout { fail "(timeout) maint dump-me" }
+ }
+ }
+ -re ".*$gdb_prompt $" { fail "maint dump-me" }
+ timeout { fail "(timeout) maint dump-me" }
+ }
+
+#set timeout $oldtimeout
+
+
+gdb_exit
+return 0
diff --git a/gdb/testsuite/gdb.base/mips-ecoff.u b/gdb/testsuite/gdb.base/mips-ecoff.u
new file mode 100644
index 00000000000..69f656a1814
--- /dev/null
+++ b/gdb/testsuite/gdb.base/mips-ecoff.u
@@ -0,0 +1,671 @@
+begin 777 mips-ecoff
+M 6 "2G<_%0 # 8 X <!"P(* @ $ )= $ !P ! 0
+M $ 0 //___X -T $ "*@"YT97AT $ !P !
+M < !E0 !P " N:6YI= ! &Q 0!L0
+M( &Q " +F1A=&$ 0 $ "I "
+M 0"YL:70X $ *D! "I 0 JD
+M @ N;&ET- ! "J 0 J@ $ *J
+M 0 +G-D871A 0 JP$ *L & "JP , "
+M "YS8G-S $ +$! "Q % # ! N8G-S
+M ! #% 0 Q0 ":\ " <G-R8P
+M " (^D
+M \'! !)Z4 !"><BH DI@ $ 00@*^%@90 PC A)[W_Z*^&@#"OH 4 #P
+M(0P0!L>OA(&0#! !9 ,$ %H @(8^$@9"/A8&4CX: , P0 .L
+M#! !I ! ("$ - ^ " GO0 ( ^ " @^"$#X (
+M /@ @ ! A ^ " #X ( /@ @ ! A ^ "
+M #X ( /@ @ ! A ^ " #X ( /@ @ ! A ^
+M" #X ( /@ @ ! A ^ " #X ( /@ @ ! A
+M ^ " #X ( /@ @ ! A ^ " #X ( /@ @
+M ! A ^ " #X ( /@ @ ! A ^ " #X ( /@
+M @ ! A ^ " #X ( /@ @ ! A ^ " #X (
+M /@ @ ! A ^ " #X ( $2 #X ( /@ @
+M ^ " !$@ 1( ( /@ @ ^ " #X ( *. @) D
+M#@ !HXZ D20/ *CCX"2)!@ Z>8@)0D&0 $IYF EB0( 6GB("8) D !J^)
+M@)PD"@ 'KXJ H"0+ BOBX"D) P ":^,@*@D#0 *KXV K"0. NOCH"PQX2
+M( #GA("TQX> $,>&@!3GAX"XYX: O)./@) HX^ P).8@)$
+MHYB PI.9@)( HYF Q(>(@)0 IXB R(>)@)8 IXF S)>*@)@
+M IXJ T(^+@)P KXN V(^,@* KXR X(^-@*0 KXV Z(^.
+M@*@ KXZ \(^/@*P KX^ ^(^8@+ KYB! ,>(@+0 YXB!
+M",>+@+C'BH"\/ $0 .0K8_#D*F/T)YF D*^9@1 GB("1KXB!%">)@)*OB8$8
+M)XJ E*^*@1PGBX"6KXN!(">,@)BOC($D)XV G*^-@2@GCH"@KXZ!+">/@*2O
+MCX$P)YB J*^8@30GF8"LKYF!.">(@+"OB($\)XF M*^)@4 GBH"XKXJ!1"0+
+M *OBX%<) P J^,@6 D#0 !KXV!:"0. &OCH%DCX^!6#P!$ "L+V,PAYB!
+M2 "GF(%0 ^ " $"$#X ( #X (
+M)[W]4 " &"$D#O__K[\ '!1@ !&OK@ D/ 00 P0 ;0DA ($$$ !0! &"&0
+M3P !7@ @ DYB 0 3 # ! ", ! A)X. 1#P%
+M$ "C@(! )*4"$">D C ,$ 'TKZ,"L(^C K GI (^#! !] !@*"$GI (P#! "
+M( *"$$0 1 $ @(2>E "PD!@("#! "**^D "@D 0("%$$ "(^D "@\!!
+M)(0 ">E "P,$ (P) 8" J^@ "2/I H#! "] "/H@ D (^_ !PG
+MO0*P ^ " )[W_X*^_ !P,$ ,.KZ0 ( P0 R@ CZ0 ( P0
+M!4P C[\ '">] " #X ( ">]_^"/@H PK[$
+M&*^P !0 @(@AK[\ '!1 , 0( A$ %0 $"&/CH P (W/
+M$> #P $"&.!0 (@("$,$ '7)A !!! , 0!@A$ !@!@$"&.
+M!0 !2@__<"(" A 0(8^_ !R/L 4C[$ & /@ @GO0 @D*( )"#
+M DI0 !$$, !"0& #T0 ,) 8 /20& #T 8! A%$8 R2$ $#X ( * 0
+M(9"B "0@P )*4 1!#__@ 8! A%& " $"&0KO__ !3. 0 ! A
+M ^ " "@$"$ ! A ^ " @! A@*@ #2- ,1 D :1P(H"I $
+MKG@@$2 'P " J@ " !% !J(K @*L YBL ,18 4J(P "&D
+M__V!Z !(>\ !!$ !,@A $@>G__@ 1( . ('J__\ $4
+M"8GL__V!ZP F>P !5@__&LC ^ " #X (N(P Z"* *@B0 !
+M ^ "*"( "0" ^T ,$. P ($ 50 /@ @
+M ) (#ZP P0X # @0!5 ^ " 0P : ( X(1"D
+M !@ A0@J%" ""C! ! IA @ (((*A @ 0HP0 0$ 6RC! ! HP0 0%"
+M!0 PH@ #,(, Q!# L $, !P IA@A@*( "2E $DA !
+M%*/__*""__\#X ( . 0(1! !@D 0 !$$$ #R0! (000 ' ("B D
+MI0 !)(0 23&__\0 .H(+__X2B DI0 ")(0 B3&__X0 (I(+__H"B
+M "$HP !H(( "2E ,DA #),;__:2#__XHP0 @%" %BC! !",H@ C*,
+M!(RH B,J0 ,C*H $(RK !2,K 8C*T '*R" "L@P $K(@ "*R) RLB@ 0
+MK(L %*R, !@DI0 @)(0 ("3&_^ 0 /_JK(W__"C! ! 4( .*,$ !(RB ",
+MHP $C*@ "(RI RL@@ K(, !*R( @DI0 0)(0 $"3&__ 0 /_RK(G__"C!
+M 04(/^U (RB DI0 $)(0 !"3&__P0 /_XK(+__"C! ! IB@@%"
+M!0"&(" PH@ #,(, Q!# T $,#_K0 DI?__)(3__P"F&". H@
+M)*7__R2$__\4H__\H(( 0/@ @ X! A$$ &"0! ,000 /) $ A!! <
+M @*+__R2E__\DA/__),;__Q Z@@@ A*+__B2E__XDA/_^),;__A
+M BD@@ @*+__X2C__V@@O__)*7__22$__TDQO_]I(, "C! " 4( 6*,$
+M$(RB__R,H__XC*C_](RI__",JO_LC*O_Z(RL_^2,K?_@K(+__*R#__BLB/_T
+MK(G_\*R*_^RLB__HK(S_Y"2E_^ DA/_@),;_X! _^JLC0 *,$ $!0@ XH
+MP0 $C*+__(RC__B,J/_TC*G_\*R"__RL@__XK(C_]"2E__ DA/_P),;_\!
+M__*LB0 *,$ !!0@_[, C*+__"2E__PDA/_\),;__! __BL@@
+M ) (#[@ P0X # @0!5 ^ " $"$0@ /
+M) ( 8^#@& *&$ (! @ HD @ ! -P@#P!$ +@@A)&, :PD B"O
+M@X!@ ^ " $"$D @ ! ^ " "/@X!@)[W_X*^_ !ROL0 8K[ %!A@
+M \D8O__/ \0 "7O B G" /!$0 "8Q B !SX ACA@ # /@)
+M "80__P"$0@K$"#_^0 "/OP <C[ %(^Q !@#X ()[T ((^.@' GO?_@
+M/ \0 *^P !@E[P0U/! 0 '/""NOOP <%" $280!#0\&! CQ@+ 3
+M % P0 W8" " A$ P ,$ -& @ @(8^9@' F$ 0 AD(*Q0@
+M__$ C[\ '(^P !@#X ()[T (">]_]BOL 8 (" (:^_ !P6 #) /_
+M_Q "4D O__D@( # P3@"#$< %#!8 @P3P &) $ A7A 8 !@A
+M#! #=@( ("$0 " $ 8(0 &"&2! -#! "]*^C "2/HP D!$$ @ D
+M ___D@( # P6 ($P !@ ".! (#! &&J^C "2/HP DK@ "(X9
+M BB ,K@ !@$"&N&0 $C[\ '(^P !@#X ()[T *">]_^"OL 8 ("
+M(18 !.OOP <CXZ <#P/$ E[P0U/! 0 '/""L4( *)A $-!( ,
+M#! #=@( ("&/F(!P)A $ (8""L4(/_X ! #@ ! AD@, # P
+M8@ "%$ ##!H 2.!0 D@0 #20& $,$ 9P 4H(XX9 BN 0(1
+M "FN&0 $,&@ !!4 " P;0 @$$ 'C!M "". @ ( !! !HP;0 @C@D
+M! 20@K$" %3!M " ,$ 14 @ @(9(# P ,&H !!5 XP;0 @
+M,&L A%@ LP;0 @C@( " 00 ',&T ((X, 0 $P(*Q0@_^X
+M ,&T (!&@ 0 !@A$ B0#__\ !@A & 0(8^_ !R/L 8 ^ "">]
+M " GO?^PK[ '*^_ "ROLP H *" (:^R "2OL0 @KZ0 4)(# PD$0!")!(
+M!B03 (P;@!2%BX )3!L !:2#P -/!D0 /P( #.,@ACSD"H(X" 0
+M %D(*Q @ $\ CZ@ 4"0! J@2 C@D ! E*@ !K@H !).K %,
+M $6$ ! "/H@!0$ 8(^_ "P,$ 14 @ @(20!__\400 $CZ, 4!
+M ,D ___CZ, 4 0 !4 & 0(3!L !863 4,'@ $H^M % GI0!,HZT
+M3)($ VN #! &>"0& $D 0 !%$$ ! "/H@!0$ 18^_ "R2#@ ,
+M) +__S7/ " 0 _H@\ ##!X !(6> 0 (X" @ $$ # ".
+M&0 $ !19 P C@@ 5 ( #!I $05( & 8(0P0
+M!)H" " A$ @! &"$ !@A$& P 0 D) +__Y(# P ,&H
+M1!5 _Z<P;@!2#! $5 ( ("&. @ "1"__\$00 &K@( ).D %,,$ /(
+M @ H(1 J2#P ,CZL 4(X, 0 H8L (X- 0 ):X :X. 22
+M#P , #'X " 3 $CZ, 4! ,D ___CZ, 4 8! AC[\ +(^P
+M !R/L0 @C[( )(^S "@#X ()[T 4">]_^"OOP 4 ( X(8SC B0[P ,C.X
+M! !@*"$Q^ !$K.4 !!, @!Q3 CD/D #3P)$ E*0*@ !E @ $)("$0 *
+MK. )#J T\#! )8P"H *6( !;" AC(T !HQ CK.( (SB
+M !$$ ! ! &"$0 " 8(0! &"&,C@ C.\ ! !S\ C P,(*A @
+M H KZ4 '*^F !@ X" A#! %-J^G ""/I0 <CZ8 &(^G " &,
+M#P $"&0Y -KZ< ( P0!GBOI@ 8CZ8 &(^G " 0P@ ' 0(9#Y PD O__
+M-R@ (! *@Z , 0(8^_ !0GO0 @ ^ " GO?_HK[\ %)"" PD
+M 0 ",$X $A'! P ,$\ @A7@ 8D ?_O#! &@R0$ D0 R) +__R0!
+M_^\ 0< D-QD J"9 R,@P ( !1@ < #! $W:^D !B/I 8
+M (R# @ C(@ ! 4: @ 0(9") P ,2H 1!5 !L ! A
+MD(L #3P-$ EK0*@ M@@ &-*"&,K@ '#>".LCP C(( $
+M00 $ $ 8(1 ( !@A $ 8(8RX ",F0 $ ,90",! P@J$" !
+M$"$,$ 4V $"&/OP 4)[T & /@ @ )[W_X*^_ !0 @"@AD*X
+M#)"C TQSP $$> # !@,"$\&1 )SE@" &P, #&1 A -(@#P!$ *0@A
+MK*( ""1( @0 TK"@"H"C! (0( 3 !3 8 / ,0 "1C$ "L
+MHP ($ !0!@$"$\ Q )&- *RC @ 8! AD*L #3P!$ "V" "P((21*
+M( 0 ?K"H"H*^E " D!" (#! %5*^F !R/I0 @CZ8 '!! RLH@ (D*T
+M#)"Y V,KP (/ $0 #6N @ &4" H*X # H""$E^" $ #*PX J \"Q
+MD*P #25K8 @ !DC 2L0(3P!$ #&B "T((:RB @D2@ (K"H"H(RN @
+MP" AK*X ! P0!HBOI0 @CZ4 (!! F/OP 4D*( # P3P $%> !(^_
+M !0T60! H+D #(^_ !0GO0 @ ^ " "0C@ -/ ,0 .>( ;Q@AC&,"
+MH(R8 0 '@0(P1! , ^ "*R# 2,F0 !9""H0( "
+M *R" #X ( ) (#Z0 P#X ( #P!$ "L
+M(@P8 ^ ""0"__\GO?^HK[8 +*^R !ROOP TK[< ,*^U "B/CH%PK[0 )*^S
+M ""OL0 8 ("0(:^P !01P $ "P(8^%@800 +)Y6!<">"@70GE8%PKX*!
+M?#1/ &OCX%P-K@ 0*@."&OF(%T $ H(:^'@7B/AX%X)!?__R04__X X(@A
+M P(8XC & 0(3!9 $7( = B" (0!@@"&. @ )D0 !P $(((P
+M2 !%0 #@ $(( "(#@AKX>!>!2P *N(@ B H(8XC &" (8X"
+M ,$D 1$@__8 B00(0("""L4( # %$(*Q @ &H & 0
+M(0(@@"$ 5(@D A$(*Q0@_]L CXJ!? 2"@ # ! 2OA8&$
+M$C4 !23& &OA8&$$ :P $"$DQ@ !+,$ A0@_\P )D, !P #&(*O
+MHP X *"((0 ("$,$ :@KX6!A(^+@7R/HP X)6P !!!, P 0( A)&8'_P &
+M,L(P1 #$( $ &,T D#0 $ :08(P!@L"$ 0X A$ "@#6,"&/A8&$CXZ!
+M? !Q7@C _ @P!X,",DQ@@ 8RP@ &,T "!L@A S (*Q @ 0\ 7__
+M$ 00 $"$\ 7__-"'@ 0#!""L4( - ,"8(3P$?_\TA. #! &H*^F $B/
+MI@!(%%< !#P!@ 0 S 0(3P!@ T(2 ,$P(0P0!J P" A%%< !0
+M ,$ :L @ @(1 "@ ! ACXB!? (32"$!-E C)4O__*T0 "N"P CXR!
+M? ( *"$EC0 $$@T !3:B &-C@ #7/ &MCP CA@ "OF(%\
+MCYF!?! _W>O(@ $ X(0#P""L0( &-.D 8SH KXB!@*SC T
+MZ0 !$+$ !*XI "OAX%X$ !*^%@80 X"@AKX6!A*^'@7@F(@ $C[\ -(^P
+M !2/L0 8C[( '(^S ""/M DC[4 *(^V "R/MP P ^ "">] %@0@ - ( 0
+M(22"__RO@H%XC$X "0!__X!P7@DK$\ (Q9 "/F(%\ !<9 (
+MKX*!A /@ @ )[W_R*^P !@ @( A$@ .*^_ !R. O_\ #!. $1
+MP ( % 8(P( ("$,$ 8:KZ4 /(^E #R. O_\ !0&", QB#KZ, ) "@
+M("$,$ 54KZ4 /(^C "2/I0 \$$ !0! ("$04 # !2@ 0DIP #$
+M(0" $"$DIP # <X@@#C""L0( " #@&"&OI T @ H(0 #,( ,$ (P
+MKZ< ((^D #2/IP @ % (*Q @ ! =X@ !/&"$ < @K%" "P
+M<,@C !E @X^8@8 "$B $E0(1 2M6 #! %5 "@("$ 0" A ( 0(8^_
+M !R/L 8 ^ "">] #@ "0" _L ,$. P ($ 50
+M /@ @ ) (#[ P0X # @0!5 ^ " "/@H&8
+M ^ " "OA(&8 ^ " " $"$ ">]_["OOP <#! &@*^D %"/
+MI !0KZ( )"0%5 @,$ :\)Z8 * 1! <D @ !CZ0 ) P0!H, $ @
+M$"$D @ !C[\ '">] % #X ( #P#$ ",8PJ$) (#
+M^0"#("$ ,%. !#P!$ 8! A ^ "*PD"H0($ 50 #P"$ ",0@J
+M """"L0( " ! ("$D @/Y #!3@__0\ 1 K"0*A /@ @
+M ! A D @0> #!#@ , "! %4 #X (
+M #X (
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M (" @(" @(" @*"@H*"@@(" @(" @(" @(" @(" @("!($! 0$! 0$! 0
+M$! 0$! 0A(2$A(2$A(2$A! 0$! 0$!"!@8&!@8$! 0$! 0$! 0$! 0$! 0$!
+M 0$! 1 0$! 0$(*"@H*"@@(" @(" @(" @(" @(" @(" @("$! 0$"
+M
+M
+M 0(#! 4&!P@)
+M"@L,#0X/$!$2$Q05%A<8&1H;'!T>'R A(B,D)28G*"DJ*RPM+B\P,3(S-#4V
+M-S@Y.CL\/3X_0&%B8V1E9F=H:6IK;&UN;W!Q<G-T=79W>'EZ6UQ=7E]@04)#
+M1$5&1TA)2DM,34Y/4%%24U155E=865I[?'U^?P
+M
+M
+M !#2%)#3$%34P O;&EB+V-H<F-L
+M87-S+P
+M
+M
+M ! 8"
+M
+M
+M
+M
+M
+M
+M
+M
+M $ " 0 ! 8!@0 & 8!@(
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M 0 *= $ "G0
+M 0&D $+(
+M 0 &%S8VEI
+M $ *=
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M < D""@ !D + P8 - ,R $Y ]L
+M "$P 3%P A, !4J !B0 %ST '@ 8Q@ !< !K
+MB (< &SX,/ @X# 00-! T$ 0(*"! !9 \# 0$!%@P% A(! 0(04%!04%
+M!04%!04%!08',!$1(1$1(1$1(1$1(A,R$A(B$A(B$A(B$A(B%"$1$2$1$2$1
+M$2$1$2$1(1$1$2(B$P$!,-" BP6(, "1$0,/ 4$A0F5! B)0& Z __*!
+M \2$P4PX#$7%!$8 !<2$1@!$1)08! 0$! 0$! 0$! 0$! 0$! P$! 0$! 0
+M$! 0$! 0$! 0$! P$" 0$! $!$1$0 0$1$10/ A,A 2$8( "A 0$7$0(! @
+M$.! \($ "A(2,! @$!#0<! @$!#0<! @\# 0X(( #! 0$! 0$! 0(! 0$! 0
+M$)" D0$-!R$! 0$" 0$-!0$!#0<A 0(! 0T( $,! T$ 0$7$0$! @$" 0
+MX$#P@0 *$A(P$" 0$-!P$" 0$-!P$"#P,!#@@@ ,$! 0$! 0$! @$! 0$! 0
+MD( "1 0T'(0$! 0(! 0T% 0$-!R$! @$!#0 ! 1$2$6%!(B!"<7%##0,- R
+MT#&$ H3,103 T#0010C$R 5$"$2$Q! X! @\!,",-!V$R8T)"#P(?!(!!@(
+M !@!" )2& H 1(8 3(0(. @\!02$!#P$/!H" 81%#$8""@' D @X2#P$. H
+M!A@(!!@ $!#P$/ T 102$1$C(Q48&!@&) ) T#'02!#P,B@(-R 2\!#P$1#P
+M. $@$/ 8 !$3. 1%! 1 !)A</ %<)1PT#0PX1 @X# 10A 5&$#P$!<6(! 0
+M$B@A$Q% \!(0\!'P<1'P(A PX" W(Q%#\"81(B,1$4!"P$ 0D'(3$A @X$ B
+M$A @(. E& ) T'$S%3$"@ )@/_WA +%1$5(. C$200%A<4$/ R% 0$1$1
+M ! 1$1%"0"$!0,!0\!0B$20A(/ @$2#P$2$3$" 0$1$1 ! 1$1$
+M @ /____\ !@ '0 . &<
+M : 0 : #_____ !T 'P ((
+M "$ &@ ' & ' _____P =
+M !\ "/ DP !L !\ " !\ /____\
+M '0 ? G@ * > "$ #_____
+M !T 'P 'D !Y !@ E !@
+M _____P = !\ !Z >@ $ P *0
+M P /____\ '0 ? >P 'L "
+M2 "T 2 #_____ !T 'P 'T !]
+M P & Q & _____P = !\
+M !^ ?@ 0 !X -0 !X /____\
+M '0 ? ?P '\ % D #D D #_____
+M !T 'P ($ "! !@ *@ ] *@
+M_____P = !\ "" @@ < # 00 #
+M /____\ '0 ? @P (, ( V
+M $4 V #_____ !T 'P (4 "%
+M"0 / !) / _____P = !\ "&
+M A@ H $( 30 $( /____\
+M'0 ? AP (< + !( %$ !( #_____
+M !T 'P (D ") # 3P !5 3P ____
+M_P = !\ "* B@ T %< A0 %<
+M /____\ '0 ? L@ /< . $
+M #_____ !T 'P ( "
+M " ( #___UL_____P "L = !\ !?
+M@P 0 " _____/____\ " '0 ?
+M '0 "X $ @ , /____S_____
+M @ !T 'P !X F (P # (P _____P
+M = !\ S .0 D 0
+M /____\ '0 ? 8@ )H $
+M #_____ !T 'P X 2
+M ! _____P = !\ . $@
+M 0 /____\ '0 ?
+M* 2X $ #_____
+M !T 'P X 3 # _____P
+M = !\ 7 ' !( !0 !* P _____/__
+M__\ " '0 ? (0 "4 $ $ @ $
+M /____S_____ @ !T 'P "H ] '@ #
+M 'H ! #____T_____P * = !\ !. 90 X
+M $X !0 $Z 0 _____/____\ " '0 ? <@
+M (D B "@ < "@@ \ /___]S_____ !0 !T
+M'P )H "Z -0 !+ ) !+( #____T_____P
+M ( = !\ #2 W@ %8 7( "P 7* _____/____\
+M !@ '0 ? Z@ /@ !K &U T &U@ /__
+M__3_____ @ !T 'P 0, $; > "#@ / "
+M#@ _____P = !\ $I !, )4
+M 0 /____\ '0 ? #@ \
+M $ #_____ !T 'P
+M !$ > & (#_ #____<_____P
+M6 = !\ !D Q0 ,8 " ,< /____\
+M '0 ? S -L !. #6 H #7@ $ /___^3_
+M____ X !T 'P .8 $! 5 !
+M _____P = !\ . $@
+M 0 /____\ '0 ? #@ !(
+M $ #_____ !T 'P !\
+M C P # P _____P =
+M !\ J , $ 0 " ____S/____\
+M % '0 ? '@ "@ $ #_____
+M !T 'P !< ? # $ "P
+M _____P = !\ E +P @ 0
+M /____\ '0 ? #@ !(
+M 0 L( + # (K___ %0! < 8( " %0 &@@( "
+M '0! B@8( & '0 @@( $ *0! C 8( * *0 P@
+M( & ,0! CP8( . ,0 @@( ( 0 @( 0
+M L( " 0 @( 0 L( " 0 @(
+M 0 L( " 0 @( 0 L( "* 0@ !AI8 )
+M 2P E8 ( 60 ! E8 # : " E8 $ =0 $ E
+M8 % @P & E8 & D@ ( E8 ' A8 ! H@
+M !AI8 1 IP E8 ( M0 ! E8 # Q " E8 $
+MT0 $ E8 % WP & E8 & [@ ( E8 ' A8 )
+M _@ AM8 9 !!@ E8 ( !% E8 # !(P E
+M8 $ !, E8 % !/@ E8 & !30 E8 '
+M A8 1 !70 AM8 A !8@ E8 ( !< E8 # !
+M?P E8 $ !C E8 % !F@ E8 & !J0 E8 '
+M A8 9 !N0! E 8( "' <( D @@
+M( B !N0 !@@( A !Q0! F@8( ") <( H
+M @@( F !Q0 !@@( E !V ! H 8( "+ <( L
+M @@( J !V !@@( I ![0! I@8( "- <( P
+M @@( N ![0 !@@( M !^@! K 8( "/ <
+M( T @@( R !^@ !@@( Q "#@! L@8( "1
+M <( X @@( V "#@ !@@( U ") ! N 8( "3
+M <( \ @@( Z ") !@@( Y "+P! O@8( "5
+M <( ! @@( ^ "+P !@@( ] "00! Q 8
+M( "7 <( !$ @@( !" "00 !@@( !! "50!
+M R@8( "9 <( !( @@( !& "50 !@@( !% "
+M80! T 8( "; <( !, @@( !* "80 !@@( !)
+M "= ! U@8( "= <( !0 @@( !. "= !@@
+M( !- "B0! W 8( "? <( !4 P@( !2 "B0
+M !P@( !1 "E@! XP8( "A <( !8 ! @( !6 "
+ME@ " @( !5 "I )AI8 !> "J0 E8 "F "K@ " E8 "I
+M "MP $ E8 "L A8 !9 "O0 )!M8 !C "Q0 E
+M8 #$ "R@ E8 #' "TP E8 #* A8 !> "V0
+M 1Q8 !H "W@ E8 #B "X@ $E8 #C "Z (E8 #D
+M A8 !C "[0 1Q8 !M "] E8 #K "^P $E8 #L
+M # @ (E8 #M A8 !H #!P 1Q8 !Q ## E
+M8 #T #$@ $E8 #U A8 !M #%P 1Q8 !U #'
+M E8 #\ #( $E8 #] A8 !Q #* 1Q8 !Y #
+M+0 E8 $$ #,P $E8 $% A8 !U #. I8 $&
+M #0 1Q8 !^ #1@ E8 $, #3 $E8 $- A
+M8 !Z #40 I8 $. #6@ 1Q8 "% #90 (E8 $4 #:0
+M $E8 $5 #;0 E8 $6 #<@ ,E8 $7 A8 !_ #
+M> ! ZP8( $8 <( "( = @( "& #> > @( "%
+M 0 @( 0 L( $ % ! !9 8( - % @@
+M( ! 0 @( 0 L( % "1 "L )K___ % !
+M!: 8( - % .P@( " 0 @( 0 L( $
+M#@! !I 8( - #@ #0@( ! 0 @( 0 L( &
+M "@! !M 8( - "@ (P@( ! $0! !UPX( / $0 '0@
+M( # 0 @( 0 L( ) #@! !] 8( " %0!
+M"!@4+___ (@! "& 4+___ *0! "&@4+___ , ! "&P4+___
+M-P! "' 4+___ #@ *@@( ! 0 @( 0 L( %
+M #0! "( 8( " $P! ")@4+___ #0 " @( ! 0 @
+M( 0 L( " 0 @( 0 L( " 0
+M @( 0 L( % #0! "* 8( " $P! "+@4+___
+M#0 " @( ! 0 @( 0 L( 9 #0! ", 8( "
+M % ! "/ 4+___ 'P! "0P4+___ ,0! "1@4+___ /P! "2P4
+M+___ 0P! "304+___ 40! "604+___ 7 ! "7P4+___ 9P!
+M"9@4+___ < ! "9@4+___ ? ! "?04+___ B ! "C 4+___
+MDP! "E04+___ GP! "G04+___ L@! "H@4+___ P ! "J04+___
+M S@! "M04+___ V0! "NP4+___ Y ! "P@4+___ [@! "P@4
+M+___ ^P! "V04+___ !" ! "Z 4+___ #0 P0@( ! 0
+M @( 0 L( % #@! "] 8( " %0! "^@4+___
+M#@ " @( ! 0 @( 0 L( ( "A "N )K___
+M $Q B (3___ '@! "_ 8( - '@ $@@( # )0! ##@8
+M( / )0 &@@( % 0 @( 0 L( 2 "@!
+M#* 8( - "@ '@@( ! $P! #1@8( / $P , @( #
+M&@! #=@8( 1 &@ 4@@( % (0! #R 8( 3 (0 C @( '
+M *0! $5 8( 5 *0 1@@( ) ,@! $F@8( 7 ,@ 0P@
+M( + .@! $W08( 9 .@ 60@( - 0P! %-@8( ; 0P
+M % @( / 0 @( 0 L( $ # ! %3 8( "
+M# ! @( ! 0 @( 0 L( $ #@! %4 8( "
+M #@ ! @( ! 0 @( 0 L( " 0 @
+M( 0 L( " 0 @( 0 L( - "A
+M"_ )S___ $1 "_@)S___ &! "_P)S___ 'Q # )S___
+M)A # 0)S___ +P! %5 8( - +P Q@@( & -@! &&@8( /
+M -@ $ @( ( .P! &*@8( 1 .P 1 @( * 0 @
+M( 0 L( % #@! &< 8( " %0! &=@4+___ #@
+M " @( ! 0 @( 0 L( % #@! &> 8( "
+M%0! &?@4+___ #@ " @( ! 0 @( 0 L( &
+M # ! &@ 8( - # P@( ! %0! &@P8( / %0 P@
+M( # 0 @( 0 L( $ "P! &B 8( - "P
+M %0@( ! 0 @( 0 L( ( #0! &H 8( "
+M#0 "@@( ! $P! &J@4+___ %P! &K 8( & ' ! &LP4+___
+M %P #@@( $ 0 @( 0 L( % #@! &O 8
+M( " %0! &P@4+___ #@ " @( ! 0 @( 0
+M L( " 0 @( _____P $ /____\
+M!@ #_____ @ _____P * &
+M @ 0 & " H + P 4 ' "0 !H #
+M # __ ! 0 @# # __ ! 0
+M @# # __ ! 0 @$ # __ !
+M 0 ! $ # __ ! 0 ! % # __ !
+M 0 ! & # __ ! 0 " & # __ !
+M 0 " ' # __ ! 0 " ( # __ !
+M 0 " ( # __ ! 0 " ) # __
+M! 0 " * # __ ! 0 " + #
+M__ ! 0 $ # ! P 0 , $ $ ! ! 0 4 $ &
+M ! !@ 0 < $ ( ! " 0 D $ * ! "P 0 P #__________PP
+M #_\ ! P #__________PP #_\ ) T #_________
+M_PT #_\ 1 T #__________PT #_\ 9 "4#
+M *0, M P #$$ -00 Y!0 #T&
+M 008 !%!P $D( 30@ !1"0
+M %4* 60L , __________\, ! __ 60 , !(0__
+M60 , #,P__ 0 #_\ $ " P/_P 0
+M $ ) __ ! !( , ! __ 60 -
+M __________\, ! __ 60 , !(0__ 60 , #,P__ 0
+M #_\ $ " P/_P 0 $ ) __
+M! !( - __ 7@ . __________\
+M . __ 8P . __________\ .
+M __ : . __________\ X #_\ !M X
+M #__________P #@ /_P '$ #@ /__________
+M . __ =0 . __________\ X #_\ !Z
+M X #__________P ")!@ &
+M @ 0 & " H + P 4 ' "0 !H
+M #!@ & @ 0 & " H + P
+M 4 ' "0 !H $!@ & @ 0 &
+M" H + P 4 ' "0 !H #!@ &
+M @ 0 & " H + P 4 ' "0 !H
+M # P 0 4# ! _____P ( /____\
+M! #_____ 0 _____P 8 /____\
+M ! !@ ( $ !@ @ * "P , %
+M !P D : !08 '&@ & @ 0
+M & " H + P 4 ' "0 !H #&@
+M 4& !P8 )!@ L& #08 /
+M!@ !$& _____P # /____\ P
+M !@ ( $ !@ @ * "P , % !P D
+M : 8 " ! 8 ( "@ L # !0
+M < ) &@ & @ 0 & " H +
+M P 4 ' "0 !H (&@ 0 H: #!H $ #_
+M____ 0 _____P $ & @ 0
+M & " H + P 4 ' "0 !H #!@
+M 4& 8 " ! 8 ( "@ L #
+M!0 < ) &@ ,& _____P # /____\
+M !P #_____ 0 &-R=#%T97AT+G, 4U1!4E1&
+M4DT 7U]S=&%R= !?;6]N8V]N=')O; !?;6-O=6YT %]S<')O8VUO;G-T87)T
+M O8F%B82]C>7!R97-S+W5S<B]I;F-L=61E+W)E9V1E9BYH O8F%B82]C
+M>7!R97-S+W5S<B]I;F-L=61E+V%S;2YH !C<G0Q=&EN:70N<P 9V1B;64N
+M8P \+S1$96)U9R\^ '!U<&EL.B]C>6=I;G0O<&QA>2]F;F8O9V1B;64N8P W
+M,#(S-#@S-CD -3,X-@!T7W-T<G5C= !V7V-H87)?;65M8F5R '9?<VAO<G1?
+M;65M8F5R '9?:6YT7VUE;6)E<@!V7VQO;F=?;65M8F5R '9?9FQO871?;65M
+M8F5R '9?9&]U8FQE7VUE;6)E<@ N1C$Q '9?8VAA<E]M96UB97( =E]S:&]R
+M=%]M96UB97( =E]I;G1?;65M8F5R '9?;&]N9U]M96UB97( =E]F;&]A=%]M
+M96UB97( =E]D;W5B;&5?;65M8F5R '1?=6YI;VX =E]C:&%R7VUE;6)E<@!V
+M7W-H;W)T7VUE;6)E<@!V7VEN=%]M96UB97( =E]L;VYG7VUE;6)E<@!V7V9L
+M;V%T7VUE;6)E<@!V7V1O=6)L95]M96UB97( +D8Q,P!V7V-H87)?;65M8F5R
+M '9?<VAO<G1?;65M8F5R '9?:6YT7VUE;6)E<@!V7VQO;F=?;65M8F5R '9?
+M9FQO871?;65M8F5R '9?9&]U8FQE7VUE;6)E<@!V7V-H87)?9G5N8P!V7W-I
+M9VYE9%]C:&%R7V9U;F, =E]U;G-I9VYE9%]C:&%R7V9U;F, =E]S:&]R=%]F
+M=6YC '9?<VEG;F5D7W-H;W)T7V9U;F, =E]U;G-I9VYE9%]S:&]R=%]F=6YC
+M '9?:6YT7V9U;F, =E]S:6=N961?:6YT7V9U;F, =E]U;G-I9VYE9%]I;G1?
+M9G5N8P!V7VQO;F=?9G5N8P!V7W-I9VYE9%]L;VYG7V9U;F, =E]U;G-I9VYE
+M9%]L;VYG7V9U;F, =E]F;&]A=%]F=6YC '9?9&]U8FQE7V9U;F, ;&EN:P!N
+M97AT &QI;FMF=6YC '-T=69F '1U7VQI;FL ;F5X= !L:6YK9G5N8P!S='5F
+M9@ N1C(Y ')E9 !G<F5E;@!B;'5E &-O;&]R<P!Y96QL;W< <'5R<&QE '!I
+M;FL +D8S,0!C:&5V>0!F;W)D &-A<G, 8FUW '!O<G-C:&4 +D8S,P!&04Q3
+M10!44E5% &)O;VQE86X 8G9A;', 9F%L<V4 =')U90!B;V]L96%N,@!M:7-O
+M<F1E<F5D '1W;P!O;F4 >F5R;P!T:')E90!M86EN !G96XO<W1U8F9P97-T
+M87)T+F, 7U]R96%D96YV7W-I9V9P90 8W1Y<&4N8P!F:7)S=%]C86QL %]S
+M971C:')C;&%S<P 9V5N+V-U97AI="YC &5X:70 &=E=&5N=BYC &=E=&5N
+M=@!N=FUA=&-H !G96XO<W1R8W!Y+G, <W1R8W!Y #$D,# P,# P,# P, D
+M9&]C:#, )&1O8V@R "1D;V-H,0 D9&]C:# '-Y<R]?;W!E;BYS %]O<&5N
+M #DD,# P,# P,# P, +V)A8F$O8WEP<F5S<R]U<W(O:6YC;'5D92]S>7,N
+M<P +V)A8F$O8WEP<F5S<R]U<W(O:6YC;'5D92]S>7,O<WES8V%L;"YH !S
+M>7,O7W)E860N<P!?<F5A9 Y)# P,# P,# P,# &=E;B]B8V]P>2YS &UE
+M;6-P>0!G;V9O<G=A<F1S &9O<G=A<F1S7V)Y=&5C;W!Y #DY)# P,# P,# P
+M,# <F5T &9O<G=A;&EG;F%B;&4 9F]R=U]C;W!Y,@!F;W)W7V-O<'DS &9O
+M<G=A<F1S &9O<G=A<F1S7S,R &9O<G=A<F1S7S$V &9O<G=A<F1S7S0 9V]B
+M86-K=V%R9', 8F%C:W=A<F1S7V)Y=&5C;W!Y #DY)# P,# P,# P,#$ 8F%C
+M:V%L:6=N86)L90!B86-K7V-O<'DR &)A8VM?8V]P>3, 8F%C:W=A<F1S &)A
+M8VMW87)D<U\S,@!B86-K=V%R9'-?,38 8F%C:W=A<F1S7S0 '-Y<R]?8VQO
+M<V4N<P!?8VQO<V4 .20P,# P,# P,# P !A=&5X:70N8P!?7VYE>'1F;@!?
+M7V5X:71?9FYS &%T97AI= !?7V-A;&Q?97AI=&9N<P 9FQS8G5F+F, 7V-L
+M96%N=7 9F-L;W-E &9F;'5S: !?9FQS8G5F %]X9FQS8G5F %]W<G1C:&L
+M7V9I;F1B=68 7V)U9G-Y;F, '-Y<R]E>&ET+G, 7V5X:70 &-R="]C97)R
+M;W(N<P!?8V5R<F]R !D871A+F, &UP7V1E9BYC !M86QL;V,N8P!A;&QO
+M8W, 86QL;V-P &%L;&]C= !A;&QO8W@ 86QL;V-E;F0 ;6%L;&]C &9R964
+M<F5A;&QO8P <WES+U]L<V5E:RYS %]L<V5E:P Y)# P,# P,# P,# '-Y
+M<R]?=W)I=&4N<P!?=W)I=&4 .20P,# P,# P,# P !?;W-E<G)O<BYC %]O
+M<V5R<F]R %]S971O<V5R<F]R !?:7-A='1Y+F, 7VES871T>0 <WES+U]S
+M8G)K+G, 7W-B<FL 97)R %]B<FL ,20P,# P,# P,# P !S>7,O7VEO8W1L
+M+G, 7VEO8W1L #DD,# P,# P,# P, 8W)T;FEN:70N<P 7V5N=FER;VX
+M96YV:7)O;@!?7T%R9V, 7U]!<F=V &5R<FYO %]?<W1A<G0 7V=P %]?:7-T
+M87)T %]?<F5A9&5N=E]S:6=F<&4 7W-E=&-H<F-L87-S &UA:6X 97AI= !?
+M;6]N8V]N=')O; !?;6-O=6YT %]S<')O8VUO;G-T87)T '9?8VAA<@!V7W-I
+M9VYE9%]C:&%R '9?=6YS:6=N961?8VAA<@!V7W-H;W)T '9?<VEG;F5D7W-H
+M;W)T '9?=6YS:6=N961?<VAO<G0 =E]I;G0 =E]S:6=N961?:6YT '9?=6YS
+M:6=N961?:6YT '9?;&]N9P!V7W-I9VYE9%]L;VYG '9?=6YS:6=N961?;&]N
+M9P!V7V9L;V%T '9?9&]U8FQE '9?8VAA<E]A<G)A>0!V7W-I9VYE9%]C:&%R
+M7V%R<F%Y '9?=6YS:6=N961?8VAA<E]A<G)A>0!V7W-H;W)T7V%R<F%Y '9?
+M<VEG;F5D7W-H;W)T7V%R<F%Y '9?=6YS:6=N961?<VAO<G1?87)R87D =E]I
+M;G1?87)R87D =E]S:6=N961?:6YT7V%R<F%Y '9?=6YS:6=N961?:6YT7V%R
+M<F%Y '9?;&]N9U]A<G)A>0!V7W-I9VYE9%]L;VYG7V%R<F%Y '9?=6YS:6=N
+M961?;&]N9U]A<G)A>0!V7V9L;V%T7V%R<F%Y '9?9&]U8FQE7V%R<F%Y '9?
+M8VAA<E]P;VEN=&5R '9?<VEG;F5D7V-H87)?<&]I;G1E<@!V7W5N<VEG;F5D
+M7V-H87)?<&]I;G1E<@!V7W-H;W)T7W!O:6YT97( =E]S:6=N961?<VAO<G1?
+M<&]I;G1E<@!V7W5N<VEG;F5D7W-H;W)T7W!O:6YT97( =E]I;G1?<&]I;G1E
+M<@!V7W-I9VYE9%]I;G1?<&]I;G1E<@!V7W5N<VEG;F5D7VEN=%]P;VEN=&5R
+M '9?;&]N9U]P;VEN=&5R '9?<VEG;F5D7VQO;F=?<&]I;G1E<@!V7W5N<VEG
+M;F5D7VQO;F=?<&]I;G1E<@!V7V9L;V%T7W!O:6YT97( =E]D;W5B;&5?<&]I
+M;G1E<@!V7W-T<G5C=#$ =E]S=')U8W0R '9?=6YI;VX =E]U;FEO;C( =E]C
+M:&%R7V9U;F, =E]S:6=N961?8VAA<E]F=6YC '9?=6YS:6=N961?8VAA<E]F
+M=6YC '9?<VAO<G1?9G5N8P!V7W-I9VYE9%]S:&]R=%]F=6YC '9?=6YS:6=N
+M961?<VAO<G1?9G5N8P!V7VEN=%]F=6YC '9?<VEG;F5D7VEN=%]F=6YC '9?
+M=6YS:6=N961?:6YT7V9U;F, =E]L;VYG7V9U;F, =E]S:6=N961?;&]N9U]F
+M=6YC '9?=6YS:6=N961?;&]N9U]F=6YC '9?9FQO871?9G5N8P!V7V1O=6)L
+M95]F=6YC '-?;&EN:P!U7VQI;FL <')I;6%R>0!N;VYP<FEM87)Y &-L=6YK
+M97( <W!O<G1S8V%R %]C='EP90!G971E;G8 <W1R8W!Y %]O<&5N %]R96%D
+M &UE;6-P>0!?8VQO<V4 7U]T<F%P7V9P95]O=F5R<FED90!?7V-A;&Q?97AI
+M=&9N<P!?8VQE86YU< !?97AI= !?8V5R<F]R &%T97AI= !?8G5F96YD=&%B
+M %]I;V( 7W-P<F]C960 7VQA<W1B=68 7W-I8G5F %]S;V)U9@!?<VUB=68
+M9F9L=7-H &9C;&]S90!F<F5E %]L<V5E:P!?>&9L<V)U9@!?9FQS8G5F %]W
+M<FET90!?=W)T8VAK %]B=69S>6YC %]S971O<V5R<F]R %]F:6YD8G5F &UA
+M;&QO8P!?:7-A='1Y %]L;V-K %]U;&]C:P!?;FQO8VL 7VEL;V-K %]F;&]C
+M:P!?=VQO8VL 7V-L;V-K %]T;&]C:P!?8W1L;V-K %]D;&]C:P!?8V%S %]U
+M<U]R<W1H<F5A9%]S=&1I;P!?<V)R:P!?8G)K ')E86QL;V, 7V]S97)R;W(
+M7VEO8W1L &5N9 !?;6EN8G)K %]C=7)B<FL 7V5N9 $ !P $
+M 0 + "$ 0 $
+M %&8 ? $ !P $ ! ) L "
+M $ 0 4 %'8 $ !
+MP $ !D (0 T " $ 0
+M H %'8 $ !P $ "% #0 \
+M " \ !'8
+M $ "4 $ "2 #?0 !$ "* (0 ,\
+M $ \ 0 !&@ ! ! 0 !\ _ $ %D $ 0/
+M )0 )L $ \ ( 3 $ $J #P !$
+M ! 8 %X ! $ %H $ 0T (0 )\ % \@
+M #L 4 $ $Y #P !( ! 8 %\ 7 $ &
+MD $ 15 $P *0 $ !+0 T 5 $ %(
+M #P !, ! 8 '8 , $ &T $ 1H &0 *@
+M & !.@ $ 6 ( %7 $0 !0 ! 8
+M (( 0 $ 'T $ 2! /@ *X ) !>@ "H
+M 8 $ %H ! !4 %&8 )( J $ (@ $ 2_
+M ( +< % !I @ 9 $ %L ! !H
+M %&8 +P % $ (@ $ 3? (0 +P "
+M ! $ !\ %'8 $ (
+M@ $ 4 *0 +X " ! $
+M "0 %'8 $ (H $ 4I ( ,
+M % !K @ : $ %P ! "D %&8
+M ,$ % $ (P $ 5) !% ,4 9 !M ,8
+M ; $ %T ! "X %&8 ,8 "T $ +T $ 9=
+M (@ -X % ">@ @ < $ %X ! #,
+M %&8 7H % $ +\ $ 9_ - ., ( "@@
+M "P = ( %\ $0 #@ ! 8 7\ ( $ ,
+MH $ :S 3 .L 2 "K@ B( ? @ &-
+M '0 #D ! 8 8< "; $ 5, $ ;_ $@ /T
+M $ $T 0 G $ &J ! #H %&8
+M B( " $ 50 $ <1 %@ 0$ $ $U 0
+M H $ &N ! #\ #&8 B0 # $ 54 $ <G
+M " 04 " &R #0 $(
+M ! 8 $ 54 $ <O "@ 0< "
+M &_ #0 $, ! 8 $ 5
+M4 $ <Y 0P 0D - $V 1L I , ',
+M $P $0 ! 8 B< !N $ 9P $ =\ (@ 18
+M % %\P @ L $ '? ! $4 %&8
+M I4 % $ 9X $ >> (@ 1L % %^P @
+M M $ 'C ! $H %&8 IH % $ : $ ?
+M (0 2 & & P 8 N ( 'G $0 $\
+M ! 8 I\ # $ :( $ ?A $P 28 $ &"0
+M !4 P $ 'X #P % ! 8 J( ) $ :
+M@ $ ?T *0 2H ( &'@ !H Q ( ('
+M " %$ %&8 JL 0 $ :\ $ @= (@ 3(
+M % &. @ S $ (/ ! %8 %&8
+M KL %$$ ;$ $ @_ # 3< "
+M %L !'8 $ !
+M @ ( 0 $ " @ ! 0 (
+M " P 0 % !@ < ( "0 ( " 0
+M $ * 0 ( + # H ! @ L ,
+M"@ $ " "P P - 0 ( + # X "
+M @ $ ! #P $ " "P P 0 $0 !(
+M ! @ L , $P $ " % !4 6 %P
+M $ " "P P 8 0 ( + # !D :
+M&P $ " "P P < 0 ( + # !T
+M ! "K %K___ D0 JP!:___P 1$ ,$ 7/__\
+M &! #!0%S___ !\0 P8!<___P E $ !P!@@
+M ( +1 BH 4K___ P #$ 0!L<%L___P 4 Z $ %
+MD!@@ $ & 2P! !: 8( " ! %@ 0 .L&" A0 < !=
+M $ &D!@@ $ 8@! B@8( $ &X 0 (P&" !@
+M !V $ "/!@@ @ $ A1 "Q %P ( ! (P0 L1!< "
+M 0 ":$ +$@7 @ $ JA "Q0%P # ! +(0 L6!<
+M P 0 #!$ +& 7 D $ TA "QP%P $ ! -@0 L@
+M!< ! 0 #E$ +) 7 H $ ]! "R@%P % ! /L0
+M LL!< !0 0 $)$ +, 7 L $ !&1 "S0%P & !
+M 2$0 LX!< !P 0 $J$ +0 7 T $ !-Q "T(%P 3
+M! 4L0 M$!< &0 0 %A$ +2 7 !\ $ !;Q "TP%P E
+M ! 800 M0!< *P 0 &;$ +6 7 #$ $ !IQ "V %
+MP W ! ;H0 MH!< /0 0 '/$ +< 7 $, $ !W!
+M"W@%P !) ! ? 0 N !< 3P 0 (&$ +B 7 %4 $ "
+M%! 8_ $8 !; ! B,0 N0!< 80 0 (R$ +E 7 &( $
+M "2! "Y@%P !C ! F 0 N<!< 9 0 )P$ +H 7 &4
+M $ "AQ "Z0%P !F ! J 0 NH!< 9P 0 *N$ +K 7
+M &@ $ "PQ "[ %P !I ! MH0 NT!< :@ 0 +I$ +
+MN 7 &L $ "_Q "[P%P !L ! Q<0 O !< ;0 0 ,G
+M$ +Q 7 &X $ #.! 8\ $8 !R ! T(0 &/8!& > 0
+M -,$ +R 7 'X $ #5! "] %P "$ ! UT 0 )0&" (0
+M 0 -I $ ":!@@ "4 $ #? ! H 8( I ! Y$ 0 *8&"
+M+0 0 .> $ "L!@@ #$ $ #L@! L@8( U ! \@ 0 +@
+M&" .0 0 /3 $ "^!@@ #T $ #Y0! Q 8( !! ! _D
+M0 ,H&" 10 0 0% $ #0!@@ $D $ $& ! U@8( !- !
+M!"T 0 -P&" 40 0 0Z $ #C!@@ %4 $ $2! "]@%P "^
+M! !$\0 &,P!& W 0 16$ +W 7 .4 $ $7A "^ %P #N
+M ! !&D0 OD!< ]@ 0 1Q$ +Z 7 /X & $>Q $
+M3___ " !(( 0 ;0&" 0 D 2) $ 'T!@@ $ * $D !
+M"( 8( ! #0 !)8 0 B@&" 0 X 2< $ (P!@@ $ / $
+MHP! "] 8( ! !P !*H0 K0!:___P ! 2^ $ ,.!@@ 4 1
+M $S0! #* 8( ! $@ !-8 0!4P&" 0 !, 3< $ 50!@@ $
+M 0 $Y ! "_ 8( # % !.L0 *@!$___P !0 3V$ $- 1/
+M__\ 5 $^Q "P %K___ % !000 KP!:___P !0 4-$ 0
+M 1O__\ 4 %%! 0 $;___ % !1L0 & (!&___P !$ 4B
+M $ -V!@@ 4 1 %*0! #1@8( # %@ !3 0!AH&" " !<
+M 4U $ 9P!@@ $ 1 %/ ! $5 8( ) $0 !44 0 \@&" !P
+M !@ 5- $ 9X!@@ $ 1 %5 ! $F@8( + $0 !5P 0!38&"
+M#P !D 5E $ :#!@@ , 1 %<0! $W08( - %@ !7H 0!50
+M&" !@ !H 6! $ :(!@@ $ 5 %B1 #!P%S___ %0 !8\0
+M P@!<___P !4 66$ ,) 7/__\ 5 %G1 #"@%S___ %0
+M!:00 PL!<___P !4 6K$ ,, 7/__\ 5 %LA ##0%S___
+M%0 !;D0 PX!<___P !4 7 $ ,/ 7/__\ 5 %R! #$ %S___
+M %0 !<\0 Q$!<___P !4 74$ +! 6O__\ ; %YP! &H 8
+M( ! &P !>T 0!JP&" ! !8 7R $ 8J!@@ H 9 %^@!
+M&@ 8( ! ' !@, 0!KP&" 0 !L 8*$ "G0!1O__\ ; &
+I#A "H $3___ &P !A80 J$!$___P __\ 8>$ "G0!1O__\;
+
+end
diff --git a/gdb/testsuite/gdb.base/mips_pro.c b/gdb/testsuite/gdb.base/mips_pro.c
new file mode 100644
index 00000000000..d2d1884b9cd
--- /dev/null
+++ b/gdb/testsuite/gdb.base/mips_pro.c
@@ -0,0 +1,35 @@
+/* Tests regarding examination of prologues. */
+
+int
+inner (z)
+ int z;
+{
+ return 2 * z;
+}
+
+int
+middle (x)
+ int x;
+{
+ if (x == 0)
+ return inner (5);
+ else
+ return inner (6);
+}
+
+int
+top (y)
+ int y;
+{
+ return middle (y + 1);
+}
+
+int
+main (argc, argv)
+{
+#ifdef usestubs
+ set_debug_traps();
+ breakpoint();
+#endif
+ return top (-1) + top (1);
+}
diff --git a/gdb/testsuite/gdb.base/mips_pro.exp b/gdb/testsuite/gdb.base/mips_pro.exp
new file mode 100644
index 00000000000..ea2461e5f04
--- /dev/null
+++ b/gdb/testsuite/gdb.base/mips_pro.exp
@@ -0,0 +1,62 @@
+# Copyright (C) 1997 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+set prms_id 0
+set bug_id 0
+
+set testfile mips_pro
+set srcfile ${srcdir}/$subdir/${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+
+# Create and source the file that provides information about the compiler
+# used to compile the test case.
+if [get_compiler_info ${binfile}] {
+ return -1;
+}
+
+
+# This test must be compiled with -O2 if using gcc.
+
+if {$gcc_compiled} then {
+ if { [gdb_compile "${srcfile}" "${binfile}" executable {debug additional_flags=-O2}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+ }
+} else {
+ if { [gdb_compile "${srcfile}" "${binfile}" executable {debug}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+ }
+}
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+if [runto middle] then {
+ # PR 3016
+ if {$gcc_compiled} then {
+ setup_xfail "hppa*-*-*" "mips*-sgi-irix4*" "mips64*-*-elf"
+ }
+ gdb_test "backtrace" "#0.*middle.*#1.*top.*#2.*main.*"
+}
+return 0
diff --git a/gdb/testsuite/gdb.base/miscexprs.c b/gdb/testsuite/gdb.base/miscexprs.c
new file mode 100644
index 00000000000..cae23d8cf33
--- /dev/null
+++ b/gdb/testsuite/gdb.base/miscexprs.c
@@ -0,0 +1,165 @@
+void marker1 ()
+{
+
+}
+/*
+static struct {
+ char c[100];
+} cbig;
+
+
+static struct {
+ int i[800];
+} ibig;
+
+
+static struct {
+ long l[900];
+} lbig;
+
+static struct {
+ float f[200];
+} fbig;
+
+static struct {
+ double d[300];
+} dbig;
+
+static struct {
+ short s[400];
+} sbig;*/
+
+/*struct {
+ long l[900];
+} lbig;*/
+
+int main()
+{
+
+struct {
+ char c[100];
+} cbig;
+
+
+struct {
+ int i[800];
+} ibig;
+
+
+struct {
+ long l[900];
+} lbig;
+
+struct {
+ float f[200];
+} fbig;
+
+struct {
+ double d[300];
+} dbig;
+
+struct {
+ short s[400];
+} sbig;
+ ibig.i[100] = 5;
+ cbig.c[100] = 'A';
+ fbig.f[100] = 11.99999;
+ dbig.d[202] = 9.99999999;
+ sbig.s[90] = 255;
+ lbig.l[333] = 999999999;
+
+ #ifdef usestubs
+ set_debug_traps();
+ breakpoint();
+ #endif
+ marker1();
+ return 0;
+
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/gdb/testsuite/gdb.base/miscexprs.exp b/gdb/testsuite/gdb.base/miscexprs.exp
new file mode 100644
index 00000000000..9ea278a570f
--- /dev/null
+++ b/gdb/testsuite/gdb.base/miscexprs.exp
@@ -0,0 +1,283 @@
+# Copyright (C) 1998 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+
+# This file is part of the gdb testsuite
+# file written by Elena Zannoni (ezannoni@cygnus.com)
+
+#
+# tests for expressions with struct/array elements and mixed operator types
+# with elementary types
+#
+
+if $tracelevel then {
+ strace $tracelevel
+ }
+
+#
+# test running programs
+#
+set prms_id 0
+set bug_id 0
+
+set testfile "miscexprs"
+set srcfile ${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug additional_flags=-w}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+
+#
+# set it up at a breakpoint so we can play with the variable values
+#
+if ![runto_main] then {
+ perror "couldn't run to breakpoint"
+ continue
+}
+
+send_gdb "break marker1\n" ; gdb_expect -re ".*$gdb_prompt $"
+
+ send_gdb "cont\n"
+ gdb_expect {
+ -re "Break.* marker1 \\(\\) at .*:$decimal.*$gdb_prompt $" {
+ send_gdb "up\n"
+ gdb_expect {
+ -re ".*$gdb_prompt $" {}
+ timeout { fail "up from marker1" }
+ }
+ }
+ -re "$gdb_prompt $" { fail "continue to marker1" }
+ timeout { fail "(timeout) continue to marker1" }
+ }
+
+global hex
+
+send_gdb "print &ibig.i\[0\]\n"
+gdb_expect {
+ -re ".\[0-9\]* = \\(int \\*\\) $hex.*$gdb_prompt $" {
+ pass "print value of &ibig.i\[0\]"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of &ibig.i\[0\]" }
+ timeout { fail "(timeout) print value of &ibig.i\[0\]" }
+ }
+
+send_gdb "print &cbig.c\[0\]\n"
+gdb_expect {
+ -re ".\[0-9\]* = $hex \"\".*$gdb_prompt $" {
+ pass "print value of &cbig.c\[0\]"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of &cbig.c\[0\]" }
+ timeout { fail "(timeout) print value of &cbig.c\[0\]" }
+ }
+
+send_gdb "print &fbig.f\[0\]\n"
+gdb_expect {
+ -re ".\[0-9\]* = \\(float \\*\\) $hex.*$gdb_prompt $" {
+ pass "print value of &fbig.f\[0\]"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of &fbig.f\[0\]" }
+ timeout { fail "(timeout) print value of &fbig.f\[0\]" }
+ }
+
+send_gdb "print &dbig.d\[0\]\n"
+gdb_expect {
+ -re ".\[0-9\]* = \\(double \\*\\) $hex.*$gdb_prompt $" {
+ pass "print value of &dbig.d\[0\]"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of &dbig.d\[0\]" }
+ timeout { fail "(timeout) print value of &dbig.d\[0\]" }
+ }
+
+send_gdb "print &sbig.s\[0\]\n"
+gdb_expect {
+ -re ".\[0-9\]* = \\(short int \\*\\) $hex.*$gdb_prompt $" {
+ pass "print value of &sbig.s\[0\]"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of &sbig.s\[0\]" }
+ timeout { fail "(timeout) print value of &sbig.s\[0\]" }
+ }
+
+send_gdb "print &lbig.l\[0\]\n"
+gdb_expect {
+ -re ".\[0-9\]* = \\(long int \\*\\) $hex.*$gdb_prompt $" {
+ pass "print value of &lbig.l\[0\]"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of &lbig.l\[0\]" }
+ timeout { fail "(timeout) print value of &lbig.l\[0\]" }
+ }
+
+
+send_gdb "print ibig.i\[100\] | 1\n"
+gdb_expect {
+ -re ".\[0-9\]* = 5.*$gdb_prompt $" {
+ pass "print value of ibig.i\[100\] | 1"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of ibig.i\[100\] | 1" }
+ timeout { fail "(timeout) print value of ibig.i\[100\] | 1" }
+ }
+
+
+send_gdb "print sbig.s\[90\] & 127\n"
+gdb_expect {
+ -re ".\[0-9\]* = 127.*$gdb_prompt $" {
+ pass "print value of sbig.s\[90\] & 127"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of sbig.s\[90\] & 127" }
+ timeout { fail "(timeout) print value of sbig.s\[90\] & 127" }
+ }
+
+send_gdb "print !ibig.i\[100\]\n"
+gdb_expect {
+ -re ".\[0-9\]* = 0.*$gdb_prompt $" {
+ pass "print value of !ibig.i\[100\]"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of !ibig.i\[100\]" }
+ timeout { fail "(timeout) print value of !ibig.i\[100\]" }
+ }
+
+send_gdb "print !sbig.s\[90\]\n"
+gdb_expect {
+ -re ".\[0-9\]* = 0.*$gdb_prompt $" {
+ pass "print value of !sbig.s\[90\]"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of !sbig.s\[90\]" }
+ timeout { fail "(timeout) print value of !sbig.s\[90\]" }
+ }
+
+
+send_gdb "print !fbig.f\[100\]\n"
+gdb_expect {
+ -re ".\[0-9\]* = 0.*$gdb_prompt $" {
+ pass "print value of !ibig.i\[100\]"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of !ibig.i\[100\]" }
+ timeout { fail "(timeout) print value of !ibig.i\[100\]" }
+ }
+
+send_gdb "print !dbig.d\[202\]\n"
+gdb_expect {
+ -re ".\[0-9\]* = 0.*$gdb_prompt $" {
+ pass "print value of !ibig.i\[100\]"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of !ibig.i\[100\]" }
+ timeout { fail "(timeout) print value of !ibig.i\[100\]" }
+ }
+
+
+
+send_gdb "print sbig.s\[90\] * 10\n"
+gdb_expect {
+ -re ".\[0-9\]* = 2550.*$gdb_prompt $" {
+ pass "print value of !sbig.s\[90\] * 10"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of !sbig.s\[90\] * 10" }
+ timeout { fail "(timeout) print value of !sbig.s\[90\] * 10" }
+ }
+
+send_gdb "print ibig.i\[100\] * sbig.s\[90\]\n"
+gdb_expect {
+ -re ".\[0-9\]* = 1275.*$gdb_prompt $" {
+ pass "print value of ibig.i\[100\] * sbig.s\[90\]"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of ibig.i\[100\] * sbig.s\[90\]" }
+ timeout { fail "(timeout) print value of ibig.i\[100\] * sbig.s\[90\]" }
+ }
+
+send_gdb "print fbig.f\[100\] * dbig.d\[202\]\n"
+gdb_expect {
+ -re ".\[0-9\]* = 119.99\[0-9\]*.*$gdb_prompt $" {
+ pass "print value of fbig.f\[100\] * dbig.d\[202\]"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of fbig.f\[100\] * dbig.d\[202\]" }
+ timeout { fail "(timeout) print value of fbig.f\[100\] * dbig.d\[202\]" }
+ }
+
+send_gdb "print !(sbig.s\[90\] * 2)\n"
+gdb_expect {
+ -re ".\[0-9\]* = 0.*$gdb_prompt $" {
+ pass "print value of !(sbig.s\[90\] * 2)"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of !(sbig.s\[90\] * 2)" }
+ timeout { fail "(timeout) print value of !(sbig.s\[90\] * 2)" }
+ }
+
+
+send_gdb "print sizeof(sbig)\n"
+gdb_expect {
+ -re ".\[0-9\]* = 800.*$gdb_prompt $" {
+ pass "print value of sizeof(sbig)"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of sizeof(sbig)" }
+ timeout { fail "(timeout) print value of sizeof(sbig)" }
+ }
+
+
+send_gdb "print sizeof(cbig)\n"
+gdb_expect {
+ -re ".\[0-9\]* = 100.*$gdb_prompt $" {
+ pass "print value of sizeof(cbig)"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of sizeof(cbig)" }
+ timeout { fail "(timeout) print value of sizeof(cbig)" }
+ }
+
+
+send_gdb "print sizeof(lbig)\n"
+gdb_expect {
+ -re ".\[0-9\]* = 3600.*$gdb_prompt $" {
+ pass "print value of sizeof(lbig)"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of sizeof(lbig)" }
+ timeout { fail "(timeout) print value of sizeof(lbig)" }
+ }
+
+send_gdb "print ibig.i\[100\] << 2\n"
+gdb_expect {
+ -re ".\[0-9\]* = 20.*$gdb_prompt $" {
+ pass "print value of ibig.i\[100\] << 2"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of ibig.i\[100\] << 2" }
+ timeout { fail "(timeout) print value of ibig.i\[100\] << 2" }
+ }
+
+send_gdb "print sbig.s\[90\] >> 4\n"
+gdb_expect {
+ -re ".\[0-9\]* = 15.*$gdb_prompt $" {
+ pass "print value of sbig.s\[90\] >> 4"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of sbig.s\[90\] >> 4" }
+ timeout { fail "(timeout) print value of sbig.s\[90\] >> 4" }
+ }
+
+send_gdb "print lbig.l\[333\] >> 6\n"
+gdb_expect {
+ -re ".\[0-9\]* = 15624999.*$gdb_prompt $" {
+ pass "print value of lbig.l\[333\] >> 6"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of lbig.l\[333\] >> 6" }
+ timeout { fail "(timeout) print value of lbig.l\[333\] >> 6" }
+ }
diff --git a/gdb/testsuite/gdb.base/nodebug.c b/gdb/testsuite/gdb.base/nodebug.c
new file mode 100644
index 00000000000..4aad099e563
--- /dev/null
+++ b/gdb/testsuite/gdb.base/nodebug.c
@@ -0,0 +1,58 @@
+/* Test that things still (sort of) work when compiled without -g. */
+
+int dataglobal = 3; /* Should go in global data */
+static int datalocal = 4; /* Should go in local data */
+int bssglobal; /* Should go in global bss */
+static int bsslocal; /* Should go in local bss */
+
+int
+inner (x)
+ int x;
+{
+ return x + dataglobal + datalocal + bssglobal + bsslocal;
+}
+
+static short
+middle (x)
+ int x;
+{
+ return 2 * inner (x);
+}
+
+short
+top (x)
+ int x;
+{
+ return 2 * middle (x);
+}
+
+int
+main (argc, argv)
+ int argc;
+ char **argv;
+{
+#ifdef usestubs
+ set_debug_traps();
+ breakpoint();
+#endif
+ return top (argc);
+}
+
+char *malloc ();
+
+int *x;
+
+int
+array_index (arr, i)
+ char *arr;
+ int i;
+{
+ /* The basic concept is just "return arr[i];". But call malloc so that gdb
+ will be able to call functions. */
+ char retval;
+ x = (int *) malloc (sizeof (int));
+ *x = i;
+ retval = arr[*x];
+ free (x);
+ return retval;
+}
diff --git a/gdb/testsuite/gdb.base/nodebug.exp b/gdb/testsuite/gdb.base/nodebug.exp
new file mode 100644
index 00000000000..e4f8a355d21
--- /dev/null
+++ b/gdb/testsuite/gdb.base/nodebug.exp
@@ -0,0 +1,163 @@
+# Copyright (C) 1997 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# Test that things still (sort of) work when compiled without -g.
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+set prms_id 0
+set bug_id 0
+
+set testfile nodebug
+set srcfile ${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable ""] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+# Create and source the file that provides information about the compiler
+# used to compile the test case.
+if [get_compiler_info ${binfile}] {
+ return -1;
+}
+
+source ${binfile}.ci
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load $binfile
+
+if [runto inner] then {
+
+ # Expect to find global/local symbols in each of text/data/bss.
+
+ # The exact format for some of this output is not necessarily
+ # ideal, particularly interpreting "p top" requires a fair bit of
+ # savvy about gdb's workings and the meaning of the "{}"
+ # construct. So the details maybe could be tweaked. But the
+ # basic purpose should be maintained, which is (a) users should be
+ # able to interact with these variables with some care (they have
+ # to know how to interpret them according to their real type,
+ # since gdb doesn't know the type), but (b) users should be able
+ # to detect that gdb does not know the type, rather than just
+ # being told they are ints or functions returning int like old
+ # versions of gdb used to do.
+
+ # On alpha (and other ecoff systems) the native compilers put
+ # out debugging info for non-aggregate return values of functions
+ # even without -g, which should be accepted.
+ # Irix5, even though it is ELF, counts as "ecoff" because it
+ # encapsulates ecoff debugging info in a .mdebug section.
+ # Irix6 gcc omits no debug info at all for static functions and
+ # variables, so all tests involving statics fail.
+
+ if {!$gcc_compiled} then { setup_xfail "mips-sgi-irix5*" "mips-sgi-irix6*" }
+ gdb_test "p top" \
+ "{(<(text variable|function), no debug info>|short \\(\\))} \[0-9a-fx]* <top>"
+ if {!$gcc_compiled} then { setup_xfail "mips-sgi-irix5*" "mips-sgi-irix6*" }
+ gdb_test "whatis top" \
+ "(<(text variable|function), no debug info>|short \\(\\))"
+ if {!$gcc_compiled} then { setup_xfail "mips-sgi-irix6*" }
+ gdb_test "ptype top" "(short|int) \\((|<non-float parameter>|<non-float parameter>, <non-float parameter>)\\)"
+
+ if {!$gcc_compiled} then { setup_xfail "mips-sgi-irix5*" }
+ setup_xfail "mips-sgi-irix6*"
+ gdb_test "p middle" \
+ "{(<(text variable|function), no debug info>|short \\(\\))} \[0-9a-fx]* <middle>"
+ if {!$gcc_compiled} then { setup_xfail "mips-sgi-irix5*" }
+ setup_xfail "mips-sgi-irix6*"
+ gdb_test "whatis middle" \
+ "(<(text variable|function), no debug info>|short \\(\\))"
+ setup_xfail "mips-sgi-irix6*"
+ gdb_test "ptype middle" "(short|int) \\((|<non-float parameter>|<non-float parameter>, <non-float parameter>)\\)"
+
+ gdb_test "p dataglobal" "= 3"
+ gdb_test "whatis dataglobal" \
+ "<(data variable|variable), no debug info>"
+ gdb_test "ptype dataglobal" "<(data variable|variable), no debug info>"
+
+ # The only symbol xcoff puts out for statics is for the TOC entry.
+ # Possible, but hairy, for gdb to deal. Right now it doesn't, it
+ # doesn't know the variables exist at all.
+ setup_xfail "rs6000*-*-aix*"
+ setup_xfail "powerpc*-*-aix*"
+ if {!$gcc_compiled} then { setup_xfail "hppa*-*-hpux*" }
+ if {$gcc_compiled} then { setup_xfail "mips-sgi-irix6*" }
+ gdb_test "p datalocal" "= 4"
+ setup_xfail "rs6000*-*-aix*"
+ setup_xfail "powerpc*-*-aix*"
+ if {!$gcc_compiled} then { setup_xfail "hppa*-*-hpux*" }
+ if {$gcc_compiled} then { setup_xfail "mips-sgi-irix6*" }
+ gdb_test "whatis datalocal" "<(data variable|variable), no debug info>"
+ setup_xfail "rs6000*-*-aix*"
+ setup_xfail "powerpc*-*-aix*"
+ if {!$gcc_compiled} then { setup_xfail "hppa*-*-hpux*" }
+ if {$gcc_compiled} then { setup_xfail "mips-sgi-irix6*" }
+ gdb_test "ptype datalocal" "<(data variable|variable), no debug info>"
+
+ gdb_test "p bssglobal" "= 0"
+ gdb_test "whatis bssglobal" "<(data variable|variable), no debug info>"
+ gdb_test "ptype bssglobal" "<(data variable|variable), no debug info>"
+
+ setup_xfail "rs6000*-*-aix*"
+ setup_xfail "powerpc*-*-aix*"
+ if {!$gcc_compiled} then { setup_xfail "hppa*-*-hpux*" }
+ if {$gcc_compiled} then { setup_xfail "mips-sgi-irix6*" }
+ gdb_test "p bsslocal" "= 0"
+ setup_xfail "rs6000*-*-aix*"
+ setup_xfail "powerpc*-*-aix*"
+ if {!$gcc_compiled} then { setup_xfail "hppa*-*-hpux*" }
+ if {$gcc_compiled} then { setup_xfail "mips-sgi-irix6*" }
+ gdb_test "whatis bsslocal" "<(data variable|variable), no debug info>"
+ setup_xfail "rs6000*-*-aix*"
+ setup_xfail "powerpc*-*-aix*"
+ if {!$gcc_compiled} then { setup_xfail "hppa*-*-hpux*" }
+ if {$gcc_compiled} then { setup_xfail "mips-sgi-irix6*" }
+ gdb_test "ptype bsslocal" "<(data variable|variable), no debug info>"
+
+ if {$gcc_compiled} then { setup_xfail "mips-sgi-irix6*" }
+ gdb_test "backtrace 10" "#0.*inner.*#1.*middle.*#2.*top.*#3.*main.*" \
+ "backtrace from inner in nodebug.exp"
+ # Or if that doesn't work, at least hope for the external symbols
+ # Commented out because if we aren't going to xfail the above test
+ # ever, why bother with a weaker test?
+ #gdb_test "backtrace 10" "#0.*inner.*#1.*#2.*top.*#3.*main.*" \
+ # "backtrace from inner in nodebug.exp for externals"
+
+ # This test is not as obscure as it might look. `p getenv ("TERM")'
+ # is a real-world example, at least on many systems.
+ if {!$gcc_compiled} then { setup_xfail "hppa*-*-hpux*" "mips-sgi-irix6*" }
+ if [target_info exists gdb,cannot_call_functions] {
+ setup_xfail "*-*-*" 2416
+ fail "p/c array_index(\"abcdef\",2)"
+ } else {
+ gdb_test {p/c array_index("abcdef",2)} " = 99 'c'"
+ }
+
+ # Now, try that we can give names of file-local symbols which happen
+ # to be unique, and have it still work
+ if {$gcc_compiled} then { setup_xfail "mips-sgi-irix6*" }
+ if [runto middle] then {
+ gdb_test "backtrace 10" "#0.*middle.*#1.*top.*#2.*main.*" \
+ "backtrace from middle in nodebug.exp"
+ }
+}
diff --git a/gdb/testsuite/gdb.base/opaque.exp b/gdb/testsuite/gdb.base/opaque.exp
new file mode 100644
index 00000000000..92e6459831f
--- /dev/null
+++ b/gdb/testsuite/gdb.base/opaque.exp
@@ -0,0 +1,244 @@
+# Copyright (C) 1992, 1994, 1997 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file was written by Fred Fish. (fnf@cygnus.com)
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+set prms_id 0
+set bug_id 0
+
+set testfile "opaque"
+set binfile ${objdir}/${subdir}/opaque
+
+#if { [gdb_compile "${srcdir}/${subdir}/opaque0.c ${srcdir}/${subdir}/opaque1.c" "${binfile}" executable {debug}] != "" } {
+# gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+#}
+
+if { [gdb_compile "${srcdir}/${subdir}/opaque0.c" "${binfile}0.o" object {debug}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+if { [gdb_compile "${srcdir}/${subdir}/opaque1.c" "${binfile}1.o" object {debug}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+if { [gdb_compile "${binfile}0.o ${binfile}1.o" ${binfile} executable {debug}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+
+# Create and source the file that provides information about the compiler
+# used to compile the test case.
+if [get_compiler_info ${binfile}] {
+ return -1;
+}
+
+# Start with a fresh gdb.
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+#
+# Test basic opaque structure handling (statically).
+# The ordering of the tests is significant. We first try the things that
+# might fail if gdb fails to connect the uses of opaque structures to
+# the actual opaque structure definition.
+
+# When we start up, gdb sets the file containing main() as the current
+# source file. The actual structure foo is defined in a different file.
+# A pointer (foop) to an instance of the opaque struct is defined in the same
+# source file as main(). Ensure that gdb correctly "connected" the definition
+# in the other file with the pointer to the opaque struct in the file containing
+# "foop".
+
+# Define a procedure to set up an xfail for all targets that do not support
+# this sort of cross reference.
+# Any target gcc that has a DBX_NO_XREFS definition in its config file will
+# not support it (FIXME: Is this still true; I suspect maybe not).
+
+# Native alpha ecoff doesn't support it either.
+# I don't think this type of cross reference works for any COFF target
+# either.
+
+proc setup_xfail_on_opaque_pointer {} {
+ global gcc_compiled
+
+ setup_xfail "a29k-*-udi" "vax-*-*" "i*86-sequent-bsd*"
+ if {!$gcc_compiled} then {
+ setup_xfail "alpha-*-*" "mips-sgi-irix5*"
+ }
+}
+
+# This seems easier than trying to track different versions of xlc; I'm
+# not sure there is much rhyme or reason regarding which tests it fails
+# and which ones it passes.
+if {[istarget "rs6000-*-aix*"] && !$gcc_compiled} then {
+ warning "xfails in opaque.exp may not be set up correctly for xlc"
+}
+
+setup_xfail_on_opaque_pointer
+gdb_test "whatis foop" \
+ "type = struct foo \[*\]+" \
+ "whatis on opaque struct pointer (statically)"
+
+
+# Ensure that we know the form of the structure that foop points to.
+
+setup_xfail_on_opaque_pointer
+if {!$gcc_compiled} then { setup_xfail "rs6000-*-*" "hppa*-*-hpux*" }
+gdb_test "ptype foop" \
+ "type = struct foo \{\[\r\n\]+ int a;\[\r\n\]+ int b;\[\r\n\]+\} \[*\]+" \
+ "ptype on opaque struct pointer (statically)"
+
+
+# An instance of the opaque structure (afoo) is defined in a different file.
+# Ensure that we can locate afoo and the structure definition.
+
+gdb_test "whatis afoo" \
+ "type = struct foo" \
+ "whatis on opaque struct instance (statically)"
+
+
+# Ensure that we know the form of "afoo".
+
+gdb_test "ptype afoo" \
+ "type = struct foo \{\[\r\n\]+ int a;\[\r\n\]+ int b;\[\r\n\]+\}" \
+ "ptype on opaque struct instance (statically)"
+
+
+# Ensure that we know what a struct foo looks like.
+
+gdb_test "ptype struct foo" \
+ "type = struct foo \{\[\r\n\]+ int a;\[\r\n\]+ int b;\[\r\n\]+\}" \
+ "ptype on opaque struct tagname (statically)"
+
+
+#
+# Done with static tests, now test dynamic opaque structure handling.
+# We reload the symbol table so we forget about anything we might
+# have learned during the static tests.
+#
+
+if [istarget "mips-idt-*"] then {
+ # Restart because IDT/SIM runs out of file descriptors.
+ gdb_exit
+ gdb_start
+}
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+# Run to main, where struct foo is incomplete.
+if ![runto_main] {
+ perror "cannot run to breakpoint at main"
+}
+
+
+# The current source file is now the one containing main(). The structure foo
+# is defined in a different file, but we have a pointer to an instance of
+# the opaque structure in the current file. Ensure we know it's type.
+
+setup_xfail_on_opaque_pointer
+gdb_test "whatis foop" \
+ "type = struct foo \[*\]+" \
+ "whatis on opaque struct pointer (dynamically)"
+
+
+# Ensure that we know the form of the thing foop points to.
+
+setup_xfail_on_opaque_pointer
+if {!$gcc_compiled} then { setup_xfail "rs6000-*-*" "hppa*-*-hpux*" }
+gdb_test "ptype foop" \
+ "type = struct foo \{\[\r\n\]+ int a;\[\r\n\]+ int b;\[\r\n\]+\} \[*\]+" \
+ "ptype on opaque struct pointer (dynamically) 1"
+
+gdb_test "whatis afoo" \
+ "type = struct foo" \
+ "whatis on opaque struct instance (dynamically) 1"
+
+
+# Ensure that we know the form of afoo, an instance of a struct foo.
+
+gdb_test "ptype afoo" \
+ "type = struct foo \{\[\r\n\]+ int a;\[\r\n\]+ int b;\[\r\n\]+\}" \
+ "ptype on opaque struct instance (dynamically) 1"
+
+
+# Ensure that we know the form of an explicit struct foo.
+
+if {!$gcc_compiled} then { setup_xfail "rs6000-*-*" }
+gdb_test "ptype struct foo" \
+ "type = struct foo \{\[\r\n\]+ int a;\[\r\n\]+ int b;\[\r\n\]+\}" \
+ "ptype on opaque struct tagname (dynamically) 1"
+
+
+# Now reload the symbols again so we forget about anything we might
+# have learned reading the symbols during the previous tests.
+
+if [istarget "mips-idt-*"] then {
+ # Restart because IDT/SIM runs out of file descriptors.
+ gdb_exit
+ gdb_start
+}
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+# Run to getfoo, where struct foo is complete.
+if ![runto getfoo] {
+ perror "cannot run to breakpoint at getfoo"
+}
+
+
+# Ensure that we know what foop is.
+
+setup_xfail_on_opaque_pointer
+gdb_test "whatis foop" \
+ "type = struct foo \[*\]+" \
+ "whatis on opaque struct pointer (dynamically) 1"
+
+
+# Ensure that we know the form of the thing foop points to.
+
+setup_xfail_on_opaque_pointer
+if {!$gcc_compiled} then { setup_xfail "rs6000-*-*" "hppa*-*-hpux*" }
+gdb_test "ptype foop" \
+ "type = struct foo \{\[\r\n\]+ int a;\[\r\n\]+ int b;\[\r\n\]+\} \[*\]+" \
+ "ptype on opaque struct pointer (dynamically) 2"
+
+gdb_test "whatis afoo" \
+ "type = struct foo" \
+ "whatis on opaque struct instance (dynamically) 2"
+
+
+# Ensure that we know the form of afoo, an instance of a struct foo.
+
+gdb_test "ptype afoo" \
+ "type = struct foo \{\[\r\n\]+ int a;\[\r\n\]+ int b;\[\r\n\]+\}" \
+ "ptype on opaque struct instance (dynamically) 2"
+
+
+# Ensure that we know the form of an explicit struct foo.
+
+gdb_test "ptype struct foo" \
+ "type = struct foo \{\[\r\n\]+ int a;\[\r\n\]+ int b;\[\r\n\]+\}" \
+ "ptype on opaque struct tagname (dynamically) 2"
diff --git a/gdb/testsuite/gdb.base/opaque0.c b/gdb/testsuite/gdb.base/opaque0.c
new file mode 100644
index 00000000000..c6e239e4ac7
--- /dev/null
+++ b/gdb/testsuite/gdb.base/opaque0.c
@@ -0,0 +1,20 @@
+/* Note that struct foo is opaque (never defined) in this file. This
+ is allowed by C since this file does not reference any members of
+ the structure. The debugger needs to be able to associate this
+ opaque structure definition with the full definition in another
+ file.
+*/
+
+struct foo *foop;
+extern struct foo *getfoo ();
+
+int main ()
+{
+#ifdef usestubs
+ set_debug_traps();
+ breakpoint();
+#endif
+ foop = getfoo ();
+ putfoo (foop);
+ return 0;
+}
diff --git a/gdb/testsuite/gdb.base/opaque1.c b/gdb/testsuite/gdb.base/opaque1.c
new file mode 100644
index 00000000000..4a3c8559b82
--- /dev/null
+++ b/gdb/testsuite/gdb.base/opaque1.c
@@ -0,0 +1,18 @@
+struct foo {
+ int a;
+ int b;
+} afoo = { 1, 2};
+
+struct foo *getfoo ()
+{
+ return (&afoo);
+}
+
+#ifdef __STDC__
+void putfoo (struct foo *foop)
+#else
+void putfoo (foop)
+ struct foo *foop;
+#endif
+{
+}
diff --git a/gdb/testsuite/gdb.base/overlays.c b/gdb/testsuite/gdb.base/overlays.c
new file mode 100644
index 00000000000..d02ed707cd1
--- /dev/null
+++ b/gdb/testsuite/gdb.base/overlays.c
@@ -0,0 +1,34 @@
+/* Support program for testing gdb's ability to debug overlays
+ in the inferior. */
+
+#include "ovlymgr.h"
+
+extern int foo PARAMS((int));
+extern int bar PARAMS((int));
+extern int baz PARAMS((int));
+extern int grbx PARAMS((int));
+
+int main ()
+{
+ int a, b, c, d, e;
+
+ OverlayLoad (0);
+ OverlayLoad (4);
+ a = foo (1);
+ OverlayLoad (1);
+ OverlayLoad (5);
+ b = bar (1);
+ OverlayLoad (2);
+ OverlayLoad (6);
+ c = baz (1);
+ OverlayLoad (3);
+ OverlayLoad (7);
+ d = grbx (1);
+ e = a + b + c + d;
+ return (e != ('f' + 'o' +'o'
+ + 'b' + 'a' + 'r'
+ + 'b' + 'a' + 'z'
+ + 'g' + 'r' + 'b' + 'x'));
+
+}
+
diff --git a/gdb/testsuite/gdb.base/overlays.exp b/gdb/testsuite/gdb.base/overlays.exp
new file mode 100644
index 00000000000..512e73c2552
--- /dev/null
+++ b/gdb/testsuite/gdb.base/overlays.exp
@@ -0,0 +1,246 @@
+# Copyright (C) 1997 Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+#
+# This file was written by Michael Snyder (msnyder@cygnus.com)
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+#
+# test running programs
+#
+
+set prms_id 0
+set bug_id 0
+
+if [istarget "d10v-*-*"] then {
+ set linker_script "${srcdir}/${subdir}/d10v.ld";
+} elseif [istarget "m32r-*-*"] then {
+ set linker_script "${srcdir}/${subdir}/m32r.ld";
+} else {
+ verbose "Skipping overlay test -- not implemented for this target."
+ return
+}
+
+set testfile "overlays"
+set binfile ${objdir}/${subdir}/${testfile}
+set srcfile ${srcdir}/${subdir}/${testfile}.c
+set foo ${srcdir}/${subdir}/foo.c
+set bar ${srcdir}/${subdir}/bar.c
+set baz ${srcdir}/${subdir}/baz.c
+set grbx ${srcdir}/${subdir}/grbx.c
+
+if {[gdb_compile "${srcfile}" "${testfile}.o" object {debug}] != ""} then {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+if {[gdb_compile "${srcdir}/${subdir}/ovlymgr.c" ovlymgr.o object {debug}] != ""} then {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+if {[gdb_compile "${foo}" foo.o object {debug} ] != ""} then {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+if {[gdb_compile "${bar}" bar.o object {debug}] != ""} then {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+if {[gdb_compile "${baz}" baz.o object {debug}] != ""} then {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+if {[gdb_compile "${grbx}" grbx.o object {debug}] != ""} then {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+if {[gdb_compile "${testfile}.o ovlymgr.o foo.o bar.o baz.o grbx.o" ${binfile} executable "ldscript=-Wl,-T$linker_script"] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+remote_exec build "mv ${testfile}.o foo.o bar.o baz.o grbx.o ovlymgr.o ${objdir}/${subdir}"
+
+
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+#
+# set it up at a breakpoint so we can play with the variable values
+#
+
+if ![runto_main] then {
+ gdb_suppress_tests;
+}
+
+# couple of convenience variables
+set fptrcast [string_to_regexp "(int (*)(int))"]
+set iptrcast [string_to_regexp "(int *)"]
+
+gdb_test "overlay manual" ""
+gdb_test "overlay list" "No sections are mapped." "List with none mapped"
+
+# capture the LMA addresses of [foo bar baz grbx foox barx bazx grbxx]
+
+gdb_test "print \$foo_lma = &foo" \
+ ".* $fptrcast 0x.* <\\*foo\\*>" "foo load addr"
+gdb_test "print \$bar_lma = &bar" \
+ ".* $fptrcast 0x.* <\\*bar\\*>" "bar load addr"
+gdb_test "print \$baz_lma = &baz" \
+ ".* $fptrcast 0x.* <\\*baz\\*>" "baz load addr"
+gdb_test "print \$grbx_lma = &grbx" \
+ ".* $fptrcast 0x.* <\\*grbx\\*>" "grbx load addr"
+gdb_test "print \$foox_lma = &foox" \
+ ".* $iptrcast 0x.*" "foox load addr"
+gdb_test "print \$barx_lma = &barx" \
+ ".* $iptrcast 0x.*" "barx load addr"
+gdb_test "print \$bazx_lma = &bazx" \
+ ".* $iptrcast 0x.*" "bazx load addr"
+gdb_test "print \$grbxx_lma = &grbxx" \
+ ".* $iptrcast 0x.*" "grbxx load addr"
+
+# map each overlay successively, and
+# capture the VMA addresses of [foo bar baz grbx foox barx bazx grbxx]
+
+gdb_test "overlay map .ovly0" ""
+gdb_test "overlay list" "Section .ovly0, loaded at.*, mapped at.*" "List ovly0"
+gdb_test "print \$foo_vma = &foo" \
+ ".* $fptrcast 0x.* <foo>" "foo runtime addr"
+
+gdb_test "overlay map .ovly1" ""
+gdb_test "overlay list" "Section .ovly1, loaded at.*, mapped at.*" "List ovly1"
+gdb_test "print \$bar_vma = &bar" \
+ ".* $fptrcast 0x.* <bar>" "bar runtime addr"
+
+gdb_test "overlay map .ovly2" ""
+gdb_test "overlay list" "Section .ovly2, loaded at.*, mapped at.*" "List ovly2"
+gdb_test "print \$baz_vma = &baz" \
+ ".* $fptrcast 0x.* <baz>" "baz runtime addr"
+
+gdb_test "overlay map .ovly3" ""
+gdb_test "overlay list" "Section .ovly3, loaded at.*, mapped at.*" "List ovly3"
+gdb_test "print \$grbx_vma = &grbx" \
+ ".* $fptrcast 0x.* <grbx>" "grbx runtime addr"
+
+gdb_test "overlay map .data00" ""
+gdb_test "overlay list" "Section .data00, loaded .*, mapped .*" "List data00"
+gdb_test "print \$foox_vma = &foox" \
+ ".* $iptrcast 0x.*" "foox runtime addr"
+
+gdb_test "overlay map .data01" ""
+gdb_test "overlay list" "Section .data01, loaded .*, mapped .*" "List data01"
+gdb_test "print \$barx_vma = &barx" \
+ ".* $iptrcast 0x.*" "barx runtime addr"
+
+gdb_test "overlay map .data02" ""
+gdb_test "overlay list" "Section .data02, loaded .*, mapped .*" "List data02"
+gdb_test "print \$bazx_vma = &bazx" \
+ ".* $iptrcast 0x.*" "bazx runtime addr"
+
+gdb_test "overlay map .data03" ""
+gdb_test "overlay list" "Section .data03, loaded .*, mapped .*" "List data03"
+gdb_test "print \$grbxx_vma = &grbxx" \
+ ".* $iptrcast 0x.*" "grbxx runtime addr"
+
+# Verify that LMA != VMA
+
+gdb_test "print \$foo_lma != \$foo_vma" ".* = 1" "foo's LMA != VMA"
+gdb_test "print \$bar_lma != \$bar_vma" ".* = 1" "bar's LMA != VMA"
+gdb_test "print \$baz_lma != \$baz_vma" ".* = 1" "baz's LMA != VMA"
+gdb_test "print \$grbx_lma != \$grbx_vma" ".* = 1" "grbx's LMA != VMA"
+gdb_test "print \$foox_lma != \$foox_vma" ".* = 1" "foox's LMA != VMA"
+gdb_test "print \$barx_lma != \$barx_vma" ".* = 1" "barx's LMA != VMA"
+gdb_test "print \$bazx_lma != \$bazx_vma" ".* = 1" "bazx's LMA != VMA"
+gdb_test "print \$grbxx_lma != \$grbxx_vma" ".* = 1" "grbxx's LMA != VMA"
+
+# Verify that early-mapped overlays have been bumped out
+# by later-mapped overlays layed over in the same VMA range.
+
+send_gdb "overlay list\n"
+gdb_expect {
+ -re ".*ovly0, " { fail ".ovly0 not unmapped by .ovly1" }
+ -re ".*ovly2, " { fail ".ovly2 not unmapped by .ovly3" }
+ -re ".*data00," { fail ".data00 not unmapped by .data01" }
+ -re ".*data02," { fail ".data02 not unmapped by .data03" }
+ -re ".*$gdb_prompt $" { pass "Automatic unmapping" }
+ timeout { fail "(timeout) Automatic unmapping" }
+}
+
+# test automatic mode
+
+gdb_test "overlay auto" ""
+gdb_test "overlay list" "No sections are mapped." "List none mapped (auto)"
+gdb_test "break foo" "Breakpoint .*at .*file .*foo.c.*" "break foo"
+gdb_test "break bar" "Breakpoint .*at .*file .*bar.c.*" "break bar"
+gdb_test "break baz" "Breakpoint .*at .*file .*baz.c.*" "break baz"
+gdb_test "break grbx" "Breakpoint .*at .*file .*grbx.c.*" "break grbx"
+
+send_gdb "continue\n"
+gdb_expect {
+ -re "Breakpoint .* foo .x=1. at .*$gdb_prompt $" { pass "hit foo" }
+ -re ".*$gdb_prompt $" { fail "hit foo" }
+ timeout { fail "(timeout) hit foo" }
+}
+
+send_gdb "backtrace\n"
+gdb_expect {
+ -re "#0 .*foo .*#1 .*main .*$gdb_prompt $" { pass "BT foo" }
+ -re ".*$gdb_prompt $" { fail "BT foo" }
+ timeout { fail "(timeout) BT foo" }
+}
+
+
+send_gdb "continue\n"
+gdb_expect {
+ -re "Breakpoint .* bar .x=1. at .*$gdb_prompt $" { pass "hit bar" }
+ -re ".*$gdb_prompt $" { fail "hit bar" }
+ timeout { fail "(timeout) hit bar" }
+}
+
+send_gdb "backtrace\n"
+gdb_expect {
+ -re "#0 .*bar .*#1 .*main .*$gdb_prompt $" { pass "BT bar" }
+ -re ".*$gdb_prompt $" { fail "BT bar" }
+ timeout { fail "(timeout) BT bar" }
+}
+
+send_gdb "continue\n"
+gdb_expect {
+ -re "Breakpoint .* baz .x=1. at .*$gdb_prompt $" { pass "hit baz" }
+ -re ".*$gdb_prompt $" { fail "hit baz" }
+ timeout { fail "(timeout) hit baz" }
+}
+
+send_gdb "backtrace\n"
+gdb_expect {
+ -re "#0 .*baz .*#1 .*main .*$gdb_prompt $" { pass "BT baz" }
+ -re ".*$gdb_prompt $" { fail "BT baz" }
+ timeout { fail "(timeout) BT baz" }
+}
+
+send_gdb "continue\n"
+gdb_expect {
+ -re "Breakpoint .* grbx .x=1. at .*$gdb_prompt $" { pass "hit grbx" }
+ -re ".*$gdb_prompt $" { fail "hit grbx" }
+ timeout { fail "(timeout) hit grbx" }
+}
+
+send_gdb "backtrace\n"
+gdb_expect {
+ -re "#0 .*grbx .*#1 .*main .*$gdb_prompt $" { pass "BT grbx" }
+ -re ".*$gdb_prompt $" { fail "BT grbx" }
+ timeout { fail "(timeout) BT grbx" }
+}
+
diff --git a/gdb/testsuite/gdb.base/ovlymgr.c b/gdb/testsuite/gdb.base/ovlymgr.c
new file mode 100644
index 00000000000..bdb90feae6b
--- /dev/null
+++ b/gdb/testsuite/gdb.base/ovlymgr.c
@@ -0,0 +1,225 @@
+
+/*
+ * Ovlymgr.c -- Runtime Overlay Manager for the GDB testsuite.
+ */
+
+#include "ovlymgr.h"
+
+/* Local functions and data: */
+
+extern unsigned long _ovly_table[][4];
+extern unsigned long _novlys __attribute__ ((section (".data")));
+enum ovly_index { VMA, SIZE, LMA, MAPPED};
+
+static void ovly_copy (unsigned long dst, unsigned long src, long size);
+
+/* Flush the data and instruction caches at address START for SIZE bytes.
+ Support for each new port must be added here. */
+/* FIXME: Might be better to have a standard libgloss function that
+ ports provide that we can then use. Use libgloss instead of newlib
+ since libgloss is the one intended to handle low level system issues.
+ I would suggest something like _flush_cache to avoid the user's namespace
+ but not be completely obscure as other things may need this facility. */
+
+static void
+FlushCache (void)
+{
+#ifdef __M32R__
+ volatile char *mspr = (char *) 0xfffffff7;
+ *mspr = 1;
+#endif
+}
+
+/* OverlayLoad:
+ * Copy the overlay into its runtime region,
+ * and mark the overlay as "mapped".
+ */
+
+bool
+OverlayLoad (unsigned long ovlyno)
+{
+ unsigned long i;
+
+ if (ovlyno < 0 || ovlyno >= _novlys)
+ exit (-1); /* fail, bad ovly number */
+
+ if (_ovly_table[ovlyno][MAPPED])
+ return TRUE; /* this overlay already mapped -- nothing to do! */
+
+ for (i = 0; i < _novlys; i++)
+ if (i == ovlyno)
+ _ovly_table[i][MAPPED] = 1; /* this one now mapped */
+ else if (_ovly_table[i][VMA] == _ovly_table[ovlyno][VMA])
+ _ovly_table[i][MAPPED] = 0; /* this one now un-mapped */
+
+ ovly_copy (_ovly_table[ovlyno][VMA],
+ _ovly_table[ovlyno][LMA],
+ _ovly_table[ovlyno][SIZE]);
+
+ FlushCache ();
+
+ return TRUE;
+}
+
+/* OverlayUnload:
+ * Copy the overlay back into its "load" region.
+ * Does NOT mark overlay as "unmapped", therefore may be called
+ * more than once for the same mapped overlay.
+ */
+
+bool
+OverlayUnload (unsigned long ovlyno)
+{
+ if (ovlyno < 0 || ovlyno >= _novlys)
+ exit (-1); /* fail, bad ovly number */
+
+ if (!_ovly_table[ovlyno][MAPPED])
+ exit (-1); /* error, can't copy out a segment that's not "in" */
+
+ ovly_copy (_ovly_table[ovlyno][LMA],
+ _ovly_table[ovlyno][VMA],
+ _ovly_table[ovlyno][SIZE]);
+
+ return TRUE;
+}
+
+#ifdef __D10V__
+#define IMAP0 (*(short *)(0xff00))
+#define IMAP1 (*(short *)(0xff02))
+#define DMAP (*(short *)(0xff04))
+
+static void
+D10VTranslate (unsigned long logical,
+ short *dmap,
+ unsigned long **addr)
+{
+ unsigned long physical;
+ unsigned long seg;
+ unsigned long off;
+
+ /* to access data, we use the following mapping
+ 0x00xxxxxx: Logical data address segment (DMAP translated memory)
+ 0x01xxxxxx: Logical instruction address segment (IMAP translated memory)
+ 0x10xxxxxx: Physical data memory segment (On-chip data memory)
+ 0x11xxxxxx: Physical instruction memory segment (On-chip insn memory)
+ 0x12xxxxxx: Phisical unified memory segment (Unified memory)
+ */
+
+ /* Addresses must be correctly aligned */
+ if (logical & (sizeof (**addr) - 1))
+ exit (-1);
+
+ /* If the address is in one of the two logical address spaces, it is
+ first translated into a physical address */
+ seg = (logical >> 24);
+ off = (logical & 0xffffffL);
+ switch (seg)
+ {
+ case 0x00: /* in logical data address segment */
+ if (off <= 0x7fffL)
+ physical = (0x10L << 24) + off;
+ else
+ /* Logical address out side of on-chip segment, not
+ supported */
+ exit (-1);
+ break;
+ case 0x01: /* in logical instruction address segment */
+ {
+ short map;
+ if (off <= 0x1ffffL)
+ map = IMAP0;
+ else if (off <= 0x3ffffL)
+ map = IMAP1;
+ else
+ /* Logical address outside of IMAP[01] segment, not
+ supported */
+ exit (-1);
+ if (map & 0x1000L)
+ {
+ /* Instruction memory */
+ physical = (0x11L << 24) | off;
+ }
+ else
+ {
+ /* Unified memory */
+ physical = ((map & 0x7fL) << 17) + (off & 0x1ffffL);
+ if (physical > 0xffffffL)
+ /* Address outside of unified address segment */
+ exit (-1);
+ physical |= (0x12L << 24);
+ }
+ break;
+ }
+ case 0x10:
+ case 0x11:
+ case 0x12:
+ physical = logical;
+ break;
+ default:
+ exit (-1); /* error */
+ }
+
+ seg = (physical >> 24);
+ off = (physical & 0xffffffL);
+ switch (seg)
+ {
+ case 0x10: /* dst is a 15 bit offset into the on-chip memory */
+ *dmap = 0;
+ *addr = (long *) (0x0000 + ((short)off & 0x7fff));
+ break;
+ case 0x11: /* dst is an 18-bit offset into the on-chip
+ instruction memory */
+ *dmap = 0x1000L | ((off & 0x3ffffL) >> 14);
+ *addr = (long *) (0x8000 + ((short)off & 0x3fff));
+ break;
+ case 0x12: /* dst is a 24-bit offset into unified memory */
+ *dmap = off >> 14;
+ *addr = (long *) (0x8000 + ((short)off & 0x3fff));
+ break;
+ default:
+ exit (-1); /* error */
+ }
+}
+#endif /* __D10V__ */
+
+static void
+ovly_copy (unsigned long dst, unsigned long src, long size)
+{
+#ifdef __M32R__
+ memcpy ((void *) dst, (void *) src, size);
+ return;
+#endif /* M32R */
+
+#ifdef __D10V__
+ unsigned long *s, *d, tmp;
+ short dmap_src, dmap_dst;
+ short dmap_save;
+
+ /* all section sizes should by multiples of 4 bytes */
+ dmap_save = DMAP;
+
+ D10VTranslate (src, &dmap_src, &s);
+ D10VTranslate (dst, &dmap_dst, &d);
+
+ while (size > 0)
+ {
+ /* NB: Transfer 4 byte (long) quantites, problems occure
+ when only two bytes are transfered */
+ DMAP = dmap_src;
+ tmp = *s;
+ DMAP = dmap_dst;
+ *d = tmp;
+ d++;
+ s++;
+ size -= sizeof (tmp);
+ src += sizeof (tmp);
+ dst += sizeof (tmp);
+ if ((src & 0x3fff) == 0)
+ D10VTranslate (src, &dmap_src, &s);
+ if ((dst & 0x3fff) == 0)
+ D10VTranslate (dst, &dmap_dst, &d);
+ }
+ DMAP = dmap_save;
+#endif /* D10V */
+}
+
diff --git a/gdb/testsuite/gdb.base/ovlymgr.h b/gdb/testsuite/gdb.base/ovlymgr.h
new file mode 100644
index 00000000000..bd0d40a2640
--- /dev/null
+++ b/gdb/testsuite/gdb.base/ovlymgr.h
@@ -0,0 +1,17 @@
+/*
+ * Sample runtime overlay manager.
+ */
+
+#ifdef NO_PROTOTYPES
+#define PARAMS(paramlist) ()
+#else
+#define PARAMS(paramlist) paramlist
+#endif
+
+typedef enum { FALSE, TRUE } bool;
+
+/* Entry Points: */
+
+bool OverlayLoad PARAMS((unsigned long ovlyno));
+bool OverlayUnload PARAMS((unsigned long ovlyno));
+
diff --git a/gdb/testsuite/gdb.base/pointers.c b/gdb/testsuite/gdb.base/pointers.c
new file mode 100644
index 00000000000..8cac2c2b906
--- /dev/null
+++ b/gdb/testsuite/gdb.base/pointers.c
@@ -0,0 +1,176 @@
+
+#if !defined (__STDC__) && !defined (_AIX)
+#define signed /**/
+#endif
+
+char v_char;
+signed char v_signed_char;
+unsigned char v_unsigned_char;
+
+short v_short;
+signed short v_signed_short;
+unsigned short v_unsigned_short;
+
+int v_int;
+signed int v_signed_int;
+unsigned int v_unsigned_int;
+
+long v_long;
+signed long v_signed_long;
+unsigned long v_unsigned_long;
+
+float v_float;
+double v_double;
+
+
+
+char *v_char_pointer;
+signed char *v_signed_char_pointer;
+unsigned char *v_unsigned_char_pointer;
+
+short *v_short_pointer;
+signed short *v_signed_short_pointer;
+unsigned short *v_unsigned_short_pointer;
+
+int *v_int_pointer;
+int *v_int_pointer2;
+signed int *v_signed_int_pointer;
+unsigned int *v_unsigned_int_pointer;
+
+long *v_long_pointer;
+signed long *v_signed_long_pointer;
+unsigned long *v_unsigned_long_pointer;
+
+float *v_float_pointer;
+double *v_double_pointer;
+
+
+char v_char_array[2];
+signed char v_signed_char_array[2];
+unsigned char v_unsigned_char_array[2];
+
+short v_short_array[2];
+signed short v_signed_short_array[2];
+unsigned short v_unsigned_short_array[2];
+
+int v_int_array[2];
+signed int v_signed_int_array[2];
+unsigned int v_unsigned_int_array[2];
+
+long v_long_array[2];
+signed long v_signed_long_array[2];
+unsigned long v_unsigned_long_array[2];
+
+float v_float_array[2];
+double v_double_array[2];
+
+int matrix[2][3] = { { 0, 1, 2}, {3, 4, 5}};
+int (*rptr)[3] = matrix;
+
+float ** ptr_to_ptr_to_float;
+
+int y;
+
+int main ()
+{
+ void dummy();
+
+ /* Ensure that malloc is a pointer type; avoid use of "void" and any include files. */
+ /* extern char *malloc();*/
+
+ /* void *malloc(size_t);*/
+
+
+
+#ifdef usestubs
+ set_debug_traps();
+ breakpoint();
+#endif
+ dummy();
+/* v_int_pointer2 = &v_int_pointer;
+ v_unsigned_int_pointer = &v_int;
+
+ y = (v_unsigned_int_pointer == v_double_pointer);
+
+ x = v_unsigned_int_pointer * v_double_pointer;
+
+ v_unsigned_int_pointer = v_double_pointer;
+
+ v_unsigned_int_pointer = v_unsigned_int;*/
+
+ return 0;
+
+}
+
+void dummy()
+{
+
+
+ v_char = 0;
+ v_signed_char = 1;
+ v_unsigned_char = 2;
+
+ v_short = 3;
+ v_signed_short = 4;
+ v_unsigned_short = 5;
+
+ v_int = 6;
+ v_signed_int = 7;
+ v_unsigned_int = 8;
+
+ v_long = 9;
+ v_signed_long = 10;
+ v_unsigned_long = 11;
+
+ v_float = 100.0;
+ v_double = 200.0;
+
+
+
+ v_char_pointer = &v_char;
+ v_signed_char_pointer = &v_signed_char;
+ v_unsigned_char_pointer = &v_unsigned_char;
+
+ v_short_pointer = &v_short;
+ v_signed_short_pointer = &v_signed_short;
+ v_unsigned_short_pointer = &v_unsigned_short;
+
+ v_int_pointer = &v_int;
+ v_signed_int_pointer = &v_signed_int;
+ v_unsigned_int_pointer = &v_unsigned_int;
+
+ v_long_pointer = &v_long;
+ v_signed_long_pointer = &v_signed_long;
+ v_unsigned_long_pointer = &v_unsigned_long;
+
+ v_float_pointer = &v_float;
+ v_double_pointer = &v_double;
+
+ ptr_to_ptr_to_float = &v_float_pointer;
+
+
+ v_char_array[0] = v_char;
+ v_signed_char_array[0] = v_signed_char;
+ v_unsigned_char_array[0] = v_unsigned_char;
+
+ v_short_array[0] = v_short;
+ v_signed_short_array[0] = v_signed_short;
+ v_unsigned_short_array[0] = v_unsigned_short;
+
+ v_int_array[0] = v_int;
+ v_int_array[1] = v_int * 3;
+
+ v_signed_int_array[0] = v_signed_int;
+ v_unsigned_int_array[0] = v_unsigned_int;
+
+ v_long_array[0] = v_long;
+ v_signed_long_array[0] = v_signed_long;
+ v_unsigned_long_array[0] = v_unsigned_long;
+
+ v_float_array[0] = v_float;
+ v_double_array[0] = v_double;
+
+}
+
+
+
diff --git a/gdb/testsuite/gdb.base/pointers.exp b/gdb/testsuite/gdb.base/pointers.exp
new file mode 100644
index 00000000000..7a0e44f3574
--- /dev/null
+++ b/gdb/testsuite/gdb.base/pointers.exp
@@ -0,0 +1,358 @@
+# Copyright (C) 1998 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file was written by Elena Zannoni (ezannoni@cygnus.com)
+
+# This file is part of the gdb testsuite
+#
+# tests for pointer arithmetic and pointer dereferencing
+# with integer type variables and pointers to integers
+#
+
+if $tracelevel then {
+ strace $tracelevel
+ }
+
+#
+# test running programs
+#
+set prms_id 0
+set bug_id 0
+
+set testfile "pointers"
+set srcfile ${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug additional_flags=-w}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+ }
+
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+
+#
+# set it up at a breakpoint so we can play with the variable values
+#
+
+if ![runto_main] then {
+ perror "couldn't run to breakpoint"
+ continue
+}
+
+gdb_test "next" "return 0;" "continuing after dummy()"
+
+
+#
+# let's see if gdb catches some illegal operations on pointers
+#
+# I must comment these out because strict type checking is not
+# supported in this version of GDB. I do not really know
+# what the expected gdb reply is.
+#
+
+#send_gdb "print v_int_pointer2 = &v_int_pointer\n"
+#gdb_expect {
+# -re ".*.*$gdb_prompt $" {
+# pass "illegal pointer assignment rejected"
+# }
+# -re ".*$gdb_prompt $" { fail "illegal pointer assignment rejected" }
+# timeout { fail "(timeout) illegal pointer assignment rejected" }
+# }
+
+
+#send_gdb "print v_unsigned_int_pointer = &v_int\n"
+#gdb_expect {
+# -re ".*.*$gdb_prompt $" {
+# pass "illegal pointer assignment rejected"
+# }
+# -re ".*$gdb_prompt $" { fail "illegal pointer assignment rejected" }
+# timeout { fail "(timeout) ilegal pointer assignment rejected" }
+# }
+
+#send_gdb "print v_unsigned_int_pointer == v_double_pointer\n"
+#gdb_expect {
+# -re ".*.*$gdb_prompt $" {
+# pass "illegal pointer operation (+) rejected"
+# }
+# -re ".*$gdb_prompt $" { fail "illegal pointer operation (+) rejected" }
+# timeout { fail "(timeout) illegal pointer operation (+) rejected" }
+# }
+
+
+#send_gdb "print v_unsigned_int_pointer * v_double_pointer\n"
+#gdb_expect {
+# -re ".*Argument to arithmetic operation not a number or boolean.*$gdb_prompt $" {
+# pass "illegal pointer operation (*) rejected"
+# }
+# -re ".*$gdb_prompt $" { fail "illegal pointer operation (*) rejected" }
+# timeout { fail "(timeout) illegal pointer operation (*) rejected" }
+# }
+
+
+#send_gdb "print v_unsigned_int_pointer = v_double_pointer\n"
+#gdb_expect {
+# -re ".*.*$gdb_prompt $" {
+# pass "ilegal pointer assignment rejected"
+# }
+# -re ".*$gdb_prompt $" { fail "illegal pointer assignment rejected" }
+# timeout { fail "(timeout) illegal pointer assignment rejected" }
+# }
+
+
+#send_gdb "print v_unsigned_int_pointer = v_unsigned_int\n"
+#gdb_expect {
+# -re ".*.*$gdb_prompt $" {
+# pass "illegal pointer assignment rejected"
+# }
+# -re ".*$gdb_prompt $" { fail "illegal pointer assignment rejected" }
+# timeout { fail "(timeout) illegal pointer assignment rejected" }
+# }
+
+gdb_test "set variable v_int_pointer=&v_int_array\[0\]" "" "set pointer to beginning of array"
+gdb_test "set variable v_int_pointer2=&v_int_array\[1\]" "" "set pointer to end of array"
+
+
+send_gdb "print *v_int_pointer\n"
+gdb_expect {
+ -re ".*= 6.*$gdb_prompt $" {
+ pass "print object pointed to"
+ }
+ -re ".*$gdb_prompt $" { fail "print object pointed to" }
+ timeout { fail "(timeout) print object pointed to" }
+ }
+
+send_gdb "print *v_int_pointer2\n"
+gdb_expect {
+ -re ".*= 18.*$gdb_prompt $" {
+ pass "print object pointed to"
+ }
+ -re ".*$gdb_prompt $" { fail "print object pointed to" }
+ timeout { fail "(timeout) print object pointed to" }
+ }
+
+
+send_gdb "print v_int_pointer == v_int_pointer2\n"
+gdb_expect {
+ -re ".*= 0.*$gdb_prompt $" {
+ pass "pointer1==pointer2"
+ }
+ -re ".*$gdb_prompt $" { fail "pointer1==pointer2" }
+ timeout { fail "(timeout) pointer1==pointer2" }
+ }
+
+send_gdb "print v_int_pointer != v_int_pointer2\n"
+gdb_expect {
+ -re ".*= 1.*$gdb_prompt $" {
+ pass "pointer1!=pointer2"
+ }
+ -re ".*$gdb_prompt $" { fail "pointer1!=pointer2" }
+ timeout { fail "(timeout) pointer1!=pointer2" }
+ }
+
+
+send_gdb "print v_int_pointer <= v_int_pointer2\n"
+gdb_expect {
+ -re ".*= 1.*$gdb_prompt $" {
+ pass "pointer1<=pointer2"
+ }
+ -re ".*$gdb_prompt $" { fail "pointer1<=pointer2" }
+ timeout { fail "(timeout) pointer1<=pointer2" }
+ }
+
+
+send_gdb "print v_int_pointer >= v_int_pointer2\n"
+gdb_expect {
+ -re ".*= 0.*$gdb_prompt $" {
+ pass "pointer1>=pointer2"
+ }
+ -re ".*$gdb_prompt $" { fail "pointer1>=pointer2" }
+ timeout { fail "(timeout) pointer1>=pointer2" }
+ }
+
+
+send_gdb "print v_int_pointer < v_int_pointer2\n"
+gdb_expect {
+ -re ".*= 1.*$gdb_prompt $" {
+ pass "pointer1<pointer2"
+ }
+ -re ".*$gdb_prompt $" { fail "pointer1<pointer2" }
+ timeout { fail "(timeout) pointer1<pointer2" }
+ }
+
+send_gdb "print v_int_pointer > v_int_pointer2\n"
+gdb_expect {
+ -re ".*= 0.*$gdb_prompt $" {
+ pass "pointer1>pointer2"
+ }
+ -re ".*$gdb_prompt $" { fail "pointer1>pointer2" }
+ timeout { fail "(timeout) pointer1>pointer2" }
+ }
+
+
+gdb_test "set variable y = *v_int_pointer++" "" "set y = *v_int_pointer++"
+send_gdb "print y\n"
+gdb_expect {
+ -re ".*= 6.*$gdb_prompt $" {
+ send_gdb "print *v_int_pointer\n"
+ gdb_expect {
+ -re ".*= 18.*$gdb_prompt $" {
+ pass "pointer assignment and increment"
+ }
+ -re ".*$gdb_prompt $" { fail "pointer assignment and increment" }
+ timeout { fail "(timeout) pointer assignment and increment" }
+ }
+ }
+ -re ".*$gdb_prompt $" { fail "pointer assignment and increment" }
+ timeout { fail "(timeout) pointer assignment and increment" }
+ }
+
+
+
+
+gdb_test "set variable y = *--v_int_pointer2" "" "set y = *--v_int_pointer2"
+send_gdb "print y\n"
+gdb_expect {
+ -re ".*= 6.*$gdb_prompt $" {
+ send_gdb "print *v_int_pointer2\n"
+ gdb_expect {
+ -re ".*= 6.*$gdb_prompt $" {
+ pass "pointer decrement and assignment"
+ }
+ -re ".*$gdb_prompt $" { fail "pointer decrement and assignment" }
+ timeout { fail "(timeout) pointer decrement and assignment" }
+ }
+ }
+ -re ".*$gdb_prompt $" { fail "pointer decrement and assignment" }
+ timeout { fail "(timeout) pointer decrement and assignment" }
+ }
+
+gdb_test "set variable y =v_int_pointer-v_int_pointer2" "" "set y =v_int_pointer-v_int_pointer2"
+send_gdb "print y\n"
+gdb_expect {
+ -re ".*= 1.*$gdb_prompt $" {
+ pass "pointer1-pointer2"
+ }
+ -re ".*$gdb_prompt $" { fail "pointer1-pointer2" }
+ timeout { fail "(timeout) pointer1-pointer2" }
+ }
+
+gdb_test "set variable v_int_pointer=v_int_array" "" "set v_int_pointer=v_int_array"
+send_gdb "print *v_int_pointer\n"
+gdb_expect {
+ -re ".*= 6.*$gdb_prompt $" {
+ pass "print array element through pointer"
+ }
+ -re ".*$gdb_prompt $" { fail "print array element through pointer" }
+ timeout { fail "(timeout) print array element through pointer" }
+ }
+
+
+send_gdb "print *(v_int_pointer+1)\n"
+gdb_expect {
+ -re ".*= 18.*$gdb_prompt $" {
+ pass "print array element through pointer"
+ }
+ -re ".*$gdb_prompt $" { fail "print array element through pointer" }
+ timeout { fail "(timeout) print array element through pointer" }
+ }
+
+# test print elements of array through pointers
+
+send_gdb "print (*rptr)\[0\]\n"
+gdb_expect {
+ -re ".*= 0.*$gdb_prompt $" {
+ pass "print array element through pointer"
+ }
+ -re ".*$gdb_prompt $" { fail "print array element through pointer" }
+ timeout { fail "(timeout) print array element through pointer" }
+ }
+
+send_gdb "print (*rptr)\[1\]\n"
+gdb_expect {
+ -re ".*= 1.*$gdb_prompt $" {
+ pass "print array element through pointer"
+ }
+ -re ".*$gdb_prompt $" { fail "print array element through pointer" }
+ timeout { fail "(timeout) print array element through pointer" }
+ }
+
+
+send_gdb "print (*rptr)\[2\]\n"
+gdb_expect {
+ -re ".*= 2.*$gdb_prompt $" {
+ pass "print array element through pointer"
+ }
+ -re ".*$gdb_prompt $" { fail "print array element through pointer" }
+ timeout { fail "(timeout) print array element through pointer" }
+ }
+
+gdb_test "set variable rptr = rptr+1" "" "increment rptr"
+
+send_gdb "print (*rptr)\[0\]\n"
+gdb_expect {
+ -re ".*= 3.*$gdb_prompt $" {
+ pass "print array element through pointer"
+ }
+ -re ".*$gdb_prompt $" { fail "print array element through pointer" }
+ timeout { fail "(timeout) print array element through pointer" }
+ }
+
+
+send_gdb "print (*rptr)\[1\]\n"
+gdb_expect {
+ -re ".*= 4.*$gdb_prompt $" {
+ pass "print array element through pointer"
+ }
+ -re ".*$gdb_prompt $" { fail "print array element through pointer" }
+ timeout { fail "(timeout) print array element through pointer" }
+ }
+
+
+send_gdb "print (*rptr)\[2\]\n"
+gdb_expect {
+ -re ".*= 5.*$gdb_prompt $" {
+ pass "print array element through pointer"
+ }
+ -re ".*$gdb_prompt $" { fail "print array element through pointer" }
+ timeout { fail "(timeout) print array element through pointer" }
+ }
+
+
+send_gdb "print *( *(matrix+1) +2)\n"
+gdb_expect {
+ -re ".*= 5.*$gdb_prompt $" {
+ pass "print array element w/ pointer arithmetic"
+ }
+ -re ".*$gdb_prompt $" { fail "print array element w/ pointer arithemtic" }
+ timeout { fail "(timeout) print array element w/ pointer arithmetic" }
+ }
+
+
+send_gdb "print **ptr_to_ptr_to_float\n"
+gdb_expect {
+ -re ".*= 100.*$gdb_prompt $" {
+ pass "print through ptr to ptr"
+ }
+ -re ".*$gdb_prompt $" { fail "print through ptr to ptr" }
+ timeout { fail "(timeout) print through ptr to ptr" }
+ }
diff --git a/gdb/testsuite/gdb.base/pointers2.c b/gdb/testsuite/gdb.base/pointers2.c
new file mode 100644
index 00000000000..6c30621a4e2
--- /dev/null
+++ b/gdb/testsuite/gdb.base/pointers2.c
@@ -0,0 +1,51 @@
+void marker1 ()
+{
+
+}
+
+
+int main()
+{
+ char C, *pC, **ppC, ***pppC, ****ppppC, *****pppppC, ******ppppppC;
+ unsigned char UC, *pUC;
+ short S, *pS;
+ unsigned short US, *pUS;
+ int I, *pI;
+ unsigned int UI, *pUI;
+ long L, *pL;
+ unsigned long UL, *pUL;
+ float F, *pF;
+ double D, *pD;
+ C = 'A';
+ UC = 21;
+ S = -14;
+ US = 7;
+ I = 102;
+ UI = 1002;
+ L = -234;
+ UL = 234;
+ F = 1.25E10;
+ D = -1.375E-123;
+ pC = &C;
+ ppC = &pC;
+ pppC = &ppC;
+ ppppC = &pppC;
+ pppppC = &ppppC;
+ ppppppC = &pppppC;
+ pUC = &UC;
+ pS = &S;
+ pUS = &US;
+ pI = &I;
+ pUI = &UI;
+ pL = &L;
+ pUL = &UL;
+ pF = &F;
+ pD = &D;
+
+ #ifdef usestubs
+ set_debug_traps();
+ breakpoint();
+ #endif
+ marker1();
+ return 0;
+}
diff --git a/gdb/testsuite/gdb.base/pointers2.exp b/gdb/testsuite/gdb.base/pointers2.exp
new file mode 100644
index 00000000000..e44e110e038
--- /dev/null
+++ b/gdb/testsuite/gdb.base/pointers2.exp
@@ -0,0 +1,288 @@
+# Copyright (C) 1997, 1998
+# Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file was written by Elena Zannoni. (ezannoni@cygnus.com)
+
+
+# This file is part of the gdb testsuite
+#
+# tests for pointers
+# with elementary type variables and pointers.
+#
+
+
+if $tracelevel then {
+ strace $tracelevel
+ }
+
+#
+# test running programs
+#
+set prms_id 0
+set bug_id 0
+
+set testfile "pointers2"
+set srcfile ${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+
+#
+# set it up at a breakpoint so we can play with the variable values
+#
+if ![runto_main] then {
+ perror "couldn't run to breakpoint"
+ continue
+}
+
+send_gdb "break marker1\n" ; gdb_expect -re ".*$gdb_prompt $"
+
+ send_gdb "cont\n"
+ gdb_expect {
+ -re "Break.* marker1 \\(\\) at .*:$decimal.*$gdb_prompt $" {
+ send_gdb "up\n"
+ gdb_expect {
+ -re ".*$gdb_prompt $" {}
+ timeout { fail "up from marker1" }
+ }
+ }
+ -re "$gdb_prompt $" { fail "continue to marker1" }
+ timeout { fail "(timeout) continue to marker1" }
+ }
+
+
+send_gdb "print *pUC\n"
+gdb_expect {
+ -re ".\[0-9\]* = 21 \'.025\'.*$gdb_prompt $" {
+ pass "print value of *pUC"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of *pUC" }
+ timeout { fail "(timeout) print value of *pUC" }
+ }
+
+
+send_gdb "ptype pUC\n"
+gdb_expect {
+ -re "type = unsigned char \\*.*$gdb_prompt $" { pass "ptype pUC" }
+ -re ".*$gdb_prompt $" { fail "ptype pUC" }
+ timeout { fail "(timeout) ptype pUC" }
+}
+
+send_gdb "print *pS\n"
+gdb_expect {
+ -re ".\[0-9\]* = -14.*$gdb_prompt $" {
+ pass "print value of *pS"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of *pS" }
+ timeout { fail "(timeout) print value of *pS" }
+ }
+
+
+send_gdb "ptype pS\n"
+gdb_expect {
+ -re "type = short \\*.*$gdb_prompt $" { pass "ptype pS" }
+ -re "type = short int \\*.*$gdb_prompt $" { pass "ptype pS" }
+ -re ".*$gdb_prompt $" { fail "ptype pS" }
+ timeout { fail "(timeout) ptype pS" }
+}
+
+send_gdb "print *pUS\n"
+gdb_expect {
+ -re ".\[0-9\]* = 7.*$gdb_prompt $" {
+ pass "print value of *pUS"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of *pUS" }
+ timeout { fail "(timeout) print value of *pUS" }
+ }
+
+
+send_gdb "ptype pUS\n"
+gdb_expect {
+ -re "type = unsigned short \\*.*$gdb_prompt $" { pass "ptype pUS" }
+ -re "type = short unsigned int \\*.*$gdb_prompt $" { pass "ptype pUS" }
+ -re ".*$gdb_prompt $" { fail "ptype pUS" }
+ timeout { fail "(timeout) ptype pUS" }
+}
+
+send_gdb "print *pI\n"
+gdb_expect {
+ -re ".\[0-9\]* = 102.*$gdb_prompt $" {
+ pass "print value of *pI"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of *pI" }
+ timeout { fail "(timeout) print value of *pI" }
+ }
+
+
+send_gdb "ptype pI\n"
+gdb_expect {
+ -re "type = int \\*.*$gdb_prompt $" { pass "ptype pI" }
+ -re ".*$gdb_prompt $" { fail "ptype pI" }
+ timeout { fail "(timeout) ptype pI" }
+}
+
+send_gdb "print *pUI\n"
+gdb_expect {
+ -re ".\[0-9\]* = 1002.*$gdb_prompt $" {
+ pass "print value of *pUI"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of *pUI" }
+ timeout { fail "(timeout) print value of *pUI" }
+ }
+
+
+send_gdb "ptype pUI\n"
+gdb_expect {
+ -re "type = unsigned int \\*.*$gdb_prompt $" { pass "ptype pUI" }
+ -re ".*$gdb_prompt $" { fail "ptype pUI" }
+ timeout { fail "(timeout) ptype pUI" }
+}
+
+send_gdb "print *pL\n"
+gdb_expect {
+ -re ".\[0-9\]* = -234.*$gdb_prompt $" {
+ pass "print value of *pL"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of *pL" }
+ timeout { fail "(timeout) print value of *pL" }
+ }
+
+
+send_gdb "ptype pL\n"
+gdb_expect {
+ -re "type = long \\*.*$gdb_prompt $" { pass "ptype pL" }
+ -re "type = long int \\*.*$gdb_prompt $" { pass "ptype pL" }
+ -re ".*$gdb_prompt $" { fail "ptype pL" }
+ timeout { fail "(timeout) ptype pL" }
+}
+
+send_gdb "print *pUL\n"
+gdb_expect {
+ -re ".\[0-9\]* = 234.*$gdb_prompt $" {
+ pass "print value of *pUL"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of *pUL" }
+ timeout { fail "(timeout) print value of *pUL" }
+ }
+
+
+send_gdb "ptype pUL\n"
+gdb_expect {
+ -re "type = unsigned long \\*.*$gdb_prompt $" { pass "ptype pUL" }
+ -re "type = long unsigned int \\*.*$gdb_prompt $" { pass "ptype pUL" }
+ -re ".*$gdb_prompt $" { fail "ptype pUL" }
+ timeout { fail "(timeout) ptype pUL" }
+}
+
+send_gdb "print *pF\n"
+gdb_expect {
+ -re ".\[0-9\]* = 1.2\[0-9\]*e\\+10.*$gdb_prompt $" {
+ pass "print value of *pF"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of *pF" }
+ timeout { fail "(timeout) print value of *pF" }
+ }
+
+
+send_gdb "ptype pF\n"
+gdb_expect {
+ -re "type = float \\*.*$gdb_prompt $" { pass "ptype pF" }
+ -re ".*$gdb_prompt $" { fail "ptype pF" }
+ timeout { fail "(timeout) ptype pF" }
+}
+
+send_gdb "print *pD\n"
+gdb_expect {
+ -re ".\[0-9\]* = -1.375e-123.*$gdb_prompt $" {
+ pass "print value of *pD"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of *pD" }
+ timeout { fail "(timeout) print value of *pD" }
+ }
+
+
+send_gdb "ptype pD\n"
+gdb_expect {
+ -re "type = double \\*.*$gdb_prompt $" { pass "ptype pD" }
+ -re ".*$gdb_prompt $" { fail "ptype pD" }
+ timeout { fail "(timeout) ptype pD" }
+}
+
+send_gdb "print ******ppppppC\n"
+gdb_expect {
+ -re ".\[0-9\]* = 65 \'A\'.*$gdb_prompt $" {
+ pass "print value of ******ppppppC"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of ******ppppppC" }
+ timeout { fail "(timeout) print value of ******ppppppC" }
+ }
+
+
+send_gdb "ptype pC\n"
+gdb_expect {
+ -re "type = char \\*.*$gdb_prompt $" { pass "ptype pC" }
+ -re ".*$gdb_prompt $" { fail "ptype pC" }
+ timeout { fail "(timeout) ptype pC" }
+}
+
+send_gdb "ptype ppC\n"
+gdb_expect {
+ -re "type = char \\*\\*.*$gdb_prompt $" { pass "ptype ppC" }
+ -re ".*$gdb_prompt $" { fail "ptype ppC" }
+ timeout { fail "(timeout) ptype ppC" }
+}
+
+send_gdb "ptype pppC\n"
+gdb_expect {
+ -re "type = char \\*\\*\\*.*$gdb_prompt $" { pass "ptype pppC" }
+ -re ".*$gdb_prompt $" { fail "ptype pppC" }
+ timeout { fail "(timeout) ptype pppC" }
+}
+
+send_gdb "ptype ppppC\n"
+gdb_expect {
+ -re "type = char \\*\\*\\*\\*.*$gdb_prompt $" { pass "ptype ppppC" }
+ -re ".*$gdb_prompt $" { fail "ptype ppppC" }
+ timeout { fail "(timeout) ptype ppppC" }
+}
+
+send_gdb "ptype pppppC\n"
+gdb_expect {
+ -re "type = char \\*\\*\\*\\*\\*.*$gdb_prompt $" { pass "ptype pppppC" }
+ -re ".*$gdb_prompt $" { fail "ptype pppppC" }
+ timeout { fail "(timeout) ptype pppppC" }
+}
+
+send_gdb "ptype ppppppC\n"
+gdb_expect {
+ -re "type = char \\*\\*\\*\\*\\*\\*.*$gdb_prompt $" { pass "ptype ppppppC" }
+ -re ".*$gdb_prompt $" { fail "ptype ppppppC" }
+ timeout { fail "(timeout) ptype ppppppC" }
+}
+
diff --git a/gdb/testsuite/gdb.base/printcmds.c b/gdb/testsuite/gdb.base/printcmds.c
new file mode 100644
index 00000000000..6f2238bd256
--- /dev/null
+++ b/gdb/testsuite/gdb.base/printcmds.c
@@ -0,0 +1,101 @@
+/* This table is used as a source for every ascii character.
+ It is explicitly unsigned to avoid differences due to native characters
+ being either signed or unsigned. */
+
+unsigned char ctable1[256] = {
+ 0000, 0001, 0002, 0003, 0004, 0005, 0006, 0007,
+ 0010, 0011, 0012, 0013, 0014, 0015, 0016, 0017,
+ 0020, 0021, 0022, 0023, 0024, 0025, 0026, 0027,
+ 0030, 0031, 0032, 0033, 0034, 0035, 0036, 0037,
+ 0040, 0041, 0042, 0043, 0044, 0045, 0046, 0047,
+ 0050, 0051, 0052, 0053, 0054, 0055, 0056, 0057,
+ 0060, 0061, 0062, 0063, 0064, 0065, 0066, 0067,
+ 0070, 0071, 0072, 0073, 0074, 0075, 0076, 0077,
+ 0100, 0101, 0102, 0103, 0104, 0105, 0106, 0107,
+ 0110, 0111, 0112, 0113, 0114, 0115, 0116, 0117,
+ 0120, 0121, 0122, 0123, 0124, 0125, 0126, 0127,
+ 0130, 0131, 0132, 0133, 0134, 0135, 0136, 0137,
+ 0140, 0141, 0142, 0143, 0144, 0145, 0146, 0147,
+ 0150, 0151, 0152, 0153, 0154, 0155, 0156, 0157,
+ 0160, 0161, 0162, 0163, 0164, 0165, 0166, 0167,
+ 0170, 0171, 0172, 0173, 0174, 0175, 0176, 0177,
+ 0200, 0201, 0202, 0203, 0204, 0205, 0206, 0207,
+ 0210, 0211, 0212, 0213, 0214, 0215, 0216, 0217,
+ 0220, 0221, 0222, 0223, 0224, 0225, 0226, 0227,
+ 0230, 0231, 0232, 0233, 0234, 0235, 0236, 0237,
+ 0240, 0241, 0242, 0243, 0244, 0245, 0246, 0247,
+ 0250, 0251, 0252, 0253, 0254, 0255, 0256, 0257,
+ 0260, 0261, 0262, 0263, 0264, 0265, 0266, 0267,
+ 0270, 0271, 0272, 0273, 0274, 0275, 0276, 0277,
+ 0300, 0301, 0302, 0303, 0304, 0305, 0306, 0307,
+ 0310, 0311, 0312, 0313, 0314, 0315, 0316, 0317,
+ 0320, 0321, 0322, 0323, 0324, 0325, 0326, 0327,
+ 0330, 0331, 0332, 0333, 0334, 0335, 0336, 0337,
+ 0340, 0341, 0342, 0343, 0344, 0345, 0346, 0347,
+ 0350, 0351, 0352, 0353, 0354, 0355, 0356, 0357,
+ 0360, 0361, 0362, 0363, 0364, 0365, 0366, 0367,
+ 0370, 0371, 0372, 0373, 0374, 0375, 0376, 0377
+};
+
+unsigned char ctable2[] = {
+ 'a','X','X','X','X','X','X','X','X','X','X','X','X','X','X','X',
+ 'a','a','X','X','X','X','X','X','X','X','X','X','X','X','X','X',
+ 'a','a','a','X','X','X','X','X','X','X','X','X','X','X','X','X',
+ 'a','a','a','a','X','X','X','X','X','X','X','X','X','X','X','X',
+ 'a','a','a','a','a','X','X','X','X','X','X','X','X','X','X','X',
+ 'a','a','a','a','a','a','X','X','X','X','X','X','X','X','X','X',
+ 'a','a','a','a','a','a','a','X','X','X','X','X','X','X','X','X',
+ 'a','a','a','a','a','a','a','a','X','X','X','X','X','X','X','X',
+ 'a','a','a','a','a','a','a','a','a','X','X','X','X','X','X','X',
+ 'a','a','a','a','a','a','a','a','a','a','X','X','X','X','X','X',
+ 'a','a','a','a','a','a','a','a','a','a','a','X','X','X','X','X',
+ 'a','a','a','a','a','a','a','a','a','a','a','a','X','X','X','X',
+ 'a','a','a','a','a','a','a','a','a','a','a','a','a','X','X','X',
+ 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','X','X',
+ 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','X',
+ 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a'
+};
+
+/* Single and multidimensional arrays to test access and printing of array
+ members. */
+
+int int1dim[12] = {0,1,2,3,4,5,6,7,8,9,10,11};
+int int2dim[3][4] = {{0,1,2,3},{4,5,6,7},{8,9,10,11}};
+int int3dim[2][3][2] = {{{0,1},{2,3},{4,5}},{{6,7},{8,9},{10,11}}};
+int int4dim[1][2][3][2] = {{{{0,1},{2,3},{4,5}},{{6,7},{8,9},{10,11}}}};
+
+char *teststring = "teststring contents";
+
+/* Test printing of a struct containing character arrays. */
+
+struct some_arrays {
+ unsigned char array1[4];
+ unsigned char array2[1];
+ unsigned char array3[1];
+ unsigned char array4[2];
+ unsigned char array5[4];
+} arrays = {
+ {'a', 'b', 'c', '\0'},
+ {'d'},
+ {'e'},
+ {'f', 'g' },
+ {'h', 'i', 'j', '\0'}
+};
+
+struct some_arrays *parrays = &arrays;
+
+/* -- */
+
+main ()
+{
+#ifdef usestubs
+ set_debug_traps();
+ breakpoint();
+#endif
+ malloc(1);
+
+ /* Prevent AIX linker from removing variables. */
+ return ctable1[0] + ctable2[0] + int1dim[0] + int2dim[0][0]
+ + int3dim[0][0][0] + int4dim[0][0][0][0] + teststring[0] +
+ *parrays -> array1;
+}
diff --git a/gdb/testsuite/gdb.base/printcmds.exp b/gdb/testsuite/gdb.base/printcmds.exp
new file mode 100644
index 00000000000..4953ec5c4a8
--- /dev/null
+++ b/gdb/testsuite/gdb.base/printcmds.exp
@@ -0,0 +1,695 @@
+# Copyright (C) 1992, 1994, 1995, 1997 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file was written by Fred Fish. (fnf@cygnus.com)
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+set prms_id 0
+set bug_id 0
+
+set testfile "printcmds"
+set srcfile ${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+# Set the current language to C. This counts as a test. If it
+# fails, then we skip the other tests.
+
+proc set_lang_c {} {
+ global gdb_prompt
+
+ if [gdb_test "set language c" "" "set language c"] {
+ return 0
+ }
+
+ if [gdb_test "show language" ".* source language is \"c\".*"] {
+ return 0
+ }
+ return 1;
+}
+
+proc test_integer_literals_accepted {} {
+ global gdb_prompt
+
+ # Test various decimal values.
+
+ gdb_test "p 123" " = 123"
+ gdb_test "p -123" " = -123"
+ gdb_test "p/d 123" " = 123"
+
+ # Test various octal values.
+
+ gdb_test "p 0123" " = 83"
+ gdb_test "p 00123" " = 83"
+ gdb_test "p -0123" " = -83"
+ gdb_test "p/o 0123" " = 0123"
+
+ # Test various hexadecimal values.
+
+ gdb_test "p 0x123" " = 291"
+ gdb_test "p -0x123" " = -291"
+ gdb_test "p 0x0123" " = 291"
+ gdb_test "p -0x0123" " = -291"
+ gdb_test "p 0xABCDEF" " = 11259375"
+ gdb_test "p 0xabcdef" " = 11259375"
+ gdb_test "p 0xAbCdEf" " = 11259375"
+ gdb_test "p/x 0x123" " = 0x123"
+}
+
+proc test_character_literals_accepted {} {
+ global gdb_prompt
+
+ gdb_test "p 'a'" " = 97 'a'"
+ gdb_test "p/c 'a'" " = 97 'a'"
+ gdb_test "p/x 'a'" " = 0x61"
+ gdb_test "p/d 'a'" " = 97"
+ gdb_test "p/t 'a'" " = 1100001"
+ gdb_test "p '\\141'" " = 97 'a'"
+ gdb_test "p/x '\\377'" " = 0xff"
+ # Note "p '\''" => "= 39 '\''"
+ gdb_test "p '\\''" " = 39 '\\\\''"
+ # Note "p '\\'" => "= 92 '\\'"
+ gdb_test "p '\\\\'" " = 92 '\\\\\\\\'"
+}
+
+proc test_integer_literals_rejected {} {
+ global gdb_prompt
+
+ test_print_reject "p 0x"
+ gdb_test "p ''" "Empty character constant\\."
+ gdb_test "p '''" "Empty character constant\\."
+ test_print_reject "p '\\'"
+
+ # Note that this turns into "p '\\\'" at gdb's input.
+ test_print_reject "p '\\\\\\'"
+
+ # Test various decimal values.
+
+ test_print_reject "p DEADBEEF"
+
+ # Gdb currently fails this test for all configurations. The C
+ # lexer thinks that 123DEADBEEF is a floating point number, but
+ # then fails to notice that atof() only eats the 123 part.
+ # FIXME: This should be put into PRMS.
+ # Fixed, 4/25/97, by Bob Manson.
+
+ test_print_reject "p 123DEADBEEF"
+ test_print_reject "p 123foobar.bazfoo3"
+ test_print_reject "p 123EEEEEEEEEEEEEEEEE33333k333"
+ gdb_test "p 123.4+56.7" "180.(099\[0-9]*|100\[0-9\]*)" "check for floating addition"
+
+ # Test various octal values.
+
+ test_print_reject "p 09"
+ test_print_reject "p 079"
+
+ # Test various hexadecimal values.
+
+ test_print_reject "p 0xG"
+ test_print_reject "p 0xAG"
+}
+
+proc test_print_all_chars {} {
+ global gdb_prompt
+
+ gdb_test "p ctable1\[0\]" " = 0 '\\\\000'"
+ gdb_test "p ctable1\[1\]" " = 1 '\\\\001'"
+ gdb_test "p ctable1\[2\]" " = 2 '\\\\002'"
+ gdb_test "p ctable1\[3\]" " = 3 '\\\\003'"
+ gdb_test "p ctable1\[4\]" " = 4 '\\\\004'"
+ gdb_test "p ctable1\[5\]" " = 5 '\\\\005'"
+ gdb_test "p ctable1\[6\]" " = 6 '\\\\006'"
+ gdb_test "p ctable1\[7\]" " = 7 '\\\\a'"
+ gdb_test "p ctable1\[8\]" " = 8 '\\\\b'"
+ gdb_test "p ctable1\[9\]" " = 9 '\\\\t'"
+ gdb_test "p ctable1\[10\]" " = 10 '\\\\n'"
+ gdb_test "p ctable1\[11\]" " = 11 '\\\\013'"
+ gdb_test "p ctable1\[12\]" " = 12 '\\\\f'"
+ gdb_test "p ctable1\[13\]" " = 13 '\\\\r'"
+ gdb_test "p ctable1\[14\]" " = 14 '\\\\016'"
+ gdb_test "p ctable1\[15\]" " = 15 '\\\\017'"
+ gdb_test "p ctable1\[16\]" " = 16 '\\\\020'"
+ gdb_test "p ctable1\[17\]" " = 17 '\\\\021'"
+ gdb_test "p ctable1\[18\]" " = 18 '\\\\022'"
+ gdb_test "p ctable1\[19\]" " = 19 '\\\\023'"
+ gdb_test "p ctable1\[20\]" " = 20 '\\\\024'"
+ gdb_test "p ctable1\[21\]" " = 21 '\\\\025'"
+ gdb_test "p ctable1\[22\]" " = 22 '\\\\026'"
+ gdb_test "p ctable1\[23\]" " = 23 '\\\\027'"
+ gdb_test "p ctable1\[24\]" " = 24 '\\\\030'"
+ gdb_test "p ctable1\[25\]" " = 25 '\\\\031'"
+ gdb_test "p ctable1\[26\]" " = 26 '\\\\032'"
+ gdb_test "p ctable1\[27\]" " = 27 '\\\\e'"
+ gdb_test "p ctable1\[28\]" " = 28 '\\\\034'"
+ gdb_test "p ctable1\[29\]" " = 29 '\\\\035'"
+ gdb_test "p ctable1\[30\]" " = 30 '\\\\036'"
+ gdb_test "p ctable1\[31\]" " = 31 '\\\\037'"
+ gdb_test "p ctable1\[32\]" " = 32 ' '"
+ gdb_test "p ctable1\[33\]" " = 33 '!'"
+ gdb_test "p ctable1\[34\]" " = 34 '\"'"
+ gdb_test "p ctable1\[35\]" " = 35 '#'"
+ gdb_test "p ctable1\[36\]" " = 36 '\\\$'"
+ gdb_test "p ctable1\[37\]" " = 37 '%'"
+ gdb_test "p ctable1\[38\]" " = 38 '&'"
+ gdb_test "p ctable1\[39\]" " = 39 '\\\\''"
+ gdb_test "p ctable1\[40\]" " = 40 '\\('"
+ gdb_test "p ctable1\[41\]" " = 41 '\\)'"
+ gdb_test "p ctable1\[42\]" " = 42 '\\*'"
+ gdb_test "p ctable1\[43\]" " = 43 '\\+'"
+ gdb_test "p ctable1\[44\]" " = 44 ','"
+ gdb_test "p ctable1\[45\]" " = 45 '-'"
+ gdb_test "p ctable1\[46\]" " = 46 '.'"
+ gdb_test "p ctable1\[47\]" " = 47 '/'"
+ gdb_test "p ctable1\[48\]" " = 48 '0'"
+ gdb_test "p ctable1\[49\]" " = 49 '1'"
+ gdb_test "p ctable1\[50\]" " = 50 '2'"
+ gdb_test "p ctable1\[51\]" " = 51 '3'"
+ gdb_test "p ctable1\[52\]" " = 52 '4'"
+ gdb_test "p ctable1\[53\]" " = 53 '5'"
+ gdb_test "p ctable1\[54\]" " = 54 '6'"
+ gdb_test "p ctable1\[55\]" " = 55 '7'"
+ gdb_test "p ctable1\[56\]" " = 56 '8'"
+ gdb_test "p ctable1\[57\]" " = 57 '9'"
+ gdb_test "p ctable1\[58\]" " = 58 ':'"
+ gdb_test "p ctable1\[59\]" " = 59 ';'"
+ gdb_test "p ctable1\[60\]" " = 60 '<'"
+ gdb_test "p ctable1\[61\]" " = 61 '='"
+ gdb_test "p ctable1\[62\]" " = 62 '>'"
+ gdb_test "p ctable1\[63\]" " = 63 '\\?'"
+ gdb_test "p ctable1\[64\]" " = 64 '@'"
+ gdb_test "p ctable1\[65\]" " = 65 'A'"
+ gdb_test "p ctable1\[66\]" " = 66 'B'"
+ gdb_test "p ctable1\[67\]" " = 67 'C'"
+ gdb_test "p ctable1\[68\]" " = 68 'D'"
+ gdb_test "p ctable1\[69\]" " = 69 'E'"
+ gdb_test "p ctable1\[70\]" " = 70 'F'"
+ gdb_test "p ctable1\[71\]" " = 71 'G'"
+ gdb_test "p ctable1\[72\]" " = 72 'H'"
+ gdb_test "p ctable1\[73\]" " = 73 'I'"
+ gdb_test "p ctable1\[74\]" " = 74 'J'"
+ gdb_test "p ctable1\[75\]" " = 75 'K'"
+ gdb_test "p ctable1\[76\]" " = 76 'L'"
+ gdb_test "p ctable1\[77\]" " = 77 'M'"
+ gdb_test "p ctable1\[78\]" " = 78 'N'"
+ gdb_test "p ctable1\[79\]" " = 79 'O'"
+ gdb_test "p ctable1\[80\]" " = 80 'P'"
+ gdb_test "p ctable1\[81\]" " = 81 'Q'"
+ gdb_test "p ctable1\[82\]" " = 82 'R'"
+ gdb_test "p ctable1\[83\]" " = 83 'S'"
+ gdb_test "p ctable1\[84\]" " = 84 'T'"
+ gdb_test "p ctable1\[85\]" " = 85 'U'"
+ gdb_test "p ctable1\[86\]" " = 86 'V'"
+ gdb_test "p ctable1\[87\]" " = 87 'W'"
+ gdb_test "p ctable1\[88\]" " = 88 'X'"
+ gdb_test "p ctable1\[89\]" " = 89 'Y'"
+ gdb_test "p ctable1\[90\]" " = 90 'Z'"
+ gdb_test "p ctable1\[91\]" " = 91 '\\\['"
+ gdb_test "p ctable1\[92\]" " = 92 '\\\\\\\\'"
+ gdb_test "p ctable1\[93\]" " = 93 '\\\]'"
+ gdb_test "p ctable1\[94\]" " = 94 '\\^'"
+ gdb_test "p ctable1\[95\]" " = 95 '_'"
+ gdb_test "p ctable1\[96\]" " = 96 '`'"
+ gdb_test "p ctable1\[97\]" " = 97 'a'"
+ gdb_test "p ctable1\[98\]" " = 98 'b'"
+ gdb_test "p ctable1\[99\]" " = 99 'c'"
+ gdb_test "p ctable1\[100\]" " = 100 'd'"
+ gdb_test "p ctable1\[101\]" " = 101 'e'"
+ gdb_test "p ctable1\[102\]" " = 102 'f'"
+ gdb_test "p ctable1\[103\]" " = 103 'g'"
+ gdb_test "p ctable1\[104\]" " = 104 'h'"
+ gdb_test "p ctable1\[105\]" " = 105 'i'"
+ gdb_test "p ctable1\[106\]" " = 106 'j'"
+ gdb_test "p ctable1\[107\]" " = 107 'k'"
+ gdb_test "p ctable1\[108\]" " = 108 'l'"
+ gdb_test "p ctable1\[109\]" " = 109 'm'"
+ gdb_test "p ctable1\[110\]" " = 110 'n'"
+ gdb_test "p ctable1\[111\]" " = 111 'o'"
+ gdb_test "p ctable1\[112\]" " = 112 'p'"
+ gdb_test "p ctable1\[113\]" " = 113 'q'"
+ gdb_test "p ctable1\[114\]" " = 114 'r'"
+ gdb_test "p ctable1\[115\]" " = 115 's'"
+ gdb_test "p ctable1\[116\]" " = 116 't'"
+ gdb_test "p ctable1\[117\]" " = 117 'u'"
+ gdb_test "p ctable1\[118\]" " = 118 'v'"
+ gdb_test "p ctable1\[119\]" " = 119 'w'"
+ gdb_test "p ctable1\[120\]" " = 120 'x'"
+ gdb_test "p ctable1\[121\]" " = 121 'y'"
+ gdb_test "p ctable1\[122\]" " = 122 'z'"
+ gdb_test "p ctable1\[123\]" " = 123 '\[{\]+'"
+ gdb_test "p ctable1\[124\]" " = 124 '\[|\]+'"
+ gdb_test "p ctable1\[125\]" " = 125 '\[}\]+'"
+ gdb_test "p ctable1\[126\]" " = 126 '\[~\]'"
+ gdb_test "p ctable1\[127\]" " = 127 '\\\\177'"
+ gdb_test "p ctable1\[128\]" " = 128 '\\\\200'"
+ gdb_test "p ctable1\[129\]" " = 129 '\\\\201'"
+ gdb_test "p ctable1\[130\]" " = 130 '\\\\202'"
+ gdb_test "p ctable1\[131\]" " = 131 '\\\\203'"
+ gdb_test "p ctable1\[132\]" " = 132 '\\\\204'"
+ gdb_test "p ctable1\[133\]" " = 133 '\\\\205'"
+ gdb_test "p ctable1\[134\]" " = 134 '\\\\206'"
+ gdb_test "p ctable1\[135\]" " = 135 '\\\\207'"
+ gdb_test "p ctable1\[136\]" " = 136 '\\\\210'"
+ gdb_test "p ctable1\[137\]" " = 137 '\\\\211'"
+ gdb_test "p ctable1\[138\]" " = 138 '\\\\212'"
+ gdb_test "p ctable1\[139\]" " = 139 '\\\\213'"
+ gdb_test "p ctable1\[140\]" " = 140 '\\\\214'"
+ gdb_test "p ctable1\[141\]" " = 141 '\\\\215'"
+ gdb_test "p ctable1\[142\]" " = 142 '\\\\216'"
+ gdb_test "p ctable1\[143\]" " = 143 '\\\\217'"
+ gdb_test "p ctable1\[144\]" " = 144 '\\\\220'"
+ gdb_test "p ctable1\[145\]" " = 145 '\\\\221'"
+ gdb_test "p ctable1\[146\]" " = 146 '\\\\222'"
+ gdb_test "p ctable1\[147\]" " = 147 '\\\\223'"
+ gdb_test "p ctable1\[148\]" " = 148 '\\\\224'"
+ gdb_test "p ctable1\[149\]" " = 149 '\\\\225'"
+ gdb_test "p ctable1\[150\]" " = 150 '\\\\226'"
+ gdb_test "p ctable1\[151\]" " = 151 '\\\\227'"
+ gdb_test "p ctable1\[152\]" " = 152 '\\\\230'"
+ gdb_test "p ctable1\[153\]" " = 153 '\\\\231'"
+ gdb_test "p ctable1\[154\]" " = 154 '\\\\232'"
+ gdb_test "p ctable1\[155\]" " = 155 '\\\\233'"
+ gdb_test "p ctable1\[156\]" " = 156 '\\\\234'"
+ gdb_test "p ctable1\[157\]" " = 157 '\\\\235'"
+ gdb_test "p ctable1\[158\]" " = 158 '\\\\236'"
+ gdb_test "p ctable1\[159\]" " = 159 '\\\\237'"
+ gdb_test "p ctable1\[160\]" " = 160 '\\\\240'"
+ gdb_test "p ctable1\[161\]" " = 161 '\\\\241'"
+ gdb_test "p ctable1\[162\]" " = 162 '\\\\242'"
+ gdb_test "p ctable1\[163\]" " = 163 '\\\\243'"
+ gdb_test "p ctable1\[164\]" " = 164 '\\\\244'"
+ gdb_test "p ctable1\[165\]" " = 165 '\\\\245'"
+ gdb_test "p ctable1\[166\]" " = 166 '\\\\246'"
+ gdb_test "p ctable1\[167\]" " = 167 '\\\\247'"
+ gdb_test "p ctable1\[168\]" " = 168 '\\\\250'"
+ gdb_test "p ctable1\[169\]" " = 169 '\\\\251'"
+ gdb_test "p ctable1\[170\]" " = 170 '\\\\252'"
+ gdb_test "p ctable1\[171\]" " = 171 '\\\\253'"
+ gdb_test "p ctable1\[172\]" " = 172 '\\\\254'"
+ gdb_test "p ctable1\[173\]" " = 173 '\\\\255'"
+ gdb_test "p ctable1\[174\]" " = 174 '\\\\256'"
+ gdb_test "p ctable1\[175\]" " = 175 '\\\\257'"
+ gdb_test "p ctable1\[176\]" " = 176 '\\\\260'"
+ gdb_test "p ctable1\[177\]" " = 177 '\\\\261'"
+ gdb_test "p ctable1\[178\]" " = 178 '\\\\262'"
+ gdb_test "p ctable1\[179\]" " = 179 '\\\\263'"
+ gdb_test "p ctable1\[180\]" " = 180 '\\\\264'"
+ gdb_test "p ctable1\[181\]" " = 181 '\\\\265'"
+ gdb_test "p ctable1\[182\]" " = 182 '\\\\266'"
+ gdb_test "p ctable1\[183\]" " = 183 '\\\\267'"
+ gdb_test "p ctable1\[184\]" " = 184 '\\\\270'"
+ gdb_test "p ctable1\[185\]" " = 185 '\\\\271'"
+ gdb_test "p ctable1\[186\]" " = 186 '\\\\272'"
+ gdb_test "p ctable1\[187\]" " = 187 '\\\\273'"
+ gdb_test "p ctable1\[188\]" " = 188 '\\\\274'"
+ gdb_test "p ctable1\[189\]" " = 189 '\\\\275'"
+ gdb_test "p ctable1\[190\]" " = 190 '\\\\276'"
+ gdb_test "p ctable1\[191\]" " = 191 '\\\\277'"
+ gdb_test "p ctable1\[192\]" " = 192 '\\\\300'"
+ gdb_test "p ctable1\[193\]" " = 193 '\\\\301'"
+ gdb_test "p ctable1\[194\]" " = 194 '\\\\302'"
+ gdb_test "p ctable1\[195\]" " = 195 '\\\\303'"
+ gdb_test "p ctable1\[196\]" " = 196 '\\\\304'"
+ gdb_test "p ctable1\[197\]" " = 197 '\\\\305'"
+ gdb_test "p ctable1\[198\]" " = 198 '\\\\306'"
+ gdb_test "p ctable1\[199\]" " = 199 '\\\\307'"
+ gdb_test "p ctable1\[200\]" " = 200 '\\\\310'"
+ gdb_test "p ctable1\[201\]" " = 201 '\\\\311'"
+ gdb_test "p ctable1\[202\]" " = 202 '\\\\312'"
+ gdb_test "p ctable1\[203\]" " = 203 '\\\\313'"
+ gdb_test "p ctable1\[204\]" " = 204 '\\\\314'"
+ gdb_test "p ctable1\[205\]" " = 205 '\\\\315'"
+ gdb_test "p ctable1\[206\]" " = 206 '\\\\316'"
+ gdb_test "p ctable1\[207\]" " = 207 '\\\\317'"
+ gdb_test "p ctable1\[208\]" " = 208 '\\\\320'"
+ gdb_test "p ctable1\[209\]" " = 209 '\\\\321'"
+ gdb_test "p ctable1\[210\]" " = 210 '\\\\322'"
+ gdb_test "p ctable1\[211\]" " = 211 '\\\\323'"
+ gdb_test "p ctable1\[212\]" " = 212 '\\\\324'"
+ gdb_test "p ctable1\[213\]" " = 213 '\\\\325'"
+ gdb_test "p ctable1\[214\]" " = 214 '\\\\326'"
+ gdb_test "p ctable1\[215\]" " = 215 '\\\\327'"
+ gdb_test "p ctable1\[216\]" " = 216 '\\\\330'"
+ gdb_test "p ctable1\[217\]" " = 217 '\\\\331'"
+ gdb_test "p ctable1\[218\]" " = 218 '\\\\332'"
+ gdb_test "p ctable1\[219\]" " = 219 '\\\\333'"
+ gdb_test "p ctable1\[220\]" " = 220 '\\\\334'"
+ gdb_test "p ctable1\[221\]" " = 221 '\\\\335'"
+ gdb_test "p ctable1\[222\]" " = 222 '\\\\336'"
+ gdb_test "p ctable1\[223\]" " = 223 '\\\\337'"
+ gdb_test "p ctable1\[224\]" " = 224 '\\\\340'"
+ gdb_test "p ctable1\[225\]" " = 225 '\\\\341'"
+ gdb_test "p ctable1\[226\]" " = 226 '\\\\342'"
+ gdb_test "p ctable1\[227\]" " = 227 '\\\\343'"
+ gdb_test "p ctable1\[228\]" " = 228 '\\\\344'"
+ gdb_test "p ctable1\[229\]" " = 229 '\\\\345'"
+ gdb_test "p ctable1\[230\]" " = 230 '\\\\346'"
+ gdb_test "p ctable1\[231\]" " = 231 '\\\\347'"
+ gdb_test "p ctable1\[232\]" " = 232 '\\\\350'"
+ gdb_test "p ctable1\[233\]" " = 233 '\\\\351'"
+ gdb_test "p ctable1\[234\]" " = 234 '\\\\352'"
+ gdb_test "p ctable1\[235\]" " = 235 '\\\\353'"
+ gdb_test "p ctable1\[236\]" " = 236 '\\\\354'"
+ gdb_test "p ctable1\[237\]" " = 237 '\\\\355'"
+ gdb_test "p ctable1\[238\]" " = 238 '\\\\356'"
+ gdb_test "p ctable1\[239\]" " = 239 '\\\\357'"
+ gdb_test "p ctable1\[240\]" " = 240 '\\\\360'"
+ gdb_test "p ctable1\[241\]" " = 241 '\\\\361'"
+ gdb_test "p ctable1\[242\]" " = 242 '\\\\362'"
+ gdb_test "p ctable1\[243\]" " = 243 '\\\\363'"
+ gdb_test "p ctable1\[244\]" " = 244 '\\\\364'"
+ gdb_test "p ctable1\[245\]" " = 245 '\\\\365'"
+ gdb_test "p ctable1\[246\]" " = 246 '\\\\366'"
+ gdb_test "p ctable1\[247\]" " = 247 '\\\\367'"
+ gdb_test "p ctable1\[248\]" " = 248 '\\\\370'"
+ gdb_test "p ctable1\[249\]" " = 249 '\\\\371'"
+ gdb_test "p ctable1\[250\]" " = 250 '\\\\372'"
+ gdb_test "p ctable1\[251\]" " = 251 '\\\\373'"
+ gdb_test "p ctable1\[252\]" " = 252 '\\\\374'"
+ gdb_test "p ctable1\[253\]" " = 253 '\\\\375'"
+ gdb_test "p ctable1\[254\]" " = 254 '\\\\376'"
+ gdb_test "p ctable1\[255\]" " = 255 '\\\\377'"
+}
+
+# Test interaction of the number of print elements to print and the
+# repeat count, set to the default of 10.
+
+proc test_print_repeats_10 {} {
+ global gdb_prompt
+
+ for { set x 1; } { $x <= 16 } { incr x; } {
+ gdb_test "set print elements $x" "" ""
+ for { set e 1; } { $e <= 16 } {incr e; } {
+ set v [expr $e - 1];
+ set command "p &ctable2\[${v}*16\]"
+ if { $x < $e } {
+ set aval $x;
+ } else {
+ set aval $e;
+ }
+ set xval [expr $x - $e];
+ if { $xval < 0 } {
+ set xval 0;
+ }
+ if { $aval > 10 } {
+ set a "'a' <repeats $aval times>";
+ if { $xval > 0 } {
+ set a "${a}, \\\"";
+ }
+ } else {
+ set a "\\\"[string range "aaaaaaaaaaaaaaaa" 1 $aval]";
+ if { $xval > 10 } {
+ set a "$a\\\", ";
+ }
+ }
+ set xstr "";
+ if { $xval > 10 } {
+ set xstr "'X' <repeats $xval times>";
+ } else {
+ if { $xval > 0 } {
+ set xstr "[string range "XXXXXXXXXXXXXXXX" 1 $xval]\\\"";
+ } else {
+ if { $aval <= 10 } {
+ set xstr "\\\"";
+ }
+ }
+ }
+ if { $aval < 16 } {
+ set xstr "${xstr}\[.\]\[.\]\[.\]"
+ }
+ set string " = \[(\]unsigned char \[*\]\[)\] ${a}${xstr}";
+ gdb_test "$command" "$string" "$command with print elements set to $x";
+ }
+ }
+}
+
+proc test_print_strings {} {
+ global gdb_prompt
+
+ # We accept "(unsigned char *) " before the string. char vs. unsigned char
+ # is already tested elsewhere.
+
+ # Test that setting print elements unlimited doesn't completely suppress
+ # printing; this was a bug in older gdb's.
+ gdb_test "set print elements 0" "" ""
+ gdb_test "p teststring" \
+ " = (.unsigned char .. )?\"teststring contents\"" "p teststring with elements set to 0"
+ gdb_test "set print elements 1" "" ""
+ gdb_test "p teststring" \
+ " = (.unsigned char .. )?\"t\"\\.\\.\\." "p teststring with elements set to 1"
+ gdb_test "set print elements 5" "" ""
+ gdb_test "p teststring" \
+ " = (.unsigned char .. )?\"tests\"\\.\\.\\." "p teststring with elements set to 5"
+ gdb_test "set print elements 19" "" ""
+ gdb_test "p teststring" \
+ " = (.unsigned char .. )?\"teststring contents\"" "p teststring with elements set to 19"
+ gdb_test "set print elements 20" "" ""
+ gdb_test "p teststring" \
+ " = (.unsigned char .. )?\"teststring contents\"" "p teststring with elements set to 20"
+
+ gdb_test "set print elements 8" "" ""
+
+ gdb_test "p &ctable1\[0\]" \
+ " = \\(unsigned char \\*\\) \"\""
+ gdb_test "p &ctable1\[1\]" \
+ " = \\(unsigned char \\*\\) \"\\\\001\\\\002\\\\003\\\\004\\\\005\\\\006\\\\a\\\\b\"..."
+ gdb_test "p &ctable1\[1*8\]" \
+ " = \\(unsigned char \\*\\) \"\\\\b\\\\t\\\\n\\\\013\\\\f\\\\r\\\\016\\\\017\"..."
+ gdb_test "p &ctable1\[2*8\]" \
+ " = \\(unsigned char \\*\\) \"\\\\020\\\\021\\\\022\\\\023\\\\024\\\\025\\\\026\\\\027\"..."
+ gdb_test "p &ctable1\[3*8\]" \
+ " = \\(unsigned char \\*\\) \"\\\\030\\\\031\\\\032\\\\e\\\\034\\\\035\\\\036\\\\037\"..."
+ gdb_test "p &ctable1\[4*8\]" \
+ " = \\(unsigned char \\*\\) \" !\\\\\"#\\\$%&'\"..."
+ gdb_test "p &ctable1\[5*8\]" \
+ " = \\(unsigned char \\*\\) \"\\(\\)\\*\\+,-./\"..."
+ gdb_test "p &ctable1\[6*8\]" \
+ " = \\(unsigned char \\*\\) \"01234567\"..."
+ gdb_test "p &ctable1\[7*8\]" \
+ " = \\(unsigned char \\*\\) \"89:;<=>\\?\"..."
+ gdb_test "p &ctable1\[8*8\]" \
+ " = \\(unsigned char \\*\\) \"@ABCDEFG\"..."
+ gdb_test "p &ctable1\[9*8\]" \
+ " = \\(unsigned char \\*\\) \"HIJKLMNO\"..."
+ gdb_test "p &ctable1\[10*8\]" \
+ " = \\(unsigned char \\*\\) \"PQRSTUVW\"..."
+ gdb_test "p &ctable1\[11*8\]" \
+ " = \\(unsigned char \\*\\) \"XYZ\\\[\\\\\\\\\\\]\\^_\"..."
+ gdb_test "p &ctable1\[12*8\]" \
+ " = \\(unsigned char \\*\\) \"`abcdefg\"..."
+ gdb_test "p &ctable1\[13*8\]" \
+ " = \\(unsigned char \\*\\) \"hijklmno\"..."
+ gdb_test "p &ctable1\[14*8\]" \
+ " = \\(unsigned char \\*\\) \"pqrstuvw\"..."
+ gdb_test "p &ctable1\[15*8\]" \
+ " = \\(unsigned char \\*\\) \"xyz\[{|}\]+\\~\\\\177\"..."
+ gdb_test "p &ctable1\[16*8\]" \
+ " = \\(unsigned char \\*\\) \"\\\\200\\\\201\\\\202\\\\203\\\\204\\\\205\\\\206\\\\207\"..."
+ gdb_test "p &ctable1\[17*8\]" \
+ " = \\(unsigned char \\*\\) \"\\\\210\\\\211\\\\212\\\\213\\\\214\\\\215\\\\216\\\\217\"..."
+ gdb_test "p &ctable1\[18*8\]" \
+ " = \\(unsigned char \\*\\) \"\\\\220\\\\221\\\\222\\\\223\\\\224\\\\225\\\\226\\\\227\"..."
+ gdb_test "p &ctable1\[19*8\]" \
+ " = \\(unsigned char \\*\\) \"\\\\230\\\\231\\\\232\\\\233\\\\234\\\\235\\\\236\\\\237\"..."
+ gdb_test "p &ctable1\[20*8\]" \
+ " = \\(unsigned char \\*\\) \"\\\\240\\\\241\\\\242\\\\243\\\\244\\\\245\\\\246\\\\247\"..."
+ gdb_test "p &ctable1\[21*8\]" \
+ " = \\(unsigned char \\*\\) \"\\\\250\\\\251\\\\252\\\\253\\\\254\\\\255\\\\256\\\\257\"..."
+ gdb_test "p &ctable1\[22*8\]" \
+ " = \\(unsigned char \\*\\) \"\\\\260\\\\261\\\\262\\\\263\\\\264\\\\265\\\\266\\\\267\"..."
+ gdb_test "p &ctable1\[23*8\]" \
+ " = \\(unsigned char \\*\\) \"\\\\270\\\\271\\\\272\\\\273\\\\274\\\\275\\\\276\\\\277\"..."
+ gdb_test "p &ctable1\[24*8\]" \
+ " = \\(unsigned char \\*\\) \"\\\\300\\\\301\\\\302\\\\303\\\\304\\\\305\\\\306\\\\307\"..."
+ gdb_test "p &ctable1\[25*8\]" \
+ " = \\(unsigned char \\*\\) \"\\\\310\\\\311\\\\312\\\\313\\\\314\\\\315\\\\316\\\\317\"..."
+ gdb_test "p &ctable1\[26*8\]" \
+ " = \\(unsigned char \\*\\) \"\\\\320\\\\321\\\\322\\\\323\\\\324\\\\325\\\\326\\\\327\"..."
+ gdb_test "p &ctable1\[27*8\]" \
+ " = \\(unsigned char \\*\\) \"\\\\330\\\\331\\\\332\\\\333\\\\334\\\\335\\\\336\\\\337\"..."
+ gdb_test "p &ctable1\[28*8\]" \
+ " = \\(unsigned char \\*\\) \"\\\\340\\\\341\\\\342\\\\343\\\\344\\\\345\\\\346\\\\347\"..."
+ gdb_test "p &ctable1\[29*8\]" \
+ " = \\(unsigned char \\*\\) \"\\\\350\\\\351\\\\352\\\\353\\\\354\\\\355\\\\356\\\\357\"..."
+ gdb_test "p &ctable1\[30*8\]" \
+ " = \\(unsigned char \\*\\) \"\\\\360\\\\361\\\\362\\\\363\\\\364\\\\365\\\\366\\\\367\"..."
+ gdb_test "p &ctable1\[31*8\]" \
+ " = \\(unsigned char \\*\\) \"\\\\370\\\\371\\\\372\\\\373\\\\374\\\\375\\\\376\\\\377\"..."
+}
+
+proc test_print_int_arrays {} {
+ global gdb_prompt
+
+ gdb_test "set print elements 24" "" ""
+
+ gdb_test "p int1dim" \
+ " = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}"
+ gdb_test "p int2dim" \
+ " = {{0, 1, 2, 3}, {4, 5, 6, 7}, {8, 9, 10, 11}}"
+ gdb_test "p int3dim" \
+ " = {{{0, 1}, {2, 3}, {4, 5}}, {{6, 7}, {8, 9}, {10, 11}}}"
+ gdb_test "p int4dim" \
+ " = {{{{0, 1}, {2, 3}, {4, 5}}, {{6, 7}, {8, 9}, {10, 11}}}}"
+}
+
+proc test_artificial_arrays {} {
+ # Send \026@ instead of just @ in case the kill character is @.
+ gdb_test "p int1dim\[0\]\026@2" " = {0, 1}" {p int1dim[0]@2}
+ gdb_test "p int1dim\[0\]\026@2\026@3" \
+ "({{0, 1}, {2, 3}, {4, 5}}|\[Cc\]annot.*)" \
+ {p int1dim[0]@2@3}
+ gdb_test {p/x (short [])0x12345678} \
+ " = ({0x1234, 0x5678}|{0x5678, 0x1234})"
+}
+
+proc test_print_char_arrays {} {
+ global gdb_prompt
+ global hex
+
+ gdb_test "set print elements 24" "" ""
+ gdb_test "set print address on" "" ""
+
+ gdb_test "p arrays" \
+ " = {array1 = \"abc\", array2 = \"d\", array3 = \"e\", array4 = \"fg\", array5 = \"hij\"}"
+
+ gdb_test "p parrays" " = \\(struct some_arrays \\*\\) $hex"
+ gdb_test "p parrays->array1" " = \"abc\""
+ gdb_test "p &parrays->array1" " = \\(unsigned char \\(\\*\\)\\\[4\\\]\\) $hex"
+ gdb_test "p parrays->array2" " = \"d\""
+ gdb_test "p &parrays->array2" " = \\(unsigned char \\(\\*\\)\\\[1\\\]\\) $hex"
+ gdb_test "p parrays->array3" " = \"e\""
+ gdb_test "p &parrays->array3" " = \\(unsigned char \\(\\*\\)\\\[1\\\]\\) $hex"
+ gdb_test "p parrays->array4" " = \"fg\""
+ gdb_test "p &parrays->array4" " = \\(unsigned char \\(\\*\\)\\\[2\\\]\\) $hex"
+ gdb_test "p parrays->array5" " = \"hij\""
+ gdb_test "p &parrays->array5" " = \\(unsigned char \\(\\*\\)\\\[4\\\]\\) $hex"
+
+ gdb_test "set print address off" "" ""
+}
+
+proc test_print_string_constants {} {
+ global gdb_prompt
+
+ gdb_test "set print elements 50" "" ""
+
+ if [target_info exists gdb,cannot_call_functions] {
+ setup_xfail "*-*-*" 2416
+ fail "This target can not call functions"
+ return
+ }
+
+ setup_xfail "a29k-*-udi" 2416
+ gdb_test "p \"a string\"" " = \"a string\""
+ setup_xfail "a29k-*-udi" 2416
+ gdb_test "p \"embedded \\000 null\"" " = \"embedded \\\\000 null\""
+ setup_xfail "a29k-*-udi" 2416
+ gdb_test "p \"abcd\"\[2\]" " = 99 'c'"
+ setup_xfail "a29k-*-udi" 2416
+ gdb_test "p sizeof (\"abcdef\")" " = 7"
+ setup_xfail "a29k-*-udi" 2416
+ gdb_test "ptype \"foo\"" " = char \\\[4\\\]"
+ setup_xfail "a29k-*-udi" 2416
+ gdb_test "p *\"foo\"" " = 102 'f'"
+ setup_xfail "a29k-*-udi" 2416
+ gdb_test "ptype *\"foo\"" " = char"
+ setup_xfail "a29k-*-udi" 2416
+ gdb_test "p &*\"foo\"" " = \"foo\""
+ setup_xfail "*-*-*"
+ gdb_test "ptype &*\"foo\"" "type = char \\*"
+ setup_xfail "a29k-*-udi" 2416
+ gdb_test "p (char *)\"foo\"" " = \"foo\""
+}
+
+proc test_print_array_constants {} {
+
+ if [target_info exists gdb,cannot_call_functions] {
+ setup_xfail "*-*-*" 2416
+ fail "This target can not call functions"
+ return
+ }
+
+ setup_xfail "a29k-*-udi" 2416
+ gdb_test "print {'a','b','c'}" " = \"abc\""
+ setup_xfail "a29k-*-udi" 2416
+ gdb_test "print {0,1,2}" " = {0, 1, 2}"
+ setup_xfail "a29k-*-udi" 2416
+ gdb_test "print {(long)0,(long)1,(long)2}" " = {0, 1, 2}"
+ setup_xfail "a29k-*-udi" 2416
+ gdb_test "print {{0,1,2},{3,4,5}}" " = {{0, 1, 2}, {3, 4, 5}}"
+ setup_xfail "a29k-*-udi" 2416
+ gdb_test "print {4,5,6}\[2\]" " = 6"
+ setup_xfail "a29k-*-udi" 2416
+ gdb_test "print *&{4,5,6}\[1\]" " = 5"
+}
+
+proc test_printf {} {
+ gdb_test "printf \"x=%d,y=%d,z=%d\\n\", 5, 6, 7" "x=5,y=6,z=7"
+ gdb_test "printf \"string=%.4sxx\\n\", teststring" "string=testxx"
+ gdb_test "printf \"string=%sxx\\n\", teststring" \
+ "string=teststring contentsxx"
+
+ gdb_test "printf \"%f is fun\\n\", 1.0" "1\.0+ is fun"
+
+ # Test mixing args of different sizes.
+ gdb_test "printf \"x=%d,y=%f,z=%d\\n\", 5, 6.0, 7" "x=5,y=6\.0+,z=7"
+ gdb_test "printf \"%x %f, %c %x, %x, %f\\n\", 0xbad, -99.541, 'z',\
+0xfeedface, 0xdeadbeef, 5.0" "bad -99.54\[0-9\]+, z feedface, deadbeef, 5.0+"
+}
+
+# Start with a fresh gdb.
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+
+gdb_test "print \$pc" "No registers\\."
+# FIXME: should also test "print $pc" when there is an execfile but no
+# remote debugging target, process or corefile.
+
+gdb_load ${binfile}
+
+gdb_test "set print sevenbit-strings" ""
+gdb_test "set print address off" "" ""
+gdb_test "set width 0" ""
+
+if [set_lang_c] then {
+ gdb_test "p ctable1\[120\]" "120 'x'" "p ctable1\[120\] #1"
+
+ if [runto_main] then {
+ test_integer_literals_accepted
+ test_integer_literals_rejected
+ test_character_literals_accepted
+ test_print_all_chars
+ test_print_repeats_10
+ test_print_strings
+ test_print_int_arrays
+ test_artificial_arrays
+ test_print_char_arrays
+# We used to do the runto main here.
+ test_print_string_constants
+ test_print_array_constants
+ test_printf
+ }
+} else {
+ fail "C print command tests suppressed"
+}
diff --git a/gdb/testsuite/gdb.base/ptype.c b/gdb/testsuite/gdb.base/ptype.c
new file mode 100644
index 00000000000..801343530eb
--- /dev/null
+++ b/gdb/testsuite/gdb.base/ptype.c
@@ -0,0 +1,313 @@
+/*
+ * Test file with lots of different types, for testing the
+ * "ptype" command.
+ */
+
+/*
+ * First the basic C types.
+ */
+
+#if !defined (__STDC__) && !defined (_AIX)
+#define signed /**/
+#endif
+
+char v_char;
+signed char v_signed_char;
+unsigned char v_unsigned_char;
+
+short v_short;
+signed short v_signed_short;
+unsigned short v_unsigned_short;
+
+int v_int;
+signed int v_signed_int;
+unsigned int v_unsigned_int;
+
+long v_long;
+signed long v_signed_long;
+unsigned long v_unsigned_long;
+
+float v_float;
+double v_double;
+
+/*
+ * Now some derived types, which are arrays, functions-returning,
+ * pointers, structures, unions, and enumerations.
+ */
+
+/**** arrays *******/
+
+char v_char_array[2];
+signed char v_signed_char_array[2];
+unsigned char v_unsigned_char_array[2];
+
+short v_short_array[2];
+signed short v_signed_short_array[2];
+unsigned short v_unsigned_short_array[2];
+
+int v_int_array[2];
+signed int v_signed_int_array[2];
+unsigned int v_unsigned_int_array[2];
+
+long v_long_array[2];
+signed long v_signed_long_array[2];
+unsigned long v_unsigned_long_array[2];
+
+float v_float_array[2];
+double v_double_array[2];
+
+/* PR 3742 */
+typedef char t_char_array[];
+
+/**** pointers *******/
+
+char *v_char_pointer;
+signed char *v_signed_char_pointer;
+unsigned char *v_unsigned_char_pointer;
+
+short *v_short_pointer;
+signed short *v_signed_short_pointer;
+unsigned short *v_unsigned_short_pointer;
+
+int *v_int_pointer;
+signed int *v_signed_int_pointer;
+unsigned int *v_unsigned_int_pointer;
+
+long *v_long_pointer;
+signed long *v_signed_long_pointer;
+unsigned long *v_unsigned_long_pointer;
+
+float *v_float_pointer;
+double *v_double_pointer;
+
+/**** structs *******/
+
+struct t_struct {
+ char v_char_member;
+ short v_short_member;
+ int v_int_member;
+ long v_long_member;
+ float v_float_member;
+ double v_double_member;
+} v_struct1;
+
+struct t_struct *v_t_struct_p;
+
+struct {
+ char v_char_member;
+ short v_short_member;
+ int v_int_member;
+ long v_long_member;
+ float v_float_member;
+ double v_double_member;
+} v_struct2;
+
+/* typedef'd struct without a tag. */
+typedef struct {
+ double v_double_member;
+ int v_int_member;
+} t_struct3;
+/* GCC seems to want a variable of this type, or else it won't put out
+ a symbol. */
+t_struct3 v_struct3;
+
+/**** unions *******/
+
+union t_union {
+ char v_char_member;
+ short v_short_member;
+ int v_int_member;
+ long v_long_member;
+ float v_float_member;
+ double v_double_member;
+} v_union;
+
+union {
+ char v_char_member;
+ short v_short_member;
+ int v_int_member;
+ long v_long_member;
+ float v_float_member;
+ double v_double_member;
+} v_union2;
+
+/* typedef'd union without a tag. */
+typedef union {
+ double v_double_member;
+ int v_int_member;
+} t_union3;
+/* GCC seems to want a variable of this type, or else it won't put out
+ a symbol. */
+t_union3 v_union3;
+
+/*** Functions returning type ********/
+
+char v_char_func () { return(0); }
+signed char v_signed_char_func () { return (0); }
+unsigned char v_unsigned_char_func () { return (0); }
+
+short v_short_func () { return (0); }
+signed short v_signed_short_func () { return (0); }
+unsigned short v_unsigned_short_func () { return (0); }
+
+int v_int_func () { return (0); }
+signed int v_signed_int_func () { return (0); }
+unsigned int v_unsigned_int_func () { return (0); }
+
+long v_long_func () { return (0); }
+signed long v_signed_long_func () { return (0); }
+unsigned long v_unsigned_long_func () { return (0); }
+
+float v_float_func () { return (0.0); }
+double v_double_func () { return (0.0); }
+
+/**** Some misc more complicated things *******/
+
+struct link {
+ struct link *next;
+#ifdef __STDC__
+ struct link *(*linkfunc) (struct link *this, int flags);
+#else
+ struct link *(*linkfunc) ();
+#endif
+ struct t_struct stuff[1][2][3];
+} *s_link;
+
+union tu_link {
+ struct link *next;
+#ifdef __STDC__
+ struct link *(*linkfunc) (struct link *this, int flags);
+#else
+ struct link *(*linkfunc) ();
+#endif
+ struct t_struct stuff[1][2][3];
+} u_link;
+
+struct outer_struct {
+ int outer_int;
+ struct inner_struct {
+ int inner_int;
+ long inner_long;
+ }inner_struct_instance;
+ union inner_union {
+ int inner_union_int;
+ long inner_union_long;
+ }inner_union_instance;
+ long outer_long;
+} nested_su;
+
+/**** Enumerations *******/
+
+enum
+/* Work around the bug for compilers which don't put out the right stabs. */
+#if __GNUC__ < 2 && !defined (_AIX)
+primary1_tag
+#endif
+{red1, green1, blue1} primary1;
+
+enum {red, green, blue} primary;
+enum colors {yellow, purple, pink} nonprimary;
+
+enum {chevy, ford} clunker;
+enum cars {bmw, porsche} sportscar;
+
+typedef enum {FALSE, TRUE} boolean;
+boolean v_boolean;
+typedef enum bvals {false, true} boolean2;
+boolean2 v_boolean2;
+
+enum misordered {two = 2, one = 1, zero = 0, three = 3};
+
+/***********/
+
+main ()
+{
+ /* Ensure that malloc is a pointer type; avoid use of "void" and any include files. */
+ extern char *malloc();
+
+ /* Seems like we need a variable of this type to get the type to be put
+ in the executable, at least for AIX xlc. */
+ enum misordered v_misordered = three;
+
+ /* Some of the tests in ptype.exp require invoking malloc, so make
+ sure it is linked in to this program. */
+ v_char_pointer = (char *) malloc (1);
+
+#ifdef usestubs
+ set_debug_traps();
+ breakpoint();
+#endif
+ /* Some linkers (e.g. on AIX) remove unreferenced variables,
+ so make sure to reference them. */
+ primary = blue;
+ primary1 = blue1;
+ nonprimary = pink;
+ sportscar = porsche;
+ clunker = ford;
+ v_struct1.v_int_member = 5;
+ v_struct2.v_int_member = 6;
+ v_struct3.v_int_member = 7;
+
+ v_char = 0;
+ v_signed_char = 0;
+ v_unsigned_char = 0;
+
+ v_short = 0;
+ v_signed_short = 0;
+ v_unsigned_short = 0;
+
+ v_int = 0;
+ v_signed_int = 0;
+ v_unsigned_int = 0;
+
+ v_long = 0;
+ v_signed_long = 0;
+ v_unsigned_long = 0;
+
+ v_float = 0;
+ v_double = 0;
+
+ v_char_array[0] = 0;
+ v_signed_char_array[0] = 0;
+ v_unsigned_char_array[0] = 0;
+
+ v_short_array[0] = 0;
+ v_signed_short_array[0] = 0;
+ v_unsigned_short_array[0] = 0;
+
+ v_int_array[0] = 0;
+ v_signed_int_array[0] = 0;
+ v_unsigned_int_array[0] = 0;
+
+ v_long_array[0] = 0;
+ v_signed_long_array[0] = 0;
+ v_unsigned_long_array[0] = 0;
+
+ v_float_array[0] = 0;
+ v_double_array[0] = 0;
+
+ v_char_pointer = 0;
+ v_signed_char_pointer = 0;
+ v_unsigned_char_pointer = 0;
+
+ v_short_pointer = 0;
+ v_signed_short_pointer = 0;
+ v_unsigned_short_pointer = 0;
+
+ v_int_pointer = 0;
+ v_signed_int_pointer = 0;
+ v_unsigned_int_pointer = 0;
+
+ v_long_pointer = 0;
+ v_signed_long_pointer = 0;
+ v_unsigned_long_pointer = 0;
+
+ v_float_pointer = 0;
+ v_double_pointer = 0;
+
+ nested_su.outer_int = 0;
+ v_t_struct_p = 0;
+
+ v_boolean = FALSE;
+ v_boolean2 = false;
+}
diff --git a/gdb/testsuite/gdb.base/ptype.exp b/gdb/testsuite/gdb.base/ptype.exp
new file mode 100644
index 00000000000..1ef677150e8
--- /dev/null
+++ b/gdb/testsuite/gdb.base/ptype.exp
@@ -0,0 +1,532 @@
+# Copyright (C) 1988, 1990, 1991, 1992, 1994, 1997 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file was written by Rob Savoye. (rob@cygnus.com)
+
+if $tracelevel then {
+ strace $tracelevel
+ }
+
+#
+# test running programs
+#
+set prms_id 0
+set bug_id 0
+
+set testfile "ptype"
+set srcfile ${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+# Create and source the file that provides information about the compiler
+# used to compile the test case.
+if [get_compiler_info ${binfile}] {
+ return -1;
+}
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+# Test ptype of unnamed enumeration members before any action causes
+# the partial symbol table to be expanded to full symbols. This fails
+# with stabs compilers which fail to use a nameless stab (such as
+# pre-2.4.5 versions of gcc and most non-gcc compilers).
+
+send_gdb "ptype red1\n"
+gdb_expect {
+ -re "type = enum primary1_tag \{red1, green1, blue1\}.*$gdb_prompt $"\
+ {
+ # The workaround is in effect. As this is a compiler, not GDB,
+ # bug, we'll make it a PASS but perhaps it should be an XFAIL.
+ pass "ptype unnamed enumeration member (worked around)"
+ }
+ -re "type = enum \{red1, green1, blue1\}.*$gdb_prompt $"\
+ { pass "ptype unnamed enumeration member" }
+ -re ".*$gdb_prompt $" { fail "ptype unnamed enumeration member" }
+ timeout { fail "(timeout) ptype unnamed enumeration member" }
+}
+
+#
+# test ptype command with structures
+#
+# Here and elsewhere, we accept
+# "long", "long int", or "int" for long variables (whatis.exp already
+# has an XFAIL for "int" (Sun cc bug), so no need to fail it here).
+gdb_test "ptype struct t_struct" "type = struct t_struct \{.*\[\r\n\] (unsigned |)char v_char_member;.*\[\r\n\] (short|short int) v_short_member;.*\[\r\n\] int v_int_member;.*\[\r\n\] (long|long int|int) v_long_member;.*\[\r\n\] float v_float_member;.*\[\r\n\] double v_double_member;.*\[\r\n\]\}.*" "ptype structure"
+
+
+# Test the equivalence between '.' and '->' for struct member references.
+
+if [gdb_test "ptype v_struct1.v_float_member" "type = float"]<0 then {
+ return -1
+}
+if [gdb_test "ptype v_struct1->v_float_member" "type = float"]<0 then {
+ return -1
+}
+if [gdb_test "ptype v_t_struct_p.v_float_member" "type = float"]<0 then {
+ return -1
+}
+if [gdb_test "ptype v_t_struct_p->v_float_member" "type = float"]<0 then {
+ return -1
+}
+
+
+# IBM's xlc puts out bogus stabs--the stuff field is type 42,
+# which isn't defined.
+
+gdb_test "ptype struct link" "type = struct link \{.*\[\r\n\] struct link \[*\]next;.*\[\r\n\] struct link \[*(\]+linkfunc\[)(\]+(struct link \[*\], int\[)\]|);.*\[\r\n\] struct t_struct stuff.1..2..3.;.*\[\r\n\]\}.*" "ptype linked list structure"
+
+#
+# test ptype command with unions
+#
+gdb_test "ptype union t_union" "type = union t_union \{.*\[\r\n\] (unsigned |)char v_char_member;.*\[\r\n\] (short|short int) v_short_member;.*\[\r\n\] int v_int_member;.*\[\r\n\] (long|long int|int) v_long_member;.*\[\r\n\] float v_float_member;.*\[\r\n\] double v_double_member;.*\[\r\n\]\}.*" "ptype union"
+
+# IBM's xlc puts out bogus stabs--the stuff field is type 42,
+# which isn't defined.
+gdb_test "ptype union tu_link" "type = union tu_link .*\[\r\n\] struct link \[*\]next;.*\[\r\n\] struct link \[(\*\]+linkfunc\[)(\]+(struct link \[*\], int\[)\]|);.*\[\r\n\] struct t_struct stuff.1..2..3.;.*\[\r\n\]\}.*" "ptype linked list union"
+
+#
+# test ptype command with enums
+#
+
+gdb_test "ptype primary" "type = enum .red, green, blue.*" "ptype unnamed enumeration"
+
+gdb_test "ptype enum colors" "type = enum colors \{yellow, purple, pink\}.*" "ptype named enumeration"
+
+
+#
+# test ptype command with enums as typedef
+#
+gdb_test "ptype boolean" "type = enum \{FALSE, TRUE\}.*" "ptype unnamed typedef'd enumeration"
+
+# And check that whatis shows the name, not "enum {...}".
+# This probably fails for all DWARF 1 cases, so assume so for now. -fnf
+# The problem with xlc is that the stabs look like
+# :t51=eFALSE:0,TRUE:1,;
+# boolean:t55=51
+# v_boolean:G51
+# GDB's behavior is correct; the type which the variable is defined
+# as (51) doesn't have a name. Only 55 has a name.
+
+if {!$gcc_compiled} then { setup_xfail "rs6000-*-*" "i*86-*-sysv4*" }
+setup_xfail_format "DWARF 1"
+gdb_test "whatis v_boolean" "type = boolean" \
+ "whatis unnamed typedef'd enum (compiler bug in IBM's xlc)"
+
+# Same thing with struct and union.
+gdb_test "ptype t_struct3" "type = struct \{.*
+ *double v_double_member;.*
+ *int v_int_member;.*\}" "printing typedef'd struct"
+
+gdb_test "ptype t_union3" "type = union \{.*
+ *double v_double_member;.*
+ *int v_int_member;.*\}" "printing typedef'd union"
+
+gdb_test "ptype enum bvals" "type = enum bvals \{false, true\}.*" "ptype named typedef'd enumf'd enum"
+
+#
+# test ptype command with out-of-order enum values
+#
+gdb_test "ptype enum misordered" "type = enum misordered \{two = 2, one = 1, zero = 0, three = 3\}.*" "ptype misordered enumeration"
+
+#
+# test ptype command with a named enum's value
+#
+gdb_test "ptype three" "type = enum misordered \{two = 2, one = 1, zero = 0, three = 3\}.*" "ptype named enumeration member"
+
+gdb_test "ptype red" "type = enum \{red, green, blue\}.*" "ptype unnamed enumeration member #2"
+
+#
+# test ptype command with basic C types
+#
+# I've commented most of this out because it duplicates tests in whatis.exp.
+# I've just left in a token test or 2 which is designed to test that ptype
+# acts like whatis for basic types. If it is thought to be necessary to
+# test both whatis and ptype for all the types, the tests should be
+# merged into whatis.exp, or else maintenance will be a royal pain -kingdon
+#setup_xfail "i960-*-*" 1821
+#setup_xfail "mips-idt-*" "mips-sgi-*" "a29k-*-*"
+#send "ptype v_char\n"
+#gdb_expect {
+# -re "type = char.*$gdb_prompt $" { pass "ptype char" }
+# -re ".*$gdb_prompt $" { fail "ptype char" }
+# timeout { fail "(timeout) ptype char" }
+#}
+#
+#
+#setup_xfail "mips-*-*" "a29k-*-*"
+#send "ptype v_signed_char\n"
+#gdb_expect {
+# -re "type = signed char.*$gdb_prompt $" { pass "ptype signed char" }
+# -re ".*$gdb_prompt $" { fail "ptype signed char" }
+# timeout { fail "(timeout) ptype signed char" }
+#}
+#
+#
+#send "ptype v_unsigned_char\n"
+#gdb_expect {
+# -re "type = unsigned char.*$gdb_prompt $" { pass "ptype unsigned char" }
+# -re ".*$gdb_prompt $" { fail "ptype unsigned char" }
+# timeout { fail "(timeout) ptype unsigned char" }
+#}
+
+gdb_test "ptype v_short" "type = short(| int).*" "ptype short"
+
+#send "ptype v_signed_short\n"
+#gdb_expect {
+# -re "type = short.*$gdb_prompt $" { pass "ptype signed short" }
+# -re ".*$gdb_prompt $" { fail "ptype signed short" }
+# timeout { fail "(timeout) ptype signed short" }
+#}
+#
+#
+#send "ptype v_unsigned_short\n"
+#gdb_expect {
+# -re "type = unsigned short.*$gdb_prompt $" { pass "ptype unsigned short" }
+# -re ".*$gdb_prompt $" { fail "ptype unsigned short" }
+# timeout { fail "(timeout) ptype unsigned short" }
+#}
+
+
+gdb_test "ptype v_int" "type = int.*" "ptype int"
+
+#send "ptype v_signed_int\n"
+#gdb_expect {
+# -re "type = int.*$gdb_prompt $" { pass "ptype signed int" }
+# -re ".*$gdb_prompt $" { fail "ptype signed int" }
+# timeout { fail "(timeout) ptype signed int" }
+#}
+#
+#
+#send "ptype v_unsigned_int\n"
+#gdb_expect {
+# -re "type = unsigned int.*$gdb_prompt $" { pass "ptype unsigned int" }
+# -re ".*$gdb_prompt $" { fail "ptype unsigned int" }
+# timeout { fail "(timeout) ptype unsigned int" }
+#}
+#
+#
+#send "ptype v_long\n"
+#gdb_expect {
+# -re "type = long.*$gdb_prompt $" { pass "ptype long" }
+# -re ".*$gdb_prompt $" { fail "ptype long" }
+# timeout { fail "(timeout) ptype long" }
+#}
+#
+#
+#send "ptype v_signed_long\n"
+#gdb_expect {
+# -re "type = long.*$gdb_prompt $" { pass "ptype signed long" }
+# -re ".*$gdb_prompt $" { fail "ptype signed long" }
+# timeout { fail "(timeout) ptype signed long" }
+#}
+#
+#
+#send "ptype v_unsigned_long\n"
+#gdb_expect {
+# -re "type = unsigned long.*$gdb_prompt $" { pass "ptype unsigned long" }
+# -re ".*$gdb_prompt $" { fail "ptype unsigned long" }
+# timeout { fail "(timeout) ptype unsigned long" }
+#}
+#
+#
+#send "ptype v_float\n"
+#gdb_expect {
+# -re "type = float.*$gdb_prompt $" { pass "ptype float" }
+# -re ".*$gdb_prompt $" { fail "ptype float" }
+# timeout { fail "(timeout) ptype float" }
+#}
+#
+#
+#send "ptype v_double\n"
+#gdb_expect {
+# -re "type = double.*$gdb_prompt $" { pass "ptype double" }
+# -re ".*$gdb_prompt $" { fail "ptype double" }
+# timeout { fail "(timeout) ptype double" }
+#}
+
+
+#
+# test ptype command with arrays
+#
+#setup_xfail "i960-*-*" 1821
+#setup_xfail "mips-idt-*" "mips-sgi-*" "a29k-*-*"
+#send "ptype v_char_array\n"
+#gdb_expect {
+# -re "type = char .2..*$gdb_prompt $" { pass "ptype char array" }
+# -re ".*$gdb_prompt $" { fail "ptype char array" }
+# timeout { fail "(timeout) ptype char array" }
+#}
+#
+#
+#setup_xfail "mips-*-*" "a29k-*-*"
+#send "ptype v_signed_char_array\n"
+#gdb_expect {
+# -re "type = (|signed )char .2..*$gdb_prompt $" { pass "ptype signed char array" }
+# -re ".*$gdb_prompt $" { fail "ptype signed char array" }
+# timeout { fail "(timeout) ptype signed char array" }
+#}
+#
+#
+#send "ptype v_unsigned_char_array\n"
+#gdb_expect {
+# -re "type = unsigned char .2..*$gdb_prompt $" { pass "ptype unsigned char array" }
+# -re ".*$gdb_prompt $" { fail "ptype unsigned char array" }
+# timeout { fail "(timeout) ptype unsigned char array" }
+#}
+#
+#
+#
+#send "ptype v_int_array\n"
+#gdb_expect {
+# -re "type = int .2..*$gdb_prompt $" { pass "ptype int array" }
+# -re ".*$gdb_prompt $" { fail "ptype int array" }
+# timeout { fail "(timeout) ptype int array" }
+#}
+#
+#
+#send "ptype v_signed_int_array\n"
+#gdb_expect {
+# -re "type = int .2..*$gdb_prompt $" { pass "ptype signed int array" }
+# -re ".*$gdb_prompt $" { fail "ptype signed int array" }
+# timeout { fail "(timeout) ptype signed int array" }
+#}
+#
+#
+#send "ptype v_unsigned_int_array\n"
+#gdb_expect {
+# -re "type = unsigned int .2..*$gdb_prompt $" { pass "ptype unsigned int array" }
+# -re ".*$gdb_prompt $" { fail "ptype unsigned int array" }
+# timeout { fail "(timeout) ptype unsigned int array" }
+#}
+#
+#
+#send "ptype v_long_array\n"
+#gdb_expect {
+# -re "type = (long|int|long int) .2..*$gdb_prompt $" {
+# pass "ptype long array" }
+# -re ".*$gdb_prompt $" { fail "ptype long array" }
+# timeout { fail "(timeout) ptype long array" }
+#}
+#
+#
+#send "ptype v_signed_long_array\n"
+#gdb_expect {
+# -re "type = (long|int|long int) .2..*$gdb_prompt $" {
+# pass "ptype signed long array" }
+# -re ".*$gdb_prompt $" { fail "ptype signed long array" }
+# timeout { fail "(timeout) ptype signed long array" }
+#}
+#
+#
+#send "ptype v_unsigned_long_array\n"
+#gdb_expect {
+# -re "type = unsigned long .2..*$gdb_prompt $" { pass "ptype unsigned long array" }
+# -re ".*$gdb_prompt $" { fail "ptype unsigned long array" }
+# timeout { fail "(timeout) ptype unsigned long array" }
+#}
+#
+#
+#send "ptype v_float_array\n"
+#gdb_expect {
+# -re "type = float .2..*$gdb_prompt $" { pass "ptype float array" }
+# -re ".*$gdb_prompt $" { fail "ptype float array" }
+# timeout { fail "(timeout) ptype float array" }
+#}
+#
+#
+#send "ptype v_double_array\n"
+#gdb_expect {
+# -re "type = double .2..*$gdb_prompt $" { pass "ptype double array" }
+# -re ".*$gdb_prompt $" { fail "ptype double array" }
+# timeout { fail "(timeout) ptype double array" }
+#}
+#
+
+if {!$gcc_compiled} then { setup_xfail "rs6000-*-*" "i*86-*-sysv4*" }
+setup_xfail_format "DWARF 1"
+gdb_test "ptype t_char_array" "type = (|unsigned )char \\\[0?\\\]"
+
+#
+##
+## test ptype command with pointers
+##
+#setup_xfail "i960-*-*" 1821
+#setup_xfail "mips-idt-*" "mips-sgi-*" "a29k-*-*"
+#send "ptype v_char_pointer\n"
+#gdb_expect {
+# -re "type = char \*.*$gdb_prompt $" { pass "ptype char pointer" }
+# -re ".*$gdb_prompt $" { fail "ptype char pointer" }
+# timeout { fail "(timeout) ptype char pointer" }
+#}
+#
+#
+#setup_xfail "mips-*-*" "a29k-*-*"
+#send "ptype v_signed_char_pointer\n"
+#gdb_expect {
+# -re "type = (|signed )char \*.*$gdb_prompt $"
+# { pass "ptype signed char pointer" }
+# -re ".*$gdb_prompt $" { fail "ptype signed char pointer" }
+# timeout { fail "(timeout) ptype signed char pointer" }
+#}
+#
+#
+#send "ptype v_unsigned_char_pointer\n"
+#gdb_expect {
+# -re "type = unsigned char \*.*$gdb_prompt $" { pass "ptype unsigned char pointer" }
+# -re ".*$gdb_prompt $" { fail "ptype unsigned char pointer" }
+# timeout { fail "(timeout) ptype unsigned char pointer" }
+#}
+#
+#
+#send "ptype v_short_pointer\n"
+#gdb_expect {
+# -re "type = (short|short int) \*.*$gdb_prompt $" { pass "ptype short pointer" }
+# -re ".*$gdb_prompt $" { fail "ptype short pointer" }
+# timeout { fail "(timeout) ptype short pointer" }
+#}
+#
+#
+#send "ptype v_signed_short_pointer\n"
+#gdb_expect {
+# -re "type = short \*.*$gdb_prompt $" { pass "ptype signed short pointer" }
+# -re ".*$gdb_prompt $" { fail "ptype signed short pointer" }
+# timeout { fail "(timeout) ptype signed short pointer" }
+#}
+#
+#
+#send "ptype v_unsigned_short_pointer\n"
+#gdb_expect {
+# -re "type = unsigned short \*.*$gdb_prompt $" { pass "ptype unsigned short pointer" }
+# -re ".*$gdb_prompt $" { fail "ptype unsigned short pointer" }
+# timeout { fail "(timeout) ptype unsigned short pointer" }
+#}
+#
+#
+#send "ptype v_int_pointer\n"
+#gdb_expect {
+# -re "type = int \*.*$gdb_prompt $" { pass "ptype int pointer" }
+# -re ".*$gdb_prompt $" { fail "ptype int pointer" }
+# timeout { fail "(timeout) ptype int pointer" }
+#}
+#
+#
+#send "ptype v_signed_int_pointer\n"
+#gdb_expect {
+# -re "type = int \*.*$gdb_prompt $" { pass "ptype signed int pointer" }
+# -re ".*$gdb_prompt $" { fail "ptype signed int pointer" }
+# timeout { fail "(timeout) ptype signed int pointer" }
+#}
+#
+#
+#send "ptype v_unsigned_int_pointer\n"
+#gdb_expect {
+# -re "type = unsigned int \*.*$gdb_prompt $" { pass "ptype unsigned int pointer" }
+# -re ".*$gdb_prompt $" { fail "ptype unsigned int pointer" }
+# timeout { fail "(timeout) ptype unsigned int pointer" }
+#}
+#
+#
+#send "ptype v_long_pointer\n"
+#gdb_expect {
+# -re "type = long \*.*$gdb_prompt $" { pass "ptype long pointer" }
+# -re ".*$gdb_prompt $" { fail "ptype long pointer" }
+# timeout { fail "(timeout) ptype long pointer" }
+#}
+#
+#
+#send "ptype v_signed_long_pointer\n"
+#gdb_expect {
+# -re "type = long \*.*$gdb_prompt $" { pass "ptype signed long pointer" }
+# -re ".*$gdb_prompt $" { fail "ptype signed long pointer" }
+# timeout { fail "(timeout) ptype signed long pointer" }
+#}
+#
+#
+#send "ptype v_unsigned_long_pointer\n"
+#gdb_expect {
+# -re "type = unsigned long \*.*$gdb_prompt $" { pass "ptype unsigned long pointer" }
+# -re ".*$gdb_prompt $" { fail "ptype unsigned long pointer" }
+# timeout { fail "(timeout) ptype unsigned long pointer" }
+#}
+#
+#
+#send "ptype v_float_pointer\n"
+#gdb_expect {
+# -re "type = float \*.*$gdb_prompt $" { pass "ptype float pointer" }
+# -re ".*$gdb_prompt $" { fail "ptype float pointer" }
+# timeout { fail "(timeout) ptype float pointer" }
+#}
+#
+#
+#send "ptype v_double_pointer\n"
+#gdb_expect {
+# -re "type = double \*.*$gdb_prompt $" { pass "ptype double pointer" }
+# -re ".*$gdb_prompt $" { fail "ptype double pointer" }
+# timeout { fail "(timeout) ptype double pointer" }
+#}
+
+#
+# test ptype command with nested structure and union
+#
+gdb_test "ptype struct outer_struct" "type = struct outer_struct \{.*\[\r\n\] int outer_int;.*\[\r\n\] struct inner_struct inner_struct_instance;.*\[\r\n\] union inner_union inner_union_instance;.*\[\r\n\] (long|long int|int) outer_long;.*\[\r\n\]\}.*" "ptype outer structure"
+
+gdb_test "ptype struct inner_struct" "type = struct inner_struct \{.*\[\r\n\] int inner_int;.*\[\r\n\] (long|long int|int) inner_long;.*\[\r\n\]\}.*" "ptype inner structure"
+
+gdb_test "ptype union inner_union" "type = union inner_union \{.*\[\r\n\] int inner_union_int;.*\[\r\n\] (long|long int|int) inner_union_long;.*\[\r\n\]\}.*" "ptype inner union"
+
+gdb_test "ptype nested_su" "type = struct outer_struct \{.*\[\r\n\] int outer_int;.*\[\r\n\] struct inner_struct inner_struct_instance;.*\[\r\n\] union inner_union inner_union_instance;.*\[\r\n\] (long|long int|int) outer_long;.*\[\r\n\]\}.*" "ptype nested structure"
+
+gdb_test "ptype nested_su.outer_int" "type = int.*" "ptype outer int"
+
+gdb_test "ptype nested_su.inner_struct_instance" "type = struct inner_struct \{.*\[\r\n\] int inner_int;.*\[\r\n\] (long|long int|int) inner_long;.*\[\r\n\]\}.*" "ptype nested structure #2"
+
+gdb_test "ptype nested_su.inner_struct_instance.inner_int" "type = int.*" "ptype inner int"
+
+gdb_test "ptype nested_su.inner_union_instance" "type = union inner_union \{.*\[\r\n\] int inner_union_int;.*\[\r\n\] (long|long int|int) inner_union_long;.*\[\r\n\]\}.*" "ptype nested union"
+
+# Test printing type of string constants and array constants, but
+# requires a running process. These call malloc, and can take a long
+# time to execute over a slow serial link, so increase the timeout.
+
+# UDI can't do this (PR 2416). XFAIL is not suitable, because attempting
+# the operation causes a slow painful death rather than a nice simple failure.
+
+if [runto_main] then {
+
+ get_debug_format
+ if [target_info exists gdb,cannot_call_functions] {
+ setup_xfail "*-*-*" 2416
+ fail "This target can not call functions"
+ continue
+ }
+
+ gdb_test "ptype \"abc\"" "type = char \\\[4\\\]"
+ gdb_test "ptype {'a','b','c'}" "type = char \\\[3\\\]"
+ gdb_test "ptype {0,1,2}" "type = int \\\[3\\\]"
+ gdb_test "ptype {(long)0,(long)1,(long)2}" "type = long \\\[3\\\]"
+ gdb_test "ptype {(float)0,(float)1,(float)2}" "type = float \\\[3\\\]"
+ gdb_test "ptype {{0,1,2},{3,4,5}}" "type = int \\\[2\\\]\\\[3\\\]"
+ gdb_test "ptype {4,5,6}\[2\]" "type = int"
+ gdb_test "ptype *&{4,5,6}\[1\]" "type = int"
+}
diff --git a/gdb/testsuite/gdb.base/radix.exp b/gdb/testsuite/gdb.base/radix.exp
new file mode 100644
index 00000000000..f81bde2b728
--- /dev/null
+++ b/gdb/testsuite/gdb.base/radix.exp
@@ -0,0 +1,201 @@
+# Copyright (C) 1993, 1997 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file was written by Fred Fish. (fnf@cygnus.com)
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+set prms_id 0
+set bug_id 0
+
+proc test_input_radix_2 {} {
+ gdb_test "set radix" \
+ "Input and output radices now set to decimal 10, hex a, octal 12." \
+ "set radix #1"
+ gdb_test "set input-radix 2" \
+ "Input radix now set to decimal 2, hex 2, octal 2."
+ gdb_test "show radix" \
+ "Input radix set to decimal 2, hex 2, octal 2.\r\nOutput radix set to decimal 10, hex a, octal 12." \
+ "show radix #1"
+ gdb_test "p 010" "8"
+ gdb_test "p 20." "20"
+ gdb_test "p (int) 20." "20"
+ gdb_test "p 0xf" "15"
+ gdb_test "p 10" "2"
+ gdb_test "p -101" "-5"
+ gdb_test "p 101" "5"
+ gdb_test "p 10101" "21"
+ gdb_test "p 4" "Invalid number \"4\"\\."
+ gdb_test "p -2" "Invalid number \"2\"\\."
+}
+
+# Test input radix 3 (an non-typical radix)
+
+proc test_input_radix_3 {} {
+ gdb_test "set radix" \
+ "Input and output radices now set to decimal 10, hex a, octal 12." \
+ "set radix #2"
+ gdb_test "set input-radix 3" \
+ "Input radix now set to decimal 3, hex 3, octal 3."
+ gdb_test "show radix" \
+ "Input radix set to decimal 3, hex 3, octal 3.\r\nOutput radix set to decimal 10, hex a, octal 12." \
+ "show radix #2"
+ gdb_test "p 010" "8"
+ gdb_test "p 20." "20"
+ gdb_test "p (int) 20." "20"
+ gdb_test "p 0xf" "15"
+ gdb_test "p 10" "3"
+ gdb_test "p 0" "0"
+ gdb_test "p 1" "1"
+ gdb_test "p 2" "2"
+ gdb_test "p 10" "3"
+ gdb_test "p 20" "6"
+ gdb_test "p 100" "9"
+ gdb_test "p -100" "-9"
+ gdb_test "p 3" "Invalid number \"3\"."
+ gdb_test "p 30" "Invalid number \"30\"."
+}
+
+proc test_input_radix_8 {} {
+ gdb_test "set radix" \
+ "Input and output radices now set to decimal 10, hex a, octal 12." \
+ "set radix #3"
+ gdb_test "set input-radix 8" \
+ "Input radix now set to decimal 8, hex 8, octal 10."
+ gdb_test "show radix" \
+ "Input radix set to decimal 8, hex 8, octal 10.\r\nOutput radix set to decimal 10, hex a, octal 12." \
+ "set radix #3"
+ gdb_test "p 010" "8"
+ gdb_test "p 20." "20"
+ gdb_test "p (int) 20." "20"
+ gdb_test "p 0xf" "15"
+ gdb_test "p 10" "8"
+ gdb_test "p 20" "16"
+ gdb_test "p -20" "-16"
+ gdb_test "p 100" "64"
+ gdb_test "p 8" "Invalid number \"8\"."
+ gdb_test "p -9" "Invalid number \"9\"."
+}
+
+proc test_input_radix_10 {} {
+ gdb_test "set radix" \
+ "Input and output radices now set to decimal 10, hex a, octal 12." \
+ "set radix #4"
+ gdb_test "set input-radix 10" \
+ "Input radix now set to decimal 10, hex a, octal 12."
+ gdb_test "show radix" \
+ "Input and output radices set to decimal 10, hex a, octal 12." \
+ "show radix #4"
+ gdb_test "p 010" "8"
+ gdb_test "p 20." "20"
+ gdb_test "p (int) 20." "20"
+ gdb_test "p 0xf" "15"
+ gdb_test "p 10" "10"
+ gdb_test "p -12" "-12"
+}
+
+proc test_input_radix_16 {} {
+ gdb_test "set radix" \
+ "Input and output radices now set to decimal 10, hex a, octal 12." \
+ "set radix #5"
+ gdb_test "set input-radix 16" \
+ "Input radix now set to decimal 16, hex 10, octal 20."
+ gdb_test "show radix" \
+ "Input radix set to decimal 16, hex 10, octal 20.\r\nOutput radix set to decimal 10, hex a, octal 12." \
+ "show radix #5"
+ gdb_test "p 010" "8"
+ gdb_test "p 20." "20"
+ gdb_test "p (int) 20." "20"
+ gdb_test "p 0xf" "15"
+ gdb_test "p 10" "16"
+ gdb_test "p 100" "256"
+}
+
+proc test_output_radix_8 {} {
+ gdb_test "set radix" \
+ "Input and output radices now set to decimal 10, hex a, octal 12." \
+ "set radix #6"
+ gdb_test "set output-radix 8" \
+ "Output radix now set to decimal 8, hex 8, octal 10."
+ gdb_test "show radix" \
+ "Input radix set to decimal 10, hex a, octal 12.\r\nOutput radix set to decimal 8, hex 8, octal 10." \
+ "show radix #6"
+ gdb_test "p 010" "010"
+ # FIXME: If gdb can't handle float printing in different radices, it
+ # should at least warn once the first time that is attempted.
+ setup_xfail "*-*-*"
+ gdb_test "p 20." "24" "Float printing when output radix is 8"
+ gdb_test "p (int) 20." "24"
+ gdb_test "p 0xf" "17"
+ gdb_test "p 10" "12"
+ gdb_test "p 100" "144"
+}
+
+proc test_output_radix_10 {} {
+ gdb_test "set radix" \
+ "Input and output radices now set to decimal 10, hex a, octal 12." \
+ "set radix #7"
+ gdb_test "set output-radix 10" \
+ "Output radix now set to decimal 10, hex a, octal 12."
+ gdb_test "show radix" \
+ "Input and output radices set to decimal 10, hex a, octal 12." \
+ "show radix #7"
+ gdb_test "p 010" "8"
+ gdb_test "p 20." "20"
+ gdb_test "p (int) 20." "20"
+ gdb_test "p 0xf" "15"
+ gdb_test "p 10" "10"
+ gdb_test "p 100" "100"
+}
+
+proc test_output_radix_16 {} {
+ gdb_test "set radix" \
+ "Input and output radices now set to decimal 10, hex a, octal 12." \
+ "set radix #8"
+ gdb_test "set output-radix 16" \
+ "Output radix now set to decimal 16, hex 10, octal 20."
+ gdb_test "show radix" \
+ "Input radix set to decimal 10, hex a, octal 12.\r\nOutput radix set to decimal 16, hex 10, octal 20." \
+ "show radix #8"
+ gdb_test "p 010" "8"
+ # FIXME: If gdb can't handle float printing in different radices, it
+ # should at least warn once the first time that is attempted.
+ setup_xfail "*-*-*"
+ gdb_test "p 20." "14" "Float printing when output radix is 16"
+ gdb_test "p (int) 20." "14"
+ gdb_test "p 0xf" "f"
+ gdb_test "p 10" "a"
+ gdb_test "p 100" "64"
+}
+
+# Start with a fresh gdb.
+
+gdb_exit
+gdb_start
+
+test_input_radix_2
+test_input_radix_3
+test_input_radix_8
+test_input_radix_10
+test_input_radix_16
+test_output_radix_8
+test_output_radix_10
+test_output_radix_16
diff --git a/gdb/testsuite/gdb.base/recurse.c b/gdb/testsuite/gdb.base/recurse.c
new file mode 100644
index 00000000000..1d6892d0f69
--- /dev/null
+++ b/gdb/testsuite/gdb.base/recurse.c
@@ -0,0 +1,25 @@
+/* Trivial code used to test watchpoints in recursive code and
+ auto-deletion of watchpoints as they go out of scope. */
+
+static int
+recurse (a)
+ int a;
+{
+ int b = 0;
+
+ if (a == 1)
+ return 1;
+
+ b = a;
+ b *= recurse (a - 1);
+ return b;
+}
+
+main()
+{
+#ifdef usestubs
+ set_debug_traps();
+ breakpoint();
+#endif
+ recurse (10);
+}
diff --git a/gdb/testsuite/gdb.base/recurse.exp b/gdb/testsuite/gdb.base/recurse.exp
new file mode 100644
index 00000000000..88e1b30ee96
--- /dev/null
+++ b/gdb/testsuite/gdb.base/recurse.exp
@@ -0,0 +1,145 @@
+# Copyright (C) 1992, 1996, 1997 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file was written by Jeff Law. (law@cs.utah.edu)
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+set prms_id 0
+set bug_id 0
+
+set testfile "recurse"
+set srcfile ${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+# Start with a fresh gdb.
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+proc recurse_tests {} {
+
+ if [runto recurse] then {
+ # First we need to step over the assignment of b, so it has a known
+ # value.
+ gdb_test "next" "if \\(a == 1\\)" "next over b = 0 in first instance"
+ gdb_test "watch b" ".*\[Ww\]atchpoint \[0-9]*: b" \
+ "set first instance watchpoint"
+
+ # Continue until initial set of b.
+ if [gdb_test "continue" \
+ "Continuing.*\[Ww\]atchpoint.*: b.*Old value = 0.*New value = 10.*" \
+ "continue to first instance watchpoint, first time"] then {
+ gdb_suppress_tests;
+ }
+
+ # Continue inward for a few iterations
+ gdb_test "continue" "Breakpoint.* recurse \\(a=9\\).*" \
+ "continue to recurse (a = 9)"
+ gdb_test "continue" "Breakpoint.* recurse \\(a=8\\).*" \
+ "continue to recurse (a = 8)"
+ gdb_test "continue" "Breakpoint.* recurse \\(a=7\\).*" \
+ "continue to recurse (a = 7)"
+ gdb_test "continue" "Breakpoint.* recurse \\(a=6\\).*" \
+ "continue to recurse (a = 6)"
+ gdb_test "continue" "Breakpoint.* recurse \\(a=5\\).*" \
+ "continue to recurse (a = 5)"
+
+ # Put a watchpoint on another instance of b
+ # First we need to step over the assignment of b, so it has a known
+ # value.
+ gdb_test "next" "if \\(a == 1\\)" "next over b = 0 in second instance"
+ gdb_test "watch b" ".*\[Ww\]atchpoint \[0-9]*: b" \
+ "set second instance watchpoint"
+
+ # Continue until initial set of b (second instance).
+ if [gdb_test "continue" \
+ "Continuing.*\[Ww\]atchpoint.*: b.*Old value = 0.*New value = 5.*"\
+ "continue to second instance watchpoint, first time"] then {
+ gdb_suppress_tests;
+ }
+
+ # Continue inward for a few iterations
+ gdb_test "continue" "Breakpoint.* recurse \\(a=4\\).*" \
+ "continue to recurse (a = 4)"
+ gdb_test "continue" "Breakpoint.* recurse \\(a=3\\).*" \
+ "continue to recurse (a = 3)"
+ gdb_test "continue" "Breakpoint.* recurse \\(a=2\\).*" \
+ "continue to recurse (a = 2)"
+ gdb_test "continue" "Breakpoint.* recurse \\(a=1\\).*" \
+ "continue to recurse (a = 1)"
+
+ # Continue until second set of b (second instance).
+ if [gdb_test "continue" \
+ "Continuing.*\[Ww\]atchpoint.*: b.*Old value = 5.*New value = 120.*return.*" \
+ "continue to second instance watchpoint, second time"] then {
+ gdb_suppress_tests;
+ }
+
+ # Continue again. We should have a watchpoint go out of scope now
+ if [gdb_test "continue" \
+ "Continuing.*\[Ww\]atchpoint.*deleted.*recurse \\(a=6\\) .*" \
+ "second instance watchpoint deleted when leaving scope"] then {
+ gdb_suppress_tests;
+ }
+
+ # Continue until second set of b (first instance).
+ # 24320 is allowed as the final value for b as that's the value
+ # b would have on systems with 16bit integers.
+ #
+ # We could fix the test program to deal with this too.
+ if [gdb_test "continue" \
+ "Continuing.*\[Ww\]atchpoint.*b.*Old value = 10.*New value = \(3628800|24320\).*return.*" \
+ "continue to first instance watchpoint, second time"] then {
+ gdb_suppress_tests
+ }
+
+ # Continue again. We should have a watchpoint go out of scope now
+ if [gdb_test "continue" \
+ "Continuing.*\[Ww\]atchpoint.*deleted.*main \\(\\) .*" \
+ "first instance watchpoint deleted when leaving scope"] then {
+ gdb_suppress_tests;
+ }
+ }
+ gdb_stop_suppressing_tests;
+}
+
+# Only enabled for some targets merely because it has not been tested
+# elsewhere.
+if {[istarget "sparc*-*-sunos4*"] || [istarget "hppa*-*-bsd*"] || [istarget "hppa*-*-hpux*"] || [istarget "sparclet-*-*"] || [istarget "m32r-*-elf"] || [istarget "mn10200-*-*"] || [istarget "mn10300-*-*"]} then {
+
+ # Preserve the old timeout, and set a new one that should be
+ # sufficient to avoid timing out during this test.
+ set oldtimeout $timeout
+ set timeout [expr "$timeout + 60"]
+ verbose "Timeout is now $timeout seconds" 2
+
+ recurse_tests
+
+ # Restore the preserved old timeout value.
+ set timeout $oldtimeout
+ verbose "Timeout is now $timeout seconds" 2
+}
diff --git a/gdb/testsuite/gdb.base/regs.exp b/gdb/testsuite/gdb.base/regs.exp
new file mode 100644
index 00000000000..548b9354715
--- /dev/null
+++ b/gdb/testsuite/gdb.base/regs.exp
@@ -0,0 +1,86 @@
+# Tests of register displays for GDB.
+# Copyright 1994, 1995, 1997 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file was written by Stan Shebs. (shebs@cygnus.com)
+
+# This does not (yet) have an associated executable, since the IDT board
+# will display registers even without a program being loaded.
+# A more comprehensive register test would actually test reading
+# and writing of registers in a real program, although some care
+# would be required in the writing of the tests.
+
+if $tracelevel then {
+ strace $tracelevel
+ }
+
+# These tests exercise IDT-specific MIPS registers for several
+# different processor models.
+
+# This should detect the actual processor in use and change
+# the expected results appropriately. FIXME
+
+proc idt_register_tests { } {
+ # Test the generic IDT chip.
+ gdb_test "info registers" ".*"
+ gdb_test "info register zero" "zero(r0): 0x0;"
+ # FIXME access each generic register individually
+ # Test the 3041.
+ gdb_test "set processor r3041" ".*"
+ gdb_test "info registers" ".*"
+ gdb_test "info register bus" "bus.*0x.*"
+ gdb_test "info register ccfg" "ccfg.*0x.*"
+ gdb_test "info register port" "port.*0x.*"
+ gdb_test "info register cmp" "cmp.*0x.*"
+ gdb_test "info register elo" "elo: invalid register"
+ gdb_test "info register ehi" "ehi: invalid register"
+ gdb_test "info register cfg" "cfg: invalid register"
+ gdb_test "info register ctxt" "ctxt: invalid register"
+ # Test the 3051.
+ gdb_test "set processor r3051" ".*"
+ gdb_test "info registers" ".*"
+ gdb_test "info register bus" "bus: invalid register"
+ gdb_test "info register ccfg" "ccfg: invalid register"
+ gdb_test "info register port" "port: invalid register"
+ gdb_test "info register cmp" "cmp: invalid register"
+ gdb_test "info register elo" "elo.*0x.*"
+ gdb_test "info register ehi" "ehi.*0x.*"
+ gdb_test "info register cfg" "cfg: invalid register"
+ gdb_test "info register ctxt" "ctxt: invalid register"
+ # Test the 3071.
+ gdb_test "set processor r3071" ".*"
+ gdb_test "info registers" ".*"
+ gdb_test "info register bus" "bus: invalid register"
+ gdb_test "info register ccfg" "ccfg: invalid register"
+ gdb_test "info register port" "port: invalid register"
+ gdb_test "info register cmp" "cmp: invalid register"
+ gdb_test "info register elo" "elo.*0x.*"
+ gdb_test "info register ehi" "ehi.*0x.*"
+ gdb_test "info register cfg" "cfg.*0x.*"
+ gdb_test "info register ctxt" "ctxt.*0x.*"
+}
+
+if [istarget "mips*-idt-*"] then {
+ gdb_exit
+ gdb_start
+ gdb_reinitialize_dir $srcdir/$subdir
+ idt_register_tests
+} else {
+ verbose "regs.exp tests ignored for this target"
+}
diff --git a/gdb/testsuite/gdb.base/relational.exp b/gdb/testsuite/gdb.base/relational.exp
new file mode 100644
index 00000000000..6a0b38acad0
--- /dev/null
+++ b/gdb/testsuite/gdb.base/relational.exp
@@ -0,0 +1,481 @@
+# Copyright (C) 1998 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file was written by Elena Zannoni (ezannoni@cygnus.com)
+
+# This file is part of the gdb testsuite
+#
+# tests for correctenss of relational operators, associativity and precedence
+# with integer type variables
+#
+
+if $tracelevel then {
+ strace $tracelevel
+ }
+
+#
+# test running programs
+#
+set prms_id 0
+set bug_id 0
+
+set testfile "int-type"
+set srcfile ${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug additional_flags=-w}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+ }
+
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+
+#
+# set it up at a breakpoint so we can play with the variable values
+#
+
+if ![runto_main] then {
+ perror "couldn't run to breakpoint"
+ continue
+}
+
+#
+# test expressions with "int" types
+#
+
+gdb_test "set variable x=14" "" "set variable x=14"
+gdb_test "set variable y=2" "" "set variable y=2"
+gdb_test "set variable z=2" "" "set variable z=2"
+gdb_test "set variable w=3" "" "set variable w=3"
+
+send_gdb "print x\n"
+gdb_expect {
+ -re ".*14.*$gdb_prompt $" {
+ pass "print value of x"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of x" }
+ timeout { fail "(timeout) print value of x" }
+ }
+
+
+send_gdb "print y\n"
+gdb_expect {
+ -re ".*2.*$gdb_prompt $" {
+ pass "print value of y"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of y" }
+ timeout { fail "(timeout) print value of y" }
+ }
+
+send_gdb "print z\n"
+gdb_expect {
+ -re ".*2.*$gdb_prompt $" {
+ pass "print value of z"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of z" }
+ timeout { fail "(timeout) print value of z" }
+ }
+
+send_gdb "print w\n"
+gdb_expect {
+ -re ".*3.*$gdb_prompt $" {
+ pass "print value of w"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of w" }
+ timeout { fail "(timeout) print value of w" }
+ }
+
+
+
+send_gdb "print x < y\n"
+gdb_expect {
+ -re ".*0.*$gdb_prompt $" {
+ pass "print value of x<y"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of x<y" }
+ timeout { fail "(timeout) print value of x<y" }
+ }
+
+send_gdb "print x <= y\n"
+gdb_expect {
+ -re ".*0.*$gdb_prompt $" {
+ pass "print value of x<=y"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of x<=y" }
+ timeout { fail "(timeout) print value of x<=y" }
+ }
+
+send_gdb "print x > y\n"
+gdb_expect {
+ -re ".*1.*$gdb_prompt $" {
+ pass "print value of x>y"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of x>y" }
+ timeout { fail "(timeout) print value of x>y" }
+ }
+
+send_gdb "print x >= y\n"
+gdb_expect {
+ -re ".*1.*$gdb_prompt $" {
+ pass "print value of x>=y"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of x>=y" }
+ timeout { fail "(timeout) print value of x>=y" }
+ }
+
+send_gdb "print x == y\n"
+gdb_expect {
+ -re ".*0.*$gdb_prompt $" {
+ pass "print value of x==y"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of x==y" }
+ timeout { fail "(timeout) print value of x==y" }
+ }
+
+send_gdb "print x != y\n"
+gdb_expect {
+ -re ".*1.*$gdb_prompt $" {
+ pass "print value of x!=y"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of x!=y" }
+ timeout { fail "(timeout) print value of x!=y" }
+ }
+
+
+
+# Test associativity of <, >, <=, >=, ==, !=
+
+gdb_test "set variable x=3" "" "set variable x"
+gdb_test "set variable y=5" "" "set variable y"
+gdb_test "set variable z=2" "" "set variable z"
+
+
+
+send_gdb "print x < y < z\n"
+gdb_expect {
+ -re ".*1\r\n$gdb_prompt $" {
+ pass "print value of x<y<z"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of x<y<z" }
+ timeout { fail "(timeout) print value of x<y<z" }
+ }
+
+send_gdb "print x <= y <= z\n"
+gdb_expect {
+ -re ".*1\r\n$gdb_prompt $" {
+ pass "print value of x<=y<=z"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of x<=y<=z" }
+ timeout { fail "(timeout) print value of x<=y<=z" }
+ }
+
+send_gdb "print x > y > z\n"
+gdb_expect {
+ -re ".*0\r\n$gdb_prompt $" {
+ pass "print value of x>y>z"
+ }
+ -re 8".*$gdb_prompt $" { fail "print value of x>y>z" }
+ timeout { fail "(timeout) print value of x>y>z" }
+ }
+
+send_gdb "print x >= y >= z\n"
+gdb_expect {
+ -re ".*0\r\n$gdb_prompt $" {
+ pass "print value of x>=y>=z"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of x>=y>=z" }
+ timeout { fail "(timeout) print value of x>=y>=z" }
+ }
+
+gdb_test "set variable x=2" "" "set variable x"
+gdb_test "set variable y=2" "" "set variable y"
+gdb_test "set variable z=1" "" "set variable z"
+
+
+send_gdb "print x == y == z\n"
+gdb_expect {
+ -re ".*1.*$gdb_prompt $" {
+ pass "print value of x==y==z"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of x==y==z" }
+ timeout { fail "(timeout) print value of x==y==z" }
+ }
+
+gdb_test "set variable z=0" "" "set variable z"
+
+
+send_gdb "print x != y != z\n"
+gdb_expect {
+ -re ".*0\r\n$gdb_prompt $" {
+ pass "print value of x!=y!=z"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of x!=y!=z" }
+ timeout { fail "(timeout) print value of x!=y!=z" }
+ }
+
+
+# test precedence rules on pairs of relational operators
+
+gdb_test "set variable x=0" "" "set variable x"
+gdb_test "set variable y=2" "" "set variable y"
+gdb_test "set variable z=2" "" "set variable z"
+
+
+send_gdb "print x < y == z\n"
+gdb_expect {
+ -re ".*0.*$gdb_prompt $" {
+ pass "print value of x<y==z"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of x<y==z" }
+ timeout { fail "(timeout) print value of x<y==z" }
+ }
+
+# 0 2 2
+send_gdb "print x < y != z\n"
+gdb_expect {
+ -re ".*1.*$gdb_prompt $" {
+ pass "print value of x<y!=z"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of x<y!=z" }
+ timeout { fail "(timeout) print value of x<y!=z" }
+ }
+
+gdb_test "set variable x=2" "" "set variable x"
+gdb_test "set variable y=3" "" "set variable y"
+gdb_test "set variable z=1" "" "set variable z"
+
+
+# 2 3 1
+send_gdb "print x < y <= z\n"
+gdb_expect {
+ -re ".*1.*$gdb_prompt $" {
+ pass "print value of x<y<=z"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of x<y<=z" }
+ timeout { fail "(timeout) print value of x<y<=z" }
+ }
+
+
+# 2 3 1
+send_gdb "print x < y >= z\n"
+gdb_expect {
+ -re ".*1.*$gdb_prompt $" {
+ pass "print value of x<y>=z"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of x<y>=z" }
+ timeout { fail "(timeout) print value of x<y>=z" }
+ }
+
+
+gdb_test "set variable z=0" "" " set variable z"
+
+
+# 2 3 0
+send_gdb "print x < y > z\n"
+gdb_expect {
+ -re ".*1.*$gdb_prompt $" {
+ pass "print value of x<y>z"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of x<y>z" }
+ timeout { fail "(timeout) print value of x<y>z" }
+ }
+
+
+gdb_test "set variable x=1" "" " set variable x"
+
+# 1 3 0
+send_gdb "print x > y >= z\n"
+gdb_expect {
+ -re ".*1.*$gdb_prompt $" {
+ pass "print value of x>y>=z"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of x>y>=z" }
+ timeout { fail "(timeout) print value of x>y>=z" }
+ }
+
+
+gdb_test "set variable z=2" "" " set variable z"
+
+# 1 3 2
+send_gdb "print x > y == z\n"
+gdb_expect {
+ -re ".*0.*$gdb_prompt $" {
+ pass "print value of x>y==z"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of x>y==z" }
+ timeout { fail "(timeout) print value of x>y==z" }
+ }
+
+
+gdb_test "set variable x=2" "" " set variable x"
+gdb_test "set variable z=0" "" " set variable z"
+
+# 2 3 0
+send_gdb "print x > y != z\n"
+gdb_expect {
+ -re ".*0.*$gdb_prompt $" {
+ pass "print value of x>y!=z"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of x>y!=z" }
+ timeout { fail "(timeout) print value of x>y!=z" }
+ }
+
+
+gdb_test "set variable x=4" "" "set x to 4"
+
+# 4 3 0
+send_gdb "print x > y <= z\n"
+gdb_expect {
+ -re ".*0.*$gdb_prompt $" {
+ pass "print value of x>y<=z"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of x>y<=z" }
+ timeout { fail "(timeout) print value of x>y<=z" }
+ }
+
+# 4 3 0
+send_gdb "print x >= y == z\n"
+gdb_expect {
+ -re ".*0\r\n$gdb_prompt $" {
+ pass "print value of x>=y==z"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of x>=y==z" }
+ timeout { fail "(timeout) print value of x>=y==z" }
+ }
+
+
+gdb_test "set variable x=2" "" " set variable x"
+
+# 2 3 0
+send_gdb "print x >= y != z\n"
+gdb_expect {
+ -re ".*0\r\n$gdb_prompt $" {
+ pass "print value of x>=y!=z"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of x>=y!=z" }
+ timeout { fail "(timeout) print value of x>=y!=z" }
+ }
+
+
+gdb_test "set variable x=0" "" " set variable x"
+gdb_test "set variable z=4" "" " set variable z"
+
+# 0 3 4
+send_gdb "print x >= y <= z\n"
+gdb_expect {
+ -re ".*1\r\n$gdb_prompt $" {
+ pass "print value of x>=y<=z"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of x>=y<=z" }
+ timeout { fail "(timeout) print value of x>=y<=z" }
+ }
+
+# 0 3 4
+send_gdb "print x <= y == z\n"
+gdb_expect {
+ -re ".*0\r\n$gdb_prompt $" {
+ pass "print value of x<=y==z"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of x<=y==z" }
+ timeout { fail "(timeout) print value of x<=y==z" }
+ }
+
+gdb_test "set variable x=2" "" " set variable x"
+
+# 2 3 4
+send_gdb "print x <= y != z\n"
+gdb_expect {
+ -re ".*1\r\n$gdb_prompt $" {
+ pass "print value of x<=y!=z"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of x<=y!=z" }
+ timeout { fail "(timeout) print value of x<=y!=z" }
+ }
+
+
+# 2 3 4
+send_gdb "print x == y != z\n"
+gdb_expect {
+ -re ".*1\r\n$gdb_prompt $" {
+ pass "print value of x==y!=z"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of x==y!=z" }
+ timeout { fail "(timeout) print value of x==y!=z" }
+ }
+
+
+
+# test use of parenthesis to enforce different order of evaluation
+
+
+gdb_test "set variable z=0" "" " set variable z"
+
+# 2 3 0
+send_gdb "print x >= (y < z)\n"
+gdb_expect {
+ -re ".*1\r\n$gdb_prompt $" {
+ pass "print value of x>=(y<z)"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of x>=(y<z)" }
+ timeout { fail "(timeout) print value of x>=(y<z)" }
+ }
+
+
+# 2 3 0
+send_gdb "print x >= (y != z)\n"
+gdb_expect {
+ -re ".*1\r\n$gdb_prompt $" {
+ pass "print value of x>=(y!=z)"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of x>=(y*!=z)" }
+ timeout { fail "(timeout) print value of x>=(y!=z)" }
+ }
+
+# 2 3 0
+send_gdb "print x == (y == z)\n"
+gdb_expect {
+ -re ".*0\r\n$gdb_prompt $" {
+ pass "print value of x==(y==z)"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of x==(y==z)" }
+ timeout { fail "(timeout) print value of x==(y==z)" }
+ }
+
+
+gdb_test "set variable x=1" "" " set variable x"
+gdb_test "set variable z=4" "" " set variable z"
+
+# 1 3 4
+send_gdb "print (x == y) < z\n"
+gdb_expect {
+ -re ".*1\r\n$gdb_prompt $" {
+ pass "print value of (x==y)<z"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of (x==y)<z" }
+ timeout { fail "(timeout) print value of (x==y)<z" }
+ }
+
+
+
+
+
+
diff --git a/gdb/testsuite/gdb.base/reread.exp b/gdb/testsuite/gdb.base/reread.exp
new file mode 100644
index 00000000000..ccdabd5306a
--- /dev/null
+++ b/gdb/testsuite/gdb.base/reread.exp
@@ -0,0 +1,117 @@
+# Copyright (C) 1998 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+set prms_id 0
+set bug_id 0
+
+set prototypes 1
+
+# build the first test case
+
+set testfile1 "reread1"
+set srcfile1 ${testfile1}.c
+set binfile1 ${objdir}/${subdir}/${testfile1}
+
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile1}" "${binfile1}" executable {debug additional_flags=-w}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+# build the second test case
+
+set testfile2 "reread2"
+set srcfile2 ${testfile2}.c
+set binfile2 ${objdir}/${subdir}/${testfile2}
+
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile2}" "${binfile2}" executable {debug additional_flags=-w}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+# Start with a fresh gdb.
+
+set testfile "reread"
+set binfile ${objdir}/${subdir}/${testfile}
+
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+
+set prms_id 13484
+set bug_id 0
+
+# Load the first executable.
+
+gdb_test "shell mv ${binfile1} ${binfile}" "" ""
+gdb_load ${binfile}
+
+# Set a breakpoint at foo
+
+gdb_test "break foo" \
+ "Breakpoint.*at.* file .*$srcfile1, line 14.*" \
+ "breakpoint foo in first file"
+
+
+# Run, should see "Breakpoint 1, foo () at hello1.c:14"
+
+gdb_run_cmd
+
+gdb_expect {
+ -re ".*Breakpoint.* foo .* at .*$srcfile1:14.*$gdb_prompt $" {
+ pass "run to foo()";
+ }
+ -re ".*$gdb_prompt $" {
+ fail "run to foo()";
+ gdb_suppress_tests;
+ }
+ timeout { fail "run to foo() (timeout)" ; gdb_suppress_tests }
+}
+
+# Restore first executable to its original name, and move
+# second executable into its place. Ensure that the new
+# executable is at least a second older than the old.
+
+gdb_test "shell mv ${binfile} ${binfile1}" "" ""
+gdb_test "shell mv ${binfile2} ${binfile}" "" ""
+gdb_test "shell sleep 1" "" ""
+gdb_test "shell touch ${binfile}" "" ""
+
+# Run a second time; GDB should detect that the executable has changed
+# and reset the breakpoints correctly.
+# Should see "Breakpoint 1, foo () at reread2.c:9"
+
+gdb_run_cmd
+gdb_expect {
+# -re ".*re-reading symbols.*Breakpoint.* foo .* at .*$srcfile2:9.*$gdb_prompt $" {}
+ -re ".*Breakpoint.* foo .* at .*:9.*$gdb_prompt $" {
+ pass "run to foo() second time ";
+ }
+ -re ".*$gdb_prompt $" {
+ fail "run to foo() second time";
+ gdb_suppress_tests;
+ }
+ timeout { fail "run to foo() second time (timeout)" ; gdb_suppress_tests }
+}
+
+# End of tests.
+
+gdb_stop_suppressing_tests
+
+return 0
diff --git a/gdb/testsuite/gdb.base/reread1.c b/gdb/testsuite/gdb.base/reread1.c
new file mode 100644
index 00000000000..ae9801047d4
--- /dev/null
+++ b/gdb/testsuite/gdb.base/reread1.c
@@ -0,0 +1,26 @@
+/* pr 13484 */
+
+#include <stdio.h>
+
+int x;
+
+void bar()
+{
+ x--;
+}
+
+void foo()
+{
+ x++;
+}
+
+int main()
+{
+#ifdef usestubs
+ set_debug_traps ();
+ breakpoint ();
+#endif
+ foo();
+ bar();
+ return 0;
+}
diff --git a/gdb/testsuite/gdb.base/reread2.c b/gdb/testsuite/gdb.base/reread2.c
new file mode 100644
index 00000000000..fd9f7b7ad64
--- /dev/null
+++ b/gdb/testsuite/gdb.base/reread2.c
@@ -0,0 +1,21 @@
+/* pr 13484 */
+
+#include <stdio.h>
+
+int x;
+
+void foo()
+{
+ x++;
+ printf("This is foo\n");
+}
+
+int main()
+{
+#ifdef usestubs
+ set_debug_traps ();
+ breakpoint ();
+#endif
+ foo();
+ return 0;
+}
diff --git a/gdb/testsuite/gdb.base/restore.c b/gdb/testsuite/gdb.base/restore.c
new file mode 100644
index 00000000000..a65d648b9d0
--- /dev/null
+++ b/gdb/testsuite/gdb.base/restore.c
@@ -0,0 +1,260 @@
+/* Test GDB's ability to restore saved registers from stack frames
+ when using the `return' command.
+ Jim Blandy <jimb@cygnus.com> --- December 1998 */
+
+#include <stdio.h>
+
+/* This is the Emacs Lisp expression I used to generate the functions
+ in this file. If people modify the functions manually, instead of
+ changing this expression and re-running it, then evaluating this
+ expression could wipe out their work, so you probably shouldn't
+ re-run it. But I leave it here for reference.
+
+ (defun callee (n) (format "callee%d" n))
+ (defun caller (n) (format "caller%d" n))
+ (defun local (n) (format "l%d" n))
+ (defun local-sum (n)
+ (let ((j 1))
+ (while (<= j n)
+ (insert (local j))
+ (if (< j n) (insert "+"))
+ (setq j (1+ j)))))
+ (defun local-chain (n previous first-end)
+ (let ((j 1))
+ (while (<= j n)
+ (insert " register int " (local j)
+ " = increment (" previous ");")
+ (if first-end
+ (progn
+ (insert " /" "* " first-end " *" "/")
+ (setq first-end nil)))
+ (insert "\n")
+ (setq previous (local j))
+ (setq j (1+ j))))
+ previous)
+
+ (save-excursion
+ (let ((limit 5))
+ (goto-char (point-max))
+ (search-backward "generated code starts here")
+ (forward-line 1)
+ (let ((start (point)))
+ (search-forward "generated code ends here")
+ (forward-line 0)
+ (delete-region start (point)))
+
+ ;; Generate callee functions.
+ (let ((i 0))
+ (while (<= i limit)
+ (insert (format "/%s Returns n * %d + %d %s/\n"
+ "*" i (/ (+ i (* i i)) 2) "*"))
+ (insert "int\n")
+ (insert (callee i) " (int n)\n")
+ (insert "{\n")
+ (local-chain i "n" (callee i))
+ (insert " return ")
+ (if (<= i 0) (insert "n")
+ (local-sum i))
+ (insert ";\n")
+ (insert "}\n\n")
+ (setq i (1+ i))))
+
+ ;; Generate caller functions.
+ (let ((i 1))
+ (while (<= i limit)
+ (insert "int\n")
+ (insert (caller i) " (void)\n")
+ (insert "{\n")
+ (let ((last (local-chain i "0xfeeb" (caller i))))
+ (insert " register int n;\n")
+ (let ((j 0))
+ (while (<= j limit)
+ (insert " n = " (callee j) " ("
+ (if (> j 0) "n + " "")
+ last ");\n")
+ (setq j (1+ j)))))
+ (insert " return n+")
+ (local-sum i)
+ (insert ";\n")
+ (insert "}\n\n")
+ (setq i (1+ i))))
+
+ ;; Generate driver function.
+ (insert "void\n")
+ (insert "driver (void)\n")
+ (insert "{\n")
+ (let ((i 1))
+ (while (<= i limit)
+ (insert " printf (\"" (caller i) " () => %d\\n\", "
+ (caller i) " ());\n")
+ (setq i (1+ i))))
+ (insert "}\n\n")))
+
+ */
+
+int
+increment (int n)
+{
+ return n + 1;
+}
+
+/* generated code starts here */
+/* Returns n * 0 + 0 */
+int
+callee0 (int n)
+{
+ return n;
+}
+
+/* Returns n * 1 + 1 */
+int
+callee1 (int n)
+{
+ register int l1 = increment (n); /* callee1 */
+ return l1;
+}
+
+/* Returns n * 2 + 3 */
+int
+callee2 (int n)
+{
+ register int l1 = increment (n); /* callee2 */
+ register int l2 = increment (l1);
+ return l1+l2;
+}
+
+/* Returns n * 3 + 6 */
+int
+callee3 (int n)
+{
+ register int l1 = increment (n); /* callee3 */
+ register int l2 = increment (l1);
+ register int l3 = increment (l2);
+ return l1+l2+l3;
+}
+
+/* Returns n * 4 + 10 */
+int
+callee4 (int n)
+{
+ register int l1 = increment (n); /* callee4 */
+ register int l2 = increment (l1);
+ register int l3 = increment (l2);
+ register int l4 = increment (l3);
+ return l1+l2+l3+l4;
+}
+
+/* Returns n * 5 + 15 */
+int
+callee5 (int n)
+{
+ register int l1 = increment (n); /* callee5 */
+ register int l2 = increment (l1);
+ register int l3 = increment (l2);
+ register int l4 = increment (l3);
+ register int l5 = increment (l4);
+ return l1+l2+l3+l4+l5;
+}
+
+int
+caller1 (void)
+{
+ register int l1 = increment (0xfeeb); /* caller1 */
+ register int n;
+ n = callee0 (l1);
+ n = callee1 (n + l1);
+ n = callee2 (n + l1);
+ n = callee3 (n + l1);
+ n = callee4 (n + l1);
+ n = callee5 (n + l1);
+ return n+l1;
+}
+
+int
+caller2 (void)
+{
+ register int l1 = increment (0xfeeb); /* caller2 */
+ register int l2 = increment (l1);
+ register int n;
+ n = callee0 (l2);
+ n = callee1 (n + l2);
+ n = callee2 (n + l2);
+ n = callee3 (n + l2);
+ n = callee4 (n + l2);
+ n = callee5 (n + l2);
+ return n+l1+l2;
+}
+
+int
+caller3 (void)
+{
+ register int l1 = increment (0xfeeb); /* caller3 */
+ register int l2 = increment (l1);
+ register int l3 = increment (l2);
+ register int n;
+ n = callee0 (l3);
+ n = callee1 (n + l3);
+ n = callee2 (n + l3);
+ n = callee3 (n + l3);
+ n = callee4 (n + l3);
+ n = callee5 (n + l3);
+ return n+l1+l2+l3;
+}
+
+int
+caller4 (void)
+{
+ register int l1 = increment (0xfeeb); /* caller4 */
+ register int l2 = increment (l1);
+ register int l3 = increment (l2);
+ register int l4 = increment (l3);
+ register int n;
+ n = callee0 (l4);
+ n = callee1 (n + l4);
+ n = callee2 (n + l4);
+ n = callee3 (n + l4);
+ n = callee4 (n + l4);
+ n = callee5 (n + l4);
+ return n+l1+l2+l3+l4;
+}
+
+int
+caller5 (void)
+{
+ register int l1 = increment (0xfeeb); /* caller5 */
+ register int l2 = increment (l1);
+ register int l3 = increment (l2);
+ register int l4 = increment (l3);
+ register int l5 = increment (l4);
+ register int n;
+ n = callee0 (l5);
+ n = callee1 (n + l5);
+ n = callee2 (n + l5);
+ n = callee3 (n + l5);
+ n = callee4 (n + l5);
+ n = callee5 (n + l5);
+ return n+l1+l2+l3+l4+l5;
+}
+
+void
+driver (void)
+{
+ printf ("caller1 () => %d\n", caller1 ());
+ printf ("caller2 () => %d\n", caller2 ());
+ printf ("caller3 () => %d\n", caller3 ());
+ printf ("caller4 () => %d\n", caller4 ());
+ printf ("caller5 () => %d\n", caller5 ());
+}
+
+/* generated code ends here */
+
+main ()
+{
+ register int local;
+#ifdef usestubs
+ set_debug_traps();
+ breakpoint();
+#endif
+ driver ();
+ printf("exiting\n");
+}
diff --git a/gdb/testsuite/gdb.base/restore.exp b/gdb/testsuite/gdb.base/restore.exp
new file mode 100644
index 00000000000..64b714bd1b6
--- /dev/null
+++ b/gdb/testsuite/gdb.base/restore.exp
@@ -0,0 +1,111 @@
+# Copyright (C) 1998 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# Test GDB's ability to restore saved registers from stack frames
+# when using the `return' command.
+#
+# This file was written by Jim Blandy <jimb@cygnus.com>, with
+# fragments borrowed from return.exp.
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+set prms_id 0
+set bug_id 0
+
+set testfile "restore"
+set srcfile ${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+proc restore_tests { } {
+ global gdb_prompt
+
+ if { ! [ runto driver ] } then { return 0 }
+
+ set limit 5
+
+ # Set breakpoints at each of the `caller' functions.
+ for {set c 1} {$c <= $limit} {incr c} {
+ gdb_test "break caller$c" "Breakpoint.*\[0-9\]*\\." "break caller$c"
+ }
+
+ # Set breakpoints at each of the `callee' functions.
+ for {set c 1} {$c <= $limit} {incr c} {
+ gdb_test "break callee$c" "Breakpoint.*\[0-9\]*\\." "break caller$c"
+ }
+
+ # For each caller function,
+ # call each of the callee functions,
+ # force a return from the callee, and
+ # make sure that the local variables still have the right values.
+ for {set c 1} {$c <= $limit} {incr c} {
+
+ # Continue to the next caller function.
+ gdb_test "continue" ".*/\\* caller$c \\*/" "run to caller$c"
+
+ # Do each callee function.
+ for {set e 1} {$e <= $limit} {incr e} {
+ gdb_test " continue" ".*/\\* callee$e \\*/" "run to callee$e"
+
+ # Do a forced return from the callee.
+ send_gdb "return 0\n"
+ gdb_expect {
+ -re "Make .* return now.*y or n. $" {
+ send_gdb "y\n"
+ exp_continue
+ }
+ -re "$gdb_prompt $" { }
+ }
+
+ # Check that the values of the local variables are what
+ # they should be.
+ for {set var 1} {$var <= $c} {incr var} {
+ set expected [expr 0xfeeb + $var]
+ gdb_test "print l$var" " = $expected" \
+ "caller$c called callee$e; variable l$var restored"
+ }
+ }
+ }
+
+ send_gdb "continue\n"
+
+ gdb_expect {
+ -re "exiting" {
+ pass "run to completion"
+ }
+ timeout {
+ fail "(timeout) run to completion"
+ }
+ }
+}
+
+
+# Start with a fresh gdb.
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+set timeout 30
+restore_tests
diff --git a/gdb/testsuite/gdb.base/return.c b/gdb/testsuite/gdb.base/return.c
new file mode 100644
index 00000000000..e19d1a0b1f2
--- /dev/null
+++ b/gdb/testsuite/gdb.base/return.c
@@ -0,0 +1,35 @@
+#include <stdio.h>
+/* Test "return" command. */
+
+func1 ()
+{
+ printf("in func1\n");
+}
+
+int
+func2 ()
+{
+ return -5;
+}
+
+double
+func3 ()
+{
+ return -5.0;
+}
+
+int tmp2;
+double tmp3;
+
+main ()
+{
+#ifdef usestubs
+ set_debug_traps();
+ breakpoint();
+#endif
+ func1 ();
+ printf("in main after func1\n");
+ tmp2 = func2 ();
+ tmp3 = func3 ();
+ printf("exiting\n");
+}
diff --git a/gdb/testsuite/gdb.base/return.exp b/gdb/testsuite/gdb.base/return.exp
new file mode 100644
index 00000000000..c3a85e8923c
--- /dev/null
+++ b/gdb/testsuite/gdb.base/return.exp
@@ -0,0 +1,124 @@
+# Copyright (C) 1992, 1997 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file was written by Jeff Law. (law@cs.utah.edu)
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+set prms_id 0
+set bug_id 0
+
+set testfile "return"
+set srcfile ${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+proc return_tests { } {
+ global gdb_prompt
+
+
+ if { ! [ runto func1 ] } then { return 0 }
+ send_gdb "return\n"
+ gdb_expect {
+ -re "Make .* return now.*y or n. $" {
+ send_gdb "y\n"
+ exp_continue
+ }
+ -re "func1 ..;.*$gdb_prompt $" {
+ send_gdb "step\n"
+ exp_continue
+ }
+ -re ".*in main after func1.*$gdb_prompt $" { pass "simple return" }
+ -re "$gdb_prompt $" { fail "simple return" }
+ timeout { fail "(timeout) simple return" }
+ }
+
+ # Set breakpoints in other interesting functions.
+ gdb_test "break func2" "" "break func2"
+ gdb_test "break func3" "" "break func3"
+
+ gdb_test "continue" "return -5;" "continue to return of -5"
+ send_gdb "return 5\n"
+ gdb_expect {
+ -re "Make .* return now.*y or n. $" {
+ send_gdb "y\n"
+ exp_continue
+ }
+ -re ".*tmp2 = func2.*$gdb_prompt $" { }
+ -re "$gdb_prompt $" { fail "did not return (integer test)" }
+ timeout { fail "(timeout) did not return (integer test)" }
+ }
+ gdb_test "next" "tmp3 = func3.*" "next over call to func2"
+
+ gdb_test "p tmp2" ".* = 5" "correct value returned (integer test)"
+
+ gdb_test "continue" "return -5.0;" "continue to return of -5.0"
+ send_gdb "return 5.0\n"
+ gdb_expect {
+ -re "Make .* return now.*y or n. $" {
+ send_gdb "y\n"
+ exp_continue
+ }
+ -re ".*tmp3 = func3.*$gdb_prompt $" { }
+ -re "$gdb_prompt $" { fail "did not return (double test)" }
+ timeout { fail "(timeout) did not return (double test)" }
+ }
+
+ gdb_test "next" "printf.*" "next over call to func3"
+
+ # This test is going to fail on all i*86 systems using an i*87.
+ # When returning a floating point value from a function, all known
+ # compilers do this via a `fldl' instruction, which pushes the floating
+ # value on the i387 stack. This causes two problems:
+ # a) Most i*86 targets do not store (or cannot store, see comment in
+ # in i386v-nat.c:i386_register_u_addr) the floating point registers
+ # to the target.
+ # b) gdb would have to figure out if the `fldl' instruction (or variants
+ # of it) has already been executed. If not, it would have to simulate
+ # a push instruction, as it is not enough to write the register,
+ # the floating point `stack pointer' has to be updated too.
+ # Do not expect this to get fixed anytime soon.
+
+ # This test also fails for sparc Solaris 2.3 & 2.4, but passes under 2.5
+ # At the time the `next' is issued, the floating point unit for the
+ # process is not yet initialized, and the storing of the floating
+ # point value to the floating point return register is ignored.
+ # Xfail it for current versions that are known to fail. Presumably
+ # if some future version does initialize the floating point unit at
+ # process start, making this test pass, it will be for a version that
+ # is not xfailed.
+
+ setup_xfail "i*86-*-*" "sparc-*-solaris2.3*" "sparc-*-solaris2.4*"
+ gdb_test "p tmp3" ".* = 5.*" "correct value returned double test (known problem with i*86 and sparc solaris"
+}
+
+
+# Start with a fresh gdb.
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+set timeout 30
+return_tests
diff --git a/gdb/testsuite/gdb.base/run.c b/gdb/testsuite/gdb.base/run.c
new file mode 100644
index 00000000000..40ec72020e6
--- /dev/null
+++ b/gdb/testsuite/gdb.base/run.c
@@ -0,0 +1,67 @@
+/*
+ * This simple classical example of recursion is useful for
+ * testing stack backtraces and such.
+ */
+
+#ifdef vxworks
+
+# include <stdio.h>
+
+/* VxWorks does not supply atoi. */
+static int
+atoi (z)
+ char *z;
+{
+ int i = 0;
+
+ while (*z >= '0' && *z <= '9')
+ i = i * 10 + (*z++ - '0');
+ return i;
+}
+
+/* I don't know of any way to pass an array to VxWorks. This function
+ can be called directly from gdb. */
+
+vxmain (arg)
+char *arg;
+{
+ char *argv[2];
+
+ argv[0] = "";
+ argv[1] = arg;
+ main (2, argv, (char **) 0);
+}
+
+#else /* ! vxworks */
+# include <stdio.h>
+#endif /* ! vxworks */
+
+main (argc, argv, envp)
+int argc;
+char *argv[], **envp;
+{
+#ifdef usestubs
+ set_debug_traps();
+ breakpoint();
+#endif
+#ifdef FAKEARGV
+ printf ("%d\n", factorial (1));
+#else
+ if (argc != 2) {
+ printf ("usage: factorial <number>\n");
+ return 1;
+ } else {
+ printf ("%d\n", factorial (atoi (argv[1])));
+ }
+#endif
+ return 0;
+}
+
+int factorial (value)
+int value;
+{
+ if (value > 1) {
+ value *= factorial (value - 1);
+ }
+ return (value);
+}
diff --git a/gdb/testsuite/gdb.base/scope.exp b/gdb/testsuite/gdb.base/scope.exp
new file mode 100644
index 00000000000..6a92ca75119
--- /dev/null
+++ b/gdb/testsuite/gdb.base/scope.exp
@@ -0,0 +1,610 @@
+# Copyright (C) 1992, 1994, 1997, 1998 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file was written by Fred Fish. (fnf@cygnus.com)
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+set prms_id 0
+set bug_id 0
+
+set testfile "scope"
+set binfile ${objdir}/${subdir}/${testfile}
+
+
+if { [gdb_compile "${srcdir}/${subdir}/scope0.c" "${binfile}0.o" object {debug}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+if { [gdb_compile "${srcdir}/${subdir}/scope1.c" "${binfile}1.o" object {debug}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+if { [gdb_compile "${binfile}0.o ${binfile}1.o" ${binfile} executable {debug}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+# Create and source the file that provides information about the compiler
+# used to compile the test case.
+if [get_compiler_info ${binfile}] {
+ return -1;
+}
+
+# Test locating various things when stopped just inside main, after
+# running init0(). To prevent cascading of errors, we report the
+# first one and quit. If all pass, then we print the pass results.
+
+proc test_at_main {} {
+ global gdb_prompt
+ global decimal
+ global det_file
+ global srcdir
+ global subdir
+ global gcc_compiled
+
+ # skip past init. There may be a call to __main at the start of
+ # main, so the first next may only get us to the init0 call.
+ if [gdb_test "next" "$decimal.*foo \\(\\);" "next over init0() in main" "$decimal.*init0 \\(\\);" "next"] {
+ gdb_suppress_tests ;
+ }
+
+
+ # Print scope0.c::filelocal, which is 1
+
+ if [gdb_test "print filelocal" "\\\$$decimal = 1" "print filelocal" ] {
+ gdb_suppress_tests ;
+ }
+
+
+ if [gdb_test "print 'scope0.c'::filelocal" "\\\$$decimal = 1" "print 'scope0.c'::filelocal at main" "No symbol \"scope0.c\" in current context.*" "print '$srcdir/$subdir/scope0.c'::filelocal"] {
+ gdb_suppress_tests ;
+ }
+
+
+ # Print scope0.c::filelocal_bss, which is 101
+
+ if [gdb_test "print filelocal_bss" "\\\$$decimal = 101" "print filelocal_bss" ] {
+ gdb_suppress_tests ;
+ }
+
+
+ if [gdb_test "print 'scope0.c'::filelocal_bss" "\\\$$decimal = 101" "print 'scope0.c'::filelocal_bss in test_at_main" "No symbol \"scope0.c\" in current context.*" "print '$srcdir/$subdir/scope0.c'::filelocal_bss"] {
+ gdb_suppress_tests ;
+ }
+
+
+ # Print scope0.c::filelocal_ro, which is 201
+
+ # No clue why the powerpc fails this test.
+ setup_xfail "powerpc-*-*"
+ if {$gcc_compiled} then { setup_xfail "rs6000-*-*" }
+ if [gdb_test "print filelocal_ro" "\\\$$decimal = 201" "print filelocal_ro in test_at_main" ] {
+ gdb_suppress_tests ;
+ }
+
+
+ if {$gcc_compiled} then { setup_xfail "rs6000-*-*" }
+ setup_xfail "powerpc-*-*"
+ if [gdb_test "print 'scope0.c'::filelocal_ro" "\\\$$decimal = 201" "print 'scope0.c'::filelocal_ro" "No symbol \"scope0.c\" in current context.*" "print '$srcdir/$subdir/scope0.c'::filelocal_ro"] {
+ gdb_suppress_tests ;
+ }
+
+
+ # Print scope1.c::filelocal, which is 2
+
+ if {$gcc_compiled} then { setup_xfail "rs6000-*-*" }
+ if [gdb_test "print 'scope1.c'::filelocal" "\\\$$decimal = 2" "print 'scope1.c'::filelocal" "No symbol \"scope1.c\" in current context.*" "print '$srcdir/$subdir/scope1.c'::filelocal"] {
+ gdb_suppress_tests ;
+ }
+
+
+ # Print scope1.c::filelocal_bss, which is 102
+
+ if {$gcc_compiled} then { setup_xfail "rs6000-*-*" }
+ if [gdb_test "print 'scope1.c'::filelocal_bss" "\\\$$decimal = 102" "print 'scope1.c'::filelocal_bss" "No symbol \"scope1.c\" in current context.*" "print '$srcdir/$subdir/scope1.c'::filelocal_bss"] {
+ gdb_suppress_tests ;
+ }
+
+
+ # Print scope1.c::filelocal_ro, which is 202
+
+ if {$gcc_compiled} then { setup_xfail "rs6000-*-*" }
+ if [gdb_test "print 'scope1.c'::filelocal_ro" "\\\$$decimal = 202" "print 'scope1.c'::filelocal_ro" "No symbol \"scope1.c\" in current context.*" "print '$srcdir/$subdir/scope1.c'::filelocal_ro"] {
+ gdb_suppress_tests ;
+ }
+
+
+ # Print scope1.c::foo::funclocal, which is 3
+
+ if {!$gcc_compiled} then { setup_xfail "hppa*-*-hpux*" }
+ if [gdb_test "print foo::funclocal" "\\\$$decimal = 3" "print foo::funclocal" ] {
+ gdb_suppress_tests ;
+ }
+
+
+ if {$gcc_compiled} then { setup_xfail "rs6000-*-*" }
+ if [gdb_test "print 'scope1.c'::foo::funclocal" "\\\$$decimal = 3" "print 'scope1.c'::foo::funclocal" "No symbol \"scope1.c\" in current context.*" "print '$srcdir/$subdir/scope1.c'::foo::funclocal"] {
+ gdb_suppress_tests ;
+ }
+
+
+ # Print scope1.c::foo::funclocal_ro, which is 203
+
+ if [gdb_test "print foo::funclocal_ro" "\\\$$decimal = 203" "print foo::funclocal_ro" ] {
+ gdb_suppress_tests ;
+ }
+
+
+ if {$gcc_compiled} then { setup_xfail "rs6000-*-*" }
+ if [gdb_test "print 'scope1.c'::foo::funclocal_ro" "\\\$$decimal = 203" "print 'scope1.c'::foo::funclocal_ro" "No symbol \"scope1.c\" in current context.*" "print '$srcdir/$subdir/scope1.c'::foo::funclocal_ro"] {
+ gdb_suppress_tests ;
+ }
+
+
+ # Print scope1.c::bar::funclocal, which is 4
+
+ if [gdb_test "print bar::funclocal" "\\\$$decimal = 4" "print bar::funclocal" ] {
+ gdb_suppress_tests ;
+ }
+
+
+ if {$gcc_compiled} then { setup_xfail "rs6000-*-*" }
+ if [gdb_test "print 'scope1.c'::bar::funclocal" "\\\$$decimal = 4" "print 'scope1.c'::bar::funclocal" "No symbol \"scope1.c\" in current context.*" "print '$srcdir/$subdir/scope1.c'::bar::funclocal"] {
+ gdb_suppress_tests ;
+ }
+ gdb_stop_suppressing_tests;
+
+}
+
+proc test_at_foo {} {
+ global gdb_prompt
+ global decimal
+ global det_file
+ global srcdir
+ global subdir
+ global gcc_compiled
+
+ if [gdb_test "next" ".*bar \\(\\);" "" ] {
+ gdb_suppress_tests ;
+ }
+
+
+ # Print scope0.c::filelocal, which is 1
+
+ if [gdb_test "print 'scope0.c'::filelocal" "\\\$$decimal = 1" "print 'scope0.c'::filelocal at foo" "No symbol \"scope0.c\" in current context.*" "print '$srcdir/$subdir/scope0.c'::filelocal"] {
+ gdb_suppress_tests ;
+ }
+
+
+ # Print scope0.c::filelocal_bss, which is 101
+
+ if [gdb_test "print 'scope0.c'::filelocal_bss" "\\\$$decimal = 101" "print 'scope0.c'::filelocal_bss in test_at_foo" "No symbol \"scope0.c\" in current context.*" "print '$srcdir/$subdir/scope0.c'::filelocal_bss"] {
+ gdb_suppress_tests ;
+ }
+
+
+ # Print scope0.c::filelocal_ro, which is 201
+
+ if {$gcc_compiled} then { setup_xfail "rs6000-*-*" }
+ setup_xfail "powerpc-*-*"
+ if [gdb_test "print 'scope0.c'::filelocal_ro" "\\\$$decimal = 201" "print 'scope0.c'::filelocal_ro" "No symbol \"scope0.c\" in current context.*" "print '$srcdir/$subdir/scope0.c'::filelocal_ro"] {
+ gdb_suppress_tests ;
+ }
+
+
+ gdb_test "print filelocal" "\\\$$decimal = 2" "print filelocal at foo"
+
+ # Print scope1.c::filelocal, which is 2
+
+ if {$gcc_compiled} then { setup_xfail "rs6000-*-*" }
+ if [gdb_test "print 'scope1.c'::filelocal" "\\\$$decimal = 2" "print 'scope1.c'::filelocal at foo" "No symbol \"scope1.c\" in current context.*" "print '$srcdir/$subdir/scope1.c'::filelocal"] {
+ gdb_suppress_tests ;
+ }
+
+
+ gdb_test "print filelocal_bss" "\\\$$decimal = 102" \
+ "print filelocal_bss at foo"
+
+ if {$gcc_compiled} then { setup_xfail "rs6000-*-*" }
+ gdb_test "print 'scope1.c'::filelocal_bss" "\\\$$decimal = 102" "print 'scope1.c'::filelocal_bss at foo" "No symbol \"scope1.c\" in current context.*" "print '$srcdir/$subdir/scope1.c'::filelocal_bss"
+
+
+ gdb_test "print filelocal_ro" "\\\$$decimal = 202" \
+ "print filelocal_ro at foo"
+
+ if {$gcc_compiled} then { setup_xfail "rs6000-*-*" }
+ gdb_test "print 'scope1.c'::filelocal_ro" "\\\$$decimal = 202" "print 'scope1.c'::filelocal_ro at foo" "No symbol \"scope1.c\" in current context.*" "print '$srcdir/$subdir/scope1.c'::filelocal_ro"
+
+
+ # Print scope1.c::foo::funclocal, which is 3
+
+ gdb_test "print funclocal" "\\\$$decimal = 3" "print funclocal at foo"
+
+ if {!$gcc_compiled} then { setup_xfail "hppa*-*-hpux*" }
+ gdb_test "print foo::funclocal" "\\\$$decimal = 3" \
+ "print foo::funclocal at foo"
+
+ if {$gcc_compiled} then { setup_xfail "rs6000-*-*" }
+ if {!$gcc_compiled} then { setup_xfail "hppa*-*-hpux*" }
+ gdb_test "print 'scope1.c'::foo::funclocal" "\\\$$decimal = 3" "print 'scope1.c'::foo::funclocal at foo" "No symbol \"scope1.c\" in current context.*" "print '$srcdir/$subdir/scope1.c'::foo::funclocal"
+
+
+ # Print scope1.c::foo::funclocal_bss, which is 103
+
+ gdb_test "print funclocal_bss" "\\\$$decimal = 103" \
+ "print funclocal_bss at foo"
+
+ if {!$gcc_compiled} then { setup_xfail "hppa*-*-hpux*" }
+ gdb_test "print foo::funclocal_bss" "\\\$$decimal = 103" \
+ "print foo::funclocal_bss at foo"
+
+ if {$gcc_compiled} then { setup_xfail "rs6000-*-*" }
+ if {!$gcc_compiled} then { setup_xfail "hppa*-*-hpux*" }
+ gdb_test "print 'scope1.c'::foo::funclocal_bss" "\\\$$decimal = 103" "print 'scope1.c'::foo::funclocal_bss at foo" "No symbol \"scope1.c\" in current context.*" "print '$srcdir/$subdir/scope1.c'::foo::funclocal_bss"
+
+
+ # Print scope1.c::foo::funclocal_ro, which is 203
+
+ gdb_test "print funclocal_ro" "\\\$$decimal = 203" \
+ "print funclocal_ro at foo"
+
+ if {!$gcc_compiled} then { setup_xfail "hppa*-*-hpux*" }
+ gdb_test "print foo::funclocal_ro" "\\\$$decimal = 203" \
+ "print foo::funclocal_ro at foo"
+
+ if {$gcc_compiled} then { setup_xfail "rs6000-*-*" }
+ if {!$gcc_compiled} then { setup_xfail "hppa*-*-hpux*" }
+ gdb_test "print 'scope1.c'::foo::funclocal_ro" "\\\$$decimal = 203" "print 'scope1.c'::foo::funclocal_ro at foo" "No symbol \"scope1.c\" in current context.*" "print '$srcdir/$subdir/scope1.c'::foo::funclocal_ro"
+
+
+ # Print scope1.c::bar::funclocal, which is 4
+
+ if {!$gcc_compiled} then { setup_xfail "hppa*-*-hpux*" }
+ gdb_test "print bar::funclocal" "\\\$$decimal = 4" \
+ "print bar::funclocal at foo"
+
+ if {$gcc_compiled} then { setup_xfail "rs6000-*-*" }
+ if {!$gcc_compiled} then { setup_xfail "hppa*-*-hpux*" }
+ gdb_test "print 'scope1.c'::bar::funclocal" "\\\$$decimal = 4" "print 'scope1.c'::bar::funclocal at foo" "No symbol \"scope1.c\" in current context.*" "print '$srcdir/$subdir/scope1.c'::bar::funclocal"
+ gdb_stop_suppressing_tests;
+
+}
+
+proc test_at_bar {} {
+ global gdb_prompt
+ global decimal
+ global det_file
+ global srcdir
+ global subdir
+ global gcc_compiled
+
+ if [gdb_test "next" ".*" "" ] {
+ gdb_suppress_tests ;
+ }
+
+
+ # Print scope0.c::filelocal, which is 1
+
+ if [gdb_test "print 'scope0.c'::filelocal" "\\\$$decimal = 1" "print 'scope0.c'::filelocal at bar" "No symbol \"scope0.c\" in current context.*" "print '$srcdir/$subdir/scope0.c'::filelocal"] {
+ gdb_suppress_tests ;
+ }
+
+
+ # Print scope0.c::filelocal_bss, which is 101
+
+ if [gdb_test "print 'scope0.c'::filelocal_bss" "\\\$$decimal = 101" "print 'scope0.c'::filelocal_bss in test_at_bar" "No symbol \"scope0.c\" in current context.*" "print '$srcdir/$subdir/scope0.c'::filelocal_bss"] {
+ gdb_suppress_tests ;
+ }
+
+
+ # Print scope0.c::filelocal_ro, which is 201
+
+ if {$gcc_compiled} then { setup_xfail "rs6000-*-*" }
+ setup_xfail "powerpc-*-*"
+ if [gdb_test "print 'scope0.c'::filelocal_ro" "\\\$$decimal = 201" "print 'scope0.c'::filelocal_ro at bar" "No symbol \"scope0.c\" in current context.*" "print '$srcdir/$subdir/scope0.c'::filelocal_ro"] {
+ gdb_suppress_tests ;
+ }
+
+
+ # Print scope1.c::filelocal, which is 2
+
+ if [gdb_test "print filelocal" "\\\$$decimal = 2" "print filelocal at bar" ] {
+ gdb_suppress_tests ;
+ }
+
+
+ if {$gcc_compiled} then { setup_xfail "rs6000-*-*" }
+ if [gdb_test "print 'scope1.c'::filelocal" "\\\$$decimal = 2" "print 'scope1.c'::filelocal at bar" "No symbol \"scope1.c\" in current context.*" "print '$srcdir/$subdir/scope1.c'::filelocal"] {
+ gdb_suppress_tests ;
+ }
+
+
+ # Print scope1.c::filelocal_bss, which is 102
+
+ if [gdb_test "print filelocal_bss" "\\\$$decimal = 102" "print filelocal_bss at bar" ] {
+ gdb_suppress_tests ;
+ }
+
+
+ if {$gcc_compiled} then { setup_xfail "rs6000-*-*" }
+ if [gdb_test "print 'scope1.c'::filelocal_bss" "\\\$$decimal = 102" "print 'scope1.c'::filelocal_bss at bar" "No symbol \"scope1.c\" in current context.*" "print '$srcdir/$subdir/scope1.c'::filelocal_bss"] {
+ gdb_suppress_tests ;
+ }
+
+
+ # Print scope1.c::filelocal_ro, which is 202
+
+ if [gdb_test "print filelocal_ro" "\\\$$decimal = 202" "print filelocal_ro in test_at_bar" ] {
+ gdb_suppress_tests ;
+ }
+
+
+ if {$gcc_compiled} then { setup_xfail "rs6000-*-*" }
+ if [gdb_test "print 'scope1.c'::filelocal_ro" "\\\$$decimal = 202" "print 'scope1.c'::filelocal_ro at bar" "No symbol \"scope1.c\" in current context.*" "print '$srcdir/$subdir/scope1.c'::filelocal_ro"] {
+ gdb_suppress_tests ;
+ }
+
+
+ # Print scope1.c::foo::funclocal, which is 3
+
+ if {!$gcc_compiled} then { setup_xfail "hppa*-*-hpux*" }
+ if [gdb_test "print foo::funclocal" "\\\$$decimal = 3" "print foo::funclocal at bar" ] {
+ gdb_suppress_tests ;
+ }
+
+
+ if {$gcc_compiled} then { setup_xfail "rs6000-*-*" }
+ if [gdb_test "print 'scope1.c'::foo::funclocal" "\\\$$decimal = 3" "print 'scope1.c'::foo::funclocal at bar" "No symbol \"scope1.c\" in current context.*" "print '$srcdir/$subdir/scope1.c'::foo::funclocal"] {
+ gdb_suppress_tests ;
+ }
+
+
+ # Print scope1.c::foo::funclocal_bss, which is 103
+
+ if [gdb_test "print foo::funclocal_bss" "\\\$$decimal = 103" "print foo::funclocal_bss at bar" ] {
+ gdb_suppress_tests ;
+ }
+
+
+ if {$gcc_compiled} then { setup_xfail "rs6000-*-*" }
+ if [gdb_test "print 'scope1.c'::foo::funclocal_bss" "\\\$$decimal = 103" "print 'scope1.c'::foo::funclocal_bss at bar" "No symbol \"scope1.c\" in current context.*" "print '$srcdir/$subdir/scope1.c'::foo::funclocal_bss"] {
+ gdb_suppress_tests ;
+ }
+
+
+ # Print scope1.c::foo::funclocal_ro, which is 203
+
+ if [gdb_test "print foo::funclocal_ro" "\\\$$decimal = 203" "print foo::funclocal_ro at bar" ] {
+ gdb_suppress_tests ;
+ }
+
+
+ if {$gcc_compiled} then { setup_xfail "rs6000-*-*" }
+ if [gdb_test "print 'scope1.c'::foo::funclocal_ro" "\\\$$decimal = 203" "print 'scope1.c'::foo::funclocal_ro at bar" "No symbol \"scope1.c\" in current context.*" "print '$srcdir/$subdir/scope1.c'::foo::funclocal_ro"] {
+ gdb_suppress_tests ;
+ }
+
+
+ # Print scope1.c::bar::funclocal, which is 4
+
+ if [gdb_test "print funclocal" "\\\$$decimal = 4" "print funclocal at bar" ] {
+ gdb_suppress_tests ;
+ }
+
+
+ if [gdb_test "print bar::funclocal" "\\\$$decimal = 4" "print bar::funclocal at bar" ] {
+ gdb_suppress_tests ;
+ }
+
+
+ if {$gcc_compiled} then { setup_xfail "rs6000-*-*" }
+ if [gdb_test "print 'scope1.c'::bar::funclocal" "\\\$$decimal = 4" "print 'scope1.c'::bar::funclocal at bar" "No symbol \"scope1.c\" in current context.*" "print '$srcdir/$subdir/scope1.c'::bar::funclocal"] {
+ gdb_suppress_tests ;
+ }
+
+
+ # Print scope1.c::bar::funclocal_bss, which is 104
+
+ if [gdb_test "print funclocal_bss" "\\\$$decimal = 104" "print funclocal_bss at bar" ] {
+ gdb_suppress_tests ;
+ }
+
+
+ if [gdb_test "print bar::funclocal_bss" "\\\$$decimal = 104" "print bar::funclocal_bss at bar" ] {
+ gdb_suppress_tests ;
+ }
+
+
+ if {$gcc_compiled} then { setup_xfail "rs6000-*-*" }
+ if [gdb_test "print 'scope1.c'::bar::funclocal_bss" "\\\$$decimal = 104" "print 'scope1.c'::bar::funclocal_bss at bar" "No symbol \"scope1.c\" in current context.*" "print '$srcdir/$subdir/scope1.c'::bar::funclocal_bss"] {
+ gdb_suppress_tests ;
+ }
+ gdb_stop_suppressing_tests;
+
+}
+
+# This test has little to do with local scopes, but it is in scope.exp anyway.
+# That's life.
+
+proc test_at_autovars {} {
+ global gdb_prompt
+ global decimal
+ global hex
+ global srcfile
+
+ # Test symbol table lookup with 100 local (auto) variables.
+
+ gdb_breakpoint marker1
+
+ if [gdb_test "cont" "Break.* marker1 \\(\\) at .*:$decimal.*" "continue to marker1"] {
+ gdb_suppress_tests;
+ }
+
+ if [gdb_test "up" ".*" "" ] {
+ gdb_suppress_tests ;
+ }
+
+ set count 0
+ while {$count < 100} {
+ if [gdb_test "print i$count" ".* = $count" "" ] {
+ gdb_suppress_tests ;
+ }
+
+ set count [expr $count+1]
+ }
+ clear_xfail "*-*-*"
+ pass "$count auto variables correctly initialized"
+
+ # Test that block variable sorting is not screwing us.
+ gdb_test "frame" "#.*autovars \\(bcd=5, abc=6\\).*" "args in correct order"
+}
+
+proc test_at_localscopes {} {
+ global gdb_prompt
+ global decimal
+ global hex
+ global srcfile
+
+ gdb_breakpoint marker2
+ gdb_breakpoint marker3
+ gdb_breakpoint marker4
+
+ if [gdb_test "cont" "Break.* marker2 \\(\\) at .*:$decimal.*" "continue to marker2"] {
+ gdb_suppress_tests;
+ }
+ if [gdb_test "up" ".*" "" ] {
+ gdb_suppress_tests ;
+ }
+
+ # Should be at first (outermost) scope. Check values.
+
+ gdb_test "print localval" " = 10" "print localval, outer scope"
+ gdb_test "print localval1" " = 11" "print localval1, outer scope"
+ gdb_test "print localval2" "No symbol \"localval2\" in current context." \
+ "print localval2, outer scope"
+ gdb_test "print localval3" "No symbol \"localval3\" in current context." \
+ "print localval3, outer scope"
+
+ if [gdb_test "cont" "Break.* marker3 \\(\\) at .*:$decimal.*" \
+ "continue to marker3 in scope.exp"] then { gdb_suppress_tests }
+ if [gdb_test "up" "" "up from marker3 in scope.exp"] then { gdb_suppress_tests }
+
+ # Should be at next (first nested) scope. Check values.
+
+ gdb_test "print localval" " = 20" \
+ "print localval, first nested scope"
+ gdb_test "print localval1" " = 11" "print localval1, first nested scope"
+ gdb_test "print localval2" " = 12" "print localval2, first nested scope"
+ gdb_test "print localval3" "No symbol \"localval3\" in current context." \
+ "print localval3, first nested scope"
+
+ # This test will only fail if the file was compiled by gcc, but
+ # there's no way to check that.
+ setup_xfail "a29k-*-udi" 2423
+ if [gdb_test "cont" "Break.* marker4.*at .*:$decimal.*" \
+ "continue to marker4 in scope.exp"] then { gdb_suppress_tests }
+ if [gdb_test "up" "" "up from marker4 in scope.exp"] then { gdb_suppress_tests }
+
+ gdb_test "print localval" " = 30" "print localval, innermost scope"
+ gdb_test "print localval1" " = 11" "print localval1, innermost scope"
+ gdb_test "print localval2" " = 12" "print localval2, innermost scope"
+ gdb_test "print localval3" " = 13" "print localval3, innermost scope"
+ gdb_stop_suppressing_tests;
+}
+
+# Start with a fresh gdb.
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+if [istarget "*-*-vxworks*"] {
+ set timeout 120
+ verbose "Timeout is now $timeout seconds" 2
+}
+
+# Test that variables in various segments print out correctly before
+# the program is run.
+
+# AIX--sections get mapped to the same address so we can't get the right one.
+setup_xfail "rs6000-*-*"
+setup_xfail "powerpc-*-*"
+
+gdb_test "print 'scope0.c'::filelocal_ro" "= 201"
+
+# gdb currently cannot access bss memory on some targets if the inferior
+# is not running.
+#
+# For PA boards using monitor/remote-pa.c, the bss test is going to
+# randomly fail. We've already put remote-pa on the target stack,
+# so we actually read memory from the board. Problem is crt0.o
+# is responsible for clearing bss and that hasnt' happened yet.
+#
+# This is a problem for all non-native targets. -- manson
+if ![isnative] {
+ unsupported "print 'scope0.c'::filelocal_bss before run"
+} else {
+ gdb_test "print 'scope0.c'::filelocal_bss" "= 0" \
+ "print 'scope0.c'::filelocal_bss before run"
+}
+
+gdb_test "print 'scope0.c'::filelocal" "= 1" \
+ "print 'scope0.c'::filelocal before run"
+
+if [runto_main] then { test_at_main }
+if [istarget "mips-idt-*"] then {
+ # Restart because IDT/SIM runs out of file descriptors.
+ gdb_exit
+ gdb_start
+ gdb_reinitialize_dir $srcdir/$subdir
+ gdb_load ${binfile}
+}
+if [runto foo] then { test_at_foo }
+if [istarget "mips-idt-*"] then {
+ # Restart because IDT/SIM runs out of file descriptors.
+ gdb_exit
+ gdb_start
+ gdb_reinitialize_dir $srcdir/$subdir
+ gdb_load ${binfile}
+}
+if [runto bar] then { test_at_bar }
+if [istarget "mips-idt-*"] then {
+ # Restart because IDT/SIM runs out of file descriptors.
+ gdb_exit
+ gdb_start
+ gdb_reinitialize_dir $srcdir/$subdir
+ gdb_load ${binfile}
+}
+if [runto localscopes] then { test_at_localscopes }
+if [istarget "mips-idt-*"] then {
+ # Restart because IDT/SIM runs out of file descriptors.
+ gdb_exit
+ gdb_start
+ gdb_reinitialize_dir $srcdir/$subdir
+ gdb_load ${binfile}
+}
+if [runto autovars] then { test_at_autovars }
+
+if [istarget "*-*-vxworks*"] {
+ set timeout 120
+ verbose "Timeout is now $timeout seconds" 2
+}
diff --git a/gdb/testsuite/gdb.base/scope0.c b/gdb/testsuite/gdb.base/scope0.c
new file mode 100644
index 00000000000..3a1b89e2500
--- /dev/null
+++ b/gdb/testsuite/gdb.base/scope0.c
@@ -0,0 +1,176 @@
+static int filelocal = 1; /* In Data section */
+static int filelocal_bss; /* In BSS section */
+#ifndef __STDC__
+#define const /**/
+#endif
+static const int filelocal_ro = 201; /* In Read-Only Data section */
+
+main ()
+{
+#ifdef usestubs
+ set_debug_traps();
+ breakpoint();
+#endif
+ init0 ();
+ foo ();
+ autovars (5, 6);
+ localscopes (0);
+}
+
+/* On some systems, such as AIX, unreferenced variables are deleted
+ from the executable. */
+usestatics ()
+{
+ useit (filelocal);
+ useit (filelocal_bss);
+ useit (filelocal_ro);
+}
+
+init0 ()
+{
+ filelocal_bss = 101;
+ init1 ();
+}
+
+/* This is to derail optimizer in localscopes.
+ Return 1 + 2 + . . . + N. */
+int
+sum_upto (n)
+ int n;
+{
+ int i;
+ int retval = 0;
+
+ for (i = 1; i <= n; ++i)
+ retval += i;
+ return retval;
+}
+
+int
+useit (val)
+{
+ static int usedval;
+
+ usedval = val;
+ return val + sum_upto (0);
+}
+
+int
+autovars (bcd, abc)
+ int bcd;
+ int abc;
+{
+ int i0 = useit (0), i1 = useit (1), i2 = useit (2);
+ int i3 = useit (3), i4 = useit (4), i5 = useit (5);
+ int i6 = useit (6), i7 = useit (7), i8 = useit (8);
+ int i9 = useit (9), i10 = useit (10), i11 = useit (11);
+ int i12 = useit (12), i13 = useit (13), i14 = useit (14);
+ int i15 = useit (15), i16 = useit (16), i17 = useit (17);
+ int i18 = useit (18), i19 = useit (19), i20 = useit (20);
+ int i21 = useit (21), i22 = useit (22), i23 = useit (23);
+ int i24 = useit (24), i25 = useit (25), i26 = useit (26);
+ int i27 = useit (27), i28 = useit (28), i29 = useit (29);
+ int i30 = useit (30), i31 = useit (31), i32 = useit (32);
+ int i33 = useit (33), i34 = useit (34), i35 = useit (35);
+ int i36 = useit (36), i37 = useit (37), i38 = useit (38);
+ int i39 = useit (39), i40 = useit (40), i41 = useit (41);
+ int i42 = useit (42), i43 = useit (43), i44 = useit (44);
+ int i45 = useit (45), i46 = useit (46), i47 = useit (47);
+ int i48 = useit (48), i49 = useit (49), i50 = useit (50);
+ int i51 = useit (51), i52 = useit (52), i53 = useit (53);
+ int i54 = useit (54), i55 = useit (55), i56 = useit (56);
+ int i57 = useit (57), i58 = useit (58), i59 = useit (59);
+ int i60 = useit (60), i61 = useit (61), i62 = useit (62);
+ int i63 = useit (63), i64 = useit (64), i65 = useit (65);
+ int i66 = useit (66), i67 = useit (67), i68 = useit (68);
+ int i69 = useit (69), i70 = useit (70), i71 = useit (71);
+ int i72 = useit (72), i73 = useit (73), i74 = useit (74);
+ int i75 = useit (75), i76 = useit (76), i77 = useit (77);
+ int i78 = useit (78), i79 = useit (79), i80 = useit (80);
+ int i81 = useit (81), i82 = useit (82), i83 = useit (83);
+ int i84 = useit (84), i85 = useit (85), i86 = useit (86);
+ int i87 = useit (87), i88 = useit (88), i89 = useit (89);
+ int i90 = useit (90), i91 = useit (91), i92 = useit (92);
+ int i93 = useit (93), i94 = useit (94), i95 = useit (95);
+ int i96 = useit (96), i97 = useit (97), i98 = useit (98);
+ int i99 = useit (99);
+
+ /* Use all 100 of the local variables to derail agressive optimizers. */
+
+ useit ( i0); useit ( i1); useit ( i2); useit ( i3); useit ( i4);
+ useit ( i5); useit ( i6); useit ( i7); useit ( i8); useit ( i9);
+ useit (i10); useit (i11); useit (i12); useit (i13); useit (i14);
+ useit (i15); useit (i16); useit (i17); useit (i18); useit (i19);
+ useit (i20); useit (i21); useit (i22); useit (i23); useit (i24);
+ useit (i25); useit (i26); useit (i27); useit (i28); useit (i29);
+ useit (i30); useit (i31); useit (i32); useit (i33); useit (i34);
+ useit (i35); useit (i36); useit (i37); useit (i38); useit (i39);
+ useit (i40); useit (i41); useit (i42); useit (i43); useit (i44);
+ useit (i45); useit (i46); useit (i47); useit (i48); useit (i49);
+ useit (i50); useit (i51); useit (i52); useit (i53); useit (i54);
+ useit (i55); useit (i56); useit (i57); useit (i58); useit (i59);
+ useit (i60); useit (i61); useit (i62); useit (i63); useit (i64);
+ useit (i65); useit (i66); useit (i67); useit (i68); useit (i69);
+ useit (i70); useit (i71); useit (i72); useit (i73); useit (i74);
+ useit (i75); useit (i76); useit (i77); useit (i78); useit (i79);
+ useit (i80); useit (i81); useit (i82); useit (i83); useit (i84);
+ useit (i85); useit (i86); useit (i87); useit (i88); useit (i89);
+ useit (i90); useit (i91); useit (i92); useit (i93); useit (i94);
+ useit (i95); useit (i96); useit (i97); useit (i98); useit (i99);
+
+ useit (abc); useit (bcd);
+
+ marker1 ();
+ return i0 + i1 + i2 + i3 + i4 + i5 + i6 + i7 + i8 + i9 + i10
+ + i11 + i12 + i13 + i14 + i15 + i16 + i17 + i18 + i19 + i20
+ + i21 + i22 + i23 + i24 + i25 + i26 + i27 + i28 + i29 + i30
+ + i31 + i32 + i33 + i34 + i35 + i36 + i37 + i38 + i39 + i40
+ + i41 + i42 + i43 + i44 + i45 + i46 + i47 + i48 + i49 + i50
+ + i51 + i52 + i53 + i54 + i55 + i56 + i57 + i58 + i59 + i60
+ + i61 + i62 + i63 + i64 + i65 + i66 + i67 + i68 + i69 + i70
+ + i71 + i72 + i73 + i74 + i75 + i76 + i77 + i78 + i79 + i80
+ + i81 + i82 + i83 + i84 + i85 + i86 + i87 + i88 + i89 + i90
+ + i91 + i92 + i93 + i94 + i95 + i96 + i97 + i98 + i99 + abc + bcd;
+}
+
+int
+localscopes (x)
+ int x;
+{
+ int localval;
+ int retval;
+ int i;
+
+ localval = 0;
+ useit (localval);
+
+ {
+ int localval = x + 4 + sum_upto (3); /* 10 */
+ int localval1 = x + 5 + sum_upto (3); /* 11 */
+
+ useit (localval);
+ useit (localval1);
+ marker2 ();
+ {
+ int localval = localval1 + 3 + sum_upto (3); /* 20 */
+ int localval2 = localval1 + sum_upto (1); /* 12 */
+ useit (localval);
+ useit (localval2);
+ marker3 ();
+ {
+ int localval = localval2 + 3 + sum_upto (5); /* 30 */
+ int localval3 = localval2 + sum_upto (1); /* 13 */
+ useit (localval);
+ useit (localval3);
+ marker4 ();
+ retval = x + localval1 + localval2 + localval3;
+ }
+ }
+ }
+ return retval;
+}
+
+marker1 () {}
+marker2 () {}
+marker3 () {}
+marker4 () {}
diff --git a/gdb/testsuite/gdb.base/scope1.c b/gdb/testsuite/gdb.base/scope1.c
new file mode 100644
index 00000000000..cccad6f321e
--- /dev/null
+++ b/gdb/testsuite/gdb.base/scope1.c
@@ -0,0 +1,45 @@
+static int filelocal = 2; /* In Data section */
+static int filelocal_bss; /* In BSS section */
+#ifndef __STDC__
+#define const /**/
+#endif
+static const int filelocal_ro = 202; /* In Read-Only Data section */
+
+foo ()
+{
+ static int funclocal = 3; /* In Data section */
+ static int funclocal_bss; /* In BSS section */
+ static const int funclocal_ro = 203; /* RO Data */
+ static const int funclocal_ro_bss; /* RO Data */
+
+ funclocal_bss = 103;
+ bar ();
+}
+
+bar ()
+{
+ static int funclocal = 4; /* In data section */
+ static int funclocal_bss; /* In BSS section */
+ funclocal_bss = 104;
+}
+
+init1 ()
+{
+ filelocal_bss = 102;
+}
+
+/* On some systems, such as AIX, unreferenced variables are deleted
+ from the executable. */
+usestatics1 ()
+{
+ useit1 (filelocal);
+ useit1 (filelocal_bss);
+ useit1 (filelocal_ro);
+}
+
+useit1 (val)
+{
+ static int usedval;
+
+ usedval = val;
+}
diff --git a/gdb/testsuite/gdb.base/sect-cmd.exp b/gdb/testsuite/gdb.base/sect-cmd.exp
new file mode 100644
index 00000000000..27bde04452a
--- /dev/null
+++ b/gdb/testsuite/gdb.base/sect-cmd.exp
@@ -0,0 +1,109 @@
+# Copyright (C) 1997, 1998 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+if $tracelevel then {
+ strace $tracelevel
+ }
+
+global usestubs
+
+#
+# test running programs
+#
+set prms_id 0
+set bug_id 0
+
+# This test exists solely to exercise the "section" command for
+# code-coverage on HP-UX. (So far as I can tell, the "section"
+# command isn't needed on HP-UX, but probably is for embedded
+# apps.)
+#
+if ![istarget "hppa*-*-hpux*"] then {
+ return
+}
+
+set testfile "break"
+set srcfile ${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+if ![runto_main] then { fail "section command tests suppressed" }
+
+# Get the $CODE$ section's starting address.
+#
+# (Note that this works for PA32 programs, which use the SOM file
+# format. PA64 uses ELF, and when support for that is added, it's
+# not clear that there'll be a section named "$CODE$" in such
+# programs.)
+#
+send_gdb "info files\n"
+gdb_expect {
+ -re ".*(0x\[0-9a-fA-F\]*) - (0x\[0-9a-fA-F\]*) is .CODE..*$gdb_prompt $"\
+ {pass "info files"}
+ -re "$gdb_prompt $"\
+ {fail "info files"}
+ timeout {fail "(timeout) info files"}
+}
+
+# Reset the section to that same starting address, which should be
+# harmless (i.e., we just want to exercise the section command).
+#
+send_gdb "section \$CODE\$ $expect_out(1,string)\n"
+gdb_expect {
+ -re ".*$expect_out(1,string) \- $expect_out(2,string) is .CODE..*$gdb_prompt $"\
+ {pass "set section command"}
+ -re "$gdb_prompt $"\
+ {fail "set section command"}
+ timeout {fail "(timeout) set section command"}
+}
+
+# Verify that GDB responds gracefully to a non-existent section name.
+#
+send_gdb "section FOOBARBAZ 0x1234\n"
+gdb_expect {
+ -re "Section FOOBARBAZ not found\r\n$gdb_prompt $"\
+ {pass "non-existent section disallowed"}
+ -re "$gdb_prompt $"\
+ {fail "non-existent section disallowed"}
+ timeout {fail "(timeout) non-existent section disallowed"}
+}
+
+# We "happen to know" that GDB uses a fixed size character buffer to
+# parse the section name into, and the buffer is declared to be 100
+# characters in length. Verify that GDB gracefully handles section
+# names longer than that. (The section is also non-existent.)
+#
+send_gdb "section A234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123 0x1234\n"
+gdb_expect {
+ -re "Section A23456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 not found\r\n$gdb_prompt $"\
+ {pass "non-existent too-long section disallowed"}
+ -re "$gdb_prompt $"\
+ {fail "non-existent too-long section disallowed"}
+ timeout {fail "(timeout) non-existent too-long section disallowed"}
+}
+
+gdb_exit
+return 0
diff --git a/gdb/testsuite/gdb.base/setshow.c b/gdb/testsuite/gdb.base/setshow.c
new file mode 100644
index 00000000000..ed4e7a9a420
--- /dev/null
+++ b/gdb/testsuite/gdb.base/setshow.c
@@ -0,0 +1,22 @@
+/* IMPORTANT: leave this comment in the first line of this source file. */
+/* this will guarantee that line 1 contains no code. */
+
+#include <stdio.h>
+
+int
+main(argc, argv)
+ int argc;
+ char **argv;
+{
+ int i = 1;
+#ifdef usestubs
+ set_debug_traps();
+ breakpoint();
+#endif
+
+ if (argc <= 0 || argc > 8)
+ return -1;
+ while (i < argc)
+ printf ("%s ", argv[i++]);
+ return 0;
+}
diff --git a/gdb/testsuite/gdb.base/setshow.exp b/gdb/testsuite/gdb.base/setshow.exp
new file mode 100644
index 00000000000..37c2f84034c
--- /dev/null
+++ b/gdb/testsuite/gdb.base/setshow.exp
@@ -0,0 +1,243 @@
+# Copyright (C) 1992, 1994, 1997 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file was written by Michael Snyder (msnyder@cygnus.com)
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+set prms_id 0
+set bug_id 0
+
+set testfile "setshow"
+set srcfile ${srcdir}/${subdir}/${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+if { [gdb_compile ${srcfile} ${binfile} executable {debug}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+# Start with a fresh gdb
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+# make sure $pc is sane, in case we're talking to a board.
+if { ![runto_main] } {
+ gdb_suppress_tests;
+}
+
+#
+# Test gdb set and show commands.
+# Add tests here for show and set that don't fit neatly elsewhere.
+# FIXME: many rudimentary tests for set and show commands have been
+# added below, but most do nothing more than check that a
+# variable has been set successfully, ie. they do not test
+# whether setting the variable has had the desired effect.
+#
+
+#test default annotation_level is 0
+gdb_test "show annotate" "Annotation_level is 0..*" "default annotation_level is zero"
+
+#test set annotate 2
+send_gdb "set annotate 2\n"
+gdb_expect {
+ -re ".*\032\032pre-prompt.*$gdb_prompt .*\032\032prompt.*$" \
+ { pass "set annotate 2" }
+ -re ".*$gdb_prompt $" { fail "set annotate 2" }
+ timeout { fail "(timeout) set annotate 2" }
+ }
+
+send_gdb "show annotate\n"
+gdb_expect {
+ -re ".*\032\032post-prompt.*Annotation_level is 2..*\032\032pre-prompt.*$gdb_prompt .*\032\032prompt.*$" \
+ { pass "show annotate (2)" }
+ -re ".*$gdb_prompt $" { fail "show annotate (2)" }
+ timeout { fail "(timeout) show annotate (2)" }
+ }
+
+#test annotation_level 2
+send_gdb "info line 1\n"
+gdb_expect {
+ -re ".*\032\032post-prompt.*Line 1 of .* is at address .* but contains no code.*:1:0:beg:0x.*\032\032pre-prompt.*$gdb_prompt .*\032\032prompt.*$" \
+ { pass "annotation_level 2" }
+ -re ".*$gdb_prompt $" { fail "annotation_level 2" }
+ timeout { fail "(timeout) annotation_level 2" }
+ }
+
+#test set annotate 1
+gdb_test "set annotate 1" ".*post-prompt.*" "set annotate 1"
+gdb_test "show annotate" "Annotation_level is 1..*" "show annotate (1)"
+#test annotation_level 1
+gdb_test "info line 1" "Line 1 of .* is at address .* but contains no code.*:1:0:beg:0x.*" "annotation_level 1"
+#test set annotate 0
+gdb_test "set annotate 0" "" "set annotate 0"
+gdb_test "show annotate" "Annotation_level is 0..*" "show annotate (0)"
+#test annotation_level 0
+gdb_test "info line 1" "Line 1 of .* is at address .* but contains no code.*" "annotation_level 0"
+#test set args
+gdb_test "set args foo bar blup baz bubble" "" "set args"
+#test show args
+gdb_test "show args" "Argument list to give program being debugged when it is started is \"foo bar blup baz bubble\"..*" "show args"
+
+# Don't test if we can't pass args or if we're using a stub.
+if { ![target_info exists use_gdb_stub] && ![target_info exists noargs] } {
+ #test passing args
+ gdb_test "cont" "Continuing.*" "continuing"
+ delete_breakpoints
+ gdb_test "run" "Starting program:.*foo bar blup baz bubble.*" "passing args"
+}
+#test set check range on
+gdb_test "set check range on" "" "set check range on"
+#test show check range on
+gdb_test "show check range" "Range checking is \"on\"\..*" "show check range (on)"
+#test set check range auto
+gdb_test "set check range auto" "" "set check range auto"
+#test show check range auto
+gdb_test "show check range" "Range checking is \"auto; currently .*" "show check range (auto)"
+#test set check type on
+gdb_test "set check type on" "" "set check type on"
+#test show check type on
+gdb_test "show check type" "Type checking is \"on\"..*" "show check type (on)"
+#test set check type auto
+gdb_test "set check type auto" "" "set check type auto"
+#test show check type
+gdb_test "show check type" "Type checking is \"auto; currently .*" "show check type (auto)"
+#test set complaints 100
+gdb_test "set complaints 100" "" "set complaints 100"
+#test show complaints 100
+gdb_test "show complaints" "Max number of complaints about incorrect symbols is 100..*" "show complaints (100)"
+#test set complaints 0
+gdb_test "set complaints 0" "" "set complaints 0"
+#test show complaints 0
+gdb_test "show complaints" "Max number of complaints about incorrect symbols is 0..*" "show complaints (0)"
+#test set confirm off
+gdb_test "set confirm off" "" "set confirm off"
+#test show confirm off
+gdb_test "show confirm" "Whether to confirm potentially dangerous operations is off..*" "show confirm (off)"
+#test set confirm on
+gdb_test "set confirm on" "" "set confirm on"
+#test show confirm on
+gdb_test "show confirm" "Whether to confirm potentially dangerous operations is on..*" "show confirm (on)"
+#test set editing off
+gdb_test "set editing off" "" "set editing off"
+#test show editing off
+gdb_test "show editing" "Editing of command lines as they are typed is off..*" "show editing (off)"
+#test set editing on
+#gdb_test "set editing on" "" "set editing on"
+#test show editing on
+#gdb_test "show editing" "Editing of command lines as they are typed is on..*" "show editing (on)"
+#test set environment FOOBARBAZ
+gdb_test "set environment FOOBARBAZ = grbxgrbxgrbx" "" "set environment FOOBARBAZ"
+#test show environment FOOBARBAZ
+gdb_test "show environment FOOBARBAZ" "FOOBARBAZ = grbxgrbxgrbx.*" "show environment FOOBARBAZ"
+#test set height 100
+gdb_test "set height 100" "" "set height 100"
+#test show height 100
+gdb_test "show height" "Number of lines gdb thinks are in a page is 100..*" "show height"
+#test set history expansion on
+gdb_test "set history expansion on" "" "set history expansion on"
+#test show history expansion on
+gdb_test "show history expansion on" "History expansion on command input is on.*" "show history expansion"
+#test set history filename foobar.baz
+gdb_test "set history filename foobar.baz" "" "set history filename foobar.baz"
+#test show history filename foobar.baz
+gdb_test "show history filename" "The filename in which to record the command history is \"foobar.baz\"..*" "show history filename (foobar.baz)"
+#test set history save on
+gdb_test "set history save on" "" "set history save on"
+#test show history save on
+gdb_test "show history save" "Saving of the history record on exit is on..*" "show history save (on)"
+#test set history size 100
+gdb_test "set history size 100" "" "set history size 100"
+#test show history size 100
+gdb_test "show history size" "The size of the command history is 100..*" "show history size (100)"
+#test set language asm
+gdb_test "set language asm" "" "set language asm"
+#test show language asm
+gdb_test "show language" "The current source language is \"asm\"..*" "show language (asm)"
+#test set language auto
+gdb_test "set language auto" "" "set language auto"
+#test show language
+gdb_test "show language" "The current source language is \"auto.*\"..*" "show language (auto)"
+#test set listsize 100
+gdb_test "set listsize 100" "" "set listsize 100"
+#test show listsize 100
+gdb_test "show listsize" "Number of source lines gdb will list by default is 100..*" "show listsize (100)"
+
+if ![board_info target exists gdb_prompt] {
+ #test set prompt (FooBarBaz)
+ set newprompt "\\(FooBarBaz\\)"
+ send_gdb "set prompt (FooBarBaz) \n"
+ gdb_expect {
+ -re "$newprompt $" { pass "set prompt (FooBarBaz) " }
+ timeout { fail "(timeout) set prompt (FooBarBaz) " }
+ }
+
+ #test show prompt (FooBarBaz)
+ send_gdb "show prompt\n"
+ gdb_expect {
+ -re "Gdb's prompt is \"$newprompt \"..* $" \
+ { pass "show prompt (FooBarBaz) " }
+ timeout { fail "(timeout) show prompt (FooBarBaz) " }
+ }
+
+ #test set prompt (gdb)
+ send_gdb "set prompt (gdb) \n"
+ gdb_expect {
+ -re "$gdb_prompt $" { pass "set prompt (gdb) " }
+ timeout { fail "(timeout) set prompt (gdb) " }
+ }
+}
+
+#test set radix 11
+gdb_test "set radix 11" "Unsupported output radix ``decimal 11''; output radix unchanged..*" "set radix 11"
+#test set radix 16
+gdb_test "set radix 16" "Input and output radices now set to decimal 16, hex 10, octal 20..*" "set radix 16"
+#test show radix 16
+gdb_test "show radix" "Input and output radices set to decimal 16, hex 10, octal 20..*" "show radix (16)"
+#test set radix 10
+gdb_test "set radix" "Input and output radices now set to decimal 10, hex a, octal 12..*" "set radix 10"
+#test show radix 10
+gdb_test "show radix" "Input and output radices set to decimal 10, hex a, octal 12..*" "show radix (10)"
+#test set width 90
+gdb_test "set width 90" "" "set width 90"
+#test show width 90
+gdb_test "show width" "Number of characters gdb thinks are in a line is 90..*" "show width (90)"
+#test set write on
+# This is only supported on targets which use exec.o.
+gdb_test "set write on" "" "set write on"
+#test show write on
+# This is only supported on targets which use exec.o.
+gdb_test "show write" "Writing into executable and core files is on..*" "show write (on)"
+#test set symbol-reloading on
+gdb_test "set symbol-reloading on" "" "set symbol-reloading on"
+#test show symbol-reloading on
+gdb_test "show symbol-reloading" "Dynamic symbol table reloading multiple times in one run is on..*" "show symbol-reloading (on)"
+#test show user
+gdb_test "show user" "" "show user"
+#test set verbose on
+gdb_test "set verbose on" "" "set verbose on"
+#test show verbose on
+gdb_test "show verbose" "Verbose printing of informational messages is on..*" "show verbose (on)"
+#test set verbose off
+gdb_test "set verbose off" "" "set verbose off"
+#test show verbose off
+gdb_test "show verbose" "Verbosity is off..*" "show verbose (off)"
diff --git a/gdb/testsuite/gdb.base/setvar.c b/gdb/testsuite/gdb.base/setvar.c
new file mode 100644
index 00000000000..7162155e79f
--- /dev/null
+++ b/gdb/testsuite/gdb.base/setvar.c
@@ -0,0 +1,271 @@
+main (argc, argv, envp)
+ int argc;
+ char **argv;
+ char **envp;
+{
+ extern void dummy();
+#ifdef usestubs
+ set_debug_traps();
+ breakpoint();
+#endif
+ dummy();
+}
+
+/* We put main() right up front so its line number doesn't keep changing. */
+
+/*
+ * Test file with lots of different types, for testing the
+ * "whatis" command.
+ */
+
+/*
+ * First the basic C types.
+ */
+
+#if !defined (__STDC__) && !defined (_AIX)
+#define signed /**/
+#endif
+
+char v_char;
+signed char v_signed_char;
+unsigned char v_unsigned_char;
+
+short v_short;
+signed short v_signed_short;
+unsigned short v_unsigned_short;
+
+int v_int;
+signed int v_signed_int;
+unsigned int v_unsigned_int;
+
+long v_long;
+signed long v_signed_long;
+unsigned long v_unsigned_long;
+
+float v_float;
+double v_double;
+
+/*
+ * Now some derived types, which are arrays, functions-returning,
+ * pointers, structures, unions, and enumerations.
+ */
+
+/**** arrays *******/
+
+char v_char_array[2];
+signed char v_signed_char_array[2];
+unsigned char v_unsigned_char_array[2];
+
+short v_short_array[2];
+signed short v_signed_short_array[2];
+unsigned short v_unsigned_short_array[2];
+
+int v_int_array[2];
+signed int v_signed_int_array[2];
+unsigned int v_unsigned_int_array[2];
+
+long v_long_array[2];
+signed long v_signed_long_array[2];
+unsigned long v_unsigned_long_array[2];
+
+float v_float_array[2];
+double v_double_array[2];
+
+/**** pointers *******/
+
+char *v_char_pointer;
+signed char *v_signed_char_pointer;
+unsigned char *v_unsigned_char_pointer;
+
+short *v_short_pointer;
+signed short *v_signed_short_pointer;
+unsigned short *v_unsigned_short_pointer;
+
+int *v_int_pointer;
+signed int *v_signed_int_pointer;
+unsigned int *v_unsigned_int_pointer;
+
+long *v_long_pointer;
+signed long *v_signed_long_pointer;
+unsigned long *v_unsigned_long_pointer;
+
+float *v_float_pointer;
+double *v_double_pointer;
+
+/**** structs *******/
+
+struct t_struct {
+ char v_char_member;
+ short v_short_member;
+ int v_int_member;
+ long v_long_member;
+ float v_float_member;
+ double v_double_member;
+} v_struct1;
+
+struct {
+ char v_char_member;
+ short v_short_member;
+ int v_int_member;
+ long v_long_member;
+ float v_float_member;
+ double v_double_member;
+} v_struct2;
+
+/**** unions *******/
+
+union t_union {
+ char v_char_member;
+ short v_short_member;
+ int v_int_member;
+ long v_long_member;
+ float v_float_member;
+ double v_double_member;
+} v_union;
+
+union {
+ char v_char_member;
+ short v_short_member;
+ int v_int_member;
+ long v_long_member;
+ float v_float_member;
+ double v_double_member;
+} v_union2;
+
+/*** Functions returning type ********/
+
+char v_char_func () { return(0); }
+signed char v_signed_char_func () { return (0); }
+unsigned char v_unsigned_char_func () { return (0); }
+
+short v_short_func () { return (0); }
+signed short v_signed_short_func () { return (0); }
+unsigned short v_unsigned_short_func () { return (0); }
+
+int v_int_func () { return (0); }
+signed int v_signed_int_func () { return (0); }
+unsigned int v_unsigned_int_func () { return (0); }
+
+long v_long_func () { return (0); }
+signed long v_signed_long_func () { return (0); }
+unsigned long v_unsigned_long_func () { return (0); }
+
+float v_float_func () { return (0.0); }
+double v_double_func () { return (0.0); }
+
+/**** Some misc more complicated things *******/
+
+struct link {
+ struct link *next;
+#ifdef __STDC__
+ struct link *(*linkfunc) (struct link *this, int flags);
+#else
+ struct link *(*linkfunc) ();
+#endif
+ struct t_struct stuff[1][2][3];
+} *s_link;
+
+union tu_link {
+ struct link *next;
+#ifdef __STDC__
+ struct link *(*linkfunc) (struct link *this, int flags);
+#else
+ struct link *(*linkfunc) ();
+#endif
+ struct t_struct stuff[1][2][3];
+} u_link;
+
+/**** Enumerations *******/
+
+enum colors {red, green, blue} color;
+enum cars {chevy, ford, porsche} clunker;
+
+/**** Enumeration bitfields, supported by GNU C *******/
+
+#ifdef __GNUC__
+enum senum {sm1 = -1, s1 = 1};
+struct senum_field {enum senum field:2; } sef;
+enum uenum {u1 = 1, u2 = 2};
+struct uenum_field {enum uenum field:2; } uef;
+#endif
+
+void
+dummy ()
+{
+ /* setvar.exp wants to allocate memory for constants. So make sure malloc
+ gets linked into the program. */
+ malloc (1);
+
+ /* Some linkers (e.g. on AIX) remove unreferenced variables,
+ so make sure to reference them. */
+ v_char = 0;
+ v_signed_char = 1;
+ v_unsigned_char = 2;
+
+ v_short = 3;
+ v_signed_short = 4;
+ v_unsigned_short = 5;
+
+ v_int = 6;
+ v_signed_int = 7;
+ v_unsigned_int = 8;
+
+ v_long = 9;
+ v_signed_long = 10;
+ v_unsigned_long = 11;
+
+ v_float = 100.0;
+ v_double = 200.0;
+
+
+ v_char_array[0] = v_char;
+ v_signed_char_array[0] = v_signed_char;
+ v_unsigned_char_array[0] = v_unsigned_char;
+
+ v_short_array[0] = v_short;
+ v_signed_short_array[0] = v_signed_short;
+ v_unsigned_short_array[0] = v_unsigned_short;
+
+ v_int_array[0] = v_int;
+ v_signed_int_array[0] = v_signed_int;
+ v_unsigned_int_array[0] = v_unsigned_int;
+
+ v_long_array[0] = v_long;
+ v_signed_long_array[0] = v_signed_long;
+ v_unsigned_long_array[0] = v_unsigned_long;
+
+ v_float_array[0] = v_float;
+ v_double_array[0] = v_double;
+
+ v_char_pointer = &v_char;
+ v_signed_char_pointer = &v_signed_char;
+ v_unsigned_char_pointer = &v_unsigned_char;
+
+ v_short_pointer = &v_short;
+ v_signed_short_pointer = &v_signed_short;
+ v_unsigned_short_pointer = &v_unsigned_short;
+
+ v_int_pointer = &v_int;
+ v_signed_int_pointer = &v_signed_int;
+ v_unsigned_int_pointer = &v_unsigned_int;
+
+ v_long_pointer = &v_long;
+ v_signed_long_pointer = &v_signed_long;
+ v_unsigned_long_pointer = &v_unsigned_long;
+
+ v_float_pointer = &v_float;
+ v_double_pointer = &v_double;
+
+ color = red;
+ clunker = porsche;
+
+ u_link.next = s_link;
+
+ v_struct2.v_int_member = v_struct1.v_int_member;
+ v_union2.v_short_member = v_union.v_short_member;
+
+#ifdef __GNUC__
+ sef.field = s1;
+ uef.field = u1;
+#endif
+}
diff --git a/gdb/testsuite/gdb.base/setvar.exp b/gdb/testsuite/gdb.base/setvar.exp
new file mode 100644
index 00000000000..96d3eb45f53
--- /dev/null
+++ b/gdb/testsuite/gdb.base/setvar.exp
@@ -0,0 +1,420 @@
+# Copyright (C) 1997 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# Copyright (C) 1988, 1990, 1991, 1992, 1994, 1995
+# Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file was written by Rob Savoye. (rob@cygnus.com)
+
+if $tracelevel then {
+ strace $tracelevel
+ }
+
+#
+# test running programs
+#
+set prms_id 0
+set bug_id 0
+
+set testfile "setvar"
+set srcfile ${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+# Create and source the file that provides information about the compiler
+# used to compile the test case.
+if [get_compiler_info ${binfile}] {
+ return -1;
+}
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load $binfile
+
+#
+# set it up at a breakpoint so we canplay with the variable values
+#
+send_gdb "set print sevenbit-strings\n" ; gdb_expect -re "$gdb_prompt $"
+
+if ![runto_main] then {
+ perror "couldn't run to breakpoint"
+ continue
+}
+
+# Determine expected output for unsigned long variables,
+# the output varies with sizeof (unsigned long).
+
+set ulong_minus_1 4294967295
+set ulong_minus_456 4294966840
+send_gdb "print sizeof (unsigned long)\n"
+gdb_expect {
+ -re ".\[0-9\]* = 4.*$gdb_prompt $" {}
+ -re ".\[0-9\]* = 8.*$gdb_prompt $" {
+ set ulong_minus_1 18446744073709551615
+ set ulong_minus_456 18446744073709551160
+ }
+ -re ".*$gdb_prompt $" {
+ fail "getting sizeof unsigned long"
+ }
+ default { fail "(timeout) getting sizeof unsigned long" }
+}
+
+proc test_set { args } {
+ global gdb_prompt
+
+ set length [expr [llength $args] - 1];
+ set message "[lindex $args $length]";
+ set final [expr $length - 2];
+ set count 1;
+
+ # Set up the variables.
+ for {set x 0;} {$x < $length} {incr x;} {
+ if { "[lindex $args $x]" != "" } {
+ set arg [lindex $args $x];
+ if { ($x == $final) || ([string first ".*" [lindex $args [expr $x + 1]]] >= 0) } {
+ set match [lindex $args [expr $x + 1]];
+ if { $count == 1 } {
+ set mess "$message"
+ } else {
+ set mess "$message (#$count)";
+ }
+ incr count;
+ incr x;
+ } else {
+ set mess "";
+ set match ""
+ }
+ verbose "doing $arg $match"
+ if [gdb_test "$arg" "$match" "$mess"] {
+ fail "$message -- $match";
+ return 1;
+ }
+ }
+ }
+ return 0;
+}
+
+#
+# test "set variable" for type "char"
+#
+# Because bare char types can be either signed or unsigned, we just test the
+# range of values that are common to both (0-127).
+#
+
+test_set "set variable v_char=0" "print v_char" ".\[0-9\]* = 0 \'.000\'" "set variable char=0"
+test_set "set variable v_char=1" "print v_char" ".\[0-9\]* = 1 \'.001\'" "set variable char=1"
+test_set "set variable v_char=27" "print v_char" ".\[0-9\]* = 27 \'.e\'" "set variable char=27 (Esc)"
+test_set "set variable v_char=32" "print v_char" ".\[0-9\]* = 32 \' \'" "set variable char=32 (SPC)"
+test_set "set variable v_char=65" "print v_char" ".\[0-9\]* = 65 \'A\'" "set variable char=65 ('A')"
+test_set "set variable v_char=97" "print v_char" ".\[0-9\]* = 97 \'a\'" "set variable char=97 ('a')"
+test_set "set variable v_char=126" "print v_char" ".\[0-9\]* = 126 \'~\'" "set variable char=126 ('~')"
+test_set "set variable v_char=127" "print v_char" ".\[0-9\]* = 127 \'.177\'" "set variable char=127 (8-bit)"
+#
+# test "set variable" for type "signed char"
+#
+test_set "set variable v_char=0" "print v_signed_char" ".\[0-9\]* = 0 \'.000\'" "set variable signed char=0"
+test_set "set variable v_signed_char=1" "print v_signed_char" ".\[0-9\]* = 1 \'.001\'" "set variable signed char=1"
+test_set "set variable v_signed_char=27" "print v_signed_char" ".\[0-9\]* = 27 \'.e\'" "set variable signed char=27 (Esc)"
+test_set "set variable v_signed_char=32" "print v_signed_char" ".\[0-9\]* = 32 \' \'" "set variable signed char=32 (SPC)"
+test_set "set variable v_signed_char=65" "print v_signed_char" ".\[0-9\]* = 65 \'A\'" "set variable signed char=65 ('A')"
+test_set "set variable v_signed_char=97" "print v_signed_char" ".\[0-9\]* = 97 \'a\'" "set variable signed char=97 ('a')"
+test_set "set variable v_signed_char=126" "print v_signed_char" ".\[0-9\]* = 126 \'~\'" "set variable signed char=126 ('~')"
+test_set "set variable v_signed_char=127" "print v_signed_char" ".\[0-9\]* = 127 \'.177\'" "set variable signed char=127 (8-bit)"
+gdb_test "set variable v_signed_char=-1" ""
+if {!$gcc_compiled} then { setup_xfail "mips-sgi-irix4*" }
+gdb_test "print v_signed_char" ".\[0-9\]* = -1 \'.377\'" \
+ "set variable signed char=-1 (-1)"
+gdb_test "set variable v_signed_char=0xFF" ""
+if {!$gcc_compiled} then { setup_xfail "mips-sgi-irix4*" }
+gdb_test "print v_signed_char" ".\[0-9\]* = -1 \'.377\'" \
+ "set variable signed char=0xFF (0xFF)"
+#
+# test "set variable" for type "unsigned char"
+#
+test_set "set variable v_unsigned_char=0" "print v_unsigned_char" ".\[0-9\]* = 0 \'.000\'" "set variable unsigned char=0"
+test_set "set variable v_unsigned_char=1" "print v_unsigned_char" ".\[0-9\]* = 1 \'.001\'" "set variable unsigned char=1"
+test_set "set variable v_unsigned_char=27" "print v_unsigned_char" ".\[0-9\]* = 27 \'.e\'" "set variable unsigned char=27 (Esc)"
+test_set "set variable v_unsigned_char=32" "print v_unsigned_char" ".\[0-9\]* = 32 \' \'" "set variable unsigned char=32 (SPC)"
+test_set "set variable v_unsigned_char=65" "print v_unsigned_char" ".\[0-9\]* = 65 \'A\'" "set variable unsigned char=65 ('A')"
+test_set "set variable v_unsigned_char=97" "print v_unsigned_char" ".\[0-9\]* = 97 \'a\'" "set variable unsigned char=97 ('a')"
+test_set "set variable v_unsigned_char=126" "print v_unsigned_char" ".\[0-9\]* = 126 \'~\'" "set variable unsigned char=126 ('~')"
+test_set "set variable v_unsigned_char=~0" "print v_unsigned_char" ".\[0-9\]* = 255 \'.377\'" "set variable unsigned char=255 (8-bit)"
+#
+# test "set variable" for type "short"
+#
+test_set "set variable v_short=0" "print v_short" ".\[0-9\]* = 0" "set variable short=0"
+test_set "set variable v_short=1" "print v_short" ".\[0-9\]* = 1" "set variable short=1"
+test_set "set variable v_short=-1" "print v_short" ".\[0-9\]* = -1" "set variable short=-1 (minus)"
+#
+# test "set variable" for type "signed short"
+#
+test_set "set variable v_signed_short=0" "print v_signed_short" ".\[0-9\]* = 0" "set variable signed short=0"
+test_set "set variable v_signed_short=1" "print v_signed_short" ".\[0-9\]* = 1" "set variable signed short=1"
+test_set "set variable v_signed_short=-1" "print v_signed_short" ".\[0-9\]* = -1" "set variable signed short=-1 (minus)"
+#
+# test "set variable" for type "unsigned short"
+#
+test_set "set variable v_unsigned_short=0" "print v_unsigned_short" ".\[0-9\]* = 0" "set variable unsigned short=0"
+test_set "set variable v_unsigned_short=1" "print v_unsigned_short" ".\[0-9\]* = 1" "set variable unsigned short=1"
+test_set "set variable v_unsigned_short=~0" "print v_unsigned_short" ".\[0-9\]* = 65535" "set variable unsigned short=~0 (minus)"
+#
+# test "set variable" for type "int"
+#
+test_set "set variable v_int=0" "print v_int" ".\[0-9\]* = 0" "set variable int=0"
+test_set "set variable v_int=1" "print v_int" ".\[0-9\]* = 1" "set variable int=1"
+test_set "set variable v_int=-1" "print v_int" ".\[0-9\]* = -1" "set variable int=-1 (minus)"
+#
+# test "set variable" for type "signed int"
+#
+test_set "set variable v_signed_int=0" "print v_signed_int" ".\[0-9\]* = 0" "set variable signed int=0"
+test_set "set variable v_signed_int=1" "print v_signed_int" ".\[0-9\]* = 1" "set variable signed int=1"
+test_set "set variable v_signed_int=-1" "print v_signed_int" ".\[0-9\]* = -1" "set variable signed int=-1 (minus)"
+#
+# test "set variable" for type "unsigned int"
+#
+test_set "set variable v_unsigned_int=0" "print v_unsigned_int" ".\[0-9\]* = 0" "set variable unsigned int=0"
+test_set "set variable v_unsigned_int=1" "print v_unsigned_int" ".\[0-9\]* = 1" "set variable unsigned int=1"
+test_set "set variable v_unsigned_int=~0" "print v_unsigned_int" ".\[0-9\]* = (4294967295|65535)" "set variable unsigned int=~0 (minus)"
+#test_set ".\[0-9\]* = 65535" "set variable unsigned int=~0 (minus)"
+#
+# test "set variable" for type "long"
+#
+test_set "set variable v_long=0" "print v_long" ".\[0-9\]* = 0" "set variable long=0"
+test_set "set variable v_long=1" "print v_long" ".\[0-9\]* = 1" "set variable long=1"
+test_set "set variable v_long=-1" "print v_long" ".\[0-9\]* = -1" "set variable long=-1 (minus)"
+#
+# test "set variable" for type "signed long"
+#
+test_set "set variable v_signed_long=0" "print v_signed_long" ".\[0-9\]* = 0" "set variable signed long=0"
+test_set "set variable v_signed_long=1" "print v_signed_long" ".\[0-9\]* = 1" "set variable signed long=1"
+test_set "set variable v_signed_long=-1" "print v_signed_long" ".\[0-9\]* = -1" "set variable signed long=-1 (minus)"
+#
+# test "set variable" for type "unsigned long"
+#
+test_set "set variable v_unsigned_long=0" "print v_unsigned_long" ".\[0-9\]* = 0" "set variable unsigned long=0"
+test_set "set variable v_unsigned_long=1" "print v_unsigned_long" ".\[0-9\]* = 1" "set variable unsigned long=1"
+test_set "set variable v_unsigned_long=~0" "print v_unsigned_long" ".\[0-9\]* = $ulong_minus_1" "set variable unsigned long=~0 (minus)"
+#
+# test "set variable" for type "float"
+#
+test_set "set variable v_float=0.0" "print v_float" ".\[0-9\]* = 0" "set variable float=0"
+test_set "set variable v_float=1.0" "print v_float" ".\[0-9\]* = 1" "set variable float=1"
+test_set "set variable v_float=-1.0" "print v_float" ".\[0-9\]* = -1" "set variable float=-1 (minus)"
+#
+# test "set variable" for type "double"
+#
+test_set "set variable v_double=0.0" "print v_double" ".\[0-9\]* = 0" "set variable double=0"
+test_set "set variable v_double=1.0" "print v_double" ".\[0-9\]* = 1" "set variable double=1"
+test_set "set variable v_double=-1.0" "print v_double" ".*.\[0-9\]* = -1" "set variable double=-1 (minus)"
+#
+# test "set variable" for "char array[2]"
+#
+test_set "set variable v_char_array\[0\]='h'" "set variable v_char_array\[1\]='i'" "print v_char_array" ".*.\[0-9\]* =.*\"hi\"" "set variable char array=\"hi\" (string)"
+#
+# test "set variable" for "signed char array[2]"
+#
+test_set "set variable v_signed_char_array\[0\]='h'" "set variable v_signed_char_array\[1\]='i'" "print v_signed_char_array" ".*.\[0-9\]* =.*\"hi\"" "set variable signed char array=\"hi\" (string)"
+#
+# test "set variable" for "unsigned char array[2]"
+#
+test_set "set variable v_unsigned_char_array\[0\]='h'" "set variable v_unsigned_char_array\[1\]='i'" "print v_unsigned_char_array" ".*.\[0-9\]* =.*\"hi\"" "set variable unsigned char array=\"hi\" (string)"
+#
+# test "set variable" for "short array[2]"
+#
+test_set "set variable v_short_array\[0\]=123" "set variable v_short_array\[1\]=-456" "print v_short_array" ".*.\[0-9\]* =.*\{123,.*-456\}" "set variable short array"
+#
+# test "set variable" for "signed short array[2]"
+#
+test_set "set variable v_signed_short_array\[0\]=123" "set variable v_signed_short_array\[1\]=-456" "print v_signed_short_array" ".*.\[0-9\]* =.*\{123,.*-456\}" "set variable signed short array"
+#
+# test "set variable" for "unsigned short array[2]"
+#
+test_set "set variable v_unsigned_short_array\[0\]=123" "set variable v_unsigned_short_array\[1\]=-456" "print v_unsigned_short_array" ".*.\[0-9\]* =.*\{123,.*65080\}" "set variable unsigned short array"
+#
+# test "set variable" for "int array[2]"
+#
+test_set "set variable v_int_array\[0\]=123" "set variable v_int_array\[1\]=-456" "print v_int_array" ".*.\[0-9\]* =.*\{123,.*-456\}" "set variable int array"
+#
+# test "set variable" for "signed int array[2]"
+#
+test_set "set variable v_signed_int_array\[0\]=123" "set variable v_signed_int_array\[1\]=-456" "print v_signed_int_array" ".*.\[0-9\]* =.*\{123,.*-456\}" "set variable signed int array"
+#
+# test "set variable" for "unsigned int array[2]"
+#
+test_set "set variable v_unsigned_int_array\[0\]=123" "set variable v_unsigned_int_array\[1\]=-456" "print v_unsigned_int_array" ".*.\[0-9\]* =.*\{123,.*(4294966840|65080)\}" "set variable unsigned int array"
+#
+# test "set variable" for "long array[2]"
+#
+test_set "set variable v_long_array\[0\]=123" "set variable v_long_array\[1\]=-456" "print v_long_array" ".*.\[0-9\]* =.*\{123,.*-456\}" "set variable long array"
+#
+# test "set variable" for "signed long array[2]"
+#
+test_set "set variable v_signed_long_array\[0\]=123" "set variable v_signed_long_array\[1\]=-456" "print v_signed_long_array" ".*.\[0-9\]* =.*\{123,.*-456\}" "set variable signed long array"
+#
+# test "set variable" for "unsigned long array[2]"
+#
+test_set "set variable v_unsigned_long_array\[0\]=123" "set variable v_unsigned_long_array\[1\]=-456" "print v_unsigned_long_array" ".*.\[0-9\]* =.*\{123,.*$ulong_minus_456\}" "set variable unsigned long array"
+#
+# test "set variable" for "float array[2]"
+#
+test_set "set variable v_float_array\[0\]=123.0" "set variable v_float_array\[1\]=-456.0" "print v_float_array" ".*.\[0-9\]* =.*\{123,.*-456\}" "set variable float array"
+#
+# test "set variable" for "double array[2]"
+#
+test_set "set variable v_double_array\[0\]=123.0" "set variable v_double_array\[1\]=-456.0" "print v_double_array" ".*.\[0-9\]* =.*\{123,.*-456\}" "set variable double array"
+#
+# test "set variable" for type "char *"
+#
+test_set "set v_char_pointer=v_char_array" "set variable *(v_char_pointer)='h'" "set variable *(v_char_pointer+1)='i'" "print v_char_array" ".*.\[0-9\]* =.*\"hi\"" "print *(v_char_pointer+1)" ".*.\[0-9\]* = 105 \'i\'" "set variable char pointer=\"hi\" (string)"
+#
+# test "set variable" for type "signed char *"
+#
+test_set "set v_signed_char_pointer=v_signed_char_array" "set variable *(v_signed_char_pointer)='h'" "set variable *(v_signed_char_pointer+1)='i'" "print v_signed_char_array" ".*.\[0-9\]* =.*\"hi\"" "print *(v_signed_char_pointer+1)" ".*.\[0-9\]* = 105 \'i\'" "set variable signed char pointer=\"hi\" (string)"
+#
+# test "set variable" for type "unsigned char *"
+#
+test_set "set v_unsigned_char_pointer=v_unsigned_char_array" "set variable *(v_unsigned_char_pointer)='h'" "set variable *(v_unsigned_char_pointer+1)='i'" "print v_unsigned_char_array" ".*.\[0-9\]* =.*\"hi\"" "print *(v_unsigned_char_pointer+1)" ".*.\[0-9\]* = 105 \'i\'" "set variable unsigned char pointer=\"hi\" (string)"
+#
+# test "set variable" for type "short *"
+#
+test_set "set v_short_pointer=v_short_array" "set variable *(v_short_pointer)=123" "set variable *(v_short_pointer+1)=-456" "print v_short_array" ".*.\[0-9\]* =.*\{123,.*-456\}" "print *(v_short_pointer+1)" ".*.\[0-9\]* = -456" "set variable short pointer"
+#
+# test "set variable" for type "signed short *"
+#
+gdb_test "set v_signed_short_pointer=v_signed_short_array" ""
+gdb_test "set variable *(v_signed_short_pointer)=123" ""
+gdb_test "set variable *(v_signed_short_pointer+1)=-456" ""
+gdb_test "print v_signed_short_array" ".\[0-9\]* =.*\{123,.*-456\}" \
+ "set variable signed short pointer"
+gdb_test "print *(v_signed_short_pointer+1)" ".\[0-9\]*.*=.*-456"
+#
+# test "set variable" for type "unsigned short *"
+#
+gdb_test "set v_unsigned_short_pointer=v_unsigned_short_array" ""
+gdb_test "set variable *(v_unsigned_short_pointer)=123" ""
+gdb_test "set variable *(v_unsigned_short_pointer+1)=-456" ""
+gdb_test "print v_unsigned_short_array" ".\[0-9\]* =.*\{123,.*65080\}" \
+ "set variable unsigned short pointer"
+gdb_test "print *(v_unsigned_short_pointer+1)" ".\[0-9\]* = 65080"
+#
+# test "set variable" for type "int *"
+#
+test_set "set v_int_pointer=v_int_array" "set variable *(v_int_pointer)=123" "set variable *(v_int_pointer+1)=-456" "print v_int_array" ".*.\[0-9\]* =.*\{123,.*-456\}" "print *(v_int_pointer+1)" ".*.\[0-9\]* = -456" "set variable int pointer"
+#
+# test "set variable" for type "signed int *"
+#
+test_set "set v_signed_int_pointer=v_signed_int_array" "set variable *(v_signed_int_pointer)=123" "set variable *(v_signed_int_pointer+1)=-456" "print v_signed_int_array" ".*.\[0-9\]* =.*\{123,.*-456\}" "print *(v_signed_int_pointer+1)" ".*.\[0-9\]* = -456" "set variable signed int pointer"
+#
+# test "set variable" for type "unsigned int *"
+#
+test_set "set v_unsigned_int_pointer=v_unsigned_int_array" "set variable *(v_unsigned_int_pointer)=123" "set variable *(v_unsigned_int_pointer+1)=-456" "print v_unsigned_int_array" ".*.\[0-9\]* =.*\{123,.*(4294966840|65080)\}" "set variable unsigned int pointer"
+test_set "" "print *(v_unsigned_int_pointer+1)" ".*.\[0-9\]* = (4294966840|65080)" "print variable unsigned int pointer+1"
+#
+# test "set variable" for type "long *"
+#
+test_set "set v_long_pointer=v_long_array" "set variable *(v_long_pointer)=123" "set variable *(v_long_pointer+1)=-456" "print v_long_array" ".*.\[0-9\]* =.*\{123,.*-456\}" "print *(v_long_pointer+1)" ".*.\[0-9\]* = -456" "set variable long pointer"
+#
+# test "set variable" for type "signed long *"
+#
+test_set "set v_signed_long_pointer=v_signed_long_array" "set variable *(v_signed_long_pointer)=123" "set variable *(v_signed_long_pointer+1)=-456" "print v_signed_long_array" ".*.\[0-9\]* =.*\{123,.*-456\}" "print *(v_signed_long_pointer+1)" ".*.\[0-9\]* = -456" "set variable signed long pointer"
+#
+# test "set variable" for type "unsigned long *"
+#
+test_set "set v_unsigned_long_pointer=v_unsigned_long_array" "set variable *(v_unsigned_long_pointer)=123" "set variable *(v_unsigned_long_pointer+1)=-456" "print v_unsigned_long_array" ".*.\[0-9\]* =.*\{123,.*$ulong_minus_456\}" "print *(v_unsigned_long_pointer+1)" ".*.\[0-9\]* = $ulong_minus_456" "set variable unsigned long pointer"
+#
+# test "set variable" for type "float *"
+#
+test_set "set v_float_pointer=v_float_array" "set variable *(v_float_pointer)=123.0" "set variable *(v_float_pointer+1)=-456.0" "print v_float_array" ".*.\[0-9\]* =.*\{123,.*-456\}" "print *(v_float_pointer+1)" ".*.\[0-9\]* = -456" "set variable float pointer"
+#
+# test "set variable" for type "double *"
+#
+test_set "set v_double_pointer=v_double_array" "set variable *(v_double_pointer)=123.0" "set variable *(v_double_pointer+1)=-456.0" "print v_double_array" ".*.\[0-9\]* =.*\{123,.*-456\}" "print *(v_double_pointer+1)" ".*.\[0-9\]* = -456" "set variable double pointer"
+#
+# test "set variable" for struct members
+#
+test_set "set variable v_struct1.v_char_member='h'" "print v_struct1.v_char_member" ".*.\[0-9\]* = 104 \'h\'" "set variable structure char member"
+test_set "set variable v_struct1.v_short_member=1" "print v_struct1.v_short_member" ".*.\[0-9\]* = 1" "set variable structure short member"
+test_set "set variable v_struct1.v_int_member=2" "print v_struct1.v_int_member" ".*.\[0-9\]* = 2" "set variable structure int member"
+test_set "set variable v_struct1.v_long_member=3" "print v_struct1.v_long_member" ".*.\[0-9\]* = 3" "set variable structure long member"
+test_set "set variable v_struct1.v_float_member=4.0" "print v_struct1.v_float_member" ".*.\[0-9\]* = 4" "set variable structure float member"
+test_set "set variable v_struct1.v_double_member=5.0" "print v_struct1.v_double_member" ".*.\[0-9\]* = 5" "set variable structure double member"
+
+gdb_test "print v_struct1" \
+ ".*.\[0-9\]* = \{.*v_char_member = 104 \'h\',.*v_short_member = 1,\
+.*v_int_member = 2,.*\
+v_long_member = 3,.*v_float_member = 4,.*v_double_member = 5.*\}" \
+ "set print structure #1"
+
+# This should be an error. GCC extensions for structure constants require
+# the type of the structure to be specified, as in
+# v_struct1 = (struct t_struct) {32, 33, 34, 35, 36, 37}
+# GDB should do the same if it wants to provide this feature.
+if [target_info exists gdb,cannot_call_functions] {
+ setup_xfail "*-*-*" 2416
+ fail "set variable v_struct1 = {32, 33, 34, 35, 36, 37}"
+ continue
+}
+gdb_test "set variable v_struct1 = {32, 33, 34, 35, 36, 37}" "Invalid.*"
+
+# And after the error the structure should be unchanged.
+gdb_test "print v_struct1" \
+ ".*.\[0-9\]* = \{.*v_char_member = 104 \'h\',.*v_short_member = 1,\
+.*v_int_member = 2,.*\
+v_long_member = 3,.*v_float_member = 4,.*v_double_member = 5.*\}" \
+ "set print structure #2"
+
+# Test printing of enumeration bitfields.
+# GNU C supports them, some other compilers don't.
+
+if {$gcc_compiled} then {
+ gdb_test "print sef.field=sm1" ".*.\[0-9\]* = sm1"
+ gdb_test "print sef.field" ".*.\[0-9\]* = sm1" "print sef.field (sm1)"
+ gdb_test "print sef.field=s1" ".*.\[0-9\]* = s1"
+ gdb_test "print sef.field" ".*.\[0-9\]* = s1" "print sef.field (s1)"
+ gdb_test "print uef.field=u2" ".*.\[0-9\]* = u2"
+ gdb_test "print uef.field" ".*.\[0-9\]* = u2" "print uef.field (u2)"
+ gdb_test "print uef.field=u1" ".*.\[0-9\]* = u1"
+ gdb_test "print uef.field" ".*.\[0-9\]* = u1" "print uef.field (u1)"
+
+ # Test for truncation when assigning invalid values to bitfields.
+ gdb_test "print sef.field=7" \
+ ".*warning: Value does not fit in 2 bits.*\[0-9\]* = sm1"
+ gdb_test "print uef.field=6" \
+ ".*warning: Value does not fit in 2 bits.*\[0-9\]* = u2"
+}
diff --git a/gdb/testsuite/gdb.base/shlib-call.exp b/gdb/testsuite/gdb.base/shlib-call.exp
new file mode 100644
index 00000000000..414d7427f01
--- /dev/null
+++ b/gdb/testsuite/gdb.base/shlib-call.exp
@@ -0,0 +1,258 @@
+# Copyright (C) 1997, 1998 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# file to test calls into shared libraries
+# the source files for this test are:
+#
+# shmain.c
+# shr1.c (shared lib)
+# shr2.c (shared lib)
+# ss.h (header for shr2.c)
+#
+# file written by Elena Zannoni: elz@ch.apollo.com
+#
+
+#debug shmain
+#prop lib shr1.sl
+#prop lib shr2.sl
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+set prms_id 0
+set bug_id 0
+
+# are we on a target board?
+if ![isnative] then {
+ return 0
+}
+
+set testfile "shmain"
+set libfile "shr"
+set srcfile ${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+
+# build the first test case
+if [get_compiler_info ${binfile}] {
+ return -1
+}
+
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}.o" object {debug}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+
+# Build the shared libraries this test case needs.
+#
+
+if {$gcc_compiled == 0} {
+ if [istarget "hppa*-hp-hpux*"] then {
+ set additional_flags "additional_flags=+z"
+ } else {
+ # don't know what the compiler is...
+ set additional_flags ""
+ }
+} else {
+ set additional_flags "additional_flags=-fpic"
+}
+
+if {[gdb_compile "${srcdir}/${subdir}/${libfile}1.c" "${objdir}/${subdir}/${libfile}1.o" object [list debug $additional_flags]] != ""} {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+if {[gdb_compile "${srcdir}/${subdir}/${libfile}2.c" "${objdir}/${subdir}/${libfile}2.o" object [list debug $additional_flags]] != ""} {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+if [istarget "hppa*-*-hpux*"] {
+ remote_exec build "ld -b ${objdir}/${subdir}/${libfile}1.o -o ${objdir}/${subdir}/${libfile}1.sl"
+ remote_exec build "ld -b ${objdir}/${subdir}/${libfile}2.o -o ${objdir}/${subdir}/${libfile}2.sl"
+} else {
+ set additional_flags "additional_flags=-shared"
+ if {[gdb_compile "${objdir}/${subdir}/${libfile}1.o" "${objdir}/${subdir}/${libfile}1.sl" executable [list debug $additional_flags]] != ""} {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+ }
+ if {[gdb_compile "${objdir}/${subdir}/${libfile}2.o" "${objdir}/${subdir}/${libfile}2.sl" executable [list debug $additional_flags]] != ""} {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+ }
+}
+if {[gdb_compile "${objdir}/${subdir}/${testfile}.o ${objdir}/${subdir}/${libfile}1.sl ${objdir}/${subdir}/${libfile}2.sl" "${binfile}" executable {debug}] != ""} {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+
+
+# Start with a fresh gdb.
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+send_gdb "set print sevenbit-strings\n" ; gdb_expect -re "$gdb_prompt $"
+send_gdb "set print address off\n" ; gdb_expect -re "$gdb_prompt $"
+send_gdb "set width 0\n" ; gdb_expect -re "$gdb_prompt $"
+
+
+if ![runto_main] then {
+ perror "C function calling tests suppressed"
+}
+
+
+#step -over
+
+ send_gdb "next\n"
+ gdb_expect {
+ -re ".*g = shr1\\(g\\).*$gdb_prompt $" {pass "next to shr2"}
+ -re ".*$gdb_prompt $" { fail "next to shr2" }
+ timeout { fail "next to shr2 (timeout)" }
+ }
+
+
+
+#print g
+
+send_gdb "print g\n"
+gdb_expect {
+ -re ".*\[0-9\]* = 1.*$gdb_prompt $" {
+ pass "print g"
+ }
+ -re ".*$gdb_prompt $" { fail "print g" }
+ timeout { fail "(timeout) print g" }
+ }
+
+
+#step -over
+ send_gdb "next\n"
+ gdb_expect {
+ -re ".*address of sgs is $hex.*g = shr2\\(g\\).*$gdb_prompt $" {
+ pass "next over shr1" }
+ -re ".*$gdb_prompt $" { fail "next over shr1" }
+ timeout { fail "next over shr1 (timeout)" }
+ }
+
+#print g
+send_gdb "print g\n"
+gdb_expect {
+ -re ".*\[0-9\]* = 2.*$gdb_prompt $" {
+ pass "print g" }
+ -re ".*$gdb_prompt $" { fail "print g" }
+ timeout { fail "(timeout) print g" }
+ }
+
+#print shr1(1)
+send_gdb "print shr1(1)\n"
+gdb_expect {
+ -re ".*address of sgs is $hex.*\[0-9\]* = 2.*$gdb_prompt $" {
+ pass "print shr1(1)" }
+ -re ".*$gdb_prompt $" { fail "print shr1(1)" }
+ timeout { fail "(timeout) print shr1(1)" }
+ }
+
+#print shr1(g)
+send_gdb "print shr1(g)\n"
+gdb_expect {
+ -re ".*address of sgs is $hex.*\[0-9\]* = 4.*$gdb_prompt $" {
+ pass "print shr1(g)" }
+ -re ".*$gdb_prompt $" { fail "print shr1(g)" }
+ timeout { fail "(timeout) print shr1(g)" }
+ }
+
+#break shr2
+#go
+gdb_test "break shr2" \
+ "Breakpoint.*file.*shr2.c, line.*" \
+ "breakpoint function shr2"
+
+gdb_test continue "Continuing\\..*Breakpoint \[0-9\]+, shr2 \\(.*\\) at.*shr2\\.c:3.*3.*return 2.x;" \
+"run until breakpoint set at a function"
+
+
+#print shr1(1)
+send_gdb "print shr1(1)\n"
+gdb_expect {
+ -re ".*address of sgs is $hex.*\[0-9\]* = 2.*$gdb_prompt $" {
+ pass "print shr1(1)"
+ }
+ -re ".*$gdb_prompt $" { fail "print shr1(1)" }
+ timeout { fail "(timeout) print shr1(1)" }
+ }
+
+#print mainshr1(1)
+send_gdb "print mainshr1(1)\n"
+gdb_expect {
+ -re ".*\[0-9\]* = 2.*$gdb_prompt $" {
+ pass "print mainshr1(1) from shlib func"
+ }
+ -re ".*$gdb_prompt $" { fail "print mainshr1(1) from shlib func" }
+ timeout { fail "(timeout) print mainshr1(1) from shlib func" }
+ }
+
+#step -return
+ send_gdb "step\n"
+ gdb_expect {
+ -re ".*\\\}.*$gdb_prompt $" { pass "step inside shr2 (shlib func)"}
+ -re ".*$gdb_prompt $" { fail "step inside shr2 (shlib func)" }
+ timeout { fail "step inside shr2 (shlib func) (timeout)" }
+ }
+
+ send_gdb "step\n"
+ gdb_expect {
+ -re "main \\(\\) at.*g = mainshr1\\(g\\);.*$gdb_prompt $" { pass "step out of shr2 to main"}
+ -re ".*$gdb_prompt $" { fail "step out of shr2 to main" }
+ timeout { fail "step out of shr2 to main (timeout)" }
+ }
+
+#print mainshr1(1)
+send_gdb "print mainshr1(1)\n"
+gdb_expect {
+ -re ".*\[0-9\]* = 2.*$gdb_prompt $" {
+ pass "print mainshr1(1)"
+ }
+ -re ".*$gdb_prompt $" { fail "print mainshr1(1) from main" }
+ timeout { fail "(timeout) print mainshr1(1) from main" }
+ }
+
+#step
+ send_gdb "step\n"
+ gdb_expect {
+ -re ".*mainshr1 \\(g=4\\) at.*return 2.g;.*$gdb_prompt $" { pass "step into mainshr1"}
+ -re ".*$gdb_prompt $" { fail "step into mainshr1" }
+ timeout { fail "step into mainshr1 (timeout)" }
+ }
+
+# Start with a fresh gdb.
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+send_gdb "set print sevenbit-strings\n" ; gdb_expect -re "$gdb_prompt $"
+send_gdb "set print address off\n" ; gdb_expect -re "$gdb_prompt $"
+send_gdb "set width 0\n" ; gdb_expect -re "$gdb_prompt $"
+
+# PR's 16495, 18213
+# test that we can re-set breakpoints in shared libraries
+gdb_test "break shr1" "Breakpoint 1 at .*" "set bp in shared library"
+gdb_test "run" "Starting program:.*Breakpoint 1,.*" "run to bp in shared library"
+gdb_test "cont" "Program exited normally."
+gdb_test "run" "Starting program:.*Breakpoint 1,.*" "re-run to bp in shared library (PR's 16495, 18213)"
+gdb_test "cont" "Program exited normally."
+
+return 0
diff --git a/gdb/testsuite/gdb.base/shmain.c b/gdb/testsuite/gdb.base/shmain.c
new file mode 100644
index 00000000000..dda5091cdc1
--- /dev/null
+++ b/gdb/testsuite/gdb.base/shmain.c
@@ -0,0 +1,47 @@
+/* A test */
+
+#include "ss.h"
+#include <stdio.h>
+
+extern int shr1();
+extern int shr2();
+extern float sg;
+
+int eglob;
+
+struct {
+ int a;
+ int b;
+} s;
+
+int g;
+
+int local_structarg(x)
+struct s x;
+{
+ return x.b;
+}
+
+main()
+{
+ struct s y;
+ g = 1;
+ g = shr1(g);
+ g = shr2(g);
+ g = mainshr1(g);
+ sg = 1.1;
+ printf("address of sg is 0x%x\n", &sg);
+ y.a = 3;
+ y.b = 4;
+ g = local_structarg(y);
+ g = structarg(y);
+ g = pstructarg(&y);
+
+ return (0);
+}
+
+int mainshr1(g)
+int g;
+{
+ return 2*g;
+}
diff --git a/gdb/testsuite/gdb.base/shr1.c b/gdb/testsuite/gdb.base/shr1.c
new file mode 100644
index 00000000000..0efaff5ec14
--- /dev/null
+++ b/gdb/testsuite/gdb.base/shr1.c
@@ -0,0 +1,47 @@
+#include "ss.h"
+#include <stdio.h>
+
+typedef float f;
+
+float sg = 5.5;
+int sgi = 2;
+static int sgs = 7;
+
+int shr1(x)
+int x;
+{
+ f mumble;
+ int l;
+ l = 1;
+ {
+ int l;
+ l = 2;
+ }
+ mumble = 7.7;
+ sg = 6.6;
+ sgi++;
+ sgs = 8;
+ printf("address of sgs is 0x%x\n", &sgs);
+ return 2*x;
+}
+
+static int shr1_local(x)
+int x;
+{
+ return 2*x;
+}
+
+int structarg(x)
+struct s x;
+{
+ return x.a;
+}
+
+int pstructarg(x)
+struct s *x;
+{
+ return x->a;
+}
+
+
+
diff --git a/gdb/testsuite/gdb.base/shr2.c b/gdb/testsuite/gdb.base/shr2.c
new file mode 100644
index 00000000000..94d5df962a5
--- /dev/null
+++ b/gdb/testsuite/gdb.base/shr2.c
@@ -0,0 +1,11 @@
+int shr2(x)
+{
+ return 2*x;
+}
+
+int shr2_local(x)
+{
+ return 2*x;
+}
+
+
diff --git a/gdb/testsuite/gdb.base/sigall.c b/gdb/testsuite/gdb.base/sigall.c
new file mode 100644
index 00000000000..1ab08e732ea
--- /dev/null
+++ b/gdb/testsuite/gdb.base/sigall.c
@@ -0,0 +1,1383 @@
+#include <signal.h>
+
+#ifdef __sh__
+#define signal(a,b) /* Signals not supported on this target - make them go away */
+#endif
+
+/* Signal handlers, we set breakpoints in them to make sure that the
+ signals really get delivered. */
+
+void
+handle_ABRT (sig)
+ int sig;
+{
+}
+
+void
+handle_HUP (sig)
+ int sig;
+{
+}
+
+void
+handle_QUIT (sig)
+ int sig;
+{
+}
+
+void
+handle_ILL (sig)
+ int sig;
+{
+}
+
+void
+handle_EMT (sig)
+ int sig;
+{
+}
+
+void
+handle_FPE (sig)
+ int sig;
+{
+}
+
+void
+handle_BUS (sig)
+ int sig;
+{
+}
+
+void
+handle_SEGV (sig)
+ int sig;
+{
+}
+
+void
+handle_SYS (sig)
+ int sig;
+{
+}
+
+void
+handle_PIPE (sig)
+ int sig;
+{
+}
+
+void
+handle_ALRM (sig)
+ int sig;
+{
+}
+
+void
+handle_URG (sig)
+ int sig;
+{
+}
+
+void
+handle_TSTP (sig)
+ int sig;
+{
+}
+
+void
+handle_CONT (sig)
+ int sig;
+{
+}
+
+void
+handle_CHLD (sig)
+ int sig;
+{
+}
+
+void
+handle_TTIN (sig)
+ int sig;
+{
+}
+
+void
+handle_TTOU (sig)
+ int sig;
+{
+}
+
+void
+handle_IO (sig)
+ int sig;
+{
+}
+
+void
+handle_XCPU (sig)
+ int sig;
+{
+}
+
+void
+handle_XFSZ (sig)
+ int sig;
+{
+}
+
+void
+handle_VTALRM (sig)
+ int sig;
+{
+}
+
+void
+handle_PROF (sig)
+ int sig;
+{
+}
+
+void
+handle_WINCH (sig)
+ int sig;
+{
+}
+
+void
+handle_LOST (sig)
+ int sig;
+{
+}
+
+void
+handle_USR1 (sig)
+ int sig;
+{
+}
+
+void
+handle_USR2 (sig)
+ int sig;
+{
+}
+
+void
+handle_PWR (sig)
+ int sig;
+{
+}
+
+void
+handle_POLL (sig)
+ int sig;
+{
+}
+
+void
+handle_WIND (sig)
+ int sig;
+{
+}
+
+void
+handle_PHONE (sig)
+ int sig;
+{
+}
+
+void
+handle_WAITING (sig)
+ int sig;
+{
+}
+
+void
+handle_LWP (sig)
+ int sig;
+{
+}
+
+void
+handle_DANGER (sig)
+ int sig;
+{
+}
+
+void
+handle_GRANT (sig)
+ int sig;
+{
+}
+
+void
+handle_RETRACT (sig)
+ int sig;
+{
+}
+
+void
+handle_MSG (sig)
+ int sig;
+{
+}
+
+void
+handle_SOUND (sig)
+ int sig;
+{
+}
+
+void
+handle_SAK (sig)
+ int sig;
+{
+}
+
+void
+handle_PRIO (sig)
+ int sig;
+{
+}
+
+void
+handle_33 (sig)
+ int sig;
+{
+}
+
+void
+handle_34 (sig)
+ int sig;
+{
+}
+
+void
+handle_35 (sig)
+ int sig;
+{
+}
+
+void
+handle_36 (sig)
+ int sig;
+{
+}
+
+void
+handle_37 (sig)
+ int sig;
+{
+}
+
+void
+handle_38 (sig)
+ int sig;
+{
+}
+
+void
+handle_39 (sig)
+ int sig;
+{
+}
+
+void
+handle_40 (sig)
+ int sig;
+{
+}
+
+void
+handle_41 (sig)
+ int sig;
+{
+}
+
+void
+handle_42 (sig)
+ int sig;
+{
+}
+
+void
+handle_43 (sig)
+ int sig;
+{
+}
+
+void
+handle_44 (sig)
+ int sig;
+{
+}
+
+void
+handle_45 (sig)
+ int sig;
+{
+}
+
+void
+handle_46 (sig)
+ int sig;
+{
+}
+
+void
+handle_47 (sig)
+ int sig;
+{
+}
+
+void
+handle_48 (sig)
+ int sig;
+{
+}
+
+void
+handle_49 (sig)
+ int sig;
+{
+}
+
+void
+handle_50 (sig)
+ int sig;
+{
+}
+
+void
+handle_51 (sig)
+ int sig;
+{
+}
+
+void
+handle_52 (sig)
+ int sig;
+{
+}
+
+void
+handle_53 (sig)
+ int sig;
+{
+}
+
+void
+handle_54 (sig)
+ int sig;
+{
+}
+
+void
+handle_55 (sig)
+ int sig;
+{
+}
+
+void
+handle_56 (sig)
+ int sig;
+{
+}
+
+void
+handle_57 (sig)
+ int sig;
+{
+}
+
+void
+handle_58 (sig)
+ int sig;
+{
+}
+
+void
+handle_59 (sig)
+ int sig;
+{
+}
+
+void
+handle_60 (sig)
+ int sig;
+{
+}
+
+void
+handle_61 (sig)
+ int sig;
+{
+}
+
+void
+handle_62 (sig)
+ int sig;
+{
+}
+
+void
+handle_63 (sig)
+ int sig;
+{
+}
+
+void
+handle_TERM (sig)
+ int sig;
+{
+}
+
+/* Functions to send signals. These also serve as markers. */
+int
+gen_ABRT ()
+{
+ kill (getpid (), SIGABRT);
+}
+
+int
+gen_HUP ()
+{
+#ifdef SIGHUP
+ kill (getpid (), SIGHUP);
+#else
+ handle_HUP (0);
+#endif
+}
+
+int
+gen_QUIT ()
+{
+#ifdef SIGQUIT
+ kill (getpid (), SIGQUIT);
+#else
+ handle_QUIT (0);
+#endif
+}
+
+int
+gen_ILL ()
+{
+#ifdef SIGILL
+ kill (getpid (), SIGILL);
+#else
+ handle_ILL (0);
+#endif
+}
+
+int
+gen_EMT ()
+{
+#ifdef SIGEMT
+ kill (getpid (), SIGEMT);
+#else
+ handle_EMT (0);
+#endif
+}
+
+int x;
+
+int
+gen_FPE ()
+{
+ /* The intent behind generating SIGFPE this way is to check the mapping
+ from the CPU exception itself to the signals. It would be nice to
+ do the same for SIGBUS, SIGSEGV, etc., but I suspect that even this
+ test might turn out to be insufficiently portable. */
+
+#if 0
+ /* Loses on the PA because after the signal handler executes we try to
+ re-execute the failing instruction again. Perhaps we could siglongjmp
+ out of the signal handler? */
+ /* The expect script looks for the word "kill"; don't delete it. */
+ return 5 / x; /* and we both started jumping up and down yelling kill */
+#else
+ kill (getpid (), SIGFPE);
+#endif
+}
+
+int
+gen_BUS ()
+{
+#ifdef SIGBUS
+ kill (getpid (), SIGBUS);
+#else
+ handle_BUS (0);
+#endif
+}
+
+int
+gen_SEGV ()
+{
+#ifdef SIGSEGV
+ kill (getpid (), SIGSEGV);
+#else
+ handle_SEGV (0);
+#endif
+}
+
+int
+gen_SYS ()
+{
+#ifdef SIGSYS
+ kill (getpid (), SIGSYS);
+#else
+ handle_SYS (0);
+#endif
+}
+
+int
+gen_PIPE ()
+{
+#ifdef SIGPIPE
+ kill (getpid (), SIGPIPE);
+#else
+ handle_PIPE (0);
+#endif
+}
+
+int
+gen_ALRM ()
+{
+#ifdef SIGALRM
+ kill (getpid (), SIGALRM);
+#else
+ handle_ALRM (0);
+#endif
+}
+
+int
+gen_URG ()
+{
+#ifdef SIGURG
+ kill (getpid (), SIGURG);
+#else
+ handle_URG (0);
+#endif
+}
+
+int
+gen_TSTP ()
+{
+#ifdef SIGTSTP
+ kill (getpid (), SIGTSTP);
+#else
+ handle_TSTP (0);
+#endif
+}
+
+int
+gen_CONT ()
+{
+#ifdef SIGCONT
+ kill (getpid (), SIGCONT);
+#else
+ handle_CONT (0);
+#endif
+}
+
+int
+gen_CHLD ()
+{
+#ifdef SIGCHLD
+ kill (getpid (), SIGCHLD);
+#else
+ handle_CHLD (0);
+#endif
+}
+
+int
+gen_TTIN ()
+{
+#ifdef SIGTTIN
+ kill (getpid (), SIGTTIN);
+#else
+ handle_TTIN (0);
+#endif
+}
+
+int
+gen_TTOU ()
+{
+#ifdef SIGTTOU
+ kill (getpid (), SIGTTOU);
+#else
+ handle_TTOU (0);
+#endif
+}
+
+int
+gen_IO ()
+{
+#ifdef SIGIO
+ kill (getpid (), SIGIO);
+#else
+ handle_IO (0);
+#endif
+}
+
+int
+gen_XCPU ()
+{
+#ifdef SIGXCPU
+ kill (getpid (), SIGXCPU);
+#else
+ handle_XCPU (0);
+#endif
+}
+
+int
+gen_XFSZ ()
+{
+#ifdef SIGXFSZ
+ kill (getpid (), SIGXFSZ);
+#else
+ handle_XFSZ (0);
+#endif
+}
+
+int
+gen_VTALRM ()
+{
+#ifdef SIGVTALRM
+ kill (getpid (), SIGVTALRM);
+#else
+ handle_VTALRM (0);
+#endif
+}
+
+int
+gen_PROF ()
+{
+#ifdef SIGPROF
+ kill (getpid (), SIGPROF);
+#else
+ handle_PROF (0);
+#endif
+}
+
+int
+gen_WINCH ()
+{
+#ifdef SIGWINCH
+ kill (getpid (), SIGWINCH);
+#else
+ handle_WINCH (0);
+#endif
+}
+
+int
+gen_LOST ()
+{
+#if defined(SIGLOST) && (!defined(SIGABRT) || SIGLOST != SIGABRT)
+ kill (getpid (), SIGLOST);
+#else
+ handle_LOST (0);
+#endif
+}
+
+int
+gen_USR1 ()
+{
+#ifdef SIGUSR1
+ kill (getpid (), SIGUSR1);
+#else
+ handle_USR1 (0);
+#endif
+}
+
+int
+gen_USR2 ()
+{
+#ifdef SIGUSR2
+ kill (getpid (), SIGUSR2);
+#else
+ handle_USR2 (0);
+#endif
+}
+
+int
+gen_PWR ()
+{
+#ifdef SIGPWR
+ kill (getpid (), SIGPWR);
+#else
+ handle_PWR (0);
+#endif
+}
+
+int
+gen_POLL ()
+{
+#if defined (SIGPOLL) && (!defined (SIGIO) || SIGPOLL != SIGIO)
+ kill (getpid (), SIGPOLL);
+#else
+ handle_POLL (0);
+#endif
+}
+
+int
+gen_WIND ()
+{
+#ifdef SIGWIND
+ kill (getpid (), SIGWIND);
+#else
+ handle_WIND (0);
+#endif
+}
+
+int
+gen_PHONE ()
+{
+#ifdef SIGPHONE
+ kill (getpid (), SIGPHONE);
+#else
+ handle_PHONE (0);
+#endif
+}
+
+int
+gen_WAITING ()
+{
+#ifdef SIGWAITING
+ kill (getpid (), SIGWAITING);
+#else
+ handle_WAITING (0);
+#endif
+}
+
+int
+gen_LWP ()
+{
+#ifdef SIGLWP
+ kill (getpid (), SIGLWP);
+#else
+ handle_LWP (0);
+#endif
+}
+
+int
+gen_DANGER ()
+{
+#ifdef SIGDANGER
+ kill (getpid (), SIGDANGER);
+#else
+ handle_DANGER (0);
+#endif
+}
+
+int
+gen_GRANT ()
+{
+#ifdef SIGGRANT
+ kill (getpid (), SIGGRANT);
+#else
+ handle_GRANT (0);
+#endif
+}
+
+int
+gen_RETRACT ()
+{
+#ifdef SIGRETRACT
+ kill (getpid (), SIGRETRACT);
+#else
+ handle_RETRACT (0);
+#endif
+}
+
+int
+gen_MSG ()
+{
+#ifdef SIGMSG
+ kill (getpid (), SIGMSG);
+#else
+ handle_MSG (0);
+#endif
+}
+
+int
+gen_SOUND ()
+{
+#ifdef SIGSOUND
+ kill (getpid (), SIGSOUND);
+#else
+ handle_SOUND (0);
+#endif
+}
+
+int
+gen_SAK ()
+{
+#ifdef SIGSAK
+ kill (getpid (), SIGSAK);
+#else
+ handle_SAK (0);
+#endif
+}
+
+int
+gen_PRIO ()
+{
+#ifdef SIGPRIO
+ kill (getpid (), SIGPRIO);
+#else
+ handle_PRIO (0);
+#endif
+}
+
+int
+gen_33 ()
+{
+#ifdef SIG33
+ kill (getpid (), 33);
+#else
+ handle_33 (0);
+#endif
+}
+
+int
+gen_34 ()
+{
+#ifdef SIG34
+ kill (getpid (), 34);
+#else
+ handle_34 (0);
+#endif
+}
+
+int
+gen_35 ()
+{
+#ifdef SIG35
+ kill (getpid (), 35);
+#else
+ handle_35 (0);
+#endif
+}
+
+int
+gen_36 ()
+{
+#ifdef SIG36
+ kill (getpid (), 36);
+#else
+ handle_36 (0);
+#endif
+}
+
+int
+gen_37 ()
+{
+#ifdef SIG37
+ kill (getpid (), 37);
+#else
+ handle_37 (0);
+#endif
+}
+
+int
+gen_38 ()
+{
+#ifdef SIG38
+ kill (getpid (), 38);
+#else
+ handle_38 (0);
+#endif
+}
+
+int
+gen_39 ()
+{
+#ifdef SIG39
+ kill (getpid (), 39);
+#else
+ handle_39 (0);
+#endif
+}
+
+int
+gen_40 ()
+{
+#ifdef SIG40
+ kill (getpid (), 40);
+#else
+ handle_40 (0);
+#endif
+}
+
+int
+gen_41 ()
+{
+#ifdef SIG41
+ kill (getpid (), 41);
+#else
+ handle_41 (0);
+#endif
+}
+
+int
+gen_42 ()
+{
+#ifdef SIG42
+ kill (getpid (), 42);
+#else
+ handle_42 (0);
+#endif
+}
+
+int
+gen_43 ()
+{
+#ifdef SIG43
+ kill (getpid (), 43);
+#else
+ handle_43 (0);
+#endif
+}
+
+int
+gen_44 ()
+{
+#ifdef SIG44
+ kill (getpid (), 44);
+#else
+ handle_44 (0);
+#endif
+}
+
+int
+gen_45 ()
+{
+#ifdef SIG45
+ kill (getpid (), 45);
+#else
+ handle_45 (0);
+#endif
+}
+
+int
+gen_46 ()
+{
+#ifdef SIG46
+ kill (getpid (), 46);
+#else
+ handle_46 (0);
+#endif
+}
+
+int
+gen_47 ()
+{
+#ifdef SIG47
+ kill (getpid (), 47);
+#else
+ handle_47 (0);
+#endif
+}
+
+int
+gen_48 ()
+{
+#ifdef SIG48
+ kill (getpid (), 48);
+#else
+ handle_48 (0);
+#endif
+}
+
+int
+gen_49 ()
+{
+#ifdef SIG49
+ kill (getpid (), 49);
+#else
+ handle_49 (0);
+#endif
+}
+
+int
+gen_50 ()
+{
+#ifdef SIG50
+ kill (getpid (), 50);
+#else
+ handle_50 (0);
+#endif
+}
+
+int
+gen_51 ()
+{
+#ifdef SIG51
+ kill (getpid (), 51);
+#else
+ handle_51 (0);
+#endif
+}
+
+int
+gen_52 ()
+{
+#ifdef SIG52
+ kill (getpid (), 52);
+#else
+ handle_52 (0);
+#endif
+}
+
+int
+gen_53 ()
+{
+#ifdef SIG53
+ kill (getpid (), 53);
+#else
+ handle_53 (0);
+#endif
+}
+
+int
+gen_54 ()
+{
+#ifdef SIG54
+ kill (getpid (), 54);
+#else
+ handle_54 (0);
+#endif
+}
+
+int
+gen_55 ()
+{
+#ifdef SIG55
+ kill (getpid (), 55);
+#else
+ handle_55 (0);
+#endif
+}
+
+int
+gen_56 ()
+{
+#ifdef SIG56
+ kill (getpid (), 56);
+#else
+ handle_56 (0);
+#endif
+}
+
+int
+gen_57 ()
+{
+#ifdef SIG57
+ kill (getpid (), 57);
+#else
+ handle_57 (0);
+#endif
+}
+
+int
+gen_58 ()
+{
+#ifdef SIG58
+ kill (getpid (), 58);
+#else
+ handle_58 (0);
+#endif
+}
+
+int
+gen_59 ()
+{
+#ifdef SIG59
+ kill (getpid (), 59);
+#else
+ handle_59 (0);
+#endif
+}
+
+int
+gen_60 ()
+{
+#ifdef SIG60
+ kill (getpid (), 60);
+#else
+ handle_60 (0);
+#endif
+}
+
+int
+gen_61 ()
+{
+#ifdef SIG61
+ kill (getpid (), 61);
+#else
+ handle_61 (0);
+#endif
+}
+
+int
+gen_62 ()
+{
+#ifdef SIG62
+ kill (getpid (), 62);
+#else
+ handle_62 (0);
+#endif
+}
+
+int
+gen_63 ()
+{
+#ifdef SIG63
+ kill (getpid (), 63);
+#else
+ handle_63 (0);
+#endif
+}
+
+int
+gen_TERM ()
+{
+ kill (getpid (), SIGTERM);
+}
+
+int
+main ()
+{
+#ifdef usestubs
+ set_debug_traps ();
+ breakpoint ();
+#endif
+ signal (SIGABRT, handle_ABRT);
+#ifdef SIGHUP
+ signal (SIGHUP, handle_HUP);
+#endif
+#ifdef SIGQUIT
+ signal (SIGQUIT, handle_QUIT);
+#endif
+#ifdef SIGILL
+ signal (SIGILL, handle_ILL);
+#endif
+#ifdef SIGEMT
+ signal (SIGEMT, handle_EMT);
+#endif
+#ifdef SIGFPE
+ signal (SIGFPE, handle_FPE);
+#endif
+#ifdef SIGBUS
+ signal (SIGBUS, handle_BUS);
+#endif
+#ifdef SIGSEGV
+ signal (SIGSEGV, handle_SEGV);
+#endif
+#ifdef SIGSYS
+ signal (SIGSYS, handle_SYS);
+#endif
+#ifdef SIGPIPE
+ signal (SIGPIPE, handle_PIPE);
+#endif
+#ifdef SIGALRM
+ signal (SIGALRM, handle_ALRM);
+#endif
+#ifdef SIGURG
+ signal (SIGURG, handle_URG);
+#endif
+#ifdef SIGTSTP
+ signal (SIGTSTP, handle_TSTP);
+#endif
+#ifdef SIGCONT
+ signal (SIGCONT, handle_CONT);
+#endif
+#ifdef SIGCHLD
+ signal (SIGCHLD, handle_CHLD);
+#endif
+#ifdef SIGTTIN
+ signal (SIGTTIN, handle_TTIN);
+#endif
+#ifdef SIGTTOU
+ signal (SIGTTOU, handle_TTOU);
+#endif
+#ifdef SIGIO
+ signal (SIGIO, handle_IO);
+#endif
+#ifdef SIGXCPU
+ signal (SIGXCPU, handle_XCPU);
+#endif
+#ifdef SIGXFSZ
+ signal (SIGXFSZ, handle_XFSZ);
+#endif
+#ifdef SIGVTALRM
+ signal (SIGVTALRM, handle_VTALRM);
+#endif
+#ifdef SIGPROF
+ signal (SIGPROF, handle_PROF);
+#endif
+#ifdef SIGWINCH
+ signal (SIGWINCH, handle_WINCH);
+#endif
+#if defined(SIGLOST) && (!defined(SIGABRT) || SIGLOST != SIGABRT)
+ signal (SIGLOST, handle_LOST);
+#endif
+#ifdef SIGUSR1
+ signal (SIGUSR1, handle_USR1);
+#endif
+#ifdef SIGUSR2
+ signal (SIGUSR2, handle_USR2);
+#endif
+#ifdef SIGPWR
+ signal (SIGPWR, handle_PWR);
+#endif
+#if defined (SIGPOLL) && (!defined (SIGIO) || SIGPOLL != SIGIO)
+ signal (SIGPOLL, handle_POLL);
+#endif
+#ifdef SIGWIND
+ signal (SIGWIND, handle_WIND);
+#endif
+#ifdef SIGPHONE
+ signal (SIGPHONE, handle_PHONE);
+#endif
+#ifdef SIGWAITING
+ signal (SIGWAITING, handle_WAITING);
+#endif
+#ifdef SIGLWP
+ signal (SIGLWP, handle_LWP);
+#endif
+#ifdef SIGDANGER
+ signal (SIGDANGER, handle_DANGER);
+#endif
+#ifdef SIGGRANT
+ signal (SIGGRANT, handle_GRANT);
+#endif
+#ifdef SIGRETRACT
+ signal (SIGRETRACT, handle_RETRACT);
+#endif
+#ifdef SIGMSG
+ signal (SIGMSG, handle_MSG);
+#endif
+#ifdef SIGSOUND
+ signal (SIGSOUND, handle_SOUND);
+#endif
+#ifdef SIGSAK
+ signal (SIGSAK, handle_SAK);
+#endif
+#ifdef SIGPRIO
+ signal (SIGPRIO, handle_PRIO);
+#endif
+#ifdef __Lynx__
+ /* Lynx doesn't seem to have anything in signal.h for this. */
+ signal (33, handle_33);
+ signal (34, handle_34);
+ signal (35, handle_35);
+ signal (36, handle_36);
+ signal (37, handle_37);
+ signal (38, handle_38);
+ signal (39, handle_39);
+ signal (40, handle_40);
+ signal (41, handle_41);
+ signal (42, handle_42);
+ signal (43, handle_43);
+ signal (44, handle_44);
+ signal (45, handle_45);
+ signal (46, handle_46);
+ signal (47, handle_47);
+ signal (48, handle_48);
+ signal (49, handle_49);
+ signal (50, handle_50);
+ signal (51, handle_51);
+ signal (52, handle_52);
+ signal (53, handle_53);
+ signal (54, handle_54);
+ signal (55, handle_55);
+ signal (56, handle_56);
+ signal (57, handle_57);
+ signal (58, handle_58);
+ signal (59, handle_59);
+ signal (60, handle_60);
+ signal (61, handle_61);
+ signal (62, handle_62);
+ signal (63, handle_63);
+#endif /* lynx */
+ signal (SIGTERM, handle_TERM);
+
+ x = 0;
+
+ gen_ABRT ();
+ gen_HUP ();
+ gen_QUIT ();
+ gen_ILL ();
+ gen_EMT ();
+ gen_FPE ();
+ gen_BUS ();
+ gen_SEGV ();
+ gen_SYS ();
+ gen_PIPE ();
+ gen_ALRM ();
+ gen_URG ();
+ gen_TSTP ();
+ gen_CONT ();
+ gen_CHLD ();
+ gen_TTIN ();
+ gen_TTOU ();
+ gen_IO ();
+ gen_XCPU ();
+ gen_XFSZ ();
+ gen_VTALRM ();
+ gen_PROF ();
+ gen_WINCH ();
+ gen_LOST ();
+ gen_USR1 ();
+ gen_USR2 ();
+ gen_PWR ();
+ gen_POLL ();
+ gen_WIND ();
+ gen_PHONE ();
+ gen_WAITING ();
+ gen_LWP ();
+ gen_DANGER ();
+ gen_GRANT ();
+ gen_RETRACT ();
+ gen_MSG ();
+ gen_SOUND ();
+ gen_SAK ();
+ gen_PRIO ();
+ gen_33 ();
+ gen_34 ();
+ gen_35 ();
+ gen_36 ();
+ gen_37 ();
+ gen_38 ();
+ gen_39 ();
+ gen_40 ();
+ gen_41 ();
+ gen_42 ();
+ gen_43 ();
+ gen_44 ();
+ gen_45 ();
+ gen_46 ();
+ gen_47 ();
+ gen_48 ();
+ gen_49 ();
+ gen_50 ();
+ gen_51 ();
+ gen_52 ();
+ gen_53 ();
+ gen_54 ();
+ gen_55 ();
+ gen_56 ();
+ gen_57 ();
+ gen_58 ();
+ gen_59 ();
+ gen_60 ();
+ gen_61 ();
+ gen_62 ();
+ gen_63 ();
+ gen_TERM ();
+
+ return 0;
+}
diff --git a/gdb/testsuite/gdb.base/sigall.exp b/gdb/testsuite/gdb.base/sigall.exp
new file mode 100644
index 00000000000..765e0ee5df9
--- /dev/null
+++ b/gdb/testsuite/gdb.base/sigall.exp
@@ -0,0 +1,210 @@
+# Copyright (C) 1995, 1997 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+if [target_info exists gdb,nosignals] {
+ verbose "Skipping sigall.exp because of nosignals."
+ continue
+}
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+set prms_id 0
+set bug_id 0
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+
+set testfile sigall
+set srcfile ${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+# Make the first signal SIGABRT because it is always supported.
+set sig_supported 1
+set thissig "ABRT"
+
+proc test_one_sig {nextsig} {
+ global sig_supported
+ global gdb_prompt
+ global thissig
+
+ set this_sig_supported $sig_supported
+ gdb_test "handle SIG$thissig stop print" \
+ "SIG$thissig\[ \t\]*Yes\[ \t\]*Yes\[ \t\]*Yes.*"
+ gdb_test "b handle_$thissig" "Breakpoint \[0-9\]+ .*"
+ gdb_test "b gen_$nextsig" "Breakpoint \[0-9\]+ .*"
+
+ set need_another_continue 1
+ set missed_handler 0
+ if $this_sig_supported then {
+ send_gdb "continue\n"
+ if { $thissig == "IO" } {
+ setup_xfail "i*86-pc-linuxoldld-gnu" "i*86-pc-linuxaout-gnu"
+ }
+ gdb_expect {
+ -re "Continuing.*Program received signal SIG$thissig.*$gdb_prompt $" {
+ pass "get signal $thissig"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "get signal $thissig"
+ set need_another_continue 0
+ }
+ default {
+ fail "get signal $thissig (eof or timeout)"
+ }
+ }
+ }
+ if [ istarget "alpha-dec-osf3*" ] then {
+ # OSF/1-3.x is unable to continue with a job control stop signal.
+ # The inferior remains stopped without an event of interest
+ # and GDB waits forever for the inferior to stop on an event
+ # of interest. Work around the kernel bug.
+ if { $thissig == "TSTP" || $thissig == "TTIN" || $thissig == "TTOU" } {
+ setup_xfail "alpha-dec-osf3*"
+ fail "cannot continue from signal $thissig"
+ set need_another_continue 0
+ }
+ }
+
+ if $need_another_continue then {
+ send_gdb "continue\n"
+ if { $thissig == "URG" } {
+ setup_xfail "i*86-pc-linuxoldld-gnu" "i*86-pc-linuxaout-gnu"
+ }
+ # Either Lynx or GDB screws up on SIGPRIO
+ if { $thissig == "PRIO" } {
+ setup_xfail "*-*-*lynx*"
+ }
+ gdb_expect {
+ -re "Breakpoint.*handle_$thissig.*$gdb_prompt $" {
+ pass "send signal $thissig"
+ }
+ -re "Breakpoint.*gen_$nextsig.*kill.*$gdb_prompt $" {
+ fail "missed breakpoint at handle_$thissig"
+ set missed_handler 1
+ }
+ }
+ }
+
+ if { $missed_handler == "0" } then {
+ send_gdb "signal 0\n"
+ gdb_expect {
+ -re "Breakpoint.*gen_$nextsig.*kill.*$gdb_prompt $" {
+ pass "advance to $nextsig"
+ set sig_supported 1
+ }
+ -re "Breakpoint.*gen_$nextsig.*handle.*$gdb_prompt $" {
+ pass "advance to $nextsig"
+ set sig_supported 0
+ }
+ -re ".*$gdb_prompt $" { fail "advance to $nextsig" }
+ default { fail "advance to $nextsig (eof or timeout)" }
+ }
+ }
+ set thissig $nextsig
+}
+
+gdb_load $binfile
+
+runto gen_ABRT
+test_one_sig HUP
+test_one_sig QUIT
+test_one_sig ILL
+test_one_sig EMT
+test_one_sig FPE
+test_one_sig BUS
+test_one_sig SEGV
+test_one_sig SYS
+test_one_sig PIPE
+test_one_sig ALRM
+test_one_sig URG
+test_one_sig TSTP
+test_one_sig CONT
+test_one_sig CHLD
+test_one_sig TTIN
+test_one_sig TTOU
+test_one_sig IO
+test_one_sig XCPU
+test_one_sig XFSZ
+test_one_sig VTALRM
+test_one_sig PROF
+test_one_sig WINCH
+test_one_sig LOST
+test_one_sig USR1
+test_one_sig USR2
+test_one_sig PWR
+test_one_sig POLL
+test_one_sig WIND
+test_one_sig PHONE
+test_one_sig WAITING
+test_one_sig LWP
+test_one_sig DANGER
+test_one_sig GRANT
+test_one_sig RETRACT
+test_one_sig MSG
+test_one_sig SOUND
+test_one_sig SAK
+test_one_sig PRIO
+test_one_sig 33
+test_one_sig 34
+test_one_sig 35
+test_one_sig 36
+test_one_sig 37
+test_one_sig 38
+test_one_sig 39
+test_one_sig 40
+test_one_sig 41
+test_one_sig 42
+test_one_sig 43
+test_one_sig 44
+test_one_sig 45
+test_one_sig 46
+test_one_sig 47
+test_one_sig 48
+test_one_sig 49
+test_one_sig 50
+test_one_sig 51
+test_one_sig 52
+test_one_sig 53
+test_one_sig 54
+test_one_sig 55
+test_one_sig 56
+test_one_sig 57
+test_one_sig 58
+test_one_sig 59
+test_one_sig 60
+test_one_sig 61
+test_one_sig 62
+test_one_sig 63
+test_one_sig TERM
+
+# The last signal (SIGTERM) gets handled slightly differently because
+# we are not setting up for another test.
+gdb_test "handle SIGTERM stop print" \
+ "SIGTERM\[ \t\]*Yes\[ \t\]*Yes\[ \t\]*Yes.*"
+gdb_test "b handle_TERM" "Breakpoint \[0-9\]+ .*"
+gdb_test "continue" \
+ "Continuing.*Program received signal SIGTERM.*" \
+ "get signal TERM"
+gdb_test "continue" "Breakpoint.*handle_TERM.*" "send signal TERM"
+gdb_test "continue" "Program exited normally\\." "continue to sigall exit"
+
+return 0
diff --git a/gdb/testsuite/gdb.base/signals.c b/gdb/testsuite/gdb.base/signals.c
new file mode 100644
index 00000000000..280e6e7c5d8
--- /dev/null
+++ b/gdb/testsuite/gdb.base/signals.c
@@ -0,0 +1,53 @@
+/* Test GDB dealing with stuff like stepping into sigtramp. */
+
+#include <signal.h>
+
+#ifdef __sh__
+#define signal(a,b) /* Signals not supported on this target - make them go away */
+#define alarm(a) /* Ditto for alarm() */
+#endif
+
+static int count = 0;
+
+static void
+handler (sig)
+ int sig;
+{
+ signal (sig, handler);
+ ++count;
+}
+
+static void
+func1 ()
+{
+ ++count;
+}
+
+static void
+func2 ()
+{
+ ++count;
+}
+
+int
+main ()
+{
+#ifdef usestubs
+ set_debug_traps();
+ breakpoint();
+#endif
+#ifdef SIGALRM
+ signal (SIGALRM, handler);
+#endif
+#ifdef SIGUSR1
+ signal (SIGUSR1, handler);
+#endif
+ alarm (1);
+ ++count; /* first */
+ alarm (1);
+ ++count; /* second */
+ func1 ();
+ alarm (1);
+ func2 ();
+ return count;
+}
diff --git a/gdb/testsuite/gdb.base/signals.exp b/gdb/testsuite/gdb.base/signals.exp
new file mode 100644
index 00000000000..49bf49081b0
--- /dev/null
+++ b/gdb/testsuite/gdb.base/signals.exp
@@ -0,0 +1,628 @@
+# Copyright (C) 1997, 1998 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+if [target_info exists gdb,nosignals] {
+ verbose "Skipping signals.exp because of nosignals."
+ continue
+}
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+set prms_id 0
+set bug_id 0
+
+set testfile signals
+set srcfile ${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+# Create and source the file that provides information about the compiler
+# used to compile the test case.
+if [get_compiler_info ${binfile}] {
+ return -1;
+}
+
+proc signal_tests_1 {} {
+ global gdb_prompt
+ if [runto_main] then {
+ gdb_test "next" "signal \\(SIGUSR1.*" \
+ "next over signal (SIGALRM, handler)"
+ gdb_test "next" "alarm \\(.*" \
+ "next over signal (SIGUSR1, handler)"
+ gdb_test "next" "\\+\\+count; /\\* first \\*/" \
+ "next over alarm (1)"
+ # An alarm has been signaled, give the signal time to get delivered.
+ sleep 2
+
+ # i386 BSD currently fails the next test with a SIGTRAP.
+ setup_xfail "i*86-*-bsd*"
+ # But Dynix has a DECR_PC_AFTER_BREAK of zero, so the failure
+ # is shadowed by hitting the through_sigtramp_breakpoint.
+ clear_xfail "i*86-sequent-bsd*"
+ # Univel SVR4 i386 continues instead of stepping.
+ setup_xfail "i*86-univel-sysv4*"
+ # lynx fails with "next" acting like "continue"
+ setup_xfail "*-*-*lynx*"
+ # linux (aout versions) also fails with "next" acting like "continue"
+ # this is probably more dependant on the kernel version than on the
+ # object file format or utils. (sigh)
+ setup_xfail "i*86-pc-linuxaout-gnu" "i*86-pc-linuxoldld-gnu"
+ send_gdb "next\n"
+ gdb_expect {
+ -re "alarm .*$gdb_prompt $" { pass "next to 2nd alarm (1)" }
+ -re "Program received signal SIGTRAP.*first.*$gdb_prompt $" {
+
+ # This can happen on machines that have a trace flag
+ # in their PS register.
+ # The trace flag in the PS register will be set due to
+ # the `next' command.
+ # Before calling the signal handler, the PS register
+ # is pushed along with the context on the user stack.
+ # When the signal handler has finished, it reenters the
+ # the kernel via a sigreturn syscall, which restores the
+ # PS register along with the context.
+ # If the kernel erroneously does not clear the trace flag
+ # in the pushed context, gdb will receive a SIGTRAP from
+ # the set trace flag in the restored context after the
+ # signal handler has finished.
+
+ # I do not yet understand why the SIGTRAP does not occur
+ # after stepping the instruction at the restored PC on
+ # i386 BSDI 1.0 systems.
+
+ # Note that the vax under Ultrix also exhibits
+ # this behaviour (it is uncovered by the `continue from
+ # a break in a signal handler' test below).
+ # With this test the failure is shadowed by hitting the
+ # through_sigtramp_breakpoint upon return from the signal
+ # handler.
+
+ # SVR4 and Linux based i*86 systems exhibit this behaviour
+ # as well (it is uncovered by the `continue from a break
+ # in a signal handler' test below).
+ # As these systems use procfs, where we tell the kernel not
+ # to tell gdb about `pass' signals, and the trace flag is
+ # cleared by the kernel before entering the sigtramp
+ # routine, GDB will not notice the execution of the signal
+ # handler.
+ # Upon return from the signal handler, GDB will receive
+ # a SIGTRAP from the set trace flag in the restored context.
+ # The SIGTRAP marks the end of a (albeit long winded)
+ # single step for GDB, causing this test to pass.
+
+ fail "next to 2nd alarm (1) (probably kernel bug)"
+ gdb_test "next" "alarm.*" "next to 2nd alarm (1)"
+ }
+ -re "Program exited with code.*$gdb_prompt $" {
+
+ # This is apparently a bug in the UnixWare kernel (but
+ # has not been investigated beyond the
+ # resume/target_wait level, and has not been reported
+ # to Univel). If it steps when a signal is pending,
+ # it does a continue instead. I don't know whether
+ # there is a workaround.
+
+ # Perhaps this problem exists on other SVR4 systems;
+ # but (a) we have no reason to think so, and (b) if we
+ # put a wrong xfail here, we never get an XPASS to let
+ # us know that it was incorrect (and then if such a
+ # configuration regresses we have no way of knowing).
+ # Solaris is not a relevant data point either way
+ # because it lacks single stepping.
+
+ # fnf: I don't agree with the above philosophy. We
+ # can never be sure that any particular XFAIL is
+ # specified 100% correctly in that no systems with
+ # the bug are missed and all systems without the bug
+ # are excluded. If we include an XFAIL that isn't
+ # appropriate for a particular system, then when that
+ # system gets tested it will XPASS, and someone should
+ # investigate and fix the setup_xfail as appropriate,
+ # or more preferably, the actual bug. Each such case
+ # adds more data to narrowing down the scope of the
+ # problem and ultimately fixing it.
+
+ setup_xfail "i*86-*-sysv4*"
+ fail "'next' behaved as 'continue (known SVR4 bug)'"
+ return 0
+ }
+ -re ".*$gdb_prompt $" { fail "next to 2nd alarm (1)" }
+ timeout { fail "next to 2nd alarm (1); (timeout)" }
+ eof { fail "next to 2nd alarm (1); (eof)" }
+ }
+
+ gdb_test "break handler" "Breakpoint \[0-9\]+ .*"
+ gdb_test "next" "\\+\\+count; /\\* second \\*/" \
+ "next to 2nd ++count in signals_tests_1"
+ # An alarm has been signaled, give the signal time to get delivered.
+ sleep 2
+
+ set bash_bug 0
+ send_gdb "next\n"
+ gdb_expect {
+ -re "Breakpoint.*handler.*$gdb_prompt $" {
+ pass "next to handler in signals_tests_1"
+ }
+ -re "Program received signal SIGEMT.*$gdb_prompt $" {
+ # Bash versions before 1.13.5 cause this behaviour
+ # by blocking SIGTRAP.
+ fail "next to handler in signals_tests_1 (known problem with bash versions before 1.13.5)"
+ set bash_bug 1
+ gdb_test "signal 0" "Breakpoint.*handler.*"
+ }
+ -re ".*$gdb_prompt $" { fail "next to handler in signals_tests_1" }
+ timeout { fail "next to handler in signals_tests_1 (timeout)" }
+ eof { fail "next to handler in signals_tests_1 (eof)" }
+ }
+
+ # This doesn't test that main is frame #2, just that main is frame
+ # #2, #3, or higher. At some point this should be fixed (but
+ # it quite possibly would introduce new FAILs on some systems).
+ setup_xfail "i*86-pc-linux-gnu*" "i*86-*-bsdi2.0"
+ gdb_test "backtrace 10" "#0.*handler.*#1.*#2.*main.*" \
+ "backtrace in signals_tests_1"
+
+ gdb_test "break func1" "Breakpoint \[0-9\]+ .*"
+ gdb_test "break func2" "Breakpoint \[0-9\]+ .*"
+
+ # Vax Ultrix and i386 BSD currently fail the next test with
+ # a SIGTRAP, but with different symptoms.
+ setup_xfail "vax-*-ultrix*"
+ setup_xfail "i*86-*-bsd*"
+ setup_xfail "i*86-pc-linux-gnu*"
+ setup_xfail "i*86-*-solaris2*"
+ send_gdb "continue\n"
+ gdb_expect {
+ -re "Breakpoint.*func1.*$gdb_prompt $" { pass "continue to func1" }
+ -re "Program received signal SIGTRAP.*second.*$gdb_prompt $" {
+
+ # See explanation for `next to 2nd alarm (1)' fail above.
+ # We did step into the signal handler, hit a breakpoint
+ # in the handler and continued from the breakpoint.
+ # The set trace flag in the restored context is causing
+ # the SIGTRAP, without stepping an instruction.
+
+ fail "continue to func1 (probably kernel bug)"
+ gdb_test "continue" "Breakpoint.*func1.*" \
+ "extra continue to func1"
+ }
+ -re "Program received signal SIGTRAP.*func1 ..;.*$gdb_prompt $" {
+
+ # On the vax under Ultrix the set trace flag in the restored
+ # context is causing the SIGTRAP, but after stepping one
+ # instruction, as expected.
+
+ fail "continue to func1 (probably kernel bug)"
+ gdb_test "continue" "Breakpoint.*func1.*" \
+ "extra continue to func1"
+ }
+ -re ".*$gdb_prompt $" { fail "continue to func1" }
+ default { fail "continue to func1" }
+ }
+
+ setup_xfail "*-*-irix*"
+ send_gdb "signal SIGUSR1\n"
+ gdb_expect {
+ -re "Breakpoint.*handler.*$gdb_prompt $" { pass "signal SIGUSR1" }
+ -re "Program received signal SIGUSR1.*$gdb_prompt $" {
+ # This is what irix4 and irix5 do.
+ # It would appear to be a kernel bug.
+ fail "signal SIGUSR1"
+ gdb_test "continue" "Breakpoint.*handler.*" "pass it SIGUSR1"
+ }
+ -re ".*$gdb_prompt $" { fail "signal SIGUSR1" }
+ default { fail "signal SIGUSR1" }
+ }
+
+ # Will tend to wrongly require an extra continue.
+
+ # The problem here is that the breakpoint at func1 will be
+ # inserted, and when the system finishes with the signal
+ # handler it will try to execute there. For GDB to try to
+ # remember that it was going to step over a breakpoint when a
+ # signal happened, distinguish this case from the case where
+ # func1 is called from the signal handler, etc., seems
+ # exceedingly difficult. So don't expect this to get fixed
+ # anytime soon.
+
+ setup_xfail "*-*-*"
+ send_gdb "continue\n"
+ gdb_expect {
+ -re "Breakpoint.*func2.*$gdb_prompt $" { pass "continue to func2" }
+ -re "Breakpoint.*func1.*$gdb_prompt $" {
+ fail "continue to func2"
+ gdb_test "continue" "Breakpoint.*func2.*" \
+ "extra continue to func2"
+ }
+ -re ".*$gdb_prompt $" { fail "continue to func2" }
+ default { fail "continue to func2" }
+ }
+
+ sleep 2
+
+ # GDB yanks out the breakpoints to step over the breakpoint it
+ # stopped at, which means the breakpoint at handler is yanked.
+ # But if SOFTWARE_SINGLE_STEP_P, we won't get another chance to
+ # reinsert them (at least not with procfs, where we tell the kernel
+ # not to tell gdb about `pass' signals). So the fix would appear to
+ # be to just yank that one breakpoint when we step over it.
+
+ setup_xfail "sparc*-*-*"
+ setup_xfail "rs6000-*-*"
+ setup_xfail "powerpc-*-*"
+
+ # A faulty bash will not step the inferior into sigtramp on sun3.
+ if {$bash_bug} then {
+ setup_xfail "m68*-*-sunos4*"
+ }
+
+ setup_xfail "i*86-pc-linux-gnu*"
+ setup_xfail "i*86-*-solaris2*"
+ gdb_test "continue" "Breakpoint.*handler.*" "continue to handler"
+
+ # If the SOFTWARE_SINGLE_STEP_P failure happened, we have already
+ # exited.
+ # If we succeeded a continue will return from the handler to func2.
+ # GDB now has `forgotten' that it intended to step over the
+ # breakpoint at func2 and will stop at func2.
+ setup_xfail "*-*-*"
+ # The sun3 with a faulty bash will also be `forgetful' but it
+ # already got the spurious stop at func2 and this continue will work.
+ if {$bash_bug} then {
+ clear_xfail "m68*-*-sunos4*"
+ }
+ gdb_test "continue" "Program exited with code 010\\." \
+ "continue to exit in signals_tests_1 "
+ }
+}
+
+# On a few losing systems, ptrace (PT_CONTINUE) or ptrace (PT_STEP)
+# causes pending signals to be cleared, which causes these tests to
+# get nowhere fast. This is totally losing behavior (perhaps there
+# are cases in which is it useful but the user needs more control,
+# which they mostly have in GDB), but some people apparently think it
+# is a feature. It is documented in the ptrace manpage on Motorola
+# Delta Series sysV68 R3V7.1 and on HPUX 9.0. Even the non-HPUX PA
+# OSes (BSD and OSF/1) seem to have figured they had to copy this
+# braindamage.
+
+if {[ istarget "m68*-motorola-*" ] || [ istarget "hppa*-*-bsd*" ] ||
+ [ istarget "hppa*-*-osf*" ]} then {
+ setup_xfail "*-*-*"
+ fail "ptrace loses on signals on this target"
+ return 0
+}
+
+# lynx2.2.2 doesn't lose signals, instead it screws up the stack pointer
+# in some of these tests leading to massive problems. I've
+# reported this to lynx, hopefully it'll be fixed in lynx2.3.
+# Severe braindamage.
+if [ istarget "*-*-*lynx*" ] then {
+ setup_xfail "*-*-*"
+ fail "kernel scroggs stack pointer in signal tests on this target"
+ return 0
+}
+
+gdb_exit
+gdb_start
+
+# This will need to be updated as the exact list of signals changes,
+# but I want to test that TARGET_SIGNAL_0, TARGET_SIGNAL_DEFAULT, and
+# TARGET_SIGNAL_UNKNOWN are skipped.
+proc test_handle_all_print {} {
+ global timeout
+ # Increase timeout and expect input buffer for large output from gdb.
+ # Allow blank or TAB as whitespace characters.
+ set oldtimeout $timeout
+ set timeout [expr "$timeout + 360"]
+ verbose "Timeout is now $timeout seconds" 2
+ if { [istarget "*-*-gnu*"] || [istarget "*-*-mach*"] } {
+ gdb_test "handle all print" "Signal\[ \]+Stop\[ \]+Print\[ \]+Pass to program\[ \]+Description\r\nSIGHUP\[ \]+Yes\[ \]+Yes\[ \]+Yes\[ \]+Hangup.*SIG63\[ \]+Yes\[ \]+Yes\[ \]+Yes\[ \]+Real-time event 63.*EXC_BREAKPOINT\[ \]+Yes\[ \]+Yes\[ \]+Yes\[ \]+Breakpoint"
+ } else {
+ gdb_test "handle all print" "Signal\[ \]+Stop\[ \]+Print\[ \]+Pass to program\[ \]+Description\r\nSIGHUP\[ \]+Yes\[ \]+Yes\[ \]+Yes\[ \]+Hangup.*SIG63\[ \]+Yes\[ \]+Yes\[ \]+Yes\[ \]+Real-time event 63"
+ }
+ set timeout $oldtimeout
+ verbose "Timeout restored to $timeout seconds" 2
+}
+test_handle_all_print
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load $binfile
+signal_tests_1
+
+# Force a resync, so we're looking at the right prompt. On SCO we
+# were getting out of sync (I don't understand why).
+send_gdb "p 1+1\n"
+gdb_expect {
+ -re "= 2.*$gdb_prompt $" {}
+ -re ".*$gdb_prompt $" { perror "sync trouble in signals.exp" }
+ default { perror "sync trouble in signals.exp" }
+}
+
+if [runto_main] then {
+ gdb_test "break handler if 0" "Breakpoint \[0-9\]+ .*"
+ gdb_test "set \$handler_breakpoint_number = \$bpnum" ""
+
+ # Get to the point where a signal is waiting to be delivered
+ gdb_test "next" "signal \\(SIGUSR1.*" "next to signal in signals.exp"
+ gdb_test "next" "alarm \\(.*" "next to alarm #1 in signals.exp"
+ gdb_test "next" "\\+\\+count; /\\* first \\*/" \
+ "next to ++count #1 in signals.exp"
+ # Give the signal time to get delivered
+ sleep 2
+
+ # Now call a function. When GDB tries to run the stack dummy,
+ # it will hit the breakpoint at handler. Provided it doesn't
+ # lose its cool, this is not a problem, it just has to note
+ # that the breakpoint condition is false and keep going.
+
+ gdb_test "p func1 ()" "^p func1 \\(\\)\r\n.\[0-9\]* = void" \
+ "p func1 () #1 in signals.exp"
+
+ # Make sure the count got incremented.
+
+ # Haven't investigated this xfail
+ setup_xfail "rs6000-*-*"
+ setup_xfail "powerpc-*-*"
+ gdb_test "p count" "= 2" "p count #1 in signals.exp"
+ if { [istarget "rs6000-*-*"] || [istarget "powerpc-*-*"] } { return 0 }
+
+ gdb_test "condition \$handler_breakpoint_number" "now unconditional\\."
+ gdb_test "next" "alarm \\(.*" "next to alarm #2 in signals.exp"
+ gdb_test "next" "\\+\\+count; /\\* second \\*/" \
+ "next to ++count #2 in signals.exp"
+ sleep 2
+
+ # This time we stop when GDB tries to run the stack dummy.
+ # So it is OK that we do not print the return value from the function.
+ gdb_test "p func1 ()" \
+"Breakpoint \[0-9\]*, handler.*
+The program being debugged stopped while in a function called from GDB.*" \
+ "p func1 () #2 in signals.exp"
+ # But we should be able to backtrace...
+ # On alpha-*-osf2.0 this test works when run manually but sometime fails when
+ # run under dejagnu, making it very hard to debug the problem. Weird...
+ gdb_test "bt 10" "#0.*handler.*#1.*#2.*main.*" "bt in signals.exp"
+ # ...and continue...
+ gdb_test "continue" "Continuing\\." "continue in signals.exp"
+ # ...and then count should have been incremented
+ gdb_test "p count" "= 5" "p count #2 in signals.exp"
+
+
+# Verify that "info signals" produces reasonable output.
+#
+ send_gdb "info signals\n"
+ gdb_expect {
+ -re "SIGHUP.*SIGINT.*SIGQUIT.*SIGILL.*SIGTRAP.*SIGABRT.*SIGEMT.*SIGFPE.*SIGKILL.*SIGBUS.*SIGSEGV.*SIGSYS.*SIGPIPE.*SIGALRM.*SIGTERM.*SIGURG.*SIGSTOP.*SIGTSTP.*SIGCONT.*SIGCHLD.*SIGTTIN.*SIGTTOU.*SIGIO.*SIGXCPU.*SIGXFSZ.*SIGVTALRM.*SIGPROF.*SIGWINCH.*SIGLOST.*SIGUSR1.*SIGUSR2.*SIGPWR.*SIGPOLL.*SIGWIND.*SIGPHONE.*SIGWAITING.*SIGLWP.*SIGDANGER.*SIGGRANT.*SIGRETRACT.*SIGMSG.*SIGSOUND.*SIGSAK.*SIGPRIO.*SIG33.*SIG34.*SIG35.*SIG36.*SIG37.*SIG38.*SIG39.*SIG40.*SIG41.*SIG42.*SIG43.*SIG44.*SIG45.*SIG46.*SIG47.*SIG48.*SIG49.*SIG50.*SIG51.*SIG52.*SIG53.*SIG54.*SIG55.*SIG56.*SIG57.*SIG58.*SIG59.*SIG60.*SIG61.*SIG62.*SIG63.*Use the \"handle\" command to change these tables.*$gdb_prompt $"\
+ {pass "info signals"}
+ -re "$gdb_prompt $"\
+ {fail "info signals"}
+ timeout {fail "(timeout) info signals"}
+ }
+
+# Verify that "info signal" correctly handles an argument, be it a
+# symbolic signal name, or an integer ID.
+#
+ send_gdb "info signal SIGTRAP\n"
+ gdb_expect {
+ -re ".*SIGTRAP\[ \t\]*Yes\[ \t\]*Yes\[ \t\]*No\[ \t\]*Trace/breakpoint trap.*$gdb_prompt $"\
+ {pass "info signal SIGTRAP"}
+ -re "$gdb_prompt $"\
+ {fail "info signal SIGTRAP"}
+ timeout {fail "(timeout) info signal SIGTRAP"}
+ }
+
+ send_gdb "info signal 5\n"
+ gdb_expect {
+ -re ".*SIGTRAP\[ \t\]*Yes\[ \t\]*Yes\[ \t\]*No\[ \t\]*Trace/breakpoint trap.*$gdb_prompt $"\
+ {pass "info signal 5"}
+ -re "$gdb_prompt $"\
+ {fail "info signal 5"}
+ timeout {fail "(timeout) info signal 5"}
+ }
+
+# Verify that "handle" with illegal arguments is gracefully, um, handled.
+#
+ send_gdb "handle\n"
+ gdb_expect {
+ -re "Argument required .signal to handle.*$gdb_prompt $"\
+ {pass "handle without arguments"}
+ -re "$gdb_prompt $"\
+ {fail "handle without arguments"}
+ timeout {fail "(timeout) handle without arguments"}
+ }
+
+ send_gdb "handle SIGFOO\n"
+ gdb_expect {
+ -re "Unrecognized or ambiguous flag word: \"SIGFOO\".*$gdb_prompt $"\
+ {pass "handle with bogus SIG"}
+ -re "$gdb_prompt $"\
+ {fail "handle with bogus SIG"}
+ timeout {fail "(timeout) handle with bogus SIG"}
+ }
+
+ send_gdb "handle SIGHUP frump\n"
+ gdb_expect {
+ -re "Unrecognized or ambiguous flag word: \"frump\".*$gdb_prompt $"\
+ {pass "handle SIG with bogus action"}
+ -re "$gdb_prompt $"\
+ {fail "handle SIG with bogus action"}
+ timeout {fail "(timeout) handle SIG with bogus action"}
+ }
+
+# Verify that "handle" can take multiple actions per SIG, and that in
+# the case of conflicting actions, that the rightmost action "wins".
+#
+ send_gdb "handle SIGHUP print noprint\n"
+ gdb_expect {
+ -re ".*SIGHUP\[ \t\]*No\[ \t\]*No\[ \t\]*Yes\[ \t\]*Hangup.*$gdb_prompt $"\
+ {pass "handle SIG with multiple conflicting actions"}
+ -re "$gdb_prompt $"\
+ {fail "handle SIG with multiple conflicting actions"}
+ timeout {fail "(timeout) handle SIG with multiple conflicting actions"}
+ }
+
+# Exercise all the various actions. (We don't care what the outcome
+# is, this is just to ensure that they all can be parsed.)
+#
+ send_gdb "handle SIGHUP print noprint stop nostop ignore noignore pass nopass\n"
+ gdb_expect {
+ -re ".*Signal.*$gdb_prompt $"\
+ {pass "handle SIG parses all legal actions"}
+ -re "$gdb_prompt $"\
+ {fail "handle SIG parses all legal actions"}
+ timeout {fail "(timeout) handle SIG parses all legal actions"}
+ }
+
+# Verify that we can "handle" multiple signals at once, interspersed
+# with actions.
+#
+ send_gdb "handle SIG63 print SIGILL\n"
+ gdb_expect {
+ -re ".*SIGILL\[ \t\]*Yes\[ \t\]*Yes\[ \t\]*Yes\[ \t\]*Illegal instruction.*SIG63\[ \t\]*Yes\[ \t\]*Yes\[ \t\]*Yes\[ \t\]*Real-time event 63.*$gdb_prompt $"\
+ {pass "handle multiple SIGs"}
+ -re "$gdb_prompt $"\
+ {fail "handle multiple SIGs"}
+ timeout {fail "(timeout) handle multiple SIGs"}
+ }
+
+# Verify that "handle" can take a numeric argument for the signal ID,
+# rather than a symbolic name. (This may not be portable; works for
+# HP-UX.)
+#
+# Also note that this testpoint overrides SIGTRAP, which on HP-UX at
+# least, is used to implement single-steps and breakpoints. Don't
+# expect to run the inferior after this!
+#
+ send_gdb "handle 5 nopass\n"
+ gdb_expect {
+ -re ".*SIGTRAP is used by the debugger.*Are you sure you want to change it.*y or n.*"\
+ {send_gdb "y\n"
+ gdb_expect {
+ -re ".*SIGTRAP\[ \t\]*Yes\[ \t\]*Yes\[ \t\]*No\[ \t\]*Trace/breakpoint trap.*$gdb_prompt $"\
+ {pass "override SIGTRAP (#5)"}
+ -re "$gdb_prompt $"\
+ {fail "override SIGTRAP (#5)"}
+ timeout {fail "(timeout) override SIGTRAP (#5)"}
+ }
+ }
+ -re "$gdb_prompt $"\
+ {fail "override SIGTRAP (#5)"}
+ timeout {fail "(timeout) override SIGTRAP (#5)"}
+ }
+
+# GDB doesn't seem to allow numeric signal IDs larger than 15. Verify
+# that restriction. ??rehrauer: Not sure if this is a feature or a
+# bug, actually. Why is the range 1-15?
+#
+ send_gdb "handle 58\n"
+ gdb_expect {
+ -re "Only signals 1-15 are valid as numeric signals.*Use \"info signals\" for a list of symbolic signals.*$gdb_prompt $"\
+ {pass "invalid signal number rejected"}
+ -re "$gdb_prompt $"\
+ {fail "invalid signal number rejected"}
+ timeout {fail "(timeout) invalid signal number rejected"}
+ }
+
+# Verify that we can accept a signal ID range (number-number).
+# ??rehrauer: This feature isn't documented on the quick-reference
+# card.
+#
+ send_gdb "handle 13-15\n"
+ gdb_expect {
+ -re ".*SIGPIPE.*SIGALRM.*SIGTERM.*$gdb_prompt $"\
+ {pass "handle multiple SIGs via integer range"}
+ -re "$gdb_prompt $"\
+ {fail "handle multiple SIGs via integer range"}
+ timeout {fail "(timeout) handle multiple SIGs via integer range"}
+
+ }
+
+# Bizarrely enough, GDB also allows you to reverse the range
+# stat, stop IDs. E.g., "3-1" and "1-3" mean the same thing.
+# Probably this isn't documented, but the code anticipates it,
+# so we'd best test it...
+#
+ send_gdb "handle 15-13\n"
+ gdb_expect {
+ -re ".*SIGPIPE.*SIGALRM.*SIGTERM.*$gdb_prompt $"\
+ {pass "handle multiple SIGs via integer range"}
+ -re "$gdb_prompt $"\
+ {fail "handle multiple SIGs via integer range"}
+ timeout {fail "(timeout) handle multiple SIGs via integer range"}
+
+ }
+
+# SIGINT is used by the debugger as well. Verify that we can change
+# our minds about changing it.
+#
+ send_gdb "handle SIGINT nopass\n"
+ gdb_expect {
+ -re ".*SIGINT is used by the debugger.*Are you sure you want to change it.*y or n.*"\
+ {send_gdb "n\n"
+# ??rehrauer: When you answer "n", the header for the signal info is
+# printed, but not the actual handler settings. Probably a bug.
+#
+ gdb_expect {
+ -re "Not confirmed, unchanged.*Signal.*$gdb_prompt $"\
+ {pass "override SIGINT"}
+ -re "$gdb_prompt $"\
+ {fail "override SIGINT"}
+ timeout {fail "(timeout) override SIGINT"}
+ }
+ }
+ -re "$gdb_prompt $"\
+ {fail "override SIGINT"}
+ timeout {fail "(timeout) override SIGINT"}
+ }
+
+# Verify that GDB responds gracefully to the "signal" command with
+# a missing argument.
+#
+ send_gdb "signal\n"
+ gdb_expect {
+ -re "Argument required .signal number..*$gdb_prompt $"\
+ {pass "signal without arguments disallowed"}
+ -re "$gdb_prompt $"\
+ {fail "signal without arguments disallowed"}
+ timeout {fail "(timeout) signal without arguments disallowed"}
+ }
+
+# Verify that we can successfully send a signal other than 0 to
+# the inferior. (This probably causes the inferior to run away.
+# Be prepared to rerun to main for further testing.)
+#
+ send_gdb "signal 5\n"
+ gdb_expect {
+ -re "Continuing with signal SIGTRAP.*$gdb_prompt $"\
+ {pass "sent signal 5"}
+ -re "$gdb_prompt $"\
+ {fail "sent signal 5"}
+ timeout {fail "(timeout) sent signal 5"}
+ }
+
+}
+
+return 0
diff --git a/gdb/testsuite/gdb.base/smoke.c b/gdb/testsuite/gdb.base/smoke.c
new file mode 100644
index 00000000000..69d34c9790f
--- /dev/null
+++ b/gdb/testsuite/gdb.base/smoke.c
@@ -0,0 +1,40 @@
+/* Test various kinds of stepping.
+*/
+int glob = 0;
+
+int callee() {
+ glob++;
+ return (0);
+}
+
+int main () {
+ int w,x,y,z;
+ int a[10], b[10];
+
+ /* Test "next" and "step" */
+ w = 0;
+ x = 1;
+ y = 2;
+ z = 3;
+ w = w + 2;
+ x = x + 3;
+ y = y + 4;
+ z = z + 5;
+
+ /* Test that "next" goes over a call */
+ callee(); /* OVER */
+
+ /* Test that "step" doesn't */
+ callee(); /* INTO */
+
+ /* Test "stepi" */
+ a[5] = a[3] - a[4];
+ callee(); /* STEPI */
+
+ /* Test "nexti" */
+ callee(); /* NEXTI */
+
+ y = w + z;
+
+ return (0);
+}
diff --git a/gdb/testsuite/gdb.base/smoke.cc b/gdb/testsuite/gdb.base/smoke.cc
new file mode 100644
index 00000000000..931fdaf061b
--- /dev/null
+++ b/gdb/testsuite/gdb.base/smoke.cc
@@ -0,0 +1,480 @@
+// Test various -*- C++ -*- things.
+
+typedef struct fleep fleep;
+struct fleep { int a; } s;
+
+// ====================== simple class structures =======================
+
+struct default_public_struct {
+ // defaults to public:
+ int a;
+ int b;
+};
+
+struct explicit_public_struct {
+ public:
+ int a;
+ int b;
+};
+
+struct protected_struct {
+ protected:
+ int a;
+ int b;
+};
+
+struct private_struct {
+ private:
+ int a;
+ int b;
+};
+
+struct mixed_protection_struct {
+ public:
+ int a;
+ int b;
+ private:
+ int c;
+ int d;
+ protected:
+ int e;
+ int f;
+ public:
+ int g;
+ private:
+ int h;
+ protected:
+ int i;
+};
+
+class public_class {
+ public:
+ int a;
+ int b;
+};
+
+class protected_class {
+ protected:
+ int a;
+ int b;
+};
+
+class default_private_class {
+ // defaults to private:
+ int a;
+ int b;
+};
+
+class explicit_private_class {
+ private:
+ int a;
+ int b;
+};
+
+class mixed_protection_class {
+ public:
+ int a;
+ int b;
+ private:
+ int c;
+ int d;
+ protected:
+ int e;
+ int f;
+ public:
+ int g;
+ private:
+ int h;
+ protected:
+ int i;
+};
+
+// ========================= simple inheritance ==========================
+
+class A {
+ public:
+ int a;
+ int x;
+};
+
+A g_A;
+
+class B : public A {
+ public:
+ int b;
+ int x;
+};
+
+B g_B;
+
+class C : public A {
+ public:
+ int c;
+ int x;
+};
+
+C g_C;
+
+class D : public B, public C {
+ public:
+ int d;
+ int x;
+};
+
+D g_D;
+
+class E : public D {
+ public:
+ int e;
+ int x;
+};
+
+E g_E;
+
+class class_with_anon_union
+{
+ public:
+ int one;
+ union
+ {
+ int a;
+ long b;
+ };
+};
+
+class_with_anon_union g_anon_union;
+
+void inheritance2 (void)
+{
+}
+
+void inheritance1 (void)
+{
+ int ival;
+ int *intp;
+
+ // {A::a, A::x}
+
+ g_A.A::a = 1;
+ g_A.A::x = 2;
+
+ // {{A::a,A::x},B::b,B::x}
+
+ g_B.A::a = 3;
+ g_B.A::x = 4;
+ g_B.B::b = 5;
+ g_B.B::x = 6;
+
+ // {{A::a,A::x},C::c,C::x}
+
+ g_C.A::a = 7;
+ g_C.A::x = 8;
+ g_C.C::c = 9;
+ g_C.C::x = 10;
+
+ // {{{A::a,A::x},B::b,B::x},{{A::a,A::x},C::c,C::x},D::d,D::x}
+
+ // The following initialization code is non-portable, but allows us
+ // to initialize all members of g_D until we can fill in the missing
+ // initialization code with legal C++ code.
+
+ for (intp = (int *) &g_D, ival = 11;
+ intp < ((int *) &g_D + sizeof (g_D) / sizeof (int));
+ intp++, ival++)
+ {
+ *intp = ival;
+ }
+
+ // Overlay the nonportable initialization with legal initialization.
+
+ // ????? = 11; (g_D.A::a = 11; is ambiguous)
+ // ????? = 12; (g_D.A::x = 12; is ambiguous)
+ g_D.B::b = 13;
+ g_D.B::x = 14;
+ // ????? = 15;
+ // ????? = 16;
+ g_D.C::c = 17;
+ g_D.C::x = 18;
+ g_D.D::d = 19;
+ g_D.D::x = 20;
+
+
+ // {{{{A::a,A::x},B::b,B::x},{{A::a,A::x},C::c,C::x},D::d,D::x}},E::e,E::x}
+
+ // The following initialization code is non-portable, but allows us
+ // to initialize all members of g_D until we can fill in the missing
+ // initialization code with legal C++ code.
+
+ for (intp = (int *) &g_E, ival = 21;
+ intp < ((int *) &g_E + sizeof (g_E) / sizeof (int));
+ intp++, ival++)
+ {
+ *intp = ival;
+ }
+
+ // Overlay the nonportable initialization with legal initialization.
+
+ // ????? = 21; (g_E.A::a = 21; is ambiguous)
+ // ????? = 22; (g_E.A::x = 22; is ambiguous)
+ g_E.B::b = 23;
+ g_E.B::x = 24;
+ // ????? = 25;
+ // ????? = 26;
+ g_E.C::c = 27;
+ g_E.C::x = 28;
+ g_E.D::d = 29;
+ g_E.D::x = 30;
+ g_E.E::e = 31;
+ g_E.E::x = 32;
+
+ g_anon_union.one = 1;
+ g_anon_union.a = 2;
+
+ inheritance2 ();
+}
+
+// ======================== virtual base classes=========================
+
+class vA {
+ public:
+ int va;
+ int vx;
+};
+
+vA g_vA;
+
+class vB : public virtual vA {
+ public:
+ int vb;
+ int vx;
+};
+
+vB g_vB;
+
+class vC : public virtual vA {
+ public:
+ int vc;
+ int vx;
+};
+
+vC g_vC;
+
+class vD : public virtual vB, public virtual vC {
+ public:
+ int vd;
+ int vx;
+};
+
+vD g_vD;
+
+class vE : public virtual vD {
+ public:
+ int ve;
+ int vx;
+};
+
+vE g_vE;
+
+void inheritance4 (void)
+{
+}
+
+void inheritance3 (void)
+{
+ int ival;
+ int *intp;
+
+ // {vA::va, vA::vx}
+
+ g_vA.vA::va = 1;
+ g_vA.vA::vx = 2;
+
+ // {{vA::va, vA::vx}, vB::vb, vB::vx}
+
+ g_vB.vA::va = 3;
+ g_vB.vA::vx = 4;
+ g_vB.vB::vb = 5;
+ g_vB.vB::vx = 6;
+
+ // {{vA::va, vA::vx}, vC::vc, vC::vx}
+
+ g_vC.vA::va = 7;
+ g_vC.vA::vx = 8;
+ g_vC.vC::vc = 9;
+ g_vC.vC::vx = 10;
+
+ // {{{{vA::va, vA::vx}, vB::vb, vB::vx}, vC::vc, vC::vx}, vD::vd,vD::vx}
+
+ g_vD.vA::va = 11;
+ g_vD.vA::vx = 12;
+ g_vD.vB::vb = 13;
+ g_vD.vB::vx = 14;
+ g_vD.vC::vc = 15;
+ g_vD.vC::vx = 16;
+ g_vD.vD::vd = 17;
+ g_vD.vD::vx = 18;
+
+
+ // {{{{{vA::va,vA::vx},vB::vb,vB::vx},vC::vc,vC::vx},vD::vd,vD::vx},vE::ve,vE::vx}
+
+ g_vD.vA::va = 19;
+ g_vD.vA::vx = 20;
+ g_vD.vB::vb = 21;
+ g_vD.vB::vx = 22;
+ g_vD.vC::vc = 23;
+ g_vD.vC::vx = 24;
+ g_vD.vD::vd = 25;
+ g_vD.vD::vx = 26;
+ g_vE.vE::ve = 27;
+ g_vE.vE::vx = 28;
+
+ inheritance4 ();
+}
+
+// ======================================================================
+
+class Base1 {
+ public:
+ int x;
+ Base1(int i) { x = i; }
+};
+
+class Foo
+{
+ public:
+ int x;
+ int y;
+ static int st;
+ Foo (int i, int j) { x = i; y = j; }
+ int operator! ();
+ operator int ();
+ int times (int y);
+};
+
+class Bar : public Base1, public Foo {
+ public:
+ int z;
+ Bar (int i, int j, int k) : Base1 (10*k), Foo (i, j) { z = k; }
+};
+
+int Foo::operator! () { return !x; }
+
+int Foo::times (int y) { return x * y; }
+
+int Foo::st = 100;
+
+Foo::operator int() { return x; }
+
+Foo foo(10, 11);
+Bar bar(20, 21, 22);
+
+class Contains_static_instance
+{
+ public:
+ int x;
+ int y;
+ Contains_static_instance (int i, int j) { x = i; y = j; }
+ static Contains_static_instance null;
+};
+
+Contains_static_instance Contains_static_instance::null(0,0);
+Contains_static_instance csi(10,20);
+
+class Contains_nested_static_instance
+{
+ public:
+ class Nested
+ {
+ public:
+ Nested(int i) : z(i) {}
+ int z;
+ static Contains_nested_static_instance xx;
+ };
+
+ Contains_nested_static_instance(int i, int j) : x(i), y(j) {}
+
+ int x;
+ int y;
+
+ static Contains_nested_static_instance null;
+ static Nested yy;
+};
+
+Contains_nested_static_instance Contains_nested_static_instance::null(0, 0);
+Contains_nested_static_instance::Nested Contains_nested_static_instance::yy(5);
+Contains_nested_static_instance
+ Contains_nested_static_instance::Nested::xx(1,2);
+Contains_nested_static_instance cnsi(30,40);
+
+typedef struct {
+ int one;
+ int two;
+} tagless_struct;
+tagless_struct v_tagless;
+
+/* Try to get the compiler to allocate a class in a register. */
+class small {
+ public:
+ int x;
+ int method ();
+};
+int small::method ()
+{
+ return x + 5;
+}
+void marker_reg1 () {}
+
+int
+register_class ()
+{
+ /* We don't call any methods for v, so gcc version cygnus-2.3.3-930220
+ might put this variable in a register. This is a lose, though, because
+ it means that GDB can't call any methods for that variable. */
+ register small v;
+
+ int i;
+
+ /* Perform a computation sufficiently complicated that optimizing compilers
+ won't optimized out the variable. If some compiler constant-folds this
+ whole loop, maybe using a parameter to this function here would help. */
+ v.x = 0;
+ for (i = 0; i < 13; ++i)
+ v.x += i;
+ --v.x; /* v.x is now 77 */
+ marker_reg1 ();
+ return v.x + 5;
+}
+
+int
+main()
+{
+#ifdef usestubs
+ set_debug_traps();
+ breakpoint();
+#endif
+ inheritance1 ();
+ inheritance3 ();
+ register_class ();
+
+ /* FIXME: pmi gets optimized out. Need to do some more computation with
+ it or something. (No one notices, because the test is xfail'd anyway,
+ but that probably won't always be true...). */
+ int Foo::* pmi = &Foo::y;
+
+ /* Make sure the AIX linker doesn't remove the variable. */
+ v_tagless.one = 5;
+
+ return foo.*pmi;
+}
+
+/* Create an instance for some classes, otherwise they get optimized away. */
+default_public_struct default_public_s;
+explicit_public_struct explicit_public_s;
+protected_struct protected_s;
+private_struct private_s;
+mixed_protection_struct mixed_protection_s;
+public_class public_c;
+protected_class protected_c;
+default_private_class default_private_c;
+explicit_private_class explicit_private_c;
+mixed_protection_class mixed_protection_c;
diff --git a/gdb/testsuite/gdb.base/smoke.exp b/gdb/testsuite/gdb.base/smoke.exp
new file mode 100644
index 00000000000..42de7c891f1
--- /dev/null
+++ b/gdb/testsuite/gdb.base/smoke.exp
@@ -0,0 +1,181 @@
+# Copyright (C) 1997, 1998 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# smoke.exp -- Expect script to test gdb before checkins
+
+# use this to debug:
+#
+#log_user 1
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+set testfile smoke
+set testfile1 smoke1
+set c_srcfile ${srcdir}/${subdir}/${testfile}.c
+set cpp_srcfile ${srcdir}/${subdir}/${testfile}.cc
+set binfile ${objdir}/${subdir}/${testfile}
+set binfile1 ${objdir}/${subdir}/${testfile1}
+
+#remote_exec build "rm -f ${binfile}"
+remote_exec build "rm -f core"
+
+# "C" section, using source copied from "step-test.c" from "gdb.base"
+#
+if { [gdb_compile "${c_srcfile}" "${binfile}" executable {debug}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+# Some basic tests
+#
+gdb_test "tb main" ".*Breakpoint 1 at.*line 15.*" "temp breakpoint"
+gdb_test "b callee" ".*Breakpoint 2 at.*line 6.*" "breakpoint"
+gdb_test "l 10" ".*10.*int main.*11.*int w,x,y,z;.*12.*int a.*" "list"
+gdb_test "c" ".*The program is not being run.*" "catch error"
+gdb_test "r" ".*Starting program.*main.*15.*" "hit bp"
+gdb_test "hel r" ".*Start debugged program.*without arguments.*" "help"
+gdb_test "n" ".*x = 1;.*" "next"
+gdb_test "s" ".*y = 2;.*" "step"
+gdb_test "p/t y" ".* = 1.*" "print y in binary"
+gdb_test "p 1+2*3+4" ".* = 11.*" "calculate"
+gdb_test "p/t 1+2*3+4" ".* = 1011.*" "binary"
+
+# Note: accept either "Watchpoint" or "Hardware watchpoint";
+# 10.20 can't do the hardware watch. The hardware kind
+# triggers one line earlier than the regular kind.
+#
+gdb_test "wat y" ".*atchpoint.*y.*" "set watch"
+gdb_test "c" ".*atchpoint.*Old.*= .*New.*= 2.*1\[78\].*" "continue, hit watch"
+
+gdb_test "set glob=999" ".*.*" "set"
+gdb_test "p glob" ".*= 999.*.*" "print glob"
+gdb_test "p/x glob" ".*= 0x3e7.*" "hex"
+gdb_test "c" ".*atchpoint.*Old.*= 2.*New.*= 6.*2\[12\].*" "continue, 2nd hit watch"
+gdb_test "d 5" "No breakpoint number 5." "del non existing watch"
+gdb_test "c" ".*Breakpoint.*callee.*6.*" "hit bp"
+gdb_test "bt" ".*callee.*6.*main.*25.*" "bt"
+gdb_test "fin" ".*Run till exit.*callee.*Value returned.*0.*" "finish"
+gdb_test "c" ".*Breakpoint.*callee.*6.*" "hit bp again"
+gdb_test "cle" ".*Deleted breakpoint.*" "clear"
+gdb_test "wat glob" ".*atchpoint.*glob.*" "set 2nd watch"
+gdb_test "i wat" ".*" ""
+gdb_test "whe" ".*" ""
+
+# ??rehrauer: We're now disabling watchpoints while an interactive
+# call is "in flight". When/if we can teach gdb how to unwind through
+# the call dummy frame, we can then allow watches during calls, and
+# also then restore this testpoint to the original, commented-out form.
+#
+gdb_test "call callee()" ".*\[0-9\]* = 0.*" "call, didn't hit watch"
+#gdb_test "call callee()" ".*atchpoint.*Old.*= 1000.*New.*= 1001.*\[67\].*being debug.*is done.*" "call, hit watch"
+
+gdb_test "d 4" ".*" "del watch 2"
+gdb_test "d 3" ".*" "del watch 1"
+gdb_test "info break" "No breakpoints or watchpoints."
+# since we have deleted all the watchpoints this test is useless
+#gdb_test "c" ".*Continuing.*" "end call"
+gdb_test "c" ".*Program exited normally.*" "pgm exit"
+
+# Check for production of a core file
+#
+#set exec_output [execute_anywhere "ls core"]
+set exec_output [remote_exec build "ls core"]
+
+if [ regexp "core not found" $exec_output] {
+ pass "No core dumped on quit"
+} else {
+ if [ regexp "No such file or directory" $exec_output] {
+ pass "ls: core: No core dumped on quit"
+ } else {
+ remote_exec build "rm -f core"
+ fail "Core dumped on quit"
+ }
+}
+
+
+#========================================
+#
+# "C++" section, using source copied from "misc.cc" from "gdb.c++"
+#
+
+#
+#remote_exec build "rm -f ${binfile}"
+#remote_exec build "CC -g -o ${binfile} ${cpp_srcfile}"
+if {[gdb_compile "${cpp_srcfile}" "${binfile1}" executable {c++ debug}] != ""} {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile1}
+
+# Tests, some copied from misc.exp.
+#
+
+ # See what language gdb thinks main() is, prior to reading full symbols.
+ # I think this fails for COFF targets.
+ setup_xfail "a29k-*-udi"
+ send_gdb "show language\n"
+ gdb_expect {
+ -re ".* source language is \"auto; currently c\\+\\+\".*$gdb_prompt $" {
+ pass "deduced language is C++, before full symbols"
+ }
+ -re ".*$gdb_prompt $" { fail "source language not correct for C++ (psymtabs only)"}
+ return
+
+ timeout { fail "can't show language (timeout)"}
+ return
+ }
+
+gdb_test "b main" ".*Breakpoint 1 at.*" ""
+gdb_test "r" ".*Starting program.*Breakpoint 1.*" "run to main"
+gdb_test "ptype Foo" ".*type = class Foo.*static int st;.*int operator.*" "ptype"
+gdb_test "step" ".*inheritance1.*" "step"
+gdb_test "ptype g_anon_union" ".*anon_union.*union.*int a;.*" "anon"
+gdb_test "p g_E" ".*class D.*class B.*class A.*class C.*class A.*x = 0.*" "print inherited class "
+gdb_test "p g_E.x = 99" ".*warn.*x ambiguous; using E::x. Use a cast to disambig.*99.*" "set via print"
+gdb_test "c" ".*Program exited.*" "run to end"
+
+gdb_exit
+
+# Check for production of a core file
+#
+#set exec_output [execute_anywhere "ls core"]
+set exec_output [remote_exec build "ls core"]
+if [ regexp "core not found" $exec_output] {
+ pass "No core dumped on quit"
+} else {
+ if [ regexp "No such file or directory" $exec_output] {
+ pass "ls: core: No core dumped on quit"
+ } else {
+ remote_exec build "rm -f core"
+ fail "Core dumped on quit"
+ }
+}
+
+# execute_anywhere "rm -f ${binfile1}"
+#
+return 0
diff --git a/gdb/testsuite/gdb.base/so-impl-ld.c b/gdb/testsuite/gdb.base/so-impl-ld.c
new file mode 100644
index 00000000000..a8fa18949b2
--- /dev/null
+++ b/gdb/testsuite/gdb.base/so-impl-ld.c
@@ -0,0 +1,18 @@
+/* This program is linked against SOM shared libraries, which the loader
+ automatically loads along with the program itself).
+ */
+
+#include <stdio.h>
+
+extern int solib_main (int);
+
+main ()
+{
+ int result;
+
+ /* Call a shlib function. */
+ result = solib_main (100);
+
+ /* Call it again. */
+ result = solib_main (result);
+}
diff --git a/gdb/testsuite/gdb.base/so-impl-ld.exp b/gdb/testsuite/gdb.base/so-impl-ld.exp
new file mode 100644
index 00000000000..a52aa1fdfb3
--- /dev/null
+++ b/gdb/testsuite/gdb.base/so-impl-ld.exp
@@ -0,0 +1,167 @@
+# Copyright (C) 1997, 1998 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+if $tracelevel then {
+ strace $tracelevel
+ }
+
+set prms_id 0
+set bug_id 0
+
+# are we on a target board
+if ![isnative] then {
+ return
+}
+
+# This test is presently only valid on HP-UX, since it requires
+# that we use HP-UX-specific compiler & linker options to build
+# the testcase.
+#
+setup_xfail "*-*-*"
+clear_xfail "hppa*-*-*hpux*"
+
+set libfile "solib"
+set testfile "so-impl-ld"
+set srcfile ${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+
+if [get_compiler_info ${binfile}] {
+ return -1
+}
+
+# Build the shared libraries this test case needs.
+#
+#cd ${subdir}
+#remote_exec build "$CC -g +z -c ${libfile}1.c -o ${libfile}1.o"
+
+
+if {$gcc_compiled == 0} {
+ if [istarget "hppa*-hp-hpux*"] then {
+ set additional_flags "additional_flags=+z"
+ } else {
+ # don't know that the compiler is, hope for the best...
+ set additional_flags ""
+ }
+} else {
+ set additional_flags "additional_flags=-fpic"
+}
+
+if {[gdb_compile "${srcdir}/${subdir}/${libfile}1.c" "${libfile}1.o" object [list debug $additional_flags]] != ""} {
+ perror "Couldn't compile ${libfile}1.c"
+ return -1
+}
+
+if [istarget "hppa*-hp-hpux*"] then {
+ remote_exec build "ld -b ${libfile}1.o -o ${libfile}1.sl"
+} else {
+ set additional_flags "additional_flags=-shared"
+ gdb_compile "${libfile}1.o" "${libfile}1.sl" executable [list debug $additional_flags]
+}
+
+# Build the test case
+#remote_exec build "$CC -Aa -g ${srcfile} ${libfile}1.sl -o ${binfile}"
+
+
+if {$gcc_compiled == 0} {
+ if [istarget "hppa*-hp-hpux*"] then {
+ set additional_flags "additional_flags=-Ae"
+ } else {
+ # don't know what the compiler is, hope for the best, maybe it's ANSI...
+ set additional_flags ""
+ }
+} else {
+ set additional_flags ""
+}
+
+if {[gdb_compile "${srcdir}/${subdir}/${srcfile} ${libfile}1.sl" "${binfile}" executable [list debug $additional_flags]] != ""} {
+ perror "Couldn't build ${binfile}"
+ return -1
+}
+#cd ..
+
+# Start with a fresh gdb
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+# This program implicitly loads SOM shared libraries.
+#
+if ![runto_main] then { fail "implicit solibs tests suppressed" }
+
+# Verify that we can step over the first shlib call.
+#
+send_gdb "next\n"
+gdb_expect {
+ -re "17\[ \t\]*result = solib_main .result.*$gdb_prompt $"\
+ {pass "step over solib call"}
+ -re "$gdb_prompt $"\
+ {fail "step over solib call"}
+ timeout {fail "(timeout) step over solib call"}
+}
+
+# Verify that we can step into the second shlib call.
+#
+send_gdb "step\n"
+gdb_expect {
+ -re "solib_main .arg=10000. at.*${libfile}1.c:8.*$gdb_prompt $"\
+ {pass "step into solib call"}
+ -re "$gdb_prompt $"\
+ {fail "step into solib call"}
+ timeout {fail "(timeout) step into solib call"}
+}
+
+# Verify that we can step within the shlib call.
+#
+send_gdb "next\n"
+gdb_expect {
+ -re "9\[ \t\]*\}.*$gdb_prompt $"\
+ {pass "step in solib call"}
+ -re "$gdb_prompt $"\
+ {fail "step in solib call"}
+ timeout {fail "(timeout) step in solib call"}
+}
+
+# Verify that we can step out of the shlib call, and back out into
+# the caller.
+#
+send_gdb "next\n"
+gdb_expect {
+ -re "0x\[0-9a-f\]*\[ \t\]*9\[ \t\]*.*$gdb_prompt $" {
+ # we haven't left the callee yet, so do another next
+ send_gdb "next\n"
+ gdb_expect {
+ -re "main .. at.*so-impl-ld.c:18.*$gdb_prompt $"\
+ {pass "step out of solib call"}
+ -re "$gdb_prompt $"\
+ {fail "step out of solib call"}
+ timeout {fail "(timeout) step out of solib call"}
+ }
+ }
+
+ -re "main .. at.*so-impl-ld.c:18.*$gdb_prompt $"\
+ {pass "step out of solib call"}
+ -re "$gdb_prompt $"\
+ {fail "step out of solib call"}
+ timeout {fail "(timeout) step out of solib call"}
+}
+
+gdb_exit
+return 0
diff --git a/gdb/testsuite/gdb.base/so-indr-cl.c b/gdb/testsuite/gdb.base/so-indr-cl.c
new file mode 100644
index 00000000000..dc29badcbd7
--- /dev/null
+++ b/gdb/testsuite/gdb.base/so-indr-cl.c
@@ -0,0 +1,23 @@
+/* This program is linked against SOM shared libraries, which the loader
+ automatically loads along with the program itself).
+ */
+
+#include <stdio.h>
+
+extern int solib_main (int);
+
+static int
+solib_wrapper (function)
+ int (*function)(int);
+{
+ return (*function)(100);
+}
+
+
+main ()
+{
+ int result;
+
+ /* This is an indirect call to solib_main. */
+ result = solib_wrapper (solib_main);
+}
diff --git a/gdb/testsuite/gdb.base/so-indr-cl.exp b/gdb/testsuite/gdb.base/so-indr-cl.exp
new file mode 100644
index 00000000000..e37878e4a6b
--- /dev/null
+++ b/gdb/testsuite/gdb.base/so-indr-cl.exp
@@ -0,0 +1,146 @@
+# Copyright (C) 1997, 1998 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+if $tracelevel then {
+ strace $tracelevel
+ }
+
+set prms_id 0
+set bug_id 0
+
+# are we on a target board
+if ![isnative] then {
+ return
+}
+
+# This test is presently only valid on HP-UX, since it requires
+# that we use HP-UX-specific compiler & linker options to build
+# the testcase.
+#
+setup_xfail "*-*-*"
+clear_xfail "hppa*-*-*hpux*"
+
+set libfile "solib"
+set testfile "so-indr-cl"
+set srcfile ${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+
+if [get_compiler_info ${binfile}] {
+ return -1
+}
+
+# Build the shared libraries this test case needs.
+#
+#cd ${subdir}
+#remote_exec build "$CC -g +z -c ${libfile}1.c -o ${libfile}1.o"
+
+
+if {$gcc_compiled == 0} {
+ if [istarget "hppa*-hp-hpux*"] then {
+ set additional_flags "additional_flags=+z"
+ } else {
+ # don't know what the compiler is...
+ set additional_flags ""
+ }
+} else {
+ set additional_flags "additional_flags=-fpic"
+}
+if {[gdb_compile "${srcdir}/${subdir}/${libfile}1.c" "${objdir}/${subdir}/${libfile}1.o" object [list debug $additional_flags]] != ""} {
+ perror "Couldn't compile ${libfile}1.c"
+ return -1
+}
+
+if [istarget "hppa*-hp-hpux*"] then {
+ remote_exec build "ld -b ${objdir}/${subdir}/${libfile}1.o -o ${objdir}/${subdir}/${libfile}1.sl"
+} else {
+ set additional_flags "additional_flags=-shared"
+ gdb_compile "${objdir}/${subdir}/${libfile}1.o" "${objdir}/${subdir}/${libfile}1.sl" executable [list debug $additional_flags]
+}
+
+# Build the test case
+#remote_exec build "$CC -Aa -g ${srcfile} ${libfile}1.sl -o ${binfile}"
+
+
+if {$gcc_compiled == 0} {
+ if [istarget "hppa*-hp-hpux*"] then {
+ set additional_flags "additional_flags=-Ae"
+ } else {
+ # don't know what the compiler is, hope for the best, maybe it's ANSI...
+ set additional_flags ""
+ }
+} else {
+ set additional_flags ""
+}
+if {[gdb_compile "${srcdir}/${subdir}/${srcfile} ${objdir}/${subdir}/${libfile}1.sl" "${binfile}" executable [list debug $additional_flags]] != ""} {
+ perror "Couldn't build ${binfile}"
+ return -1
+}
+
+#cd ..
+
+# Start with a fresh gdb
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+# This program implicitly loads SOM shared libraries. We wish to test
+# whether a user can set breakpoints in a shlib before running the
+# program, where the program doesn't directly call the shlib, but
+# indirectly does via passing its address to another function.
+#
+# ??rehrauer: Currently, this doesn't work, but we do catch the case
+# and explicitly disallow it. The reason it fails appears to be that
+#
+# [1] gdb consults only the linker symbol table in this scenario, and
+# [2] For a shlib function that is only indirectly called from the
+# main a.out, there is in the linker symbol table a stub whose
+# address is negative. Possibly this is to be interpreted as
+# an index into the DLT??
+#
+send_gdb "break solib_main\n"
+gdb_expect {
+ -re "Cannot break on solib_main without a running program.*$gdb_prompt $"\
+ {pass "break on indirect solib call before running"}
+ -re "$gdb_prompt $"\
+ {fail "break on indirect solib call before running"}
+ timeout {fail "(timeout) break on indirect solib call before running"}
+}
+
+# However, if we do run to the program's main, we then ought to be
+# able to set a breakpoint on the indirectly called function. (Apparently,
+# once the inferior is running, gdb consults the debug info rather than
+# the linker symbol table, and is able to find the correct address.)
+#
+if ![runto_main] then { fail "indirect solib call tests suppressed" }
+
+# Verify that we can step over the first shlib call.
+#
+send_gdb "break solib_main\n"
+gdb_expect {
+ -re ".*\[Bb\]reakpoint \[0-9\]* at 0x\[0-9a-fA-F\]*: file.*${libfile}1.c.*$gdb_prompt $"\
+ {pass "break on indirect solib call after running"}
+ -re "$gdb_prompt $"\
+ {fail "break on indirect solib call after running"}
+ timeout {fail "(timeout) break on indirect solib call after running"}
+}
+
+gdb_exit
+return 0
diff --git a/gdb/testsuite/gdb.base/solib.c b/gdb/testsuite/gdb.base/solib.c
new file mode 100644
index 00000000000..ff9d359218e
--- /dev/null
+++ b/gdb/testsuite/gdb.base/solib.c
@@ -0,0 +1,59 @@
+/* This program uses HP-UX-specific features to load and unload SOM
+ shared libraries that it wasn't linked against (i.e., libraries
+ that the loader doesn't automatically load along with the program
+ itself).
+ */
+
+#include <stdio.h>
+#include <dl.h>
+
+main ()
+{
+ shl_t solib_handle;
+ int dummy;
+ int status;
+ int (*solib_main) ();
+
+ /* Load a shlib, with immediate binding of all symbols.
+
+ Note that the pathname of the loaded shlib is assumed to be relative
+ to the testsuite directory (from whence the tested GDB is run), not
+ from dot/.
+ */
+ dummy = 1; /* Put some code between shl_ calls... */
+ solib_handle = shl_load ("gdb.base/solib1.sl", BIND_IMMEDIATE, 0);
+
+ /* Find a function within the shlib, and call it. */
+ status = shl_findsym (&solib_handle,
+ "solib_main",
+ TYPE_PROCEDURE,
+ (long *) &solib_main);
+ status = (*solib_main) (dummy);
+
+ /* Unload the shlib. */
+ status = shl_unload (solib_handle);
+
+ /* Load a different shlib, with deferred binding of all symbols. */
+ dummy = 2;
+ solib_handle = shl_load ("gdb.base/solib2.sl", BIND_DEFERRED, 0);
+
+ /* Find a function within the shlib, and call it. */
+ status = shl_findsym (&solib_handle,
+ "solib_main",
+ TYPE_PROCEDURE,
+ (long *) &solib_main);
+ status = (*solib_main) (dummy);
+
+ /* Unload the shlib. */
+ status = shl_unload (solib_handle);
+
+ /* Reload the first shlib again, with deferred symbol binding this time. */
+ dummy = 3;
+ solib_handle = shl_load ("gdb.base/solib1.sl", BIND_IMMEDIATE, 0);
+
+ /* Unload it without trying to find any symbols in it. */
+ status = shl_unload (solib_handle);
+
+ /* All done. */
+ dummy = -1;
+}
diff --git a/gdb/testsuite/gdb.base/solib.exp b/gdb/testsuite/gdb.base/solib.exp
new file mode 100644
index 00000000000..f452194d8a7
--- /dev/null
+++ b/gdb/testsuite/gdb.base/solib.exp
@@ -0,0 +1,319 @@
+# Copyright (C) 1997, 1998 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+if $tracelevel then {
+ strace $tracelevel
+ }
+
+set prms_id 0
+set bug_id 0
+
+# are we on a target board
+if ![isnative] then {
+ return
+}
+
+# This test is presently only valid on HP-UX. It verifies GDB's
+# ability to catch loads and unloads of shared libraries.
+#
+
+#setup_xfail "*-*-*"
+#clear_xfail "hppa*-*-*hpux*"
+if {![istarget "hppa*-*-hpux*"]} {
+ return 0
+}
+
+set testfile "solib"
+set srcfile ${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+
+# build the first test case
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+if [get_compiler_info ${binfile}] {
+ return -1
+}
+
+# Build the shared libraries this test case needs.
+#
+#cd ${subdir}
+#remote_exec build "$CC -g +z -c ${testfile}1.c -o ${testfile}1.o"
+#remote_exec build "$CC -g +z -c ${testfile}2.c -o ${testfile}2.o"
+
+if {$gcc_compiled == 0} {
+ if [istarget "hppa*-hp-hpux*"] then {
+ set additional_flags "additional_flags=+z"
+ } else {
+ # don't know what the compiler is...
+ set additional_flags ""
+ }
+} else {
+ set additional_flags "additional_flags=-fpic"
+}
+
+if {[gdb_compile "${srcdir}/${subdir}/${testfile}1.c" "${binfile}1.o" object [list debug $additional_flags]] != ""} {
+ perror "Couldn't compile ${testfile}1.c"
+ #return -1
+}
+if {[gdb_compile "${srcdir}/${subdir}/${testfile}2.c" "${binfile}2.o" object [list debug, $additional_flags]] != ""} {
+ perror "Couldn't compile ${testfile}2.c"
+ #return -1
+}
+
+if [istarget "hppa*-*-hpux*"] {
+ remote_exec build "ld -b ${binfile}1.o -o ${binfile}1.sl"
+ remote_exec build "ld -b ${binfile}2.o -o ${binfile}2.sl"
+} else {
+ set additional_flags "additional_flags=-shared"
+ gdb_compile "${binfile}1.o" "${binfile}1.sl" executable [list debug $additional_flags]
+ gdb_compile "${binfile}2.o" "${binfile}2.sl" executable [list debug $additional_flags]
+}
+#cd ..
+
+# Start with a fresh gdb
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+# This program manually loads and unloads SOM shared libraries, via calls
+# to shl_load and shl_unload.
+#
+if ![runto_main] then { fail "catch load/unload tests suppressed" }
+
+# Verify that we complain if the user tells us to catch something we
+# don't understand.
+#
+send_gdb "catch a_cold\n"
+gdb_expect {
+ -re "Unknown event kind specified for catch.*$gdb_prompt $"\
+ {pass "bogus catch kind is disallowed"}
+ -re "$gdb_prompt $"\
+ {fail "bogus catch kind is disallowed"}
+ timeout {fail "(timeout) bogus catch kind is disallowed"}
+}
+
+# Verify that we can set a generic catchpoint on shlib loads. I.e., that
+# we can catch any shlib load, without specifying the name.
+#
+send_gdb "catch load\n"
+gdb_expect {
+ -re "Catchpoint \[0-9\]* .load <any library>.*$gdb_prompt $"\
+ {pass "set generic catch load"}
+ -re "$gdb_prompt $"\
+ {fail "set generic catch load"}
+ timeout {fail "(timeout) set generic catch load"}
+}
+
+send_gdb "continue\n"
+gdb_expect {
+ -re "Catchpoint \[0-9\] .loaded gdb.base/solib1.sl.*$gdb_prompt $"\
+ {pass "caught generic solib load"}
+ -re "$gdb_prompt $"\
+ {fail "caught generic solib load"}
+ timeout {fail "(timeout) caught generic solib load"}
+}
+
+# Set a breakpoint on the line following the shl_load call, and
+# continue.
+#
+# ??rehrauer: It appears that we can't just say "finish" from here;
+# GDB is getting confused by the dld's presense on the stack.
+#
+send_gdb "break 27\n"
+gdb_expect {
+ -re "Breakpoint \[0-9\]* at.*$gdb_prompt $"\
+ {pass "set break after shl_load"}
+ -re "$gdb_prompt $"\
+ {fail "set break after shl_load"}
+ timeout {fail "(timeout) set break after shl_load"}
+}
+
+send_gdb "continue\n"
+gdb_expect {
+ -re "Breakpoint \[0-9\]*, main .. at .*solib.c:27.*$gdb_prompt $"\
+ {pass "continue after generic catch load"}
+ -re "$gdb_prompt $"\
+ {fail "continue after generic catch load"}
+ timeout {fail "(timeout) continue after generic catch load"}
+}
+
+# Step over the call to shl_findsym.
+#
+# ??rehrauer: In theory, since the call to shl_load asked for
+# immediate binding of the shlib's symbols, and since the
+# shlib's symbols should have been auto-loaded, we ought to
+# be able to set a breakpoint on solib_main now. However,
+# that seems not to be the case. Dunno why for sure; perhaps
+# the breakpoint wants to be set on an import stub in the
+# main program for solib_main? There wouldn't be one, in
+# this case...
+#
+send_gdb "next\n"
+gdb_expect {
+ -re "$gdb_prompt $"\
+ {pass "step over shl_findsym"}
+ timeout {fail "(timeout) step over shl_findsym"}
+}
+
+# Verify that we can catch an unload of any library.
+#
+send_gdb "catch unload\n"
+gdb_expect {
+ -re "Catchpoint \[0-9\]* .unload <any library>.*$gdb_prompt $"\
+ {pass "set generic catch unload"}
+ -re "$gdb_prompt $"\
+ {fail "set generic catch unload"}
+ timeout {fail "(timeout) set generic catch load"}
+}
+
+send_gdb "continue\n"
+gdb_expect {
+ -re "Catchpoint \[0-9\] .unloaded gdb.base/solib1.sl.*$gdb_prompt $"\
+ {pass "caught generic solib unload"}
+ -re "$gdb_prompt $"\
+ {fail "caught generic solib unload"}
+ timeout {fail "(timeout) caught generic solib unload"}
+}
+
+# Verify that we can catch a load of a specific library. (Delete
+# all the other catchpoints first, so that the generic catchpoints
+# we've previously set don't trigger.)
+#
+send_gdb "delete\n"
+gdb_expect {
+ -re "Delete all breakpoints.*y or n.*"\
+ {send_gdb "y\n"
+ gdb_expect {
+ -re "$gdb_prompt $"\
+ {pass "delete all catchpoints"}
+ timeout {fail "(timeout) delete all catchpoints"}
+ }
+ }
+ -re "$gdb_prompt $"\
+ {fail "delete all catchpoints"}
+ timeout {fail "(timeout) delete all catchpoints"}
+}
+
+send_gdb "catch load gdb.base/solib2.sl\n"
+gdb_expect {
+ -re "Catchpoint \[0-9\]* .load gdb.base/solib2.sl.*$gdb_prompt $"\
+ {pass "set specific catch load"}
+ -re "$gdb_prompt $"\
+ {fail "set specific catch load"}
+ timeout {fail "(timeout) set specific catch load"}
+}
+
+send_gdb "continue\n"
+gdb_expect {
+ -re "Catchpoint \[0-9\] .loaded gdb.base/solib2.sl.*$gdb_prompt $"\
+ {pass "caught specific solib load"}
+ -re "$gdb_prompt $"\
+ {fail "caught specific solib load"}
+ timeout {fail "(timeout) caught specific solib load"}
+}
+
+# Verify that we can catch an unload of a specific library.
+#
+send_gdb "catch unload gdb.base/solib2.sl\n"
+gdb_expect {
+ -re "Catchpoint \[0-9\]* .unload gdb.base/solib2.sl.*$gdb_prompt $"\
+ {pass "set specific catch unload"}
+ -re "$gdb_prompt $"\
+ {fail "set specific catch unload"}
+ timeout {fail "(timeout) set specific catch unload"}
+}
+
+send_gdb "continue\n"
+gdb_expect {
+ -re "Catchpoint \[0-9\] .unloaded gdb.base/solib2.sl.*$gdb_prompt $"\
+ {pass "caught specific solib unload"}
+ -re "$gdb_prompt $"\
+ {fail "caught specific solib unload"}
+ timeout {fail "(timeout) caught specific solib unload"}
+}
+
+# Verify that we can set a catchpoint on a specific library that
+# happens not to be loaded by the program. And, that this catchpoint
+# won't trigger inappropriately when other shlibs are loaded.
+#
+send_gdb "break 55\n"
+gdb_expect {
+ -re "Breakpoint \[0-9\]* at.*$gdb_prompt $"\
+ {pass "set break on shl_unload"}
+ -re "$gdb_prompt $"\
+ {fail "set break on shl_unload"}
+ timeout {fail "(timeout) set break on shl_unload"}
+}
+
+send_gdb "break 58\n"
+gdb_expect {
+ -re "Breakpoint \[0-9\]* at.*$gdb_prompt $"\
+ {pass "set break after shl_unload"}
+ -re "$gdb_prompt $"\
+ {fail "set break after shl_unload"}
+ timeout {fail "(timeout) set break after shl_unload"}
+}
+
+send_gdb "catch load foobar.sl\n"
+gdb_expect {
+ -re "Catchpoint \[0-9\]* .load foobar.sl.*$gdb_prompt $"\
+ {pass "set specific catch load for nonloaded shlib"}
+ -re "$gdb_prompt $"\
+ {fail "set specific catch load for nonloaded shlib"}
+ timeout {fail "(timeout) set specific catch load for nonloaded shlib"}
+}
+
+send_gdb "catch unload foobar.sl\n"
+gdb_expect {
+ -re "Catchpoint \[0-9\]* .unload foobar.sl.*$gdb_prompt $"\
+ {pass "set specific catch unload for nonloaded shlib"}
+ -re "$gdb_prompt $"\
+ {fail "set specific catch unload for nonloaded shlib"}
+ timeout {fail "(timeout) set specific catch unload for nonloaded shlib"}
+}
+
+send_gdb "continue\n"
+gdb_expect {
+ -re "Breakpoint \[0-9\]*.*$gdb_prompt $"\
+ {pass "specific catch load doesn't trigger inappropriately"}
+ -re "$gdb_prompt $"\
+ {fail "specific catch load doesn't trigger inappropriately"}
+ timeout {fail "(timeout) specific catch load doesn't trigger inappropriately"}
+}
+
+send_gdb "continue\n"
+gdb_expect {
+ -re "Breakpoint \[0-9\]*.*$gdb_prompt $"\
+ {pass "specific catch unload doesn't trigger inappropriately"}
+ -re "$gdb_prompt $"\
+ {fail "specific catch unload doesn't trigger inappropriately"}
+ timeout {fail "(timeout) specific catch unload doesn't trigger inappropriately"}
+}
+
+# ??rehrauer: There ought to be testpoints here that verify that
+# load/unload catchpoints can use conditionals, can be temporary,
+# self-disabling, etc etc.
+#
+
+gdb_exit
+return 0
diff --git a/gdb/testsuite/gdb.base/solib1.c b/gdb/testsuite/gdb.base/solib1.c
new file mode 100644
index 00000000000..eecf02438b4
--- /dev/null
+++ b/gdb/testsuite/gdb.base/solib1.c
@@ -0,0 +1,9 @@
+/* This program is intended to be built as an HP-UX SOM shared
+ library, for use by the solib.exp testcase. It simply returns
+ the square of its integer argument.
+ */
+int solib_main (arg)
+ int arg;
+{
+ return arg*arg;
+}
diff --git a/gdb/testsuite/gdb.base/solib2.c b/gdb/testsuite/gdb.base/solib2.c
new file mode 100644
index 00000000000..2cd451321bd
--- /dev/null
+++ b/gdb/testsuite/gdb.base/solib2.c
@@ -0,0 +1,9 @@
+/* This program is intended to be built as an HP-UX SOM shared
+ library, for use by the solib.exp testcase. It simply returns
+ the cube of its integer argument.
+ */
+int solib_main (arg)
+ int arg;
+{
+ return arg*arg*arg;
+}
diff --git a/gdb/testsuite/gdb.base/sparc-aout.u b/gdb/testsuite/gdb.base/sparc-aout.u
new file mode 100644
index 00000000000..8b4eef915c3
--- /dev/null
+++ b/gdb/testsuite/gdb.base/sparc-aout.u
@@ -0,0 +1,732 @@
+begin 777 sparc-aout
+M@0,!"P ( " #YP " @ "\$" T .@0)(#H$25
+M*B "E *@!)0"0 H7 0U"+@H , C" &((@) 0* 0! 0 "@$
+M ! @$ 0 $ -6<(Z @0 ( P$ ! @$ 0 )WCOV@O (KA7B
+M*!$ B0$B(,0 2Y(0( "L$ (D@.@7$ $N4$" @@*(@(!* $\!
+MPA.@7H"@80L2@ !+ 0 .@#H&#" Z!DX@.@:*0% &2!( 1+P "*X5XDB0
+M$" E! @!1<@ "6$N "F! %D #2:$" IA ") " !32 Z!DE! @!Q<@
+M "6$N 2F! %D "N:$ 4+P "*X5XG01 (D!(B&T ".2$" JA
+M",(#H&B D ! H "R\ BN%>)(D 3 $I(0 !&4$" '%R )82X!*8$ 5
+M0 %YH0( #" Z!PH 3 >8CH'SJ(Z" [".@A , C" &((PB.@B , !#"
+M &"@PB.@C , B"$&!DPB.@D) 0( &?Q DA @?(''X B!Z $( !H(0
+M( 40@ $@A @1Q" *"$" #D= @ J 0! @</@" $ "0$" "D@7@
+M!-0%P ""$" $D= @ ) 0('^"$" !D= @ 0 O=7-R+VQI8B]L9"YS;P O
+M9&5V+WIE<F\ &6-R=# Z(&YO("]U<W(O;&EB+VQD+G-O"@
+M F8W)T,#H@+W5S<B]L:6(O;&0N<V\@;6%P<&EN9R!F86EL=7)E"@
+M !1C<G0P.B!N;R O9&5V+WIE<F\* "=X[^0L! @ #" &!Q^ (@>@
+M )WCOY"P$" ,( 8''X B!Z G>._D+ 0( P@ !@<?@"('H "=X[^0
+ML! @ #" &!Q^ (@>@ )WCOY"P$" ,( 8''X B!Z G>._D+ 0( P
+M@ !@<?@"('H "=X[^0L! @ #" &!Q^ (@>@ )WCOY"P$" ,( 8''
+MX B!Z G>._D+ 0( P@ !@<?@"('H "=X[^0L! @ #" &!Q^ (@>@
+M )WCOY"P$" ,( 8''X B!Z G>._D+ 0( P@ !@<?@"('H
+MG>._D!$ C! B. ,( 8''X B!Z G>._D!$ !#!&B"H,( 8''X B!
+MZ 0L@ )WCOWA #D 0 !$ !# *B,0$0 $)(0( '2*B)8$0 $)(0
+M( +2*B%X$0 $)(0( /2,B$P$0 $)(0( 32,B$($0 $)(0( 72,B'@$0
+M$)(0( ;2(B'($0 $)(0( ?2(B&@$0 $)(0( C2(B$ $0 $)(0( G2(B,(
+M$0 $)(0( K2(B)($0 $)(0( O2(B%@$0 $!, C4 F.TU"(A*!$ ! 3
+M 0U!I@L-0Z(8@1 0$P $-0*8Q#4*B&P$0 $!, !#4"F)8U"HAF!$
+M ! 3 0U IA>-0J(.@1 0$P $-0283#4,B)H$0 $!, !#4$F$(U#(B
+M,!$ ! 3 0U!)AX-0R(5@1 0$P $-0"8<C4(B% $0 $!, !#4 F&@
+MU"(A.!$ ! 3 0U )A -0B(B@1 0$P $-0"8PC4(B&H$0 $!, !#4
+M F)(U"(AD!$ ! 3 0U )A8-0B(. 1 0$P $-0"82C4(B)@$0 $!,
+M !#4&F&(U#HA$!$ ! 5 0DA*C$-(B(/@1 0%0 $)(2HEC2(B#8$0
+M$!4 !"2$J%XTB(AP!$ ! 5 0DA*A,-(B(7 1 0%0 $)(2H0C2(B%0
+M$0 $!4 !"2$J'@TB(C !$ ! 5 0DA*AR-(B(E 1 0%0 $)(2H:#2
+M(B(@$0 $!4 !"2$J$ TB(A2!$ ! 5 0DA*C"-(B(/ 1 0%0 $)(2
+MHDC2(B#0$0 $!4 !"2$J%@TB(AN!$ ! 5 0DA*A*-(B(6@1 0%0
+M$)(2H8C2(B'8$0 $)(0( +2(B#($0 $)(0( +2(B(X$0 $)(0( '2(B'0
+M$0 $)(0( '2(B'H$0 $!, !#4 F) U"(B<!$ ! 3 0U!)A(-0R(8"!
+MQ^ (@>@ )WCOY 1 0U (C(("BO_\2@ -DA(C(- "8 2 HB H "900
+M( "6 F $DA @ )("8 30 D +@*(@ !*___V4 J !DI* 2 H1 0HA(C
+M(*$J8 +0! 1G\( * $/_R I" -+___= $ !&!Q^ (@>@ )WCOY 1 0
+MT@(C'("B8 "@ )H!(C'- $ "?P@ H 0@!- $ " HB $K__^P$ 1
+M )D!(BB$ !E62$" @<?@"('H "=X[^0$P $- "8+R HB $H !) 0
+M( %____GT")@O(''X B!Z 0&P 26____Q 0'@ F6____
+MM 0(0 66____K 0) $V6____3 4 6 2@
+M & H 7 ! !D ) 50 T A (@ "T
+M G 1_____\ -@ #_____ $$ !@
+M #X " %0 P R *@ K ,P "0 U
+M!P "0 ! ( , : " #@ + , X <
+M #P !L 0 )0 !$ = $@ !X 3 'P !0
+M Y %0 "( 6 *P !< !& & ", 9 ,0
+M !H G &P "8 < * !T J '@ "D ?
+M/P " !! (0 "P C +P "4 N )@ H
+M "D [ + #8 M -P "X T +P #T
+M P .@ #$ !/ ,@ S 0@ #0 -0
+M $4 W / #@ ! .0 Z #L !4
+M/ %( ] 0P #X !$ /P $D ! 2 $(
+M 0P !$ 30 $4 !* 1@ $P !' 2P $@
+M !0 20 $X !+ 40 $P !3 30 !.
+M $\ 4 !1 %( 4P !0 '
+MC ,[@ '!P &X0 0,@ ."0 %S 0R@ 3!0 %#@ (" 9
+M 0 #8@ E 0 &X@ L!0 #?@ ([@ R!P %<@ 0*
+M [!P '.0 0 !% 0 #H !+!0 \P (QP !>!0 'KP
+M(P@ !J"0 'SP 0,@ !S!0 "@P (O0 "*"0 &] 0- "A"0 #
+M^@ 0-@ "X"0 '3P 0. #/"0 $:0 0.@ #F"0 "K@ 0/ #V
+M"0 (4@ 0/@ $&"0 &@ 00 $6"0 3 00@ $F"0 N0 01
+M $V"0 'Q@ 02 $_"0 &R 02@ %("0 'F@ 03 %1!0 $DP
+M(U@ %E!0 ';P (J0 %Y"0 " P 03@ &-!0 SP (T0 &:!0 #
+MJP (I &G"0 &W0 04 &T!0 $I@ )TP &\"0 (A 04@ '4
+M"0 &% 05 'L"0 %(P 05@ ($"0 $V0 06 (5"0 "]@ 06@
+M (F"0 &)@ 07 (W"0 $9@ 07@ )("0 '( 08 )2"0 %:P
+M08@ )<!0 $Q0 (S )Q!0 $=P (N *&"0 I0 09 *;"0 &
+M70 09@ *P!0 %)P (X0 *^!0 %C0 (LP +,"0 (1 0: +:
+M"0 !NP 0:@ +H"0 '<P 0; +V"0 'P@ 0;@ ,/"0 $R 0<
+M ,H"0 '\ 0<@ ,O"0 "^ 0= ,Z"0 '1 0=@ -,"0 !V@
+M0> ->"0 $G@ 0>@ -G"0 '*P 0? -R"0 '+ 0@@ -]!0 #
+MF0 (VP .3!0 &=0 (K@ .I"0 #S@ 0B ._"0 !"0 0B@ /5
+M"0 ;0 0C /K"0 "=P 0C@ /W"0 '10 0D /_!0 $G0 (YP
+M 0."0 (80 0D@ 0="0 %^@ 0E 0L"0 '[@ 0E@ 0["0 !S0
+M0F 1*"0 "F0 0F@ 19"0 'A0 0G 1A"0 'K 0P 1["0 '
+MN0 0P@ 2#"0 '1@ 0Q 2+ 0 &= 24!P "F 0, 2F
+M"0 '<0 0Q@ 2U"0 "TP 0R 3$!0 &>0 )P 37!0 &B0 )H@
+M 3J!P %H 0+A?971E>'0 7V5D871A %]E;F0 <W1A<G0 <W1A<G1?9FQO
+M870 7U]E>&ET %]M86EN %]E;G9I<F]N %]?1%E.04U)0P!?97AI= !?=E]S
+M:6=N961?:6YT7V9U;F, 7W9?:6YT7V9U;F, 7W!R:6UA<GD 7W9?=6YS:6=N
+M961?<VAO<G1?9G5N8P!?=E]S:6=N961?;&]N9U]P;VEN=&5R %]V7W-I9VYE
+M9%]C:&%R7W!O:6YT97( 7W9?=6YS:6=N961?;&]N9U]A<G)A>0!?=E]U;G-I
+M9VYE9%]C:&%R7V%R<F%Y %]V7VQO;F=?<&]I;G1E<@!?=E]C:&%R7W!O:6YT
+M97( 7W9?=6YS:6=N961?:6YT %]V7W-I9VYE9%]S:&]R= !?=E]D;W5B;&5?
+M87)R87D 7W9?=6YI;VX 7W9?9FQO870 7W9?<VAO<G0 7W9?<VEG;F5D7VQO
+M;F=?9G5N8P!?=E]S:6=N961?8VAA<E]F=6YC %]V7W-I9VYE9%]I;G1?87)R
+M87D 7W9?;&]N9U]F=6YC %]V7V-H87)?9G5N8P!?=E]I;G1?87)R87D 7U]?
+M;6%I;@!?=E]U;G-I9VYE9%]I;G1?<&]I;G1E<@!?=E]S:6=N961?<VAO<G1?
+M<&]I;G1E<@!?=E]U;G-I9VYE9%]S:&]R=%]A<G)A>0!?=E]U;G-I9VYE9%]L
+M;VYG %]V7V9L;V%T7W!O:6YT97( 7W9?<VAO<G1?<&]I;G1E<@!?=E]U;G-I
+M9VYE9%]C:&%R %]V7W5N:6]N,@!?=E]D;W5B;&4 7W9?=6YS:6=N961?:6YT
+M7V9U;F, 7W9?<VEG;F5D7W-H;W)T7V9U;F, 7W9?<VEG;F5D7VQO;F=?87)R
+M87D 7W9?<VEG;F5D7V-H87)?87)R87D 7W9?9FQO871?9G5N8P!?=E]S:&]R
+M=%]F=6YC %]V7W-I9VYE9%]I;G0 7W9?;&]N9U]A<G)A>0!?=E]C:&%R7V%R
+M<F%Y %]V7W5N<VEG;F5D7VQO;F=?<&]I;G1E<@!?=E]U;G-I9VYE9%]C:&%R
+M7W!O:6YT97( 7W9?:6YT %]S<&]R='-C87( 7W9?9&]U8FQE7W!O:6YT97(
+M7W9?=6YS:6=N961?<VAO<G0 7V-L=6YK97( 7W9?<W1R=6-T,0!?=E]S=')U
+M8W0R %]V7W5N<VEG;F5D7VQO;F=?9G5N8P!?=E]U;G-I9VYE9%]C:&%R7V9U
+M;F, 7W9?<VEG;F5D7VEN=%]P;VEN=&5R %]V7W5N<VEG;F5D7VEN=%]A<G)A
+M>0!?=E]S:6=N961?<VAO<G1?87)R87D 7VYO;G!R:6UA<GD 7W-?;&EN:P!?
+M=E]D;W5B;&5?9G5N8P!?=E]S:6=N961?;&]N9P!?=E]I;G1?<&]I;G1E<@!?
+M=E]S:6=N961?8VAA<@!?=E]F;&]A=%]A<G)A>0!?=E]S:&]R=%]A<G)A>0!?
+M=5]L:6YK %]V7W5N<VEG;F5D7W-H;W)T7W!O:6YT97( 7W9?;&]N9P!?=E]C
+M:&%R %]O;E]E>&ET %]?97AI=%]D=6UM>5]D96-L %]?7T-43U)?3$E35%]?
+M %]?7T143U)?3$E35%]? %]?7V1O7V=L;V)A;%]C=&]R<P!?7U]D;U]G;&]B
+M86Q?9'1O<G, 7U]E>&ET7V1U;6UY7W)E9@ "]U<W(O;&]C86PO;&EB
+M+V=C8RUL:6(O<W5N-"\R+C$O.B]U<W(O;&]C86PO;&EB+P 3
+MD( 0 & &,
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M # ! # 0"0 3
+M@ $T@ $!< ! 8 !W@ >H *6 5 .2 !0 "
+M / 0 # @<!@ $ "=X[^@?____ $ "=X[^@?___^0$ &=
+MX[^@?___]@$ *=X[^@?___\P$ , $!I
+M ! P
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M 0& ! X$ @( !4$ BD !T$
+M BD "QD BD %5D BD %V
+M '^ )& +B -&
+M .^ 0V 2> 4F
+M 6R 8F :6 ;>
+M <J >* >Z
+M HB !$ !Y BD !$ !Y BE !$ !Y B
+MG QHD BD !$ !Z BI !$ !Z BJ !$ !Z
+M BL RDD BI !$ ![ BN !$ ![ BO !$
+M ![ BQ T D BN !$ !] BS !$ !] BT
+M !$ !] BV UDD BS !$ !^ BX !$ !^ B
+MY !$ !^ B[ VDD BX !$ !_ B] !$ !_
+M B^ !$ !_ C X D B] !$ "! C" !$
+M "! C# !$ "! C% YDD C" !$ "" C'
+M !$ "" C( !$ "" C* Z<D C' !$ "# C
+M, !$ "# C- !$ "# C/ [PD C, !$ "%
+M C1 !$ "% C2 !$ "% C4 ],D C1 !$
+M "& C6 !$ "& C7 !$ "& C9 ^(D C6
+M !$ "' C; !$ "' C< !$ "' C> _@D C
+M; !$ ") CA !$ ") CB !$ ") CE !! D
+M CA !$ "* CG !$ "* CH !$ "* CK !"$D
+M CG !#. !)^ !-^
+M!0: !2* !4" !5R
+M !6F !$ "R CN !$ "U CQ !$ "V
+M CS !$ "W CV !$ "Y CY !$ "Z C\ !$
+M "[ C_ !$ "] D" !$ "^ D% !$ "_ D(
+M !$ #! D+ !$ #" D. !$ ## D1 !$ #% D
+M4 !$ #& D8 !$ #) D< !$ #* D@ !$ #+
+M DD !$ #- DH !$ #. DL !$ #/ DP !$
+M #1 DT !$ #2 DX !$ #3 D\ !$ #5 E
+M !$ #6 E$ !$ #7 E( !$ #9 E, !$ #: E
+M0 !$ #< E4 !$ #= E8 !$ #> E< !$ #@
+M E@ !$ #A ED !$ #B EH !$ #D EL !$
+M #E EP !$ #F ET !$ #H EX !$ #I E\
+M !$ #J F !$ #L F$ !$ #M F( !$ #O F
+M, !$ #P F/ !$ #Q F2 !$ #R F5 !$ #T
+M F8 !$ #V F< !$ #W F@ !$ #W F@ !98D
+M CN !9X@ !:@@ !;H@
+M!<X@ !=D@ !>L@ !?\@
+M !@@@ !A@@ !BH@ !C0@
+M !D4@ !E@@ !F0@ !G$@
+M !HP@ !J\@ !M0@
+M!O @ !PD@ !RX@ !T@@
+M !U\@ !X(@ !YT@ ![4@
+M !]D@ !_8@ "!0@ ""H@
+M "$@@ "&@@ "'\@
+M")H@ "+H@ ",\@ ".@@
+M "08@ "1P@ "38@ "54@
+M "6T@ "88@ "90@ "B\@
+M "CL@ "LX@ "MD@
+M"N0@ "P@@ "Q<@ "S4@
+M "T,$ FB "TP$ FB "UL& ! O "VID
+M FB "WUD FB "XF "ZN "[V
+M "^2 "_V #!N
+M##F #%. #'6 #)B
+M #+6 #-& #.. #/:
+M #0Z #1J #6N #7B
+M #8* #8V #;:
+M#=R #?$D FB #@<@ #AXD G
+M #C0D G3 #C\$ G> #D<$ G> #E9D
+M G> #FED G> #G6 #I> #JF
+M #M" #NF #P>
+M#R6 #S^ #V& #X2
+M #Z& #[V #\^ #^*
+M #_J $ : $%> $&2
+M $&Z $'F $**
+M$,B $-T@ $/$@ $0X@
+M $2 $ G> $21D G> !$ /__ G> $2L% >,
+M SN $3(' ;A ! R $3D) 7, !#* $3X% 4. @( $40%
+M -^ CN $4H' 5R ! H $5,% #S C' $68% >O C"
+M$7() ?/ ! R $7L% *# B] $9() ;T ! T $:D) /Z !
+MV $< ) =/ ! X $=<) 1I ! Z $>X) *N ! \ $?X) A2
+M ! ^ $@X) : !! $AX) !, !!" $BX) "Y !!$ $CX)
+M ?& !!( $D<) ;( !!* $E ) >: !!, $ED% 23 C6
+M$FT% =O BI $H$) (# !!. $I4% #/ C1 $J(% .K B
+MD $J\) ;= !!0 $KP% 2F G3 $L0) B$ !!2 $MP) 84
+M !!4 $O0) 4C !!6 $PP) 39 !!8 $QT) +V !!: $RX)
+M 8F !!< $S\) 1F !!> $U ) <@ !!@ $UH) 5K !!B
+M$V0% 3% C, $WD% 1W BX $XX) "E !!D $Z,) 9= !!
+MF $[@% 4G CA $\8% 6- BS $]0) A$ !!H $^() &[
+M !!J $_ ) =S !!L $_X) ?" !!N %!<) 3( !!P %# )
+M ?P !!R %#<) +X !!T %$() =$ !!V %%0) ': !!X
+M%&8) 2> !!Z %&\) <K !!\ %'H) <L !"" %(4% .9 C
+M; %)L% 9U BN %+$) /. !"( %,<) $) !"* %-T) !M
+M !", %/,) )W !". %/\) =% !"0 %0<% 2= CG %18)
+M AA !"2 %24) 7Z !"4 %30) ?N !"6 %4,) '- !"8
+M%5() *9 !": %6$) >% !"< %6D) >L !# %8,) >Y !#
+M" %8L) =& !#$ %9,' *8 ! P %:4) =Q !#& %;0) +3
+M !#( %<,% 9Y G %=8% :) FB %>D' 6@ ! N %?I?
+M7T193D%-24, 8W)T,"YO &=D8FUE+F\ 9V-C,E]C;VUP:6QE9"X +VAO;64O
+M9VYU+V=D8B]W;W)K+VYE=R]D979O+V=D8G1E<W0O=#$P+P!G9&)M92YC &EN
+M=#IT,3UR,3LM,C$T-S0X,S8T.#LR,30W-#@S-C0W.P!C:&%R.G0R/7(R.S [
+M,3(W.P!L;VYG(&EN=#IT,SUR,3LM,C$T-S0X,S8T.#LR,30W-#@S-C0W.P!U
+M;G-I9VYE9"!I;G0Z=#0]<C$[,#LM,3L ;&]N9R!U;G-I9VYE9"!I;G0Z=#4]
+M<C$[,#LM,3L <VAO<G0@:6YT.G0V/7(Q.RTS,C<V.#LS,C<V-SL ;&]N9R!L
+M;VYG(&EN=#IT-SUR,3LP.RTQ.P!S:&]R="!U;G-I9VYE9"!I;G0Z=#@]<C$[
+M,#LV-34S-3L ;&]N9R!L;VYG('5N<VEG;F5D(&EN=#IT.3UR,3LP.RTQ.P!S
+M:6=N960@8VAA<CIT,3 ]<C$[+3$R.#LQ,C<[ '5N<VEG;F5D(&-H87(Z=#$Q
+M/7(Q.S [,C4U.P!F;&]A=#IT,3(]<C$[-#LP.P!D;W5B;&4Z=#$S/7(Q.S@[
+M,#L ;&]N9R!D;W5B;&4Z=#$T/7(Q.S@[,#L =F]I9#IT,34],34 =%]S=')U
+M8W0Z5#$V/7,R-'9?8VAA<E]M96UB97(Z,BPP+#@[=E]S:&]R=%]M96UB97(Z
+M-BPQ-BPQ-CMV7VEN=%]M96UB97(Z,2PS,BPS,CMV7VQO;F=?;65M8F5R.C,L
+M-C0L,S([=E]F;&]A=%]M96UB97(Z,3(L.38L,S([=E]D;W5B;&5?;65M8F5R
+M.C$S+#$R."PV-#L[ '1?=6YI;VXZ5#$W/74X=E]C:&%R7VUE;6)E<CHR+# L
+M.#MV7W-H;W)T7VUE;6)E<CHV+# L,38[=E]I;G1?;65M8F5R.C$L,"PS,CMV
+M7VQO;F=?;65M8F5R.C,L,"PS,CMV7V9L;V%T7VUE;6)E<CHQ,BPP+#,R.W9?
+M9&]U8FQE7VUE;6)E<CHQ,RPP+#8T.SL =E]C:&%R7V9U;F,Z1C( =E]S:6=N
+M961?8VAA<E]F=6YC.D8Q, !V7W5N<VEG;F5D7V-H87)?9G5N8SI&,3$ =E]S
+M:&]R=%]F=6YC.D8V '9?<VEG;F5D7W-H;W)T7V9U;F,Z1C8 =E]U;G-I9VYE
+M9%]S:&]R=%]F=6YC.D8X '9?:6YT7V9U;F,Z1C$ =E]S:6=N961?:6YT7V9U
+M;F,Z1C$ =E]U;G-I9VYE9%]I;G1?9G5N8SI&- !V7VQO;F=?9G5N8SI&,P!V
+M7W-I9VYE9%]L;VYG7V9U;F,Z1C, =E]U;G-I9VYE9%]L;VYG7V9U;F,Z1C4
+M=E]F;&]A=%]F=6YC.D8Q,@!V7V1O=6)L95]F=6YC.D8Q,P!L:6YK.E0Q.#US
+M,34R;F5X=#HQ.3TJ,3@L,"PS,CML:6YK9G5N8SHR,#TJ,C$]9C$Y+#,R+#,R
+M.W-T=69F.C(R/6%R,3LP.S [,C,]87(Q.S [,3LR-#UA<C$[,#LR.S$V+#8T
+M+#$Q-3([.P!T=5]L:6YK.E0R-3UU,30T;F5X=#HQ.2PP+#,R.VQI;FMF=6YC
+M.C(P+# L,S([<W1U9F8Z,C(L,"PQ,34R.SL 8V]L;W)S.E0R-CUE>65L;&]W
+M.C L<'5R<&QE.C$L<&EN:SHR+#L 8V%R<SI4,C<]96)M=SHP+'!O<G-C:&4Z
+M,2P[ &)O;VQE86XZ=#(X/65&04Q313HP+%12544Z,2P[ &)V86QS.E0R.3UE
+M9F%L<V4Z,"QT<G5E.C$L.P!B;V]L96%N,CIT,CD ;6ES;W)D97)E9#I4,S ]
+M971W;SHR+&]N93HQ+'IE<F\Z,"QT:')E93HS+#L ;6%I;CI&,0!V7V-H87(Z
+M1S( =E]S:6=N961?8VAA<CI',3 =E]U;G-I9VYE9%]C:&%R.D<Q,0!V7W-H
+M;W)T.D<V '9?<VEG;F5D7W-H;W)T.D<V '9?=6YS:6=N961?<VAO<G0Z1S@
+M=E]I;G0Z1S$ =E]S:6=N961?:6YT.D<Q '9?=6YS:6=N961?:6YT.D<T '9?
+M;&]N9SI',P!V7W-I9VYE9%]L;VYG.D<S '9?=6YS:6=N961?;&]N9SI'-0!V
+M7V9L;V%T.D<Q,@!V7V1O=6)L93I',3, =E]C:&%R7V%R<F%Y.D<S,3UA<C$[
+M,#LQ.S( =E]S:6=N961?8VAA<E]A<G)A>3I',S(]87(Q.S [,3LQ, !V7W5N
+M<VEG;F5D7V-H87)?87)R87DZ1S,S/6%R,3LP.S$[,3$ =E]S:&]R=%]A<G)A
+M>3I',S0]87(Q.S [,3LV '9?<VEG;F5D7W-H;W)T7V%R<F%Y.D<S- !V7W5N
+M<VEG;F5D7W-H;W)T7V%R<F%Y.D<S-3UA<C$[,#LQ.S@ =E]I;G1?87)R87DZ
+M1S,V/6%R,3LP.S$[,0!V7W-I9VYE9%]I;G1?87)R87DZ1S,V '9?=6YS:6=N
+M961?:6YT7V%R<F%Y.D<S-SUA<C$[,#LQ.S0 =E]L;VYG7V%R<F%Y.D<S.#UA
+M<C$[,#LQ.S, =E]S:6=N961?;&]N9U]A<G)A>3I',S@ =E]U;G-I9VYE9%]L
+M;VYG7V%R<F%Y.D<S.3UA<C$[,#LQ.S4 =E]F;&]A=%]A<G)A>3I'-# ]87(Q
+M.S [,3LQ,@!V7V1O=6)L95]A<G)A>3I'-#$]87(Q.S [,3LQ,P!V7V-H87)?
+M<&]I;G1E<CI'-#(]*C( =E]S:6=N961?8VAA<E]P;VEN=&5R.D<T,STJ,3
+M=E]U;G-I9VYE9%]C:&%R7W!O:6YT97(Z1S0T/2HQ,0!V7W-H;W)T7W!O:6YT
+M97(Z1S0U/2HV '9?<VEG;F5D7W-H;W)T7W!O:6YT97(Z1S0U '9?=6YS:6=N
+M961?<VAO<G1?<&]I;G1E<CI'-#8]*C@ =E]I;G1?<&]I;G1E<CI'-#<]*C$
+M=E]S:6=N961?:6YT7W!O:6YT97(Z1S0W '9?=6YS:6=N961?:6YT7W!O:6YT
+M97(Z1S0X/2HT '9?;&]N9U]P;VEN=&5R.D<T.3TJ,P!V7W-I9VYE9%]L;VYG
+M7W!O:6YT97(Z1S0Y '9?=6YS:6=N961?;&]N9U]P;VEN=&5R.D<U,#TJ-0!V
+M7V9L;V%T7W!O:6YT97(Z1S4Q/2HQ,@!V7V1O=6)L95]P;VEN=&5R.D<U,CTJ
+M,3, =E]S=')U8W0Q.D<Q-@!V7W-T<G5C=#(Z1S4S/7,R-'9?8VAA<E]M96UB
+M97(Z,BPP+#@[=E]S:&]R=%]M96UB97(Z-BPQ-BPQ-CMV7VEN=%]M96UB97(Z
+M,2PS,BPS,CMV7VQO;F=?;65M8F5R.C,L-C0L,S([=E]F;&]A=%]M96UB97(Z
+M,3(L.38L,S([=E]D;W5B;&5?;65M8F5R.C$S+#$R."PV-#L[ '9?=6YI;VXZ
+M1S$W '9?=6YI;VXR.D<U-#UU.'9?8VAA<E]M96UB97(Z,BPP+#@[=E]S:&]R
+M=%]M96UB97(Z-BPP+#$V.W9?:6YT7VUE;6)E<CHQ+# L,S([=E]L;VYG7VUE
+M;6)E<CHS+# L,S([=E]F;&]A=%]M96UB97(Z,3(L,"PS,CMV7V1O=6)L95]M
+M96UB97(Z,3,L,"PV-#L[ '-?;&EN:SI',3D =5]L:6YK.D<R-0!P<FEM87)Y
+M.D<U-3UE<F5D.C L9W)E96XZ,2QB;'5E.C(L.P!N;VYP<FEM87)Y.D<R-@!C
+M;'5N:V5R.D<U-CUE8VAE=GDZ,"QF;W)D.C$L.P!S<&]R='-C87(Z1S(W %]?
+M;6%I;BYO &=C8S)?8V]M<&EL960N %]I;FET:6%L:7IE9"XP "]G;G4O9V-C
+M+V=C8S(O<W)C+P N+VQI8F=C8S(N8P!I;G0Z=#$]<C$[+3(Q-#<T.#,V-#@[
+M,C$T-S0X,S8T-SL 8VAA<CIT,CUR,CLP.S$R-SL ;&]N9R!I;G0Z=#,]<C$[
+M+3(Q-#<T.#,V-#@[,C$T-S0X,S8T-SL =6YS:6=N960@:6YT.G0T/7(Q.S [
+M+3$[ &QO;F<@=6YS:6=N960@:6YT.G0U/7(Q.S [+3$[ '-H;W)T(&EN=#IT
+M-CUR,3LM,S(W-C@[,S(W-C<[ &QO;F<@;&]N9R!I;G0Z=#<]<C$[,#LM,3L
+M<VAO<G0@=6YS:6=N960@:6YT.G0X/7(Q.S [-C4U,S4[ &QO;F<@;&]N9R!U
+M;G-I9VYE9"!I;G0Z=#D]<C$[,#LM,3L <VEG;F5D(&-H87(Z=#$P/7(Q.RTQ
+M,C@[,3(W.P!U;G-I9VYE9"!C:&%R.G0Q,3UR,3LP.S(U-3L 9FQO870Z=#$R
+M/7(Q.S0[,#L 9&]U8FQE.G0Q,SUR,3LX.S [ &QO;F<@9&]U8FQE.G0Q-#UR
+M,3LX.S [ '9O:60Z=#$U/3$U ')E9U]C;&%S<SI4,38]94Y/7U)%1U,Z,"Q'
+M14Y%4D%,7U)%1U,Z,2Q&4%]214=3.C(L04Q,7U)%1U,Z,RQ,24U?4D5'7T-,
+M05-315,Z-"P[ '!T<F1I9F9?=#IT,0!S:7IE7W0Z=#$ =V-H87)?=#IT. !L
+M;VYG;&]N9SI4,3<]<SAH:6=H.C,L,"PS,CML;W<Z,RPS,BPS,CL[ &QO;F=?
+M;&]N9SIT,3@]=3AS.C$W+# L-C0[;&PZ-RPP+#8T.SL 9G5N8U]P='(Z=#$Y
+M/2HR,#UF,34 7U]D;U]G;&]B86Q?9'1O<G,Z1C$U %]E>&ET7V1U;6UY7W)E
+M9CI',C$]*C$ 7U]D;U]G;&]B86Q?8W1O<G,Z1C$U %]?;6%I;CI&,34 7V5X
+M:70N;P!G8V,R7V-O;7!I;&5D+@ O9VYU+V=C8R]G8V,R+W-R8R\ +B]L:6)G
+M8V,R+F, :6YT.G0Q/7(Q.RTR,30W-#@S-C0X.S(Q-#<T.#,V-#<[ &-H87(Z
+M=#(]<C([,#LQ,C<[ &QO;F<@:6YT.G0S/7(Q.RTR,30W-#@S-C0X.S(Q-#<T
+M.#,V-#<[ '5N<VEG;F5D(&EN=#IT-#UR,3LP.RTQ.P!L;VYG('5N<VEG;F5D
+M(&EN=#IT-3UR,3LP.RTQ.P!S:&]R="!I;G0Z=#8]<C$[+3,R-S8X.S,R-S8W
+M.P!L;VYG(&QO;F<@:6YT.G0W/7(Q.S [+3$[ '-H;W)T('5N<VEG;F5D(&EN
+M=#IT.#UR,3LP.S8U-3,U.P!L;VYG(&QO;F<@=6YS:6=N960@:6YT.G0Y/7(Q
+M.S [+3$[ '-I9VYE9"!C:&%R.G0Q,#UR,3LM,3(X.S$R-SL =6YS:6=N960@
+M8VAA<CIT,3$]<C$[,#LR-34[ &9L;V%T.G0Q,CUR,3LT.S [ &1O=6)L93IT
+M,3,]<C$[.#LP.P!L;VYG(&1O=6)L93IT,30]<C$[.#LP.P!V;VED.G0Q-3TQ
+M-0!R96=?8VQA<W,Z5#$V/65.3U]214=3.C L1T5.15)!3%]214=3.C$L1E!?
+M4D5'4SHR+$%,3%]214=3.C,L3$E-7U)%1U]#3$%34T53.C0L.P!P=')D:69F
+M7W0Z=#$ <VEZ95]T.G0Q '=C:&%R7W0Z=#@ ;&]N9VQO;F<Z5#$W/7,X:&EG
+M:#HS+# L,S([;&]W.C,L,S(L,S([.P!L;VYG7VQO;F<Z=#$X/74X<SHQ-RPP
+M+#8T.VQL.C<L,"PV-#L[ &9U;F-?<'1R.G0Q.3TJ,C ]9C$U %]E>&ET7V1U
+M;6UY7V1E8VPZ1S$ 7U]#5$]27TQ)4U1?7SI',C$]87(Q.S [,3LQ.0!?7T14
+M3U)?3$E35%]?.D<R,0 M;&< ;&EB9RYS %]E=&5X= !?961A=&$ 7V5N9 !S
+M=&%R= !?;6%I;@!?96YV:7)O;@!?=E]S:6=N961?:6YT7V9U;F, 7W9?:6YT
+M7V9U;F, 7W!R:6UA<GD 7W9?=6YS:6=N961?<VAO<G1?9G5N8P!?=E]S:6=N
+M961?;&]N9U]P;VEN=&5R %]V7W-I9VYE9%]C:&%R7W!O:6YT97( 7W9?=6YS
+M:6=N961?;&]N9U]A<G)A>0!?=E]U;G-I9VYE9%]C:&%R7V%R<F%Y %]V7VQO
+M;F=?<&]I;G1E<@!?=E]C:&%R7W!O:6YT97( 7W9?=6YS:6=N961?:6YT %]V
+M7W-I9VYE9%]S:&]R= !?=E]D;W5B;&5?87)R87D 7W9?=6YI;VX 7W9?9FQO
+M870 7W9?<VAO<G0 7W9?<VEG;F5D7VQO;F=?9G5N8P!?=E]S:6=N961?8VAA
+M<E]F=6YC %]V7W-I9VYE9%]I;G1?87)R87D 7W9?;&]N9U]F=6YC %]V7V-H
+M87)?9G5N8P!?=E]I;G1?87)R87D 7U]?;6%I;@!?=E]U;G-I9VYE9%]I;G1?
+M<&]I;G1E<@!?=E]S:6=N961?<VAO<G1?<&]I;G1E<@!?=E]U;G-I9VYE9%]S
+M:&]R=%]A<G)A>0!?=E]U;G-I9VYE9%]L;VYG %]V7V9L;V%T7W!O:6YT97(
+M7W9?<VAO<G1?<&]I;G1E<@!?=E]U;G-I9VYE9%]C:&%R %]V7W5N:6]N,@!?
+M=E]D;W5B;&4 7W9?=6YS:6=N961?:6YT7V9U;F, 7W9?<VEG;F5D7W-H;W)T
+M7V9U;F, 7W9?<VEG;F5D7VQO;F=?87)R87D 7W9?<VEG;F5D7V-H87)?87)R
+M87D 7W9?9FQO871?9G5N8P!?=E]S:&]R=%]F=6YC %]V7W-I9VYE9%]I;G0
+M7W9?;&]N9U]A<G)A>0!?=E]C:&%R7V%R<F%Y %]V7W5N<VEG;F5D7VQO;F=?
+M<&]I;G1E<@!?=E]U;G-I9VYE9%]C:&%R7W!O:6YT97( 7W9?:6YT %]S<&]R
+M='-C87( 7W9?9&]U8FQE7W!O:6YT97( 7W9?=6YS:6=N961?<VAO<G0 7V-L
+M=6YK97( 7W9?<W1R=6-T,0!?=E]S=')U8W0R %]V7W5N<VEG;F5D7VQO;F=?
+M9G5N8P!?=E]U;G-I9VYE9%]C:&%R7V9U;F, 7W9?<VEG;F5D7VEN=%]P;VEN
+M=&5R %]V7W5N<VEG;F5D7VEN=%]A<G)A>0!?=E]S:6=N961?<VAO<G1?87)R
+M87D 7VYO;G!R:6UA<GD 7W-?;&EN:P!?=E]D;W5B;&5?9G5N8P!?=E]S:6=N
+M961?;&]N9P!?=E]I;G1?<&]I;G1E<@!?=E]S:6=N961?8VAA<@!?=E]F;&]A
+M=%]A<G)A>0!?=E]S:&]R=%]A<G)A>0!?=5]L:6YK %]V7W5N<VEG;F5D7W-H
+M;W)T7W!O:6YT97( 7W9?;&]N9P!?=E]C:&%R %]?97AI=%]D=6UM>5]D96-L
+M %]?7T-43U)?3$E35%]? %]?7T143U)?3$E35%]? %]?7V1O7V=L;V)A;%]C
+M=&]R<P!?7U]D;U]G;&]B86Q?9'1O<G, 7U]E>&ET7V1U;6UY7W)E9@
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+M
+(
+
+end
diff --git a/gdb/testsuite/gdb.base/sparc-elf.u b/gdb/testsuite/gdb.base/sparc-elf.u
new file mode 100644
index 00000000000..9320c0f0f3d
--- /dev/null
+++ b/gdb/testsuite/gdb.base/sparc-elf.u
@@ -0,0 +1,336 @@
+begin 777 sparc-elf
+M?T5,1@$" 0 " ( ! $/% #0 #;0 T "
+M!0 H !< $P 8 T $ - "@ H 4 P
+M -0 !$ ! ! - ! #0 3
+M= $W0 % $ $ !.H (3J #L "M < 0
+M @ % P A0, (@ !P O=7-R+VQI8B]L9"YS
+M;RXQ %, !H 2P .@ &( W 5
+M 4P %\ !D 4 $ !* 5P #8
+M20 #, M /P %X "4 < 0P !1
+M * !" "0 !; , #$ R 1P $4
+M !. 8 C +@ %@ /0 (
+M $0 !< 2 + !/ !6
+M &< !: 60 &8 .P %T
+M +P !E !A
+M
+M
+M (0
+M *@ "D
+M 9 'P
+M "8 ; !T !H ^ 00 "L U
+M 7 "( $P
+M $8 X 4@ #0 !- #P
+M G %4 !@ > Y 8P
+M $ U # ! ! .@ P
+M @ 0/< , , $*7 # $ !#M@
+M P !0 0[D , 8 $/" # ' !#Q0
+M P " 1-P , D $3@ # * "
+M$Z@ P "P A0 , P (4# # -
+M "%)@ P #@ , \ # 0
+M P $0 , !( #
+M 3 P % , !4
+M # 6 0 "%)@ ($0 #@ D 1-P !( D / (4
+MH 01 . %@ "%*@ "0$0 #@ !T A4X !!$ X T
+M (5/ 01 . .@ "%4 !$0 #@ $@ A5$ !!$ X
+M !6 (52 @1 . 7P "%5 ($0 #@ '4 A58 "!$
+M X "* (58 01 . GP "%60 $$0 #@ *< A5H
+M!!$ X "T $09 !02 ( R0 !#X@ 4$@ " -4 A5P
+M "!$ X #> (5> 01 . Z "%7P "$0 #@ /X
+M A5^ A$ X $/ (5@ @1 . !(P !#P@ $@ !P
+M 2D A6( A$ X $X $/Q !02 ( !10 "%8P $$0
+M#@ 4T A60 A$ X %: (5F !@1 . !9 "%; 8
+M$0 #@ 6X A7( !!$ X %U (5S 01 . !A "%=
+M $$0 #@ 9P 1!0 %!( @ &O (5U 01 . !Q@ "
+M%=@ "$0 #@ <X 0_L %!( @ 'D (4# 1 /_Q !
+M[0 !$*@ +($@ " ?( 1. !!$ H '_ $0D !@2 (
+M "#0 "%=H "$0 #@ B$ 1 4 %!( @ (S (5W 01
+M . "0P "%> $$0 #@ E( A7H $!$ X )A $/%
+M '02 ( ": "%)0 $0#_\0 F\ 1 H %!( @ *# (5
+M^ @1 . "CP "%@ $$0 #@ I< 1!X &!( @ *D
+M $0/ !02 ( "L "%@0 ($0 #@ L, A90 !"$ X
+M ++ (6# 01 . "W "%A $$0 #@ O( 0_8 %!(
+M @ ,& (6% 01 . #%0 "%A@ $$0 #@ RT 0^P
+M%!( @ -" (67 1 /_Q #1P "%AP $$0 #@ UX A8@
+M !!$ X -L (6) $1 . #? "%B@ $$0 #@ XP
+M A8L !!$ X .< $3J 1 /_Q #HP "%C ($0 #@
+M [$ A8X !!$ X /& (4 1 /_Q #W !$ 4$@
+M" ^< 0^< %!( @ /Z (6/ 01 . $" "%D !
+M$0 #@ ! \ A9$ !!$ X 0: (62 @1 . $)P "$^0
+M 0$@ !"P A/8 6!( 0S (3\ @2 $.0 "
+M%E $$0 #@ !$( A94 !!$ X 1; (66 01 . '9?
+M=6YI;VX 7V9I;FD <U]L:6YK '5?;&EN:P!V7W-I9VYE9%]S:&]R=%]P;VEN
+M=&5R '9?:6YT '9?<VEG;F5D7V-H87( =E]I;G1?<&]I;G1E<@!V7V1O=6)L
+M90!V7W5N<VEG;F5D7VQO;F=?87)R87D =E]U;G-I9VYE9%]I;G1?87)R87D
+M=E]S:6=N961?:6YT7W!O:6YT97( 8VQU;FME<@!V7W-I9VYE9%]I;G0 =E]U
+M;G-I9VYE9%]L;VYG7V9U;F, =E]C:&%R7V9U;F, =E]U;FEO;C( <W!O<G1S
+M8V%R '9?=6YS:6=N961?8VAA<E]A<G)A>0!V7W5N<VEG;F5D7W-H;W)T '9?
+M<VEG;F5D7VQO;F=?87)R87D 7VEN:70 =E]S:6=N961?<VAO<G0 =E]S:&]R
+M=%]F=6YC '9?9FQO870 =E]C:&%R7V%R<F%Y '9?<W1R=6-T,0!V7W-T<G5C
+M=#( =E]L;VYG '9?;&]N9U]P;VEN=&5R '9?=6YS:6=N961?;&]N9U]P;VEN
+M=&5R '9?<VEG;F5D7VQO;F=?9G5N8P!V7W5N<VEG;F5D7VEN=%]P;VEN=&5R
+M '9?<VAO<G0 =E]U;G-I9VYE9%]S:&]R=%]F=6YC %]$64Y!34E# &UA:6X
+M7VQI8E]V97)S:6]N '9?9&]U8FQE7V9U;F, =E]S:6=N961?8VAA<E]A<G)A
+M>0!V7W-I9VYE9%]I;G1?9G5N8P!V7W5N<VEG;F5D7VQO;F< =E]U;G-I9VYE
+M9%]I;G0 =E]D;W5B;&5?87)R87D 7W-T87)T %]E9&%T80!V7W5N<VEG;F5D
+M7VEN=%]F=6YC '9?:6YT7V%R<F%Y '!R:6UA<GD =E]F;&]A=%]F=6YC '9?
+M;&]N9U]F=6YC '9?<VEG;F5D7VEN=%]A<G)A>0!E;G9I<F]N '9?9&]U8FQE
+M7W!O:6YT97( =E]S:6=N961?8VAA<E]P;VEN=&5R '9?<VEG;F5D7W-H;W)T
+M7V9U;F, =E]C:&%R7W!O:6YT97( =E]U;G-I9VYE9%]C:&%R7W!O:6YT97(
+M=E]U;G-I9VYE9%]C:&%R7V9U;F, 7V5N9 !V7W5N<VEG;F5D7W-H;W)T7V%R
+M<F%Y '9?<VEG;F5D7VQO;F< =E]U;G-I9VYE9%]C:&%R '9?<VAO<G1?<&]I
+M;G1E<@!V7V9L;V%T7W!O:6YT97( 7V5T97AT '9?9FQO871?87)R87D =E]S
+M:6=N961?<VAO<G1?87)R87D 7T=,3T)!3%]/1D93151?5$%"3$5? '9?:6YT
+M7V9U;F, =E]S:6=N961?8VAA<E]F=6YC '9?<VAO<G1?87)R87D =E]C:&%R
+M &YO;G!R:6UA<GD =E]L;VYG7V%R<F%Y &5X:70 871E>&ET %]E>&ET %]E
+M;G9I<F]N '9?=6YS:6=N961?<VAO<G1?<&]I;G1E<@!V7W-I9VYE9%]L;VYG
+M7W!O:6YT97( ;&EB8RYS;RXQ A90 !E$P A/8 !C%0
+M A/D !B%0 A/P !D%0 "=X[^@@<?@"('H "\$" X .@0*(#
+MH$2<(Z @@) 0* 20$ !0 !!*@$ 1 !$D!(C<$ 028! ?___
+M\ $ "0$ 0DA $94L( *4 J $E 1 "A< (66$N)0U"+ $ $X!
+M0 !!&P$ ! $$< 0 )WCOY"P$" ,( 8''X B!Z G>._D+ 0( P
+M@ !@<?@"('H "=X[^0L! @ #" &!Q^ (@>@ )WCOY"P$" ,( 8''
+MX B!Z G>._D+ 0( P@ !@<?@"('H "=X[^0L! @ #" &!Q^ (@>@
+M )WCOY"P$" ,( 8''X B!Z G>._D+ 0( P@ !@<?@"('H "=X[^0
+ML! @ #" &!Q^ (@>@ )WCOY"P$" ,( 8''X B!Z G>._D+ 0( P
+M@ !@<?@"('H "=X[^0L! @ #" &!Q^ (@>@ )WCOY 1 !$P0(CB#"
+M &!Q^ (@>@ )WCOY 1 !$P1HCD#" &!Q^ (@>@ )WCOY 1 "%P"HB
+M0!$ (62$" !TBHA0!$ (62$" "TBHB)!$ (62$" #TC(AV!$ (62$" $
+MTC(AB!$ (62$" %TC(A?A$ (62$" &TB(A/!$ (62$" 'TB(A:!$ (62
+M$" (TB(AX!$ (62$" )TB(AR!$ (62$" *TB(B(!$ (62$" +TB(AW!$
+M (43 !$U )CF-0B(8P1 "%$P 1-0:8Z#4.B%($0 A1, (74"F) U"HA
+MD!$ (43 "%U IA0-0J(=H1 "%$P A=0*8B34*B%\$0 A1, (74$F'8
+MU#(B/!$ (43 "%U!)AB-0R(C@1 "%$P A=0287[4,B(<$0 A1, (74
+M F$\U"(A^!$ (43 "%U )A:-0B(@01 "%$P A=0"8>#4(B%8$0 A1,
+M (74 F'(U"(B2!$ (43 "%U )B(-0B(8 1 "%$P A=0"8=S4(B%0$0
+MA1, (74 F&,U"(B,!$ (43 "%U!IA2-0Z(>@1 "%%0 A9(2HD#2(B(4
+M$0 A14 (62$J% TB(B$!$ (45 "%DA*B)-(B(A@1 "%%0 A9(2H=C2
+M(B(H$0 A14 (62$J&(TB(A.!$ (45 "%DA*A?M(B(E01 "%%0 A9(2
+MH3S2(B%$$0 A14 (62$J%HTB(A8!$ (45 "%DA*AX-(B(=01 "%%0
+MA9(2H<C2(B',$0 A14 (62$J(@TB(B6!$ (45 "%DA*AW-(B(= 1 "%
+M%0 A9(2H8S2(B(L$0 A14 (62$J%(TB(B#!$ (62$" "TB(B !$ (62
+M$" "TB(B1!$ (62$" !TB(A>!$ (62$" !TB(A9!$ (43 "%U )@H-0B
+M(*@1 "%$P A=028)C4,B%P@<?@"('H "=X[^@@<?@"('H
+M 0 0L@ ! :0
+M , # P
+MO__S 0 , #PPO__P 0 , $@PO__M 0 $ A0,
+M ! $<0 P 0\( #0 !$W $ $ Z 4 0I<
+M!@ ! ]P * $>P L 0 %0 # (3J ( D
+M % < 7 $.Y < 0[8 " # ) #
+M ! $ /_Q !
+M -0 P 0 0#H , ( $#W # #
+M !"EP P ! 0[8 , 4 $.Y # &
+M !#P@ P !P 0\4 , @ $3< #
+M ) !$X P "@ A.H , L (4
+M # , "% P P #0 A28 , X
+M # / P $ , !$
+M # 2 P $P , !0
+M # 5 P %@ < 0
+M__$ . $ /_Q &@ ! #_\0 "(
+M 0 __$ I (4F @1 . ,0 !$W $@ "0 #< A2@
+M !!$ X ^ (4J ) 1 . 10 "%3@ $$0 #@ %P
+M A4\ !!$ X !B (50 $1 . < "%40 $$0 #@
+M 'X A5( "!$ X "' (54 @1 . G0 "%5@ ($0
+M#@ +( A5@ !!$ X #' (59 01 . SP "%6@ $
+M$0 #@ -P 1!D %!( @ #Q $/B !02 ( _0 "%7
+M ($0 #@ 08 A5X !!$ X $0 (5? (1 . !)@ "
+M%7X "$0 #@ 3< A6 "!$ X %+ $/" 2 ' !
+M40 "%8@ "$0 #@ 6 0_$ %!( @ %M (5C 01 .
+M !=0 "%9 "$0 #@ 8( A68 &!$ X &, (5L !@1
+M . !E@ "%<@ $$0 #@ 9T A7, !!$ X &L (5T
+M 01 . !Q !$% 4$@ " =< A74 !!$ X 'N (5
+MV (1 . !]@ !#^P 4$@ " @P A0, !$ __$ (5
+M $0J L@2 ( "&@ !$X $$0 "@ B< 1"0 &!( @
+M (U (5V@ (1 . "20 !$!0 4$@ " EL A7< !!$
+M X )K (5X 01 . ">@ "%>@ 0$0 #@ HD 0\4
+M=!( @ *0 (4E 1 /_Q "EP !$"@ 4$@ " JL A7X
+M "!$ X *W (6 01 . "OP !$'@ 8$@ " LP
+M 1 \ %!( @ +8 (6! @1 . "ZP "%E $(0 #@
+M O, A8, !!$ X ,$ (6$ 01 . #&@ !#]@ 4$@
+M" RX A84 !!$ X ,] (6& 01 . #50 !#[ 4
+M$@ " VH A9< !$ __$ -O (6' 01 . #A@ "%B
+M $$0 #@ Y0 A8D 1$ X .D (6* 01 . #M "
+M%BP $$0 #@ \0 1.H !$ __$ /+ (6, @1 . #
+MV0 "%C@ $$0 #@ ^X A0 !$ __$ 0$ $0 !02 (
+M $#P !#YP 4$@ " !"( A8\ !!$ X 0P (60 $1
+M . $-P "%D0 $$0 #@ !$( A9( "!$ X 1/ (3Y
+M ! 2 $5 "$]@ !8$@ !%L A/P "!( 1A (6
+M4 01 . $:@ "%E0 $$0 #@ !(, A98 !!$ X 9V1B
+M;64 8W)T:2YS '9A;'5E<RU882YC &=D8FUE+F, 8W)T;BYS '9?=6YI;VX
+M7V9I;FD <U]L:6YK '5?;&EN:P!V7W-I9VYE9%]S:&]R=%]P;VEN=&5R '9?
+M:6YT '9?<VEG;F5D7V-H87( =E]I;G1?<&]I;G1E<@!V7V1O=6)L90!V7W5N
+M<VEG;F5D7VQO;F=?87)R87D =E]U;G-I9VYE9%]I;G1?87)R87D =E]S:6=N
+M961?:6YT7W!O:6YT97( 8VQU;FME<@!V7W-I9VYE9%]I;G0 =E]U;G-I9VYE
+M9%]L;VYG7V9U;F, =E]C:&%R7V9U;F, =E]U;FEO;C( <W!O<G1S8V%R '9?
+M=6YS:6=N961?8VAA<E]A<G)A>0!V7W5N<VEG;F5D7W-H;W)T '9?<VEG;F5D
+M7VQO;F=?87)R87D 7VEN:70 =E]S:6=N961?<VAO<G0 =E]S:&]R=%]F=6YC
+M '9?9FQO870 =E]C:&%R7V%R<F%Y '9?<W1R=6-T,0!V7W-T<G5C=#( =E]L
+M;VYG '9?;&]N9U]P;VEN=&5R '9?=6YS:6=N961?;&]N9U]P;VEN=&5R '9?
+M<VEG;F5D7VQO;F=?9G5N8P!V7W5N<VEG;F5D7VEN=%]P;VEN=&5R '9?<VAO
+M<G0 =E]U;G-I9VYE9%]S:&]R=%]F=6YC %]$64Y!34E# &UA:6X 7VQI8E]V
+M97)S:6]N '9?9&]U8FQE7V9U;F, =E]S:6=N961?8VAA<E]A<G)A>0!V7W-I
+M9VYE9%]I;G1?9G5N8P!V7W5N<VEG;F5D7VQO;F< =E]U;G-I9VYE9%]I;G0
+M=E]D;W5B;&5?87)R87D 7W-T87)T %]E9&%T80!V7W5N<VEG;F5D7VEN=%]F
+M=6YC '9?:6YT7V%R<F%Y '!R:6UA<GD =E]F;&]A=%]F=6YC '9?;&]N9U]F
+M=6YC '9?<VEG;F5D7VEN=%]A<G)A>0!E;G9I<F]N '9?9&]U8FQE7W!O:6YT
+M97( =E]S:6=N961?8VAA<E]P;VEN=&5R '9?<VEG;F5D7W-H;W)T7V9U;F,
+M=E]C:&%R7W!O:6YT97( =E]U;G-I9VYE9%]C:&%R7W!O:6YT97( =E]U;G-I
+M9VYE9%]C:&%R7V9U;F, 7V5N9 !V7W5N<VEG;F5D7W-H;W)T7V%R<F%Y '9?
+M<VEG;F5D7VQO;F< =E]U;G-I9VYE9%]C:&%R '9?<VAO<G1?<&]I;G1E<@!V
+M7V9L;V%T7W!O:6YT97( 7V5T97AT '9?9FQO871?87)R87D =E]S:6=N961?
+M<VAO<G1?87)R87D 7T=,3T)!3%]/1D93151?5$%"3$5? '9?:6YT7V9U;F,
+M=E]S:6=N961?8VAA<E]F=6YC '9?<VAO<G1?87)R87D =E]C:&%R &YO;G!R
+M:6UA<GD =E]L;VYG7V%R<F%Y &5X:70 871E>&ET %]E>&ET %]E;G9I<F]N
+M '9?=6YS:6=N961?<VAO<G1?<&]I;G1E<@!V7W-I9VYE9%]L;VYG7W!O:6YT
+M97( '9A;'5E<RU882YC "]D:79E+W)E;&5A<V4O8BUS>7-I9FEX+W5S<B]S
+M<F,O;&EB+VQI8F,O '!O<G0O9V5N+W9A;'5E<RU882YC 6'0@.R!6/3(N
+M, !M86EN %]L:6)?=F5R<VEO;@ O=&UP "]U<W(O8V-S+VQI8B]V86QU97,M
+M6&$N;P 9V1B;64N8P O=&UP+P!G9&)M92YC &=C8S)?8V]M<&EL960N &EN
+M=#IT,3UR,3LM,C$T-S0X,S8T.#LR,30W-#@S-C0W.P!C:&%R.G0R/7(R.S [
+M,3(W.P!L;VYG(&EN=#IT,SUR,3LM,C$T-S0X,S8T.#LR,30W-#@S-C0W.P!U
+M;G-I9VYE9"!I;G0Z=#0]<C$[,#LM,3L ;&]N9R!U;G-I9VYE9"!I;G0Z=#4]
+M<C$[,#LM,3L <VAO<G0@:6YT.G0V/7(Q.RTS,C<V.#LS,C<V-SL ;&]N9R!L
+M;VYG(&EN=#IT-SUR,3LP.RTQ.P!S:&]R="!U;G-I9VYE9"!I;G0Z=#@]<C$[
+M,#LV-34S-3L ;&]N9R!L;VYG('5N<VEG;F5D(&EN=#IT.3UR,3LP.RTQ.P!S
+M:6=N960@8VAA<CIT,3 ]<C$[+3$R.#LQ,C<[ '5N<VEG;F5D(&-H87(Z=#$Q
+M/7(Q.S [,C4U.P!F;&]A=#IT,3(]<C$[-#LP.P!D;W5B;&4Z=#$S/7(Q.S@[
+M,#L ;&]N9R!D;W5B;&4Z=#$T/7(Q.S@[,#L =F]I9#IT,34],34 =%]S=')U
+M8W0Z5#$V/7,R-'9?8VAA<E]M96UB97(Z,BPP+#@[=E]S:&]R=%]M96UB97(Z
+M-BPQ-BPQ-CMV7VEN=%]M96UB97(Z,2PS,BPS,CMV7VQO;F=?;65M8F5R.C,L
+M-C0L,S([=E]F;&]A=%]M96UB97(Z,3(L.38L,S([=E]D;W5B;&5?;65M8F5R
+M.C$S+#$R."PV-#L[ '1?=6YI;VXZ5#$W/74X=E]C:&%R7VUE;6)E<CHR+# L
+M.#MV7W-H;W)T7VUE;6)E<CHV+# L,38[=E]I;G1?;65M8F5R.C$L,"PS,CMV
+M7VQO;F=?;65M8F5R.C,L,"PS,CMV7V9L;V%T7VUE;6)E<CHQ,BPP+#,R.W9?
+M9&]U8FQE7VUE;6)E<CHQ,RPP+#8T.SL =E]C:&%R7V9U;F,Z1C( =E]S:6=N
+M961?8VAA<E]F=6YC.D8Q, !V7W5N<VEG;F5D7V-H87)?9G5N8SI&,3$ =E]S
+M:&]R=%]F=6YC.D8V '9?<VEG;F5D7W-H;W)T7V9U;F,Z1C8 =E]U;G-I9VYE
+M9%]S:&]R=%]F=6YC.D8X '9?:6YT7V9U;F,Z1C$ =E]S:6=N961?:6YT7V9U
+M;F,Z1C$ =E]U;G-I9VYE9%]I;G1?9G5N8SI&- !V7VQO;F=?9G5N8SI&,P!V
+M7W-I9VYE9%]L;VYG7V9U;F,Z1C, =E]U;G-I9VYE9%]L;VYG7V9U;F,Z1C4
+M=E]F;&]A=%]F=6YC.D8Q,@!V7V1O=6)L95]F=6YC.D8Q,P!L:6YK.E0Q.#US
+M,34R;F5X=#HQ.3TJ,3@L,"PS,CML:6YK9G5N8SHR,#TJ,C$]9C$Y+#,R+#,R
+M.W-T=69F.C(R/6%R,3LP.S [,C,]87(Q.S [,3LR-#UA<C$[,#LR.S$V+#8T
+M+#$Q-3([.P!T=5]L:6YK.E0R-3UU,30T;F5X=#HQ.2PP+#,R.VQI;FMF=6YC
+M.C(P+# L,S([<W1U9F8Z,C(L,"PQ,34R.SL 8V]L;W)S.E0R-CUE>65L;&]W
+M.C L<'5R<&QE.C$L<&EN:SHR+#L 8V%R<SI4,C<]96)M=SHP+'!O<G-C:&4Z
+M,2P[ &)O;VQE86XZ=#(X/65&04Q313HP+%12544Z,2P[ &)V86QS.E0R.3UE
+M9F%L<V4Z,"QT<G5E.C$L.P!B;V]L96%N,CIT,CD ;6ES;W)D97)E9#I4,S ]
+M971W;SHR+&]N93HQ+'IE<F\Z,"QT:')E93HS+#L ;6%I;CI&,0!V7V-H87(Z
+M1S( =E]S:6=N961?8VAA<CI',3 =E]U;G-I9VYE9%]C:&%R.D<Q,0!V7W-H
+M;W)T.D<V '9?<VEG;F5D7W-H;W)T.D<V '9?=6YS:6=N961?<VAO<G0Z1S@
+M=E]I;G0Z1S$ =E]S:6=N961?:6YT.D<Q '9?=6YS:6=N961?:6YT.D<T '9?
+M;&]N9SI',P!V7W-I9VYE9%]L;VYG.D<S '9?=6YS:6=N961?;&]N9SI'-0!V
+M7V9L;V%T.D<Q,@!V7V1O=6)L93I',3, =E]C:&%R7V%R<F%Y.D<S,3UA<C$[
+M,#LQ.S( =E]S:6=N961?8VAA<E]A<G)A>3I',S(]87(Q.S [,3LQ, !V7W5N
+M<VEG;F5D7V-H87)?87)R87DZ1S,S/6%R,3LP.S$[,3$ =E]S:&]R=%]A<G)A
+M>3I',S0]87(Q.S [,3LV '9?<VEG;F5D7W-H;W)T7V%R<F%Y.D<S- !V7W5N
+M<VEG;F5D7W-H;W)T7V%R<F%Y.D<S-3UA<C$[,#LQ.S@ =E]I;G1?87)R87DZ
+M1S,V/6%R,3LP.S$[,0!V7W-I9VYE9%]I;G1?87)R87DZ1S,V '9?=6YS:6=N
+M961?:6YT7V%R<F%Y.D<S-SUA<C$[,#LQ.S0 =E]L;VYG7V%R<F%Y.D<S.#UA
+M<C$[,#LQ.S, =E]S:6=N961?;&]N9U]A<G)A>3I',S@ =E]U;G-I9VYE9%]L
+M;VYG7V%R<F%Y.D<S.3UA<C$[,#LQ.S4 =E]F;&]A=%]A<G)A>3I'-# ]87(Q
+M.S [,3LQ,@!V7V1O=6)L95]A<G)A>3I'-#$]87(Q.S [,3LQ,P!V7V-H87)?
+M<&]I;G1E<CI'-#(]*C( =E]S:6=N961?8VAA<E]P;VEN=&5R.D<T,STJ,3
+M=E]U;G-I9VYE9%]C:&%R7W!O:6YT97(Z1S0T/2HQ,0!V7W-H;W)T7W!O:6YT
+M97(Z1S0U/2HV '9?<VEG;F5D7W-H;W)T7W!O:6YT97(Z1S0U '9?=6YS:6=N
+M961?<VAO<G1?<&]I;G1E<CI'-#8]*C@ =E]I;G1?<&]I;G1E<CI'-#<]*C$
+M=E]S:6=N961?:6YT7W!O:6YT97(Z1S0W '9?=6YS:6=N961?:6YT7W!O:6YT
+M97(Z1S0X/2HT '9?;&]N9U]P;VEN=&5R.D<T.3TJ,P!V7W-I9VYE9%]L;VYG
+M7W!O:6YT97(Z1S0Y '9?=6YS:6=N961?;&]N9U]P;VEN=&5R.D<U,#TJ-0!V
+M7V9L;V%T7W!O:6YT97(Z1S4Q/2HQ,@!V7V1O=6)L95]P;VEN=&5R.D<U,CTJ
+M,3, =E]S=')U8W0Q.D<Q-@!V7W-T<G5C=#(Z1S4S/7,R-'9?8VAA<E]M96UB
+M97(Z,BPP+#@[=E]S:&]R=%]M96UB97(Z-BPQ-BPQ-CMV7VEN=%]M96UB97(Z
+M,2PS,BPS,CMV7VQO;F=?;65M8F5R.C,L-C0L,S([=E]F;&]A=%]M96UB97(Z
+M,3(L.38L,S([=E]D;W5B;&5?;65M8F5R.C$S+#$R."PV-#L[ '9?=6YI;VXZ
+M1S$W '9?=6YI;VXR.D<U-#UU.'9?8VAA<E]M96UB97(Z,BPP+#@[=E]S:&]R
+M=%]M96UB97(Z-BPP+#$V.W9?:6YT7VUE;6)E<CHQ+# L,S([=E]L;VYG7VUE
+M;6)E<CHS+# L,S([=E]F;&]A=%]M96UB97(Z,3(L,"PS,CMV7V1O=6)L95]M
+M96UB97(Z,3,L,"PV-#L[ '-?;&EN:SI',3D =5]L:6YK.D<R-0!P<FEM87)Y
+M.D<U-3UE<F5D.C L9W)E96XZ,2QB;'5E.C(L.P!N;VYP<FEM87)Y.D<R-@!C
+M;'5N:V5R.D<U-CUE8VAE=GDZ,"QF;W)D.C$L.P!S<&]R='-C87(Z1S(W N
+M:6YT97)P "YH87-H "YD>6YS>6T +F1Y;G-T<@ N<F5L82YB<W, +G)E;&$N
+M<&QT "YI;FET "YT97AT "YF:6YI "YR;V1A=&$ +G!L= N9V]T "YD>6YA
+M;6EC "YB<W, +G-Y;71A8@ N<W1R=&%B "YS=&%B+FEN9&5X<W1R "YS=&%B
+M<W1R "YS:'-T<G1A8@ N8V]M;65N= N<W1A8BYI;F1E> N<W1A8@ 87,Z
+M($,@1&5V96QO<&UE;G0@4V5T(" H0T13*2!34$%20V]M<&EL97)S(#(N," Q
+M."!-87D@,3DY,@H &%S.B!#($1E=F5L;W!M96YT(%-E=" @*$-$4RD@4U!!
+M4D-O;7!I;&5R<R R+C @,3@@36%Y(#$Y.3(* ! *",I4W5N3U,@-2XP(&9C
+M<RX@($IU;F4@,3DY,@ 87,Z($,@1&5V96QO<&UE;G0@4V5T(" H0T13*2!3
+M4$%20V]M<&EL97)S(#(N," Q."!-87D@,3DY,@H 1T-#.B H1TY5*2!C>6=N
+M=7,M,BXP+C( &%S.B!#($1E=F5L;W!M96YT(%-E=" @*$-$4RD@4U!!4D-O
+M;7!I;&5R<R R+C @,3@@36%Y(#$Y.3(* &QD.B H4T=5*2!3=6Y/4R]35E(T
+M("A,2RTQ+C I $ ' B0 UD #=D #
+M &LX ' X $X\ *A=6!@ %DJ
+M %X@ $ "\ +# ED $/B
+M ]D $/B !<\ ": $B
+M %J (& )J +B
+M -: /" 1* 36
+M 5* 6Z 8"
+M 9. :N ;> E&
+M N,D $/B !$ !Y !$ !Y ! !$ !Y
+M # O(D $/G !$ !Z !$ !Z ! !$
+M !Z # PDD $/L !$ ![ !$ ![ !
+M !$ ![ # R(D $/Q !$ !] !$ !]
+M! !$ !] # S(D $/V !$ !^ !$ !^
+M ! !$ !^ # TDD $/[ !$ !_ !$
+M !_ ! !$ !_ # V(D $0 !$ "!
+M !$ "! ! !$ "! # W D $0% !$ ""
+M !$ "" ! !$ "" # X4D $0* !$ "#
+M !$ "# ! !$ "# # YPD $0/ !$
+M "% !$ "% ! !$ "% # ZLD $04
+M !$ "& !$ "& ! !$ "& # \$D $0
+M9 !$ "' !$ "' ! !$ "' # ]DD
+M $0> !$ ") !$ ") ! !$ ") $ ^HD
+M $0D !$ "* !$ "* ! !$ "* $
+M _R !&B !*B !,^
+M !.N !0F !26 !3*
+M !5\D $0J !$ "R !$ "U ! !$
+M "V # !$ "W & !$ "Y ) !$ "Z ,
+M !$ "[ / !$ "] 2 !$ "^ 5 !$ "_
+M8 !$ #! ; !$ #" > !$ ## A !$ #%
+M D !$ #& H !$ #) L !$ #* P !$
+M #+ T !$ #- X !$ #. \ !$ #/ !
+M !$ #1 !$ !$ #2 !( !$ #3 !, !$ #5 !
+M0 !$ #6 !4 !$ #7 !8 !$ #9 !< !$ #:
+M !@ !$ #< !D !$ #= !H !$ #> !L !$
+M #@ !P !$ #A !T !$ #B !X !$ #D !\
+M !$ #E " !$ #F "$ !$ #H "( !$ #I "
+M, !$ #J "0 !$ #L "4 !$ #M "8 !$ #O
+M "< !$ #P "? !$ #Q "B !$ #R "E !$
+M #T "H !$ #V "L !$ #W "P !$ #W "P
+M!6<@ !7$@ !8,@ !9<@
+M !:(@ !;0@ !<@@ !=$@
+M !>$@ !?,@ !?T@ !@X@
+M !B$@ !BT@ !CH@
+M!E4@ !G@@ !IT@ !KD@
+M !M(@ !O<@ !Q$@ !R@@
+M !TL@ !V8@ !WX@ !Z(@
+M ![\@ !]T@ !_,@
+M"!$@ "#$@ "$@@ "&,@
+M "(,@ ")@@ "+$@ ",\@
+M ".4@ "/\@ "1X@ "38@
+M "4\@ "5T@ "?@@
+M"@0@ "I<@ "J(@ "JT@
+M "M$@ "N @ "OX@
+M ! 0 (
+M 0#4 U !$ $ "0 4 " $ Z
+M .@ +T P $ ! \ + @ ! ]P /< &
+M@ 0 7 ! ! 7 P ( 0I< *7 !'L
+M $ 'P 0 " $.V #M@ , P X
+M $ # "D $ @ !#N0 [D ) , + !
+M P S 0 8 0\( /" P 0
+M.0 $ & $/% #Q0 1< $ #\ !
+M !@ !$W !-P # ! !% 0 (
+M 1. 3@ "@ @ 30 $ ' (3J
+M$Z@ !8 $ ! %( ! P "% !0
+M# ! 0 !7 !@ , A0, 4# (@ $
+M 0 ( 8 @ # (4F %)@ '$
+M ( &4 " !28 &T ! < !
+M ! !M P ;: !)D $
+M=0 , ( $ ") ! (0 #
+M ""* +# 0 "- P
+M KE@ +( $ EP $
+M+$@ %) ! * ! "V4
+M8 ! P "L 0 M] "-P
+, 0 ,
+
+end
diff --git a/gdb/testsuite/gdb.base/ss.h b/gdb/testsuite/gdb.base/ss.h
new file mode 100644
index 00000000000..2a4c162dcd6
--- /dev/null
+++ b/gdb/testsuite/gdb.base/ss.h
@@ -0,0 +1,4 @@
+struct s {
+ int a;
+ int b;
+};
diff --git a/gdb/testsuite/gdb.base/step-test.c b/gdb/testsuite/gdb.base/step-test.c
new file mode 100644
index 00000000000..7130725400e
--- /dev/null
+++ b/gdb/testsuite/gdb.base/step-test.c
@@ -0,0 +1,58 @@
+/* Test various kinds of stepping.
+*/
+int glob = 0;
+
+int callee() {
+ glob++;
+}
+
+/* A structure which, we hope, will need to be passed using memcpy. */
+struct rhomboidal {
+ int rather_large[100];
+};
+
+void
+large_struct_by_value (struct rhomboidal r)
+{
+ glob += r.rather_large[42]; /* step-test.exp: arrive here 1 */
+}
+
+int main () {
+ int w,x,y,z;
+ int a[10], b[10];
+
+ /* Test "next" and "step" */
+ w = 0;
+ x = 1;
+ y = 2;
+ z = 3;
+ w = w + 2;
+ x = x + 3;
+ y = y + 4;
+ z = z + 5;
+
+ /* Test that "next" goes over a call */
+ callee(); /* OVER */
+
+ /* Test that "step" doesn't */
+ callee(); /* INTO */
+
+ /* Test "stepi" */
+ a[5] = a[3] - a[4];
+ callee(); /* STEPI */
+
+ /* Test "nexti" */
+ callee(); /* NEXTI */
+
+ y = w + z;
+
+ {
+ struct rhomboidal r;
+ memset (r.rather_large, 0, sizeof (r.rather_large));
+ r.rather_large[42] = 10;
+ large_struct_by_value (r); /* step-test.exp: large struct by value */
+ }
+
+ exit (0);
+}
+
diff --git a/gdb/testsuite/gdb.base/step-test.exp b/gdb/testsuite/gdb.base/step-test.exp
new file mode 100644
index 00000000000..415714d81e4
--- /dev/null
+++ b/gdb/testsuite/gdb.base/step-test.exp
@@ -0,0 +1,153 @@
+# Copyright (C) 1997, 1998 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# use this to debug:
+#
+#log_user 1
+
+# step-test.exp -- Expect script to test stepping in gdb
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+set testfile step-test
+set srcfile ${srcdir}/${subdir}/${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+
+remote_exec build "rm -f ${binfile}"
+if { [gdb_compile "${srcfile}" "${binfile}" executable {debug}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+if ![runto_main] then {
+ fail "Can't run to main"
+ return 0
+}
+
+# Vanilla step/next
+#
+gdb_test "next" ".*${decimal}.*x = 1;.*" "next 1"
+gdb_test "step" ".*${decimal}.*y = 2;.*" "step 1"
+
+# With count
+#
+gdb_test "next 2" ".*${decimal}.*w = w.*2;.*" "next 2"
+gdb_test "step 3" ".*${decimal}.*z = z.*5;.*" "step 3"
+gdb_test "next" ".*${decimal}.*callee.*OVER.*" "next 3"
+
+# Step over call
+#
+gdb_test "next" ".*${decimal}.*callee.*INTO.*" "next over"
+
+# Step into call
+#
+gdb_test "step" ".*${decimal}.*glob.*" "step into"
+
+# Step out of call
+#
+# I wonder if this is really portable. Are there any caller-saves
+# platforms, on which `finish' will return you to some kind of pop
+# instruction, which is attributed to the line containing the function
+# call?
+gdb_test "finish" ".*${decimal}.*a.*5.*= a.*3.*" "step out"
+
+### Testing nexti and stepi.
+###
+### test_i NAME COMMAND HERE THERE
+###
+### Send COMMAND to gdb over and over, while the output matches the
+### regexp HERE, followed by the gdb prompt. Pass if the output
+### eventually matches the regexp THERE, followed by the gdb prompt;
+### fail if we have to iterate more than a hundred times, we time out
+### talking to gdb, or we get output which is neither HERE nor THERE. :)
+###
+### Use NAME as the name of the test.
+###
+### The exact regexps used are "$HERE.*$gdb_prompt $"
+### and "$THERE.*$gdb_prompt $"
+###
+proc test_i {name command here there} {
+ global gdb_prompt
+
+ set i 0
+ while 1 {
+ send_gdb "${command}\n"
+ gdb_expect {
+ -re "$here.*$gdb_prompt $" {
+ # Okay, we're still on the same line. Just step again.
+ }
+ -re "$there.*$gdb_prompt $" {
+ # We've reached the next line. Rah.
+ pass "$name"
+ return
+ }
+ -re "$gdb_prompt $" {
+ # We got something else. Fail.
+ fail "$name"
+ return
+ }
+ timeout {
+ fail "$name (timeout)"
+ return
+ }
+ }
+
+ # Have we gone for too many steps without seeing any progress?
+ if {[incr i] >= 100} {
+ fail "$name (no progress after 100 steps)"
+ return
+ }
+ }
+}
+
+test_i "stepi to next line" "stepi" \
+ ".*${decimal}.*a.*5.* = a.*3" \
+ ".*${decimal}.*callee.*STEPI"
+test_i "stepi into function" "stepi" \
+ ".*${decimal}.*callee.*STEPI" \
+ ".*callee \\(\\) at .*step-test\\.c"
+gdb_test "finish" ".*${decimal}.*callee.*NEXTI.*" "stepi: finish call"
+test_i "nexti over function" "nexti" \
+ ".*${decimal}.*callee.*NEXTI" \
+ ".*${decimal}.*y = w \\+ z;"
+
+# On some platforms, if we try to step into a function call that
+# passes a large structure by value, then we actually end up stepping
+# into memcpy, bcopy, or some such --- GCC emits the call to pass the
+# argument. Opinion is bitterly divided about whether this is the
+# right behavior for GDB or not, but we'll catch it here, so folks
+# won't forget about it.
+
+send_gdb "break [gdb_get_line_number "step-test.exp: large struct by value"]\n"
+gdb_test "continue" \
+ ".*Breakpoint ${decimal},.*large_struct_by_value.*" \
+ "run to pass large struct"
+gdb_test "step" \
+ ".*step-test.exp: arrive here 1.*" \
+ "large struct by value"
+
+gdb_test "continue" ".*Program exited normally.*" "run to finish"
+
+return 0
diff --git a/gdb/testsuite/gdb.base/structs2.c b/gdb/testsuite/gdb.base/structs2.c
new file mode 100644
index 00000000000..f9f59e91421
--- /dev/null
+++ b/gdb/testsuite/gdb.base/structs2.c
@@ -0,0 +1,38 @@
+/* pr 13536 */
+
+static void param_reg (register char pr_char,
+ register unsigned char pr_uchar,
+ register short pr_short,
+ register unsigned short pr_ushort);
+
+int bkpt;
+
+int
+main ()
+{
+#ifdef usestubs
+ set_debug_traps ();
+ breakpoint ();
+#endif
+
+ bkpt = 0;
+ param_reg (120, 130, 32000, 33000);
+ param_reg (130, 120, 33000, 32000);
+
+ return 0;
+}
+
+static void dummy () {}
+
+static void
+param_reg(register char pr_char,
+ register unsigned char pr_uchar,
+ register short pr_short,
+ register unsigned short pr_ushort)
+{
+ bkpt = 1;
+ dummy ();
+ pr_char = 1;
+ pr_uchar = pr_short = pr_ushort = 1;
+ dummy ();
+}
diff --git a/gdb/testsuite/gdb.base/structs2.exp b/gdb/testsuite/gdb.base/structs2.exp
new file mode 100644
index 00000000000..14652bef06c
--- /dev/null
+++ b/gdb/testsuite/gdb.base/structs2.exp
@@ -0,0 +1,79 @@
+# Copyright (C) 1998 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+set prms_id 0
+set bug_id 0
+
+set prototypes 1
+set testfile "structs2"
+set srcfile ${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+
+# build the first test case
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } {
+ # built the second test case since we can't use prototypes
+ warning "Prototypes not supported, rebuilding with -DNO_PROTOTYPES"
+ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug additional_flags=-DNO_PROTOTYPES}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+ }
+ set prototypes 0
+}
+
+# Start with a fresh gdb.
+
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+gdb_test "set width 0" "" ""
+
+if { ![runto_main] } then {
+ gdb_suppress_tests
+}
+
+# Ok, we're finally ready to actually do our tests.
+
+set prms_id 13536
+set bug_id 0
+
+gdb_test "f" \
+ ".*bkpt = 0.*" \
+ "structs2 sanity check"
+
+gdb_test "break param_reg" \
+ "Breakpoint .* at .*" \
+ "structs2 breakpoint set"
+
+gdb_test "continue" \
+ ".*pr_char=120.*pr_uchar=130.*pr_short=32000.*pr_ushort=33000.*bkpt = 1.*" \
+ "structs2 continue1"
+
+gdb_test "continue" \
+ ".*pr_char=-126.*pr_uchar=120.*pr_short=-32536.*pr_ushort=32000.*bkpt = 1.*" \
+ "structs2 continue2"
+
+# End of tests.
+
+gdb_stop_suppressing_tests
+
+return 0
diff --git a/gdb/testsuite/gdb.base/term.exp b/gdb/testsuite/gdb.base/term.exp
new file mode 100644
index 00000000000..211a94c1120
--- /dev/null
+++ b/gdb/testsuite/gdb.base/term.exp
@@ -0,0 +1,73 @@
+# Copyright (C) 1988, 1990, 1991, 1992, 1997 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file was written by Rob Savoye. (rob@cygnus.com)
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+# This only works for native, I think.
+if ![isnative] then {
+ continue
+}
+
+gdb_start
+
+#
+# test running programs
+#
+set prms_id 0
+set bug_id 0
+
+set testfile "run"
+set srcfile ${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+delete_breakpoints
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+gdb_test "set print sevenbit-strings" "" "test set print sevenbit-strings"
+gdb_test "set print address off" "" "test set print address off"
+gdb_test "set width 0" "" "test set width 0"
+gdb_test "info terminal" "No saved terminal information.*" "test info terminal"
+gdb_run_cmd 5
+gdb_expect {
+ -re ".*120.*Program exited normally.*$gdb_prompt $" {
+ gdb_test "info terminal" "No saved terminal information.*" "test info terminal #2"
+ }
+ default {
+ fail "term.exp, factorial didn't run to completion for info terminal"
+ }
+}
+
+# In mid-execution
+gdb_breakpoint main
+gdb_run_cmd 5
+gdb_expect {
+ -re ".*Breakpoint \[0-9\]+,.*main.*if .argc != 2.*$gdb_prompt $" {
+ gdb_test "info terminal" "Inferior's terminal status .currently saved by GDB.:.*" "info terminal at breakpoint"
+ }
+ -re ".*$gdb_prompt $" { fail "info terminal at breakpoint" }
+ timeout { fail "(timeout) info terminal at breakpoint" }
+}
diff --git a/gdb/testsuite/gdb.base/twice.c b/gdb/testsuite/gdb.base/twice.c
new file mode 100644
index 00000000000..c50a2b362d7
--- /dev/null
+++ b/gdb/testsuite/gdb.base/twice.c
@@ -0,0 +1,19 @@
+int nothing ()
+
+{
+ int x = 3 ;
+ return x ;
+}
+
+
+main ()
+
+{
+ int y ;
+#ifdef usestubs
+ set_debug_traps();
+ breakpoint();
+#endif
+ y = nothing () ;
+ printf ("hello\n") ;
+}
diff --git a/gdb/testsuite/gdb.base/twice.exp b/gdb/testsuite/gdb.base/twice.exp
new file mode 100644
index 00000000000..8d8c403a7ca
--- /dev/null
+++ b/gdb/testsuite/gdb.base/twice.exp
@@ -0,0 +1,63 @@
+# Copyright (C) 1997 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+set prms_id 0
+set bug_id 0
+
+set testfile twice-tmp
+set srcfile ${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+set options debug
+lappend options "additional_flags=-I."
+
+set fileid [open ${objdir}/${subdir}/${srcfile} w];
+puts $fileid "#include \"twice.c\"";
+close $fileid;
+
+remote_download host ${srcdir}/${subdir}/twice.c twice.c
+
+if { [gdb_compile "${objdir}/${subdir}/${srcfile}" "${binfile}" executable $options] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+# Start with a fresh gdb.
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load $binfile
+
+if [runto_main] then {
+ # Test that GDB can still detect whether we have line numbers
+ # even if we're executing code in an include file.
+
+ # The bug was fixed by
+ #Tue Jun 29 11:02:58 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+ #
+ # * infrun.c (wait_for_inferior): Use find_pc_line not
+ # find_pc_symtab to check whether there is line number
+ # information.
+
+ gdb_test "step" "nothing \\(\\) at.*"
+}
+return 0
diff --git a/gdb/testsuite/gdb.base/varargs.c b/gdb/testsuite/gdb.base/varargs.c
new file mode 100644
index 00000000000..729d7df5bea
--- /dev/null
+++ b/gdb/testsuite/gdb.base/varargs.c
@@ -0,0 +1,108 @@
+/* varargs.c -
+ * (Added as part of fix for bug 15306 - "call" to varargs functions fails)
+ * This program is intended to let me try out "call" to varargs functions
+ * with varying numbers of declared args and various argument types.
+ * - RT 9/27/95
+ */
+
+#include <stdio.h>
+#include <stdarg.h>
+
+int find_max1(int, ...);
+int find_max2(int, int, ...);
+double find_max_double(int, double, ...);
+
+char ch;
+unsigned char uc;
+short s;
+unsigned short us;
+int a,b,c,d;
+int max_val;
+float fa,fb,fc,fd;
+double da,db,dc,dd;
+double dmax_val;
+
+main() {
+ c = -1;
+ uc = 1;
+ s = -2;
+ us = 2;
+ a = 1;
+ b = 60;
+ max_val = find_max1(1, 60);
+ max_val = find_max1(a, b);
+ a = 3;
+ b = 1;
+ c = 4;
+ d = 2;
+ max_val = find_max1(3, 1, 4, 2);
+ max_val = find_max2(a, b, c, d);
+ da = 3.0;
+ db = 1.0;
+ dc = 4.0;
+ dd = 2.0;
+ dmax_val = find_max_double(3, 1.0, 4.0, 2.0);
+ dmax_val = find_max_double(a, db, dc, dd);
+}
+
+/* Integer varargs, 1 declared arg */
+
+int find_max1(int num_vals, ...) {
+ int max_val = 0;
+ int x;
+ int i;
+ va_list argp;
+ va_start(argp, num_vals);
+ printf("find_max(%d,", num_vals);
+ for (i = 0; i < num_vals; i++) {
+ x = va_arg(argp, int);
+ if (max_val < x) max_val = x;
+ if (i < num_vals - 1)
+ printf(" %d,", x);
+ else
+ printf(" %d)", x);
+ }
+ printf(" returns %d\n", max_val);
+ return max_val;
+}
+
+/* Integer varargs, 2 declared args */
+
+int find_max2(int num_vals, int first_val, ...) {
+ int max_val = 0;
+ int x;
+ int i;
+ va_list argp;
+ va_start(argp, first_val);
+ x = first_val;
+ if (max_val < x) max_val = x;
+ printf("find_max(%d, %d", num_vals, first_val);
+ for (i = 1; i < num_vals; i++) {
+ x = va_arg(argp, int);
+ if (max_val < x) max_val = x;
+ printf(", %d", x);
+ }
+ printf(") returns %d\n", max_val);
+ return max_val;
+}
+
+/* Double-float varargs, 2 declared args */
+
+double find_max_double(int num_vals, double first_val, ...) {
+ double max_val = 0;
+ double x;
+ int i;
+ va_list argp;
+ va_start(argp, first_val);
+ x = first_val;
+ if (max_val < x) max_val = x;
+ printf("find_max(%f, %f", num_vals, first_val);
+ for (i = 1; i < num_vals; i++) {
+ x = va_arg(argp, double);
+ if (max_val < x) max_val = x;
+ printf(", %f", x);
+ }
+ printf(") returns %f\n", max_val);
+ return max_val;
+}
+
diff --git a/gdb/testsuite/gdb.base/varargs.exp b/gdb/testsuite/gdb.base/varargs.exp
new file mode 100644
index 00000000000..e6548b288f5
--- /dev/null
+++ b/gdb/testsuite/gdb.base/varargs.exp
@@ -0,0 +1,139 @@
+# Copyright (C) 1997, 1998 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file was written by Elena Zannoni (ezannoni@cygnus.com)
+
+
+# this file tests command line calls with functions having variable
+# args list
+# corresponding source file: varargs.c
+
+#print find_max1(5,1,2,3,4,5)
+#print find_max1(1,3)
+#call find_max1(10,1,2,3,4,5,6,7,8,29,0)
+#print find_max2(3,1,2,3)
+#print find_max_double(5,1.0,17.0,2.0,3.0,4.0)
+#quit
+
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+set prms_id 0
+set bug_id 0
+
+set prototypes 0
+set testfile "varargs"
+set srcfile ${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+
+if [get_compiler_info ${binfile}] {
+ return -1
+}
+
+if {$gcc_compiled == 0} {
+ if [istarget "hppa*-hp-hpux*"] then {
+ set additional_flags "additional_flags=-Ae"
+ } else {
+ # don't know what the compiler is, hope for the best, maybe it's ANSI...
+ set additional_flags ""
+ }
+} else {
+ set additional_flags ""
+}
+
+# build the first test case
+#if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable [list debug $additional_flags]] != "" } {
+# gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+#}
+
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable [list debug $additional_flags]] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+# Start with a fresh gdb.
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+send_gdb "set print sevenbit-strings\n" ; gdb_expect -re "$gdb_prompt $"
+send_gdb "set print address off\n" ; gdb_expect -re "$gdb_prompt $"
+send_gdb "set width 0\n" ; gdb_expect -re "$gdb_prompt $"
+
+
+if ![runto_main] then {
+ perror "couldn't run to breakpoint"
+ continue
+}
+
+
+send_gdb "print find_max1(5,1,2,3,4,5)\n"
+gdb_expect {
+ -re ".*find_max\\(5, 1, 2, 3, 4, 5\\) returns 5\[ \r\n\]+.\[0-9\]+ = 5.*$gdb_prompt $" {
+ pass "print find_max1(5,1,2,3,4,5)"
+ }
+ -re ".*$gdb_prompt $" { fail "print find_max1(5,1,2,3,4,5)" }
+ timeout { fail "(timeout) print find_max1(5,1,2,3,4,5)" }
+ }
+
+
+
+
+send_gdb "print find_max1(1,3)\n"
+gdb_expect {
+ -re ".*find_max\\(1, 3\\) returns 3\[ \r\n\]+.\[0-9\]+ = 3.*$gdb_prompt $" {
+ pass "print find_max1(1,3)"
+ }
+ -re ".*$gdb_prompt $" { fail "print find_max1(1,3)" }
+ timeout { fail "(timeout) print find_max1(1,3)" }
+ }
+
+
+send_gdb "print find_max1(10,1,2,3,4,5,6,7,8,29,0)\n"
+gdb_expect {
+ -re ".*find_max\\(10, 1, 2, 3, 4, 5, 6, 7, 8, 29, 0\\) returns 29\[ \r\n\]+.\[0-9\]+ = 29.*$gdb_prompt $" {
+ pass "print find_max1(10,1,2,3,4,5,6,7,8,29,0)"
+ }
+ -re ".*$gdb_prompt $" { fail "print find_max1(10,1,2,3,4,5,6,7,8,29,0)" }
+ timeout { fail "(timeout) print find_max1(10,1,2,3,4,5,6,7,8,29,0)" }
+ }
+
+
+
+send_gdb "print find_max2(3,1,2,3)\n"
+gdb_expect {
+ -re ".*find_max\\(3, 1, 2, 3\\) returns 3\[ \r\n\]+.\[0-9\]+ = 3.*$gdb_prompt $" {
+ pass "print find_max2(3,1,2,3)"
+ }
+ -re ".*$gdb_prompt $" { fail "print find_max2(3,1,2,3)" }
+ timeout { fail "(timeout) print find_max2(3,1,2,3)" }
+ }
+
+
+send_gdb "print find_max_double(5,1.0,17.0,2.0,3.0,4.0)\n"
+gdb_expect {
+ -re ".*find_max\\(.*\\) returns 17\\.000000\[ \r\n\]+.\[0-9\]+ = 17.*$gdb_prompt $" {
+ pass "print find_max_double(5,1.0,17.0,2.0,3.0,4.0)"
+ }
+ -re ".*$gdb_prompt $" { fail "print find_max_double(5,1.0,17.0,2.0,3.0,4.0)" }
+ timeout { fail "(timeout) print find_max_double(5,1.0,17.0,2.0,3.0,4.0)" }
+ }
+
diff --git a/gdb/testsuite/gdb.base/volatile.exp b/gdb/testsuite/gdb.base/volatile.exp
new file mode 100644
index 00000000000..a2a2b59f5f6
--- /dev/null
+++ b/gdb/testsuite/gdb.base/volatile.exp
@@ -0,0 +1,243 @@
+# Copyright (C) 1997, 1998, 1999 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# Written by Satish Pai <pai@apollo.hp.com> 1997-07-07
+# In the spirit of constvars.exp: added volatile, const-volatile stuff.
+
+# This file is part of the gdb testsuite
+# Tests for:
+# volatile vars
+# pointers to volatile vars
+# const volatile vars
+# pointers to const volatile vars
+# const pointers to volatile vars
+# volatile pointers to const vars
+# const volatile pointers to const vars
+# const volatile pointers to volatile vars
+# ... etc. (you get the idea)
+# Mostly with char and unsigned char.
+
+if $tracelevel then {
+ strace $tracelevel
+ }
+
+#
+# test running programs
+#
+set prms_id 0
+set bug_id 0
+
+# Use the same test program constvars.c.
+
+set testfile "constvars"
+set srcfile ${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+remote_exec build "rm -f ${binfile}.ci"
+if [get_compiler_info ${binfile}] {
+ return -1
+}
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+source ${binfile}.ci
+
+#
+# set it up at a breakpoint so we can play with the variable values
+#
+if ![runto_main] then {
+ perror "couldn't run to breakpoint"
+ continue
+}
+
+send_gdb "break marker1\n" ; gdb_expect -re ".*$gdb_prompt $"
+
+ send_gdb "cont\n"
+ gdb_expect {
+ -re "Break.* marker1 \\(\\) at .*:$decimal.*$gdb_prompt $" {
+ send_gdb "up\n"
+ gdb_expect {
+ -re ".*$gdb_prompt $" {}
+ timeout { fail "up from marker1" }
+ }
+ }
+ -re "Break.* marker1__.* \\(\\) at .*:$decimal.*$gdb_prompt $" {
+ fail "continue to marker1 (demangling)"
+ send_gdb "up\n"
+ gdb_expect {
+ -re ".*$gdb_prompt $" {}
+ timeout { fail "up from marker1" }
+ }
+ }
+ -re "$gdb_prompt $" { fail "continue to marker1" }
+ timeout { fail "(timeout) continue to marker1" }
+ }
+
+# As of Feb 1999, GCC does not issue info about volatility of vars, so
+# these tests are all expected to fail if GCC is the compiler. -sts
+
+if {$gcc_compiled} then { setup_xfail "*-*-*" }
+gdb_test "ptype vox" "type = volatile char"
+
+if {$gcc_compiled} then { setup_xfail "*-*-*" }
+gdb_test "ptype victuals" "type = volatile unsigned char"
+
+if {$gcc_compiled} then { setup_xfail "*-*-*" }
+gdb_test "ptype vixen" "type = volatile short"
+
+if {$gcc_compiled} then { setup_xfail "*-*-*" }
+gdb_test "ptype vitriol" "type = volatile unsigned short"
+
+if {$gcc_compiled} then { setup_xfail "*-*-*" }
+gdb_test "ptype vellum" "type = volatile long"
+
+if {$gcc_compiled} then { setup_xfail "*-*-*" }
+gdb_test "ptype valve" "type = volatile unsigned long"
+
+if {$gcc_compiled} then { setup_xfail "*-*-*" }
+gdb_test "ptype vacuity" "type = volatile float"
+
+if {$gcc_compiled} then { setup_xfail "*-*-*" }
+gdb_test "ptype vertigo" "type = volatile double"
+
+if {$gcc_compiled} then { setup_xfail "*-*-*" }
+gdb_test "ptype vampire" "type = volatile char *"
+
+if {$gcc_compiled} then { setup_xfail "*-*-*" }
+gdb_test "ptype viper" "type = volatile unsigned char *"
+
+if {$gcc_compiled} then { setup_xfail "*-*-*" }
+gdb_test "ptype vigour" "type = volatile short *"
+
+if {$gcc_compiled} then { setup_xfail "*-*-*" }
+gdb_test "ptype vapour" "type = volatile unsigned short *"
+
+if {$gcc_compiled} then { setup_xfail "*-*-*" }
+gdb_test "ptype ventricle" "type = volatile long *"
+
+if {$gcc_compiled} then { setup_xfail "*-*-*" }
+gdb_test "ptype vigintillion" "type = volatile unsigned long *"
+
+if {$gcc_compiled} then { setup_xfail "*-*-*" }
+gdb_test "ptype vocation" "type = volatile float *"
+
+if {$gcc_compiled} then { setup_xfail "*-*-*" }
+gdb_test "ptype veracity" "type = volatile double *"
+
+if {$gcc_compiled} then { setup_xfail "*-*-*" }
+gdb_test "ptype vapidity" "type = volatile char * volatile"
+
+if {$gcc_compiled} then { setup_xfail "*-*-*" }
+gdb_test "ptype velocity" "type = volatile unsigned char * volatile"
+
+if {$gcc_compiled} then { setup_xfail "*-*-*" }
+gdb_test "ptype veneer" "type = volatile short * volatile"
+
+if {$gcc_compiled} then { setup_xfail "*-*-*" }
+gdb_test "ptype video" "type = volatile unsigned short * volatile"
+
+if {$gcc_compiled} then { setup_xfail "*-*-*" }
+gdb_test "ptype vacuum" "type = volatile long * volatile"
+
+if {$gcc_compiled} then { setup_xfail "*-*-*" }
+gdb_test "ptype veniality" "type = volatile unsigned long * volatile"
+
+if {$gcc_compiled} then { setup_xfail "*-*-*" }
+gdb_test "ptype vitality" "type = volatile float * volatile"
+
+if {$gcc_compiled} then { setup_xfail "*-*-*" }
+gdb_test "ptype voracity" "type = volatile double * volatile"
+
+if {$gcc_compiled} then { setup_xfail "*-*-*" }
+gdb_test "ptype victor" "type = const volatile char"
+
+if {$gcc_compiled} then { setup_xfail "*-*-*" }
+gdb_test "ptype vicar" "type = const volatile unsigned char"
+
+if {$gcc_compiled} then { setup_xfail "*-*-*" }
+gdb_test "ptype victory" "type = const volatile char *"
+
+if {$gcc_compiled} then { setup_xfail "*-*-*" }
+gdb_test "ptype vicarage" "type = const volatile unsigned char *"
+
+if {$gcc_compiled} then { setup_xfail "*-*-*" }
+gdb_test "ptype vein" "type = volatile char * const"
+
+if {$gcc_compiled} then { setup_xfail "*-*-*" }
+gdb_test "ptype vogue" "type = volatile unsigned char * const"
+
+if {$gcc_compiled} then { setup_xfail "*-*-*" }
+gdb_test "ptype cavern" "type = const volatile char * const"
+
+if {$gcc_compiled} then { setup_xfail "*-*-*" }
+gdb_test "ptype coverlet" "type = const volatile unsigned char * const"
+
+if {$gcc_compiled} then { setup_xfail "*-*-*" }
+gdb_test "ptype caveat" "type = const char * volatile"
+
+if {$gcc_compiled} then { setup_xfail "*-*-*" }
+gdb_test "ptype covenant" "type = const unsigned char * volatile"
+
+if {$gcc_compiled} then { setup_xfail "*-*-*" }
+gdb_test "ptype vizier" "type = const volatile char * volatile"
+
+if {$gcc_compiled} then { setup_xfail "*-*-*" }
+gdb_test "ptype vanadium" "type = const volatile unsigned char * volatile"
+
+if {$gcc_compiled} then { setup_xfail "*-*-*" }
+gdb_test "ptype vane" "type = char * const volatile"
+
+if {$gcc_compiled} then { setup_xfail "*-*-*" }
+gdb_test "ptype veldt" "type = unsigned char * const volatile"
+
+if {$gcc_compiled} then { setup_xfail "*-*-*" }
+gdb_test "ptype cove" "type = const char * const volatile"
+
+if {$gcc_compiled} then { setup_xfail "*-*-*" }
+gdb_test "ptype cavity" "type = const unsigned char * const volatile"
+
+if {$gcc_compiled} then { setup_xfail "*-*-*" }
+gdb_test "ptype vagus" "type = volatile char * const volatile"
+
+if {$gcc_compiled} then { setup_xfail "*-*-*" }
+gdb_test "ptype vagrancy" "type = volatile unsigned char * const volatile"
+
+if {$gcc_compiled} then { setup_xfail "*-*-*" }
+gdb_test "ptype vagary" "type = const volatile char * const volatile"
+
+if {$gcc_compiled} then { setup_xfail "*-*-*" }
+gdb_test "ptype vendor" "type = const volatile unsigned char * const volatile"
+
+# test function parameters
+if {$gcc_compiled} then { setup_xfail "*-*-*" }
+send_gdb "ptype qux2\n"
+gdb_expect {
+ -re "type = int \\(volatile unsigned char, const volatile int, volatile short &, volatile long \\*, float \\* volatile, const volatile signed char \\* const volatile\\)" {
+ pass "ptype qux2"
+ }
+ -re ".*$gdb_prompt $" { fail "ptype qux2" }
+ timeout { fail "(timeout) ptype qux2" }
+ }
diff --git a/gdb/testsuite/gdb.base/watchpoint.c b/gdb/testsuite/gdb.base/watchpoint.c
new file mode 100644
index 00000000000..bd54f3e9621
--- /dev/null
+++ b/gdb/testsuite/gdb.base/watchpoint.c
@@ -0,0 +1,124 @@
+#include <stdio.h>
+/*
+ * Since using watchpoints can be very slow, we have to take some pains to
+ * ensure that we don't run too long with them enabled or we run the risk
+ * of having the test timeout. To help avoid this, we insert some marker
+ * functions in the execution stream so we can set breakpoints at known
+ * locations, without worrying about invalidating line numbers by changing
+ * this file. We use null bodied functions are markers since gdb does
+ * not support breakpoints at labeled text points at this time.
+ *
+ * One place we need is a marker for when we start executing our tests
+ * instructions rather than any process startup code, so we insert one
+ * right after entering main(). Another is right before we finish, before
+ * we start executing any process termination code.
+ *
+ * Another problem we have to guard against, at least for the test
+ * suite, is that we need to ensure that the line that causes the
+ * watchpoint to be hit is still the current line when gdb notices
+ * the hit. Depending upon the specific code generated by the compiler,
+ * the instruction after the one that triggers the hit may be part of
+ * the same line or part of the next line. Thus we ensure that there
+ * are always some instructions to execute on the same line after the
+ * code that should trigger the hit.
+ */
+
+int count = -1;
+int ival1 = -1;
+int ival2 = -1;
+int ival3 = -1;
+int ival4 = -1;
+char buf[10];
+struct foo
+{
+ int val;
+};
+struct foo struct1, struct2, *ptr1, *ptr2;
+
+int doread = 0;
+
+void marker1 ()
+{
+}
+
+void marker2 ()
+{
+}
+
+void marker4 ()
+{
+}
+
+void marker5 ()
+{
+}
+
+void
+func2 ()
+{
+}
+
+int
+func1 ()
+{
+ /* The point of this is that we will set a breakpoint at this call.
+
+ Then, if DECR_PC_AFTER_BREAK equals the size of a function call
+ instruction (true on a sun3 if this is gcc-compiled--FIXME we
+ should use asm() to make it work for any compiler, present or
+ future), then we will end up branching to the location just after
+ the breakpoint. And we better not confuse that with hitting the
+ breakpoint. */
+ func2 ();
+ return 73;
+}
+
+int main ()
+{
+#ifdef usestubs
+ set_debug_traps();
+ breakpoint();
+#endif
+ struct1.val = 1;
+ struct2.val = 2;
+ ptr1 = &struct1;
+ ptr2 = &struct2;
+ marker1 ();
+ func1 ();
+ for (count = 0; count < 4; count++) {
+ ival1 = count;
+ ival3 = count; ival4 = count;
+ }
+ ival1 = count; /* Outside loop */
+ ival2 = count;
+ ival3 = count; ival4 = count;
+ marker2 ();
+ if (doread)
+ {
+ static char msg[] = "type stuff for buf now:";
+ write (1, msg, sizeof (msg) - 1);
+ read (0, &buf[0], 5);
+ }
+ marker4 ();
+
+ /* We have a watchpoint on ptr1->val. It should be triggered if
+ ptr1's value changes. */
+ ptr1 = ptr2;
+
+ /* This should not trigger the watchpoint. If it does, then we
+ used the wrong value chain to re-insert the watchpoints or we
+ are not evaluating the watchpoint expression correctly. */
+ struct1.val = 5;
+ marker5 ();
+
+ /* We have a watchpoint on ptr1->val. It should be triggered if
+ ptr1's value changes. */
+ ptr1 = ptr2;
+
+ /* This should not trigger the watchpoint. If it does, then we
+ used the wrong value chain to re-insert the watchpoints or we
+ are not evaluating the watchpoint expression correctly. */
+ struct1.val = 5;
+ marker5 ();
+ return 0;
+}
diff --git a/gdb/testsuite/gdb.base/watchpoint.exp b/gdb/testsuite/gdb.base/watchpoint.exp
new file mode 100644
index 00000000000..a2954452cd1
--- /dev/null
+++ b/gdb/testsuite/gdb.base/watchpoint.exp
@@ -0,0 +1,583 @@
+# Copyright (C) 1992, 1994, 1997, 1998 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file was written by Fred Fish. (fnf@cygnus.com)
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+set prms_id 0
+set bug_id 0
+
+set testfile "watchpoint"
+set srcfile ${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+
+
+if [get_compiler_info ${binfile}] {
+ return -1
+}
+
+# if we are on HPUX and we are not compiled with gcc, then skip these tests.
+
+if [istarget hppa*-*-hpux*] {
+ if {!$gcc_compiled} {
+ continue
+ }
+}
+
+
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+# Prepare for watchpoint tests by setting up two breakpoints and one
+# watchpoint.
+#
+# We use breakpoints at marker functions to get past all the startup code,
+# so we can get to the watchpoints in a reasonable amount of time from a
+# known starting point.
+#
+# For simplicity, so we always know how to reference specific breakpoints or
+# watchpoints by number, we expect a particular ordering and numbering of
+# each in the combined breakpoint/watchpoint table, as follows:
+#
+# Number What Where
+# 1 Breakpoint marker1()
+# 2 Breakpoint marker2()
+# 3 Watchpoint ival3
+
+proc initialize {} {
+ global gdb_prompt
+ global hex
+ global decimal
+ global srcfile
+
+ if [gdb_test "break marker1" "Breakpoint 1 at $hex: file .*$srcfile, line $decimal.*" "set breakpoint at marker1" ] {
+ return 0;
+ }
+
+
+ if [gdb_test "break marker2" "Breakpoint 2 at $hex: file .*$srcfile, line $decimal.*" "set breakpoint at marker2" ] {
+ return 0;
+ }
+
+
+ if [gdb_test "info break" "1\[ \]*breakpoint.*marker1.*\r\n2\[ \]*breakpoint.*marker2.*" "info break in watchpoint.exp" ] {
+ return 0;
+ }
+
+
+ if [gdb_test "watch ival3" ".*\[Ww\]atchpoint 3: ival3" "set watchpoint on ival3" ] {
+ return 0;
+ }
+
+
+ # "info watch" is the same as "info break"
+
+ if [gdb_test "info watch" "1\[ \]*breakpoint.*marker1.*\r\n2\[ \]*breakpoint.*marker2.*\r\n3\[ \]*.*watchpoint.*ival3" "watchpoint found in watchpoint/breakpoint table" ] {
+ return 0;
+ }
+
+
+ # After installing the watchpoint, we disable it until we are ready
+ # to use it. This allows the test program to run at full speed until
+ # we get to the first marker function.
+
+ if [gdb_test "disable 3" "disable 3\[\r\n\]+" "disable watchpoint" ] {
+ return 0;
+ }
+
+
+ return 1
+}
+
+#
+# Test simple watchpoint.
+#
+
+proc test_simple_watchpoint {} {
+ global gdb_prompt
+ global hex
+ global decimal
+
+ # Ensure that the watchpoint is disabled when we startup.
+
+ if [gdb_test "disable 3" "^disable 3\[\r\n\]+" "disable watchpoint in test_simple_watchpoint" ] {
+ return 0;
+ }
+
+
+ # Run until we get to the first marker function.
+
+ gdb_run_cmd
+ set timeout 600
+ gdb_expect {
+ -re "Breakpoint 1, marker1 .*$gdb_prompt $" {
+ pass "run to marker1 in test_simple_watchpoint"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "run to marker1 in test_simple_watchpoint"
+ return
+ }
+ timeout {
+ fail "run to marker1 in test_simple_watchpoint (timeout)"
+ return
+ }
+ }
+
+ # After reaching the marker function, enable the watchpoint.
+
+ if [gdb_test "enable 3" "^enable 3\[\r\n\]+" "enable watchpoint" ] {
+ return ;
+ }
+
+
+ gdb_test "break func1" "Breakpoint.*at.*"
+ gdb_test "set \$func1_breakpoint_number = \$bpnum" ""
+
+ gdb_test "continue" "Continuing.*Breakpoint \[0-9\]*, func1.*" \
+ "continue to breakpoint at func1"
+
+ # Continue until the first change, from -1 to 0
+
+ send_gdb "cont\n"
+ gdb_expect {
+ -re "Continuing.*\[Ww\]atchpoint.*ival3.*Old value = -1.*New value = 0.*ival3 = count; ival4 = count;.*$gdb_prompt $" {
+ pass "watchpoint hit, first time"
+ }
+ -re "Continuing.*Breakpoint.*func1.*$gdb_prompt $" {
+ setup_xfail "m68*-*-*" 2597
+ fail "thought it hit breakpoint at func1 twice"
+ gdb_test "delete \$func1_breakpoint_number" ""
+ gdb_test "continue" "\
+Continuing.*\[Ww\]atchpoint.*ival3.*Old value = -1.*New value = 0.*ival3 = count;" \
+ "watchpoint hit, first time"
+ }
+ -re ".*$gdb_prompt $" { fail "watchpoint hit, first time" ; return }
+ timeout { fail "watchpoint hit, first time (timeout)" ; return }
+ eof { fail "watchpoint hit, first time (eof)" ; return }
+ }
+
+ gdb_test "delete \$func1_breakpoint_number" ""
+
+ # Continue until the next change, from 0 to 1.
+ gdb_test "cont" "Continuing.*\[Ww\]atchpoint.*ival3.*Old value = 0.*New value = 1.*ival3 = count; ival4 = count;.*" "watchpoint hit, second time"
+
+ # Continue until the next change, from 1 to 2.
+ gdb_test "cont" "Continuing.*\[Ww\]atchpoint.*ival3.*Old value = 1.*New value = 2.*ival3 = count; ival4 = count;.*" "watchpoint hit, third time"
+
+ # Continue until the next change, from 2 to 3.
+ gdb_test "cont" "Continuing.*\[Ww\]atchpoint.*ival3.*Old value = 2.*New value = 3.*ival3 = count; ival4 = count;.*" "watchpoint hit, fourth time"
+
+ # Continue until the next change, from 3 to 4.
+ # Note that this one is outside the loop.
+
+ gdb_test "cont" "Continuing.*\[Ww\]atchpoint.*ival3.*Old value = 3.*New value = 4.*ival3 = count; ival4 = count;.*" "watchpoint hit, fifth time"
+
+ # Continue until we hit the finishing marker function.
+ # Make sure we hit no more watchpoints.
+
+ gdb_test "cont" "Continuing.*Breakpoint.*marker2 \(\).*" \
+ "continue to marker2"
+
+ # Disable the watchpoint so we run at full speed until we exit.
+
+ if [gdb_test "disable 3" "^disable 3\[\r\n\]+" "watchpoint disabled" ] {
+ return ;
+ }
+
+
+ # Run until process exits.
+
+ if [target_info exists gdb,noresults] { return }
+
+ gdb_test "cont" "Continuing.*Program exited normally.*" \
+ "continue to exit in test_simple_watchpoint"
+}
+
+# Test disabling watchpoints.
+
+proc test_disabling_watchpoints {} {
+ global gdb_prompt
+ global binfile
+ global srcfile
+ global decimal
+ global hex
+
+ # Ensure that the watchpoint is disabled when we startup.
+
+ if [gdb_test "disable 3" "^disable 3\[\r\n\]+" "disable watchpoint in test_disabling_watchpoints" ] {
+ return 0;
+ }
+
+
+ # Run until we get to the first marker function.
+
+ gdb_run_cmd
+ set timeout 600
+ gdb_expect {
+ -re "Breakpoint 1, marker1 .*$gdb_prompt $" {
+ pass "run to marker1 in test_disabling_watchpoints"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "run to marker1 in test_disabling_watchpoints"
+ return
+ }
+ timeout {
+ fail "run to marker1 in test_disabling_watchpoints (timeout)"
+ return
+ }
+ }
+
+ # After reaching the marker function, enable the watchpoint.
+
+ if [gdb_test "enable 3" "^enable 3\[\r\n\]+" "watchpoint enabled" ] {
+ return ;
+ }
+
+
+ # Continue until the first change, from -1 to 0
+ # Don't check the old value, because on VxWorks the variable value
+ # will not have been reinitialized.
+ gdb_test "cont" "Continuing.*\[Ww\]atchpoint.*ival3.*Old value = .*New value = 0.*ival3 = count; ival4 = count;.*" "watchpoint hit in test_disabling_watchpoints, first time"
+
+ # Continue until the next change, from 0 to 1.
+ gdb_test "cont" "Continuing.*\[Ww\]atchpoint.*ival3.*Old value = 0.*New value = 1.*ival3 = count; ival4 = count;.*" "watchpoint hit in test_disabling_watchpoints, second time"
+
+ # Disable the watchpoint but leave breakpoints
+
+ if [gdb_test "disable 3" "^disable 3\[\r\n\]+" "disable watchpoint #2 in test_disabling_watchpoints" ] {
+ return 0;
+ }
+
+
+ # Check watchpoint list, looking for the entry that confirms the
+ # watchpoint is disabled.
+ gdb_test "info watchpoints" "3\[ \]*.*watchpoint\[ \]*keep\[ \]*n\[ \]*ival3\r\n.*" "watchpoint disabled in table"
+
+ # Continue until we hit the finishing marker function.
+ # Make sure we hit no more watchpoints.
+ gdb_test "cont" "Continuing.*Breakpoint.*marker2 \\(\\).*" \
+ "disabled watchpoint skipped"
+
+ if [target_info exists gdb,noresults] { return }
+
+ gdb_test "cont" "Continuing.*Program exited normally.*" \
+ "continue to exit in test_disabling_watchpoints"
+}
+
+# Test stepping and other mundane operations with watchpoints enabled
+proc test_stepping {} {
+ global gdb_prompt
+
+ if [runto marker1] then {
+ gdb_test "watch ival2" ".*\[Ww\]atchpoint \[0-9\]*: ival2"
+
+ # Well, let's not be too mundane. It should be a *bit* of a challenge
+ gdb_test "break func2 if 0" "Breakpoint.*at.*"
+ gdb_test "p \$func2_breakpoint_number = \$bpnum" " = .*"
+
+ # The HPPA has a problem here if it's not using hardware watchpoints
+ if {[ istarget "hppa*-*-*" ] && ![ istarget "hppa*-*-*bsd*" ]} then {
+ # Don't actually try doing the call, if we do we can't continue.
+ setup_xfail "*-*-*"
+ fail "calling function with watchpoint enabled"
+ } else {
+ # The problem is that GDB confuses stepping through the call
+ # dummy with hitting the breakpoint at the end of the call dummy.
+ # Will be fixed once all architectures define
+ # CALL_DUMMY_BREAKPOINT_OFFSET.
+ setup_xfail "*-*-*"
+ # This doesn't occur if the call dummy starts with a call,
+ # because we are out of the dummy by the first time the inferior
+ # stops.
+ clear_xfail "d10v*-*-*"
+ clear_xfail "m68*-*-*"
+ clear_xfail "i*86*-*-*"
+ clear_xfail "vax-*-*"
+ # The following architectures define CALL_DUMMY_BREAKPOINT_OFFSET.
+ clear_xfail "alpha-*-*"
+ clear_xfail "mips*-*-*"
+ clear_xfail "sparc-*-*"
+ clear_xfail "hppa*-*-*bsd*"
+ # It works with the generic inferior function calling code too.
+ clear_xfail "mn10200*-*-*"
+ clear_xfail "mn10300*-*-*"
+ gdb_test "p func1 ()" "= 73" \
+ "calling function with watchpoint enabled"
+ }
+
+ #
+ # "finish" brings us back to main.
+ # On some targets (e.g. alpha) gdb will stop from the finish in midline
+ # of the marker1 call. This is due to register restoring code on
+ # the alpha and might be caused by stack adjustment instructions
+ # on other targets. In this case we will step once more.
+ #
+
+ send_gdb "finish\n"
+ gdb_expect {
+ -re "Run.*exit from.*marker1.* at" { }
+ default { fail "finish from marker1" ; return }
+ }
+
+ gdb_expect {
+ -re "marker1 \\(\\);.*$gdb_prompt $" {
+ send_gdb "step\n"
+ exp_continue
+ }
+ -re "func1 \\(\\);.*$gdb_prompt $" {
+ pass "finish from marker1"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "finish from marker1"
+ }
+ default { fail "finish from marker1" ; return }
+ }
+
+ gdb_test "next" "for \\(count = 0.*" "next to `for' in watchpoint.exp"
+
+ # Now test that "until" works. It's a bit tricky to test
+ # "until", because compilers don't always arrange the code
+ # exactly the same way, and we might get slightly different
+ # sequences of statements. But the following should be true
+ # (if not it is a compiler or a debugger bug): The user who
+ # does "until" at every statement of a loop should end up
+ # stepping through the loop once, and the debugger should not
+ # stop for any of the remaining iterations.
+
+ gdb_test "until" "ival1 = count.*" "until to ival1 assignment"
+ gdb_test "until" "ival3 = count.*" "until to ival3 assignment"
+ send_gdb "until\n"
+ gdb_expect {
+ -re "(for \\(count = 0|\}).*$gdb_prompt $" {
+ gdb_test "until" "ival1 = count; /. Outside loop ./" \
+ "until out of loop"
+ }
+ -re "ival1 = count; /. Outside loop ./.*$gdb_prompt $" {
+ pass "until out of loop"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "until out of loop"
+ }
+ default { fail "until out of loop" ; return }
+ }
+
+ gdb_test "step" "ival2 = count.*" "step to ival2 assignment"
+ }
+}
+
+# Test stepping and other mundane operations with watchpoints enabled
+proc test_watchpoint_triggered_in_syscall {} {
+ global gdb_prompt
+
+ if [target_info exists gdb,noinferiorio] {
+ verbose "Skipping test_watchpoint_triggered_in_syscall due to noinferiorio"
+ return
+ }
+ # Run until we get to the first marker function.
+ set x 0
+ set y 0
+ set testname "Watch buffer passed to read syscall"
+ if [runto marker2] then {
+ gdb_test "watch buf\[0\]" ".*\[Ww\]atchpoint \[0-9\]*: buf\\\[0\\\]"
+ gdb_test "watch buf\[1\]" ".*\[Ww\]atchpoint \[0-9\]*: buf\\\[1\\\]"
+ gdb_test "watch buf\[2\]" ".*\[Ww\]atchpoint \[0-9\]*: buf\\\[2\\\]"
+ gdb_test "watch buf\[3\]" ".*\[Ww\]atchpoint \[0-9\]*: buf\\\[3\\\]"
+ gdb_test "watch buf\[4\]" ".*\[Ww\]atchpoint \[0-9\]*: buf\\\[4\\\]"
+ gdb_test "break marker4" ".*Breakpoint.*"
+
+ gdb_test "set doread = 1" ""
+
+ # If we send_gdb "123\n" before gdb has switched the tty, then it goes
+ # to gdb, not the inferior, and we lose. So that is why we have
+ # watchpoint.c prompt us, so we can wait for that prompt.
+ send_gdb "continue\n";
+ gdb_expect {
+ -re "Continuing\\.\r\ntype stuff for buf now:" {
+ pass "continue to read"
+ }
+ default {
+ fail "continue to read";
+ return ;
+ }
+ }
+
+ send_gdb "123\n"
+ gdb_expect {
+ -re ".*\[Ww\]atchpoint.*buf\\\[0\\\].*Old value = 0.*New value = 49\[^\n\]*\n" { set x [expr $x+1] ; exp_continue }
+ -re ".*\[Ww\]atchpoint.*buf\\\[1\\\].*Old value = 0.*New value = 50\[^\n\]*\n" { set x [expr $x+1] ; exp_continue }
+ -re ".*\[Ww\]atchpoint.*buf\\\[2\\\].*Old value = 0.*New value = 51\[^\n\]*\n" { set x [expr $x+1] ; exp_continue }
+ -re ".*\[Ww\]atchpoint.*buf\\\[3\\\].*Old value = 0.*New value = 10\[^\n\]*\n" { set x [expr $x+1] ; exp_continue }
+ -re ".*$gdb_prompt $" { pass "sent 123" }
+ timeout { fail "sent 123 (timeout)" }
+ }
+
+ # Examine the values in buf to see how many watchpoints we
+ # should have printed.
+ send_gdb "print buf\[0\]\n"
+ gdb_expect {
+ -re ".*= 49.*$gdb_prompt $" { set y [expr $y+1]; pass "print buf\[0\]"}
+ -re ".*= 0.*$gdb_prompt $" { pass "print buf\[0\]"}
+ -re ".*$gdb_prompt $" { fail "print buf\[0\]"}
+ default { fail "print buf\[0\]"}
+ }
+ send_gdb "print buf\[1\]\n"
+ gdb_expect {
+ -re ".*= 50.*$gdb_prompt $" { set y [expr $y+1]; pass "print buf\[1\]"}
+ -re ".*= 0.*$gdb_prompt $" { pass "print buf\[1\]"}
+ -re ".*$gdb_prompt $" { fail "print buf\[1\]"}
+ default { fail "print buf\[1\]"}
+ }
+ send_gdb "print buf\[2\]\n"
+ gdb_expect {
+ -re ".*= 51.*$gdb_prompt $" { set y [expr $y+1]; pass "print buf\[2\]"}
+ -re ".*= 0.*$gdb_prompt $" { pass "print buf\[2\]"}
+ -re ".*$gdb_prompt $" { fail "print buf\[2\]"}
+ default { fail "print buf\[2\]"}
+ }
+ send_gdb "print buf\[3\]\n"
+ gdb_expect {
+ -re ".*= 10.*$gdb_prompt $" { set y [expr $y+1]; pass "print buf\[3\]"}
+ -re ".*= 0.*$gdb_prompt $" { pass "print buf\[3\]"}
+ -re ".*$gdb_prompt $" { fail "print buf\[3\]" }
+ default { fail "print buf\[3\]" }
+ }
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x==$y] then { pass $testname } else { fail "$testname (only triggered $x watchpoints, expected $y)"}
+
+ # Continue until we hit the finishing marker function.
+ # Make sure we hit no more watchpoints.
+ gdb_test "cont" "Continuing.*Breakpoint.*marker4 \\(\\).*" \
+ "continue to marker4"
+
+ # Disable everything so we can finish the program at full speed
+ gdb_test "disable" "" "disable in test_watchpoint_triggered_in_syscall"
+
+ if [target_info exists gdb,noresults] { return }
+
+ gdb_test "cont" "Continuing.*Program exited normally.*" \
+ "continue to exit in test_watchpoint_triggered_in_syscall"
+ }
+}
+
+# Do a simple test of of watching through a pointer when the pointer
+# itself changes. Should add some more complicated stuff here.
+
+proc test_complex_watchpoint {} {
+ global gdb_prompt
+
+ if [runto marker4] then {
+ gdb_test "watch ptr1->val" ".*\[Ww\]atchpoint \[0-9\]*: ptr1->val"
+ gdb_test "break marker5" ".*Breakpoint.*"
+
+ gdb_test "cont" "Continuing.*\[Ww\]atchpoint.*ptr1->val.*Old value = 1.*New value = 2.*" "Test complex watchpoint"
+
+ # Continue until we hit the marker5 function.
+ # Make sure we hit no more watchpoints.
+
+ gdb_test "cont" "Continuing.*Breakpoint.*marker5 \\(\\).*" \
+ "did not trigger wrong watchpoint"
+
+ # Disable everything so we can finish the program at full speed
+ gdb_test "disable" "" "disable in test_complex_watchpoint"
+
+ if [target_info exists gdb,noresults] { return }
+
+
+ gdb_test "cont" "Continuing.*Program exited normally.*" \
+ "continue to exit in test_complex_watchpoint"
+ }
+}
+
+# Start with a fresh gdb.
+
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load $binfile
+set timeout 600
+verbose "Timeout now 600 sec.\n"
+
+if [initialize] then {
+
+ test_simple_watchpoint
+
+ # The IDT/sim monitor only has 8 (!) open files, of which it uses
+ # 4 (!). So we have to make sure one program exits before
+ # starting another one.
+ if [istarget "mips-idt-*"] then {
+ gdb_exit
+ gdb_start
+ gdb_reinitialize_dir $srcdir/$subdir
+ gdb_load $binfile
+ initialize
+ }
+
+ test_disabling_watchpoints
+
+ # See above.
+ if [istarget "mips-idt-*"] then {
+ gdb_exit
+ gdb_start
+ gdb_reinitialize_dir $srcdir/$subdir
+ gdb_load $binfile
+ initialize
+ }
+
+ if ![target_info exists gdb,cannot_call_functions] {
+ test_stepping
+
+ # See above.
+ if [istarget "mips-idt-*"] then {
+ gdb_exit
+ gdb_start
+ gdb_reinitialize_dir $srcdir/$subdir
+ gdb_load $binfile
+ initialize
+ }
+ }
+
+ # Only enabled for some targets merely because it has not been tested
+ # elsewhere.
+ # On sparc-sun-sunos4.1.3, GDB was running all the way to the marker4
+ # breakpoint before stopping for the watchpoint. I don't know why.
+ if {[istarget "hppa*-*-*"]} then {
+ test_watchpoint_triggered_in_syscall
+ }
+
+ # See above.
+ if [istarget "mips-idt-*"] then {
+ gdb_exit
+ gdb_start
+ gdb_reinitialize_dir $srcdir/$subdir
+ gdb_load $binfile
+ initialize
+ }
+
+ # Only enabled for some targets merely because it has not been tested
+ # elsewhere.
+ if {[istarget "hppa*-*-*"] || \
+ [istarget "sparc*-*-sunos*"] || \
+ [istarget "m32r-*-*"]} then {
+ test_complex_watchpoint
+ }
+}
diff --git a/gdb/testsuite/gdb.base/whatis-exp.exp b/gdb/testsuite/gdb.base/whatis-exp.exp
new file mode 100644
index 00000000000..c5b97eed357
--- /dev/null
+++ b/gdb/testsuite/gdb.base/whatis-exp.exp
@@ -0,0 +1,217 @@
+# Copyright (C) 1998 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file was written by Elena Zannoni (ezannoni@cygnus.com)
+
+# This file is part of the gdb testsuite
+#
+# tests for whatis command on expressions.
+# used in file eval.c. This flavor of whatis
+# command performs evaluation of expressions w/o actually
+# computing the value, but just the type
+# of the result. It goes through the evaluate_subexp_standard
+# with the EVAL_AVOID_SIDE_EFFECTS flag rather than EVAL_NORMAL
+#
+
+if $tracelevel then {
+ strace $tracelevel
+ }
+
+#
+# test running programs
+#
+set prms_id 0
+set bug_id 0
+
+set testfile "int-type"
+set srcfile ${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug additional_flags=-w}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+ }
+
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+
+#
+# set it up at a breakpoint so we can play with the variable values
+#
+
+if ![runto_main] then {
+ perror "couldn't run to breakpoint"
+ continue
+}
+
+#
+# test expressions with "int" types
+#
+
+gdb_test "set variable x=14" "" "set variable x=14"
+gdb_test "set variable y=2" "" "set variable y=2"
+gdb_test "set variable z=2" "" "set variable z=2"
+gdb_test "set variable w=3" "" "set variable w=3"
+
+send_gdb "print x\n"
+gdb_expect {
+ -re ".*14.*$gdb_prompt $" {
+ pass "print value of x"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of x" }
+ timeout { fail "(timeout) print value of x" }
+ }
+
+
+send_gdb "print y\n"
+gdb_expect {
+ -re ".*2.*$gdb_prompt $" {
+ pass "print value of y"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of y" }
+ timeout { fail "(timeout) print value of y" }
+ }
+
+send_gdb "print z\n"
+gdb_expect {
+ -re ".*2.*$gdb_prompt $" {
+ pass "print value of z"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of z" }
+ timeout { fail "(timeout) print value of z" }
+ }
+
+send_gdb "print w\n"
+gdb_expect {
+ -re ".*3.*$gdb_prompt $" {
+ pass "print value of w"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of w" }
+ timeout { fail "(timeout) print value of w" }
+ }
+
+
+
+send_gdb "whatis x+y\n"
+gdb_expect {
+ -re ".*type = long.*$gdb_prompt $" {
+ pass "whatis value of x+y"
+ }
+ -re ".*$gdb_prompt $" { fail "whatis value of x+y" }
+ timeout { fail "(timeout) whatis value of x+y" }
+ }
+
+send_gdb "whatis x-y\n"
+gdb_expect {
+ -re ".*type = long.*$gdb_prompt $" {
+ pass "whatis value of x-y"
+ }
+ -re ".*$gdb_prompt $" { fail "whatis value of x-y" }
+ timeout { fail "(timeout) whatis value of x-y" }
+ }
+
+send_gdb "whatis x*y\n"
+gdb_expect {
+ -re ".*type = long.*$gdb_prompt $" {
+ pass "whatis value of x*y"
+ }
+ -re ".*$gdb_prompt $" { fail "whatis value of x*y" }
+ timeout { fail "(timeout) whatis value of x*y" }
+ }
+
+send_gdb "whatis x/y\n"
+gdb_expect {
+ -re ".*type = int.*$gdb_prompt $" {
+ pass "whatis value of x/y"
+ }
+ -re ".*$gdb_prompt $" { fail "whatis value of x/y" }
+ timeout { fail "(timeout) whatis value of x/y" }
+ }
+
+send_gdb "whatis x%y\n"
+gdb_expect {
+ -re ".*type = int.*$gdb_prompt $" {
+ pass "whatis value of x%y"
+ }
+ -re ".*$gdb_prompt $" { fail "whatis value of x%y" }
+ timeout { fail "(timeout) whatis value of x%y" }
+ }
+
+
+
+send_gdb "whatis x=y\n"
+gdb_expect {
+ -re ".*type = int.*$gdb_prompt $" {
+ pass "whatis value of x=y"
+ }
+ -re ".*$gdb_prompt $" { fail "whatis value of x=y" }
+ timeout { fail "(timeout) whatis value of x=y" }
+ }
+
+
+send_gdb "whatis x+=2\n"
+gdb_expect {
+ -re ".*type = int.*$gdb_prompt $" {
+ pass "whatis value of x+=2"
+ }
+ -re ".*$gdb_prompt $" { fail "whatis value of x+=2" }
+ timeout { fail "(timeout) whatis value of x+=2" }
+ }
+
+
+send_gdb "whatis ++x\n"
+gdb_expect {
+ -re ".*type = int.*$gdb_prompt $" {
+ pass "whatis value of ++x"
+ }
+ -re ".*$gdb_prompt $" { fail "whatis value of ++x" }
+ timeout { fail "(timeout) whatis value of ++x" }
+ }
+
+send_gdb "whatis --x\n"
+gdb_expect {
+ -re ".*type = int.*$gdb_prompt $" {
+ pass "whatis value of --x"
+ }
+ -re ".*$gdb_prompt $" { fail "whatis value of --x" }
+ timeout { fail "(timeout) whatis value of --x" }
+ }
+
+send_gdb "whatis x++\n"
+gdb_expect {
+ -re ".*type = int.*$gdb_prompt $" {
+ pass "whatis value of x++"
+ }
+ -re ".*$gdb_prompt $" { fail "whatis value of x++" }
+ timeout { fail "(timeout) whatis value of x++" }
+ }
+
+send_gdb "whatis x--\n"
+gdb_expect {
+ -re ".*type = int.*$gdb_prompt $" {
+ pass "whatis value of x--"
+ }
+ -re ".*$gdb_prompt $" { fail "whatis value of x--" }
+ timeout { fail "(timeout) whatis value of x--" }
+ }
+
+gdb_exit
+return 0
diff --git a/gdb/testsuite/gdb.base/whatis.c b/gdb/testsuite/gdb.base/whatis.c
new file mode 100644
index 00000000000..6d8d1e64bb5
--- /dev/null
+++ b/gdb/testsuite/gdb.base/whatis.c
@@ -0,0 +1,269 @@
+/*
+ * Test file with lots of different types, for testing the
+ * "whatis" command.
+ */
+
+/*
+ * First the basic C types.
+ */
+
+#if !(defined (__STDC__) || defined (_AIX))
+#define signed /**/
+#endif
+
+char v_char;
+signed char v_signed_char;
+unsigned char v_unsigned_char;
+
+short v_short;
+signed short v_signed_short;
+unsigned short v_unsigned_short;
+
+int v_int;
+signed int v_signed_int;
+unsigned int v_unsigned_int;
+
+long v_long;
+signed long v_signed_long;
+unsigned long v_unsigned_long;
+
+float v_float;
+double v_double;
+
+/*
+ * Now some derived types, which are arrays, functions-returning,
+ * pointers, structures, unions, and enumerations.
+ */
+
+/**** arrays *******/
+
+char v_char_array[2];
+signed char v_signed_char_array[2];
+unsigned char v_unsigned_char_array[2];
+
+short v_short_array[2];
+signed short v_signed_short_array[2];
+unsigned short v_unsigned_short_array[2];
+
+int v_int_array[2];
+signed int v_signed_int_array[2];
+unsigned int v_unsigned_int_array[2];
+
+long v_long_array[2];
+signed long v_signed_long_array[2];
+unsigned long v_unsigned_long_array[2];
+
+float v_float_array[2];
+double v_double_array[2];
+
+/**** pointers *******/
+
+/* Make sure they still print as pointer to foo even there is a typedef
+ for that type. Test this not just for char *, which might be
+ a special case kludge in GDB (Unix system include files like to define
+ caddr_t), but for a variety of types. */
+typedef char *char_addr;
+typedef unsigned short *ushort_addr;
+typedef signed long *slong_addr;
+
+char *v_char_pointer;
+signed char *v_signed_char_pointer;
+unsigned char *v_unsigned_char_pointer;
+
+short *v_short_pointer;
+signed short *v_signed_short_pointer;
+unsigned short *v_unsigned_short_pointer;
+
+int *v_int_pointer;
+signed int *v_signed_int_pointer;
+unsigned int *v_unsigned_int_pointer;
+
+long *v_long_pointer;
+signed long *v_signed_long_pointer;
+unsigned long *v_unsigned_long_pointer;
+
+float *v_float_pointer;
+double *v_double_pointer;
+
+/**** structs *******/
+
+struct t_struct {
+ char v_char_member;
+ short v_short_member;
+ int v_int_member;
+ long v_long_member;
+ float v_float_member;
+ double v_double_member;
+} v_struct1;
+
+struct {
+ char v_char_member;
+ short v_short_member;
+ int v_int_member;
+ long v_long_member;
+ float v_float_member;
+ double v_double_member;
+} v_struct2;
+
+/**** unions *******/
+
+union t_union {
+ char v_char_member;
+ short v_short_member;
+ int v_int_member;
+ long v_long_member;
+ float v_float_member;
+ double v_double_member;
+} v_union;
+
+union {
+ char v_char_member;
+ short v_short_member;
+ int v_int_member;
+ long v_long_member;
+ float v_float_member;
+ double v_double_member;
+} v_union2;
+
+/*** Functions returning type ********/
+
+char v_char_func () { return(0); }
+signed char v_signed_char_func () { return (0); }
+unsigned char v_unsigned_char_func () { return (0); }
+
+short v_short_func () { return (0); }
+signed short v_signed_short_func () { return (0); }
+unsigned short v_unsigned_short_func () { return (0); }
+
+int v_int_func () { return (0); }
+signed int v_signed_int_func () { return (0); }
+unsigned int v_unsigned_int_func () { return (0); }
+
+long v_long_func () { return (0); }
+signed long v_signed_long_func () { return (0); }
+unsigned long v_unsigned_long_func () { return (0); }
+
+float v_float_func () { return (0.0); }
+double v_double_func () { return (0.0); }
+
+/**** Some misc more complicated things *******/
+
+struct link {
+ struct link *next;
+#ifdef __STDC__
+ struct link *(*linkfunc) (struct link *this, int flags);
+#else
+ struct link *(*linkfunc) ();
+#endif
+ struct t_struct stuff[1][2][3];
+} *s_link;
+
+union tu_link {
+ struct link *next;
+#ifdef __STDC__
+ struct link *(*linkfunc) (struct link *this, int flags);
+#else
+ struct link *(*linkfunc) ();
+#endif
+ struct t_struct stuff[1][2][3];
+} u_link;
+
+struct outer_struct {
+ int outer_int;
+ struct inner_struct {
+ int inner_int;
+ long inner_long;
+ }inner_struct_instance;
+ union inner_union {
+ int inner_union_int;
+ long inner_union_long;
+ }inner_union_instance;
+ long outer_long;
+} nested_su;
+
+/**** Enumerations *******/
+
+enum colors {red, green, blue} color;
+enum cars {chevy, ford, porsche} clunker;
+
+/***********/
+
+main ()
+{
+#ifdef usestubs
+ set_debug_traps();
+ breakpoint();
+#endif
+ /* Some linkers (e.g. on AIX) remove unreferenced variables,
+ so make sure to reference them. */
+ v_char = 0;
+ v_signed_char = 1;
+ v_unsigned_char = 2;
+
+ v_short = 3;
+ v_signed_short = 4;
+ v_unsigned_short = 5;
+
+ v_int = 6;
+ v_signed_int = 7;
+ v_unsigned_int = 8;
+
+ v_long = 9;
+ v_signed_long = 10;
+ v_unsigned_long = 11;
+
+ v_float = 100.0;
+ v_double = 200.0;
+
+
+ v_char_array[0] = v_char;
+ v_signed_char_array[0] = v_signed_char;
+ v_unsigned_char_array[0] = v_unsigned_char;
+
+ v_short_array[0] = v_short;
+ v_signed_short_array[0] = v_signed_short;
+ v_unsigned_short_array[0] = v_unsigned_short;
+
+ v_int_array[0] = v_int;
+ v_signed_int_array[0] = v_signed_int;
+ v_unsigned_int_array[0] = v_unsigned_int;
+
+ v_long_array[0] = v_long;
+ v_signed_long_array[0] = v_signed_long;
+ v_unsigned_long_array[0] = v_unsigned_long;
+
+ v_float_array[0] = v_float;
+ v_double_array[0] = v_double;
+
+ v_char_pointer = &v_char;
+ v_signed_char_pointer = &v_signed_char;
+ v_unsigned_char_pointer = &v_unsigned_char;
+
+ v_short_pointer = &v_short;
+ v_signed_short_pointer = &v_signed_short;
+ v_unsigned_short_pointer = &v_unsigned_short;
+
+ v_int_pointer = &v_int;
+ v_signed_int_pointer = &v_signed_int;
+ v_unsigned_int_pointer = &v_unsigned_int;
+
+ v_long_pointer = &v_long;
+ v_signed_long_pointer = &v_signed_long;
+ v_unsigned_long_pointer = &v_unsigned_long;
+
+ v_float_pointer = &v_float;
+ v_double_pointer = &v_double;
+
+ color = red;
+ clunker = porsche;
+
+ u_link.next = s_link;
+
+ v_union2.v_short_member = v_union.v_short_member;
+
+ v_struct1.v_char_member = 0;
+ v_struct2.v_char_member = 0;
+
+ nested_su.outer_int = 0;
+ return 0;
+}
diff --git a/gdb/testsuite/gdb.base/whatis.exp b/gdb/testsuite/gdb.base/whatis.exp
new file mode 100644
index 00000000000..1f4e8b35de8
--- /dev/null
+++ b/gdb/testsuite/gdb.base/whatis.exp
@@ -0,0 +1,393 @@
+# Copyright (C) 1988, 1990, 1991, 1992, 1995, 1997 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file was written by Rob Savoye. (rob@cygnus.com)
+
+if $tracelevel {
+ strace $tracelevel
+}
+
+#
+# test running programs
+#
+set prms_id 0
+set bug_id 0
+
+set testfile whatis
+set srcfile ${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+# Create and source the file that provides information about the compiler
+# used to compile the test case.
+if [get_compiler_info ${binfile}] {
+ return -1;
+}
+
+# Start with a fresh gdb.
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load $binfile
+
+# If we did not use the signed keyword when compiling the file, don't
+# expect GDB to know that char is signed.
+if $signed_keyword_not_used then {
+ set signed_char "char"
+} else {
+ set signed_char "signed char"
+}
+
+# Define a procedure to set up an xfail for all targets that put out a
+# `long' type as an `int' type.
+# Sun/Ultrix cc have this problem.
+# It was said that COFF targets can not distinguish int from long either.
+
+proc setup_xfail_on_long_vs_int {} {
+ global gcc_compiled
+
+ if {!$gcc_compiled} {
+ setup_xfail "*-sun-sunos4*" "*-*-ultrix*" "i*86-sequent-bsd*"
+ }
+}
+
+#
+# Test whatis command with basic C types
+#
+# The name printed now (as of 23 May 1993) is whatever name the compiler
+# uses in the stabs. So we need to deal with names both from gcc and
+# native compilers.
+#
+gdb_test "whatis v_char" \
+ "type = (unsigned char|char)" \
+ "whatis char"
+
+setup_xfail "a29k-*-*"
+if {!$gcc_compiled} then { setup_xfail "mips-sgi-irix*" }
+gdb_test "whatis v_signed_char" \
+ "type = $signed_char" \
+ "whatis signed char"
+
+gdb_test "whatis v_unsigned_char" \
+ "type = unsigned char" \
+ "whatis unsigned char"
+
+gdb_test "whatis v_short" \
+ "type = (short|short int)" \
+ "whatis short"
+
+gdb_test "whatis v_signed_short" \
+ "type = (short|short int|signed short|signed short int)" \
+ "whatis signed short"
+
+gdb_test "whatis v_unsigned_short" \
+ "type = (unsigned short|short unsigned int)" \
+ "whatis unsigned short"
+
+gdb_test "whatis v_int" \
+ "type = int" \
+ "whatis int"
+
+gdb_test "whatis v_signed_int" \
+ "type = (signed |)int" \
+ "whatis signed int"
+
+gdb_test "whatis v_unsigned_int" \
+ "type = unsigned int" \
+ "whatis unsigned int"
+
+setup_xfail_on_long_vs_int
+# AIX xlc gets this wrong and unsigned long right. Go figure.
+if {!$gcc_compiled} then {setup_xfail "rs6000-*-aix*"}
+gdb_test "whatis v_long" \
+ "type = (long|long int)" \
+ "whatis long"
+
+setup_xfail_on_long_vs_int
+# AIX xlc gets this wrong and unsigned long right. Go figure.
+if {!$gcc_compiled} then {setup_xfail "rs6000-*-aix*"}
+gdb_test "whatis v_signed_long" \
+ "type = (signed |)(long|long int)" \
+ "whatis signed long"
+
+setup_xfail_on_long_vs_int
+gdb_test "whatis v_unsigned_long" \
+ "type = (unsigned long|long unsigned int)" \
+ "whatis unsigned long"
+
+gdb_test "whatis v_float" \
+ "type = float" \
+ "whatis float"
+
+gdb_test "whatis v_double" \
+ "type = double" \
+ "whatis double"
+
+
+# test whatis command with arrays
+#
+# We already tested whether char prints as "char", so here we accept
+# "unsigned char", "signed char", and other perversions. No need for more
+# than one xfail for the same thing.
+gdb_test "whatis v_char_array" \
+ "type = (signed |unsigned |)char \\\[2\\\]" \
+ "whatis char array"
+
+gdb_test "whatis v_signed_char_array" \
+ "type = (signed |unsigned |)char \\\[2\\\]" \
+ "whatis signed char array"
+
+gdb_test "whatis v_unsigned_char_array" \
+ "type = unsigned char \\\[2\\\]" \
+ "whatis unsigned char array"
+
+gdb_test "whatis v_short_array" \
+ "type = (short|short int) \\\[2\\\]" \
+ "whatis short array"
+
+gdb_test "whatis v_signed_short_array" \
+ "type = (signed |)(short|short int) \\\[2\\\]" \
+ "whatis signed short array"
+
+gdb_test "whatis v_unsigned_short_array" \
+ "type = (unsigned short|short unsigned int) \\\[2\\\]" \
+ "whatis unsigned short array"
+
+gdb_test "whatis v_int_array" \
+ "type = int \\\[2\\\]" \
+ "whatis int array"
+
+gdb_test "whatis v_signed_int_array" \
+ "type = (signed |)int \\\[2\\\]" \
+ "whatis signed int array"
+
+gdb_test "whatis v_unsigned_int_array" \
+ "type = unsigned int \\\[2\\\]" \
+ "whatis unsigned int array"
+
+# We already tested whether long prints as long, so here we accept int
+# No need for more than one xfail for the same thing.
+gdb_test "whatis v_long_array" \
+ "type = (int|long|long int) \\\[2\\\]" \
+ "whatis long array"
+
+gdb_test "whatis v_signed_long_array" \
+ "type = (signed |)(int|long|long int) \\\[2\\\]" \
+ "whatis signed long array"
+
+gdb_test "whatis v_unsigned_long_array" \
+ "type = (unsigned (int|long|long int)|long unsigned int) \\\[2\\\]" \
+ "whatis unsigned long array"
+
+gdb_test "whatis v_float_array" \
+ "type = float \\\[2\\\]" \
+ "whatis float array"
+
+gdb_test "whatis v_double_array" \
+ "type = double \\\[2\\\]" \
+ "whatis double array"
+
+
+# test whatis command with pointers
+#
+# We already tested whether char prints as char, so accept various perversions
+# here. We especially want to make sure we test that it doesn't print as
+# caddr_t.
+gdb_test "whatis v_char_pointer" \
+ "type = (unsigned |signed |)char \\*" \
+ "whatis char pointer"
+
+gdb_test "whatis v_signed_char_pointer" \
+ "type = (unsigned |signed |)char \\*" \
+ "whatis signed char pointer"
+
+gdb_test "whatis v_unsigned_char_pointer" \
+ "type = unsigned char \\*" \
+ "whatis unsigned char pointer"
+
+gdb_test "whatis v_short_pointer" \
+ "type = (short|short int) \\*" \
+ "whatis short pointer"
+
+gdb_test "whatis v_signed_short_pointer" \
+ "type = (signed |)(short|short int) \\*" \
+ "whatis signed short pointer"
+
+gdb_test "whatis v_unsigned_short_pointer" \
+ "type = (unsigned short|short unsigned int) \\*" \
+ "whatis unsigned short pointer"
+
+gdb_test "whatis v_int_pointer" \
+ "type = int \\*" \
+ "whatis int pointer"
+
+gdb_test "whatis v_signed_int_pointer" \
+ "type = (signed |)int \\*" \
+ "whatis signed int pointer"
+
+gdb_test "whatis v_unsigned_int_pointer" \
+ "type = unsigned int \\*" \
+ "whatis unsigned int pointer"
+
+# We already tested whether long prints as long, so here we accept int
+gdb_test "whatis v_long_pointer" \
+ "type = (long|int|long int) \\*" \
+ "whatis long pointer"
+
+gdb_test "whatis v_signed_long_pointer" \
+ "type = (signed |)(long|int|long int) \\*" \
+ "whatis signed long pointer"
+
+gdb_test "whatis v_unsigned_long_pointer" \
+ "type = (unsigned (int|long|long int)|long unsigned int) \\*" \
+ "whatis unsigned long pointer"
+
+gdb_test "whatis v_float_pointer" \
+ "type = float \\*" \
+ "whatis float pointer"
+
+gdb_test "whatis v_double_pointer" \
+ "type = double \\*" \
+ "whatis double pointer"
+
+
+# test whatis command with structure types
+gdb_test "whatis v_struct1" \
+ "type = struct t_struct" \
+ "whatis named structure"
+
+gdb_test "whatis v_struct2" \
+ "type = struct \{...\}" \
+ "whatis unnamed structure"
+
+
+# test whatis command with union types
+gdb_test "whatis v_union" \
+ "type = union t_union" \
+ "whatis named union"
+
+gdb_test "whatis v_union2" \
+ "type = union \{...\}" \
+ "whatis unnamed union"
+
+
+
+# test whatis command with functions return type
+gdb_test "whatis v_char_func" \
+ "type = (signed |unsigned |)char \\(\\)" \
+ "whatis char function"
+
+gdb_test "whatis v_signed_char_func" \
+ "type = (signed |unsigned |)char \\(\\)" \
+ "whatis signed char function"
+
+gdb_test "whatis v_unsigned_char_func" \
+ "type = unsigned char \\(\\)" \
+ "whatis unsigned char function"
+
+gdb_test "whatis v_short_func" \
+ "type = short (int |)\\(\\)" \
+ "whatis short function"
+
+gdb_test "whatis v_signed_short_func" \
+ "type = (signed |)short (int |)\\(\\)" \
+ "whatis signed short function"
+
+gdb_test "whatis v_unsigned_short_func" \
+ "type = (unsigned short|short unsigned int) \\(\\)" \
+ "whatis unsigned short function"
+
+gdb_test "whatis v_int_func" \
+ "type = int \\(\\)" \
+ "whatis int function"
+
+gdb_test "whatis v_signed_int_func" \
+ "type = (signed |)int \\(\\)" \
+ "whatis signed int function"
+
+gdb_test "whatis v_unsigned_int_func" \
+ "type = unsigned int \\(\\)" \
+ "whatis unsigned int function"
+
+gdb_test "whatis v_long_func" \
+ "type = (long|int|long int) \\(\\)" \
+ "whatis long function"
+
+gdb_test "whatis v_signed_long_func" \
+ "type = (signed |)(int|long|long int) \\(\\)" \
+ "whatis signed long function"
+
+gdb_test "whatis v_unsigned_long_func" \
+ "type = (unsigned (int|long|long int)|long unsigned int) \\(\\)" \
+ "whatis unsigned long function"
+
+# Sun /bin/cc calls this a function returning double.
+if {!$gcc_compiled} then {setup_xfail "*-sun-sunos4*"}
+gdb_test "whatis v_float_func" \
+ "type = float \\(\\)" \
+ "whatis float function"
+
+gdb_test "whatis v_double_func" \
+ "type = double \\(\\)" \
+ "whatis double function" \
+
+
+# test whatis command with some misc complicated types
+gdb_test "whatis s_link" \
+ "type = struct link \\*" \
+ "whatis complicated structure"
+
+gdb_test "whatis u_link" \
+ "type = union tu_link" \
+ "whatis complicated union"
+
+
+# test whatis command with enumerations
+gdb_test "whatis clunker" \
+ "type = enum cars" \
+ "whatis enumeration"
+
+
+# test whatis command with nested struct and union
+gdb_test "whatis nested_su" \
+ "type = struct outer_struct" \
+ "whatis outer structure"
+
+gdb_test "whatis nested_su.outer_int" \
+ "type = int" \
+ "whatis outer structure member"
+
+gdb_test "whatis nested_su.inner_struct_instance" \
+ "type = struct inner_struct" \
+ "whatis inner structure"
+
+gdb_test "whatis nested_su.inner_struct_instance.inner_int" \
+ "type = int" \
+ "whatis inner structure member"
+
+gdb_test "whatis nested_su.inner_union_instance" \
+ "type = union inner_union" \
+ "whatis inner union"
+
+gdb_test "whatis nested_su.inner_union_instance.inner_union_int" \
+ "type = int" \
+ "whatis inner union member"
diff --git a/gdb/testsuite/gdb.c++/Makefile.in b/gdb/testsuite/gdb.c++/Makefile.in
new file mode 100644
index 00000000000..13a1234a890
--- /dev/null
+++ b/gdb/testsuite/gdb.c++/Makefile.in
@@ -0,0 +1,20 @@
+VPATH = @srcdir@
+srcdir = @srcdir@
+
+PROGS = anon-union compiler cplusfuncs derivation inherit local \
+ member-ptr method misc \
+ overload ovldbreak ref-types ref-types2 templates userdef virtfunc
+
+all:
+ @echo "Nothing to be done for all..."
+
+#### host, target, and site specific Makefile frags come in here.
+
+clean mostlyclean:
+ -rm -f *.ci *.o ${OBJS} ${PROGS} *~ core
+
+distclean maintainer-clean realclean: clean
+ -rm -f Makefile config.status config.log
+
+Makefile: $(srcdir)/Makefile.in $(srcdir)/configure.in
+ $(SHELL) ./config.status --recheck
diff --git a/gdb/testsuite/gdb.c++/anon-union.cc b/gdb/testsuite/gdb.c++/anon-union.cc
new file mode 100644
index 00000000000..c58a3068223
--- /dev/null
+++ b/gdb/testsuite/gdb.c++/anon-union.cc
@@ -0,0 +1,54 @@
+
+struct Foo {
+ union {
+ int zero;
+ unsigned int one;
+ } num1;
+
+ union {
+ int pebble;
+ struct {
+ int rock;
+ unsigned int rock2;
+ } x;
+ union {
+ int qux;
+ unsigned int mux;
+ };
+ unsigned int boulder;
+ };
+ union {
+ int paper;
+ unsigned int cloth;
+ };
+ union {
+ int two;
+ unsigned int three;
+ } num2;
+};
+
+union Bar {
+ int x;
+ unsigned int y;
+};
+
+Foo foo;
+Bar bar;
+
+int main()
+{
+ foo.paper = 33;
+ foo.pebble = 44;
+ foo.mux = 55;
+
+ bar.x = 33;
+
+ union
+ {
+ int z;
+ unsigned int w;
+ };
+
+ w = 45;
+
+}
diff --git a/gdb/testsuite/gdb.c++/anon-union.exp b/gdb/testsuite/gdb.c++/anon-union.exp
new file mode 100644
index 00000000000..83171a27e85
--- /dev/null
+++ b/gdb/testsuite/gdb.c++/anon-union.exp
@@ -0,0 +1,337 @@
+# Copyright (C) 1998 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+#
+# Tests for anonymous union support
+# Written by Satish Pai <pai@apollo.hp.com> 1997-08-19
+
+# This file is part of the gdb testsuite
+
+if $tracelevel then {
+ strace $tracelevel
+ }
+
+#
+# test running programs
+#
+
+set prms_id 0
+set bug_id 0
+
+set testfile "anon-union"
+set srcfile ${testfile}.cc
+set binfile ${objdir}/${subdir}/${testfile}
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug c++}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+# Start with a fresh gdb
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+
+if ![runto_main] then {
+ perror "couldn't run to breakpoint"
+ continue
+}
+
+send_gdb "set width 0\n"
+gdb_expect -re "$gdb_prompt $"
+
+#send_gdb "ptype foo\n"
+#gdb_expect {
+# -re "\r\n$gdb_prompt $" {
+# pass "ptype foo"
+# }
+# -re ".*$gdb_prompt $" { fail "ptype foo" }
+# timeout { fail "(timeout) ptype foo" }
+#}
+
+#send_gdb "ptype bar\n"
+#gdb_expect {
+# -re "\r\n$gdb_prompt $" {
+# pass "ptype foo"
+# }
+# -re ".*$gdb_prompt $" { fail "ptype foo" }
+# timeout { fail "(timeout) ptype foo" }
+#}
+
+# NOTE: Add -- ptype foo.x, etc. when things are working
+
+# Print out the big anon union.
+send_gdb "print foo\n"
+gdb_expect {
+ -re "\\$\[0-9\]* = \{num1 = \{zero = 0, one = 0\}, \{pebble = 0, x = \{rock = 0, rock2 = 0\}, \{qux = 0, mux = 0\}, boulder = 0\}, \{paper = 0, cloth = 0\}, num2 = \{two = 0, three = 0\}\}\r\n$gdb_prompt $" {
+ pass "print foo 1"
+ }
+ -re ".*$gdb_prompt $" { fail "print foo 1" }
+ timeout { fail "(timeout) print foo 1" }
+}
+
+# Step over assignment to member
+
+send_gdb "next\n"
+gdb_expect {
+ -re "41\[ \t\]*foo.pebble = 44;\r\n$gdb_prompt $" {
+ pass "next 1"
+ }
+ -re ".*$gdb_prompt $" { fail "next 1" }
+ timeout { fail "(timeout) next 1" }
+}
+
+# Now print out anon union again
+send_gdb "print foo\n"
+gdb_expect {
+ -re "\\$\[0-9\]* = \{num1 = \{zero = 0, one = 0\}, \{pebble = 0, x = \{rock = 0, rock2 = 0\}, \{qux = 0, mux = 0\}, boulder = 0\}, \{paper = 33, cloth = 33\}, num2 = \{two = 0, three = 0\}\}\r\n$gdb_prompt $" {
+ pass "print foo 2"
+ }
+ -re ".*$gdb_prompt $" { fail "print foo 2" }
+ timeout { fail "(timeout) print foo 2" }
+}
+
+# Modify the member just set
+send_gdb "set var foo.cloth = 35\n"
+gdb_expect {
+ -re "\r\n$gdb_prompt $" {
+ pass "set var foo.cloth"
+ }
+ timeout { fail "(timeout) set var foo.cloth" }
+}
+
+# Now print out anon union again to see if the right member was set
+send_gdb "print foo\n"
+gdb_expect {
+ -re "\\$\[0-9\]* = \{num1 = \{zero = 0, one = 0\}, \{pebble = 0, x = \{rock = 0, rock2 = 0\}, \{qux = 0, mux = 0\}, boulder = 0\}, \{paper = 35, cloth = 35\}, num2 = \{two = 0, three = 0\}\}\r\n$gdb_prompt $" {
+ pass "print foo 3"
+ }
+ -re ".*$gdb_prompt $" { fail "print foo 3" }
+ timeout { fail "(timeout) print foo 3" }
+}
+
+
+# Step over next assignment to member
+
+send_gdb "next\n"
+gdb_expect {
+ -re "42\[ \t\]*foo.mux = 55;\r\n$gdb_prompt $" {
+ pass "next 2"
+ }
+ -re ".*$gdb_prompt $" { fail "next 2" }
+ timeout { fail "(timeout) next 2" }
+}
+
+# Now print out anon union again
+send_gdb "print foo\n"
+gdb_expect {
+ -re "\\$\[0-9\]* = \{num1 = \{zero = 0, one = 0\}, \{pebble = 44, x = \{rock = 44, rock2 = 0\}, \{qux = 44, mux = 44\}, boulder = 44\}, \{paper = 35, cloth = 35\}, num2 = \{two = 0, three = 0\}\}\r\n$gdb_prompt $" {
+ pass "print foo 4"
+ }
+ -re ".*$gdb_prompt $" { fail "print foo 4" }
+ timeout { fail "(timeout) print foo 4" }
+}
+
+# Modify the member just set
+send_gdb "set var foo.pebble = 45\n"
+gdb_expect {
+ -re "\r\n$gdb_prompt $" {
+ pass "set var foo.pebble"
+ }
+ timeout { fail "(timeout) set var foo.pebble" }
+}
+
+# Now print out anon union again to see if the right member was set
+send_gdb "print foo\n"
+gdb_expect {
+ -re "\\$\[0-9\]* = \{num1 = \{zero = 0, one = 0\}, \{pebble = 45, x = \{rock = 45, rock2 = 0\}, \{qux = 45, mux = 45\}, boulder = 45\}, \{paper = 35, cloth = 35\}, num2 = \{two = 0, three = 0\}\}\r\n$gdb_prompt $" {
+ pass "print foo 5"
+ }
+ -re ".*$gdb_prompt $" { fail "print foo 5" }
+ timeout { fail "(timeout) print foo 5" }
+}
+
+# Modify another member at a different level
+send_gdb "set var foo.qux = 46\n"
+gdb_expect {
+ -re "\r\n$gdb_prompt $" {
+ pass "set var foo.qux"
+ }
+ timeout { fail "(timeout) set var foo.qux" }
+}
+
+# Now print out anon union again to see if the right member was set
+send_gdb "print foo\n"
+gdb_expect {
+ -re "\\$\[0-9\]* = \{num1 = \{zero = 0, one = 0\}, \{pebble = 46, x = \{rock = 46, rock2 = 0\}, \{qux = 46, mux = 46\}, boulder = 46\}, \{paper = 35, cloth = 35\}, num2 = \{two = 0, three = 0\}\}\r\n$gdb_prompt $" {
+ pass "print foo 6"
+ }
+ -re ".*$gdb_prompt $" { fail "print foo 6" }
+ timeout { fail "(timeout) print foo 6" }
+}
+
+# Modify the member at another level, but not the first one in the union
+send_gdb "set var foo.mux = 47\n"
+gdb_expect {
+ -re "\r\n$gdb_prompt $" {
+ pass "set var foo.mux"
+ }
+ timeout { fail "(timeout) set var foo.mux" }
+}
+
+# Now print out anon union again to see if things worked
+send_gdb "print foo\n"
+gdb_expect {
+ -re "\\$\[0-9\]* = \{num1 = \{zero = 0, one = 0\}, \{pebble = 47, x = \{rock = 47, rock2 = 0\}, \{qux = 47, mux = 47\}, boulder = 47\}, \{paper = 35, cloth = 35\}, num2 = \{two = 0, three = 0\}\}\r\n$gdb_prompt $" {
+ pass "print foo 7"
+ }
+ -re ".*$gdb_prompt $" { fail "print foo 7" }
+ timeout { fail "(timeout) print foo 7" }
+}
+
+# Modify a member of a struct in an anon union
+send_gdb "set var foo.x.rock = 48\n"
+gdb_expect {
+ -re "\r\n$gdb_prompt $" {
+ pass "set var foo.x.rock"
+ }
+ timeout { fail "(timeout) set var foo.x.rock" }
+}
+
+# Now print out anon union again to see if things worked
+send_gdb "print foo\n"
+gdb_expect {
+ -re "\\$\[0-9\]* = \{num1 = \{zero = 0, one = 0\}, \{pebble = 48, x = \{rock = 48, rock2 = 0\}, \{qux = 48, mux = 48\}, boulder = 48\}, \{paper = 35, cloth = 35\}, num2 = \{two = 0, three = 0\}\}\r\n$gdb_prompt $" {
+ pass "print foo 8"
+ }
+ -re ".*$gdb_prompt $" { fail "print foo 8" }
+ timeout { fail "(timeout) print foo 8" }
+}
+
+# Modify a member of a struct in an anon union, but something
+# that doesn't alias to some other union member
+send_gdb "set var foo.x.rock2 = 49\n"
+gdb_expect {
+ -re "\r\n$gdb_prompt $" {
+ pass "set var foo.x.rock2"
+ }
+ timeout { fail "(timeout) set var foo.x.rock2" }
+}
+
+# Now print out anon union again to see if things worked
+send_gdb "print foo\n"
+gdb_expect {
+ -re "\\$\[0-9\]* = \{num1 = \{zero = 0, one = 0\}, \{pebble = 48, x = \{rock = 48, rock2 = 49\}, \{qux = 48, mux = 48\}, boulder = 48\}, \{paper = 35, cloth = 35\}, num2 = \{two = 0, three = 0\}\}\r\n$gdb_prompt $" {
+ pass "print foo 9"
+ }
+ -re ".*$gdb_prompt $" { fail "print foo 9" }
+ timeout { fail "(timeout) print foo 9" }
+}
+
+
+# Step over next two assignments
+send_gdb "next 2\n"
+gdb_expect {
+ -re "52\[ \t\]*w = 45;\r\n$gdb_prompt $" {
+ pass "next 3"
+ }
+ -re ".*$gdb_prompt $" { fail "next 3" }
+ timeout { fail "(timeout) next 3" }
+}
+
+# Tests for anon unions that are not members of a class or struct
+
+# w is not yet initialized; it contains garbage
+#send_gdb "print w\n"
+#gdb_expect {
+# -re "\\$\[0-9\]* = 0\r\n$gdb_prompt $" {
+# pass "print w 1"
+# }
+# -re ".*$gdb_prompt $" { fail "print w 1" }
+# timeout { fail "(timeout) print w 1" }
+#}
+#
+# z is not yet initialized; it contains garbage
+#send_gdb "print z\n"
+#gdb_expect {
+# -re "\\$\[0-9\]* = 0\r\n$gdb_prompt $" {
+# pass "print z 1"
+# }
+# -re ".*$gdb_prompt $" { fail "print z 1" }
+# timeout { fail "(timeout) print z 1" }
+#}
+
+# Step over next assignment to w
+send_gdb "next\n"
+gdb_expect {
+ -re "54\[ \t\]*\}\r\n$gdb_prompt $" {
+ pass "next 4"
+ }
+ -re ".*$gdb_prompt $" { fail "next 4" }
+ timeout { fail "(timeout) next 4" }
+}
+
+# See if the change in value is noticed
+send_gdb "print w\n"
+gdb_expect {
+ -re "\\$\[0-9\]* = 45\r\n$gdb_prompt $" {
+ pass "print w 2"
+ }
+ -re ".*$gdb_prompt $" { fail "print w 2" }
+ timeout { fail "(timeout) print w 2" }
+}
+
+# See if z shows the same value
+send_gdb "print z\n"
+gdb_expect {
+ -re "\\$\[0-9\]* = 45\r\n$gdb_prompt $" {
+ pass "print z 2"
+ }
+ -re ".*$gdb_prompt $" { fail "print z 2" }
+ timeout { fail "(timeout) print z 2" }
+}
+
+# Set the anon union member
+send_gdb "set var z = 27\n"
+gdb_expect {
+ -re "\r\n$gdb_prompt $" {
+ pass "set var z"
+ }
+ timeout { fail "(timeout) set var z" }
+}
+
+# See if the change in value is noticed
+send_gdb "print w\n"
+gdb_expect {
+ -re "\\$\[0-9\]* = 27\r\n$gdb_prompt $" {
+ pass "print w 3"
+ }
+ -re ".*$gdb_prompt $" { fail "print w 3" }
+ timeout { fail "(timeout) print w 3" }
+}
+
+# See if z shows the same value
+send_gdb "print z\n"
+gdb_expect {
+ -re "\\$\[0-9\]* = 27\r\n$gdb_prompt $" {
+ pass "print z 3"
+ }
+ -re ".*$gdb_prompt $" { fail "print z 3" }
+ timeout { fail "(timeout) print z 3" }
+}
diff --git a/gdb/testsuite/gdb.c++/classes.exp b/gdb/testsuite/gdb.c++/classes.exp
new file mode 100644
index 00000000000..5e97cb4eb4c
--- /dev/null
+++ b/gdb/testsuite/gdb.c++/classes.exp
@@ -0,0 +1,850 @@
+# Copyright (C) 1992, 1994, 1995, 1997 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file was written by Fred Fish. (fnf@cygnus.com)
+
+set ws "\[\r\n\t \]+"
+set nl "\[\r\n\]+"
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+
+# Check to see if we have an executable to test. If not, then either we
+# haven't tried to compile one, or the compilation failed for some reason.
+# In either case, just notify the user and skip the tests in this file.
+
+set testfile "misc"
+set srcfile ${testfile}.cc
+set binfile ${objdir}/${subdir}/${testfile}
+
+# Create and source the file that provides information about the compiler
+# used to compile the test case.
+
+if [get_compiler_info ${binfile} "c++"] {
+ return -1
+}
+
+# if we are on HPUX and we are not compiled with gcc, then skip these tests.
+
+if [istarget hppa*-*-hpux*] {
+ if {!$gcc_compiled} {
+ continue
+ }
+}
+
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug c++}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+#
+# Test ptype of class objects.
+#
+
+proc test_ptype_class_objects {} {
+ global gdb_prompt
+ global ws
+ global nl
+
+ # Note that struct members are public by default, so we don't print
+ # "public:" for the public members of structs.
+ # Accept it as an expected failure if gdb just fails to distinguish between
+ # class and struct, and everything else is OK.
+
+ send_gdb "ptype struct default_public_struct\n"
+ gdb_expect {
+ -re "type = struct default_public_struct \{${ws}int a;${ws}int b;$nl\}$nl$gdb_prompt $" {
+ pass "ptype struct default_public_struct"
+ }
+ -re "type = class default_public_struct \{$nl.*int a;${ws}int b;$nl.*\}$nl$gdb_prompt $" {
+ setup_xfail "*-*-*"
+ fail "ptype struct default_public_struct"
+ }
+ -re ".*$gdb_prompt $" { fail "ptype struct default_public_struct" }
+ timeout { fail "ptype struct default_public_struct (timeout)" ; return }
+ }
+
+ # Note that struct members are public by default, so we don't print
+ # "public:" for the public members of structs.
+ # Accept it as an expected failure if gdb just fails to distinguish between
+ # class and struct, and everything else is OK.
+
+ send_gdb "ptype struct explicit_public_struct\n"
+ gdb_expect {
+ -re "type = struct explicit_public_struct \{${ws}int a;${ws}int b;$nl.*\}$nl$gdb_prompt $" {
+ pass "ptype struct explicit_public_struct"
+ }
+ -re "type = class explicit_public_struct \{$nl.*int a;${ws}int b;$nl.*\}$nl$gdb_prompt $" {
+ setup_xfail "*-*-*"
+ fail "ptype struct explicit_public_struct"
+ }
+ -re ".*$gdb_prompt $" { fail "ptype struct explicit_public_struct" }
+ timeout { fail "ptype struct explicit_public_struct (timeout)" ; return }
+ }
+
+ # Accept it as an expected failure if gdb just fails to distinguish between
+ # class and struct, and everything else is OK.
+
+ setup_xfail_format "DWARF 1"
+ send_gdb "ptype struct protected_struct\n"
+ gdb_expect {
+ -re "type = struct protected_struct \{${ws}protected:${ws}int a;${ws}int b;$nl\}$nl$gdb_prompt $" {
+ pass "ptype struct protected_struct (FIXME)"
+ }
+ -re "type = class protected_struct \{${ws}protected:${ws}int a;${ws}int b;$nl.*\}$nl$gdb_prompt $" {
+ setup_xfail "*-*-*"
+ fail "ptype struct protected_struct (FIXME)"
+ }
+ -re ".*$gdb_prompt $" { fail "ptype struct protected_struct" }
+ timeout { fail "ptype struct protected_struct (timeout)" ; return }
+ }
+
+ # Accept it as an expected failure if gdb just fails to distinguish between
+ # class and struct, and everything else is OK.
+
+ setup_xfail_format "DWARF 1"
+ send_gdb "ptype struct private_struct\n"
+ gdb_expect {
+ -re "type = struct private_struct \{${ws}private:${ws}int a;${ws}int b;$nl\}$nl$gdb_prompt $" {
+ pass "ptype struct private_struct (FIXME)"
+ }
+ -re "type = class private_struct \{${ws}private:${ws}int a;${ws}int b;$nl.*\}$nl$gdb_prompt $" {
+ setup_xfail "*-*-*"
+ fail "ptype struct private_struct (FIXME)"
+ }
+ -re ".*$gdb_prompt $" { fail "ptype struct private_struct" }
+ timeout { fail "ptype struct private_struct (timeout)" ; return }
+ }
+
+ # Accept it as an expected failure if gdb just fails to distinguish between
+ # class and struct, and everything else is OK.
+
+ setup_xfail_format "DWARF 1"
+ send_gdb "ptype struct mixed_protection_struct\n"
+ gdb_expect {
+ -re "type = struct mixed_protection_struct \{${ws}int a;${ws}int b;${ws}private:${ws}int c;${ws}int d;${ws}protected:${ws}int e;${ws}int f;${ws}public:${ws}int g;${ws}private:${ws}int h;${ws}protected:${ws}int i;$nl\}$nl$gdb_prompt $" {
+ pass "ptype struct mixed_protection_struct (FIXME)"
+ }
+ -re "type = class mixed_protection_struct \{${ws}public:${ws}int a;${ws}int b;${ws}private:${ws}int c;${ws}int d;${ws}protected:${ws}int e;${ws}int f;${ws}public:${ws}int g;${ws}private:${ws}int h;${ws}protected:${ws}int i;$nl.*\}$nl$gdb_prompt $" {
+ setup_xfail "*-*-*"
+ fail "ptype struct mixed_protection_struct (FIXME)"
+ }
+ -re ".*$gdb_prompt $" { fail "ptype struct mixed_protection_struct" }
+ timeout { fail "ptype struct mixed_protection_struct (timeout)" ; return }
+ }
+
+ # Accept it as an expected failure if gdb just fails to distinguish between
+ # class and struct, and everything else is OK.
+
+ send_gdb "ptype class public_class\n"
+ gdb_expect {
+ -re "type = class public_class \{${ws}public:${ws}int a;${ws}int b;$nl.*\}$nl$gdb_prompt $" {
+ pass "ptype class public_class (FIXME)"
+ }
+ -re "type = struct public_class \{${ws}int a;${ws}int b;$nl\}$nl$gdb_prompt $" {
+ setup_xfail "*-*-*"
+ fail "ptype class public_class (FIXME)"
+ }
+ -re ".*$gdb_prompt $" { fail "ptype class public_class" }
+ timeout { fail "ptype class public_class (timeout)" ; return }
+ }
+
+ send_gdb "ptype class protected_class\n"
+ gdb_expect {
+ -re "type = class protected_class \{${ws}protected:${ws}int a;${ws}int b;$nl.*\}$nl$gdb_prompt $" {
+ pass "ptype class protected_class"
+ }
+ -re "type = struct protected_class \{${ws}int a;${ws}int b;$nl\}$nl$gdb_prompt $" {
+ setup_xfail "*-*-*"
+ fail "ptype class protected_class"
+ }
+ -re ".*$gdb_prompt $" { fail "ptype class protected_class" }
+ timeout { fail "ptype class protected_class (timeout)" ; return }
+ }
+
+ # Accept it as an expected failure if gdb just emits a superflous "private:"
+ # attribute, since classes default to private and for consistency with
+ # structs (where we don't print the "public:" attribute) we don't print
+ # the "private:" attribute.
+
+ setup_xfail_format "DWARF 1"
+ send_gdb "ptype class default_private_class\n"
+ gdb_expect {
+ -re "type = class default_private_class \{${ws}int a;${ws}int b;$nl.*\}$nl$gdb_prompt $" {
+ pass "ptype class default_private_class (FIXME)"
+ }
+ -re "type = class default_private_class \{${ws}private:${ws}int a;${ws}int b;$nl.*\}$nl$gdb_prompt $" {
+ setup_xfail "*-*-*"
+ fail "ptype class default_private_class (FIXME)"
+ }
+ -re ".*$gdb_prompt $" { fail "ptype class default_private_class" }
+ timeout { fail "ptype class default_private_class (timeout)" ; return }
+ }
+
+ send_gdb "ptype class explicit_private_class\n"
+ gdb_expect {
+ -re "type = class explicit_private_class \{${ws}private:${ws}int a;${ws}int b;$nl.*\}$nl$gdb_prompt $" {
+ pass "ptype class explicit_private_class"
+ }
+ -re "type = struct explicit_private_class \{${ws}int a;${ws}int b;$nl.*\}$nl$gdb_prompt $" {
+ setup_xfail "*-*-*"
+ fail "ptype class explicit_private_class"
+ }
+ -re ".*$gdb_prompt $" { fail "ptype class explicit_private_class" }
+ timeout { fail "ptype class explicit_private_class (timeout)" ; return }
+ }
+
+ send_gdb "ptype class mixed_protection_class\n"
+ gdb_expect {
+ -re "type = class mixed_protection_class \{${ws}public:${ws}int a;${ws}int b;${ws}private:${ws}int c;${ws}int d;${ws}protected:${ws}int e;${ws}int f;${ws}public:${ws}int g;${ws}private:${ws}int h;${ws}protected:${ws}int i;$nl.*\}$nl$gdb_prompt $" {
+ pass "ptype class mixed_protection_class"
+ }
+ -re "type = struct mixed_protection_class \{${ws}int a;${ws}int b;${ws}int c;${ws}int d;${ws}int e;${ws}int f;${ws}int g;${ws}int h;${ws}int i;$nl.*\}$nl$gdb_prompt $" {
+ setup_xfail "*-*-*"
+ fail "ptype class mixed_protection_class"
+ }
+ -re ".*$gdb_prompt $" { fail "ptype class mixed_protection_class" }
+ timeout { fail "ptype class mixed_protection_class (timeout)" ; return }
+ }
+
+ # This class does not use any C++-specific features, so it's fine for
+ # it to print as "struct".
+ send_gdb "ptype class A\n"
+ gdb_expect {
+ -re "type = (class|struct) A \{(${ws}public:|)${ws}int a;${ws}int x;((${ws}A & operator=\\(A const &\\);)|(${ws}A\\(A const &\\);)|(${ws}A\\(void\\);))*${ws}\}$nl$gdb_prompt $" {
+ pass "ptype class A"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "ptype class A"
+ }
+ timeout {
+ fail "ptype class A (timeout)"
+ return
+ }
+ }
+
+ setup_xfail_format "DWARF 1"
+ send_gdb "ptype class B\n"
+ gdb_expect {
+ -re "type = class B : public A \{${ws}public:${ws}int b;${ws}int x;${ws}B & operator=\\(B const &\\);${ws}B\\(B const &\\);${ws}B\\(void\\);${ws}\}$nl$gdb_prompt $" {
+ pass "ptype class B"
+ }
+ -re "type = class B : public A \{${ws}public:${ws}int b;${ws}int x;((${ws}B & operator=\\(B const &\\);)|(${ws}B\\(B const &\\);)|(${ws}B\\(void\\);))*${ws}\}$nl$gdb_prompt $" {
+ pass "ptype class B (obsolescent gcc or gdb)"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "ptype class B"
+ }
+ timeout {
+ fail "ptype class B (timeout)"
+ return
+ }
+ }
+
+ setup_xfail_format "DWARF 1"
+ send_gdb "ptype class C\n"
+ gdb_expect {
+ -re "type = class C : public A \{${ws}public:${ws}int c;${ws}int x;${ws}C & operator=\\(C const &\\);${ws}C\\(C const &\\);${ws}C\\(void\\);${ws}\}$nl$gdb_prompt $" {
+ pass "ptype class C"
+ }
+ -re "type = class C : public A \{${ws}public:${ws}int c;${ws}int x;((${ws}C & operator=\\(C const &\\);)|(${ws}C\\(C const &\\);)|(${ws}C\\(void\\);))*${ws}\}$nl$gdb_prompt $" {
+ pass "ptype class C (obsolescent gcc or gdb)"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "ptype class C"
+ }
+ timeout {
+ fail "ptype class C (timeout)"
+ return
+ }
+ }
+
+ setup_xfail_format "DWARF 1"
+ send_gdb "ptype class D\n"
+ gdb_expect {
+ -re "type = class D : public B, public C \{${ws}public:${ws}int d;${ws}int x;${ws}D & operator=\\(D const &\\);${ws}D\\(D const &\\);${ws}D\\(void\\);${ws}\}$nl$gdb_prompt $" {
+ pass "ptype class D"
+ }
+ -re "type = class D : public B, public C \{${ws}public:${ws}int d;${ws}int x;((${ws}D & operator=\\(D const &\\);)|(${ws}D\\(D const &\\);)|(${ws}D\\(void\\);))*${ws}\}$nl$gdb_prompt $" {
+ pass "ptype class D (obsolescent gcc or gdb)"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "ptype class D"
+ }
+ timeout {
+ fail "ptype class D (timeout)"
+ return
+ }
+ }
+
+ setup_xfail_format "DWARF 1"
+ send_gdb "ptype class E\n"
+ gdb_expect {
+ -re "type = class E : public D \{${ws}public:${ws}int e;${ws}int x;${ws}E & operator=\\(E const &\\);${ws}E\\(E const &\\);${ws}E\\(void\\);${ws}\}$nl$gdb_prompt $" {
+ pass "ptype class E"
+ }
+ -re "type = class E : public D \{${ws}public:${ws}int e;${ws}int x;((${ws}E & operator=\\(E const &\\);)|(${ws}E\\(E const &\\);)|(${ws}E\\(void\\);))*${ws}\}$nl$gdb_prompt $" {
+ pass "ptype class E"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "ptype class E"
+ }
+ timeout {
+ fail "ptype class E (timeout)"
+ return
+ }
+ }
+
+ send_gdb "ptype class vA\n"
+ gdb_expect {
+ -re "type = (class|struct) vA \{(${ws}public:|)${ws}int va;${ws}int vx;${ws}vA & operator=\\(vA const &\\);${ws}vA\\(vA const &\\);${ws}vA\\(void\\);${ws}\}$nl$gdb_prompt $" {
+ pass "ptype class vA"
+ }
+ -re "type = (class|struct) vA \{(${ws}public:|)${ws}int va;${ws}int vx;((${ws}vA & operator=\\(vA const &\\);)|(${ws}vA\\(vA const &\\);)|(${ws}vA\\(void\\);))*${ws}\}$nl$gdb_prompt $" {
+ pass "ptype class vA (obsolescent gcc or gdb)"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "ptype class vA"
+ }
+ timeout {
+ fail "ptype class vA (timeout)"
+ return
+ }
+ }
+
+ # Accept the form with embedded GNU style mangled virtual table constructs
+ # for now, but with a FIXME. At some future point, gdb should use a
+ # portable representation for the virtual table constructs.
+
+ setup_xfail_format "DWARF 1"
+ send_gdb "ptype class vB\n"
+ gdb_expect {
+ -re "type = class vB : public virtual vA \{${ws}private:${ws}vA \\*_vb.vA;${ws}public:${ws}int vb;${ws}int vx;${ws}vB & operator=\\(vB const &\\);${ws}vB\\(int, vB const &\\);${ws}vB\\(int\\);${ws}\}$nl$gdb_prompt $" {
+ setup_xfail "*-*-*"
+ fail "ptype class vB (FIXME: non-portable virtual table constructs)"
+ }
+ -re "type = class vB : public virtual vA \{${ws}private:${ws}vA \\*_vb.vA;${ws}public:${ws}int vb;${ws}int vx;((${ws}vB & operator=\\(vB const &\\);)|(${ws}vB\\(int, vB const &\\);)|(${ws}vB\\(int\\);))*${ws}\}$nl$gdb_prompt $" {
+ setup_xfail "*-*-*"
+ fail "ptype class vB (FIXME) (obsolescent gcc or gdb)"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "ptype class vB"
+ }
+ timeout {
+ fail "ptype class vB (timeout)"
+ return
+ }
+ }
+
+ # Accept the form with embedded GNU style mangled virtual table constructs
+ # for now, but with a FIXME. At some future point, gdb should use a
+ # portable representation for the virtual table constructs.
+
+ setup_xfail_format "DWARF 1"
+ send_gdb "ptype class vC\n"
+ gdb_expect {
+ -re "type = class vC : public virtual vA \{${ws}private:${ws}vA \\*_vb.vA;${ws}public:${ws}int vc;${ws}int vx;${ws}vC & operator=\\(vC const &\\);${ws}vC\\(int, vC const &\\);${ws}vC\\(int\\);${ws}\}$nl$gdb_prompt $" {
+ setup_xfail "*-*-*"
+ fail "ptype class vC (FIXME: non-portable virtual table constructs)"
+ }
+ -re "type = class vC : public virtual vA \{${ws}private:${ws}vA \\*_vb.vA;${ws}public:${ws}int vc;${ws}int vx;((${ws}vC & operator=\\(vC const &\\);)|(${ws}vC\\(int, vC const &\\);)|(${ws}vC\\(int\\);))*${ws}\}$nl$gdb_prompt $" {
+ setup_xfail "*-*-*"
+ fail "ptype class vC (FIXME) (obsolescent gcc or gdb)"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "ptype class vC"
+ }
+ timeout {
+ fail "ptype class vC (timeout)"
+ return
+ }
+ }
+
+ # Accept the form with embedded GNU style mangled virtual table constructs
+ # for now, but with a FIXME. At some future point, gdb should use a
+ # portable representation for the virtual table constructs.
+
+ setup_xfail_format "DWARF 1"
+ send_gdb "ptype class vD\n"
+ gdb_expect {
+ -re "type = class vD : public virtual vB, public virtual vC \{${ws}private:${ws}vC \\*_vb.vC;${ws}vB \\*_vb.vB;${ws}public:${ws}int vd;${ws}int vx;${ws}vD & operator=\\(vD const &\\);${ws}vD\\(int, vD const &\\);${ws}vD\\(int\\);${ws}\}$nl$gdb_prompt $" {
+ setup_xfail "*-*-*"
+ fail "ptype class vD (FIXME: non-portable virtual table constructs)"
+ }
+ -re "type = class vD : public virtual vB, public virtual vC \{${ws}private:${ws}vC \\*_vb.vC;${ws}vB \\*_vb.vB;${ws}public:${ws}int vd;${ws}int vx;((${ws}vD & operator=\\(vD const &\\);)|(${ws}vD\\(int, vD const &\\);)|(${ws}vD\\(int\\);))*${ws}\}$nl$gdb_prompt $" {
+ setup_xfail "*-*-*"
+ fail "ptype class vD (FIXME) (obsolescent gcc or gdb)"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "ptype class vD"
+ }
+ timeout {
+ fail "ptype class vD (timeout)"
+ return
+ }
+ }
+
+ # Accept the form with embedded GNU style mangled virtual table constructs
+ # for now, but with a FIXME. At some future point, gdb should use a
+ # portable representation for the virtual table constructs.
+
+ setup_xfail_format "DWARF 1"
+ send_gdb "ptype class vE\n"
+ gdb_expect {
+ -re "type = class vE : public virtual vD \{${ws}private:${ws}vD \\*_vb.vD;${ws}public:${ws}int ve;${ws}int vx;${ws}vE & operator=\\(vE const &\\);${ws}vE\\(int, vE const &\\);${ws}vE\\(int\\);${ws}\}$nl$gdb_prompt $" {
+ setup_xfail "*-*-*"
+ fail "ptype class vE (FIXME: non-portable virtual table constructs)"
+ }
+ -re "type = class vE : public virtual vD \{${ws}private:${ws}vD \\*_vb.vD;${ws}public:${ws}int ve;${ws}int vx;((${ws}vE & operator=\\(vE const &\\);)|(${ws}vE\\(int, vE const &\\);)|(${ws}vE\\(int\\);))*${ws}\}$nl$gdb_prompt $" {
+ setup_xfail "*-*-*"
+ fail "ptype class vE (FIXME) (obsolescent gcc or gdb)"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "ptype class vE"
+ }
+ timeout {
+ fail "ptype class vE (timeout)"
+ return
+ }
+ }
+
+ setup_xfail_format "DWARF 1"
+ send_gdb "ptype class Base1\n"
+ gdb_expect {
+ -re "type = class Base1 \{${ws}public:${ws}int x;${ws}Base1 & operator=\\(Base1 const &\\);${ws}Base1\\(Base1 const &\\);${ws}Base1\\(int\\);${ws}\}$nl$gdb_prompt $" {
+ pass "ptype class Base1"
+ }
+ -re "type = class Base1 \{${ws}public:${ws}int x;((${ws}Base1 & operator=\\(Base1 const &\\);)|(${ws}Base1\\(Base1 const &\\);)|(${ws}Base1\\(int\\);))*${ws}\}$nl$gdb_prompt $" {
+ pass "ptype class Base1 (obsolescent gcc or gdb)"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "ptype class Base1"
+ }
+ timeout {
+ fail "ptype class Base1 (timeout)"
+ return
+ }
+ }
+
+ setup_xfail_format "DWARF 1"
+ send_gdb "ptype class Foo\n"
+ gdb_expect {
+ -re "type = class Foo \{${ws}public:${ws}int x;${ws}int y;${ws}static int st;${ws}Foo & operator=\\(Foo const &\\);${ws}Foo\\(Foo const &\\);${ws}Foo\\(int, int\\);${ws}int operator!\\(void\\);${ws}int operator int\\(void\\);${ws}int times\\(int\\);${ws}\}$nl$gdb_prompt $" {
+ pass "ptype class Foo"
+ }
+ -re "type = class Foo \{${ws}public:${ws}int x;${ws}int y;${ws}static int st;((${ws}Foo & operator=\\(Foo const &\\);)|(${ws}Foo\\(Foo const &\\);)|(${ws}Foo\\(int, int\\);)|(${ws}int operator!\\(void\\);)|(${ws}int operator int\\(void\\);)|(${ws}int times\\(int\\);))*${ws}\}$nl$gdb_prompt $" {
+ pass "ptype class Foo (obsolescent gcc or gdb)"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "ptype class Foo"
+ }
+ timeout {
+ fail "ptype class Foo (timeout)"
+ return
+ }
+ }
+
+ setup_xfail_format "DWARF 1"
+ send_gdb "ptype class Bar\n"
+ gdb_expect {
+ -re "type = class Bar : public Base1, public Foo \{${ws}public:${ws}int z;${ws}Bar & operator=\\(Bar const &\\);${ws}Bar\\(Bar const &\\);${ws}Bar\\(int, int, int\\);${ws}\}$nl$gdb_prompt $" {
+ pass "ptype class Bar"
+ }
+ -re "type = class Bar : public Base1, public Foo \{${ws}public:${ws}int z;((${ws}Bar & operator=\\(Bar const &\\);)|(${ws}Bar\\(Bar const &\\);)|(${ws}Bar\\(int, int, int\\);))*${ws}\}$nl$gdb_prompt $" {
+ pass "ptype class Bar (obsolescent gcc or gdb)"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "ptype class Bar"
+ }
+ timeout {
+ fail "ptype class Bar (timeout)"
+ return
+ }
+ }
+}
+
+#
+# Test simple access to class members.
+#
+
+proc test_non_inherited_member_access {} {
+ global gdb_prompt
+
+ # Print non-inherited members of g_A.
+
+ gdb_test "print g_A.a" ".* = 1" "g_A.a incorrect"
+
+ gdb_test "print g_A.x" ".* = 2" "g_A.x incorrect"
+
+ # Print non-inherited members of g_B.
+
+ gdb_test "print g_B.b" ".* = 5" "g_B.b incorrect"
+
+ gdb_test "print g_B.x" ".* = 6" "g_B.x incorrect"
+
+ # Print non-inherited members of g_C.
+
+ gdb_test "print g_C.c" ".* = 9" "g_C.c incorrect"
+
+ gdb_test "print g_C.x" ".* = 10" "g_C.x incorrect"
+
+ # Print non-inherited members of g_D.
+
+ gdb_test "print g_D.d" ".* = 19" "g_D.d incorrect"
+
+ gdb_test "print g_D.x" ".* = 20" "g_D.x incorrect"
+
+ # Print non-inherited members of g_E.
+
+ gdb_test "print g_E.e" ".* = 31" "g_E.e incorrect"
+
+ gdb_test "print g_E.x" ".* = 32" "g_E.x incorrect"
+}
+
+#
+# Try access to non-members that are members of another class.
+# Should give errors.
+#
+
+proc test_wrong_class_members {} {
+ global gdb_prompt
+
+ gdb_test "print g_A.b" "There is no member( or method|) named b." "print g_A.b should be error"
+
+ gdb_test "print g_B.c" "There is no member( or method|) named c." "print g_B.c should be error"
+
+ gdb_test "print g_B.d" "There is no member( or method|) named d." "print g_B.d should be error"
+
+ gdb_test "print g_C.b" "There is no member( or method|) named b." "print g_C.b should be error"
+
+ gdb_test "print g_C.d" "There is no member( or method|) named d." "print g_C.d should be error"
+
+ gdb_test "print g_D.e" "There is no member( or method|) named e." "print g_D.e should be error"
+}
+
+#
+# Try access to non-members that are not members of any class.
+# Should give errors.
+#
+
+proc test_nonexistant_members {} {
+ global gdb_prompt
+
+ gdb_test "print g_A.y" "There is no member( or method|) named y." "print g_A.y should be error"
+
+ gdb_test "print g_B.z" "There is no member( or method|) named z." "print g_B.z should be error"
+
+ gdb_test "print g_C.q" "There is no member( or method|) named q." "print g_C.q should be error"
+
+ gdb_test "print g_D.p" "There is no member( or method|) named p." "print g_D.p should be error"
+}
+
+#
+# Pointers to class members
+#
+
+proc test_pointers_to_class_members {} {
+ global gdb_prompt
+ global decimal
+ global nl
+
+ gdb_test "print Bar::z" ".* = .int\[ \]*\[( \]*Bar::&\[)\]+\[ \]*Bar::z" "print Bar::z"
+
+ gdb_test "print &Foo::x" ".* = .int\[ \]*\[( \]*Foo::\[*)\]+\[ \]*&Foo::x" "print &Foo::x"
+
+ gdb_test "print (int)&Foo::x" ".* = 0" "print (int)&Foo::x"
+
+ send_gdb "print (int)&Bar::y == 2*sizeof(int)\n"
+ gdb_expect {
+ -re ".* = true$nl$gdb_prompt $" {
+ pass "print (int)&Bar::y == 2*sizeof(int)"
+ }
+ -re "There is no field named y.*$gdb_prompt $" {
+ setup_xfail "*-*-*"
+ fail "print (int)&Bar::y == 2*sizeof(int)"
+ }
+ -re ".*$gdb_prompt $" { fail "print (int)&Bar::y == 2*sizeof(int)" }
+ timeout { fail "print (int)&Bar::y == 2*sizeof(int) (timeout)" ; return }
+ }
+
+ send_gdb "next\n"
+ setup_xfail "*-*-*"
+ gdb_expect {
+ -re "$decimal\[ \t\]+inheritance3 \[)(\]+;$nl$gdb_prompt $" {}
+ -re ".*$gdb_prompt $" { fail "next to inheritance3" ; return }
+ }
+ clear_xfail "*-*-*"
+
+ setup_xfail_format "DWARF 1"
+ gdb_test "print (int)pmi == sizeof(int)" ".* = false" "print (int)pmi == sizeof(int)"
+}
+
+#
+# Test static members.
+#
+
+proc test_static_members {} {
+ global gdb_prompt
+ global hex
+ global nl
+
+ send_gdb "print Foo::st\n"
+ gdb_expect {
+ -re ".* = 100$nl$gdb_prompt $" {
+ pass "print Foo::st"
+ }
+ -re "There is no field named st.*$gdb_prompt $" {
+ setup_xfail "*-*-*"
+ fail "print Foo::st"
+ }
+ -re ".*$gdb_prompt $" { fail "print Foo::st" }
+ timeout { fail "print Foo::st (timeout)" ; return }
+ }
+
+ send_gdb "set foo.st = 200\n"
+ gdb_expect {
+ -re ".*$gdb_prompt $" {}
+ }
+
+ send_gdb "print bar.st\n"
+ gdb_expect {
+ -re ".* = 200$nl$gdb_prompt $" {
+ pass "print bar.st"
+ }
+ -re "There is no member( or method|) named st.*$gdb_prompt $" {
+ setup_xfail "*-*-*"
+ fail "print bar.st"
+ }
+ -re ".*$gdb_prompt $" { fail "print bar.st" }
+ timeout { fail "print bar.st (timeout)" ; return }
+ }
+
+ send_gdb "print &foo.st\n"
+ gdb_expect {
+ -re ".* = .int \[*)\]+ $hex$nl$gdb_prompt $" {
+ pass "print &foo.st"
+ }
+ -re "There is no member( or method|) named st.*$gdb_prompt $" {
+ setup_xfail "*-*-*"
+ fail "print &foo.st"
+ }
+ -re ".*$gdb_prompt $" { fail "print &foo.st" }
+ timeout { fail "print &foo.st (timeout)" ; return }
+ }
+
+ set got_bar_st 0
+ send_gdb "print &Bar::st\n"
+ gdb_expect {
+ -re ".* = .int \[*)\]+ $hex$nl$gdb_prompt $" {
+ pass "print &Bar::st"
+ set got_bar_st 1
+ }
+ -re "There is no field named st.*$gdb_prompt $" {
+ setup_xfail "*-*-*"
+ fail "print &Bar::st"
+ }
+ -re ".*$gdb_prompt $" { fail "print &Bar::st" }
+ timeout { fail "print &Bar::st (timeout)" ; return }
+ }
+
+ if $got_bar_st then {
+ gdb_test "print *\$" ".* = 200" "print *\$"
+ }
+
+ gdb_test "set print static-members off" ""
+ gdb_test "print csi" \
+ "{x = 10, y = 20}" \
+ "print csi without static members"
+ gdb_test "print cnsi" \
+ "{x = 30, y = 40}" \
+ "print cnsi without static members"
+
+ gdb_test "set print static-members on" ""
+ setup_xfail_format "DWARF 1"
+ gdb_test "print csi" \
+ "{x = 10, y = 20, static null = {x = 0, y = 0, static null = <same as static member of an already seen type>}}" \
+ "print csi with static members"
+ setup_xfail_format "DWARF 1"
+ gdb_test "print cnsi" \
+ "{x = 30, y = 40, static null = {x = 0, y = 0, static null = <same as static member of an already seen type>, static yy = {z = 5, static xx = {x = 1, y = 2, static null = <same as static member of an already seen type>, static yy = <same as static member of an already seen type>}}}, static yy = <same as static member of an already seen type>}" \
+ "print cnsi with static members"
+}
+
+proc do_tests {} {
+ global prms_id
+ global bug_id
+ global subdir
+ global objdir
+ global srcdir
+ global binfile
+ global gdb_prompt
+
+ set prms_id 0
+ set bug_id 0
+
+ # Start with a fresh gdb.
+
+ gdb_exit
+ gdb_start
+ gdb_reinitialize_dir $srcdir/$subdir
+ gdb_load $binfile
+
+ send_gdb "set language c++\n"
+ gdb_expect -re "$gdb_prompt $"
+ send_gdb "set width 0\n"
+ gdb_expect -re "$gdb_prompt $"
+
+ # Get the debug format for the compiled test case.
+
+ if [ runto_main ] then {
+ get_debug_format
+ }
+
+ test_ptype_class_objects
+
+ if [ runto 'inheritance2(void)' ] then {
+ test_non_inherited_member_access
+ test_wrong_class_members
+ test_nonexistant_members
+ }
+
+ if [istarget "mips-idt-*"] then {
+ # Restart because IDT/SIM runs out of file descriptors.
+ gdb_exit
+ gdb_start
+ gdb_reinitialize_dir $srcdir/$subdir
+ gdb_load $binfile
+ }
+
+ if [ runto_main ] then {
+ test_pointers_to_class_members
+ test_static_members
+ }
+
+ if [istarget "mips-idt-*"] then {
+ # Restart because IDT/SIM runs out of file descriptors.
+ gdb_exit
+ gdb_start
+ gdb_reinitialize_dir $srcdir/$subdir
+ gdb_load $binfile
+ }
+
+ if [ runto marker_reg1 ] then {
+
+ gdb_test "finish" "Run till exit from.*" "finish from marker_reg1"
+
+ send_gdb "print v.method ()\n"
+ gdb_expect {
+ -re "= 82.*$gdb_prompt $" {
+ pass "calling method for small class"
+ }
+ -re "Address requested for identifier .v. which is in a register.*$gdb_prompt $" {
+ setup_xfail "*-*-*" 2972
+ fail "calling method for small class"
+ }
+ -re ".*$gdb_prompt $" { fail "calling method for small class" }
+ timeout { fail "calling method for small class (timeout)" }
+ eof { fail "calling method for small class (eof)" }
+ }
+ }
+
+}
+
+do_tests
+
+
+# Some additional tests for enums inside classes
+
+
+# set a breakpoint and go there
+send_gdb "break 498\n"
+gdb_expect {
+ -re "Breakpoint \[0-9\] at.*$gdb_prompt $" { pass "set break 498" }
+ -re "$gdb_prompt $" { fail "set break 498" }
+ timeout { fail "(timeout) set break 498" }
+}
+send_gdb "continue\n"
+gdb_expect {
+ -re "Continuing\\.\r\n\r\nBreakpoint \[0-9\]*, main....at.*misc\\.cc:498\r\n498.*\r\n$gdb_prompt $" { pass "continue" }
+ -re "$gdb_prompt $" { fail "continue" }
+ timeout { fail "(timeout) continue" }
+}
+
+# print the object
+send_gdb "print obj_with_enum\n"
+gdb_expect {
+ -re "\\$\[0-9\]* = \\{priv_enum = red, x = 0\\}.*$gdb_prompt $" { pass "print obj_with_enum (1)" }
+ -re "$gdb_prompt $" { fail "print obj_with_enum (1)" }
+ timeout { fail "(timeout) print obj_with_enum (1)" }
+}
+
+send_gdb "next\n"
+gdb_expect {
+ -re "$gdb_prompt $" { pass "next" }
+ timeout { fail "(timeout) next" }
+}
+
+# print the object again
+send_gdb "print obj_with_enum\n"
+gdb_expect {
+ -re "\\$\[0-9\]* = \\{priv_enum = green, x = 0\\}.*$gdb_prompt $" { pass "print obj_with_enum (2)" }
+ -re "$gdb_prompt $" { fail "print obj_with_enum (2)" }
+ timeout { fail "(timeout) print obj_with_enum (2)" }
+}
+
+# print out the enum member
+send_gdb "print obj_with_enum.priv_enum\n"
+gdb_expect {
+ -re "\\$\[0-9\]* = green.*$gdb_prompt $" { pass "print obj_with_enum.priv_enum" }
+ -re "$gdb_prompt $" { fail "print obj_with_enum.priv_enum" }
+ timeout { fail "(timeout) print obj_with_enum.priv_enum" }
+}
+
+# ptype on the enum member
+send_gdb "ptype obj_with_enum.priv_enum\n"
+gdb_expect {
+ -re "type = enum ClassWithEnum::PrivEnum \\{red, green, blue, yellow = 42\\}.*$gdb_prompt $" { pass "ptype obj_with_enum.priv_enum" }
+ -re "$gdb_prompt $" { fail "ptype obj_with_enum.priv_enum" }
+ timeout { fail "(timeout) ptype obj_with_enum.priv_enum" }
+}
+
+# ptype on the object
+send_gdb "ptype obj_with_enum\n"
+gdb_expect {
+ -re "type = class ClassWithEnum \\{\r\n\[ \t\]*public:\r\n\[ \t\]*enum ClassWithEnum::PrivEnum priv_enum;\r\n\[ \t\]*int x;\r\n\\}\r\n$gdb_prompt $" { pass "ptype obj_with_enum" }
+ -re "$gdb_prompt $" { fail "ptype obj_with_enum" }
+ timeout { fail "(timeout) ptype obj_with_enum" }
+}
+
+send_gdb "print (ClassWithEnum::PrivEnum) 42\n"
+gdb_expect {
+ -re "\\$\[0-9\]* = yellow.*$gdb_prompt $" { pass "print (ClassWithEnum::PrivEnum) 42" }
+ -re "$gdb_prompt $" { fail "print (ClassWithEnum::PrivEnum) 42" }
+ timeout { fail "(timeout) print (ClassWithEnum::PrivEnum) 42" }
+}
+
+
+send_gdb "maint demangle inheritance1__Fv\n"
+gdb_expect {
+ -re "inheritance1\\(void\\).*$gdb_prompt $" { pass "demangle" }
+ -re ".*$gdb_prompt $" { fail "demangle" }
+ timeout { fail "(timeout) demangle" }
+}
+
diff --git a/gdb/testsuite/gdb.c++/compiler.cc b/gdb/testsuite/gdb.c++/compiler.cc
new file mode 100644
index 00000000000..aa35c7510ff
--- /dev/null
+++ b/gdb/testsuite/gdb.c++/compiler.cc
@@ -0,0 +1,34 @@
+/* Often the behavior of any particular test depends upon what compiler was
+ used to compile the test. As each test is compiled, this file is
+ preprocessed by the same compiler used to compile that specific test
+ (different tests might be compiled by different compilers, particularly
+ if compiled at different times), and used to generate a *.ci (compiler
+ info) file for that test.
+
+ I.E., when callfuncs is compiled, a callfuncs.ci file will be generated,
+ which can then be sourced by callfuncs.exp to give callfuncs.exp access
+ to information about the compilation environment.
+
+ TODO: It might be a good idea to add expect code that tests each
+ definition made with 'set" to see if one already exists, and if so
+ warn about conflicts if it is being set to something else. */
+
+#if defined(__GNUC__) && __GNUC__ >= 2 && __GNUC_MINOR__ >= 6
+set supports_template_debugging 1
+#else
+set supports_template_debugging 0
+#endif
+
+#if defined(__cplusplus)
+set supports_template_debugging 1
+#else
+set supports_template_debugging 0
+#endif
+
+#if defined (__GNUC__)
+set gcc_compiled __GNUC__
+#else
+set gcc_compiled 0
+#endif
+
+return 0
diff --git a/gdb/testsuite/gdb.c++/configure b/gdb/testsuite/gdb.c++/configure
new file mode 100644
index 00000000000..6d0b517b4a6
--- /dev/null
+++ b/gdb/testsuite/gdb.c++/configure
@@ -0,0 +1,899 @@
+#! /bin/sh
+
+# Guess values for system-dependent variables and create Makefiles.
+# Generated automatically using autoconf version 2.12.1
+# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc.
+#
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+
+# Defaults:
+ac_help=
+ac_default_prefix=/usr/local
+# Any additions from configure.in:
+
+# Initialize some variables set by options.
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+build=NONE
+cache_file=./config.cache
+exec_prefix=NONE
+host=NONE
+no_create=
+nonopt=NONE
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+target=NONE
+verbose=
+x_includes=NONE
+x_libraries=NONE
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datadir='${prefix}/share'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+libdir='${exec_prefix}/lib'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+infodir='${prefix}/info'
+mandir='${prefix}/man'
+
+# Initialize some other variables.
+subdirs=
+MFLAGS= MAKEFLAGS=
+SHELL=${CONFIG_SHELL-/bin/sh}
+# Maximum number of lines to put in a shell here document.
+ac_max_here_lines=12
+
+ac_prev=
+for ac_option
+do
+
+ # If the previous option needs an argument, assign it.
+ if test -n "$ac_prev"; then
+ eval "$ac_prev=\$ac_option"
+ ac_prev=
+ continue
+ fi
+
+ case "$ac_option" in
+ -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
+ *) ac_optarg= ;;
+ esac
+
+ # Accept the important Cygnus configure options, so we can diagnose typos.
+
+ case "$ac_option" in
+
+ -bindir | --bindir | --bindi | --bind | --bin | --bi)
+ ac_prev=bindir ;;
+ -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+ bindir="$ac_optarg" ;;
+
+ -build | --build | --buil | --bui | --bu)
+ ac_prev=build ;;
+ -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+ build="$ac_optarg" ;;
+
+ -cache-file | --cache-file | --cache-fil | --cache-fi \
+ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+ ac_prev=cache_file ;;
+ -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+ cache_file="$ac_optarg" ;;
+
+ -datadir | --datadir | --datadi | --datad | --data | --dat | --da)
+ ac_prev=datadir ;;
+ -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \
+ | --da=*)
+ datadir="$ac_optarg" ;;
+
+ -disable-* | --disable-*)
+ ac_feature=`echo $ac_option|sed -e 's/-*disable-//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then
+ { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
+ fi
+ ac_feature=`echo $ac_feature| sed 's/-/_/g'`
+ eval "enable_${ac_feature}=no" ;;
+
+ -enable-* | --enable-*)
+ ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then
+ { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
+ fi
+ ac_feature=`echo $ac_feature| sed 's/-/_/g'`
+ case "$ac_option" in
+ *=*) ;;
+ *) ac_optarg=yes ;;
+ esac
+ eval "enable_${ac_feature}='$ac_optarg'" ;;
+
+ -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+ | --exec | --exe | --ex)
+ ac_prev=exec_prefix ;;
+ -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+ | --exec=* | --exe=* | --ex=*)
+ exec_prefix="$ac_optarg" ;;
+
+ -gas | --gas | --ga | --g)
+ # Obsolete; use --with-gas.
+ with_gas=yes ;;
+
+ -help | --help | --hel | --he)
+ # Omit some internal or obsolete options to make the list less imposing.
+ # This message is too long to be a string in the A/UX 3.1 sh.
+ cat << EOF
+Usage: configure [options] [host]
+Options: [defaults in brackets after descriptions]
+Configuration:
+ --cache-file=FILE cache test results in FILE
+ --help print this message
+ --no-create do not create output files
+ --quiet, --silent do not print \`checking...' messages
+ --version print the version of autoconf that created configure
+Directory and file names:
+ --prefix=PREFIX install architecture-independent files in PREFIX
+ [$ac_default_prefix]
+ --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
+ [same as prefix]
+ --bindir=DIR user executables in DIR [EPREFIX/bin]
+ --sbindir=DIR system admin executables in DIR [EPREFIX/sbin]
+ --libexecdir=DIR program executables in DIR [EPREFIX/libexec]
+ --datadir=DIR read-only architecture-independent data in DIR
+ [PREFIX/share]
+ --sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc]
+ --sharedstatedir=DIR modifiable architecture-independent data in DIR
+ [PREFIX/com]
+ --localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var]
+ --libdir=DIR object code libraries in DIR [EPREFIX/lib]
+ --includedir=DIR C header files in DIR [PREFIX/include]
+ --oldincludedir=DIR C header files for non-gcc in DIR [/usr/include]
+ --infodir=DIR info documentation in DIR [PREFIX/info]
+ --mandir=DIR man documentation in DIR [PREFIX/man]
+ --srcdir=DIR find the sources in DIR [configure dir or ..]
+ --program-prefix=PREFIX prepend PREFIX to installed program names
+ --program-suffix=SUFFIX append SUFFIX to installed program names
+ --program-transform-name=PROGRAM
+ run sed PROGRAM on installed program names
+EOF
+ cat << EOF
+Host type:
+ --build=BUILD configure for building on BUILD [BUILD=HOST]
+ --host=HOST configure for HOST [guessed]
+ --target=TARGET configure for TARGET [TARGET=HOST]
+Features and packages:
+ --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
+ --enable-FEATURE[=ARG] include FEATURE [ARG=yes]
+ --with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
+ --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
+ --x-includes=DIR X include files are in DIR
+ --x-libraries=DIR X library files are in DIR
+EOF
+ if test -n "$ac_help"; then
+ echo "--enable and --with options recognized:$ac_help"
+ fi
+ exit 0 ;;
+
+ -host | --host | --hos | --ho)
+ ac_prev=host ;;
+ -host=* | --host=* | --hos=* | --ho=*)
+ host="$ac_optarg" ;;
+
+ -includedir | --includedir | --includedi | --included | --include \
+ | --includ | --inclu | --incl | --inc)
+ ac_prev=includedir ;;
+ -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+ | --includ=* | --inclu=* | --incl=* | --inc=*)
+ includedir="$ac_optarg" ;;
+
+ -infodir | --infodir | --infodi | --infod | --info | --inf)
+ ac_prev=infodir ;;
+ -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+ infodir="$ac_optarg" ;;
+
+ -libdir | --libdir | --libdi | --libd)
+ ac_prev=libdir ;;
+ -libdir=* | --libdir=* | --libdi=* | --libd=*)
+ libdir="$ac_optarg" ;;
+
+ -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+ | --libexe | --libex | --libe)
+ ac_prev=libexecdir ;;
+ -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+ | --libexe=* | --libex=* | --libe=*)
+ libexecdir="$ac_optarg" ;;
+
+ -localstatedir | --localstatedir | --localstatedi | --localstated \
+ | --localstate | --localstat | --localsta | --localst \
+ | --locals | --local | --loca | --loc | --lo)
+ ac_prev=localstatedir ;;
+ -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+ | --localstate=* | --localstat=* | --localsta=* | --localst=* \
+ | --locals=* | --local=* | --loca=* | --loc=* | --lo=*)
+ localstatedir="$ac_optarg" ;;
+
+ -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+ ac_prev=mandir ;;
+ -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+ mandir="$ac_optarg" ;;
+
+ -nfp | --nfp | --nf)
+ # Obsolete; use --without-fp.
+ with_fp=no ;;
+
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c)
+ no_create=yes ;;
+
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+ no_recursion=yes ;;
+
+ -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+ | --oldin | --oldi | --old | --ol | --o)
+ ac_prev=oldincludedir ;;
+ -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+ oldincludedir="$ac_optarg" ;;
+
+ -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+ ac_prev=prefix ;;
+ -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+ prefix="$ac_optarg" ;;
+
+ -program-prefix | --program-prefix | --program-prefi | --program-pref \
+ | --program-pre | --program-pr | --program-p)
+ ac_prev=program_prefix ;;
+ -program-prefix=* | --program-prefix=* | --program-prefi=* \
+ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+ program_prefix="$ac_optarg" ;;
+
+ -program-suffix | --program-suffix | --program-suffi | --program-suff \
+ | --program-suf | --program-su | --program-s)
+ ac_prev=program_suffix ;;
+ -program-suffix=* | --program-suffix=* | --program-suffi=* \
+ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+ program_suffix="$ac_optarg" ;;
+
+ -program-transform-name | --program-transform-name \
+ | --program-transform-nam | --program-transform-na \
+ | --program-transform-n | --program-transform- \
+ | --program-transform | --program-transfor \
+ | --program-transfo | --program-transf \
+ | --program-trans | --program-tran \
+ | --progr-tra | --program-tr | --program-t)
+ ac_prev=program_transform_name ;;
+ -program-transform-name=* | --program-transform-name=* \
+ | --program-transform-nam=* | --program-transform-na=* \
+ | --program-transform-n=* | --program-transform-=* \
+ | --program-transform=* | --program-transfor=* \
+ | --program-transfo=* | --program-transf=* \
+ | --program-trans=* | --program-tran=* \
+ | --progr-tra=* | --program-tr=* | --program-t=*)
+ program_transform_name="$ac_optarg" ;;
+
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ silent=yes ;;
+
+ -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+ ac_prev=sbindir ;;
+ -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+ | --sbi=* | --sb=*)
+ sbindir="$ac_optarg" ;;
+
+ -sharedstatedir | --sharedstatedir | --sharedstatedi \
+ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+ | --sharedst | --shareds | --shared | --share | --shar \
+ | --sha | --sh)
+ ac_prev=sharedstatedir ;;
+ -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+ | --sha=* | --sh=*)
+ sharedstatedir="$ac_optarg" ;;
+
+ -site | --site | --sit)
+ ac_prev=site ;;
+ -site=* | --site=* | --sit=*)
+ site="$ac_optarg" ;;
+
+ -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+ ac_prev=srcdir ;;
+ -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+ srcdir="$ac_optarg" ;;
+
+ -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+ | --syscon | --sysco | --sysc | --sys | --sy)
+ ac_prev=sysconfdir ;;
+ -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+ sysconfdir="$ac_optarg" ;;
+
+ -target | --target | --targe | --targ | --tar | --ta | --t)
+ ac_prev=target ;;
+ -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+ target="$ac_optarg" ;;
+
+ -v | -verbose | --verbose | --verbos | --verbo | --verb)
+ verbose=yes ;;
+
+ -version | --version | --versio | --versi | --vers)
+ echo "configure generated by autoconf version 2.12.1"
+ exit 0 ;;
+
+ -with-* | --with-*)
+ ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then
+ { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
+ fi
+ ac_package=`echo $ac_package| sed 's/-/_/g'`
+ case "$ac_option" in
+ *=*) ;;
+ *) ac_optarg=yes ;;
+ esac
+ eval "with_${ac_package}='$ac_optarg'" ;;
+
+ -without-* | --without-*)
+ ac_package=`echo $ac_option|sed -e 's/-*without-//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then
+ { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
+ fi
+ ac_package=`echo $ac_package| sed 's/-/_/g'`
+ eval "with_${ac_package}=no" ;;
+
+ --x)
+ # Obsolete; use --with-x.
+ with_x=yes ;;
+
+ -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+ | --x-incl | --x-inc | --x-in | --x-i)
+ ac_prev=x_includes ;;
+ -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+ x_includes="$ac_optarg" ;;
+
+ -x-libraries | --x-libraries | --x-librarie | --x-librari \
+ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+ ac_prev=x_libraries ;;
+ -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+ x_libraries="$ac_optarg" ;;
+
+ -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; }
+ ;;
+
+ *)
+ if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then
+ echo "configure: warning: $ac_option: invalid host type" 1>&2
+ fi
+ if test "x$nonopt" != xNONE; then
+ { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; }
+ fi
+ nonopt="$ac_option"
+ ;;
+
+ esac
+done
+
+if test -n "$ac_prev"; then
+ { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; }
+fi
+
+trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
+
+# File descriptor usage:
+# 0 standard input
+# 1 file creation
+# 2 errors and warnings
+# 3 some systems may open it to /dev/tty
+# 4 used on the Kubota Titan
+# 6 checking for... messages and results
+# 5 compiler messages saved in config.log
+if test "$silent" = yes; then
+ exec 6>/dev/null
+else
+ exec 6>&1
+fi
+exec 5>./config.log
+
+echo "\
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+" 1>&5
+
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Also quote any args containing shell metacharacters.
+ac_configure_args=
+for ac_arg
+do
+ case "$ac_arg" in
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c) ;;
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;;
+ *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*)
+ ac_configure_args="$ac_configure_args '$ac_arg'" ;;
+ *) ac_configure_args="$ac_configure_args $ac_arg" ;;
+ esac
+done
+
+# NLS nuisances.
+# Only set these to C if already set. These must not be set unconditionally
+# because not all systems understand e.g. LANG=C (notably SCO).
+# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'!
+# Non-C LC_CTYPE values break the ctype check.
+if test "${LANG+set}" = set; then LANG=C; export LANG; fi
+if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi
+if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi
+if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -rf conftest* confdefs.h
+# AIX cpp loses on an empty file, so make sure it contains at least a newline.
+echo > confdefs.h
+
+# A filename unique to this package, relative to the directory that
+# configure is in, which we can look for to find out if srcdir is correct.
+ac_unique_file=cplusfuncs.cc
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+ ac_srcdir_defaulted=yes
+ # Try the directory containing this script, then its parent.
+ ac_prog=$0
+ ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'`
+ test "x$ac_confdir" = "x$ac_prog" && ac_confdir=.
+ srcdir=$ac_confdir
+ if test ! -r $srcdir/$ac_unique_file; then
+ srcdir=..
+ fi
+else
+ ac_srcdir_defaulted=no
+fi
+if test ! -r $srcdir/$ac_unique_file; then
+ if test "$ac_srcdir_defaulted" = yes; then
+ { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; }
+ else
+ { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; }
+ fi
+fi
+srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'`
+
+# Prefer explicitly selected file to automatically selected ones.
+if test -z "$CONFIG_SITE"; then
+ if test "x$prefix" != xNONE; then
+ CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site"
+ else
+ CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
+ fi
+fi
+for ac_site_file in $CONFIG_SITE; do
+ if test -r "$ac_site_file"; then
+ echo "loading site script $ac_site_file"
+ . "$ac_site_file"
+ fi
+done
+
+if test -r "$cache_file"; then
+ echo "loading cache $cache_file"
+ . $cache_file
+else
+ echo "creating cache $cache_file"
+ > $cache_file
+fi
+
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then
+ # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu.
+ if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then
+ ac_n= ac_c='
+' ac_t=' '
+ else
+ ac_n=-n ac_c= ac_t=
+ fi
+else
+ ac_n= ac_c='\c' ac_t=
+fi
+
+
+
+CC=${CC-cc}
+
+ac_aux_dir=
+for ac_dir in `cd $srcdir;pwd`/../../.. $srcdir/`cd $srcdir;pwd`/../../..; do
+ if test -f $ac_dir/install-sh; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install-sh -c"
+ break
+ elif test -f $ac_dir/install.sh; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install.sh -c"
+ break
+ fi
+done
+if test -z "$ac_aux_dir"; then
+ { echo "configure: error: can not find install-sh or install.sh in `cd $srcdir;pwd`/../../.. $srcdir/`cd $srcdir;pwd`/../../.." 1>&2; exit 1; }
+fi
+ac_config_guess=$ac_aux_dir/config.guess
+ac_config_sub=$ac_aux_dir/config.sub
+ac_configure=$ac_aux_dir/configure # This should be Cygnus configure.
+
+
+# Do some error checking and defaulting for the host and target type.
+# The inputs are:
+# configure --host=HOST --target=TARGET --build=BUILD NONOPT
+#
+# The rules are:
+# 1. You are not allowed to specify --host, --target, and nonopt at the
+# same time.
+# 2. Host defaults to nonopt.
+# 3. If nonopt is not specified, then host defaults to the current host,
+# as determined by config.guess.
+# 4. Target and build default to nonopt.
+# 5. If nonopt is not specified, then target and build default to host.
+
+# The aliases save the names the user supplied, while $host etc.
+# will get canonicalized.
+case $host---$target---$nonopt in
+NONE---*---* | *---NONE---* | *---*---NONE) ;;
+*) { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; } ;;
+esac
+
+
+# Make sure we can run config.sub.
+if ${CONFIG_SHELL-/bin/sh} $ac_config_sub sun4 >/dev/null 2>&1; then :
+else { echo "configure: error: can not run $ac_config_sub" 1>&2; exit 1; }
+fi
+
+echo $ac_n "checking host system type""... $ac_c" 1>&6
+echo "configure:573: checking host system type" >&5
+
+host_alias=$host
+case "$host_alias" in
+NONE)
+ case $nonopt in
+ NONE)
+ if host_alias=`${CONFIG_SHELL-/bin/sh} $ac_config_guess`; then :
+ else { echo "configure: error: can not guess host type; you must specify one" 1>&2; exit 1; }
+ fi ;;
+ *) host_alias=$nonopt ;;
+ esac ;;
+esac
+
+host=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $host_alias`
+host_cpu=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+host_vendor=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+host_os=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+echo "$ac_t""$host" 1>&6
+
+echo $ac_n "checking target system type""... $ac_c" 1>&6
+echo "configure:594: checking target system type" >&5
+
+target_alias=$target
+case "$target_alias" in
+NONE)
+ case $nonopt in
+ NONE) target_alias=$host_alias ;;
+ *) target_alias=$nonopt ;;
+ esac ;;
+esac
+
+target=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $target_alias`
+target_cpu=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+target_vendor=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+target_os=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+echo "$ac_t""$target" 1>&6
+
+echo $ac_n "checking build system type""... $ac_c" 1>&6
+echo "configure:612: checking build system type" >&5
+
+build_alias=$build
+case "$build_alias" in
+NONE)
+ case $nonopt in
+ NONE) build_alias=$host_alias ;;
+ *) build_alias=$nonopt ;;
+ esac ;;
+esac
+
+build=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $build_alias`
+build_cpu=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+build_vendor=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+build_os=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+echo "$ac_t""$build" 1>&6
+
+test "$host_alias" != "$target_alias" &&
+ test "$program_prefix$program_suffix$program_transform_name" = \
+ NONENONEs,x,x, &&
+ program_prefix=${target_alias}-
+
+
+trap '' 1 2 15
+cat > confcache <<\EOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs. It is not useful on other systems.
+# If it contains results you don't want to keep, you may remove or edit it.
+#
+# By default, configure uses ./config.cache as the cache file,
+# creating it if it does not exist already. You can give configure
+# the --cache-file=FILE option to use a different cache file; that is
+# what configure does when it calls configure scripts in
+# subdirectories, so they share the cache.
+# Giving --cache-file=/dev/null disables caching, for debugging configure.
+# config.status only pays attention to the cache file if you give it the
+# --recheck option to rerun configure.
+#
+EOF
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, don't put newlines in cache variables' values.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(set) 2>&1 |
+ case `(ac_space=' '; set) 2>&1 | grep ac_space` in
+ *ac_space=\ *)
+ # `set' does not quote correctly, so add quotes (double-quote substitution
+ # turns \\\\ into \\, and sed turns \\ into \).
+ sed -n \
+ -e "s/'/'\\\\''/g" \
+ -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p"
+ ;;
+ *)
+ # `set' quotes correctly as required by POSIX, so do not add quotes.
+ sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p'
+ ;;
+ esac >> confcache
+if cmp -s $cache_file confcache; then
+ :
+else
+ if test -w $cache_file; then
+ echo "updating cache $cache_file"
+ cat confcache > $cache_file
+ else
+ echo "not updating unwritable cache $cache_file"
+ fi
+fi
+rm -f confcache
+
+trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+# Any assignment to VPATH causes Sun make to only execute
+# the first set of double-colon rules, so remove it if not needed.
+# If there is a colon in the path, we need to keep it.
+if test "x$srcdir" = x.; then
+ ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d'
+fi
+
+trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15
+
+# Transform confdefs.h into DEFS.
+# Protect against shell expansion while executing Makefile rules.
+# Protect against Makefile macro expansion.
+cat > conftest.defs <<\EOF
+s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%-D\1=\2%g
+s%[ `~#$^&*(){}\\|;'"<>?]%\\&%g
+s%\[%\\&%g
+s%\]%\\&%g
+s%\$%$$%g
+EOF
+DEFS=`sed -f conftest.defs confdefs.h | tr '\012' ' '`
+rm -f conftest.defs
+
+
+# Without the "./", some shells look in PATH for config.status.
+: ${CONFIG_STATUS=./config.status}
+
+echo creating $CONFIG_STATUS
+rm -f $CONFIG_STATUS
+cat > $CONFIG_STATUS <<EOF
+#! /bin/sh
+# Generated automatically by configure.
+# Run this file to recreate the current configuration.
+# This directory was configured as follows,
+# on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+#
+# $0 $ac_configure_args
+#
+# Compiler output produced by configure, useful for debugging
+# configure, is in ./config.log if it exists.
+
+ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]"
+for ac_option
+do
+ case "\$ac_option" in
+ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+ echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion"
+ exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;;
+ -version | --version | --versio | --versi | --vers | --ver | --ve | --v)
+ echo "$CONFIG_STATUS generated by autoconf version 2.12.1"
+ exit 0 ;;
+ -help | --help | --hel | --he | --h)
+ echo "\$ac_cs_usage"; exit 0 ;;
+ *) echo "\$ac_cs_usage"; exit 1 ;;
+ esac
+done
+
+ac_given_srcdir=$srcdir
+
+trap 'rm -fr `echo "Makefile" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15
+EOF
+cat >> $CONFIG_STATUS <<EOF
+
+# Protect against being on the right side of a sed subst in config.status.
+sed 's/%@/@@/; s/@%/@@/; s/%g\$/@g/; /@g\$/s/[\\\\&%]/\\\\&/g;
+ s/@@/%@/; s/@@/@%/; s/@g\$/%g/' > conftest.subs <<\\CEOF
+$ac_vpsub
+$extrasub
+s%@SHELL@%$SHELL%g
+s%@CFLAGS@%$CFLAGS%g
+s%@CPPFLAGS@%$CPPFLAGS%g
+s%@CXXFLAGS@%$CXXFLAGS%g
+s%@DEFS@%$DEFS%g
+s%@LDFLAGS@%$LDFLAGS%g
+s%@LIBS@%$LIBS%g
+s%@exec_prefix@%$exec_prefix%g
+s%@prefix@%$prefix%g
+s%@program_transform_name@%$program_transform_name%g
+s%@bindir@%$bindir%g
+s%@sbindir@%$sbindir%g
+s%@libexecdir@%$libexecdir%g
+s%@datadir@%$datadir%g
+s%@sysconfdir@%$sysconfdir%g
+s%@sharedstatedir@%$sharedstatedir%g
+s%@localstatedir@%$localstatedir%g
+s%@libdir@%$libdir%g
+s%@includedir@%$includedir%g
+s%@oldincludedir@%$oldincludedir%g
+s%@infodir@%$infodir%g
+s%@mandir@%$mandir%g
+s%@CC@%$CC%g
+s%@host@%$host%g
+s%@host_alias@%$host_alias%g
+s%@host_cpu@%$host_cpu%g
+s%@host_vendor@%$host_vendor%g
+s%@host_os@%$host_os%g
+s%@target@%$target%g
+s%@target_alias@%$target_alias%g
+s%@target_cpu@%$target_cpu%g
+s%@target_vendor@%$target_vendor%g
+s%@target_os@%$target_os%g
+s%@build@%$build%g
+s%@build_alias@%$build_alias%g
+s%@build_cpu@%$build_cpu%g
+s%@build_vendor@%$build_vendor%g
+s%@build_os@%$build_os%g
+
+CEOF
+EOF
+
+cat >> $CONFIG_STATUS <<\EOF
+
+# Split the substitutions into bite-sized pieces for seds with
+# small command number limits, like on Digital OSF/1 and HP-UX.
+ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script.
+ac_file=1 # Number of current file.
+ac_beg=1 # First line for current file.
+ac_end=$ac_max_sed_cmds # Line after last line for current file.
+ac_more_lines=:
+ac_sed_cmds=""
+while $ac_more_lines; do
+ if test $ac_beg -gt 1; then
+ sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file
+ else
+ sed "${ac_end}q" conftest.subs > conftest.s$ac_file
+ fi
+ if test ! -s conftest.s$ac_file; then
+ ac_more_lines=false
+ rm -f conftest.s$ac_file
+ else
+ if test -z "$ac_sed_cmds"; then
+ ac_sed_cmds="sed -f conftest.s$ac_file"
+ else
+ ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file"
+ fi
+ ac_file=`expr $ac_file + 1`
+ ac_beg=$ac_end
+ ac_end=`expr $ac_end + $ac_max_sed_cmds`
+ fi
+done
+if test -z "$ac_sed_cmds"; then
+ ac_sed_cmds=cat
+fi
+EOF
+
+cat >> $CONFIG_STATUS <<EOF
+
+CONFIG_FILES=\${CONFIG_FILES-"Makefile"}
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then
+ # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+ case "$ac_file" in
+ *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'`
+ ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
+ *) ac_file_in="${ac_file}.in" ;;
+ esac
+
+ # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories.
+
+ # Remove last slash and all that follows it. Not all systems have dirname.
+ ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
+ if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
+ # The file is in a subdirectory.
+ test ! -d "$ac_dir" && mkdir "$ac_dir"
+ ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`"
+ # A "../" for each directory in $ac_dir_suffix.
+ ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'`
+ else
+ ac_dir_suffix= ac_dots=
+ fi
+
+ case "$ac_given_srcdir" in
+ .) srcdir=.
+ if test -z "$ac_dots"; then top_srcdir=.
+ else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;;
+ /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;;
+ *) # Relative path.
+ srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix"
+ top_srcdir="$ac_dots$ac_given_srcdir" ;;
+ esac
+
+
+ echo creating "$ac_file"
+ rm -f "$ac_file"
+ configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure."
+ case "$ac_file" in
+ *Makefile*) ac_comsub="1i\\
+# $configure_input" ;;
+ *) ac_comsub= ;;
+ esac
+
+ ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"`
+ sed -e "$ac_comsub
+s%@configure_input@%$configure_input%g
+s%@srcdir@%$srcdir%g
+s%@top_srcdir@%$top_srcdir%g
+" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file
+fi; done
+rm -f conftest.s*
+
+EOF
+cat >> $CONFIG_STATUS <<EOF
+
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+
+exit 0
+EOF
+chmod +x $CONFIG_STATUS
+rm -fr confdefs* $ac_clean_files
+test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1
+
diff --git a/gdb/testsuite/gdb.c++/configure.in b/gdb/testsuite/gdb.c++/configure.in
new file mode 100644
index 00000000000..f989cb82865
--- /dev/null
+++ b/gdb/testsuite/gdb.c++/configure.in
@@ -0,0 +1,15 @@
+dnl Process this file file with autoconf to produce a configure script.
+dnl This file is a shell script fragment that supplies the information
+dnl necessary to tailor a template configure script into the configure
+dnl script appropriate for this directory. For more information, check
+dnl any existing configure script.
+
+AC_PREREQ(2.5)
+AC_INIT(cplusfuncs.cc)
+
+CC=${CC-cc}
+AC_SUBST(CC)
+AC_CONFIG_AUX_DIR(`cd $srcdir;pwd`/../../..)
+AC_CANONICAL_SYSTEM
+
+AC_OUTPUT(Makefile)
diff --git a/gdb/testsuite/gdb.c++/cplusfuncs.cc b/gdb/testsuite/gdb.c++/cplusfuncs.cc
new file mode 100644
index 00000000000..924cf54b262
--- /dev/null
+++ b/gdb/testsuite/gdb.c++/cplusfuncs.cc
@@ -0,0 +1,185 @@
+#include <stddef.h>
+
+class foo {
+public:
+ foo (int);
+ foo (int, const char *);
+ foo (foo&);
+ ~foo ();
+
+ void operator * (foo&);
+ void operator % (foo&);
+ void operator - (foo&);
+ void operator >> (foo&);
+ void operator != (foo&);
+ void operator > (foo&);
+ void operator >= (foo&);
+ void operator | (foo&);
+ void operator && (foo&);
+ void operator ! (void);
+ void operator ++ (int);
+ void operator = (foo&);
+ void operator += (foo&);
+ void operator *= (foo&);
+ void operator %= (foo&);
+ void operator >>= (foo&);
+ void operator |= (foo&);
+ void operator , (foo&);
+ void operator / (foo&);
+ void operator + (foo&);
+ void operator << (foo&);
+ void operator == (foo&);
+ void operator < (foo&);
+ void operator <= (foo&);
+ void operator & (foo&);
+ void operator ^ (foo&);
+ void operator || (foo&);
+ void operator ~ (void);
+ void operator -- (int);
+ void operator -> (void);
+ void operator -= (foo&);
+ void operator /= (foo&);
+ void operator <<= (foo&);
+ void operator &= (foo&);
+ void operator ^= (foo&);
+ void operator ->* (foo&);
+ void operator [] (foo&);
+ void operator () (foo&);
+ void* operator new (size_t);
+ void operator delete (void *);
+ /**/ operator int ();
+ /**/ operator char* ();
+
+ int foofunc (int); // forced to have int return type, which is required
+ int foofunc (int, signed char *); // forced to have int return type, which is required
+ int ifoo;
+ const char *ccpfoo;
+};
+
+#ifdef usestubs
+extern "C" {
+ void set_debug_traps();
+ void breakpoint();
+};
+#endif
+
+main () {
+#ifdef usestubs
+ set_debug_traps();
+ breakpoint();
+#endif
+ int z=3;
+}
+
+foo::foo (int i) { ifoo = i;}
+foo::foo (int i, const char *ccp) { ifoo = i; ccpfoo = ccp; }
+foo::foo (foo& afoo) { afoo.ifoo = 0; }
+foo::~foo () {}
+
+void foo::operator * (foo& afoo) { afoo.ifoo = 0; }
+void foo::operator % (foo& afoo) { afoo.ifoo = 0; }
+void foo::operator - (foo& afoo) { afoo.ifoo = 0; }
+void foo::operator >> (foo& afoo) { afoo.ifoo = 0; }
+void foo::operator != (foo& afoo) { afoo.ifoo = 0; }
+void foo::operator > (foo& afoo) { afoo.ifoo = 0; }
+void foo::operator >= (foo& afoo) { afoo.ifoo = 0; }
+void foo::operator | (foo& afoo) { afoo.ifoo = 0; }
+void foo::operator && (foo& afoo) { afoo.ifoo = 0; }
+void foo::operator ! (void) {}
+void foo::operator ++ (int ival) { ival = 0; }
+void foo::operator = (foo& afoo) { afoo.ifoo = 0; }
+void foo::operator += (foo& afoo) { afoo.ifoo = 0; }
+void foo::operator *= (foo& afoo) { afoo.ifoo = 0; }
+void foo::operator %= (foo& afoo) { afoo.ifoo = 0; }
+void foo::operator >>= (foo& afoo) { afoo.ifoo = 0; }
+void foo::operator |= (foo& afoo) { afoo.ifoo = 0; }
+void foo::operator , (foo& afoo) { afoo.ifoo = 0; }
+void foo::operator / (foo& afoo) { afoo.ifoo = 0; }
+void foo::operator + (foo& afoo) { afoo.ifoo = 0; }
+void foo::operator << (foo& afoo) { afoo.ifoo = 0; }
+void foo::operator == (foo& afoo) { afoo.ifoo = 0; }
+void foo::operator < (foo& afoo) { afoo.ifoo = 0; }
+void foo::operator <= (foo& afoo) { afoo.ifoo = 0; }
+void foo::operator & (foo& afoo) { afoo.ifoo = 0; }
+void foo::operator ^ (foo& afoo) { afoo.ifoo = 0; }
+void foo::operator || (foo& afoo) { afoo.ifoo = 0; }
+void foo::operator ~ (void) {}
+void foo::operator -- (int ival) { ival = 0; }
+void foo::operator -> (void) {}
+void foo::operator -= (foo& afoo) { afoo.ifoo = 0; }
+void foo::operator /= (foo& afoo) { afoo.ifoo = 0; }
+void foo::operator <<= (foo& afoo) { afoo.ifoo = 0; }
+void foo::operator &= (foo& afoo) { afoo.ifoo = 0; }
+void foo::operator ^= (foo& afoo) { afoo.ifoo = 0; }
+void foo::operator ->* (foo& afoo) { afoo.ifoo = 0; }
+void foo::operator [] (foo& afoo) { afoo.ifoo = 0; }
+void foo::operator () (foo& afoo) { afoo.ifoo = 0; }
+void* foo::operator new (size_t ival) { ival = 0; return 0; }
+void foo::operator delete (void *ptr) { ptr = 0; }
+/**/ foo::operator int () { return 0; }
+/**/ foo::operator char* () { return 0; }
+
+/* Some functions to test overloading by varying one argument type. */
+
+void overload1arg (void) { }
+void overload1arg (char arg) { arg = 0; }
+void overload1arg (signed char arg) { arg = 0; }
+void overload1arg (unsigned char arg) { arg = 0; }
+void overload1arg (short arg) { arg = 0; }
+void overload1arg (unsigned short arg) { arg = 0; }
+void overload1arg (int arg) { arg = 0; }
+void overload1arg (unsigned int arg) { arg = 0; }
+void overload1arg (long arg) { arg = 0; }
+void overload1arg (unsigned long arg) { arg = 0; }
+void overload1arg (float arg) { arg = 0; }
+void overload1arg (double arg) { arg = 0; }
+
+/* Some functions to test overloading by varying argument count. */
+
+void overloadargs (int a1) { a1 = 0; }
+void overloadargs (int a1, int a2) { a1 = a2 = 0; }
+void overloadargs (int a1, int a2, int a3) { a1 = a2 = a3 = 0; }
+void overloadargs (int a1, int a2, int a3, int a4)
+ { a1 = a2 = a3 = a4 = 0; }
+void overloadargs (int a1, int a2, int a3, int a4, int a5)
+ { a1 = a2 = a3 = a4 = a5 = 0; }
+void overloadargs (int a1, int a2, int a3, int a4, int a5, int a6)
+ { a1 = a2 = a3 = a4 = a5 = a6 = 0; }
+void overloadargs (int a1, int a2, int a3, int a4, int a5, int a6, int a7)
+ { a1 = a2 = a3 = a4 = a5 = a6 = a7 = 0; }
+void overloadargs (int a1, int a2, int a3, int a4, int a5, int a6, int a7,
+ int a8)
+ { a1 = a2 = a3 = a4 = a5 = a6 = a7 = a8 = 0; }
+void overloadargs (int a1, int a2, int a3, int a4, int a5, int a6, int a7,
+ int a8, int a9)
+ { a1 = a2 = a3 = a4 = a5 = a6 = a7 = a8 = a9 = 0; }
+void overloadargs (int a1, int a2, int a3, int a4, int a5, int a6, int a7,
+ int a8, int a9, int a10)
+ { a1 = a2 = a3 = a4 = a5 = a6 = a7 = a8 = a9 =
+ a10 = 0; }
+void overloadargs (int a1, int a2, int a3, int a4, int a5, int a6, int a7,
+ int a8, int a9, int a10, int a11)
+ { a1 = a2 = a3 = a4 = a5 = a6 = a7 = a8 = a9 =
+ a10 = a11 == 0; }
+
+/* Some hairy function definitions.
+ Use typedefs to help maintain sanity. */
+
+typedef int (*PFPc_i)(char *);
+typedef short (*PFPl_s)(long *);
+typedef short (*PFPc_s)(char *);
+typedef int (*PFl_i)(long);
+typedef PFl_i (*PFPc_PFl_i)(char *);
+typedef PFl_i (*PFPi_PFl_i)(int *);
+typedef PFl_i (*PFPFPc_i_PFl_i)(PFPc_i);
+typedef PFl_i (*PFs_PFl_i)(short);
+typedef int (*PFPFPl_s_i)(PFPl_s);
+typedef int (*PFPFPc_s_i)(PFPc_s);
+
+PFs_PFl_i hairyfunc1 (int arg) { arg = 0; return 0; }
+int hairyfunc2 (PFPc_i arg) { arg = 0; return 0; }
+int hairyfunc3 (PFPFPl_s_i arg) { arg = 0; return 0; }
+int hairyfunc4 (PFPFPc_s_i arg) { arg = 0; return 0; }
+int hairyfunc5 (PFPc_PFl_i arg) { arg = 0; return 0; }
+int hairyfunc6 (PFPi_PFl_i arg) { arg = 0; return 0; }
+int hairyfunc7 (PFPFPc_i_PFl_i arg) { arg = 0; return 0; }
diff --git a/gdb/testsuite/gdb.c++/cplusfuncs.exp b/gdb/testsuite/gdb.c++/cplusfuncs.exp
new file mode 100644
index 00000000000..e36d3793447
--- /dev/null
+++ b/gdb/testsuite/gdb.c++/cplusfuncs.exp
@@ -0,0 +1,300 @@
+# Copyright (C) 1992, 1997 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file was written by Fred Fish. (fnf@cygnus.com)
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+# Check to see if we have an executable to test. If not, then either we
+# haven't tried to compile one, or the compilation failed for some reason.
+# In either case, just notify the user and skip the tests in this file.
+
+set testfile "cplusfuncs"
+set srcfile ${testfile}.cc
+set binfile ${objdir}/${subdir}/${testfile}
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug c++}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+#
+# Cause gdb to lookup a specific C++ function and print the demangled
+# form.
+#
+
+proc info_func { regex demangled } {
+ global gdb_prompt
+
+ send_gdb "info function $regex\n"
+ gdb_expect {
+ -re "File .*:\r\n$demangled\r\n$gdb_prompt $" {
+ pass "info function for \"$regex\""
+ }
+ -re ".*$gdb_prompt $" {
+ fail "info function for \"$regex\""
+ }
+ timeout {
+ fail "info function for \"$regex\" (timeout)"
+ }
+ }
+}
+
+#
+# Run print &'$arg' on the input arg and verify that we can correctly
+# lookup the fully qualified C++ function.
+# We ignore the return type of the function since we are only interested
+# in the rootname and arguments part.
+#
+
+proc print_addr_of { arg } {
+ global gdb_prompt
+ global hex
+
+ set pattern [string_to_regexp $arg]
+ send_gdb "print &'$arg'\n"
+ gdb_expect {
+ -re ".* = .* $hex <$pattern>\r\n$gdb_prompt $" { pass "print &'$arg'" }
+ -re ".*$gdb_prompt $" {
+ fail "print &'$arg'"
+ }
+ timeout {
+ fail "print &'$arg' (timeout)"
+ }
+ }
+}
+
+#
+# Test name demangling for operators.
+#
+# The '(' at the end of each regex input pattern is so that we match only
+# the one we are looking for. I.E. "operator&" would match both
+# "operator&(foo &)" and "operator&&(foo &)".
+#
+
+proc test_lookup_operator_functions {} {
+
+ # These tests don't work for COFF targets; don't even try them
+ if [istarget "a29k-*-udi"] then {
+ setup_xfail "a29k-*-udi"
+ fail "skipping operator tests"
+ return
+ }
+
+ info_func "operator&&(" "void foo::operator&&\\(foo &\\);"
+ info_func "operator&=(" "void foo::operator&=\\(foo &\\);"
+ info_func "operator&(" "void foo::operator&\\(foo &\\);"
+ info_func "operator/=(" "void foo::operator/=\\(foo &\\);"
+ info_func "operator^=(" "void foo::operator.=\\(foo &\\);"
+ info_func "operator<<=(" "void foo::operator<<=\\(foo &\\);"
+ info_func "operator%=(" "void foo::operator%=\\(foo &\\);"
+ info_func "operator-=(" "void foo::operator-=\\(foo &\\);"
+
+ # There doesn't appear to be any way to get GDB to treat '*' as a
+ # character to match, rather than as a regex special character.
+ setup_xfail "*-*-*"
+ info_func "operator\*=(" "void foo::operator\\*=\\(foo &\\);"
+
+ info_func "operator|=(" "void foo::operator\\|=\\(foo &\\);"
+ info_func "operator+=(" "void foo::operator.=\\(foo &\\);"
+ info_func "operator>>=(" "void foo::operator\>\>=\\(foo &\\);"
+ info_func "operator=(" "void foo::operator=\\(foo &\\);"
+ info_func "operator()(" "void foo::operator\\(\\)\\(foo &\\);"
+
+ # The function should be "operator," not "operator, ". (note space)
+ # This test will work; I've commented it out because it should not
+ # count as a pass, since it is incorrect. Ian Taylor.
+ # info_func "operator, (" "void foo::operator, \\(foo &\\);"
+ setup_xfail "*-*-*"
+ info_func "operator,(" "void foo::operator,\\(foo &\\);"
+
+ info_func "operator~(" "void foo::operator~\\(void\\);"
+ info_func "operator delete(" "void foo::operator delete\\(void \\*\\);"
+ info_func "operator/(" "void foo::operator/\\(foo &\\);"
+ info_func "operator==(" "void foo::operator==\\(foo &\\);"
+ info_func "operator^(" "void foo::operator\\^\\(foo &\\);"
+
+ info_func "operator>=(" "void foo::operator>=\\(foo &\\);"
+ info_func "operator>(" "void foo::operator>\\(foo &\\);"
+ info_func "operator<=(" "void foo::operator<=\\(foo &\\);"
+ info_func "operator<<(" "void foo::operator<<\\(foo &\\);"
+ info_func "operator<(" "void foo::operator<\\(foo &\\);"
+ info_func "operator%(" "void foo::operator%\\(foo &\\);"
+ info_func "operator-(" "void foo::operator-\\(foo &\\);"
+
+ # There doesn't appear to be anyway to get '*' treated as a character
+ # to match, rather than as a regex special character.
+ setup_xfail "*-*-*"
+ info_func "operator\*(" "void foo::operator\\*\\(foo &\\);"
+
+ info_func "operator--(" "void foo::operator--\\(int\\);"
+ info_func "operator!=(" "void foo::operator!=\\(foo &\\);"
+ info_func "operator!(" "void foo::operator!\\(void\\);"
+ info_func "operator new(" "void \\*foo::operator new\\(.*\\);"
+ info_func "operator||(" "void foo::operator\\|\\|\\(foo &\\);"
+ info_func "operator char \\*(" "char \\*foo::operator char \\*\\(void\\);"
+ info_func "operator int(" "int foo::operator int\\(void\\);"
+ info_func "operator|(" "void foo::operator\\|\\(foo &\\);"
+ info_func "operator+(" "void foo::operator\\+\\(foo &\\);"
+ info_func "operator++(" "void foo::operator\\+\\+\\(int\\);"
+ info_func "operator->(" "void foo::operator->\\(void\\);"
+ info_func "operator->\\*(" "void foo::operator->\\*\\(foo &\\);"
+ info_func "operator>>(" "void foo::operator\>\>\\(foo &\\);"
+
+ # GDB says "`operator \[\](' not supported". I don't know why.
+ setup_xfail "*-*-*"
+ info_func "operator\\\[\\\](" "void foo::operator\\\[\\\]\\(foo &\\);"
+ # But this works, for some reason.
+ info_func ".perator\\\[\\\](" "void foo::operator\\\[\\\]\\(foo &\\);"
+}
+
+
+proc test_paddr_operator_functions {} {
+ global hex
+
+ print_addr_of "foo::operator&&(foo &)"
+ print_addr_of "foo::operator&=(foo &)"
+ print_addr_of "foo::operator&(foo &)"
+ print_addr_of "foo::operator/=(foo &)"
+ print_addr_of "foo::operator^=(foo &)"
+ print_addr_of "foo::operator<<=(foo &)"
+ print_addr_of "foo::operator%=(foo &)"
+ print_addr_of "foo::operator-=(foo &)"
+ print_addr_of "foo::operator*=(foo &)"
+ print_addr_of "foo::operator|=(foo &)"
+ print_addr_of "foo::operator+=(foo &)"
+ print_addr_of "foo::operator>>=(foo &)"
+ print_addr_of "foo::operator=(foo &)"
+ print_addr_of "foo::operator()(foo &)"
+ print_addr_of "foo::operator, (foo &)"
+ print_addr_of "foo::operator~(void)"
+ print_addr_of "foo::operator delete(void *)"
+ print_addr_of "foo::operator/(foo &)"
+ print_addr_of "foo::operator==(foo &)"
+ print_addr_of "foo::operator^(foo &)"
+ print_addr_of "foo::operator>=(foo &)"
+ print_addr_of "foo::operator>(foo &)"
+ print_addr_of "foo::operator<=(foo &)"
+ print_addr_of "foo::operator<<(foo &)"
+ print_addr_of "foo::operator<(foo &)"
+ print_addr_of "foo::operator%(foo &)"
+ print_addr_of "foo::operator-(foo &)"
+ print_addr_of "foo::operator*(foo &)"
+ print_addr_of "foo::operator--(int)"
+ print_addr_of "foo::operator!=(foo &)"
+ print_addr_of "foo::operator!(void)"
+ gdb_test "print &'foo::operator new'" \
+ " = .* $hex <foo::operator new\\(.*\\)>"
+ print_addr_of "foo::operator||(foo &)"
+ print_addr_of "foo::operator char *(void)"
+ print_addr_of "foo::operator int(void)"
+ print_addr_of "foo::operator|(foo &)"
+ print_addr_of "foo::operator+(foo &)"
+ print_addr_of "foo::operator++(int)"
+ print_addr_of "foo::operator->(void)"
+ print_addr_of "foo::operator->*(foo &)"
+ print_addr_of "foo::operator>>(foo &)"
+ gdb_test "print &'foo::operator\[\](foo &)'" \
+ " = .*0x\[0-9a-f\]+ <foo::operator\\\[\\\]\\(foo &\\)>"
+}
+
+#
+# Test overloaded functions (1 arg).
+#
+
+proc test_paddr_overloaded_functions {} {
+ print_addr_of "overload1arg(signed char)"
+ print_addr_of "overload1arg(unsigned char)"
+ print_addr_of "overload1arg(unsigned int)"
+ print_addr_of "overload1arg(unsigned long)"
+ print_addr_of "overload1arg(unsigned short)"
+ print_addr_of "overload1arg(char)"
+ print_addr_of "overload1arg(double)"
+ print_addr_of "overload1arg(float)"
+ print_addr_of "overload1arg(int)"
+ print_addr_of "overload1arg(long)"
+ print_addr_of "overload1arg(short)"
+ print_addr_of "overload1arg(void)"
+ print_addr_of "overloadargs(int)"
+ print_addr_of "overloadargs(int, int)"
+ print_addr_of "overloadargs(int, int, int)"
+ print_addr_of "overloadargs(int, int, int, int)"
+ print_addr_of "overloadargs(int, int, int, int, int)"
+ print_addr_of "overloadargs(int, int, int, int, int, int)"
+ print_addr_of "overloadargs(int, int, int, int, int, int, int)"
+ print_addr_of "overloadargs(int, int, int, int, int, int, int, int)"
+ print_addr_of "overloadargs(int, int, int, int, int, int, int, int, int)"
+ print_addr_of "overloadargs(int, int, int, int, int, int, int, int, int, int)"
+ print_addr_of "overloadargs(int, int, int, int, int, int, int, int, int, int, int)"
+}
+
+proc test_paddr_hairy_functions {} {
+ print_addr_of "hairyfunc1(int)"
+ print_addr_of "hairyfunc2(int (*)(char *))"
+ print_addr_of "hairyfunc3(int (*)(short (*)(long *)))"
+ print_addr_of "hairyfunc4(int (*)(short (*)(char *)))"
+ print_addr_of "hairyfunc5(int (*(*)(char *))(long))"
+ print_addr_of "hairyfunc6(int (*(*)(int *))(long))"
+ print_addr_of "hairyfunc7(int (*(*)(int (*)(char *)))(long))"
+}
+
+proc do_tests {} {
+ global prms_id
+ global bug_id
+ global subdir
+ global objdir
+ global srcdir
+ global binfile
+ global gdb_prompt
+
+ set prms_id 0
+ set bug_id 0
+
+ # Start with a fresh gdb.
+
+ gdb_exit
+ gdb_start
+ gdb_reinitialize_dir $srcdir/$subdir
+ gdb_load $binfile
+
+ send_gdb "set language c++\n"
+ gdb_expect -re "$gdb_prompt $"
+ send_gdb "set width 0\n"
+ gdb_expect -re "$gdb_prompt $"
+
+ # Get the debug format for the compiled test case. If that
+ # format is DWARF 1 then just skip all the tests since none of
+ # them will pass.
+
+ if [ runto_main] then {
+ get_debug_format
+ if [ setup_xfail_format "DWARF 1" ] then {
+ fail "C++ tests skipped due to limited C++ support in DWARF 1 debug format"
+ return
+ }
+ clear_xfail "*-*-*"
+ }
+
+ test_paddr_overloaded_functions
+ test_paddr_operator_functions
+ test_paddr_hairy_functions
+ test_lookup_operator_functions
+}
+
+do_tests
diff --git a/gdb/testsuite/gdb.c++/demangle.exp b/gdb/testsuite/gdb.c++/demangle.exp
new file mode 100644
index 00000000000..fd1d344adcd
--- /dev/null
+++ b/gdb/testsuite/gdb.c++/demangle.exp
@@ -0,0 +1,1517 @@
+# Copyright (C) 1992, 1997 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file was written by Fred Fish. (fnf@cygnus.com)
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+#
+# Test gnu style name demangling
+#
+
+proc test_gnu_style_demangling {} {
+ global gdb_prompt
+
+ # Set the demangling style to "gnu" and then check to make sure
+ # it really got set. Return if the style failed to get set for
+ # some reason.
+
+ send_gdb "set demangle-style gnu\n"
+ gdb_expect {
+ -re "set demangle-style gnu\[\r\n\]+$gdb_prompt $" {}
+ -re ".*$gdb_prompt $" { fail "set demangle-style gnu failed" ; return }
+ timeout { fail "set demangle-style gnu failed (timeout)" ; return }
+ }
+
+ send_gdb "show demangle-style\n"
+ gdb_expect {
+ -re "The current C\[+\]+ demangling style is \"gnu\".\r\n$gdb_prompt $" {}
+ -re ".*$gdb_prompt $" { fail "demangling style not set to gnu" }
+ timeout { fail "show demangle-style timed out" }
+ }
+
+ gdb_test "maint dem Abort__FP6EditoriPCc" \
+ "Abort\[(\]+Editor \[*\]+, int, (const char|char const) \[*\]+\[)\]+"
+ gdb_test_exact "maint demangle AddAlignment__9ivTSolverUiP12ivInteractorP7ivTGlue" "ivTSolver::AddAlignment(unsigned int, ivInteractor *, ivTGlue *)"
+ gdb_test "maint dem Append__15NameChooserViewPCc" \
+ "NameChooserView::Append\[(\]+(const char|char const) \[*\]+\[)\]+"
+ gdb_test_exact "maint demangle ArrowheadIntersects__9ArrowLineP9ArrowheadR6BoxObjP7Graphic" "ArrowLine::ArrowheadIntersects(Arrowhead *, BoxObj &, Graphic *)"
+ gdb_test_exact "maint demangle AtEnd__13ivRubberGroup" "ivRubberGroup::AtEnd(void)"
+ gdb_test_exact "maint demangle BgFilter__9ivTSolverP12ivInteractor" "ivTSolver::BgFilter(ivInteractor *)"
+ gdb_test "maint dem BitPatterntoa__FRC10BitPatternccc" \
+ "BitPatterntoa\[(\]+(const BitPattern|BitPattern const) &, char, char, char\[)\]+"
+ gdb_test_exact "maint demangle Check__6UArrayi" "UArray::Check(int)"
+ gdb_test_exact "maint demangle CoreConstDecls__8TextCodeR7ostream" "TextCode::CoreConstDecls(ostream &)"
+ gdb_test_exact "maint demangle Detach__8StateVarP12StateVarView" "StateVar::Detach(StateVarView *)"
+ gdb_test_exact "maint demangle Done__9ComponentG8Iterator" "Component::Done(Iterator)"
+ gdb_test "maint dem DrawDestinationTransformedImage__FP7_XImageiiT0iiUlUiiiUiUlUlP4_XGCRC13ivTransformeriiii" \
+ "DrawDestinationTransformedImage\[(\]+_XImage \[*\]+, int, int, _XImage \[*\]+, int, int, unsigned long, unsigned int, int, int, unsigned int, unsigned long, unsigned long, _XGC \[*\]+, (const ivTransformer|ivTransformer const) &, int, int, int, int\[)\]+"
+
+ gdb_test "maint dem Edit__12StringEditorPCcii" \
+ "StringEditor::Edit\[(\]+(const char|char const) \[*\]+, int, int\[)\]+"
+ gdb_test_exact "maint demangle Effect__11RelateManipR7ivEvent" "RelateManip::Effect(ivEvent &)"
+ gdb_test "maint dem FilterName__FPCc" \
+ "FilterName\[(\]+(const char|char const) \[*\]+\[)\]+"
+ gdb_test "maint dem Filter__6PSTextPCci" \
+ "PSText::Filter\[(\]+(const char|char const) \[*\]+, int\[)\]+"
+ gdb_test "maint dem FindColor__7CatalogPCciii" \
+ "Catalog::FindColor\[(\]+(const char|char const) \[*\]+, int, int, int\[)\]+"
+ gdb_test_exact "maint demangle FindFixed__FRP4CNetP4CNet" "FindFixed(CNet *&, CNet *)"
+ gdb_test "maint dem FindFont__7CatalogPCcN21" \
+ "Catalog::FindFont\[(\]+(const char|char const) \[*\]+, (const char|char const) \[*\]+, (const char|char const) \[*\]+\[)\]+"
+ gdb_test_exact "maint demangle Fix48_abort__FR8twolongs" "Fix48_abort(twolongs &)"
+ gdb_test_exact "maint demangle GetBarInfo__15iv2_6_VScrollerP13ivPerspectiveRiT2" "iv2_6_VScroller::GetBarInfo(ivPerspective *, int &, int &)"
+ gdb_test_exact "maint demangle GetBgColor__C9ivPainter" "ivPainter::GetBgColor(void) const"
+
+ gdb_test "maint dem Iisdouble__FPC6IntRep" \
+ "Iisdouble\[(\]+(const IntRep|IntRep const) \[*\]+\[)\]+"
+ gdb_test_exact "maint demangle InsertBody__15H_PullrightMenuii" "H_PullrightMenu::InsertBody(int, int)"
+ gdb_test_exact "maint demangle InsertCharacter__9TextManipc" "TextManip::InsertCharacter(char)"
+
+ gdb_test_exact "maint demangle InsertToplevel__7ivWorldP12ivInteractorT1" "ivWorld::InsertToplevel(ivInteractor *, ivInteractor *)"
+ gdb_test_exact "maint demangle InsertToplevel__7ivWorldP12ivInteractorT1iiUi" "ivWorld::InsertToplevel(ivInteractor *, ivInteractor *, int, int, unsigned int)"
+ gdb_test "maint dem IsADirectory__FPCcR4stat" \
+ "IsADirectory\[(\]+(const char|char const) \[*\]+, stat &\[)\]+"
+ gdb_test_exact "maint demangle IsAGroup__FP11GraphicViewP11GraphicComp" "IsAGroup(GraphicView *, GraphicComp *)"
+ gdb_test_exact "maint demangle IsA__10ButtonCodeUl" "ButtonCode::IsA(unsigned long)"
+
+ gdb_test_exact "maint demangle ReadName__FR7istreamPc" "ReadName(istream &, char *)"
+ gdb_test_exact "maint demangle Redraw__13StringBrowseriiii" "StringBrowser::Redraw(int, int, int, int)"
+ gdb_test_exact "maint demangle Rotate__13ivTransformerf" "ivTransformer::Rotate(float)"
+ gdb_test_exact "maint demangle Rotated__C13ivTransformerf" "ivTransformer::Rotated(float) const"
+ gdb_test_exact "maint demangle Round__Ff" "Round(float)"
+
+ gdb_test_exact "maint demangle SetExport__16MemberSharedNameUi" "MemberSharedName::SetExport(unsigned int)"
+ gdb_test_exact "maint demangle Set__14ivControlState13ControlStatusUi" "ivControlState::Set(ControlStatus, unsigned int)"
+ gdb_test_exact "maint demangle Set__5DFacePcii" "DFace::Set(char *, int, int)"
+
+ gdb_test_exact "maint demangle VConvert__9ivTSolverP12ivInteractorRP8TElementT2" "ivTSolver::VConvert(ivInteractor *, TElement *&, TElement *&)"
+ gdb_test_exact "maint demangle VConvert__9ivTSolverP7ivTGlueRP8TElement" "ivTSolver::VConvert(ivTGlue *, TElement *&)"
+ gdb_test_exact "maint demangle VOrder__9ivTSolverUiRP12ivInteractorT2" "ivTSolver::VOrder(unsigned int, ivInteractor *&, ivInteractor *&)"
+ gdb_test "maint dem Valid__7CatalogPCcRP4Tool" \
+ "Catalog::Valid\[(\]+(const char|char const) \[*\]+, Tool \[*\]+&\[)\]+"
+ gdb_test_exact "maint demangle _10PageButton\$__both" "PageButton::__both"
+ gdb_test_exact "maint demangle _3RNG\$singleMantissa" "RNG::singleMantissa"
+ gdb_test_exact "maint demangle _5IComp\$_release" "IComp::_release"
+ gdb_test_exact "maint demangle _\$_10BitmapComp" "BitmapComp::~BitmapComp(void)"
+
+ gdb_test_exact "maint demangle _\$_9__io_defs" "__io_defs::~__io_defs(void)"
+ gdb_test_exact "maint demangle _\$_Q23foo3bar" "foo::bar::~bar(void)"
+ gdb_test_exact "maint demangle _\$_Q33foo3bar4bell" "foo::bar::bell::~bell(void)"
+ gdb_test_exact "maint demangle __10ivTelltaleiP7ivGlyph" "ivTelltale::ivTelltale(int, ivGlyph *)"
+ gdb_test_exact "maint demangle __10ivViewportiP12ivInteractorUi" "ivViewport::ivViewport(int, ivInteractor *, unsigned int)"
+ gdb_test_exact "maint demangle __10ostrstream" "ostrstream::ostrstream(void)"
+ gdb_test_exact "maint demangle __10ostrstreamPcii" "ostrstream::ostrstream(char *, int, int)"
+ gdb_test "maint dem __11BasicDialogiPCcP13ivButtonStateN22Ui" \
+ "BasicDialog::BasicDialog\[(\]+int, (const char|char const) \[*\]+, ivButtonState \[*\]+, (const char|char const) \[*\]+, (const char|char const) \[*\]+, unsigned int\[)\]+"
+ gdb_test_exact "maint demangle __11BitmapTablei" "BitmapTable::BitmapTable(int)"
+ gdb_test_exact "maint demangle __12ViewportCodeP12ViewportComp" "ViewportCode::ViewportCode(ViewportComp *)"
+ gdb_test "maint dem __12iv2_6_BorderiPCci" \
+ "iv2_6_Border::iv2_6_Border\[(\]+int, (const char|char const) \[*\]+, int\[)\]+"
+ gdb_test_exact "maint demangle __12iv2_6_Borderii" "iv2_6_Border::iv2_6_Border(int, int)"
+ gdb_test "maint dem __12ivBackgroundiP7ivGlyphPC7ivColor" \
+ "ivBackground::ivBackground\[(\]+int, ivGlyph \[*\]+, (const ivColor|ivColor const) \[*\]+\[)\]+"
+ gdb_test_exact "maint demangle __12ivBreak_Listl" "ivBreak_List::ivBreak_List(long)"
+ gdb_test "maint dem __14TextInteractoriPCcUi" \
+ "TextInteractor::TextInteractor\[(\]+int, (const char|char const) \[*\]+, unsigned int\[)\]+"
+ gdb_test_exact "maint demangle __14iv2_6_MenuItemiP12ivInteractor" "iv2_6_MenuItem::iv2_6_MenuItem(int, ivInteractor *)"
+ gdb_test "maint dem __14iv2_6_MenuItemiPCcP12ivInteractor" \
+ "iv2_6_MenuItem::iv2_6_MenuItem\[(\]+int, (const char|char const) \[*\]+, ivInteractor \[*\]+\[)\]+"
+
+ gdb_test_exact "maint demangle __20DisplayList_IteratorR11DisplayList" "DisplayList_Iterator::DisplayList_Iterator(DisplayList &)"
+ gdb_test_exact "maint demangle __3fooRT0" "foo::foo(foo &)"
+ gdb_test_exact "maint demangle __3fooiN31" "foo::foo(int, int, int, int)"
+ gdb_test "maint dem __3fooiPCc" \
+ "foo::foo\[(\]+int, (const char|char const) \[*\]+\[)\]+"
+ gdb_test_exact "maint demangle __3fooiRT0iT2iT2" "foo::foo(int, foo &, int, foo &, int, foo &)"
+ gdb_test "maint dem __6GetOptiPPcPCc" \
+ "GetOpt::GetOpt\[(\]+int, char \[*\]+\[*\]+, (const char|char const) \[*\]+\[)\]+"
+ gdb_test_exact "maint demangle __6KeyMapPT0" "KeyMap::KeyMap(KeyMap *)"
+ gdb_test "maint dem __7ivWorldPCcRiPPcPC12ivOptionDescPC14ivPropertyData" \
+ "ivWorld::ivWorld\[(\]+(const char|char const) \[*\]+, int &, char \[*\]+\[*\]+, (const ivOptionDesc|ivOptionDesc const) \[*\]+, (const ivPropertyData|ivPropertyData const) \[*\]+\[)\]+"
+ gdb_test "maint dem __7procbufPCci" \
+ "procbuf::procbuf\[(\]+(const char|char const) \[*\]+, int\[)\]+"
+ gdb_test_exact "maint demangle __8ArrowCmdP6EditorUiUi" "ArrowCmd::ArrowCmd(Editor *, unsigned int, unsigned int)"
+
+ gdb_test_exact "maint demangle __9F_EllipseiiiiP7Graphic" "F_Ellipse::F_Ellipse(int, int, int, int, Graphic *)"
+ gdb_test_exact "maint demangle __9FrameDataP9FrameCompi" "FrameData::FrameData(FrameComp *, int)"
+ gdb_test_exact "maint demangle __9HVGraphicP9CanvasVarP7Graphic" "HVGraphic::HVGraphic(CanvasVar *, Graphic *)"
+ gdb_test_exact "maint demangle __Q23foo3bar" "foo::bar::bar(void)"
+ gdb_test_exact "maint demangle __Q33foo3bar4bell" "foo::bar::bell::bell(void)"
+ gdb_test_exact "maint demangle __aa__3fooRT0" "foo::operator&&(foo &)"
+ gdb_test_exact "maint demangle __aad__3fooRT0" "foo::operator&=(foo &)"
+ gdb_test_exact "maint demangle __ad__3fooRT0" "foo::operator&(foo &)"
+ gdb_test_exact "maint demangle __adv__3fooRT0" "foo::operator/=(foo &)"
+ gdb_test_exact "maint demangle __aer__3fooRT0" "foo::operator^=(foo &)"
+ gdb_test_exact "maint demangle __als__3fooRT0" "foo::operator<<=(foo &)"
+ gdb_test_exact "maint demangle __amd__3fooRT0" "foo::operator%=(foo &)"
+ gdb_test_exact "maint demangle __ami__3fooRT0" "foo::operator-=(foo &)"
+ gdb_test_exact "maint demangle __aml__3FixRT0" "Fix::operator*=(Fix &)"
+ gdb_test_exact "maint demangle __aml__5Fix16i" "Fix16::operator*=(int)"
+ gdb_test_exact "maint demangle __aml__5Fix32RT0" "Fix32::operator*=(Fix32 &)"
+ gdb_test_exact "maint demangle __aor__3fooRT0" "foo::operator|=(foo &)"
+ gdb_test_exact "maint demangle __apl__3fooRT0" "foo::operator+=(foo &)"
+ gdb_test_exact "maint demangle __ars__3fooRT0" "foo::operator>>=(foo &)"
+
+ gdb_test_exact "maint demangle __as__3fooRT0" "foo::operator=(foo &)"
+ gdb_test_exact "maint demangle __cl__3fooRT0" "foo::operator()(foo &)"
+ gdb_test_exact "maint demangle __cl__6Normal" "Normal::operator()(void)"
+ gdb_test_exact "maint demangle __cl__6Stringii" "String::operator()(int, int)"
+ gdb_test_exact "maint demangle __cm__3fooRT0" "foo::operator, (foo &)"
+ gdb_test_exact "maint demangle __co__3foo" "foo::operator~(void)"
+ gdb_test_exact "maint demangle __dl__3fooPv" "foo::operator delete(void *)"
+ gdb_test_exact "maint demangle __dv__3fooRT0" "foo::operator/(foo &)"
+ gdb_test_exact "maint demangle __eq__3fooRT0" "foo::operator==(foo &)"
+ gdb_test_exact "maint demangle __er__3fooRT0" "foo::operator^(foo &)"
+ gdb_test_exact "maint demangle __ge__3fooRT0" "foo::operator>=(foo &)"
+ gdb_test_exact "maint demangle __gt__3fooRT0" "foo::operator>(foo &)"
+ gdb_test_exact "maint demangle __le__3fooRT0" "foo::operator<=(foo &)"
+ gdb_test_exact "maint demangle __ls__3fooRT0" "foo::operator<<(foo &)"
+ gdb_test_exact "maint demangle __ls__FR7ostreamPFR3ios_R3ios" "operator<<(ostream &, ios &(*)(ios &))"
+ gdb_test_exact "maint demangle __ls__FR7ostreamR3Fix" "operator<<(ostream &, Fix &)"
+ gdb_test_exact "maint demangle __lt__3fooRT0" "foo::operator<(foo &)"
+ gdb_test_exact "maint demangle __md__3fooRT0" "foo::operator%(foo &)"
+ gdb_test_exact "maint demangle __mi__3fooRT0" "foo::operator-(foo &)"
+ gdb_test_exact "maint demangle __ml__3fooRT0" "foo::operator*(foo &)"
+ gdb_test_exact "maint demangle __mm__3fooi" "foo::operator--(int)"
+
+ gdb_test_exact "maint demangle __ne__3fooRT0" "foo::operator!=(foo &)"
+ gdb_test "maint dem __ne__FRC7ComplexT0" \
+ "operator!=\[(\]+(const Complex|Complex const) &, (const Complex|Complex const) &\[)\]+"
+ gdb_test "maint dem __ne__FRC7Complexd" \
+ "operator!=\[(\]+(const Complex|Complex const) &, double\[)\]+"
+ gdb_test "maint dem __ne__FRC9SubStringRC6String" \
+ "operator!=\[(\]+(const SubString|SubString const) &, (const String|String const) &\[)\]+"
+ gdb_test_exact "maint demangle __nt__3foo" "foo::operator!(void)"
+ gdb_test_exact "maint demangle __nw__3fooi" "foo::operator new(int)"
+ gdb_test_exact "maint demangle __oo__3fooRT0" "foo::operator||(foo &)"
+ gdb_test_exact "maint demangle __opPc__3foo" "foo::operator char *(void)"
+ gdb_test_exact "maint demangle __opi__3foo" "foo::operator int(void)"
+ gdb_test_exact "maint demangle __or__3fooRT0" "foo::operator|(foo &)"
+ gdb_test_exact "maint demangle __pl__3fooRT0" "foo::operator+(foo &)"
+ gdb_test_exact "maint demangle __pp__3fooi" "foo::operator++(int)"
+ gdb_test_exact "maint demangle __rf__3foo" "foo::operator->(void)"
+ gdb_test_exact "maint demangle __rm__3fooRT0" "foo::operator->*(foo &)"
+ gdb_test_exact "maint demangle __rs__3fooRT0" "foo::operator>>(foo &)"
+ gdb_test "maint dem __vc__3fooRT0" "foo::operator\\\[\\\]\\(foo &\\)"
+ gdb_test "maint dem _gsub__6StringRC5RegexPCci" \
+ "String::_gsub\[(\]+(const Regex|Regex const) &, (const char|char const) \[*\]+, int\[)\]+"
+ gdb_test_exact "maint demangle _new_Fix__FUs" "_new_Fix(unsigned short)"
+
+ # gcc 2.4.5 (and earlier) style virtual tables. We want to continue to
+ # correctly demangle these even if newer compilers use a different form.
+ gdb_test_exact "maint demangle _vt.foo" "foo virtual table"
+ gdb_test_exact "maint demangle _vt.foo.bar" "foo::bar virtual table"
+ gdb_test_exact "maint demangle _vt\$foo" "foo virtual table"
+ gdb_test_exact "maint demangle _vt\$foo\$bar" "foo::bar virtual table"
+
+ gdb_test_exact "maint demangle append__7ivGlyphPT0" "ivGlyph::append(ivGlyph *)"
+ gdb_test "maint dem arg__FRC7Complex" \
+ "arg\[(\]+(const Complex|Complex const) &\[)\]+"
+ gdb_test_exact "maint demangle clearok__FP7_win_sti" "clearok(_win_st *, int)"
+
+ gdb_test_exact "maint demangle complexfunc2__FPFPc_i" "complexfunc2(int (*)(char *))"
+ gdb_test_exact "maint demangle complexfunc3__FPFPFPl_s_i" "complexfunc3(int (*)(short (*)(long *)))"
+ gdb_test_exact "maint demangle complexfunc4__FPFPFPc_s_i" "complexfunc4(int (*)(short (*)(char *)))"
+ gdb_test_exact "maint demangle complexfunc5__FPFPc_PFl_i" "complexfunc5(int (*(*)(char *))(long))"
+ gdb_test_exact "maint demangle complexfunc6__FPFPi_PFl_i" "complexfunc6(int (*(*)(int *))(long))"
+ gdb_test_exact "maint demangle complexfunc7__FPFPFPc_i_PFl_i" "complexfunc7(int (*(*)(int (*)(char *)))(long))"
+ gdb_test "maint dem contains__C9BitStringRC10BitPattern" \
+ "BitString::contains\[(\]+(const BitPattern|BitPattern const) &\[)\]+ const"
+ gdb_test "maint dem contains__C9BitStringRC12BitSubStringi" \
+ "BitString::contains\[(\]+(const BitSubString|BitSubString const) &, int\[)\]+ const"
+ gdb_test "maint dem contains__C9BitStringRT0" \
+ "BitString::contains\[(\]+(const BitString|BitString const) &\[)\]+ const"
+ gdb_test "maint dem div__FPC6IntRepT0P6IntRep" \
+ "div\[(\]+(const IntRep|IntRep const) \[*\]+, (const IntRep|IntRep const) \[*\]+, IntRep \[*\]+\[)\]+"
+ gdb_test "maint dem div__FPC6IntReplP6IntRep" \
+ "div\[(\]+(const IntRep|IntRep const) \[*\]+, long, IntRep \[*\]+\[)\]+"
+ gdb_test "maint dem div__FRC8RationalT0R8Rational" \
+ "div\[(\]+(const Rational|Rational const) &, (const Rational|Rational const) &, Rational &\[)\]+"
+ gdb_test "maint dem divide__FRC7IntegerT0R7IntegerT2" \
+ "divide\[(\]+(const Integer|Integer const) &, (const Integer|Integer const) &, Integer &, Integer &\[)\]+"
+ gdb_test "maint dem divide__FRC7IntegerlR7IntegerRl" \
+ "divide\[(\]+(const Integer|Integer const) &, long, Integer &, long &\[)\]+"
+ gdb_test "maint dem enable__14DocumentViewerPCcUi" \
+ "DocumentViewer::enable\[(\]+(const char|char const) \[*\]+, unsigned int\[)\]+"
+
+ gdb_test_exact "maint demangle foo__FiN30" "foo(int, int, int, int)"
+ gdb_test_exact "maint demangle foo__FiR3fooiT1iT1" "foo(int, foo &, int, foo &, int, foo &)"
+ gdb_test_exact "maint demangle foo___3barl" "bar::foo_(long)"
+ gdb_test_exact "maint demangle insert__15ivClippingStacklRP8_XRegion" "ivClippingStack::insert(long, _XRegion *&)"
+ gdb_test_exact "maint demangle insert__16ChooserInfo_ListlR11ChooserInfo" "ChooserInfo_List::insert(long, ChooserInfo &)"
+ gdb_test_exact "maint demangle insert__17FontFamilyRepListlRP15ivFontFamilyRep" "FontFamilyRepList::insert(long, ivFontFamilyRep *&)"
+ gdb_test_exact "maint demangle leaveok__FP7_win_stc" "leaveok(_win_st *, char)"
+ gdb_test_exact "maint demangle left_mover__C7ivMFKitP12ivAdjustableP7ivStyle" "ivMFKit::left_mover(ivAdjustable *, ivStyle *) const"
+ gdb_test "maint dem matches__C9BitStringRC10BitPatterni" \
+ "BitString::matches\[(\]+(const BitPattern|BitPattern const) &, int\[)\]+ const"
+ gdb_test "maint dem matches__C9SubStringRC5Regex" \
+ "SubString::matches\[(\]+(const Regex|Regex const) &\[)\]+ const"
+
+ gdb_test_exact "maint demangle overload1arg__FSc" "overload1arg(signed char)"
+ gdb_test_exact "maint demangle overload1arg__FUc" "overload1arg(unsigned char)"
+ gdb_test_exact "maint demangle overload1arg__FUi" "overload1arg(unsigned int)"
+ gdb_test_exact "maint demangle overload1arg__FUl" "overload1arg(unsigned long)"
+ gdb_test_exact "maint demangle overload1arg__FUs" "overload1arg(unsigned short)"
+ gdb_test_exact "maint demangle overload1arg__Fc" "overload1arg(char)"
+ gdb_test_exact "maint demangle overload1arg__Fd" "overload1arg(double)"
+ gdb_test_exact "maint demangle overload1arg__Ff" "overload1arg(float)"
+ gdb_test_exact "maint demangle overload1arg__Fi" "overload1arg(int)"
+ gdb_test_exact "maint demangle overload1arg__Fl" "overload1arg(long)"
+ gdb_test_exact "maint demangle overload1arg__Fs" "overload1arg(short)"
+ gdb_test_exact "maint demangle overload1arg__Fv" "overload1arg(void)"
+ gdb_test_exact "maint demangle overloadargs__Fi" "overloadargs(int)"
+ gdb_test_exact "maint demangle overloadargs__Fii" "overloadargs(int, int)"
+ gdb_test_exact "maint demangle overloadargs__Fiii" "overloadargs(int, int, int)"
+ gdb_test_exact "maint demangle overloadargs__Fiiii" "overloadargs(int, int, int, int)"
+
+ gdb_test_exact "maint demangle overloadargs__Fiiiii" "overloadargs(int, int, int, int, int)"
+ gdb_test_exact "maint demangle overloadargs__Fiiiiii" "overloadargs(int, int, int, int, int, int)"
+ gdb_test_exact "maint demangle overloadargs__Fiiiiiii" "overloadargs(int, int, int, int, int, int, int)"
+ gdb_test_exact "maint demangle overloadargs__Fiiiiiiii" "overloadargs(int, int, int, int, int, int, int, int)"
+ gdb_test_exact "maint demangle overloadargs__Fiiiiiiiii" "overloadargs(int, int, int, int, int, int, int, int, int)"
+ gdb_test_exact "maint demangle overloadargs__Fiiiiiiiiii" "overloadargs(int, int, int, int, int, int, int, int, int, int)"
+ gdb_test_exact "maint demangle overloadargs__Fiiiiiiiiiii" "overloadargs(int, int, int, int, int, int, int, int, int, int, int)"
+ gdb_test "maint dem pick__13ivCompositionP8ivCanvasRC12ivAllocationiR5ivHit" \
+ "ivComposition::pick\[(\]+ivCanvas \[*\]+, (const ivAllocation|ivAllocation const) &, int, ivHit &\[)\]+"
+ gdb_test "maint dem pointer__C11ivHScrollerRC7ivEventRC12ivAllocation" \
+ "ivHScroller::pointer\[(\]+(const ivEvent|ivEvent const) &, (const ivAllocation|ivAllocation const) &\[)\]+ const"
+ gdb_test_exact "maint demangle poke__8ivRasterUlUlffff" "ivRaster::poke(unsigned long, unsigned long, float, float, float, float)"
+ gdb_test_exact "maint demangle polar__Fdd" "polar(double, double)"
+ gdb_test "maint dem read__10osStdInputRPCc" \
+ "osStdInput::read\[(\]+(const char|char const) \[*\]+&\[)\]+"
+
+ gdb_test_exact "maint demangle scale__13ivTransformerff" "ivTransformer::scale(float, float)"
+ gdb_test "maint dem scanw__12CursesWindowPCce" \
+ "CursesWindow::scanw\[(\]+(const char|char const) \[*\]+,...\[)\]+"
+ gdb_test "maint dem scmp__FPCcT0" \
+ "scmp\[(\]+(const char|char const) \[*\]+, (const char|char const) \[*\]+\[)\]+"
+ gdb_test_exact "maint demangle sgetn__7filebufPci" "filebuf::sgetn(char *, int)"
+ gdb_test_exact "maint demangle shift__FP5_FrepiT0" "shift(_Frep *, int, _Frep *)"
+ gdb_test_exact "maint demangle test__C6BitSeti" "BitSet::test(int) const"
+ gdb_test_exact "maint demangle test__C6BitSetii" "BitSet::test(int, int) const"
+ gdb_test "maint dem testbit__FRC7Integerl" \
+ "testbit\[(\]+(const Integer|Integer const) &, long\[)\]+"
+ gdb_test_exact "maint demangle text_source__8Documentl" "Document::text_source(long)"
+ gdb_test_exact "maint demangle variance__6Erlangd" "Erlang::variance(double)"
+ gdb_test "maint dem vform__8iostreamPCcPc" \
+ "iostream::vform\[(\]+(const char|char const) \[*\]+, char \[*\]+\[)\]+"
+ gdb_test_exact "maint demangle view__14DocumentViewerP8ItemViewP11TabularItem" "DocumentViewer::view(ItemView *, TabularItem *)"
+ gdb_test_exact "maint demangle xy_extents__11ivExtensionffff" "ivExtension::xy_extents(float, float, float, float)"
+ gdb_test_exact "maint demangle zero__8osMemoryPvUi" "osMemory::zero(void *, unsigned int)"
+ gdb_test_exact "maint demangle _2T4\$N" "T4::N"
+ gdb_test_exact "maint demangle _Q22T42t1\$N" "T4::t1::N"
+ gdb_test_exact "maint demangle get__2T1" "T1::get(void)"
+ gdb_test_exact "maint demangle get__Q22T11a" "T1::a::get(void)"
+ gdb_test_exact "maint demangle get__Q32T11a1b" "T1::a::b::get(void)"
+ gdb_test_exact "maint demangle get__Q42T11a1b1c" "T1::a::b::c::get(void)"
+ gdb_test_exact "maint demangle get__Q52T11a1b1c1d" "T1::a::b::c::d::get(void)"
+ gdb_test_exact "maint demangle put__2T1i" "T1::put(int)"
+ gdb_test_exact "maint demangle put__Q22T11ai" "T1::a::put(int)"
+ gdb_test_exact "maint demangle put__Q32T11a1bi" "T1::a::b::put(int)"
+ gdb_test_exact "maint demangle put__Q42T11a1b1ci" "T1::a::b::c::put(int)"
+ gdb_test_exact "maint demangle put__Q52T11a1b1c1di" "T1::a::b::c::d::put(int)"
+
+ gdb_test_exact "maint demangle bar__3fooPv" "foo::bar(void *)"
+ gdb_test "maint dem bar__3fooPCv" \
+ "foo::bar\[(\]+(const void|void const) *\[*\]+\[)\]+"
+ gdb_test_exact "maint demangle bar__C3fooPv" "foo::bar(void *) const"
+ gdb_test "maint dem bar__C3fooPCv" \
+ "foo::bar\[(\]+(const void|void const) *\[*\]+\[)\]+ const"
+ gdb_test_exact "maint demangle __eq__3fooRT0" "foo::operator==(foo &)"
+ gdb_test "maint dem __eq__3fooRC3foo" \
+ "foo::operator==\[(\]+(const foo|foo const) &\[)\]+"
+ gdb_test_exact "maint demangle __eq__C3fooR3foo" "foo::operator==(foo &) const"
+ gdb_test "maint dem __eq__C3fooRT0" \
+ "foo::operator==\[(\]+(const foo|foo const) &\[)\]+ const"
+
+ gdb_test_exact "maint demangle elem__t6vector1Zdi" "vector<double>::elem(int)"
+ gdb_test_exact "maint demangle elem__t6vector1Zii" "vector<int>::elem(int)"
+ gdb_test_exact "maint demangle __t6vector1Zdi" "vector<double>::vector(int)"
+ gdb_test_exact "maint demangle __t6vector1Zii" "vector<int>::vector(int)"
+ gdb_test_exact "maint demangle _\$_t6vector1Zdi" "vector<double>::~vector(int)"
+ gdb_test_exact "maint demangle _\$_t6vector1Zii" "vector<int>::~vector(int)"
+
+ gdb_test_exact "maint demangle __nw__t2T11ZcUi" "T1<char>::operator new(unsigned int)"
+ gdb_test_exact "maint demangle __nw__t2T11Z1tUi" "T1<t>::operator new(unsigned int)"
+ gdb_test_exact "maint demangle __dl__t2T11ZcPv" "T1<char>::operator delete(void *)"
+ gdb_test_exact "maint demangle __dl__t2T11Z1tPv" "T1<t>::operator delete(void *)"
+ gdb_test_exact "maint demangle __t2T11Zci" "T1<char>::T1(int)"
+ gdb_test_exact "maint demangle __t2T11Zc" "T1<char>::T1(void)"
+ gdb_test_exact "maint demangle __t2T11Z1ti" "T1<t>::T1(int)"
+ gdb_test_exact "maint demangle __t2T11Z1t" "T1<t>::T1(void)"
+
+ gdb_test_exact "maint demangle __Q2t4List1Z10VHDLEntity3Pix" \
+ "List<VHDLEntity>::Pix::Pix(void)"
+
+ gdb_test_exact "maint demangle __Q2t4List1Z10VHDLEntity3PixPQ2t4List1Z10VHDLEntity7element" \
+ "List<VHDLEntity>::Pix::Pix(List<VHDLEntity>::element *)"
+
+ gdb_test_exact "maint demangle __Q2t4List1Z10VHDLEntity3PixRCQ2t4List1Z10VHDLEntity3Pix" \
+ "List<VHDLEntity>::Pix::Pix(List<VHDLEntity>::Pix const &)"
+
+ gdb_test_exact "maint demangle __Q2t4List1Z10VHDLEntity7elementRC10VHDLEntityPT0" \
+ "List<VHDLEntity>::element::element(VHDLEntity const &, List<VHDLEntity>::element *)"
+
+ gdb_test_exact "maint demangle __Q2t4List1Z10VHDLEntity7elementRCQ2t4List1Z10VHDLEntity7element" \
+ "List<VHDLEntity>::element::element(List<VHDLEntity>::element const &)"
+
+ gdb_test_exact "maint demangle __cl__C11VHDLLibraryGt4PixX3Z11VHDLLibraryZ14VHDLLibraryRepZt4List1Z10VHDLEntity" \
+ "VHDLLibrary::operator()(PixX<VHDLLibrary, VHDLLibraryRep, List<VHDLEntity> >) const"
+
+ gdb_test_exact "maint demangle __cl__Ct4List1Z10VHDLEntityRCQ2t4List1Z10VHDLEntity3Pix" \
+ "List<VHDLEntity>::operator()(List<VHDLEntity>::Pix const &) const"
+
+ gdb_test_exact "maint demangle __ne__FPvRCQ2t4List1Z10VHDLEntity3Pix" \
+ "operator!=(void *, List<VHDLEntity>::Pix const &)"
+
+ gdb_test_exact "maint demangle __ne__FPvRCt4PixX3Z11VHDLLibraryZ14VHDLLibraryRepZt4List1Z10VHDLEntity" \
+ "operator!=(void *, PixX<VHDLLibrary, VHDLLibraryRep, List<VHDLEntity> > const &)"
+
+ gdb_test_exact "maint demangle __t4List1Z10VHDLEntityRCt4List1Z10VHDLEntity" \
+ "List<VHDLEntity>::List(List<VHDLEntity> const &)"
+
+ gdb_test_exact "maint demangle __t4PixX3Z11VHDLLibraryZ14VHDLLibraryRepZt4List1Z10VHDLEntity" \
+ "PixX<VHDLLibrary, VHDLLibraryRep, List<VHDLEntity> >::PixX(void)"
+
+ gdb_test_exact "maint demangle __t4PixX3Z11VHDLLibraryZ14VHDLLibraryRepZt4List1Z10VHDLEntityP14VHDLLibraryRepGQ2t4List1Z10VHDLEntity3Pix" \
+ "PixX<VHDLLibrary, VHDLLibraryRep, List<VHDLEntity> >::PixX(VHDLLibraryRep *, List<VHDLEntity>::Pix)"
+
+ gdb_test_exact "maint demangle __t4PixX3Z11VHDLLibraryZ14VHDLLibraryRepZt4List1Z10VHDLEntityRCt4PixX3Z11VHDLLibraryZ14VHDLLibraryRepZt4List1Z10VHDLEntity" \
+ "PixX<VHDLLibrary, VHDLLibraryRep, List<VHDLEntity> >::PixX(PixX<VHDLLibrary, VHDLLibraryRep, List<VHDLEntity> > const &)"
+
+ gdb_test_exact "maint demangle nextE__C11VHDLLibraryRt4PixX3Z11VHDLLibraryZ14VHDLLibraryRepZt4List1Z10VHDLEntity" \
+ "VHDLLibrary::nextE(PixX<VHDLLibrary, VHDLLibraryRep, List<VHDLEntity> > &) const"
+
+ gdb_test_exact "maint demangle next__Ct4List1Z10VHDLEntityRQ2t4List1Z10VHDLEntity3Pix" \
+ "List<VHDLEntity>::next(List<VHDLEntity>::Pix &) const"
+
+ gdb_test_exact "maint demangle _GLOBAL_\$D\$set" "global destructors keyed to set"
+
+ gdb_test_exact "maint demangle _GLOBAL_\$I\$set" "global constructors keyed to set"
+
+ gdb_test_exact "maint demangle __as__t5ListS1ZUiRCt5ListS1ZUi" \
+ "ListS<unsigned int>::operator=(ListS<unsigned int> const &)"
+
+ gdb_test_exact "maint demangle __cl__Ct5ListS1ZUiRCQ2t5ListS1ZUi3Vix" \
+ "ListS<unsigned int>::operator()(ListS<unsigned int>::Vix const &) const"
+
+ gdb_test_exact "maint demangle __cl__Ct5SetLS1ZUiRCQ2t5SetLS1ZUi3Vix" \
+ "SetLS<unsigned int>::operator()(SetLS<unsigned int>::Vix const &) const"
+
+ gdb_test_exact "maint demangle __t10ListS_link1ZUiRCUiPT0" \
+ "ListS_link<unsigned int>::ListS_link(unsigned int const &, ListS_link<unsigned int> *)"
+
+ gdb_test_exact "maint demangle __t10ListS_link1ZUiRCt10ListS_link1ZUi" \
+ "ListS_link<unsigned int>::ListS_link(ListS_link<unsigned int> const &)"
+
+ gdb_test_exact "maint demangle __t5ListS1ZUiRCt5ListS1ZUi" \
+ "ListS<unsigned int>::ListS(ListS<unsigned int> const &)"
+
+ gdb_test_exact "maint demangle next__Ct5ListS1ZUiRQ2t5ListS1ZUi3Vix" \
+ "ListS<unsigned int>::next(ListS<unsigned int>::Vix &) const"
+
+ gdb_test_exact "maint demangle __ne__FPvRCQ2t5SetLS1ZUi3Vix" \
+ "operator!=(void *, SetLS<unsigned int>::Vix const &)"
+ gdb_test_exact "maint demangle __t8ListElem1Z5LabelRt4List1Z5Label" \
+ "ListElem<Label>::ListElem(List<Label> &)"
+ gdb_test_exact "maint demangle __t8BDDHookV1ZPcRCPc" \
+ "BDDHookV<char *>::BDDHookV(char *const &)"
+
+ gdb_test_exact "maint demangle _vt\$t8BDDHookV1ZPc" "BDDHookV<char *> virtual table"
+
+ gdb_test_exact "maint demangle __ne__FPvRCQ211BDDFunction4VixB" \
+ "operator!=(void *, BDDFunction::VixB const &)"
+ gdb_test_exact "maint demangle __eq__FPvRCQ211BDDFunction4VixB" \
+ "operator==(void *, BDDFunction::VixB const &)"
+
+ gdb_test_exact "maint demangle relativeId__CQ36T_phi210T_preserve8FPC_nextRCQ26T_phi210T_preserveRC10Parameters" \
+ "T_phi2::T_preserve::FPC_next::relativeId(T_phi2::T_preserve const &, Parameters const &) const"
+
+}
+
+#
+# Test lucid style name demangling
+#
+
+proc test_lucid_style_demangling {} {
+ global gdb_prompt
+
+ # Set the demangling style to "lucid" and then check to make sure
+ # it really got set. Return if the style failed to get set for
+ # some reason.
+
+ send_gdb "set demangle-style lucid\n"
+ gdb_expect {
+ -re "set demangle-style lucid\[\r\n\]+$gdb_prompt $" {}
+ -re ".*$gdb_prompt $" { fail "set demangle-style lucid failed" ; return }
+ timeout { fail "set demangle-style lucid failed (timeout)" ; return }
+ }
+
+ send_gdb "show demangle-style\n"
+ gdb_expect {
+ -re "The current C\[+\]+ demangling style is \"lucid\".\r\n$gdb_prompt $" {}
+ -re ".*$gdb_prompt $" { fail "demangling style not set to lucid" }
+ timeout { fail "show demangle-style timed out" }
+ }
+
+ gdb_test_exact "maint demangle WS__FR7istream" "WS(istream &)"
+ gdb_test_exact "maint demangle __aa__3fooFR3foo" "foo::operator&&(foo &)"
+ gdb_test_exact "maint demangle __aad__3fooFR3foo" "foo::operator&=(foo &)"
+ gdb_test_exact "maint demangle __ad__3fooFR3foo" "foo::operator&(foo &)"
+ gdb_test_exact "maint demangle __adv__3fooFR3foo" "foo::operator/=(foo &)"
+ gdb_test_exact "maint demangle __adv__7complexF7complex" "complex::operator/=(complex)"
+ gdb_test_exact "maint demangle __aer__3fooFR3foo" "foo::operator^=(foo &)"
+ gdb_test_exact "maint demangle __als__3fooFR3foo" "foo::operator<<=(foo &)"
+ gdb_test_exact "maint demangle __amd__3fooFR3foo" "foo::operator%=(foo &)"
+ gdb_test_exact "maint demangle __ami__3fooFR3foo" "foo::operator-=(foo &)"
+ gdb_test_exact "maint demangle __amu__3fooFR3foo" "foo::operator*=(foo &)"
+ gdb_test_exact "maint demangle __amu__7complexF7complex" "complex::operator*=(complex)"
+ gdb_test_exact "maint demangle __aor__3fooFR3foo" "foo::operator|=(foo &)"
+ gdb_test_exact "maint demangle __apl__3fooFR3foo" "foo::operator+=(foo &)"
+ gdb_test_exact "maint demangle __ars__3fooFR3foo" "foo::operator>>=(foo &)"
+ gdb_test_exact "maint demangle __as__18istream_withassignFP9streambuf" "istream_withassign::operator=(streambuf *)"
+ gdb_test_exact "maint demangle __as__18istream_withassignFR7istream" "istream_withassign::operator=(istream &)"
+ gdb_test_exact "maint demangle __as__3fooFR3foo" "foo::operator=(foo &)"
+ gdb_test_exact "maint demangle __as__3iosFR3ios" "ios::operator=(ios &)"
+ gdb_test_exact "maint demangle __cl__3fooFR3foo" "foo::operator()(foo &)"
+ gdb_test_exact "maint demangle __cm__3fooFR3foo" "foo::operator, (foo &)"
+
+ gdb_test_exact "maint demangle __co__3fooFv" "foo::operator~(void)"
+ gdb_test_exact "maint demangle __ct__10istrstreamFPc" "istrstream::istrstream(char *)"
+ gdb_test_exact "maint demangle __ct__10istrstreamFPci" "istrstream::istrstream(char *, int)"
+ gdb_test_exact "maint demangle __ct__10ostrstreamFPciT2" "ostrstream::ostrstream(char *, int, int)"
+ gdb_test_exact "maint demangle __ct__10ostrstreamFv" "ostrstream::ostrstream(void)"
+ gdb_test_exact "maint demangle __ct__10smanip_intFPFR3iosi_R3iosi" "smanip_int::smanip_int(ios &(*)(ios &, int), int)"
+ gdb_test "maint dem __ct__11c_exceptionFPcRC7complexT2" "c_exception::c_exception\[(\]+char \[*\]+, (const complex|complex const) &, (const complex|complex const) &\[)\]+"
+ gdb_test "maint dem __ct__11fstreambaseFPCciT2" "fstreambase::fstreambase\[(\]+(const char|char const) \[*\]+, int, int\[)\]+"
+ gdb_test_exact "maint demangle __ct__11fstreambaseFi" "fstreambase::fstreambase(int)"
+ gdb_test_exact "maint demangle __ct__11fstreambaseFiPcT1" "fstreambase::fstreambase(int, char *, int)"
+ gdb_test_exact "maint demangle __ct__11fstreambaseFv" "fstreambase::fstreambase(void)"
+ gdb_test_exact "maint demangle __ct__11smanip_longFPFR3iosl_R3iosl" "smanip_long::smanip_long(ios &(*)(ios &, long), long)"
+ gdb_test_exact "maint demangle __ct__11stdiostreamFP4FILE" "stdiostream::stdiostream(FILE *)"
+ gdb_test_exact "maint demangle __ct__12strstreambufFPFl_PvPFPv_v" "strstreambuf::strstreambuf(void *(*)(long), void (*)(void *))"
+ gdb_test_exact "maint demangle __ct__12strstreambufFPUciT1" "strstreambuf::strstreambuf(unsigned char *, int, unsigned char *)"
+ gdb_test_exact "maint demangle __ct__12strstreambufFPciT1" "strstreambuf::strstreambuf(char *, int, char *)"
+ gdb_test_exact "maint demangle __ct__12strstreambufFi" "strstreambuf::strstreambuf(int)"
+ gdb_test_exact "maint demangle __ct__12strstreambufFv" "strstreambuf::strstreambuf(void)"
+ gdb_test_exact "maint demangle __ct__13strstreambaseFPciT1" "strstreambase::strstreambase(char *, int, char *)"
+ gdb_test_exact "maint demangle __ct__3fooFR3foo" "foo::foo(foo &)"
+
+ gdb_test_exact "maint demangle __ct__3fooFi" "foo::foo(int)"
+ gdb_test_exact "maint demangle __ct__3fooFiN31" "foo::foo(int, int, int, int)"
+ gdb_test "maint dem __ct__3fooFiPCc" \
+ "foo::foo\[(\]+int, (const char|char const) \[*\]+\[)\]+"
+ gdb_test_exact "maint demangle __ct__3fooFiR3fooT1T2T1T2" "foo::foo(int, foo &, int, foo &, int, foo &)"
+ gdb_test_exact "maint demangle __ct__3iosFP9streambuf" "ios::ios(streambuf *)"
+ gdb_test_exact "maint demangle __ct__7filebufFiPcT1" "filebuf::filebuf(int, char *, int)"
+ gdb_test "maint dem __ct__7fstreamFPCciT2" \
+ "fstream::fstream\[(\]+(const char|char const) \[*\]+, int, int\[)\]+"
+ gdb_test_exact "maint demangle __ct__7fstreamFiPcT1" "fstream::fstream(int, char *, int)"
+ gdb_test_exact "maint demangle __ct__7istreamFP9streambuf" "istream::istream(streambuf *)"
+ gdb_test_exact "maint demangle __ct__7istreamFP9streambufiP7ostream" "istream::istream(streambuf *, int, ostream *)"
+ gdb_test_exact "maint demangle __ct__7istreamFiPcT1" "istream::istream(int, char *, int)"
+ gdb_test_exact "maint demangle __ct__7istreamFiT1P7ostream" "istream::istream(int, int, ostream *)"
+ gdb_test_exact "maint demangle __ct__7ostreamFP9streambuf" "ostream::ostream(streambuf *)"
+ gdb_test_exact "maint demangle __ct__7ostreamFiPc" "ostream::ostream(int, char *)"
+ gdb_test "maint dem __ct__8ifstreamFPCciT2" \
+ "ifstream::ifstream\[(\]+(const char|char const) \[*\]+, int, int\[)\]+"
+ gdb_test_exact "maint demangle __ct__8ifstreamFiPcT1" "ifstream::ifstream(int, char *, int)"
+
+ gdb_test_exact "maint demangle __ct__Q23foo3barFv" "foo::bar::bar(void)"
+ gdb_test_exact "maint demangle __ct__Q33foo3bar4bellFv" "foo::bar::bell::bell(void)"
+ gdb_test_exact "maint demangle __dl__3fooSFPv" "foo::operator delete(void *) static"
+ gdb_test_exact "maint demangle __dl__FPv" "operator delete(void *)"
+ gdb_test_exact "maint demangle __dt__10istrstreamFv" "istrstream::~istrstream(void)"
+
+ gdb_test_exact "maint demangle __dt__Q23foo3barFv" "foo::bar::~bar(void)"
+ gdb_test_exact "maint demangle __dt__Q33foo3bar4bellFv" "foo::bar::bell::~bell(void)"
+ gdb_test_exact "maint demangle __dv__3fooFR3foo" "foo::operator/(foo &)"
+ gdb_test_exact "maint demangle __dv__F7complexT1" "operator/(complex, complex)"
+ gdb_test_exact "maint demangle __eq__3fooFR3foo" "foo::operator==(foo &)"
+ gdb_test_exact "maint demangle __er__3fooFR3foo" "foo::operator^(foo &)"
+ gdb_test_exact "maint demangle __ge__3fooFR3foo" "foo::operator>=(foo &)"
+ gdb_test_exact "maint demangle __gt__3fooFR3foo" "foo::operator>(foo &)"
+ gdb_test_exact "maint demangle __le__3fooFR3foo" "foo::operator<=(foo &)"
+ gdb_test_exact "maint demangle __ls__3fooFR3foo" "foo::operator<<(foo &)"
+ gdb_test_exact "maint demangle __ls__7ostreamFP9streambuf" "ostream::operator<<(streambuf *)"
+
+ gdb_test "maint dem __ls__7ostreamFPCc" \
+ "ostream::operator<<\[(\]+(const char|char const) \[*\]+\[)\]+"
+ gdb_test_exact "maint demangle __ls__7ostreamFPFR3ios_R3ios" "ostream::operator<<(ios &(*)(ios &))"
+ gdb_test_exact "maint demangle __ls__7ostreamFPv" "ostream::operator<<(void *)"
+ gdb_test_exact "maint demangle __ls__7ostreamFUi" "ostream::operator<<(unsigned int)"
+ gdb_test_exact "maint demangle __ls__7ostreamFUl" "ostream::operator<<(unsigned long)"
+ gdb_test_exact "maint demangle __ls__7ostreamFd" "ostream::operator<<(double)"
+ gdb_test_exact "maint demangle __ls__7ostreamFf" "ostream::operator<<(float)"
+ gdb_test_exact "maint demangle __ls__7ostreamFi" "ostream::operator<<(int)"
+ gdb_test_exact "maint demangle __ls__7ostreamFl" "ostream::operator<<(long)"
+ gdb_test_exact "maint demangle __ls__FR7ostream7complex" "operator<<(ostream &, complex)"
+ gdb_test_exact "maint demangle __lt__3fooFR3foo" "foo::operator<(foo &)"
+ gdb_test_exact "maint demangle __md__3fooFR3foo" "foo::operator%(foo &)"
+ gdb_test_exact "maint demangle __mi__3fooFR3foo" "foo::operator-(foo &)"
+ gdb_test_exact "maint demangle __ml__3fooFR3foo" "foo::operator*(foo &)"
+ gdb_test_exact "maint demangle __ml__F7complexT1" "operator*(complex, complex)"
+ gdb_test_exact "maint demangle __mm__3fooFi" "foo::operator--(int)"
+ gdb_test_exact "maint demangle __ne__3fooFR3foo" "foo::operator!=(foo &)"
+ gdb_test_exact "maint demangle __nt__3fooFv" "foo::operator!(void)"
+ gdb_test_exact "maint demangle __nw__3fooSFi" "foo::operator new(int) static"
+ gdb_test_exact "maint demangle __nw__FUi" "operator new(unsigned int)"
+ gdb_test_exact "maint demangle __nw__FUiPv" "operator new(unsigned int, void *)"
+ gdb_test_exact "maint demangle __oo__3fooFR3foo" "foo::operator||(foo &)"
+ gdb_test_exact "maint demangle __opPc__3fooFv" "foo::operator char *(void)"
+ gdb_test_exact "maint demangle __opi__3fooFv" "foo::operator int(void)"
+ gdb_test_exact "maint demangle __or__3fooFR3foo" "foo::operator|(foo &)"
+
+ gdb_test_exact "maint demangle __pl__3fooFR3foo" "foo::operator+(foo &)"
+ gdb_test_exact "maint demangle __pp__3fooFi" "foo::operator++(int)"
+ gdb_test_exact "maint demangle __pt__3fooFv" "foo::operator->(void)"
+ gdb_test_exact "maint demangle __rm__3fooFR3foo" "foo::operator->*(foo &)"
+ gdb_test_exact "maint demangle __rs__3fooFR3foo" "foo::operator>>(foo &)"
+ gdb_test_exact "maint demangle __rs__7istreamFP9streambuf" "istream::operator>>(streambuf *)"
+ gdb_test_exact "maint demangle __rs__7istreamFPFR3ios_R3ios" "istream::operator>>(ios &(*)(ios &))"
+ gdb_test_exact "maint demangle __rs__7istreamFPFR7istream_R7istream" "istream::operator>>(istream &(*)(istream &))"
+ gdb_test_exact "maint demangle __rs__7istreamFPUc" "istream::operator>>(unsigned char *)"
+ gdb_test_exact "maint demangle __rs__7istreamFPc" "istream::operator>>(char *)"
+ gdb_test_exact "maint demangle __rs__7istreamFRUi" "istream::operator>>(unsigned int &)"
+ gdb_test_exact "maint demangle __rs__7istreamFRUl" "istream::operator>>(unsigned long &)"
+ gdb_test_exact "maint demangle __rs__7istreamFRUs" "istream::operator>>(unsigned short &)"
+ gdb_test_exact "maint demangle __rs__7istreamFRd" "istream::operator>>(double &)"
+ gdb_test_exact "maint demangle __rs__7istreamFRf" "istream::operator>>(float &)"
+ gdb_test_exact "maint demangle __rs__7istreamFRi" "istream::operator>>(int &)"
+ gdb_test_exact "maint demangle __rs__7istreamFRl" "istream::operator>>(long &)"
+ gdb_test_exact "maint demangle __rs__7istreamFRs" "istream::operator>>(short &)"
+ gdb_test_exact "maint demangle __rs__FR7istreamR7complex" "operator>>(istream &, complex &)"
+ gdb_test "maint dem __vc__3fooFR3foo" "foo::operator\\\[\\\]\\(foo &\\)"
+ gdb_test_exact "maint demangle __vtbl__10istrstream" "istrstream virtual table"
+ gdb_test_exact "maint demangle __vtbl__17ostream__iostream__19iostream_withassign" "iostream_withassign::ostream__iostream virtual table"
+
+ gdb_test_exact "maint demangle __vtbl__3ios" "ios virtual table"
+ gdb_test_exact "maint demangle __vtbl__3ios__13strstreambase" "strstreambase::ios virtual table"
+
+ # GDB 930414 demangles this as t_cc_main_ (obviously wrong).
+ # GDB 930701 gets into an infinite loop.
+ # GDB 930727 says "Can't demangle".
+ # What is the correct demangling? FIXME.
+ setup_xfail "*-*-*"
+ gdb_test_exact "maint demangle __vtbl__3foo__vt_cc_main_" ""
+
+ gdb_test_exact "maint demangle abs__F7complex" "abs(complex)"
+ gdb_test_exact "maint demangle allocate__9streambufFv" "streambuf::allocate(void)"
+ gdb_test_exact "maint demangle attach__11fstreambaseFi" "fstreambase::attach(int)"
+ gdb_test_exact "maint demangle bitalloc__3iosSFv" "ios::bitalloc(void) static"
+ gdb_test_exact "maint demangle chr__FiT1" "chr(int, int)"
+ gdb_test_exact "maint demangle complex_error__FR11c_exception" "complex_error(c_exception &)"
+ gdb_test_exact "maint demangle complexfunc2__FPFPc_i" "complexfunc2(int (*)(char *))"
+ gdb_test_exact "maint demangle complexfunc3__FPFPFPl_s_i" "complexfunc3(int (*)(short (*)(long *)))"
+
+ gdb_test_exact "maint demangle complexfunc4__FPFPFPc_s_i" "complexfunc4(int (*)(short (*)(char *)))"
+ gdb_test_exact "maint demangle complexfunc5__FPFPc_PFl_i" "complexfunc5(int (*(*)(char *))(long))"
+ gdb_test_exact "maint demangle complexfunc6__FPFPi_PFl_i" "complexfunc6(int (*(*)(int *))(long))"
+ gdb_test_exact "maint demangle complexfunc7__FPFPFPc_i_PFl_i" "complexfunc7(int (*(*)(int (*)(char *)))(long))"
+ gdb_test_exact "maint demangle complicated_put__7ostreamFc" "ostream::complicated_put(char)"
+ gdb_test_exact "maint demangle conv10__FlPc" "conv10(long, char *)"
+ gdb_test_exact "maint demangle conv16__FUlPc" "conv16(unsigned long, char *)"
+ gdb_test_exact "maint demangle dec__FR3ios" "dec(ios &)"
+ gdb_test_exact "maint demangle dec__Fli" "dec(long, int)"
+ gdb_test_exact "maint demangle dofield__FP7ostreamPciT2T3" "dofield(ostream *, char *, int, char *, int)"
+
+ gdb_test_exact "maint demangle flags__3iosFl" "ios::flags(long)"
+ gdb_test_exact "maint demangle flags__3iosFv" "ios::flags(void)"
+ gdb_test_exact "maint demangle foo__FiN31" "foo(int, int, int, int)"
+ gdb_test_exact "maint demangle foo__FiR3fooT1T2T1T2" "foo(int, foo &, int, foo &, int, foo &)"
+ gdb_test_exact "maint demangle foo___3barFl" "bar::foo_(long)"
+ gdb_test "maint dem form__FPCce" "form\[(\]+(const char|char const) \[*\]+,...\[)\]+"
+ gdb_test_exact "maint demangle get__7istreamFPcic" "istream::get(char *, int, char)"
+ gdb_test_exact "maint demangle get__7istreamFR9streambufc" "istream::get(streambuf &, char)"
+ gdb_test_exact "maint demangle get_complicated__7istreamFRUc" "istream::get_complicated(unsigned char &)"
+ gdb_test_exact "maint demangle get_complicated__7istreamFRc" "istream::get_complicated(char &)"
+ gdb_test_exact "maint demangle getline__7istreamFPUcic" "istream::getline(unsigned char *, int, char)"
+ gdb_test_exact "maint demangle getline__7istreamFPcic" "istream::getline(char *, int, char)"
+
+ gdb_test_exact "maint demangle ignore__7istreamFiT1" "istream::ignore(int, int)"
+ gdb_test_exact "maint demangle init__12strstreambufFPciT1" "strstreambuf::init(char *, int, char *)"
+ gdb_test_exact "maint demangle init__3iosFP9streambuf" "ios::init(streambuf *)"
+ gdb_test_exact "maint demangle initcount__13Iostream_init" "Iostream_init::initcount"
+ gdb_test_exact "maint demangle ipfx__7istreamFi" "istream::ipfx(int)"
+ gdb_test_exact "maint demangle ls_complicated__7ostreamFUc" "ostream::ls_complicated(unsigned char)"
+ gdb_test_exact "maint demangle ls_complicated__7ostreamFc" "ostream::ls_complicated(char)"
+ gdb_test "maint dem open__11fstreambaseFPCciT2" \
+ "fstreambase::open\[(\]+(const char|char const) \[*\]+, int, int\[)\]+"
+ gdb_test "maint dem open__7filebufFPCciT2" \
+ "filebuf::open\[(\]+(const char|char const) \[*\]+, int, int\[)\]+"
+
+ gdb_test_exact "maint demangle overload1arg__FSc" "overload1arg(signed char)"
+ gdb_test_exact "maint demangle overload1arg__FUc" "overload1arg(unsigned char)"
+ gdb_test_exact "maint demangle overload1arg__FUi" "overload1arg(unsigned int)"
+ gdb_test_exact "maint demangle overload1arg__FUl" "overload1arg(unsigned long)"
+ gdb_test_exact "maint demangle overload1arg__FUs" "overload1arg(unsigned short)"
+ gdb_test_exact "maint demangle overload1arg__Fc" "overload1arg(char)"
+ gdb_test_exact "maint demangle overload1arg__Fd" "overload1arg(double)"
+ gdb_test_exact "maint demangle overload1arg__Ff" "overload1arg(float)"
+ gdb_test_exact "maint demangle overload1arg__Fi" "overload1arg(int)"
+ gdb_test_exact "maint demangle overload1arg__Fl" "overload1arg(long)"
+ gdb_test_exact "maint demangle overload1arg__Fs" "overload1arg(short)"
+ gdb_test_exact "maint demangle overload1arg__Fv" "overload1arg(void)"
+ gdb_test_exact "maint demangle overloadargs__FiN21" "overloadargs(int, int, int)"
+ gdb_test_exact "maint demangle overloadargs__FiN31" "overloadargs(int, int, int, int)"
+ gdb_test_exact "maint demangle overloadargs__FiN41" "overloadargs(int, int, int, int, int)"
+ gdb_test_exact "maint demangle overloadargs__FiN51" "overloadargs(int, int, int, int, int, int)"
+ gdb_test_exact "maint demangle overloadargs__FiN61" "overloadargs(int, int, int, int, int, int, int)"
+
+ gdb_test_exact "maint demangle overloadargs__FiN71" "overloadargs(int, int, int, int, int, int, int, int)"
+ gdb_test_exact "maint demangle overloadargs__FiN81" "overloadargs(int, int, int, int, int, int, int, int, int)"
+ gdb_test_exact "maint demangle overloadargs__FiN91" "overloadargs(int, int, int, int, int, int, int, int, int, int)"
+ gdb_test_exact "maint demangle overloadargs__FiN91N11" "overloadargs(int, int, int, int, int, int, int, int, int, int, int)"
+ gdb_test_exact "maint demangle overloadargs__FiT1" "overloadargs(int, int)"
+ gdb_test_exact "maint demangle polar__FdT1" "polar(double, double)"
+ gdb_test_exact "maint demangle pow__F7complexT1" "pow(complex, complex)"
+ gdb_test_exact "maint demangle pow__F7complexd" "pow(complex, double)"
+ gdb_test_exact "maint demangle pow__F7complexi" "pow(complex, int)"
+ gdb_test_exact "maint demangle pow__Fd7complex" "pow(double, complex)"
+ gdb_test_exact "maint demangle pstart__FPciT2" "pstart(char *, int, int)"
+ gdb_test_exact "maint demangle put__7ostreamFc" "ostream::put(char)"
+
+ gdb_test_exact "maint demangle read__7istreamFPci" "istream::read(char *, int)"
+ gdb_test_exact "maint demangle resetiosflags__FR3iosl" "resetiosflags(ios &, long)"
+ gdb_test_exact "maint demangle restore_errno__FRi" "restore_errno(int &)"
+ gdb_test_exact "maint demangle rs_complicated__7istreamFRUc" "istream::rs_complicated(unsigned char &)"
+ gdb_test_exact "maint demangle rs_complicated__7istreamFRc" "istream::rs_complicated(char &)"
+ gdb_test_exact "maint demangle seekg__7istreamFl8seek_dir" "istream::seekg(long, seek_dir)"
+ gdb_test_exact "maint demangle seekoff__12strstreambufFl8seek_diri" "strstreambuf::seekoff(long, seek_dir, int)"
+ gdb_test_exact "maint demangle seekoff__9streambufFlQ2_3ios12ios_seek_diri" "streambuf::seekoff(long, ios::ios_seek_dir, int)"
+ gdb_test_exact "maint demangle seekpos__9streambufFli" "streambuf::seekpos(long, int)"
+ gdb_test_exact "maint demangle set_new_handler__FPFv_v" "set_new_handler(void (*)(void))"
+ gdb_test_exact "maint demangle setb__9streambufFPcT1i" "streambuf::setb(char *, char *, int)"
+
+ gdb_test_exact "maint demangle setb__FR3iosi" "setb(ios &, int)"
+ gdb_test_exact "maint demangle setbuf__11fstreambaseFPci" "fstreambase::setbuf(char *, int)"
+ gdb_test_exact "maint demangle setbuf__9streambufFPUci" "streambuf::setbuf(unsigned char *, int)"
+ gdb_test_exact "maint demangle setbuf__9streambufFPciT2" "streambuf::setbuf(char *, int, int)"
+ gdb_test_exact "maint demangle setf__3iosFlT1" "ios::setf(long, long)"
+ gdb_test_exact "maint demangle setfill__FR3iosi" "setfill(ios &, int)"
+ gdb_test_exact "maint demangle setg__9streambufFPcN21" "streambuf::setg(char *, char *, char *)"
+ gdb_test_exact "maint demangle setp__9streambufFPcT1" "streambuf::setp(char *, char *)"
+
+ gdb_test "maint dem sputn__9streambufFPCci" \
+ "streambuf::sputn\[(\]+(const char|char const) \[*\]+, int\[)\]+"
+ gdb_test "maint dem str__FPCci" \
+ "str\[(\]+(const char|char const) \[*\]+, int\[)\]+"
+ gdb_test_exact "maint demangle tie__3iosFP7ostream" "ios::tie(ostream *)"
+ gdb_test_exact "maint demangle uconv10__FUlPc" "uconv10(unsigned long, char *)"
+
+ gdb_test "maint dem write__7ostreamFPCci" \
+ "ostream::write\[(\]+(const char|char const) \[*\]+, int\[)\]+"
+ gdb_test_exact "maint demangle xget__7istreamFPc" "istream::xget(char *)"
+ gdb_test_exact "maint demangle xsgetn__9streambufFPci" "streambuf::xsgetn(char *, int)"
+ gdb_test "maint dem xsputn__9streambufFPCci" \
+ "streambuf::xsputn\[(\]+(const char|char const) \[*\]+, int\[)\]+"
+}
+
+#
+# Test arm style name demangling
+#
+
+proc test_arm_style_demangling {} {
+ global gdb_prompt
+
+ # Set the demangling style to "arm" and then check to make sure
+ # it really got set. Return if the style failed to get set for
+ # some reason.
+
+ send_gdb "set demangle-style arm\n"
+ gdb_expect {
+ -re "set demangle-style arm\[\r\n\]+$gdb_prompt $" {}
+ -re ".*$gdb_prompt $" { fail "set demangle-style arm failed" ; return }
+ timeout { fail "set demangle-style arm failed (timeout)" ; return }
+ }
+
+ send_gdb "show demangle-style\n"
+ gdb_expect {
+ -re "The current C\[+\]+ demangling style is \"arm\".\r\n$gdb_prompt $" {}
+ -re ".*$gdb_prompt $" { fail "demangling style not set to arm" }
+ timeout { fail "show demangle-style timed out" }
+ }
+
+ gdb_test_exact "maint demangle __dt__21T5__pt__11_PFiPPdPv_iFv" "T5<int (*)(int, double **, void *)>::~T5(void)"
+
+ gdb_test_exact "maint demangle __ct__1cFi" "c::c(int)"
+
+ gdb_test_exact "maint demangle __dt__11T5__pt__2_iFv" "T5<int>::~T5(void)"
+
+ gdb_test_exact "maint demangle __dt__11T5__pt__2_cFv" "T5<char>::~T5(void)"
+
+ gdb_test_exact "maint demangle __ct__2T2Fi" "T2::T2(int)"
+ gdb_test_exact "maint demangle __dt__2T1Fv" "T1::~T1(void)"
+
+ gdb_test_exact "maint demangle __dt__12T5__pt__3_1xFv" "T5<x>::~T5(void)"
+
+ gdb_test_exact "maint demangle __dt__17T5__pt__8_PFcPv_iFv" "T5<int (*)(char, void *)>::~T5(void)"
+
+ gdb_test "maint dem g__FP1cPC1cT1" \
+ "g\[(\]+c *\[*\]+, (const c|c const) *\[*\]+, c *\[*\]+\[)\]+"
+ gdb_test "maint dem g__FPUlPCUlT1" \
+ "g\[(\]+unsigned long \[*\]+, (const unsigned long|unsigned long const) \[*\]+, unsigned long \[*\]+\[)\]+"
+ gdb_test "maint dem g__FPUiPCUiT1" \
+ "g\[(\]+unsigned int \[*\]+, (const unsigned int|unsigned int const) \[*\]+, unsigned int \[*\]+\[)\]+"
+ gdb_test "maint dem g__FPUsPCUsT1" \
+ "g\[(\]+unsigned short \[*\]+, (const unsigned short|unsigned short const) \[*\]+, unsigned short \[*\]+\[)\]+"
+ gdb_test "maint dem g__FPUcPCUcT1" \
+ "g\[(\]+unsigned char \[*\]+, (const unsigned char|unsigned char const) \[*\]+, unsigned char \[*\]+\[)\]+"
+ gdb_test "maint dem g__F1TPlPClT2" \
+ "g\[(\]+T, long \[*\]+, (const long|long const) \[*\]+, long \[*\]+\[)\]+"
+ gdb_test "maint dem g__F1RRlRClT2" \
+ "g\[(\]+R, long &, (const long|long const) &, long &\[)\]+"
+ gdb_test "maint dem g__F1TPiPCiT2" \
+ "g\[(\]+T, int \[*\]+, (const int|int const) \[*\]+, int \[*\]+\[)\]+"
+ gdb_test "maint dem g__F1RRiRCiT2" \
+ "g\[(\]+R, int &, (const int|int const) &, int &\[)\]+"
+ gdb_test "maint dem g__F1TPsPCsT2" \
+ "g\[(\]+T, short \[*\]+, (const short|short const) \[*\]+, short \[*\]+\[)\]+"
+ gdb_test "maint dem g__F1RRsRCsT2" \
+ "g\[(\]+R, short &, (const short|short const) &, short &\[)\]+"
+ gdb_test "maint dem g__F1TPcPCcT2" \
+ "g\[(\]+T, char \[*\]+, (const char|char const) \[*\]+, char \[*\]+\[)\]+"
+ gdb_test "maint dem g__F1RRcRCcT2" \
+ "g\[(\]+R, char &, (const char|char const) &, char &\[)\]+"
+
+ gdb_test_exact "maint demangle __ct__21T5__pt__11_PFiPPdPv_iFi" "T5<int (*)(int, double **, void *)>::T5(int)"
+
+ gdb_test "maint dem __gt__FRC2T2c" \
+ "operator>\[(\]+(const T2|T2 const) &, char\[)\]+"
+ gdb_test "maint dem __ge__FRC2T2c" \
+ "operator>=\[(\]+(const T2|T2 const) &, char\[)\]+"
+ gdb_test "maint dem __lt__FRC2T2c" \
+ "operator<\[(\]+(const T2|T2 const) &, char\[)\]+"
+
+ gdb_test "maint dem __le__FRC2T2c" \
+ "operator<=\[(\]+(const T2|T2 const) &, char\[)\]+"
+ gdb_test "maint dem __ne__FRC2T2c" \
+ "operator!=\[(\]+(const T2|T2 const) &, char\[)\]+"
+ gdb_test "maint dem __eq__FRC2T2c" \
+ "operator==\[(\]+(const T2|T2 const) &, char\[)\]+"
+ gdb_test_exact "maint demangle __amd__FR2T2i" "operator%=(T2 &, int)"
+ gdb_test_exact "maint demangle __adv__FR2T2i" "operator/=(T2 &, int)"
+ gdb_test_exact "maint demangle __amu__FR2T2i" "operator*=(T2 &, int)"
+ gdb_test_exact "maint demangle __ami__FR2T2i" "operator-=(T2 &, int)"
+ gdb_test_exact "maint demangle __apl__FR2T2i" "operator+=(T2 &, int)"
+ gdb_test_exact "maint demangle __nw__2T1SFUi" "T1::operator new(unsigned int) static"
+ gdb_test_exact "maint demangle __dl__2T1SFPv" "T1::operator delete(void *) static"
+ gdb_test_exact "maint demangle put__2T7SFi" "T7::put(int) static"
+
+ gdb_test_exact "maint demangle __dl__12T5__pt__3_1xSFPv" "T5<x>::operator delete(void *) static"
+
+ gdb_test_exact "maint demangle h__FUc" "h(unsigned char)"
+ gdb_test_exact "maint demangle f__Fic" "f(int, char)"
+ gdb_test_exact "maint demangle h__FUi" "h(unsigned int)"
+ gdb_test_exact "maint demangle h__Fci" "h(char, int)"
+ gdb_test_exact "maint demangle h__FUl" "h(unsigned long)"
+ gdb_test_exact "maint demangle h__Fcl" "h(char, long)"
+ gdb_test_exact "maint demangle h__FUs" "h(unsigned short)"
+ gdb_test_exact "maint demangle h__Fcs" "h(char, short)"
+ gdb_test "maint dem __amd__FR2T2RC2T2" \
+ "operator%=\[(\]+T2 &, (const T2|T2 const) &\[)\]+"
+ gdb_test "maint dem __adv__FR2T2RC2T2" \
+ "operator/=\[(\]+T2 &, (const T2|T2 const) &\[)\]+"
+ gdb_test "maint dem __amu__FR2T2RC2T2" \
+ "operator\[*\]+=\[(\]+T2 &, (const T2|T2 const) &\[)\]+"
+ gdb_test "maint dem __ami__FR2T2RC2T2" \
+ "operator-=\[(\]+T2 &, (const T2|T2 const) &\[)\]+"
+ gdb_test "maint dem __apl__FR2T2RC2T2" \
+ "operator\[+\]+=\[(\]+T2 &, (const T2|T2 const) &\[)\]+"
+
+ gdb_test "maint dem g__F1SRPUlRPCUlT2" \
+ "g\[(\]+S, unsigned long \[*\]+&, (const unsigned long|unsigned long const) \[*\]+&, unsigned long \[*\]+&\[)\]+"
+ gdb_test "maint dem g__F1SRPUiRPCUiT2" \
+ "g\[(\]+S, unsigned int \[*\]+&, (const unsigned int|unsigned int const) \[*\]+&, unsigned int \[*\]+&\[)\]+"
+ gdb_test "maint dem g__F1SRPUsRPCUsT2" \
+ "g\[(\]+S, unsigned short \[*\]+&, (const unsigned short|unsigned short const) \[*\]+&, unsigned short \[*\]+&\[)\]+"
+ gdb_test "maint dem g__F1SRPUcRPCUcT2" \
+ "g\[(\]+S, unsigned char \[*\]+&, (const unsigned char|unsigned char const) \[*\]+&, unsigned char \[*\]+&\[)\]+"
+ gdb_test "maint dem g__F1T1SRPlRPClT3" \
+ "g\[(\]+T, S, long \[*\]+&, (const long|long const) \[*\]+&, long \[*\]+&\[)\]+"
+ gdb_test "maint dem g__F1T1SRPiRPCiT3" \
+ "g\[(\]+T, S, int \[*\]+&, (const int|int const) \[*\]+&, int \[*\]+&\[)\]+"
+ gdb_test "maint dem g__F1T1SRPcRPCcT3" \
+ "g\[(\]+T, S, char \[*\]+&, (const char|char const) \[*\]+&, char \[*\]+&\[)\]+"
+
+ gdb_test_exact "maint demangle X__12T5__pt__3_1x" "T5<x>::X"
+
+ gdb_test_exact "maint demangle __ct__11T5__pt__2_iFi" "T5<int>::T5(int)"
+
+ gdb_test_exact "maint demangle __ct__11T5__pt__2_cFi" "T5<char>::T5(int)"
+
+ gdb_test "maint dem __gt__FRC2T2T1" \
+ "operator>\[(\]+(const T2|T2 const) &, (const T2|T2 const) &\[)\]+"
+ gdb_test "maint dem __ge__FRC2T2T1" \
+ "operator>=\[(\]+(const T2|T2 const) &, (const T2|T2 const) &\[)\]+"
+ gdb_test "maint dem __lt__FRC2T2T1" \
+ "operator<\[(\]+(const T2|T2 const) &, (const T2|T2 const) &\[)\]+"
+ gdb_test "maint dem __le__FRC2T2T1" \
+ "operator<=\[(\]+(const T2|T2 const) &, (const T2|T2 const) &\[)\]+"
+ gdb_test "maint dem __ne__FRC2T2T1" \
+ "operator!=\[(\]+(const T2|T2 const) &, (const T2|T2 const) &\[)\]+"
+ gdb_test "maint dem __eq__FRC2T2T1" \
+ "operator==\[(\]+(const T2|T2 const) &, (const T2|T2 const) &\[)\]+"
+ gdb_test "maint dem g__FcR1cRC1cT2" \
+ "g\[(\]+char, c &, (const c|c const) &, c &\[)\]+"
+ gdb_test "maint dem g__FcRPdRPCdT2" \
+ "g\[(\]+char, double *\[*\]+&, (const double|double const) *\[*\]+&, double *\[*\]+&\[)\]+"
+ gdb_test "maint dem g__FcRPfRPCfT2" \
+ "g\[(\]+char, float *\[*\]+&, (const float|float const) *\[*\]+&, float *\[*\]+&\[)\]+"
+ gdb_test_exact "maint demangle h__FcT1" "h(char, char)"
+ gdb_test_exact "maint demangle f__Ficd" "f(int, char, double)"
+ gdb_test "maint dem g__F1T1SdRPsRPCsT4" \
+ "g\[(\]+T, S, double, short \[*\]+&, (const short|short const) \[*\]+&, short \[*\]+&\[)\]+"
+ gdb_test "maint dem g__F1cC1cT1" \
+ "g\[(\]+c, (const c|c const), c\[)\]+"
+ gdb_test "maint dem g__FPdPCdT1" \
+ "g\[(\]+double *\[*\]+, (const double|double const) *\[*\]+, double *\[*\]+\[)\]+"
+ gdb_test "maint dem g__FPfPCfT1" \
+ "g\[(\]+float *\[*\]+, (const float|float const) *\[*\]+, float *\[*\]+\[)\]+"
+
+ gdb_test "maint dem g__FUlCUlT1" \
+ "g\[(\]+unsigned long, (const unsigned long|unsigned long const), unsigned long\[)\]+"
+ gdb_test "maint dem g__FPlPClT1" \
+ "g\[(\]+long \[*\]+, (const long|long const) \[*\]+, long \[*\]+\[)\]+"
+ gdb_test "maint dem g__FUiCUiT1" \
+ "g\[(\]+unsigned int, (const unsigned int|unsigned int const), unsigned int\[)\]+"
+ gdb_test "maint dem g__FPiPCiT1" \
+ "g\[(\]+int \[*\]+, (const int|int const) \[*\]+, int \[*\]+\[)\]+"
+ gdb_test "maint dem g__FUsCUsT1" \
+ "g\[(\]+unsigned short, (const unsigned short|unsigned short const), unsigned short\[)\]+"
+ gdb_test "maint dem g__FPsPCsT1" \
+ "g\[(\]+short \[*\]+, (const short|short const) \[*\]+, short \[*\]+\[)\]+"
+ gdb_test "maint dem g__FUcCUcT1" \
+ "g\[(\]+unsigned char, (const unsigned char|unsigned char const), unsigned char\[)\]+"
+ gdb_test "maint dem g__FPcPCcT1" \
+ "g\[(\]+char \[*\]+, (const char|char const) \[*\]+, char \[*\]+\[)\]+"
+ gdb_test "maint dem g__F1TlClT2" \
+ "g\[(\]+T, long, (const long|long const), long\[)\]+"
+ gdb_test "maint dem g__F1TiCiT2" \
+ "g\[(\]+T, int, (const int|int const), int\[)\]+"
+ gdb_test "maint dem g__F1TsCsT2" \
+ "g\[(\]+T, short, (const short|short const), short\[)\]+"
+ gdb_test "maint dem g__F1TcCcT2" \
+ "g\[(\]+T, char, (const char|char const), char\[)\]+"
+
+ gdb_test_exact "maint demangle __dl__17T5__pt__8_PFcPv_iSFPv" "T5<int (*)(char, void *)>::operator delete(void *) static"
+
+ gdb_test "maint dem printf__FPCce" \
+ "printf\[(\]+(const char|char const) \[*\]+,...\[)\]+"
+
+ gdb_test_exact "maint demangle X__17T5__pt__8_PFcPv_i" "T5<int (*)(char, void *)>::X"
+
+ gdb_test_exact "maint demangle __ct__12T5__pt__3_1xFi" "T5<x>::T5(int)"
+
+ gdb_test "maint dem g__F1SRUlRCUlT2" \
+ "g\[(\]+S, unsigned long &, (const unsigned long|unsigned long const) &, unsigned long &\[)\]+"
+ gdb_test "maint dem g__F1SRPlRPClT2" \
+ "g\[(\]+S, long \[*\]+&, (const long|long const) \[*\]+&, long \[*\]+&\[)\]+"
+ gdb_test "maint dem g__F1RRUiRCUiT2" \
+ "g\[(\]+R, unsigned int &, (const unsigned int|unsigned int const) &, unsigned int &\[)\]+"
+ gdb_test "maint dem g__F1SRPiRPCiT2" \
+ "g\[(\]+S, int \[*\]+&, (const int|int const) \[*\]+&, int \[*\]+&\[)\]+"
+ gdb_test "maint dem g__F1RRUsRCUsT2" \
+ "g\[(\]+R, unsigned short &, (const unsigned short|unsigned short const) &, unsigned short &\[)\]+"
+ gdb_test "maint dem g__F1SRPsRPCsT2" \
+ "g\[(\]+S, short \[*\]+&, (const short|short const) \[*\]+&, short \[*\]+&\[)\]+"
+ gdb_test "maint dem g__F1RRUcRCUcT2" \
+ "g\[(\]+R, unsigned char &, (const unsigned char|unsigned char const) &, unsigned char &\[)\]+"
+ gdb_test "maint dem g__F1SRPcRPCcT2" \
+ "g\[(\]+S, char \[*\]+&, (const char|char const) \[*\]+&, char \[*\]+&\[)\]+"
+ gdb_test "maint dem g__F1T1RRlRClT3" \
+ "g\[(\]+T, R, long &, (const long|long const) &, long &\[)\]+"
+ gdb_test "maint dem g__F1T1RRiRCiT3" \
+ "g\[(\]+T, R, int &, (const int|int const) &, int &\[)\]+"
+ gdb_test "maint dem g__F1T1RRsRCsT3" \
+ "g\[(\]+T, R, short &, (const short|short const) &, short &\[)\]+"
+ gdb_test "maint dem g__F1T1RRcRCcT3" \
+ "g\[(\]+T, R, char &, (const char|char const) &, char &\[)\]+"
+
+ gdb_test_exact "maint demangle __dl__21T5__pt__11_PFiPPdPv_iSFPv" "T5<int (*)(int, double **, void *)>::operator delete(void *) static"
+
+ gdb_test_exact "maint demangle __std__foo" "global destructors keyed to foo"
+
+ gdb_test_exact "maint demangle __sti__bar" "global constructors keyed to bar"
+
+ gdb_test_exact "maint demangle f__FicdPcPFci_v" "f(int, char, double, char *, void (*)(char, int))"
+ gdb_test_exact "maint demangle f__FicdPcPFic_v" "f(int, char, double, char *, void (*)(int, char))"
+ gdb_test_exact "maint demangle get__2T7SFv" "T7::get(void) static"
+
+ gdb_test_exact "maint demangle X__21T5__pt__11_PFiPPdPv_i" "T5<int (*)(int, double **, void *)>::X"
+
+ gdb_test "maint dem g__FcRdRCdT2" \
+ "g\[(\]+char, double &, (const double|double const) &, double &\[)\]+"
+ gdb_test "maint dem g__FcRfRCfT2" \
+ "g\[(\]+char, float &, (const float|float const) &, float &\[)\]+"
+ gdb_test "maint dem __md__FC2T2i" \
+ "operator%\[(\]+(const T2|T2 const), int\[)\]+"
+ gdb_test "maint dem __dv__FC2T2i" \
+ "operator/\[(\]+(const T2|T2 const), int\[)\]+"
+ gdb_test "maint dem __ml__FC2T2i" \
+ "operator\[*\]+\[(\]+(const T2|T2 const), int\[)\]+"
+ gdb_test "maint dem __mi__FC2T2i" \
+ "operator-\[(\]+(const T2|T2 const), int\[)\]+"
+ gdb_test "maint dem __pl__FC2T2i" \
+ "operator\[+\]+\[(\]+(const T2|T2 const), int\[)\]+"
+
+ gdb_test_exact "maint demangle __dl__11T5__pt__2_iSFPv" "T5<int>::operator delete(void *) static"
+
+ gdb_test_exact "maint demangle __dl__11T5__pt__2_cSFPv" "T5<char>::operator delete(void *) static"
+
+ gdb_test_exact "maint demangle h__Fc" "h(char)"
+ gdb_test_exact "maint demangle h__Fd" "h(double)"
+ gdb_test_exact "maint demangle h__Ff" "h(float)"
+ gdb_test_exact "maint demangle h__Fi" "h(int)"
+ gdb_test_exact "maint demangle f__Fi" "f(int)"
+ gdb_test_exact "maint demangle h__Fl" "h(long)"
+
+ gdb_test_exact "maint demangle h__Fs" "h(short)"
+ gdb_test "maint dem __md__FC2T2RC2T2" \
+ "operator%\[(\]+(const T2|T2 const), (const T2|T2 const) &\[)\]+"
+ gdb_test "maint dem __dv__FC2T2RC2T2" \
+ "operator/\[(\]+(const T2|T2 const), (const T2|T2 const) &\[)\]+"
+ gdb_test "maint dem __ml__FC2T2RC2T2" \
+ "operator\[*\]+\[(\]+(const T2|T2 const), (const T2|T2 const) &\[)\]+"
+ gdb_test "maint dem __mi__FC2T2RC2T2" \
+ "operator-\[(\]+(const T2|T2 const), (const T2|T2 const) &\[)\]+"
+ gdb_test "maint dem __pl__FC2T2RC2T2" \
+ "operator\[+\]+\[(\]+(const T2|T2 const), (const T2|T2 const) &\[)\]+"
+ gdb_test "maint dem g__FcRP1cRPC1cT2" \
+ "g\[(\]+char, c *\[*\]+&, (const c|c const) *\[*\]+&, c *\[*\]+&\[)\]+"
+
+ gdb_test_exact "maint demangle X__11T5__pt__2_c" "T5<char>::X"
+
+ gdb_test_exact "maint demangle X__11T5__pt__2_i" "T5<int>::X"
+
+ gdb_test "maint dem g__FdCdT1" \
+ "g\[(\]+double, (const double|double const), double\[)\]+"
+ gdb_test "maint dem g__FfCfT1" \
+ "g\[(\]+float, (const float|float const), float\[)\]+"
+ gdb_test "maint dem g__FlClT1" \
+ "g\[(\]+long, (const long|long const), long\[)\]+"
+ gdb_test "maint dem g__FiCiT1" \
+ "g\[(\]+int, (const int|int const), int\[)\]+"
+ gdb_test "maint dem g__FsCsT1" \
+ "g\[(\]+short, (const short|short const), short\[)\]+"
+ gdb_test "maint dem g__FcCcT1" \
+ "g\[(\]+char, (const char|char const), char\[)\]+"
+
+ gdb_test_exact "maint demangle __ct__17T5__pt__8_PFcPv_iFi" "T5<int (*)(char, void *)>::T5(int)"
+
+ gdb_test_exact "maint demangle f__FicdPc" "f(int, char, double, char *)"
+ gdb_test_exact "maint demangle __nw__FUi" "operator new(unsigned int)"
+ gdb_test_exact "maint demangle __ct__Q3_2T11a1bSFi" "T1::a::b::b(int) static"
+ gdb_test_exact "maint demangle __dt__Q3_2T11a1bSFi" "T1::a::b::~b(int) static"
+ gdb_test_exact "maint demangle put__Q3_2T11a1bSFi" "T1::a::b::put(int) static"
+ gdb_test_exact "maint demangle get__Q2_2T11aSFv" "T1::a::get(void) static"
+ gdb_test_exact "maint demangle put__2T1SFi" "T1::put(int) static"
+ gdb_test_exact "maint demangle put__Q5_2T11a1b1c1dSFi" "T1::a::b::c::d::put(int) static"
+ gdb_test_exact "maint demangle get__Q4_2T11a1b1cSFv" "T1::a::b::c::get(void) static"
+ gdb_test_exact "maint demangle put__Q2_2T11aSFi" "T1::a::put(int) static"
+ gdb_test_exact "maint demangle put__Q4_2T11a1b1cSFi" "T1::a::b::c::put(int) static"
+ gdb_test_exact "maint demangle get__Q3_2T11a1bSFv" "T1::a::b::get(void) static"
+ gdb_test_exact "maint demangle get__2T1SFv" "T1::get(void) static"
+ gdb_test_exact "maint demangle get__Q5_2T11a1b1c1dSFv" "T1::a::b::c::d::get(void) static"
+
+ gdb_test_exact "maint demangle __dt__11T1__pt__2_cFv" "T1<char>::~T1(void)"
+
+ gdb_test_exact "maint demangle __dt__12T1__pt__3_1tFv" "T1<t>::~T1(void)"
+
+ gdb_test_exact "maint demangle __dl__12T1__pt__3_1tSFPv" "T1<t>::operator delete(void *) static"
+
+ gdb_test_exact "maint demangle __ct__11T1__pt__2_cFi" "T1<char>::T1(int)"
+
+ gdb_test_exact "maint demangle __ct__11T1__pt__2_cFv" "T1<char>::T1(void)"
+
+ gdb_test_exact "maint demangle __ct__12T1__pt__3_1tFi" "T1<t>::T1(int)"
+
+ gdb_test_exact "maint demangle __ct__12T1__pt__3_1tFv" "T1<t>::T1(void)"
+
+ gdb_test_exact "maint demangle __dl__11T1__pt__2_cSFPv" "T1<char>::operator delete(void *) static"
+
+ gdb_test_exact "maint demangle bar__3fooFPv" "foo::bar(void *)"
+ gdb_test "maint dem bar__3fooFPCv" \
+ "foo::bar\[(\]+(const void|void const) *\[*\]+\[)\]+"
+ gdb_test_exact "maint demangle bar__3fooCFPv" "foo::bar(void *) const"
+ gdb_test "maint dem bar__3fooCFPCv" \
+ "foo::bar\[(\]+(const void|void const) *\[*\]+\[)\]+ const"
+ gdb_test_exact "maint demangle __eq__3fooFR3foo" "foo::operator==(foo &)"
+ gdb_test "maint dem __eq__3fooFRC3foo" \
+ "foo::operator==\[(\]+(const foo|foo const) &\[)\]+"
+ gdb_test_exact "maint demangle __eq__3fooCFR3foo" "foo::operator==(foo &) const"
+ gdb_test "maint dem __eq__3fooCFRC3foo" \
+ "foo::operator==\[(\]+(const foo|foo const) &\[)\]+ const"
+
+ gdb_test_exact "maint demangle elem__15vector__pt__2_dFi" "vector<double>::elem(int)"
+
+ gdb_test_exact "maint demangle elem__15vector__pt__2_iFi" "vector<int>::elem(int)"
+
+ gdb_test_exact "maint demangle __ct__15vector__pt__2_dFi" "vector<double>::vector(int)"
+
+ gdb_test_exact "maint demangle __ct__15vector__pt__2_iFi" "vector<int>::vector(int)"
+
+ gdb_test_exact "maint demangle __ct__25DListNode__pt__9_R6RLabelFR6RLabelP25DListNode__pt__9_R6RLabelT2" \
+ "DListNode<RLabel &>::DListNode(RLabel &, DListNode<RLabel &> *, DListNode<RLabel &> *)"
+
+ gdb_test_exact "maint demangle bar__3fooFiT16FooBar" "foo::bar(int, int, FooBar)"
+
+ gdb_test_exact "maint demangle bar__3fooFPiN51PdN37PcN211T1iN215" \
+ "foo::bar(int *, int *, int *, int *, int *, int *, double *, double *, double *, double *, char *, char *, char *, int *, int, int, int)"
+
+}
+
+proc test_hp_style_demangling {} {
+ global gdb_prompt
+
+ # Set the demangling style to "hp" and then check to make sure
+ # it really got set. Return if the style failed to get set for
+ # some reason.
+
+ send_gdb "set demangle-style hp\n"
+ gdb_expect {
+ -re "set demangle-style hp\[\r\n\]+$gdb_prompt $" {}
+ -re ".*$gdb_prompt $" { fail "set demangle-style hp failed" ; return }
+ timeout { fail "set demangle-style hp failed (timeout)" ; return }
+ }
+
+ send_gdb "show demangle-style\n"
+ gdb_expect {
+ -re "The current C\[+\]+ demangling style is \"hp\".\r\n$gdb_prompt $" {}
+ -re ".*$gdb_prompt $" { fail "demangling style not set to hp" }
+ timeout { fail "show demangle-style timed out (HP)" }
+ }
+
+ # HP aCC mangling style is based on ARM for all the basic stuff,
+ # so first we use some of the ARM tests here. Later we have HP-specific
+ # tests.
+
+ gdb_test "maint dem g__FP1cPC1cT1" \
+ "g\[(\]+c *\[*\]+, (const c|c const) *\[*\]+, c *\[*\]+\[)\]+"
+ gdb_test "maint dem g__FPUlPCUlT1" \
+ "g\[(\]+unsigned long \[*\]+, (const unsigned long|unsigned long const) \[*\]+, unsigned long \[*\]+\[)\]+"
+ gdb_test "maint dem g__FPUiPCUiT1" \
+ "g\[(\]+unsigned int \[*\]+, (const unsigned int|unsigned int const) \[*\]+, unsigned int \[*\]+\[)\]+"
+ gdb_test "maint dem g__FPUsPCUsT1" \
+ "g\[(\]+unsigned short \[*\]+, (const unsigned short|unsigned short const) \[*\]+, unsigned short \[*\]+\[)\]+"
+ gdb_test "maint dem g__FPUcPCUcT1" \
+ "g\[(\]+unsigned char \[*\]+, (const unsigned char|unsigned char const) \[*\]+, unsigned char \[*\]+\[)\]+"
+ gdb_test "maint dem g__F1TPlPClT2" \
+ "g\[(\]+T, long \[*\]+, (const long|long const) \[*\]+, long \[*\]+\[)\]+"
+ gdb_test "maint dem g__F1RRlRClT2" \
+ "g\[(\]+R, long &, (const long|long const) &, long &\[)\]+"
+ gdb_test "maint dem g__F1TPiPCiT2" \
+ "g\[(\]+T, int \[*\]+, (const int|int const) \[*\]+, int \[*\]+\[)\]+"
+ gdb_test "maint dem g__F1RRiRCiT2" \
+ "g\[(\]+R, int &, (const int|int const) &, int &\[)\]+"
+ gdb_test "maint dem g__F1TPsPCsT2" \
+ "g\[(\]+T, short \[*\]+, (const short|short const) \[*\]+, short \[*\]+\[)\]+"
+ gdb_test "maint dem g__F1RRsRCsT2" \
+ "g\[(\]+R, short &, (const short|short const) &, short &\[)\]+"
+ gdb_test "maint dem g__F1TPcPCcT2" \
+ "g\[(\]+T, char \[*\]+, (const char|char const) \[*\]+, char \[*\]+\[)\]+"
+ gdb_test "maint dem g__F1RRcRCcT2" \
+ "g\[(\]+R, char &, (const char|char const) &, char &\[)\]+"
+
+ gdb_test "maint dem __gt__FRC2T2c" \
+ "operator>\[(\]+(const T2|T2 const) &, char\[)\]+"
+ gdb_test "maint dem __ge__FRC2T2c" \
+ "operator>=\[(\]+(const T2|T2 const) &, char\[)\]+"
+ gdb_test "maint dem __lt__FRC2T2c" \
+ "operator<\[(\]+(const T2|T2 const) &, char\[)\]+"
+
+ gdb_test "maint dem __le__FRC2T2c" \
+ "operator<=\[(\]+(const T2|T2 const) &, char\[)\]+"
+ gdb_test "maint dem __ne__FRC2T2c" \
+ "operator!=\[(\]+(const T2|T2 const) &, char\[)\]+"
+ gdb_test "maint dem __eq__FRC2T2c" \
+ "operator==\[(\]+(const T2|T2 const) &, char\[)\]+"
+ gdb_test_exact "maint demangle __amd__FR2T2i" "operator%=(T2 &, int)"
+ gdb_test_exact "maint demangle __adv__FR2T2i" "operator/=(T2 &, int)"
+ gdb_test_exact "maint demangle __amu__FR2T2i" "operator*=(T2 &, int)"
+ gdb_test_exact "maint demangle __ami__FR2T2i" "operator-=(T2 &, int)"
+ gdb_test_exact "maint demangle __apl__FR2T2i" "operator+=(T2 &, int)"
+ gdb_test_exact "maint demangle __nw__2T1SFUi" "T1::operator new(unsigned int) static"
+ gdb_test_exact "maint demangle __dl__2T1SFPv" "T1::operator delete(void *) static"
+ gdb_test_exact "maint demangle put__2T7SFi" "T7::put(int) static"
+
+ gdb_test_exact "maint demangle h__FUc" "h(unsigned char)"
+ gdb_test_exact "maint demangle f__Fic" "f(int, char)"
+ gdb_test_exact "maint demangle h__FUi" "h(unsigned int)"
+ gdb_test_exact "maint demangle h__Fci" "h(char, int)"
+ gdb_test_exact "maint demangle h__FUl" "h(unsigned long)"
+ gdb_test_exact "maint demangle h__Fcl" "h(char, long)"
+ gdb_test_exact "maint demangle h__FUs" "h(unsigned short)"
+ gdb_test_exact "maint demangle h__Fcs" "h(char, short)"
+ gdb_test "maint dem __amd__FR2T2RC2T2" \
+ "operator%=\[(\]+T2 &, (const T2|T2 const) &\[)\]+"
+ gdb_test "maint dem __adv__FR2T2RC2T2" \
+ "operator/=\[(\]+T2 &, (const T2|T2 const) &\[)\]+"
+ gdb_test "maint dem __amu__FR2T2RC2T2" \
+ "operator\[*\]+=\[(\]+T2 &, (const T2|T2 const) &\[)\]+"
+ gdb_test "maint dem __ami__FR2T2RC2T2" \
+ "operator-=\[(\]+T2 &, (const T2|T2 const) &\[)\]+"
+ gdb_test "maint dem __apl__FR2T2RC2T2" \
+ "operator\[+\]+=\[(\]+T2 &, (const T2|T2 const) &\[)\]+"
+
+ gdb_test "maint dem g__F1SRPUlRPCUlT2" \
+ "g\[(\]+S, unsigned long \[*\]+&, (const unsigned long|unsigned long const) \[*\]+&, unsigned long \[*\]+&\[)\]+"
+ gdb_test "maint dem g__F1SRPUiRPCUiT2" \
+ "g\[(\]+S, unsigned int \[*\]+&, (const unsigned int|unsigned int const) \[*\]+&, unsigned int \[*\]+&\[)\]+"
+ gdb_test "maint dem g__F1SRPUsRPCUsT2" \
+ "g\[(\]+S, unsigned short \[*\]+&, (const unsigned short|unsigned short const) \[*\]+&, unsigned short \[*\]+&\[)\]+"
+ gdb_test "maint dem g__F1SRPUcRPCUcT2" \
+ "g\[(\]+S, unsigned char \[*\]+&, (const unsigned char|unsigned char const) \[*\]+&, unsigned char \[*\]+&\[)\]+"
+ gdb_test "maint dem g__F1T1SRPlRPClT3" \
+ "g\[(\]+T, S, long \[*\]+&, (const long|long const) \[*\]+&, long \[*\]+&\[)\]+"
+ gdb_test "maint dem g__F1T1SRPiRPCiT3" \
+ "g\[(\]+T, S, int \[*\]+&, (const int|int const) \[*\]+&, int \[*\]+&\[)\]+"
+ gdb_test "maint dem g__F1T1SRPcRPCcT3" \
+ "g\[(\]+T, S, char \[*\]+&, (const char|char const) \[*\]+&, char \[*\]+&\[)\]+"
+
+
+ gdb_test "maint dem __gt__FRC2T2T1" \
+ "operator>\[(\]+(const T2|T2 const) &, (const T2|T2 const) &\[)\]+"
+ gdb_test "maint dem __ge__FRC2T2T1" \
+ "operator>=\[(\]+(const T2|T2 const) &, (const T2|T2 const) &\[)\]+"
+ gdb_test "maint dem __lt__FRC2T2T1" \
+ "operator<\[(\]+(const T2|T2 const) &, (const T2|T2 const) &\[)\]+"
+ gdb_test "maint dem __le__FRC2T2T1" \
+ "operator<=\[(\]+(const T2|T2 const) &, (const T2|T2 const) &\[)\]+"
+ gdb_test "maint dem __ne__FRC2T2T1" \
+ "operator!=\[(\]+(const T2|T2 const) &, (const T2|T2 const) &\[)\]+"
+ gdb_test "maint dem __eq__FRC2T2T1" \
+ "operator==\[(\]+(const T2|T2 const) &, (const T2|T2 const) &\[)\]+"
+ gdb_test "maint dem g__FcR1cRC1cT2" \
+ "g\[(\]+char, c &, (const c|c const) &, c &\[)\]+"
+ gdb_test "maint dem g__FcRPdRPCdT2" \
+ "g\[(\]+char, double *\[*\]+&, (const double|double const) *\[*\]+&, double *\[*\]+&\[)\]+"
+ gdb_test "maint dem g__FcRPfRPCfT2" \
+ "g\[(\]+char, float *\[*\]+&, (const float|float const) *\[*\]+&, float *\[*\]+&\[)\]+"
+ gdb_test_exact "maint demangle h__FcT1" "h(char, char)"
+ gdb_test_exact "maint demangle f__Ficd" "f(int, char, double)"
+ gdb_test "maint dem g__F1T1SdRPsRPCsT4" \
+ "g\[(\]+T, S, double, short \[*\]+&, (const short|short const) \[*\]+&, short \[*\]+&\[)\]+"
+ gdb_test "maint dem g__F1cC1cT1" \
+ "g\[(\]+c, (const c|c const), c\[)\]+"
+ gdb_test "maint dem g__FPdPCdT1" \
+ "g\[(\]+double *\[*\]+, (const double|double const) *\[*\]+, double *\[*\]+\[)\]+"
+ gdb_test "maint dem g__FPfPCfT1" \
+ "g\[(\]+float *\[*\]+, (const float|float const) *\[*\]+, float *\[*\]+\[)\]+"
+
+ gdb_test "maint dem g__FUlCUlT1" \
+ "g\[(\]+unsigned long, (const unsigned long|unsigned long const), unsigned long\[)\]+"
+ gdb_test "maint dem g__FPlPClT1" \
+ "g\[(\]+long \[*\]+, (const long|long const) \[*\]+, long \[*\]+\[)\]+"
+ gdb_test "maint dem g__FUiCUiT1" \
+ "g\[(\]+unsigned int, (const unsigned int|unsigned int const), unsigned int\[)\]+"
+ gdb_test "maint dem g__FPiPCiT1" \
+ "g\[(\]+int \[*\]+, (const int|int const) \[*\]+, int \[*\]+\[)\]+"
+ gdb_test "maint dem g__FUsCUsT1" \
+ "g\[(\]+unsigned short, (const unsigned short|unsigned short const), unsigned short\[)\]+"
+ gdb_test "maint dem g__FPsPCsT1" \
+ "g\[(\]+short \[*\]+, (const short|short const) \[*\]+, short \[*\]+\[)\]+"
+ gdb_test "maint dem g__FUcCUcT1" \
+ "g\[(\]+unsigned char, (const unsigned char|unsigned char const), unsigned char\[)\]+"
+ gdb_test "maint dem g__FPcPCcT1" \
+ "g\[(\]+char \[*\]+, (const char|char const) \[*\]+, char \[*\]+\[)\]+"
+ gdb_test "maint dem g__F1TlClT2" \
+ "g\[(\]+T, long, (const long|long const), long\[)\]+"
+ gdb_test "maint dem g__F1TiCiT2" \
+ "g\[(\]+T, int, (const int|int const), int\[)\]+"
+ gdb_test "maint dem g__F1TsCsT2" \
+ "g\[(\]+T, short, (const short|short const), short\[)\]+"
+ gdb_test "maint dem g__F1TcCcT2" \
+ "g\[(\]+T, char, (const char|char const), char\[)\]+"
+
+ gdb_test "maint dem printf__FPCce" \
+ "printf\[(\]+(const char|char const) \[*\]+,...\[)\]+"
+
+
+ gdb_test "maint dem g__F1SRUlRCUlT2" \
+ "g\[(\]+S, unsigned long &, (const unsigned long|unsigned long const) &, unsigned long &\[)\]+"
+ gdb_test "maint dem g__F1SRPlRPClT2" \
+ "g\[(\]+S, long \[*\]+&, (const long|long const) \[*\]+&, long \[*\]+&\[)\]+"
+ gdb_test "maint dem g__F1RRUiRCUiT2" \
+ "g\[(\]+R, unsigned int &, (const unsigned int|unsigned int const) &, unsigned int &\[)\]+"
+ gdb_test "maint dem g__F1SRPiRPCiT2" \
+ "g\[(\]+S, int \[*\]+&, (const int|int const) \[*\]+&, int \[*\]+&\[)\]+"
+ gdb_test "maint dem g__F1RRUsRCUsT2" \
+ "g\[(\]+R, unsigned short &, (const unsigned short|unsigned short const) &, unsigned short &\[)\]+"
+ gdb_test "maint dem g__F1SRPsRPCsT2" \
+ "g\[(\]+S, short \[*\]+&, (const short|short const) \[*\]+&, short \[*\]+&\[)\]+"
+ gdb_test "maint dem g__F1RRUcRCUcT2" \
+ "g\[(\]+R, unsigned char &, (const unsigned char|unsigned char const) &, unsigned char &\[)\]+"
+ gdb_test "maint dem g__F1SRPcRPCcT2" \
+ "g\[(\]+S, char \[*\]+&, (const char|char const) \[*\]+&, char \[*\]+&\[)\]+"
+ gdb_test "maint dem g__F1T1RRlRClT3" \
+ "g\[(\]+T, R, long &, (const long|long const) &, long &\[)\]+"
+ gdb_test "maint dem g__F1T1RRiRCiT3" \
+ "g\[(\]+T, R, int &, (const int|int const) &, int &\[)\]+"
+ gdb_test "maint dem g__F1T1RRsRCsT3" \
+ "g\[(\]+T, R, short &, (const short|short const) &, short &\[)\]+"
+ gdb_test "maint dem g__F1T1RRcRCcT3" \
+ "g\[(\]+T, R, char &, (const char|char const) &, char &\[)\]+"
+
+
+ gdb_test_exact "maint demangle f__FicdPcPFci_v" "f(int, char, double, char *, void (*)(char, int))"
+ gdb_test_exact "maint demangle f__FicdPcPFic_v" "f(int, char, double, char *, void (*)(int, char))"
+ gdb_test_exact "maint demangle get__2T7SFv" "T7::get(void) static"
+
+
+ gdb_test "maint dem g__FcRdRCdT2" \
+ "g\[(\]+char, double &, (const double|double const) &, double &\[)\]+"
+ gdb_test "maint dem g__FcRfRCfT2" \
+ "g\[(\]+char, float &, (const float|float const) &, float &\[)\]+"
+ gdb_test "maint dem __md__FC2T2i" \
+ "operator%\[(\]+(const T2|T2 const), int\[)\]+"
+ gdb_test "maint dem __dv__FC2T2i" \
+ "operator/\[(\]+(const T2|T2 const), int\[)\]+"
+ gdb_test "maint dem __ml__FC2T2i" \
+ "operator\[*\]+\[(\]+(const T2|T2 const), int\[)\]+"
+ gdb_test "maint dem __mi__FC2T2i" \
+ "operator-\[(\]+(const T2|T2 const), int\[)\]+"
+ gdb_test "maint dem __pl__FC2T2i" \
+ "operator\[+\]+\[(\]+(const T2|T2 const), int\[)\]+"
+
+
+ gdb_test_exact "maint demangle h__Fc" "h(char)"
+ gdb_test_exact "maint demangle h__Fd" "h(double)"
+ gdb_test_exact "maint demangle h__Ff" "h(float)"
+ gdb_test_exact "maint demangle h__Fi" "h(int)"
+ gdb_test_exact "maint demangle f__Fi" "f(int)"
+ gdb_test_exact "maint demangle h__Fl" "h(long)"
+
+ gdb_test_exact "maint demangle h__Fs" "h(short)"
+ gdb_test "maint dem __md__FC2T2RC2T2" \
+ "operator%\[(\]+(const T2|T2 const), (const T2|T2 const) &\[)\]+"
+ gdb_test "maint dem __dv__FC2T2RC2T2" \
+ "operator/\[(\]+(const T2|T2 const), (const T2|T2 const) &\[)\]+"
+ gdb_test "maint dem __ml__FC2T2RC2T2" \
+ "operator\[*\]+\[(\]+(const T2|T2 const), (const T2|T2 const) &\[)\]+"
+ gdb_test "maint dem __mi__FC2T2RC2T2" \
+ "operator-\[(\]+(const T2|T2 const), (const T2|T2 const) &\[)\]+"
+ gdb_test "maint dem __pl__FC2T2RC2T2" \
+ "operator\[+\]+\[(\]+(const T2|T2 const), (const T2|T2 const) &\[)\]+"
+ gdb_test "maint dem g__FcRP1cRPC1cT2" \
+ "g\[(\]+char, c *\[*\]+&, (const c|c const) *\[*\]+&, c *\[*\]+&\[)\]+"
+
+
+ gdb_test "maint dem g__FdCdT1" \
+ "g\[(\]+double, (const double|double const), double\[)\]+"
+ gdb_test "maint dem g__FfCfT1" \
+ "g\[(\]+float, (const float|float const), float\[)\]+"
+ gdb_test "maint dem g__FlClT1" \
+ "g\[(\]+long, (const long|long const), long\[)\]+"
+ gdb_test "maint dem g__FiCiT1" \
+ "g\[(\]+int, (const int|int const), int\[)\]+"
+ gdb_test "maint dem g__FsCsT1" \
+ "g\[(\]+short, (const short|short const), short\[)\]+"
+ gdb_test "maint dem g__FcCcT1" \
+ "g\[(\]+char, (const char|char const), char\[)\]+"
+
+
+ gdb_test_exact "maint demangle f__FicdPc" "f(int, char, double, char *)"
+ gdb_test_exact "maint demangle __nw__FUi" "operator new(unsigned int)"
+ gdb_test_exact "maint demangle __ct__Q3_2T11a1bSFi" "T1::a::b::b(int) static"
+ gdb_test_exact "maint demangle __dt__Q3_2T11a1bSFi" "T1::a::b::~b(int) static"
+ gdb_test_exact "maint demangle put__Q3_2T11a1bSFi" "T1::a::b::put(int) static"
+ gdb_test_exact "maint demangle get__Q2_2T11aSFv" "T1::a::get(void) static"
+ gdb_test_exact "maint demangle put__2T1SFi" "T1::put(int) static"
+ gdb_test_exact "maint demangle put__Q5_2T11a1b1c1dSFi" "T1::a::b::c::d::put(int) static"
+ gdb_test_exact "maint demangle get__Q4_2T11a1b1cSFv" "T1::a::b::c::get(void) static"
+ gdb_test_exact "maint demangle put__Q2_2T11aSFi" "T1::a::put(int) static"
+ gdb_test_exact "maint demangle put__Q4_2T11a1b1cSFi" "T1::a::b::c::put(int) static"
+ gdb_test_exact "maint demangle get__Q3_2T11a1bSFv" "T1::a::b::get(void) static"
+ gdb_test_exact "maint demangle get__2T1SFv" "T1::get(void) static"
+ gdb_test_exact "maint demangle get__Q5_2T11a1b1c1dSFv" "T1::a::b::c::d::get(void) static"
+
+
+ gdb_test_exact "maint demangle bar__3fooFPv" "foo::bar(void *)"
+ gdb_test "maint dem bar__3fooFPCv" \
+ "foo::bar\[(\]+(const void|void const) *\[*\]+\[)\]+"
+ gdb_test_exact "maint demangle bar__3fooCFPv" "foo::bar(void *) const"
+ gdb_test "maint dem bar__3fooCFPCv" \
+ "foo::bar\[(\]+(const void|void const) *\[*\]+\[)\]+ const"
+ gdb_test_exact "maint demangle __eq__3fooFR3foo" "foo::operator==(foo &)"
+ gdb_test "maint dem __eq__3fooFRC3foo" \
+ "foo::operator==\[(\]+(const foo|foo const) &\[)\]+"
+ gdb_test_exact "maint demangle __eq__3fooCFR3foo" "foo::operator==(foo &) const"
+ gdb_test "maint dem __eq__3fooCFRC3foo" \
+ "foo::operator==\[(\]+(const foo|foo const) &\[)\]+ const"
+
+ gdb_test_exact "maint demangle bar__3fooFiT16FooBar" "foo::bar(int, int, FooBar)"
+
+ gdb_test_exact "maint demangle bar__3fooFPiN51PdN37PcN211T1iN215" \
+ "foo::bar(int *, int *, int *, int *, int *, int *, double *, double *, double *, double *, char *, char *, char *, int *, int, int, int)"
+
+
+ # HP aCC specific tests. HP aCC demangling does not use __pt__ for
+ # template specifications. There are other differences as well.
+
+ gdb_test_exact "maint demangle __dt__2T5XTPFiPPdPv_i__Fv" "T5<int (*)(int, double **, void *)>::~T5(void)"
+
+ gdb_test_exact "maint demangle __ct__1cFi" "c::c(int)"
+
+ gdb_test_exact "maint demangle __dt__2T5XTi__Fv" "T5<int>::~T5(void)"
+
+ gdb_test_exact "maint demangle __dt__2T5XTc__Fv" "T5<char>::~T5(void)"
+
+ gdb_test_exact "maint demangle __ct__2T2Fi" "T2::T2(int)"
+ gdb_test_exact "maint demangle __dt__2T1Fv" "T1::~T1(void)"
+
+ gdb_test_exact "maint demangle __dt__2T5XT1x__Fv" "T5<x>::~T5(void)"
+
+ gdb_test_exact "maint demangle __dt__2T5XTPFcPv_i__Fv" "T5<int (*)(char, void *)>::~T5(void)"
+
+ gdb_test_exact "maint demangle __ct__2T5XTPFiPPdPv_i__Fi" "T5<int (*)(int, double **, void *)>::T5(int)"
+
+ gdb_test_exact "maint demangle __dl__2T5XT1x__SFPv" "T5<x>::operator delete(void *) static"
+
+ gdb_test_exact "maint demangle X__2T5XT1x" "T5<x>::X"
+
+ gdb_test_exact "maint demangle __ct__2T5XTi__Fi" "T5<int>::T5(int)"
+
+ gdb_test_exact "maint demangle __ct__2T5XTc__Fi" "T5<char>::T5(int)"
+
+ gdb_test_exact "maint demangle __dl__2T5XTPFcPv_i__SFPv" "T5<int (*)(char, void *)>::operator delete(void *) static"
+
+ gdb_test_exact "maint demangle X__2T5XTPFcPv_i" "T5<int (*)(char, void *)>::X"
+
+ gdb_test_exact "maint demangle __ct__2T5XT1x__Fi" "T5<x>::T5(int)"
+
+ gdb_test_exact "maint demangle __dl__2T5XTPFiPPdPv_i__SFPv" "T5<int (*)(int, double **, void *)>::operator delete(void *) static"
+ gdb_test_exact "maint demangle X__2T5XTPFiPPdPv_i" "T5<int (*)(int, double **, void *)>::X"
+
+ gdb_test_exact "maint demangle __dl__2T5XTi__SFPv" "T5<int>::operator delete(void *) static"
+
+ gdb_test_exact "maint demangle __dl__2T5XTc__SFPv" "T5<char>::operator delete(void *) static"
+
+ gdb_test_exact "maint demangle X__2T5XTc" "T5<char>::X"
+
+ gdb_test_exact "maint demangle X__2T5XTi" "T5<int>::X"
+
+ gdb_test_exact "maint demangle __ct__2T5XTPFcPv_i__Fi" "T5<int (*)(char, void *)>::T5(int)"
+
+ gdb_test_exact "maint demangle __dt__2T1XTc__Fv" "T1<char>::~T1(void)"
+
+ gdb_test_exact "maint demangle __dt__2T1XT1t__Fv" "T1<t>::~T1(void)"
+
+ gdb_test_exact "maint demangle __dl__2T1XT1t__SFPv" "T1<t>::operator delete(void *) static"
+
+ gdb_test_exact "maint demangle __ct__2T1XTc__Fi" "T1<char>::T1(int)"
+
+ gdb_test_exact "maint demangle __ct__2T1XTc__Fv" "T1<char>::T1(void)"
+
+ gdb_test_exact "maint demangle __ct__2T1XT1t__Fi" "T1<t>::T1(int)"
+
+ gdb_test_exact "maint demangle __ct__2T1XT1t__Fv" "T1<t>::T1(void)"
+
+ gdb_test_exact "maint demangle __dl__2T1XTc__SFPv" "T1<char>::operator delete(void *) static"
+
+ gdb_test_exact "maint demangle elem__6vectorXTd__Fi" "vector<double>::elem(int)"
+
+ gdb_test_exact "maint demangle elem__6vectorXTi__Fi" "vector<int>::elem(int)"
+
+ gdb_test_exact "maint demangle __ct__6vectorXTd__Fi" "vector<double>::vector(int)"
+
+ gdb_test_exact "maint demangle __ct__6vectorXTi__Fi" "vector<int>::vector(int)"
+
+ gdb_test_exact "maint demangle __ct__9DListNodeXTR6RLabel__FR6RLabelP9DListNodeXTR6RLabel_T2" \
+ "DListNode<RLabel &>::DListNode(RLabel &, DListNode<RLabel &> *, DListNode<RLabel &> *)"
+
+
+ # Absolute integer constants in template args
+
+ gdb_test_exact "maint demangle elem__6vectorXTiUP34__Fi" "vector<int,34U>::elem(int)"
+ gdb_test_exact "maint demangle elem__6vectorXUP2701Td__Fi" "vector<2701U,double>::elem(int)"
+ gdb_test_exact "maint demangle elem__6vectorXTiSP334__Fi" "vector<int,334>::elem(int)"
+ gdb_test_exact "maint demangle elem__6vectorXTiSN67__Fi" "vector<int,-67>::elem(int)"
+ gdb_test_exact "maint demangle elem__6vectorXTiSM__SCFPPd" "vector<int,-2147483648>::elem(double **) static const"
+ gdb_test_exact "maint demangle elem__6vectorXTiSN67UP4000TRs__Fi" "vector<int,-67,4000U,short &>::elem(int)"
+ gdb_test_exact "maint demangle elem__6vectorXTiSN67TRdTFPv_i__Fi" "vector<int,-67,double &,int (void *)>::elem(int)"
+ gdb_test_exact "maint demangle X__6vectorXTiSN67TdTPvUP5TRs" "vector<int,-67,double,void *,5U,short &>::X"
+
+ # Named constants in template args
+
+ gdb_test_exact "maint demangle elem__6vectorXTiA3foo__Fi" "vector<int,&foo>::elem(int)"
+ gdb_test_exact "maint demangle elem__6vectorXTiA3fooTPvA5Label__FiPPvT2" "vector<int,&foo,void *,&Label>::elem(int, void **, void **)"
+ gdb_test_exact "maint demangle elem__6vectorXTiSN42A3foo__Fi" "vector<int,-42,&foo>::elem(int)"
+
+ # Alternate entry points for functions
+
+ gdb_test_exact "maint demangle __ct__2T5XTPFcPv_i__Fi_2" "T5<int (*)(char, void *)>::T5(int)"
+ gdb_test_exact "maint demangle __ct__2T5XTPFcPv_i__Fi_19" "T5<int (*)(char, void *)>::T5(int)"
+ gdb_test_exact "maint demangle f__FicdPcPFci_v_34" "f(int, char, double, char *, void (*)(char, int))"
+
+
+ # Template partial specializations
+
+# FIXME! The # characters don't go through expect, and backslashes don't seem to work.
+# gdb_test_exact "maint demangle spec__13Spec<#1,#1.*>XTiTPi_FPi" "Spec<int,int *>::spec(int *)"
+# gdb_test_exact "maint demangle spec__16Spec<#1,#1.&,#1>XTiTRiTi_FPi" "Spec<int,int &, int>::spec(int *)"
+# Fake test -- replace # with %
+ gdb_test_exact "maint demangle spec__13Spec<%1,%1.*>XTiTPi_FPi" "Spec<int,int *>::spec(int *)"
+ gdb_test_exact "maint demangle spec__16Spec<%1,%1.&,%1>XTiTRiTi_FPi" "Spec<int,int &,int>::spec(int *)"
+
+ # Global template functions
+
+ gdb_test_exact "maint demangle add__XTc_FcT1" "add<char>(char, char)"
+ gdb_test_exact "maint demangle add__XTcSP9A5label_FcPPlT1" "add<char,9,&label>(char, long **, char)"
+ gdb_test_exact "maint demangle add__XTPfTFPd_f_FcT1" "add<float *,float (double *)>(char, char)"
+
+ # Template for template arg
+
+ gdb_test_exact "maint demangle unLink__12basic_stringXTcT18string_char_traitsXTc_T9allocator_Fv" "basic_string<char,string_char_traits<char>,allocator>::unLink(void)"
+
+}
+# Test support for different demangling styles. Note that this does
+# not depend upon running the test program and does not depend upon
+# gdb being able to lookup any C++ symbols. It simply calls the
+# internal demangler with synthesized strings and tests the results.
+
+proc do_tests {} {
+ global prms_id
+ global bug_id
+ global subdir
+ global gdb_prompt
+
+ set prms_id 0
+ set bug_id 0
+
+ # Start with a fresh gdb.
+
+ gdb_exit
+ gdb_start
+
+ send_gdb "set language c++\n"
+ gdb_expect -re "$gdb_prompt $"
+ send_gdb "set width 0\n"
+ gdb_expect -re "$gdb_prompt $"
+
+ test_lucid_style_demangling
+ test_gnu_style_demangling
+ test_arm_style_demangling
+ test_hp_style_demangling
+}
+
+do_tests
diff --git a/gdb/testsuite/gdb.c++/derivation.cc b/gdb/testsuite/gdb.c++/derivation.cc
new file mode 100644
index 00000000000..99efa7605a4
--- /dev/null
+++ b/gdb/testsuite/gdb.c++/derivation.cc
@@ -0,0 +1,240 @@
+class A {
+public:
+ int a;
+ int aa;
+
+ A()
+ {
+ a=1;
+ aa=2;
+ }
+ int afoo();
+ int foo();
+
+};
+
+
+
+class B {
+public:
+ int b;
+ int bb;
+
+ B()
+ {
+ b=3;
+ bb=4;
+ }
+ int bfoo();
+ int foo();
+
+};
+
+
+
+class C {
+public:
+ int c;
+ int cc;
+
+ C()
+ {
+ c=5;
+ cc=6;
+ }
+ int cfoo();
+ int foo();
+
+};
+
+
+
+class D : private A, public B, protected C {
+public:
+ int d;
+ int dd;
+
+ D()
+ {
+ d =7;
+ dd=8;
+ }
+ int dfoo();
+ int foo();
+
+};
+
+
+class E : public A, B, protected C {
+public:
+ int e;
+ int ee;
+
+ E()
+ {
+ e =9;
+ ee=10;
+ }
+ int efoo();
+ int foo();
+
+};
+
+
+class F : A, public B, C {
+public:
+ int f;
+ int ff;
+
+ F()
+ {
+ f =11;
+ ff=12;
+ }
+ int ffoo();
+ int foo();
+
+};
+
+class G : private A, public B, protected C {
+public:
+ int g;
+ int gg;
+ int a;
+ int b;
+ int c;
+
+ G()
+ {
+ g =13;
+ gg =14;
+ a=15;
+ b=16;
+ c=17;
+
+ }
+ int gfoo();
+ int foo();
+
+};
+
+
+
+
+int A::afoo() {
+ return 1;
+}
+
+int B::bfoo() {
+ return 2;
+}
+
+int C::cfoo() {
+ return 3;
+}
+
+int D::dfoo() {
+ return 4;
+}
+
+int E::efoo() {
+ return 5;
+}
+
+int F::ffoo() {
+ return 6;
+}
+
+int G::gfoo() {
+ return 77;
+}
+
+int A::foo()
+{
+ return 7;
+
+}
+
+int B::foo()
+{
+ return 8;
+
+}
+
+int C::foo()
+{
+ return 9;
+
+}
+
+int D::foo()
+{
+ return 10;
+
+}
+
+int E::foo()
+{
+ return 11;
+
+}
+
+int F::foo()
+{
+ return 12;
+
+}
+
+int G::foo()
+{
+ return 13;
+
+}
+
+
+void marker1()
+{
+}
+
+
+int main(void)
+{
+
+ A a_instance;
+ B b_instance;
+ C c_instance;
+ D d_instance;
+ E e_instance;
+ F f_instance;
+ G g_instance;
+
+ #ifdef usestubs
+ set_debug_traps();
+ breakpoint();
+ #endif
+
+
+ marker1();
+
+ a_instance.a = 20;
+ a_instance.aa = 21;
+ b_instance.b = 22;
+ b_instance.bb = 23;
+ c_instance.c = 24;
+ c_instance.cc = 25;
+ d_instance.d = 26;
+ d_instance.dd = 27;
+ e_instance.e = 28;
+ e_instance.ee =29;
+ f_instance.f =30;
+ f_instance.ff =31;
+
+
+
+
+ return 0;
+
+}
+
+
+
diff --git a/gdb/testsuite/gdb.c++/derivation.exp b/gdb/testsuite/gdb.c++/derivation.exp
new file mode 100644
index 00000000000..ed3cc2cfbcc
--- /dev/null
+++ b/gdb/testsuite/gdb.c++/derivation.exp
@@ -0,0 +1,316 @@
+# Copyright (C) 1998 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file was written by Elena Zannoni (ezannoni@cygnus.com)
+
+# This file is part of the gdb testsuite
+#
+
+#
+# tests for inheritance, with several derivations types combinations (private,
+# public, protected)
+# classes have simple members and member functions.
+#
+
+
+if $tracelevel then {
+ strace $tracelevel
+ }
+
+#
+# test running programs
+#
+set prms_id 0
+set bug_id 0
+
+set testfile "derivation"
+set srcfile ${testfile}.cc
+set binfile ${objdir}/${subdir}/${testfile}
+
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug c++}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+remote_file build delete ${binfile}.ci
+ if {![istarget "hppa*-*-hpux*"]} {
+ if { [gdb_compile "${srcdir}/${subdir}/compiler.cc" "${binfile}.ci" preprocess ""] != ""
+} {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will auto
+matically fail."
+ }
+ } else {
+ if { [gdb_preprocess "${srcdir}/${subdir}/compiler.cc" "${binfile}.ci" "c++"] != "" } {
+ perror "Couldn't make ${binfile}.ci file"
+ return 1;
+ }
+ }
+
+source ${binfile}.ci
+
+#
+# set it up at a breakpoint so we can play with the variable values
+#
+if ![runto_main] then {
+ perror "couldn't run to breakpoint"
+ continue
+}
+
+send_gdb "break marker1\n" ; gdb_expect -re ".*$gdb_prompt $"
+
+ send_gdb "cont\n"
+ gdb_expect {
+ -re "Break.* marker1 \\(\\) at .*:$decimal.*$gdb_prompt $" {
+ send_gdb "up\n"
+ gdb_expect {
+ -re ".*$gdb_prompt $" {}
+ timeout { fail "up from marker1" }
+ }
+ }
+ -re "$gdb_prompt $" { fail "continue to marker1" }
+ timeout { fail "(timeout) continue to marker1" }
+ }
+
+
+
+send_gdb "print a_instance\n"
+gdb_expect {
+ -re ".\[0-9\]* = \{a = 1, aa = 2\}\r\n$gdb_prompt $" {
+ pass "print value of a_instance"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of a_instance" }
+ timeout { fail "(timeout) print value of a_instance" }
+ }
+
+
+send_gdb "ptype a_instance\n"
+gdb_expect {
+ -re "type = class A \{\r\n\[\t \]*public:\r\n\[\t \]*int a;\r\n\[\t \]*int aa;\[\r\n\t \]+A\\(void\\);\r\n\[\t \]*int afoo\\(void\\);\r\n\[\t \]*int foo\\(void\\);\r\n\}.*$gdb_prompt $" { pass "ptype a_instance" }
+ -re ".*$gdb_prompt $" { fail "ptype a_instance" }
+ timeout { fail "(timeout) ptype a_instance" }
+}
+
+
+send_gdb "print d_instance\n"
+gdb_expect {
+ -re ".\[0-9\]* = \{<A> = \{a = 1, aa = 2\}, <B> = \{b = 3, bb = 4\}, <C> = \{c = 5, cc = 6\}, d = 7, dd = 8\}\r\n$gdb_prompt $" {
+ pass "print value of d_instance"
+ }
+ -re ".\[0-9\]* = \{<class A> = \{a = 1, aa = 2\}, <class B> = \{b = 3, bb = 4\}, <class C> = \{c = 5, cc = 6\}, d = 7, dd = 8\}\r\n$gdb_prompt $" {
+ pass "print value of d_instance"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of d_instance" }
+ timeout { fail "(timeout) print value of d_instance" }
+ }
+
+ if {$gcc_compiled} then {
+ send_gdb "ptype d_instance\n"
+ gdb_expect {
+ -re "type = class D : private A, public B, private C \{\r\n\[\t \]*public:\r\n\[\t \]*int d;\r\n\[\t \]*int dd;\[\r\n\t \]+D\\(void\\);\r\n\[\t \]*int dfoo\\(void\\);\r\n\[\t \]*int foo\\(void\\);\r\n\}.*$gdb_prompt $" { pass "ptype d_instance" }
+ -re ".*$gdb_prompt $" { fail "ptype d_instance" }
+ timeout { fail "(timeout) ptype d_instance" }
+ }
+ } else {
+ send_gdb "ptype d_instance\n"
+ gdb_expect {
+ -re "type = class D : private A, public B, protected C \{\r\n\[\t \]*public:\r\n\[\t \]*int d;\r\n\[\t \]*int dd;\[\r\n\t \]+D\\(void\\);\r\n\[\t \]*int dfoo\\(void\\);\r\n\[\t \]*int foo\\(void\\);\r\n\}.*$gdb_prompt $" { pass "ptype d_instance" }
+ -re ".*$gdb_prompt $" { fail "ptype d_instance" }
+ timeout { fail "(timeout) ptype d_instance" }
+ }
+ }
+
+
+send_gdb "print e_instance\n"
+gdb_expect {
+ -re ".\[0-9\]* = \{<A> = \{a = 1, aa = 2\}, <B> = \{b = 3, bb = 4\}, <C> = \{c = 5, cc = 6\}, e = 9, ee = 10\}\r\n$gdb_prompt $" {
+ pass "print value of e_instance"
+ }
+ -re ".\[0-9\]* = \{<class A> = \{a = 1, aa = 2\}, <class B> = \{b = 3, bb = 4\}, <class C> = \{c = 5, cc = 6\}, e = 9, ee = 10\}\r\n$gdb_prompt $" {
+ pass "print value of e_instance"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of e_instance" }
+ timeout { fail "(timeout) print value of e_instance" }
+ }
+
+ if {$gcc_compiled} {
+ send_gdb "ptype e_instance\n"
+ gdb_expect {
+ -re "type = class E : public A, private B, private C \{\r\n\[\t \]*public:\r\n\[\t \]*int e;\r\n\[\t \]*int ee;\[\r\n\t \]+E\\(void\\);\r\n\[\t \]*int efoo\\(void\\);\r\n\[\t \]*int foo\\(void\\);\r\n\}.*$gdb_prompt $" { pass "ptype e_instance" }
+ -re ".*$gdb_prompt $" { fail "ptype e_instance" }
+ timeout { fail "(timeout) ptype e_instance" }
+ }
+ } else {
+ send_gdb "ptype e_instance\n"
+ gdb_expect {
+ -re "type = class E : public A, private B, protected C \{\r\n\[\t \]*public:\r\n\[\t \]*int e;\r\n\[\t \]*int ee;\[\r\n\t \]+E\\(void\\);\r\n\[\t \]*int efoo\\(void\\);\r\n\[\t \]*int foo\\(void\\);\r\n\}.*$gdb_prompt $" { pass "ptype e_instance" }
+ -re ".*$gdb_prompt $" { fail "ptype e_instance" }
+ timeout { fail "(timeout) ptype e_instance" }
+ }
+ }
+
+
+send_gdb "print f_instance\n"
+gdb_expect {
+ -re ".\[0-9\]* = \{<A> = \{a = 1, aa = 2\}, <B> = \{b = 3, bb = 4\}, <C> = \{c = 5, cc = 6\}, f = 11, ff = 12\}\r\n$gdb_prompt $" {
+ pass "print value of f_instance"
+ }
+ -re ".\[0-9\]* = \{<class A> = \{a = 1, aa = 2\}, <class B> = \{b = 3, bb = 4\}, <class C> = \{c = 5, cc = 6\}, f = 11, ff = 12\}\r\n$gdb_prompt $" {
+ pass "print value of f_instance"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of f_instance" }
+ timeout { fail "(timeout) print value of f_instance" }
+ }
+
+send_gdb "ptype f_instance\n"
+gdb_expect {
+ -re "type = class F : private A, public B, private C \{\r\n\[\t \]*public:\r\n\[\t \]*int f;\r\n\[\t \]*int ff;\[\r\n\t \]+F\\(void\\);\r\n\[\t \]*int ffoo\\(void\\);\r\n\[\t \]*int foo\\(void\\);\r\n\}.*$gdb_prompt $" { pass "ptype f_instance" }
+ -re ".*$gdb_prompt $" { fail "ptype f_instance" }
+ timeout { fail "(timeout) ptype f_instance" }
+}
+
+
+
+send_gdb "print d_instance.a\n"
+gdb_expect {
+ -re ".\[0-9\]* = 1.*$gdb_prompt $" {
+ pass "print value of d_instance.a"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of d_instance.a" }
+ timeout { fail "(timeout) print value of d_instance.a" }
+ }
+
+send_gdb "print d_instance.aa\n"
+gdb_expect {
+ -re ".\[0-9\]* = 2.*$gdb_prompt $" {
+ pass "print value of d_instance.aa"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of d_instance.aa" }
+ timeout { fail "(timeout) print value of d_instance.aa" }
+ }
+
+send_gdb "print d_instance.b\n"
+gdb_expect {
+ -re ".\[0-9\]* = 3.*$gdb_prompt $" {
+ pass "print value of d_instance.b"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of d_instance.b" }
+ timeout { fail "(timeout) print value of d_instance.b" }
+ }
+
+send_gdb "print d_instance.bb\n"
+gdb_expect {
+ -re ".\[0-9\]* = 4.*$gdb_prompt $" {
+ pass "print value of d_instance.bb"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of d_instance.bb" }
+ timeout { fail "(timeout) print value of d_instance.bb" }
+ }
+
+send_gdb "print d_instance.c\n"
+gdb_expect {
+ -re ".\[0-9\]* = 5.*$gdb_prompt $" {
+ pass "print value of d_instance.c"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of d_instance.c" }
+ timeout { fail "(timeout) print value of d_instance.c" }
+ }
+
+send_gdb "print d_instance.cc\n"
+gdb_expect {
+ -re ".\[0-9\]* = 6.*$gdb_prompt $" {
+ pass "print value of d_instance.cc"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of d_instance.cc" }
+ timeout { fail "(timeout) print value of d_instance.cc" }
+ }
+
+send_gdb "print d_instance.d\n"
+gdb_expect {
+ -re ".\[0-9\]* = 7.*$gdb_prompt $" {
+ pass "print value of d_instance.d"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of d_instance.d" }
+ timeout { fail "(timeout) print value of d_instance.d" }
+ }
+
+send_gdb "print d_instance.dd\n"
+gdb_expect {
+ -re ".\[0-9\]* = 8.*$gdb_prompt $" {
+ pass "print value of d_instance.dd"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of d_instance.dd" }
+ timeout { fail "(timeout) print value of d_instance.dd" }
+ }
+
+send_gdb "print g_instance.a\n"
+gdb_expect {
+ -re ".\[0-9\]* = 15.*$gdb_prompt $" {
+ pass "print value of g_instance.a"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of g_instance.a" }
+ timeout { fail "(timeout) print value of g_instance.a" }
+ }
+
+send_gdb "print g_instance.b\n"
+gdb_expect {
+ -re ".\[0-9\]* = 16.*$gdb_prompt $" {
+ pass "print value of g_instance.b"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of g_instance.b" }
+ timeout { fail "(timeout) print value of g_instance.b" }
+ }
+
+send_gdb "print g_instance.c\n"
+gdb_expect {
+ -re ".\[0-9\]* = 17.*$gdb_prompt $" {
+ pass "print value of g_instance.c"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of g_instance.c" }
+ timeout { fail "(timeout) print value of g_instance.c" }
+ }
+
+send_gdb "print g_instance.afoo()\n"
+gdb_expect {
+ -re ".\[0-9\]* = 1.*$gdb_prompt $" {
+ pass "print value of g_instance.afoo()"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of g_instance.afoo()" }
+ timeout { fail "(timeout) print value of g_instance.afoo()" }
+ }
+
+send_gdb "print g_instance.bfoo()\n"
+gdb_expect {
+ -re ".\[0-9\]* = 2.*$gdb_prompt $" {
+ pass "print value of g_instance.bfoo()"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of g_instance.bfoo()" }
+ timeout { fail "(timeout) print value of g_instance.bfoo()" }
+ }
+
+send_gdb "print g_instance.cfoo()\n"
+gdb_expect {
+ -re ".\[0-9\]* = 3.*$gdb_prompt $" {
+ pass "print value of g_instance.cfoo()"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of g_instance.cfoo()" }
+ timeout { fail "(timeout) print value of g_instance.cfoo()" }
+ }
diff --git a/gdb/testsuite/gdb.c++/inherit.exp b/gdb/testsuite/gdb.c++/inherit.exp
new file mode 100644
index 00000000000..8c7a90c9153
--- /dev/null
+++ b/gdb/testsuite/gdb.c++/inherit.exp
@@ -0,0 +1,859 @@
+# Copyright (C) 1992, 1993, 1994, 1997 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file was written by Fred Fish. (fnf@cygnus.com)
+
+set ws "\[\r\n\t \]+"
+set nl "\[\r\n\]+"
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+# Check to see if we have an executable to test. If not, then either we
+# haven't tried to compile one, or the compilation failed for some reason.
+# In either case, just notify the user and skip the tests in this file.
+# Note - create separate "inherit" executable from misc.cc
+
+set testfile "inherit"
+set srcfile misc.cc
+set binfile ${objdir}/${subdir}/${testfile}
+
+
+# Create and source the file that provides information about the compiler
+# used to compile the test case.
+
+if [get_compiler_info ${binfile} "c++"] {
+ return -1
+}
+
+# if we are on HPUX and we are not compiled with gcc, then skip these tests.
+
+if [istarget hppa*-*-hpux*] {
+ if {!$gcc_compiled} {
+ continue
+ }
+}
+
+
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug c++}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+#
+# Single inheritance, print individual members.
+#
+
+proc test_print_si_members {} {
+ # Print all members of g_A using fully qualified form.
+
+ gdb_test "print g_A.A::a" ".* = 1" "print g_A.A::a"
+
+ gdb_test "print g_A.A::x" ".* = 2" "print g_A.A::x"
+
+ # Print members of g_A using nonambiguous compact form.
+
+ gdb_test "print g_A.a" ".* = 1" "print g_A.a"
+
+ gdb_test "print g_A.x" ".* = 2" "print g_A.x"
+
+ # Print all members of g_B using fully qualified form.
+
+ gdb_test "print g_B.A::a" ".* = 3" "print g_B.A::a"
+
+ gdb_test "print g_B.A::x" ".* = 4" "print g_B.A::x"
+
+ gdb_test "print g_B.B::b" ".* = 5" "print g_B.B::b"
+
+ gdb_test "print g_B.B::x" ".* = 6" "print g_B.B::x"
+
+ # Print members of g_B using nonambiguous compact form.
+
+ setup_xfail_format "DWARF 1"
+ gdb_test "print g_B.a" ".* = 3" "print g_B.a"
+
+ gdb_test "print g_B.b" ".* = 5" "print g_B.b"
+
+ gdb_test "print g_B.x" ".* = 6" "print g_B.x"
+
+ # Print all members of g_C using fully qualified form.
+
+ gdb_test "print g_C.A::a" ".* = 7" "print g_C.A::a"
+
+ gdb_test "print g_C.A::x" ".* = 8" "print g_C.A::x"
+
+ gdb_test "print g_C.C::c" ".* = 9" "print g_C.C::c"
+
+ gdb_test "print g_C.C::x" ".* = 10" "print g_C.C::x"
+
+ # Print members of g_C using nonambiguous compact form.
+
+ setup_xfail_format "DWARF 1"
+ gdb_test "print g_C.a" ".* = 7" "print g_C.a"
+
+ gdb_test "print g_C.c" ".* = 9" "print g_C.c"
+
+ gdb_test "print g_C.x" ".* = 10" "print g_C.x"
+}
+
+#
+# Single inheritance, print type definitions.
+#
+
+proc test_ptype_si {} {
+ global gdb_prompt
+ global ws
+ global nl
+
+ # Print class A as a type.
+
+ send_gdb "ptype A\n"
+ gdb_expect {
+ -re "type = class A \{$nl.*\[ \]*int a;$nl\[ \]*int x;$nl.*\[ \]*\}$nl$gdb_prompt $" {
+ pass "ptype A (FIXME)"
+ }
+ -re "type = struct A \{$nl\[ \]*int a;$nl\[ \]*int x;$nl\[ \]*\}$nl$gdb_prompt $" {
+ setup_xfail "*-*-*"
+ fail "ptype A (FIXME)"
+ }
+ -re ".*$gdb_prompt $" { fail "ptype A" }
+ timeout { fail "ptype A (timeout)" ; return }
+ }
+
+ # Print class A as an explicit class.
+
+ send_gdb "ptype class A\n"
+ gdb_expect {
+ -re "type = class A \{$nl.*\[ \]*int a;$nl\[ \]*int x;$nl.*\[ \]*\}$nl$gdb_prompt $" {
+ pass "ptype class A (FIXME)"
+ }
+ -re "type = struct A \{$nl\[ \]*int a;$nl\[ \]*int x;$nl\[ \]*\}$nl$gdb_prompt $" {
+ setup_xfail "*-*-*"
+ fail "ptype class A (FIXME)"
+ }
+ -re ".*$gdb_prompt $" { fail "ptype class A" }
+ timeout { fail "ptype class A (timeout)" ; return }
+ }
+
+ # Print type of an object of type A.
+
+ send_gdb "ptype g_A\n"
+ gdb_expect {
+ -re "type = class A \{$nl.*\[ \]*int a;$nl\[ \]*int x;$nl.*\[ \]*\}$nl$gdb_prompt $" {
+ pass "ptype g_A (FIXME)"
+ }
+ -re "type = struct A \{$nl\[ \]*int a;$nl\[ \]*int x;$nl\[ \]*\}$nl$gdb_prompt $" {
+ setup_xfail "*-*-*"
+ fail "ptype g_A (FIXME)"
+ }
+ -re ".*$gdb_prompt $" { fail "ptype g_A" }
+ timeout { fail "ptype g_A (timeout)" ; return }
+ }
+
+ # Print class B as a type.
+
+ setup_xfail_format "DWARF 1"
+ gdb_test "ptype B" "type = class B : public A \{$nl\[ \]*public:$nl\[ \]*int b;$nl\[ \]*int x;$nl.*\}" "ptype B"
+
+ # Print class B as an explicit class.
+
+ setup_xfail_format "DWARF 1"
+ gdb_test "ptype class B" "type = class B : public A \{$nl\[ \]*public:$nl\[ \]*int b;$nl\[ \]*int x;$nl.*\}" "ptype class B"
+
+ # Print type of an object of type B.
+
+ setup_xfail_format "DWARF 1"
+ gdb_test "ptype g_B" "type = class B : public A \{$nl\[ \]*public:$nl\[ \]*int b;$nl\[ \]*int x;$nl.*\}" "ptype g_B"
+
+ # Print class C as a type.
+
+ setup_xfail_format "DWARF 1"
+ gdb_test "ptype C" "type = class C : public A \{$nl\[ \]*public:$nl\[ \]*int c;$nl\[ \]*int x;$nl.*\}" "ptype C"
+
+ # Print class C as an explicit class.
+
+ setup_xfail_format "DWARF 1"
+ gdb_test "ptype class C" "type = class C : public A \{$nl\[ \]*public:$nl\[ \]*int c;$nl\[ \]*int x;$nl.*\}" "ptype class C"
+
+ # Print type of an object of type g_C.
+
+ setup_xfail_format "DWARF 1"
+ gdb_test "ptype g_C" "type = class C : public A \{$nl\[ \]*public:$nl\[ \]*int c;$nl\[ \]*int x;$nl.*\}" "ptype g_C"
+
+ # gcc cygnus-2.3.3 (Q1) has this bug, but it was fixed as of
+ # cygnus-2.3.3-930417. PR 2819.
+ send_gdb "ptype tagless_struct\n"
+ gdb_expect {
+ -re "type = class \{${ws}public:${ws}int one;${ws}int two;${ws}tagless_struct & operator=\\(tagless_struct &\\);${ws}\\\$_1 \\(tagless_struct &\\);${ws}\\\$_1 \\(\\);${ws}\}$nl$gdb_prompt $" {
+ pass "ptype tagless struct"
+ }
+ -re "type = (struct|class).*\{.*int one;.*int two;.*\}$nl$gdb_prompt $" {
+ pass "ptype tagless struct (obsolete gcc or gdb)"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "ptype tagless struct"
+ }
+ timeout {
+ fail "ptype tagless struct (timeout)"
+ }
+ }
+
+ send_gdb "ptype v_tagless\n"
+ gdb_expect {
+ -re "type = class \{${ws}public:${ws}int one;${ws}int two;${ws}tagless_struct & operator=\\(tagless_struct &\\);${ws}\\\$_1 \\(tagless_struct &\\);${ws}\\\$_1 \\(\\);${ws}\}$nl$gdb_prompt $" {
+ pass "ptype variable of type tagless struct"
+ }
+ -re "type = (struct|class).*\{.*int one;.*int two;.*\}$nl$gdb_prompt $" {
+ pass "ptype variable of type tagless struct (obsolete gcc or gdb)"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "ptype variable of type tagless struct"
+ }
+ timeout {
+ fail "ptype variable of type tagless struct (timeout)"
+ }
+ }
+}
+
+#
+# Single inheritance, print complete classes.
+#
+
+proc test_print_si_classes {} {
+ # Print all members of g_A.
+
+ gdb_test "print g_A" ".* = \{a = 1, x = 2\}" "print g_A"
+
+ # Print all members of g_B.
+
+ setup_xfail_format "DWARF 1"
+ gdb_test "print g_B" ".* = \{\<A\> = \{a = 3, x = 4\}, b = 5, x = 6\}" "print g_B"
+
+ # Print all members of g_C.
+
+ setup_xfail_format "DWARF 1"
+ gdb_test "print g_C" ".* = \{\<A\> = \{a = 7, x = 8\}, c = 9, x = 10\}" "print g_C"
+}
+
+#
+# Single inheritance, print anonymous unions.
+# GDB versions prior to 4.14 entered an infinite loop when printing
+# the type of a class containing an anonymous union, and they were also
+# incapable of printing the member of an anonymous union.
+# We test the printing of the member first, and perform the other tests
+# only if the test succeeds, to avoid the infinite loop.
+#
+
+proc test_print_anon_union {} {
+ global gdb_prompt
+ global ws
+ global nl
+
+ setup_xfail_format "DWARF 1"
+ gdb_test "print g_anon_union.a" ".* = 2" "print anonymous union member"
+ setup_xfail_format "DWARF 1"
+ send_gdb "print g_anon_union\n"
+ gdb_expect {
+ -re ".* = \{one = 1, = \{a = 2, b = 2\}\}$nl$gdb_prompt $" {
+ pass "print variable of type anonymous union"
+ }
+ -re ".* = .*\{one = 1, = \{a = 2, b = .*\}\}$nl$gdb_prompt $" {
+ pass "print variable of type anonymous union (obsolete gcc or gdb)"
+ }
+ -re ".*$nl$gdb_prompt $" {
+ fail "print variable of type anonymous union"
+ }
+ timeout {
+ fail "print variableof type anonymous union (timeout)"
+ }
+ }
+ setup_xfail_format "DWARF 1"
+ send_gdb "ptype g_anon_union\n"
+ gdb_expect {
+ -re "type = class class_with_anon_union \{${ws}public:${ws}int one;${ws}union \{${ws}public:${ws}int a;${ws}long int b;${ws}union \{\.\.\.\} & operator=\\(union \{\.\.\.\} &\\);${ws}\\\$_0 \\(union \{\.\.\.\} &\\);${ws}\\\$_0 \\(\\);${ws}\};${ws}class_with_anon_union & operator=\\(class_with_anon_union const &\\);${ws}class_with_anon_union\\(class_with_anon_union const &\\);${ws}class_with_anon_union\\(void\\);${ws}\}$nl$gdb_prompt $" {
+ pass "print type of anonymous union"
+ }
+ -re "type = (struct|class).*\{.*int one;.*union \{.*int a;.*(long|long int|int) b;.*\};.*\}$nl$gdb_prompt $" {
+ pass "print type of anonymous union (obsolete gcc or gdb)"
+ }
+ -re ".*$nl$gdb_prompt $" {
+ fail "print type of anonymous union"
+ }
+ timeout {
+ fail "print type of anonymous union (timeout)"
+ }
+ }
+}
+
+#
+# Multiple inheritance, print individual members.
+#
+
+proc test_print_mi_members {} {
+ global gdb_prompt
+ global nl
+
+ # Print all members of g_A.
+
+ gdb_test "print g_A.A::a" ".* = 1" "print g_A.A::a"
+
+ gdb_test "print g_A.A::x" ".* = 2" "print g_A.A::x"
+
+ # Print all members of g_B.
+
+ gdb_test "print g_B.A::a" ".* = 3" "print g_B.A::a"
+
+ gdb_test "print g_B.A::x" ".* = 4" "print g_B.A::x"
+
+ gdb_test "print g_B.B::b" ".* = 5" "print g_B.B::b"
+
+ gdb_test "print g_B.B::x" ".* = 6" "print g_B.B::x"
+
+ # Print all members of g_C.
+
+ gdb_test "print g_C.A::a" ".* = 7" "print g_C.A::a"
+
+ gdb_test "print g_C.A::x" ".* = 8" "print g_C.A::x"
+
+ gdb_test "print g_C.C::c" ".* = 9" "print g_C.C::c"
+
+ gdb_test "print g_C.C::x" ".* = 10" "print g_C.C::x"
+
+ # Print all members of g_D.
+
+ # The following is ambiguous, and gdb should detect this.
+ # For now, accept gdb's behavior as an expected failure if it
+ # simply prints either member correctly.
+
+ setup_xfail "*-*-*"
+ send_gdb "print g_D.A::a\n"
+ gdb_expect {
+ -re ".* = 11$nl$gdb_prompt $" {
+ fail "print g_D.A::a (FIXME)"
+ }
+ -re ".* = 15$nl$gdb_prompt $" {
+ fail "print g_D.A::a (FIXME)"
+ }
+ -re ".*$gdb_prompt $" { fail "print g_D.A::a" }
+ timeout { fail "print g_D.A::a (timeout)" ; return }
+ }
+
+ # The following is ambiguous, and gdb should detect this.
+ # For now, accept gdb's behavior as an expected failure if it
+ # simply prints either member correctly.
+
+ setup_xfail "*-*-*"
+ send_gdb "print g_D.A::x\n"
+ gdb_expect {
+ -re ".* = 12$nl$gdb_prompt $" {
+ fail "print g_D.A::x (FIXME)"
+ }
+ -re ".* = 16$nl$gdb_prompt $" {
+ fail "print g_D.A::x (FIXME)"
+ }
+ -re ".*$gdb_prompt $" { fail "print g_D.A::x" }
+ timeout { fail "print g_D.A::x (timeout)" ; return }
+ }
+
+ gdb_test "print g_D.B::b" ".* = 13" "print g_D.B::b"
+
+ gdb_test "print g_D.B::x" ".* = 14" "print g_D.B::x"
+
+ setup_xfail_format "DWARF 1"
+ gdb_test "print g_D.C::c" ".* = 17" "print g_D.C::c"
+
+ setup_xfail_format "DWARF 1"
+ gdb_test "print g_D.C::x" ".* = 18" "print g_D.C::x"
+
+ gdb_test "print g_D.D::d" ".* = 19" "print g_D.D::d"
+
+ gdb_test "print g_D.D::x" ".* = 20" "print g_D.D::x"
+
+ # Print all members of g_E.
+
+ # The following is ambiguous, and gdb should detect this.
+ # For now, accept gdb's behavior as an expected failure if it
+ # simply prints either member correctly.
+
+ setup_xfail "*-*-*"
+ send_gdb "print g_E.A::a\n"
+ gdb_expect {
+ -re ".* = 21$nl$gdb_prompt $" {
+ fail "print g_E.A::a (FIXME)"
+ }
+ -re ".* = 25$nl$gdb_prompt $" {
+ fail "print g_E.A::a (FIXME)"
+ }
+ -re ".*$gdb_prompt $" { fail "print g_E.A::a" }
+ timeout { fail "print g_E.A::a (timeout)" ; return }
+ }
+
+ # The following is ambiguous, and gdb should detect this.
+ # For now, accept gdb's behavior as an expected failure if it
+ # simply prints either member correctly.
+
+ setup_xfail "*-*-*"
+ send_gdb "print g_E.A::x\n"
+ gdb_expect {
+ -re ".* = 22$nl$gdb_prompt $" {
+ fail "print g_E.A::x (FIXME)"
+ }
+ -re ".* = 26$nl$gdb_prompt $" {
+ fail "print g_E.A::x (FIXME)"
+ }
+ -re ".*$gdb_prompt $" { fail "print g_E.A::x" }
+ timeout { fail "print g_E.A::x (timeout)" ; return }
+ }
+
+ gdb_test "print g_E.B::b" ".* = 23" "print g_E.B::b"
+
+ gdb_test "print g_E.B::x" ".* = 24" "print g_E.B::x"
+
+ setup_xfail_format "DWARF 1"
+ gdb_test "print g_E.C::c" ".* = 27" "print g_E.C::c"
+
+ setup_xfail_format "DWARF 1"
+ gdb_test "print g_E.C::x" ".* = 28" "print g_E.C::x"
+
+ gdb_test "print g_E.D::d" ".* = 29" "print g_E.D::d"
+
+ gdb_test "print g_E.D::x" ".* = 30" "print g_E.D::x"
+
+ gdb_test "print g_E.E::e" ".* = 31" "print g_E.E::e"
+
+ gdb_test "print g_E.E::x" ".* = 32" "print g_E.E::x"
+}
+
+#
+# Multiple inheritance, print type definitions.
+#
+
+proc test_ptype_mi {} {
+ global nl
+
+ setup_xfail_format "DWARF 1"
+ gdb_test "ptype D" "type = class D : public B, public C \{$nl\[ \]*public:$nl\[ \]*int d;$nl\[ \]*int x;$nl.*\}" "ptype D"
+
+ setup_xfail_format "DWARF 1"
+ gdb_test "ptype class D" "type = class D : public B, public C \{$nl\[ \]*public:$nl\[ \]*int d;$nl\[ \]*int x;$nl.*\}" "ptype class D"
+
+ setup_xfail_format "DWARF 1"
+ gdb_test "ptype g_D" "type = class D : public B, public C \{$nl\[ \]*public:$nl\[ \]*int d;$nl\[ \]*int x;$nl.*\}" "ptype g_D"
+
+ setup_xfail_format "DWARF 1"
+ gdb_test "ptype E" "type = class E : public D \{$nl\[ \]*public:$nl\[ \]*int e;$nl\[ \]*int x;$nl.*\}" "ptype E"
+
+ setup_xfail_format "DWARF 1"
+ gdb_test "ptype class E" "type = class E : public D \{$nl\[ \]*public:$nl\[ \]*int e;$nl\[ \]*int x;$nl.*\}" "ptype class E"
+
+ setup_xfail_format "DWARF 1"
+ gdb_test "ptype g_E" "type = class E : public D \{$nl\[ \]*public:$nl\[ \]*int e;$nl\[ \]*int x;$nl.*\}" "ptype g_E"
+}
+
+#
+# Multiple inheritance, print complete classes.
+#
+
+proc test_print_mi_classes {} {
+ # Print all members of g_D.
+
+ setup_xfail_format "DWARF 1"
+ gdb_test "print g_D" ".* = \{\<B\> = \{\<A\> = \{a = 11, x = 12\}, b = 13, x = 14\}, \<C\> = \{\<A\> = \{a = 15, x = 16\}, c = 17, x = 18\}, d = 19, x = 20\}" "print g_D"
+
+ # Print all members of g_E.
+
+ setup_xfail_format "DWARF 1"
+ gdb_test "print g_E" ".* = \{\<D\> = \{\<B\> = \{\<A\> = \{a = 21, x = 22\}, b = 23, x = 24\}, \<C\> = \{\<A\> = \{a = 25, x = 26\}, c = 27, x = 28\}, d = 29, x = 30\}, e = 31, x = 32\}" "print g_E"
+}
+
+#
+# Single virtual inheritance, print individual members.
+#
+
+proc test_print_svi_members {} {
+ global gdb_prompt
+ global decimal
+ global nl
+
+ # Print all members of g_vA.
+
+ gdb_test "print g_vA.vA::va" ".* = 1" "print g_vA.vA::va"
+
+ gdb_test "print g_vA.vA::vx" ".* = 2" "print g_vA.vA::vx"
+
+ # Print members of g_vA using compact form.
+
+ gdb_test "print g_vA.va" ".* = 1" "print g_vA.va"
+
+ gdb_test "print g_vA.vx" ".* = 2" "print g_vA.vx"
+
+ # Print all members of g_vB.
+
+ setup_xfail_format "DWARF 1"
+ send_gdb "print g_vB.vA::va\n"
+ gdb_expect {
+ -re ".* = 3$nl$gdb_prompt $" { pass "print g_vB.vA::va" }
+ -re ".*virtual baseclass botch.*$gdb_prompt $" {
+ # Does not happen with gcc cygnus-2.4.5-930828
+ fail "print g_vB.vA::va (known bug with gcc cygnus-2.4.5-930417)"
+ # Many of the rest of these tests have the same problem.
+ return 0
+ }
+ -re ".*$gdb_prompt $" { fail "print g_vB.vA::va" }
+ timeout { fail "print g_vB.vA::va (timeout)" ; return }
+ }
+
+ setup_xfail_format "DWARF 1"
+ gdb_test "print g_vB.vA::vx" ".* = 4" "print g_vB.vA::vx"
+
+ gdb_test "print g_vB.vB::vb" ".* = 5" "print g_vB.vB::vb"
+
+ gdb_test "print g_vB.vB::vx" ".* = 6" "print g_vB.vB::vx"
+
+ # Print members of g_vB using compact form.
+
+ setup_xfail_format "DWARF 1"
+ gdb_test "print g_vB.va" ".* = 3" "print g_vB.va"
+
+ gdb_test "print g_vB.vb" ".* = 5" "print g_vB.vb"
+
+ gdb_test "print g_vB.vx" ".* = 6" "print g_vB.vx"
+
+ # Print all members of g_vC.
+
+ setup_xfail_format "DWARF 1"
+ gdb_test "print g_vC.vA::va" ".* = 7" "print g_vC.vA::va"
+
+ setup_xfail_format "DWARF 1"
+ gdb_test "print g_vC.vA::vx" ".* = 8" "print g_vC.vA::vx"
+
+ gdb_test "print g_vC.vC::vc" ".* = 9" "print g_vC.vC::vc"
+
+ gdb_test "print g_vC.vC::vx" ".* = 10" "print g_vC.vC::vx"
+
+ # Print members of g_vC using compact form.
+
+ setup_xfail_format "DWARF 1"
+ gdb_test "print g_vC.va" ".* = 7" "print g_vC.va"
+
+ gdb_test "print g_vC.vc" ".* = 9" "print g_vC.vc"
+
+ gdb_test "print g_vC.vx" ".* = 10" "print g_vC.vx"
+}
+
+#
+# Single virtual inheritance, print type definitions.
+#
+
+proc test_ptype_vi {} {
+ global gdb_prompt
+ global nl
+
+ # This class does not use any C++-specific features, so it's fine for
+ # it to print as "struct".
+ send_gdb "ptype vA\n"
+ gdb_expect {
+ -re "type = class vA \{$nl\[ \]*public:$nl\[ \]*int va;$nl\[ \]*int vx;$nl.*\}$nl$gdb_prompt $" {
+ pass "ptype vA"
+ }
+ -re "type = struct vA \{$nl\[ \]*int va;$nl\[ \]*int vx;$nl\}$nl$gdb_prompt $" {
+ pass "ptype vA"
+ }
+ -re ".*$gdb_prompt $" { fail "ptype vA" }
+ timeout { fail "ptype vA (timeout)" ; return }
+ }
+
+ # This class does not use any C++-specific features, so it's fine for
+ # it to print as "struct".
+ send_gdb "ptype class vA\n"
+ gdb_expect {
+ -re "type = class vA \{$nl\[ \]*public:$nl\[ \]*int va;$nl\[ \]*int vx;$nl.*\}$nl$gdb_prompt $" {
+ pass "ptype class vA"
+ }
+ -re "type = struct vA \{$nl\[ \]*int va;$nl\[ \]*int vx;$nl\}$nl$gdb_prompt $" {
+ pass "ptype class vA"
+ }
+ -re ".*$gdb_prompt $" { fail "ptype class vA" }
+ timeout { fail "ptype class vA (timeout)" ; return }
+ }
+
+ # This class does not use any C++-specific features, so it's fine for
+ # it to print as "struct".
+ send_gdb "ptype g_vA\n"
+ gdb_expect {
+ -re "type = class vA \{$nl\[ \]*public:$nl\[ \]*int va;$nl\[ \]*int vx;$nl.*\}$nl$gdb_prompt $" {
+ pass "ptype g_vA"
+ }
+ -re "type = struct vA \{$nl\[ \]*int va;$nl\[ \]*int vx;$nl\}$nl$gdb_prompt $" {
+ pass "ptype g_vA"
+ }
+ -re ".*$gdb_prompt $" { fail "ptype g_vA" }
+ timeout { fail "ptype g_vA (timeout)" ; return }
+ }
+
+ setup_xfail_format "DWARF 1"
+ gdb_test "ptype vB" "ptype vB\[\r\n\]+type = class vB : public virtual vA \{$nl private:$nl\[ \]+vA \[*\]+_vb\[\\\$\.\]+vA;$nl public:$nl\[ \]+int vb;$nl\[ \]+int vx;$nl.*\}" "ptype vB"
+
+ setup_xfail_format "DWARF 1"
+ gdb_test "ptype class vB" "type = class vB : public virtual vA \{$nl\[ \]*private:$nl\[ \]*vA \[*\]+_vb\[\\\$\.\]vA;$nl\[ \]*public:$nl\[ \]*int vb;$nl\[ \]*int vx;$nl.*\}" "ptype class vB"
+
+ setup_xfail_format "DWARF 1"
+ gdb_test "ptype g_vB" "type = class vB : public virtual vA \{$nl\[ \]*private:$nl\[ \]*vA \[*\]+_vb\[\\\$\.\]vA;$nl\[ \]*public:$nl\[ \]*int vb;$nl\[ \]*int vx;$nl.*\}" "ptype g_vB"
+
+ setup_xfail_format "DWARF 1"
+ gdb_test "ptype vC" "type = class vC : public virtual vA \{$nl\[ \]*private:$nl\[ \]*vA \[*\]+_vb\[\\\$\.\]vA;$nl\[ \]*public:$nl\[ \]*int vc;$nl\[ \]*int vx;$nl.*\}" "ptype vC"
+
+ setup_xfail_format "DWARF 1"
+ gdb_test "ptype class vC" "type = class vC : public virtual vA \{$nl\[ \]*private:$nl\[ \]*vA \[*\]+_vb\[\\\$\.\]vA;$nl\[ \]*public:$nl\[ \]*int vc;$nl\[ \]*int vx;$nl.*\}" "ptype class vC"
+
+ setup_xfail_format "DWARF 1"
+ gdb_test "ptype g_vC" "type = class vC : public virtual vA \{$nl\[ \]*private:$nl\[ \]*vA \[*\]+_vb\[\\\$\.\]vA;$nl\[ \]*public:$nl\[ \]*int vc;$nl\[ \]*int vx;$nl.*\}" "ptype g_vC"
+}
+
+#
+# Single virtual inheritance, print complete classes.
+#
+
+proc test_print_svi_classes {} {
+ global gdb_prompt
+ global hex
+ global decimal
+ global nl
+
+ # Print all members of g_vA.
+
+ gdb_test "print g_vA" ".* = \{va = 1, vx = 2\}" "print g_vA"
+
+ # Print all members of g_vB.
+
+ setup_xfail_format "DWARF 1"
+ send_gdb "print g_vB\n"
+ gdb_expect {
+ -re ".* = \{\<vA\> = \{va = 3, vx = 4\}, _vb\[\\\$\.\]vA = $hex, vb = 5, vx = 6\}$nl$gdb_prompt $" {
+ pass "print g_vB"
+ }
+ -re ".*invalid address 0x0.*$gdb_prompt $" {
+ # Does not happen with gcc cygnus-2.4.5-930828
+ fail "print g_vB (known bug with gcc cygnus-2.4.5-930417)"
+ # Many of the rest of these tests have the same problem.
+ return 0
+ }
+ -re ".*$gdb_prompt $" { fail "print g_vB" }
+ timeout { fail "print g_vB (timeout)" ; return }
+ }
+
+ # Print all members of g_vC.
+
+ setup_xfail_format "DWARF 1"
+ gdb_test "print g_vC" ".* = \{\<vA\> = \{va = 7, vx = 8\}, _vb\[\\\$\.\]vA = $hex, vc = 9, vx = 10\}" "print g_vC"
+}
+
+#
+# Multiple virtual inheritance, print individual members.
+#
+
+proc test_print_mvi_members {} {
+ global gdb_prompt
+ global decimal
+ global nl
+
+ # Print all members of g_vD.
+
+ setup_xfail_format "DWARF 1"
+ send_gdb "print g_vD.vA::va\n"
+ gdb_expect {
+ -re ".* = 19$nl$gdb_prompt $" { pass "print g_vD.vA::va" }
+ -re ".*virtual baseclass botch.*$gdb_prompt $" {
+ # Does not happen with gcc cygnus-2.4.5-930828
+ fail "print g_vD.vA::va (known bug with gcc cygnus-2.4.5-930417)"
+ # Many of the rest of these tests have the same problem.
+ return 0
+ }
+ -re ".*$gdb_prompt $" { fail "print g_vD.vA::va" }
+ timeout { fail "print g_vD.vA::va (timeout)" ; return }
+ }
+
+ setup_xfail_format "DWARF 1"
+ gdb_test "print g_vD.vA::vx" ".* = 20" "print g_vD.vA::vx"
+
+ setup_xfail_format "DWARF 1"
+ gdb_test "print g_vD.vB::vb" ".* = 21" "print g_vD.vB::vb"
+
+ setup_xfail_format "DWARF 1"
+ gdb_test "print g_vD.vB::vx" ".* = 22" "print g_vD.vB::vx"
+
+ setup_xfail_format "DWARF 1"
+ gdb_test "print g_vD.vC::vc" ".* = 23" "print g_vD.vC::vc"
+
+ setup_xfail_format "DWARF 1"
+ gdb_test "print g_vD.vC::vx" ".* = 24" "print g_vD.vC::vx"
+
+ gdb_test "print g_vD.vD::vd" ".* = 25" "print g_vD.vD::vd"
+
+ gdb_test "print g_vD.vD::vx" ".* = 26" "print g_vD.vD::vx"
+
+ # Print all members of g_vE.
+
+ setup_xfail_format "DWARF 1"
+ gdb_test "print g_vE.vA::va" ".* = 0" "print g_vE.vA::va"
+
+ setup_xfail_format "DWARF 1"
+ gdb_test "print g_vE.vA::vx" ".* = 0" "print g_vE.vA::vx"
+
+ setup_xfail_format "DWARF 1"
+ gdb_test "print g_vE.vB::vb" ".* = 0" "print g_vE.vB::vb"
+
+ setup_xfail_format "DWARF 1"
+ gdb_test "print g_vE.vB::vx" ".* = 0" "print g_vE.vB::vx"
+
+ setup_xfail_format "DWARF 1"
+ gdb_test "print g_vE.vC::vc" ".* = 0" "print g_vE.vC::vc"
+
+ setup_xfail_format "DWARF 1"
+ gdb_test "print g_vE.vC::vx" ".* = 0" "print g_vE.vC::vx"
+
+ setup_xfail_format "DWARF 1"
+ gdb_test "print g_vE.vD::vd" ".* = 0" "print g_vE.vD::vd"
+
+ gdb_test "print g_vE.vD::vx" ".* = 0" "print g_vE.vD::vx"
+
+ gdb_test "print g_vE.vE::ve" ".* = 27" "print g_vE.vE::ve"
+
+ gdb_test "print g_vE.vE::vx" ".* = 28" "print g_vE.vE::vx"
+}
+
+#
+# Multiple virtual inheritance, print type definitions.
+#
+
+proc test_ptype_mvi {} {
+ global nl
+
+ setup_xfail_format "DWARF 1"
+ gdb_test "ptype vD" "type = class vD : public virtual vB, public virtual vC \{$nl\[ \]*private:$nl\[ \]*vC \[*\]+_vb\[\\\$\.\]vC;$nl\[ \]*vB \[*\]+_vb\[\\\$\.\]vB;$nl\[ \]*public:$nl\[ \]*int vd;$nl\[ \]*int vx;$nl.*\}" "ptype vD"
+
+ setup_xfail_format "DWARF 1"
+ gdb_test "ptype class vD" "type = class vD : public virtual vB, public virtual vC \{$nl\[ \]*private:$nl\[ \]*vC \[*\]+_vb\[\\\$\.\]vC;$nl\[ \]*vB \[*\]+_vb\[\\\$\.\]vB;$nl\[ \]*public:$nl\[ \]*int vd;$nl\[ \]*int vx;$nl.*\}" "ptype class vD"
+
+ setup_xfail_format "DWARF 1"
+ gdb_test "ptype g_vD" "type = class vD : public virtual vB, public virtual vC \{$nl\[ \]*private:$nl\[ \]*vC \[*\]+_vb\[\\\$\.\]vC;$nl\[ \]*vB \[*\]+_vb\[\\\$\.\]vB;$nl\[ \]*public:$nl\[ \]*int vd;$nl\[ \]*int vx;$nl.*\}" "ptype g_vD"
+
+ setup_xfail_format "DWARF 1"
+ gdb_test "ptype vE" "type = class vE : public virtual vD \{$nl\[ \]*private:$nl\[ \]*vD \[*\]+_vb\[\\\$\.\]vD;$nl\[ \]*public:$nl\[ \]*int ve;$nl\[ \]*int vx;$nl.*\}" "ptype vE"
+
+ setup_xfail_format "DWARF 1"
+ gdb_test "ptype class vE" "type = class vE : public virtual vD \{$nl\[ \]*private:$nl\[ \]*vD \[*\]+_vb\[\\\$\.\]vD;$nl\[ \]*public:$nl\[ \]*int ve;$nl\[ \]*int vx;$nl.*\}" "ptype class vE"
+
+ setup_xfail_format "DWARF 1"
+ gdb_test "ptype g_vE" "type = class vE : public virtual vD \{$nl\[ \]*private:$nl\[ \]*vD \[*\]+_vb\[\\\$\.\]vD;$nl\[ \]*public:$nl\[ \]*int ve;$nl\[ \]*int vx;$nl.*\}" "ptype g_vE"
+}
+
+#
+# Multiple virtual inheritance, print complete classes.
+#
+
+proc test_print_mvi_classes {} {
+ global gdb_prompt
+ global hex
+ global decimal
+ global nl
+
+ # Print all members of g_vD.
+
+ setup_xfail_format "DWARF 1"
+ send_gdb "print g_vD\n"
+ gdb_expect {
+ -re ".* = \{\<vB\> = \{\<vA\> = \{va = 19, vx = 20\}, _vb\[\\\$\.\]vA = $hex, vb = 21, vx = 22\}, \<vC\> = \{_vb\[\\\$\.\]vA = $hex, vc = 23, vx = 24\}, _vb\[\\\$\.\]vC = $hex, _vb\[\\\$\.\]vB = $hex, vd = 25, vx = 26\}$nl$gdb_prompt $" {
+ pass "print g_vD"
+ }
+ -re ".*invalid address 0x0.*$gdb_prompt $" {
+ # Does not happen with gcc cygnus-2.4.5-930828
+ fail "print g_vD (known bug with gcc cygnus-2.4.5-930417)"
+ # Many of the rest of these tests have the same problem.
+ return 0
+ }
+ -re ".*$gdb_prompt $" { fail "print g_vD" }
+ timeout { fail "print g_vD (timeout)" ; return }
+ }
+
+ # Print all members of g_vE.
+
+ setup_xfail_format "DWARF 1"
+ gdb_test "print g_vE" ".* = \{\<vD\> = \{\<vB\> = \{\<vA\> = \{va = 0, vx = 0\}, _vb\[\\\$\.\]vA = $hex, vb = 0, vx = 0\}, \<vC\> = \{_vb\[\\\$\.\]vA = $hex, vc = 0, vx = 0\}, _vb\[\\\$\.\]vC = $hex, _vb\[\\\$\.\]vB = $hex, vd = 0, vx = 0\}, _vb\[\\\$\.\]vD = $hex, ve = 27, vx = 28\}" "print g_vE"
+}
+
+proc do_tests {} {
+ global prms_id
+ global bug_id
+ global subdir
+ global objdir
+ global srcdir
+ global binfile
+
+ set prms_id 0
+ set bug_id 0
+
+ # Start with a fresh gdb.
+
+ gdb_exit
+ gdb_start
+ gdb_reinitialize_dir $srcdir/$subdir
+ gdb_load $binfile
+
+ gdb_test "set language c++" ""
+ gdb_test "set width 0" ""
+
+ # Get the debug format for the compiled test case.
+
+ if { ![ runto_main] } {
+ gdb_suppress_tests;
+ } else {
+ get_debug_format
+ }
+
+ test_ptype_si
+ test_ptype_mi
+ test_ptype_vi
+ test_ptype_mvi
+
+ gdb_stop_suppressing_tests;
+
+ if { ![ runto 'inheritance2(void)' ] } {
+ gdb_suppress_tests;
+ }
+
+ test_print_si_members
+ test_print_si_classes
+ test_print_mi_members
+ test_print_mi_classes
+ test_print_anon_union
+
+ gdb_stop_suppressing_tests;
+
+ if { ![ runto 'inheritance4(void)' ] } {
+ gdb_suppress_tests;
+ }
+
+ test_print_svi_members
+ test_print_svi_classes
+ test_print_mvi_members
+ test_print_mvi_classes
+}
+
+do_tests
diff --git a/gdb/testsuite/gdb.c++/local.cc b/gdb/testsuite/gdb.c++/local.cc
new file mode 100644
index 00000000000..c811debdf97
--- /dev/null
+++ b/gdb/testsuite/gdb.c++/local.cc
@@ -0,0 +1,67 @@
+// Tests for local types
+
+void marker1 (void)
+{
+}
+
+
+int foobar (int x)
+{
+ class Local {
+ public:
+ int loc1;
+ char loc_foo (char c)
+ {
+ return c + 3;
+ }
+ };
+
+ Local l;
+ static Local l1;
+ char c;
+
+ l.loc1 = 23;
+
+ c = l.loc_foo('x');
+ return c + 2;
+}
+
+int main()
+{
+ int c;
+
+ c = foobar (31);
+
+ { // inner block
+ class InnerLocal {
+ public:
+ char ilc;
+ int * ip;
+ int il_foo (unsigned const char & uccr)
+ {
+ return uccr + 333;
+ }
+ class NestedInnerLocal {
+ public:
+ int nil;
+ int nil_foo (int i)
+ {
+ return i * 27;
+ }
+ };
+ NestedInnerLocal nest1;
+ };
+
+ InnerLocal il;
+
+ il.ilc = 'b';
+ il.ip = &c;
+ }
+ marker1();
+}
+
+
+
+
+
+
diff --git a/gdb/testsuite/gdb.c++/local.exp b/gdb/testsuite/gdb.c++/local.exp
new file mode 100644
index 00000000000..0aa84683d80
--- /dev/null
+++ b/gdb/testsuite/gdb.c++/local.exp
@@ -0,0 +1,110 @@
+# Copyright (C) 1998 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# tests for local variables
+# Written by Satish Pai <pai@apollo.hp.com> 1997-07-08
+
+
+# This file is part of the gdb testsuite
+
+if $tracelevel then {
+ strace $tracelevel
+ }
+
+#
+# test running programs
+#
+set prms_id 0
+set bug_id 0
+
+set testfile "local"
+set srcfile ${testfile}.cc
+set binfile ${objdir}/${subdir}/${testfile}
+
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug c++}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+
+#
+# set it up at a breakpoint so we can play with the variable values
+#
+if ![runto_main] then {
+ perror "couldn't run to breakpoint"
+ continue
+}
+
+send_gdb "break marker1\n" ; gdb_expect -re ".*$gdb_prompt $"
+
+ send_gdb "cont\n"
+ gdb_expect {
+ -re "Break.* marker1 \\(\\) at .*:$decimal.*$gdb_prompt $" {
+ send_gdb "up\n"
+ gdb_expect {
+ -re ".*$gdb_prompt $" {}
+ timeout { fail "up from marker1" }
+ }
+ }
+ -re "$gdb_prompt $" { fail "continue to marker1" }
+ timeout { fail "(timeout) continue to marker1" }
+ }
+
+send_gdb "ptype Local\n"
+gdb_expect {
+ -re "type = class Local \{\r\n\[\t \]*public:\r\n\[\t \]*int loc1;\r\n\r\n\[\t \]*.char loc_foo\\(char\\);\r\n\[\t \]*\}\[\t \]*\\(Local at.*local\\.C:10\\).*$gdb_prompt $" { pass "ptype Local" }
+ -re "type = class Local \{\r\n\[\t \]*public:\r\n\[\t \]*int loc1;\r\n\r\n\[\t \]*.char loc_foo\\(char\\);\r\n\[\t \]*\}\[\t \]*\\(Local at.*local\\.C:\[0-9\]*\\).*$gdb_prompt $" { pass "ptype Local (incorrect line number?)" }
+ -re ".*$gdb_prompt $" { fail "ptype Local" }
+ timeout { fail "(timeout) ptype Local" }
+}
+
+send_gdb "ptype InnerLocal\n"
+gdb_expect {
+ -re "type = class InnerLocal \{\r\n\[\t \]*public:\r\n\[\t \]*char ilc;\r\n\[\t \]*int \\*ip;\r\n\[\t \]*InnerLocal::NestedInnerLocal nest1;\r\n\r\n\[\t \]*.int il_foo\\(const unsigned char &\\);\r\n\[\t \]*\}\[\t \]*\\(Local at.*local\\.C:36\\).*$gdb_prompt $" { pass "ptype InnerLocal" }
+ -re "type = class InnerLocal \{\r\n\[\t \]*public:\r\n\[\t \]*char ilc;\r\n\[\t \]*int \\*ip;\r\n\[\t \]*class InnerLocal::NestedInnerLocal nest1;\r\n\r\n\[\t \]*.int il_foo\\(const unsigned char &\\);\r\n\[\t \]*\}\[\t \]*\\(Local at.*local\\.C:36\\).*$gdb_prompt $" { pass "ptype InnerLocal" }
+ -re "type = class InnerLocal \{\r\n\[\t \]*public:\r\n\[\t \]*char ilc;\r\n\[\t \]*int \\*ip;\r\n\[\t \]*InnerLocal::NestedInnerLocal nest1;\r\n\r\n\[\t \]*.int il_foo\\(const unsigned char &\\);\r\n\[\t \]*\}\[\t \]*\\(Local at.*local\\.C:\[0-9\]*\\).*$gdb_prompt $" { pass "ptype InnerLocal (incorrect line number?" }
+ -re "type = class InnerLocal \{\r\n\[\t \]*public:\r\n\[\t \]*char ilc;\r\n\[\t \]*int \\*ip;\r\n\[\t \]*class InnerLocal::NestedInnerLocal nest1;\r\n\r\n\[\t \]*.int il_foo\\(const unsigned char &\\);\r\n\[\t \]*\}\[\t \]*\\(Local at.*local\\.C:\[0-9\]*\\).*$gdb_prompt $" { pass "ptype InnerLocal (incorrect line number?" }
+ -re ".*$gdb_prompt $" { fail "ptype InnerLocal" }
+ timeout { fail "(timeout) ptype InnerLocal" }
+}
+
+
+send_gdb "ptype NestedInnerLocal\n"
+gdb_expect {
+ -re "type = class InnerLocal::NestedInnerLocal \{\r\n\[\t \]*public:\r\n\[\t \]*int nil;\r\n\r\n\[\t \]*.int nil_foo\\(int\\);\r\n\[\t \]*\}\[\t \]*\\(Local at.*local\\.C:44\\).*$gdb_prompt $" { pass "ptype NestedInnerLocal" }
+ -re "type = class InnerLocal::NestedInnerLocal \{\r\n\[\t \]*public:\r\n\[\t \]*int nil;\r\n\r\n\[\t \]*.int nil_foo\\(int\\);\r\n\[\t \]*\}\[\t \]*\\(Local at.*local\\.C:\[0-9\]*\\).*$gdb_prompt $" { pass "ptype NestedInnerLocal (incorrect line number?)" }
+ -re "No symbol.*in current context.*$gdb_prompt $" { pass "ptype NestedInnerLocal (known aCC limitation)" }
+ -re ".*$gdb_prompt $" { fail "ptype NestedInnerLocal" }
+ timeout { fail "(timeout) ptype NestedInnerLocal" }
+}
+
+send_gdb "ptype InnerLocal::NestedInnerLocal\n"
+gdb_expect {
+ -re "type = class InnerLocal::NestedInnerLocal \{\r\n\[\t \]*public:\r\n\[\t \]*int nil;\r\n\r\n\[\t \]*.int nil_foo\\(int\\);\r\n\[\t \]*\}\[\t \]*\\(Local at.*local\\.C:44\\).*$gdb_prompt $" { pass "ptype InnerLocal::NestedInnerLocal" }
+ -re "type = class InnerLocal::NestedInnerLocal \{\r\n\[\t \]*public:\r\n\[\t \]*int nil;\r\n\r\n\[\t \]*.int nil_foo\\(int\\);\r\n\[\t \]*\}\[\t \]*\\(Local at.*local\\.C:\[0-9\]*\\).*$gdb_prompt $" { pass "ptype InnerLocal::NestedInnerLocal (incorrect line number?)" }
+ -re ".*$gdb_prompt $" { fail "ptype InnerLocal::NestedInnerLocal" }
+ timeout { fail "(timeout) ptype InnerLocal::NestedInnerLocal" }
+}
+
+
diff --git a/gdb/testsuite/gdb.c++/member-ptr.cc b/gdb/testsuite/gdb.c++/member-ptr.cc
new file mode 100644
index 00000000000..4beb92616d4
--- /dev/null
+++ b/gdb/testsuite/gdb.c++/member-ptr.cc
@@ -0,0 +1,106 @@
+extern "C" {
+#include <stdio.h>
+}
+
+
+class A {
+public:
+ A();
+ int foo (int x);
+ int bar (int y);
+ virtual int baz (int z);
+ char c;
+ int j;
+ int jj;
+ static int s;
+};
+
+class B {
+public:
+ static int s;
+};
+
+int A::s = 10;
+int B::s = 20;
+
+A::A()
+{
+ c = 'x';
+ j = 5;
+}
+
+int A::foo (int dummy)
+{
+ j += 3;
+ return j + dummy;
+}
+
+int A::bar (int dummy)
+{
+ int r;
+ j += 13;
+ r = this->foo(15);
+ return r + j + 2 * dummy;
+}
+
+int A::baz (int dummy)
+{
+ int r;
+ j += 15;
+ r = this->foo(15);
+ return r + j + 12 * dummy;
+}
+
+int fum (int dummy)
+{
+ return 2 + 13 * dummy;
+}
+
+typedef int (A::*PMF)(int);
+
+typedef int A::*PMI;
+
+int main ()
+{
+ A a;
+ A * a_p;
+ PMF pmf;
+
+ PMF * pmf_p;
+ PMI pmi;
+
+ a.j = 121;
+ a.jj = 1331;
+
+ int k;
+
+ a_p = &a;
+
+ pmi = &A::j;
+ pmf = &A::bar;
+ pmf_p = &pmf;
+
+ pmi = NULL;
+
+ k = (a.*pmf)(3);
+
+ pmi = &A::jj;
+ pmf = &A::foo;
+ pmf_p = &pmf;
+
+ k = (a.*pmf)(4);
+
+ k = (a.**pmf_p)(5);
+
+ k = a.*pmi;
+
+
+ k = a.bar(2);
+
+ k += fum (4);
+
+ B b;
+
+ k += b.s;
+
+}
diff --git a/gdb/testsuite/gdb.c++/member-ptr.exp b/gdb/testsuite/gdb.c++/member-ptr.exp
new file mode 100644
index 00000000000..7b4dd7c1bf1
--- /dev/null
+++ b/gdb/testsuite/gdb.c++/member-ptr.exp
@@ -0,0 +1,510 @@
+# Copyright (C) 1998 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+# Tests for pointer-to-member support
+# Written by Satish Pai <pai@apollo.hp.com> 1997-08-19
+
+# This file is part of the gdb testsuite
+
+
+if $tracelevel then {
+ strace $tracelevel
+ }
+
+#
+# test running programs
+#
+
+# Start with a fresh gdb
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+
+set prms_id 0
+set bug_id 0
+
+set testfile "member-ptr"
+set srcfile ${testfile}.cc
+set binfile ${objdir}/${subdir}/${testfile}
+
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug c++}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+
+if ![runto_main] then {
+ perror "couldn't run to breakpoint"
+ continue
+}
+
+send_gdb "break 83\n"
+gdb_expect {
+ -re "Breakpoint \[0-9\]*.*line 83\\.\r\n$gdb_prompt $" {
+ pass "set break at 83"
+ }
+ -re ".*$gdb_prompt $" { fail "set break at 83" }
+ timeout { fail "(timeout) set break at 83" }
+}
+
+send_gdb "continue\n"
+gdb_expect {
+ -re "Continuing\\.\r\n\r\nBreakpoint.*at.*member-ptr\\.cc:83\r\n83\[ \t]*pmi = NULL;\r\n$gdb_prompt $" {
+ pass "continue to 83"
+ }
+ -re ".*$gdb_prompt $" { fail "continue to 83" }
+ timeout { fail "(timeout) continue to 83" }
+}
+
+# ptype on pointer to data member
+
+send_gdb "ptype pmi\n"
+gdb_expect {
+ -re "type = int \\( A::\\*\\)\r\n$gdb_prompt $" {
+ pass "ptype pmi"
+ }
+ -re ".*$gdb_prompt $" { fail "ptype pmi" }
+ timeout { fail "(timeout) ptype pmi" }
+}
+
+# print pointer to data member
+
+send_gdb "print pmi\n"
+gdb_expect {
+ -re "\\$\[0-9\]* = \\(int \\( A::\\*\\)\\) &A::j\r\n$gdb_prompt $" {
+ pass "print pmi"
+ }
+ -re ".*$gdb_prompt $" { fail "print pmi" }
+ timeout { fail "(timeout) print pmi" }
+}
+
+
+# print dereferenced pointer to data member
+
+send_gdb "print a.*pmi\n"
+gdb_expect {
+ -re "\\$\[0-9\]* = 121\r\n$gdb_prompt $" {
+ pass "print a.*pmi"
+ }
+ -re ".*$gdb_prompt $" { fail "print a.*pmi" }
+ timeout { fail "(timeout) print a.*pmi" }
+}
+
+# print dereferenced pointer to data member
+# this time, dereferenced through a pointer
+
+send_gdb "print a_p->*pmi\n"
+gdb_expect {
+ -re "\\$\[0-9\]* = 121\r\n$gdb_prompt $" {
+ pass "print a->*pmi"
+ }
+ -re ".*$gdb_prompt $" { fail "print a->*pmi" }
+ timeout { fail "(timeout) print a->*pmi" }
+}
+
+
+# set the pointer to data member
+
+send_gdb "set var pmi = &A::jj\n"
+gdb_expect {
+ -re "$gdb_prompt $" {
+ pass "set var (not really a pass)"
+ }
+ timeout { fail "(timeout) " }
+}
+
+# Now print the pointer again
+
+send_gdb "print pmi\n"
+gdb_expect {
+ -re "\\$\[0-9\]* = \\(int \\( A::\\*\\)\\) &A::jj\r\n$gdb_prompt $" {
+ pass "print pmi after setting"
+ }
+ -re ".*$gdb_prompt $" { fail "print pmi after setting" }
+ timeout { fail "(timeout) print pmi after setting" }
+}
+
+# print dereferenced pointer to data member again
+
+send_gdb "print a.*pmi\n"
+gdb_expect {
+ -re "\\$\[0-9\]* = 1331\r\n$gdb_prompt $" {
+ pass "print a.*pmi after setting"
+ }
+ -re ".*$gdb_prompt $" { fail "print a.*pmi after setting" }
+ timeout { fail "(timeout) print a.*pmi after setting" }
+}
+
+# set the pointer to data member back to A::j
+
+send_gdb "set var pmi = &A::j\n"
+gdb_expect {
+ -re "$gdb_prompt $" {
+ pass "set var back to A::j (not really a pass)"
+ }
+ timeout { fail "(timeout) set var pmi" }
+}
+
+# print dereferenced pointer to data member yet again (extra check, why not)
+
+send_gdb "print a.*pmi\n"
+gdb_expect {
+ -re "\\$\[0-9\]* = 121\r\n$gdb_prompt $" {
+ pass "print a.*pmi after resetting"
+ }
+ -re ".*$gdb_prompt $" { fail "print a.*pmi after resetting" }
+ timeout { fail "(timeout) print a.*pmi after resetting" }
+}
+
+# Set the data member pointed to.
+
+send_gdb "print a.*pmi = 33\n"
+gdb_expect {
+ -re "\\$\[0-9\]* = 33\r\n$gdb_prompt $" {
+ pass "print command to set"
+ }
+ -re ".*$gdb_prompt $" { fail "print command to set" }
+ timeout { fail "(timeout) print command to set" }
+}
+
+# Now check that the data really was changed
+send_gdb "print a.*pmi\n"
+gdb_expect {
+ -re "\\$\[0-9\]* = 33\r\n$gdb_prompt $" {
+ pass "print a.*pmi after setting member pointed to"
+ }
+ -re ".*$gdb_prompt $" { fail "print a.*pmi after setting member pointed to" }
+ timeout { fail "(timeout) print a.*pmi after setting member pointed to" }
+}
+
+# Double-check by printing a.
+send_gdb "print a\n"
+gdb_expect {
+ -re "\\$\[0-9\]* = \{c = 120 'x', j = 33, jj = 1331, static s = 10, Virtual table at $hex\}\r\n$gdb_prompt $" {
+ pass "print a after setting member pointed to by pmi"
+ }
+ -re ".*$gdb_prompt $" { fail "print a after setting member pointed to by pmi" }
+ timeout { fail "(timeout) print a after setting member pointed to by pmi" }
+}
+
+
+# Set the data member pointed to, using ->*
+
+send_gdb "print a_p->*pmi = 44\n"
+gdb_expect {
+ -re "\\$\[0-9\]* = 44\r\n$gdb_prompt $" {
+ pass "print command to set (->)"
+ }
+ -re ".*$gdb_prompt $" { fail "print command to set (->)" }
+ timeout { fail "(timeout) print command to set (->)" }
+}
+
+# Now check that the data really was changed
+send_gdb "print a_p->*pmi\n"
+gdb_expect {
+ -re "\\$\[0-9\]* = 44\r\n$gdb_prompt $" {
+ pass "print a_p->*pmi after setting member pointed to"
+ }
+ -re ".*$gdb_prompt $" { fail "print a_p->*pmi after setting member pointed to" }
+ timeout { fail "(timeout) print a_p->*pmi after setting member pointed to" }
+}
+
+# Double-check by printing a.
+send_gdb "print a\n"
+gdb_expect {
+ -re "\\$\[0-9\]* = \{c = 120 'x', j = 44, jj = 1331, static s = 10, Virtual table at $hex\}\r\n$gdb_prompt $" {
+ pass "print a after setting member pointed to by pmi (->) "
+ }
+ -re ".*$gdb_prompt $" { fail "print a after setting member pointed to by pmi (->) " }
+ timeout { fail "(timeout) print a after setting member pointed to by pmi (->) " }
+}
+
+
+# Do a ptype on the dereferenced pointer to member
+# pai/1997-08-20 Doesn't work
+
+# send_gdb "ptype a.*pmi\n"
+# gdb_expect {
+# -re "type = int\r\n$gdb_prompt $" {
+# pass "ptype a.*pmi"
+# }
+# -re ".*$gdb_prompt $" { fail "ptype a.*pmi" }
+# timeout { fail "(timeout) ptype a.*pmi" }
+#}
+
+# Try to dereference the pointer to data member without any object
+
+send_gdb "print *pmi\n"
+gdb_expect {
+ -re "Attempt to dereference pointer to member without an object\r\n$gdb_prompt $" {
+ pass "attempt to print ptr to member without object"
+ }
+ -re ".*$gdb_prompt $" { fail "attempt to print ptr to member without object" }
+ timeout { fail "(timeout) attempt to print ptr to member without object" }
+}
+
+# Try to ptype a dereference of the pointer to data member without any object
+
+send_gdb "ptype *pmi\n"
+gdb_expect {
+ -re "Attempt to dereference pointer to member without an object\r\n$gdb_prompt $" {
+ pass "attempt to ptype ptr to member without object"
+ }
+ -re ".*$gdb_prompt $" { fail "attempt to ptype ptr to member without object" }
+ timeout { fail "(timeout) attempt to ptype ptr to member without object" }
+}
+
+# Ptype a pointer to a method.
+
+send_gdb "ptype pmf\n"
+gdb_expect {
+ -re "type = int \\( A::\\*\\)\\(\\.\\.\\.\\)\r\n$gdb_prompt $" {
+ pass "ptype pmf"
+ }
+ -re ".*$gdb_prompt $" { fail "ptype pmf" }
+ timeout { fail "(timeout) ptype pmf" }
+}
+
+# print a pointer to a method
+
+send_gdb "print pmf\n"
+gdb_expect {
+ -re "\\$\[0-9\]* = \\(int \\( A::\\*\\)\\(\\.\\.\\.\\)\\) \\?\\? <not supported with HP aCC>\r\n$gdb_prompt $" {
+ pass "print pmf"
+ }
+ -re ".*$gdb_prompt $" { fail "print pmf" }
+ timeout { fail "(timeout) print pmf" }
+}
+
+
+# Ptype a pointer to a pointer to a method
+
+send_gdb "ptype pmf_p\n"
+gdb_expect {
+ -re "type = int \\( A::\\*\\*\\)\\(\\.\\.\\.\\)\r\n$gdb_prompt $" {
+ pass "ptype pmf_p"
+ }
+ -re ".*$gdb_prompt $" { fail "ptype pmf_p" }
+ timeout { fail "(timeout) ptype pmf_p" }
+}
+
+# print a pointer to a pointer to a method
+
+send_gdb "print pmf_p\n"
+gdb_expect {
+ -re "\\$\[0-9\]* = \\(int \\( A::\\*\\*\\)\\(\\.\\.\\.\\)\\) $hex\r\n$gdb_prompt $" {
+ pass "print pmf_p"
+ }
+ -re ".*$gdb_prompt $" { fail "print pmf_p" }
+ timeout { fail "(timeout) print pmf_p" }
+}
+
+# print dereferenced pointer to method
+
+send_gdb "print a.*pmf\n"
+gdb_expect {
+ -re "Pointers to methods not supported with HP aCC\r\n$gdb_prompt $" {
+ pass "print a.*pmf (known aCC limitation)"
+ }
+ -re ".*$gdb_prompt $" { fail "print a.*pmf -- ??" }
+ timeout { fail "(timeout) print a.*pmf" }
+}
+
+# print dereferenced pointer to method, using ->*
+
+send_gdb "print a_p->*pmf\n"
+gdb_expect {
+ -re "Pointers to methods not supported with HP aCC\r\n$gdb_prompt $" {
+ pass "print a_p->*pmf (known aCC limitation)"
+ }
+ -re ".*$gdb_prompt $" { fail "print a_p->*pmf -- ??" }
+ timeout { fail "(timeout) print a_p->*pmf" }
+}
+
+# set the pointer to data member
+
+send_gdb "set var pmf = &A::foo\n"
+gdb_expect {
+ -re "Assignment to pointers to methods not implemented with HP aCC\r\n$gdb_prompt $" {
+ pass "set var pmf (known aCC limitation)"
+ }
+ -re ".*$gdb_prompt $" { fail "set var pmf -- ??" }
+ timeout { fail "(timeout) set var pmf" }
+}
+
+# Try to dereference the pointer to method without any object
+
+send_gdb "print *pmf\n"
+gdb_expect {
+ -re "Attempt to dereference pointer to member without an object\r\n$gdb_prompt $" {
+ pass "attempt to print ptr to method without object"
+ }
+ -re ".*$gdb_prompt $" { fail "attempt to print ptr to method without object" }
+ timeout { fail "(timeout) attempt to print ptr to method without object" }
+}
+
+# Try to ptype a dereference of the pointer to method without any object
+
+send_gdb "ptype *pmi\n"
+gdb_expect {
+ -re "Attempt to dereference pointer to member without an object\r\n$gdb_prompt $" {
+ pass "attempt to ptype ptr to member without object"
+ }
+ -re ".*$gdb_prompt $" { fail "attempt to ptype ptr to member without object" }
+ timeout { fail "(timeout) attempt to ptype ptr to member without object" }
+}
+
+# Check cast of pointer to member to integer
+send_gdb "print (int) pmi\n"
+gdb_expect {
+ -re "\\$\[0-9\]* = 8\r\n$gdb_prompt $" {
+ pass "casting pmi to int"
+ }
+ -re ".*$gdb_prompt $" { fail "casting pmi to int" }
+ timeout { fail "(timeout) casting pmi to int" }
+}
+
+# Check cast of pointer to method to integer
+send_gdb "print (int) pmf\n"
+gdb_expect {
+ -re "Pointers to methods not supported with HP aCC\r\n$gdb_prompt $" {
+ pass "casting pmf to int (known aCC limitation)"
+ }
+ -re ".*$gdb_prompt $" { fail "casting pmf to int -- ??" }
+ timeout { fail "(timeout) casting pmf to int" }
+}
+
+# Try to invoke a function through a pointer to data member
+send_gdb "print (a.*pmi)(3)\n"
+gdb_expect {
+ -re "Not implemented: function invocation through pointer to method with HP aCC\r\n$gdb_prompt $" {
+ pass "print (a.*pmi)(3) -- error message should be different"
+ }
+ -re ".*$gdb_prompt $" { fail "print (a.*pmi)(3) -- ???" }
+ timeout { fail "(timeout) print (a.*pmi)(3)" }
+}
+
+# Try to invoke a function through a pointer to a method
+send_gdb "print (a.*pmf)(3)\n"
+gdb_expect {
+ -re "Not implemented: function invocation through pointer to method with HP aCC\r\n$gdb_prompt $" {
+ pass "print (a.*pmi)(3) -- known aCC limitation"
+ }
+ -re ".*$gdb_prompt $" { fail "print (a.*pmf)(3) -- ???" }
+ timeout { fail "(timeout) print (a.*pmf)(3)" }
+}
+
+
+# Go past assignment of NULL to pmi
+send_gdb "next\n"
+gdb_expect {
+ -re "\r\n85\[ \t\]*k = \\(a.\\*pmf\\)\\(3\\);\r\n$gdb_prompt $" {
+ pass "next past 83"
+ }
+ -re ".*$gdb_prompt $" { fail "next past 83" }
+ timeout { fail "(timeout) next past 83" }
+}
+
+#send_gdb "print pmi\n"
+#gdb_expect {
+# -re "Attempted dereference of null pointer-to-member\r\n$gdb_prompt $" {
+# pass ""
+# }
+# -re ".*$gdb_prompt $" { fail "" }
+# timeout { fail "(timeout) " }
+#}
+
+# Dereference the null pointer to member
+send_gdb "print a.*pmi\n"
+gdb_expect {
+ -re "Attempted dereference of null pointer-to-member\r\n$gdb_prompt $" {
+ pass "print a.*NULL"
+ }
+ -re ".*$gdb_prompt $" { fail "print a.*NULL" }
+ timeout { fail "(timeout) print a.*NULL" }
+}
+
+
+# Go to another part of the program
+send_gdb "break 91\n"
+gdb_expect {
+ -re "Breakpoint \[0-9\]*.*line 91\\.\r\n$gdb_prompt $" {
+ pass "set break at 91"
+ }
+ -re ".*$gdb_prompt $" { fail "set break at 91" }
+ timeout { fail "(timeout) set break at 91" }
+}
+
+send_gdb "continue\n"
+gdb_expect {
+ -re "Continuing\\.\r\n\r\nBreakpoint.*at.*member-ptr\\.cc:91\r\n91\[ \t]*k = \\(a.\\*pmf\\)\\(4\\);\r\n$gdb_prompt $" {
+ pass "continue to 91"
+ }
+ -re ".*$gdb_prompt $" { fail "continue to 91" }
+ timeout { fail "(timeout) continue to 91" }
+}
+
+
+# Now check again that pmi works even when not set to
+# something that's at the beginning of the object
+
+send_gdb "print pmi\n"
+gdb_expect {
+ -re "\\$\[0-9\]* = \\(int \\( A::\\*\\)\\) &A::jj\r\n$gdb_prompt $" {
+ pass "print pmi (2)"
+ }
+ -re ".*$gdb_prompt $" { fail "print pmi (2)" }
+ timeout { fail "(timeout) print pmi (2)" }
+}
+
+
+# print dereferenced pointer to data member
+
+send_gdb "print a.*pmi\n"
+gdb_expect {
+ -re "\\$\[0-9\]* = 1331\r\n$gdb_prompt $" {
+ pass "print a.*pmi (2)"
+ }
+ -re ".*$gdb_prompt $" { fail "print a.*pmi (2)" }
+ timeout { fail "(timeout) print a.*pmi (2)" }
+}
+
+# print dereferenced pointer to data member
+# this time, dereferenced through a pointer
+
+send_gdb "print a_p->*pmi\n"
+gdb_expect {
+ -re "\\$\[0-9\]* = 1331\r\n$gdb_prompt $" {
+ pass "print a->*pmi"
+ }
+ -re ".*$gdb_prompt $" { fail "print a->*pmi (2)" }
+ timeout { fail "(timeout) print a->*pmi (2)" }
+}
+
+
+# p a.*pmf - fail
+
+# p pmi
+
+# p a.*pmi
+
diff --git a/gdb/testsuite/gdb.c++/method.cc b/gdb/testsuite/gdb.c++/method.cc
new file mode 100644
index 00000000000..949b027a02e
--- /dev/null
+++ b/gdb/testsuite/gdb.c++/method.cc
@@ -0,0 +1,80 @@
+// Class funk has a constructor and an ordinary method
+// Test for CHFts23426
+
+class funk
+{
+public:
+ funk();
+ void getFunky(int a, int b);
+ int data_;
+};
+
+funk::funk()
+ : data_(33)
+{
+}
+
+void funk::getFunky(int a, int b)
+{
+ int res;
+ res = a + b - data_;
+ data_ = res;
+}
+
+// Class A has const and volatile methods
+
+class A {
+public:
+ int x;
+ int y;
+ int foo (int arg);
+ int bar (int arg) const;
+ int baz (int arg, char c) volatile;
+ int qux (int arg, float f) const volatile;
+};
+
+int A::foo (int arg)
+{
+ x += arg;
+ return arg *2;
+}
+
+int A::bar (int arg) const
+{
+ return arg + 2 * x;
+}
+
+int A::baz (int arg, char c) volatile
+{
+ return arg - 2 * x + c;
+}
+
+int A::qux (int arg, float f) const volatile
+{
+ if (f > 0)
+ return 2 * arg - x;
+ else
+ return 2 * arg + x;
+}
+
+
+int main()
+{
+ A a;
+ int k;
+
+ k = 10;
+ a.x = k * 2;
+
+ k = a.foo(13);
+
+ k += a.bar(15);
+
+ // Test for CHFts23426 follows
+ funk f;
+ f.getFunky(1, 2);
+ return 0;
+}
+
+
+
diff --git a/gdb/testsuite/gdb.c++/method.exp b/gdb/testsuite/gdb.c++/method.exp
new file mode 100644
index 00000000000..a3939dc0582
--- /dev/null
+++ b/gdb/testsuite/gdb.c++/method.exp
@@ -0,0 +1,233 @@
+# Copyright (C) 1998 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# tests for misc. C++ method stuff
+# Written by Satish Pai <pai@apollo.hp.com> 1997-07-08
+
+# This file is part of the gdb testsuite
+
+# This tests:
+# 0. method arguments are correct
+# 1. access to class data members inside method scopes
+# 2. correct param types for methods in ptype.
+# 3. const and volatile methods
+
+# (#0 and #1 above relate to an HP specific problem -- GDB must correctly
+# integrate FPARAM symbols in HP debug info into the local var list
+# for the function or method's block.)
+
+if $tracelevel then {
+ strace $tracelevel
+ }
+
+#
+# test running programs
+#
+set prms_id 0
+set bug_id 0
+
+set testfile "method"
+set srcfile ${testfile}.cc
+set binfile ${objdir}/${subdir}/${testfile}
+
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug c++}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+
+#
+# set it up at a breakpoint so we can play with the variable values
+#
+if ![runto_main] then {
+ perror "couldn't run to breakpoint"
+ continue
+}
+
+send_gdb "break A::foo\n"
+gdb_expect {
+ -re "Breakpoint \[0-9\]* at $hex.*file .*method.cc, line 38*\\.\r\n$gdb_prompt $" {
+ pass "set breakpoint on A::foo"
+ }
+ -re ".*$gdb_prompt $" { fail "set breakpoint on A::foo" }
+ timeout { fail "(timeout) set breakpoint on A::foo" }
+}
+
+send_gdb "continue\n"
+gdb_expect {
+ -re "Continuing\\.\r\n\r\nBreakpoint \[0-9\]*, A::foo \\(this=$hex, arg=13\\) at .*method\\.cc:38\r\n38\[\t \]*x \\+= arg;\r\n$gdb_prompt $" {
+ pass "continued and got breakpoint in A::foo"
+ }
+ -re ".*$gdb_prompt $" { fail "continuing and breaking in A::foo" }
+ timeout { fail "(timeout) continue" }
+}
+
+# Check ability to access this-relative stuff.
+
+send_gdb "print x\n"
+gdb_expect {
+ -re "\\$\[0-9\]* = 20\r\n$gdb_prompt $" {
+ pass "access this-relative x (in foo)"
+ }
+ -re ".*$gdb_prompt $" { fail "print x (in foo)" }
+ timeout { fail "(timeout) print x (in foo)" }
+}
+
+# Check access to this pointer
+
+send_gdb "print this\n"
+gdb_expect {
+ -re "\\$\[0-9\]* = \\(A \\*\\) $hex\r\n$gdb_prompt $" {
+ pass "print this (in foo)"
+ }
+ -re ".*$gdb_prompt $" { fail "print this (in foo)" }
+ timeout { fail "(timeout) print this (in foo)" }
+}
+
+# Now do everything over again for A::bar, because sometimes processing one method
+# (the first one) is fine, but the second one's debug info gets munged beyond recognition.
+
+send_gdb "break A::bar\n"
+gdb_expect {
+ -re "Breakpoint \[0-9\]* at $hex.*file .*method.cc, line 44\\.\r\n$gdb_prompt $" {
+ pass "set breakpoint on A::bar"
+ }
+ -re ".*$gdb_prompt $" { fail "set breakpoint on A::bar" }
+ timeout { fail "(timeout) set breakpoint on A::bar" }
+}
+
+send_gdb "continue\n"
+gdb_expect {
+ -re "Continuing\\.\r\n\r\nBreakpoint \[0-9\]*, A::bar \\(this=$hex, arg=15\\) at .*method\\.cc:44\r\n44\[\t \]*return arg \\+ 2 \\* x;\r\n$gdb_prompt $" {
+ pass "continued and got breakpoint in A::bar"
+ }
+ -re ".*$gdb_prompt $" { fail "continuing and breaking in A::bar" }
+ timeout { fail "(timeout) continue" }
+}
+
+# Check ability to access this-relative stuff.
+
+send_gdb "print x\n"
+gdb_expect {
+ -re "\\$\[0-9\]* = 33\r\n$gdb_prompt $" {
+ pass "access this-relative x (in bar)"
+ }
+ -re ".*$gdb_prompt $" { fail "print x (in bar)" }
+ timeout { fail "(timeout) print x (in bar)" }
+}
+
+# Check access to this pointer
+
+send_gdb "print this\n"
+gdb_expect {
+ -re "\\$\[0-9\]* = \\(const class A \\*\\) $hex\r\n$gdb_prompt $" {
+ pass "print this (in bar)"
+ }
+ -re ".*$gdb_prompt $" { fail "print this (in bar)" }
+ timeout { fail "(timeout) print this (in bar)" }
+}
+
+# Check again with funk::getFunky (this is the original test case
+# for CHFts23426); sometimes having a constructor with no arguments
+# will nuke the debug info read in for other methods in the class.
+
+send_gdb "break funk::getFunky\n"
+gdb_expect {
+ -re "Breakpoint \[0-9\]* at $hex.*file .*method.cc, line 20\\.\r\n$gdb_prompt $" {
+ pass "set breakpoint on funk::getFunky"
+ }
+ -re ".*$gdb_prompt $" { fail "set breakpoint on funk::getfunky" }
+ timeout { fail "(timeout) set breakpoint on funk::getfunky" }
+}
+
+send_gdb "continue\n"
+gdb_expect {
+ -re "Continuing\\.\r\n\r\nBreakpoint \[0-9\]*, funk::getFunky \\(this=$hex, a=1, b=2\\) at .*method\\.cc:20\r\n20\[\t \]*res = a \\+ b - data_;\r\n$gdb_prompt $" {
+ pass "continued and got breakpoint in funk::getfunky"
+ }
+ -re ".*$gdb_prompt $" { fail "continuing and breaking in funk::getfunky" }
+ timeout { fail "(timeout) continue" }
+}
+
+# Check ability to access this-relative stuff.
+
+send_gdb "print data_\n"
+gdb_expect {
+ -re "\\$\[0-9\]* = 33\r\n$gdb_prompt $" {
+ pass "access this-relative data_ in getFunky"
+ }
+ -re ".*$gdb_prompt $" { fail "print data_ in getFunky" }
+ timeout { fail "(timeout) print data_ in getFunky" }
+}
+
+# Check access to this pointer
+
+send_gdb "print this\n"
+gdb_expect {
+ -re "\\$\[0-9\]* = \\(funk \\*\\) $hex\r\n$gdb_prompt $" {
+ pass "print this in getFunky"
+ }
+ -re ".*$gdb_prompt $" { fail "print this in getfunky" }
+ timeout { fail "(timeout) print this in getfunky" }
+}
+
+# Check access to local variable
+
+send_gdb "print res\n"
+gdb_expect {
+ -re "\\$\[0-9\]* = \[0-9\]*\r\n$gdb_prompt $" {
+ pass "print res in getFunky"
+ }
+ -re ".*$gdb_prompt $" { fail "print res in getfunky" }
+ timeout { fail "(timeout) print res in getfunky" }
+}
+
+
+# Check ptype of class -- should show const/volatile methods
+
+send_gdb "ptype A\n"
+gdb_expect {
+ -re "type = class A \{\r\n\[ \]*public:\r\n\[ \]*int x;\r\n\[ \]*int y;\r\n\r\n\\[ \]*A & operator=\\(A const &\\);\r\n\[ \]*A\\(A const &\\)\r\n\[ \]*A\\(void\\)\r\n[ \]*int foo\\(int\\);\r\n\[ \]*int bar\\(int\\) const;\r\n\[ \]*int baz\\(int, char\\) volatile;\r\n\[ \]*int qux\\(int, float\\) const volatile;\r\n\}\r\n$gdb_prompt $" {
+ pass "ptype A"
+ }
+ -re "type = class A \{\r\n\[ \]*public:\r\n\[ \]*int x;\r\n\[ \]*int y;\r\n\r\n\[ \]*int foo\\(int\\);\r\n\[ \]*int bar\\(int\\) const;\r\n\[ \]*int baz\\(int, char\\);\r\n\[ \]*int qux\\(int, float\\) const;\r\n\}\r\n$gdb_prompt $" {
+ pass "ptype A (HP aCC bug -- volatile not indicated)"
+ }
+ -re "type = class A \{\r\n\[ \]*public:\r\n\[ \]*int x;\r\n\[ \]*int y;\r\n\r\n\[ \]*int foo\\(int\\);\r\n\[ \]*int bar\\(int\\) const;\r\n\[ \]*int baz\\(int, char\\) volatile;\r\n\[ \]*int qux\\(int, float\\) const volatile;\r\n\}\r\n$gdb_prompt $" {
+ pass "ptype A"
+ }
+ -re ".*$gdb_prompt $" { fail "ptype A" }
+ timeout { fail "(timeout) ptype A" }
+}
+
+send_gdb "cont\n"
+gdb_expect {
+ -re "Continuing.\r\n\r\nProgram exited normally.\r\n$gdb_prompt $" {
+ pass "finish program"
+ }
+ -re "$gdb_prompt $" { fail "finish program" }
+ timeout { fail "(timeout) finish program" }
+}
+
diff --git a/gdb/testsuite/gdb.c++/misc.cc b/gdb/testsuite/gdb.c++/misc.cc
new file mode 100644
index 00000000000..ffeb73962fd
--- /dev/null
+++ b/gdb/testsuite/gdb.c++/misc.cc
@@ -0,0 +1,517 @@
+// Test various -*- C++ -*- things.
+
+typedef struct fleep fleep;
+struct fleep { int a; } s;
+
+// ====================== simple class structures =======================
+
+struct default_public_struct {
+ // defaults to public:
+ int a;
+ int b;
+};
+
+struct explicit_public_struct {
+ public:
+ int a;
+ int b;
+};
+
+struct protected_struct {
+ protected:
+ int a;
+ int b;
+};
+
+struct private_struct {
+ private:
+ int a;
+ int b;
+};
+
+struct mixed_protection_struct {
+ public:
+ int a;
+ int b;
+ private:
+ int c;
+ int d;
+ protected:
+ int e;
+ int f;
+ public:
+ int g;
+ private:
+ int h;
+ protected:
+ int i;
+};
+
+class public_class {
+ public:
+ int a;
+ int b;
+};
+
+class protected_class {
+ protected:
+ int a;
+ int b;
+};
+
+class default_private_class {
+ // defaults to private:
+ int a;
+ int b;
+};
+
+class explicit_private_class {
+ private:
+ int a;
+ int b;
+};
+
+class mixed_protection_class {
+ public:
+ int a;
+ int b;
+ private:
+ int c;
+ int d;
+ protected:
+ int e;
+ int f;
+ public:
+ int g;
+ private:
+ int h;
+ protected:
+ int i;
+};
+
+class const_vol_method_class {
+public:
+ int a;
+ int b;
+ int foo (int &) const;
+ int bar (int &) volatile;
+ int baz (int &) const volatile;
+};
+
+int const_vol_method_class::foo (int & ir) const
+{
+ return ir + 3;
+}
+int const_vol_method_class::bar (int & ir) volatile
+{
+ return ir + 4;
+}
+int const_vol_method_class::baz (int & ir) const volatile
+{
+ return ir + 5;
+}
+
+// ========================= simple inheritance ==========================
+
+class A {
+ public:
+ int a;
+ int x;
+};
+
+A g_A;
+
+class B : public A {
+ public:
+ int b;
+ int x;
+};
+
+B g_B;
+
+class C : public A {
+ public:
+ int c;
+ int x;
+};
+
+C g_C;
+
+class D : public B, public C {
+ public:
+ int d;
+ int x;
+};
+
+D g_D;
+
+class E : public D {
+ public:
+ int e;
+ int x;
+};
+
+E g_E;
+
+class class_with_anon_union
+{
+ public:
+ int one;
+ union
+ {
+ int a;
+ long b;
+ };
+};
+
+class_with_anon_union g_anon_union;
+
+void inheritance2 (void)
+{
+}
+
+void inheritance1 (void)
+{
+ int ival;
+ int *intp;
+
+ // {A::a, A::x}
+
+ g_A.A::a = 1;
+ g_A.A::x = 2;
+
+ // {{A::a,A::x},B::b,B::x}
+
+ g_B.A::a = 3;
+ g_B.A::x = 4;
+ g_B.B::b = 5;
+ g_B.B::x = 6;
+
+ // {{A::a,A::x},C::c,C::x}
+
+ g_C.A::a = 7;
+ g_C.A::x = 8;
+ g_C.C::c = 9;
+ g_C.C::x = 10;
+
+ // {{{A::a,A::x},B::b,B::x},{{A::a,A::x},C::c,C::x},D::d,D::x}
+
+ // The following initialization code is non-portable, but allows us
+ // to initialize all members of g_D until we can fill in the missing
+ // initialization code with legal C++ code.
+
+ for (intp = (int *) &g_D, ival = 11;
+ intp < ((int *) &g_D + sizeof (g_D) / sizeof (int));
+ intp++, ival++)
+ {
+ *intp = ival;
+ }
+
+ // Overlay the nonportable initialization with legal initialization.
+
+ // ????? = 11; (g_D.A::a = 11; is ambiguous)
+ // ????? = 12; (g_D.A::x = 12; is ambiguous)
+ g_D.B::b = 13;
+ g_D.B::x = 14;
+ // ????? = 15;
+ // ????? = 16;
+ g_D.C::c = 17;
+ g_D.C::x = 18;
+ g_D.D::d = 19;
+ g_D.D::x = 20;
+
+
+ // {{{{A::a,A::x},B::b,B::x},{{A::a,A::x},C::c,C::x},D::d,D::x}},E::e,E::x}
+
+ // The following initialization code is non-portable, but allows us
+ // to initialize all members of g_D until we can fill in the missing
+ // initialization code with legal C++ code.
+
+ for (intp = (int *) &g_E, ival = 21;
+ intp < ((int *) &g_E + sizeof (g_E) / sizeof (int));
+ intp++, ival++)
+ {
+ *intp = ival;
+ }
+
+ // Overlay the nonportable initialization with legal initialization.
+
+ // ????? = 21; (g_E.A::a = 21; is ambiguous)
+ // ????? = 22; (g_E.A::x = 22; is ambiguous)
+ g_E.B::b = 23;
+ g_E.B::x = 24;
+ // ????? = 25;
+ // ????? = 26;
+ g_E.C::c = 27;
+ g_E.C::x = 28;
+ g_E.D::d = 29;
+ g_E.D::x = 30;
+ g_E.E::e = 31;
+ g_E.E::x = 32;
+
+ g_anon_union.one = 1;
+ g_anon_union.a = 2;
+
+ inheritance2 ();
+}
+
+// ======================== virtual base classes=========================
+
+class vA {
+ public:
+ int va;
+ int vx;
+};
+
+vA g_vA;
+
+class vB : public virtual vA {
+ public:
+ int vb;
+ int vx;
+};
+
+vB g_vB;
+
+class vC : public virtual vA {
+ public:
+ int vc;
+ int vx;
+};
+
+vC g_vC;
+
+class vD : public virtual vB, public virtual vC {
+ public:
+ int vd;
+ int vx;
+};
+
+vD g_vD;
+
+class vE : public virtual vD {
+ public:
+ int ve;
+ int vx;
+};
+
+vE g_vE;
+
+void inheritance4 (void)
+{
+}
+
+void inheritance3 (void)
+{
+ int ival;
+ int *intp;
+
+ // {vA::va, vA::vx}
+
+ g_vA.vA::va = 1;
+ g_vA.vA::vx = 2;
+
+ // {{vA::va, vA::vx}, vB::vb, vB::vx}
+
+ g_vB.vA::va = 3;
+ g_vB.vA::vx = 4;
+ g_vB.vB::vb = 5;
+ g_vB.vB::vx = 6;
+
+ // {{vA::va, vA::vx}, vC::vc, vC::vx}
+
+ g_vC.vA::va = 7;
+ g_vC.vA::vx = 8;
+ g_vC.vC::vc = 9;
+ g_vC.vC::vx = 10;
+
+ // {{{{vA::va, vA::vx}, vB::vb, vB::vx}, vC::vc, vC::vx}, vD::vd,vD::vx}
+
+ g_vD.vA::va = 11;
+ g_vD.vA::vx = 12;
+ g_vD.vB::vb = 13;
+ g_vD.vB::vx = 14;
+ g_vD.vC::vc = 15;
+ g_vD.vC::vx = 16;
+ g_vD.vD::vd = 17;
+ g_vD.vD::vx = 18;
+
+
+ // {{{{{vA::va,vA::vx},vB::vb,vB::vx},vC::vc,vC::vx},vD::vd,vD::vx},vE::ve,vE::vx}
+
+ g_vD.vA::va = 19;
+ g_vD.vA::vx = 20;
+ g_vD.vB::vb = 21;
+ g_vD.vB::vx = 22;
+ g_vD.vC::vc = 23;
+ g_vD.vC::vx = 24;
+ g_vD.vD::vd = 25;
+ g_vD.vD::vx = 26;
+ g_vE.vE::ve = 27;
+ g_vE.vE::vx = 28;
+
+ inheritance4 ();
+}
+
+// ======================================================================
+
+class Base1 {
+ public:
+ int x;
+ Base1(int i) { x = i; }
+};
+
+class Foo
+{
+ public:
+ int x;
+ int y;
+ static int st;
+ Foo (int i, int j) { x = i; y = j; }
+ int operator! ();
+ operator int ();
+ int times (int y);
+};
+
+class Bar : public Base1, public Foo {
+ public:
+ int z;
+ Bar (int i, int j, int k) : Base1 (10*k), Foo (i, j) { z = k; }
+};
+
+class ClassWithEnum {
+public:
+ enum PrivEnum { red, green, blue, yellow = 42 };
+ PrivEnum priv_enum;
+ int x;
+};
+
+int Foo::operator! () { return !x; }
+
+int Foo::times (int y) { return x * y; }
+
+int Foo::st = 100;
+
+Foo::operator int() { return x; }
+
+Foo foo(10, 11);
+Bar bar(20, 21, 22);
+
+class Contains_static_instance
+{
+ public:
+ int x;
+ int y;
+ Contains_static_instance (int i, int j) { x = i; y = j; }
+ static Contains_static_instance null;
+};
+
+Contains_static_instance Contains_static_instance::null(0,0);
+Contains_static_instance csi(10,20);
+
+class Contains_nested_static_instance
+{
+ public:
+ class Nested
+ {
+ public:
+ Nested(int i) : z(i) {}
+ int z;
+ static Contains_nested_static_instance xx;
+ };
+
+ Contains_nested_static_instance(int i, int j) : x(i), y(j) {}
+
+ int x;
+ int y;
+
+ static Contains_nested_static_instance null;
+ static Nested yy;
+};
+
+Contains_nested_static_instance Contains_nested_static_instance::null(0, 0);
+Contains_nested_static_instance::Nested Contains_nested_static_instance::yy(5);
+Contains_nested_static_instance
+ Contains_nested_static_instance::Nested::xx(1,2);
+Contains_nested_static_instance cnsi(30,40);
+
+typedef struct {
+ int one;
+ int two;
+} tagless_struct;
+tagless_struct v_tagless;
+
+/* Try to get the compiler to allocate a class in a register. */
+class small {
+ public:
+ int x;
+ int method ();
+};
+
+int
+small::method ()
+{
+ return x + 5;
+}
+
+void marker_reg1 () {}
+
+int
+register_class ()
+{
+ /* We don't call any methods for v, so gcc version cygnus-2.3.3-930220
+ might put this variable in a register. This is a lose, though, because
+ it means that GDB can't call any methods for that variable. */
+ register small v;
+
+ int i;
+
+ /* Perform a computation sufficiently complicated that optimizing compilers
+ won't optimized out the variable. If some compiler constant-folds this
+ whole loop, maybe using a parameter to this function here would help. */
+ v.x = 0;
+ for (i = 0; i < 13; ++i)
+ v.x += i;
+ --v.x; /* v.x is now 77 */
+ marker_reg1 ();
+ return v.x + 5;
+}
+
+int
+main()
+{
+#ifdef usestubs
+ set_debug_traps();
+ breakpoint();
+#endif
+ inheritance1 ();
+ inheritance3 ();
+ register_class ();
+
+ /* FIXME: pmi gets optimized out. Need to do some more computation with
+ it or something. (No one notices, because the test is xfail'd anyway,
+ but that probably won't always be true...). */
+ int Foo::* pmi = &Foo::y;
+
+ /* Make sure the AIX linker doesn't remove the variable. */
+ v_tagless.one = 5;
+
+ /* Class with enumeration inside it */
+ ClassWithEnum obj_with_enum;
+ obj_with_enum.priv_enum = ClassWithEnum::green;
+
+ return foo.*pmi;
+}
+
+/* Create an instance for some classes, otherwise they get optimized away. */
+
+default_public_struct default_public_s;
+explicit_public_struct explicit_public_s;
+protected_struct protected_s;
+private_struct private_s;
+mixed_protection_struct mixed_protection_s;
+public_class public_c;
+protected_class protected_c;
+default_private_class default_private_c;
+explicit_private_class explicit_private_c;
+mixed_protection_class mixed_protection_c;
diff --git a/gdb/testsuite/gdb.c++/misc.exp b/gdb/testsuite/gdb.c++/misc.exp
new file mode 100644
index 00000000000..6090fbb3c2a
--- /dev/null
+++ b/gdb/testsuite/gdb.c++/misc.exp
@@ -0,0 +1,106 @@
+# Copyright (C) 1992, 1994, 1997 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file was written by Fred Fish. (fnf@cygnus.com)
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+# Check to see if we have an executable to test. If not, then either we
+# haven't tried to compile one, or the compilation failed for some reason.
+# In either case, just notify the user and skip the tests in this file.
+
+set testfile "misc"
+set srcfile ${testfile}.cc
+set binfile ${objdir}/${subdir}/${testfile}
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug c++}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+#
+# Deduce language of main()
+#
+
+proc deduce_language_of_main {} {
+ global gdb_prompt
+
+ # See what language gdb thinks main() is, prior to reading full symbols.
+ # I think this fails for COFF targets.
+ setup_xfail "a29k-*-udi"
+ send_gdb "show language\n"
+ gdb_expect {
+ -re ".* source language is \"auto; currently c\[+\]+\".*$gdb_prompt $" {
+ pass "deduced language is C++, before full symbols"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "source language not correct for C++ (psymtabs only)"
+ return
+ }
+ timeout {
+ fail "can't show language (timeout)"
+ return
+ }
+ }
+
+ runto_main
+
+ # See if our idea of the language has changed.
+
+ send_gdb "show language\n"
+ gdb_expect {
+ -re ".* source language is \"auto; currently c\[+\]+\".*$gdb_prompt $" {
+ pass "deduced language is C++, after full symbols"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "source language not correct for C++ (full symbols)"
+ return
+ }
+ timeout {
+ fail "can't show language (timeout)"
+ return
+ }
+ }
+}
+
+proc do_tests {} {
+ global prms_id
+ global bug_id
+ global subdir
+ global objdir
+ global srcdir
+ global binfile
+ global gdb_prompt
+
+ set prms_id 0
+ set bug_id 0
+
+ # Start with a fresh gdb.
+
+ gdb_exit
+ gdb_start
+ gdb_reinitialize_dir $srcdir/$subdir
+ gdb_load $binfile
+
+ deduce_language_of_main
+ # Check for fixes for PRs 8916 and 8630
+ gdb_test "print s.a" ".* = 0" "print s.a for foo struct (known gcc 2.7.2 and earlier bug)"
+}
+
+do_tests
diff --git a/gdb/testsuite/gdb.c++/overload.cc b/gdb/testsuite/gdb.c++/overload.cc
new file mode 100644
index 00000000000..40feb3b5e84
--- /dev/null
+++ b/gdb/testsuite/gdb.c++/overload.cc
@@ -0,0 +1,151 @@
+#include <stddef.h>
+
+class foo {
+public:
+ foo (int);
+ foo (int, const char *);
+ foo (foo&);
+ ~foo ();
+ void foofunc (int);
+ void foofunc (int, signed char *);
+ int ifoo;
+ const char *ccpfoo;
+
+int overload1arg (void);
+int overload1arg (char);
+int overload1arg (signed char);
+int overload1arg (unsigned char);
+int overload1arg (short);
+int overload1arg (unsigned short);
+int overload1arg (int);
+int overload1arg (unsigned int);
+int overload1arg (long);
+int overload1arg (unsigned long);
+int overload1arg (float);
+int overload1arg (double);
+
+int overloadargs (int a1);
+int overloadargs (int a1, int a2);
+int overloadargs (int a1, int a2, int a3);
+int overloadargs (int a1, int a2, int a3, int a4);
+int overloadargs (int a1, int a2, int a3, int a4, int a5);
+int overloadargs (int a1, int a2, int a3, int a4, int a5, int a6);
+int overloadargs (int a1, int a2, int a3, int a4, int a5, int a6, int a7);
+int overloadargs (int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8);
+int overloadargs (int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8, int a9);
+int overloadargs (int a1, int a2, int a3, int a4, int a5, int a6, int a7,
+ int a8, int a9, int a10);
+int overloadargs (int a1, int a2, int a3, int a4, int a5, int a6, int a7,
+ int a8, int a9, int a10, int a11);
+
+
+};
+
+void marker1()
+{}
+
+int main ()
+{
+ char arg2 = 2;
+ signed char arg3 =3;
+ unsigned char arg4 =4;
+ short arg5 =5;
+ unsigned short arg6 =6;
+ int arg7 =7;
+ unsigned int arg8 =8;
+ long arg9 =9;
+ unsigned long arg10 =10;
+ float arg11 =100.0;
+ double arg12 = 200.0;
+
+ char *str = "A";
+ foo foo_instance1(111);
+ foo foo_instance2(222, str);
+ foo foo_instance3(foo_instance2);
+
+ #ifdef usestubs
+ set_debug_traps();
+ breakpoint();
+ #endif
+
+
+ marker1();
+ return 0;
+}
+
+foo::foo (int i) { ifoo = i; ccpfoo = NULL; }
+foo::foo (int i, const char *ccp) { ifoo = i; ccpfoo = ccp; }
+foo::foo (foo& afoo) { ifoo = afoo.ifoo; ccpfoo = afoo.ccpfoo;}
+foo::~foo () {}
+
+
+/* Some functions to test overloading by varying one argument type. */
+
+int foo::overload1arg (void) { return 1; }
+int foo::overload1arg (char arg) { arg = 0; return 2;}
+int foo::overload1arg (signed char arg) { arg = 0; return 3;}
+int foo::overload1arg (unsigned char arg) { arg = 0; return 4;}
+int foo::overload1arg (short arg) { arg = 0; return 5;}
+int foo::overload1arg (unsigned short arg) { arg = 0; return 6;}
+int foo::overload1arg (int arg) { arg = 0; return 7;}
+int foo::overload1arg (unsigned int arg) { arg = 0; return 8;}
+int foo::overload1arg (long arg) { arg = 0; return 9;}
+int foo::overload1arg (unsigned long arg) { arg = 0; return 10;}
+int foo::overload1arg (float arg) { arg = 0; return 11;}
+int foo::overload1arg (double arg) { arg = 0; return 12;}
+
+
+/* Some functions to test overloading by varying argument count. */
+
+int foo::overloadargs (int a1)
+{ a1 = 0;
+return 1;}
+
+int foo::overloadargs (int a1, int a2)
+{ a1 = a2 = 0;
+return 2;}
+
+int foo::overloadargs (int a1, int a2, int a3)
+{ a1 = a2 = a3 = 0;
+return 3;}
+
+int foo::overloadargs (int a1, int a2, int a3, int a4)
+{ a1 = a2 = a3 = a4 = 0;
+return 4;}
+
+int foo::overloadargs (int a1, int a2, int a3, int a4, int a5)
+{ a1 = a2 = a3 = a4 = a5 = 0;
+return 5;}
+
+int foo::overloadargs (int a1, int a2, int a3, int a4, int a5, int a6)
+{ a1 = a2 = a3 = a4 = a5 = a6 = 0;
+return 6;}
+
+int foo::overloadargs (int a1, int a2, int a3, int a4, int a5, int a6, int a7)
+{ a1 = a2 = a3 = a4 = a5 = a6 = a7 = 0;
+return 7;}
+
+int foo::overloadargs (int a1, int a2, int a3, int a4, int a5, int a6, int a7,
+ int a8)
+{ a1 = a2 = a3 = a4 = a5 = a6 = a7 = a8 = 0;
+return 8;}
+
+int foo::overloadargs (int a1, int a2, int a3, int a4, int a5, int a6, int a7,
+ int a8, int a9)
+{
+ a1 = a2 = a3 = a4 = a5 = a6 = a7 = a8 = a9 = 0;
+ return 9;
+}
+
+int foo::overloadargs (int a1, int a2, int a3, int a4, int a5, int a6, int a7,
+ int a8, int a9, int a10)
+ { a1 = a2 = a3 = a4 = a5 = a6 = a7 = a8 = a9 =
+ a10 = 0; return 10;}
+
+int foo::overloadargs (int a1, int a2, int a3, int a4, int a5, int a6, int a7,
+ int a8, int a9, int a10, int a11)
+ { a1 = a2 = a3 = a4 = a5 = a6 = a7 = a8 = a9 =
+ a10 = a11 = 0; return 11;}
+
+
+
diff --git a/gdb/testsuite/gdb.c++/overload.exp b/gdb/testsuite/gdb.c++/overload.exp
new file mode 100644
index 00000000000..b1ddb16303a
--- /dev/null
+++ b/gdb/testsuite/gdb.c++/overload.exp
@@ -0,0 +1,338 @@
+# Copyright (C) 1998 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# written by Elena Zannoni (ezannoni@cygnus.com)
+
+# This file is part of the gdb testsuite
+#
+# tests for overloaded member functions. Command Line calls
+#
+
+
+if $tracelevel then {
+ strace $tracelevel
+ }
+
+#
+# test running programs
+#
+set prms_id 0
+set bug_id 0
+
+set testfile "overload"
+set srcfile ${testfile}.cc
+set binfile ${objdir}/${subdir}/${testfile}
+
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug c++}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+# set it up at a breakpoint so we can play with the variable values
+#
+if ![runto_main] then {
+ perror "couldn't run to breakpoint"
+ continue
+}
+
+send_gdb "break marker1\n" ; gdb_expect -re ".*$gdb_prompt $"
+
+ send_gdb "cont\n"
+ gdb_expect {
+ -re "Break.* marker1 \\(\\) at .*:$decimal.*$gdb_prompt $" {
+ send_gdb "up\n"
+ gdb_expect {
+ -re ".*$gdb_prompt $" {}
+ timeout { fail "up from marker1" }
+ }
+ }
+ -re "$gdb_prompt $" { fail "continue to marker1" }
+ timeout { fail "(timeout) continue to marker1" }
+ }
+
+
+send_gdb "print foo_instance1\n"
+gdb_expect {
+ -re ".\[0-9\]* = \{ifoo = 111, ccpfoo = 0x0\}\r\n$gdb_prompt $" {
+ pass "print foo_instance1"
+ }
+ -re ".*$gdb_prompt $" { fail "print foo_instance1" }
+ timeout { fail "(timeout) print foo_instance1" }
+ }
+
+
+send_gdb "ptype foo_instance1\n"
+gdb_expect {
+ -re "type = class foo \{.*public:.*int ifoo;.*const char \\*ccpfoo;.*foo\\(int\\);.*foo\\(int, (const char|char const) \\*\\);.*foo\\(foo &\\);.*~foo\\(void\\);.*void foofunc\\(int\\);.*void foofunc\\(int, signed char \\*\\);.*int overload1arg\\(void\\);.*int overload1arg\\(char\\);.*int overload1arg\\(signed char\\);.*int overload1arg\\(unsigned char\\);.*int overload1arg\\(short\\);.*int overload1arg\\(unsigned short\\);.*int overload1arg\\(int\\);.*int overload1arg\\(unsigned int\\);.*int overload1arg\\(long\\);.*int overload1arg\\(unsigned long\\);.*int overload1arg\\(float\\);.*int overload1arg\\(double\\);.*int overloadargs\\(int\\);.*int overloadargs\\(int, int\\);.*int overloadargs\\(int, int, int\\);.*int overloadargs\\(int, int, int, int\\);.*int overloadargs\\(int, int, int, int, int\\);.*int overloadargs\\(int, int, int, int, int, int\\);.*int overloadargs\\(int, int, int, int, int, int, int\\);.*int overloadargs\\(int, int, int, int, int, int, int, int\\);.*int overloadargs\\(int, int, int, int, int, int, int, int, int\\);.*int overloadargs\\(int, int, int, int, int, int, int, int, int, int\\);.*int overloadargs\\(int, int, int, int, int, int, int, int, int, int, int\\);\r\n\}\r\n$gdb_prompt $" {
+ pass "ptype foo_instance1 (HP aCC -- known quirk with ~foo parameter list)"
+ }
+ -re ".*$gdb_prompt $" { fail "ptype foo_instance1" }
+ timeout { fail "(timeout) ptype foo_instance1" }
+ }
+
+send_gdb "print foo_instance2\n"
+gdb_expect {
+ -re ".\[0-9\]* = \{ifoo = 222, ccpfoo = $hex \"A\"\}\r\n$gdb_prompt $" {
+ pass "print foo_instance2"
+ }
+ -re ".*$gdb_prompt $" { fail "print foo_instance2" }
+ timeout { fail "(timeout) print foo_instance2" }
+ }
+
+send_gdb "print foo_instance3\n"
+gdb_expect {
+ -re ".\[0-9\]* = \{ifoo = 222, ccpfoo = $hex \"A\"\}\r\n$gdb_prompt $" {
+ pass "print foo_instance3"
+ }
+ -re ".*$gdb_prompt $" { fail "print foo_instance3" }
+ timeout { fail "(timeout) print foo_instance3" }
+ }
+
+
+
+send_gdb "print foo_instance1.overloadargs(1)\n"
+gdb_expect {
+ -re ".\[0-9\]* = 1\r\n$gdb_prompt $" {
+ pass "print call overloaded func 1 arg"
+ }
+ -re ".*$gdb_prompt $" { fail "print call overloaded func 1 arg" }
+ timeout { fail "(timeout) print call overloaded func 1 arg" }
+ }
+
+send_gdb "print foo_instance1.overloadargs(1, 2)\n"
+gdb_expect {
+ -re ".\[0-9\]* = 2\r\n$gdb_prompt $" {
+ pass "print call overloaded func 2 args"
+ }
+ -re ".*$gdb_prompt $" { fail "print call overloaded func 2 args" }
+ timeout { fail "(timeout) print call overloaded func 2 args" }
+ }
+
+
+send_gdb "print foo_instance1.overloadargs(1, 2, 3)\n"
+gdb_expect {
+ -re ".\[0-9\]* = 3\r\n$gdb_prompt $" {
+ pass "print call overloaded func 3 args"
+ }
+ -re ".*$gdb_prompt $" { fail "print call overloaded func 3 args" }
+ timeout { fail "(timeout) print call overloaded func 3 args" }
+ }
+
+
+send_gdb "print foo_instance1.overloadargs(1, 2, 3, 4)\n"
+gdb_expect {
+ -re ".\[0-9\]* = 4\r\n$gdb_prompt $" {
+ pass "print call overloaded func 4 args"
+ }
+ -re ".*$gdb_prompt $" { fail "print call overloaded func 4 args" }
+ timeout { fail "(timeout) print call overloaded func 4 args" }
+ }
+
+
+send_gdb "print foo_instance1.overloadargs(1, 2, 3, 4, 5)\n"
+gdb_expect {
+ -re ".\[0-9\]* = 5\r\n$gdb_prompt $" {
+ pass "print call overloaded func 5 args"
+ }
+ -re ".*$gdb_prompt $" { fail "print call overloaded func 5 args" }
+ timeout { fail "(timeout) print call overloaded func 5 args" }
+ }
+
+
+send_gdb "print foo_instance1.overloadargs(1, 2, 3, 4, 5, 6)\n"
+gdb_expect {
+ -re ".\[0-9\]* = 6\r\n$gdb_prompt $" {
+ pass "print call overloaded func 6 args"
+ }
+ -re ".*$gdb_prompt $" { fail "print call overloaded func 6 args" }
+ timeout { fail "(timeout) print call overloaded func 6 args" }
+ }
+
+
+send_gdb "print foo_instance1.overloadargs(1, 2, 3, 4, 5, 6, 7)\n"
+gdb_expect {
+ -re ".\[0-9\]* = 7\r\n$gdb_prompt $" {
+ pass "print call overloaded func 7 args"
+ }
+ -re ".*$gdb_prompt $" { fail "print call overloaded func 7 args" }
+ timeout { fail "(timeout) print call overloaded func 7 args" }
+ }
+
+
+send_gdb "print foo_instance1.overloadargs(1, 2, 3, 4, 5, 6, 7, 8)\n"
+gdb_expect {
+ -re ".\[0-9\]* = 8\r\n$gdb_prompt $" {
+ pass "print call overloaded func 8 args"
+ }
+ -re ".*$gdb_prompt $" { fail "print call overloaded func 8 args" }
+ timeout { fail "(timeout) print call overloaded func 8 args" }
+ }
+
+
+send_gdb "print foo_instance1.overloadargs(1, 2, 3, 4, 5, 6, 7, 8, 9)\n"
+gdb_expect {
+ -re ".\[0-9\]* = 9\r\n$gdb_prompt $" {
+ pass "print call overloaded func 9 args"
+ }
+ -re ".*$gdb_prompt $" { fail "print call overloaded func 9 args" }
+ timeout { fail "(timeout) print call overloaded func 9 args" }
+ }
+
+
+send_gdb "print foo_instance1.overloadargs(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)\n"
+gdb_expect {
+ -re ".\[0-9\]* = 10\r\n$gdb_prompt $" {
+ pass "print call overloaded func 10 args"
+ }
+ -re ".*$gdb_prompt $" { fail "print call overloaded func 10 args" }
+ timeout { fail "(timeout) print call overloaded func 10 args" }
+ }
+
+
+send_gdb "print foo_instance1.overloadargs(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11)\n"
+gdb_expect {
+ -re ".\[0-9\]* = 11\r\n$gdb_prompt $" {
+ pass "print call overloaded func 11 args"
+ }
+ -re ".*$gdb_prompt $" { fail "print call overloaded func 11 args" }
+ timeout { fail "(timeout) print call overloaded func 11 args" }
+ }
+
+
+send_gdb "print foo_instance1.overload1arg()\n"
+gdb_expect {
+ -re ".\[0-9\]* = 1\r\n$gdb_prompt $" {
+ pass "print call overloaded func void arg"
+ }
+ -re ".*$gdb_prompt $" { fail "print call overloaded func void arg" }
+ timeout { fail "(timeout) print call overloaded func void arg" }
+ }
+
+send_gdb "print foo_instance1.overload1arg((char)arg2)\n"
+gdb_expect {
+ -re ".\[0-9\]* = 2\r\n$gdb_prompt $" {
+ pass "print call overloaded func char arg"
+ }
+ -re ".*$gdb_prompt $" { fail "print call overloaded func char arg" }
+ timeout { fail "(timeout) print call overloaded func char arg" }
+ }
+
+send_gdb "print foo_instance1.overload1arg((signed char)arg3)\n"
+gdb_expect {
+ -re ".\[0-9\]* = 3\r\n$gdb_prompt $" {
+ pass "print call overloaded func signed char arg"
+ }
+ -re ".*$gdb_prompt $" { fail "print call overloaded func signed char arg" }
+ timeout { fail "(timeout) print call overloaded func signed char arg" }
+ }
+
+
+send_gdb "print foo_instance1.overload1arg((unsigned char)arg4)\n"
+gdb_expect {
+ -re ".\[0-9\]* = 4\r\n$gdb_prompt $" {
+ pass "print call overloaded func unsigned char arg"
+ }
+ -re ".*$gdb_prompt $" { fail "print call overloaded func unsigned char arg" }
+ timeout { fail "(timeout) print call overloaded func unsigned char arg" }
+ }
+
+
+send_gdb "print foo_instance1.overload1arg((short)arg5)\n"
+gdb_expect {
+ -re ".\[0-9\]* = 5\r\n$gdb_prompt $" {
+ pass "print call overloaded func short arg"
+ }
+ -re ".*$gdb_prompt $" { fail "print call overloaded func short arg" }
+ timeout { fail "(timeout) print call overloaded func short arg" }
+ }
+
+
+send_gdb "print foo_instance1.overload1arg((unsigned short)arg6)\n"
+gdb_expect {
+ -re ".\[0-9\]* = 6\r\n$gdb_prompt $" {
+ pass "print call overloaded func unsigned short arg"
+ }
+ -re ".*$gdb_prompt $" { fail "print call overloaded func unsigned short arg" }
+ timeout { fail "(timeout) print call overloaded func unsigned short arg" }
+ }
+
+
+send_gdb "print foo_instance1.overload1arg((int)arg7)\n"
+gdb_expect {
+ -re ".\[0-9\]* = 7\r\n$gdb_prompt $" {
+ pass "print call overloaded func int arg"
+ }
+ -re ".*$gdb_prompt $" { fail "print call overloaded func int arg" }
+ timeout { fail "(timeout) print call overloaded func int arg" }
+ }
+
+
+send_gdb "print foo_instance1.overload1arg((unsigned int)arg8)\n"
+gdb_expect {
+ -re ".\[0-9\]* = 8\r\n$gdb_prompt $" {
+ pass "print call overloaded func unsigned int arg"
+ }
+ -re ".*$gdb_prompt $" { fail "print call overloaded func unsigned int arg" }
+ timeout { fail "(timeout) print call overloaded func unsigned int arg" }
+ }
+
+
+send_gdb "print foo_instance1.overload1arg((long)arg9)\n"
+gdb_expect {
+ -re ".\[0-9\]* = 9\r\n$gdb_prompt $" {
+ pass "print call overloaded func long arg"
+ }
+ -re ".*$gdb_prompt $" { fail "print call overloaded func long arg" }
+ timeout { fail "(timeout) print call overloaded func long arg" }
+ }
+
+
+send_gdb "print foo_instance1.overload1arg((unsigned long)arg10)\n"
+gdb_expect {
+ -re ".\[0-9\]* = 10\r\n$gdb_prompt $" {
+ pass "print call overloaded func unsigned long arg"
+ }
+ -re ".*$gdb_prompt $" { fail "print call overloaded func unsigned long arg" }
+ timeout { fail "(timeout) print call overloaded func unsigned long arg" }
+ }
+
+
+send_gdb "print foo_instance1.overload1arg((float)arg11)\n"
+gdb_expect {
+ -re ".\[0-9\]* = 11\r\n$gdb_prompt $" {
+ pass "print call overloaded func float arg"
+ }
+ -re ".*$gdb_prompt $" { fail "print call overloaded func float arg" }
+ timeout { fail "(timeout) print call overloaded func float arg" }
+ }
+
+
+send_gdb "print foo_instance1.overload1arg((double)arg12)\n"
+gdb_expect {
+ -re ".\[0-9\]* = 12\r\n$gdb_prompt $" {
+ pass "print call overloaded func double arg"
+ }
+ -re ".*$gdb_prompt $" { fail "print call overloaded func double arg" }
+ timeout { fail "(timeout) print call overloaded func double arg" }
+ }
diff --git a/gdb/testsuite/gdb.c++/ovldbreak.cc b/gdb/testsuite/gdb.c++/ovldbreak.cc
new file mode 100644
index 00000000000..9a5b5cbf7c7
--- /dev/null
+++ b/gdb/testsuite/gdb.c++/ovldbreak.cc
@@ -0,0 +1,177 @@
+#include <stddef.h>
+
+class foo {
+public:
+ foo (int);
+ foo (int, const char *);
+ foo (foo&);
+ ~foo ();
+ void foofunc (int);
+ void foofunc (int, signed char *);
+ int ifoo;
+ const char *ccpfoo;
+
+int overload1arg (void);
+int overload1arg (char);
+int overload1arg (signed char);
+int overload1arg (unsigned char);
+int overload1arg (short);
+int overload1arg (unsigned short);
+int overload1arg (int);
+int overload1arg (unsigned int);
+int overload1arg (long);
+int overload1arg (unsigned long);
+int overload1arg (float);
+int overload1arg (double);
+
+int overloadargs (int a1);
+int overloadargs (int a1, int a2);
+int overloadargs (int a1, int a2, int a3);
+int overloadargs (int a1, int a2, int a3, int a4);
+int overloadargs (int a1, int a2, int a3, int a4, int a5);
+int overloadargs (int a1, int a2, int a3, int a4, int a5, int a6);
+int overloadargs (int a1, int a2, int a3, int a4, int a5, int a6, int a7);
+int overloadargs (int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8);
+int overloadargs (int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8, int a9);
+int overloadargs (int a1, int a2, int a3, int a4, int a5, int a6, int a7,
+ int a8, int a9, int a10);
+int overloadargs (int a1, int a2, int a3, int a4, int a5, int a6, int a7,
+ int a8, int a9, int a10, int a11);
+
+
+};
+
+void marker1()
+{}
+
+int main ()
+{
+ char arg2 = 2;
+ signed char arg3 =3;
+ unsigned char arg4 =4;
+ short arg5 =5;
+ unsigned short arg6 =6;
+ int arg7 =7;
+ unsigned int arg8 =8;
+ long arg9 =9;
+ unsigned long arg10 =10;
+ float arg11 =100.0;
+ double arg12 = 200.0;
+
+ char ch='A';
+ foo foo_instance1(111);
+ foo foo_instance2(222, &ch);
+ foo foo_instance3(foo_instance2);
+
+ foo_instance1.overload1arg();
+ foo_instance1.overload1arg(arg2);
+ foo_instance1.overload1arg(arg3);
+ foo_instance1.overload1arg(arg4);
+ foo_instance1.overload1arg(arg5);
+ foo_instance1.overload1arg(arg6);
+ foo_instance1.overload1arg(arg7);
+ foo_instance1.overload1arg(arg8);
+ foo_instance1.overload1arg(arg9);
+ foo_instance1.overload1arg(arg10);
+ foo_instance1.overload1arg(arg11);
+ foo_instance1.overload1arg(arg12);
+
+ foo_instance1.overloadargs(1);
+ foo_instance1.overloadargs(1, 2);
+ foo_instance1.overloadargs(1, 2, 3);
+ foo_instance1.overloadargs(1, 2, 3, 4);
+ foo_instance1.overloadargs(1, 2, 3, 4, 5);
+ foo_instance1.overloadargs(1, 2, 3, 4, 5, 6);
+ foo_instance1.overloadargs(1, 2, 3, 4, 5, 6, 7);
+ foo_instance1.overloadargs(1, 2, 3, 4, 5, 6, 7, 8);
+ foo_instance1.overloadargs(1, 2, 3, 4, 5, 6, 7, 8, 9);
+ foo_instance1.overloadargs(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
+ foo_instance1.overloadargs(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11);
+
+
+ #ifdef usestubs
+ set_debug_traps();
+ breakpoint();
+ #endif
+
+
+ marker1();
+ return 0;
+}
+
+foo::foo (int i) { ifoo = i;}
+foo::foo (int i, const char *ccp) { ifoo = i; ccpfoo = ccp; }
+foo::foo (foo& afoo) { ifoo = afoo.ifoo; ccpfoo = afoo.ccpfoo;}
+foo::~foo () {}
+
+
+/* Some functions to test overloading by varying one argument type. */
+
+int foo::overload1arg (void) { return 1; }
+int foo::overload1arg (char arg) { arg = 0; return 2;}
+int foo::overload1arg (signed char arg) { arg = 0; return 3;}
+int foo::overload1arg (unsigned char arg) { arg = 0; return 4;}
+int foo::overload1arg (short arg) { arg = 0; return 5;}
+int foo::overload1arg (unsigned short arg) { arg = 0; return 6;}
+int foo::overload1arg (int arg) { arg = 0; return 7;}
+int foo::overload1arg (unsigned int arg) { arg = 0; return 8;}
+int foo::overload1arg (long arg) { arg = 0; return 9;}
+int foo::overload1arg (unsigned long arg) { arg = 0; return 10;}
+int foo::overload1arg (float arg) { arg = 0; return 11;}
+int foo::overload1arg (double arg) { arg = 0; return 12;}
+
+
+/* Some functions to test overloading by varying argument count. */
+
+int foo::overloadargs (int a1)
+{ a1 = 0;
+return 1;}
+
+int foo::overloadargs (int a1, int a2)
+{ a1 = a2 = 0;
+return 2;}
+
+int foo::overloadargs (int a1, int a2, int a3)
+{ a1 = a2 = a3 = 0;
+return 3;}
+
+int foo::overloadargs (int a1, int a2, int a3, int a4)
+{ a1 = a2 = a3 = a4 = 0;
+return 4;}
+
+int foo::overloadargs (int a1, int a2, int a3, int a4, int a5)
+{ a1 = a2 = a3 = a4 = a5 = 0;
+return 5;}
+
+int foo::overloadargs (int a1, int a2, int a3, int a4, int a5, int a6)
+{ a1 = a2 = a3 = a4 = a5 = a6 = 0;
+return 6;}
+
+int foo::overloadargs (int a1, int a2, int a3, int a4, int a5, int a6, int a7)
+{ a1 = a2 = a3 = a4 = a5 = a6 = a7 = 0;
+return 7;}
+
+int foo::overloadargs (int a1, int a2, int a3, int a4, int a5, int a6, int a7,
+ int a8)
+{ a1 = a2 = a3 = a4 = a5 = a6 = a7 = a8 = 0;
+return 8;}
+
+int foo::overloadargs (int a1, int a2, int a3, int a4, int a5, int a6, int a7,
+ int a8, int a9)
+{
+ a1 = a2 = a3 = a4 = a5 = a6 = a7 = a8 = a9 = 0;
+ return 9;
+}
+
+int foo::overloadargs (int a1, int a2, int a3, int a4, int a5, int a6, int a7,
+ int a8, int a9, int a10)
+ { a1 = a2 = a3 = a4 = a5 = a6 = a7 = a8 = a9 =
+ a10 = 0; return 10;}
+
+int foo::overloadargs (int a1, int a2, int a3, int a4, int a5, int a6, int a7,
+ int a8, int a9, int a10, int a11)
+ { a1 = a2 = a3 = a4 = a5 = a6 = a7 = a8 = a9 =
+ a10 = a11 = 0; return 11;}
+
+
+
diff --git a/gdb/testsuite/gdb.c++/ovldbreak.exp b/gdb/testsuite/gdb.c++/ovldbreak.exp
new file mode 100644
index 00000000000..c90b51d6be3
--- /dev/null
+++ b/gdb/testsuite/gdb.c++/ovldbreak.exp
@@ -0,0 +1,680 @@
+# Copyright (C) 1998 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# written by Elena Zannoni (ezannoni@cygnus.com)
+
+# This file is part of the gdb testsuite
+#
+# tests for overloaded member functions. Set breakpoints on
+# overloaded member functions
+#
+
+
+if $tracelevel then {
+ strace $tracelevel
+ }
+
+#
+# test running programs
+#
+set prms_id 0
+set bug_id 0
+
+set testfile "ovldbreak"
+set srcfile ${testfile}.cc
+set binfile ${objdir}/${subdir}/${testfile}
+
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug c++}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+# set it up at a breakpoint so we can play with the variable values
+#
+if ![runto_main] then {
+ perror "couldn't run to breakpoint"
+ continue
+}
+
+
+
+send_gdb "break foo::overload1arg\n"
+gdb_expect {
+-re "\\\[0\\\] cancel\r\n\\\[1\\\] all\r\n\\\[2\\\] foo::overload1arg\\(double\\) at.*$srcfile:121\r\n\\\[3\\\] foo::overload1arg\\(float\\) at.*$srcfile:120\r\n\\\[4\\\] foo::overload1arg\\(unsigned long\\) at.*$srcfile:119\r\n\\\[5\\\] foo::overload1arg\\(long\\) at.*$srcfile:118\r\n\\\[6\\\] foo::overload1arg\\(unsigned int\\) at.*$srcfile:117\r\n\\\[7\\\] foo::overload1arg\\(int\\) at.*$srcfile:116\r\n\\\[8\\\] foo::overload1arg\\(unsigned short\\) at.*$srcfile:115\r\n\\\[9\\\] foo::overload1arg\\(short\\) at.*$srcfile:114\r\n\\\[10\\\] foo::overload1arg\\(unsigned char\\) at.*$srcfile:113\r\n\\\[11\\\] foo::overload1arg\\(signed char\\) at.*$srcfile:112\r\n\\\[12\\\] foo::overload1arg\\(char\\) at.*$srcfile:111\r\n\\\[13\\\] foo::overload1arg\\(void\\) at.*$srcfile:110\r\n> $" {
+ send_gdb "12\n"
+ gdb_expect {
+ -re "Breakpoint 2 at $hex: file.*$srcfile, line 111.\r\n$gdb_prompt $" {
+ pass "set bp on overload1arg(char)" }
+ -re ".*$gdb_prompt $" {
+ fail "set bp on overload1arg(char) wrong bp reply" }
+ timeout {
+ fail "(timeout)set bp on overload1arg(char) wrong bp reply" }
+ }
+ }
+ -re ".*$gdb_prompt $" { fail "set bp on overload1arg(char)(wrong menu)" }
+ timeout { fail "(timeout)set bp on overload1arg(char)(wrong menu)" }
+ }
+
+
+gdb_test "info break" \
+ "Num Type\[\t \]+Disp Enb Address\[\t \]+What.*
+\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex in main at.*$srcfile:49\r
+\[\t \]+breakpoint already hit 1 time\r
+\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex in foo::overload1arg\\(char\\) at.*$srcfile:111" \
+ "breakpoint info"
+
+
+send_gdb "break foo::overload1arg\n"
+gdb_expect {
+-re "\\\[0\\\] cancel\r\n\\\[1\\\] all\r\n\\\[2\\\] foo::overload1arg\\(double\\) at.*$srcfile:121\r\n\\\[3\\\] foo::overload1arg\\(float\\) at.*$srcfile:120\r\n\\\[4\\\] foo::overload1arg\\(unsigned long\\) at.*$srcfile:119\r\n\\\[5\\\] foo::overload1arg\\(long\\) at.*$srcfile:118\r\n\\\[6\\\] foo::overload1arg\\(unsigned int\\) at.*$srcfile:117\r\n\\\[7\\\] foo::overload1arg\\(int\\) at.*$srcfile:116\r\n\\\[8\\\] foo::overload1arg\\(unsigned short\\) at.*$srcfile:115\r\n\\\[9\\\] foo::overload1arg\\(short\\) at.*$srcfile:114\r\n\\\[10\\\] foo::overload1arg\\(unsigned char\\) at.*$srcfile:113\r\n\\\[11\\\] foo::overload1arg\\(signed char\\) at.*$srcfile:112\r\n\\\[12\\\] foo::overload1arg\\(char\\) at.*$srcfile:111\r\n\\\[13\\\] foo::overload1arg\\(void\\) at.*$srcfile:110\r\n> $" {
+ send_gdb "11\n"
+ gdb_expect {
+ -re "Breakpoint 3 at $hex: file.*$srcfile, line 112.\r\n$gdb_prompt $" {
+ pass "set bp on overload1arg(signed char)" }
+ -re ".*$gdb_prompt $" {
+ fail "set bp on overload1arg(signed char) wrong bp reply" }
+ timeout {
+ fail "(timeout)set bp on overload1arg(signed char) wrong bp reply" }
+ }
+ }
+ -re ".*$gdb_prompt $" { fail "set bp on overload1arg(signed char)(wrong menu)" }
+ timeout { fail "(timeout)set bp on overload1arg(signed char)(wrong menu)" }
+ }
+
+
+gdb_test "info break" \
+ "Num Type\[\t \]+Disp Enb Address\[\t \]+What.*
+\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex in main at.*$srcfile:49\r
+\[\t \]+breakpoint already hit 1 time\r
+\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex in foo::overload1arg\\(char\\) at.*$srcfile:111\r
+\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex in foo::overload1arg\\(signed char\\) at.*$srcfile:112" \
+ "breakpoint info"
+
+
+
+
+
+send_gdb "break foo::overload1arg\n"
+gdb_expect {
+-re "\\\[0\\\] cancel\r\n\\\[1\\\] all\r\n\\\[2\\\] foo::overload1arg\\(double\\) at.*$srcfile:121\r\n\\\[3\\\] foo::overload1arg\\(float\\) at.*$srcfile:120\r\n\\\[4\\\] foo::overload1arg\\(unsigned long\\) at.*$srcfile:119\r\n\\\[5\\\] foo::overload1arg\\(long\\) at.*$srcfile:118\r\n\\\[6\\\] foo::overload1arg\\(unsigned int\\) at.*$srcfile:117\r\n\\\[7\\\] foo::overload1arg\\(int\\) at.*$srcfile:116\r\n\\\[8\\\] foo::overload1arg\\(unsigned short\\) at.*$srcfile:115\r\n\\\[9\\\] foo::overload1arg\\(short\\) at.*$srcfile:114\r\n\\\[10\\\] foo::overload1arg\\(unsigned char\\) at.*$srcfile:113\r\n\\\[11\\\] foo::overload1arg\\(signed char\\) at.*$srcfile:112\r\n\\\[12\\\] foo::overload1arg\\(char\\) at.*$srcfile:111\r\n\\\[13\\\] foo::overload1arg\\(void\\) at.*$srcfile:110\r\n> $" {
+ send_gdb "10\n"
+ gdb_expect {
+ -re "Breakpoint 4 at $hex: file.*$srcfile, line 113.\r\n$gdb_prompt $" {
+ pass "set bp on overload1arg(unsigned char)" }
+ -re ".*$gdb_prompt $" {
+ fail "set bp on overload1arg(unsigned char) wrong bp reply" }
+ timeout {
+ fail "(timeout)set bp on overload1arg(unsigned char) wrong bp reply" }
+ }
+ }
+ -re ".*$gdb_prompt $" { fail "set bp on overload1arg(unsigned char)(wrong menu)" }
+ timeout { fail "(timeout)set bp on overload1arg(unsigned char)(wrong menu)" }
+ }
+
+
+
+gdb_test "info break" \
+ "Num Type\[\t \]+Disp Enb Address\[\t \]+What.*
+\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex in main at.*$srcfile:49\r
+\[\t \]+breakpoint already hit 1 time\r
+\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex in foo::overload1arg\\(char\\) at.*$srcfile:111\r
+\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex in foo::overload1arg\\(signed char\\) at.*$srcfile:112\r
+\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex in foo::overload1arg\\(unsigned char\\) at.*$srcfile:113" \
+ "breakpoint info"
+
+
+
+send_gdb "break foo::overload1arg\n"
+gdb_expect {
+-re "\\\[0\\\] cancel\r\n\\\[1\\\] all\r\n\\\[2\\\] foo::overload1arg\\(double\\) at.*$srcfile:121\r\n\\\[3\\\] foo::overload1arg\\(float\\) at.*$srcfile:120\r\n\\\[4\\\] foo::overload1arg\\(unsigned long\\) at.*$srcfile:119\r\n\\\[5\\\] foo::overload1arg\\(long\\) at.*$srcfile:118\r\n\\\[6\\\] foo::overload1arg\\(unsigned int\\) at.*$srcfile:117\r\n\\\[7\\\] foo::overload1arg\\(int\\) at.*$srcfile:116\r\n\\\[8\\\] foo::overload1arg\\(unsigned short\\) at.*$srcfile:115\r\n\\\[9\\\] foo::overload1arg\\(short\\) at.*$srcfile:114\r\n\\\[10\\\] foo::overload1arg\\(unsigned char\\) at.*$srcfile:113\r\n\\\[11\\\] foo::overload1arg\\(signed char\\) at.*$srcfile:112\r\n\\\[12\\\] foo::overload1arg\\(char\\) at.*$srcfile:111\r\n\\\[13\\\] foo::overload1arg\\(void\\) at.*$srcfile:110\r\n> $" {
+ send_gdb "9\n"
+ gdb_expect {
+ -re "Breakpoint 5 at $hex: file.*$srcfile, line 114.\r\n$gdb_prompt $" {
+ pass "set bp on overload1arg(short)" }
+ -re ".*$gdb_prompt $" {
+ fail "set bp on overload1arg(short) wrong bp reply" }
+ timeout {
+ fail "(timeout)set bp on overload1arg(short) wrong bp reply" }
+ }
+ }
+ -re ".*$gdb_prompt $" { fail "set bp on overload1arg(short)(wrong menu)" }
+ timeout { fail "(timeout)set bp on overload1arg(short)(wrong menu)" }
+ }
+
+
+gdb_test "info break" \
+ "Num Type\[\t \]+Disp Enb Address\[\t \]+What.*
+\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex in main at.*$srcfile:49\r
+\[\t \]+breakpoint already hit 1 time\r
+\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex in foo::overload1arg\\(char\\) at.*$srcfile:111\r
+\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex in foo::overload1arg\\(signed char\\) at.*$srcfile:112\r
+\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex in foo::overload1arg\\(unsigned char\\) at.*$srcfile:113\r
+\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex in foo::overload1arg\\(short\\) at.*$srcfile:114" \
+ "breakpoint info"
+
+
+
+send_gdb "break foo::overload1arg\n"
+gdb_expect {
+-re "\\\[0\\\] cancel\r\n\\\[1\\\] all\r\n\\\[2\\\] foo::overload1arg\\(double\\) at.*$srcfile:121\r\n\\\[3\\\] foo::overload1arg\\(float\\) at.*$srcfile:120\r\n\\\[4\\\] foo::overload1arg\\(unsigned long\\) at.*$srcfile:119\r\n\\\[5\\\] foo::overload1arg\\(long\\) at.*$srcfile:118\r\n\\\[6\\\] foo::overload1arg\\(unsigned int\\) at.*$srcfile:117\r\n\\\[7\\\] foo::overload1arg\\(int\\) at.*$srcfile:116\r\n\\\[8\\\] foo::overload1arg\\(unsigned short\\) at.*$srcfile:115\r\n\\\[9\\\] foo::overload1arg\\(short\\) at.*$srcfile:114\r\n\\\[10\\\] foo::overload1arg\\(unsigned char\\) at.*$srcfile:113\r\n\\\[11\\\] foo::overload1arg\\(signed char\\) at.*$srcfile:112\r\n\\\[12\\\] foo::overload1arg\\(char\\) at.*$srcfile:111\r\n\\\[13\\\] foo::overload1arg\\(void\\) at.*$srcfile:110\r\n> $" {
+ send_gdb "8\n"
+ gdb_expect {
+ -re "Breakpoint 6 at $hex: file.*$srcfile, line 115.\r\n$gdb_prompt $" {
+ pass "set bp on overload1arg(unsigned short)" }
+ -re ".*$gdb_prompt $" {
+ fail "set bp on overload1arg(unsigned short) wrong bp reply" }
+ timeout {
+ fail "(timeout)set bp on overload1arg(unsigned short) wrong bp reply" }
+ }
+ }
+ -re ".*$gdb_prompt $" { fail "set bp on overload1arg(unsigned short)(wrong menu)" }
+ timeout { fail "(timeout)set bp on overload1arg(unsigned short)(wrong menu)" }
+ }
+
+
+gdb_test "info break" \
+ "Num Type\[\t \]+Disp Enb Address\[\t \]+What.*
+\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex in main at.*$srcfile:49\r
+\[\t \]+breakpoint already hit 1 time\r
+\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex in foo::overload1arg\\(char\\) at.*$srcfile:111\r
+\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex in foo::overload1arg\\(signed char\\) at.*$srcfile:112\r
+\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex in foo::overload1arg\\(unsigned char\\) at.*$srcfile:113\r
+\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex in foo::overload1arg\\(short\\) at.*$srcfile:114\r
+\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex in foo::overload1arg\\(unsigned short\\) at.*$srcfile:115" \
+ "breakpoint info"
+
+
+
+send_gdb "break foo::overload1arg\n"
+gdb_expect {
+-re "\\\[0\\\] cancel\r\n\\\[1\\\] all\r\n\\\[2\\\] foo::overload1arg\\(double\\) at.*$srcfile:121\r\n\\\[3\\\] foo::overload1arg\\(float\\) at.*$srcfile:120\r\n\\\[4\\\] foo::overload1arg\\(unsigned long\\) at.*$srcfile:119\r\n\\\[5\\\] foo::overload1arg\\(long\\) at.*$srcfile:118\r\n\\\[6\\\] foo::overload1arg\\(unsigned int\\) at.*$srcfile:117\r\n\\\[7\\\] foo::overload1arg\\(int\\) at.*$srcfile:116\r\n\\\[8\\\] foo::overload1arg\\(unsigned short\\) at.*$srcfile:115\r\n\\\[9\\\] foo::overload1arg\\(short\\) at.*$srcfile:114\r\n\\\[10\\\] foo::overload1arg\\(unsigned char\\) at.*$srcfile:113\r\n\\\[11\\\] foo::overload1arg\\(signed char\\) at.*$srcfile:112\r\n\\\[12\\\] foo::overload1arg\\(char\\) at.*$srcfile:111\r\n\\\[13\\\] foo::overload1arg\\(void\\) at.*$srcfile:110\r\n> $" {
+ send_gdb "7\n"
+ gdb_expect {
+ -re "Breakpoint 7 at $hex: file.*$srcfile, line 116.\r\n$gdb_prompt $" {
+ pass "set bp on overload1arg(int)" }
+ -re ".*$gdb_prompt $" {
+ fail "set bp on overload1arg(int) wrong bp reply" }
+ timeout {
+ fail "(timeout)set bp on overload1arg(int) wrong bp reply" }
+ }
+ }
+ -re ".*$gdb_prompt $" { fail "set bp on overload1arg(int)(wrong menu)" }
+ timeout { fail "(timeout)set bp on overload1arg(int)(wrong menu)" }
+ }
+
+
+gdb_test "info break" \
+ "Num Type\[\t \]+Disp Enb Address\[\t \]+What.*
+\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex in main at.*$srcfile:49\r
+\[\t \]+breakpoint already hit 1 time\r
+\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex in foo::overload1arg\\(char\\) at.*$srcfile:111\r
+\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex in foo::overload1arg\\(signed char\\) at.*$srcfile:112\r
+\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex in foo::overload1arg\\(unsigned char\\) at.*$srcfile:113\r
+\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex in foo::overload1arg\\(short\\) at.*$srcfile:114\r
+\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex in foo::overload1arg\\(unsigned short\\) at.*$srcfile:115\r
+\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex in foo::overload1arg\\(int\\) at.*$srcfile:116" \
+ "breakpoint info"
+
+
+
+send_gdb "break foo::overload1arg\n"
+gdb_expect {
+-re "\\\[0\\\] cancel\r\n\\\[1\\\] all\r\n\\\[2\\\] foo::overload1arg\\(double\\) at.*$srcfile:121\r\n\\\[3\\\] foo::overload1arg\\(float\\) at.*$srcfile:120\r\n\\\[4\\\] foo::overload1arg\\(unsigned long\\) at.*$srcfile:119\r\n\\\[5\\\] foo::overload1arg\\(long\\) at.*$srcfile:118\r\n\\\[6\\\] foo::overload1arg\\(unsigned int\\) at.*$srcfile:117\r\n\\\[7\\\] foo::overload1arg\\(int\\) at.*$srcfile:116\r\n\\\[8\\\] foo::overload1arg\\(unsigned short\\) at.*$srcfile:115\r\n\\\[9\\\] foo::overload1arg\\(short\\) at.*$srcfile:114\r\n\\\[10\\\] foo::overload1arg\\(unsigned char\\) at.*$srcfile:113\r\n\\\[11\\\] foo::overload1arg\\(signed char\\) at.*$srcfile:112\r\n\\\[12\\\] foo::overload1arg\\(char\\) at.*$srcfile:111\r\n\\\[13\\\] foo::overload1arg\\(void\\) at.*$srcfile:110\r\n> $" {
+ send_gdb "6\n"
+ gdb_expect {
+ -re "Breakpoint 8 at $hex: file.*$srcfile, line 117.\r\n$gdb_prompt $" {
+ pass "set bp on overload1arg(unsigned int)" }
+ -re ".*$gdb_prompt $" {
+ fail "set bp on overload1arg(unsigned int) wrong bp reply" }
+ timeout {
+ fail "(timeout)set bp on overload1arg(unsigned int) wrong bp reply" }
+ }
+ }
+ -re ".*$gdb_prompt $" { fail "set bp on overload1arg(unsigned int)(wrong menu)" }
+ timeout { fail "(timeout)set bp on overload1arg(unsigned int)(wrong menu)" }
+ }
+
+
+gdb_test "info break" \
+ "Num Type\[\t \]+Disp Enb Address\[\t \]+What.*
+\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex in main at.*$srcfile:49\r
+\[\t \]+breakpoint already hit 1 time\r
+\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex in foo::overload1arg\\(char\\) at.*$srcfile:111\r
+\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex in foo::overload1arg\\(signed char\\) at.*$srcfile:112\r
+\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex in foo::overload1arg\\(unsigned char\\) at.*$srcfile:113\r
+\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex in foo::overload1arg\\(short\\) at.*$srcfile:114\r
+\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex in foo::overload1arg\\(unsigned short\\) at.*$srcfile:115\r
+\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex in foo::overload1arg\\(int\\) at.*$srcfile:116\r
+\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex in foo::overload1arg\\(unsigned int\\) at.*$srcfile:117" \
+ "breakpoint info"
+
+
+
+send_gdb "break foo::overload1arg\n"
+gdb_expect {
+-re "\\\[0\\\] cancel\r\n\\\[1\\\] all\r\n\\\[2\\\] foo::overload1arg\\(double\\) at.*$srcfile:121\r\n\\\[3\\\] foo::overload1arg\\(float\\) at.*$srcfile:120\r\n\\\[4\\\] foo::overload1arg\\(unsigned long\\) at.*$srcfile:119\r\n\\\[5\\\] foo::overload1arg\\(long\\) at.*$srcfile:118\r\n\\\[6\\\] foo::overload1arg\\(unsigned int\\) at.*$srcfile:117\r\n\\\[7\\\] foo::overload1arg\\(int\\) at.*$srcfile:116\r\n\\\[8\\\] foo::overload1arg\\(unsigned short\\) at.*$srcfile:115\r\n\\\[9\\\] foo::overload1arg\\(short\\) at.*$srcfile:114\r\n\\\[10\\\] foo::overload1arg\\(unsigned char\\) at.*$srcfile:113\r\n\\\[11\\\] foo::overload1arg\\(signed char\\) at.*$srcfile:112\r\n\\\[12\\\] foo::overload1arg\\(char\\) at.*$srcfile:111\r\n\\\[13\\\] foo::overload1arg\\(void\\) at.*$srcfile:110\r\n> $" {
+ send_gdb "5\n"
+ gdb_expect {
+ -re "Breakpoint 9 at $hex: file.*$srcfile, line 118.\r\n$gdb_prompt $" {
+ pass "set bp on overload1arg(long)" }
+ -re ".*$gdb_prompt $" {
+ fail "set bp on overload1arg(long) wrong bp reply" }
+ timeout {
+ fail "(timeout)set bp on overload1arg(long) wrong bp reply" }
+ }
+ }
+ -re ".*$gdb_prompt $" { fail "set bp on overload1arg(long)(wrong menu)" }
+ timeout { fail "(timeout)set bp on overload1arg(long)(wrong menu)" }
+ }
+
+
+gdb_test "info break" \
+ "Num Type\[\t \]+Disp Enb Address\[\t \]+What.*
+\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex in main at.*$srcfile:49\r
+\[\t \]+breakpoint already hit 1 time\r
+\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex in foo::overload1arg\\(char\\) at.*$srcfile:111\r
+\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex in foo::overload1arg\\(signed char\\) at.*$srcfile:112\r
+\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex in foo::overload1arg\\(unsigned char\\) at.*$srcfile:113\r
+\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex in foo::overload1arg\\(short\\) at.*$srcfile:114\r
+\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex in foo::overload1arg\\(unsigned short\\) at.*$srcfile:115\r
+\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex in foo::overload1arg\\(int\\) at.*$srcfile:116\r
+\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex in foo::overload1arg\\(unsigned int\\) at.*$srcfile:117\r
+\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex in foo::overload1arg\\(long\\) at.*$srcfile:118" \
+ "breakpoint info"
+
+
+
+send_gdb "break foo::overload1arg\n"
+gdb_expect {
+-re "\\\[0\\\] cancel\r\n\\\[1\\\] all\r\n\\\[2\\\] foo::overload1arg\\(double\\) at.*$srcfile:121\r\n\\\[3\\\] foo::overload1arg\\(float\\) at.*$srcfile:120\r\n\\\[4\\\] foo::overload1arg\\(unsigned long\\) at.*$srcfile:119\r\n\\\[5\\\] foo::overload1arg\\(long\\) at.*$srcfile:118\r\n\\\[6\\\] foo::overload1arg\\(unsigned int\\) at.*$srcfile:117\r\n\\\[7\\\] foo::overload1arg\\(int\\) at.*$srcfile:116\r\n\\\[8\\\] foo::overload1arg\\(unsigned short\\) at.*$srcfile:115\r\n\\\[9\\\] foo::overload1arg\\(short\\) at.*$srcfile:114\r\n\\\[10\\\] foo::overload1arg\\(unsigned char\\) at.*$srcfile:113\r\n\\\[11\\\] foo::overload1arg\\(signed char\\) at.*$srcfile:112\r\n\\\[12\\\] foo::overload1arg\\(char\\) at.*$srcfile:111\r\n\\\[13\\\] foo::overload1arg\\(void\\) at.*$srcfile:110\r\n> $" {
+ send_gdb "4\n"
+ gdb_expect {
+ -re "Breakpoint 10 at $hex: file.*$srcfile, line 119.\r\n$gdb_prompt $" {
+ pass "set bp on overload1arg(unsigned long)" }
+ -re ".*$gdb_prompt $" {
+ fail "set bp on overload1arg(unsigned long) wrong bp reply" }
+ timeout {
+ fail "(timeout)set bp on overload1arg(unsigned long) wrong bp reply" }
+ }
+ }
+ -re ".*$gdb_prompt $" { fail "set bp on overload1arg(unsigned long)(wrong menu)" }
+ timeout { fail "(timeout)set bp on overload1arg(unsigned long)(wrong menu)" }
+ }
+
+
+gdb_test "info break" \
+ "Num Type\[\t \]+Disp Enb Address\[\t \]+What.*
+\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex in main at.*$srcfile:49\r
+\[\t \]+breakpoint already hit 1 time\r
+\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex in foo::overload1arg\\(char\\) at.*$srcfile:111\r
+\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex in foo::overload1arg\\(signed char\\) at.*$srcfile:112\r
+\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex in foo::overload1arg\\(unsigned char\\) at.*$srcfile:113\r
+\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex in foo::overload1arg\\(short\\) at.*$srcfile:114\r
+\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex in foo::overload1arg\\(unsigned short\\) at.*$srcfile:115\r
+\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex in foo::overload1arg\\(int\\) at.*$srcfile:116\r
+\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex in foo::overload1arg\\(unsigned int\\) at.*$srcfile:117\r
+\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex in foo::overload1arg\\(long\\) at.*$srcfile:118\r
+\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex in foo::overload1arg\\(unsigned long\\) at.*$srcfile:119" \
+ "breakpoint info"
+
+
+send_gdb "break foo::overload1arg\n"
+gdb_expect {
+-re "\\\[0\\\] cancel\r\n\\\[1\\\] all\r\n\\\[2\\\] foo::overload1arg\\(double\\) at.*$srcfile:121\r\n\\\[3\\\] foo::overload1arg\\(float\\) at.*$srcfile:120\r\n\\\[4\\\] foo::overload1arg\\(unsigned long\\) at.*$srcfile:119\r\n\\\[5\\\] foo::overload1arg\\(long\\) at.*$srcfile:118\r\n\\\[6\\\] foo::overload1arg\\(unsigned int\\) at.*$srcfile:117\r\n\\\[7\\\] foo::overload1arg\\(int\\) at.*$srcfile:116\r\n\\\[8\\\] foo::overload1arg\\(unsigned short\\) at.*$srcfile:115\r\n\\\[9\\\] foo::overload1arg\\(short\\) at.*$srcfile:114\r\n\\\[10\\\] foo::overload1arg\\(unsigned char\\) at.*$srcfile:113\r\n\\\[11\\\] foo::overload1arg\\(signed char\\) at.*$srcfile:112\r\n\\\[12\\\] foo::overload1arg\\(char\\) at.*$srcfile:111\r\n\\\[13\\\] foo::overload1arg\\(void\\) at.*$srcfile:110\r\n> $" {
+ send_gdb "3\n"
+ gdb_expect {
+ -re "Breakpoint 11 at $hex: file.*$srcfile, line 120.\r\n$gdb_prompt $" {
+ pass "set bp on overload1arg(float)" }
+ -re ".*$gdb_prompt $" {
+ fail "set bp on overload1arg(float) wrong bp reply" }
+ timeout {
+ fail "(timeout)set bp on overload1arg(float) wrong bp reply" }
+ }
+ }
+ -re ".*$gdb_prompt $" { fail "set bp on overload1arg(float)(wrong menu)" }
+ timeout { fail "(timeout)set bp on overload1arg(float)(wrong menu)" }
+ }
+
+gdb_test "info break" \
+ "Num Type\[\t \]+Disp Enb Address\[\t \]+What.*
+\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex in main at.*$srcfile:49\r
+\[\t \]+breakpoint already hit 1 time\r
+\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex in foo::overload1arg\\(char\\) at.*$srcfile:111\r
+\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex in foo::overload1arg\\(signed char\\) at.*$srcfile:112\r
+\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex in foo::overload1arg\\(unsigned char\\) at.*$srcfile:113\r
+\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex in foo::overload1arg\\(short\\) at.*$srcfile:114\r
+\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex in foo::overload1arg\\(unsigned short\\) at.*$srcfile:115\r
+\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex in foo::overload1arg\\(int\\) at.*$srcfile:116\r
+\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex in foo::overload1arg\\(unsigned int\\) at.*$srcfile:117\r
+\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex in foo::overload1arg\\(long\\) at.*$srcfile:118\r
+\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex in foo::overload1arg\\(unsigned long\\) at.*$srcfile:119\r
+\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex in foo::overload1arg\\(float\\) at.*$srcfile:120" \
+ "breakpoint info"
+
+
+
+send_gdb "break foo::overload1arg\n"
+gdb_expect {
+-re "\\\[0\\\] cancel\r\n\\\[1\\\] all\r\n\\\[2\\\] foo::overload1arg\\(double\\) at.*$srcfile:121\r\n\\\[3\\\] foo::overload1arg\\(float\\) at.*$srcfile:120\r\n\\\[4\\\] foo::overload1arg\\(unsigned long\\) at.*$srcfile:119\r\n\\\[5\\\] foo::overload1arg\\(long\\) at.*$srcfile:118\r\n\\\[6\\\] foo::overload1arg\\(unsigned int\\) at.*$srcfile:117\r\n\\\[7\\\] foo::overload1arg\\(int\\) at.*$srcfile:116\r\n\\\[8\\\] foo::overload1arg\\(unsigned short\\) at.*$srcfile:115\r\n\\\[9\\\] foo::overload1arg\\(short\\) at.*$srcfile:114\r\n\\\[10\\\] foo::overload1arg\\(unsigned char\\) at.*$srcfile:113\r\n\\\[11\\\] foo::overload1arg\\(signed char\\) at.*$srcfile:112\r\n\\\[12\\\] foo::overload1arg\\(char\\) at.*$srcfile:111\r\n\\\[13\\\] foo::overload1arg\\(void\\) at.*$srcfile:110\r\n> $" {
+ send_gdb "2\n"
+ gdb_expect {
+ -re "Breakpoint 12 at $hex: file.*$srcfile, line 121.\r\n$gdb_prompt $" {
+ pass "set bp on overload1arg(double)" }
+ -re ".*$gdb_prompt $" {
+ fail "set bp on overload1arg(double) wrong bp reply" }
+ timeout {
+ fail "(timeout)set bp on overload1arg(double) wrong bp reply" }
+ }
+ }
+ -re ".*$gdb_prompt $" { fail "set bp on overload1arg(double)(wrong menu)" }
+ timeout { fail "(timeout)set bp on overload1arg(double)(wrong menu)" }
+ }
+
+
+gdb_test "info break" \
+ "Num Type\[\t \]+Disp Enb Address\[\t \]+What.*
+\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex in main at.*$srcfile:49\r
+\[\t \]+breakpoint already hit 1 time\r
+\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex in foo::overload1arg\\(char\\) at.*$srcfile:111\r
+\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex in foo::overload1arg\\(signed char\\) at.*$srcfile:112\r
+\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex in foo::overload1arg\\(unsigned char\\) at.*$srcfile:113\r
+\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex in foo::overload1arg\\(short\\) at.*$srcfile:114\r
+\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex in foo::overload1arg\\(unsigned short\\) at.*$srcfile:115\r
+\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex in foo::overload1arg\\(int\\) at.*$srcfile:116\r
+\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex in foo::overload1arg\\(unsigned int\\) at.*$srcfile:117\r
+\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex in foo::overload1arg\\(long\\) at.*$srcfile:118\r
+\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex in foo::overload1arg\\(unsigned long\\) at.*$srcfile:119\r
+\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex in foo::overload1arg\\(float\\) at.*$srcfile:120\r
+\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex in foo::overload1arg\\(double\\) at.*$srcfile:121" \
+ "breakpoint info"
+
+
+
+send_gdb "break foo::overload1arg\n"
+gdb_expect {
+-re "\\\[0\\\] cancel\r\n\\\[1\\\] all\r\n\\\[2\\\] foo::overload1arg\\(double\\) at.*$srcfile:121\r\n\\\[3\\\] foo::overload1arg\\(float\\) at.*$srcfile:120\r\n\\\[4\\\] foo::overload1arg\\(unsigned long\\) at.*$srcfile:119\r\n\\\[5\\\] foo::overload1arg\\(long\\) at.*$srcfile:118\r\n\\\[6\\\] foo::overload1arg\\(unsigned int\\) at.*$srcfile:117\r\n\\\[7\\\] foo::overload1arg\\(int\\) at.*$srcfile:116\r\n\\\[8\\\] foo::overload1arg\\(unsigned short\\) at.*$srcfile:115\r\n\\\[9\\\] foo::overload1arg\\(short\\) at.*$srcfile:114\r\n\\\[10\\\] foo::overload1arg\\(unsigned char\\) at.*$srcfile:113\r\n\\\[11\\\] foo::overload1arg\\(signed char\\) at.*$srcfile:112\r\n\\\[12\\\] foo::overload1arg\\(char\\) at.*$srcfile:111\r\n\\\[13\\\] foo::overload1arg\\(void\\) at.*$srcfile:110\r\n> $" {
+ send_gdb "13\n"
+ gdb_expect {
+ -re "Breakpoint 13 at $hex: file.*$srcfile, line 110.\r\n$gdb_prompt $" {
+ pass "set bp on overload1arg(void)" }
+ -re ".*$gdb_prompt $" {
+ fail "set bp on overload1arg(void) wrong bp reply" }
+ timeout {
+ fail "(timeout)set bp on overload1arg(void) wrong bp reply" }
+ }
+ }
+ -re ".*$gdb_prompt $" { fail "set bp on overload1arg(void)(wrong menu)" }
+ timeout { fail "(timeout)set bp on overload1arg(void)(wrong menu)" }
+ }
+
+
+gdb_test "info break" \
+ "Num Type\[\t \]+Disp Enb Address\[\t \]+What.*
+\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex in main at.*$srcfile:49\r
+\[\t \]+breakpoint already hit 1 time\r
+\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex in foo::overload1arg\\(char\\) at.*$srcfile:111\r
+\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex in foo::overload1arg\\(signed char\\) at.*$srcfile:112\r
+\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex in foo::overload1arg\\(unsigned char\\) at.*$srcfile:113\r
+\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex in foo::overload1arg\\(short\\) at.*$srcfile:114\r
+\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex in foo::overload1arg\\(unsigned short\\) at.*$srcfile:115\r
+\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex in foo::overload1arg\\(int\\) at.*$srcfile:116\r
+\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex in foo::overload1arg\\(unsigned int\\) at.*$srcfile:117\r
+\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex in foo::overload1arg\\(long\\) at.*$srcfile:118\r
+\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex in foo::overload1arg\\(unsigned long\\) at.*$srcfile:119\r
+\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex in foo::overload1arg\\(float\\) at.*$srcfile:120\r
+\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex in foo::overload1arg\\(double\\) at.*$srcfile:121\r
+\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex in foo::overload1arg\\(void\\) at.*$srcfile:110" \
+ "breakpoint info"
+
+
+
+
+send_gdb "break foo::overload1arg\n"
+gdb_expect {
+-re "\\\[0\\\] cancel\r\n\\\[1\\\] all\r\n\\\[2\\\] foo::overload1arg\\(double\\) at.*$srcfile:121\r\n\\\[3\\\] foo::overload1arg\\(float\\) at.*$srcfile:120\r\n\\\[4\\\] foo::overload1arg\\(unsigned long\\) at.*$srcfile:119\r\n\\\[5\\\] foo::overload1arg\\(long\\) at.*$srcfile:118\r\n\\\[6\\\] foo::overload1arg\\(unsigned int\\) at.*$srcfile:117\r\n\\\[7\\\] foo::overload1arg\\(int\\) at.*$srcfile:116\r\n\\\[8\\\] foo::overload1arg\\(unsigned short\\) at.*$srcfile:115\r\n\\\[9\\\] foo::overload1arg\\(short\\) at.*$srcfile:114\r\n\\\[10\\\] foo::overload1arg\\(unsigned char\\) at.*$srcfile:113\r\n\\\[11\\\] foo::overload1arg\\(signed char\\) at.*$srcfile:112\r\n\\\[12\\\] foo::overload1arg\\(char\\) at.*$srcfile:111\r\n\\\[13\\\] foo::overload1arg\\(void\\) at.*$srcfile:110\r\n> $" {
+ send_gdb "0\n"
+ gdb_expect {
+ -re "cancelled\r\n$gdb_prompt $" {
+ pass "set bp cancelled" }
+ -re ".*$gdb_prompt $" {
+ fail "set bp cancelled wrong bp reply" }
+ timeout {
+ fail "(timeout)set bp cancelled wrong bp reply" }
+ }
+ }
+ -re ".*$gdb_prompt $" { fail "set bp cancelled(wrong menu)" }
+ timeout { fail "(timeout)set bp cancelled(wrong menu)" }
+ }
+
+
+
+
+gdb_test "info break" \
+ "Num Type\[\t \]+Disp Enb Address\[\t \]+What.*
+\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex in main at.*$srcfile:49\r
+\[\t \]+breakpoint already hit 1 time\r
+\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex in foo::overload1arg\\(char\\) at.*$srcfile:111\r
+\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex in foo::overload1arg\\(signed char\\) at.*$srcfile:112\r
+\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex in foo::overload1arg\\(unsigned char\\) at.*$srcfile:113\r
+\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex in foo::overload1arg\\(short\\) at.*$srcfile:114\r
+\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex in foo::overload1arg\\(unsigned short\\) at.*$srcfile:115\r
+\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex in foo::overload1arg\\(int\\) at.*$srcfile:116\r
+\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex in foo::overload1arg\\(unsigned int\\) at.*$srcfile:117\r
+\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex in foo::overload1arg\\(long\\) at.*$srcfile:118\r
+\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex in foo::overload1arg\\(unsigned long\\) at.*$srcfile:119\r
+\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex in foo::overload1arg\\(float\\) at.*$srcfile:120\r
+\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex in foo::overload1arg\\(double\\) at.*$srcfile:121\r
+\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex in foo::overload1arg\\(void\\) at.*$srcfile:110" \
+ "breakpoint info"
+
+
+
+
+
+send_gdb "delete breakpoints\n"
+gdb_expect {
+ -re "Delete all breakpoints.*$" {
+ send_gdb "y\n"
+ gdb_expect {
+ -re ".*$gdb_prompt $" {
+ send_gdb "info breakpoints\n"
+ gdb_expect {
+ -re "No breakpoints or watchpoints..*$gdb_prompt $" {
+ pass "Deleted all breakpoints"
+ }
+ -re ".*$gdb_prompt $" { fail "Deleted all breakpoints" }
+ timeout { fail "Deleted all breakpoints (timeout)" }
+ }
+ }
+ timeout { fail "Deleted all breakpoints (timeout)" }
+ }
+ }
+ -re ".*$gdb_prompt $" { fail "Deleted all breakpoints" }
+ timeout { fail "Deleted all breakpoints (timeout)" }
+}
+
+
+
+
+send_gdb "break foo::overload1arg\n"
+gdb_expect {
+-re "\\\[0\\\] cancel\r\n\\\[1\\\] all\r\n\\\[2\\\] foo::overload1arg\\(double\\) at.*$srcfile:121\r\n\\\[3\\\] foo::overload1arg\\(float\\) at.*$srcfile:120\r\n\\\[4\\\] foo::overload1arg\\(unsigned long\\) at.*$srcfile:119\r\n\\\[5\\\] foo::overload1arg\\(long\\) at.*$srcfile:118\r\n\\\[6\\\] foo::overload1arg\\(unsigned int\\) at.*$srcfile:117\r\n\\\[7\\\] foo::overload1arg\\(int\\) at.*$srcfile:116\r\n\\\[8\\\] foo::overload1arg\\(unsigned short\\) at.*$srcfile:115\r\n\\\[9\\\] foo::overload1arg\\(short\\) at.*$srcfile:114\r\n\\\[10\\\] foo::overload1arg\\(unsigned char\\) at.*$srcfile:113\r\n\\\[11\\\] foo::overload1arg\\(signed char\\) at.*$srcfile:112\r\n\\\[12\\\] foo::overload1arg\\(char\\) at.*$srcfile:111\r\n\\\[13\\\] foo::overload1arg\\(void\\) at.*$srcfile:110\r\n> $" {
+ send_gdb "1\n"
+ gdb_expect {
+ -re "Breakpoint $decimal at $hex: file.*$srcfile, line 121.\r\nBreakpoint $decimal at $hex: file.*$srcfile, line 120.\r\nBreakpoint $decimal at $hex: file.*$srcfile, line 119.\r\nBreakpoint $decimal at $hex: file.*$srcfile, line 118.\r\nBreakpoint $decimal at $hex: file.*$srcfile, line 117.\r\nBreakpoint $decimal at $hex: file.*$srcfile, line 116.\r\nBreakpoint $decimal at $hex: file.*$srcfile, line 115.\r\nBreakpoint $decimal at $hex: file.*$srcfile, line 114.\r\nBreakpoint $decimal at $hex: file.*$srcfile, line 113.\r\nBreakpoint $decimal at $hex: file.*$srcfile, line 112.\r\nBreakpoint $decimal at $hex: file.*$srcfile, line 111.\r\nBreakpoint $decimal at $hex: file.*$srcfile, line 110.\r\nMultiple breakpoints were set.\r\nUse the .delete. command to delete unwanted breakpoints.\r\n$gdb_prompt $" {
+ pass "set bp on all overload1arg()" }
+ -re ".*$gdb_prompt $" {
+ fail "set bp on all overload1arg() wrong bp reply" }
+ timeout {
+ fail "(timeout)set bp on all overload1arg() wrong bp reply" }
+ }
+ }
+ -re ".*$gdb_prompt $" { fail "set bp on all overload1arg()(wrong menu)" }
+ timeout { fail "(timeout)set bp on all overload1arg()(wrong menu)" }
+ }
+
+
+
+gdb_test "info break" \
+ "Num Type\[\t \]+Disp Enb Address\[\t \]+What.*
+\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex in foo::overload1arg\\(double\\) at.*$srcfile:121\r
+\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex in foo::overload1arg\\(float\\) at.*$srcfile:120\r
+\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex in foo::overload1arg\\(unsigned long\\) at.*$srcfile:119\r
+\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex in foo::overload1arg\\(long\\) at.*$srcfile:118\r
+\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex in foo::overload1arg\\(unsigned int\\) at.*$srcfile:117\r
+\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex in foo::overload1arg\\(int\\) at.*$srcfile:116\r
+\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex in foo::overload1arg\\(unsigned short\\) at.*$srcfile:115\r
+\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex in foo::overload1arg\\(short\\) at.*$srcfile:114\r
+\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex in foo::overload1arg\\(unsigned char\\) at.*$srcfile:113\r
+\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex in foo::overload1arg\\(signed char\\) at.*$srcfile:112\r
+\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex in foo::overload1arg\\(char\\) at.*$srcfile:111\r
+\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex in foo::overload1arg\\(void\\) at.*$srcfile:110" \
+ "breakpoint info"
+
+
+ send_gdb "cont\n"
+ gdb_expect {
+ -re "Continuing.\r\n\r\nBreakpoint 25, foo::overload1arg \\(this=$hex\\) at.*$srcfile:110\r\n110\[\t \]+int foo::overload1arg \\(void\\)\[\t \]+\{ return 1; \}\r\n$gdb_prompt $" {
+ pass "continue to bp overloaded : void"
+ }
+ -re "$gdb_prompt $" { fail "continue to bp overloaded : void" }
+ timeout { fail "(timeout) continue to bp overloaded : void" }
+ }
+
+
+ send_gdb "cont\n"
+ gdb_expect {
+ -re "Continuing.\r\n\r\nBreakpoint 24, foo::overload1arg \\(this=$hex, arg=2 \\'\\\\002\\'\\) at.*$srcfile:111\r\n111\[\t \]+int foo::overload1arg \\(char arg\\).*$gdb_prompt $" {
+ pass "continue to bp overloaded : char"
+ }
+ -re "$gdb_prompt $" { fail "continue to bp overloaded : char" }
+ timeout { fail "(timeout) continue to bp overloaded : char" }
+ }
+
+
+ send_gdb "cont\n"
+ gdb_expect {
+ -re "Continuing.\r\n\r\nBreakpoint 23, foo::overload1arg \\(this=$hex, arg=3 \\'\\\\003\\'\\) at.*$srcfile:112\r\n112\[\t \]+int foo::overload1arg \\(signed char arg\\).*$gdb_prompt $" {
+ pass "continue to bp overloaded : signed char"
+ }
+ -re "$gdb_prompt $" { fail "continue to bp overloaded : signed char" }
+ timeout { fail "(timeout) continue to bp overloaded : signed char" }
+ }
+
+
+ send_gdb "cont\n"
+ gdb_expect {
+ -re "Continuing.\r\n\r\nBreakpoint 22, foo::overload1arg \\(this=$hex, arg=4 \\'\\\\004\\'\\) at.*$srcfile:113\r\n113\[\t \]+int foo::overload1arg \\(unsigned char arg\\).*$gdb_prompt $" {
+ pass "continue to bp overloaded : unsigned char"
+ }
+ -re "$gdb_prompt $" { fail "continue to bp overloaded : unsigned char" }
+ timeout { fail "(timeout) continue to bp overloaded : unsigned char" }
+ }
+
+
+ send_gdb "cont\n"
+ gdb_expect {
+ -re "Continuing.\r\n\r\nBreakpoint 21, foo::overload1arg \\(this=$hex, arg=5\\) at.*$srcfile:114\r\n114\[\t \]+int foo::overload1arg \\(short arg\\).*$gdb_prompt $" {
+ pass "continue to bp overloaded : short"
+ }
+ -re "$gdb_prompt $" { fail "continue to bp overloaded : short" }
+ timeout { fail "(timeout) continue to bp overloaded : short" }
+ }
+
+
+ send_gdb "cont\n"
+ gdb_expect {
+ -re "Continuing.\r\n\r\nBreakpoint 20, foo::overload1arg \\(this=$hex, arg=6\\) at.*$srcfile:115\r\n115\[\t \]+int foo::overload1arg \\(unsigned short arg\\).*$gdb_prompt $" {
+ pass "continue to bp overloaded : unsigned short"
+ }
+ -re "$gdb_prompt $" { fail "continue to bp overloaded : unsigned short" }
+ timeout { fail "(timeout) continue to bp overloaded : unsigned short" }
+ }
+
+
+ send_gdb "cont\n"
+ gdb_expect {
+ -re "Continuing.\r\n\r\nBreakpoint 19, foo::overload1arg \\(this=$hex, arg=7\\) at.*$srcfile:116\r\n116\[\t \]+int foo::overload1arg \\(int arg\\).*$gdb_prompt $" {
+ pass "continue to bp overloaded : int"
+ }
+ -re "$gdb_prompt $" { fail "continue to bp overloaded : int" }
+ timeout { fail "(timeout) continue to bp overloaded : int" }
+ }
+
+
+ send_gdb "cont\n"
+ gdb_expect {
+ -re "Continuing.\r\n\r\nBreakpoint 18, foo::overload1arg \\(this=$hex, arg=8\\) at.*$srcfile:117\r\n117\[\t \]+int foo::overload1arg \\(unsigned int arg\\).*$gdb_prompt $" {
+ pass "continue to bp overloaded : unsigned int"
+ }
+ -re "$gdb_prompt $" { fail "continue to bp overloaded : unsigned int" }
+ timeout { fail "(timeout) continue to bp overloaded : unsigned int" }
+ }
+
+
+ send_gdb "cont\n"
+ gdb_expect {
+ -re "Continuing.\r\n\r\nBreakpoint 17, foo::overload1arg \\(this=$hex, arg=9\\) at.*$srcfile:118\r\n118\[\t \]+int foo::overload1arg \\(long arg\\).*$gdb_prompt $" {
+ pass "continue to bp overloaded : long"
+ }
+ -re "$gdb_prompt $" { fail "continue to bp overloaded : long" }
+ timeout { fail "(timeout) continue to bp overloaded : long" }
+ }
+
+
+ send_gdb "cont\n"
+ gdb_expect {
+ -re "Continuing.\r\n\r\nBreakpoint 16, foo::overload1arg \\(this=$hex, arg=10\\) at.*$srcfile:119\r\n119\[\t \]+int foo::overload1arg \\(unsigned long arg\\).*$gdb_prompt $" {
+ pass "continue to bp overloaded : unsigned long"
+ }
+ -re "$gdb_prompt $" { fail "continue to bp overloaded : unsigned long" }
+ timeout { fail "(timeout) continue to bp overloaded : unsigned long" }
+ }
+
+
+ send_gdb "cont\n"
+ gdb_expect {
+ -re "Continuing.\r\n\r\nBreakpoint 15, foo::overload1arg \\(this=$hex, arg=100\\) at.*$srcfile:120\r\n120\[\t \]+int foo::overload1arg \\(float arg\\).*$gdb_prompt $" {
+ pass "continue to bp overloaded : float"
+ }
+ -re "$gdb_prompt $" { fail "continue to bp overloaded : float" }
+ timeout { fail "(timeout) continue to bp overloaded : float" }
+ }
+
+ send_gdb "cont\n"
+ gdb_expect {
+ -re "Continuing.\r\n\r\nBreakpoint 14, foo::overload1arg \\(this=$hex, arg=200\\) at.*$srcfile:121\r\n121\[\t \]+int foo::overload1arg \\(double arg\\).*$gdb_prompt $" {
+ pass "continue to bp overloaded : double"
+ }
+ -re "$gdb_prompt $" { fail "continue to bp overloaded : double" }
+ timeout { fail "(timeout) continue to bp overloaded : double" }
+ }
+
+ send_gdb "cont\n"
+ gdb_expect {
+ -re "Continuing.\r\n\r\nProgram exited normally.\r\n$gdb_prompt $" {
+ pass "finish program"
+ }
+ -re "$gdb_prompt $" { fail "finish program" }
+ timeout { fail "(timeout) finish program" }
+ }
diff --git a/gdb/testsuite/gdb.c++/ref-types.cc b/gdb/testsuite/gdb.c++/ref-types.cc
new file mode 100644
index 00000000000..8ee5c405d87
--- /dev/null
+++ b/gdb/testsuite/gdb.c++/ref-types.cc
@@ -0,0 +1,30 @@
+void marker1 (void)
+{
+
+}
+
+
+
+int main(void)
+{
+ short s;
+ short &rs = s;
+ short *ps;
+ short *&rps = ps;
+ short as[4];
+ short (&ras)[4] = as;
+ s = -1;
+ ps = &s;
+ as[0] = 0;
+ as[1] = 1;
+ as[2] = 2;
+ as[3] = 3;
+
+ #ifdef usestubs
+ set_debug_traps();
+ breakpoint();
+ #endif
+ marker1();
+
+ return 0;
+}
diff --git a/gdb/testsuite/gdb.c++/ref-types.exp b/gdb/testsuite/gdb.c++/ref-types.exp
new file mode 100644
index 00000000000..7f255909575
--- /dev/null
+++ b/gdb/testsuite/gdb.c++/ref-types.exp
@@ -0,0 +1,276 @@
+# Copyright (C) 1998 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# written by Elena Zannoni (ezannoni@cygnus.com)
+
+# This file is part of the gdb testsuite
+#
+# tests for reference types
+# with short type variables.
+#
+
+if $tracelevel then {
+ strace $tracelevel
+ }
+
+#
+# test running programs
+#
+set prms_id 0
+set bug_id 0
+
+set testfile "ref-types"
+set srcfile ${testfile}.cc
+set binfile ${objdir}/${subdir}/${testfile}
+
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug c++}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+
+#
+# set it up at a breakpoint so we can play with the variable values
+#
+if ![runto_main] then {
+ perror "couldn't run to breakpoint"
+ continue
+}
+
+send_gdb "break marker1\n" ; gdb_expect -re ".*$gdb_prompt $"
+
+ send_gdb "cont\n"
+ gdb_expect {
+ -re "Break.* marker1 \\(\\) at .*:$decimal.*$gdb_prompt $" {
+ send_gdb "up\n"
+ gdb_expect {
+ -re ".*$gdb_prompt $" {}
+ timeout { fail "up from marker1" }
+ }
+ }
+ -re "$gdb_prompt $" { fail "continue to marker1" }
+ timeout { fail "(timeout) continue to marker1" }
+ }
+
+
+proc gdb_start_again {} {
+global srcdir
+global subdir
+global binfile
+global gdb_prompt
+global decimal
+
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+source ${binfile}.ci
+
+#
+# set it up at a breakpoint so we can play with the variable values
+#
+if ![runto_main] then {
+ perror "couldn't run to breakpoint"
+ continue
+}
+
+send_gdb "break marker1\n" ; gdb_expect -re ".*$gdb_prompt $"
+
+ send_gdb "cont\n"
+ gdb_expect {
+ -re "Break.* marker1 \\(\\) at .*:$decimal.*$gdb_prompt $" {
+ send_gdb "up\n"
+ gdb_expect {
+ -re ".*$gdb_prompt $" {}
+ timeout { fail "up from marker1" }
+ }
+ }
+ -re "$gdb_prompt $" { fail "continue to marker1" }
+ timeout { fail "(timeout) continue to marker1" }
+ }
+}
+
+
+
+
+
+send_gdb "print s\n"
+gdb_expect {
+ -re ".\[0-9\]* = -1.*$gdb_prompt $" {
+ pass "print value of s"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of s" }
+ timeout { fail "(timeout) print value of s" }
+ }
+
+
+send_gdb "ptype s\n"
+gdb_expect {
+ -re "type = short.*$gdb_prompt $" { pass "ptype s" }
+ -re ".*$gdb_prompt $" { fail "ptype s" }
+ timeout { fail "(timeout) ptype s" }
+}
+
+
+send_gdb "print *ps\n"
+gdb_expect {
+ -re ".\[0-9\]* = -1.*$gdb_prompt $" {
+ pass "print value of ps"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of ps" }
+ timeout { fail "(timeout) print value of ps" }
+ }
+
+
+send_gdb "ptype ps\n"
+gdb_expect {
+ -re "type = short \*.*$gdb_prompt $" { pass "ptype ps" }
+ -re ".*$gdb_prompt $" { fail "ptype ps" }
+ timeout { fail "(timeout) ptype ps" }
+}
+
+send_gdb "print as\[0\]\n"
+gdb_expect {
+ -re ".\[0-9\]* = 0.*$gdb_prompt $" {
+ pass "print value of as\[0\]"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of as\[0\]" }
+ timeout { fail "(timeout) print value of as\[0\]" }
+ }
+
+
+send_gdb "ptype as\n"
+gdb_expect {
+ -re "type = short \\\[4\\\].*$gdb_prompt $" { pass "ptype as" }
+ -re ".*$gdb_prompt $" { fail "ptype as" }
+ timeout { fail "(timeout) ptype as" }
+}
+
+send_gdb "print as\[1\]\n"
+gdb_expect {
+ -re ".\[0-9\]* = 1.*$gdb_prompt $" {
+ pass "print value of as\[1\]"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of as\[1\]" }
+ timeout { fail "(timeout) print value of as\[1\]" }
+ }
+
+send_gdb "print as\[2\]\n"
+gdb_expect {
+ -re ".\[0-9\]* = 2.*$gdb_prompt $" {
+ pass "print value of as\[2\]"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of as\[2\]" }
+ timeout { fail "(timeout) print value of as\[2\]" }
+ }
+
+send_gdb "print as\[3\]\n"
+gdb_expect {
+ -re ".\[0-9\]* = 3.*$gdb_prompt $" {
+ pass "print value of as\[3\]"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of as\[3\]" }
+ timeout { fail "(timeout) print value of as\[3\]" }
+ }
+
+send_gdb "print rs\n"
+gdb_expect {
+ -re ".\[0-9\]* = \\(short &\\) @$hex: -1.*$gdb_prompt $" {
+ pass "print value of rs"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of rs" }
+ timeout { fail "(timeout) print value of rs" }
+ eof { fail "print rs ($GDB dumped core) (FIXME)" ; gdb_start_again ; }
+
+ }
+
+send_gdb "ptype rs\n"
+gdb_expect {
+ -re "type = short &.*$gdb_prompt $" { pass "ptype rs" }
+ -re ".*$gdb_prompt $" { fail "ptype rs" }
+ timeout { fail "(timeout) ptype rs" }
+}
+
+
+send_gdb "print *rps\n"
+gdb_expect {
+ -re ".\[0-9\]* = -1.*$gdb_prompt $" {
+ pass "print value of *rps"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of *rps" }
+ timeout { fail "(timeout) print value of *rps" }
+ }
+
+
+send_gdb "ptype rps\n"
+gdb_expect {
+ -re "type = short \\*&.*$gdb_prompt $" { pass "ptype rps" }
+ -re ".*$gdb_prompt $" { fail "ptype rps" }
+ timeout { fail "(timeout) ptype rps" }
+}
+
+
+
+send_gdb "print ras\[0\]\n"
+gdb_expect {
+ -re ".\[0-9\]* = 0.*$gdb_prompt $" {
+ pass "print value of ras\[0\]"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of ras\[0\]" }
+ timeout { fail "(timeout) print value of ras\[0\]" }
+ }
+
+
+send_gdb "ptype ras\n"
+gdb_expect {
+ -re "type = short \\\(&\\\)\\\[4\\\].*$gdb_prompt $" { pass "ptype ras" }
+ -re ".*$gdb_prompt $" { fail "ptype ras" }
+ timeout { fail "(timeout) ptype ras" }
+}
+
+send_gdb "print ras\[1\]\n"
+gdb_expect {
+ -re ".\[0-9\]* = 1.*$gdb_prompt $" {
+ pass "print value of ras\[1\]"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of ras\[1\]" }
+ timeout { fail "(timeout) print value of ras\[1\]" }
+ }
+
+send_gdb "print ras\[2\]\n"
+gdb_expect {
+ -re ".\[0-9\]* = 2.*$gdb_prompt $" {
+ pass "print value of ras\[2\]"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of ras\[2\]" }
+ timeout { fail "(timeout) print value of ras\[2\]" }
+ }
+
+send_gdb "print ras\[3\]\n"
+gdb_expect {
+ -re ".\[0-9\]* = 3.*$gdb_prompt $" {
+ pass "print value of ras\[3\]"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of ras\[3\]" }
+ timeout { fail "(timeout) print value of ras\[3\]" }
+ }
diff --git a/gdb/testsuite/gdb.c++/ref-types2.cc b/gdb/testsuite/gdb.c++/ref-types2.cc
new file mode 100644
index 00000000000..62c982d91c1
--- /dev/null
+++ b/gdb/testsuite/gdb.c++/ref-types2.cc
@@ -0,0 +1,47 @@
+int f()
+{
+ int f1;
+ f1 = 1;
+ return f1;
+}
+
+int main(void)
+{
+ char C;
+ unsigned char UC;
+ short S;
+ unsigned short US;
+ int I;
+ unsigned int UI;
+ long L;
+ unsigned long UL;
+ float F;
+ double D;
+ char &rC = C;
+ unsigned char &rUC = UC;
+ short &rS = S;
+ unsigned short &rUS = US;
+ int &rI = I;
+ unsigned int &rUI = UI;
+ long &rL = L;
+ unsigned long &rUL = UL;
+ float &rF = F;
+ double &rD = D;
+ C = 'A';
+ UC = 21;
+ S = -14;
+ US = 7;
+ I = 102;
+ UI = 1002;
+ L = -234;
+ UL = 234;
+ F = 1.25E10;
+ D = -1.375E-123;
+ I = f();
+ #ifdef usestubs
+ set_debug_traps();
+ breakpoint();
+ #endif
+ return 0;
+
+}
diff --git a/gdb/testsuite/gdb.c++/ref-types2.exp b/gdb/testsuite/gdb.c++/ref-types2.exp
new file mode 100644
index 00000000000..675414754c4
--- /dev/null
+++ b/gdb/testsuite/gdb.c++/ref-types2.exp
@@ -0,0 +1,450 @@
+# Copyright (C) 1998 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# written by Elena Zannoni (ezannoni@cygnus.com)
+
+# This file is part of the gdb testsuite
+#
+# tests for reference types
+# with elementary type variables.
+#
+
+if $tracelevel then {
+ strace $tracelevel
+ }
+
+#
+# test running programs
+#
+set prms_id 0
+set bug_id 0
+
+set testfile "ref-types2"
+set srcfile ${testfile}.cc
+set binfile ${objdir}/${subdir}/${testfile}
+
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug c++}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+
+#
+# set it up at a breakpoint so we can play with the variable values
+#
+if ![runto_main] then {
+ perror "couldn't run to breakpoint"
+ continue
+}
+
+send_gdb "break f\n" ; gdb_expect -re ".*$gdb_prompt $"
+
+ send_gdb "cont\n"
+ gdb_expect {
+ -re "Break.* f \\(\\) at .*:$decimal.*$gdb_prompt $" {
+ send_gdb "up\n"
+ gdb_expect {
+ -re ".*$gdb_prompt $" {}
+ timeout { fail "up from f" }
+ }
+ }
+ -re "$gdb_prompt $" { fail "continue to f" }
+ timeout { fail "(timeout) continue to f" }
+ }
+
+
+send_gdb "print C\n"
+gdb_expect {
+ -re ".\[0-9\]* = 65 \'A\'.*$gdb_prompt $" {
+ pass "print value of C"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of C" }
+ timeout { fail "(timeout) print value of C" }
+ }
+
+
+send_gdb "ptype C\n"
+gdb_expect {
+ -re "type = char.*$gdb_prompt $" { pass "ptype C" }
+ -re ".*$gdb_prompt $" { fail "ptype C" }
+ timeout { fail "(timeout) ptype C" }
+}
+
+
+send_gdb "print UC\n"
+gdb_expect {
+ -re ".\[0-9\]* = 21 '\.025'\.*$gdb_prompt $" {
+ pass "print value of UC"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of UC" }
+ timeout { fail "(timeout) print value of UC" }
+ }
+
+
+send_gdb "ptype UC\n"
+gdb_expect {
+ -re "type = unsigned char.*$gdb_prompt $" { pass "ptype UC" }
+ -re ".*$gdb_prompt $" { fail "ptype UC" }
+ timeout { fail "(timeout) ptype UC" }
+}
+
+
+send_gdb "print S\n"
+gdb_expect {
+ -re ".\[0-9\]* = -14.*$gdb_prompt $" {
+ pass "print value of S"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of S" }
+ timeout { fail "(timeout) print value of S" }
+ }
+
+
+send_gdb "ptype S\n"
+gdb_expect {
+ -re "type = short.*$gdb_prompt $" { pass "ptype S" }
+ -re ".*$gdb_prompt $" { fail "ptype S" }
+ timeout { fail "(timeout) ptype S" }
+}
+
+
+send_gdb "print US\n"
+gdb_expect {
+ -re ".\[0-9\]* = 7.*$gdb_prompt $" {
+ pass "print value of US"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of US" }
+ timeout { fail "(timeout) print value of US" }
+ }
+
+
+send_gdb "ptype US\n"
+gdb_expect {
+ -re "type = unsigned short.*$gdb_prompt $" { pass "ptype US" }
+ -re ".*$gdb_prompt $" { fail "ptype US" }
+ timeout { fail "(timeout) ptype US" }
+}
+
+
+send_gdb "print I\n"
+gdb_expect {
+ -re ".\[0-9\]* = 102.*$gdb_prompt $" {
+ pass "print value of I"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of I" }
+ timeout { fail "(timeout) print value of I" }
+ }
+
+
+send_gdb "ptype I\n"
+gdb_expect {
+ -re "type = int.*$gdb_prompt $" { pass "ptype I" }
+ -re ".*$gdb_prompt $" { fail "ptype I" }
+ timeout { fail "(timeout) ptype I" }
+}
+
+
+send_gdb "print UI\n"
+gdb_expect {
+ -re ".\[0-9\]* = 1002.*$gdb_prompt $" {
+ pass "print value of UI"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of UI" }
+ timeout { fail "(timeout) print value of UI" }
+ }
+
+
+send_gdb "ptype UI\n"
+gdb_expect {
+ -re "type = unsigned int.*$gdb_prompt $" { pass "ptype UI" }
+ -re ".*$gdb_prompt $" { fail "ptype UI" }
+ timeout { fail "(timeout) ptype UI" }
+}
+
+
+send_gdb "print L\n"
+gdb_expect {
+ -re ".\[0-9\]* = -234.*$gdb_prompt $" {
+ pass "print value of L"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of L" }
+ timeout { fail "(timeout) print value of L" }
+ }
+
+
+send_gdb "ptype L\n"
+gdb_expect {
+ -re "type = long.*$gdb_prompt $" { pass "ptype L" }
+ -re ".*$gdb_prompt $" { fail "ptype L" }
+ timeout { fail "(timeout) ptype L" }
+}
+
+
+send_gdb "print UL\n"
+gdb_expect {
+ -re ".\[0-9\]* = 234.*$gdb_prompt $" {
+ pass "print value of UL"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of UL" }
+ timeout { fail "(timeout) print value of UL" }
+ }
+
+
+send_gdb "ptype UL\n"
+gdb_expect {
+ -re "type = unsigned long.*$gdb_prompt $" { pass "ptype UL" }
+ -re ".*$gdb_prompt $" { fail "ptype UL" }
+ timeout { fail "(timeout) ptype UL" }
+}
+
+
+send_gdb "print F\n"
+gdb_expect {
+ -re ".\[0-9\]* = 1.2\[0-9\]*e\\+10.*$gdb_prompt $" {
+ pass "print value of F"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of F" }
+ timeout { fail "(timeout) print value of F" }
+ }
+
+
+
+send_gdb "ptype F\n"
+gdb_expect {
+ -re "type = float.*$gdb_prompt $" { pass "ptype F" }
+ -re ".*$gdb_prompt $" { fail "ptype F" }
+ timeout { fail "(timeout) ptype F" }
+}
+
+
+send_gdb "print D\n"
+gdb_expect {
+ -re ".\[0-9\]* = -1.375e-123.*$gdb_prompt $" {
+ pass "print value of D"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of D" }
+ timeout { fail "(timeout) print value of D" }
+ }
+
+
+send_gdb "ptype D\n"
+gdb_expect {
+ -re "type = double.*$gdb_prompt $" { pass "ptype D" }
+ -re ".*$gdb_prompt $" { fail "ptype D" }
+ timeout { fail "(timeout) ptype D" }
+}
+
+
+
+#
+# test reference types
+#
+
+
+
+
+send_gdb "ptype rC\n"
+gdb_expect {
+ -re "type = char &.*$gdb_prompt $" { pass "ptype rC" }
+ -re ".*$gdb_prompt $" { fail "ptype rC" }
+ timeout { fail "(timeout) ptype rC" }
+}
+
+
+
+
+send_gdb "ptype rUC\n"
+gdb_expect {
+ -re "type = unsigned char &.*$gdb_prompt $" { pass "ptype rUC" }
+ -re ".*$gdb_prompt $" { fail "ptype rUC" }
+ timeout { fail "(timeout) ptype rUC" }
+}
+
+
+
+send_gdb "ptype rS\n"
+gdb_expect {
+ -re "type = short &.*$gdb_prompt $" { pass "ptype rS" }
+ -re ".*$gdb_prompt $" { fail "ptype rS" }
+ timeout { fail "(timeout) ptype rS" }
+}
+
+
+
+send_gdb "ptype rUS\n"
+gdb_expect {
+ -re "type = unsigned short &.*$gdb_prompt $" { pass "ptype rUS" }
+ -re ".*$gdb_prompt $" { fail "ptype rUS" }
+ timeout { fail "(timeout) ptype rUS" }
+}
+
+
+send_gdb "ptype rI\n"
+gdb_expect {
+ -re "type = int &.*$gdb_prompt $" { pass "ptype rI" }
+ -re ".*$gdb_prompt $" { fail "ptype rI" }
+ timeout { fail "(timeout) ptype rI" }
+}
+
+
+
+send_gdb "ptype rUI\n"
+gdb_expect {
+ -re "type = unsigned int &.*$gdb_prompt $" { pass "ptype rUI" }
+ -re ".*$gdb_prompt $" { fail "ptype rUI" }
+ timeout { fail "(timeout) ptype rUI" }
+}
+
+
+
+send_gdb "ptype rL\n"
+gdb_expect {
+ -re "type = long &.*$gdb_prompt $" { pass "ptype rL" }
+ -re ".*$gdb_prompt $" { fail "ptype rL" }
+ timeout { fail "(timeout) ptype rL" }
+}
+
+
+send_gdb "ptype rUL\n"
+gdb_expect {
+ -re "type = unsigned long &.*$gdb_prompt $" { pass "ptype rUL" }
+ -re ".*$gdb_prompt $" { fail "ptype rUL" }
+ timeout { fail "(timeout) ptype rUL" }
+}
+
+
+send_gdb "ptype rF\n"
+gdb_expect {
+ -re "type = float &.*$gdb_prompt $" { pass "ptype rF" }
+ -re ".*$gdb_prompt $" { fail "ptype rF" }
+ timeout { fail "(timeout) ptype rF" }
+}
+
+
+send_gdb "ptype rD\n"
+gdb_expect {
+ -re "type = double &.*$gdb_prompt $" { pass "ptype rD" }
+ -re ".*$gdb_prompt $" { fail "ptype rD" }
+ timeout { fail "(timeout) ptype rD" }
+}
+
+
+send_gdb "print rC\n"
+gdb_expect {
+ -re ".\[0-9\]* = \\(char &\\) @$hex: 65 \'A\'.*$gdb_prompt $" {
+ pass "print value of rC"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of rC" }
+ timeout { fail "(timeout) print value of rC" }
+ }
+
+
+send_gdb "print rUC\n"
+gdb_expect {
+ -re ".\[0-9\]* = \\(unsigned char &\\) @$hex: 21 \'.025\'.*$gdb_prompt $" {
+ pass "print value of rUC"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of rUC" }
+ timeout { fail "(timeout) print value of rUC" }
+ }
+
+
+send_gdb "print rS\n"
+gdb_expect {
+ -re ".\[0-9\]* = \\(short &\\) @$hex: -14.*$gdb_prompt $" {
+ pass "print value of rS"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of rS" }
+ timeout { fail "(timeout) print value of rS" }
+ }
+
+
+send_gdb "print rUS\n"
+gdb_expect {
+ -re ".\[0-9\]* = \\(unsigned short &\\) @$hex: 7.*$gdb_prompt $" {
+ pass "print value of rUS"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of rUS" }
+ timeout { fail "(timeout) print value of rUS" }
+ }
+
+
+send_gdb "print rI\n"
+gdb_expect {
+ -re ".\[0-9\]* = \\(int &\\) @$hex: 102.*$gdb_prompt $" {
+ pass "print value of rI"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of rI" }
+ timeout { fail "(timeout) print value of rI" }
+ }
+
+
+send_gdb "print rUI\n"
+gdb_expect {
+ -re ".\[0-9\]* = \\(unsigned int &\\) @$hex: 1002.*$gdb_prompt $" {
+ pass "print value of UI"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of rUI" }
+ timeout { fail "(timeout) print value of rUI" }
+ }
+
+
+send_gdb "print rL\n"
+gdb_expect {
+ -re ".\[0-9\]* = \\(long &\\) @$hex: -234.*$gdb_prompt $" {
+ pass "print value of rL"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of rL" }
+ timeout { fail "(timeout) print value of rL" }
+ }
+
+
+
+send_gdb "print rUL\n"
+gdb_expect {
+ -re ".\[0-9\]* = \\(unsigned long &\\) @$hex: 234.*$gdb_prompt $" {
+ pass "print value of rUL"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of rUL" }
+ timeout { fail "(timeout) print value of rUL" }
+ }
+
+
+send_gdb "print rF\n"
+gdb_expect {
+ -re ".\[0-9\]* = \\(float &\\) @$hex: 1.2\[0-9\]*e\\+10.*$gdb_prompt $" {
+ pass "print value of rF"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of rF" }
+ timeout { fail "(timeout) print value of rF" }
+ }
+
+
+send_gdb "print rD\n"
+gdb_expect {
+ -re ".\[0-9\]* = \\(double &\\) @$hex: -1.375e-123.*$gdb_prompt $" {
+ pass "print value of rD"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of rD" }
+ timeout { fail "(timeout) print value of rD" }
+ }
+
diff --git a/gdb/testsuite/gdb.c++/templates.cc b/gdb/testsuite/gdb.c++/templates.cc
new file mode 100644
index 00000000000..25241dc6dbf
--- /dev/null
+++ b/gdb/testsuite/gdb.c++/templates.cc
@@ -0,0 +1,785 @@
+/* This test code is from Wendell Baker (wbaker@comet.berkeley.edu) */
+
+#include <stddef.h>
+
+int a_i;
+char a_c;
+double a_d;
+
+typedef void *Pix;
+
+int
+f(int i)
+{ return 0; }
+
+int
+f(int i, char c)
+{ return 0; }
+
+int
+f(int i, char c, double d)
+{ return 0; }
+
+int
+f(int i, char c, double d, char *cs)
+{ return 0; }
+
+int
+f(int i, char c, double d, char *cs, void (*fig)(int, char))
+{ return 0; }
+
+int
+f(int i, char c, double d, char *cs, void (*fig)(char, int))
+{ return 0; }
+
+class R {
+public:
+ int i;
+};
+class S {
+public:
+ int i;
+};
+class T {
+public:
+ int i;
+};
+
+char g(char, const char, volatile char)
+{ return 'c'; }
+char g(R, char&, const char&, volatile char&)
+{ return 'c'; }
+char g(char*, const char*, volatile char*)
+{ return 'c'; }
+char g(S, char*&, const char*&, volatile char*&)
+{ return 'c'; }
+
+signed char g(T,signed char, const signed char, volatile signed char)
+{ return 'c'; }
+signed char g(T, R, signed char&, const signed char&, volatile signed char&)
+{ return 'c'; }
+signed char g(T, signed char*, const signed char*, volatile signed char*)
+{ return 'c'; }
+signed char g(T, S, signed char*&, const signed char*&, volatile signed char*&)
+{ return 'c'; }
+
+unsigned char g(unsigned char, const unsigned char, volatile unsigned char)
+{ return 'c'; }
+unsigned char g(R, unsigned char&, const unsigned char&, volatile unsigned char&)
+{ return 'c'; }
+unsigned char g(unsigned char*, const unsigned char*, volatile unsigned char*)
+{ return 'c'; }
+unsigned char g(S, unsigned char*&, const unsigned char*&, volatile unsigned char*&)
+{ return 'c'; }
+
+short g(short, const short, volatile short)
+{ return 0; }
+short g(R, short&, const short&, volatile short&)
+{ return 0; }
+short g(short*, const short*, volatile short*)
+{ return 0; }
+short g(S, short*&, const short*&, volatile short*&)
+{ return 0; }
+
+signed short g(T, signed short, const signed short, volatile signed short)
+{ return 0; }
+signed short g(T, R, signed short&, const signed short&, volatile signed short&)
+{ return 0; }
+signed short g(T, signed short*, const signed short*, volatile signed short*)
+{ return 0; }
+signed short g(T, S, double, signed short*&, const signed short*&, volatile signed short*&)
+{ return 0; }
+
+unsigned short g(unsigned short, const unsigned short, volatile unsigned short)
+{ return 0; }
+unsigned short g(R, unsigned short&, const unsigned short&, volatile unsigned short&)
+{ return 0; }
+unsigned short g(unsigned short*, const unsigned short*, volatile unsigned short*)
+{ return 0; }
+unsigned short g(S, unsigned short*&, const unsigned short*&, volatile unsigned short*&)
+{ return 0; }
+
+int g(int, const int, volatile int)
+{ return 0; }
+int g(R, int&, const int&, volatile int&)
+{ return 0; }
+int g(int*, const int*, volatile int*)
+{ return 0; }
+int g(S, int*&, const int*&, volatile int*&)
+{ return 0; }
+
+signed int g(T, signed int, const signed int, volatile signed int)
+{ return 0; }
+signed int g(T, R, signed int&, const signed int&, volatile signed int&)
+{ return 0; }
+signed int g(T, signed int*, const signed int*, volatile signed int*)
+{ return 0; }
+signed int g(T, S, signed int*&, const signed int*&, volatile signed int*&)
+{ return 0; }
+
+unsigned int g(unsigned int, const unsigned int, volatile unsigned int)
+{ return 0; }
+unsigned int g(R, unsigned int&, const unsigned int&, volatile unsigned int&)
+{ return 0; }
+unsigned int g(unsigned int*, const unsigned int*, volatile unsigned int*)
+{ return 0; }
+unsigned int g(S, unsigned int*&, const unsigned int*&, volatile unsigned int*&)
+{ return 0; }
+
+long g(long, const long, volatile long)
+{ return 0; }
+long g(R, long&, const long&, volatile long&)
+{ return 0; }
+long g(long*, const long*, volatile long*)
+{ return 0; }
+long g(S, long*&, const long*&, volatile long*&)
+{ return 0; }
+
+signed long g(T, signed long, const signed long, volatile signed long)
+{ return 0; }
+signed long g(T, R, signed long&, const signed long&, volatile signed long&)
+{ return 0; }
+signed long g(T, signed long*, const signed long*, volatile signed long*)
+{ return 0; }
+signed long g(T, S, signed long*&, const signed long*&, volatile signed long*&)
+{ return 0; }
+
+unsigned long g(unsigned long, const unsigned long, volatile unsigned long)
+{ return 0; }
+unsigned long g(S, unsigned long&, const unsigned long&, volatile unsigned long&)
+{ return 0; }
+unsigned long g(unsigned long*, const unsigned long*, volatile unsigned long*)
+{ return 0; }
+unsigned long g(S, unsigned long*&, const unsigned long*&, volatile unsigned long*&)
+{ return 0; }
+
+#ifdef __GNUC__
+long long g(long long, const long long, volatile long long)
+{ return 0; }
+long long g(S, long long&, const long long&, volatile long long&)
+{ return 0; }
+long long g(long long*, const long long*, volatile long long*)
+{ return 0; }
+long long g(R, long long*&, const long long*&, volatile long long*&)
+{ return 0; }
+
+signed long long g(T, signed long long, const signed long long, volatile signed long long)
+{ return 0; }
+signed long long g(T, R, signed long long&, const signed long long&, volatile signed long long&)
+{ return 0; }
+signed long long g(T, signed long long*, const signed long long*, volatile signed long long*)
+{ return 0; }
+signed long long g(T, S, signed long long*&, const signed long long*&, volatile signed long long*&)
+{ return 0; }
+
+unsigned long long g(unsigned long long, const unsigned long long, volatile unsigned long long)
+{ return 0; }
+unsigned long long g(R, unsigned long long*, const unsigned long long*, volatile unsigned long long*)
+{ return 0; }
+unsigned long long g(unsigned long long&, const unsigned long long&, volatile unsigned long long&)
+{ return 0; }
+unsigned long long g(S, unsigned long long*&, const unsigned long long*&, volatile unsigned long long*&)
+{ return 0; }
+#endif
+
+float g(float, const float, volatile float)
+{ return 0; }
+float g(char, float&, const float&, volatile float&)
+{ return 0; }
+float g(float*, const float*, volatile float*)
+{ return 0; }
+float g(char, float*&, const float*&, volatile float*&)
+{ return 0; }
+
+double g(double, const double, volatile double)
+{ return 0; }
+double g(char, double&, const double&, volatile double&)
+{ return 0; }
+double g(double*, const double*, volatile double*)
+{ return 0; }
+double g(char, double*&, const double*&, volatile double*&)
+{ return 0; }
+
+#ifdef __GNUC__
+long double g(long double, const long double, volatile long double)
+{ return 0; }
+long double g(char, long double&, const long double&, volatile long double&)
+{ return 0; }
+long double g(long double*, const long double*, volatile long double*)
+{ return 0; }
+long double g(char, long double*&, const long double*&, volatile long double*&)
+{ return 0; }
+#endif
+
+class c {
+public:
+ c(int) {};
+ int i;
+};
+
+class c g(c, const c, volatile c)
+{ return 0; }
+c g(char, c&, const c&, volatile c&)
+{ return 0; }
+c g(c*, const c*, volatile c*)
+{ return 0; }
+c g(char, c*&, const c*&, volatile c*&)
+{ return 0; }
+
+/*
+void h(char = 'a')
+{ }
+void h(char, signed char = 'a')
+{ }
+void h(unsigned char = 'a')
+{ }
+*/
+/*
+void h(char = (char)'a')
+{ }
+void h(char, signed char = (signed char)'a')
+{ }
+void h(unsigned char = (unsigned char)'a')
+{ }
+
+
+void h(short = (short)43)
+{ }
+void h(char, signed short = (signed short)43)
+{ }
+void h(unsigned short = (unsigned short)43)
+{ }
+
+void h(int = (int)43)
+{ }
+void h(char, signed int = (signed int)43)
+{ }
+void h(unsigned int = (unsigned int)43)
+{ }
+
+
+void h(long = (long)43)
+{ }
+void h(char, signed long = (signed long)43)
+{ }
+void h(unsigned long = (unsigned long)43)
+{ }
+
+#ifdef __GNUC__
+void h(long long = 43)
+{ }
+void h(char, signed long long = 43)
+{ }
+void h(unsigned long long = 43)
+{ }
+#endif
+
+void h(float = 4.3e-10)
+{ }
+void h(double = 4.3)
+{ }
+#ifdef __GNUC__
+void h(long double = 4.33e33)
+{ }
+#endif
+*/
+void printf(const char *format, ... )
+{
+ // elipsis
+}
+
+class T1 {
+public:
+ static void* operator new(size_t);
+ static void operator delete(void *pointer);
+
+ void operator=(const T1&);
+ T1& operator=(int);
+
+ int operator==(int) const;
+ int operator==(const T1&) const;
+ int operator!=(int) const;
+ int operator!=(const T1&) const;
+
+ int operator<=(int) const;
+ int operator<=(const T1&) const;
+ int operator<(int) const;
+ int operator<(const T1&) const;
+ int operator>=(int) const;
+ int operator>=(const T1&) const;
+ int operator>(int) const;
+ int operator>(const T1&) const;
+
+ void operator+(int) const;
+ T1& operator+(const T1&) const;
+ void operator+=(int) const;
+ T1& operator+=(const T1&) const;
+
+ T1& operator++() const;
+
+ void operator-(int) const;
+ T1& operator-(const T1&) const;
+ void operator-=(int) const;
+ T1& operator-=(const T1&) const;
+
+ T1& operator--() const;
+
+ void operator*(int) const;
+ T1& operator*(const T1&) const;
+ void operator*=(int) const;
+ T1& operator*=(const T1&) const;
+
+ void operator/(int) const;
+ T1& operator/(const T1&) const;
+ void operator/=(int) const;
+ T1& operator/=(const T1&) const;
+
+ void operator%(int) const;
+ T1& operator%(const T1&) const;
+ void operator%=(int) const;
+ T1& operator%=(const T1&) const;
+
+ void operator&&(int) const;
+ T1& operator&&(const T1&) const;
+
+ void operator||(int) const;
+ T1& operator||(const T1&) const;
+
+ void operator&(int) const;
+ T1& operator&(const T1&) const;
+ void operator&=(int) const;
+ T1& operator&=(const T1&) const;
+
+ void operator|(int) const;
+ T1& operator|(const T1&) const;
+ void operator|=(int) const;
+ T1& operator|=(const T1&) const;
+
+ void operator^(int) const;
+ T1& operator^(const T1&) const;
+ void operator^=(int) const;
+ T1& operator^=(const T1&) const;
+
+ T1& operator!() const;
+ T1& operator~() const;
+};
+
+void*
+T1::operator new(size_t)
+{ return 0; }
+
+void
+T1::operator delete(void *pointer)
+{ }
+
+class T2 {
+public:
+ T2(int i): integer(i)
+ { }
+ int integer;
+};
+
+int operator==(const T2&, const T2&)
+{ return 0; }
+int operator==(const T2&, char)
+{ return 0; }
+int operator!=(const T2&, const T2&)
+{ return 0; }
+int operator!=(const T2&, char)
+{ return 0; }
+
+int operator<=(const T2&, const T2&)
+{ return 0; }
+int operator<=(const T2&, char)
+{ return 0; }
+int operator<(const T2&, const T2&)
+{ return 0; }
+int operator<(const T2&, char)
+{ return 0; }
+int operator>=(const T2&, const T2&)
+{ return 0; }
+int operator>=(const T2&, char)
+{ return 0; }
+int operator>(const T2&, const T2&)
+{ return 0; }
+int operator>(const T2&, char)
+{ return 0; }
+
+T2 operator+(const T2 t, int i)
+{ return t.integer + i; }
+T2 operator+(const T2 a, const T2& b)
+{ return a.integer + b.integer; }
+T2& operator+=(T2& t, int i)
+{ t.integer += i; return t; }
+T2& operator+=(T2& a, const T2& b)
+{ a.integer += b.integer; return a; }
+
+T2 operator-(const T2 t, int i)
+{ return t.integer - i; }
+T2 operator-(const T2 a, const T2& b)
+{ return a.integer - b.integer; }
+T2& operator-=(T2& t, int i)
+{ t.integer -= i; return t; }
+T2& operator-=(T2& a, const T2& b)
+{ a.integer -= b.integer; return a; }
+
+T2 operator*(const T2 t, int i)
+{ return t.integer * i; }
+T2 operator*(const T2 a, const T2& b)
+{ return a.integer * b.integer; }
+T2& operator*=(T2& t, int i)
+{ t.integer *= i; return t; }
+T2& operator*=(T2& a, const T2& b)
+{ a.integer *= b.integer; return a; }
+
+T2 operator/(const T2 t, int i)
+{ return t.integer / i; }
+T2 operator/(const T2 a, const T2& b)
+{ return a.integer / b.integer; }
+T2& operator/=(T2& t, int i)
+{ t.integer /= i; return t; }
+T2& operator/=(T2& a, const T2& b)
+{ a.integer /= b.integer; return a; }
+
+T2 operator%(const T2 t, int i)
+{ return t.integer % i; }
+T2 operator%(const T2 a, const T2& b)
+{ return a.integer % b.integer; }
+T2& operator%=(T2& t, int i)
+{ t.integer %= i; return t; }
+T2& operator%=(T2& a, const T2& b)
+{ a.integer %= b.integer; return a; }
+
+template<class T>
+class T5 {
+public:
+ T5(int);
+ T5(const T5<T>&);
+ ~T5();
+ static void* operator new(size_t);
+ static void operator delete(void *pointer);
+ int value();
+
+ static T X;
+ T x;
+ int val;
+};
+
+template<class T>
+T5<T>::T5(int v)
+{ val = v; }
+
+template<class T>
+T5<T>::T5(const T5<T>&)
+{}
+
+template<class T>
+T5<T>::~T5()
+{}
+
+template<class T>
+void*
+T5<T>::operator new(size_t)
+{ return 0; }
+
+template<class T>
+void
+T5<T>::operator delete(void *pointer)
+{ }
+
+template<class T>
+int
+T5<T>::value()
+{ return val; }
+
+
+#if ! defined(__GNUC__) || defined(GCC_BUG)
+template<class T>
+T T5<T>::X;
+#endif
+
+
+
+
+T5<char> t5c(1);
+T5<int> t5i(2);
+T5<int (*)(char, void *)> t5fi1(3);
+T5<int (*)(int, double **, void *)> t5fi2(4);
+
+
+
+
+
+
+class x {
+public:
+ int (*manage[5])(double,
+ void *(*malloc)(unsigned size),
+ void (*free)(void *pointer));
+ int (*device[5])(int open(const char *, unsigned mode, unsigned perms, int extra = 0),
+ int *(*read)(int fd, void *place, unsigned size),
+ int *(*write)(int fd, void *place, unsigned size),
+ void (*close)(int fd));
+};
+T5<x> t5x(5);
+
+#if !defined(__GNUC__) || (__GNUC__ >= 2 && __GNUC_MINOR__ >= 6)
+template class T5<char>;
+template class T5<int>;
+template class T5<int (*)(char, void *)>;
+template class T5<int (*)(int, double **, void *)>;
+template class T5<x>;
+#endif
+
+class T7 {
+public:
+ static int get();
+ static void put(int);
+};
+
+int
+T7::get()
+{ return 1; }
+
+void
+T7::put(int i)
+{
+ // nothing
+}
+
+// More template kinds. GDB 4.16 didn't handle these, but
+// Wildebeest does. Note: Assuming HP aCC is used to compile
+// this file; with g++ or HP cfront or other compilers the
+// demangling may not get done correctly.
+
+// Ordinary template, to be instantiated with different types
+template<class T>
+class Foo {
+public:
+ int x;
+ T t;
+ T foo (int, T);
+};
+
+
+template<class T> T Foo<T>::foo (int i, T tt)
+{
+ return tt;
+}
+
+// Template with int parameter
+
+template<class T, int sz>
+class Bar {
+public:
+ int x;
+ T t;
+ T bar (int, T);
+};
+
+
+template<class T, int sz> T Bar<T, sz>::bar (int i, T tt)
+{
+ if (i < sz)
+ return tt;
+ else
+ return 0;
+}
+
+// function template with int parameter
+template<class T> int dummy (T tt, int i)
+{
+ return tt;
+}
+
+// Template with partial specializations
+template<class T1, class T2>
+class Spec {
+public:
+ int x;
+ T1 spec (T2);
+};
+
+template<class T1, class T2>
+T1 Spec<T1, T2>::spec (T2 t2)
+{
+ return 0;
+}
+
+template<class T>
+class Spec<T, T*> {
+public:
+ int x;
+ T spec (T*);
+};
+
+template<class T>
+T Spec<T, T*>::spec (T * tp)
+{
+ return *tp;
+}
+
+// Template with char parameter
+template<class T, char sz>
+class Baz {
+public:
+ int x;
+ T t;
+ T baz (int, T);
+};
+
+template<class T, char sz> T Baz<T, sz>::baz (int i, T tt)
+{
+ if (i < sz)
+ return tt;
+ else
+ return 0;
+}
+
+// Template with char * parameter
+template<class T, char * sz>
+class Qux {
+public:
+ int x;
+ T t;
+ T qux (int, T);
+};
+
+template<class T, char * sz> T Qux<T, sz>::qux (int i, T tt)
+{
+ if (sz[0] == 'q')
+ return tt;
+ else
+ return 0;
+}
+
+// Template with a function pointer parameter
+template<class T, int (*f)(int) >
+class Qux1 {
+public:
+ int x;
+ T t;
+ T qux (int, T);
+};
+
+template<class T, int (*f)(int)> T Qux1<T, f>::qux (int i, T tt)
+{
+ if (f != 0)
+ return tt;
+ else
+ return 0;
+}
+
+// Some functions to provide as arguments to template
+int gf1 (int a) {
+ return a * 2 + 13;
+}
+int gf2 (int a) {
+ return a * 2 + 26;
+}
+
+char string[3];
+
+
+// Template for nested instantiations
+
+template<class T>
+class Garply {
+public:
+ int x;
+ T t;
+ T garply (int, T);
+};
+
+template<class T> T Garply<T>::garply (int i, T tt)
+{
+ if (i > x)
+ return tt;
+ else
+ {
+ x += i;
+ return tt;
+ }
+}
+
+
+int main()
+{
+ int i;
+#ifdef usestubs
+ set_debug_traps();
+ breakpoint();
+#endif
+ i = i + 1;
+
+ // New tests added here
+
+ Foo<int> fint;
+ Foo<char> fchar;
+ Foo<volatile char *> fvpchar;
+
+ Bar<int, 33> bint;
+ Bar<int, (4 > 3)> bint2;
+
+ Baz<int, 's'> bazint;
+ Baz<char, 'a'> bazint2;
+
+ Qux<char, string> quxint2;
+ Qux<int, string> quxint;
+
+ Qux1<int, gf1> qux11;
+
+ int x = fint.foo(33, 47);
+ char c = fchar.foo(33, 'x');
+ volatile char * cp = fvpchar.foo(33, 0);
+
+ int y = dummy<int> (400, 600);
+
+ int z = bint.bar(55, 66);
+ z += bint2.bar(55, 66);
+
+ c = bazint2.baz(4, 'y');
+ c = quxint2.qux(4, 'z');
+
+ y = bazint.baz(4,3);
+ y = quxint.qux(4, 22);
+ y += qux11.qux(4, 22);
+
+ y *= gf1(y) - gf2(y);
+
+ Spec<int, char> sic;
+ Spec<int, int *> siip;
+
+ sic.spec ('c');
+ siip.spec (&x);
+
+ Garply<int> f;
+ Garply<char> fc;
+ f.x = 13;
+
+ Garply<Garply<char> > nf;
+ nf.x = 31;
+
+ x = f.garply (3, 4);
+
+ fc = nf.garply (3, fc);
+
+ y = x + fc.x;
+
+
+ return 0;
+
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/gdb/testsuite/gdb.c++/templates.exp b/gdb/testsuite/gdb.c++/templates.exp
new file mode 100644
index 00000000000..ee25eaa9ad7
--- /dev/null
+++ b/gdb/testsuite/gdb.c++/templates.exp
@@ -0,0 +1,202 @@
+# Copyright (C) 1992, 1996, 1997 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file was written by Fred Fish. (fnf@cygnus.com)
+
+set ws "\[\r\n\t \]+"
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+set testfile "templates"
+set srcfile ${testfile}.cc
+set binfile ${objdir}/${subdir}/${testfile}
+
+# Create and source the file that provides information about the compiler
+# used to compile the test case.
+if [get_compiler_info ${binfile} "c++"] {
+ return -1
+}
+source ${binfile}.ci
+
+# if we are on HPUX and we are not compiled with gcc, then skip these tests.
+
+if [istarget hppa*-*-hpux*] {
+ if {!$gcc_compiled} {
+ continue
+ }
+}
+
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug c++}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+source ${binfile}.ci
+
+#
+# Test printing of the types of templates.
+#
+
+proc test_ptype_of_templates {} {
+ global gdb_prompt
+ global ws
+
+ send_gdb "ptype T5<int>\n"
+ gdb_expect {
+ -re "type = class T5<int> \{${ws}public:${ws}static int X;${ws}int x;${ws}int val;${ws}T5\\<int> & operator=\\(T5<int> const &\\);${ws}T5\\(int\\);${ws}T5\\(T5<int> const &\\);${ws}~T5\\(void\\);${ws}static void \\* operator new\\(unsigned (int|long)\\);${ws}static void operator delete\\(void \\*\\);${ws}int value\\(void\\);${ws}\}\r\n$gdb_prompt $" {
+ pass "ptype T5<int>"
+ }
+ -re "type = class T5<int> \{${ws}public:${ws}static int X;${ws}int x;${ws}int val;((${ws}T5\\<int> & operator=\\(T5<int> const &\\);)|(${ws}T5\\(int\\);)|(${ws}T5\\(T5<int> const &\\);)|(${ws}~T5\\(void\\);)|(${ws}static void \\* operator new\\(unsigned (int|long)\\);)|(${ws}static void operator delete\\(void \\*\\);)|(${ws}int value\\(void\\);))*${ws}\}\r\n$gdb_prompt $" {
+ pass "ptype T5<int> (obsolescent gcc or gdb)"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "ptype T5<int>"
+ }
+ timeout {
+ fail "ptype T5<int> (timeout)"
+ }
+ }
+
+ send_gdb "ptype t5i\n"
+ gdb_expect {
+ -re "type = class T5<int> \{${ws}public:${ws}static int X;${ws}int x;${ws}int val;${ws}T5<int> & operator=\\(T5<int> const &\\);${ws}T5\\(int\\);${ws}T5\\(T5<int> const &\\);${ws}~T5\\(void\\);${ws}static void \\* operator new\\(unsigned (int|long)\\);${ws}static void operator delete\\(void \\*\\);${ws}int value\\(void\\);${ws}\}\r\n$gdb_prompt $" {
+ pass "ptype t5i"
+ }
+ -re "type = class T5<int> \{${ws}public:${ws}static int X;${ws}int x;${ws}int val;((${ws}T5<int> & operator=\\(T5<int> const &\\);)|(${ws}T5\\(int\\);)|(${ws}T5\\(T5<int> const &\\);)|(${ws}~T5\\(void\\);)|(${ws}static void \\* operator new\\(unsigned (int|long)\\);)|(${ws}static void operator delete\\(void \\*\\);)|(${ws}int value\\(void\\);))*${ws}\}\r\n$gdb_prompt $" {
+ pass "ptype t5i (obsolescent gcc or gdb)"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "ptype t5i"
+ }
+ timeout {
+ fail "ptype t5i (timeout)"
+ }
+ }
+}
+
+#
+# Test breakpoint setting on template methods.
+#
+
+proc test_template_breakpoints {} {
+ global gdb_prompt
+ global testfile
+ global srcdir
+
+ send_gdb "break T5<int>::T5\n"
+ gdb_expect {
+ -re "0. cancel.*\[\r\n\]*.1. all.*\[\r\n\]*.2. T5<int>::T5\\(int\\) at .*\[\r\n\]*.3. T5<int>::T5\\(T5<int> const &\\) at .*\[\r\n\]*> $" {
+ gdb_test "0" \
+ "cancelled" \
+ "constructor breakpoint (obsolete format!)"
+ }
+ -re ".0. cancel\[\r\n\]*.1. all\[\r\n\]*.2. T5<int>::T5\\(T5<int> const &\\) at .*templates.cc:.*\[\r\n\]*.3. T5<int>::T5\\(int\\) at .*templates.cc:.*\[\r\n\]*> $" {
+ gdb_test "0" \
+ "cancelled" \
+ "constructor breakpoint"
+ }
+ -re ".*$gdb_prompt $" { fail "constructor breakpoint" }
+ default { fail "constructor breakpoint (timeout)" }
+ }
+
+ gdb_test "break T5<int>::~T5" \
+ "Breakpoint.*at.* file .*${testfile}.cc, line.*" \
+ "destructor breakpoint"
+
+ gdb_test "break T5<int>::value" \
+ "Breakpoint.*at.* file .*${testfile}.cc, line.*" \
+ "value method breakpoint"
+
+ delete_breakpoints
+}
+
+#
+# Test calling of template methods.
+#
+
+proc test_template_calls {} {
+ global gdb_prompt
+
+ if [target_info exists gdb,cannot_call_functions] {
+ setup_xfail "*-*-*" 2416
+ fail "This target can not call functions"
+ return
+ }
+
+ send_gdb "print t5i.value()\n"
+ gdb_expect {
+ -re ".* = 2\[\r\n\]*$gdb_prompt $" { pass "print t5i.value()" }
+ -re "Cannot invoke functions on this machine.*$gdb_prompt $" {
+ fail "print t5i.value()"
+ }
+ -re ".*$gdb_prompt $" { fail "print t5i.value()" }
+ default { fail "print t5i.value() (timeout)" }
+ }
+}
+
+
+proc do_tests {} {
+ global prms_id
+ global bug_id
+ global subdir
+ global objdir
+ global srcdir
+ global binfile
+ global gdb_prompt
+ global supports_template_debugging
+
+ set prms_id 0
+ set bug_id 0
+
+ # Start with a fresh gdb.
+
+ gdb_exit
+ gdb_start
+ gdb_reinitialize_dir $srcdir/$subdir
+ gdb_load $binfile
+
+ if { !$supports_template_debugging } {
+ warning "compiler lacks debugging info for templates; tests suppressed." 0
+ return
+ }
+
+ # Get the debug format for the compiled test case. If that
+ # format is DWARF 1 then just skip all the tests since none of
+ # them will pass.
+
+ if [ runto_main] then {
+ get_debug_format
+ if [ setup_xfail_format "DWARF 1" ] then {
+ fail "C++ tests skipped due to limited C++ support in DWARF 1 debug format"
+ return
+ }
+ clear_xfail "*-*-*"
+ }
+
+ test_ptype_of_templates
+ test_template_breakpoints
+
+ if [ runto_main] {
+ test_template_calls
+ }
+}
+
+do_tests
+
diff --git a/gdb/testsuite/gdb.c++/userdef.cc b/gdb/testsuite/gdb.c++/userdef.cc
new file mode 100644
index 00000000000..9ad6c869b6e
--- /dev/null
+++ b/gdb/testsuite/gdb.c++/userdef.cc
@@ -0,0 +1,339 @@
+#include <iostream.h>
+
+void marker1()
+{
+ return;
+}
+
+class A1 {
+ int x;
+ int y;
+
+friend ostream& operator<<(ostream& outs, A1 one);
+
+public:
+
+ A1(int a, int b)
+ {
+ x=a;
+ y=b;
+ }
+
+A1 operator+=(int value);
+A1 operator+(const A1&);
+A1 operator-(const A1&);
+A1 operator%(const A1&);
+int operator==(const A1&);
+int operator!=(const A1&);
+int operator&&(const A1&);
+int operator||(const A1&);
+A1 operator<<(int);
+A1 operator>>(int);
+A1 operator|(const A1&);
+A1 operator^(const A1&);
+A1 operator&(const A1&);
+int operator<(const A1&);
+int operator<=(const A1&);
+int operator>=(const A1&);
+int operator>(const A1&);
+A1 operator*(const A1&);
+A1 operator/(const A1&);
+A1 operator=(const A1&);
+
+A1 operator~();
+A1 operator-();
+int operator!();
+A1 operator++();
+A1 operator++(int);
+A1 operator--();
+A1 operator--(int);
+
+};
+
+
+A1 A1::operator+(const A1& second)
+{
+ A1 sum(0,0);
+ sum.x = x + second.x;
+ sum.y = y + second.y;
+
+ return (sum);
+}
+
+A1 A1::operator*(const A1& second)
+{
+ A1 product(0,0);
+ product.x = this->x * second.x;
+ product.y = this->y * second.y;
+
+ return product;
+}
+
+A1 A1::operator-(const A1& second)
+{
+ A1 diff(0,0);
+ diff.x = x - second.x;
+ diff.y = y - second.y;
+
+ return diff;
+}
+
+A1 A1::operator/(const A1& second)
+{
+ A1 div(0,0);
+ div.x = x / second.x;
+ div.y = y / second.y;
+
+ return div;
+}
+
+A1 A1::operator%(const A1& second)
+{
+ A1 rem(0,0);
+ rem.x = x % second.x;
+ rem.y = y % second.y;
+
+ return rem;
+}
+
+int A1::operator==(const A1& second)
+{
+ int a = (x == second.x);
+ int b = (y == second.y);
+
+ return (a && b);
+}
+
+int A1::operator!=(const A1& second)
+{
+ int a = (x != second.x);
+ int b = (y != second.y);
+
+ return (a || b);
+}
+
+int A1::operator&&(const A1& second)
+{
+ return ( x && second.x);
+}
+
+int A1::operator||(const A1& second)
+{
+ return ( x || second.x);
+}
+
+A1 A1::operator<<(int value)
+{
+ A1 lshft(0,0);
+ lshft.x = x << value;
+ lshft.y = y << value;
+
+ return lshft;
+}
+
+A1 A1::operator>>(int value)
+{
+ A1 rshft(0,0);
+ rshft.x = x >> value;
+ rshft.y = y >> value;
+
+ return rshft;
+}
+
+A1 A1::operator|(const A1& second)
+{
+ A1 abitor(0,0);
+ abitor.x = x | second.x;
+ abitor.y = y | second.y;
+
+ return abitor;
+}
+
+A1 A1::operator^(const A1& second)
+{
+ A1 axor(0,0);
+ axor.x = x ^ second.x;
+ axor.y = y ^ second.y;
+
+ return axor;
+}
+
+A1 A1::operator&(const A1& second)
+{
+ A1 abitand(0,0);
+ abitand.x = x & second.x;
+ abitand.y = y & second.y;
+
+ return abitand;
+}
+
+int A1::operator<(const A1& second)
+{
+ A1 b(0,0);
+ b.x = 3;
+ return (x < second.x);
+}
+
+int A1::operator<=(const A1& second)
+{
+ return (x <= second.x);
+}
+
+int A1::operator>=(const A1& second)
+{
+ return (x >= second.x);
+}
+
+int A1::operator>(const A1& second)
+{
+ return (x > second.x);
+}
+
+int A1::operator!(void)
+{
+ return (!x);
+}
+
+A1 A1::operator-(void)
+{
+ A1 neg(0,0);
+ neg.x = -x;
+ neg.y = -y;
+
+ return (neg);
+}
+
+A1 A1::operator~(void)
+{
+ A1 acompl(0,0);
+ acompl.x = ~x;
+ acompl.y = ~y;
+
+ return (acompl);
+}
+
+A1 A1::operator++() // pre increment
+{
+ x = x +1;
+
+ return (*this);
+}
+
+A1 A1::operator++(int) // post increment
+{
+ y = y +1;
+
+ return (*this);
+}
+
+A1 A1::operator--() // pre decrement
+{
+ x = x -1;
+
+ return (*this);
+}
+
+A1 A1::operator--(int) // post decrement
+{
+ y = y -1;
+
+ return (*this);
+}
+
+
+A1 A1::operator=(const A1& second)
+{
+
+ x = second.x;
+ y = second.y;
+
+ return (*this);
+}
+
+A1 A1::operator+=(int value)
+{
+
+ x += value;
+ y += value;
+
+ return (*this);
+}
+
+ostream& operator<<(ostream& outs, A1 one)
+{
+ return (outs << endl << "x = " << one.x << endl << "y = " << one.y << endl << "-------" << endl);
+}
+
+int main (void)
+{
+ A1 one(2,3);
+ A1 two(4,5);
+ A1 three(0,0);
+ int val;
+
+ marker1();
+ cout << one;
+ cout << two;
+ three = one + two;
+ cout << "+ " << three;
+ three = one - two;
+ cout << "- " << three;
+ three = one * two;
+ cout <<"* " << three;
+ three = one / two;
+ cout << "/ " << three;
+ three = one % two;
+ cout << "% " << three;
+ three = one | two;
+ cout << "| " <<three;
+ three = one ^ two;
+ cout << "^ " <<three;
+ three = one & two;
+ cout << "& "<< three;
+
+ val = one && two;
+ cout << "&& " << val << endl << "-----"<<endl;
+ val = one || two;
+ cout << "|| " << val << endl << "-----"<<endl;
+ val = one == two;
+ cout << " == " << val << endl << "-----"<<endl;
+ val = one != two;
+ cout << "!= " << val << endl << "-----"<<endl;
+ val = one >= two;
+ cout << ">= " << val << endl << "-----"<<endl;
+ val = one <= two;
+ cout << "<= " << val << endl << "-----"<<endl;
+ val = one < two;
+ cout << "< " << val << endl << "-----"<<endl;
+ val = one > two;
+ cout << "> " << val << endl << "-----"<<endl;
+
+ three = one << 2;
+ cout << "lsh " << three;
+ three = one >> 2;
+ cout << "rsh " << three;
+
+ three = one;
+ cout << " = "<< three;
+ three += 5;
+ cout << " += "<< three;
+
+ val = (!one);
+ cout << "! " << val << endl << "-----"<<endl;
+ three = (-one);
+ cout << "- " << three;
+ three = (~one);
+ cout << " ~" << three;
+ three++;
+ cout << "postinc " << three;
+ three--;
+ cout << "postdec " << three;
+
+ --three;
+ cout << "predec " << three;
+ ++three;
+ cout << "preinc " << three;
+
+ return 0;
+
+}
diff --git a/gdb/testsuite/gdb.c++/userdef.exp b/gdb/testsuite/gdb.c++/userdef.exp
new file mode 100644
index 00000000000..c9bb0530f37
--- /dev/null
+++ b/gdb/testsuite/gdb.c++/userdef.exp
@@ -0,0 +1,317 @@
+# Copyright (C) 1998 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# written by Elena Zannoni (ezannoni@cygnus.com)
+#
+# testing overloaded operators resolution.
+#
+# source file "userdef.cc"
+#
+
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+# Check to see if we have an executable to test. If not, then either we
+# haven't tried to compile one, or the compilation failed for some reason.
+# In either case, just notify the user and skip the tests in this file.
+
+set testfile "userdef"
+set srcfile ${testfile}.cc
+set binfile ${objdir}/${subdir}/${testfile}
+
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug c++}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+
+if ![runto_main] then {
+ perror "couldn't run to breakpoint"
+ continue
+}
+
+send_gdb "break marker1\n" ; gdb_expect -re ".*$gdb_prompt $"
+ send_gdb "cont\n"
+ gdb_expect {
+ -re "Break.* marker1 \\(\\) at .*:$decimal.*$gdb_prompt $" {
+ send_gdb "up\n"
+ gdb_expect {
+ -re ".*$gdb_prompt $" { pass "up from marker1" }
+ timeout { fail "up from marker1" }
+ }
+ }
+ -re "$gdb_prompt $" { fail "continue to marker1" }
+ timeout { fail "(timeout) continue to marker1" }
+ }
+
+
+ setup_xfail hppa_*_*
+send_gdb "print one+two\n"
+gdb_expect {
+ -re "FIXME.*$gdb_prompt $" {
+ pass "print value of one + two"
+ }
+ -re ".*$gdb_prompt $" { xfail "print value of one two" }
+ timeout { fail "(timeout) print value of one two" }
+ }
+
+send_gdb "print one-two\n"
+gdb_expect {
+ -re ".*FIXME.*$gdb_prompt $" {
+ pass "print value of one - two"
+ }
+ -re ".*$gdb_prompt $" { xfail "print value of one - two" }
+ timeout { fail "(timeout) print value of one - two" }
+ }
+
+send_gdb "print one*two\n"
+gdb_expect {
+ -re ".*FIXME.*$gdb_prompt $" {
+ pass "print value of one * two"
+ }
+ -re ".*$gdb_prompt $" { xfail "print value of one * two" }
+ timeout { fail "(timeout) print value of one * two" }
+ }
+
+send_gdb "print one/two\n"
+gdb_expect {
+ -re ".*FIXME.*$gdb_prompt $" {
+ pass "print value of one / two"
+ }
+ -re ".*$gdb_prompt $" { xfail "print value of one / two" }
+ timeout { fail "(timeout) print value of one / two" }
+ }
+
+send_gdb "print one%two\n"
+gdb_expect {
+ -re ".*FIXME.*$gdb_prompt $" {
+ pass "print value of one % two"
+ }
+ -re ".*$gdb_prompt $" { xfail "print value of one % two" }
+ timeout { fail "(timeout) print value of one % two" }
+ }
+
+send_gdb "print one&&two\n"
+gdb_expect {
+ -re ".*FIXME.*$gdb_prompt $" {
+ pass "print value of one && two"
+ }
+ -re ".*$gdb_prompt $" { xfail "print value of one && two" }
+ timeout { fail "(timeout) print value of one && two" }
+ }
+
+send_gdb "print one||two\n"
+gdb_expect {
+ -re ".*FIXME.*$gdb_prompt $" {
+ pass "print value of one|| two"
+ }
+ -re ".*$gdb_prompt $" { xfail "print value of one|| two" }
+ timeout { fail "(timeout) print value of one|| two" }
+ }
+
+send_gdb "print one&two\n"
+gdb_expect {
+ -re ".*FIXME.*$gdb_prompt $" {
+ pass "print value of one & two"
+ }
+ -re ".*$gdb_prompt $" { xfail "print value of one & two" }
+ timeout { fail "(timeout) print value of one & two" }
+ }
+
+send_gdb "print one|two\n"
+gdb_expect {
+ -re ".*FIXME.*$gdb_prompt $" {
+ pass "print value of one | two"
+ }
+ -re ".*$gdb_prompt $" { xfail "print value of one | two" }
+ timeout { fail "(timeout) print value of one | two" }
+ }
+
+send_gdb "print one ^ two\n"
+gdb_expect {
+ -re ".*FIXME.*$gdb_prompt $" {
+ pass "print value of one ^ two"
+ }
+ -re ".*$gdb_prompt $" { xfail "print value of one ^ two" }
+ timeout { fail "(timeout) print value of one ^ two" }
+ }
+
+send_gdb "print one < two\n"
+gdb_expect {
+ -re ".*FIXME.*$gdb_prompt $" {
+ pass "print value of one < two"
+ }
+ -re ".*$gdb_prompt $" { xfail "print value of one < two" }
+ timeout { fail "(timeout) print value of one < two" }
+ }
+
+send_gdb "print one <= two\n"
+gdb_expect {
+ -re ".*FIXME.*$gdb_prompt $" {
+ pass "print value of one <= two"
+ }
+ -re ".*$gdb_prompt $" { xfail "print value of one <= two" }
+ timeout { fail "(timeout) print value of one <= two" }
+ }
+
+send_gdb "print one > two\n"
+gdb_expect {
+ -re ".*FIXME.*$gdb_prompt $" {
+ pass "print value of one > two"
+ }
+ -re ".*$gdb_prompt $" { xfail "print value of one > two" }
+ timeout { fail "(timeout) print value of one > two" }
+ }
+
+send_gdb "print one >= two\n"
+gdb_expect {
+ -re ".*FIXME.*$gdb_prompt $" {
+ pass "print value of one >= two"
+ }
+ -re ".*$gdb_prompt $" { xfail "print value of one >= two" }
+ timeout { fail "(timeout) print value of one >= two" }
+ }
+
+
+send_gdb "print one==two\n"
+gdb_expect {
+ -re ".*FIXME.*$gdb_prompt $" {
+ pass "print value of one == two"
+ }
+ -re ".*$gdb_prompt $" { xfail "print value of one == two" }
+ timeout { fail "(timeout) print value of one == two" }
+ }
+
+send_gdb "print one!=two\n"
+gdb_expect {
+ -re ".*FIXME.*$gdb_prompt $" {
+ pass "print value of one != two"
+ }
+ -re ".*$gdb_prompt $" { xfail "print value of one != two" }
+ timeout { fail "(timeout) print value of one != two" }
+ }
+
+send_gdb "print one<<31\n"
+gdb_expect {
+ -re ".*FIXME.*$gdb_prompt $" {
+ pass "print value of one<<31"
+ }
+ -re ".*$gdb_prompt $" { xfail "print value of one<<31" }
+ timeout { fail "(timeout) print value of one<<31" }
+ }
+
+send_gdb "print one>>31\n"
+gdb_expect {
+ -re ".*FIXME.*$gdb_prompt $" {
+ pass "print value of one>>31"
+ }
+ -re ".*$gdb_prompt $" { xfail "print value of one>>31" }
+ timeout { fail "(timeout) print value of one>>31" }
+ }
+
+send_gdb "print !one\n"
+gdb_expect {
+ -re ".*FIXME.*$gdb_prompt $" {
+ pass "print value of !one"
+ }
+ -re ".*$gdb_prompt $" { xfail "print value of !one" }
+ timeout { fail "(timeout) print value of !one" }
+ }
+
+send_gdb "print ~one\n"
+gdb_expect {
+ -re ".*FIXME.*$gdb_prompt $" {
+ pass "print value of ~one"
+ }
+ -re ".*$gdb_prompt $" { xfail "print value of ~one" }
+ timeout { fail "(timeout) print value of ~one" }
+ }
+
+send_gdb "print -one\n"
+gdb_expect {
+ -re ".*FIXME.*$gdb_prompt $" {
+ pass "print value of -one"
+ }
+ -re ".*$gdb_prompt $" { xfail "print value of -one" }
+ timeout { fail "(timeout) print value of -one" }
+ }
+
+send_gdb "print one++\n"
+gdb_expect {
+ -re ".*FIXME.*$gdb_prompt $" {
+ pass "print value of one++"
+ }
+ -re ".*$gdb_prompt $" { xfail "print value of one++" }
+ timeout { fail "(timeout) print value of one++" }
+ }
+
+send_gdb "print ++one\n"
+gdb_expect {
+ -re ".*FIXME.*$gdb_prompt $" {
+ pass "print value of ++one>>31"
+ }
+ -re ".*$gdb_prompt $" { xfail "print value of ++one" }
+ timeout { fail "(timeout) print value of ++one" }
+ }
+
+send_gdb "print one--\n"
+gdb_expect {
+ -re ".*.FIXME*$gdb_prompt $" {
+ pass "print value of one-->>31"
+ }
+ -re ".*$gdb_prompt $" { xfail "print value of one-->>31" }
+ timeout { fail "(timeout) print value of one-->>31" }
+ }
+
+send_gdb "print --one\n"
+gdb_expect {
+ -re ".*FIXME.*$gdb_prompt $" {
+ pass "print value of --one"
+ }
+ -re ".*$gdb_prompt $" { xfail "print value of --one" }
+ timeout { fail "(timeout) print value of --one" }
+ }
+
+send_gdb "print one+=7\n"
+gdb_expect {
+ -re ".*FIXME.*$gdb_prompt $" {
+ pass "print value of one+=7"
+ }
+ -re ".*$gdb_prompt $" { xfail "print value of one+=7" }
+ timeout { fail "(timeout) print value of one+=7" }
+ }
+
+send_gdb "print two=one\n"
+gdb_expect {
+ -re ".*FIXME.*$gdb_prompt $" {
+ pass "print value of two=one"
+ }
+ -re ".*$gdb_prompt $" { xfail "print value of two=one" }
+ timeout { fail "(timeout) print value of two=one" }
+ }
+
+gdb_exit
+return 0
diff --git a/gdb/testsuite/gdb.c++/virtfunc.cc b/gdb/testsuite/gdb.c++/virtfunc.cc
new file mode 100644
index 00000000000..883d502ea11
--- /dev/null
+++ b/gdb/testsuite/gdb.c++/virtfunc.cc
@@ -0,0 +1,199 @@
+// Pls try the following program on virtual functions and try to do print on
+// most of the code in main(). Almost none of them works !
+
+//
+// The inheritance structure is:
+//
+// V : VA VB
+// A : (V)
+// B : A
+// D : AD (V)
+// C : (V)
+// E : B (V) D C
+//
+
+class VA
+{
+public:
+ int va;
+};
+
+class VB
+{
+public:
+ int vb;
+ int fvb();
+ virtual int vvb();
+};
+
+class V : public VA, public VB
+{
+public:
+ int f();
+ virtual int vv();
+ int w;
+};
+
+class A : virtual public V
+{
+public:
+ virtual int f();
+private:
+ int a;
+};
+
+class B : public A
+{
+public:
+ int f();
+private:
+ int b;
+};
+
+class C : public virtual V
+{
+public:
+ int c;
+};
+
+class AD
+{
+public:
+ virtual int vg() = 0;
+};
+
+class D : public AD, virtual public V
+{
+public:
+ static void s();
+ virtual int vg();
+ virtual int vd();
+ int fd();
+ int d;
+};
+
+class E : public B, virtual public V, public D, public C
+{
+public:
+ int f();
+ int vg();
+ int vv();
+ int e;
+};
+
+D dd;
+D* ppd = &dd;
+AD* pAd = &dd;
+
+A a;
+B b;
+C c;
+D d;
+E e;
+V v;
+VB vb;
+
+
+A* pAa = &a;
+A* pAe = &e;
+
+B* pBe = &e;
+
+D* pDd = &d;
+D* pDe = &e;
+
+V* pVa = &a;
+V* pVv = &v;
+V* pVe = &e;
+V* pVd = &d;
+
+AD* pADe = &e;
+
+E* pEe = &e;
+
+VB* pVB = &vb;
+
+void init()
+{
+ a.vb = 1;
+ b.vb = 2;
+ c.vb = 3;
+ d.vb = 4;
+ e.vb = 5;
+ v.vb = 6;
+ vb.vb = 7;
+
+ d.d = 1;
+ e.d = 2;
+}
+
+extern "C" int printf(const char *, ...);
+
+int all_count = 0;
+int failed_count = 0;
+
+#define TEST(EXPR, EXPECTED) \
+ ret = EXPR; \
+ if (ret != EXPECTED) {\
+ printf("Failed %s is %d, should be %d!\n", #EXPR, ret, EXPECTED); \
+ failed_count++; } \
+ all_count++;
+
+int ret;
+
+void test_calls()
+{
+ TEST(pAe->f(), 20);
+ TEST(pAa->f(), 1);
+
+ TEST(pDe->vg(), 202);
+ TEST(pADe->vg(), 202);
+ TEST(pDd->vg(), 101);
+
+ TEST(pEe->vvb(), 411);
+
+ TEST(pVB->vvb(), 407);
+
+ TEST(pBe->vvb(), 411);
+ TEST(pDe->vvb(), 411);
+
+ TEST(pEe->vd(), 282);
+ TEST(pEe->fvb(), 311);
+
+ TEST(pEe->D::vg(), 102);
+ printf("Did %d tests, of which %d failed.\n", all_count, failed_count);
+}
+#ifdef usestubs
+extern "C" {
+ void set_debug_traps();
+ void breakpoint();
+};
+#endif
+
+main()
+{
+#ifdef usestubs
+ set_debug_traps();
+ breakpoint();
+#endif
+ init();
+
+ e.w = 7;
+ e.vb = 11;
+
+ test_calls();
+}
+
+int A::f() {return 1;}
+int B::f() {return 2;}
+void D::s() {}
+int E::f() {return 20;}
+int D::vg() {return 100+d;}
+int E::vg() {return 200+d;}
+int V::f() {return 600+w;}
+int V::vv() {return 400+w;}
+int E::vv() {return 450+w;}
+int D::fd() {return 250+d;}
+int D::vd() {return 280+d;}
+int VB::fvb() {return 300+vb;}
+int VB::vvb() {return 400+vb;}
diff --git a/gdb/testsuite/gdb.c++/virtfunc.exp b/gdb/testsuite/gdb.c++/virtfunc.exp
new file mode 100644
index 00000000000..d0db7557fd1
--- /dev/null
+++ b/gdb/testsuite/gdb.c++/virtfunc.exp
@@ -0,0 +1,751 @@
+# Copyright (C) 1992, 1994, 1997 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file was written by Fred Fish. (fnf@cygnus.com)
+
+set ws "\[\r\n\t \]+"
+set nl "\[\r\n\]+"
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+set testfile "virtfunc"
+set srcfile ${testfile}.cc
+set binfile ${objdir}/${subdir}/${testfile}
+
+if [get_compiler_info ${binfile} "c++"] {
+ return -1
+}
+
+# if we are on HPUX and we are not compiled with gcc, then skip these tests.
+
+if [istarget hppa*-*-hpux*] {
+ if {!$gcc_compiled} {
+ continue
+ }
+}
+
+
+
+# Check to see if we have an executable to test. If not, then either we
+# haven't tried to compile one, or the compilation failed for some reason.
+# In either case, just notify the user and skip the tests in this file.
+
+set src "${srcdir}/${subdir}/${srcfile}"
+if { [gdb_compile "${src}" "${binfile}" executable {c++ debug}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+proc gdb_virtfunc_init {} {
+ global srcdir subdir binfile
+ global gdb_prompt
+
+ gdb_reinitialize_dir $srcdir/$subdir
+ gdb_load $binfile
+
+ send_gdb "set language c++\n"
+ gdb_expect -re "$gdb_prompt $"
+ send_gdb "set width 0\n"
+ gdb_expect -re "$gdb_prompt $"
+}
+
+proc gdb_virtfunc_restart {} {
+ gdb_exit;
+ gdb_start;
+ gdb_virtfunc_init;
+ runto 'test_calls(void)';
+}
+
+#
+# Test printing of the types of various classes.
+#
+
+proc test_ptype_of_classes {} {
+ global gdb_prompt
+ global ws
+ global nl
+
+ # This used to be a fail if it printed "struct" not "class". But
+ # since this struct doesn't use any special C++ features, it is
+ # considered right for GDB to print it as "struct".
+ send_gdb "ptype VA\n"
+ gdb_expect {
+ -re "type = (struct|class) VA \{(${ws}public:|)${ws}int va;${ws}VA & operator=\\(VA const &\\);${ws}VA\\(VA const &\\);${ws}VA\\(void\\);${ws}\}.*$gdb_prompt $" {
+ pass "ptype VA"
+ }
+ -re "type = (struct|class) VA \{(${ws}public:|)${ws}int va;((${ws}VA & operator=\\(VA const &\\);)|(${ws}VA\\(VA const &\\);)|(${ws}VA\\(void\\);))*${ws}\}.*$gdb_prompt $" {
+ pass "ptype VA (obsolescent gcc or gdb)"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "ptype VA"
+ }
+ timeout {
+ fail "ptype VA (timeout)"
+ }
+ }
+
+ send_gdb "ptype VB\n"
+ gdb_expect {
+ -re "type = class VB \{${ws}public:${ws}int vb;${ws}VB & operator=\\(VB const &\\);${ws}VB\\(VB const &\\);${ws}VB\\(void\\);${ws}int fvb\\(void\\);${ws}virtual int vvb\\(void\\);${ws}\}.*$gdb_prompt $" {
+ pass "ptype VB"
+ }
+ -re "type = class VB \{${ws}public:${ws}int vb;((${ws}VB & operator=\\(VB const &\\);)|(${ws}VB\\(VB const &\\);)|(${ws}VB\\(void\\);)|(${ws}int fvb\\(void\\);)|(${ws}virtual int vvb\\(void\\);))*${ws}\}.*$gdb_prompt $" {
+ pass "ptype VB (obsolescent gcc or gdb)"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "ptype VB"
+ }
+ timeout {
+ fail "ptype VB (timeout)"
+ }
+ }
+
+ send_gdb "ptype V\n"
+ gdb_expect {
+ -re "type = class V : public VA, public VB \{${ws}public:${ws}int w;${ws}V & operator=\\(V const &\\);${ws}V\\(V const &\\);${ws}V\\(void\\);${ws}int f\\(void\\);${ws}virtual int vv\\(void\\);${ws}\}$nl$gdb_prompt $" {
+ pass "ptype V"
+ }
+ -re "type = class V : public VA, public VB \{${ws}public:${ws}int w;((${ws}V & operator=\\(V const &\\);)|(${ws}V\\(V const &\\);)|(${ws}V\\(void\\);)|(${ws}int f\\(void\\);)|(${ws}virtual int vv\\(void\\);))*${ws}\}$nl$gdb_prompt $" {
+ pass "ptype V (obsolescent gcc or gdb)"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "ptype V"
+ }
+ timeout {
+ fail "ptype V (timeout)"
+ }
+ }
+
+ send_gdb "ptype A\n"
+ gdb_expect {
+ -re "type = class A : public virtual V \{${ws}private:${ws}V \[*\]+_vb\[\\\$\.\]+V;${ws}int a;${ws}public:${ws}A & operator=\\(A const &\\);${ws}A\\(int, A const &\\);${ws}A\\(int\\);${ws}virtual int f\\(void\\);${ws}\}$nl$gdb_prompt $" {
+ pass "ptype A"
+ }
+ -re "type = class A : public virtual V \{${ws}private:${ws}V \[*\]+_vb\[\\\$\.\]+V;${ws}int a;${ws}public:((${ws}A & operator=\\(A const &\\);)|(${ws}A\\(int, A const &\\);)|(${ws}A\\(int\\);)|(${ws}virtual int f\\(void\\);))*${ws}\}$nl$gdb_prompt $" {
+ pass "ptype A (obsolescent gcc or gdb)"
+ }
+ -re "type = class A : public virtual V \{${ws}private:${ws}V \[*\]+_vb.FOO;${ws}int a;${ws}public:${ws}virtual int f.void.;${ws}\}$nl$gdb_prompt $" {
+ # This happens because the type is defined only after it is
+ # too late.
+ fail "ptype A (known failure with gcc cygnus-2.4.5-930417)"
+ # Many of the rest of these tests have the same problem.
+ return 0
+ }
+ -re ".*$gdb_prompt $" {
+ fail "ptype A"
+ }
+ timeout {
+ fail "ptype A (timeout)"
+ }
+ }
+
+ send_gdb "ptype B\n"
+ gdb_expect {
+ -re "type = class B : public A \{${ws}private:${ws}int b;${ws}public:${ws}B & operator=\\(B const &\\);${ws}B\\(int, B const &\\);${ws}B\\(int\\);${ws}virtual int f\\(void\\);${ws}\}$nl$gdb_prompt $" {
+ pass "ptype B"
+ }
+ -re "type = class B : public A \{${ws}private:${ws}int b;${ws}public:((${ws}B & operator=\\(B const &\\);)|(${ws}B\\(int, B const &\\);)|(${ws}B\\(int\\);)|(${ws}virtual int f\\(void\\);))*${ws}\}$nl$gdb_prompt $" {
+ pass "ptype B (obsolescent gcc or gdb)"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "ptype B"
+ }
+ timeout {
+ fail "ptype B (timeout)"
+ }
+ }
+
+ send_gdb "ptype C\n"
+ gdb_expect {
+ -re "type = class C : public virtual V \{${ws}private:${ws}V \[*\]+_vb.V;${ws}public:${ws}int c;${ws}C & operator=\\(C const &\\);${ws}C\\(int, C const &\\);${ws}C\\(int\\);${ws}\}$nl$gdb_prompt $" {
+ pass "ptype C"
+ }
+ -re "type = class C : public virtual V \{${ws}private:${ws}V \[*\]+_vb.V;${ws}public:${ws}int c;((${ws}C & operator=\\(C const &\\);)|(${ws}C\\(int, C const &\\);)|(${ws}C\\(int\\);))*${ws}\}$nl$gdb_prompt $" {
+ pass "ptype C (obsolescent gcc or gdb)"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "ptype C"
+ }
+ timeout {
+ fail "ptype C (timeout)"
+ }
+ }
+
+ send_gdb "ptype AD\n"
+ gdb_expect {
+ -re "type = class AD \{${ws}public:${ws}AD & operator=\\(AD const &\\);${ws}AD\\(AD const &\\);${ws}AD\\(void\\);${ws}virtual int vg\\(void\\);${ws}\}$nl$gdb_prompt $" {
+ pass "ptype AD"
+ }
+ -re "type = class AD \{${ws}public:((${ws}AD & operator=\\(AD const &\\);)|(${ws}AD\\(AD const &\\);)|(${ws}AD\\(void\\);)|(${ws}virtual int vg\\(void\\);))*${ws}\}$nl$gdb_prompt $" {
+ pass "ptype AD (obsolescent gcc or gdb)"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "ptype AD"
+ }
+ timeout {
+ fail "ptype AD (timeout)"
+ }
+ }
+
+ send_gdb "ptype D\n"
+ gdb_expect {
+ -re "type = class D : public AD, public virtual V \{${ws}private:${ws}V \[*\]+_vb.V;${ws}public:${ws}int d;${ws}D & operator=\\(D const &\\);${ws}D\\(int, D const &\\);${ws}D\\(int\\);${ws}static void s\\(void\\);${ws}virtual int vg\\(void\\);${ws}virtual int vd\\(void\\);${ws}int fd\\(void\\);${ws}\}$nl$gdb_prompt $" {
+ pass "ptype D"
+ }
+ -re "type = class D : public AD, public virtual V \{${ws}private:${ws}V \[*\]+_vb.V;${ws}public:${ws}int d;((${ws}D & operator=\\(D const &\\);)|(${ws}D\\(int, D const &\\);)|(${ws}D\\(int\\);)|(${ws}static void s\\(void\\);)|(${ws}virtual int vg\\(void\\);)|(${ws}virtual int vd\\(void\\);)|(${ws}int fd\\(void\\);))*${ws}\}$nl$gdb_prompt $" {
+ pass "ptype D (obsolescent gcc or gdb)"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "ptype D"
+ }
+ timeout {
+ fail "ptype D (timeout)"
+ }
+ }
+
+ send_gdb "ptype E\n"
+ gdb_expect {
+ -re "type = class E : public B, public virtual V, public D, public C \{${ws}public:${ws}int e;${ws}E & operator=\\(E const &\\);${ws}E\\(int, E const &\\);${ws}E\\(int\\);${ws}virtual int f\\(void\\);${ws}virtual int vg\\(void\\);${ws}virtual int vv\\(void\\);${ws}\}$nl$gdb_prompt $" {
+ pass "ptype E"
+ }
+ -re "type = class E : public B, public virtual V, public D, public C \{${ws}public:${ws}int e;((${ws}E & operator=\\(E const &\\);)|(${ws}E\\(int, E const &\\);)|(${ws}E\\(int\\);)|(${ws}virtual int f\\(void\\);)|(${ws}virtual int vg\\(void\\);)|(${ws}virtual int vv\\(void\\);))*${ws}\}$nl$gdb_prompt $" {
+ pass "ptype E (obsolescent gcc or gdb)"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "ptype E"
+ }
+ timeout {
+ fail "ptype E (timeout)"
+ }
+ }
+
+ send_gdb "ptype dd\n"
+ gdb_expect {
+ -re "type = class D : public AD, public virtual V \{${ws}private:${ws}V \[*\]+_vb.V;${ws}public:${ws}int d;${ws}D & operator=\\(D const &\\);${ws}D\\(int, D const &\\);${ws}D\\(int\\);${ws}static void s\\(void\\);${ws}virtual int vg\\(void\\);${ws}virtual int vd\\(void\\);${ws}int fd\\(void\\);${ws}\}$nl$gdb_prompt $" {
+ pass "ptype dd"
+ }
+ -re "type = class D : public AD, public virtual V \{${ws}private:${ws}V \[*\]+_vb.V;${ws}public:${ws}int d;((${ws}D & operator=\\(D const &\\);)|(${ws}D\\(int, D const &\\);)|(${ws}D\\(int\\);)|(${ws}static void s\\(void\\);)|(${ws}virtual int vg\\(void\\);)|(${ws}virtual int vd\\(void\\);)|(${ws}int fd\\(void\\);))*${ws}\}$nl$gdb_prompt $" {
+ pass "ptype dd (obsolescent gcc or gdb)"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "ptype dd"
+ }
+ timeout {
+ fail "ptype dd (timeout)"
+ }
+ }
+
+ send_gdb "ptype ppd\n"
+ gdb_expect {
+ -re "type = class D : public AD, public virtual V \{${ws}private:${ws}V \[*\]+_vb.V;${ws}public:${ws}int d;${ws}D & operator=\\(D const &\\);${ws}D\\(int, D const &\\);${ws}D\\(int\\);${ws}static void s\\(void\\);${ws}virtual int vg\\(void\\);${ws}virtual int vd\\(void\\);${ws}int fd\\(void\\);${ws}\} \[*\]+$nl$gdb_prompt $" {
+ pass "ptype ppd"
+ }
+ -re "type = class D : public AD, public virtual V \{${ws}private:${ws}V \[*\]+_vb.V;${ws}public:${ws}int d;((${ws}D & operator=\\(D const &\\);)|(${ws}D\\(int, D const &\\);)|(${ws}D\\(int\\);)|(${ws}static void s\\(void\\);)|(${ws}virtual int vg\\(void\\);)|(${ws}virtual int vd\\(void\\);)|(${ws}int fd\\(void\\);))*${ws}\} \[*\]+$nl$gdb_prompt $" {
+ pass "ptype ppd (obsolescent gcc or gdb)"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "ptype ppd"
+ }
+ timeout {
+ fail "ptype ppd (timeout)"
+ }
+ }
+
+ send_gdb "ptype pAd\n"
+ gdb_expect {
+ -re "type = class AD \{${ws}public:${ws}AD & operator=\\(AD const &\\);${ws}AD\\(AD const &\\);${ws}AD\\(void\\);${ws}virtual int vg\\(void\\);${ws}\} \[*\]+$nl$gdb_prompt $" {
+ pass "ptype pAd"
+ }
+ -re "type = class AD \{${ws}public:((${ws}AD & operator=\\(AD const &\\);)|(${ws}AD\\(AD const &\\);)|(${ws}AD\\(void\\);)|(${ws}virtual int vg\\(void\\);))*${ws}\} \[*\]+$nl$gdb_prompt $" {
+ pass "ptype pAd (obsolescent gcc or gdb)"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "ptype pAd"
+ }
+ timeout {
+ fail "ptype pAd (timeout)"
+ }
+ }
+
+ send_gdb "ptype a\n"
+ gdb_expect {
+ -re "type = class A : public virtual V \{${ws}private:${ws}V \[*\]+_vb.V;${ws}int a;${ws}public:${ws}A & operator=\\(A const &\\);${ws}A\\(int, A const &\\);${ws}A\\(int\\);${ws}virtual int f\\(void\\);${ws}\}$nl$gdb_prompt $" {
+ pass "ptype a"
+ }
+ -re "type = class A : public virtual V \{${ws}private:${ws}V \[*\]+_vb.V;${ws}int a;${ws}public:((${ws}A & operator=\\(A const &\\);)|(${ws}A\\(int, A const &\\);)|(${ws}A\\(int\\);)|(${ws}virtual int f\\(void\\);))*${ws}\}$nl$gdb_prompt $" {
+ pass "ptype a (obsolescent gcc or gdb)"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "ptype a"
+ }
+ timeout {
+ fail "ptype a (timeout)"
+ }
+ }
+
+ send_gdb "ptype b\n"
+ gdb_expect {
+ -re "type = class B : public A \{${ws}private:${ws}int b;${ws}public:${ws}B & operator=\\(B const &\\);${ws}B\\(int, B const &\\);${ws}B\\(int\\);${ws}virtual int f\\(void\\);${ws}\}$nl$gdb_prompt $" {
+ pass "ptype b"
+ }
+ -re "type = class B : public A \{${ws}private:${ws}int b;${ws}public:((${ws}B & operator=\\(B const &\\);)|(${ws}B\\(int, B const &\\);)|(${ws}B\\(int\\);)|(${ws}virtual int f\\(void\\);))*${ws}\}$nl$gdb_prompt $" {
+ pass "ptype b (obsolescent gcc or gdb)"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "ptype b"
+ }
+ timeout {
+ fail "ptype b (timeout)"
+ }
+ }
+
+ send_gdb "ptype c\n"
+ gdb_expect {
+ -re "type = class C : public virtual V \{${ws}private:${ws}V \[*\]+_vb.V;${ws}public:${ws}int c;${ws}C & operator=\\(C const &\\);${ws}C\\(int, C const &\\);${ws}C\\(int\\);${ws}\}$nl$gdb_prompt $" {
+ pass "ptype c"
+ }
+ -re "type = class C : public virtual V \{${ws}private:${ws}V \[*\]+_vb.V;${ws}public:${ws}int c;((${ws}C & operator=\\(C const &\\);)|(${ws}C\\(int, C const &\\);)|(${ws}C\\(int\\);))*${ws}\}$nl$gdb_prompt $" {
+ pass "ptype c (obsolescent gcc or gdb)"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "ptype c"
+ }
+ timeout {
+ fail "ptype c (timeout)"
+ }
+ }
+
+ send_gdb "ptype d\n"
+ gdb_expect {
+ -re "type = class D : public AD, public virtual V \{${ws}private:${ws}V \[*\]+_vb.V;${ws}public:${ws}int d;${ws}D & operator=\\(D const &\\);${ws}D\\(int, D const &\\);${ws}D\\(int\\);${ws}static void s\\(void\\);${ws}virtual int vg\\(void\\);${ws}virtual int vd\\(void\\);${ws}int fd\\(void\\);${ws}\}$nl$gdb_prompt $" {
+ pass "ptype d"
+ }
+ -re "type = class D : public AD, public virtual V \{${ws}private:${ws}V \[*\]+_vb.V;${ws}public:${ws}int d;((${ws}D & operator=\\(D const &\\);)|(${ws}D\\(int, D const &\\);)|(${ws}D\\(int\\);)|(${ws}static void s\\(void\\);)|(${ws}virtual int vg\\(void\\);)|(${ws}virtual int vd\\(void\\);)|(${ws}int fd\\(void\\);))*${ws}\}$nl$gdb_prompt $" {
+ pass "ptype d (obsolescent gcc or gdb)"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "ptype d"
+ }
+ timeout {
+ fail "ptype d (timeout)"
+ }
+ }
+
+ send_gdb "ptype e\n"
+ gdb_expect {
+ -re "type = class E : public B, public virtual V, public D, public C \{${ws}public:${ws}int e;${ws}E & operator=\\(E const &\\);${ws}E\\(int, E const &\\);${ws}E\\(int\\);${ws}virtual int f\\(void\\);${ws}virtual int vg\\(void\\);${ws}virtual int vv\\(void\\);${ws}\}$nl$gdb_prompt $" {
+ pass "ptype e"
+ }
+ -re "type = class E : public B, public virtual V, public D, public C \{${ws}public:${ws}int e;((${ws}E & operator=\\(E const &\\);)|(${ws}E\\(int, E const &\\);)|(${ws}E\\(int\\);)|(${ws}virtual int f\\(void\\);)|(${ws}virtual int vg\\(void\\);)|(${ws}virtual int vv\\(void\\);))*${ws}\}$nl$gdb_prompt $" {
+ pass "ptype e (obsolescent gcc or gdb)"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "ptype e"
+ }
+ timeout {
+ fail "ptype e (timeout)"
+ }
+ }
+
+ send_gdb "ptype v\n"
+ gdb_expect {
+ -re "type = class V : public VA, public VB \{${ws}public:${ws}int w;${ws}V & operator=\\(V const &\\);${ws}V\\(V const &\\);${ws}V\\(void\\);${ws}int f\\(void\\);${ws}virtual int vv\\(void\\);${ws}\}$nl$gdb_prompt $" {
+ pass "ptype v"
+ }
+ -re "type = class V : public VA, public VB \{${ws}public:${ws}int w;((${ws}V & operator=\\(V const &\\);)|(${ws}V\\(V const &\\);)|(${ws}V\\(void\\);)|(${ws}int f\\(void\\);)|(${ws}virtual int vv\\(void\\);))*${ws}\}$nl$gdb_prompt $" {
+ pass "ptype v (obsolescent gcc or gdb)"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "ptype v"
+ }
+ timeout {
+ fail "ptype v (timeout)"
+ }
+ }
+
+ send_gdb "ptype vb\n"
+ gdb_expect {
+ -re "type = class VB \{${ws}public:${ws}int vb;${ws}VB & operator=\\(VB const &\\);${ws}VB\\(VB const &\\);${ws}VB\\(void\\);${ws}int fvb\\(void\\);${ws}virtual int vvb\\(void\\);${ws}\}$nl$gdb_prompt $" {
+ pass "ptype vb"
+ }
+ -re "type = class VB \{${ws}public:${ws}int vb;((${ws}VB & operator=\\(VB const &\\);)|(${ws}VB\\(VB const &\\);)|(${ws}VB\\(void\\);)|(${ws}int fvb\\(void\\);)|(${ws}virtual int vvb\\(void\\);))*${ws}\}$nl$gdb_prompt $" {
+ pass "ptype vb (obsolescent gcc or gdb)"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "ptype vb"
+ }
+ timeout {
+ fail "ptype vb (timeout)"
+ }
+ }
+
+ send_gdb "ptype pAa\n"
+ gdb_expect {
+ -re "type = class A : public virtual V \{${ws}private:${ws}V \[*\]+_vb.V;${ws}int a;${ws}public:${ws}A & operator=\\(A const &\\);${ws}A\\(int, A const &\\);${ws}A\\(int\\);${ws}virtual int f\\(void\\);${ws}\} \[*\]+$nl$gdb_prompt $" {
+ pass "ptype pAa"
+ }
+ -re "type = class A : public virtual V \{${ws}private:${ws}V \[*\]+_vb.V;${ws}int a;${ws}public:((${ws}A & operator=\\(A const &\\);)|(${ws}A\\(int, A const &\\);)|(${ws}A\\(int\\);)|(${ws}virtual int f\\(void\\);))*${ws}\} \[*\]+$nl$gdb_prompt $" {
+ pass "ptype pAa (obsolescent gcc or gdb)"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "ptype pAa"
+ }
+ timeout {
+ fail "ptype pAa (timeout)"
+ }
+ }
+
+ send_gdb "ptype pAe\n"
+ gdb_expect {
+ -re "type = class A : public virtual V \{${ws}private:${ws}V \[*\]+_vb.V;${ws}int a;${ws}public:${ws}A & operator=\\(A const &\\);${ws}A\\(int, A const &\\);${ws}A\\(int\\);${ws}virtual int f\\(void\\);${ws}\} \[*\]+$nl$gdb_prompt $" {
+ pass "ptype pAe"
+ }
+ -re "type = class A : public virtual V \{${ws}private:${ws}V \[*\]+_vb.V;${ws}int a;${ws}public:((${ws}A & operator=\\(A const &\\);)|(${ws}A\\(int, A const &\\);)|(${ws}A\\(int\\);)|(${ws}virtual int f\\(void\\);))*${ws}\} \[*\]+$nl$gdb_prompt $" {
+ pass "ptype pAe (obsolescent gcc or gdb)"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "ptype pAe"
+ }
+ timeout {
+ fail "ptype pAe (timeout)"
+ }
+ }
+
+ send_gdb "ptype pBe\n"
+ gdb_expect {
+ -re "type = class B : public A \{${ws}private:${ws}int b;${ws}public:${ws}B & operator=\\(B const &\\);${ws}B\\(int, B const &\\);${ws}B\\(int\\);${ws}virtual int f\\(void\\);${ws}\} \[*\]+$nl$gdb_prompt $" {
+ pass "ptype pBe"
+ }
+ -re "type = class B : public A \{${ws}private:${ws}int b;${ws}public:((${ws}B & operator=\\(B const &\\);)|(${ws}B\\(int, B const &\\);)|(${ws}B\\(int\\);)|(${ws}virtual int f\\(void\\);))*${ws}\} \[*\]+$nl$gdb_prompt $" {
+ pass "ptype pBe (obsolescent gcc or gdb)"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "ptype pBe"
+ }
+ timeout {
+ fail "ptype pBe (timeout)"
+ }
+ }
+
+ send_gdb "ptype pDd\n"
+ gdb_expect {
+ -re "type = class D : public AD, public virtual V \{${ws}private:${ws}V \[*\]+_vb.V;${ws}public:${ws}int d;${ws}D & operator=\\(D const &\\);${ws}D\\(int, D const &\\);${ws}D\\(int\\);${ws}static void s\\(void\\);${ws}virtual int vg\\(void\\);${ws}virtual int vd\\(void\\);${ws}int fd\\(void\\);${ws}\} \[*\]+$nl$gdb_prompt $" {
+ pass "ptype pDd"
+ }
+ -re "type = class D : public AD, public virtual V \{${ws}private:${ws}V \[*\]+_vb.V;${ws}public:${ws}int d;((${ws}D & operator=\\(D const &\\);)|(${ws}D\\(int, D const &\\);)|(${ws}D\\(int\\);)|(${ws}static void s\\(void\\);)|(${ws}virtual int vg\\(void\\);)|(${ws}virtual int vd\\(void\\);)|(${ws}int fd\\(void\\);))*${ws}\} \[*\]+$nl$gdb_prompt $" {
+ pass "ptype pDd (obsolescent gcc or gdb)"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "ptype pDd"
+ }
+ timeout {
+ fail "ptype pDd (timeout)"
+ }
+ }
+
+ send_gdb "ptype pDe\n"
+ gdb_expect {
+ -re "type = class D : public AD, public virtual V \{${ws}private:${ws}V \[*\]+_vb.V;${ws}public:${ws}int d;${ws}D & operator=\\(D const &\\);${ws}D\\(int, D const &\\);${ws}D\\(int\\);${ws}static void s\\(void\\);${ws}virtual int vg\\(void\\);${ws}virtual int vd\\(void\\);${ws}int fd\\(void\\);${ws}\} \[*\]+$nl$gdb_prompt $" {
+ pass "ptype pDe"
+ }
+ -re "type = class D : public AD, public virtual V \{${ws}private:${ws}V \[*\]+_vb.V;${ws}public:${ws}int d;((${ws}D & operator=\\(D const &\\);)|(${ws}D\\(int, D const &\\);)|(${ws}D\\(int\\);)|(${ws}static void s\\(void\\);)|(${ws}virtual int vg\\(void\\);)|(${ws}virtual int vd\\(void\\);)|(${ws}int fd\\(void\\);))*${ws}\} \[*\]+$nl$gdb_prompt $" {
+ pass "ptype pDe (obsolescent gcc or gdb)"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "ptype pDe"
+ }
+ timeout {
+ fail "ptype pDe (timeout)"
+ }
+ }
+
+ send_gdb "ptype pVa\n"
+ gdb_expect {
+ -re "type = class V : public VA, public VB \{${ws}public:${ws}int w;${ws}V & operator=\\(V const &\\);${ws}V\\(V const &\\);${ws}V\\(void\\);${ws}int f\\(void\\);${ws}virtual int vv\\(void\\);${ws}\} \[*\]+$nl$gdb_prompt $" {
+ pass "ptype pVa"
+ }
+ -re "type = class V : public VA, public VB \{${ws}public:${ws}int w;((${ws}V & operator=\\(V const &\\);)|(${ws}V\\(V const &\\);)|(${ws}V\\(void\\);)|(${ws}int f\\(void\\);)|(${ws}virtual int vv\\(void\\);))*${ws}\} \[*\]+$nl$gdb_prompt $" {
+ pass "ptype pVa (obsolescent gcc or gdb)"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "ptype pVa"
+ }
+ timeout {
+ fail "ptype pVa (timeout)"
+ }
+ }
+
+ send_gdb "ptype pVv\n"
+ gdb_expect {
+ -re "type = class V : public VA, public VB \{${ws}public:${ws}int w;${ws}V & operator=\\(V const &\\);${ws}V\\(V const &\\);${ws}V\\(void\\);${ws}int f\\(void\\);${ws}virtual int vv\\(void\\);${ws}\} \[*\]+$nl$gdb_prompt $" {
+ pass "ptype pVv"
+ }
+ -re "type = class V : public VA, public VB \{${ws}public:${ws}int w;((${ws}V & operator=\\(V const &\\);)|(${ws}V\\(V const &\\);)|(${ws}V\\(void\\);)|(${ws}int f\\(void\\);)|(${ws}virtual int vv\\(void\\);))*${ws}\} \[*\]+$nl$gdb_prompt $" {
+ pass "ptype pVv (obsolescent gcc or gdb)"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "ptype pVv"
+ }
+ timeout {
+ fail "ptype pVv (timeout)"
+ }
+ }
+
+ send_gdb "ptype pVe\n"
+ gdb_expect {
+ -re "type = class V : public VA, public VB \{${ws}public:${ws}int w;${ws}V & operator=\\(V const &\\);${ws}V\\(V const &\\);${ws}V\\(void\\);${ws}int f\\(void\\);${ws}virtual int vv\\(void\\);${ws}\} \[*\]+$nl$gdb_prompt $" {
+ pass "ptype pVe"
+ }
+ -re "type = class V : public VA, public VB \{${ws}public:${ws}int w;((${ws}V & operator=\\(V const &\\);)|(${ws}V\\(V const &\\);)|(${ws}V\\(void\\);)|(${ws}int f\\(void\\);)|(${ws}virtual int vv\\(void\\);))*${ws}\} \[*\]+$nl$gdb_prompt $" {
+ pass "ptype pVe (obsolescent gcc or gdb)"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "ptype pVe"
+ }
+ timeout {
+ fail "ptype pVe (timeout)"
+ }
+ }
+
+ send_gdb "ptype pVd\n"
+ gdb_expect {
+ -re "type = class V : public VA, public VB \{${ws}public:${ws}int w;${ws}V & operator=\\(V const &\\);${ws}V\\(V const &\\);${ws}V\\(void\\);${ws}int f\\(void\\);${ws}virtual int vv\\(void\\);${ws}\} \[*\]+$nl$gdb_prompt $" {
+ pass "ptype pVd"
+ }
+ -re "type = class V : public VA, public VB \{${ws}public:${ws}int w;((${ws}V & operator=\\(V const &\\);)|(${ws}V\\(V const &\\);)|(${ws}V\\(void\\);)|(${ws}int f\\(void\\);)|(${ws}virtual int vv\\(void\\);))*${ws}\} \[*\]+$nl$gdb_prompt $" {
+ pass "ptype pVd (obsolescent gcc or gdb)"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "ptype pVd"
+ }
+ timeout {
+ fail "ptype pVd (timeout)"
+ }
+ }
+
+ send_gdb "ptype pADe\n"
+ gdb_expect {
+ -re "type = class AD \{${ws}public:${ws}AD & operator=\\(AD const &\\);${ws}AD\\(AD const &\\);${ws}AD\\(void\\);${ws}virtual int vg\\(void\\);${ws}\} \[*\]+$nl$gdb_prompt $" {
+ pass "ptype pADe"
+ }
+ -re "type = class AD \{${ws}public:((${ws}AD & operator=\\(AD const &\\);)|(${ws}AD\\(AD const &\\);)|(${ws}AD\\(void\\);)|(${ws}virtual int vg\\(void\\);))*${ws}\} \[*\]+$nl$gdb_prompt $" {
+ pass "ptype pADe (obsolescent gcc or gdb)"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "ptype pADe"
+ }
+ timeout {
+ fail "ptype pADe (timeout)"
+ }
+ }
+
+ send_gdb "ptype pEe\n"
+ gdb_expect {
+ -re "type = class E : public B, public virtual V, public D, public C \{${ws}public:${ws}int e;${ws}E & operator=\\(E const &\\);${ws}E\\(int, E const &\\);${ws}E\\(int\\);${ws}virtual int f\\(void\\);${ws}virtual int vg\\(void\\);${ws}virtual int vv\\(void\\);${ws}\} \[*\]+$nl$gdb_prompt $" {
+ pass "ptype pEe"
+ }
+ -re "type = class E : public B, public virtual V, public D, public C \{${ws}public:${ws}int e;((${ws}E & operator=\\(E const &\\);)|(${ws}E\\(int, E const &\\);)|(${ws}E\\(int\\);)|(${ws}virtual int f\\(void\\);)|(${ws}virtual int vg\\(void\\);)|(${ws}virtual int vv\\(void\\);))*${ws}\} \[*\]+$nl$gdb_prompt $" {
+ pass "ptype pEe (obsolescent gcc or gdb)"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "ptype pEe"
+ }
+ timeout {
+ fail "ptype pEe (timeout)"
+ }
+ }
+
+ send_gdb "ptype pVB\n"
+ gdb_expect {
+ -re "type = class VB \{${ws}public:${ws}int vb;${ws}VB & operator=\\(VB const &\\);${ws}VB\\(VB const &\\);${ws}VB\\(void\\);${ws}int fvb\\(void\\);${ws}virtual int vvb\\(void\\);${ws}\} \[*\]+$nl$gdb_prompt $" {
+ pass "ptype pVB"
+ }
+ -re "type = class VB \{${ws}public:${ws}int vb;((${ws}VB & operator=\\(VB const &\\);)|(${ws}VB\\(VB const &\\);)|(${ws}VB\\(void\\);)|(${ws}int fvb\\(void\\);)|(${ws}virtual int vvb\\(void\\);))*${ws}\} \[*\]+$nl$gdb_prompt $" {
+ pass "ptype pVB (obsolescent gcc or gdb)"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "ptype pVB"
+ }
+ timeout {
+ fail "ptype pVB (timeout)"
+ }
+ }
+}
+
+#
+# Test calling of virtual functions.
+#
+
+proc test_virtual_calls {} {
+ global gdb_prompt
+ global GDB
+ global nl
+
+ if [target_info exists gdb,cannot_call_functions] {
+ setup_xfail "*-*-*" 2416
+ fail "This target can not call functions"
+ return 0
+ }
+
+ send_gdb "print pAe->f()\n"
+ gdb_expect {
+ -re ".* = 20$nl$gdb_prompt $" { pass "print pAe->f()" }
+ -re "Cannot invoke functions on this machine.*$gdb_prompt $" {
+ fail "print pAe->f() (cannot invoke functions, skipping virtual calls)"
+ return 0
+ }
+ -re ".*Cannot access memory at address 0x8.*$gdb_prompt $" {
+ fail "print pAe->f() \
+(known failure with gcc cygnus-2.4.5-930417, skipping virtual calls)"
+ return 0
+ }
+ -re ".*$gdb_prompt $" { fail "print pAe->f()" }
+ timeout { fail "print pAe->f() (timeout)" }
+ eof { fail "print pAe->f() ($GDB dumped core) (FIXME)" ; gdb_virtfunc_restart; return }
+ }
+
+ send_gdb "print pAa->f()\n"
+ gdb_expect {
+ -re ".* = 1$nl$gdb_prompt $" { pass "print pAa->f()" }
+ -re ".*$gdb_prompt $" { fail "print pAa->f()" }
+ timeout { fail "print pAa->f() (timeout)" }
+ eof { fail "print pAa->f() ($GDB dumped core) (FIXME)" ; gdb_virtfunc_restart; return }
+ }
+
+ send_gdb "print pDe->vg()\n"
+# setup_xfail "*-*-*"
+ gdb_expect {
+ -re ".* = 202$nl$gdb_prompt $" { pass "print pDe->vg()" }
+ -re ".*$gdb_prompt $" { fail "print pDe->vg()" }
+ timeout { fail "print pDe->vg() (timeout)" }
+ eof { fail "print pDe->vg() ($GDB dumped core) (FIXME)" ; gdb_virtfunc_restart; return }
+ }
+
+ send_gdb "print pADe->vg()\n"
+ gdb_expect {
+ -re ".* = 202$nl$gdb_prompt $" { pass "print pADe->vg()" }
+ -re ".*$gdb_prompt $" { fail "print pADe->vg()" }
+ timeout { fail "print pADe->vg() (timeout)" }
+ eof { fail "print pADe->vg() ($GDB dumped core) (FIXME)" ; gdb_virtfunc_restart; return }
+ }
+
+ send_gdb "print pDd->vg()\n"
+# setup_xfail "*-*-*"
+ gdb_expect {
+ -re ".* = 101$nl$gdb_prompt $" { pass "print pDd->vg()" }
+ -re ".*$gdb_prompt $" { fail "print pDd->vg()" }
+ timeout { fail "print pDd->vg() (timeout)" }
+ eof { fail "print pDd->vg() ($GDB dumped core) (FIXME)" ; gdb_virtfunc_restart; return }
+ }
+
+ send_gdb "print pEe->vvb()\n"
+# setup_xfail "*-*-*"
+ gdb_expect {
+ -re ".* = 411$nl$gdb_prompt $" { pass "print pEe->vvb()" }
+ -re ".*$gdb_prompt $" { fail "print pEe->vvb()" }
+ timeout { fail "print pEe->vvb() (timeout)" }
+ eof { fail "print pEe->vvb() ($GDB dumped core) (FIXME)" ; gdb_virtfunc_restart; return }
+ }
+
+ send_gdb "print pVB->vvb()\n"
+ gdb_expect {
+ -re ".* = 407$nl$gdb_prompt $" { pass "print pVB->vvb()" }
+ -re ".*$gdb_prompt $" { fail "print pVB->vvb()" }
+ timeout { fail "print pVB->vvb() (timeout)" }
+ eof { fail "print pVB->vvb() ($GDB dumped core) (FIXME)" ; gdb_virtfunc_restart; return }
+ }
+
+ send_gdb "print pBe->vvb()\n"
+# setup_xfail "*-*-*"
+ gdb_expect {
+ -re ".* = 411$nl$gdb_prompt $" { pass "print pBe->vvb()" }
+ -re ".*$gdb_prompt $" { fail "print pBe->vvb()" }
+ timeout { fail "print pBe->vvb() (timeout)" }
+ eof { fail "print pBe->vvb() ($GDB dumped core) (FIXME)" ; gdb_virtfunc_restart; return }
+ }
+
+ send_gdb "print pDe->vvb()\n"
+# setup_xfail "*-*-*"
+ gdb_expect {
+ -re ".* = 411$nl$gdb_prompt $" { pass "print pDe->vvb()" }
+ -re ".*$gdb_prompt $" { fail "print pDe->vvb()" }
+ timeout { fail "print pDe->vvb() (timeout)" }
+ eof { fail "print pDe->vvb() ($GDB dumped core) (FIXME)" ; gdb_virtfunc_restart; return }
+ }
+
+ send_gdb "print pEe->vd()\n"
+# setup_xfail "*-*-*"
+ gdb_expect {
+ -re ".* = 282$nl$gdb_prompt $" { pass "print pEe->vd()" }
+ -re ".*$gdb_prompt $" { fail "print pEe->vd()" }
+ timeout { fail "print pEe->vd() (timeout)" }
+ eof { fail "print pEe->vd() ($GDB dumped core) (FIXME)" ; gdb_virtfunc_restart; return }
+ }
+
+ send_gdb "print pEe->fvb()\n"
+# setup_xfail "*-*-*"
+ gdb_expect {
+ -re ".* = 311$nl$gdb_prompt $" { pass "print pEe->fvb()" }
+ -re ".*$gdb_prompt $" { fail "print pEe->fvb()" }
+ timeout { fail "print pEe->fvb() (timeout)" }
+ eof { fail "print pEe->fvb() ($GDB dumped core) (FIXME)" ; gdb_virtfunc_restart; return }
+ }
+
+ send_gdb "print pEe->D::vg()\n"
+ setup_xfail "*-*-*"
+ gdb_expect {
+ -re ".* = 102$nl$gdb_prompt $" { pass "print pEe->D::vg()" }
+ -re ".*$gdb_prompt $" { fail "print pEe->D::vg()" }
+ timeout { fail "print pEe->D::vg() (timeout)" }
+ eof { fail "print pEe->D::vg() ($GDB dumped core) (FIXME)" ; gdb_virtfunc_restart; return }
+ }
+}
+
+proc do_tests {} {
+ global prms_id
+ global bug_id
+
+ set prms_id 0
+ set bug_id 0
+
+ gdb_start;
+ gdb_virtfunc_init;
+
+ # Get the debug format for the compiled test case. If that
+ # format is DWARF 1 then just skip all the tests since none of
+ # them will pass.
+
+ if [ runto_main ] then {
+ get_debug_format
+ if [ setup_xfail_format "DWARF 1" ] then {
+ fail "C++ tests skipped due to limited C++ support in DWARF 1 debug format"
+ return
+ }
+ clear_xfail "*-*-*"
+ }
+
+ test_ptype_of_classes
+
+ if [ runto 'test_calls(void)' ] then {
+ test_virtual_calls
+ }
+}
+
+do_tests
diff --git a/gdb/testsuite/gdb.chill/ChangeLog b/gdb/testsuite/gdb.chill/ChangeLog
new file mode 100644
index 00000000000..9db44ea6b38
--- /dev/null
+++ b/gdb/testsuite/gdb.chill/ChangeLog
@@ -0,0 +1,313 @@
+Thu May 21 02:45:18 1998 Felix Lee <flee@zog.cygnus.com>
+
+ * chexp.exp: fix tests that assume >16-bit ints.
+
+Wed Sep 10 15:01:55 1997 Bob Manson <manson@charmed.cygnus.com>
+
+ * *.exp: The end-all be-all of quoting fixes. Ha.
+
+Thu Aug 21 10:31:23 1997 Bob Manson <manson@charmed.cygnus.com>
+
+ * enum.exp: More quoting fixes.
+ * pr-9946.exp: Ditto.
+ * gch1280.exp: Ditto.
+ * gch1272.exp: Ditto.
+
+Tue Aug 12 21:48:08 1997 Bob Manson <manson@charmed.cygnus.com>
+
+ * tests2.exp: Fix quoting.
+ * tests1.exp: Ditto.
+ * pr-9946.exp: Ditto.
+ * enum.exp: Ditto.
+ * builtins.exp: Ditto.
+ * powerset.exp: Ditto.
+ * misc.exp: Ditto.
+ * gch981.exp: Ditto.
+ * gch922.exp: Ditto.
+ * gch1280.exp: Ditto.
+ * gch1272.exp: Ditto.
+ * gch1041.exp: Ditto.
+
+Sat Nov 23 14:00:59 1996 Fred Fish <fnf@cygnus.com>
+
+ * misc.exp: Change x86 linux setup_xfails to use new
+ i*86-pc-linux*-gnu quads.
+ * tuples.exp: Ditto.
+ * tests2.exp: Ditto.
+ * pr-5016.exp: Ditto.
+
+ * tuples.exp: Add i*86-pc-linux-gnu setup_fail to existing
+ xfails for 'set var vs1 := [ "bar", 42, m_ps[ a ] ]',
+ 'set var $i := m_s1["foo", 44, m_ps[a ]]', and
+ 'set var vs2 := [ 10+3, m_s1[ "foo" , 42, m_ps[ b ]]]'.
+
+Mon Nov 11 10:27:32 1996 Fred Fish <fnf@cygnus.com>
+
+ * callch.exp: Add mips*-sgi-irix* xfail for
+ "call king(a, otto[[10, 15], [20, 25]])".
+ * pr-8742.exp: Add mips*-sgi-irix* xfails for
+ "pass int powerset tuple"
+ "pass set powerset tuple"
+ "pass modeless int powerset tuple" and
+ "pass modeless set powerset tuple".
+ * tuples.exp: Add sparc-*-solaris* and sparc-*-sunos*
+ xfails for several "set var" commands that are failing.
+ Convert most of the set commands into gdb_test_exact
+ commands.
+
+Fri Oct 11 16:48:56 1996 Fred Fish <fnf@cygnus.com>
+
+ * expstruct.exp (objfile2): Set and use, like other chill tests.
+ * pr-4975.exp: Ditto.
+ * pr-5646.exp: Ditto.
+ * pr-8134.exp: Ditto.
+
+Thu Sep 5 01:54:42 1996 Wilfried Moser (Alcatel) <moser@rtl.cygnus.com>
+
+ * gch1280.exp: Enhance test case.
+
+Wed Sep 4 07:30:44 1996 Wilfried Moser (Alcatel) <moser@rtl.cygnus.com>
+
+ * gch1272.{ch,exp}, gch1280.{ch,exp}, pr-9946.{ch,exp}:
+ New test cases.
+
+Sun Aug 18 13:29:48 1996 Fred Fish <fnf@cygnus.com>
+
+ * tests2.exp: Remove mips-sgi-irix* setup_xfail for
+ "real write 4" and "real write 8".
+
+Mon Jun 10 14:04:05 1996 Fred Fish <fnf@cygnus.com>
+
+ * tests1.exp (test_modes): Remove *-*-* setup_sfail for
+ "print unnumbered set range mode" and
+ "print numbered set range mode".
+
+Wed Apr 17 01:23:06 1996 Wilfried Moser (Alcatel) <moser@rtl.cygnus.com>
+
+ * tests1.{ch,exp}: Tets case modified and enhanced.
+
+Tue Apr 9 01:18:04 1996 Wilfried Moser (Alcatel) <moser@rtl.cygnus.com>
+
+ * gch981.{ch,exp}, gch1041.{ch,exp}: New test cases.
+
+Wed Mar 6 00:29:35 1996 Wilfried Moser (Alcatel) <moser@rtl.cygnus.com>
+
+ * powerset.exp: Add test.
+
+Tue Mar 5 23:41:39 1996 Wilfried Moser (Alcatel) <moser@rtl.cygnus.com>
+
+ * gch922.{ch,exp}, powerset.{ch,exp}: New test cases.
+
+ * builtins.exp, chillvars.exp, misc.exp, tests1.exp: Updated
+ due to new format of nonprintable characters (control sequence
+ instead of C'xx').
+
+Tue Mar 5 00:09:17 1996 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * string.ch, string.exp: Add tests (from Cygnus PR chill/9078).
+
+ * pr-9095.ch, pr-9095.exp: New test case.
+
+Fri Feb 9 08:22:16 1996 Fred Fish <fnf@cygnus.com>
+
+ * Makefile.in (clean): Add missing '{'.
+
+Tue Feb 6 21:52:26 1996 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * pr-8894.exp, pr-8894.ch, pr-8894-grt.ch: New test case.
+
+Mon Jan 29 00:05:01 1996 Wilfried Moser (Alcatel) <moser@rtl.cygnus.com>
+
+ * builtins.ch, builtins.exp: Enhance test case.
+
+ * extstruct.ch, extstruct-grt.ch, extstruct.exp: New test case.
+
+Tue Jan 23 16:57:13 1996 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * enum.ch, enum.exp: New test case (covers PRs 8869 and 8870).
+
+Thu Jan 11 17:34:01 1996 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * Makefile.in (PROGS): Removed.
+ (clean mostlyclean): Remove *.exe rather than ${PROGS}.
+
+ * pr-8742.ch, pr-8742.exp: New test case.
+
+Tue Jan 9 04:47:27 1996 Wilfried Moser (Alcatel) <moser@rtl.cygnus.com>
+
+ * misc.ch, misc.exp: Enhance test case.
+
+Sat Dec 30 15:31:59 1995 Fred Fish <fnf@cygnus.com>
+
+ * tests2.exp: Setup_xfail "i*86-*-linux" and
+ "mips-sgi-irix*" for "real write 4" and "real write 8".
+ Conditionalize both tests for system specific value
+ of "infinity" string.
+
+Fri Dec 29 10:46:09 1995 Fred Fish <fnf@cygnus.com>
+
+ * builtins.exp (test_size): Alpha seems to have long builtins.
+ * tests1.exp: Setup xfail "*-*-*" for "ptype r2".
+ * tests2.exp: Add check to skip chill tests.
+
+Mon Dec 11 16:53:40 1995 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * tuples.ch, tuples.exp: Exhance test cases (from PR 8643).
+
+Mon Dec 11 06:57:07 1995 Wilfried Moser (Alcatel) <moser@rtl.cygnus.com>
+
+ * builtins.exp, pr-5016.{ch,exp}, result.{ch,exp},
+ tests1.{ch,exp}: Enhance test cases.
+
+Thu Dec 7 05:16:34 1995 Wilfried Moser (Alcatel) <moser@rtl.cygnus.com>
+
+ * builtins.ch, builtins.exp, Makefile.in: New test case.
+
+Tue Dec 5 01:51:45 1995 Wilfried Moser (Alcatel) <moser@rtl.cygnus.com>
+
+ * tests2.exp: Add compiling of the test case.
+
+Fri Dec 1 00:08:37 1995 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * pr-8405.ch, pr-8405.exp, Makefile.in: New test case.
+
+ * tests1.exp, tests2.exp (test_print_reject): Remove; causes
+ conflicts with later tests using test_print_reject in ../lib/gdb.exp.
+ (passcount): Remove.
+ * tests2.exp (test_print_accept): Removed.
+ (test_write): Re-write to use gdb_test rather than test_print_accept.
+ * tests1.exp (test_print_accept_exact): Removed.
+ (tests_locations): Rewrite to use gdb_test and not above proc.
+
+ * tests1.ch, tests1.exp, tests2.ch, tests2.exp, Makefile.in:
+ New (extensive) test cases.
+ * chexp.exp: Fix relations to return TRUE or FALSE.
+
+Wed Nov 29 19:28:13 1995 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * Makefile.in: Add .exp.check rule.
+ * callch.ch: Add missing "%." to format strings.
+ * callch.exp: Fix argument to gdb_load.
+ * chexp.exp: Add specific error messages to test_print_reject calls.
+ * misc.exp: Add a test for PR 8496.
+ * pr-6632.exp, pr-8136.exp: Link executables from two .o files.
+
+Sat Nov 25 20:49:27 1995 Fred Fish <fnf@phydeaux.cygnus.com>
+
+ * pr-5016.exp: xfail "whatis i" for alpha-osf-dec-osf2*, same as linux.
+
+Sun Oct 29 17:58:01 1995 Fred Fish <fnf@cygnus.com>
+
+ * pr-5016.exp: xfail "whatis i" for sparc-sun-sunos4*, same as linux.
+
+Wed Oct 4 18:20:53 1995 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * pr-8136.{ch,exp}, pr-8134.exp, func1.ch, Makefile.in: New test cases.
+
+Wed Sep 27 11:51:50 1995 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * tuples.ch. tuples.exp: Add new test for setting a variant record
+ using a tuple, and access the fields.
+
+Thu Aug 3 10:45:37 1995 Fred Fish <fnf@cygnus.com>
+
+ * Update all FSF addresses except those in COPYING* files.
+
+Thu Jul 27 20:36:30 1995 Fred Fish (fnf@cygnus.com)
+
+ * pr-5016.exp: xfail "i*86-*-linux*" for "whatis int-range"
+ test. Thinks it is "_cint" rather than "m_index".
+ * misc.exp: xfail "i*86-*-linux*" for "info line" test.
+ Line number is off by one.
+
+Wed Jun 14 13:07:45 1995 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * chillvars.exp, string.exp: New tests for LOWER/UPPER/LENGTH.
+
+Wed Jun 7 17:52:38 1995 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * chillvars.ch (xptr): Declare new variable.
+ * chillvars.exp (test_ptr): New function to test EXPR->MODENAME.
+
+Tue Mar 28 17:13:13 1995 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * pr-6632.ch, pr-6632-grt.ch, pr-6632.exp, Makefile.in: New test case.
+
+Tue Mar 21 12:10:06 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * tuples.exp (do_tests): Make names of "print v_ps" test unique.
+
+Wed Mar 8 13:26:36 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * *.exp: Skip all tests silently if skip_chill_tests returns true.
+
+ * misc.exp: Remove reference to non-existent variable passcount.
+
+Tue Mar 7 19:30:05 1995 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * string.ch, string.exp, Makefile.in: New test case.
+
+Mon Mar 6 14:11:01 1995 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * tuples.ch (setnmode); New module.
+ * tuples.exp: Add some extra tests.
+
+Sat Mar 4 15:16:17 1995 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * callch.ch, callch.exp, Makefile.in: New test case.
+
+Thu Mar 2 06:17:41 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * misc.exp: If executable does not exist, issue warning and skip
+ remaining tests, like other chill tests.
+
+Wed Mar 1 20:28:42 1995 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * misc.ch, misc.exp, Makefile.in: New test case.
+
+Mon Feb 20 16:19:58 1995 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * chillvars.ch: Add missing INIT's.
+ * chillvars.exp: Allow builtin types as either case. E.g. (BOOL|bool).
+ * pr-5016.exp: Likewise.
+
+Sun Feb 12 11:26:08 1995 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * pr-6292.ch, pr-6292.exp, Makefile.in: New test case.
+
+Wed Feb 1 13:09:48 1995 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * tuples.ch, tuples.exp, Makefile.in: New test case.
+
+Mon Nov 28 18:39:08 1994 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * pr-5984.ch, pr-5984.exp, Makefile.in: New test case.
+
+Fri Sep 16 16:55:03 1994 Per Bothner (bothner@kalessin.cygnus.com)
+
+ * pr-5646.ch, pr-5646-grt.ch, pr-5646.exp, Makefile.in: New testcase.
+
+Tue Sep 6 13:21:27 1994 Per Bothner (bothner@kalessin.cygnus.com)
+
+ * pr-5016.ch, pr-5016.exp, Makefile.in: New testcase.
+ * Makefile.in (.exe.check): New rule, to run just one test.
+
+Tue Jun 14 16:20:18 1994 Per Bothner (bothner@kalessin.cygnus.com)
+
+ * result.ch, result.exp, Makefile.in: New test case.
+ * pr-4975.ch, pr-4975-grt.ch, pr-4975.exp, Makefile.in: Ditto.
+
+Thu Jun 9 15:20:43 1994 Per Bothner (bothner@kalessin.cygnus.com)
+
+ * pr-5022.ch, pr-5022.exp: New testcase.
+ * chillvars.exp: Remove spurious newline.
+
+ * Makefile.in: Bunch of fixes so it actually works in this
+ directory. (E.g. add extra ../ where needed.)
+ Also, add .exe to executables, so we can use suffix rules.
+ * chexp.exp (test_print_reject): Update syntax error message.
+ * chillvars.ch (module PR_5020): Moved from here ...
+ * pr-5022.ch: ... to this new file.
+ * chillvars.exp, pr-5020.exp (binfile): Add .exe extension.
+ * chillvars.exp, pr-5020.exp: Don't check all_flag.
+ * pr-5020.exp: Add more tests; fix "print y pretty" output.
diff --git a/gdb/testsuite/gdb.chill/Makefile.in b/gdb/testsuite/gdb.chill/Makefile.in
new file mode 100644
index 00000000000..a965b578d74
--- /dev/null
+++ b/gdb/testsuite/gdb.chill/Makefile.in
@@ -0,0 +1,26 @@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+all:
+ @echo "Nothing to be done for all..."
+
+#### host, target, and site specific Makefile frags come in here.
+
+.SUFFIXES: .ch .o .exe .exp .check
+
+# Do 'make chillvars.check' to run just the chillvars.{ch,exp} test.
+
+.exp.check:
+ rootme=`pwd`/; export rootme; \
+ cd .. ; \
+ $(MAKE) just-check RUNTESTFLAGS="${RUNTESTFLAGS} $*.exp" \
+ EXPECT=${EXPECT}
+
+clean mostlyclean:
+ -rm -f *.o ${OBJS} *.exe *~ core
+
+distclean maintainer-clean realclean: clean
+ -rm -f Makefile config.status config.log
+
+Makefile: $(srcdir)/Makefile.in $(srcdir)/configure.in
+ $(SHELL) ./config.status --recheck
diff --git a/gdb/testsuite/gdb.chill/builtins.ch b/gdb/testsuite/gdb.chill/builtins.ch
new file mode 100644
index 00000000000..ef12c839b90
--- /dev/null
+++ b/gdb/testsuite/gdb.chill/builtins.ch
@@ -0,0 +1,83 @@
+xx: MODULE
+
+DCL v_bool BOOL INIT := FALSE;
+DCL v_char CHAR INIT := 'X';
+DCL v_byte BYTE INIT := -30;
+DCL v_ubyte UBYTE INIT := 30;
+DCL v_int INT INIT := -333;
+DCL v_uint UINT INIT := 333;
+DCL v_long LONG INIT := -4444;
+DCL v_ulong ULONG INIT := 4444;
+DCL v_ptr PTR;
+
+SYNMODE m_set = SET (e1, e2, e3, e4, e5, e6);
+DCL v_set m_set INIT := e3;
+
+SYNMODE m_set_range = m_set(e2:e5);
+DCL v_set_range m_set_range INIT := e3;
+
+SYNMODE m_numbered_set = SET (n1 = 25, n2 = 22, n3 = 35, n4 = 33,
+ n5 = 45, n6 = 43);
+DCL v_numbered_set m_numbered_set INIT := n3;
+
+SYNMODE m_char_range = CHAR('A':'Z');
+DCL v_char_range m_char_range INIT := 'G';
+
+SYNMODE m_bool_range = BOOL(FALSE:FALSE);
+DCL v_bool_range m_bool_range;
+
+SYNMODE m_long_range = LONG(255:3211);
+DCL v_long_range m_long_range INIT := 1000;
+
+SYNMODE m_range = RANGE(12:28);
+DCL v_range m_range INIT := 23;
+
+SYNMODE m_chars = CHARS(20);
+SYNMODE m_chars_v = CHARS(20) VARYING;
+DCL v_chars CHARS(20);
+DCL v_chars_v CHARS(20) VARYING INIT := "foo bar";
+
+SYNMODE m_bits = BOOLS(10);
+DCL v_bits BOOLS(10);
+
+SYNMODE m_arr = ARRAY(1:10) BYTE;
+DCL v_arr ARRAY(1:10) BYTE;
+
+SYNMODE m_char_arr = ARRAY (CHAR) BYTE;
+DCL v_char_arr ARRAY(CHAR) BYTE;
+
+SYNMODE m_bool_arr = ARRAY (BOOL) BYTE;
+DCL v_bool_arr ARRAY (BOOL) BYTE;
+
+SYNMODE m_int_arr = ARRAY (INT) BYTE;
+DCL v_int_arr ARRAY (INT) BYTE;
+
+SYNMODE m_set_arr = ARRAY (m_set) BYTE;
+DCL v_set_arr ARRAY (m_set) BYTE;
+
+SYNMODE m_numbered_set_arr = ARRAY (m_numbered_set) BYTE;
+DCL v_numbered_set_arr ARRAY (m_numbered_set) BYTE;
+
+SYNMODE m_char_range_arr = ARRAY (m_char_range) BYTE;
+DCL v_char_range_arr ARRAY (m_char_range) BYTE;
+
+SYNMODE m_set_range_arr = ARRAY (m_set_range) BYTE;
+DCL v_set_range_arr ARRAY (m_set_range) BYTE;
+
+SYNMODE m_bool_range_arr = ARRAY (m_bool_range) BYTE;
+DCL v_bool_range_arr ARRAY (m_bool_range) BYTE;
+
+SYNMODE m_long_range_arr = ARRAY (m_long_range) BYTE;
+DCL v_long_range_arr ARRAY (m_long_range) BYTE;
+
+SYNMODE m_range_arr = ARRAY (m_range) BYTE;
+DCL v_range_arr ARRAY (m_range) BYTE;
+
+SYNMODE m_struct = STRUCT (i LONG,
+ c CHAR,
+ s CHARS(30));
+DCL v_struct m_struct;
+
+v_bool := TRUE;
+
+END xx;
diff --git a/gdb/testsuite/gdb.chill/builtins.exp b/gdb/testsuite/gdb.chill/builtins.exp
new file mode 100644
index 00000000000..a75ca200c80
--- /dev/null
+++ b/gdb/testsuite/gdb.chill/builtins.exp
@@ -0,0 +1,441 @@
+# Copyright (C) 1995, 1997 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file tests various Chill values, expressions, and types.
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+if [skip_chill_tests] then { continue }
+
+set testfile "builtins"
+set srcfile ${srcdir}/$subdir/${testfile}.ch
+set binfile ${objdir}/${subdir}/${testfile}.exe
+if { [compile "${srcfile} -g -w -o ${binfile} ${CHILL_RT0} ${CHILL_LIB}"] != "" } {
+ perror "Couldn't compile ${srcfile}"
+ return -1
+}
+
+# Set the current language to chill. This counts as a test. If it
+# fails, then we skip the other tests.
+
+proc set_lang_chill {} {
+ global gdb_prompt
+ global binfile objdir subdir
+
+ verbose "loading file '$binfile'"
+ gdb_load $binfile
+ send_gdb "set language chill\n"
+ gdb_expect {
+ -re ".*$gdb_prompt $" {}
+ timeout { fail "set language chill (timeout)" ; return 0 }
+ }
+
+ send_gdb "show language\n"
+ gdb_expect {
+ -re ".* source language is \"chill\".*$gdb_prompt $" {
+ pass "set language to \"chill\""
+ send_gdb "break xx_\n"
+ gdb_expect {
+ -re ".*$gdb_prompt $" {
+ send_gdb "run\n"
+ gdb_expect -re ".*$gdb_prompt $" {}
+ return 1
+ }
+ timeout {
+ fail "can't set breakpoint (timeout)"
+ return 0
+ }
+ }
+ }
+ -re ".*$gdb_prompt $" {
+ fail "setting language to \"chill\""
+ return 0
+ }
+ timeout {
+ fail "can't show language (timeout)"
+ return 0
+ }
+ }
+}
+
+# Testing printing of a specific value. Increment passcount for
+# success or issue fail message for failure. In both cases, return
+# a 1 to indicate that more tests can proceed. However a timeout
+# is a serious error, generates a special fail message, and causes
+# a 0 to be returned to indicate that more tests are likely to fail
+# as well.
+#
+# Args are:
+#
+# First one is string to send_gdb to gdb
+# Second one is string to match gdb result to
+# Third one is an optional message to be printed
+
+proc test_print_accept { args } {
+ global gdb_prompt
+ global passcount
+ global verbose
+
+ if [llength $args]==3 then {
+ set message [lindex $args 2]
+ } else {
+ set message [lindex $args 0]
+ }
+ set sendthis [lindex $args 0]
+ set expectthis [lindex $args 1]
+ set result [gdb_test $sendthis ".* = ${expectthis}" $message]
+ if $result==0 {incr passcount}
+ return $result
+}
+
+proc test_lower {} {
+ global passcount
+
+ verbose "testing builtin LOWER"
+ set passcount 0
+
+ # discrete mode names
+ test_print_accept "print lower(bool)" "FALSE"
+ test_print_accept "print lower(char)" {'\^[(]0[)]'}
+ test_print_accept "print lower(byte)" "-128"
+ test_print_accept "print lower(ubyte)" "0"
+ if [istarget "alpha-*-*"] then {
+ test_print_accept "print lower(int)" "-2147483648"
+ } else {
+ test_print_accept "print lower(int)" "-32768"
+ }
+ test_print_accept "print lower(uint)" "0"
+ setup_xfail "alpha-*-*"
+ test_print_accept "print lower(long)" "-2147483648"
+ test_print_accept "print lower(ulong)" "0"
+ test_print_accept "print lower(m_set)" "e1"
+ test_print_accept "print lower(m_set_range)" "e2"
+ test_print_accept "print lower(m_numbered_set)" "n2"
+ test_print_accept "print lower(m_char_range)" "'A'"
+ test_print_accept "print lower(m_bool_range)" "FALSE"
+ test_print_accept "print lower(m_long_range)" "255"
+ test_print_accept "print lower(m_range)" "12"
+
+ # discrete locations
+ test_print_accept "print lower(v_bool)" "FALSE"
+ test_print_accept "print lower(v_char)" {'\^[(]0[)]'}
+ test_print_accept "print lower(v_byte)" "-128"
+ test_print_accept "print lower(v_ubyte)" "0"
+ if [istarget "alpha-*-*"] then {
+ test_print_accept "print lower(v_int)" "-2147483648"
+ } else {
+ test_print_accept "print lower(v_int)" "-32768"
+ }
+ test_print_accept "print lower(v_uint)" "0"
+ setup_xfail "alpha-*-*"
+ test_print_accept "print lower(v_long)" "-2147483648"
+ test_print_accept "print lower(v_ulong)" "0"
+ test_print_accept "print lower(v_set)" "e1"
+ test_print_accept "print lower(v_set_range)" "e2"
+ test_print_accept "print lower(v_numbered_set)" "n2"
+ test_print_accept "print lower(v_char_range)" "'A'"
+ test_print_accept "print lower(v_bool_range)" "FALSE"
+ test_print_accept "print lower(v_long_range)" "255"
+ test_print_accept "print lower(v_range)" "12"
+
+ # string mode names
+ test_print_accept "print lower(m_chars)" "0"
+ test_print_accept "print lower(m_chars_v)" "0"
+ test_print_accept "print lower(m_bits)" "0"
+
+ # string locations
+ test_print_accept "print lower(v_chars)" "0"
+ test_print_accept "print lower(v_chars_v)" "0"
+ test_print_accept "print lower(v_bits)" "0"
+
+ # string expressions
+ test_print_accept "print lower(\"abcd\")" "0"
+ test_print_accept "print lower(B'010101')" "0"
+
+ # array mode name
+ test_print_accept "print lower(m_arr)" "1";
+ test_print_accept "print lower(m_char_arr)" {'\^[(]0[)]'}
+ test_print_accept "print lower(m_bool_arr)" "FALSE"
+ if [istarget "alpha-*-*"] then {
+ test_print_accept "print lower(m_int_arr)" "-2147483648"
+ } else {
+ test_print_accept "print lower(m_int_arr)" "-32768"
+ }
+ test_print_accept "print lower(m_set_arr)" "e1"
+ test_print_accept "print lower(m_set_range_arr)" "e2"
+ test_print_accept "print lower(m_numbered_set_arr)" "n2"
+ test_print_accept "print lower(m_char_range_arr)" "'A'"
+ test_print_accept "print lower(m_bool_range_arr)" "FALSE"
+ test_print_accept "print lower(m_long_range_arr)" "255"
+ test_print_accept "print lower(m_range_arr)" "12"
+
+ # array locations
+ test_print_accept "print lower(v_arr)" "1";
+ test_print_accept "print lower(v_char_arr)" {'\^[(]0[)]'}
+ test_print_accept "print lower(v_bool_arr)" "FALSE"
+ if [istarget "alpha-*-*"] then {
+ test_print_accept "print lower(v_int_arr)" "-2147483648"
+ } else {
+ test_print_accept "print lower(v_int_arr)" "-32768"
+ }
+ test_print_accept "print lower(v_set_arr)" "e1"
+ test_print_accept "print lower(v_set_range_arr)" "e2"
+ test_print_accept "print lower(v_numbered_set_arr)" "n2"
+ test_print_accept "print lower(v_char_range_arr)" "'A'"
+ test_print_accept "print lower(v_bool_range_arr)" "FALSE"
+ test_print_accept "print lower(v_long_range_arr)" "255"
+ test_print_accept "print lower(v_range_arr)" "12"
+}
+
+proc test_upper {} {
+ global passcount
+
+ verbose "testing builtin UPPER"
+ set passcount 0
+
+ # discrete mode names
+ test_print_accept "print upper(bool)" "TRUE"
+ test_print_accept "print upper(char)" {'\^[(]255[)]'}
+ test_print_accept "print upper(byte)" "127"
+ test_print_accept "print upper(ubyte)" "255"
+ if [istarget "alpha-*-*"] then {
+ test_print_accept "print upper(int)" "2147483647"
+ test_print_accept "print upper(uint)" "4294967295"
+ setup_xfail "alpha-*-*"
+ test_print_accept "print upper(long)" "4294967295"
+ test_print_accept "print upper(ulong)" "18446744073709551615"
+ } else {
+ test_print_accept "print upper(int)" "32767"
+ test_print_accept "print upper(uint)" "65535"
+ test_print_accept "print upper(long)" "2147483647"
+ test_print_accept "print upper(ulong)" "4294967295"
+ }
+ test_print_accept "print upper(m_set)" "e6"
+ test_print_accept "print upper(m_set_range)" "e5"
+ test_print_accept "print upper(m_numbered_set)" "n5"
+ test_print_accept "print upper(m_char_range)" "'Z'"
+ test_print_accept "print upper(m_bool_range)" "FALSE"
+ test_print_accept "print upper(m_long_range)" "3211"
+ test_print_accept "print upper(m_range)" "28"
+
+ # discrete locations
+ test_print_accept "print upper(v_bool)" "TRUE"
+ test_print_accept "print upper(v_char)" {'\^[(]255[)]'}
+ test_print_accept "print upper(v_byte)" "127"
+ test_print_accept "print upper(v_ubyte)" "255"
+ if [istarget "alpha-*-*"] then {
+ test_print_accept "print upper(v_int)" "2147483647"
+ test_print_accept "print upper(v_uint)" "4294967295"
+ setup_xfail "alpha-*-*"
+ test_print_accept "print upper(v_long)" "4294967295"
+ test_print_accept "print upper(v_ulong)" "18446744073709551615"
+ } else {
+ test_print_accept "print upper(v_int)" "32767"
+ test_print_accept "print upper(v_uint)" "65535"
+ test_print_accept "print upper(v_long)" "2147483647"
+ test_print_accept "print upper(v_ulong)" "4294967295"
+ }
+ test_print_accept "print upper(v_set)" "e6"
+ test_print_accept "print upper(v_set_range)" "e5"
+ test_print_accept "print upper(v_numbered_set)" "n5"
+ test_print_accept "print upper(v_char_range)" "'Z'"
+ test_print_accept "print upper(v_bool_range)" "FALSE"
+ test_print_accept "print upper(v_long_range)" "3211"
+ test_print_accept "print upper(v_range)" "28"
+
+ # string mode names
+ test_print_accept "print upper(m_chars)" "19"
+ test_print_accept "print upper(m_chars_v)" "19"
+ test_print_accept "print upper(m_bits)" "9"
+
+ # string locations
+ test_print_accept "print upper(v_chars)" "19"
+ test_print_accept "print upper(v_chars_v)" "19"
+ test_print_accept "print upper(v_bits)" "9"
+
+ # string expressions
+ test_print_accept "print upper(\"abcd\")" "3"
+ test_print_accept "print upper(B'010101')" "5"
+
+ # array mode name
+ test_print_accept "print upper(m_arr)" "10";
+ test_print_accept "print upper(m_char_arr)" {'\^[(]255[)]'}
+ test_print_accept "print upper(m_bool_arr)" "TRUE"
+ if [istarget "alpha-*-*"] then {
+ test_print_accept "print upper(m_int_arr)" "2147483647"
+ } else {
+ test_print_accept "print upper(m_int_arr)" "32767"
+ }
+ test_print_accept "print upper(m_set_arr)" "e6"
+ test_print_accept "print upper(m_set_range_arr)" "e5"
+ test_print_accept "print upper(m_numbered_set_arr)" "n5"
+ test_print_accept "print upper(m_char_range_arr)" "'Z'"
+ test_print_accept "print upper(m_bool_range_arr)" "FALSE"
+ test_print_accept "print upper(m_long_range_arr)" "3211"
+ test_print_accept "print upper(m_range_arr)" "28"
+
+ # array locations
+ test_print_accept "print upper(v_arr)" "10";
+ test_print_accept "print upper(v_char_arr)" {'\^[(]255[)]'}
+ test_print_accept "print upper(v_bool_arr)" "TRUE"
+ if [istarget "alpha-*-*"] then {
+ test_print_accept "print upper(v_int_arr)" "2147483647"
+ } else {
+ test_print_accept "print upper(v_int_arr)" "32767"
+ }
+ test_print_accept "print upper(v_set_arr)" "e6"
+ test_print_accept "print upper(v_set_range_arr)" "e5"
+ test_print_accept "print upper(v_numbered_set_arr)" "n5"
+ test_print_accept "print upper(v_char_range_arr)" "'Z'"
+ test_print_accept "print upper(v_bool_range_arr)" "FALSE"
+ test_print_accept "print upper(v_long_range_arr)" "3211"
+ test_print_accept "print upper(v_range_arr)" "28"
+}
+
+proc test_length {} {
+ global passcount
+
+ verbose "testing builtin LENGTH"
+ set passcount 0
+
+ # string locations
+ test_print_accept "print length(v_chars)" "20"
+ test_print_accept "print length(v_chars_v)" "7";
+ test_print_accept "print length(v_bits)" "10";
+
+ # string expressions
+ test_print_accept "print length(\"the quick brown fox ...\")" "23"
+ test_print_accept "print length(B'010101010101')" "12"
+ test_print_accept "print length(\"foo \" // \"bar\")" "7"
+
+ # check some failures
+ setup_xfail "*-*-*"
+ test_print_accept "print length(m_chars)" "typename in invalid context"
+ setup_xfail "*-*-*"
+ test_print_accept "print length(v_byte)" "bad argument to LENGTH builtin"
+ setup_xfail "*-*-*"
+ test_print_accept "print length(b'000000' // b'111111')" "12"
+}
+
+proc test_size {} {
+ global passcount
+
+ verbose "testing builtin SIZE"
+ set passcount 0
+
+ # modes
+ test_print_accept "print size(bool)" "1"
+ test_print_accept "print size(char)" "1"
+ test_print_accept "print size(byte)" "1"
+ if [istarget "alpha-*-*"] then {
+ test_print_accept "print size(int)" "4"
+ test_print_accept "print size(ulong)" "8"
+ test_print_accept "print size(ptr)" "8"
+ test_print_accept "print size(m_chars_v)" "24"
+ test_print_accept "print size(m_struct)" "40"
+ } else {
+ test_print_accept "print size(int)" "2"
+ test_print_accept "print size(ulong)" "4"
+ test_print_accept "print size(ptr)" "4"
+ test_print_accept "print size(m_chars_v)" "22"
+ test_print_accept "print size(m_struct)" "36"
+ }
+ test_print_accept "print size(m_set)" "1"
+ test_print_accept "print size(m_numbered_set)" "1"
+ test_print_accept "print size(m_char_range)" "1"
+ test_print_accept "print size(m_range_arr)" "17"
+ test_print_accept "print size(m_chars)" "20"
+ test_print_accept "print size(m_bits)" "2"
+
+ # locations
+ test_print_accept "print size(v_bool)" "1"
+ test_print_accept "print size(v_char)" "1"
+ test_print_accept "print size(v_byte)" "1"
+ if [istarget "alpha-*-*"] then {
+ test_print_accept "print size(v_int)" "4"
+ test_print_accept "print size(v_ulong)" "8"
+ test_print_accept "print size(v_ptr)" "8"
+ test_print_accept "print size(v_chars_v)" "24"
+ test_print_accept "print size(v_struct)" "40"
+ } else {
+ test_print_accept "print size(v_int)" "2"
+ test_print_accept "print size(v_ulong)" "4"
+ test_print_accept "print size(v_ptr)" "4"
+ test_print_accept "print size(v_chars_v)" "22"
+ test_print_accept "print size(v_struct)" "36"
+ }
+ test_print_accept "print size(v_set)" "1"
+ test_print_accept "print size(v_numbered_set)" "1"
+ test_print_accept "print size(v_char_range)" "1"
+ test_print_accept "print size(v_range_arr)" "17"
+ test_print_accept "print size(v_chars)" "20"
+ test_print_accept "print size(v_bits)" "2"
+}
+
+proc test_num {} {
+ global passcount
+
+ verbose "testing builtin NUM"
+ set passcount 0
+
+ # constants
+ test_print_accept "print num(false)" "0"
+ test_print_accept "print num(true)" "1"
+ test_print_accept "print num(10)" "10"
+ test_print_accept "print num(33-34)" "-1"
+ test_print_accept "print num('X')" "88"
+ test_print_accept "print num(e5)" "4"
+
+ # locations
+ test_print_accept "print num(v_bool)" "0"
+ test_print_accept "print num(v_char)" "88"
+ test_print_accept "print num(v_byte)" "-30"
+ test_print_accept "print num(v_ubyte)" "30"
+ test_print_accept "print num(v_int)" "-333"
+ test_print_accept "print num(v_uint)" "333"
+ test_print_accept "print num(v_long)" "-4444"
+ test_print_accept "print num(v_ulong)" "4444"
+ test_print_accept "print num(v_set)" "2"
+ test_print_accept "print num(v_set_range)" "2"
+ test_print_accept "print num(v_numbered_set)" "35"
+ test_print_accept "print num(v_char_range)" "71"
+ test_print_accept "print num(v_long_range)" "1000"
+ test_print_accept "print num(v_range)" "23"
+}
+
+# Start with a fresh gdb.
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+
+gdb_test "set print sevenbit-strings" ".*"
+
+if [set_lang_chill] then {
+ # test builtins as described in chapter 6.20.3 Z.200
+ test_num
+ test_size
+ test_lower
+ test_upper
+ test_length
+} else {
+ warning "$test_name tests suppressed."
+}
diff --git a/gdb/testsuite/gdb.chill/callch.ch b/gdb/testsuite/gdb.chill/callch.ch
new file mode 100644
index 00000000000..6001d92443b
--- /dev/null
+++ b/gdb/testsuite/gdb.chill/callch.ch
@@ -0,0 +1,50 @@
+hack : module
+
+dcl i int;
+newmode otto = array (bool, bool) byte;
+newmode str1 = struct (f1 int, f2 bool);
+newmode str2 = struct (f1 otto);
+
+dcl a otto := [[1,1],[1,1]];
+dcl b str1 := [10, false];
+dcl c str2;
+
+fred : proc (a int in, b int loc);
+ writetext(stdout, "a is '%C'; b is '%C'.%/", a, b);
+end fred;
+
+klaus : proc ();
+ writetext(stdout, "here's klaus calling.%/");
+end klaus;
+
+king : proc (p otto loc, x otto in);
+ dcl i, j bool;
+ p := [[h'ff,h'ff],[h'ff,h'ff]];
+ do for i:= lower(bool) to upper(bool);
+ do for j:= lower(bool) to upper(bool);
+ writetext(stdout, "x(%C, %C) = %C%..%/", i, j, x(i, j));
+ writetext(stdout, "p(%C, %C) = %C%..%/", i, j, p(i, j));
+ od;
+ od;
+end king;
+
+ralph : proc (x str1 in);
+ writetext(stdout, "x.f1 = %C, x.f2 = %C%..%/", x.f1, x.f2);
+end ralph;
+
+whitney : proc (x str2 in);
+ dcl i, j bool;
+
+ do for i:= lower(bool) to upper(bool);
+ do for j:= lower(bool) to upper(bool);
+ writetext(stdout, "x.f1(%C, %C) = %C%..%/", i, j, x.f1(i, j));
+ od;
+ od;
+
+end whitney;
+
+c := [a];
+i:=12;
+writetext(stdout, "done.%/");
+
+end hack;
diff --git a/gdb/testsuite/gdb.chill/callch.exp b/gdb/testsuite/gdb.chill/callch.exp
new file mode 100644
index 00000000000..c579a059e07
--- /dev/null
+++ b/gdb/testsuite/gdb.chill/callch.exp
@@ -0,0 +1,69 @@
+# Copyright (C) 1995, 1997 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file tests that gdb can call functions in a Chill inferior.
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+if [skip_chill_tests] then { continue }
+
+set testfile "callch"
+set srcfile ${srcdir}/$subdir/${testfile}.ch
+set binfile ${objdir}/${subdir}/${testfile}.exe
+if { [compile "${srcfile} -g -o ${binfile} ${CHILL_RT0} ${CHILL_LIB}"] != "" } {
+ perror "Couldn't compile ${srcfile}"
+ return -1
+}
+
+proc do_tests {} {
+ global prms_id bug_id subdir objdir srcdir binfile gdb_prompt
+
+ set prms_id 0
+ set bug_id 0
+
+ # Start with a fresh gdb.
+
+ gdb_exit
+ gdb_start
+ gdb_reinitialize_dir $srcdir/$subdir
+ gdb_load $binfile
+
+ send_gdb "set language chill\n" ;
+
+ gdb_test "break callch.ch:48" ""
+ send_gdb "run\n"; gdb_expect -re "Breakpoint .*callch.ch:48.*$gdb_prompt $"
+ gdb_test {set fred(10, i)} {a is '10'; b is '12'.}
+ gdb_test_exact "call klaus()" {here's klaus calling.}
+ gdb_test_exact "call fred()" {too few arguments in function call}
+ # Too many arguments are allowed
+ gdb_test_exact "call klaus(10, 20, 30)" {here's klaus calling.}
+ gdb_test "print a" { = \[\(FALSE:TRUE\): \[\(FALSE:TRUE\): 1\]\]}\
+ "print a before king"
+ # Current gdb prints 255 for the results that are expected to be -1.
+ setup_xfail "mips*-sgi-irix*"
+ gdb_test {call king(a, otto[[10, 15], [20, 25]])} "x\\(FALSE, FALSE\\) = 10.*p\\(FALSE, FALSE\\) = -1.*x\\(FALSE, TRUE\\) = 15.*p\\(FALSE, TRUE\\) = -1.*x\\(TRUE, FALSE\\) = 20.*p\\(TRUE, FALSE\\) = -1.*x\\(TRUE, TRUE\\) = 25.*p\\(TRUE, TRUE\\) = -1.*"
+ gdb_test "print a" { = \[\(FALSE:TRUE\): \[\(FALSE:TRUE\): -1\]\]}\
+ "print a after king"
+ gdb_test_exact "call ralph(b)" {x.f1 = 10, x.f2 = FALSE.}
+ gdb_test "call whitney(c)" "x.f1\\(FALSE, FALSE\\) = 1.*x.f1\\(FALSE, TRUE\\) = 1.*x.f1\\(TRUE, FALSE\\) = 1.*x.f1\\(TRUE, TRUE\\) = 1.*"
+}
+
+do_tests
diff --git a/gdb/testsuite/gdb.chill/chexp.exp b/gdb/testsuite/gdb.chill/chexp.exp
new file mode 100644
index 00000000000..bed4aba983e
--- /dev/null
+++ b/gdb/testsuite/gdb.chill/chexp.exp
@@ -0,0 +1,450 @@
+# Copyright (C) 1992, 1997 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file was written by Fred Fish. (fnf@cygnus.com)
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+set prms_id 0
+set bug_id 0
+
+# Set the current language to chill. This counts as a test. If it
+# fails, then we skip the other tests.
+
+proc set_lang_chill {} {
+ global gdb_prompt
+
+ send_gdb "set language chill\n"
+ gdb_expect {
+ -re ".*$gdb_prompt $" {}
+ timeout { fail "set language chill (timeout)" ; return 0 }
+ }
+
+ send_gdb "show language\n"
+ gdb_expect {
+ -re ".* source language is \"chill\".*$gdb_prompt $" {
+ pass "set language to \"chill\""
+ return 1
+ }
+ -re ".*$gdb_prompt $" {
+ fail "setting language to \"chill\""
+ return 0
+ }
+ timeout {
+ fail "can't show language (timeout)"
+ return 0
+ }
+ }
+}
+
+proc test_integer_literals_accepted {} {
+ global gdb_prompt
+
+ # Test various decimal values.
+
+ gdb_test "p 123" " = 123"
+ gdb_test "p -123" " = -123"
+ gdb_test "p D'123" " = 123"
+ gdb_test "p d'123" " = 123"
+ gdb_test "p -D'123" " = -123"
+ gdb_test "p -d'123" " = -123"
+ gdb_test "p 12_345" " = 12345"
+ gdb_test "p __1_2_3__" " = 123"
+ gdb_test "p/d 123" " = D'123"
+
+ # Test various binary values.
+
+ gdb_test "p B'111" " = 7"
+ gdb_test "p b'111" " = 7"
+ gdb_test "p -B'111" " = -7"
+ gdb_test "p B'0111" " = 7"
+ gdb_test "p b'0111" " = 7"
+ gdb_test "p -b'0111" " = -7"
+ gdb_test "p B'_0_1_1_1_" " = 7"
+ gdb_test "p b'_0_1_1_1_" " = 7"
+ gdb_test "p -b'_0_1_1_1_" " = -7"
+ gdb_test "p/t B'111" " = B'111"
+
+ # Test various octal values.
+
+ gdb_test "p O'123" " = 83"
+ gdb_test "p o'123" " = 83"
+ gdb_test "p -o'0123" " = -83"
+ gdb_test "p O'0123" " = 83"
+ gdb_test "p o'0123" " = 83"
+ gdb_test "p -o'123" " = -83"
+ gdb_test "p O'_1_2_3_" " = 83"
+ gdb_test "p o'_1_2_3_" " = 83"
+ gdb_test "p -o'_1_2_3_" " = -83"
+ gdb_test "p/o O'123" " = O'123"
+
+ # Test various hexadecimal values.
+
+ gdb_test "p H'123" " = 291"
+ gdb_test "p h'123" " = 291"
+ gdb_test "p -h'123" " = -291"
+ gdb_test "p H'0123" " = 291"
+ gdb_test "p h'0123" " = 291"
+ gdb_test "p -h'0123" " = -291"
+ gdb_test "p H'_1_2_3_" " = 291"
+ gdb_test "p h'_1_2_3_" " = 291"
+ gdb_test "p -h'_1_2_3_" " = -291"
+ gdb_test "p H'ABC" " = 2748"
+ gdb_test "p H'abc" " = 2748"
+ gdb_test "p H'AbC" " = 2748"
+ gdb_test "p H'_A_b_C_" " = 2748"
+ gdb_test "p H'_D_e_F_" " = 3567"
+ gdb_test "p H'_d_E_f_" " = 3567"
+ gdb_test "p/x H'123" " = H'123"
+}
+
+proc test_character_literals_accepted {} {
+ global gdb_prompt
+
+ # Test various decimal values.
+
+ gdb_test "p 'a'" " = 'a'"
+ gdb_test "p/x 'a'" " = H'61"
+ gdb_test "p/d 'a'" " = D'97"
+ gdb_test "p/t 'a'" " = B'1100001"
+ # gdb_test "p '^(97)'" " = 'a'" (not in GNU Chill)
+ gdb_test "p C'61'" " = 'a'"
+ gdb_test "p c'61'" " = 'a'"
+ gdb_test "p/x C'FF'" " = H'ff"
+ # gdb_test "p/x '^(H'FF)'" " = H'ff" (not in GNU Chill)
+ # gdb_test "p/x '^(D'255)'" " = H'ff" (not in GNU Chill)
+}
+
+proc test_integer_literals_rejected {} {
+ global gdb_prompt
+
+ # These are valid integer literals in Z.200, but not GNU-Chill.
+
+ test_print_reject "p _"
+ test_print_reject "p __"
+
+ test_print_reject "p D'"
+ test_print_reject "p D'_"
+ test_print_reject "p D'__"
+
+ test_print_reject "p B'"
+ test_print_reject "p B'_"
+ test_print_reject "p B'__"
+
+ test_print_reject "p O'"
+ test_print_reject "p O'_"
+ test_print_reject "p O'__"
+
+ test_print_reject "p H'"
+ test_print_reject "p H'_"
+ test_print_reject "p H'__"
+
+ # Test various decimal values.
+
+ test_print_reject "p D'DEADBEEF"
+ test_print_reject "p D'123DEADBEEF"
+
+ # Test various binary values.
+
+ test_print_reject "p B'2" "Too-large digit in bitstring or integer."
+ test_print_reject "p B'12" "Too-large digit in bitstring or integer."
+
+ # Test various octal values.
+
+ test_print_reject "p O'9" "Too-large digit in bitstring or integer."
+ test_print_reject "p O'79" "Too-large digit in bitstring or integer."
+
+ # Test various hexadecimal values.
+
+ test_print_reject "p H'G" "Invalid character in bitstring or integer."
+ test_print_reject "p H'AG" "Invalid character in bitstring or integer."
+}
+
+proc test_boolean_literals_accepted {} {
+ global gdb_prompt
+
+ # Test the only possible values for a boolean, TRUE and FALSE.
+
+ gdb_test "p TRUE" " = TRUE"
+ gdb_test "p FALSE" " = FALSE"
+}
+
+proc test_float_literals_accepted {} {
+ global gdb_prompt
+
+ # Test various floating point formats
+
+ gdb_test "p .44 < .45" " = TRUE"
+ gdb_test "p .44 > .45" " = FALSE"
+ gdb_test "p 0.44 < 0.45" " = TRUE"
+ gdb_test "p 0.44 > 0.45" " = FALSE"
+ gdb_test "p 44. < 45." " = TRUE"
+ gdb_test "p 44. > 45." " = FALSE"
+ gdb_test "p 44.0 < 45.0" " = TRUE"
+ gdb_test "p 44.0 > 45.0" " = FALSE"
+ gdb_test "p 10D20 < 10D21" " = TRUE"
+ gdb_test "p 10D20 > 10D21" " = FALSE"
+ gdb_test "p 10d20 < 10d21" " = TRUE"
+ gdb_test "p 10d20 > 10d21" " = FALSE"
+ gdb_test "p 10E20 < 10E21" " = TRUE"
+ gdb_test "p 10E20 > 10E21" " = FALSE"
+ gdb_test "p 10e20 < 10e21" " = TRUE"
+ gdb_test "p 10e20 > 10e21" " = FALSE"
+ gdb_test "p 10.D20 < 10.D21" " = TRUE"
+ gdb_test "p 10.D20 > 10.D21" " = FALSE"
+ gdb_test "p 10.d20 < 10.d21" " = TRUE"
+ gdb_test "p 10.d20 > 10.d21" " = FALSE"
+ gdb_test "p 10.E20 < 10.E21" " = TRUE"
+ gdb_test "p 10.E20 > 10.E21" " = FALSE"
+ gdb_test "p 10.e20 < 10.e21" " = TRUE"
+ gdb_test "p 10.e20 > 10.e21" " = FALSE"
+ gdb_test "p 10.0D20 < 10.0D21" " = TRUE"
+ gdb_test "p 10.0D20 > 10.0D21" " = FALSE"
+ gdb_test "p 10.0d20 < 10.0d21" " = TRUE"
+ gdb_test "p 10.0d20 > 10.0d21" " = FALSE"
+ gdb_test "p 10.0E20 < 10.0E21" " = TRUE"
+ gdb_test "p 10.0E20 > 10.0E21" " = FALSE"
+ gdb_test "p 10.0e20 < 10.0e21" " = TRUE"
+ gdb_test "p 10.0e20 > 10.0e21" " = FALSE"
+ gdb_test "p 10.0D+20 < 10.0D+21" " = TRUE"
+ gdb_test "p 10.0D+20 > 10.0D+21" " = FALSE"
+ gdb_test "p 10.0d+20 < 10.0d+21" " = TRUE"
+ gdb_test "p 10.0d+20 > 10.0d+21" " = FALSE"
+ gdb_test "p 10.0E+20 < 10.0E+21" " = TRUE"
+ gdb_test "p 10.0E+20 > 10.0E+21" " = FALSE"
+ gdb_test "p 10.0e+20 < 10.0e+21" " = TRUE"
+ gdb_test "p 10.0e+20 > 10.0e+21" " = FALSE"
+ gdb_test "p 10.0D-11 < 10.0D-10" " = TRUE"
+ gdb_test "p 10.0D-11 > 10.0D-10" " = FALSE"
+ gdb_test "p 10.0d-11 < 10.0d-10" " = TRUE"
+ gdb_test "p 10.0d-11 > 10.0d-10" " = FALSE"
+ gdb_test "p 10.0E-11 < 10.0E-10" " = TRUE"
+ gdb_test "p 10.0E-11 > 10.0E-10" " = FALSE"
+ gdb_test "p 10.0e-11 < 10.0e-10" " = TRUE"
+ gdb_test "p 10.0e-11 > 10.0e-10" " = FALSE"
+ # looks funny, but apparently legal
+ gdb_test "p _.1e+10 < _.1e+11" " = TRUE"
+ gdb_test "p _.1e+10 > _.1e+11" " = FALSE"
+ gdb_test "p __.1e-12 < __.1e-11" " = TRUE"
+ gdb_test "p __.1e-12 > __.1e-11" " = FALSE"
+}
+
+proc test_convenience_variables {} {
+ global gdb_prompt
+
+ gdb_test "set \$foo := 101" " := 101\[\r\]*" \
+ "Set a new convenience variable"
+
+ gdb_test "print \$foo" " = 101" \
+ "Print contents of new convenience variable"
+
+ gdb_test "set \$foo := 301" " := 301\[\r\]*" \
+ "Set convenience variable to a new value"
+
+ gdb_test "print \$foo" " = 301" \
+ "Print new contents of convenience variable"
+
+ gdb_test "set \$_ := 11" " := 11\[\r\]*" \
+ "Set convenience variable \$_"
+
+ gdb_test "print \$_" " = 11" \
+ "Print contents of convenience variable \$_"
+
+ gdb_test "print \$foo + 10" " = 311" \
+ "Use convenience variable in arithmetic expression"
+
+ gdb_test "print (\$foo := 32) + 4" " = 36" \
+ "Use convenience variable assignment in arithmetic expression"
+
+ gdb_test "print \$bar" " = void" \
+ "Print contents of uninitialized convenience variable"
+}
+
+proc test_value_history {} {
+ global gdb_prompt
+
+ gdb_test "print 101" "\\\$1 = 101" \
+ "Set value-history\[1\] using \$1"
+
+ gdb_test "print 102" "\\\$2 = 102" \
+ "Set value-history\[2\] using \$2"
+
+ gdb_test "print 103" "\\\$3 = 103" \
+ "Set value-history\[3\] using \$3"
+
+ gdb_test "print \$\$" "\\\$4 = 102" \
+ "Print value-history\[MAX-1\] using inplicit index \$\$"
+
+ gdb_test "print \$\$" "\\\$5 = 103" \
+ "Print value-history\[MAX-1\] again using implicit index \$\$"
+
+ gdb_test "print \$" "\\\$6 = 103" \
+ "Print value-history\[MAX\] using implicit index \$"
+
+ gdb_test "print \$\$2" "\\\$7 = 102" \
+ "Print value-history\[MAX-2\] using explicit index \$\$2"
+
+ gdb_test "print \$0" "\\\$8 = 102" \
+ "Print value-history\[MAX\] using explicit index \$0"
+
+ gdb_test "print 108" "\\\$9 = 108" ""
+
+ gdb_test "print \$\$0" "\\\$10 = 108" \
+ "Print value-history\[MAX\] using explicit index \$\$0"
+
+ gdb_test "print \$1" "\\\$11 = 101" \
+ "Print value-history\[1\] using explicit index \$1"
+
+ gdb_test "print \$2" "\\\$12 = 102" \
+ "Print value-history\[2\] using explicit index \$2"
+
+ gdb_test "print \$3" "\\\$13 = 103" \
+ "Print value-history\[3\] using explicit index \$3"
+
+ gdb_test "print \$-3" "\\\$14 = 100" \
+ "Print (value-history\[MAX\] - 3) using implicit index \$"
+
+ gdb_test "print \$1 + 3" "\\\$15 = 104" \
+ "Use value-history element in arithmetic expression"
+}
+
+proc test_arithmetic_expressions {} {
+ global gdb_prompt
+
+ # Test unary minus with various operands
+
+# gdb_test "p -(TRUE)" " = -1" "unary minus applied to bool"
+# gdb_test "p -('a')" " = xxx" "unary minus applied to char"
+ gdb_test "p -(1)" " = -1" "unary minus applied to int"
+ gdb_test "p -(1.0)" " = -1" "unary minus applied to real"
+
+ # Test addition with various operands
+
+ gdb_test "p TRUE + 1" " = 2" "bool plus int"
+ gdb_test "p 'a' + 1" " = 98" "char plus int"
+ gdb_test "p 1 + 1" " = 2" "int plus int"
+ gdb_test "p 1.0 + 1" " = 2" "real plus int"
+ gdb_test "p 1.0 + 2.0" " = 3" "real plus real"
+
+ # Test subtraction with various operands
+
+ gdb_test "p TRUE - 1" " = 0" "bool minus int"
+ gdb_test "p 'b' - 1" " = 97" "char minus int"
+ gdb_test "p 3 - 1" " = 2" "int minus int"
+ gdb_test "p 3.0 - 1" " = 2" "real minus int"
+ gdb_test "p 5.0 - 2.0" " = 3" "real minus real"
+
+ # Test multiplication with various operands
+
+ gdb_test "p TRUE * 1" " = 1" "bool times int"
+ gdb_test "p 'a' * 2" " = 194" "char times int"
+ gdb_test "p 2 * 3" " = 6" "int times int"
+ gdb_test "p 2.0 * 3" " = 6" "real times int"
+ gdb_test "p 2.0 * 3.0" " = 6" "real times real"
+
+ # Test division with various operands
+
+ gdb_test "p TRUE / 1" " = 1" "bool divided by int"
+ gdb_test "p 'a' / 2" " = 48" "char divided by int"
+ gdb_test "p 6 / 3" " = 2" "int divided by int"
+ gdb_test "p 6.0 / 3" " = 2" "real divided by int"
+ gdb_test "p 6.0 / 3.0" " = 2" "real divided by real"
+
+ # Test modulo with various operands
+
+ gdb_test "p TRUE MOD 1" " = 0" "bool modulo int"
+ gdb_test "p 'a' MOD 2" " = 1" "char modulo int"
+ gdb_test "p -5 MOD 3" " = 1" "negative int modulo int"
+ gdb_test "p 5 MOD 1" " = 0" "int modulo int"
+ gdb_test "p 5 MOD 2" " = 1" "int modulo int"
+ gdb_test "p 5 MOD 3" " = 2" "int modulo int"
+ gdb_test "p 5 MOD 4" " = 1" "int modulo int"
+ gdb_test "p 5 MOD 5" " = 0" "int modulo int"
+ gdb_test "p 0 MOD 1" " = 0" "int modulo int"
+ gdb_test "p 0 MOD 2" " = 0" "int modulo int"
+ gdb_test "p 0 MOD 3" " = 0" "int modulo int"
+ gdb_test "p 0 MOD 4" " = 0" "int modulo int"
+ gdb_test "p -5 MOD 1" " = 0" "int modulo int"
+ gdb_test "p -5 MOD 2" " = 1" "int modulo int"
+ gdb_test "p -5 MOD 3" " = 1" "int modulo int"
+ gdb_test "p -5 MOD 4" " = 3" "int modulo int"
+ gdb_test "p -5 MOD 5" " = 0" "int modulo int"
+ gdb_test "p -5 MOD 5" " = 0" "int modulo int"
+ test_print_reject "p 6.0 MOD 3" \
+ "Integer-only operation on floating point number.*"
+ test_print_reject "p 6.0 MOD 3.0" \
+ "Integer-only operation on floating point number.*"
+ test_print_reject "p -5 MOD -1" \
+ "Second operand of MOD must be greater than zero.*"
+ test_print_reject "p -5 MOD 0" \
+ "Second operand of MOD must be greater than zero.*"
+
+ # Test remainder with various operands
+
+ gdb_test "p TRUE REM 1" " = 0" "bool remainder int"
+ gdb_test "p 'a' REM 2" " = 1" "char remainder int"
+ gdb_test "p 5 REM 5" " = 0" "int remainder int"
+ gdb_test "p 5 REM 4" " = 1" "int remainder int"
+ gdb_test "p 5 REM 3" " = 2" "int remainder int"
+ gdb_test "p 5 REM 2" " = 1" "int remainder int"
+ gdb_test "p 5 REM 1" " = 0" "int remainder int"
+ gdb_test "p 5 REM -1" " = 0" "int remainder int"
+ gdb_test "p 5 REM -2" " = 1" "int remainder int"
+ gdb_test "p 5 REM -3" " = 2" "int remainder int"
+ gdb_test "p 5 REM -4" " = 1" "int remainder int"
+ gdb_test "p 5 REM -5" " = 0" "int remainder int"
+ gdb_test "p -5 REM 5" " = 0" "int remainder int"
+ gdb_test "p -5 REM 4" " = -1" "int remainder int"
+ gdb_test "p -5 REM 3" " = -2" "int remainder int"
+ gdb_test "p -5 REM 2" " = -1" "int remainder int"
+ gdb_test "p -5 REM 1" " = 0" "int remainder int"
+ gdb_test "p -5 REM -1" " = 0" "int remainder int"
+ gdb_test "p -5 REM -2" " = -1" "int remainder int"
+ gdb_test "p -5 REM -3" " = -2" "int remainder int"
+ gdb_test "p -5 REM -4" " = -1" "int remainder int"
+ gdb_test "p -5 REM -5" " = 0" "int remainder int"
+ gdb_test "p 6 REM 3" " = 0" "int remainder int"
+ test_print_reject "p 6.0 REM 3" \
+ "Integer-only operation on floating point number.*"
+ test_print_reject "p 6.0 REM 3.0" \
+ "Integer-only operation on floating point number.*"
+}
+
+# Start with a fresh gdb.
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+
+gdb_test "set print sevenbit-strings" ""
+
+if [set_lang_chill] then {
+ test_value_history
+ test_convenience_variables
+ test_integer_literals_accepted
+ test_integer_literals_rejected
+ test_boolean_literals_accepted
+ test_character_literals_accepted
+ test_float_literals_accepted
+ test_arithmetic_expressions
+} else {
+ warning "$test_name tests suppressed." 0
+}
diff --git a/gdb/testsuite/gdb.chill/chillvars.ch b/gdb/testsuite/gdb.chill/chillvars.ch
new file mode 100644
index 00000000000..21dfcba5486
--- /dev/null
+++ b/gdb/testsuite/gdb.chill/chillvars.ch
@@ -0,0 +1,204 @@
+testvars: MODULE
+
+DCL bool_true BOOL INIT := TRUE;
+DCL bool_false BOOL INIT := FALSE;
+DCL booltable1 ARRAY (0:3) BOOL INIT := [ TRUE, FALSE, FALSE, TRUE ];
+DCL booltable2 ARRAY (4:7) BOOL INIT := [ TRUE, FALSE, FALSE, TRUE ];
+
+DCL control_char CHAR INIT := C'07';
+DCL printable_char CHAR INIT := 'a';
+DCL chartable1 ARRAY (0:2) CHAR INIT := [ C'00', C'01', C'02' ];
+DCL chartable2 ARRAY (3:5) CHAR INIT := [ C'00', C'01', C'02' ];
+
+DCL string1 CHARS (4) INIT := 'abcd';
+DCL string2 CHARS (5) INIT := 'ef' // C'00' // 'gh';
+DCL string3 CHARS (6) INIT := 'ef' // 'gh' // 'ij';
+DCL string4 CHARS (7) INIT := (6) 'z' // C'00';
+
+DCL byte_low BYTE INIT := -128;
+DCL byte_high BYTE INIT := 127;
+DCL bytetable1 ARRAY (0:4) BYTE INIT := [ -2, -1, 0, 1, 2 ];
+DCL bytetable2 ARRAY (5:9) BYTE INIT := [ -2, -1, 0, 1, 2 ];
+DCL bytetable3 ARRAY (1:2,'c':'d',FALSE:TRUE) BYTE
+ INIT := [ [ [ 0, 1 ], [ 2, 3 ] ], [ [ 4, 5 ], [ 6, 7 ] ] ];
+DCL bytetable4 ARRAY (1:2) ARRAY ('c':'d') ARRAY (FALSE:TRUE) BYTE
+ INIT := [ [ [ 0, 1 ], [ 2, 3 ] ], [ [ 4, 5 ], [ 6, 7 ] ] ];
+
+DCL ubyte_low UBYTE INIT := 0;
+DCL ubyte_high UBYTE INIT := 255;
+DCL ubytetable1 ARRAY (0:4) UBYTE INIT := [ 0, 1, 2, 3, 4 ];
+DCL ubytetable2 ARRAY (5:9) UBYTE INIT := [ 0, 1, 2, 3, 4 ];
+
+DCL int_low INT INIT := -32_768;
+DCL int_high INT INIT := 32_767;
+DCL inttable1 ARRAY (0:4) INT INIT := [ -2, -1, 0, 1, 2 ];
+DCL inttable2 ARRAY (5:9) INT INIT := [ -2, -1, 0, 1, 2 ];
+
+DCL uint_low UINT INIT := 0;
+DCL uint_high UINT INIT := 65_535;
+DCL uinttable1 ARRAY (0:4) UINT INIT := [ 0, 1, 2, 3, 4 ];
+DCL uinttable2 ARRAY (5:9) UINT INIT := [ 0, 1, 2, 3, 4 ];
+
+DCL long_low LONG INIT := -2_147_483_648;
+DCL long_high LONG INIT := 2_147_483_647;
+DCL longtable1 ARRAY (0:4) LONG INIT := [ -2, -1, 0, 1, 2 ];
+DCL longtable2 ARRAY (5:9) LONG INIT := [ -2, -1, 0, 1, 2 ];
+
+DCL ulong_low ULONG INIT := 0;
+DCL ulong_high ULONG INIT := 4_294_967_295;
+DCL ulongtable1 ARRAY (0:4) ULONG INIT := [ 0, 1, 2, 3, 4 ];
+DCL ulongtable2 ARRAY (5:9) ULONG INIT := [ 0, 1, 2, 3, 4 ];
+
+DCL real1 FLOAT INIT := 3.14159265358;
+DCL real2 FLOAT INIT := -3.14159265358;
+DCL realtable1 ARRAY (0:4) FLOAT INIT := [ -2.0, -1.0, 0.0, 1.0, 2.0 ];
+DCL realtable2 ARRAY (5:9) FLOAT INIT := [ -2.0, -1.0, 0.0, 1.0, 2.0 ];
+
+DCL long_real1 DOUBLE INIT := 3.14e300;
+DCL long_real2 DOUBLE INIT := -3.14e-300;
+DCL longrealtable1 ARRAY (0:4) DOUBLE INIT := [ -2.0, -1.0, 0.0, 1.0, 2.0 ];
+DCL longrealtable2 ARRAY (5:9) DOUBLE INIT := [ -2.0, -1.0, 0.0, 1.0, 2.0 ];
+
+/* DCL powerset1 POWERSET INT(0:7);*/
+/* DCL chars1 CHAR (16) INIT := (16)'b'; */
+/* DCL bits1 BIT(20) := B'11111111000010101011'; */
+
+NEWMODE simple_struct = STRUCT (abool BOOL, aint INT, astring CHARS (8));
+DCL struct1 simple_struct := [ TRUE, 123, "a string" ];
+
+NEWMODE nested_struct = STRUCT (abool BOOL, nstruct simple_struct, aint INT);
+DCL struct2 nested_struct := [ TRUE, [ FALSE, 456, "deadbeef" ], 789 ];
+
+/* This table is used as a source for every ascii character. */
+
+DCL asciitable ARRAY (0:255) CHAR INIT := [
+ C'00', C'01', C'02', C'03', C'04', C'05', C'06', C'07',
+ C'08', C'09', C'0a', C'0b', C'0c', C'0d', C'0e', C'0f',
+ C'10', C'11', C'12', C'13', C'14', C'15', C'16', C'17',
+ C'18', C'19', C'1a', C'1b', C'1c', C'1d', C'1e', C'1f',
+ C'20', C'21', C'22', C'23', C'24', C'25', C'26', C'27',
+ C'28', C'29', C'2a', C'2b', C'2c', C'2d', C'2e', C'2f',
+ C'30', C'31', C'32', C'33', C'34', C'35', C'36', C'37',
+ C'38', C'39', C'3a', C'3b', C'3c', C'3d', C'3e', C'3f',
+ C'40', C'41', C'42', C'43', C'44', C'45', C'46', C'47',
+ C'48', C'49', C'4a', C'4b', C'4c', C'4d', C'4e', C'4f',
+ C'50', C'51', C'52', C'53', C'54', C'55', C'56', C'57',
+ C'58', C'59', C'5a', C'5b', C'5c', C'5d', C'5e', C'5f',
+ C'60', C'61', C'62', C'63', C'64', C'65', C'66', C'67',
+ C'68', C'69', C'6a', C'6b', C'6c', C'6d', C'6e', C'6f',
+ C'70', C'71', C'72', C'73', C'74', C'75', C'76', C'77',
+ C'78', C'79', C'7a', C'7b', C'7c', C'7d', C'7e', C'7f',
+ C'80', C'81', C'82', C'83', C'84', C'85', C'86', C'87',
+ C'88', C'89', C'8a', C'8b', C'8c', C'8d', C'8e', C'8f',
+ C'90', C'91', C'92', C'93', C'94', C'95', C'96', C'97',
+ C'98', C'99', C'9a', C'9b', C'9c', C'9d', C'9e', C'9f',
+ C'a0', C'a1', C'a2', C'a3', C'a4', C'a5', C'a6', C'a7',
+ C'a8', C'a9', C'aa', C'ab', C'ac', C'ad', C'ae', C'af',
+ C'b0', C'b1', C'b2', C'b3', C'b4', C'b5', C'b6', C'b7',
+ C'b8', C'b9', C'ba', C'bb', C'bc', C'bd', C'be', C'bf',
+ C'c0', C'c1', C'c2', C'c3', C'c4', C'c5', C'c6', C'c7',
+ C'c8', C'c9', C'ca', C'cb', C'cc', C'cd', C'ce', C'cf',
+ C'd0', C'd1', C'd2', C'd3', C'd4', C'd5', C'd6', C'd7',
+ C'd8', C'd9', C'da', C'db', C'dc', C'dd', C'de', C'df',
+ C'e0', C'e1', C'e2', C'e3', C'e4', C'e5', C'e6', C'e7',
+ C'e8', C'e9', C'ea', C'eb', C'ec', C'ed', C'ee', C'ef',
+ C'f0', C'f1', C'f2', C'f3', C'f4', C'f5', C'f6', C'f7',
+ C'f8', C'f9', C'fa', C'fb', C'fc', C'fd', C'fe', C'ff'
+];
+
+DCL charmatrix ARRAY (0:255) CHAR INIT := [
+ 'a','X','X','X','X','X','X','X','X','X','X','X','X','X','X','X',
+ 'a','a','X','X','X','X','X','X','X','X','X','X','X','X','X','X',
+ 'a','a','a','X','X','X','X','X','X','X','X','X','X','X','X','X',
+ 'a','a','a','a','X','X','X','X','X','X','X','X','X','X','X','X',
+ 'a','a','a','a','a','X','X','X','X','X','X','X','X','X','X','X',
+ 'a','a','a','a','a','a','X','X','X','X','X','X','X','X','X','X',
+ 'a','a','a','a','a','a','a','X','X','X','X','X','X','X','X','X',
+ 'a','a','a','a','a','a','a','a','X','X','X','X','X','X','X','X',
+ 'a','a','a','a','a','a','a','a','a','X','X','X','X','X','X','X',
+ 'a','a','a','a','a','a','a','a','a','a','X','X','X','X','X','X',
+ 'a','a','a','a','a','a','a','a','a','a','a','X','X','X','X','X',
+ 'a','a','a','a','a','a','a','a','a','a','a','a','X','X','X','X',
+ 'a','a','a','a','a','a','a','a','a','a','a','a','a','X','X','X',
+ 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','X','X',
+ 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','X',
+ 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a'
+];
+
+DCL xptr PTR INIT := ->int_high;
+
+booleans: PROC ();
+
+ DCL val1 BOOL := TRUE;
+ DCL val2 BOOL := FALSE;
+ DCL val3 BOOL := TRUE;
+
+ val1 := TRUE XOR TRUE;
+ val1 := TRUE XOR FALSE;
+ val1 := FALSE XOR TRUE;
+ val1 := FALSE XOR FALSE;
+ val1 := val2 XOR val3;
+
+ val1 := TRUE AND TRUE;
+ val1 := TRUE AND FALSE;
+ val1 := FALSE AND TRUE;
+ val1 := FALSE AND FALSE;
+ val1 := val2 AND val3;
+
+ val1 := TRUE ANDIF TRUE;
+ val1 := TRUE ANDIF FALSE;
+ val1 := FALSE ANDIF TRUE;
+ val1 := FALSE ANDIF FALSE;
+ val1 := val2 ANDIF val3;
+
+ val1 := TRUE OR TRUE;
+ val1 := TRUE OR FALSE;
+ val1 := FALSE OR TRUE;
+ val1 := FALSE OR FALSE;
+ val1 := val2 OR val3;
+
+-- val1 := NOT TRUE;
+-- val1 := NOT FALSE;
+-- val1 := NOT val2;
+-- val1 := NOT val3;
+
+END booleans;
+
+scalar_arithmetic: PROC ();
+
+ DCL val1 INT := 1;
+ DCL val2 INT := 2;
+ DCL val3 INT := 3;
+
+ val1 := -val2;
+ val1 := val2 + val3;
+ val1 := val2 - val3;
+ val1 := val2 * val3;
+ val1 := val2 / val3;
+ val1 := val2 MOD val3;
+ val1 := val2 REM val3;
+
+END scalar_arithmetic;
+
+write_arrays: PROC ();
+
+ inttable1(0) := 0;
+ inttable1(1) := 1;
+ inttable1(2) := 2;
+ inttable1(3) := 3;
+ inttable1(4) := 4;
+ inttable2(5) := 5;
+ inttable2(6) := 6;
+ inttable2(7) := 7;
+ inttable2(8) := 8;
+ inttable2(9) := 9;
+
+END write_arrays;
+
+uint_low := 0;
+
+scalar_arithmetic ();
+write_arrays ();
+booleans ();
+
+END;
diff --git a/gdb/testsuite/gdb.chill/chillvars.exp b/gdb/testsuite/gdb.chill/chillvars.exp
new file mode 100644
index 00000000000..f37c94dd62d
--- /dev/null
+++ b/gdb/testsuite/gdb.chill/chillvars.exp
@@ -0,0 +1,316 @@
+# Copyright (C) 1992, 1997 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file was written by Fred Fish. (fnf@cygnus.com)
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+if [skip_chill_tests] then { continue }
+
+set testfile "chillvars"
+set srcfile ${srcdir}/$subdir/${testfile}.ch
+set binfile ${objdir}/${subdir}/${testfile}.exe
+if { [compile "${srcfile} -g -o ${binfile} ${CHILL_RT0} ${CHILL_LIB}"] != "" } {
+ perror "Couldn't compile ${srcfile}"
+ return -1
+}
+
+proc do_tests {} {
+ global prms_id bug_id subdir objdir srcdir binfile gdb_prompt
+
+ set prms_id 0
+ set bug_id 0
+
+ # Start with a fresh gdb.
+
+ gdb_exit
+ gdb_start
+ gdb_reinitialize_dir $srcdir/$subdir
+ gdb_load $binfile
+
+ gdb_test "set language chill" ""
+
+ # This is needed (at least on SunOS4) to make sure the
+ # the symbol table is read.
+ gdb_test "break chillvars.ch:3" ""
+ gdb_test "delete 1" ""
+
+ gdb_test "set width 0" ""
+ gdb_test "set print sevenbit-strings" ""
+ gdb_test "set print address off" ""
+
+ test_BOOL
+ test_CHAR
+ test_BYTE
+ test_UBYTE
+ test_INT
+ test_UINT
+ test_LONG
+ test_ULONG
+ test_REAL
+ test_LONG_REAL
+ test_POWERSET
+ test_arrays
+ test_strings
+ test_structs
+
+ test_ptr
+}
+
+proc test_BOOL {} {
+
+ gdb_test "ptype bool_true" "type = (BOOL|bool)"
+ gdb_test "ptype bool_false" "type = (BOOL|bool)"
+ gdb_test "whatis bool_true" "type = (BOOL|bool)"
+ gdb_test "whatis bool_false" "type = (BOOL|bool)"
+ gdb_test "print bool_false" " = FALSE"
+ gdb_test "print bool_true" " = TRUE"
+
+}
+
+proc test_CHAR {} {
+ gdb_test "ptype control_char" "type = (CHAR|char)"
+ gdb_test "whatis control_char" "type = (CHAR|char)"
+ gdb_test "print control_char" { = '\^[(]7[)]'}
+ gdb_test "ptype printable_char" "type = (CHAR|char)"
+ gdb_test "whatis printable_char" "type = (CHAR|char)"
+ gdb_test "print printable_char" " = 'a'"
+
+ gdb_test "print lower(char)" { = '\^[(]0[)]'}
+ gdb_test "print upper(char)" { = '\^[(]255[)]'}
+}
+
+proc test_BYTE {} {
+ gdb_test "ptype byte_low" "type = (BYTE|byte)"
+ gdb_test "whatis byte_low" "type = (BYTE|byte)"
+ gdb_test "print byte_low" " = -128"
+ gdb_test "ptype byte_high" "type = (BYTE|byte)"
+ gdb_test "whatis byte_high" "type = (BYTE|byte)"
+ gdb_test "print byte_high" " = 127"
+
+ gdb_test "print lower(byte)" " = -128"
+ gdb_test "print upper(byte)" " = 127"
+ gdb_test "print lower(byte_high)" " = -128"
+ gdb_test "print upper(byte_high)" " = 127"
+}
+
+proc test_UBYTE {} {
+ gdb_test "ptype ubyte_low" "type = (UBYTE|ubyte)"
+ gdb_test "whatis ubyte_low" "type = (UBYTE|ubyte)"
+ gdb_test "print ubyte_low" " = 0"
+ gdb_test "ptype ubyte_high" "type = (UBYTE|ubyte)"
+ gdb_test "whatis ubyte_high" "type = (UBYTE|ubyte)"
+ gdb_test "print ubyte_high" " = 255"
+}
+
+proc test_INT {} {
+ gdb_test "ptype int_low" "type = (INT|int)"
+ gdb_test "whatis int_low" "type = (INT|int)"
+ gdb_test "print int_low" " = -32768"
+ gdb_test "ptype int_high" "type = (INT|int)"
+ gdb_test "whatis int_high" "type = (INT|int)"
+ gdb_test "print int_high" " = 32767"
+}
+
+proc test_UINT {} {
+ gdb_test "ptype uint_low" "type = (UINT|uint)"
+ gdb_test "whatis uint_low" "type = (UINT|uint)"
+ gdb_test "print uint_low" " = 0"
+ gdb_test "ptype uint_high" "type = (UINT|uint)"
+ gdb_test "whatis uint_high" "type = (UINT|uint)"
+ gdb_test "print uint_high" " = 65535"
+}
+
+proc test_LONG {} {
+ gdb_test "ptype long_low" "type = (LONG|long)"
+ gdb_test "whatis long_low" "type = (LONG|long)"
+ gdb_test "print long_low" " = -2147483648"
+ gdb_test "ptype long_high" "type = (LONG|long)"
+ gdb_test "whatis long_high" "type = (LONG|long)"
+ gdb_test "print long_high" " = 2147483647"
+}
+
+proc test_ULONG {} {
+ gdb_test "ptype ulong_low" "type = (ULONG|ulong)"
+ gdb_test "whatis ulong_low" "type = (ULONG|ulong)"
+ gdb_test "print ulong_low" " = 0"
+ gdb_test "ptype ulong_high" "type = (ULONG|ulong)"
+ gdb_test "whatis ulong_high" "type = (ULONG|ulong)"
+ gdb_test "print ulong_high" " = 4294967295"
+}
+
+proc test_REAL {} {
+ gdb_test "ptype real1" "type = (FLOAT|float)"
+ gdb_test "whatis real1" "type = (FLOAT|float)"
+ gdb_test "print real1" " = 3.14159274"
+}
+
+proc test_LONG_REAL {} {
+ gdb_test "ptype long_real1" "type = (DOUBLE|double)"
+ gdb_test "whatis long_real1" "type = (DOUBLE|double)"
+ gdb_test "print long_real1" " = 3\\.1400000000000001e\\+300"
+}
+
+proc test_POWERSET {} {
+}
+
+proc test_arrays {} {
+ gdb_test "ptype booltable1" "type = ARRAY \\(+0:3\\)+ (BOOL|bool)"
+ gdb_test_exact "print booltable1" \
+ { = [(0): TRUE, (1:2): FALSE, (3): TRUE]}
+
+ gdb_test "ptype booltable2" "type = ARRAY \\(+4:7\\)+ (BOOL|bool)"
+ gdb_test_exact "print booltable2" { = [(4): TRUE, (5:6): FALSE, (7): TRUE]}
+
+ gdb_test "ptype chartable1" "type = ARRAY \\(+0:2\\)+ (CHAR|char)"
+ gdb_test_exact "print chartable1" {= [(0): '^(0)', (1): '^(1)', (2): '^(2)']}
+
+ gdb_test "ptype chartable2" "type = ARRAY \\(+3:5\\)+ (CHAR|char)"
+ gdb_test_exact "print chartable2" \
+ {= [(3): '^(0)', (4): '^(1)', (5): '^(2)']}
+
+ gdb_test "ptype bytetable1" "type = ARRAY \\(+0:4\\)+ (BYTE|byte)"
+ gdb_test_exact "print bytetable1" \
+ {= [(0): -2, (1): -1, (2): 0, (3): 1, (4): 2]}
+
+ gdb_test "ptype bytetable2" "type = ARRAY \\(+5:9\\)+ (BYTE|byte)"
+ gdb_test_exact "print bytetable2" \
+ {= [(5): -2, (6): -1, (7): 0, (8): 1, (9): 2]}
+
+ gdb_test "ptype bytetable3" \
+ "type = ARRAY \\(1:2\\) ARRAY \\('c':'d'\\) ARRAY \\(FALSE:TRUE\\) (BYTE|byte)"
+ gdb_test_exact "print bytetable3" \
+ {= [(1): [('c'): [(FALSE): 0, (TRUE): 1], ('d'): [(FALSE): 2, (TRUE): 3]], (2): [('c'): [(FALSE): 4, (TRUE): 5], ('d'): [(FALSE): 6, (TRUE): 7]]]}
+ gdb_test "ptype bytetable4" \
+ "type = ARRAY \\(1:2\\) ARRAY \\('c':'d'\\) ARRAY \\(FALSE:TRUE\\) (BYTE|byte)"
+ gdb_test_exact "print bytetable4" \
+ {= [(1): [('c'): [(FALSE): 0, (TRUE): 1], ('d'): [(FALSE): 2, (TRUE): 3]], (2): [('c'): [(FALSE): 4, (TRUE): 5], ('d'): [(FALSE): 6, (TRUE): 7]]]}
+
+ gdb_test "ptype ubytetable1" "type = ARRAY \\(+0:4\\)+ (UBYTE|ubyte)"
+ gdb_test_exact "print ubytetable1" \
+ {= [(0): 0, (1): 1, (2): 2, (3): 3, (4): 4]}
+
+ gdb_test "ptype ubytetable2" "type = ARRAY \\(+5:9\\)+ (UBYTE|ubyte)"
+ gdb_test_exact "print ubytetable2" \
+ {= [(5): 0, (6): 1, (7): 2, (8): 3, (9): 4]}
+
+ gdb_test "ptype inttable1" "type = ARRAY \\(+0:4\\)+ (INT|int)"
+ gdb_test_exact "print inttable1" \
+ {= [(0): -2, (1): -1, (2): 0, (3): 1, (4): 2]}
+
+ gdb_test "ptype inttable2" "type = ARRAY \\(+5:9\\)+ (INT|int)"
+ gdb_test_exact "print inttable2" \
+ {= [(5): -2, (6): -1, (7): 0, (8): 1, (9): 2]}
+
+ gdb_test "ptype uinttable1" "type = ARRAY \\(+0:4\\)+ (UINT|uint)"
+ gdb_test_exact "print uinttable1" \
+ {= [(0): 0, (1): 1, (2): 2, (3): 3, (4): 4]}
+
+ gdb_test "ptype uinttable2" "type = ARRAY \\(+5:9\\)+ (UINT|uint)"
+ gdb_test_exact "print uinttable2" \
+ {= [(5): 0, (6): 1, (7): 2, (8): 3, (9): 4]}
+
+ gdb_test "ptype longtable1" "type = ARRAY \\(+0:4\\)+ (LONG|long)"
+ gdb_test_exact "print longtable1" \
+ {= [(0): -2, (1): -1, (2): 0, (3): 1, (4): 2]}
+
+ gdb_test "ptype longtable2" "type = ARRAY \\(+5:9\\)+ (LONG|long)"
+ gdb_test_exact "print longtable2" \
+ {= [(5): -2, (6): -1, (7): 0, (8): 1, (9): 2]}
+
+ gdb_test "ptype ulongtable1" "type = ARRAY \\(+0:4\\)+ (ULONG|ulong)"
+ gdb_test_exact "print ulongtable1" \
+ {= [(0): 0, (1): 1, (2): 2, (3): 3, (4): 4]}
+
+ gdb_test "ptype ulongtable2" "type = ARRAY \\(+5:9\\)+ (ULONG|ulong)"
+ gdb_test_exact "print ulongtable2" \
+ {= [(5): 0, (6): 1, (7): 2, (8): 3, (9): 4]}
+
+ gdb_test "ptype realtable1" "type = ARRAY \\(+0:4\\)+ (FLOAT|float)"
+ gdb_test_exact "print realtable1" \
+ {= [(0): -2, (1): -1, (2): 0, (3): 1, (4): 2]}
+
+ gdb_test "ptype realtable2" "type = ARRAY \\(+5:9\\)+ (FLOAT|float)"
+ gdb_test_exact "print realtable2" \
+ {= [(5): -2, (6): -1, (7): 0, (8): 1, (9): 2]}
+
+ gdb_test "ptype longrealtable1" "type = ARRAY \\(+0:4\\)+ (DOUBLE|double)"
+ gdb_test_exact "print longrealtable1" \
+ {= [(0): -2, (1): -1, (2): 0, (3): 1, (4): 2]}
+
+ gdb_test "ptype longrealtable2" "type = ARRAY \\(+5:9\\)+ (DOUBLE|double)"
+ gdb_test_exact "print longrealtable2" \
+ {= [(5): -2, (6): -1, (7): 0, (8): 1, (9): 2]}
+
+ gdb_test "print length(longrealtable2)" {= 5}
+ gdb_test "print lower(longrealtable2)" {= 5}
+ gdb_test "print upper(longrealtable2)" {= 9}
+}
+
+proc test_strings {} {
+
+ gdb_test "ptype string1" "type = CHARS \[(\]4\[)\]+"
+ gdb_test "print string1" " = \"abcd\""
+
+ gdb_test "ptype string2" "type = CHARS \[(\]+5\[)\]+"
+ gdb_test "print string2" { = \"ef\^\(0\)gh\"}
+
+ gdb_test "ptype string3" "type = CHARS \[(\]+6\[)\]+"
+ gdb_test "print string3" " = \"efghij\""
+
+ gdb_test "ptype string4" "type = CHARS \[(\]+7\[)\]+"
+ gdb_test "print string4" { = \"zzzzzz\^\(0\)\"}
+
+ # These tests require a running process, so run to one of the procs
+ # and then do the tests.
+
+ if [runto scalar_arithmetic] then {
+ gdb_test "ptype string1//string2" "type = CHARS \\(9\\)"
+ gdb_test "print string1//string2" { = \"abcdef\^\(0\)gh\"}
+ gdb_test_exact {ptype "a chill string"} {type = CHARS (14)}
+ gdb_test "print 'a chill string'" " = \"a chill string\""
+ gdb_test "print \"ef\"//c'00'//\"gh\"" { = \"ef\^\(0\)gh\"}
+ gdb_test "print string1 // \"efgh\"" " = \"abcdefgh\""
+ gdb_test "print (6) 'z'" " = \"zzzzzz\""
+ gdb_test "ptype (6) 'z'" "type = CHARS \[(\]+6\[)\]+"
+ gdb_test "print (1+2*3) 'x'" " = \"xxxxxxx\""
+ gdb_test "ptype (1+2*3) 'x'" "type = CHARS \[(\]+7\[)\]+"
+ }
+
+}
+
+proc test_structs {} {
+ gdb_test "ptype struct1" \
+ "type = STRUCT \\(+.*abool (BOOL|bool),.*aint (INT|int),.*astring CHARS \\(+8\\)+.*\\)+"
+ gdb_test "print struct1" \
+ ".* = \\\[\.abool: TRUE, \.aint: 123, \.astring: \"a string\"\\\]"
+ gdb_test "ptype struct2" \
+ "type = STRUCT \\(+.*abool (BOOL|bool),.*nstruct simple_struct,.*aint (INT|int).*\\)+"
+ gdb_test "print struct2" \
+ ".* = \\\[.abool: TRUE, \.nstruct: \\\[\.abool: FALSE, \.aint: 456, \.astring: \"deadbeef\"\\\], \.aint: 789\\\]"
+}
+
+proc test_ptr {} {
+ # This is to test Cygnus PR 6932
+ gdb_test "print xptr->int" ".* = 32767"
+}
+
+do_tests
diff --git a/gdb/testsuite/gdb.chill/configure b/gdb/testsuite/gdb.chill/configure
new file mode 100755
index 00000000000..24e429d9ce5
--- /dev/null
+++ b/gdb/testsuite/gdb.chill/configure
@@ -0,0 +1,899 @@
+#! /bin/sh
+
+# Guess values for system-dependent variables and create Makefiles.
+# Generated automatically using autoconf version 2.12.1
+# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc.
+#
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+
+# Defaults:
+ac_help=
+ac_default_prefix=/usr/local
+# Any additions from configure.in:
+
+# Initialize some variables set by options.
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+build=NONE
+cache_file=./config.cache
+exec_prefix=NONE
+host=NONE
+no_create=
+nonopt=NONE
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+target=NONE
+verbose=
+x_includes=NONE
+x_libraries=NONE
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datadir='${prefix}/share'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+libdir='${exec_prefix}/lib'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+infodir='${prefix}/info'
+mandir='${prefix}/man'
+
+# Initialize some other variables.
+subdirs=
+MFLAGS= MAKEFLAGS=
+SHELL=${CONFIG_SHELL-/bin/sh}
+# Maximum number of lines to put in a shell here document.
+ac_max_here_lines=12
+
+ac_prev=
+for ac_option
+do
+
+ # If the previous option needs an argument, assign it.
+ if test -n "$ac_prev"; then
+ eval "$ac_prev=\$ac_option"
+ ac_prev=
+ continue
+ fi
+
+ case "$ac_option" in
+ -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
+ *) ac_optarg= ;;
+ esac
+
+ # Accept the important Cygnus configure options, so we can diagnose typos.
+
+ case "$ac_option" in
+
+ -bindir | --bindir | --bindi | --bind | --bin | --bi)
+ ac_prev=bindir ;;
+ -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+ bindir="$ac_optarg" ;;
+
+ -build | --build | --buil | --bui | --bu)
+ ac_prev=build ;;
+ -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+ build="$ac_optarg" ;;
+
+ -cache-file | --cache-file | --cache-fil | --cache-fi \
+ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+ ac_prev=cache_file ;;
+ -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+ cache_file="$ac_optarg" ;;
+
+ -datadir | --datadir | --datadi | --datad | --data | --dat | --da)
+ ac_prev=datadir ;;
+ -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \
+ | --da=*)
+ datadir="$ac_optarg" ;;
+
+ -disable-* | --disable-*)
+ ac_feature=`echo $ac_option|sed -e 's/-*disable-//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then
+ { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
+ fi
+ ac_feature=`echo $ac_feature| sed 's/-/_/g'`
+ eval "enable_${ac_feature}=no" ;;
+
+ -enable-* | --enable-*)
+ ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then
+ { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
+ fi
+ ac_feature=`echo $ac_feature| sed 's/-/_/g'`
+ case "$ac_option" in
+ *=*) ;;
+ *) ac_optarg=yes ;;
+ esac
+ eval "enable_${ac_feature}='$ac_optarg'" ;;
+
+ -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+ | --exec | --exe | --ex)
+ ac_prev=exec_prefix ;;
+ -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+ | --exec=* | --exe=* | --ex=*)
+ exec_prefix="$ac_optarg" ;;
+
+ -gas | --gas | --ga | --g)
+ # Obsolete; use --with-gas.
+ with_gas=yes ;;
+
+ -help | --help | --hel | --he)
+ # Omit some internal or obsolete options to make the list less imposing.
+ # This message is too long to be a string in the A/UX 3.1 sh.
+ cat << EOF
+Usage: configure [options] [host]
+Options: [defaults in brackets after descriptions]
+Configuration:
+ --cache-file=FILE cache test results in FILE
+ --help print this message
+ --no-create do not create output files
+ --quiet, --silent do not print \`checking...' messages
+ --version print the version of autoconf that created configure
+Directory and file names:
+ --prefix=PREFIX install architecture-independent files in PREFIX
+ [$ac_default_prefix]
+ --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
+ [same as prefix]
+ --bindir=DIR user executables in DIR [EPREFIX/bin]
+ --sbindir=DIR system admin executables in DIR [EPREFIX/sbin]
+ --libexecdir=DIR program executables in DIR [EPREFIX/libexec]
+ --datadir=DIR read-only architecture-independent data in DIR
+ [PREFIX/share]
+ --sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc]
+ --sharedstatedir=DIR modifiable architecture-independent data in DIR
+ [PREFIX/com]
+ --localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var]
+ --libdir=DIR object code libraries in DIR [EPREFIX/lib]
+ --includedir=DIR C header files in DIR [PREFIX/include]
+ --oldincludedir=DIR C header files for non-gcc in DIR [/usr/include]
+ --infodir=DIR info documentation in DIR [PREFIX/info]
+ --mandir=DIR man documentation in DIR [PREFIX/man]
+ --srcdir=DIR find the sources in DIR [configure dir or ..]
+ --program-prefix=PREFIX prepend PREFIX to installed program names
+ --program-suffix=SUFFIX append SUFFIX to installed program names
+ --program-transform-name=PROGRAM
+ run sed PROGRAM on installed program names
+EOF
+ cat << EOF
+Host type:
+ --build=BUILD configure for building on BUILD [BUILD=HOST]
+ --host=HOST configure for HOST [guessed]
+ --target=TARGET configure for TARGET [TARGET=HOST]
+Features and packages:
+ --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
+ --enable-FEATURE[=ARG] include FEATURE [ARG=yes]
+ --with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
+ --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
+ --x-includes=DIR X include files are in DIR
+ --x-libraries=DIR X library files are in DIR
+EOF
+ if test -n "$ac_help"; then
+ echo "--enable and --with options recognized:$ac_help"
+ fi
+ exit 0 ;;
+
+ -host | --host | --hos | --ho)
+ ac_prev=host ;;
+ -host=* | --host=* | --hos=* | --ho=*)
+ host="$ac_optarg" ;;
+
+ -includedir | --includedir | --includedi | --included | --include \
+ | --includ | --inclu | --incl | --inc)
+ ac_prev=includedir ;;
+ -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+ | --includ=* | --inclu=* | --incl=* | --inc=*)
+ includedir="$ac_optarg" ;;
+
+ -infodir | --infodir | --infodi | --infod | --info | --inf)
+ ac_prev=infodir ;;
+ -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+ infodir="$ac_optarg" ;;
+
+ -libdir | --libdir | --libdi | --libd)
+ ac_prev=libdir ;;
+ -libdir=* | --libdir=* | --libdi=* | --libd=*)
+ libdir="$ac_optarg" ;;
+
+ -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+ | --libexe | --libex | --libe)
+ ac_prev=libexecdir ;;
+ -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+ | --libexe=* | --libex=* | --libe=*)
+ libexecdir="$ac_optarg" ;;
+
+ -localstatedir | --localstatedir | --localstatedi | --localstated \
+ | --localstate | --localstat | --localsta | --localst \
+ | --locals | --local | --loca | --loc | --lo)
+ ac_prev=localstatedir ;;
+ -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+ | --localstate=* | --localstat=* | --localsta=* | --localst=* \
+ | --locals=* | --local=* | --loca=* | --loc=* | --lo=*)
+ localstatedir="$ac_optarg" ;;
+
+ -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+ ac_prev=mandir ;;
+ -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+ mandir="$ac_optarg" ;;
+
+ -nfp | --nfp | --nf)
+ # Obsolete; use --without-fp.
+ with_fp=no ;;
+
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c)
+ no_create=yes ;;
+
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+ no_recursion=yes ;;
+
+ -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+ | --oldin | --oldi | --old | --ol | --o)
+ ac_prev=oldincludedir ;;
+ -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+ oldincludedir="$ac_optarg" ;;
+
+ -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+ ac_prev=prefix ;;
+ -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+ prefix="$ac_optarg" ;;
+
+ -program-prefix | --program-prefix | --program-prefi | --program-pref \
+ | --program-pre | --program-pr | --program-p)
+ ac_prev=program_prefix ;;
+ -program-prefix=* | --program-prefix=* | --program-prefi=* \
+ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+ program_prefix="$ac_optarg" ;;
+
+ -program-suffix | --program-suffix | --program-suffi | --program-suff \
+ | --program-suf | --program-su | --program-s)
+ ac_prev=program_suffix ;;
+ -program-suffix=* | --program-suffix=* | --program-suffi=* \
+ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+ program_suffix="$ac_optarg" ;;
+
+ -program-transform-name | --program-transform-name \
+ | --program-transform-nam | --program-transform-na \
+ | --program-transform-n | --program-transform- \
+ | --program-transform | --program-transfor \
+ | --program-transfo | --program-transf \
+ | --program-trans | --program-tran \
+ | --progr-tra | --program-tr | --program-t)
+ ac_prev=program_transform_name ;;
+ -program-transform-name=* | --program-transform-name=* \
+ | --program-transform-nam=* | --program-transform-na=* \
+ | --program-transform-n=* | --program-transform-=* \
+ | --program-transform=* | --program-transfor=* \
+ | --program-transfo=* | --program-transf=* \
+ | --program-trans=* | --program-tran=* \
+ | --progr-tra=* | --program-tr=* | --program-t=*)
+ program_transform_name="$ac_optarg" ;;
+
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ silent=yes ;;
+
+ -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+ ac_prev=sbindir ;;
+ -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+ | --sbi=* | --sb=*)
+ sbindir="$ac_optarg" ;;
+
+ -sharedstatedir | --sharedstatedir | --sharedstatedi \
+ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+ | --sharedst | --shareds | --shared | --share | --shar \
+ | --sha | --sh)
+ ac_prev=sharedstatedir ;;
+ -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+ | --sha=* | --sh=*)
+ sharedstatedir="$ac_optarg" ;;
+
+ -site | --site | --sit)
+ ac_prev=site ;;
+ -site=* | --site=* | --sit=*)
+ site="$ac_optarg" ;;
+
+ -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+ ac_prev=srcdir ;;
+ -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+ srcdir="$ac_optarg" ;;
+
+ -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+ | --syscon | --sysco | --sysc | --sys | --sy)
+ ac_prev=sysconfdir ;;
+ -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+ sysconfdir="$ac_optarg" ;;
+
+ -target | --target | --targe | --targ | --tar | --ta | --t)
+ ac_prev=target ;;
+ -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+ target="$ac_optarg" ;;
+
+ -v | -verbose | --verbose | --verbos | --verbo | --verb)
+ verbose=yes ;;
+
+ -version | --version | --versio | --versi | --vers)
+ echo "configure generated by autoconf version 2.12.1"
+ exit 0 ;;
+
+ -with-* | --with-*)
+ ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then
+ { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
+ fi
+ ac_package=`echo $ac_package| sed 's/-/_/g'`
+ case "$ac_option" in
+ *=*) ;;
+ *) ac_optarg=yes ;;
+ esac
+ eval "with_${ac_package}='$ac_optarg'" ;;
+
+ -without-* | --without-*)
+ ac_package=`echo $ac_option|sed -e 's/-*without-//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then
+ { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
+ fi
+ ac_package=`echo $ac_package| sed 's/-/_/g'`
+ eval "with_${ac_package}=no" ;;
+
+ --x)
+ # Obsolete; use --with-x.
+ with_x=yes ;;
+
+ -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+ | --x-incl | --x-inc | --x-in | --x-i)
+ ac_prev=x_includes ;;
+ -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+ x_includes="$ac_optarg" ;;
+
+ -x-libraries | --x-libraries | --x-librarie | --x-librari \
+ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+ ac_prev=x_libraries ;;
+ -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+ x_libraries="$ac_optarg" ;;
+
+ -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; }
+ ;;
+
+ *)
+ if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then
+ echo "configure: warning: $ac_option: invalid host type" 1>&2
+ fi
+ if test "x$nonopt" != xNONE; then
+ { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; }
+ fi
+ nonopt="$ac_option"
+ ;;
+
+ esac
+done
+
+if test -n "$ac_prev"; then
+ { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; }
+fi
+
+trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
+
+# File descriptor usage:
+# 0 standard input
+# 1 file creation
+# 2 errors and warnings
+# 3 some systems may open it to /dev/tty
+# 4 used on the Kubota Titan
+# 6 checking for... messages and results
+# 5 compiler messages saved in config.log
+if test "$silent" = yes; then
+ exec 6>/dev/null
+else
+ exec 6>&1
+fi
+exec 5>./config.log
+
+echo "\
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+" 1>&5
+
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Also quote any args containing shell metacharacters.
+ac_configure_args=
+for ac_arg
+do
+ case "$ac_arg" in
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c) ;;
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;;
+ *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*)
+ ac_configure_args="$ac_configure_args '$ac_arg'" ;;
+ *) ac_configure_args="$ac_configure_args $ac_arg" ;;
+ esac
+done
+
+# NLS nuisances.
+# Only set these to C if already set. These must not be set unconditionally
+# because not all systems understand e.g. LANG=C (notably SCO).
+# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'!
+# Non-C LC_CTYPE values break the ctype check.
+if test "${LANG+set}" = set; then LANG=C; export LANG; fi
+if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi
+if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi
+if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -rf conftest* confdefs.h
+# AIX cpp loses on an empty file, so make sure it contains at least a newline.
+echo > confdefs.h
+
+# A filename unique to this package, relative to the directory that
+# configure is in, which we can look for to find out if srcdir is correct.
+ac_unique_file=chexp.exp
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+ ac_srcdir_defaulted=yes
+ # Try the directory containing this script, then its parent.
+ ac_prog=$0
+ ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'`
+ test "x$ac_confdir" = "x$ac_prog" && ac_confdir=.
+ srcdir=$ac_confdir
+ if test ! -r $srcdir/$ac_unique_file; then
+ srcdir=..
+ fi
+else
+ ac_srcdir_defaulted=no
+fi
+if test ! -r $srcdir/$ac_unique_file; then
+ if test "$ac_srcdir_defaulted" = yes; then
+ { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; }
+ else
+ { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; }
+ fi
+fi
+srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'`
+
+# Prefer explicitly selected file to automatically selected ones.
+if test -z "$CONFIG_SITE"; then
+ if test "x$prefix" != xNONE; then
+ CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site"
+ else
+ CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
+ fi
+fi
+for ac_site_file in $CONFIG_SITE; do
+ if test -r "$ac_site_file"; then
+ echo "loading site script $ac_site_file"
+ . "$ac_site_file"
+ fi
+done
+
+if test -r "$cache_file"; then
+ echo "loading cache $cache_file"
+ . $cache_file
+else
+ echo "creating cache $cache_file"
+ > $cache_file
+fi
+
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then
+ # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu.
+ if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then
+ ac_n= ac_c='
+' ac_t=' '
+ else
+ ac_n=-n ac_c= ac_t=
+ fi
+else
+ ac_n= ac_c='\c' ac_t=
+fi
+
+
+
+CC=${CC-cc}
+
+ac_aux_dir=
+for ac_dir in `cd $srcdir;pwd`/../../.. $srcdir/`cd $srcdir;pwd`/../../..; do
+ if test -f $ac_dir/install-sh; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install-sh -c"
+ break
+ elif test -f $ac_dir/install.sh; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install.sh -c"
+ break
+ fi
+done
+if test -z "$ac_aux_dir"; then
+ { echo "configure: error: can not find install-sh or install.sh in `cd $srcdir;pwd`/../../.. $srcdir/`cd $srcdir;pwd`/../../.." 1>&2; exit 1; }
+fi
+ac_config_guess=$ac_aux_dir/config.guess
+ac_config_sub=$ac_aux_dir/config.sub
+ac_configure=$ac_aux_dir/configure # This should be Cygnus configure.
+
+
+# Do some error checking and defaulting for the host and target type.
+# The inputs are:
+# configure --host=HOST --target=TARGET --build=BUILD NONOPT
+#
+# The rules are:
+# 1. You are not allowed to specify --host, --target, and nonopt at the
+# same time.
+# 2. Host defaults to nonopt.
+# 3. If nonopt is not specified, then host defaults to the current host,
+# as determined by config.guess.
+# 4. Target and build default to nonopt.
+# 5. If nonopt is not specified, then target and build default to host.
+
+# The aliases save the names the user supplied, while $host etc.
+# will get canonicalized.
+case $host---$target---$nonopt in
+NONE---*---* | *---NONE---* | *---*---NONE) ;;
+*) { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; } ;;
+esac
+
+
+# Make sure we can run config.sub.
+if ${CONFIG_SHELL-/bin/sh} $ac_config_sub sun4 >/dev/null 2>&1; then :
+else { echo "configure: error: can not run $ac_config_sub" 1>&2; exit 1; }
+fi
+
+echo $ac_n "checking host system type""... $ac_c" 1>&6
+echo "configure:573: checking host system type" >&5
+
+host_alias=$host
+case "$host_alias" in
+NONE)
+ case $nonopt in
+ NONE)
+ if host_alias=`${CONFIG_SHELL-/bin/sh} $ac_config_guess`; then :
+ else { echo "configure: error: can not guess host type; you must specify one" 1>&2; exit 1; }
+ fi ;;
+ *) host_alias=$nonopt ;;
+ esac ;;
+esac
+
+host=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $host_alias`
+host_cpu=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+host_vendor=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+host_os=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+echo "$ac_t""$host" 1>&6
+
+echo $ac_n "checking target system type""... $ac_c" 1>&6
+echo "configure:594: checking target system type" >&5
+
+target_alias=$target
+case "$target_alias" in
+NONE)
+ case $nonopt in
+ NONE) target_alias=$host_alias ;;
+ *) target_alias=$nonopt ;;
+ esac ;;
+esac
+
+target=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $target_alias`
+target_cpu=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+target_vendor=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+target_os=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+echo "$ac_t""$target" 1>&6
+
+echo $ac_n "checking build system type""... $ac_c" 1>&6
+echo "configure:612: checking build system type" >&5
+
+build_alias=$build
+case "$build_alias" in
+NONE)
+ case $nonopt in
+ NONE) build_alias=$host_alias ;;
+ *) build_alias=$nonopt ;;
+ esac ;;
+esac
+
+build=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $build_alias`
+build_cpu=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+build_vendor=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+build_os=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+echo "$ac_t""$build" 1>&6
+
+test "$host_alias" != "$target_alias" &&
+ test "$program_prefix$program_suffix$program_transform_name" = \
+ NONENONEs,x,x, &&
+ program_prefix=${target_alias}-
+
+
+trap '' 1 2 15
+cat > confcache <<\EOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs. It is not useful on other systems.
+# If it contains results you don't want to keep, you may remove or edit it.
+#
+# By default, configure uses ./config.cache as the cache file,
+# creating it if it does not exist already. You can give configure
+# the --cache-file=FILE option to use a different cache file; that is
+# what configure does when it calls configure scripts in
+# subdirectories, so they share the cache.
+# Giving --cache-file=/dev/null disables caching, for debugging configure.
+# config.status only pays attention to the cache file if you give it the
+# --recheck option to rerun configure.
+#
+EOF
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, don't put newlines in cache variables' values.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(set) 2>&1 |
+ case `(ac_space=' '; set) 2>&1 | grep ac_space` in
+ *ac_space=\ *)
+ # `set' does not quote correctly, so add quotes (double-quote substitution
+ # turns \\\\ into \\, and sed turns \\ into \).
+ sed -n \
+ -e "s/'/'\\\\''/g" \
+ -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p"
+ ;;
+ *)
+ # `set' quotes correctly as required by POSIX, so do not add quotes.
+ sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p'
+ ;;
+ esac >> confcache
+if cmp -s $cache_file confcache; then
+ :
+else
+ if test -w $cache_file; then
+ echo "updating cache $cache_file"
+ cat confcache > $cache_file
+ else
+ echo "not updating unwritable cache $cache_file"
+ fi
+fi
+rm -f confcache
+
+trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+# Any assignment to VPATH causes Sun make to only execute
+# the first set of double-colon rules, so remove it if not needed.
+# If there is a colon in the path, we need to keep it.
+if test "x$srcdir" = x.; then
+ ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d'
+fi
+
+trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15
+
+# Transform confdefs.h into DEFS.
+# Protect against shell expansion while executing Makefile rules.
+# Protect against Makefile macro expansion.
+cat > conftest.defs <<\EOF
+s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%-D\1=\2%g
+s%[ `~#$^&*(){}\\|;'"<>?]%\\&%g
+s%\[%\\&%g
+s%\]%\\&%g
+s%\$%$$%g
+EOF
+DEFS=`sed -f conftest.defs confdefs.h | tr '\012' ' '`
+rm -f conftest.defs
+
+
+# Without the "./", some shells look in PATH for config.status.
+: ${CONFIG_STATUS=./config.status}
+
+echo creating $CONFIG_STATUS
+rm -f $CONFIG_STATUS
+cat > $CONFIG_STATUS <<EOF
+#! /bin/sh
+# Generated automatically by configure.
+# Run this file to recreate the current configuration.
+# This directory was configured as follows,
+# on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+#
+# $0 $ac_configure_args
+#
+# Compiler output produced by configure, useful for debugging
+# configure, is in ./config.log if it exists.
+
+ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]"
+for ac_option
+do
+ case "\$ac_option" in
+ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+ echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion"
+ exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;;
+ -version | --version | --versio | --versi | --vers | --ver | --ve | --v)
+ echo "$CONFIG_STATUS generated by autoconf version 2.12.1"
+ exit 0 ;;
+ -help | --help | --hel | --he | --h)
+ echo "\$ac_cs_usage"; exit 0 ;;
+ *) echo "\$ac_cs_usage"; exit 1 ;;
+ esac
+done
+
+ac_given_srcdir=$srcdir
+
+trap 'rm -fr `echo "Makefile" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15
+EOF
+cat >> $CONFIG_STATUS <<EOF
+
+# Protect against being on the right side of a sed subst in config.status.
+sed 's/%@/@@/; s/@%/@@/; s/%g\$/@g/; /@g\$/s/[\\\\&%]/\\\\&/g;
+ s/@@/%@/; s/@@/@%/; s/@g\$/%g/' > conftest.subs <<\\CEOF
+$ac_vpsub
+$extrasub
+s%@SHELL@%$SHELL%g
+s%@CFLAGS@%$CFLAGS%g
+s%@CPPFLAGS@%$CPPFLAGS%g
+s%@CXXFLAGS@%$CXXFLAGS%g
+s%@DEFS@%$DEFS%g
+s%@LDFLAGS@%$LDFLAGS%g
+s%@LIBS@%$LIBS%g
+s%@exec_prefix@%$exec_prefix%g
+s%@prefix@%$prefix%g
+s%@program_transform_name@%$program_transform_name%g
+s%@bindir@%$bindir%g
+s%@sbindir@%$sbindir%g
+s%@libexecdir@%$libexecdir%g
+s%@datadir@%$datadir%g
+s%@sysconfdir@%$sysconfdir%g
+s%@sharedstatedir@%$sharedstatedir%g
+s%@localstatedir@%$localstatedir%g
+s%@libdir@%$libdir%g
+s%@includedir@%$includedir%g
+s%@oldincludedir@%$oldincludedir%g
+s%@infodir@%$infodir%g
+s%@mandir@%$mandir%g
+s%@CC@%$CC%g
+s%@host@%$host%g
+s%@host_alias@%$host_alias%g
+s%@host_cpu@%$host_cpu%g
+s%@host_vendor@%$host_vendor%g
+s%@host_os@%$host_os%g
+s%@target@%$target%g
+s%@target_alias@%$target_alias%g
+s%@target_cpu@%$target_cpu%g
+s%@target_vendor@%$target_vendor%g
+s%@target_os@%$target_os%g
+s%@build@%$build%g
+s%@build_alias@%$build_alias%g
+s%@build_cpu@%$build_cpu%g
+s%@build_vendor@%$build_vendor%g
+s%@build_os@%$build_os%g
+
+CEOF
+EOF
+
+cat >> $CONFIG_STATUS <<\EOF
+
+# Split the substitutions into bite-sized pieces for seds with
+# small command number limits, like on Digital OSF/1 and HP-UX.
+ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script.
+ac_file=1 # Number of current file.
+ac_beg=1 # First line for current file.
+ac_end=$ac_max_sed_cmds # Line after last line for current file.
+ac_more_lines=:
+ac_sed_cmds=""
+while $ac_more_lines; do
+ if test $ac_beg -gt 1; then
+ sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file
+ else
+ sed "${ac_end}q" conftest.subs > conftest.s$ac_file
+ fi
+ if test ! -s conftest.s$ac_file; then
+ ac_more_lines=false
+ rm -f conftest.s$ac_file
+ else
+ if test -z "$ac_sed_cmds"; then
+ ac_sed_cmds="sed -f conftest.s$ac_file"
+ else
+ ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file"
+ fi
+ ac_file=`expr $ac_file + 1`
+ ac_beg=$ac_end
+ ac_end=`expr $ac_end + $ac_max_sed_cmds`
+ fi
+done
+if test -z "$ac_sed_cmds"; then
+ ac_sed_cmds=cat
+fi
+EOF
+
+cat >> $CONFIG_STATUS <<EOF
+
+CONFIG_FILES=\${CONFIG_FILES-"Makefile"}
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then
+ # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+ case "$ac_file" in
+ *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'`
+ ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
+ *) ac_file_in="${ac_file}.in" ;;
+ esac
+
+ # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories.
+
+ # Remove last slash and all that follows it. Not all systems have dirname.
+ ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
+ if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
+ # The file is in a subdirectory.
+ test ! -d "$ac_dir" && mkdir "$ac_dir"
+ ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`"
+ # A "../" for each directory in $ac_dir_suffix.
+ ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'`
+ else
+ ac_dir_suffix= ac_dots=
+ fi
+
+ case "$ac_given_srcdir" in
+ .) srcdir=.
+ if test -z "$ac_dots"; then top_srcdir=.
+ else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;;
+ /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;;
+ *) # Relative path.
+ srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix"
+ top_srcdir="$ac_dots$ac_given_srcdir" ;;
+ esac
+
+
+ echo creating "$ac_file"
+ rm -f "$ac_file"
+ configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure."
+ case "$ac_file" in
+ *Makefile*) ac_comsub="1i\\
+# $configure_input" ;;
+ *) ac_comsub= ;;
+ esac
+
+ ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"`
+ sed -e "$ac_comsub
+s%@configure_input@%$configure_input%g
+s%@srcdir@%$srcdir%g
+s%@top_srcdir@%$top_srcdir%g
+" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file
+fi; done
+rm -f conftest.s*
+
+EOF
+cat >> $CONFIG_STATUS <<EOF
+
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+
+exit 0
+EOF
+chmod +x $CONFIG_STATUS
+rm -fr confdefs* $ac_clean_files
+test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1
+
diff --git a/gdb/testsuite/gdb.chill/configure.in b/gdb/testsuite/gdb.chill/configure.in
new file mode 100644
index 00000000000..3eed026de42
--- /dev/null
+++ b/gdb/testsuite/gdb.chill/configure.in
@@ -0,0 +1,11 @@
+dnl Process this file file with autoconf to produce a configure script.
+
+AC_PREREQ(2.5)
+AC_INIT(chexp.exp)
+
+CC=${CC-cc}
+AC_SUBST(CC)
+AC_CONFIG_AUX_DIR(`cd $srcdir;pwd`/../../..)
+AC_CANONICAL_SYSTEM
+
+AC_OUTPUT(Makefile)
diff --git a/gdb/testsuite/gdb.chill/enum.ch b/gdb/testsuite/gdb.chill/enum.ch
new file mode 100644
index 00000000000..971fc9421a5
--- /dev/null
+++ b/gdb/testsuite/gdb.chill/enum.ch
@@ -0,0 +1,9 @@
+hugo: module
+
+ synmode m_set = set (a, b, c, d, e, f, g, h, i);
+ dcl x long;
+ dcl y m_set;
+
+ writetext (stdout, "done.%/");
+
+end hugo;
diff --git a/gdb/testsuite/gdb.chill/enum.exp b/gdb/testsuite/gdb.chill/enum.exp
new file mode 100644
index 00000000000..74fee35bcd9
--- /dev/null
+++ b/gdb/testsuite/gdb.chill/enum.exp
@@ -0,0 +1,85 @@
+# Copyright (C) 1995, 1997 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file was written by Wilfried Moser (moser@aut.alcatel.at
+#
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+if [skip_chill_tests] then { continue }
+
+set testfile "enum"
+set srcfile ${srcdir}/$subdir/${testfile}.ch
+set binfile ${objdir}/${subdir}/${testfile}.exe
+if { [compile "${srcfile} -g -o ${binfile} ${CHILL_RT0} ${CHILL_LIB}"] != "" } {
+ perror "Couldn't compile ${srcfile}"
+ return -1
+}
+
+# Set the current language to chill. This counts as a test. If it
+# fails, then we skip the other tests.
+
+proc set_lang_chill {} {
+ global gdb_prompt
+ global binfile objdir subdir
+
+ verbose "loading file '$binfile'"
+ gdb_load $binfile
+
+ send_gdb "set language chill\n"
+ gdb_expect {
+ -re ".*$gdb_prompt $" {}
+ timeout { fail "set language chill (timeout)" ; return 0 }
+ }
+
+ return [gdb_test "show language" ".* source language is \"chill\".*" \
+ "set language to \"chill\""]
+}
+
+set prms_id 0
+set bug_id 0
+
+# Start with a fresh gdb.
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+
+gdb_test "set print sevenbit-strings" ".*"
+
+if ![set_lang_chill] then {
+ runto hugo_
+
+ send_gdb "set var \$i := d\n"
+ gdb_expect -re ".*$gdb_prompt $"
+ gdb_test "print \$i" { = d}
+ gdb_test "print size (\$i)" { = 1}
+ gdb_test "print b+c" { = 3}
+ gdb_test "print c*d" { = 6}
+ gdb_test "print a<b" { = TRUE}
+ gdb_test "print a=b" { = FALSE}
+ gdb_test "print a=a" { = TRUE}
+ gdb_test "print a/=\$i" { = TRUE}
+
+# This is PR 8870
+ gdb_test "break malloc" ".*"
+ gdb_test {set var $j := m_set[b]} ".*invalid.*tuple.*"
+}
diff --git a/gdb/testsuite/gdb.chill/extstruct-grt.ch b/gdb/testsuite/gdb.chill/extstruct-grt.ch
new file mode 100644
index 00000000000..abd0d5ee3e4
--- /dev/null
+++ b/gdb/testsuite/gdb.chill/extstruct-grt.ch
@@ -0,0 +1,12 @@
+pot1: MODULE
+
+SYNMODE m_array1 = ARRAY (2:3) ulong;
+SYNMODE m_struct = STRUCT (f1 int,
+ f2 REF m_array1,
+ f3 m_array1);
+SYNMODE m_array3 = ARRAY (5:6) m_struct;
+SYNMODE m_array4 = ARRAY (7:8) ARRAY (9:10) m_struct;
+
+GRANT all;
+
+END pot1;
diff --git a/gdb/testsuite/gdb.chill/extstruct.ch b/gdb/testsuite/gdb.chill/extstruct.ch
new file mode 100644
index 00000000000..649f60948ed
--- /dev/null
+++ b/gdb/testsuite/gdb.chill/extstruct.ch
@@ -0,0 +1,16 @@
+pottendo: MODULE
+
+<> USE_SEIZE_FILE "extstruct-grt.grt" <>
+SEIZE m_array3;
+SEIZE m_array4;
+
+SYNMODE m_x = STRUCT (i long,
+ ar m_array3);
+SYNMODE m_y = STRUCT (i long,
+ ar m_array4);
+
+DCL x LONG;
+
+x := 10;
+
+END pottendo;
diff --git a/gdb/testsuite/gdb.chill/extstruct.exp b/gdb/testsuite/gdb.chill/extstruct.exp
new file mode 100644
index 00000000000..39d61cbe873
--- /dev/null
+++ b/gdb/testsuite/gdb.chill/extstruct.exp
@@ -0,0 +1,66 @@
+# Copyright (C) 1992, 1994, 1997 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file was written by Per Bothner. (bothner@cygnus.com)
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+if [skip_chill_tests] then { continue }
+
+set testfile2 "extstruct-grt"
+set srcfile2 ${srcdir}/$subdir/${testfile2}.ch
+set objfile2 ${objdir}/$subdir/${testfile2}.o
+if { [compile "${srcfile2} -g -c -o ${objfile2}"] != "" } {
+ perror "Couldn't compile ${srcfile2}"
+ return -1
+}
+
+set testfile "extstruct"
+set srcfile ${srcdir}/$subdir/${testfile}.ch
+set binfile ${objdir}/${subdir}/${testfile}.exe
+if { [compile "${srcfile} -g ${objfile2} -o ${binfile} ${CHILL_RT0} ${CHILL_LIB}"] != "" } {
+ perror "Couldn't compile ${srcfile}"
+ return -1
+}
+
+proc do_tests {} {
+ global prms_id bug_id subdir objdir srcdir binfile gdb_prompt
+
+ set prms_id 0
+ set bug_id 0
+
+ # Start with a fresh gdb.
+
+ gdb_exit
+ gdb_start
+ gdb_reinitialize_dir $srcdir/$subdir
+ gdb_load $binfile
+
+ gdb_test "set language chill" ""
+
+ gdb_test "set var \$i := m_x\[\]" ""
+ gdb_test "print \$i" { = \[.i: 0, .ar: \[\(5:6\): \[.f1: 0, .f2: NULL, .f3: \[\(2:3\): 0\]\]\]\]}
+
+ gdb_test "set var \$j := m_y\[\]" ""
+ gdb_test "print \$j" { = \[.i: 0, .ar: \[\(7:8\): \[\(9:10\): \[.f1: 0, .f2: NULL, .f3: \[\(2:3\): 0\]\]\]\]\]}
+}
+
+do_tests
diff --git a/gdb/testsuite/gdb.chill/func1.ch b/gdb/testsuite/gdb.chill/func1.ch
new file mode 100644
index 00000000000..d0d28ce9fae
--- /dev/null
+++ b/gdb/testsuite/gdb.chill/func1.ch
@@ -0,0 +1,9 @@
+func1: MODULE
+
+SYNMODE m_set = SET (e1, e2, e3, e4, e5, e6, e7, e8, e9, e10);
+SYNMODE m_setrange = RANGE (e3:e8);
+SYNMODE m_ps = POWERSET m_set;
+SYNMODE m_rangeps = POWERSET RANGE(0:31);
+GRANT ALL;
+
+END func1;
diff --git a/gdb/testsuite/gdb.chill/gch1041.ch b/gdb/testsuite/gdb.chill/gch1041.ch
new file mode 100644
index 00000000000..a9ce80b75ed
--- /dev/null
+++ b/gdb/testsuite/gdb.chill/gch1041.ch
@@ -0,0 +1,17 @@
+arr: MODULE
+
+SYNMODE m_chars = CHARS(30) VARYING;
+SYNMODE m_s = STRUCT (l LONG, c m_chars, b BOOL);
+
+DCL a1 ARRAY (1:1000) LONG INIT := [(5:100): 33, (1:4): 44, (ELSE): 55 ];
+DCL a2 ARRAY (1:10) m_s INIT := [(*): [ 22, "mowi", TRUE ] ];
+DCL a3 ARRAY (CHAR) CHAR INIT := [(*): 'X'];
+
+SYNMODE m_set = SET (e1, e2, e3, e4, e5, e6, e7, e9, e10);
+DCL a4 ARRAY (m_set) BOOL INIT := [(*): TRUE];
+
+a1 := [(5:100): 33, (1:4): 44, (ELSE): 55 ];
+a1 := [ (*): 22 ];
+a2 := [(*): [ 22, "mowi", TRUE ] ];
+
+END arr;
diff --git a/gdb/testsuite/gdb.chill/gch1041.exp b/gdb/testsuite/gdb.chill/gch1041.exp
new file mode 100644
index 00000000000..1cec0f9d883
--- /dev/null
+++ b/gdb/testsuite/gdb.chill/gch1041.exp
@@ -0,0 +1,76 @@
+# Copyright (C) 1995, 1997 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file was written by Fred Fish. (fnf@cygnus.com)
+# Martin Pottendorfer (pottendo@aut.alcatel.at)
+#
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+if [skip_chill_tests] then { continue }
+
+set testfile "gch1041"
+set srcfile ${srcdir}/$subdir/${testfile}.ch
+set binfile ${objdir}/${subdir}/${testfile}.exe
+if { [compile "${srcfile} -g -o ${binfile} ${CHILL_RT0} ${CHILL_LIB}"] != "" } {
+ perror "Couldn't compile ${srcfile}"
+ return -1
+}
+
+# Set the current language to chill. This counts as a test. If it
+# fails, then we skip the other tests.
+
+proc set_lang_chill {} {
+ global gdb_prompt
+ global binfile objdir subdir
+
+ verbose "loading file '$binfile'"
+ gdb_load $binfile
+
+ send_gdb "set language chill\n"
+ gdb_expect {
+ -re ".*$gdb_prompt $" {}
+ timeout { fail "set language chill (timeout)" ; return 0 }
+ }
+
+ return [gdb_test "show language" ".* source language is \"chill\".*" \
+ "set language to \"chill\""]
+}
+
+set prms_id 0
+set bug_id 0
+
+# Start with a fresh gdb.
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+
+gdb_test "set print sevenbit-strings" ".*"
+
+if ![set_lang_chill] then {
+ runto arr_
+ # check if array slices print correct index
+ gdb_test {print a1(10:30)} { = \[\(10:30\): 33\]}
+ gdb_test {print a2(3:5)} { = \[\(3:5\): \[.l: 22, .c: "mowi", .b: TRUE\]\]}
+ gdb_test {print a3('a':'c')} { = \[\('a':'c'\): 'X'\]}
+ gdb_test {print a4(e2:e5)} { = \[\(e2:e5\): TRUE\]}
+}
diff --git a/gdb/testsuite/gdb.chill/gch1272.ch b/gdb/testsuite/gdb.chill/gch1272.ch
new file mode 100644
index 00000000000..6112d4ba60a
--- /dev/null
+++ b/gdb/testsuite/gdb.chill/gch1272.ch
@@ -0,0 +1,21 @@
+gch1272: MODULE
+
+SYNMODE m_array = ARRAY (0:99) INT;
+DCL foo m_array;
+
+SYNMODE m_xxx = ARRAY (1:10) LONG;
+
+SYNMODE m_struct = STRUCT (i LONG, b BOOL);
+SYNMODE m_bar = ARRAY (-10:20) m_struct;
+DCL bar m_bar;
+
+SYNMODE m_ps = POWERSET LONG (0:20);
+
+brrr: PROC ()
+END;
+
+foo := [ (*): 222 ];
+
+brrr ();
+
+END gch1272;
diff --git a/gdb/testsuite/gdb.chill/gch1272.exp b/gdb/testsuite/gdb.chill/gch1272.exp
new file mode 100644
index 00000000000..db60715462d
--- /dev/null
+++ b/gdb/testsuite/gdb.chill/gch1272.exp
@@ -0,0 +1,86 @@
+# Copyright (C) 1995, 1997 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file was written by Wilfried Moser (moser@aut.alcatel.at)
+#
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+if [skip_chill_tests] then { continue }
+
+set testfile "gch1272"
+set srcfile ${srcdir}/$subdir/${testfile}.ch
+set binfile ${objdir}/${subdir}/${testfile}.exe
+if { [compile "${srcfile} -g -o ${binfile} ${CHILL_RT0} ${CHILL_LIB}"] != "" } {
+ perror "Couldn't compile ${srcfile}"
+ return -1
+}
+
+# Set the current language to chill. This counts as a test. If it
+# fails, then we skip the other tests.
+
+proc set_lang_chill {} {
+ global gdb_prompt
+ global binfile objdir subdir
+
+ verbose "loading file '$binfile'"
+ gdb_load $binfile
+
+ send_gdb "set language chill\n"
+ gdb_expect {
+ -re ".*$gdb_prompt $" {}
+ timeout { fail "set language chill (timeout)" ; return 0 }
+ }
+
+ return [gdb_test "show language" ".* source language is \"chill\".*" \
+ "set language to \"chill\""]
+}
+
+set prms_id 0
+set bug_id 0
+
+# Start with a fresh gdb.
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+
+gdb_test "set print sevenbit-strings" ".*"
+
+if ![set_lang_chill] then {
+ runto brrr
+
+ # check foo
+ gdb_test {print foo} { = \[\(0:99\): 222\]}
+ gdb_test "set var foo := m_array\[\(\*\):44\]" ".*"
+ gdb_test {print foo} { = \[\(0:99\): 44\]}
+
+ # check bar
+ gdb_test {print bar} { = \[\(-10:20\): \[.i: 0, .b: FALSE\]\]}
+ gdb_test "set var bar := m_bar\[\(\*\): \[42, TRUE\]\]" ".*"
+ gdb_test {print bar} { = \[\(-10:20\): \[.i: 42, .b: TRUE\]\]}
+
+ # some failues
+ gdb_test "set var foo := \[\(\*\):44\]" {\(\*\) only possible with modename in front of tuple \(mode\[\.\.\]\)}
+ gdb_test "set var foo := m_xxx\[\(\*\):44\]" {Invalid cast\.}
+ gdb_test "set var foo := m_struct\[\(\*\):44\]" {\(\*\) in invalid context}
+ gdb_test "set var foo := m_ps\[\(\*\):44\]" {\(\*\) in invalid context}
+}
diff --git a/gdb/testsuite/gdb.chill/gch1280.ch b/gdb/testsuite/gdb.chill/gch1280.ch
new file mode 100644
index 00000000000..3fba71f9111
--- /dev/null
+++ b/gdb/testsuite/gdb.chill/gch1280.ch
@@ -0,0 +1,13 @@
+gch1280: MODULE
+
+SYNMODE m_x = ARRAY (1:3) LONG;
+DCL v_x m_x;
+DCL v_xx m_x;
+
+doit: PROC ()
+END doit;
+
+v_x := [ 11, 12, 13 ];
+doit ();
+
+END gch1280;
diff --git a/gdb/testsuite/gdb.chill/gch1280.exp b/gdb/testsuite/gdb.chill/gch1280.exp
new file mode 100644
index 00000000000..216625d3931
--- /dev/null
+++ b/gdb/testsuite/gdb.chill/gch1280.exp
@@ -0,0 +1,76 @@
+# Copyright (C) 1995, 1997 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file was written by Wilfried Moser (moser@aut.alcatel.at)
+#
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+if [skip_chill_tests] then { continue }
+
+set testfile "gch1280"
+set srcfile ${srcdir}/$subdir/${testfile}.ch
+set binfile ${objdir}/${subdir}/${testfile}.exe
+if { [compile "${srcfile} -g -o ${binfile} ${CHILL_RT0} ${CHILL_LIB}"] != "" } {
+ perror "Couldn't compile ${srcfile}"
+ return -1
+}
+
+# Set the current language to chill. This counts as a test. If it
+# fails, then we skip the other tests.
+
+proc set_lang_chill {} {
+ global gdb_prompt
+ global binfile objdir subdir
+
+ verbose "loading file '$binfile'"
+ gdb_load $binfile
+
+ send_gdb "set language chill\n"
+ gdb_expect {
+ -re ".*$gdb_prompt $" {}
+ timeout { fail "set language chill (timeout)" ; return 0 }
+ }
+
+ return [gdb_test "show language" ".* source language is \"chill\".*" \
+ "set language to \"chill\""]
+}
+
+set prms_id 0
+set bug_id 0
+
+# Start with a fresh gdb.
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+
+gdb_test "set print sevenbit-strings" ".*"
+
+if ![set_lang_chill] then {
+ runto doit
+ gdb_test "next" ""
+ # check too many array elements
+ gdb_test {set var v_x := [1,2,3,4,5]} {Too many array elements}
+ gdb_test {set var $i := m_x[(3): 22, 25]} {Too many array elements}
+ gdb_test "set var \$i := m_x\[\(2\): 22, 25\]" ""
+ gdb_test {print $i} { = \[\(1\): 0, \(2\): 22, \(3\): 25\]}
+}
diff --git a/gdb/testsuite/gdb.chill/gch922.ch b/gdb/testsuite/gdb.chill/gch922.ch
new file mode 100644
index 00000000000..b3e8a239512
--- /dev/null
+++ b/gdb/testsuite/gdb.chill/gch922.ch
@@ -0,0 +1,23 @@
+xx : module
+
+dcl a chars(200) varying init := (70)'^(0)' // "Jason""^(0,5)""Hugo^(10)" // (70)'^(1)';
+dcl b chars(20) varying init := "Jason""^(0,5)""Hugo^(10)";
+dcl c chars(256) varying init := (70)'a' // "^(0,5)Jason" // (70)'b';
+dcl d char init := '^(11)';
+
+bulk: PROC ();
+END bulk;
+
+a := (50) '^(255,0,222,127)';
+b := (1)'^(200)';
+d := 'a';
+
+c:= (256)" ";
+
+DO FOR i:= 0 BY 1 TO 255;
+ c (255-i) := char (i);
+OD;
+
+bulk ();
+
+end xx; \ No newline at end of file
diff --git a/gdb/testsuite/gdb.chill/gch922.exp b/gdb/testsuite/gdb.chill/gch922.exp
new file mode 100644
index 00000000000..c0fb6dc7fb3
--- /dev/null
+++ b/gdb/testsuite/gdb.chill/gch922.exp
@@ -0,0 +1,183 @@
+# Copyright (C) 1995, 1997 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file tests various Chill values, expressions, and types.
+
+# This file was written by Wilfried Moser (moser@aut.alcatel.at)
+# Kurt Fuchs (fuchs_k@aut.alcatel.at)
+#
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+if [skip_chill_tests] then { continue }
+
+set testfile "gch922"
+set srcfile ${srcdir}/$subdir/${testfile}.ch
+set binfile ${objdir}/${subdir}/${testfile}.exe
+if { [compile "${srcfile} -g -w -o ${binfile} ${CHILL_RT0} ${CHILL_LIB}"] != "" } {
+ perror "Couldn't compile ${srcfile}"
+ return -1
+}
+
+# Set the current language to chill. This counts as a test. If it
+# fails, then we skip the other tests.
+
+proc set_lang_chill {} {
+ global gdb_prompt
+ global binfile objdir subdir
+
+ verbose "loading file '$binfile'"
+ gdb_load $binfile
+ send_gdb "set language chill\n"
+ gdb_expect {
+ -re ".*$gdb_prompt $" {}
+ timeout { fail "set language chill (timeout)" ; return 0 }
+ }
+
+ send_gdb "show language\n"
+ gdb_expect {
+ -re ".* source language is \"chill\".*$gdb_prompt $" {
+ pass "set language to \"chill\""
+ send_gdb "break xx_\n"
+ gdb_expect {
+ -re ".*$gdb_prompt $" {
+ send_gdb "run\n"
+ gdb_expect -re ".*$gdb_prompt $" {}
+ return 1
+ }
+ timeout {
+ fail "can't set breakpoint (timeout)"
+ return 0
+ }
+ }
+ }
+ -re ".*$gdb_prompt $" {
+ fail "setting language to \"chill\""
+ return 0
+ }
+ timeout {
+ fail "can't show language (timeout)"
+ return 0
+ }
+ }
+}
+
+# Testing printing of a specific value. Increment passcount for
+# success or issue fail message for failure. In both cases, return
+# a 1 to indicate that more tests can proceed. However a timeout
+# is a serious error, generates a special fail message, and causes
+# a 0 to be returned to indicate that more tests are likely to fail
+# as well.
+#
+# Args are:
+#
+# First one is string to send_gdb to gdb
+# Second one is string to match gdb result to
+# Third one is an optional message to be printed
+
+proc test_print_accept { args } {
+ global gdb_prompt
+ global passcount
+ global verbose
+
+ if [llength $args]==3 then {
+ set message [lindex $args 2]
+ } else {
+ set message [lindex $args 0]
+ }
+ set sendthis [lindex $args 0]
+ set expectthis [lindex $args 1]
+ set result [gdb_test $sendthis ".* = ${expectthis}" $message]
+ if $result==0 {incr passcount}
+ return $result
+}
+
+
+proc test_chars {} {
+ global passcount gdb_prompt
+
+ verbose "Testing Chars"
+ set passcount 0
+
+ test_print_accept "print a" {'\^\(0\)'<repeats 70 times>//"Jason""\^\(0,5\)""Hugo\^\(10\)"//'\^\(1\)'<repeats 70 times>}
+ test_print_accept "print b" {"Jason""\^\(0,5\)""Hugo\^\(10\)"}
+ test_print_accept "print c" {'a'<repeats 70 times>//"\^\(0,5\)Jason"//'b'<repeats 70 times>}
+ test_print_accept "print d" {'\^\(11\)'}
+
+ gdb_test "set var a := (100)'\^(0,255)'" ""
+ test_print_accept "print a" {"\^\(0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255\)"}
+
+ send_gdb "set var a := (10)'\^(1)'//(26)\"\^(66,67)\"//\" \"//'I'//' '//'a'//'m'//\" Hugo\" \n" ; gdb_expect -re "$gdb_prompt $"
+ test_print_accept "print a" {"\^\(1,1,1,1,1,1,1,1,1,1\)BCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBC I am Hugo"}
+ send_gdb "set var b := \"Hugo \"\"\^(3,4)\"\"Otto\^(17)\" \n" ; gdb_expect -re "$gdb_prompt $"
+ test_print_accept "print b" {"Hugo ""\^\(3,4\)""Otto\^\(17\)"}
+ send_gdb "set var c := (70)'b' // \"\^(2,3)Hugo \" // (70)'c' \n" ; gdb_expect -re "$gdb_prompt $"
+ test_print_accept "print c" {'b'<repeats 70 times>//"\^\(2,3\)Hugo "//'c'<repeats 70 times>}
+ gdb_test "set var d := '\^(199)'" ""
+ test_print_accept "print d" {'\^\(199\)'}
+
+ test_print_accept "print (10)'\^(0)'//(26)\"\^(66,67)\"//\" \"//'I'//' '//'a'//'m'//\" Hugo\"" {"\^\(0,0,0,0,0,0,0,0,0,0\)BCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBC I am Hugo"}
+ test_print_accept "print \"Jason\"\"\^(0,5)\"\"Hugo\^(10)\"" {"Jason""\^\(0,5\)""Hugo\^\(10\)"}
+
+ send_gdb "set var a := \"\" \n" ; gdb_expect -re "$gdb_prompt $"
+ test_print_accept "print a" {""}
+ send_gdb "set var a := \"\"\"\" \n" ; gdb_expect -re "$gdb_prompt $"
+ test_print_accept "print a" {""""}
+ send_gdb "set var a := \" \"\"\" \n" ; gdb_expect -re "$gdb_prompt $"
+ test_print_accept "print a" {" """}
+ send_gdb "set var a := \"\^\^\" \n" ; gdb_expect -re "$gdb_prompt $"
+ test_print_accept "print a" {"\^\^"}
+ send_gdb "set var a := \"'\" \n" ; gdb_expect -re "$gdb_prompt $"
+ test_print_accept "print a" {"'"}
+}
+
+
+proc test_code {} {
+ global passcount gdb_prompt
+
+ verbose "Testing Chars"
+ set passcount 0
+
+ runto bulk
+ test_print_accept "print a" {"\^\(255,0,222,127,255,0,222,127,255,0,222,127,255,0,222,127,255,0,222,127,255,0,222,127,255,0,222,127,255,0,222,127,255,0,222,127,255,0,222,127,255,0,222,127,255,0,222,127,255,0,222,127,255,0,222,127,255,0,222,127,255,0,222,127,255,0,222,127,255,0,222,127,255,0,222,127,255,0,222,127,255,0,222,127,255,0,222,127,255,0,222,127,255,0,222,127,255,0,222,127,255,0,222,127,255,0,222,127,255,0,222,127,255,0,222,127,255,0,222,127,255,0,222,127,255,0,222,127,255,0,222,127,255,0,222,127,255,0,222,127,255,0,222,127,255,0,222,127,255,0,222,127,255,0,222,127,255,0,222,127,255,0,222,127,255,0,222,127,255,0,222,127,255,0,222,127,255,0,222,127,255,0,222,127,255,0,222,127,255,0,222,127,255,0,222,127,255,0,222,127\)"}
+ test_print_accept "print b" {"\^\(200\)"}
+# test_print_accept "print c" {'a'<repeats 70 times>//"\^\(0,5\)Jason"//'b'<repeats 70 times>}
+ test_print_accept "print d" {'a'}
+}
+
+
+# Start with a fresh gdb.
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+
+gdb_test "set print sevenbit-strings" ".*"
+
+
+if [set_lang_chill] then {
+ # test builtins as described in chapter 6.20.3 Z.200
+
+ test_chars
+# test_code
+} else {
+ warning "$test_name tests suppressed."
+}
diff --git a/gdb/testsuite/gdb.chill/gch981.ch b/gdb/testsuite/gdb.chill/gch981.ch
new file mode 100644
index 00000000000..e8f0474729e
--- /dev/null
+++ b/gdb/testsuite/gdb.chill/gch981.ch
@@ -0,0 +1,60 @@
+xx: MODULE
+
+SYNMODE m_set1 = SET (e1, e2, e3, e4, e5);
+DCL v_set1 m_set1 INIT := e3;
+
+SYNMODE m_set2 = SET (a1=1, a2=2, a3=17, a4=9, a5=8, a6=0, a7=14, a8=33, a9=12);
+DCL v1_set2 m_set2 INIT := a1;
+DCL v2_set2 m_set2 INIT := a2;
+DCL v3_set2 m_set2 INIT := a3;
+DCL v4_set2 m_set2 INIT := a4;
+DCL v5_set2 m_set2 INIT := a5;
+DCL v6_set2 m_set2 INIT := a6;
+DCL v7_set2 m_set2 INIT := a7;
+DCL v8_set2 m_set2 INIT := a8;
+DCL v9_set2 m_set2 INIT := a9;
+
+SYNMODE m_set3 = SET (b1, b2, b3, b4, b5 = 4711, b6, b7 = 4713);
+DCL v_set3 m_set3 INIT := b7;
+
+SYNMODE m_set4 = SET(s1=111111, s2, s3, s4);
+DCL v1_set4 m_set4 INIT := s1;
+
+SYNMODE m_set_range = m_set1(e2:e5);
+DCL v_set_range m_set_range INIT := e3;
+
+SYNMODE m_set_range_arr = ARRAY (m_set_range) BYTE;
+DCL v_set_range_arr ARRAY (m_set_range) BYTE;
+
+SYNMODE m_set_arr = ARRAY (m_set1) BYTE;
+DCL v_set_arr ARRAY (m_set1) BYTE;
+
+NEWMODE m_power1 = POWERSET m_set1;
+DCL v1_power1 READ m_power1 INIT := [e1,e2,e3,e4,e5];
+DCL v2_power1 m_power1 INIT := [];
+
+NEWMODE m_power2 = POWERSET m_set2;
+DCL v_power2 m_power2 INIT := [];
+
+NEWMODE m_power3 = POWERSET m_set3;
+DCL v_power3 m_power3 INIT := [b1:b2];
+
+NEWMODE m_power4 = POWERSET CHAR;
+DCL v_power4 m_power4 INIT := ['b':'x'];
+
+NEWMODE m_power5 = POWERSET INT (2:400);
+DCL v_power5 m_power5 INIT := [2:100];
+
+NEWMODE m_power6 = POWERSET INT;
+DCL v_power6 m_power6;
+
+NEWMODE m_power7 = POWERSET LONG;
+DCL v_power7 m_power7;
+
+
+v_set1:= e2;
+v2_power1:= [e1];
+
+v_set1:= e1;
+
+END xx;
diff --git a/gdb/testsuite/gdb.chill/gch981.exp b/gdb/testsuite/gdb.chill/gch981.exp
new file mode 100644
index 00000000000..3a948b1ccc7
--- /dev/null
+++ b/gdb/testsuite/gdb.chill/gch981.exp
@@ -0,0 +1,249 @@
+# Copyright (C) 1995, 1997 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file tests various Chill values, expressions, and types.
+
+# This file was written by Wilfried Moser (moser@aut.alcatel.at)
+# Kurt Fuchs (fuchs_k@aut.alcatel.at)
+#
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+if [skip_chill_tests] then { continue }
+
+set testfile "gch981"
+set srcfile ${srcdir}/$subdir/${testfile}.ch
+set binfile ${objdir}/${subdir}/${testfile}.exe
+if { [compile "${srcfile} -g -w -o ${binfile} ${CHILL_RT0} ${CHILL_LIB}"] != "" } {
+ perror "Couldn't compile ${srcfile}"
+ return -1
+}
+
+# Set the current language to chill. This counts as a test. If it
+# fails, then we skip the other tests.
+
+proc set_lang_chill {} {
+ global gdb_prompt
+ global binfile objdir subdir
+
+ verbose "loading file '$binfile'"
+ gdb_load $binfile
+ send_gdb "set language chill\n"
+ gdb_expect {
+ -re ".*$gdb_prompt $" {}
+ timeout { fail "set language chill (timeout)" ; return 0 }
+ }
+
+ send_gdb "show language\n"
+ gdb_expect {
+ -re ".* source language is \"chill\".*$gdb_prompt $" {
+ pass "set language to \"chill\""
+ send_gdb "break xx_\n"
+ gdb_expect {
+ -re ".*$gdb_prompt $" {
+ send_gdb "run\n"
+ gdb_expect -re ".*$gdb_prompt $" {}
+ return 1
+ }
+ timeout {
+ fail "can't set breakpoint (timeout)"
+ return 0
+ }
+ }
+ }
+ -re ".*$gdb_prompt $" {
+ fail "setting language to \"chill\""
+ return 0
+ }
+ timeout {
+ fail "can't show language (timeout)"
+ return 0
+ }
+ }
+}
+
+# Testing printing of a specific value. Increment passcount for
+# success or issue fail message for failure. In both cases, return
+# a 1 to indicate that more tests can proceed. However a timeout
+# is a serious error, generates a special fail message, and causes
+# a 0 to be returned to indicate that more tests are likely to fail
+# as well.
+#
+# Args are:
+#
+# First one is string to send_gdb to gdb
+# Second one is string to match gdb result to
+# Third one is an optional message to be printed
+
+proc test_print_accept { args } {
+ global gdb_prompt
+ global passcount
+ global verbose
+
+ if [llength $args]==3 then {
+ set message [lindex $args 2]
+ } else {
+ set message [lindex $args 0]
+ }
+ set sendthis [lindex $args 0]
+ set expectthis [lindex $args 1]
+ set result [gdb_test $sendthis ".* = ${expectthis}" $message]
+ if $result==0 {incr passcount}
+ return $result
+}
+
+proc test_power {} {
+ global passcount gdb_prompt
+
+ verbose "Testing some POWERSET Stuff"
+ set passcount 0
+
+ test_print_accept "print v1_power1" {\[e1:e5\]}
+ test_print_accept "print v2_power1" {\[\]}
+ test_print_accept "print SIZE(v1_power1)" "1"
+
+ gdb_test "set v1_power1 := \[b1\]" ""
+# if GDB has rejected the improper values, we have to gdb_expect the same!
+ test_print_accept "print v1_power1" {\[e1:e5\]}
+
+ gdb_test "set v1_power1 := \[a1,a2\]" ""
+ test_print_accept "print v1_power1" {\[e1:e5\]}
+ gdb_test "set v1_power1 := \[b1,b2,b3,e4\]" ""
+ test_print_accept "print v1_power1" {\[e1:e5\]}
+ gdb_test "set v1_power1 := \[e4:e5\]" ""
+ test_print_accept "print v1_power1" {\[e4:e5\]}
+ gdb_test "set v1_power1 := \[e1, e2:e3, e5\]" ""
+ test_print_accept "print v1_power1" {\[e1:e3, e5\]}
+ gdb_test "set v1_power1 := \[e1, e2:e4, e4:e5\]" ""
+ test_print_accept "print v1_power1" {\[e1:e5\]}
+ gdb_test "set v1_power1 := \[e1, e1:e3, e1:e2, e2:e3\]" ""
+ test_print_accept "print v1_power1" {\[e1:e3\]}
+
+ gdb_test "set v_power2 := \[e2\]" ""
+ test_print_accept "print v_power2" {\[\]}
+ gdb_test "set v_power2 := \[1,2,3\]" ""
+ test_print_accept "print v_power2" {\[\]}
+ gdb_test "set v_power2 := \[e2, b2, b1\]" ""
+ test_print_accept "print v_power2" {\[\]}
+
+# Note, that this is a numbered SET, so a1:a3 contains all elements (exept a6)
+ gdb_test "set v_power2 := \[a1:a3, a6:a4, a7:a9\]" ""
+ test_print_accept "print v_power2" {\[a6:a3\]}
+ gdb_test "set v_power2 := \[a1, a4:a6, a9\]" ""
+ test_print_accept "print v_power2" {\[a1, a9\]}
+ gdb_test "set v_power2 := \[a1:a2, a6, a9\]" ""
+ test_print_accept "print v_power2" {\[a6:a2, a9\]}
+ gdb_test "set v_power2 := \[a1, a4, a7:a8, a9:a3\]" ""
+ test_print_accept "print v_power2" {\[a1, a4, a9:a8\]}
+ gdb_test "set v_power2 := \[a1, a4:a8\]" ""
+ test_print_accept "print v_power2" {\[a1, a4:a8\]}
+ gdb_test "set v_power2 := \[a8,a3,a7,a9,a5,a6\]" ""
+ test_print_accept "print v_power2" {\[a6, a5, a9, a7, a3, a8\]}
+
+ gdb_test "set v_power3 := \[b1:b2,e1\]" ""
+ test_print_accept "print v_power3" {\[b1:b2\]}
+ gdb_test "set v_power3 := \[b1, b3, b6:b7\]" ""
+ test_print_accept "print v_power3" {\[b1, b3, b6:b7\]}
+ gdb_test "set v_power3 := \[b1, b3:b4, b7\]" ""
+ test_print_accept "print v_power3" {\[b1, b3:b4, b7\]}
+ gdb_test "set v_power3 := \[b1, b4:b6, b7\]" ""
+ test_print_accept "print v_power3" {\[b1, b4:b7\]}
+ gdb_test "set v_power3 := \[b1:b7\]" ""
+ test_print_accept "print v_power3" {\[b1:b7\]}
+ gdb_test "set v_power3 := \[b5:b7, b1\]" ""
+ test_print_accept "print v_power3" {\[b1, b5:b7\]}
+
+ gdb_test "set v_power4 := \[\"b\"\]" ""
+ test_print_accept "print v_power4" {\['b':'x'\]}
+ gdb_test "set v_power4 := \[5\]" ""
+ test_print_accept "print v_power4" {\['b':'x'\]}
+ gdb_test "set v_power4 := \['c':'f','g':'h','o':'t'\]" ""
+ test_print_accept "print v_power4" {\['c':'h', 'o':'t'\]}
+ gdb_test "set v_power4 := \['a','b','c','d','e','f'\]" ""
+ test_print_accept "print v_power4" {\['a':'f'\]}
+ gdb_test "set v_power4 := \['\^(0)':'\^(200)'\]" ""
+ test_print_accept "print v_power4" {\['\^\(0\)':'\^\(200\)'\]}
+
+ gdb_test "set v_power5 := \[a8\]" ""
+ test_print_accept "print v_power5" {\[2:100\]}
+ gdb_test "set v_power5 := \[4\]" ""
+ test_print_accept "print v_power5" {\[4\]}
+ gdb_test "set v_power5 := \[3:95,9:100,10:107,200:250\]" ""
+ test_print_accept "print v_power5" {\[3:107, 200:250\]}
+ gdb_test "set v_power5 := \[2, 100:120, 350:400\]" ""
+ test_print_accept "print v_power5" {\[2, 100:120, 350:400\]}
+ gdb_test "set v_power5 := \[2:64,65:127,128:256,256:399,400\]" ""
+ test_print_accept "print v_power5" {\[2:400\]}
+ gdb_test "set v_power5 := \[3:95, 99:100, 101:107, 200:250\]" ""
+ test_print_accept "print v_power5" {\[3:95, 99:107, 200:250\]}
+
+ gdb_test "set v_power6 := \[a8\]" ""
+ test_print_accept "print v_power6" {\[\]}
+ gdb_test "set v_power6 := \[4\]" ""
+ test_print_accept "print v_power6" {\[4\]}
+ gdb_test "set v_power6 := \[3:95, 99:100, 101:107, 200:250\]" ""
+ test_print_accept "print v_power6" {\[3:95, 99:107, 200:250\]}
+ gdb_test "set v_power6 := \[-111:0, 1:112, 11111:22222\]" ""
+ test_print_accept "print v_power6" {\[-111:112, 11111:22222\]}
+ gdb_test "set v_power6 := \[0, 200:4000, 6666:9999\]" ""
+ test_print_accept "print v_power6" {\[0, 200:4000, 6666:9999\]}
+
+# gdb_test "set v_power7 := \[a8\]" ""
+# test_print_accept "print v_power7" {\[2:100\]}
+# gdb_test "set v_power7 := \[4\]" ""
+# test_print_accept "print v_power7" {\[4\]}
+# gdb_test "set v_power7 := \[3:95, 99:100, 101:107, 200:250\]" ""
+# test_print_accept "print v_power7" {\[3:95, 99:107, 200:250\]}
+# gdb_test "set v_power7 := \[0, 1000, 1000000, 10000000000\]" ""
+# test_print_accept "print v_power7" {\[0, 1000, 1000000, 1000000000\]}
+# gdb_test "set v_power7 := \[-20000:100000, 111111:2222222\]" ""
+# test_print_accept "print v_power7" {\[-20000:100000, 111111:2222222\]}
+# gdb_test "set v_power7 := \[\]" ""
+# test_print_accept "print v_power7" {\[3:95, 99:107, 200:250\]}
+# gdb_test "set v_power7 := \[2:-500, -501:1, 20:370, -888:-920, 1000:2000, 1800:2500\]\ " ""
+# test_print_accept "print v_power7" {\[-920:-888, -501:2, 20:370, 1000:2500\]}
+# test_print_accept "print SIZE(v_power7)" ""
+
+
+ runto 58
+ test_print_accept "print v_set1 IN v1_power1" "TRUE"
+ test_print_accept "print v_set1 IN v2_power1" "FALSE"
+
+}
+
+
+
+# Start with a fresh gdb.
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+
+gdb_test "set print sevenbit-strings" ".*"
+
+
+if [set_lang_chill] then {
+ # test builtins as described in chapter 6.20.3 Z.200
+
+ test_power
+} else {
+ warning "$test_name tests suppressed."
+}
diff --git a/gdb/testsuite/gdb.chill/misc.ch b/gdb/testsuite/gdb.chill/misc.ch
new file mode 100644
index 00000000000..20f12c81405
--- /dev/null
+++ b/gdb/testsuite/gdb.chill/misc.ch
@@ -0,0 +1,12 @@
+misc_tests : MODULE;
+
+DCL otto INT := 42;
+
+DCL foo STRUCT (l LONG, c CHAR, b BOOL, s CHARS(3));
+
+dummyfunc: PROC();
+END dummyfunc;
+
+dummyfunc();
+
+END misc_tests;
diff --git a/gdb/testsuite/gdb.chill/misc.exp b/gdb/testsuite/gdb.chill/misc.exp
new file mode 100644
index 00000000000..684c34d4376
--- /dev/null
+++ b/gdb/testsuite/gdb.chill/misc.exp
@@ -0,0 +1,100 @@
+# Copyright (C) 1995, 1997 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file was written by Fred Fish. (fnf@cygnus.com)
+# Martin Pottendorfer (pottendo@aut.alcatel.at)
+#
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+if [skip_chill_tests] then { continue }
+
+set testfile "misc"
+set srcfile ${srcdir}/$subdir/${testfile}.ch
+set binfile ${objdir}/${subdir}/${testfile}.exe
+if { [compile "${srcfile} -g -o ${binfile} ${CHILL_RT0} ${CHILL_LIB}"] != "" } {
+ perror "Couldn't compile ${srcfile}"
+ return -1
+}
+
+# Set the current language to chill. This counts as a test. If it
+# fails, then we skip the other tests.
+
+proc set_lang_chill {} {
+ global gdb_prompt
+ global binfile objdir subdir
+
+ verbose "loading file '$binfile'"
+ gdb_load $binfile
+
+ send_gdb "set language chill\n"
+ gdb_expect {
+ -re ".*$gdb_prompt $" {}
+ timeout { fail "set language chill (timeout)" ; return 0 }
+ }
+
+ return [gdb_test "show language" ".* source language is \"chill\".*" \
+ "set language to \"chill\""]
+}
+
+set prms_id 0
+set bug_id 0
+
+# Start with a fresh gdb.
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+
+gdb_test "set print sevenbit-strings" ".*"
+
+if ![set_lang_chill] then {
+ runto dummyfunc
+ # check upper/lower case
+ gdb_test "ptype BOOL" " = (bool|BOOL)"
+ gdb_test "ptype bool" " = (bool|BOOL)"
+ gdb_test "print otto" " = 42"
+ gdb_test "print OTTO" " = 42"
+ gdb_test "print otTO" " = 42"
+ gdb_test "print OTto" " = 42"
+ gdb_test "print NULL" " = NULL" "print emptiness literal"
+
+ # This tests PR 8496.
+ gdb_test {printf "%d %d.", 3+4,2} "7 2." "printf with 2 arguments"
+
+ # This tests GCH/924
+ gdb_test {print (h'23)} { = 35} "print parantised integer literal"
+
+ # Linux thinks this is at line 6, but is otherwise ok.
+ setup_xfail "i*86-pc-linux*-gnu"
+ gdb_test "info line" \
+ {Line 7 of .*misc.ch.* at address H'[0-9a-fA-F]+.*}\
+ "info about current line"
+
+ # check array () type (expr)
+ setup_xfail "m68*-*-hpux*"
+ gdb_test "print array () ubyte (foo)" { = \[\(0:11\): 0\]}
+
+ send_gdb "set var \$i := foo\n"
+ gdb_expect -re ".*$gdb_prompt $"
+ setup_xfail "m68*-*-hpux*"
+ gdb_test "print/x array () byte (\$i)" { = \[\(0:11\): H'0\]}
+}
diff --git a/gdb/testsuite/gdb.chill/powerset.ch b/gdb/testsuite/gdb.chill/powerset.ch
new file mode 100644
index 00000000000..dd3172d3640
--- /dev/null
+++ b/gdb/testsuite/gdb.chill/powerset.ch
@@ -0,0 +1,33 @@
+--
+-- check powerset operators and built-ins
+--
+
+ps: MODULE
+
+SYNMODE m_ps1 = POWERSET ULONG (0:8);
+DCL v_ps1 m_ps1 INIT := [1,3,5,7];
+
+SYNMODE m_ps2 = POWERSET LONG (-100:100);
+DCL v_ps2 m_ps2 INIT := [ -100:-95, -1:1, 95:100];
+
+SYNMODE m_set = SET (aa, bb, cc, dd, ee, ff, gg, hh, ii, jj);
+SYNMODE m_ps3 = POWERSET m_set;
+DCL v_ps3 m_ps3 INIT := [bb, dd, ff, ii];
+
+SYNMODE m_ps4 = POWERSET CHAR(' ':'z');
+DCL v_ps4 m_ps4 INIT := [ '.', ',', 'A':'F', 'x':'z' ];
+
+SYNMODE m_ps5 = POWERSET BOOL;
+DCL v_ps5 m_ps5 INIT := [ FALSE ];
+DCL v_ps51 m_ps5 INIT := [ ];
+
+SYNMODE m_int_range = INT(-100:100);
+SYNMODE m_int_subrange = m_int_range(-50:50);
+SYNMODE m_ps6 = POWERSET m_int_subrange;
+DCL v_ps6 m_ps6 INIT := [ LOWER(m_int_subrange):UPPER(m_int_subrange) ];
+
+DCL x INT;
+
+x := 25;
+
+END ps;
diff --git a/gdb/testsuite/gdb.chill/powerset.exp b/gdb/testsuite/gdb.chill/powerset.exp
new file mode 100644
index 00000000000..f047507cc17
--- /dev/null
+++ b/gdb/testsuite/gdb.chill/powerset.exp
@@ -0,0 +1,187 @@
+# Copyright (C) 1995, 1997 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file tests various Chill values, expressions, and types.
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+if [skip_chill_tests] then { continue }
+
+set testfile "powerset"
+set srcfile ${srcdir}/$subdir/${testfile}.ch
+set binfile ${objdir}/${subdir}/${testfile}.exe
+if { [compile "${srcfile} -g -w -o ${binfile} ${CHILL_RT0} ${CHILL_LIB}"] != "" } {
+ perror "Couldn't compile ${srcfile}"
+ return -1
+}
+
+# Set the current language to chill. This counts as a test. If it
+# fails, then we skip the other tests.
+
+proc set_lang_chill {} {
+ global gdb_prompt
+ global binfile objdir subdir
+
+ verbose "loading file '$binfile'"
+ gdb_load $binfile
+ send_gdb "set language chill\n"
+ gdb_expect {
+ -re ".*$gdb_prompt $" {}
+ timeout { fail "set language chill (timeout)" ; return 0 }
+ }
+
+ send_gdb "show language\n"
+ gdb_expect {
+ -re ".* source language is \"chill\".*$gdb_prompt $" {
+ pass "set language to \"chill\""
+ send_gdb "break xx_\n"
+ gdb_expect {
+ -re ".*$gdb_prompt $" {
+ send_gdb "run\n"
+ gdb_expect -re ".*$gdb_prompt $" {}
+ return 1
+ }
+ timeout {
+ fail "can't set breakpoint (timeout)"
+ return 0
+ }
+ }
+ }
+ -re ".*$gdb_prompt $" {
+ fail "setting language to \"chill\""
+ return 0
+ }
+ timeout {
+ fail "can't show language (timeout)"
+ return 0
+ }
+ }
+}
+
+# Testing printing of a specific value. Increment passcount for
+# success or issue fail message for failure. In both cases, return
+# a 1 to indicate that more tests can proceed. However a timeout
+# is a serious error, generates a special fail message, and causes
+# a 0 to be returned to indicate that more tests are likely to fail
+# as well.
+#
+# Args are:
+#
+# First one is string to send_gdb to gdb
+# Second one is string to match gdb result to
+# Third one is an optional message to be printed
+
+proc test_print_accept { args } {
+ global gdb_prompt
+ global passcount
+ global verbose
+
+ if [llength $args]==3 then {
+ set message [lindex $args 2]
+ } else {
+ set message [lindex $args 0]
+ }
+ set sendthis [lindex $args 0]
+ set expectthis [lindex $args 1]
+ set result [gdb_test $sendthis ".* = ${expectthis}" $message]
+ if $result==0 {incr passcount}
+ return $result
+}
+
+proc test_card {} {
+ global passcount
+
+ verbose "testing builtin CARD"
+ set passcount 0
+
+ # discrete mode names
+ test_print_accept "print card(v_ps1)" "4"
+ test_print_accept "print card(v_ps2)" "15"
+ test_print_accept "print card(v_ps3)" "4"
+ test_print_accept "print card(v_ps4)" "11"
+ test_print_accept "print card(v_ps5)" "1"
+ test_print_accept "print card(v_ps51)" "0"
+ test_print_accept "print card(v_ps6)" "101"
+
+ # a failure
+ setup_xfail "*-*-*"
+ test_print_accept "print card(m_ps1)" "typename in invalid context"
+}
+
+proc test_min {} {
+ global passcount
+
+ verbose "testing builtin MIN"
+ set passcount 0
+
+ # discrete mode names
+ test_print_accept "print min(v_ps1)" "1"
+ test_print_accept "print min(v_ps2)" "-100"
+ test_print_accept "print min(v_ps3)" "bb"
+ test_print_accept "print min(v_ps4)" "','"
+ test_print_accept "print min(v_ps5)" "FALSE"
+ test_print_accept "print min(v_ps6)" "-50"
+
+ # a failure
+ setup_xfail "*-*-*"
+ test_print_accept "print min(v_ps51)" "MIN for empty powerset"
+ setup_xfail "*-*-*"
+ test_print_accept "print min(m_ps1)" "typename in invalid context"
+}
+
+proc test_max {} {
+ global passcount
+
+ verbose "testing builtin MIN"
+ set passcount 0
+
+ # discrete mode names
+ test_print_accept "print max(v_ps1)" "7"
+ test_print_accept "print max(v_ps2)" "100"
+ test_print_accept "print max(v_ps3)" "ii"
+ test_print_accept "print max(v_ps4)" "'z'"
+ test_print_accept "print max(v_ps5)" "FALSE"
+ test_print_accept "print max(v_ps6)" "50"
+
+ # test an IN
+ test_print_accept "print 0 in v_ps6" "TRUE"
+
+ # a failure
+ setup_xfail "*-*-*"
+ test_print_accept "print max(v_ps51)" "MAX for empty powerset"
+}
+
+# Start with a fresh gdb.
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+
+gdb_test "set print sevenbit-strings" ".*"
+
+if [set_lang_chill] then {
+ # test builtins as described in chapter 6.20.3 Z.200
+ test_card
+ test_min
+ test_max
+} else {
+ warning "$test_name tests suppressed."
+}
diff --git a/gdb/testsuite/gdb.chill/pr-4975-grt.ch b/gdb/testsuite/gdb.chill/pr-4975-grt.ch
new file mode 100644
index 00000000000..77963628086
--- /dev/null
+++ b/gdb/testsuite/gdb.chill/pr-4975-grt.ch
@@ -0,0 +1,13 @@
+gdb_bug_grt: MODULE
+NEWMODE is_channel_type = SET (chan_1,
+ chan_2,
+ chan_3,
+ chan_4,
+ chan_5,
+ chan_6,
+ chan_7,
+ chan_8,
+ chan_9,
+ chan_10);
+GRANT is_channel_type;
+END;
diff --git a/gdb/testsuite/gdb.chill/pr-4975.ch b/gdb/testsuite/gdb.chill/pr-4975.ch
new file mode 100644
index 00000000000..dbba064a728
--- /dev/null
+++ b/gdb/testsuite/gdb.chill/pr-4975.ch
@@ -0,0 +1,43 @@
+/*
+>Number: 4975
+>Category: chill
+>Synopsis: Segmentation fault of gdb 4.12.1
+>Description:
+
+ Problem: gdb 4.12.1 segment faults with following chill program.
+*/
+
+gdb_bug: MODULE
+
+<> USE_SEIZE_FILE "pr-4975-grt.grt" <>
+SEIZE is_channel_type;
+
+ SYNMODE chan_type = POWERSET is_channel_type;
+ SYN hugo chan_type = [chan_1, chan_3];
+
+DCL otto is_channel_type := chan_2;
+
+x: PROC ();
+
+ IF otto IN hugo THEN
+ WRITETEXT (STDOUT, "otto IN hugo%/");
+ ELSE
+ WRITETEXT (STDOUT, "You loose%/");
+ FI;
+END x;
+
+x ();
+
+END gdb_bug;
+/*
+Compiled with:
+
+ chill -S -fgrant-only pr-315-grt.ch
+ chill -g -o pr-315 pr-315.ch
+
+Run gdb with
+
+ gdb pr-315 --readnow
+
+will result in a sigsegv in file gdbtypes.c function force_to_range_type.
+*/
diff --git a/gdb/testsuite/gdb.chill/pr-4975.exp b/gdb/testsuite/gdb.chill/pr-4975.exp
new file mode 100644
index 00000000000..f59e7dc1728
--- /dev/null
+++ b/gdb/testsuite/gdb.chill/pr-4975.exp
@@ -0,0 +1,67 @@
+# Copyright (C) 1992, 1994, 1997 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file was written by Per Bothner. (bothner@cygnus.com)
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+if [skip_chill_tests] then { continue }
+
+set testfile2 "pr-4975-grt"
+set srcfile2 ${srcdir}/$subdir/${testfile2}.ch
+set objfile2 ${objdir}/$subdir/${testfile2}.o
+if { [compile "${srcfile2} -g -c -o ${objfile2}"] != "" } {
+ perror "Couldn't compile ${srcfile2}"
+ return -1
+}
+
+set testfile "pr-4975"
+set srcfile ${srcdir}/$subdir/${testfile}.ch
+set binfile ${objdir}/${subdir}/${testfile}.exe
+if { [compile "${srcfile} -g ${objfile2} -o ${binfile} ${CHILL_RT0} ${CHILL_LIB}"] != "" } {
+ perror "Couldn't compile ${srcfile}"
+ return -1
+}
+
+proc do_tests {} {
+ global prms_id bug_id subdir objdir srcdir binfile gdb_prompt
+
+ set prms_id 0
+ set bug_id 0
+
+ # Start with a fresh gdb.
+
+ gdb_exit
+ gdb_start
+ gdb_reinitialize_dir $srcdir/$subdir
+ gdb_load $binfile
+
+ gdb_test "set language chill" ""
+
+ # This is needed (at least on SunOS4) to make sure the
+ # the symbol table is read.
+ runto "x"
+ # "You loose"? Why, thank you. (But I suspect "You lose" might have
+ # been what was intended).
+ gdb_test "finish" "You loose.*" "Runs and reads symbols OK"
+}
+
+do_tests
diff --git a/gdb/testsuite/gdb.chill/pr-5016.ch b/gdb/testsuite/gdb.chill/pr-5016.ch
new file mode 100644
index 00000000000..16f49e8f5f5
--- /dev/null
+++ b/gdb/testsuite/gdb.chill/pr-5016.ch
@@ -0,0 +1,24 @@
+vector: MODULE
+
+SYNMODE m_index = RANGE(1:10);
+NEWMODE vector = ARRAY (m_index) INT;
+
+DCL a, b, c vector;
+
+dump: PROC( a vector LOC, c CHAR );
+ DCL i m_index := 5;
+ DO FOR i IN m_index;
+ WRITETEXT( STDOUT, "%C(%C)=%C ", c, i, a(i) );
+ OD;
+ WRITETEXT( STDOUT, "%/" );
+END dump;
+
+a := vector [ 1, -1, 2, -2, 3, -3, 4, -4, 5, -5 ];
+b := a;
+b(4) := 4;
+b(7) := 7;
+c := vector [(*): 0];
+
+dump(a,'a');
+
+END vector;
diff --git a/gdb/testsuite/gdb.chill/pr-5016.exp b/gdb/testsuite/gdb.chill/pr-5016.exp
new file mode 100644
index 00000000000..4384d8ce9f6
--- /dev/null
+++ b/gdb/testsuite/gdb.chill/pr-5016.exp
@@ -0,0 +1,62 @@
+# Copyright (C) 1992, 1997 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file was written by Per Bothner. (bothner@cygnus.com)
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+if [skip_chill_tests] then { continue }
+
+set testfile "pr-5016"
+set srcfile ${srcdir}/$subdir/${testfile}.ch
+set binfile ${objdir}/${subdir}/${testfile}.exe
+if { [compile "${srcfile} -g -o ${binfile} ${CHILL_RT0} ${CHILL_LIB}"] != "" } {
+ perror "Couldn't compile ${srcfile}"
+ return -1
+}
+
+proc do_tests {} {
+ global prms_id bug_id subdir objdir srcdir binfile gdb_prompt
+
+ set prms_id 0
+ set bug_id 0
+
+ # Start with a fresh gdb.
+
+ gdb_exit
+ gdb_start
+ gdb_reinitialize_dir $srcdir/$subdir
+ gdb_load $binfile
+
+ gdb_test "set language chill" ""
+
+ runto dump
+ # Linux thinks type is "_cint" (and so does sparc-sun-sunos4, alpha-dec-osf2.0)
+ #setup_xfail "i*86-pc-linux*-gnu" "sparc-sun-sunos4*" "alpha-dec-osf2*"
+ gdb_test "whatis i" "type = m_index" "whatis int-range"
+ gdb_test_exact "ptype m_index" "type = RANGE (1:10)" "ptype m_index"
+ gdb_test_exact "whatis a" "type = /*LOC*/ vector"
+ gdb_test "ptype a" "type = /\\*LOC\\*/ ARRAY \\(1:10\\) (INT|int)"
+ gdb_test "step" ""
+ gdb_test_exact "whatis i" "type = long" "whatis loop counter i"
+}
+
+do_tests
diff --git a/gdb/testsuite/gdb.chill/pr-5020.ch b/gdb/testsuite/gdb.chill/pr-5020.ch
new file mode 100644
index 00000000000..6aba793d0d0
--- /dev/null
+++ b/gdb/testsuite/gdb.chill/pr-5020.ch
@@ -0,0 +1,19 @@
+
+PR_5020: MODULE
+ dummy_pr_5020: PROC ();
+ END;
+ NEWMODE x = STRUCT (l LONG, b BOOL);
+ NEWMODE aset = SET (aa, bb);
+
+ DCL y ARRAY ('a':'b') x;
+ DCL setarr ARRAY (aset) x;
+ DCL intarr ARRAY(10:11) x;
+ DCL boolarr ARRAY (BOOL) x;
+
+ y('a').l, setarr(aa).l, intarr(10).l, boolarr(FALSE).l := 10;
+ y('a').b, setarr(aa).b, intarr(10).b, boolarr(FALSE).b := TRUE;
+ y('b').l, setarr(bb).l, intarr(11).l, boolarr(TRUE).l := 111;
+ y('b').b, setarr(bb).b, intarr(11).b, boolarr(TRUE).b := FALSE;
+
+ dummy_pr_5020 ();
+END;
diff --git a/gdb/testsuite/gdb.chill/pr-5020.exp b/gdb/testsuite/gdb.chill/pr-5020.exp
new file mode 100644
index 00000000000..1adece34cfc
--- /dev/null
+++ b/gdb/testsuite/gdb.chill/pr-5020.exp
@@ -0,0 +1,85 @@
+# Copyright (C) 1992, 1994, 1997 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file was written by Per Bothner. (bothner@cygnus.com)
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+if [skip_chill_tests] then { continue }
+
+set testfile "pr-5020"
+set srcfile ${srcdir}/$subdir/${testfile}.ch
+set binfile ${objdir}/${subdir}/${testfile}.exe
+if { [compile "${srcfile} -g -o ${binfile} ${CHILL_RT0} ${CHILL_LIB}"] != "" } {
+ perror "Couldn't compile ${srcfile}"
+ return -1
+}
+
+proc do_tests {} {
+ global prms_id bug_id subdir objdir srcdir binfile gdb_prompt
+
+ set prms_id 0
+ set bug_id 0
+
+ # Start with a fresh gdb.
+
+ gdb_exit
+ gdb_start
+ gdb_reinitialize_dir $srcdir/$subdir
+ gdb_load $binfile
+
+ gdb_test "set language chill" ""
+
+ # This is needed (at least on SunOS4) to make sure the
+ # the symbol table is read.
+ gdb_test "break chillvars.ch:3" ""
+ gdb_test "delete 1" ""
+
+ gdb_test "set width 0" ""
+ gdb_test "set print sevenbit-strings" ""
+ gdb_test "set print address off" ""
+
+ test_pr_5020
+}
+
+proc test_pr_5020 {} {
+ global gdb_prompt
+ runto dummy_pr_5020
+ gdb_test_exact "print y" \
+ {= [('a'): [.l: 10, .b: TRUE], ('b'): [.l: 111, .b: FALSE]]}
+ gdb_test_exact "print boolarr" \
+ {= [(FALSE): [.l: 10, .b: TRUE], (TRUE): [.l: 111, .b: FALSE]]}
+ gdb_test_exact "print intarr" \
+ {= [(10): [.l: 10, .b: TRUE], (11): [.l: 111, .b: FALSE]]}
+ gdb_test_exact "print setarr" \
+ {= [(aa): [.l: 10, .b: TRUE], (bb): [.l: 111, .b: FALSE]]}
+ gdb_test "set print pretty" ""
+ gdb_test_exact "print y" \
+{= [('a'): [
+ .l: 10,
+ .b: TRUE
+ ], ('b'): [
+ .l: 111,
+ .b: FALSE
+ ]]} "print y pretty"
+}
+
+do_tests
diff --git a/gdb/testsuite/gdb.chill/pr-5022.ch b/gdb/testsuite/gdb.chill/pr-5022.ch
new file mode 100644
index 00000000000..aeaad4e8f17
--- /dev/null
+++ b/gdb/testsuite/gdb.chill/pr-5022.ch
@@ -0,0 +1,12 @@
+PR_5022: MODULE
+ dummy_pr_5022: PROC ();
+ END;
+ DCL p PTR;
+ DCL i INT;
+
+ p := NULL;
+ dummy_pr_5022 ();
+ i := 13;
+ p := ->i;
+ dummy_pr_5022 ();
+END;
diff --git a/gdb/testsuite/gdb.chill/pr-5022.exp b/gdb/testsuite/gdb.chill/pr-5022.exp
new file mode 100644
index 00000000000..097e386be3b
--- /dev/null
+++ b/gdb/testsuite/gdb.chill/pr-5022.exp
@@ -0,0 +1,70 @@
+# Copyright (C) 1992, 1997 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file was written by Per Bothner. (bothner@cygnus.com)
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+if [skip_chill_tests] then { continue }
+
+set testfile "pr-5022"
+set srcfile ${srcdir}/$subdir/${testfile}.ch
+set binfile ${objdir}/${subdir}/${testfile}.exe
+if { [compile "${srcfile} -g -o ${binfile} ${CHILL_RT0} ${CHILL_LIB}"] != "" } {
+ perror "Couldn't compile ${srcfile}"
+ return -1
+}
+
+proc do_tests {} {
+ global prms_id bug_id subdir objdir srcdir binfile gdb_prompt
+
+ set prms_id 0
+ set bug_id 0
+
+ # Start with a fresh gdb.
+
+ gdb_exit
+ gdb_start
+ gdb_reinitialize_dir $srcdir/$subdir
+ gdb_load $binfile
+
+ gdb_test "set language chill" ""
+
+ # This is needed (at least on SunOS4) to make sure the
+ # the symbol table is read.
+ gdb_test "break gdbme.ch:3" ""
+ gdb_test "delete 1" ""
+
+ gdb_test "set width 0" ""
+ gdb_test "set print sevenbit-strings" ""
+
+ test_pr_5022
+}
+
+proc test_pr_5022 {} {
+ global gdb_prompt
+ runto dummy_pr_5022
+ gdb_test "p p" " = NULL" "print NULL pointer"
+ gdb_test "continue" ""
+ gdb_test "p p" {= PTR\(H'[0-9a-fA-F]+\)} "print non-NULL pointer"
+}
+
+do_tests
diff --git a/gdb/testsuite/gdb.chill/pr-5646-grt.ch b/gdb/testsuite/gdb.chill/pr-5646-grt.ch
new file mode 100644
index 00000000000..b7a90023585
--- /dev/null
+++ b/gdb/testsuite/gdb.chill/pr-5646-grt.ch
@@ -0,0 +1,5 @@
+x: MODULE
+NEWMODE a_set = SET (a, b, c, d);
+NEWMODE a_ps = POWERSET a_set;
+GRANT a_ps;
+END;
diff --git a/gdb/testsuite/gdb.chill/pr-5646.ch b/gdb/testsuite/gdb.chill/pr-5646.ch
new file mode 100644
index 00000000000..8c14cb86b4f
--- /dev/null
+++ b/gdb/testsuite/gdb.chill/pr-5646.ch
@@ -0,0 +1,15 @@
+y: MODULE
+
+<> USE_SEIZE_FILE "pr-5646-grt.grt" <>
+SEIZE a_ps;
+
+p: PROC ();
+
+ DCL xx a_ps;
+
+ xx := [a, b];
+END p;
+
+p();
+
+END y;
diff --git a/gdb/testsuite/gdb.chill/pr-5646.exp b/gdb/testsuite/gdb.chill/pr-5646.exp
new file mode 100644
index 00000000000..958b36aa3a7
--- /dev/null
+++ b/gdb/testsuite/gdb.chill/pr-5646.exp
@@ -0,0 +1,64 @@
+# Copyright (C) 1992, 1997 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file was written by Per Bothner. (bothner@cygnus.com)
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+if [skip_chill_tests] then { continue }
+
+set testfile2 "pr-5646-grt"
+set srcfile2 ${srcdir}/$subdir/${testfile2}.ch
+set objfile2 ${objdir}/$subdir/${testfile2}.o
+if { [compile "${srcfile2} -g -c -o ${objfile2}"] != "" } {
+ perror "Couldn't compile ${srcfile2}"
+ return -1
+}
+
+set testfile "pr-5646"
+set srcfile ${srcdir}/$subdir/${testfile}.ch
+set binfile ${objdir}/${subdir}/${testfile}.exe
+if { [compile "${srcfile} -g ${objfile2} -o ${binfile} ${CHILL_RT0} ${CHILL_LIB}"] != "" } {
+ perror "Couldn't compile ${srcfile}"
+ return -1
+}
+
+proc do_tests {} {
+ global prms_id bug_id subdir objdir srcdir binfile gdb_prompt
+
+ set prms_id 0
+ set bug_id 0
+
+ # Start with a fresh gdb.
+
+ gdb_exit
+ gdb_start
+ gdb_reinitialize_dir $srcdir/$subdir
+ gdb_load $binfile
+
+ gdb_test "set language chill" ""
+
+ runto p
+ gdb_test "next" ""
+ gdb_test_exact "print xx" {= [a:b]}
+}
+
+do_tests
diff --git a/gdb/testsuite/gdb.chill/pr-5984.ch b/gdb/testsuite/gdb.chill/pr-5984.ch
new file mode 100644
index 00000000000..3e74a5660ce
--- /dev/null
+++ b/gdb/testsuite/gdb.chill/pr-5984.ch
@@ -0,0 +1,8 @@
+x: module -- line 1
+ p:proc (t char (20) varying); -- 2
+ writetext(stdout, t); -- 3
+ end p; -- 4
+ -- 5
+ p("Jason Dark.%/"); -- 6
+ p("Hello World.%/"); -- 7
+end x;
diff --git a/gdb/testsuite/gdb.chill/pr-5984.exp b/gdb/testsuite/gdb.chill/pr-5984.exp
new file mode 100644
index 00000000000..f8ea37ea33e
--- /dev/null
+++ b/gdb/testsuite/gdb.chill/pr-5984.exp
@@ -0,0 +1,57 @@
+# Copyright (C) 1992, 1997 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file was written by Per Bothner. (bothner@cygnus.com)
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+if [skip_chill_tests] then { continue }
+
+set testfile "pr-5984"
+set srcfile ${srcdir}/$subdir/${testfile}.ch
+set binfile ${objdir}/${subdir}/${testfile}.exe
+if { [compile "${srcfile} -g -o ${binfile} ${CHILL_RT0} ${CHILL_LIB}"] != "" } {
+ perror "Couldn't compile ${srcfile}"
+ return -1
+}
+
+proc do_tests {} {
+ global prms_id bug_id subdir objdir srcdir binfile gdb_prompt
+
+ set prms_id 0
+ set bug_id 0
+
+ # Start with a fresh gdb.
+
+ gdb_exit
+ gdb_start
+ gdb_reinitialize_dir $srcdir/$subdir
+ gdb_load $binfile
+
+ send_gdb "set language chill\n" ;
+
+ gdb_test "break pr-5984.ch:6" ""
+ send_gdb "run\n"; gdb_expect -re "Breakpoint .*pr-5984.ch:6"
+ gdb_expect -re "$gdb_prompt $"
+ gdb_test "next" "Jason Dark.*" "next over Jason Dark"
+}
+
+do_tests
diff --git a/gdb/testsuite/gdb.chill/pr-6292.ch b/gdb/testsuite/gdb.chill/pr-6292.ch
new file mode 100644
index 00000000000..c2ed95361c6
--- /dev/null
+++ b/gdb/testsuite/gdb.chill/pr-6292.ch
@@ -0,0 +1,17 @@
+hack : module
+
+dcl i int;
+
+fred : proc (a int in, b int loc);
+ writetext(stdout, "a was '%C'; b was '%C'.%/", a, b);
+ b + := 1;
+end fred;
+
+klaus : proc ();
+ writetext(stdout, "here's klaus calling.%/");
+end klaus;
+
+i:=12;
+writetext(stdout, "done.%/");
+
+end hack;
diff --git a/gdb/testsuite/gdb.chill/pr-6292.exp b/gdb/testsuite/gdb.chill/pr-6292.exp
new file mode 100644
index 00000000000..db276b87986
--- /dev/null
+++ b/gdb/testsuite/gdb.chill/pr-6292.exp
@@ -0,0 +1,58 @@
+# Copyright (C) 1995, 1997 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file was written by Per Bothner. (bothner@cygnus.com)
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+if [skip_chill_tests] then { continue }
+
+set testfile "pr-6292"
+set srcfile ${srcdir}/$subdir/${testfile}.ch
+set binfile ${objdir}/${subdir}/${testfile}.exe
+if { [compile "${srcfile} -g -o ${binfile} ${CHILL_RT0} ${CHILL_LIB}"] != "" } {
+ perror "Couldn't compile ${srcfile}"
+ return -1
+}
+
+proc do_tests {} {
+ global prms_id bug_id subdir objdir srcdir binfile gdb_prompt
+
+ set prms_id 0
+ set bug_id 0
+
+ # Start with a fresh gdb.
+
+ gdb_exit
+ gdb_start
+ gdb_reinitialize_dir $srcdir/$subdir
+ gdb_load $binfile
+
+ send_gdb "set language chill\n" ;
+
+ gdb_test "break pr-6292.ch:15" ""
+ send_gdb "run\n"; gdb_expect -re "Breakpoint .*pr-6292.ch:15.*$gdb_prompt $"
+ gdb_test_exact "call klaus()" {here's klaus calling.}
+ gdb_test {set fred(10, i)} {a was '10'; b was '12'.}
+ gdb_test "print i" { = 13} "print i after call"
+}
+
+do_tests
diff --git a/gdb/testsuite/gdb.chill/pr-6632-grt.ch b/gdb/testsuite/gdb.chill/pr-6632-grt.ch
new file mode 100644
index 00000000000..e9434f1bb48
--- /dev/null
+++ b/gdb/testsuite/gdb.chill/pr-6632-grt.ch
@@ -0,0 +1,34 @@
+markus1: MODULE
+
+SYNMODE m_dummy = SET (dummy_1,
+ dummy_2,
+ dummy_3,
+ dummy_4,
+ dummy_5,
+ dummy_6,
+ dummy_7,
+ dummy_8,
+ dummy_9,
+ dummy_10,
+ dummy_11,
+ dummy_12,
+ dummy_13,
+ dummy_14,
+ dummy_15,
+ dummy_16,
+ dummy_17,
+ dummy_18,
+ dummy_19,
+ dummy_20,
+ dummy_21,
+ dummy_22,
+ dummy_23,
+ dummy_24,
+ dummy_25,
+ dummy_26);
+
+SYNMODE m_dummy_range = m_dummy(dummy_6 : dummy_22);
+
+GRANT m_dummy, m_dummy_range;
+
+END markus1;
diff --git a/gdb/testsuite/gdb.chill/pr-6632.ch b/gdb/testsuite/gdb.chill/pr-6632.ch
new file mode 100644
index 00000000000..b82c7ae1c88
--- /dev/null
+++ b/gdb/testsuite/gdb.chill/pr-6632.ch
@@ -0,0 +1,31 @@
+markus: MODULE
+
+<> USE_SEIZE_FILE "pr-6632-grt.grt" <>
+SEIZE m_dummy, m_dummy_range;
+
+DCL v m_dummy_range;
+
+NEWMODE is_str_descr = STRUCT (p PTR,
+ l INT,
+ flag STRUCT (x UBYTE,
+ y SET (aa, bb, cc, dd, ee, ff)));
+DCL des is_str_descr;
+
+NEWMODE is_cb_debug = STRUCT (i INT,
+ channel m_dummy_range,
+ p PTR);
+NEWMODE is_cb_debug_array = ARRAY (0:20) is_cb_debug;
+DCL cb_debug is_cb_debug_array;
+DCL cb_debug_index INT := 0;
+
+p: PROC (pp is_str_descr IN, x m_dummy_range IN)
+ DO WITH cb_debug(cb_debug_index);
+ channel := x;
+ OD;
+END p;
+
+p (des, dummy_10);
+WRITETEXT (stdout, "cb_debug(%C).channel := %C%/",
+ cb_debug_index, cb_debug(cb_debug_index).channel);
+
+END markus;
diff --git a/gdb/testsuite/gdb.chill/pr-6632.exp b/gdb/testsuite/gdb.chill/pr-6632.exp
new file mode 100644
index 00000000000..03e342cbc25
--- /dev/null
+++ b/gdb/testsuite/gdb.chill/pr-6632.exp
@@ -0,0 +1,66 @@
+# Copyright (C) 1995, 1997 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file was written by Per Bothner. (bothner@cygnus.com)
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+
+if [skip_chill_tests] then { continue }
+
+set testfile2 "pr-6632-grt"
+set srcfile2 ${srcdir}/$subdir/${testfile2}.ch
+set objfile2 ${objdir}/$subdir/${testfile2}.o
+if { [compile "${srcfile2} -g -c -o ${objfile2}"] != "" } {
+ perror "Couldn't compile ${srcfile2}"
+ return -1
+}
+
+set testfile "pr-6632"
+set srcfile ${srcdir}/$subdir/${testfile}.ch
+set binfile ${objdir}/${subdir}/${testfile}.exe
+if { [compile "${srcfile} ${objfile2} -g -o ${binfile} ${CHILL_RT0} ${CHILL_LIB}"] != "" } {
+ perror "Couldn't compile ${srcfile}"
+ return -1
+}
+
+proc do_tests {} {
+ global prms_id bug_id subdir objdir srcdir binfile gdb_prompt
+
+ set prms_id 0
+ set bug_id 0
+
+ # Start with a fresh gdb.
+
+ gdb_exit
+ gdb_start
+ gdb_reinitialize_dir $srcdir/$subdir
+ gdb_load $binfile
+
+ gdb_test "set language chill" ""
+
+ runto p
+ gdb_test "whatis x" {type = m_dummy_range}
+ gdb_test_exact "ptype x" {type = m_dummy (dummy_6:dummy_22)}
+ gdb_test "print x" { = dummy_10}
+}
+
+do_tests
diff --git a/gdb/testsuite/gdb.chill/pr-8134.exp b/gdb/testsuite/gdb.chill/pr-8134.exp
new file mode 100644
index 00000000000..5bbd66cbefc
--- /dev/null
+++ b/gdb/testsuite/gdb.chill/pr-8134.exp
@@ -0,0 +1,65 @@
+# Copyright (C) 1995, 1997 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file was written by Per Bothner. (bothner@cygnus.com)
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+if [skip_chill_tests] then { continue }
+
+# Note we use pr-8136.ch for pr-8134.exp as well as pr-8136.exp.
+set testfile2 "func1"
+set srcfile2 ${srcdir}/$subdir/${testfile2}.ch
+set objfile2 ${objdir}/$subdir/${testfile2}.o
+if { [compile "${srcfile2} -g -c -o ${objfile2}"] != "" } {
+ perror "Couldn't compile ${srcfile2}"
+ return -1
+}
+
+set testfile "pr-8134"
+set srcfile ${srcdir}/$subdir/pr-8136.ch
+set binfile ${objdir}/${subdir}/${testfile}.exe
+if { [compile "${srcfile} -g ${objfile2} -o ${binfile} ${CHILL_RT0} ${CHILL_LIB}"] != "" } {
+ perror "Couldn't compile ${srcfile}"
+ return -1
+}
+
+proc do_tests {} {
+ global prms_id bug_id subdir objdir srcdir binfile gdb_prompt
+
+ set prms_id 0
+ set bug_id 0
+
+ # Start with a fresh gdb.
+
+ gdb_exit
+ gdb_start
+ gdb_reinitialize_dir $srcdir/$subdir
+ gdb_load $binfile
+
+ gdb_test "set language chill" ""
+
+ runto p1
+ gdb_test "print first" "= 1"
+ gdb_test "print last" "= 10"
+}
+
+do_tests
diff --git a/gdb/testsuite/gdb.chill/pr-8136.ch b/gdb/testsuite/gdb.chill/pr-8136.ch
new file mode 100644
index 00000000000..b380110eb18
--- /dev/null
+++ b/gdb/testsuite/gdb.chill/pr-8136.ch
@@ -0,0 +1,34 @@
+-- NOTE: This test is used for pr-3134.exp as well as pr-8136.
+func: MODULE
+
+<> USE_SEIZE_FILE "func1.grt" <>
+SEIZE ALL;
+
+NEWMODE m_struct = STRUCT (i LONG, str CHARS(50) VARYING);
+DCL insarr ARRAY (1:10) INT;
+
+DCL setrange m_setrange := e5;
+
+DCL ps m_ps := [ e3, e7:e9 ];
+DCL range_ps m_rangeps := [ 2, 3, 4, 28 ];
+
+p1: PROC (first INT IN, last INT IN, s m_struct IN);
+
+ DCL foo LONG := 3;
+
+ startall: PROC ()
+ DO FOR i := first to last;
+ insarr(i) := i;
+ OD;
+ DO FOR i := first TO last;
+ WRITETEXT (stdout, "insarr(%C) := %C%/", i, insarr(i));
+ OD;
+ END startall;
+
+ startall ();
+
+END p1;
+
+p1 (LOWER (insarr), UPPER (insarr), [ 10, "This is a string." ]);
+
+END func;
diff --git a/gdb/testsuite/gdb.chill/pr-8136.exp b/gdb/testsuite/gdb.chill/pr-8136.exp
new file mode 100644
index 00000000000..7bf360c9290
--- /dev/null
+++ b/gdb/testsuite/gdb.chill/pr-8136.exp
@@ -0,0 +1,63 @@
+# Copyright (C) 1995, 1997 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file was written by Per Bothner. (bothner@cygnus.com)
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+if [skip_chill_tests] then { continue }
+
+set testfile2 "func1"
+set srcfile2 ${srcdir}/$subdir/${testfile2}.ch
+set objfile2 ${objdir}/$subdir/${testfile2}.o
+if { [compile "${srcfile2} -g -c -o ${objfile2}"] != "" } {
+ perror "Couldn't compile ${srcfile2}"
+ return -1
+}
+
+set testfile "pr-8136"
+set srcfile ${srcdir}/$subdir/pr-8136.ch
+set binfile ${objdir}/${subdir}/${testfile}.exe
+if { [compile "${srcfile} -g ${objfile2} -o ${binfile} ${CHILL_RT0} ${CHILL_LIB}"] != "" } {
+ perror "Couldn't compile ${srcfile}"
+ return -1
+}
+
+proc do_tests {} {
+ global prms_id bug_id subdir objdir srcdir binfile gdb_prompt
+
+ set prms_id 0
+ set bug_id 0
+
+ # Start with a fresh gdb.
+
+ gdb_exit
+ gdb_start
+ gdb_reinitialize_dir $srcdir/$subdir
+ gdb_load $binfile
+
+ gdb_test "set language chill" ""
+
+ runto p1
+ gdb_test "print ps" {= \[e3, e7:e9\]}
+}
+
+do_tests
diff --git a/gdb/testsuite/gdb.chill/pr-8405.ch b/gdb/testsuite/gdb.chill/pr-8405.ch
new file mode 100644
index 00000000000..a9b25312d6e
--- /dev/null
+++ b/gdb/testsuite/gdb.chill/pr-8405.ch
@@ -0,0 +1,19 @@
+emptybit: MODULE
+
+SYNMODE b8 = BOOLS(8);
+SYN bit8 b8 = B'00000000';
+
+SYNMODE char_m = CHARS(40) VARYING;
+
+SYNMODE stru_m = STRUCT (c char_m, b b8, boo BOOL);
+DCL xx stru_m;
+
+SYNMODE m_stru = STRUCT (c char_m, i LONG, boo BOOL);
+DCL yy m_stru;
+
+SYNMODE m_arr = ARRAY (1:10) LONG;
+DCL zz m_arr;
+
+WRITETEXT (stdout, "%C%/", bit8);
+
+END emptybit;
diff --git a/gdb/testsuite/gdb.chill/pr-8405.exp b/gdb/testsuite/gdb.chill/pr-8405.exp
new file mode 100644
index 00000000000..dff230e7c82
--- /dev/null
+++ b/gdb/testsuite/gdb.chill/pr-8405.exp
@@ -0,0 +1,61 @@
+# Copyright (C) 1995, 1997 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file was written by Per Bothner. (bothner@cygnus.com)
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+proc do_tests {} {
+ global prms_id bug_id subdir objdir srcdir binfile gdb_prompt
+
+ set prms_id 0
+ set bug_id 0
+
+ # Start with a fresh gdb.
+
+ gdb_exit
+ gdb_start
+ gdb_load $binfile
+
+ gdb_test "set language chill" ""
+ gdb_test "set var \$i:=xx" ""
+ gdb_test "print \$i" {= \[.c: "", .b: B'00000000', .boo: FALSE\]}
+}
+
+if [skip_chill_tests] then { continue }
+
+# Check to see if we have an executable to test. If not, then either we
+# haven't tried to compile one, or the compilation failed for some reason.
+# In either case, just notify the user and skip the tests in this file.
+
+set testfile "pr-8405"
+set srcfile ${srcdir}/$subdir/${testfile}.ch
+set binfile ${objdir}/${subdir}/${testfile}.exe
+if { [compile "${srcfile} -g -w -o ${binfile} ${CHILL_RT0} ${CHILL_LIB}"] != "" } {
+ perror "Couldn't compile ${srcfile}"
+ return -1
+}
+
+if ![file exists $binfile] then {
+ warning "$binfile does not exist; tests suppressed." 0
+} else {
+ do_tests
+}
diff --git a/gdb/testsuite/gdb.chill/pr-8742.ch b/gdb/testsuite/gdb.chill/pr-8742.ch
new file mode 100644
index 00000000000..0541149978e
--- /dev/null
+++ b/gdb/testsuite/gdb.chill/pr-8742.ch
@@ -0,0 +1,32 @@
+hugo : module
+
+ synmode a = range(1:10);
+ synmode p = powerset a;
+
+ synmode s = set (sa, sb, sc);
+ synmode s_ps = powerset s;
+
+ x: proc (ps p);
+ dcl i a;
+ do for i in ps;
+ writetext (stdout, "%C ", i);
+ od;
+ writetext(stdout, "%/");
+ end x;
+
+ y : proc (ps s_ps);
+ dcl i s;
+ do for i in ps;
+ writetext (stdout, "%C ", i);
+ od;
+ writetext(stdout, "%/");
+ end y;
+
+ dummy: proc ();
+ end dummy;
+
+ x([1,2,3]);
+ y([sa, sc]);
+ dummy ();
+
+end hugo;
diff --git a/gdb/testsuite/gdb.chill/pr-8742.exp b/gdb/testsuite/gdb.chill/pr-8742.exp
new file mode 100644
index 00000000000..ee49c287eaa
--- /dev/null
+++ b/gdb/testsuite/gdb.chill/pr-8742.exp
@@ -0,0 +1,64 @@
+# Copyright (C) 1992, 1997 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file was written by Per Bothner. (bothner@cygnus.com)
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+if [skip_chill_tests] then { continue }
+
+set testfile "pr-8742"
+set srcfile ${srcdir}/$subdir/${testfile}.ch
+set binfile ${objdir}/${subdir}/${testfile}.exe
+if { [compile "${srcfile} -g -o ${binfile} ${CHILL_RT0} ${CHILL_LIB}"] != "" } {
+ perror "Couldn't compile ${srcfile}"
+ return -1
+}
+
+proc do_tests {} {
+ global prms_id bug_id subdir objdir srcdir binfile gdb_prompt
+
+ set prms_id 0
+ set bug_id 0
+
+ # Start with a fresh gdb.
+
+ gdb_exit
+ gdb_start
+ gdb_reinitialize_dir $srcdir/$subdir
+ gdb_load $binfile
+
+ gdb_test "set language chill" ""
+
+ runto dummy
+
+ # Haven't investigated why these fail on mips-sgi-irix*
+ setup_xfail "m68*-*-hpux*" "mips*-sgi-irix*"
+ gdb_test {call x(p [1, 3, 5])} "1 3 5 " "pass int powerset tuple"
+ setup_xfail "mips*-sgi-irix*"
+ gdb_test {call y(s_ps [sc])} "sc " "pass set powerset tuple"
+ setup_xfail "m68*-*-hpux*" "mips*-sgi-irix*"
+ gdb_test {call x([1, 3, 5])} "1 3 5 " "pass modeless int powerset tuple"
+ setup_xfail "mips*-sgi-irix*"
+ gdb_test {call y([sc])} "sc " "pass modeless set powerset tuple"
+}
+
+do_tests
diff --git a/gdb/testsuite/gdb.chill/pr-8894-grt.ch b/gdb/testsuite/gdb.chill/pr-8894-grt.ch
new file mode 100644
index 00000000000..572017053d0
--- /dev/null
+++ b/gdb/testsuite/gdb.chill/pr-8894-grt.ch
@@ -0,0 +1,6 @@
+yy: MODULE
+
+SYNMODE m_byte = INT (0:255);
+GRANT ALL;
+
+END yy;
diff --git a/gdb/testsuite/gdb.chill/pr-8894.ch b/gdb/testsuite/gdb.chill/pr-8894.ch
new file mode 100644
index 00000000000..391d56b2fc0
--- /dev/null
+++ b/gdb/testsuite/gdb.chill/pr-8894.ch
@@ -0,0 +1,12 @@
+xx: MODULE
+
+<> USE_SEIZE_FILE "pr-8894-grt.grt" <>
+SEIZE m_byte;
+
+SYNMODE m_struct = STRUCT (a, b, c m_byte);
+
+DCL v m_struct;
+
+v.a := 100;
+
+END xx;
diff --git a/gdb/testsuite/gdb.chill/pr-8894.exp b/gdb/testsuite/gdb.chill/pr-8894.exp
new file mode 100644
index 00000000000..adef6f63325
--- /dev/null
+++ b/gdb/testsuite/gdb.chill/pr-8894.exp
@@ -0,0 +1,61 @@
+# Copyright (C) 1996, 1997 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+if [skip_chill_tests] then { continue }
+
+set testfile2 "pr-8894-grt"
+set srcfile2 ${srcdir}/$subdir/${testfile2}.ch
+set objfile2 ${objdir}/$subdir/${testfile2}.o
+if { [compile "${srcfile2} -g -c -o ${objfile2}"] != "" } {
+ perror "Couldn't compile ${srcfile2}"
+ return -1
+}
+
+set testfile "pr-8894"
+set srcfile ${srcdir}/$subdir/$testfile.ch
+set binfile ${objdir}/${subdir}/${testfile}.exe
+if { [compile "${srcfile} -g ${objfile2} -o ${binfile} ${CHILL_RT0} ${CHILL_LIB}"] != "" } {
+ perror "Couldn't compile ${srcfile}"
+ return -1
+}
+
+proc do_tests {} {
+ global prms_id bug_id subdir objdir srcdir binfile gdb_prompt
+
+ set prms_id 0
+ set bug_id 0
+
+ # Start with a fresh gdb.
+
+ gdb_exit
+ gdb_start
+ gdb_reinitialize_dir $srcdir/$subdir
+ gdb_load $binfile
+
+ gdb_test "set language chill" ""
+
+ gdb_test "print size(m_byte)" { = 2}
+ gdb_test "print size(m_struct)" { = 6}
+}
+
+do_tests
diff --git a/gdb/testsuite/gdb.chill/pr-9095.ch b/gdb/testsuite/gdb.chill/pr-9095.ch
new file mode 100644
index 00000000000..61ffb700fbe
--- /dev/null
+++ b/gdb/testsuite/gdb.chill/pr-9095.ch
@@ -0,0 +1,13 @@
+gdb1: MODULE
+
+SYNMODE m_arr1 = ARRAY (1:10) UBYTE;
+SYNMODE m_struct = STRUCT ( i LONG,
+ p REF m_arr1);
+SYNMODE m_arr2 = ARRAY (0:10) REF m_struct;
+
+DCL v_arr1 m_arr1 INIT := [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ];
+DCL v_struct m_struct INIT := [ 10, ->v_arr1 ];
+DCL v_arr2 m_arr2 INIT := [ (5): ->v_struct, (ELSE): NULL ];
+
+WRITETEXT (stdout, "v_arr2(5)->.p->(5) = %C%/", v_arr2(5)->.p->(5));
+END gdb1;
diff --git a/gdb/testsuite/gdb.chill/pr-9095.exp b/gdb/testsuite/gdb.chill/pr-9095.exp
new file mode 100644
index 00000000000..4c5ce97d150
--- /dev/null
+++ b/gdb/testsuite/gdb.chill/pr-9095.exp
@@ -0,0 +1,62 @@
+# Copyright (C) 1996, 1997 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file was written by Per Bothner. (bothner@cygnus.com)
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+proc do_tests {} {
+ global prms_id bug_id subdir objdir srcdir binfile gdb_prompt
+
+ set prms_id 0
+ set bug_id 0
+
+ # Start with a fresh gdb.
+
+ gdb_exit
+ gdb_start
+ gdb_load $binfile
+
+ gdb_test "set language chill" ""
+ runto pr-9095.ch:12
+ gdb_test {p v_arr2(5)->.p(5)} "reference value used as function" \
+ "bad call using pointer"
+}
+
+if [skip_chill_tests] then { continue }
+
+# Check to see if we have an executable to test. If not, then either we
+# haven't tried to compile one, or the compilation failed for some reason.
+# In either case, just notify the user and skip the tests in this file.
+
+set testfile "pr-9095"
+set srcfile ${srcdir}/$subdir/${testfile}.ch
+set binfile ${objdir}/${subdir}/${testfile}.exe
+if { [compile "${srcfile} -g -w -o ${binfile} ${CHILL_RT0} ${CHILL_LIB}"] != "" } {
+ perror "Couldn't compile ${srcfile}"
+ return -1
+}
+
+if ![file exists $binfile] then {
+ warning "$binfile does not exist; tests suppressed." 0
+} else {
+ do_tests
+}
diff --git a/gdb/testsuite/gdb.chill/pr-9946.ch b/gdb/testsuite/gdb.chill/pr-9946.ch
new file mode 100644
index 00000000000..3d9210a5b8d
--- /dev/null
+++ b/gdb/testsuite/gdb.chill/pr-9946.ch
@@ -0,0 +1,10 @@
+x: module
+
+synmode aset = SET (stopped, moving);
+
+DCL xyz aset;
+
+xyz := moving;
+xyz := SUCC (xyz);
+
+END x;
diff --git a/gdb/testsuite/gdb.chill/pr-9946.exp b/gdb/testsuite/gdb.chill/pr-9946.exp
new file mode 100644
index 00000000000..b6b592f4344
--- /dev/null
+++ b/gdb/testsuite/gdb.chill/pr-9946.exp
@@ -0,0 +1,79 @@
+# Copyright (C) 1995, 1997 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file was written by Fred Fish. (fnf@cygnus.com)
+# Martin Pottendorfer (pottendo@aut.alcatel.at)
+#
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+if [skip_chill_tests] then { continue }
+
+set testfile "pr-9946"
+set srcfile ${srcdir}/$subdir/${testfile}.ch
+set binfile ${objdir}/${subdir}/${testfile}.exe
+if { [compile "${srcfile} -g -o ${binfile} ${CHILL_RT0} ${CHILL_LIB}"] != "" } {
+ perror "Couldn't compile ${srcfile}"
+ return -1
+}
+
+# Set the current language to chill. This counts as a test. If it
+# fails, then we skip the other tests.
+
+proc set_lang_chill {} {
+ global gdb_prompt
+ global binfile objdir subdir
+
+ verbose "loading file '$binfile'"
+ gdb_load $binfile
+
+ send_gdb "set language chill\n"
+ gdb_expect {
+ -re ".*$gdb_prompt $" {}
+ timeout { fail "set language chill (timeout)" ; return 0 }
+ }
+
+ return [gdb_test "show language" ".* source language is \"chill\".*" \
+ "set language to \"chill\""]
+}
+
+set prms_id 0
+set bug_id 0
+
+# Start with a fresh gdb.
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+
+gdb_test "set print sevenbit-strings" ".*"
+
+if ![set_lang_chill] then {
+ runto x_
+ gdb_test "next" ""
+ # check comparison of SET's
+ gdb_test {print xyz=moving} { = TRUE}
+ gdb_test {print xyz/=moving} { = FALSE}
+ gdb_test {print xyz<moving} { = FALSE}
+ gdb_test {print xyz<=moving} { = TRUE}
+ gdb_test {print xyz>moving} { = FALSE}
+ gdb_test {print xyz>=moving} { = TRUE}
+}
diff --git a/gdb/testsuite/gdb.chill/result.ch b/gdb/testsuite/gdb.chill/result.ch
new file mode 100644
index 00000000000..b8c65e7d085
--- /dev/null
+++ b/gdb/testsuite/gdb.chill/result.ch
@@ -0,0 +1,29 @@
+test_result: MODULE
+
+ DCL i INT := 5;
+
+ SYNMODE m_struct = STRUCT (l LONG, b BOOL);
+ DCL v_struct m_struct := [ 20, TRUE ];
+
+ simple_func: PROC () RETURNS (INT);
+ DCL j INT := i;
+ RESULT 10;
+ i + := 2;
+ RESULT j + 2;
+ i + := 2;
+ END simple_func;
+
+ ret_struct: PROC () RETURNS (m_struct)
+ DCL v m_struct := [ 33, FALSE ];
+ RESULT v;
+ v.l := 18;
+ END ret_struct;
+
+ i := simple_func ();
+ i := simple_func ();
+ i * := 10;
+
+ v_struct := ret_struct ();
+
+ i := 33; -- for gdb
+END test_result;
diff --git a/gdb/testsuite/gdb.chill/result.exp b/gdb/testsuite/gdb.chill/result.exp
new file mode 100644
index 00000000000..64ca33529c8
--- /dev/null
+++ b/gdb/testsuite/gdb.chill/result.exp
@@ -0,0 +1,77 @@
+# Copyright (C) 1994, 1997 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file was written by Per Bothner. (bothner@cygnus.com)
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+if [skip_chill_tests] then { continue }
+
+set testfile "result"
+set srcfile ${srcdir}/$subdir/${testfile}.ch
+set binfile ${objdir}/${subdir}/${testfile}.exe
+if { [compile "${srcfile} -g -o ${binfile} ${CHILL_RT0} ${CHILL_LIB}"] != "" } {
+ perror "Couldn't compile ${srcfile}"
+ return -1
+}
+
+proc do_tests {} {
+ global prms_id bug_id subdir objdir srcdir binfile gdb_prompt
+
+ set prms_id 0
+ set bug_id 0
+
+ # Start with a fresh gdb.
+
+ gdb_exit
+ gdb_start
+ gdb_reinitialize_dir $srcdir/$subdir
+ gdb_load $binfile
+
+ gdb_test "set language chill" ""
+
+ gdb_test "set width 0" ""
+ gdb_test "set print sevenbit-strings" ""
+ gdb_test "set print address off" ""
+
+ # simple function
+ runto simple_func
+ gdb_test "step 2" ""
+ gdb_test "print j" "= 5"
+ gdb_test "p RESULT" "= 10"
+ gdb_test "continue" ""
+ gdb_test "print i" "= 7"
+ gdb_test "step 4" ""
+ gdb_test "set RESULT := 50" ""
+ gdb_test "finish" ""
+ gdb_test "step" ""
+ gdb_test "print i" "= 50"
+
+ # returning a structure
+ runto ret_struct
+ gdb_test "step 2" ""
+ gdb_test "p result" {\[.l: 33, .b: FALSE\]}
+ gdb_test "set var result := \[383, TRUE\]" ""
+ gdb_test "finish" ""
+ gdb_test "p v_struct" {\[.l: 383, .b: TRUE\]}
+}
+
+do_tests
diff --git a/gdb/testsuite/gdb.chill/string.ch b/gdb/testsuite/gdb.chill/string.ch
new file mode 100644
index 00000000000..3503c462eae
--- /dev/null
+++ b/gdb/testsuite/gdb.chill/string.ch
@@ -0,0 +1,24 @@
+ss: MODULE
+
+/* These declarations are from Cygnus PR chill/9078. */
+ SYNMODE m_char20 = CHARS(20) VARYING;
+
+ DCL foo m_char20 INIT := "Moser ";
+ DCL bar m_char20 INIT := "Wilfried";
+
+ DCL foo1 CHARS(5) INIT := "12345";
+ DCL bar1 CHARS(5) INIT := "abcde";
+
+/* This is Cynus PR chill/5696. */
+
+DCL s20 CHARS(20) VARYING;
+
+DCL s10 CHARS(10);
+
+
+s20 := "Moser Wilfried";
+S10 := "1234567890";
+
+WRITETEXT (stdout, "s20 := ""%C"", s10 := ""%C""%/", s20, s10);
+
+END ss;
diff --git a/gdb/testsuite/gdb.chill/string.exp b/gdb/testsuite/gdb.chill/string.exp
new file mode 100644
index 00000000000..dabd7e90a7f
--- /dev/null
+++ b/gdb/testsuite/gdb.chill/string.exp
@@ -0,0 +1,73 @@
+# Copyright (C) 1995, 1997 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+if [skip_chill_tests] then { continue }
+
+set testfile "string"
+set srcfile ${srcdir}/$subdir/${testfile}.ch
+set binfile ${objdir}/${subdir}/${testfile}.exe
+if { [compile "${srcfile} -g -o ${binfile} ${CHILL_RT0} ${CHILL_LIB}"] != "" } {
+ perror "Couldn't compile ${srcfile}"
+ return -1
+}
+
+proc do_tests {} {
+ global prms_id bug_id subdir objdir srcdir binfile gdb_prompt
+
+ set prms_id 0
+ set bug_id 0
+
+ # Start with a fresh gdb.
+
+ gdb_exit
+ gdb_start
+ gdb_reinitialize_dir $srcdir/$subdir
+ gdb_load $binfile
+
+ gdb_test "set language chill" ""
+
+ # These tests based on Cygnus PR chill/5696.
+ runto string.ch:22
+ gdb_test "p s20" { = "Moser Wilfried"} "print simple vstring"
+ gdb_test "p s20(1)" { = 'o'} "print vstring element"
+ gdb_test "p s20(1:3)" { = "ose"} "print vstring slice (:)"
+ gdb_test "p s20(2 up 3)" { = "ser"} "print vstring slice (up)"
+ gdb_test "p s10" { = "1234567890"} "print simple string"
+ gdb_test "p s10(1)" { = '2'} "print string element"
+ gdb_test "p s10(1:3)" { = "234"} "print string slice (:)"
+ gdb_test "p s10(2 up 3)" { = "345"} "print string slice (up)"
+
+ gdb_test "p length(s10)" { = 10} "print string length"
+ gdb_test "p length(s20)" { = 14} "print varying string length"
+ gdb_test "p lower(s10)" { = 0} "print string lower"
+ gdb_test "p upper(s10)" { = 9} "print string upper"
+ gdb_test "p lower(s20)" { = 0} "print varying string lower"
+ gdb_test "p upper(s20)" { = 19} "print varying string upper"
+
+ # These tests are based on Cygnus PR chill/9078.
+ gdb_test "print foo // bar" { = "Moser Wilfried"}
+ gdb_test "print foo // bar1" { = "Moser abcde"}
+ gdb_test "print foo1 // bar1" { = "12345abcde"}
+}
+
+do_tests
diff --git a/gdb/testsuite/gdb.chill/tests1.ch b/gdb/testsuite/gdb.chill/tests1.ch
new file mode 100644
index 00000000000..b545d072a27
--- /dev/null
+++ b/gdb/testsuite/gdb.chill/tests1.ch
@@ -0,0 +1,240 @@
+-- Copyright (C) 1992, 1995 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. */
+
+-- Please email any bugs, comments, and/or additions to this file to:
+-- bug-gdb@prep.ai.mit.edu
+
+--
+-- test program 1 (refer to tests1.exp)
+--
+
+/* These functions are defined in libchill.a */
+
+runtime: SPEC MODULE
+DCL chill_argc long;
+DCL chill_argv REF ARRAY (0:1000) REF CHARS (1000) VARYING;
+__print_event: PROC (arg0 ptr,
+ arg1 ptr) END;
+__print_buffer: PROC (arg0 ptr,
+ arg1 ptr) END;
+GRANT ALL;
+END;
+
+tests1: module;
+
+seize __print_event,
+ __print_buffer;
+
+newmode set1 = set(aaa, bbb, ccc);
+newmode nset1 = set(na = 1, nb = 34, nc = 20);
+newmode r11 = range (0 : upper(ubyte));
+newmode r12 = range (0 : upper(uint));
+--newmode r13 = range (0 : upper(ulong)); -- bug in gnuchill
+newmode r14 = range (lower(byte) : upper(byte));
+newmode r15 = range (lower(int) : upper(int));
+newmode r16 = range (lower(long): upper(long));
+newmode r2 = set1(bbb : ccc);
+newmode r3 = nset1(na : na);
+newmode r4 = nset1(nc : nb);
+newmode r5 = nset1(lower(nset1) : upper(nset1));
+
+newmode pm1 = powerset set(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10);
+newmode pm2 = powerset byte (1:8);
+newmode pm3 = powerset int (-32768:32767);
+newmode pm4 = powerset long (-32768:32768);
+newmode pm5 = powerset long (lower(long):upper(long));
+newmode ref1 = ref pm1;
+newmode ref2 = ref byte;
+newmode ref3 = ptr;
+synmode ref4 = ptr;
+synmode syn_int = int;
+
+newmode prm1 = proc ();
+newmode prm2 = proc (bool in, int out, long inout) returns (char);
+newmode prm3 = proc (pm1, ref1 loc) returns (ref3);
+newmode prm4 = proc () exceptions(ex1, ex2, ex3);
+newmode prm5 = proc (r11, r16 inout, r5 out) returns (r2) exceptions (ex1);
+
+newmode ev1m = event;
+newmode ev2m = event (42);
+
+newmode bu1m = buffer ref1;
+newmode bu2m = buffer (42) ubyte;
+
+newmode strm1 = char (5);
+synmode strm2 = char (7) varying;
+
+synmode bstr1 = bit(20);
+--newmode bstr2 = bit(10) varying;
+
+newmode arr1m = array(1:100) set1;
+newmode arr2m = array(1:100, 1:100) set1;
+newmode arr3m = array(r11, r12, r14) set1;
+newmode arr4m = array(r2) array (r3) array (r4, r5) pm1;
+newmode arr5m = array(1:10) int;
+newmode arr6m = array(1:5, 1:3, 1:2) long;
+
+newmode stru1m = struct (a, b long,
+ case b of
+ (42): ch1 chars(20),
+ (52): ch2 chars(10)
+ else ch3 chars(1)
+ esac);
+
+newmode stru2m = struct (f set1,
+ case f of
+ (aaa): ch1 char(20),
+ (bbb): ch2 char(10) varying
+ else ch3 char(0) varying
+ esac);
+newmode stru3m = struct (f r3,
+ case f of
+ (na): ch1 char(20)
+ esac);
+newmode stru4m = struct (i long,
+ case of
+ : i1, i11 int,
+ b1 bool,
+ c1 char,
+ : i2, i22 long,
+ bs2 bools (10),
+ :
+ s3 struct (i3 int,
+ case of
+ : foo long
+ else bar char
+ esac)
+ else
+ x stru2m
+ esac,
+ y stru3m);
+
+synmode m_xyzmode = struct (next ref m_xyzmode,
+ i long);
+
+-- set mode locations
+dcl s1l set1 := ccc;
+dcl s2l nset1 := nb;
+
+-- range mode locations
+dcl rl1 r11 := 3;
+dcl rl2 r11 := lower(r11);
+dcl rl3 r11 := upper(r11);
+
+dcl rl5 r12 := 65530;
+dcl rl6 r12 := lower(r12);
+dcl rl7 r12 := upper(r12);
+
+--dcl rl9 r13 := 128;
+--dcl rl10 r13 := lower(r13);
+--dcl rl11 r13 := upper(r13);
+
+dcl rl13 r14 := -121;
+dcl rl14 r14 := lower(r14);
+dcl rl15 r14 := upper(r14);
+
+dcl rl17 r15 := -32720;
+dcl rl18 r15 := lower(r15);
+dcl rl19 r15 := upper(r15);
+
+dcl rl21 r16 := 2147483643;
+dcl rl22 r16 := lower(r16);
+dcl rl23 r16 := upper(r16);
+
+-- powerset mode locations
+dcl pl1 pm1 := [p1:p10];
+dcl pl2 pm1 := [];
+dcl pl3 pm1 := [p1, p10];
+dcl pl4 pm1 := [p1:p2, p4:p6, p8:p10];
+dcl pl5 pm1 := [p1:p4, p6, p8:p10];
+dcl pl6 pm1 := [p1, p3:p8, p10];
+
+dcl pl7 pm2 := [1:8];
+dcl pl8 pm3 := [-32768:32767];
+--dcl pl9 pm5 := [-2147483648:2147483647];
+
+-- reference mode locations
+dcl ref3l ref3;
+dcl ref4l ref4;
+dcl ref5l, ref6l, ref7l, ref8l ptr;
+dcl syn_intl1 syn_int := 42;
+dcl intl1 int := -42;
+
+-- synchronization mode locations
+dcl ev1l ev1m;
+dcl ev2l ev2m;
+dcl bu1l bu1m;
+dcl bu2l bu2m;
+
+-- timing mode locations
+dcl til1 time;
+
+-- string mode locations
+dcl strl1, strl2 strm2;
+dcl bstrl1 bstr1 := B'10101010101010101010';
+
+-- array mode locations
+dcl arrl1 arr1m;
+dcl arrl2 arr5m := [1, -1, 32767, -32768, 0, 10, 11, 12, 13, 42];
+dcl arrl3 arr6m := [(1:5): [(1:3): [(1:2): -2147483648]]];
+dcl arrl4 arr6m := [(1:2): [(1:3): [(1:2): -2147483648]],
+ (3): [(1:3): [(1:2): 100]],
+ (4:5): [(1:3): [(1:2): -2147483648]]];
+dcl arrl5 array(1:10) nset1;
+
+-- structure mode locations
+dcl strul1 stru1m := [-2147483648, 42, "12345678900987654321"];
+
+dummyfunc: proc();
+end dummyfunc;
+
+ref3l:=->pl1; -- newmode ref
+ref4l:=->pl1; -- synmode ref
+ref5l:=->pl1; -- ptr
+
+ref6l:=->syn_intl1; -- ref to synmode
+ref7l:=->intl1; -- ref to predefined mode
+ref8l:=->pl1; -- ref to newmode
+
+strl1 := "ha" // C'6e' // "s" // "i" // C'00';
+strl2 := C'00' // "ope";
+
+__print_event(addr(ev1l), addr("ev1l"));
+__print_event(addr(ev2l), addr("ev2l"));
+__print_buffer(addr(bu1l), addr("bu1m"));
+__print_buffer(addr(bu2l), addr("bu2m"));
+
+til1 := abstime(1970, 3, 12, 10, 43, 0);
+writetext(stdout, "lower(pm3) = %C; upper(pm3) = %C%..%/",
+ lower(pm3), upper(pm3));
+writetext(stdout, "lower(pm5) = %C; upper(pm5) = %C%..%/",
+ lower(pm5), upper(pm5));
+--writetext(stdout, "lower(pl9) = %C; upper(pl9) = %C%..%/",
+-- lower(pl9), upper(pl9));
+writetext(stdout, "date = %C%..%/", til1);
+
+writetext(stdout, "slice1 = %C%..%/", strl1(3 : 5));
+writetext(stdout, "slice2 = %C%..%/", strl2(0 : 3));
+--writetext(stdout, "slice3 = %C%..%/", strl1(0 up 20));
+writetext(stdout, "slice4 = %C%..%/", bstrl1(0));
+--writetext(stdout, "slice5 = %C%..%/", arrl3(1:5));
+
+
+writetext(stdout, "done.%/");
+
+dummyfunc();
+
+end tests1;
diff --git a/gdb/testsuite/gdb.chill/tests1.exp b/gdb/testsuite/gdb.chill/tests1.exp
new file mode 100644
index 00000000000..3ede1eb08bd
--- /dev/null
+++ b/gdb/testsuite/gdb.chill/tests1.exp
@@ -0,0 +1,822 @@
+# Copyright (C) 1995, 1997 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file tests various Chill values, expressions, and types.
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+if [skip_chill_tests] then { continue }
+
+set testfile "tests1"
+set srcfile ${srcdir}/$subdir/${testfile}.ch
+set binfile ${objdir}/${subdir}/${testfile}.exe
+if { [compile "${srcfile} -g -w -o ${binfile} ${CHILL_RT0} ${CHILL_LIB}"] != "" } {
+ perror "Couldn't compile ${srcfile}"
+ return -1
+}
+
+# Set the current language to chill. This counts as a test. If it
+# fails, then we skip the other tests.
+
+proc set_lang_chill {} {
+ global gdb_prompt
+ global binfile objdir subdir
+
+ verbose "loading file '$binfile'"
+ gdb_load $binfile
+ send_gdb "set language chill\n"
+ gdb_expect {
+ -re ".*$gdb_prompt $" {}
+ timeout { fail "set language chill (timeout)" ; return 0 }
+ }
+
+ send_gdb "show language\n"
+ gdb_expect {
+ -re ".* source language is \"chill\".*$gdb_prompt $" {
+ pass "set language to \"chill\""
+ send_gdb "break dummyfunc\n"
+ gdb_expect {
+ -re ".*$gdb_prompt $" {
+ send_gdb "run\n"
+ gdb_expect -re ".*$gdb_prompt $" {}
+ return 1
+ }
+ timeout {
+ fail "can't set breakpoint (timeout)"
+ return 0
+ }
+ }
+ }
+ -re ".*$gdb_prompt $" {
+ fail "setting language to \"chill\""
+ return 0
+ }
+ timeout {
+ fail "can't show language (timeout)"
+ return 0
+ }
+ }
+}
+
+# Testing printing of a specific value. Increment passcount for
+# success or issue fail message for failure. In both cases, return
+# a 1 to indicate that more tests can proceed. However a timeout
+# is a serious error, generates a special fail message, and causes
+# a 0 to be returned to indicate that more tests are likely to fail
+# as well.
+#
+# Args are:
+#
+# First one is string to send_gdb to gdb
+# Second one is string to match gdb result to
+# Third one is an optional message to be printed
+
+proc test_print_accept { args } {
+ global gdb_prompt
+ global passcount
+ global verbose
+
+ if [llength $args]==3 then {
+ set message [lindex $args 2]
+ } else {
+ set message [lindex $args 0]
+ }
+ set sendthis [lindex $args 0]
+ set expectthis [lindex $args 1]
+ set result [gdb_test $sendthis ".* = ${expectthis}" $message]
+ if $result==0 {incr passcount}
+ return $result
+}
+
+# Testing printing of a specific value. Increment passcount for
+# success or issue fail message for failure. In both cases, return
+# a 1 to indicate that more tests can proceed. However a timeout
+# is a serious error, generates a special fail message, and causes
+# a 0 to be returned to indicate that more tests are likely to fail
+# as well.
+
+# various tests if modes are treated correctly
+# using ptype
+proc test_modes {} {
+ global passcount
+
+ verbose "testing chill modes"
+ set passcount 0
+
+ # discrete modes
+ test_print_accept "ptype BYTE" "byte"
+ test_print_accept "ptype UBYTE" "ubyte"
+ test_print_accept "ptype INT" "int"
+ test_print_accept "ptype UINT" "uint"
+ test_print_accept "ptype LONG" "long"
+ test_print_accept "ptype ULONG" "ulong"
+ test_print_accept "ptype BOOL" "bool"
+ test_print_accept "ptype CHAR" "char"
+
+ test_print_accept "ptype set1" "SET \[(\]aaa, bbb, ccc\[)\]" \
+ "print unnumbered set mode"
+ test_print_accept "ptype nset1" "SET \[(\]na = 1, nb = 34, nc = 20\[)\]" \
+ "print numbered set mode"
+
+ # mp:
+ # display maybe in hex values ?
+ #
+ test_print_accept "ptype r11" "ubyte \\(0:255\\)" \
+ "print ubyte range mode"
+ test_print_accept "ptype r12" "uint \\(0:65535\\)" \
+ "print uint range mode"
+# test_print_accept "ptype r13" "ulong \\(0:4294967295\\)" \
+# "print ulong range mode"
+ test_print_accept "ptype r14" "byte \\(-128:127\\)" \
+ "print byte range mode"
+ test_print_accept "ptype r15" "int \\(-32768:32767\\)" \
+ "print int range mode"
+ test_print_accept "ptype r16" "long \\(-2147483648:2147483647\\)" \
+ "print long range mode"
+
+ test_print_accept "ptype r2" "set1 \\(bbb:ccc\\)" \
+ "print unnumbered set range mode"
+ test_print_accept "ptype r3" "nset1 \\(na:na\\)" \
+ "print numbered set range mode"
+ # really this order ?
+ # I'm not sure what should happen for the next two tests.
+ setup_xfail "*-*-*"
+ test_print_accept "ptype r4" "nset1 \\(nb = 34:nc = 20\\)" \
+ "print numbered set range mode"
+ setup_xfail "*-*-*"
+ test_print_accept "ptype r5" "nset1 \\(na = 1, nb = 34, nc = 20\\)" \
+ "print numbered set range mode"
+
+ # powerset modes
+ test_print_accept "ptype pm1" \
+ "POWERSET SET \[(\]p1, p2, p3, p4, p5, p6, p7, p8, p9, p10\[)\]" \
+ "print powerset mode 1"
+ test_print_accept "ptype pm2" "POWERSET byte \\(1:8\\)" \
+ "print powerset mode 2"
+ test_print_accept "ptype pm3" "POWERSET int \\(-32768:32767\\)" \
+ "print powerset mode 3"
+ test_print_accept "ptype pm4" "POWERSET long \\(-32768:32768\\)" \
+ "print powerset mode 4"
+ test_print_accept "ptype pm5" \
+ "POWERSET long \\(-2147483648:2147483647\\)" \
+ "print powerset mode 5"
+
+ # reference modes
+ test_print_accept "ptype ref1" "REF pm1" \
+ "print reference to powerset mode"
+ test_print_accept "ptype ref2" "REF byte" \
+ "print reference to byte"
+ test_print_accept "ptype ref3" "PTR" \
+ "print free reference type"
+
+ # procedure modes
+ # FIXME: we have to talk about this ...
+ test_print_accept "ptype prm1" \
+ "REF PROC \[(\]\[)\]" \
+ "print procedure mode 1"
+ setup_xfail "*-*-*"
+ test_print_accept "ptype prm2" \
+ "REF PROC \[(\]bool in, int out long inout\[)\] RETURNS \[(\]char\[)\]" \
+ "print procedure mode 2"
+ setup_xfail "*-*-*"
+ test_print_accept "ptype prm3" \
+ "REF PROC \[(\]pm1, ref loc\[)\] RETURNS \[(\]ref3\[)\]" \
+ "print procedure mode 3"
+ setup_xfail "*-*-*"
+ test_print_accept "ptype prm4" \
+ "\[(\] \[)\] EXCEPTIONS \[(\]ex1, ex2, ex3\[)\]" \
+ "print procedure mode 4"
+ setup_xfail "*-*-*"
+ test_print_accept "ptype prm5" \
+ "REF PROC \[(\]r11, r16 inout, r5 out\[)\] RETURNS \[(\]r2\[)\] EXCEPTIONS \[(\]ex1\[)\]" \
+ "print procedure mode 5"
+
+ # synchronization modes
+ # FIXME: since gdb doesn't process events & buffers so far, this has be
+ # filled later...
+ xfail "synchronization mode handling"
+
+ # timing modes
+ test_print_accept "ptype DURATION" "duration"
+ test_print_accept "ptype TIME" "time"
+
+ # string modes
+ # some tests are done in chillvars.exp
+ test_print_accept "ptype strm1" "CHARS \\(5\\)" "print char string mode"
+ test_print_accept "ptype strm2" "CHARS \[(\]7\[)\] VARYING" \
+ "print varying char string mode"
+ test_print_accept "ptype bstr1" "BOOLS \\(20\\)" "print bit string mode"
+
+ test_print_accept "ptype B'000'" "BOOLS \\(3\\)" "bit string literal"
+ test_print_accept "ptype B'11110000'" "BOOLS \\(8\\)" "bit string literal"
+ # FIXME: adjust error message
+ gdb_test "ptype B'00110211'" {.*Too-large digit.*[.]} \
+ "reject invalid bitstring"
+
+ # array modes
+ # some tests are done in chillvars.exp
+ test_print_accept "ptype arr1m" "ARRAY \\(1:100\\) set1" \
+ "print array mode 1"
+ test_print_accept "ptype arr2m" "ARRAY \\(1:100\\) ARRAY \\(1:100\\) set1"\
+ "print array mode 2"
+ test_print_accept "ptype arr3m" "ARRAY \\(0:255\\) ARRAY \\(0:65535\\) ARRAY \\(-128:127\\) set1" \
+ "print array mode 3"
+ setup_xfail "*-*-*"
+ test_print_accept "ptype arr4m" "ARRAY \\(b:c\\) ARRAY \\(na = 1:na = 1\\) ARRAY \\(nc:nb\\) ARRAY \\(na = 1:nc = 20\\) POWERSET SET \[(\]p1, p2, p3, p4, p5, p6, p7, p8, p9, p10\[)\]" \
+ "print array mode 4"
+
+ # structure modes
+ # some checks are in chillvars.exp
+ # setup_xfail "*-*-*"
+ test_print_accept "ptype stru1m" "STRUCT \\(.*a long,.*b long,.*CASE OF.*:.*ch1 CHARS \\(20\\).*:.*ch2 CHARS \\(10\\).*ELSE.*ch3 CHARS \\(1\\).*ESAC.*\\)" \
+ "print structure mode 1"
+ #setup_xfail "*-*-*"
+ test_print_accept "ptype stru2m" "STRUCT \\(.*f set1,.*CASE OF.*:.*ch1 CHARS \\(20\\).*:.*ch2 CHARS \\(10\\) VARYING.*ELSE.*ch3 CHARS \\(0\\) VARYING.*ESAC.*\\)" \
+ "print structure mode 2"
+ #setup_xfail "*-*-*"
+ test_print_accept "ptype stru3m" "STRUCT \\(.*f r3,.*CASE OF.*:.*ch1 CHARS \\(20\\).*ESAC.*\\)" \
+ "print structure mode 3"
+ # setup_xfail "*-*-*"
+ test_print_accept "ptype stru4m" "STRUCT \\(.*i long,.*CASE OF.*:.*i1 int,.*i11 int,.*b1 bool,.*c1 char.*:.*i2 long,.*i22 long,.*bs2 BOOLS \\(10\\).*:.*s3 STRUCT \\(.*i3 int,.*CASE OF.*:.*foo long.*ELSE.*bar char.*ESAC.*\\).*ELSE.*x stru2m.*ESAC,.*y stru3m.*\\)" \
+ "print structure mode 4"
+
+
+ if $passcount then {
+ pass "$passcount correct modes printed"
+ }
+}
+
+# various tests if locations are treated correctly
+# read access using ptype, print, whatis
+proc test_locations {} {
+ global passcount
+
+ set passcount 0
+ verbose "testing read access to locations"
+ # various location tests can be found in chillvars.exp
+
+ # set locations
+ test_print_accept "ptype s1l" "SET \\(aaa, bbb, ccc\\)" \
+ "print mode of set location"
+ test_print_accept "whatis s1l" "set1" \
+ "print modename of set location"
+ test_print_accept "print s1l" "ccc" "print set location"
+ test_print_accept "ptype s2l" "SET \\(na = 1, nb = 34, nc = 20\\)" \
+ "print mode of numbered set location"
+ test_print_accept "whatis s2l" "nset1" \
+ "print mode name of numbered set location"
+ test_print_accept "print s2l" "nb" "print numberes set location"
+
+ # range modes
+ test_print_accept "ptype rl1" "ubyte \\(0:255\\)" \
+ "print mode of range location"
+ test_print_accept "whatis rl1" "r11" \
+ "print mode name of range location"
+ test_print_accept "print rl1" "3" \
+ "print range location"
+
+ test_print_accept "ptype rl2" "ubyte \\(0:255\\)" \
+ "print mode of range location"
+ test_print_accept "whatis rl2" "r11" \
+ "print mode name of range location"
+ test_print_accept "print rl2" "0" \
+ "print range location"
+
+ test_print_accept "ptype rl3" "ubyte \\(0:255\\)" \
+ "print mode of range location"
+ test_print_accept "whatis rl3" "r11" \
+ "print mode name of range location"
+ test_print_accept "print rl3" "255" \
+ "print range location"
+
+ test_print_accept "ptype rl5" "uint \\(0:65535\\)" \
+ "print mode of range location"
+ test_print_accept "whatis rl5" "r12" \
+ "print mode name of range location"
+ test_print_accept "print rl5" "65530" \
+ "print range location"
+
+ test_print_accept "ptype rl6" "uint \\(0:65535\\)" \
+ "print mode of range location"
+ test_print_accept "whatis rl6" "r12" \
+ "print mode name of range location"
+ test_print_accept "print rl6" "0" \
+ "print range location"
+
+ test_print_accept "ptype rl7" "uint \\(0:65535\\)" \
+ "print mode of range location"
+ test_print_accept "whatis rl7" "r12" \
+ "print mode name of range location"
+ test_print_accept "print rl7" "65535" \
+ "print range location"
+
+# test_print_accept "ptype rl9" "ulong \\(0:4294967295\\)" \
+# "print mode of range location"
+# test_print_accept "whatis rl9" "r13" \
+# "print mode name of range location"
+# test_print_accept "print rl9" "128" \
+# "print range location"
+
+# test_print_accept "ptype rl10" "ulong \\(0:4294967295\\)" \
+# "print mode of range location"
+# test_print_accept "whatis rl10" "r13" \
+# "print mode name of range location"
+# test_print_accept "print rl10" "0" \
+# "print range location"
+
+# test_print_accept "ptype rl11" "ulong \\(0:4294967295\\)" \
+# "print mode of range location"
+# test_print_accept "whatis rl11" "r13" \
+# "print mode name of range location"
+# test_print_accept "print rl11" "4294967295" \
+# "print range location"
+
+ test_print_accept "ptype rl13" "byte \\(-128:127\\)" \
+ "print mode of range location"
+ test_print_accept "whatis rl13" "r14" \
+ "print mode name of range location"
+ test_print_accept "print rl13" "-121" \
+ "print range location"
+
+ test_print_accept "ptype rl14" "byte \\(-128:127\\)" \
+ "print mode of range location"
+ test_print_accept "whatis rl14" "r14" \
+ "print mode name of range location"
+ test_print_accept "print rl14" "-128" \
+ "print range location"
+
+ test_print_accept "ptype rl15" "byte \\(-128:127\\)" \
+ "print mode of range location"
+ test_print_accept "whatis rl15" "r14" \
+ "print mode name of range location"
+ test_print_accept "print rl15" "127" \
+ "print range location"
+
+ test_print_accept "ptype rl17" "int \\(-32768:32767\\)" \
+ "print mode of range location"
+ test_print_accept "whatis rl17" "r15" \
+ "print mode name of range location"
+ test_print_accept "print rl17" "-32720" \
+ "print range location"
+
+ test_print_accept "ptype rl18" "int \\(-32768:32767\\)" \
+ "print mode of range location"
+ test_print_accept "whatis rl18" "r15" \
+ "print mode name of range location"
+ test_print_accept "print rl18" "-32768" \
+ "print range location"
+
+ test_print_accept "ptype rl19" "int \\(-32768:32767\\)" \
+ "print mode of range location"
+ test_print_accept "whatis rl19" "r15" \
+ "print mode name of range location"
+ test_print_accept "print rl19" "32767" \
+ "print range location"
+
+ test_print_accept "ptype rl21" "long \\(-2147483648:2147483647\\)" \
+ "print mode of range location"
+ test_print_accept "whatis rl21" "r16" \
+ "print mode name of range location"
+ test_print_accept "print rl21" "2147483643" \
+ "print range location"
+
+ test_print_accept "ptype rl22" "long \\(-2147483648:2147483647\\)" \
+ "print mode of range location"
+ test_print_accept "whatis rl22" "r16" \
+ "print mode name of range location"
+ test_print_accept "print rl22" "-2147483648" \
+ "print range location"
+
+ test_print_accept "ptype rl23" "long \\(-2147483648:2147483647\\)" \
+ "print mode of range location"
+ test_print_accept "whatis rl23" "r16" \
+ "print mode name of range location"
+ test_print_accept "print rl23" "2147483647" \
+ "print range location"
+
+ # powerset locations
+ test_print_accept "ptype pl1" \
+ "POWERSET SET \\(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10\\)" \
+ "print mode of powerset location 1"
+ test_print_accept "whatis pl1" "pm1" \
+ "print mode mode name of powerset location"
+ test_print_accept "print pl1" \
+ "\[\[\]p1:p10\[\]\]" \
+ "print powerset location 1"
+ test_print_accept "print pl2" {\[\]} \
+ "print powerset location 2"
+ test_print_accept "print pl3" "\[\[\]p1, p10\[\]\]" \
+ "print powerset location 3"
+ test_print_accept "print pl4" {\[p1:p2, p4:p6, p8:p10\]} \
+ "print powerset location 4"
+ test_print_accept "print pl5" {\[p1:p4, p6, p8:p10\]} \
+ "print powerset location 5"
+ test_print_accept "print pl6" {\[p1, p3:p8, p10\]} \
+ "print powerset location 6"
+
+ test_print_accept "ptype pl7" \
+ "POWERSET byte \\(1:8\\)" \
+ "print mode of byte powerset location"
+ test_print_accept "whatis pl7" "pm2" \
+ "print modename of byte powerset location"
+ test_print_accept "print pl7" {\[1:8\]} \
+ "print powerset location 7"
+
+ test_print_accept "ptype pl8" \
+ "POWERSET int \\(-32768:32767\\)" \
+ "print mode of int powerset location"
+ test_print_accept "whatis pl8" "pm3" \
+ "print modename of int powerset location"
+ test_print_accept "print pl8" {\[-32768:32767\]} \
+ "print powerset location 8"
+
+# test_print_accept "ptype pl9" \
+# "POWERSET long \\(-2147483648:2147483647\\)" \
+# "print mode of long powerset location"
+# test_print_accept "whatis pl9" "pm5" \
+# "print modename of long powerset location"
+# test_print_accept "print pl9" {\[-2147483648:2147483647\]} \
+# "print powerset location 9"
+
+ # reference modes
+ test_print_accept "ptype ref3l" "PTR" "print mode of reference location"
+ # setup_xfail "*-*-*"
+ test_print_accept "whatis ref3l" "ref3" \
+ "print modename of reference location"
+ # setup_xfail "*-*-*"
+ test_print_accept "print ref3l" "ref3\\(H'.*\\)" \
+ "print reference location"
+ test_print_accept "ptype ref4l" "PTR" "print mode of reference location"
+ # setup_xfail "*-*-*"
+ test_print_accept "whatis ref4l" "ref4" \
+ "print modename of reference location"
+ # setup_xfail "*-*-*"
+ test_print_accept "print ref4l" "ref4\\(H'.*\\)" \
+ "print reference location"
+ test_print_accept "ptype ref5l" "PTR" "print mode of reference location"
+ test_print_accept "whatis ref5l" "PTR" \
+ "print modename of reference location"
+ test_print_accept "print ref5l" "PTR\\(H'.*\\)" \
+ "print reference location"
+
+ # dereference a little bit..
+ test_print_accept "print ref6l->syn_int" "42" \
+ "dereference reference to synmode location"
+ test_print_accept "print ref7l->int" "-42" \
+ "dereference reference to predefined mode location"
+ test_print_accept "print ref8l->pm1" \
+ "\[\[\]p1:p10\[\]\]" \
+ "dereference reference to newmode location"
+
+ # synchronization mode locations
+ # FIXME: synchronization modes are not supported so far...
+ xfail "no synchronization mode location support, not implemented yet"
+
+ # timing mode locations
+ # FIXME: callbacks to abstime, inttime not implemented
+ xfail "timing modes not implemented properly yet"
+
+ # char string locations
+ # some tests are don in chillvars.exp
+ test_print_accept "ptype strl1" \
+ "CHARS \\(7\\) VARYING" \
+ "print varying string location"
+ test_print_accept "whatis strl1" "strm2" \
+ "print string locationa mode name"
+ test_print_accept "print strl1" \
+ {\"hansi\^\(0\)\"} \
+ "print string location"
+ # string elements
+ test_print_accept "print strl1(0)" "\'h\'" \
+ "print string element 1"
+ test_print_accept "print strl1(5)" {'\^[(]0[)]'} \
+ "print string element 2"
+ test_print_accept "print strl1(3)" "\'s\'" \
+ "print string element 3"
+ test_print_accept "ptype strl1(0)" "char" \
+ "print mode of string element"
+ # slices
+ test_print_accept "print strl1(3:4)" "\"si\"" \
+ "print string slice 1"
+ test_print_accept "print strl1(0:5)" \
+ {\"hansi\^\(0\)\"} \
+ "print string slice 2"
+ test_print_accept "print strl1(0:0)" "\"h\"" \
+ "print string slice 3"
+ test_print_accept "print strl1(0 up 6)" \
+ {\"hansi\^\(0\)\"} \
+ "print string slice 4"
+ # FIXME: adjust error message, when implented
+ gdb_test "print strl1(6 up 1)" \
+ ".*slice.*out of range.*" \
+ "print invalid string slice length"
+ gdb_test "print strl1(-1 up 5)" \
+ ".*slice.*out of range.*" \
+ "print invalid string slice length"
+ gdb_test "print strl1(-1:5)" \
+ ".*slice.*out of range.*" \
+ "print invalid string slice"
+ gdb_test "print strl1(-1:7)" \
+ ".*slice.*out of range.*" \
+ "print invalid string slice"
+ gdb_test "print strl1(0 up -1)" \
+ ".*slice.*out of range.*" \
+ "print invalid string slice length"
+ gdb_test "print strl1(0 up 0)" {""}
+
+ # bitstring locations
+ test_print_accept "ptype bstr1" \
+ "BOOLS \\(20\\)" \
+ "print mode of bitstring location"
+ test_print_accept "whatis bstrl1" "bstr1" \
+ "print mode name of bitstring location"
+ test_print_accept "print bstrl1" \
+ "B'10101010101010101010'" \
+ "print bitstring location"
+
+ test_print_accept "ptype bstrl1(0)" "bool|BOOL" \
+ "print mode of bitstring element"
+ test_print_accept "print bstrl1(0)" "TRUE" \
+ "print bitstring element 1"
+ test_print_accept "print bstrl1(19)" "FALSE" \
+ "print bitstring element 2"
+ test_print_accept "print bstrl1(10)" "TRUE" \
+ "print bitstring element 3"
+
+ test_print_accept "print bstrl1(0:19)" \
+ "B'10101010101010101010'" \
+ "print bitstring location slice 1"
+ test_print_accept "print bstrl1(0:0)" \
+ "B'1'" \
+ "print bitstring location slice 2"
+ test_print_accept "print bstrl1(3:9)" \
+ "B'0101010'" \
+ "print bitstring location slice 3"
+ test_print_accept "print bstrl1(0 up 20)" \
+ "B'10101010101010101010'" \
+ "print bitstring location slice 4"
+ test_print_accept "print bstrl1(19 up 1)" \
+ "B'0'" \
+ "print bitstring location slice 5"
+ gdb_test "print bstrl1(20 up 1)" \
+ ".*slice out of range.*" \
+ "print invalid bitstring slice (20 up 1)"
+ gdb_test "print bstrl1(-4:5)" \
+ ".*slice out of range.*" \
+ "print invalid bitstring slice (-4:5)"
+ gdb_test "print bstrl1(-1:up 1)" \
+ ".*invalid expression syntax.*" \
+ "print invalid bitstring slice (-1:ip 1)"
+ gdb_test "print bstrl1(-1:20)" \
+ ".*slice out of range.*" \
+ "print invalid bitstring slice (-1:20)"
+ gdb_test "print bstrl1(0 up -1)" \
+ ".*slice out of range.*" \
+ "print invalid bitstring slice (0 up -1)"
+ test_print_accept "print bstrl1(4 up 0)" "B''"
+
+ # array mode locations
+ gdb_test_exact "ptype arrl1" \
+ "ARRAY (1:100) set1" \
+ "print mode of array location"
+ gdb_test "whatis arrl1" "arr1m" \
+ "print mode name of array location"
+ gdb_test_exact "print arrl1" {[(1:100): aaa]} \
+ "print array location"
+ test_print_accept "ptype arrl1(1)" \
+ "SET \\(aaa, bbb, ccc\\)" \
+ "print mode of array element"
+ gdb_test_exact "print arrl3" \
+ {[(1:5): [(1:3): [(1:2): -2147483648]]]} \
+ "print array location 2"
+ gdb_test_exact "print arrl3(1)" \
+ {[(1:3): [(1:2): -2147483648]]} \
+ "print array location 3"
+ gdb_test_exact "ptype arrl3(1)" \
+ {ARRAY (1:3) ARRAY (1:2) long} \
+ "print mode of array element"
+ test_print_accept "print arrl3(5)" \
+ {\[\(1:3\): \[\(1:2\): -2147483648\]\]} \
+ "print array location 4"
+ test_print_accept "print arrl3(1,1)" \
+ {\[\(1:2\): -2147483648\]} \
+ "print array location 5"
+ test_print_accept "ptype arrl3(1,1)" \
+ {ARRAY \(1:2\) long} \
+ "print mode of array element"
+ test_print_accept "print arrl3(5,3)" \
+ {\[\(1:2\): -2147483648\]} \
+ "print array location 6"
+ test_print_accept "print arrl3(1,1,1)" \
+ "-2147483648" \
+ "print array location 7"
+ test_print_accept "print arrl3(5,3,2)" \
+ "-2147483648" \
+ "print array location 8"
+ test_print_accept "print arrl3(1)(3)(2)" \
+ "-2147483648" \
+ "print array location 9"
+
+ # reject the following range fails
+ # FIXME: adjust error messages
+ gdb_test "print arrl3(-1)" \
+ ".*out of range.*" \
+ "check invalid array indices 1"
+ gdb_test "print arrl3(6)" \
+ ".*out of range.*" \
+ "check invalid array indices 2"
+ gdb_test "print arrl3(0,0)" \
+ ".*out of range.*" \
+ "check invalid array indices 3"
+ gdb_test "print arrl3(1,0)" \
+ ".*out of range.*" \
+ "check invalid array indices 4"
+ gdb_test "print arrl3(1,4)" \
+ ".*out of range.*" \
+ "check invalid array indices 5"
+ gdb_test "print arrl3(6,4)" \
+ ".*out of range.*" \
+ "check invalid array indices 6"
+ gdb_test "print arrl3(1,1,0)" \
+ ".*out of range.*" \
+ "check invalid array indices 7"
+ gdb_test "print arrl3(6,4,0)" \
+ ".*out of range.*" \
+ "check invalid array indices 8"
+ gdb_test "print arrl3(1,1,3)" \
+ ".*out of range.*" \
+ "check invalid array indices 9"
+
+ gdb_test "print arrl3(0)(0)" \
+ ".* array or string index out of range.*" \
+ "check invalid array indices 10"
+ gdb_test "print arrl3(1)(0)" \
+ ".* array or string index out of range.*" \
+ "check invalid array indices 11"
+ gdb_test "print arrl3(1)(4)" \
+ ".* array or string index out of range.*" \
+ "check invalid array indices 12"
+ gdb_test "print arrl3(6)(4)" \
+ ".* array or string index out of range.*" \
+ "check invalid array indices 13"
+ gdb_test "print arrl3(1)(1)(0)" \
+ ".* array or string index out of range.*" \
+ "check invalid array indices 14"
+ gdb_test "print arrl3(6)(4)(0)" \
+ ".* array or string index out of range.*" \
+ "check invalid array indices 15"
+ gdb_test "print arrl3(1)(1)(3)" \
+ ".* array or string index out of range.*" \
+ "check invalid array indices 16"
+
+ # slices
+ test_print_accept "print arrl4(1:3)" \
+ {\[\(1:2\): \[\(1:3\): \[\(1:2\): -2147483648\]\], \(3\): \[\(1:3\): \[\(1:2\): 100\]\]\]} \
+ "print array slice 1"
+ test_print_accept "ptype arrl4(1:3)" \
+ {ARRAY \(1:3\) ARRAY \(1:3\) ARRAY \(1:2\) long} \
+ "print mode of array slice"
+# The next one is bogus:
+# test_print_accept "print arrl4(5, 2:3, 1)" \
+# # FIXME: maybe the '(1): ' in the inner tupel should be omitted ? \
+# {\[(2): \[\(1\): 100\], \(3\):\[\(1\): 100\]\]} \
+# "print array slice 2"
+ test_print_accept "print arrl4(1 up 4)" \
+ {\[\(1:2\): \[\(1:3\): \[\(1:2\): -2147483648\]\], \(3\): \[\(1:3\): \[\(1:2\): 100\]\], \(4\): \[\(1:3\): \[\(1:2\): -2147483648\]\]\]} \
+ "print array slice 3"
+# The next two are bogus:
+# test_print_accept "print arrl4(3, 2 up 1)" \
+# {\[\(2:3\): \[\(1:2\): 100\]\]} \
+# "print array slice 4"
+# test_print_accept "print arrl4(1:2, 1 up 1, 2)" \
+# {\[\(1\): \[\(1\): \[\(2\): -2147483648\], \(2\): \[\(2\): -2147483648\]\], \(2\): \[\(1\): \[\(2\): -2147483648\], \(2\): \[\(2\): -2147483648\]\]\]} \
+# "print array slice 4"
+ # reject invalid slices
+ # FIXME: adjust error messages
+ gdb_test "print arrl4(5:6)" \
+ ".*slice out of range.*" \
+ "check invalid range 1"
+ gdb_test "print arrl4(0:1)" \
+ ".*slice out of range.*" \
+ "check invalid range 2"
+ gdb_test "print arrl4(0:6)" \
+ ".*slice out of range.*" \
+ "check invalid range 3"
+ gdb_test "print arrl4(3:2)" \
+ ".*slice out of range.*" \
+ "check invalid range 4"
+ gdb_test "print arrl4(1,3:4)" \
+ ".*syntax error.*" \
+ "check invalid range 5"
+ gdb_test "print arrl4(1,0:1)" \
+ ".*syntax error.*" \
+ "check invalid range 6"
+ gdb_test "print arrl4(1,0:4)" \
+ ".*syntax error.*" \
+ "check invalid range 7"
+ gdb_test "print arrl4(1,3:2)" \
+ ".*syntax error.*" \
+ "check invalid range 8"
+ gdb_test "print arrl4(5 up 2)" \
+ ".*slice out of range.*" \
+ "check invalid range 9"
+ gdb_test "print arrl4(-1 up 1)" \
+ ".*slice out of range.*" \
+ "check invalid range 10"
+ gdb_test "print arrl4(-1 up 7)" \
+ ".*slice out of range.*" \
+ "check invalid range 11"
+ gdb_test "print arrl4(1 up 0)" \
+ ".*slice out of range.*" \
+ "check invalid range 12"
+ gdb_test "print arrl4(1,3 up 1)" \
+ ".*syntax error.*" \
+ "check invalid range 13"
+ gdb_test "print arrl4(1,-1 up 1)" \
+ ".*syntax error.*" \
+ "check invalid range 14"
+ gdb_test "print arrl4(1,-1 up 5)" \
+ ".*syntax error.*" \
+ "check invalid range 15"
+ gdb_test "print arrl4(1,2 up 0)" \
+ ".*syntax error.*" \
+ "check invalid range 16"
+
+ # structure modes
+ # some tests are in chillvars.exp
+ # FIXME: no tag processing implemented do maybe adjust these tests
+ setup_xfail "*-*-*"
+ test_print_accept "ptype stru1m" \
+ "STRUCT \\(.*a long,.*b long,.*CASE b OF.*\\(42\\):.*ch1 CHARS\\(20\\),.*\\(52\\):.*ch2 CHARS\\(10\\).*ELSE.*ch3 CHARS\\(1\\).*ESAC.*\\)" \
+ "print mode of structure location 1"
+ test_print_accept "whatis strul1" "stru1m" \
+ "print mode name of structure location 1"
+ setup_xfail "*-*-*"
+ test_print_accept "print strul1" \
+ {\[\.a: -2147483648, \.b: 42, \.\(b\): \{\(42\) = \[\.ch1: \"12345678900987654321\"\], \(52\) = \[\.ch2: \"1234567890\"\], (else) = \[\.ch3: \"1\"\]\}\]} \
+ "print structure location 1"
+ test_print_accept "print strul1.a" \
+ "-2147483648" \
+ "print field of structure location 1"
+ test_print_accept "print strul1.b" "42" \
+ "print field of structure location 1"
+ test_print_accept "print strul1.ch1" \
+ "\"12345678900987654321\"" \
+ "print field of structure location 1"
+ # setup_xfail "*-*-*"
+ test_print_accept "print strul1.ch2" \
+ "\"1234567890\"" \
+ "print field of structure location 1"
+ # setup_xfail "*-*-*"
+ test_print_accept "print strul1.ch3" \
+ "\"1\"" \
+ "print field of structure location 1"
+
+ if $passcount then {
+ pass "$passcount correct locations printed"
+ }
+}
+
+# This is chill/9434
+
+proc test_9434 {} {
+ global passcount
+
+ verbose "testing pr-9434"
+
+ test_print_accept "ptype m_xyzmode" "STRUCT \\(.*next REF m_xyzmode,.*i long.*\\)"
+}
+
+# Start with a fresh gdb.
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+
+gdb_test "set print sevenbit-strings" ".*"
+
+if [set_lang_chill] then {
+ test_modes
+ test_locations
+ test_9434
+} else {
+ warning "$test_name tests suppressed."
+}
diff --git a/gdb/testsuite/gdb.chill/tests2.ch b/gdb/testsuite/gdb.chill/tests2.ch
new file mode 100644
index 00000000000..1596f3b31e8
--- /dev/null
+++ b/gdb/testsuite/gdb.chill/tests2.ch
@@ -0,0 +1,193 @@
+-- Copyright (C) 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. */
+
+-- Please email any bugs, comments, and/or additions to this file to:
+-- bug-gdb@prep.ai.mit.edu
+
+--
+-- test program 2 (refer to tests2.exp)
+--
+
+tests2: module;
+
+-- testpattern
+syn pat1 ulong = H'aaaaaaaa;
+syn pat2 ulong = H'55555555;
+
+-- discrete modes
+newmode bytem = struct (
+ p1 ulong,
+ m byte,
+ p2 ulong);
+newmode ubytem = struct (
+ p1 ulong,
+ m ubyte,
+ p2 ulong);
+newmode intm = struct (
+ p1 ulong,
+ m int,
+ p2 ulong);
+newmode uintm = struct (
+ p1 ulong,
+ m uint,
+ p2 ulong);
+newmode longm = struct (
+ p1 ulong,
+ m long,
+ p2 ulong);
+newmode ulongm = struct (
+ p1 ulong,
+ m ulong,
+ p2 ulong);
+newmode boolm = struct (
+ p1 ulong,
+ m bool,
+ p2 ulong);
+newmode charm1 = struct (
+ p1 ulong,
+ m char(4),
+ p2 ulong);
+newmode charm2 = struct (
+ p1 ulong,
+ m char(7),
+ p2 ulong);
+newmode charm3 = struct (
+ p1 ulong,
+ m char(8) varying,
+ p2 ulong);
+newmode charm4 = struct (
+ p1 ulong,
+ m char,
+ p2 ulong);
+newmode bitm1 = struct (
+ p1 ulong,
+ m bit(8),
+ p2 ulong);
+newmode bitm2 = struct (
+ p1 ulong,
+ m bit(10),
+ p2 ulong);
+newmode setm1 = struct (
+ p1 ulong,
+ m set (a, b, c, d, e, f, g, h),
+ p2 ulong);
+newmode nset1 = struct (
+ p1 ulong,
+ m set (na = 2147483648, nb = 1024, nc = 4294967295),
+ p2 ulong);
+newmode rm1 = struct (
+ p1 ulong,
+ m range (lower(byte):upper(byte)),
+ p2 ulong);
+newmode rm2 = struct (
+ p1 ulong,
+ m range (lower(int):upper(int)),
+ p2 ulong);
+newmode rm3 = struct (
+ p1 ulong,
+ m range (lower(long):upper(long)),
+ p2 ulong);
+newmode pm1 = struct (
+ p1 ulong,
+ m powerset set (pa, pb, pc, pd, pe, pf, pg, ph),
+ p2 ulong);
+newmode pm2 = struct (
+ p1 ulong,
+ m powerset int (1:32),
+ p2 ulong);
+-- this should be rejected by the gnuchill compiler !
+newmode pm3 = struct (
+ p1 ulong,
+-- m powerset long (lower(long): upper(long)),
+ p2 ulong);
+newmode refm1 = struct (
+ p1 ulong,
+ m ptr,
+ p2 ulong);
+newmode refm2 = struct (
+ p1 ulong,
+ m ref bytem,
+ p2 ulong);
+newmode prm1 = struct (
+ p1 ulong,
+ m proc (),
+ p2 ulong);
+newmode tim1 = struct (
+ p1 ulong,
+ m time,
+ p2 ulong);
+newmode tim2 = struct (
+ p1 ulong,
+ m duration,
+ p2 ulong);
+newmode rem1 = struct (
+ p1 ulong,
+ m real,
+ p2 ulong);
+newmode rem2 = struct (
+ p1 ulong,
+ m long_real,
+ p2 ulong);
+newmode arrm1 = struct (
+ p1 ulong,
+ m array(1:3, 1:2) int,
+ p2 ulong);
+newmode strum1 = struct (
+ p1 ulong,
+ m struct (a, b int, ch char(4)),
+ p2 ulong);
+
+
+-- dummyfunction for breakpoints
+dummyfunc: proc();
+end dummyfunc;
+
+
+dcl b1 bytem init := [pat1, -128, pat2];
+dcl ub1 ubytem init := [pat1, 0, pat2];
+dcl i1 intm init := [pat1, -32768, pat2];
+dcl ui1 uintm init := [pat1, 0, pat2];
+dcl l1 longm init := [pat1, -2147483648, pat2];
+dcl ul1 ulongm init := [pat1, 0, pat2];
+dcl bo1 boolm init := [pat1, true, pat2];
+dcl c1 charm1 init := [pat1, "1234", pat2];
+dcl c2 charm2 init := [pat1, "1234567", pat2];
+dcl c3 charm3 init := [pat1, "12345678", pat2];
+dcl c4 charm4 init := [pat1, C'00', pat2];
+dcl bi1 bitm1 init := [pat1, B'01011010', pat2];
+dcl bi2 bitm2 init := [pat1, B'1010110101', pat2];
+dcl se1 setm1 init := [pat1, a, pat2];
+dcl nse1 nset1 init := [pat1, na, pat2];
+dcl r1 rm1 init := [pat1, -128, pat2];
+dcl r2 rm2 init := [pat1, -32768, pat2];
+dcl r3 rm3 init := [pat1, -2147483648, pat2];
+dcl p1 pm1 init := [pat1, [pa], pat2];
+dcl p2 pm2 init := [pat1, [1], pat2];
+-- dcl p3 pm3 init := [pat1, [-1], pat2]; -- FIXME: bug in gnuchill
+dcl ref1 refm1 init := [pat1, null, pat2];
+dcl ref2 refm2 init := [pat1, null, pat2];
+dcl pr1 prm1;
+dcl ti1 tim1 init := [pat1, 0, pat2];
+dcl ti2 tim2 init := [pat1, 0, pat2];
+dcl re1 rem1 init := [pat1, 0.0, pat2];
+dcl re2 rem2 init := [pat1, 0.0, pat2];
+dcl arrl1 arrm1 init:=[pat1, [(1:3): [0,0]], pat2];
+dcl strul1 strum1 init := [pat1, [.a: 0, .b: 0, .ch: "0000"], pat2];
+
+pr1 := [pat1, dummyfunc, pat2];
+dummyfunc();
+
+end tests2;
diff --git a/gdb/testsuite/gdb.chill/tests2.exp b/gdb/testsuite/gdb.chill/tests2.exp
new file mode 100644
index 00000000000..46c4821005a
--- /dev/null
+++ b/gdb/testsuite/gdb.chill/tests2.exp
@@ -0,0 +1,271 @@
+# Copyright (C) 1992, 1995, 1997 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+if [skip_chill_tests] then { continue }
+
+set prms_id 0
+set bug_id 0
+
+# Set the current language to chill. This counts as a test. If it
+# fails, then we skip the other tests.
+
+set testfile "tests2"
+set srcfile ${srcdir}/$subdir/${testfile}.ch
+set binfile ${objdir}/${subdir}/${testfile}.exe
+if { [compile "${srcfile} -g -w -o ${binfile} ${CHILL_RT0} ${CHILL_LIB}"] != "" } {
+ perror "Couldn't compile ${srcfile}"
+ return -1
+}
+
+global infinity
+if [istarget "i*86-*-sysv4*"] then {
+ set infinity "inf"
+} else {
+ set infinity "Infinity"
+}
+
+proc set_lang_chill {} {
+ global gdb_prompt
+ global binfile objdir subdir
+
+ if ![file exists $objdir/$subdir/$binfile] then {
+ return 0
+ }
+ verbose "loading file '$objdir/$subdir/$binfile'"
+ gdb_load $objdir/$subdir/$binfile
+
+ send_gdb "set language chill\n"
+ gdb_expect {
+ -re ".*$gdb_prompt $" {}
+ timeout { fail "set language chill (timeout)" ; return 0 }
+ }
+
+ send_gdb "show language\n"
+ gdb_expect {
+ -re ".* source language is \"chill\".*$gdb_prompt $" {
+ pass "set language to \"chill\""
+ send_gdb "break dummyfunc\n"
+ gdb_expect {
+ -re ".*$gdb_prompt $" {
+ send_gdb "run\n"
+ gdb_expect -re ".*$gdb_prompt $" {}
+ return 1
+ }
+ timeout {
+ fail "can't set breakpoint (timeout)"
+ return 0
+ }
+ }
+ }
+ -re ".*$gdb_prompt $" {
+ fail "setting language to \"chill\""
+ return 0
+ }
+ timeout {
+ fail "can't show language (timeout)"
+ return 0
+ }
+ }
+}
+
+# checks if structure was accessed correctly
+proc test_write { args } {
+ global gdb_prompt
+
+ if [llength $args]==5 then {
+ set message [lindex $args 4]
+ set extended [lindex $args 3]
+ set matchval [lindex $args 2]
+ } elseif [llength $args]==4 then {
+ set message [lindex $args 3]
+ set matchval [lindex $args 2]
+ set extended ""
+ } elseif [llength $args]==3 then {
+ set message [lindex $args 2]
+ set extended ""
+ } else {
+ warning "test ($args) write called with wrong number of arguments"
+ return
+ }
+
+ set location [lindex $args 0]
+ set value [lindex $args 1]
+ if ![info exists matchval] then {
+ set matchval $value
+ }
+ verbose "loc: $location, val: $value, msg: $message, ext: $extended, match: $matchval"
+
+ verbose "setting var $value..."
+ send_gdb "set var $location.m$extended := $value\n"
+ gdb_expect -re ".*$gdb_prompt $" {}
+ gdb_test "print $location" \
+ ".*= \[\[\]\\.p1: 2863311530, \\.m: $matchval, \\.p2: 1431655765\[\]\]"\
+ "$message"
+}
+
+# test write access from gdb (setvar x:=y) from gdb
+proc write_access { } {
+ global infinity
+
+ verbose "testing write access to locations"
+
+ # discrete modes
+ test_write b1 127 "byte write 1"
+ test_write b1 -128 "byte write 2"
+ test_write b1 0 "byte write 3"
+ test_write ub1 255 "ubyte write 1"
+ test_write ub1 0 "ubyte write 2"
+ test_write ub1 42 "ubyte write 3"
+ test_write i1 32767 "int write 1"
+ test_write i1 -32768 "int write 2"
+ test_write i1 0 "int write 3"
+ test_write ui1 65535 "uint write 1"
+ test_write ui1 0 "uint write 2"
+ test_write ui1 123 "uint write 3"
+ test_write l1 2147483647 "long write 1"
+ test_write l1 -2147483648 "long write 2"
+ test_write l1 0 "long write 3"
+ test_write ul1 4294967295 "ulong write 1"
+ test_write ul1 0 "ulong write 2"
+ test_write ul1 1000000 "ulong write 3"
+ test_write bo1 FALSE "bool write 1"
+ test_write bo1 TRUE "bool write 2"
+ test_write c1 \"1234\" "char write 1"
+ test_write c2 \"1234567\" "char write 2"
+ test_write c3 \"654321\" "char write 3"
+ test_write c4 C'65' 'e' "char write 4"
+ test_write bi1 B'10100101' "bitstring write 1"
+ test_write bi2 B'0101001010' "bitstring write 2"
+ test_write se1 a "set write 1"
+ test_write se1 h "set write 2"
+ # The following two use numbered sets with too-large values.
+ setup_xfail "*-*-*"
+ test_write nse1 nb "numbered set write 1"
+ setup_xfail "*-*-*"
+ test_write nse1 nc "numbered set write 2"
+ test_write r1 127 "range write 1"
+ test_write r2 32767 "range write 2"
+ test_write r3 2147483647 "range write 3"
+
+ # powerset modes
+ test_write p1 {[pa:ph]} {\[pa:ph\]} "powerset write 1"
+ test_write p1 {[pa, pc:pf, ph]} {\[pa, pc:pf, ph\]} "powerset write 2"
+ test_write p1 {[pa, pc, pe, pg]} {\[pa, pc, pe, pg\]} "powerset write 3"
+ test_write p1 {[]} {\[\]} "powerset write 4"
+ test_write p2 {[1:32]} {\[1:32\]} "powerset write 5"
+ test_write p2 {[1, 3:30, 32]} {\[1, 3:30, 32\]} "powerset write 6"
+ test_write p2 {[1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31]} {\[1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31\]} \
+ "powerset write 7"
+ test_write p2 {[]} {\[\]} "powerset write 8"
+
+# Fixme: this should be rejected by gnuchill
+# test_write p3 {[-2147483648:2147483647]} {\[-2147483648:2147483647\]} \
+# "powerset write 9"
+# test_write p3 {[-2147483648, -1000000:1000000, 2147483647]} \
+# {\[-2147483648, -1000000:1000000, 2147483647\]} \
+# "powerset write 10"
+# test_write p3 {[-99, -97, -95, 1001, 1003, 1005]} \
+# {\[-99, -97, -95, 1001, 1003, 1005\]} "powerset write 11"
+# test_write p3 {[]} {\[\]} "powerset write 12"
+
+ # reference modes
+ test_write ref1 ->ref1 {H'[0-9a-fA-F]+} "reference write 1"
+ test_write ref2 ->b1 {H'[0-9a-fA-F]+} "reference write 2"
+ test_write ref1 NULL "reference write 3"
+ test_write ref2 NULL "reference write 4"
+
+ # procedure modes
+ test_write pr1 NULL "procefure write 1"
+ # FIXME: remove when NULL is understood
+ test_write pr1 0 NULL "procefure write 2"
+ test_write pr1 dummyfunc {H'[0-9a-fA-F]+ <dummyfunc>} "procedure write 3"
+
+ # timing modes, FIXME when callbacks to timefunctions are implemented
+ #test_write ti1 abstime(1970, 3, 12, 10, 43, 0) {} "time write 1"
+ #test_write ti2 <set somehow a duration>
+ xfail "timing modes not implemented yet"
+
+ # real modes
+ # This ones
+ test_write re1 42.03 {42.0[0-9]*} "real write 1"
+ test_write re1 0 "real write 2"
+ test_write re1 "1e+38" {1e\+38|1\.0[0-9]*e\+38|9\.9[0-9]*e\+37} \
+ "real write 3"
+ setup_xfail "i*86-pc-linux-gnu" "m68*-*-hpux*"
+ test_write re1 "1e+39" $infinity "real write 4"
+ test_write re2 42.03 {42.0[0-9]*} "real write 5"
+ test_write re2 0 "real write 6"
+ test_write re2 "1e+308" {1e\+308} "real write 7"
+ setup_xfail "i*86-pc-linux-gnu" "m68*-*-hpux*"
+ test_write re2 "1e+309" $infinity "real write 8"
+ # array modes
+ test_write arrl1 {[(1:3): [(1:2): -128]]} {\[\(1:3\): \[\(1:2\): -128\]\]}\
+ "array write 1"
+ test_write arrl1 {[(1:3): [(1:2): 0]]} {\[\(1:3\): \[\(1:2\): 0\]\]}\
+ "array write 2"
+ test_write arrl1 {[(1): [(1:2): 127], (2): [(1:2): -128], (3): [(1:2): 127]]} {\[\(1\): \[\(1:2\): 127\], \(2\): \[\(1:2\): -128\], \(3\): \[\(1:2\): 127\]\]}\
+ "array write 3"
+ test_write arrl1 {[(1:3): [(1:2): 0]]} {\[\(1:3\): \[\(1:2\): 0\]\]}\
+ "array write 4"
+ setup_xfail "*-*-*"
+ # Bogus test case - type mismatch?
+ test_write arrl1 {[(1): 127, (2): -128]} "array write 5"
+ test_write arrl1 {[(1:3): [(1:2): 0]]} {\[\(1:3\): \[\(1:2\): 0\]\]}\
+ "array write 6"
+
+ # structure modes
+ test_write strul1 {[.a: -32768, .b: 32767, .ch: "ZZZZ"]} \
+ {\[\.a: -32768, \.b: 32767, \.ch: \"ZZZZ\"\]} \
+ "structure write 1"
+ test_write strul1 {[.a: 0, .b: 0, .ch: "0000"]} \
+ {\[\.a: 0, \.b: 0, \.ch: \"0000\"\]} \
+ "structure write 2"
+ test_write strul1 -32768 {\[\.a: -32768, \.b: 0, \.ch: \"0000\"\]} \
+ {.a} "structure write 3"
+ test_write strul1 {[.a: 0, .b: 0, .ch: "0000"]} \
+ {\[\.a: 0, \.b: 0, \.ch: \"0000\"\]} \
+ "structure write 4"
+ test_write strul1 -32768 {\[\.a: 0, \.b: -32768, \.ch: \"0000\"\]} \
+ {.b} "structure write 5"
+ test_write strul1 {[.a: 0, .b: 0, .ch: "0000"]} \
+ {\[\.a: 0, \.b: 0, \.ch: \"0000\"\]} \
+ "structure write 6"
+ test_write strul1 \"HUGO\" {\[\.a: 0, \.b: 0, \.ch: \"HUGO\"\]} \
+ {.ch} "structure write 7"
+}
+
+# Start with a fresh gdb.
+
+set binfile "tests2.exe"
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+
+gdb_test "set print sevenbit-strings" ".*"
+
+if [set_lang_chill] then {
+ write_access
+} else {
+ warning "$test_name tests suppressed."
+}
diff --git a/gdb/testsuite/gdb.chill/tuples.ch b/gdb/testsuite/gdb.chill/tuples.ch
new file mode 100644
index 00000000000..24709f8fe05
--- /dev/null
+++ b/gdb/testsuite/gdb.chill/tuples.ch
@@ -0,0 +1,86 @@
+x: MODULE
+
+SYNMODE m_arri = ARRAY(1:5) INT;
+DCL v_arri m_arri := [ -1, -2, -3, -4, -5 ];
+
+SYNMODE m_arrui = ARRAY(1:5) UINT;
+DCL v_arrui m_arrui := [ 1, 2, 3, 4, 5 ];
+
+SYNMODE r1 = RANGE (1:5);
+SYNMODE m_arrb = ARRAY(r1) BYTE;
+DCL v_arrb m_arrb := [ -3, -4, -5, -6, -7 ];
+
+SYNMODE m_arrub = ARRAY(r1) UBYTE;
+DCL v_arrub m_arrub := [ 3, 4, 5, 6, 7 ];
+
+SYNMODE m_arrc = ARRAY (1:5) CHAR;
+DCL v_arrc m_arrc := [ '1', '2', '3', '4', '5' ];
+
+SYNMODE m_ps = POWERSET r1;
+DCL v_ps m_ps := [ 1, 3, 5 ];
+
+DCL v_cv CHARS(20) VARYING := "foo";
+
+SYNMODE m_arrbool = ARRAY(r1) BOOL;
+DCL v_arrbool m_arrbool := [ true, false, true, false, true ];
+
+DCL j r1 := 4;
+
+DCL i INT;
+
+newmode vstruct = struct (a, b long,
+ case b of
+ (42): ch8 chars(20),
+ (52): i long
+ else ch1 char
+ esac);
+
+DCL vstr vstruct := [ .a: 10, .b: 52, .i: 100 ];
+
+i := 0;
+
+END x;
+
+setmode: MODULE /* This is from Cygnus PR chill/5024. */
+
+NEWMODE day = SET( monday, tuesday, wednesday, thursday, friday, saturday, sunday );
+NEWMODE dow = POWERSET day;
+
+DCL d day;
+DCL w dow;
+
+printdow: PROC( w dow );
+ DCL d day;
+ DO FOR d in w;
+ WRITETEXT( stdout, "%C ", d );
+ OD;
+END;
+
+d := monday;
+w := dow[monday : friday];
+printdow( w );
+
+printdow( dow[LOWER(dow) : UPPER(dow)] );
+
+END setmode;
+
+PR8643: MODULE
+
+SYNMODE m_set = SET (a, b, c, d);
+SYNMODE m_ps = POWERSET m_set;
+
+SYNMODE m_s1 = STRUCT (str CHARS(40) VARYING, i INT, ps m_ps);
+DCL vs1 m_s1;
+
+SYNMODE m_s2 = STRUCT (i LONG, s m_s1);
+DCL vs2 m_s2;
+
+SYNMODE m_arr = ARRAY (1:3) BYTE;
+SYNMODE m_s3 = STRUCT (i LONG, a m_arr);
+DCL vs3 m_s3;
+
+DCL i LONG;
+
+i := 24;
+
+END PR8643;
diff --git a/gdb/testsuite/gdb.chill/tuples.exp b/gdb/testsuite/gdb.chill/tuples.exp
new file mode 100644
index 00000000000..fbfa9ed0003
--- /dev/null
+++ b/gdb/testsuite/gdb.chill/tuples.exp
@@ -0,0 +1,161 @@
+# Copyright (C) 1995, 1997 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file was written by Per Bothner. (bothner@cygnus.com)
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+if [skip_chill_tests] then { continue }
+
+set testfile "tuples"
+set srcfile ${srcdir}/$subdir/${testfile}.ch
+set binfile ${objdir}/${subdir}/${testfile}.exe
+if { [compile "${srcfile} -g -o ${binfile} ${CHILL_RT0} ${CHILL_LIB}"] != "" } {
+ perror "Couldn't compile ${srcfile}"
+ return -1
+}
+
+proc do_tests {} {
+ global prms_id bug_id subdir objdir srcdir binfile gdb_prompt
+
+ set prms_id 0
+ set bug_id 0
+
+ # Start with a fresh gdb.
+
+ gdb_exit
+ gdb_start
+ gdb_reinitialize_dir $srcdir/$subdir
+ gdb_load $binfile
+
+ gdb_test "set language chill" ""
+
+ runto tuples.ch:40
+
+ gdb_test_exact "print v_arri" {= [(1): -1, (2): -2, (3): -3, (4): -4, (5): -5]}
+ gdb_test_exact "set v_arri := \[ 33, 44, 55, 66, 77 \]" {}
+ gdb_test_exact "print v_arri" {= [(1): 33, (2): 44, (3): 55, (4): 66, (5): 77]} "after assignment 1 to v_arri"
+ gdb_test_exact "set v_arri := \[-33, -44, -55, -66, -77\]" {}
+ gdb_test_exact "print v_arri" {= [(1): -33, (2): -44, (3): -55, (4): -66, (5): -77]} {after assignment 2 to v_arri}
+
+ gdb_test_exact "print v_arrui" {= [(1): 1, (2): 2, (3): 3, (4): 4, (5): 5]}
+ gdb_test_exact "set v_arrui := \[ 11, 11, 11, 11, 11 \]" {}
+ gdb_test_exact "print v_arrui" {= [(1:5): 11]} "after assignment to v_arrui"
+
+ gdb_test_exact "print v_arrb" {= [(1): -3, (2): -4, (3): -5, (4): -6, (5): -7]}
+
+ gdb_test_exact "set v_arrb := \[ -9, -8, -7, -6, -5 \]" {}
+ gdb_test_exact "print v_arrb" {= [(1): -9, (2): -8, (3): -7, (4): -6, (5): -5]} "after assignment to v_arrb"
+
+ gdb_test_exact "print v_arrub" {= [(1): 3, (2): 4, (3): 5, (4): 6, (5): 7]}
+ gdb_test_exact "set v_arrub := \[ 77, 77, 77, 77, 77 \]" {}
+ gdb_test_exact "print v_arrub" {= [(1:5): 77]} "v_arrub after assignment"
+
+ gdb_test_exact "print j" {= 4}
+ gdb_test_exact "print j := 3+4" {= 7}
+ gdb_test_exact "print j := r1(3)" {= 3}
+
+ gdb_test_exact "print v_arrc" {= [(1): '1', (2): '2', (3): '3', (4): '4', (5): '5']}
+ gdb_test_exact "set v_arrc := \[ 'a', 'b', 'c', 'd', 'e' \]" {}
+ gdb_test_exact "print v_arrc" {= [(1): 'a', (2): 'b', (3): 'c', (4): 'd', (5): 'e']} "v_arrc after assignment"
+
+ gdb_test_exact "print v_ps" {= [1, 3, 5]}
+ gdb_test_exact "set v_ps := \[ 2, 4 \]" {}
+ gdb_test_exact "print v_ps" {= [2, 4]} {v_ps after assignment}
+ gdb_test_exact "print v_ps := \[\]" {= []} {assign [] to v_ps}
+
+ gdb_test_exact "print m_arri\[1, 2, 3, 4, 5\]" {= [(1): 1, (2): 2, (3): 3, (4): 4, (5): 5]}
+ gdb_test_exact "print m_arrub\[45, 46, 47, 48, 49\]" {= [(1): 45, (2): 46, (3): 47, (4): 48, (5): 49]}
+
+ gdb_test_exact "print v_cv" {= "foo"}
+ gdb_test_exact "set v_cv := \"foo-bar\"" {}
+ gdb_test_exact "print v_cv" {= "foo-bar"} "v_cv after assignment"
+ gdb_test_exact "set v_cv(3) := ' '" {}
+ gdb_test_exact "print v_cv" {= "foo bar"} "v_cv after element assignment"
+
+ gdb_test_exact "print v_arrbool" {= [(1): TRUE, (2): FALSE, (3): TRUE, (4): FALSE, (5): TRUE]}
+ gdb_test_exact "set v_arrbool := \[ false, false, false, false, false \]" {}
+ gdb_test_exact "print v_arrbool" {= [(1:5): FALSE]} "v_arrbool after assignment 1"
+ gdb_test_exact "set v_arrbool := \[true, true, true, true, true\]" {}
+ gdb_test_exact "print v_arrbool" {= [(1:5): TRUE]} "v_arrbool after assignment 2"
+ gdb_test_exact "set v_arrbool(3) := false" {}
+ gdb_test_exact "print v_arrbool" {= [(1:2): TRUE, (3): FALSE, (4:5): TRUE]} "v_arrbool after element assignment"
+
+ gdb_test_exact "set v_arrbool(1 up 2) := \[ false, true \]" {}
+ gdb_test_exact "print v_arrbool" {= [(1): FALSE, (2): TRUE, (3): FALSE, (4:5): TRUE]} "v_arrbool after slice assignment 1"
+ gdb_test_exact "set v_arrbool(3 : 5) := \[ true, true, false \]" {}
+ gdb_test_exact "print v_arrbool" {= [(1): FALSE, (2:4): TRUE, (5): FALSE]} "v_arrbool after slice assignment 2"
+
+ gdb_test_exact "set vstr := \[ .a: 2+3, .b: 12, .ch1: 'x' \]" {}
+ gdb_test_exact "print vstr.a" {= 5} "vstr.a after assignment"
+ gdb_test_exact "print vstr.ch1" {= 'x'} "vstr.ch1 after assignment"
+
+# These tests are from Cygnus PR chill/5024:
+ gdb_test "break printdow" ""
+ gdb_test "continue" ""
+ gdb_test_exact "set var w:= dow\[monday\]" {}
+ gdb_test "print w" " = \\\[monday\\\]" \
+ "print bitstring after assignment"
+ gdb_test_exact "set var w:=\[\]" {}
+ gdb_test "print w" " = \\\[\\\]" \
+ "print bitstring after assignment of \[\]"
+
+# These tests are from Cygnus PR chill/8643:
+ runto tuples.ch:40
+ gdb_test_exact "set var vs1 := \[ \"foo\", 41, \[ b \] \]" {}
+ gdb_test_exact "print vs1" { = [.str: "foo", .i: 41, .ps: [b]]} \
+ "print vs1 after tuple assign 1"
+ setup_xfail "i*86-pc-linux*-gnu" "sparc-*-solaris*" "sparc-*-sunos*"
+ gdb_test_exact "set var vs1 := \[ \"bar\", 42, m_ps\[ a \] \]" {}
+ setup_xfail "i*86-pc-linux*-gnu" "sparc-*-solaris*" "sparc-*-sunos*"
+ gdb_test_exact "print vs1" { = [.str: "bar", .i: 42, .ps: [a]]} \
+ "print vs1 after tuple assign 2"
+
+ gdb_test_exact "set var \$i := m_s1\[\"foo\", 42, \[a \]\]" {}
+ gdb_test_exact {print $i} { = [.str: "foo", .i: 42, .ps: [a]]} \
+ "print \$i after tuple assign 1"
+ setup_xfail "i*86-pc-linux*-gnu" "sparc-*-solaris*" "sparc-*-sunos*"
+ gdb_test_exact "set var \$i := m_s1\[\"foo\", 44, m_ps\[a \]\]" {}
+ setup_xfail "i*86-pc-linux*-gnu" "sparc-*-solaris*" "sparc-*-sunos*"
+ gdb_test_exact {print $i} { = [.str: "foo", .i: 44, .ps: [a]]} \
+ "print \$i after tuple assign 2"
+
+ gdb_test_exact "set var vs2 := \[ 10, \[ \"foo\" , 42, \[ b \] \] \]" {}
+ gdb_test_exact "print vs2" \
+ { = [.i: 10, .s: [.str: "foo", .i: 42, .ps: [b]]]} \
+ "print vs2 after tuple assign 1"
+ setup_xfail "i*86-pc-linux*-gnu" "sparc-*-solaris*" "sparc-*-sunos*"
+ gdb_test_exact "set var vs2 := \[ 10+3, m_s1\[ \"foo\" , 42, m_ps\[ b \] \] \]" {}
+ setup_xfail "i*86-pc-linux*-gnu" "sparc-*-solaris*" "sparc-*-sunos*"
+ gdb_test_exact "print vs2" \
+ { = [.i: 13, .s: [.str: "foo", .i: 42, .ps: [b]]]} \
+ "print vs2 after tuple assign 2"
+
+ gdb_test_exact "set var vs3 := \[ 33, \[ -1, -2, -3 \] \]" {}
+ gdb_test_exact "print vs3" {[.i: 33, .a: [(1): -1, (2): -2, (3): -3]]} \
+ "print vs3 after tuple assign"
+ gdb_test_exact "set var \$k := m_s3\[ 33, m_arr\[ 4, 3, 2 \] \]" {}
+ gdb_test_exact {print $k} { = [.i: 33, .a: [(1): 4, (2): 3, (3): 2]]} \
+ "print \$k after tuple assign"
+
+}
+
+do_tests
diff --git a/gdb/testsuite/gdb.disasm/Makefile.in b/gdb/testsuite/gdb.disasm/Makefile.in
new file mode 100644
index 00000000000..ab228ddf935
--- /dev/null
+++ b/gdb/testsuite/gdb.disasm/Makefile.in
@@ -0,0 +1,20 @@
+#### host, target, and site specific Makefile frags come in here.
+
+VPATH = @srcdir@
+srcdir = @srcdir@
+
+.PHONY: all clean mostlyclean distclean realclean
+
+all:
+ @echo "Nothing to be done for all..."
+
+clean mostlyclean:
+ -rm -f *.o *.diff *~ *.bad core sh3 hppa mn10200 mn10300
+
+distclean maintainer-clean realclean: clean
+ -rm -f Makefile config.status config.log
+
+Makefile: $(srcdir)/Makefile.in $(srcdir)/configure.in
+ $(SHELL) ./config.status --recheck
+
+
diff --git a/gdb/testsuite/gdb.disasm/configure b/gdb/testsuite/gdb.disasm/configure
new file mode 100644
index 00000000000..0e6cbf20749
--- /dev/null
+++ b/gdb/testsuite/gdb.disasm/configure
@@ -0,0 +1,899 @@
+#! /bin/sh
+
+# Guess values for system-dependent variables and create Makefiles.
+# Generated automatically using autoconf version 2.12.1
+# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc.
+#
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+
+# Defaults:
+ac_help=
+ac_default_prefix=/usr/local
+# Any additions from configure.in:
+
+# Initialize some variables set by options.
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+build=NONE
+cache_file=./config.cache
+exec_prefix=NONE
+host=NONE
+no_create=
+nonopt=NONE
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+target=NONE
+verbose=
+x_includes=NONE
+x_libraries=NONE
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datadir='${prefix}/share'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+libdir='${exec_prefix}/lib'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+infodir='${prefix}/info'
+mandir='${prefix}/man'
+
+# Initialize some other variables.
+subdirs=
+MFLAGS= MAKEFLAGS=
+SHELL=${CONFIG_SHELL-/bin/sh}
+# Maximum number of lines to put in a shell here document.
+ac_max_here_lines=12
+
+ac_prev=
+for ac_option
+do
+
+ # If the previous option needs an argument, assign it.
+ if test -n "$ac_prev"; then
+ eval "$ac_prev=\$ac_option"
+ ac_prev=
+ continue
+ fi
+
+ case "$ac_option" in
+ -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
+ *) ac_optarg= ;;
+ esac
+
+ # Accept the important Cygnus configure options, so we can diagnose typos.
+
+ case "$ac_option" in
+
+ -bindir | --bindir | --bindi | --bind | --bin | --bi)
+ ac_prev=bindir ;;
+ -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+ bindir="$ac_optarg" ;;
+
+ -build | --build | --buil | --bui | --bu)
+ ac_prev=build ;;
+ -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+ build="$ac_optarg" ;;
+
+ -cache-file | --cache-file | --cache-fil | --cache-fi \
+ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+ ac_prev=cache_file ;;
+ -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+ cache_file="$ac_optarg" ;;
+
+ -datadir | --datadir | --datadi | --datad | --data | --dat | --da)
+ ac_prev=datadir ;;
+ -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \
+ | --da=*)
+ datadir="$ac_optarg" ;;
+
+ -disable-* | --disable-*)
+ ac_feature=`echo $ac_option|sed -e 's/-*disable-//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then
+ { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
+ fi
+ ac_feature=`echo $ac_feature| sed 's/-/_/g'`
+ eval "enable_${ac_feature}=no" ;;
+
+ -enable-* | --enable-*)
+ ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then
+ { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
+ fi
+ ac_feature=`echo $ac_feature| sed 's/-/_/g'`
+ case "$ac_option" in
+ *=*) ;;
+ *) ac_optarg=yes ;;
+ esac
+ eval "enable_${ac_feature}='$ac_optarg'" ;;
+
+ -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+ | --exec | --exe | --ex)
+ ac_prev=exec_prefix ;;
+ -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+ | --exec=* | --exe=* | --ex=*)
+ exec_prefix="$ac_optarg" ;;
+
+ -gas | --gas | --ga | --g)
+ # Obsolete; use --with-gas.
+ with_gas=yes ;;
+
+ -help | --help | --hel | --he)
+ # Omit some internal or obsolete options to make the list less imposing.
+ # This message is too long to be a string in the A/UX 3.1 sh.
+ cat << EOF
+Usage: configure [options] [host]
+Options: [defaults in brackets after descriptions]
+Configuration:
+ --cache-file=FILE cache test results in FILE
+ --help print this message
+ --no-create do not create output files
+ --quiet, --silent do not print \`checking...' messages
+ --version print the version of autoconf that created configure
+Directory and file names:
+ --prefix=PREFIX install architecture-independent files in PREFIX
+ [$ac_default_prefix]
+ --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
+ [same as prefix]
+ --bindir=DIR user executables in DIR [EPREFIX/bin]
+ --sbindir=DIR system admin executables in DIR [EPREFIX/sbin]
+ --libexecdir=DIR program executables in DIR [EPREFIX/libexec]
+ --datadir=DIR read-only architecture-independent data in DIR
+ [PREFIX/share]
+ --sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc]
+ --sharedstatedir=DIR modifiable architecture-independent data in DIR
+ [PREFIX/com]
+ --localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var]
+ --libdir=DIR object code libraries in DIR [EPREFIX/lib]
+ --includedir=DIR C header files in DIR [PREFIX/include]
+ --oldincludedir=DIR C header files for non-gcc in DIR [/usr/include]
+ --infodir=DIR info documentation in DIR [PREFIX/info]
+ --mandir=DIR man documentation in DIR [PREFIX/man]
+ --srcdir=DIR find the sources in DIR [configure dir or ..]
+ --program-prefix=PREFIX prepend PREFIX to installed program names
+ --program-suffix=SUFFIX append SUFFIX to installed program names
+ --program-transform-name=PROGRAM
+ run sed PROGRAM on installed program names
+EOF
+ cat << EOF
+Host type:
+ --build=BUILD configure for building on BUILD [BUILD=HOST]
+ --host=HOST configure for HOST [guessed]
+ --target=TARGET configure for TARGET [TARGET=HOST]
+Features and packages:
+ --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
+ --enable-FEATURE[=ARG] include FEATURE [ARG=yes]
+ --with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
+ --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
+ --x-includes=DIR X include files are in DIR
+ --x-libraries=DIR X library files are in DIR
+EOF
+ if test -n "$ac_help"; then
+ echo "--enable and --with options recognized:$ac_help"
+ fi
+ exit 0 ;;
+
+ -host | --host | --hos | --ho)
+ ac_prev=host ;;
+ -host=* | --host=* | --hos=* | --ho=*)
+ host="$ac_optarg" ;;
+
+ -includedir | --includedir | --includedi | --included | --include \
+ | --includ | --inclu | --incl | --inc)
+ ac_prev=includedir ;;
+ -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+ | --includ=* | --inclu=* | --incl=* | --inc=*)
+ includedir="$ac_optarg" ;;
+
+ -infodir | --infodir | --infodi | --infod | --info | --inf)
+ ac_prev=infodir ;;
+ -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+ infodir="$ac_optarg" ;;
+
+ -libdir | --libdir | --libdi | --libd)
+ ac_prev=libdir ;;
+ -libdir=* | --libdir=* | --libdi=* | --libd=*)
+ libdir="$ac_optarg" ;;
+
+ -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+ | --libexe | --libex | --libe)
+ ac_prev=libexecdir ;;
+ -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+ | --libexe=* | --libex=* | --libe=*)
+ libexecdir="$ac_optarg" ;;
+
+ -localstatedir | --localstatedir | --localstatedi | --localstated \
+ | --localstate | --localstat | --localsta | --localst \
+ | --locals | --local | --loca | --loc | --lo)
+ ac_prev=localstatedir ;;
+ -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+ | --localstate=* | --localstat=* | --localsta=* | --localst=* \
+ | --locals=* | --local=* | --loca=* | --loc=* | --lo=*)
+ localstatedir="$ac_optarg" ;;
+
+ -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+ ac_prev=mandir ;;
+ -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+ mandir="$ac_optarg" ;;
+
+ -nfp | --nfp | --nf)
+ # Obsolete; use --without-fp.
+ with_fp=no ;;
+
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c)
+ no_create=yes ;;
+
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+ no_recursion=yes ;;
+
+ -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+ | --oldin | --oldi | --old | --ol | --o)
+ ac_prev=oldincludedir ;;
+ -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+ oldincludedir="$ac_optarg" ;;
+
+ -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+ ac_prev=prefix ;;
+ -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+ prefix="$ac_optarg" ;;
+
+ -program-prefix | --program-prefix | --program-prefi | --program-pref \
+ | --program-pre | --program-pr | --program-p)
+ ac_prev=program_prefix ;;
+ -program-prefix=* | --program-prefix=* | --program-prefi=* \
+ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+ program_prefix="$ac_optarg" ;;
+
+ -program-suffix | --program-suffix | --program-suffi | --program-suff \
+ | --program-suf | --program-su | --program-s)
+ ac_prev=program_suffix ;;
+ -program-suffix=* | --program-suffix=* | --program-suffi=* \
+ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+ program_suffix="$ac_optarg" ;;
+
+ -program-transform-name | --program-transform-name \
+ | --program-transform-nam | --program-transform-na \
+ | --program-transform-n | --program-transform- \
+ | --program-transform | --program-transfor \
+ | --program-transfo | --program-transf \
+ | --program-trans | --program-tran \
+ | --progr-tra | --program-tr | --program-t)
+ ac_prev=program_transform_name ;;
+ -program-transform-name=* | --program-transform-name=* \
+ | --program-transform-nam=* | --program-transform-na=* \
+ | --program-transform-n=* | --program-transform-=* \
+ | --program-transform=* | --program-transfor=* \
+ | --program-transfo=* | --program-transf=* \
+ | --program-trans=* | --program-tran=* \
+ | --progr-tra=* | --program-tr=* | --program-t=*)
+ program_transform_name="$ac_optarg" ;;
+
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ silent=yes ;;
+
+ -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+ ac_prev=sbindir ;;
+ -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+ | --sbi=* | --sb=*)
+ sbindir="$ac_optarg" ;;
+
+ -sharedstatedir | --sharedstatedir | --sharedstatedi \
+ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+ | --sharedst | --shareds | --shared | --share | --shar \
+ | --sha | --sh)
+ ac_prev=sharedstatedir ;;
+ -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+ | --sha=* | --sh=*)
+ sharedstatedir="$ac_optarg" ;;
+
+ -site | --site | --sit)
+ ac_prev=site ;;
+ -site=* | --site=* | --sit=*)
+ site="$ac_optarg" ;;
+
+ -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+ ac_prev=srcdir ;;
+ -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+ srcdir="$ac_optarg" ;;
+
+ -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+ | --syscon | --sysco | --sysc | --sys | --sy)
+ ac_prev=sysconfdir ;;
+ -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+ sysconfdir="$ac_optarg" ;;
+
+ -target | --target | --targe | --targ | --tar | --ta | --t)
+ ac_prev=target ;;
+ -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+ target="$ac_optarg" ;;
+
+ -v | -verbose | --verbose | --verbos | --verbo | --verb)
+ verbose=yes ;;
+
+ -version | --version | --versio | --versi | --vers)
+ echo "configure generated by autoconf version 2.12.1"
+ exit 0 ;;
+
+ -with-* | --with-*)
+ ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then
+ { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
+ fi
+ ac_package=`echo $ac_package| sed 's/-/_/g'`
+ case "$ac_option" in
+ *=*) ;;
+ *) ac_optarg=yes ;;
+ esac
+ eval "with_${ac_package}='$ac_optarg'" ;;
+
+ -without-* | --without-*)
+ ac_package=`echo $ac_option|sed -e 's/-*without-//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then
+ { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
+ fi
+ ac_package=`echo $ac_package| sed 's/-/_/g'`
+ eval "with_${ac_package}=no" ;;
+
+ --x)
+ # Obsolete; use --with-x.
+ with_x=yes ;;
+
+ -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+ | --x-incl | --x-inc | --x-in | --x-i)
+ ac_prev=x_includes ;;
+ -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+ x_includes="$ac_optarg" ;;
+
+ -x-libraries | --x-libraries | --x-librarie | --x-librari \
+ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+ ac_prev=x_libraries ;;
+ -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+ x_libraries="$ac_optarg" ;;
+
+ -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; }
+ ;;
+
+ *)
+ if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then
+ echo "configure: warning: $ac_option: invalid host type" 1>&2
+ fi
+ if test "x$nonopt" != xNONE; then
+ { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; }
+ fi
+ nonopt="$ac_option"
+ ;;
+
+ esac
+done
+
+if test -n "$ac_prev"; then
+ { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; }
+fi
+
+trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
+
+# File descriptor usage:
+# 0 standard input
+# 1 file creation
+# 2 errors and warnings
+# 3 some systems may open it to /dev/tty
+# 4 used on the Kubota Titan
+# 6 checking for... messages and results
+# 5 compiler messages saved in config.log
+if test "$silent" = yes; then
+ exec 6>/dev/null
+else
+ exec 6>&1
+fi
+exec 5>./config.log
+
+echo "\
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+" 1>&5
+
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Also quote any args containing shell metacharacters.
+ac_configure_args=
+for ac_arg
+do
+ case "$ac_arg" in
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c) ;;
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;;
+ *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*)
+ ac_configure_args="$ac_configure_args '$ac_arg'" ;;
+ *) ac_configure_args="$ac_configure_args $ac_arg" ;;
+ esac
+done
+
+# NLS nuisances.
+# Only set these to C if already set. These must not be set unconditionally
+# because not all systems understand e.g. LANG=C (notably SCO).
+# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'!
+# Non-C LC_CTYPE values break the ctype check.
+if test "${LANG+set}" = set; then LANG=C; export LANG; fi
+if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi
+if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi
+if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -rf conftest* confdefs.h
+# AIX cpp loses on an empty file, so make sure it contains at least a newline.
+echo > confdefs.h
+
+# A filename unique to this package, relative to the directory that
+# configure is in, which we can look for to find out if srcdir is correct.
+ac_unique_file=sh3.s
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+ ac_srcdir_defaulted=yes
+ # Try the directory containing this script, then its parent.
+ ac_prog=$0
+ ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'`
+ test "x$ac_confdir" = "x$ac_prog" && ac_confdir=.
+ srcdir=$ac_confdir
+ if test ! -r $srcdir/$ac_unique_file; then
+ srcdir=..
+ fi
+else
+ ac_srcdir_defaulted=no
+fi
+if test ! -r $srcdir/$ac_unique_file; then
+ if test "$ac_srcdir_defaulted" = yes; then
+ { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; }
+ else
+ { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; }
+ fi
+fi
+srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'`
+
+# Prefer explicitly selected file to automatically selected ones.
+if test -z "$CONFIG_SITE"; then
+ if test "x$prefix" != xNONE; then
+ CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site"
+ else
+ CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
+ fi
+fi
+for ac_site_file in $CONFIG_SITE; do
+ if test -r "$ac_site_file"; then
+ echo "loading site script $ac_site_file"
+ . "$ac_site_file"
+ fi
+done
+
+if test -r "$cache_file"; then
+ echo "loading cache $cache_file"
+ . $cache_file
+else
+ echo "creating cache $cache_file"
+ > $cache_file
+fi
+
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then
+ # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu.
+ if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then
+ ac_n= ac_c='
+' ac_t=' '
+ else
+ ac_n=-n ac_c= ac_t=
+ fi
+else
+ ac_n= ac_c='\c' ac_t=
+fi
+
+
+
+CC=${CC-cc}
+
+ac_aux_dir=
+for ac_dir in `cd $srcdir;pwd`/../../.. $srcdir/`cd $srcdir;pwd`/../../..; do
+ if test -f $ac_dir/install-sh; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install-sh -c"
+ break
+ elif test -f $ac_dir/install.sh; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install.sh -c"
+ break
+ fi
+done
+if test -z "$ac_aux_dir"; then
+ { echo "configure: error: can not find install-sh or install.sh in `cd $srcdir;pwd`/../../.. $srcdir/`cd $srcdir;pwd`/../../.." 1>&2; exit 1; }
+fi
+ac_config_guess=$ac_aux_dir/config.guess
+ac_config_sub=$ac_aux_dir/config.sub
+ac_configure=$ac_aux_dir/configure # This should be Cygnus configure.
+
+
+# Do some error checking and defaulting for the host and target type.
+# The inputs are:
+# configure --host=HOST --target=TARGET --build=BUILD NONOPT
+#
+# The rules are:
+# 1. You are not allowed to specify --host, --target, and nonopt at the
+# same time.
+# 2. Host defaults to nonopt.
+# 3. If nonopt is not specified, then host defaults to the current host,
+# as determined by config.guess.
+# 4. Target and build default to nonopt.
+# 5. If nonopt is not specified, then target and build default to host.
+
+# The aliases save the names the user supplied, while $host etc.
+# will get canonicalized.
+case $host---$target---$nonopt in
+NONE---*---* | *---NONE---* | *---*---NONE) ;;
+*) { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; } ;;
+esac
+
+
+# Make sure we can run config.sub.
+if ${CONFIG_SHELL-/bin/sh} $ac_config_sub sun4 >/dev/null 2>&1; then :
+else { echo "configure: error: can not run $ac_config_sub" 1>&2; exit 1; }
+fi
+
+echo $ac_n "checking host system type""... $ac_c" 1>&6
+echo "configure:573: checking host system type" >&5
+
+host_alias=$host
+case "$host_alias" in
+NONE)
+ case $nonopt in
+ NONE)
+ if host_alias=`${CONFIG_SHELL-/bin/sh} $ac_config_guess`; then :
+ else { echo "configure: error: can not guess host type; you must specify one" 1>&2; exit 1; }
+ fi ;;
+ *) host_alias=$nonopt ;;
+ esac ;;
+esac
+
+host=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $host_alias`
+host_cpu=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+host_vendor=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+host_os=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+echo "$ac_t""$host" 1>&6
+
+echo $ac_n "checking target system type""... $ac_c" 1>&6
+echo "configure:594: checking target system type" >&5
+
+target_alias=$target
+case "$target_alias" in
+NONE)
+ case $nonopt in
+ NONE) target_alias=$host_alias ;;
+ *) target_alias=$nonopt ;;
+ esac ;;
+esac
+
+target=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $target_alias`
+target_cpu=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+target_vendor=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+target_os=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+echo "$ac_t""$target" 1>&6
+
+echo $ac_n "checking build system type""... $ac_c" 1>&6
+echo "configure:612: checking build system type" >&5
+
+build_alias=$build
+case "$build_alias" in
+NONE)
+ case $nonopt in
+ NONE) build_alias=$host_alias ;;
+ *) build_alias=$nonopt ;;
+ esac ;;
+esac
+
+build=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $build_alias`
+build_cpu=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+build_vendor=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+build_os=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+echo "$ac_t""$build" 1>&6
+
+test "$host_alias" != "$target_alias" &&
+ test "$program_prefix$program_suffix$program_transform_name" = \
+ NONENONEs,x,x, &&
+ program_prefix=${target_alias}-
+
+
+trap '' 1 2 15
+cat > confcache <<\EOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs. It is not useful on other systems.
+# If it contains results you don't want to keep, you may remove or edit it.
+#
+# By default, configure uses ./config.cache as the cache file,
+# creating it if it does not exist already. You can give configure
+# the --cache-file=FILE option to use a different cache file; that is
+# what configure does when it calls configure scripts in
+# subdirectories, so they share the cache.
+# Giving --cache-file=/dev/null disables caching, for debugging configure.
+# config.status only pays attention to the cache file if you give it the
+# --recheck option to rerun configure.
+#
+EOF
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, don't put newlines in cache variables' values.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(set) 2>&1 |
+ case `(ac_space=' '; set) 2>&1 | grep ac_space` in
+ *ac_space=\ *)
+ # `set' does not quote correctly, so add quotes (double-quote substitution
+ # turns \\\\ into \\, and sed turns \\ into \).
+ sed -n \
+ -e "s/'/'\\\\''/g" \
+ -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p"
+ ;;
+ *)
+ # `set' quotes correctly as required by POSIX, so do not add quotes.
+ sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p'
+ ;;
+ esac >> confcache
+if cmp -s $cache_file confcache; then
+ :
+else
+ if test -w $cache_file; then
+ echo "updating cache $cache_file"
+ cat confcache > $cache_file
+ else
+ echo "not updating unwritable cache $cache_file"
+ fi
+fi
+rm -f confcache
+
+trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+# Any assignment to VPATH causes Sun make to only execute
+# the first set of double-colon rules, so remove it if not needed.
+# If there is a colon in the path, we need to keep it.
+if test "x$srcdir" = x.; then
+ ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d'
+fi
+
+trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15
+
+# Transform confdefs.h into DEFS.
+# Protect against shell expansion while executing Makefile rules.
+# Protect against Makefile macro expansion.
+cat > conftest.defs <<\EOF
+s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%-D\1=\2%g
+s%[ `~#$^&*(){}\\|;'"<>?]%\\&%g
+s%\[%\\&%g
+s%\]%\\&%g
+s%\$%$$%g
+EOF
+DEFS=`sed -f conftest.defs confdefs.h | tr '\012' ' '`
+rm -f conftest.defs
+
+
+# Without the "./", some shells look in PATH for config.status.
+: ${CONFIG_STATUS=./config.status}
+
+echo creating $CONFIG_STATUS
+rm -f $CONFIG_STATUS
+cat > $CONFIG_STATUS <<EOF
+#! /bin/sh
+# Generated automatically by configure.
+# Run this file to recreate the current configuration.
+# This directory was configured as follows,
+# on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+#
+# $0 $ac_configure_args
+#
+# Compiler output produced by configure, useful for debugging
+# configure, is in ./config.log if it exists.
+
+ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]"
+for ac_option
+do
+ case "\$ac_option" in
+ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+ echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion"
+ exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;;
+ -version | --version | --versio | --versi | --vers | --ver | --ve | --v)
+ echo "$CONFIG_STATUS generated by autoconf version 2.12.1"
+ exit 0 ;;
+ -help | --help | --hel | --he | --h)
+ echo "\$ac_cs_usage"; exit 0 ;;
+ *) echo "\$ac_cs_usage"; exit 1 ;;
+ esac
+done
+
+ac_given_srcdir=$srcdir
+
+trap 'rm -fr `echo "Makefile" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15
+EOF
+cat >> $CONFIG_STATUS <<EOF
+
+# Protect against being on the right side of a sed subst in config.status.
+sed 's/%@/@@/; s/@%/@@/; s/%g\$/@g/; /@g\$/s/[\\\\&%]/\\\\&/g;
+ s/@@/%@/; s/@@/@%/; s/@g\$/%g/' > conftest.subs <<\\CEOF
+$ac_vpsub
+$extrasub
+s%@SHELL@%$SHELL%g
+s%@CFLAGS@%$CFLAGS%g
+s%@CPPFLAGS@%$CPPFLAGS%g
+s%@CXXFLAGS@%$CXXFLAGS%g
+s%@DEFS@%$DEFS%g
+s%@LDFLAGS@%$LDFLAGS%g
+s%@LIBS@%$LIBS%g
+s%@exec_prefix@%$exec_prefix%g
+s%@prefix@%$prefix%g
+s%@program_transform_name@%$program_transform_name%g
+s%@bindir@%$bindir%g
+s%@sbindir@%$sbindir%g
+s%@libexecdir@%$libexecdir%g
+s%@datadir@%$datadir%g
+s%@sysconfdir@%$sysconfdir%g
+s%@sharedstatedir@%$sharedstatedir%g
+s%@localstatedir@%$localstatedir%g
+s%@libdir@%$libdir%g
+s%@includedir@%$includedir%g
+s%@oldincludedir@%$oldincludedir%g
+s%@infodir@%$infodir%g
+s%@mandir@%$mandir%g
+s%@CC@%$CC%g
+s%@host@%$host%g
+s%@host_alias@%$host_alias%g
+s%@host_cpu@%$host_cpu%g
+s%@host_vendor@%$host_vendor%g
+s%@host_os@%$host_os%g
+s%@target@%$target%g
+s%@target_alias@%$target_alias%g
+s%@target_cpu@%$target_cpu%g
+s%@target_vendor@%$target_vendor%g
+s%@target_os@%$target_os%g
+s%@build@%$build%g
+s%@build_alias@%$build_alias%g
+s%@build_cpu@%$build_cpu%g
+s%@build_vendor@%$build_vendor%g
+s%@build_os@%$build_os%g
+
+CEOF
+EOF
+
+cat >> $CONFIG_STATUS <<\EOF
+
+# Split the substitutions into bite-sized pieces for seds with
+# small command number limits, like on Digital OSF/1 and HP-UX.
+ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script.
+ac_file=1 # Number of current file.
+ac_beg=1 # First line for current file.
+ac_end=$ac_max_sed_cmds # Line after last line for current file.
+ac_more_lines=:
+ac_sed_cmds=""
+while $ac_more_lines; do
+ if test $ac_beg -gt 1; then
+ sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file
+ else
+ sed "${ac_end}q" conftest.subs > conftest.s$ac_file
+ fi
+ if test ! -s conftest.s$ac_file; then
+ ac_more_lines=false
+ rm -f conftest.s$ac_file
+ else
+ if test -z "$ac_sed_cmds"; then
+ ac_sed_cmds="sed -f conftest.s$ac_file"
+ else
+ ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file"
+ fi
+ ac_file=`expr $ac_file + 1`
+ ac_beg=$ac_end
+ ac_end=`expr $ac_end + $ac_max_sed_cmds`
+ fi
+done
+if test -z "$ac_sed_cmds"; then
+ ac_sed_cmds=cat
+fi
+EOF
+
+cat >> $CONFIG_STATUS <<EOF
+
+CONFIG_FILES=\${CONFIG_FILES-"Makefile"}
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then
+ # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+ case "$ac_file" in
+ *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'`
+ ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
+ *) ac_file_in="${ac_file}.in" ;;
+ esac
+
+ # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories.
+
+ # Remove last slash and all that follows it. Not all systems have dirname.
+ ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
+ if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
+ # The file is in a subdirectory.
+ test ! -d "$ac_dir" && mkdir "$ac_dir"
+ ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`"
+ # A "../" for each directory in $ac_dir_suffix.
+ ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'`
+ else
+ ac_dir_suffix= ac_dots=
+ fi
+
+ case "$ac_given_srcdir" in
+ .) srcdir=.
+ if test -z "$ac_dots"; then top_srcdir=.
+ else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;;
+ /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;;
+ *) # Relative path.
+ srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix"
+ top_srcdir="$ac_dots$ac_given_srcdir" ;;
+ esac
+
+
+ echo creating "$ac_file"
+ rm -f "$ac_file"
+ configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure."
+ case "$ac_file" in
+ *Makefile*) ac_comsub="1i\\
+# $configure_input" ;;
+ *) ac_comsub= ;;
+ esac
+
+ ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"`
+ sed -e "$ac_comsub
+s%@configure_input@%$configure_input%g
+s%@srcdir@%$srcdir%g
+s%@top_srcdir@%$top_srcdir%g
+" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file
+fi; done
+rm -f conftest.s*
+
+EOF
+cat >> $CONFIG_STATUS <<EOF
+
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+
+exit 0
+EOF
+chmod +x $CONFIG_STATUS
+rm -fr confdefs* $ac_clean_files
+test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1
+
diff --git a/gdb/testsuite/gdb.disasm/configure.in b/gdb/testsuite/gdb.disasm/configure.in
new file mode 100644
index 00000000000..508636ff2c6
--- /dev/null
+++ b/gdb/testsuite/gdb.disasm/configure.in
@@ -0,0 +1,15 @@
+dnl Process this file file with autoconf to produce a configure script.
+dnl This file is a shell script fragment that supplies the information
+dnl necessary to tailor a template configure script into the configure
+dnl script appropriate for this directory. For more information, check
+dnl any existing configure script.
+
+AC_PREREQ(2.5)
+AC_INIT(sh3.s)
+
+CC=${CC-cc}
+AC_SUBST(CC)
+AC_CONFIG_AUX_DIR(`cd $srcdir;pwd`/../../..)
+AC_CANONICAL_SYSTEM
+
+AC_OUTPUT(Makefile)
diff --git a/gdb/testsuite/gdb.disasm/hppa.exp b/gdb/testsuite/gdb.disasm/hppa.exp
new file mode 100644
index 00000000000..4c679a9c63c
--- /dev/null
+++ b/gdb/testsuite/gdb.disasm/hppa.exp
@@ -0,0 +1,1403 @@
+
+# Copyright (C) 1992, 1997 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file was written by Jeff Law. (law@cs.utah.edu)
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+if ![istarget "hppa*-*-*"] {
+ verbose "Tests ignored for all but hppa based targets."
+ return
+}
+
+set prms_id 0
+set bug_id 0
+
+set testfile "hppa"
+set srcfile ${srcdir}/${subdir}/${testfile}.s
+set binfile ${objdir}/${subdir}/${testfile}
+set comp_output [gdb_compile "${srcfile}" "${binfile}" executable ""];
+if { $comp_output != "" } {
+ if [ regexp "Opcode not defined - DIAG" $comp_output] {
+ warning "HP assembler in use--skipping disasm tests"
+ return
+ } else {
+ perror "Couldn't compile ${srcfile}"
+ return -1
+ }
+}
+
+proc all_integer_memory_tests { } {
+ global gdb_prompt
+ global hex
+ global decimal
+
+ send_gdb "x/8i integer_memory_tests\n"
+ gdb_expect {
+ -re "
+.*ldw 0\\(sr0,r4\\),r26.*
+.*ldh 0\\(sr0,r4\\),r26.*
+.*ldb 0\\(sr0,r4\\),r26.*
+.*stw r26,0\\(sr0,r4\\).*
+.*sth r26,0\\(sr0,r4\\).*
+.*stb r26,0\\(sr0,r4\\).*
+.*ldwm 0\\(sr0,r4\\),r26.*
+.*stwm r26,0\\(sr0,r4\\).*
+.*$gdb_prompt $" { pass "integer_memory_tests" }
+ -re "$gdb_prompt $" { fail "integer_memory_tests" }
+ timeout { fail "(timeout) integer memory_tests" }
+ }
+
+ send_gdb "x/20i integer_indexing_load\n"
+ gdb_expect {
+ -re "
+.*ldwx r5\\(sr0,r4\\),r26.*
+.*ldwx,s r5\\(sr0,r4\\),r26.*
+.*ldwx,m r5\\(sr0,r4\\),r26.*
+.*ldwx,sm r5\\(sr0,r4\\),r26.*
+.*ldhx r5\\(sr0,r4\\),r26.*
+.*ldhx,s r5\\(sr0,r4\\),r26.*
+.*ldhx,m r5\\(sr0,r4\\),r26.*
+.*ldhx,sm r5\\(sr0,r4\\),r26.*
+.*ldbx r5\\(sr0,r4\\),r26.*
+.*ldbx,s r5\\(sr0,r4\\),r26.*
+.*ldbx,m r5\\(sr0,r4\\),r26.*
+.*ldbx,sm r5\\(sr0,r4\\),r26.*
+.*ldwax r5\\(r4\\),r26.*
+.*ldwax,s r5\\(r4\\),r26.*
+.*ldwax,m r5\\(r4\\),r26.*
+.*ldwax,sm r5\\(r4\\),r26.*
+.*ldcwx r5\\(sr0,r4\\),r26.*
+.*ldcwx,s r5\\(sr0,r4\\),r26.*
+.*ldcwx,m r5\\(sr0,r4\\),r26.*
+.*ldcwx,sm r5\\(sr0,r4\\),r26.*
+.*$gdb_prompt $" { pass "integer_indexing_load" }
+ -re "$gdb_prompt $" { fail "integer_indexing_load" }
+ timeout { fail "(timeout) integer_indexing" }
+ }
+
+ send_gdb "x/15i integer_load_short_memory\n"
+ gdb_expect {
+ -re "
+.*ldws 0\\(sr0,r4\\),r26.*
+.*ldws,mb 0\\(sr0,r4\\),r26.*
+.*ldws,ma 0\\(sr0,r4\\),r26.*
+.*ldhs 0\\(sr0,r4\\),r26.*
+.*ldhs,mb 0\\(sr0,r4\\),r26.*
+.*ldhs,ma 0\\(sr0,r4\\),r26.*
+.*ldbs 0\\(sr0,r4\\),r26.*
+.*ldbs,mb 0\\(sr0,r4\\),r26.*
+.*ldbs,ma 0\\(sr0,r4\\),r26.*
+.*ldwas 0\\(r4\\),r26.*
+.*ldwas,mb 0\\(r4\\),r26.*
+.*ldwas,ma 0\\(r4\\),r26.*
+.*ldcws 0\\(sr0,r4\\),r26.*
+.*ldcws,mb 0\\(sr0,r4\\),r26.*
+.*ldcws,ma 0\\(sr0,r4\\),r26.*
+.*$gdb_prompt $" { pass "integer_load_short_memory" }
+ -re "$gdb_prompt $" { fail "integer_load_short_memory" }
+ timeout { fail "(timeout) integer_load_short_memory " }
+ }
+
+
+ send_gdb "x/17i integer_store_short_memory\n"
+ gdb_expect {
+ -re "
+.*stws r26,0\\(sr0,r4\\).*
+.*stws,mb r26,0\\(sr0,r4\\).*
+.*stws,ma r26,0\\(sr0,r4\\).*
+.*sths r26,0\\(sr0,r4\\).*
+.*sths,mb r26,0\\(sr0,r4\\).*
+.*sths,ma r26,0\\(sr0,r4\\).*
+.*stbs r26,0\\(sr0,r4\\).*
+.*stbs,mb r26,0\\(sr0,r4\\).*
+.*stbs,ma r26,0\\(sr0,r4\\).*
+.*stwas r26,0\\(r4\\).*
+.*stwas,mb r26,0\\(r4\\).*
+.*stwas,ma r26,0\\(r4\\).*
+.*stbys r26,0\\(sr0,r4\\).*
+.*stbys r26,0\\(sr0,r4\\).*
+.*stbys,e r26,0\\(sr0,r4\\).*
+.*stbys,b,m r26,0\\(sr0,r4\\).*
+.*stbys,e,m r26,0\\(sr0,r4\\).*
+.*$gdb_prompt $" { pass "integer_store_short_memory" }
+ -re "$gdb_prompt $" { fail "integer_store_short_memory" }
+ timeout { fail "(timeout) integer_short_memory " }
+ }
+}
+
+proc all_immediate_tests { } {
+ global gdb_prompt
+ global hex
+ global decimal
+
+ send_gdb "x/3i immediate_tests\n"
+ gdb_expect {
+ -re "
+.*ldo 5\\(r26\\),r26.*
+.*ldil -21524800,r26.*
+.*addil -21524800,r5.*
+.*$gdb_prompt $" { pass "immedate_tests" }
+ -re "$gdb_prompt $" { fail "immedate_tests" }
+ timeout { fail "(timeout) immedate_tests " }
+ }
+}
+
+proc all_branch_tests { } {
+ global gdb_prompt
+ global hex
+ global decimal
+
+ send_gdb "x/10i branch_tests_1\n"
+ gdb_expect {
+ -re "
+.*bl.*,rp.*
+.*bl,n.*,rp.*
+.*b.*
+.*b,n.*
+.*gate.*,rp.*
+.*gate,n.*,rp.*
+.*blr r4,rp.*
+.*blr,n r4,rp.*
+.*blr r4,r0.*
+.*blr,n r4,r0.*
+.*$gdb_prompt $" { pass "branch_tests_1" }
+ -re "$gdb_prompt $" { fail "branch_tests_1" }
+ timeout { fail "(timeout) branch_tests_1" }
+ }
+
+ send_gdb "x/6i branch_tests_2\n"
+ gdb_expect {
+ -re "
+.*bv r0\\(rp\\).*
+.*bv,n r0\\(rp\\).*
+.*be 1234\\(sr1,rp\\).*
+.*be,n 1234\\(sr1,rp\\).*
+.*ble 1234\\(sr1,rp\\).*
+.*ble,n 1234\\(sr1,rp\\).*
+.*$gdb_prompt $" { pass "branch_tests_2" }
+ -re "$gdb_prompt $" { fail "branch_tests_2" }
+ timeout { fail "(timeout) branch_tests_2" }
+ }
+
+
+ send_gdb "x/8i movb_tests\n"
+ gdb_expect {
+ -re "
+.*movb r4,r26,.* <movb_tests>.*
+.*movb,= r4,r26,.* <movb_tests>.*
+.*movb,< r4,r26,.* <movb_tests>.*
+.*movb,od r4,r26,.* <movb_tests>.*
+.*movb,tr r4,r26,.* <movb_tests>.*
+.*movb,<> r4,r26,.* <movb_tests>.*
+.*movb,>= r4,r26,.* <movb_tests>.*
+.*movb,ev r4,r26,.* <movb_tests>.*
+.*$gdb_prompt $" { pass "movb_tests" }
+ -re "$gdb_prompt $" { fail "movb_tests" }
+ timeout { fail "(timeout) movb_tests " }
+ }
+
+ send_gdb "x/8i movb_nullified_tests\n"
+ gdb_expect {
+ -re "
+.*movb,n.*r4,r26,.* <movb_tests>.*
+.*movb,=,n.*r4,r26,.* <movb_tests>.*
+.*movb,<,n.*r4,r26,.* <movb_tests>.*
+.*movb,od,n.*r4,r26,.* <movb_tests>.*
+.*movb,tr,n.*r4,r26,.* <movb_tests>.*
+.*movb,<>,n.*r4,r26,.* <movb_tests>.*
+.*movb,>=,n.*r4,r26,.* <movb_tests>.*
+.*movb,ev,n.*r4,r26,.* <movb_tests>.*
+.*$gdb_prompt $" { pass "movb_nullified_tests" }
+ -re "$gdb_prompt $" { fail "movb_nullified_tests" }
+ timeout { fail "(timeout) movb_nullified_tests " }
+ }
+
+ send_gdb "x/8i movib_tests\n"
+ gdb_expect {
+ -re "
+.*movib 5,r26,.* <movib_tests>.*
+.*movib,= 5,r26,.* <movib_tests>.*
+.*movib,< 5,r26,.* <movib_tests>.*
+.*movib,od 5,r26,.* <movib_tests>.*
+.*movib,tr 5,r26,.* <movib_tests>.*
+.*movib,<> 5,r26,.* <movib_tests>.*
+.*movib,>= 5,r26,.* <movib_tests>.*
+.*movib,ev 5,r26,.* <movib_tests>.*
+.*$gdb_prompt $" { pass "movib_tests" }
+ -re "$gdb_prompt $" { fail "movib_tests" }
+ timeout { fail "(timeout) movib_tests " }
+ }
+
+ send_gdb "x/8i movib_nullified_tests\n"
+ gdb_expect {
+ -re "
+.*movib,n.*5,r26,.* <movib_tests>.*
+.*movib,=,n.*5,r26,.* <movib_tests>.*
+.*movib,<,n.*5,r26,.* <movib_tests>.*
+.*movib,od,n.*5,r26,.* <movib_tests>.*
+.*movib,tr,n.*5,r26,.* <movib_tests>.*
+.*movib,<>,n.*5,r26,.* <movib_tests>.*
+.*movib,>=,n.*5,r26,.* <movib_tests>.*
+.*movib,ev,n.*5,r26,.* <movib_tests>.*
+.*$gdb_prompt $" { pass "movib_nullified_tests" }
+ -re "$gdb_prompt $" { fail "movib_nullified_tests" }
+ timeout { fail "(timeout) movib_nullified_tests " }
+ }
+
+ send_gdb "x/8i comb_tests_1\n"
+ gdb_expect {
+ -re "
+.*comb r0,r4,.* <comb_tests_1>.*
+.*comb,= r0,r4,.* <comb_tests_1>.*
+.*comb,< r0,r4,.* <comb_tests_1>.*
+.*comb,<= r0,r4,.* <comb_tests_1>.*
+.*comb,<< r0,r4,.* <comb_tests_1>.*
+.*comb,<<= r0,r4,.* <comb_tests_1>.*
+.*comb,sv r0,r4,.* <comb_tests_1>.*
+.*comb,od r0,r4,.* <comb_tests_1>.*
+.*$gdb_prompt $" { pass "comb_tests_1" }
+ -re "$gdb_prompt $" { fail "comb_tests_1" }
+ timeout { fail "(timeout) comb_tests_1" }
+ }
+
+ send_gdb "x/8i comb_tests_2\n"
+ gdb_expect {
+ -re "
+.*combf r0,r4,.* <comb_tests_2>.*
+.*combf,= r0,r4,.* <comb_tests_2>.*
+.*combf,< r0,r4,.* <comb_tests_2>.*
+.*combf,<= r0,r4,.* <comb_tests_2>.*
+.*combf,<< r0,r4,.* <comb_tests_2>.*
+.*combf,<<= r0,r4,.* <comb_tests_2>.*
+.*combf,sv r0,r4,.* <comb_tests_2>.*
+.*combf,od r0,r4,.* <comb_tests_2>.*
+.*$gdb_prompt $" { pass "comb_tests_2" }
+ -re "$gdb_prompt $" { fail "comb_tests_2" }
+ timeout { fail "(timeout) comb_tests_2" }
+ }
+
+ send_gdb "x/8i comb_nullified_tests_1\n"
+ gdb_expect {
+ -re "
+.*comb,n r0,r4,.* <comb_tests_1>.*
+.*comb,=,n r0,r4,.* <comb_tests_1>.*
+.*comb,<,n r0,r4,.* <comb_tests_1>.*
+.*comb,<=,n r0,r4,.* <comb_tests_1>.*
+.*comb,<<,n r0,r4,.* <comb_tests_1>.*
+.*comb,<<=,n r0,r4,.* <comb_tests_1>.*
+.*comb,sv,n r0,r4,.* <comb_tests_1>.*
+.*comb,od,n r0,r4,.* <comb_tests_1>.*
+.*$gdb_prompt $" { pass "comb_nullified_tests_1" }
+ -re "$gdb_prompt $" { fail "comb_nullified_tests_1" }
+ timeout { fail "(timeout) comb_nullified_tests_1" }
+ }
+
+ send_gdb "x/8i comb_nullified_tests_2\n"
+ gdb_expect {
+ -re "
+.*combf,n r0,r4,.* <comb_tests_2>.*
+.*combf,=,n r0,r4,.* <comb_tests_2>.*
+.*combf,<,n r0,r4,.* <comb_tests_2>.*
+.*combf,<=,n r0,r4,.* <comb_tests_2>.*
+.*combf,<<,n r0,r4,.* <comb_tests_2>.*
+.*combf,<<=,n r0,r4,.* <comb_tests_2>.*
+.*combf,sv,n r0,r4,.* <comb_tests_2>.*
+.*combf,od,n r0,r4,.* <comb_tests_2>.*
+.*$gdb_prompt $" { pass "comb_nullified_tests_2" }
+ -re "$gdb_prompt $" { fail "comb_nullified_tests_2" }
+ timeout { fail "(timeout) comb_nullified_tests_2" }
+ }
+
+ send_gdb "x/8i comib_tests_1\n"
+ gdb_expect {
+ -re "
+.*comib 0,r4,.* <comib_tests_1>.*
+.*comib,= 0,r4,.* <comib_tests_1>.*
+.*comib,< 0,r4,.* <comib_tests_1>.*
+.*comib,<= 0,r4,.* <comib_tests_1>.*
+.*comib,<< 0,r4,.* <comib_tests_1>.*
+.*comib,<<= 0,r4,.* <comib_tests_1>.*
+.*comib,sv 0,r4,.* <comib_tests_1>.*
+.*comib,od 0,r4,.* <comib_tests_1>.*
+.*$gdb_prompt $" { pass "comib_tests_1" }
+ -re "$gdb_prompt $" { fail "comib_tests_1" }
+ timeout { fail "(timeout) comib_tests_1" }
+ }
+
+ send_gdb "x/8i comib_tests_2\n"
+ gdb_expect {
+ -re "
+.*comibf 0,r4,.* <comib_tests_2>.*
+.*comibf,= 0,r4,.* <comib_tests_2>.*
+.*comibf,< 0,r4,.* <comib_tests_2>.*
+.*comibf,<= 0,r4,.* <comib_tests_2>.*
+.*comibf,<< 0,r4,.* <comib_tests_2>.*
+.*comibf,<<= 0,r4,.* <comib_tests_2>.*
+.*comibf,sv 0,r4,.* <comib_tests_2>.*
+.*comibf,od 0,r4,.* <comib_tests_2>.*
+.*$gdb_prompt $" { pass "comib_tests_2" }
+ -re "$gdb_prompt $" { fail "comib_tests_2" }
+ timeout { fail "(timeout) comib_tests_2" }
+ }
+
+ send_gdb "x/8i comib_nullified_tests_1\n"
+ gdb_expect {
+ -re "
+.*comib,n 0,r4,.* <comib_tests_1>.*
+.*comib,=,n 0,r4,.* <comib_tests_1>.*
+.*comib,<,n 0,r4,.* <comib_tests_1>.*
+.*comib,<=,n 0,r4,.* <comib_tests_1>.*
+.*comib,<<,n 0,r4,.* <comib_tests_1>.*
+.*comib,<<=,n 0,r4,.* <comib_tests_1>.*
+.*comib,sv,n 0,r4,.* <comib_tests_1>.*
+.*comib,od,n 0,r4,.* <comib_tests_1>.*
+.*$gdb_prompt $" { pass "comib_nullified_tests_1" }
+ -re "$gdb_prompt $" { fail "comib_nullified_tests_1" }
+ timeout { fail "(timeout) comib_nullified_tests_1" }
+ }
+
+ send_gdb "x/8i comib_nullified_tests_2\n"
+ gdb_expect {
+ -re "
+.*comibf,n 0,r4,.* <comib_tests_2>.*
+.*comibf,=,n 0,r4,.* <comib_tests_2>.*
+.*comibf,<,n 0,r4,.* <comib_tests_2>.*
+.*comibf,<=,n 0,r4,.* <comib_tests_2>.*
+.*comibf,<<,n 0,r4,.* <comib_tests_2>.*
+.*comibf,<<=,n 0,r4,.* <comib_tests_2>.*
+.*comibf,sv,n 0,r4,.* <comib_tests_2>.*
+.*comibf,od,n 0,r4,.* <comib_tests_2>.*
+.*$gdb_prompt $" { pass "comib_nullified_tests_2" }
+ -re "$gdb_prompt $" { fail "comib_nullified_tests_2" }
+ timeout { fail "(timeout) comib_nullified_tests_2" }
+ }
+
+ send_gdb "x/8i addb_tests_1\n"
+ gdb_expect {
+ -re "
+.*addb r1,r4,.* <addb_tests_1>.*
+.*addb,= r1,r4,.* <addb_tests_1>.*
+.*addb,< r1,r4,.* <addb_tests_1>.*
+.*addb,<= r1,r4,.* <addb_tests_1>.*
+.*addb,nuv r1,r4,.* <addb_tests_1>.*
+.*addb,znv r1,r4,.* <addb_tests_1>.*
+.*addb,sv r1,r4,.* <addb_tests_1>.*
+.*addb,od r1,r4,.* <addb_tests_1>.*
+.*$gdb_prompt $" { pass "addb_tests_1" }
+ -re "$gdb_prompt $" { fail "addb_tests_1" }
+ timeout { fail "(timeout) addb_tests_1" }
+ }
+
+ send_gdb "x/8i addb_tests_2\n"
+ gdb_expect {
+ -re "
+.*addbf r1,r4,.* <addb_tests_2>.*
+.*addbf,= r1,r4,.* <addb_tests_2>.*
+.*addbf,< r1,r4,.* <addb_tests_2>.*
+.*addbf,<= r1,r4,.* <addb_tests_2>.*
+.*addbf,nuv r1,r4,.* <addb_tests_2>.*
+.*addbf,znv r1,r4,.* <addb_tests_2>.*
+.*addbf,sv r1,r4,.* <addb_tests_2>.*
+.*addbf,od r1,r4,.* <addb_tests_2>.*
+.*$gdb_prompt $" { pass "addb_tests_2" }
+ -re "$gdb_prompt $" { fail "addb_tests_2" }
+ timeout { fail "(timeout) addb_tests_2" }
+ }
+
+ send_gdb "x/8i addb_nullified_tests_1\n"
+ gdb_expect {
+ -re "
+.*addb,n r1,r4,.* <addb_tests_1>.*
+.*addb,=,n r1,r4,.* <addb_tests_1>.*
+.*addb,<,n r1,r4,.* <addb_tests_1>.*
+.*addb,<=,n r1,r4,.* <addb_tests_1>.*
+.*addb,nuv,n r1,r4,.* <addb_tests_1>.*
+.*addb,znv,n r1,r4,.* <addb_tests_1>.*
+.*addb,sv,n r1,r4,.* <addb_tests_1>.*
+.*addb,od,n r1,r4,.* <addb_tests_1>.*
+.*$gdb_prompt $" { pass "addb_nullified_tests_1" }
+ -re "$gdb_prompt $" { fail "addb_nullified_tests_1" }
+ timeout { fail "(timeout) addb_nullified_tests_1" }
+ }
+
+ send_gdb "x/8i addb_nullified_tests_2\n"
+ gdb_expect {
+ -re "
+.*addbf,n r1,r4,.* <addb_tests_2>.*
+.*addbf,=,n r1,r4,.* <addb_tests_2>.*
+.*addbf,<,n r1,r4,.* <addb_tests_2>.*
+.*addbf,<=,n r1,r4,.* <addb_tests_2>.*
+.*addbf,nuv,n r1,r4,.* <addb_tests_2>.*
+.*addbf,znv,n r1,r4,.* <addb_tests_2>.*
+.*addbf,sv,n r1,r4,.* <addb_tests_2>.*
+.*addbf,od,n r1,r4,.* <addb_tests_2>.*
+.*$gdb_prompt $" { pass "addb_nullified_tests_2" }
+ -re "$gdb_prompt $" { fail "addb_nullified_tests_2" }
+ timeout { fail "(timeout) addb_nullified_tests_2" }
+ }
+
+ send_gdb "x/8i addib_tests_1\n"
+ gdb_expect {
+ -re "
+.*addib -1,r4,.* <addib_tests_1>.*
+.*addib,= -1,r4,.* <addib_tests_1>.*
+.*addib,< -1,r4,.* <addib_tests_1>.*
+.*addib,<= -1,r4,.* <addib_tests_1>.*
+.*addib,nuv -1,r4,.* <addib_tests_1>.*
+.*addib,znv -1,r4,.* <addib_tests_1>.*
+.*addib,sv -1,r4,.* <addib_tests_1>.*
+.*addib,od -1,r4,.* <addib_tests_1>.*
+.*$gdb_prompt $" { pass "addib_tests_1" }
+ -re "$gdb_prompt $" { fail "addib_tests_1" }
+ timeout { fail "(timeout) addib_tests_1" }
+ }
+
+ send_gdb "x/8i addib_tests_2\n"
+ gdb_expect {
+ -re "
+.*addibf -1,r4,.* <addib_tests_2>.*
+.*addibf,= -1,r4,.* <addib_tests_2>.*
+.*addibf,< -1,r4,.* <addib_tests_2>.*
+.*addibf,<= -1,r4,.* <addib_tests_2>.*
+.*addibf,nuv -1,r4,.* <addib_tests_2>.*
+.*addibf,znv -1,r4,.* <addib_tests_2>.*
+.*addibf,sv -1,r4,.* <addib_tests_2>.*
+.*addibf,od -1,r4,.* <addib_tests_2>.*
+.*$gdb_prompt $" { pass "addib_tests_2" }
+ -re "$gdb_prompt $" { fail "addib_tests_2" }
+ timeout { fail "(timeout) addib_tests_2" }
+ }
+
+ send_gdb "x/8i addib_nullified_tests_1\n"
+ gdb_expect {
+ -re "
+.*addib,n -1,r4,.* <addib_tests_1>.*
+.*addib,=,n -1,r4,.* <addib_tests_1>.*
+.*addib,<,n -1,r4,.* <addib_tests_1>.*
+.*addib,<=,n -1,r4,.* <addib_tests_1>.*
+.*addib,nuv,n -1,r4,.* <addib_tests_1>.*
+.*addib,znv,n -1,r4,.* <addib_tests_1>.*
+.*addib,sv,n -1,r4,.* <addib_tests_1>.*
+.*addib,od,n -1,r4,.* <addib_tests_1>.*
+.*$gdb_prompt $" { pass "addb_nullified_tests_1" }
+ -re "$gdb_prompt $" { fail "addb_nullified_tests_1" }
+ timeout { fail "(timeout) addb_nullified_tests_1" }
+ }
+
+ send_gdb "x/8i addib_nullified_tests_2\n"
+ gdb_expect {
+ -re "
+.*addibf,n -1,r4,.* <addib_tests_2>.*
+.*addibf,=,n -1,r4,.* <addib_tests_2>.*
+.*addibf,<,n -1,r4,.* <addib_tests_2>.*
+.*addibf,<=,n -1,r4,.* <addib_tests_2>.*
+.*addibf,nuv,n -1,r4,.* <addib_tests_2>.*
+.*addibf,znv,n -1,r4,.* <addib_tests_2>.*
+.*addibf,sv,n -1,r4,.* <addib_tests_2>.*
+.*addibf,od,n -1,r4,.* <addib_tests_2>.*
+.*$gdb_prompt $" { pass "addb_nullified_tests_2" }
+ -re "$gdb_prompt $" { fail "addb_nullified_tests_2" }
+ timeout { fail "(timeout) addb_nullified_tests_2" }
+ }
+
+ send_gdb "x/8i bb_tests\n"
+ gdb_expect {
+ -re "
+.*bvb,< r4,.* <bb_tests>.*
+.*bvb,>= r4,.* <bb_tests>.*
+.*bvb,<,n r4,.* <bb_tests>.*
+.*bvb,>=,n r4,.* <bb_tests>.*
+.*bb,< r4,5,.* <bb_tests>.*
+.*bb,>= r4,5,.* <bb_tests>.*
+.*bb,<,n r4,5,.* <bb_tests>.*
+.*bb,>=,n r4,5,.* <bb_tests>.*
+.*$gdb_prompt $" { pass "bb_tests" }
+ -re "$gdb_prompt $" { fail "bb_tests" }
+ timeout { fail "(timeout) bb_tests " }
+ }
+}
+
+proc all_integer_computational_tests { } {
+ global gdb_prompt
+ global hex
+ global decimal
+
+ set add_insns [list {add} {addl} {addo} {addc} {addco} \
+ {sh1add} {sh1addl} {sh1addo} \
+ {sh2add} {sh2addl} {sh2addo} \
+ {sh3add} {sh3addl} {sh3addo} ]
+
+ foreach i $add_insns {
+ send_gdb "x/16i $i"; send_gdb "_tests\n"
+ gdb_expect {
+ -re "
+.*$i r4,r5,r6.*
+.*$i,= r4,r5,r6.*
+.*$i,< r4,r5,r6.*
+.*$i,<= r4,r5,r6.*
+.*$i,nuv r4,r5,r6.*
+.*$i,znv r4,r5,r6.*
+.*$i,sv r4,r5,r6.*
+.*$i,od r4,r5,r6.*
+.*$i,tr r4,r5,r6.*
+.*$i,<> r4,r5,r6.*
+.*$i,>= r4,r5,r6.*
+.*$i,> r4,r5,r6.*
+.*$i,uv r4,r5,r6.*
+.*$i,vnz r4,r5,r6.*
+.*$i,nsv r4,r5,r6.*
+.*$i,ev r4,r5,r6.*
+.*$gdb_prompt $" { pass "$i tests" }
+ -re "$gdb_prompt $" { fail "$i tests" }
+ timeout { fail "(timeout) $i tests" }
+ }
+ }
+
+ set sub_insns [list {sub} {subo} {subb} {subbo} {subt} {subto} \
+ {ds} {comclr} ]
+
+ foreach i $sub_insns {
+ send_gdb "x/16i $i"; send_gdb "_tests\n"
+ gdb_expect {
+ -re "
+.*$i r4,r5,r6.*
+.*$i,= r4,r5,r6.*
+.*$i,< r4,r5,r6.*
+.*$i,<= r4,r5,r6.*
+.*$i,<< r4,r5,r6.*
+.*$i,<<= r4,r5,r6.*
+.*$i,sv r4,r5,r6.*
+.*$i,od r4,r5,r6.*
+.*$i,tr r4,r5,r6.*
+.*$i,<> r4,r5,r6.*
+.*$i,>= r4,r5,r6.*
+.*$i,> r4,r5,r6.*
+.*$i,>>= r4,r5,r6.*
+.*$i,>> r4,r5,r6.*
+.*$i,nsv r4,r5,r6.*
+.*$i,ev r4,r5,r6.*
+.*$gdb_prompt $" { pass "$i tests" }
+ -re "$gdb_prompt $" { fail "$i tests" }
+ timeout { fail "(timeout) $i tests" }
+ }
+ }
+
+ set logical_insns [list {or} {xor} {and} {andcm} ]
+
+ foreach i $logical_insns {
+ send_gdb "x/10i $i"; send_gdb "_tests\n"
+ gdb_expect {
+ -re "
+.*$i r4,r5,r6.*
+.*$i,= r4,r5,r6.*
+.*$i,< r4,r5,r6.*
+.*$i,<= r4,r5,r6.*
+.*$i,od r4,r5,r6.*
+.*$i,tr r4,r5,r6.*
+.*$i,<> r4,r5,r6.*
+.*$i,>= r4,r5,r6.*
+.*$i,> r4,r5,r6.*
+.*$i,ev r4,r5,r6.*
+.*$gdb_prompt $" { pass "$i tests" }
+ -re "$gdb_prompt $" { fail "$i tests" }
+ timeout { fail "(timeout) $i tests" }
+ }
+ }
+
+ set unit_insns1 [list {uxor} {uaddcm} {uaddcmt} ]
+
+ foreach i $unit_insns1 {
+ send_gdb "x/12i $i"; send_gdb "_tests\n"
+ gdb_expect {
+ -re "
+.*$i r4,r5,r6.*
+.*$i,sbz r4,r5,r6.*
+.*$i,shz r4,r5,r6.*
+.*$i,sdc r4,r5,r6.*
+.*$i,sbc r4,r5,r6.*
+.*$i,shc r4,r5,r6.*
+.*$i,tr r4,r5,r6.*
+.*$i,nbz r4,r5,r6.*
+.*$i,nhz r4,r5,r6.*
+.*$i,ndc r4,r5,r6.*
+.*$i,nbc r4,r5,r6.*
+.*$i,nhc r4,r5,r6.*
+.*$gdb_prompt $" { pass "$i tests" }
+ -re "$gdb_prompt $" { fail "$i tests" }
+ timeout { fail "(timeout) $i tests" }
+ }
+ }
+
+ set unit_insns2 [list {dcor} {idcor} ]
+
+ foreach i $unit_insns2 {
+ send_gdb "x/12i $i"; send_gdb "_tests\n"
+ gdb_expect {
+ -re "
+.*$i r4,r5.*
+.*$i,sbz r4,r5.*
+.*$i,shz r4,r5.*
+.*$i,sdc r4,r5.*
+.*$i,sbc r4,r5.*
+.*$i,shc r4,r5.*
+.*$i,tr r4,r5.*
+.*$i,nbz r4,r5.*
+.*$i,nhz r4,r5.*
+.*$i,ndc r4,r5.*
+.*$i,nbc r4,r5.*
+.*$i,nhc r4,r5.*
+.*$gdb_prompt $" { pass "$i tests" }
+ -re "$gdb_prompt $" { fail "$i tests" }
+ timeout { fail "(timeout) $i tests" }
+ }
+ }
+
+ set addi_insns [list {addi} {addio} {addit} {addito} ]
+
+ foreach i $addi_insns {
+ send_gdb "x/16i $i"; send_gdb "_tests\n"
+ gdb_expect {
+ -re "
+.*$i 7b,r5,r6.*
+.*$i,= 7b,r5,r6.*
+.*$i,< 7b,r5,r6.*
+.*$i,<= 7b,r5,r6.*
+.*$i,nuv 7b,r5,r6.*
+.*$i,znv 7b,r5,r6.*
+.*$i,sv 7b,r5,r6.*
+.*$i,od 7b,r5,r6.*
+.*$i,tr 7b,r5,r6.*
+.*$i,<> 7b,r5,r6.*
+.*$i,>= 7b,r5,r6.*
+.*$i,> 7b,r5,r6.*
+.*$i,uv 7b,r5,r6.*
+.*$i,vnz 7b,r5,r6.*
+.*$i,nsv 7b,r5,r6.*
+.*$i,ev 7b,r5,r6.*
+.*$gdb_prompt $" { pass "$i tests" }
+ -re "$gdb_prompt $" { fail "$i tests" }
+ timeout { fail "(timeout) $i tests" }
+ }
+ }
+
+ set subi_insns [list {subi} {subio} {comiclr} ]
+
+ foreach i $subi_insns {
+ send_gdb "x/16i $i"; send_gdb "_tests\n"
+ gdb_expect {
+ -re "
+.*$i 7b,r5,r6.*
+.*$i,= 7b,r5,r6.*
+.*$i,< 7b,r5,r6.*
+.*$i,<= 7b,r5,r6.*
+.*$i,<< 7b,r5,r6.*
+.*$i,<<= 7b,r5,r6.*
+.*$i,sv 7b,r5,r6.*
+.*$i,od 7b,r5,r6.*
+.*$i,tr 7b,r5,r6.*
+.*$i,<> 7b,r5,r6.*
+.*$i,>= 7b,r5,r6.*
+.*$i,> 7b,r5,r6.*
+.*$i,>>= 7b,r5,r6.*
+.*$i,>> 7b,r5,r6.*
+.*$i,nsv 7b,r5,r6.*
+.*$i,ev 7b,r5,r6.*
+.*$gdb_prompt $" { pass "$i tests" }
+ -re "$gdb_prompt $" { fail "$i tests" }
+ timeout { fail "(timeout) $i tests" }
+ }
+ }
+
+ send_gdb "x/8i vshd_tests\n"
+ gdb_expect {
+ -re "
+.*vshd r4,r5,r6.*
+.*vshd,= r4,r5,r6.*
+.*vshd,< r4,r5,r6.*
+.*vshd,od r4,r5,r6.*
+.*vshd,tr r4,r5,r6.*
+.*vshd,<> r4,r5,r6.*
+.*vshd,>= r4,r5,r6.*
+.*vshd,ev r4,r5,r6.*
+.*$gdb_prompt $" { pass "vshd tests" }
+ -re "$gdb_prompt $" { fail "vshd tests" }
+ timeout { fail "(timeout) "vshd tests" }
+ }
+
+ send_gdb "x/8i shd_tests\n"
+ gdb_expect {
+ -re "
+.*shd r4,r5,5,r6.*
+.*shd,= r4,r5,5,r6.*
+.*shd,< r4,r5,5,r6.*
+.*shd,od r4,r5,5,r6.*
+.*shd,tr r4,r5,5,r6.*
+.*shd,<> r4,r5,5,r6.*
+.*shd,>= r4,r5,5,r6.*
+.*shd,ev r4,r5,5,r6.*
+.*$gdb_prompt $" { pass "shd tests" }
+ -re "$gdb_prompt $" { fail "shd tests" }
+ timeout { fail "(timeout) "shd tests" }
+ }
+
+ set extract_insns1 [list {extru} {extrs} {zdep} {dep} ]
+
+ foreach i $extract_insns1 {
+ send_gdb "x/8i $i"; send_gdb "_tests\n"
+ gdb_expect {
+ -re "
+.*$i r4,5,10,r6.*
+.*$i,= r4,5,10,r6.*
+.*$i,< r4,5,10,r6.*
+.*$i,od r4,5,10,r6.*
+.*$i,tr r4,5,10,r6.*
+.*$i,<> r4,5,10,r6.*
+.*$i,>= r4,5,10,r6.*
+.*$i,ev r4,5,10,r6.*
+.*$gdb_prompt $" { pass "$i tests" }
+ -re "$gdb_prompt $" { fail "$i tests" }
+ timeout { fail "(timeout) $i tests" }
+ }
+ }
+
+ set extract_insns2 [list {vextru} {vextrs} {zvdep} {vdep} ]
+
+ foreach i $extract_insns2 {
+ send_gdb "x/8i $i"; send_gdb "_tests\n"
+ gdb_expect {
+ -re "
+.*$i r4,5,r6.*
+.*$i,= r4,5,r6.*
+.*$i,< r4,5,r6.*
+.*$i,od r4,5,r6.*
+.*$i,tr r4,5,r6.*
+.*$i,<> r4,5,r6.*
+.*$i,>= r4,5,r6.*
+.*$i,ev r4,5,r6.*
+.*$gdb_prompt $" { pass "$i tests" }
+ -re "$gdb_prompt $" { fail "$i tests" }
+ timeout { fail "(timeout) $i tests" }
+ }
+ }
+
+ set extract_insns3 [list {vdepi} {zvdepi} ]
+
+ foreach i $extract_insns3 {
+ send_gdb "x/8i $i"; send_gdb "_tests\n"
+ gdb_expect {
+ -re "
+.*$i -1,5,r6.*
+.*$i,= -1,5,r6.*
+.*$i,< -1,5,r6.*
+.*$i,od -1,5,r6.*
+.*$i,tr -1,5,r6.*
+.*$i,<> -1,5,r6.*
+.*$i,>= -1,5,r6.*
+.*$i,ev -1,5,r6.*
+.*$gdb_prompt $" { pass "$i tests" }
+ -re "$gdb_prompt $" { fail "$i tests" }
+ timeout { fail "(timeout) $i tests" }
+ }
+ }
+
+ set extract_insns4 [list {depi} {zdepi} ]
+
+ foreach i $extract_insns4 {
+ send_gdb "x/8i $i"; send_gdb "_tests\n"
+ gdb_expect {
+ -re "
+.*$i -1,4,10,r6.*
+.*$i,= -1,4,10,r6.*
+.*$i,< -1,4,10,r6.*
+.*$i,od -1,4,10,r6.*
+.*$i,tr -1,4,10,r6.*
+.*$i,<> -1,4,10,r6.*
+.*$i,>= -1,4,10,r6.*
+.*$i,ev -1,4,10,r6.*
+.*$gdb_prompt $" { pass "$i tests" }
+ -re "$gdb_prompt $" { fail "$i tests" }
+ timeout { fail "(timeout) $i tests" }
+ }
+ }
+}
+
+proc all_system_control_tests { } {
+ global gdb_prompt
+ global hex
+ global decimal
+
+ send_gdb "x/14i system_control_tests\n"
+ gdb_expect {
+ -re "
+.*break 5,c.*
+.*rfi.*
+.*rfir.*
+.*ssm 5,r4.*
+.*rsm 5,r4.*
+.*mtsm r4.*
+.*ldsid \\(sr0,r5\\),r4.*
+.*mtsp r4,sr0.*
+.*mtctl r4,ccr.*
+.*mfsp sr0,r4.*
+.*mfctl ccr,r4.*
+.*sync.*
+.*syncdma.*
+.*diag 4d2.*
+.*$gdb_prompt $" { pass "system_constrol_tests" }
+ -re "$gdb_prompt $" { fail "system_control_tests" }
+ timeout { file "(timeout) system_control_tests" }
+ }
+
+ send_gdb "x/4i probe_tests\n"
+ gdb_expect {
+ -re "
+.*prober \\(sr0,r5\\),r6,r7.*
+.*proberi \\(sr0,r5\\),1,r7.*
+.*probew \\(sr0,r5\\),r6,r7.*
+.*probewi \\(sr0,r5\\),1,r7.*
+.*$gdb_prompt $" { pass "probe_tests" }
+ -re "$gdb_prompt $" { fail "probe_tests" }
+ timeout { file "(timeout) probe_tests" }
+ }
+
+ # lci uses the same bit pattern as lha, so accept lha.
+ send_gdb "x/5i lpa_tests\n"
+ gdb_expect {
+ -re "
+.*lpa r4\\(sr0,r5\\),r6.*
+.*lpa,m r4\\(sr0,r5\\),r6.*
+.*lha r4\\(sr0,r5\\),r6.*
+.*lha,m r4\\(sr0,r5\\),r6.*
+.*lha r4\\(sr0,r5\\),r6.*
+.*$gdb_prompt $" { pass "lpa_tests" }
+ -re "$gdb_prompt $" { fail "lpa_tests" }
+ timeout { file "(timeout) lpa_tests" }
+ }
+
+ send_gdb "x/18i purge_tests\n"
+ gdb_expect {
+ -re "
+.*pdtlb r4\\(sr0,r5\\).*
+.*pdtlb,m r4\\(sr0,r5\\).*
+.*pitlb r4\\(sr0,r5\\).*
+.*pitlb,m r4\\(sr0,r5\\).*
+.*pdtlbe r4\\(sr0,r5\\).*
+.*pdtlbe,m r4\\(sr0,r5\\).*
+.*pitlbe r4\\(sr0,r5\\).*
+.*pitlbe,m r4\\(sr0,r5\\).*
+.*pdc r4\\(sr0,r5\\).*
+.*pdc,m r4\\(sr0,r5\\).*
+.*fdc r4\\(sr0,r5\\).*
+.*fdc,m r4\\(sr0,r5\\).*
+.*fic r4\\(sr0,r5\\).*
+.*fic,m r4\\(sr0,r5\\).*
+.*fdce r4\\(sr0,r5\\).*
+.*fdce,m r4\\(sr0,r5\\).*
+.*fice r4\\(sr0,r5\\).*
+.*fice,m r4\\(sr0,r5\\).*
+.*$gdb_prompt $" { pass "purge_tests" }
+ -re "$gdb_prompt $" { fail "purge_tests" }
+ timeout { file "(timeout) purge_tests" }
+ }
+
+ send_gdb "x/4i insert_tests\n"
+ gdb_expect {
+ -re "
+.*idtlba r4,\\(sr0,r5\\).*
+.*iitlba r4,\\(sr0,r5\\).*
+.*idtlbp r4,\\(sr0,r5\\).*
+.*iitlbp r4,\\(sr0,r5\\).*
+.*$gdb_prompt $" { pass "insert_tests" }
+ -re "$gdb_prompt $" { fail "insert_tests" }
+ timeout { file "(timeout) insert_tests" }
+ }
+
+}
+
+proc all_fpu_memory_tests { } {
+ global gdb_prompt
+ global hex
+ global decimal
+
+ send_gdb "x/20i fpu_memory_indexing_tests\n"
+ gdb_expect {
+ -re "
+.*fldwx r4\\(sr0,r5\\),fr6.*
+.*fldwx,s r4\\(sr0,r5\\),fr6.*
+.*fldwx,m r4\\(sr0,r5\\),fr6.*
+.*fldwx,sm r4\\(sr0,r5\\),fr6.*
+.*flddx r4\\(sr0,r5\\),fr6.*
+.*flddx,s r4\\(sr0,r5\\),fr6.*
+.*flddx,m r4\\(sr0,r5\\),fr6.*
+.*flddx,sm r4\\(sr0,r5\\),fr6.*
+.*fstwx fr6,r4\\(sr0,r5\\).*
+.*fstwx,s fr6,r4\\(sr0,r5\\).*
+.*fstwx,m fr6,r4\\(sr0,r5\\).*
+.*fstwx,sm fr6,r4\\(sr0,r5\\).*
+.*fstdx fr6,r4\\(sr0,r5\\).*
+.*fstdx,s fr6,r4\\(sr0,r5\\).*
+.*fstdx,m fr6,r4\\(sr0,r5\\).*
+.*fstdx,sm fr6,r4\\(sr0,r5\\).*
+.*fstqx fr6,r4\\(sr0,r5\\).*
+.*fstqx,s fr6,r4\\(sr0,r5\\).*
+.*fstqx,m fr6,r4\\(sr0,r5\\).*
+.*fstqx,sm fr6,r4\\(sr0,r5\\).*
+.*$gdb_prompt $" { pass "fpu_memory_indexing_tests" }
+ -re "$gdb_prompt $" { fail "fpu_memory_indexing_tests" }
+ timeout { file "(timeout) fpu_memory_indexing_tests" }
+ }
+
+ send_gdb "x/15i fpu_short_memory_tests\n"
+ gdb_expect {
+ -re "
+.*fldws 0\\(sr0,r5\\),fr6.*
+.*fldws,mb 0\\(sr0,r5\\),fr6.*
+.*fldws,ma 0\\(sr0,r5\\),fr6.*
+.*fldds 0\\(sr0,r5\\),fr6.*
+.*fldds,mb 0\\(sr0,r5\\),fr6.*
+.*fldds,ma 0\\(sr0,r5\\),fr6.*
+.*fstws fr6,0\\(sr0,r5\\).*
+.*fstws,mb fr6,0\\(sr0,r5\\).*
+.*fstws,ma fr6,0\\(sr0,r5\\).*
+.*fstds fr6,0\\(sr0,r5\\).*
+.*fstds,mb fr6,0\\(sr0,r5\\).*
+.*fstds,ma fr6,0\\(sr0,r5\\).*
+.*fstqs fr6,0\\(sr0,r5\\).*
+.*fstqs,mb fr6,0\\(sr0,r5\\).*
+.*fstqs,ma fr6,0\\(sr0,r5\\).*
+.*$gdb_prompt $" { pass "fpu_short_memory_tests" }
+ -re "$gdb_prompt $" { fail "fpu_short_memory_tests" }
+ timeout { file "(timeout) fpu_short_memory_tests" }
+ }
+
+}
+
+proc all_fpu_computational_tests { } {
+ global gdb_prompt
+ global hex
+ global decimal
+
+ send_gdb "x/1i fpu_misc_tests\n"
+ gdb_expect {
+ -re "
+.*ftest.*
+.*$gdb_prompt $" { pass "fpu_misc_tests" }
+ -re "$gdb_prompt $" { fail "fpu_misc_tests" }
+ timeout { file "(timeout) fpu_misc_tests" }
+ }
+
+ set fpu_two_op_insns [list {fcpy} {fabs} {fsqrt} {frnd} ]
+
+ foreach i $fpu_two_op_insns {
+ send_gdb "x/5i $i"; send_gdb "_tests\n"
+ gdb_expect {
+ -re "
+.*$i,sgl fr5,fr10.*
+.*$i,dbl fr5,fr10.*
+.*$i,quad fr5,fr10.*
+.*$i,sgl fr20,fr24.*
+.*$i,dbl fr20,fr24.*
+.*$gdb_prompt $" { pass "$i tests" }
+ -re "$gdb_prompt $" { fail "$i tests" }
+ timeout { fail "(timeout) $i tests" }
+ }
+ }
+
+ set fpu_conversions [list {fcnvff} {fcnvxf} {fcnvfx} {fcnvfxt} ]
+
+ foreach i $fpu_conversions {
+ send_gdb "x/18i $i"; send_gdb "_tests\n"
+ gdb_expect {
+ -re "
+.*$i,sgl,sgl fr5,fr10.*
+.*$i,sgl,dbl fr5,fr10.*
+.*$i,sgl,quad fr5,fr10.*
+.*$i,dbl,sgl fr5,fr10.*
+.*$i,dbl,dbl fr5,fr10.*
+.*$i,dbl,quad fr5,fr10.*
+.*$i,quad,sgl fr5,fr10.*
+.*$i,quad,dbl fr5,fr10.*
+.*$i,quad,quad fr5,fr10.*
+.*$i,sgl,sgl fr20,fr24.*
+.*$i,sgl,dbl fr20,fr24.*
+.*$i,sgl,quad fr20,fr24.*
+.*$i,dbl,sgl fr20,fr24.*
+.*$i,dbl,dbl fr20,fr24.*
+.*$i,dbl,quad fr20,fr24.*
+.*$i,quad,sgl fr20,fr24.*
+.*$i,quad,dbl fr20,fr24.*
+.*$i,quad,quad fr20,fr24.*
+.*$gdb_prompt $" { pass "$i tests" }
+ -re "$gdb_prompt $" { fail "$i tests" }
+ timeout { fail "(timeout) $i tests" }
+ }
+ }
+
+ set fpu_three_op_insns [list {fadd} {fsub} {fmpy} {fdiv} {frem} ]
+
+ foreach i $fpu_three_op_insns {
+ send_gdb "x/6i $i"; send_gdb "_tests\n"
+ gdb_expect {
+ -re "
+.*$i,sgl fr4,fr8,fr12.*
+.*$i,dbl fr4,fr8,fr12.*
+.*$i,quad fr4,fr8,fr12.*
+.*$i,sgl fr20,fr24,fr28.*
+.*$i,dbl fr20,fr24,fr28.*
+.*$i,quad fr20,fr24,fr28.*
+.*$gdb_prompt $" { pass "$i tests" }
+ -re "$gdb_prompt $" { fail "$i tests" }
+ timeout { fail "(timeout) $i tests" }
+ }
+ }
+
+ send_gdb "x/4i fmpy_addsub_tests\n"
+ gdb_expect {
+ -re "
+.*fmpyadd,sgl fr16,fr17,fr18,fr19,fr20.*
+.*fmpyadd,dbl fr16,fr17,fr18,fr19,fr20.*
+.*fmpysub,sgl fr16,fr17,fr18,fr19,fr20.*
+.*fmpysub,dbl fr16,fr17,fr18,fr19,fr20.*
+.*$gdb_prompt $" { pass "fmpy_addsub_tests" }
+ -re "$gdb_prompt $" { fail "fmpy_addsub_tests" }
+ timeout { fail "(timeout) fmpy_addsub_tests" }
+ }
+
+ send_gdb "x/i xmpyu_tests\n"
+ gdb_expect {
+ -re "
+.*xmpyu fr4,fr5,fr6.*
+.*$gdb_prompt $" {pass "xmpyu_tests" }
+ -re "$gdb_prompt $" {fail "xmpyu_tests" }
+ timeout { fail "(timeout) xmpyu_tests" }
+ }
+
+}
+
+proc all_fpu_comparison_tests { } {
+ global gdb_prompt
+ global hex
+ global decimal
+
+ set fpu_comparison_formats [list {sgl} {dbl} {quad} ]
+
+ foreach i $fpu_comparison_formats {
+ send_gdb "x/8i fcmp_$i"; send_gdb "_tests_1\n"
+ gdb_expect {
+ -re "
+.*fcmp,$i,false\\? fr4,fr5.*
+.*fcmp,$i,false fr4,fr5.*
+.*fcmp,$i,\\? fr4,fr5.*
+.*fcmp,$i,!<=> fr4,fr5.*
+.*fcmp,$i,= fr4,fr5.*
+.*fcmp,$i,=t fr4,fr5.*
+.*fcmp,$i,\\?= fr4,fr5.*
+.*fcmp,$i,!<> fr4,fr5.*
+.*$gdb_prompt $" { pass "$i tests (part1) " }
+ -re "$gdb_prompt $" { fail "fcmp_$i tests (part1) " }
+ timeout { fail "(timeout) fcmp_$i tests (part1) " }
+ }
+
+ send_gdb "x/8i fcmp_$i"; send_gdb "_tests_2\n"
+ gdb_expect {
+ -re "
+.*fcmp,$i,!\\?>= fr4,fr5.*
+.*fcmp,$i,< fr4,fr5.*
+.*fcmp,$i,\\?< fr4,fr5.*
+.*fcmp,$i,!>= fr4,fr5.*
+.*fcmp,$i,!\\?> fr4,fr5.*
+.*fcmp,$i,<= fr4,fr5.*
+.*fcmp,$i,\\?<= fr4,fr5.*
+.*fcmp,$i,!> fr4,fr5.*
+.*$gdb_prompt $" { pass "$i tests (part2) " }
+ -re "$gdb_prompt $" { fail "fcmp_$i tests (part2) " }
+ timeout { fail "(timeout) fcmp_$i tests (part2) " }
+ }
+
+ send_gdb "x/8i fcmp_$i"; send_gdb "_tests_3\n"
+ gdb_expect {
+ -re "
+.*fcmp,$i,!\\?<= fr4,fr5.*
+.*fcmp,$i,> fr4,fr5.*
+.*fcmp,$i,\\?> fr4,fr5.*
+.*fcmp,$i,!<= fr4,fr5.*
+.*fcmp,$i,!\\?< fr4,fr5.*
+.*fcmp,$i,>= fr4,fr5.*
+.*fcmp,$i,\\?>= fr4,fr5.*
+.*fcmp,$i,!< fr4,fr5.*
+.*$gdb_prompt $" { pass "$i tests (part3) " }
+ -re "$gdb_prompt $" { fail "fcmp_$i tests (part3) " }
+ timeout { fail "(timeout) fcmp_$i tests (part3) " }
+ }
+
+ send_gdb "x/8i fcmp_$i"; send_gdb "_tests_4\n"
+ gdb_expect {
+ -re "
+.*fcmp,$i,!\\?= fr4,fr5.*
+.*fcmp,$i,<> fr4,fr5.*
+.*fcmp,$i,!= fr4,fr5.*
+.*fcmp,$i,!=t fr4,fr5.*
+.*fcmp,$i,!\\? fr4,fr5.*
+.*fcmp,$i,<=> fr4,fr5.*
+.*fcmp,$i,true\\? fr4,fr5.*
+.*fcmp,$i,true fr4,fr5.*
+.*$gdb_prompt $" { pass "$i tests (part4) " }
+ -re "$gdb_prompt $" { fail "fcmp_$i tests (part4) " }
+ timeout { fail "(timeout) fcmp_$i tests (part4) " }
+ }
+ }
+}
+
+proc all_special_tests { } {
+ global gdb_prompt
+ global hex
+ global decimal
+
+ send_gdb "x/4i special_tests\n"
+ gdb_expect {
+ -re "
+.*gfw r4\\(sr0,r5\\).*
+.*gfw,m r4\\(sr0,r5\\).*
+.*gfr r4\\(sr0,r5\\).*
+.*gfr,m r4\\(sr0,r5\\).*
+.*$gdb_prompt $" { pass "special tests" }
+ -re "$gdb_prompt $" { fail "special tests" }
+ timeout { fail "(timeout) special tests " }
+ }
+
+}
+
+proc all_sfu_tests { } {
+ global gdb_prompt
+ global hex
+ global decimal
+
+ send_gdb "x/16i sfu_tests\n"
+ gdb_expect {
+ -re "
+.*spop0,4,5.*
+.*spop0,4,73.*
+.*spop0,4,5,n.*
+.*spop0,4,73,n.*
+.*spop1,4,5 r5.*
+.*spop1,4,73 r5.*
+.*spop1,4,5,n r5.*
+.*spop1,4,73,n r5.*
+.*spop2,4,5 r5.*
+.*spop2,4,73 r5.*
+.*spop2,4,5,n r5.*
+.*spop2,4,73,n r5.*
+.*spop3,4,5 r5,r6.*
+.*spop3,4,73 r5,r6.*
+.*spop3,4,5,n r5,r6.*
+.*spop3,4,73,n r5,r6.*
+.*$gdb_prompt $" { pass "sfu tests" }
+ -re "$gdb_prompt $" { fail "sfu tests" }
+ timeout { fail "(timeout) sfu tests " }
+ }
+}
+
+proc all_copr_tests { } {
+ global gdb_prompt
+ global hex
+ global decimal
+
+ send_gdb "x/4i copr_tests\n"
+ gdb_expect {
+ -re "
+.*copr,4,5.*
+.*copr,4,73.*
+.*copr,4,5,n.*
+.*copr,4,73,n.*
+.*$gdb_prompt $" { pass "copr tests" }
+ -re "$gdb_prompt $" { fail "copr tests" }
+ timeout { fail "(timeout) copr tests " }
+ }
+}
+
+proc all_copr_mem_tests { } {
+ global gdb_prompt
+ global hex
+ global decimal
+
+ send_gdb "x/8i copr_indexing_load\n"
+ gdb_expect {
+ -re "
+.*cldwx,4 r5\\(sr0,r4\\),r26.*
+.*cldwx,4,s r5\\(sr0,r4\\),r26.*
+.*cldwx,4,m r5\\(sr0,r4\\),r26.*
+.*cldwx,4,sm r5\\(sr0,r4\\),r26.*
+.*clddx,4 r5\\(sr0,r4\\),r26.*
+.*clddx,4,s r5\\(sr0,r4\\),r26.*
+.*clddx,4,m r5\\(sr0,r4\\),r26.*
+.*clddx,4,sm r5\\(sr0,r4\\),r26.*
+.*$gdb_prompt $" { pass "copr indexed load tests" }
+ -re "$gdb_prompt $" { fail "copr indexed load tests" }
+ timeout { fail "(timeout) copr indexed load tests " }
+ }
+
+ send_gdb "x/8i copr_indexing_store\n"
+ gdb_expect {
+ -re "
+.*cstwx,4 r26,r5\\(sr0,r4\\).*
+.*cstwx,4,s r26,r5\\(sr0,r4\\).*
+.*cstwx,4,m r26,r5\\(sr0,r4\\).*
+.*cstwx,4,sm r26,r5\\(sr0,r4\\).*
+.*cstdx,4 r26,r5\\(sr0,r4\\).*
+.*cstdx,4,s r26,r5\\(sr0,r4\\).*
+.*cstdx,4,m r26,r5\\(sr0,r4\\).*
+.*cstdx,4,sm r26,r5\\(sr0,r4\\).*
+.*$gdb_prompt $" { pass "copr indexed store tests" }
+ -re "$gdb_prompt $" { fail "copr indexed store tests" }
+ timeout { fail "(timeout) copr indexed load tests " }
+ }
+
+ send_gdb "x/12i copr_short_memory\n"
+ gdb_expect {
+ -re "
+.*cldws,4 0\\(sr0,r4\\),r26.*
+.*cldws,4,mb 0\\(sr0,r4\\),r26.*
+.*cldws,4,ma 0\\(sr0,r4\\),r26.*
+.*cldds,4 0\\(sr0,r4\\),r26.*
+.*cldds,4,mb 0\\(sr0,r4\\),r26.*
+.*cldds,4,ma 0\\(sr0,r4\\),r26.*
+.*cstws,4 r26,0\\(sr0,r4\\).*
+.*cstws,4,mb r26,0\\(sr0,r4\\).*
+.*cstws,4,ma r26,0\\(sr0,r4\\).*
+.*cstds,4 r26,0\\(sr0,r4\\).*
+.*cstds,4,mb r26,0\\(sr0,r4\\).*
+.*cstds,4,ma r26,0\\(sr0,r4\\).*
+.*$gdb_prompt $" { pass "copr short memory tests" }
+ -re "$gdb_prompt $" { fail "copr short memory tests" }
+ timeout { fail "(timeout) copr short memory tests " }
+ }
+}
+
+proc fmemLRbug_tests { } {
+ global gdb_prompt
+ global hex
+ global decimal
+
+ send_gdb "x/12i fmemLRbug_tests_1\n"
+ gdb_expect {
+ -re "
+.*fstws fr6R,0\\(sr0,r26\\).*
+.*fstws fr6,4\\(sr0,r26\\).*
+.*fstws fr6,8\\(sr0,r26\\).*
+.*fstds fr6,0\\(sr0,r26\\).*
+.*fstds fr6,4\\(sr0,r26\\).*
+.*fstds fr6,8\\(sr0,r26\\).*
+.*fldws 0\\(sr0,r26\\),fr6R.*
+.*fldws 4\\(sr0,r26\\),fr6.*
+.*fldws 8\\(sr0,r26\\),fr6.*
+.*fldds 0\\(sr0,r26\\),fr6.*
+.*fldds 4\\(sr0,r26\\),fr6.*
+.*fldds 8\\(sr0,r26\\),fr6.*
+.*$gdb_prompt $" { pass "fmem LR register selector tests (part1)" }
+ -re "$gdb_prompt $" { fail "fmem LR register selector tests (part1)" }
+ timeout { fail "(timeout) fmem LR register selector tests (part1)" }
+ }
+
+ send_gdb "x/12i fmemLRbug_tests_2\n"
+ gdb_expect {
+ -re "
+.*fstws fr6R,0\\(sr0,r26\\).*
+.*fstws fr6,4\\(sr0,r26\\).*
+.*fstws fr6,8\\(sr0,r26\\).*
+.*fstds fr6,0\\(sr0,r26\\).*
+.*fstds fr6,4\\(sr0,r26\\).*
+.*fstds fr6,8\\(sr0,r26\\).*
+.*fldws 0\\(sr0,r26\\),fr6R.*
+.*fldws 4\\(sr0,r26\\),fr6.*
+.*fldws 8\\(sr0,r26\\),fr6.*
+.*fldds 0\\(sr0,r26\\),fr6.*
+.*fldds 4\\(sr0,r26\\),fr6.*
+.*fldds 8\\(sr0,r26\\),fr6.*
+.*$gdb_prompt $" { pass "fmem LR register selector tests (part2)" }
+ -re "$gdb_prompt $" { fail "fmem LR register selector tests (part2)" }
+ timeout { fail "(timeout) fmem LR register selector tests (part2)" }
+ }
+
+ send_gdb "x/12i fmemLRbug_tests_3\n"
+ gdb_expect {
+ -re "
+.*fstwx fr6R,r25\\(sr0,r26\\).*
+.*fstwx fr6,r25\\(sr0,r26\\).*
+.*fstwx fr6,r25\\(sr0,r26\\).*
+.*fstdx fr6,r25\\(sr0,r26\\).*
+.*fstdx fr6,r25\\(sr0,r26\\).*
+.*fstdx fr6,r25\\(sr0,r26\\).*
+.*fldwx r25\\(sr0,r26\\),fr6R.*
+.*fldwx r25\\(sr0,r26\\),fr6.*
+.*fldwx r25\\(sr0,r26\\),fr6.*
+.*flddx r25\\(sr0,r26\\),fr6.*
+.*flddx r25\\(sr0,r26\\),fr6.*
+.*flddx r25\\(sr0,r26\\),fr6.*
+.*$gdb_prompt $" { pass "fmem LR register selector tests (part3)" }
+ -re "$gdb_prompt $" { fail "fmem LR register selector tests (part3)" }
+ timeout { fail "(timeout) fmem LR register selector tests (part3)" }
+ }
+
+ send_gdb "x/12i fmemLRbug_tests_4\n"
+ gdb_expect {
+ -re "
+.*fstwx fr6R,r25\\(sr0,r26\\).*
+.*fstwx fr6,r25\\(sr0,r26\\).*
+.*fstwx fr6,r25\\(sr0,r26\\).*
+.*fstdx fr6,r25\\(sr0,r26\\).*
+.*fstdx fr6,r25\\(sr0,r26\\).*
+.*fstdx fr6,r25\\(sr0,r26\\).*
+.*fldwx r25\\(sr0,r26\\),fr6R.*
+.*fldwx r25\\(sr0,r26\\),fr6.*
+.*fldwx r25\\(sr0,r26\\),fr6.*
+.*flddx r25\\(sr0,r26\\),fr6.*
+.*flddx r25\\(sr0,r26\\),fr6.*
+.*flddx r25\\(sr0,r26\\),fr6.*
+.*$gdb_prompt $" { pass "fmem LR register selector tests (part4)" }
+ -re "$gdb_prompt $" { fail "fmem LR register selector tests (part4)" }
+ timeout { fail "(timeout) fmem LR register selector tests (part4)" }
+ }
+}
+
+# Start with a fresh gdb.
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load $binfile
+
+all_integer_memory_tests
+all_immediate_tests
+all_branch_tests
+all_integer_computational_tests
+all_system_control_tests
+all_fpu_memory_tests
+all_fpu_computational_tests
+all_fpu_comparison_tests
+all_special_tests
+all_sfu_tests
+all_copr_tests
+all_copr_mem_tests
+
+# Regression test for a bug Tege found.
+fmemLRbug_tests
diff --git a/gdb/testsuite/gdb.disasm/hppa.s b/gdb/testsuite/gdb.disasm/hppa.s
new file mode 100644
index 00000000000..593d8bfefee
--- /dev/null
+++ b/gdb/testsuite/gdb.disasm/hppa.s
@@ -0,0 +1,1738 @@
+ .SPACE $PRIVATE$
+ .SUBSPA $DATA$,QUAD=1,ALIGN=8,ACCESS=31
+ .SUBSPA $BSS$,QUAD=1,ALIGN=8,ACCESS=31,ZERO,SORT=82
+ .SPACE $TEXT$
+ .SUBSPA $LIT$,QUAD=0,ALIGN=8,ACCESS=44
+ .SUBSPA $CODE$,QUAD=0,ALIGN=8,ACCESS=44,CODE_ONLY
+ .IMPORT $global$,DATA
+ .IMPORT $$dyncall,MILLICODE
+; gcc_compiled.:
+ .SPACE $TEXT$
+ .SUBSPA $CODE$
+
+ .align 4
+ .EXPORT integer_memory_tests,CODE
+ .EXPORT integer_indexing_load,CODE
+ .EXPORT integer_load_short_memory,CODE
+ .EXPORT integer_store_short_memory,CODE
+ .EXPORT immediate_tests,CODE
+ .EXPORT branch_tests_1,CODE
+ .EXPORT branch_tests_2,CODE
+ .EXPORT movb_tests,CODE
+ .EXPORT movb_nullified_tests,CODE
+ .EXPORT movib_tests,CODE
+ .EXPORT movib_nullified_tests,CODE
+ .EXPORT comb_tests_1,CODE
+ .EXPORT comb_tests_2,CODE
+ .EXPORT comb_nullified_tests_1,CODE
+ .EXPORT comb_nullified_tests_2,CODE
+ .EXPORT comib_tests_1,CODE
+ .EXPORT comib_tests_2,CODE
+ .EXPORT comib_nullified_tests_1,CODE
+ .EXPORT comib_nullified_tests_2,CODE
+ .EXPORT addb_tests_1,CODE
+ .EXPORT addb_tests_2,CODE
+ .EXPORT addb_nullified_tests_1,CODE
+ .EXPORT addb_nullified_tests_2,CODE
+ .EXPORT addib_tests_1,CODE
+ .EXPORT addib_tests_2,CODE
+ .EXPORT addib_nullified_tests_1,CODE
+ .EXPORT addib_nullified_tests_2,CODE
+ .EXPORT bb_tests,CODE
+ .EXPORT add_tests,CODE
+ .EXPORT addl_tests,CODE
+ .EXPORT addo_tests,CODE
+ .EXPORT addc_tests,CODE
+ .EXPORT addco_tests,CODE
+ .EXPORT sh1add_tests,CODE
+ .EXPORT sh1addl_tests,CODE
+ .EXPORT sh1addo_tests,CODE
+ .EXPORT sh2add_tests,CODE
+ .EXPORT sh2addl_tests,CODE
+ .EXPORT sh2addo_tests,CODE
+ .EXPORT sh3add_tests,CODE
+ .EXPORT sh3addl_tests,CODE
+ .EXPORT sh3addo_tests,CODE
+ .EXPORT sub_tests,CODE
+ .EXPORT subo_tests,CODE
+ .EXPORT subb_tests,CODE
+ .EXPORT subbo_tests,CODE
+ .EXPORT subt_tests,CODE
+ .EXPORT subto_tests,CODE
+ .EXPORT ds_tests,CODE
+ .EXPORT comclr_tests,CODE
+ .EXPORT or_tests,CODE
+ .EXPORT xor_tests,CODE
+ .EXPORT and_tests,CODE
+ .EXPORT andcm_tests,CODE
+ .EXPORT uxor_tests,CODE
+ .EXPORT uaddcm_tests,CODE
+ .EXPORT uaddcmt_tests,CODE
+ .EXPORT dcor_tests,CODE
+ .EXPORT idcor_tests,CODE
+ .EXPORT addi_tests,CODE
+ .EXPORT addio_tests,CODE
+ .EXPORT addit_tests,CODE
+ .EXPORT addito_tests,CODE
+ .EXPORT subi_tests,CODE
+ .EXPORT subio_tests,CODE
+ .EXPORT comiclr_tests,CODE
+ .EXPORT vshd_tests,CODE
+ .EXPORT shd_tests,CODE
+ .EXPORT extru_tests,CODE
+ .EXPORT extrs_tests,CODE
+ .EXPORT zdep_tests,CODE
+ .EXPORT dep_tests,CODE
+ .EXPORT vextru_tests,CODE
+ .EXPORT vextrs_tests,CODE
+ .EXPORT zvdep_tests,CODE
+ .EXPORT vdep_tests,CODE
+ .EXPORT vdepi_tests,CODE
+ .EXPORT zvdepi_tests,CODE
+ .EXPORT depi_tests,CODE
+ .EXPORT zdepi_tests,CODE
+ .EXPORT system_control_tests,CODE
+ .EXPORT probe_tests,CODE
+ .EXPORT lpa_tests,CODE
+ .EXPORT purge_tests,CODE
+ .EXPORT insert_tests,CODE
+ .EXPORT fpu_misc_tests,CODE
+ .EXPORT fpu_memory_indexing_tests,CODE
+ .EXPORT fpu_short_memory_tests,CODE
+ .EXPORT fcpy_tests,CODE
+ .EXPORT fabs_tests,CODE
+ .EXPORT fsqrt_tests,CODE
+ .EXPORT frnd_tests,CODE
+ .EXPORT fcnvff_tests,CODE
+ .EXPORT fcnvxf_tests,CODE
+ .EXPORT fcnvfx_tests,CODE
+ .EXPORT fcnvfxt_tests,CODE
+ .EXPORT fadd_tests,CODE
+ .EXPORT fsub_tests,CODE
+ .EXPORT fmpy_tests,CODE
+ .EXPORT fdiv_tests,CODE
+ .EXPORT frem_tests,CODE
+ .EXPORT fcmp_sgl_tests_1,CODE
+ .EXPORT fcmp_sgl_tests_2,CODE
+ .EXPORT fcmp_sgl_tests_3,CODE
+ .EXPORT fcmp_sgl_tests_4,CODE
+ .EXPORT fcmp_dbl_tests_1,CODE
+ .EXPORT fcmp_dbl_tests_2,CODE
+ .EXPORT fcmp_dbl_tests_3,CODE
+ .EXPORT fcmp_dbl_tests_4,CODE
+ .EXPORT fcmp_quad_tests_1,CODE
+ .EXPORT fcmp_quad_tests_2,CODE
+ .EXPORT fcmp_quad_tests_3,CODE
+ .EXPORT fcmp_quad_tests_4,CODE
+ .EXPORT fmpy_addsub_tests,CODE
+ .EXPORT xmpyu_tests,CODE
+ .EXPORT special_tests,CODE
+ .EXPORT sfu_tests,CODE
+ .EXPORT copr_tests,CODE
+ .EXPORT copr_indexing_load,CODE
+ .EXPORT copr_indexing_store,CODE
+ .EXPORT copr_short_memory,CODE
+ .EXPORT fmemLRbug_tests_1,CODE
+ .EXPORT fmemLRbug_tests_2,CODE
+ .EXPORT fmemLRbug_tests_3,CODE
+ .EXPORT fmemLRbug_tests_4,CODE
+ .EXPORT main,CODE
+ .EXPORT main,ENTRY,PRIV_LEV=3,RTNVAL=GR
+main
+ .PROC
+ .CALLINFO FRAME=64,NO_CALLS,SAVE_SP
+ .ENTRY
+ copy %r4,%r1
+ copy %r30,%r4
+ stwm %r1,64(0,%r30)
+; First memory reference instructions.
+; Should try corner cases for each field extraction.
+; Should deal with s == 0 case somehow?!?
+integer_memory_tests
+ ldw 0(0,%r4),%r26
+ ldh 0(0,%r4),%r26
+ ldb 0(0,%r4),%r26
+ stw %r26,0(0,%r4)
+ sth %r26,0(0,%r4)
+ stb %r26,0(0,%r4)
+
+; Should make sure pre/post modes are recognized correctly.
+ ldwm 0(0,%r4),%r26
+ stwm %r26,0(0,%r4)
+
+integer_indexing_load
+ ldwx %r5(0,%r4),%r26
+ ldwx,s %r5(0,%r4),%r26
+ ldwx,m %r5(0,%r4),%r26
+ ldwx,sm %r5(0,%r4),%r26
+ ldhx %r5(0,%r4),%r26
+ ldhx,s %r5(0,%r4),%r26
+ ldhx,m %r5(0,%r4),%r26
+ ldhx,sm %r5(0,%r4),%r26
+ ldbx %r5(0,%r4),%r26
+ ldbx,s %r5(0,%r4),%r26
+ ldbx,m %r5(0,%r4),%r26
+ ldbx,sm %r5(0,%r4),%r26
+ ldwax %r5(%r4),%r26
+ ldwax,s %r5(%r4),%r26
+ ldwax,m %r5(%r4),%r26
+ ldwax,sm %r5(%r4),%r26
+ ldcwx %r5(0,%r4),%r26
+ ldcwx,s %r5(0,%r4),%r26
+ ldcwx,m %r5(0,%r4),%r26
+ ldcwx,sm %r5(0,%r4),%r26
+
+integer_load_short_memory
+ ldws 0(0,%r4),%r26
+ ldws,mb 0(0,%r4),%r26
+ ldws,ma 0(0,%r4),%r26
+ ldhs 0(0,%r4),%r26
+ ldhs,mb 0(0,%r4),%r26
+ ldhs,ma 0(0,%r4),%r26
+ ldbs 0(0,%r4),%r26
+ ldbs,mb 0(0,%r4),%r26
+ ldbs,ma 0(0,%r4),%r26
+ ldwas 0(%r4),%r26
+ ldwas,mb 0(%r4),%r26
+ ldwas,ma 0(%r4),%r26
+ ldcws 0(0,%r4),%r26
+ ldcws,mb 0(0,%r4),%r26
+ ldcws,ma 0(0,%r4),%r26
+
+integer_store_short_memory
+ stws %r26,0(0,%r4)
+ stws,mb %r26,0(0,%r4)
+ stws,ma %r26,0(0,%r4)
+ sths %r26,0(0,%r4)
+ sths,mb %r26,0(0,%r4)
+ sths,ma %r26,0(0,%r4)
+ stbs %r26,0(0,%r4)
+ stbs,mb %r26,0(0,%r4)
+ stbs,ma %r26,0(0,%r4)
+ stwas %r26,0(%r4)
+ stwas,mb %r26,0(%r4)
+ stwas,ma %r26,0(%r4)
+ stbys %r26,0(0,%r4)
+ stbys,b %r26,0(0,%r4)
+ stbys,e %r26,0(0,%r4)
+ stbys,b,m %r26,0(0,%r4)
+ stbys,e,m %r26,0(0,%r4)
+
+; Immediate instructions.
+immediate_tests
+ ldo 5(%r26),%r26
+ ldil L%0xdeadbeef,%r26
+ addil L%0xdeadbeef,%r5
+
+; Lots of branch instructions.
+; blr with %r0 as return pointer should really be just br <target>,
+; but the assemblers can't handle it.
+branch_tests_1
+ bl main,%r2
+ bl,n main,%r2
+ b main
+ b,n main
+ gate main,%r2
+ gate,n main,%r2
+ blr %r4,%r2
+ blr,n %r4,%r2
+ blr %r4,%r0
+ blr,n %r4,%r0
+branch_tests_2
+ bv 0(%r2)
+ bv,n 0(%r2)
+ be 0x1234(%sr1,%r2)
+ be,n 0x1234(%sr1,%r2)
+ ble 0x1234(%sr1,%r2)
+ ble,n 0x1234(%sr1,%r2)
+
+; GAS can't assemble movb,n or movib,n.
+movb_tests
+ movb %r4,%r26,movb_tests
+ movb,= %r4,%r26,movb_tests
+ movb,< %r4,%r26,movb_tests
+ movb,od %r4,%r26,movb_tests
+ movb,tr %r4,%r26,movb_tests
+ movb,<> %r4,%r26,movb_tests
+ movb,>= %r4,%r26,movb_tests
+ movb,ev %r4,%r26,movb_tests
+movb_nullified_tests
+ movb,n %r4,%r26,movb_tests
+ movb,=,n %r4,%r26,movb_tests
+ movb,<,n %r4,%r26,movb_tests
+ movb,od,n %r4,%r26,movb_tests
+ movb,tr,n %r4,%r26,movb_tests
+ movb,<>,n %r4,%r26,movb_tests
+ movb,>=,n %r4,%r26,movb_tests
+ movb,ev,n %r4,%r26,movb_tests
+
+movib_tests
+ movib 5,%r26,movib_tests
+ movib,= 5,%r26,movib_tests
+ movib,< 5,%r26,movib_tests
+ movib,od 5,%r26,movib_tests
+ movib,tr 5,%r26,movib_tests
+ movib,<> 5,%r26,movib_tests
+ movib,>= 5,%r26,movib_tests
+ movib,ev 5,%r26,movib_tests
+movib_nullified_tests
+ movib,n 5,%r26,movib_tests
+ movib,=,n 5,%r26,movib_tests
+ movib,<,n 5,%r26,movib_tests
+ movib,od,n 5,%r26,movib_tests
+ movib,tr,n 5,%r26,movib_tests
+ movib,<>,n 5,%r26,movib_tests
+ movib,>=,n 5,%r26,movib_tests
+ movib,ev,n 5,%r26,movib_tests
+
+comb_tests_1
+ comb %r0,%r4,comb_tests_1
+ comb,= %r0,%r4,comb_tests_1
+ comb,< %r0,%r4,comb_tests_1
+ comb,<= %r0,%r4,comb_tests_1
+ comb,<< %r0,%r4,comb_tests_1
+ comb,<<= %r0,%r4,comb_tests_1
+ comb,sv %r0,%r4,comb_tests_1
+ comb,od %r0,%r4,comb_tests_1
+
+comb_tests_2
+ comb,tr %r0,%r4,comb_tests_2
+ comb,<> %r0,%r4,comb_tests_2
+ comb,>= %r0,%r4,comb_tests_2
+ comb,> %r0,%r4,comb_tests_2
+ comb,>>= %r0,%r4,comb_tests_2
+ comb,>> %r0,%r4,comb_tests_2
+ comb,nsv %r0,%r4,comb_tests_2
+ comb,ev %r0,%r4,comb_tests_2
+
+comb_nullified_tests_1
+ comb,n %r0,%r4,comb_tests_1
+ comb,=,n %r0,%r4,comb_tests_1
+ comb,<,n %r0,%r4,comb_tests_1
+ comb,<=,n %r0,%r4,comb_tests_1
+ comb,<<,n %r0,%r4,comb_tests_1
+ comb,<<=,n %r0,%r4,comb_tests_1
+ comb,sv,n %r0,%r4,comb_tests_1
+ comb,od,n %r0,%r4,comb_tests_1
+
+comb_nullified_tests_2
+ comb,tr,n %r0,%r4,comb_tests_2
+ comb,<>,n %r0,%r4,comb_tests_2
+ comb,>=,n %r0,%r4,comb_tests_2
+ comb,>,n %r0,%r4,comb_tests_2
+ comb,>>=,n %r0,%r4,comb_tests_2
+ comb,>>,n %r0,%r4,comb_tests_2
+ comb,nsv,n %r0,%r4,comb_tests_2
+ comb,ev,n %r0,%r4,comb_tests_2
+
+comib_tests_1
+ comib 0,%r4,comib_tests_1
+ comib,= 0,%r4,comib_tests_1
+ comib,< 0,%r4,comib_tests_1
+ comib,<= 0,%r4,comib_tests_1
+ comib,<< 0,%r4,comib_tests_1
+ comib,<<= 0,%r4,comib_tests_1
+ comib,sv 0,%r4,comib_tests_1
+ comib,od 0,%r4,comib_tests_1
+
+comib_tests_2
+ comib,tr 0,%r4,comib_tests_2
+ comib,<> 0,%r4,comib_tests_2
+ comib,>= 0,%r4,comib_tests_2
+ comib,> 0,%r4,comib_tests_2
+ comib,>>= 0,%r4,comib_tests_2
+ comib,>> 0,%r4,comib_tests_2
+ comib,nsv 0,%r4,comib_tests_2
+ comib,ev 0,%r4,comib_tests_2
+
+comib_nullified_tests_1
+ comib,n 0,%r4,comib_tests_1
+ comib,=,n 0,%r4,comib_tests_1
+ comib,<,n 0,%r4,comib_tests_1
+ comib,<=,n 0,%r4,comib_tests_1
+ comib,<<,n 0,%r4,comib_tests_1
+ comib,<<=,n 0,%r4,comib_tests_1
+ comib,sv,n 0,%r4,comib_tests_1
+ comib,od,n 0,%r4,comib_tests_1
+
+comib_nullified_tests_2
+ comib,tr,n 0,%r4,comib_tests_2
+ comib,<>,n 0,%r4,comib_tests_2
+ comib,>=,n 0,%r4,comib_tests_2
+ comib,>,n 0,%r4,comib_tests_2
+ comib,>>=,n 0,%r4,comib_tests_2
+ comib,>>,n 0,%r4,comib_tests_2
+ comib,nsv,n 0,%r4,comib_tests_2
+ comib,ev,n 0,%r4,comib_tests_2
+
+addb_tests_1
+ addb %r1,%r4,addb_tests_1
+ addb,= %r1,%r4,addb_tests_1
+ addb,< %r1,%r4,addb_tests_1
+ addb,<= %r1,%r4,addb_tests_1
+ addb,nuv %r1,%r4,addb_tests_1
+ addb,znv %r1,%r4,addb_tests_1
+ addb,sv %r1,%r4,addb_tests_1
+ addb,od %r1,%r4,addb_tests_1
+
+addb_tests_2
+ addb,tr %r1,%r4,addb_tests_2
+ addb,<> %r1,%r4,addb_tests_2
+ addb,>= %r1,%r4,addb_tests_2
+ addb,> %r1,%r4,addb_tests_2
+ addb,uv %r1,%r4,addb_tests_2
+ addb,vnz %r1,%r4,addb_tests_2
+ addb,nsv %r1,%r4,addb_tests_2
+ addb,ev %r1,%r4,addb_tests_2
+
+addb_nullified_tests_1
+ addb,n %r1,%r4,addb_tests_1
+ addb,=,n %r1,%r4,addb_tests_1
+ addb,<,n %r1,%r4,addb_tests_1
+ addb,<=,n %r1,%r4,addb_tests_1
+ addb,nuv,n %r1,%r4,addb_tests_1
+ addb,znv,n %r1,%r4,addb_tests_1
+ addb,sv,n %r1,%r4,addb_tests_1
+ addb,od,n %r1,%r4,addb_tests_1
+
+addb_nullified_tests_2
+ addb,tr,n %r1,%r4,addb_tests_2
+ addb,<>,n %r1,%r4,addb_tests_2
+ addb,>=,n %r1,%r4,addb_tests_2
+ addb,>,n %r1,%r4,addb_tests_2
+ addb,uv,n %r1,%r4,addb_tests_2
+ addb,vnz,n %r1,%r4,addb_tests_2
+ addb,nsv,n %r1,%r4,addb_tests_2
+ addb,ev,n %r1,%r4,addb_tests_2
+
+addib_tests_1
+ addib -1,%r4,addib_tests_1
+ addib,= -1,%r4,addib_tests_1
+ addib,< -1,%r4,addib_tests_1
+ addib,<= -1,%r4,addib_tests_1
+ addib,nuv -1,%r4,addib_tests_1
+ addib,znv -1,%r4,addib_tests_1
+ addib,sv -1,%r4,addib_tests_1
+ addib,od -1,%r4,addib_tests_1
+
+addib_tests_2
+ addib,tr -1,%r4,addib_tests_2
+ addib,<> -1,%r4,addib_tests_2
+ addib,>= -1,%r4,addib_tests_2
+ addib,> -1,%r4,addib_tests_2
+ addib,uv -1,%r4,addib_tests_2
+ addib,vnz -1,%r4,addib_tests_2
+ addib,nsv -1,%r4,addib_tests_2
+ addib,ev -1,%r4,addib_tests_2
+
+addib_nullified_tests_1
+ addib,n -1,%r4,addib_tests_1
+ addib,=,n -1,%r4,addib_tests_1
+ addib,<,n -1,%r4,addib_tests_1
+ addib,<=,n -1,%r4,addib_tests_1
+ addib,nuv,n -1,%r4,addib_tests_1
+ addib,znv,n -1,%r4,addib_tests_1
+ addib,sv,n -1,%r4,addib_tests_1
+ addib,od,n -1,%r4,addib_tests_1
+
+addib_nullified_tests_2
+ addib,tr,n -1,%r4,addib_tests_2
+ addib,<>,n -1,%r4,addib_tests_2
+ addib,>=,n -1,%r4,addib_tests_2
+ addib,>,n -1,%r4,addib_tests_2
+ addib,uv,n -1,%r4,addib_tests_2
+ addib,vnz,n -1,%r4,addib_tests_2
+ addib,nsv,n -1,%r4,addib_tests_2
+ addib,ev,n -1,%r4,addib_tests_2
+
+
+; Needs to check lots of stuff (like corner bit cases)
+bb_tests
+ bvb,< %r4,bb_tests
+ bvb,>= %r4,bb_tests
+ bvb,<,n %r4,bb_tests
+ bvb,>=,n %r4,bb_tests
+ bb,< %r4,5,bb_tests
+ bb,>= %r4,5,bb_tests
+ bb,<,n %r4,5,bb_tests
+ bb,>=,n %r4,5,bb_tests
+
+; Computational instructions
+add_tests
+ add %r4,%r5,%r6
+ add,= %r4,%r5,%r6
+ add,< %r4,%r5,%r6
+ add,<= %r4,%r5,%r6
+ add,nuv %r4,%r5,%r6
+ add,znv %r4,%r5,%r6
+ add,sv %r4,%r5,%r6
+ add,od %r4,%r5,%r6
+ add,tr %r4,%r5,%r6
+ add,<> %r4,%r5,%r6
+ add,>= %r4,%r5,%r6
+ add,> %r4,%r5,%r6
+ add,uv %r4,%r5,%r6
+ add,vnz %r4,%r5,%r6
+ add,nsv %r4,%r5,%r6
+ add,ev %r4,%r5,%r6
+
+addl_tests
+ addl %r4,%r5,%r6
+ addl,= %r4,%r5,%r6
+ addl,< %r4,%r5,%r6
+ addl,<= %r4,%r5,%r6
+ addl,nuv %r4,%r5,%r6
+ addl,znv %r4,%r5,%r6
+ addl,sv %r4,%r5,%r6
+ addl,od %r4,%r5,%r6
+ addl,tr %r4,%r5,%r6
+ addl,<> %r4,%r5,%r6
+ addl,>= %r4,%r5,%r6
+ addl,> %r4,%r5,%r6
+ addl,uv %r4,%r5,%r6
+ addl,vnz %r4,%r5,%r6
+ addl,nsv %r4,%r5,%r6
+ addl,ev %r4,%r5,%r6
+
+addo_tests
+ addo %r4,%r5,%r6
+ addo,= %r4,%r5,%r6
+ addo,< %r4,%r5,%r6
+ addo,<= %r4,%r5,%r6
+ addo,nuv %r4,%r5,%r6
+ addo,znv %r4,%r5,%r6
+ addo,sv %r4,%r5,%r6
+ addo,od %r4,%r5,%r6
+ addo,tr %r4,%r5,%r6
+ addo,<> %r4,%r5,%r6
+ addo,>= %r4,%r5,%r6
+ addo,> %r4,%r5,%r6
+ addo,uv %r4,%r5,%r6
+ addo,vnz %r4,%r5,%r6
+ addo,nsv %r4,%r5,%r6
+ addo,ev %r4,%r5,%r6
+
+addc_tests
+ addc %r4,%r5,%r6
+ addc,= %r4,%r5,%r6
+ addc,< %r4,%r5,%r6
+ addc,<= %r4,%r5,%r6
+ addc,nuv %r4,%r5,%r6
+ addc,znv %r4,%r5,%r6
+ addc,sv %r4,%r5,%r6
+ addc,od %r4,%r5,%r6
+ addc,tr %r4,%r5,%r6
+ addc,<> %r4,%r5,%r6
+ addc,>= %r4,%r5,%r6
+ addc,> %r4,%r5,%r6
+ addc,uv %r4,%r5,%r6
+ addc,vnz %r4,%r5,%r6
+ addc,nsv %r4,%r5,%r6
+ addc,ev %r4,%r5,%r6
+
+addco_tests
+ addco %r4,%r5,%r6
+ addco,= %r4,%r5,%r6
+ addco,< %r4,%r5,%r6
+ addco,<= %r4,%r5,%r6
+ addco,nuv %r4,%r5,%r6
+ addco,znv %r4,%r5,%r6
+ addco,sv %r4,%r5,%r6
+ addco,od %r4,%r5,%r6
+ addco,tr %r4,%r5,%r6
+ addco,<> %r4,%r5,%r6
+ addco,>= %r4,%r5,%r6
+ addco,> %r4,%r5,%r6
+ addco,uv %r4,%r5,%r6
+ addco,vnz %r4,%r5,%r6
+ addco,nsv %r4,%r5,%r6
+ addco,ev %r4,%r5,%r6
+
+sh1add_tests
+ sh1add %r4,%r5,%r6
+ sh1add,= %r4,%r5,%r6
+ sh1add,< %r4,%r5,%r6
+ sh1add,<= %r4,%r5,%r6
+ sh1add,nuv %r4,%r5,%r6
+ sh1add,znv %r4,%r5,%r6
+ sh1add,sv %r4,%r5,%r6
+ sh1add,od %r4,%r5,%r6
+ sh1add,tr %r4,%r5,%r6
+ sh1add,<> %r4,%r5,%r6
+ sh1add,>= %r4,%r5,%r6
+ sh1add,> %r4,%r5,%r6
+ sh1add,uv %r4,%r5,%r6
+ sh1add,vnz %r4,%r5,%r6
+ sh1add,nsv %r4,%r5,%r6
+ sh1add,ev %r4,%r5,%r6
+
+sh1addl_tests
+ sh1addl %r4,%r5,%r6
+ sh1addl,= %r4,%r5,%r6
+ sh1addl,< %r4,%r5,%r6
+ sh1addl,<= %r4,%r5,%r6
+ sh1addl,nuv %r4,%r5,%r6
+ sh1addl,znv %r4,%r5,%r6
+ sh1addl,sv %r4,%r5,%r6
+ sh1addl,od %r4,%r5,%r6
+ sh1addl,tr %r4,%r5,%r6
+ sh1addl,<> %r4,%r5,%r6
+ sh1addl,>= %r4,%r5,%r6
+ sh1addl,> %r4,%r5,%r6
+ sh1addl,uv %r4,%r5,%r6
+ sh1addl,vnz %r4,%r5,%r6
+ sh1addl,nsv %r4,%r5,%r6
+ sh1addl,ev %r4,%r5,%r6
+
+sh1addo_tests
+ sh1addo %r4,%r5,%r6
+ sh1addo,= %r4,%r5,%r6
+ sh1addo,< %r4,%r5,%r6
+ sh1addo,<= %r4,%r5,%r6
+ sh1addo,nuv %r4,%r5,%r6
+ sh1addo,znv %r4,%r5,%r6
+ sh1addo,sv %r4,%r5,%r6
+ sh1addo,od %r4,%r5,%r6
+ sh1addo,tr %r4,%r5,%r6
+ sh1addo,<> %r4,%r5,%r6
+ sh1addo,>= %r4,%r5,%r6
+ sh1addo,> %r4,%r5,%r6
+ sh1addo,uv %r4,%r5,%r6
+ sh1addo,vnz %r4,%r5,%r6
+ sh1addo,nsv %r4,%r5,%r6
+ sh1addo,ev %r4,%r5,%r6
+
+
+sh2add_tests
+ sh2add %r4,%r5,%r6
+ sh2add,= %r4,%r5,%r6
+ sh2add,< %r4,%r5,%r6
+ sh2add,<= %r4,%r5,%r6
+ sh2add,nuv %r4,%r5,%r6
+ sh2add,znv %r4,%r5,%r6
+ sh2add,sv %r4,%r5,%r6
+ sh2add,od %r4,%r5,%r6
+ sh2add,tr %r4,%r5,%r6
+ sh2add,<> %r4,%r5,%r6
+ sh2add,>= %r4,%r5,%r6
+ sh2add,> %r4,%r5,%r6
+ sh2add,uv %r4,%r5,%r6
+ sh2add,vnz %r4,%r5,%r6
+ sh2add,nsv %r4,%r5,%r6
+ sh2add,ev %r4,%r5,%r6
+
+sh2addl_tests
+ sh2addl %r4,%r5,%r6
+ sh2addl,= %r4,%r5,%r6
+ sh2addl,< %r4,%r5,%r6
+ sh2addl,<= %r4,%r5,%r6
+ sh2addl,nuv %r4,%r5,%r6
+ sh2addl,znv %r4,%r5,%r6
+ sh2addl,sv %r4,%r5,%r6
+ sh2addl,od %r4,%r5,%r6
+ sh2addl,tr %r4,%r5,%r6
+ sh2addl,<> %r4,%r5,%r6
+ sh2addl,>= %r4,%r5,%r6
+ sh2addl,> %r4,%r5,%r6
+ sh2addl,uv %r4,%r5,%r6
+ sh2addl,vnz %r4,%r5,%r6
+ sh2addl,nsv %r4,%r5,%r6
+ sh2addl,ev %r4,%r5,%r6
+
+sh2addo_tests
+ sh2addo %r4,%r5,%r6
+ sh2addo,= %r4,%r5,%r6
+ sh2addo,< %r4,%r5,%r6
+ sh2addo,<= %r4,%r5,%r6
+ sh2addo,nuv %r4,%r5,%r6
+ sh2addo,znv %r4,%r5,%r6
+ sh2addo,sv %r4,%r5,%r6
+ sh2addo,od %r4,%r5,%r6
+ sh2addo,tr %r4,%r5,%r6
+ sh2addo,<> %r4,%r5,%r6
+ sh2addo,>= %r4,%r5,%r6
+ sh2addo,> %r4,%r5,%r6
+ sh2addo,uv %r4,%r5,%r6
+ sh2addo,vnz %r4,%r5,%r6
+ sh2addo,nsv %r4,%r5,%r6
+ sh2addo,ev %r4,%r5,%r6
+
+
+sh3add_tests
+ sh3add %r4,%r5,%r6
+ sh3add,= %r4,%r5,%r6
+ sh3add,< %r4,%r5,%r6
+ sh3add,<= %r4,%r5,%r6
+ sh3add,nuv %r4,%r5,%r6
+ sh3add,znv %r4,%r5,%r6
+ sh3add,sv %r4,%r5,%r6
+ sh3add,od %r4,%r5,%r6
+ sh3add,tr %r4,%r5,%r6
+ sh3add,<> %r4,%r5,%r6
+ sh3add,>= %r4,%r5,%r6
+ sh3add,> %r4,%r5,%r6
+ sh3add,uv %r4,%r5,%r6
+ sh3add,vnz %r4,%r5,%r6
+ sh3add,nsv %r4,%r5,%r6
+ sh3add,ev %r4,%r5,%r6
+
+sh3addl_tests
+ sh3addl %r4,%r5,%r6
+ sh3addl,= %r4,%r5,%r6
+ sh3addl,< %r4,%r5,%r6
+ sh3addl,<= %r4,%r5,%r6
+ sh3addl,nuv %r4,%r5,%r6
+ sh3addl,znv %r4,%r5,%r6
+ sh3addl,sv %r4,%r5,%r6
+ sh3addl,od %r4,%r5,%r6
+ sh3addl,tr %r4,%r5,%r6
+ sh3addl,<> %r4,%r5,%r6
+ sh3addl,>= %r4,%r5,%r6
+ sh3addl,> %r4,%r5,%r6
+ sh3addl,uv %r4,%r5,%r6
+ sh3addl,vnz %r4,%r5,%r6
+ sh3addl,nsv %r4,%r5,%r6
+ sh3addl,ev %r4,%r5,%r6
+
+sh3addo_tests
+ sh3addo %r4,%r5,%r6
+ sh3addo,= %r4,%r5,%r6
+ sh3addo,< %r4,%r5,%r6
+ sh3addo,<= %r4,%r5,%r6
+ sh3addo,nuv %r4,%r5,%r6
+ sh3addo,znv %r4,%r5,%r6
+ sh3addo,sv %r4,%r5,%r6
+ sh3addo,od %r4,%r5,%r6
+ sh3addo,tr %r4,%r5,%r6
+ sh3addo,<> %r4,%r5,%r6
+ sh3addo,>= %r4,%r5,%r6
+ sh3addo,> %r4,%r5,%r6
+ sh3addo,uv %r4,%r5,%r6
+ sh3addo,vnz %r4,%r5,%r6
+ sh3addo,nsv %r4,%r5,%r6
+ sh3addo,ev %r4,%r5,%r6
+
+
+sub_tests
+ sub %r4,%r5,%r6
+ sub,= %r4,%r5,%r6
+ sub,< %r4,%r5,%r6
+ sub,<= %r4,%r5,%r6
+ sub,<< %r4,%r5,%r6
+ sub,<<= %r4,%r5,%r6
+ sub,sv %r4,%r5,%r6
+ sub,od %r4,%r5,%r6
+ sub,tr %r4,%r5,%r6
+ sub,<> %r4,%r5,%r6
+ sub,>= %r4,%r5,%r6
+ sub,> %r4,%r5,%r6
+ sub,>>= %r4,%r5,%r6
+ sub,>> %r4,%r5,%r6
+ sub,nsv %r4,%r5,%r6
+ sub,ev %r4,%r5,%r6
+
+subo_tests
+ subo %r4,%r5,%r6
+ subo,= %r4,%r5,%r6
+ subo,< %r4,%r5,%r6
+ subo,<= %r4,%r5,%r6
+ subo,<< %r4,%r5,%r6
+ subo,<<= %r4,%r5,%r6
+ subo,sv %r4,%r5,%r6
+ subo,od %r4,%r5,%r6
+ subo,tr %r4,%r5,%r6
+ subo,<> %r4,%r5,%r6
+ subo,>= %r4,%r5,%r6
+ subo,> %r4,%r5,%r6
+ subo,>>= %r4,%r5,%r6
+ subo,>> %r4,%r5,%r6
+ subo,nsv %r4,%r5,%r6
+ subo,ev %r4,%r5,%r6
+
+subb_tests
+ subb %r4,%r5,%r6
+ subb,= %r4,%r5,%r6
+ subb,< %r4,%r5,%r6
+ subb,<= %r4,%r5,%r6
+ subb,<< %r4,%r5,%r6
+ subb,<<= %r4,%r5,%r6
+ subb,sv %r4,%r5,%r6
+ subb,od %r4,%r5,%r6
+ subb,tr %r4,%r5,%r6
+ subb,<> %r4,%r5,%r6
+ subb,>= %r4,%r5,%r6
+ subb,> %r4,%r5,%r6
+ subb,>>= %r4,%r5,%r6
+ subb,>> %r4,%r5,%r6
+ subb,nsv %r4,%r5,%r6
+ subb,ev %r4,%r5,%r6
+
+subbo_tests
+ subbo %r4,%r5,%r6
+ subbo,= %r4,%r5,%r6
+ subbo,< %r4,%r5,%r6
+ subbo,<= %r4,%r5,%r6
+ subbo,<< %r4,%r5,%r6
+ subbo,<<= %r4,%r5,%r6
+ subbo,sv %r4,%r5,%r6
+ subbo,od %r4,%r5,%r6
+ subbo,tr %r4,%r5,%r6
+ subbo,<> %r4,%r5,%r6
+ subbo,>= %r4,%r5,%r6
+ subbo,> %r4,%r5,%r6
+ subbo,>>= %r4,%r5,%r6
+ subbo,>> %r4,%r5,%r6
+ subbo,nsv %r4,%r5,%r6
+ subbo,ev %r4,%r5,%r6
+
+subt_tests
+ subt %r4,%r5,%r6
+ subt,= %r4,%r5,%r6
+ subt,< %r4,%r5,%r6
+ subt,<= %r4,%r5,%r6
+ subt,<< %r4,%r5,%r6
+ subt,<<= %r4,%r5,%r6
+ subt,sv %r4,%r5,%r6
+ subt,od %r4,%r5,%r6
+ subt,tr %r4,%r5,%r6
+ subt,<> %r4,%r5,%r6
+ subt,>= %r4,%r5,%r6
+ subt,> %r4,%r5,%r6
+ subt,>>= %r4,%r5,%r6
+ subt,>> %r4,%r5,%r6
+ subt,nsv %r4,%r5,%r6
+ subt,ev %r4,%r5,%r6
+
+subto_tests
+ subto %r4,%r5,%r6
+ subto,= %r4,%r5,%r6
+ subto,< %r4,%r5,%r6
+ subto,<= %r4,%r5,%r6
+ subto,<< %r4,%r5,%r6
+ subto,<<= %r4,%r5,%r6
+ subto,sv %r4,%r5,%r6
+ subto,od %r4,%r5,%r6
+ subto,tr %r4,%r5,%r6
+ subto,<> %r4,%r5,%r6
+ subto,>= %r4,%r5,%r6
+ subto,> %r4,%r5,%r6
+ subto,>>= %r4,%r5,%r6
+ subto,>> %r4,%r5,%r6
+ subto,nsv %r4,%r5,%r6
+ subto,ev %r4,%r5,%r6
+
+ds_tests
+ ds %r4,%r5,%r6
+ ds,= %r4,%r5,%r6
+ ds,< %r4,%r5,%r6
+ ds,<= %r4,%r5,%r6
+ ds,<< %r4,%r5,%r6
+ ds,<<= %r4,%r5,%r6
+ ds,sv %r4,%r5,%r6
+ ds,od %r4,%r5,%r6
+ ds,tr %r4,%r5,%r6
+ ds,<> %r4,%r5,%r6
+ ds,>= %r4,%r5,%r6
+ ds,> %r4,%r5,%r6
+ ds,>>= %r4,%r5,%r6
+ ds,>> %r4,%r5,%r6
+ ds,nsv %r4,%r5,%r6
+ ds,ev %r4,%r5,%r6
+
+comclr_tests
+ comclr %r4,%r5,%r6
+ comclr,= %r4,%r5,%r6
+ comclr,< %r4,%r5,%r6
+ comclr,<= %r4,%r5,%r6
+ comclr,<< %r4,%r5,%r6
+ comclr,<<= %r4,%r5,%r6
+ comclr,sv %r4,%r5,%r6
+ comclr,od %r4,%r5,%r6
+ comclr,tr %r4,%r5,%r6
+ comclr,<> %r4,%r5,%r6
+ comclr,>= %r4,%r5,%r6
+ comclr,> %r4,%r5,%r6
+ comclr,>>= %r4,%r5,%r6
+ comclr,>> %r4,%r5,%r6
+ comclr,nsv %r4,%r5,%r6
+ comclr,ev %r4,%r5,%r6
+
+or_tests
+ or %r4,%r5,%r6
+ or,= %r4,%r5,%r6
+ or,< %r4,%r5,%r6
+ or,<= %r4,%r5,%r6
+ or,od %r4,%r5,%r6
+ or,tr %r4,%r5,%r6
+ or,<> %r4,%r5,%r6
+ or,>= %r4,%r5,%r6
+ or,> %r4,%r5,%r6
+ or,ev %r4,%r5,%r6
+xor_tests
+ xor %r4,%r5,%r6
+ xor,= %r4,%r5,%r6
+ xor,< %r4,%r5,%r6
+ xor,<= %r4,%r5,%r6
+ xor,od %r4,%r5,%r6
+ xor,tr %r4,%r5,%r6
+ xor,<> %r4,%r5,%r6
+ xor,>= %r4,%r5,%r6
+ xor,> %r4,%r5,%r6
+ xor,ev %r4,%r5,%r6
+
+and_tests
+ and %r4,%r5,%r6
+ and,= %r4,%r5,%r6
+ and,< %r4,%r5,%r6
+ and,<= %r4,%r5,%r6
+ and,od %r4,%r5,%r6
+ and,tr %r4,%r5,%r6
+ and,<> %r4,%r5,%r6
+ and,>= %r4,%r5,%r6
+ and,> %r4,%r5,%r6
+ and,ev %r4,%r5,%r6
+
+andcm_tests
+ andcm %r4,%r5,%r6
+ andcm,= %r4,%r5,%r6
+ andcm,< %r4,%r5,%r6
+ andcm,<= %r4,%r5,%r6
+ andcm,od %r4,%r5,%r6
+ andcm,tr %r4,%r5,%r6
+ andcm,<> %r4,%r5,%r6
+ andcm,>= %r4,%r5,%r6
+ andcm,> %r4,%r5,%r6
+ andcm,ev %r4,%r5,%r6
+
+
+uxor_tests
+ uxor %r4,%r5,%r6
+ uxor,sbz %r4,%r5,%r6
+ uxor,shz %r4,%r5,%r6
+ uxor,sdc %r4,%r5,%r6
+ uxor,sbc %r4,%r5,%r6
+ uxor,shc %r4,%r5,%r6
+ uxor,tr %r4,%r5,%r6
+ uxor,nbz %r4,%r5,%r6
+ uxor,nhz %r4,%r5,%r6
+ uxor,ndc %r4,%r5,%r6
+ uxor,nbc %r4,%r5,%r6
+ uxor,nhc %r4,%r5,%r6
+
+uaddcm_tests
+ uaddcm %r4,%r5,%r6
+ uaddcm,sbz %r4,%r5,%r6
+ uaddcm,shz %r4,%r5,%r6
+ uaddcm,sdc %r4,%r5,%r6
+ uaddcm,sbc %r4,%r5,%r6
+ uaddcm,shc %r4,%r5,%r6
+ uaddcm,tr %r4,%r5,%r6
+ uaddcm,nbz %r4,%r5,%r6
+ uaddcm,nhz %r4,%r5,%r6
+ uaddcm,ndc %r4,%r5,%r6
+ uaddcm,nbc %r4,%r5,%r6
+ uaddcm,nhc %r4,%r5,%r6
+
+uaddcmt_tests
+ uaddcmt %r4,%r5,%r6
+ uaddcmt,sbz %r4,%r5,%r6
+ uaddcmt,shz %r4,%r5,%r6
+ uaddcmt,sdc %r4,%r5,%r6
+ uaddcmt,sbc %r4,%r5,%r6
+ uaddcmt,shc %r4,%r5,%r6
+ uaddcmt,tr %r4,%r5,%r6
+ uaddcmt,nbz %r4,%r5,%r6
+ uaddcmt,nhz %r4,%r5,%r6
+ uaddcmt,ndc %r4,%r5,%r6
+ uaddcmt,nbc %r4,%r5,%r6
+ uaddcmt,nhc %r4,%r5,%r6
+
+dcor_tests
+ dcor %r4,%r5
+ dcor,sbz %r4,%r5
+ dcor,shz %r4,%r5
+ dcor,sdc %r4,%r5
+ dcor,sbc %r4,%r5
+ dcor,shc %r4,%r5
+ dcor,tr %r4,%r5
+ dcor,nbz %r4,%r5
+ dcor,nhz %r4,%r5
+ dcor,ndc %r4,%r5
+ dcor,nbc %r4,%r5
+ dcor,nhc %r4,%r5
+
+idcor_tests
+ idcor %r4,%r5
+ idcor,sbz %r4,%r5
+ idcor,shz %r4,%r5
+ idcor,sdc %r4,%r5
+ idcor,sbc %r4,%r5
+ idcor,shc %r4,%r5
+ idcor,tr %r4,%r5
+ idcor,nbz %r4,%r5
+ idcor,nhz %r4,%r5
+ idcor,ndc %r4,%r5
+ idcor,nbc %r4,%r5
+ idcor,nhc %r4,%r5
+
+addi_tests
+ addi 123,%r5,%r6
+ addi,= 123,%r5,%r6
+ addi,< 123,%r5,%r6
+ addi,<= 123,%r5,%r6
+ addi,nuv 123,%r5,%r6
+ addi,znv 123,%r5,%r6
+ addi,sv 123,%r5,%r6
+ addi,od 123,%r5,%r6
+ addi,tr 123,%r5,%r6
+ addi,<> 123,%r5,%r6
+ addi,>= 123,%r5,%r6
+ addi,> 123,%r5,%r6
+ addi,uv 123,%r5,%r6
+ addi,vnz 123,%r5,%r6
+ addi,nsv 123,%r5,%r6
+ addi,ev 123,%r5,%r6
+
+addio_tests
+ addio 123,%r5,%r6
+ addio,= 123,%r5,%r6
+ addio,< 123,%r5,%r6
+ addio,<= 123,%r5,%r6
+ addio,nuv 123,%r5,%r6
+ addio,znv 123,%r5,%r6
+ addio,sv 123,%r5,%r6
+ addio,od 123,%r5,%r6
+ addio,tr 123,%r5,%r6
+ addio,<> 123,%r5,%r6
+ addio,>= 123,%r5,%r6
+ addio,> 123,%r5,%r6
+ addio,uv 123,%r5,%r6
+ addio,vnz 123,%r5,%r6
+ addio,nsv 123,%r5,%r6
+ addio,ev 123,%r5,%r6
+
+addit_tests
+ addit 123,%r5,%r6
+ addit,= 123,%r5,%r6
+ addit,< 123,%r5,%r6
+ addit,<= 123,%r5,%r6
+ addit,nuv 123,%r5,%r6
+ addit,znv 123,%r5,%r6
+ addit,sv 123,%r5,%r6
+ addit,od 123,%r5,%r6
+ addit,tr 123,%r5,%r6
+ addit,<> 123,%r5,%r6
+ addit,>= 123,%r5,%r6
+ addit,> 123,%r5,%r6
+ addit,uv 123,%r5,%r6
+ addit,vnz 123,%r5,%r6
+ addit,nsv 123,%r5,%r6
+ addit,ev 123,%r5,%r6
+
+addito_tests
+ addito 123,%r5,%r6
+ addito,= 123,%r5,%r6
+ addito,< 123,%r5,%r6
+ addito,<= 123,%r5,%r6
+ addito,nuv 123,%r5,%r6
+ addito,znv 123,%r5,%r6
+ addito,sv 123,%r5,%r6
+ addito,od 123,%r5,%r6
+ addito,tr 123,%r5,%r6
+ addito,<> 123,%r5,%r6
+ addito,>= 123,%r5,%r6
+ addito,> 123,%r5,%r6
+ addito,uv 123,%r5,%r6
+ addito,vnz 123,%r5,%r6
+ addito,nsv 123,%r5,%r6
+ addito,ev 123,%r5,%r6
+
+subi_tests
+ subi 123,%r5,%r6
+ subi,= 123,%r5,%r6
+ subi,< 123,%r5,%r6
+ subi,<= 123,%r5,%r6
+ subi,<< 123,%r5,%r6
+ subi,<<= 123,%r5,%r6
+ subi,sv 123,%r5,%r6
+ subi,od 123,%r5,%r6
+ subi,tr 123,%r5,%r6
+ subi,<> 123,%r5,%r6
+ subi,>= 123,%r5,%r6
+ subi,> 123,%r5,%r6
+ subi,>>= 123,%r5,%r6
+ subi,>> 123,%r5,%r6
+ subi,nsv 123,%r5,%r6
+ subi,ev 123,%r5,%r6
+
+subio_tests
+ subio 123,%r5,%r6
+ subio,= 123,%r5,%r6
+ subio,< 123,%r5,%r6
+ subio,<= 123,%r5,%r6
+ subio,<< 123,%r5,%r6
+ subio,<<= 123,%r5,%r6
+ subio,sv 123,%r5,%r6
+ subio,od 123,%r5,%r6
+ subio,tr 123,%r5,%r6
+ subio,<> 123,%r5,%r6
+ subio,>= 123,%r5,%r6
+ subio,> 123,%r5,%r6
+ subio,>>= 123,%r5,%r6
+ subio,>> 123,%r5,%r6
+ subio,nsv 123,%r5,%r6
+ subio,ev 123,%r5,%r6
+
+comiclr_tests
+ comiclr 123,%r5,%r6
+ comiclr,= 123,%r5,%r6
+ comiclr,< 123,%r5,%r6
+ comiclr,<= 123,%r5,%r6
+ comiclr,<< 123,%r5,%r6
+ comiclr,<<= 123,%r5,%r6
+ comiclr,sv 123,%r5,%r6
+ comiclr,od 123,%r5,%r6
+ comiclr,tr 123,%r5,%r6
+ comiclr,<> 123,%r5,%r6
+ comiclr,>= 123,%r5,%r6
+ comiclr,> 123,%r5,%r6
+ comiclr,>>= 123,%r5,%r6
+ comiclr,>> 123,%r5,%r6
+ comiclr,nsv 123,%r5,%r6
+ comiclr,ev 123,%r5,%r6
+
+vshd_tests
+ vshd %r4,%r5,%r6
+ vshd,= %r4,%r5,%r6
+ vshd,< %r4,%r5,%r6
+ vshd,od %r4,%r5,%r6
+ vshd,tr %r4,%r5,%r6
+ vshd,<> %r4,%r5,%r6
+ vshd,>= %r4,%r5,%r6
+ vshd,ev %r4,%r5,%r6
+
+shd_tests
+ shd %r4,%r5,5,%r6
+ shd,= %r4,%r5,5,%r6
+ shd,< %r4,%r5,5,%r6
+ shd,od %r4,%r5,5,%r6
+ shd,tr %r4,%r5,5,%r6
+ shd,<> %r4,%r5,5,%r6
+ shd,>= %r4,%r5,5,%r6
+ shd,ev %r4,%r5,5,%r6
+
+extru_tests
+ extru %r4,5,10,%r6
+ extru,= %r4,5,10,%r6
+ extru,< %r4,5,10,%r6
+ extru,od %r4,5,10,%r6
+ extru,tr %r4,5,10,%r6
+ extru,<> %r4,5,10,%r6
+ extru,>= %r4,5,10,%r6
+ extru,ev %r4,5,10,%r6
+
+extrs_tests
+ extrs %r4,5,10,%r6
+ extrs,= %r4,5,10,%r6
+ extrs,< %r4,5,10,%r6
+ extrs,od %r4,5,10,%r6
+ extrs,tr %r4,5,10,%r6
+ extrs,<> %r4,5,10,%r6
+ extrs,>= %r4,5,10,%r6
+ extrs,ev %r4,5,10,%r6
+
+zdep_tests
+ zdep %r4,5,10,%r6
+ zdep,= %r4,5,10,%r6
+ zdep,< %r4,5,10,%r6
+ zdep,od %r4,5,10,%r6
+ zdep,tr %r4,5,10,%r6
+ zdep,<> %r4,5,10,%r6
+ zdep,>= %r4,5,10,%r6
+ zdep,ev %r4,5,10,%r6
+
+dep_tests
+ dep %r4,5,10,%r6
+ dep,= %r4,5,10,%r6
+ dep,< %r4,5,10,%r6
+ dep,od %r4,5,10,%r6
+ dep,tr %r4,5,10,%r6
+ dep,<> %r4,5,10,%r6
+ dep,>= %r4,5,10,%r6
+ dep,ev %r4,5,10,%r6
+
+vextru_tests
+ vextru %r4,5,%r6
+ vextru,= %r4,5,%r6
+ vextru,< %r4,5,%r6
+ vextru,od %r4,5,%r6
+ vextru,tr %r4,5,%r6
+ vextru,<> %r4,5,%r6
+ vextru,>= %r4,5,%r6
+ vextru,ev %r4,5,%r6
+
+vextrs_tests
+ vextrs %r4,5,%r6
+ vextrs,= %r4,5,%r6
+ vextrs,< %r4,5,%r6
+ vextrs,od %r4,5,%r6
+ vextrs,tr %r4,5,%r6
+ vextrs,<> %r4,5,%r6
+ vextrs,>= %r4,5,%r6
+ vextrs,ev %r4,5,%r6
+
+zvdep_tests
+ zvdep %r4,5,%r6
+ zvdep,= %r4,5,%r6
+ zvdep,< %r4,5,%r6
+ zvdep,od %r4,5,%r6
+ zvdep,tr %r4,5,%r6
+ zvdep,<> %r4,5,%r6
+ zvdep,>= %r4,5,%r6
+ zvdep,ev %r4,5,%r6
+
+
+vdep_tests
+ vdep %r4,5,%r6
+ vdep,= %r4,5,%r6
+ vdep,< %r4,5,%r6
+ vdep,od %r4,5,%r6
+ vdep,tr %r4,5,%r6
+ vdep,<> %r4,5,%r6
+ vdep,>= %r4,5,%r6
+ vdep,ev %r4,5,%r6
+
+vdepi_tests
+ vdepi -1,5,%r6
+ vdepi,= -1,5,%r6
+ vdepi,< -1,5,%r6
+ vdepi,od -1,5,%r6
+ vdepi,tr -1,5,%r6
+ vdepi,<> -1,5,%r6
+ vdepi,>= -1,5,%r6
+ vdepi,ev -1,5,%r6
+
+zvdepi_tests
+ zvdepi -1,5,%r6
+ zvdepi,= -1,5,%r6
+ zvdepi,< -1,5,%r6
+ zvdepi,od -1,5,%r6
+ zvdepi,tr -1,5,%r6
+ zvdepi,<> -1,5,%r6
+ zvdepi,>= -1,5,%r6
+ zvdepi,ev -1,5,%r6
+
+depi_tests
+ depi -1,4,10,%r6
+ depi,= -1,4,10,%r6
+ depi,< -1,4,10,%r6
+ depi,od -1,4,10,%r6
+ depi,tr -1,4,10,%r6
+ depi,<> -1,4,10,%r6
+ depi,>= -1,4,10,%r6
+ depi,ev -1,4,10,%r6
+
+zdepi_tests
+ zdepi -1,4,10,%r6
+ zdepi,= -1,4,10,%r6
+ zdepi,< -1,4,10,%r6
+ zdepi,od -1,4,10,%r6
+ zdepi,tr -1,4,10,%r6
+ zdepi,<> -1,4,10,%r6
+ zdepi,>= -1,4,10,%r6
+ zdepi,ev -1,4,10,%r6
+
+
+system_control_tests
+ break 5,12
+ rfi
+ rfir
+ ssm 5,%r4
+ rsm 5,%r4
+ mtsm %r4
+ ldsid (%sr0,%r5),%r4
+ mtsp %r4,%sr0
+ mtctl %r4,%cr10
+ mfsp %sr0,%r4
+ mfctl %cr10,%r4
+ sync
+ syncdma
+ diag 1234
+
+probe_tests
+ prober (%sr0,%r5),%r6,%r7
+ proberi (%sr0,%r5),1,%r7
+ probew (%sr0,%r5),%r6,%r7
+ probewi (%sr0,%r5),1,%r7
+
+lpa_tests
+ lpa %r4(%sr0,%r5),%r6
+ lpa,m %r4(%sr0,%r5),%r6
+ lha %r4(%sr0,%r5),%r6
+ lha,m %r4(%sr0,%r5),%r6
+ lci %r4(%sr0,%r5),%r6
+
+purge_tests
+ pdtlb %r4(%sr0,%r5)
+ pdtlb,m %r4(%sr0,%r5)
+ pitlb %r4(%sr0,%r5)
+ pitlb,m %r4(%sr0,%r5)
+ pdtlbe %r4(%sr0,%r5)
+ pdtlbe,m %r4(%sr0,%r5)
+ pitlbe %r4(%sr0,%r5)
+ pitlbe,m %r4(%sr0,%r5)
+ pdc %r4(%sr0,%r5)
+ pdc,m %r4(%sr0,%r5)
+ fdc %r4(%sr0,%r5)
+ fdc,m %r4(%sr0,%r5)
+ fic %r4(%sr0,%r5)
+ fic,m %r4(%sr0,%r5)
+ fdce %r4(%sr0,%r5)
+ fdce,m %r4(%sr0,%r5)
+ fice %r4(%sr0,%r5)
+ fice,m %r4(%sr0,%r5)
+
+insert_tests
+ idtlba %r4,(%sr0,%r5)
+ iitlba %r4,(%sr0,%r5)
+ idtlbp %r4,(%sr0,%r5)
+ iitlbp %r4,(%sr0,%r5)
+
+fpu_misc_tests
+ ftest
+
+fpu_memory_indexing_tests
+ fldwx %r4(%sr0,%r5),%fr6
+ fldwx,s %r4(%sr0,%r5),%fr6
+ fldwx,m %r4(%sr0,%r5),%fr6
+ fldwx,sm %r4(%sr0,%r5),%fr6
+ flddx %r4(%sr0,%r5),%fr6
+ flddx,s %r4(%sr0,%r5),%fr6
+ flddx,m %r4(%sr0,%r5),%fr6
+ flddx,sm %r4(%sr0,%r5),%fr6
+ fstwx %fr6,%r4(%sr0,%r5)
+ fstwx,s %fr6,%r4(%sr0,%r5)
+ fstwx,m %fr6,%r4(%sr0,%r5)
+ fstwx,sm %fr6,%r4(%sr0,%r5)
+ fstdx %fr6,%r4(%sr0,%r5)
+ fstdx,s %fr6,%r4(%sr0,%r5)
+ fstdx,m %fr6,%r4(%sr0,%r5)
+ fstdx,sm %fr6,%r4(%sr0,%r5)
+ fstqx %fr6,%r4(%sr0,%r5)
+ fstqx,s %fr6,%r4(%sr0,%r5)
+ fstqx,m %fr6,%r4(%sr0,%r5)
+ fstqx,sm %fr6,%r4(%sr0,%r5)
+
+fpu_short_memory_tests
+ fldws 0(%sr0,%r5),%fr6
+ fldws,mb 0(%sr0,%r5),%fr6
+ fldws,ma 0(%sr0,%r5),%fr6
+ fldds 0(%sr0,%r5),%fr6
+ fldds,mb 0(%sr0,%r5),%fr6
+ fldds,ma 0(%sr0,%r5),%fr6
+ fstws %fr6,0(%sr0,%r5)
+ fstws,mb %fr6,0(%sr0,%r5)
+ fstws,ma %fr6,0(%sr0,%r5)
+ fstds %fr6,0(%sr0,%r5)
+ fstds,mb %fr6,0(%sr0,%r5)
+ fstds,ma %fr6,0(%sr0,%r5)
+ fstqs %fr6,0(%sr0,%r5)
+ fstqs,mb %fr6,0(%sr0,%r5)
+ fstqs,ma %fr6,0(%sr0,%r5)
+
+
+fcpy_tests
+ fcpy,sgl %fr5,%fr10
+ fcpy,dbl %fr5,%fr10
+ fcpy,quad %fr5,%fr10
+ fcpy,sgl %fr20,%fr24
+ fcpy,dbl %fr20,%fr24
+
+fabs_tests
+ fabs,sgl %fr5,%fr10
+ fabs,dbl %fr5,%fr10
+ fabs,quad %fr5,%fr10
+ fabs,sgl %fr20,%fr24
+ fabs,dbl %fr20,%fr24
+
+fsqrt_tests
+ fsqrt,sgl %fr5,%fr10
+ fsqrt,dbl %fr5,%fr10
+ fsqrt,quad %fr5,%fr10
+ fsqrt,sgl %fr20,%fr24
+ fsqrt,dbl %fr20,%fr24
+
+frnd_tests
+ frnd,sgl %fr5,%fr10
+ frnd,dbl %fr5,%fr10
+ frnd,quad %fr5,%fr10
+ frnd,sgl %fr20,%fr24
+ frnd,dbl %fr20,%fr24
+
+fcnvff_tests
+ fcnvff,sgl,sgl %fr5,%fr10
+ fcnvff,sgl,dbl %fr5,%fr10
+ fcnvff,sgl,quad %fr5,%fr10
+ fcnvff,dbl,sgl %fr5,%fr10
+ fcnvff,dbl,dbl %fr5,%fr10
+ fcnvff,dbl,quad %fr5,%fr10
+ fcnvff,quad,sgl %fr5,%fr10
+ fcnvff,quad,dbl %fr5,%fr10
+ fcnvff,quad,quad %fr5,%fr10
+ fcnvff,sgl,sgl %fr20,%fr24
+ fcnvff,sgl,dbl %fr20,%fr24
+ fcnvff,sgl,quad %fr20,%fr24
+ fcnvff,dbl,sgl %fr20,%fr24
+ fcnvff,dbl,dbl %fr20,%fr24
+ fcnvff,dbl,quad %fr20,%fr24
+ fcnvff,quad,sgl %fr20,%fr24
+ fcnvff,quad,dbl %fr20,%fr24
+ fcnvff,quad,quad %fr20,%fr24
+
+fcnvxf_tests
+ fcnvxf,sgl,sgl %fr5,%fr10
+ fcnvxf,sgl,dbl %fr5,%fr10
+ fcnvxf,sgl,quad %fr5,%fr10
+ fcnvxf,dbl,sgl %fr5,%fr10
+ fcnvxf,dbl,dbl %fr5,%fr10
+ fcnvxf,dbl,quad %fr5,%fr10
+ fcnvxf,quad,sgl %fr5,%fr10
+ fcnvxf,quad,dbl %fr5,%fr10
+ fcnvxf,quad,quad %fr5,%fr10
+ fcnvxf,sgl,sgl %fr20,%fr24
+ fcnvxf,sgl,dbl %fr20,%fr24
+ fcnvxf,sgl,quad %fr20,%fr24
+ fcnvxf,dbl,sgl %fr20,%fr24
+ fcnvxf,dbl,dbl %fr20,%fr24
+ fcnvxf,dbl,quad %fr20,%fr24
+ fcnvxf,quad,sgl %fr20,%fr24
+ fcnvxf,quad,dbl %fr20,%fr24
+ fcnvxf,quad,quad %fr20,%fr24
+
+fcnvfx_tests
+ fcnvfx,sgl,sgl %fr5,%fr10
+ fcnvfx,sgl,dbl %fr5,%fr10
+ fcnvfx,sgl,quad %fr5,%fr10
+ fcnvfx,dbl,sgl %fr5,%fr10
+ fcnvfx,dbl,dbl %fr5,%fr10
+ fcnvfx,dbl,quad %fr5,%fr10
+ fcnvfx,quad,sgl %fr5,%fr10
+ fcnvfx,quad,dbl %fr5,%fr10
+ fcnvfx,quad,quad %fr5,%fr10
+ fcnvfx,sgl,sgl %fr20,%fr24
+ fcnvfx,sgl,dbl %fr20,%fr24
+ fcnvfx,sgl,quad %fr20,%fr24
+ fcnvfx,dbl,sgl %fr20,%fr24
+ fcnvfx,dbl,dbl %fr20,%fr24
+ fcnvfx,dbl,quad %fr20,%fr24
+ fcnvfx,quad,sgl %fr20,%fr24
+ fcnvfx,quad,dbl %fr20,%fr24
+ fcnvfx,quad,quad %fr20,%fr24
+
+fcnvfxt_tests
+ fcnvfxt,sgl,sgl %fr5,%fr10
+ fcnvfxt,sgl,dbl %fr5,%fr10
+ fcnvfxt,sgl,quad %fr5,%fr10
+ fcnvfxt,dbl,sgl %fr5,%fr10
+ fcnvfxt,dbl,dbl %fr5,%fr10
+ fcnvfxt,dbl,quad %fr5,%fr10
+ fcnvfxt,quad,sgl %fr5,%fr10
+ fcnvfxt,quad,dbl %fr5,%fr10
+ fcnvfxt,quad,quad %fr5,%fr10
+ fcnvfxt,sgl,sgl %fr20,%fr24
+ fcnvfxt,sgl,dbl %fr20,%fr24
+ fcnvfxt,sgl,quad %fr20,%fr24
+ fcnvfxt,dbl,sgl %fr20,%fr24
+ fcnvfxt,dbl,dbl %fr20,%fr24
+ fcnvfxt,dbl,quad %fr20,%fr24
+ fcnvfxt,quad,sgl %fr20,%fr24
+ fcnvfxt,quad,dbl %fr20,%fr24
+ fcnvfxt,quad,quad %fr20,%fr24
+
+fadd_tests
+ fadd,sgl %fr4,%fr8,%fr12
+ fadd,dbl %fr4,%fr8,%fr12
+ fadd,quad %fr4,%fr8,%fr12
+ fadd,sgl %fr20,%fr24,%fr28
+ fadd,dbl %fr20,%fr24,%fr28
+ fadd,quad %fr20,%fr24,%fr28
+
+fsub_tests
+ fsub,sgl %fr4,%fr8,%fr12
+ fsub,dbl %fr4,%fr8,%fr12
+ fsub,quad %fr4,%fr8,%fr12
+ fsub,sgl %fr20,%fr24,%fr28
+ fsub,dbl %fr20,%fr24,%fr28
+ fsub,quad %fr20,%fr24,%fr28
+
+fmpy_tests
+ fmpy,sgl %fr4,%fr8,%fr12
+ fmpy,dbl %fr4,%fr8,%fr12
+ fmpy,quad %fr4,%fr8,%fr12
+ fmpy,sgl %fr20,%fr24,%fr28
+ fmpy,dbl %fr20,%fr24,%fr28
+ fmpy,quad %fr20,%fr24,%fr28
+
+fdiv_tests
+ fdiv,sgl %fr4,%fr8,%fr12
+ fdiv,dbl %fr4,%fr8,%fr12
+ fdiv,quad %fr4,%fr8,%fr12
+ fdiv,sgl %fr20,%fr24,%fr28
+ fdiv,dbl %fr20,%fr24,%fr28
+ fdiv,quad %fr20,%fr24,%fr28
+
+frem_tests
+ frem,sgl %fr4,%fr8,%fr12
+ frem,dbl %fr4,%fr8,%fr12
+ frem,quad %fr4,%fr8,%fr12
+ frem,sgl %fr20,%fr24,%fr28
+ frem,dbl %fr20,%fr24,%fr28
+ frem,quad %fr20,%fr24,%fr28
+
+fcmp_sgl_tests_1
+ fcmp,sgl,false? %fr4,%fr5
+ fcmp,sgl,false %fr4,%fr5
+ fcmp,sgl,? %fr4,%fr5
+ fcmp,sgl,!<=> %fr4,%fr5
+ fcmp,sgl,= %fr4,%fr5
+ fcmp,sgl,=T %fr4,%fr5
+ fcmp,sgl,?= %fr4,%fr5
+ fcmp,sgl,!<> %fr4,%fr5
+fcmp_sgl_tests_2
+ fcmp,sgl,!?>= %fr4,%fr5
+ fcmp,sgl,< %fr4,%fr5
+ fcmp,sgl,?< %fr4,%fr5
+ fcmp,sgl,!>= %fr4,%fr5
+ fcmp,sgl,!?> %fr4,%fr5
+ fcmp,sgl,<= %fr4,%fr5
+ fcmp,sgl,?<= %fr4,%fr5
+ fcmp,sgl,!> %fr4,%fr5
+fcmp_sgl_tests_3
+ fcmp,sgl,!?<= %fr4,%fr5
+ fcmp,sgl,> %fr4,%fr5
+ fcmp,sgl,?> %fr4,%fr5
+ fcmp,sgl,!<= %fr4,%fr5
+ fcmp,sgl,!?< %fr4,%fr5
+ fcmp,sgl,>= %fr4,%fr5
+ fcmp,sgl,?>= %fr4,%fr5
+ fcmp,sgl,!< %fr4,%fr5
+fcmp_sgl_tests_4
+ fcmp,sgl,!?= %fr4,%fr5
+ fcmp,sgl,<> %fr4,%fr5
+ fcmp,sgl,!= %fr4,%fr5
+ fcmp,sgl,!=T %fr4,%fr5
+ fcmp,sgl,!? %fr4,%fr5
+ fcmp,sgl,<=> %fr4,%fr5
+ fcmp,sgl,true? %fr4,%fr5
+ fcmp,sgl,true %fr4,%fr5
+
+fcmp_dbl_tests_1
+ fcmp,dbl,false? %fr4,%fr5
+ fcmp,dbl,false %fr4,%fr5
+ fcmp,dbl,? %fr4,%fr5
+ fcmp,dbl,!<=> %fr4,%fr5
+ fcmp,dbl,= %fr4,%fr5
+ fcmp,dbl,=T %fr4,%fr5
+ fcmp,dbl,?= %fr4,%fr5
+ fcmp,dbl,!<> %fr4,%fr5
+fcmp_dbl_tests_2
+ fcmp,dbl,!?>= %fr4,%fr5
+ fcmp,dbl,< %fr4,%fr5
+ fcmp,dbl,?< %fr4,%fr5
+ fcmp,dbl,!>= %fr4,%fr5
+ fcmp,dbl,!?> %fr4,%fr5
+ fcmp,dbl,<= %fr4,%fr5
+ fcmp,dbl,?<= %fr4,%fr5
+ fcmp,dbl,!> %fr4,%fr5
+fcmp_dbl_tests_3
+ fcmp,dbl,!?<= %fr4,%fr5
+ fcmp,dbl,> %fr4,%fr5
+ fcmp,dbl,?> %fr4,%fr5
+ fcmp,dbl,!<= %fr4,%fr5
+ fcmp,dbl,!?< %fr4,%fr5
+ fcmp,dbl,>= %fr4,%fr5
+ fcmp,dbl,?>= %fr4,%fr5
+ fcmp,dbl,!< %fr4,%fr5
+fcmp_dbl_tests_4
+ fcmp,dbl,!?= %fr4,%fr5
+ fcmp,dbl,<> %fr4,%fr5
+ fcmp,dbl,!= %fr4,%fr5
+ fcmp,dbl,!=T %fr4,%fr5
+ fcmp,dbl,!? %fr4,%fr5
+ fcmp,dbl,<=> %fr4,%fr5
+ fcmp,dbl,true? %fr4,%fr5
+ fcmp,dbl,true %fr4,%fr5
+
+fcmp_quad_tests_1
+ fcmp,quad,false? %fr4,%fr5
+ fcmp,quad,false %fr4,%fr5
+ fcmp,quad,? %fr4,%fr5
+ fcmp,quad,!<=> %fr4,%fr5
+ fcmp,quad,= %fr4,%fr5
+ fcmp,quad,=T %fr4,%fr5
+ fcmp,quad,?= %fr4,%fr5
+ fcmp,quad,!<> %fr4,%fr5
+fcmp_quad_tests_2
+ fcmp,quad,!?>= %fr4,%fr5
+ fcmp,quad,< %fr4,%fr5
+ fcmp,quad,?< %fr4,%fr5
+ fcmp,quad,!>= %fr4,%fr5
+ fcmp,quad,!?> %fr4,%fr5
+ fcmp,quad,<= %fr4,%fr5
+ fcmp,quad,?<= %fr4,%fr5
+ fcmp,quad,!> %fr4,%fr5
+fcmp_quad_tests_3
+ fcmp,quad,!?<= %fr4,%fr5
+ fcmp,quad,> %fr4,%fr5
+ fcmp,quad,?> %fr4,%fr5
+ fcmp,quad,!<= %fr4,%fr5
+ fcmp,quad,!?< %fr4,%fr5
+ fcmp,quad,>= %fr4,%fr5
+ fcmp,quad,?>= %fr4,%fr5
+ fcmp,quad,!< %fr4,%fr5
+fcmp_quad_tests_4
+ fcmp,quad,!?= %fr4,%fr5
+ fcmp,quad,<> %fr4,%fr5
+ fcmp,quad,!= %fr4,%fr5
+ fcmp,quad,!=T %fr4,%fr5
+ fcmp,quad,!? %fr4,%fr5
+ fcmp,quad,<=> %fr4,%fr5
+ fcmp,quad,true? %fr4,%fr5
+ fcmp,quad,true %fr4,%fr5
+
+fmpy_addsub_tests
+ fmpyadd,sgl %fr16,%fr17,%fr18,%fr19,%fr20
+ fmpyadd,dbl %fr16,%fr17,%fr18,%fr19,%fr20
+ fmpysub,sgl %fr16,%fr17,%fr18,%fr19,%fr20
+ fmpysub,dbl %fr16,%fr17,%fr18,%fr19,%fr20
+
+xmpyu_tests
+ xmpyu %fr4,%fr5,%fr6
+
+special_tests
+ gfw %r4(%sr0,%r5)
+ gfw,m %r4(%sr0,%r5)
+ gfr %r4(%sr0,%r5)
+ gfr,m %r4(%sr0,%r5)
+
+sfu_tests
+ spop0,4,5
+ spop0,4,115
+ spop0,4,5,n
+ spop0,4,115,n
+ spop1,4,5 5
+ spop1,4,115 5
+ spop1,4,5,n 5
+ spop1,4,115,n 5
+ spop2,4,5 5
+ spop2,4,115 5
+ spop2,4,5,n 5
+ spop2,4,115,n 5
+ spop3,4,5 5,6
+ spop3,4,115 5,6
+ spop3,4,5,n 5,6
+ spop3,4,115,n 5,6
+
+copr_tests
+ copr,4,5
+ copr,4,115
+ copr,4,5,n
+ copr,4,115,n
+
+copr_indexing_load
+ cldwx,4 5(0,4),26
+ cldwx,4,s 5(0,4),26
+ cldwx,4,m 5(0,4),26
+ cldwx,4,sm 5(0,4),26
+ clddx,4 5(0,4),26
+ clddx,4,s 5(0,4),26
+ clddx,4,m 5(0,4),26
+ clddx,4,sm 5(0,4),26
+
+copr_indexing_store
+ cstwx,4 26,5(0,4)
+ cstwx,4,s 26,5(0,4)
+ cstwx,4,m 26,5(0,4)
+ cstwx,4,sm 26,5(0,4)
+ cstdx,4 26,5(0,4)
+ cstdx,4,s 26,5(0,4)
+ cstdx,4,m 26,5(0,4)
+ cstdx,4,sm 26,5(0,4)
+
+copr_short_memory
+ cldws,4 0(0,4),26
+ cldws,4,mb 0(0,4),26
+ cldws,4,ma 0(0,4),26
+ cldds,4 0(0,4),26
+ cldds,4,mb 0(0,4),26
+ cldds,4,ma 0(0,4),26
+ cstws,4 26,0(0,4)
+ cstws,4,mb 26,0(0,4)
+ cstws,4,ma 26,0(0,4)
+ cstds,4 26,0(0,4)
+ cstds,4,mb 26,0(0,4)
+ cstds,4,ma 26,0(0,4)
+
+fmemLRbug_tests_1
+ fstws %fr6R,0(%r26)
+ fstws %fr6L,4(%r26)
+ fstws %fr6,8(%r26)
+ fstds %fr6R,0(%r26)
+ fstds %fr6L,4(%r26)
+ fstds %fr6,8(%r26)
+ fldws 0(%r26),%fr6R
+ fldws 4(%r26),%fr6L
+ fldws 8(%r26),%fr6
+ fldds 0(%r26),%fr6R
+ fldds 4(%r26),%fr6L
+ fldds 8(%r26),%fr6
+
+fmemLRbug_tests_2
+ fstws %fr6R,0(%sr0,%r26)
+ fstws %fr6L,4(%sr0,%r26)
+ fstws %fr6,8(%sr0,%r26)
+ fstds %fr6R,0(%sr0,%r26)
+ fstds %fr6L,4(%sr0,%r26)
+ fstds %fr6,8(%sr0,%r26)
+ fldws 0(%sr0,%r26),%fr6R
+ fldws 4(%sr0,%r26),%fr6L
+ fldws 8(%sr0,%r26),%fr6
+ fldds 0(%sr0,%r26),%fr6R
+ fldds 4(%sr0,%r26),%fr6L
+ fldds 8(%sr0,%r26),%fr6
+
+fmemLRbug_tests_3
+ fstwx %fr6R,%r25(%r26)
+ fstwx %fr6L,%r25(%r26)
+ fstwx %fr6,%r25(%r26)
+ fstdx %fr6R,%r25(%r26)
+ fstdx %fr6L,%r25(%r26)
+ fstdx %fr6,%r25(%r26)
+ fldwx %r25(%r26),%fr6R
+ fldwx %r25(%r26),%fr6L
+ fldwx %r25(%r26),%fr6
+ flddx %r25(%r26),%fr6R
+ flddx %r25(%r26),%fr6L
+ flddx %r25(%r26),%fr6
+
+fmemLRbug_tests_4
+ fstwx %fr6R,%r25(%sr0,%r26)
+ fstwx %fr6L,%r25(%sr0,%r26)
+ fstwx %fr6,%r25(%sr0,%r26)
+ fstdx %fr6R,%r25(%sr0,%r26)
+ fstdx %fr6L,%r25(%sr0,%r26)
+ fstdx %fr6,%r25(%sr0,%r26)
+ fldwx %r25(%sr0,%r26),%fr6R
+ fldwx %r25(%sr0,%r26),%fr6L
+ fldwx %r25(%sr0,%r26),%fr6
+ flddx %r25(%sr0,%r26),%fr6R
+ flddx %r25(%sr0,%r26),%fr6L
+ flddx %r25(%sr0,%r26),%fr6
+
+ ldw 0(0,%r4),%r26
+ ldw 0(0,%r4),%r26
+ ldo 64(%r4),%r30
+ ldwm -64(0,%r30),%r4
+ bv,n 0(%r2)
+ .EXIT
+ .PROCEND
diff --git a/gdb/testsuite/gdb.disasm/mn10200.exp b/gdb/testsuite/gdb.disasm/mn10200.exp
new file mode 100644
index 00000000000..f9e71df30ab
--- /dev/null
+++ b/gdb/testsuite/gdb.disasm/mn10200.exp
@@ -0,0 +1,478 @@
+
+# Copyright (C) 1997 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file was written by Jeff Law. (law@cygnus.com)
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+if ![istarget "mn10200*-*-*"] {
+ verbose "Tests ignored for all but mn10200 based targets."
+ return
+}
+
+global exec_output
+set prms_id 0
+set bug_id 0
+
+set testfile "mn10200"
+set srcfile ${srcdir}/${subdir}/${testfile}.s
+set binfile ${objdir}/${subdir}/${testfile}
+if { [gdb_compile "${srcfile}" "${binfile}" executable ""] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+proc add_tests { } {
+ global gdb_prompt
+ global hex
+ global decimal
+
+ send_gdb "x/12i add_tests\n"
+ gdb_expect {
+ -re "
+.*add d1,d2.*
+.*add d2,a3.*
+.*add a2,d1.*
+.*add a3,a2.*
+.*add 16,d1.*
+.*add 256,d2.*
+.*add 131071,d3.*
+.*add 16,a1.*
+.*add 256,a2.*
+.*add 131071,a3.*
+.*addc d1,d2.*
+.*addnf 16,a2.*
+.*$gdb_prompt $" { pass "add tests" }
+ -re "$gdb_prompt $" { fail "add tests" }
+ timeout { fail "(timeout) add tests" }
+ }
+}
+
+proc bcc_tests { } {
+ global gdb_prompt
+ global hex
+ global decimal
+
+ send_gdb "x/15i bCC_tests\n"
+ gdb_expect {
+ -re "
+.*beq 0x\[0-9a-f]+ <bCC_tests>.*
+.*bne 0x\[0-9a-f]+ <bCC_tests>.*
+.*bgt 0x\[0-9a-f]+ <bCC_tests>.*
+.*bge 0x\[0-9a-f]+ <bCC_tests>.*
+.*ble 0x\[0-9a-f]+ <bCC_tests>.*
+.*blt 0x\[0-9a-f]+ <bCC_tests>.*
+.*bhi 0x\[0-9a-f]+ <bCC_tests>.*
+.*bcc 0x\[0-9a-f]+ <bCC_tests>.*
+.*bls 0x\[0-9a-f]+ <bCC_tests>.*
+.*bcs 0x\[0-9a-f]+ <bCC_tests>.*
+.*bvc 0x\[0-9a-f]+ <bCC_tests>.*
+.*bvs 0x\[0-9a-f]+ <bCC_tests>.*
+.*bnc 0x\[0-9a-f]+ <bCC_tests>.*
+.*bns 0x\[0-9a-f]+ <bCC_tests>.*
+.*bra 0x\[0-9a-f]+ <bCC_tests>.*
+.*$gdb_prompt $" { pass "bCC tests" }
+ -re "$gdb_prompt $" { fail "bCC tests" }
+ timeout { fail "(timeout) bCC tests" }
+ }
+}
+
+proc bccx_tests { } {
+ global gdb_prompt
+ global hex
+ global decimal
+
+ send_gdb "x/14i bCCx_tests\n"
+ gdb_expect {
+ -re "
+.*beqx 0x\[0-9a-f]+ <bCCx_tests>.*
+.*bnex 0x\[0-9a-f]+ <bCCx_tests>.*
+.*bgtx 0x\[0-9a-f]+ <bCCx_tests>.*
+.*bgex 0x\[0-9a-f]+ <bCCx_tests>.*
+.*blex 0x\[0-9a-f]+ <bCCx_tests>.*
+.*bltx 0x\[0-9a-f]+ <bCCx_tests>.*
+.*bhix 0x\[0-9a-f]+ <bCCx_tests>.*
+.*bccx 0x\[0-9a-f]+ <bCCx_tests>.*
+.*blsx 0x\[0-9a-f]+ <bCCx_tests>.*
+.*bcsx 0x\[0-9a-f]+ <bCCx_tests>.*
+.*bvcx 0x\[0-9a-f]+ <bCCx_tests>.*
+.*bvsx 0x\[0-9a-f]+ <bCCx_tests>.*
+.*bncx 0x\[0-9a-f]+ <bCCx_tests>.*
+.*bnsx 0x\[0-9a-f]+ <bCCx_tests>.*
+.*$gdb_prompt $" { pass "bCCx tests" }
+ -re "$gdb_prompt $" { fail "bCCx tests" }
+ timeout { fail "(timeout) bCCx tests" }
+ }
+}
+
+proc bit_tests { } {
+ global gdb_prompt
+ global hex
+ global decimal
+
+ send_gdb "x/4 bit_tests\n"
+ gdb_expect {
+ -re "
+.*btst 64,d1.*
+.*btst 8192,d2.*
+.*bset d1,\\(a2\\).*
+.*bclr d1,\\(a2\\).*
+.*$gdb_prompt $" { pass "bit tests" }
+ -re "$gdb_prompt $" { fail "bit tests" }
+ timeout { fail "(timeout) bit tests" }
+ }
+}
+
+proc cmp_tests { } {
+ global gdb_prompt
+ global hex
+ global decimal
+
+ send_gdb "x/9i cmp_tests\n"
+ gdb_expect {
+ -re "
+.*cmp d1,d2.*
+.*cmp d2,a3.*
+.*cmp a3,d3.*
+.*cmp a3,a2.*
+.*cmp 16,d3.*
+.*cmp 256,d2.*
+.*cmp 131071,d1.*
+.*cmp 256,a2.*
+.*cmp 131071,a1.*
+.*$gdb_prompt $" { pass "cmp tests" }
+ -re "$gdb_prompt $" { fail "cmp tests" }
+ timeout { fail "(timeout) cmp tests" }
+ }
+}
+
+proc extend_tests { } {
+ global gdb_prompt
+ global hex
+ global decimal
+
+ send_gdb "x/5i extend_tests\n"
+ gdb_expect {
+ -re "
+.*ext d1.*
+.*extx d2.*
+.*extxu d3.*
+.*extxb d2.*
+.*extxbu d1.*
+.*$gdb_prompt $" { pass "extend tests" }
+ -re "$gdb_prompt $" { fail "extend tests" }
+ timeout { fail "(timeout) extend tests" }
+ }
+}
+
+proc logical_tests { } {
+ global gdb_prompt
+ global hex
+ global decimal
+
+ send_gdb "x/11i logical_tests\n"
+ gdb_expect {
+ -re "
+.*and d1,d2.*
+.*and 127,d2.*
+.*and 32767,d3.*
+.*and 32767,psw.*
+.*or d1,d2.*
+.*or 127,d2.*
+.*or 32767,d3.*
+.*or 32767,psw.*
+.*xor d1,d2.*
+.*xor 32767,d3.*
+.*not d3.*
+.*$gdb_prompt $" { pass "logical tests" }
+ -re "$gdb_prompt $" { fail "logical tests" }
+ timeout { fail "(timeout) logical tests" }
+ }
+}
+
+proc mov_tests_1 { } {
+ global gdb_prompt
+ global hex
+ global decimal
+
+ send_gdb "x/12i mov_tests_1\n"
+ gdb_expect {
+ -re "
+.*mov d1,a2.*
+.*mov a2,d1.*
+.*mov d1,d2.*
+.*mov a2,a1.*
+.*mov psw,d3.*
+.*mov d2,psw.*
+.*mov mdr,d1.*
+.*mov d2,mdr.*
+.*mov \\(a2\\),d1.*
+.*mov \\(8,a2\\),d1.*
+.*mov \\(256,a2\\),d1.*
+.*mov \\(131071,a2\\),d1.*
+.*$gdb_prompt $" { pass "mov1 tests" }
+ -re "$gdb_prompt $" { fail "mov1 tests" }
+ timeout { fail "(timeout) mov1 tests" }
+ }
+}
+
+proc mov_tests_2 { } {
+ global gdb_prompt
+ global hex
+ global decimal
+
+ send_gdb "x/9 mov_tests_2\n"
+ gdb_expect {
+ -re "
+.*mov \\(d1,a1\\),d2.*
+.*mov \\(0x8000.*\\),d1.*
+.*mov \\(0x1ffff.*\\),d1.*
+.*mov \\(8,a2\\),a1.*
+.*mov \\(256,a2\\),a1.*
+.*mov \\(131071,a2\\),a1.*
+.*mov \\(d1,a1\\),a2.*
+.*mov \\(0x8000.*\\),a1.*
+.*mov \\(0x1ffff.*\\),a1.*
+.*$gdb_prompt $" { pass "mov2 tests" }
+ -re "$gdb_prompt $" { fail "mov2 tests" }
+ timeout { fail "(timeout) mov2 tests" }
+ }
+}
+
+proc mov_tests_3 { } {
+ global gdb_prompt
+ global hex
+ global decimal
+
+ send_gdb "x/10 mov_tests_3\n"
+ gdb_expect {
+ -re "
+.*mov d1,\\(a2\\).*
+.*mov d1,\\(32,a2\\).*
+.*mov d1,\\(256,a2\\).*
+.*mov d1,\\(131071,a2\\).*
+.*mov d1,\\(d2,a2\\).*
+.*mov d1,\\(0x80.*\\).*
+.*mov d1,\\(0x1ffff.*\\).*
+.*mov a1,\\(32,a2\\).*
+.*mov a1,\\(256,a2\\).*
+.*mov a1,\\(131071,a2\\).*
+.*$gdb_prompt $" { pass "mov3 tests" }
+ -re "$gdb_prompt $" { fail "mov3 tests" }
+ timeout { fail "(timeout) mov3 tests" }
+ }
+}
+
+proc mov_tests_4 { } {
+ global gdb_prompt
+ global hex
+ global decimal
+
+ send_gdb "x/8 mov_tests_4\n"
+ gdb_expect {
+ -re "
+.*mov a1,\\(d2,a2\\).*
+.*mov a1,\\(0x80.*\\).*
+.*mov a1,\\(0x1ffff.*\\).*
+.*mov 8,d1.*
+.*mov 256,d1.*
+.*mov 131071,d1.*
+.*mov 256,a1.*
+.*mov 131071,a1.*
+.*$gdb_prompt $" { pass "mov4 tests" }
+ -re "$gdb_prompt $" { fail "mov4 tests" }
+ timeout { fail "(timeout) mov4 tests" }
+ }
+}
+
+proc movb_tests { } {
+ global gdb_prompt
+ global hex
+ global decimal
+
+ send_gdb "x/12 movb_tests\n"
+ gdb_expect {
+ -re "
+.*movb \\(8,a2\\),d1.*
+.*movb \\(256,a2\\),d1.*
+.*movb \\(131071,a2\\),d1.*
+.*movb \\(d2,a2\\),d3.*
+.*movb \\(0x1ffff.*\\),d2.*
+.*movb d1,\\(a2\\).*
+.*movb d1,\\(8,a2\\).*
+.*movb d1,\\(256,a2\\).*
+.*movb d1,\\(131071,a2\\).*
+.*movb d1,\\(d2,a2\\).*
+.*movb d1,\\(0x100.*\\).*
+.*movb d1,\\(0x1ffff.*\\).*
+.*$gdb_prompt $" { pass "movb tests" }
+ -re "$gdb_prompt $" { fail "movb tests" }
+ timeout { fail "(timeout) movb tests" }
+ }
+}
+
+proc movbu_tests { } {
+ global gdb_prompt
+ global hex
+ global decimal
+
+ send_gdb "x/7 movbu_tests\n"
+ gdb_expect {
+ -re "
+.*movbu \\(a2\\),d1.*
+.*movbu \\(8,a2\\),d1.*
+.*movbu \\(256,a2\\),d1.*
+.*movbu \\(131071,a2\\),d1.*
+.*movbu \\(d1,a1\\),d2.*
+.*movbu \\(0x8000.*\\),d1.*
+.*movbu \\(0x1ffff.*\\),d1.*
+.*$gdb_prompt $" { pass "movbu tests" }
+ -re "$gdb_prompt $" { fail "movbu tests" }
+ timeout { fail "(timeout) movbu tests" }
+ }
+}
+
+proc movx_tests { } {
+ global gdb_prompt
+ global hex
+ global decimal
+
+ send_gdb "x/6 movx_tests\n"
+ gdb_expect {
+ -re "
+.*movx \\(8,a2\\),d1.*
+.*movx \\(256,a2\\),d1.*
+.*movx \\(131071,a2\\),d1.*
+.*movx d1,\\(8,a2\\).*
+.*movx d1,\\(256,a2\\).*
+.*movx d1,\\(131071,a2\\).*
+.*$gdb_prompt $" { pass "movx tests" }
+ -re "$gdb_prompt $" { fail "movx tests" }
+ timeout { fail "(timeout) movx tests" }
+ }
+}
+
+proc muldiv_tests { } {
+ global gdb_prompt
+ global hex
+ global decimal
+
+ send_gdb "x/3 muldiv_tests\n"
+ gdb_expect {
+ -re "
+.*mul d1,d2.*
+.*mulu d2,d3.*
+.*divu d3,d2.*
+.*$gdb_prompt $" { pass "muldiv tests" }
+ -re "$gdb_prompt $" { fail "muldiv tests" }
+ timeout { fail "(timeout) muldiv tests" }
+ }
+}
+
+proc misc_tests { } {
+ global gdb_prompt
+ global hex
+ global decimal
+
+ send_gdb "x/9 misc_tests\n"
+ gdb_expect {
+ -re "
+.*jmp 0x\[0-9a-f]+ <main>.*
+.*jmp 0x\[0-9a-f]+ <start>.*
+.*jmp \\(a2\\).*
+.*jsr 0x\[0-9a-f]+ <main>.*
+.*jsr 0x\[0-9a-f]+ <start>.*
+.*jsr \\(a2\\).*
+.*rts.*
+.*rti.*
+.*nop.*
+.*$gdb_prompt $" { pass "misc tests" }
+ -re "$gdb_prompt $" { fail "misc tests" }
+ timeout { fail "(timeout) misc tests" }
+ }
+}
+
+proc shift_tests { } {
+ global gdb_prompt
+ global hex
+ global decimal
+
+ send_gdb "x/4i shift_tests\n"
+ gdb_expect {
+ -re "
+.*asr d2.*
+.*lsr d3.*
+.*ror d1.*
+.*rol d2.*
+.*$gdb_prompt $" { pass "shift tests" }
+ -re "$gdb_prompt $" { fail "shift tests" }
+ timeout { fail "(timeout) shift tests" }
+ }
+}
+
+proc sub_tests { } {
+ global gdb_prompt
+ global hex
+ global decimal
+
+ send_gdb "x/9i sub_tests\n"
+ gdb_expect {
+ -re "
+.*sub d1,d2.*
+.*sub d2,a3.*
+.*sub a3,d3.*
+.*sub a3,a2.*
+.*sub 32767,d2.*
+.*sub 131071,d2.*
+.*sub 32767,a2.*
+.*sub 131071,a2.*
+.*subc d1,d2.*
+.*$gdb_prompt $" { pass "sub tests" }
+ -re "$gdb_prompt $" { fail "sub tests" }
+ timeout { fail "(timeout) sub tests" }
+ }
+}
+
+# Start with a fresh gdb.
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load $binfile
+
+add_tests
+bcc_tests
+bccx_tests
+bit_tests
+cmp_tests
+extend_tests
+logical_tests
+mov_tests_1
+mov_tests_2
+mov_tests_3
+mov_tests_4
+movb_tests
+movbu_tests
+movx_tests
+muldiv_tests
+misc_tests
+shift_tests
+sub_tests
diff --git a/gdb/testsuite/gdb.disasm/mn10200.s b/gdb/testsuite/gdb.disasm/mn10200.s
new file mode 100644
index 00000000000..32357b0401b
--- /dev/null
+++ b/gdb/testsuite/gdb.disasm/mn10200.s
@@ -0,0 +1,217 @@
+ .text
+ .global _main
+ .global add_tests
+ .global bCC_tests
+ .global bCCx_tests
+ .global bit_tests
+ .global cmp_tests
+ .global extend_tests
+ .global logical_tests
+ .global mov_tests_1
+ .global mov_tests_2
+ .global mov_tests_3
+ .global mov_tests_4
+ .global movb_tests
+ .global movbu_tests
+ .global movx_tests
+ .global misc_tests
+ .global shift_tests
+ .global sub_tests
+
+_main:
+ nop
+
+add_tests:
+ add d1,d2
+ add d2,a3
+ add a2,d1
+ add a3,a2
+ add 16,d1
+ add 256,d2
+ add 131071,d3
+ add 16,a1
+ add 256,a2
+ add 131071,a3
+ addc d1,d2
+ addnf 16,a2
+
+bCC_tests:
+ beq bCC_tests
+ bne bCC_tests
+ bgt bCC_tests
+ bge bCC_tests
+ ble bCC_tests
+ blt bCC_tests
+ bhi bCC_tests
+ bcc bCC_tests
+ bls bCC_tests
+ bcs bCC_tests
+ bvc bCC_tests
+ bvs bCC_tests
+ bnc bCC_tests
+ bns bCC_tests
+ bra bCC_tests
+
+bCCx_tests:
+ beqx bCCx_tests
+ bnex bCCx_tests
+ bgtx bCCx_tests
+ bgex bCCx_tests
+ blex bCCx_tests
+ bltx bCCx_tests
+ bhix bCCx_tests
+ bccx bCCx_tests
+ blsx bCCx_tests
+ bcsx bCCx_tests
+ bvcx bCCx_tests
+ bvsx bCCx_tests
+ bncx bCCx_tests
+ bnsx bCCx_tests
+
+bit_tests:
+ btst 64,d1
+ btst 8192,d2
+ bset d1,(a2)
+ bclr d1,(a2)
+
+cmp_tests:
+ cmp d1,d2
+ cmp d2,a3
+ cmp a3,d3
+ cmp a3,a2
+ cmp 16,d3
+ cmp 256,d2
+ cmp 131071,d1
+ cmp 256,a2
+ cmp 131071,a1
+
+extend_tests:
+ ext d1
+ extx d2
+ extxu d3
+ extxb d2
+ extxbu d1
+
+logical_tests:
+ and d1,d2
+ and 127,d2
+ and 32767,d3
+ and 32767,psw
+ or d1,d2
+ or 127,d2
+ or 32767,d3
+ or 32767,psw
+ xor d1,d2
+ xor 32767,d3
+ not d3
+
+mov_tests_1:
+ mov d1,a2
+ mov a2,d1
+ mov d1,d2
+ mov a2,a1
+ mov psw,d3
+ mov d2,psw
+ mov mdr,d1
+ mov d2,mdr
+ mov (a2),d1
+ mov (8,a2),d1
+ mov (256,a2),d1
+ mov (131071,a2),d1
+
+mov_tests_2:
+ mov (d1,a1),d2
+ mov (32768),d1
+ mov (131071),d1
+ mov (8,a2),a1
+ mov (256,a2),a1
+ mov (131071,a2),a1
+ mov (d1,a1),a2
+ mov (32768),a1
+ mov (131071),a1
+
+mov_tests_3:
+ mov d1,(a2)
+ mov d1,(32,a2)
+ mov d1,(256,a2)
+ mov d1,(131071,a2)
+ mov d1,(d2,a2)
+ mov d1,(128)
+ mov d1,(131071)
+ mov a1,(32,a2)
+ mov a1,(256,a2)
+ mov a1,(131071,a2)
+
+mov_tests_4:
+ mov a1,(d2,a2)
+ mov a1,(128)
+ mov a1,(131071)
+ mov 8,d1
+ mov 256,d1
+ mov 131071,d1
+ mov 256,a1
+ mov 131071,a1
+
+movb_tests:
+ movb (8,a2),d1
+ movb (256,a2),d1
+ movb (131071,a2),d1
+ movb (d2,a2),d3
+ movb (131071),d2
+ movb d1,(a2)
+ movb d1,(8,a2)
+ movb d1,(256,a2)
+ movb d1,(131071,a2)
+ movb d1,(d2,a2)
+ movb d1,(256)
+ movb d1,(131071)
+
+movbu_tests:
+ movbu (a2),d1
+ movbu (8,a2),d1
+ movbu (256,a2),d1
+ movbu (131071,a2),d1
+ movbu (d1,a1),d2
+ movbu (32768),d1
+ movbu (131071),d1
+
+movx_tests:
+ movx (8,a2),d1
+ movx (256,a2),d1
+ movx (131071,a2),d1
+ movx d1,(8,a2)
+ movx d1,(256,a2)
+ movx d1,(131071,a2)
+
+muldiv_tests:
+ mul d1,d2
+ mulu d2,d3
+ divu d3,d2
+
+misc_tests:
+ jmp _main
+ jmp _start
+ jmp (a2)
+ jsr _main
+ jsr _start
+ jsr (a2)
+ rts
+ rti
+ nop
+
+shift_tests:
+ asr d2
+ lsr d3
+ ror d1
+ rol d2
+
+sub_tests:
+ sub d1,d2
+ sub d2,a3
+ sub a3,d3
+ sub a3,a2
+ sub 32767,d2
+ sub 131071,d2
+ sub 32767,a2
+ sub 131071,a2
+ subc d1,d2
diff --git a/gdb/testsuite/gdb.disasm/mn10300.exp b/gdb/testsuite/gdb.disasm/mn10300.exp
new file mode 100644
index 00000000000..b61a2cb594f
--- /dev/null
+++ b/gdb/testsuite/gdb.disasm/mn10300.exp
@@ -0,0 +1,569 @@
+
+# Copyright (C) 1997 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file was written by Jeff Law. (law@cygnus.com)
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+if ![istarget "mn10300*-*-*"] {
+ verbose "Tests ignored for all but mn10300 based targets."
+ return
+}
+
+global exec_output
+set prms_id 0
+set bug_id 0
+
+set testfile "mn10300"
+set srcfile ${srcdir}/${subdir}/${testfile}.s
+set binfile ${objdir}/${subdir}/${testfile}
+if { [gdb_compile "${srcfile}" "${binfile}" executable ""] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+proc add_tests { } {
+ global gdb_prompt
+ global hex
+ global decimal
+
+ send_gdb "x/14i add_tests\n"
+ gdb_expect {
+ -re "
+.*add d1,d2.*
+.*add d2,a3.*
+.*add a3,a2.*
+.*add a2,d1.*
+.*add 16,d1.*
+.*add 256,d2.*
+.*add 131071,d3.*
+.*add 16,a1.*
+.*add 256,a2.*
+.*add 131071,a3.*
+.*add 16,sp.*
+.*add 256,sp.*
+.*add 131071,sp.*
+.*addc d1,d2.*
+.*$gdb_prompt $" { pass "add tests" }
+ -re "$gdb_prompt $" { fail "add tests" }
+ timeout { fail "(timeout) add tests" }
+ }
+}
+
+proc bcc_tests { } {
+ global gdb_prompt
+ global hex
+ global decimal
+
+ send_gdb "x/15i bCC_tests\n"
+ gdb_expect {
+ -re "
+.*beq 0x\[0-9a-f]+ <bCC_tests>.*
+.*bne 0x\[0-9a-f]+ <bCC_tests>.*
+.*bgt 0x\[0-9a-f]+ <bCC_tests>.*
+.*bge 0x\[0-9a-f]+ <bCC_tests>.*
+.*ble 0x\[0-9a-f]+ <bCC_tests>.*
+.*blt 0x\[0-9a-f]+ <bCC_tests>.*
+.*bhi 0x\[0-9a-f]+ <bCC_tests>.*
+.*bcc 0x\[0-9a-f]+ <bCC_tests>.*
+.*bls 0x\[0-9a-f]+ <bCC_tests>.*
+.*bcs 0x\[0-9a-f]+ <bCC_tests>.*
+.*bvc 0x\[0-9a-f]+ <bCC_tests>.*
+.*bvs 0x\[0-9a-f]+ <bCC_tests>.*
+.*bnc 0x\[0-9a-f]+ <bCC_tests>.*
+.*bns 0x\[0-9a-f]+ <bCC_tests>.*
+.*bra 0x\[0-9a-f]+ <bCC_tests>.*
+.*$gdb_prompt $" { pass "bCC tests" }
+ -re "$gdb_prompt $" { fail "bCC tests" }
+ timeout { fail "(timeout) bCC tests" }
+ }
+}
+
+proc bit_tests { } {
+ global gdb_prompt
+ global hex
+ global decimal
+
+ send_gdb "x/11i bit_tests\n"
+ gdb_expect {
+ -re "
+.*btst 64,d1.*
+.*btst 8192,d2.*
+.*btst 131071,d3.*
+.*btst 64,\\(8,a1\\).*
+.*btst 64,\\(0x1ffff\\).*
+.*bset d1,\\(a2\\).*
+.*bset 64,\\(8,a1\\).*
+.*bset 64,\\(0x1ffff\\).*
+.*bclr d1,\\(a2\\).*
+.*bclr 64,\\(8,a1\\).*
+.*bclr 64,\\(0x1ffff\\).*
+.*$gdb_prompt $" { pass "bit tests" }
+ -re "$gdb_prompt $" { fail "bit tests" }
+ timeout { fail "(timeout) bit tests" }
+ }
+}
+
+proc cmp_tests { } {
+ global gdb_prompt
+ global hex
+ global decimal
+
+ send_gdb "x/10i cmp_tests\n"
+ gdb_expect {
+ -re "
+.*cmp d1,d2.*
+.*cmp d2,a3.*
+.*cmp a3,d3.*
+.*cmp a3,a2.*
+.*cmp 16,d3.*
+.*cmp 256,d2.*
+.*cmp 131071,d1.*
+.*cmp 16,a3.*
+.*cmp 256,a2.*
+.*cmp 131071,a1.*
+.*$gdb_prompt $" { pass "cmp tests" }
+ -re "$gdb_prompt $" { fail "cmp tests" }
+ timeout { fail "(timeout) cmp tests" }
+ }
+}
+
+proc extend_tests { } {
+ global gdb_prompt
+ global hex
+ global decimal
+
+ send_gdb "x/5i extend_tests\n"
+ gdb_expect {
+ -re "
+.*ext d1.*
+.*extb d2.*
+.*extbu d3.*
+.*exth d2.*
+.*exthu d1.*
+.*$gdb_prompt $" { pass "extend tests" }
+ -re "$gdb_prompt $" { fail "extend tests" }
+ timeout { fail "(timeout) extend tests" }
+ }
+}
+
+proc extended_tests { } {
+ global gdb_prompt
+ global hex
+ global decimal
+
+ send_gdb "x/13i extended_tests\n"
+ gdb_expect {
+ -re "
+.*putx d1.*
+.*getx d2.*
+.*mulq d1,d2.*
+.*mulq 16,d2.*
+.*mulq 256,d3.*
+.*mulq 131071,d3.*
+.*mulqu d1,d2.*
+.*mulqu 16,d2.*
+.*mulqu 256,d3.*
+.*mulqu 131071,d3.*
+.*sat16 d2,d3.*
+.*sat24 d3,d2.*
+.*bsch d1,d2.*
+.*$gdb_prompt $" { pass "extended tests" }
+ -re "$gdb_prompt $" { fail "extended tests" }
+ timeout { fail "(timeout) extended tests" }
+ }
+}
+
+proc logical_tests { } {
+ global gdb_prompt
+ global hex
+ global decimal
+
+ send_gdb "x/14i logical_tests\n"
+ gdb_expect {
+ -re "
+.*and d1,d2.*
+.*and 127,d2.*
+.*and 32767,d3.*
+.*and 131071,d3.*
+.*and 32767,psw.*
+.*or d1,d2.*
+.*or 127,d2.*
+.*or 32767,d3.*
+.*or 131071,d3.*
+.*or 32767,psw.*
+.*xor d1,d2.*
+.*xor 32767,d3.*
+.*xor 131071,d3.*
+.*not d3.*
+.*$gdb_prompt $" { pass "logical tests" }
+ -re "$gdb_prompt $" { fail "logical tests" }
+ timeout { fail "(timeout) logical tests" }
+ }
+}
+
+proc loop_tests { } {
+ global gdb_prompt
+ global hex
+ global decimal
+
+ send_gdb "x/12i loop_tests\n"
+ gdb_expect {
+ -re "
+.*leq.*
+.*lne.*
+.*lgt.*
+.*lge.*
+.*lle.*
+.*llt.*
+.*lhi.*
+.*lcc.*
+.*lls.*
+.*lcs.*
+.*lra.*
+.*setlb.*
+.*$gdb_prompt $" { pass "loop tests" }
+ -re "$gdb_prompt $" { fail "loop tests" }
+ timeout { fail "(timeout) loop tests" }
+ }
+}
+
+proc mov_tests_1 { } {
+ global gdb_prompt
+ global hex
+ global decimal
+
+ send_gdb "x/16i mov_tests_1\n"
+ gdb_expect {
+ -re "
+.*mov d1,d2.*
+.*mov d1,a2.*
+.*mov a2,d1.*
+.*mov a2,a1.*
+.*mov sp,a2.*
+.*mov a1,sp.*
+.*mov d2,psw.*
+.*mov mdr,d1.*
+.*mov d2,mdr.*
+.*mov \\(a2\\),d1.*
+.*mov \\(8,a2\\),d1.*
+.*mov \\(256,a2\\),d1.*
+.*mov \\(131071,a2\\),d1.*
+.*mov \\(8,sp\\),d1.*
+.*mov \\(256,sp\\),d1.*
+.*mov psw,d3.*
+.*$gdb_prompt $" { pass "mov1 tests" }
+ -re "$gdb_prompt $" { fail "mov1 tests" }
+ timeout { fail "(timeout) mov1 tests" }
+ }
+}
+
+proc mov_tests_2 { } {
+ global gdb_prompt
+ global hex
+ global decimal
+
+ send_gdb "x/15i mov_tests_2\n"
+ gdb_expect {
+ -re "
+.*mov \\(131071,sp\\),d1.*
+.*mov \\(d1,a1\\),d2.*
+.*mov \\(0x8000.*\\),d1.*
+.*mov \\(0x1ffff.*\\),d1.*
+.*mov \\(a2\\),a1.*
+.*mov \\(8,a2\\),a1.*
+.*mov \\(256,a2\\),a1.*
+.*mov \\(131071,a2\\),a1.*
+.*mov \\(8,sp\\),a1.*
+.*mov \\(256,sp\\),a1.*
+.*mov \\(131071,sp\\),a1.*
+.*mov \\(d1,a1\\),a2.*
+.*mov \\(0x8000.*\\),a1.*
+.*mov \\(0x1ffff.*\\),a1.*
+.*mov \\(32,a1\\),sp.*
+.*$gdb_prompt $" { pass "mov2 tests" }
+ -re "$gdb_prompt $" { fail "mov2 tests" }
+ timeout { fail "(timeout) mov2 tests" }
+ }
+}
+
+proc mov_tests_3 { } {
+ global gdb_prompt
+ global hex
+ global decimal
+
+ send_gdb "x/15i mov_tests_3\n"
+ gdb_expect {
+ -re "
+.*mov d1,\\(a2\\).*
+.*mov d1,\\(32,a2\\).*
+.*mov d1,\\(256,a2\\).*
+.*mov d1,\\(131071,a2\\).*
+.*mov d1,\\(32,sp\\).*
+.*mov d1,\\(32768,sp\\).*
+.*mov d1,\\(131071,sp\\).*
+.*mov d1,\\(d2,a2\\).*
+.*mov d1,\\(0x80.*\\).*
+.*mov d1,\\(0x1ffff.*\\).*
+.*mov a1,\\(a2\\).*
+.*mov a1,\\(32,a2\\).*
+.*mov a1,\\(256,a2\\).*
+.*mov a1,\\(131071,a2\\).*
+.*mov a1,\\(32,sp\\).*
+.*$gdb_prompt $" { pass "mov3 tests" }
+ -re "$gdb_prompt $" { fail "mov3 tests" }
+ timeout { fail "(timeout) mov3 tests" }
+ }
+}
+
+proc mov_tests_4 { } {
+ global gdb_prompt
+ global hex
+ global decimal
+
+ send_gdb "x/12i mov_tests_4\n"
+ gdb_expect {
+ -re "
+.*mov a1,\\(32768,sp\\).*
+.*mov a1,\\(131071,sp\\).*
+.*mov a1,\\(d2,a2\\).*
+.*mov a1,\\(0x80.*\\).*
+.*mov a1,\\(0x1ffff.*\\).*
+.*mov sp,\\(32,a1\\).*
+.*mov 8,d1.*
+.*mov 256,d1.*
+.*mov 131071,d1.*
+.*mov 8,a1.*
+.*mov 256,a1.*
+.*mov 131071,a1.*
+.*$gdb_prompt $" { pass "mov4 tests" }
+ -re "$gdb_prompt $" { fail "mov4 tests" }
+ timeout { fail "(timeout) mov4 tests" }
+ }
+}
+
+proc movbu_tests { } {
+ global gdb_prompt
+ global hex
+ global decimal
+
+ send_gdb "x/20i movbu_tests\n"
+ gdb_expect {
+ -re "
+.*movbu \\(a2\\),d1.*
+.*movbu \\(8,a2\\),d1.*
+.*movbu \\(256,a2\\),d1.*
+.*movbu \\(131071,a2\\),d1.*
+.*movbu \\(8,sp\\),d1.*
+.*movbu \\(256,sp\\),d1.*
+.*movbu \\(131071,sp\\),d1.*
+.*movbu \\(d1,a1\\),d2.*
+.*movbu \\(0x8000.*\\),d1.*
+.*movbu \\(0x1ffff.*\\),d1.*
+.*movbu d1,\\(a2\\).*
+.*movbu d1,\\(32,a2\\).*
+.*movbu d1,\\(256,a2\\).*
+.*movbu d1,\\(131071,a2\\).*
+.*movbu d1,\\(32,sp\\).*
+.*movbu d1,\\(32768,sp\\).*
+.*movbu d1,\\(131071,sp\\).*
+.*movbu d1,\\(d2,a2\\).*
+.*movbu d1,\\(0x80.*\\).*
+.*movbu d1,\\(0x1ffff.*\\).*
+.*$gdb_prompt $" { pass "movbu tests" }
+ -re "$gdb_prompt $" { fail "movbu tests" }
+ timeout { fail "(timeout) movbu tests" }
+ }
+}
+
+proc movhu_tests { } {
+ global gdb_prompt
+ global hex
+ global decimal
+
+ send_gdb "x/20i movhu_tests\n"
+ gdb_expect {
+ -re "
+.*movhu \\(a2\\),d1.*
+.*movhu \\(8,a2\\),d1.*
+.*movhu \\(256,a2\\),d1.*
+.*movhu \\(131071,a2\\),d1.*
+.*movhu \\(8,sp\\),d1.*
+.*movhu \\(256,sp\\),d1.*
+.*movhu \\(131071,sp\\),d1.*
+.*movhu \\(d1,a1\\),d2.*
+.*movhu \\(0x8000.*\\),d1.*
+.*movhu \\(0x1ffff.*\\),d1.*
+.*movhu d1,\\(a2\\).*
+.*movhu d1,\\(32,a2\\).*
+.*movhu d1,\\(256,a2\\).*
+.*movhu d1,\\(131071,a2\\).*
+.*movhu d1,\\(32,sp\\).*
+.*movhu d1,\\(32768,sp\\).*
+.*movhu d1,\\(131071,sp\\).*
+.*movhu d1,\\(d2,a2\\).*
+.*movhu d1,\\(0x80.*\\).*
+.*movhu d1,\\(0x1ffff.*\\).*
+.*$gdb_prompt $" { pass "movhu tests" }
+ -re "$gdb_prompt $" { fail "movhu tests" }
+ timeout { fail "(timeout) movhu tests" }
+ }
+}
+
+proc movm_tests { } {
+ global gdb_prompt
+ global hex
+ global decimal
+
+ send_gdb "x/4i movm_tests\n"
+ gdb_expect {
+ -re "
+.*movm \\(sp\\),.a2,a3..*
+.*movm \\(sp\\),.d2,d3,a2,a3,other..*
+.*movm .a2,a3.,\\(sp\\).*
+.*movm .d2,d3,a2,a3,other.,\\(sp\\).*
+.*$gdb_prompt $" { pass "movm tests" }
+ -re "$gdb_prompt $" { fail "movm tests" }
+ timeout { fail "(timeout) movm tests" }
+ }
+}
+
+proc muldiv_tests { } {
+ global gdb_prompt
+ global hex
+ global decimal
+
+ send_gdb "x/4i muldiv_tests\n"
+ gdb_expect {
+ -re "
+.*mul d1,d2.*
+.*mulu d2,d3.*
+.*div d3,d3.*
+.*divu d3,d2.*
+.*$gdb_prompt $" { pass "muldiv tests" }
+ -re "$gdb_prompt $" { fail "muldiv tests" }
+ timeout { fail "(timeout) muldiv tests" }
+ }
+}
+
+proc other_tests { } {
+ global gdb_prompt
+ global hex
+ global decimal
+
+ send_gdb "x/19i other_tests\n"
+ gdb_expect {
+ -re "
+.*clr d2.*
+.*inc d1.*
+.*inc a2.*
+.*inc4 a3.*
+.*jmp \\(a2\\).*
+.*jmp 0x\[0-9a-f]+ <main>.*
+.*jmp 0x\[0-9a-f]+ <start>.*
+.*call 0x\[0-9a-f]+ <main>,.a2,a3.,9.*
+.*call 0x\[0-9a-f]+ <start>,.a2,a3.,32.*
+.*calls \\(a2\\).*
+.*calls 0x\[0-9a-f]+ <main>.*
+.*calls 0x\[0-9a-f]+ <start>.*
+.*ret .a2,a3.,7.*
+.*retf .a2,a3.,5.*
+.*rets.*
+.*rti.*
+.*trap.*
+.*nop.*
+.*rtm.*
+.*$gdb_prompt $" { pass "other tests" }
+ -re "$gdb_prompt $" { fail "other tests" }
+ timeout { fail "(timeout) other tests" }
+ }
+}
+
+proc shift_tests { } {
+ global gdb_prompt
+ global hex
+ global decimal
+
+ send_gdb "x/9i shift_tests\n"
+ gdb_expect {
+ -re "
+.*asr d1,d2.*
+.*asr 4,d2.*
+.*lsr d2,d3.*
+.*lsr 4,d3.*
+.*asl d3,d2.*
+.*asl 4,d2.*
+.*asl2 d2.*
+.*ror d1.*
+.*rol d2.*
+.*$gdb_prompt $" { pass "shift tests" }
+ -re "$gdb_prompt $" { fail "shift tests" }
+ timeout { fail "(timeout) shift tests" }
+ }
+}
+
+proc sub_tests { } {
+ global gdb_prompt
+ global hex
+ global decimal
+
+ send_gdb "x/7i sub_tests\n"
+ gdb_expect {
+ -re "
+.*sub d1,d2.*
+.*sub d2,a3.*
+.*sub a3,d3.*
+.*sub a3,a2.*
+.*sub 131071,d2.*
+.*sub 131071,a1.*
+.*subc d1,d2.*
+.*$gdb_prompt $" { pass "sub tests" }
+ -re "$gdb_prompt $" { fail "sub tests" }
+ timeout { fail "(timeout) sub tests" }
+ }
+}
+
+# Start with a fresh gdb.
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load $binfile
+
+add_tests
+bcc_tests
+bit_tests
+cmp_tests
+extend_tests
+extended_tests
+logical_tests
+loop_tests
+mov_tests_1
+mov_tests_2
+mov_tests_3
+mov_tests_4
+movbu_tests
+movhu_tests
+movm_tests
+muldiv_tests
+other_tests
+shift_tests
+sub_tests
diff --git a/gdb/testsuite/gdb.disasm/mn10300.s b/gdb/testsuite/gdb.disasm/mn10300.s
new file mode 100644
index 00000000000..3ad6c95e6a1
--- /dev/null
+++ b/gdb/testsuite/gdb.disasm/mn10300.s
@@ -0,0 +1,300 @@
+ .text
+ .global _main
+ .global add_tests
+ .global bCC_tests
+ .global bit_tests
+ .global cmp_tests
+ .global extend_tests
+ .global extended_tests
+ .global logical_tests
+ .global loop_tests
+ .global mov_tests_1
+ .global mov_tests_2
+ .global mov_tests_3
+ .global mov_tests_4
+ .global movbu_tests
+ .global movhu_tests
+ .global movm_tests
+ .global muldiv_tests
+ .global other_tests
+ .global shift_tests
+ .global sub_tests
+
+_main:
+ nop
+
+add_tests:
+ add d1,d2
+ add d2,a3
+ add a3,a2
+ add a2,d1
+ add 16,d1
+ add 256,d2
+ add 131071,d3
+ add 16,a1
+ add 256,a2
+ add 131071,a3
+ add 16,sp
+ add 256,sp
+ add 131071,sp
+ addc d1,d2
+
+bCC_tests:
+ beq bCC_tests
+ bne bCC_tests
+ bgt bCC_tests
+ bge bCC_tests
+ ble bCC_tests
+ blt bCC_tests
+ bhi bCC_tests
+ bcc bCC_tests
+ bls bCC_tests
+ bcs bCC_tests
+ bvc bCC_tests
+ bvs bCC_tests
+ bnc bCC_tests
+ bns bCC_tests
+ bra bCC_tests
+
+bit_tests:
+ btst 64,d1
+ btst 8192,d2
+ btst 131071,d3
+ btst 64,(8,a1)
+ btst 64,(0x1ffff)
+ bset d1,(a2)
+ bset 64,(8,a1)
+ bset 64,(0x1ffff)
+ bclr d1,(a2)
+ bclr 64,(8,a1)
+ bclr 64,(0x1ffff)
+
+cmp_tests:
+ cmp d1,d2
+ cmp d2,a3
+ cmp a3,d3
+ cmp a3,a2
+ cmp 16,d3
+ cmp 256,d2
+ cmp 131071,d1
+ cmp 16,a3
+ cmp 256,a2
+ cmp 131071,a1
+
+
+extend_tests:
+ ext d1
+ extb d2
+ extbu d3
+ exth d2
+ exthu d1
+
+extended_tests:
+ putx d1
+ getx d2
+ mulq d1,d2
+ mulq 16,d2
+ mulq 256,d3
+ mulq 131071,d3
+ mulqu d1,d2
+ mulqu 16,d2
+ mulqu 256,d3
+ mulqu 131071,d3
+ sat16 d2,d3
+ sat24 d3,d2
+ bsch d1,d2
+
+logical_tests:
+ and d1,d2
+ and 127,d2
+ and 32767,d3
+ and 131071,d3
+ and 32767,psw
+ or d1,d2
+ or 127,d2
+ or 32767,d3
+ or 131071,d3
+ or 32767,psw
+ xor d1,d2
+ xor 32767,d3
+ xor 131071,d3
+ not d3
+
+loop_tests:
+ leq
+ lne
+ lgt
+ lge
+ lle
+ llt
+ lhi
+ lcc
+ lls
+ lcs
+ lra
+ setlb
+
+mov_tests_1:
+ mov d1,d2
+ mov d1,a2
+ mov a2,d1
+ mov a2,a1
+ mov sp,a2
+ mov a1,sp
+ mov d2,psw
+ mov mdr,d1
+ mov d2,mdr
+ mov (a2),d1
+ mov (8,a2),d1
+ mov (256,a2),d1
+ mov (131071,a2),d1
+ mov (8,sp),d1
+ mov (256,sp),d1
+ mov psw,d3
+
+mov_tests_2:
+ mov (131071,sp),d1
+ mov (d1,a1),d2
+ mov (32768),d1
+ mov (131071),d1
+ mov (a2),a1
+ mov (8,a2),a1
+ mov (256,a2),a1
+ mov (131071,a2),a1
+ mov (8,sp),a1
+ mov (256,sp),a1
+ mov (131071,sp),a1
+ mov (d1,a1),a2
+ mov (32768),a1
+ mov (131071),a1
+ mov (32,a1),sp
+
+mov_tests_3:
+ mov d1,(a2)
+ mov d1,(32,a2)
+ mov d1,(256,a2)
+ mov d1,(131071,a2)
+ mov d1,(32,sp)
+ mov d1,(32768,sp)
+ mov d1,(131071,sp)
+ mov d1,(d2,a2)
+ mov d1,(128)
+ mov d1,(131071)
+ mov a1,(a2)
+ mov a1,(32,a2)
+ mov a1,(256,a2)
+ mov a1,(131071,a2)
+ mov a1,(32,sp)
+
+mov_tests_4:
+ mov a1,(32768,sp)
+ mov a1,(131071,sp)
+ mov a1,(d2,a2)
+ mov a1,(128)
+ mov a1,(131071)
+ mov sp,(32,a1)
+ mov 8,d1
+ mov 256,d1
+ mov 131071,d1
+ mov 8,a1
+ mov 256,a1
+ mov 131071,a1
+
+movbu_tests:
+ movbu (a2),d1
+ movbu (8,a2),d1
+ movbu (256,a2),d1
+ movbu (131071,a2),d1
+ movbu (8,sp),d1
+ movbu (256,sp),d1
+ movbu (131071,sp),d1
+ movbu (d1,a1),d2
+ movbu (32768),d1
+ movbu (131071),d1
+ movbu d1,(a2)
+ movbu d1,(32,a2)
+ movbu d1,(256,a2)
+ movbu d1,(131071,a2)
+ movbu d1,(32,sp)
+ movbu d1,(32768,sp)
+ movbu d1,(131071,sp)
+ movbu d1,(d2,a2)
+ movbu d1,(128)
+ movbu d1,(131071)
+
+movhu_tests:
+ movhu (a2),d1
+ movhu (8,a2),d1
+ movhu (256,a2),d1
+ movhu (131071,a2),d1
+ movhu (8,sp),d1
+ movhu (256,sp),d1
+ movhu (131071,sp),d1
+ movhu (d1,a1),d2
+ movhu (32768),d1
+ movhu (131071),d1
+ movhu d1,(a2)
+ movhu d1,(32,a2)
+ movhu d1,(256,a2)
+ movhu d1,(131071,a2)
+ movhu d1,(32,sp)
+ movhu d1,(32768,sp)
+ movhu d1,(131071,sp)
+ movhu d1,(d2,a2)
+ movhu d1,(128)
+ movhu d1,(131071)
+
+movm_tests:
+ movm (sp),[a2,a3]
+ movm (sp),[d2,d3,a2,a3,other]
+ movm [a2,a3],(sp)
+ movm [d2,d3,a2,a3,other],(sp)
+
+
+muldiv_tests:
+ mul d1,d2
+ mulu d2,d3
+ div d3,d3
+ divu d3,d2
+
+other_tests:
+ clr d2
+ inc d1
+ inc a2
+ inc4 a3
+ jmp (a2)
+ jmp _main
+ jmp _start
+ call _main,[a2,a3],9
+ call _start,[a2,a3],32
+ calls (a2)
+ calls _main
+ calls _start
+ ret [a2,a3],7
+ retf [a2,a3],5
+ rets
+ rti
+ trap
+ nop
+ rtm
+
+shift_tests:
+ asr d1,d2
+ asr 4,d2
+ lsr d2,d3
+ lsr 4,d3
+ asl d3,d2
+ asl 4,d2
+ asl2 d2
+ ror d1
+ rol d2
+
+sub_tests:
+ sub d1,d2
+ sub d2,a3
+ sub a3,d3
+ sub a3,a2
+ sub 131071,d2
+ sub 131071,a1
+ subc d1,d2
+
diff --git a/gdb/testsuite/gdb.disasm/sh3.exp b/gdb/testsuite/gdb.disasm/sh3.exp
new file mode 100644
index 00000000000..6c82f9151fb
--- /dev/null
+++ b/gdb/testsuite/gdb.disasm/sh3.exp
@@ -0,0 +1,123 @@
+# Copyright (C) 1992, 1997 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file was written by Jeff Law. (law@cs.utah.edu)
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+if ![istarget "sh3*-*-*"] {
+ verbose "Tests ignored for all but sh3 based targets."
+ return
+}
+
+set prms_id 0
+set bug_id 0
+
+set testfile "sh3"
+set srcfile ${srcdir}/${subdir}/${testfile}.s
+set binfile ${objdir}/${subdir}/${testfile}
+if { [gdb_compile "${srcfile}" "${binfile}" executable ""] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+proc all_fp_move_and_load_tests { } {
+ global gdb_prompt
+ global hex
+ global decimal
+
+ send_gdb "x/9i fp_move_and_load_tests\n"
+ gdb_expect {
+ -re "
+.*fmov.s\t@r0,fr0.*
+.*fmov.s\tfr0,@r0.*
+.*fmov.s\t@r0\\+,fr0.*
+.*fmov.s\tfr0,@-r0.*
+.*fmov.s\t@\\(r0,r0\\),fr0.*
+.*fmov.s\tfr0,@\\(r0,r0\\).*
+.*fmov\tfr0,fr1.*
+.*fldi0\tfr0.*
+.*fldi1\tfr0.*
+.*$gdb_prompt $" { pass "fp_move_and_load_tests" }
+ -re "$gdb_prompt $" { fail "fp_move_and_load_tests" }
+ timeout { fail "(timeout) fp_move_and_load_tests" }
+ }
+}
+
+proc all_fp_arithmetic_tests { } {
+ global gdb_prompt
+ global hex
+ global decimal
+
+ send_gdb "x/13i fp_arithmetic_tests\n"
+ gdb_expect {
+ -re "
+.*fadd\tfr0,fr1.*
+.*fsub\tfr0,fr1.*
+.*fmul\tfr0,fr1.*
+.*fdiv\tfr0,fr1.*
+.*fmac\tfr0,fr0,fr1.*
+.*fcmp/eq\tfr0,fr1.*
+.*fcmp/gt\tfr0,fr1.*
+.*ftst/nan\tfr0.*
+.*fneg\tfr0.*
+.*fabs\tfr0.*
+.*fsqrt\tfr0.*
+.*float\tfpul,fr0.*
+.*ftrc\tfr0,fpul.*
+.*$gdb_prompt $" { pass "fp_arithmetic_tests" }
+ -re "$gdb_prompt $" { fail "fp_arithmetic_tests" }
+ timeout { fail "(timeout) fp_arithmetic_tests" }
+ }
+}
+
+proc all_fp_misc_tests { } {
+ global gdb_prompt
+ global hex
+ global decimal
+
+ send_gdb "x/10i fp_misc_tests\n"
+ gdb_expect {
+ -re "
+.*fsts\tfpul,fr0.*
+.*flds\tfr0,fpul.*
+.*lds\tr3,fpul.*
+.*lds\\.l\t@r3\\+,fpul.*
+.*lds\tr3,fpscr.*
+.*lds\\.l\t@r3\\+,fpscr.*
+.*sts\tfpul,r3.*
+.*sts\\.l\tfpul,@-r3.*
+.*sts\tfpscr,r3.*
+.*sts\\.l\tfpscr,@-r3.*
+.*$gdb_prompt $" { pass "fp_misc_tests" }
+ -re "$gdb_prompt $" { fail "fp_misc_tests" }
+ timeout { fail "(timeout) fp_misc_tests" }
+ }
+}
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load $binfile
+
+all_fp_move_and_load_tests
+all_fp_arithmetic_tests
+all_fp_misc_tests
+
diff --git a/gdb/testsuite/gdb.disasm/sh3.s b/gdb/testsuite/gdb.disasm/sh3.s
new file mode 100644
index 00000000000..8bab256901c
--- /dev/null
+++ b/gdb/testsuite/gdb.disasm/sh3.s
@@ -0,0 +1,54 @@
+ .file "test.c"
+ .data
+
+! Hitachi SH cc1 (cygnus-2.7.1-950728) arguments: -O -fpeephole
+! -ffunction-cse -freg-struct-return -fdelayed-branch -fcommon -fgnu-linker
+
+gcc2_compiled.:
+___gnu_compiled_c:
+ .text
+ .align 2
+ .global _fp_move_and_load_tests
+ .global _fp_arithmetic_tests
+ .global _fp_misc_tests
+ .global _main
+
+_main:
+_fp_move_and_load_tests:
+ fmov.s @r0,fr0
+ fmov.s fr0,@r0
+ fmov.s @r0+,fr0
+ fmov.s fr0,@-r0
+ fmov.s @(r0,r0),fr0
+ fmov.s fr0,@(r0,r0)
+ fmov fr0,fr1
+ fldi0 fr0
+ fldi1 fr0
+
+_fp_arithmetic_tests:
+ fadd fr0,fr1
+ fsub fr0,fr1
+ fmul fr0,fr1
+ fdiv fr0,fr1
+ fmac fr0,fr0,fr1
+ fcmp/eq fr0,fr1
+ fcmp/gt fr0,fr1
+ ftst/nan fr0
+ fneg fr0
+ fabs fr0
+ fsqrt fr0
+ float fpul,fr0
+ ftrc fr0,fpul
+
+_fp_misc_tests:
+ fsts fpul,fr0
+ flds fr0,fpul
+ lds r3,fpul
+ lds.l @r3+,fpul
+ lds r3,fpscr
+ lds.l @r3+,fpscr
+ sts fpul,r3
+ sts.l fpul,@-r3
+ sts fpscr,r3
+ sts.l fpscr,@-r3
+
diff --git a/gdb/testsuite/gdb.fortran/exprs.exp b/gdb/testsuite/gdb.fortran/exprs.exp
new file mode 100644
index 00000000000..cccc82a3f5d
--- /dev/null
+++ b/gdb/testsuite/gdb.fortran/exprs.exp
@@ -0,0 +1,273 @@
+# Copyright (C) 1994, 1997 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file was adapted from Chill tests by Stan Shebs (shebs@cygnus.com).
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+set prms_id 0
+set bug_id 0
+
+# Set the current language to fortran. This counts as a test. If it
+# fails, then we skip the other tests.
+
+proc set_lang_fortran {} {
+ global gdb_prompt
+
+ if [gdb_test "set language fortran" ""] {
+ return 0;
+ }
+
+ if ![gdb_test "show language" ".* source language is \"fortran\".*"] {
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+proc test_integer_literals_accepted {} {
+ global gdb_prompt
+
+ # Test various decimal values.
+
+ gdb_test "p 123" " = 123"
+ gdb_test "p -123" " = -123"
+}
+
+proc test_character_literals_accepted {} {
+ global gdb_prompt
+
+ # Test various character values.
+
+ gdb_test "p 'a'" " = 'a'"
+}
+
+proc test_integer_literals_rejected {} {
+ global gdb_prompt
+
+ test_print_reject "p _"
+}
+
+proc test_logical_literals_accepted {} {
+ global gdb_prompt
+
+ # Test the only possible values for a logical, TRUE and FALSE.
+
+ gdb_test "p .TRUE." " = .TRUE."
+ gdb_test "p .FALSE." " = .FALSE."
+}
+
+proc test_float_literals_accepted {} {
+ global gdb_prompt
+
+ # Test various floating point formats
+
+ gdb_test "p .44 .LT. .45" " = .TRUE."
+ gdb_test "p .44 .GT. .45" " = .FALSE."
+ gdb_test "p 0.44 .LT. 0.45" " = .TRUE."
+ gdb_test "p 0.44 .GT. 0.45" " = .FALSE."
+ gdb_test "p 44. .LT. 45." " = .TRUE."
+ gdb_test "p 44. .GT. 45." " = .FALSE."
+ gdb_test "p 44.0 .LT. 45.0" " = .TRUE."
+ gdb_test "p 44.0 .GT. 45.0" " = .FALSE."
+ gdb_test "p 10D20 .LT. 10D21" " = .TRUE."
+ gdb_test "p 10D20 .GT. 10D21" " = .FALSE."
+ gdb_test "p 10d20 .LT. 10d21" " = .TRUE."
+ gdb_test "p 10d20 .GT. 10d21" " = .FALSE."
+ gdb_test "p 10E20 .LT. 10E21" " = .TRUE."
+ gdb_test "p 10E20 .GT. 10E21" " = .FALSE."
+ gdb_test "p 10e20 .LT. 10e21" " = .TRUE."
+ gdb_test "p 10e20 .GT. 10e21" " = .FALSE."
+ gdb_test "p 10.D20 .LT. 10.D21" " = .TRUE."
+ gdb_test "p 10.D20 .GT. 10.D21" " = .FALSE."
+ gdb_test "p 10.d20 .LT. 10.d21" " = .TRUE."
+ gdb_test "p 10.d20 .GT. 10.d21" " = .FALSE."
+ gdb_test "p 10.E20 .LT. 10.E21" " = .TRUE."
+ gdb_test "p 10.E20 .GT. 10.E21" " = .FALSE."
+ gdb_test "p 10.e20 .LT. 10.e21" " = .TRUE."
+ gdb_test "p 10.e20 .GT. 10.e21" " = .FALSE."
+ gdb_test "p 10.0D20 .LT. 10.0D21" " = .TRUE."
+ gdb_test "p 10.0D20 .GT. 10.0D21" " = .FALSE."
+ gdb_test "p 10.0d20 .LT. 10.0d21" " = .TRUE."
+ gdb_test "p 10.0d20 .GT. 10.0d21" " = .FALSE."
+ gdb_test "p 10.0E20 .LT. 10.0E21" " = .TRUE."
+ gdb_test "p 10.0E20 .GT. 10.0E21" " = .FALSE."
+ gdb_test "p 10.0e20 .LT. 10.0e21" " = .TRUE."
+ gdb_test "p 10.0e20 .GT. 10.0e21" " = .FALSE."
+ gdb_test "p 10.0D+20 .LT. 10.0D+21" " = .TRUE."
+ gdb_test "p 10.0D+20 .GT. 10.0D+21" " = .FALSE."
+ gdb_test "p 10.0d+20 .LT. 10.0d+21" " = .TRUE."
+ gdb_test "p 10.0d+20 .GT. 10.0d+21" " = .FALSE."
+ gdb_test "p 10.0E+20 .LT. 10.0E+21" " = .TRUE."
+ gdb_test "p 10.0E+20 .GT. 10.0E+21" " = .FALSE."
+ gdb_test "p 10.0e+20 .LT. 10.0e+21" " = .TRUE."
+ gdb_test "p 10.0e+20 .GT. 10.0e+21" " = .FALSE."
+ gdb_test "p 10.0D-11 .LT. 10.0D-10" " = .TRUE."
+ gdb_test "p 10.0D-11 .GT. 10.0D-10" " = .FALSE."
+ gdb_test "p 10.0d-11 .LT. 10.0d-10" " = .TRUE."
+ gdb_test "p 10.0d-11 .GT. 10.0d-10" " = .FALSE."
+ gdb_test "p 10.0E-11 .LT. 10.0E-10" " = .TRUE."
+ gdb_test "p 10.0E-11 .GT. 10.0E-10" " = .FALSE."
+ gdb_test "p 10.0e-11 .LT. 10.0e-10" " = .TRUE."
+ gdb_test "p 10.0e-11 .GT. 10.0e-10" " = .FALSE."
+}
+
+proc test_convenience_variables {} {
+ global gdb_prompt
+
+ gdb_test "set \$foo = 101" " = 101\[\r\n\]*" \
+ "Set a new convenience variable"
+
+ gdb_test "print \$foo" " = 101" \
+ "Print contents of new convenience variable"
+
+ gdb_test "set \$foo = 301" " = 301\[\r\n\]*" \
+ "Set convenience variable to a new value"
+
+ gdb_test "print \$foo" " = 301" \
+ "Print new contents of convenience variable"
+
+ gdb_test "set \$_ = 11" " = 11\[\r\n\]*" \
+ "Set convenience variable \$_"
+
+ gdb_test "print \$_" " = 11" \
+ "Print contents of convenience variable \$_"
+
+ gdb_test "print \$foo + 10" " = 311" \
+ "Use convenience variable in arithmetic expression"
+
+ gdb_test "print (\$foo = 32) + 4" " = 36" \
+ "Use convenience variable assignment in arithmetic expression"
+
+ gdb_test "print \$bar" " = VOID" \
+ "Print contents of uninitialized convenience variable"
+}
+
+proc test_value_history {} {
+ global gdb_prompt
+
+ gdb_test "print 101" "\\\$1 = 101" \
+ "Set value-history\[1\] using \$1"
+
+ gdb_test "print 102" "\\\$2 = 102" \
+ "Set value-history\[2\] using \$2"
+
+ gdb_test "print 103" "\\\$3 = 103" \
+ "Set value-history\[3\] using \$3"
+
+ gdb_test "print \$\$" "\\\$4 = 102" \
+ "Print value-history\[MAX-1\] using inplicit index \$\$"
+
+ gdb_test "print \$\$" "\\\$5 = 103" \
+ "Print value-history\[MAX-1\] again using implicit index \$\$"
+
+ gdb_test "print \$" "\\\$6 = 103" \
+ "Print value-history\[MAX\] using implicit index \$"
+
+ gdb_test "print \$\$2" "\\\$7 = 102" \
+ "Print value-history\[MAX-2\] using explicit index \$\$2"
+
+ gdb_test "print \$0" "\\\$8 = 102" \
+ "Print value-history\[MAX\] using explicit index \$0"
+
+ gdb_test "print 108" "\\\$9 = 108" ""
+
+ gdb_test "print \$\$0" "\\\$10 = 108" \
+ "Print value-history\[MAX\] using explicit index \$\$0"
+
+ gdb_test "print \$1" "\\\$11 = 101" \
+ "Print value-history\[1\] using explicit index \$1"
+
+ gdb_test "print \$2" "\\\$12 = 102" \
+ "Print value-history\[2\] using explicit index \$2"
+
+ gdb_test "print \$3" "\\\$13 = 103" \
+ "Print value-history\[3\] using explicit index \$3"
+
+ gdb_test "print \$-3" "\\\$14 = 100" \
+ "Print (value-history\[MAX\] - 3) using implicit index \$"
+
+ gdb_test "print \$1 + 3" "\\\$15 = 104" \
+ "Use value-history element in arithmetic expression"
+}
+
+proc test_arithmetic_expressions {} {
+ global gdb_prompt
+
+ # Test unary minus with various operands
+
+# gdb_test "p -(TRUE)" " = -1" "unary minus applied to bool"
+# gdb_test "p -('a')" " = xxx" "unary minus applied to char"
+ gdb_test "p -(1)" " = -1" "unary minus applied to int"
+ gdb_test "p -(1.0)" " = -1" "unary minus applied to real"
+
+ # Test addition with various operands
+
+ gdb_test "p .TRUE. + 1" " = 2" "bool plus int"
+ gdb_test "p 1 + 1" " = 2" "int plus int"
+ gdb_test "p 1.0 + 1" " = 2" "real plus int"
+ gdb_test "p 1.0 + 2.0" " = 3" "real plus real"
+
+ # Test subtraction with various operands
+
+ gdb_test "p .TRUE. - 1" " = 0" "bool minus int"
+ gdb_test "p 3 - 1" " = 2" "int minus int"
+ gdb_test "p 3.0 - 1" " = 2" "real minus int"
+ gdb_test "p 5.0 - 2.0" " = 3" "real minus real"
+
+ # Test multiplication with various operands
+
+ gdb_test "p .TRUE. * 1" " = 1" "bool times int"
+ gdb_test "p 2 * 3" " = 6" "int times int"
+ gdb_test "p 2.0 * 3" " = 6" "real times int"
+ gdb_test "p 2.0 * 3.0" " = 6" "real times real"
+
+ # Test division with various operands
+
+ gdb_test "p .TRUE. / 1" " = 1" "bool divided by int"
+ gdb_test "p 6 / 3" " = 2" "int divided by int"
+ gdb_test "p 6.0 / 3" " = 2" "real divided by int"
+ gdb_test "p 6.0 / 3.0" " = 2" "real divided by real"
+
+ # Test modulo with various operands
+
+}
+
+# Start with a fresh gdb.
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+
+gdb_test "set print sevenbit-strings" ""
+
+if [set_lang_fortran] then {
+ test_value_history
+ test_convenience_variables
+ test_integer_literals_accepted
+ test_integer_literals_rejected
+ test_logical_literals_accepted
+ test_character_literals_accepted
+ test_float_literals_accepted
+ test_arithmetic_expressions
+} else {
+ warning "$test_name tests suppressed." 0
+}
diff --git a/gdb/testsuite/gdb.fortran/types.exp b/gdb/testsuite/gdb.fortran/types.exp
new file mode 100644
index 00000000000..6f99a2997ad
--- /dev/null
+++ b/gdb/testsuite/gdb.fortran/types.exp
@@ -0,0 +1,114 @@
+# Copyright (C) 1994, 1997, 1998 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file was adapted from Chill tests by Stan Shebs (shebs@cygnus.com).
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+set prms_id 0
+set bug_id 0
+
+# Set the current language to fortran. This counts as a test. If it
+# fails, then we skip the other tests.
+
+proc set_lang_fortran {} {
+ global gdb_prompt
+
+ if [gdb_test "set language fortran" ""] {
+ return 0;
+ }
+
+ if ![gdb_test "show language" ".* source language is \"fortran\".*"] {
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+proc test_integer_literal_types_accepted {} {
+ global gdb_prompt
+
+ # Test various decimal values.
+ # Should be integer*4 probably.
+ gdb_test "pt 123" "type = int"
+}
+
+proc test_character_literal_types_accepted {} {
+ global gdb_prompt
+
+ # Test various character values.
+
+ gdb_test "pt 'a'" "type = character\\*1"
+}
+
+proc test_integer_literal_types_rejected {} {
+ global gdb_prompt
+
+ test_print_reject "pt _"
+}
+
+proc test_logical_literal_types_accepted {} {
+ global gdb_prompt
+
+ # Test the only possible values for a logical, TRUE and FALSE.
+
+ gdb_test "pt .TRUE." "type = logical\\*2"
+ gdb_test "pt .FALSE." "type = logical\\*2"
+}
+
+proc test_float_literal_types_accepted {} {
+ global gdb_prompt
+
+ # Test various floating point formats
+
+ # this used to guess whether to look for "real*4" or
+ # "real*8" based on a target config variable, but noone
+ # maintained it properly.
+
+ gdb_test "pt .44" "type = real\\*\[0-9\]+"
+ gdb_test "pt 44.0" "type = real\\*\[0-9\]+"
+ gdb_test "pt 10D20" "type = real\\*\[0-9\]+"
+ gdb_test "pt 10D20" "type = real\\*\[0-9\]+"
+ gdb_test "pt 10d20" "type = real\\*\[0-9\]+"
+ gdb_test "pt 10d20" "type = real\\*\[0-9\]+"
+ gdb_test "pt 10E20" "type = real\\*\[0-9\]+"
+ gdb_test "pt 10E20" "type = real\\*\[0-9\]+"
+ gdb_test "pt 10e20" "type = real\\*\[0-9\]+"
+ gdb_test "pt 10e20" "type = real\\*\[0-9\]+"
+}
+
+# Start with a fresh gdb.
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+
+gdb_test "set print sevenbit-strings" ""
+
+if [set_lang_fortran] then {
+ test_integer_literal_types_accepted
+ test_integer_literal_types_rejected
+ test_logical_literal_types_accepted
+ test_character_literal_types_accepted
+ test_float_literal_types_accepted
+} else {
+ warning "$test_name tests suppressed." 0
+}
diff --git a/gdb/testsuite/gdb.hp/Makefile.in b/gdb/testsuite/gdb.hp/Makefile.in
new file mode 100644
index 00000000000..d65fc75e222
--- /dev/null
+++ b/gdb/testsuite/gdb.hp/Makefile.in
@@ -0,0 +1,25 @@
+VPATH = @srcdir@
+srcdir = @srcdir@
+
+PROGS = ambiguous ctti-add exception gen-so-thresh namespace \
+ optimize pxdb so-thresh templ-hp watch-hp xdb
+
+MISCELLANEOUS = \
+ lib00-so-thresh.c lib00-so-thresh.sl \
+ lib01-so-thresh.c lib01-so-thresh.sl \
+ lib02-so-thresh.c lib02-so-thresh.sl \
+ so-thresh.c so-thresh.linkopts
+
+all:
+ @echo "Nothing to be done for all..."
+
+#### host, target, and site specific Makefile frags come in here.
+
+clean mostlyclean:
+ -rm -f *.ci *.o $(OBJS) $(PROGS) $(MISCELLANEOUS) *~ core
+
+distclean maintainer-clean realclean: clean
+ -rm -f Makefile config.status config.log
+
+Makefile: $(srcdir)/Makefile.in $(srcdir)/configure.in
+ $(SHELL) ./config.status --recheck
diff --git a/gdb/testsuite/gdb.hp/ambiguous.cc b/gdb/testsuite/gdb.hp/ambiguous.cc
new file mode 100644
index 00000000000..6ee7bc18ea9
--- /dev/null
+++ b/gdb/testsuite/gdb.hp/ambiguous.cc
@@ -0,0 +1,110 @@
+
+void marker1()
+{
+ return;
+}
+
+class A1 {
+public:
+ int x;
+ int y;
+};
+
+class A2 {
+public:
+ int x;
+ int y;
+};
+
+class A3 {
+public:
+ int x;
+ int y;
+};
+
+class X : public A1, public A2 {
+public:
+ int z;
+};
+
+class L : public A1 {
+public:
+ int z;
+};
+
+class LV : public virtual A1 {
+public:
+ int z;
+};
+
+class M : public A2 {
+public:
+ int w;
+};
+
+class N : public L, public M {
+public:
+ int r;
+};
+
+class K : public A1 {
+public:
+ int i;
+};
+
+class KV : public virtual A1 {
+public:
+ int i;
+};
+
+class J : public K, public L {
+public:
+ int j;
+};
+
+class JV : public KV, public LV {
+public:
+ int jv;
+};
+
+class JVA1 : public KV, public LV, public A1 {
+public:
+ int jva1;
+};
+
+class JVA2 : public KV, public LV, public A2 {
+public:
+ int jva2;
+};
+
+class JVA1V : public KV, public LV, public virtual A1 {
+public:
+ int jva1v;
+};
+
+int main()
+{
+ A1 a1;
+ A2 a2;
+ A3 a3;
+ X x;
+ L l;
+ M m;
+ N n;
+ K k;
+ J j;
+ JV jv;
+ JVA1 jva1;
+ JVA2 jva2;
+ JVA1V jva1v;
+
+ int i;
+
+ i += k.i + m.w + a1.x + a2.x + a3.x + x.z + l.z + n.r + j.j;
+
+ marker1();
+
+}
+
+
+
diff --git a/gdb/testsuite/gdb.hp/ambiguous.exp b/gdb/testsuite/gdb.hp/ambiguous.exp
new file mode 100644
index 00000000000..5b87af36d79
--- /dev/null
+++ b/gdb/testsuite/gdb.hp/ambiguous.exp
@@ -0,0 +1,216 @@
+# Copyright (C) 1998 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file is part of the gdb testsuite
+
+# tests relating to ambiguous class members
+# Written by Satish Pai <pai@apollo.hp.com> 1997-07-28
+
+# This file is part of the gdb testsuite
+
+if $tracelevel then {
+ strace $tracelevel
+ }
+
+#
+# test running programs
+#
+
+set prms_id 0
+set bug_id 0
+
+set testfile "ambiguous"
+set srcfile ${testfile}.cc
+set binfile ${objdir}/${subdir}/${testfile}
+
+if [get_compiler_info ${binfile} "c++"] {
+ return -1;
+}
+
+
+if {[skip_hp_tests $gcc_compiled]} then { continue }
+
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug c++}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+
+#
+# set it up at a breakpoint so we can play with the variable values
+#
+if ![runto_main] then {
+ perror "couldn't run to breakpoint"
+ continue
+}
+
+send_gdb "break marker1\n" ; gdb_expect -re ".*$gdb_prompt $"
+ send_gdb "cont\n"
+ gdb_expect {
+ -re "Break.* marker1 \\(\\) at .*:$decimal.*$gdb_prompt $" {
+ send_gdb "up\n"
+ gdb_expect {
+ -re ".*$gdb_prompt $" { pass "up from marker1" }
+ timeout { fail "up from marker1" }
+ }
+ }
+ -re "$gdb_prompt $" { fail "continue to marker1" }
+ timeout { fail "(timeout) continue to marker1" }
+ }
+
+# print out various class objects' members. The values aren't
+# important, just check that the warning is emitted at the
+# right times.
+
+# X is derived from A1 and A2; both A1 and A2 have a member 'x'
+send_gdb "print x.x\n"
+gdb_expect {
+ -re "warning: x ambiguous; using X::A1::x. Use a cast to disambiguate.\r\n\\$\[0-9\]* = 0\r\n$gdb_prompt $" {
+ pass "print x.x"
+ }
+ -re ".*$gdb_prompt $" { fail "print x.x" }
+ timeout { fail "(timeout) print x.x" }
+}
+
+
+# N is derived from A1 and A2, but not immediately -- two steps
+# up in the hierarchy. Both A1 and A2 have a member 'x'.
+send_gdb "print n.x\n"
+gdb_expect {
+ -re "warning: x ambiguous; using N::L::A1::x. Use a cast to disambiguate.\r\n\\$\[0-9\]* = 0\r\n$gdb_prompt $" {
+ pass "print n.x"
+ }
+ -re ".*$gdb_prompt $" { fail "print n.x" }
+ timeout { fail "(timeout) print n.x" }
+}
+
+# J is derived from A1 twice. A1 has a member x.
+send_gdb "print j.x\n"
+gdb_expect {
+ -re "warning: x ambiguous; using J::K::A1::x. Use a cast to disambiguate.\r\n\\$\[0-9\]* = 0\r\n$gdb_prompt $" {
+ pass "print j.x"
+ }
+ -re ".*$gdb_prompt $" { fail "print j.x" }
+ timeout { fail "(timeout) print j.x" }
+}
+
+# JV is derived from A1 but A1 is a virtual base. Should not
+# report an ambiguity in this case.
+send_gdb "print jv.x\n"
+gdb_expect {
+ -re "warning: x ambiguous.*Use a cast to disambiguate.\r\n\\$\[0-9\]* = 0\r\n$gdb_prompt $" {
+ fail "print jv.x (ambiguity reported)"
+ }
+ -re "\\$\[0-9\]* = 0\r\n$gdb_prompt $" { pass "print jv.x" }
+ -re ".*$gdb_prompt $" { fail "print jv.x (??)" }
+ timeout { fail "(timeout) print jv.x" }
+}
+
+# JVA1 is derived from A1; A1 occurs as a virtual base in two
+# ancestors, and as a non-virtual immediate base. Ambiguity must
+# be reported.
+send_gdb "print jva1.x\n"
+gdb_expect {
+ -re "warning: x ambiguous; using JVA1::KV::A1::x. Use a cast to disambiguate.\r\n\\$\[0-9\]* = 0\r\n$gdb_prompt $" {
+ pass "print jva1.x"
+ }
+ -re ".*$gdb_prompt $" { fail "print jva1.x" }
+ timeout { fail "(timeout) print jva1.x" }
+}
+
+# JVA2 is derived from A1 & A2; A1 occurs as a virtual base in two
+# ancestors, and A2 is a non-virtual immediate base. Ambiguity must
+# be reported as A1 and A2 both have a member 'x'.
+send_gdb "print jva2.x\n"
+gdb_expect {
+ -re "warning: x ambiguous; using JVA2::KV::A1::x. Use a cast to disambiguate.\r\n\\$\[0-9\]* = 0\r\n$gdb_prompt $" {
+ pass "print jva2.x"
+ }
+ -re ".*$gdb_prompt $" { fail "print jva2.x" }
+ timeout { fail "(timeout) print jva2.x" }
+}
+
+# JVA1V is derived from A1; A1 occurs as a virtual base in two
+# ancestors, and also as a virtual immediate base. Ambiguity must
+# not be reported.
+send_gdb "print jva1v.x\n"
+gdb_expect {
+ -re "warning: x ambiguous.*Use a cast to disambiguate.\r\n\\$\[0-9\]* = 0\r\n$gdb_prompt $" {
+ fail "print jva1v.x (ambiguity reported)"
+ }
+ -re "\\$\[0-9\]* = 0\r\n$gdb_prompt $" { pass "print jva1v.x" }
+ -re ".*$gdb_prompt $" { fail "print jva1v.x (??)" }
+ timeout { fail "(timeout) print jva1v.x" }
+}
+
+# Now check for ambiguous bases.
+
+# J is derived from A1 twice; report ambiguity if a J is
+# cast to an A1.
+send_gdb "print (A1)j\n"
+gdb_expect {
+ -re "warning: A1 ambiguous; using J::K::A1. Use a cast to disambiguate.\r\n\\$\[0-9\]* = \{x = 0, y = 0\}\r\n$gdb_prompt $" {
+ pass "print (A1)j"
+ }
+ -re ".*$gdb_prompt $" { fail "print (A1)j" }
+ timeout { fail "(timeout) print (A1)j" }
+}
+
+# JV is derived from A1 twice, but A1 is a virtual base; should
+# not report ambiguity when a JV is cast to an A1.
+send_gdb "print (A1)jv\n"
+gdb_expect {
+ -re "warning: A1 ambiguous.*Use a cast to disambiguate.\r\n\\$\[0-9\]* = \{x = 0, y = 0\}\r\n$gdb_prompt $" {
+ fail "print (A1)jv (ambiguity reported)"
+ }
+ -re "\\$\[0-9\]* = \{x = 0, y = 0\}\r\n$gdb_prompt $" { pass "print (A1)jv" }
+ -re ".*$gdb_prompt $" { fail "print (A1)jv (??)" }
+ timeout { fail "(timeout) print (A1)jv" }
+}
+
+# JVA1 is derived from A1; A1 is a virtual base and also a
+# non-virtual base. Must report ambiguity if a JVA1 is cast to an A1.
+send_gdb "print (A1)jva1\n"
+gdb_expect {
+ -re "warning: A1 ambiguous; using JVA1::KV::A1. Use a cast to disambiguate.\r\n\\$\[0-9\]* = \{x = 0, y = 0\}\r\n$gdb_prompt $" {
+ pass "print (A1)jva1"
+ }
+ -re ".*$gdb_prompt $" { fail "print (A1)jva1" }
+ timeout { fail "(timeout) print (A1)jva1" }
+}
+
+# JVA1V is derived from A1; A1 is a virtual base indirectly
+# and also directly; must not report ambiguity when a JVA1V is cast to an A1.
+send_gdb "print (A1)jva1v\n"
+gdb_expect {
+ -re "warning: A1 ambiguous.*Use a cast to disambiguate.\r\n\\$\[0-9\]* = \{x = 0, y = 0\}\r\n$gdb_prompt $" {
+ fail "print (A1)jva1v (ambiguity reported)"
+ }
+ -re "\\$\[0-9\]* = \{x = 0, y = 0\}\r\n$gdb_prompt $" { pass "print (A1)jva1v"
+ }
+ -re ".*$gdb_prompt $" { fail "print (A1)jva1v (??)" }
+ timeout { fail "(timeout) print (A1)jva1v" }
+}
+
+
diff --git a/gdb/testsuite/gdb.hp/attach.c b/gdb/testsuite/gdb.hp/attach.c
new file mode 100644
index 00000000000..1aad3c1cc07
--- /dev/null
+++ b/gdb/testsuite/gdb.hp/attach.c
@@ -0,0 +1,19 @@
+/* This program is intended to be started outside of gdb, and then
+ attached to by gdb. Thus, it simply spins in a loop. The loop
+ is exited when & if the variable 'should_exit' is non-zero. (It
+ is initialized to zero in this program, so the loop will never
+ exit unless/until gdb sets the variable to non-zero.)
+ */
+#include <stdio.h>
+
+int should_exit = 0;
+
+main ()
+{
+ int local_i = 0;
+
+ while (! should_exit)
+ {
+ local_i++;
+ }
+}
diff --git a/gdb/testsuite/gdb.hp/attach.exp b/gdb/testsuite/gdb.hp/attach.exp
new file mode 100644
index 00000000000..372acd05d7e
--- /dev/null
+++ b/gdb/testsuite/gdb.hp/attach.exp
@@ -0,0 +1,416 @@
+# Copyright (C) 1997 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# On HP-UX 11.0, this test is causing a process running
+# the program "attach" to be left around spinning.
+# Until we figure out why, I am commenting out the test
+# to avoid polluting tiamat (our 11.0 nightly test machine)
+# with these processes. RT
+#
+# Setting the magic bit in the target app should work.
+# I added a "kill", and also a test for the R3 register
+# warning. JB
+#
+if $tracelevel then {
+ strace $tracelevel
+ }
+
+set prms_id 0
+set bug_id 0
+
+
+# are we on a target board
+if ![isnative] then {
+ return
+}
+
+if { ![istarget "hppa*-*-hpux10.30"] && ![istarget "hppa*-*-hpux11.*"] } {
+ #setup_xfail "*-*-*"
+ return 0
+}
+
+set testfile "attach"
+set srcfile ${testfile}.c
+set srcfile2 ${testfile}2.c
+set binfile ${objdir}/${subdir}/${testfile}
+set binfile2 ${objdir}/${subdir}/${testfile}2
+set cleanupfile ${objdir}/${subdir}/${testfile}.awk
+
+#execute_anywhere "rm -f ${binfile} ${binfile2}"
+remote_exec build "rm -f ${binfile} ${binfile2}"
+# For debugging this test
+#
+#log_user 1
+
+# Clean out any old files from past runs.
+#
+remote_exec build "${cleanupfile}"
+
+# build the first test case
+#
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+# Build the in-system-call test
+
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile2}" "${binfile2}" executable {debug}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+#if { [compile "-E ${srcdir}/${subdir}/compiler.c >> ${objdir}/${subdir}/${testfile}.tmp"] != ""# } {
+# perror "Couldn't make ${testfile}.tmp"
+# return -1
+#}
+
+#execute_anywhere "mv ${objdir}/${subdir}/${testfile}.tmp ${binfile}.ci"
+
+#source ${binfile}.ci
+
+proc do_attach_tests {} {
+ global gdb_prompt
+ global binfile
+ global srcfile
+ global testfile
+ global objdir
+ global subdir
+ global timeout
+
+ # Start the program running and then wait for a bit, to be sure
+ # that it can be attached to.
+ #
+ set testpid [eval exec $binfile &]
+ exec sleep 2
+
+ # Verify that we cannot attach to nonsense.
+ #
+ send_gdb "attach abc\n"
+ gdb_expect {
+ -re "Illegal process-id: abc.*$gdb_prompt $"\
+ {pass "attach to nonsense is prohibited"}
+ -re "Attaching to.*$gdb_prompt $"\
+ {fail "attach to nonsense is prohibited (bogus pid allowed)"}
+ -re "$gdb_prompt $" {fail "attach to nonsense is prohibited"}
+ timeout {fail "(timeout) attach to nonsense is prohibited"}
+ }
+
+ # Verify that we cannot attach to what appears to be a valid
+ # process ID, but is a process that doesn't exist. (I don't
+ # believe any process is ever assigned #0, at least on HPUX.)
+ #
+ send_gdb "attach 0\n"
+ gdb_expect {
+ # This reponse is expected on HP-UX 10.20 (i.e., ptrace-based).
+ -re "Attaching to.*, process 0.*No such process.*$gdb_prompt $"\
+ {pass "attach to nonexistent process is prohibited"}
+ # This response is expected on HP-UX 10.30 & 11.0 (i.e., ttrace-based).
+ -re "Attaching to.*, process 0.*Permission denied.*$gdb_prompt $"\
+ {pass "attach to nonexistent process is prohibited"}
+ -re "$gdb_prompt $" {fail "attach to nonexistent process is prohibited"}
+ timeout {fail "(timeout) attach to nonexistent process is prohibited"}
+ }
+
+ # Verify that we can attach to the process by first giving its
+ # executable name via the file command, and using attach with
+ # the process ID.
+ #
+ # (Actually, the test system appears to do this automatically
+ # for us. So, we must also be prepared to be asked if we want
+ # to discard an existing set of symbols.)
+ #
+ send_gdb "file $binfile\n"
+ gdb_expect {
+ -re "Load new symbol table from.*y or n.*$" {
+ send_gdb "y\n"
+ gdb_expect {
+ -re "Reading symbols from $binfile\.\.\.*done.*$gdb_prompt $"\
+ {pass "(re)set file, before attach1"}
+ -re "$gdb_prompt $" {fail "(re)set file, before attach1"}
+ timeout {fail "(timeout) (re)set file, before attach1"}
+ }
+ }
+ -re "Reading symbols from $binfile\.\.\.*done.*$gdb_prompt $"\
+ {pass "set file, before attach1"}
+ -re "$gdb_prompt $" {fail "set file, before attach1"}
+ timeout {fail "(timeout) set file, before attach1"}
+ }
+
+ send_gdb "attach $testpid\n"
+ gdb_expect {
+ -re "Attaching to program.*$binfile, process $testpid.*main.*at .*$srcfile:.*$gdb_prompt $"\
+ {pass "attach1, after setting file"}
+ -re "$gdb_prompt $" {fail "attach1, after setting file"}
+ timeout {fail "(timeout) attach1, after setting file"}
+ }
+
+ # Verify that we can "see" the variable "should_exit" in the
+ # program, and that it is zero.
+ #
+ send_gdb "print should_exit\n"
+ gdb_expect {
+ -re ".* = 0.*$gdb_prompt $"\
+ {pass "after attach1, print should_exit"}
+ -re "$gdb_prompt $" {fail "after attach1, print should_exit"}
+ timeout {fail "(timeout) after attach1, print should_exit"}
+ }
+
+ # Detach the process.
+ #
+ send_gdb "detach\n"
+ gdb_expect {
+ -re "Detaching from program: .*$binfile.*$gdb_prompt $"\
+ {pass "attach1 detach"}
+ -re "$gdb_prompt $" {fail "attach1 detach"}
+ timeout {fail "(timeout) attach1 detach"}
+ }
+
+ # Wait a bit for gdb to finish detaching
+ #
+ exec sleep 5
+
+ # Purge the symbols from gdb's brain. (We want to be certain
+ # the next attach, which won't be preceded by a "file" command,
+ # is really getting the executable file without our help.)
+ #
+ set old_timeout $timeout
+ set timeout [expr $timeout + 20]
+ send_gdb "file\n"
+ gdb_expect {
+ -re ".*gdb internal error.*$" {
+ fail "Internal error, prob. Memory corruption"
+ }
+ -re "No exec file now.*Discard symbol table.*y or n.*$" {
+ send_gdb "y\n"
+ gdb_expect {
+ -re "No symbol file now.*$gdb_prompt $"\
+ {pass "attach1, purging symbols after detach"}
+ -re "$gdb_prompt $" {fail "attach1, purging symbols after detach"}
+ timeout {fail "(timeout) attach1, purging symbols after detach"}
+ }
+ }
+ -re "$gdb_prompt $" {fail "attach1, purging file after detach"}
+ timeout {
+ fail "(timeout) attach1, purging file after detach"
+ }
+ }
+ set timeout $old_timeout
+
+ # Verify that we can attach to the process just by giving the
+ # process ID.
+ #
+ send_gdb "attach $testpid\n"
+ gdb_expect {
+ -re "Attaching to process $testpid.*Reading symbols from $binfile.*main.*at .*$gdb_prompt $"\
+ {pass "attach2"}
+ -re "$gdb_prompt $" {fail "attach2"}
+ timeout {fail "(timeout) attach2"}
+ }
+
+ # Verify that we can modify the variable "should_exit" in the
+ # program.
+ #
+ send_gdb "set should_exit=1\n"
+ gdb_expect {
+ -re "$gdb_prompt $" {pass "after attach2, set should_exit"}
+ timeout {fail "(timeout) after attach2, set should_exit"}
+ }
+
+ # Verify that the modification really happened.
+ #
+ send_gdb "tbreak 19\n"
+ gdb_expect {
+ -re "Breakpoint .*at.*$srcfile, line 19.*$gdb_prompt $"\
+ {pass "after attach2, set tbreak postloop"}
+ -re "$gdb_prompt $" {fail "after attach2, set tbreak postloop"}
+ timeout {fail "(timeout) after attach2, set tbreak postloop"}
+ }
+ send_gdb "continue\n"
+ gdb_expect {
+ -re "main.*at.*$srcfile:19.*$gdb_prompt $"\
+ {pass "after attach2, reach tbreak postloop"}
+ -re "$gdb_prompt $" {fail "after attach2, reach tbreak postloop"}
+ timeout {fail "(timeout) after attach2, reach tbreak postloop"}
+ }
+
+ # Allow the test process to exit, to cleanup after ourselves.
+ #
+ send_gdb "continue\n"
+ gdb_expect {
+ -re "Program exited normally.*$gdb_prompt $"\
+ {pass "after attach2, exit"}
+ -re "$gdb_prompt $" {fail "after attach2, exit"}
+ timeout {fail "(timeout) after attach2, exit"}
+ }
+
+ # Make sure we don't leave a process around to confuse
+ # the next test run (and prevent the compile by keeping
+ # the text file busy), in case the "set should_exit" didn't
+ # work.
+ #
+# execute_anywhere "kill -9 ${testpid}"
+remote_exec build "kill -9 ${testpid}"
+ # Start the program running and then wait for a bit, to be sure
+ # that it can be attached to.
+ #
+ set testpid [eval exec $binfile &]
+ exec sleep 2
+
+ # Verify that we can attach to the process, and find its a.out
+ # when we're cd'd to some directory that doesn't contain the
+ # a.out. (We use the source path set by the "dir" command.)
+ #
+ send_gdb "dir ${objdir}/${subdir}\n"
+ gdb_expect {
+ -re ".*Source directories searched: .*$gdb_prompt $"\
+ {pass "set source path"}
+ -re "$gdb_prompt $" {fail "set source path"}
+ timeout {fail "(timeout) set source path"}
+ }
+
+ send_gdb "cd /tmp\n"
+ gdb_expect {
+ -re ".*Working directory /tmp.*$gdb_prompt $"\
+ {pass "cd away from process' a.out"}
+ -re "$gdb_prompt $" {fail "cd away from process' a.out"}
+ timeout {fail "(timeout) cd away from process' a.out"}
+ }
+
+ # Explicitly flush out any knowledge of the previous attachment.
+ send_gdb "symbol\n"
+ gdb_expect {
+ -re ".*Discard symbol table from.*y or n. $"\
+ {send_gdb "y\n"
+ gdb_expect {
+ -re ".*No symbol file now.*$gdb_prompt $"\
+ {pass "before attach3, flush symbols"}
+ -re "$gdb_prompt $" {fail "before attach3, flush symbols"}
+ timeout {fail "(timeout) before attach3, flush symbols"}
+ }
+ }
+ -re ".*No symbol file now.*$gdb_prompt $"\
+ {pass "before attach3, flush symbols"}
+ -re "$gdb_prompt $" {fail "before attach3, flush symbols"}
+ timeout {fail "(timeout) before attach3, flush symbols"}
+ }
+ send_gdb "exec\n"
+ gdb_expect {
+ -re ".*No exec file now.*$gdb_prompt $"\
+ {pass "before attach3, flush exec"}
+ -re "$gdb_prompt $" {fail "before attach3, flush exec"}
+ timeout {fail "(timeout) before attach3, flush exec"}
+ }
+
+ send_gdb "attach $testpid\n"
+ gdb_expect {
+ -re "Attaching to process $testpid.*Reading symbols from $binfile.*main.*at .*$gdb_prompt $"\
+ {pass "attach when process' a.out not in cwd"}
+ -re "$gdb_prompt $" {fail "attach when process' a.out not in cwd"}
+ timeout {fail "(timeout) attach when process' a.out not in cwd"}
+ }
+
+ send_gdb "kill\n"
+ gdb_expect {
+ -re ".*Kill the program being debugged.*y or n. $"\
+ {send_gdb "y\n"
+ gdb_expect {
+ -re "$gdb_prompt $" {pass "after attach3, exit"}
+ timeout {fail "(timeout) after attach3, exit"}
+ }
+ }
+ -re "$gdb_prompt $" {fail "after attach3, exit"}
+ timeout {fail "(timeout) after attach3, exit"}
+ }
+}
+
+proc do_call_attach_tests {} {
+ global gdb_prompt
+ global binfile2
+
+ # Start the program running and then wait for a bit, to be sure
+ # that it can be attached to.
+ #
+ set testpid [eval exec $binfile2 &]
+ exec sleep 2
+
+ # Attach
+ #
+ send_gdb "attach $testpid\n"
+ gdb_expect {
+ -re ".*warning: reading register.*I.*O error.*$gdb_prompt $" {
+ fail "attach call, read register 3 error"
+ }
+ -re "Attaching to.*process $testpid.*libc.*$gdb_prompt $" {
+ pass "attach call"
+ }
+ -re "$gdb_prompt $" {fail "attach call"}
+ timeout {fail "(timeout) attach call"}
+ }
+
+ # See if other registers are problems
+ #
+ send_gdb "i r r3\n"
+ gdb_expect {
+ -re ".*warning: reading register.*$gdb_prompt $" {
+ pass "CHFts23490: known bug"
+ }
+ -re ".*r3.*$gdb_prompt $" {
+ pass "Bug fixed, Yayyy!"
+ }
+ timeout { fail "timeout on info reg" }
+ }
+
+ # Get rid of the process
+ #
+ gdb_test "p should_exit = 1" ".*" ""
+ gdb_test "c" ".*Program exited normally.*" ""
+
+ # Be paranoid
+ #
+# execute_anywhere "kill -9 ${testpid}"
+remote_exec build "kill -9 ${testpid}"
+
+}
+
+
+# Start with a fresh gdb
+#
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+# This is a test of gdb's ability to attach to a running process.
+#
+do_attach_tests
+
+# Test attaching when the target is inside a system call
+#
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+do_call_attach_tests
+
+# Until "set follow-fork-mode" and "catch fork" are implemented on
+# other targets...
+#
+if ![istarget "hppa*-hp-hpux*"] then {
+ setup_xfail "*-*-*"
+}
+
+return 0
diff --git a/gdb/testsuite/gdb.hp/attach2.c b/gdb/testsuite/gdb.hp/attach2.c
new file mode 100644
index 00000000000..8eb7a056746
--- /dev/null
+++ b/gdb/testsuite/gdb.hp/attach2.c
@@ -0,0 +1,23 @@
+/* This program is intended to be started outside of gdb, and then
+ attached to by gdb. Thus, it simply spins in a loop. The loop
+ is exited when & if the variable 'should_exit' is non-zero. (It
+ is initialized to zero in this program, so the loop will never
+ exit unless/until gdb sets the variable to non-zero.)
+ */
+#include <stdio.h>
+#include <stdlib.h>
+
+int should_exit = 0;
+
+main ()
+{
+ int local_i = 0;
+
+ sleep( 10 ); /* System call causes register fetch to fail */
+ /* This is a known HPUX "feature" */
+ while (! should_exit)
+ {
+ local_i++;
+ }
+ return (0);
+}
diff --git a/gdb/testsuite/gdb.hp/attach2.exp b/gdb/testsuite/gdb.hp/attach2.exp
new file mode 100644
index 00000000000..e298ee93f7a
--- /dev/null
+++ b/gdb/testsuite/gdb.hp/attach2.exp
@@ -0,0 +1,263 @@
+# attach.exp -- Expect script to test attaching to a threaded pgm
+# Copyright (C) 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# use this to debug:
+#
+#log_user 1
+
+# Temporarily comment out - hanging
+#return 0
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+# Thread stuff is _slow_; prepare for long waits.
+#
+# Further, this test has some "null" lines designed
+# to consume output from gdb that was too late to be
+# matched (sequence is "gdb_test" sends; timeout and
+# on to next send; result finally comes in; mismatch).
+#
+# The null command is 'gdb_test "p \$pc" ".*" ""'
+# NOTE: this command undoes any up/down stuff!
+#
+proc pre_timeout { how_long } {
+ global timeout
+
+ set timeout [expr "$timeout + $how_long"]
+}
+
+proc post_timeout {} {
+ global timeout
+ global oldtimeout
+
+ set timeout $oldtimeout
+ gdb_test "p \$pc" ".*" ""
+}
+
+if { ![istarget "hppa*-*-hpux10.30"] && ![istarget "hppa*-*-hpux11.*"] } {
+ verbose "HPUX thread test ignored for non-hppa or pre-HP/UX-10.30 targets."
+ return 0
+}
+
+# We used to wait 5 seconds , but tiamat is faster than
+# hydra...or is it that the OS allocates time differently(?).
+#
+set delay 5
+if { ![istarget "hppa*-*-hpux11.*"] } {
+ set delay 45
+}
+
+set testfile quicksort
+set srcfile ${srcdir}/${subdir}/${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+
+if [get_compiler_info ${binfile}] {
+ return -1
+}
+
+set oldtimeout $timeout
+#set timeout [expr "$timeout + 100"]
+set oldverbose $verbose
+#set verbose 40
+
+# To build the executable we need to link against the thread library.
+#
+# cc -Ae -g -o quicksort -lpthread quicksort.c
+#
+#remote_exec build "${srcfile} -Ae -g -lpthread -o ${binfile}"
+#gdb_compile "${srcfile} -Ae -g -lpthread -o ${binfile}"
+
+if {$gcc_compiled == 0} {
+ set additional_flags "additional_flags=-Ae"
+} else {
+ set additional_flags ""
+}
+
+if { [gdb_compile "${srcdir}/${subdir}/${testfile}.c" "${binfile}.o" object [list debug $additional_flags]] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+remote_exec build "ld /usr/ccs/lib/crt0.o ${binfile}.o -lcl -lpthread -lc /opt/langtools/lib/end.o -o ${binfile}"
+
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+
+# Start the application running and get its pid.
+# Then we wait for it to get started and attach.
+#
+set testpid [eval exec $binfile 1 &]
+exec sleep $delay
+
+# Now attach to the file.
+#
+pre_timeout 100
+gdb_test "attach $testpid" ".*Attaching to process.*Reading symbols from.*done.*" "attach to target"
+post_timeout
+
+# Wait for things to quiesce.
+#
+exec sleep 0
+
+send_gdb "bt\n"
+
+set do_return 0
+set do_go_to_118 0
+pre_timeout 400
+gdb_expect {
+ -re ".*sleep.*work_init.*main.*$gdb_prompt $" {
+ pass "at expected location"
+ }
+ -re ".*drand48.*$gdb_prompt $" {
+ set do_go_to_118 1
+ }
+ -re ".*pthread_mutex_lock.*$gdb_prompt $" {
+ set do_go_to_118 1
+ }
+ -re ".*pthread_mutex_unlock.*$gdb_prompt $" {
+ set do_go_to_118 1
+ }
+ -re ".*main.*$gdb_prompt $" {
+ set do_go_to_118 1
+ }
+ -re ".*No stack.*$gdb_prompt $" {
+ fail "Failed attach, change wait amount down, rest would fail"
+ set do_return 1
+ }
+ -re ".*$gdb_prompt $" {
+ # Who knows?
+ #
+ set do_go_to_118 1
+ }
+ timeout {
+ set do_return 1
+ fail "timeout on bt, avoiding rest of test"
+ }
+}
+post_timeout
+
+# Too late; just give up.
+#
+if { $do_return } {
+ set timeout $oldtimeout
+ set verbose $oldverbose
+ return 0
+}
+
+# Maybe too early--set a temp break and continue.
+# We have to set this on both paths, so that we can
+# know what numbers breakpoints will be.
+#
+gdb_test "tb 118" ".*Breakpoint 1.*118.*" ""
+if { $do_go_to_118 } {
+ pre_timeout 100
+ send_gdb "c\n"
+ gdb_expect {
+ -re ".*at.*118.*118.*$gdb_prompt $" {
+ # Ok, just keep going
+ }
+ -re ".*Program exited.*$gdb_prompt $" {
+ fail "Attached too late, set wait amount downwards"
+ set timeout $oldtimeout
+ set verbose $oldverbose
+ return 0
+ }
+ -re ".*$gdb_prompt $" {
+ fail "Unexpected result on attach"
+ set timeout $oldtimeout
+ set verbose $oldverbose
+ return 0
+ }
+ timeout {
+ fail "timeout on continue "
+ }
+ }
+ post_timeout
+}
+
+# Look at the threads.
+#
+pre_timeout 100
+gdb_test "info thread" ".*7.*6.*5.*4.*3.*2.*\\\* 1.*thread.*" "first info thread"
+post_timeout
+
+# We expect to be inside the "sleep" call, so check that.
+#
+if { [expr "!$do_go_to_118"] } {
+ gdb_test "up" ".*\#1.*nanosleep.*" "up 1"
+ gdb_test "up" ".*\#2.*sleep.*" "up 2"
+ pre_timeout 100
+ gdb_test "up" ".*\#3.*work_init.*$testfile.*c:118.*sleep.*" "up 3"
+ post_timeout
+} else {
+ send_user "Skipped three tests\n"
+}
+
+# Get out of that call.
+#
+gdb_test "b 120" ".*Breakpoint 2.*120.*" "set bp"
+pre_timeout 100
+gdb_test "c" ".*Breakpoint 2.*at.*120.*" "hit bp"
+post_timeout
+
+# Look at the threads.
+#
+pre_timeout 100
+gdb_test "info thread" ".*7.*6.*5.*4.*3.*2.*1.*thread.*$testfile.*c*120.*" "2nd info thread"
+post_timeout
+
+# Do some more stuff, to make sure we can
+#
+gdb_test "thread 3" ".*Switching to.*thread.*ksleep.*" "switch thread"
+
+gdb_test "up" ".*_lwp_cond_timedwait.*" "up 5"
+gdb_test "up" ".*pthread_cond_wait.*" "up 6"
+gdb_test "up" ".*\#3.*worker.*144.*" "up 7"
+gdb_test "up" ".*__pthread_exit.*" "up 8"
+gdb_test "up" ".*Initial.*cannot go up.*" "found thread base"
+
+gdb_test "b 145 thr 3" ".*Breakpoint 3.*145.*" "thread-specific bp"
+gdb_test "i b" ".*2.*breakpoint.*at.*120.*3.*breakpoint.*at.*145 thread 3.*" "show thread-specific bp"
+gdb_test "del 2" ".*" ""
+
+gdb_test "c" ".*Breakpoint 3.*145.*" "hit thread-specific bp"
+gdb_test "i th" ".*\\\* 3.*145.*" "at correct thread"
+
+pre_timeout 100
+gdb_test "n" ".*146.*" "next from thread-specific bp"
+post_timeout
+
+gdb_test "d 3" ".*" ""
+gdb_test "c" ".*Program exited normally\..*" "run to finish"
+
+# Done!
+#
+gdb_exit
+
+set timeout $oldtimeout
+set verbose $oldverbose
+
+# execute_anywhere "rm -f ${binfile}"
+#
+return 0
+
+
diff --git a/gdb/testsuite/gdb.hp/average.c b/gdb/testsuite/gdb.hp/average.c
new file mode 100644
index 00000000000..070eaefa27e
--- /dev/null
+++ b/gdb/testsuite/gdb.hp/average.c
@@ -0,0 +1,39 @@
+/* This is a sample program for the HP WDB debugger. */
+
+#include <stdio.h>
+
+#define num 10
+
+static int my_list[num] = {3,4,2,0,2,1,8,3,6,7};
+
+#ifdef __STDC__
+void print_average(int list[], int low, int high)
+#else
+void print_average(list, low, high)
+int list[], low, high;
+#endif
+ {
+ int total, num_elements, average;
+ total = sum(list, low, high);
+ num_elements = high - low; /* note this is an off-by-one bug */
+
+ average = total / num_elements;
+ printf("%10.d\n", average);
+ }
+
+#ifdef __STDC__
+int main(void)
+#else
+main ()
+#endif
+{
+ char c;
+ int first = 0;
+ int last = num-1;
+
+ /* Try two test cases. */
+ print_average (my_list, first, last);
+ print_average (my_list, first, last - 3);
+foo:
+ exit(0);
+}
diff --git a/gdb/testsuite/gdb.hp/classes-hp.exp b/gdb/testsuite/gdb.hp/classes-hp.exp
new file mode 100644
index 00000000000..cb22c96e8fc
--- /dev/null
+++ b/gdb/testsuite/gdb.hp/classes-hp.exp
@@ -0,0 +1,859 @@
+# Copyright (C) 1992, 1994, 1995, 1997 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file was written by Fred Fish. (fnf@cygnus.com)
+
+set ws "\[\r\n\t \]+"
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+
+# Check to see if we have an executable to test. If not, then either we
+# haven't tried to compile one, or the compilation failed for some reason.
+# In either case, just notify the user and skip the tests in this file.
+
+set testfile "misc-hp"
+set srcfile ${testfile}.cc
+set binfile ${objdir}/${subdir}/${testfile}
+
+if [get_compiler_info ${binfile} "c++"] {
+ return -1;
+}
+
+
+if {[skip_hp_tests $gcc_compiled]} then { continue }
+
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug c++}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+#
+# Test ptype of class objects.
+#
+
+proc test_ptype_class_objects {} {
+ global gdb_prompt
+ global ws
+
+ # Note that struct members are public by default, so we don't print
+ # "public:" for the public members of structs.
+ # Accept it as an expected failure if gdb just fails to distinguish between
+ # class and struct, and everything else is OK.
+
+ send_gdb "ptype struct default_public_struct\n"
+ gdb_expect {
+ -re "type = struct default_public_struct \{${ws}int a;${ws}int b;\r\n\}\r\n$gdb_prompt $" {
+ pass "ptype struct default_public_struct"
+ }
+ -re "type = class default_public_struct \{\r\n.*int a;${ws}int b;\r\n.*\}\r\n$gdb_prompt $" {
+ setup_xfail "*-*-*"
+ fail "ptype struct default_public_struct"
+ }
+ -re ".*$gdb_prompt $" { fail "ptype struct default_public_struct" }
+ timeout { fail "ptype struct default_public_struct (timeout)" ; return }
+ }
+
+ # Note that struct members are public by default, so we don't print
+ # "public:" for the public members of structs.
+ # Accept it as an expected failure if gdb just fails to distinguish between
+ # class and struct, and everything else is OK.
+
+ send_gdb "ptype struct explicit_public_struct\n"
+ gdb_expect {
+ -re "type = struct explicit_public_struct \{${ws}int a;${ws}int b;\r\n.*\}\r\n$gdb_prompt $" {
+ pass "ptype struct explicit_public_struct"
+ }
+ -re "type = class explicit_public_struct \{\r\n.*int a;${ws}int b;\r\n.*\}\r\n$gdb_prompt $" {
+ setup_xfail "*-*-*"
+ fail "ptype struct explicit_public_struct"
+ }
+ -re ".*$gdb_prompt $" { fail "ptype struct explicit_public_struct" }
+ timeout { fail "ptype struct explicit_public_struct (timeout)" ; return }
+ }
+
+ # Accept it as an expected failure if gdb just fails to distinguish between
+ # class and struct, and everything else is OK.
+
+ setup_xfail_format "DWARF 1"
+ send_gdb "ptype struct protected_struct\n"
+ gdb_expect {
+ -re "type = struct protected_struct \{${ws}protected:${ws}int a;${ws}int b;\r\n\}\r\n$gdb_prompt $" {
+ pass "ptype struct protected_struct (FIXME)"
+ }
+ -re "type = class protected_struct \{${ws}protected:${ws}int a;${ws}int b;\r\n.*\}\r\n$gdb_prompt $" {
+ setup_xfail "*-*-*"
+ fail "ptype struct protected_struct (FIXME)"
+ }
+ -re ".*$gdb_prompt $" { fail "ptype struct protected_struct" }
+ timeout { fail "ptype struct protected_struct (timeout)" ; return }
+ }
+
+ # Accept it as an expected failure if gdb just fails to distinguish between
+ # class and struct, and everything else is OK.
+
+ setup_xfail_format "DWARF 1"
+ send_gdb "ptype struct private_struct\n"
+ gdb_expect {
+ -re "type = struct private_struct \{${ws}private:${ws}int a;${ws}int b;\r\n\}\r\n$gdb_prompt $" {
+ pass "ptype struct private_struct (FIXME)"
+ }
+ -re "type = class private_struct \{${ws}private:${ws}int a;${ws}int b;\r\n.*\}\r\n$gdb_prompt $" {
+ setup_xfail "*-*-*"
+ fail "ptype struct private_struct (FIXME)"
+ }
+ -re ".*$gdb_prompt $" { fail "ptype struct private_struct" }
+ timeout { fail "ptype struct private_struct (timeout)" ; return }
+ }
+
+ # Accept it as an expected failure if gdb just fails to distinguish between
+ # class and struct, and everything else is OK.
+
+ setup_xfail_format "DWARF 1"
+ send_gdb "ptype struct mixed_protection_struct\n"
+ gdb_expect {
+ -re "type = struct mixed_protection_struct \{${ws}int a;${ws}int b;${ws}private:${ws}int c;${ws}int d;${ws}protected:${ws}int e;${ws}int f;${ws}public:${ws}int g;${ws}private:${ws}int h;${ws}protected:${ws}int i;\[\r\n\]+\}\[\r\n\]+$gdb_prompt $" {
+ pass "ptype struct mixed_protection_struct (FIXME)"
+ }
+ -re "type = struct mixed_protection_struct \{\r\n\[ \]*public:\r\n\[ \]*int a;\r\n\[ \]*int b;\r\n\[ \]*private:\r\n\[ \]*int c;\r\n\[ \]*int d;\r\n\[ \]*protected:\r\n\[ \]*int e;\r\n\[ \]*int f;\r\n\[ \]*public:\r\n\[ \]*int g;\r\n\[ \]*private:\r\n\[ \]*int h;\r\n\[ \]*protected:\r\n\[ \]*int i;\r\n.*\}\r\n$gdb_prompt $" {
+ pass "ptype struct mixed_protection_struct (extra public)"
+ }
+ -re "type = class mixed_protection_struct \{${ws}public:${ws}int a;${ws}int b;${ws}private:${ws}int c;${ws}int d;${ws}protected:${ws}int e;${ws}int f;${ws}public:${ws}int g;${ws}private:${ws}int h;${ws}protected:${ws}int i;\r\n.*\}\r\n$gdb_prompt $" {
+ setup_xfail "*-*-*"
+ fail "ptype struct mixed_protection_struct (FIXME)"
+ }
+ -re ".*$gdb_prompt $" { fail "ptype struct mixed_protection_struct" }
+ timeout { fail "ptype struct mixed_protection_struct (timeout)" ; return }
+ }
+
+ # Accept it as an expected failure if gdb just fails to distinguish between
+ # class and struct, and everything else is OK.
+
+ send_gdb "ptype class public_class\n"
+ gdb_expect {
+ -re "type = class public_class \{${ws}public:${ws}int a;${ws}int b;\r\n.*\}\r\n$gdb_prompt $" {
+ pass "ptype class public_class (FIXME)"
+ }
+ -re "type = struct public_class \{${ws}int a;${ws}int b;\r\n\}\r\n$gdb_prompt $" {
+ setup_xfail "*-*-*"
+ fail "ptype class public_class (FIXME)"
+ }
+ -re ".*$gdb_prompt $" { fail "ptype class public_class" }
+ timeout { fail "ptype class public_class (timeout)" ; return }
+ }
+
+ send_gdb "ptype class protected_class\n"
+ gdb_expect {
+ -re "type = class protected_class \{${ws}protected:${ws}int a;${ws}int b;\r\n.*\}\r\n$gdb_prompt $" {
+ pass "ptype class protected_class"
+ }
+ -re "type = struct protected_class \{${ws}int a;${ws}int b;\r\n\}\r\n$gdb_prompt $" {
+ setup_xfail "*-*-*"
+ fail "ptype class protected_class"
+ }
+ -re ".*$gdb_prompt $" { fail "ptype class protected_class" }
+ timeout { fail "ptype class protected_class (timeout)" ; return }
+ }
+
+ # Accept it as an expected failure if gdb just emits a superflous "private:"
+ # attribute, since classes default to private and for consistency with
+ # structs (where we don't print the "public:" attribute) we don't print
+ # the "private:" attribute.
+
+ setup_xfail_format "DWARF 1"
+ send_gdb "ptype class default_private_class\n"
+ gdb_expect {
+ -re "type = class default_private_class \{${ws}int a;${ws}int b;\r\n.*\}\r\n$gdb_prompt $" {
+ pass "ptype class default_private_class (FIXME)"
+ }
+ -re "type = class default_private_class \{${ws}private:${ws}int a;${ws}int b;\r\n.*\}\r\n$gdb_prompt $" {
+ setup_xfail "*-*-*"
+ fail "ptype class default_private_class (FIXME)"
+ }
+ -re ".*$gdb_prompt $" { fail "ptype class default_private_class" }
+ timeout { fail "ptype class default_private_class (timeout)" ; return }
+ }
+
+ send_gdb "ptype class explicit_private_class\n"
+ gdb_expect {
+ -re "type = class explicit_private_class \{${ws}private:${ws}int a;${ws}int b;\r\n.*\}\r\n$gdb_prompt $" {
+ pass "ptype class explicit_private_class"
+ }
+ -re "type = class explicit_private_class \{\r\n\[ \]*int a;\r\n\[ \]*int b;\r\n.*\}\r\n$gdb_prompt $" {
+ pass "ptype class explicit_private_class (OK for HP aCC)"
+ }
+ -re "type = struct explicit_private_class \{${ws}int a;${ws}int b;\r\n.*\}\r\n$gdb_prompt $" {
+ setup_xfail "*-*-*"
+ fail "ptype class explicit_private_class"
+ }
+ -re ".*$gdb_prompt $" { fail "ptype class explicit_private_class" }
+ timeout { fail "ptype class explicit_private_class (timeout)" ; return }
+ }
+
+ send_gdb "ptype class mixed_protection_class\n"
+ gdb_expect {
+ -re "type = class mixed_protection_class \{${ws}public:${ws}int a;${ws}int b;${ws}private:${ws}int c;${ws}int d;${ws}protected:${ws}int e;${ws}int f;${ws}public:${ws}int g;${ws}private:${ws}int h;${ws}protected:${ws}int i;\r\n.*\}\r\n$gdb_prompt $" {
+ pass "ptype class mixed_protection_class"
+ }
+ -re "type = struct mixed_protection_class \{${ws}int a;${ws}int b;${ws}int c;${ws}int d;${ws}int e;${ws}int f;${ws}int g;${ws}int h;${ws}int i;\r\n.*\}\r\n$gdb_prompt $" {
+ setup_xfail "*-*-*"
+ fail "ptype class mixed_protection_class"
+ }
+ -re ".*$gdb_prompt $" { fail "ptype class mixed_protection_class" }
+ timeout { fail "ptype class mixed_protection_class (timeout)" ; return }
+ }
+
+ # This class does not use any C++-specific features, so it's fine for
+ # it to print as "struct".
+ send_gdb "ptype class A\n"
+ gdb_expect {
+ -re "type = (class|struct) A \{(${ws}public:|)${ws}int a;${ws}int x;((${ws}A & operator=\\(A const &\\);)|(${ws}A\\(A const &\\);)|(${ws}A\\(void\\);))*${ws}\}\r\n$gdb_prompt $" {
+ pass "ptype class A"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "ptype class A"
+ }
+ timeout {
+ fail "ptype class A (timeout)"
+ return
+ }
+ }
+
+ setup_xfail_format "DWARF 1"
+ send_gdb "ptype class B\n"
+ gdb_expect {
+ -re "type = class B : public A \{${ws}public:${ws}int b;${ws}int x;${ws}B & operator=\\(B const &\\);${ws}B\\(B const &\\);${ws}B\\(void\\);${ws}\}\r\n$gdb_prompt $" {
+ pass "ptype class B"
+ }
+ -re "type = class B : public A \{${ws}public:${ws}int b;${ws}int x;((${ws}B & operator=\\(B const &\\);)|(${ws}B\\(B const &\\);)|(${ws}B\\(void\\);))*${ws}\}\r\n$gdb_prompt $" {
+ pass "ptype class B (obsolescent gcc or gdb)"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "ptype class B"
+ }
+ timeout {
+ fail "ptype class B (timeout)"
+ return
+ }
+ }
+
+ setup_xfail_format "DWARF 1"
+ send_gdb "ptype class C\n"
+ gdb_expect {
+ -re "type = class C : public A \{${ws}public:${ws}int c;${ws}int x;${ws}C & operator=\\(C const &\\);${ws}C\\(C const &\\);${ws}C\\(void\\);${ws}\}\r\n$gdb_prompt $" {
+ pass "ptype class C"
+ }
+ -re "type = class C : public A \{${ws}public:${ws}int c;${ws}int x;((${ws}C & operator=\\(C const &\\);)|(${ws}C\\(C const &\\);)|(${ws}C\\(void\\);))*${ws}\}\r\n$gdb_prompt $" {
+ pass "ptype class C (obsolescent gcc or gdb)"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "ptype class C"
+ }
+ timeout {
+ fail "ptype class C (timeout)"
+ return
+ }
+ }
+
+ setup_xfail_format "DWARF 1"
+ send_gdb "ptype class D\n"
+ gdb_expect {
+ -re "type = class D : public B, public C \{${ws}public:${ws}int d;${ws}int x;${ws}D & operator=\\(D const &\\);${ws}D\\(D const &\\);${ws}D\\(void\\);${ws}\}\r\n$gdb_prompt $" {
+ pass "ptype class D"
+ }
+ -re "type = class D : public B, public C \{${ws}public:${ws}int d;${ws}int x;((${ws}D & operator=\\(D const &\\);)|(${ws}D\\(D const &\\);)|(${ws}D\\(void\\);))*${ws}\}\r\n$gdb_prompt $" {
+ pass "ptype class D (obsolescent gcc or gdb)"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "ptype class D"
+ }
+ timeout {
+ fail "ptype class D (timeout)"
+ return
+ }
+ }
+
+ setup_xfail_format "DWARF 1"
+ send_gdb "ptype class E\n"
+ gdb_expect {
+ -re "type = class E : public D \{${ws}public:${ws}int e;${ws}int x;${ws}E & operator=\\(E const &\\);${ws}E\\(E const &\\);${ws}E\\(void\\);${ws}\}\r\n$gdb_prompt $" {
+ pass "ptype class E"
+ }
+ -re "type = class E : public D \{${ws}public:${ws}int e;${ws}int x;((${ws}E & operator=\\(E const &\\);)|(${ws}E\\(E const &\\);)|(${ws}E\\(void\\);))*${ws}\}\r\n$gdb_prompt $" {
+ pass "ptype class E"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "ptype class E"
+ }
+ timeout {
+ fail "ptype class E (timeout)"
+ return
+ }
+ }
+
+ send_gdb "ptype class vA\n"
+ gdb_expect {
+ -re "type = (class|struct) vA \{(${ws}public:|)${ws}int va;${ws}int vx;${ws}vA & operator=\\(vA const &\\);${ws}vA\\(vA const &\\);${ws}vA\\(void\\);${ws}\}\r\n$gdb_prompt $" {
+ pass "ptype class vA"
+ }
+ -re "type = (class|struct) vA \{(${ws}public:|)${ws}int va;${ws}int vx;((${ws}vA & operator=\\(vA const &\\);)|(${ws}vA\\(vA const &\\);)|(${ws}vA\\(void\\);))*${ws}\}\r\n$gdb_prompt $" {
+ pass "ptype class vA (obsolescent gcc or gdb)"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "ptype class vA"
+ }
+ timeout {
+ fail "ptype class vA (timeout)"
+ return
+ }
+ }
+
+ # Accept the form with embedded GNU style mangled virtual table constructs
+ # for now, but with a FIXME. At some future point, gdb should use a
+ # portable representation for the virtual table constructs.
+
+ setup_xfail_format "DWARF 1"
+ send_gdb "ptype class vB\n"
+ gdb_expect {
+ -re "type = class vB : public virtual vA \{${ws}private:${ws}vA \\*_vb.vA;${ws}public:${ws}int vb;${ws}int vx;${ws}vB & operator=\\(vB const &\\);${ws}vB\\(int, vB const &\\);${ws}vB\\(int\\);${ws}\}\r\n$gdb_prompt $" {
+ setup_xfail "*-*-*"
+ fail "ptype class vB (FIXME: non-portable virtual table constructs)"
+ }
+ -re "type = class vB : public virtual vA \{\r\n\[ \]*public:\r\n\[ \]*int vb;\r\n\[ \]*int vx;\[\r\n\t \]+\}\r\n$gdb_prompt $" {
+ pass "ptype class vB (aCC)"
+ }
+ -re "type = class vB : public virtual vA \{${ws}private:${ws}vA \\*_vb.vA;${ws}public:${ws}int vb;${ws}int vx;((${ws}vB & operator=\\(vB const &\\);)|(${ws}vB\\(int, vB const &\\);)|(${ws}vB\\(int\\);))*${ws}\}\r\n$gdb_prompt $" {
+ setup_xfail "*-*-*"
+ fail "ptype class vB (FIXME) (obsolescent gcc or gdb)"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "ptype class vB"
+ }
+ timeout {
+ fail "ptype class vB (timeout)"
+ return
+ }
+ }
+
+ # Accept the form with embedded GNU style mangled virtual table constructs
+ # for now, but with a FIXME. At some future point, gdb should use a
+ # portable representation for the virtual table constructs.
+
+ setup_xfail_format "DWARF 1"
+ send_gdb "ptype class vC\n"
+ gdb_expect {
+ -re "type = class vC : public virtual vA \{${ws}private:${ws}vA \\*_vb.vA;${ws}public:${ws}int vc;${ws}int vx;${ws}vC & operator=\\(vC const &\\);${ws}vC\\(int, vC const &\\);${ws}vC\\(int\\);${ws}\}\r\n$gdb_prompt $" {
+ setup_xfail "*-*-*"
+ fail "ptype class vC (FIXME: non-portable virtual table constructs)"
+ }
+ -re "type = class vC : public virtual vA \{\r\n\[ \]*public:\r\n\[ \]*int vc;\r\n\[ \]*int vx;\[\r\n\t \]+\}\r\n$gdb_prompt $" {
+ pass "ptype class vC (aCC)"
+ }
+ -re "type = class vC : public virtual vA \{${ws}private:${ws}vA \\*_vb.vA;${ws}public:${ws}int vc;${ws}int vx;((${ws}vC & operator=\\(vC const &\\);)|(${ws}vC\\(int, vC const &\\);)|(${ws}vC\\(int\\);))*${ws}\}\r\n$gdb_prompt $" {
+ setup_xfail "*-*-*"
+ fail "ptype class vC (FIXME) (obsolescent gcc or gdb)"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "ptype class vC"
+ }
+ timeout {
+ fail "ptype class vC (timeout)"
+ return
+ }
+ }
+
+ # Accept the form with embedded GNU style mangled virtual table constructs
+ # for now, but with a FIXME. At some future point, gdb should use a
+ # portable representation for the virtual table constructs.
+
+ setup_xfail_format "DWARF 1"
+ send_gdb "ptype class vD\n"
+ gdb_expect {
+ -re "type = class vD : public virtual vB, public virtual vC \{${ws}private:${ws}vC \\*_vb.vC;${ws}vB \\*_vb.vB;${ws}public:${ws}int vd;${ws}int vx;${ws}vD & operator=\\(vD const &\\);${ws}vD\\(int, vD const &\\);${ws}vD\\(int\\);${ws}\}\r\n$gdb_prompt $" {
+ setup_xfail "*-*-*"
+ fail "ptype class vD (FIXME: non-portable virtual table constructs)"
+ }
+ -re "type = class vD : public virtual vB, public virtual vC \{\r\n\[ \]*public:\r\n\[ \]*int vd;\r\n\[ \]*int vx;\[\r\n\t \]+\}\r\n$gdb_prompt $" {
+ pass "ptype class vD (aCC)"
+ }
+ -re "type = class vD : public virtual vB, public virtual vC \{${ws}private:${ws}vC \\*_vb.vC;${ws}vB \\*_vb.vB;${ws}public:${ws}int vd;${ws}int vx;((${ws}vD & operator=\\(vD const &\\);)|(${ws}vD\\(int, vD const &\\);)|(${ws}vD\\(int\\);))*${ws}\}\r\n$gdb_prompt $" {
+ setup_xfail "*-*-*"
+ fail "ptype class vD (FIXME) (obsolescent gcc or gdb)"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "ptype class vD"
+ }
+ timeout {
+ fail "ptype class vD (timeout)"
+ return
+ }
+ }
+
+ # Accept the form with embedded GNU style mangled virtual table constructs
+ # for now, but with a FIXME. At some future point, gdb should use a
+ # portable representation for the virtual table constructs.
+
+ setup_xfail_format "DWARF 1"
+ send_gdb "ptype class vE\n"
+ gdb_expect {
+ -re "type = class vE : public virtual vD \{${ws}private:${ws}vD \\*_vb.vD;${ws}public:${ws}int ve;${ws}int vx;${ws}vE & operator=\\(vE const &\\);${ws}vE\\(int, vE const &\\);${ws}vE\\(int\\);${ws}\}\r\n$gdb_prompt $" {
+ setup_xfail "*-*-*"
+ fail "ptype class vE (FIXME: non-portable virtual table constructs)"
+ }
+ -re "type = class vE : public virtual vD \{\r\n\[ \]*public:\r\n\[ \]*int ve;\r\n\[ \]*int vx;\[\r\n\t \]+\}\r\n$gdb_prompt $" {
+ pass "ptype class vE (aCC)"
+ }
+ -re "type = class vE : public virtual vD \{${ws}private:${ws}vD \\*_vb.vD;${ws}public:${ws}int ve;${ws}int vx;((${ws}vE & operator=\\(vE const &\\);)|(${ws}vE\\(int, vE const &\\);)|(${ws}vE\\(int\\);))*${ws}\}\r\n$gdb_prompt $" {
+ setup_xfail "*-*-*"
+ fail "ptype class vE (FIXME) (obsolescent gcc or gdb)"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "ptype class vE"
+ }
+ timeout {
+ fail "ptype class vE (timeout)"
+ return
+ }
+ }
+
+ setup_xfail_format "DWARF 1"
+ send_gdb "ptype class Base1\n"
+ gdb_expect {
+ -re "type = class Base1 \{${ws}public:${ws}int x;${ws}Base1 & operator=\\(Base1 const &\\);${ws}Base1\\(Base1 const &\\);${ws}Base1\\(int\\);${ws}\}\r\n$gdb_prompt $" {
+ pass "ptype class Base1"
+ }
+ -re "type = class Base1 \{${ws}public:${ws}int x;((${ws}Base1 & operator=\\(Base1 const &\\);)|(${ws}Base1\\(Base1 const &\\);)|(${ws}Base1\\(int\\);))*${ws}\}\r\n$gdb_prompt $" {
+ pass "ptype class Base1 (obsolescent gcc or gdb)"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "ptype class Base1"
+ }
+ timeout {
+ fail "ptype class Base1 (timeout)"
+ return
+ }
+ }
+
+ setup_xfail_format "DWARF 1"
+ send_gdb "ptype class Foo\n"
+ gdb_expect {
+ -re "type = class Foo \{\r\n\[ \]*public:\r\n\[ \]*int x;\r\n\[ \]*int y;\r\n\[ \]*static int st;\r\n\r\n\[ \]*Foo\\(int, int\\);\r\n\[ \]*int operator!.void.;\r\n\[ \]*operator int.void.;\r\n\[ \]*int times.int.;\r\n\}\r\n$gdb_prompt $" {
+ pass "ptype class Foo(aCC)"
+ }
+ -re "type = class Foo \{${ws}public:${ws}int x;${ws}int y;${ws}static int st;${ws}Foo & operator=\\(Foo const &\\);${ws}Foo\\(Foo const &\\);${ws}Foo\\(int, int\\);${ws}int operator!\\(void\\);${ws}int operator int\\(void\\);${ws}int times\\(int\\);${ws}\}\r\n$gdb_prompt $" {
+ pass "ptype class Foo"
+ }
+ -re "type = class Foo \{${ws}public:${ws}int x;${ws}int y;${ws}static int st;((${ws}Foo & operator=\\(Foo const &\\);)|(${ws}Foo\\(Foo const &\\);)|(${ws}Foo\\(int, int\\);)|(${ws}int operator!\\(void\\);)|(${ws}int operator int\\(void\\);)|(${ws}int times\\(int\\);))*${ws}\}\r\n$gdb_prompt $" {
+ pass "ptype class Foo (obsolescent gcc or gdb)"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "ptype class Foo"
+ }
+ timeout {
+ fail "ptype class Foo (timeout)"
+ return
+ }
+ }
+
+ setup_xfail_format "DWARF 1"
+ send_gdb "ptype class Bar\n"
+ gdb_expect {
+ -re "type = class Bar : public Base1, public Foo \{${ws}public:${ws}int z;${ws}Bar & operator=\\(Bar const &\\);${ws}Bar\\(Bar const &\\);${ws}Bar\\(int, int, int\\);${ws}\}\r\n$gdb_prompt $" {
+ pass "ptype class Bar"
+ }
+ -re "type = class Bar : public Base1, public Foo \{${ws}public:${ws}int z;((${ws}Bar & operator=\\(Bar const &\\);)|(${ws}Bar\\(Bar const &\\);)|(${ws}Bar\\(int, int, int\\);))*${ws}\}\r\n$gdb_prompt $" {
+ pass "ptype class Bar (obsolescent gcc or gdb)"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "ptype class Bar"
+ }
+ timeout {
+ fail "ptype class Bar (timeout)"
+ return
+ }
+ }
+}
+
+#
+# Test simple access to class members.
+#
+
+proc test_non_inherited_member_access {} {
+ global gdb_prompt
+
+ # Print non-inherited members of g_A.
+
+ gdb_test "print g_A.a" ".* = 1" "g_A.a incorrect"
+
+ gdb_test "print g_A.x" ".* = 2" "g_A.x incorrect"
+
+ # Print non-inherited members of g_B.
+
+ gdb_test "print g_B.b" ".* = 5" "g_B.b incorrect"
+
+ gdb_test "print g_B.x" ".* = 6" "g_B.x incorrect"
+
+ # Print non-inherited members of g_C.
+
+ gdb_test "print g_C.c" ".* = 9" "g_C.c incorrect"
+
+ gdb_test "print g_C.x" ".* = 10" "g_C.x incorrect"
+
+ # Print non-inherited members of g_D.
+
+ gdb_test "print g_D.d" ".* = 19" "g_D.d incorrect"
+
+ gdb_test "print g_D.x" ".* = 20" "g_D.x incorrect"
+
+ # Print non-inherited members of g_E.
+
+ gdb_test "print g_E.e" ".* = 31" "g_E.e incorrect"
+
+ gdb_test "print g_E.x" ".* = 32" "g_E.x incorrect"
+}
+
+#
+# Try access to non-members that are members of another class.
+# Should give errors.
+#
+
+proc test_wrong_class_members {} {
+ global gdb_prompt
+
+ gdb_test "print g_A.b" "There is no member( or method|) named b." "print g_A.b should be error"
+
+ gdb_test "print g_B.c" "There is no member( or method|) named c." "print g_B.c should be error"
+
+ gdb_test "print g_B.d" "There is no member( or method|) named d." "print g_B.d should be error"
+
+ gdb_test "print g_C.b" "There is no member( or method|) named b." "print g_C.b should be error"
+
+ gdb_test "print g_C.d" "There is no member( or method|) named d." "print g_C.d should be error"
+
+ gdb_test "print g_D.e" "There is no member( or method|) named e." "print g_D.e should be error"
+}
+
+#
+# Try access to non-members that are not members of any class.
+# Should give errors.
+#
+
+proc test_nonexistant_members {} {
+ global gdb_prompt
+
+ gdb_test "print g_A.y" "There is no member( or method|) named y." "print g_A.y should be error"
+
+ gdb_test "print g_B.z" "There is no member( or method|) named z." "print g_B.z should be error"
+
+ gdb_test "print g_C.q" "There is no member( or method|) named q." "print g_C.q should be error"
+
+ gdb_test "print g_D.p" "There is no member( or method|) named p." "print g_D.p should be error"
+}
+
+#
+# Pointers to class members
+#
+
+proc test_pointers_to_class_members {} {
+ global gdb_prompt
+ global decimal
+
+ gdb_test "print Bar::z" ".* = .int\[ \]*\[( \]*Bar::&\[)\]+\[ \]*Bar::z" "print Bar::z"
+
+ gdb_test "print &Foo::x" ".* = .int\[ \]*\[( \]*Foo::\[*)\]+\[ \]*&Foo::x" "print &Foo::x"
+
+ gdb_test "print (int)&Foo::x" ".* = 0" "print (int)&Foo::x"
+
+ send_gdb "print (int)&Bar::y == 2*sizeof(int)\n"
+ gdb_expect {
+ -re ".* = true\r\n$gdb_prompt $" {
+ pass "print (int)&Bar::y == 2*sizeof(int)"
+ }
+ -re "There is no field named y.*$gdb_prompt $" {
+ setup_xfail "*-*-*"
+ fail "print (int)&Bar::y == 2*sizeof(int)"
+ }
+ -re ".*$gdb_prompt $" { fail "print (int)&Bar::y == 2*sizeof(int)" }
+ timeout { fail "print (int)&Bar::y == 2*sizeof(int) (timeout)" ; return }
+ }
+
+ send_gdb "next\n"
+ setup_xfail "*-*-*"
+ gdb_expect {
+ -re "$decimal\[ \t\]+inheritance3 \[)(\]+;\r\n$gdb_prompt $" {}
+ -re ".*$gdb_prompt $" { fail "next to inheritance3" ; return }
+ }
+ clear_xfail "*-*-*"
+
+ setup_xfail_format "DWARF 1"
+ gdb_test "print (int)pmi == sizeof(int)" ".* = false" "print (int)pmi == sizeof(int)"
+}
+
+#
+# Test static members.
+#
+
+proc test_static_members {} {
+ global gdb_prompt
+ global hex
+
+ send_gdb "print Foo::st\n"
+ gdb_expect {
+ -re ".* = 100\r\n$gdb_prompt $" {
+ pass "print Foo::st"
+ }
+ -re "There is no field named st.*$gdb_prompt $" {
+ setup_xfail "*-*-*"
+ fail "print Foo::st"
+ }
+ -re ".*$gdb_prompt $" { fail "print Foo::st" }
+ timeout { fail "print Foo::st (timeout)" ; return }
+ }
+
+ send_gdb "set foo.st = 200\n"
+ gdb_expect {
+ -re ".*$gdb_prompt $" {}
+ }
+
+ send_gdb "print bar.st\n"
+ gdb_expect {
+ -re ".* = 200\r\n$gdb_prompt $" {
+ pass "print bar.st"
+ }
+ -re "There is no member( or method|) named st.*$gdb_prompt $" {
+ setup_xfail "*-*-*"
+ fail "print bar.st"
+ }
+ -re ".*$gdb_prompt $" { fail "print bar.st" }
+ timeout { fail "print bar.st (timeout)" ; return }
+ }
+
+ send_gdb "print &foo.st\n"
+ gdb_expect {
+ -re ".* = .int \[*)\]+ $hex\r\n$gdb_prompt $" {
+ pass "print &foo.st"
+ }
+ -re "There is no member( or method|) named st.*$gdb_prompt $" {
+ setup_xfail "*-*-*"
+ fail "print &foo.st"
+ }
+ -re ".*$gdb_prompt $" { fail "print &foo.st" }
+ timeout { fail "print &foo.st (timeout)" ; return }
+ }
+
+ set got_bar_st 0
+ send_gdb "print &Bar::st\n"
+ gdb_expect {
+ -re ".* = .int \[*)\]+ $hex\r\n$gdb_prompt $" {
+ pass "print &Bar::st"
+ set got_bar_st 1
+ }
+ -re "There is no field named st.*$gdb_prompt $" {
+ setup_xfail "*-*-*"
+ fail "print &Bar::st"
+ }
+ -re ".*$gdb_prompt $" { fail "print &Bar::st" }
+ timeout { fail "print &Bar::st (timeout)" ; return }
+ }
+
+ if $got_bar_st then {
+ gdb_test "print *\$" ".* = 200" "print *\$"
+ }
+
+ gdb_test "set print static-members off" ""
+ gdb_test "print csi" \
+ "{x = 10, y = 20}" \
+ "print csi without static members"
+ gdb_test "print cnsi" \
+ "{x = 30, y = 40}" \
+ "print cnsi without static members"
+
+ gdb_test "set print static-members on" ""
+ setup_xfail_format "DWARF 1"
+ gdb_test "print csi" \
+ "{x = 10, y = 20, static null = {x = 0, y = 0, static null = <same as static member of an already seen type>}}" \
+ "print csi with static members"
+ setup_xfail_format "DWARF 1"
+ gdb_test "print cnsi" \
+ "{x = 30, y = 40, static null = {x = 0, y = 0, static null = <same as static member of an already seen type>, static yy = {z = 5, static xx = {x = 1, y = 2, static null = <same as static member of an already seen type>, static yy = <same as static member of an already seen type>}}}, static yy = <same as static member of an already seen type>}" \
+ "print cnsi with static members"
+}
+
+proc do_tests {} {
+ global prms_id
+ global bug_id
+ global subdir
+ global objdir
+ global srcdir
+ global binfile
+ global gdb_prompt
+
+ set prms_id 0
+ set bug_id 0
+
+ # Start with a fresh gdb.
+
+ gdb_exit
+ gdb_start
+ gdb_reinitialize_dir $srcdir/$subdir
+ gdb_load $binfile
+
+ send_gdb "set language c++\n"
+ gdb_expect -re "$gdb_prompt $"
+ send_gdb "set width 0\n"
+ gdb_expect -re "$gdb_prompt $"
+
+ # Get the debug format for the compiled test case.
+
+ if [ runto_main ] then {
+ get_debug_format
+ }
+
+ test_ptype_class_objects
+
+ if [ runto 'inheritance2(void)' ] then {
+ test_non_inherited_member_access
+ test_wrong_class_members
+ test_nonexistant_members
+ }
+
+ if [istarget "mips-idt-*"] then {
+ # Restart because IDT/SIM runs out of file descriptors.
+ gdb_exit
+ gdb_start
+ gdb_reinitialize_dir $srcdir/$subdir
+ gdb_load $binfile
+ }
+
+ if [ runto_main ] then {
+ test_pointers_to_class_members
+ test_static_members
+ }
+
+ if [istarget "mips-idt-*"] then {
+ # Restart because IDT/SIM runs out of file descriptors.
+ gdb_exit
+ gdb_start
+ gdb_reinitialize_dir $srcdir/$subdir
+ gdb_load $binfile
+ }
+
+ if [ runto marker_reg1 ] then {
+
+ gdb_test "finish" "Run till exit from.*" "finish from marker_reg1"
+
+ send_gdb "print v.method ()\n"
+ gdb_expect {
+ -re "= 82.*$gdb_prompt $" {
+ pass "calling method for small class"
+ }
+ -re "Address requested for identifier .v. which is in a register.*$gdb_prompt $" {
+ setup_xfail "*-*-*" 2972
+ fail "calling method for small class"
+ }
+ -re ".*$gdb_prompt $" { fail "calling method for small class" }
+ timeout { fail "calling method for small class (timeout)" }
+ eof { fail "calling method for small class (eof)" }
+ }
+ }
+
+}
+
+do_tests
+
+
+# Some additional tests for enums inside classes
+
+
+# set a breakpoint and go there
+send_gdb "break 498\n"
+gdb_expect {
+ -re "Breakpoint \[0-9\] at.*$gdb_prompt $" { pass "set break 498" }
+ -re "$gdb_prompt $" { fail "set break 498" }
+ timeout { fail "(timeout) set break 498" }
+}
+send_gdb "continue\n"
+gdb_expect {
+ -re "Continuing\\.\r\n\r\nBreakpoint \[0-9\]*, main....at ${srcdir}/${subdir}/${srcfile}:498\r\n498.*\r\n$gdb_prompt $" { pass "continue" }
+ -re "$gdb_prompt $" { fail "continue" }
+ timeout { fail "(timeout) continue" }
+}
+
+# print the object
+send_gdb "print obj_with_enum\n"
+gdb_expect {
+ -re "\\$\[0-9\]* = \\{priv_enum = red, x = 0\\}.*$gdb_prompt $" { pass "print obj_with_enum (1)" }
+ -re "$gdb_prompt $" { fail "print obj_with_enum (1)" }
+ timeout { fail "(timeout) print obj_with_enum (1)" }
+}
+
+send_gdb "next\n"
+gdb_expect {
+ -re "$gdb_prompt $" { pass "next" }
+ timeout { fail "(timeout) next" }
+}
+
+# print the object again
+send_gdb "print obj_with_enum\n"
+gdb_expect {
+ -re "\\$\[0-9\]* = \\{priv_enum = green, x = 0\\}.*$gdb_prompt $" { pass "print obj_with_enum (2)" }
+ -re "$gdb_prompt $" { fail "print obj_with_enum (2)" }
+ timeout { fail "(timeout) print obj_with_enum (2)" }
+}
+
+# print out the enum member
+send_gdb "print obj_with_enum.priv_enum\n"
+gdb_expect {
+ -re "\\$\[0-9\]* = green.*$gdb_prompt $" { pass "print obj_with_enum.priv_enum" }
+ -re "$gdb_prompt $" { fail "print obj_with_enum.priv_enum" }
+ timeout { fail "(timeout) print obj_with_enum.priv_enum" }
+}
+
+# ptype on the enum member
+send_gdb "ptype obj_with_enum.priv_enum\n"
+gdb_expect {
+ -re "type = enum ClassWithEnum::PrivEnum \\{red, green, blue, yellow = 42\\}.*$gdb_prompt $" { pass "ptype obj_with_enum.priv_enum" }
+ -re "$gdb_prompt $" { fail "ptype obj_with_enum.priv_enum" }
+ timeout { fail "(timeout) ptype obj_with_enum.priv_enum" }
+}
+
+# ptype on the object
+send_gdb "ptype obj_with_enum\n"
+gdb_expect {
+ -re "type = class ClassWithEnum \\{\r\n\[ \t\]*public:\r\n\[ \t\]*enum ClassWithEnum::PrivEnum priv_enum;\r\n\[ \t\]*int x;\r\n\\}\r\n$gdb_prompt $" { pass "ptype obj_with_enum" }
+ -re "$gdb_prompt $" { fail "ptype obj_with_enum" }
+ timeout { fail "(timeout) ptype obj_with_enum" }
+}
+
+send_gdb "print (ClassWithEnum::PrivEnum) 42\n"
+gdb_expect {
+ -re "\\$\[0-9\]* = yellow.*$gdb_prompt $" { pass "print (ClassWithEnum::PrivEnum) 42" }
+ -re "$gdb_prompt $" { fail "print (ClassWithEnum::PrivEnum) 42" }
+ timeout { fail "(timeout) print (ClassWithEnum::PrivEnum) 42" }
+}
+
+
+send_gdb "maint demangle inheritance1__Fv\n"
+gdb_expect {
+ -re "inheritance1\\(void\\).*$gdb_prompt $" { pass "demangle" }
+ -re ".*$gdb_prompt $" { fail "demangle" }
+ timeout { fail "(timeout) demangle" }
+}
+
diff --git a/gdb/testsuite/gdb.hp/compiler.c b/gdb/testsuite/gdb.hp/compiler.c
new file mode 100644
index 00000000000..8eb0d47dd19
--- /dev/null
+++ b/gdb/testsuite/gdb.hp/compiler.c
@@ -0,0 +1,31 @@
+/* Often the behavior of any particular test depends upon what compiler was
+ used to compile the test. As each test is compiled, this file is
+ preprocessed by the same compiler used to compile that specific test
+ (different tests might be compiled by different compilers, particularly
+ if compiled at different times), and used to generate a *.ci (compiler
+ info) file for that test.
+
+ I.E., when callfuncs is compiled, a callfuncs.ci file will be generated,
+ which can then be sourced by callfuncs.exp to give callfuncs.exp access
+ to information about the compilation environment.
+
+ TODO: It might be a good idea to add expect code that tests each
+ definition made with 'set" to see if one already exists, and if so
+ warn about conflicts if it is being set to something else. */
+
+/* This needs to be kept in sync with whatis.c and gdb.exp(get_compiler_info).
+ If this ends up being hairy, we could use a common header file. */
+
+#if defined (__STDC__) || defined (_AIX)
+set signed_keyword_not_used 0
+#else
+set signed_keyword_not_used 1
+#endif
+
+#if defined (__GNUC__)
+set gcc_compiled __GNUC__
+#else
+set gcc_compiled 0
+#endif
+
+return 0
diff --git a/gdb/testsuite/gdb.hp/compiler.cc b/gdb/testsuite/gdb.hp/compiler.cc
new file mode 100644
index 00000000000..aa35c7510ff
--- /dev/null
+++ b/gdb/testsuite/gdb.hp/compiler.cc
@@ -0,0 +1,34 @@
+/* Often the behavior of any particular test depends upon what compiler was
+ used to compile the test. As each test is compiled, this file is
+ preprocessed by the same compiler used to compile that specific test
+ (different tests might be compiled by different compilers, particularly
+ if compiled at different times), and used to generate a *.ci (compiler
+ info) file for that test.
+
+ I.E., when callfuncs is compiled, a callfuncs.ci file will be generated,
+ which can then be sourced by callfuncs.exp to give callfuncs.exp access
+ to information about the compilation environment.
+
+ TODO: It might be a good idea to add expect code that tests each
+ definition made with 'set" to see if one already exists, and if so
+ warn about conflicts if it is being set to something else. */
+
+#if defined(__GNUC__) && __GNUC__ >= 2 && __GNUC_MINOR__ >= 6
+set supports_template_debugging 1
+#else
+set supports_template_debugging 0
+#endif
+
+#if defined(__cplusplus)
+set supports_template_debugging 1
+#else
+set supports_template_debugging 0
+#endif
+
+#if defined (__GNUC__)
+set gcc_compiled __GNUC__
+#else
+set gcc_compiled 0
+#endif
+
+return 0
diff --git a/gdb/testsuite/gdb.hp/ctti-add.cc b/gdb/testsuite/gdb.hp/ctti-add.cc
new file mode 100644
index 00000000000..1f50fae24c1
--- /dev/null
+++ b/gdb/testsuite/gdb.hp/ctti-add.cc
@@ -0,0 +1,29 @@
+template<class T> T add(T v1, T v2)
+{
+ T v3;
+ v3 = v1;
+ v3 += v2;
+ return v3;
+ }
+
+int main()
+{
+ char c;
+ int i;
+ float f;
+ extern void add1();
+ extern void subr2();
+ extern void subr3();
+
+ c = 'a';
+ i = 2;
+ f = 4.5;
+
+ c = add(c, c);
+ i = add(i, i);
+ f = add(f, f);
+
+ add1();
+ subr2();
+ subr3();
+}
diff --git a/gdb/testsuite/gdb.hp/ctti-add1.cc b/gdb/testsuite/gdb.hp/ctti-add1.cc
new file mode 100644
index 00000000000..7113ecea421
--- /dev/null
+++ b/gdb/testsuite/gdb.hp/ctti-add1.cc
@@ -0,0 +1,16 @@
+template<class T> T add(T v1, T v2);
+
+void add1()
+{
+ char c;
+ int i;
+ float f;
+
+ c = 'b';
+ i = 3;
+ f = 6.5;
+
+ c = add(c, c);
+ i = add(i, i);
+ f = add(f, f);
+}
diff --git a/gdb/testsuite/gdb.hp/ctti-add2.cc b/gdb/testsuite/gdb.hp/ctti-add2.cc
new file mode 100644
index 00000000000..d0d9891fb2f
--- /dev/null
+++ b/gdb/testsuite/gdb.hp/ctti-add2.cc
@@ -0,0 +1,22 @@
+template<class T> T add2(T v1, T v2)
+{
+ T v3;
+ v3 = v1;
+ v3 += v2;
+ return v3;
+}
+
+void subr2()
+{
+ char c;
+ int i;
+ float f;
+
+ c = 'b';
+ i = 3;
+ f = 6.5;
+
+ c = add2(c, c);
+ i = add2(i, i);
+ f = add2(f, f);
+}
diff --git a/gdb/testsuite/gdb.hp/ctti-add3.cc b/gdb/testsuite/gdb.hp/ctti-add3.cc
new file mode 100644
index 00000000000..7ba1b019f16
--- /dev/null
+++ b/gdb/testsuite/gdb.hp/ctti-add3.cc
@@ -0,0 +1,33 @@
+template<class T> T add3(T v1, T v2)
+{
+ T v3;
+ v3 = v1;
+ v3 += v2;
+ return v3;
+}
+
+template<class T> T add4(T v1, T v2)
+{
+ T v3;
+ v3 = v1;
+ v3 += v2;
+ return v3;
+}
+
+void subr3()
+{
+ char c;
+ int i;
+ float f;
+
+ c = 'b';
+ i = 3;
+ f = 6.5;
+
+ c = add3(c, c);
+ i = add3(i, i);
+ f = add3(f, f);
+ c = add4(c, c);
+ i = add4(i, i);
+ f = add4(f, f);
+}
diff --git a/gdb/testsuite/gdb.hp/ctti.exp b/gdb/testsuite/gdb.hp/ctti.exp
new file mode 100644
index 00000000000..e53210dda0b
--- /dev/null
+++ b/gdb/testsuite/gdb.hp/ctti.exp
@@ -0,0 +1,269 @@
+# Copyright (C) 1998 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+
+# This file is part of the gdb testsuite
+# file written by Elena Zannoni (ezannoni@cygnus.com)
+#
+# source files ctti-add.cc, ctti-add1.cc, ctti-add2.cc, ctti-add3.cc
+#
+
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+
+# Check to see if we have an executable to test. If not, then either we
+# haven't tried to compile one, or the compilation failed for some reason.
+# In either case, just notify the user and skip the tests in this file.
+
+set testfile "ctti-add"
+set srcfile ${testfile}.cc
+set srcfile1 ${testfile}1.cc
+set srcfile2 ${testfile}2.cc
+set srcfile3 ${testfile}3.cc
+set binfile ${objdir}/${subdir}/${testfile}
+
+if [get_compiler_info ${binfile} "c++"] {
+ return -1;
+}
+
+
+if {[skip_hp_tests $gcc_compiled]} then { continue }
+
+#if { [gdb_compile "${srcdir}/${subdir}/${srcfile} ${srcdir}/${subdir}/${srcfile1} ${srcdir}/${subdir}/${srcfile2} ${srcdir}/${subdir}/${srcfile3}" "${binfile}" executable {debug c++}] != "" } {
+# gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+#}
+
+set cmdline "$CXX ${srcdir}/${subdir}/${srcfile} ${srcdir}/${subdir}/${srcfile1} ${srcdir}/${subdir}/${srcfile2} ${srcdir}/${subdir}/${srcfile3} -g -o ${binfile}"
+
+remote_exec build $cmdline
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+
+
+if ![runto_main] then {
+ perror "couldn't run to breakpoint"
+ continue
+}
+
+
+send_gdb "n\n"
+gdb_expect {
+ -re "$decimal.*i = 2;.*$gdb_prompt $" {
+ pass "next "
+ }
+ -re ".*$gdb_prompt $" { fail "next " }
+ timeout { fail "next " }
+ }
+
+
+send_gdb "n\n"
+gdb_expect {
+ -re "$decimal.*f = 4.5;.*$gdb_prompt $" {
+ pass "next "
+ }
+ -re ".*$gdb_prompt $" { fail "next " }
+ timeout { fail "next " }
+ }
+
+send_gdb "n\n"
+gdb_expect {
+ -re "$decimal.*c = add\\(c, c\\);.*$gdb_prompt $" {
+ pass "next "
+ }
+ -re ".*$gdb_prompt $" { fail "next " }
+ timeout { fail "next " }
+ }
+
+send_gdb "n\n"
+gdb_expect {
+ -re "$decimal.*i = add\\(i, i\\);.*$gdb_prompt $" {
+ pass "next "
+ }
+ -re ".*$gdb_prompt $" { fail "next " }
+ timeout { fail "next " }
+ }
+
+send_gdb "n\n"
+gdb_expect {
+ -re "$decimal.*f = add\\(f, f\\);.*$gdb_prompt $" {
+ pass "next "
+ }
+ -re ".*$gdb_prompt $" { fail "next " }
+ timeout { fail "next " }
+ }
+
+send_gdb "n\n"
+gdb_expect {
+ -re "$decimal.*add1\\(\\);.*$gdb_prompt $" {
+ pass "next "
+ }
+ -re ".*$gdb_prompt $" { fail "next " }
+ timeout { fail "next " }
+ }
+
+send_gdb "print c\n"
+gdb_expect {
+ -re ".$decimal = -62.*\r\n$gdb_prompt $" {
+ pass "print value of c"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of c" }
+ timeout { fail "(timeout) print value of c" }
+ }
+
+
+send_gdb "print f\n"
+gdb_expect {
+ -re ".$decimal = 9\r\n$gdb_prompt $" {
+ pass "print value of f"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of f" }
+ timeout { fail "(timeout) print value of f" }
+ }
+
+
+send_gdb "print i\n"
+gdb_expect {
+ -re ".$decimal = 4\r\n$gdb_prompt $" {
+ pass "print value of i"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of i" }
+ timeout { fail "(timeout) print value of i" }
+ }
+
+
+
+send_gdb "print add<int>(2,2)\n"
+gdb_expect {
+ -re ".$decimal = 4\r\n$gdb_prompt $" {
+ pass "print value of add<int>(2,2)"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of add<int>(2,2)" }
+ timeout { fail "(timeout) print value of add<int>(2,2)" }
+ }
+
+send_gdb "print add<float>(2.3,2.3)\n"
+gdb_expect {
+ -re ".$decimal = 4\\.5\[0-9\]+\r\n$gdb_prompt $" {
+ pass "print value of add<float>(2.3,2.3)"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of add<float>(2.3,2.3)" }
+ timeout { fail "(timeout) print value of add<float>(2.3,2.3)" }
+ }
+
+send_gdb "print add<char>('A','A')\n"
+gdb_expect {
+ -re ".$decimal = -126.*202.\r\n$gdb_prompt $" {
+ pass "print value of add<char>('A','A')"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of add<char>('A','A')" }
+ timeout { fail "(timeout) print value of add<char>('A','A')" }
+ }
+
+
+send_gdb "print add2<int>(2,2)\n"
+gdb_expect {
+ -re ".$decimal = 4\r\n$gdb_prompt $" {
+ pass "print value of add2<int>(2,2)"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of add2<int>(2,2)" }
+ timeout { fail "(timeout) print value of add2<int>(2,2)" }
+ }
+
+send_gdb "print add2<float>(2.3,2.3)\n"
+gdb_expect {
+ -re ".$decimal = 4\\.5\[0-9\]+\r\n$gdb_prompt $" {
+ pass "print value of add2<float>(2.3,2.3)"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of add2<float>(2.3,2.3)" }
+ timeout { fail "(timeout) print value of add2<float>(2.3,2.3)" }
+ }
+
+send_gdb "print add2<char>('A','A')\n"
+gdb_expect {
+ -re ".$decimal = -126.*202.\r\n$gdb_prompt $" {
+ pass "print value of add2<char>('A','A')"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of add2<char>('A','A')" }
+ timeout { fail "(timeout) print value of add2<char>('A','A')" }
+ }
+
+send_gdb "print add3<int>(2,2)\n"
+gdb_expect {
+ -re ".$decimal = 4\r\n$gdb_prompt $" {
+ pass "print value of add3<int>(2,2)"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of add3<int>(2,2)" }
+ timeout { fail "(timeout) print value of add3<int>(2,2)" }
+ }
+
+send_gdb "print add3<float>(2.3,2.3)\n"
+gdb_expect {
+ -re ".$decimal = 4\\.5\[0-9\]+\r\n$gdb_prompt $" {
+ pass "print value of add3<float>(2.3,2.3)"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of add3<float>(2.3,2.3)" }
+ timeout { fail "(timeout) print value of add3<float>(2.3,2.3)" }
+ }
+
+send_gdb "print add3<char>('A','A')\n"
+gdb_expect {
+ -re ".$decimal = -126.*202.\r\n$gdb_prompt $" {
+ pass "print value of add3<char>('A','A')"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of add3<char>('A','A')" }
+ timeout { fail "(timeout) print value of add3<char>('A','A')" }
+ }
+
+send_gdb "print add4<int>(2,2)\n"
+gdb_expect {
+ -re ".$decimal = 4\r\n$gdb_prompt $" {
+ pass "print value of add4<int>(2,2)"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of add4<int>(2,2)" }
+ timeout { fail "(timeout) print value of add4<int>(2,2)" }
+ }
+
+send_gdb "print add4<float>(2.3,2.3)\n"
+gdb_expect {
+ -re ".$decimal = 4\\.5\[0-9\]+\r\n$gdb_prompt $" {
+ pass "print value of add4<float>(2.3,2.3)"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of add4<float>(2.3,2.3)" }
+ timeout { fail "(timeout) print value of add4<float>(2.3,2.3)" }
+ }
+
+send_gdb "print add4<char>('A','A')\n"
+gdb_expect {
+ -re ".$decimal = -126.*202.\r\n$gdb_prompt $" {
+ pass "print value of add4<char>('A','A')"
+ }
+ -re ".*$gdb_prompt $" { fail "print value of add4<char>('A','A')" }
+ timeout { fail "(timeout) print value of add4<char>('A','A')" }
+ }
+
+
+gdb_exit
+return 0
diff --git a/gdb/testsuite/gdb.hp/dbx.exp b/gdb/testsuite/gdb.hp/dbx.exp
new file mode 100644
index 00000000000..66f24e90a59
--- /dev/null
+++ b/gdb/testsuite/gdb.hp/dbx.exp
@@ -0,0 +1,222 @@
+# Copyright (C) 1998 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+
+set testfile1 "average"
+set testfile2 "sum"
+set testfile "dbx-test"
+set binfile1 ${objdir}/${subdir}/${testfile1}
+set binfile2 ${objdir}/${subdir}/${testfile2}
+set binfile ${objdir}/${subdir}/${testfile}
+
+
+
+if { [gdb_compile "${srcdir}/${subdir}/average.c" "${binfile1}.o" object {debug}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+if { [gdb_compile "${srcdir}/${subdir}/sum.c" "${binfile2}.o" object {debug}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+if { [gdb_compile "${binfile1}.o ${binfile2}.o" ${binfile} executable {debug}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+if [get_compiler_info ${binfile}] {
+ return -1;
+}
+if {[skip_hp_tests $gcc_compiled]} then { continue }
+
+proc dbx_reinitialize_dir { subdir } {
+ global gdb_prompt
+
+ send_gdb "use\n"
+ gdb_expect {
+ -re "Reinitialize source path to empty.*y or n. " {
+ send_gdb "y\n"
+ gdb_expect {
+ -re "Source directories searched.*$gdb_prompt $" {
+ send_gdb "use $subdir\n"
+ gdb_expect {
+ -re "Source directories searched.*$gdb_prompt $" {
+ verbose "Dir set to $subdir"
+ }
+ -re ".*$gdb_prompt $" {
+ perror "Dir \"$subdir\" failed."
+ }
+ }
+ }
+ -re ".*$gdb_prompt $" {
+ perror "Dir \"$subdir\" failed."
+ }
+ }
+ }
+ -re ".*$gdb_prompt $" {
+ perror "Dir \"$subdir\" failed."
+ }
+ }
+}
+
+# In "testsuite/config/unix-gdb.exp", the routine "gdb_load"
+# is defined as "gdb_file_cmd". The binding of "gdb_file_cmd"
+# is done at invocation time. Before this file is processed,
+# it binds to the definition in "testsuite/lib/gdb.exp"; after
+# this file is processed, it binds to this definition.
+# TCL lets us overrides a previous routine definition without a
+# warning (isn't that special?).
+#
+# This means that tests before use "file" to load a target, and
+# tests afterwards use the pair "symbol-file" "exec-file".
+#
+# I'm leaving it as it is for now because at the moment it
+# is the only test we have of the use of the combination of
+# "symbol-file" and "exec-file" to load a debugging target (the
+# other definition uses "file".
+#
+# Symbol-file and exec-file should be tested explicitly, not
+# as a side effect of running a particular test (in this case,
+# "testsuite/gdb.compat/dbx.exp").
+#
+#
+proc gdb_file_cmd {arg } {
+ global verbose
+ global loadpath
+ global loadfile
+ global GDB
+ global gdb_prompt
+ global spawn_id
+ upvar timeout timeout
+
+ send_gdb "symbol-file $arg\n"
+ gdb_expect {
+ -re "Reading symbols from.*done.*$gdb_prompt $" {
+ verbose "\t\tLoaded $arg into the $GDB"
+ send_gdb "exec-file $arg\n"
+ return 0
+ }
+ -re "has no symbol-table.*$gdb_prompt $" {
+ perror "$arg wasn't compiled with \"-g\""
+ return -1
+ }
+ -re "A program is being debugged already.*Kill it.*y or n. $" {
+ send_gdb "y\n"
+ verbose "\t\tKilling previous program being debugged"
+ exp_continue
+ }
+ -re "Load new symbol table from \".*\".*y or n. $" {
+ send_gdb "y\n"
+ gdb_expect {
+ -re "Reading symbols from.*done.*$gdb_prompt $" {
+ verbose "\t\tLoaded $arg with new symbol table into $GDB"
+ return 0
+ }
+ timeout {
+ perror "(timeout) Couldn't load $arg, other program already loaded."
+ return -1
+ }
+ }
+ }
+ -re ".*No such file or directory.*$gdb_prompt $" {
+ perror "($arg) No such file or directory\n"
+ return -1
+ }
+ -re "$gdb_prompt $" {
+ perror "couldn't load $arg into $GDB."
+ return -1
+ }
+ timeout {
+ perror "couldn't load $arg into $GDB (timed out)."
+ return -1
+ }
+ eof {
+ # This is an attempt to detect a core dump, but seems not to
+ # work. Perhaps we need to match .* followed by eof, in which
+ # expect does not seem to have a way to do that.
+ perror "couldn't load $arg into $GDB (end of file)."
+ return -1
+ }
+ }
+}
+
+#
+#test_breakpoints
+#
+proc test_breakpoints { } {
+ gdb_test "stop in main" "Breakpoint.*at.*: file.*average\.c, line 31\."
+ gdb_test "status" "Num.*Type.*Disp.*Enb.*Address.*What\r\n1\[ \r\]+breakpoint\[ \r\]+keep y.*in main at.*average\.c:31.*"
+ gdb_test "stop at 36" "Breakpoint.*at.*: file.*average\.c, line 36.*"
+ gdb_test "stop in 36" "Usage: stop in <function . address>"
+ gdb_test "stop at main" "Usage: stop at <line>"
+}
+
+#
+#test_assign
+#
+proc test_assign { } {
+ gdb_test "run" ""
+ gdb_test "assign first=1" ""
+ gdb_test "print first" ".1 = 1"
+}
+
+#
+#test_whereis
+#
+proc test_whereis { } {
+ gdb_test "whereis my_list" "All variables matching regular expression \"my_list\":\r\n\r\nFile.*average\.c:\r\nstatic int my_list\\\[10\\\];"
+}
+
+#
+#test_func
+#
+proc test_func { } {
+ gdb_test "cont" ""
+ gdb_test "step" ""
+ gdb_test "func sum" "'sum' not within current stack frame\."
+ gdb_test "stop in sum" "Breakpoint.*at.*: file.*sum\.c, line 11\."
+ gdb_test "cont"
+ gdb_test "func print_average" ".*in print_average.*\\(list=.*, low=0, high=6\\).*at.*average\.c:17\r\n17\[ \t\]+total = sum\\(list, low, high\\);"
+}
+
+# Start with a fresh gdb.
+
+gdb_exit
+global GDBFLAGS
+set saved_gdbflags $GDBFLAGS
+
+set GDBFLAGS "$GDBFLAGS --dbx"
+gdb_start
+dbx_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+send_gdb "set width 0\n"
+gdb_expect -re "$gdb_prompt $"
+test_breakpoints
+test_assign
+test_whereis
+gdb_test "file average.c:1" "1\[ \t\]+/. This is a sample program.*"
+test_func
+
+gdb_exit
+set GDBFLAGS $saved_gdbflags
+return 0
diff --git a/gdb/testsuite/gdb.hp/exception.cc b/gdb/testsuite/gdb.hp/exception.cc
new file mode 100644
index 00000000000..27459329a8b
--- /dev/null
+++ b/gdb/testsuite/gdb.hp/exception.cc
@@ -0,0 +1,48 @@
+// Test file for exception handling support.
+
+#include <iostream.h>
+
+int foo (int i)
+{
+ if (i < 32)
+ throw (int) 13;
+ else
+ return i * 2;
+}
+
+extern "C" int bar (int k, unsigned long eharg, int flag);
+
+int bar (int k, unsigned long eharg, int flag)
+{
+ cout << "k is " << k << " eharg is " << eharg << " flag is " << flag << endl;
+ return 1;
+}
+
+int main()
+{
+ int j;
+
+ try {
+ j = foo (20);
+ }
+ catch (int x) {
+ cout << "Got an except " << x << endl;
+ }
+
+ try {
+ try {
+ j = foo (20);
+ }
+ catch (int x) {
+ cout << "Got an except " << x << endl;
+ throw;
+ }
+ }
+ catch (int y) {
+ cout << "Got an except (rethrown) " << y << endl;
+ }
+
+ // Not caught
+ foo (20);
+
+}
diff --git a/gdb/testsuite/gdb.hp/exception.exp b/gdb/testsuite/gdb.hp/exception.exp
new file mode 100644
index 00000000000..4cafbdcd001
--- /dev/null
+++ b/gdb/testsuite/gdb.hp/exception.exp
@@ -0,0 +1,408 @@
+# Copyright (C) 1997, 1998 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+#
+# tests for exception-handling support
+# Written by Satish Pai <pai@apollo.hp.com> 1997-07-23
+
+# This file is part of the gdb testsuite
+
+# Note: These tests are geared to the HP aCC compiler,
+# which has an idiosyncratic way of emitting debug info
+# for exceptions -- it uses a callback mechanism, which
+# is different from the way g++ records exception info
+# for debugging
+
+# The tests are in two parts; the first part deals with
+# statically linked (archive-bound) executables, and the
+# second part repeats those tests with dynamically linked
+# (shared bound) executables. (In the latter case we use
+# a different mechanism to get the address of the notification
+# hook in the C++ support library.) The tests themselves are
+# the same in both parts.
+#
+# IMPORTANT:
+# ---------
+# IF YOU CHANGE A TEST IN ONE PART MAKE SURE YOU CHANGE IT
+# --------------------------------------------------------
+# IN THE OTHER PART TOO!
+# ----------------------
+
+
+
+if $tracelevel then {
+ strace $tracelevel
+ }
+
+
+#
+# test running programs
+#
+
+# Part I : Archive-bound executables
+# ----------------------------------
+
+set testfile "exception"
+set srcfile ${testfile}.cc
+set binfile ${objdir}/${subdir}/${testfile}
+
+if [get_compiler_info ${binfile} "c++"] {
+ return -1;
+}
+
+
+if {[skip_hp_tests $gcc_compiled]} then { continue }
+
+set cmdline "$CXX ${srcdir}/${subdir}/${srcfile} +A -Wl,-a,archive -g -o ${binfile}"
+
+remote_exec build $cmdline
+
+# Start with a fresh gdb
+
+set prms_id 0
+set bug_id 0
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+if ![runto_main] then {
+ perror "couldn't run to breakpoint"
+ continue
+}
+
+# Set a catch catchpoint
+
+send_gdb "catch catch\n"
+gdb_expect {
+ -re "Catchpoint \[0-9\]* \\(catch\\)\r\n$gdb_prompt $" {
+ pass "catch catch (static executable)"
+ }
+ -re ".*$gdb_prompt $" { fail "catch catch (static executable)" }
+ timeout { fail "(timeout) catch catch (static executable)" }
+}
+
+# Set a throw catchpoint
+
+send_gdb "catch throw\n"
+gdb_expect {
+ -re "Catchpoint \[0-9\]* \\(throw\\)\r\n$gdb_prompt $" {
+ pass "catch throw (static executable)"
+ }
+ -re ".*$gdb_prompt $" { fail "catch throw (static executable)" }
+ timeout { fail "(timeout) catch throw (static executable)" }
+}
+
+# The catchpoints should be listed in the list of breakpoints.
+
+send_gdb "info break\n"
+gdb_expect {
+ -re ".*\[0-9\]*\[ \]*catch catch\[ \]*keep y\[ \]*exception catch\[ \]*\r\n\[0-9\]*\[ \]*catch throw\[ \]*keep y\[ \]*exception throw\[ \]*\r\n$gdb_prompt $" {
+ pass "info break with catchpoints (static executable)"
+ }
+ -re ".*$gdb_prompt $" { fail "info break (static executable)" }
+ timeout { fail "(timeout) info break (static executable)" }
+}
+
+# Info catch currently does not work with HP aCC. No easy way to
+# list the active handlers on the stack.
+
+send_gdb "info catch\n"
+gdb_expect {
+ -re "Info catch not supported with this target/compiler combination.\r\n$gdb_prompt $" {
+ pass "info catch (static executable)"
+ }
+ -re ".*$gdb_prompt $" { fail "info catch (static executable)" }
+ timeout { fail "(timeout) info catch (static executable)" }
+}
+
+# Get the first exception thrown
+
+send_gdb "continue\n"
+gdb_expect {
+ -re "Continuing.*Catchpoint \[0-9\]* \\(exception thrown\\), throw location.*exception\\.cc:8, catch location .*exception\\.cc:28\r\n.*$gdb_prompt $" {
+ pass "caught a throw (static executable)"
+ }
+ -re ".*$gdb_prompt $" { fail "didn't catch a throw (static executable)" }
+ timeout { fail "(timeout) after continue -- didn't catch a throw? (static executable)" }
+}
+
+send_gdb "backtrace\n"
+gdb_expect {
+ -re "#0\[ \]*__d_eh_break.*\r\n#1\[ \]*$hex in __d_eh_notify_callback \\(eh_type=__EH_NOTIFY_THROW.*\r\n#2\[ \]*$hex in __eh_notify_throw.*\r\n#3\[ \]*$hex in foo \\(i=20\\) at .*exception\\.cc:8\r\n#4\[ \]*$hex in main.* at .*exception\\.cc:26\r\n$gdb_prompt $" {
+ pass "backtrace after throw (static executable)"
+ }
+ -re ".*$gdb_prompt $" { fail "backtrace after throw (static executable)" }
+ timeout { fail "(timeout) backtrace after throw (static executable)" }
+}
+
+# Now intercept it when it is caught.
+
+send_gdb "continue\n"
+gdb_expect {
+ -re "Continuing.*Catchpoint \[0-9\]* \\(exception caught\\), throw location.*exception\\.cc:8, catch location .*exception\\.cc:28\r\n.*$gdb_prompt $" {
+ pass "caught a catch (static executable)"
+ }
+ -re ".*$gdb_prompt $" { fail "didn't catch a catch (static executable)" }
+ timeout { fail "(timeout) after continue -- didn't catch a catch? (static executable)" }
+}
+
+send_gdb "backtrace\n"
+gdb_expect {
+ -re "#0\[ \]*__d_eh_break.*\r\n#1\[ \]*$hex in __d_eh_notify_callback \\(eh_type=__EH_NOTIFY_CATCH.*\r\n.*\r\n#3\[ \]*$hex in __throw__.*\r\n#4\[ \]*$hex in foo \\(i=20\\) at .*exception.cc:8\r\n#5\[ \]*$hex in main.* at .*exception.cc:26\r\n$gdb_prompt $" {
+ pass "backtrace after catch (static executable)"
+ }
+ -re ".*$gdb_prompt $" { fail "backtrace after catch (static executable)" }
+ timeout { fail "(timeout) backtrace after catch (static executable)" }
+}
+
+send_gdb "continue\n"
+gdb_expect {
+ -re "Continuing\\.\r\nGot.*\r\nCatchpoint \[0-9\]* \\(exception thrown\\), throw location.*exception\\.cc:8, catch location .*exception\\.cc:36\r\n.*$gdb_prompt $" {
+ pass "caught a throw (2) (static executable)"
+ }
+ -re ".*$gdb_prompt $" { fail "didn't catch a throw (2) (static executable)" }
+ timeout { fail "(timeout) after continue -- didn't catch a throw (2)? (static executable)" }
+}
+
+send_gdb "continue\n"
+gdb_expect {
+ -re "Continuing.*Catchpoint \[0-9\]* \\(exception caught\\), throw location.*exception\\.cc:8, catch location .*exception\\.cc:36\r\n.*$gdb_prompt $" {
+ pass "caught a catch (2) (static executable)"
+ }
+ -re ".*$gdb_prompt $" { fail "didn't catch a catch (2) (static executable)" }
+ timeout { fail "(timeout) after continue -- didn't catch a catch (2)? (static executable)" }
+}
+
+# Now the exception will be rethrown.
+
+send_gdb "continue\n"
+gdb_expect {
+ -re "Continuing\\.\r\nGot.*\r\nCatchpoint \[0-9\]* \\(exception thrown\\), throw location.*exception\\.cc:38, catch location .*exception\\.cc:41\r\n.*$gdb_prompt $" {
+ pass "caught a rethrow (static executable)"
+ }
+ -re ".*$gdb_prompt $" { fail "didn't catch a rethrow (static executable)" }
+ timeout { fail "(timeout) after continue -- didn't catch a rethrow? (static executable)" }
+}
+
+send_gdb "continue\n"
+gdb_expect {
+ -re "Continuing.*Catchpoint \[0-9\]* \\(exception caught\\), throw location.*exception\\.cc:38, catch location .*exception\\.cc:41\r\n.*$gdb_prompt $" {
+ pass "caught a catch (3) (static executable)"
+ }
+ -re ".*$gdb_prompt $" { fail "didn't catch a catch (3) (static executable)" }
+ timeout { fail "(timeout) after continue -- didn't catch a catch (3)? (static executable)" }
+}
+
+send_gdb "backtrace\n"
+gdb_expect {
+ -re "#0\[ \]*__d_eh_break.*\r\n#1\[ \]*$hex in __d_eh_notify_callback \\(eh_type=__EH_NOTIFY_CATCH.*\r\n.*\r\n#3\[ \]*$hex in __rethrow.*\r\n#4\[ \]*$hex in main.* at .*exception\\.cc:38\r\n#5\[ \]*$hex in foo \\(i=20\\) at .*exception.cc:8\r\n#6\[ \]*$hex in main.* at .*exception.cc:34\r\n$gdb_prompt $" {
+ pass "backtrace after catch (3) (static executable)"
+ }
+ -re ".*$gdb_prompt $" { fail "backtrace after catch (3) (static executable)" }
+ timeout { fail "(timeout) backtrace after catch (3) (static executable)" }
+}
+
+# Now the exception will be thrown, but not catch-able anywhere.
+
+send_gdb "continue\n"
+gdb_expect {
+ -re "Continuing\\.\r\nGot.*\r\nCatchpoint \[0-9\]* \\(exception thrown\\), throw location.*exception\\.cc:8, catch location unknown\r\n.*$gdb_prompt $" {
+ pass "caught an uncatchable throw (static executable)"
+ }
+ -re ".*$gdb_prompt $" { fail "didn't catch an uncatchable throw (static executable)" }
+ timeout { fail "(timeout) after continue -- didn't catch an uncatchable throw? (static executable)" }
+}
+
+# Part II : Shared-bound executables
+# ----------------------------------
+
+# Start with a fresh gdb
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+
+set prms_id 0
+set bug_id 0
+
+set testfile "exception"
+set srcfile ${testfile}.cc
+set binfile ${objdir}/${subdir}/${testfile}
+
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug c++}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will a
+utomatically fail."
+}
+
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+
+if ![runto_main] then {
+ perror "couldn't run to breakpoint"
+ continue
+}
+
+# Set a catch catchpoint
+
+send_gdb "catch catch\n"
+gdb_expect {
+ -re "Catchpoint \[0-9\]* \\(catch\\)\r\n$gdb_prompt $" {
+ pass "catch catch (dynamic executable)"
+ }
+ -re ".*$gdb_prompt $" { fail "catch catch (dynamic executable)" }
+ timeout { fail "(timeout) catch catch (dynamic executable)" }
+}
+
+# Set a throw catchpoint
+
+send_gdb "catch throw\n"
+gdb_expect {
+ -re "Catchpoint \[0-9\]* \\(throw\\)\r\n$gdb_prompt $" {
+ pass "catch throw (dynamic executable)"
+ }
+ -re ".*$gdb_prompt $" { fail "catch throw (dynamic executable)" }
+ timeout { fail "(timeout) catch throw (dynamic executable)" }
+}
+
+# The catchpoints should be listed in the list of breakpoints.
+
+send_gdb "info break\n"
+gdb_expect {
+ -re ".*\[0-9\]*\[ \]*catch catch\[ \]*keep y\[ \]*exception catch\[ \]*\r\n\[0-9\]*\[ \]*catch throw\[ \]*keep y\[ \]*exception throw\[ \]*\r\n$gdb_prompt $" {
+ pass "info break with catchpoints (dynamic executable)"
+ }
+ -re ".*$gdb_prompt $" { fail "info break (dynamic executable)" }
+ timeout { fail "(timeout) info break (dynamic executable)" }
+}
+
+# Info catch currently does not work with HP aCC. No easy way to
+# list the active handlers on the stack.
+
+send_gdb "info catch\n"
+gdb_expect {
+ -re "Info catch not supported with this target/compiler combination.\r\n$gdb_prompt $" {
+ pass "info catch (dynamic executable)"
+ }
+ -re ".*$gdb_prompt $" { fail "info catch (dynamic executable)" }
+ timeout { fail "(timeout) info catch (dynamic executable)" }
+}
+
+# Get the first exception thrown
+
+send_gdb "continue\n"
+gdb_expect {
+ -re "Continuing.*Catchpoint \[0-9\]* \\(exception thrown\\), throw location.*exception\\.cc:8, catch location .*exception\\.cc:28\r\n.*$gdb_prompt $" {
+ pass "caught a throw (dynamic executable)"
+ }
+ -re ".*$gdb_prompt $" { fail "didn't catch a throw (dynamic executable)" }
+ timeout { fail "(timeout) after continue -- didn't catch a throw? (dynamic executable)" }
+}
+
+send_gdb "backtrace\n"
+gdb_expect {
+ -re "#0\[ \]*__d_eh_break.*\r\n#1\[ \]*$hex in __d_eh_notify_callback \\(eh_type=__EH_NOTIFY_THROW.*\r\n#2\[ \]*$hex in __eh_notify_throw.*\r\n#3\[ \]*$hex in foo \\(i=20\\) at .*exception\\.cc:8\r\n#4\[ \]*$hex in main.* at .*exception\\.cc:26\r\n$gdb_prompt $" {
+ pass "backtrace after throw (dynamic executable)"
+ }
+ -re ".*$gdb_prompt $" { fail "backtrace after throw (dynamic executable)" }
+ timeout { fail "(timeout) backtrace after throw (dynamic executable)" }
+}
+
+# Now intercept it when it is caught.
+
+send_gdb "continue\n"
+gdb_expect {
+ -re "Continuing.*Catchpoint \[0-9\]* \\(exception caught\\), throw location.*exception\\.cc:8, catch location .*exception\\.cc:28\r\n.*$gdb_prompt $" {
+ pass "caught a catch (dynamic executable)"
+ }
+ -re ".*$gdb_prompt $" { fail "didn't catch a catch (dynamic executable)" }
+ timeout { fail "(timeout) after continue -- didn't catch a catch? (dynamic executable)" }
+}
+
+send_gdb "backtrace\n"
+gdb_expect {
+ -re "#0\[ \]*__d_eh_break.*\r\n#1\[ \]*$hex in __d_eh_notify_callback \\(eh_type=__EH_NOTIFY_CATCH.*\r\n.*\r\n#3\[ \]*$hex in __throw__.*\r\n#4\[ \]*$hex in foo \\(i=20\\) at .*exception.cc:8\r\n#5\[ \]*$hex in main.* at .*exception.cc:26\r\n$gdb_prompt $" {
+ pass "backtrace after catch (dynamic executable)"
+ }
+ -re ".*$gdb_prompt $" { fail "backtrace after catch (dynamic executable)" }
+ timeout { fail "(timeout) backtrace after catch (dynamic executable)" }
+}
+
+send_gdb "continue\n"
+gdb_expect {
+ -re "Continuing\\.\r\nGot.*\r\nCatchpoint \[0-9\]* \\(exception thrown\\), throw location.*exception\\.cc:8, catch location .*exception\\.cc:36\r\n.*$gdb_prompt $" {
+ pass "caught a throw (2) (dynamic executable)"
+ }
+ -re ".*$gdb_prompt $" { fail "didn't catch a throw (2) (dynamic executable)" }
+ timeout { fail "(timeout) after continue -- didn't catch a throw (2)? (dynamic executable)" }
+}
+
+send_gdb "continue\n"
+gdb_expect {
+ -re "Continuing.*Catchpoint \[0-9\]* \\(exception caught\\), throw location.*exception\\.cc:8, catch location .*exception\\.cc:36\r\n.*$gdb_prompt $" {
+ pass "caught a catch (2) (dynamic executable)"
+ }
+ -re ".*$gdb_prompt $" { fail "didn't catch a catch (2) (dynamic executable)" }
+ timeout { fail "(timeout) after continue -- didn't catch a catch (2)? (dynamic executable)" }
+}
+
+# Now the exception will be rethrown.
+
+send_gdb "continue\n"
+gdb_expect {
+ -re "Continuing\\.\r\nGot.*\r\nCatchpoint \[0-9\]* \\(exception thrown\\), throw location.*exception\\.cc:38, catch location .*exception\\.cc:41\r\n.*$gdb_prompt $" {
+ pass "caught a rethrow (dynamic executable)"
+ }
+ -re ".*$gdb_prompt $" { fail "didn't catch a rethrow (dynamic executable)" }
+ timeout { fail "(timeout) after continue -- didn't catch a rethrow? (dynamic executable)" }
+}
+
+send_gdb "continue\n"
+gdb_expect {
+ -re "Continuing.*Catchpoint \[0-9\]* \\(exception caught\\), throw location.*exception\\.cc:38, catch location .*exception\\.cc:41\r\n.*$gdb_prompt $" {
+ pass "caught a catch (3) (dynamic executable)"
+ }
+ -re ".*$gdb_prompt $" { fail "didn't catch a catch (3) (dynamic executable)" }
+ timeout { fail "(timeout) after continue -- didn't catch a catch (3)? (dynamic executable)" }
+}
+
+send_gdb "backtrace\n"
+gdb_expect {
+ -re "#0\[ \]*__d_eh_break.*\r\n#1\[ \]*$hex in __d_eh_notify_callback \\(eh_type=__EH_NOTIFY_CATCH.*\r\n.*\r\n#3\[ \]*$hex in __rethrow.*\r\n#4\[ \]*$hex in main.* at .*exception\\.cc:38\r\n#5\[ \]*$hex in foo \\(i=20\\) at .*exception.cc:8\r\n#6\[ \]*$hex in main.* at .*exception.cc:34\r\n$gdb_prompt $" {
+ pass "backtrace after catch (3) (dynamic executable)"
+ }
+ -re ".*$gdb_prompt $" { fail "backtrace after catch (3) (dynamic executable)" }
+ timeout { fail "(timeout) backtrace after catch (3) (dynamic executable)" }
+}
+
+# Now the exception will be thrown, but not catch-able anywhere.
+
+send_gdb "continue\n"
+gdb_expect {
+ -re "Continuing\\.\r\nGot.*\r\nCatchpoint \[0-9\]* \\(exception thrown\\), throw location.*exception\\.cc:8, catch location unknown\r\n.*$gdb_prompt $" {
+ pass "caught an uncatchable throw (dynamic executable)"
+ }
+ -re ".*$gdb_prompt $" { fail "didn't catch an uncatchable throw (dynamic executable)" }
+ timeout { fail "(timeout) after continue -- didn't catch an uncatchable throw? (dynamic executable)" }
+}
+
diff --git a/gdb/testsuite/gdb.hp/execd-program.c b/gdb/testsuite/gdb.hp/execd-program.c
new file mode 100644
index 00000000000..0320991062d
--- /dev/null
+++ b/gdb/testsuite/gdb.hp/execd-program.c
@@ -0,0 +1,28 @@
+#include <stdio.h>
+
+/* There is a global_i in follow_exec, which exec's us. We
+ should not be able to see that other definition of global_i
+ after we are exec'd.
+ */
+int global_i = 0;
+
+main (argc, argv)
+ int argc;
+ char * argv[];
+{
+ /* There is a local_j in follow_exec, which exec's us. We
+ should not be able to see that other definition of local_j
+ after we are exec'd.
+ */
+ int local_j = argc;
+ char * s;
+
+ printf ("Hello from execd_program...\n");
+ if (argc != 2)
+ {
+ printf ("expected one string argument\n");
+ exit (-1);
+ }
+ s = argv[1];
+ printf ("argument received: %s\n", s);
+}
diff --git a/gdb/testsuite/gdb.hp/foll-exec.c b/gdb/testsuite/gdb.hp/foll-exec.c
new file mode 100644
index 00000000000..c51fa52dcfd
--- /dev/null
+++ b/gdb/testsuite/gdb.hp/foll-exec.c
@@ -0,0 +1,35 @@
+#include <stdio.h>
+
+int global_i = 100;
+
+main ()
+{
+ int local_j = global_i+1;
+ int local_k = local_j+1;
+
+ printf ("follow-exec is about to execlp(execd-program)...\n");
+
+ execlp ("gdb.hp/execd-program",
+ "gdb.hp/execd-program",
+ "execlp arg1 from follow-exec",
+ (char *)0);
+
+ printf ("follow-exec is about to execl(execd-program)...\n");
+
+ execl ("gdb.hp/execd-program",
+ "gdb.hp/execd-program",
+ "execl arg1 from follow-exec",
+ "execl arg2 from follow-exec",
+ (char *)0);
+
+ {
+ static char * argv[] = {
+ "gdb.hp/execd-program",
+ "execv arg1 from follow-exec",
+ 0};
+
+ printf ("follow-exec is about to execv(execd-program)...\n");
+
+ execv ("gdb.hp/execd-program", argv);
+ }
+}
diff --git a/gdb/testsuite/gdb.hp/foll-exec.exp b/gdb/testsuite/gdb.hp/foll-exec.exp
new file mode 100644
index 00000000000..f7d6089931c
--- /dev/null
+++ b/gdb/testsuite/gdb.hp/foll-exec.exp
@@ -0,0 +1,412 @@
+# Copyright (C) 1997 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+if $tracelevel then {
+ strace $tracelevel
+ }
+
+set prms_id 0
+set bug_id 0
+
+# are we on a target board
+if ![isnative] then {
+ return
+}
+
+if {![istarget "hppa*-*-hpux10.30"] && ![istarget "hppa*-*-hpux11.*"]} {
+ #setup_xfail "*-*.*"
+ return 0
+}
+
+set testfile "foll-exec"
+set testfile2 "execd-program"
+set srcfile ${testfile}.c
+set srcfile2 ${testfile2}.c
+set binfile ${objdir}/${subdir}/${testfile}
+set binfile2 ${objdir}/${subdir}/${testfile2}
+
+# build the first test case
+#if { [compile "-g -DNO_PROTOTYPES ${srcdir}/${subdir}/${srcfile2} -o ${binfile2} "] != "" } {
+# perror "Couldn't compile ${srcfile2}"
+# return -1
+#}
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile2}" "${binfile2}" executable {debug}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+#if { [compile "-g ${srcdir}/${subdir}/${srcfile} -o ${binfile} "] != "" } {
+# execute_anywhere "rm -f ${objdir}/${subdir}/${testfile}.tmp"
+ # built the second test case since we can't use prototypes
+# warning "Prototypes not supported, rebuilding with -DNO_PROTOTYPES"
+# execute_anywhere "echo set prototypes 0 > ${objdir}/${subdir}/${testfile}.tmp"
+# if { [compile "-g -DNO_PROTOTYPES ${srcdir}/${subdir}/${srcfile} -o ${binfile} "] != "" } {
+# perror "Couldn't compile ${testfile}.c"
+# return -1
+# }
+#}
+
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+
+# Until "catch exec" is implemented on other targets...
+#
+if ![istarget "hppa*-hp-hpux*"] then {
+ setup_xfail "*-*-*"
+}
+
+proc zap_session {} {
+ global gdb_prompt
+ global binfile
+
+ send_gdb "kill\n"
+ gdb_expect {
+ -re ".*Kill the program being debugged.*y or n. $" {
+ send_gdb "y\n"
+ send_gdb "file $binfile\n"
+ gdb_expect {
+ -re ".*Load new symbol table from.*y or n. $" {
+ send_gdb "y\n"
+ gdb_expect {
+ -re "Reading symbols from.*$gdb_prompt $" {}
+ timeout { fail "loading symbols (timeout)"; return }
+ }
+ }
+ -re ".*gdb_prompt $" {}
+ timeout { fail "loading symbols (timeout)"; return }
+ }
+ }
+ -re ".*$gdb_prompt $" {}
+ timeout { fail "killing inferior (timeout)" ; return }
+ }
+}
+
+proc do_exec_tests {} {
+ global gdb_prompt
+ global binfile
+ global srcfile
+ global srcfile2
+ global testfile
+ global testfile2
+
+ # Start the program running, and stop at main.
+ #
+ if ![runto_main] then {
+ perror "Couldn't run ${testfile}"
+ return
+ }
+
+ # Verify that we can see various global and local variables
+ # in this program, and that they have expected values. Some
+ # of these variables are also declared in the program we'll
+ # exec in a moment.
+ #
+ send_gdb "next 3\n"
+ gdb_expect {
+ -re "12.*execlp.*$gdb_prompt $"\
+ {pass "step to exec call"}
+ -re "$gdb_prompt $" {fail "step to exec call"}
+ timeout {fail "(timeout) step to exec call"}
+ }
+ send_gdb "print global_i\n"
+ gdb_expect {
+ -re ".* = 100.*$gdb_prompt $"\
+ {pass "print follow-exec/global_i"}
+ -re "$gdb_prompt $" {fail "print follow-exec/global_i"}
+ timeout {fail "(timeout) print follow-exec/global_i"}
+ }
+ send_gdb "print local_j\n"
+ gdb_expect {
+ -re ".* = 101.*$gdb_prompt $"\
+ {pass "print follow-exec/local_j"}
+ -re "$gdb_prompt $" {fail "print follow-exec/local_j"}
+ timeout {fail "(timeout) print follow-exec/local_j"}
+ }
+ send_gdb "print local_k\n"
+ gdb_expect {
+ -re ".* = 102.*$gdb_prompt $"\
+ {pass "print follow-exec/local_k"}
+ -re "$gdb_prompt $" {fail "print follow-exec/local_k"}
+ timeout {fail "(timeout) print follow-exec/local_k"}
+ }
+
+ # Try stepping through an execlp call, without catching it.
+ # We should stop in execd-program, at its first statement.
+ #
+ send_gdb "next\n"
+ gdb_expect {
+ -re "Executing new program: .*${testfile2}.*${srcfile2}:17.*int local_j = argc;.*$gdb_prompt $"\
+ {pass "step through execlp call"}
+ -re "$gdb_prompt $" {fail "step through execlp call"}
+ timeout {fail "(timeout) step through execlp call"}
+ }
+
+ # Verify that we can see the variables defined in the newly-exec'd
+ # program, and CANNOT see those defined in the exec'ing program.
+ #
+ send_gdb "next\n"
+ gdb_expect {
+ -re "20.*printf.*$gdb_prompt $"\
+ {pass "step after execlp call"}
+ -re "$gdb_prompt $" {fail "step after execlp call"}
+ timeout {fail "(timeout) step after execlp call"}
+ }
+ send_gdb "print global_i\n"
+ gdb_expect {
+ -re ".* = 0.*$gdb_prompt $"\
+ {pass "print execd-program/global_i (after execlp)"}
+ -re "$gdb_prompt $" {fail "print execd-program/global_i (after execlp)"}
+ timeout {fail "(timeout) print execd-program/global_i (after execlp)"}
+ }
+ send_gdb "print local_j\n"
+ gdb_expect {
+ -re ".* = 2.*$gdb_prompt $"\
+ {pass "print execd-program/local_j (after execlp)"}
+ -re "$gdb_prompt $" {fail "print execd-program/local_j (after execlp)"}
+ timeout {fail "(timeout) print execd-program/local_j (after execlp)"}
+ }
+ send_gdb "print local_k\n"
+ gdb_expect {
+ -re "No symbol \"local_k\" in current context.*$gdb_prompt $"\
+ {pass "print follow-exec/local_k (after execlp)"}
+ -re "$gdb_prompt $" {fail "print follow-exec/local_k (after execlp)"}
+ timeout {fail "(timeout) print follow-exec/local_k (after execlp)"}
+ }
+
+ # Explicitly kill this program, or a subsequent rerun actually runs
+ # the exec'd program, not the original program...
+ zap_session
+
+ # Start the program running, and stop at main.
+ #
+ if ![runto_main] then {
+ perror "Couldn't run ${testfile} (2nd try)"
+ return
+ }
+
+ # Verify that we can catch an exec event, and then continue
+ # to follow through the exec. (Since there's a breakpoint on
+ # "main", it'll also be transferred to the exec'd program,
+ # and we expect to stop there.)
+ #
+ send_gdb "catch exec\n"
+ gdb_expect {
+ -re "Catchpoint .*(exec).*$gdb_prompt $"\
+ {pass "set catch exec"}
+ -re "$gdb_prompt $" {fail "set catch exec"}
+ timeout {fail "(timeout) set catch exec"}
+ }
+
+ # Verify that the catchpoint is mentioned in an "info breakpoints",
+ # and further that the catchpoint mentions no program name.
+ #
+ send_gdb "info breakpoints\n"
+ gdb_expect {
+ -re ".*catch exec.*keep y.*$gdb_prompt $"\
+ {pass "info shows catchpoint without exec pathname"}
+ -re ".*catch exec.*program \"\".*$gdb_prompt $"\
+ {fail "info shows catchpoint without exec pathname"}
+ -re "$gdb_prompt $" {fail "info shows catchpoint without exec pathname"}
+ timeout {fail "(timeout) info shows catchpoint without exec pathname"}
+ }
+
+ send_gdb "continue\n"
+ gdb_expect {
+ -re ".*Executing new program:.*${testfile2}.*Catchpoint .*(exec\'d .*${testfile2}).*in .START..*$gdb_prompt $"\
+ {pass "hit catch exec"}
+ -re "$gdb_prompt $" {fail "hit catch exec"}
+ timeout {fail "(timeout) hit catch exec"}
+ }
+
+ # Verify that the catchpoint is mentioned in an "info breakpoints",
+ # and further that the catchpoint managed to capture the exec'd
+ # program's name.
+ #
+ send_gdb "info breakpoints\n"
+ gdb_expect {
+ -re ".*catch exec .*program \".*${testfile2}\".*$gdb_prompt $"\
+ {pass "info shows catchpoint exec pathname"}
+ -re "$gdb_prompt $" {fail "info shows catchpoint exec pathname"}
+ timeout {fail "(timeout) info shows catchpoint exec pathname"}
+ }
+
+ # Verify that we can continue from the catchpoint, and land in the
+ # main of the newly-exec'd program.
+ #
+ send_gdb "continue\n"
+ gdb_expect {
+ -re ".*${srcfile2}:17.*$gdb_prompt $"\
+ {pass "continue after hit catch exec"}
+ -re "$gdb_prompt $" {fail "continue after hit catch exec"}
+ timeout {fail "(timeout) continue after hit catch exec"}
+ }
+
+ # Explicitly kill this program, or a subsequent rerun actually runs
+ # the exec'd program, not the original program...
+ zap_session
+
+ # Start the program running, and stop at main.
+ #
+ if ![runto_main] then {
+ perror "Couldn't run ${testfile} (3rd try)"
+ return
+ }
+
+ # Verify that we can follow through follow an execl()
+ # call. (We must jump around earlier exec* calls.)
+ #
+ send_gdb "tbreak 19\n"
+ gdb_expect {
+ -re "Breakpoint .*file .*${srcfile}, line 19.*$gdb_prompt $"\
+ {pass "prepare to jump to execl call"}
+ -re "$gdb_prompt $" {fail "prepare to jump to execl call"}
+ timeout {fail "(timeout) prepare to jump to execl call"}
+ }
+ send_gdb "jump 19\n"
+ gdb_expect {
+ -re "main.* at .*${srcfile}:19.*$gdb_prompt $"\
+ {pass "jump to execl call"}
+ -re "$gdb_prompt $" {fail "jump to execl call"}
+ timeout {fail "(timeout) jump to execl call"}
+ }
+ # Note that stepping through an exec call causes the step-count
+ # to be reset to zero. I.e.: you may specify "next 2" at the
+ # call, but you'll actually stop at the first breakpoint set in
+ # the newly-exec'd program, not after the remaining step-count
+ # reaches zero.
+ #
+ send_gdb "next 2\n"
+ gdb_expect {
+ -re "Executing new program: .*${testfile2}.*${srcfile2}:17.*int local_j = argc;.*$gdb_prompt $"\
+ {pass "step through execl call"}
+ -re "$gdb_prompt $" {fail "step through execl call"}
+ timeout {fail "(timeout) step through execl call"}
+ }
+ send_gdb "next\n"
+ gdb_expect {
+ -re "20.*printf.*$gdb_prompt $"\
+ {pass "step after execl call"}
+ -re "$gdb_prompt $" {fail "step after execl call"}
+ timeout {fail "(timeout) step after execl call"}
+ }
+
+ # Verify that we can print a local variable (which happens to be
+ # assigned the value of main's argc).
+ #
+ send_gdb "print local_j\n"
+ gdb_expect {
+ -re ".* = 3.*$gdb_prompt $"\
+ {pass "print execd-program/local_j (after execl)"}
+ -re "$gdb_prompt $" {fail "print execd-program/local_j (after execl)"}
+ timeout {fail "(timeout) print execd-program/local_j (after execl)"}
+ }
+
+ # Explicitly kill this program, or a subsequent rerun actually runs
+ # the exec'd program, not the original program...
+ zap_session
+
+ # Start the program running, and stop at main.
+ #
+ if ![runto_main] then {
+ perror "Couldn't run ${testfile} (4th try)"
+ return
+ }
+
+ # Verify that we can follow through follow an execv()
+ # call. (We must jump around earlier exec* calls.)
+ #
+ send_gdb "tbreak 33\n"
+ gdb_expect {
+ -re "Breakpoint .*file .*${srcfile}, line 33.*$gdb_prompt $"\
+ {pass "prepare to jump to execv call"}
+ -re "$gdb_prompt $" {fail "prepare to jump to execv call"}
+ timeout {fail "(timeout) prepare to jump to execv call"}
+ }
+ send_gdb "jump 33\n"
+ gdb_expect {
+ -re "main.* at .*${srcfile}:33.*$gdb_prompt $"\
+ {pass "jump to execv call"}
+ -re "$gdb_prompt $" {fail "jump to execv call"}
+ timeout {fail "(timeout) jump to execv call"}
+ }
+ send_gdb "next\n"
+ gdb_expect {
+ -re "Executing new program: .*${testfile2}.*${srcfile2}:17.*int local_j = argc;.*$gdb_prompt $"\
+ {pass "step through execv call"}
+ -re "$gdb_prompt $" {fail "step through execv call"}
+ timeout {fail "(timeout) step through execv call"}
+ }
+ send_gdb "next\n"
+ gdb_expect {
+ -re "20.*printf.*$gdb_prompt $"\
+ {pass "step after execv call"}
+ -re "$gdb_prompt $" {fail "step after execv call"}
+ timeout {fail "(timeout) step after execv call"}
+ }
+
+ # Verify that we can print a local variable (which happens to be
+ # assigned the value of main's argc).
+ #
+ send_gdb "print local_j\n"
+ gdb_expect {
+ -re ".* = 2.*$gdb_prompt $"\
+ {pass "print execd-program/local_j (after execv)"}
+ -re "$gdb_prompt $" {fail "print execd-program/local_j (after execv)"}
+ timeout {fail "(timeout) print execd-program/local_j (after execv)"}
+ }
+
+ # Explicitly kill this program, or a subsequent rerun actually runs
+ # the exec'd program, not the original program...
+ zap_session
+
+ # Start the program running, and stop at main.
+ #
+ if ![runto_main] then {
+ perror "Couldn't run ${testfile} (4th try)"
+ return
+ }
+
+ # Verify that we can just continue and thereby follow through an
+ # exec call. (Since the breakpoint on "main" is reset, we should
+ # just stop in main of the newly-exec'd program.)
+ #
+ send_gdb "continue\n"
+ gdb_expect {
+ -re "Executing new program: .*${testfile2}.*${srcfile2}:17.*int local_j = argc;.*$gdb_prompt $"\
+ {pass "continue through exec"}
+ -re "$gdb_prompt $" {fail "continue through exec"}
+ timeout {fail "(timeout) continue through exec"}
+ }
+}
+
+# Start with a fresh gdb
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+
+# This is a test of gdb's ability to follow a process through a
+# Unix exec() system call.
+#
+do_exec_tests
+
+return 0
diff --git a/gdb/testsuite/gdb.hp/foll-fork.c b/gdb/testsuite/gdb.hp/foll-fork.c
new file mode 100644
index 00000000000..89f92ae22fe
--- /dev/null
+++ b/gdb/testsuite/gdb.hp/foll-fork.c
@@ -0,0 +1,25 @@
+#include <stdio.h>
+
+void callee (i)
+ int i;
+{
+ printf("callee: %d\n", i);
+}
+
+main ()
+{
+ int pid;
+ int v = 5;
+
+ pid = fork ();
+ if (pid == 0)
+ {
+ v++;
+ /* printf ("I'm the child!\n"); */
+ }
+ else
+ {
+ v--;
+ /* printf ("I'm the proud parent of child #%d!\n", pid); */
+ }
+}
diff --git a/gdb/testsuite/gdb.hp/foll-fork.exp b/gdb/testsuite/gdb.hp/foll-fork.exp
new file mode 100644
index 00000000000..7231764f3b4
--- /dev/null
+++ b/gdb/testsuite/gdb.hp/foll-fork.exp
@@ -0,0 +1,385 @@
+# Copyright (C) 1997 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+if $tracelevel then {
+ strace $tracelevel
+ }
+
+set prms_id 0
+set bug_id 0
+
+# are we on a target board
+if ![isnative] then {
+ return
+}
+
+if {![istarget "hppa*-*-hpux10.30"] && ![istarget "hppa*-*-hpux11.*"]} {
+ #setup_xfail "*-*.*"
+ return 0
+}
+
+set testfile "foll-fork"
+set srcfile ${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+
+# build the first test case
+#if { [compile "-g ${srcdir}/${subdir}/${srcfile} -o ${binfile} "] != "" } {
+# execute_anywhere "rm -f ${objdir}/${subdir}/${testfile}.tmp"
+ # built the second test case since we can't use prototypes
+# warning "Prototypes not supported, rebuilding with -DNO_PROTOTYPES"
+# execute_anywhere "echo set prototypes 0 > ${objdir}/${subdir}/${testfile}.tmp"
+# if { [compile "-g -DNO_PROTOTYPES ${srcdir}/${subdir}/${srcfile} -o ${binfile} "] != "" } {
+# perror "Couldn't compile ${testfile}.c"
+# return -1
+# }
+#}
+
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+
+
+# Until "set follow-fork-mode" and "catch fork" are implemented on
+# other targets...
+#
+if ![istarget "hppa*-hp-hpux*"] then {
+ setup_xfail "*-*-*"
+}
+
+proc default_fork_parent_follow {} {
+ global gdb_prompt
+
+ send_gdb "show follow\n"
+ gdb_expect {
+ -re "Debugger response to a program call of fork or vfork is \"parent\"..*$gdb_prompt $"\
+ {pass "default show parent follow, no catchpoints"}
+ -re "$gdb_prompt $" {fail "default show parent follow, no catchpoints"}
+ timeout {fail "(timeout) default show parent follow, no catchpoints"}
+ }
+ send_gdb "next 2\n"
+ gdb_expect {
+ -re "Detaching after fork from.*$gdb_prompt $"\
+ {pass "default parent follow, no catchpoints"}
+ -re "$gdb_prompt $" {fail "default parent follow, no catchpoints"}
+ timeout {fail "(timeout) default parent follow, no catchpoints" }
+ }
+ # The child has been detached; allow time for any output it might
+ # generate to arrive, so that output doesn't get confused with
+ # any expected debugger output from a subsequent testpoint.
+ #
+ exec sleep 1
+}
+
+proc explicit_fork_parent_follow {} {
+ global gdb_prompt
+
+ send_gdb "set follow parent\n"
+ gdb_expect {
+ -re "$gdb_prompt $" {pass "set follow parent"}
+ timeout {fail "(timeout) set follow parent"}
+ }
+ send_gdb "show follow\n"
+ gdb_expect {
+ -re "Debugger response to a program call of fork or vfork is \"parent\"..*$gdb_prompt $"\
+ {pass "explicit show parent follow, no catchpoints"}
+ -re "$gdb_prompt $" {fail "explicit show parent follow, no catchpoints"}
+ timeout {fail "(timeout) explicit show parent follow, no catchpoints"}
+ }
+ send_gdb "next 2\n"
+ gdb_expect {
+ -re "Detaching after fork from.*$gdb_prompt $"\
+ {pass "explicit parent follow, no catchpoints"}
+ -re "$gdb_prompt $" {fail "explicit parent follow, no catchpoints"}
+ timeout {fail "(timeout) explicit parent follow, no catchpoints"}
+ }
+ # The child has been detached; allow time for any output it might
+ # generate to arrive, so that output doesn't get confused with
+ # any expected debugger output from a subsequent testpoint.
+ #
+ exec sleep 1
+}
+
+proc explicit_fork_child_follow {} {
+ global gdb_prompt
+
+ send_gdb "set follow child\n"
+ gdb_expect {
+ -re "$gdb_prompt $" {pass "set follow child"}
+ timeout {fail "(timeout) set follow child"}
+ }
+ send_gdb "show follow\n"
+ gdb_expect {
+ -re "Debugger response to a program call of fork or vfork is \"child\"..*$gdb_prompt $"\
+ {pass "explicit show child follow, no catchpoints"}
+ -re "$gdb_prompt $" {fail "explicit show child follow, no catchpoints"}
+ timeout {fail "(timeout) explicit show child follow, no catchpoints"}
+ }
+ send_gdb "next 2\n"
+ gdb_expect {
+ -re "Detaching from program:.*Attaching after fork to.*$gdb_prompt $"\
+ {pass "explicit child follow, no catchpoints"}
+ -re "$gdb_prompt $" {fail "explicit child follow, no catchpoints"}
+ timeout {fail "(timeout) explicit child follow, no catchpoints"}
+ }
+ # The child has been detached; allow time for any output it might
+ # generate to arrive, so that output doesn't get confused with
+ # any gdb_expected debugger output from a subsequent testpoint.
+ #
+ exec sleep 1
+}
+
+proc catch_fork_child_follow {} {
+ global gdb_prompt
+
+ send_gdb "catch fork\n"
+ gdb_expect {
+ -re "Catchpoint .*(fork).*$gdb_prompt $"\
+ {pass "explicit child follow, set catch fork"}
+ -re "$gdb_prompt $" {fail "explicit child follow, set catch fork"}
+ timeout {fail "(timeout) explicit child follow, set catch fork"}
+ }
+
+ # Verify that the catchpoint is mentioned in an "info breakpoints",
+ # and further that the catchpoint mentions no process id.
+ #
+ send_gdb "info breakpoints\n"
+ gdb_expect {
+ -re ".*catch fork.*keep y.*$gdb_prompt $"\
+ {pass "info shows catchpoint without pid"}
+ -re ".*catch fork.*process .*$gdb_prompt $"\
+ {fail "info shows catchpoint without pid"}
+ -re "$gdb_prompt $" {fail "info shows catchpoint without pid"}
+ timeout {fail "(timeout) info shows catchpoint without pid"}
+ }
+
+ send_gdb "continue\n"
+ gdb_expect {
+ -re "Catchpoint.*(forked process.*),.*in _fork_sys.*$gdb_prompt $"\
+ {pass "explicit child follow, catch fork"}
+ -re "$gdb_prompt $" {fail "explicit child follow, catch fork"}
+ timeout {fail "(timeout) explicit child follow, catch fork"}
+ }
+
+ # Verify that the catchpoint is mentioned in an "info breakpoints",
+ # and further that the catchpoint managed to capture a process id.
+ #
+ send_gdb "info breakpoints\n"
+ gdb_expect {
+ -re ".*catch fork .*process \[0-9\]+.*$gdb_prompt $"\
+ {pass "info shows catchpoint pid"}
+ -re "$gdb_prompt $" {fail "info shows catchpoint pid"}
+ timeout {fail "(timeout) info shows catchpoint pid"}
+ }
+
+ send_gdb "set follow child\n"
+ gdb_expect {
+ -re "$gdb_prompt $" {pass "set follow child"}
+ timeout {fail "(timeout) set follow child"}
+ }
+ send_gdb "tbreak 15\n"
+ gdb_expect {
+ -re "Breakpoint.*, line 15.*$gdb_prompt $"\
+ {pass "set follow child, tbreak"}
+ -re "$gdb_prompt $" {fail "set follow child, tbreak"}
+ timeout {fail "(timeout) set follow child, tbreak"}
+ }
+ send_gdb "continue\n"
+ gdb_expect {
+ -re ".*Detaching from program:.*Attaching after fork to.* at .*15.*$gdb_prompt $"\
+ {pass "set follow child, hit tbreak"}
+ -re "$gdb_prompt $" {fail "set follow child, hit tbreak"}
+ timeout {fail "(timeout) set follow child, hit tbreak"}
+ }
+ # The child has been detached; allow time for any output it might
+ # generate to arrive, so that output doesn't get confused with
+ # any expected debugger output from a subsequent testpoint.
+ #
+ exec sleep 1
+ send_gdb "delete breakpoints\n"
+ gdb_expect {
+ -re "Delete all breakpoints.*$" {
+ send_gdb "y\n"
+ gdb_expect {
+ -re "$gdb_prompt $"\
+ {pass "set follow child, cleanup"}
+ timeout {fail "(timeout) set follow child, cleanup"}
+ }
+ }
+ -re "$gdb_prompt $" {fail "set follow child, cleanup"}
+ timeout {fail "(timeout) set follow child, cleanup"}
+ }
+}
+
+proc tcatch_fork_parent_follow {} {
+ global gdb_prompt
+
+ send_gdb "catch fork\n"
+ gdb_expect {
+ -re "Catchpoint .*(fork).*$gdb_prompt $"\
+ {pass "explicit parent follow, set tcatch fork"}
+ -re "$gdb_prompt $" {fail "explicit parent follow, set tcatch fork"}
+ timeout {fail "(timeout) explicit parent follow, set tcatch fork"}
+ }
+# ??rehrauer: I don't yet know how to get the id of the tcatch
+# via this script, so that I can add a -do list to it. For now,
+# do the follow stuff after the catch happens.
+
+ send_gdb "continue\n"
+ gdb_expect {
+ -re ".*in _fork_sys.*$gdb_prompt $"\
+ {pass "explicit parent follow, tcatch fork"}
+ -re "$gdb_prompt $" {fail "explicit parent follow, tcatch fork"}
+ timeout {fail "(timeout) explicit parent follow, tcatch fork"}
+ }
+ send_gdb "set follow parent\n"
+ gdb_expect {
+ -re "$gdb_prompt $" {pass "set follow parent"}
+ timeout {fail "(timeout) set follow parent"}
+ }
+ send_gdb "tbreak 15\n"
+ gdb_expect {
+ -re "Breakpoint.*, line 15.*$gdb_prompt $"\
+ {pass "set follow parent, tbreak"}
+ -re "$gdb_prompt $" {fail "set follow parent, tbreak"}
+ timeout {fail "(timeout) set follow child, tbreak"}
+ }
+ send_gdb "continue\n"
+ gdb_expect {
+ -re ".*Detaching after fork from.* at .*15.*$gdb_prompt $"\
+ {pass "set follow parent, hit tbreak"}
+ -re "$gdb_prompt $" {fail "set follow parent, hit tbreak"}
+ timeout {fail "(timeout) set follow parent, hit tbreak"}
+ }
+ # The child has been detached; allow time for any output it might
+ # generate to arrive, so that output doesn't get confused with
+ # any expected debugger output from a subsequent testpoint.
+ #
+ exec sleep 1
+ send_gdb "delete breakpoints\n"
+ gdb_expect {
+ -re "Delete all breakpoints.*$" {
+ send_gdb "y\n"
+ gdb_expect {
+ -re "$gdb_prompt $"\
+ {pass "set follow parent, cleanup"}
+ timeout {fail "(timeout) set follow parent, cleanup"}
+ }
+ }
+ -re "$gdb_prompt $" {fail "set follow parent, cleanup"}
+ timeout {fail "(timeout) set follow parent, cleanup"}
+ }
+}
+
+proc do_fork_tests {} {
+ global gdb_prompt
+
+ # Verify that help is available for "set follow-fork-mode".
+ #
+ send_gdb "help set follow-fork-mode\n"
+ gdb_expect {
+ -re "Set debugger response to a program call of fork or vfork..*
+A fork or vfork creates a new process. follow-fork-mode can be:.*
+.*parent - the original process is debugged after a fork.*
+.*child - the new process is debugged after a fork.*
+.*ask - the debugger will ask for one of the above choices.*
+For \"parent\" or \"child\", the unfollowed process will run free..*
+By default, the debugger will follow the parent process..*$gdb_prompt $"\
+ { pass "help set follow" }
+ -re "$gdb_prompt $" { fail "help set follow" }
+ timeout { fail "(timeout) help set follow" }
+ }
+
+ # Verify that we can set follow-fork-mode, using an abbreviation
+ # for both the flag and its value.
+ #
+ send_gdb "set follow ch\n"
+ send_gdb "show fol\n"
+ gdb_expect {
+ -re "Debugger response to a program call of fork or vfork is \"child\".*$gdb_prompt $"\
+ {pass "set follow, using abbreviations"}
+ timeout {fail "(timeout) set follow, using abbreviations"}
+ }
+
+ # Verify that we cannot set follow-fork-mode to nonsense.
+ #
+ send_gdb "set follow chork\n"
+ gdb_expect {
+ -re "Undefined item: \"chork\".*$gdb_prompt $"\
+ {pass "set follow to nonsense is prohibited"}
+ -re "$gdb_prompt $" {fail "set follow to nonsense is prohibited"}
+ timeout {fail "(timeout) set follow to nonsense is prohibited"}
+ }
+ send_gdb "set follow parent\n"
+ gdb_expect {
+ -re "$gdb_prompt $" {pass "set follow to nonsense is prohibited (reset parent)"}
+ timeout {fail "set follow to nonsense is prohibited (reset parent)"}
+ }
+
+ # Test the default behaviour, which is to follow the parent of a
+ # fork, and detach from the child. Do this without catchpoints.
+ #
+ if [runto_main] then { default_fork_parent_follow }
+
+ # Test the ability to explicitly follow the parent of a fork, and
+ # detach from the child. Do this without catchpoints.
+ #
+ if [runto_main] then { explicit_fork_parent_follow }
+
+ # Test the ability to follow the child of a fork, and detach from
+ # the parent. Do this without catchpoints.
+ #
+ if [runto_main] then { explicit_fork_child_follow }
+
+ # Test the ability to follow both child and parent of a fork. Do
+ # this without catchpoints.
+ # ??rehrauer: NYI. Will add testpoints here when implemented.
+ #
+
+ # Test the ability to have the debugger ask the user at fork-time
+ # whether to follow the parent, child or both. Do this without
+ # catchpoints.
+ # ??rehrauer: NYI. Will add testpoints here when implemented.
+ #
+
+ # Test the ability to catch a fork, specify that the child be
+ # followed, and continue. Make the catchpoint permanent.
+ #
+ if [runto_main] then { catch_fork_child_follow }
+
+ # Test the ability to catch a fork, specify via a -do clause that
+ # the parent be followed, and continue. Make the catchpoint temporary.
+ #
+ if [runto_main] then { tcatch_fork_parent_follow }
+}
+
+# Start with a fresh gdb
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+
+# This is a test of gdb's ability to follow the parent, child or both
+# parent and child of a Unix fork() system call.
+#
+do_fork_tests
+
+return 0
diff --git a/gdb/testsuite/gdb.hp/foll-vfork.c b/gdb/testsuite/gdb.hp/foll-vfork.c
new file mode 100644
index 00000000000..c7e6cd32909
--- /dev/null
+++ b/gdb/testsuite/gdb.hp/foll-vfork.c
@@ -0,0 +1,15 @@
+#include <stdio.h>
+
+main ()
+{
+ int pid;
+
+ pid = vfork ();
+ if (pid == 0) {
+ printf ("I'm the child!\n");
+ execlp ("gdb.hp/vforked-program", "gdb.hp/vforked-program", (char *)0);
+ }
+ else {
+ printf ("I'm the proud parent of child #%d!\n", pid);
+ }
+}
diff --git a/gdb/testsuite/gdb.hp/foll-vfork.exp b/gdb/testsuite/gdb.hp/foll-vfork.exp
new file mode 100644
index 00000000000..26c6981f974
--- /dev/null
+++ b/gdb/testsuite/gdb.hp/foll-vfork.exp
@@ -0,0 +1,381 @@
+# Copyright (C) 1997 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+if $tracelevel then {
+ strace $tracelevel
+ }
+
+set prms_id 0
+set bug_id 0
+
+# are we on a target board
+if ![isnative] then {
+ return
+}
+
+if {![istarget "hppa*-*-hpux10.30"] && ![istarget "hppa*-*-hpux11.*"]} {
+ #setup_xfail "*-*.*"
+ return 0
+}
+
+set testfile "foll-vfork"
+set testfile2 "vforked-program"
+set srcfile ${testfile}.c
+set srcfile2 ${testfile2}.c
+set binfile ${objdir}/${subdir}/${testfile}
+set binfile2 ${objdir}/${subdir}/${testfile2}
+
+# build the first test case
+#execute_anywhere "echo set prototypes 1 > ${objdir}/${subdir}/${testfile}.tmp"
+#if { [compile "-g -DNO_PROTOTYPES ${srcdir}/${subdir}/${srcfile2} -o ${binfile2} "] != "" } {
+# perror "Couldn't compile ${srcfile2}"
+# return -1
+#}
+
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+#if { [compile "-g ${srcdir}/${subdir}/${srcfile} -o ${binfile} "] != "" } {
+# execute_anywhere "rm -f ${objdir}/${subdir}/${testfile}.tmp"
+ # built the second test case since we can't use prototypes
+# warning "Prototypes not supported, rebuilding with -DNO_PROTOTYPES"
+# execute_anywhere "echo set prototypes 0 > ${objdir}/${subdir}/${testfile}.tmp"
+# if { [compile "-g -DNO_PROTOTYPES ${srcdir}/${subdir}/${srcfile} -o ${binfile} "] != "" } {
+# perror "Couldn't compile ${testfile}.c"
+# return -1
+# }
+#}
+
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile2}" "${binfile2}" executable {debug}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+
+# Until "set follow-fork-mode" and "catch vfork" are implemented on
+# other targets...
+#
+if ![istarget "hppa*-hp-hpux*"] then {
+ setup_xfail "*-*-*"
+}
+
+
+# A few of these tests require a little more time than the standard
+# timeout allows.
+set oldtimeout $timeout
+set timeout [expr "$timeout + 10"]
+
+proc vfork_parent_follow_through_step {} {
+ global gdb_prompt
+
+ send_gdb "set follow parent\n"
+ gdb_expect {
+ -re "$gdb_prompt $" {pass "set follow parent, vfork through step"}
+ timeout {fail "set follow parent, vfork through step"}
+ }
+ send_gdb "next\n"
+ gdb_expect {
+ -re "Detaching after fork from.*8.*$gdb_prompt $"\
+ {pass "vfork parent follow, through step"}
+ -re "$gdb_prompt $" {fail "vfork parent follow, through step"}
+ timeout {fail "(timeout) vfork parent follow, through step" }
+ }
+ # The child has been detached; allow time for any output it might
+ # generate to arrive, so that output doesn't get confused with
+ # any gdb_expected debugger output from a subsequent testpoint.
+ #
+ exec sleep 1
+}
+
+proc vfork_parent_follow_to_bp {} {
+ global gdb_prompt
+
+ send_gdb "set follow parent\n"
+ gdb_expect {
+ -re "$gdb_prompt $" {pass "set follow parent, vfork to bp"}
+ timeout {fail "set follow parent, vfork to bp"}
+ }
+ send_gdb "break 13\n"
+ gdb_expect {
+ -re "$gdb_prompt $" {pass "break, vfork to bp"}
+ timeout {fail "break, vfork to bp"}
+ }
+ send_gdb "continue\n"
+ gdb_expect {
+ -re ".*Detaching after fork from process.*Breakpoint.*13.*$gdb_prompt $"\
+ {pass "vfork parent follow, to bp"}
+ -re "$gdb_prompt $" {fail "vfork parent follow, to bp"}
+ timeout {fail "(timeout) vfork parent follow, to bp" }
+ }
+ # The child has been detached; allow time for any output it might
+ # generate to arrive, so that output doesn't get confused with
+ # any expected debugger output from a subsequent testpoint.
+ #
+ exec sleep 1
+}
+
+proc vfork_and_exec_child_follow_to_main_bp {} {
+ global gdb_prompt
+ global binfile
+
+ send_gdb "set follow child\n"
+ gdb_expect {
+ -re "$gdb_prompt $" {pass "set follow child, vfork and exec to main bp"}
+ timeout {fail "set follow child, vfork and exec to main bp"}
+ }
+ send_gdb "continue\n"
+ gdb_expect {
+ -re "Detaching from program.*Attaching after fork to.*Executing new program.*Breakpoint.*vforked-program.c:5.*$gdb_prompt $"\
+ {pass "vfork and exec child follow, to main bp"}
+ -re "$gdb_prompt $" {fail "vfork and exec child follow, to main bp"}
+ timeout {fail "(timeout) vfork and exec child follow, to main bp" }
+ }
+ # The parent has been detached; allow time for any output it might
+ # generate to arrive, so that output doesn't get confused with
+ # any gdb_expected debugger output from a subsequent testpoint.
+ #
+ exec sleep 1
+
+ # Explicitly kill this child, or a subsequent rerun actually runs
+ # the exec'd child, not the original program...
+ send_gdb "kill\n"
+ gdb_expect {
+ -re ".*Kill the program being debugged.*y or n. $" {
+ send_gdb "y\n"
+ send_gdb "file $binfile\n"
+ gdb_expect {
+ -re ".*Load new symbol table from.*y or n. $" {
+ send_gdb "y\n"
+ gdb_expect {
+ -re "Reading symbols from.*$gdb_prompt $" {}
+ timeout { fail "loading symbols (timeout)"; return }
+ }
+ }
+ -re ".*gdb_prompt $" {}
+ timeout { fail "loading symbols (timeout)"; return }
+ }
+ }
+ -re ".*$gdb_prompt $" {}
+ timeout { fail "killing inferior (timeout)" ; return }
+ }
+}
+
+proc vfork_and_exec_child_follow_through_step {} {
+ global gdb_prompt
+ global binfile
+
+# This test cannot be performed prior to HP-UX 10.30, because ptrace-based
+# debugging of a vforking program basically doesn't allow the child to do
+# things like hit a breakpoint between a vfork and exec. This means that
+# saying "set follow child; next" at a vfork() call won't work, because
+# the implementation of "next" sets a "step resume" breakpoint at the
+# return from the vfork(), which the child will hit on its way to exec'ing.
+#
+ if { ![istarget "hppa*-*-hpux10.30"] && ![istarget "hppa*-*-hpux11.*"] } {
+ verbose "vfork child-following next test ignored for non-hppa or pre-HP/UX-10.30 targets."
+ return 0
+ }
+
+ send_gdb "set follow child\n"
+ gdb_expect {
+ -re "$gdb_prompt $" {pass "set follow child, vfork and exec through step"}
+ timeout {fail "set follow child, vfork and exec through step"}
+ }
+ send_gdb "next\n"
+ gdb_expect {
+ -re "Detaching from program.*Attaching after fork to.*Executing new program.*Breakpoint.*vforked_program.c:5.*$gdb_prompt $"\
+ {pass "vfork and exec child follow, through step"}
+ -re "$gdb_prompt $" {fail "vfork and exec child follow, through step"}
+ timeout {fail "(timeout) vfork and exec child follow, through step" }
+ }
+ # The parent has been detached; allow time for any output it might
+ # generate to arrive, so that output doesn't get confused with
+ # any expected debugger output from a subsequent testpoint.
+ #
+ exec sleep 1
+
+ # Explicitly kill this child, or a subsequent rerun actually runs
+ # the exec'd child, not the original program...
+ send_gdb "kill\n"
+ gdb_expect {
+ -re ".*Kill the program being debugged.*y or n. $" {
+ send_gdb "y\n"
+ send_gdb "file $binfile\n"
+ gdb_expect {
+ -re ".*Load new symbol table from.*y or n. $" {
+ send_gdb "y\n"
+ gdb_expect {
+ -re "Reading symbols from.*$gdb_prompt $" {}
+ timeout { fail "loading symbols (timeout)"; return }
+ }
+ }
+ -re ".*gdb_prompt $" {}
+ timeout { fail "loading symbols (timeout)"; return }
+ }
+ }
+ -re ".*$gdb_prompt $" {}
+ timeout { fail "killing inferior (timeout)" ; return }
+ }
+}
+
+proc tcatch_vfork_then_parent_follow {} {
+ global gdb_prompt
+ global srcfile
+
+ send_gdb "set follow parent\n"
+ gdb_expect {
+ -re "$gdb_prompt $" {pass "set follow parent, tcatch vfork"}
+ timeout {fail "set follow parent, tcatch vfork"}
+ }
+ send_gdb "tcatch vfork\n"
+ gdb_expect {
+ -re "Catchpoint .*(vfork).*$gdb_prompt $"\
+ {pass "vfork parent follow, set tcatch vfork"}
+ -re "$gdb_prompt $" {fail "vfork parent follow, set tcatch vfork"}
+ timeout {fail "(timeout) vfork parent follow, set tcatch vfork"}
+ }
+ send_gdb "continue\n"
+# HP-UX 10.20 seems to stop you in "vfork", while more recent HP-UXs
+# stop you in "_vfork".
+ gdb_expect {
+ -re "0x\[0-9a-fA-F\]*.*vfork.*$gdb_prompt $"\
+ {pass "vfork parent follow, tcatch vfork"}
+ -re "0x\[0-9a-fA-F\]*.*_vfork.*$gdb_prompt $"\
+ {pass "vfork parent follow, tcatch vfork"}
+ -re "$gdb_prompt $" {fail "vfork parent follow, tcatch vfork"}
+ timeout {fail "(timeout) vfork parent follow, tcatch vfork"}
+ }
+ send_gdb "finish\n"
+ gdb_expect {
+ -re "Run till exit from.*vfork.*0x\[0-9a-fA-F\]* in main .* at .*${srcfile}:7.*$gdb_prompt $"\
+ {pass "vfork parent follow, finish after tcatch vfork"}
+ -re "$gdb_prompt $" {fail "vfork parent follow, finish after tcatch vfork"}
+ timeout {fail "(timeout) vfork parent follow, finish after tcatch vfork" }
+ }
+ # The child has been detached; allow time for any output it might
+ # generate to arrive, so that output doesn't get confused with
+ # any expected debugger output from a subsequent testpoint.
+ #
+ exec sleep 1
+}
+
+proc tcatch_vfork_then_child_follow {} {
+ global gdb_prompt
+ global srcfile2
+
+ send_gdb "set follow child\n"
+ gdb_expect {
+ -re "$gdb_prompt $" {pass "set follow child, tcatch vfork"}
+ timeout {fail "set follow child, tcatch vfork"}
+ }
+ send_gdb "tcatch vfork\n"
+ gdb_expect {
+ -re "Catchpoint .*(vfork).*$gdb_prompt $"\
+ {pass "vfork child follow, set tcatch vfork"}
+ -re "$gdb_prompt $" {fail "vfork child follow, set tcatch vfork"}
+ timeout {fail "(timeout) vfork child follow, set tcatch vfork"}
+ }
+ send_gdb "continue\n"
+# HP-UX 10.20 seems to stop you in "vfork", while more recent HP-UXs
+# stop you in "_vfork".
+ gdb_expect {
+ -re "0x\[0-9a-fA-F\]*.*vfork.*$gdb_prompt $"\
+ {pass "vfork child follow, tcatch vfork"}
+ -re "0x\[0-9a-fA-F\]*.*_vfork.*$gdb_prompt $"\
+ {pass "vfork child follow, tcatch vfork"}
+ -re "$gdb_prompt $" {fail "vfork child follow, tcatch vfork"}
+ timeout {fail "(timeout) vfork child follow, tcatch vfork"}
+ }
+ send_gdb "finish\n"
+ gdb_expect {
+ -re "Run till exit from.*vfork.*${srcfile2}:5.*$gdb_prompt $"\
+ {pass "vfork child follow, finish after tcatch vfork"}
+ -re "$gdb_prompt $" {fail "vfork child follow, finish after tcatch vfork"}
+ timeout {fail "(timeout) vfork child follow, finish after tcatch vfork" }
+ }
+ # The parent has been detached; allow time for any output it might
+ # generate to arrive, so that output doesn't get confused with
+ # any expected debugger output from a subsequent testpoint.
+ #
+ exec sleep 1
+}
+
+proc do_vfork_and_exec_tests {} {
+ global gdb_prompt
+
+ # Try following the parent process by stepping through a call to
+ # vfork. Do this without catchpoints.
+ if [runto_main] then { vfork_parent_follow_through_step }
+
+ # Try following the parent process by setting a breakpoint on the
+ # other side of a vfork, and running to that point. Do this
+ # without catchpoints.
+ if [runto_main] then { vfork_parent_follow_to_bp }
+
+ # Try following the child process by just continuing through the
+ # vfork, and letting the parent's breakpoint on "main" be auto-
+ # magically reset in the child.
+ #
+ if [runto_main] then { vfork_and_exec_child_follow_to_main_bp }
+
+ # Try following the child process by stepping through a call to
+ # vfork. The child also executes an exec. Since the child cannot
+ # be debugged until after it has exec'd, and since there's a bp on
+ # "main" in the parent, and since the bp's for the parent are
+ # recomputed in the exec'd child, the step through a vfork should
+ # land us in the "main" for the exec'd child, too.
+ #
+ if [runto_main] then { vfork_and_exec_child_follow_through_step }
+
+ # Try catching a vfork, and stepping out to the parent.
+ #
+ if [runto_main] then { tcatch_vfork_then_parent_follow }
+
+ # Try catching a vfork, and stepping out to the child.
+ #
+ if [runto_main] then { tcatch_vfork_then_child_follow }
+
+ # Test the ability to follow both child and parent of a vfork. Do
+ # this without catchpoints.
+ # ??rehrauer: NYI. Will add testpoints here when implemented.
+ #
+
+ # Test the ability to have the debugger ask the user at vfork-time
+ # whether to follow the parent, child or both. Do this without
+ # catchpoints.
+ # ??rehrauer: NYI. Will add testpoints here when implemented.
+ #
+}
+
+# Start with a fresh gdb
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+
+# This is a test of gdb's ability to follow the parent or child
+# of a Unix vfork() system call. (The child will subsequently
+# call a variant of a Unix exec() system call.)
+#
+do_vfork_and_exec_tests
+
+set timeout $oldtimeout
+return 0
diff --git a/gdb/testsuite/gdb.hp/gen-so-thresh.c b/gdb/testsuite/gdb.hp/gen-so-thresh.c
new file mode 100644
index 00000000000..c1a3eb580c5
--- /dev/null
+++ b/gdb/testsuite/gdb.hp/gen-so-thresh.c
@@ -0,0 +1,229 @@
+/*
+ * Program to generate the so-thresh testcase,
+ * including associated linked-against shared libraries.
+ * Build as:
+ *
+ * cc -g -o gen-so-thresh gen-so-thresh.c
+ *
+ * Invoke as:
+ *
+ * gen-so-thresh
+ *
+ * It will put all the code in the current directory (".").
+ *
+ * A makefile can also be generated if the -makemake option is used.
+ * To use the makefile:
+ *
+ * make -f so-thresh.mk all
+ *
+ * The name of the application is
+ *
+ * so-thresh
+ *
+ * (Revised from a program by John Bishop. --rehrauer)
+ */
+
+#include <stdio.h>
+#include <sys/stat.h>
+#include <sys/fcntl.h>
+
+int main (argc, argv)
+int argc;
+char **argv;
+{
+#define NUMBER_OF_INT_VARS 1500
+#define NUMBER_OF_LIBS 3
+ int lib_num = NUMBER_OF_LIBS;
+ int i;
+ int i2;
+ FILE *main_file;
+ FILE *lib_file;
+ FILE *make_file;
+ FILE *link_file;
+
+ char testcase_name [1000];
+ char linkfile_name [1000];
+ char makefile_name [1000];
+ char mainfile_name [1000];
+
+ char file_name[100];
+ /*
+ * 0123456789 <-- length of field
+ * "./fil0000000002.c"; <-- typical filename
+ * 12345678901234567890 <-- length of string
+ * 10 20
+ * ^where null goes
+ */
+ char file_name_core[100];
+
+ /* Verify input.
+ */
+ if ((argc < 1) || (argc > 2) || (argv == NULL) ||
+ ((argc == 2) && (strcmp (argv[1], "-makemake") != 0)))
+ {
+ printf ("** Syntax: %s [-makemake]\n", argv[0]);
+ return;
+ }
+
+ if (strncmp (argv[0], "gen-", 4) != 0)
+ {
+ printf ("** This tool expected to be named \"gen-something\"\n");
+ return;
+ }
+ strcpy (testcase_name, argv[0]+4);
+
+ strcpy (linkfile_name, testcase_name);
+ strcat (linkfile_name, ".linkopts");
+ link_file = fopen (linkfile_name, "w");
+ fprintf (link_file, "# Linker options for %s test\n", testcase_name);
+
+ /* Generate the makefile, if requested.
+ */
+ if (argc == 2)
+ {
+ strcpy (makefile_name, testcase_name);
+ strcat (makefile_name, ".mk.new");
+ make_file = fopen (makefile_name, "w");
+ printf (" Note: New makefile (%s) generated.\n", makefile_name);
+ printf (" May want to update existing makefile, if any.\n");
+ fprintf (make_file, "# Generated automatically by %s\n", argv[0]);
+ fprintf (make_file, "# Make file for %s test\n", testcase_name);
+ fprintf (make_file, "\n");
+ fprintf (make_file, "CFLAGS = +DA1.1 -g\n");
+ fprintf (make_file, "\n");
+ fprintf (make_file, "# This is how to build this generator.\n");
+ fprintf (make_file, "%s.o: %s.c\n", argv[0], argv[0]);
+ fprintf (make_file, "\t$(CC) $(CFLAGS) -o %s.o -c %s.c\n", argv[0], argv[0]);
+ fprintf (make_file, "%s: %s.o\n", argv[0], argv[0]);
+ fprintf (make_file, "\t$(CC) $(CFLAGS) -o %s %s.o\n", argv[0], argv[0]);
+ fprintf (make_file, "\n");
+ fprintf (make_file, "# This is how to run this generator.\n");
+ fprintf (make_file, "# This target should be made before the 'all' target,\n");
+ fprintf (make_file, "# to ensure that the shlib sources are all available.\n");
+ fprintf (make_file, "require_shlibs: %s\n", argv[0]);
+ for (i=0; i < lib_num; i++)
+ {
+ fprintf (make_file, "\tif ! [ -a lib%2.2d_%s.c ] ; then \\\n", i, testcase_name);
+ fprintf (make_file, "\t %s ; \\\n", argv[0]);
+ fprintf (make_file, "\tfi\n");
+ }
+ fprintf (make_file, "\n");
+ fprintf (make_file, "# This is how to build all the shlibs.\n");
+ fprintf (make_file, "# Be sure to first make the require_shlibs target!\n");
+ for (i=0; i < lib_num; i++)
+ {
+ fprintf (make_file, "lib%2.2d_%s.o: lib%2.2d_%s.c\n", i, testcase_name, i, testcase_name);
+ fprintf (make_file, "\t$(CC) $(CFLAGS) +Z -o lib%2.2d_%s.o -c lib%2.2d_%s.c\n", i, testcase_name, i, testcase_name);
+ fprintf (make_file, "lib%2.2d-%s.sl: lib%2.2d-%s.o\n", i, testcase_name, i, testcase_name);
+ fprintf (make_file, "\t$(LD) $(LDFLAGS) -b -o lib%2.2d-%s.sl lib%2.2d-%s.o\n", i, testcase_name, i, testcase_name);
+ }
+ fprintf (make_file, "\n");
+fprintf (make_file, "# For convenience, here's names for all pieces of all shlibs.\n");
+ fprintf (make_file, "SHLIB_SOURCES = \\\n");
+ for (i=0; i < lib_num-1; i++)
+ fprintf (make_file, "\tlib%2.2d-%s.c \\\n", i, testcase_name);
+ fprintf (make_file, "\tlib%2.2d-%s.c\n", lib_num-1, testcase_name);
+ fprintf (make_file, "SHLIB_OBJECTS = $(SHLIB_SOURCES:.c=.o)\n");
+ fprintf (make_file, "SHLIBS = $(SHLIB_SOURCES:.c=.sl)\n");
+ fprintf (make_file, "SHLIB_NAMES = $(SHLIB_SOURCES:.c=)\n");
+ fprintf (make_file, "EXECUTABLES = $(SHLIBS) %s %s\n", argv[0], testcase_name);
+ fprintf (make_file, "OBJECT_FILES = $(SHLIB_OBJECTS) %s.o %s.o\n", argv[0], testcase_name);
+ fprintf (make_file, "\n");
+ fprintf (make_file, "shlib_objects: $(SHLIB_OBJECTS)\n");
+ fprintf (make_file, "shlibs: $(SHLIBS)\n");
+ fprintf (make_file, "\n");
+ fprintf (make_file, "# This is how to build the debuggable testcase that uses the shlibs.\n");
+ fprintf (make_file, "%s.o: %s.c\n", testcase_name, testcase_name);
+ fprintf (make_file, "\t$(CC) $(CFLAGS) -o %s.o -c %s.c\n", testcase_name, testcase_name);
+ fprintf (make_file, "%s: shlibs %s.o\n", testcase_name, testcase_name);
+ fprintf (make_file, "\t$(LD) $(LDFLAGS) -o %s -lc -L. ", testcase_name);
+ fprintf (make_file, "-c %s /opt/langtools/lib/end.o /lib/crt0.o %s.o\n", linkfile_name, testcase_name);
+ fprintf (make_file, "\n");
+ fprintf (make_file, "# Yeah, but you should first make the require_shlibs target!\n");
+ fprintf (make_file, "all: %s %s\n", testcase_name, argv[0]);
+ fprintf (make_file, "\n");
+ fprintf (make_file, "# To remove everything built via this makefile...\n");
+ fprintf (make_file, "clean:\n");
+ /* Do this carefully, to avoid hitting silly HP-UX ARG_MAX limits... */
+ fprintf (make_file, "\trm -f lib0*-%s.*\n", testcase_name);
+ fprintf (make_file, "\trm -f lib1*-%s.*\n", testcase_name);
+ fprintf (make_file, "\trm -f lib2*-%s.*\n", testcase_name);
+ fprintf (make_file, "\trm -f lib3*-%s.*\n", testcase_name);
+ fprintf (make_file, "\trm -f lib4*-%s.*\n", testcase_name);
+ fprintf (make_file, "\trm -f lib5*-%s.*\n", testcase_name);
+ fprintf (make_file, "\trm -f lib6*-%s.*\n", testcase_name);
+ fprintf (make_file, "\trm -f lib7*-%s.*\n", testcase_name);
+ fprintf (make_file, "\trm -f lib8*-%s.*\n", testcase_name);
+ fprintf (make_file, "\trm -f lib9*-%s.*\n", testcase_name);
+ fprintf (make_file, "\trm -f %s %s %s %s.c\n", argv[0], testcase_name, linkfile_name, testcase_name);
+ fprintf (make_file, "\n");
+ fclose (make_file);
+ }
+
+ /* Generate the code for the libraries.
+ */
+ for (i=0; i < lib_num; i++) {
+
+ /* Generate the names for the library.
+ */
+ sprintf (file_name, "lib%2.2d-%s.c", i, testcase_name);
+ sprintf (file_name_core, "lib%2.2d-%s", i, testcase_name);
+
+ /* Generate the source code.
+ */
+ lib_file = fopen (file_name, "w");
+ fprintf (lib_file, "/* Shared library file number %d */\n", i);
+ fprintf (lib_file, "#include <stdio.h>\n\n");
+ fprintf (lib_file, "/* The following variables largely exist to bloat this library's debug info. */\n");
+ fprintf (lib_file, "static char c_static_buf_%d [100];\n", i);
+ for (i2=0; i2<NUMBER_OF_INT_VARS; i2++)
+ fprintf (lib_file, "int i_%d_%d;\n", i, i2);
+ fprintf (lib_file, "\nint r_%d ()\n", i);
+ fprintf (lib_file, "{\n");
+ for (i2=0; i2<NUMBER_OF_INT_VARS; i2++)
+ fprintf (lib_file, " i_%d_%d = %d*%d;\n", i, i2, i2, i2);
+ fprintf (lib_file, " return 1;\n");
+ fprintf (lib_file, "}\n\n");
+ fprintf (lib_file, "/* end of generated file */\n");
+ fclose (lib_file);
+
+ /* Add a linker options line
+ */
+ fprintf (link_file, "-l%2.2d-%s\n", i, testcase_name);
+ }
+
+ /* Generate the "main" file.
+ */
+ strcpy (mainfile_name, testcase_name);
+ strcat (mainfile_name, ".c");
+ main_file = fopen (mainfile_name, "w");
+ fprintf (main_file, "/* Generated test progam with %d shared libraries. */\n\n",
+ lib_num);
+ fprintf (main_file, "#include <stdio.h>\n\n");
+
+ for (i = 0; i < lib_num; i++) {
+ fprintf (main_file, "extern int r_%d();\n", i);
+ }
+
+ fprintf (main_file, "\n");
+ fprintf (main_file, "int main()\n");
+ fprintf (main_file, "{\n");
+ fprintf (main_file, " int accum;\n");
+ fprintf (main_file, " int lib_num = %d;\n", lib_num);
+
+ for (i = 0; i < lib_num; i++) {
+ fprintf (main_file, " accum += r_%d();\n", i);
+ }
+
+ fprintf (main_file, " printf( \"Final value: %%d, should be %%d\\n\", accum, lib_num );\n\n");
+ fprintf (main_file, " return 0;\n");
+ fprintf (main_file, "}\n\n");
+ fprintf (main_file, "/* end of generated file */\n");
+ fclose (main_file);
+
+ /* Finish up the link file and the build file
+ */
+ fclose (link_file);
+}
+
+/* End of file */
diff --git a/gdb/testsuite/gdb.hp/hwwatchbus.c b/gdb/testsuite/gdb.hp/hwwatchbus.c
new file mode 100644
index 00000000000..7a02c9b4498
--- /dev/null
+++ b/gdb/testsuite/gdb.hp/hwwatchbus.c
@@ -0,0 +1,9 @@
+/* This program raises a SIGBUS signal on HP-UX when the
+ pointer "bogus_p" is dereferenced.
+ */
+int * bogus_p = (int *)3;
+
+main()
+{
+ *bogus_p = 0xdeadbeef;
+}
diff --git a/gdb/testsuite/gdb.hp/hwwatchbus.exp b/gdb/testsuite/gdb.hp/hwwatchbus.exp
new file mode 100644
index 00000000000..d4899a997e2
--- /dev/null
+++ b/gdb/testsuite/gdb.hp/hwwatchbus.exp
@@ -0,0 +1,84 @@
+# Copyright (C) 1997, 1998 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+if $tracelevel then {
+ strace $tracelevel
+ }
+
+set prms_id 0
+set bug_id 0
+
+# are we on a target board
+if ![isnative] then {
+ return
+}
+
+if { ![istarget "hppa*-*-hpux10.30"] && ![istarget "hppa*-*-hpux11.*"] } {
+ verbose "HPUX h/w watch test ignored for non-hppa or pre-HP/UX-10.30 targets."
+ return 0
+}
+
+set testfile "hwwatchbus"
+set srcfile ${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+
+# build the first test case
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+if [get_compiler_info ${binfile}] {
+ return -1
+}
+
+# Start with a fresh gdb
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+
+# We ought to be able to set a hardware watchpoint, step, and
+# get a SIGBUS signal reported.
+#
+if ![runto_main] then {
+ fail "can't run to main"
+ return 0
+}
+
+send_gdb "watch bogus_p\n"
+gdb_expect {
+ -re "Hardware watchpoint \[0-9\]*: bogus_p.*$gdb_prompt $"\
+ {pass "set h/w watchpoint"}
+ -re "$gdb_prompt $"\
+ {fail "set h/w watchpoint"}
+ timeout {fail "(timeout) set h/w watchpoint"}
+}
+
+send_gdb "step\n"
+gdb_expect {
+ -re "Program received signal SIGBUS, Bus error.* in main .*${srcfile}:8.*$gdb_prompt $"\
+ {pass "see real SIGBUS when h/w watchpoint set"}
+ -re "$gdb_prompt $"\
+ {fail "see real SIGBUS when h/w watchpoint set"}
+ timeout {fail "(timeout) see real SIGBUS when h/w watchpoint set"}
+}
+
+return 0
diff --git a/gdb/testsuite/gdb.hp/inherit-hp.exp b/gdb/testsuite/gdb.hp/inherit-hp.exp
new file mode 100644
index 00000000000..645358ec0da
--- /dev/null
+++ b/gdb/testsuite/gdb.hp/inherit-hp.exp
@@ -0,0 +1,849 @@
+# Copyright (C) 1992, 1993, 1994, 1997 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file was written by Fred Fish. (fnf@cygnus.com)
+
+set ws "\[\r\n\t \]+"
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+# Check to see if we have an executable to test. If not, then either we
+# haven't tried to compile one, or the compilation failed for some reason.
+# In either case, just notify the user and skip the tests in this file.
+# Note - create separate "inherit" executable from misc.cc
+
+set testfile "inherit-hp"
+set srcfile misc-hp.cc
+set binfile ${objdir}/${subdir}/${testfile}
+
+if [get_compiler_info ${binfile} "c++"] {
+ return -1;
+}
+
+
+if {[skip_hp_tests $gcc_compiled]} then { continue }
+
+
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug c++}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+#
+# Single inheritance, print individual members.
+#
+
+proc test_print_si_members {} {
+ # Print all members of g_A using fully qualified form.
+
+ gdb_test "print g_A.A::a" ".* = 1" "print g_A.A::a"
+
+ gdb_test "print g_A.A::x" ".* = 2" "print g_A.A::x"
+
+ # Print members of g_A using nonambiguous compact form.
+
+ gdb_test "print g_A.a" ".* = 1" "print g_A.a"
+
+ gdb_test "print g_A.x" ".* = 2" "print g_A.x"
+
+ # Print all members of g_B using fully qualified form.
+
+ gdb_test "print g_B.A::a" ".* = 3" "print g_B.A::a"
+
+ gdb_test "print g_B.A::x" ".* = 4" "print g_B.A::x"
+
+ gdb_test "print g_B.B::b" ".* = 5" "print g_B.B::b"
+
+ gdb_test "print g_B.B::x" ".* = 6" "print g_B.B::x"
+
+ # Print members of g_B using nonambiguous compact form.
+
+ setup_xfail_format "DWARF 1"
+ gdb_test "print g_B.a" ".* = 3" "print g_B.a"
+
+ gdb_test "print g_B.b" ".* = 5" "print g_B.b"
+
+ gdb_test "print g_B.x" ".* = 6" "print g_B.x"
+
+ # Print all members of g_C using fully qualified form.
+
+ gdb_test "print g_C.A::a" ".* = 7" "print g_C.A::a"
+
+ gdb_test "print g_C.A::x" ".* = 8" "print g_C.A::x"
+
+ gdb_test "print g_C.C::c" ".* = 9" "print g_C.C::c"
+
+ gdb_test "print g_C.C::x" ".* = 10" "print g_C.C::x"
+
+ # Print members of g_C using nonambiguous compact form.
+
+ setup_xfail_format "DWARF 1"
+ gdb_test "print g_C.a" ".* = 7" "print g_C.a"
+
+ gdb_test "print g_C.c" ".* = 9" "print g_C.c"
+
+ gdb_test "print g_C.x" ".* = 10" "print g_C.x"
+}
+
+#
+# Single inheritance, print type definitions.
+#
+
+proc test_ptype_si {} {
+ global gdb_prompt
+ global ws
+
+ # Print class A as a type.
+
+ send_gdb "ptype A\n"
+ gdb_expect {
+ -re "type = class A \{\r\n.*\[ \]*int a;\r\n\[ \]*int x;\r\n.*\[ \]*\}\r\n$gdb_prompt $" {
+ pass "ptype A (FIXME)"
+ }
+ -re "type = struct A \{\r\n\[ \]*int a;\r\n\[ \]*int x;\r\n\[ \]*\}\r\n$gdb_prompt $" {
+ setup_xfail "*-*-*"
+ fail "ptype A (FIXME)"
+ }
+ -re ".*$gdb_prompt $" { fail "ptype A" }
+ timeout { fail "ptype A (timeout)" ; return }
+ }
+
+ # Print class A as an explicit class.
+
+ send_gdb "ptype class A\n"
+ gdb_expect {
+ -re "type = class A \{\r\n.*\[ \]*int a;\r\n\[ \]*int x;\r\n.*\[ \]*\}\r\n$gdb_prompt $" {
+ pass "ptype class A (FIXME)"
+ }
+ -re "type = struct A \{\r\n\[ \]*int a;\r\n\[ \]*int x;\r\n\[ \]*\}\r\n$gdb_prompt $" {
+ setup_xfail "*-*-*"
+ fail "ptype class A (FIXME)"
+ }
+ -re ".*$gdb_prompt $" { fail "ptype class A" }
+ timeout { fail "ptype class A (timeout)" ; return }
+ }
+
+ # Print type of an object of type A.
+
+ send_gdb "ptype g_A\n"
+ gdb_expect {
+ -re "type = class A \{\r\n.*\[ \]*int a;\r\n\[ \]*int x;\r\n.*\[ \]*\}\r\n$gdb_prompt $" {
+ pass "ptype g_A (FIXME)"
+ }
+ -re "type = struct A \{\r\n\[ \]*int a;\r\n\[ \]*int x;\r\n\[ \]*\}\r\n$gdb_prompt $" {
+ setup_xfail "*-*-*"
+ fail "ptype g_A (FIXME)"
+ }
+ -re ".*$gdb_prompt $" { fail "ptype g_A" }
+ timeout { fail "ptype g_A (timeout)" ; return }
+ }
+
+ # Print class B as a type.
+
+ setup_xfail_format "DWARF 1"
+ gdb_test "ptype B" "type = class B : public A \{\r\n\[ \]*public:\r\n\[ \]*int b;\r\n\[ \]*int x;\r\n.*\}" "ptype B"
+
+ # Print class B as an explicit class.
+
+ setup_xfail_format "DWARF 1"
+ gdb_test "ptype class B" "type = class B : public A \{\r\n\[ \]*public:\r\n\[ \]*int b;\r\n\[ \]*int x;\r\n.*\}" "ptype class B"
+
+ # Print type of an object of type B.
+
+ setup_xfail_format "DWARF 1"
+ gdb_test "ptype g_B" "type = class B : public A \{\r\n\[ \]*public:\r\n\[ \]*int b;\r\n\[ \]*int x;\r\n.*\}" "ptype g_B"
+
+ # Print class C as a type.
+
+ setup_xfail_format "DWARF 1"
+ gdb_test "ptype C" "type = class C : public A \{\r\n\[ \]*public:\r\n\[ \]*int c;\r\n\[ \]*int x;\r\n.*\}" "ptype C"
+
+ # Print class C as an explicit class.
+
+ setup_xfail_format "DWARF 1"
+ gdb_test "ptype class C" "type = class C : public A \{\r\n\[ \]*public:\r\n\[ \]*int c;\r\n\[ \]*int x;\r\n.*\}" "ptype class C"
+
+ # Print type of an object of type g_C.
+
+ setup_xfail_format "DWARF 1"
+ gdb_test "ptype g_C" "type = class C : public A \{\r\n\[ \]*public:\r\n\[ \]*int c;\r\n\[ \]*int x;\r\n.*\}" "ptype g_C"
+
+ # gcc cygnus-2.3.3 (Q1) has this bug, but it was fixed as of
+ # cygnus-2.3.3-930417. PR 2819.
+ send_gdb "ptype tagless_struct\n"
+ gdb_expect {
+ -re "type = class \{${ws}public:${ws}int one;${ws}int two;${ws}tagless_struct & operator=\\(tagless_struct &\\);${ws}\\\$_1 \\(tagless_struct &\\);${ws}\\\$_1 \\(\\);${ws}\}\r\n$gdb_prompt $" {
+ pass "ptype tagless struct"
+ }
+ -re "type = (struct|class).*\{.*int one;.*int two;.*\}\r\n$gdb_prompt $" {
+ pass "ptype tagless struct (obsolete gcc or gdb)"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "ptype tagless struct"
+ }
+ timeout {
+ fail "ptype tagless struct (timeout)"
+ }
+ }
+
+ send_gdb "ptype v_tagless\n"
+ gdb_expect {
+ -re "type = class \{${ws}public:${ws}int one;${ws}int two;${ws}tagless_struct & operator=\\(tagless_struct &\\);${ws}\\\$_1 \\(tagless_struct &\\);${ws}\\\$_1 \\(\\);${ws}\}\r\n$gdb_prompt $" {
+ pass "ptype variable of type tagless struct"
+ }
+ -re "type = (struct|class).*\{.*int one;.*int two;.*\}\r\n$gdb_prompt $" {
+ pass "ptype variable of type tagless struct (obsolete gcc or gdb)"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "ptype variable of type tagless struct"
+ }
+ timeout {
+ fail "ptype variable of type tagless struct (timeout)"
+ }
+ }
+}
+
+#
+# Single inheritance, print complete classes.
+#
+
+proc test_print_si_classes {} {
+ # Print all members of g_A.
+
+ gdb_test "print g_A" ".* = \{a = 1, x = 2\}" "print g_A"
+
+ # Print all members of g_B.
+
+ setup_xfail_format "DWARF 1"
+ gdb_test "print g_B" ".* = \{\<class A\> = \{a = 3, x = 4\}, b = 5, x = 6\}" "print g_B"
+
+ # Print all members of g_C.
+
+ setup_xfail_format "DWARF 1"
+ gdb_test "print g_C" ".* = \{\<class A\> = \{a = 7, x = 8\}, c = 9, x = 10\}" "print g_C"
+}
+
+#
+# Single inheritance, print anonymous unions.
+# GDB versions prior to 4.14 entered an infinite loop when printing
+# the type of a class containing an anonymous union, and they were also
+# incapable of printing the member of an anonymous union.
+# We test the printing of the member first, and perform the other tests
+# only if the test succeeds, to avoid the infinite loop.
+#
+
+proc test_print_anon_union {} {
+ global gdb_prompt
+ global ws
+
+ setup_xfail_format "DWARF 1"
+ gdb_test "print g_anon_union.a" ".* = 2" "print anonymous union member"
+ setup_xfail_format "DWARF 1"
+ send_gdb "print g_anon_union\n"
+ gdb_expect {
+ -re ".* = \{one = 1, \{a = 2, b = 2\}\}\r\n$gdb_prompt $" {
+ pass "print variable of type anonymous union"
+ }
+ -re ".* = .*\{one = 1, = \{a = 2, b = .*\}\}\r\n$gdb_prompt $" {
+ pass "print variable of type anonymous union (obsolete gcc or gdb)"
+ }
+ -re ".*\r\n$gdb_prompt $" {
+ fail "print variable of type anonymous union"
+ }
+ timeout {
+ fail "print variableof type anonymous union (timeout)"
+ }
+ }
+ setup_xfail_format "DWARF 1"
+ send_gdb "ptype g_anon_union\n"
+ gdb_expect {
+ -re "type = class class_with_anon_union \{${ws}public:${ws}int one;${ws}union \{${ws}public:${ws}int a;${ws}long int b;${ws}union \{\.\.\.\} & operator=\\(union \{\.\.\.\} &\\);${ws}\\\$_0 \\(union \{\.\.\.\} &\\);${ws}\\\$_0 \\(\\);${ws}\};${ws}class_with_anon_union & operator=\\(class_with_anon_union const &\\);${ws}class_with_anon_union\\(class_with_anon_union const &\\);${ws}class_with_anon_union\\(void\\);${ws}\}\r\n$gdb_prompt $" {
+ pass "print type of anonymous union"
+ }
+ -re "type = (struct|class).*\{.*int one;.*union \{.*int a;.*(long|long int|int) b;.*\};.*\}\r\n$gdb_prompt $" {
+ pass "print type of anonymous union (obsolete gcc or gdb)"
+ }
+ -re ".*\r\n$gdb_prompt $" {
+ fail "print type of anonymous union"
+ }
+ timeout {
+ fail "print type of anonymous union (timeout)"
+ }
+ }
+}
+
+#
+# Multiple inheritance, print individual members.
+#
+
+proc test_print_mi_members {} {
+ global gdb_prompt
+
+ # Print all members of g_A.
+
+ gdb_test "print g_A.A::a" ".* = 1" "print g_A.A::a"
+
+ gdb_test "print g_A.A::x" ".* = 2" "print g_A.A::x"
+
+ # Print all members of g_B.
+
+ gdb_test "print g_B.A::a" ".* = 3" "print g_B.A::a"
+
+ gdb_test "print g_B.A::x" ".* = 4" "print g_B.A::x"
+
+ gdb_test "print g_B.B::b" ".* = 5" "print g_B.B::b"
+
+ gdb_test "print g_B.B::x" ".* = 6" "print g_B.B::x"
+
+ # Print all members of g_C.
+
+ gdb_test "print g_C.A::a" ".* = 7" "print g_C.A::a"
+
+ gdb_test "print g_C.A::x" ".* = 8" "print g_C.A::x"
+
+ gdb_test "print g_C.C::c" ".* = 9" "print g_C.C::c"
+
+ gdb_test "print g_C.C::x" ".* = 10" "print g_C.C::x"
+
+ # Print all members of g_D.
+
+ # The following is ambiguous, and gdb should detect this.
+ # For now, accept gdb's behavior as an expected failure if it
+ # simply prints either member correctly.
+
+ # setup_xfail "*-*-*"
+ send_gdb "print g_D.A::a\n"
+ gdb_expect {
+ -re "warning: A ambiguous; using D::B::A. Use a cast to disambiguate.\r\n\\$\[0-9\]* = 11\r\n$gdb_prompt $" {
+ pass "print g_D.A::a"
+ }
+ -re ".* = 15\r\n$gdb_prompt $" {
+ fail "print g_D.A::a (did GDB's algorithm change?)"
+ }
+ -re ".* = 11\r\n$gdb_prompt $" {
+ fail "print g_D.A::a (ambiguity not reported)"
+ }
+ -re ".*$gdb_prompt $" { fail "print g_D.A::a" }
+ timeout { fail "print g_D.A::a (timeout)" ; return }
+ }
+
+ # The following is ambiguous, and gdb should detect this.
+ # For now, accept gdb's behavior as an expected failure if it
+ # simply prints either member correctly.
+
+ # setup_xfail "*-*-*"
+ send_gdb "print g_D.A::x\n"
+ gdb_expect {
+ -re "warning: A ambiguous; using D::B::A. Use a cast to disambiguate.\r\n\\$\[0-9\]* = 12\r\n$gdb_prompt $" {
+ pass "print g_D.A::x"
+ }
+ -re ".* = 16\r\n$gdb_prompt $" {
+ fail "print g_D.A::x (did GDB's algorithm change?)"
+ }
+ -re ".* = 12\r\n$gdb_prompt $" {
+ fail "print g_D.A::x (ambiguity not reported)"
+ }
+ -re ".*$gdb_prompt $" { fail "print g_D.A::x" }
+ timeout { fail "print g_D.A::x (timeout)" ; return }
+ }
+
+ gdb_test "print g_D.B::b" ".* = 13" "print g_D.B::b"
+
+ gdb_test "print g_D.B::x" ".* = 14" "print g_D.B::x"
+
+ setup_xfail_format "DWARF 1"
+ gdb_test "print g_D.C::c" ".* = 17" "print g_D.C::c"
+
+ setup_xfail_format "DWARF 1"
+ gdb_test "print g_D.C::x" ".* = 18" "print g_D.C::x"
+
+ gdb_test "print g_D.D::d" ".* = 19" "print g_D.D::d"
+
+ gdb_test "print g_D.D::x" ".* = 20" "print g_D.D::x"
+
+ # Print all members of g_E.
+
+ # The following is ambiguous, and gdb should detect this.
+ # For now, accept gdb's behavior as an expected failure if it
+ # simply prints either member correctly.
+
+ #setup_xfail "*-*-*"
+ send_gdb "print g_E.A::a\n"
+ gdb_expect {
+ -re "warning: A ambiguous; using E::D::B::A. Use a cast to disambiguate.\r\n\\$\[0-9\]* = 21\r\n$gdb_prompt $" {
+ pass "print g_E.A::a"
+ }
+ -re ".* = 25\r\n$gdb_prompt $" {
+ fail "print g_E.A::a (did GDB's algorithm change?)"
+ }
+ -re ".* = 21\r\n$gdb_prompt $" {
+ fail "print g_E.A::a (ambiguity not reported)"
+ }
+ -re ".*$gdb_prompt $" { fail "print g_E.A::a" }
+ timeout { fail "print g_E.A::a (timeout)" ; return }
+ }
+
+ # The following is ambiguous, and gdb should detect this.
+ # For now, accept gdb's behavior as an expected failure if it
+ # simply prints either member correctly.
+
+ # setup_xfail "*-*-*"
+ send_gdb "print g_E.A::x\n"
+ gdb_expect {
+ -re "warning: A ambiguous; using E::D::B::A. Use a cast to disambiguate.\r\n\\$\[0-9\]* = 22\r\n$gdb_prompt $" {
+ pass "print g_E.A::x"
+ }
+ -re ".* = 26\r\n$gdb_prompt $" {
+ fail "print g_E.A::x (did GDB's algorithm change?)"
+ }
+ -re ".* = 22\r\n$gdb_prompt $" {
+ fail "print g_E.A::x (ambiguity not reported)"
+ }
+ -re ".*$gdb_prompt $" { fail "print g_E.A::x" }
+ timeout { fail "print g_E.A::x (timeout)" ; return }
+ }
+
+ gdb_test "print g_E.B::b" ".* = 23" "print g_E.B::b"
+
+ gdb_test "print g_E.B::x" ".* = 24" "print g_E.B::x"
+
+ setup_xfail_format "DWARF 1"
+ gdb_test "print g_E.C::c" ".* = 27" "print g_E.C::c"
+
+ setup_xfail_format "DWARF 1"
+ gdb_test "print g_E.C::x" ".* = 28" "print g_E.C::x"
+
+ gdb_test "print g_E.D::d" ".* = 29" "print g_E.D::d"
+
+ gdb_test "print g_E.D::x" ".* = 30" "print g_E.D::x"
+
+ gdb_test "print g_E.E::e" ".* = 31" "print g_E.E::e"
+
+ gdb_test "print g_E.E::x" ".* = 32" "print g_E.E::x"
+}
+
+#
+# Multiple inheritance, print type definitions.
+#
+
+proc test_ptype_mi {} {
+ setup_xfail_format "DWARF 1"
+ gdb_test "ptype D" "type = class D : public B, public C \{\r\n\[ \]*public:\r\n\[ \]*int d;\r\n\[ \]*int x;\r\n.*\}" "ptype D"
+
+ setup_xfail_format "DWARF 1"
+ gdb_test "ptype class D" "type = class D : public B, public C \{\r\n\[ \]*public:\r\n\[ \]*int d;\r\n\[ \]*int x;\r\n.*\}" "ptype class D"
+
+ setup_xfail_format "DWARF 1"
+ gdb_test "ptype g_D" "type = class D : public B, public C \{\r\n\[ \]*public:\r\n\[ \]*int d;\r\n\[ \]*int x;\r\n.*\}" "ptype g_D"
+
+ setup_xfail_format "DWARF 1"
+ gdb_test "ptype E" "type = class E : public D \{\r\n\[ \]*public:\r\n\[ \]*int e;\r\n\[ \]*int x;\r\n.*\}" "ptype E"
+
+ setup_xfail_format "DWARF 1"
+ gdb_test "ptype class E" "type = class E : public D \{\r\n\[ \]*public:\r\n\[ \]*int e;\r\n\[ \]*int x;\r\n.*\}" "ptype class E"
+
+ setup_xfail_format "DWARF 1"
+ gdb_test "ptype g_E" "type = class E : public D \{\r\n\[ \]*public:\r\n\[ \]*int e;\r\n\[ \]*int x;\r\n.*\}" "ptype g_E"
+}
+
+#
+# Multiple inheritance, print complete classes.
+#
+
+proc test_print_mi_classes {} {
+ # Print all members of g_D.
+
+ setup_xfail_format "DWARF 1"
+ gdb_test "print g_D" ".* = \{\<class B\> = \{\<class A\> = \{a = 11, x = 12\}, b = 13, x = 14\}, \<class C\> = \{\<class A\> = \{a = 15, x = 16\}, c = 17, x = 18\}, d = 19, x = 20\}" "print g_D"
+
+ # Print all members of g_E.
+
+ setup_xfail_format "DWARF 1"
+ gdb_test "print g_E" ".* = \{\<class D\> = \{\<class B\> = \{\<class A\> = \{a = 21, x = 22\}, b = 23, x = 24\}, \<class C\> = \{\<class A\> = \{a = 25, x = 26\}, c = 27, x = 28\}, d = 29, x = 30\}, e = 31, x = 32\}" "print g_E"
+}
+
+#
+# Single virtual inheritance, print individual members.
+#
+
+proc test_print_svi_members {} {
+ global gdb_prompt
+ global decimal
+
+ # Print all members of g_vA.
+
+ gdb_test "print g_vA.vA::va" ".* = 1" "print g_vA.vA::va"
+
+ gdb_test "print g_vA.vA::vx" ".* = 2" "print g_vA.vA::vx"
+
+ # Print members of g_vA using compact form.
+
+ gdb_test "print g_vA.va" ".* = 1" "print g_vA.va"
+
+ gdb_test "print g_vA.vx" ".* = 2" "print g_vA.vx"
+
+ # Print all members of g_vB.
+
+ setup_xfail_format "DWARF 1"
+ send_gdb "print g_vB.vA::va\n"
+ gdb_expect {
+ -re ".* = 3\r\n$gdb_prompt $" { pass "print g_vB.vA::va" }
+ -re ".*virtual baseclass botch.*$gdb_prompt $" {
+ # Does not happen with gcc cygnus-2.4.5-930828
+ fail "print g_vB.vA::va (known bug with gcc cygnus-2.4.5-930417)"
+ # Many of the rest of these tests have the same problem.
+ return 0
+ }
+ -re ".*$gdb_prompt $" { fail "print g_vB.vA::va" }
+ timeout { fail "print g_vB.vA::va (timeout)" ; return }
+ }
+
+ setup_xfail_format "DWARF 1"
+ gdb_test "print g_vB.vA::vx" ".* = 4" "print g_vB.vA::vx"
+
+ gdb_test "print g_vB.vB::vb" ".* = 5" "print g_vB.vB::vb"
+
+ gdb_test "print g_vB.vB::vx" ".* = 6" "print g_vB.vB::vx"
+
+ # Print members of g_vB using compact form.
+
+ setup_xfail_format "DWARF 1"
+ gdb_test "print g_vB.va" ".* = 3" "print g_vB.va"
+
+ gdb_test "print g_vB.vb" ".* = 5" "print g_vB.vb"
+
+ gdb_test "print g_vB.vx" ".* = 6" "print g_vB.vx"
+
+ # Print all members of g_vC.
+
+ setup_xfail_format "DWARF 1"
+ gdb_test "print g_vC.vA::va" ".* = 7" "print g_vC.vA::va"
+
+ setup_xfail_format "DWARF 1"
+ gdb_test "print g_vC.vA::vx" ".* = 8" "print g_vC.vA::vx"
+
+ gdb_test "print g_vC.vC::vc" ".* = 9" "print g_vC.vC::vc"
+
+ gdb_test "print g_vC.vC::vx" ".* = 10" "print g_vC.vC::vx"
+
+ # Print members of g_vC using compact form.
+
+ setup_xfail_format "DWARF 1"
+ gdb_test "print g_vC.va" ".* = 7" "print g_vC.va"
+
+ gdb_test "print g_vC.vc" ".* = 9" "print g_vC.vc"
+
+ gdb_test "print g_vC.vx" ".* = 10" "print g_vC.vx"
+}
+
+#
+# Single virtual inheritance, print type definitions.
+#
+
+proc test_ptype_vi {} {
+ global gdb_prompt
+
+ # This class does not use any C++-specific features, so it's fine for
+ # it to print as "struct".
+ send_gdb "ptype vA\n"
+ gdb_expect {
+ -re "type = class vA \{\[\r\n\]+\[ \]*public:\[\r\n\]+\[ \]*int va;\[\r\n\]+\[ \]*int vx;\[\r\n\]+.*\}\[\r\n\]+$gdb_prompt $" {
+ pass "ptype vA"
+ }
+ -re "type = struct vA \{\[\r\n\]+\[ \]*int va;\[\r\n\]+\[ \]*int vx;\[\r\n\]+\}\[\r\n\]+$gdb_prompt $" {
+ pass "ptype vA"
+ }
+ -re ".*$gdb_prompt $" { fail "ptype vA" }
+ timeout { fail "ptype vA (timeout)" ; return }
+ }
+
+ # This class does not use any C++-specific features, so it's fine for
+ # it to print as "struct".
+ send_gdb "ptype class vA\n"
+ gdb_expect {
+ -re "type = class vA \{\[\r\n\]+\[ \]*public:\[\r\n\]+\[ \]*int va;\[\r\n\]+\[ \]*int vx;\[\r\n\]+.*\}\[\r\n\]+$gdb_prompt $" {
+ pass "ptype class vA"
+ }
+ -re "type = struct vA \{\[\r\n\]+\[ \]*int va;\[\r\n\]+\[ \]*int vx;\[\r\n\]+\}\[\r\n\]+$gdb_prompt $" {
+ pass "ptype class vA"
+ }
+ -re ".*$gdb_prompt $" { fail "ptype class vA" }
+ timeout { fail "ptype class vA (timeout)" ; return }
+ }
+
+ # This class does not use any C++-specific features, so it's fine for
+ # it to print as "struct".
+ send_gdb "ptype g_vA\n"
+ gdb_expect {
+ -re "type = class vA \{\[\r\n\]+\[ \]*public:\[\r\n\]+\[ \]*int va;\[\r\n\]+\[ \]*int vx;\[\r\n\]+.*\}\[\r\n\]+$gdb_prompt $" {
+ pass "ptype g_vA"
+ }
+ -re "type = struct vA \{\[\r\n\]+\[ \]*int va;\[\r\n\]+\[ \]*int vx;\[\r\n\]+\}\[\r\n\]+$gdb_prompt $" {
+ pass "ptype g_vA"
+ }
+ -re ".*$gdb_prompt $" { fail "ptype g_vA" }
+ timeout { fail "ptype g_vA (timeout)" ; return }
+ }
+
+ setup_xfail_format "DWARF 1"
+ gdb_test "ptype vB" "ptype vB\[\r\n\]+type = class vB : public virtual vA \{\[\r\n\]+ public:\r\n\[ \]+int vb;\r\n\[ \]+int vx;\r\n.*\}" "ptype vB (aCC)"
+
+ setup_xfail_format "DWARF 1"
+ gdb_test "ptype class vB" "type = class vB : public virtual vA \{\r\n\[ \]*public:\r\n\[ \]*int vb;\r\n\[ \]*int vx;\r\n.*\}" "ptype class vB (aCC)"
+
+ setup_xfail_format "DWARF 1"
+ gdb_test "ptype g_vB" "type = class vB : public virtual vA \{\r\n\[ \]*public:\r\n\[ \]*int vb;\r\n\[ \]*int vx;\r\n.*\}" "ptype g_vB (aCC)"
+
+ setup_xfail_format "DWARF 1"
+ gdb_test "ptype vC" "type = class vC : public virtual vA \{\r\n\[ \]*public:\r\n\[ \]*int vc;\r\n\[ \]*int vx;\r\n.*\}" "ptype vC (aCC)"
+
+ setup_xfail_format "DWARF 1"
+ gdb_test "ptype class vC" "type = class vC : public virtual vA \{\r\n\[ \]*public:\r\n\[ \]*int vc;\r\n\[ \]*int vx;\r\n.*\}" "ptype class vC (aCC)"
+
+ setup_xfail_format "DWARF 1"
+ gdb_test "ptype g_vC" "type = class vC : public virtual vA \{\r\n\[ \]*public:\r\n\[ \]*int vc;\r\n\[ \]*int vx;\r\n.*\}" "ptype g_vC (aCC)"
+}
+
+#
+# Single virtual inheritance, print complete classes.
+#
+
+proc test_print_svi_classes {} {
+ global gdb_prompt
+ global hex
+ global decimal
+
+ # Print all members of g_vA.
+
+ gdb_test "print g_vA" ".* = \{va = 1, vx = 2\}" "print g_vA"
+
+ # Print all members of g_vB.
+
+ setup_xfail_format "DWARF 1"
+ send_gdb "print g_vB\n"
+ gdb_expect {
+ -re ".* = \{\<class vA\> = \{va = 3, vx = 4\}, vb = 5, vx = 6, Virtual table at $hex\}\r\n$gdb_prompt $" {
+ pass "print g_vB"
+ }
+ -re ".*invalid address 0x0.*$gdb_prompt $" {
+ # Does not happen with gcc cygnus-2.4.5-930828
+ fail "print g_vB (known bug with gcc cygnus-2.4.5-930417)"
+ # Many of the rest of these tests have the same problem.
+ return 0
+ }
+ -re ".*$gdb_prompt $" { fail "print g_vB" }
+ timeout { fail "print g_vB (timeout)" ; return }
+ }
+
+ # Print all members of g_vC.
+
+ setup_xfail_format "DWARF 1"
+ gdb_test "print g_vC" ".* = \{\<class vA\> = \{va = 7, vx = 8\}, vc = 9, vx = 10, Virtual table at $hex\}" "print g_vC"
+}
+
+#
+# Multiple virtual inheritance, print individual members.
+#
+
+proc test_print_mvi_members {} {
+ global gdb_prompt
+ global decimal
+
+ # Print all members of g_vD.
+
+ setup_xfail_format "DWARF 1"
+ send_gdb "print g_vD.vA::va\n"
+ gdb_expect {
+ -re ".* = 19\r\n$gdb_prompt $" { pass "print g_vD.vA::va" }
+ -re ".*virtual baseclass botch.*$gdb_prompt $" {
+ # Does not happen with gcc cygnus-2.4.5-930828
+ fail "print g_vD.vA::va (known bug with gcc cygnus-2.4.5-930417)"
+ # Many of the rest of these tests have the same problem.
+ return 0
+ }
+ -re ".*$gdb_prompt $" { fail "print g_vD.vA::va" }
+ timeout { fail "print g_vD.vA::va (timeout)" ; return }
+ }
+
+ setup_xfail_format "DWARF 1"
+ gdb_test "print g_vD.vA::vx" ".* = 20" "print g_vD.vA::vx"
+
+ setup_xfail_format "DWARF 1"
+ gdb_test "print g_vD.vB::vb" ".* = 21" "print g_vD.vB::vb"
+
+ setup_xfail_format "DWARF 1"
+ gdb_test "print g_vD.vB::vx" ".* = 22" "print g_vD.vB::vx"
+
+ setup_xfail_format "DWARF 1"
+ gdb_test "print g_vD.vC::vc" ".* = 23" "print g_vD.vC::vc"
+
+ setup_xfail_format "DWARF 1"
+ gdb_test "print g_vD.vC::vx" ".* = 24" "print g_vD.vC::vx"
+
+ gdb_test "print g_vD.vD::vd" ".* = 25" "print g_vD.vD::vd"
+
+ gdb_test "print g_vD.vD::vx" ".* = 26" "print g_vD.vD::vx"
+
+ # Print all members of g_vE.
+
+ setup_xfail_format "DWARF 1"
+ gdb_test "print g_vE.vA::va" ".* = 0" "print g_vE.vA::va"
+
+ setup_xfail_format "DWARF 1"
+ gdb_test "print g_vE.vA::vx" ".* = 0" "print g_vE.vA::vx"
+
+ setup_xfail_format "DWARF 1"
+ gdb_test "print g_vE.vB::vb" ".* = 0" "print g_vE.vB::vb"
+
+ setup_xfail_format "DWARF 1"
+ gdb_test "print g_vE.vB::vx" ".* = 0" "print g_vE.vB::vx"
+
+ setup_xfail_format "DWARF 1"
+ gdb_test "print g_vE.vC::vc" ".* = 0" "print g_vE.vC::vc"
+
+ setup_xfail_format "DWARF 1"
+ gdb_test "print g_vE.vC::vx" ".* = 0" "print g_vE.vC::vx"
+
+ setup_xfail_format "DWARF 1"
+ gdb_test "print g_vE.vD::vd" ".* = 0" "print g_vE.vD::vd"
+
+ gdb_test "print g_vE.vD::vx" ".* = 0" "print g_vE.vD::vx"
+
+ gdb_test "print g_vE.vE::ve" ".* = 27" "print g_vE.vE::ve"
+
+ gdb_test "print g_vE.vE::vx" ".* = 28" "print g_vE.vE::vx"
+}
+
+#
+# Multiple virtual inheritance, print type definitions.
+#
+
+proc test_ptype_mvi {} {
+ setup_xfail_format "DWARF 1"
+ gdb_test "ptype vD" "type = class vD : public virtual vB, public virtual vC \{\r\n\[ \]*public:\r\n\[ \]*int vd;\r\n\[ \]*int vx;\r\n.*\}" "ptype vD (aCC)"
+
+ setup_xfail_format "DWARF 1"
+ gdb_test "ptype class vD" "type = class vD : public virtual vB, public virtual vC \{\r\n\[ \]*public:\r\n\[ \]*int vd;\r\n\[ \]*int vx;\r\n.*\}" "ptype class vD (aCC)"
+
+ setup_xfail_format "DWARF 1"
+ gdb_test "ptype g_vD" "type = class vD : public virtual vB, public virtual vC \{\r\n\[ \]*public:\r\n\[ \]*int vd;\r\n\[ \]*int vx;\r\n.*\}" "ptype g_vD (aCC)"
+
+ setup_xfail_format "DWARF 1"
+ gdb_test "ptype vE" "type = class vE : public virtual vD \{\r\n\[ \]*public:\r\n\[ \]*int ve;\r\n\[ \]*int vx;\r\n.*\}" "ptype vE (aCC)"
+
+ setup_xfail_format "DWARF 1"
+ gdb_test "ptype class vE" "type = class vE : public virtual vD \{\r\n\[ \]*public:\r\n\[ \]*int ve;\r\n\[ \]*int vx;\r\n.*\}" "ptype class vE (aCC)"
+
+ setup_xfail_format "DWARF 1"
+ gdb_test "ptype g_vE" "type = class vE : public virtual vD \{\r\n\[ \]*public:\r\n\[ \]*int ve;\r\n\[ \]*int vx;\r\n.*\}" "ptype g_vE (aCC)"
+}
+
+#
+# Multiple virtual inheritance, print complete classes.
+#
+
+proc test_print_mvi_classes {} {
+ global gdb_prompt
+ global hex
+ global decimal
+
+ # Print all members of g_vD.
+
+ setup_xfail_format "DWARF 1"
+ send_gdb "print g_vD\n"
+ gdb_expect {
+ -re ".* = \{\<class vB\> = \{\<class vA\> = \{va = 19, vx = 20\}, vb = 21, vx = 22, Virtual table at $hex\}, \<class vC\> = \{vc = 23, vx = 24, Virtual table at $hex\}, vd = 25, vx = 26, Virtual table at $hex\}\r\n$gdb_prompt $" {
+ pass "print g_vD"
+ }
+ -re ".*invalid address 0x0.*$gdb_prompt $" {
+ # Does not happen with gcc cygnus-2.4.5-930828
+ fail "print g_vD (known bug with gcc cygnus-2.4.5-930417)"
+ # Many of the rest of these tests have the same problem.
+ return 0
+ }
+ -re ".*$gdb_prompt $" { fail "print g_vD" }
+ timeout { fail "print g_vD (timeout)" ; return }
+ }
+
+ # Print all members of g_vE.
+
+ setup_xfail_format "DWARF 1"
+ gdb_test "print g_vE" ".* = \{\<class vD\> = \{\<class vB\> = \{\<class vA\> = \{va = 0, vx = 0\}, vb = 0, vx = 0, Virtual table at $hex\}, \<class vC\> = \{vc = 0, vx = 0, Virtual table at $hex\}, vd = 0, vx = 0, Virtual table at $hex\}, ve = 27, vx = 28, Virtual table at $hex\}" "print g_vE"
+}
+
+proc do_tests {} {
+ global prms_id
+ global bug_id
+ global subdir
+ global objdir
+ global srcdir
+ global binfile
+
+ set prms_id 0
+ set bug_id 0
+
+ # Start with a fresh gdb.
+
+ gdb_exit
+ gdb_start
+ gdb_reinitialize_dir $srcdir/$subdir
+ gdb_load $binfile
+
+ gdb_test "set language c++" ""
+ gdb_test "set width 0" ""
+
+ # Get the debug format for the compiled test case.
+
+ if { ![ runto_main] } {
+ gdb_suppress_tests;
+ } else {
+ get_debug_format
+ }
+
+ test_ptype_si
+ test_ptype_mi
+ test_ptype_vi
+ test_ptype_mvi
+
+ gdb_stop_suppressing_tests;
+
+ if { ![ runto 'inheritance2(void)' ] } {
+ gdb_suppress_tests;
+ }
+
+ test_print_si_members
+ test_print_si_classes
+ test_print_mi_members
+ test_print_mi_classes
+ test_print_anon_union
+
+ gdb_stop_suppressing_tests;
+
+ if { ![ runto 'inheritance4(void)' ] } {
+ gdb_suppress_tests;
+ }
+
+ test_print_svi_members
+ test_print_svi_classes
+ test_print_mvi_members
+ test_print_mvi_classes
+}
+
+do_tests
diff --git a/gdb/testsuite/gdb.hp/misc-hp.cc b/gdb/testsuite/gdb.hp/misc-hp.cc
new file mode 100644
index 00000000000..af46830601c
--- /dev/null
+++ b/gdb/testsuite/gdb.hp/misc-hp.cc
@@ -0,0 +1,514 @@
+// Test various -*- C++ -*- things.
+
+typedef struct fleep fleep;
+struct fleep { int a; } s;
+
+// ====================== simple class structures =======================
+
+struct default_public_struct {
+ // defaults to public:
+ int a;
+ int b;
+};
+
+struct explicit_public_struct {
+ public:
+ int a;
+ int b;
+};
+
+struct protected_struct {
+ protected:
+ int a;
+ int b;
+};
+
+struct private_struct {
+ private:
+ int a;
+ int b;
+};
+
+struct mixed_protection_struct {
+ public:
+ int a;
+ int b;
+ private:
+ int c;
+ int d;
+ protected:
+ int e;
+ int f;
+ public:
+ int g;
+ private:
+ int h;
+ protected:
+ int i;
+};
+
+class public_class {
+ public:
+ int a;
+ int b;
+};
+
+class protected_class {
+ protected:
+ int a;
+ int b;
+};
+
+class default_private_class {
+ // defaults to private:
+ int a;
+ int b;
+};
+
+class explicit_private_class {
+ private:
+ int a;
+ int b;
+};
+
+class mixed_protection_class {
+ public:
+ int a;
+ int b;
+ private:
+ int c;
+ int d;
+ protected:
+ int e;
+ int f;
+ public:
+ int g;
+ private:
+ int h;
+ protected:
+ int i;
+};
+
+class const_vol_method_class {
+public:
+ int a;
+ int b;
+ int foo (int &) const;
+ int bar (int &) volatile;
+ int baz (int &) const volatile;
+};
+
+int const_vol_method_class::foo (int & ir) const
+{
+ return ir + 3;
+}
+int const_vol_method_class::bar (int & ir) volatile
+{
+ return ir + 4;
+}
+int const_vol_method_class::baz (int & ir) const volatile
+{
+ return ir + 5;
+}
+
+// ========================= simple inheritance ==========================
+
+class A {
+ public:
+ int a;
+ int x;
+};
+
+A g_A;
+
+class B : public A {
+ public:
+ int b;
+ int x;
+};
+
+B g_B;
+
+class C : public A {
+ public:
+ int c;
+ int x;
+};
+
+C g_C;
+
+class D : public B, public C {
+ public:
+ int d;
+ int x;
+};
+
+D g_D;
+
+class E : public D {
+ public:
+ int e;
+ int x;
+};
+
+E g_E;
+
+class class_with_anon_union
+{
+ public:
+ int one;
+ union
+ {
+ int a;
+ long b;
+ };
+};
+
+class_with_anon_union g_anon_union;
+
+void inheritance2 (void)
+{
+}
+
+void inheritance1 (void)
+{
+ int ival;
+ int *intp;
+
+ // {A::a, A::x}
+
+ g_A.A::a = 1;
+ g_A.A::x = 2;
+
+ // {{A::a,A::x},B::b,B::x}
+
+ g_B.A::a = 3;
+ g_B.A::x = 4;
+ g_B.B::b = 5;
+ g_B.B::x = 6;
+
+ // {{A::a,A::x},C::c,C::x}
+
+ g_C.A::a = 7;
+ g_C.A::x = 8;
+ g_C.C::c = 9;
+ g_C.C::x = 10;
+
+ // {{{A::a,A::x},B::b,B::x},{{A::a,A::x},C::c,C::x},D::d,D::x}
+
+ // The following initialization code is non-portable, but allows us
+ // to initialize all members of g_D until we can fill in the missing
+ // initialization code with legal C++ code.
+
+ for (intp = (int *) &g_D, ival = 11;
+ intp < ((int *) &g_D + sizeof (g_D) / sizeof (int));
+ intp++, ival++)
+ {
+ *intp = ival;
+ }
+
+ // Overlay the nonportable initialization with legal initialization.
+
+ // ????? = 11; (g_D.A::a = 11; is ambiguous)
+ // ????? = 12; (g_D.A::x = 12; is ambiguous)
+ g_D.B::b = 13;
+ g_D.B::x = 14;
+ // ????? = 15;
+ // ????? = 16;
+ g_D.C::c = 17;
+ g_D.C::x = 18;
+ g_D.D::d = 19;
+ g_D.D::x = 20;
+
+
+ // {{{{A::a,A::x},B::b,B::x},{{A::a,A::x},C::c,C::x},D::d,D::x}},E::e,E::x}
+
+ // The following initialization code is non-portable, but allows us
+ // to initialize all members of g_D until we can fill in the missing
+ // initialization code with legal C++ code.
+
+ for (intp = (int *) &g_E, ival = 21;
+ intp < ((int *) &g_E + sizeof (g_E) / sizeof (int));
+ intp++, ival++)
+ {
+ *intp = ival;
+ }
+
+ // Overlay the nonportable initialization with legal initialization.
+
+ // ????? = 21; (g_E.A::a = 21; is ambiguous)
+ // ????? = 22; (g_E.A::x = 22; is ambiguous)
+ g_E.B::b = 23;
+ g_E.B::x = 24;
+ // ????? = 25;
+ // ????? = 26;
+ g_E.C::c = 27;
+ g_E.C::x = 28;
+ g_E.D::d = 29;
+ g_E.D::x = 30;
+ g_E.E::e = 31;
+ g_E.E::x = 32;
+
+ g_anon_union.one = 1;
+ g_anon_union.a = 2;
+
+ inheritance2 ();
+}
+
+// ======================== virtual base classes=========================
+
+class vA {
+ public:
+ int va;
+ int vx;
+};
+
+vA g_vA;
+
+class vB : public virtual vA {
+ public:
+ int vb;
+ int vx;
+};
+
+vB g_vB;
+
+class vC : public virtual vA {
+ public:
+ int vc;
+ int vx;
+};
+
+vC g_vC;
+
+class vD : public virtual vB, public virtual vC {
+ public:
+ int vd;
+ int vx;
+};
+
+vD g_vD;
+
+class vE : public virtual vD {
+ public:
+ int ve;
+ int vx;
+};
+
+vE g_vE;
+
+void inheritance4 (void)
+{
+}
+
+void inheritance3 (void)
+{
+ int ival;
+ int *intp;
+
+ // {vA::va, vA::vx}
+
+ g_vA.vA::va = 1;
+ g_vA.vA::vx = 2;
+
+ // {{vA::va, vA::vx}, vB::vb, vB::vx}
+
+ g_vB.vA::va = 3;
+ g_vB.vA::vx = 4;
+ g_vB.vB::vb = 5;
+ g_vB.vB::vx = 6;
+
+ // {{vA::va, vA::vx}, vC::vc, vC::vx}
+
+ g_vC.vA::va = 7;
+ g_vC.vA::vx = 8;
+ g_vC.vC::vc = 9;
+ g_vC.vC::vx = 10;
+
+ // {{{{vA::va, vA::vx}, vB::vb, vB::vx}, vC::vc, vC::vx}, vD::vd,vD::vx}
+
+ g_vD.vA::va = 11;
+ g_vD.vA::vx = 12;
+ g_vD.vB::vb = 13;
+ g_vD.vB::vx = 14;
+ g_vD.vC::vc = 15;
+ g_vD.vC::vx = 16;
+ g_vD.vD::vd = 17;
+ g_vD.vD::vx = 18;
+
+
+ // {{{{{vA::va,vA::vx},vB::vb,vB::vx},vC::vc,vC::vx},vD::vd,vD::vx},vE::ve,vE::vx}
+
+ g_vD.vA::va = 19;
+ g_vD.vA::vx = 20;
+ g_vD.vB::vb = 21;
+ g_vD.vB::vx = 22;
+ g_vD.vC::vc = 23;
+ g_vD.vC::vx = 24;
+ g_vD.vD::vd = 25;
+ g_vD.vD::vx = 26;
+ g_vE.vE::ve = 27;
+ g_vE.vE::vx = 28;
+
+ inheritance4 ();
+}
+
+// ======================================================================
+
+class Base1 {
+ public:
+ int x;
+ Base1(int i) { x = i; }
+};
+
+class Foo
+{
+ public:
+ int x;
+ int y;
+ static int st;
+ Foo (int i, int j) { x = i; y = j; }
+ int operator! ();
+ operator int ();
+ int times (int y);
+};
+
+class Bar : public Base1, public Foo {
+ public:
+ int z;
+ Bar (int i, int j, int k) : Base1 (10*k), Foo (i, j) { z = k; }
+};
+
+class ClassWithEnum {
+public:
+ enum PrivEnum { red, green, blue, yellow = 42 };
+ PrivEnum priv_enum;
+ int x;
+};
+
+int Foo::operator! () { return !x; }
+
+int Foo::times (int y) { return x * y; }
+
+int Foo::st = 100;
+
+Foo::operator int() { return x; }
+
+Foo foo(10, 11);
+Bar bar(20, 21, 22);
+
+class Contains_static_instance
+{
+ public:
+ int x;
+ int y;
+ Contains_static_instance (int i, int j) { x = i; y = j; }
+ static Contains_static_instance null;
+};
+
+Contains_static_instance Contains_static_instance::null(0,0);
+Contains_static_instance csi(10,20);
+
+class Contains_nested_static_instance
+{
+ public:
+ class Nested
+ {
+ public:
+ Nested(int i) : z(i) {}
+ int z;
+ static Contains_nested_static_instance xx;
+ };
+
+ Contains_nested_static_instance(int i, int j) : x(i), y(j) {}
+
+ int x;
+ int y;
+
+ static Contains_nested_static_instance null;
+ static Nested yy;
+};
+
+Contains_nested_static_instance Contains_nested_static_instance::null(0, 0);
+Contains_nested_static_instance::Nested Contains_nested_static_instance::yy(5);
+Contains_nested_static_instance
+ Contains_nested_static_instance::Nested::xx(1,2);
+Contains_nested_static_instance cnsi(30,40);
+
+typedef struct {
+ int one;
+ int two;
+} tagless_struct;
+tagless_struct v_tagless;
+
+/* Try to get the compiler to allocate a class in a register. */
+class small {
+ public:
+ int x;
+ int method ();
+};
+int small::method ()
+{
+ return x + 5;
+}
+void marker_reg1 () {}
+
+int
+register_class ()
+{
+ /* We don't call any methods for v, so gcc version cygnus-2.3.3-930220
+ might put this variable in a register. This is a lose, though, because
+ it means that GDB can't call any methods for that variable. */
+ register small v;
+
+ int i;
+
+ /* Perform a computation sufficiently complicated that optimizing compilers
+ won't optimized out the variable. If some compiler constant-folds this
+ whole loop, maybe using a parameter to this function here would help. */
+ v.x = 0;
+ for (i = 0; i < 13; ++i)
+ v.x += i;
+ --v.x; /* v.x is now 77 */
+ marker_reg1 ();
+ return v.x + 5;
+}
+
+int
+main()
+{
+#ifdef usestubs
+ set_debug_traps();
+ breakpoint();
+#endif
+ inheritance1 ();
+ inheritance3 ();
+ register_class ();
+
+ /* FIXME: pmi gets optimized out. Need to do some more computation with
+ it or something. (No one notices, because the test is xfail'd anyway,
+ but that probably won't always be true...). */
+ int Foo::* pmi = &Foo::y;
+
+ /* Make sure the AIX linker doesn't remove the variable. */
+ v_tagless.one = 5;
+
+ /* Class with enumeration inside it */
+ ClassWithEnum obj_with_enum;
+ obj_with_enum.priv_enum = ClassWithEnum::green;
+
+ return foo.*pmi;
+}
+
+/* Create an instance for some classes, otherwise they get optimized away. */
+
+default_public_struct default_public_s;
+explicit_public_struct explicit_public_s;
+protected_struct protected_s;
+private_struct private_s;
+mixed_protection_struct mixed_protection_s;
+public_class public_c;
+protected_class protected_c;
+default_private_class default_private_c;
+explicit_private_class explicit_private_c;
+mixed_protection_class mixed_protection_c;
diff --git a/gdb/testsuite/gdb.hp/more-steps.c b/gdb/testsuite/gdb.hp/more-steps.c
new file mode 100644
index 00000000000..c5ba1e26865
--- /dev/null
+++ b/gdb/testsuite/gdb.hp/more-steps.c
@@ -0,0 +1,140 @@
+/* BeginSourceFile more_steps.c
+
+ This file creates a lot of threads which then execute
+ in parallel, so that wdb can be tested on handling
+ simultaneous thread events.
+
+ To compile:
+
+ cc -Ae +DA1.0 -g -o more_steps -lpthread more_steps.c
+
+ To run:
+
+ more_threads
+*/
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <assert.h>
+#include <pthread.h>
+
+#define TRUE 1
+#define FALSE 0
+#define N_THREADS 3
+#define PHASES 3
+
+typedef enum {
+ ZERO,
+ ONE,
+ TWO,
+ THREE
+} phase_t;
+
+/* Uncomment to turn on debugging output */
+/* #define DEBUG */
+
+/* Locks.
+ */
+int lock_one; /* Main W, others R */
+int lock_two; /* ditto */
+int lock_end[ N_THREADS ]; /* Main R, others R[i] */
+int phase[ N_THREADS ];
+
+/* Routine for each thread to run.
+ */
+void *spin( vp )
+ void * vp;
+{
+ int me = (int) vp;
+ int i;
+
+ lock_end[ me ] = TRUE;
+
+ phase[ me ] = ONE;
+
+ while( lock_one );
+
+ phase[ me ] = TWO;
+
+ while( lock_two );
+
+ phase[ me ] = THREE;
+
+ lock_end[ me ] = FALSE;
+}
+
+void
+do_pass()
+{
+ int i;
+ pthread_t t[ N_THREADS ];
+ int err;
+ int done;
+
+ /* Start N_THREADS threads, then join them so
+ * that they are terminated.
+ */
+ for( i = 0; i < N_THREADS; i++ ) {
+ err = pthread_create( &t[i], NULL, spin, (void *)i );
+ if( err != 0 ) {
+ printf( "== Start/stop, error in thread %d create\n", i );
+ }
+ }
+
+ /* Do phase 1.
+ */
+ lock_one = FALSE;
+
+ /* Do phase 2.
+ */
+ lock_two = FALSE;
+
+ /* Be done.
+ */
+ done = 0;
+ while( !done ) {
+
+ /* Be optimistic.
+ */
+ done = 1;
+ for( i = 0; i < N_THREADS; i++ ) {
+ if( lock_end[i] ) {
+ /* Thread "i" is not ready yet.
+ */
+ done = 0;
+ break;
+ }
+ }
+ }
+
+ /* Finish up
+ */
+ for( i = 0; i < N_THREADS; i++ ) {
+ err = pthread_join(t[i], NULL ); /* Line 105 */
+ if( err != 0 ) { /* Line 106 */
+ printf( "== Start/stop, error in thread %d join\n", i );
+ }
+ }
+
+ i = 10; /* Line 109. Null line for setting bpts on. */
+}
+
+main( argc, argv )
+int argc;
+char **argv;
+{
+ int i;
+
+ /* Init
+ */
+ lock_one = TRUE;
+ lock_two = TRUE;
+ for( i = 0; i < N_THREADS; i++ ) {
+ lock_end[i] = TRUE;
+ phase[i] = ZERO;
+ }
+
+ do_pass();
+ return(0);
+}
diff --git a/gdb/testsuite/gdb.hp/more-steps.exp b/gdb/testsuite/gdb.hp/more-steps.exp
new file mode 100644
index 00000000000..320a0d68872
--- /dev/null
+++ b/gdb/testsuite/gdb.hp/more-steps.exp
@@ -0,0 +1,152 @@
+# more-steps.exp -- Expect script to test gdb's ability to step threaded pgms
+# Copyright (C) 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# use this to debug:
+#
+#log_user 1
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+#if { ![istarget "hppa*-*-hpux10.30"] && ![istarget "hppa*-*-hpux11.*"] } {
+# verbose "HPUX thread test ignored for non-hppa or pre-HP/UX-10.30 targets."
+# return 0
+#}
+
+set testfile more-steps
+set srcfile ${srcdir}/${subdir}/${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+
+if [get_compiler_info ${binfile}] {
+ return -1
+}
+
+# To build the executable we need to link against the thread library.
+#
+# cc -Ae -g -o more-steps -lpthread more-steps.c
+#
+#compile "${srcfile} -Ae -g -lpthread -o ${binfile}"
+
+if {$gcc_compiled == 0} {
+ set additional_flags "additional_flags=-Ae"
+} else {
+ set additional_flags ""
+}
+
+if { [gdb_compile "${srcdir}/${subdir}/${testfile}.c" "${binfile}.o" object [list debug $additional_flags]] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+if { ![istarget "hppa*-*-hpux10.30"] && ![istarget "hppa*-*-hpux11.*"] } {
+ if { [gdb_compile "${binfile}.o" "${binfile}" executable {debug "additional_flags=-lpthread"}] != ""} {
+ gdb_suppress_entire_file "Testcase link failed, so all tests in this file will automatically fail."
+ }
+} else {
+ remote_exec build "ld /usr/ccs/lib/crt0.o ${binfile}.o -lcl -lpthread -lc /opt/langtools/lib/end.o -o ${binfile}"
+}
+#remote_exec build "ld /usr/ccs/lib/crt0.o ${binfile}.o -lcl -lpthread -lc /opt/langtools/lib/end.o -o ${binfile}"
+
+
+
+# Thread stuff is _slow_; prepare for long waits.
+#
+set oldtimeout $timeout
+set timeout [expr "$timeout + 300"]
+set oldverbose $verbose
+#set verbose 40
+
+# Further, this test has some "null" lines designed
+# to consume output from gdb that was too late to be
+# matched (sequence is "gdb_test" sends; timeout and
+# on to next send; result finally comes in; mismatch).
+#
+# The null command is 'gdb_test "p \$pc" ".*" ""'
+#
+# NOTE: to pass a literal "$", "/" or "*" (etc.) to gdb_test,
+# remember that the pattern will be escaped once and
+# $-evaluated twice:
+#
+# "\\\*" matches "\*"
+# "\$" matches "$"
+#
+proc fix_timeout {} {
+ gdb_test "p \$pc" ".*" ""
+}
+
+#=========================
+#
+# Simple sanity test first.
+#
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+# First, step in the main thread.
+#
+gdb_test "b do_pass" ".*Breakpoint 1.*" ""
+gdb_test "r" ".*Breakpoint 1.*do_pass.*" ""
+
+# Breaks as well as nexts to make
+# sure we can handle simultaneous hit
+# of bpt and step, as well as stepping
+# past bpts.
+#
+gdb_test "tb 87" ".*Breakpoint 2.*" ""
+gdb_test "tb 91" ".*Breakpoint 3.*" ""
+gdb_test "tb 96" ".*Breakpoint 4.*" ""
+gdb_test "tb 113" ".*Breakpoint 5.*" ""
+gdb_test "c" ".*do_pass.*87.*" "87"
+gdb_test "n" ".*do_pass.*91.*" "n"
+
+# This only gets a number, as it doesn't
+# hit a bpt.
+#
+gdb_test "n" ".*95.*" "n"
+
+gdb_test "n" ".*do_pass.*96.*" "n"
+gdb_test "c" ".*do_pass.*113.*" "c"
+gdb_test "c" ".*Program exited normally.*" "c"
+
+# Now step in a thread
+#
+gdb_test "r" ".*Breakpoint.*do_pass.*" "do_pass"
+gdb_test "until 87" ".*do_pass.*87.*" "until"
+gdb_test "thr 4" ".*Switching to thread 4.*spin.*56.*" "switch"
+gdb_test "tb 60 thr 4" ".*Breakpoint.*" ""
+
+# If we do "next" now, all the other threads
+# can finish!
+#
+gdb_test "n" ".*spin.*60.*" ""
+gdb_test "i th" ".*\\\* 4 sys.*spin.*1 sys.*do_pass.*" "still in 4"
+
+# Done!
+#
+gdb_exit
+
+set timeout $oldtimeout
+set verbose $oldverbose
+
+# execute_anywhere "rm -f ${binfile}"
+#
+return 0
+
diff --git a/gdb/testsuite/gdb.hp/namespace.cc b/gdb/testsuite/gdb.hp/namespace.cc
new file mode 100644
index 00000000000..53d5bd6608d
--- /dev/null
+++ b/gdb/testsuite/gdb.hp/namespace.cc
@@ -0,0 +1,103 @@
+namespace AAA {
+ char c;
+ int i;
+ int A_foo (int);
+ char foo (char);
+ class inA {
+ public:
+ int xx;
+ int fum (int);
+ };
+};
+
+int AAA::inA::fum (int i)
+{
+ return 10 + i;
+}
+
+namespace BBB {
+ char c;
+ int i;
+ int B_foo (int);
+ char foo (char);
+
+ namespace CCC {
+ char foo (char);
+ };
+
+ class Class {
+ public:
+ char foo (char);
+ int dummy;
+ };
+};
+
+int AAA::A_foo (int x)
+{
+ return 2 * x;
+}
+
+char AAA::foo (char c)
+{
+ return 'a';
+}
+
+
+int BBB::B_foo (int x)
+{
+ return 3 * x;
+}
+
+char BBB::foo (char c)
+{
+ return 'b';
+}
+
+char BBB::CCC::foo (char c)
+{
+ return 'z';
+}
+
+char BBB::Class::foo (char c)
+{
+ return 'o';
+}
+
+void marker1(void)
+{
+ return;
+}
+
+
+int main ()
+{
+ using AAA::inA;
+ char c1;
+
+ using namespace BBB;
+
+ c1 = foo ('x');
+ c1 = AAA::foo ('x');
+ c1 = BBB::CCC::foo ('m');
+
+ inA ina;
+
+ ina.xx = 33;
+
+ int y;
+
+ y = AAA::A_foo (33);
+ y += B_foo (44);
+
+ BBB::Class cl;
+
+ c1 = cl.foo('e');
+
+ marker1();
+
+}
+
+
+
+
+
diff --git a/gdb/testsuite/gdb.hp/namespace.exp b/gdb/testsuite/gdb.hp/namespace.exp
new file mode 100644
index 00000000000..1708db8ebb0
--- /dev/null
+++ b/gdb/testsuite/gdb.hp/namespace.exp
@@ -0,0 +1,195 @@
+# Copyright (C) 1997, 1998 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# tests for namespaces
+# Written by Satish Pai <pai@apollo.hp.com> 1997-07-23
+
+# This file is part of the gdb testsuite
+
+# Note: These tests are geared to the HP aCC compiler,
+# which has an idiosyncratic way of emitting debug info
+# for namespaces.
+
+
+if $tracelevel then {
+ strace $tracelevel
+ }
+
+
+#
+# test running programs
+#
+
+set prms_id 0
+set bug_id 0
+
+set testfile "namespace"
+set srcfile ${testfile}.cc
+set binfile ${objdir}/${subdir}/${testfile}
+
+if [get_compiler_info ${binfile}] {
+ return -1;
+}
+
+
+if {[skip_hp_tests $gcc_compiled]} then { continue }
+
+
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug c++}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will a
+utomatically fail."
+}
+
+
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+
+#
+# set it up at a breakpoint so we can play with the variable values
+#
+if ![runto_main] then {
+ perror "couldn't run to breakpoint"
+ continue
+}
+
+send_gdb "break marker1\n" ; gdb_expect -re ".*$gdb_prompt $"
+ send_gdb "cont\n"
+ gdb_expect {
+ -re "Break.* marker1 \\(\\) at .*:$decimal.*$gdb_prompt $" {
+ send_gdb "up\n"
+ gdb_expect {
+ -re ".*$gdb_prompt $" { pass "up from marker1" }
+ timeout { fail "up from marker1" }
+ }
+ }
+ -re "$gdb_prompt $" { fail "continue to marker1" }
+ timeout { fail "(timeout) continue to marker1" }
+ }
+
+# Access a data item inside a namespace using colons and
+# single quotes :-(
+
+send_gdb "print 'AAA::c'\n"
+gdb_expect {
+ -re "\\$\[0-9\]* = 0 '\\\\000'\r\n$gdb_prompt $" { pass "print 'AAA::c'" }
+ -re ".*$gdb_prompt $" { fail "print 'AAA::c'" }
+ timeout { fail "(timeout) print 'AAA::c'" }
+}
+
+# An object declared using "using".
+
+send_gdb "print ina\n"
+gdb_expect {
+ -re "\\$\[0-9\]+ = {xx = 33}.*$gdb_prompt $" {
+ pass "print ina"
+ }
+ -re ".*$gdb_prompt $" { fail "print ina" }
+ timeout { fail "(timeout) print ina" }
+}
+
+send_gdb "ptype ina\n"
+gdb_expect {
+ -re "type = class AAA::inA \{\r\n\[ \]*public:\r\n\[ \]*int xx;\r\n\[ \]*\r\n\[ \]*int fum\\(int\\);\r\n\}\r\n$gdb_prompt $" {
+ pass "ptype ina"
+ }
+ -re ".*$gdb_prompt $" { fail "ptype ina" }
+ timeout { fail "(timeout) ptype ina" }
+}
+
+# Check all functions are known to GDB
+
+send_gdb "info func foo\n"
+gdb_expect {
+ -re "All functions.*File.*namespace.cc:\r\nint AAA::A_foo\\(int\\);\r\nint BBB::B_foo\\(int\\);\r\nchar AAA::foo\\(char\\);\r\nchar BBB::foo\\(char\\);\r\nchar BBB::CCC::foo\\(char\\);\r\nchar BBB::Class::foo\\(char\\);\r\n$gdb_prompt $" {
+ pass "info func foo"
+ }
+ -re ".*$gdb_prompt $" { fail "info func foo" }
+ timeout { fail "(timeout) info func foo" }
+}
+
+# Call a function in a namespace
+
+send_gdb "print 'AAA::foo'('x')\n"
+gdb_expect {
+ -re "\\$\[0-9\]* = 97 'a'\r\n$gdb_prompt $" {
+ pass "print 'AAA::foo'('x')"
+ }
+ -re ".*$gdb_prompt $" { fail "print 'AAA::foo'('x')" }
+ timeout { fail "(timeout) print 'AAA::foo'('x')" }
+}
+
+# Break on a function in a namespace
+
+send_gdb "break AAA::foo\n"
+gdb_expect {
+ -re "Breakpoint.*at $hex: file.*namespace.cc, line 42\\.\r\n$gdb_prompt $" {
+ pass "break AAA::foo"
+ }
+ -re ".*$gdb_prompt $" { fail "break AAA::foo" }
+ timeout { fail "(timeout) break AAA::foo" }
+}
+
+# Call a function in a nested namespace
+
+send_gdb "print 'BBB::CCC::foo'('x')\n"
+gdb_expect {
+ -re "\\$\[0-9\]* = 122 'z'\r\n$gdb_prompt $" {
+ pass "print 'BBB::CCC::foo'('x')"
+ }
+ -re ".*$gdb_prompt $" { fail "print 'BBB::CCC::foo'('x')" }
+ timeout { fail "(timeout) print 'BBB::CCC::foo'('x')" }
+}
+
+# Break on a function in a nested namespace
+
+send_gdb "break BBB::CCC::foo\n"
+gdb_expect {
+ -re "Breakpoint.*at $hex: file.*namespace.cc, line 58\\.\r\n$gdb_prompt $" {
+ pass "break BBB::CCC::foo"
+ }
+ -re ".*$gdb_prompt $" { fail "break BBB::CCC::foo" }
+ timeout { fail "(timeout) break BBB::CCC::foo" }
+}
+
+# Print address of a function in a class in a namespace
+
+send_gdb "print 'BBB::Class'::foo\n"
+gdb_expect {
+ -re "\\$\[0-9\]* = \{char \\(BBB::Class \\*, char\\)\} $hex <BBB::Class::foo\\(char\\)>\r\n$gdb_prompt $" {
+ pass "print 'BBB::Class'::foo"
+ }
+ -re ".*$gdb_prompt $" { fail "print 'BBB::Class'::foo" }
+ timeout { fail "(timeout) print 'BBB::Class'::foo" }
+}
+
+# Break on a function in a class in a namespace
+
+send_gdb "break BBB::Class::foo\n"
+gdb_expect {
+ -re "Breakpoint.*at $hex: file.*namespace.cc, line 63\\.\r\n$gdb_prompt $" {
+ pass "break BBB::Class::foo"
+ }
+ -re ".*$gdb_prompt $" { fail "break BBB::Class::foo" }
+ timeout { fail "(timeout) break BBB::Class::foo" }
+}
+
diff --git a/gdb/testsuite/gdb.hp/optimize.c b/gdb/testsuite/gdb.hp/optimize.c
new file mode 100644
index 00000000000..2a8daa8c7a0
--- /dev/null
+++ b/gdb/testsuite/gdb.hp/optimize.c
@@ -0,0 +1,76 @@
+/* Source for debugging optimimzed code test.
+
+ cc -g -O -o optimize optimize.c
+*/
+int callee();
+int test_opt;
+
+int main()
+{
+ int a,b,c,d,e,f,g,h;
+
+ a = 10;;
+
+ /* Value propagate
+ */
+ b = 2 * a + 1;
+ c = 3 * b + 2;
+
+ /* Re-use expressions
+ */
+ d = (2 * a + 1) * (3 * b + 2);
+ e = (2 * a + 1) * (3 * b + 2);
+
+ /* Create dead stores--do lines still exist?
+ */
+ d = (2 * a + 1) * (3 * b + 2);
+ e = (2 * a + 1) * (3 * b + 2);
+ d = (2 * a + 1) * (3 * b + 2);
+ e = (2 * a + 1) * (3 * b + 2);
+
+ /* Alpha and psi motion
+ */
+ if( test_opt ) {
+ f = e - d;
+ f = f--;
+ }
+ else {
+ f = e - d;
+ f = f + d * e;
+ }
+
+ /* Chi and Rho motion
+ */
+ h = 0;
+ do {
+ h++;
+ a = b * c + d * e; /* Chi */
+ f = f + d * e;
+ g = f + d * e; /* Rho */
+ callee( g+1 );
+ test_opt = (test_opt != 1); /* Cycles */
+ } while( g && h < 10);
+
+ /* Opps for tail recursion, unrolling,
+ * folding, evaporating
+ */
+ for( a = 0; a < 100; a++ ) {
+ callee( callee ( callee( a )));
+ callee( callee ( callee( a )));
+ callee( callee ( callee( a )));
+ }
+
+ return callee( test_opt );
+}
+
+/* defined late to keep line numbers the same
+*/
+int callee( x )
+ int x; /* not used! */
+{
+ test_opt++; /* side effect */
+
+ return test_opt;
+}
+
+/* end */ \ No newline at end of file
diff --git a/gdb/testsuite/gdb.hp/optimize.exp b/gdb/testsuite/gdb.hp/optimize.exp
new file mode 100644
index 00000000000..34606eb668f
--- /dev/null
+++ b/gdb/testsuite/gdb.hp/optimize.exp
@@ -0,0 +1,144 @@
+# Copyright (C) 1998 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# optimize.exp -- Expect script for testing apps compiled with -O
+
+global timeout
+
+# use this to debug:
+#
+#log_user 1
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+set testfile optimize
+set srcfile ${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+
+if [get_compiler_info ${binfile}] {
+ return -1;
+}
+
+
+if {[skip_hp_tests $gcc_compiled]} then { continue }
+
+
+# Vanilla -O, which is the same as +O2
+#
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug optimize=+O2}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+
+send_gdb "file $binfile\n"
+gdb_expect {
+ -re ".*no debugging symbols found.*$gdb_prompt $" {
+ fail "Didn't find debug symbols; CHFts23488"
+ }
+ -re ".*No header section (PXDB data).*$gdb_prompt $" {
+ fail "pointless warning"
+ }
+ -re ".*done.*$gdb_prompt $" {
+ pass "load debug symbols"
+ }
+ timeout { fail "timeout on file" }
+}
+
+# Two lines at the same place after opt.
+#
+gdb_test "b 28" ".*" ""
+gdb_test "b 26" ".*also set at.*" "same line"
+
+gdb_test "b 47" ".*" ""
+gdb_test "b 48" ".*also set at.*" "same line"
+
+gdb_test "tb main" ".*" ""
+
+set old_timeout $timeout
+set timeout [expr "$timeout + 200"]
+send_gdb "r\n"
+gdb_expect {
+ -re ".*No header section (PXDB data).*$gdb_prompt $" {
+ fail "pointless warning"
+ }
+ -re ".*main.*2\[12].*$gdb_prompt $" {
+ # All the lines before line 21 or 22 are
+ # evaporated by the compiler.
+ #
+ pass "hit main"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "didn't hit main"
+ }
+ timeout { fail "timeout on run" }
+}
+set timeout $old_timeout
+
+gdb_test "c" ".*Breakpoint 1.*33.*" ""
+gdb_test "c" ".*51.*" ""
+gdb_test "cle" ".*Deleted breakpoints.*" "set 2, so del 2"
+
+gdb_test "b callee" ".*" ""
+gdb_test "c" ".*callee.*" "hit called rtn"
+
+gdb_exit
+
+# +O4, don't use -g
+#
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {optimize=+O4}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+
+send_gdb "file $binfile\n"
+gdb_expect {
+ -re ".*no debugging symbols found.*$gdb_prompt $" {
+ pass "Didn't find debug symbols, as expected"
+ }
+ -re ".*No header section (PXDB data).*$gdb_prompt $" {
+ fail "pointless warning"
+ }
+ -re ".*done.*$gdb_prompt $" {
+ fail "Somehow found debug symbols--make this a pass?"
+ }
+ timeout { fail "timeout on file" }
+}
+
+gdb_test "b main" ".*" ""
+gdb_test "b callee" ".*" ""
+gdb_test "r" ".*Breakpoint 1.*main.*" ""
+gdb_test "si 3" ".*main.*" "steps"
+gdb_test "x/4i \$pc" ".*main.*main+4.*main+8.*" ""
+gdb_test "c" ".*callee.*" "hit bp"
+gdb_test "disas" ".*callee.*callee+4.*callee+12.*" ""
+gdb_test "si" ".*callee.*" ""
+gdb_test "fin" ".*Run till exit.*main.*" "finish"
+gdb_test "x/i \$pc" ".*main+.*" "back in main"
+gdb_exit
+
+#remote_exec build "rm -f ${binfile}"
+return 0
diff --git a/gdb/testsuite/gdb.hp/pxdb.c b/gdb/testsuite/gdb.hp/pxdb.c
new file mode 100644
index 00000000000..e3e3fc23e9f
--- /dev/null
+++ b/gdb/testsuite/gdb.hp/pxdb.c
@@ -0,0 +1,20 @@
+#include <stdio.h>
+
+int callee( x )
+int x;
+{
+ int y = x * x;
+ return (y - 2);
+}
+
+main()
+{
+ int i;
+ for (i = 1; i < 10; i++)
+ {
+ printf( "%d ", callee( i ));
+
+ }
+ printf( " Goodbye!\n" );
+
+}
diff --git a/gdb/testsuite/gdb.hp/pxdb.exp b/gdb/testsuite/gdb.hp/pxdb.exp
new file mode 100644
index 00000000000..c8b3ace9961
--- /dev/null
+++ b/gdb/testsuite/gdb.hp/pxdb.exp
@@ -0,0 +1,114 @@
+# Copyright (C) 1998 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+
+# This file is part of the gdb testsuite
+
+
+# pxdb.exp Test that gdb calls pxdb on an application
+# built without it.
+#
+if $tracelevel then {
+ strace $tracelevel
+}
+
+set prms_id 0
+set bug_id 0
+
+set testfile pxdb
+set srcfile ${testfile}.c
+set objfile ${objdir}/${subdir}/${testfile}.o
+set binfile ${objdir}/${subdir}/${testfile}
+
+if [get_compiler_info ${binfile} "c++"] {
+ return -1;
+}
+
+
+if {[skip_hp_tests $gcc_compiled]} then { continue }
+
+# To build a non-pxdb-ed file, use
+#
+# <compile to .o file>
+# export LD_PXDB /dev/null
+# ld -o hello_no_pxdb hello.o /opt/langtools/lib/end.o /usr/ccs/lib/crt0.o -lc
+#
+
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${objfile}" object {debug}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+#
+# use this to debug:
+#log_user 1
+
+
+# Following should get the error message:
+#
+# ld: (Warning) Can't exec pxdb using path: /dev/null
+#
+
+set cmdline "ksh -c \"LD_PXDB=/dev/null ld -o ${binfile} ${objfile} /usr/ccs/lib/crt0.o /opt/langtools/lib/end.o -lc\""
+
+remote_exec build "rm ${binfile}"
+remote_exec build $cmdline
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+
+# We expect to see this:
+#
+# "warning: File not processed by pxdb--about to process now.
+# "
+# ".
+# "Procedures: 7
+# "Files: 2
+# "Reading symbols from ~/c_code.dir/hello_no_pxdb...done.
+# "(gdb)
+#
+send_gdb "file ${binfile}\n"
+gdb_expect {
+
+ -re ".*warning: File not processed by pxdb.*Procedures: \[0-9\]+.*done.*$gdb_prompt $"\
+ { pass "PXDB call" }
+
+ -re "$gdb_prompt $" { fail "Didn't call pxdb" }
+
+ timeout { fail "call pxdb (timeout)" }
+}
+
+# Make sure the new data makes sense
+#
+if { ![runto callee] } then { return }
+
+send_gdb "print x\n"
+gdb_expect {
+ -re ".*= 1.*$gdb_prompt $" { pass "Good data after pxdb call" }
+ -re ".*$gdb_prompt $" { fail "No data after pxdb call" }
+ timeout { fail "(timeout)" }
+}
+
+gdb_exit
+return 0
+
+
+
+
+
diff --git a/gdb/testsuite/gdb.hp/quicksort.c b/gdb/testsuite/gdb.hp/quicksort.c
new file mode 100644
index 00000000000..b44b828a8d5
--- /dev/null
+++ b/gdb/testsuite/gdb.hp/quicksort.c
@@ -0,0 +1,284 @@
+/* BeginSourceFile quicksort.c
+
+ This file is take from the DDE test system. It spawns six
+ threads to do a sort of an array of random numbers.
+
+ The locations marked "quick N" are used in the test "quicksort.exp".
+
+ The locations marked "att N" are used in the test "attach.exp".
+
+ To compile:
+
+ cc -Ae +DA1.0 -g -o quicksort -lpthread quicksort.c
+
+ To run:
+
+ quicksort --normal run
+ quicksort 1 --waits before starting to allow attach
+*/
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <assert.h>
+#include <pthread.h>
+
+#define TRUE 1
+#define FALSE 0
+#define SORTSET 100000
+
+/* Uncomment to turn on debugging output */
+/* #define QUICK_DEBUG */
+
+/* Uncomment to turn on wait on each thread create */
+/* #define THREAD_WAIT */
+
+/* Fewer than SORT_DIRECT items are sorted with an insertion sort. */
+#define SORT_DIRECT 20
+
+/* Work at this depth or less generates a separate work item. */
+#define DEFER_DEPTH 6
+
+/* Workpile controller */
+typedef void (*work_proc_t)(void *);
+
+typedef struct workpile_struct {
+ pthread_mutex_t lock; /* mutex for this structure */
+ pthread_cond_t work_wait; /* workers waiting for work */
+ pthread_cond_t finish_wait; /* to wait for workers to finish */
+ int max_pile; /* length of workpile array */
+ work_proc_t worker_proc; /* work procedure */
+ int n_working; /* number of workers working */
+ int n_waiting; /* number of workers waiting for work */
+ int n_pile; /* number of pointers in the workpile */
+ int inp; /* FIFO input pointer */
+ int outp; /* FIFO output pointer */
+ void *pile[1]; /* array of pointers - the workpile */
+} *workpile_t;
+
+typedef struct {
+ float *data; /* Array to sort */
+ int n; /* Number of elements in the array */
+ int depth; /* Depth of recursion */
+ workpile_t wp; /* Workpile to use */
+} quick_sort_args;
+
+/* True if waiting for attach.
+ */
+int wait_here = FALSE;
+
+static workpile_t quick_sort_workpile = NULL;
+
+void *worker(void * wptr);
+
+/* Allocates and initializes a workpile that holds max_pile entries.
+ * worker_proc is called to process each work item on the queue.
+ */
+workpile_t
+work_init(int max_pile, work_proc_t worker_proc, int n_threads)
+{
+ int err;
+ pthread_t t;
+ workpile_t wp = (workpile_t)
+ malloc(sizeof (struct workpile_struct) +
+ (max_pile * sizeof (void *)));
+
+ if (wp != NULL) {
+ pthread_mutex_init(&wp->lock, NULL);
+ pthread_cond_init(&wp->work_wait, NULL);
+ pthread_cond_init(&wp->finish_wait, NULL);
+ wp->max_pile = max_pile;
+ wp->worker_proc = worker_proc;
+ wp->n_working = wp->n_waiting = wp->n_pile = 0;
+ wp->inp = wp->outp = 0;
+ while (n_threads--) {
+ err = pthread_create(&t, NULL,
+ worker, (void *)&wp);
+#ifdef QUICK_DEBUG
+ printf( "== Quicksort: created new thread\n" );
+#ifdef THREAD_WAIT
+ if( n_threads > 0 ) {
+ int i;
+ printf( "== Quicksort: waiting on user input of an integer\n" );
+ scanf( "%d", &i );
+ printf( "== Quicksort: continuing with quicksort\n" );
+ }
+#endif
+#endif
+
+ assert(err == 0); /* quick 1 */
+ }
+ /* All the threads have now been created.
+ */
+ assert( n_threads == -1 ); /* att 1 */
+ if( wait_here ) {
+#ifdef QUICK_DEBUG
+ printf( "== Quicksort: waiting for attach\n" );
+#endif
+ sleep( 25 );
+ }
+ wait_here = 99; /* att 2, otherwise useless */
+ }
+ return (wp); /* quick 2 */
+}
+
+/*
+ * Worker thread routine. Continuously looks for work, calls the
+ * worker_proc associated with the workpile to do work.
+ */
+void *
+worker(void * wptr)
+{
+ workpile_t wp;
+ void *ptr;
+
+ wp = * (workpile_t *) wptr;
+
+ pthread_mutex_lock(&wp->lock);
+ wp->n_working++;
+ for (;;) {
+ while (wp->n_pile == 0) { /* wait for new work */
+ if (--wp->n_working == 0)
+ pthread_cond_signal(&wp->finish_wait);
+ wp->n_waiting++;
+ pthread_cond_wait(&wp->work_wait, &wp->lock);
+ wp->n_waiting--; /* quick 3 */
+ wp->n_working++;
+ }
+ wp->n_pile--;
+ ptr = wp->pile[wp->outp];
+ wp->outp = (wp->outp + 1) % wp->max_pile;
+ pthread_mutex_unlock(&wp->lock);
+ /* Call application worker routine. */
+ (*wp->worker_proc)(ptr);
+ pthread_mutex_lock(&wp->lock); /* quick 4 */
+ }
+ /* NOTREACHED */
+}
+
+/* Puts ptr in workpile. Called at the outset, or within a worker. */
+void
+work_put(workpile_t wp, void *ptr)
+{
+ pthread_mutex_lock(&wp->lock);
+ if (wp->n_waiting) {
+ /* idle workers to be awakened */
+ pthread_cond_signal(&wp->work_wait);
+ }
+ assert(wp->n_pile != wp->max_pile); /* check for room */
+ wp->n_pile++;
+ wp->pile[wp->inp] = ptr;
+ wp->inp = (wp->inp + 1) % wp->max_pile;
+ pthread_mutex_unlock(&wp->lock);
+}
+
+
+/* Wait until all work is done and workers quiesce. */
+void
+work_wait(workpile_t wp)
+{
+ pthread_mutex_lock(&wp->lock);
+ while(wp->n_pile !=0 || wp->n_working != 0)
+ pthread_cond_wait(&wp->finish_wait, &wp->lock);
+ pthread_mutex_unlock(&wp->lock);
+}
+
+void
+quick_sort_aux(float *data, int n, int depth, workpile_t wp, int deferrable)
+{
+ int i,j;
+
+ /* If array small, use insertion sort */
+ if (n <= SORT_DIRECT) {
+ for (j = 1; j < n; j++) {
+ /* data[0..j-1] in sort; find a spot for data[j] */
+ float key = data[j];
+ for (i = j - 1; i >= 0 && key < data[i]; i--)
+ data[i+1] = data[i];
+ data[i+1] = key;
+ }
+ return;
+ }
+ /* Defer this work to work queue if policy says so */
+ if (deferrable && depth <= DEFER_DEPTH) {
+ quick_sort_args *q = (quick_sort_args *)
+ malloc(sizeof (quick_sort_args));
+ assert(q != NULL);
+ q->data = data; q->n = n; q->depth = depth; q->wp = wp;
+ work_put(wp, (void *)q);
+ return;
+ }
+ /* Otherwise, partition data based on a median estimate */
+#define swap(i,j) {float t = data[i]; data[i] = data[j]; data[j] = t;}
+ i = 0;
+ j = n - 1;
+ for (;;) {
+ while (data[i] < data[j]) j--;
+ if (i >= j) break;
+ swap(i, j); i++;
+ while (data[i] < data[j]) i++;
+ if (i >= j) { i = j; break; }
+ swap(i, j); j--;
+ }
+ /* Median value is now at data[i] */
+ /* Partitioned so that data[0..i-1] <= median <= data[i+1..n-1] */
+ quick_sort_aux(data, i, depth+1, wp, TRUE);
+ quick_sort_aux(&data[i+1], n-i-1, depth+1, wp, TRUE);
+}
+/* Called from workpile controller with argument pointing to work. */
+void
+quick_sort_worker(void *a)
+{
+ quick_sort_args *q = (quick_sort_args *)a;
+ quick_sort_aux(q->data, q->n, q->depth, q->wp, FALSE);
+ free(q);
+}
+/* Main routine, called by client to do a sort. */
+void
+quick_sort(float *data, int n)
+{
+ if (quick_sort_workpile == NULL) {
+ int n_threads = 6;
+ quick_sort_workpile = work_init(2 << DEFER_DEPTH,
+ quick_sort_worker, n_threads);
+ assert(quick_sort_workpile != NULL);
+ }
+
+ quick_sort_aux(data, n, 0, quick_sort_workpile, FALSE);
+
+ /* Wait for all work to finish */
+ work_wait(quick_sort_workpile);
+
+#ifdef QUICK_DEBUG
+ printf( "== Quicksort: done sorting\n" );
+#endif
+}
+
+
+main( argc, argv )
+int argc;
+char **argv;
+{
+ float data[SORTSET];
+ int i; int debugging = 0;
+
+ if((argc > 1) && (0 != argv )) {
+ if( 1 == atoi( argv[1] ) )
+ wait_here = TRUE;
+ }
+
+ for(i = 0; i < SORTSET; i++)
+ data[SORTSET -1 -i] = drand48();
+
+ for(i = 0; i < SORTSET; i++)
+ if (debugging)
+ printf("data[%d] = %f\n", i, data[i]);
+
+ quick_sort(data, SORTSET);
+ for(i = 0; i < SORTSET; i++)
+ if (debugging)
+ printf("data[%d] = %f\n", i, data[i]);
+
+ return(0);
+}
+/* EndSourceFile */
diff --git a/gdb/testsuite/gdb.hp/quicksort.exp b/gdb/testsuite/gdb.hp/quicksort.exp
new file mode 100644
index 00000000000..719bfdfb0a9
--- /dev/null
+++ b/gdb/testsuite/gdb.hp/quicksort.exp
@@ -0,0 +1,809 @@
+# quicksort.exp -- Expect script to test gdb with quicksort.c
+# Copyright (C) 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# use this to debug:
+#
+#log_user 1
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+if { ![istarget "hppa*-*-hpux10.30"] && ![istarget "hppa*-*-hpux11.*"] } {
+ verbose "HPUX thread test ignored for non-hppa or pre-HP/UX-10.30 targets."
+ return 0
+}
+
+set testfile quicksort
+set srcfile ${srcdir}/${subdir}/${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+
+if [get_compiler_info ${binfile}] {
+ return -1
+}
+
+# To build the executable we need to link against the thread library.
+#
+# cc -Ae -g -o quicksort -lpthread quicksort.c
+#
+#compile "${srcfile} -Ae -g -lpthread -o ${binfile}"
+
+if {$gcc_compiled == 0} {
+ set additional_flags "additional_flags=-Ae"
+} else {
+ set additional_flags ""
+}
+
+if { [gdb_compile "${srcdir}/${subdir}/${testfile}.c" "${binfile}.o" object [list debug $additional_flags]] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+remote_exec build "ld /usr/ccs/lib/crt0.o ${binfile}.o -lcl -lpthread -lc /opt/langtools/lib/end.o -o ${binfile}"
+
+
+# Thread stuff is _slow_; prepare for long waits.
+#
+set oldtimeout $timeout
+set timeout [expr "$timeout + 300"]
+set oldverbose $verbose
+#set verbose 40
+
+# Further, this test has some "null" lines designed
+# to consume output from gdb that was too late to be
+# matched (sequence is "gdb_test" sends; timeout and
+# on to next send; result finally comes in; mismatch).
+#
+# The null command is 'gdb_test "p \$pc" ".*" ""'
+#
+# NOTE: to pass a literal "$", "/" or "*" (etc.) to gdb_test,
+# remember that the pattern will be escaped once and
+# $-evaluated twice:
+#
+# "\\\*" matches "\*"
+# "\$" matches "$"
+#
+proc fix_timeout {} {
+ gdb_test "p \$pc" ".*" ""
+}
+
+#=========================
+#
+# Simple sanity test first.
+#
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+gdb_test "tb 122" ".*Breakpoint.*" ""
+gdb_test "r" ".*122.*" ""
+gdb_test "thr 99" ".*Thread ID 99 not known.*" "Check too-big thread number"
+gdb_test "tb 145 thr 3" ".*Breakpoint.*" "set thread-specific bp 145"
+gdb_test "tb 146 thr 4" ".*Breakpoint.*" "set thread-specific bp 146"
+gdb_test "c" ".*Switched to thread.*145.*" "auto switch"
+gdb_test "c" ".*Switched to thread.*146.*" "auto switch 2"
+gdb_test "c" ".*Program exited normally.*" ""
+
+#=========================
+#
+# Test that you can't do a thread select after a program runs.
+#
+gdb_test "thread" ".*No stack.*" "No live thread after run"
+gdb_test "thr 2" ".*No stack.*" "Can't set thread after run"
+
+#=========================
+#
+# Test thread command changes, look for frame level reset bug.
+#
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+gdb_test "b 122" ".*" ""
+gdb_test "r" ".*122.*" ""
+
+# Prep for frame level test--go up/info thread/check frame
+#
+gdb_test "up" ".*quick_sort.*" ""
+gdb_test "up" ".*main.*" ""
+
+send_gdb "i th\n"
+gdb_expect {
+ -re ".*7 thread.* in .* from .* in .* from .* 6 thread.*$gdb_prompt $" {
+ fail "old thread command, says things twice"
+ }
+ -re ".*7 system thread.*6 system th.*5 sys.*4.*3.*2.*1.*work_init.*$gdb_prompt $" {
+ pass "info threads"
+ }
+ -re ".*$gdb_prompt $" { fail "no info thread command" }
+ timeout { fail "timeout" }
+}
+
+# We should have been restored two frames up--check.
+#
+send_gdb "up\n"
+gdb_expect {
+ -re ".*Initial frame selected.*$gdb_prompt $" {
+ pass "Frame correctly reset after 'info threads'"
+ }
+ -re ".*quick_sort.*$gdb_prompt $" {
+ fail "Old gdb bug; should be fixed someday"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "real bug--FIX!"
+ }
+ timeout { fail "timeout" }
+}
+
+# Do it again, only just go to a middle frame, and use another thread.
+#
+gdb_test "thr 5" ".*" ""
+gdb_test "bt" ".* ___ksleep.*_lwp_cond_timedwait.*pthread_cond_wait.*worker.*__pthread_create_system.*" ""
+gdb_test "up" ".*1.*_lwp_cond_timedwait.*" ""
+gdb_test "up" ".*2.*pthread_cond_wait.*" ""
+gdb_test "up" ".*3.*worker.*" ""
+gdb_test "i th" ".*7.*6.*work_init.*" ""
+gdb_test "f" ".*3.*worker.*" "Frame restored"
+gdb_test "p wp->max_pile" ".*= 128.*" "can see vars in frame"
+
+# Thread command changes
+#
+gdb_test "thr" ".*Current thread is 5.*" "threads-no-num"
+gdb_test "thr 6" ".*Switching to thread 6.*" "new switch"
+gdb_test "thr" ".*Current thread is 6.*" "check switch"
+#gdb_test "thr 6" ".*Current thread is already 6.*" "dup, no switch"
+gdb_test "thr app all p x" ".*No symbol.*" ""
+gdb_test "thr" ".*Current thread is 6.*" "restore current thread"
+
+#=========================
+#
+# Test new stepping
+#
+
+proc get_hit { } {
+ global hit2
+ global hit3
+ global hit4
+ global hit5
+ global hit6
+ global hit7
+ global gdb_prompt
+
+ send_gdb "cont\n"
+ gdb_expect {
+ -re ".*Breakpoint.*145.*$gdb_prompt $" {
+ send_gdb "thr\n"
+ gdb_expect {
+ -re ".*is 7.*$gdb_prompt $" {
+ set hit7 [expr "$hit7 + 1"]
+ }
+ -re ".*is 6.*$gdb_prompt $" {
+ set hit6 [expr "$hit6 + 1"]
+ }
+ -re ".*is 5.*$gdb_prompt $" {
+ set hit5 [expr "$hit5 + 1"]
+ }
+ -re ".*is 4.*$gdb_prompt $" {
+ set hit4 [expr "$hit4 + 1"]
+ }
+ -re ".*is 3.*$gdb_prompt $" {
+ set hit3 [expr "$hit3 + 1"]
+ }
+ -re ".*is 2.*$gdb_prompt $" {
+ set hit2 [expr "$hit2 + 1"]
+ }
+ -re ".*$gdb_prompt $" {
+ fail "can't see which thread"
+ }
+ timeout { fail "timeout" }
+ }
+ }
+ -re ".*$gdb_prompt $" {
+ fail "thread command"
+ }
+ timeout { fail "timeout" }
+ }
+}
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+gdb_test "break 122" ".*" ""
+gdb_test "run" ".*122.*" ""
+
+# Make sure we hit a bp on every thread.
+#
+# Try one, via thread-specific bps
+#
+gdb_test "break 145 thr 2" ".*" "set thread-specific bp thr 2"
+gdb_test "break 145 thr 3" ".*" "set thread-specific bp thr 3"
+gdb_test "break 145 thr 4" ".*" "set thread-specific bp thr 4"
+gdb_test "break 145 thr 5" ".*" "set thread-specific bp thr 5"
+gdb_test "break 145 thr 6" ".*" "set thread-specific bp thr 6"
+gdb_test "break 145 thr 7" ".*" "set thread-specific bp thr 7"
+
+set hit2 0
+set hit3 0
+set hit4 0
+set hit5 0
+set hit6 0
+set hit7 0
+
+get_hit
+get_hit
+get_hit
+get_hit
+get_hit
+get_hit
+
+if { [expr "$hit2 == 1"]
+ && [expr "$hit3 == 1"]
+ && [expr "$hit4 == 1"]
+ && [expr "$hit5 == 1"]
+ && [expr "$hit6 == 1"]
+ && [expr "$hit7 == 1"] } {
+ pass "thread-specific bps 1"
+} else {
+ fail "thread-specific bps 1"
+}
+
+#====================
+#
+# Now use generic bps
+#
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+gdb_test "b 122" ".*" ""
+gdb_test "r" ".*122.*" ""
+
+# Make sure we hit a bp on every thread.
+#
+# Try two, via non-thread-specific bp
+#
+gdb_test "b 145" ".*" "b 145"
+
+set hit2 0
+set hit3 0
+set hit4 0
+set hit5 0
+set hit6 0
+set hit7 0
+
+get_hit
+get_hit
+get_hit
+get_hit
+get_hit
+get_hit
+
+if { [expr "$hit2 == 1"]
+ && [expr "$hit3 == 1"]
+ && [expr "$hit4 == 1"]
+ && [expr "$hit5 == 1"]
+ && [expr "$hit6 == 1"]
+ && [expr "$hit7 == 1"] } {
+ pass "thread-specific bps 2"
+} else {
+ fail "thread-specific bps 2"
+}
+
+#====================
+#
+# Complicated (original) test next.
+#
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+if ![runto_main] then {
+ fail "Can't run to main"
+ return 0
+}
+
+# OK, we're at "main", there should be one thread.
+#
+gdb_test "info thread" ".*\\\* 1 system thread .*main.*" "initial thread"
+
+# Try to see the threads being created: set a breakpoint
+# after the creation and go around the loop a few times.
+#
+gdb_test "break 109" "Breakpoint.*109.*" "set bpt"
+
+gdb_test "c" ".*New thread.*Breakpoint.*109.*" "first continue"
+fix_timeout
+
+# Make sure we don't wait (waiting is for attach test)
+#
+gdb_test "set wait_here = 0" ".*" ""
+
+send_gdb "info thr\n"
+gdb_expect {
+ -re ".*2 system th.*1 sy.*109.*$gdb_prompt $" { pass "saw thread create" }
+ -re ".*1 system thread.*87.*$gdb_prompt $" { fail "didn't see thread create" }
+ -re ".*$gdb_prompt $" { fail "no info thread command" }
+ timeout { fail "timeout" }
+}
+
+gdb_test "c" ".*New thread.*Breakpoint.*109.*" "continue"
+fix_timeout
+
+send_gdb "info thr\n"
+gdb_expect {
+ -re ".*3 system thread.*2 sys.*\\\* 1 system thread.*109.*$gdb_prompt $" {
+ pass "saw thread create" }
+ -re ".*2 system thread.*1 sys.*109.*$gdb_prompt $" {
+ fail "didn't see thread create"
+ }
+ -re ".*1 system thread.*109.*$gdb_prompt $" {
+ fail "didn't see thread create"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "no info thread command"
+ }
+ timeout { fail "timeout" }
+}
+
+fix_timeout
+gdb_test "clear" ".*Deleted breakpoint.*" ""
+
+# Now go on to the end of thread creation.
+#
+gdb_test "b 122" ".*" "set bpt 122"
+gdb_test "c" ".*New thread.*New thread.*New thread.*122.*" ""
+gdb_test "p \$pc" ".*" ""
+gdb_test "clear" ".*Deleted breakpoint.*" ""
+
+send_gdb "info thr\n"
+gdb_expect {
+ -re ".*7 system thread.*6 sys.*5.*1 system thread.*122.*$gdb_prompt $"
+ { pass "saw thread creates" }
+ -re ".*$gdb_prompt $"
+ { fail "no info thread command" }
+ timeout { fail "timeout" }
+}
+
+# Try a thread-specific breakpoint; we expect the other threads to
+# be waiting at this point.
+#
+gdb_test "thr 3" ".*Switching to thread.*ksleep.*" "thread switch"
+gdb_test "i th" ".*\\\* 3 system thread.*" "show new current thread"
+
+gdb_test "up" ".*lwp_cond_timedwait.*" ""
+gdb_test "up" ".*pthread_cond_wait.*" ""
+gdb_test "up" ".*worker.*144.*" ""
+
+gdb_test "b 145 th 3" ".*Breakpoint.*145.*" "set thread-specific bp"
+gdb_test "i b" ".*breakpoint.*breakpoint.*145 thread 3.*" "show thread-specific bp"
+
+gdb_test "c" ".*Breakpoint.*145.*145.*" "hit thread-specific bp"
+gdb_test "p \$pc" ".*" ""
+
+# Test thread apply command on thread specific data.
+#
+gdb_test "thre app all p \$pc" ".*Thread 7.*Thread 6.*Thread 5.*Thread 4.*Thread 3.*Thread 2.*Thread 1.*" "thread apply all"
+gdb_test "thr ap 1 3 5 p \$pc" ".*Thread 1.*Thread 3.*Thread 5.*" "thr app 1 3 5"
+
+# Switch again, and test that others continue on a "next"
+# This test _could_ fail due to timing issues, but that's
+# unlikely.
+#
+gdb_test "thr 7" ".*Switching to thread.*" ""
+
+# Make sure that "up" stops at __pthread_exit, or
+# __pthread_create, the pseudo-roots, and that we
+# only see that pseudo-root once.
+#
+send_gdb "bt\n"
+gdb_expect {
+ -re ".*Error accessing memory address.*" { fail "bt" }
+ -re ".*pthread_create.*pthread_create.*" { fail "bt" }
+ -re ".*worker.*pthread_create.*" { pass "bt" }
+ -re ".*pthread_exit.*" { pass "bt" }
+ timeout { fail "timeout on bt" }
+}
+
+gdb_test "up" ".*" ""
+gdb_test "up" ".*" ""
+gdb_test "up" ".*144.*" "Up 3"
+gdb_test "up" ".*pthread_.*" "Up 4"
+gdb_test "up" ".*Initial frame selected; you cannot go up.*" "catch end of thread stack"
+
+#=====================
+#
+# Things get iffy here; when we step, sometimes the step
+# completes, sometimes it doesn't. When it doesn't, we
+# hit a bp somewhere else and the step never completes
+# (wait_for_inferior just evaporates it).
+#
+# I think the right answer is that any failures here
+# should stick around to trigger later fixing.
+#
+# Here's the plan:
+#
+# Bps at 148 (5) and 154 (6) on thread 7 (two bps so we
+# see the difference between going around the loop and
+# reporting the same bp hit twice).
+#
+# Bp at 144 on thread 3.
+#
+# Step out of a library routine.
+#
+# Either the step will finish or a bp will hit. Try to
+# handle all the cases.
+#
+gdb_test "b 148 thr 7" ".*Breakpoint.*148.*" ""
+gdb_test "b 154 thr 7" ".*Breakpoint.*154.*" "set bpt 2"
+
+set hit_154_bp 0
+set hit_148_bp 0
+set hit_145_bp 0
+set step_completed 0
+
+# Expect zero hits
+#
+gdb_test "i b" ".*" ""
+
+send_gdb "n\n"
+gdb_expect {
+ -re ".*Single stepping.*_lwp_cond_timedwait.*$gdb_prompt $" {
+ send_gdb "thr\n"
+ gdb_expect {
+ -re ".*is 7.*$gdb_prompt $" {
+ set step_completed 1
+ pass "completed step in library code"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "completed step in library code, but in wrong thread"
+ }
+ timeout { fail "timeout" }
+ }
+ }
+ -re ".*Single stepping.*Switched to thread 3.*Breakpoint.*$gdb_prompt $" {
+ pass "step cancelled; hit bp due to thread parallelism"
+ set hit_145_bp 1
+ }
+ -re ".*Single stepping.*Switched to thread 7.*Breakpoint.*148.*$gdb_prompt $" {
+ pass "step cancelled; hit bp due to thread parallelism"
+ set hit_148_bp 1
+ }
+ -re ".*Single stepping.*Switched to thread 7.*Breakpoint.*154.*$gdb_prompt $" {
+ pass "step cancelled; hit bp due to thread parallelism"
+ set hit_154_bp 1
+ }
+ -re ".*$gdb_prompt $" {
+ send_gdb "thr\n"
+ gdb_expect {
+ -re ".*is 7.*$gdb_prompt $" {
+ fail "No event?"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "No event"
+ }
+ timeout { fail "timeout" }
+ }
+ }
+ timeout { fail "timeout" }
+}
+
+# Sometimes used to get SIGTRAP here; that should be fixed
+#
+
+# Expect appropriate hits of bpt; too much work to parse
+# result and check...
+#
+gdb_test "i b" ".*" ""
+
+send_gdb "c\n"
+gdb_expect {
+ -re ".*SIGTRAP.*$gdb_prompt $" {
+ fail "got SIGTRAP"
+ }
+ -re ".*Switched to thread 7.*Breakpoint.*154.*$gdb_prompt $" {
+ if { $hit_154_bp == 1 } {
+ fail "re-hit old bp"
+ } else {
+ pass "continue; hit parallel event after continue"
+ }
+ set hit_154_bp 1
+ }
+ -re ".*Switched to thread 7.*Breakpoint.*148.*$gdb_prompt $" {
+ if { $hit_148_bp == 1 } {
+ fail "re-hit old bp"
+ } else {
+ pass "continue; hit parallel event after continue"
+ }
+ set hit_148_bp 1
+ }
+ -re ".*Breakpoint.*154.*$gdb_prompt $" {
+ if { $hit_154_bp == 1 } {
+ fail "re-hit old bp"
+ } else {
+ send_gdb "thr\n"
+ gdb_expect {
+ -re ".*is 7.*$gdb_prompt $" {
+ pass "continue; hit parallel event after continue"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "hit bp in wrong thread"
+ }
+ timeout { fail "timeout" }
+ }
+ }
+ set hit_154_bp 1
+ }
+ -re ".*Breakpoint.*148.*$gdb_prompt $" {
+ if { $hit_148_bp == 1 } {
+ fail "re-hit old bp"
+ } else {
+ send_gdb "thr\n"
+ gdb_expect {
+ -re ".*is 7.*$gdb_prompt $" {
+ pass "continue; hit parallel event after continue"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "hit bp in wrong thread"
+ }
+ timeout { fail "timeout" }
+ }
+ }
+ set hit_148_bp 1
+ }
+ -re ".*Breakpoint.*145.*$gdb_prompt $" {
+ if { $hit_145_bp == 1 } {
+ fail "re-hit old bp"
+ } else {
+ send_gdb "thr\n"
+ gdb_expect {
+ -re ".*is 3.*$gdb_prompt $" {
+ pass "continue; hit parallel event after continue"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "hit bp in wrong thread"
+ }
+ timeout { fail "timeout" }
+ }
+ }
+ set hit_145_bp 1
+ }
+ -re ".*_lwp_cond_timedwait.*$gdb_prompt $" {
+ pass "continue; hit step completion after continue"
+ }
+ -re ".*Program exited normally.*" {
+ fail "Program ended? HOW?"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "Unexpected event"
+ }
+ timeout { fail "timeout" }
+}
+
+# There are a number of places we _could_ be now;
+# this is the price of really running in parallel.
+#
+send_gdb "n\n"
+gdb_expect {
+ -re ".*Switched to thread 7.*pthread_cond_wait.*$gdb_prompt $" {
+ if { $step_completed } {
+ fail "step already completed"
+ } else {
+ pass "finish step"
+ }
+ }
+ -re ".*pthread_cond_wait.*$gdb_prompt $" {
+ #
+ # Unlikely, but we might finish the range step from inside
+ # ksleep, before anything else.
+ #
+ if { $step_completed } {
+ fail "step already completed"
+ } else {
+ send_gdb "thr\n"
+ gdb_expect {
+ -re ".*is 7.*$gdb_prompt $" {
+ pass "finish step"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "step in wrong thread"
+ }
+ timeout { fail "timeout" }
+ }
+ }
+ }
+ -re ".*Switched to thread.*Breakpoint.*145.*$gdb_prompt $" {
+ pass "auto-switch thread"
+ }
+ -re ".*Breakpoint.*145.*$gdb_prompt $" {
+ pass "auto-switch not needed, ok"
+ }
+ -re ".*140.*while.*n_pile.*$gdb_prompt $" {
+ #
+ # This is just going around the loop from the 154 bp.
+ #
+ send_gdb "thr\n"
+ gdb_expect {
+ -re ".*is 7.*$gdb_prompt $" {
+ pass "finish step"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "step in wrong thread"
+ }
+ timeout { fail "timeout" }
+ }
+ }
+ -re ".*149.*ptr = wp.*pile.*$gdb_prompt $" {
+ #
+ # This is just going around the loop from the 148 bp.
+ #
+ if { $hit_154_bp } {
+ send_gdb "thr\n"
+ gdb_expect {
+ -re ".*is 7.*$gdb_prompt $" {
+ pass "finish step"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "step in wrong thread"
+ }
+ timeout { fail "timeout" }
+ }
+ } else {
+ pass "step from 149 but didn't hit it first"
+ }
+ }
+ -re ".*Breakpoint 5.*154.*$gdb_prompt $" {
+ gdb_test "i b" ".*" ""
+ if { $hit_154_bp } {
+ fail "hit bp again?"
+ } else {
+ pass "hit bp"
+ }
+ }
+ -re ".*Breakpoint 5.*148.*$gdb_prompt $" {
+ gdb_test "i b" ".*" ""
+ if { $hit_148_bp } {
+ fail "hit bp again?"
+ } else {
+ pass "hit bp"
+ }
+ }
+ -re ".*$gdb_prompt $" {
+ fail "no step finished"
+ }
+ timeout { fail "timeout on 'next'" }
+}
+
+# Let's get into some kind of known state again.
+#
+gdb_test "thr 7" ".*" ""
+gdb_test "info thread" ".*" ""
+#gdb_test "i b" ".*" ""
+
+# Leave breakpoint "154 thr 7" as only live bp.
+#
+gdb_test "d 1" ".*" "del main bp"
+gdb_test "d 4" ".*" "thread-specific bpt delete"
+gdb_test "d 5" ".*" "other bp delete"
+send_gdb "i b\n"
+gdb_expect {
+ -re ".*breakpoint.*breakpoint.*$gdb_prompt $" {
+ fail "more than one bp left"
+ }
+ -re ".*breakpoint.*154.*thread.*7.*$gdb_prompt $" {
+ pass "Only one bp left"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "Wrong or no bp left"
+ }
+ timeout { fail "timeout on info b" }
+}
+
+send_gdb "c\n"
+gdb_expect {
+ -re ".*SIGTRAP.*Switched to thread.*$gdb_prompt $" {
+ fail "SIGTRAP error; lost thread-specific bpt"
+ }
+ -re ".*SIGTRAP.*Switched to thread.*154.*$gdb_prompt $" {
+ fail "SIGTRAP, but hit right thread-specific bpt"
+ }
+ -re ".*Switched to thread.*Breakpoint.*154.*$gdb_prompt $" {
+ pass "auto-switch back"
+ }
+ -re ".*Breakpoint.*154.*$gdb_prompt $" {
+ pass "step to bp"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "auto-switch back"
+ }
+ -re ".*Program exited normally.*$gdb_prompt $" {
+ fail "step lost"
+ }
+ timeout {
+ fail "timeout"
+ }
+}
+fix_timeout
+
+gdb_test "cle" ".*Deleted breakpoint.*" "delete last breakpoint"
+
+# Sometimes get SIGTRAP here. Continue sometimes gets another...
+#
+send_gdb "c\n"
+gdb_expect {
+ -re ".*SIGTRAP.*154.*154.*$gdb_prompt $" {
+ fail "SIGTRAP on deleted bp 154 "
+ send_gdb "c\n"
+ gdb_expect {
+ -re ".*$gdb_prompt $" { pass "fixup"}
+ timeout { fail "fixup" }
+ }
+ }
+ -re ".*SIGTRAP.*144.*145.*$gdb_prompt $" {
+ fail "SIGTRAP on deleted bp 145 "
+ send_gdb "c\n"
+ gdb_expect {
+ -re ".*$gdb_prompt $" { pass "fixup"}
+ timeout { fail "fixup" }
+ }
+ }
+ -re ".*SIGTRAP.*148.*148.*$gdb_prompt $" {
+ fail "SIGTRAP on deleted bp 148 "
+ send_gdb "c\n"
+ gdb_expect {
+ -re ".*$gdb_prompt $" { pass "fixup"}
+ timeout { fail "fixup" }
+ }
+ }
+ -re ".*SIGTRAP.*$gdb_prompt $" {
+ fail "unknown SIGTRAP"
+ send_gdb "c\n"
+ gdb_expect {
+ -re ".*$gdb_prompt $" { pass "fixup"}
+ timeout { fail "fixup" }
+ }
+ }
+ -re ".*Program exited.*$gdb_prompt $" {
+ pass "run to end"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "run to end"
+ send_gdb "c\n"
+ gdb_expect {
+ -re ".*$gdb_prompt $" { pass "fixup"}
+ timeout { fail "fixup" }
+ }
+ }
+ timeout { fail "timeout" }
+}
+
+gdb_test "p \$pc" ".*No registers.*" "program done"
+
+# Done!
+#
+gdb_exit
+
+set timeout $oldtimeout
+set verbose $oldverbose
+
+# execute_anywhere "rm -f ${binfile}"
+#
+return 0
+
diff --git a/gdb/testsuite/gdb.hp/reg-test.exp b/gdb/testsuite/gdb.hp/reg-test.exp
new file mode 100644
index 00000000000..4bdc3069293
--- /dev/null
+++ b/gdb/testsuite/gdb.hp/reg-test.exp
@@ -0,0 +1,190 @@
+# Copyright (C) 1998 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# Tests of wide register displays for GDB on HPPA 2.0 machines
+
+# use this to debug:
+#log_user 1
+
+if $tracelevel then {
+ strace $tracelevel
+ }
+
+if ![istarget "hppa*-*-*"] {
+ verbose "Wide register test ignored for non-hppa targets."
+ return
+}
+
+set testfile "reg_test"
+set srcfile ${testfile}.s
+set binfile ${objdir}/${subdir}/${testfile}
+
+# To build a pa 2.0 executable
+#
+# as -o reg_test reg_test.s
+# or
+# cc -g -o reg_test reg_test.s
+#
+# The +DA2.0N flag doesn't seem to be needed.
+#
+# Don't reject if there are warnings, as we expect this warning:
+#
+# (Warning) At least one PA 2.0 object file (pa2.0_test2.o) was detected.
+# The linked output may not run on a PA 1.x system.
+#
+
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+# test machine--there's no 2.0n architecture, so we have
+# to try to run the app.
+#
+send_gdb "break main\n"
+ gdb_expect {
+ -re "Breakpoint.*$gdb_prompt $" {
+ pass "initial set-up"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "initial set-up"
+ }
+ timeout {
+ fail "initial set-up (timeout)"
+ }
+ }
+
+send_gdb "run\n"
+ gdb_expect {
+ -re ".*Executable file incompatible with hardware.*$gdb_prompt $" {
+ # Not hppa2.0 machine
+ #
+ return 0
+ }
+ -re "Cannot exec.*$gdb_prompt $" {
+ # Not hppa2.0 machine
+ #
+ return 0
+ }
+ -re ".*Starting program:.*$gdb_prompt $" {
+ pass "Ready to start test"
+ }
+ timeout {
+ fail "initial set-up, part 2 (timeout)"
+ return 0
+ }
+ }
+
+# Let the program set known values. This secretly deletes
+# the breakpoint at main and re-runs to mainend.
+#
+runto mainend
+
+# Look for known values
+#
+gdb_test "info reg r1" "r1 1"
+gdb_test "info reg r4" "r4 2"
+gdb_test "info reg r5" "r5 4"
+gdb_test "info reg r6" "r6 8"
+gdb_test "info reg r7" "r7 10"
+gdb_test "info reg r8" "r8 20"
+gdb_test "info reg r9" "r9 40"
+gdb_test "info reg r10" "r10 80"
+gdb_test "info reg r11" "r11 100"
+gdb_test "info reg r12" "r12 200"
+gdb_test "info reg r13" "r13 400"
+gdb_test "info reg r14" "r14 800"
+gdb_test "info reg r15" "r15 1000"
+gdb_test "info reg r16" "r16 2000"
+
+# Two odd variants that GDB supports are:
+# "1" means "r1", and
+# "$1" means "r1"
+#
+gdb_test "info reg 1 4" "r1 1.*r4 2"
+gdb_test "info reg \$1" "r1 1"
+
+# Verify that GDB responds gracefully to a register ID number that
+# is out of range.
+#
+gdb_test "info reg 999" "999: invalid register"
+
+# Make sure the floating point status and error registers
+# don't show up as floating point numbers!
+#
+gdb_test "info reg fpsr" ".*fpsr 0.*" "fpsr"
+gdb_test "info reg fpe1" ".*fpe1 0.*" "fpe1"
+gdb_test "info reg fpe2" ".*fpe2 0.*" "fpe2"
+gdb_test "info reg fpe3" ".*fpe3 0.*" "fpe3"
+gdb_test "info reg fpe4" ".*fpe4 0.*" "fpe4"
+gdb_test "info reg fpe5" ".*fpe5 0.*" "fpe5"
+gdb_test "info reg fpe6" ".*fpe6 0.*" "fpe6"
+gdb_test "info reg fpe7" ".*fpe7 0.*" "fpe7"
+
+gdb_test "info reg fr4" ".*fr4.*(double precision).* 1"
+gdb_test "info reg fr5" ".*fr5.*(double precision).* 2"
+gdb_test "info reg fr6" ".*fr6.*(double precision).* 2"
+gdb_test "info reg fr7" ".*fr7.*(double precision).* 4"
+gdb_test "info reg fr8" ".*fr8.*(double precision).* 8"
+gdb_test "info reg fr9" ".*fr9.*(double precision).* 32"
+gdb_test "info reg fr10" ".*fr10.*(double precision).* 256"
+
+gdb_test "info reg r19" "r19 deadbeefbadcadee"
+
+# Need to add test of use of $<register-name>
+#
+# Q: How do you say a literal "$" in expect?
+# A: You say "\$". A literal "\" is "\\".
+#
+# Please note that this test will fail as long as we are running
+# in 32-bit mode: it will produce "$1 = 0xbadcadee". To fix it
+# would require building a real 64-bit gdb (expression evaluation,
+# in particular).
+#
+send_gdb "p/x \$r19\n"
+ gdb_expect {
+ -re ".*= 0xdeadbeefbadcadee.*$gdb_prompt $" {
+ pass "64-bit works"
+ }
+ -re ".*= 0xbadcadee.*$gdb_prompt $" {
+ pass "32-bit extract when using PRINT; expected but not good"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "didn't print any part of right value"
+ }
+ timeout {
+ fail "timeout on print"
+ }
+ }
+
+# Need to add tests of setting wide regs too. E.g.
+#
+# set $r4 = 0x1234567890123456
+# p/x $r4
+#
+
+# done
+#
+gdb_exit
+remote_exec build "rm -f ${binfile}"
+return 0
diff --git a/gdb/testsuite/gdb.hp/reg-test.s b/gdb/testsuite/gdb.hp/reg-test.s
new file mode 100644
index 00000000000..39bb5d863c1
--- /dev/null
+++ b/gdb/testsuite/gdb.hp/reg-test.s
@@ -0,0 +1,96 @@
+; assemble as "as -o reg_test.exe reg_test.s"
+; or
+; cc -g -o +DA2.0N
+;
+; PA-RISC 2.0 register contents test.
+;
+ .level 2.0
+
+ .code
+ .export main,ENTRY
+ .export mainend,CODE
+ .export lab1,CODE
+ .space $TEXT$
+ .subspa $CODE$
+
+main
+ .proc
+ .callinfo NO_CALLS,FRAME=0
+ .entry
+
+ ;; Test we have right register numbers
+ ;;
+ ADD %r0,%r0,%r1 ; 0
+ LDI 1,%r1 ; 1
+ ;;
+ ;; Don't put anything into r2 or r3--they are special registers.
+ ;;
+ ADD %r1,%r1,%r4 ; 2
+ ADD %r4,%r4,%r5 ; 4
+ ADD %r5,%r5,%r6 ; 8
+ ADD %r6,%r6,%r7 ; 16
+ ADD %r7,%r7,%r8 ; 32
+ ADD %r8,%r8,%r9 ; 64
+ ADD %r9,%r9,%r10 ; 128
+ ADD %r10,%r10,%r11 ; 256
+ ADD %r11,%r11,%r12 ; 512
+ ADD %r12,%r12,%r13 ; 1024
+ ADD %r13,%r13,%r14 ; 2048
+ ADD %r14,%r14,%r15 ; 4096
+ ADD %r15,%r15,%r16 ; 9192
+
+ ;; Test high bits, to be sure we show them.
+ ;;
+ LDI 0xde,%r19 ; "de"
+ DEPD,Z %r19,55,56,%r19 ; "de00"
+ LDI 0xad,%r18 ; "ad"
+ ADD %r18,%r19,%r19 ; "dead"
+ DEPD,Z %r19,55,56,%r19 ; "dead00"
+ LDI 0xbe,%r18 ; "be"
+ ADD %r18,%r19,%r19 ; "deadbe"
+ DEPD,Z %r19,55,56,%r19 ; "deadbe00"
+ LDI 0xef,%r18 ; "ef"
+ ADD %r18,%r19,%r19 ; "deadbeef"
+ ;
+ DEPD,Z %r19,55,56,%r19 ; "deadbeef00"
+ LDI 0xba,%r18 ; "ba"
+ ADD %r18,%r19,%r19 ; "deadbeefba"
+ DEPD,Z %r19,55,56,%r19 ; "deadbeefba00"
+ LDI 0xdc,%r18 ; "dc"
+ ADD %r18,%r19,%r19 ; "deadbeefbadc"
+ DEPD,Z %r19,55,56,%r19 ; "deadbeefbadc00"
+ LDI 0xad,%r18 ; "ad"
+ ADD %r18,%r19,%r19 ; "deadbeefbadcad"
+ DEPD,Z %r19,55,56,%r19 ; "deadbeefbadcad00"
+ LDI 0xee,%r18 ; "ee"
+ ADD %r18,%r19,%r19 ; "deadbeefbadcadee"
+
+lab1 ;; Test floating point registers
+ ;;
+ LDIL LR'one,%r22 ;
+ FLDD RR'one(%r22),%fr4 ; 1.0
+ FLDD RR'one+8(%r22),%fr5 ; 2.0
+ FLDD RR'one+8(%r22),%fr6 ; 2.0
+ FMPY,DBL %fr5,%fr6,%fr7 ; 4.0
+ FMPY,DBL %fr6,%fr7,%fr8 ; 8.0
+ FMPY,DBL %fr7,%fr8,%fr9 ; 32.0
+ FMPY,DBL %fr8,%fr9,%fr10 ; 256.0
+
+ ;; The NOP prevents anything from end.o or crt0.o from
+ ;; being appended immediately after "mainend". If that
+ ;; happens, then we may have other labels that have the
+ ;; same address as "mainend", and thus the debugger
+ ;; may symbolize this PC to something other than "mainend".
+mainend
+ NOP
+ .exit
+ .procend
+
+ .space $TEXT$
+ .subspa $CODE$
+ .subspa $LIT$ ;; <don't use> ,QUAD=0,ALIGN=8,ACCESS=0x2c,SORT=16
+one
+ .align 8
+ .stringz "?\xF0\x00\x00\x00\x00\x00\x00@\x00\x00\x00\x00\x00\x00"
+ .end
+
diff --git a/gdb/testsuite/gdb.hp/run-hp.c b/gdb/testsuite/gdb.hp/run-hp.c
new file mode 100644
index 00000000000..91da1e0fc16
--- /dev/null
+++ b/gdb/testsuite/gdb.hp/run-hp.c
@@ -0,0 +1,70 @@
+/*
+ * This simple classical example of recursion is useful for
+ * testing stack backtraces and such.
+ */
+
+#ifdef vxworks
+
+# include <stdio.h>
+
+/* VxWorks does not supply atoi. */
+static int
+atoi (z)
+ char *z;
+{
+ int i = 0;
+
+ while (*z >= '0' && *z <= '9')
+ i = i * 10 + (*z++ - '0');
+ return i;
+}
+
+/* I don't know of any way to pass an array to VxWorks. This function
+ can be called directly from gdb. */
+
+vxmain (arg)
+char *arg;
+{
+ char *argv[2];
+
+ argv[0] = "";
+ argv[1] = arg;
+ main (2, argv, (char **) 0);
+}
+
+#else /* ! vxworks */
+# include <stdio.h>
+#endif /* ! vxworks */
+
+main (argc, argv, envp)
+int argc;
+char *argv[], **envp;
+{
+#ifdef usestubs
+ set_debug_traps();
+ breakpoint();
+#endif
+#ifdef FAKEARGV
+ printf ("%d\n", factorial (1));
+#else
+ if (argc != 2) {
+ printf ("usage: factorial <number>\n");
+ return 1;
+ } else {
+ printf ("%d\n", factorial (atoi (argv[1])));
+ }
+#endif
+ return 0;
+}
+
+int factorial (value)
+int value;
+{
+ int local_var;
+
+ if (value > 1) {
+ value *= factorial (value - 1);
+ }
+ local_var = value;
+ return (value);
+}
diff --git a/gdb/testsuite/gdb.hp/sized-enum.c b/gdb/testsuite/gdb.hp/sized-enum.c
new file mode 100644
index 00000000000..a6d57881f48
--- /dev/null
+++ b/gdb/testsuite/gdb.hp/sized-enum.c
@@ -0,0 +1,43 @@
+
+enum Normal {
+ red,
+ blue,
+ green
+};
+
+short enum Small {
+ pink,
+ cyan,
+ grey
+};
+
+char enum Tiny {
+ orange,
+ yellow,
+ brown
+};
+
+
+main()
+{
+ enum Normal normal[3];
+ short enum Small small[3];
+ char enum Tiny tiny[3];
+ int i;
+
+ for (i=0; i < 3; i++)
+ {
+ normal[i] = (enum Normal) i;
+ small[i] = (short enum Small) i;
+ tiny[i] = (char enum Tiny) i;
+ }
+ normal[0] = 0; /* place to hang a breakpoint */
+}
+
+
+
+
+
+
+
+
diff --git a/gdb/testsuite/gdb.hp/sized-enum.exp b/gdb/testsuite/gdb.hp/sized-enum.exp
new file mode 100644
index 00000000000..191050ada4c
--- /dev/null
+++ b/gdb/testsuite/gdb.hp/sized-enum.exp
@@ -0,0 +1,162 @@
+# Copyright (C) 1997, 1998 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# GDB tests for sized enumerations
+
+# This is aimed at HP-UX systems. The HP C compiler
+# allows specifying "char" or "short" for an enum, to
+# indicate that it is 1 or 2 bytes long.
+
+# This file was written by Satish Pai <pai@apollo.hp.com>
+# 1997-09-24
+
+if $tracelevel then {
+ strace $tracelevel
+ }
+
+#
+# test running programs
+#
+set prms_id 0
+set bug_id 0
+
+set testfile "sized-enum"
+set srcfile ${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+
+if [get_compiler_info ${binfile}] {
+ return -1
+}
+
+if {[skip_hp_tests $gcc_compiled]} then { continue }
+
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+#
+# set it up at a breakpoint so we can play with the variable values
+#
+
+if ![runto_main] then {
+ perror "couldn't run to breakpoint"
+ continue
+}
+
+# set a breakpoint and go there
+send_gdb "break 34\n"
+gdb_expect {
+ -re "Breakpoint \[0-9\] at.*$gdb_prompt $" { pass "set break 34" }
+ -re "$gdb_prompt $" { fail "set break 34" }
+ timeout { fail "(timeout) set break 34" }
+}
+send_gdb "continue\n"
+gdb_expect {
+ -re "Continuing\\.\r\n\r\nBreakpoint \[0-9\]*, main....at.*sized-enum\\.c:34\r\n34.*\r\n$gdb_prompt $" { pass "continue" }
+ -re "$gdb_prompt $" { fail "continue" }
+ timeout { fail "(timeout) continue" }
+}
+
+# print stuff
+send_gdb "print normal\n"
+gdb_expect {
+ -re "\\$\[0-9\]* = \\{red, blue, green\\}.*$gdb_prompt $" { pass "print normal" }
+ -re "$gdb_prompt $" { fail "print normal" }
+ timeout { fail "(timeout) print normal" }
+}
+send_gdb "print small\n"
+gdb_expect {
+ -re "\\$\[0-9\]* = \\{pink, cyan, grey\\}.*$gdb_prompt $" { pass "print small" }
+ -re "$gdb_prompt $" { fail "print small" }
+ timeout { fail "(timeout) print small" }
+}
+send_gdb "print tiny\n"
+gdb_expect {
+ -re "\\$\[0-9\]* = \\{orange, yellow, brown\\}.*$gdb_prompt $" { pass "print tiny" }
+ -re "$gdb_prompt $" { fail "print tiny" }
+ timeout { fail "(timeout) print tiny" }
+}
+
+# print type sizes
+send_gdb "print sizeof (Normal)\n"
+gdb_expect {
+ -re "\\$\[0-9\]* = 4.*$gdb_prompt $" { pass "print sizeof (Normal)" }
+ -re "$gdb_prompt $" { fail "print sizeof (Normal)" }
+ timeout { fail "(timeout) print sizeof (Normal)" }
+}
+send_gdb "print sizeof (Small)\n"
+gdb_expect {
+ -re "\\$\[0-9\]* = 2.*$gdb_prompt $" { pass "print sizeof (Small)" }
+ -re "$gdb_prompt $" { fail "print sizeof (Small)" }
+ timeout { fail "(timeout) print sizeof (Small)" }
+}
+send_gdb "print sizeof (Tiny)\n"
+gdb_expect {
+ -re "\\$\[0-9\]* = 1.*$gdb_prompt $" { pass "print sizeof (Tiny)" }
+ -re "$gdb_prompt $" { fail "print sizeof (Tiny)" }
+ timeout { fail "(timeout) print sizeof (Tiny)" }
+}
+
+# print types
+send_gdb "ptype normal\n"
+gdb_expect {
+ -re "type = enum Normal \\{red, blue, green\\} \\\[3\\\].*$gdb_prompt $" { pass "ptype normal" }
+ -re "$gdb_prompt $" { fail "ptype normal" }
+ timeout { fail "(timeout) ptype normal" }
+}
+send_gdb "ptype small\n"
+gdb_expect {
+ -re "type = short enum Small \\{pink, cyan, grey\\} \\\[3\\\].*$gdb_prompt $" { pass "ptype small" }
+ -re "$gdb_prompt $" { fail "ptype small" }
+ timeout { fail "(timeout) ptype small" }
+}
+send_gdb "ptype tiny\n"
+gdb_expect {
+ -re "type = char enum Tiny \\{orange, yellow, brown\\} \\\[3\\\].*$gdb_prompt $" { pass "ptype tiny" }
+ -re "$gdb_prompt $" { fail "ptype tiny" }
+ timeout { fail "(timeout) ptype tiny" }
+}
+
+# convert to int
+send_gdb "print (int) blue\n"
+gdb_expect {
+ -re "\\$\[0-9\]* = 1.*$gdb_prompt $" { pass "print (int) blue" }
+ -re "$gdb_prompt $" { fail "print (int) blue" }
+ timeout { fail "(timeout) print (int) blue" }
+}
+send_gdb "print (int) cyan\n"
+gdb_expect {
+ -re "\\$\[0-9\]* = 1.*$gdb_prompt $" { pass "print (int) cyan" }
+ -re "$gdb_prompt $" { fail "print (int) cyan" }
+ timeout { fail "(timeout) print (int) cyan" }
+}
+send_gdb "print (int) yellow\n"
+gdb_expect {
+ -re "\\$\[0-9\]* = 1.*$gdb_prompt $" { pass "print (int) yellow" }
+ -re "$gdb_prompt $" { fail "print (int) yellow" }
+ timeout { fail "(timeout) print (int) yellow" }
+}
+
+
+
diff --git a/gdb/testsuite/gdb.hp/so-thresh.exp b/gdb/testsuite/gdb.hp/so-thresh.exp
new file mode 100644
index 00000000000..1977e92a7d9
--- /dev/null
+++ b/gdb/testsuite/gdb.hp/so-thresh.exp
@@ -0,0 +1,362 @@
+# Copyright (C) 1997, 1998 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+if $tracelevel then {
+ strace $tracelevel
+ }
+
+set prms_id 0
+set bug_id 0
+
+# are we on a target board
+if ![isnative] then {
+ return
+}
+
+set testfile "so-thresh"
+set srcfile ${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+
+if [get_compiler_info ${binfile}] {
+ return -1
+}
+
+# This testcase is automatically generated, via the
+# gen-so-thresh program, which also should
+# live in this same directory.
+#
+# The generator produces:
+# - so-thresh.c
+# - 3 .c files named libXX-so-thresh.c
+# - a makefile named so-thresh.mk with a
+# target named "so-thresh" that will compile
+# and link the testcase
+#
+# Making with so-thresh.mk produces:
+# - so-thresh
+# - 3 shared libraries that are linked against, named
+# libXX-so-thresh.sl
+#
+# We build gen-so-thresh, run it, and then make with
+# the makefile it produces.
+#
+set genfile gen_${testfile}
+set gen_srcfile ${genfile}.c
+set gen_binfile ${genfile}
+set gen_makefile ${testfile}.mk
+
+# This testcase is relatively large, and therefore can take awhile to
+# load. We'd best set the timeout to something suitable, or we may
+# seem to fail...
+#
+set timeout 60
+
+# It's easiest to build and run the testcase in this directory. (Linking
+# against shlibs puts relative paths to them in the a.out, so it's best
+# if we remain in this directory for the entire test run.)
+#
+#cd gdb.base
+
+# Ensure that the testcase is built. This may cause the generator to
+# be built & run.
+#
+# Warning! The final link of this testcase is not for the
+# faint-hearted nor under-disked machine!
+#
+# ??rehrauer: I tried for a very long time to get make invoked
+# directly here, rather than invoking a script to do it. I
+# finally gave up in frustration; I'm not sure why it wouldn't
+# work that way, but this method DOES work, albeit clumsily.
+#
+
+send_user "Making with ${testfile}.mk ...\n"
+# remote_exec build "sh -c \\\"cd ${objdir}/${subdir}\\; make -v -f ${srcdir}/${subdir}/${testfile}.mk clean require_shlibs all SRCDIR=${srcdir}/${subdir} OBJDIR=${objdir}/${subdir}\\\""
+remote_exec build "sh -c \\\"cd ${objdir}/${subdir}\\; make -v -f ${srcdir}/${subdir}/${testfile}.mk clean require_shlibs all SRCDIR=${srcdir}/${subdir} OBJDIR=${objdir}/${subdir}\\\""
+
+# Only HP-UX (and any other platforms using SOM shared libraries, I
+# guess) interprets the auto-solib-add variable as a threshhold,
+# rather than a boolean that strictly enables or disables automatic
+# loading of shlib symbol tables.
+#
+# On HP-UX, it is the size threshhold (in megabytes) at which to
+# stop auto loading of symbol tables.
+#
+if ![istarget "hppa*-hp-hpux*"] then {
+ setup_xfail "*-*-*"
+}
+
+# Start with a fresh gdb
+#
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+# This is a test of gdb's ability on HP-UX to stop automatically
+# loading symbols of shared libraries, when the total size of the
+# debugger's symbol table reaches a specified threshhold.
+#
+
+# On HP-UX, the help text for auto-solib-add mentions that it
+# serves as a threshhold.
+#
+send_gdb "help set auto-solib-add\n"
+gdb_expect {
+ -re "Set autoloading size threshold .in megabytes. of shared library symbols.*
+If nonzero, symbols from all shared object libraries will be loaded.*
+automatically when the inferior begins execution or when the dynamic linker.*
+informs gdb that a new library has been loaded, until the symbol table.*
+of the program and libraries exceeds this threshold.*
+Otherwise, symbols must be loaded manually, using `sharedlibrary'.*$gdb_prompt $"\
+ {pass "help set auto-solib-add"}
+ -re "$gdb_prompt $"\
+ {fail "help set auto-solib-add"}
+ timeout {fail "(timeout) help set auto-solib-add"}
+}
+
+# On HP-UX, the threshhold is by default set to 50, which means
+# 50 megabytes.
+#
+send_gdb "show auto-solib-add\n"
+gdb_expect {
+ -re "Autoloading size threshold .in megabytes. of shared library symbols is 100.*$gdb_prompt $"\
+ {pass "show auto-solib-add (default is 100)"}
+ -re "$gdb_prompt $"\
+ {fail "show auto-solib-add (default is 100)"}
+ timeout {fail "(timeout) show auto-solib-add (default is 100)"}
+}
+
+send_gdb "set auto-solib-add 1\n"
+gdb_expect {
+ -re ".*$gdb_prompt $"
+ {pass "set auto-solib-add to 1"}
+ -re ".*$gdb_prompt $"
+ {fail "set auto-solib-add to 1"}
+ timeout {fail "(timeout) set auto-solib-add to 1"}
+}
+
+
+# We have manually verified that our testcase exceeds 1 Mbytes
+# of heap space in GDB to hold the symbols for the main program
+# and all associated linked-against libraries. Thus, when we
+# run to the program's main, and therefore notice all the linked-
+# against shlibs, we expect to hit the threshhold.
+#
+# (Note that we're not using the expect [runto main] function here,
+# 'cause we want to match on output from the run command.
+#
+send_gdb "break main\n"
+gdb_expect {
+ -re "Breakpoint \[0-9\]* at.*$gdb_prompt $"\
+ {pass "set break at main"}
+ -re "$gdb_prompt $"\
+ {fail "set break at main"}
+ timeout {fail "(timeout) set break at main"}
+}
+
+send_gdb "run\n"
+gdb_expect {
+ -re ".*warning. Symbols for some libraries have not been loaded, because.*
+doing so would exceed the size threshold specified by auto-solib-add.*
+To manually load symbols, use the 'sharedlibrary' command.*
+To raise the threshold, set auto-solib-add to a larger value and rerun.*
+the program.*$gdb_prompt $"\
+ {pass "run to main hit auto-solib-add threshold"}
+ -re "$gdb_prompt $"\
+ {fail "run to main hit auto-solib-add threshold"}
+ timeout {fail "(timeout) run to main hit auto-solib-add threshold"}
+}
+
+# Verify that "info share" mentions something about libraries whose
+# symbols weren't loaded.
+#
+# We'll assume that at least the last two shlib's symbols weren't
+# loaded. As a side-effect of matching this pattern, the text start
+# address of the last one is captured in expect_out(1,string).
+# (we'll need it for the 'add-symbol-file' command in a nonce...)
+#
+send_gdb "info sharedlibrary\n"
+gdb_expect {
+ -re ".*lib01_$testfile.sl .*symbols not loaded.*0x\[0-9\]* (0x\[0-9a-fA-F\]*).*$gdb_prompt $"\
+ { send_gdb "add-symbol-file lib02_$testfile.sl $expect_out(1,string)\n"
+ gdb_expect {
+ -re "add symbol table.*y or n.*$"\
+ {send_gdb "y\n"
+ gdb_expect {
+ -re "$gdb_prompt $" {pass "add-symbol-file and info sharedlib"}
+ timeout {fail "(timeout) add-symbol-file and info sharedlib"}
+ }}
+ -re "$gdb_prompt $"\
+ {fail "add-symbol-file and info sharedlib"}
+ timeout {fail "(timeout) add-symbol-file and info sharedlib"}
+ }
+ }
+ -re "$gdb_prompt $"\
+ {fail "info sharedlibrary shows shlibs with unloaded symbols"}
+ timeout {fail "(timeout) info sharedlibrary shows shlibs with unloaded symbols"}
+}
+
+# Verify that we can manually load the symbol table of a library
+# whose symbols weren't loaded. (We'll pick the last one.)
+#
+
+# I moved this test inside the one above, because the expect_out array is not ok if the
+# previous test has failed, and expect would error out (elz)
+#
+#send_gdb "add-symbol-file lib02_$testfile.sl $expect_out(1,string)\n"
+#gdb_expect {
+# -re "add symbol table.*y or n.*$"\
+# {send_gdb "y\n"
+# gdb_expect {
+# -re "$gdb_prompt $" {pass "add-symbol-file"}
+# timeout {fail "(timeout) add-symbol-file"}
+# }}
+# -re "$gdb_prompt $"\
+# {fail "add-symbol-file"}
+# timeout {fail "(timeout) add-symbol-file"}
+#}
+
+# Verify that we can manually load the symbols for all libraries
+# which weren't already loaded.
+#
+# Warning! On a machine with little free swap space, this may
+# fail!
+#
+send_gdb "sharedlibrary\n"
+gdb_expect {
+ -re "Reading symbols from.*done.*$gdb_prompt $"\
+ {pass "sharedlibrary"}
+ -re "$gdb_prompt $"\
+ {fail "sharedlibrary"}
+ timeout {fail "(timeout) sharedlibrary"}
+}
+
+# Rerun the program, this time verifying that we can set the
+# threshhold high enough to avoid hitting it.
+#
+# It appears that gdb isn't freeing memory when rerunning, as one
+# would expect. To avoid potentially hitting a virtual memory
+# ceiling, start with a fresh gdb.
+#
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+send_gdb "break main\n"
+gdb_expect {
+ -re "Breakpoint \[0-9\]* at.*$gdb_prompt $"\
+ {pass "set break at main"}
+ -re "$gdb_prompt $"\
+ {fail "set break at main"}
+ timeout {fail "(timeout) set break at main"}
+}
+
+send_gdb "set auto-solib-add 9999\n"
+gdb_expect {
+ -re "$gdb_prompt $"\
+ {pass "set auto-solib-add threshold to practical infinity"}
+ timeout {fail "(timeout) set auto-solib-add threshold to practical infinity"}
+}
+send_gdb "run\n"
+gdb_expect {
+ -re ".*warning. Symbols for some libraries have not been loaded, because.*
+doing so would exceed the size threshold specified by auto-solib-add.*
+To manually load symbols, use the 'sharedlibrary' command.*
+To raise the threshold, set auto-solib-add to a larger value and rerun.*
+the program.*$gdb_prompt $"\
+ {fail "rerun threshold at practical infinity (still hit threshold)"}
+ -re "$gdb_prompt $"\
+ {pass "rerun with threshold at practical infinity"}
+ timeout {fail "(timeout) rerun with threshold at practical infinity"}
+}
+
+# Rerun the program, this time altogether disabling the auto loading
+# feature. There should be no information at all about shared
+# libraries now.
+#
+# ??rehrauer: Personally, I'd call that a bug, since it doesn't give
+# you the ability to manually load single shlibs (you need the text
+# start address that 'info share' normall gives you). On the other
+# hand, one can easily choose to load them all...
+#
+# It appears that gdb isn't freeing memory when rerunning, as one
+# would expect. To avoid potentially hitting a virtual memory
+# ceiling, start with a fresh gdb.
+#
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+send_gdb "break main\n"
+gdb_expect {
+ -re "Breakpoint \[0-9\]* at.*$gdb_prompt $"\
+ {pass "set break at main"}
+ -re "$gdb_prompt $"\
+ {fail "set break at main"}
+ timeout {fail "(timeout) set break at main"}
+}
+
+send_gdb "set auto-solib-add 0\n"
+gdb_expect {
+ -re "$gdb_prompt $"\
+ {pass "set auto-solib-add threshold to 0"}
+ timeout {fail "(timeout) set auto-solib-add threshold to 0"}
+}
+send_gdb "run\n"
+gdb_expect {
+ -re ".*warning. Symbols for some libraries have not been loaded, because.*
+doing so would exceed the size threshold specified by auto-solib-add.*
+To manually load symbols, use the 'sharedlibrary' command.*
+To raise the threshold, set auto-solib-add to a larger value and rerun.*
+the program.*$gdb_prompt $"\
+ {fail "rerun threshold at 0 (still hit threshold)"}
+ -re "$gdb_prompt $"\
+ {pass "rerun with threshold at 0"}
+ timeout {fail "(timeout) rerun with threshold at 0"}
+}
+
+# Verify that we can still manually load symbols for all libraries.
+# (We'll assume that if the last shlib's symbols are loaded, that
+# all of them were.)
+#
+# Note that we set the GDB "height" variable to prevent GDB from
+# prompting
+#
+# Warning! On a machine with little free swap space, this may
+# fail!
+#
+send_gdb "set height 9999\n"
+gdb_expect {
+ -re "$gdb_prompt $"\
+ {pass "set screen page height to practical infinity"}
+ timeout {fail "(timeout) set screen page height to practical infinity"}
+}
+send_gdb "sharedlibrary\n"
+gdb_expect {
+ -re ".*Reading symbols from .*/lib02-so-thresh\\.sl\\.\\.\\.done\\..*$gdb_prompt $"\
+ {pass "manually load all symbols"}
+ -re "$gdb_prompt $"\
+ {fail "manually load all symbols"}
+ timeout {fail "(timeout) manually load all symbols"}
+}
+
+#cd ..
+return 0
diff --git a/gdb/testsuite/gdb.hp/so-thresh.linkopts b/gdb/testsuite/gdb.hp/so-thresh.linkopts
new file mode 100644
index 00000000000..547b4ebb1fe
--- /dev/null
+++ b/gdb/testsuite/gdb.hp/so-thresh.linkopts
@@ -0,0 +1,5 @@
+# Linker options for so-thresh test
+-l00-so-thresh
+-l01-so-thresh
+-l02-so-thresh
+
diff --git a/gdb/testsuite/gdb.hp/so-thresh.mk b/gdb/testsuite/gdb.hp/so-thresh.mk
new file mode 100644
index 00000000000..343185cbe86
--- /dev/null
+++ b/gdb/testsuite/gdb.hp/so-thresh.mk
@@ -0,0 +1,73 @@
+# Make file for so-thresh test
+
+OBJDIR=.
+SRCDIR=.
+CFLAGS = +DA1.1 -g
+
+# This is how to build this generator.
+gen-so-thresh.o: ${SRCDIR}/gen-so-thresh.c
+ $(CC) $(CFLAGS) -o gen-so-thresh.o -c ${SRCDIR}/gen-so-thresh.c
+gen-so-thresh: gen-so-thresh.o
+ $(CC) $(CFLAGS) -o gen-so-thresh gen-so-thresh.o
+
+# This is how to run this generator.
+# This target should be made before the 'all' target,
+# to ensure that the shlib sources are all available.
+require_shlibs: gen-so-thresh
+ if ! [ -a lib00-so-thresh.c ] ; then \
+ gen-so-thresh ; \
+ fi
+ if ! [ -a lib01-so-thresh.c ] ; then \
+ gen-so-thresh ; \
+ fi
+ if ! [ -a lib02-so-thresh.c ] ; then \
+ gen-so-thresh ; \
+ fi
+
+# This is how to build all the shlibs.
+# Be sure to first make the require_shlibs target!
+lib00-so-thresh.o: lib00-so-thresh.c
+ $(CC) $(CFLAGS) +Z -o lib00-so-thresh.o -c lib00-so-thresh.c
+lib00-so-thresh.sl: lib00-so-thresh.o
+ $(LD) $(LDFLAGS) -b -o lib00-so-thresh.sl lib00-so-thresh.o
+lib01-so-thresh.o: lib01-so-thresh.c
+ $(CC) $(CFLAGS) +Z -o lib01-so-thresh.o -c lib01-so-thresh.c
+lib01-so-thresh.sl: lib01-so-thresh.o
+ $(LD) $(LDFLAGS) -b -o lib01-so-thresh.sl lib01-so-thresh.o
+lib02-so-thresh.o: lib02-so-thresh.c
+ $(CC) $(CFLAGS) +Z -o lib02-so-thresh.o -c lib02-so-thresh.c
+lib02-so-thresh.sl: lib02-so-thresh.o
+ $(LD) $(LDFLAGS) -b -o lib02-so-thresh.sl lib02-so-thresh.o
+
+
+
+
+# For convenience, here's names for all pieces of all shlibs.
+SHLIB_SOURCES = \
+ lib00-so-thresh.c \
+ lib01-so-thresh.c \
+ lib02-so-thresh.c
+
+SHLIB_OBJECTS = $(SHLIB_SOURCES:.c=.o)
+SHLIBS = $(SHLIB_SOURCES:.c=.sl)
+SHLIB_NAMES = $(SHLIB_SOURCES:.c=)
+EXECUTABLES = $(SHLIBS) gen-so-thresh so-thresh
+OBJECT_FILES = $(SHLIB_OBJECTS) gen-so-thresh.o so-thresh.o
+
+shlib_objects: $(SHLIB_OBJECTS)
+shlibs: $(SHLIBS)
+
+# This is how to build the debuggable testcase that uses the shlibs.
+so-thresh.o: so-thresh.c
+ $(CC) $(CFLAGS) -o so-thresh.o -c so-thresh.c
+so-thresh: shlibs so-thresh.o
+ $(LD) $(LDFLAGS) -o so-thresh -lc -L${OBJDIR} -c so-thresh.linkopts /opt/langtools/lib/end.o /lib/crt0.o so-thresh.o
+
+# Yeah, but you should first make the require_shlibs target!
+all: so-thresh gen-so-thresh
+
+# To remove everything built via this makefile...
+clean:
+ rm -f lib0*-so-thresh.*
+ rm -f *.o gen-so-thresh so-thresh.linkopts so-thresh.c
+ rm -f so-thresh
diff --git a/gdb/testsuite/gdb.hp/so-thresh.sh b/gdb/testsuite/gdb.hp/so-thresh.sh
new file mode 100755
index 00000000000..dc90270a1e1
--- /dev/null
+++ b/gdb/testsuite/gdb.hp/so-thresh.sh
@@ -0,0 +1,12 @@
+#!/bin/ksh
+#
+# This script is a "wrapper" to use the so-thresh.mk
+# Makefile. See the comments in so-thresh.exp
+# regarding why this script exists.
+#
+
+#set -o xtrace
+#set -o verbose
+
+MAKEFLAGS=
+make -v -f so-thresh.mk require_shlibs all
diff --git a/gdb/testsuite/gdb.hp/start-stop.c b/gdb/testsuite/gdb.hp/start-stop.c
new file mode 100644
index 00000000000..dcf2c7ebb10
--- /dev/null
+++ b/gdb/testsuite/gdb.hp/start-stop.c
@@ -0,0 +1,161 @@
+/* BeginSourceFile start_stop.c
+
+ This file creates and deletes threads, so that wdb
+ can be tested on thread delete.
+
+ To compile:
+
+ cc -Ae +DA1.0 -g -o start_stop -lpthread start_stop.c
+
+ To run:
+
+ start_stop --normal run
+ start_stop 1 --waits in each thread to keep it alive.
+*/
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <assert.h>
+#include <pthread.h>
+
+#define TRUE 1
+#define FALSE 0
+#define OUTER_LOOP_COUNT 3
+#define N_THREADS 3
+#define MAX_LOCAL_VAL 40
+
+/* Uncomment to turn on debugging output */
+/* #define START_DEBUG */
+
+/* True if waiting for attach.
+ */
+int wait_here;
+
+/* Thing to check for debugging purposes.
+*/
+int a_global = 0;
+
+/* Thread-local storage.
+ */
+__thread int a_thread_local;
+
+/* Check the results of thread-local storage.
+ */
+int thread_local_val[ N_THREADS ];
+int val_debugger_saw[ N_THREADS ];
+
+/* Routine for each thread to run, does nothing.
+ */
+void *spin( vp )
+ void * vp;
+{
+ int me = (int) vp;
+ int i;
+
+#ifdef START_DEBUG
+ printf( "== In thread %d\n", me );
+#endif
+
+ a_global++;
+
+ a_thread_local = 0;
+ for( i = 0; i < a_global; i++ ) {
+ a_thread_local += i;
+ }
+
+ thread_local_val[ me ] = a_thread_local; /* Line 67 */
+
+ printf( "== Thread %d, a_thread_local is %d\n",
+ (int) vp, a_thread_local );
+
+ if( wait_here ) {
+ /* Extend life of thread to extend life of thread-local var.
+ * This makes life easier for human debugging (though you'd
+ * probably want to make the delay longer).
+ */
+ sleep( 5 );
+ }
+}
+
+void
+do_pass( pass )
+ int pass;
+{
+ int i;
+ pthread_t t[ N_THREADS ];
+ int err;
+
+ for( i = 0; i < N_THREADS; i++) {
+ thread_local_val[i] = 0;
+ val_debugger_saw[i] = 0;
+ }
+
+ /* Start N_THREADS threads, then join them so
+ * that they are terminated.
+ */
+ for( i = 0; i < N_THREADS; i++ ) {
+ err = pthread_create( &t[i], NULL, spin, (void *)i );
+ if( err != 0 ) {
+ printf( "== Start/stop, error in thread %d create\n", i );
+ }
+ }
+
+ for( i = 0; i < N_THREADS; i++ ) {
+ err = pthread_join(t[i], NULL ); /* Line 105 */
+ if( err != 0 ) { /* Line 106 */
+ printf( "== Start/stop, error in thread %d join\n", i );
+ }
+ }
+
+ i = 10; /* Line 109. Null line for setting bpts on. */
+
+/*#ifdef START_DEBUG*/
+ for( i = 0; i < N_THREADS; i++) {
+ printf( " Local in thread %d was %d, debugger saw %d\n",
+ i, thread_local_val[i], val_debugger_saw[i] );
+ }
+ printf( "== Pass %d done\n", pass );
+/*#endif*/
+
+}
+
+void
+do_it()
+{
+ /* We want to start some threads and then
+ * end them, and then do it again and again
+ */
+ int i;
+ int dummy;
+
+ for( i = 0; i < OUTER_LOOP_COUNT; i++ ) {
+ do_pass( i );
+ dummy = i; /* Line 134, null line for setting bps on */
+ }
+}
+
+main( argc, argv )
+int argc;
+char **argv;
+{
+ wait_here = FALSE;
+ if((argc > 1) && (0 != argv )) {
+ if( 1 == atoi( argv[1] ) )
+ wait_here = TRUE;
+ }
+
+#ifdef START_DEBUG
+ printf( "== Test starting\n" );
+#endif
+
+ do_it();
+
+#ifdef START_DEBUG
+ printf( "== Test done\n" );
+#endif
+
+ return(0);
+}
+
+/* EndSourceFile */
diff --git a/gdb/testsuite/gdb.hp/start-stop.exp b/gdb/testsuite/gdb.hp/start-stop.exp
new file mode 100644
index 00000000000..4f70f51cede
--- /dev/null
+++ b/gdb/testsuite/gdb.hp/start-stop.exp
@@ -0,0 +1,360 @@
+# start_stop.exp -- Expect script to test a threaded pgm which has terminating threads
+# Copyright (C) 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# Comment out for now, since this test is (sometimes?) hanging on 11.0
+#
+# return 0
+
+# use this to debug:
+#
+#log_user 1
+
+# Thread stuff is _slow_; prepare for long waits.
+#
+# Further, this test has some "null" lines designed
+# to consume output from gdb that was too late to be
+# matched (sequence is "gdb_test" sends; timeout and
+# on to next send; result finally comes in; mismatch).
+#
+# The null command is 'gdb_test "p \$pc" ".*" ""'
+# NOTE: this command undoes any up/down stuff!
+#
+proc pre_timeout {} {
+ global timeout
+
+ set timeout [expr "$timeout + 100"]
+}
+
+proc post_timeout {} {
+ global timeout
+ global oldtimeout
+
+ set timeout $oldtimeout
+ gdb_test "p \$pc" ".*" ""
+}
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+if { ![istarget "hppa*-*-hpux10.30"] && ![istarget "hppa*-*-hpux11.*"] } {
+ verbose "HPUX thread test ignored for non-hppa or pre-HP/UX-10.30 targets."
+ return 0
+}
+
+set testfile start-stop
+set srcfile ${srcdir}/${subdir}/${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+
+if [get_compiler_info ${binfile}] {
+ return -1
+}
+
+# To build the executable we need to link against the thread library.
+#
+# cc -Ae -g -o start-stop -lpthread start-stop.c
+#
+#compile "${srcfile} -Ae -g -lpthread -o ${binfile}"
+
+if {$gcc_compiled == 0} {
+ set additional_flags "additional_flags=-Ae"
+} else {
+ set additional_flags ""
+}
+
+if { [gdb_compile "${srcdir}/${subdir}/${testfile}.c" "${binfile}.o" object [list debug $additional_flags]] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+remote_exec build "ld /usr/ccs/lib/crt0.o ${binfile}.o -lcl -lpthread -lc /opt/langtools/lib/end.o -o ${binfile}"
+
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+
+gdb_load ${binfile}
+if ![runto_main] then {
+ fail "Can't run to main"
+ return 0
+}
+
+set oldtimeout $timeout
+#set timeout [expr "$timeout + 200"]
+set oldverbose $verbose
+#set verbose 40
+
+gdb_test "b do_pass" ".*" "set do_pass bp"
+gdb_test "c" ".*Breakpoint.*do_pass.*" "run to do_pass"
+
+# Should be only one thread.
+#
+pre_timeout
+send_gdb "info thread\n"
+gdb_expect {
+ -re ".*2 process.*$gdb_prompt $" { fail "Old code for 'thread.c'" }
+ -re ".*2 system thread.*1 sys.*$gdb_prompt $" { fail "Too many threads" }
+ -re ".*1 system thread.*$gdb_prompt $" { pass "Just one thread" }
+ -re ".*$gdb_prompt $" { fail "no thread info" }
+ timeout { fail "timeout on info thread 1" }
+}
+post_timeout
+
+# Run to a point after the thread creates (105 is just
+# before the first join).
+#
+# The "== Thread" stuff is output from the computing threads.
+#
+gdb_test "b 105" ".*Breakpoint.*" "set 105 bp"
+
+pre_timeout
+send_gdb "c\n"
+gdb_expect {
+ -re ".*== Thread.*== Thread.*== Thread.*105.*$gdb_prompt $" {
+ pass "new threads created and ended"
+ set threads_exist 0
+ }
+ -re ".*== Thread.*== Thread.*105.*$gdb_prompt $" {
+ pass "new threads created and ended"
+ set threads_exist 1
+ }
+ -re ".*== Thread.*.*105.*$gdb_prompt $" {
+ pass "new threads created and ended"
+ set threads_exist 2
+ }
+ -re ".*New thread.*New th.*New th.*105.*$gdb_prompt $" {
+ pass "new threads created"
+ set threads_exist 3
+ }
+ -re ".*Breakpoint.*105.*$gdb_prompt $" {
+ set threads_exist 0
+ fail "didn't see any threads"
+ }
+ -re ".*$gdb_prompt $" {
+ set threads_exist 0
+ fail "didn't even hit bp"
+ }
+ timeout {
+ set threads_exist -1
+ fail "timeout on continue"
+ }
+}
+
+# Look at the threads again. We expect that some of
+# the threads may have already finished execution.
+#
+send_gdb "info thread\n"
+gdb_expect {
+ -re ".*4.*3.*2.* 1.*thread.*$gdb_prompt $" { set seen_threads 3 }
+ -re ".*3.*2.* 1.*thread.*$gdb_prompt $" { set seen_threads 2 }
+ -re ".*2.* 1.*thread.*$gdb_prompt $" { set seen_threads 1 }
+ -re ".* 1.*thread.*$gdb_prompt $" { set seen_threads 0 }
+ -re ".*$gdb_prompt $" { set seen_threads 0 }
+ timeout {
+ set seen_threads -10
+ fail "timeout on second info thread"
+ }
+}
+post_timeout
+
+if { $seen_threads == $threads_exist } {
+ pass "saw all threads that existed"
+} else {
+ if { $seen_threads > $threads_exist } {
+ fail "may have seen threads that didn't finish exiting yet"
+ } else {
+ fail "didn't see live threads"
+ }
+}
+
+gdb_test "cle" ".*Deleted.*" "del bp at 105"
+
+# Check that threads are being consumed at the join call.
+# We expect to join three times. If we ever see the bp at
+# 111, we've gone too far.
+#
+gdb_test "b 106" ".*Breakpoint.*106.*" "set bp at 106"
+gdb_test "b 111" ".*Breakpoint.*111.*" "set bp at 111"
+
+# This one is sure: we're already in the loop.
+#
+gdb_test "c" ".*Breakpoint.*106.*" "hit bp at 106 1st time, 2 left"
+
+# Did we go around the loop again?
+#
+send_gdb "c\n"
+gdb_expect {
+ -re ".*Breakpoint.*111.*" {
+ fail "didn't join right 1"
+ gdb_test "cle" ".*" ""
+ }
+ -re ".*Breakpoint.*106.*" {
+ pass "hit bp at 106 2nd time, 1 left"
+ send_gdb "c\n"
+ gdb_expect {
+ -re ".*Breakpoint.*111.*" {
+ fail "didn't join right 2"
+ gdb_test "cle" ".*" ""
+ }
+ -re ".*Breakpoint.*106.*" {
+ pass "hit bp at 106 3rd time, 0 left"
+ gdb_test "cle" ".*" ""
+ gdb_test "c" ".*Breakpoint.*111.*" ""
+ gdb_test "cle" ".*" ""
+ }
+ timeout { fail "timeout going around the loop"}
+ }
+ }
+ timeout { fail "timeout getting to 106"}
+}
+
+# Should only be one thread now.
+#
+pre_timeout
+send_gdb "info thread\n"
+gdb_expect {
+ -re ".*2 system thread.*1 sys.*$gdb_prompt $" { fail "Too many threads" }
+ -re ".*1 system th.*$gdb_prompt $" { pass "Just one thread" }
+ -re ".*$gdb_prompt $" { pass "One thread shown as no threads, ok" }
+ timeout { fail "timeout third info thread" }
+}
+post_timeout
+
+#============================= Begin pass 2 ===========
+#
+# Ok, go around again
+#
+gdb_test "c" ".*Breakpoint.*do_pass.*" "hit do_pass bp again 2"
+gdb_test "b 105" ".*Breakpoint.*" "set 105 bp 2"
+
+pre_timeout
+send_gdb "c\n"
+gdb_expect {
+ -re ".*== Thread.*== Thread.*== Thread.*$gdb_prompt $" {
+ pass "new threads created and ended 2"
+ set threads_exist 0
+ }
+ -re ".*== Thread.*== Thread.*$gdb_prompt $" {
+ pass "new threads created and ended 2"
+ set threads_exist 1
+ }
+ -re ".*== Thread.*$gdb_prompt $" {
+ pass "new threads created and ended 2"
+ set threads_exist 2
+ }
+ -re ".*New system thread.*New sys.*New.*105.*$gdb_prompt $" {
+ pass "new threads created 2"
+ set threads_exist 3
+ }
+ timeout {
+ set threads_exist -1
+ fail "timeout on continue 2"
+ }
+}
+
+# Look at the threads again. We expect that some of
+# the threads may have already finished execution.
+#
+send_gdb "info thread\n"
+gdb_expect {
+ -re ".*4.*3.*2.* 1.*thread.*$gdb_prompt $" { set seen_threads 3 }
+ -re ".*3.*2.* 1.*thread.*$gdb_prompt $" { set seen_threads 2 }
+ -re ".*2.* 1.*thread.*$gdb_prompt $" { set seen_threads 1 }
+ -re ".* 1.*thread.*$gdb_prompt $" { set seen_threads 0 }
+ -re ".*$gdb_prompt $" { set seen_threads 0 }
+ timeout {
+ set seen_threads -10
+ fail "timeout on second info thread 2"
+ }
+}
+post_timeout
+
+if { $seen_threads == $threads_exist } {
+ pass "saw all threads that existed"
+} else {
+ if { $seen_threads > $threads_exist } {
+ fail "may have seen threads that didn't finish exiting yet 2"
+ } else {
+ fail "didn't see live threads 2"
+ }
+}
+
+gdb_test "cle" ".*Deleted.*" "del bp at 105 2"
+
+# Check that threads are being consumed at the join call.
+# We expect to join three times. If we ever see the bp at
+# 111, we've gone too far.
+#
+gdb_test "b 106" ".*Breakpoint.*106.*" "set bp at 106 2"
+gdb_test "b 111" ".*Breakpoint.*111.*" "set bp at 111 2"
+
+# This one is sure: we're already in the loop.
+#
+gdb_test "c" ".*Breakpoint.*106.*" "hit bp at 106 1st time, 2 left 2"
+
+# Did we go around the loop again?
+#
+send_gdb "c\n"
+gdb_expect {
+ -re ".*Breakpoint.*111.*" {
+ fail "didn't join right 1, pass 2"
+ gdb_test "cle" ".*" ""
+ }
+ -re ".*Breakpoint.*106.*" {
+ pass "hit bp at 106 2nd time, 1 left, pass 2"
+ send_gdb "c\n"
+ gdb_expect {
+ -re ".*Breakpoint.*111.*" {
+ fail "didn't join right 2, pass 2"
+ gdb_test "cle" ".*" ""
+ }
+ -re ".*Breakpoint.*106.*" {
+ pass "hit bp at 106 3rd time, 0 left, pass 2"
+ gdb_test "cle" ".*" ""
+ gdb_test "c" ".*Breakpoint.*111.*" ""
+ gdb_test "cle" ".*" ""
+ }
+ timeout { fail "timeout going around loop, pass 2"}
+ }
+ }
+ timeout { fail "timeout continue to 106, pass 2"}
+}
+
+# Should only be one thread now.
+#
+pre_timeout
+send_gdb "info thread\n"
+gdb_expect {
+ -re ".*2 system thread.*1 sys.*$gdb_prompt $" { fail "Too many threads, pass 2" }
+ -re ".*1 system thread.*$gdb_prompt $" { pass "Just one thread, pass 2" }
+ -re ".*$gdb_prompt $" { pass "One thread shown as no threads, ok, pass 2" }
+ timeout { fail "timeout last info thread, pass 2" }
+}
+post_timeout
+
+# Done!
+#
+gdb_exit
+
+set timeout $oldtimeout
+set verbose $oldverbose
+
+# execute_anywhere "rm -f ${binfile}"
+#
+return 0
diff --git a/gdb/testsuite/gdb.hp/sum.c b/gdb/testsuite/gdb.hp/sum.c
new file mode 100644
index 00000000000..c28afa53856
--- /dev/null
+++ b/gdb/testsuite/gdb.hp/sum.c
@@ -0,0 +1,15 @@
+/* This is a sample program for the HP/DDE debugger. */
+#include <stdio.h>
+
+#ifdef __STDC__
+int sum(int list[], int low, int high)
+#else
+int sum(list, low, high)
+int list[], low, high;
+#endif
+ {
+ int i, s = 0;
+ for (i = low; i <= high; i++)
+ s += list[i];
+ return(s);
+ }
diff --git a/gdb/testsuite/gdb.hp/templ-hp.cc b/gdb/testsuite/gdb.hp/templ-hp.cc
new file mode 100644
index 00000000000..25241dc6dbf
--- /dev/null
+++ b/gdb/testsuite/gdb.hp/templ-hp.cc
@@ -0,0 +1,785 @@
+/* This test code is from Wendell Baker (wbaker@comet.berkeley.edu) */
+
+#include <stddef.h>
+
+int a_i;
+char a_c;
+double a_d;
+
+typedef void *Pix;
+
+int
+f(int i)
+{ return 0; }
+
+int
+f(int i, char c)
+{ return 0; }
+
+int
+f(int i, char c, double d)
+{ return 0; }
+
+int
+f(int i, char c, double d, char *cs)
+{ return 0; }
+
+int
+f(int i, char c, double d, char *cs, void (*fig)(int, char))
+{ return 0; }
+
+int
+f(int i, char c, double d, char *cs, void (*fig)(char, int))
+{ return 0; }
+
+class R {
+public:
+ int i;
+};
+class S {
+public:
+ int i;
+};
+class T {
+public:
+ int i;
+};
+
+char g(char, const char, volatile char)
+{ return 'c'; }
+char g(R, char&, const char&, volatile char&)
+{ return 'c'; }
+char g(char*, const char*, volatile char*)
+{ return 'c'; }
+char g(S, char*&, const char*&, volatile char*&)
+{ return 'c'; }
+
+signed char g(T,signed char, const signed char, volatile signed char)
+{ return 'c'; }
+signed char g(T, R, signed char&, const signed char&, volatile signed char&)
+{ return 'c'; }
+signed char g(T, signed char*, const signed char*, volatile signed char*)
+{ return 'c'; }
+signed char g(T, S, signed char*&, const signed char*&, volatile signed char*&)
+{ return 'c'; }
+
+unsigned char g(unsigned char, const unsigned char, volatile unsigned char)
+{ return 'c'; }
+unsigned char g(R, unsigned char&, const unsigned char&, volatile unsigned char&)
+{ return 'c'; }
+unsigned char g(unsigned char*, const unsigned char*, volatile unsigned char*)
+{ return 'c'; }
+unsigned char g(S, unsigned char*&, const unsigned char*&, volatile unsigned char*&)
+{ return 'c'; }
+
+short g(short, const short, volatile short)
+{ return 0; }
+short g(R, short&, const short&, volatile short&)
+{ return 0; }
+short g(short*, const short*, volatile short*)
+{ return 0; }
+short g(S, short*&, const short*&, volatile short*&)
+{ return 0; }
+
+signed short g(T, signed short, const signed short, volatile signed short)
+{ return 0; }
+signed short g(T, R, signed short&, const signed short&, volatile signed short&)
+{ return 0; }
+signed short g(T, signed short*, const signed short*, volatile signed short*)
+{ return 0; }
+signed short g(T, S, double, signed short*&, const signed short*&, volatile signed short*&)
+{ return 0; }
+
+unsigned short g(unsigned short, const unsigned short, volatile unsigned short)
+{ return 0; }
+unsigned short g(R, unsigned short&, const unsigned short&, volatile unsigned short&)
+{ return 0; }
+unsigned short g(unsigned short*, const unsigned short*, volatile unsigned short*)
+{ return 0; }
+unsigned short g(S, unsigned short*&, const unsigned short*&, volatile unsigned short*&)
+{ return 0; }
+
+int g(int, const int, volatile int)
+{ return 0; }
+int g(R, int&, const int&, volatile int&)
+{ return 0; }
+int g(int*, const int*, volatile int*)
+{ return 0; }
+int g(S, int*&, const int*&, volatile int*&)
+{ return 0; }
+
+signed int g(T, signed int, const signed int, volatile signed int)
+{ return 0; }
+signed int g(T, R, signed int&, const signed int&, volatile signed int&)
+{ return 0; }
+signed int g(T, signed int*, const signed int*, volatile signed int*)
+{ return 0; }
+signed int g(T, S, signed int*&, const signed int*&, volatile signed int*&)
+{ return 0; }
+
+unsigned int g(unsigned int, const unsigned int, volatile unsigned int)
+{ return 0; }
+unsigned int g(R, unsigned int&, const unsigned int&, volatile unsigned int&)
+{ return 0; }
+unsigned int g(unsigned int*, const unsigned int*, volatile unsigned int*)
+{ return 0; }
+unsigned int g(S, unsigned int*&, const unsigned int*&, volatile unsigned int*&)
+{ return 0; }
+
+long g(long, const long, volatile long)
+{ return 0; }
+long g(R, long&, const long&, volatile long&)
+{ return 0; }
+long g(long*, const long*, volatile long*)
+{ return 0; }
+long g(S, long*&, const long*&, volatile long*&)
+{ return 0; }
+
+signed long g(T, signed long, const signed long, volatile signed long)
+{ return 0; }
+signed long g(T, R, signed long&, const signed long&, volatile signed long&)
+{ return 0; }
+signed long g(T, signed long*, const signed long*, volatile signed long*)
+{ return 0; }
+signed long g(T, S, signed long*&, const signed long*&, volatile signed long*&)
+{ return 0; }
+
+unsigned long g(unsigned long, const unsigned long, volatile unsigned long)
+{ return 0; }
+unsigned long g(S, unsigned long&, const unsigned long&, volatile unsigned long&)
+{ return 0; }
+unsigned long g(unsigned long*, const unsigned long*, volatile unsigned long*)
+{ return 0; }
+unsigned long g(S, unsigned long*&, const unsigned long*&, volatile unsigned long*&)
+{ return 0; }
+
+#ifdef __GNUC__
+long long g(long long, const long long, volatile long long)
+{ return 0; }
+long long g(S, long long&, const long long&, volatile long long&)
+{ return 0; }
+long long g(long long*, const long long*, volatile long long*)
+{ return 0; }
+long long g(R, long long*&, const long long*&, volatile long long*&)
+{ return 0; }
+
+signed long long g(T, signed long long, const signed long long, volatile signed long long)
+{ return 0; }
+signed long long g(T, R, signed long long&, const signed long long&, volatile signed long long&)
+{ return 0; }
+signed long long g(T, signed long long*, const signed long long*, volatile signed long long*)
+{ return 0; }
+signed long long g(T, S, signed long long*&, const signed long long*&, volatile signed long long*&)
+{ return 0; }
+
+unsigned long long g(unsigned long long, const unsigned long long, volatile unsigned long long)
+{ return 0; }
+unsigned long long g(R, unsigned long long*, const unsigned long long*, volatile unsigned long long*)
+{ return 0; }
+unsigned long long g(unsigned long long&, const unsigned long long&, volatile unsigned long long&)
+{ return 0; }
+unsigned long long g(S, unsigned long long*&, const unsigned long long*&, volatile unsigned long long*&)
+{ return 0; }
+#endif
+
+float g(float, const float, volatile float)
+{ return 0; }
+float g(char, float&, const float&, volatile float&)
+{ return 0; }
+float g(float*, const float*, volatile float*)
+{ return 0; }
+float g(char, float*&, const float*&, volatile float*&)
+{ return 0; }
+
+double g(double, const double, volatile double)
+{ return 0; }
+double g(char, double&, const double&, volatile double&)
+{ return 0; }
+double g(double*, const double*, volatile double*)
+{ return 0; }
+double g(char, double*&, const double*&, volatile double*&)
+{ return 0; }
+
+#ifdef __GNUC__
+long double g(long double, const long double, volatile long double)
+{ return 0; }
+long double g(char, long double&, const long double&, volatile long double&)
+{ return 0; }
+long double g(long double*, const long double*, volatile long double*)
+{ return 0; }
+long double g(char, long double*&, const long double*&, volatile long double*&)
+{ return 0; }
+#endif
+
+class c {
+public:
+ c(int) {};
+ int i;
+};
+
+class c g(c, const c, volatile c)
+{ return 0; }
+c g(char, c&, const c&, volatile c&)
+{ return 0; }
+c g(c*, const c*, volatile c*)
+{ return 0; }
+c g(char, c*&, const c*&, volatile c*&)
+{ return 0; }
+
+/*
+void h(char = 'a')
+{ }
+void h(char, signed char = 'a')
+{ }
+void h(unsigned char = 'a')
+{ }
+*/
+/*
+void h(char = (char)'a')
+{ }
+void h(char, signed char = (signed char)'a')
+{ }
+void h(unsigned char = (unsigned char)'a')
+{ }
+
+
+void h(short = (short)43)
+{ }
+void h(char, signed short = (signed short)43)
+{ }
+void h(unsigned short = (unsigned short)43)
+{ }
+
+void h(int = (int)43)
+{ }
+void h(char, signed int = (signed int)43)
+{ }
+void h(unsigned int = (unsigned int)43)
+{ }
+
+
+void h(long = (long)43)
+{ }
+void h(char, signed long = (signed long)43)
+{ }
+void h(unsigned long = (unsigned long)43)
+{ }
+
+#ifdef __GNUC__
+void h(long long = 43)
+{ }
+void h(char, signed long long = 43)
+{ }
+void h(unsigned long long = 43)
+{ }
+#endif
+
+void h(float = 4.3e-10)
+{ }
+void h(double = 4.3)
+{ }
+#ifdef __GNUC__
+void h(long double = 4.33e33)
+{ }
+#endif
+*/
+void printf(const char *format, ... )
+{
+ // elipsis
+}
+
+class T1 {
+public:
+ static void* operator new(size_t);
+ static void operator delete(void *pointer);
+
+ void operator=(const T1&);
+ T1& operator=(int);
+
+ int operator==(int) const;
+ int operator==(const T1&) const;
+ int operator!=(int) const;
+ int operator!=(const T1&) const;
+
+ int operator<=(int) const;
+ int operator<=(const T1&) const;
+ int operator<(int) const;
+ int operator<(const T1&) const;
+ int operator>=(int) const;
+ int operator>=(const T1&) const;
+ int operator>(int) const;
+ int operator>(const T1&) const;
+
+ void operator+(int) const;
+ T1& operator+(const T1&) const;
+ void operator+=(int) const;
+ T1& operator+=(const T1&) const;
+
+ T1& operator++() const;
+
+ void operator-(int) const;
+ T1& operator-(const T1&) const;
+ void operator-=(int) const;
+ T1& operator-=(const T1&) const;
+
+ T1& operator--() const;
+
+ void operator*(int) const;
+ T1& operator*(const T1&) const;
+ void operator*=(int) const;
+ T1& operator*=(const T1&) const;
+
+ void operator/(int) const;
+ T1& operator/(const T1&) const;
+ void operator/=(int) const;
+ T1& operator/=(const T1&) const;
+
+ void operator%(int) const;
+ T1& operator%(const T1&) const;
+ void operator%=(int) const;
+ T1& operator%=(const T1&) const;
+
+ void operator&&(int) const;
+ T1& operator&&(const T1&) const;
+
+ void operator||(int) const;
+ T1& operator||(const T1&) const;
+
+ void operator&(int) const;
+ T1& operator&(const T1&) const;
+ void operator&=(int) const;
+ T1& operator&=(const T1&) const;
+
+ void operator|(int) const;
+ T1& operator|(const T1&) const;
+ void operator|=(int) const;
+ T1& operator|=(const T1&) const;
+
+ void operator^(int) const;
+ T1& operator^(const T1&) const;
+ void operator^=(int) const;
+ T1& operator^=(const T1&) const;
+
+ T1& operator!() const;
+ T1& operator~() const;
+};
+
+void*
+T1::operator new(size_t)
+{ return 0; }
+
+void
+T1::operator delete(void *pointer)
+{ }
+
+class T2 {
+public:
+ T2(int i): integer(i)
+ { }
+ int integer;
+};
+
+int operator==(const T2&, const T2&)
+{ return 0; }
+int operator==(const T2&, char)
+{ return 0; }
+int operator!=(const T2&, const T2&)
+{ return 0; }
+int operator!=(const T2&, char)
+{ return 0; }
+
+int operator<=(const T2&, const T2&)
+{ return 0; }
+int operator<=(const T2&, char)
+{ return 0; }
+int operator<(const T2&, const T2&)
+{ return 0; }
+int operator<(const T2&, char)
+{ return 0; }
+int operator>=(const T2&, const T2&)
+{ return 0; }
+int operator>=(const T2&, char)
+{ return 0; }
+int operator>(const T2&, const T2&)
+{ return 0; }
+int operator>(const T2&, char)
+{ return 0; }
+
+T2 operator+(const T2 t, int i)
+{ return t.integer + i; }
+T2 operator+(const T2 a, const T2& b)
+{ return a.integer + b.integer; }
+T2& operator+=(T2& t, int i)
+{ t.integer += i; return t; }
+T2& operator+=(T2& a, const T2& b)
+{ a.integer += b.integer; return a; }
+
+T2 operator-(const T2 t, int i)
+{ return t.integer - i; }
+T2 operator-(const T2 a, const T2& b)
+{ return a.integer - b.integer; }
+T2& operator-=(T2& t, int i)
+{ t.integer -= i; return t; }
+T2& operator-=(T2& a, const T2& b)
+{ a.integer -= b.integer; return a; }
+
+T2 operator*(const T2 t, int i)
+{ return t.integer * i; }
+T2 operator*(const T2 a, const T2& b)
+{ return a.integer * b.integer; }
+T2& operator*=(T2& t, int i)
+{ t.integer *= i; return t; }
+T2& operator*=(T2& a, const T2& b)
+{ a.integer *= b.integer; return a; }
+
+T2 operator/(const T2 t, int i)
+{ return t.integer / i; }
+T2 operator/(const T2 a, const T2& b)
+{ return a.integer / b.integer; }
+T2& operator/=(T2& t, int i)
+{ t.integer /= i; return t; }
+T2& operator/=(T2& a, const T2& b)
+{ a.integer /= b.integer; return a; }
+
+T2 operator%(const T2 t, int i)
+{ return t.integer % i; }
+T2 operator%(const T2 a, const T2& b)
+{ return a.integer % b.integer; }
+T2& operator%=(T2& t, int i)
+{ t.integer %= i; return t; }
+T2& operator%=(T2& a, const T2& b)
+{ a.integer %= b.integer; return a; }
+
+template<class T>
+class T5 {
+public:
+ T5(int);
+ T5(const T5<T>&);
+ ~T5();
+ static void* operator new(size_t);
+ static void operator delete(void *pointer);
+ int value();
+
+ static T X;
+ T x;
+ int val;
+};
+
+template<class T>
+T5<T>::T5(int v)
+{ val = v; }
+
+template<class T>
+T5<T>::T5(const T5<T>&)
+{}
+
+template<class T>
+T5<T>::~T5()
+{}
+
+template<class T>
+void*
+T5<T>::operator new(size_t)
+{ return 0; }
+
+template<class T>
+void
+T5<T>::operator delete(void *pointer)
+{ }
+
+template<class T>
+int
+T5<T>::value()
+{ return val; }
+
+
+#if ! defined(__GNUC__) || defined(GCC_BUG)
+template<class T>
+T T5<T>::X;
+#endif
+
+
+
+
+T5<char> t5c(1);
+T5<int> t5i(2);
+T5<int (*)(char, void *)> t5fi1(3);
+T5<int (*)(int, double **, void *)> t5fi2(4);
+
+
+
+
+
+
+class x {
+public:
+ int (*manage[5])(double,
+ void *(*malloc)(unsigned size),
+ void (*free)(void *pointer));
+ int (*device[5])(int open(const char *, unsigned mode, unsigned perms, int extra = 0),
+ int *(*read)(int fd, void *place, unsigned size),
+ int *(*write)(int fd, void *place, unsigned size),
+ void (*close)(int fd));
+};
+T5<x> t5x(5);
+
+#if !defined(__GNUC__) || (__GNUC__ >= 2 && __GNUC_MINOR__ >= 6)
+template class T5<char>;
+template class T5<int>;
+template class T5<int (*)(char, void *)>;
+template class T5<int (*)(int, double **, void *)>;
+template class T5<x>;
+#endif
+
+class T7 {
+public:
+ static int get();
+ static void put(int);
+};
+
+int
+T7::get()
+{ return 1; }
+
+void
+T7::put(int i)
+{
+ // nothing
+}
+
+// More template kinds. GDB 4.16 didn't handle these, but
+// Wildebeest does. Note: Assuming HP aCC is used to compile
+// this file; with g++ or HP cfront or other compilers the
+// demangling may not get done correctly.
+
+// Ordinary template, to be instantiated with different types
+template<class T>
+class Foo {
+public:
+ int x;
+ T t;
+ T foo (int, T);
+};
+
+
+template<class T> T Foo<T>::foo (int i, T tt)
+{
+ return tt;
+}
+
+// Template with int parameter
+
+template<class T, int sz>
+class Bar {
+public:
+ int x;
+ T t;
+ T bar (int, T);
+};
+
+
+template<class T, int sz> T Bar<T, sz>::bar (int i, T tt)
+{
+ if (i < sz)
+ return tt;
+ else
+ return 0;
+}
+
+// function template with int parameter
+template<class T> int dummy (T tt, int i)
+{
+ return tt;
+}
+
+// Template with partial specializations
+template<class T1, class T2>
+class Spec {
+public:
+ int x;
+ T1 spec (T2);
+};
+
+template<class T1, class T2>
+T1 Spec<T1, T2>::spec (T2 t2)
+{
+ return 0;
+}
+
+template<class T>
+class Spec<T, T*> {
+public:
+ int x;
+ T spec (T*);
+};
+
+template<class T>
+T Spec<T, T*>::spec (T * tp)
+{
+ return *tp;
+}
+
+// Template with char parameter
+template<class T, char sz>
+class Baz {
+public:
+ int x;
+ T t;
+ T baz (int, T);
+};
+
+template<class T, char sz> T Baz<T, sz>::baz (int i, T tt)
+{
+ if (i < sz)
+ return tt;
+ else
+ return 0;
+}
+
+// Template with char * parameter
+template<class T, char * sz>
+class Qux {
+public:
+ int x;
+ T t;
+ T qux (int, T);
+};
+
+template<class T, char * sz> T Qux<T, sz>::qux (int i, T tt)
+{
+ if (sz[0] == 'q')
+ return tt;
+ else
+ return 0;
+}
+
+// Template with a function pointer parameter
+template<class T, int (*f)(int) >
+class Qux1 {
+public:
+ int x;
+ T t;
+ T qux (int, T);
+};
+
+template<class T, int (*f)(int)> T Qux1<T, f>::qux (int i, T tt)
+{
+ if (f != 0)
+ return tt;
+ else
+ return 0;
+}
+
+// Some functions to provide as arguments to template
+int gf1 (int a) {
+ return a * 2 + 13;
+}
+int gf2 (int a) {
+ return a * 2 + 26;
+}
+
+char string[3];
+
+
+// Template for nested instantiations
+
+template<class T>
+class Garply {
+public:
+ int x;
+ T t;
+ T garply (int, T);
+};
+
+template<class T> T Garply<T>::garply (int i, T tt)
+{
+ if (i > x)
+ return tt;
+ else
+ {
+ x += i;
+ return tt;
+ }
+}
+
+
+int main()
+{
+ int i;
+#ifdef usestubs
+ set_debug_traps();
+ breakpoint();
+#endif
+ i = i + 1;
+
+ // New tests added here
+
+ Foo<int> fint;
+ Foo<char> fchar;
+ Foo<volatile char *> fvpchar;
+
+ Bar<int, 33> bint;
+ Bar<int, (4 > 3)> bint2;
+
+ Baz<int, 's'> bazint;
+ Baz<char, 'a'> bazint2;
+
+ Qux<char, string> quxint2;
+ Qux<int, string> quxint;
+
+ Qux1<int, gf1> qux11;
+
+ int x = fint.foo(33, 47);
+ char c = fchar.foo(33, 'x');
+ volatile char * cp = fvpchar.foo(33, 0);
+
+ int y = dummy<int> (400, 600);
+
+ int z = bint.bar(55, 66);
+ z += bint2.bar(55, 66);
+
+ c = bazint2.baz(4, 'y');
+ c = quxint2.qux(4, 'z');
+
+ y = bazint.baz(4,3);
+ y = quxint.qux(4, 22);
+ y += qux11.qux(4, 22);
+
+ y *= gf1(y) - gf2(y);
+
+ Spec<int, char> sic;
+ Spec<int, int *> siip;
+
+ sic.spec ('c');
+ siip.spec (&x);
+
+ Garply<int> f;
+ Garply<char> fc;
+ f.x = 13;
+
+ Garply<Garply<char> > nf;
+ nf.x = 31;
+
+ x = f.garply (3, 4);
+
+ fc = nf.garply (3, fc);
+
+ y = x + fc.x;
+
+
+ return 0;
+
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/gdb/testsuite/gdb.hp/templ-hp.exp b/gdb/testsuite/gdb.hp/templ-hp.exp
new file mode 100644
index 00000000000..64ca53daf76
--- /dev/null
+++ b/gdb/testsuite/gdb.hp/templ-hp.exp
@@ -0,0 +1,381 @@
+# Copyright (C) 1992, 1996, 1997 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+
+
+# More tests for different kinds of template parameters,
+# templates with partial specializations, nested templates, etc.
+# These have been tested only with HP aCC. They probably won't
+# work with other compilers because of differences in mangling
+# schemes.
+# Added by Satish Pai <pai@apollo.hp.com> 1997-09-25
+
+
+set ws "\[\r\n\t \]+"
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+set testfile "templ-hp"
+set srcfile ${testfile}.cc
+set binfile ${objdir}/${subdir}/${testfile}
+
+
+
+# Create and source the file that provides information about the compiler
+# used to compile the test case.
+
+if [get_compiler_info ${binfile} "c++"] {
+ return -1;
+}
+
+if {[skip_hp_tests $gcc_compiled]} then { continue }
+
+
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug c++}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+
+}
+
+#
+# Test printing of the types of templates.
+#
+
+proc test_ptype_of_templates {} {
+ global gdb_prompt
+
+ send_gdb "ptype T5<int>\n"
+ gdb_expect {
+ -re "type = class T5<int> \\{\r\n\[ \t\]*public:\r\n\[ \t\]*static int X;\r\n\[ \t\]*int x;\r\n\[ \t\]*int val;\r\n\r\n\[ \t\]*T5\\(int\\);\r\n\[ \t\]*T5\\(class T5<int> const &\\);\r\n\[ \t\]*void ~T5\\(int\\);\r\n\[ \t\]*static void \\* new\\(unsigned int\\);\r\n\[ \t\]*static void delete\\(void \\*\\);\r\n\[ \t\]*int value\\(void\\);\r\n\[ \t\]*\\}\r\n$gdb_prompt $" { pass "ptype T5<int>" }
+ -re ".*$gdb_prompt $" { fail "ptype T5<int>" }
+ timeout { fail "ptype T5<int> (timeout)" }
+ }
+
+ send_gdb "ptype t5i\n"
+ gdb_expect {
+ -re "type = class T5<int> \\{\r\n\[ \t\]*public:\r\n\[ \t\]*static int X;\r\n\[ \t\]*int x;\r\n\[ \t\]*int val;\r\n\r\n\[ \t\]*T5\\(int\\);\r\n\[ \t\]*T5\\(class T5<int> const &\\);\r\n\[ \t\]*void ~T5\\(int\\);\r\n\[ \t\]*static void \\* new\\(unsigned int\\);\r\n\[ \t\]*static void delete\\(void \\*\\);\r\n\[ \t\]*int value\\(void\\);\r\n\[ \t\]*\\}\r\n$gdb_prompt $" { pass "ptype t5i<int> 1" }
+ -re "type = class T5<int> \{.*public:.*static int X;.*int x;.*int val;.*.*T5 \\(int\\);.*.*void ~T5 \\(int\\).*.*.*int value \\(void\\);.*\}.*$gdb_prompt $" {
+ pass "ptype t5i"
+ }
+ -re ".*$gdb_prompt $" { fail "ptype t5i" }
+ timeout { fail "ptype t5i (timeout)" }
+ }
+}
+
+#
+# Test breakpoint setting on template methods.
+#
+
+proc test_template_breakpoints {} {
+ global gdb_prompt
+ global testfile
+ global srcdir
+
+ send_gdb "break T5<int>::T5\n"
+ gdb_expect {
+ -re "0. cancel.*\r\n.1. all.*\r\n.2. *.*\r\n.3. *.*\r\n> $" {
+ gdb_test "0" \
+ "cancelled" \
+ "constructor breakpoint"
+ }
+ -re ".0. cancel\r\n.1. all\r\n.2. T5<int>::T5\\(T5<int> const &\\) at .*/templates.cc:.*\r\n.3. T5<int>::T5\\(int\\) at .*/templates-hp.cc:.*\r\n> $" {
+ gdb_test "0" \
+ "cancelled" \
+ "constructor breakpoint"
+ }
+ -re ".*$gdb_prompt $" { fail "constructor breakpoint" }
+ default { fail "constructor breakpoint (timeout)" }
+ }
+
+ gdb_test "break T5<int>::~T5" \
+ "Breakpoint.*at.* file .*${testfile}.cc, line.*" \
+ "destructor breakpoint"
+
+ gdb_test "break T5<int>::value" \
+ "Breakpoint.*at.* file .*${testfile}.cc, line.*" \
+ "value method breakpoint"
+
+ delete_breakpoints
+}
+
+#
+# Test calling of template methods.
+#
+
+proc test_template_calls {} {
+ global gdb_prompt
+
+ send_gdb "print t5i.value()\n"
+ gdb_expect {
+ -re ".* = 2\r\n$gdb_prompt $" { pass "print t5i.value()" }
+ -re "Cannot invoke functions on this machine.*$gdb_prompt $" {
+ fail "print t5i.value()"
+ }
+ -re ".*$gdb_prompt $" { fail "print t5i.value()" }
+ timeout { fail "print t5i.value() (timeout)" }
+ }
+}
+
+
+proc do_tests {} {
+ global prms_id
+ global bug_id
+ global subdir
+ global objdir
+ global srcdir
+ global binfile
+ global prompt
+ global supports_template_debugging
+
+ set prms_id 0
+ set bug_id 0
+
+ # Start with a fresh gdb.
+
+ gdb_exit
+ gdb_start
+ gdb_reinitialize_dir $srcdir/$subdir
+ gdb_load $binfile
+
+ source ${binfile}.ci
+
+ if { !$supports_template_debugging } {
+ warning "compiler lacks debugging info for templates; tests suppressed." 0
+ return
+ }
+
+ test_ptype_of_templates
+ test_template_breakpoints
+
+ if [ runto_main ] {
+ test_template_calls
+ }
+}
+
+do_tests
+
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load $binfile
+
+# set it up at a breakpoint so we can play with the variable values
+#
+if ![runto_main] then {
+ perror "couldn't run to breakpoint"
+ continue
+}
+
+send_gdb "print fint\n"
+gdb_expect {
+ -re "\\$\[0-9\]* = \\{x = 0, t = 0\\}\r\n$gdb_prompt $" { pass "print fint" }
+ -re "$gdb_prompt $" { fail "print fint" }
+ timeout { fail "(timeout) print fint" }
+}
+
+send_gdb "print fvpchar\n"
+gdb_expect {
+ -re "\\$\[0-9\]* = \\{x = 0, t = 0x0\\}\r\n$gdb_prompt $" { pass "print fvpchar" }
+ -re "$gdb_prompt $" { fail "print fvpchar" }
+ timeout { fail "(timeout) print fvpchar" }
+}
+
+# Template Foo<T>
+
+send_gdb "ptype Foo\n"
+gdb_expect {
+ -re "type = template <(class |)T> (class |)Foo \\{\r\n\[ \t\]*public:\r\n\[ \t\]*int x;\r\n\[ \t\]*T t;\r\n\\}\r\ntemplate instantiations:\r\n\[ \t\]*(class |)Foo<volatile char \\*>\r\n\[ \t\]*(class |)Foo<char>\r\n\[ \t\]*(class |)Foo<int>\r\n$gdb_prompt $" { pass "ptype Foo" }
+ -re "$gdb_prompt $" { fail "ptype Foo" }
+ timeout { fail "(timeout) ptype Foo" }
+}
+
+# ptype Foo<int>
+
+send_gdb "ptype fint\n"
+gdb_expect {
+ -re "type = (class |)Foo<int> \\{\r\n\[ \t\]*public:\r\n\[ \t\]*int x;\r\n\[ \t\]*int t;\r\n\r\n\[ \t\]*int foo\\(int, int\\);\r\n\\}\r\n$gdb_prompt $" { pass "ptype fint" }
+ -re "$gdb_prompt $" { fail "ptype fint" }
+ timeout { fail "(timeout) ptype fint" }
+}
+
+# ptype Foo<char>
+
+send_gdb "ptype fchar\n"
+gdb_expect {
+ -re "type = (class |)Foo<char> \\{\r\n\[ \t\]*public:\r\n\[ \t\]*int x;\r\n\[ \t\]*char t;\r\n\r\n\[ \t\]*char foo\\(int, char\\);\r\n\\}\r\n$gdb_prompt $" { pass "ptype fchar" }
+ -re "$gdb_prompt $" { fail "ptype fchar" }
+ timeout { fail "(timeout) ptype fchar" }
+}
+
+# ptype Foo<volatile char *>
+
+send_gdb "ptype fvpchar\n"
+gdb_expect {
+ -re "type = (class |)Foo<volatile char \\*> \\{\r\n\[ \t\]*public:\r\n\[ \t\]*int x;\r\n\[ \t\]*volatile char \\*t;\r\n\r\n\[ \t\]*volatile char \\* foo\\(int, volatile char \\*\\);\r\n\\}\r\n$gdb_prompt $" { pass "ptype fvpchar" }
+ -re "$gdb_prompt $" { fail "ptype fvpchar" }
+ timeout { fail "(timeout) ptype fvpchar" }
+}
+
+# print a function from Foo<volatile char *>
+
+send_gdb "print Foo<volatile char *>::foo\n"
+gdb_expect {
+ -re "\\$\[0-9\]* = \\{volatile char \\*\\((class |)Foo<volatile char \\*> \\*, int, volatile char \\*\\)\\} $hex <Foo<volatile char \\*>::foo\\(int, volatile char \\*\\)>\r\n$gdb_prompt $" { pass "print Foo<volatile char *>::foo" }
+ -re "$gdb_prompt $" { fail "print Foo<volatile char *>::foo" }
+ timeout { fail "(timeout) print Foo<volatile char *>::foo" }
+}
+
+# Template Bar<T, int>
+
+send_gdb "ptype Bar\n"
+gdb_expect {
+ -re "type = template <(class |)T, (class |)sz> (class |)Bar \\{\r\n\[ \t\]*public:\r\n\[ \t\]*int x;\r\n\[ \t\]*T t;\r\n\\}\r\ntemplate instantiations:\r\n\[ \t\]*(class |)Bar<int,1>\r\n\[ \t\]*(class |)Bar<int,33>\r\n$gdb_prompt $" { pass "ptype Bar" }
+ -re "$gdb_prompt $" { fail "ptype Bar" }
+ timeout { fail "(timeout) ptype Bar" }
+}
+
+
+# ptype Bar<int,33>
+
+send_gdb "ptype bint\n"
+gdb_expect {
+ -re "type = (class |)Bar<int,33> \\{\r\n\[ \t\]*public:\r\n\[ \t\]*int x;\r\n\[ \t\]*int t;\r\n\r\n\[ \t\]*int bar\\(int, int\\);\r\n\\}\r\n$gdb_prompt $" { pass "ptype bint" }
+ -re "$gdb_prompt $" { fail "ptype bint" }
+ timeout { fail "(timeout) ptype bint" }
+}
+
+# ptype Bar<int, (4>3)>
+
+send_gdb "ptype bint2\n"
+gdb_expect {
+ -re "type = (class |)Bar<int,1> \\{\r\n\[ \t\]*public:\r\n\[ \t\]*int x;\r\n\[ \t\]*int t;\r\n\r\n\[ \t\]*int bar\\(int, int\\);\r\n\\}\r\n$gdb_prompt $" { pass "ptype bint2" }
+ -re "$gdb_prompt $" { fail "ptype bint2" }
+ timeout { fail "(timeout) ptype bint2" }
+}
+
+# Template Baz<T, char>
+
+send_gdb "ptype Baz\n"
+gdb_expect {
+ -re "type = template <(class |)T, (class |)sz> (class |)Baz \\{\r\n\[ \t\]*public:\r\n\[ \t\]*int x;\r\n\[ \t\]*T t;\r\n\\}\r\ntemplate instantiations:\r\n\[ \t\]*(class |)Baz<char,97>\r\n\[ \t\]*(class |)Baz<int,115>\r\n$gdb_prompt $" { pass "ptype Baz" }
+ -re "$gdb_prompt $" { fail "ptype Baz" }
+ timeout { fail "(timeout) ptype Baz" }
+}
+
+
+# ptype Baz<int, 's'>
+
+send_gdb "ptype bazint\n"
+gdb_expect {
+ -re "type = (class |)Baz<int,115> \\{\r\n\[ \t\]*public:\r\n\[ \t\]*int x;\r\n\[ \t\]*int t;\r\n\r\n\[ \t\]*int baz\\(int, int\\);\r\n\\}\r\n$gdb_prompt $" { pass "ptype bazint" }
+ -re "$gdb_prompt $" { fail "ptype bazint" }
+ timeout { fail "(timeout) ptype bazint" }
+}
+
+# ptype Baz<char, 'a'>
+
+send_gdb "ptype bazint2\n"
+gdb_expect {
+ -re "type = (class |)Baz<char,97> \\{\r\n\[ \t\]*public:\r\n\[ \t\]*int x;\r\n\[ \t\]*char t;\r\n\r\n\[ \t\]*char baz\\(int, char\\);\r\n\\}\r\n$gdb_prompt $" { pass "ptype bazint2" }
+ -re "$gdb_prompt $" { fail "ptype bazint2" }
+ timeout { fail "(timeout) ptype bazint2" }
+}
+
+# Template Qux<T, int (*f)(int) >
+
+send_gdb "ptype Qux\n"
+gdb_expect {
+ -re "type = template <(class |)T, (class |)sz> (class |)Qux \\{\r\n\[ \t\]*public:\r\n\[ \t\]*int x;\r\n\[ \t\]*T t;\r\n\\}\r\ntemplate instantiations:\r\n\[ \t\]*(class |)Qux<int,&string>\r\n\[ \t\]*(class |)Qux<char,&string>\r\n$gdb_prompt $" { pass "ptype Qux" }
+ -re "$gdb_prompt $" { fail "ptype Qux" }
+ timeout { fail "(timeout) ptype Qux" }
+}
+
+# pt Qux<int,&string>
+
+send_gdb "ptype quxint\n"
+gdb_expect {
+ -re "type = class Qux<int,&string> \\{\r\n\[ \t\]*public:\r\n\[ \t\]*int x;\r\n\[ \t\]*int t;\r\n\r\n\[ \t\]*int qux\\(int, int\\);\r\n\\}\r\n$gdb_prompt $" { pass "ptype quxint" }
+ -re "$gdb_prompt $" { fail "ptype quxint" }
+ timeout { fail "(timeout) ptype quxint" }
+}
+
+# pt Qux<char,0>
+
+send_gdb "ptype quxint2\n"
+gdb_expect {
+ -re "type = class Qux<char,&string> \\{\r\n\[ \t\]*public:\r\n\[ \t\]*int x;\r\n\[ \t\]*char t;\r\n\r\n\[ \t\]*char qux\\(int, char\\);\r\n\\}\r\n$gdb_prompt $" { pass "ptype quxint2" }
+ -re "$gdb_prompt $" { fail "ptype quxint2" }
+ timeout { fail "(timeout) ptype quxint2" }
+}
+
+# Template Spec<T1, T2>
+
+send_gdb "ptype Spec\n"
+gdb_expect {
+ -re "type = template <(class |)T1, (class |)T2> (class |)Spec \\{\r\n\[ \t\]*public:\r\n\[ \t\]*int x;\r\n\\}\r\ntemplate instantiations:\r\n\[ \t\]*(class |)Spec<int,int \\*>\r\n\[ \t\]*(class |)Spec<int,char>\r\n$gdb_prompt $" { pass "ptype Spec" }
+ -re "$gdb_prompt $" { fail "ptype Spec" }
+ timeout { fail "(timeout) ptype Spec" }
+}
+
+# pt Spec<char,0>
+
+send_gdb "ptype siip\n"
+gdb_expect {
+ -re "type = class Spec<int,int \\*> \\{\r\n\[ \t\]*public:\r\n\[ \t\]*int x;\r\n\r\n\[ \t\]*int spec\\(int \\*\\);\r\n\\}\r\n$gdb_prompt $" { pass "ptype siip" }
+ -re "$gdb_prompt $" { fail "ptype siip" }
+ timeout { fail "(timeout) ptype siip" }
+}
+
+# pt Garply<int>
+
+send_gdb "ptype Garply<int>\n"
+gdb_expect {
+ -re "type = class Garply<int> \\{\r\n\[ \t\]*public:\r\n\[ \t\]*int x;\r\n\[ \t\]*int t;\r\n\r\n\[ \t\]*int garply\\(int, int\\);\r\n\\}\r\n$gdb_prompt $" { pass "ptype Garply<int>" }
+ -re "$gdb_prompt $" { fail "ptype Garply<int>" }
+ timeout { fail "(timeout) ptype Garply<int>" }
+}
+
+# ptype of nested template name
+
+send_gdb "ptype Garply<Garply<char> >\n"
+gdb_expect {
+ -re "type = (class |)Garply<Garply<char> > \\{\r\n\[ \t\]*public:\r\n\[ \t\]*int x;\r\n\[ \t\]*(class |)Garply<char> t;\r\n\r\n\[ \t\]*(class |)Garply<char> garply\\(int, (class |)Garply<char>\\);\r\n\\}\r\n$gdb_prompt $" { pass "ptype Garply<Garply<char> >" }
+ -re "$gdb_prompt $" { fail "ptype Garply<Garply<char> >" }
+ timeout { fail "(timeout) ptype Garply<Garply<char> >" }
+}
+
+# print out a function from a nested template name
+
+send_gdb "print Garply<Garply<char> >::garply\n"
+gdb_expect {
+ -re "\\$\[0-9\]* = \\{(class |)Garply<char> \\((class |)Garply<Garply<char> > \\*, int, (class |)Garply<char>\\)\\} $hex <Garply<Garply<char>>::garply\\(int, (class |)Garply<char>\\)>\r\n$gdb_prompt $" { pass "print Garply<Garply<char> >::garply" }
+ -re ".*$gdb_prompt $" { fail "print Garply<Garply<char> >::garply" }
+ timeout { fail "print Garply<Garply<char> >::garply (timeout)" }
+}
+
+# UNFORTUNATELY, "break Garply<Garply<char> >::garply" doesn't yet work.
+
+#send_gdb "break Garply<Garply<char> >::garply
+#gdb_expect {
+# -re "Breakpoint \[0-9\]* at $hex: file .*templates.cc, line.*\r\n$gdb_prompt $" { pass "break Garply<Garply<char> >::garply" }
+# -re ".*$gdb_prompt $" { fail "break Garply<Garply<char> >::garply" }
+# timeout { fail "break Garply<Garply<char> >::garply (timeout)" }
+#}
diff --git a/gdb/testsuite/gdb.hp/thr-lib.c b/gdb/testsuite/gdb.hp/thr-lib.c
new file mode 100644
index 00000000000..15cd16829e1
--- /dev/null
+++ b/gdb/testsuite/gdb.hp/thr-lib.c
@@ -0,0 +1,79 @@
+/* Thread local in a library.
+*/
+#include "thr-lib.h"
+/*
+ * #define NTHREADS 4
+ * #define NUM_ELEMS 12
+ */
+
+extern void* adder( void * );
+
+pthread_mutex_t mutex; /* mutex for protecting global data total */
+
+int numbers[NUM_ELEMS] = {5, 4, 3, 2, 1, 6, 7, 8, 9, 10, 12, 11};
+int total = 0;
+
+int debugger_saw[NTHREADS][ELEMS_PER_THREAD]; /* [4][3] */
+int the_code_saw[NTHREADS][ELEMS_PER_THREAD];
+
+int get_number(i)
+int i;
+{
+ /* sleep to force context switch to another thread in non-MP system
+ * so that TLS symbols are used by multiple threads concurrently
+ * in some way.
+ */
+ sleep(1);
+ return numbers[i];
+}
+
+main()
+{
+ pthread_t thread[NTHREADS];
+ void *status;
+ int i, j, ret;
+
+ printf("== Thread: Test started\n");
+
+ for( i = 0; i < NTHREADS; i++ ) {
+ for( j = 0; j < ELEMS_PER_THREAD; j++ ) {
+ debugger_saw[i][j] = 0;
+ the_code_saw[i][j] = 0;
+ }
+ }
+
+ ret = pthread_mutex_init(&mutex, NULL);
+ if (ret != 0) {
+ printf("== Thread: pthread_mutex_init() error: %d\n", ret);
+ exit(1);
+ }
+
+ for (i=0; i < NTHREADS; i++) {
+ ret = pthread_create( &thread[i],
+ NULL,
+ adder,
+ (void *) i);
+ if (ret != 0) {
+ printf("== Thread: pthread_create() error: %d\n", ret);
+ exit(1);
+ }
+ printf("== Thread: thread %d created\n", i);
+ }
+
+ for (i=0; i < NTHREADS; i++) {
+ pthread_join( thread[i], &status);
+ }
+
+ printf("== Thread: total = %d\n", total); /* Expect "78" */
+
+ for( i = 0; i < NTHREADS; i++ ) {
+ for( j = 0; j < ELEMS_PER_THREAD; j++ ) {
+ printf( "== Thread: the debugger saw %d, the program saw %d\n",
+ debugger_saw[i][j],
+ the_code_saw[i][j] );
+ }
+ }
+
+ printf("== Thread: Test ended\n");
+ exit(0);
+}
diff --git a/gdb/testsuite/gdb.hp/thr-lib.exp b/gdb/testsuite/gdb.hp/thr-lib.exp
new file mode 100644
index 00000000000..53bf4668749
--- /dev/null
+++ b/gdb/testsuite/gdb.hp/thr-lib.exp
@@ -0,0 +1,234 @@
+# thr-lib.exp -- Expect script to test thread-local storage in lib
+# Copyright (C) 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# use this to debug:
+#
+#log_user 1
+
+# Thread stuff is _slow_; prepare for long waits.
+#
+# Further, this test has some "null" lines designed
+# to consume output from gdb that was too late to be
+# matched (sequence is "gdb_test" sends; timeout and
+# on to next send; result finally comes in; mismatch).
+#
+# The null command is 'gdb_test "p \$pc" ".*" ""'
+# NOTE: this command undoes any up/down stuff!
+#
+proc pre_timeout {} {
+ global timeout
+
+ set timeout [expr "$timeout + 100"]
+}
+
+proc post_timeout {} {
+ global timeout
+ global oldtimeout
+
+ set timeout $oldtimeout
+ gdb_test "p \$pc" ".*" ""
+}
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+if { ![istarget "hppa*-*-hpux10.30"] && ![istarget "hppa*-*-hpux11.*"] } {
+ verbose "HPUX thread test ignored for non-hppa or pre-HP/UX-10.30 targets."
+ return 0
+}
+
+set testfile thr-lib
+set srcfile ${srcdir}/${subdir}/${testfile}.c
+set libsrc ${srcdir}/${subdir}/${testfile}lib.c
+set mainobj ${objdir}/${testfile}.o
+set libobj ${objdir}/${testfile}lib.o
+set libsl ${objdir}/${subdir}/${testfile}lib.sl
+set binfile ${objdir}/${subdir}/${testfile}
+
+# To build the executable we need to do this:
+#
+# cc -c -Aa -g -D_HPUX_SOURCE -D_REENTRANT +DA1.0 ./gdb.hp/thr-lib.c
+# cc -c -Aa -g -D_HPUX_SOURCE -D_REENTRANT +DA1.0 +z ./gdb.hp/thr-liblib.c
+# ld -o thread_local_in_lib.lib.sl -b ./gdb.hp/thr-liblib.o
+# ld -a archive /opt/langtools/lib/crt0.o /opt/langtools/lib/end.o \
+# > thr-lib.o ./gdb.hp/thr-liblib.sl \
+# > -o thr-lib -lpthread -lc
+#
+remote_exec build "$CC ${srcfile} -c -Aa -g -D_HPUX_SOURCE -D_REENTRANT +DA1.0"
+remote_exec build "$CC ${libsrc} -c -Aa -g -D_HPUX_SOURCE -D_REENTRANT +DA1.0 +z"
+remote_exec build "ld -o ${libsl} -b ${libobj}"
+remote_exec build "ld -a archive /opt/langtools/lib/crt0.o /opt/langtools/lib/end.o ${mainobj} ${libsl} -lpthread -lc -o ${binfile}"
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+
+set oldtimeout $timeout
+#set timeout [expr "$timeout + 200"]
+set oldverbose $verbose
+
+gdb_load ${binfile}
+
+# Here we go: test various things.
+#
+gdb_test "b adder" ".*Cannot break on adder without a running program.*" "shared loc, needs to run"
+gdb_test "b main" ".*" ""
+gdb_test "run" ".*Breakpoint 1, main.*" ""
+
+# Set a bp to inspect the results
+#
+gdb_test "b 67" ".*Breakpoint 2.*" ""
+
+# get to a point where we can set the collection breakpoint.
+#
+gdb_test "tb adder" ".*Breakpoint 3.*line 47.*" "set bp in shared lib"
+gdb_test "c" ".*Switched to.*adder.*" "run to shared lib rtn"
+
+# Check locations of things
+#
+gdb_test "i ad sum" ".*Symbol \"sum\" is a thread-local variable.*offset.*from the thread base register mpsfu_high.*" "find sum"
+gdb_test "i add x" ".*Symbol \"x\" is a thread-local variable.*" "find x"
+
+# Set a breakpoint later on in "adder" and
+# collect the thread local's value.
+#
+gdb_test "b 61" ".*Breakpoint 4.*61.*" "Set collection bp"
+
+# extra check for grins, expect to hit "adder" in thread 2 first
+# but could be wrong...
+#
+gdb_test "info thread" ".*\\\* 2.*thread.*thread.*" "two threads"
+
+# Can't use "gdb_test", as it uses "$gdb_prompt $" in
+# testing the result. Our new prompt is ">", with
+# no trailing space, so we can't do this just by
+# changing "prompt".
+#
+# Anyway, I couldn't get expect to see the ">" prompt,
+# during the command addition, so I just punted.
+# _You_ are welcome to try, if you want!
+#
+send_gdb "commands 4\n"
+gdb_expect {
+ -re "(.*Type commands.*\"end\"\.\r\n\>)" {
+ pass "start commands"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "start commands"
+ }
+}
+
+# Assume we're in commands-input mode. (Self-debug stuff turned off)
+#
+send_gdb "silent\n"
+#send_gdb "p id\n"
+#send_gdb "p j\n"
+#send_gdb "p x\[j\]\n"
+send_gdb "set debugger_saw\[id\]\[j\] = x\[j\]\n"
+send_gdb "continue\n"
+send_gdb "end\n"
+
+gdb_expect {
+ -re ".*set.*cont.*$gdb_prompt $" {
+ pass "add commands"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "add commands"
+ }
+}
+
+# Check out of paranoia.
+#
+send_gdb "info break 4\n"
+gdb_expect {
+ -re ".*breakpoint.*set debugger_saw.*continue.*$gdb_prompt $" {
+ pass "Commands added"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "Commands not added."
+ }
+}
+
+# We now expect to run through the whole application
+# Since this'll run for while, set a generous timeout.
+#
+set timeout [expr "$timeout + 30"]
+send_gdb "c\n"
+gdb_expect {
+ -re ".*Program exited normally.*$gdb_prompt $" {
+ fail "program runaway"
+ }
+ -re ".*Breakpoint 2.*67.*$gdb_prompt $" {
+ pass "get to end"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "No progress?"
+ }
+ timeout { fail "timeout" }
+}
+set timeout $oldtimeout
+
+gdb_test "p debugger_saw" ".*5, 1, 9.*4, 6, 10.*3, 7, 12.*2, 8, 11.*" "check results"
+
+# Often only one misses; let's get detailed!
+#
+gdb_test "p debugger_saw\[0\]\[0\]" ".*= 5.*" "1"
+gdb_test "p debugger_saw\[0\]\[1\]" ".*= 1.*" "2"
+gdb_test "p debugger_saw\[0\]\[2\]" ".*= 9.*" "3"
+gdb_test "p debugger_saw\[1\]\[0\]" ".*= 4.*" "4"
+gdb_test "p debugger_saw\[1\]\[1\]" ".*= 6.*" "5"
+gdb_test "p debugger_saw\[1\]\[2\]" ".*= 10.*" "6"
+gdb_test "p debugger_saw\[2\]\[0\]" ".*= 3.*" "7"
+gdb_test "p debugger_saw\[2\]\[1\]" ".*= 7.*" "8"
+gdb_test "p debugger_saw\[2\]\[2\]" ".*= 12.*" "9"
+gdb_test "p debugger_saw\[3\]\[0\]" ".*= 2.*" "10"
+gdb_test "p debugger_saw\[3\]\[1\]" ".*= 8.*" "11"
+gdb_test "p debugger_saw\[3\]\[2\]" ".*= 11.*" "12"
+
+send_gdb "i th\n"
+gdb_expect {
+ -re ".* 1.*system thread.* 2.*system thread.*$gdb_prompt $" {
+ fail "Too many threads left"
+ }
+ -re ".*\\\* 1.*system thread.*main.*$gdb_prompt $" {
+ pass "Expect only base thread"
+ }
+ -re ".*No stack.*$gdb_prompt $" {
+ fail "runaway"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "Hunh?"
+ }
+ timeout { fail "timeout" }
+}
+
+gdb_test "c" ".*exited normally.*" "run to completion"
+
+# Done!
+#
+gdb_exit
+
+set timeout $oldtimeout
+set verbose $oldverbose
+
+# execute_anywhere "rm -f ${binfile}"
+#
+return 0
diff --git a/gdb/testsuite/gdb.hp/thr-lib.h b/gdb/testsuite/gdb.hp/thr-lib.h
new file mode 100644
index 00000000000..c9395dfd0ca
--- /dev/null
+++ b/gdb/testsuite/gdb.hp/thr-lib.h
@@ -0,0 +1,7 @@
+#include <stdio.h>
+#include <pthread.h>
+
+#define NTHREADS 4
+#define NUM_ELEMS 12
+
+#define ELEMS_PER_THREAD (NUM_ELEMS/NTHREADS)
diff --git a/gdb/testsuite/gdb.hp/thr-liblib.c b/gdb/testsuite/gdb.hp/thr-liblib.c
new file mode 100644
index 00000000000..a3effcc111f
--- /dev/null
+++ b/gdb/testsuite/gdb.hp/thr-liblib.c
@@ -0,0 +1,92 @@
+#include <stdio.h>
+
+/* Library code for thread local in lib test.
+*/
+#include "thr-lib.h"
+
+extern pthread_mutex_t mutex;
+extern int get_number();
+extern int total;
+extern int the_code_saw[NTHREADS][ELEMS_PER_THREAD];
+
+/* The debugger should see this without a declaration.
+ *
+ * extern int debugger_saw[NTHREADS][ELEMS_PER_THREAD];
+ */
+
+/* The actual thread locals.
+ */
+__thread int sum;
+__thread int x[ ELEMS_PER_THREAD ]; /* [3] */
+
+void sumup()
+{
+ int j;
+
+ sum = 0;
+ for (j = 0; j < ELEMS_PER_THREAD; j++) {
+ sum += x[j];
+ }
+
+ if( sum == x[0] )
+ /* It won't be "==", but this lets us set a breakpoint
+ * and look at the thread-local storage.
+ */
+ sum++;
+
+ x[0] = x[2]; /* Another no-op for debugger use */
+}
+
+void *adder( vid )
+ void * vid;
+{
+ int id;
+ int i, j;
+ int ret;
+
+ id = (int) vid;
+
+ /* printf( "== Thread: Welcome to adder %d\n", id ); */
+
+ for (j = 0; j < ELEMS_PER_THREAD; j++) {
+ x[j] = 0;
+ }
+
+ for (i = id, j = 0; i < NUM_ELEMS; i += NTHREADS, j++ ) {
+
+ /* printf( "== Thread: id %d, i %d, j %d\n", id, i, j );
+ fflush( stdout ); */
+
+ x[j] = get_number(i); /* {0,1,2,3} +0, +4, +8 */
+
+ /* Record for posterity; the debugger will gather
+ * the same data here, using "x[j]".
+ */
+ the_code_saw[ id ][ j ] = x[j];
+
+ /* printf( "== Thread %d, sample %d, val %d, i %d\n", id, j, x[j],i );
+ fflush( stdout ); */
+ }
+
+ sumup();
+ /* printf("== Thread: adder %d contributes total %d\n", id, sum); */
+
+ /* protect global data */
+ ret = pthread_mutex_lock(&mutex);
+ if (ret != 0) {
+ printf("== Thread: pthread_mutex_lock() error: %d\n", ret);
+ exit(1);
+ }
+
+ total += sum;
+
+ ret = pthread_mutex_unlock(&mutex);
+ if (ret != 0) {
+ printf("== Thread: pthread_mutex_unlock() error: %d\n", ret);
+ exit(1);
+ }
+
+ if( NTHREADS != 4 || ELEMS_PER_THREAD != 3 || NUM_ELEMS != 12 ) {
+ printf( "** ERROR in test code **\n" );
+ }
+}
diff --git a/gdb/testsuite/gdb.hp/thr-stg.exp b/gdb/testsuite/gdb.hp/thr-stg.exp
new file mode 100644
index 00000000000..19d69ee9297
--- /dev/null
+++ b/gdb/testsuite/gdb.hp/thr-stg.exp
@@ -0,0 +1,255 @@
+# thread_local_stg.exp -- Expect script to test thread-local storage
+# Copyright (C) 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# use this to debug:
+#
+#log_user 1
+
+# Thread stuff is _slow_; prepare for long waits.
+#
+# Further, this test has some "null" lines designed
+# to consume output from gdb that was too late to be
+# matched (sequence is "gdb_test" sends; timeout and
+# on to next send; result finally comes in; mismatch).
+#
+# The null command is 'gdb_test "p \$pc" ".*" ""'
+# NOTE: this command undoes any up/down stuff!
+#
+proc pre_timeout {} {
+ global timeout
+
+ set timeout [expr "$timeout + 100"]
+}
+
+proc post_timeout {} {
+ global timeout
+ global oldtimeout
+
+ set timeout $oldtimeout
+ gdb_test "p \$pc" ".*" ""
+}
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+if { ![istarget "hppa*-*-hpux10.30"] && ![istarget "hppa*-*-hpux11.*"] } {
+ verbose "HPUX thread test ignored for non-hppa or pre-HP/UX-10.30 targets."
+ return 0
+}
+
+set testfile start-stop
+set srcfile ${srcdir}/${subdir}/${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+
+if [get_compiler_info ${binfile}] {
+ return -1
+}
+
+# To build the executable we need to link against the thread library.
+#
+# cc -Ae -g -o start_stop -lpthread start_stop.c
+#
+#compile "${srcfile} -Ae -g -lpthread -o ${binfile}"
+
+if {$gcc_compiled == 0} {
+ set additional_flags "additional_flags=-Ae"
+} else {
+ set additional_flags ""
+}
+
+if { [gdb_compile "${srcdir}/${subdir}/${testfile}.c" "${binfile}.o" object [list debug $additional_flags]] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+remote_exec build "ld /usr/ccs/lib/crt0.o ${binfile}.o -lcl -lpthread -lc /opt/langtools/lib/end.o -o ${binfile}"
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+
+gdb_load ${binfile}
+if ![runto_main] then {
+ fail "Can't run to main"
+ return 0
+}
+
+set oldtimeout $timeout
+#set timeout [expr "$timeout + 200"]
+set oldverbose $verbose
+#set verbose 40
+
+gdb_test "b do_pass" ".*" "set do_pass bp"
+gdb_test "c" ".*do_pass.*" "run to do_pass"
+gdb_test "cle" ".*" ""
+
+# Set a breakpoint at the "spin" routine and
+# collect the thread local's value.
+#
+gdb_test "b 67" ".*Breakpoint 3.*67.*" "Set bp"
+
+# Can't use "gdb_test", as it uses "$gdb_prompt $" in
+# testing the result. Our new prompt is ">", with
+# no trailing space, so we can't do this just by
+# changing "prompt".
+#
+# Anyway, I couldn't get expect to see the ">" prompt,
+# during the command addition, so I just punted.
+# _You_ are welcome to try, if you want!
+#
+send_gdb "commands 3\n"
+gdb_expect {
+ -re "(.*Type commands.*\"end\"\.\r\n\>)" {
+ pass "start commands"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "start commands"
+ }
+}
+
+# Assume we're in commands-input mode.
+#
+send_gdb "silent\n"
+send_gdb "set val_debugger_saw\[me\] = a_thread_local\n"
+send_gdb "continue\n"
+send_gdb "end\n"
+
+gdb_expect {
+ -re ".*set.*cont.*$gdb_prompt $" {
+ pass "add commands"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "add commands"
+ }
+}
+
+# Check out of paranoia.
+#
+send_gdb "info break 3\n"
+gdb_expect {
+ -re ".*breakpoint.*set val_debugger.*continue.*$gdb_prompt $" {
+ pass "Commands added"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "Commands not added."
+ }
+}
+
+# Set a bp to inspect the results
+#
+gdb_test "b 134" ".*Breakpoint 4.*" ""
+
+# We now expect to run through a whole pass, seeing
+# specific results as noted below (actual gotten by
+# running application with debugging print statements
+# turned on.
+#
+# Since this'll run for while, set a generous timeout.
+#
+set timeout [expr "$timeout + 30"]
+send_gdb "c\n"
+gdb_expect {
+ -re ".*Program exited normally.*$gdb_prompt $" {
+ fail "program runaway"
+ }
+ -re ".*Pass 0 done.*Pass 1 done.*$gdb_prompt $" {
+ fail "program runaway 2"
+ }
+ -re ".*Pass 0 done.*Breakpoint 4.*134.*$gdb_prompt $" {
+ pass "get to end of first pass"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "No progress?"
+ }
+ timeout { fail "timeout" }
+}
+
+gdb_test "p val_debugger_saw" ".*0, 1, 3.*" "first pass"
+
+send_gdb "i th\n"
+gdb_expect {
+ -re ".* 1.*system thread.* 2.*system thread.*$gdb_prompt $" {
+ fail "Too many threads left"
+ }
+ -re ".*\\\* 1 system thread.*$gdb_prompt $" {
+ pass "Expect only base thread"
+ }
+ -re ".*No stack.*$gdb_prompt $" {
+ fail "runaway"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "Hunh?"
+ }
+ timeout { fail "timeout" }
+}
+
+gdb_test "i b" ".*4.*breakpoint.*134.*hit.*1 time.*" "Expect 134 bp to exist"
+
+gdb_test "c" ".*Breakpoint 4.*134.*" "get to end of second pass"
+gdb_test "p val_debugger_saw" ".*6, 10, 15.*" "second pass"
+
+gdb_test "c" ".*Breakpoint 4.*134.*" "get to end of third pass"
+gdb_test "p val_debugger_saw" ".*21, 28, 36.*" "third pass"
+
+gdb_test "info bre 3" ".*already hit 9 times.*" "count of silent bp hits"
+
+# Start over and do some "info address" stuff
+#
+send_gdb "d\n"
+gdb_expect {
+ -re ".*Delete all breakpoints.*$" {
+ send_gdb "y\n"
+ gdb_expect {
+ -re ".*$gdb_prompt $" {
+ pass "del bps"
+ }
+ }
+ }
+ -re ".*$gdb_prompt $" { fail "no question" }
+}
+
+gdb_test "b spin" ".*Breakpoint 5.*" ""
+
+send_gdb "r\n"
+gdb_expect {
+ -re ".*Start it from the beginning.*$" {
+ send_gdb "y\n"
+ gdb_expect {
+ -re ".*$gdb_prompt $" { pass "restart" }
+ }
+ }
+ -re ".*Starting program.*$gdb_prompt $" {
+ pass "restart after previous fails"
+ }
+ -re ".*$gdb_prompt $" { fail "Can't restart" }
+}
+gdb_test "i ad a_global" ".*a_global.*static storage at address.*" "i ad a_global"
+gdb_test "i add me" ".*me.*local variable at frame offset.*" "i ad me"
+gdb_test "i ad a_thread_local" ".*a_thread_local.*a thread-local variable at offset.*" "i ad a_thread_local"
+
+# Done!
+#
+gdb_exit
+
+set timeout $oldtimeout
+set verbose $oldverbose
+
+# execute_anywhere "rm -f ${binfile}"
+#
+return 0
diff --git a/gdb/testsuite/gdb.hp/vforked-program.c b/gdb/testsuite/gdb.hp/vforked-program.c
new file mode 100644
index 00000000000..52c6cd2bbfd
--- /dev/null
+++ b/gdb/testsuite/gdb.hp/vforked-program.c
@@ -0,0 +1,6 @@
+#include <stdio.h>
+
+main()
+{
+ printf("Hello from vforked_program...\n");
+}
diff --git a/gdb/testsuite/gdb.hp/virtfun-hp.cc b/gdb/testsuite/gdb.hp/virtfun-hp.cc
new file mode 100644
index 00000000000..6552a6233fc
--- /dev/null
+++ b/gdb/testsuite/gdb.hp/virtfun-hp.cc
@@ -0,0 +1,192 @@
+// Pls try the following program on virtual functions and try to do print on
+// most of the code in main(). Almost none of them works !
+
+//
+// The inheritance structure is:
+//
+// V : VA VB
+// A : (V)
+// B : A
+// D : AD (V)
+// C : (V)
+// E : B (V) D C
+//
+
+class VA
+{
+public:
+ int va;
+};
+
+class VB
+{
+public:
+ int vb;
+ int fvb();
+ virtual vvb();
+};
+
+class V : public VA, public VB
+{
+public:
+ int f();
+ virtual vv();
+ int w;
+};
+
+class A : virtual public V
+{
+public:
+ virtual int f();
+private:
+ int a;
+};
+
+class B : public A
+{
+public:
+ int f();
+private:
+ int b;
+};
+
+class C : public virtual V
+{
+public:
+ int c;
+};
+
+class AD
+{
+public:
+ virtual int vg() = 0;
+};
+
+class D : public AD, virtual public V
+{
+public:
+ static void s();
+ virtual int vg();
+ virtual int vd();
+ int fd();
+ int d;
+};
+
+class E : public B, virtual public V, public D, public C
+{
+public:
+ int f();
+ int vg();
+ int vv();
+ int e;
+};
+
+D dd;
+D* ppd = &dd;
+AD* pAd = &dd;
+
+A a;
+B b;
+C c;
+D d;
+E e;
+V v;
+VB vb;
+
+
+A* pAa = &a;
+A* pAe = &e;
+
+B* pBe = &e;
+
+D* pDd = &d;
+D* pDe = &e;
+
+V* pVa = &a;
+V* pVv = &v;
+V* pVe = &e;
+V* pVd = &d;
+
+AD* pADe = &e;
+
+E* pEe = &e;
+
+VB* pVB = &vb;
+
+void init()
+{
+ a.vb = 1;
+ b.vb = 2;
+ c.vb = 3;
+ d.vb = 4;
+ e.vb = 5;
+ v.vb = 6;
+ vb.vb = 7;
+
+ d.d = 1;
+ e.d = 2;
+}
+
+extern "C" printf(const char *, ...);
+
+int all_count = 0;
+int failed_count = 0;
+
+#define TEST(EXPR, EXPECTED) \
+ ret = EXPR; \
+ if (ret != EXPECTED) {\
+ printf("Failed %s is %d, should be %d!\n", #EXPR, ret, EXPECTED); \
+ failed_count++; } \
+ all_count++;
+
+int ret;
+
+void test_calls()
+{
+ TEST(pAe->f(), 20);
+ TEST(pAa->f(), 1);
+
+ TEST(pDe->vg(), 202);
+ TEST(pADe->vg(), 202);
+ TEST(pDd->vg(), 101);
+
+ TEST(pEe->vvb(), 411);
+
+ TEST(pVB->vvb(), 407);
+
+ TEST(pBe->vvb(), 411);
+ TEST(pDe->vvb(), 411);
+
+ TEST(pEe->vd(), 282);
+ TEST(pEe->fvb(), 311);
+
+ TEST(pEe->D::vg(), 102);
+ printf("Did %d tests, of which %d failed.\n", all_count, failed_count);
+}
+
+int main()
+{
+
+ init();
+
+ e.w = 7;
+ e.vb = 11;
+
+ test_calls();
+ return 0;
+
+}
+
+int A::f() {return 1;}
+int B::f() {return 2;}
+void D::s() {}
+int E::f() {return 20;}
+int D::vg() {return 100+d;}
+int E::vg() {return 200+d;}
+int V::f() {return 600+w;}
+int V::vv() {return 400+w;}
+int E::vv() {return 450+w;}
+int D::fd() {return 250+d;}
+int D::vd() {return 280+d;}
+int VB::fvb() {return 300+vb;}
+int VB::vvb() {return 400+vb;}
diff --git a/gdb/testsuite/gdb.hp/virtfun-hp.exp b/gdb/testsuite/gdb.hp/virtfun-hp.exp
new file mode 100644
index 00000000000..f5b36375082
--- /dev/null
+++ b/gdb/testsuite/gdb.hp/virtfun-hp.exp
@@ -0,0 +1,773 @@
+# Copyright (C) 1992, 1994, 1997 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file was written by Fred Fish. (fnf@cygnus.com)
+
+set ws "\[\r\n\t \]+"
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+set testfile "virtfun-hp"
+set srcfile ${testfile}.cc
+set binfile ${objdir}/${subdir}/${testfile}
+
+if [get_compiler_info ${binfile} "c++"] {
+ return -1;
+}
+
+
+if {[skip_hp_tests $gcc_compiled]} then { continue }
+
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug c++}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+
+proc gdb_virtfunc_init {} {
+ global srcdir subdir binfile
+ global gdb_prompt
+
+ gdb_reinitialize_dir $srcdir/$subdir
+ gdb_load $binfile
+
+ send_gdb "set language c++\n"
+ gdb_expect -re "$gdb_prompt $"
+ send_gdb "set width 0\n"
+ gdb_expect -re "$gdb_prompt $"
+}
+
+proc gdb_virtfunc_restart {} {
+ gdb_exit;
+ gdb_start;
+ gdb_virtfunc_init;
+ runto 'test_calls(void)';
+}
+
+#
+# Test printing of the types of various classes.
+#
+
+proc test_ptype_of_classes {} {
+ global gdb_prompt
+ global ws
+
+ # This used to be a fail if it printed "struct" not "class". But
+ # since this struct doesn't use any special C++ features, it is
+ # considered right for GDB to print it as "struct".
+ send_gdb "ptype VA\n"
+ gdb_expect {
+ -re "type = (struct|class) VA \{(${ws}public:|)${ws}int va;${ws}VA & operator=\\(VA const &\\);${ws}VA\\(VA const &\\);${ws}VA\\(void\\);${ws}\}.*$gdb_prompt $" {
+ pass "ptype VA"
+ }
+ -re "type = (struct|class) VA \{(${ws}public:|)${ws}int va;((${ws}VA & operator=\\(VA const &\\);)|(${ws}VA\\(VA const &\\);)|(${ws}VA\\(void\\);))*${ws}\}.*$gdb_prompt $" {
+ pass "ptype VA (obsolescent gcc or gdb)"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "ptype VA"
+ }
+ timeout {
+ fail "ptype VA (timeout)"
+ }
+ }
+
+ send_gdb "ptype VB\n"
+ gdb_expect {
+ -re "type = class VB \{${ws}public:${ws}int vb;${ws}VB & operator=\\(VB const &\\);${ws}VB\\(VB const &\\);${ws}VB\\(void\\);${ws}int fvb\\(void\\);${ws}virtual int vvb\\(void\\);${ws}\}.*$gdb_prompt $" {
+ pass "ptype VB"
+ }
+ -re "type = class VB \{${ws}public:${ws}int vb;((${ws}VB & operator=\\(VB const &\\);)|(${ws}VB\\(VB const &\\);)|(${ws}VB\\(void\\);)|(${ws}int fvb\\(void\\);)|(${ws}virtual int vvb\\(void\\);))*${ws}\}.*$gdb_prompt $" {
+ pass "ptype VB (obsolescent gcc or gdb)"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "ptype VB"
+ }
+ timeout {
+ fail "ptype VB (timeout)"
+ }
+ }
+
+ send_gdb "ptype V\n"
+ gdb_expect {
+ -re "type = class V : public VA, public VB \{${ws}public:${ws}int w;${ws}V & operator=\\(V const &\\);${ws}V\\(V const &\\);${ws}V\\(void\\);${ws}int f\\(void\\);${ws}virtual int vv\\(void\\);${ws}\}\r\n$gdb_prompt $" {
+ pass "ptype V"
+ }
+ -re "type = class V : public VA, public VB \{${ws}public:${ws}int w;((${ws}V & operator=\\(V const &\\);)|(${ws}V\\(V const &\\);)|(${ws}V\\(void\\);)|(${ws}int f\\(void\\);)|(${ws}virtual int vv\\(void\\);))*${ws}\}\r\n$gdb_prompt $" {
+ pass "ptype V (obsolescent gcc or gdb)"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "ptype V"
+ }
+ timeout {
+ fail "ptype V (timeout)"
+ }
+ }
+
+ send_gdb "ptype A\n"
+ gdb_expect {
+ -re "type = class A : public virtual V \{\[\r\n\t \]+private:\[\r\n\t \]+int a;\[\r\n\t \]+public:\[\r\n\t \]+virtual int f\\(void\\);\[\r\n\t \]+\}\r\n$gdb_prompt $" {
+ pass "ptype A (aCC)"
+ }
+ -re "type = class A : public virtual V \{${ws}private:${ws}V \[*\]+_vb\[\\\$\.\]+V;${ws}int a;${ws}public:${ws}A & operator=\\(A const &\\);${ws}A\\(int, A const &\\);${ws}A\\(int\\);${ws}virtual int f\\(void\\);${ws}\}\r\n$gdb_prompt $" {
+ pass "ptype A"
+ }
+ -re "type = class A : public virtual V \{${ws}private:${ws}V \[*\]+_vb\[\\\$\.\]+V;${ws}int a;${ws}public:((${ws}A & operator=\\(A const &\\);)|(${ws}A\\(int, A const &\\);)|(${ws}A\\(int\\);)|(${ws}virtual int f\\(void\\);))*${ws}\}\r\n$gdb_prompt $" {
+ pass "ptype A (obsolescent gcc or gdb)"
+ }
+ -re "type = class A : public virtual V \{${ws}private:${ws}V \[*\]+_vb.FOO;${ws}int a;${ws}public:${ws}virtual int f.void.;${ws}\}\r\n$gdb_prompt $" {
+ # This happens because the type is defined only after it is
+ # too late.
+ fail "ptype A (known failure with gcc cygnus-2.4.5-930417)"
+ # Many of the rest of these tests have the same problem.
+ return 0
+ }
+ -re ".*$gdb_prompt $" {
+ fail "ptype A"
+ }
+ timeout {
+ fail "ptype A (timeout)"
+ }
+ }
+
+ send_gdb "ptype B\n"
+ gdb_expect {
+ -re "type = class B : public A \{${ws}private:${ws}int b;${ws}public:${ws}B & operator=\\(B const &\\);${ws}B\\(int, B const &\\);${ws}B\\(int\\);${ws}virtual int f\\(void\\);${ws}\}\r\n$gdb_prompt $" {
+ pass "ptype B"
+ }
+ -re "type = class B : public A \{${ws}private:${ws}int b;${ws}public:((${ws}B & operator=\\(B const &\\);)|(${ws}B\\(int, B const &\\);)|(${ws}B\\(int\\);)|(${ws}virtual int f\\(void\\);))*${ws}\}\r\n$gdb_prompt $" {
+ pass "ptype B (obsolescent gcc or gdb)"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "ptype B"
+ }
+ timeout {
+ fail "ptype B (timeout)"
+ }
+ }
+
+ send_gdb "ptype C\n"
+ gdb_expect {
+ -re "type = class C : public virtual V \{\[\r\n\t \]+public:\[\r\n\t \]+int c;\[\r\n\t \]+\}\r\n$gdb_prompt $" {
+ pass "ptype C (aCC)"
+ }
+ -re "type = class C : public virtual V \{${ws}private:${ws}V \[*\]+_vb.V;${ws}public:${ws}int c;${ws}C & operator=\\(C const &\\);${ws}C\\(int, C const &\\);${ws}C\\(int\\);${ws}\}\r\n$gdb_prompt $" {
+ pass "ptype C"
+ }
+ -re "type = class C : public virtual V \{${ws}private:${ws}V \[*\]+_vb.V;${ws}public:${ws}int c;((${ws}C & operator=\\(C const &\\);)|(${ws}C\\(int, C const &\\);)|(${ws}C\\(int\\);))*${ws}\}\r\n$gdb_prompt $" {
+ pass "ptype C (obsolescent gcc or gdb)"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "ptype C"
+ }
+ timeout {
+ fail "ptype C (timeout)"
+ }
+ }
+
+ send_gdb "ptype AD\n"
+ gdb_expect {
+ -re "type = class AD \{${ws}public:${ws}AD & operator=\\(AD const &\\);${ws}AD\\(AD const &\\);${ws}AD\\(void\\);${ws}virtual int vg\\(void\\);${ws}\}\r\n$gdb_prompt $" {
+ pass "ptype AD"
+ }
+ -re "type = class AD \{${ws}public:((${ws}AD & operator=\\(AD const &\\);)|(${ws}AD\\(AD const &\\);)|(${ws}AD\\(void\\);)|(${ws}virtual int vg\\(void\\);))*${ws}\}\r\n$gdb_prompt $" {
+ pass "ptype AD (obsolescent gcc or gdb)"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "ptype AD"
+ }
+ timeout {
+ fail "ptype AD (timeout)"
+ }
+ }
+
+ send_gdb "ptype D\n"
+ gdb_expect {
+ -re "type = class D : public AD, public virtual V \{\[\r\n\t \]+public:\[\r\n\t \]+int d;\[\r\n\t \]+static void s\\(void\\);\[\r\n\t \]+virtual int vg\\(void\\);\[\r\n\t \]+virtual int vd\\(void\\);\[\r\n\t \]+int fd\\(void\\);\[\r\n\t \]+\}\r\n$gdb_prompt $" {
+ pass "ptype D (aCC)"
+ }
+ -re "type = class D : public AD, public virtual V \{${ws}private:${ws}V \[*\]+_vb.V;${ws}public:${ws}int d;${ws}D & operator=\\(D const &\\);${ws}D\\(int, D const &\\);${ws}D\\(int\\);${ws}static void s\\(void\\);${ws}virtual int vg\\(void\\);${ws}virtual int vd\\(void\\);${ws}int fd\\(void\\);${ws}\}\r\n$gdb_prompt $" {
+ pass "ptype D"
+ }
+ -re "type = class D : public AD, public virtual V \{${ws}private:${ws}V \[*\]+_vb.V;${ws}public:${ws}int d;((${ws}D & operator=\\(D const &\\);)|(${ws}D\\(int, D const &\\);)|(${ws}D\\(int\\);)|(${ws}static void s\\(void\\);)|(${ws}virtual int vg\\(void\\);)|(${ws}virtual int vd\\(void\\);)|(${ws}int fd\\(void\\);))*${ws}\}\r\n$gdb_prompt $" {
+ pass "ptype D (obsolescent gcc or gdb)"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "ptype D"
+ }
+ timeout {
+ fail "ptype D (timeout)"
+ }
+ }
+
+ send_gdb "ptype E\n"
+ gdb_expect {
+ -re "type = class E : public B, public virtual V, public D, public C \{${ws}public:${ws}int e;${ws}E & operator=\\(E const &\\);${ws}E\\(int, E const &\\);${ws}E\\(int\\);${ws}virtual int f\\(void\\);${ws}virtual int vg\\(void\\);${ws}virtual int vv\\(void\\);${ws}\}\r\n$gdb_prompt $" {
+ pass "ptype E"
+ }
+ -re "type = class E : public B, public virtual V, public D, public C \{${ws}public:${ws}int e;((${ws}E & operator=\\(E const &\\);)|(${ws}E\\(int, E const &\\);)|(${ws}E\\(int\\);)|(${ws}virtual int f\\(void\\);)|(${ws}virtual int vg\\(void\\);)|(${ws}virtual int vv\\(void\\);))*${ws}\}\r\n$gdb_prompt $" {
+ pass "ptype E (obsolescent gcc or gdb)"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "ptype E"
+ }
+ timeout {
+ fail "ptype E (timeout)"
+ }
+ }
+
+ send_gdb "ptype dd\n"
+ gdb_expect {
+ -re "type = class D : public AD, public virtual V \{\[\r\n\t \]+public:\[\r\n\t \]+int d;\[\r\n\t \]+static void s\\(void\\);\[\r\n\t \]+virtual int vg\\(void\\);\[\r\n\t \]+virtual int vd\\(void\\);\[\r\n\t \]+int fd\\(void\\);\[\r\n\t \]+\}\r\n$gdb_prompt $" {
+ pass "ptype dd (aCC)"
+ }
+ -re "type = class D : public AD, public virtual V \{${ws}private:${ws}V \[*\]+_vb.V;${ws}public:${ws}int d;${ws}D & operator=\\(D const &\\);${ws}D\\(int, D const &\\);${ws}D\\(int\\);${ws}static void s\\(void\\);${ws}virtual int vg\\(void\\);${ws}virtual int vd\\(void\\);${ws}int fd\\(void\\);${ws}\}\r\n$gdb_prompt $" {
+ pass "ptype dd"
+ }
+ -re "type = class D : public AD, public virtual V \{${ws}private:${ws}V \[*\]+_vb.V;${ws}public:${ws}int d;((${ws}D & operator=\\(D const &\\);)|(${ws}D\\(int, D const &\\);)|(${ws}D\\(int\\);)|(${ws}static void s\\(void\\);)|(${ws}virtual int vg\\(void\\);)|(${ws}virtual int vd\\(void\\);)|(${ws}int fd\\(void\\);))*${ws}\}\r\n$gdb_prompt $" {
+ pass "ptype dd (obsolescent gcc or gdb)"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "ptype dd"
+ }
+ timeout {
+ fail "ptype dd (timeout)"
+ }
+ }
+
+ send_gdb "ptype ppd\n"
+ gdb_expect {
+ -re "type = class D : public AD, public virtual V \{\[\r\n\t \]+public:\[\r\n\t \]+int d;\[\r\n\t \]+static void s\\(void\\);\[\r\n\t \]+virtual int vg\\(void\\);\[\r\n\t \]+virtual int vd\\(void\\);\[\r\n\t \]+int fd\\(void\\);\[\r\n\t \]+\} \[*\]+\r\n$gdb_prompt $" {
+ pass "ptype ppd (aCC)"
+ }
+ -re "type = class D : public AD, public virtual V \{${ws}private:${ws}V \[*\]+_vb.V;${ws}public:${ws}int d;${ws}D & operator=\\(D const &\\);${ws}D\\(int, D const &\\);${ws}D\\(int\\);${ws}static void s\\(void\\);${ws}virtual int vg\\(void\\);${ws}virtual int vd\\(void\\);${ws}int fd\\(void\\);${ws}\} \[*\]+\r\n$gdb_prompt $" {
+ pass "ptype ppd"
+ }
+ -re "type = class D : public AD, public virtual V \{${ws}private:${ws}V \[*\]+_vb.V;${ws}public:${ws}int d;((${ws}D & operator=\\(D const &\\);)|(${ws}D\\(int, D const &\\);)|(${ws}D\\(int\\);)|(${ws}static void s\\(void\\);)|(${ws}virtual int vg\\(void\\);)|(${ws}virtual int vd\\(void\\);)|(${ws}int fd\\(void\\);))*${ws}\} \[*\]+\r\n$gdb_prompt $" {
+ pass "ptype ppd (obsolescent gcc or gdb)"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "ptype ppd"
+ }
+ timeout {
+ fail "ptype ppd (timeout)"
+ }
+ }
+
+ send_gdb "ptype pAd\n"
+ gdb_expect {
+ -re "type = class AD \{${ws}public:${ws}AD & operator=\\(AD const &\\);${ws}AD\\(AD const &\\);${ws}AD\\(void\\);${ws}virtual int vg\\(void\\);${ws}\} \[*\]+\r\n$gdb_prompt $" {
+ pass "ptype pAd"
+ }
+ -re "type = class AD \{${ws}public:((${ws}AD & operator=\\(AD const &\\);)|(${ws}AD\\(AD const &\\);)|(${ws}AD\\(void\\);)|(${ws}virtual int vg\\(void\\);))*${ws}\} \[*\]+\r\n$gdb_prompt $" {
+ pass "ptype pAd (obsolescent gcc or gdb)"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "ptype pAd"
+ }
+ timeout {
+ fail "ptype pAd (timeout)"
+ }
+ }
+
+ send_gdb "ptype a\n"
+ gdb_expect {
+ -re "type = class A : public virtual V \{\[\r\n\t \]+private:\[\r\n\t \]+int a;\[\r\n\t \]+public:\[\r\n\t \]+virtual int f\\(void\\);\[\r\n\t \]+\}\r\n$gdb_prompt $" {
+ pass "ptype a (aCC)"
+ }
+ -re "type = class A : public virtual V \{${ws}private:${ws}V \[*\]+_vb.V;${ws}int a;${ws}public:${ws}A & operator=\\(A const &\\);${ws}A\\(int, A const &\\);${ws}A\\(int\\);${ws}virtual int f\\(void\\);${ws}\}\r\n$gdb_prompt $" {
+ pass "ptype a"
+ }
+ -re "type = class A : public virtual V \{${ws}private:${ws}V \[*\]+_vb.V;${ws}int a;${ws}public:((${ws}A & operator=\\(A const &\\);)|(${ws}A\\(int, A const &\\);)|(${ws}A\\(int\\);)|(${ws}virtual int f\\(void\\);))*${ws}\}\r\n$gdb_prompt $" {
+ pass "ptype a (obsolescent gcc or gdb)"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "ptype a"
+ }
+ timeout {
+ fail "ptype a (timeout)"
+ }
+ }
+
+ send_gdb "ptype b\n"
+ gdb_expect {
+ -re "type = class B : public A \{${ws}private:${ws}int b;${ws}public:${ws}B & operator=\\(B const &\\);${ws}B\\(int, B const &\\);${ws}B\\(int\\);${ws}virtual int f\\(void\\);${ws}\}\r\n$gdb_prompt $" {
+ pass "ptype b"
+ }
+ -re "type = class B : public A \{${ws}private:${ws}int b;${ws}public:((${ws}B & operator=\\(B const &\\);)|(${ws}B\\(int, B const &\\);)|(${ws}B\\(int\\);)|(${ws}virtual int f\\(void\\);))*${ws}\}\r\n$gdb_prompt $" {
+ pass "ptype b (obsolescent gcc or gdb)"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "ptype b"
+ }
+ timeout {
+ fail "ptype b (timeout)"
+ }
+ }
+
+ send_gdb "ptype c\n"
+ gdb_expect {
+ -re "type = class C : public virtual V \{\[\r\n\t \]+public:\[\r\n\t \]+int c;\[\r\n\t \]+\}\r\n$gdb_prompt $" {
+ pass "ptype c (aCC)"
+ }
+ -re "type = class C : public virtual V \{${ws}private:${ws}V \[*\]+_vb.V;${ws}public:${ws}int c;${ws}C & operator=\\(C const &\\);${ws}C\\(int, C const &\\);${ws}C\\(int\\);${ws}\}\r\n$gdb_prompt $" {
+ pass "ptype c"
+ }
+ -re "type = class C : public virtual V \{${ws}private:${ws}V \[*\]+_vb.V;${ws}public:${ws}int c;((${ws}C & operator=\\(C const &\\);)|(${ws}C\\(int, C const &\\);)|(${ws}C\\(int\\);))*${ws}\}\r\n$gdb_prompt $" {
+ pass "ptype c (obsolescent gcc or gdb)"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "ptype c"
+ }
+ timeout {
+ fail "ptype c (timeout)"
+ }
+ }
+
+ send_gdb "ptype d\n"
+ gdb_expect {
+ -re "type = class D : public AD, public virtual V \{\[\r\n\t \]+public:\[\r\n\t \]+int d;\[\r\n\t \]+static void s\\(void\\);\[\r\n\t \]+virtual int vg\\(void\\);\[\r\n\t \]+virtual int vd\\(void\\);\[\r\n\t \]+int fd\\(void\\);\[\r\n\t \]+\}\r\n$gdb_prompt $" {
+ pass "ptype d (aCC)"
+ }
+ -re "type = class D : public AD, public virtual V \{${ws}private:${ws}V \[*\]+_vb.V;${ws}public:${ws}int d;${ws}D & operator=\\(D const &\\);${ws}D\\(int, D const &\\);${ws}D\\(int\\);${ws}static void s\\(void\\);${ws}virtual int vg\\(void\\);${ws}virtual int vd\\(void\\);${ws}int fd\\(void\\);${ws}\}\r\n$gdb_prompt $" {
+ pass "ptype d"
+ }
+ -re "type = class D : public AD, public virtual V \{${ws}private:${ws}V \[*\]+_vb.V;${ws}public:${ws}int d;((${ws}D & operator=\\(D const &\\);)|(${ws}D\\(int, D const &\\);)|(${ws}D\\(int\\);)|(${ws}static void s\\(void\\);)|(${ws}virtual int vg\\(void\\);)|(${ws}virtual int vd\\(void\\);)|(${ws}int fd\\(void\\);))*${ws}\}\r\n$gdb_prompt $" {
+ pass "ptype d (obsolescent gcc or gdb)"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "ptype d"
+ }
+ timeout {
+ fail "ptype d (timeout)"
+ }
+ }
+
+ send_gdb "ptype e\n"
+ gdb_expect {
+ -re "type = class E : public B, public virtual V, public D, public C \{${ws}public:${ws}int e;${ws}E & operator=\\(E const &\\);${ws}E\\(int, E const &\\);${ws}E\\(int\\);${ws}virtual int f\\(void\\);${ws}virtual int vg\\(void\\);${ws}virtual int vv\\(void\\);${ws}\}\r\n$gdb_prompt $" {
+ pass "ptype e"
+ }
+ -re "type = class E : public B, public virtual V, public D, public C \{${ws}public:${ws}int e;((${ws}E & operator=\\(E const &\\);)|(${ws}E\\(int, E const &\\);)|(${ws}E\\(int\\);)|(${ws}virtual int f\\(void\\);)|(${ws}virtual int vg\\(void\\);)|(${ws}virtual int vv\\(void\\);))*${ws}\}\r\n$gdb_prompt $" {
+ pass "ptype e (obsolescent gcc or gdb)"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "ptype e"
+ }
+ timeout {
+ fail "ptype e (timeout)"
+ }
+ }
+
+ send_gdb "ptype v\n"
+ gdb_expect {
+ -re "type = class V : public VA, public VB \{${ws}public:${ws}int w;${ws}V & operator=\\(V const &\\);${ws}V\\(V const &\\);${ws}V\\(void\\);${ws}int f\\(void\\);${ws}virtual int vv\\(void\\);${ws}\}\r\n$gdb_prompt $" {
+ pass "ptype v"
+ }
+ -re "type = class V : public VA, public VB \{${ws}public:${ws}int w;((${ws}V & operator=\\(V const &\\);)|(${ws}V\\(V const &\\);)|(${ws}V\\(void\\);)|(${ws}int f\\(void\\);)|(${ws}virtual int vv\\(void\\);))*${ws}\}\r\n$gdb_prompt $" {
+ pass "ptype v (obsolescent gcc or gdb)"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "ptype v"
+ }
+ timeout {
+ fail "ptype v (timeout)"
+ }
+ }
+
+ send_gdb "ptype vb\n"
+ gdb_expect {
+ -re "type = class VB \{${ws}public:${ws}int vb;${ws}VB & operator=\\(VB const &\\);${ws}VB\\(VB const &\\);${ws}VB\\(void\\);${ws}int fvb\\(void\\);${ws}virtual int vvb\\(void\\);${ws}\}\r\n$gdb_prompt $" {
+ pass "ptype vb"
+ }
+ -re "type = class VB \{${ws}public:${ws}int vb;((${ws}VB & operator=\\(VB const &\\);)|(${ws}VB\\(VB const &\\);)|(${ws}VB\\(void\\);)|(${ws}int fvb\\(void\\);)|(${ws}virtual int vvb\\(void\\);))*${ws}\}\r\n$gdb_prompt $" {
+ pass "ptype vb (obsolescent gcc or gdb)"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "ptype vb"
+ }
+ timeout {
+ fail "ptype vb (timeout)"
+ }
+ }
+
+ send_gdb "ptype pAa\n"
+ gdb_expect {
+ -re "type = class A : public virtual V \{\[\r\n\t \]+private:\[\r\n\t \]+int a;\[\r\n\t \]+public:\[\r\n\t \]+virtual int f\\(void\\);\[\r\n\t \]+\} \[*\]+\r\n$gdb_prompt $" {
+ pass "ptype pAa (aCC)"
+ }
+ -re "type = class A : public virtual V \{${ws}private:${ws}V \[*\]+_vb.V;${ws}int a;${ws}public:${ws}A & operator=\\(A const &\\);${ws}A\\(int, A const &\\);${ws}A\\(int\\);${ws}virtual int f\\(void\\);${ws}\} \[*\]+\r\n$gdb_prompt $" {
+ pass "ptype pAa"
+ }
+ -re "type = class A : public virtual V \{${ws}private:${ws}V \[*\]+_vb.V;${ws}int a;${ws}public:((${ws}A & operator=\\(A const &\\);)|(${ws}A\\(int, A const &\\);)|(${ws}A\\(int\\);)|(${ws}virtual int f\\(void\\);))*${ws}\} \[*\]+\r\n$gdb_prompt $" {
+ pass "ptype pAa (obsolescent gcc or gdb)"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "ptype pAa"
+ }
+ timeout {
+ fail "ptype pAa (timeout)"
+ }
+ }
+
+ send_gdb "ptype pAe\n"
+ gdb_expect {
+ -re "type = class A : public virtual V \{\[\r\n\t \]+private:\[\r\n\t \]+int a;\[\r\n\t \]+public:\[\r\n\t \]+virtual int f\\(void\\);\[\r\n\t \]+\} \[*\]+\r\n$gdb_prompt $" {
+ pass "ptype pAe (aCC)"
+ }
+ -re "type = class A : public virtual V \{${ws}private:${ws}V \[*\]+_vb.V;${ws}int a;${ws}public:${ws}A & operator=\\(A const &\\);${ws}A\\(int, A const &\\);${ws}A\\(int\\);${ws}virtual int f\\(void\\);${ws}\} \[*\]+\r\n$gdb_prompt $" {
+ pass "ptype pAe"
+ }
+ -re "type = class A : public virtual V \{${ws}private:${ws}V \[*\]+_vb.V;${ws}int a;${ws}public:((${ws}A & operator=\\(A const &\\);)|(${ws}A\\(int, A const &\\);)|(${ws}A\\(int\\);)|(${ws}virtual int f\\(void\\);))*${ws}\} \[*\]+\r\n$gdb_prompt $" {
+ pass "ptype pAe (obsolescent gcc or gdb)"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "ptype pAe"
+ }
+ timeout {
+ fail "ptype pAe (timeout)"
+ }
+ }
+
+ send_gdb "ptype pBe\n"
+ gdb_expect {
+ -re "type = class B : public A \{${ws}private:${ws}int b;${ws}public:${ws}B & operator=\\(B const &\\);${ws}B\\(int, B const &\\);${ws}B\\(int\\);${ws}virtual int f\\(void\\);${ws}\} \[*\]+\r\n$gdb_prompt $" {
+ pass "ptype pBe"
+ }
+ -re "type = class B : public A \{${ws}private:${ws}int b;${ws}public:((${ws}B & operator=\\(B const &\\);)|(${ws}B\\(int, B const &\\);)|(${ws}B\\(int\\);)|(${ws}virtual int f\\(void\\);))*${ws}\} \[*\]+\r\n$gdb_prompt $" {
+ pass "ptype pBe (obsolescent gcc or gdb)"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "ptype pBe"
+ }
+ timeout {
+ fail "ptype pBe (timeout)"
+ }
+ }
+
+ send_gdb "ptype pDd\n"
+ gdb_expect {
+ -re "type = class D : public AD, public virtual V \{\[\r\n\t \]+public:\[\r\n\t \]+int d;\[\r\n\t \]+static void s\\(void\\);\[\r\n\t \]+virtual int vg\\(void\\);\[\r\n\t \]+virtual int vd\\(void\\);\[\r\n\t \]+int fd\\(void\\);\[\r\n\t \]+\} \[*\]+\r\n$gdb_prompt $" {
+ pass "ptype pDd (aCC)"
+ }
+ -re "type = class D : public AD, public virtual V \{${ws}private:${ws}V \[*\]+_vb.V;${ws}public:${ws}int d;${ws}D & operator=\\(D const &\\);${ws}D\\(int, D const &\\);${ws}D\\(int\\);${ws}static void s\\(void\\);${ws}virtual int vg\\(void\\);${ws}virtual int vd\\(void\\);${ws}int fd\\(void\\);${ws}\} \[*\]+\r\n$gdb_prompt $" {
+ pass "ptype pDd"
+ }
+ -re "type = class D : public AD, public virtual V \{${ws}private:${ws}V \[*\]+_vb.V;${ws}public:${ws}int d;((${ws}D & operator=\\(D const &\\);)|(${ws}D\\(int, D const &\\);)|(${ws}D\\(int\\);)|(${ws}static void s\\(void\\);)|(${ws}virtual int vg\\(void\\);)|(${ws}virtual int vd\\(void\\);)|(${ws}int fd\\(void\\);))*${ws}\} \[*\]+\r\n$gdb_prompt $" {
+ pass "ptype pDd (obsolescent gcc or gdb)"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "ptype pDd"
+ }
+ timeout {
+ fail "ptype pDd (timeout)"
+ }
+ }
+
+ send_gdb "ptype pDe\n"
+ gdb_expect {
+ -re "type = class D : public AD, public virtual V \{\[\r\n\t \]+public:\[\r\n\t \]+int d;\[\r\n\t \]+static void s\\(void\\);\[\r\n\t \]+virtual int vg\\(void\\);\[\r\n\t \]+virtual int vd\\(void\\);\[\r\n\t \]+int fd\\(void\\);\[\r\n\t \]+\} \[*\]+\r\n$gdb_prompt $" {
+ pass "ptype pDe (aCC)"
+ }
+ -re "type = class D : public AD, public virtual V \{${ws}private:${ws}V \[*\]+_vb.V;${ws}public:${ws}int d;${ws}D & operator=\\(D const &\\);${ws}D\\(int, D const &\\);${ws}D\\(int\\);${ws}static void s\\(void\\);${ws}virtual int vg\\(void\\);${ws}virtual int vd\\(void\\);${ws}int fd\\(void\\);${ws}\} \[*\]+\r\n$gdb_prompt $" {
+ pass "ptype pDe"
+ }
+ -re "type = class D : public AD, public virtual V \{${ws}private:${ws}V \[*\]+_vb.V;${ws}public:${ws}int d;((${ws}D & operator=\\(D const &\\);)|(${ws}D\\(int, D const &\\);)|(${ws}D\\(int\\);)|(${ws}static void s\\(void\\);)|(${ws}virtual int vg\\(void\\);)|(${ws}virtual int vd\\(void\\);)|(${ws}int fd\\(void\\);))*${ws}\} \[*\]+\r\n$gdb_prompt $" {
+ pass "ptype pDe (obsolescent gcc or gdb)"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "ptype pDe"
+ }
+ timeout {
+ fail "ptype pDe (timeout)"
+ }
+ }
+
+ send_gdb "ptype pVa\n"
+ gdb_expect {
+ -re "type = class V : public VA, public VB \{${ws}public:${ws}int w;${ws}V & operator=\\(V const &\\);${ws}V\\(V const &\\);${ws}V\\(void\\);${ws}int f\\(void\\);${ws}virtual int vv\\(void\\);${ws}\} \[*\]+\r\n$gdb_prompt $" {
+ pass "ptype pVa"
+ }
+ -re "type = class V : public VA, public VB \{${ws}public:${ws}int w;((${ws}V & operator=\\(V const &\\);)|(${ws}V\\(V const &\\);)|(${ws}V\\(void\\);)|(${ws}int f\\(void\\);)|(${ws}virtual int vv\\(void\\);))*${ws}\} \[*\]+\r\n$gdb_prompt $" {
+ pass "ptype pVa (obsolescent gcc or gdb)"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "ptype pVa"
+ }
+ timeout {
+ fail "ptype pVa (timeout)"
+ }
+ }
+
+ send_gdb "ptype pVv\n"
+ gdb_expect {
+ -re "type = class V : public VA, public VB \{${ws}public:${ws}int w;${ws}V & operator=\\(V const &\\);${ws}V\\(V const &\\);${ws}V\\(void\\);${ws}int f\\(void\\);${ws}virtual int vv\\(void\\);${ws}\} \[*\]+\r\n$gdb_prompt $" {
+ pass "ptype pVv"
+ }
+ -re "type = class V : public VA, public VB \{${ws}public:${ws}int w;((${ws}V & operator=\\(V const &\\);)|(${ws}V\\(V const &\\);)|(${ws}V\\(void\\);)|(${ws}int f\\(void\\);)|(${ws}virtual int vv\\(void\\);))*${ws}\} \[*\]+\r\n$gdb_prompt $" {
+ pass "ptype pVv (obsolescent gcc or gdb)"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "ptype pVv"
+ }
+ timeout {
+ fail "ptype pVv (timeout)"
+ }
+ }
+
+ send_gdb "ptype pVe\n"
+ gdb_expect {
+ -re "type = class V : public VA, public VB \{${ws}public:${ws}int w;${ws}V & operator=\\(V const &\\);${ws}V\\(V const &\\);${ws}V\\(void\\);${ws}int f\\(void\\);${ws}virtual int vv\\(void\\);${ws}\} \[*\]+\r\n$gdb_prompt $" {
+ pass "ptype pVe"
+ }
+ -re "type = class V : public VA, public VB \{${ws}public:${ws}int w;((${ws}V & operator=\\(V const &\\);)|(${ws}V\\(V const &\\);)|(${ws}V\\(void\\);)|(${ws}int f\\(void\\);)|(${ws}virtual int vv\\(void\\);))*${ws}\} \[*\]+\r\n$gdb_prompt $" {
+ pass "ptype pVe (obsolescent gcc or gdb)"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "ptype pVe"
+ }
+ timeout {
+ fail "ptype pVe (timeout)"
+ }
+ }
+
+ send_gdb "ptype pVd\n"
+ gdb_expect {
+ -re "type = class V : public VA, public VB \{${ws}public:${ws}int w;${ws}V & operator=\\(V const &\\);${ws}V\\(V const &\\);${ws}V\\(void\\);${ws}int f\\(void\\);${ws}virtual int vv\\(void\\);${ws}\} \[*\]+\r\n$gdb_prompt $" {
+ pass "ptype pVd"
+ }
+ -re "type = class V : public VA, public VB \{${ws}public:${ws}int w;((${ws}V & operator=\\(V const &\\);)|(${ws}V\\(V const &\\);)|(${ws}V\\(void\\);)|(${ws}int f\\(void\\);)|(${ws}virtual int vv\\(void\\);))*${ws}\} \[*\]+\r\n$gdb_prompt $" {
+ pass "ptype pVd (obsolescent gcc or gdb)"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "ptype pVd"
+ }
+ timeout {
+ fail "ptype pVd (timeout)"
+ }
+ }
+
+ send_gdb "ptype pADe\n"
+ gdb_expect {
+ -re "type = class AD \{${ws}public:${ws}AD & operator=\\(AD const &\\);${ws}AD\\(AD const &\\);${ws}AD\\(void\\);${ws}virtual int vg\\(void\\);${ws}\} \[*\]+\r\n$gdb_prompt $" {
+ pass "ptype pADe"
+ }
+ -re "type = class AD \{${ws}public:((${ws}AD & operator=\\(AD const &\\);)|(${ws}AD\\(AD const &\\);)|(${ws}AD\\(void\\);)|(${ws}virtual int vg\\(void\\);))*${ws}\} \[*\]+\r\n$gdb_prompt $" {
+ pass "ptype pADe (obsolescent gcc or gdb)"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "ptype pADe"
+ }
+ timeout {
+ fail "ptype pADe (timeout)"
+ }
+ }
+
+ send_gdb "ptype pEe\n"
+ gdb_expect {
+ -re "type = class E : public B, public virtual V, public D, public C \{${ws}public:${ws}int e;${ws}E & operator=\\(E const &\\);${ws}E\\(int, E const &\\);${ws}E\\(int\\);${ws}virtual int f\\(void\\);${ws}virtual int vg\\(void\\);${ws}virtual int vv\\(void\\);${ws}\} \[*\]+\r\n$gdb_prompt $" {
+ pass "ptype pEe"
+ }
+ -re "type = class E : public B, public virtual V, public D, public C \{${ws}public:${ws}int e;((${ws}E & operator=\\(E const &\\);)|(${ws}E\\(int, E const &\\);)|(${ws}E\\(int\\);)|(${ws}virtual int f\\(void\\);)|(${ws}virtual int vg\\(void\\);)|(${ws}virtual int vv\\(void\\);))*${ws}\} \[*\]+\r\n$gdb_prompt $" {
+ pass "ptype pEe (obsolescent gcc or gdb)"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "ptype pEe"
+ }
+ timeout {
+ fail "ptype pEe (timeout)"
+ }
+ }
+
+ send_gdb "ptype pVB\n"
+ gdb_expect {
+ -re "type = class VB \{${ws}public:${ws}int vb;${ws}VB & operator=\\(VB const &\\);${ws}VB\\(VB const &\\);${ws}VB\\(void\\);${ws}int fvb\\(void\\);${ws}virtual int vvb\\(void\\);${ws}\} \[*\]+\r\n$gdb_prompt $" {
+ pass "ptype pVB"
+ }
+ -re "type = class VB \{${ws}public:${ws}int vb;((${ws}VB & operator=\\(VB const &\\);)|(${ws}VB\\(VB const &\\);)|(${ws}VB\\(void\\);)|(${ws}int fvb\\(void\\);)|(${ws}virtual int vvb\\(void\\);))*${ws}\} \[*\]+\r\n$gdb_prompt $" {
+ pass "ptype pVB (obsolescent gcc or gdb)"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "ptype pVB"
+ }
+ timeout {
+ fail "ptype pVB (timeout)"
+ }
+ }
+}
+
+#
+# Test calling of virtual functions.
+#
+
+proc test_virtual_calls {} {
+ global gdb_prompt
+ global GDB
+
+ if [target_info exists gdb,cannot_call_functions] {
+ setup_xfail "*-*-*" 2416
+ fail "This target can not call functions"
+ return 0
+ }
+
+ send_gdb "print pAe->f()\n"
+ gdb_expect {
+ -re ".* = 20\r\n$gdb_prompt $" { pass "print pAe->f()" }
+ -re "Cannot invoke functions on this machine.*$gdb_prompt $" {
+ fail "print pAe->f() (cannot invoke functions, skipping virtual calls)"
+ return 0
+ }
+ -re ".*Cannot access memory at address 0x8.*$gdb_prompt $" {
+ fail "print pAe->f() \
+(known failure with gcc cygnus-2.4.5-930417, skipping virtual calls)"
+ return 0
+ }
+ -re ".*$gdb_prompt $" { fail "print pAe->f()" }
+ timeout { fail "print pAe->f() (timeout)" }
+ eof { fail "print pAe->f() ($GDB dumped core) (FIXME)" ; gdb_virtfunc_restart; return }
+ }
+
+ send_gdb "print pAa->f()\n"
+ gdb_expect {
+ -re ".* = 1\r\n$gdb_prompt $" { pass "print pAa->f()" }
+ -re ".*$gdb_prompt $" { fail "print pAa->f()" }
+ timeout { fail "print pAa->f() (timeout)" }
+ eof { fail "print pAa->f() ($GDB dumped core) (FIXME)" ; gdb_virtfunc_restart; return }
+ }
+
+ send_gdb "print pDe->vg()\n"
+# setup_xfail "*-*-*"
+ gdb_expect {
+ -re ".* = 202\r\n$gdb_prompt $" { pass "print pDe->vg()" }
+ -re ".*$gdb_prompt $" { fail "print pDe->vg()" }
+ timeout { fail "print pDe->vg() (timeout)" }
+ eof { fail "print pDe->vg() ($GDB dumped core) (FIXME)" ; gdb_virtfunc_restart; return }
+ }
+
+ send_gdb "print pADe->vg()\n"
+ gdb_expect {
+ -re ".* = 202\r\n$gdb_prompt $" { pass "print pADe->vg()" }
+ -re ".*$gdb_prompt $" { fail "print pADe->vg()" }
+ timeout { fail "print pADe->vg() (timeout)" }
+ eof { fail "print pADe->vg() ($GDB dumped core) (FIXME)" ; gdb_virtfunc_restart; return }
+ }
+
+ send_gdb "print pDd->vg()\n"
+# setup_xfail "*-*-*"
+ gdb_expect {
+ -re ".* = 101\r\n$gdb_prompt $" { pass "print pDd->vg()" }
+ -re ".*$gdb_prompt $" { fail "print pDd->vg()" }
+ timeout { fail "print pDd->vg() (timeout)" }
+ eof { fail "print pDd->vg() ($GDB dumped core) (FIXME)" ; gdb_virtfunc_restart; return }
+ }
+
+ send_gdb "print pEe->vvb()\n"
+# setup_xfail "*-*-*"
+ gdb_expect {
+ -re ".* = 411\r\n$gdb_prompt $" { pass "print pEe->vvb()" }
+ -re ".*$gdb_prompt $" { fail "print pEe->vvb()" }
+ timeout { fail "print pEe->vvb() (timeout)" }
+ eof { fail "print pEe->vvb() ($GDB dumped core) (FIXME)" ; gdb_virtfunc_restart; return }
+ }
+
+ send_gdb "print pVB->vvb()\n"
+ gdb_expect {
+ -re ".* = 407\r\n$gdb_prompt $" { pass "print pVB->vvb()" }
+ -re ".*$gdb_prompt $" { fail "print pVB->vvb()" }
+ timeout { fail "print pVB->vvb() (timeout)" }
+ eof { fail "print pVB->vvb() ($GDB dumped core) (FIXME)" ; gdb_virtfunc_restart; return }
+ }
+
+ send_gdb "print pBe->vvb()\n"
+# setup_xfail "*-*-*"
+ gdb_expect {
+ -re ".* = 411\r\n$gdb_prompt $" { pass "print pBe->vvb()" }
+ -re ".*$gdb_prompt $" { fail "print pBe->vvb()" }
+ timeout { fail "print pBe->vvb() (timeout)" }
+ eof { fail "print pBe->vvb() ($GDB dumped core) (FIXME)" ; gdb_virtfunc_restart; return }
+ }
+
+ send_gdb "print pDe->vvb()\n"
+# setup_xfail "*-*-*"
+ gdb_expect {
+ -re ".* = 411\r\n$gdb_prompt $" { pass "print pDe->vvb()" }
+ -re ".*$gdb_prompt $" { fail "print pDe->vvb()" }
+ timeout { fail "print pDe->vvb() (timeout)" }
+ eof { fail "print pDe->vvb() ($GDB dumped core) (FIXME)" ; gdb_virtfunc_restart; return }
+ }
+
+ send_gdb "print pEe->vd()\n"
+# setup_xfail "*-*-*"
+ gdb_expect {
+ -re ".* = 282\r\n$gdb_prompt $" { pass "print pEe->vd()" }
+ -re ".*$gdb_prompt $" { fail "print pEe->vd()" }
+ timeout { fail "print pEe->vd() (timeout)" }
+ eof { fail "print pEe->vd() ($GDB dumped core) (FIXME)" ; gdb_virtfunc_restart; return }
+ }
+
+ send_gdb "print pEe->fvb()\n"
+# setup_xfail "*-*-*"
+ gdb_expect {
+ -re ".* = 311\r\n$gdb_prompt $" { pass "print pEe->fvb()" }
+ -re ".*$gdb_prompt $" { fail "print pEe->fvb()" }
+ timeout { fail "print pEe->fvb() (timeout)" }
+ eof { fail "print pEe->fvb() ($GDB dumped core) (FIXME)" ; gdb_virtfunc_restart; return }
+ }
+
+ send_gdb "print pEe->D::vg()\n"
+ setup_xfail "*-*-*"
+ gdb_expect {
+ -re ".* = 102\r\n$gdb_prompt $" { pass "print pEe->D::vg()" }
+ -re ".*$gdb_prompt $" { fail "print pEe->D::vg()" }
+ timeout { fail "print pEe->D::vg() (timeout)" }
+ eof { fail "print pEe->D::vg() ($GDB dumped core) (FIXME)" ; gdb_virtfunc_restart; return }
+ }
+}
+
+proc do_tests {} {
+ global prms_id
+ global bug_id
+
+ set prms_id 0
+ set bug_id 0
+
+ gdb_start;
+ gdb_virtfunc_init;
+
+ # Get the debug format for the compiled test case. If that
+ # format is DWARF 1 then just skip all the tests since none of
+ # them will pass.
+
+ if [ runto_main ] then {
+ get_debug_format
+ if [ setup_xfail_format "DWARF 1" ] then {
+ fail "C++ tests skipped due to limited C++ support in DWARF 1 debug format"
+ return
+ }
+ clear_xfail "*-*-*"
+ }
+
+ test_ptype_of_classes
+
+ if [ runto 'test_calls(void)' ] then {
+ test_virtual_calls
+ }
+}
+
+do_tests
diff --git a/gdb/testsuite/gdb.hp/watch-cmd.exp b/gdb/testsuite/gdb.hp/watch-cmd.exp
new file mode 100644
index 00000000000..a7e3b5c5132
--- /dev/null
+++ b/gdb/testsuite/gdb.hp/watch-cmd.exp
@@ -0,0 +1,165 @@
+# Copyright (C) 1998 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+#
+# test special commands
+#
+set prms_id 0
+set bug_id 0
+
+set testfile "run-hp"
+set srcfile ${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug additional_flags=-DFAKEARGV}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+
+}
+
+# are we on a target board
+if ![isnative] then {
+ return
+}
+
+if {![istarget "hppa*-*-hpux10.30"] && ![istarget "hppa*-*-hpux11.*"]} {
+ #setup_xfail "*-*.*"
+ return 0
+}
+
+if [get_compiler_info ${binfile}] {
+ return -1;
+}
+if {[skip_hp_tests $gcc_compiled]} then { continue }
+
+
+gdb_exit
+gdb_start
+delete_breakpoints
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+
+
+proc watchpoint_command_test {} {
+ global gdb_prompt
+
+ if [target_info exists noargs] {
+ verbose "Skipping watchpoint_command_test because of noargs."
+ return
+ }
+
+ if { ![runto factorial] } then { gdb_suppress_tests }
+ # Don't depend upon argument passing, since most simulators don't currently
+ # support it. Bash value variable to be what we want.
+ gdb_test "p value=6" "" "set value to 6 in watchpoint_command_test"
+ delete_breakpoints
+
+ # Verify that we can create a watchpoint, and give it a commands
+ # list that continues the inferior. We set the watchpoint on a
+ # local variable, too, so that it self-deletes when the watched
+ # data goes out of scope.
+ #
+ # What should happen is: Each time the watchpoint triggers, it
+ # continues the inferior. Eventually, the watchpoint will self-
+ # delete, when the watched variable is out of scope. But by that
+ # time, the inferior should have exited. GDB shouldn't crash or
+ # anything untoward as a result of this.
+ #
+ send_gdb "watch local_var\n"
+ gdb_expect {
+ -re ".*\[Ww\]atchpoint (\[0-9\]*): local_var.*$gdb_prompt $"\
+ { pass "watch local_var"
+ set wp_id $expect_out(1,string)
+ send_gdb "commands $wp_id\n"
+ gdb_expect {
+ -re "Type commands for when breakpoint $wp_id is hit, one per line.*>"\
+ { pass "begin commands on watch"}
+ -re "$gdb_prompt $"\
+ {fail "begin commands on watch"}
+ timeout {fail "(timeout) begin commands on watch"}
+ }
+ }
+ -re "$gdb_prompt $"\
+ {fail "watch local_var"}
+ timeout {fail "(timeout) watch local_var"}
+ }
+# set wp_id $expect_out(1,string)
+# send_gdb "commands $wp_id\n"
+# gdb_expect {
+# -re "Type commands for when breakpoint $wp_id is hit, one per line.*>"\
+# {pass "begin commands on watch"}
+# -re "$gdb_prompt $"\
+# {fail "begin commands on watch"}
+# timeout {fail "(timeout) begin commands on watch"}
+# }
+ send_gdb "print value\n"
+ gdb_expect {
+ -re ">"\
+ {pass "add print command to watch"}
+ -re "$gdb_prompt $"\
+ {fail "add print command to watch"}
+ timeout {fail "(timeout) add print command to watch"}
+ }
+ send_gdb "continue\n"
+ gdb_expect {
+ -re ">"\
+ {pass "add continue command to watch"}
+ -re "$gdb_prompt $"\
+ {fail "add continue command to watch"}
+ timeout {fail "(timeout) add continue command to watch"}
+ }
+ send_gdb "end\n"
+ gdb_expect {
+ -re "$gdb_prompt $"\
+ {pass "begin commands on watch"}
+ timeout {fail "(timeout) begin commands on watch"}
+ }
+ send_gdb "continue\n"
+ gdb_expect {
+ -re "Continuing.*\[Ww\]atchpoint $wp_id deleted because the program has left the block in.*which its expression is valid.*in main.*$gdb_prompt $"\
+ {pass "continue with watch"}
+ -re "$gdb_prompt $"\
+ {fail "continue with watch"}
+ timeout {fail "(timeout) continue with watch"}
+ }
+ send_gdb "continue\n"
+ gdb_expect {
+ -re "Continuing.*$gdb_prompt $"\
+ {pass "continue until exit"}
+ -re "$gdb_prompt $"\
+ {fail "continue until exit"}
+ timeout {fail "(timeout) continue until exit"}
+ }
+}
+
+watchpoint_command_test
+
+
+
+
+
+
+
+
+
+
+
diff --git a/gdb/testsuite/gdb.hp/watch-hp.c b/gdb/testsuite/gdb.hp/watch-hp.c
new file mode 100644
index 00000000000..7336fe2bec8
--- /dev/null
+++ b/gdb/testsuite/gdb.hp/watch-hp.c
@@ -0,0 +1,166 @@
+#include <stdio.h>
+/*
+ * Since using watchpoints can be very slow, we have to take some pains to
+ * ensure that we don't run too long with them enabled or we run the risk
+ * of having the test timeout. To help avoid this, we insert some marker
+ * functions in the execution stream so we can set breakpoints at known
+ * locations, without worrying about invalidating line numbers by changing
+ * this file. We use null bodied functions are markers since gdb does
+ * not support breakpoints at labeled text points at this time.
+ *
+ * One place we need is a marker for when we start executing our tests
+ * instructions rather than any process startup code, so we insert one
+ * right after entering main(). Another is right before we finish, before
+ * we start executing any process termination code.
+ *
+ * Another problem we have to guard against, at least for the test
+ * suite, is that we need to ensure that the line that causes the
+ * watchpoint to be hit is still the current line when gdb notices
+ * the hit. Depending upon the specific code generated by the compiler,
+ * the instruction after the one that triggers the hit may be part of
+ * the same line or part of the next line. Thus we ensure that there
+ * are always some instructions to execute on the same line after the
+ * code that should trigger the hit.
+ */
+
+int count = -1;
+int ival1 = -1;
+int ival2 = -1;
+int ival3 = -1;
+int ival4 = -1;
+int ival5 = -1;
+char buf[10];
+struct foo
+{
+ int val;
+};
+struct foo struct1, struct2, *ptr1, *ptr2;
+
+int doread = 0;
+
+void marker1 ()
+{
+}
+
+void marker2 ()
+{
+}
+
+void marker4 ()
+{
+}
+
+void marker5 ()
+{
+}
+
+void marker6 ()
+{
+}
+
+void recurser (x)
+ int x;
+{
+ int local_x;
+
+ if (x > 0)
+ recurser (x-1);
+ local_x = x;
+}
+
+void
+func2 ()
+{
+ int local_a;
+ static int static_b;
+
+ ival5++;
+ local_a = ival5;
+ static_b = local_a;
+}
+
+int
+func1 ()
+{
+ /* The point of this is that we will set a breakpoint at this call.
+
+ Then, if DECR_PC_AFTER_BREAK equals the size of a function call
+ instruction (true on a sun3 if this is gcc-compiled--FIXME we
+ should use asm() to make it work for any compiler, present or
+ future), then we will end up branching to the location just after
+ the breakpoint. And we better not confuse that with hitting the
+ breakpoint. */
+ func2 ();
+ return 73;
+}
+
+int main ()
+{
+ struct1.val = 1;
+ struct2.val = 2;
+ ptr1 = &struct1;
+ ptr2 = &struct2;
+ marker1 ();
+ func1 ();
+ for (count = 0; count < 4; count++) {
+ ival1 = count;
+ ival3 = count; ival4 = count;
+ }
+ ival1 = count; /* Outside loop */
+ ival2 = count;
+ ival3 = count; ival4 = count;
+ marker2 ();
+ if (doread)
+ {
+ static char msg[] = "type stuff for buf now:";
+ write (1, msg, sizeof (msg) - 1);
+ read (0, &buf[0], 5);
+ }
+ marker4 ();
+
+ /* We have a watchpoint on ptr1->val. It should be triggered if
+ ptr1's value changes. */
+ ptr1 = ptr2;
+
+ /* This should not trigger the watchpoint. If it does, then we
+ used the wrong value chain to re-insert the watchpoints or we
+ are not evaluating the watchpoint expression correctly. */
+ struct1.val = 5;
+ marker5 ();
+
+ /* We have a watchpoint on ptr1->val. It should be triggered if
+ ptr1's value changes. */
+ ptr1 = ptr2;
+
+ /* This should not trigger the watchpoint. If it does, then we
+ used the wrong value chain to re-insert the watchpoints or we
+ are not evaluating the watchpoint expression correctly. */
+ struct1.val = 5;
+ marker5 ();
+
+ /* We're going to watch locals of func2, to see that out-of-scope
+ watchpoints are detected and properly deleted.
+ */
+ marker6 ();
+
+ /* This invocation is used for watches of a single
+ local variable. */
+ func2 ();
+
+ /* This invocation is used for watches of an expression
+ involving a local variable. */
+ func2 ();
+
+ /* This invocation is used for watches of a static
+ (non-stack-based) local variable. */
+ func2 ();
+
+ /* This invocation is used for watches of a local variable
+ when recursion happens.
+ */
+ marker6 ();
+ recurser (2);
+
+ marker6 ();
+ return 0;
+}
diff --git a/gdb/testsuite/gdb.hp/watch-hp.exp b/gdb/testsuite/gdb.hp/watch-hp.exp
new file mode 100644
index 00000000000..a1c3fc823f7
--- /dev/null
+++ b/gdb/testsuite/gdb.hp/watch-hp.exp
@@ -0,0 +1,784 @@
+# Copyright (C) 1992, 1994, 1997 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file was written by Fred Fish. (fnf@cygnus.com)
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+set prms_id 0
+set bug_id 0
+
+set testfile "watch-hp"
+set srcfile ${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+if [get_compiler_info ${binfile}] {
+ return -1;
+}
+if {[skip_hp_tests $gcc_compiled]} then { continue }
+
+# Prepare for watchpoint tests by setting up two breakpoints and one
+# watchpoint.
+#
+# We use breakpoints at marker functions to get past all the startup code,
+# so we can get to the watchpoints in a reasonable amount of time from a
+# known starting point.
+#
+# For simplicity, so we always know how to reference specific breakpoints or
+# watchpoints by number, we expect a particular ordering and numbering of
+# each in the combined breakpoint/watchpoint table, as follows:
+#
+# Number What Where
+# 1 Breakpoint marker1()
+# 2 Breakpoint marker2()
+# 3 Watchpoint ival3
+
+proc initialize {} {
+ global gdb_prompt
+ global hex
+ global decimal
+ global srcfile
+
+ if [gdb_test "break marker1" "Breakpoint 1 at $hex: file .*$srcfile, line $decimal.*" "set breakpoint at marker1" ] {
+ return 0;
+ }
+
+
+ if [gdb_test "break marker2" "Breakpoint 2 at $hex: file .*$srcfile, line $decimal.*" "set breakpoint at marker2" ] {
+ return 0;
+ }
+
+
+ if [gdb_test "info break" "1\[ \]*breakpoint.*marker1.*\r\n2\[ \]*breakpoint.*marker2.*" "info break in watchpoint.exp" ] {
+ return 0;
+ }
+
+# ??rehrauer: To fix DTS #CHFts23014, in which setting a watchpoint
+# before running can cause the inferior to croak on HP-UX 10.30 and
+# 11.0 for reasons as yet unknown, we've disabled the ability to set
+# watches without a running inferior. Verify the restriction.
+#
+ send_gdb "watch ival3\n"
+ gdb_expect {
+ -re ".*can't do that without a running program; try \"break main\", \"run\" first.*$gdb_prompt $" {
+ pass "set watchpoint on ival3"
+ }
+ -re ".*$gdb_prompt $" { fail "set watchpoint on ival3" }
+ timeout { fail "set watchpoint on ival3 (timeout)" }
+ }
+
+
+# if [gdb_test "watch ival3" ".*\[Ww\]atchpoint 3: ival3" "set watchpoint on ival3" ] {
+# return 0;
+# }
+
+
+ # "info watch" is the same as "info break"
+
+# if [gdb_test "info watch" "1\[ \]*breakpoint.*marker1.*\r\n2\[ \]*breakpoint.*marker2.*\r\n3\[ \]*.*watchpoint.*ival3" "watchpoint found in watchpoint/breakpoint table" ] {
+# return 0;
+# }
+
+
+ # After installing the watchpoint, we disable it until we are ready
+ # to use it. This allows the test program to run at full speed until
+ # we get to the first marker function.
+
+# if [gdb_test "disable 3" "disable 3\[\r\n\]+" "disable watchpoint" ] {
+# return 0;
+# }
+
+
+ return 1
+}
+
+#
+# Test simple watchpoint.
+#
+
+proc test_simple_watchpoint {} {
+ global gdb_prompt
+ global hex
+ global decimal
+
+ # Ensure that the watchpoint is disabled when we startup.
+
+# if [gdb_test "disable 3" "^disable 3\[\r\n\]+" "disable watchpoint in test_simple_watchpoint" ] {
+# return 0;
+# }
+
+
+ # Run until we get to the first marker function.
+
+ gdb_run_cmd
+ set timeout 600
+ gdb_expect {
+ -re "Breakpoint 1, marker1 .*$gdb_prompt $" {
+ pass "run to marker1 in test_simple_watchpoint"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "run to marker1 in test_simple_watchpoint"
+ return
+ }
+ timeout {
+ fail "run to marker1 in test_simple_watchpoint (timeout)"
+ return
+ }
+ }
+#************************
+
+# ??rehrauer: To fix DTS #CHFts23014, in which setting a watchpoint
+# before running can cause the inferior to croak on HP-UX 10.30 and
+# 11.0 for reasons as yet unknown, we've disabled the ability to set
+# watches without a running inferior. The following testpoints used
+# to be in [initialize].
+#
+ send_gdb "watch ival3\n"
+ gdb_expect {
+ -re ".*\[Ww\]atchpoint 3: ival3\r\n$gdb_prompt $" {
+ pass "set watchpoint on ival3"
+ }
+ -re ".*$gdb_prompt $" { fail "set watchpoint on ival3" }
+ timeout { fail "set watchpoint on ival3 (timeout)" }
+ }
+
+ # "info watch" is the same as "info break"
+
+ send_gdb "info watch\n"
+ gdb_expect {
+ -re "1\[ \]*breakpoint.*marker1.*\r\n2\[ \]*breakpoint.*marker2.*\r\n3\[ \]*.*watchpoint.*ival3\r\n$gdb_prompt $" {
+ pass "watchpoint found in watchpoint/breakpoint table"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "watchpoint found in watchpoint/breakpoint table"
+ }
+ timeout {
+ fail "watchpoint found in watchpoint/breakpoint table"
+ }
+ }
+
+ # After installing the watchpoint, we disable it until we are ready
+ # to use it. This allows the test program to run at full speed until
+ # we get to the first marker function.
+
+ send_gdb "disable 3\n"
+ gdb_expect {
+ -re "disable 3\[\r\n\]+$gdb_prompt $" { pass "disable watchpoint" }
+ -re ".*$gdb_prompt $" { fail "disable watchpoint" }
+ timeout { fail "disable watchpoint (timeout)" }
+ }
+#******
+ # After reaching the marker function, enable the watchpoint.
+
+ if [gdb_test "enable 3" "^enable 3\[\r\n\]+" "enable watchpoint" ] {
+ return ;
+ }
+
+
+ gdb_test "break func1" "Breakpoint.*at.*"
+ gdb_test "set \$func1_breakpoint_number = \$bpnum" ""
+
+ gdb_test "continue" "Continuing.*Breakpoint \[0-9\]*, func1.*" \
+ "continue to breakpoint at func1"
+
+ # Continue until the first change, from -1 to 0
+
+ send_gdb "cont\n"
+ gdb_expect {
+ -re "Continuing.*\[Ww\]atchpoint.*ival3.*Old value = -1.*New value = 0.*ival3 = count; ival4 = count;.*$gdb_prompt $" {
+ pass "watchpoint hit, first time"
+ }
+ -re "Continuing.*Breakpoint.*func1.*$gdb_prompt $" {
+ setup_xfail "m68*-*-*" 2597
+ fail "thought it hit breakpoint at func1 twice"
+ gdb_test "delete \$func1_breakpoint_number" ""
+ gdb_test "continue" "\
+Continuing.*\[Ww\]atchpoint.*ival3.*Old value = -1.*New value = 0.*ival3 = count;" \
+ "watchpoint hit, first time"
+ }
+ -re ".*$gdb_prompt $" { fail "watchpoint hit, first time" ; return }
+ timeout { fail "watchpoint hit, first time (timeout)" ; return }
+ eof { fail "watchpoint hit, first time (eof)" ; return }
+ }
+
+ gdb_test "delete \$func1_breakpoint_number" ""
+
+ # Continue until the next change, from 0 to 1.
+ gdb_test "cont" "Continuing.*\[Ww\]atchpoint.*ival3.*Old value = 0.*New value = 1.*ival3 = count; ival4 = count;.*" "watchpoint hit, second time"
+
+ # Continue until the next change, from 1 to 2.
+ gdb_test "cont" "Continuing.*\[Ww\]atchpoint.*ival3.*Old value = 1.*New value = 2.*ival3 = count; ival4 = count;.*" "watchpoint hit, third time"
+
+ # Continue until the next change, from 2 to 3.
+ gdb_test "cont" "Continuing.*\[Ww\]atchpoint.*ival3.*Old value = 2.*New value = 3.*ival3 = count; ival4 = count;.*" "watchpoint hit, fourth time"
+
+ # Continue until the next change, from 3 to 4.
+ # Note that this one is outside the loop.
+
+ gdb_test "cont" "Continuing.*\[Ww\]atchpoint.*ival3.*Old value = 3.*New value = 4.*ival3 = count; ival4 = count;.*" "watchpoint hit, fifth time"
+
+ # Continue until we hit the finishing marker function.
+ # Make sure we hit no more watchpoints.
+
+ gdb_test "cont" "Continuing.*Breakpoint.*marker2 \(\).*" \
+ "continue to marker2"
+
+ # Disable the watchpoint so we run at full speed until we exit.
+
+ if [gdb_test "disable 3" "^disable 3\[\r\n\]+" "watchpoint disabled" ] {
+ return ;
+ }
+
+
+ # Run until process exits.
+
+ if [target_info exists gdb,noresults] { return }
+
+ gdb_test "cont" "Continuing.*Program exited normally.*" \
+ "continue to exit in test_simple_watchpoint"
+}
+
+# Test disabling watchpoints.
+
+proc test_disabling_watchpoints {} {
+ global gdb_prompt
+ global binfile
+ global srcfile
+ global decimal
+ global hex
+
+ # Ensure that the watchpoint is disabled when we startup.
+
+ if [gdb_test "disable 3" "^disable 3\[\r\n\]+" "disable watchpoint in test_disabling_watchpoints" ] {
+ return 0;
+ }
+
+
+ # Run until we get to the first marker function.
+
+ gdb_run_cmd
+ set timeout 600
+ gdb_expect {
+ -re "Breakpoint 1, marker1 .*$gdb_prompt $" {
+ pass "run to marker1 in test_disabling_watchpoints"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "run to marker1 in test_disabling_watchpoints"
+ return
+ }
+ timeout {
+ fail "run to marker1 in test_disabling_watchpoints (timeout)"
+ return
+ }
+ }
+
+ # After reaching the marker function, enable the watchpoint.
+
+ if [gdb_test "enable 3" "^enable 3\[\r\n\]+" "watchpoint enabled" ] {
+ return ;
+ }
+
+
+ # Continue until the first change, from -1 to 0
+ # Don't check the old value, because on VxWorks the variable value
+ # will not have been reinitialized.
+ gdb_test "cont" "Continuing.*\[Ww\]atchpoint.*ival3.*Old value = .*New value = 0.*ival3 = count; ival4 = count;.*" "watchpoint hit in test_disabling_watchpoints, first time"
+
+ # Continue until the next change, from 0 to 1.
+ gdb_test "cont" "Continuing.*\[Ww\]atchpoint.*ival3.*Old value = 0.*New value = 1.*ival3 = count; ival4 = count;.*" "watchpoint hit in test_disabling_watchpoints, second time"
+
+ # Disable the watchpoint but leave breakpoints
+
+ if [gdb_test "disable 3" "^disable 3\[\r\n\]+" "disable watchpoint #2 in test_disabling_watchpoints" ] {
+ return 0;
+ }
+
+
+ # Check watchpoint list, looking for the entry that confirms the
+ # watchpoint is disabled.
+ gdb_test "info watchpoints" "3\[ \]*.*watchpoint\[ \]*keep\[ \]*n\[ \]*ival3\r\n.*" "watchpoint disabled in table"
+
+ # Continue until we hit the finishing marker function.
+ # Make sure we hit no more watchpoints.
+ gdb_test "cont" "Continuing.*Breakpoint.*marker2 \\(\\).*" \
+ "disabled watchpoint skipped"
+
+ if [target_info exists gdb,noresults] { return }
+
+ gdb_test "cont" "Continuing.*Program exited normally.*" \
+ "continue to exit in test_disabling_watchpoints"
+}
+
+# Test stepping and other mundane operations with watchpoints enabled
+proc test_stepping {} {
+ global gdb_prompt
+
+ if [runto marker1] then {
+ gdb_test "watch ival2" ".*\[Ww\]atchpoint \[0-9\]*: ival2"
+
+ # Well, let's not be too mundane. It should be a *bit* of a challenge
+ gdb_test "break func2 if 0" "Breakpoint.*at.*"
+ gdb_test "p \$func2_breakpoint_number = \$bpnum" " = .*"
+
+ # The HPPA has a problem here if it's not using hardware watchpoints
+ if {[ istarget "hppa*-*-*" ] && ![ istarget "hppa*-*-*bsd*" ]} then {
+ # Don't actually try doing the call, if we do we can't continue.
+ setup_xfail "*-*-*"
+ fail "calling function with watchpoint enabled"
+ } else {
+ # The problem is that GDB confuses stepping through the call
+ # dummy with hitting the breakpoint at the end of the call dummy.
+ # Will be fixed once all architectures define
+ # CALL_DUMMY_BREAKPOINT_OFFSET.
+ setup_xfail "*-*-*"
+ # This doesn't occur if the call dummy starts with a call,
+ # because we are out of the dummy by the first time the inferior
+ # stops.
+ clear_xfail "d10v*-*-*"
+ clear_xfail "m68*-*-*"
+ clear_xfail "i*86*-*-*"
+ clear_xfail "vax-*-*"
+ # The following architectures define CALL_DUMMY_BREAKPOINT_OFFSET.
+ clear_xfail "alpha-*-*"
+ clear_xfail "mips*-*-*"
+ clear_xfail "sparc-*-*"
+ clear_xfail "hppa*-*-*bsd*"
+ # It works with the generic inferior function calling code too.
+ clear_xfail "mn10200*-*-*"
+ clear_xfail "mn10300*-*-*"
+ gdb_test "p func1 ()" "= 73" \
+ "calling function with watchpoint enabled"
+ }
+
+ #
+ # "finish" brings us back to main.
+ # On some targets (e.g. alpha) gdb will stop from the finish in midline
+ # of the marker1 call. This is due to register restoring code on
+ # the alpha and might be caused by stack adjustment instructions
+ # on other targets. In this case we will step once more.
+ #
+
+ send_gdb "finish\n"
+ gdb_expect {
+ -re "Run.*exit from.*marker1.* at" { }
+ default { fail "finish from marker1" ; return }
+ }
+
+ gdb_expect {
+ -re "marker1 \\(\\);.*$gdb_prompt $" {
+ send_gdb "step\n"
+ exp_continue
+ }
+ -re "func1 \\(\\);.*$gdb_prompt $" {
+ pass "finish from marker1"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "finish from marker1"
+ }
+ default { fail "finish from marker1" ; return }
+ }
+
+ gdb_test "next" "for \\(count = 0.*" "next to `for' in watchpoint.exp"
+
+ # Now test that "until" works. It's a bit tricky to test
+ # "until", because compilers don't always arrange the code
+ # exactly the same way, and we might get slightly different
+ # sequences of statements. But the following should be true
+ # (if not it is a compiler or a debugger bug): The user who
+ # does "until" at every statement of a loop should end up
+ # stepping through the loop once, and the debugger should not
+ # stop for any of the remaining iterations.
+
+ gdb_test "until" "ival1 = count.*" "until to ival1 assignment"
+ gdb_test "until" "ival3 = count.*" "until to ival3 assignment"
+ send_gdb "until\n"
+ gdb_expect {
+ -re "(for \\(count = 0|\}).*$gdb_prompt $" {
+ gdb_test "until" "ival1 = count; /. Outside loop ./" \
+ "until out of loop"
+ }
+ -re "ival1 = count; /. Outside loop ./.*$gdb_prompt $" {
+ pass "until out of loop"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "until out of loop"
+ }
+ default { fail "until out of loop" ; return }
+ }
+
+ gdb_test "step" "ival2 = count.*" "step to ival2 assignment"
+ }
+}
+
+# Test stepping and other mundane operations with watchpoints enabled
+proc test_watchpoint_triggered_in_syscall {} {
+ global gdb_prompt
+
+ if [target_info exists gdb,noinferiorio] {
+ verbose "Skipping test_watchpoint_triggered_in_syscall due to noinferiorio"
+ return
+ }
+ # Run until we get to the first marker function.
+ set x 0
+ set y 0
+ set testname "Watch buffer passed to read syscall"
+ if [runto marker2] then {
+ gdb_test "watch buf\[0\]" ".*\[Ww\]atchpoint \[0-9\]*: buf\\\[0\\\]"
+ gdb_test "watch buf\[1\]" ".*\[Ww\]atchpoint \[0-9\]*: buf\\\[1\\\]"
+ gdb_test "watch buf\[2\]" ".*\[Ww\]atchpoint \[0-9\]*: buf\\\[2\\\]"
+ gdb_test "watch buf\[3\]" ".*\[Ww\]atchpoint \[0-9\]*: buf\\\[3\\\]"
+ gdb_test "watch buf\[4\]" ".*\[Ww\]atchpoint \[0-9\]*: buf\\\[4\\\]"
+ gdb_test "break marker4" ".*Breakpoint.*"
+
+ gdb_test "set doread = 1" ""
+
+ # If we send_gdb "123\n" before gdb has switched the tty, then it goes
+ # to gdb, not the inferior, and we lose. So that is why we have
+ # watchpoint.c prompt us, so we can wait for that prompt.
+ send_gdb "continue\n";
+ gdb_expect {
+ -re "Continuing\\.\r\ntype stuff for buf now:" {
+ pass "continue to read"
+ }
+ default {
+ fail "continue to read";
+ return ;
+ }
+ }
+
+ send_gdb "123\n"
+ gdb_expect {
+ -re ".*\[Ww\]atchpoint.*buf\\\[0\\\].*Old value = 0.*New value = 49\[^\n\]*\n" { set x [expr $x+1] ; exp_continue }
+ -re ".*\[Ww\]atchpoint.*buf\\\[1\\\].*Old value = 0.*New value = 50\[^\n\]*\n" { set x [expr $x+1] ; exp_continue }
+ -re ".*\[Ww\]atchpoint.*buf\\\[2\\\].*Old value = 0.*New value = 51\[^\n\]*\n" { set x [expr $x+1] ; exp_continue }
+ -re ".*\[Ww\]atchpoint.*buf\\\[3\\\].*Old value = 0.*New value = 10\[^\n\]*\n" { set x [expr $x+1] ; exp_continue }
+ -re ".*$gdb_prompt $" { pass "sent 123" }
+ timeout { fail "sent 123 (timeout)" }
+ }
+
+ # Examine the values in buf to see how many watchpoints we
+ # should have printed.
+ send_gdb "print buf\[0\]\n"
+ gdb_expect {
+ -re ".*= 49.*$gdb_prompt $" { set y [expr $y+1]; pass "print buf\[0\]"}
+ -re ".*= 0.*$gdb_prompt $" { pass "print buf\[0\]"}
+ -re ".*$gdb_prompt $" { fail "print buf\[0\]"}
+ default { fail "print buf\[0\]"}
+ }
+ send_gdb "print buf\[1\]\n"
+ gdb_expect {
+ -re ".*= 50.*$gdb_prompt $" { set y [expr $y+1]; pass "print buf\[1\]"}
+ -re ".*= 0.*$gdb_prompt $" { pass "print buf\[1\]"}
+ -re ".*$gdb_prompt $" { fail "print buf\[1\]"}
+ default { fail "print buf\[1\]"}
+ }
+ send_gdb "print buf\[2\]\n"
+ gdb_expect {
+ -re ".*= 51.*$gdb_prompt $" { set y [expr $y+1]; pass "print buf\[2\]"}
+ -re ".*= 0.*$gdb_prompt $" { pass "print buf\[2\]"}
+ -re ".*$gdb_prompt $" { fail "print buf\[2\]"}
+ default { fail "print buf\[2\]"}
+ }
+ send_gdb "print buf\[3\]\n"
+ gdb_expect {
+ -re ".*= 10.*$gdb_prompt $" { set y [expr $y+1]; pass "print buf\[3\]"}
+ -re ".*= 0.*$gdb_prompt $" { pass "print buf\[3\]"}
+ -re ".*$gdb_prompt $" { fail "print buf\[3\]" }
+ default { fail "print buf\[3\]" }
+ }
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x==$y] then { pass $testname } else { fail "$testname (only triggered $x watchpoints, expected $y)"}
+
+ # Continue until we hit the finishing marker function.
+ # Make sure we hit no more watchpoints.
+ gdb_test "cont" "Continuing.*Breakpoint.*marker4 \\(\\).*" \
+ "continue to marker4"
+
+ # Disable everything so we can finish the program at full speed
+ gdb_test "disable" "" "disable in test_watchpoint_triggered_in_syscall"
+
+ if [target_info exists gdb,noresults] { return }
+
+ gdb_test "cont" "Continuing.*Program exited normally.*" \
+ "continue to exit in test_watchpoint_triggered_in_syscall"
+ }
+}
+
+# Do a simple test of of watching through a pointer when the pointer
+# itself changes. Should add some more complicated stuff here.
+
+proc test_complex_watchpoint {} {
+ global gdb_prompt
+
+ if [runto marker4] then {
+ gdb_test "watch ptr1->val" ".*\[Ww\]atchpoint \[0-9\]*: ptr1->val"
+ gdb_test "break marker5" ".*Breakpoint.*"
+
+ gdb_test "cont" "Continuing.*\[Ww\]atchpoint.*ptr1->val.*Old value = 1.*New value = 2.*" "Test complex watchpoint"
+
+ # Continue until we hit the marker5 function.
+ # Make sure we hit no more watchpoints.
+
+ gdb_test "cont" "Continuing.*Breakpoint.*marker5 \\(\\).*" \
+ "did not trigger wrong watchpoint"
+#********************
+ # Test watches of things declared locally in a function.
+ # In particular, test that a watch of stack-based things
+ # is deleted when the stack-based things go out of scope.
+ #
+ gdb_test "disable" "" "disable in test_complex_watchpoint"
+ gdb_test "break marker6" ".*Breakpoint.*"
+ gdb_test "cont" "Continuing.*Breakpoint.*marker6 \\(\\).*" \
+ "continue to marker6"
+ gdb_test "break func2" ".*Breakpoint.*"
+ gdb_test "cont" "Continuing.*func2.*"
+
+ # Test a watch of a single stack-based variable, whose scope
+ # is the function we're now in. This should auto-delete when
+ # execution exits the scope of the watchpoint.
+ #
+ gdb_test "watch local_a" ".*\[Ww\]atchpoint \[0-9\]*: local_a" "set local watch"
+ gdb_test "cont" "\[Ww\]atchpoint.*local_a.*" "trigger local watch"
+ gdb_test "cont" "Continuing.*Watchpoint .* deleted because the program has left the block in.*which its expression is valid.*" "self-delete local watch"
+
+ # after func2 returned, gdb stopped and deleted the watchpoint
+ # we're now in main, let's get to func2
+ gdb_test "cont" "Continuing.*func2.*"
+
+ # We should be in "func2" again now. Test a watch of an
+ # expression which includes both a stack-based local and
+ # something whose scope is larger than this invocation
+ # of "func2". This should also auto-delete.
+ #
+ gdb_test "watch local_a + ival5" ".*\[Ww\]atchpoint \[0-9\]*: local_a . ival5" \
+ "set partially local watch"
+ gdb_test "cont" "Continuing.*\[Ww\]atchpoint .*: local_a . ival5.*" \
+ "trigger1 partially local watch"
+ gdb_test "cont" "Continuing.*\[Ww\]atchpoint .*: local_a . ival5.*" \
+ "trigger2 partially local watch"
+ gdb_test "cont" "Continuing.*\[Ww\]atchpoint .* deleted because the program has left the block in.*which its expression is valid.*" \
+ "self-delete partially local watch"
+
+ # after func2 returned, gdb stopped and deleted the watchpoint
+ # we're now in main, let's get to func2
+ gdb_test "cont" "Continuing.*func2.*"
+
+ # We should be in "func2" again now. Test a watch of a
+ # static (non-stack-based) local. Since this has scope
+ # across any invocations of "func2", it should not auto-
+ # delete.
+ #
+ gdb_test "watch static_b" ".*\[Ww\]atchpoint \[0-9\]*: static_b" \
+ "set static local watch"
+ gdb_test "cont" "Continuing.*\[Ww\]atchpoint .*: static_b.*" \
+ "trigger static local watch"
+ gdb_test "cont" "Continuing.*marker6 \\(\\).*" \
+ "continue after trigger static local watch"
+ gdb_test "info break" ".*watchpoint.*static_b.*" \
+ "static local watch did not self-delete"
+
+ # We should be in "recurser" now. Test a watch of a stack-
+ # based local. Symbols mentioned in a watchpoint are bound
+ # at watchpoint-creation. Thus, a watch of a stack-based
+ # local to a recursing function should be bound only to that
+ # one invocation, and should not trigger for other invocations.
+ #
+ gdb_test "tbreak recurser" ".*Breakpoint.*"
+ gdb_test "cont" "Continuing.*recurser.*"
+ gdb_test "watch local_x" ".*\[Ww\]atchpoint \[0-9\]*: local_x" \
+ "set local watch in recursive call"
+ gdb_test "cont" "Continuing.*\[Ww\]atchpoint .*: local_x.*New value = 2.*" \
+ "trigger local watch in recursive call"
+ gdb_test "cont" "Continuing.*\[Ww\]atchpoint .* deleted because the program has left the block in.*which its expression is valid.*" \
+ "self-delete local watch in recursive call"
+
+
+
+
+#******************
+ # Disable everything so we can finish the program at full speed
+ gdb_test "disable" "" "disable in test_complex_watchpoint"
+
+ if [target_info exists gdb,noresults] { return }
+
+
+ gdb_test "cont" "Continuing.*Program exited normally.*" \
+ "continue to exit in test_complex_watchpoint"
+ }
+}
+
+# Start with a fresh gdb.
+
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load $binfile
+set timeout 600
+verbose "Timeout now 600 sec.\n"
+
+if [initialize] then {
+
+ test_simple_watchpoint
+
+ # The IDT/sim monitor only has 8 (!) open files, of which it uses
+ # 4 (!). So we have to make sure one program exits before
+ # starting another one.
+ if [istarget "mips-idt-*"] then {
+ gdb_exit
+ gdb_start
+ gdb_reinitialize_dir $srcdir/$subdir
+ gdb_load $binfile
+ initialize
+ }
+
+ test_disabling_watchpoints
+
+ # See above.
+ if [istarget "mips-idt-*"] then {
+ gdb_exit
+ gdb_start
+ gdb_reinitialize_dir $srcdir/$subdir
+ gdb_load $binfile
+ initialize
+ }
+
+ if ![target_info exists gdb,cannot_call_functions] {
+ test_stepping
+
+ # See above.
+ if [istarget "mips-idt-*"] then {
+ gdb_exit
+ gdb_start
+ gdb_reinitialize_dir $srcdir/$subdir
+ gdb_load $binfile
+ initialize
+ }
+ }
+
+ # Only enabled for some targets merely because it has not been tested
+ # elsewhere.
+ # On sparc-sun-sunos4.1.3, GDB was running all the way to the marker4
+ # breakpoint before stopping for the watchpoint. I don't know why.
+ if {[istarget "hppa*-*-*"]} then {
+ test_watchpoint_triggered_in_syscall
+ }
+
+ # See above.
+ if [istarget "mips-idt-*"] then {
+ gdb_exit
+ gdb_start
+ gdb_reinitialize_dir $srcdir/$subdir
+ gdb_load $binfile
+ initialize
+ }
+
+ # Only enabled for some targets merely because it has not been tested
+ # elsewhere.
+ if {[istarget "hppa*-*-*"] || \
+ [istarget "sparc*-*-sunos*"] || \
+ [istarget "m32r-*-*"]} then {
+ test_complex_watchpoint
+#***************
+ }
+
+ # Verify that a user can force GDB to use "slow" watchpoints.
+ # (This proves rather little on kernels that don't support
+ # fast watchpoints, but still...)
+ #
+ if ![runto_main] then { fail "watch tests suppressed" }
+
+ send_gdb "set can-use-hw-watchpoints 0\n"
+ gdb_expect {
+ -re "$gdb_prompt $"\
+ {pass "disable fast watches"}
+ timeout {fail "(timeout) disable fast watches"}
+ }
+ send_gdb "show can-use-hw-watchpoints\n"
+ gdb_expect {
+ -re "Debugger's willingness to use watchpoint hardware is 0.*$gdb_prompt $"\
+ {pass "show disable fast watches"}
+ -re "$gdb_prompt $"\
+ {fail "show disable fast watches"}
+ timeout {fail "(timeout) show disable fast watches"}
+ }
+ send_gdb "watch ival3 if count > 1\n"
+ gdb_expect {
+ -re "Watchpoint \[0-9\]*: ival3.*$gdb_prompt $"\
+ {pass "set slow conditional watch"}
+ -re "$gdb_prompt $"\
+ {fail "set slow conditional watch"}
+ timeout {fail "(timeout) set slow conditional watch"}
+ }
+ send_gdb "continue\n"
+ gdb_expect {
+ -re "Watchpoint \[0-9\]*: ival3.*Old value = 1.*New value = 2.*$gdb_prompt $"\
+ {pass "trigger slow conditional watch"}
+ -re "$gdb_prompt $"\
+ {fail "trigger slow conditional watch"}
+ timeout {fail "(timeout) trigger slow conditional watch"}
+ }
+
+ # We've explicitly disabled hardware watches. Verify that GDB
+ #
+ #
+ send_gdb "rwatch ival3\n"
+ gdb_expect {
+ -re "Expression cannot be implemented with read/access watchpoint..*$gdb_prompt $"\
+ {pass "rwatch disallowed when can-set-hw-watchpoints cleared"}
+ -re "$gdb_prompt $"\
+ {fail "rwatch disallowed when can-set-hw-watchpoints cleared"}
+ timeout {fail "(timeout) rwatch disallowed when can-use-hw-watchpoints cleared"}
+ }
+
+ # Read- and access watchpoints are unsupported on HP-UX. Verify
+ # that GDB gracefully responds to requests to create them.
+ #
+ if [istarget "hppa*-*-hpux*"] then {
+ send_gdb "set can-use-hw-watchpoints 1\n"
+ gdb_expect {
+ -re "$gdb_prompt $"\
+ {pass "enable fast watches"}
+ timeout {fail "(timeout) enable fast watches"}
+ }
+ send_gdb "rwatch ival3\n"
+ gdb_expect {
+ -re "Target does not have this type of hardware watchpoint support.*$gdb_prompt $"\
+ {pass "read watches disallowed"}
+ -re "$gdb_prompt $"\
+ {fail "read watches disallowed"}
+ timeout {fail "(timeout) read watches disallowed"}
+ }
+
+ send_gdb "awatch ival3\n"
+ gdb_expect {
+ -re "Target does not have this type of hardware watchpoint support.*$gdb_prompt $"\
+ {pass "access watches disallowed"}
+ -re "$gdb_prompt $"\
+ {fail "access watches disallowed"}
+ timeout {fail "(timeout) access watches disallowed"}
+ }
+
+#***************
+ }
+}
diff --git a/gdb/testsuite/gdb.hp/xdb.c b/gdb/testsuite/gdb.hp/xdb.c
new file mode 100644
index 00000000000..e3e3fc23e9f
--- /dev/null
+++ b/gdb/testsuite/gdb.hp/xdb.c
@@ -0,0 +1,20 @@
+#include <stdio.h>
+
+int callee( x )
+int x;
+{
+ int y = x * x;
+ return (y - 2);
+}
+
+main()
+{
+ int i;
+ for (i = 1; i < 10; i++)
+ {
+ printf( "%d ", callee( i ));
+
+ }
+ printf( " Goodbye!\n" );
+
+}
diff --git a/gdb/testsuite/gdb.hp/xdb0.c b/gdb/testsuite/gdb.hp/xdb0.c
new file mode 100644
index 00000000000..fa5c76f7418
--- /dev/null
+++ b/gdb/testsuite/gdb.hp/xdb0.c
@@ -0,0 +1,42 @@
+#include "xdb0.h"
+
+main ()
+{
+ int x;
+#ifdef usestubs
+ set_debug_traps();
+ breakpoint();
+#endif
+ x = 0;
+ foo (x++);
+ foo (x++);
+ foo (x++);
+ foo (x++);
+ foo (x++);
+ foo (x++);
+ foo (x++);
+ foo (x++);
+ foo (x++);
+ foo (x++);
+ foo (x++);
+ foo (x++);
+ foo (x++);
+ foo (x++);
+ foo (x++);
+ foo (x++);
+ foo (x++);
+ foo (x++);
+ foo (x++);
+ foo (x++);
+ foo (x++);
+ foo (x++);
+ foo (x++);
+ foo (x++);
+ foo (x++);
+}
+
+static void
+unused ()
+{
+ /* Not used for anything */
+}
diff --git a/gdb/testsuite/gdb.hp/xdb0.h b/gdb/testsuite/gdb.hp/xdb0.h
new file mode 100644
index 00000000000..c4d337c6770
--- /dev/null
+++ b/gdb/testsuite/gdb.hp/xdb0.h
@@ -0,0 +1,36 @@
+/* An include file that actually causes code to be generated in the
+ including file. This is known to cause problems on some systems. */
+
+static void
+foo (x)
+int x;
+{
+ bar (x++);
+ bar (x++);
+ bar (x++);
+ bar (x++);
+ bar (x++);
+ bar (x++);
+ bar (x++);
+ bar (x++);
+ bar (x++);
+ bar (x++);
+ bar (x++);
+ bar (x++);
+ bar (x++);
+ bar (x++);
+ bar (x++);
+ bar (x++);
+ bar (x++);
+ bar (x++);
+ bar (x++);
+ bar (x++);
+ bar (x++);
+ bar (x++);
+ bar (x++);
+ bar (x++);
+ bar (x++);
+ bar (x++);
+ bar (x++);
+ bar (x++);
+}
diff --git a/gdb/testsuite/gdb.hp/xdb1.c b/gdb/testsuite/gdb.hp/xdb1.c
new file mode 100644
index 00000000000..51632b94d07
--- /dev/null
+++ b/gdb/testsuite/gdb.hp/xdb1.c
@@ -0,0 +1,33 @@
+void
+bar (x)
+int x;
+{
+ printf ("%d\n", x);
+
+ long_line ();
+}
+
+static void
+unused ()
+{
+ /* Not used for anything */
+}
+
+
+/* This routine has a very long line that will break searching in older
+ versions of GDB. */
+
+long_line ()
+{
+ oof (67);
+
+ oof (6789);
+
+ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* 5 */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* 10 */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* 15 */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* 20 */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* 25 */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* 30 */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* 35 */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* 40 */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* 45 */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* 50 */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* 55 */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* 60 */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* 65 */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (1234); /* 70 */
+}
+
+oof (n)
+ int n;
+{
+ return n + 1;
+}
diff --git a/gdb/testsuite/gdb.hp/xdb1.exp b/gdb/testsuite/gdb.hp/xdb1.exp
new file mode 100644
index 00000000000..88ab2fc5864
--- /dev/null
+++ b/gdb/testsuite/gdb.hp/xdb1.exp
@@ -0,0 +1,77 @@
+# Copyright (C) 1992, 1994, 1995 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file was written by Fred Fish. (fnf@cygnus.com)
+
+if $tracelevel then {
+ strace $tracelevel
+ }
+
+
+global usestubs
+
+#
+# test running programs
+#
+set prms_id 0
+set bug_id 0
+
+set testfile "xdb"
+set srcfile ${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+if [get_compiler_info ${binfile}] {
+ return -1;
+}
+if {[skip_hp_tests $gcc_compiled]} then { continue }
+
+global GDBFLAGS
+set saved_gdbflags $GDBFLAGS
+
+set GDBFLAGS "$GDBFLAGS --xdb"
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+gdb_test "set pagination off" ""
+gdb_test "show pagination" "State of pagination is off."
+gdb_test "set pagination on" ""
+gdb_test "show pagination" "State of pagination is on."
+
+gdb_test "txbreak callee" "Breakpoint.*at.*"
+gdb_test "info break" "Num.*Type.*Disp.*Enb.*Address.*What\r\n.*breakpoint.*del.*y.*"
+
+gdb_test "xbreak callee" "Breakpoint.*at.*.*"
+gdb_test "info break" "Num.*Type.*Disp.*Enb.*Address.*What\r\n.*breakpoint.*keep.*y.*"
+
+gdb_exit
+set GDBFLAGS $saved_gdbflags
+return 0
+
+
+
+
+
+
+
diff --git a/gdb/testsuite/gdb.hp/xdb2.exp b/gdb/testsuite/gdb.hp/xdb2.exp
new file mode 100644
index 00000000000..4cc7b341e09
--- /dev/null
+++ b/gdb/testsuite/gdb.hp/xdb2.exp
@@ -0,0 +1,104 @@
+# Copyright (C) 1992, 1994, 1995 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file was written by Fred Fish. (fnf@cygnus.com)
+
+if $tracelevel then {
+ strace $tracelevel
+ }
+
+global message
+
+#
+# test running programs
+#
+set prms_id 0
+set bug_id 0
+
+set testfile "xdb"
+set binfile ${objdir}/${subdir}/${testfile}
+
+if { [gdb_compile "${srcdir}/${subdir}/xdb0.c" "${binfile}0.o" object {debug}] != "" } {
+ perror "Couldn't compile ${testfile}0.c to object"
+ return -1
+}
+
+if { [gdb_compile "${srcdir}/${subdir}/xdb1.c" "${binfile}1.o" object {debug}] != "" } {
+ perror "Couldn't compile ${testfile}1.c to object"
+ return -1
+}
+
+if { [gdb_compile "${binfile}0.o ${binfile}1.o" ${binfile} executable {debug}] != "" } {
+ perror "Couldn't link ${testfile}."
+ return -1
+}
+
+
+if [get_compiler_info ${binfile}] {
+ return -1;
+}
+if {[skip_hp_tests $gcc_compiled]} then { continue }
+
+
+global GDBFLAGS
+set saved_gdbflags $GDBFLAGS
+set GDBFLAGS "$GDBFLAGS --xdb"
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+gdb_test "break main" ""
+gdb_test "run" ""
+gdb_test "go +2" "Breakpoint.*at.*file.*xdb0\.c, line 12\.\r\nContinuing at.*\r\nmain \\(\\) at.*xdb0\.c:12\r\n12\[ \t\]+foo \\(x\\+\\+\\);"
+gdb_test "go -2" "Note: breakpoint.*also set at pc.*\.\r\nBreakpoint.*at.*file.*xdb0\.c, line 10\.\r\nContinuing at.*\.\r\n\r\nBreakpoint.*, main \\(\\) at.*xdb0\.c:10.*"
+gdb_test "go 16" "Breakpoint.*at.*file.*xdb0\.c, line 16\.\r\nContinuing at.*\.\r\nmain \\(\\) at.*xdb0\.c:16\r\n16\[ \t\]+foo \\(x\\+\\+\\);"
+
+send_gdb "go bar\n"
+ gdb_expect {
+ -re ".*Line 5 is not in .main.. Jump anyway.*y or n. $" {
+ send_gdb "y\n"
+ gdb_expect {
+ -re "$gdb_prompt $"\
+ {pass "go bar"}
+ timeout {fail "(timeout) go bar"}
+ }
+ }
+ -re "Continuing at.*\.\r\nbar \\(x=0\\) at.*xdb1\.c:5" {}
+ timeout { perror "(timeout) go bar" ; return }
+ }
+
+# Verify that GDB responds gracefully to a "go" command without
+# an argument.
+#
+gdb_test "go" "Usage: go <location>"
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+gdb_test "break bar" ""
+gdb_test "run" ""
+gdb_test "backtrace full" ".*bar \\(x=0\\) at.*xdb1\.c:5\r\nNo locals\.\r\n.1.* in foo \\(x=1\\) at.*xdb0\.h:8\r\nNo locals\.\r\n.2.* in main \\(\\) at.*xdb0\.c:11\r\n.*x = 1"
+gdb_test "bt 1 full" ".*bar \\(x=0\\) at.*xdb1\.c:5\r\nNo locals\.\r\n\\(More stack frames follow\.\.\.\\)"
+gdb_test "bt full 2" ".*bar \\(x=0\\) at.*xdb1\.c:5\r\nNo locals\.\r\n.1.* in foo \\(x=1\\) at.*xdb0\.h:8\r\nNo locals\.\r\n\\(More stack frames follow\.\.\.\\)"
+
+set GDBFLAGS $saved_gdbflags
+return 0
diff --git a/gdb/testsuite/gdb.hp/xdb3.exp b/gdb/testsuite/gdb.hp/xdb3.exp
new file mode 100644
index 00000000000..cf569e9511c
--- /dev/null
+++ b/gdb/testsuite/gdb.hp/xdb3.exp
@@ -0,0 +1,307 @@
+# Copyright (C) 1998 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+
+set testfile1 "average"
+set testfile2 "sum"
+set testfile "xdb-test"
+set binfile1 ${objdir}/${subdir}/${testfile1}
+set binfile2 ${objdir}/${subdir}/${testfile2}
+set binfile ${objdir}/${subdir}/${testfile}
+
+if { [gdb_compile "${srcdir}/${subdir}/average.c" "${binfile1}.o" object {debug}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+if { [gdb_compile "${srcdir}/${subdir}/sum.c" "${binfile2}.o" object {debug}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+if { [gdb_compile "${binfile1}.o ${binfile2}.o" ${binfile} executable {debug}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+if [get_compiler_info ${binfile}] {
+ return -1;
+}
+if {[skip_hp_tests $gcc_compiled]} then { continue }
+
+
+proc xdb_reinitialize_dir { subdir } {
+ global gdb_prompt
+
+ send_gdb "D\n"
+ gdb_expect {
+ -re "Reinitialize source path to empty.*y or n. " {
+ send_gdb "y\n"
+ gdb_expect {
+ -re "Source directories searched.*$gdb_prompt $" {
+ send_gdb "D $subdir\n"
+ gdb_expect {
+ -re "Source directories searched.*$gdb_prompt $" {
+ verbose "Dir set to $subdir"
+ }
+ -re ".*$gdb_prompt $" {
+ perror "Dir \"$subdir\" failed."
+ }
+ }
+ }
+ -re ".*$gdb_prompt $" {
+ perror "Dir \"$subdir\" failed."
+ }
+ }
+ }
+ -re ".*$gdb_prompt $" {
+ perror "Dir \"$subdir\" failed."
+ }
+ }
+}
+
+#
+#test_search
+#
+proc test_search { } {
+ gdb_test "set listsize 4" ""
+ gdb_test "list average.c:1" "1\[ \t\]+/. This is a sample .*"
+ gdb_test "/ print_average" "10\[ \t\]+void print_average\\(int list.*"
+ gdb_test "/ print_average" "12\[ \t\]+void print_average\\(list, low, high\\)"
+ gdb_test "/ print_average" "35\[ \t\]+print_average \\(my_list, first, last\\);"
+ gdb_test "? print_average" "12\[ \t\]+void print_average\\(list, low, high\\)"
+ gdb_test "? sum" "Expression not found"
+}
+
+#
+#test_viewing_loc
+#
+proc test_viewing_loc { } {
+ gdb_test "L" "No stack."
+ gdb_test "break main" ""
+ gdb_test "R" ""
+ gdb_test "L" "#0\[ \t\]+main \\(\\) at.*average.c:31\r\n31\[ \t\]+int first = 0;"
+}
+
+#
+#test_dir_list
+#
+proc test_dir_list { } {
+ gdb_test "ld" "Source directories searched: .*"
+}
+
+#
+#test_list_sources
+#
+proc test_list_sources { } {
+ gdb_test "lf" "Source files for which symbols have been read in:.*average\\.c,.*Source files for which symbols will be read in on demand:.*sum\\.c"
+}
+
+#
+#test_vlist
+#
+proc test_vlist { } {
+ gdb_test "v main" "27\[ \t\]+main \\(\\)\r\n28\[ \t\]+#endif\r\n29\[ \t\]+.\r\n30\[ \t\]+char c;"
+}
+
+#
+#test_va
+#
+proc test_va { } {
+ gdb_test "va main" "Dump of assembler code for function main:.*End of assembler dump\."
+}
+
+#
+#test_list_globals
+#
+proc test_list_globals { } {
+ gdb_test "lg" "All defined variables:\r\n\r\nFile globals:.*"
+# gdb_test "lg" "All defined variables:\r\n\r\nFile globals:\r\nchar __buffer.512.;\r\nint __d_eh_catch_catch;\r\nint __d_eh_catch_throw;.*"
+}
+
+#
+#test_list_registers
+#
+proc test_list_registers { } {
+ gdb_test "lr" "\[ \t\]+flags:.*r18:.*pcsqt:.*ccr:.*\r\n\[ \t\]+r1:.*r19:.*eiem:.*cr12:.*"
+ gdb_test "lr r1" "r1 .*"
+}
+
+#
+#test_backtrace
+#
+proc test_backtrace { } {
+ gdb_test "t" "#0 main \\(\\) at.*average.c:31"
+ gdb_test "T" "#0 main \\(\\) at.*average.c:31\r\n\[ \t\]+c = 0.*\r\n\[ \t\]+first = 0\r\n\[ \t\]+last = 0"
+
+ gdb_test "break sum" ""
+ gdb_test "cont" ""
+
+ gdb_test "t" "#0 sum \\(list=0x.*, low=0, high=9\\) at.*sum\.c:11\r\n#1 0x.* in print_average \\(list=0x.*, low=0, high=9\\) at.*average\.c:17\r\n#2 0x.* in main \\(\\) at.*average\.c:35"
+ gdb_test "t 1" "#0 sum \\(list=0x.*, low=0, high=9\\) at.*sum\.c:11\r\n\\(More stack frames follow\.\.\.\\)"
+ gdb_test "T" "#0 sum \\(list=0x.*, low=0, high=9\\) at.*sum\.c:11\r\n\[ \t\]+i = 0\r\n\[ \t\]+s = 0\r\n#1 0x.* in print_average \\(list=0x.*, low=0, high=9\\) at.*average\.c:17\r\n\[ \t\]+total = 0\r\n\[ \t\]+num_elements = 0\r\n\[ \t\]+average = 0\r\n#2 0x.* in main \\(\\) at.*average\.c:35\r\n\[ \t\]+c = 0 '.000'\r\n\[ \t\]+first = 0\r\n\[ \t\]+last = 9"
+ gdb_test "T 1" "#0 sum \\(list=0x.*, low=0, high=9\\) at.*sum\.c:11\r\n\[ \t\]+i = 0\r\n\[ \t\]+s = 0\r\n\\(More stack frames follow\.\.\.\\)"
+
+ gdb_test "V" "#0 sum \\(list=0x.*, low=0, high=9\\) at.*sum\.c:11\r\n\\11\[ \t\]+int i, s = 0;"
+ gdb_test "V 1" "#1 0x.* in print_average \\(list=0x.*, low=0, high=9\\) at.*average\.c:17\r\n17\[ \t\]+total = sum\\(list, low, high\\);"
+}
+
+#
+# test_go
+#
+proc test_go { } {
+ gdb_test "break main" ""
+ gdb_test "R" ""
+
+ gdb_test "g +1" "Breakpoint.*at 0x.*: file.*average\.c, line 32\.\r\nContinuing at 0x.*\.\r\nmain \\(\\) at.*average\.c:32\r\n32\[ \t\]+int last = num-1;"
+ gdb_test "g 35" "Breakpoint.*at 0x.*: file.*average\.c, line 35\.\r\nContinuing at 0x.*\.\r\nmain \\(\\) at.*average\.c:35\r\n35\[ \t\]+print_average \\(my_list, first, last\\);"
+
+}
+
+#
+#test_breakpoints
+#
+proc test_breakpoints { } {
+ global gdb_prompt
+
+ gdb_test "sb" ""
+ gdb_test "lb" "Num.*Type.*Disp.*Enb.*Address.*What\r\n1\[ \r\]+breakpoint\[ \r\]+keep n.*in main at.*average\.c:31.*"
+ gdb_test "ab" ""
+ gdb_test "lb" "Num.*Type.*Disp.*Enb.*Address.*What\r\n1\[ \r\]+breakpoint\[ \r\]+keep y.*in main at.*average\.c:31.*"
+ gdb_test "ba sum" "Breakpoint.*at.*: file.*sum\.c, line 11\."
+ gdb_test "cont" ""
+ gdb_test "bx" "Breakpoint.*at.*: file.*sum.c, line 15\."
+ gdb_test "bx if (1)" "Breakpoint.*at.*: file.*sum.c, line 15\."
+ gdb_test "bx 1" "Breakpoint.*at.*: file.*average.c, line 22\."
+ gdb_test "bx 1 if (1)" "Breakpoint.*at.*: file.*average.c, line 22\."
+ gdb_test "bc 1 2" "Will ignore next 2 crossings of breakpoint 1\."
+ gdb_test "lb 1" "Num.*Type.*Disp.*Enb.*Address.*What\r\n1\[ \r\]+breakpoint\[ \r\]+keep y.*in main at.*average\.c:31\r\n.*breakpoint already hit 1 time\r\n.*ignore next 2 hits.*"
+
+ send_gdb "db\n"
+ gdb_expect {
+ -re "Delete all breakpoints.*y or n. $" {
+ send_gdb "y\n"
+ exp_continue
+ }
+ -re "y\r\n$gdb_prompt $" {}
+ -re ".*$gdb_prompt $" { # This happens if there were no breakpoints
+ }
+ timeout { perror "Delete all breakpoints (timeout)" ; return }
+ }
+ send_gdb "lb\n"
+ gdb_expect {
+ -re "No breakpoints or watchpoints..*$gdb_prompt $" {}
+ -re ".*$gdb_prompt $" { perror "breakpoints not deleted" ; return }
+ timeout { perror "info breakpoints (timeout)" ; return }
+ }
+gdb_test "xbreak" "Breakpoint.*at.*file.*sum.c, line 15."
+gdb_test "xbreak print_average" "Breakpoint.*at.*file.*average.c, line 22."
+gdb_test "xbreak if (1)" "Note: breakpoint.*also set at pc.*Breakpoint.*at.*file.*sum.c, line 15."
+gdb_test "xbreak print_average if (1)" "Note: breakpoint.*also set at pc.*Breakpoint.*at.*file.*average.c, line 22."
+
+ send_gdb "lb\n"
+ gdb_expect {
+ -re "Num Type Disp Enb Address What.*breakpoint keep y.*in sum at.*sum.c:15.*breakpoint keep y.*in print_average at.*average.c:22.*breakpoint keep y.*in sum at.*sum.c:15.*stop only if 1.*breakpoint keep y.*in print_average at.*average.c:22.*stop only if 1.*$gdb_prompt $" {pass "lb on xbreaks"}
+ -re ".*$gdb_prompt $" { fail "breakpoints not deleted"}
+ timeout { fail "info breakpoints (timeout)" }
+ }
+
+}
+
+#
+# test_signals
+#
+proc test_signals { } {
+ gdb_test "handle SIGTERM nostop noprint" ""
+ gdb_test "z SIGTERM s" "Signal.*Stop.*Print.*Pass to program.*Description\r\nSIGTERM.*Yes.*Yes.*Yes.*Terminated"
+ gdb_test "z SIGTERM r" "Signal.*Stop.*Print.*Pass to program.*Description\r\nSIGTERM.*No.*No.*Yes.*Terminated"
+ gdb_test "z SIGTERM i" "Signal.*Stop.*Print.*Pass to program.*Description\r\nSIGTERM.*No.*No.*No.*Terminated"
+ gdb_test "z SIGTERM r" "Signal.*Stop.*Print.*Pass to program.*Description\r\nSIGTERM.*No.*Yes.*No.*Terminated"
+ gdb_test "z SIGTERM Q" "Signal.*Stop.*Print.*Pass to program.*Description\r\nSIGTERM.*No.*No.*No.*Terminated"
+ gdb_test "lz" "Signal.*Stop.*Print.*Pass to program.*Description\r\n\r\nSIGHUP.*Yes.*"
+}
+
+
+
+# Start with a fresh gdb.
+global GDBFLAGS
+set saved_gdbflags $GDBFLAGS
+
+set GDBFLAGS "$GDBFLAGS --xdb"
+
+gdb_exit
+gdb_start
+
+xdb_reinitialize_dir $srcdir/$subdir
+
+gdb_load ${binfile}
+send_gdb "set width 0\n"
+gdb_expect -re "$gdb_prompt $"
+test_search
+test_viewing_loc
+test_dir_list
+test_list_sources
+test_vlist
+test_va
+gdb_test "l" "No arguments.\r\nc = 0.*\r\nfirst = 0\r\nlast = 0"
+#test_list_globals
+test_list_registers
+test_backtrace
+
+# Start with a fresh gdb.
+
+gdb_exit
+gdb_start
+xdb_reinitialize_dir $srcdir/$subdir
+
+gdb_load ${binfile}
+send_gdb "set width 0\n"
+gdb_expect -re "$gdb_prompt $"
+test_go
+
+
+gdb_exit
+gdb_start
+xdb_reinitialize_dir $srcdir/$subdir
+
+gdb_load ${binfile}
+send_gdb "set width 0\n"
+gdb_expect -re "$gdb_prompt $"
+gdb_test "break main" ""
+gdb_test "R" ""
+gdb_test "S" "32\[ \t\]+int last = num-1;"
+test_breakpoints
+test_signals
+gdb_test "sm" ""
+gdb_test "info set" ".*pagination: State of pagination is off.*"
+gdb_test "am" ""
+gdb_test "info set" ".*pagination: State of pagination is on.*"
+gdb_exit
+
+set GDBFLAGS $saved_gdbflags
+
+return 0
+
+
+
+
+
+
diff --git a/gdb/testsuite/gdb.stabs/Makefile.in b/gdb/testsuite/gdb.stabs/Makefile.in
new file mode 100644
index 00000000000..5bf35ea76a1
--- /dev/null
+++ b/gdb/testsuite/gdb.stabs/Makefile.in
@@ -0,0 +1,16 @@
+VPATH = @srcdir@
+srcdir = @srcdir@
+
+all:
+ @echo "Nothing to be done for all..."
+
+#### host, target, and site specific Makefile frags come in here.
+
+clean mostlyclean:
+ -rm -f *.o *~ core tmp.c tmp.s weird.s errs
+
+distclean maintainer-clean realclean: clean
+ -rm -f Makefile config.status config.log
+
+Makefile: $(srcdir)/Makefile.in $(srcdir)/configure.in
+ $(SHELL) ./config.status --recheck
diff --git a/gdb/testsuite/gdb.stabs/aout.sed b/gdb/testsuite/gdb.stabs/aout.sed
new file mode 100644
index 00000000000..bbe38bc459a
--- /dev/null
+++ b/gdb/testsuite/gdb.stabs/aout.sed
@@ -0,0 +1,16 @@
+s/# Irix4 sed blows up if you have a sed command starting with "#"//
+s/# Avoid it by putting the comments within real sed commands.//
+s/# GDB legitimately expects a file name.//
+s/# The sun3 assembler bogusly requires that the value of this stab be a//
+s/# label. Placate it.//
+1i\
+ .stabs "weird.c",0x64,0,0,Label0\
+Label0:
+s/N_LSYM/0x80/
+s/N_GSYM/0x20/
+s/# Replace a single backslash with a doubled backslash//
+/\.stabs/s/\\/\\\\/
+s/\.begin_common\(.*\)/.stabs \1,0xe2,0,0,0/
+s/\.end_common\(.*\)/.stabs \1,0xe4,0,0,0/
+s/\.align_it/.align 2/
+/^#/d
diff --git a/gdb/testsuite/gdb.stabs/configure b/gdb/testsuite/gdb.stabs/configure
new file mode 100755
index 00000000000..698233dcc7d
--- /dev/null
+++ b/gdb/testsuite/gdb.stabs/configure
@@ -0,0 +1,899 @@
+#! /bin/sh
+
+# Guess values for system-dependent variables and create Makefiles.
+# Generated automatically using autoconf version 2.12.1
+# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc.
+#
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+
+# Defaults:
+ac_help=
+ac_default_prefix=/usr/local
+# Any additions from configure.in:
+
+# Initialize some variables set by options.
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+build=NONE
+cache_file=./config.cache
+exec_prefix=NONE
+host=NONE
+no_create=
+nonopt=NONE
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+target=NONE
+verbose=
+x_includes=NONE
+x_libraries=NONE
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datadir='${prefix}/share'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+libdir='${exec_prefix}/lib'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+infodir='${prefix}/info'
+mandir='${prefix}/man'
+
+# Initialize some other variables.
+subdirs=
+MFLAGS= MAKEFLAGS=
+SHELL=${CONFIG_SHELL-/bin/sh}
+# Maximum number of lines to put in a shell here document.
+ac_max_here_lines=12
+
+ac_prev=
+for ac_option
+do
+
+ # If the previous option needs an argument, assign it.
+ if test -n "$ac_prev"; then
+ eval "$ac_prev=\$ac_option"
+ ac_prev=
+ continue
+ fi
+
+ case "$ac_option" in
+ -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
+ *) ac_optarg= ;;
+ esac
+
+ # Accept the important Cygnus configure options, so we can diagnose typos.
+
+ case "$ac_option" in
+
+ -bindir | --bindir | --bindi | --bind | --bin | --bi)
+ ac_prev=bindir ;;
+ -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+ bindir="$ac_optarg" ;;
+
+ -build | --build | --buil | --bui | --bu)
+ ac_prev=build ;;
+ -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+ build="$ac_optarg" ;;
+
+ -cache-file | --cache-file | --cache-fil | --cache-fi \
+ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+ ac_prev=cache_file ;;
+ -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+ cache_file="$ac_optarg" ;;
+
+ -datadir | --datadir | --datadi | --datad | --data | --dat | --da)
+ ac_prev=datadir ;;
+ -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \
+ | --da=*)
+ datadir="$ac_optarg" ;;
+
+ -disable-* | --disable-*)
+ ac_feature=`echo $ac_option|sed -e 's/-*disable-//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then
+ { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
+ fi
+ ac_feature=`echo $ac_feature| sed 's/-/_/g'`
+ eval "enable_${ac_feature}=no" ;;
+
+ -enable-* | --enable-*)
+ ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then
+ { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
+ fi
+ ac_feature=`echo $ac_feature| sed 's/-/_/g'`
+ case "$ac_option" in
+ *=*) ;;
+ *) ac_optarg=yes ;;
+ esac
+ eval "enable_${ac_feature}='$ac_optarg'" ;;
+
+ -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+ | --exec | --exe | --ex)
+ ac_prev=exec_prefix ;;
+ -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+ | --exec=* | --exe=* | --ex=*)
+ exec_prefix="$ac_optarg" ;;
+
+ -gas | --gas | --ga | --g)
+ # Obsolete; use --with-gas.
+ with_gas=yes ;;
+
+ -help | --help | --hel | --he)
+ # Omit some internal or obsolete options to make the list less imposing.
+ # This message is too long to be a string in the A/UX 3.1 sh.
+ cat << EOF
+Usage: configure [options] [host]
+Options: [defaults in brackets after descriptions]
+Configuration:
+ --cache-file=FILE cache test results in FILE
+ --help print this message
+ --no-create do not create output files
+ --quiet, --silent do not print \`checking...' messages
+ --version print the version of autoconf that created configure
+Directory and file names:
+ --prefix=PREFIX install architecture-independent files in PREFIX
+ [$ac_default_prefix]
+ --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
+ [same as prefix]
+ --bindir=DIR user executables in DIR [EPREFIX/bin]
+ --sbindir=DIR system admin executables in DIR [EPREFIX/sbin]
+ --libexecdir=DIR program executables in DIR [EPREFIX/libexec]
+ --datadir=DIR read-only architecture-independent data in DIR
+ [PREFIX/share]
+ --sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc]
+ --sharedstatedir=DIR modifiable architecture-independent data in DIR
+ [PREFIX/com]
+ --localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var]
+ --libdir=DIR object code libraries in DIR [EPREFIX/lib]
+ --includedir=DIR C header files in DIR [PREFIX/include]
+ --oldincludedir=DIR C header files for non-gcc in DIR [/usr/include]
+ --infodir=DIR info documentation in DIR [PREFIX/info]
+ --mandir=DIR man documentation in DIR [PREFIX/man]
+ --srcdir=DIR find the sources in DIR [configure dir or ..]
+ --program-prefix=PREFIX prepend PREFIX to installed program names
+ --program-suffix=SUFFIX append SUFFIX to installed program names
+ --program-transform-name=PROGRAM
+ run sed PROGRAM on installed program names
+EOF
+ cat << EOF
+Host type:
+ --build=BUILD configure for building on BUILD [BUILD=HOST]
+ --host=HOST configure for HOST [guessed]
+ --target=TARGET configure for TARGET [TARGET=HOST]
+Features and packages:
+ --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
+ --enable-FEATURE[=ARG] include FEATURE [ARG=yes]
+ --with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
+ --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
+ --x-includes=DIR X include files are in DIR
+ --x-libraries=DIR X library files are in DIR
+EOF
+ if test -n "$ac_help"; then
+ echo "--enable and --with options recognized:$ac_help"
+ fi
+ exit 0 ;;
+
+ -host | --host | --hos | --ho)
+ ac_prev=host ;;
+ -host=* | --host=* | --hos=* | --ho=*)
+ host="$ac_optarg" ;;
+
+ -includedir | --includedir | --includedi | --included | --include \
+ | --includ | --inclu | --incl | --inc)
+ ac_prev=includedir ;;
+ -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+ | --includ=* | --inclu=* | --incl=* | --inc=*)
+ includedir="$ac_optarg" ;;
+
+ -infodir | --infodir | --infodi | --infod | --info | --inf)
+ ac_prev=infodir ;;
+ -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+ infodir="$ac_optarg" ;;
+
+ -libdir | --libdir | --libdi | --libd)
+ ac_prev=libdir ;;
+ -libdir=* | --libdir=* | --libdi=* | --libd=*)
+ libdir="$ac_optarg" ;;
+
+ -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+ | --libexe | --libex | --libe)
+ ac_prev=libexecdir ;;
+ -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+ | --libexe=* | --libex=* | --libe=*)
+ libexecdir="$ac_optarg" ;;
+
+ -localstatedir | --localstatedir | --localstatedi | --localstated \
+ | --localstate | --localstat | --localsta | --localst \
+ | --locals | --local | --loca | --loc | --lo)
+ ac_prev=localstatedir ;;
+ -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+ | --localstate=* | --localstat=* | --localsta=* | --localst=* \
+ | --locals=* | --local=* | --loca=* | --loc=* | --lo=*)
+ localstatedir="$ac_optarg" ;;
+
+ -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+ ac_prev=mandir ;;
+ -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+ mandir="$ac_optarg" ;;
+
+ -nfp | --nfp | --nf)
+ # Obsolete; use --without-fp.
+ with_fp=no ;;
+
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c)
+ no_create=yes ;;
+
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+ no_recursion=yes ;;
+
+ -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+ | --oldin | --oldi | --old | --ol | --o)
+ ac_prev=oldincludedir ;;
+ -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+ oldincludedir="$ac_optarg" ;;
+
+ -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+ ac_prev=prefix ;;
+ -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+ prefix="$ac_optarg" ;;
+
+ -program-prefix | --program-prefix | --program-prefi | --program-pref \
+ | --program-pre | --program-pr | --program-p)
+ ac_prev=program_prefix ;;
+ -program-prefix=* | --program-prefix=* | --program-prefi=* \
+ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+ program_prefix="$ac_optarg" ;;
+
+ -program-suffix | --program-suffix | --program-suffi | --program-suff \
+ | --program-suf | --program-su | --program-s)
+ ac_prev=program_suffix ;;
+ -program-suffix=* | --program-suffix=* | --program-suffi=* \
+ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+ program_suffix="$ac_optarg" ;;
+
+ -program-transform-name | --program-transform-name \
+ | --program-transform-nam | --program-transform-na \
+ | --program-transform-n | --program-transform- \
+ | --program-transform | --program-transfor \
+ | --program-transfo | --program-transf \
+ | --program-trans | --program-tran \
+ | --progr-tra | --program-tr | --program-t)
+ ac_prev=program_transform_name ;;
+ -program-transform-name=* | --program-transform-name=* \
+ | --program-transform-nam=* | --program-transform-na=* \
+ | --program-transform-n=* | --program-transform-=* \
+ | --program-transform=* | --program-transfor=* \
+ | --program-transfo=* | --program-transf=* \
+ | --program-trans=* | --program-tran=* \
+ | --progr-tra=* | --program-tr=* | --program-t=*)
+ program_transform_name="$ac_optarg" ;;
+
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ silent=yes ;;
+
+ -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+ ac_prev=sbindir ;;
+ -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+ | --sbi=* | --sb=*)
+ sbindir="$ac_optarg" ;;
+
+ -sharedstatedir | --sharedstatedir | --sharedstatedi \
+ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+ | --sharedst | --shareds | --shared | --share | --shar \
+ | --sha | --sh)
+ ac_prev=sharedstatedir ;;
+ -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+ | --sha=* | --sh=*)
+ sharedstatedir="$ac_optarg" ;;
+
+ -site | --site | --sit)
+ ac_prev=site ;;
+ -site=* | --site=* | --sit=*)
+ site="$ac_optarg" ;;
+
+ -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+ ac_prev=srcdir ;;
+ -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+ srcdir="$ac_optarg" ;;
+
+ -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+ | --syscon | --sysco | --sysc | --sys | --sy)
+ ac_prev=sysconfdir ;;
+ -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+ sysconfdir="$ac_optarg" ;;
+
+ -target | --target | --targe | --targ | --tar | --ta | --t)
+ ac_prev=target ;;
+ -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+ target="$ac_optarg" ;;
+
+ -v | -verbose | --verbose | --verbos | --verbo | --verb)
+ verbose=yes ;;
+
+ -version | --version | --versio | --versi | --vers)
+ echo "configure generated by autoconf version 2.12.1"
+ exit 0 ;;
+
+ -with-* | --with-*)
+ ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then
+ { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
+ fi
+ ac_package=`echo $ac_package| sed 's/-/_/g'`
+ case "$ac_option" in
+ *=*) ;;
+ *) ac_optarg=yes ;;
+ esac
+ eval "with_${ac_package}='$ac_optarg'" ;;
+
+ -without-* | --without-*)
+ ac_package=`echo $ac_option|sed -e 's/-*without-//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then
+ { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
+ fi
+ ac_package=`echo $ac_package| sed 's/-/_/g'`
+ eval "with_${ac_package}=no" ;;
+
+ --x)
+ # Obsolete; use --with-x.
+ with_x=yes ;;
+
+ -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+ | --x-incl | --x-inc | --x-in | --x-i)
+ ac_prev=x_includes ;;
+ -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+ x_includes="$ac_optarg" ;;
+
+ -x-libraries | --x-libraries | --x-librarie | --x-librari \
+ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+ ac_prev=x_libraries ;;
+ -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+ x_libraries="$ac_optarg" ;;
+
+ -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; }
+ ;;
+
+ *)
+ if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then
+ echo "configure: warning: $ac_option: invalid host type" 1>&2
+ fi
+ if test "x$nonopt" != xNONE; then
+ { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; }
+ fi
+ nonopt="$ac_option"
+ ;;
+
+ esac
+done
+
+if test -n "$ac_prev"; then
+ { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; }
+fi
+
+trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
+
+# File descriptor usage:
+# 0 standard input
+# 1 file creation
+# 2 errors and warnings
+# 3 some systems may open it to /dev/tty
+# 4 used on the Kubota Titan
+# 6 checking for... messages and results
+# 5 compiler messages saved in config.log
+if test "$silent" = yes; then
+ exec 6>/dev/null
+else
+ exec 6>&1
+fi
+exec 5>./config.log
+
+echo "\
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+" 1>&5
+
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Also quote any args containing shell metacharacters.
+ac_configure_args=
+for ac_arg
+do
+ case "$ac_arg" in
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c) ;;
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;;
+ *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*)
+ ac_configure_args="$ac_configure_args '$ac_arg'" ;;
+ *) ac_configure_args="$ac_configure_args $ac_arg" ;;
+ esac
+done
+
+# NLS nuisances.
+# Only set these to C if already set. These must not be set unconditionally
+# because not all systems understand e.g. LANG=C (notably SCO).
+# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'!
+# Non-C LC_CTYPE values break the ctype check.
+if test "${LANG+set}" = set; then LANG=C; export LANG; fi
+if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi
+if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi
+if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -rf conftest* confdefs.h
+# AIX cpp loses on an empty file, so make sure it contains at least a newline.
+echo > confdefs.h
+
+# A filename unique to this package, relative to the directory that
+# configure is in, which we can look for to find out if srcdir is correct.
+ac_unique_file=weird.exp
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+ ac_srcdir_defaulted=yes
+ # Try the directory containing this script, then its parent.
+ ac_prog=$0
+ ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'`
+ test "x$ac_confdir" = "x$ac_prog" && ac_confdir=.
+ srcdir=$ac_confdir
+ if test ! -r $srcdir/$ac_unique_file; then
+ srcdir=..
+ fi
+else
+ ac_srcdir_defaulted=no
+fi
+if test ! -r $srcdir/$ac_unique_file; then
+ if test "$ac_srcdir_defaulted" = yes; then
+ { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; }
+ else
+ { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; }
+ fi
+fi
+srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'`
+
+# Prefer explicitly selected file to automatically selected ones.
+if test -z "$CONFIG_SITE"; then
+ if test "x$prefix" != xNONE; then
+ CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site"
+ else
+ CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
+ fi
+fi
+for ac_site_file in $CONFIG_SITE; do
+ if test -r "$ac_site_file"; then
+ echo "loading site script $ac_site_file"
+ . "$ac_site_file"
+ fi
+done
+
+if test -r "$cache_file"; then
+ echo "loading cache $cache_file"
+ . $cache_file
+else
+ echo "creating cache $cache_file"
+ > $cache_file
+fi
+
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then
+ # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu.
+ if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then
+ ac_n= ac_c='
+' ac_t=' '
+ else
+ ac_n=-n ac_c= ac_t=
+ fi
+else
+ ac_n= ac_c='\c' ac_t=
+fi
+
+
+
+CC=${CC-cc}
+
+ac_aux_dir=
+for ac_dir in `cd $srcdir;pwd`/../../.. $srcdir/`cd $srcdir;pwd`/../../..; do
+ if test -f $ac_dir/install-sh; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install-sh -c"
+ break
+ elif test -f $ac_dir/install.sh; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install.sh -c"
+ break
+ fi
+done
+if test -z "$ac_aux_dir"; then
+ { echo "configure: error: can not find install-sh or install.sh in `cd $srcdir;pwd`/../../.. $srcdir/`cd $srcdir;pwd`/../../.." 1>&2; exit 1; }
+fi
+ac_config_guess=$ac_aux_dir/config.guess
+ac_config_sub=$ac_aux_dir/config.sub
+ac_configure=$ac_aux_dir/configure # This should be Cygnus configure.
+
+
+# Do some error checking and defaulting for the host and target type.
+# The inputs are:
+# configure --host=HOST --target=TARGET --build=BUILD NONOPT
+#
+# The rules are:
+# 1. You are not allowed to specify --host, --target, and nonopt at the
+# same time.
+# 2. Host defaults to nonopt.
+# 3. If nonopt is not specified, then host defaults to the current host,
+# as determined by config.guess.
+# 4. Target and build default to nonopt.
+# 5. If nonopt is not specified, then target and build default to host.
+
+# The aliases save the names the user supplied, while $host etc.
+# will get canonicalized.
+case $host---$target---$nonopt in
+NONE---*---* | *---NONE---* | *---*---NONE) ;;
+*) { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; } ;;
+esac
+
+
+# Make sure we can run config.sub.
+if ${CONFIG_SHELL-/bin/sh} $ac_config_sub sun4 >/dev/null 2>&1; then :
+else { echo "configure: error: can not run $ac_config_sub" 1>&2; exit 1; }
+fi
+
+echo $ac_n "checking host system type""... $ac_c" 1>&6
+echo "configure:573: checking host system type" >&5
+
+host_alias=$host
+case "$host_alias" in
+NONE)
+ case $nonopt in
+ NONE)
+ if host_alias=`${CONFIG_SHELL-/bin/sh} $ac_config_guess`; then :
+ else { echo "configure: error: can not guess host type; you must specify one" 1>&2; exit 1; }
+ fi ;;
+ *) host_alias=$nonopt ;;
+ esac ;;
+esac
+
+host=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $host_alias`
+host_cpu=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+host_vendor=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+host_os=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+echo "$ac_t""$host" 1>&6
+
+echo $ac_n "checking target system type""... $ac_c" 1>&6
+echo "configure:594: checking target system type" >&5
+
+target_alias=$target
+case "$target_alias" in
+NONE)
+ case $nonopt in
+ NONE) target_alias=$host_alias ;;
+ *) target_alias=$nonopt ;;
+ esac ;;
+esac
+
+target=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $target_alias`
+target_cpu=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+target_vendor=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+target_os=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+echo "$ac_t""$target" 1>&6
+
+echo $ac_n "checking build system type""... $ac_c" 1>&6
+echo "configure:612: checking build system type" >&5
+
+build_alias=$build
+case "$build_alias" in
+NONE)
+ case $nonopt in
+ NONE) build_alias=$host_alias ;;
+ *) build_alias=$nonopt ;;
+ esac ;;
+esac
+
+build=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $build_alias`
+build_cpu=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+build_vendor=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+build_os=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+echo "$ac_t""$build" 1>&6
+
+test "$host_alias" != "$target_alias" &&
+ test "$program_prefix$program_suffix$program_transform_name" = \
+ NONENONEs,x,x, &&
+ program_prefix=${target_alias}-
+
+
+trap '' 1 2 15
+cat > confcache <<\EOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs. It is not useful on other systems.
+# If it contains results you don't want to keep, you may remove or edit it.
+#
+# By default, configure uses ./config.cache as the cache file,
+# creating it if it does not exist already. You can give configure
+# the --cache-file=FILE option to use a different cache file; that is
+# what configure does when it calls configure scripts in
+# subdirectories, so they share the cache.
+# Giving --cache-file=/dev/null disables caching, for debugging configure.
+# config.status only pays attention to the cache file if you give it the
+# --recheck option to rerun configure.
+#
+EOF
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, don't put newlines in cache variables' values.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(set) 2>&1 |
+ case `(ac_space=' '; set) 2>&1 | grep ac_space` in
+ *ac_space=\ *)
+ # `set' does not quote correctly, so add quotes (double-quote substitution
+ # turns \\\\ into \\, and sed turns \\ into \).
+ sed -n \
+ -e "s/'/'\\\\''/g" \
+ -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p"
+ ;;
+ *)
+ # `set' quotes correctly as required by POSIX, so do not add quotes.
+ sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p'
+ ;;
+ esac >> confcache
+if cmp -s $cache_file confcache; then
+ :
+else
+ if test -w $cache_file; then
+ echo "updating cache $cache_file"
+ cat confcache > $cache_file
+ else
+ echo "not updating unwritable cache $cache_file"
+ fi
+fi
+rm -f confcache
+
+trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+# Any assignment to VPATH causes Sun make to only execute
+# the first set of double-colon rules, so remove it if not needed.
+# If there is a colon in the path, we need to keep it.
+if test "x$srcdir" = x.; then
+ ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d'
+fi
+
+trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15
+
+# Transform confdefs.h into DEFS.
+# Protect against shell expansion while executing Makefile rules.
+# Protect against Makefile macro expansion.
+cat > conftest.defs <<\EOF
+s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%-D\1=\2%g
+s%[ `~#$^&*(){}\\|;'"<>?]%\\&%g
+s%\[%\\&%g
+s%\]%\\&%g
+s%\$%$$%g
+EOF
+DEFS=`sed -f conftest.defs confdefs.h | tr '\012' ' '`
+rm -f conftest.defs
+
+
+# Without the "./", some shells look in PATH for config.status.
+: ${CONFIG_STATUS=./config.status}
+
+echo creating $CONFIG_STATUS
+rm -f $CONFIG_STATUS
+cat > $CONFIG_STATUS <<EOF
+#! /bin/sh
+# Generated automatically by configure.
+# Run this file to recreate the current configuration.
+# This directory was configured as follows,
+# on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+#
+# $0 $ac_configure_args
+#
+# Compiler output produced by configure, useful for debugging
+# configure, is in ./config.log if it exists.
+
+ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]"
+for ac_option
+do
+ case "\$ac_option" in
+ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+ echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion"
+ exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;;
+ -version | --version | --versio | --versi | --vers | --ver | --ve | --v)
+ echo "$CONFIG_STATUS generated by autoconf version 2.12.1"
+ exit 0 ;;
+ -help | --help | --hel | --he | --h)
+ echo "\$ac_cs_usage"; exit 0 ;;
+ *) echo "\$ac_cs_usage"; exit 1 ;;
+ esac
+done
+
+ac_given_srcdir=$srcdir
+
+trap 'rm -fr `echo "Makefile" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15
+EOF
+cat >> $CONFIG_STATUS <<EOF
+
+# Protect against being on the right side of a sed subst in config.status.
+sed 's/%@/@@/; s/@%/@@/; s/%g\$/@g/; /@g\$/s/[\\\\&%]/\\\\&/g;
+ s/@@/%@/; s/@@/@%/; s/@g\$/%g/' > conftest.subs <<\\CEOF
+$ac_vpsub
+$extrasub
+s%@SHELL@%$SHELL%g
+s%@CFLAGS@%$CFLAGS%g
+s%@CPPFLAGS@%$CPPFLAGS%g
+s%@CXXFLAGS@%$CXXFLAGS%g
+s%@DEFS@%$DEFS%g
+s%@LDFLAGS@%$LDFLAGS%g
+s%@LIBS@%$LIBS%g
+s%@exec_prefix@%$exec_prefix%g
+s%@prefix@%$prefix%g
+s%@program_transform_name@%$program_transform_name%g
+s%@bindir@%$bindir%g
+s%@sbindir@%$sbindir%g
+s%@libexecdir@%$libexecdir%g
+s%@datadir@%$datadir%g
+s%@sysconfdir@%$sysconfdir%g
+s%@sharedstatedir@%$sharedstatedir%g
+s%@localstatedir@%$localstatedir%g
+s%@libdir@%$libdir%g
+s%@includedir@%$includedir%g
+s%@oldincludedir@%$oldincludedir%g
+s%@infodir@%$infodir%g
+s%@mandir@%$mandir%g
+s%@CC@%$CC%g
+s%@host@%$host%g
+s%@host_alias@%$host_alias%g
+s%@host_cpu@%$host_cpu%g
+s%@host_vendor@%$host_vendor%g
+s%@host_os@%$host_os%g
+s%@target@%$target%g
+s%@target_alias@%$target_alias%g
+s%@target_cpu@%$target_cpu%g
+s%@target_vendor@%$target_vendor%g
+s%@target_os@%$target_os%g
+s%@build@%$build%g
+s%@build_alias@%$build_alias%g
+s%@build_cpu@%$build_cpu%g
+s%@build_vendor@%$build_vendor%g
+s%@build_os@%$build_os%g
+
+CEOF
+EOF
+
+cat >> $CONFIG_STATUS <<\EOF
+
+# Split the substitutions into bite-sized pieces for seds with
+# small command number limits, like on Digital OSF/1 and HP-UX.
+ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script.
+ac_file=1 # Number of current file.
+ac_beg=1 # First line for current file.
+ac_end=$ac_max_sed_cmds # Line after last line for current file.
+ac_more_lines=:
+ac_sed_cmds=""
+while $ac_more_lines; do
+ if test $ac_beg -gt 1; then
+ sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file
+ else
+ sed "${ac_end}q" conftest.subs > conftest.s$ac_file
+ fi
+ if test ! -s conftest.s$ac_file; then
+ ac_more_lines=false
+ rm -f conftest.s$ac_file
+ else
+ if test -z "$ac_sed_cmds"; then
+ ac_sed_cmds="sed -f conftest.s$ac_file"
+ else
+ ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file"
+ fi
+ ac_file=`expr $ac_file + 1`
+ ac_beg=$ac_end
+ ac_end=`expr $ac_end + $ac_max_sed_cmds`
+ fi
+done
+if test -z "$ac_sed_cmds"; then
+ ac_sed_cmds=cat
+fi
+EOF
+
+cat >> $CONFIG_STATUS <<EOF
+
+CONFIG_FILES=\${CONFIG_FILES-"Makefile"}
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then
+ # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+ case "$ac_file" in
+ *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'`
+ ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
+ *) ac_file_in="${ac_file}.in" ;;
+ esac
+
+ # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories.
+
+ # Remove last slash and all that follows it. Not all systems have dirname.
+ ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
+ if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
+ # The file is in a subdirectory.
+ test ! -d "$ac_dir" && mkdir "$ac_dir"
+ ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`"
+ # A "../" for each directory in $ac_dir_suffix.
+ ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'`
+ else
+ ac_dir_suffix= ac_dots=
+ fi
+
+ case "$ac_given_srcdir" in
+ .) srcdir=.
+ if test -z "$ac_dots"; then top_srcdir=.
+ else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;;
+ /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;;
+ *) # Relative path.
+ srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix"
+ top_srcdir="$ac_dots$ac_given_srcdir" ;;
+ esac
+
+
+ echo creating "$ac_file"
+ rm -f "$ac_file"
+ configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure."
+ case "$ac_file" in
+ *Makefile*) ac_comsub="1i\\
+# $configure_input" ;;
+ *) ac_comsub= ;;
+ esac
+
+ ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"`
+ sed -e "$ac_comsub
+s%@configure_input@%$configure_input%g
+s%@srcdir@%$srcdir%g
+s%@top_srcdir@%$top_srcdir%g
+" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file
+fi; done
+rm -f conftest.s*
+
+EOF
+cat >> $CONFIG_STATUS <<EOF
+
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+
+exit 0
+EOF
+chmod +x $CONFIG_STATUS
+rm -fr confdefs* $ac_clean_files
+test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1
+
diff --git a/gdb/testsuite/gdb.stabs/configure.in b/gdb/testsuite/gdb.stabs/configure.in
new file mode 100644
index 00000000000..aa494262bc1
--- /dev/null
+++ b/gdb/testsuite/gdb.stabs/configure.in
@@ -0,0 +1,15 @@
+dnl Process this file file with autoconf to produce a configure script.
+dnl This file is a shell script fragment that supplies the information
+dnl necessary to tailor a template configure script into the configure
+dnl script appropriate for this directory. For more information, check
+dnl any existing configure script.
+
+AC_PREREQ(2.5)
+AC_INIT(weird.exp)
+
+CC=${CC-cc}
+AC_SUBST(CC)
+AC_CONFIG_AUX_DIR(`cd $srcdir;pwd`/../../..)
+AC_CANONICAL_SYSTEM
+
+AC_OUTPUT(Makefile)
diff --git a/gdb/testsuite/gdb.stabs/ecoff.sed b/gdb/testsuite/gdb.stabs/ecoff.sed
new file mode 100644
index 00000000000..3411c294198
--- /dev/null
+++ b/gdb/testsuite/gdb.stabs/ecoff.sed
@@ -0,0 +1,17 @@
+# GDB legitimately expects a file name.
+1i\
+ .file 1 "weird.c"\
+\ #@stabs\
+\ #.stabs "weird.c",0x64,0,0,0
+/^#/d
+s/" *, */",/g
+s/\([0-9]\) *, */\1,/g
+s/ *$//
+s/N_LSYM/0x80/
+s/N_GSYM/0x20/
+s/\.begin_common\(.*\)/.stabs \1,0xe2,0,0,0/
+s/\.end_common\(.*\)/.stabs \1,0xe4,0,0,0/
+s/\.align_it/.align 2/
+/.if/d
+/.endif/d
+s/\.stabs/ #.stabs/
diff --git a/gdb/testsuite/gdb.stabs/hppa.sed b/gdb/testsuite/gdb.stabs/hppa.sed
new file mode 100644
index 00000000000..5ca1a003c37
--- /dev/null
+++ b/gdb/testsuite/gdb.stabs/hppa.sed
@@ -0,0 +1,20 @@
+s/# Old OSF sed blows up if you have a sed command starting with "#"//
+s/# Avoid it by putting the comments within real sed commands.//
+s/# GDB legitimately expects a file name.//
+s/# The sun3 assembler bogusly requires that the value of this stab be a//
+s/# label. Placate it.//
+1i\
+\ .stabs "weird.c",0x64,0,0,Label0\
+Label0:
+s/N_LSYM/0x80/
+s/N_GSYM/0x20/
+s/# Replace a single backslash with a doubled backslash//
+/\.stabs/s/\\/\\\\/
+s/# Only labels should be at the beginning of a line, assembler directives//
+s/# and instructions should start somewhere after column zero.//
+/^\./s/^\./ ./
+s/\.begin_common\(.*\)/.stabs \1,0xe2,0,0,0/
+s/\.end_common\(.*\)/.stabs \1,0xe4,0,0,0/
+s/\.align_it/.align 4/
+s/\.globl/.export/
+/^#/d
diff --git a/gdb/testsuite/gdb.stabs/weird.def b/gdb/testsuite/gdb.stabs/weird.def
new file mode 100644
index 00000000000..134e37131eb
--- /dev/null
+++ b/gdb/testsuite/gdb.stabs/weird.def
@@ -0,0 +1,939 @@
+# We'll need an integer type.
+.stabs "inttype:t1=bu4;0;32;",N_LSYM,0,0,0
+
+# There are several kinds of tests in here. We mix up the order to see
+# if we can test for poor handling of a stab affecting the next or previous
+# stab.
+
+# Try all possible symbol descriptors. Note that GDB should merely
+# complain() even though these strings are totally bogus. This allows
+# future compilers to define new syntaxes.
+.stabs "sym32: !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+
+# Type descriptors.
+.stabs "type32:t32= !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+
+# Note that a 'G', N_GSYM symbol needs no value. The name of the stab
+# is used to look up a non-stab symbol with the same name. On some
+# machines, the non-stab symbols will normally have underscores, but
+# if they lack the underscores, then GDB will simply put the symbol in
+# the minimal symbol table all the same. So we can use them without
+# underscores and that way we don't need to worry about which machines
+# need underscores.
+
+# Type attributes.
+.stabs "attr104:G404=@h !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",N_GSYM,0,0, 0
+.stabs "attr105:G405=@i !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",N_GSYM,0,0, 0
+
+# A few real type attributes.
+# Alignment.
+.stabs "var0:G300=@a8;1",N_GSYM,0,0, 0
+.globl var0
+.data
+.align_it
+var0:
+.long 42
+
+.stabs "sym33:! !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "sym35:# !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "sym36:$ !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "sym37:% !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "sym38:& !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "sym39:' !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "sym40:( !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "sym41:) !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "sym42:* !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "sym43:+ !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "sym44:, !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "sym45:- !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+
+.globl attr122
+.data
+.align_it
+attr122:
+.long 42
+.globl attr123
+.data
+.align_it
+attr123:
+.long 42
+.globl attr124
+.data
+.align_it
+attr124:
+.long 42
+
+.stabs "sym46:. !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "sym47:/ !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "sym48:0 !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "sym49:1 !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "sym50:2 !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+
+.stabs "attr96:G396=@` !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",N_GSYM,0,0, 0
+.stabs "attr97:G397=@a !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",N_GSYM,0,0, 0
+.stabs "attr98:G398=@b !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",N_GSYM,0,0, 0
+.stabs "attr99:G399=@c !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",N_GSYM,0,0, 0
+
+.stabs "sym51:3 !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "sym52:4 !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "sym53:5 !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "sym54:6 !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "sym55:7 !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "sym56:8 !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "sym57:9 !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "sym58:: !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "sym59:; !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "sym60:< !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "sym61:= !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "sym62:> !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "sym63:? !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "sym64:@ !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "sym65:A !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "sym66:B !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "sym67:C !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "sym68:D !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "sym69:E !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "sym70:F !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "sym71:G !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "sym72:H !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "sym73:I !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "sym74:J !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "sym75:K !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "sym76:L !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "sym77:M !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "sym78:N !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "sym79:O !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "sym80:P !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "sym81:Q !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "sym82:R !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "sym83:S !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "sym84:T !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "sym85:U !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "sym86:V !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "sym87:W !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "sym88:X !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "sym89:Y !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "sym90:Z !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "sym91:[ !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+
+.stabs "sym93:] !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "sym94:^ !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "sym95:_ !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "sym96:` !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "sym97:a !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "sym98:b !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "sym99:c !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "sym100:d !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "sym101:e !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "sym102:f !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "sym103:g !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "sym104:h !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "sym105:i !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "sym106:j !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "sym107:k !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "sym108:l !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "sym109:m !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "sym110:n !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "sym111:o !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "sym112:p !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "sym113:q !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "sym114:r !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "sym115:s !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "sym116:t !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "sym117:u !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "sym118:v !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "sym119:w !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "sym120:x !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "sym121:y !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "sym122:z !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "sym123:{ !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "sym124:| !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "sym125:} !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "sym126:~ !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+
+.stabs "type33:t33=! !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "type35:t35=# !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "type36:t36=$ !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "type37:t37=% !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "type38:t38=& !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "type39:t39=' !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "type40:t40=( !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "type41:t41=) !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "type42:t42=* !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "type43:t43=+ !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "type44:t44=, !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "type45:t45=- !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "type46:t46=. !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "type47:t47=/ !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "type48:t48=0 !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "type49:t49=1 !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "type50:t50=2 !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "type51:t51=3 !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "type52:t52=4 !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "type53:t53=5 !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "type54:t54=6 !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "type55:t55=7 !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "type56:t56=8 !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "type57:t57=9 !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "type58:t58=: !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "type59:t59=; !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "type60:t60=< !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "type61:t61== !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "type62:t62=> !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "type63:t63=? !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "type64:t64=@ !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "type65:t65=A !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "type66:t66=B !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "type67:t67=C !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+
+.globl attr66
+.data
+.align_it
+attr66:
+.long 42
+.globl attr67
+.data
+.align_it
+attr67:
+.long 42
+.globl attr68
+.data
+.align_it
+attr68:
+.long 42
+.globl attr69
+.data
+.align_it
+attr69:
+.long 42
+
+.stabs "type68:t68=D !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "type69:t69=E !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "type70:t70=F !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "type71:t71=G !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "type72:t72=H !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "type73:t73=I !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "type74:t74=J !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "type75:t75=K !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "type76:t76=L !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "type77:t77=M !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "type78:t78=N !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "type79:t79=O !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "type80:t80=P !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "type81:t81=Q !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "type82:t82=R !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "type83:t83=S !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "type84:t84=T !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "type85:t85=U !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "type86:t86=V !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "type87:t87=W !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+
+.stabs "attr69:G369=@E !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",N_GSYM,0,0, 0
+.stabs "attr70:G370=@F !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",N_GSYM,0,0, 0
+.stabs "attr71:G371=@G !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",N_GSYM,0,0, 0
+
+.stabs "type88:t88=X !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "type89:t89=Y !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "type90:t90=Z !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "type91:t91=[ !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+
+.stabs "type93:t93=] !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "type94:t94=^ !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "type95:t95=_ !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "type96:t96=` !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "type97:t97=a !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "type98:t98=b !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "type99:t99=c !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "type100:t100=d !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "type101:t101=e !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "type102:t102=f !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "type103:t103=g !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "type104:t104=h !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "type105:t105=i !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "type106:t106=j !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "type107:t107=k !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "type108:t108=l !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "type109:t109=m !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "type110:t110=n !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "type111:t111=o !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "type112:t112=p !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "type113:t113=q !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "type114:t114=r !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "type115:t115=s !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "type116:t116=t !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "type117:t117=u !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "type118:t118=v !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "type119:t119=w !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "type120:t120=x !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "type121:t121=y !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "type122:t122=z !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "type123:t123={ !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "type124:t124=| !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "type125:t125=} !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "type126:t126=~ !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+
+.stabs "attr32:G332=@ !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",N_GSYM,0,0, 0
+.stabs "attr33:G333=@! !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",N_GSYM,0,0, 0
+.stabs "attr35:G334=@# !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",N_GSYM,0,0, 0
+
+.stabs "attr36:G335=@$ !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",N_GSYM,0,0, 0
+
+.stabs "attr37:G337=@% !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",N_GSYM,0,0, 0
+
+# Test 'e' constant on non-enum type.
+.stabs "const69:c=e1,69", N_LSYM,0,0, 0
+
+# Test constant with the type embedded.
+.stabs "const70:c=e190=bs2;0;16;,70", N_LSYM,0,0, 0
+
+.stabs "attr38:G338=@& !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",N_GSYM,0,0, 0
+
+# Unrecognized negative type number.
+.stabs "bad_neg0type:t201=s16field0:1,0,32;field2:-534,32,64;field3:-1,96,32;;", N_LSYM,0,0, 0
+
+.stabs "bad_neg0:G201", N_GSYM,0,0, 0
+
+.globl bad_neg0
+.data
+.align_it
+bad_neg0:
+.long 42
+ .long 43, 44, 45
+
+.stabs "attr39:G339=@' !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",N_GSYM,0,0, 0
+.stabs "attr41:G341=@) !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",N_GSYM,0,0, 0
+.stabs "attr42:G342=@* !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",N_GSYM,0,0, 0
+.stabs "attr43:G343=@+ !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",N_GSYM,0,0, 0
+.stabs "attr44:G344=@, !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",N_GSYM,0,0, 0
+.stabs "attr46:G346=@. !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",N_GSYM,0,0, 0
+.stabs "attr47:G347=@/ !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",N_GSYM,0,0, 0
+.stabs "attr58:G358=@: !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",N_GSYM,0,0, 0
+
+# Test two type attributes for one type.
+.stabs "attr59:G359=@;@ !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",N_GSYM,0,0, 0
+
+.stabs "attr60:G360=@< !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",N_GSYM,0,0, 0
+.stabs "attr61:G361=@= !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",N_GSYM,0,0, 0
+.stabs "attr62:G362=@> !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",N_GSYM,0,0, 0
+.stabs "attr63:G363=@? !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",N_GSYM,0,0, 0
+.stabs "attr64:G364=@@ !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",N_GSYM,0,0, 0
+.stabs "attr65:G365=@A !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",N_GSYM,0,0, 0
+.stabs "attr66:G366=@B !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",N_GSYM,0,0, 0
+.stabs "attr67:G367=@C !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",N_GSYM,0,0, 0
+.stabs "attr68:G368=@D !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",N_GSYM,0,0, 0
+.stabs "attr72:G372=@H !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",N_GSYM,0,0, 0
+.stabs "attr73:G373=@I !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",N_GSYM,0,0, 0
+.stabs "attr74:G374=@J !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",N_GSYM,0,0, 0
+.stabs "attr75:G375=@K !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",N_GSYM,0,0, 0
+.stabs "attr76:G376=@L !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",N_GSYM,0,0, 0
+.stabs "attr77:G377=@M !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",N_GSYM,0,0, 0
+.stabs "attr78:G378=@N !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",N_GSYM,0,0, 0
+.stabs "attr79:G379=@O !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",N_GSYM,0,0, 0
+.stabs "attr80:G380=@P !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",N_GSYM,0,0, 0
+.stabs "attr81:G381=@Q !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",N_GSYM,0,0, 0
+.stabs "attr82:G382=@R !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",N_GSYM,0,0, 0
+.stabs "attr83:G383=@S !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",N_GSYM,0,0, 0
+.stabs "attr84:G384=@T !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",N_GSYM,0,0, 0
+.stabs "attr85:G385=@U !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",N_GSYM,0,0, 0
+.stabs "attr86:G386=@V !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",N_GSYM,0,0, 0
+.stabs "attr87:G387=@W !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",N_GSYM,0,0, 0
+.stabs "attr88:G388=@X !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",N_GSYM,0,0, 0
+.stabs "attr89:G389=@Y !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",N_GSYM,0,0, 0
+.stabs "attr90:G390=@Z !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",N_GSYM,0,0, 0
+.stabs "attr91:G391=@[ !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",N_GSYM,0,0, 0
+
+.stabs "attr93:G393=@] !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",N_GSYM,0,0, 0
+
+# Do with and without underscore, so this wins regardless of whether
+# names have underscores.
+
+.globl _common0
+.data
+.align_it
+_common0:
+.long 42
+ .long 24
+ .long 22
+.globl common0
+.data
+.align_it
+common0:
+.long 42
+ .long 24
+ .long 22
+.begin_common "common0"
+.stabs "common0var0:S1", N_GSYM,0,0, 0
+.stabs "common0var1:S1", N_GSYM,0,0, 4
+.stabs "common0var2:S1", N_GSYM,0,0, 8
+.end_common "common0"
+
+.stabs "attr94:G394=@^ !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",N_GSYM,0,0, 0
+.stabs "attr95:G395=@_ !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",N_GSYM,0,0, 0
+.stabs "attr100:G400=@d !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",N_GSYM,0,0, 0
+.stabs "attr101:G401=@e !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",N_GSYM,0,0, 0
+.stabs "attr102:G402=@f !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",N_GSYM,0,0, 0
+.stabs "attr103:G403=@g !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",N_GSYM,0,0, 0
+.stabs "attr106:G406=@j !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",N_GSYM,0,0, 0
+.stabs "attr107:G407=@k !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",N_GSYM,0,0, 0
+.stabs "attr108:G408=@l !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",N_GSYM,0,0, 0
+.stabs "attr109:G409=@m !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",N_GSYM,0,0, 0
+.stabs "attr110:G410=@n !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",N_GSYM,0,0, 0
+.stabs "attr111:G411=@o !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",N_GSYM,0,0, 0
+.stabs "attr112:G412=@p !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",N_GSYM,0,0, 0
+.stabs "attr113:G413=@q !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",N_GSYM,0,0, 0
+.stabs "attr114:G414=@r !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",N_GSYM,0,0, 0
+.stabs "attr115:G415=@s !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",N_GSYM,0,0, 0
+.stabs "attr116:G416=@t !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",N_GSYM,0,0, 0
+.stabs "attr117:G417=@u !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",N_GSYM,0,0, 0
+.stabs "attr118:G418=@v !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",N_GSYM,0,0, 0
+.stabs "attr119:G419=@w !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",N_GSYM,0,0, 0
+.stabs "attr120:G420=@x !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",N_GSYM,0,0, 0
+.stabs "attr121:G421=@y !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",N_GSYM,0,0, 0
+.stabs "attr122:G422=@z !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",N_GSYM,0,0, 0
+.stabs "attr123:G423=@{ !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",N_GSYM,0,0, 0
+.stabs "attr124:G424=@| !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",N_GSYM,0,0, 0
+.stabs "attr125:G425=@} !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",N_GSYM,0,0, 0
+.stabs "attr126:G426=@~ !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",N_GSYM,0,0, 0
+
+# Define a variable for all the above stabs.
+.globl attr32
+.data
+.align_it
+attr32:
+.long 42
+.globl attr33
+.data
+.align_it
+attr33:
+.long 42
+.globl attr35
+.data
+.align_it
+attr35:
+.long 42
+.globl attr36
+.data
+.align_it
+attr36:
+.long 42
+.globl attr37
+.data
+.align_it
+attr37:
+.long 42
+.globl attr38
+.data
+.align_it
+attr38:
+.long 42
+.globl attr39
+.data
+.align_it
+attr39:
+.long 42
+.globl attr41
+.data
+.align_it
+attr41:
+.long 42
+.globl attr42
+.data
+.align_it
+attr42:
+.long 42
+.globl attr43
+.data
+.align_it
+attr43:
+.long 42
+.globl attr44
+.data
+.align_it
+attr44:
+.long 42
+.globl attr46
+.data
+.align_it
+attr46:
+.long 42
+.globl attr47
+.data
+.align_it
+attr47:
+.long 42
+.globl attr58
+.data
+.align_it
+attr58:
+.long 42
+.globl attr59
+.data
+.align_it
+attr59:
+.long 42
+.globl attr60
+.data
+.align_it
+attr60:
+.long 42
+.globl attr61
+.data
+.align_it
+attr61:
+.long 42
+.globl attr62
+.data
+.align_it
+attr62:
+.long 42
+.globl attr63
+.data
+.align_it
+attr63:
+.long 42
+.globl attr64
+.data
+.align_it
+attr64:
+.long 42
+.globl attr65
+.data
+.align_it
+attr65:
+.long 42
+.globl attr70
+.data
+.align_it
+attr70:
+.long 42
+.globl attr71
+.data
+.align_it
+attr71:
+.long 42
+.globl attr72
+.data
+.align_it
+attr72:
+.long 42
+.globl attr73
+.data
+.align_it
+attr73:
+.long 42
+.globl attr74
+.data
+.align_it
+attr74:
+.long 42
+.globl attr75
+.data
+.align_it
+attr75:
+.long 42
+.globl attr76
+.data
+.align_it
+attr76:
+.long 42
+.globl attr77
+.data
+.align_it
+attr77:
+.long 42
+.globl attr78
+.data
+.align_it
+attr78:
+.long 42
+.globl attr79
+.data
+.align_it
+attr79:
+.long 42
+.globl attr80
+.data
+.align_it
+attr80:
+.long 42
+.globl attr81
+.data
+.align_it
+attr81:
+.long 42
+.globl attr82
+.data
+.align_it
+attr82:
+.long 42
+.globl attr83
+.data
+.align_it
+attr83:
+.long 42
+.globl attr84
+.data
+.align_it
+attr84:
+.long 42
+
+# Unrecognized floating point code.
+.stabs "float72type:t202=R87;9;", N_LSYM,0,0, 0
+
+# 256-bit integer. The point is obviously not that GDB should have a
+# special case for this size, but that an integer of any size should
+# work (at least for printing in hex, not necessarily for arithmetic.
+.stabs "int256var:G203=bu32;0;256;", N_GSYM,0,0, 0
+# The value is palindromic, so it works whether words are big or little
+# endian.
+.globl int256var
+.data
+.align_it
+ int256var:
+.long 42
+ .long 0x2b, 0x2c, 0x2d, 0x2d, 0x2c, 0x2b, 0x2a
+
+# Huge value in constant should at least get the type right.
+
+# This value is just big enough not to fit in 32 bits.
+.stabs "consth:c=e1,4294967296", N_LSYM,0,0, 0
+
+.stabs "consth2:c=e1,-734723985732642758928475678987234563284937456", N_LSYM,0,0, 0
+
+# Test a struct constant using S.
+.stabs "bad_neg0const:c=S201,128,128,11222211343434345656565677888877", N_LSYM,0,0, 0
+
+# Bad filenumbers.
+# This one is totally bogus.
+.stabs "bad_type0:t(-3,7)", N_LSYM,0,0, 0
+# This one probably gets interpreted as a forward reference.
+.stabs "bad_type1:t(42,6)", N_LSYM,0,0, 0
+
+# Arrays indexed by weird things.
+.stabs "array_index0:t205=r1;0;5;", N_LSYM,0,0, 0
+.stabs "array0:G206=a205;1", N_GSYM,0,0, 0
+.globl array0
+.data
+.align_it
+ array0:
+.long 42
+ .long 43, 44, 45, 46, 47
+
+.stabs "array_index1:t207=", N_LSYM,0,0, 0
+.stabs "array1:G208=aeai1_red:0,ai1_green:1,ai1_blue:2,;;1", N_GSYM,0,0, 0
+.globl array1
+.data
+.align_it
+ array1:
+.long 42
+ .long 43, 44
+
+# See if GDB can deal with it if the compiler gets smarter about saying
+# which variables were defined with which types.
+.stabs "inttype_one:t209=1", N_LSYM,0,0, 0
+.stabs "inttype_two:t210=1", N_LSYM,0,0, 0
+.stabs "one_var:G209", N_GSYM,0,0, 0
+.globl one_var
+.data
+.align_it
+one_var:
+.long 42
+.stabs "two_var:G210", N_GSYM,0,0, 0
+.globl two_var
+.data
+.align_it
+two_var:
+.long 42
+
+# And see if the caddr_t hack can deal with the same thing.
+.stabs "intp:t211=*1", N_LSYM,0,0, 0
+# If it weren't for this variable, we'd need to ignore the intp name.
+.stabs "pointer_to_int_var:G212=*1", N_LSYM,0,0, 0
+.stabs "intp_var:G211", N_GSYM,0,0, 0
+.globl intp_var
+.data
+.align_it
+intp_var:
+.long 42
+
+# Unrecognized constant code.
+.stabs "unrecog_const:c=xjksdflskd33,4;473;", N_LSYM,0,0, 0
+
+.globl attr85
+.data
+.align_it
+attr85:
+.long 42
+.globl attr86
+.data
+.align_it
+attr86:
+.long 42
+.globl attr87
+.data
+.align_it
+attr87:
+.long 42
+.globl attr88
+.data
+.align_it
+attr88:
+.long 42
+.globl attr89
+.data
+.align_it
+attr89:
+.long 42
+.globl attr90
+.data
+.align_it
+attr90:
+.long 42
+.globl attr91
+.data
+.align_it
+attr91:
+.long 42
+.globl attr92
+.data
+.align_it
+attr92:
+.long 42
+.globl attr93
+.data
+.align_it
+attr93:
+.long 42
+.globl attr94
+.data
+.align_it
+attr94:
+.long 42
+.globl attr95
+.data
+.align_it
+attr95:
+.long 42
+.globl attr96
+.data
+.align_it
+attr96:
+.long 42
+.globl attr97
+.data
+.align_it
+attr97:
+.long 42
+.globl attr98
+.data
+.align_it
+attr98:
+.long 42
+.globl attr99
+.data
+.align_it
+attr99:
+.long 42
+.globl attr100
+.data
+.align_it
+attr100:
+.long 42
+.globl attr101
+.data
+.align_it
+attr101:
+.long 42
+.globl attr102
+.data
+.align_it
+attr102:
+.long 42
+.globl attr103
+.data
+.align_it
+attr103:
+.long 42
+.globl attr104
+.data
+.align_it
+attr104:
+.long 42
+.globl attr105
+.data
+.align_it
+attr105:
+.long 42
+.globl attr106
+.data
+.align_it
+attr106:
+.long 42
+.globl attr107
+.data
+.align_it
+attr107:
+.long 42
+.globl attr108
+.data
+.align_it
+attr108:
+.long 42
+.globl attr109
+.data
+.align_it
+attr109:
+.long 42
+.globl attr110
+.data
+.align_it
+attr110:
+.long 42
+.globl attr111
+.data
+.align_it
+attr111:
+.long 42
+.globl attr112
+.data
+.align_it
+attr112:
+.long 42
+.globl attr113
+.data
+.align_it
+attr113:
+.long 42
+.globl attr114
+.data
+.align_it
+attr114:
+.long 42
+.globl attr115
+.data
+.align_it
+attr115:
+.long 42
+.globl attr116
+.data
+.align_it
+attr116:
+.long 42
+.globl attr117
+.data
+.align_it
+attr117:
+.long 42
+.globl attr118
+.data
+.align_it
+attr118:
+.long 42
+.globl attr119
+.data
+.align_it
+attr119:
+.long 42
+.globl attr120
+.data
+.align_it
+attr120:
+.long 42
+.globl attr121
+.data
+.align_it
+attr121:
+.long 42
+.globl attr125
+.data
+.align_it
+attr125:
+.long 42
+.globl attr126
+.data
+.align_it
+attr126:
+.long 42
+
+# Size.
+.stabs "var1:G301=@s32;1",N_GSYM,0,0, 0
+.globl var1
+.data
+.align_it
+var1:
+.long 42
+# Pointer class.
+.stabs "var2:G302=@p42;1",N_GSYM,0,0, 0
+.globl var2
+.data
+.align_it
+var2:
+.long 42
+# Packed type.
+.stabs "var3:G303=@P;1",N_GSYM,0,0, 0
+.globl var3
+.data
+.align_it
+var3:
+.long 42
+
+# Manually hacked version of the following. The manual hacking is to
+# remove the extra names (which GDB 4.9 bogusly relies on).
+
+# Virtual base classes in which there are no variables of the base
+# class types.
+
+# class only_one_instance {
+# public:
+# int x;
+# };
+
+# class inherit_path_a : public virtual only_one_instance {
+# int a;
+# };
+
+# class inherit_path_b : public virtual only_one_instance {
+# int b;
+# };
+
+# class combine_paths : public inherit_path_a, public inherit_path_b {
+# int comb;
+# };
+
+# combine_paths v_comb;
+
+# These are the unhacked stabs I started with (only change has been to
+# convert them to weird.def format, and change the numbers to the 400
+# range.
+
+# .stabs "only_one_instance:Tt444=s4x:1,0,32;;", N_LSYM,0,0, 0
+# .stabs "inherit_path_a:Tt445=s12!1,120,444;$vb444:446=*444,0;a:/01,32,32;;",
+# N_LSYM,0,0, 0
+# .stabs "inherit_path_b:Tt447=s12!1,120,444;$vb444:446,0;b:/01,32,32;;", N_LSYM,0,0, 0
+# .stabs "combine_paths:Tt448=s24!2,020,445;0264,447;comb:/01,128,32;;", N_LSYM,0,0, 0
+# .stabs "v_comb:G448", N_GSYM,0,0, 0
+
+# Hacked version, without class names.
+
+.stabs "v_comb:G448=s24!2,020,445=s12!1,120,444=s4x:1,0,32;;;$vb444:446=@s32;*444,0;a:/01,32,32;;;0264,447=s12!1,120,444;$vb444:446,0;b:/01,32,32;;;comb:/01,128,32;;", N_GSYM,0,0, 0
+
+ .globl v_comb
+ .align 1
+v_comb:
+# virtual base class pointer for inherit_path_a
+ .long v_comb_shared
+# a
+ .long 43
+# virtual base class pointer for inherit_path_b
+ .long v_comb_shared
+# b
+ .long 44
+# comb
+ .long 45
+v_comb_shared:
+# x
+ .long 42
+
+.stabs "sym92:\ !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "type92:t92=\ !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",N_LSYM,0,0,0
+.stabs "attr92:G392=@\ !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",N_GSYM,0,0, 0
diff --git a/gdb/testsuite/gdb.stabs/weird.exp b/gdb/testsuite/gdb.stabs/weird.exp
new file mode 100644
index 00000000000..86ac7a6bca6
--- /dev/null
+++ b/gdb/testsuite/gdb.stabs/weird.exp
@@ -0,0 +1,325 @@
+# Copyright (C) 1997 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# Test that GDB properly ignores invalid stabs.
+# Also test that GDB can debug a .o file, and that it doesn't mind
+# a file that's more minimal than what a compiler normally puts out.
+if $tracelevel then {
+ strace $tracelevel
+}
+
+# If the test directory was not created by configure then skip
+# this test.
+if ![file isdirectory ${objdir}/${subdir}] then {
+ return 0
+}
+
+set prms_id 0
+set bug_id 0
+
+proc do_tests {} {
+ global binfile
+ global gdb_prompt
+
+ # Mips/alpha targets that use gcc with mips-tfile put out the stabs
+ # assembler directives embedded in comments. If the assembler
+ # file is then processed with native cc, all stabs directives
+ # will be lost.
+ # Skip the rest of the stabs tests for this case.
+ send_gdb "ptype inttype\n"
+ gdb_expect {
+ -re "^ptype inttype\r*\ntype = inttype.*$gdb_prompt $" {
+ pass "stabs found"
+ }
+ -re ".*$gdb_prompt $" {
+ setup_xfail "mips-*-*"
+ setup_xfail "alpha-*-*"
+ fail "stabs not found"
+ return
+ }
+ default { fail "checking for stabs" }
+ }
+
+ print_weird_var var0
+ print_weird_var var1
+ print_weird_var var2
+ print_weird_var var3
+
+ print_weird_var attr32
+ print_weird_var attr33
+ print_weird_var attr35
+ print_weird_var attr36
+ print_weird_var attr37
+ print_weird_var attr38
+ print_weird_var attr39
+ print_weird_var attr41
+ print_weird_var attr42
+ print_weird_var attr43
+ print_weird_var attr44
+ print_weird_var attr46
+ print_weird_var attr47
+ print_weird_var attr58
+ print_weird_var attr59
+ print_weird_var attr60
+ print_weird_var attr61
+ print_weird_var attr62
+ print_weird_var attr63
+ print_weird_var attr64
+ print_weird_var attr65
+ print_weird_var attr66
+ print_weird_var attr67
+ print_weird_var attr68
+ print_weird_var attr69
+ print_weird_var attr70
+ print_weird_var attr71
+ print_weird_var attr72
+ print_weird_var attr73
+ print_weird_var attr74
+ print_weird_var attr75
+ print_weird_var attr76
+ print_weird_var attr77
+ print_weird_var attr78
+ print_weird_var attr79
+ print_weird_var attr80
+ print_weird_var attr81
+ print_weird_var attr82
+ print_weird_var attr83
+ print_weird_var attr84
+ print_weird_var attr85
+ print_weird_var attr86
+ print_weird_var attr87
+ print_weird_var attr88
+ print_weird_var attr89
+ print_weird_var attr90
+ print_weird_var attr91
+ print_weird_var attr92
+ print_weird_var attr93
+ print_weird_var attr94
+ print_weird_var attr95
+ print_weird_var attr96
+ print_weird_var attr97
+ print_weird_var attr98
+ print_weird_var attr99
+ print_weird_var attr100
+ print_weird_var attr101
+ print_weird_var attr102
+ print_weird_var attr103
+ print_weird_var attr104
+ print_weird_var attr105
+ print_weird_var attr106
+ print_weird_var attr107
+ print_weird_var attr108
+ print_weird_var attr109
+ print_weird_var attr110
+ print_weird_var attr111
+ print_weird_var attr112
+ print_weird_var attr113
+ print_weird_var attr114
+ print_weird_var attr115
+ print_weird_var attr116
+ print_weird_var attr117
+ print_weird_var attr118
+ print_weird_var attr119
+ print_weird_var attr120
+ print_weird_var attr121
+ print_weird_var attr122
+ print_weird_var attr123
+ print_weird_var attr124
+ print_weird_var attr125
+ print_weird_var attr126
+
+ gdb_test "p const69" " = 69" "'e' constant on non-enum type"
+ gdb_test "whatis const69" "type = (unsigned int|inttype)" "whatis const69"
+
+ gdb_test "p sizeof (const70)" " = 2" "'e' constant with embedded type"
+
+ gdb_test "p bad_neg0" " = \{field0 = 42, field2 =.*field3 = 45\}" "p bad_neg0"
+
+ gdb_test "ptype inttype" "type = (unsigned int|inttype)" "ptype on inttype"
+ gdb_test "p sizeof (float72type)" " = 9" "unrecognized floating point type"
+
+ # This big number needs to be kept as one piece
+ gdb_test "p/x int256var" " = 0x0*2a0000002b0000002c0000002d0000002d0000002c0000002b0000002a" "print very big integer"
+
+ gdb_test "whatis consth" "type = inttype" "whatis consth"
+ gdb_test "whatis consth2" "type = inttype" "whatis consth2"
+
+ # GDB does not yet understand S constants
+ setup_xfail "*-*-*"
+ gdb_test "p/x bad_neg0const" " = \{field0 = 0x11222211, field2 =.*\
+field3 = 0x77888877\}" "print struct constant"
+
+ gdb_test "ptype bad_type0" "type = .*" "print bad_type0"
+ gdb_test "ptype bad_type1" "type = .*" "print bad_type1"
+
+ # GDB does not yet support arrays indexed by anything at all unusual
+ setup_xfail "*-*-*"
+ gdb_test "p array0" " = \{42, 43, 44, 45, 46, 47\}" "array0 with strange index"
+ setup_xfail "*-*-*"
+ gdb_test "p array1" " = \{42, 43, 44\}" "array1 with strange index"
+
+ # GDB does not yet support this feature
+ gdb_test "whatis one_var" "type = inttype_one" \
+ "whatis one_var (known failure in gdb 4.10)"
+ # But do make sure that it prints as something reasonable
+ gdb_test "whatis one_var" "type = inttype(|_one)" \
+ "whatis one_var test 2"
+
+ gdb_test "whatis two_var" "type = inttype_two" \
+ "whatis two_var (known failure in gdb 4.10)"
+ # But do make sure that it prints as something reasonable
+ gdb_test "whatis two_var" "type = inttype(|_two)" \
+ "whatis two_var test 2"
+
+ setup_xfail "*-*-*"
+ gdb_test "whatis pointer_to_int_var" "type = int \[*\]"
+ setup_xfail "*-*-*"
+ gdb_test "whatis intp_var" "type = intp"
+
+ gdb_test "p common0var0" "= 42"
+ # GDB seems to only understand common blocks local to a function.
+ # These variables never get relocated to be relative to the common
+ # block.
+ # I'm not sure whether it is valid to have a common block which
+ # is not local to a function.
+ setup_xfail "*-*-*"
+ gdb_test "p common0var1" "= 24"
+ setup_xfail "*-*-*"
+ gdb_test "p common0var2" "= 22"
+
+ # this long line must be continous, not with "/" escaping the newline
+ gdb_test "p v_comb" "{<> = {<> = {x = 42}, \[_a-zA-Z$.\]* = \[0-9xa-fA-F\]*, a = 43}, <> = {\[_a-zA-Z$.\]* = \[0-9xa-fA-F\]*, b = 44}, comb = 45}"
+}
+
+proc print_weird_var { var } {
+ global gdb_prompt
+
+ # Make sure that the variable gets printed out correctly, without
+ # any sort of warning message.
+ send_gdb "print $var\n"
+ gdb_expect {
+ -re "^print $var\r*\n.\[0-9\]* = 42.*$gdb_prompt $" {
+ pass "variable $var printed properly"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "variable $var not printed properly"
+ }
+ timeout { fail "variable $var not printed (timeout)" }
+ eof { fail "(eof) variable $var not printed" }
+ }
+
+ # Make sure that the stabs did get loaded in a sensible way.
+ # If somehow the stabs got skipped, then the above test can
+ # pass because GDB assumes int for variables without a stab.
+
+ # This doesn't work because 32=45 doesn't preserve the name in
+ # gdb (as of 14 Sep 93 anyway).
+ #gdb_test "whatis $var" "type = (unsigned int|inttype)"
+
+ # But the size should be right.
+ gdb_test "print sizeof ($var)" "= 4"
+}
+
+
+# Don't use gdb_load; it doesn't bitch if the loading produced some
+# error messages during symbol reading.
+set testfile weird
+set srcfile ${objdir}/${subdir}/weird.s
+set binfile ${objdir}/${subdir}/weirdx.o
+
+global target_os
+set sedscript ${srcdir}/${subdir}/aout.sed
+switch -glob ${target_triplet} {
+ "hppa*-*-*" {
+ set sedscript ${srcdir}/${subdir}/hppa.sed
+ }
+ "mips-*-ecoff" {
+ set sedscript ${srcdir}/${subdir}/ecoff.sed
+ }
+ "powerpc-*-aix*" {
+ set sedscript ${srcdir}/${subdir}/xcoff.sed
+ }
+ "rs6000-*-aix*" {
+ set sedscript ${srcdir}/${subdir}/xcoff.sed
+ }
+ "*-*-aout" {
+ set sedscript ${srcdir}/${subdir}/aout.sed
+ }
+ "*-*-xcoff" {
+ set sedscript ${srcdir}/${subdir}/xcoff.sed
+ }
+ "alpha-*-*" {
+ set sedscript ${srcdir}/${subdir}/ecoff.sed
+ }
+}
+
+
+# Hope this is a Unix box.
+set exec_output [remote_exec build "sed" "-f ${sedscript}" "${srcdir}/${subdir}/weird.def" "${srcfile}"]
+if { [lindex $exec_output 0] != 0 } {
+ perror "Couldn't make test case. $exec_output"
+ return -1
+}
+
+if { [gdb_compile "${srcfile}" "${binfile}" object ""] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+remote_file build delete ${srcfile}
+
+# Start with a fresh gdb
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+
+set binfile [remote_download host ${binfile} object.o]
+send_gdb "file $binfile\n"
+# If $binfile is very long, a \r (but not a \n) will echo in the
+# middle of the echo of the command. So to match the echo, we
+# would like to match anything not containing \n
+# (we would prefer to be sure not to match any warning message).
+# But \[^\n\]* doesn't seem to work, so instead use the heuristic
+# that a filename won't contain a space and a warning message will.
+# But spaces following by backspaces aren't really spaces.
+gdb_expect 60 {
+ -re "^file (\[^ \]| +\008)*\r*\n" {
+ exp_continue
+ }
+ -re "A program is being debugged already. Kill it\\? \\(y or n\\)" {
+ send_gdb "y\n"
+ exp_continue
+ }
+ -re "^Reading symbols from $binfile\\.\\.\\.done\.\r*\n$gdb_prompt $" {
+ pass "weirdx.o read without error"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "Errors reading weirdx.o"
+ }
+ timeout {
+ perror "couldn't load $binfile into $GDB (timed out)."
+ return -1
+ }
+ eof { fail "(eof) cannot read weirdx.o" }
+}
+
+do_tests
+
+remote_file host delete ${binfile}
+
+return 0
diff --git a/gdb/testsuite/gdb.stabs/xcoff.sed b/gdb/testsuite/gdb.stabs/xcoff.sed
new file mode 100644
index 00000000000..8a6b4ef1986
--- /dev/null
+++ b/gdb/testsuite/gdb.stabs/xcoff.sed
@@ -0,0 +1,17 @@
+# Put everything in this csect, which seems to make things work.
+# The compiler actually puts the stabs in .csect [PR], but that didn't
+# work here (I guess because there is no text section).
+1i\
+ .csect .data[RW]
+# .stabs string,type,0,0,value -> .stabx string,value,type,0
+s/^[ ]*\.stabs[ ]*\("[^"]*"\),[ ]*\([^,]*\),[ ]*0,0,[ ]*\(.*\)$/.stabx \1,\3,\2,0/
+s/N_GSYM/128/
+# This needs to be C_DECL, which is used for types, not C_LSYM, which is
+# ignored on the initial scan.
+s/N_LSYM/140/
+s/\.begin_common/.bc/
+# The AIX assembler doesn't want the name in a .ec directive
+s/\.end_common.*/.ec/
+s/\.align_it/.align 1/
+/\.data/d
+/^#/d
diff --git a/gdb/testsuite/gdb.threads/Makefile.in b/gdb/testsuite/gdb.threads/Makefile.in
new file mode 100644
index 00000000000..34f22b53bb3
--- /dev/null
+++ b/gdb/testsuite/gdb.threads/Makefile.in
@@ -0,0 +1,31 @@
+VPATH = @srcdir@
+srcdir = @srcdir@
+
+EXECUTABLES = pthreads
+
+all:
+ @echo "Nothing to be done for all..."
+
+info:
+install-info:
+dvi:
+install:
+uninstall: force
+installcheck:
+check:
+
+clean mostlyclean:
+ -rm -f *~ *.o a.out xgdb *.x *.ci *.tmp core* $(EXECUTABLES)
+
+distclean maintainer-clean realclean: clean
+ -rm -f Makefile config.status config.log config.h
+
+Makefile : $(srcdir)/Makefile.in $(srcdir)/configure.in
+ $(SHELL) ./config.status --recheck
+
+config.h: stamp-h ; @true
+stamp-h: config.in config.status
+ CONFIG_HEADERS=config.h:config.in $(SHELL) config.status
+
+config.status: configure
+ $(SHELL) config.status --recheck
diff --git a/gdb/testsuite/gdb.threads/config.in b/gdb/testsuite/gdb.threads/config.in
new file mode 100644
index 00000000000..37bfc2ba592
--- /dev/null
+++ b/gdb/testsuite/gdb.threads/config.in
@@ -0,0 +1,4 @@
+/* config.in. Generated automatically from configure.in by autoheader. */
+
+/* Define if you have the <pthread.h> header file. */
+#undef HAVE_PTHREAD_H
diff --git a/gdb/testsuite/gdb.threads/configure b/gdb/testsuite/gdb.threads/configure
new file mode 100755
index 00000000000..6649098712b
--- /dev/null
+++ b/gdb/testsuite/gdb.threads/configure
@@ -0,0 +1,1098 @@
+#! /bin/sh
+
+# Guess values for system-dependent variables and create Makefiles.
+# Generated automatically using autoconf version 2.12.1
+# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc.
+#
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+
+# Defaults:
+ac_help=
+ac_default_prefix=/usr/local
+# Any additions from configure.in:
+
+# Initialize some variables set by options.
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+build=NONE
+cache_file=./config.cache
+exec_prefix=NONE
+host=NONE
+no_create=
+nonopt=NONE
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+target=NONE
+verbose=
+x_includes=NONE
+x_libraries=NONE
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datadir='${prefix}/share'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+libdir='${exec_prefix}/lib'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+infodir='${prefix}/info'
+mandir='${prefix}/man'
+
+# Initialize some other variables.
+subdirs=
+MFLAGS= MAKEFLAGS=
+SHELL=${CONFIG_SHELL-/bin/sh}
+# Maximum number of lines to put in a shell here document.
+ac_max_here_lines=12
+
+ac_prev=
+for ac_option
+do
+
+ # If the previous option needs an argument, assign it.
+ if test -n "$ac_prev"; then
+ eval "$ac_prev=\$ac_option"
+ ac_prev=
+ continue
+ fi
+
+ case "$ac_option" in
+ -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
+ *) ac_optarg= ;;
+ esac
+
+ # Accept the important Cygnus configure options, so we can diagnose typos.
+
+ case "$ac_option" in
+
+ -bindir | --bindir | --bindi | --bind | --bin | --bi)
+ ac_prev=bindir ;;
+ -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+ bindir="$ac_optarg" ;;
+
+ -build | --build | --buil | --bui | --bu)
+ ac_prev=build ;;
+ -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+ build="$ac_optarg" ;;
+
+ -cache-file | --cache-file | --cache-fil | --cache-fi \
+ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+ ac_prev=cache_file ;;
+ -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+ cache_file="$ac_optarg" ;;
+
+ -datadir | --datadir | --datadi | --datad | --data | --dat | --da)
+ ac_prev=datadir ;;
+ -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \
+ | --da=*)
+ datadir="$ac_optarg" ;;
+
+ -disable-* | --disable-*)
+ ac_feature=`echo $ac_option|sed -e 's/-*disable-//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then
+ { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
+ fi
+ ac_feature=`echo $ac_feature| sed 's/-/_/g'`
+ eval "enable_${ac_feature}=no" ;;
+
+ -enable-* | --enable-*)
+ ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then
+ { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
+ fi
+ ac_feature=`echo $ac_feature| sed 's/-/_/g'`
+ case "$ac_option" in
+ *=*) ;;
+ *) ac_optarg=yes ;;
+ esac
+ eval "enable_${ac_feature}='$ac_optarg'" ;;
+
+ -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+ | --exec | --exe | --ex)
+ ac_prev=exec_prefix ;;
+ -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+ | --exec=* | --exe=* | --ex=*)
+ exec_prefix="$ac_optarg" ;;
+
+ -gas | --gas | --ga | --g)
+ # Obsolete; use --with-gas.
+ with_gas=yes ;;
+
+ -help | --help | --hel | --he)
+ # Omit some internal or obsolete options to make the list less imposing.
+ # This message is too long to be a string in the A/UX 3.1 sh.
+ cat << EOF
+Usage: configure [options] [host]
+Options: [defaults in brackets after descriptions]
+Configuration:
+ --cache-file=FILE cache test results in FILE
+ --help print this message
+ --no-create do not create output files
+ --quiet, --silent do not print \`checking...' messages
+ --version print the version of autoconf that created configure
+Directory and file names:
+ --prefix=PREFIX install architecture-independent files in PREFIX
+ [$ac_default_prefix]
+ --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
+ [same as prefix]
+ --bindir=DIR user executables in DIR [EPREFIX/bin]
+ --sbindir=DIR system admin executables in DIR [EPREFIX/sbin]
+ --libexecdir=DIR program executables in DIR [EPREFIX/libexec]
+ --datadir=DIR read-only architecture-independent data in DIR
+ [PREFIX/share]
+ --sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc]
+ --sharedstatedir=DIR modifiable architecture-independent data in DIR
+ [PREFIX/com]
+ --localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var]
+ --libdir=DIR object code libraries in DIR [EPREFIX/lib]
+ --includedir=DIR C header files in DIR [PREFIX/include]
+ --oldincludedir=DIR C header files for non-gcc in DIR [/usr/include]
+ --infodir=DIR info documentation in DIR [PREFIX/info]
+ --mandir=DIR man documentation in DIR [PREFIX/man]
+ --srcdir=DIR find the sources in DIR [configure dir or ..]
+ --program-prefix=PREFIX prepend PREFIX to installed program names
+ --program-suffix=SUFFIX append SUFFIX to installed program names
+ --program-transform-name=PROGRAM
+ run sed PROGRAM on installed program names
+EOF
+ cat << EOF
+Host type:
+ --build=BUILD configure for building on BUILD [BUILD=HOST]
+ --host=HOST configure for HOST [guessed]
+ --target=TARGET configure for TARGET [TARGET=HOST]
+Features and packages:
+ --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
+ --enable-FEATURE[=ARG] include FEATURE [ARG=yes]
+ --with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
+ --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
+ --x-includes=DIR X include files are in DIR
+ --x-libraries=DIR X library files are in DIR
+EOF
+ if test -n "$ac_help"; then
+ echo "--enable and --with options recognized:$ac_help"
+ fi
+ exit 0 ;;
+
+ -host | --host | --hos | --ho)
+ ac_prev=host ;;
+ -host=* | --host=* | --hos=* | --ho=*)
+ host="$ac_optarg" ;;
+
+ -includedir | --includedir | --includedi | --included | --include \
+ | --includ | --inclu | --incl | --inc)
+ ac_prev=includedir ;;
+ -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+ | --includ=* | --inclu=* | --incl=* | --inc=*)
+ includedir="$ac_optarg" ;;
+
+ -infodir | --infodir | --infodi | --infod | --info | --inf)
+ ac_prev=infodir ;;
+ -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+ infodir="$ac_optarg" ;;
+
+ -libdir | --libdir | --libdi | --libd)
+ ac_prev=libdir ;;
+ -libdir=* | --libdir=* | --libdi=* | --libd=*)
+ libdir="$ac_optarg" ;;
+
+ -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+ | --libexe | --libex | --libe)
+ ac_prev=libexecdir ;;
+ -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+ | --libexe=* | --libex=* | --libe=*)
+ libexecdir="$ac_optarg" ;;
+
+ -localstatedir | --localstatedir | --localstatedi | --localstated \
+ | --localstate | --localstat | --localsta | --localst \
+ | --locals | --local | --loca | --loc | --lo)
+ ac_prev=localstatedir ;;
+ -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+ | --localstate=* | --localstat=* | --localsta=* | --localst=* \
+ | --locals=* | --local=* | --loca=* | --loc=* | --lo=*)
+ localstatedir="$ac_optarg" ;;
+
+ -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+ ac_prev=mandir ;;
+ -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+ mandir="$ac_optarg" ;;
+
+ -nfp | --nfp | --nf)
+ # Obsolete; use --without-fp.
+ with_fp=no ;;
+
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c)
+ no_create=yes ;;
+
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+ no_recursion=yes ;;
+
+ -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+ | --oldin | --oldi | --old | --ol | --o)
+ ac_prev=oldincludedir ;;
+ -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+ oldincludedir="$ac_optarg" ;;
+
+ -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+ ac_prev=prefix ;;
+ -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+ prefix="$ac_optarg" ;;
+
+ -program-prefix | --program-prefix | --program-prefi | --program-pref \
+ | --program-pre | --program-pr | --program-p)
+ ac_prev=program_prefix ;;
+ -program-prefix=* | --program-prefix=* | --program-prefi=* \
+ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+ program_prefix="$ac_optarg" ;;
+
+ -program-suffix | --program-suffix | --program-suffi | --program-suff \
+ | --program-suf | --program-su | --program-s)
+ ac_prev=program_suffix ;;
+ -program-suffix=* | --program-suffix=* | --program-suffi=* \
+ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+ program_suffix="$ac_optarg" ;;
+
+ -program-transform-name | --program-transform-name \
+ | --program-transform-nam | --program-transform-na \
+ | --program-transform-n | --program-transform- \
+ | --program-transform | --program-transfor \
+ | --program-transfo | --program-transf \
+ | --program-trans | --program-tran \
+ | --progr-tra | --program-tr | --program-t)
+ ac_prev=program_transform_name ;;
+ -program-transform-name=* | --program-transform-name=* \
+ | --program-transform-nam=* | --program-transform-na=* \
+ | --program-transform-n=* | --program-transform-=* \
+ | --program-transform=* | --program-transfor=* \
+ | --program-transfo=* | --program-transf=* \
+ | --program-trans=* | --program-tran=* \
+ | --progr-tra=* | --program-tr=* | --program-t=*)
+ program_transform_name="$ac_optarg" ;;
+
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ silent=yes ;;
+
+ -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+ ac_prev=sbindir ;;
+ -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+ | --sbi=* | --sb=*)
+ sbindir="$ac_optarg" ;;
+
+ -sharedstatedir | --sharedstatedir | --sharedstatedi \
+ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+ | --sharedst | --shareds | --shared | --share | --shar \
+ | --sha | --sh)
+ ac_prev=sharedstatedir ;;
+ -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+ | --sha=* | --sh=*)
+ sharedstatedir="$ac_optarg" ;;
+
+ -site | --site | --sit)
+ ac_prev=site ;;
+ -site=* | --site=* | --sit=*)
+ site="$ac_optarg" ;;
+
+ -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+ ac_prev=srcdir ;;
+ -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+ srcdir="$ac_optarg" ;;
+
+ -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+ | --syscon | --sysco | --sysc | --sys | --sy)
+ ac_prev=sysconfdir ;;
+ -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+ sysconfdir="$ac_optarg" ;;
+
+ -target | --target | --targe | --targ | --tar | --ta | --t)
+ ac_prev=target ;;
+ -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+ target="$ac_optarg" ;;
+
+ -v | -verbose | --verbose | --verbos | --verbo | --verb)
+ verbose=yes ;;
+
+ -version | --version | --versio | --versi | --vers)
+ echo "configure generated by autoconf version 2.12.1"
+ exit 0 ;;
+
+ -with-* | --with-*)
+ ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then
+ { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
+ fi
+ ac_package=`echo $ac_package| sed 's/-/_/g'`
+ case "$ac_option" in
+ *=*) ;;
+ *) ac_optarg=yes ;;
+ esac
+ eval "with_${ac_package}='$ac_optarg'" ;;
+
+ -without-* | --without-*)
+ ac_package=`echo $ac_option|sed -e 's/-*without-//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then
+ { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
+ fi
+ ac_package=`echo $ac_package| sed 's/-/_/g'`
+ eval "with_${ac_package}=no" ;;
+
+ --x)
+ # Obsolete; use --with-x.
+ with_x=yes ;;
+
+ -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+ | --x-incl | --x-inc | --x-in | --x-i)
+ ac_prev=x_includes ;;
+ -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+ x_includes="$ac_optarg" ;;
+
+ -x-libraries | --x-libraries | --x-librarie | --x-librari \
+ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+ ac_prev=x_libraries ;;
+ -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+ x_libraries="$ac_optarg" ;;
+
+ -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; }
+ ;;
+
+ *)
+ if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then
+ echo "configure: warning: $ac_option: invalid host type" 1>&2
+ fi
+ if test "x$nonopt" != xNONE; then
+ { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; }
+ fi
+ nonopt="$ac_option"
+ ;;
+
+ esac
+done
+
+if test -n "$ac_prev"; then
+ { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; }
+fi
+
+trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
+
+# File descriptor usage:
+# 0 standard input
+# 1 file creation
+# 2 errors and warnings
+# 3 some systems may open it to /dev/tty
+# 4 used on the Kubota Titan
+# 6 checking for... messages and results
+# 5 compiler messages saved in config.log
+if test "$silent" = yes; then
+ exec 6>/dev/null
+else
+ exec 6>&1
+fi
+exec 5>./config.log
+
+echo "\
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+" 1>&5
+
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Also quote any args containing shell metacharacters.
+ac_configure_args=
+for ac_arg
+do
+ case "$ac_arg" in
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c) ;;
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;;
+ *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*)
+ ac_configure_args="$ac_configure_args '$ac_arg'" ;;
+ *) ac_configure_args="$ac_configure_args $ac_arg" ;;
+ esac
+done
+
+# NLS nuisances.
+# Only set these to C if already set. These must not be set unconditionally
+# because not all systems understand e.g. LANG=C (notably SCO).
+# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'!
+# Non-C LC_CTYPE values break the ctype check.
+if test "${LANG+set}" = set; then LANG=C; export LANG; fi
+if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi
+if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi
+if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -rf conftest* confdefs.h
+# AIX cpp loses on an empty file, so make sure it contains at least a newline.
+echo > confdefs.h
+
+# A filename unique to this package, relative to the directory that
+# configure is in, which we can look for to find out if srcdir is correct.
+ac_unique_file=pthreads.exp
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+ ac_srcdir_defaulted=yes
+ # Try the directory containing this script, then its parent.
+ ac_prog=$0
+ ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'`
+ test "x$ac_confdir" = "x$ac_prog" && ac_confdir=.
+ srcdir=$ac_confdir
+ if test ! -r $srcdir/$ac_unique_file; then
+ srcdir=..
+ fi
+else
+ ac_srcdir_defaulted=no
+fi
+if test ! -r $srcdir/$ac_unique_file; then
+ if test "$ac_srcdir_defaulted" = yes; then
+ { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; }
+ else
+ { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; }
+ fi
+fi
+srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'`
+
+# Prefer explicitly selected file to automatically selected ones.
+if test -z "$CONFIG_SITE"; then
+ if test "x$prefix" != xNONE; then
+ CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site"
+ else
+ CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
+ fi
+fi
+for ac_site_file in $CONFIG_SITE; do
+ if test -r "$ac_site_file"; then
+ echo "loading site script $ac_site_file"
+ . "$ac_site_file"
+ fi
+done
+
+if test -r "$cache_file"; then
+ echo "loading cache $cache_file"
+ . $cache_file
+else
+ echo "creating cache $cache_file"
+ > $cache_file
+fi
+
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then
+ # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu.
+ if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then
+ ac_n= ac_c='
+' ac_t=' '
+ else
+ ac_n=-n ac_c= ac_t=
+ fi
+else
+ ac_n= ac_c='\c' ac_t=
+fi
+
+
+
+
+CC=${CC-cc}
+
+ac_aux_dir=
+for ac_dir in `cd $srcdir;pwd`/../../.. $srcdir/`cd $srcdir;pwd`/../../..; do
+ if test -f $ac_dir/install-sh; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install-sh -c"
+ break
+ elif test -f $ac_dir/install.sh; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install.sh -c"
+ break
+ fi
+done
+if test -z "$ac_aux_dir"; then
+ { echo "configure: error: can not find install-sh or install.sh in `cd $srcdir;pwd`/../../.. $srcdir/`cd $srcdir;pwd`/../../.." 1>&2; exit 1; }
+fi
+ac_config_guess=$ac_aux_dir/config.guess
+ac_config_sub=$ac_aux_dir/config.sub
+ac_configure=$ac_aux_dir/configure # This should be Cygnus configure.
+
+
+# Do some error checking and defaulting for the host and target type.
+# The inputs are:
+# configure --host=HOST --target=TARGET --build=BUILD NONOPT
+#
+# The rules are:
+# 1. You are not allowed to specify --host, --target, and nonopt at the
+# same time.
+# 2. Host defaults to nonopt.
+# 3. If nonopt is not specified, then host defaults to the current host,
+# as determined by config.guess.
+# 4. Target and build default to nonopt.
+# 5. If nonopt is not specified, then target and build default to host.
+
+# The aliases save the names the user supplied, while $host etc.
+# will get canonicalized.
+case $host---$target---$nonopt in
+NONE---*---* | *---NONE---* | *---*---NONE) ;;
+*) { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; } ;;
+esac
+
+
+# Make sure we can run config.sub.
+if ${CONFIG_SHELL-/bin/sh} $ac_config_sub sun4 >/dev/null 2>&1; then :
+else { echo "configure: error: can not run $ac_config_sub" 1>&2; exit 1; }
+fi
+
+echo $ac_n "checking host system type""... $ac_c" 1>&6
+echo "configure:574: checking host system type" >&5
+
+host_alias=$host
+case "$host_alias" in
+NONE)
+ case $nonopt in
+ NONE)
+ if host_alias=`${CONFIG_SHELL-/bin/sh} $ac_config_guess`; then :
+ else { echo "configure: error: can not guess host type; you must specify one" 1>&2; exit 1; }
+ fi ;;
+ *) host_alias=$nonopt ;;
+ esac ;;
+esac
+
+host=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $host_alias`
+host_cpu=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+host_vendor=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+host_os=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+echo "$ac_t""$host" 1>&6
+
+echo $ac_n "checking target system type""... $ac_c" 1>&6
+echo "configure:595: checking target system type" >&5
+
+target_alias=$target
+case "$target_alias" in
+NONE)
+ case $nonopt in
+ NONE) target_alias=$host_alias ;;
+ *) target_alias=$nonopt ;;
+ esac ;;
+esac
+
+target=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $target_alias`
+target_cpu=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+target_vendor=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+target_os=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+echo "$ac_t""$target" 1>&6
+
+echo $ac_n "checking build system type""... $ac_c" 1>&6
+echo "configure:613: checking build system type" >&5
+
+build_alias=$build
+case "$build_alias" in
+NONE)
+ case $nonopt in
+ NONE) build_alias=$host_alias ;;
+ *) build_alias=$nonopt ;;
+ esac ;;
+esac
+
+build=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $build_alias`
+build_cpu=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+build_vendor=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+build_os=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+echo "$ac_t""$build" 1>&6
+
+test "$host_alias" != "$target_alias" &&
+ test "$program_prefix$program_suffix$program_transform_name" = \
+ NONENONEs,x,x, &&
+ program_prefix=${target_alias}-
+
+
+echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6
+echo "configure:637: checking how to run the C preprocessor" >&5
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+ CPP=
+fi
+if test -z "$CPP"; then
+if eval "test \"`echo '$''{'ac_cv_prog_CPP'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ # This must be in double quotes, not single quotes, because CPP may get
+ # substituted into the Makefile and "${CC-cc}" will confuse make.
+ CPP="${CC-cc} -E"
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp.
+ cat > conftest.$ac_ext <<EOF
+#line 652 "configure"
+#include "confdefs.h"
+#include <assert.h>
+Syntax Error
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:658: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out`
+if test -z "$ac_err"; then
+ :
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ CPP="${CC-cc} -E -traditional-cpp"
+ cat > conftest.$ac_ext <<EOF
+#line 669 "configure"
+#include "confdefs.h"
+#include <assert.h>
+Syntax Error
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:675: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out`
+if test -z "$ac_err"; then
+ :
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ CPP=/lib/cpp
+fi
+rm -f conftest*
+fi
+rm -f conftest*
+ ac_cv_prog_CPP="$CPP"
+fi
+ CPP="$ac_cv_prog_CPP"
+else
+ ac_cv_prog_CPP="$CPP"
+fi
+echo "$ac_t""$CPP" 1>&6
+
+for ac_hdr in pthread.h
+do
+ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
+echo "configure:701: checking for $ac_hdr" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 706 "configure"
+#include "confdefs.h"
+#include <$ac_hdr>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:711: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=yes"
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_hdr 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+
+trap '' 1 2 15
+cat > confcache <<\EOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs. It is not useful on other systems.
+# If it contains results you don't want to keep, you may remove or edit it.
+#
+# By default, configure uses ./config.cache as the cache file,
+# creating it if it does not exist already. You can give configure
+# the --cache-file=FILE option to use a different cache file; that is
+# what configure does when it calls configure scripts in
+# subdirectories, so they share the cache.
+# Giving --cache-file=/dev/null disables caching, for debugging configure.
+# config.status only pays attention to the cache file if you give it the
+# --recheck option to rerun configure.
+#
+EOF
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, don't put newlines in cache variables' values.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(set) 2>&1 |
+ case `(ac_space=' '; set) 2>&1 | grep ac_space` in
+ *ac_space=\ *)
+ # `set' does not quote correctly, so add quotes (double-quote substitution
+ # turns \\\\ into \\, and sed turns \\ into \).
+ sed -n \
+ -e "s/'/'\\\\''/g" \
+ -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p"
+ ;;
+ *)
+ # `set' quotes correctly as required by POSIX, so do not add quotes.
+ sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p'
+ ;;
+ esac >> confcache
+if cmp -s $cache_file confcache; then
+ :
+else
+ if test -w $cache_file; then
+ echo "updating cache $cache_file"
+ cat confcache > $cache_file
+ else
+ echo "not updating unwritable cache $cache_file"
+ fi
+fi
+rm -f confcache
+
+trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+# Any assignment to VPATH causes Sun make to only execute
+# the first set of double-colon rules, so remove it if not needed.
+# If there is a colon in the path, we need to keep it.
+if test "x$srcdir" = x.; then
+ ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d'
+fi
+
+trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15
+
+DEFS=-DHAVE_CONFIG_H
+
+# Without the "./", some shells look in PATH for config.status.
+: ${CONFIG_STATUS=./config.status}
+
+echo creating $CONFIG_STATUS
+rm -f $CONFIG_STATUS
+cat > $CONFIG_STATUS <<EOF
+#! /bin/sh
+# Generated automatically by configure.
+# Run this file to recreate the current configuration.
+# This directory was configured as follows,
+# on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+#
+# $0 $ac_configure_args
+#
+# Compiler output produced by configure, useful for debugging
+# configure, is in ./config.log if it exists.
+
+ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]"
+for ac_option
+do
+ case "\$ac_option" in
+ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+ echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion"
+ exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;;
+ -version | --version | --versio | --versi | --vers | --ver | --ve | --v)
+ echo "$CONFIG_STATUS generated by autoconf version 2.12.1"
+ exit 0 ;;
+ -help | --help | --hel | --he | --h)
+ echo "\$ac_cs_usage"; exit 0 ;;
+ *) echo "\$ac_cs_usage"; exit 1 ;;
+ esac
+done
+
+ac_given_srcdir=$srcdir
+
+trap 'rm -fr `echo "Makefile config.h:config.in" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15
+EOF
+cat >> $CONFIG_STATUS <<EOF
+
+# Protect against being on the right side of a sed subst in config.status.
+sed 's/%@/@@/; s/@%/@@/; s/%g\$/@g/; /@g\$/s/[\\\\&%]/\\\\&/g;
+ s/@@/%@/; s/@@/@%/; s/@g\$/%g/' > conftest.subs <<\\CEOF
+$ac_vpsub
+$extrasub
+s%@SHELL@%$SHELL%g
+s%@CFLAGS@%$CFLAGS%g
+s%@CPPFLAGS@%$CPPFLAGS%g
+s%@CXXFLAGS@%$CXXFLAGS%g
+s%@DEFS@%$DEFS%g
+s%@LDFLAGS@%$LDFLAGS%g
+s%@LIBS@%$LIBS%g
+s%@exec_prefix@%$exec_prefix%g
+s%@prefix@%$prefix%g
+s%@program_transform_name@%$program_transform_name%g
+s%@bindir@%$bindir%g
+s%@sbindir@%$sbindir%g
+s%@libexecdir@%$libexecdir%g
+s%@datadir@%$datadir%g
+s%@sysconfdir@%$sysconfdir%g
+s%@sharedstatedir@%$sharedstatedir%g
+s%@localstatedir@%$localstatedir%g
+s%@libdir@%$libdir%g
+s%@includedir@%$includedir%g
+s%@oldincludedir@%$oldincludedir%g
+s%@infodir@%$infodir%g
+s%@mandir@%$mandir%g
+s%@CC@%$CC%g
+s%@host@%$host%g
+s%@host_alias@%$host_alias%g
+s%@host_cpu@%$host_cpu%g
+s%@host_vendor@%$host_vendor%g
+s%@host_os@%$host_os%g
+s%@target@%$target%g
+s%@target_alias@%$target_alias%g
+s%@target_cpu@%$target_cpu%g
+s%@target_vendor@%$target_vendor%g
+s%@target_os@%$target_os%g
+s%@build@%$build%g
+s%@build_alias@%$build_alias%g
+s%@build_cpu@%$build_cpu%g
+s%@build_vendor@%$build_vendor%g
+s%@build_os@%$build_os%g
+s%@CPP@%$CPP%g
+
+CEOF
+EOF
+
+cat >> $CONFIG_STATUS <<\EOF
+
+# Split the substitutions into bite-sized pieces for seds with
+# small command number limits, like on Digital OSF/1 and HP-UX.
+ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script.
+ac_file=1 # Number of current file.
+ac_beg=1 # First line for current file.
+ac_end=$ac_max_sed_cmds # Line after last line for current file.
+ac_more_lines=:
+ac_sed_cmds=""
+while $ac_more_lines; do
+ if test $ac_beg -gt 1; then
+ sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file
+ else
+ sed "${ac_end}q" conftest.subs > conftest.s$ac_file
+ fi
+ if test ! -s conftest.s$ac_file; then
+ ac_more_lines=false
+ rm -f conftest.s$ac_file
+ else
+ if test -z "$ac_sed_cmds"; then
+ ac_sed_cmds="sed -f conftest.s$ac_file"
+ else
+ ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file"
+ fi
+ ac_file=`expr $ac_file + 1`
+ ac_beg=$ac_end
+ ac_end=`expr $ac_end + $ac_max_sed_cmds`
+ fi
+done
+if test -z "$ac_sed_cmds"; then
+ ac_sed_cmds=cat
+fi
+EOF
+
+cat >> $CONFIG_STATUS <<EOF
+
+CONFIG_FILES=\${CONFIG_FILES-"Makefile"}
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then
+ # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+ case "$ac_file" in
+ *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'`
+ ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
+ *) ac_file_in="${ac_file}.in" ;;
+ esac
+
+ # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories.
+
+ # Remove last slash and all that follows it. Not all systems have dirname.
+ ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
+ if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
+ # The file is in a subdirectory.
+ test ! -d "$ac_dir" && mkdir "$ac_dir"
+ ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`"
+ # A "../" for each directory in $ac_dir_suffix.
+ ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'`
+ else
+ ac_dir_suffix= ac_dots=
+ fi
+
+ case "$ac_given_srcdir" in
+ .) srcdir=.
+ if test -z "$ac_dots"; then top_srcdir=.
+ else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;;
+ /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;;
+ *) # Relative path.
+ srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix"
+ top_srcdir="$ac_dots$ac_given_srcdir" ;;
+ esac
+
+
+ echo creating "$ac_file"
+ rm -f "$ac_file"
+ configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure."
+ case "$ac_file" in
+ *Makefile*) ac_comsub="1i\\
+# $configure_input" ;;
+ *) ac_comsub= ;;
+ esac
+
+ ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"`
+ sed -e "$ac_comsub
+s%@configure_input@%$configure_input%g
+s%@srcdir@%$srcdir%g
+s%@top_srcdir@%$top_srcdir%g
+" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file
+fi; done
+rm -f conftest.s*
+
+# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where
+# NAME is the cpp macro being defined and VALUE is the value it is being given.
+#
+# ac_d sets the value in "#define NAME VALUE" lines.
+ac_dA='s%^\([ ]*\)#\([ ]*define[ ][ ]*\)'
+ac_dB='\([ ][ ]*\)[^ ]*%\1#\2'
+ac_dC='\3'
+ac_dD='%g'
+# ac_u turns "#undef NAME" with trailing blanks into "#define NAME VALUE".
+ac_uA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)'
+ac_uB='\([ ]\)%\1#\2define\3'
+ac_uC=' '
+ac_uD='\4%g'
+# ac_e turns "#undef NAME" without trailing blanks into "#define NAME VALUE".
+ac_eA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)'
+ac_eB='$%\1#\2define\3'
+ac_eC=' '
+ac_eD='%g'
+
+if test "${CONFIG_HEADERS+set}" != set; then
+EOF
+cat >> $CONFIG_STATUS <<EOF
+ CONFIG_HEADERS="config.h:config.in"
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+fi
+for ac_file in .. $CONFIG_HEADERS; do if test "x$ac_file" != x..; then
+ # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+ case "$ac_file" in
+ *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'`
+ ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
+ *) ac_file_in="${ac_file}.in" ;;
+ esac
+
+ echo creating $ac_file
+
+ rm -f conftest.frag conftest.in conftest.out
+ ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"`
+ cat $ac_file_inputs > conftest.in
+
+EOF
+
+# Transform confdefs.h into a sed script conftest.vals that substitutes
+# the proper values into config.h.in to produce config.h. And first:
+# Protect against being on the right side of a sed subst in config.status.
+# Protect against being in an unquoted here document in config.status.
+rm -f conftest.vals
+cat > conftest.hdr <<\EOF
+s/[\\&%]/\\&/g
+s%[\\$`]%\\&%g
+s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD}%gp
+s%ac_d%ac_u%gp
+s%ac_u%ac_e%gp
+EOF
+sed -n -f conftest.hdr confdefs.h > conftest.vals
+rm -f conftest.hdr
+
+# This sed command replaces #undef with comments. This is necessary, for
+# example, in the case of _POSIX_SOURCE, which is predefined and required
+# on some systems where configure will not decide to define it.
+cat >> conftest.vals <<\EOF
+s%^[ ]*#[ ]*undef[ ][ ]*[a-zA-Z_][a-zA-Z_0-9]*%/* & */%
+EOF
+
+# Break up conftest.vals because some shells have a limit on
+# the size of here documents, and old seds have small limits too.
+
+rm -f conftest.tail
+while :
+do
+ ac_lines=`grep -c . conftest.vals`
+ # grep -c gives empty output for an empty file on some AIX systems.
+ if test -z "$ac_lines" || test "$ac_lines" -eq 0; then break; fi
+ # Write a limited-size here document to conftest.frag.
+ echo ' cat > conftest.frag <<CEOF' >> $CONFIG_STATUS
+ sed ${ac_max_here_lines}q conftest.vals >> $CONFIG_STATUS
+ echo 'CEOF
+ sed -f conftest.frag conftest.in > conftest.out
+ rm -f conftest.in
+ mv conftest.out conftest.in
+' >> $CONFIG_STATUS
+ sed 1,${ac_max_here_lines}d conftest.vals > conftest.tail
+ rm -f conftest.vals
+ mv conftest.tail conftest.vals
+done
+rm -f conftest.vals
+
+cat >> $CONFIG_STATUS <<\EOF
+ rm -f conftest.frag conftest.h
+ echo "/* $ac_file. Generated automatically by configure. */" > conftest.h
+ cat conftest.in >> conftest.h
+ rm -f conftest.in
+ if cmp -s $ac_file conftest.h 2>/dev/null; then
+ echo "$ac_file is unchanged"
+ rm -f conftest.h
+ else
+ # Remove last slash and all that follows it. Not all systems have dirname.
+ ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
+ if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
+ # The file is in a subdirectory.
+ test ! -d "$ac_dir" && mkdir "$ac_dir"
+ fi
+ rm -f $ac_file
+ mv conftest.h $ac_file
+ fi
+fi; done
+
+EOF
+cat >> $CONFIG_STATUS <<EOF
+
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+
+exit 0
+EOF
+chmod +x $CONFIG_STATUS
+rm -fr confdefs* $ac_clean_files
+test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1
+
diff --git a/gdb/testsuite/gdb.threads/configure.in b/gdb/testsuite/gdb.threads/configure.in
new file mode 100644
index 00000000000..1afe91ac4e1
--- /dev/null
+++ b/gdb/testsuite/gdb.threads/configure.in
@@ -0,0 +1,18 @@
+dnl Process this file file with autoconf to produce a configure script.
+dnl This file is a shell script fragment that supplies the information
+dnl necessary to tailor a template configure script into the configure
+dnl script appropriate for this directory. For more information, check
+dnl any existing configure script.
+
+AC_PREREQ(2.5)
+AC_INIT(pthreads.exp)
+AC_CONFIG_HEADER(config.h:config.in)
+
+CC=${CC-cc}
+AC_SUBST(CC)
+AC_CONFIG_AUX_DIR(`cd $srcdir;pwd`/../../..)
+AC_CANONICAL_SYSTEM
+
+AC_CHECK_HEADERS(pthread.h)
+
+AC_OUTPUT(Makefile)
diff --git a/gdb/testsuite/gdb.threads/pthreads.c b/gdb/testsuite/gdb.threads/pthreads.c
new file mode 100644
index 00000000000..1fe1ae96f35
--- /dev/null
+++ b/gdb/testsuite/gdb.threads/pthreads.c
@@ -0,0 +1,168 @@
+#include <stdio.h>
+
+#include "config.h"
+
+#ifndef HAVE_PTHREAD_H
+
+/* Don't even try to compile. In fact, cause a syntax error that we can
+ look for as a compiler error message and know that we have no pthread
+ support. In that case we can just suppress the test completely. */
+
+#error "no posix threads support"
+
+#else
+
+/* OK. We have the right header. If we try to compile this and fail, then
+ there is something wrong and the user should know about it so the testsuite
+ should issue an ERROR result.. */
+
+#ifdef __linux__
+#define _MIT_POSIX_THREADS 1 /* Linux (or at least RedHat 4.0) needs this */
+#endif
+
+#include <pthread.h>
+
+/* Under OSF 2.0 & 3.0 and HPUX 10, the second arg of pthread_create
+ is prototyped to be just a "pthread_attr_t", while under Solaris it
+ is a "pthread_attr_t *". Arg! */
+
+#if defined (__osf__) || defined (__hpux__)
+#define PTHREAD_CREATE_ARG2(arg) arg
+#define PTHREAD_CREATE_NULL_ARG2 null_attr
+static pthread_attr_t null_attr;
+#else
+#define PTHREAD_CREATE_ARG2(arg) &arg
+#define PTHREAD_CREATE_NULL_ARG2 NULL
+#endif
+
+static int verbose = 0;
+
+static void
+common_routine (arg)
+ int arg;
+{
+ static int from_thread1;
+ static int from_thread2;
+ static int from_main;
+ static int hits;
+ static int full_coverage;
+
+ if (verbose) printf("common_routine (%d)\n", arg);
+ hits++;
+ switch (arg)
+ {
+ case 0:
+ from_main++;
+ break;
+ case 1:
+ from_thread1++;
+ break;
+ case 2:
+ from_thread2++;
+ break;
+ }
+ if (from_main && from_thread1 && from_thread2)
+ full_coverage = 1;
+}
+
+static void *
+thread1 (void *arg)
+{
+ int i;
+ int z = 0;
+
+ if (verbose) printf ("thread1 (%0x) ; pid = %d\n", arg, getpid ());
+ for (i=1; i <= 10000000; i++)
+ {
+ if (verbose) printf("thread1 %d\n", pthread_self ());
+ z += i;
+ common_routine (1);
+ sleep(1);
+ }
+}
+
+static void *
+thread2 (void * arg)
+{
+ int i;
+ int k = 0;
+
+ if (verbose) printf ("thread2 (%0x) ; pid = %d\n", arg, getpid ());
+ for (i=1; i <= 10000000; i++)
+ {
+ if (verbose) printf("thread2 %d\n", pthread_self ());
+ k += i;
+ common_routine (2);
+ sleep(1);
+ }
+ sleep(100);
+}
+
+int
+foo (a, b, c)
+ int a, b, c;
+{
+ int d, e, f;
+
+ if (verbose) printf("a=%d\n", a);
+}
+
+main(argc, argv)
+ int argc;
+ char **argv;
+{
+ pthread_t tid1, tid2;
+ int j;
+ int t = 0;
+ void (*xxx) ();
+ pthread_attr_t attr;
+
+ if (verbose) printf ("pid = %d\n", getpid());
+
+ foo (1, 2, 3);
+
+#ifndef __osf__
+ if (pthread_attr_init (&attr))
+ {
+ perror ("pthread_attr_init 1");
+ exit (1);
+ }
+#endif
+
+#ifdef PTHREAD_SCOPE_SYSTEM
+ if (pthread_attr_setscope (&attr, PTHREAD_SCOPE_SYSTEM))
+ {
+ perror ("pthread_attr_setscope 1");
+ exit (1);
+ }
+#endif
+
+ if (pthread_create (&tid1, PTHREAD_CREATE_ARG2(attr), thread1, (void *) 0xfeedface))
+ {
+ perror ("pthread_create 1");
+ exit (1);
+ }
+ if (verbose) printf ("Made thread %d\n", tid1);
+ sleep (1);
+
+ if (pthread_create (&tid2, PTHREAD_CREATE_NULL_ARG2, thread2, (void *) 0xdeadbeef))
+ {
+ perror ("pthread_create 2");
+ exit (1);
+ }
+ if (verbose) printf("Made thread %d\n", tid2);
+
+ sleep (1);
+
+ for (j = 1; j <= 10000000; j++)
+ {
+ if (verbose) printf("top %d\n", pthread_self ());
+ common_routine (0);
+ sleep(1);
+ t += j;
+ }
+
+ exit(0);
+}
+
+#endif /* ifndef HAVE_PTHREAD_H */
diff --git a/gdb/testsuite/gdb.threads/pthreads.exp b/gdb/testsuite/gdb.threads/pthreads.exp
new file mode 100644
index 00000000000..08e4af384d6
--- /dev/null
+++ b/gdb/testsuite/gdb.threads/pthreads.exp
@@ -0,0 +1,328 @@
+# Copyright (C) 1996, 1997 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file was written by Fred Fish. (fnf@cygnus.com)
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+set prms_id 0
+set bug_id 0
+
+# This only works with native configurations
+if ![isnative] then {
+ return
+}
+
+set testfile "pthreads"
+set srcfile ${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+
+# regexp for "horizontal" text (i.e. doesn't include newline or
+# carriage return)
+set horiz "\[^\n\r\]*"
+
+set built_binfile 0
+if [istarget "*-*-linux"] then {
+ set target_cflags "-D_MIT_POSIX_THREADS"
+} else {
+ set target_cflags ""
+}
+set why_msg "unrecognized error"
+foreach lib {-lpthreads -lpthread} {
+ set options "debug"
+ lappend options "incdir=${objdir}/${subdir}"
+ lappend options "libs=$lib"
+ set ccout [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable $options]
+ switch -regexp -- $ccout {
+ ".*no posix threads support.*" {
+ set why_msg "missing threads include file"
+ break
+ }
+ ".*cannot open -lpthread.*" {
+ set why_msg "missing runtime threads library"
+ }
+ ".*Can't find library for -lpthread.*" {
+ set why_msg "missing runtime threads library"
+ }
+ {^$} {
+ pass "successfully compiled posix threads test case"
+ set built_binfile 1
+ break
+ }
+ }
+}
+if {$built_binfile == "0"} {
+ unsupported "Couldn't compile ${srcfile}, ${why_msg}"
+ return -1
+}
+
+# Now we can proceed with the real testing.
+
+# Start with a fresh gdb.
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+gdb_test "set print sevenbit-strings" ""
+#gdb_test "set print address off" ""
+gdb_test "set width 0" ""
+
+# We'll need this when we send_gdb a ^C to GDB. Need to do it before we
+# run the program and gdb starts saving and restoring tty states.
+# On Ultrix, we don't need it and it is really slow (because shell_escape
+# doesn't use vfork).
+if ![istarget "*-*-ultrix*"] then {
+ gdb_test "shell stty intr '^C'" ""
+}
+
+proc all_threads_running {} {
+ global gdb_prompt
+ global srcfile
+
+ # Reset all the counters to zero.
+ gdb_test "set var common_routine::hits=0" ""
+ gdb_test "set var common_routine::from_thread1=0" ""
+ gdb_test "set var common_routine::from_thread2=0" ""
+ gdb_test "set var common_routine::from_main=0" ""
+ gdb_test "set var common_routine::full_coverage=0" ""
+
+ # Disable all breakpoints.
+ gdb_test "disable" ""
+
+ # Set up a breakpoint that will cause us to stop when we have
+ # been called 15 times. This should be plenty of time to allow
+ # every thread to run at least once, since each thread sleeps for
+ # one second between calls to common_routine.
+ gdb_test "tbreak common_routine if hits == 15" ""
+
+ # Start all the threads running again and wait for the inferior
+ # to stop. Since no other breakpoints are set at this time
+ # we should stop only when we have been previously called 15 times.
+
+ send_gdb "continue\n"
+ gdb_expect {
+ -re "Continuing.*common_routine.*at.*$srcfile.*$gdb_prompt $" {}
+ default {
+ fail "continue until common routine run 15 times"
+ return 0
+ }
+ timeout {
+ fail "continue until common routine run 15 times (timeout)"
+ return 0
+ }
+ }
+
+ # Check that we stopped when we actually expected to stop, by
+ # verifying that there have been 15 previous hits.
+
+ send_gdb "p common_routine::hits\n"
+ gdb_expect {
+ -re ".*= 15\r\n$gdb_prompt $" {}
+ default {
+ fail "stopped before calling common_routine 15 times"
+ return 0
+ }
+ -re ".*$gdb_prompt $" {
+ fail "stopped before calling common_routine 15 times"
+ return 0
+ }
+ timeout {
+ fail "stopped before calling common_routine 15 times (timeout)"
+ return 0
+ }
+ }
+
+ # Also check that all of the threads have run, which will only be true
+ # if the full_coverage variable is set.
+
+ send_gdb "p common_routine::full_coverage\n"
+ gdb_expect {
+ -re ".*= 1\r\n$gdb_prompt $" {}
+ default {
+ fail "some threads didn't run"
+ return 0
+ }
+ timeout {
+ fail "some threads didn't run (timeout)"
+ return 0
+ }
+ }
+
+ # Looks fine, return success.
+ return 1
+}
+
+proc test_startup {} {
+ global srcdir srcfile gdb_prompt expect_out
+ global horiz
+ global main_id thread1_id thread2_id
+
+ # We should be able to do an info threads before starting any others.
+ send_gdb "info threads\n"
+ gdb_expect {
+ -re ".*Thread.*LWP.*main.*$gdb_prompt $" {
+ pass "info threads"
+ }
+ -re "\r\n$gdb_prompt $" {
+ pass "info threads"
+ setup_xfail "*-*-*"
+ fail "gdb does not support pthreads for this machine"
+ return 0
+ }
+ }
+
+ # Extract the thread id number of main thread from "info threads" output.
+ send_gdb "info threads\n"
+ gdb_expect -re "(\[0-9\]+)(${horiz}Thread${horiz}main.*)($gdb_prompt $)"
+ set main_id $expect_out(1,string)
+
+ # Check that we can continue and create the first thread.
+ gdb_test "break thread1" "Breakpoint .* file .*$srcdir.*"
+ gdb_test "continue" \
+ "Continuing.*Breakpoint .*, thread1 \\(arg=0xfeedface\\).*at.*$srcfile.*" \
+ "Continue to creation of first thread"
+ gdb_test "disable" ""
+
+ # Extract the thread id number of thread 1 from "info threads" output.
+ send_gdb "info threads\n"
+ gdb_expect -re "(\[0-9\]+)(${horiz}Thread${horiz}thread1.*)($gdb_prompt $)"
+ set thread1_id $expect_out(1,string)
+
+ # Check that we can continue and create the second thread,
+ # ignoring the first thread for the moment.
+ gdb_test "break thread2" "Breakpoint .* file .*$srcdir.*"
+ gdb_test "continue" \
+ "Continuing.*Breakpoint .*, thread2 \\(arg=0xdeadbeef\\).*at.*$srcfile.*" \
+ "Continue to creation of second thread"
+
+ # Extract the thread id number of thread 2 from "info threads" output.
+ send_gdb "info threads\n"
+ gdb_expect -re "(\[0-9\]+)(${horiz}Thread${horiz}thread2.*)($gdb_prompt $)"
+ set thread2_id $expect_out(1,string)
+
+ return 1
+}
+
+proc check_control_c {} {
+ global gdb_prompt
+
+ # Verify that all threads are running.
+ if [all_threads_running] then {
+ pass "All threads running after startup"
+ }
+
+ # Send a continue followed by ^C to the process to stop it.
+ send_gdb "continue\n"
+ set description "Stopped with a ^C"
+ after 1000 [send_gdb "\003"]
+ gdb_expect {
+ -re "Program received signal SIGINT.*$gdb_prompt $" {
+ pass $description
+ }
+ -re "Quit.*$gdb_prompt $" {
+ pass $description
+ }
+ timeout {
+ fail "$description (timeout)"
+ }
+ }
+ gdb_test "bt" ""
+
+ # Verify that all threads can be run again after a ^C stop.
+ if [all_threads_running] then {
+ pass "All threads running after continuing from ^C stop"
+ }
+}
+
+proc check_backtraces {} {
+ global gdb_prompt main_id thread1_id thread2_id
+
+ # Check that the "thread apply N backtrace" command works
+
+ gdb_test "thread apply $main_id backtrace" \
+ ".* in main \\(argc=.*, argv=.*\\).*" \
+ "check backtrace from main thread"
+ gdb_test "thread apply $thread1_id backtrace" \
+ ".* in thread1 \\(arg=0xfeedface\\).*" \
+ "check backtrace from thread 1"
+ gdb_test "thread apply $thread2_id backtrace" \
+ ".* in thread2 \\(arg=0xdeadbeef\\).*" \
+ "check backtrace from thread 2"
+
+ # Check that we can apply the backtrace command to all
+ # three threads with a single gdb command
+
+ gdb_test "thread apply $main_id $thread1_id $thread2_id bt" \
+ ".* in main .* in thread1 .* in thread2.*" \
+ "apply backtrace command to all three threads"
+
+ # Check that we can do thread specific backtraces
+ # This also tests that we can do thread specific breakpoints.
+
+ gdb_test "break common_routine thread $thread2_id" \
+ "Breakpoint .* at 0x.* file .* line .*" \
+ "set break at common_routine in thread 2"
+
+ send_gdb "continue\n"
+ gdb_expect {
+ -re "Breakpoint .* common_routine \\(arg=2\\).*" {
+ send_gdb "backtrace\n"
+ gdb_expect {
+ -re "#0.*common_routine \\(arg=2\\).*#1.*thread2.*" {
+ pass "backtrace from thread 2 bkpt in common_routine"
+ }
+ default {
+ fail "backtrace from thread 2 bkpt in common_routine"
+ }
+ timeout {
+ fail "backtrace from thread 2 bkpt in common_routine (timeout)"
+ }
+ }
+ }
+ -re "Breakpoint .* common_routine \\(arg=0\\).*" {
+ fail "stopped in main thread at breakpoint for thread 2"
+ }
+ -re "Breakpoint .* common_routine \\(arg=1\\).*" {
+ fail "stopped in main thread at breakpoint for thread 1"
+ }
+ -re ".*$gdb_prompt" {
+ fail "continue to bkpt at common_routine in thread 2"
+ }
+ default {
+ fail "continue to bkpt at common_routine in thread 2"
+ }
+ timeout {
+ fail "continue to bkpt at common_routine in thread 2 (timeout)"
+ }
+ }
+}
+
+setup_xfail "alpha-*-osf*"
+if [runto_main] then {
+ clear_xfail "alpha-*-osf*"
+ if [test_startup] then {
+ check_control_c
+ check_backtraces
+ }
+}
+clear_xfail "alpha-*-osf*"
diff --git a/gdb/testsuite/gdb.threads/step.c b/gdb/testsuite/gdb.threads/step.c
new file mode 100644
index 00000000000..1b18a4b07ad
--- /dev/null
+++ b/gdb/testsuite/gdb.threads/step.c
@@ -0,0 +1,221 @@
+/* step.c for step.exp */
+#include <ipc.h>
+#include <pthread.h>
+#include <st.h>
+#include <signal.h>
+#include <stdio.h>
+
+void alarm_handler ();
+void alarm_handler1 ();
+void alarm_handler2 ();
+void thread1 ();
+void thread2 ();
+
+#define TIME_LIMIT 30
+
+
+int count1 = 0;
+int count2 = 0;
+
+pthread_t tid1, tid2;
+pthread_attr_t attr1, attr2;
+
+pthread_mutex_t mut;
+pthread_mutexattr_t mut_attr;
+
+pthread_condattr_t cv_attr_a, cv_attr_b;
+pthread_cond_t cv_a, cv_b;
+
+struct cv_struct
+ {
+ char a;
+ char b;
+ }
+test_struct;
+
+main ()
+{
+ /*init la struct */
+ test_struct.a = 0;
+ test_struct.b = 1;
+
+ /* create le mutex */
+ if (pthread_mutexattr_create (&mut_attr) == -1)
+ {
+ perror ("mutexattr_create");
+ exit (1);
+ }
+
+
+ if (pthread_mutex_init (&mut, mut_attr) == -1)
+ {
+ perror ("mutex_init");
+ exit (1);
+ }
+
+ /* create 2 cv */
+ if (pthread_condattr_create (&cv_attr_a) == -1)
+ {
+ perror ("condattr_create(1)");
+ exit (1);
+ }
+
+ if (pthread_cond_init (&cv_a, cv_attr_a) == -1)
+ {
+ perror ("cond_init(1)");
+ exit (1);
+ }
+
+ if (pthread_condattr_create (&cv_attr_b) == -1)
+ {
+ perror ("condattr_create(2)");
+ exit (1);
+ }
+
+ if (pthread_cond_init (&cv_b, cv_attr_b) == -1)
+ {
+ perror ("cond_init(2)");
+ exit (1);
+ }
+
+ /* create 2 threads of execution */
+ if (pthread_attr_create (&attr1) == -1)
+ {
+ perror ("attr_create(1)");
+ exit (1);
+ }
+
+ if (pthread_create (&tid1, attr1, thread1, &count1) == -1)
+ {
+ perror ("pthread_create(1)");
+ exit (1);
+ }
+
+ if (pthread_attr_create (&attr2) == -1)
+ {
+ perror ("attr_create(2)");
+ exit (1);
+ }
+
+ if (pthread_create (&tid2, attr2, thread2, &count2) == -1)
+ {
+ perror ("pthread_create(2)");
+ exit (1);
+ }
+
+ /* set alarm to print out data and exit */
+ signal (SIGALRM, alarm_handler);
+ alarm (TIME_LIMIT);
+
+ for (;;)
+ pause ();
+}
+
+void
+thread1 (count)
+ int *count;
+{
+ tid_t tid;
+
+ tid = getstid ();
+ printf ("Thread1 tid 0x%x (%d) \n", tid, tid);
+ printf ("Thread1 @tid=0x%x \n", &tid);
+ signal (SIGALRM, alarm_handler1);
+
+ for (;;)
+ {
+ if (pthread_mutex_lock (&mut) == -1)
+ {
+ perror ("pthread_mutex_lock(1)");
+ pthread_exit ((void *) 0);
+ }
+
+ while (test_struct.a == 0)
+ {
+ if (pthread_cond_wait (&cv_a, &mut) == -1)
+ {
+ perror ("pthread_cond_wait(1)");
+ pthread_exit ((void *) -1);
+ }
+ }
+
+ (*count)++;
+ printf ("*******thread1 count %d\n", *count);
+
+ test_struct.a = 0;
+
+ test_struct.b = 1;
+ pthread_cond_signal (&cv_b);
+
+ if (pthread_mutex_unlock (&mut) == -1)
+ {
+ perror ("pthread_mutex_unlock(1)");
+ pthread_exit ((void *) -1);
+ }
+ }
+}
+
+void
+thread2 (count)
+ int *count;
+{
+ tid_t tid;
+
+ tid = getstid ();
+ printf ("Thread2 tid 0x%x (%d) \n", tid, tid);
+ printf ("Thread1 @tid=0x%x \n", &tid);
+ signal (SIGALRM, alarm_handler2);
+
+ for (;;)
+ {
+ if (pthread_mutex_lock (&mut) == -1)
+ {
+ perror ("pthread_mutex_lock(2)");
+ pthread_exit ((void *) 0);
+ }
+
+ while (test_struct.b == 0)
+ {
+ if (pthread_cond_wait (&cv_b, &mut) == -1)
+ {
+ perror ("pthread_cond_wait(2)");
+ pthread_exit ((void *) -1);
+ }
+ }
+
+ (*count)++;
+ printf ("*******thread2 count %d\n", *count);
+
+ test_struct.b = 0;
+
+ test_struct.a = 1;
+ pthread_cond_signal (&cv_a);
+
+ if (pthread_mutex_unlock (&mut) == -1)
+ {
+ perror ("pthread_mutex_unlock(2)");
+ pthread_exit ((void *) -1);
+ }
+ }
+}
+
+
+void
+alarm_handler ()
+{
+ printf ("\tcount1 (%d) \n\tcount2 (%d)\n", count1, count2);
+ exit (0);
+}
+
+void
+alarm_handler1 ()
+{
+ printf ("ALARM thread 1\n");
+}
+
+void
+alarm_handler2 ()
+{
+ printf ("ALARM thread 2\n");
+ pthread_exit ((void *) 0);
+}
diff --git a/gdb/testsuite/gdb.threads/step.exp b/gdb/testsuite/gdb.threads/step.exp
new file mode 100644
index 00000000000..aa5639347b7
--- /dev/null
+++ b/gdb/testsuite/gdb.threads/step.exp
@@ -0,0 +1,200 @@
+# step.exp -- Expect script to test gdb with step.c
+# Copyright (C) 1992, 1997 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file was written by Hiro Sugawara. (hiro@lynx.com)
+#
+# This test really needs some major surgery to be acceptable, but
+# I'm just about burnt out on lynx work, so I'm not doing it now.
+#
+# * The test has an indeterminate number of pass/fails
+# for each run (it runs a small group of tests until
+# it's timer kicks off). This is very bad for nightly
+# automated regression testing.
+#
+# * It tries to "step" from withint he prologue of a
+# function. This isn't support in gdb (it's going
+# to act like a continue).
+#
+# * This test rarely check that it stopped in sensible
+# places. (see previous bullet -- this test doesn't
+# catch the fact it continued rather than stepped)
+
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+set program_exited 0
+
+proc set_bp { where } {
+ global gdb_prompt
+
+ send_gdb "break $where\n"
+ # The first regexp is what we get with -g, the second without -g.
+ gdb_expect {
+ -re "Break.* at .*: file .*, line \[0-9\]*.*$gdb_prompt $" {}
+ -re "Breakpoint \[0-9\]* at 0x\[0-9a-f\]*.*$gdb_prompt $" {}
+ -re "$gdb_prompt $" { fail "setting breakpoint at $where" ; return 0 }
+ timeout { fail "setting breakpoint at $where (timeout)" ; return 0 }
+ }
+ pass "set_bp"
+}
+
+proc step_it { cmd } {
+ global gdb_prompt
+ global program_exited
+
+ send_gdb "$cmd\n"
+ gdb_expect {
+ -re "0x\[0-9A-Fa-f\]* *in.*\r\n$gdb_prompt $" { pass "step_it"; return 0 }
+ -re "0x\[0-9A-Fa-f\]* *\[0-9\]*.*\r\n$gdb_prompt $" { pass "step_it"; return 1 }
+ -re "Program exited .*\n$gdb_prompt $" {
+ set program_exited 1
+ return -1
+ }
+ -re "$gdb_prompt $" { fail "single-stepping ($cmd).\n" ; return -1 }
+ timeout { fail "single-stepping ($cmd) timout.\n" ; return -1 }
+ }
+}
+
+proc step_inst {} {
+ step_it "stepi"
+}
+
+proc step_source {} {
+ step_it "step"
+}
+
+proc continue_all {} {
+ global gdb_prompt
+
+ send_gdb "continue\n"
+ gdb_expect {
+ -re "Breakpoint \[0-9\]*, thread\[0-9\]* .*$gdb_prompt $" {
+ pass "continue_all"
+ return 0
+ }
+ -re "Program exited .*\n$gdb_prompt $" {
+ set program_exited 1
+ return 1;
+ }
+ -re "$gdb_prompt $" { fail "continue" ; return -1 }
+ timeout { fail "continue (timeout)" ; return -1 }
+ }
+}
+
+proc check_threads { num_threads } {
+ global gdb_prompt
+
+ set curr_thread 0
+ send_gdb "info threads\n"
+ while { $num_threads > 0 } {
+ gdb_expect {
+ -re "\\* *\[0-9\]* process \[0-9\]* thread \[0-9\]* .*\n" {
+ incr curr_thread
+ set num_threads [expr $num_threads - 1]
+ }
+ -re " *\[0-9\]* process \[0-9\]* thread \[0-9\]* .*\n" {
+ set num_threads [expr $num_threads - 1]
+ }
+ -re "$gdb_prompt $" {
+ if { $num_threads < 0 } {
+ fail "check_threads (too many)" ; return -1
+ }
+ break
+ }
+ timeout { fail "check_threads (timeout)" ; return -1 }
+ }
+ }
+
+ if { $curr_thread == 0 } {
+ fail "check_threads (no current thread)\n"
+ return -1
+ }
+ if { $curr_thread > 1 } {
+ fail "check_threads (more than one current thread)\n"
+ return -1
+ }
+ return 0
+}
+
+proc test_cond_wait {} {
+ global program_exited
+
+ set_bp 135
+ runto 179
+ while { 1 } {
+ set stepi_counter 0
+ while { [step_inst] } {
+ if { $program_exited } { break }
+ incr stepi_counter
+ if { $stepi_counter > 30 } {
+ fail "too many stepi's per line\n"
+ return -1
+ }
+ }
+ if { $program_exited } { break }
+ step_source
+ if { $program_exited } { break }
+ continue_all
+ if { $program_exited } { break }
+ check_threads 3
+ }
+}
+
+proc do_tests {} {
+ global prms_id
+ global bug_id
+ global subdir
+ global objdir
+ global srcdir
+ global binfile
+ global gdb_prompt
+
+ set prms_id 0
+ set bug_id 0
+
+ # Start with a fresh gdb.
+
+ gdb_exit
+ gdb_start
+ gdb_reinitialize_dir $srcdir/$subdir
+ gdb_load $objdir/$subdir/$binfile
+
+ send_gdb "set width 0\n"
+ gdb_expect -re "$gdb_prompt $"
+
+ test_cond_wait
+}
+
+# Check to see if we have an executable to test. If not, then either we
+# haven't tried to compile one, or the compilation failed for some reason.
+# In either case, just notify the user and skip the tests in this file.
+
+set binfile "step"
+set srcfile "step.c"
+
+if ![file exists $objdir/$subdir/$binfile] then {
+ if $all_flag then {
+ warning "$binfile does not exist; tests suppressed."
+ }
+} else {
+ do_tests
+}
diff --git a/gdb/testsuite/gdb.threads/step2.exp b/gdb/testsuite/gdb.threads/step2.exp
new file mode 100644
index 00000000000..5442e6aef6f
--- /dev/null
+++ b/gdb/testsuite/gdb.threads/step2.exp
@@ -0,0 +1,150 @@
+# step2.exp -- Expect script to test gdb step.c
+# Copyright (C) 1992, 1997 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file was written by Jeff Law. (law@cygnus.com)
+#
+
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+set program_exited 0
+
+# A simple and crude test to see that we can step two threads independently
+proc test_multi_threaded_stepping {} {
+ global gdb_prompt
+ global hex
+ global srcfile
+ global decimal
+
+ # Set breakpoints in code that we know is executed in only
+ # thread of control.
+ gdb_test "break thread1" \
+ "Break.* at $hex: file .*$srcfile, line $decimal\\."
+ gdb_test "break thread2" \
+ "Break.* at $hex: file .*$srcfile, line $decimal\\."
+
+ # the order in which things happen is indeterminate. So we basically
+ # look for a set of events and note that each one happens and that
+ # all of the required events have happened when we're done.
+ #
+ # Right now we only verify that both threads start and that they
+ # both call pthread_cond_wait twice.
+ set thread1started 0
+ set thread1condwait 0
+ set thread2started 0
+ set thread2condwait 0
+
+ send_gdb "run\n"
+ gdb_expect {
+ -re "The program .* has been started already.*y or n. $" {
+ send_gdb "y\n"
+ exp_continue
+ }
+ -re ".*Breakpoint \[0-9\]+,.*thread1.* at .*$srcfile:.*\[\t \].*$gdb_prompt $" {
+ if { $thread1started != 0 } then {
+ fail "thread1 started"
+ return
+ } else {
+ set thread1started 1
+ pass "thread1 started"
+ }
+ send_gdb "step\n"
+ exp_continue
+ }
+ -re ".*Breakpoint \[0-9\]+,.*thread2.* at .*$srcfile:.*\[\t \].*$gdb_prompt $" {
+ if { $thread2started != 0 } then {
+ fail "thread2 started"
+ return
+ } else {
+ set thread2started 1
+ pass "thread2 started"
+ }
+ send_gdb "step\n"
+ exp_continue
+ }
+ -re ".*pthread_cond_wait.*cv_a.*$gdb_prompt" {
+ if { $thread1started == 0 } then {
+ fail "thread1 condwait"
+ return
+ }
+ if { $thread1condwait < 2 } then {
+ pass "thread1 condwait"
+ incr thread1condwait
+ }
+ if { $thread2condwait == 2 } then {
+ pass "multi threaded stepping"
+ return
+ }
+ send_gdb "step\n"
+ exp_continue
+ }
+
+ -re ".*pthread_cond_wait.*cv_b.*$gdb_prompt" {
+ if { $thread2started == 0 } then {
+ fail "thread2 condwait"
+ return
+ }
+ if { $thread2condwait < 2 } then {
+ pass "thread2 condwait"
+ incr thread2condwait
+ }
+ if { $thread1condwait == 2 } then {
+ pass "multi threaded stepping"
+ return
+ }
+ send_gdb "step\n"
+ exp_continue
+ }
+
+ -re "$gdb_prompt" {
+ send_gdb "step\n"
+ exp_continue
+ }
+ default { fail "multi threaded stepping" }
+ }
+}
+
+# Check to see if we have an executable to test. If not, then either we
+# haven't tried to compile one, or the compilation failed for some reason.
+# In either case, just notify the user and skip the tests in this file.
+
+set binfile "step"
+set srcfile "step.c"
+
+if ![file exists $objdir/$subdir/$binfile] then {
+ if $all_flag then {
+ warning "$binfile does not exist; tests suppressed."
+ }
+ return
+}
+
+set prms_id 0
+set bug_id 0
+
+# Start with a fresh gdb.
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load $objdir/$subdir/$binfile
+
+test_multi_threaded_stepping
diff --git a/gdb/testsuite/gdb.trace/Makefile.in b/gdb/testsuite/gdb.trace/Makefile.in
new file mode 100644
index 00000000000..601c9e17ff9
--- /dev/null
+++ b/gdb/testsuite/gdb.trace/Makefile.in
@@ -0,0 +1,21 @@
+#### host, target, and site specific Makefile frags come in here.
+
+VPATH = @srcdir@
+srcdir = @srcdir@
+
+.PHONY: all clean mostlyclean distclean realclean
+
+all:
+ @echo "Nothing to be done for all..."
+
+clean mostlyclean:
+ -rm -f actions circ collection limits
+ -rm -f *.o *.diff *~ *.bad core sh3 hppa mn10200 mn10300
+
+distclean maintainer-clean realclean: clean
+ -rm -f Makefile config.status config.log
+
+Makefile: $(srcdir)/Makefile.in $(srcdir)/configure.in
+ $(SHELL) ./config.status --recheck
+
+
diff --git a/gdb/testsuite/gdb.trace/actions.c b/gdb/testsuite/gdb.trace/actions.c
new file mode 100644
index 00000000000..e8df6148461
--- /dev/null
+++ b/gdb/testsuite/gdb.trace/actions.c
@@ -0,0 +1,134 @@
+/*
+ * Test program for trace action commands
+ */
+
+static char gdb_char_test;
+static short gdb_short_test;
+static long gdb_long_test;
+static char gdb_arr_test[25];
+static struct GDB_STRUCT_TEST
+{
+ char c;
+ short s;
+ long l;
+ int bfield : 11; /* collect bitfield */
+ char arr[25];
+ struct GDB_STRUCT_TEST *next;
+} gdb_struct1_test, gdb_struct2_test, *gdb_structp_test, **gdb_structpp_test;
+
+static union GDB_UNION_TEST
+{
+ char c;
+ short s;
+ long l;
+ int bfield : 11; /* collect bitfield */
+ char arr[4];
+ union GDB_UNION_TEST *next;
+} gdb_union1_test;
+
+void gdb_recursion_test (int, int, int, int, int, int, int);
+
+void gdb_recursion_test (int depth,
+ int q1,
+ int q2,
+ int q3,
+ int q4,
+ int q5,
+ int q6)
+{ /* gdb_recursion_test line 0 */
+ int q = q1; /* gdbtestline 1 */
+
+ q1 = q2; /* gdbtestline 2 */
+ q2 = q3; /* gdbtestline 3 */
+ q3 = q4; /* gdbtestline 4 */
+ q4 = q5; /* gdbtestline 5 */
+ q5 = q6; /* gdbtestline 6 */
+ q6 = q; /* gdbtestline 7 */
+ if (depth--) /* gdbtestline 8 */
+ gdb_recursion_test (depth, q1, q2, q3, q4, q5, q6); /* gdbtestline 9 */
+}
+
+
+unsigned long gdb_c_test( unsigned long *parm )
+
+{
+ char *p = "gdb_c_test";
+ char *rediculously_long_variable_name_with_equally_long_string_assignment;
+ register long local_reg = 7;
+ static unsigned long local_static, local_static_sizeof;
+ long local_long;
+ unsigned long *stack_ptr;
+ unsigned long end_of_stack;
+
+ rediculously_long_variable_name_with_equally_long_string_assignment =
+ "rediculously long variable name with equally long string assignment";
+ local_static = 9;
+ local_static_sizeof = sizeof (struct GDB_STRUCT_TEST);
+ local_long = local_reg + 1;
+ stack_ptr = (unsigned long *) &local_long;
+ end_of_stack =
+ (unsigned long) &stack_ptr + sizeof(stack_ptr) + sizeof(end_of_stack) - 1;
+
+ gdb_char_test = gdb_struct1_test.c = (char) ((long) parm[1] & 0xff);
+ gdb_short_test = gdb_struct1_test.s = (short) ((long) parm[2] & 0xffff);
+ gdb_long_test = gdb_struct1_test.l = (long) ((long) parm[3] & 0xffffffff);
+ gdb_union1_test.l = (long) parm[4];
+ gdb_arr_test[0] = gdb_struct1_test.arr[0] = (char) ((long) parm[1] & 0xff);
+ gdb_arr_test[1] = gdb_struct1_test.arr[1] = (char) ((long) parm[2] & 0xff);
+ gdb_arr_test[2] = gdb_struct1_test.arr[2] = (char) ((long) parm[3] & 0xff);
+ gdb_arr_test[3] = gdb_struct1_test.arr[3] = (char) ((long) parm[4] & 0xff);
+ gdb_arr_test[4] = gdb_struct1_test.arr[4] = (char) ((long) parm[5] & 0xff);
+ gdb_arr_test[5] = gdb_struct1_test.arr[5] = (char) ((long) parm[6] & 0xff);
+ gdb_struct1_test.bfield = 144;
+ gdb_struct1_test.next = &gdb_struct2_test;
+ gdb_structp_test = &gdb_struct1_test;
+ gdb_structpp_test = &gdb_structp_test;
+
+ gdb_recursion_test (3, (long) parm[1], (long) parm[2], (long) parm[3],
+ (long) parm[4], (long) parm[5], (long) parm[6]);
+
+ gdb_char_test = gdb_short_test = gdb_long_test = 0;
+ gdb_structp_test = (void *) 0;
+ gdb_structpp_test = (void *) 0;
+ memset ((char *) &gdb_struct1_test, 0, sizeof (gdb_struct1_test));
+ memset ((char *) &gdb_struct2_test, 0, sizeof (gdb_struct2_test));
+ local_static_sizeof = 0;
+ local_static = 0;
+ return ( (unsigned long) 0 );
+}
+
+static void gdb_asm_test (void)
+{
+}
+
+static void begin () /* called before anything else */
+{
+}
+
+static void end () /* called after everything else */
+{
+}
+
+int
+main (argc, argv, envp)
+ int argc;
+ char *argv[], **envp;
+{
+ int i;
+ unsigned long myparms[10];
+
+#ifdef usestubs
+ set_debug_traps ();
+ breakpoint ();
+#endif
+
+ begin ();
+ for (i = 0; i < sizeof (myparms) / sizeof (myparms[0]); i++)
+ myparms[i] = i;
+
+ gdb_c_test (&myparms[0]);
+
+ end ();
+ return 0;
+}
+
diff --git a/gdb/testsuite/gdb.trace/actions.exp b/gdb/testsuite/gdb.trace/actions.exp
new file mode 100644
index 00000000000..f9ac7a431dc
--- /dev/null
+++ b/gdb/testsuite/gdb.trace/actions.exp
@@ -0,0 +1,207 @@
+# Copyright (C) 1998 Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file was written by Michael Snyder (msnyder@cygnus.com)
+
+load_lib "trace-support.exp";
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+set prms_id 0
+set bug_id 0
+
+gdb_exit
+gdb_start
+
+if [istarget "m68k-*-elf"] then {
+ set binfile [board_info target d490_binfile];
+ set srcfile gdb_c_test.c
+} else {
+ set testfile "actions"
+ set srcfile ${testfile}.c
+ set binfile $objdir/$subdir/$testfile
+ if { [gdb_compile "$srcdir/$subdir/$srcfile" $binfile \
+ executable {debug additional_flags=-w}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+ }
+}
+gdb_reinitialize_dir $srcdir/$subdir
+
+# If testing on a remote host, download the source file.
+# remote_download host $srcdir/$subdir/$srcfile
+
+gdb_file_cmd $binfile
+
+# define relative source line numbers:
+# all subsequent line numbers are relative to this first one (baseline)
+
+set baseline [gdb_find_recursion_test_baseline $srcfile];
+if { $baseline == -1 } then {
+ fail "Could not find gdb_recursion_test function"
+ return;
+}
+
+set testline1 [expr $baseline + 7]
+
+#
+# test actions command
+#
+
+gdb_delete_tracepoints
+set trcpt1 [gdb_gettpnum gdb_c_test];
+set trcpt2 [gdb_gettpnum gdb_asm_test];
+set trcpt3 [gdb_gettpnum $testline1];
+if { $trcpt1 <= 0 || $trcpt2 <= 0 || $trcpt3 <= 0 } then {
+ fail "setting tracepoints"
+ return;
+}
+
+# 5.1 actions of specified tracepoint
+
+send_gdb "info tracepoints\n"
+gdb_expect {
+ -re "Actions for tracepoint \[0-9\]+:.*$gdb_prompt $" {
+ fail "5.1a: testsuite failure (tracepoint already has action)!"
+ }
+ -re "No tracepoints.*$gdb_prompt $" {
+ fail "5.1a: set three tracepoints, no actions (No tracepoints!)"
+ }
+ -re "$gdb_prompt $" {
+ pass "5.1a: set three tracepoints, no actions"
+ }
+}
+
+gdb_trace_setactions "5.1b: set actions for first tracepoint" \
+ "$trcpt1" \
+ "collect gdb_char_test" "^$"
+
+send_gdb "info tracepoints\n"
+gdb_expect {
+ -re "Actions for.* $trcpt1:.*collect gdb_char_test.*$gdb_prompt $" {
+ pass "5.1c: verify actions set for first tracepoint"
+ }
+ -re "$gdb_prompt $" {
+ fail "5.1c: verify actions set for first tracepoint"
+ }
+}
+
+gdb_trace_setactions "5.1d: set actions for second tracepoint" \
+ "$trcpt2" \
+ "collect gdb_short_test" "^$"
+
+send_gdb "info tracepoints\n"
+gdb_expect {
+ -re "Actions for.* $trcpt2:.*collect gdb_short_test.*$gdb_prompt $" {
+ pass "5.1e: verify actions set for second tracepoint"
+ }
+ -re "$gdb_prompt $" {
+ fail "5.1e: verify actions set for second tracepoint"
+ }
+}
+
+gdb_trace_setactions "5.2a: set actions for last (default) tracepoint" \
+ "" \
+ "collect gdb_long_test" "^$"
+
+send_gdb "info tracepoints\n"
+gdb_expect {
+ -re "Actions for.* $trcpt3:.*collect gdb_long_test.*$gdb_prompt $" {
+ pass "5.2b: verify actions set for last (default) tracepoint"
+ }
+ -re "$gdb_prompt $" {
+ fail "5.2b: verify actions set for last (default) tracepoint"
+ }
+}
+
+# 5.3 replace actions set earlier
+
+gdb_trace_setactions "5.3a: reset actions for first tracepoint" \
+ "$trcpt1" \
+ "collect gdb_struct1_test" "^$"
+
+send_gdb "info tracepoints\n"
+gdb_expect {
+ -re "Actions for.* $trcpt1:.*collect gdb_struct1_test.*$gdb_prompt $" {
+ pass "5.3b: verify actions set for first tracepoint"
+ }
+ -re "$gdb_prompt $" {
+ fail "5.3b: verify actions set for first tracepoint"
+ }
+}
+
+#
+# test end command (all by itself)
+#
+
+# 5.4 end outside of context
+
+gdb_test "end" "This command cannot be used at the top level." \
+ "5.4: 'end' command out of context"
+
+# 5.5 empty actions (just an end with no other actions)
+
+gdb_trace_setactions "5.5a: set empty actions for first tracepoint" \
+ "$trcpt1"
+
+send_gdb "info tracepoints\n"
+gdb_expect {
+ -re "No tracepoints.*$gdb_prompt $" {
+ fail "5.5c: verify NO actions for first tracepoint"
+ }
+ -re "Actions for.* $trcpt1:.*$gdb_prompt $" {
+ fail "5.5c: verify NO actions for first tracepoint"
+ }
+ -re "$gdb_prompt $" {
+ pass "5.5c: verify NO actions for first tracepoint"
+ }
+}
+
+# 5.6 actions for invalid tracepoint number
+
+gdb_test "actions [expr $trcpt2 + $trcpt3]" \
+ "No tracepoint number [expr $trcpt2 + $trcpt3]." \
+ "5.6: actions for invalid tracepoint number"
+
+# 5.7 invalid action (other than 'collect', 'while-stepping' or 'end')
+# "warning: .print gdb_c_test. is not a supported trace.*> $" \
+
+gdb_trace_setactions "5.7: invalid action" \
+ "$trcpt1" \
+ "print gdb_c_test" \
+ "warning: .print gdb_c_test. is not a supported trace"
+
+# 5.8 help actions (collect, while-stepping, end)
+
+gdb_test "help actions" \
+ "Specify the actions to be taken at a tracepoint.*" \
+ "5.8a: help actions"
+
+gdb_test "help collect" \
+ "Specify one or more data items to be collected at a tracepoint.*" \
+ "5.8b: help collect"
+
+gdb_test "help while-stepping" \
+ "Specify single-stepping behavior at a tracepoint.*" \
+ "5.8c: help while-stepping"
+
+gdb_test "help end" "Ends a list of commands or actions.*" \
+ "5.8d: help end"
+
diff --git a/gdb/testsuite/gdb.trace/backtrace.exp b/gdb/testsuite/gdb.trace/backtrace.exp
new file mode 100644
index 00000000000..4d44ed45776
--- /dev/null
+++ b/gdb/testsuite/gdb.trace/backtrace.exp
@@ -0,0 +1,376 @@
+# Copyright (C) 1998 Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file was written by Michael Snyder (msnyder@cygnus.com)
+
+load_lib "trace-support.exp";
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+set prms_id 0
+set bug_id 0
+
+gdb_exit
+gdb_start
+
+if [istarget "m68k-*-elf"] then {
+ load_lib "emc-support.exp";
+ set srcfile gdb_c_test.c
+ set binfile [board_info target d490_binfile];
+ gdb_test "set remotetimeout 6" "" ""
+ set timeout 500
+ gdb_target_monitor "$binfile"
+ # Give a TSTOP and ignore errors, to make sure any previous trace is off
+ gdb_test "tstop" "" ""
+ gdb_test "tfind none" "" ""
+ send_gdb "compare-sections CS\n"
+ gdb_expect {
+ -re "MIS-MATCHED.*$gdb_prompt $" {
+ gdb_suppress_entire_file "Symbol file does not match target!
+ all tests in this module will fail.";
+ }
+ -re ".*$gdb_prompt $" { }
+ }
+} else {
+ set testfile "actions"
+ set srcfile ${testfile}.c
+ set binfile $objdir/$subdir/$testfile
+ if { [gdb_compile "$srcdir/$subdir/$srcfile" $binfile \
+ executable {debug additional_flags=-w}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+ }
+ gdb_load $binfile
+ gdb_test "tstop" "" ""
+ gdb_test "tfind none" "" ""
+ runto_main
+}
+gdb_reinitialize_dir $srcdir/$subdir
+
+# We generously give ourselves one "pass" if we successfully
+# detect that this test cannot be run on this target!
+if { ![gdb_target_supports_trace] } then {
+ pass "Current target does not supporst trace"
+ return 1;
+
+}
+
+#
+# test backtraces in trace frames
+#
+
+set testline1 0
+set testline2 0
+set testline3 0
+set testline4 0
+set testline5 0
+set testline6 0
+
+set arg1 1
+set arg2 2
+set arg3 3
+set arg4 4
+set arg5 5
+set arg6 6
+
+set baseline [gdb_find_recursion_test_baseline $srcfile];
+if { $baseline == -1 } {
+ fail "Could not find gdb_recursion_test function"
+ return;
+}
+
+send_gdb "list $baseline, +12\n"
+gdb_expect {
+ -re "\[\r\n\](\[0-9\]+).*gdbtestline 1 " {
+ set testline1 $expect_out(1,string)
+ exp_continue
+ }
+ -re "\[\r\n\](\[0-9\]+).*gdbtestline 2 " {
+ set testline2 $expect_out(1,string)
+ exp_continue
+ }
+ -re "\[\r\n\](\[0-9\]+).*gdbtestline 3 " {
+ set testline3 $expect_out(1,string)
+ exp_continue
+ }
+ -re "\[\r\n\](\[0-9\]+).*gdbtestline 4 " {
+ set testline4 $expect_out(1,string)
+ exp_continue
+ }
+ -re "\[\r\n\](\[0-9\]+).*gdbtestline 5 " {
+ set testline5 $expect_out(1,string)
+ exp_continue
+ }
+ -re "\[\r\n\](\[0-9\]+).*gdbtestline 6 " {
+ set testline6 $expect_out(1,string)
+ exp_continue
+ }
+ -re ".*$gdb_prompt $" {
+ if { ($testline1 == 0) || ($testline2 == 0) || ($testline3 == 0) || ($testline4 == 0) || ($testline5 == 0) || ($testline6 == 0) } {
+ gdb_suppress_entire_file "failed to locate test source lines:
+all tests in this module will fail."
+ }
+ }
+ default {
+ gdb_suppress_entire_file "failed to locate test source lines (def):
+all tests in this module will fail."
+ }
+}
+
+#
+# Setup backtrace experiment. This will involve:
+# 1) a tracepoint where nothing is collected
+# 2) a tracepoint where only regs are collected
+# 3) a tracepoint where regs, locals and args are collected
+# 4) a tracepoint where regs plus some amount of stack are collected.
+#
+
+gdb_delete_tracepoints
+set tdp2 [gdb_gettpnum $testline2]
+set tdp3 [gdb_gettpnum $testline3]
+set tdp4 [gdb_gettpnum $testline4]
+set tdp5 [gdb_gettpnum $testline5]
+set tdp6 [gdb_gettpnum $testline6]
+if { $tdp2 <= 0 || $tdp3 <= 0 || \
+ $tdp4 <= 0 || $tdp5 <= 0 || $tdp6 <= 0 } then {
+ fail "setting tracepoints failed"
+ return;
+}
+
+#gdb_trace_setactions "setup TP to collect FP" \
+# "$tdp2" \
+# "collect \$fp" ""
+#
+
+gdb_trace_setactions "8.6: setup TP to collect regs" \
+ "$tdp3" \
+ "collect \$regs" "^$"
+
+gdb_trace_setactions "8.6: setup TP to collect regs, args, and locals" \
+ "$tdp4" \
+ "collect \$regs, \$args, \$locs" "^$"
+
+gdb_trace_setactions "8.6: setup TP to collect stack mem cast expr" \
+ "$tdp6" \
+ "collect \$fp, \(\*\(void \*\*\) \(\$sp\)\) @ 64" "^$"
+
+gdb_test "tstart" "" ""
+
+if [istarget "m68k-*-elf"] then {
+ gdb_emclaptop_command "85,$arg1,$arg2,$arg3,$arg4,$arg5,$arg6"
+ sleep 5
+} else {
+ gdb_test "break end" "" ""
+ gdb_test "continue" \
+ "Continuing.*Breakpoint $decimal, end.*" \
+ "run trace experiment"
+}
+
+gdb_test "tstop" "" ""
+
+proc gdb_backtrace_tdp_1 { msg } {
+ global gdb_prompt
+
+ # We are in a trace frame at which we didn't collect anything
+ # except $PC. Therefore we expect to be able to identify stack
+ # frame #0, but that's about all. In particular we do not expect
+ # to be able to display the function's arguments or locals, and we
+ # do not expect to be able to identify the caller of this function.
+
+ send_gdb "backtrace\n"
+ gdb_expect {
+ -re "#0\[\t \]+gdb_recursion_test.*depth=.*$gdb_prompt $" {
+ pass "$msg"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "$msg"
+ }
+ timeout { fail "$msg (timeout)" }
+ }
+}
+
+proc gdb_backtrace_tdp_2 { msg } {
+ global gdb_prompt
+
+ # We are in a trace frame at which we collected only the registers
+ # Therefore we expect to be able to identify stack frame #0, but
+ # we don't expect to be able to display its args unles they are
+ # passed in registers (which isn't the case for m68k), and we
+ # don't expect to be able to identify the caller's stack frame.
+
+ send_gdb "backtrace\n"
+ gdb_expect {
+ -re "#0\[\t \]+gdb_recursion_test.*depth=.*$gdb_prompt $" {
+ pass "$msg"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "$msg"
+ }
+ timeout { fail "$msg (timeout)" }
+ }
+}
+
+proc gdb_backtrace_tdp_3 { msg } {
+ global gdb_prompt
+
+ # We are in a trace frame at which we collected all registers, all
+ # arguments and all locals. This means that the display of
+ # stack frame #0 should be complete (including argument values).
+
+ send_gdb "backtrace\n"
+ gdb_expect {
+ -re "#0\[\t \]+gdb_recursion_test.*depth=\[0-9\]+.*q1=\[0-9\]+.*q2=\[0-9\]+.*q3=\[0-9\]+.*q4=\[0-9\]+.*q5=\[0-9\]+.*q6=\[0-9\]+.*$gdb_prompt $" {
+ pass "$msg"
+ }
+ -re "#0\[\t \]+gdb_recursion_test.*depth=Cannot access.*$gdb_prompt $" {
+ fail "$msg (failed to collect arguments)"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "$msg"
+ }
+ timeout { fail "$msg (timeout)" }
+ }
+}
+
+proc gdb_backtrace_tdp_4 { msg depth } {
+ global gdb_prompt
+
+ # We are in a trace frame at which we collected all registers,
+ # plus a sizeable hunk of stack memory. This should enable us to
+ # display at least several stack frames worth of backtrace. We'll
+ # assume that if we can't display at least "depth" levels (with
+ # args), it counts as an error.
+
+ send_gdb "backtrace\n"
+ gdb_expect {
+ -re "#$depth\[\t \].*gdb_recursion_test.*depth=\[0-9\]+.*q1=\[0-9\]+.*q2=\[0-9\]+.*q3=\[0-9\]+.*q4=\[0-9\]+.*q5=\[0-9\]+.*q6=\[0-9\]+.*$gdb_prompt $" {
+ pass "$msg"
+ }
+ -re "#$depth\[\t \].*gdb_recursion_test.*depth=.*$gdb_prompt $" {
+ fail "$msg (args missing from #$depth stack frame)"
+ }
+ -re "#\[0-9\]+\[\t \].*gdb_recursion_test.*depth=.*$gdb_prompt $" {
+ fail "$msg (fewer than $depth stack frames found)"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "$msg"
+ }
+ timeout { fail "$msg (timeout)" }
+ }
+}
+
+#
+# begin backtrace test
+#
+
+set timeout 60
+
+gdb_tfind_test "init: make sure not debugging any trace frame" "none" "-1"
+
+gdb_tfind_test "8.6: find start frame" "start" "0"
+gdb_test "printf \"TDP \%d:\\n\", \$tracepoint" \
+ "TDP $tdp2:" ""
+gdb_backtrace_tdp_1 "8.6: Backtrace, depth == 1, collect nothing"
+
+gdb_tfind_test "8.6: find frame 1" "1" "1"
+gdb_test "printf \"TDP \%d:\\n\", \$tracepoint" \
+ "TDP $tdp3:" ""
+gdb_backtrace_tdp_2 "8.6: Backtrace, depth == 1, collect regs"
+
+gdb_tfind_test "8.6: find frame 2" "2" "2"
+gdb_test "printf \"TDP \%d:\\n\", \$tracepoint" \
+ "TDP $tdp4:" ""
+gdb_backtrace_tdp_3 "8.6: Backtrace, depth == 1, collect args and locals"
+
+
+gdb_tfind_test "8.6: find frame 4" "4" "4"
+gdb_test "printf \"TDP \%d:\\n\", \$tracepoint" \
+ "TDP $tdp6:" ""
+gdb_backtrace_tdp_4 "8.6: Backtrace, depth == 1, collect stack mem expr" "0"
+
+gdb_tfind_test "8.6: find frame 5" "5" "5"
+gdb_test "printf \"TDP \%d:\\n\", \$tracepoint" \
+ "TDP $tdp2:" ""
+gdb_backtrace_tdp_1 "8.6: Backtrace, depth == 2, collect nothing"
+
+gdb_tfind_test "8.6: find frame 6" "6" "6"
+gdb_test "printf \"TDP \%d:\\n\", \$tracepoint" \
+ "TDP $tdp3:" ""
+gdb_backtrace_tdp_2 "8.6: Backtrace, depth == 2, collect regs"
+
+gdb_tfind_test "8.6: find frame 7" "7" "7"
+gdb_test "printf \"TDP \%d:\\n\", \$tracepoint" \
+ "TDP $tdp4:" ""
+gdb_backtrace_tdp_3 "8.6: Backtrace, depth == 2, collect args and locals"
+
+
+gdb_tfind_test "8.6: find frame 9" "9" "9"
+gdb_test "printf \"TDP \%d:\\n\", \$tracepoint" \
+ "TDP $tdp6:" ""
+gdb_backtrace_tdp_4 "8.6: Backtrace, depth == 1, collect stack mem expr" "0"
+
+gdb_tfind_test "8.6: find frame 10" "10" "10"
+gdb_test "printf \"TDP \%d:\\n\", \$tracepoint" \
+ "TDP $tdp2:" ""
+gdb_backtrace_tdp_1 "8.6: Backtrace, depth == 3, collect nothing"
+
+gdb_tfind_test "8.6: find frame 11" "11" "11"
+gdb_test "printf \"TDP \%d:\\n\", \$tracepoint" \
+ "TDP $tdp3:" ""
+gdb_backtrace_tdp_2 "8.6: Backtrace, depth == 3, collect regs"
+
+gdb_tfind_test "8.6: find frame 12" "12" "12"
+gdb_test "printf \"TDP \%d:\\n\", \$tracepoint" \
+ "TDP $tdp4:" ""
+gdb_backtrace_tdp_3 "8.6: Backtrace, depth == 3, collect args and locals"
+
+
+gdb_tfind_test "8.6: find frame 14" "14" "14"
+gdb_test "printf \"TDP \%d:\\n\", \$tracepoint" \
+ "TDP $tdp6:" ""
+gdb_backtrace_tdp_4 "8.6: Backtrace, depth == 1, collect stack mem expr" "0"
+
+gdb_tfind_test "8.6: find frame 15" "15" "15"
+gdb_test "printf \"TDP \%d:\\n\", \$tracepoint" \
+ "TDP $tdp2:" ""
+gdb_backtrace_tdp_1 "8.6: Backtrace, depth == 4, collect nothing"
+
+gdb_tfind_test "8.6: find frame 16" "16" "16"
+gdb_test "printf \"TDP \%d:\\n\", \$tracepoint" \
+ "TDP $tdp3:" ""
+gdb_backtrace_tdp_2 "8.6: Backtrace, depth == 4, collect regs"
+
+gdb_tfind_test "8.6: find frame 17" "17" "17"
+gdb_test "printf \"TDP \%d:\\n\", \$tracepoint" \
+ "TDP $tdp4:" ""
+gdb_backtrace_tdp_3 "8.6: Backtrace, depth == 4, collect args and locals"
+
+
+gdb_tfind_test "8.6: find frame 19" "19" "19"
+gdb_test "printf \"TDP \%d:\\n\", \$tracepoint" \
+ "TDP $tdp6:" ""
+gdb_backtrace_tdp_4 "8.6: Backtrace, depth == 1, collect stack mem expr" "0"
+
+gdb_test "printf \"x \%d x\\n\", depth == 3" \
+ "x 0 x" \
+ "1.13: trace in recursion: depth not equal to 3"
+
+# Finished!
+gdb_test "tfind none" "" ""
diff --git a/gdb/testsuite/gdb.trace/circ.c b/gdb/testsuite/gdb.trace/circ.c
new file mode 100644
index 00000000000..98a2ce6be54
--- /dev/null
+++ b/gdb/testsuite/gdb.trace/circ.c
@@ -0,0 +1,90 @@
+/*
+ * Test program for tracing; circular buffer
+ */
+
+int n = 6;
+
+int testload[13];
+
+static void func0(void)
+{
+}
+
+static void func1(void)
+{
+}
+
+static void func2(void)
+{
+}
+
+static void func3(void)
+{
+}
+
+static void func4(void)
+{
+}
+
+static void func5(void)
+{
+}
+
+static void func6(void)
+{
+}
+
+static void func7(void)
+{
+}
+
+static void func8(void)
+{
+}
+
+static void func9(void)
+{
+}
+
+static void begin () /* called before anything else */
+{
+}
+
+static void end () /* called after everything else */
+{
+}
+
+int
+main (argc, argv, envp)
+ int argc;
+ char *argv[], **envp;
+{
+ int i;
+
+#ifdef usestubs
+ set_debug_traps ();
+ breakpoint ();
+#endif
+
+ begin ();
+ for (i = 0; i < sizeof(testload) / sizeof(testload[0]); i++)
+ testload[i] = i + 1;
+
+ func0 ();
+ func1 ();
+ func2 ();
+ func3 ();
+ func4 ();
+ func5();
+ func6 ();
+ func7 ();
+ func8 ();
+ func9 ();
+
+ end ();
+
+#ifdef usestubs
+ breakpoint ();
+#endif
+ return 0;
+}
diff --git a/gdb/testsuite/gdb.trace/circ.exp b/gdb/testsuite/gdb.trace/circ.exp
new file mode 100644
index 00000000000..ff1724f7d67
--- /dev/null
+++ b/gdb/testsuite/gdb.trace/circ.exp
@@ -0,0 +1,215 @@
+# Copyright (C) 1998 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+if [istarget "m68k-*-elf"] then {
+ pass "Test not supported on this target"
+ return;
+}
+
+load_lib "trace-support.exp"
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+set prms_id 0
+set bug_id 0
+
+set testfile "circ"
+set srcfile ${testfile}.c
+set binfile $objdir/$subdir/$testfile
+
+if { [gdb_compile "$srcdir/$subdir/$srcfile" $binfile \
+ executable {debug additional_flags=-w}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+# Tests:
+# 1) Set up a trace experiment that will collect approximately 10 frames,
+# requiring more than 512 but less than 1024 bytes of cache buffer.
+# (most targets should have at least 1024 bytes of cache buffer!)
+# Run and confirm that it collects all 10 frames.
+# 2) Artificially limit the trace buffer to 512 bytes, and rerun the
+# experiment. Confirm that the first several frames are collected,
+# but that the last several are not.
+# 3) Set trace buffer to circular mode, still with the artificial limit
+# of 512 bytes, and rerun the experiment. Confirm that the last
+# several frames are collected, but the first several are not.
+#
+
+# return 0 for success, 1 for failure
+proc run_trace_experiment { pass } {
+ gdb_run_cmd
+
+ if [gdb_test "tstart" \
+ "\[\r\n\]*" \
+ "start trace experiment, pass $pass"] then { return 1; }
+ if [gdb_test "continue" \
+ "Continuing.*Breakpoint \[0-9\]+, end.*" \
+ "run to end, pass $pass"] then { return 1; }
+ if [gdb_test "tstop" \
+ "\[\r\n\]*" \
+ "stop trace experiment, pass $pass"] then { return 1; }
+ return 0;
+}
+
+# return 0 for success, 1 for failure
+proc set_a_tracepoint { func } {
+ if [gdb_test "trace $func" \
+ "Tracepoint \[0-9\]+ at .*" \
+ "set tracepoint at $func"] then {
+ return 1;
+ }
+ if [gdb_trace_setactions "set actions for $func" \
+ "" \
+ "collect testload" "^$"] then {
+ return 1;
+ }
+ return 0;
+}
+
+# return 0 for success, 1 for failure
+proc setup_tracepoints { } {
+ gdb_delete_tracepoints
+ if [set_a_tracepoint func0] then { return 1; }
+ if [set_a_tracepoint func1] then { return 1; }
+ if [set_a_tracepoint func2] then { return 1; }
+ if [set_a_tracepoint func3] then { return 1; }
+ if [set_a_tracepoint func4] then { return 1; }
+ if [set_a_tracepoint func5] then { return 1; }
+ if [set_a_tracepoint func6] then { return 1; }
+ if [set_a_tracepoint func7] then { return 1; }
+ if [set_a_tracepoint func8] then { return 1; }
+ if [set_a_tracepoint func9] then { return 1; }
+ return 0;
+}
+
+# return 0 for success, 1 for failure
+proc trace_buffer_normal { } {
+ if [gdb_test "maint packet QTBuffer:size:ffffffff" \
+ "received: .OK." ""] then {
+ pass "This test cannot be run on this target"
+ return 1;
+ }
+ if [gdb_test "maint packet QTBuffer:circular:0" \
+ "received: .OK." ""] then {
+ pass "This test cannot be run on this target"
+ return 1;
+ }
+ return 0;
+}
+
+# return 0 for success, 1 for failure
+proc gdb_trace_circular_tests { } {
+
+ # We generously give ourselves one "pass" if we successfully
+ # detect that this test cannot be run on this target!
+ if { ![gdb_target_supports_trace] } then {
+ pass "Current target does not supporst trace"
+ return 1;
+ }
+
+ if [trace_buffer_normal] then { return 1; }
+
+ gdb_test "break begin" "" ""
+ gdb_test "break end" "" ""
+ gdb_test "tstop" "" ""
+ gdb_test "tfind none" "" ""
+
+ if [setup_tracepoints] then { return 1; }
+
+ # First, run the trace experiment with default attributes:
+ # Make sure it behaves as expected.
+ if [run_trace_experiment 1] then { return 1; }
+ if [gdb_test "tfind start" \
+ "#0 func0 .*" \
+ "find frame zero, pass 1"] then { return 1; }
+
+ if [gdb_test "tfind 9" \
+ "#0 func9 .*" \
+ "find frame nine, pass 1"] then { return 1; }
+
+ if [gdb_test "tfind none" \
+ "#0 end .*" \
+ "quit trace debugging, pass 1"] then { return 1; }
+
+ # Then, shrink the trace buffer so that it will not hold
+ # all ten trace frames. Verify that frame zero is still
+ # collected, but frame nine is not.
+ if [gdb_test "maint packet QTBuffer:size:200" \
+ "received: .OK." "shrink the target trace buffer"] then {
+ return 1;
+ }
+ if [run_trace_experiment 2] then { return 1; }
+ if [gdb_test "tfind start" \
+ "#0 func0 .*" \
+ "find frame zero, pass 2"] then { return 1; }
+
+ if [gdb_test "tfind 9" \
+ ".* failed to find .*" \
+ "fail to find frame nine, pass 2"] then { return 1; }
+
+ if [gdb_test "tfind none" \
+ "#0 end .*" \
+ "quit trace debugging, pass 2"] then { return 1; }
+
+ # Finally, make the buffer circular. Now when it runs out of
+ # space, it should wrap around and overwrite the earliest frames.
+ # This means that:
+ # 1) frame zero will be overwritten and therefore unavailable
+ # 2) the earliest frame in the buffer will be other-than-zero
+ # 3) frame nine will be available (unlike on pass 2).
+ if [gdb_test "maint packet QTBuffer:circular:1" \
+ "received: .OK." "make the target trace buffer circular"] then {
+ return 1;
+ }
+ if [run_trace_experiment 3] then { return 1; }
+ if [gdb_test "tfind start" \
+ "#0 func\[1-9\] .*" \
+ "first frame is NOT frame zero, pass 3"] then { return 1; }
+
+ if [gdb_test "tfind 9" \
+ "#0 func9 .*" \
+ "find frame nine, pass 3"] then { return 1; }
+
+ if [gdb_test "tfind none" \
+ "#0 end .*" \
+ "quit trace debugging, pass 3"] then { return 1; }
+
+ return 0;
+}
+
+# Start with a fresh gdb.
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load $binfile
+
+if [target_info exists gdb_stub] {
+ gdb_step_for_stub;
+}
+# Body of test encased in a proc so we can return prematurely.
+if { ![gdb_trace_circular_tests] } then {
+ # Set trace buffer attributes back to normal
+ trace_buffer_normal;
+}
+
+# Finished!
+gdb_test "tfind none" "" ""
diff --git a/gdb/testsuite/gdb.trace/collection.c b/gdb/testsuite/gdb.trace/collection.c
new file mode 100644
index 00000000000..39863325b0a
--- /dev/null
+++ b/gdb/testsuite/gdb.trace/collection.c
@@ -0,0 +1,280 @@
+/*
+ * Test program for trace collection
+ */
+
+/*
+ * Typedefs
+ */
+
+typedef struct TEST_STRUCT {
+ char memberc;
+ int memberi;
+ float memberf;
+ double memberd;
+} test_struct;
+
+typedef int test_array [4];
+
+/*
+ * Global variables to be collected
+ */
+
+char globalc;
+int globali;
+float globalf;
+double globald;
+test_struct globalstruct;
+test_struct *globalp;
+int globalarr[16];
+
+/*
+ * Additional globals used in arithmetic tests
+ */
+
+signed char c0, c1, c2, c3, c4, c5, c6, c7,
+ c8, c9, c10, c11, c12, c13, c14, c15, cminus;
+signed short s0, s1, s2, s3, s4, s5, s6, s7,
+ s8, s9, s10, s11, s12, s13, s14, s15, sminus;
+signed long l0, l1, l2, l3, l4, l5, l6, l7,
+ l8, l9, l10, l11, l12, l13, l14, l15, lminus;
+
+
+/*
+ * Test functions
+ */
+
+static void begin () /* called before anything else */
+{
+}
+
+static void end () /* called after everything else */
+{
+}
+
+/* Test collecting args. */
+int args_test_func (argc, argi, argf, argd, argstruct, argarray)
+ char argc;
+ int argi;
+ float argf;
+ double argd;
+ test_struct argstruct;
+ int argarray[4];
+{
+ int i;
+
+ i = (int) argc + argi + argf + argd + argstruct.memberi + argarray[1];
+
+ return i;
+}
+
+/* Test collecting struct args. */
+int argstruct_test_func (argstruct)
+ test_struct argstruct;
+{
+ return (int) argstruct.memberc + argstruct.memberi +
+ argstruct.memberf + argstruct.memberd;
+}
+
+/* Test collecting array args. */
+int argarray_test_func (argarray)
+ int argarray[4];
+{
+ return (int) argarray[0] + argarray[1] + argarray[2] + argarray[3];
+}
+
+
+
+int local_test_func () /* test collecting locals */
+{
+ char locc = 11;
+ int loci = 12;
+ float locf = 13.3;
+ double locd = 14.4;
+ test_struct locst;
+ int locar[4];
+ int i;
+
+ locst.memberc = 15;
+ locst.memberi = 16;
+ locst.memberf = 17.7;
+ locst.memberd = 18.8;
+ locar[0] = 121;
+ locar[1] = 122;
+ locar[2] = 123;
+ locar[3] = 124;
+
+ i = /* Set_Tracepoint_Here */
+ (int) locc + loci + locf + locd + locst.memberi + locar[1];
+
+ return i;
+}
+
+int reglocal_test_func () /* test collecting register locals */
+{
+ register char locc = 11;
+ register int loci = 12;
+ register float locf = 13.3;
+ register double locd = 14.4;
+ register test_struct locst;
+ register int locar[4];
+ int i;
+
+ locst.memberc = 15;
+ locst.memberi = 16;
+ locst.memberf = 17.7;
+ locst.memberd = 18.8;
+ locar[0] = 121;
+ locar[1] = 122;
+ locar[2] = 123;
+ locar[3] = 124;
+
+ i = /* Set_Tracepoint_Here */
+ (int) locc + loci + locf + locd + locst.memberi + locar[1];
+
+ return i;
+}
+
+int statlocal_test_func () /* test collecting static locals */
+{
+ static char locc;
+ static int loci;
+ static float locf;
+ static double locd;
+ static test_struct locst;
+ static int locar[4];
+ int i;
+
+ locc = 11;
+ loci = 12;
+ locf = 13.3;
+ locd = 14.4;
+ locst.memberc = 15;
+ locst.memberi = 16;
+ locst.memberf = 17.7;
+ locst.memberd = 18.8;
+ locar[0] = 121;
+ locar[1] = 122;
+ locar[2] = 123;
+ locar[3] = 124;
+
+ i = /* Set_Tracepoint_Here */
+ (int) locc + loci + locf + locd + locst.memberi + locar[1];
+
+ /* Set static locals back to zero so collected values are clearly special. */
+ locc = 0;
+ loci = 0;
+ locf = 0;
+ locd = 0;
+ locst.memberc = 0;
+ locst.memberi = 0;
+ locst.memberf = 0;
+ locst.memberd = 0;
+ locar[0] = 0;
+ locar[1] = 0;
+ locar[2] = 0;
+ locar[3] = 0;
+
+ return i;
+}
+
+
+int globals_test_func ()
+{
+ int i = 0;
+
+ i += globalc + globali + globalf + globald;
+ i += globalstruct.memberc + globalstruct.memberi;
+ i += globalstruct.memberf + globalstruct.memberd;
+ i += globalarr[1];
+
+ return i; /* Set_Tracepoint_Here */
+}
+
+int
+main (argc, argv, envp)
+ int argc;
+ char *argv[], **envp;
+{
+ int i = 0;
+ test_struct mystruct;
+ int myarray[4];
+
+#ifdef usestubs
+ set_debug_traps ();
+ breakpoint ();
+#endif
+
+ begin ();
+ /* Assign collectable values to global variables. */
+ l0 = s0 = c0 = 0; l1 = s1 = c1 = 1;
+ l2 = s2 = c2 = 2; l3 = s3 = c3 = 3;
+ l4 = s4 = c4 = 4; l5 = s5 = c5 = 5;
+ l6 = s6 = c6 = 6; l7 = s7 = c7 = 7;
+ l8 = s8 = c8 = 8; l9 = s9 = c9 = 9;
+ l10 = s10 = c10 = 10; l11 = s11 = c11 = 11;
+ l12 = s12 = c12 = 12; l13 = s13 = c13 = 13;
+ l14 = s14 = c14 = 14; l15 = s15 = c15 = 15;
+ lminus = sminus = cminus = -2;
+ globalc = 71;
+ globali = 72;
+ globalf = 73.3;
+ globald = 74.4;
+ globalstruct.memberc = 81;
+ globalstruct.memberi = 82;
+ globalstruct.memberf = 83.3;
+ globalstruct.memberd = 84.4;
+ globalp = &globalstruct;
+
+ for (i = 0; i < 15; i++)
+ globalarr[i] = i;
+
+ mystruct.memberc = 101;
+ mystruct.memberi = 102;
+ mystruct.memberf = 103.3;
+ mystruct.memberd = 104.4;
+ myarray[0] = 111;
+ myarray[1] = 112;
+ myarray[2] = 113;
+ myarray[3] = 114;
+
+ /* Call test functions, so they can be traced and data collected. */
+ i = 0;
+ i += args_test_func (1, 2, 3.3, 4.4, mystruct, myarray);
+ i += argstruct_test_func (mystruct);
+ i += argarray_test_func (myarray);
+ i += local_test_func ();
+ i += reglocal_test_func ();
+ i += statlocal_test_func ();
+ i += globals_test_func ();
+
+ /* Values of globals at end of test should be different from
+ values that they had when trace data was captured. */
+
+ l0 = s0 = c0 = 0; l1 = s1 = c1 = 0;
+ l2 = s2 = c2 = 0; l3 = s3 = c3 = 0;
+ l4 = s4 = c4 = 0; l5 = s5 = c5 = 0;
+ l6 = s6 = c6 = 0; l7 = s7 = c7 = 0;
+ l8 = s8 = c8 = 0; l9 = s9 = c9 = 0;
+ l10 = s10 = c10 = 0; l11 = s11 = c11 = 0;
+ l12 = s12 = c12 = 0; l13 = s13 = c13 = 0;
+ l14 = s14 = c14 = 0; l15 = s15 = c15 = 0;
+ lminus = sminus = cminus = 0;
+
+ /* Set 'em back to zero, so that the collected values will be
+ distinctly different from the "realtime" (end of test) values. */
+
+ globalc = 0;
+ globali = 0;
+ globalf = 0;
+ globald = 0;
+ globalstruct.memberc = 0;
+ globalstruct.memberi = 0;
+ globalstruct.memberf = 0;
+ globalstruct.memberd = 0;
+ globalp = 0;
+ for (i = 0; i < 15; i++)
+ globalarr[i] = 0;
+
+ end ();
+ return 0;
+}
diff --git a/gdb/testsuite/gdb.trace/collection.exp b/gdb/testsuite/gdb.trace/collection.exp
new file mode 100644
index 00000000000..8cd75774fa8
--- /dev/null
+++ b/gdb/testsuite/gdb.trace/collection.exp
@@ -0,0 +1,623 @@
+# Copyright (C) 1998 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+if [istarget "m68k-*-elf"] then {
+ pass "Test not supported on this target"
+ return;
+}
+
+load_lib "trace-support.exp"
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+set prms_id 0
+set bug_id 0
+
+set testfile "collection"
+set srcfile ${testfile}.c
+set binfile $objdir/$subdir/$testfile
+
+if { [gdb_compile "$srcdir/$subdir/$srcfile" $binfile \
+ executable {debug additional_flags=-w}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+# Tests:
+# 1) $args
+# 2) function args by name
+# 3) $locs
+# 4) function locals by name
+# 5) $regs
+# 6) registers by name ($sp, $fp?)
+# 7) globals by name
+# 8) expressions (lots of different kinds: local and global)
+
+set ws "\[\r\n\t \]+"
+set cr "\[\r\n\]+"
+
+#
+# Utility procs
+#
+
+proc test_register { reg test_id } {
+ global cr
+ global gdb_prompt
+
+ send_gdb "print $reg\n"
+ gdb_expect {
+ -re "\\$\[0-9\]+ = \[x0\]+$cr$gdb_prompt " {
+ fail "collect $test_id: collected $reg (zero)"
+ }
+ -re "\\$\[0-9\]+ = \[x0-9a-fA-F\]+$cr$gdb_prompt " {
+ pass "collect $test_id: collected $reg"
+ }
+ -re "\[Ee\]rror.*$gdb_prompt " {
+ fail "collect $test_id: collected $reg (error)"
+ }
+ timeout {
+ fail "collect $test_id: collected $reg (timeout)"
+ }
+ }
+}
+
+proc run_trace_experiment { msg test_func } {
+ gdb_run_cmd
+ gdb_test "tstart" \
+ "\[\r\n\]+" \
+ "collect $msg: start trace experiment"
+ gdb_test "continue" \
+ "Continuing.*Breakpoint \[0-9\]+, end.*" \
+ "collect $msg: run trace experiment"
+ gdb_test "tstop" \
+ "\[\r\n\]+" \
+ "collect $msg: stop trace experiment"
+ gdb_test "tfind start" \
+ "#0 $test_func .*" \
+ "collect $msg: tfind test frame"
+}
+
+
+#
+# Test procs
+#
+
+proc gdb_collect_args_test { myargs msg } {
+ global cr
+ global gdb_prompt
+
+ # Make sure we're in a sane starting state.
+ gdb_test "tstop" "" ""
+ gdb_test "tfind none" "" ""
+ gdb_delete_tracepoints
+
+ gdb_test "trace args_test_func" \
+ "Tracepoint \[0-9\]+ at .*" \
+ "collect $msg: set tracepoint"
+ gdb_trace_setactions "collect $msg: define actions" \
+ "" \
+ "collect $myargs" "^$"
+
+ # Begin the test.
+ run_trace_experiment $msg args_test_func
+
+ gdb_test "print argc" \
+ "\\$\[0-9\]+ = 1 '.001'$cr" \
+ "collect $msg: collected arg char"
+ gdb_test "print argi" \
+ "\\$\[0-9\]+ = 2$cr" \
+ "collect $msg: collected arg int"
+ gdb_test "print argf" \
+ "\\$\[0-9\]+ = 3.\[23\]\[0-9\]*$cr" \
+ "collect $msg: collected arg float"
+ gdb_test "print argd" \
+ "\\$\[0-9\]+ = 4.\[34\]\[0-9\]*$cr" \
+ "collect $msg: collected arg double"
+
+ # struct arg as one of several args (near end of list)
+ gdb_test "print argstruct.memberc" \
+ "\\$\[0-9\]+ = 101 'e'$cr" \
+ "collect $msg: collected arg struct member char"
+ gdb_test "print argstruct.memberi" \
+ "\\$\[0-9\]+ = 102$cr" \
+ "collect $msg: collected arg struct member int"
+ gdb_test "print argstruct.memberf" \
+ "\\$\[0-9\]+ = 103.\[23\]\[0-9\]*$cr" \
+ "collect $msg: collected arg struct member float"
+ gdb_test "print argstruct.memberd" \
+ "\\$\[0-9\]+ = 104.\[34\]\[0-9\]*$cr" \
+ "collect $msg: collected arg struct member double"
+
+ # array arg as one of several args (near end of list)
+ gdb_test "print argarray\[0\]" \
+ "\\$\[0-9\]+ = 111$cr" \
+ "collect $msg: collected argarray #0"
+ gdb_test "print argarray\[1\]" \
+ "\\$\[0-9\]+ = 112$cr" \
+ "collect $msg: collected argarray #1"
+ gdb_test "print argarray\[2\]" \
+ "\\$\[0-9\]+ = 113$cr" \
+ "collect $msg: collected argarray #2"
+ gdb_test "print argarray\[3\]" \
+ "\\$\[0-9\]+ = 114$cr" \
+ "collect $msg: collected argarray #3"
+
+ gdb_test "tfind none" \
+ "#0 end .*" \
+ "collect $msg: cease trace debugging"
+}
+
+proc gdb_collect_argstruct_test { myargs msg } {
+ global cr
+ global gdb_prompt
+
+ # Make sure we're in a sane starting state.
+ gdb_test "tstop" "" ""
+ gdb_test "tfind none" "" ""
+ gdb_delete_tracepoints
+
+ gdb_test "trace argstruct_test_func" \
+ "Tracepoint \[0-9\]+ at .*" \
+ "collect $msg: set tracepoint"
+ gdb_trace_setactions "collect $msg: define actions" \
+ "" \
+ "collect $myargs" "^$"
+
+ # Begin the test.
+ run_trace_experiment $msg argstruct_test_func
+
+ # struct argument as only argument
+ gdb_test "print argstruct.memberc" \
+ "\\$\[0-9\]+ = 101 'e'$cr" \
+ "collect $msg: collected arg struct member char"
+ gdb_test "print argstruct.memberi" \
+ "\\$\[0-9\]+ = 102$cr" \
+ "collect $msg: collected arg struct member int"
+ gdb_test "print argstruct.memberf" \
+ "\\$\[0-9\]+ = 103.\[23\]\[0-9\]*$cr" \
+ "collect $msg: collected arg struct member float"
+ gdb_test "print argstruct.memberd" \
+ "\\$\[0-9\]+ = 104.\[34\]\[0-9\]*$cr" \
+ "collect $msg: collected arg struct member double"
+
+ gdb_test "tfind none" \
+ "#0 end .*" \
+ "collect $msg: cease trace debugging"
+}
+
+
+proc gdb_collect_argarray_test { myargs msg } {
+ global cr
+ global gdb_prompt
+
+ # Make sure we're in a sane starting state.
+ gdb_test "tstop" "" ""
+ gdb_test "tfind none" "" ""
+ gdb_delete_tracepoints
+
+ gdb_test "trace argarray_test_func" \
+ "Tracepoint \[0-9\]+ at .*" \
+ "collect $msg: set tracepoint"
+ gdb_trace_setactions "collect $msg: define actions" \
+ "" \
+ "collect $myargs" "^$"
+
+ # Begin the test.
+ run_trace_experiment $msg argarray_test_func
+
+ # array arg as only argument
+ gdb_test "print argarray\[0\]" \
+ "\\$\[0-9\]+ = 111$cr" \
+ "collect $msg: collected argarray #0"
+ gdb_test "print argarray\[1\]" \
+ "\\$\[0-9\]+ = 112$cr" \
+ "collect $msg: collected argarray #1"
+ gdb_test "print argarray\[2\]" \
+ "\\$\[0-9\]+ = 113$cr" \
+ "collect $msg: collected argarray #2"
+ gdb_test "print argarray\[3\]" \
+ "\\$\[0-9\]+ = 114$cr" \
+ "collect $msg: collected argarray #3"
+
+ gdb_test "tfind none" \
+ "#0 end .*" \
+ "collect $msg: cease trace debugging"
+}
+
+
+proc gdb_collect_locals_test { func mylocs msg } {
+ global cr
+ global gdb_prompt
+
+ # Make sure we're in a sane starting state.
+ gdb_test "tstop" "" ""
+ gdb_test "tfind none" "" ""
+ gdb_delete_tracepoints
+
+ # Find the comment-identified line for setting this tracepoint.
+ set testline 0
+ send_gdb "list $func, +30\n"
+ gdb_expect {
+ -re "\[\r\n\](\[0-9\]+)\[^\r\n\]+ Set_Tracepoint_Here .*$gdb_prompt" {
+ set testline $expect_out(1,string)
+ pass "collect $msg: find tracepoint line"
+ }
+ -re ".*$gdb_prompt " {
+ fail "collect $msg: find tracepoint line (skipping locals test)"
+ return
+ }
+ timeout {
+ fail "collect $msg: find tracepoint line (skipping locals test)"
+ return
+ }
+ }
+
+ gdb_test "trace $testline" \
+ "Tracepoint \[0-9\]+ at .*" \
+ "collect $msg: set tracepoint"
+ gdb_trace_setactions "collect $msg: define actions" \
+ "" \
+ "collect $mylocs" "^$"
+
+ # Begin the test.
+ run_trace_experiment $msg $func
+
+ gdb_test "print locc" \
+ "\\$\[0-9\]+ = 11 '.013'$cr" \
+ "collect $msg: collected local char"
+ gdb_test "print loci" \
+ "\\$\[0-9\]+ = 12$cr" \
+ "collect $msg: collected local int"
+ gdb_test "print locf" \
+ "\\$\[0-9\]+ = 13.\[23\]\[0-9\]*$cr" \
+ "collect $msg: collected local float"
+ gdb_test "print locd" \
+ "\\$\[0-9\]+ = 14.\[34\]\[0-9\]*$cr" \
+ "collect $msg: collected local double"
+
+ gdb_test "print locst.memberc" \
+ "\\$\[0-9\]+ = 15 '.017'$cr" \
+ "collect $msg: collected local member char"
+ gdb_test "print locst.memberi" \
+ "\\$\[0-9\]+ = 16$cr" \
+ "collect $msg: collected local member int"
+ gdb_test "print locst.memberf" \
+ "\\$\[0-9\]+ = 17.\[67\]\[0-9\]*$cr" \
+ "collect $msg: collected local member float"
+ gdb_test "print locst.memberd" \
+ "\\$\[0-9\]+ = 18.\[78\]\[0-9\]*$cr" \
+ "collect $msg: collected local member double"
+
+ gdb_test "print locar\[0\]" \
+ "\\$\[0-9\]+ = 121$cr" \
+ "collect $msg: collected locarray #0"
+ gdb_test "print locar\[1\]" \
+ "\\$\[0-9\]+ = 122$cr" \
+ "collect $msg: collected locarray #1"
+ gdb_test "print locar\[2\]" \
+ "\\$\[0-9\]+ = 123$cr" \
+ "collect $msg: collected locarray #2"
+ gdb_test "print locar\[3\]" \
+ "\\$\[0-9\]+ = 124$cr" \
+ "collect $msg: collected locarray #3"
+
+
+ gdb_test "tfind none" \
+ "#0 end .*" \
+ "collect $msg: cease trace debugging"
+}
+
+proc gdb_collect_registers_test { myregs } {
+ global cr
+ global gdb_prompt
+
+ # Make sure we're in a sane starting state.
+ gdb_test "tstop" "" ""
+ gdb_test "tfind none" "" ""
+ gdb_delete_tracepoints
+
+ # We'll simply re-use the args_test_function for this test
+ gdb_test "trace args_test_func" \
+ "Tracepoint \[0-9\]+ at .*" \
+ "collect $myregs: set tracepoint"
+ gdb_trace_setactions "collect $myregs: define actions" \
+ "" \
+ "collect $myregs" "^$"
+
+ # Begin the test.
+ run_trace_experiment $myregs args_test_func
+
+ test_register "\$fp" $myregs
+ test_register "\$sp" $myregs
+ test_register "\$pc" $myregs
+
+ gdb_test "tfind none" \
+ "#0 end .*" \
+ "collect $myregs: cease trace debugging"
+}
+
+proc gdb_collect_expression_test { func expr val msg } {
+ global cr
+ global gdb_prompt
+
+ # Make sure we're in a sane starting state.
+ gdb_test "tstop" "" ""
+ gdb_test "tfind none" "" ""
+ gdb_delete_tracepoints
+
+ # Find the comment-identified line for setting this tracepoint.
+ set testline 0
+ send_gdb "list $func, +30\n"
+ gdb_expect {
+ -re "\[\r\n\](\[0-9\]+)\[^\r\n\]+ Set_Tracepoint_Here .*$gdb_prompt" {
+ set testline $expect_out(1,string)
+ pass "collect $msg: find tracepoint line"
+ }
+ -re ".*$gdb_prompt " {
+ fail "collect $msg: find tracepoint line (skipping locals test)"
+ return
+ }
+ timeout {
+ fail "collect $msg: find tracepoint line (skipping locals test)"
+ return
+ }
+ }
+
+ gdb_test "trace $testline" \
+ "Tracepoint \[0-9\]+ at .*" \
+ "collect $msg: set tracepoint"
+ gdb_trace_setactions "collect $msg: define actions" \
+ "" \
+ "collect $expr" "^$"
+
+ # Begin the test.
+ run_trace_experiment $msg $func
+
+ gdb_test "print $expr" \
+ "\\$\[0-9\]+ = $val$cr" \
+ "collect $msg: got expected value '$val'"
+
+ gdb_test "tfind none" \
+ "#0 end .*" \
+ "collect $msg: cease trace debugging"
+}
+
+proc gdb_collect_globals_test { } {
+ global cr
+ global gdb_prompt
+
+ # Make sure we're in a sane starting state.
+ gdb_test "tstop" "" ""
+ gdb_test "tfind none" "" ""
+ gdb_delete_tracepoints
+
+ # Find the comment-identified line for setting this tracepoint.
+ set testline 0
+ send_gdb "list globals_test_func, +30\n"
+ gdb_expect {
+ -re "\[\r\n\](\[0-9\]+)\[^\r\n\]+ Set_Tracepoint_Here .*$gdb_prompt" {
+ set testline $expect_out(1,string)
+ pass "collect globals: find tracepoint line"
+ }
+ -re ".*$gdb_prompt " {
+ fail "collect globals: find tracepoint line (skipping global test)"
+ return
+ }
+ timeout {
+ fail "collect globals: find tracepoint line (skipping global test)"
+ return
+ }
+ }
+
+ gdb_test "trace $testline" \
+ "Tracepoint \[0-9\]+ at .*" \
+ "collect globals: set tracepoint"
+ gdb_trace_setactions "collect globals: define actions" \
+ "" \
+ "collect globalc, globali, globalf, globald" "^$" \
+ "collect globalstruct, globalp, globalarr" "^$"
+
+ # Begin the test.
+ run_trace_experiment "globals" globals_test_func
+
+ gdb_test "print globalc" \
+ "\\$\[0-9\]+ = 71 'G'$cr" \
+ "collect globals: collected global char"
+ gdb_test "print globali" \
+ "\\$\[0-9\]+ = 72$cr" \
+ "collect globals: collected global int"
+ gdb_test "print globalf" \
+ "\\$\[0-9\]+ = 73.\[23\]\[0-9\]*$cr" \
+ "collect globals: collected global float"
+ gdb_test "print globald" \
+ "\\$\[0-9\]+ = 74.\[34\]\[0-9\]*$cr" \
+ "collect globals: collected global double"
+
+ gdb_test "print globalstruct.memberc" \
+ "\\$\[0-9\]+ = 81 'Q'$cr" \
+ "collect globals: collected struct char member"
+ gdb_test "print globalstruct.memberi" \
+ "\\$\[0-9\]+ = 82$cr" \
+ "collect globals: collected struct member int"
+ gdb_test "print globalstruct.memberf" \
+ "\\$\[0-9\]+ = 83.\[23\]\[0-9\]*$cr" \
+ "collect globals: collected struct member float"
+ gdb_test "print globalstruct.memberd" \
+ "\\$\[0-9\]+ = 84.\[34\]\[0-9\]*$cr" \
+ "collect globals: collected struct member double"
+
+ gdb_test "print globalp == &globalstruct" \
+ "\\$\[0-9\]+ = 1$cr" \
+ "collect globals: collected global pointer"
+
+ gdb_test "print globalarr\[1\]" \
+ "\\$\[0-9\]+ = 1$cr" \
+ "collect globals: collected global array element #1"
+ gdb_test "print globalarr\[2\]" \
+ "\\$\[0-9\]+ = 2$cr" \
+ "collect globals: collected global array element #2"
+ gdb_test "print globalarr\[3\]" \
+ "\\$\[0-9\]+ = 3$cr" \
+ "collect globals: collected global array element #3"
+
+ gdb_test "tfind none" \
+ "#0 end .*" \
+ "collect globals: cease trace debugging"
+}
+
+proc gdb_trace_collection_test { } {
+ global gdb_prompt;
+
+ gdb_test "set width 0" "" ""
+ delete_breakpoints
+
+ # We generously give ourselves one "pass" if we successfully
+ # detect that this test cannot be run on this target!
+ if { ![gdb_target_supports_trace] } then {
+ pass "Current target does not supporst trace"
+ return 1;
+ }
+
+ gdb_test "break begin" "" ""
+ gdb_test "break end" "" ""
+ gdb_collect_args_test "\$args" \
+ "args collectively"
+ gdb_collect_args_test "argc, argi, argf, argd, argstruct, argarray" \
+ "args individually"
+ gdb_collect_argstruct_test "\$args" \
+ "argstruct collectively"
+ gdb_collect_argstruct_test "argstruct" \
+ "argstruct individually"
+ gdb_collect_argarray_test "\$args" \
+ "argarray collectively"
+ gdb_collect_argarray_test "argarray" \
+ "argarray individually"
+ gdb_collect_locals_test local_test_func "\$locals" \
+ "auto locals collectively"
+ gdb_collect_locals_test local_test_func \
+ "locc, loci, locf, locd, locst, locar" \
+ "auto locals individually"
+ gdb_collect_locals_test reglocal_test_func "\$locals" \
+ "register locals collectively"
+ gdb_collect_locals_test reglocal_test_func \
+ "locc, loci, locf, locd, locst, locar" \
+ "register locals individually"
+ gdb_collect_locals_test statlocal_test_func "\$locals" \
+ "static locals collectively"
+ gdb_collect_locals_test statlocal_test_func \
+ "locc, loci, locf, locd, locst, locar" \
+ "static locals individually"
+
+ gdb_collect_registers_test "\$regs"
+ gdb_collect_registers_test "\$fp, \$sp, \$pc"
+ gdb_collect_globals_test
+
+ #
+ # Expression tests:
+ #
+ # *x (**x, ...)
+ # x.y (x.y.z, ...)
+ # x->y (x->y->z, ...)
+ # x[2] (x[2][3], ...) (const index)
+ # x[y] (x[y][z], ...) (index to be char, short, long, float, double)
+ # NOTE:
+ # We test the following operators by using them in an array index
+ # expression -- because the naked result of an operator is not really
+ # collected. To be sure the operator was evaluated correctly on the
+ # target, we have to actually use the result eg. in an array offset
+ # calculation.
+ # x[y + z] (tests addition: y and z various combos of types, sclasses)
+ # x[y - z] (tests subtraction) (ditto)
+ # x[y * z] (tests multiplication) (ditto)
+ # x[y / z] (tests division) (ditto)
+ # x[y % z] (tests modulo division) (ditto)
+ # x[y == z] (tests equality relation) (ditto) UNSUPPORTED
+ # x[y != z] (tests inequality relation) (ditto) UNSUPPORTED
+ # x[y > z] (tests greater-than relation) (ditto) UNSUPPORTED
+ # x[y < z] (tests less-than relation) (ditto) UNSUPPORTED
+ # x[y >= z] (tests greater-than-or-equal relation) (ditto) UNSUPPORTED
+ # x[y <= z] (tests less-than-or-equal relation) (ditto) UNSUPPORTED
+ # x[y && z] (tests logical and) (ditto) UNSUPPORTED
+ # x[y || z] (tests logical or) (ditto) UNSUPPORTED
+ # x[y & z] (tests binary and) (ditto) UNSUPPORTED
+ # x[y | z] (tests binary or) (ditto) UNSUPPORTED
+ # x[y ^ z] (tests binary xor) (ditto) UNSUPPORTED
+ # x[y ? z1 : z2] (tests ternary operator) (ditto) UNSUPPORTED
+ # x[y << z] (tests shift-left) (ditto) UNSUPPORTED
+ # x[y >> z] (tests shift-right) (ditto) UNSUPPORTED
+ # x[y = z] (tests assignment operator) (ditto) UNSUPPORTED
+ # x[++y] (tests pre-increment operator) (ditto) UNSUPPORTED
+ # x[--y] (tests pre-decrement operator) (ditto) UNSUPPORTED
+ # x[y++] (tests post-increment operator) (ditto) UNSUPPORTED
+ # x[y--] (tests post-decrement operator) (ditto) UNSUPPORTED
+ # x[+y] (tests unary plus) (ditto)
+ # x[-y] (tests unary minus) (ditto)
+ # x[!y] (tests logical not) (ditto) UNSUPPORTED
+ # x[~y] (tests binary not) (ditto) UNSUPPORTED
+ # x[(y, z)] (tests comma expression) (ditto)
+ # cast expr
+ # stack data
+
+ gdb_collect_expression_test globals_test_func \
+ "globalstruct.memberi" "82" "a.b"
+ gdb_collect_expression_test globals_test_func \
+ "globalp->memberc" "81 'Q'" "a->b"
+ gdb_collect_expression_test globals_test_func \
+ "globalarr\[2\]" "2" "a\[2\]"
+ gdb_collect_expression_test globals_test_func \
+ "globalarr\[l3\]" "3" "a\[b\]"
+ gdb_collect_expression_test globals_test_func \
+ "globalarr\[l3 + l2\]" "5" "a\[b + c\]"
+ gdb_collect_expression_test globals_test_func \
+ "globalarr\[l3 - l2\]" "1" "a\[b - c\]"
+ gdb_collect_expression_test globals_test_func \
+ "globalarr\[l3 * l2\]" "6" "a\[b * c\]"
+ gdb_collect_expression_test globals_test_func \
+ "globalarr\[l6 / l3\]" "2" "a\[b / c\]"
+ gdb_collect_expression_test globals_test_func \
+ "globalarr\[l7 % l3\]" "1" "a\[b % c\]"
+ gdb_collect_expression_test globals_test_func \
+ "globalarr\[+l1\]" "1" "a\[+b\]"
+ gdb_collect_expression_test globals_test_func \
+ "globalarr\[-lminus\]" "2" "a\[-b\]"
+ gdb_collect_expression_test globals_test_func \
+ "globalarr\[\(l6, l7\)\]" "7" "a\[\(b, c\)\]"
+
+}
+
+# Start with a fresh gdb.
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load $binfile
+
+if [target_info exists gdb_stub] {
+ gdb_step_for_stub;
+}
+
+# Body of test encased in a proc so we can return prematurely.
+gdb_trace_collection_test
+
+# Finished!
+gdb_test "tfind none" "" ""
+
+
+
diff --git a/gdb/testsuite/gdb.trace/configure b/gdb/testsuite/gdb.trace/configure
new file mode 100755
index 00000000000..417620553ee
--- /dev/null
+++ b/gdb/testsuite/gdb.trace/configure
@@ -0,0 +1,899 @@
+#! /bin/sh
+
+# Guess values for system-dependent variables and create Makefiles.
+# Generated automatically using autoconf version 2.12.1
+# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc.
+#
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+
+# Defaults:
+ac_help=
+ac_default_prefix=/usr/local
+# Any additions from configure.in:
+
+# Initialize some variables set by options.
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+build=NONE
+cache_file=./config.cache
+exec_prefix=NONE
+host=NONE
+no_create=
+nonopt=NONE
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+target=NONE
+verbose=
+x_includes=NONE
+x_libraries=NONE
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datadir='${prefix}/share'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+libdir='${exec_prefix}/lib'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+infodir='${prefix}/info'
+mandir='${prefix}/man'
+
+# Initialize some other variables.
+subdirs=
+MFLAGS= MAKEFLAGS=
+SHELL=${CONFIG_SHELL-/bin/sh}
+# Maximum number of lines to put in a shell here document.
+ac_max_here_lines=12
+
+ac_prev=
+for ac_option
+do
+
+ # If the previous option needs an argument, assign it.
+ if test -n "$ac_prev"; then
+ eval "$ac_prev=\$ac_option"
+ ac_prev=
+ continue
+ fi
+
+ case "$ac_option" in
+ -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
+ *) ac_optarg= ;;
+ esac
+
+ # Accept the important Cygnus configure options, so we can diagnose typos.
+
+ case "$ac_option" in
+
+ -bindir | --bindir | --bindi | --bind | --bin | --bi)
+ ac_prev=bindir ;;
+ -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+ bindir="$ac_optarg" ;;
+
+ -build | --build | --buil | --bui | --bu)
+ ac_prev=build ;;
+ -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+ build="$ac_optarg" ;;
+
+ -cache-file | --cache-file | --cache-fil | --cache-fi \
+ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+ ac_prev=cache_file ;;
+ -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+ cache_file="$ac_optarg" ;;
+
+ -datadir | --datadir | --datadi | --datad | --data | --dat | --da)
+ ac_prev=datadir ;;
+ -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \
+ | --da=*)
+ datadir="$ac_optarg" ;;
+
+ -disable-* | --disable-*)
+ ac_feature=`echo $ac_option|sed -e 's/-*disable-//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then
+ { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
+ fi
+ ac_feature=`echo $ac_feature| sed 's/-/_/g'`
+ eval "enable_${ac_feature}=no" ;;
+
+ -enable-* | --enable-*)
+ ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then
+ { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
+ fi
+ ac_feature=`echo $ac_feature| sed 's/-/_/g'`
+ case "$ac_option" in
+ *=*) ;;
+ *) ac_optarg=yes ;;
+ esac
+ eval "enable_${ac_feature}='$ac_optarg'" ;;
+
+ -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+ | --exec | --exe | --ex)
+ ac_prev=exec_prefix ;;
+ -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+ | --exec=* | --exe=* | --ex=*)
+ exec_prefix="$ac_optarg" ;;
+
+ -gas | --gas | --ga | --g)
+ # Obsolete; use --with-gas.
+ with_gas=yes ;;
+
+ -help | --help | --hel | --he)
+ # Omit some internal or obsolete options to make the list less imposing.
+ # This message is too long to be a string in the A/UX 3.1 sh.
+ cat << EOF
+Usage: configure [options] [host]
+Options: [defaults in brackets after descriptions]
+Configuration:
+ --cache-file=FILE cache test results in FILE
+ --help print this message
+ --no-create do not create output files
+ --quiet, --silent do not print \`checking...' messages
+ --version print the version of autoconf that created configure
+Directory and file names:
+ --prefix=PREFIX install architecture-independent files in PREFIX
+ [$ac_default_prefix]
+ --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
+ [same as prefix]
+ --bindir=DIR user executables in DIR [EPREFIX/bin]
+ --sbindir=DIR system admin executables in DIR [EPREFIX/sbin]
+ --libexecdir=DIR program executables in DIR [EPREFIX/libexec]
+ --datadir=DIR read-only architecture-independent data in DIR
+ [PREFIX/share]
+ --sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc]
+ --sharedstatedir=DIR modifiable architecture-independent data in DIR
+ [PREFIX/com]
+ --localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var]
+ --libdir=DIR object code libraries in DIR [EPREFIX/lib]
+ --includedir=DIR C header files in DIR [PREFIX/include]
+ --oldincludedir=DIR C header files for non-gcc in DIR [/usr/include]
+ --infodir=DIR info documentation in DIR [PREFIX/info]
+ --mandir=DIR man documentation in DIR [PREFIX/man]
+ --srcdir=DIR find the sources in DIR [configure dir or ..]
+ --program-prefix=PREFIX prepend PREFIX to installed program names
+ --program-suffix=SUFFIX append SUFFIX to installed program names
+ --program-transform-name=PROGRAM
+ run sed PROGRAM on installed program names
+EOF
+ cat << EOF
+Host type:
+ --build=BUILD configure for building on BUILD [BUILD=HOST]
+ --host=HOST configure for HOST [guessed]
+ --target=TARGET configure for TARGET [TARGET=HOST]
+Features and packages:
+ --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
+ --enable-FEATURE[=ARG] include FEATURE [ARG=yes]
+ --with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
+ --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
+ --x-includes=DIR X include files are in DIR
+ --x-libraries=DIR X library files are in DIR
+EOF
+ if test -n "$ac_help"; then
+ echo "--enable and --with options recognized:$ac_help"
+ fi
+ exit 0 ;;
+
+ -host | --host | --hos | --ho)
+ ac_prev=host ;;
+ -host=* | --host=* | --hos=* | --ho=*)
+ host="$ac_optarg" ;;
+
+ -includedir | --includedir | --includedi | --included | --include \
+ | --includ | --inclu | --incl | --inc)
+ ac_prev=includedir ;;
+ -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+ | --includ=* | --inclu=* | --incl=* | --inc=*)
+ includedir="$ac_optarg" ;;
+
+ -infodir | --infodir | --infodi | --infod | --info | --inf)
+ ac_prev=infodir ;;
+ -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+ infodir="$ac_optarg" ;;
+
+ -libdir | --libdir | --libdi | --libd)
+ ac_prev=libdir ;;
+ -libdir=* | --libdir=* | --libdi=* | --libd=*)
+ libdir="$ac_optarg" ;;
+
+ -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+ | --libexe | --libex | --libe)
+ ac_prev=libexecdir ;;
+ -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+ | --libexe=* | --libex=* | --libe=*)
+ libexecdir="$ac_optarg" ;;
+
+ -localstatedir | --localstatedir | --localstatedi | --localstated \
+ | --localstate | --localstat | --localsta | --localst \
+ | --locals | --local | --loca | --loc | --lo)
+ ac_prev=localstatedir ;;
+ -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+ | --localstate=* | --localstat=* | --localsta=* | --localst=* \
+ | --locals=* | --local=* | --loca=* | --loc=* | --lo=*)
+ localstatedir="$ac_optarg" ;;
+
+ -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+ ac_prev=mandir ;;
+ -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+ mandir="$ac_optarg" ;;
+
+ -nfp | --nfp | --nf)
+ # Obsolete; use --without-fp.
+ with_fp=no ;;
+
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c)
+ no_create=yes ;;
+
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+ no_recursion=yes ;;
+
+ -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+ | --oldin | --oldi | --old | --ol | --o)
+ ac_prev=oldincludedir ;;
+ -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+ oldincludedir="$ac_optarg" ;;
+
+ -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+ ac_prev=prefix ;;
+ -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+ prefix="$ac_optarg" ;;
+
+ -program-prefix | --program-prefix | --program-prefi | --program-pref \
+ | --program-pre | --program-pr | --program-p)
+ ac_prev=program_prefix ;;
+ -program-prefix=* | --program-prefix=* | --program-prefi=* \
+ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+ program_prefix="$ac_optarg" ;;
+
+ -program-suffix | --program-suffix | --program-suffi | --program-suff \
+ | --program-suf | --program-su | --program-s)
+ ac_prev=program_suffix ;;
+ -program-suffix=* | --program-suffix=* | --program-suffi=* \
+ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+ program_suffix="$ac_optarg" ;;
+
+ -program-transform-name | --program-transform-name \
+ | --program-transform-nam | --program-transform-na \
+ | --program-transform-n | --program-transform- \
+ | --program-transform | --program-transfor \
+ | --program-transfo | --program-transf \
+ | --program-trans | --program-tran \
+ | --progr-tra | --program-tr | --program-t)
+ ac_prev=program_transform_name ;;
+ -program-transform-name=* | --program-transform-name=* \
+ | --program-transform-nam=* | --program-transform-na=* \
+ | --program-transform-n=* | --program-transform-=* \
+ | --program-transform=* | --program-transfor=* \
+ | --program-transfo=* | --program-transf=* \
+ | --program-trans=* | --program-tran=* \
+ | --progr-tra=* | --program-tr=* | --program-t=*)
+ program_transform_name="$ac_optarg" ;;
+
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ silent=yes ;;
+
+ -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+ ac_prev=sbindir ;;
+ -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+ | --sbi=* | --sb=*)
+ sbindir="$ac_optarg" ;;
+
+ -sharedstatedir | --sharedstatedir | --sharedstatedi \
+ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+ | --sharedst | --shareds | --shared | --share | --shar \
+ | --sha | --sh)
+ ac_prev=sharedstatedir ;;
+ -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+ | --sha=* | --sh=*)
+ sharedstatedir="$ac_optarg" ;;
+
+ -site | --site | --sit)
+ ac_prev=site ;;
+ -site=* | --site=* | --sit=*)
+ site="$ac_optarg" ;;
+
+ -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+ ac_prev=srcdir ;;
+ -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+ srcdir="$ac_optarg" ;;
+
+ -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+ | --syscon | --sysco | --sysc | --sys | --sy)
+ ac_prev=sysconfdir ;;
+ -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+ sysconfdir="$ac_optarg" ;;
+
+ -target | --target | --targe | --targ | --tar | --ta | --t)
+ ac_prev=target ;;
+ -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+ target="$ac_optarg" ;;
+
+ -v | -verbose | --verbose | --verbos | --verbo | --verb)
+ verbose=yes ;;
+
+ -version | --version | --versio | --versi | --vers)
+ echo "configure generated by autoconf version 2.12.1"
+ exit 0 ;;
+
+ -with-* | --with-*)
+ ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then
+ { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
+ fi
+ ac_package=`echo $ac_package| sed 's/-/_/g'`
+ case "$ac_option" in
+ *=*) ;;
+ *) ac_optarg=yes ;;
+ esac
+ eval "with_${ac_package}='$ac_optarg'" ;;
+
+ -without-* | --without-*)
+ ac_package=`echo $ac_option|sed -e 's/-*without-//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then
+ { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
+ fi
+ ac_package=`echo $ac_package| sed 's/-/_/g'`
+ eval "with_${ac_package}=no" ;;
+
+ --x)
+ # Obsolete; use --with-x.
+ with_x=yes ;;
+
+ -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+ | --x-incl | --x-inc | --x-in | --x-i)
+ ac_prev=x_includes ;;
+ -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+ x_includes="$ac_optarg" ;;
+
+ -x-libraries | --x-libraries | --x-librarie | --x-librari \
+ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+ ac_prev=x_libraries ;;
+ -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+ x_libraries="$ac_optarg" ;;
+
+ -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; }
+ ;;
+
+ *)
+ if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then
+ echo "configure: warning: $ac_option: invalid host type" 1>&2
+ fi
+ if test "x$nonopt" != xNONE; then
+ { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; }
+ fi
+ nonopt="$ac_option"
+ ;;
+
+ esac
+done
+
+if test -n "$ac_prev"; then
+ { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; }
+fi
+
+trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
+
+# File descriptor usage:
+# 0 standard input
+# 1 file creation
+# 2 errors and warnings
+# 3 some systems may open it to /dev/tty
+# 4 used on the Kubota Titan
+# 6 checking for... messages and results
+# 5 compiler messages saved in config.log
+if test "$silent" = yes; then
+ exec 6>/dev/null
+else
+ exec 6>&1
+fi
+exec 5>./config.log
+
+echo "\
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+" 1>&5
+
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Also quote any args containing shell metacharacters.
+ac_configure_args=
+for ac_arg
+do
+ case "$ac_arg" in
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c) ;;
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;;
+ *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*)
+ ac_configure_args="$ac_configure_args '$ac_arg'" ;;
+ *) ac_configure_args="$ac_configure_args $ac_arg" ;;
+ esac
+done
+
+# NLS nuisances.
+# Only set these to C if already set. These must not be set unconditionally
+# because not all systems understand e.g. LANG=C (notably SCO).
+# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'!
+# Non-C LC_CTYPE values break the ctype check.
+if test "${LANG+set}" = set; then LANG=C; export LANG; fi
+if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi
+if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi
+if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -rf conftest* confdefs.h
+# AIX cpp loses on an empty file, so make sure it contains at least a newline.
+echo > confdefs.h
+
+# A filename unique to this package, relative to the directory that
+# configure is in, which we can look for to find out if srcdir is correct.
+ac_unique_file=collection.c
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+ ac_srcdir_defaulted=yes
+ # Try the directory containing this script, then its parent.
+ ac_prog=$0
+ ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'`
+ test "x$ac_confdir" = "x$ac_prog" && ac_confdir=.
+ srcdir=$ac_confdir
+ if test ! -r $srcdir/$ac_unique_file; then
+ srcdir=..
+ fi
+else
+ ac_srcdir_defaulted=no
+fi
+if test ! -r $srcdir/$ac_unique_file; then
+ if test "$ac_srcdir_defaulted" = yes; then
+ { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; }
+ else
+ { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; }
+ fi
+fi
+srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'`
+
+# Prefer explicitly selected file to automatically selected ones.
+if test -z "$CONFIG_SITE"; then
+ if test "x$prefix" != xNONE; then
+ CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site"
+ else
+ CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
+ fi
+fi
+for ac_site_file in $CONFIG_SITE; do
+ if test -r "$ac_site_file"; then
+ echo "loading site script $ac_site_file"
+ . "$ac_site_file"
+ fi
+done
+
+if test -r "$cache_file"; then
+ echo "loading cache $cache_file"
+ . $cache_file
+else
+ echo "creating cache $cache_file"
+ > $cache_file
+fi
+
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then
+ # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu.
+ if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then
+ ac_n= ac_c='
+' ac_t=' '
+ else
+ ac_n=-n ac_c= ac_t=
+ fi
+else
+ ac_n= ac_c='\c' ac_t=
+fi
+
+
+
+CC=${CC-cc}
+
+ac_aux_dir=
+for ac_dir in `cd $srcdir;pwd`/../../.. $srcdir/`cd $srcdir;pwd`/../../..; do
+ if test -f $ac_dir/install-sh; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install-sh -c"
+ break
+ elif test -f $ac_dir/install.sh; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install.sh -c"
+ break
+ fi
+done
+if test -z "$ac_aux_dir"; then
+ { echo "configure: error: can not find install-sh or install.sh in `cd $srcdir;pwd`/../../.. $srcdir/`cd $srcdir;pwd`/../../.." 1>&2; exit 1; }
+fi
+ac_config_guess=$ac_aux_dir/config.guess
+ac_config_sub=$ac_aux_dir/config.sub
+ac_configure=$ac_aux_dir/configure # This should be Cygnus configure.
+
+
+# Do some error checking and defaulting for the host and target type.
+# The inputs are:
+# configure --host=HOST --target=TARGET --build=BUILD NONOPT
+#
+# The rules are:
+# 1. You are not allowed to specify --host, --target, and nonopt at the
+# same time.
+# 2. Host defaults to nonopt.
+# 3. If nonopt is not specified, then host defaults to the current host,
+# as determined by config.guess.
+# 4. Target and build default to nonopt.
+# 5. If nonopt is not specified, then target and build default to host.
+
+# The aliases save the names the user supplied, while $host etc.
+# will get canonicalized.
+case $host---$target---$nonopt in
+NONE---*---* | *---NONE---* | *---*---NONE) ;;
+*) { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; } ;;
+esac
+
+
+# Make sure we can run config.sub.
+if ${CONFIG_SHELL-/bin/sh} $ac_config_sub sun4 >/dev/null 2>&1; then :
+else { echo "configure: error: can not run $ac_config_sub" 1>&2; exit 1; }
+fi
+
+echo $ac_n "checking host system type""... $ac_c" 1>&6
+echo "configure:573: checking host system type" >&5
+
+host_alias=$host
+case "$host_alias" in
+NONE)
+ case $nonopt in
+ NONE)
+ if host_alias=`${CONFIG_SHELL-/bin/sh} $ac_config_guess`; then :
+ else { echo "configure: error: can not guess host type; you must specify one" 1>&2; exit 1; }
+ fi ;;
+ *) host_alias=$nonopt ;;
+ esac ;;
+esac
+
+host=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $host_alias`
+host_cpu=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+host_vendor=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+host_os=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+echo "$ac_t""$host" 1>&6
+
+echo $ac_n "checking target system type""... $ac_c" 1>&6
+echo "configure:594: checking target system type" >&5
+
+target_alias=$target
+case "$target_alias" in
+NONE)
+ case $nonopt in
+ NONE) target_alias=$host_alias ;;
+ *) target_alias=$nonopt ;;
+ esac ;;
+esac
+
+target=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $target_alias`
+target_cpu=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+target_vendor=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+target_os=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+echo "$ac_t""$target" 1>&6
+
+echo $ac_n "checking build system type""... $ac_c" 1>&6
+echo "configure:612: checking build system type" >&5
+
+build_alias=$build
+case "$build_alias" in
+NONE)
+ case $nonopt in
+ NONE) build_alias=$host_alias ;;
+ *) build_alias=$nonopt ;;
+ esac ;;
+esac
+
+build=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $build_alias`
+build_cpu=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+build_vendor=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+build_os=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+echo "$ac_t""$build" 1>&6
+
+test "$host_alias" != "$target_alias" &&
+ test "$program_prefix$program_suffix$program_transform_name" = \
+ NONENONEs,x,x, &&
+ program_prefix=${target_alias}-
+
+
+trap '' 1 2 15
+cat > confcache <<\EOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs. It is not useful on other systems.
+# If it contains results you don't want to keep, you may remove or edit it.
+#
+# By default, configure uses ./config.cache as the cache file,
+# creating it if it does not exist already. You can give configure
+# the --cache-file=FILE option to use a different cache file; that is
+# what configure does when it calls configure scripts in
+# subdirectories, so they share the cache.
+# Giving --cache-file=/dev/null disables caching, for debugging configure.
+# config.status only pays attention to the cache file if you give it the
+# --recheck option to rerun configure.
+#
+EOF
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, don't put newlines in cache variables' values.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(set) 2>&1 |
+ case `(ac_space=' '; set) 2>&1` in
+ *ac_space=\ *)
+ # `set' does not quote correctly, so add quotes (double-quote substitution
+ # turns \\\\ into \\, and sed turns \\ into \).
+ sed -n \
+ -e "s/'/'\\\\''/g" \
+ -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p"
+ ;;
+ *)
+ # `set' quotes correctly as required by POSIX, so do not add quotes.
+ sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p'
+ ;;
+ esac >> confcache
+if cmp -s $cache_file confcache; then
+ :
+else
+ if test -w $cache_file; then
+ echo "updating cache $cache_file"
+ cat confcache > $cache_file
+ else
+ echo "not updating unwritable cache $cache_file"
+ fi
+fi
+rm -f confcache
+
+trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+# Any assignment to VPATH causes Sun make to only execute
+# the first set of double-colon rules, so remove it if not needed.
+# If there is a colon in the path, we need to keep it.
+if test "x$srcdir" = x.; then
+ ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d'
+fi
+
+trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15
+
+# Transform confdefs.h into DEFS.
+# Protect against shell expansion while executing Makefile rules.
+# Protect against Makefile macro expansion.
+cat > conftest.defs <<\EOF
+s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%-D\1=\2%g
+s%[ `~#$^&*(){}\\|;'"<>?]%\\&%g
+s%\[%\\&%g
+s%\]%\\&%g
+s%\$%$$%g
+EOF
+DEFS=`sed -f conftest.defs confdefs.h | tr '\012' ' '`
+rm -f conftest.defs
+
+
+# Without the "./", some shells look in PATH for config.status.
+: ${CONFIG_STATUS=./config.status}
+
+echo creating $CONFIG_STATUS
+rm -f $CONFIG_STATUS
+cat > $CONFIG_STATUS <<EOF
+#! /bin/sh
+# Generated automatically by configure.
+# Run this file to recreate the current configuration.
+# This directory was configured as follows,
+# on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+#
+# $0 $ac_configure_args
+#
+# Compiler output produced by configure, useful for debugging
+# configure, is in ./config.log if it exists.
+
+ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]"
+for ac_option
+do
+ case "\$ac_option" in
+ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+ echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion"
+ exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;;
+ -version | --version | --versio | --versi | --vers | --ver | --ve | --v)
+ echo "$CONFIG_STATUS generated by autoconf version 2.12.1"
+ exit 0 ;;
+ -help | --help | --hel | --he | --h)
+ echo "\$ac_cs_usage"; exit 0 ;;
+ *) echo "\$ac_cs_usage"; exit 1 ;;
+ esac
+done
+
+ac_given_srcdir=$srcdir
+
+trap 'rm -fr `echo "Makefile" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15
+EOF
+cat >> $CONFIG_STATUS <<EOF
+
+# Protect against being on the right side of a sed subst in config.status.
+sed 's/%@/@@/; s/@%/@@/; s/%g\$/@g/; /@g\$/s/[\\\\&%]/\\\\&/g;
+ s/@@/%@/; s/@@/@%/; s/@g\$/%g/' > conftest.subs <<\\CEOF
+$ac_vpsub
+$extrasub
+s%@SHELL@%$SHELL%g
+s%@CFLAGS@%$CFLAGS%g
+s%@CPPFLAGS@%$CPPFLAGS%g
+s%@CXXFLAGS@%$CXXFLAGS%g
+s%@DEFS@%$DEFS%g
+s%@LDFLAGS@%$LDFLAGS%g
+s%@LIBS@%$LIBS%g
+s%@exec_prefix@%$exec_prefix%g
+s%@prefix@%$prefix%g
+s%@program_transform_name@%$program_transform_name%g
+s%@bindir@%$bindir%g
+s%@sbindir@%$sbindir%g
+s%@libexecdir@%$libexecdir%g
+s%@datadir@%$datadir%g
+s%@sysconfdir@%$sysconfdir%g
+s%@sharedstatedir@%$sharedstatedir%g
+s%@localstatedir@%$localstatedir%g
+s%@libdir@%$libdir%g
+s%@includedir@%$includedir%g
+s%@oldincludedir@%$oldincludedir%g
+s%@infodir@%$infodir%g
+s%@mandir@%$mandir%g
+s%@CC@%$CC%g
+s%@host@%$host%g
+s%@host_alias@%$host_alias%g
+s%@host_cpu@%$host_cpu%g
+s%@host_vendor@%$host_vendor%g
+s%@host_os@%$host_os%g
+s%@target@%$target%g
+s%@target_alias@%$target_alias%g
+s%@target_cpu@%$target_cpu%g
+s%@target_vendor@%$target_vendor%g
+s%@target_os@%$target_os%g
+s%@build@%$build%g
+s%@build_alias@%$build_alias%g
+s%@build_cpu@%$build_cpu%g
+s%@build_vendor@%$build_vendor%g
+s%@build_os@%$build_os%g
+
+CEOF
+EOF
+
+cat >> $CONFIG_STATUS <<\EOF
+
+# Split the substitutions into bite-sized pieces for seds with
+# small command number limits, like on Digital OSF/1 and HP-UX.
+ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script.
+ac_file=1 # Number of current file.
+ac_beg=1 # First line for current file.
+ac_end=$ac_max_sed_cmds # Line after last line for current file.
+ac_more_lines=:
+ac_sed_cmds=""
+while $ac_more_lines; do
+ if test $ac_beg -gt 1; then
+ sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file
+ else
+ sed "${ac_end}q" conftest.subs > conftest.s$ac_file
+ fi
+ if test ! -s conftest.s$ac_file; then
+ ac_more_lines=false
+ rm -f conftest.s$ac_file
+ else
+ if test -z "$ac_sed_cmds"; then
+ ac_sed_cmds="sed -f conftest.s$ac_file"
+ else
+ ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file"
+ fi
+ ac_file=`expr $ac_file + 1`
+ ac_beg=$ac_end
+ ac_end=`expr $ac_end + $ac_max_sed_cmds`
+ fi
+done
+if test -z "$ac_sed_cmds"; then
+ ac_sed_cmds=cat
+fi
+EOF
+
+cat >> $CONFIG_STATUS <<EOF
+
+CONFIG_FILES=\${CONFIG_FILES-"Makefile"}
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then
+ # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+ case "$ac_file" in
+ *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'`
+ ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
+ *) ac_file_in="${ac_file}.in" ;;
+ esac
+
+ # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories.
+
+ # Remove last slash and all that follows it. Not all systems have dirname.
+ ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
+ if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
+ # The file is in a subdirectory.
+ test ! -d "$ac_dir" && mkdir "$ac_dir"
+ ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`"
+ # A "../" for each directory in $ac_dir_suffix.
+ ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'`
+ else
+ ac_dir_suffix= ac_dots=
+ fi
+
+ case "$ac_given_srcdir" in
+ .) srcdir=.
+ if test -z "$ac_dots"; then top_srcdir=.
+ else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;;
+ /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;;
+ *) # Relative path.
+ srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix"
+ top_srcdir="$ac_dots$ac_given_srcdir" ;;
+ esac
+
+
+ echo creating "$ac_file"
+ rm -f "$ac_file"
+ configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure."
+ case "$ac_file" in
+ *Makefile*) ac_comsub="1i\\
+# $configure_input" ;;
+ *) ac_comsub= ;;
+ esac
+
+ ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"`
+ sed -e "$ac_comsub
+s%@configure_input@%$configure_input%g
+s%@srcdir@%$srcdir%g
+s%@top_srcdir@%$top_srcdir%g
+" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file
+fi; done
+rm -f conftest.s*
+
+EOF
+cat >> $CONFIG_STATUS <<EOF
+
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+
+exit 0
+EOF
+chmod +x $CONFIG_STATUS
+rm -fr confdefs* $ac_clean_files
+test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1
+
diff --git a/gdb/testsuite/gdb.trace/configure.in b/gdb/testsuite/gdb.trace/configure.in
new file mode 100644
index 00000000000..6d0eae2674b
--- /dev/null
+++ b/gdb/testsuite/gdb.trace/configure.in
@@ -0,0 +1,15 @@
+dnl Process this file file with autoconf to produce a configure script.
+dnl This file is a shell script fragment that supplies the information
+dnl necessary to tailor a template configure script into the configure
+dnl script appropriate for this directory. For more information, check
+dnl any existing configure script.
+
+AC_PREREQ(2.5)
+AC_INIT(collection.c)
+
+CC=${CC-cc}
+AC_SUBST(CC)
+AC_CONFIG_AUX_DIR(`cd $srcdir;pwd`/../../..)
+AC_CANONICAL_SYSTEM
+
+AC_OUTPUT(Makefile)
diff --git a/gdb/testsuite/gdb.trace/deltrace.exp b/gdb/testsuite/gdb.trace/deltrace.exp
new file mode 100644
index 00000000000..d3198ade0fc
--- /dev/null
+++ b/gdb/testsuite/gdb.trace/deltrace.exp
@@ -0,0 +1,269 @@
+# Copyright (C) 1998 Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file was written by Michael Snyder (msnyder@cygnus.com)
+
+load_lib "trace-support.exp";
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+set prms_id 0
+set bug_id 0
+
+gdb_exit
+gdb_start
+
+if [istarget "m68k-*-elf"] then {
+ set srcfile gdb_c_test.c
+ set binfile [board_info target d490_binfile];
+} else {
+ set testfile "actions"
+ set srcfile ${testfile}.c
+ set binfile $objdir/$subdir/$testfile
+ if { [gdb_compile "$srcdir/$subdir/$srcfile" $binfile \
+ executable {debug additional_flags=-w}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+ }
+}
+gdb_reinitialize_dir $srcdir/$subdir
+
+# If testing on a remote host, download the source file.
+# remote_download host $srcdir/$subdir/$srcfile
+
+gdb_file_cmd $binfile
+
+# define relative source line numbers:
+# all subsequent line numbers are relative to this first one (baseline)
+set baseline [gdb_find_recursion_test_baseline $srcfile];
+if { $baseline == -1 } then {
+ fail "Could not find gdb_recursion_test function"
+ return;
+}
+set testline1 [expr $baseline + 4]
+
+#
+# test "delete tracepoints" command
+#
+
+# 3.1 delete tracepoints (all)
+gdb_delete_tracepoints
+gdb_test "trace gdb_c_test" "Tracepoint \[0-9\]+ at .*" "set tracepoint 1"
+gdb_test "trace gdb_asm_test" "Tracepoint \[0-9\]+ at .*" "set tracepoint 2"
+gdb_test "trace $testline1" "Tracepoint \[0-9\]+ at .*" "set tracepoint 3"
+
+gdb_test "info tracepoints" \
+ "Num Enb Address PassC StepC What.*\[0-9\]+\[\t \]+y\[\t \]+0x\[0-9a-fA-F\]+.*in gdb_c_test.*\[0-9\]+\[\t \]+y\[\t \]+0x\[0-9a-fA-F\]+.*gdb_asm_test.*\[0-9\]+\[\t \]+y\[\t \]+0x\[0-9a-fA-F\]+.*in gdb_recursion_test.*" \
+ "3.1a: set three tracepoints"
+
+send_gdb "delete tracepoints\n"
+gdb_expect 30 {
+ -re "Delete all tracepoints.*y or n.*$" {
+ send_gdb "y\n"
+ gdb_expect 30 {
+ -re "$gdb_prompt $" {
+ pass "3.1b: delete all tracepoints"
+ }
+ timeout { fail "3.1b: delete all tracepoints (timeout)" }
+ }
+ }
+ -re "$gdb_prompt $" { # This should only happen if there are no tracepoints
+ fail "3.1b: delete all tracepoints (no tracepoints?)"
+ }
+ timeout { fail "3.1b: delete all tracepoints (timeout)" }
+}
+
+# 3.2 delete tracepoint <n>
+gdb_delete_tracepoints
+set trcpt1 [gdb_gettpnum gdb_c_test];
+set trcpt2 [gdb_gettpnum gdb_asm_test];
+set trcpt3 [gdb_gettpnum $testline1];
+if { $trcpt1 <= 0 || $trcpt2 <= 0 || $trcpt3 <= 0 } then {
+ fail "setting tracepoints"
+ return;
+}
+
+gdb_test "info tracepoints" \
+ "Num Enb Address PassC StepC What.*$trcpt1\[\t \]+y\[\t \]+0x\[0-9a-fA-F\]+.*in.*gdb_c_test.*$trcpt2\[\t \]+y\[\t \]+0x\[0-9a-fA-F\]+.*gdb_asm_test.*$trcpt3\[\t \]+y\[\t \]+0x\[0-9a-fA-F\]+.*in.*gdb_recursion_test.*" \
+ "3.2a: set three tracepoints"
+
+#gdb_test "delete tracepoint $trcpt1" "" ""
+send_gdb "delete tracepoint $trcpt1\n"
+gdb_expect {
+ -re "No tracepoint number.*$gdb_prompt $" {
+ fail "3.2b: delete first tracepoint"
+ }
+ -re ".*\[Ee\]rror.*$gdb_prompt $" {
+ fail "3.2b: delete first tracepoint"
+ }
+ -re "$gdb_prompt $" {
+ pass "3.2b: delete first tracepoint"
+ }
+ timeout {
+ fail "3.2b: delete first tracepoint (timeout)"
+ }
+}
+
+send_gdb "info tracepoints\n"
+gdb_expect {
+ -re "$trcpt1\[\t \]+y\[\t \]+0x.*in.*gdb_c_test.*$gdb_prompt $" {
+ fail "3.2c: verify delete first tracepoint (argh)"
+ }
+ -re "$trcpt2\[\t \]+y.*gdb_asm_test.*\[\r\n\t ]+$trcpt3\[\t \]+y.* in gdb_recursion_test at .*$gdb_prompt $" {
+ pass "3.2c: verify delete first tracepoint"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "3.2c: verify delete first tracepoint (mumble)"
+ }
+ timeout {
+ fail "3.2c: verify delete first tracepoint (timeout)"
+ }
+}
+
+#gdb_test "delete tracepoint $trcpt2" "" ""
+send_gdb "delete tracepoint $trcpt2\n"
+gdb_expect {
+ -re "No tracepoint number.*$gdb_prompt $" {
+ fail "3.2d: delete second tracepoint"
+ }
+ -re ".*\[Ee\]rror.*$gdb_prompt $" {
+ fail "3.2d: delete second tracepoint"
+ }
+ -re "$gdb_prompt $" {
+ pass "3.2d: delete second tracepoint"
+ }
+ timeout {
+ fail "3.2d: delete second tracepoint (timeout)"
+ }
+}
+
+send_gdb "info tracepoints\n"
+gdb_expect {
+ -re "$trcpt1\[\t \]+y\[\t \]+0x.*in.*gdb_c_test.*$gdb_prompt $" {
+ fail "3.2e: verify delete second tracepoint"
+ }
+ -re "$trcpt2\[\t \]+y\[\t \]+0x.*in gdb_asm_test.*$gdb_prompt $" {
+ fail "3.2e: verify delete second tracepoint"
+ }
+ -re "$trcpt3\[\t \]+y\[\t \]+0x.*in gdb_recursion_test.*$gdb_prompt $" {
+ pass "3.2e: verify delete second tracepoint"
+ }
+ -re "$gdb_prompt $" {
+ fail "3.2e: verify delete second tracepoint"
+ }
+ timeout {
+ fail "3.2e: verify delete second tracepoint (timeout)"
+ }
+}
+
+#gdb_test "delete tracepoint $trcpt3" "" ""
+send_gdb "delete tracepoint $trcpt3\n"
+gdb_expect {
+ -re "No tracepoint number.*$gdb_prompt $" {
+ fail "3.2f: delete third tracepoint"
+ }
+ -re ".*\[Ee\]rror.*$gdb_prompt $" {
+ fail "3.2f: delete third tracepoint"
+ }
+ -re "$gdb_prompt $" {
+ pass "3.2f: delete third tracepoint"
+ }
+ timeout {
+ fail "3.2f: delete third tracepoint (timeout)"
+ }
+}
+
+# send_gdb "ARF! \\n\n"
+send_gdb "info tracepoints\n"
+gdb_expect {
+ -re "$trcpt3\[\t \]+y\[\t \]+0x.*in gdb_recursion_test.*$gdb_prompt $" {
+ fail "3.2g: verify delete third tracepoint"
+ }
+ -re "$gdb_prompt $" {
+ pass "3.2g: verify delete third tracepoint"
+ }
+ timeout {
+ fail "3.2g: verify delete third tracepoint (timeout)"
+ }
+}
+
+# 3.3 delete three tracepoints at once
+gdb_delete_tracepoints
+set trcpt1 [gdb_gettpnum gdb_c_test];
+set trcpt2 [gdb_gettpnum gdb_asm_test];
+set trcpt3 [gdb_gettpnum $testline1];
+if { $trcpt1 <= 0 || $trcpt2 <= 0 || $trcpt3 <= 0 } then {
+ fail "setting tracepoints"
+ return;
+}
+
+gdb_test "info tracepoints" \
+ "Num Enb Address PassC StepC What.*$trcpt1\[\t \]+y\[\t \]+0x\[0-9a-fA-F\]+.*in gdb_c_test.*$trcpt2\[\t \]+y\[\t \]+0x\[0-9a-fA-F\]+.*gdb_asm_test.*$trcpt3\[\t \]+y\[\t \]+0x\[0-9a-fA-F\]+.*in gdb_recursion_test.*" \
+ "3.3a: set three tracepoints"
+
+#gdb_test "delete tracepoint $trcpt1 $trcpt2 $trcpt3" "" ""
+send_gdb "delete tracepoint $trcpt1 $trcpt2 $trcpt3\n"
+gdb_expect {
+ -re "No tracepoint number.*$gdb_prompt $" {
+ fail "3.3b: delete three tracepoints"
+ }
+ -re ".*\[Ee\]rror.*$gdb_prompt $" {
+ fail "3.3b: delete three tracepoints"
+ }
+ -re "$gdb_prompt $" {
+ pass "3.3b: delete three tracepoints"
+ }
+ timeout {
+ fail "3.3b: delete three tracepoint (timeout)"
+ }
+}
+
+send_gdb "info tracepoints\n"
+gdb_expect {
+ -re "$trcpt1\[\t \]+y\[\t \]+0x.*in gdb_c_test.*$gdb_prompt $" {
+ fail "3.3c: verify delete three tracepoints (first one persists)"
+ }
+ -re "$trcpt2\[\t \]+y\[\t \]+0x.*in gdb_asm_test.*$gdb_prompt $" {
+ fail "3.3c: verify delete three tracepoints (second one persists)"
+ }
+ -re "$trcpt3\[\t \]+y\[\t \]+0x.*in gdb_recursion_test.*$gdb_prompt $" {
+ fail "3.3c: verify delete three tracepoints (third one persists)"
+ }
+ -re "$gdb_prompt $" {
+ pass "3.3c: verify delete three tracepoints"
+ }
+ timeout {
+ fail "3.3c: verify delete three tracepoints (timeout)"
+ }
+}
+
+# 3.4 delete invalid tracepoint number
+gdb_test "delete tracepoint [expr $trcpt2 + $trcpt3]" \
+ "No tracepoint number [expr $trcpt2 + $trcpt3]." \
+ "3.4: delete invalid tracepoint number"
+
+# 3.5 delete tracepoint number zero
+gdb_test "delete tracepoint 0" "No tracepoint number 0." \
+ "3.5: delete tracepoint number zero"
+
+# 3.6 help delete tracepoints
+gdb_test "help delete tracepoints" \
+ "Delete specified tracepoints.*" \
+ "3.6: help delete tracepoints"
diff --git a/gdb/testsuite/gdb.trace/gdb_c_test.c b/gdb/testsuite/gdb.trace/gdb_c_test.c
new file mode 100644
index 00000000000..6447fb194c9
--- /dev/null
+++ b/gdb/testsuite/gdb.trace/gdb_c_test.c
@@ -0,0 +1,3792 @@
+/*
+ ******************************************************************************
+ ******************************************************************************
+ *
+ * COPYRIGHT (C) by EMC Corporation, 1997 All rights reserved.
+ * $Id$
+ * DESCRIPTION: This module has been provided for the purpose of testing GDB.
+ *
+ * NOTES:
+ *
+ ******************************************************************************
+ *****************************************************************************/
+
+/*=============================================================================
+ * INCLUDE FILES
+ *===========================================================================*/
+
+
+#ifdef DO_IT_BY_THE_BOOK
+
+
+#include "symtypes_defs.h"
+#include "printp.h"
+
+#include "adbg_expression.h"
+#include "common_hw_ds.h"
+#include "common_hw_defs.h"
+#include "evnttrac.h"
+#include "sym_scratch_ds.h"
+#include "symglob_ds.h"
+#include "sym_protglob_ds.h"
+
+#include "ether.h"
+
+#include <ctype.h>
+
+
+#else
+
+#include "adbg_dtc.h"
+
+#define YES 1
+#define NO 0
+
+#define TRUE 1
+#define FALSE 0
+
+#define ENABLED 1
+#define DISABLED 0
+
+#define CONTROL_C 3 /* ASCII 'ETX' */
+
+
+/*
+ * Faked after ctype.h
+ */
+
+#define isxdigit(X) (((X) >= '0' && (X) <= '9') || \
+ ((X) >= 'A' && (X) <= 'F') || \
+ ((X) >= 'a' && (X) <= 'f'))
+/*
+ * Borrowed from string.h
+ */
+
+extern unsigned int strlen ( const char * );
+
+/*
+ * Extracted from symtypes.h:
+ */
+
+typedef char BOOL; /* 8 Bits */
+typedef unsigned char UCHAR; /* 8 Bits */
+typedef unsigned short USHORT; /* 16 Bits */
+typedef unsigned long ULONG; /* 32 Bits */
+
+/*
+ * for struct t_expr_tag and
+ * decl of build_and_add_expression
+ */
+#include "adbg_expression.h"
+#define NULL 0
+
+/*
+ * Extracted from printp.h:
+ */
+
+extern void printp ( const char * fptr, ... );
+extern void sprintp ( const char * fptr, ... );
+
+/*
+ * Extracted from ether.h:
+ */
+
+extern long eth_to_gdb ( UCHAR *buf, long length );
+
+
+/*
+ * Derived from hwequs.s:
+ */
+
+#define CS_CODE_START 0x100000
+#define CS_CODE_SIZE 0x200000
+#define LAST_CS_WORD (CS_CODE_START + CS_CODE_SIZE - 2)
+
+#define sh_genstat1 (*((volatile ULONG *) 0xFFFFFE54))
+
+#define rs232_mode1 0 /* rs-232 mode 1 reg. */
+#define rs232_mode2 rs232_mode1 /* rs-232 mode 2 reg. */
+#define rs232_stat 4 /* rs-232 status reg. */
+#define rs232_clk rs232_stat /* rs-232 clock select reg. */
+#define rs232_cmd 8 /* rs-232 command reg */
+#define rs232_transmit 12 /* rs-232 transmit reg. */
+#define rs232_receive rs232_transmit /* rs-232 transmit reg. */
+#define rs232_aux 16 /* rs-232 aux control reg. */
+#define rs232_isr 20 /* rs-232 interrupt status reg. */
+#define rs232_imr rs232_isr /* rs-232 interrupt mask reg. */
+#define rs232_tc_high 24 /* rs-232 timer/counter high reg. */
+#define rs232_tc_low 28 /* rs-232 timer/counter low reg. */
+
+
+#endif
+
+
+/*============================================================================
+ * MODULE DEFINES
+ *===========================================================================*/
+
+#define P_RST_LAN_UART_REG ((volatile UCHAR *) 0xFFFFFE45)
+#define M_RST_LAN_UART 0x80 /* Bit 7 */
+
+#define P_LAN0TR_REG P_RST_LAN_UART_REG
+#define M_LAN0TR 0x20 /* Bit 5 */
+
+#define M_SH_GENCON_LAN0TR 0x00200000 /* Bit 21 */
+
+#define MAX_RS232_CHARS 512
+
+#define LAN_Q_MOD(X) ((X) % MAX_RS232_CHARS)
+
+/*---------------------------------------*
+ * LAN UART Registers *
+ *---------------------------------------*/
+
+#define LAN_UART_BASE ((ULONG) 0xfffffc22)
+
+/* Write-Read */
+
+#define P_LAN_MR1 ((volatile UCHAR *) (LAN_UART_BASE + ((ULONG) rs232_mode1 )))
+#define P_LAN_MR2 ((volatile UCHAR *) (LAN_UART_BASE + ((ULONG) rs232_mode2 )))
+
+/* Write-Only */
+
+#define P_LAN_ACR ((volatile UCHAR *) (LAN_UART_BASE + ((ULONG) rs232_aux )))
+#define P_LAN_CR ((volatile UCHAR *) (LAN_UART_BASE + ((ULONG) rs232_cmd )))
+#define P_LAN_CSR ((volatile UCHAR *) (LAN_UART_BASE + ((ULONG) rs232_clk )))
+#define P_LAN_CTLR ((volatile UCHAR *) (LAN_UART_BASE + ((ULONG) rs232_tc_low )))
+#define P_LAN_CTUR ((volatile UCHAR *) (LAN_UART_BASE + ((ULONG) rs232_tc_high )))
+#define P_LAN_IMR ((volatile UCHAR *) (LAN_UART_BASE + ((ULONG) rs232_imr )))
+
+/* Read-Only */
+
+#define P_LAN_SR ((volatile UCHAR *) (LAN_UART_BASE + ((ULONG) rs232_stat )))
+#define P_LAN_ISR ((volatile UCHAR *) (LAN_UART_BASE + ((ULONG) rs232_isr )))
+#define P_LAN_XMT ((volatile UCHAR *) (LAN_UART_BASE + ((ULONG) rs232_transmit)))
+#define P_LAN_RCV ((volatile UCHAR *) (LAN_UART_BASE + ((ULONG) rs232_receive )))
+
+/*
+ * Bit Values for Write-Read and Write-Only Registers
+ */
+
+#define DEFAULT_LAN_MR1 ((UCHAR) 0x13)
+#define DEFAULT_LAN_MR2 ((UCHAR) 0x07)
+#define DEFAULT_LAN_CSR ((UCHAR) 0xcc)
+#define DEFAULT_LAN_ACR ((UCHAR) 0x38)
+#define DEFAULT_LAN_CTUR ((UCHAR) 0xff)
+#define DEFAULT_LAN_CTLR ((UCHAR) 0xff)
+
+#define LAN_ACR_SELECT_BRG_0 DEFAULT_LAN_ACR
+#define LAN_ACR_SELECT_BRG_1 (DEFAULT_LAN_ACR | 0x80)
+
+#define UART_CR_RESET_MR_PTR ((UCHAR) 0x10) /* Reset MR pointer (points to MR1). */
+#define UART_CR_RESET_RVCR ((UCHAR) 0x20) /* Reset receiver (disabled). */
+#define UART_CR_RESET_XMTR ((UCHAR) 0x30) /* Reset transmitter (disabled). */
+#define UART_CR_RESET_ERROR_STATUS ((UCHAR) 0x40) /* Reset error status. */
+#define UART_CR_RESET_BRK_CHG_INT ((UCHAR) 0x50) /* Reset break change interrupt. */
+#define UART_CR_START_CNTR_TIMER ((UCHAR) 0x80) /* Start counter/timer. */
+#define UART_CR_STOP_CNTR ((UCHAR) 0x90) /* Stop counter. */
+
+#define UART_CR_DISABLE_XMTR ((UCHAR) 0x08) /* Disable transmitter. */
+#define UART_CR_ENABLE_XMTR ((UCHAR) 0x04) /* Enable transmitter. */
+#define UART_CR_DISABLE_RCVR ((UCHAR) 0x02) /* Disable receiver. */
+#define UART_CR_ENABLE_RCVR ((UCHAR) 0x01) /* Enable receiver. */
+
+#define UART_CSR_BR_4800 ((UCHAR) 0x99) /* With either BRG Set selected (via ACR). */
+#define UART_CSR_BR_9600 ((UCHAR) 0xbb) /* With either BRG Set selected (via ACR). */
+#define UART_CSR_BR_19200 ((UCHAR) 0xcc) /* With BRG Set '1' selected (via ACR). */
+#define UART_CSR_BR_38400 ((UCHAR) 0xcc) /* With BRG Set '0' selected (via ACR). */
+
+#define UART_IMR_RxRDY ((UCHAR) 0x04) /* Enable 'RxRDY' interrupt. */
+#define UART_IMR_TxEMT ((UCHAR) 0x02) /* Enable 'TxEMT' interrupt. */
+#define UART_IMR_TxRDY ((UCHAR) 0x01) /* Enable 'TxRDY' interrupt. */
+
+/*
+ * Bit Masks for Read-Only Registers
+ */
+
+#define M_UART_SR_RCVD_BRK 0x80 /* Bit 7 */
+#define M_UART_SR_FE 0x40 /* Bit 6 */
+#define M_UART_SR_PE 0x20 /* Bit 5 */
+#define M_UART_SR_OE 0x10 /* Bit 4 */
+#define M_UART_SR_TxEMT 0x08 /* Bit 3 */
+#define M_UART_SR_TxRDY 0x04 /* Bit 2 */
+#define M_UART_SR_FFULL 0x02 /* Bit 1 */
+#define M_UART_SR_RxRDY 0x01 /* Bit 0 */
+
+#define M_UART_ISR_RxRDY 0x04 /* Bit 2 */
+#define M_UART_ISR_TxEMT 0x02 /* Bit 1 */
+#define M_UART_ISR_TxRDY 0x01 /* Bit 0 */
+
+/*---------------------------------------*
+ * Support for 'Utility 83'. *
+ *---------------------------------------*/
+
+#define LAN_UTIL_CODE 0x83
+
+#define LAN_INIT ((ULONG) (('I' << 24) | ('N' << 16) | ('I' << 8) | 'T'))
+#define LAN_BAUD ((ULONG) (('B' << 24) | ('A' << 16) | ('U' << 8) | 'D'))
+#define LAN_INTR ((ULONG) (('I' << 24) | ('N' << 16) | ('T' << 8) | 'R'))
+#define LAN_XMT ((ULONG) (('X' << 16) | ('M' << 8) | 'T'))
+#define LAN_ECHO ((ULONG) (('E' << 24) | ('C' << 16) | ('H' << 8) | 'O'))
+#define LAN_STAT ((ULONG) (('S' << 24) | ('T' << 16) | ('A' << 8) | 'T'))
+#define LAN_IN ((ULONG) (('I' << 8) | 'N'))
+#define LAN_OUT ((ULONG) (('O' << 16) | ('U' << 8) | 'T'))
+
+#define LAN_PUTC ((ULONG) (('P' << 24) | ('U' << 16) | ('T' << 8) | 'C'))
+#define LAN_WPM ((ULONG) (('W' << 16) | ('P' << 8) | 'M'))
+
+#define STATUS(X) ( ( ( X ) == 0 ) ? "disabled" : "enabled" )
+
+#define XMT_VIA_BP_ENABLED() ( *P_LAN0TR_REG & M_LAN0TR ? 1 : 0 )
+
+#define TRAP_1_INST 0x4E41
+
+/*
+ * Bit #13 of shared genstat 1 indicates
+ * which processor we are as follows.
+ *
+ * 0 => X (side A)
+ * 1 => Y (side B)
+ */
+
+#define M_PROC_ID 0x00002000
+
+#define IS_SIDE_A() ( ( (sh_genstat1) & M_PROC_ID ) == 0 )
+#define IS_SIDE_B() ( (sh_genstat1) & M_PROC_ID )
+
+
+#ifdef STANDALONE /* Compile this module stand-alone for debugging */
+#define LAN_PUT_CHAR(X) printf("%c", X)
+#else
+#define LAN_PUT_CHAR(X) while ( lan_put_char( X ) )
+#endif
+
+
+
+
+#define VIA_RS232 0
+#define VIA_ETHERNET 1
+
+#define MAX_IO_BUF_SIZE 400
+
+#define MAX_BYTE_CODES 200 /* maximum length for bytecode string */
+
+
+static ULONG gdb_host_comm;
+
+static ULONG gdb_cat_ack;
+
+static char eth_outbuffer[ MAX_IO_BUF_SIZE + 1 ];
+
+
+#ifdef STANDALONE
+
+#define ACK_PKT() LAN_PUT_CHAR( '+' )
+#define NACK_PKT() LAN_PUT_CHAR( '-' )
+
+#else
+
+#define ACK_PKT() { \
+ if ( VIA_ETHERNET == gdb_host_comm ) \
+ { \
+ gdb_cat_ack = YES; \
+ } \
+ else \
+ { \
+ LAN_PUT_CHAR( '+' ); \
+ } \
+ }
+
+
+
+#define NACK_PKT() { \
+ if ( VIA_ETHERNET == gdb_host_comm ) \
+ { \
+ eth_outbuffer[ 0 ] = '-'; \
+ eth_to_gdb( (UCHAR *) eth_outbuffer, 1 ); \
+ } \
+ else \
+ { \
+ LAN_PUT_CHAR( '-' ); \
+ } \
+ }
+
+#endif
+
+
+
+
+/*============================================================================
+ * MODULE TYPEDEFS
+ *===========================================================================*/
+
+typedef struct rs232_queue {
+
+ long head_index;
+
+ long tail_index;
+
+ ULONG overflows;
+
+ long gdb_packet_start;
+ long gdb_packet_end;
+ long gdb_packet_csum1;
+ long gdb_packet_csum2;
+
+ UCHAR buf[ MAX_RS232_CHARS ];
+
+} T_RS232_QUEUE;
+
+
+
+
+/*=============================================================================
+ * EXTERNAL GLOBAL VARIABLES
+ *===========================================================================*/
+
+extern volatile UCHAR sss_trace_flag;
+
+
+/*=============================================================================
+ * STATIC MODULE DECLARATIONS
+ *===========================================================================*/
+
+static T_RS232_QUEUE lan_input_queue,
+ lan_output_queue;
+
+static BOOL test_echo;
+
+#if 0
+/* The stub no longer seems to use this. */
+static BOOL write_access_enabled;
+#endif
+
+static int baud_rate_idx;
+
+static ULONG tx_by_intr,
+ tx_by_poll;
+
+static UCHAR lan_shadow_imr;
+
+
+/*=============================================================================
+ * EXTERNAL FUNCTION PROTOTYPES
+ *===========================================================================*/
+
+extern long write_to_protected_mem( void *address, unsigned short value );
+
+
+/*=============================================================================
+ * MODULE GLOBAL FUNCTIONS PROTOTYPES
+ *===========================================================================*/
+
+ULONG gdb_c_test( ULONG *parm );
+
+
+void lan_init( void );
+
+void lan_isr( void );
+
+long lan_get_char( void );
+
+long lan_put_char( UCHAR c );
+
+ULONG lan_util( ULONG *parm );
+
+
+/*=============================================================================
+ * MODULE LOCAL FUNCTION PROTOTYPES
+ *===========================================================================*/
+
+static void lan_reset( void );
+
+static void lan_configure( void );
+
+static void lan_init_queue( T_RS232_QUEUE *p_queue );
+
+static void lan_add_to_queue( long c, T_RS232_QUEUE *p_queue );
+
+static UCHAR lan_next_queue_char( T_RS232_QUEUE *p_queue );
+
+static void lan_util_menu( void );
+
+static long get_gdb_input( long c, T_RS232_QUEUE *p_input_q );
+
+
+/*=============================================================================
+ * GDB STUB FUNCTION PROTOTYPES
+ *===========================================================================*/
+
+void gdb_trap_1_handler( void );
+void gdb_trace_handler ( void );
+
+void gdb_get_eth_input( unsigned char *buf, long length );
+
+static void getpacket ( void );
+static void putpacket ( char * );
+static void discard_packet ( void );
+
+#ifdef STANDALONE /* Compile this module stand-alone for debugging */
+#include <stdio.h>
+#define printp printf /* easier than declaring a local varargs stub func. */
+#endif /* STANDALONE */
+
+
+/*=============================================================================
+ * MODULE BODY
+ *===========================================================================*/
+
+/* ------------------- Things that belong in a header file --------------- */
+extern char *memset (char *, int, int);
+
+ /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*
+ * *
+ * Global Module Functions *
+ * *
+ *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+
+static char gdb_char_test;
+static short gdb_short_test;
+static long gdb_long_test;
+static char gdb_arr_test[25];
+static struct GDB_STRUCT_TEST
+{
+ char c;
+ short s;
+ long l;
+ int bfield : 11; /* collect bitfield */
+ char arr[25];
+ struct GDB_STRUCT_TEST *next;
+} gdb_struct1_test, gdb_struct2_test, *gdb_structp_test, **gdb_structpp_test;
+
+static union GDB_UNION_TEST
+{
+ char c;
+ short s;
+ long l;
+ int bfield : 11; /* collect bitfield */
+ char arr[4];
+ union GDB_UNION_TEST *next;
+} gdb_union1_test;
+
+void gdb_recursion_test (int, int, int, int, int, int, int);
+
+void gdb_recursion_test (int depth,
+ int q1,
+ int q2,
+ int q3,
+ int q4,
+ int q5,
+ int q6)
+{ /* gdb_recursion_test line 0 */
+ int q = q1; /* gdbtestline 1 */
+
+ q1 = q2; /* gdbtestline 2 */
+ q2 = q3; /* gdbtestline 3 */
+ q3 = q4; /* gdbtestline 4 */
+ q4 = q5; /* gdbtestline 5 */
+ q5 = q6; /* gdbtestline 6 */
+ q6 = q; /* gdbtestline 7 */
+ if (depth--) /* gdbtestline 8 */
+ gdb_recursion_test (depth, q1, q2, q3, q4, q5, q6); /* gdbtestline 9 */
+}
+
+
+ULONG gdb_c_test( ULONG *parm )
+
+{
+ char *p = "gdb_c_test";
+ char *rediculously_long_variable_name_with_equally_long_string_assignment;
+ register long local_reg = 7;
+ static unsigned long local_static, local_static_sizeof;
+ long local_long;
+ unsigned long *stack_ptr;
+ unsigned long end_of_stack;
+
+ rediculously_long_variable_name_with_equally_long_string_assignment =
+ "rediculously long variable name with equally long string assignment";
+ local_static = 9;
+ local_static_sizeof = sizeof (struct GDB_STRUCT_TEST);
+ local_long = local_reg + 1;
+ stack_ptr = (unsigned long *) &local_long;
+ end_of_stack =
+ (unsigned long) &stack_ptr + sizeof(stack_ptr) + sizeof(end_of_stack) - 1;
+
+ printp ("\n$Id$\n");
+
+ printp( "%s: arguments = %X, %X, %X, %X, %X, %X\n",
+ p, parm[ 1 ], parm[ 2 ], parm[ 3 ], parm[ 4 ], parm[ 5 ], parm[ 6 ] );
+
+ gdb_char_test = gdb_struct1_test.c = (char) ((long) parm[1] & 0xff);
+ gdb_short_test = gdb_struct1_test.s = (short) ((long) parm[2] & 0xffff);
+ gdb_long_test = gdb_struct1_test.l = (long) ((long) parm[3] & 0xffffffff);
+ gdb_union1_test.l = (long) parm[4];
+ gdb_arr_test[0] = gdb_struct1_test.arr[0] = (char) ((long) parm[1] & 0xff);
+ gdb_arr_test[1] = gdb_struct1_test.arr[1] = (char) ((long) parm[2] & 0xff);
+ gdb_arr_test[2] = gdb_struct1_test.arr[2] = (char) ((long) parm[3] & 0xff);
+ gdb_arr_test[3] = gdb_struct1_test.arr[3] = (char) ((long) parm[4] & 0xff);
+ gdb_arr_test[4] = gdb_struct1_test.arr[4] = (char) ((long) parm[5] & 0xff);
+ gdb_arr_test[5] = gdb_struct1_test.arr[5] = (char) ((long) parm[6] & 0xff);
+ gdb_struct1_test.bfield = 144;
+ gdb_struct1_test.next = &gdb_struct2_test;
+ gdb_structp_test = &gdb_struct1_test;
+ gdb_structpp_test = &gdb_structp_test;
+
+ gdb_recursion_test (3, (long) parm[1], (long) parm[2], (long) parm[3],
+ (long) parm[4], (long) parm[5], (long) parm[6]);
+
+ gdb_char_test = gdb_short_test = gdb_long_test = 0;
+ gdb_structp_test = (void *) 0;
+ gdb_structpp_test = (void *) 0;
+ memset ((char *) &gdb_struct1_test, 0, sizeof (gdb_struct1_test));
+ memset ((char *) &gdb_struct2_test, 0, sizeof (gdb_struct2_test));
+ local_static_sizeof = 0;
+ local_static = 0;
+ return ( (ULONG) 0 );
+}
+
+
+/*-----------------------------------------------------------------------------
+ *
+ * FUNCTION NAME: lan_init
+ *
+ *
+ * DESCRIPTION:
+ *
+ *
+ * RETURN VALUE:
+ *
+ *
+ * USED GLOBAL VARIABLES:
+ *
+ *
+ * AFFECTED GLOBAL VARIABLES/SIDE EFFECTS:
+ *
+ *
+ * NOTES:
+ *
+ *
+ *
+ *---------------------------------------------------------------------------*/
+
+void lan_init( void )
+
+{
+
+ if ( IS_SIDE_A( ) )
+ {
+
+ lan_reset( );
+
+ lan_init_queue( &lan_input_queue );
+
+ lan_init_queue( &lan_output_queue );
+
+ lan_configure( );
+ }
+
+ return;
+}
+/* end of 'lan_init'
+ *===========================================================================*/
+
+
+/*-----------------------------------------------------------------------------
+ *
+ * FUNCTION NAME: lan_isr
+ *
+ *
+ * DESCRIPTION:
+ *
+ *
+ * RETURN VALUE: None.
+ *
+ *
+ * USED GLOBAL VARIABLES:
+ *
+ *
+ * AFFECTED GLOBAL VARIABLES/SIDE EFFECTS:
+ *
+ *
+ * NOTES:
+ *
+ *
+ *---------------------------------------------------------------------------*/
+
+void lan_isr( void )
+
+{
+ UCHAR c;
+
+
+ lan_shadow_imr = 0; /* Disable all UART interrupts. */
+ *P_LAN_IMR = lan_shadow_imr;
+
+
+ if ( *P_LAN_ISR & M_UART_ISR_RxRDY )
+ {
+
+ gdb_host_comm = VIA_RS232;
+
+ c = *P_LAN_RCV;
+
+ if ( test_echo )
+ {
+ /* ????? */
+ }
+
+ if ( c == CONTROL_C )
+ {
+ /* can't stop the target, but we can tell gdb to stop waiting... */
+ discard_packet( );
+ putpacket( "S03" ); /* send back SIGINT to the debugger */
+ }
+
+ else
+ {
+ lan_add_to_queue( (long) c, &lan_input_queue );
+ get_gdb_input( (long) c, &lan_input_queue );
+ }
+
+ }
+
+ if ( XMT_VIA_BP_ENABLED( ) )
+ {
+
+ c = 0;
+
+ while ( (*P_LAN_ISR & M_UART_ISR_TxRDY) && (c = lan_next_queue_char( &lan_output_queue )) )
+ {
+ *P_LAN_XMT = c;
+ ++tx_by_intr;
+ }
+
+ if ( c )
+ {
+ lan_shadow_imr |= UART_IMR_TxRDY; /* (Re-)Enable 'TxRDY' interrupt from UART. */
+ }
+
+ }
+
+
+ lan_shadow_imr |= UART_IMR_RxRDY; /* Re-Enable 'RxRDY' interrupt from UART. */
+ *P_LAN_IMR = lan_shadow_imr;
+
+
+
+ return;
+}
+/* end of 'lan_isr'
+ *===========================================================================*/
+
+
+/*-----------------------------------------------------------------------------
+ *
+ * FUNCTION NAME: lan_get_char
+ *
+ *
+ * DESCRIPTION: Fetches a character from the UART.
+ *
+ *
+ * RETURN VALUE: 0 on success, -1 on failure.
+ *
+ *
+ * USED GLOBAL VARIABLES:
+ *
+ *
+ * AFFECTED GLOBAL VARIABLES/SIDE EFFECTS:
+ *
+ *
+ * NOTES:
+ *
+ *
+ *---------------------------------------------------------------------------*/
+
+long lan_get_char( void )
+
+{
+ long status = -2; /* AGD: nothing found in rcv buffer */
+
+ if ( *P_LAN_SR & M_UART_SR_RxRDY )
+ {
+ char c = (char) *P_LAN_RCV;
+
+ if ( test_echo )
+ {
+ LAN_PUT_CHAR ( c );
+ }
+
+ if ( c == CONTROL_C )
+ {
+ /* can't stop the target, but we can tell gdb to stop waiting... */
+ discard_packet( );
+ putpacket( "S03" ); /* send back SIGINT to the debugger */
+ status = 0; /* success */
+ }
+
+ else
+ {
+ lan_add_to_queue( (long) c, &lan_input_queue );
+ status = get_gdb_input( (long) c, &lan_input_queue );
+ }
+
+ }
+
+ return( status );
+}
+/* end of 'lan_get_char'
+ *===========================================================================*/
+
+
+/*-----------------------------------------------------------------------------
+ *
+ * FUNCTION NAME: lan_put_char
+ *
+ * DESCRIPTION: Puts a character out via the UART.
+ *
+ * RETURN VALUE: 0 on success, -1 on failure.
+ *
+ * USED GLOBAL VARIABLES: none.
+ *
+ * AFFECTED GLOBAL VARIABLES/SIDE EFFECTS:
+ *
+ * NOTES: !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ * !! !!
+ * !! If 'XMT_VIA_BP_ENABLED()' is FALSE then output is THROWN AWAY. !!
+ * !! This prevents anyone infinite-looping on this function. !!
+ * !! !!
+ * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ *
+ *---------------------------------------------------------------------------*/
+
+long lan_put_char( UCHAR c )
+
+{
+ long status = -1;
+
+ if ( XMT_VIA_BP_ENABLED( ) )
+ {
+
+ if ( *P_LAN_SR & M_UART_SR_TxRDY )
+ {
+ lan_add_to_queue( (long) c, &lan_output_queue );
+
+ c = lan_next_queue_char( &lan_output_queue );
+
+ *P_LAN_XMT = c;
+ ++tx_by_poll;
+ status = 0;
+ }
+#if 0
+ else
+ {
+ status = 0;
+ lan_shadow_imr |= UART_IMR_TxRDY; /* Enable 'TxRDY' interrupt from UART. */
+ *P_LAN_IMR = lan_shadow_imr;
+ }
+#endif
+ }
+
+ else
+ {
+ status = 0; /* You lose: input character goes to the bit bucket. */
+ }
+
+ return( status );
+}
+/* end of 'lan_put_char'
+ *===========================================================================*/
+
+
+/*-----------------------------------------------------------------------------
+ *
+ * FUNCTION NAME: lan_util
+ *
+ * DESCRIPTION:
+ *
+ * RETURN VALUE:
+ *
+ * USED GLOBAL VARIABLES:
+ *
+ * AFFECTED GLOBAL VARIABLES/SIDE EFFECTS:
+ *
+ * NOTES:
+ *
+ *---------------------------------------------------------------------------*/
+
+ULONG lan_util( ULONG *parm )
+
+{
+
+
+ static const struct {
+
+ ULONG rate_code;
+ UCHAR acr_setting;
+ UCHAR csr_setting;
+
+ } baud_rate_setting [] = {
+
+ { 0x38400, LAN_ACR_SELECT_BRG_0, UART_CSR_BR_38400 },
+ { 0x19200, LAN_ACR_SELECT_BRG_1, UART_CSR_BR_19200 },
+ { 0x9600, LAN_ACR_SELECT_BRG_0, UART_CSR_BR_9600 },
+ { 0x4800, LAN_ACR_SELECT_BRG_0, UART_CSR_BR_4800 }
+ };
+
+
+#define BOGUS_P1 0xE1
+#define BOGUS_P2 0xE2
+
+ ULONG not_done_code;
+
+
+ ULONG opcode;
+ ULONG parm_1;
+ ULONG parm_2;
+
+ int i;
+ UCHAR c;
+
+
+ not_done_code = 0;
+
+ opcode = parm[ 1 ];
+ parm_1 = parm[ 2 ];
+ parm_2 = parm[ 3 ];
+
+
+ switch ( opcode )
+ {
+
+ case LAN_INIT:
+ {
+
+ lan_init( );
+ printp( "\n\n Interface (Re)Initialized ...\n\n" );
+
+ break;
+ }
+
+
+ case LAN_BAUD:
+ {
+
+ for ( i = 0; i < (int)(sizeof(baud_rate_setting) / sizeof(baud_rate_setting[0])); i ++ )
+ {
+ if ( baud_rate_setting[i].rate_code == parm_1 )
+ {
+ baud_rate_idx = i;
+ *P_LAN_ACR = baud_rate_setting[i].acr_setting;
+ *P_LAN_CSR = baud_rate_setting[i].csr_setting;
+ printp ( "Baud rate set to %X!\n", baud_rate_setting[i].rate_code );
+ return( not_done_code );
+ }
+ }
+
+ printp( "\n\n *** SYNTAX Error - Invalid baudrate (P2)\n\n" );
+ not_done_code = BOGUS_P2;
+
+ break;
+ }
+
+
+ case LAN_INTR:
+ {
+
+ switch ( parm_1 )
+ {
+
+ case 0x0D: /* Disable 'RxRDY' Interrupts */
+ {
+ lan_shadow_imr &= ~UART_IMR_RxRDY;
+ *P_LAN_IMR = lan_shadow_imr;
+ printp( "\n\n Receive Ready Interrupts DISABLED ...\n\n" );
+ break;
+ }
+
+ case 0x0E: /* Enable 'RxRDY' Interrupts */
+ {
+ lan_shadow_imr |= UART_IMR_RxRDY;
+ *P_LAN_IMR = lan_shadow_imr;
+ printp( "\n\n Receive Ready Interrupts ENABLED ...\n\n" );
+ break;
+ }
+
+ default:
+ {
+ printp( "\n\n *** SYNTAX Error - Invalid P2 (use D or E)\n\n" );
+ not_done_code = BOGUS_P2;
+ }
+ }
+
+ break;
+ }
+
+
+ case LAN_XMT:
+ {
+
+ switch ( parm_1 )
+ {
+
+ case 0x0E: /* Enable Transmission-via-Backplane */
+ {
+ if ( !(*P_LAN0TR_REG & M_LAN0TR) )
+ {
+ *P_LAN0TR_REG |= M_LAN0TR; /* 0 -> 1 */
+ }
+
+ printp( "\n\n Transmit-via-Backplane ENABLED ...\n\n" );
+ break;
+ }
+
+ case 0x0D: /* Disable Transmission-via-Backplane */
+ {
+ if ( *P_LAN0TR_REG & M_LAN0TR )
+ {
+ *P_LAN0TR_REG &= ~M_LAN0TR; /* 1 -> 0 */
+ }
+
+ printp( "\n\n Transmit-via-Backplane DISABLED ...\n\n" );
+ break;
+ }
+
+ default:
+ {
+ printp( "\n\n *** SYNTAX Error - Invalid P2 (use D or E)\n\n" );
+ not_done_code = BOGUS_P2;
+ lan_util_menu( );
+ }
+ }
+
+ break;
+ }
+
+
+ case LAN_STAT:
+ {
+
+ printp( "\n -- Status --\n\n" );
+
+ printp( " Baud Rate: %X *\n", baud_rate_setting[ baud_rate_idx ].rate_code );
+ printp( " Xmt-via-BP: %s *\n", STATUS( XMT_VIA_BP_ENABLED( ) ) );
+ printp( " RxRdy Intr: %s *\n", STATUS( (lan_shadow_imr & M_UART_ISR_RxRDY) ) );
+ /*** printp( " TxRdy Intr: %s\n", STATUS( (lan_shadow_imr & M_UART_ISR_TxRDY) ) ); ***/
+ printp( " Echo: %s *\n\n", STATUS( test_echo ) );
+
+ printp( " IMR: %02X\n", (ULONG) lan_shadow_imr );
+ printp( " ISR: %02X\n", (ULONG) *P_LAN_ISR );
+ printp( " SR: %02X\n\n", (ULONG) *P_LAN_SR );
+
+ printp( " Input Overflows: %d\n\n", lan_input_queue.overflows );
+
+ printp( " Tx by Intr: %d\n", tx_by_intr );
+ printp( " Tx by Poll: %d\n\n", tx_by_poll );
+
+ printp( " * Can be set or toggled via Utility %2X.\n\n", (ULONG) LAN_UTIL_CODE );
+
+ break;
+ }
+
+
+ case LAN_IN:
+ {
+
+ switch ( parm_1 )
+ {
+
+ case 0x0C: /* Clear and Reset Queue */
+ {
+ lan_init_queue( &lan_input_queue );
+ printp( "\n\n Queue CLEARED/RESET ...\n\n" );
+ break;
+ }
+
+ case 0x0D: /* Display Queue */
+ {
+ printp( "\n -- Input Queue --\n" );
+ printp( "\n Head Index: %8X Tail Index: %8X\n\n ",
+ (ULONG) lan_input_queue.head_index, (ULONG) lan_input_queue.tail_index );
+
+ for ( i = 0; i < MAX_RS232_CHARS; ++i )
+ {
+ printp( " %02X", (ULONG) lan_input_queue.buf[ i ] );
+
+ if ( 15 == (i % 16) )
+ {
+ int j;
+
+ printp ( " " );
+ for ( j = i - 15; j <= i; j++ )
+ {
+ if ( lan_input_queue.buf[ j ] >= ' ' &&
+ lan_input_queue.buf[ j ] < 127 )
+ printp ( "%c", lan_input_queue.buf[ j ] );
+ else
+ printp ( "." );
+ }
+ printp( "\n " );
+ }
+
+ else if ( 7 == (i % 8) )
+ {
+ printp( " " );
+ }
+
+ }
+
+ printp( "\n" );
+
+ break;
+ }
+
+ case 0x0F: /* Fetch next character in Queue */
+ {
+ c = lan_next_queue_char( &lan_input_queue );
+
+ if ( c )
+ {
+ printp( "\n\n Next Character: " );
+ if ( 0x21 <= c && c <= 0x7F )
+ {
+ printp( "%c\n\n", (ULONG) c );
+ }
+
+ else if ( 0x20 == ((UCHAR) c) )
+ {
+ printp( "<space>\n\n" );
+ }
+
+ else
+ {
+ printp( "%02X\n\n", (ULONG) c );
+ }
+ }
+
+ else
+ {
+ printp( "\n\n Input Queue EMPTY ...\n\n" );
+ }
+
+ break;
+ }
+
+ default:
+ {
+ printp( "\n\n *** SYNTAX Error - Invalid P2 ...\n\n" );
+ not_done_code = BOGUS_P2;
+ break;
+ }
+ }
+
+ break;
+ }
+
+
+ case LAN_OUT:
+ {
+
+ switch ( parm_1 )
+ {
+
+ case 0x0C: /* Clear and Reset Queue */
+ {
+ lan_init_queue( &lan_output_queue );
+ printp( "\n\n Queue CLEARED/RESET ...\n\n" );
+ break;
+ }
+
+ case 0x0D: /* Display Queue */
+ {
+ printp( "\n -- Output Queue --\n" );
+ printp( "\n Head Index: %8X Tail Index: %8X\n\n ",
+ (ULONG) lan_output_queue.head_index, (ULONG) lan_output_queue.tail_index );
+
+ for ( i = 0; i < MAX_RS232_CHARS; ++i )
+ {
+ printp( " %02X", (ULONG) lan_output_queue.buf[ i ] );
+
+ if ( 15 == (i % 16) )
+ {
+ int j;
+
+ printp ( " " );
+ for ( j = i - 15; j <= i; j++ )
+ {
+ if ( lan_output_queue.buf[ j ] >= ' ' &&
+ lan_output_queue.buf[ j ] < 127 )
+ printp ( "%c", lan_output_queue.buf[ j ] );
+ else
+ printp ( "." );
+ }
+ printp( "\n " );
+ }
+
+ else if ( 7 == (i % 8) )
+ {
+ printp( " " );
+ }
+
+ }
+
+ printp( "\n" );
+
+ break;
+ }
+
+ case 0x0F: /* Fetch next character in Queue */
+ {
+ c = lan_next_queue_char( &lan_output_queue );
+
+ if ( c )
+ {
+ printp( "\n\n Next Character: " );
+ if ( 0x21 <= c && c <= 0x7F )
+ {
+ printp( "%c\n\n", (ULONG) c );
+ }
+
+ else if ( 0x20 == c )
+ {
+ printp( "<space>\n\n" );
+ }
+
+ else
+ {
+ printp( "%02X\n\n", (ULONG) c );
+ }
+ }
+
+ else
+ {
+ printp( "\n\n Input Queue EMPTY ...\n\n" );
+ }
+
+ break;
+ }
+
+ default:
+ {
+ printp( "\n\n *** SYNTAX Error - Invalid P2 ...\n\n" );
+ not_done_code = BOGUS_P2;
+ break;
+ }
+ }
+
+ break;
+ }
+
+
+ case LAN_ECHO:
+ {
+
+ switch ( parm_1 )
+ {
+
+ case 0x0E:
+ {
+ test_echo = ENABLED;
+ printp( "\n\n Test echo ENABLED ...\n\n" );
+ break;
+ }
+
+ case 0x0D:
+ {
+ test_echo = DISABLED;
+ printp( "\n\n Test echo DISABLED ...\n\n" );
+ break;
+ }
+
+ default:
+ {
+ printp( "\n\n *** SYNTAX Error - Invalid P2 ...\n\n" );
+ not_done_code = BOGUS_P2;
+ break;
+ }
+ }
+
+ break;
+ }
+
+
+ case LAN_PUTC:
+ {
+
+ if ( 0x20 < parm_1 && parm_1 < 0x7F )
+ {
+ if ( lan_put_char( (UCHAR) parm_1 ) )
+ {
+ printp( "\n\n *** 'lan_put_char' Error ...\n" );
+ }
+
+ else
+ {
+ printp( "\n\n O.K. ...\n" );
+ }
+
+ }
+
+ else
+ {
+ printp( "\n\n *** Error - character must be in the 0x21-0x7E range ...\n" );
+ not_done_code = BOGUS_P2;
+ }
+
+ break;
+ }
+
+/***
+ case LAN_WPM:
+ {
+
+ if ( write_to_protected_mem( (void *) parm_1, (unsigned short) parm_2 ) )
+ {
+ printp( "\n Write to protected memory FAILED ...\n" );
+ }
+
+ break;
+ }
+***/
+
+ case 0: /* no argument -- print menu */
+ {
+ lan_util_menu( );
+ break;
+ }
+
+
+ default:
+ {
+ parm_2 = 0; /* to supress compiler warning with 'LAN_WPM' case disabled */
+
+ printp( "\n\n *** SYNTAX Error - Invalid P1 ...\n\n" );
+ not_done_code = BOGUS_P1;
+ break;
+ }
+
+
+ } /* End of 'switch ( opcode )'. */
+
+
+return( not_done_code );
+}
+/* end of 'lan_util'
+ *===========================================================================*/
+
+
+ /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*
+ * *
+ * Local Module Functions *
+ * *
+ *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+/*-----------------------------------------------------------------------------
+ *
+ * FUNCTION NAME: lan_reset
+ *
+ * DESCRIPTION: Resets the LAN UART by strobing the 'RST_LAN_UART' bit in the
+ * Shared Control 1 area.
+ *
+ * 1 _| ______
+ * | | |
+ * Bit | | |
+ * | | |
+ * 0 _|______| |______
+ * |---------------------> t
+ *
+ * RETURN VALUE: None.
+ *
+ * USED GLOBAL VARIABLES:
+ *
+ * AFFECTED GLOBAL VARIABLES/SIDE EFFECTS:
+ *
+ * NOTES: H/W configuration requires that a byte in the shared
+ * control 1 area must be read before being written.
+ *
+ *---------------------------------------------------------------------------*/
+
+static void lan_reset( void )
+
+{
+
+ while ( *P_RST_LAN_UART_REG & M_RST_LAN_UART )
+ {
+ *P_RST_LAN_UART_REG &= ~M_RST_LAN_UART; /* 0 */
+ }
+
+ while ( !(*P_RST_LAN_UART_REG & M_RST_LAN_UART) )
+ {
+ *P_RST_LAN_UART_REG |= M_RST_LAN_UART; /* 1 */
+ }
+
+ while ( *P_RST_LAN_UART_REG & M_RST_LAN_UART )
+ {
+ *P_RST_LAN_UART_REG &= ~M_RST_LAN_UART; /* 0 */
+ }
+
+}
+/* end of 'lan_reset'
+ *===========================================================================*/
+
+
+/*-----------------------------------------------------------------------------
+ *
+ * FUNCTION NAME: lan_configure
+ *
+ *
+ * DESCRIPTION:
+ *
+ *
+ * RETURN VALUE:
+ *
+ *
+ * USED GLOBAL VARIABLES:
+ *
+ *
+ * AFFECTED GLOBAL VARIABLES/SIDE EFFECTS:
+ *
+ *
+ * NOTES:
+ *
+ *
+ *
+ *---------------------------------------------------------------------------*/
+
+static void lan_configure( void )
+
+{
+
+ *P_LAN_CR = UART_CR_RESET_MR_PTR; /* Points to MR1. */
+ *P_LAN_CR = UART_CR_RESET_RVCR; /* Receiver disabled. */
+ *P_LAN_CR = UART_CR_RESET_XMTR; /* Transmitter disabled. */
+ *P_LAN_CR = UART_CR_RESET_ERROR_STATUS;
+ *P_LAN_CR = UART_CR_RESET_BRK_CHG_INT;
+
+ *P_LAN_MR1 = DEFAULT_LAN_MR1;
+ *P_LAN_MR2 = DEFAULT_LAN_MR2;
+
+ *P_LAN_ACR = DEFAULT_LAN_ACR;
+
+ *P_LAN_CSR = UART_CSR_BR_9600;
+ baud_rate_idx = 2;
+
+ *P_LAN_CTUR = DEFAULT_LAN_CTUR;
+ *P_LAN_CTLR = DEFAULT_LAN_CTLR;
+
+ *P_LAN_CR = (UART_CR_START_CNTR_TIMER | UART_CR_ENABLE_XMTR | UART_CR_ENABLE_RCVR);
+
+ lan_shadow_imr = UART_IMR_RxRDY; /* Enable only 'RxRDY' interrupt from UART. */
+ *P_LAN_IMR = lan_shadow_imr;
+
+ tx_by_intr = 0;
+ tx_by_poll = 0;
+
+ return;
+}
+/* end of 'lan_configure'
+ *===========================================================================*/
+
+
+/*-----------------------------------------------------------------------------
+ *
+ * FUNCTION NAME: lan_init_queue
+ *
+ * DESCRIPTION:
+ *
+ * RETURN VALUE: None.
+ *
+ * USED GLOBAL VARIABLES:
+ *
+ * AFFECTED GLOBAL VARIABLES/SIDE EFFECTS:
+ *
+ * NOTES:
+ *
+ *---------------------------------------------------------------------------*/
+
+static void lan_init_queue( T_RS232_QUEUE *p_queue )
+
+{
+ long i;
+
+ /*
+ * We set "head" equal to "tail" implying the queue is empty,
+ * BUT the "head" and "tail" should each point to valid queue
+ * positions.
+ */
+
+ p_queue->head_index = 0;
+ p_queue->tail_index = 0;
+
+ p_queue->overflows = 0;
+
+ p_queue->gdb_packet_start = -1;
+ p_queue->gdb_packet_end = -1;
+
+ p_queue->gdb_packet_csum1 = -1;
+ p_queue->gdb_packet_csum2 = -1;
+
+ for ( i = 0; i < MAX_RS232_CHARS; ++i )
+ {
+ p_queue->buf[ i ] = 0;
+ }
+
+ return;
+}
+/* end of 'lan_init_queue'
+ *===========================================================================*/
+
+
+/*-----------------------------------------------------------------------------
+ *
+ * FUNCTION NAME: lan_add_to_queue
+ *
+ *
+ * DESCRIPTION: Adds the specified character to the tail of the
+ * specified queue. Observes "oldest thrown on floor"
+ * rule (i.e. the queue is allowed to "wrap" and the
+ * input character is unconditionally placed at the
+ * tail of the queue.
+ *
+ *
+ * RETURN VALUE: None.
+ *
+ *
+ * USED GLOBAL VARIABLES:
+ *
+ *
+ * AFFECTED GLOBAL VARIABLES/SIDE EFFECTS:
+ *
+ *
+ * NOTES:
+ *
+ *
+ *---------------------------------------------------------------------------*/
+
+static void lan_add_to_queue( long c, T_RS232_QUEUE *p_queue )
+
+{
+
+ if ( p_queue ) /* Sanity check. */
+ {
+
+ if ( c & 0x000000FF ) /* We don't allow NULL characters to be added to a queue. */
+ {
+ /* Insert the new character at the tail of the queue. */
+
+ p_queue->buf[ p_queue->tail_index ] = (UCHAR) (c & 0x000000FF);
+
+ /* Increment the tail index. */
+
+ if ( MAX_RS232_CHARS <= ++(p_queue->tail_index) )
+ {
+ p_queue->tail_index = 0;
+ }
+
+ /* Check for wrapping (i.e. overflow). */
+
+ if ( p_queue->head_index == p_queue->tail_index )
+ {
+ /* If the tail has caught up to the head record the overflow . . . */
+
+ ++(p_queue->overflows);
+
+ /* . . . then increment the head index. */
+
+ if ( MAX_RS232_CHARS <= ++(p_queue->head_index) )
+ {
+ p_queue->head_index = 0;
+ }
+
+ }
+
+ } /* End of 'if ( c & 0x000000FF )'. */
+
+ } /* End of 'if ( p_queue )'. */
+
+
+ return;
+}
+/* end of 'lan_add_to_queue'
+ *===========================================================================*/
+
+
+/*-----------------------------------------------------------------------------
+ *
+ * FUNCTION NAME: lan_next_queue_char
+ *
+ * DESCRIPTION:
+ *
+ * RETURN VALUE:
+ *
+ * USED GLOBAL VARIABLES:
+ *
+ * AFFECTED GLOBAL VARIABLES/SIDE EFFECTS:
+ *
+ * NOTES:
+ *
+ *---------------------------------------------------------------------------*/
+
+static UCHAR lan_next_queue_char( T_RS232_QUEUE *p_queue )
+
+{
+ UCHAR c;
+
+
+ c = 0;
+
+ if ( p_queue )
+ {
+
+ if ( p_queue->head_index != p_queue->tail_index )
+ {
+ /* Return the 'oldest' character in the queue. */
+
+ c = p_queue->buf[ p_queue->head_index ];
+
+ /* Increment the head index. */
+
+ if ( MAX_RS232_CHARS <= ++(p_queue->head_index) )
+ {
+ p_queue->head_index = 0;
+ }
+
+ }
+
+ } /* End of 'if ( p_queue )'. */
+
+
+ return( c );
+}
+
+/* end of 'lan_next_queue_char'
+ *===========================================================================*/
+
+
+/*-----------------------------------------------------------------------------
+ *
+ * FUNCTION NAME: lan_util_menu
+ *
+ * DESCRIPTION: Prints out a brief help on the LAN UART control utility.
+ *
+ * RETURN VALUE: None.
+ *
+ * USED GLOBAL VARIABLES: None.
+ *
+ * AFFECTED GLOBAL VARIABLES/SIDE EFFECTS: None.
+ *
+ * NOTES: None.
+ *
+ *---------------------------------------------------------------------------*/
+
+static void lan_util_menu( void )
+
+{
+
+ /*
+ * Multiply calling printp() below is made due to the limitations
+ * of printp(), incapable of handling long formatting constants:
+ */
+
+ printp( "\n -- Options --\n\n" );
+
+ printp( " %2X,'INIT' ............... Reset & (Re)INITIALIZE Interface.\n", (ULONG) LAN_UTIL_CODE );
+ printp( " %2X,'BAUD',<rate> ........ Set BAUD Rate.\n", (ULONG) LAN_UTIL_CODE );
+ printp( " %2X,'INTR',<mode> ........ Toggle 'RxRDY' Interrupts.\n", (ULONG) LAN_UTIL_CODE );
+ printp( " %2X,'XMT',<mode> ......... Toggle TRANSMIT-via-backplane.\n", (ULONG) LAN_UTIL_CODE );
+ printp( " %2X,'STAT' ............... Display STATUS.\n", (ULONG) LAN_UTIL_CODE );
+ printp( " %2X,'ECHO',<mode> ........ Enable/Disable Test ECHO.\n", (ULONG) LAN_UTIL_CODE );
+ printp( " %2X,'IN',<action> ........ Access INPUT Queue.\n", (ULONG) LAN_UTIL_CODE );
+ printp( " %2X,'OUT',<action> ....... Access OUTPUT Queue.\n\n", (ULONG) LAN_UTIL_CODE );
+
+ printp( " %2X,'PUTC',<char> ........ Output a Character (i.e. <char>).\n\n", (ULONG) LAN_UTIL_CODE );
+
+/***
+ printp( " %2X,'WPM',address,word ... Write Protected Memory Test.\n\n", (ULONG) LAN_UTIL_CODE );
+***/
+
+ printp( " <rate>: 4800 <mode>: E - enable <action>: C - clear/reset\n" );
+ printp( " 9600 D - disable D - display\n" );
+ printp( " 19200 F - fetch next char\n" );
+ printp( " 38400\n" );
+}
+/* end of 'lan_util_menu'
+ *===========================================================================*/
+
+
+/* Thu Feb 5 17:14:41 EST 1998 CYGNUS...CYGNUS...CYGNUS...CYGNUS...CYGNUS...CYGNUS...CYGNUS...CYGNUS */
+
+
+static long get_gdb_input( long c, T_RS232_QUEUE * p_input_q )
+
+{
+
+ /* Now to detect when we've got a gdb packet... */
+
+ if ( '$' == c ) { /* char marks beginning of a packet */
+
+ if ( -1 != p_input_q->gdb_packet_start ||
+ -1 != p_input_q->gdb_packet_end ||
+ -1 != p_input_q->gdb_packet_csum1 ||
+ -1 != p_input_q->gdb_packet_csum2 ) { /* PROTOCOL ERROR */
+
+ /* NEW: Actually, this probably means that we muffed a packet,
+ and GDB has already resent it. The thing to do now is to
+ throw away the one we WERE working on, but immediately start
+ accepting the new one. Don't NAK, or GDB will have to try
+ and send it yet a third time! */
+
+ /*NACK_PKT( );*/ /*<ETHERNET>*/
+ discard_packet( ); /* throw away old packet */
+ lan_add_to_queue ('$', p_input_q); /* put the new "$" back in */
+ return 0;
+ } else { /* match new "$" */
+ p_input_q->gdb_packet_start = p_input_q->tail_index;
+ p_input_q->gdb_packet_end =
+ p_input_q->gdb_packet_csum1 =
+ p_input_q->gdb_packet_csum2 = -1;
+ }
+ } else if ( '#' == c ) { /* # marks end of packet (except for checksum) */
+
+ if ( -1 == p_input_q->gdb_packet_start ||
+ -1 != p_input_q->gdb_packet_end ||
+ -1 != p_input_q->gdb_packet_csum1 ||
+ -1 != p_input_q->gdb_packet_csum2 ) { /* PROTOCOL ERROR */
+
+ /* Garbled packet. Discard, but do not NAK. */
+
+ /*NACK_PKT( );*/ /*<ETHERNET>*/
+ discard_packet( );
+ return -1;
+ }
+ p_input_q->gdb_packet_end = p_input_q->tail_index;
+ p_input_q->gdb_packet_csum1 = p_input_q->gdb_packet_csum2 = -1;
+
+ } else if ( -1 != p_input_q->gdb_packet_start &&
+ -1 != p_input_q->gdb_packet_end) {
+
+ if ( isxdigit( c ) ) { /* char is one of two checksum digits for packet */
+
+ if ( -1 == p_input_q->gdb_packet_csum1 &&
+ LAN_Q_MOD( p_input_q->gdb_packet_end + 1 ) ==
+ p_input_q->tail_index ) {
+
+ /* first checksum digit */
+
+ p_input_q->gdb_packet_csum1 = p_input_q->tail_index;
+ p_input_q->gdb_packet_csum2 = -1;
+
+ } else if ( -1 == p_input_q->gdb_packet_csum2 &&
+ LAN_Q_MOD( p_input_q->gdb_packet_end + 2 ) ==
+ p_input_q->tail_index ) {
+
+ /* second checksum digit: packet is complete! */
+
+ p_input_q->gdb_packet_csum2 = p_input_q->tail_index;
+ getpacket(); /* got a packet -- extract it */
+
+ } else { /* probably can't happen (um... three hex digits?) */
+
+ /* PROTOCOL ERROR */
+ /* Not sure how this can happen, but ...
+ discard it, but do not NAK it. */
+ /*NACK_PKT( );*/ /*<ETHERNET>*/
+ discard_packet( );
+ return -1;
+ }
+
+ } else { /* '#' followed by non-hex char */
+
+ /* PROTOCOL ERROR */
+ /* Bad packet -- discard but do not NAK */
+ /*NACK_PKT( );*/ /*<ETHERNET>*/
+ discard_packet( );
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+
+
+
+#ifdef STANDALONE
+
+/* stand-alone stand-alone stand-alone stand-alone stand-alone stand-alone
+ stand-alone stand-alone
+ stand-alone Enable stand-alone build, for ease of debugging stand-alone
+ stand-alone stand-alone
+ stand-alone stand-alone stand-alone stand-alone stand-alone stand-alone */
+
+long write_to_protected_mem (addr, word)
+ void *addr;
+ unsigned short word;
+{
+ return 0;
+}
+
+
+char dummy_memory[0x4000];
+
+int main ( void )
+{
+ long c;
+
+ lan_init_queue( &lan_input_queue );
+ printf( "Stand-alone EMC 'stub', pid = %d\n", getpid( ) );
+ printf( "Start of simulated 'memory': 0x%08x\n", &dummy_memory);
+ while ( (c = getc( stdin ) ) != EOF )
+ {
+ if ( c == '\\' ) /* escape char */
+ break;
+
+ lan_add_to_queue( c, &lan_input_queue );
+ get_gdb_input (c, &lan_input_queue);
+ fflush( stdout );
+ }
+
+ printf( "Goodbye!\n" );
+ exit( 0 );
+}
+
+#define SRAM_START ((void *) (&dummy_memory[0] + 0x00000000))
+#define SRAM_END ((void *) (&dummy_memory[0] + 0x00000400))
+
+#define RO_AREA_START ((void *) (&dummy_memory[0] + 0x00000100))
+#define RO_AREA_END ((void *) (&dummy_memory[0] + 0x00000300))
+
+#define NVD_START ((void *) (&dummy_memory[0] + 0x00003000))
+#define NVD_END ((void *) (&dummy_memory[0] + 0x00003100))
+
+#else /* normal stub (not stand-alone) */
+
+#define SRAM_START ((void *) 0x00000000)
+#define SRAM_END ((void *) 0x00400000)
+
+#define RO_AREA_START ((void *) 0x00100000)
+#define RO_AREA_END ((void *) 0x00300000)
+
+#define NVD_START ((void *) 0x03000000)
+#define NVD_END ((void *) 0x03100000)
+
+#endif /* STANDALONE */
+
+
+
+
+/* gdb gdb gdb gdb gdb gdb gdb gdb gdb gdb gdb gdb gdb gdb gdb gdb gdb gdb
+ gdb gdb
+ gdb Here begins the gdb stub section. gdb
+ gdb The following functions were added by Cygnus, gdb
+ gdb to make this thing act like a gdb stub. gdb
+ gdb gdb
+ gdb gdb gdb gdb gdb gdb gdb gdb gdb gdb gdb gdb gdb gdb gdb gdb gdb gdb */
+
+
+/* ------------------- global defines and data decl's -------------------- */
+
+#define hexchars "0123456789abcdef"
+
+/* there are 180 bytes of registers on a 68020 w/68881 */
+/* many of the fpa registers are 12 byte (96 bit) registers */
+#define NUMREGBYTES 180
+#define NUMREGS 29
+#define REGISTER_BYTE(regno) regno
+
+enum regnames { D0, D1, D2, D3, D4, D5, D6, D7,
+ A0, A1, A2, A3, A4, A5, A6, A7,
+ PS, PC,
+ FP0, FP1,
+ FP2, FP3,
+ FP4, FP5,
+ FP6, FP7,
+ FPCONTROL, FPSTATUS, FPIADDR
+ };
+
+unsigned long registers[NUMREGBYTES/4];
+
+static long remote_debug;
+
+#define BUFMAX MAX_IO_BUF_SIZE
+static char inbuffer[BUFMAX], outbuffer[BUFMAX];
+static char spare_buffer[BUFMAX];
+
+
+struct stub_trace_frame
+{
+ int valid;
+ unsigned long frame_id;
+ unsigned long tdp_id;
+ FRAME_DEF *frame_data;
+ COLLECTION_FORMAT_DEF *format;
+ unsigned long traceregs[NUMREGBYTES/4];
+ unsigned char *stack_data;
+ unsigned char *memrange_data;
+} curframe;
+
+/* ------------------- function prototypes -------------------- */
+
+void handle_request ( char * );
+
+/* ------------------- Implementation -------------------- */
+
+static void
+discard_packet( void )
+{
+ lan_input_queue.head_index = lan_input_queue.tail_index;
+
+ lan_input_queue.gdb_packet_start =
+ lan_input_queue.gdb_packet_end =
+ lan_input_queue.gdb_packet_csum1 =
+ lan_input_queue.gdb_packet_csum2 = -1;
+}
+
+/* Utility function: convert an ASCII isxdigit to a hex nybble */
+
+static long
+hex( char ch )
+{
+ if ( (ch >= 'A') && (ch <= 'F') )
+ return ch - 'A' + 10;
+ if ( (ch >= 'a') && (ch <= 'f') )
+ return ch - 'a' + 10;
+ if ( (ch >= '0') && (ch <= '9') )
+ return ch - '0';
+ return -1;
+}
+
+static void
+getpacket( void )
+{
+ unsigned char our_checksum, their_checksum;
+ char *copy = inbuffer;
+ unsigned char c;
+
+ our_checksum = 0;
+
+ /* first find the '$' */
+ while ((c = lan_next_queue_char ( &lan_input_queue )) != '$')
+ if (c == 0) /* ??? Protocol error? (paranoia) */
+ {
+ /* PROTOCOL ERROR (missing '$') */
+ /*NACK_PKT( );*/ /*<ETHERNET>*/
+ return;
+ }
+
+ /* Now copy the message (up to the '#') */
+ for (c = lan_next_queue_char ( &lan_input_queue ); /* skip the '$' */
+ c != 0 && c != '#'; /* stop at the '#' */
+ c = lan_next_queue_char ( &lan_input_queue ))
+ {
+ *copy++ = c;
+ our_checksum += c;
+ }
+ *copy++ = '\0'; /* terminate the copy */
+
+ if (c == 0) /* ??? Protocol error? (paranoia) */
+ {
+ /* PROTOCOL ERROR (missing '#') */
+ /*NACK_PKT( );*/ /*<ETHERNET>*/
+ return;
+ }
+ their_checksum = hex( lan_next_queue_char ( &lan_input_queue ) ) << 4;
+ their_checksum += hex( lan_next_queue_char ( &lan_input_queue ) );
+
+ /* Now reset the queue packet-recognition bits */
+ discard_packet( );
+
+ if ( remote_debug ||
+ our_checksum == their_checksum )
+ {
+ ACK_PKT( ); /* good packet */
+ /* Parse and process the packet */
+ handle_request( inbuffer );
+ }
+ else
+ /* PROTOCOL ERROR (bad check sum) */
+ NACK_PKT( );
+}
+
+/* EMC will provide a better implementation
+ (perhaps just of LAN_PUT_CHAR) that does not block.
+ For now, this works. */
+
+
+static void
+putpacket( char *str )
+{
+ unsigned char checksum;
+
+ /* '$'<packet>'#'<checksum> */
+
+ if ( VIA_ETHERNET == gdb_host_comm )
+ {
+ char *p_out;
+ long length;
+
+ p_out = eth_outbuffer;
+ length = 0;
+
+
+ if ( YES == gdb_cat_ack )
+ {
+ *p_out++ = '+';
+ ++length;
+ }
+
+ gdb_cat_ack = NO;
+
+
+ *p_out++ = '$';
+ ++length;
+
+ checksum = 0;
+
+ while ( *str )
+ {
+ *p_out++ = *str;
+ ++length;
+ checksum += *str++;
+ }
+
+ *p_out++ = '#';
+ *p_out++ = hexchars[checksum >> 4];
+ *p_out = hexchars[checksum % 16];
+ length += 3;
+
+ eth_to_gdb( (UCHAR *) eth_outbuffer, length );
+ }
+
+ else
+ {
+
+ /* via RS-232 */
+ do {
+ LAN_PUT_CHAR( '$' );
+ checksum = 0;
+
+ while ( *str )
+ {
+ LAN_PUT_CHAR( *str );
+ checksum += *str++;
+ }
+
+ LAN_PUT_CHAR( '#' );
+ LAN_PUT_CHAR( hexchars[checksum >> 4] );
+ LAN_PUT_CHAR( hexchars[checksum % 16] );
+ } while ( 0 /* get_debug_char( ) != '+' */ );
+ /* XXX FIXME: not waiting for the ack. */
+
+ }
+
+}
+
+
+/*-----------------------------------------------------------------------------
+ *
+ * FUNCTION NAME: gdb_get_eth_input
+ *
+ *
+ * DESCRIPTION:
+ *
+ *
+ * RETURN VALUE: None.
+ *
+ *
+ * USED GLOBAL VARIABLES:
+ *
+ *
+ * AFFECTED GLOBAL VARIABLES/SIDE EFFECTS:
+ *
+ *
+ * NOTES:
+ *
+ *
+ *---------------------------------------------------------------------------*/
+
+void gdb_get_eth_input( unsigned char *buf, long length )
+
+{
+
+ gdb_host_comm = VIA_ETHERNET;
+
+ for ( ; 0 < length; ++buf, --length)
+ {
+
+ if ( *buf == CONTROL_C )
+ {
+ /* can't stop the target, but we can tell gdb to stop waiting... */
+ discard_packet( );
+ putpacket( "S03" ); /* send back SIGINT to the debugger */
+ }
+
+ else
+ {
+ lan_add_to_queue( (long) *buf, &lan_input_queue );
+ get_gdb_input( (long) *buf, &lan_input_queue );
+ }
+
+ }
+
+
+ return;
+}
+/* end of 'gdb_get_eth_input'
+ *===========================================================================*/
+
+
+
+
+/* STDOUT STDOUT STDOUT STDOUT STDOUT STDOUT STDOUT STDOUT STDOUT STDOUT
+ Stuff pertaining to simulating stdout by sending chars to gdb to be echoed.
+
+ Dear reader:
+ This code is based on the premise that if GDB receives a packet
+ from the stub that begins with the character CAPITAL-OH, GDB will
+ echo the rest of the packet to GDB's console / stdout. This gives
+ the stub a way to send a message directly to the user. In practice,
+ (as currently implemented), GDB will only accept such a packet when
+ it believes the target to be running (ie. when you say STEP or
+ CONTINUE); at other times it does not expect it. This will probably
+ change as a side effect of the "asynchronous" behavior.
+
+ Functions: gdb_putchar(char ch)
+ gdb_write(char *str, int len)
+ gdb_puts(char *str)
+ gdb_error(char *format, char *parm)
+ */
+
+#if 0 /* avoid compiler warning while this is not used */
+
+/* Function: gdb_putchar(int)
+ Make gdb write a char to stdout.
+ Returns: the char */
+
+static int
+gdb_putchar( long ch )
+{
+ char buf[4];
+
+ buf[0] = 'O';
+ buf[1] = hexchars[ch >> 4];
+ buf[2] = hexchars[ch & 0x0F];
+ buf[3] = 0;
+ putpacket( buf );
+ return ch;
+}
+#endif
+
+/* Function: gdb_write(char *, int)
+ Make gdb write n bytes to stdout (not assumed to be null-terminated).
+ Returns: number of bytes written */
+
+static int
+gdb_write( char *data, long len )
+{
+ char *buf, *cpy;
+ long i;
+
+ buf = outbuffer;
+ buf[0] = 'O';
+ i = 0;
+ while ( i < len )
+ {
+ for ( cpy = buf+1;
+ i < len && cpy < buf + BUFMAX - 3;
+ i++ )
+ {
+ *cpy++ = hexchars[data[i] >> 4];
+ *cpy++ = hexchars[data[i] & 0x0F];
+ }
+ *cpy = 0;
+ putpacket( buf );
+ }
+ return len;
+}
+
+/* Function: gdb_puts(char *)
+ Make gdb write a null-terminated string to stdout.
+ Returns: the length of the string */
+
+static int
+gdb_puts( char *str )
+{
+ return gdb_write( str, strlen( str ) );
+}
+
+/* Function: gdb_error(char *, char *)
+ Send an error message to gdb's stdout.
+ First string may have 1 (one) optional "%s" in it, which
+ will cause the optional second string to be inserted. */
+
+#if 0
+static void
+gdb_error( char *format, char *parm )
+{
+ static char buf[400];
+ char *cpy;
+ long len;
+
+ if ( remote_debug )
+ {
+ if ( format && *format )
+ len = strlen( format );
+ else
+ return; /* empty input */
+
+ if ( parm && *parm )
+ len += strlen( parm );
+
+ for ( cpy = buf; *format; )
+ {
+ if ( format[0] == '%' && format[1] == 's' ) /* include 2nd string */
+ {
+ format += 2; /* advance two chars instead of just one */
+ while ( parm && *parm )
+ *cpy++ = *parm++;
+ }
+ else
+ *cpy++ = *format++;
+ }
+ *cpy = '\0';
+ gdb_puts( buf );
+ }
+}
+#endif
+
+static void gdb_note (char *, int);
+static int error_ret (int, char *, int);
+
+static unsigned long
+elinum_to_index (unsigned long elinum)
+{
+ if ((elinum & 0xf0) == 0xd0)
+ return (elinum & 0x0f);
+ else if ((elinum & 0xf0) == 0xa0)
+ return (elinum & 0x0f) + 8;
+ else
+ return -1;
+}
+
+static long
+index_to_elinum (unsigned long index)
+{
+ if (index <= 7)
+ return index + 0xd0;
+ else if (index <= 15)
+ return (index - 8) + 0xa0;
+ else
+ return -1;
+}
+
+
+/*
+ READMEM READMEM READMEM READMEM READMEM READMEM READMEM READMEM READMEM
+
+ The following code pertains to reading memory from the target.
+ Some sort of exception handling should be added to make it safe.
+
+ READMEM READMEM READMEM READMEM READMEM READMEM READMEM READMEM READMEM
+
+ Safe Memory Access:
+
+ All reads and writes into the application's memory will pass thru
+ get_uchar() or set_uchar(), which check whether accessing their
+ argument is legal before actual access (thus avoiding a bus error).
+
+ */
+
+enum { SUCCESS = 0, FAIL = -1 };
+
+#if 0
+static long get_uchar ( const unsigned char * );
+#endif
+static long set_uchar ( unsigned char *, unsigned char );
+static long read_access_violation ( const void * );
+static long write_access_violation ( const void * );
+static long read_access_range(const void *, long);
+static DTC_RESPONSE find_memory(unsigned char *,long,unsigned char **,long *);
+
+static int
+dtc_error_ret (int ret, char *src, DTC_RESPONSE code)
+{
+ if (src)
+ sprintp (spare_buffer,
+ "'%s' returned DTC error '%s'.\n", src, get_err_text (code));
+ else
+ sprintp (spare_buffer, "DTC error '%s'.\n", get_err_text (code));
+
+ gdb_puts (spare_buffer);
+ return ret;
+}
+
+
+#if 0
+/* I think this function is unnecessary since the introduction of
+ adbg_find_memory_addr_in_frame. */
+
+/* Return the number of expressions in the format associated with a
+ given trace frame. */
+static int
+count_frame_exprs (FRAME_DEF *frame)
+{
+ CFD *format;
+ T_EXPR *expr;
+ int num_exprs;
+
+ /* Get the format from the frame. */
+ get_frame_format_pointer (frame, &format);
+
+ /* Walk the linked list of expressions, and count the number of
+ expressions we find there. */
+ num_exprs = 0;
+ for (expr = format->p_cfd_expr; expr; expr = expr->next)
+ num_exprs++;
+
+ return num_exprs;
+}
+#endif
+
+#if 0
+/* Function: get_frame_addr
+ *
+ * Description: If the input memory address was collected in the
+ * current trace frame, then lookup and return the address
+ * from within the trace buffer from which the collected byte
+ * may be retrieved. Else return -1. */
+
+unsigned char *
+get_frame_addr ( const unsigned char *addr )
+{
+ unsigned char *base, *regs, *stack, *mem;
+ CFD *dummy;
+ DTC_RESPONSE ret;
+
+ /* first, see if addr is on the saved piece of stack for curframe */
+ if (curframe.format->stack_size > 0 &&
+ (base = (unsigned char *) curframe.traceregs[A7]) <= addr &&
+ addr < base + curframe.format->stack_size)
+ {
+ gdb_puts("STUB: get_frame_addr: call get_addr_to_frame_regs_stack_mem\n");
+ if ((ret = get_addr_to_frame_regs_stack_mem (curframe.frame_data,
+ &dummy,
+ (void *) &regs,
+ (void *) &stack,
+ (void *) &mem))
+ != OK_TARGET_RESPONSE)
+ return (void *) dtc_error_ret (-1,
+ "get_addr_to_frame_regs_stack_mem",
+ ret);
+ else
+ return stack + (addr - base);
+ }
+
+ /* Next, try to find addr in the current frame's expression-
+ collected memory blocks. I'm sure this is at least quadradic in
+ time. */
+ {
+ int num_exprs = count_frame_exprs (curframe.frame_data);
+ int expr, block;
+
+ /* Try each expression in turn. */
+ for (expr = 0; expr < num_exprs; expr++)
+ {
+ for (block = 0; ; block++)
+ {
+ T_EXPR_DATA *data;
+ if (adbg_get_expr_data (curframe.frame_data,
+ 'x', expr, block,
+ &data)
+ != OK_TARGET_RESPONSE)
+ break;
+ else if ((unsigned char *) data->address <= addr
+ && addr < ((unsigned char *) data->address + data->size))
+ {
+ /* We have found the right block; is it valid data?
+ Upper-case stamps mean bad data. */
+ if ('A' <= data->stamp && data->stamp <= 'Z')
+ {
+ gdb_puts("STUB: get_frame_addr: adbg_get_expr_data INVALID\n");
+ return (unsigned char *) -1;
+ }
+ else
+ {
+ if (remote_debug > 1)
+ {
+ sprintp(spare_buffer,
+ "STUB: get_frame_addr: got it [%x,%x)\n",
+ data->address, data->address + data->size);
+ gdb_puts(spare_buffer);
+ }
+
+ return (((unsigned char *) &data->data)
+ + (addr - (unsigned char *) data->address));
+ }
+ }
+ }
+ }
+ }
+
+ /* not found, return error */
+ return (unsigned char *) -1;
+}
+
+/*============================================================*/
+
+static long get_uchar ( const unsigned char * addr )
+{
+ unsigned char *frame_addr;
+
+ if ( read_access_violation ( addr ) )
+ return ( -1 ); /* Access error */
+
+ if (curframe.valid) /* if debugging a trace frame? */
+ {
+ /* If the requested address was collected in the current frame,
+ * then fetch and return the data from the trace buffer.
+ */
+ if ((frame_addr = get_frame_addr (addr)) != (unsigned char *) -1)
+ return ( *frame_addr );
+ /* If the requested address is in the Code Section,
+ * let's be magnanimous and read it anyway (else we shall
+ * not be able to disassemble, find function prologues, etc.)
+ */
+ else if (CS_CODE_START <= (unsigned long) addr &&
+ (unsigned long) addr < CS_CODE_START + CS_CODE_SIZE)
+ return (*addr);
+ else
+ return ( -1 ); /* "Access error" (the data was not collected) */
+ }
+ else
+ /* Not debugging a trace frame, read the data from live memory. */
+ return ( *addr ); /* Meaningful result >= 0 */
+}
+#endif
+
+/*============================================================*/
+
+static long set_uchar ( unsigned char * addr, unsigned char val )
+{
+ long check_result = write_access_violation ( addr );
+
+ if ( check_result != 0L )
+ return ( check_result ); /* Access error */
+
+ return ( *addr = val ); /* Successful writing */
+}
+
+/*============================================================*/
+
+/*
+ * Function read_access_violation() below returns TRUE if dereferencing
+ * its argument for reading would cause a bus error - and FALSE otherwise:
+ */
+
+static long read_access_violation ( const void * addr )
+{
+ return ( ( ( addr < SRAM_START ) || ( addr >= SRAM_END ) ) &&
+ ( ( addr < NVD_START ) || ( addr >= NVD_END ) ) );
+}
+
+/*============================================================*/
+
+/*
+ * Function write_access_violation() below returns zero if dereferencing
+ * its argument for writing is safe, -1 on a soft error (the argument
+ * falls into the write-protected area), -2 on a hard error (the argument
+ * points to a non-existent memory location). In other words, it returns
+ * FALSE when no bus error is expected - and an error code otherwise:
+ */
+
+static long write_access_violation ( const void * addr )
+{
+ /*
+ * The boundaries of the write-protected area have to be received via
+ * an API provided in the Symmetrix core code. For now, these limits
+ * are hard-coded:
+ */
+
+ if ( ( addr >= RO_AREA_START ) && ( addr < RO_AREA_END ) )
+ return ( -1 ); /* soft error */
+
+ if ( ( ( addr < SRAM_START ) || ( addr >= SRAM_END ) ) &&
+ ( ( addr < NVD_START ) || ( addr >= NVD_END ) ) )
+ return ( -2 ); /* hard error */
+
+ return ( 0 );
+}
+
+
+/* read_access_range is like read_access_violation,
+ but returns the number of bytes we can read w/o faulting.
+ that is, it checks an address range and tells us what portion
+ (if any) of the prefix is safe to read without a bus error */
+static long
+read_access_range(const void *addr, long count)
+{
+ if ((addr >= SRAM_START) && (addr < SRAM_END))
+ {
+ if ((char *)addr + count < (char *)SRAM_END)
+ return (count);
+ else
+ return ((char *)SRAM_END - (char *)addr);
+ }
+ else if (((char *)addr >= (char *)NVD_START) &&
+ ((char *)addr < (char *)NVD_END))
+ {
+ if ((char *)addr + count < (char *)NVD_END)
+ return (count);
+ else
+ return ((char *)NVD_END - (char *)addr);
+ }
+ else
+ return (0);
+}
+
+/* Convert the memory pointed to by mem into hex, placing result in buf.
+ Return SUCCESS or FAIL.
+ If MAY_FAULT is non-zero, then we should return FAIL in response to
+ a fault; if zero treat a fault like any other fault in the stub. */
+
+static long
+mem2hex(unsigned char *mem, char *buf, long count, long may_fault)
+{
+ long ndx;
+ long ndx2;
+ long ch;
+ long incr;
+ unsigned char *location;
+ DTC_RESPONSE status;
+
+ if (may_fault)
+ {
+ for (ndx = 0, incr = 1; (ndx < count) && (incr > 0); ndx += incr)
+ {
+ status = find_memory(mem, count - ndx, &location, &incr);
+
+ if (status == OK_TARGET_RESPONSE)
+ {
+ if (incr > 0)
+ {
+ for (ndx2 = 0; ndx2 < incr; ndx2++)
+ {
+ ch = *location++;
+ *buf++ = hexchars[ch >> 4];
+ *buf++ = hexchars[ch & 0xf];
+ }
+ mem += incr;
+ }
+ else if (incr <= 0) /* should never happen */
+ {
+ *buf = 0;
+ return (0);
+ }
+ }
+ else if (status == NOT_FOUND_TARGET_RESPONSE)
+ {
+ *buf = 0;
+ return (ndx); /* return amount copied */
+ }
+ else
+ {
+ *buf = 0;
+ return (0); /* XXX: how do we tell the user the status? */
+ }
+ }
+ *buf = 0;
+ return (count);
+ }
+ else
+ {
+ for (ndx = 0; ndx < count; ndx++)
+ {
+ ch = *mem++;
+ *buf++ = hexchars[ch >> 4];
+ *buf++ = hexchars[ch & 0xf];
+ }
+ *buf = 0;
+ return (count); /* we copied everything */
+ }
+}
+
+static DTC_RESPONSE
+find_memory(unsigned char *mem, long count,
+ unsigned char **location, long *incr)
+{
+ DTC_RESPONSE retval;
+ long length;
+
+ /* figure out how much of the memory range we can read w/o faulting */
+ count = read_access_range(mem, count);
+ if (count == 0)
+ return (NOT_FOUND_TARGET_RESPONSE);
+
+ if (curframe.valid)
+ {
+ unsigned char *mem_block;
+ unsigned char *mem_addr;
+ unsigned long mem_size;
+ unsigned long mem_stamp;
+
+ retval = adbg_find_memory_addr_in_frame(curframe.frame_data, mem,
+ (unsigned long **)&mem_block,
+ (unsigned long **)&mem_addr,
+ &mem_size, &mem_stamp);
+
+ switch (retval)
+ {
+ case OK_TARGET_RESPONSE:
+#if 0
+ printp("FOUND: mem %x block %x addr %x size %d stamp %x\n",
+ mem, mem_block, mem_addr, mem_size, mem_stamp);
+#endif
+ *location = mem_block + (mem - mem_addr);
+ length = mem_size - (mem - mem_addr);;
+
+ if (length < count)
+ *incr = length;
+ else
+ *incr = count;
+
+ break;
+
+ case NOT_FOUND_TARGET_RESPONSE:
+ case NEAR_FOUND_TARGET_RESPONSE:
+#if 0
+ printp("NOT FOUND: mem %x, checking code region\n", mem);
+#endif
+ /* check to see if it's in the code region */
+ if ((CS_CODE_START <= (long)mem) &&
+ ((long)mem < CS_CODE_START + CS_CODE_SIZE))
+ {
+ /* some or all of the address range is in the code */
+ *location = mem;
+ if ((long)mem + count <= CS_CODE_START + CS_CODE_SIZE)
+ *incr = count; /* it's totally in the code */
+ else
+ /* how much is in the code? */
+ *incr = CS_CODE_START + CS_CODE_SIZE - (long)mem;
+#if 0
+ printp("FOUND in code region: %x\n", mem);
+#endif
+ retval = OK_TARGET_RESPONSE;
+ }
+ else
+ retval = NOT_FOUND_TARGET_RESPONSE;
+
+ break;
+
+ default:
+#if 0
+ printp("BAD RETURN: %d\n", retval);
+#endif
+ retval = NOT_FOUND_TARGET_RESPONSE;
+ break;
+ }
+ }
+ else
+ {
+ *location = mem;
+ *incr = count;
+ retval = OK_TARGET_RESPONSE;
+ }
+
+ return (retval);
+}
+
+/* Convert the hex array pointed to by buf into binary to be placed in mem.
+ Return SUCCESS or FAIL. */
+
+static long
+hex2mem( char *buf, unsigned char *mem, long count, long may_fault )
+{
+ long i, ch;
+
+ for ( i=0; i<count; i++ )
+ {
+ ch = hex( *buf++ ) << 4;
+ ch = ch + hex( *buf++ );
+ if ( may_fault )
+ {
+ ch = set_uchar( mem++, ch );
+ if ( ch < 0 ) /* negative return indicates error */
+ return FAIL;
+ }
+ else
+ *mem++ = ch;
+ }
+ return SUCCESS;
+}
+
+/**********************************************/
+/* WHILE WE FIND NICE HEX CHARS, BUILD AN INT */
+/* RETURN NUMBER OF CHARS PROCESSED */
+/**********************************************/
+
+static int
+hexToInt( char **ptr, unsigned long *intValue )
+{
+ long numChars = 0;
+ long hexValue;
+
+ *intValue = 0;
+ while ( **ptr )
+ {
+ hexValue = hex( **ptr );
+ if ( hexValue >=0 )
+ {
+ *intValue = (*intValue << 4) | hexValue;
+ numChars ++;
+ }
+ else
+ break;
+ (*ptr)++;
+ }
+ return numChars;
+}
+
+static volatile long gdb_handling_trap1;
+static volatile long gdb_handling_sstrace;
+static volatile long gdb_signo;
+
+/*
+ Here is the "callable" stub entry point.
+ Call this function with a GDB request as an argument,
+ and it will service the request and return.
+
+ May be further broken up as we go along, with individual requests
+ broken out as separate functions.
+ */
+
+static char * handle_trace_query (char *);
+static char * handle_trace_set (char *);
+static int handle_format (char **request, CFD *format);
+static unsigned long crc32 (unsigned char *buf, int len, unsigned long crc);
+static char * crc_query (char *);
+static char * handle_test (char *);
+
+void
+handle_request( char *request )
+{
+#if 0
+ remote_debug = 2;
+#endif
+ switch( *request++ )
+ {
+ case 'k': /* "kill" */
+ curframe.valid = FALSE;
+ putpacket ("");
+ break;
+ case 'D': /* "detach" */
+ curframe.valid = FALSE;
+ putpacket ("");
+ break;
+ default: /* Unknown code. Return an empty reply message. */
+ putpacket( "" ); /* return empty packet */
+ break;
+
+ case 'H': /* Set thread for subsequent operations.
+ Hct... c = 'c' for thread used in step and continue;
+ t... can be -1 for all threads.
+ c = 'g' for thread used in other operations.
+ If zero, pick a thread, any thread. */
+
+ putpacket( "OK" );
+ break;
+
+ case 'g': /* Read registers.
+ 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. */
+ {
+ /* Return the values in (one of) the registers cache(s).
+ Several situations may pertain:
+ 1) We're synchronous, in which case the "registers" array
+ should actually be current.
+ 2) We're asynchronous, in which case the "registers" array
+ holds whatever was cached most recently.
+ 3) We're looking at a trace frame that was collected earlier:
+ we will return those earlier registers.
+ */
+
+ /* all registers default to zero */
+ memset (outbuffer, '0', NUMREGBYTES);
+ outbuffer[NUMREGBYTES] = '\0';
+
+ if (curframe.valid) /* debugging a trace frame */
+ mem2hex( (unsigned char*) curframe.traceregs,
+ outbuffer, NUMREGBYTES, 0 );
+ else
+ mem2hex( (unsigned char*) registers, outbuffer, NUMREGBYTES, 0 );
+
+ putpacket( outbuffer );
+ }
+ break;
+ case 'G': /* Write registers.
+ Gxxxxxxxx Each byte of register data is described by
+ two hex digits. */
+ if (curframe.valid) /* debugging a trace frame */
+ putpacket ("E03"); /* can't write regs into a trace frame! */
+ else
+ {
+ /* Write the values into the local registers cache...
+ Note that no actual registers are being changed. */
+
+ hex2mem( request,
+ (unsigned char *) registers, NUMREGBYTES, 0 );
+ putpacket( "OK" );
+ }
+ break;
+ case 'P': /* Write (single) register.
+ Pnn=xxxxxxxx register nn gets value xxxxxxxx;
+ two hex digits for each byte in the register
+ (target byte order). */
+
+ if (curframe.valid)
+ putpacket ("E03"); /* can't write regs into a trace frame! */
+ else
+ {
+ unsigned long regno;
+
+ if ( hexToInt( &request, &regno ) && *(request++) == '=' )
+ {
+ if ( regno < NUMREGS )
+ {
+ hexToInt( &request,
+ (unsigned long *) &registers[REGISTER_BYTE(regno)]);
+
+ putpacket( "OK" );
+ }
+ else
+ putpacket( "E01" ); /* bad packet or regno */
+ }
+ }
+ break;
+ case 'm': /* Read memory.
+ mAAAAAAAA,LLLL AAAAAAAA is address, LLLL is length.
+ Reply can be fewer bytes than requested
+ if able to read only part of the data. */
+ {
+ unsigned long addr, len;
+
+ if ( hexToInt( &request, &addr ) &&
+ *(request++) == ',' &&
+ hexToInt( &request, &len ) )
+ {
+ /* better not overwrite outbuffer! */
+ if ( len > (BUFMAX / 2) - 5 )
+ len = (BUFMAX / 2) - 5;
+ if (mem2hex((unsigned char *) addr, outbuffer, len, 1) == 0) /* XXX: eventually use returned value */
+ putpacket( "E03" ); /* read fault (access denied) */
+ else
+ putpacket( outbuffer ); /* read succeeded */
+ }
+ else
+ putpacket( "E01" ); /* badly formed read request */
+
+ }
+ break;
+ case 'M': /* Write memory.
+ Maaaaaaaa,llll:xxxx aaaaaaaa is address, llll is length;
+ xxxx is data to write. */
+
+ {
+ unsigned long addr, len;
+
+ if (curframe.valid) /* can't write memory into a trace frame! */
+ putpacket ("E03"); /* "access denied" */
+ else /*** if ( write_access_enabled ) ***/
+ {
+ if ( hexToInt( &request, &addr ) &&
+ *(request++) == ',' &&
+ hexToInt( &request, &len ) &&
+ *(request++) == ':' )
+ {
+ if (len == 2 &&
+ addr >= CS_CODE_START &&
+ addr <= LAST_CS_WORD)
+ {
+ unsigned long val;
+
+ if ( !hexToInt( &request, &val ) ||
+ write_to_protected_mem( (void *)addr, val ) )
+ putpacket( "E03" ); /* write fault (access denied) */
+ else
+ putpacket( "OK" ); /* write succeeded */
+ }
+ else
+ {
+ if ( hex2mem( request, (unsigned char*) addr, len, 1 ) )
+ putpacket( "E03" ); /* write fault (access denied) */
+ else
+ putpacket( "OK" ); /* write succeeded */
+ }
+ }
+ else
+ putpacket( "E02" ); /* badly formed write request */
+ }
+ }
+ break;
+ case 'c': /* Continue.
+ cAAAAAAAA AAAAAAAA is address from which to resume.
+ If omitted, resume at current PC. */
+
+ {
+ unsigned long addr;
+
+ if (curframe.valid)
+ {
+ /* Don't continue if debugging a trace frame! */
+ gdb_puts ("Error: can't continue!\n");
+ putpacket ("S03");
+ }
+ else
+ {
+ gdb_signo = 3;
+ if (isxdigit(request[0]))
+ {
+ hexToInt(&request, &addr);
+ registers[REGISTER_BYTE(PC)] = addr;
+ }
+
+ gdb_handling_trap1 = FALSE;
+ gdb_handling_sstrace = FALSE;
+ sss_trace_flag = '\0';
+ }
+ }
+ break;
+ case 's': /* Step.
+ sAAAAAAAA AAAAAAAA is address from which to begin stepping.
+ If omitted, begin stepping at current PC. */
+ {
+ unsigned long addr;
+
+ if (curframe.valid)
+ {
+ /* Don't step if debugging a trace frame! */
+ gdb_puts ("Error: can't step!\n");
+ putpacket ("S03");
+ }
+ else
+ {
+ gdb_signo = 3;
+ if (isxdigit(request[0]))
+ {
+ hexToInt(&request, &addr);
+ registers[REGISTER_BYTE(PC)] = addr;
+ }
+
+ gdb_handling_trap1 = FALSE;
+ gdb_handling_sstrace = FALSE;
+ sss_trace_flag = 't';
+ }
+ }
+ break;
+ case 'C': /* Continue with signal.
+ Cxx;AAAAAAAA xx is signal number in hex;
+ AAAAAAAA is adddress from which to resume.
+ If ;AAAAAAAA omitted, continue from PC. */
+
+ {
+ unsigned long addr = 0;
+
+ if (!gdb_handling_trap1 || curframe.valid)
+ {
+ /* Don't continue if not currently in synchronous mode,
+ or if currently debugging a trace frame! */
+ gdb_puts( "Error: can't continue!\n" );
+ putpacket( "S03" ); /* "sigquit" (better idea?) */
+ }
+ else
+ {
+ gdb_signo = 3;
+ if ( isxdigit( *request ) )
+ {
+ hex2mem( request, (unsigned char *) &gdb_signo, 2, 0 );
+ request += 2;
+ if ( *request == ';' && isxdigit( *++request ) )
+ {
+ hexToInt( &request, &addr );
+ registers[REGISTER_BYTE(PC)] = addr;
+ }
+ }
+ gdb_handling_trap1 = FALSE;
+ gdb_handling_sstrace = FALSE;
+ sss_trace_flag = '\0';
+ }
+ }
+ break;
+ case 'S': /* Step with signal.
+ Sxx;AAAAAAAA xx is signal number in hex;
+ AAAAAAAA is adddress from which to begin stepping.
+ If ;AAAAAAAA omitted, begin stepping from PC. */
+ {
+ unsigned long addr = 0;
+
+ if (!gdb_handling_trap1 || curframe.valid)
+ {
+ /* Don't step if not currently in synchronous mode,
+ or if currently debugging a trace frame! */
+ gdb_puts( "Error: can't step!\n" );
+ putpacket( "S03" ); /* "sigquit" (better idea?) */
+ }
+ else
+ {
+ gdb_signo = 3;
+ if ( isxdigit( *request ) )
+ {
+ hex2mem( request, (unsigned char *) &gdb_signo, 2, 0 );
+ request += 2;
+ if ( *request == ';' && isxdigit( *++request ) )
+ {
+ hexToInt( &request, &addr );
+ registers[REGISTER_BYTE(PC)] = addr;
+ }
+ }
+ gdb_handling_trap1 = FALSE;
+ gdb_handling_sstrace = FALSE;
+ sss_trace_flag = 't';
+ }
+ }
+ break;
+ case '?': /* Query the latest reason for stopping.
+ Should be same reply as was last generated
+ for step or continue. */
+
+ if ( gdb_signo == 0 )
+ gdb_signo = 3; /* default to SIGQUIT */
+ outbuffer[ 0 ] = 'S';
+ outbuffer[ 1 ] = hexchars[ gdb_signo >> 4 ];
+ outbuffer[ 2 ] = hexchars[ gdb_signo & 0xf ];
+ outbuffer[ 3 ] = 0;
+ putpacket( outbuffer );
+ break;
+
+ case 'd': /* Toggle debug mode
+ I'm sure we can think of something interesting. */
+
+ remote_debug = !remote_debug;
+ putpacket( "" ); /* return empty packet */
+ break;
+
+ case 'q': /* general query */
+ switch (*request++)
+ {
+ default:
+ putpacket (""); /* nak a request which we don't handle */
+ break;
+ case 'T': /* trace query */
+ putpacket (handle_trace_query (request));
+ break;
+ case 'C': /* crc query (?) */
+ if (*request++ == 'R' &&
+ *request++ == 'C' &&
+ *request++ == ':')
+ putpacket (crc_query (request));
+ else
+ putpacket (""); /* unknown query */
+ break;
+ }
+ break;
+
+ case 'Q': /* general set */
+ switch (*request++)
+ {
+ default:
+ putpacket (""); /* nak a request which we don't handle */
+ break;
+ case 'T': /* trace */
+ putpacket (handle_trace_set (request));
+ break;
+ }
+ break;
+
+ case 'T':
+ /* call test function: TAAA,BBB,CCC
+ A, B, and C are arguments to pass to gdb_c_test. Reply is
+ "E01" (bad arguments) or "OK" (test function called). */
+ putpacket (handle_test (request));
+ break;
+ }
+}
+
+static TDP_SETUP_INFO tdp_temp;
+static int trace_running;
+
+/*
+ * Function msgcmp:
+ *
+ * If second argument (str) is matched in first argument,
+ * then advance first argument past end of str and return "SAME"
+ * else return "DIFFERENT" without changing first argument.
+ *
+ * Return: zero for DIFFERENT, non-zero for SUCCESS
+ */
+
+static int
+msgcmp (char **msgp, char *str)
+{
+ char *next;
+
+ if (msgp != 0 && str != 0) /* input validation */
+ if ((next = *msgp) != 0)
+ {
+ for (;
+ *next && *str && *next == *str;
+ next++, str++)
+ ;
+
+ if (*str == 0) /* matched all of str in msg */
+ return (int) (*msgp = next); /* advance msg ptr past str */
+ }
+ return 0; /* failure */
+}
+
+static char *
+handle_trace_query (char *request)
+{
+ if (msgcmp (&request, "Status"))
+ {
+ if (adbg_check_if_active ())
+ {
+ gdb_puts ("Target trace is running.\n");
+ return "T1";
+ }
+ else
+ {
+ gdb_puts ("Target trace not running.\n");
+ trace_running = 0;
+ return "T0";
+ }
+ }
+ else /* unknown trace query */
+ {
+ return "";
+ }
+}
+
+static void
+gdb_note (char *fmt, int arg1)
+{
+ if (remote_debug > 1)
+ {
+ sprintp (spare_buffer, fmt, arg1);
+ gdb_puts (spare_buffer);
+ }
+}
+
+static int
+error_ret (int ret, char *fmt, int arg1)
+{
+ if (remote_debug > 0)
+ {
+ sprintp (spare_buffer, fmt, arg1);
+ gdb_puts (spare_buffer);
+ }
+ return ret;
+}
+
+static int
+handle_format (char **request, COLLECTION_FORMAT_DEF *format)
+{
+ MEMRANGE_DEF m;
+ DTC_RESPONSE ret;
+ int elinum;
+ unsigned long regnum;
+ long bytecodes[(MAX_BYTE_CODES + sizeof (struct t_expr_tag))/ 4];
+ struct t_expr_tag *t_expr = (struct t_expr_tag *)bytecodes;
+
+ if (format->id == 0)
+ {
+ if ((ret = get_unused_format_id (&format->id)) != OK_TARGET_RESPONSE)
+ return dtc_error_ret (-1, "get_unused_format_id", ret);
+
+ if (**request == 'R')
+ {
+ (*request)++;
+ hexToInt (request, &format->regs_mask);
+ }
+ gdb_note ("STUB: call define_format (id = %d, ", format->id);
+ gdb_note ("regs_mask = 0x%X);\n", format->regs_mask);
+
+ if ((ret = define_format (format)) != OK_TARGET_RESPONSE)
+ {
+ sprintp (spare_buffer,
+ "'define_format': DTC error '%s' for format id %d.\n",
+ get_err_text (ret),
+ format->id);
+ gdb_puts (spare_buffer);
+ return -1;
+ }
+ }
+
+ while ((**request == 'M') || (**request == 'X'))
+ {
+ switch (**request)
+ {
+ case 'M': /* M<regnum>,<offset>,<size> */
+ (*request)++;
+ hexToInt(request, &regnum);
+
+ if (regnum == 0 || regnum == (unsigned long) -1)
+ m.typecode = -1;
+ else if ((elinum = index_to_elinum (regnum)) > 0)
+ m.typecode = elinum;
+ else
+ return error_ret (-1,
+ "Memrange register %d is not between 0 and 15\n",
+ regnum);
+
+ if (*(*request)++ != ',')
+ return error_ret (-1,"Malformed memrange (comma #%d missing)\n",1);
+ hexToInt(request, &m.offset);
+ if (*(*request)++ != ',')
+ return error_ret (-1,"Malformed memrange (comma #%d missing)\n",2);
+ hexToInt(request, &m.size);
+
+ gdb_note ("STUB: call add_format_mem_range (typecode = 0x%x, ",
+ m.typecode);
+ gdb_note ("offset = 0x%X, ", m.offset);
+ gdb_note ("size = %d);\n", m.size);
+ if ((ret = add_format_mem_ranges (format->id, &m)) !=
+ OK_TARGET_RESPONSE)
+ {
+ dtc_error_ret (-1, "add_format_mem_ranges", ret);
+ sprintp (spare_buffer,
+ "format id %d: memrange (0x%x, 0x%x, 0x%x).\n",
+ format->id, m.typecode, m.offset, m.size);
+ gdb_puts (spare_buffer);
+ return -1;
+ }
+ break;
+
+ case 'X': /* X<length>,<bytecodes> */
+ {
+ unsigned long length;
+
+ (*request)++;
+ hexToInt(request, &length);
+
+ if ((length <= 0) || (length > MAX_BYTE_CODES))
+ return error_ret (-1,
+ "Bytecode expression length (%d) too large\n",
+ length);
+
+ if (*(*request)++ != ',')
+ return error_ret (-1,
+ "Malformed bytecode expr (comma#%d missing)\n",
+ 1);
+ t_expr->next = NULL;
+ /* subtract one to account for expr[0] in header */
+ t_expr->size = sizeof(struct t_expr_tag) + length - 1;
+ t_expr->expr_size = length;
+
+ hex2mem(*request, &t_expr->expr[0], length, 0);
+ *request += 2 * length;
+ build_and_add_expression(format->id, t_expr);
+ }
+ break;
+ }
+ }
+ return 0;
+}
+
+static char *
+handle_trace_set (char *request)
+{
+ long n_frame;
+ unsigned long frameno, tdp, pc, start, stop;
+ DTC_RESPONSE ret = -1;
+ static COLLECTION_FORMAT_DEF tempfmt1;
+ static char enable;
+ static char retbuf[20];
+
+ if (msgcmp (&request, "init"))
+ {
+ gdb_note ("STUB: call clear_trace_state();\n", 0);
+ curframe.valid = 0; /* all old frames become invalid now */
+ if ((ret = clear_trace_state ()) == OK_TARGET_RESPONSE)
+ return "OK";
+ else
+ {
+ sprintp (retbuf, "E2%x", ret);
+ return (char *) dtc_error_ret ((int) &retbuf,
+ "clear_trace_state",
+ ret);
+ }
+ }
+ else if (msgcmp (&request, "Start"))
+ {
+ trace_running = 1;
+ curframe.valid = 0; /* all old frames become invalid now */
+ gdb_note ("STUB: call start_trace_experiment();\n", 0);
+ adbg_save_trace_in_nvd ();
+ if ((ret = start_trace_experiment ()) == OK_TARGET_RESPONSE)
+ return "OK";
+ else
+ {
+ sprintp (retbuf, "E2%x", ret);
+ return (char *) dtc_error_ret ((int) &retbuf,
+ "start_trace_experiment",
+ ret);
+ }
+ }
+ else if (msgcmp (&request, "Stop"))
+ {
+ trace_running = 0;
+ if (adbg_check_if_active ())
+ {
+ gdb_note ("STUB: call end_trace_experiment();\n", 0);
+ if ((ret = end_trace_experiment ()) == OK_TARGET_RESPONSE)
+ return "OK";
+ else
+ {
+ sprintp (retbuf, "E2%x", ret);
+ return (char *) dtc_error_ret ((int) &retbuf,
+ "end_trace_experiment",
+ ret);
+ }
+ }
+ else return "OK";
+ }
+ /* "TDP:" (The 'T' was consumed in handle_request.) */
+ else if (msgcmp (&request, "DP:"))
+ {
+ /* TDP:<id>:<addr>:{D,E}:<stepcount>:<pass_limit>{R[M,X]+}<tdp-format>
+ {S{R[M,X]+}}<tp-format>
+
+ D -- disable tracepoint (illegal from EMC's point of view)
+ E -- enable tracepoint?
+
+ R -- regs format: R<regs-mask>
+ M -- memory format: M<regnum>,<offset>,<size>
+ X -- expr format: X<size>,<bytecodes>
+ S -- fencepost between trap formats and stepping formats.
+ */
+
+ /* state variable, required for splitting TDP packets. */
+ static int doing_step_formats;
+
+ /*
+ * TDP: packets may now be split into multiple packets.
+ * If a TDP packet is to be continued in another packet, it
+ * must end in a "-" character. The subsequent continuation
+ * packet will then begin with a "-" character, between the
+ * token "TDP:" and the tdp_id field. The ID and address
+ * will be repeated in each sub-packet. The step_count,
+ * pass_count, and 'enabled' field must appear in the first
+ * packet. The boundary between sub-packets may not appear
+ * between the "S" that denotes the start of stepping "formats",
+ * and the regs_mask that follows it. The split may also not
+ * occur in the middle of either a memrange description or a
+ * bytecode string. -- MVS
+ */
+
+ if (*request == '-') /* this is a continuation of a
+ trace definition in progress */
+ {
+ unsigned long temp_id, temp_addr;
+
+ request++;
+ if (!(hexToInt (&request, &temp_id) &&
+ *request++ == ':'))
+ return "E11"; /* badly formed packet, field 1 */
+
+ if (!(hexToInt (&request, (unsigned long *) &temp_addr) &&
+ *request++ == ':'))
+ return "E12"; /* badly formed packet, field 2 */
+
+ if (temp_id != tdp_temp.id)
+ return "E11"; /* something wrong: field 1 doesn't match */
+ if (temp_addr != (unsigned long) tdp_temp.addr)
+ return "E12"; /* something wrong: field 2 doesn't match */
+ }
+ else /* This is a new TDP definition */
+ {
+ memset ((char *) &tdp_temp, 0, sizeof (tdp_temp));
+ memset ((char *) &tempfmt1, 0, sizeof (tempfmt1));
+ doing_step_formats = FALSE;
+
+ if (!(hexToInt (&request, &tdp_temp.id) &&
+ *request++ == ':'))
+ return "E11"; /* badly formed packet, field 1 */
+
+ if (!(hexToInt (&request, (unsigned long *) &tdp_temp.addr) &&
+ *request++ == ':'))
+ return "E12"; /* badly formed packet, field 2 */
+
+ if (!(((enable = *request++) == 'D' || enable == 'E') &&
+ *request++ == ':'))
+ return "E13"; /* badly formed packet, field 3 */
+#if 0
+ if (enable == 'D')
+ {
+ gdb_puts ("Disabling of tracepoints not supported by EMC target\n");
+ return "E20";
+ }
+#endif
+ if (!(hexToInt (&request, &tdp_temp.stepcount) &&
+ *request++ == ':'))
+ return "E14"; /* badly formed packet, field 4 */
+
+ if (!hexToInt (&request, &tdp_temp.pass_limit))
+ return "E15"; /* badly formed packet, field 5 */
+
+ }
+
+ /* Typically, the first group of collection descriptors
+ refers to the trap collection. There is an "S" token
+ to act as a fencepost between collection descriptors for
+ the trap, and those for the single-stepping.
+
+ However, when the packet is split up into several packets,
+ this "S" token may already have been seen in a previous
+ sub-packet; so we have to remember it in a state variable. */
+
+ if (*request == 'R' || *request == 'M' || *request == 'X')
+ {
+ if (handle_format (&request, &tempfmt1))
+ return "E16";
+ if (doing_step_formats)
+ tdp_temp.tp_format_p = tempfmt1.id;
+ else
+ tdp_temp.tdp_format_p = tempfmt1.id;
+ }
+
+ /* When we see the "S" token, we remember it in a state variable
+ (in case the packet is split up and continued in another message),
+ and discard all current state from the collection "format". */
+ if (*request == 'S')
+ {
+ doing_step_formats = TRUE;
+ /* discard prev format and start a new one */
+ memset ((char *) &tempfmt1, 0, sizeof (tempfmt1));
+ request++;
+
+ /* Having seen the "S" fencepost, it is now possible that
+ we will see some more collection descriptors pertaining
+ to the stepping collection. */
+ if (*request == 'R' || *request == 'M' || *request == 'X')
+ {
+ if (handle_format (&request, &tempfmt1))
+ return "E17";
+ /* new format ID is tp_format */
+ tdp_temp.tp_format_p = tempfmt1.id;
+ }
+ }
+
+ if (*request == '-') /* this TDP definition will be continued. */
+ sprintp (retbuf, "OK");
+ else if (enable == 'E') /* end of TDP definition: pass to ADBG (if enabled!) */
+ {
+ gdb_note ("STUB: call define_tdp (id %d, ", tdp_temp.id);
+ gdb_note ("addr 0x%X, ", (int) tdp_temp.addr);
+ gdb_note ("passc %d, ", tdp_temp.pass_limit);
+ gdb_note ("stepc %d, ", tdp_temp.stepcount);
+ gdb_note ("TDP fmt #%d, ", tdp_temp.tdp_format_p);
+ gdb_note ("TP fmt #%d);\n", tdp_temp.tp_format_p);
+
+ ret = define_tdp (tdp_temp.id, &tdp_temp, 0);
+
+ if (ret == OK_TARGET_RESPONSE)
+ {
+ sprintp (retbuf, "OK");
+ }
+ else
+ {
+ sprintp (spare_buffer,
+ "'define_tdp' returned DTC error '%s' for tracepoint %d.\n",
+ get_err_text (ret),
+ tdp_temp.id);
+ gdb_puts (spare_buffer);
+ sprintp (retbuf, "E2%x", ret);
+ }
+ /* Redundant, but let's try to make sure this state gets discarded. */
+ {
+ memset ((char *) &tdp_temp, 0, sizeof (tdp_temp));
+ memset ((char *) &tempfmt1, 0, sizeof (tempfmt1));
+ }
+ }
+ else /* ADBG_DTC does not support disabled tracepoints -- ignore it. */
+ gdb_note ("STUB: ignoring disabled tracepoint %d.\n", tdp_temp.id);
+
+ return retbuf;
+ }
+ else if (msgcmp (&request, "Frame:"))
+ {
+ ret = OK_TARGET_RESPONSE;
+
+ if (msgcmp (&request, "pc:"))
+ {
+ if (!hexToInt (&request, &pc))
+ return "E10"; /* badly formed packet */
+ n_frame = curframe.valid ? curframe.frame_id + 1 : 0;
+ gdb_note ("STUB: call fetch_trace_frame_pc (id %d, ", n_frame);
+ gdb_note ("pc 0x%X);\n", pc);
+ ret = fetch_trace_frame_with_pc (&n_frame,
+ (void *) pc,
+ &curframe.format,
+ &curframe.frame_data);
+ }
+ else if (msgcmp (&request, "tdp:"))
+ {
+ if (!hexToInt (&request, &tdp))
+ return "E10"; /* badly formed packet */
+ n_frame = curframe.valid ? curframe.frame_id + 1: 0;
+ gdb_note ("STUB: call fetch_trace_frame_tdp (id %d, ", n_frame);
+ gdb_note ("tdp 0x%X);\n", tdp);
+ ret = fetch_trace_frame_with_tdp (&n_frame,
+ tdp,
+ &curframe.format,
+ &curframe.frame_data);
+ }
+ else if (msgcmp (&request, "range:"))
+ {
+ if (!(hexToInt (&request, &start) &&
+ *request++ == ':'))
+ return "E11"; /* badly formed packet, field 1 */
+ else if (!hexToInt (&request, &stop))
+ return "E12"; /* badly formed packet, field 2 */
+ n_frame = curframe.valid ? curframe.frame_id + 1: 0;
+ gdb_note ("STUB: call fetch_trace_frame_range (id %d, ", n_frame);
+ gdb_note ("start 0x%X, ", start);
+ gdb_note ("stop 0x%X);\n", stop);
+ ret = fetch_trace_frame_with_pc_in_range (&n_frame,
+ (void *) start,
+ (void *) stop,
+ &curframe.format,
+ &curframe.frame_data);
+ }
+ else if (msgcmp (&request, "outside:"))
+ {
+ if (!(hexToInt (&request, &start) &&
+ *request++ == ':'))
+ return "E11"; /* badly formed packet, field 1 */
+ else if (!hexToInt (&request, &stop))
+ return "E12"; /* badly formed packet, field 2 */
+ n_frame = curframe.valid ? curframe.frame_id + 1: 0;
+ gdb_note ("STUB: call fetch_trace_frame_outside (id %d, ", n_frame);
+ gdb_note ("start 0x%X, ", start);
+ gdb_note ("stop 0x%X);\n", stop);
+ ret = fetch_trace_frame_with_pc_outside (&n_frame,
+ (void *) start,
+ (void *) stop,
+ &curframe.format,
+ &curframe.frame_data);
+ }
+ else /* simple TFind by frame number: */
+ {
+ if (!hexToInt (&request, &frameno))
+ return "E10"; /* badly formed packet */
+ if (frameno != (unsigned long) -1)
+ {
+ gdb_note ("STUB: call fetch_trace_frame (id %d);\n", frameno);
+ ret = fetch_trace_frame (n_frame = frameno,
+ &curframe.format,
+ &curframe.frame_data);
+#if 0
+ printp("STUB: fetch_trace_frame: return %d\n", ret);
+#endif
+ }
+ else /* discard any trace frame, debug "the real world" */
+ {
+ if (curframe.valid)
+ gdb_note ("STUB: discard current trace frame #%d.\n",
+ curframe.frame_id);
+ curframe.valid = 0;
+ return "OK";
+ }
+ }
+ if (ret == OK_TARGET_RESPONSE) /* fetch_trace_frame succeeded */
+ { /* setup for debugging the trace frame */
+ curframe.valid = 1;
+ curframe.frame_id = n_frame;
+ curframe.tdp_id = curframe.frame_data->id;
+
+ memset ((char *) &curframe.traceregs, 0,
+ sizeof (curframe.traceregs));
+ curframe.traceregs[PC] = (unsigned long)
+ curframe.frame_data->program_counter;
+
+ if (curframe.format)
+ {
+ unsigned long regs_mask = curframe.format->regs_mask;
+ unsigned long *regs, *stack, *mem;
+ unsigned long regno, index = 0;
+ CFD *dummy;
+
+ if ((ret = get_addr_to_frame_regs_stack_mem
+ (curframe.frame_data, &dummy, &regs, &stack, &mem))
+ != OK_TARGET_RESPONSE)
+ {
+ curframe.valid = 0;
+ sprintp (retbuf, "E2%x", ret);
+ return (char *)
+ dtc_error_ret ((int) &retbuf,
+ "get_addr_to_frame_regs_stack_mem",
+ ret);
+ }
+
+ if (remote_debug > 1)
+ { /* echo what we've found to gdb console */
+ sprintp (spare_buffer,
+ "STUB: Found frame %d, TDP %d, format %d (%s):\n",
+ curframe.frame_id,
+ curframe.tdp_id & 0x7fffffff,
+ curframe.format->id,
+ curframe.tdp_id & 0x80000000 ?
+ "trap frame" : "stepping frame");
+ gdb_puts (spare_buffer);
+ }
+ /* copy trace frame regs into stub's data format */
+ for (regno = 0, index = 0;
+ regno < 16;
+ regno++, regs_mask >>= 1)
+ if (regs_mask & 1) /* got a collected register */
+ {
+ curframe.traceregs[regno] = regs[index++];
+ if (remote_debug > 1)
+ {
+ sprintp (spare_buffer,
+ " Collected 0x%08x for register %d.\n",
+ curframe.traceregs[regno], regno);
+ gdb_puts (spare_buffer);
+ }
+ }
+ if (remote_debug > 1)
+ {
+ long midx, ridx, len;
+ MEMRANGE_DEF *mrange;
+ unsigned char *data, *base;
+
+ if (curframe.format->stack_size > 0)
+ {
+ len = curframe.format->stack_size;
+ sprintp (spare_buffer,
+ " Collected %d bytes of stack at 0x%x:\n",
+ len, curframe.traceregs[A7]);
+ gdb_puts (spare_buffer);
+
+ /* print stack data, but stay under msg len */
+ if (len >= (NUMREGBYTES/2 - 2))
+ len = (NUMREGBYTES/2 - 3);
+ mem2hex ((unsigned char *) stack,
+ spare_buffer, len, 0);
+ spare_buffer [len * 2] = '\n';
+ spare_buffer [len * 2 + 1] = '\0'; /* EOS */
+ gdb_puts (spare_buffer);
+ }
+ else
+ gdb_puts ("Stack not collected\n");
+
+ for (midx = 0;
+ get_addr_to_a_mem_range (curframe.frame_data,
+ midx,
+ &mrange,
+ (void **) &data)
+ == OK_TARGET_RESPONSE;
+ midx++)
+ {
+ if ((mrange->typecode == 0) ||
+ (mrange->typecode == (unsigned long) -1))
+ {
+ sprintp (spare_buffer,
+ " Collected %d bytes at MEM: 0x%x:\n",
+ mrange->size, mrange->offset);
+ base = (unsigned char *) mrange->offset;
+ }
+ else
+ {
+ if ((ridx = elinum_to_index (mrange->typecode)) > 0)
+ base = (unsigned char *) curframe.traceregs[ridx]
+ + (long) mrange->offset;
+ else
+ {
+ sprintp (spare_buffer,
+ "STUB: bad typecode in memrange #%d: (0x%x,0x%x,0x%x).\n",
+ midx,
+ mrange->typecode,
+ mrange->offset,
+ mrange->size);
+ gdb_puts (spare_buffer);
+ continue;
+ }
+ sprintp (spare_buffer,
+ " Collected %d bytes at 0x%x (REG %X + %d):\n",
+ mrange->size,
+ base,
+ mrange->typecode,
+ mrange->offset);
+ }
+ gdb_puts (spare_buffer);
+ len = mrange->size;
+ if (len >= (NUMREGBYTES/2 - 2))
+ len = (NUMREGBYTES/2 - 3);
+ mem2hex (data, spare_buffer, len, 0);
+ spare_buffer [len * 2] = '\n';
+ spare_buffer [len * 2 + 1] = '\0'; /* EOS */
+ gdb_puts (spare_buffer);
+ }
+ }
+ }
+ sprintp (retbuf, "F%xT%x", n_frame, curframe.tdp_id & 0x7fffffff);
+ return retbuf;
+ }
+ else if (ret == NOT_FOUND_TARGET_RESPONSE)
+ {
+ /* Here's a question: if the fetch_trace_frame call failed
+ (which probably means a bad "TFIND" command from GDB),
+ should we remain focused on the previous frame (if any),
+ or should we revert to "no current frame"?
+ */
+ return "F-1";
+ }
+ else
+ {
+ sprintp (retbuf, "E2%x", ret);
+ return (char *) dtc_error_ret ((int) &retbuf,
+ "fetch_trace_frame[...]",
+ ret);
+ }
+ }
+ else /* unknown trace command */
+ {
+ return "";
+ }
+}
+
+/* Table used by the crc32 function to calcuate the checksum. */
+static unsigned long crc32_table[256];
+
+static int crc_mem_err;
+
+static unsigned long
+crc32 (buf, len, crc)
+ unsigned char *buf;
+ int len;
+ unsigned long crc;
+{
+ crc_mem_err = FALSE;
+
+ if (! crc32_table[1])
+ {
+ /* Initialize the CRC table and the decoding table. */
+ int i, j;
+ unsigned int c;
+
+ for (i = 0; i < 256; i++)
+ {
+ for (c = i << 24, j = 8; j > 0; --j)
+ c = c & 0x80000000 ? (c << 1) ^ 0x04c11db7 : (c << 1);
+ crc32_table[i] = c;
+ }
+ }
+
+ while (len--)
+ {
+ if (read_access_violation (buf))
+ {
+ crc_mem_err = TRUE;
+ return -1;
+ }
+ crc = (crc << 8) ^ crc32_table[((crc >> 24) ^ *buf++) & 255];
+ }
+ return crc;
+}
+
+static char *
+crc_query (cmd)
+ char *cmd;
+{
+ unsigned long startmem, len, crc;
+ static char buf[32];
+
+ if (hexToInt (&cmd, &startmem) &&
+ *cmd++ == ',' &&
+ hexToInt (&cmd, &len))
+ {
+ crc = crc32 ((unsigned char *) startmem, len, 0xffffffff);
+ if (!crc_mem_err)
+ {
+ sprintp (buf, "C%08x", crc);
+ return buf;
+ }
+ /* else error, fall thru */
+ }
+ sprintp (buf, "E01");
+ return buf;
+}
+
+
+static char *
+handle_test (request)
+ char *request;
+{
+ ULONG args[7];
+ int i;
+
+ /* Parse the arguments, a comma-separated list of hex numbers, into
+ ARGS. Parse at most six arguments. */
+ i = 1;
+ if (*request != '\0')
+ while (i < 7)
+ {
+ if (! hexToInt (&request, &args[i++]))
+ return "E01";
+ if (*request == '\0')
+ break;
+ if (*request++ != ',')
+ return "E01";
+ }
+
+ /* Fill the rest of the args array with zeros. This is what the
+ INLINES command processor does with omitted arguments. */
+ for (; i < 7; i++)
+ args[i] = 0;
+
+ gdb_c_test (args);
+
+ return "OK";
+}
+
+
+/* GDB_TRAP_1_HANDLER
+
+ By the time this is called, the registers have been saved in "registers",
+ and the interrupt priority has been set to permit serial UART interrupts.
+
+ However, since no gdb request has yet been received, and there is no
+ equivalent of getpacket for us to wait on, we can't sit here waiting
+ for packets and processing them.
+
+ In fact, the ONLY thing for us to do here is sit and wait.
+ As gdb sends packet requests, they will handle themselves at the
+ interrupt level. When gdb decides we can continue, it will reset
+ the global variable "gdb_handling_trap1", and we will return
+ (whereupon registers will be restored etc.) */
+
+void gdb_trap_1_handler( void )
+{
+ gdb_handling_trap1 = TRUE;
+ sss_trace_flag = '\0'; /* shut off "trace bit" (indirectly) */
+ gdb_signo = 5;
+ putpacket( "S05" );
+ while ( gdb_handling_trap1 )
+ ;
+ return;
+}
+
+void gdb_trace_handler( void )
+{
+ sss_trace_flag = '\0'; /* shut off "trace bit" (indirectly) */
+ gdb_handling_trap1 = TRUE;
+ gdb_handling_sstrace = TRUE;
+ gdb_signo = 5;
+ putpacket( "S05" );
+ while ( gdb_handling_trap1 )
+ ;
+ return;
+}
diff --git a/gdb/testsuite/gdb.trace/infotrace.exp b/gdb/testsuite/gdb.trace/infotrace.exp
new file mode 100644
index 00000000000..16cf25ef4c3
--- /dev/null
+++ b/gdb/testsuite/gdb.trace/infotrace.exp
@@ -0,0 +1,99 @@
+# Copyright (C) 1998 Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file was written by Michael Snyder (msnyder@cygnus.com)
+
+load_lib "trace-support.exp";
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+set prms_id 0
+set bug_id 0
+
+gdb_exit
+gdb_start
+
+if [istarget "m68k-*-elf"] then {
+ set srcfile gdb_c_test.c
+ set binfile [board_info target d490_binfile];
+} else {
+ set testfile "actions"
+ set srcfile ${testfile}.c
+ set binfile $objdir/$subdir/$testfile
+ if { [gdb_compile "$srcdir/$subdir/$srcfile" $binfile \
+ executable {debug additional_flags=-w}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+ }
+}
+gdb_reinitialize_dir $srcdir/$subdir
+
+# If testing on a remote host, download the source file.
+# remote_download host $srcdir/$subdir/$srcfile
+
+gdb_file_cmd $binfile
+
+#
+# test "info tracepoints" command
+#
+
+gdb_delete_tracepoints
+set c_test_num [gdb_gettpnum gdb_c_test];
+set asm_test_num [gdb_gettpnum gdb_asm_test];
+if { $c_test_num <= 0 || $asm_test_num <= 0 } then {
+ fail "setting tracepoints"
+ return;
+}
+
+# 2.1 info tracepoints (all)
+gdb_test "info tracepoints" \
+ "Num Enb Address PassC StepC What.*$c_test_num\[\t \]+y\[\t \]+0x\[0-9a-fA-F\]+.*in gdb_c_test.*$asm_test_num\[\t \]+y\[\t \]+0x\[0-9a-fA-F\]+.*gdb_asm_test.*" \
+ "2.1: info tracepoints (all)"
+
+# 2.2 info tracepoint (specific)
+gdb_test "info tracepoint $c_test_num" \
+ "$c_test_num\[\t \]+y\[\t \]+0x\[0-9a-fA-F\]+.*in gdb_c_test.*" \
+ "2.2a: info tracepoint $c_test_num (gdb_c_test)"
+
+gdb_test "info tracepoint $asm_test_num" \
+ "$asm_test_num\[\t \]+y\[\t \]+0x\[0-9a-fA-F\]+.*gdb_asm_test.*" \
+ "2.2b: info tracepoint $asm_test_num (gdb_asm_test)"
+
+# 2.3 info tracepoint (invalid tracepoint number)
+gdb_test "info tracepoint [expr $c_test_num + $asm_test_num]" \
+ "No tracepoint number [expr $c_test_num + $asm_test_num]." \
+ "2.3: info tracepoint (invalid tracepoint number)"
+
+# 2.4 info tracepoints (list of numbers)
+send_gdb "info tracepoints $c_test_num $asm_test_num \n"
+gdb_expect {
+ -re "Num Enb .*$gdb_prompt $" {
+ fail "2.4: info trace rejects multiple tracepoint numbers"
+ }
+ -re ".*$gdb_prompt $" {
+ pass "2.4: info trace rejects multiple tracepoint numbers"
+ }
+}
+
+# 2.5 help info trace
+gdb_test "help info tracepoints" \
+ "Status of tracepoints, or tracepoint number NUMBER.*" \
+ "2.5: help info tracepoints"
+
diff --git a/gdb/testsuite/gdb.trace/limits.c b/gdb/testsuite/gdb.trace/limits.c
new file mode 100644
index 00000000000..d9c02e74bac
--- /dev/null
+++ b/gdb/testsuite/gdb.trace/limits.c
@@ -0,0 +1,51 @@
+/*
+ * Test program for tracing internal limits (number of tracepoints etc.)
+ */
+
+int n = 6;
+
+int arr[64];
+
+static void foo(int x)
+{
+}
+
+static void bar(int y)
+{
+}
+
+static void baz(int z)
+{
+}
+
+static void begin () /* called before anything else */
+{
+}
+
+static void end () /* called after everything else */
+{
+}
+
+int
+main (argc, argv, envp)
+ int argc;
+ char *argv[], **envp;
+{
+ int i;
+
+#ifdef usestubs
+ set_debug_traps ();
+ breakpoint ();
+#endif
+
+ begin ();
+ for (i = 0; i < sizeof(arr) / sizeof(arr[0]); i++)
+ arr[i] = i + 1;
+
+ foo (1);
+ bar (2);
+ baz (3);
+ end ();
+ return 0;
+}
+
diff --git a/gdb/testsuite/gdb.trace/limits.exp b/gdb/testsuite/gdb.trace/limits.exp
new file mode 100644
index 00000000000..00e15b2adba
--- /dev/null
+++ b/gdb/testsuite/gdb.trace/limits.exp
@@ -0,0 +1,316 @@
+# Copyright (C) 1998 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+if [istarget "m68k-*-elf"] then {
+ pass "Test not supported on this target"
+ return;
+}
+
+load_lib "trace-support.exp"
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+set prms_id 0
+set bug_id 0
+
+set testfile "limits"
+set srcfile ${testfile}.c
+set binfile $objdir/$subdir/$testfile
+
+if { [gdb_compile "$srcdir/$subdir/$srcfile" $binfile \
+ executable {debug additional_flags=-w}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+# Tests:
+# 1) Meet and exceed artificial limit on number of tracepoints
+# 2) Meet and exceed artificial limit on number of memranges
+# 3) Meet and exceed artificial limit on bytes of bytecode data
+# [NOTE: number four is moved out into its own separate test module.]
+# 4) Meet and exceed artificial limit on bytes of trace buffer storage
+# (circular and non-circular modes). However note that a more
+# thorough test of the circular mode can be made separately.
+
+set cr "\[\r\n\]+"
+
+proc gdb_tracepoint_limit_test { } {
+ global gdb_prompt
+ global cr
+
+ # Make sure we're in a sane starting state.
+ gdb_test "tstop" "" ""
+ gdb_test "tfind none" "" ""
+ gdb_delete_tracepoints
+
+ # Set three tracepoints
+ gdb_test "trace foo" \
+ "Tracepoint \[0-9\]+ at .*" \
+ "tracepoint limit test: set first tracepoint"
+
+ gdb_test "trace bar" \
+ "Tracepoint \[0-9\]+ at .*" \
+ "tracepoint limit test: set second tracepoint"
+
+ gdb_test "trace baz" \
+ "Tracepoint \[0-9\]+ at .*" \
+ "tracepoint limit test: set third tracepoint"
+
+ # Set secret artificial tracepoint limit to four
+ gdb_test "maint packet QTLimit:tp:4" \
+ "received: .OK." \
+ "tracepoint limit test: set limit to four"
+
+ # Now sending three tracepoints should succeed.
+ send_gdb "tstart\n"
+ gdb_expect {
+ -re "$cr$gdb_prompt" {
+ pass "tracepoint limit test: send fewer than limit"
+ }
+ default {
+ fail "tracepoint limit test: send fewer than limit"
+ }
+ }
+
+ # Set secret artificial tracepoint limit to three
+ gdb_test "maint packet QTLimit:tp:3" \
+ "received: .OK." \
+ "tracepoint limit test: set limit to three"
+
+ # Now sending three tracepoints should still succeed.
+ send_gdb "tstart\n"
+ gdb_expect {
+ -re "$cr$gdb_prompt" {
+ pass "tracepoint limit test: send equal to limit"
+ }
+ default {
+ fail "tracepoint limit test: send equal to limit"
+ }
+ }
+
+ # Set secret artificial tracepoint limit to two
+ gdb_test "maint packet QTLimit:tp:2" \
+ "received: .OK." \
+ "tracepoint limit test: set limit to two"
+
+ # Now sending three tracepoints should fail.
+ gdb_test "tstart" \
+ ".*\[Ee\]rror.*" \
+ "tracepoint limit test: send more than limit"
+
+ # Clean up:
+ gdb_test "tstop" "" ""
+ gdb_test "maint packet QTLimit:tp:FFFFFFFF" "" ""
+}
+
+proc gdb_memrange_limit_test { } {
+ global gdb_prompt
+ global cr
+
+ # Make sure we're in a sane starting state.
+ gdb_test "tstop" "" ""
+ gdb_test "tfind none" "" ""
+ gdb_delete_tracepoints
+
+ # Set three tracepoints, and make 'em collect memranges
+ gdb_test "trace foo" \
+ "Tracepoint \[0-9\]+ at .*" \
+ "memrange limit test: set first tracepoint"
+
+ gdb_trace_setactions "memrange limit test: set first actions" \
+ "" \
+ "collect \$arg" "^$"
+
+ gdb_test "trace bar" \
+ "Tracepoint \[0-9\]+ at .*" \
+ "memrange limit test: set second tracepoint"
+
+ gdb_trace_setactions "memrange limit test: set second actions" \
+ "" \
+ "collect \$arg" "^$"
+
+ gdb_test "trace baz" \
+ "Tracepoint \[0-9\]+ at .*" \
+ "memrange limit test: set third tracepoint"
+
+ gdb_trace_setactions "memrange limit test: set third actions" \
+ "" \
+ "collect \$arg" "^$"
+
+ # Set secret artificial memrange limit to four
+ gdb_test "maint packet QTLimit:memrange:4" \
+ "received: .OK." \
+ "memrange limit test: set limit to four"
+
+ # Now sending three memranges should still succeed.
+ send_gdb "tstart\n"
+ gdb_expect {
+ -re "$cr$gdb_prompt" {
+ pass "memrange limit test: send fewer than limit"
+ }
+ default {
+ fail "memrange limit test: send fewer than limit"
+ }
+ }
+
+ # Set secret artificial memrange limit to three
+ gdb_test "maint packet QTLimit:memrange:3" \
+ "received: .OK." \
+ "memrange limit test: set limit to three"
+
+ # Now sending three memranges should still succeed.
+ send_gdb "tstart\n"
+ gdb_expect {
+ -re "$cr$gdb_prompt" {
+ pass "memrange limit test: send equal to limit"
+ }
+ default {
+ fail "memrange limit test: send equal to limit"
+ }
+ }
+
+ # Set secret artificial memrange limit to two
+ gdb_test "maint packet QTLimit:memrange:2" \
+ "received: .OK." \
+ "memrange limit test: set limit to two"
+
+ # Now sending three memranges should fail.
+ gdb_test "tstart" \
+ ".*\[Ee\]rror.*" \
+ "memrange limit test: send more than limit"
+
+ # Clean up:
+ gdb_test "tstop" "" ""
+ gdb_test "maint packet QTLimit:memrange:FFFFFFFF" "" ""
+}
+
+
+proc gdb_bytecode_limit_test { } {
+ global gdb_prompt
+ global cr
+
+ # Make sure we're in a sane starting state.
+ gdb_test "tstop" "" ""
+ gdb_test "tfind none" "" ""
+ gdb_delete_tracepoints
+
+ # Set three tracepoints
+ gdb_test "trace foo" \
+ "Tracepoint \[0-9\]+ at .*" \
+ "bytecode limit test: set first tracepoint"
+
+ gdb_trace_setactions "bytecode limit test: set first actions" \
+ "" \
+ "collect x + n" "^$"
+
+ gdb_test "trace bar" \
+ "Tracepoint \[0-9\]+ at .*" \
+ "bytecode limit test: set second tracepoint"
+
+ gdb_trace_setactions "bytecode limit test: set second actions" \
+ "" \
+ "collect y + n" "^$"
+
+ gdb_test "trace baz" \
+ "Tracepoint \[0-9\]+ at .*" \
+ "bytecode limit test: set third tracepoint"
+
+ gdb_trace_setactions "bytecode limit test: set third actions" \
+ "" \
+ "collect z + n" "^$"
+
+ # Set secret artificial bytecode limit to a large number
+ gdb_test "maint packet QTLimit:bytecode:400" \
+ "received: .OK." \
+ "bytecode limit test: set limit to large"
+
+ # Now sending three bytecodes should still succeed.
+ send_gdb "tstart\n"
+ gdb_expect {
+ -re "$cr$gdb_prompt" {
+ pass "bytecode limit test: send fewer than limit"
+ }
+ default {
+ fail "bytecode limit test: send fewer than limit"
+ }
+ }
+
+ # Set secret artificial bytecode limit to a small number
+ gdb_test "maint packet QTLimit:bytecode:40" \
+ "received: .OK." \
+ "bytecode limit test: set limit to small"
+
+ # Now sending three bytecodes should fail.
+ gdb_test "tstart" \
+ ".*\[Ee\]rror.*" \
+ "bytecode limit test: send more than limit"
+
+
+ # Clean up:
+ gdb_test "tstop" "" ""
+ gdb_test "maint packet QTLimit:bytecode:FFFFFFFF" "" ""
+}
+
+proc gdb_trace_limits_tests { } {
+ global gdb_prompt
+
+ # We generously give ourselves one "pass" if we successfully
+ # detect that this test cannot be run on this target!
+
+ if { ![gdb_target_supports_trace] } then {
+ pass "Current target does not supporst trace"
+ return 1;
+ }
+
+ if [gdb_test "maint packet QTLimit:tp:ffffffff" \
+ "received: .OK." ""] then {
+ pass "This test cannot be run on this target"
+ return 1;
+ }
+
+ if [gdb_test "maint packet QTLimit:memrange:ffffffff" \
+ "received: .OK." ""] then {
+ pass "This test cannot be run on this target"
+ return 1;
+ }
+
+ if [gdb_test "maint packet QTLimit:bytecode:ffffffff" \
+ "received: .OK." ""] then {
+ pass "This test cannot be run on this target"
+ return;
+ }
+
+ gdb_tracepoint_limit_test
+ gdb_memrange_limit_test
+ gdb_bytecode_limit_test
+}
+
+# Start with a fresh gdb.
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load $binfile
+
+if [target_info exists gdb_stub] {
+ gdb_step_for_stub;
+}
+# Body of test encased in a proc so we can return prematurely.
+gdb_trace_limits_tests
diff --git a/gdb/testsuite/gdb.trace/packetlen.exp b/gdb/testsuite/gdb.trace/packetlen.exp
new file mode 100644
index 00000000000..fd53e45bd4f
--- /dev/null
+++ b/gdb/testsuite/gdb.trace/packetlen.exp
@@ -0,0 +1,100 @@
+# Copyright (C) 1998 Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file was written by Michael Snyder (msnyder@cygnus.com)
+
+load_lib "trace-support.exp"
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+set prms_id 0
+set bug_id 0
+
+gdb_exit
+gdb_start
+
+if [istarget "m68k-*-elf"] then {
+ load_lib "emc-support.exp"
+ set srcfile gdb_c_test.c
+ set binfile [board_info target d490_binfile];
+ gdb_test "set remotetimeout 6" "" ""
+ set timeout 500
+ gdb_target_monitor "$binfile"
+ # Give a TSTOP and ignore errors, to make sure any previous trace is off
+ gdb_test "tstop" "" ""
+ gdb_test "tfind none" "" ""
+ send_gdb "compare-sections CS\n"
+ gdb_expect {
+ -re "MIS-MATCHED.*$gdb_prompt $" {
+ gdb_suppress_entire_file "Symbol file does not match target!
+ all tests in this module will fail.";
+ }
+ -re ".*$gdb_prompt $" { }
+ }
+} else {
+ set testfile "actions"
+ set srcfile ${testfile}.c
+ set binfile $objdir/$subdir/$testfile
+ if { [gdb_compile "$srcdir/$subdir/$srcfile" $binfile \
+ executable {debug additional_flags=-w}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+ }
+ gdb_load $binfile
+ gdb_test "tstop" "" ""
+ gdb_test "tfind none" "" ""
+ runto_main
+}
+gdb_reinitialize_dir $srcdir/$subdir
+
+# If testing on a remote host, download the source file.
+# remote_download host $srcdir/$subdir/$srcfile
+
+#
+# Test collecting a whole bunch of stuff at a single tracepoint.
+# The test is whether this crashes GDB.
+#
+
+gdb_delete_tracepoints
+gdb_test "trace gdb_c_test" "" ""
+gdb_trace_setactions "setup collect actions" \
+ "" \
+ "collect parm\[0\], parm\[1\], parm\[2\], parm\[3\]" "^$" \
+ "collect parm\[4\], parm\[5\], parm\[6\], parm\[7\]" "^$" \
+ "collect p, local_reg, local_static, local_static_sizeof" "^$" \
+ "collect local_long, stack_ptr, end_of_stack" "^$" \
+ "collect gdb_char_test, gdb_short_test, gdb_long_test" "^$" \
+ "collect gdb_arr_test, gdb_struct1_test, gdb_struct2_test" "^$" \
+ "collect gdb_structp_test, gdb_structpp_test, gdb_union1_test" "^$" \
+ "end" ""
+
+gdb_test "tstart" "" "survive the long packet send"
+if [istarget "m68k-*-elf"] then {
+ gdb_emclaptop_command "85,1,2,3,4,5,6"
+ sleep 5
+} else {
+ gdb_test "break end" "" ""
+ gdb_test "continue" \
+ "Continuing.*Breakpoint $decimal, end.*" \
+ "run trace experiment"
+}
+
+gdb_test "tstop" "" "confirm: survived the long packet send"
+
diff --git a/gdb/testsuite/gdb.trace/passc-dyn.exp b/gdb/testsuite/gdb.trace/passc-dyn.exp
new file mode 100644
index 00000000000..930a2ec3e78
--- /dev/null
+++ b/gdb/testsuite/gdb.trace/passc-dyn.exp
@@ -0,0 +1,181 @@
+# Copyright (C) 1998 Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file was written by Michael Snyder (msnyder@cygnus.com)
+
+load_lib "trace-support.exp";
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+set prms_id 0
+set bug_id 0
+
+gdb_exit
+gdb_start
+if [istarget "m68k-*-elf"] then {
+ load_lib "emc-support.exp";
+ set srcfile gdb_c_test.c
+ set binfile [board_info target d490_binfile];
+ gdb_test "set remotetimeout 6" "" ""
+ set timeout 500
+ gdb_target_monitor $binfile
+ # Give a TSTOP and ignore errors, to make sure any previous trace is off
+ gdb_test "tstop" "" ""
+ gdb_test "tfind none" "" ""
+ send_gdb "compare-sections CS\n"
+ gdb_expect {
+ -re "MIS-MATCHED.*$gdb_prompt $" {
+ gdb_suppress_entire_file "Symbol file does not match target!
+ all tests in this module will fail.";
+ }
+ -re ".*$gdb_prompt $" { }
+ }
+} else {
+ set testfile "actions"
+ set srcfile ${testfile}.c
+ set binfile $objdir/$subdir/$testfile
+ if { [gdb_compile "$srcdir/$subdir/$srcfile" $binfile \
+ executable {debug additional_flags=-w}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+ }
+ gdb_load $binfile
+ gdb_test "tstop" "" ""
+ gdb_test "tfind none" "" ""
+ runto_main
+}
+gdb_reinitialize_dir $srcdir/$subdir
+
+# We generously give ourselves one "pass" if we successfully
+# detect that this test cannot be run on this target!
+if { ![gdb_target_supports_trace] } then {
+ pass "Current target does not supporst trace"
+ return 1;
+
+}
+
+# If testing on a remote host, download the source file.
+# remote_download host $srcdir/$subdir/$srcfile
+
+
+#
+# test passcount dynamically (live target)
+#
+
+set baseline [gdb_find_recursion_test_baseline $srcfile];
+
+if { $baseline == -1 } then {
+ fail "Could not find gdb_recursion_test function"
+ return;
+}
+
+# define relative source line numbers:
+# all subsequent line numbers are relative to this first one (baseline)
+
+set testline2 [expr $baseline + 4]
+set testline3 [expr $baseline + 5]
+set testline4 [expr $baseline + 6]
+
+#
+# test passcount command semantics (live test)
+#
+
+## Set three tracepoints with three different passcounts.
+## Verify that the experiment stops after the one with the
+## lowest passcount is hit.
+
+gdb_delete_tracepoints
+set tdp2 [gdb_gettpnum "$testline2"]
+set tdp3 [gdb_gettpnum "$testline3"]
+set tdp4 [gdb_gettpnum "$testline4"]
+if { $tdp2 <= 0 || $tdp3 <= 0 || $tdp4 <= 0 } then {
+ fail "setting tracepoints"
+ return;
+}
+
+gdb_test "passcount 4 $tdp2" "Setting tracepoint $tdp2's passcount to 4" \
+ "4.5: set passcount for tracepoint $tdp2"
+gdb_test "passcount 2 $tdp3" "Setting tracepoint $tdp3's passcount to 2" \
+ "4.5: set passcount for tracepoint $tdp3"
+gdb_test "passcount 3 $tdp4" "Setting tracepoint $tdp4's passcount to 3" \
+ "4.5: set passcount for tracepoint $tdp4"
+
+gdb_test "tstart" "" ""
+
+if [istarget "m68k-*-elf"] then {
+ gdb_emclaptop_command "85,1,2,3,4,5,6"
+ sleep 5
+ gdb_emclaptop_command "85,7,8,9,A,B,C"
+ sleep 5
+ gdb_emclaptop_command "85,D,E,F,10,11,12"
+ sleep 5
+ # gdb_test "tstop"
+ ##
+ ## Note! Must NOT give the tstop command, because the passcount
+ ## has already stopped the experiment. You would not
+ ## think this would be an error, but in EMC's mind it is...
+ ##
+} else {
+ gdb_test "break end" "" ""
+ gdb_test "continue" \
+ "Continuing.*Breakpoint $decimal, end.*" \
+ "run trace experiment"
+ gdb_test "tstop" "" ""
+}
+
+gdb_test "tfind none" "" ""
+if [gdb_test "printf \"x \%d x\\n\", \$trace_frame" "x -1 x" ""] {
+ gdb_suppress_entire_file "0: tfind none failed"
+}
+
+gdb_test "tfind tracepoint $tdp2" "" ""
+if [gdb_test "printf \"x \%d x\\n\", \$trace_frame" "x 0 x" ""] {
+ gdb_suppress_entire_file "1: first tfind failed"
+}
+
+gdb_test "tfind tracepoint $tdp3" "" ""
+if [gdb_test "printf \"x \%d x\\n\", \$trace_frame" "x 1 x" ""] {
+ gdb_suppress_entire_file "2: second tfind failed"
+}
+
+gdb_test "tfind tracepoint $tdp4" "" ""
+if [gdb_test "printf \"x \%d x\\n\", \$trace_frame" "x 2 x" ""] {
+ gdb_suppress_entire_file "3: third tfind failed"
+}
+
+gdb_test "tfind tracepoint $tdp2" "" ""
+if [gdb_test "printf \"x \%d x\\n\", \$trace_frame" "x 3 x" ""] {
+ gdb_suppress_entire_file "4: fourth tfind failed"
+}
+
+gdb_test "tfind tracepoint $tdp3" "" ""
+if [gdb_test "printf \"x \%d x\\n\", \$trace_frame" "x 4 x" ""] {
+ gdb_suppress_entire_file "5: fifth tfind failed"
+}
+
+## We should now be at the last frame, because this frame's passcount
+## should have caused collection to stop. If we do a tfind now,
+## it should fail.
+
+gdb_test "tfind" "failed to find.*" "4.5: dynamic passcount test"
+
+# Finished!
+gdb_test "tfind none" "" ""
+
diff --git a/gdb/testsuite/gdb.trace/passcount.exp b/gdb/testsuite/gdb.trace/passcount.exp
new file mode 100644
index 00000000000..eae6ddfb8c0
--- /dev/null
+++ b/gdb/testsuite/gdb.trace/passcount.exp
@@ -0,0 +1,178 @@
+# Copyright (C) 1998 Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file was written by Michael Snyder (msnyder@cygnus.com)
+
+load_lib "trace-support.exp";
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+set prms_id 0
+set bug_id 0
+
+gdb_exit
+gdb_start
+if [istarget "m68k-*-elf"] then {
+ set srcfile gdb_c_test.c
+ set binfile [board_info target d490_binfile];
+} else {
+ set testfile "actions"
+ set srcfile ${testfile}.c
+ set binfile $objdir/$subdir/$testfile
+ if { [gdb_compile "$srcdir/$subdir/$srcfile" $binfile \
+ executable {debug additional_flags=-w}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+ }
+}
+gdb_reinitialize_dir $srcdir/$subdir
+
+# If testing on a remote host, download the source file.
+# remote_download host $srcdir/$subdir/$srcfile
+
+gdb_file_cmd $binfile
+
+# define relative source line numbers:
+# all subsequent line numbers are relative to this first one (baseline)
+set baseline [gdb_find_recursion_test_baseline $srcfile];
+if { $baseline == -1 } then {
+ fail "Could not find gdb_recursion_test function"
+ return;
+}
+
+set testline1 [expr $baseline + 3]
+
+#
+# test "passcount" command
+#
+
+gdb_delete_tracepoints
+set trcpt1 [gdb_gettpnum gdb_c_test];
+set trcpt2 [gdb_gettpnum gdb_asm_test];
+set trcpt3 [gdb_gettpnum $testline1];
+if { $trcpt1 <= 0 || $trcpt2 <= 0 || $trcpt3 <= 0 } then {
+ fail "setting tracepoints"
+ return;
+}
+
+# 4.1 passcount of specified tracepoint
+
+gdb_test "info tracepoints" \
+ "Num Enb Address PassC StepC What.*$trcpt1\[\t \]+y\[\t \]+$hex\[\t \]+0\[\t \]+.*in gdb_c_test.*$trcpt2\[\t \]+y\[\t \]+$hex\[\t \]+0\[\t \]+.*gdb_asm_test.*$trcpt3\[\t \]+y\[\t \]+$hex\[\t \]+0\[\t \]+.*in gdb_recursion_test.*" \
+ "4.1a: set three tracepoints, passcounts all zero"
+
+gdb_test "passcount 2 $trcpt1" \
+ "Setting tracepoint $trcpt1.s passcount to 2" \
+ "4.1b: set 1st tracepoint's passcount to two"
+
+gdb_test "info tracepoints" \
+ "Num Enb Address PassC StepC What.*$trcpt1\[\t \]+y\[\t \]+$hex\[\t \]+2\[\t \]+.*in gdb_c_test.*$trcpt2\[\t \]+y\[\t \]+$hex\[\t \]+0\[\t \]+.*gdb_asm_test.*$trcpt3\[\t \]+y\[\t \]+$hex\[\t \]+0\[\t \]+.*in gdb_recursion_test.*" \
+ "4.1c: verify 1st tracepoint's passcount set to two"
+
+gdb_test "passcount 4 $trcpt2" \
+ "Setting tracepoint $trcpt2.s passcount to 4" \
+ "4.1d: set 2nd tracepoint's passcount to four"
+
+gdb_test "info tracepoints" \
+ "Num Enb Address PassC StepC What.*$trcpt1\[\t \]+y\[\t \]+$hex\[\t \]+2\[\t \]+.*in gdb_c_test.*$trcpt2\[\t \]+y\[\t \]+$hex\[\t \]+4\[\t \]+.*gdb_asm_test.*$trcpt3\[\t \]+y\[\t \]+$hex\[\t \]+0\[\t \]+.*in gdb_recursion_test.*" \
+ "4.1c: verify 2nd tracepoint's passcount set to four"
+
+# 4.2 passcount of last (default) tracepoint
+
+gdb_test "passcount 6" \
+ "Setting tracepoint $trcpt3.s passcount to 6" \
+ "4.2b: set last (default) tp's passcount to six"
+
+gdb_test "info tracepoints" \
+ "Num Enb Address PassC StepC What.*$trcpt1\[\t \]+y\[\t \]+$hex\[\t \]+2\[\t \]+.*in gdb_c_test.*$trcpt2\[\t \]+y\[\t \]+$hex\[\t \]+4\[\t \]+.*gdb_asm_test.*$trcpt3\[\t \]+y\[\t \]+$hex\[\t \]+6\[\t \]+.*in gdb_recursion_test.*" \
+ "4.2b: verify last (default) tp's passcount set to six"
+
+# 4.3 run until stopped explicitly by user
+# [deferred to dynamic test section]
+
+# 4.4 reset the previously set passcounts to new values
+
+gdb_test "passcount 7" \
+ "Setting tracepoint $trcpt3.s passcount to 7" \
+ "4.4a: reset last (default) tp's passcount to seven"
+
+gdb_test "info tracepoints" \
+ "Num Enb Address PassC StepC What.*$trcpt1\[\t \]+y\[\t \]+$hex\[\t \]+2\[\t \]+.*in gdb_c_test.*$trcpt2\[\t \]+y\[\t \]+$hex\[\t \]+4\[\t \]+.*gdb_asm_test.*$trcpt3\[\t \]+y\[\t \]+$hex\[\t \]+7\[\t \]+.*in gdb_recursion_test.*" \
+ "4.4a: verify reset last (default) tp's passcount to seven"
+
+gdb_test "passcount 5 $trcpt2" \
+ "Setting tracepoint $trcpt2.s passcount to 5" \
+ "4.4b: reset second tracepoint's passcount to five"
+
+gdb_test "info tracepoints" \
+ "Num Enb Address PassC StepC What.*$trcpt1\[\t \]+y\[\t \]+$hex\[\t \]+2\[\t \]+.*in gdb_c_test.*$trcpt2\[\t \]+y\[\t \]+$hex\[\t \]+5\[\t \]+.*gdb_asm_test.*$trcpt3\[\t \]+y\[\t \]+$hex\[\t \]+7\[\t \]+.*in gdb_recursion_test.*" \
+ "4.4c: verify reset second tracepoint's passcount to five"
+
+# 4.20 <FIXME test number> passcount for "all"
+
+gdb_test "passcount 3 all" \
+ ".*$trcpt1.s pass.* 3.*$trcpt2.s pass.* 3.*$trcpt3.s pass.* 3" \
+ "4.20a: set all three passcounts to three"
+
+gdb_test "info tracepoints" \
+ "Num Enb Address PassC StepC What.*$trcpt1\[\t \]+y\[\t \]+$hex\[\t \]+3\[\t \]+.*in gdb_c_test.*$trcpt2\[\t \]+y\[\t \]+$hex\[\t \]+3\[\t \]+.*gdb_asm_test.*$trcpt3\[\t \]+y\[\t \]+$hex\[\t \]+3\[\t \]+.*in gdb_recursion_test.*" \
+ "4.20a: set all three passcounts to three"
+
+gdb_test "passcount 4 all" \
+ ".*$trcpt1.s pass.* 4.*$trcpt2.s pass.* 4.*$trcpt3.s pass.* 4" \
+ "4.20a: reset all three passcounts to four"
+
+gdb_test "info tracepoints" \
+ "Num Enb Address PassC StepC What.*$trcpt1\[\t \]+y\[\t \]+$hex\[\t \]+4\[\t \]+.*in gdb_c_test.*$trcpt2\[\t \]+y\[\t \]+$hex\[\t \]+4\[\t \]+.*gdb_asm_test.*$trcpt3\[\t \]+y\[\t \]+$hex\[\t \]+4\[\t \]+.*in gdb_recursion_test.*" \
+ "4.20b: reset all three passcounts to four"
+
+# 4.5 Verify trace stops on first "satisfied" passcount
+# [deferred to dynamic test section]
+
+# 4.6 minimum passcount boundary condition
+
+gdb_test "passcount 0 $trcpt1" \
+ "Setting tracepoint $trcpt1.s passcount to 0" \
+ "4.6: set passcount to zero"
+
+gdb_test "info tracepoints" \
+ "Num Enb Address PassC StepC What.*$trcpt1\[\t \]+y\[\t \]+$hex\[\t \]+0\[\t \]+.*in gdb_c_test.*$trcpt2\[\t \]+y\[\t \]+$hex\[\t \]+4\[\t \]+.*gdb_asm_test.*$trcpt3\[\t \]+y\[\t \]+$hex\[\t \]+4\[\t \]+.*in gdb_recursion_test.*" \
+ "4.6: set passcount to zero"
+
+# 4.7 (test a very large passcount)
+
+gdb_test "passcount 32767 $trcpt1" \
+ "Setting tracepoint $trcpt1.s passcount to 32767" \
+ "4.7: set passcount to large number (32767)"
+
+gdb_test "info tracepoints" \
+ "Num Enb Address PassC StepC What.*$trcpt1\[\t \]+y\[\t \]+$hex\[\t \]+32767\[\t \]+.*in gdb_c_test.*$trcpt2\[\t \]+y\[\t \]+$hex\[\t \]+4\[\t \]+.*gdb_asm_test.*$trcpt3\[\t \]+y\[\t \]+$hex\[\t \]+4\[\t \]+.*in gdb_recursion_test.*" \
+ "4.7: set passcount to large number (32767)"
+
+# 4.8 set passcount for invalid tracepoint
+
+gdb_test "passcount 1 [expr $trcpt2 + $trcpt3]" \
+ "No tracepoint number [expr $trcpt2 + $trcpt3]." \
+ "4.8: invalid tracepoint number in passcount"
+
+# 4.9 help passcount
+gdb_test "help passcount" "Set the passcount for a tracepoint.*" \
+ "4.9: help passcount"
+
diff --git a/gdb/testsuite/gdb.trace/report.exp b/gdb/testsuite/gdb.trace/report.exp
new file mode 100644
index 00000000000..0f133ad3bca
--- /dev/null
+++ b/gdb/testsuite/gdb.trace/report.exp
@@ -0,0 +1,421 @@
+# Copyright (C) 1998 Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file was written by Michael Snyder (msnyder@cygnus.com)
+
+load_lib "trace-support.exp";
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+set prms_id 0
+set bug_id 0
+
+gdb_exit
+gdb_start
+
+if [istarget "m68k-*-elf"] then {
+ load_lib "emc-support.exp";
+ set srcfile gdb_c_test.c
+ set binfile [board_info target d490_binfile];
+ gdb_test "set remotetimeout 6" "" ""
+ set timeout 500
+ gdb_target_monitor $binfile
+ # Give a TSTOP and ignore errors, to make sure any previous trace is off
+ gdb_test "tstop" "" ""
+ gdb_test "tfind none" "" ""
+ send_gdb "compare-sections CS\n"
+ gdb_expect {
+ -re "MIS-MATCHED.*$gdb_prompt $" {
+ gdb_suppress_entire_file "Symbol file does not match target!
+ all tests in this module will fail.";
+ }
+ -re ".*$gdb_prompt $" { }
+ }
+} else {
+ set testfile "actions"
+ set srcfile ${testfile}.c
+ set binfile $objdir/$subdir/$testfile
+ if { [gdb_compile "$srcdir/$subdir/$srcfile" $binfile \
+ executable {debug additional_flags=-w}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+ }
+ gdb_load $binfile
+ gdb_test "tstop" "" ""
+ gdb_test "tfind none" "" ""
+ runto_main
+}
+gdb_reinitialize_dir $srcdir/$subdir
+
+# We generously give ourselves one "pass" if we successfully
+# detect that this test cannot be run on this target!
+if { ![gdb_target_supports_trace] } then {
+ pass "Current target does not supporst trace"
+ return 1;
+
+}
+
+set cr "\[\r\n\]+"
+
+# If testing on a remote host, download the source file.
+# remote_download host $srcdir/$subdir/$srcfile
+
+#
+# test general reporting of trace experiment results
+#
+
+set testline1 0
+set testline2 0
+set testline3 0
+set testline4 0
+set testline5 0
+set testline6 0
+
+set arg1 1
+set arg2 2
+set arg3 3
+set arg4 4
+set arg5 5
+set arg6 6
+
+set gdb_recursion_test_baseline [gdb_find_recursion_test_baseline $srcfile];
+if { $gdb_recursion_test_baseline == -1 } {
+ fail "Could not find gdb_recursion_test function"
+ return;
+}
+
+send_gdb "list $gdb_recursion_test_baseline, +12\n"
+gdb_expect {
+ -re "\[\r\n\](\[0-9\]+)\[^\r\n\]+gdbtestline 1 " {
+ set testline1 $expect_out(1,string)
+ exp_continue
+ }
+ -re "\[\r\n\](\[0-9\]+)\[^\r\n\]+gdbtestline 2 " {
+ set testline2 $expect_out(1,string)
+ exp_continue
+ }
+ -re "\[\r\n\](\[0-9\]+)\[^\r\n\]+gdbtestline 3 " {
+ set testline3 $expect_out(1,string)
+ exp_continue
+ }
+ -re "\[\r\n\](\[0-9\]+)\[^\r\n\]+gdbtestline 4 " {
+ set testline4 $expect_out(1,string)
+ exp_continue
+ }
+ -re "\[\r\n\](\[0-9\]+)\[^\r\n\]+gdbtestline 5 " {
+ set testline5 $expect_out(1,string)
+ exp_continue
+ }
+ -re "\[\r\n\](\[0-9\]+)\[^\r\n\]+gdbtestline 6 " {
+ set testline6 $expect_out(1,string)
+ exp_continue
+ }
+ -re ".*$gdb_prompt $" {
+ if { ($testline1 == 0) || ($testline2 == 0) || ($testline3 == 0) || ($testline4 == 0) || ($testline5 == 0) || ($testline6 == 0) } {
+ gdb_suppress_entire_file "failed to locate test source lines:
+all tests in this module will fail."
+ }
+ }
+ default {
+ gdb_suppress_entire_file "failed to locate test source lines (def):
+all tests in this module will fail."
+ }
+}
+
+#
+# Setup trace experiment. This will involve:
+# 1) a tracepoint where nothing is collected
+# 2) a tracepoint where only regs are collected
+# 3) a tracepoint where only args are collected
+# 4) a tracepoint where only locals are collected
+# 5) a tracepoint where some amount of stack memory is collected.
+# 6) a tracepoint where some expressions are collected.
+#
+
+gdb_delete_tracepoints
+set tdp1 [gdb_gettpnum $testline1]
+set tdp2 [gdb_gettpnum $testline2]
+set tdp3 [gdb_gettpnum $testline3]
+set tdp4 [gdb_gettpnum $testline4]
+set tdp5 [gdb_gettpnum $testline5]
+set tdp6 [gdb_gettpnum $testline6]
+
+if { $tdp1 <= 0 || $tdp2 <= 0 || $tdp3 <= 0 || \
+ $tdp4 <= 0 || $tdp5 <= 0 || $tdp6 <= 0 } then {
+ fail "setting tracepoints failed"
+ return;
+}
+
+gdb_trace_setactions "9.x: setup TP to collect regs" \
+ "$tdp2" \
+ "collect \$regs" "^$"
+
+
+gdb_trace_setactions "9.x: setup TP to collect args" \
+ "$tdp3" \
+ "collect \$args" "^$"
+
+gdb_trace_setactions "9.x: setup TP to collect locals" \
+ "$tdp4" \
+ "collect \$locs" "^$"
+
+gdb_trace_setactions "9.x: setup TP to collect stack memory" \
+ "$tdp5" \
+ "collect \$fp, \*\(void \*\*\) \$sp @ 64" "^$"
+
+gdb_trace_setactions "9.x: setup TP to collect expressions" \
+ "$tdp6" \
+ "collect gdb_char_test, gdb_short_test, gdb_long_test" "^$"
+
+gdb_test "tstart" "" ""
+
+if [istarget "m68k-*-elf"] then {
+ gdb_emclaptop_command "85,$arg1,$arg2,$arg3,$arg4,$arg5,$arg6"
+ sleep 5
+
+} else {
+ gdb_test "break end" "" ""
+ gdb_test "continue" \
+ "Continuing.*Breakpoint $decimal, end.*" \
+ "run trace experiment"
+}
+
+gdb_test "tstop" "" ""
+
+#
+# 9.1 test the tdump command
+#
+
+set timeout 60
+
+gdb_tfind_test "9.1: init: make sure not debugging any trace frame" "none" "-1"
+
+gdb_tfind_test "9.1: find frame for TP $tdp1" "tracepoint $tdp1" \
+ "\$tracepoint" "$tdp1"
+
+# Nothing was collected at tdp1, so this tdump should be empty.
+gdb_test "tdump" \
+ "Data collected at tracepoint $tdp1, trace frame $decimal:" \
+ "9.1: tdump, nothing collected"
+
+gdb_tfind_test "9.1: find frame for TP $tdp2" "tracepoint $tdp2" \
+ "\$tracepoint" "$tdp2"
+
+# regs were collected at tdp2.
+# How to match for the output of "info registers" on an unknown architecture?
+# For now, assume that every architecture has a register called "pc".
+gdb_test "tdump" \
+ "\[\r\n\]pc .*" \
+ "9.1: tdump, regs collected"
+
+gdb_tfind_test "9.1: find frame for TP $tdp3" "tracepoint $tdp3" \
+ "\$tracepoint" "$tdp3"
+
+# args were collected at tdp3
+gdb_test "tdump" \
+ "depth = 3.*q1 = 2.*q2 = 2.*q3 = 3.*q4 = 4.*q5 = 5.*q6 = 6" \
+ "9.1: tdump, args collected"
+
+gdb_tfind_test "9.1: find frame for TP $tdp4" "tracepoint $tdp4" \
+ "\$tracepoint" "$tdp4"
+
+# locals were collected at tdp4
+gdb_test "tdump" \
+ "q = 1" \
+ "9.1: tdump, locals collected"
+
+gdb_tfind_test "9.1: find frame for TP $tdp5" "tracepoint $tdp5" \
+ "\$tracepoint" "$tdp5"
+
+# stack was collected at tdp5, plus the frame pointer
+gdb_test "tdump" \
+ ".fp = .*sp @ 64 = .*" \
+ "9.1: tdump, memrange collected"
+
+gdb_tfind_test "9.1: find frame for TP $tdp6" "tracepoint $tdp6" \
+ "\$tracepoint" "$tdp6"
+
+# globals were collected at tdp6
+gdb_test "tdump" \
+ "gdb_char_test = 1.*gdb_short_test = 2.*gdb_long_test = 3" \
+ "9.1: tdump, global variables collected"
+
+# 9.2 test tdump with arguments
+# [no go, tdump doesn't have any arguments]
+
+# 9.3 help tdump
+
+gdb_test "help tdump" "Print everything collected at the current.*" \
+ "9.3: help tdump"
+
+set linecount1 0
+set linecount2 0
+set linecount3 0
+set linecount4 0
+set linecount5 0
+set linecount6 0
+
+gdb_tfind_test "11.x, 12.1: find start frame" "start" "0"
+
+#
+# 11.x test built-in trace variables $trace_frame, $trace_line etc.
+#
+
+gdb_test "printf \"x %d x\\n\", \$trace_frame" "x 0 x" \
+ "11.1: test \$trace_frame"
+
+gdb_test "printf \"x %d x\\n\", \$tracepoint" "x $tdp1 x" \
+ "11.2: test \$tracepoint"
+
+gdb_test "printf \"x %d x\\n\", \$trace_line" "x $testline1 x" \
+ "11.3: test \$trace_line"
+
+send_gdb "print \$trace_file\n"
+gdb_expect {
+ -re "\\$\[0-9\]+ = \"$srcfile\"\[\r\n\]+$gdb_prompt $" {
+ pass "11.4: test \$trace_file"
+ }
+ -re "\\$\[0-9\]+ = \"$srcdir/$subdir/$srcfile\"\[\r\n\]+$gdb_prompt $" {
+ pass "11.4: test \$trace_file"
+ }
+ -re "$gdb_prompt $" {
+ fail "11.4: test \$trace_file"
+ }
+ timeout {
+ fail "11.4: test \$trace_file (timeout)"
+ }
+}
+
+#gdb_test "print \$trace_file" "\"$srcdir/$subdir/$srcfile\"" \
+# "11.4: test \$trace_file"
+
+#
+# 12.x test report generation using arbitrary GDB commands, loops etc.
+#
+
+send_gdb "while \$trace_frame != -1\n output \$trace_file\n printf \", line \%d \(tracepoint #\%d\)\\n\", \$trace_line, \$tracepoint\n tfind\n end\n"
+gdb_expect {
+ -re " line $testline1 .tracepoint .$tdp1" {
+ set linecount1 [expr $linecount1 + 1]
+ exp_continue
+ }
+ -re " line $testline2 .tracepoint .$tdp2" {
+ set linecount2 [expr $linecount2 + 1]
+ exp_continue
+ }
+ -re " line $testline3 .tracepoint .$tdp3" {
+ set linecount3 [expr $linecount3 + 1]
+ exp_continue
+ }
+ -re " line $testline4 .tracepoint .$tdp4" {
+ set linecount4 [expr $linecount4 + 1]
+ exp_continue
+ }
+ -re " line $testline5 .tracepoint .$tdp5" {
+ set linecount5 [expr $linecount5 + 1]
+ exp_continue
+ }
+ -re " line $testline6 .tracepoint .$tdp6" {
+ set linecount6 [expr $linecount6 + 1]
+ exp_continue
+ }
+ -re ".*$gdb_prompt $" {
+ if { ($linecount1 < 4) || ($linecount2 < 4) || ($linecount3 < 4) || ($linecount4 < 4) || ($linecount5 < 4) || ($linecount6 < 4) } {
+ fail "12.1: trace report #1"
+ } else {
+ pass "12.1: trace report #1"
+ }
+ }
+ timeout {
+ fail "12.1: trace report #1 (timeout)"
+ }
+}
+
+gdb_tfind_test "12.2: find first TDP #2 frame" "tracepoint $tdp2" \
+ "\$tracepoint" "$tdp2"
+
+set linecount2 0
+
+send_gdb "while \$trace_frame != -1\n printf \"tracepoint #\%d, FP 0x\%08x, SP 0x\%08x, PC 0x%08x\\n\", \$tracepoint, \$fp, \$sp, \$pc\n tfind tracepoint\n end\n"
+gdb_expect {
+ -re "tracepoint #$tdp2, FP $hex, SP $hex, PC $hex" {
+ set linecount2 [expr $linecount2 + 1]
+ exp_continue
+ }
+ -re ".*$gdb_prompt $" {
+ if { ($linecount2 < 4) } {
+ fail "12.2: trace report #2"
+ } else {
+ pass "12.2: trace report #2"
+ }
+ }
+ timeout {
+ fail "12.2: trace report #2 (timeout)"
+ }
+}
+
+gdb_tfind_test "12.3: find first TDP #3 frame" "tracepoint $tdp3" \
+ "\$tracepoint" "$tdp3"
+
+set linecount3 0
+
+send_gdb "while \$trace_frame != -1\n printf \"TDP #\%d, frame \%d: depth = \%d, q1 = \%d\\n\", \$tracepoint, \$trace_frame, depth, q1\n tfind tracepoint\n end\n"
+gdb_expect {
+ -re "TDP #$tdp3, frame $decimal: depth = $decimal, q1 = $decimal" {
+ set linecount3 [expr $linecount3 + 1]
+ exp_continue
+ }
+ -re ".*$gdb_prompt $" {
+ if { ($linecount3 < 4) } {
+ fail "12.3: trace report #3"
+ } else {
+ pass "12.3: trace report #3"
+ }
+ }
+ timeout {
+ fail "12.3: trace report #3 (timeout)"
+ }
+}
+
+gdb_tfind_test "12.4: find first TDP #6 frame" "tracepoint $tdp6" \
+ "\$tracepoint" "$tdp6"
+
+set linecount6 0
+
+send_gdb "while \$trace_frame != -1\n printf \"TDP #\%d, frame %d: char_test = \%d, long_test = \%d\\n\", \$tracepoint, \$trace_frame, gdb_char_test, gdb_long_test\n tfind tracepoint\n end\n"
+gdb_expect {
+ -re "TDP #$tdp6, frame $decimal: char_test = $arg1, long_test = $arg3" {
+ set linecount6 [expr $linecount6 + 1]
+ exp_continue
+ }
+ -re ".*$gdb_prompt $" {
+ if { ($linecount6 < 4) } {
+ fail "12.4: trace report #4"
+ } else {
+ pass "12.4: trace report #4"
+ }
+ }
+ timeout {
+ fail "12.4: trace report #4 (timeout)"
+ }
+}
+
+# Finished!
+gdb_tfind_test "finished: make sure not debugging any trace frame" "none" "-1"
diff --git a/gdb/testsuite/gdb.trace/save-trace.exp b/gdb/testsuite/gdb.trace/save-trace.exp
new file mode 100644
index 00000000000..3ff9890438b
--- /dev/null
+++ b/gdb/testsuite/gdb.trace/save-trace.exp
@@ -0,0 +1,171 @@
+# Copyright (C) 1998 Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file was written by Michael Snyder (msnyder@cygnus.com)
+
+load_lib "trace-support.exp";
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+set prms_id 0
+set bug_id 0
+
+gdb_exit
+gdb_start
+
+if [istarget "m68k-*-elf"] then {
+ set srcfile gdb_c_test.c
+ set binfile [board_info target d490_binfile];
+} else {
+ set testfile "actions"
+ set srcfile ${testfile}.c
+ set binfile $objdir/$subdir/$testfile
+ if { [gdb_compile "$srcdir/$subdir/$srcfile" $binfile \
+ executable {debug additional_flags=-w}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+ }
+}
+gdb_reinitialize_dir $srcdir/$subdir
+
+# If testing on a remote host, download the source file.
+# remote_download host $srcdir/$subdir/$srcfile
+
+gdb_file_cmd $binfile
+
+# define relative source line numbers:
+# all subsequent line numbers are relative to this first one (baseline)
+set baseline [gdb_find_recursion_test_baseline $srcfile];
+if { $baseline == -1 } then {
+ fail "Could not find gdb_recursion_test function"
+ return;
+}
+
+set testline1 [expr $baseline + 4]
+set testline2 [expr $baseline + 5]
+set testline3 [expr $baseline + 6]
+set testline4 [expr $baseline + 7]
+set testline5 [expr $baseline + 8]
+set testline6 [expr $baseline + 9]
+
+#
+# test save-trace command
+#
+
+# setup a set of tracepoints to save
+
+gdb_delete_tracepoints
+
+foreach x { 1 2 3 4 5 6 } {
+ set testline [expr \$testline$x];
+ set trcpt [gdb_gettpnum $testline];
+ set trcpt$x $trcpt;
+ gdb_test "passcount $x" \
+ "Setting tracepoint $trcpt.* to $x" \
+ "10.x: set passcount for tracepoint $trcpt"
+
+ gdb_trace_setactions "10.x: set actions for tracepoint $x" \
+ "" \
+ "collect q$x" "^$" \
+ "while-stepping $x" "^$" \
+ "collect q$x" "^$" \
+ "end" "^$"
+}
+
+
+proc gdb_verify_tracepoints { testname } {
+ global gdb_prompt;
+
+ set ws "\[\t \]+"
+ set nl "\[\r\n\]+"
+ set ourstate 1;
+ set result "pass";
+ send_gdb "info tracepoints\n";
+ gdb_expect 10 {
+ -re "y\[\t \]+0x\[0-9a-fA-F\]+\[\t \]+(\[0-9\]+)\[\t \]+(\[0-9\]+)\[\t \]+in gdb_recursion_test\[^\r\n\]+" {
+ if { $expect_out(1,string) != $expect_out(2,string) } {
+ #set result "fail";
+ }
+ if { $expect_out(1,string) != $ourstate } {
+ set result "fail";
+ }
+ incr ourstate;
+ exp_continue;
+ }
+ -re "$gdb_prompt $" {
+ if { $ourstate >= 6 } {
+ set result "pass";
+ } else {
+ set result "fail";
+ }
+ }
+ default {
+ set result "fail";
+ }
+ }
+ $result $testname;
+ return $result;
+}
+
+gdb_verify_tracepoints "10.x: verify trace setup";
+
+# 10.1 Save current tracepoint definitions to a file
+
+remote_file host delete savetrace.tr
+gdb_test "save-tracepoints savetrace.tr" \
+ "Tracepoints saved to file 'savetrace.tr'." \
+ "10.1: save tracepoint definitions"
+
+# 10.2 Read back tracepoint definitions
+
+gdb_delete_tracepoints
+gdb_test "info tracepoints" "No tracepoints." "10.2: delete tracepoints"
+gdb_test "source savetrace.tr" \
+ "Tracepoint \[0-9\]+ at .*" \
+ "10.2: read back saved tracepoints"
+gdb_verify_tracepoints "10.2: verify recovered tracepoints";
+remote_file host delete savetrace.tr
+
+# 10.3 repeat with a path to the file
+
+remote_file host delete $objdir/savetrace.tr
+gdb_test "save-tracepoints $objdir/savetrace.tr" \
+ "Tracepoints saved to file '$objdir/savetrace.tr'." \
+ "10.3: save tracepoint definitions, full path"
+
+gdb_delete_tracepoints
+gdb_test "info tracepoints" "No tracepoints." "10.3: delete tracepoints"
+gdb_test "source $objdir/savetrace.tr" \
+ "Tracepoint \[0-9\]+ at .*" \
+ "10.4: read saved tracepoints, full path"
+gdb_verify_tracepoints "10.3: verify recovered tracepoints, full path";
+remote_file host delete $objdir/savetrace.tr
+
+# 10.5 invalid filename
+# [deferred -- not sure what a good invalid filename would be]
+
+# 10.6 save-trace (file already exists)
+# [expect it to clobber the old one]
+
+# 10.7 help save-tracepoints
+
+gdb_test "help save-tracepoints" \
+ "Save current tracepoint definitions as a script.*" \
+ "10.7: help save-tracepoints"
diff --git a/gdb/testsuite/gdb.trace/tfind.exp b/gdb/testsuite/gdb.trace/tfind.exp
new file mode 100644
index 00000000000..f101851b93e
--- /dev/null
+++ b/gdb/testsuite/gdb.trace/tfind.exp
@@ -0,0 +1,405 @@
+# Copyright (C) 1998 Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file was written by Michael Snyder (msnyder@cygnus.com)
+
+load_lib "trace-support.exp";
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+set prms_id 0
+set bug_id 0
+
+gdb_exit
+gdb_start
+
+if [istarget "m68k-*-elf"] then {
+ load_lib "emc-support.exp";
+ set srcfile gdb_c_test.c
+ set binfile [board_info target d490_binfile];
+ gdb_test "set remotetimeout 6" "" ""
+ set timeout 500
+ gdb_target_monitor $binfile
+ # Give a TSTOP and ignore errors, to make sure any previous trace is off
+ gdb_test "tstop" "" ""
+ gdb_test "tfind none" "" ""
+ send_gdb "compare-sections CS\n"
+ gdb_expect {
+ -re "MIS-MATCHED.*$gdb_prompt $" {
+ gdb_suppress_entire_file "Symbol file does not match target!
+ all tests in this module will fail.";
+ }
+ -re ".*$gdb_prompt $" { }
+ }
+} else {
+ set testfile "actions"
+ set srcfile ${testfile}.c
+ set binfile $objdir/$subdir/$testfile
+ if { [gdb_compile "$srcdir/$subdir/$srcfile" "$binfile -O1" \
+ executable {debug additional_flags=-w}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+ }
+ gdb_load $binfile
+ gdb_test "tstop" "" ""
+ gdb_test "tfind none" "" ""
+ runto_main
+}
+gdb_reinitialize_dir $srcdir/$subdir
+
+# We generously give ourselves one "pass" if we successfully
+# detect that this test cannot be run on this target!
+if { ![gdb_target_supports_trace] } then {
+ pass "Current target does not supporst trace"
+ return 1;
+
+}
+
+# If testing on a remote host, download the source file.
+# remote_download host $srcdir/$subdir/$srcfile
+
+# define relative source line numbers:
+# all subsequent line numbers are relative to this first one (baseline)
+set baseline [gdb_find_recursion_test_baseline $srcfile];
+if { $baseline == -1 } then {
+ fail "Could not find gdb_recursion_test function"
+ return;
+}
+
+set testline1 [expr $baseline + 1]
+set testline2 [expr $baseline + 5]
+set testline3 [expr $baseline + 6]
+set testline4 [expr $baseline + 7]
+set testline5 [expr $baseline + 8]
+
+#
+# test tfind command
+#
+
+gdb_delete_tracepoints
+set tdp1 [gdb_gettpnum "\*gdb_recursion_test"]
+set tdp2 [gdb_gettpnum $testline2]
+set tdp3 [gdb_gettpnum $testline3]
+set tdp4 [gdb_gettpnum $testline4]
+set tdp5 [gdb_gettpnum $testline5]
+if { $tdp1 <= 0 || $tdp2 <= 0 || $tdp3 <= 0 || \
+ $tdp4 <= 0 || $tdp5 <= 0 } then {
+ fail "setting tracepoints"
+ return;
+}
+
+# 6.1 test tstart command
+send_gdb "tstart\n"
+gdb_expect {
+ -re "Trace can only be run on remote targets.*$gdb_prompt $" {
+ fail "6.1: tstart (not connected to remote?)"
+ return;
+ }
+ -re "Target does not support this command.*$gdb_prompt $" {
+ fail "6.1: tstart (connected to wrong target?)"
+ return;
+ }
+ -re "Target returns error code.*$gdb_prompt $" {
+ fail "6.1: tstart (connected to wrong target?)"
+ return;
+ }
+ -re "$gdb_prompt $" {
+ pass "6.1: tstart"
+ }
+ default {
+ fail "6.1: tstart (default)"
+ return;
+ }
+}
+
+# test tstatus (when trace on)
+gdb_test "tstatus" "\[Tt\]race is running.*" "test tstatus on"
+
+# 6.2 test help tstart
+gdb_test "help tstart" "Start trace data collection." "6.2: help tstart"
+
+if [istarget "m68k-*-elf"] then {
+ gdb_emclaptop_command "85,1,2,3,4,5,6"
+ sleep 5
+
+ gdb_emclaptop_command "85,7,8,9,A,B,C"
+ sleep 5
+} else {
+ gdb_test "break end" "" ""
+ gdb_test "continue" \
+ "Continuing.*Breakpoint $decimal, end.*" \
+ "run trace experiment"
+}
+
+# 7.1 test tstop command
+send_gdb "tstop\n"
+gdb_expect {
+ -re "Trace can only be run on remote targets.*$gdb_prompt $" {
+ fail "7.1: tstop (not connected to remote?)"
+ return;
+ }
+ -re "Target does not support this command.*$gdb_prompt $" {
+ fail "7.1: tstop (connected to wrong target?)"
+ return;
+ }
+ -re "Target returns error code.*$gdb_prompt $" {
+ fail "7.1: tstop (connected to wrong target?)"
+ return;
+ }
+ -re "$gdb_prompt $" {
+ pass "7.1: tstop"
+ }
+ default {
+ fail "7.1: tstop (default)"
+ return;
+ }
+}
+
+# 7.2 test help tstop
+gdb_test "help tstop" "Stop trace data collection." "7.2: help tstop"
+
+# test tstatus (when trace off)
+gdb_test "tstatus" "\[Tt\]race.* not running.*" "test tstatus off"
+
+## record starting PC
+set save_pc [gdb_readexpr "(unsigned long) \$pc"];
+if { $save_pc == -1 } then {
+ fail "could not read PC"
+ return;
+}
+
+# 8.7 tfind start
+## check $trace_frame == 0
+gdb_tfind_test "8.7: tfind start command" "start" "0";
+## check $pc != startPC
+gdb_test "printf \"x \%d x\\n\", \$pc != $save_pc" \
+ "x 1 x" \
+ "8.7b: tfind start"
+
+# 8.8 tfind none
+## check $trace_frame == -1
+gdb_tfind_test "8.8: tfind none" "none" "-1";
+## check $pc == startPC
+gdb_test "printf \"x \%d x\\n\", \$pc == $save_pc" \
+ "x 1 x" \
+ "8.8b: tfind none (restores non-trace PC)"
+
+# 8.9 tfind end
+## check $trace_frame == -1
+gdb_tfind_test "8.9: tfind end, selects no frame" "end" "-1";
+## check $pc == startPC
+gdb_test "printf \"x \%d x\\n\", \$pc == $save_pc" \
+ "x 1 x" \
+ "8.9b: tfind end (restores non-tracing PC)"
+
+# 8.1 tfind n
+## check $trace_frame == n
+gdb_tfind_test "8.1: tfind 1" "1" "1"
+## check $trace_line corresponds to tracepoint for frame n
+gdb_test "print \$trace_line" "$testline2" "8.1b: tfind 1 (correct line)"
+
+# 8.28 tfind invalid n (big number)
+## check "not found" error
+## check $trace_frame != n
+gdb_test "tfind 32767" \
+ "failed to find.*" \
+ "8.28: tfind <n> command rejects invalid frame number"
+
+gdb_test "printf \"x \%d x\\n\", \$trace_frame == 32767" \
+ "x 0 x" \
+ "8.28: tfind <n> rejected bad input (32767)"
+
+# 8.31 tfind negative n
+## check error
+gdb_test "tfind -3" "invalid input.*" "8.31: tfind <n> rejects negative input"
+## check $trace_frame != -n
+gdb_test "printf \"x \%d x\\n\", \$trace_frame == -3" "x 0 x" \
+ "8.31: tfind <n> rejected negative input (-3)"
+
+# 8.10 tfind <no arg>
+## check $trace_frame += 1
+
+gdb_tfind_test "8.10: tfind start" "start" "0";
+gdb_test "print \$trace_line" "$baseline" \
+ "8.10: tfind 0 (correct line $baseline)"
+gdb_tfind_test "8.10: tfind noargument 1" "" "1";
+gdb_test "print \$trace_line" "$testline2" \
+ "8.10: tfind 1 (correct line $testline2)"
+gdb_tfind_test "8.10: tfind noargument 2" "" "2";
+gdb_test "print \$trace_line" "$testline3" \
+ "8.10: tfind 2 (correct line $testline3)"
+gdb_tfind_test "8.10: tfind noargument 3" "" "3";
+gdb_test "print \$trace_line" "$testline4" \
+ "8.10: tfind 3 (correct line $testline4)"
+
+gdb_tfind_test "8.11: tfind 3" "3" "3";
+gdb_test "print \$trace_line" "$testline4" \
+ "8.11: tfind 3 (correct line $testline4)"
+gdb_tfind_test "8.11: tfind backward 2" "-" "2";
+gdb_test "print \$trace_line" "$testline3" \
+ "8.11: tfind 2 (correct line $testline3)"
+gdb_tfind_test "8.11: tfind backward 1" "-" "1";
+gdb_test "print \$trace_line" "$testline2" \
+ "8.11: tfind 1 (correct line $testline2)"
+gdb_tfind_test "8.11: tfind backward 0" "-" "0";
+gdb_test "print \$trace_line" "$baseline" \
+ "8.11: tfind 0 (correct line $baseline)"
+
+gdb_tfind_test "8.12: tfind none" "none" "-1";
+gdb_tfind_test "8.12: tfind tracepoint <n>" "tracepoint $tdp2" \
+ "\$tracepoint" "$tdp2";
+gdb_test "print \$trace_line" "$testline2" \
+ "8.12: tfind tracepoint <n> (line $testline2)"
+
+gdb_tfind_test "8.25: tfind none" "none" "-1";
+gdb_test "tfind tracepoint 0" "failed to find.*" \
+ "8.25: tfind tracepoint rejects zero"
+gdb_test "tfind tracepoint 32767" "failed to find.*" \
+ "8.25: tfind tracepoint rejects nonexistant tracepoint (32767)"
+gdb_test "tfind tracepoint -1" "failed to find.*" \
+ "8.25: tfind tracepoint rejects nonexistant tracepoint (-1)"
+
+# 8.37 tfind tracepoint n where n no longer exists (but used to)
+gdb_test "delete trace $tdp2" "" ""
+gdb_tfind_test "8.37: tfind none" "none" "-1";
+gdb_tfind_test "8.37: tfind deleted tracepoint" \
+ "tracepoint $tdp2" \
+ "\$tracepoint" "$tdp2";
+gdb_test "print \$trace_line" "$testline2" \
+ "8.37: tfind deleted tracepoint (line $testline2)"
+
+# 8.13 tfind tracepoint <no arg>
+## check $tracepoint same before and after, $trace_frame changed
+
+gdb_tfind_test "8.13: tfind none" "none" "-1";
+gdb_tfind_test "8.13: tracepoint $tdp1" "tracepoint $tdp1" \
+ "\$tracepoint" "$tdp1";
+gdb_test "print \$trace_line" "$baseline" \
+ "8.13: tfind tracepoint $tdp1 (line $baseline)"
+gdb_test "set \$save_frame = \$trace_frame" "" ""
+gdb_tfind_test "8.13: tracepoint <no arg>" "tracepoint" \
+ "\$tracepoint" "$tdp1";
+gdb_test "printf \"x \%d x\\n\", \$trace_frame == \$save_frame" \
+ "x 0 x" \
+ "8.13: tracepoint <no arg>, tracepoint number unchanged"]
+
+# 1.12 set tracepoint in prologue
+#
+# tdp1 was set at *gdb_recursion_test (ie. the hard address of the
+# function, before the prologue). Test to see that it succeeded.
+# Current pc should be equal to the address of the function.
+
+gdb_test "printf \"x \%d x\\n\", \$pc == gdb_recursion_test" \
+ "x 1 x" \
+ "1.12: set tracepoint in prologue"
+
+# 8.14 tfind pc x
+## check pc == x, $trace_frame != -1
+gdb_tfind_test "8.14: tfind 3" "3" "3"
+gdb_test "print \$trace_line" "$testline4" \
+ "8.14: tfind 3 (line $testline4)"
+
+gdb_test "set \$test_pc = \$pc" "" ""
+gdb_tfind_test "8.14: tfind none" "none" "-1"
+gdb_tfind_test "8.14: tfind pc" "pc \$test_pc" "\$trace_frame != -1" "1";
+gdb_test "print \$trace_line" "$testline4" \
+ "8.14: tfind pc x (line $testline4)"
+gdb_test "printf \"x \%d x\\n\", \$pc == \$test_pc" \
+ "x 1 x" \
+ "8.14: tfind pc x"
+
+# 8.15 tfind pc <no arg>
+## check pc same before and after, $trace_frame changed
+gdb_tfind_test "8.15: tfind 3" "3" "3"
+gdb_test "print \$trace_line" "$testline4" \
+ "8.15: tfind 3 (line $testline4)"
+gdb_test "set \$test_pc = \$pc" "" ""
+gdb_tfind_test "8.15: tfind pc" "pc" "\$pc == \$test_pc" "1"
+gdb_test "print \$trace_line" "$testline4" \
+ "8.15: tfind pc (line $testline4)"
+gdb_test "printf \"x \%d x\\n\", \$trace_frame != 3" "x 1 x" \
+ "8.15: trace frame didn't change"
+
+# 8.26 tfind pc invalid x
+## check error, pc != x (trace_frame unchanged?)
+gdb_tfind_test "8.26: tfind start" "start" "0"
+gdb_test "tfind pc 0" "failed to find.*" "8.26: tfind pc zero"
+gdb_test "tfind pc -1" "failed to find.*" "8.26: tfind pc -1"
+
+# 8.16 tfind line n
+## check #trace_frame != -1, $trace_line == n
+gdb_tfind_test "8.16: tfind none" "none" "-1"
+gdb_tfind_test "8.16: tfind line $testline3" \
+ "line $testline3" \
+ "\$trace_line == $testline3" "1"
+
+# 8.17 tfind line <no arg> (# 8.19, 8.20)
+## check $trace_line changed, no error, pc changed, frame changed, tdp changed
+gdb_tfind_test "8.17: tfind none" "none" "-1"
+gdb_tfind_test "8.17: tfind line $testline3" "line $testline3" "\$trace_line == $testline3" "1"
+gdb_tfind_test "8.17: tfind line <no arg>" "line" "\$trace_line != $testline3" "1"
+
+# 8.36 tfind and disassembly
+gdb_tfind_test "8.36: tfind start" "start" "0"
+set timeout 60
+send_gdb "disassemble gdb_c_test\n"
+# look for disassembly of function label
+gdb_expect {
+ -re "<gdb_c_test>:.*$gdb_prompt $" { pass "8.36: trace disassembly" }
+ -re ".*$gdb_prompt $" { fail "8.36: trace disassembly" }
+ timeout { fail "8.36: trace disassembly (timeout)" }
+}
+
+gdb_test "tfind line 0" \
+ "out of range.*|failed to find.*" \
+ "8.18: tfind line 0";
+gdb_test "tfind line 32767" \
+ "out of range.*|failed to find.*" \
+ "8.27: tfind line 32767";
+gdb_test "tfind line NoSuChFiLe.c:$baseline" \
+ "No source file named.*" \
+ "8.27: tfind line in bad source file";
+
+# 8.32 tfind invalid subcommand (tfind foo)
+## check error
+gdb_test "tfind NoSuChOpTiOn 21" \
+ "No symbol.*|\[Ww\]arning.*|\[Ee\]rror.*" \
+ "8.32: tfind with bad subcommand"
+
+# 8.38 test help tfind
+gdb_test "help tfind" "Select a trace frame.*" \
+ "8.38: help tfind"
+gdb_test "help tfind pc" "Select a trace frame by PC.*" \
+ "8.38: help tfind PC"
+gdb_test "help tfind end" "Synonym for 'none'.*" \
+ "8.38: help tfind end"
+gdb_test "help tfind none" "De-select any trace frame.*" \
+ "8.38: help tfind none"
+gdb_test "help tfind line" "Select a trace frame by source line.*" \
+ "8.38: help tfind line"
+gdb_test "help tfind start" "Select the first trace frame.*" \
+ "8.38: help tfind start"
+gdb_test "help tfind range" "Select a trace frame whose PC is in.*" \
+ "8.38: help tfind range"
+gdb_test "help tfind trace" "Select a trace frame by tracepoint number.*" \
+ "8.38: help tfind tracepoint"
+
+# Finished!
+gdb_tfind_test "8.17: tfind none" "none" "-1"
diff --git a/gdb/testsuite/gdb.trace/tracecmd.exp b/gdb/testsuite/gdb.trace/tracecmd.exp
new file mode 100644
index 00000000000..9ba5501645c
--- /dev/null
+++ b/gdb/testsuite/gdb.trace/tracecmd.exp
@@ -0,0 +1,269 @@
+# Copyright (C) 1998 Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file was written by Michael Snyder (msnyder@cygnus.com)
+
+load_lib "trace-support.exp";
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+set prms_id 0
+set bug_id 0
+
+gdb_exit
+gdb_start
+if [istarget "m68k-*-elf"] then {
+ set srcfile gdb_c_test.c
+ set binfile [board_info target d490_binfile];
+} else {
+ set testfile "actions"
+ set srcfile ${testfile}.c
+ set binfile $objdir/$subdir/$testfile
+ if { [gdb_compile "$srcdir/$subdir/$srcfile" $binfile \
+ executable {debug additional_flags=-w}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+ }
+}
+gdb_reinitialize_dir $srcdir/$subdir
+
+# If testing on a remote host, download the source file.
+# remote_download host $srcdir/$subdir/$srcfile
+
+gdb_file_cmd $binfile
+
+# define relative source line numbers:
+# all subsequent line numbers are relative to this first one (baseline)
+set baseline [gdb_find_recursion_test_baseline $srcfile];
+if { $baseline == -1 } then {
+ fail "Could not find gdb_recursion_test function"
+ return;
+}
+
+set testline1 [expr $baseline + 1]
+set testline2 [expr $baseline + 3]
+
+#
+# test "help tracepoints"
+#
+
+set helpcnt 0;
+send_gdb "help tracepoints\n"
+gdb_expect {
+ -re "Tracing of program execution without stopping the program." {
+ incr helpcnt;
+ exp_continue
+ }
+ -re "actions -- Specify the actions to be taken at a tracepoint" {
+ incr helpcnt;
+ exp_continue
+ }
+ -re "collect -- Specify one or more data items to be collected" {
+ incr helpcnt;
+ exp_continue
+ }
+ -re "delete tracepoints -- Delete specified tracepoints" {
+ incr helpcnt;
+ exp_continue
+ }
+ -re "end -- Ends a list of.*actions" {
+ incr helpcnt;
+ exp_continue
+ }
+ -re "info tracepoints -- Status of tracepoints" {
+ incr helpcnt;
+ exp_continue
+ }
+ -re "passcount -- Set the passcount for a tracepoint" {
+ incr helpcnt;
+ exp_continue
+ }
+ -re "save-tracepoints -- Save current tracepoint definitions" {
+ incr helpcnt;
+ exp_continue
+ }
+ -re "tdump -- Print everything collected at the current tracepoint" {
+ incr helpcnt;
+ exp_continue
+ }
+ -re "tfind -- Select a trace frame" {
+ incr helpcnt;
+ exp_continue
+ }
+ -re "tfind end -- Synonym for 'none'" {
+ incr helpcnt;
+ exp_continue
+ }
+ -re "tfind line -- Select a trace frame by line number" {
+ incr helpcnt;
+ exp_continue
+ }
+ -re "tfind none -- De-select any trace frame and resume 'live' debugging" {
+ incr helpcnt;
+ exp_continue
+ }
+ -re "tfind outside -- Select a trace frame whose PC is outside" {
+ incr helpcnt;
+ exp_continue
+ }
+ -re "tfind pc -- Select a trace frame by PC" {
+ incr helpcnt;
+ exp_continue
+ }
+ -re "tfind range -- Select a trace frame whose PC is in the given" {
+ incr helpcnt;
+ exp_continue
+ }
+ -re "tfind start -- Select the first trace frame in the trace buffer" {
+ incr helpcnt;
+ exp_continue
+ }
+ -re "tfind tracepoint -- Select a trace frame by tracepoint number" {
+ incr helpcnt;
+ exp_continue
+ }
+ -re "trace -- Set a tracepoint at a specified line or function or addr" {
+ incr helpcnt;
+ exp_continue
+ }
+ -re "tstart -- Start trace data collection" {
+ incr helpcnt;
+ exp_continue
+ }
+ -re "tstatus -- Display the status of the current trace data collection" {
+ incr helpcnt;
+ exp_continue
+ }
+ -re "tstop -- Stop trace data collection" {
+ incr helpcnt;
+ exp_continue
+ }
+ -re "while-stepping -- Specify single-stepping behavior at a tracepoint" {
+ incr helpcnt;
+ exp_continue
+ }
+ -re ".*$gdb_prompt $" {
+ if { $helpcnt == 21 } {
+ pass "1.0: help tracepoints"
+ } else {
+ warning "$helpcnt";
+ fail "1.0: help tracepoints"
+ }
+ }
+}
+
+#
+# test trace command:
+#
+
+# 1.1 trace source line
+gdb_delete_tracepoints
+gdb_test "trace $srcfile:$testline2" \
+ "Tracepoint $decimal at $hex: file.*$srcfile, line $testline2." \
+ "1.1a: set tracepoint at sourceline"
+gdb_test "info trace" "in gdb_recursion_test.*$srcfile:$testline2" \
+ "1.1b: trace sourcefile:line"
+
+# 1.2 trace invalid source line
+gdb_delete_tracepoints
+gdb_test "trace $srcfile:99999" "No line 99999 in file \".*$srcfile\"." \
+ "1.2a: trace invalid line in sourcefile"
+gdb_test "info trace" "No tracepoints.*" \
+ "1.2b: reject invalid line in srcfile"
+
+# 1.3 trace line in invalid source file
+gdb_delete_tracepoints
+gdb_test "trace NoSuChFiLe.c:1" "No source file named NoSuChFiLe.c." \
+ "1.3a: trace invalid source file"
+gdb_test "info trace" "No tracepoints.*" \
+ "1.3b: reject invalid srcfile"
+
+# 1.4 trace function by name
+gdb_delete_tracepoints
+gdb_test "trace gdb_recursion_test" \
+ "Tracepoint $decimal at $hex: file.*$srcfile, line $testline1." \
+ "1.4a: trace function by name"
+gdb_test "info trace" "in gdb_recursion_test.*$srcfile:$testline1" \
+ "1.4b: trace function by name"
+
+# 1.5 trace non-existant function
+gdb_delete_tracepoints
+gdb_test "trace NoSuChFuNc" "Function \"NoSuChFuNc\" not defined." \
+ "1.5a: trace invalid function"
+gdb_test "info trace" "No tracepoints.*" \
+ "1.5b: reject invalid srcfile"
+
+# 1.6 trace at a specific address
+# Collect the address of "gdb_asm_test", and use that.
+send_gdb "print gdb_asm_test\n"
+gdb_expect {
+ -re "\[$\]\[0-9\].*0x(\[0-9a-fA-F\]+).*$gdb_prompt $" {
+ set asm_test_addr $expect_out(1,string)
+ }
+ timeout { }
+}
+
+gdb_delete_tracepoints
+gdb_test "trace \*0x$asm_test_addr" \
+ "Tracepoint $decimal at .*$asm_test_addr.*" \
+ "1.6a: trace at specific address"
+gdb_test "info trace" "$asm_test_addr.*gdb_asm_test.*" \
+ "1.6b: verify trace at specific address"
+
+# 1.7 trace at function's exact address
+# Collect the address of the function for comparison
+send_gdb "print gdb_recursion_test\n"
+gdb_expect {
+ -re "\[$\]\[0-9\].*0x(\[0-9a-fA-F\]+).*$gdb_prompt $" {
+ set c_test_addr $expect_out(1,string)
+ }
+ timeout { }
+}
+
+gdb_delete_tracepoints
+gdb_test "trace \*gdb_recursion_test" \
+ "Tracepoint $decimal at .*$c_test_addr.*" \
+ "1.7a: trace at function label (before prologue)"
+gdb_test "info trace" "$c_test_addr.*in gdb_recursion_test.*:$baseline" \
+ "1.7b: verify trace at specific address"
+
+# 1.8 trace at invalid address
+# no address is invalid
+
+# 1.9 trace no arguments
+gdb_test "trace" "trace command requires an argument" \
+ "1.9: trace <no arguments>"
+
+# 1.10 set large number of tracepoints
+# deferred to limits test module
+
+# 1.11 tracepoint conditions
+# conditions on tracepoints not implemented
+
+# 1.12 set tracepoint in prologue
+# [see tfind.exp]
+
+# 1.13 trace on recursion
+# interesting only in "live" session: see backtrace.exp for live test.
+
+# 1.14 help trace
+gdb_test "help trace" "Set a tracepoint at .*" "1.14: help trace"
+
+
diff --git a/gdb/testsuite/gdb.trace/while-dyn.exp b/gdb/testsuite/gdb.trace/while-dyn.exp
new file mode 100644
index 00000000000..a6ff0fc7850
--- /dev/null
+++ b/gdb/testsuite/gdb.trace/while-dyn.exp
@@ -0,0 +1,124 @@
+# Copyright (C) 1998 Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file was written by Michael Snyder (msnyder@cygnus.com)
+
+load_lib "trace-support.exp"
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+set prms_id 0
+set bug_id 0
+
+gdb_exit
+gdb_start
+
+if [istarget "m68k-*-elf"] then {
+ load_lib "emc-support.exp"
+ set testfile "gdb_c_test"
+ set srcfile $testfile.c
+ set binfile [board_info target d490_binfile];
+ gdb_test "set remotetimeout 6" "" ""
+ set timeout 500
+ gdb_target_monitor "$binfile"
+ # Give a TSTOP and ignore errors, to make sure any previous trace is off
+ gdb_test "tstop" "" ""
+ gdb_test "tfind none" "" ""
+ send_gdb "compare-section CS\n"
+ gdb_expect {
+ -re "MIS-MATCHED.*$gdb_prompt $" {
+ gdb_suppress_entire_file "Symbol file does not match target!
+ all tests in this module will fail.";
+ }
+ -re ".*$gdb_prompt $" { }
+ }
+} else {
+ set testfile "actions"
+ set srcfile $testfile.c
+ set binfile $objdir/$subdir/$testfile
+ if { [gdb_compile "$srcdir/$subdir/$srcfile" $binfile \
+ executable {debug additional_flags=-w}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+ }
+ gdb_load $binfile
+ gdb_test "tstop" "" ""
+ gdb_test "tfind none" "" ""
+ runto_main
+}
+gdb_reinitialize_dir $srcdir/$subdir
+
+# We generously give ourselves one "pass" if we successfully
+# detect that this test cannot be run on this target!
+if { ![gdb_target_supports_trace] } then {
+ pass "Current target does not supporst trace"
+ return 1;
+
+}
+
+# If testing on a remote host, download the source file.
+# remote_download host $srcdir/$subdir/$srcfile
+
+#
+# test while-stepping dynamically (live target)
+#
+
+## verify number of trace frames collected matches stepcount
+
+gdb_delete_tracepoints
+gdb_test "trace gdb_c_test" \
+ "Tracepoint $decimal at .*" \
+ "Set tracepoint at gdb_c_test"
+
+gdb_trace_setactions "5.12: define while-stepping <stepcount>" \
+ "" \
+ "collect \$fp" "^$" \
+ "while-stepping 5" "^$" \
+ "collect p" "^$" \
+ "end" "^$" \
+ "end" ""
+
+gdb_test "tstart" "" ""
+
+if [istarget "m68k-*-elf"] then {
+ gdb_emclaptop_command "85,1,2,3,4,5,6"
+ sleep 5
+} else {
+ gdb_test "break end" "" ""
+ gdb_test "continue" \
+ "Continuing.*Breakpoint $decimal, end.*" \
+ "run trace experiment"
+}
+
+gdb_test "tstop" "" ""
+
+gdb_tfind_test "5.12: frame 5 should be the last one collected" "5" "5"
+
+send_gdb "tfind 6\n"
+gdb_expect {
+ -re "failed to find.*$gdb_prompt $" {
+ pass "5.12: trace stopped after 5 stepping frames"
+ }
+ -re ".*$gdb_prompt $" {
+ fail "5.12: trace stopped after 5 stepping frames"
+ }
+}
+
+gdb_test "tfind none" "" ""
diff --git a/gdb/testsuite/gdb.trace/while-stepping.exp b/gdb/testsuite/gdb.trace/while-stepping.exp
new file mode 100644
index 00000000000..610bd419331
--- /dev/null
+++ b/gdb/testsuite/gdb.trace/while-stepping.exp
@@ -0,0 +1,116 @@
+# Copyright (C) 1998 Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file was written by Michael Snyder (msnyder@cygnus.com)
+
+load_lib "trace-support.exp";
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+set prms_id 0
+set bug_id 0
+
+gdb_exit
+gdb_start
+
+if [istarget "m68k-*-elf"] then {
+ set srcfile gdb_c_test.c
+ set binfile [board_info target d490_binfile];
+} else {
+ set testfile "actions"
+ set srcfile ${testfile}.c
+ set binfile ${objdir}/${subdir}/${testfile}
+ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" $binfile \
+ executable {debug additional_flags=-w}] != "" } {
+ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+ }
+}
+gdb_reinitialize_dir $srcdir/$subdir
+
+# If testing on a remote host, download the source file.
+# remote_download host $srcdir/$subdir/$srcfile
+
+gdb_file_cmd $binfile
+
+#
+# test while-stepping command
+#
+
+gdb_delete_tracepoints
+set trcpt1 [gdb_gettpnum gdb_c_test]
+if { $trcpt1 <= 0 } then {
+ fail "Could not find gdb_c_test function"
+ return;
+}
+
+# 5.12 basic while-stepping command (collect regs)
+
+gdb_test "info tracepoints" \
+ "Num Enb Address PassC StepC What.*$trcpt1.*0x.*\[\t \]+\[0-9\]+\[\t \]+0\[\t \]+.*in gdb_c_test.*" \
+ "5.12: set a tracepoint, stepcount is zero"
+
+set stepcount 12
+
+gdb_trace_setactions "5.12: set stepcount to $stepcount" \
+ "" \
+ "while-stepping $stepcount" "" \
+ "collect \$regs" "^$" \
+ "end" ""
+
+gdb_test "info tracepoints" \
+ "Num Enb Address PassC StepC What.*$trcpt1.*0x.*\[\t \]+\[0-9\]+\[\t \]+$stepcount\[\t \]+.*in gdb_c_test.*" \
+ "5.12: confirm stepcount set to $stepcount"
+
+gdb_test "info tracepoints" \
+ "Num Enb Address PassC StepC What.*
+.*while-stepping $stepcount.*" \
+ "5.12: info trace shows \"while-stepping\""
+
+
+# 5.13 step out of context while collecting local variable
+# [deferred to dynamic test section]
+
+proc while_stepping_bogus_arg { bogus msgstring } {
+ global gdb_prompt;
+
+ gdb_trace_setactions "$msgstring" \
+ "" \
+ "while-stepping $bogus" "\[Ee\]rror|\[Ww\]arning"
+}
+
+# 5.14 while-stepping (no argument)
+
+while_stepping_bogus_arg "" "5.14: while-stepping null stepcount"
+
+# 5.15 while-stepping (zero stepcount)
+
+while_stepping_bogus_arg "0" "5.15: while-stepping rejects zero stepcount"
+
+# 5.16 while-stepping without collecting anything
+gdb_trace_setactions "5.16: step without collecting anything" \
+ "" \
+ "while-stepping $stepcount" "^$" \
+ "end" ""
+
+gdb_test "info tracepoints" \
+ ".*$trcpt1.*0x.*\[\t \]+\[0-9\]+\[\t \]+$stepcount\[\t \]+.*in gdb_c_test.*\[ \t\]+Actions for tracepoint $trcpt1:.*\[ \t\]+while-stepping $stepcount.*\[ \t\]+end.*\[ \t\]+end.*" \
+ "5.16: confirm actions, step without collecting anything"
+
diff --git a/gdb/testsuite/lib/emc-support.exp b/gdb/testsuite/lib/emc-support.exp
new file mode 100644
index 00000000000..70bf2df0690
--- /dev/null
+++ b/gdb/testsuite/lib/emc-support.exp
@@ -0,0 +1,223 @@
+proc gdb_emc_readvar { varname } {
+ global gdb_prompt;
+
+ set result -1;
+ send_gdb "print $varname\n"
+ gdb_expect 5 {
+ -re "\[$\].*= (\[0-9\]+).*$gdb_prompt $" {
+ set result $expect_out(1,string);
+ }
+ -re "$gdb_prompt $" { }
+ default { }
+ }
+ return $result;
+}
+
+proc gdb_emc_gettpnum { testname } {
+ global gdb_prompt;
+
+ if { $testname != "" } {
+ gdb_test "trace $testname" "" ""
+ }
+ return [gdb_emc_readvar "\$tpnum"];
+}
+
+proc gdb_emc_setactions { testname actionname args } {
+ global gdb_prompt;
+
+ set state 0;
+ set status "pass";
+ send_gdb "actions $actionname\n";
+ set expected_result "";
+ gdb_expect 5 {
+ -re "No tracepoint number .*$gdb_prompt $" {
+ fail $testname
+ return 1;
+ }
+ -re "Enter actions for tracepoint $actionname.*>" {
+ if { [llength $args] > 0 } {
+ set lastcommand "[lindex $args $state]";
+ send_gdb "[lindex $args $state]\n";
+ incr state;
+ set expected_result [lindex $args $state];
+ incr state;
+ } else {
+ send_gdb "end\n";
+ }
+ exp_continue;
+ }
+ -re "\(.*\[\r\n\]+)\[ \t]*> $" {
+ if { $expected_result != "" } {
+ # Remove echoed command and its associated newline.
+ regsub "^\[^\r\n\]+\[\r\n\]+" "$expect_out(1,string)" "" out;
+ # Strip off any newlines at the end of the string.
+ regsub "\[\r\n\]+$" "$out" "" out;
+ verbose "expected '$expected_result', got '$out', expect_out is '$expect_out(1,string)'";
+ if ![regexp $expected_result $out] {
+ set status "fail";
+ }
+ set expected_result "";
+ }
+ if { $state < [llength $args] } {
+ send_gdb "[lindex $args $state]\n";
+ incr state;
+ set expected_result [lindex $args $state];
+ incr state;
+ } else {
+ send_gdb "end\n";
+ set expected_result "";
+ }
+ exp_continue;
+ }
+ -re "\(.*\)$gdb_prompt $" {
+ if { $expected_result != "" } {
+ if ![regexp $expected_result $expect_out(1,string)] {
+ set status "fail";
+ }
+ set expected_result "";
+ }
+ if { [llength $args] < $state } {
+ set status "fail";
+ }
+ }
+ default {
+ set status "fail";
+ }
+ }
+ if { $testname != "" } {
+ $status $testname;
+ }
+ if { $status == "pass" } then {
+ return 0;
+ } else {
+ return 1;
+ }
+}
+
+#
+# test collect command
+#
+
+proc gdb_emc_tracetest_collect { arg1 msgstring } {
+ global decimal
+ global gdb_prompt;
+
+ set teststate 0
+ gdb_expect 30 {
+ -re "Enter actions for tracepoint $decimal.*> $" {
+ send_gdb "collect $arg1\n"
+ incr teststate;
+ exp_continue
+ }
+ -re "> $" {
+ if { $teststate == 1 } {
+ send_gdb "end\n"
+ incr teststate;
+ exp_continue
+ } else {
+ fail "$msgstring"
+ }
+ }
+ -re ".*$gdb_prompt $" {
+ if { $teststate == 2 } {
+ pass "$msgstring";
+ } else {
+ fail "$msgstring";
+ }
+ }
+ default {
+ fail "$msgstring (default)";
+ }
+ }
+ regsub -all "(\[($@*+)\])" "collect $arg1" "\[\\1\]" arg1_regexp;
+ gdb_test "info tracepoints" ".*$arg1_regexp.*" "$msgstring info tracepoint"
+}
+
+proc gdb_delete_tracepoints { } {
+ global gdb_prompt;
+
+ send_gdb "delete tracepoints\n"
+ gdb_expect 30 {
+ -re "Delete all tracepoints.*y or n.*$" {
+ send_gdb "y\n"
+ exp_continue;
+ }
+ -re "$gdb_prompt $" { }
+ timeout { fail "delete all tracepoints (timeout)" }
+ }
+}
+
+
+# Send each command in the list CMDLIST to gdb. If we see the string
+# "error" or "warning" from gdb, we assume an error has occured and
+# return a non-zero result. All of the commands in CMDLIST are always
+# sent, even if an error occurs.
+# If TESTNAME is non-null, we call pass or fail with the string in TESTNAME
+# depending on whether or not an error/warning has occurred.
+#
+proc gdb_do_cmdlist { cmdlist testname } {
+ global gdb_prompt;
+
+ set status 0;
+
+ foreach x $cmdlist {
+ send_gdb "$x\n";
+ gdb_expect 60 {
+ -re "\[Ee\]rror|\[Ww\]arning" {
+ set status 1;
+ exp_continue;
+ }
+ -re "$gdb_prompt $" { }
+ -re "\[\r\n\]\[ \t\]*> *$" { }
+ }
+ }
+ if { $testname != "" } {
+ if { $status == 0 } {
+ pass "$testname";
+ } else {
+ fail "$testname";
+ }
+ }
+ return $status;
+}
+
+#
+# Given the file FILENAME, we read it as a list of commands and generate
+# a list suitable for use by gdb_do_cmdlist. Lines beginning with # are
+# ignored; blank lines are interpreted as empty lines to be sent to gdb.
+#
+proc gdb_process_cmdfile { filename } {
+ set id [open $filename "r"];
+ if { $id < 0 } {
+ return "";
+ }
+ set result {};
+ while { [gets $id line] >= 0 } {
+ if [regexp "^#" $line] {
+ continue;
+ }
+ set result [concat $result [list "$line"]];
+ }
+ close $id;
+ return $result;
+}
+
+# gdb_find_c_test_baseline
+# returns -1 on failure (CALLER MUST CHECK RETURN!)
+proc gdb_find_c_test_baseline { } {
+ global gdb_prompt;
+
+ set gdb_c_test_baseline -1;
+
+ send_gdb "list gdb_c_test\n"
+ gdb_expect {
+ -re "void.*p5,.*void.*p6.*\[\r\n\](\[0-9\]+)\[\t \]+\{.*$gdb_prompt $" {
+ set gdb_c_test_baseline $expect_out(1,string)
+ }
+ -re "$gdb_prompt $" { }
+ default { }
+ }
+ return $gdb_c_test_baseline;
+}
+
+
diff --git a/gdb/testsuite/lib/gdb.exp b/gdb/testsuite/lib/gdb.exp
new file mode 100644
index 00000000000..c61abb6f592
--- /dev/null
+++ b/gdb/testsuite/lib/gdb.exp
@@ -0,0 +1,1334 @@
+# Copyright (C) 1992, 1994, 1995, 1997 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file was written by Fred Fish. (fnf@cygnus.com)
+
+# Generic gdb subroutines that should work for any target. If these
+# need to be modified for any target, it can be done with a variable
+# or by passing arguments.
+
+load_lib libgloss.exp
+
+global GDB
+global CHILL_LIB
+global CHILL_RT0
+
+if ![info exists CHILL_LIB] {
+ set CHILL_LIB [findfile $base_dir/../../gcc/ch/runtime/libchill.a "$base_dir/../../gcc/ch/runtime/libchill.a" [transform -lchill]]
+}
+verbose "using CHILL_LIB = $CHILL_LIB" 2
+if ![info exists CHILL_RT0] {
+ set CHILL_RT0 [findfile $base_dir/../../gcc/ch/runtime/chillrt0.o "$base_dir/../../gcc/ch/runtime/chillrt0.o" ""]
+}
+verbose "using CHILL_RT0 = $CHILL_RT0" 2
+
+if [info exists TOOL_EXECUTABLE] {
+ set GDB $TOOL_EXECUTABLE;
+}
+if ![info exists GDB] {
+ if ![is_remote host] {
+ set GDB [findfile $base_dir/../../gdb/gdb "$base_dir/../../gdb/gdb" [transform gdb]]
+ } else {
+ set GDB [transform gdb];
+ }
+}
+verbose "using GDB = $GDB" 2
+
+global GDBFLAGS
+if ![info exists GDBFLAGS] {
+ set GDBFLAGS "-nx"
+}
+verbose "using GDBFLAGS = $GDBFLAGS" 2
+
+# The variable prompt is a regexp which matches the gdb prompt. Set it if it
+# is not already set.
+global gdb_prompt
+if ![info exists prompt] then {
+ set gdb_prompt "\[(\]gdb\[)\]"
+}
+
+#
+# gdb_version -- extract and print the version number of GDB
+#
+proc default_gdb_version {} {
+ global GDB
+ global GDBFLAGS
+ global gdb_prompt
+ set fileid [open "gdb_cmd" w];
+ puts $fileid "q";
+ close $fileid;
+ set cmdfile [remote_download host "gdb_cmd"];
+ set output [remote_exec host "$GDB -nw --command $cmdfile"]
+ remote_file build delete "gdb_cmd";
+ remote_file host delete "$cmdfile";
+ set tmp [lindex $output 1];
+ set version ""
+ regexp " \[0-9\]\[^ \t\n\r\]+" "$tmp" version
+ if ![is_remote host] {
+ clone_output "[which $GDB] version $version $GDBFLAGS\n"
+ } else {
+ clone_output "$GDB on remote host version $version $GDBFLAGS\n"
+ }
+}
+
+proc gdb_version { } {
+ return [default_gdb_version];
+}
+
+#
+# gdb_unload -- unload a file if one is loaded
+#
+
+proc gdb_unload {} {
+ global verbose
+ global GDB
+ global gdb_prompt
+ send_gdb "file\n"
+ gdb_expect 60 {
+ -re "No executable file now\[^\r\n\]*\[\r\n\]" { exp_continue }
+ -re "No symbol file now\[^\r\n\]*\[\r\n\]" { exp_continue }
+ -re "A program is being debugged already..*Kill it.*y or n. $"\
+ { send_gdb "y\n"
+ verbose "\t\tKilling previous program being debugged"
+ exp_continue
+ }
+ -re "Discard symbol table from .*y or n.*$" {
+ send_gdb "y\n"
+ exp_continue
+ }
+ -re "$gdb_prompt $" {}
+ timeout {
+ perror "couldn't unload file in $GDB (timed out)."
+ return -1
+ }
+ }
+}
+
+# Many of the tests depend on setting breakpoints at various places and
+# running until that breakpoint is reached. At times, we want to start
+# with a clean-slate with respect to breakpoints, so this utility proc
+# lets us do this without duplicating this code everywhere.
+#
+
+proc delete_breakpoints {} {
+ global gdb_prompt
+
+ send_gdb "delete breakpoints\n"
+ gdb_expect 30 {
+ -re "Delete all breakpoints.*y or n.*$" {
+ send_gdb "y\n";
+ exp_continue
+ }
+ -re "$gdb_prompt $" { # This happens if there were no breakpoints
+ }
+ timeout { perror "Delete all breakpoints in delete_breakpoints (timeout)" ; return }
+ }
+ send_gdb "info breakpoints\n"
+ gdb_expect 30 {
+ -re "No breakpoints or watchpoints..*$gdb_prompt $" {}
+ -re "$gdb_prompt $" { perror "breakpoints not deleted" ; return }
+ -re "Delete all breakpoints.*or n.*$" {
+ send_gdb "y\n";
+ exp_continue
+ }
+ timeout { perror "info breakpoints (timeout)" ; return }
+ }
+}
+
+
+#
+# Generic run command.
+#
+# The second pattern below matches up to the first newline *only*.
+# Using ``.*$'' could swallow up output that we attempt to match
+# elsewhere.
+#
+proc gdb_run_cmd {args} {
+ global gdb_prompt
+
+ if [target_info exists gdb_init_command] {
+ send_gdb "[target_info gdb_init_command]\n";
+ gdb_expect 30 {
+ -re "$gdb_prompt $" { }
+ default {
+ perror "gdb_init_command for target failed";
+ return;
+ }
+ }
+ }
+
+ if [target_info exists use_gdb_stub] {
+ if [target_info exists gdb,do_reload_on_run] {
+ # According to Stu, this will always work.
+ gdb_load "";
+ send_gdb "continue\n";
+ gdb_expect 60 {
+ -re "Continu\[^\r\n\]*\[\r\n\]" {}
+ default {}
+ }
+ return;
+ }
+
+ if [target_info exists gdb,start_symbol] {
+ set start [target_info gdb,start_symbol];
+ } else {
+ set start "start";
+ }
+ send_gdb "jump *$start\n"
+ gdb_expect 30 {
+ -re "Continuing at \[^\r\n\]*\[\r\n\]" {
+ if ![target_info exists gdb_stub] {
+ return;
+ }
+ }
+ -re "No symbol \"start\" in current.*$gdb_prompt $" {
+ send_gdb "jump *_start\n";
+ exp_continue;
+ }
+ -re "No symbol \"_start\" in current.*$gdb_prompt $" {
+ perror "Can't find start symbol to run in gdb_run";
+ return;
+ }
+ -re "Line.* Jump anyway.*y or n. $" {
+ send_gdb "y\n"
+ exp_continue;
+ }
+ -re "No symbol.*context.*$gdb_prompt $" {}
+ -re "The program is not being run.*$gdb_prompt $" {
+ gdb_load "";
+ send_gdb "jump *$start\n";
+ exp_continue;
+ }
+ timeout { perror "Jump to start() failed (timeout)"; return }
+ }
+ if [target_info exists gdb_stub] {
+ gdb_expect 60 {
+ -re "$gdb_prompt $" {
+ send_gdb "continue\n"
+ }
+ }
+ }
+ return
+ }
+ send_gdb "run $args\n"
+# This doesn't work quite right yet.
+ gdb_expect 60 {
+ -re "The program .* has been started already.*y or n. $" {
+ send_gdb "y\n"
+ exp_continue
+ }
+ -re "Starting program: \[^\r\n\]*" {}
+ }
+}
+
+proc gdb_breakpoint { function } {
+ global gdb_prompt
+ global decimal
+
+ send_gdb "break $function\n"
+ # The first two regexps are what we get with -g, the third is without -g.
+ gdb_expect 30 {
+ -re "Breakpoint \[0-9\]* at .*: file .*, line $decimal.\r\n$gdb_prompt $" {}
+ -re "Breakpoint \[0-9\]*: file .*, line $decimal.\r\n$gdb_prompt $" {}
+ -re "Breakpoint \[0-9\]* at .*$gdb_prompt $" {}
+ -re "$gdb_prompt $" { fail "setting breakpoint at $function" ; return 0 }
+ timeout { fail "setting breakpoint at $function (timeout)" ; return 0 }
+ }
+ return 1;
+}
+
+# Set breakpoint at function and run gdb until it breaks there.
+# Since this is the only breakpoint that will be set, if it stops
+# at a breakpoint, we will assume it is the one we want. We can't
+# just compare to "function" because it might be a fully qualified,
+# single quoted C++ function specifier.
+
+proc runto { function } {
+ global gdb_prompt
+ global decimal
+
+ delete_breakpoints
+
+ if ![gdb_breakpoint $function] {
+ return 0;
+ }
+
+ gdb_run_cmd
+
+ # the "at foo.c:36" output we get with -g.
+ # the "in func" output we get without -g.
+ gdb_expect 30 {
+ -re "Break.* at .*:$decimal.*$gdb_prompt $" {
+ return 1
+ }
+ -re "Breakpoint \[0-9\]*, \[0-9xa-f\]* in .*$gdb_prompt $" {
+ return 1
+ }
+ -re "$gdb_prompt $" {
+ fail "running to $function in runto"
+ return 0
+ }
+ timeout {
+ fail "running to $function in runto (timeout)"
+ return 0
+ }
+ }
+ return 1
+}
+
+#
+# runto_main -- ask gdb to run until we hit a breakpoint at main.
+# The case where the target uses stubs has to be handled
+# specially--if it uses stubs, assuming we hit
+# breakpoint() and just step out of the function.
+#
+proc runto_main { } {
+ global gdb_prompt
+ global decimal
+
+ if ![target_info exists gdb_stub] {
+ return [runto main]
+ }
+
+ delete_breakpoints
+
+ gdb_step_for_stub;
+
+ return 1
+}
+
+# gdb_test COMMAND PATTERN MESSAGE -- send a command to gdb; test the result.
+#
+# COMMAND is the command to execute, send to GDB with send_gdb. If
+# this is the null string no command is sent.
+# PATTERN is the pattern to match for a PASS, and must NOT include
+# the \r\n sequence immediately before the gdb prompt.
+# MESSAGE is an optional message to be printed. If this is
+# omitted, then the pass/fail messages use the command string as the
+# message. (If this is the empty string, then sometimes we don't
+# call pass or fail at all; I don't understand this at all.)
+#
+# Returns:
+# 1 if the test failed,
+# 0 if the test passes,
+# -1 if there was an internal error.
+#
+proc gdb_test { args } {
+ global verbose
+ global gdb_prompt
+ global GDB
+ upvar timeout timeout
+
+ if [llength $args]>2 then {
+ set message [lindex $args 2]
+ } else {
+ set message [lindex $args 0]
+ }
+ set command [lindex $args 0]
+ set pattern [lindex $args 1]
+
+ if [llength $args]==5 {
+ set question_string [lindex $args 3];
+ set response_string [lindex $args 4];
+ } else {
+ set question_string "^FOOBAR$"
+ }
+
+ if $verbose>2 then {
+ send_user "Sending \"$command\" to gdb\n"
+ send_user "Looking to match \"$pattern\"\n"
+ send_user "Message is \"$message\"\n"
+ }
+
+ set result -1
+ set string "${command}\n";
+ if { $command != "" } {
+ while { "$string" != "" } {
+ set foo [string first "\n" "$string"];
+ set len [string length "$string"];
+ if { $foo < [expr $len - 1] } {
+ set str [string range "$string" 0 $foo];
+ if { [send_gdb "$str"] != "" } {
+ global suppress_flag;
+
+ if { ! $suppress_flag } {
+ perror "Couldn't send $command to GDB.";
+ }
+ fail "$message";
+ return $result;
+ }
+ gdb_expect 2 {
+ -re "\[\r\n\]" { }
+ timeout { }
+ }
+ set string [string range "$string" [expr $foo + 1] end];
+ } else {
+ break;
+ }
+ }
+ if { "$string" != "" } {
+ if { [send_gdb "$string"] != "" } {
+ global suppress_flag;
+
+ if { ! $suppress_flag } {
+ perror "Couldn't send $command to GDB.";
+ }
+ fail "$message";
+ return $result;
+ }
+ }
+ }
+
+ if [info exists timeout] {
+ set tmt $timeout;
+ } else {
+ global timeout;
+ if [info exists timeout] {
+ set tmt $timeout;
+ } else {
+ set tmt 60;
+ }
+ }
+ gdb_expect $tmt {
+ -re "\\*\\*\\* DOSEXIT code.*" {
+ if { $message != "" } {
+ fail "$message";
+ }
+ gdb_suppress_entire_file "GDB died";
+ return -1;
+ }
+ -re "Ending remote debugging.*$gdb_prompt$" {
+ if ![isnative] then {
+ warning "Can`t communicate to remote target."
+ }
+ gdb_exit
+ gdb_start
+ set result -1
+ }
+ -re "\[\r\n\]*($pattern)\[\r\n\]+$gdb_prompt $" {
+ if ![string match "" $message] then {
+ pass "$message"
+ }
+ set result 0
+ }
+ -re "(${question_string})$" {
+ send_gdb "$response_string\n";
+ exp_continue;
+ }
+ -re "Undefined command:.*$gdb_prompt" {
+ perror "Undefined command \"$command\"."
+ set result 1
+ }
+ -re "Ambiguous command.*$gdb_prompt $" {
+ perror "\"$command\" is not a unique command name."
+ set result 1
+ }
+ -re "Program exited with code \[0-9\]+.*$gdb_prompt $" {
+ if ![string match "" $message] then {
+ set errmsg "$message: the program exited"
+ } else {
+ set errmsg "$command: the program exited"
+ }
+ fail "$errmsg"
+ return -1
+ }
+ -re "The program is not being run.*$gdb_prompt $" {
+ if ![string match "" $message] then {
+ set errmsg "$message: the program is no longer running"
+ } else {
+ set errmsg "$command: the program is no longer running"
+ }
+ fail "$errmsg"
+ return -1
+ }
+ -re ".*$gdb_prompt $" {
+ if ![string match "" $message] then {
+ fail "$message"
+ }
+ set result 1
+ }
+ "<return>" {
+ send_gdb "\n"
+ perror "Window too small."
+ }
+ -re "\\(y or n\\) " {
+ send_gdb "n\n"
+ perror "Got interactive prompt."
+ }
+ eof {
+ perror "Process no longer exists"
+ if { $message != "" } {
+ fail "$message"
+ }
+ return -1
+ }
+ full_buffer {
+ perror "internal buffer is full."
+ }
+ timeout {
+ if ![string match "" $message] then {
+ fail "$message (timeout)"
+ }
+ set result 1
+ }
+ }
+ return $result
+}
+
+# Test that a command gives an error. For pass or fail, return
+# a 1 to indicate that more tests can proceed. However a timeout
+# is a serious error, generates a special fail message, and causes
+# a 0 to be returned to indicate that more tests are likely to fail
+# as well.
+
+proc test_print_reject { args } {
+ global gdb_prompt
+ global verbose
+
+ if [llength $args]==2 then {
+ set expectthis [lindex $args 1]
+ } else {
+ set expectthis "should never match this bogus string"
+ }
+ set sendthis [lindex $args 0]
+ if $verbose>2 then {
+ send_user "Sending \"$sendthis\" to gdb\n"
+ send_user "Looking to match \"$expectthis\"\n"
+ }
+ send_gdb "$sendthis\n"
+ #FIXME: Should add timeout as parameter.
+ gdb_expect {
+ -re "A .* in expression.*\\.*$gdb_prompt $" {
+ pass "reject $sendthis"
+ return 1
+ }
+ -re "Invalid syntax in expression.*$gdb_prompt $" {
+ pass "reject $sendthis"
+ return 1
+ }
+ -re "Junk after end of expression.*$gdb_prompt $" {
+ pass "reject $sendthis"
+ return 1
+ }
+ -re "Invalid number.*$gdb_prompt $" {
+ pass "reject $sendthis"
+ return 1
+ }
+ -re "Invalid character constant.*$gdb_prompt $" {
+ pass "reject $sendthis"
+ return 1
+ }
+ -re "No symbol table is loaded.*$gdb_prompt $" {
+ pass "reject $sendthis"
+ return 1
+ }
+ -re "No symbol .* in current context.*$gdb_prompt $" {
+ pass "reject $sendthis"
+ return 1
+ }
+ -re "$expectthis.*$gdb_prompt $" {
+ pass "reject $sendthis"
+ return 1
+ }
+ -re ".*$gdb_prompt $" {
+ fail "reject $sendthis"
+ return 1
+ }
+ default {
+ fail "reject $sendthis (eof or timeout)"
+ return 0
+ }
+ }
+}
+
+# Given an input string, adds backslashes as needed to create a
+# regexp that will match the string.
+
+proc string_to_regexp {str} {
+ set result $str
+ regsub -all {[]*+.|()^$\[]} $str {\\&} result
+ return $result
+}
+
+# Same as gdb_test, but the second parameter is not a regexp,
+# but a string that must match exactly.
+
+proc gdb_test_exact { args } {
+ upvar timeout timeout
+
+ set command [lindex $args 0]
+
+ # This applies a special meaning to a null string pattern. Without
+ # this, "$pattern\r\n$gdb_prompt $" will match anything, including error
+ # messages from commands that should have no output except a new
+ # prompt. With this, only results of a null string will match a null
+ # string pattern.
+
+ set pattern [lindex $args 1]
+ if [string match $pattern ""] {
+ set pattern [string_to_regexp [lindex $args 0]]
+ } else {
+ set pattern [string_to_regexp [lindex $args 1]]
+ }
+
+ # It is most natural to write the pattern argument with only
+ # embedded \n's, especially if you are trying to avoid Tcl quoting
+ # problems. But gdb_expect really wants to see \r\n in patterns. So
+ # transform the pattern here. First transform \r\n back to \n, in
+ # case some users of gdb_test_exact already do the right thing.
+ regsub -all "\r\n" $pattern "\n" pattern
+ regsub -all "\n" $pattern "\r\n" pattern
+ if [llength $args]==3 then {
+ set message [lindex $args 2]
+ } else {
+ set message $command
+ }
+
+ return [gdb_test $command $pattern $message]
+}
+
+proc gdb_reinitialize_dir { subdir } {
+ global gdb_prompt
+
+ if [is_remote host] {
+ return "";
+ }
+ send_gdb "dir\n"
+ gdb_expect 60 {
+ -re "Reinitialize source path to empty.*y or n. " {
+ send_gdb "y\n"
+ gdb_expect 60 {
+ -re "Source directories searched.*$gdb_prompt $" {
+ send_gdb "dir $subdir\n"
+ gdb_expect 60 {
+ -re "Source directories searched.*$gdb_prompt $" {
+ verbose "Dir set to $subdir"
+ }
+ -re "$gdb_prompt $" {
+ perror "Dir \"$subdir\" failed."
+ }
+ }
+ }
+ -re "$gdb_prompt $" {
+ perror "Dir \"$subdir\" failed."
+ }
+ }
+ }
+ -re "$gdb_prompt $" {
+ perror "Dir \"$subdir\" failed."
+ }
+ }
+}
+
+#
+# gdb_exit -- exit the GDB, killing the target program if necessary
+#
+proc default_gdb_exit {} {
+ global GDB
+ global GDBFLAGS
+ global verbose
+ global gdb_spawn_id;
+
+ gdb_stop_suppressing_tests;
+
+ if ![info exists gdb_spawn_id] {
+ return;
+ }
+
+ verbose "Quitting $GDB $GDBFLAGS"
+
+ if { [is_remote host] && [board_info host exists fileid] } {
+ send_gdb "quit\n";
+ gdb_expect 10 {
+ -re "y or n" {
+ send_gdb "y\n";
+ exp_continue;
+ }
+ -re "DOSEXIT code" { }
+ default { }
+ }
+ }
+
+ if ![is_remote host] {
+ remote_close host;
+ }
+ unset gdb_spawn_id
+}
+
+#
+# load a file into the debugger.
+# return a -1 if anything goes wrong.
+#
+proc gdb_file_cmd { arg } {
+ global verbose
+ global loadpath
+ global loadfile
+ global GDB
+ global gdb_prompt
+ upvar timeout timeout
+
+ if [is_remote host] {
+ set arg [remote_download host $arg];
+ if { $arg == "" } {
+ error "download failed"
+ return -1;
+ }
+ }
+
+ send_gdb "file $arg\n"
+ gdb_expect 120 {
+ -re "Reading symbols from.*done.*$gdb_prompt $" {
+ verbose "\t\tLoaded $arg into the $GDB"
+ return 0
+ }
+ -re "has no symbol-table.*$gdb_prompt $" {
+ perror "$arg wasn't compiled with \"-g\""
+ return -1
+ }
+ -re "A program is being debugged already.*Kill it.*y or n. $" {
+ send_gdb "y\n"
+ verbose "\t\tKilling previous program being debugged"
+ exp_continue
+ }
+ -re "Load new symbol table from \".*\".*y or n. $" {
+ send_gdb "y\n"
+ gdb_expect 120 {
+ -re "Reading symbols from.*done.*$gdb_prompt $" {
+ verbose "\t\tLoaded $arg with new symbol table into $GDB"
+ return 0
+ }
+ timeout {
+ perror "(timeout) Couldn't load $arg, other program already loaded."
+ return -1
+ }
+ }
+ }
+ -re "No such file or directory.*$gdb_prompt $" {
+ perror "($arg) No such file or directory\n"
+ return -1
+ }
+ -re "$gdb_prompt $" {
+ perror "couldn't load $arg into $GDB."
+ return -1
+ }
+ timeout {
+ perror "couldn't load $arg into $GDB (timed out)."
+ return -1
+ }
+ eof {
+ # This is an attempt to detect a core dump, but seems not to
+ # work. Perhaps we need to match .* followed by eof, in which
+ # gdb_expect does not seem to have a way to do that.
+ perror "couldn't load $arg into $GDB (end of file)."
+ return -1
+ }
+ }
+}
+
+#
+# start gdb -- start gdb running, default procedure
+#
+# When running over NFS, particularly if running many simultaneous
+# tests on different hosts all using the same server, things can
+# get really slow. Give gdb at least 3 minutes to start up.
+#
+proc default_gdb_start { } {
+ global verbose
+ global GDB
+ global GDBFLAGS
+ global gdb_prompt
+ global timeout
+ global gdb_spawn_id;
+
+ gdb_stop_suppressing_tests;
+
+ verbose "Spawning $GDB -nw $GDBFLAGS"
+
+ if [info exists gdb_spawn_id] {
+ return 0;
+ }
+
+ if ![is_remote host] {
+ if { [which $GDB] == 0 } then {
+ perror "$GDB does not exist."
+ exit 1
+ }
+ }
+ set res [remote_spawn host "$GDB -nw $GDBFLAGS [host_info gdb_opts]"];
+ if { $res < 0 || $res == "" } {
+ perror "Spawning $GDB failed."
+ return 1;
+ }
+ gdb_expect 360 {
+ -re "\[\r\n\]$gdb_prompt $" {
+ verbose "GDB initialized."
+ }
+ -re "$gdb_prompt $" {
+ perror "GDB never initialized."
+ return -1
+ }
+ timeout {
+ perror "(timeout) GDB never initialized after 10 seconds."
+ remote_close host;
+ return -1
+ }
+ }
+ set gdb_spawn_id -1;
+ # force the height to "unlimited", so no pagers get used
+
+ send_gdb "set height 0\n"
+ gdb_expect 10 {
+ -re "$gdb_prompt $" {
+ verbose "Setting height to 0." 2
+ }
+ timeout {
+ warning "Couldn't set the height to 0"
+ }
+ }
+ # force the width to "unlimited", so no wraparound occurs
+ send_gdb "set width 0\n"
+ gdb_expect 10 {
+ -re "$gdb_prompt $" {
+ verbose "Setting width to 0." 2
+ }
+ timeout {
+ warning "Couldn't set the width to 0."
+ }
+ }
+ return 0;
+}
+
+# * For crosses, the CHILL runtime doesn't build because it can't find
+# setjmp.h, stdio.h, etc.
+# * For AIX (as of 16 Mar 95), (a) there is no language code for
+# CHILL in output_epilog in gcc/config/rs6000/rs6000.c, (b) collect2
+# does not get along with AIX's too-clever linker.
+# * On Irix5, there is a bug whereby set of bool, etc., don't get
+# TYPE_LOW_BOUND for the bool right because force_to_range_type doesn't
+# work with stub types.
+# Lots of things seem to fail on the PA, and since it's not a supported
+# chill target at the moment, don't run the chill tests.
+
+proc skip_chill_tests {} {
+ if ![info exists do_chill_tests] {
+ return 1;
+ }
+ eval set skip_chill [expr ![isnative] || [istarget "*-*-aix*"] || [istarget "*-*-irix5*"] || [istarget "*-*-irix6*"] || [istarget "alpha-*-osf*"] || [istarget "hppa*-*-*"]]
+ verbose "Skip chill tests is $skip_chill"
+ return $skip_chill
+}
+
+# skip all the tests in the file if you are not on an hppa running hpux target.
+# and you compiled with gcc
+proc skip_hp_tests {gcc_used} {
+ # if ![info exists do_hp_tests] {
+ # return 1;
+ # }
+ eval set skip_hp [expr ![isnative] || ![istarget "hppa*-*-hpux*"] || $gcc_used!=0 ]
+ verbose "Skip hp tests is $skip_hp"
+ return $skip_hp
+}
+
+proc get_compiler_info {binfile args} {
+ # Create and source the file that provides information about the compiler
+ # used to compile the test case.
+ # Compiler_type can be null or c++. If null we assume c.
+ global srcdir
+ global subdir
+ # These two come from compiler.c.
+ global signed_keyword_not_used
+ global gcc_compiled
+
+ if {![istarget "hppa*-*-hpux*"]} {
+ if { [llength $args] > 0 } {
+ if {$args == "c++"} {
+ if { [gdb_compile "${srcdir}/${subdir}/compiler.cc" "${binfile}.ci" preprocess {}] != "" } {
+ perror "Couldn't make ${binfile}.ci file"
+ return 1;
+ }
+ }
+ } else {
+ if { [gdb_compile "${srcdir}/${subdir}/compiler.c" "${binfile}.ci" preprocess {}] != "" } {
+ perror "Couldn't make ${binfile}.ci file"
+ return 1;
+ }
+ }
+ } else {
+ if { [llength $args] > 0 } {
+ if {$args == "c++"} {
+ if { [eval gdb_preprocess \
+ [list "${srcdir}/${subdir}/compiler.cc" "${binfile}.ci"] \
+ $args] != "" } {
+ perror "Couldn't make ${binfile}.ci file"
+ return 1;
+ }
+ }
+ } else {
+ if { [eval gdb_preprocess \
+ [list "${srcdir}/${subdir}/compiler.c" "${binfile}.ci"] \
+ $args] != "" } {
+ perror "Couldn't make ${binfile}.ci file"
+ return 1;
+ }
+ }
+ }
+
+ source ${binfile}.ci
+ return 0;
+}
+
+proc gdb_preprocess {source dest args} {
+ global CC_FOR_TARGET
+ global CXX_FOR_TARGET
+
+ if { [llength $args] == 0 } {
+ set which_compiler "c"
+ } else {
+ if { $args =="c++" } {
+ set which_compiler "c++"
+ } else {
+ perror "Unknown compiler type supplied to gdb_preprocess"
+ return 1;
+ }
+ }
+
+ if [info exists CC_FOR_TARGET] {
+ if { $which_compiler == "c"} {
+ set compiler $CC_FOR_TARGET;
+ }
+ }
+
+ if [info exists CXX_FOR_TARGET] {
+ if { $which_compiler == "c++"} {
+ set compiler $CXX_FOR_TARGET;
+ }
+ }
+
+ if { ![info exists compiler] } {
+ if { $which_compiler == "c" } {
+ if {[info exists CC]} {
+ set compiler $CC;
+ }
+ }
+ if { $which_compiler == "c++" } {
+ if {[info exists CXX]} {
+ set compiler $CXX;
+ }
+ }
+ if {![info exists compiler]} {
+ set compiler [board_info [target_info name] compiler];
+ if { $compiler == "" } {
+ puts "default_target_compile: No compiler to compile with";
+ return "default_target_compile: No compiler to compile with";
+ }
+ }
+ }
+
+ set cmdline "$compiler -E $source > $dest"
+
+ verbose "Invoking $compiler -E $source > $dest"
+ verbose -log "Executing on local host: $cmdline" 2
+ set status [catch "exec ${cmdline}" exec_output]
+
+ set result [prune_warnings $exec_output]
+ regsub "\[\r\n\]*$" "$result" "" result;
+ regsub "^\[\r\n\]*" "$result" "" result;
+ if { $result != "" } {
+ clone_output "gdb compile failed, $result"
+ }
+ return $result;
+}
+
+proc gdb_compile {source dest type options} {
+ global GDB_TESTCASE_OPTIONS;
+
+ if [target_info exists gdb_stub] {
+ set options2 { "additional_flags=-Dusestubs" }
+ lappend options "libs=[target_info gdb_stub]";
+ set options [concat $options2 $options]
+ }
+ if [target_info exists is_vxworks] {
+ set options2 { "additional_flags=-Dvxworks" }
+ lappend options "libs=[target_info gdb_stub]";
+ set options [concat $options2 $options]
+ }
+ if [info exists GDB_TESTCASE_OPTIONS] {
+ lappend options "additional_flags=$GDB_TESTCASE_OPTIONS";
+ }
+ verbose "options are $options"
+ verbose "source is $source $dest $type $options"
+
+ set result [target_compile $source $dest $type $options];
+ regsub "\[\r\n\]*$" "$result" "" result;
+ regsub "^\[\r\n\]*" "$result" "" result;
+ if { $result != "" } {
+ clone_output "gdb compile failed, $result"
+ }
+ return $result;
+}
+
+proc send_gdb { string } {
+ global suppress_flag;
+ if { $suppress_flag } {
+ return "suppressed";
+ }
+ return [remote_send host "$string"];
+}
+
+#
+#
+
+proc gdb_expect { args } {
+ if { [llength $args] == 2 && [lindex $args 0] != "-re" } {
+ set gtimeout [lindex $args 0];
+ set expcode [list [lindex $args 1]];
+ } else {
+ upvar timeout timeout;
+
+ set expcode $args;
+ if [target_info exists gdb,timeout] {
+ if [info exists timeout] {
+ if { $timeout < [target_info gdb,timeout] } {
+ set gtimeout [target_info gdb,timeout];
+ } else {
+ set gtimeout $timeout;
+ }
+ } else {
+ set gtimeout [target_info gdb,timeout];
+ }
+ }
+
+ if ![info exists gtimeout] {
+ global timeout;
+ if [info exists timeout] {
+ set gtimeout $timeout;
+ } else {
+ # Eeeeew.
+ set gtimeout 60;
+ }
+ }
+ }
+ global suppress_flag;
+ global remote_suppress_flag;
+ if [info exists remote_suppress_flag] {
+ set old_val $remote_suppress_flag;
+ }
+ if [info exists suppress_flag] {
+ if { $suppress_flag } {
+ set remote_suppress_flag 1;
+ }
+ }
+ set code [catch {uplevel remote_expect host $gtimeout $expcode} string];
+ if [info exists old_val] {
+ set remote_suppress_flag $old_val;
+ } else {
+ if [info exists remote_suppress_flag] {
+ unset remote_suppress_flag;
+ }
+ }
+
+ if {$code == 1} {
+ global errorInfo errorCode;
+
+ return -code error -errorinfo $errorInfo -errorcode $errorCode $string
+ } elseif {$code == 2} {
+ return -code return $string
+ } elseif {$code == 3} {
+ return
+ } elseif {$code > 4} {
+ return -code $code $string
+ }
+}
+
+proc gdb_suppress_entire_file { reason } {
+ global suppress_flag;
+
+ warning "$reason\n";
+ set suppress_flag -1;
+}
+
+#
+# Set suppress_flag, which will cause all subsequent calls to send_gdb and
+# gdb_expect to fail immediately (until the next call to
+# gdb_stop_suppressing_tests).
+#
+proc gdb_suppress_tests { args } {
+ global suppress_flag;
+
+ return; # fnf - disable pending review of results where
+ # testsuite ran better without this
+ incr suppress_flag;
+
+ if { $suppress_flag == 1 } {
+ if { [llength $args] > 0 } {
+ warning "[lindex $args 0]\n";
+ } else {
+ warning "Because of previous failure, all subsequent tests in this group will automatically fail.\n";
+ }
+ }
+}
+
+#
+# Clear suppress_flag.
+#
+proc gdb_stop_suppressing_tests { } {
+ global suppress_flag;
+
+ if [info exists suppress_flag] {
+ if { $suppress_flag > 0 } {
+ set suppress_flag 0;
+ clone_output "Tests restarted.\n";
+ }
+ } else {
+ set suppress_flag 0;
+ }
+}
+
+proc gdb_clear_suppressed { } {
+ global suppress_flag;
+
+ set suppress_flag 0;
+}
+
+proc gdb_start { } {
+ default_gdb_start
+}
+
+proc gdb_exit { } {
+ catch default_gdb_exit
+}
+
+#
+# gdb_load -- load a file into the debugger.
+# return a -1 if anything goes wrong.
+#
+proc gdb_load { arg } {
+ return [gdb_file_cmd $arg]
+}
+
+proc gdb_continue { function } {
+ global decimal
+
+ return [gdb_test "continue" ".*Breakpoint $decimal, $function .*" "continue to $function"];
+}
+
+proc default_gdb_init { args } {
+ gdb_clear_suppressed;
+
+ # Uh, this is lame. Really, really, really lame. But there's this *one*
+ # testcase that will fail in random places if we don't increase this.
+ match_max -d 20000
+
+ # We want to add the name of the TCL testcase to the PASS/FAIL messages.
+ if { [llength $args] > 0 } {
+ global pf_prefix
+
+ set file [lindex $args 0];
+
+ set pf_prefix "[file tail [file dirname $file]]/[file tail $file]:";
+ }
+ global gdb_prompt;
+ if [target_info exists gdb_prompt] {
+ set gdb_prompt [target_info gdb_prompt];
+ } else {
+ set gdb_prompt "\\(gdb\\)"
+ }
+}
+
+proc gdb_init { args } {
+ return [eval default_gdb_init $args];
+}
+
+proc gdb_finish { } {
+ gdb_exit;
+}
+
+global debug_format
+
+# Run the gdb command "info source" and extract the debugging format
+# information from the output and save it in debug_format.
+
+proc get_debug_format { } {
+ global gdb_prompt
+ global verbose
+ global expect_out
+ global debug_format
+
+ set debug_format "unknown"
+ send_gdb "info source\n"
+ gdb_expect 10 {
+ -re "Compiled with (.*) debugging format.\r\n$gdb_prompt $" {
+ set debug_format $expect_out(1,string)
+ verbose "debug format is $debug_format"
+ return 1;
+ }
+ -re "No current source file.\r\n$gdb_prompt $" {
+ perror "get_debug_format used when no current source file"
+ return 0;
+ }
+ -re "$gdb_prompt $" {
+ warning "couldn't check debug format (no valid response)."
+ return 1;
+ }
+ timeout {
+ warning "couldn't check debug format (timed out)."
+ return 1;
+ }
+ }
+}
+
+# Like setup_xfail, but takes the name of a debug format (DWARF 1,
+# COFF, stabs, etc). If that format matches the format that the
+# current test was compiled with, then the next test is expected to
+# fail for any target. Returns 1 if the next test or set of tests is
+# expected to fail, 0 otherwise (or if it is unknown). Must have
+# previously called get_debug_format.
+
+proc setup_xfail_format { format } {
+ global debug_format
+
+ if [string match $debug_format $format] then {
+ setup_xfail "*-*-*"
+ return 1;
+ }
+ return 0
+}
+
+proc gdb_step_for_stub { } {
+ global gdb_prompt;
+
+ if ![target_info exists gdb,use_breakpoint_for_stub] {
+ if [target_info exists gdb_stub_step_command] {
+ set command [target_info gdb_stub_step_command];
+ } else {
+ set command "step";
+ }
+ send_gdb "${command}\n";
+ set tries 0;
+ gdb_expect 60 {
+ -re "(main.* at |.*in .*start).*$gdb_prompt" {
+ return;
+ }
+ -re ".*$gdb_prompt" {
+ incr tries;
+ if { $tries == 5 } {
+ fail "stepping out of breakpoint function";
+ return;
+ }
+ send_gdb "${command}\n";
+ exp_continue;
+ }
+ default {
+ fail "stepping out of breakpoint function";
+ return;
+ }
+ }
+ }
+ send_gdb "where\n";
+ gdb_expect {
+ -re "main\[^\r\n\]*at \(\[^:]+\):\(\[0-9\]+\)" {
+ set file $expect_out(1,string);
+ set linenum [expr $expect_out(2,string) + 1];
+ set breakplace "${file}:${linenum}";
+ }
+ default {}
+ }
+ send_gdb "break ${breakplace}\n";
+ gdb_expect 60 {
+ -re "Breakpoint (\[0-9\]+) at.*$gdb_prompt" {
+ set breakpoint $expect_out(1,string);
+ }
+ -re "Breakpoint (\[0-9\]+): file.*$gdb_prompt" {
+ set breakpoint $expect_out(1,string);
+ }
+ default {}
+ }
+ send_gdb "continue\n";
+ gdb_expect 60 {
+ -re "Breakpoint ${breakpoint},.*$gdb_prompt" {
+ gdb_test "delete $breakpoint" ".*" "";
+ return;
+ }
+ default {}
+ }
+}
+
+### gdb_get_line_number TEXT [FILE]
+###
+### Search the source file FILE, and return the line number of a line
+### containing TEXT. Use this function instead of hard-coding line
+### numbers into your test script.
+###
+### Specifically, this function uses GDB's "search" command to search
+### FILE for the first line containing TEXT, and returns its line
+### number. Thus, FILE must be a source file, compiled into the
+### executable you are running. If omitted, FILE defaults to the
+### value of the global variable `srcfile'; most test scripts set
+### `srcfile' appropriately at the top anyway.
+###
+### Use this function to keep your test scripts independent of the
+### exact line numbering of the source file. Don't write:
+###
+### send_gdb "break 20"
+###
+### This means that if anyone ever edits your test's source file,
+### your test could break. Instead, put a comment like this on the
+### source file line you want to break at:
+###
+### /* breakpoint spot: frotz.exp: test name */
+###
+### and then write, in your test script (which we assume is named
+### frotz.exp):
+###
+### send_gdb "break [gdb_get_line_number "frotz.exp: test name"]\n"
+###
+### (Yes, Tcl knows how to handle the nested quotes and brackets.
+### Try this:
+### $ tclsh
+### % puts "foo [lindex "bar baz" 1]"
+### foo baz
+### %
+### Tcl is quite clever, for a little stringy language.)
+
+proc gdb_get_line_number {text {file /omitted/}} {
+ global gdb_prompt;
+ global srcfile;
+
+ if {! [string compare $file /omitted/]} {
+ set file $srcfile
+ }
+
+ set result -1;
+ gdb_test "list ${file}:1,1" ".*" ""
+ send_gdb "search ${text}\n"
+ gdb_expect {
+ -re "\[\r\n\]+(\[0-9\]+)\[ \t\].*${text}.*$gdb_prompt $" {
+ set result $expect_out(1,string)
+ }
+ -re ".*$gdb_prompt $" {
+ fail "find line number containing \"${text}\""
+ }
+ timeout {
+ fail "find line number containing \"${text}\" (timeout)"
+ }
+ }
+ return $result;
+}
+
+
diff --git a/gdb/testsuite/lib/trace-support.exp b/gdb/testsuite/lib/trace-support.exp
new file mode 100644
index 00000000000..4765791b817
--- /dev/null
+++ b/gdb/testsuite/lib/trace-support.exp
@@ -0,0 +1,307 @@
+# Copyright (C) 1998 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+
+#
+# Support procedures for trace testing
+#
+
+
+#
+# Procedure: gdb_target_supports_trace
+# Returns true if GDB is connected to a target that supports tracing.
+# Allows tests to abort early if not running on a trace-aware target.
+#
+
+proc gdb_target_supports_trace { } {
+ global gdb_prompt
+
+ send_gdb "tstatus\n"
+ gdb_expect {
+ -re "\[Tt\]race can only be run on.*$gdb_prompt $" {
+ return 0
+ }
+ -re "\[Tt\]race can not be run on.*$gdb_prompt $" {
+ return 0
+ }
+ -re "\[Tt\]arget does not support.*$gdb_prompt $" {
+ return 0
+ }
+ -re ".*\[Ee\]rror.*$gdb_prompt $" {
+ return 0
+ }
+ -re ".*\[Ww\]arning.*$gdb_prompt $" {
+ return 0
+ }
+ -re ".*$gdb_prompt $" {
+ return 1
+ }
+ timeout {
+ return 0
+ }
+ }
+}
+
+
+#
+# Procedure: gdb_delete_tracepoints
+# Many of the tests depend on setting tracepoints at various places and
+# running until that tracepoint is reached. At times, we want to start
+# with a clean slate with respect to tracepoints, so this utility proc
+# lets us do this without duplicating this code everywhere.
+#
+
+proc gdb_delete_tracepoints {} {
+ global gdb_prompt
+
+ send_gdb "delete tracepoints\n"
+ gdb_expect 30 {
+ -re "Delete all tracepoints.*y or n.*$" {
+ send_gdb "y\n";
+ exp_continue
+ }
+ -re ".*$gdb_prompt $" { # This happens if there were no tracepoints }
+ timeout {
+ perror "Delete all tracepoints in delete_tracepoints (timeout)"
+ return
+ }
+ }
+ send_gdb "info tracepoints\n"
+ gdb_expect 30 {
+ -re "No tracepoints.*$gdb_prompt $" {}
+ -re "$gdb_prompt $" { perror "tracepoints not deleted" ; return }
+ timeout { perror "info tracepoints (timeout)" ; return }
+ }
+}
+
+#
+# Procedure: gdb_trace_setactions
+# Define actions for a tracepoint.
+# Arguments:
+# testname -- identifying string for pass/fail output
+# tracepoint -- to which tracepoint do these actions apply? (optional)
+# args -- list of actions to be defined.
+# Returns:
+# zero -- success
+# non-zero -- failure
+
+proc gdb_trace_setactions { testname tracepoint args } {
+ global gdb_prompt;
+
+ set state 0;
+ set passfail "pass";
+ send_gdb "actions $tracepoint\n";
+ set expected_result "";
+ gdb_expect 5 {
+ -re "No tracepoint number .*$gdb_prompt $" {
+ fail $testname
+ return 1;
+ }
+ -re "Enter actions for tracepoint $tracepoint.*>" {
+ if { [llength $args] > 0 } {
+ set lastcommand "[lindex $args $state]";
+ send_gdb "[lindex $args $state]\n";
+ incr state;
+ set expected_result [lindex $args $state];
+ incr state;
+ } else {
+ send_gdb "end\n";
+ }
+ exp_continue;
+ }
+ -re "\(.*\)\[\r\n\]+\[ \t]*> $" {
+ if { $expected_result != "" } {
+ regsub "^\[^\r\n\]+\[\r\n\]+" "$expect_out(1,string)" "" out;
+ if ![regexp $expected_result $out] {
+ set passfail "fail";
+ }
+ set expected_result "";
+ }
+ if { $state < [llength $args] } {
+ send_gdb "[lindex $args $state]\n";
+ incr state;
+ set expected_result [lindex $args $state];
+ incr state;
+ } else {
+ send_gdb "end\n";
+ set expected_result "";
+ }
+ exp_continue;
+ }
+ -re "\(.*\)$gdb_prompt $" {
+ if { $expected_result != "" } {
+ if ![regexp $expected_result $expect_out(1,string)] {
+ set passfail "fail";
+ }
+ set expected_result "";
+ }
+ if { [llength $args] < $state } {
+ set passfail "fail";
+ }
+ }
+ default {
+ set passfail "fail";
+ }
+ }
+ if { $testname != "" } {
+ $passfail $testname;
+ }
+ if { $passfail == "pass" } then {
+ return 0;
+ } else {
+ return 1;
+ }
+}
+
+#
+# Procedure: gdb_tfind_test
+# Find a specified trace frame.
+# Arguments:
+# testname -- identifying string for pass/fail output
+# tfind_arg -- frame (line, PC, etc.) identifier
+# exp_res -- Expected result of frame test
+# args -- Test expression
+# Returns:
+# zero -- success
+# non-zero -- failure
+#
+
+proc gdb_tfind_test { testname tfind_arg exp_res args } {
+ global gdb_prompt;
+
+ if { "$args" != "" } {
+ set expr "$exp_res";
+ set exp_res "$args";
+ } else {
+ set expr "(int) \$trace_frame";
+ }
+ set passfail "fail";
+
+ gdb_test "tfind $tfind_arg" "" ""
+ send_gdb "printf \"x \%d x\\n\", $expr\n";
+ gdb_expect 10 {
+ -re "x (-*\[0-9\]+) x" {
+ if { $expect_out(1,string) == $exp_res } {
+ set passfail "pass";
+ }
+ exp_continue;
+ }
+ -re "$gdb_prompt $" { }
+ }
+ $passfail "$testname";
+ if { $passfail == "pass" } then {
+ return 0;
+ } else {
+ return 1;
+ }
+}
+
+#
+# Procedure: gdb_readexpr
+# Arguments:
+# gdb_expr -- the expression whose value is desired
+# Returns:
+# the value of gdb_expr, as evaluated by gdb.
+# [FIXME: returns -1 on error, which is sometimes a legit value]
+#
+
+proc gdb_readexpr { gdb_expr } {
+ global gdb_prompt;
+
+ set result -1;
+ send_gdb "print $gdb_expr\n"
+ gdb_expect 5 {
+ -re "\[$\].*= (\[0-9\]+).*$gdb_prompt $" {
+ set result $expect_out(1,string);
+ }
+ -re "$gdb_prompt $" { }
+ default { }
+ }
+ return $result;
+}
+
+#
+# Procedure: gdb_gettpnum
+# Arguments:
+# tracepoint (optional): if supplied, set a tracepoint here.
+# Returns:
+# the tracepoint ID of the most recently set tracepoint.
+#
+
+proc gdb_gettpnum { tracepoint } {
+ global gdb_prompt;
+
+ if { $tracepoint != "" } {
+ gdb_test "trace $tracepoint" "" ""
+ }
+ return [gdb_readexpr "\$tpnum"];
+}
+
+
+#
+# Procedure: gdb_find_function_baseline
+# Arguments:
+# func_name -- name of source function
+# Returns:
+# Sourcefile line of function definition (open curly brace),
+# or -1 on failure. Caller must check return value.
+# Note:
+# Works only for open curly brace at beginning of source line!
+#
+
+proc gdb_find_function_baseline { func_name } {
+ global gdb_prompt;
+
+ set baseline -1;
+
+ send_gdb "list $func_name\n"
+# gdb_expect {
+# -re "\[\r\n\]\[\{\].*$gdb_prompt $" {
+# set baseline 1
+# }
+# }
+}
+
+#
+# Procedure: gdb_find_function_baseline
+# Arguments:
+# filename: name of source file of desired function.
+# Returns:
+# Sourcefile line of function definition (open curly brace),
+# or -1 on failure. Caller must check return value.
+# Note:
+# Works only for open curly brace at beginning of source line!
+#
+
+proc gdb_find_recursion_test_baseline { filename } {
+ global gdb_prompt;
+
+ set baseline -1;
+
+ gdb_test "list $filename:1" "" ""
+ send_gdb "search gdb_recursion_test line 0\n"
+ gdb_expect {
+ -re "(\[0-9\]+)\[\t \]+\{.*line 0.*$gdb_prompt $" {
+ set baseline $expect_out(1,string);
+ }
+ -re "$gdb_prompt $" { }
+ default { }
+ }
+ return $baseline;
+}
diff --git a/gdb/thread.c b/gdb/thread.c
new file mode 100644
index 00000000000..6a7ab092d7c
--- /dev/null
+++ b/gdb/thread.c
@@ -0,0 +1,721 @@
+/* Multi-process/thread control for GDB, the GNU debugger.
+ Copyright 1986, 1987, 1988, 1993, 1998
+
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "symtab.h"
+#include "frame.h"
+#include "inferior.h"
+#include "environ.h"
+#include "value.h"
+#include "target.h"
+#include "gdbthread.h"
+#include "command.h"
+#include "gdbcmd.h"
+
+#include <ctype.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 */
+ CORE_ADDR prev_pc; /* State from wait_for_inferior */
+ CORE_ADDR prev_func_start;
+ char *prev_func_name;
+ struct breakpoint *step_resume_breakpoint;
+ struct breakpoint *through_sigtramp_breakpoint;
+ CORE_ADDR step_range_start;
+ CORE_ADDR step_range_end;
+ CORE_ADDR step_frame_address;
+ int trap_expected;
+ int handling_longjmp;
+ int another_trap;
+
+ /* This is set TRUE when a catchpoint of a shared library event
+ triggers. Since we don't wish to leave the inferior in the
+ solib hook when we report the event, we step the inferior
+ back to user code before stopping and reporting the event.
+ */
+ int stepping_through_solib_after_catch;
+
+ /* When stepping_through_solib_after_catch is TRUE, this is a
+ list of the catchpoints that should be reported as triggering
+ when we finally do stop stepping.
+ */
+ bpstat stepping_through_solib_catchpoints;
+
+ /* This is set to TRUE when this thread is in a signal handler
+ trampoline and we're single-stepping through it */
+ int stepping_through_sigtramp;
+
+};
+
+/* Prototypes for exported functions. */
+
+void _initialize_thread PARAMS ((void));
+
+/* Prototypes for local functions. */
+
+#if !defined(FIND_NEW_THREADS)
+#define FIND_NEW_THREADS target_find_new_threads
+#endif
+
+static struct thread_info *thread_list = NULL;
+static int highest_thread_num;
+
+static struct thread_info * find_thread_id PARAMS ((int num));
+
+static void thread_command PARAMS ((char * tidstr, int from_tty));
+static void thread_apply_all_command PARAMS ((char *, int));
+static int thread_alive PARAMS ((struct thread_info *));
+static void info_threads_command PARAMS ((char *, int));
+static void thread_apply_command PARAMS ((char *, int));
+static void restore_current_thread PARAMS ((int));
+static void switch_to_thread PARAMS ((int pid));
+static void prune_threads PARAMS ((void));
+
+/* If the host has threads, the host machine definition may set this
+ macro. But, for remote thread debugging, it gets more complex and
+ setting macros does not bind to the various target dependent
+ methods well. So, we use the vector target_thread_functions */
+
+static struct target_thread_vector *target_thread_functions;
+
+int
+target_find_new_threads ()
+{
+ int retval = 0;
+ if (target_thread_functions &&
+ target_thread_functions->find_new_threads)
+ retval = (*(target_thread_functions->find_new_threads)) ();
+ return retval; /* no support */
+}
+
+
+int
+target_get_thread_info PARAMS ((gdb_threadref * ref,
+ int selection, /* FIXME: Selection */
+ struct gdb_ext_thread_info * info));
+
+int
+target_get_thread_info (ref, selection, info)
+
+ gdb_threadref *ref;
+ int selection;
+ /* FIXME: Selection */
+ struct gdb_ext_thread_info *info;
+
+{
+ int retval = 0;
+ if (target_thread_functions
+ && target_thread_functions->get_thread_info)
+ retval = (*(target_thread_functions->get_thread_info)) (ref, selection, info);
+ return retval;
+}
+
+
+/* It is possible that these bind and unbinf functions implement a
+ stack the interface allows it, but its not implemented that way
+ */
+
+
+void
+bind_target_thread_vector (vec)
+ struct target_thread_vector *vec;
+{
+ target_thread_functions = vec;
+}
+
+struct target_thread_vector *
+unbind_target_thread_vector ()
+{
+ struct target_thread_vector *retval;
+ retval = target_thread_functions;
+ target_thread_functions = 0;
+ return retval;
+} /* unbind_target_thread-vector */
+
+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->prev_pc = 0;
+ tp->prev_func_start = 0;
+ tp->prev_func_name = NULL;
+ tp->step_range_start = 0;
+ tp->step_range_end = 0;
+ tp->step_frame_address =0;
+ tp->step_resume_breakpoint = 0;
+ tp->through_sigtramp_breakpoint = 0;
+ tp->handling_longjmp = 0;
+ tp->trap_expected = 0;
+ tp->another_trap = 0;
+ tp->stepping_through_solib_after_catch = 0;
+ tp->stepping_through_solib_catchpoints = NULL;
+ tp->stepping_through_sigtramp = 0;
+ tp->next = thread_list;
+ thread_list = tp;
+}
+
+void
+delete_thread (pid)
+ int pid;
+{
+ struct thread_info *tp, *tpprev;
+
+ tpprev = NULL;
+
+ for (tp = thread_list; tp; tpprev = tp, tp = tp->next)
+ if (tp->pid == pid)
+ break;
+
+ if (!tp)
+ return;
+
+ if (tpprev)
+ tpprev->next = tp->next;
+ else
+ thread_list = tp->next;
+
+ free (tp);
+
+ return;
+}
+
+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
+thread_id_to_pid (num)
+ int num;
+{
+ struct thread_info *thread = find_thread_id (num);
+ if (thread)
+ return thread->pid;
+ else
+ return -1;
+}
+
+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 */
+}
+
+/* Load infrun state for the thread PID. */
+
+void load_infrun_state (pid, prev_pc, prev_func_start, prev_func_name,
+ trap_expected, step_resume_breakpoint,
+ through_sigtramp_breakpoint, step_range_start,
+ step_range_end, step_frame_address,
+ handling_longjmp, another_trap,
+ stepping_through_solib_after_catch,
+ stepping_through_solib_catchpoints,
+ stepping_through_sigtramp)
+ int pid;
+ CORE_ADDR *prev_pc;
+ CORE_ADDR *prev_func_start;
+ char **prev_func_name;
+ int *trap_expected;
+ struct breakpoint **step_resume_breakpoint;
+ struct breakpoint **through_sigtramp_breakpoint;
+ CORE_ADDR *step_range_start;
+ CORE_ADDR *step_range_end;
+ CORE_ADDR *step_frame_address;
+ int *handling_longjmp;
+ int *another_trap;
+ int * stepping_through_solib_after_catch;
+ bpstat * stepping_through_solib_catchpoints;
+ int * stepping_through_sigtramp;
+{
+ struct thread_info *tp;
+
+ /* If we can't find the thread, then we're debugging a single threaded
+ process. No need to do anything in that case. */
+ tp = find_thread_id (pid_to_thread_id (pid));
+ if (tp == NULL)
+ return;
+
+ *prev_pc = tp->prev_pc;
+ *prev_func_start = tp->prev_func_start;
+ *prev_func_name = tp->prev_func_name;
+ *step_resume_breakpoint = tp->step_resume_breakpoint;
+ *step_range_start = tp->step_range_start;
+ *step_range_end = tp->step_range_end;
+ *step_frame_address = tp->step_frame_address;
+ *through_sigtramp_breakpoint = tp->through_sigtramp_breakpoint;
+ *handling_longjmp = tp->handling_longjmp;
+ *trap_expected = tp->trap_expected;
+ *another_trap = tp->another_trap;
+ *stepping_through_solib_after_catch = tp->stepping_through_solib_after_catch;
+ *stepping_through_solib_catchpoints = tp->stepping_through_solib_catchpoints;
+ *stepping_through_sigtramp = tp->stepping_through_sigtramp;
+}
+
+/* Save infrun state for the thread PID. */
+
+void save_infrun_state (pid, prev_pc, prev_func_start, prev_func_name,
+ trap_expected, step_resume_breakpoint,
+ through_sigtramp_breakpoint, step_range_start,
+ step_range_end, step_frame_address,
+ handling_longjmp, another_trap,
+ stepping_through_solib_after_catch,
+ stepping_through_solib_catchpoints,
+ stepping_through_sigtramp)
+ int pid;
+ CORE_ADDR prev_pc;
+ CORE_ADDR prev_func_start;
+ char *prev_func_name;
+ int trap_expected;
+ struct breakpoint *step_resume_breakpoint;
+ struct breakpoint *through_sigtramp_breakpoint;
+ CORE_ADDR step_range_start;
+ CORE_ADDR step_range_end;
+ CORE_ADDR step_frame_address;
+ int handling_longjmp;
+ int another_trap;
+ int stepping_through_solib_after_catch;
+ bpstat stepping_through_solib_catchpoints;
+ int stepping_through_sigtramp;
+{
+ struct thread_info *tp;
+
+ /* If we can't find the thread, then we're debugging a single-threaded
+ process. Nothing to do in that case. */
+ tp = find_thread_id (pid_to_thread_id (pid));
+ if (tp == NULL)
+ return;
+
+ tp->prev_pc = prev_pc;
+ tp->prev_func_start = prev_func_start;
+ tp->prev_func_name = prev_func_name;
+ tp->step_resume_breakpoint = step_resume_breakpoint;
+ tp->step_range_start = step_range_start;
+ tp->step_range_end = step_range_end;
+ tp->step_frame_address = step_frame_address;
+ tp->through_sigtramp_breakpoint = through_sigtramp_breakpoint;
+ tp->handling_longjmp = handling_longjmp;
+ tp->trap_expected = trap_expected;
+ tp->another_trap = another_trap;
+ tp->stepping_through_solib_after_catch = stepping_through_solib_after_catch;
+ tp->stepping_through_solib_catchpoints = stepping_through_solib_catchpoints;
+ tp->stepping_through_sigtramp = stepping_through_sigtramp;
+}
+
+/* Return true if TP is an active thread. */
+static int
+thread_alive (tp)
+ struct thread_info *tp;
+{
+ if (tp->pid == -1)
+ return 0;
+ if (! target_thread_alive (tp->pid))
+ {
+ tp->pid = -1; /* Mark it as dead */
+ return 0;
+ }
+ return 1;
+}
+
+static void
+prune_threads ()
+{
+ struct thread_info *tp, *tpprev, *next;
+
+ tpprev = 0;
+ for (tp = thread_list; tp; tp = next)
+ {
+ next = tp->next;
+ if (!thread_alive (tp))
+ {
+ if (tpprev)
+ tpprev->next = next;
+ else
+ thread_list = next;
+ free (tp);
+ }
+ else
+ tpprev = tp;
+ }
+}
+
+/* Print information about currently known threads
+ *
+ * Note: this has the drawback that it _really_ switches
+ * threads, which frees the frame cache. A no-side
+ * effects info-threads command would be nicer.
+ */
+
+static void
+info_threads_command (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ struct thread_info *tp;
+ int current_pid;
+ struct frame_info *cur_frame;
+ int saved_frame_level = selected_frame_level;
+ int counter;
+
+ /* Avoid coredumps which would happen if we tried to access a NULL
+ selected_frame. */
+ if (!target_has_stack) error ("No stack.");
+
+ prune_threads ();
+#if defined(FIND_NEW_THREADS)
+ FIND_NEW_THREADS ();
+#endif
+ current_pid = inferior_pid;
+ for (tp = thread_list; tp; tp = tp->next)
+ {
+ if (tp->pid == current_pid)
+ printf_filtered ("* ");
+ else
+ printf_filtered (" ");
+
+#ifdef HPUXHPPA
+ printf_filtered ("%d %s ", tp->num, target_tid_to_str (tp->pid));
+#else
+ printf_filtered ("%d %s ", tp->num, target_pid_to_str (tp->pid));
+#endif
+ switch_to_thread (tp->pid);
+ if (selected_frame)
+ print_only_stack_frame (selected_frame, -1, 0);
+ else
+ printf_filtered ("[No stack.]\n");
+ }
+
+ switch_to_thread (current_pid);
+
+ /* Code below copied from "up_silently_base" in "stack.c".
+ * It restores the frame set by the user before the "info threads"
+ * command. We have finished the info-threads display by switching
+ * back to the current thread. That switch has put us at the top
+ * of the stack (leaf frame).
+ */
+ counter = saved_frame_level;
+ cur_frame = find_relative_frame(selected_frame, &counter);
+ if (counter != 0)
+ {
+ /* Ooops, can't restore, tell user where we are. */
+ warning ("Couldn't restore frame in current thread, at frame 0");
+ print_stack_frame (selected_frame, -1, 0);
+ }
+ else
+ {
+ select_frame(cur_frame, saved_frame_level);
+ }
+
+ /* re-show current frame. */
+ show_stack_frame(cur_frame);
+}
+
+/* Switch from one thread to another. */
+
+static void
+switch_to_thread (pid)
+ int pid;
+{
+ if (pid == inferior_pid)
+ return;
+
+ inferior_pid = pid;
+ flush_cached_frames ();
+ registers_changed ();
+ stop_pc = read_pc();
+ select_frame (get_current_frame (), 0);
+}
+
+static void
+restore_current_thread (pid)
+ int pid;
+{
+ if (pid != inferior_pid)
+ {
+ switch_to_thread (pid);
+ print_stack_frame( get_current_frame(), 0, -1);
+ }
+}
+
+/* Apply a GDB command to a list of threads. List syntax is a whitespace
+ seperated list of numbers, or ranges, or the keyword `all'. Ranges consist
+ of two numbers seperated by a hyphen. Examples:
+
+ thread apply 1 2 7 4 backtrace Apply backtrace cmd to threads 1,2,7,4
+ thread apply 2-7 9 p foo(1) Apply p foo(1) cmd to threads 2->7 & 9
+ thread apply all p x/i $pc Apply x/i $pc cmd to all threads
+*/
+
+static void
+thread_apply_all_command (cmd, from_tty)
+ char *cmd;
+ int from_tty;
+{
+ struct thread_info *tp;
+ struct cleanup *old_chain;
+
+ if (cmd == NULL || *cmd == '\000')
+ error ("Please specify a command following the thread ID list");
+
+ old_chain = make_cleanup ((make_cleanup_func) restore_current_thread,
+ (void *) inferior_pid);
+
+ for (tp = thread_list; tp; tp = tp->next)
+ if (thread_alive (tp))
+ {
+ switch_to_thread (tp->pid);
+#ifdef HPUXHPPA
+ printf_filtered ("\nThread %d (%s):\n",
+ tp->num,
+ target_tid_to_str (inferior_pid));
+#else
+ printf_filtered ("\nThread %d (%s):\n", tp->num,
+ target_pid_to_str (inferior_pid));
+#endif
+ execute_command (cmd, from_tty);
+ }
+}
+
+static void
+thread_apply_command (tidlist, from_tty)
+ char *tidlist;
+ int from_tty;
+{
+ char *cmd;
+ char *p;
+ struct cleanup *old_chain;
+
+ if (tidlist == NULL || *tidlist == '\000')
+ error ("Please specify a thread ID list");
+
+ for (cmd = tidlist; *cmd != '\000' && !isalpha(*cmd); cmd++);
+
+ if (*cmd == '\000')
+ error ("Please specify a command following the thread ID list");
+
+ old_chain = make_cleanup ((make_cleanup_func) restore_current_thread,
+ (void *) inferior_pid);
+
+ while (tidlist < cmd)
+ {
+ struct thread_info *tp;
+ int start, end;
+
+ start = strtol (tidlist, &p, 10);
+ if (p == tidlist)
+ error ("Error parsing %s", tidlist);
+ tidlist = p;
+
+ while (*tidlist == ' ' || *tidlist == '\t')
+ tidlist++;
+
+ if (*tidlist == '-') /* Got a range of IDs? */
+ {
+ tidlist++; /* Skip the - */
+ end = strtol (tidlist, &p, 10);
+ if (p == tidlist)
+ error ("Error parsing %s", tidlist);
+ tidlist = p;
+
+ while (*tidlist == ' ' || *tidlist == '\t')
+ tidlist++;
+ }
+ else
+ end = start;
+
+ for (; start <= end; start++)
+ {
+ tp = find_thread_id (start);
+
+ if (!tp)
+ warning ("Unknown thread %d.", start);
+ else if (!thread_alive (tp))
+ warning ("Thread %d has terminated.", start);
+ else
+ {
+ switch_to_thread (tp->pid);
+#ifdef HPUXHPPA
+ printf_filtered ("\nThread %d (%s):\n", tp->num,
+ target_tid_to_str (inferior_pid));
+#else
+ printf_filtered ("\nThread %d (%s):\n", tp->num,
+ target_pid_to_str (inferior_pid));
+#endif
+ execute_command (cmd, from_tty);
+ }
+ }
+ }
+}
+
+/* Switch to the specified thread. Will dispatch off to thread_apply_command
+ if prefix of arg is `apply'. */
+
+static void
+thread_command (tidstr, from_tty)
+ char *tidstr;
+ int from_tty;
+{
+ int num;
+ struct thread_info *tp;
+
+ if (!tidstr)
+ {
+ /* Don't generate an error, just say which thread is current. */
+ if (target_has_stack)
+ printf_filtered ("[Current thread is %d (%s)]\n",
+ pid_to_thread_id(inferior_pid),
+#if defined(HPUXHPPA)
+ target_tid_to_str(inferior_pid)
+#else
+ target_pid_to_str(inferior_pid)
+#endif
+ );
+ else
+ error ("No stack.");
+ return;
+ }
+ 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);
+
+ if (!thread_alive (tp))
+ error ("Thread ID %d has terminated.\n", num);
+
+ switch_to_thread (tp->pid);
+
+ if (context_hook)
+ context_hook (num);
+
+ printf_filtered ("[Switching to thread %d (%s)]\n",
+ pid_to_thread_id (inferior_pid),
+#if defined(HPUXHPPA)
+ target_tid_to_str (inferior_pid)
+#else
+ target_pid_to_str (inferior_pid)
+#endif
+ );
+ print_stack_frame (selected_frame, selected_frame_level, 1);
+}
+
+/* Commands with a prefix of `thread'. */
+struct cmd_list_element *thread_cmd_list = NULL;
+
+void
+_initialize_thread ()
+{
+ static struct cmd_list_element *thread_apply_list = NULL;
+ extern struct cmd_list_element *cmdlist;
+
+ add_info ("threads", info_threads_command,
+ "IDs of currently known threads.");
+
+ add_prefix_cmd ("thread", class_run, thread_command,
+ "Use this command to switch between threads.\n\
+The new thread ID must be currently known.", &thread_cmd_list, "thread ", 1,
+ &cmdlist);
+
+ add_prefix_cmd ("apply", class_run, thread_apply_command,
+ "Apply a command to a list of threads.",
+ &thread_apply_list, "apply ", 1, &thread_cmd_list);
+
+ add_cmd ("all", class_run, thread_apply_all_command,
+ "Apply a command to all threads.",
+ &thread_apply_list);
+
+ if (!xdb_commands)
+ add_com_alias ("t", "thread", class_run, 1);
+}
diff --git a/gdb/top.c b/gdb/top.c
new file mode 100644
index 00000000000..189e3c395ef
--- /dev/null
+++ b/gdb/top.c
@@ -0,0 +1,3677 @@
+/* Top level stuff for GDB, the GNU debugger.
+ Copyright 1986, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 1998
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 "value.h"
+#include "language.h"
+#include "terminal.h" /* For job_control. */
+#include "annotate.h"
+#include <setjmp.h>
+#include "top.h"
+
+/* readline include files */
+#include <readline/readline.h>
+#include <readline/history.h>
+
+/* readline defines this. */
+#undef savestring
+
+#include <sys/types.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include "gdb_string.h"
+#include "gdb_stat.h"
+#include <ctype.h>
+
+extern void initialize_utils PARAMS ((void));
+
+/* Prototypes for local functions */
+
+static void dont_repeat_command PARAMS ((char *, int));
+
+static void source_cleanup_lines PARAMS ((PTR));
+
+static void user_defined_command PARAMS ((char *, int));
+
+static void init_signals PARAMS ((void));
+
+#ifdef STOP_SIGNAL
+static void stop_sig PARAMS ((int));
+#endif
+
+static char * line_completion_function PARAMS ((char *, int, char *, int));
+
+static char * readline_line_completion_function PARAMS ((char *, int));
+
+static void command_loop_marker PARAMS ((int));
+
+static void while_command PARAMS ((char *, int));
+
+static void if_command PARAMS ((char *, int));
+
+static struct command_line *
+build_command_line PARAMS ((enum command_control_type, char *));
+
+static struct command_line *
+get_command_line PARAMS ((enum command_control_type, char *));
+
+static void realloc_body_list PARAMS ((struct command_line *, int));
+
+static enum misc_command_type read_next_line PARAMS ((struct command_line **));
+
+static enum command_control_type
+recurse_read_control_structure PARAMS ((struct command_line *));
+
+static struct cleanup * setup_user_args PARAMS ((char *));
+
+static char * locate_arg PARAMS ((char *));
+
+static char * insert_args PARAMS ((char *));
+
+static void arg_cleanup PARAMS ((void));
+
+static void init_main PARAMS ((void));
+
+static void init_cmd_lists PARAMS ((void));
+
+static void float_handler PARAMS ((int));
+
+static void init_signals PARAMS ((void));
+
+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 complete_command PARAMS ((char *, int));
+
+static void do_nothing PARAMS ((int));
+
+#ifdef SIGHUP
+static int quit_cover PARAMS ((PTR));
+
+static void disconnect PARAMS ((int));
+#endif
+
+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
+char gdbinit[] = GDBINIT_FILENAME;
+
+int inhibit_gdbinit = 0;
+
+/* If nonzero, and GDB has been configured to be able to use windows,
+ attempt to open them upon startup. */
+
+int use_windows = 1;
+
+/* Version number of GDB, as a string. */
+
+extern char *version;
+
+/* Canonical host name as a string. */
+
+extern char *host_name;
+
+/* Canonical target name as a string. */
+
+extern char *target_name;
+
+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_elements. */
+
+/* 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 toggle subcommands. */
+
+struct cmd_list_element *togglelist;
+
+/* Chain containing all defined stop subcommands. */
+
+struct cmd_list_element *stoplist;
+
+/* 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 or interacting via a GUI. */
+
+FILE *instream;
+
+/* Current working directory. */
+
+char *current_directory;
+
+/* The directory name is actually stored here (usually). */
+char gdb_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 *));
+
+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;
+
+/* Nonzero if the current command is modified by "server ". This
+ affects things like recording into the command history, comamnds
+ repeating on RETURN, etc. This is so a user interface (emacs, GUI,
+ whatever) can issue its own commands and also send along commands
+ from the user, and have the user not notice that the user interface
+ is issuing commands too. */
+int server_command;
+
+/* Baud rate specified for talking to serial target systems. Default
+ is left as -1, so targets can choose their own defaults. */
+/* FIXME: This means that "show remotebaud" and gr_files_info can print -1
+ or (unsigned int)-1. This is a Bad User Interface. */
+
+int baud_rate = -1;
+
+/* Timeout limit for response from target. */
+
+int remote_timeout = 20; /* Set default to 20 */
+
+/* Non-zero tells remote* modules to output debugging info. */
+
+int remote_debug = 0;
+
+/* Level of control structure. */
+static int control_level;
+
+/* Structure for arguments to user defined functions. */
+#define MAXUSERARGS 10
+struct user_args
+{
+ struct user_args *next;
+ struct
+ {
+ char *arg;
+ int len;
+ } a[MAXUSERARGS];
+ int count;
+} *user_args;
+
+/* 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)
+#if !defined (USG)
+#define HAVE_SIGSETMASK 1
+#else
+#define HAVE_SIGSETMASK 0
+#endif
+#endif
+
+#if 0 == (HAVE_SIGSETMASK)
+#define sigsetmask(n)
+#endif
+
+/* Hooks for alternate command interfaces. */
+
+/* Called after most modules have been initialized, but before taking users
+ command file. */
+
+void (*init_ui_hook) PARAMS ((char *argv0));
+#ifdef __CYGWIN32__
+void (*ui_loop_hook) PARAMS ((int));
+#endif
+
+/* Called instead of command_loop at top level. Can be invoked via
+ return_to_top_level. */
+
+void (*command_loop_hook) PARAMS ((void));
+
+
+/* Called instead of fputs for all output. */
+
+void (*fputs_unfiltered_hook) PARAMS ((const char *linebuffer, GDB_FILE *stream));
+
+/* Called when the target says something to the host, which may
+ want to appear in a different window. */
+
+void (*target_output_hook) PARAMS ((char *));
+
+/* Called from print_frame_info to list the line we stopped in. */
+
+void (*print_frame_info_listing_hook) PARAMS ((struct symtab *s, int line,
+ int stopline, int noerror));
+/* Replaces most of query. */
+
+int (*query_hook) PARAMS ((const char *, va_list));
+
+/* Replaces most of warning. */
+
+void (*warning_hook) PARAMS ((const char *, va_list));
+
+/* Called from gdb_flush to flush output. */
+
+void (*flush_hook) PARAMS ((GDB_FILE *stream));
+
+/* These three functions support getting lines of text from the user. They
+ are used in sequence. First readline_begin_hook is called with a text
+ string that might be (for example) a message for the user to type in a
+ sequence of commands to be executed at a breakpoint. If this function
+ calls back to a GUI, it might take this opportunity to pop up a text
+ interaction window with this message. Next, readline_hook is called
+ with a prompt that is emitted prior to collecting the user input.
+ It can be called multiple times. Finally, readline_end_hook is called
+ to notify the GUI that we are done with the interaction window and it
+ can close it. */
+
+void (*readline_begin_hook) PARAMS ((char *, ...));
+char * (*readline_hook) PARAMS ((char *));
+void (*readline_end_hook) PARAMS ((void));
+
+/* Called as appropriate to notify the interface of the specified breakpoint
+ conditions. */
+
+void (*create_breakpoint_hook) PARAMS ((struct breakpoint *bpt));
+void (*delete_breakpoint_hook) PARAMS ((struct breakpoint *bpt));
+void (*modify_breakpoint_hook) PARAMS ((struct breakpoint *bpt));
+
+/* Called during long calculations to allow GUI to repair window damage, and to
+ check for stop buttons, etc... */
+
+void (*interactive_hook) PARAMS ((void));
+
+/* Called when the registers have changed, as a hint to a GUI
+ to minimize window update. */
+
+void (*registers_changed_hook) PARAMS ((void));
+
+/* Tell the GUI someone changed the register REGNO. -1 means
+ that the caller does not know which register changed or
+ that several registers have changed (see value_assign).*/
+void (*register_changed_hook) PARAMS ((int regno));
+
+/* Tell the GUI someone changed LEN bytes of memory at ADDR */
+void (*memory_changed_hook) PARAMS ((CORE_ADDR addr, int len));
+
+/* Called when going to wait for the target. Usually allows the GUI to run
+ while waiting for target events. */
+
+int (*target_wait_hook) PARAMS ((int pid, struct target_waitstatus *status));
+
+/* Used by UI as a wrapper around command execution. May do various things
+ like enabling/disabling buttons, etc... */
+
+void (*call_command_hook) PARAMS ((struct cmd_list_element *c, char *cmd,
+ int from_tty));
+
+/* Called when the current thread changes. Argument is thread id. */
+
+void (*context_hook) PARAMS ((int id));
+
+/* Takes control from error (). Typically used to prevent longjmps out of the
+ middle of the GUI. Usually used in conjunction with a catch routine. */
+
+NORETURN void (*error_hook) PARAMS ((void)) ATTR_NORETURN;
+
+
+/* Where to go for return_to_top_level (RETURN_ERROR). */
+SIGJMP_BUF error_return;
+/* Where to go for return_to_top_level (RETURN_QUIT). */
+SIGJMP_BUF quit_return;
+
+/* 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);
+
+ if (annotation_level > 1)
+ switch (reason)
+ {
+ case RETURN_QUIT:
+ annotate_quit ();
+ break;
+ case RETURN_ERROR:
+ annotate_error ();
+ break;
+ }
+
+ (NORETURN void) SIGLONGJMP
+ (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)
+ catch_errors_ftype *func;
+ PTR args;
+ char *errstring;
+ return_mask mask;
+{
+ SIGJMP_BUF saved_error;
+ SIGJMP_BUF saved_quit;
+ SIGJMP_BUF tmp_jmp;
+ int val;
+ struct cleanup *saved_cleanup_chain;
+ char *saved_error_pre_print;
+ char *saved_quit_pre_print;
+
+ saved_cleanup_chain = save_cleanups ();
+ saved_error_pre_print = error_pre_print;
+ saved_quit_pre_print = quit_pre_print;
+
+ if (mask & RETURN_MASK_ERROR)
+ {
+ memcpy ((char *)saved_error, (char *)error_return, sizeof (SIGJMP_BUF));
+ error_pre_print = errstring;
+ }
+ if (mask & RETURN_MASK_QUIT)
+ {
+ memcpy (saved_quit, quit_return, sizeof (SIGJMP_BUF));
+ quit_pre_print = errstring;
+ }
+
+ if (SIGSETJMP (tmp_jmp) == 0)
+ {
+ if (mask & RETURN_MASK_ERROR)
+ memcpy (error_return, tmp_jmp, sizeof (SIGJMP_BUF));
+ if (mask & RETURN_MASK_QUIT)
+ memcpy (quit_return, tmp_jmp, sizeof (SIGJMP_BUF));
+ val = (*func) (args);
+ }
+ else
+ val = 0;
+
+ restore_cleanups (saved_cleanup_chain);
+
+ if (mask & RETURN_MASK_ERROR)
+ {
+ memcpy (error_return, saved_error, sizeof (SIGJMP_BUF));
+ error_pre_print = saved_error_pre_print;
+ }
+ if (mask & RETURN_MASK_QUIT)
+ {
+ memcpy (quit_return, saved_quit, sizeof (SIGJMP_BUF));
+ quit_pre_print = saved_quit_pre_print;
+ }
+ return val;
+}
+
+/* Handler for SIGHUP. */
+
+#ifdef 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)
+ PTR 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;
+}
+#endif /* defined SIGHUP */
+
+/* Line number we are currently in in a file which is being sourced. */
+static int source_line_number;
+
+/* Name of the file we are sourcing. */
+static char *source_file_name;
+
+/* Buffer containing the error_pre_print used by the source stuff.
+ Malloc'd. */
+static char *source_error;
+static int source_error_allocated;
+
+/* Something to glom on to the start of error_pre_print if source_file_name
+ is set. */
+static char *source_pre_error;
+
+/* 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. */
+void
+read_command_file (stream)
+ FILE *stream;
+{
+ struct cleanup *cleanups;
+
+ cleanups = make_cleanup ((make_cleanup_func) source_cleanup, instream);
+ instream = stream;
+ command_loop ();
+ do_cleanups (cleanups);
+}
+
+extern void init_proc PARAMS ((void));
+
+void (*pre_init_ui_hook) PARAMS ((void));
+
+void
+gdb_init (argv0)
+ char *argv0;
+{
+ if (pre_init_ui_hook)
+ pre_init_ui_hook ();
+
+ /* Run the init function of each source file */
+
+ getcwd (gdb_dirbuf, sizeof (gdb_dirbuf));
+ current_directory = gdb_dirbuf;
+
+ init_cmd_lists (); /* This needs to be done first */
+ initialize_targets (); /* Setup target_terminal macros for utils.c */
+ initialize_utils (); /* Make errors and warnings possible */
+ initialize_all_files ();
+ init_main (); /* But that omits this file! Do it now */
+ init_signals ();
+
+ init_proc ();
+
+ /* 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. */
+
+ if (init_ui_hook)
+ init_ui_hook (argv0);
+}
+
+/* Allocate, initialize a new command line structure for one of the
+ control commands (if/while). */
+
+static struct command_line *
+build_command_line (type, args)
+ enum command_control_type type;
+ char *args;
+{
+ struct command_line *cmd;
+
+ if (args == NULL)
+ error ("if/while commands require arguments.\n");
+
+ cmd = (struct command_line *)xmalloc (sizeof (struct command_line));
+ cmd->next = NULL;
+ cmd->control_type = type;
+
+ cmd->body_count = 1;
+ cmd->body_list
+ = (struct command_line **)xmalloc (sizeof (struct command_line *)
+ * cmd->body_count);
+ memset (cmd->body_list, 0, sizeof (struct command_line *) * cmd->body_count);
+ cmd->line = savestring (args, strlen (args));
+ return cmd;
+}
+
+/* Build and return a new command structure for the control commands
+ such as "if" and "while". */
+
+static struct command_line *
+get_command_line (type, arg)
+ enum command_control_type type;
+ char *arg;
+{
+ struct command_line *cmd;
+ struct cleanup *old_chain = NULL;
+
+ /* Allocate and build a new command line structure. */
+ cmd = build_command_line (type, arg);
+
+ old_chain = make_cleanup ((make_cleanup_func) free_command_lines, &cmd);
+
+ /* Read in the body of this command. */
+ if (recurse_read_control_structure (cmd) == invalid_control)
+ {
+ warning ("error reading in control structure\n");
+ do_cleanups (old_chain);
+ return NULL;
+ }
+
+ discard_cleanups (old_chain);
+ return cmd;
+}
+
+/* Recursively print a command (including full control structures). */
+void
+print_command_line (cmd, depth)
+ struct command_line *cmd;
+ unsigned int depth;
+{
+ unsigned int i;
+
+ if (depth)
+ {
+ for (i = 0; i < depth; i++)
+ fputs_filtered (" ", gdb_stdout);
+ }
+
+ /* A simple command, print it and return. */
+ if (cmd->control_type == simple_control)
+ {
+ fputs_filtered (cmd->line, gdb_stdout);
+ fputs_filtered ("\n", gdb_stdout);
+ return;
+ }
+
+ /* loop_continue to jump to the start of a while loop, print it
+ and return. */
+ if (cmd->control_type == continue_control)
+ {
+ fputs_filtered ("loop_continue\n", gdb_stdout);
+ return;
+ }
+
+ /* loop_break to break out of a while loop, print it and return. */
+ if (cmd->control_type == break_control)
+ {
+ fputs_filtered ("loop_break\n", gdb_stdout);
+ return;
+ }
+
+ /* A while command. Recursively print its subcommands before returning. */
+ if (cmd->control_type == while_control)
+ {
+ struct command_line *list;
+ fputs_filtered ("while ", gdb_stdout);
+ fputs_filtered (cmd->line, gdb_stdout);
+ fputs_filtered ("\n", gdb_stdout);
+ list = *cmd->body_list;
+ while (list)
+ {
+ print_command_line (list, depth + 1);
+ list = list->next;
+ }
+ }
+
+ /* An if command. Recursively print both arms before returning. */
+ if (cmd->control_type == if_control)
+ {
+ fputs_filtered ("if ", gdb_stdout);
+ fputs_filtered (cmd->line, gdb_stdout);
+ fputs_filtered ("\n", gdb_stdout);
+ /* The true arm. */
+ print_command_line (cmd->body_list[0], depth + 1);
+
+ /* Show the false arm if it exists. */
+ if (cmd->body_count == 2)
+ {
+ if (depth)
+ {
+ for (i = 0; i < depth; i++)
+ fputs_filtered (" ", gdb_stdout);
+ }
+ fputs_filtered ("else\n", gdb_stdout);
+ print_command_line (cmd->body_list[1], depth + 1);
+ }
+ if (depth)
+ {
+ for (i = 0; i < depth; i++)
+ fputs_filtered (" ", gdb_stdout);
+ }
+ fputs_filtered ("end\n", gdb_stdout);
+ }
+}
+
+/* Execute the command in CMD. */
+
+enum command_control_type
+execute_control_command (cmd)
+ struct command_line *cmd;
+{
+ struct expression *expr;
+ struct command_line *current;
+ struct cleanup *old_chain = 0;
+ value_ptr val;
+ value_ptr val_mark;
+ int loop;
+ enum command_control_type ret;
+ char *new_line;
+
+ switch (cmd->control_type)
+ {
+ case simple_control:
+ /* A simple command, execute it and return. */
+ new_line = insert_args (cmd->line);
+ if (!new_line)
+ return invalid_control;
+ old_chain = make_cleanup ((make_cleanup_func) free_current_contents,
+ &new_line);
+ execute_command (new_line, 0);
+ ret = cmd->control_type;
+ break;
+
+ case continue_control:
+ case break_control:
+ /* Return for "continue", and "break" so we can either
+ continue the loop at the top, or break out. */
+ ret = cmd->control_type;
+ break;
+
+ case while_control:
+ {
+ /* Parse the loop control expression for the while statement. */
+ new_line = insert_args (cmd->line);
+ if (!new_line)
+ return invalid_control;
+ old_chain = make_cleanup ((make_cleanup_func) free_current_contents,
+ &new_line);
+ expr = parse_expression (new_line);
+ make_cleanup ((make_cleanup_func) free_current_contents, &expr);
+
+ ret = simple_control;
+ loop = 1;
+
+ /* Keep iterating so long as the expression is true. */
+ while (loop == 1)
+ {
+ int cond_result;
+
+ QUIT;
+
+ /* Evaluate the expression. */
+ val_mark = value_mark ();
+ val = evaluate_expression (expr);
+ cond_result = value_true (val);
+ value_free_to_mark (val_mark);
+
+ /* If the value is false, then break out of the loop. */
+ if (!cond_result)
+ break;
+
+ /* Execute the body of the while statement. */
+ current = *cmd->body_list;
+ while (current)
+ {
+ ret = execute_control_command (current);
+
+ /* If we got an error, or a "break" command, then stop
+ looping. */
+ if (ret == invalid_control || ret == break_control)
+ {
+ loop = 0;
+ break;
+ }
+
+ /* If we got a "continue" command, then restart the loop
+ at this point. */
+ if (ret == continue_control)
+ break;
+
+ /* Get the next statement. */
+ current = current->next;
+ }
+ }
+
+ /* Reset RET so that we don't recurse the break all the way down. */
+ if (ret == break_control)
+ ret = simple_control;
+
+ break;
+ }
+
+ case if_control:
+ {
+ new_line = insert_args (cmd->line);
+ if (!new_line)
+ return invalid_control;
+ old_chain = make_cleanup ((make_cleanup_func) free_current_contents,
+ &new_line);
+ /* Parse the conditional for the if statement. */
+ expr = parse_expression (new_line);
+ make_cleanup ((make_cleanup_func) free_current_contents, &expr);
+
+ current = NULL;
+ ret = simple_control;
+
+ /* Evaluate the conditional. */
+ val_mark = value_mark ();
+ val = evaluate_expression (expr);
+
+ /* Choose which arm to take commands from based on the value of the
+ conditional expression. */
+ if (value_true (val))
+ current = *cmd->body_list;
+ else if (cmd->body_count == 2)
+ current = *(cmd->body_list + 1);
+ value_free_to_mark (val_mark);
+
+ /* Execute commands in the given arm. */
+ while (current)
+ {
+ ret = execute_control_command (current);
+
+ /* If we got an error, get out. */
+ if (ret != simple_control)
+ break;
+
+ /* Get the next statement in the body. */
+ current = current->next;
+ }
+
+ break;
+ }
+
+ default:
+ warning ("Invalid control type in command structure.");
+ return invalid_control;
+ }
+
+ if (old_chain)
+ do_cleanups (old_chain);
+
+ return ret;
+}
+
+/* "while" command support. Executes a body of statements while the
+ loop condition is nonzero. */
+
+static void
+while_command (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ struct command_line *command = NULL;
+
+ control_level = 1;
+ command = get_command_line (while_control, arg);
+
+ if (command == NULL)
+ return;
+
+ execute_control_command (command);
+ free_command_lines (&command);
+}
+
+/* "if" command support. Execute either the true or false arm depending
+ on the value of the if conditional. */
+
+static void
+if_command (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ struct command_line *command = NULL;
+
+ control_level = 1;
+ command = get_command_line (if_control, arg);
+
+ if (command == NULL)
+ return;
+
+ execute_control_command (command);
+ free_command_lines (&command);
+}
+
+/* Cleanup */
+static void
+arg_cleanup ()
+{
+ struct user_args *oargs = user_args;
+ if (!user_args)
+ fatal ("Internal error, arg_cleanup called with no user args.\n");
+
+ user_args = user_args->next;
+ free (oargs);
+}
+
+/* Bind the incomming arguments for a user defined command to
+ $arg0, $arg1 ... $argMAXUSERARGS. */
+
+static struct cleanup *
+setup_user_args (p)
+ char *p;
+{
+ struct user_args *args;
+ struct cleanup *old_chain;
+ unsigned int arg_count = 0;
+
+ args = (struct user_args *)xmalloc (sizeof (struct user_args));
+ memset (args, 0, sizeof (struct user_args));
+
+ args->next = user_args;
+ user_args = args;
+
+ old_chain = make_cleanup ((make_cleanup_func) arg_cleanup, 0);
+
+ if (p == NULL)
+ return old_chain;
+
+ while (*p)
+ {
+ char *start_arg;
+ int squote = 0;
+ int dquote = 0;
+ int bsquote = 0;
+
+ if (arg_count >= MAXUSERARGS)
+ {
+ error ("user defined function may only have %d arguments.\n",
+ MAXUSERARGS);
+ return old_chain;
+ }
+
+ /* Strip whitespace. */
+ while (*p == ' ' || *p == '\t')
+ p++;
+
+ /* P now points to an argument. */
+ start_arg = p;
+ user_args->a[arg_count].arg = p;
+
+ /* Get to the end of this argument. */
+ while (*p)
+ {
+ if (((*p == ' ' || *p == '\t')) && !squote && !dquote && !bsquote)
+ break;
+ else
+ {
+ if (bsquote)
+ bsquote = 0;
+ else if (*p == '\\')
+ bsquote = 1;
+ else if (squote)
+ {
+ if (*p == '\'')
+ squote = 0;
+ }
+ else if (dquote)
+ {
+ if (*p == '"')
+ dquote = 0;
+ }
+ else
+ {
+ if (*p == '\'')
+ squote = 1;
+ else if (*p == '"')
+ dquote = 1;
+ }
+ p++;
+ }
+ }
+
+ user_args->a[arg_count].len = p - start_arg;
+ arg_count++;
+ user_args->count++;
+ }
+ return old_chain;
+}
+
+/* Given character string P, return a point to the first argument ($arg),
+ or NULL if P contains no arguments. */
+
+static char *
+locate_arg (p)
+ char *p;
+{
+ while ((p = strchr (p, '$')))
+ {
+ if (strncmp (p, "$arg", 4) == 0 && isdigit (p[4]))
+ return p;
+ p++;
+ }
+ return NULL;
+}
+
+/* Insert the user defined arguments stored in user_arg into the $arg
+ arguments found in line, with the updated copy being placed into nline. */
+
+static char *
+insert_args (line)
+ char *line;
+{
+ char *p, *save_line, *new_line;
+ unsigned len, i;
+
+ /* First we need to know how much memory to allocate for the new line. */
+ save_line = line;
+ len = 0;
+ while ((p = locate_arg (line)))
+ {
+ len += p - line;
+ i = p[4] - '0';
+
+ if (i >= user_args->count)
+ {
+ error ("Missing argument %d in user function.\n", i);
+ return NULL;
+ }
+ len += user_args->a[i].len;
+ line = p + 5;
+ }
+
+ /* Don't forget the tail. */
+ len += strlen (line);
+
+ /* Allocate space for the new line and fill it in. */
+ new_line = (char *)xmalloc (len + 1);
+ if (new_line == NULL)
+ return NULL;
+
+ /* Restore pointer to beginning of old line. */
+ line = save_line;
+
+ /* Save pointer to beginning of new line. */
+ save_line = new_line;
+
+ while ((p = locate_arg (line)))
+ {
+ int i, len;
+
+ memcpy (new_line, line, p - line);
+ new_line += p - line;
+ i = p[4] - '0';
+
+ len = user_args->a[i].len;
+ if (len)
+ {
+ memcpy (new_line, user_args->a[i].arg, len);
+ new_line += len;
+ }
+ line = p + 5;
+ }
+ /* Don't forget the tail. */
+ strcpy (new_line, line);
+
+ /* Return a pointer to the beginning of the new line. */
+ return save_line;
+}
+
+void
+execute_user_command (c, args)
+ struct cmd_list_element *c;
+ char *args;
+{
+ register struct command_line *cmdlines;
+ struct cleanup *old_chain;
+ enum command_control_type ret;
+
+ old_chain = setup_user_args (args);
+
+ 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 ((make_cleanup_func) source_cleanup, instream);
+ instream = (FILE *) 0;
+ while (cmdlines)
+ {
+ ret = execute_control_command (cmdlines);
+ if (ret != simple_control && ret != break_control)
+ {
+ warning ("Error in control structure.\n");
+ break;
+ }
+ 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;
+ /* FIXME: These should really be in an appropriate header file */
+ extern void serial_log_command PARAMS ((const char *));
+
+ free_all_values ();
+
+ /* Force cleanup of any alloca areas if using C alloca instead of
+ a builtin alloca. */
+ alloca (0);
+
+ /* This can happen when command_line_input hits end of file. */
+ if (p == NULL)
+ return;
+
+ serial_log_command (p);
+
+ 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;
+
+ /* Clear off trailing whitespace, except for set and complete command. */
+ if (arg && c->type != set_cmd && c->function.cfunc != complete_command)
+ {
+ p = arg + strlen (arg) - 1;
+ while (p >= arg && (*p == ' ' || *p == '\t'))
+ p--;
+ *(p + 1) = '\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 if (call_command_hook)
+ call_command_hook (c, arg, from_tty & caution);
+ 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. */
+
+void
+command_loop ()
+{
+ struct cleanup *old_chain;
+ char *command;
+ int stdin_is_tty = ISATTY (stdin);
+ long time_at_cmd_start;
+#ifdef HAVE_SBRK
+ long space_at_cmd_start = 0;
+#endif
+ extern int display_time;
+ extern int display_space;
+
+ while (instream && !feof (instream))
+ {
+#if defined(TUI)
+ extern int insert_mode;
+#endif
+ 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 ((make_cleanup_func) command_loop_marker, 0);
+
+#if defined(TUI)
+ /* A bit of paranoia: I want to make sure the "insert_mode" global
+ * is clear except when it is being used for command-line editing
+ * (see tuiIO.c, utils.c); otherwise normal output will
+ * get messed up in the TUI. So clear it before/after
+ * the command-line-input call. - RT
+ */
+ insert_mode = 0;
+#endif
+ /* Get a command-line. This calls the readline package. */
+ command = command_line_input (instream == stdin ? prompt : (char *) NULL,
+ instream == stdin, "prompt");
+#if defined(TUI)
+ insert_mode = 0;
+#endif
+ if (command == 0)
+ return;
+
+ time_at_cmd_start = get_run_time ();
+
+ if (display_space)
+ {
+#ifdef HAVE_SBRK
+ extern char **environ;
+ char *lim = (char *) sbrk (0);
+
+ space_at_cmd_start = (long) (lim - (char *) &environ);
+#endif
+ }
+
+ execute_command (command, instream == stdin);
+ /* Do any commands attached to breakpoint we stopped at. */
+ bpstat_do_actions (&stop_bpstat);
+ do_cleanups (old_chain);
+
+ if (display_time)
+ {
+ long cmd_time = get_run_time () - time_at_cmd_start;
+
+ printf_unfiltered ("Command execution time: %ld.%06ld\n",
+ cmd_time / 1000000, cmd_time % 1000000);
+ }
+
+ if (display_space)
+ {
+#ifdef HAVE_SBRK
+ extern char **environ;
+ char *lim = (char *) sbrk (0);
+ long space_now = lim - (char *) &environ;
+ long space_diff = space_now - space_at_cmd_start;
+
+ printf_unfiltered ("Space used: %ld (%c%ld for this command)\n",
+ space_now,
+ (space_diff >= 0 ? '+' : '-'),
+ space_diff);
+#endif
+ }
+ }
+}
+
+/* Commands call this if they do not want to be repeated by null lines. */
+
+void
+dont_repeat ()
+{
+ if (server_command)
+ return;
+
+ /* 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_unfiltered (prrompt, gdb_stdout);
+#ifdef MPW
+ /* Move to a new line so the entered line doesn't have a prompt
+ on the front of it. */
+ fputs_unfiltered ("\n", gdb_stdout);
+#endif /* MPW */
+ gdb_flush (gdb_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')
+#ifndef CRLF_SOURCE_FILES
+ break;
+#else
+ {
+ if (input_index > 0 && result[input_index - 1] == '\r')
+ input_index--;
+ break;
+ }
+#endif
+
+ 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 PARAMS ((char *, int));
+ 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/we" "ird" (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.
+ line_completion 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 the caller's idea of the "word" we are looking at.
+
+ 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.
+
+ LINE_BUFFER is available to be looked at; it contains the entire text
+ of the line. POINT is the offset in that line of the cursor. You
+ should pretend that the line ends at POINT.
+
+ Returns NULL if there are no more completions, else a pointer to a string
+ which is a possible completion, it is the caller's responsibility to
+ free the string. */
+
+static char *
+line_completion_function (text, matches, line_buffer, point)
+ char *text;
+ int matches;
+ char *line_buffer;
+ int point;
+{
+ 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;
+
+ 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 (point + 1);
+ p = tmp_command;
+
+ strncpy (tmp_command, line_buffer, point);
+ tmp_command[point] = '\0';
+ /* Since text always contains some number of characters leading up
+ to point, we can find the equivalent position in tmp_command
+ by subtracting that many characters from the end of tmp_command. */
+ word = tmp_command + point - strlen (text);
+
+ if (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 + 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 + 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 if (c->enums)
+ {
+ list = complete_on_enum (c->enums, p, word);
+ 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 if (c->enums)
+ {
+ list = complete_on_enum (c->enums, p, word);
+ }
+ 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);
+}
+
+/* Line completion interface function for readline. */
+
+static char *
+readline_line_completion_function (text, matches)
+ char *text;
+ int matches;
+{
+ return line_completion_function (text, matches, rl_line_buffer, rl_point);
+}
+
+/* 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_unfiltered ("%s", prompt);
+ gdb_flush (gdb_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;
+{
+ /* Under System V the default disposition of a signal is reinstated after
+ the signal is caught and delivered to an application process. On such
+ systems one must restore the replacement signal handler if one wishes
+ to continue handling the signal in one's program. On BSD systems this
+ is not needed but it is harmless, and it simplifies the code to just do
+ it unconditionally. */
+ signal (signo, do_nothing);
+}
+
+static void
+init_signals ()
+{
+ signal (SIGINT, request_quit);
+
+ /* If SIGTRAP was set to SIG_IGN, then the SIG_IGN will get passed
+ to the inferior and breakpoints will be ignored. */
+#ifdef SIGTRAP
+ signal (SIGTRAP, SIG_DFL);
+#endif
+
+ /* 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);
+#ifdef SIGHUP
+ if (signal (SIGHUP, do_nothing) != SIG_IGN)
+ signal (SIGHUP, disconnect);
+#endif
+ 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, annotation_suffix)
+ char *prrompt;
+ int repeat;
+ char *annotation_suffix;
+{
+ static char *linebuffer = 0;
+ static unsigned linelength = 0;
+ register char *p;
+ char *p1;
+ char *rl;
+ char *local_prompt = prrompt;
+ char *nline;
+ char got_eof = 0;
+
+ /* The annotation suffix must be non-NULL. */
+ if (annotation_suffix == NULL)
+ annotation_suffix = "";
+
+ if (annotation_level > 1 && instream == stdin)
+ {
+ local_prompt = alloca ((prrompt == NULL ? 0 : strlen (prrompt))
+ + strlen (annotation_suffix) + 40);
+ if (prrompt == NULL)
+ local_prompt[0] = '\0';
+ else
+ strcpy (local_prompt, prrompt);
+ strcat (local_prompt, "\n\032\032");
+ strcat (local_prompt, annotation_suffix);
+ strcat (local_prompt, "\n");
+ }
+
+ 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)
+ {
+ /* Make sure that all output has been output. Some machines may let
+ you get away with leaving out some of the gdb_flush, but not all. */
+ wrap_here ("");
+ gdb_flush (gdb_stdout);
+ gdb_flush (gdb_stderr);
+
+ if (source_file_name != NULL)
+ {
+ ++source_line_number;
+ sprintf (source_error,
+ "%s%s:%d: Error in sourced command file:\n",
+ source_pre_error,
+ source_file_name,
+ source_line_number);
+ error_pre_print = source_error;
+ }
+
+ if (annotation_level > 1 && instream == stdin)
+ {
+ printf_unfiltered ("\n\032\032pre-");
+ printf_unfiltered (annotation_suffix);
+ printf_unfiltered ("\n");
+ }
+
+ /* Don't use fancy stuff if not talking to stdin. */
+ if (readline_hook && instream == NULL)
+ {
+ rl = (*readline_hook) (local_prompt);
+ }
+ else if (command_editing_p && instream == stdin && ISATTY (instream))
+ {
+ rl = readline (local_prompt);
+ }
+ else
+ {
+ rl = gdb_readline (local_prompt);
+ }
+
+ if (annotation_level > 1 && instream == stdin)
+ {
+ printf_unfiltered ("\n\032\032post-");
+ printf_unfiltered (annotation_suffix);
+ printf_unfiltered ("\n");
+ }
+
+ 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;
+
+#define SERVER_COMMAND_LENGTH 7
+ server_command =
+ (p - linebuffer > SERVER_COMMAND_LENGTH)
+ && STREQN (linebuffer, "server ", SERVER_COMMAND_LENGTH);
+ if (server_command)
+ {
+ /* Note that we don't set `line'. Between this and the check in
+ dont_repeat, this insures that repeating will still do the
+ right thing. */
+ *p = '\0';
+ return linebuffer + SERVER_COMMAND_LENGTH;
+ }
+
+ /* 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_unfiltered ("%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, annotation_suffix);
+ }
+ 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 && p == linebuffer)
+ return line;
+ for (p1 = linebuffer; *p1 == ' ' || *p1 == '\t'; p1++) ;
+ if (repeat && !*p1)
+ return line;
+
+ *p = 0;
+
+ /* Add line to history if appropriate. */
+ if (instream == stdin
+ && ISATTY (stdin) && *linebuffer)
+ add_history (linebuffer);
+
+ /* Note: lines consisting solely 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. */
+ if (*p1 == '#')
+ *p1 = '\0'; /* Found a comment. */
+
+ /* Save into global buffer if appropriate. */
+ if (repeat)
+ {
+ if (linelength > linesize)
+ {
+ line = xrealloc (line, linelength);
+ linesize = linelength;
+ }
+ strcpy (line, linebuffer);
+ return line;
+ }
+
+ return linebuffer;
+}
+
+
+/* Expand the body_list of COMMAND so that it can hold NEW_LENGTH
+ code bodies. This is typically used when we encounter an "else"
+ clause for an "if" command. */
+
+static void
+realloc_body_list (command, new_length)
+ struct command_line *command;
+ int new_length;
+{
+ int n;
+ struct command_line **body_list;
+
+ n = command->body_count;
+
+ /* Nothing to do? */
+ if (new_length <= n)
+ return;
+
+ body_list = (struct command_line **)
+ xmalloc (sizeof (struct command_line *) * new_length);
+
+ memcpy (body_list, command->body_list, sizeof (struct command_line *) * n);
+
+ free (command->body_list);
+ command->body_list = body_list;
+ command->body_count = new_length;
+}
+
+/* Read one line from the input stream. If the command is an "else" or
+ "end", return such an indication to the caller. */
+
+static enum misc_command_type
+read_next_line (command)
+ struct command_line **command;
+{
+ char *p, *p1, *prompt_ptr, control_prompt[256];
+ int i = 0;
+
+ if (control_level >= 254)
+ error ("Control nesting too deep!\n");
+
+ /* Set a prompt based on the nesting of the control commands. */
+ if (instream == stdin || (instream == 0 && readline_hook != NULL))
+ {
+ for (i = 0; i < control_level; i++)
+ control_prompt[i] = ' ';
+ control_prompt[i] = '>';
+ control_prompt[i+1] = '\0';
+ prompt_ptr = (char *)&control_prompt[0];
+ }
+ else
+ prompt_ptr = NULL;
+
+ p = command_line_input (prompt_ptr, instream == stdin, "commands");
+
+ /* Not sure what to do here. */
+ if (p == NULL)
+ return end_command;
+
+ /* Strip leading and trailing whitespace. */
+ while (*p == ' ' || *p == '\t')
+ p++;
+
+ p1 = p + strlen (p);
+ while (p1 != p && (p1[-1] == ' ' || p1[-1] == '\t'))
+ p1--;
+
+ /* Blanks and comments don't really do anything, but we need to
+ distinguish them from else, end and other commands which can be
+ executed. */
+ if (p1 == p || p[0] == '#')
+ return nop_command;
+
+ /* Is this the end of a simple, while, or if control structure? */
+ if (p1 - p == 3 && !strncmp (p, "end", 3))
+ return end_command;
+
+ /* Is the else clause of an if control structure? */
+ if (p1 - p == 4 && !strncmp (p, "else", 4))
+ return else_command;
+
+ /* Check for while, if, break, continue, etc and build a new command
+ line structure for them. */
+ if (p1 - p > 5 && !strncmp (p, "while", 5))
+ *command = build_command_line (while_control, p + 6);
+ else if (p1 - p > 2 && !strncmp (p, "if", 2))
+ *command = build_command_line (if_control, p + 3);
+ else if (p1 - p == 10 && !strncmp (p, "loop_break", 10))
+ {
+ *command = (struct command_line *)
+ xmalloc (sizeof (struct command_line));
+ (*command)->next = NULL;
+ (*command)->line = NULL;
+ (*command)->control_type = break_control;
+ (*command)->body_count = 0;
+ (*command)->body_list = NULL;
+ }
+ else if (p1 - p == 13 && !strncmp (p, "loop_continue", 13))
+ {
+ *command = (struct command_line *)
+ xmalloc (sizeof (struct command_line));
+ (*command)->next = NULL;
+ (*command)->line = NULL;
+ (*command)->control_type = continue_control;
+ (*command)->body_count = 0;
+ (*command)->body_list = NULL;
+ }
+ else
+ {
+ /* A normal command. */
+ *command = (struct command_line *)
+ xmalloc (sizeof (struct command_line));
+ (*command)->next = NULL;
+ (*command)->line = savestring (p, p1 - p);
+ (*command)->control_type = simple_control;
+ (*command)->body_count = 0;
+ (*command)->body_list = NULL;
+ }
+
+ /* Nothing special. */
+ return ok_command;
+}
+
+/* Recursively read in the control structures and create a command_line
+ structure from them.
+
+ The parent_control parameter is the control structure in which the
+ following commands are nested. */
+
+static enum command_control_type
+recurse_read_control_structure (current_cmd)
+ struct command_line *current_cmd;
+{
+ int current_body, i;
+ enum misc_command_type val;
+ enum command_control_type ret;
+ struct command_line **body_ptr, *child_tail, *next;
+
+ child_tail = NULL;
+ current_body = 1;
+
+ /* Sanity checks. */
+ if (current_cmd->control_type == simple_control)
+ {
+ error ("Recursed on a simple control type\n");
+ return invalid_control;
+ }
+
+ if (current_body > current_cmd->body_count)
+ {
+ error ("Allocated body is smaller than this command type needs\n");
+ return invalid_control;
+ }
+
+ /* Read lines from the input stream and build control structures. */
+ while (1)
+ {
+ dont_repeat ();
+
+ next = NULL;
+ val = read_next_line (&next);
+
+ /* Just skip blanks and comments. */
+ if (val == nop_command)
+ continue;
+
+ if (val == end_command)
+ {
+ if (current_cmd->control_type == while_control
+ || current_cmd->control_type == if_control)
+ {
+ /* Success reading an entire control structure. */
+ ret = simple_control;
+ break;
+ }
+ else
+ {
+ ret = invalid_control;
+ break;
+ }
+ }
+
+ /* Not the end of a control structure. */
+ if (val == else_command)
+ {
+ if (current_cmd->control_type == if_control
+ && current_body == 1)
+ {
+ realloc_body_list (current_cmd, 2);
+ current_body = 2;
+ child_tail = NULL;
+ continue;
+ }
+ else
+ {
+ ret = invalid_control;
+ break;
+ }
+ }
+
+ if (child_tail)
+ {
+ child_tail->next = next;
+ }
+ else
+ {
+ body_ptr = current_cmd->body_list;
+ for (i = 1; i < current_body; i++)
+ body_ptr++;
+
+ *body_ptr = next;
+
+ }
+
+ child_tail = next;
+
+ /* If the latest line is another control structure, then recurse
+ on it. */
+ if (next->control_type == while_control
+ || next->control_type == if_control)
+ {
+ control_level++;
+ ret = recurse_read_control_structure (next);
+ control_level--;
+
+ if (ret != simple_control)
+ break;
+ }
+ }
+
+ dont_repeat ();
+
+ return ret;
+}
+
+/* Read lines from the input stream and accumulate them in a chain of
+ struct command_line's, which is then returned. For input from a
+ terminal, the special command "end" is used to mark the end of the
+ input, and is not included in the returned chain of commands. */
+
+#define END_MESSAGE "End with a line saying just \"end\"."
+
+struct command_line *
+read_command_lines (prompt, from_tty)
+char *prompt;
+int from_tty;
+{
+ struct command_line *head, *tail, *next;
+ struct cleanup *old_chain;
+ enum command_control_type ret;
+ enum misc_command_type val;
+
+ if (readline_begin_hook)
+ {
+ /* Note - intentional to merge messages with no newline */
+ (*readline_begin_hook) ("%s %s\n", prompt, END_MESSAGE);
+ }
+ else if (from_tty && input_from_terminal_p ())
+ {
+ printf_unfiltered ("%s\n%s\n", prompt, END_MESSAGE);
+ gdb_flush (gdb_stdout);
+ }
+
+ head = tail = NULL;
+ old_chain = NULL;
+
+ while (1)
+ {
+ val = read_next_line (&next);
+
+ /* Ignore blank lines or comments. */
+ if (val == nop_command)
+ continue;
+
+ if (val == end_command)
+ {
+ ret = simple_control;
+ break;
+ }
+
+ if (val != ok_command)
+ {
+ ret = invalid_control;
+ break;
+ }
+
+ if (next->control_type == while_control
+ || next->control_type == if_control)
+ {
+ control_level++;
+ ret = recurse_read_control_structure (next);
+ control_level--;
+
+ if (ret == invalid_control)
+ break;
+ }
+
+ if (tail)
+ {
+ tail->next = next;
+ }
+ else
+ {
+ head = next;
+ old_chain = make_cleanup ((make_cleanup_func) free_command_lines,
+ &head);
+ }
+ tail = next;
+ }
+
+ dont_repeat ();
+
+ if (head)
+ {
+ if (ret != invalid_control)
+ {
+ discard_cleanups (old_chain);
+ }
+ else
+ do_cleanups (old_chain);
+ }
+
+ if (readline_end_hook)
+ {
+ (*readline_end_hook) ();
+ }
+ return (head);
+}
+
+/* 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;
+ struct command_line **blist;
+ int i;
+
+ while (l)
+ {
+ if (l->body_count > 0)
+ {
+ blist = l->body_list;
+ for (i = 0; i < l->body_count; i++, blist++)
+ free_command_lines (blist);
+ }
+ 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_unfiltered ("\"info\" must be followed by the name of an info command.\n");
+ help_list (infolist, "info ", -1, gdb_stdout);
+}
+
+/* The "complete" command is used by Emacs to implement completion. */
+
+/* ARGSUSED */
+static void
+complete_command (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ int i;
+ int argpoint;
+ char *completion;
+
+ dont_repeat ();
+
+ if (arg == NULL)
+ arg = "";
+ argpoint = strlen (arg);
+
+ for (completion = line_completion_function (arg, i = 0, arg, argpoint);
+ completion;
+ completion = line_completion_function (arg, ++i, arg, argpoint))
+ {
+ printf_unfiltered ("%s\n", completion);
+ free (completion);
+ }
+}
+
+/* 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, gdb_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 != '-' && *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;
+ char tmpbuf[128];
+#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? "))
+ 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);
+
+ control_level = 0;
+ sprintf (tmpbuf, "Type commands for definition of \"%s\".", comname);
+ cmds = read_command_lines (tmpbuf, from_tty);
+
+ 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;
+ char tmpbuf[128];
+
+ validate_comname (comname);
+
+ c = lookup_cmd (&tem, cmdlist, "", 0, 1);
+
+ if (c->class != class_user)
+ error ("Command \"%s\" is built-in.", comname);
+
+ sprintf (tmpbuf, "Type documentation for \"%s\".", comname);
+ doclines = read_command_lines (tmpbuf, from_tty);
+
+ 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);
+}
+
+/* Print the GDB banner. */
+void
+print_gdb_version (stream)
+ GDB_FILE *stream;
+{
+ /* From GNU coding standards, first line is meant to be easy for a
+ program to parse, and is just canonical program name and version
+ number, which starts after last space. */
+
+ fprintf_filtered (stream, "GNU gdb %s\n", version);
+
+ /* Second line is a copyright notice. */
+
+ fprintf_filtered (stream, "Copyright 1998 Free Software Foundation, Inc.\n");
+
+ /* Following the copyright is a brief statement that the program is
+ free software, that users are free to copy and change it on
+ certain conditions, that it is covered by the GNU GPL, and that
+ there is no warranty. */
+
+ fprintf_filtered (stream, "\
+GDB is free software, covered by the GNU General Public License, and you are\n\
+welcome to change it and/or distribute copies of it under certain conditions.\n\
+Type \"show copying\" to see the conditions.\n\
+There is absolutely no warranty for GDB. Type \"show warranty\" for details.\n");
+
+ /* After the required info we print the configuration information. */
+
+ fprintf_filtered (stream, "This GDB was configured as \"");
+ if (!STREQ (host_name, target_name))
+ {
+ fprintf_filtered (stream, "--host=%s --target=%s", host_name, target_name);
+ }
+ else
+ {
+ fprintf_filtered (stream, "%s", host_name);
+ }
+ fprintf_filtered (stream, "\".");
+}
+
+/* ARGSUSED */
+static void
+show_version (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ immediate_quit++;
+ print_gdb_version (gdb_stdout);
+ printf_filtered ("\n");
+ immediate_quit--;
+}
+
+/* xgdb calls this to reprint the usual GDB prompt. Obsolete now that xgdb
+ is obsolete. */
+
+void
+print_prompt ()
+{
+ printf_unfiltered ("%s", prompt);
+ gdb_flush (gdb_stdout);
+}
+
+/* This replaces the above for the frontends: it returns a pointer
+ to the prompt. */
+char *
+get_prompt ()
+{
+ return prompt;
+}
+
+void
+set_prompt (s)
+ char *s;
+{
+/* ??rehrauer: I don't know why this fails, since it looks as though
+ assignments to prompt are wrapped in calls to savestring...
+ if (prompt != NULL)
+ free (prompt);
+*/
+ prompt = savestring (s, strlen (s));
+}
+
+
+/* If necessary, make the user confirm that we should quit. Return
+ non-zero if we should quit, zero if we shouldn't. */
+
+int
+quit_confirm ()
+{
+ if (inferior_pid != 0 && target_has_execution)
+ {
+ char *s;
+
+ /* This is something of a hack. But there's no reliable way to
+ see if a GUI is running. The `use_windows' variable doesn't
+ cut it. */
+ if (init_ui_hook)
+ s = "A debugging session is active.\nDo you still want to close the debugger?";
+ else if (attach_flag)
+ s = "The program is running. Quit anyway (and detach it)? ";
+ else
+ s = "The program is running. Exit anyway? ";
+
+ if (! query (s))
+ return 0;
+ }
+
+ return 1;
+}
+
+/* Quit without asking for confirmation. */
+
+void
+quit_force (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ int exit_code = 0;
+
+ /* An optional expression may be used to cause gdb to terminate with the
+ value of that expression. */
+ if (args)
+ {
+ value_ptr val = parse_and_eval (args);
+
+ exit_code = (int) value_as_long (val);
+ }
+
+ if (inferior_pid != 0 && target_has_execution)
+ {
+ if (attach_flag)
+ target_detach (args, from_tty);
+ else
+ target_kill ();
+ }
+
+ /* UDI wants this, to kill the TIP. */
+ target_close (1);
+
+ /* Save the history information if it is appropriate to do so. */
+ if (write_history_p && history_filename)
+ write_history (history_filename);
+
+ do_final_cleanups(ALL_CLEANUPS); /* Do any final cleanups before exiting */
+
+#if defined(TUI)
+ /* tuiDo((TuiOpaqueFuncPtr)tuiCleanUp); */
+ /* The above does not need to be inside a tuiDo(), since
+ * it is not manipulating the curses screen, but rather,
+ * it is tearing it down.
+ */
+ if (tui_version)
+ tuiCleanUp();
+#endif
+
+ exit (exit_code);
+}
+
+/* Handle the quit command. */
+
+void
+quit_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ if (! quit_confirm ())
+ error ("Not confirmed.");
+ quit_force (args, from_tty);
+}
+
+/* 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 (gdb_dirbuf, sizeof (gdb_dirbuf));
+
+ if (!STREQ (gdb_dirbuf, current_directory))
+ printf_unfiltered ("Working directory %s\n (canonically %s).\n",
+ current_directory, gdb_dirbuf);
+ else
+ printf_unfiltered ("Working directory %s.\n", current_directory);
+}
+
+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 && SLASH_P(dir[len-1])));
+ if (ROOTED_P(dir))
+ current_directory = dir;
+ else
+ {
+ if (SLASH_P (current_directory[0]) && current_directory[1] == '\0')
+ current_directory = concat (current_directory, dir, NULL);
+ else
+ current_directory = concat (current_directory, SLASH_STRING, dir, NULL);
+ free (dir);
+ }
+
+ /* Now simplify any occurrences of `.' and `..' in the pathname. */
+
+ found_real_path = 0;
+ for (p = current_directory; *p;)
+ {
+ if (SLASH_P (p[0]) && p[1] == '.' && (p[2] == 0 || SLASH_P (p[2])))
+ strcpy (p, p + 2);
+ else if (SLASH_P (p[0]) && p[1] == '.' && p[2] == '.'
+ && (p[3] == 0 || SLASH_P (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 && ! SLASH_P (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);
+}
+
+struct source_cleanup_lines_args {
+ int old_line;
+ char *old_file;
+ char *old_pre_error;
+ char *old_error_pre_print;
+};
+
+static void
+source_cleanup_lines (args)
+ PTR args;
+{
+ struct source_cleanup_lines_args *p =
+ (struct source_cleanup_lines_args *)args;
+ source_line_number = p->old_line;
+ source_file_name = p->old_file;
+ source_pre_error = p->old_pre_error;
+ error_pre_print = p->old_error_pre_print;
+}
+
+/* ARGSUSED */
+void
+source_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ FILE *stream;
+ struct cleanup *old_cleanups;
+ char *file = args;
+ struct source_cleanup_lines_args old_lines;
+ int needed_length;
+
+ if (file == NULL)
+ {
+ error ("source command requires pathname of file to source.");
+ }
+
+ file = tilde_expand (file);
+ old_cleanups = make_cleanup (free, file);
+
+ stream = fopen (file, FOPEN_RT);
+ if (!stream)
+ if (from_tty)
+ perror_with_name (file);
+ else
+ return;
+
+ make_cleanup ((make_cleanup_func) fclose, stream);
+
+ old_lines.old_line = source_line_number;
+ old_lines.old_file = source_file_name;
+ old_lines.old_pre_error = source_pre_error;
+ old_lines.old_error_pre_print = error_pre_print;
+ make_cleanup (source_cleanup_lines, &old_lines);
+ source_line_number = 0;
+ source_file_name = file;
+ source_pre_error = error_pre_print == NULL ? "" : error_pre_print;
+ source_pre_error = savestring (source_pre_error, strlen (source_pre_error));
+ make_cleanup (free, source_pre_error);
+ /* This will get set every time we read a line. So it won't stay "" for
+ long. */
+ error_pre_print = "";
+
+ needed_length = strlen (source_file_name) + strlen (source_pre_error) + 80;
+ if (source_error_allocated < needed_length)
+ {
+ source_error_allocated *= 2;
+ if (source_error_allocated < needed_length)
+ source_error_allocated = needed_length;
+ if (source_error == NULL)
+ source_error = xmalloc (source_error_allocated);
+ else
+ source_error = xrealloc (source_error, source_error_allocated);
+ }
+
+ read_command_file (stream);
+
+ do_cleanups (old_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 ("");
+ gdb_flush (gdb_stdout);
+}
+
+/* ARGSUSED */
+static void
+dont_repeat_command (ignored, from_tty)
+ char *ignored;
+ int from_tty;
+{
+ *line = 0; /* Can't call dont_repeat here because we're not
+ necessarily reading from stdin. */
+}
+
+/* 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 HIST_ENTRY *history_get PARAMS ((int));
+
+ /* 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_unfiltered ("\"set history\" must be followed by the name of a history subcommand.\n");
+ help_list (sethistlist, "set history ", -1, gdb_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.");
+}
+
+
+static void
+init_cmd_lists ()
+{
+ cmdlist = NULL;
+ infolist = NULL;
+ enablelist = NULL;
+ disablelist = NULL;
+ togglelist = NULL;
+ stoplist = 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.
+ */
+
+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 (*)()) readline_line_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);
+ if (!dbx_commands)
+ 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 may have up to ten 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);
+
+ add_com ("dont-repeat", class_support, dont_repeat_command, "Don't repeat this command.\n\
+Primarily used inside of user-defined commands that should not be repeated when\n\
+hitting return.");
+
+ 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 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 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_com ("complete", class_obscure, complete_command,
+ "List the completions for the rest of the line as a command.");
+
+ 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 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_com ("while", class_support, while_command,
+"Execute nested commands WHILE the conditional expression is non zero.\n\
+The conditional expression must follow the word `while' and must in turn be\n\
+followed by a new line. The nested commands must be entered one per line,\n\
+and should be terminated by the word `end'.");
+
+ add_com ("if", class_support, if_command,
+"Execute nested commands once IF the conditional expression is non zero.\n\
+The conditional expression must follow the word `if' and must in turn be\n\
+followed by a new line. The nested commands must be entered one per line,\n\
+and should be terminated by the word 'else' or `end'. If an else clause\n\
+is used, the same rules apply to its nested commands as to the first ones.");
+
+ /* If target is open when baud changes, it doesn't take effect until the
+ next open (I think, not sure). */
+ 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);
+
+ add_show_from_set (
+ add_set_cmd ("remotedebug", no_class, var_zinteger, (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);
+
+ add_show_from_set (
+ add_set_cmd ("remotetimeout", no_class, var_integer, (char *)&remote_timeout,
+ "Set timeout limit to wait for target to respond.\n\
+This value is used to set the time limit for gdb to wait for a response\n\
+from the target.", &setlist),
+ &showlist);
+
+ c = add_set_cmd ("annotate", class_obscure, var_zinteger,
+ (char *)&annotation_level, "Set annotation_level.\n\
+0 == normal; 1 == fullname (for use when running under emacs)\n\
+2 == output annotated suitably for use by programs that control GDB.",
+ &setlist);
+ c = add_show_from_set (c, &showlist);
+}
diff --git a/gdb/top.h b/gdb/top.h
new file mode 100644
index 00000000000..fe7002b6091
--- /dev/null
+++ b/gdb/top.h
@@ -0,0 +1,67 @@
+/* Top level stuff for GDB, the GNU debugger.
+ Copyright 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* From top.c. */
+extern char *line;
+extern int linesize;
+extern FILE *instream;
+extern char gdb_dirbuf[1024];
+extern int inhibit_gdbinit;
+extern int epoch_interface;
+extern char gdbinit[];
+
+/* Generally one should use catch_errors rather than manipulating these
+ directly. The exception is main(). */
+#if defined(HAVE_SIGSETJMP)
+#define SIGJMP_BUF sigjmp_buf
+#define SIGSETJMP(buf) sigsetjmp(buf, 1)
+#define SIGLONGJMP(buf,val) siglongjmp(buf,val)
+#else
+#define SIGJMP_BUF jmp_buf
+#define SIGSETJMP(buf) setjmp(buf)
+#define SIGLONGJMP(buf,val) longjmp(buf,val)
+#endif
+
+extern SIGJMP_BUF error_return;
+extern SIGJMP_BUF quit_return;
+
+extern void print_gdb_version PARAMS ((GDB_FILE *));
+
+extern void source_command PARAMS ((char *, int));
+extern void cd_command PARAMS ((char *, int));
+extern void read_command_file PARAMS ((FILE *));
+extern void init_history PARAMS ((void));
+extern void command_loop PARAMS ((void));
+extern int quit_confirm PARAMS ((void));
+extern void quit_force PARAMS ((char *, int));
+extern void quit_command PARAMS ((char *, int));
+
+/* This function returns a pointer to the string that is used
+ by gdb for its command prompt. */
+extern char *get_prompt PARAMS((void));
+
+/* This function copies the specified string into the string that
+ is used by gdb for its command prompt. */
+extern void set_prompt PARAMS ((char *));
+
+/* From random places. */
+extern int mapped_symbol_files;
+extern int readnow_symbol_files;
+#define ALL_CLEANUPS ((struct cleanup *)0)
diff --git a/gdb/tracepoint.c b/gdb/tracepoint.c
new file mode 100644
index 00000000000..9f036178bd1
--- /dev/null
+++ b/gdb/tracepoint.c
@@ -0,0 +1,2780 @@
+/* Tracing functionality for remote targets in custom GDB protocol
+ Copyright 1997, 1998 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "symtab.h"
+#include "frame.h"
+#include "tracepoint.h"
+#include "gdbtypes.h"
+#include "expression.h"
+#include "gdbcmd.h"
+#include "value.h"
+#include "target.h"
+#include "language.h"
+#include "gdb_string.h"
+
+#include "ax.h"
+#include "ax-gdb.h"
+
+/* readline include files */
+#include <readline/readline.h>
+#include <readline/history.h>
+
+/* readline defines this. */
+#undef savestring
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+/* maximum length of an agent aexpression.
+ this accounts for the fact that packets are limited to 400 bytes
+ (which includes everything -- including the checksum), and assumes
+ the worst case of maximum length for each of the pieces of a
+ continuation packet.
+
+ NOTE: expressions get mem2hex'ed otherwise this would be twice as
+ large. (400 - 31)/2 == 184 */
+#define MAX_AGENT_EXPR_LEN 184
+
+
+extern int info_verbose;
+extern void (*readline_begin_hook) PARAMS ((char *, ...));
+extern char * (*readline_hook) PARAMS ((char *));
+extern void (*readline_end_hook) PARAMS ((void));
+extern void x_command PARAMS ((char *, int));
+extern int addressprint; /* Print machine addresses? */
+
+/* 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
+
+/*
+ Tracepoint.c:
+
+ This module defines the following debugger commands:
+ trace : set a tracepoint on a function, line, or address.
+ info trace : list all debugger-defined tracepoints.
+ delete trace : delete one or more tracepoints.
+ enable trace : enable one or more tracepoints.
+ disable trace : disable one or more tracepoints.
+ actions : specify actions to be taken at a tracepoint.
+ passcount : specify a pass count for a tracepoint.
+ tstart : start a trace experiment.
+ tstop : stop a trace experiment.
+ tstatus : query the status of a trace experiment.
+ tfind : find a trace frame in the trace buffer.
+ tdump : print everything collected at the current tracepoint.
+ save-tracepoints : write tracepoint setup into a file.
+
+ This module defines the following user-visible debugger variables:
+ $trace_frame : sequence number of trace frame currently being debugged.
+ $trace_line : source line of trace frame currently being debugged.
+ $trace_file : source file of trace frame currently being debugged.
+ $tracepoint : tracepoint number of trace frame currently being debugged.
+ */
+
+
+/* ======= Important global variables: ======= */
+
+/* Chain of all tracepoints defined. */
+struct tracepoint *tracepoint_chain;
+
+/* Number of last tracepoint made. */
+static int tracepoint_count;
+
+/* Number of last traceframe collected. */
+static int traceframe_number;
+
+/* Tracepoint for last traceframe collected. */
+static int tracepoint_number;
+
+/* Symbol for function for last traceframe collected */
+static struct symbol *traceframe_fun;
+
+/* Symtab and line for last traceframe collected */
+static struct symtab_and_line traceframe_sal;
+
+/* Tracing command lists */
+static struct cmd_list_element *tfindlist;
+
+/* ======= Important command functions: ======= */
+static void trace_command PARAMS ((char *, int));
+static void tracepoints_info PARAMS ((char *, int));
+static void delete_trace_command PARAMS ((char *, int));
+static void enable_trace_command PARAMS ((char *, int));
+static void disable_trace_command PARAMS ((char *, int));
+static void trace_pass_command PARAMS ((char *, int));
+static void trace_actions_command PARAMS ((char *, int));
+static void trace_start_command PARAMS ((char *, int));
+static void trace_stop_command PARAMS ((char *, int));
+static void trace_status_command PARAMS ((char *, int));
+static void trace_find_command PARAMS ((char *, int));
+static void trace_find_pc_command PARAMS ((char *, int));
+static void trace_find_tracepoint_command PARAMS ((char *, int));
+static void trace_find_line_command PARAMS ((char *, int));
+static void trace_find_range_command PARAMS ((char *, int));
+static void trace_find_outside_command PARAMS ((char *, int));
+static void tracepoint_save_command PARAMS ((char *, int));
+static void trace_dump_command PARAMS ((char *, int));
+
+/* support routines */
+static void trace_mention PARAMS ((struct tracepoint *));
+
+struct collection_list;
+static void add_aexpr PARAMS ((struct collection_list *, struct agent_expr *));
+static unsigned char *mem2hex(unsigned char *, unsigned char *, int);
+
+/* Utility: returns true if "target remote" */
+static int
+target_is_remote ()
+{
+ if (current_target.to_shortname &&
+ strcmp (current_target.to_shortname, "remote") == 0)
+ return 1;
+ else
+ return 0;
+}
+
+/* Utility: generate error from an incoming stub packet. */
+static void
+trace_error (buf)
+ char *buf;
+{
+ if (*buf++ != 'E')
+ return; /* not an error msg */
+ switch (*buf)
+ {
+ case '1': /* malformed packet error */
+ if (*++buf == '0') /* general case: */
+ error ("tracepoint.c: error in outgoing packet.");
+ else
+ error ("tracepoint.c: error in outgoing packet at field #%d.",
+ strtol (buf, NULL, 16));
+ case '2':
+ error ("trace API error 0x%s.", ++buf);
+ default:
+ error ("Target returns error code '%s'.", buf);
+ }
+}
+
+/* Utility: wait for reply from stub, while accepting "O" packets */
+static char *
+remote_get_noisy_reply (buf)
+ char *buf;
+{
+ do /* loop on reply from remote stub */
+ {
+ QUIT; /* allow user to bail out with ^C */
+ getpkt (buf, 0);
+ if (buf[0] == 0)
+ error ("Target does not support this command.");
+ else if (buf[0] == 'E')
+ trace_error (buf);
+ else if (buf[0] == 'O' &&
+ buf[1] != 'K')
+ remote_console_output (buf + 1); /* 'O' message from stub */
+ else
+ return buf; /* here's the actual reply */
+ } while (1);
+}
+
+/* Set tracepoint count to NUM. */
+static void
+set_tracepoint_count (num)
+ int num;
+{
+ tracepoint_count = num;
+ set_internalvar (lookup_internalvar ("tpnum"),
+ value_from_longest (builtin_type_int, (LONGEST) num));
+}
+
+/* Set traceframe number to NUM. */
+static void
+set_traceframe_num (num)
+ int num;
+{
+ traceframe_number = num;
+ set_internalvar (lookup_internalvar ("trace_frame"),
+ value_from_longest (builtin_type_int, (LONGEST) num));
+}
+
+/* Set tracepoint number to NUM. */
+static void
+set_tracepoint_num (num)
+ int num;
+{
+ tracepoint_number = num;
+ set_internalvar (lookup_internalvar ("tracepoint"),
+ value_from_longest (builtin_type_int, (LONGEST) num));
+}
+
+/* Set externally visible debug variables for querying/printing
+ the traceframe context (line, function, file) */
+
+static void
+set_traceframe_context (trace_pc)
+ CORE_ADDR trace_pc;
+{
+ static struct type *func_string, *file_string;
+ static struct type *func_range, *file_range;
+ static value_ptr func_val, file_val;
+ static struct type *charstar;
+ int len;
+
+ if (charstar == (struct type *) NULL)
+ charstar = lookup_pointer_type (builtin_type_char);
+
+ if (trace_pc == -1) /* cease debugging any trace buffers */
+ {
+ traceframe_fun = 0;
+ traceframe_sal.pc = traceframe_sal.line = 0;
+ traceframe_sal.symtab = NULL;
+ set_internalvar (lookup_internalvar ("trace_func"),
+ value_from_longest (charstar, (LONGEST) 0));
+ set_internalvar (lookup_internalvar ("trace_file"),
+ value_from_longest (charstar, (LONGEST) 0));
+ set_internalvar (lookup_internalvar ("trace_line"),
+ value_from_longest (builtin_type_int, (LONGEST) -1));
+ return;
+ }
+
+ /* save as globals for internal use */
+ traceframe_sal = find_pc_line (trace_pc, 0);
+ traceframe_fun = find_pc_function (trace_pc);
+
+ /* save linenumber as "$trace_line", a debugger variable visible to users */
+ set_internalvar (lookup_internalvar ("trace_line"),
+ value_from_longest (builtin_type_int,
+ (LONGEST) traceframe_sal.line));
+
+ /* save func name as "$trace_func", a debugger variable visible to users */
+ if (traceframe_fun == NULL ||
+ SYMBOL_NAME (traceframe_fun) == NULL)
+ set_internalvar (lookup_internalvar ("trace_func"),
+ value_from_longest (charstar, (LONGEST) 0));
+ else
+ {
+ len = strlen (SYMBOL_NAME (traceframe_fun));
+ func_range = create_range_type (func_range,
+ builtin_type_int, 0, len - 1);
+ func_string = create_array_type (func_string,
+ builtin_type_char, func_range);
+ func_val = allocate_value (func_string);
+ VALUE_TYPE (func_val) = func_string;
+ memcpy (VALUE_CONTENTS_RAW (func_val),
+ SYMBOL_NAME (traceframe_fun),
+ len);
+ func_val->modifiable = 0;
+ set_internalvar (lookup_internalvar ("trace_func"), func_val);
+ }
+
+ /* save file name as "$trace_file", a debugger variable visible to users */
+ if (traceframe_sal.symtab == NULL ||
+ traceframe_sal.symtab->filename == NULL)
+ set_internalvar (lookup_internalvar ("trace_file"),
+ value_from_longest (charstar, (LONGEST) 0));
+ else
+ {
+ len = strlen (traceframe_sal.symtab->filename);
+ file_range = create_range_type (file_range,
+ builtin_type_int, 0, len - 1);
+ file_string = create_array_type (file_string,
+ builtin_type_char, file_range);
+ file_val = allocate_value (file_string);
+ VALUE_TYPE (file_val) = file_string;
+ memcpy (VALUE_CONTENTS_RAW (file_val),
+ traceframe_sal.symtab->filename,
+ len);
+ file_val->modifiable = 0;
+ set_internalvar (lookup_internalvar ("trace_file"), file_val);
+ }
+}
+
+/* Low level routine to set a tracepoint.
+ Returns the tracepoint object so caller can set other things.
+ Does not set the tracepoint number!
+ Does not print anything.
+
+ ==> This routine should not be called if there is a chance of later
+ error(); otherwise it leaves a bogus tracepoint on the chain. Validate
+ your arguments BEFORE calling this routine! */
+
+static struct tracepoint *
+set_raw_tracepoint (sal)
+ struct symtab_and_line sal;
+{
+ register struct tracepoint *t, *tc;
+ struct cleanup *old_chain;
+
+ t = (struct tracepoint *) xmalloc (sizeof (struct tracepoint));
+ old_chain = make_cleanup (free, t);
+ memset (t, 0, sizeof (*t));
+ t->address = sal.pc;
+ if (sal.symtab == NULL)
+ t->source_file = NULL;
+ else
+ t->source_file = savestring (sal.symtab->filename,
+ strlen (sal.symtab->filename));
+
+ t->section = sal.section;
+ t->language = current_language->la_language;
+ t->input_radix = input_radix;
+ t->line_number = sal.line;
+ t->enabled = enabled;
+ t->next = 0;
+ t->step_count = 0;
+ t->pass_count = 0;
+ t->addr_string = NULL;
+
+ /* Add this tracepoint to the end of the chain
+ so that a list of tracepoints will come out in order
+ of increasing numbers. */
+
+ tc = tracepoint_chain;
+ if (tc == 0)
+ tracepoint_chain = t;
+ else
+ {
+ while (tc->next)
+ tc = tc->next;
+ tc->next = t;
+ }
+ discard_cleanups (old_chain);
+ return t;
+}
+
+/* Set a tracepoint according to ARG (function, linenum or *address) */
+static void
+trace_command (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ char **canonical = (char **)NULL;
+ struct symtabs_and_lines sals;
+ struct symtab_and_line sal;
+ struct tracepoint *t;
+ char *addr_start = 0, *addr_end = 0;
+ int i;
+
+ if (!arg || !*arg)
+ error ("trace command requires an argument");
+
+ if (from_tty && info_verbose)
+ printf_filtered ("TRACE %s\n", arg);
+
+ addr_start = arg;
+ sals = decode_line_1 (&arg, 1, (struct symtab *)NULL, 0, &canonical);
+ addr_end = arg;
+ if (! sals.nelts)
+ return; /* ??? Presumably decode_line_1 has already warned? */
+
+ /* Resolve all line numbers to PC's */
+ for (i = 0; i < sals.nelts; i++)
+ resolve_sal_pc (&sals.sals[i]);
+
+ /* Now set all the tracepoints. */
+ for (i = 0; i < sals.nelts; i++)
+ {
+ sal = sals.sals[i];
+
+ t = set_raw_tracepoint (sal);
+ set_tracepoint_count (tracepoint_count + 1);
+ t->number = tracepoint_count;
+
+ /* If a canonical line spec is needed use that instead of the
+ command string. */
+ if (canonical != (char **)NULL && canonical[i] != NULL)
+ t->addr_string = canonical[i];
+ else if (addr_start)
+ t->addr_string = savestring (addr_start, addr_end - addr_start);
+
+ trace_mention (t);
+
+ /* Let the UI know of any additions */
+ if (create_tracepoint_hook)
+ create_tracepoint_hook (t);
+ }
+
+ if (sals.nelts > 1)
+ {
+ printf_filtered ("Multiple tracepoints were set.\n");
+ printf_filtered ("Use 'delete trace' to delete unwanted tracepoints.\n");
+ }
+}
+
+/* Tell the user we have just set a tracepoint TP. */
+
+static void
+trace_mention (tp)
+ struct tracepoint *tp;
+{
+ printf_filtered ("Tracepoint %d", tp->number);
+
+ if (addressprint || (tp->source_file == NULL))
+ {
+ printf_filtered (" at ");
+ print_address_numeric (tp->address, 1, gdb_stdout);
+ }
+ if (tp->source_file)
+ printf_filtered (": file %s, line %d.",
+ tp->source_file, tp->line_number);
+
+ printf_filtered ("\n");
+}
+
+/* Print information on tracepoint number TPNUM_EXP, or all if omitted. */
+
+static void
+tracepoints_info (tpnum_exp, from_tty)
+ char *tpnum_exp;
+ int from_tty;
+{
+ struct tracepoint *t;
+ struct action_line *action;
+ int found_a_tracepoint = 0;
+ char wrap_indent[80];
+ struct symbol *sym;
+ int tpnum = -1;
+
+ if (tpnum_exp)
+ tpnum = parse_and_eval_address (tpnum_exp);
+
+ ALL_TRACEPOINTS (t)
+ if (tpnum == -1 || tpnum == t->number)
+ {
+ extern int addressprint; /* print machine addresses? */
+
+ if (!found_a_tracepoint++)
+ {
+ printf_filtered ("Num Enb ");
+ if (addressprint)
+ printf_filtered ("Address ");
+ printf_filtered ("PassC StepC What\n");
+ }
+ strcpy (wrap_indent, " ");
+ if (addressprint)
+ strcat (wrap_indent, " ");
+
+ printf_filtered ("%-3d %-3s ", t->number,
+ t->enabled == enabled ? "y" : "n");
+ if (addressprint)
+ printf_filtered ("%s ",
+ local_hex_string_custom ((unsigned long) t->address,
+ "08l"));
+ printf_filtered ("%-5d %-5d ", t->pass_count, t->step_count);
+
+ if (t->source_file)
+ {
+ sym = find_pc_sect_function (t->address, t->section);
+ if (sym)
+ {
+ fputs_filtered ("in ", gdb_stdout);
+ fputs_filtered (SYMBOL_SOURCE_NAME (sym), gdb_stdout);
+ wrap_here (wrap_indent);
+ fputs_filtered (" at ", gdb_stdout);
+ }
+ fputs_filtered (t->source_file, gdb_stdout);
+ printf_filtered (":%d", t->line_number);
+ }
+ else
+ print_address_symbolic (t->address, gdb_stdout, demangle, " ");
+
+ printf_filtered ("\n");
+ if (t->actions)
+ {
+ printf_filtered (" Actions for tracepoint %d: \n", t->number);
+ for (action = t->actions; action; action = action->next)
+ {
+ printf_filtered ("\t%s\n", action->action);
+ }
+ }
+ }
+ if (!found_a_tracepoint)
+ {
+ if (tpnum == -1)
+ printf_filtered ("No tracepoints.\n");
+ else
+ printf_filtered ("No tracepoint number %d.\n", tpnum);
+ }
+}
+
+/* Optimization: the code to parse an enable, disable, or delete TP command
+ is virtually identical except for whether it performs an enable, disable,
+ or delete. Therefore I've combined them into one function with an opcode.
+ */
+enum tracepoint_opcode
+{
+ enable,
+ disable,
+ delete
+};
+
+/* This function implements enable, disable and delete. */
+static void
+tracepoint_operation (t, from_tty, opcode)
+ struct tracepoint *t;
+ int from_tty;
+ enum tracepoint_opcode opcode;
+{
+ struct tracepoint *t2;
+
+ switch (opcode) {
+ case enable:
+ t->enabled = enabled;
+ if (modify_tracepoint_hook)
+ modify_tracepoint_hook (t);
+ break;
+ case disable:
+ t->enabled = disabled;
+ if (modify_tracepoint_hook)
+ modify_tracepoint_hook (t);
+ break;
+ case delete:
+ if (tracepoint_chain == t)
+ tracepoint_chain = t->next;
+
+ ALL_TRACEPOINTS (t2)
+ if (t2->next == t)
+ {
+ t2->next = t->next;
+ break;
+ }
+
+ /* Let the UI know of any deletions */
+ if (delete_tracepoint_hook)
+ delete_tracepoint_hook (t);
+
+ if (t->addr_string)
+ free (t->addr_string);
+ if (t->source_file)
+ free (t->source_file);
+ if (t->actions)
+ free_actions (t);
+
+ free (t);
+ break;
+ }
+}
+
+/* Utility: parse a tracepoint number and look it up in the list. */
+struct tracepoint *
+get_tracepoint_by_number (arg)
+ char **arg;
+{
+ struct tracepoint *t;
+ char *end, *copy;
+ value_ptr val;
+ int tpnum;
+
+ if (arg == 0)
+ error ("Bad tracepoint argument");
+
+ if (*arg == 0 || **arg == 0) /* empty arg means refer to last tp */
+ tpnum = tracepoint_count;
+ else if (**arg == '$') /* handle convenience variable */
+ {
+ /* Make a copy of the name, so we can null-terminate it
+ to pass to lookup_internalvar(). */
+ end = *arg + 1;
+ while (isalnum(*end) || *end == '_')
+ end++;
+ copy = (char *) alloca (end - *arg);
+ strncpy (copy, *arg + 1, (end - *arg - 1));
+ copy[end - *arg - 1] = '\0';
+ *arg = end;
+
+ val = value_of_internalvar (lookup_internalvar (copy));
+ if (TYPE_CODE( VALUE_TYPE (val)) != TYPE_CODE_INT)
+ error ("Convenience variable must have integral type.");
+ tpnum = (int) value_as_long (val);
+ }
+ else /* handle tracepoint number */
+ {
+ tpnum = strtol (*arg, arg, 0);
+ if (tpnum == 0) /* possible strtol failure */
+ while (**arg && !isspace (**arg))
+ (*arg)++; /* advance to next white space, if any */
+ }
+ ALL_TRACEPOINTS (t)
+ if (t->number == tpnum)
+ {
+ return t;
+ }
+ printf_unfiltered ("No tracepoint number %d.\n", tpnum);
+ return NULL;
+}
+
+/* Utility: parse a list of tracepoint numbers, and call a func for each. */
+static void
+map_args_over_tracepoints (args, from_tty, opcode)
+ char *args;
+ int from_tty;
+ enum tracepoint_opcode opcode;
+{
+ struct tracepoint *t, *tmp;
+ int tpnum;
+ char *cp;
+
+ if (args == 0 || *args == 0) /* do them all */
+ ALL_TRACEPOINTS_SAFE (t, tmp)
+ tracepoint_operation (t, from_tty, opcode);
+ else
+ while (*args)
+ {
+ QUIT; /* give user option to bail out with ^C */
+ if (t = get_tracepoint_by_number (&args))
+ tracepoint_operation (t, from_tty, opcode);
+ while (*args == ' ' || *args == '\t')
+ args++;
+ }
+}
+
+/* The 'enable trace' command enables tracepoints. Not supported by all targets. */
+static void
+enable_trace_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ dont_repeat ();
+ map_args_over_tracepoints (args, from_tty, enable);
+}
+
+/* The 'disable trace' command enables tracepoints. Not supported by all targets. */
+static void
+disable_trace_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ dont_repeat ();
+ map_args_over_tracepoints (args, from_tty, disable);
+}
+
+/* Remove a tracepoint (or all if no argument) */
+static void
+delete_trace_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ dont_repeat ();
+ if (!args || !*args) /* No args implies all tracepoints; */
+ if (from_tty) /* confirm only if from_tty... */
+ if (tracepoint_chain) /* and if there are tracepoints to delete! */
+ if (!query ("Delete all tracepoints? "))
+ return;
+
+ map_args_over_tracepoints (args, from_tty, delete);
+}
+
+/* Set passcount for tracepoint.
+
+ First command argument is passcount, second is tracepoint number.
+ If tracepoint number omitted, apply to most recently defined.
+ Also accepts special argument "all". */
+
+static void
+trace_pass_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ struct tracepoint *t1 = (struct tracepoint *) -1, *t2;
+ unsigned long count;
+
+ if (args == 0 || *args == 0)
+ error ("PASS command requires an argument (count + optional TP num)");
+
+ count = strtoul (args, &args, 10); /* count comes first, then TP num */
+
+ while (*args && isspace (*args))
+ args++;
+
+ if (*args && strncasecmp (args, "all", 3) == 0)
+ args += 3; /* skip special argument "all" */
+ else
+ t1 = get_tracepoint_by_number (&args);
+
+ if (*args)
+ error ("Junk at end of arguments.");
+
+ if (t1 == NULL)
+ return; /* error, bad tracepoint number */
+
+ ALL_TRACEPOINTS (t2)
+ if (t1 == (struct tracepoint *) -1 || t1 == t2)
+ {
+ t2->pass_count = count;
+ if (modify_tracepoint_hook)
+ modify_tracepoint_hook (t2);
+ if (from_tty)
+ printf_filtered ("Setting tracepoint %d's passcount to %d\n",
+ t2->number, count);
+ }
+}
+
+/* ACTIONS functions: */
+
+/* Prototypes for action-parsing utility commands */
+static void read_actions PARAMS((struct tracepoint *));
+static char *parse_and_eval_memrange PARAMS ((char *,
+ CORE_ADDR,
+ long *,
+ bfd_signed_vma *,
+ long *));
+
+/* The three functions:
+ collect_pseudocommand,
+ while_stepping_pseudocommand, and
+ end_actions_pseudocommand
+ are placeholders for "commands" that are actually ONLY to be used
+ within a tracepoint action list. If the actual function is ever called,
+ it means that somebody issued the "command" at the top level,
+ which is always an error. */
+
+static void
+end_actions_pseudocommand (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ error ("This command cannot be used at the top level.");
+}
+
+static void
+while_stepping_pseudocommand (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ error ("This command can only be used in a tracepoint actions list.");
+}
+
+static void
+collect_pseudocommand (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ error ("This command can only be used in a tracepoint actions list.");
+}
+
+/* Enter a list of actions for a tracepoint. */
+static void
+trace_actions_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ struct tracepoint *t;
+ char *actions;
+ char tmpbuf[128];
+ char *end_msg = "End with a line saying just \"end\".";
+
+ if (t = get_tracepoint_by_number (&args))
+ {
+ sprintf (tmpbuf, "Enter actions for tracepoint %d, one per line.",
+ t->number);
+
+ if (from_tty)
+ {
+ if (readline_begin_hook)
+ (*readline_begin_hook) ("%s %s\n", tmpbuf, end_msg);
+ else if (input_from_terminal_p ())
+ printf_filtered ("%s\n%s\n", tmpbuf, end_msg);
+ }
+
+ free_actions (t);
+ t->step_count = 0; /* read_actions may set this */
+ read_actions (t);
+
+ if (readline_end_hook)
+ (*readline_end_hook) ();
+
+ /* tracepoints_changed () */
+ }
+ /* else error, just return; */
+}
+
+/* worker function */
+static void
+read_actions (t)
+ struct tracepoint *t;
+{
+ char *line;
+ char *prompt1 = "> ", *prompt2 = " > ";
+ char *prompt = prompt1;
+ enum actionline_type linetype;
+ extern FILE *instream;
+ struct action_line *next = NULL, *temp;
+ struct cleanup *old_chain;
+
+ /* 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
+ old_chain = make_cleanup ((make_cleanup_func) free_actions, (void *) t);
+ while (1)
+ {
+ /* Make sure that all output has been output. Some machines may let
+ you get away with leaving out some of the gdb_flush, but not all. */
+ wrap_here ("");
+ gdb_flush (gdb_stdout);
+ gdb_flush (gdb_stderr);
+
+ if (readline_hook && instream == NULL)
+ line = (*readline_hook) (prompt);
+ else if (instream == stdin && ISATTY (instream))
+ {
+ line = readline (prompt);
+ if (line && *line) /* add it to command history */
+ add_history (line);
+ }
+ else
+ line = gdb_readline (0);
+
+ linetype = validate_actionline (&line, t);
+ if (linetype == BADLINE)
+ continue; /* already warned -- collect another line */
+
+ temp = xmalloc (sizeof (struct action_line));
+ temp->next = NULL;
+ temp->action = line;
+
+ if (next == NULL) /* first action for this tracepoint? */
+ t->actions = next = temp;
+ else
+ {
+ next->next = temp;
+ next = temp;
+ }
+
+ if (linetype == STEPPING) /* begin "while-stepping" */
+ if (prompt == prompt2)
+ {
+ warning ("Already processing 'while-stepping'");
+ continue;
+ }
+ else
+ prompt = prompt2; /* change prompt for stepping actions */
+ else if (linetype == END)
+ if (prompt == prompt2)
+ {
+ prompt = prompt1; /* end of single-stepping actions */
+ }
+ else
+ { /* end of actions */
+ if (t->actions->next == NULL)
+ {
+ /* an "end" all by itself with no other actions means
+ this tracepoint has no actions. Discard empty list. */
+ free_actions (t);
+ }
+ break;
+ }
+ }
+#ifdef STOP_SIGNAL
+ if (job_control)
+ signal (STOP_SIGNAL, SIG_DFL);
+#endif
+ immediate_quit = 0;
+ discard_cleanups (old_chain);
+}
+
+/* worker function */
+enum actionline_type
+validate_actionline (line, t)
+ char **line;
+ struct tracepoint *t;
+{
+ struct cmd_list_element *c;
+ struct expression *exp = NULL;
+ value_ptr temp, temp2;
+ struct cleanup *old_chain = NULL;
+ char *p;
+
+ for (p = *line; isspace (*p); )
+ p++;
+
+ /* symbol lookup etc. */
+ if (*p == '\0') /* empty line: just prompt for another line. */
+ return BADLINE;
+
+ if (*p == '#') /* comment line */
+ return GENERIC;
+
+ c = lookup_cmd (&p, cmdlist, "", -1, 1);
+ if (c == 0)
+ {
+ warning ("'%s' is not an action that I know, or is ambiguous.", p);
+ return BADLINE;
+ }
+
+ if (c->function.cfunc == collect_pseudocommand)
+ {
+ struct agent_expr *aexpr;
+ struct agent_reqs areqs;
+
+ do { /* repeat over a comma-separated list */
+ QUIT; /* allow user to bail out with ^C */
+ while (isspace (*p))
+ p++;
+
+ if (*p == '$') /* look for special pseudo-symbols */
+ {
+ long typecode, size;
+ bfd_signed_vma offset;
+
+ if ((0 == strncasecmp ("reg", p + 1, 3)) ||
+ (0 == strncasecmp ("arg", p + 1, 3)) ||
+ (0 == strncasecmp ("loc", p + 1, 3)))
+ {
+ p = strchr (p, ',');
+ continue;
+ }
+ /* else fall thru, treat p as an expression and parse it! */
+ }
+ exp = parse_exp_1 (&p, block_for_pc (t->address), 1);
+ old_chain = make_cleanup ((make_cleanup_func) free_current_contents,
+ &exp);
+
+ if (exp->elts[0].opcode == OP_VAR_VALUE)
+ if (SYMBOL_CLASS (exp->elts[2].symbol) == LOC_CONST)
+ {
+ warning ("%s is constant (value %d): will not be collected.",
+ SYMBOL_NAME (exp->elts[2].symbol),
+ SYMBOL_VALUE (exp->elts[2].symbol));
+ return BADLINE;
+ }
+ else if (SYMBOL_CLASS (exp->elts[2].symbol) == LOC_OPTIMIZED_OUT)
+ {
+ warning ("%s is optimized away and cannot be collected.",
+ SYMBOL_NAME (exp->elts[2].symbol));
+ return BADLINE;
+ }
+
+ /* we have something to collect, make sure that the expr to
+ bytecode translator can handle it and that it's not too long */
+ aexpr = gen_trace_for_expr (t->address, exp);
+ (void) make_cleanup ((make_cleanup_func) free_agent_expr, aexpr);
+
+ if (aexpr->len > MAX_AGENT_EXPR_LEN)
+ error ("expression too complicated, try simplifying");
+
+ ax_reqs(aexpr, &areqs);
+ (void) make_cleanup (free, areqs.reg_mask);
+
+ if (areqs.flaw != agent_flaw_none)
+ error ("malformed expression");
+
+ if (areqs.min_height < 0)
+ error ("gdb: Internal error: expression has min height < 0");
+
+ if (areqs.max_height > 20)
+ error ("expression too complicated, try simplifying");
+
+ do_cleanups (old_chain);
+ } while (p && *p++ == ',');
+ return GENERIC;
+ }
+ else if (c->function.cfunc == while_stepping_pseudocommand)
+ {
+ char *steparg; /* in case warning is necessary */
+
+ while (isspace (*p))
+ p++;
+ steparg = p;
+
+ if (*p == '\0' ||
+ (t->step_count = strtol (p, &p, 0)) == 0)
+ {
+ warning ("bad step-count: command ignored.", *line);
+ return BADLINE;
+ }
+ return STEPPING;
+ }
+ else if (c->function.cfunc == end_actions_pseudocommand)
+ return END;
+ else
+ {
+ warning ("'%s' is not a supported tracepoint action.", *line);
+ return BADLINE;
+ }
+}
+
+/* worker function */
+void
+free_actions (t)
+ struct tracepoint *t;
+{
+ struct action_line *line, *next;
+
+ for (line = t->actions; line; line = next)
+ {
+ next = line->next;
+ if (line->action)
+ free (line->action);
+ free (line);
+ }
+ t->actions = NULL;
+}
+
+struct memrange {
+ int type; /* 0 for absolute memory range, else basereg number */
+ bfd_signed_vma start;
+ bfd_signed_vma end;
+};
+
+struct collection_list {
+ unsigned char regs_mask[8]; /* room for up to 256 regs */
+ long listsize;
+ long next_memrange;
+ struct memrange *list;
+ long aexpr_listsize; /* size of array pointed to by expr_list elt */
+ long next_aexpr_elt;
+ struct agent_expr **aexpr_list;
+
+} tracepoint_list, stepping_list;
+
+/* MEMRANGE functions: */
+
+static int memrange_cmp PARAMS ((const void *, const void *));
+
+/* compare memranges for qsort */
+static int
+memrange_cmp (va, vb)
+ const void *va;
+ const void *vb;
+{
+ const struct memrange *a = va, *b = vb;
+
+ if (a->type < b->type)
+ return -1;
+ if (a->type > b->type)
+ return 1;
+ if (a->type == 0)
+ {
+ if ((bfd_vma) a->start < (bfd_vma) b->start) return -1;
+ if ((bfd_vma) a->start > (bfd_vma) b->start) return 1;
+ }
+ else
+ {
+ if (a->start < b->start)
+ return -1;
+ if (a->start > b->start)
+ return 1;
+ }
+ return 0;
+}
+
+/* Sort the memrange list using qsort, and merge adjacent memranges */
+static void
+memrange_sortmerge (memranges)
+ struct collection_list *memranges;
+{
+ int a, b;
+
+ qsort (memranges->list, memranges->next_memrange,
+ sizeof (struct memrange), memrange_cmp);
+ if (memranges->next_memrange > 0)
+ {
+ for (a = 0, b = 1; b < memranges->next_memrange; b++)
+ {
+ if (memranges->list[a].type == memranges->list[b].type &&
+ memranges->list[b].start - memranges->list[a].end <=
+ MAX_REGISTER_VIRTUAL_SIZE)
+ {
+ /* memrange b starts before memrange a ends; merge them. */
+ if (memranges->list[b].end > memranges->list[a].end)
+ memranges->list[a].end = memranges->list[b].end;
+ continue; /* next b, same a */
+ }
+ a++; /* next a */
+ if (a != b)
+ memcpy (&memranges->list[a], &memranges->list[b],
+ sizeof (struct memrange));
+ }
+ memranges->next_memrange = a + 1;
+ }
+}
+
+/* Add a register to a collection list */
+void
+add_register (collection, regno)
+ struct collection_list *collection;
+ unsigned long regno;
+{
+ if (info_verbose)
+ printf_filtered ("collect register %d\n", regno);
+ if (regno > (8 * sizeof (collection->regs_mask)))
+ error ("Internal: register number %d too large for tracepoint",
+ regno);
+ collection->regs_mask [regno / 8] |= 1 << (regno % 8);
+}
+
+/* Add a memrange to a collection list */
+static void
+add_memrange (memranges, type, base, len)
+ struct collection_list *memranges;
+ int type;
+ bfd_signed_vma base;
+ unsigned long len;
+{
+ if (info_verbose)
+ printf_filtered ("(%d,0x%x,%d)\n", type, base, len);
+ /* type: 0 == memory, n == basereg */
+ memranges->list[memranges->next_memrange].type = type;
+ /* base: addr if memory, offset if reg relative. */
+ memranges->list[memranges->next_memrange].start = base;
+ /* len: we actually save end (base + len) for convenience */
+ memranges->list[memranges->next_memrange].end = base + len;
+ memranges->next_memrange++;
+ if (memranges->next_memrange >= memranges->listsize)
+ {
+ memranges->listsize *= 2;
+ memranges->list = xrealloc (memranges->list,
+ memranges->listsize);
+ }
+
+ if (type != -1) /* better collect the base register! */
+ add_register (memranges, type);
+}
+
+/* Add a symbol to a collection list */
+static void
+collect_symbol (collect, sym, frame_regno, frame_offset)
+ struct collection_list *collect;
+ struct symbol *sym;
+ long frame_regno;
+ long frame_offset;
+{
+ unsigned long len;
+ unsigned long reg;
+ bfd_signed_vma offset;
+
+ len = TYPE_LENGTH (check_typedef (SYMBOL_TYPE (sym)));
+ switch (SYMBOL_CLASS (sym)) {
+ default:
+ printf_filtered ("%s: don't know symbol class %d\n",
+ SYMBOL_NAME (sym), SYMBOL_CLASS (sym));
+ break;
+ case LOC_CONST:
+ printf_filtered ("%s is constant, value is %d: will not be collected.\n",
+ SYMBOL_NAME (sym), SYMBOL_VALUE (sym));
+ break;
+ case LOC_STATIC:
+ offset = SYMBOL_VALUE_ADDRESS (sym);
+ if (info_verbose)
+ printf_filtered ("LOC_STATIC %s: collect %d bytes at 0x%08x\n",
+ SYMBOL_NAME (sym), len, offset);
+ add_memrange (collect, -1, offset, len); /* 0 == memory */
+ break;
+ case LOC_REGISTER:
+ case LOC_REGPARM:
+ reg = SYMBOL_VALUE (sym);
+ if (info_verbose)
+ printf_filtered ("LOC_REG[parm] %s: ", SYMBOL_NAME (sym));
+ add_register (collect, reg);
+ /* check for doubles stored in two registers */
+ /* FIXME: how about larger types stored in 3 or more regs? */
+ if (TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_FLT &&
+ len > REGISTER_RAW_SIZE (reg))
+ add_register (collect, reg + 1);
+ break;
+ case LOC_REF_ARG:
+ printf_filtered ("Sorry, don't know how to do LOC_REF_ARG yet.\n");
+ printf_filtered (" (will not collect %s)\n",
+ SYMBOL_NAME (sym));
+ break;
+ case LOC_ARG:
+ reg = frame_regno;
+ offset = frame_offset + SYMBOL_VALUE (sym);
+ if (info_verbose)
+ {
+ printf_filtered ("LOC_LOCAL %s: Collect %d bytes at offset",
+ SYMBOL_NAME (sym), len);
+ printf_filtered (" %d from frame ptr reg %d\n", offset, reg);
+ }
+ add_memrange (collect, reg, offset, len);
+ break;
+ case LOC_REGPARM_ADDR:
+ reg = SYMBOL_VALUE (sym);
+ offset = 0;
+ if (info_verbose)
+ {
+ printf_filtered ("LOC_REGPARM_ADDR %s: Collect %d bytes at offset",
+ SYMBOL_NAME (sym), len);
+ printf_filtered (" %d from reg %d\n", offset, reg);
+ }
+ add_memrange (collect, reg, offset, len);
+ break;
+ case LOC_LOCAL:
+ case LOC_LOCAL_ARG:
+ reg = frame_regno;
+ offset = frame_offset + SYMBOL_VALUE (sym);
+ if (info_verbose)
+ {
+ printf_filtered ("LOC_LOCAL %s: Collect %d bytes at offset",
+ SYMBOL_NAME (sym), len);
+ printf_filtered (" %d from frame ptr reg %d\n", offset, reg);
+ }
+ add_memrange (collect, reg, offset, len);
+ break;
+ case LOC_BASEREG:
+ case LOC_BASEREG_ARG:
+ reg = SYMBOL_BASEREG (sym);
+ offset = SYMBOL_VALUE (sym);
+ if (info_verbose)
+ {
+ printf_filtered ("LOC_BASEREG %s: collect %d bytes at offset %d from basereg %d\n",
+ SYMBOL_NAME (sym), len, offset, reg);
+ }
+ add_memrange (collect, reg, offset, len);
+ break;
+ case LOC_UNRESOLVED:
+ printf_filtered ("Don't know LOC_UNRESOLVED %s\n", SYMBOL_NAME (sym));
+ break;
+ case LOC_OPTIMIZED_OUT:
+ printf_filtered ("%s has been optimized out of existance.\n",
+ SYMBOL_NAME (sym));
+ break;
+ }
+}
+
+/* Add all locals (or args) symbols to collection list */
+static void
+add_local_symbols (collect, pc, frame_regno, frame_offset, type)
+ struct collection_list *collect;
+ CORE_ADDR pc;
+ long frame_regno;
+ long frame_offset;
+ int type;
+{
+ struct symbol *sym;
+ struct block *block;
+ int i, nsyms, count = 0;
+
+ block = block_for_pc (pc);
+ while (block != 0)
+ {
+ QUIT; /* allow user to bail out with ^C */
+ nsyms = BLOCK_NSYMS (block);
+ for (i = 0; i < nsyms; i++)
+ {
+ sym = BLOCK_SYM (block, i);
+ switch (SYMBOL_CLASS (sym)) {
+ case LOC_LOCAL:
+ case LOC_STATIC:
+ case LOC_REGISTER:
+ case LOC_BASEREG:
+ if (type == 'L') /* collecting Locals */
+ {
+ count++;
+ collect_symbol (collect, sym, frame_regno, frame_offset);
+ }
+ break;
+ case LOC_ARG:
+ case LOC_LOCAL_ARG:
+ case LOC_REF_ARG:
+ case LOC_REGPARM:
+ case LOC_REGPARM_ADDR:
+ case LOC_BASEREG_ARG:
+ if (type == 'A') /* collecting Arguments */
+ {
+ count++;
+ collect_symbol (collect, sym, frame_regno, frame_offset);
+ }
+ }
+ }
+ if (BLOCK_FUNCTION (block))
+ break;
+ else
+ block = BLOCK_SUPERBLOCK (block);
+ }
+ if (count == 0)
+ warning ("No %s found in scope.", type == 'L' ? "locals" : "args");
+}
+
+/* worker function */
+static void
+clear_collection_list (list)
+ struct collection_list *list;
+{
+ int ndx;
+
+ list->next_memrange = 0;
+ for (ndx = 0; ndx < list->next_aexpr_elt; ndx++)
+ {
+ free_agent_expr(list->aexpr_list[ndx]);
+ list->aexpr_list[ndx] = NULL;
+ }
+ list->next_aexpr_elt = 0;
+ memset (list->regs_mask, 0, sizeof (list->regs_mask));
+}
+
+/* reduce a collection list to string form (for gdb protocol) */
+static char **
+stringify_collection_list (list, string)
+ struct collection_list *list;
+ char *string;
+{
+ char temp_buf[2048];
+ int count;
+ int ndx = 0;
+ char *(*str_list)[];
+ char *end;
+ long i;
+
+ count = 1 + list->next_memrange + list->next_aexpr_elt + 1;
+ str_list = (char *(*)[])xmalloc(count * sizeof (char *));
+
+ for (i = sizeof (list->regs_mask) - 1; i > 0; i--)
+ if (list->regs_mask[i] != 0) /* skip leading zeroes in regs_mask */
+ break;
+ if (list->regs_mask[i] != 0) /* prepare to send regs_mask to the stub */
+ {
+ if (info_verbose)
+ printf_filtered ("\nCollecting registers (mask): 0x");
+ end = temp_buf;
+ *end++='R';
+ for (; i >= 0; i--)
+ {
+ QUIT; /* allow user to bail out with ^C */
+ if (info_verbose)
+ printf_filtered ("%02X", list->regs_mask[i]);
+ sprintf (end, "%02X", list->regs_mask[i]);
+ end += 2;
+ }
+ (*str_list)[ndx] = savestring(temp_buf, end - temp_buf);
+ ndx++;
+ }
+ if (info_verbose)
+ printf_filtered ("\n");
+ if (list->next_memrange > 0 && info_verbose)
+ printf_filtered ("Collecting memranges: \n");
+ for (i = 0, count = 0, end = temp_buf; i < list->next_memrange; i++)
+ {
+ QUIT; /* allow user to bail out with ^C */
+ if (info_verbose)
+ printf_filtered ("(%d, 0x%x, %d)\n",
+ list->list[i].type,
+ list->list[i].start,
+ list->list[i].end - list->list[i].start);
+ if (count + 27 > MAX_AGENT_EXPR_LEN)
+ {
+ (*str_list)[ndx] = savestring(temp_buf, count);
+ ndx++;
+ count = 0;
+ end = temp_buf;
+ }
+ sprintf (end, "M%X,%X,%X",
+ list->list[i].type,
+ list->list[i].start,
+ list->list[i].end - list->list[i].start);
+ count += strlen (end);
+ end += strlen (end);
+ }
+
+ for (i = 0; i < list->next_aexpr_elt; i++)
+ {
+ QUIT; /* allow user to bail out with ^C */
+ if ((count + 10 + 2 * list->aexpr_list[i]->len) > MAX_AGENT_EXPR_LEN)
+ {
+ (*str_list)[ndx] = savestring(temp_buf, count);
+ ndx++;
+ count = 0;
+ end = temp_buf;
+ }
+ sprintf (end, "X%08X,", list->aexpr_list[i]->len);
+ end += 10; /* 'X' + 8 hex digits + ',' */
+ count += 10;
+
+ end = mem2hex(list->aexpr_list[i]->buf, end, list->aexpr_list[i]->len);
+ count += 2 * list->aexpr_list[i]->len;
+ }
+
+ if (count != 0)
+ {
+ (*str_list)[ndx] = savestring(temp_buf, count);
+ ndx++;
+ count = 0;
+ end = temp_buf;
+ }
+ (*str_list)[ndx] = NULL;
+
+ if (ndx == 0)
+ return NULL;
+ else
+ return *str_list;
+}
+
+void
+free_actions_list(actions_list)
+ char **actions_list;
+{
+ int ndx;
+
+ if (actions_list == 0)
+ return;
+
+ for (ndx = 0; actions_list[ndx]; ndx++)
+ free(actions_list[ndx]);
+
+ free(actions_list);
+}
+
+/* render all actions into gdb protocol */
+static void
+encode_actions (t, tdp_actions, stepping_actions)
+ struct tracepoint *t;
+ char ***tdp_actions;
+ char ***stepping_actions;
+{
+ static char tdp_buff[2048], step_buff[2048];
+ char *action_exp;
+ struct expression *exp = NULL;
+ struct action_line *action;
+ bfd_signed_vma offset;
+ long i;
+ value_ptr tempval;
+ struct collection_list *collect;
+ struct cmd_list_element *cmd;
+ struct agent_expr *aexpr;
+ long frame_reg, frame_offset;
+
+
+ clear_collection_list (&tracepoint_list);
+ clear_collection_list (&stepping_list);
+ collect = &tracepoint_list;
+
+ *tdp_actions = NULL;
+ *stepping_actions = NULL;
+
+ TARGET_VIRTUAL_FRAME_POINTER (t->address, &frame_reg, &frame_offset);
+
+ for (action = t->actions; action; action = action->next)
+ {
+ QUIT; /* allow user to bail out with ^C */
+ action_exp = action->action;
+ while (isspace (*action_exp))
+ action_exp++;
+
+ if (*action_exp == '#') /* comment line */
+ return;
+
+ cmd = lookup_cmd (&action_exp, cmdlist, "", -1, 1);
+ if (cmd == 0)
+ error ("Bad action list item: %s", action_exp);
+
+ if (cmd->function.cfunc == collect_pseudocommand)
+ {
+ do { /* repeat over a comma-separated list */
+ QUIT; /* allow user to bail out with ^C */
+ while (isspace (*action_exp))
+ action_exp++;
+
+ if (0 == strncasecmp ("$reg", action_exp, 4))
+ {
+ for (i = 0; i < NUM_REGS; i++)
+ add_register (collect, i);
+ action_exp = strchr (action_exp, ','); /* more? */
+ }
+ else if (0 == strncasecmp ("$arg", action_exp, 4))
+ {
+ add_local_symbols (collect,
+ t->address,
+ frame_reg,
+ frame_offset,
+ 'A');
+ action_exp = strchr (action_exp, ','); /* more? */
+ }
+ else if (0 == strncasecmp ("$loc", action_exp, 4))
+ {
+ add_local_symbols (collect,
+ t->address,
+ frame_reg,
+ frame_offset,
+ 'L');
+ action_exp = strchr (action_exp, ','); /* more? */
+ }
+ else
+ {
+ unsigned long addr, len;
+ struct cleanup *old_chain = NULL;
+ struct cleanup *old_chain1 = NULL;
+ struct agent_reqs areqs;
+
+ exp = parse_exp_1 (&action_exp, block_for_pc (t->address), 1);
+ old_chain = make_cleanup ((make_cleanup_func)
+ free_current_contents, &exp);
+
+ switch (exp->elts[0].opcode) {
+ case OP_REGISTER:
+ i = exp->elts[1].longconst;
+ if (info_verbose)
+ printf_filtered ("OP_REGISTER: ");
+ add_register (collect, i);
+ break;
+
+ case UNOP_MEMVAL:
+ /* safe because we know it's a simple expression */
+ tempval = evaluate_expression (exp);
+ addr = VALUE_ADDRESS (tempval) + VALUE_OFFSET (tempval);
+ len = TYPE_LENGTH (check_typedef (exp->elts[1].type));
+ add_memrange (collect, -1, addr, len);
+ break;
+
+ case OP_VAR_VALUE:
+ collect_symbol (collect,
+ exp->elts[2].symbol,
+ frame_reg,
+ frame_offset);
+ break;
+
+ default: /* full-fledged expression */
+ aexpr = gen_trace_for_expr (t->address, exp);
+
+ old_chain1 = make_cleanup ((make_cleanup_func)
+ free_agent_expr, aexpr);
+
+ ax_reqs (aexpr, &areqs);
+ if (areqs.flaw != agent_flaw_none)
+ error ("malformed expression");
+
+ if (areqs.min_height < 0)
+ error ("gdb: Internal error: expression has min height < 0");
+ if (areqs.max_height > 20)
+ error ("expression too complicated, try simplifying");
+
+ discard_cleanups (old_chain1);
+ add_aexpr (collect, aexpr);
+
+ /* take care of the registers */
+ if (areqs.reg_mask_len > 0)
+ {
+ int ndx1;
+ int ndx2;
+
+ for (ndx1 = 0; ndx1 < areqs.reg_mask_len; ndx1++)
+ {
+ QUIT; /* allow user to bail out with ^C */
+ if (areqs.reg_mask[ndx1] != 0)
+ {
+ /* assume chars have 8 bits */
+ for (ndx2 = 0; ndx2 < 8; ndx2++)
+ if (areqs.reg_mask[ndx1] & (1 << ndx2))
+ /* it's used -- record it */
+ add_register (collect, ndx1 * 8 + ndx2);
+ }
+ }
+ }
+ break;
+ } /* switch */
+ do_cleanups (old_chain);
+ } /* do */
+ } while (action_exp && *action_exp++ == ',');
+ } /* if */
+ else if (cmd->function.cfunc == while_stepping_pseudocommand)
+ {
+ collect = &stepping_list;
+ }
+ else if (cmd->function.cfunc == end_actions_pseudocommand)
+ {
+ if (collect == &stepping_list) /* end stepping actions */
+ collect = &tracepoint_list;
+ else
+ break; /* end tracepoint actions */
+ }
+ } /* for */
+ memrange_sortmerge (&tracepoint_list);
+ memrange_sortmerge (&stepping_list);
+
+ *tdp_actions = stringify_collection_list (&tracepoint_list, &tdp_buff);
+ *stepping_actions = stringify_collection_list (&stepping_list, &step_buff);
+}
+
+static void
+add_aexpr(collect, aexpr)
+ struct collection_list *collect;
+ struct agent_expr *aexpr;
+{
+ if (collect->next_aexpr_elt >= collect->aexpr_listsize)
+ {
+ collect->aexpr_list =
+ xrealloc (collect->aexpr_list,
+ 2 * collect->aexpr_listsize * sizeof (struct agent_expr *));
+ collect->aexpr_listsize *= 2;
+ }
+ collect->aexpr_list[collect->next_aexpr_elt] = aexpr;
+ collect->next_aexpr_elt++;
+}
+
+static char target_buf[2048];
+
+/* Set "transparent" memory ranges
+
+ Allow trace mechanism to treat text-like sections
+ (and perhaps all read-only sections) transparently,
+ i.e. don't reject memory requests from these address ranges
+ just because they haven't been collected. */
+
+static void
+remote_set_transparent_ranges (void)
+{
+ extern bfd *exec_bfd;
+ asection *s;
+ bfd_size_type size;
+ bfd_vma lma;
+ int anysecs = 0;
+
+ if (!exec_bfd)
+ return; /* no information to give. */
+
+ strcpy (target_buf, "QTro");
+ for (s = exec_bfd->sections; s; s = s->next)
+ {
+ char tmp[40];
+
+ if ((s->flags & SEC_LOAD) == 0 ||
+ /* (s->flags & SEC_CODE) == 0 || */
+ (s->flags & SEC_READONLY) == 0)
+ continue;
+
+ anysecs = 1;
+ lma = s->lma;
+ size = bfd_get_section_size_before_reloc (s);
+ sprintf (tmp, ":%x,%x", lma, lma + size);
+ strcat (target_buf, tmp);
+ }
+ if (anysecs)
+ {
+ putpkt (target_buf);
+ getpkt (target_buf, 0);
+ }
+}
+
+/* tstart command:
+
+ Tell target to clear any previous trace experiment.
+ Walk the list of tracepoints, and send them (and their actions)
+ to the target. If no errors,
+ Tell target to start a new trace experiment. */
+
+static void
+trace_start_command (args, from_tty)
+ char *args;
+ int from_tty;
+{ /* STUB_COMM MOSTLY_IMPLEMENTED */
+ struct tracepoint *t;
+ char buf[2048];
+ char **tdp_actions;
+ char **stepping_actions;
+ int ndx;
+ struct cleanup *old_chain = NULL;
+
+ dont_repeat (); /* like "run", dangerous to repeat accidentally */
+
+ if (target_is_remote ())
+ {
+ putpkt ("QTinit");
+ remote_get_noisy_reply (target_buf);
+ if (strcmp (target_buf, "OK"))
+ error ("Target does not support this command.");
+
+ ALL_TRACEPOINTS (t)
+ {
+ int ss_count; /* if actions include singlestepping */
+ int disable_mask; /* ??? */
+ int enable_mask; /* ??? */
+
+ sprintf (buf, "QTDP:%x:%x:%c:%x:%x", t->number, t->address,
+ t->enabled == enabled ? 'E' : 'D',
+ t->step_count, t->pass_count);
+
+ if (t->actions)
+ strcat (buf, "-");
+ putpkt (buf);
+ remote_get_noisy_reply (target_buf);
+ if (strcmp (target_buf, "OK"))
+ error ("Target does not support tracepoints.");
+
+ if (t->actions)
+ {
+ encode_actions (t, &tdp_actions, &stepping_actions);
+ old_chain = make_cleanup (free_actions_list, tdp_actions);
+ (void) make_cleanup (free_actions_list, stepping_actions);
+
+ /* do_single_steps (t); */
+ if (tdp_actions)
+ {
+ for (ndx = 0; tdp_actions[ndx]; ndx++)
+ {
+ QUIT; /* allow user to bail out with ^C */
+ sprintf (buf, "QTDP:-%x:%x:%s%c",
+ t->number, t->address,
+ tdp_actions[ndx],
+ ((tdp_actions[ndx+1] || stepping_actions)
+ ? '-' : 0));
+ putpkt (buf);
+ remote_get_noisy_reply (target_buf);
+ if (strcmp (target_buf, "OK"))
+ error ("Error on target while setting tracepoints.");
+ }
+ }
+ if (stepping_actions)
+ {
+ for (ndx = 0; stepping_actions[ndx]; ndx++)
+ {
+ QUIT; /* allow user to bail out with ^C */
+ sprintf (buf, "QTDP:-%x:%x:%s%s%s",
+ t->number, t->address,
+ ((ndx == 0) ? "S" : ""),
+ stepping_actions[ndx],
+ (stepping_actions[ndx+1] ? "-" : ""));
+ putpkt (buf);
+ remote_get_noisy_reply (target_buf);
+ if (strcmp (target_buf, "OK"))
+ error ("Error on target while setting tracepoints.");
+ }
+ }
+
+ do_cleanups (old_chain);
+ }
+ }
+ /* Tell target to treat text-like sections as transparent */
+ remote_set_transparent_ranges ();
+ /* Now insert traps and begin collecting data */
+ putpkt ("QTStart");
+ remote_get_noisy_reply (target_buf);
+ if (strcmp (target_buf, "OK"))
+ error ("Bogus reply from target: %s", target_buf);
+ set_traceframe_num (-1); /* all old traceframes invalidated */
+ set_tracepoint_num (-1);
+ set_traceframe_context(-1);
+ trace_running_p = 1;
+ if (trace_start_stop_hook)
+ trace_start_stop_hook(1, from_tty);
+
+ }
+ else
+ error ("Trace can only be run on remote targets.");
+}
+
+/* tstop command */
+static void
+trace_stop_command (args, from_tty)
+ char *args;
+ int from_tty;
+{ /* STUB_COMM IS_IMPLEMENTED */
+ if (target_is_remote ())
+ {
+ putpkt ("QTStop");
+ remote_get_noisy_reply (target_buf);
+ if (strcmp (target_buf, "OK"))
+ error ("Bogus reply from target: %s", target_buf);
+ trace_running_p = 0;
+ if (trace_start_stop_hook)
+ trace_start_stop_hook(0, from_tty);
+ }
+ else
+ error ("Trace can only be run on remote targets.");
+}
+
+unsigned long trace_running_p;
+
+/* tstatus command */
+static void
+trace_status_command (args, from_tty)
+ char *args;
+ int from_tty;
+{ /* STUB_COMM IS_IMPLEMENTED */
+ if (target_is_remote ())
+ {
+ putpkt ("qTStatus");
+ remote_get_noisy_reply (target_buf);
+
+ if (target_buf[0] != 'T' ||
+ (target_buf[1] != '0' && target_buf[1] != '1'))
+ error ("Bogus reply from target: %s", target_buf);
+
+ /* exported for use by the GUI */
+ trace_running_p = (target_buf[1] == '1');
+ }
+ else
+ error ("Trace can only be run on remote targets.");
+}
+
+/* Worker function for the various flavors of the tfind command */
+static void
+finish_tfind_command (msg, from_tty)
+ char *msg;
+ int from_tty;
+{
+ int target_frameno = -1, target_tracept = -1;
+ CORE_ADDR old_frame_addr;
+ struct symbol *old_func;
+ char *reply;
+
+ old_frame_addr = FRAME_FP (get_current_frame ());
+ old_func = find_pc_function (read_pc ());
+
+ putpkt (msg);
+ reply = remote_get_noisy_reply (msg);
+
+ while (reply && *reply)
+ switch (*reply) {
+ case 'F':
+ if ((target_frameno = (int) strtol (++reply, &reply, 16)) == -1)
+ {
+ /* A request for a non-existant trace frame has failed.
+ Our response will be different, depending on FROM_TTY:
+
+ If FROM_TTY is true, meaning that this command was
+ typed interactively by the user, then give an error
+ and DO NOT change the state of traceframe_number etc.
+
+ However if FROM_TTY is false, meaning that we're either
+ in a script, a loop, or a user-defined command, then
+ DON'T give an error, but DO change the state of
+ traceframe_number etc. to invalid.
+
+ The rationalle is that if you typed the command, you
+ might just have committed a typo or something, and you'd
+ like to NOT lose your current debugging state. However
+ if you're in a user-defined command or especially in a
+ loop, then you need a way to detect that the command
+ failed WITHOUT aborting. This allows you to write
+ scripts that search thru the trace buffer until the end,
+ and then continue on to do something else. */
+
+ if (from_tty)
+ error ("Target failed to find requested trace frame.");
+ else
+ {
+ if (info_verbose)
+ printf_filtered ("End of trace buffer.\n");
+ /* The following will not recurse, since it's special-cased */
+ trace_find_command ("-1", from_tty);
+ reply = NULL; /* break out of loop,
+ (avoid recursive nonsense) */
+ }
+ }
+ break;
+ case 'T':
+ if ((target_tracept = (int) strtol (++reply, &reply, 16)) == -1)
+ error ("Target failed to find requested trace frame.");
+ break;
+ case 'O': /* "OK"? */
+ if (reply[1] == 'K' && reply[2] == '\0')
+ reply += 2;
+ else
+ error ("Bogus reply from target: %s", reply);
+ break;
+ default:
+ error ("Bogus reply from target: %s", reply);
+ }
+
+ flush_cached_frames ();
+ registers_changed ();
+ select_frame (get_current_frame (), 0);
+ set_traceframe_num (target_frameno);
+ set_tracepoint_num (target_tracept);
+ if (target_frameno == -1)
+ set_traceframe_context (-1);
+ else
+ set_traceframe_context (read_pc ());
+
+ if (from_tty)
+ {
+ int source_only;
+
+ /* NOTE: in immitation of the step command, try to determine
+ whether we have made a transition from one function to another.
+ If so, we'll print the "stack frame" (ie. the new function and
+ it's arguments) -- otherwise we'll just show the new source line.
+
+ This determination is made by checking (1) whether the current
+ function has changed, and (2) whether the current FP has changed.
+ Hack: if the FP wasn't collected, either at the current or the
+ previous frame, assume that the FP has NOT changed. */
+
+ if (old_func == find_pc_function (read_pc ()) &&
+ (old_frame_addr == 0 ||
+ FRAME_FP (get_current_frame ()) == 0 ||
+ old_frame_addr == FRAME_FP (get_current_frame ())))
+ source_only = -1;
+ else
+ source_only = 1;
+
+ print_stack_frame (selected_frame, selected_frame_level, source_only);
+ do_displays ();
+ }
+}
+
+/* trace_find_command takes a trace frame number n,
+ sends "QTFrame:<n>" to the target,
+ and accepts a reply that may contain several optional pieces
+ of information: a frame number, a tracepoint number, and an
+ indication of whether this is a trap frame or a stepping frame.
+
+ The minimal response is just "OK" (which indicates that the
+ target does not give us a frame number or a tracepoint number).
+ Instead of that, the target may send us a string containing
+ any combination of:
+ F<hexnum> (gives the selected frame number)
+ T<hexnum> (gives the selected tracepoint number)
+ */
+
+/* tfind command */
+static void
+trace_find_command (args, from_tty)
+ char *args;
+ int from_tty;
+{ /* STUB_COMM PART_IMPLEMENTED */
+ /* this should only be called with a numeric argument */
+ int frameno = -1;
+ char *tmp;
+
+ if (target_is_remote ())
+ {
+ if (trace_find_hook)
+ trace_find_hook (args, from_tty);
+
+ if (args == 0 || *args == 0)
+ { /* TFIND with no args means find NEXT trace frame. */
+ if (traceframe_number == -1)
+ frameno = 0; /* "next" is first one */
+ else
+ frameno = traceframe_number + 1;
+ }
+ else if (0 == strcmp (args, "-"))
+ {
+ if (traceframe_number == -1)
+ error ("not debugging trace buffer");
+ else if (from_tty && traceframe_number == 0)
+ error ("already at start of trace buffer");
+
+ frameno = traceframe_number - 1;
+ }
+ else
+ frameno = parse_and_eval_address (args);
+
+ if (frameno < -1)
+ error ("invalid input (%d is less than zero)", frameno);
+
+ sprintf (target_buf, "QTFrame:%x", frameno);
+ finish_tfind_command (target_buf, from_tty);
+ }
+ else
+ error ("Trace can only be run on remote targets.");
+}
+
+/* tfind end */
+static void
+trace_find_end_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ trace_find_command ("-1", from_tty);
+}
+
+/* tfind none */
+static void
+trace_find_none_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ trace_find_command ("-1", from_tty);
+}
+
+/* tfind start */
+static void
+trace_find_start_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ trace_find_command ("0", from_tty);
+}
+
+/* tfind pc command */
+static void
+trace_find_pc_command (args, from_tty)
+ char *args;
+ int from_tty;
+{ /* STUB_COMM PART_IMPLEMENTED */
+ CORE_ADDR pc;
+ char *tmp;
+
+ if (target_is_remote ())
+ {
+ if (args == 0 || *args == 0)
+ pc = read_pc (); /* default is current pc */
+ else
+ pc = parse_and_eval_address (args);
+
+ sprintf (target_buf, "QTFrame:pc:%x", pc);
+ finish_tfind_command (target_buf, from_tty);
+ }
+ else
+ error ("Trace can only be run on remote targets.");
+}
+
+/* tfind tracepoint command */
+static void
+trace_find_tracepoint_command (args, from_tty)
+ char *args;
+ int from_tty;
+{ /* STUB_COMM PART_IMPLEMENTED */
+ int tdp;
+ char buf[40], *tmp;
+
+ if (target_is_remote ())
+ {
+ if (args == 0 || *args == 0)
+ if (tracepoint_number == -1)
+ error ("No current tracepoint -- please supply an argument.");
+ else
+ tdp = tracepoint_number; /* default is current TDP */
+ else
+ tdp = parse_and_eval_address (args);
+
+ sprintf (target_buf, "QTFrame:tdp:%x", tdp);
+ finish_tfind_command (target_buf, from_tty);
+ }
+ else
+ error ("Trace can only be run on remote targets.");
+}
+
+/* TFIND LINE command:
+
+ This command will take a sourceline for argument, just like BREAK
+ or TRACE (ie. anything that "decode_line_1" can handle).
+
+ With no argument, this command will find the next trace frame
+ corresponding to a source line OTHER THAN THE CURRENT ONE. */
+
+static void
+trace_find_line_command (args, from_tty)
+ char *args;
+ int from_tty;
+{ /* STUB_COMM PART_IMPLEMENTED */
+ static CORE_ADDR start_pc, end_pc;
+ struct symtabs_and_lines sals;
+ struct symtab_and_line sal;
+ char *tmp;
+ struct cleanup *old_chain;
+
+ if (target_is_remote ())
+ {
+ if (args == 0 || *args == 0)
+ {
+ sal = find_pc_line ((get_current_frame ())->pc, 0);
+ sals.nelts = 1;
+ sals.sals = (struct symtab_and_line *)
+ xmalloc (sizeof (struct symtab_and_line));
+ sals.sals[0] = sal;
+ }
+ else
+ {
+ sals = decode_line_spec (args, 1);
+ sal = sals.sals[0];
+ }
+
+ old_chain = make_cleanup (free, sals.sals);
+ if (sal.symtab == 0)
+ {
+ printf_filtered ("TFIND: 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, gdb_stdout);
+ printf_filtered (";\n -- will attempt to find by PC. \n");
+ }
+ else
+ {
+ printf_filtered (".\n");
+ return; /* no line, no PC; what can we do? */
+ }
+ }
+ else if (sal.line > 0
+ && find_line_pc_range (sal, &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, gdb_stdout);
+ wrap_here (" ");
+ printf_filtered (" but contains no code.\n");
+ sal = find_pc_line (start_pc, 0);
+ if (sal.line > 0 &&
+ find_line_pc_range (sal, &start_pc, &end_pc) &&
+ start_pc != end_pc)
+ printf_filtered ("Attempting to find line %d instead.\n",
+ sal.line);
+ else
+ error ("Cannot find a good line.");
+ }
+ }
+ 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? */
+ error ("Line number %d is out of range for \"%s\".\n",
+ sal.line, sal.symtab->filename);
+
+ if (args && *args) /* find within range of stated line */
+ sprintf (target_buf, "QTFrame:range:%x:%x", start_pc, end_pc - 1);
+ else /* find OUTSIDE OF range of CURRENT line */
+ sprintf (target_buf, "QTFrame:outside:%x:%x", start_pc, end_pc - 1);
+ finish_tfind_command (target_buf, from_tty);
+ do_cleanups (old_chain);
+ }
+ else
+ error ("Trace can only be run on remote targets.");
+}
+
+/* tfind range command */
+static void
+trace_find_range_command (args, from_tty)
+ char *args;
+ int from_tty;
+{ /* STUB_COMM PART_IMPLEMENTED */
+ static CORE_ADDR start, stop;
+ char *tmp;
+
+ if (target_is_remote ())
+ {
+ if (args == 0 || *args == 0)
+ { /* XXX FIXME: what should default behavior be? */
+ printf_filtered ("Usage: tfind range <startaddr>,<endaddr>\n");
+ return;
+ }
+
+ if (0 != (tmp = strchr (args, ',' )))
+ {
+ *tmp++ = '\0'; /* terminate start address */
+ while (isspace (*tmp))
+ tmp++;
+ start = parse_and_eval_address (args);
+ stop = parse_and_eval_address (tmp);
+ }
+ else
+ { /* no explicit end address? */
+ start = parse_and_eval_address (args);
+ stop = start + 1; /* ??? */
+ }
+
+ sprintf (target_buf, "QTFrame:range:%x:%x", start, stop);
+ finish_tfind_command (target_buf, from_tty);
+ }
+ else
+ error ("Trace can only be run on remote targets.");
+}
+
+/* tfind outside command */
+static void
+trace_find_outside_command (args, from_tty)
+ char *args;
+ int from_tty;
+{ /* STUB_COMM PART_IMPLEMENTED */
+ CORE_ADDR start, stop;
+ char *tmp;
+
+ if (target_is_remote ())
+ {
+ if (args == 0 || *args == 0)
+ { /* XXX FIXME: what should default behavior be? */
+ printf_filtered ("Usage: tfind outside <startaddr>,<endaddr>\n");
+ return;
+ }
+
+ if (0 != (tmp = strchr (args, ',' )))
+ {
+ *tmp++ = '\0'; /* terminate start address */
+ while (isspace (*tmp))
+ tmp++;
+ start = parse_and_eval_address (args);
+ stop = parse_and_eval_address (tmp);
+ }
+ else
+ { /* no explicit end address? */
+ start = parse_and_eval_address (args);
+ stop = start + 1; /* ??? */
+ }
+
+ sprintf (target_buf, "QTFrame:outside:%x:%x", start, stop);
+ finish_tfind_command (target_buf, from_tty);
+ }
+ else
+ error ("Trace can only be run on remote targets.");
+}
+
+/* save-tracepoints command */
+static void
+tracepoint_save_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ struct tracepoint *tp;
+ struct action_line *line;
+ FILE *fp;
+ char *i1 = " ", *i2 = " ";
+ char *indent, *actionline;
+
+ if (args == 0 || *args == 0)
+ error ("Argument required (file name in which to save tracepoints");
+
+ if (tracepoint_chain == 0)
+ {
+ warning ("save-tracepoints: no tracepoints to save.\n");
+ return;
+ }
+
+ if (!(fp = fopen (args, "w")))
+ error ("Unable to open file '%s' for saving tracepoints");
+
+ ALL_TRACEPOINTS (tp)
+ {
+ if (tp->addr_string)
+ fprintf (fp, "trace %s\n", tp->addr_string);
+ else
+ fprintf (fp, "trace *0x%x\n", tp->address);
+
+ if (tp->pass_count)
+ fprintf (fp, " passcount %d\n", tp->pass_count);
+
+ if (tp->actions)
+ {
+ fprintf (fp, " actions\n");
+ indent = i1;
+ for (line = tp->actions; line; line = line->next)
+ {
+ struct cmd_list_element *cmd;
+
+ QUIT; /* allow user to bail out with ^C */
+ actionline = line->action;
+ while (isspace(*actionline))
+ actionline++;
+
+ fprintf (fp, "%s%s\n", indent, actionline);
+ if (*actionline != '#') /* skip for comment lines */
+ {
+ cmd = lookup_cmd (&actionline, cmdlist, "", -1, 1);
+ if (cmd == 0)
+ error ("Bad action list item: %s", actionline);
+ if (cmd->function.cfunc == while_stepping_pseudocommand)
+ indent = i2;
+ else if (cmd->function.cfunc == end_actions_pseudocommand)
+ indent = i1;
+ }
+ }
+ }
+ }
+ fclose (fp);
+ if (from_tty)
+ printf_filtered ("Tracepoints saved to file '%s'.\n", args);
+ return;
+}
+
+/* info scope command: list the locals for a scope. */
+static void
+scope_info (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ struct symtab_and_line sal;
+ struct symtabs_and_lines sals;
+ struct symbol *sym;
+ struct minimal_symbol *msym;
+ struct block *block;
+ char **canonical, *symname, *save_args = args;
+ int i, j, nsyms, count = 0;
+
+ if (args == 0 || *args == 0)
+ error ("requires an argument (function, line or *addr) to define a scope");
+
+ sals = decode_line_1 (&args, 1, NULL, 0, &canonical);
+ if (sals.nelts == 0)
+ return; /* presumably decode_line_1 has already warned */
+
+ /* Resolve line numbers to PC */
+ resolve_sal_pc (&sals.sals[0]);
+ block = block_for_pc (sals.sals[0].pc);
+
+ while (block != 0)
+ {
+ QUIT; /* allow user to bail out with ^C */
+ nsyms = BLOCK_NSYMS (block);
+ for (i = 0; i < nsyms; i++)
+ {
+ QUIT; /* allow user to bail out with ^C */
+ if (count == 0)
+ printf_filtered ("Scope for %s:\n", save_args);
+ count++;
+ sym = BLOCK_SYM (block, i);
+ symname = SYMBOL_NAME (sym);
+ if (symname == NULL || *symname == '\0')
+ continue; /* probably botched, certainly useless */
+
+ printf_filtered ("Symbol %s is ", symname);
+ switch (SYMBOL_CLASS (sym)) {
+ default:
+ case LOC_UNDEF: /* messed up symbol? */
+ printf_filtered ("a bogus symbol, class %d.\n",
+ SYMBOL_CLASS (sym));
+ count--; /* don't count this one */
+ continue;
+ case LOC_CONST:
+ printf_filtered ("a constant with value %d (0x%x)",
+ SYMBOL_VALUE (sym), SYMBOL_VALUE (sym));
+ break;
+ case LOC_CONST_BYTES:
+ printf_filtered ("constant bytes: ");
+ if (SYMBOL_TYPE (sym))
+ for (j = 0; j < TYPE_LENGTH (SYMBOL_TYPE (sym)); j++)
+ fprintf_filtered (gdb_stdout, " %02x",
+ (unsigned) SYMBOL_VALUE_BYTES (sym) [j]);
+ break;
+ case LOC_STATIC:
+ printf_filtered ("in static storage at address ");
+ print_address_numeric (SYMBOL_VALUE_ADDRESS (sym), 1, gdb_stdout);
+ break;
+ case LOC_REGISTER:
+ printf_filtered ("a local variable in register $%s",
+ REGISTER_NAME (SYMBOL_VALUE (sym)));
+ break;
+ case LOC_ARG:
+ case LOC_LOCAL_ARG:
+ printf_filtered ("an argument at stack/frame offset %ld",
+ SYMBOL_VALUE (sym));
+ break;
+ case LOC_LOCAL:
+ printf_filtered ("a local variable at frame offset %ld",
+ SYMBOL_VALUE (sym));
+ break;
+ case LOC_REF_ARG:
+ printf_filtered ("a reference argument at offset %ld",
+ SYMBOL_VALUE (sym));
+ break;
+ case LOC_REGPARM:
+ printf_filtered ("an argument in register $%s",
+ REGISTER_NAME (SYMBOL_VALUE (sym)));
+ break;
+ case LOC_REGPARM_ADDR:
+ printf_filtered ("the address of an argument, in register $%s",
+ REGISTER_NAME (SYMBOL_VALUE (sym)));
+ break;
+ case LOC_TYPEDEF:
+ printf_filtered ("a typedef.\n");
+ continue;
+ case LOC_LABEL:
+ printf_filtered ("a label at address ");
+ print_address_numeric (SYMBOL_VALUE_ADDRESS (sym), 1, gdb_stdout);
+ break;
+ case LOC_BLOCK:
+ printf_filtered ("a function at address ");
+ print_address_numeric (BLOCK_START (SYMBOL_BLOCK_VALUE (sym)), 1,
+ gdb_stdout);
+ break;
+ case LOC_BASEREG:
+ printf_filtered ("a variable at offset %d from register $%s",
+ SYMBOL_VALUE (sym),
+ REGISTER_NAME (SYMBOL_BASEREG (sym)));
+ break;
+ case LOC_BASEREG_ARG:
+ printf_filtered ("an argument at offset %d from register $%s",
+ SYMBOL_VALUE (sym),
+ REGISTER_NAME (SYMBOL_BASEREG (sym)));
+ break;
+ case LOC_UNRESOLVED:
+ msym = lookup_minimal_symbol (SYMBOL_NAME (sym), NULL, NULL);
+ if (msym == NULL)
+ printf_filtered ("Unresolved Static");
+ else
+ {
+ printf_filtered ("static storage at address ");
+ print_address_numeric (SYMBOL_VALUE_ADDRESS (msym), 1,
+ gdb_stdout);
+ }
+ break;
+ case LOC_OPTIMIZED_OUT:
+ printf_filtered ("optimized out.\n");
+ continue;
+ }
+ if (SYMBOL_TYPE (sym))
+ printf_filtered (", length %d.\n",
+ TYPE_LENGTH (check_typedef (SYMBOL_TYPE (sym))));
+ }
+ if (BLOCK_FUNCTION (block))
+ break;
+ else
+ block = BLOCK_SUPERBLOCK (block);
+ }
+ if (count <= 0)
+ printf_filtered ("Scope for %s contains no locals or arguments.\n",
+ save_args);
+}
+
+/* worker function (cleanup) */
+static void
+replace_comma (comma)
+ char *comma;
+{
+ *comma = ',';
+}
+
+/* tdump command */
+static void
+trace_dump_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ struct tracepoint *t;
+ struct action_line *action;
+ char *action_exp, *next_comma;
+ struct cleanup *old_cleanups;
+ int stepping_actions = 0;
+ int stepping_frame = 0;
+
+ if (!target_is_remote ())
+ {
+ error ("Trace can only be run on remote targets.");
+ return;
+ }
+
+ if (tracepoint_number == -1)
+ {
+ warning ("No current trace frame.");
+ return;
+ }
+
+ ALL_TRACEPOINTS (t)
+ if (t->number == tracepoint_number)
+ break;
+
+ if (t == NULL)
+ error ("No known tracepoint matches 'current' tracepoint #%d.",
+ tracepoint_number);
+
+ old_cleanups = make_cleanup (null_cleanup, NULL);
+
+ printf_filtered ("Data collected at tracepoint %d, trace frame %d:\n",
+ tracepoint_number, traceframe_number);
+
+ /* The current frame is a trap frame if the frame PC is equal
+ to the tracepoint PC. If not, then the current frame was
+ collected during single-stepping. */
+
+ stepping_frame = (t->address != read_pc());
+
+ for (action = t->actions; action; action = action->next)
+ {
+ struct cmd_list_element *cmd;
+
+ QUIT; /* allow user to bail out with ^C */
+ action_exp = action->action;
+ while (isspace (*action_exp))
+ action_exp++;
+
+ /* The collection actions to be done while stepping are
+ bracketed by the commands "while-stepping" and "end". */
+
+ if (*action_exp == '#') /* comment line */
+ continue;
+
+ cmd = lookup_cmd (&action_exp, cmdlist, "", -1, 1);
+ if (cmd == 0)
+ error ("Bad action list item: %s", action_exp);
+
+ if (cmd->function.cfunc == while_stepping_pseudocommand)
+ stepping_actions = 1;
+ else if (cmd->function.cfunc == end_actions_pseudocommand)
+ stepping_actions = 0;
+ else if (cmd->function.cfunc == collect_pseudocommand)
+ {
+ /* Display the collected data.
+ For the trap frame, display only what was collected at the trap.
+ Likewise for stepping frames, display only what was collected
+ while stepping. This means that the two boolean variables,
+ STEPPING_FRAME and STEPPING_ACTIONS should be equal. */
+ if (stepping_frame == stepping_actions)
+ {
+ do { /* repeat over a comma-separated list */
+ QUIT; /* allow user to bail out with ^C */
+ if (*action_exp == ',')
+ action_exp++;
+ while (isspace (*action_exp))
+ action_exp++;
+
+ next_comma = strchr (action_exp, ',');
+
+ if (0 == strncasecmp (action_exp, "$reg", 4))
+ registers_info (NULL, from_tty);
+ else if (0 == strncasecmp (action_exp, "$loc", 4))
+ locals_info (NULL, from_tty);
+ else if (0 == strncasecmp (action_exp, "$arg", 4))
+ args_info (NULL, from_tty);
+ else
+ { /* variable */
+ if (next_comma)
+ {
+ make_cleanup (replace_comma, next_comma);
+ *next_comma = '\0';
+ }
+ printf_filtered ("%s = ", action_exp);
+ output_command (action_exp, from_tty);
+ printf_filtered ("\n");
+ }
+ if (next_comma)
+ *next_comma = ',';
+ action_exp = next_comma;
+ } while (action_exp && *action_exp == ',');
+ }
+ }
+ }
+ discard_cleanups (old_cleanups);
+}
+
+/* Convert the memory pointed to by mem into hex, placing result in buf.
+ * Return a pointer to the last char put in buf (null)
+ * "stolen" from sparc-stub.c
+ */
+
+static const char hexchars[]="0123456789abcdef";
+
+static unsigned char *
+mem2hex(mem, buf, count)
+ unsigned char *mem;
+ unsigned char *buf;
+ int count;
+{
+ unsigned char ch;
+
+ while (count-- > 0)
+ {
+ ch = *mem++;
+
+ *buf++ = hexchars[ch >> 4];
+ *buf++ = hexchars[ch & 0xf];
+ }
+
+ *buf = 0;
+
+ return buf;
+}
+
+int get_traceframe_number()
+{
+ return traceframe_number;
+}
+
+
+/* module initialization */
+void
+_initialize_tracepoint ()
+{
+ tracepoint_chain = 0;
+ tracepoint_count = 0;
+ traceframe_number = -1;
+ tracepoint_number = -1;
+
+ set_internalvar (lookup_internalvar ("tpnum"),
+ value_from_longest (builtin_type_int, (LONGEST) 0));
+ set_internalvar (lookup_internalvar ("trace_frame"),
+ value_from_longest (builtin_type_int, (LONGEST) -1));
+
+ if (tracepoint_list.list == NULL)
+ {
+ tracepoint_list.listsize = 128;
+ tracepoint_list.list = xmalloc
+ (tracepoint_list.listsize * sizeof (struct memrange));
+ }
+ if (tracepoint_list.aexpr_list == NULL)
+ {
+ tracepoint_list.aexpr_listsize = 128;
+ tracepoint_list.aexpr_list = xmalloc
+ (tracepoint_list.aexpr_listsize * sizeof (struct agent_expr *));
+ }
+
+ if (stepping_list.list == NULL)
+ {
+ stepping_list.listsize = 128;
+ stepping_list.list = xmalloc
+ (stepping_list.listsize * sizeof (struct memrange));
+ }
+
+ if (stepping_list.aexpr_list == NULL)
+ {
+ stepping_list.aexpr_listsize = 128;
+ stepping_list.aexpr_list = xmalloc
+ (stepping_list.aexpr_listsize * sizeof (struct agent_expr *));
+ }
+
+ add_info ("scope", scope_info,
+ "List the variables local to a scope");
+
+ add_cmd ("tracepoints", class_trace, NO_FUNCTION,
+ "Tracing of program execution without stopping the program.",
+ &cmdlist);
+
+ add_info ("tracepoints", tracepoints_info,
+ "Status of tracepoints, or tracepoint number NUMBER.\n\
+Convenience variable \"$tpnum\" contains the number of the\n\
+last tracepoint set.");
+
+ add_info_alias ("tp", "tracepoints", 1);
+
+ add_com ("save-tracepoints", class_trace, tracepoint_save_command,
+ "Save current tracepoint definitions as a script.\n\
+Use the 'source' command in another debug session to restore them.");
+
+ add_com ("tdump", class_trace, trace_dump_command,
+ "Print everything collected at the current tracepoint.");
+
+ add_prefix_cmd ("tfind", class_trace, trace_find_command,
+ "Select a trace frame;\n\
+No argument means forward by one frame; '-' meand backward by one frame.",
+ &tfindlist, "tfind ", 1, &cmdlist);
+
+ add_cmd ("outside", class_trace, trace_find_outside_command,
+ "Select a trace frame whose PC is outside the given \
+range.\nUsage: tfind outside addr1, addr2",
+ &tfindlist);
+
+ add_cmd ("range", class_trace, trace_find_range_command,
+ "Select a trace frame whose PC is in the given range.\n\
+Usage: tfind range addr1,addr2",
+ &tfindlist);
+
+ add_cmd ("line", class_trace, trace_find_line_command,
+ "Select a trace frame by source line.\n\
+Argument can be a line number (with optional source file), \n\
+a function name, or '*' followed by an address.\n\
+Default argument is 'the next source line that was traced'.",
+ &tfindlist);
+
+ add_cmd ("tracepoint", class_trace, trace_find_tracepoint_command,
+ "Select a trace frame by tracepoint number.\n\
+Default is the tracepoint for the current trace frame.",
+ &tfindlist);
+
+ add_cmd ("pc", class_trace, trace_find_pc_command,
+ "Select a trace frame by PC.\n\
+Default is the current PC, or the PC of the current trace frame.",
+ &tfindlist);
+
+ add_cmd ("end", class_trace, trace_find_end_command,
+ "Synonym for 'none'.\n\
+De-select any trace frame and resume 'live' debugging.",
+ &tfindlist);
+
+ add_cmd ("none", class_trace, trace_find_none_command,
+ "De-select any trace frame and resume 'live' debugging.",
+ &tfindlist);
+
+ add_cmd ("start", class_trace, trace_find_start_command,
+ "Select the first trace frame in the trace buffer.",
+ &tfindlist);
+
+ add_com ("tstatus", class_trace, trace_status_command,
+ "Display the status of the current trace data collection.");
+
+ add_com ("tstop", class_trace, trace_stop_command,
+ "Stop trace data collection.");
+
+ add_com ("tstart", class_trace, trace_start_command,
+ "Start trace data collection.");
+
+ add_com ("passcount", class_trace, trace_pass_command,
+ "Set the passcount for a tracepoint.\n\
+The trace will end when the tracepoint has been passed 'count' times.\n\
+Usage: passcount COUNT TPNUM, where TPNUM may also be \"all\";\n\
+if TPNUM is omitted, passcount refers to the last tracepoint defined.");
+
+ add_com ("end", class_trace, end_actions_pseudocommand,
+ "Ends a list of commands or actions.\n\
+Several GDB commands allow you to enter a list of commands or actions.\n\
+Entering \"end\" on a line by itself is the normal way to terminate\n\
+such a list.\n\n\
+Note: the \"end\" command cannot be used at the gdb prompt.");
+
+ add_com ("while-stepping", class_trace, while_stepping_pseudocommand,
+ "Specify single-stepping behavior at a tracepoint.\n\
+Argument is number of instructions to trace in single-step mode\n\
+following the tracepoint. This command is normally followed by\n\
+one or more \"collect\" commands, to specify what to collect\n\
+while single-stepping.\n\n\
+Note: this command can only be used in a tracepoint \"actions\" list.");
+
+ add_com_alias ("ws", "while-stepping", class_alias, 0);
+ add_com_alias ("stepping", "while-stepping", class_alias, 0);
+
+ add_com ("collect", class_trace, collect_pseudocommand,
+ "Specify one or more data items to be collected at a tracepoint.\n\
+Accepts a comma-separated list of (one or more) expressions. GDB will\n\
+collect all data (variables, registers) referenced by that expression.\n\
+Also accepts the following special arguments:\n\
+ $regs -- all registers.\n\
+ $args -- all function arguments.\n\
+ $locals -- all variables local to the block/function scope.\n\
+Note: this command can only be used in a tracepoint \"actions\" list.");
+
+ add_com ("actions", class_trace, trace_actions_command,
+ "Specify the actions to be taken at a tracepoint.\n\
+Tracepoint actions may include collecting of specified data, \n\
+single-stepping, or enabling/disabling other tracepoints, \n\
+depending on target's capabilities.");
+
+ add_cmd ("tracepoints", class_trace, delete_trace_command,
+ "Delete specified tracepoints.\n\
+Arguments are tracepoint numbers, separated by spaces.\n\
+No argument means delete all tracepoints.",
+ &deletelist);
+
+ add_cmd ("tracepoints", class_trace, disable_trace_command,
+ "Disable specified tracepoints.\n\
+Arguments are tracepoint numbers, separated by spaces.\n\
+No argument means disable all tracepoints.",
+ &disablelist);
+
+ add_cmd ("tracepoints", class_trace, enable_trace_command,
+ "Enable specified tracepoints.\n\
+Arguments are tracepoint numbers, separated by spaces.\n\
+No argument means enable all tracepoints.",
+ &enablelist);
+
+ add_com ("trace", class_trace, trace_command,
+ "Set a tracepoint at a specified line or function or address.\n\
+Argument may be a line number, function name, or '*' plus an address.\n\
+For a line number or function, trace at the start of its code.\n\
+If an address is specified, trace at that exact address.\n\n\
+Do \"help tracepoints\" for info on other tracepoint commands.");
+
+ add_com_alias ("tp", "trace", class_alias, 0);
+ add_com_alias ("tr", "trace", class_alias, 1);
+ add_com_alias ("tra", "trace", class_alias, 1);
+ add_com_alias ("trac", "trace", class_alias, 1);
+}
+
diff --git a/gdb/tracepoint.h b/gdb/tracepoint.h
new file mode 100644
index 00000000000..4c1ee82d8d7
--- /dev/null
+++ b/gdb/tracepoint.h
@@ -0,0 +1,137 @@
+/* Data structures associated with tracepoints in GDB.
+ Copyright (C) 1997 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#if !defined (TRACEPOINT_H)
+#define TRACEPOINT_H 1
+
+#if !defined (BREAKPOINT_H)
+enum enable { disabled, enabled };
+#endif
+/* The data structure for an action: */
+struct action_line
+{
+ struct action_line *next;
+ char *action;
+};
+
+/* The data structure for a tracepoint: */
+
+struct tracepoint
+{
+ struct tracepoint *next;
+
+ enum enable enabled;
+
+#if 0
+ /* Type of tracepoint (MVS FIXME: needed?). */
+ enum tptype type;
+
+ /* What to do with this tracepoint after we hit it MVS FIXME: needed?). */
+ enum tpdisp disposition;
+#endif
+ /* Number assigned to distinguish tracepoints. */
+ int number;
+
+ /* Address to trace at, or NULL if not an instruction tracepoint (MVS ?). */
+ 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;
+
+ /* Number of times this tracepoint should single-step
+ and collect additional data */
+ long step_count;
+
+ /* Number of times this tracepoint should be hit before disabling/ending. */
+ int pass_count;
+
+ /* Chain of action lines to execute when this tracepoint is hit. */
+ struct action_line *actions;
+
+ /* Conditional (MVS ?). */
+ struct expression *cond;
+
+ /* String we used to set the tracepoint (malloc'd). Only matters if
+ address is non-NULL. */
+ char *addr_string;
+
+ /* Language we used to set the tracepoint. */
+ enum language language;
+
+ /* Input radix we used to set the tracepoint. */
+ int input_radix;
+
+ /* Count of the number of times this tracepoint was taken, dumped
+ with the info, but not used for anything else. Useful for
+ seeing how many times you hit a tracepoint prior to the program
+ aborting, so you can back up to just before the abort. */
+ int hit_count;
+
+ /* Thread number for thread-specific tracepoint, or -1 if don't care */
+ int thread;
+
+ /* BFD section, in case of overlays:
+ no, I don't know if tracepoints are really gonna work with overlays. */
+ asection *section;
+};
+
+enum actionline_type
+{
+ BADLINE = -1,
+ GENERIC = 0,
+ END = 1,
+ STEPPING = 2
+};
+
+
+/* The tracepont chain of all tracepoints */
+
+extern struct tracepoint *tracepoint_chain;
+
+extern unsigned long trace_running_p;
+
+/* A hook used to notify the UI of tracepoint operations */
+
+void (*create_tracepoint_hook) PARAMS ((struct tracepoint *));
+void (*delete_tracepoint_hook) PARAMS ((struct tracepoint *));
+void (*modify_tracepoint_hook) PARAMS ((struct tracepoint *));
+void (*trace_find_hook) PARAMS ((char *arg, int from_tty));
+void (*trace_start_stop_hook) PARAMS ((int start, int from_tty));
+
+struct tracepoint *get_tracepoint_by_number PARAMS ((char **));
+int get_traceframe_number PARAMS ((void));
+void free_actions PARAMS((struct tracepoint *));
+enum actionline_type validate_actionline PARAMS((char **,
+ struct tracepoint *));
+
+
+/* Walk the following statement or block through all tracepoints.
+ ALL_TRACEPOINTS_SAFE does so even if the statment deletes the current
+ breakpoint. */
+
+#define ALL_TRACEPOINTS(t) for (t = tracepoint_chain; t; t = t->next)
+
+#define ALL_TRACEPOINTS_SAFE(t,tmp) \
+ for (t = tracepoint_chain; \
+ t ? (tmp = t->next, 1) : 0;\
+ t = tmp)
+#endif /* TRACEPOINT_H */
diff --git a/gdb/tui/ChangeLog b/gdb/tui/ChangeLog
new file mode 100644
index 00000000000..7dc1bf60460
--- /dev/null
+++ b/gdb/tui/ChangeLog
@@ -0,0 +1,121 @@
+1999-01-26 Jason Molenda (jsm@bugshack.cygnus.com)
+
+ * tui.h: Include stdarg.h instead of varargs.h if we're on an ISO Cish
+ system.
+
+Thu Dec 31 12:08:32 1998 David Taylor <taylor@texas.cygnus.com>
+
+ The following changes were made by Jim Blandy <jimb@cygnus.com>,
+ Edith Epstein <eepstein@cygnus.com>, Elena Zannoni
+ <ezannoni@cygnus.com> Stan Shebs <shebs@cygnus.com>, and David
+ Taylor <taylor@cygnus.com>, as part of the project to merge in
+ changes originally made by HP; HP did not create ChangeLog
+ entries.
+
+ * Makefile.in: New file; we're merging HP's changes into GDB, and
+ we've moved the TUI files into a subdirectory, so we need a new
+ Makefile.
+
+ * tui.c:
+ #include <term.h>, if we have it, to get declarations for
+ the termcap functions on Solaris.
+ (tgoto): Add external K&R declaration for this; Solaris doesn't
+ bother to actually declare it in their header files.
+ (_tuiReset): Ignore the #definition of TIOCGETC if USG is defined;
+ we'd rather use the USG mechanisms than the Berkeley mechanisms
+ (TIOCGETC is one of the Berkeley terminal control ioctls).
+ Apologies if this causes trouble later; this should all be handled
+ by autoconf...
+ (strcat_to_buf, strcat_to_buf_with_fmt): New functions, moved here
+ from ../utils.h.
+ (tuiFree): replace safe_free with free.
+ (strcat_to_buf): new function, copied from utils.c.
+ (tuiInit): Add ignored `argv0' argument, to match the type that
+ init_ui_hook expects; updated declaration. Call the
+ initialize_tui_files function constructed above. Initialize
+ flush_hook to NULL.
+ (tuiInitWindows): Call tuiSetLocatorContent, to get the first
+ element of the locator window's content allocated. This seems
+ wrong, because it must have been initialized somehow in HP's
+ sources, and we should do it the same way now. But we do get
+ further before it segfaults. [Postscript: HP didn't bother to
+ initialize it; they compile
+ (va_catch_errors, vcatch_errors): Functions moved here from
+ ../utils.c in HP's sources. They're not used anywhere else.
+ (xdb_style): Delete this variable, and remove all references to
+ it. It's always true.
+ (tuiInit, _tui_vDo): References removed.
+
+ * tui.h: Add prototypes.
+ Don't #include "gendefs.h"; it's only used in the TUI.
+ Integrate its contents into this file:
+ #include <ansidecl.h> here.
+ (Opaque, OpaqueFuncPtr): Typedefs moved to here.
+
+ * tuiCommand.c: #include "defs.h", so we get the appropriate
+ definition of GDB_FILE.
+
+ * tuiData.c
+ (freeWindow): replace safe_free with free.
+ (tui_version): don't define it here; it's defined in main.c now.
+
+ * tuiDisassem.c
+ (tuiSetDisassemContent): Call strcat_address_numeric instead of
+ strcat_address. Simplify the control structure. Use predefined
+ GDB function to print asm inst address. Use GDB_FILE to collect
+ output into buffers.
+
+ * tuiIO.c
+ (tgoto): Add external K&R declaration for this here too.
+ (tuiGetc, tuiTermSetup, tuiTermUnsetup): Same.
+ (tuiPuts_unfiltered): change FILE to GDB_FILE.
+ (tui_tputs): fix prototype for 3rd argument.
+
+ * tuiIO.h (tuiPuts_unfiltered): change declaration.
+
+ * tuiLayout.c
+ (_tuiSetLayoutTo): for displaying registers, hook up the HP code
+ that decides which registers to display (i.e. single precision
+ float, double precision float, general, special). Previously,
+ only handled TUI_GENERAL_REGS. Now that the code is hooked up,
+ compiling with -z poses a problem. When the first layout command
+ is 'layout regs', dataWin->detail is a NULL pointer, and gdb
+ core dumps.
+
+ * tuiLayout.c (_tuiSetLayoutTo): replace safe_free with free.
+
+ * tuiRegs.c #include "defs.h" earlier, to avoid problems in
+ <stdarg.h>. No idea exactly what's conflicting with what, but the
+ errors went away...
+ (_tuiRegisterFormat): Change so that function creates a GDB_FILE
+ object, calls pa_do_strcat_registers_info, copies the register
+ info into a buffer, and deallocates the GDB_FILE object. Remove
+ some code that is not executed. Also, call to
+ pa_do_strcat_registers_info has an additional parameter,
+ precision. This code requires some new per-target functions that
+ we don't want to merge. Dyke it out, with #ifdef
+ TUI_EXTENDED_FORMATTERS.
+ (_tuiSetSpecialRegsContent): this function was ifdefed out.
+ Hooked this up.
+ (_tuiSetGeneralAndSpecialRegsContent): this function was ifdefed
+ out. Hooked it up.
+ (IS_64BIT): Just define this to be zero; we're not merging in the
+ 64-bit support.
+ (tuiShowRegisters): Comment out all references to the "special"
+ regs; we don't have a distinction between the "special" and
+ "non-special" regs in most of our machine descriptions. This code
+ is PA-specific in other ways as well, and needs to be redesigned
+ to be portable to other processors.
+
+ * tuiWin.c: #include <string.h>, to get a declaration for
+ strchr.
+
+ * tui.c, tuiCommand.c, tuiData.c, tuiDataWin.c, tuiDisassem.c,
+ tuiGeneralWin.c, tuiIO.c, tuiLayout.c, tuiRegs.c, tuiSource.c,
+ tuiSourceWin.c, tuiStack.c, tuiWin.c: New files (from HP). Changed
+ bool to int throughout. Re-indented, GNU style.
+
+ * tui.h, tuiCommand.h, tuiData.h, tuiDataWin.h, tuiDisassem.h,
+ tuiGeneralWin.h, tuiIO.h, tuiLayout.h, tuiRegs.h, tuiSource.h,
+ tuiSourceWin.h, tuiStack.h, tuiWin.h: new files (from HP).
+ Changed bool to int throughout.
diff --git a/gdb/tui/Makefile.in b/gdb/tui/Makefile.in
new file mode 100644
index 00000000000..256464b5bc5
--- /dev/null
+++ b/gdb/tui/Makefile.in
@@ -0,0 +1,168 @@
+# Copyright 1998 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+all: libtui.a
+
+srcdir=@srcdir@
+VPATH = @srcdir@
+
+SHELL = @SHELL@
+
+CC=@CC@
+CFLAGS=@CFLAGS@
+AR=@AR@
+RANLIB=@RANLIB@
+
+# Host and target-dependent makefile fragments come in here.
+@host_makefile_frag@
+@target_makefile_frag@
+# End of host and target-dependent makefile fragments
+
+# Where is our "include" directory? Typically $(srcdir)/../include.
+# This is essentially the header file directory for the library
+# routines in libiberty.
+INCLUDE_DIR = $(srcdir)/../../include
+INCLUDE_CFLAGS = -I$(INCLUDE_DIR)
+
+# Configured by the --with-mmalloc option to configure.
+MMALLOC = @MMALLOC@
+MMALLOC_CFLAGS = @MMALLOC_CFLAGS@
+
+# Where is the BFD library? Typically in ../bfd.
+BFD_DIR = ../../bfd
+BFD_SRC = $(srcdir)/$(BFD_DIR)
+BFD_CFLAGS = -I$(BFD_DIR) -I$(BFD_SRC)
+
+# Where is the READLINE library? Typically in ../readline.
+READLINE_DIR = ../../readline
+READLINE_SRC = $(srcdir)/$(READLINE_DIR)
+READLINE_CFLAGS = -I$(READLINE_SRC)
+
+# Where is the INTL library? Typically in ../intl.
+INTL_DIR = ../../intl
+INTL_SRC = $(srcdir)/$(INTL_DIR)
+INTL_CFLAGS = -I$(INTL_DIR) -I$(INTL_SRC)
+
+# Where is the TCL library? Typically in ../tcl.
+TCL_CFLAGS = @TCLHDIR@
+
+# Where is the TK library? Typically in ../tk.
+TK_CFLAGS = @TKHDIR@ @TK_BUILD_INCLUDES@
+
+# Where is Itcl? Typically in ../itcl.
+ITCL_CFLAGS = @ITCLHDIR@
+
+# Where is Tix? Typically in ../tix.
+TIX_CFLAGS = @TIXHDIR@
+
+X11_CFLAGS = @TK_XINCLUDES@
+
+ENABLE_IDE= @ENABLE_IDE@
+
+GUI_CFLAGS_X = -I$(srcdir)/../../libgui/src
+
+IDE_CFLAGS_X = -I$(srcdir)/../../libidetcl/src -I$(srcdir)/../../libide/src \
+ `if [ x"$(ENABLE_IDE)" != x ] ; then \
+ echo -DIDE -I$(srcdir)/../../ilu/runtime/mainloop;\
+ fi`
+
+IDE_CFLAGS=$(GUI_CFLAGS_X) $(IDE_CFLAGS_X)
+
+ENABLE_CFLAGS= @ENABLE_CFLAGS@
+
+# -I. for config files.
+# -I$(srcdir) for gdb internal headers and possibly for gnu-regex.h also.
+# -I$(srcdir)/config for more generic config files.
+
+# It is also possible that you will need to add -I/usr/include/sys if
+# your system doesn't have fcntl.h in /usr/include (which is where it
+# should be according to Posix).
+DEFS = @DEFS@
+GDB_CFLAGS = -I. -I.. -I$(srcdir) -I$(srcdir)/.. -I$(srcdir)/../config $(DEFS)
+
+# M{H,T}_CFLAGS, if defined, have host- and target-dependent CFLAGS
+# from the config directory.
+GLOBAL_CFLAGS = $(MT_CFLAGS) $(MH_CFLAGS)
+#PROFILE_CFLAGS = -pg
+
+# INTERNAL_CFLAGS is the aggregate of all other *CFLAGS macros.
+INTERNAL_CFLAGS = $(CFLAGS) $(GLOBAL_CFLAGS) $(PROFILE_CFLAGS) \
+ $(GDB_CFLAGS) $(READLINE_CFLAGS) $(BFD_CFLAGS) \
+ $(MMALLOC_CFLAGS) $(INCLUDE_CFLAGS) $(INTL_CFLAGS) \
+ $(ENABLE_CFLAGS)
+
+HEADERS = tuiIO.h tuiData.h tuiGeneralWin.h tuiLayout.h tuiStack.h \
+ tuiSource.h tuiCommand.h tuiWin.h tuiDisassem.h \
+ tuiSourceWin.h tuiRegs.h tuiDataWin.h
+
+SOURCES = tui.c tuiData.c tuiSource.c tuiStack.c tuiIO.c \
+ tuiGeneralWin.c tuiLayout.c tuiWin.c tuiCommand.c \
+ tuiDisassem.c tuiSourceWin.c tuiRegs.c tuiDataWin.c
+
+OBJECTS = tui.o tuiData.o tuiSource.o tuiStack.o tuiIO.o \
+ tuiGeneralWin.o tuiLayout.o tuiWin.o tuiCommand.o \
+ tuiDisassem.o tuiSourceWin.o tuiRegs.o tuiDataWin.o \
+ tuiInit.o
+
+
+# Prevent Sun make from putting in the machine type. Setting
+# TARGET_ARCH to nothing works for SunOS 3, 4.0, but not for 4.1.
+.c.o:
+ $(CC) -c $(INTERNAL_CFLAGS) $<
+.SUFFIXES: .cpp
+.c.cpp:
+ $(CC) -E $(INTERNAL_CFLAGS) $< > $@
+
+libtui.a: $(OBJECTS)
+ rm -f libtui.a
+ $(AR) rc libtui.a $(OBJECTS)
+ $(RANLIB) libtui.a
+
+tui.o: tui.c tui.h tuiData.h tuiLayout.h tuiIO.h tuiRegs.h tuiWin.h
+tuiCommand.o: tui.h tuiData.h tuiWin.h tuiIO.h
+tuiData.o: tui.h tuiData.h
+tuiDataWin.o: tui.h tuiData.h tuiRegs.h
+tuiDisassem.o: tui.h tuiData.h tuiLayout.h tuiSourceWin.h tuiStack.h
+tuiGeneralWin.o: tui.h tuiData.h tuiGeneralWin.h
+tuiIO.o: tui.h tuiData.h tuiIO.h tuiCommand.h tuiWin.h
+tuiLayout.o: tui.h tuiData.h tuiGeneralWin.h tuiStack.h tuiRegs.h \
+ tuiDisassem.h
+tuiRegs.o: tui.h tuiData.h tuiLayout.h tuiWin.h
+tuiSource.o: tui.h tuiData.h tuiStack.h tuiSourceWin.h tuiSource.h
+tuiSourceWin.o: tui.h tuiData.h tuiStack.h tuiSourceWin.h tuiSource.h \
+ tuiDisassem.h
+tuiStack.o: tui.h tuiData.h tuiStack.h tuiSourceWin.h
+tuiWin.o: tui.h tuiData.h tuiGeneralWin.h tuiStack.h tuiSourceWin.h \
+ tuiDataWin.h
+
+tuiInit.o: tuiInit.c
+tuiInit.c: $(SOURCES)
+ @echo Making tuiInit.c
+ @rm -f init.c-tmp
+ @echo '/* Do not modify this file. */' >init.c-tmp
+ @echo '/* It is created automatically by the Makefile. */'>>init.c-tmp
+ @echo '#include "ansidecl.h"' >>init.c-tmp
+ @echo 'extern void initialize_tui_files PARAMS ((void));' >>init.c-tmp
+ @echo 'void initialize_tui_files PARAMS ((void)) {' >>init.c-tmp
+ @-( cd $(srcdir) ; grep '^_initialize_[a-z_0-9A-Z]* *(' $(SOURCES) ) 2>/dev/null \
+ | sed -e 's/^.*://' -e 's/^\([a-z_0-9A-Z]*\).*/ {extern void \1 PARAMS ((void)); \1 ();}/' >>init.c-tmp
+ @echo '}' >>init.c-tmp
+ @mv init.c-tmp tuiInit.c
+
+clean:
+ rm -f *.o *.a
diff --git a/gdb/tui/tui.c b/gdb/tui/tui.c
new file mode 100644
index 00000000000..f64db4442a8
--- /dev/null
+++ b/gdb/tui/tui.c
@@ -0,0 +1,830 @@
+/*
+** tui.c
+** General functions for the WDB TUI
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <malloc.h>
+#include <curses.h>
+#ifdef HAVE_TERM_H
+#include <term.h>
+#endif
+#include <signal.h>
+#include <fcntl.h>
+#include <termio.h>
+#include <setjmp.h>
+#include "defs.h"
+#include "gdbcmd.h"
+#include "tui.h"
+#include "tuiData.h"
+#include "tuiLayout.h"
+#include "tuiIO.h"
+#include "tuiRegs.h"
+#include "tuiWin.h"
+
+/* The Solaris header files seem to provide no declaration for this at
+ all when __STDC__ is defined. This shouldn't conflict with
+ anything. */
+extern char *tgoto ();
+
+/***********************
+** Local Definitions
+************************/
+#define FILEDES 2
+/* Solaris <sys/termios.h> defines CTRL. */
+#ifndef CTRL
+#define CTRL(x) (x & ~0140)
+#endif
+#define CHK(val, dft) (val<=0 ? dft : val)
+
+#define TOGGLE_USAGE "Usage:toggle breakpoints"
+#define TUI_TOGGLE_USAGE "Usage:\ttoggle $fregs\n\ttoggle breakpoints"
+
+/*****************************
+** Local static forward decls
+******************************/
+static void _tuiReset PARAMS ((void));
+static void _toggle_command PARAMS ((char *, int));
+static void _tui_vToggle_command PARAMS ((va_list));
+static Opaque _tui_vDo PARAMS ((TuiOpaqueFuncPtr, va_list));
+
+
+
+/***********************
+** Public Functions
+************************/
+
+/*
+** tuiInit().
+*/
+void
+#ifdef __STDC__
+tuiInit (char *argv0)
+#else
+tuiInit (argv0)
+ char *argv0;
+#endif
+{
+ extern void init_page_info ();
+ extern void initialize_tui_files PARAMS ((void));
+
+ initialize_tui_files ();
+ initializeStaticData ();
+ initscr ();
+ refresh ();
+ setTermHeightTo (LINES);
+ setTermWidthTo (COLS);
+ tuiInitWindows ();
+ wrefresh (cmdWin->generic.handle);
+ init_page_info ();
+ /* Don't hook debugger output if doing command-window
+ * the XDB way. However, one thing we do want to do in
+ * XDB style is set up the scrolling region to be
+ * the bottom of the screen (tuiTermUnsetup()).
+ */
+ fputs_unfiltered_hook = NULL;
+ flush_hook = NULL;
+ rl_initialize (); /* need readline initialization to
+ * create termcap sequences
+ */
+ tuiTermUnsetup (1, cmdWin->detail.commandInfo.curch);
+
+ return;
+} /* tuiInit */
+
+
+/*
+** tuiInitWindows().
+*/
+void
+#ifdef __STDC__
+tuiInitWindows (void)
+#else
+tuiInitWindows ()
+#endif
+{
+ TuiWinType type;
+
+ tuiSetLocatorContent (0);
+ showLayout (SRC_COMMAND);
+ keypad (cmdWin->generic.handle, TRUE);
+ echo ();
+ crmode ();
+ nl ();
+ tuiSetWinFocusTo (srcWin);
+
+ return;
+} /* tuiInitWindows */
+
+
+/*
+** tuiCleanUp().
+** Kill signal handler and cleanup termination method
+*/
+void
+#ifdef __STDC__
+tuiResetScreen (void)
+#else
+tuiResetScreen ()
+#endif
+{
+ TuiWinType type = SRC_WIN;
+
+ keypad (cmdWin->generic.handle, FALSE);
+ for (; type < MAX_MAJOR_WINDOWS; type++)
+ {
+ if (m_winPtrNotNull (winList[type]) &&
+ winList[type]->generic.type != UNDEFINED_WIN &&
+ !winList[type]->generic.isVisible)
+ tuiDelWindow (winList[type]);
+ }
+ endwin ();
+ initscr ();
+ refresh ();
+ echo ();
+ crmode ();
+ nl ();
+
+ return;
+} /* tuiResetScreen */
+
+
+/*
+** tuiCleanUp().
+** Kill signal handler and cleanup termination method
+*/
+void
+#ifdef __STDC__
+tuiCleanUp (void)
+#else
+tuiCleanUp ()
+#endif
+{
+ char *buffer;
+ extern char *term_cursor_move;
+
+ signal (SIGINT, SIG_IGN);
+ tuiTermSetup (0); /* Restore scrolling region to whole screen */
+ keypad (cmdWin->generic.handle, FALSE);
+ freeAllWindows ();
+ endwin ();
+ buffer = tgoto (term_cursor_move, 0, termHeight ());
+ tputs (buffer, 1, putchar);
+ _tuiReset ();
+
+ return;
+} /* tuiCleanUp */
+
+
+/*
+** tuiError().
+*/
+void
+#ifdef __STDC__
+tuiError (
+ char *string,
+ int exitGdb)
+#else
+tuiError (string, exitGdb)
+ char *string;
+ int exitGdb;
+#endif
+{
+ puts_unfiltered (string);
+ if (exitGdb)
+ {
+ tuiCleanUp ();
+ exit (-1);
+ }
+
+ return;
+} /* tuiError */
+
+
+/*
+** tui_vError()
+** tuiError with args in a va_list.
+*/
+void
+#ifdef __STDC__
+tui_vError (
+ va_list args)
+#else
+tui_vError (args)
+ va_list args;
+#endif
+{
+ char *string;
+ int exitGdb;
+
+ string = va_arg (args, char *);
+ exitGdb = va_arg (args, int);
+
+ tuiError (string, exitGdb);
+
+ return;
+} /* tui_vError */
+
+
+/*
+** tuiFree()
+** Wrapper on top of free() to ensure that input address is greater than 0x0
+*/
+void
+#ifdef __STDC__
+tuiFree (
+ char *ptr)
+#else
+tuiFree (ptr)
+ char *ptr;
+#endif
+{
+ if (ptr != (char *) NULL)
+ {
+ free (ptr);
+ }
+
+ return;
+} /* tuiFree */
+
+
+/* tuiGetLowDisassemblyAddress().
+** Determine what the low address will be to display in the TUI's
+** disassembly window. This may or may not be the same as the
+** low address input.
+*/
+Opaque
+#ifdef __STDC__
+tuiGetLowDisassemblyAddress (
+ Opaque low,
+ Opaque pc)
+#else
+tuiGetLowDisassemblyAddress (low, pc)
+ Opaque low;
+ Opaque pc;
+#endif
+{
+ int line;
+ Opaque newLow;
+
+ /*
+ ** Determine where to start the disassembly so that the pc is about in the
+ ** middle of the viewport.
+ */
+ for (line = 0, newLow = pc;
+ (newLow > low &&
+ line < (tuiDefaultWinViewportHeight (DISASSEM_WIN,
+ DISASSEM_COMMAND) / 2));)
+ {
+ bfd_byte buffer[4];
+
+ newLow -= sizeof (bfd_getb32 (buffer));
+ line++;
+ }
+
+ return newLow;
+} /* tuiGetLowDisassemblyAddress */
+
+
+/* tui_vGetLowDisassemblyAddress().
+** Determine what the low address will be to display in the TUI's
+** disassembly window with args in a va_list.
+*/
+Opaque
+#ifdef __STDC__
+tui_vGetLowDisassemblyAddress (
+ va_list args)
+#else
+tui_vGetLowDisassemblyAddress (args)
+ va_list args;
+#endif
+{
+ int line;
+ Opaque newLow;
+ Opaque low;
+ Opaque pc;
+
+ low = va_arg (args, Opaque);
+ pc = va_arg (args, Opaque);
+
+ return (tuiGetLowDisassemblyAddress (low, pc));
+
+} /* tui_vGetLowDisassemblyAddress */
+
+
+/*
+** tuiDo().
+** General purpose function to execute a tui function. Transitions
+** between curses and the are handled here. This function is called
+** by non-tui gdb functions.
+**
+** Errors are caught here.
+** If there is no error, the value returned by 'func' is returned.
+** If there is an error, then zero is returned.
+**
+** 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.
+*/
+Opaque
+#ifdef __STDC__
+tuiDo (
+ TuiOpaqueFuncPtr func,...)
+#else
+tuiDo (func, va_alist)
+ TuiOpaqueFuncPtr func;
+ va_dcl
+#endif
+{
+ extern int terminal_is_ours;
+
+ Opaque ret = (Opaque) NULL;
+
+ /* It is an error to be tuiDo'ing if we
+ * don't own the terminal.
+ */
+ if (!terminal_is_ours)
+ return ret;
+
+ if (tui_version)
+ {
+ va_list args;
+
+#ifdef __STDC__
+ va_start (args, func);
+#else
+ va_start (args);
+#endif
+ ret = _tui_vDo (func, args);
+ va_end (args);
+ }
+
+ return ret;
+} /* tuiDo */
+
+
+/*
+** tuiDoAndReturnToTop().
+** General purpose function to execute a tui function. Transitions
+** between curses and the are handled here. This function is called
+** by non-tui gdb functions who wish to reset gdb to the top level.
+** After the tuiDo is performed, a return to the top level occurs.
+**
+** Errors are caught here.
+** If there is no error, the value returned by 'func' is returned.
+** If there is an error, then zero is returned.
+**
+** 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.
+**
+*/
+Opaque
+#ifdef __STDC__
+tuiDoAndReturnToTop (
+ TuiOpaqueFuncPtr func,...)
+#else
+tuiDoAndReturnToTop (func, va_alist)
+ TuiOpaqueFuncPtr func;
+ va_dcl
+#endif
+{
+ extern int terminal_is_ours;
+
+ Opaque ret = (Opaque) NULL;
+
+ /* It is an error to be tuiDo'ing if we
+ * don't own the terminal.
+ */
+ if (!terminal_is_ours)
+ return ret;
+
+ if (tui_version)
+ {
+ va_list args;
+
+#ifdef __STDC__
+ va_start (args, func);
+#else
+ va_start (args);
+#endif
+ ret = _tui_vDo (func, args);
+
+ /* force a return to the top level */
+ return_to_top_level (RETURN_ERROR);
+ }
+
+ return ret;
+} /* tuiDoAndReturnToTop */
+
+
+void
+#ifdef __STDC__
+tui_vSelectSourceSymtab (
+ va_list args)
+#else
+tui_vSelectSourceSymtab (args)
+ va_list args;
+#endif
+{
+ struct symtab *s = va_arg (args, struct symtab *);
+
+ select_source_symtab (s);
+ return;
+} /* tui_vSelectSourceSymtab */
+
+
+/*
+** _initialize_tui().
+** Function to initialize gdb commands, for tui window manipulation.
+*/
+void
+_initialize_tui ()
+{
+#if 0
+ if (tui_version)
+ {
+ add_com ("toggle", class_tui, _toggle_command,
+ "Toggle Terminal UI Features\n\
+Usage: Toggle $fregs\n\
+\tToggles between single and double precision floating point registers.\n");
+ }
+#endif
+ char *helpStr;
+
+ if (tui_version)
+ helpStr = "Toggle Specified Features\n\
+Usage:\ttoggle $fregs\n\ttoggle breakpoints";
+ else
+ helpStr = "Toggle Specified Features\nUsage:toggle breakpoints";
+ add_abbrev_prefix_cmd ("toggle",
+ class_tui,
+ _toggle_command,
+ helpStr,
+ &togglelist,
+ "toggle ",
+ 1,
+ &cmdlist);
+} /* _initialize_tui*/
+
+
+/*
+** va_catch_errors().
+** General purpose function to execute a function, catching errors.
+** If there is no error, the value returned by 'func' is returned.
+** If there is error, then zero is returned.
+** Note that 'func' must take a variable argument list as well.
+**
+** 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.
+*/
+Opaque
+#ifdef __STDC__
+va_catch_errors (
+ TuiOpaqueFuncPtr func,
+ va_list args)
+#else
+va_catch_errors (func, args)
+ TuiOpaqueFuncPtr func;
+ va_list args;
+#endif
+{
+ Opaque ret = (Opaque) NULL;
+
+ /*
+ ** We could have used catch_errors(), but it doesn't handle variable args.
+ ** Also, for the tui, we always want to catch all errors, so we don't
+ ** need to pass a mask, or an error string.
+ */
+ jmp_buf saved_error;
+ jmp_buf saved_quit;
+ jmp_buf tmp_jmp;
+ struct cleanup *saved_cleanup_chain;
+ char *saved_error_pre_print;
+ char *saved_quit_pre_print;
+ extern jmp_buf error_return;
+ extern jmp_buf quit_return;
+
+ saved_cleanup_chain = save_cleanups ();
+ saved_error_pre_print = error_pre_print;
+ saved_quit_pre_print = quit_pre_print;
+
+ memcpy ((char *) saved_error, (char *) error_return, sizeof (jmp_buf));
+ error_pre_print = "";
+ memcpy (saved_quit, quit_return, sizeof (jmp_buf));
+ quit_pre_print = "";
+
+ if (setjmp (tmp_jmp) == 0)
+ {
+ va_list argList = args;
+ memcpy (error_return, tmp_jmp, sizeof (jmp_buf));
+ memcpy (quit_return, tmp_jmp, sizeof (jmp_buf));
+ ret = func (argList);
+ }
+ restore_cleanups (saved_cleanup_chain);
+ memcpy (error_return, saved_error, sizeof (jmp_buf));
+ error_pre_print = saved_error_pre_print;
+ memcpy (quit_return, saved_quit, sizeof (jmp_buf));
+ quit_pre_print = saved_quit_pre_print;
+
+ return ret;
+}
+
+/*
+** vcatch_errors().
+** Catch errors occurring in tui or non tui function, handling
+** variable param lists. Note that 'func' must take a variable
+** argument list as well.
+*/
+Opaque
+#ifdef __STDC__
+vcatch_errors (
+ OpaqueFuncPtr func,...)
+#else
+vcatch_errors (va_alist)
+ va_dcl
+/*
+vcatch_errors(func, va_alist)
+ OpaqueFuncPtr func;
+ va_dcl
+*/
+#endif
+{
+ Opaque ret = (Opaque) NULL;
+ va_list args;
+#ifdef __STDC__
+ va_start (args, func);
+/*
+ va_arg(args, OpaqueFuncPtr);
+*/
+#else
+ OpaqueFuncPtr func;
+
+ va_start (args);
+ func = va_arg (args, OpaqueFuncPtr);
+#endif
+ ret = va_catch_errors (func, args);
+ va_end (args);
+
+ return ret;
+}
+
+
+void
+#ifdef __STDC__
+strcat_to_buf (
+ char *buf,
+ int buflen,
+ char *itemToAdd)
+#else
+strcat_to_buf (buf, buflen, itemToAdd)
+ char *buf;
+ int buflen;
+ char *itemToAdd;
+#endif
+{
+ if (itemToAdd != (char *) NULL && buf != (char *) NULL)
+ {
+ if ((strlen (buf) + strlen (itemToAdd)) <= buflen)
+ strcat (buf, itemToAdd);
+ else
+ strncat (buf, itemToAdd, (buflen - strlen (buf)));
+ }
+
+ return;
+} /* strcat_to_buf */
+
+/* VARARGS */
+void
+#ifdef ANSI_PROTOTYPES
+strcat_to_buf_with_fmt (
+ char *buf,
+ int bufLen,
+ char *format,...)
+#else
+strcat_to_buf_with_fmt (va_alist)
+ va_dcl
+#endif
+{
+ char *linebuffer;
+ struct cleanup *old_cleanups;
+ va_list args;
+#ifdef ANSI_PROTOTYPES
+ va_start (args, format);
+#else
+ char *buf;
+ int bufLen;
+ char *format;
+
+ va_start (args);
+ buf = va_arg (args, char *);
+ bufLen = va_arg (args, int);
+ format = va_arg (args, char *);
+#endif
+ vasprintf (&linebuffer, format, args);
+ old_cleanups = make_cleanup (free, linebuffer);
+ strcat_to_buf (buf, bufLen, linebuffer);
+ do_cleanups (old_cleanups);
+ va_end (args);
+}
+
+
+
+
+
+/***********************
+** Static Functions
+************************/
+
+
+/*
+** _tui_vDo().
+** General purpose function to execute a tui function. Transitions
+** between curses and the are handled here. This function is called
+** by non-tui gdb functions.
+**
+** Errors are caught here.
+** If there is no error, the value returned by 'func' is returned.
+** If there is an error, then zero is returned.
+**
+** 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.
+*/
+static Opaque
+#ifdef __STDC__
+_tui_vDo (
+ TuiOpaqueFuncPtr func,
+ va_list args)
+#else
+_tui_vDo (func, args)
+ TuiOpaqueFuncPtr func;
+ va_list args;
+#endif
+{
+ extern int terminal_is_ours;
+
+ Opaque ret = (Opaque) NULL;
+
+ /* It is an error to be tuiDo'ing if we
+ * don't own the terminal.
+ */
+ if (!terminal_is_ours)
+ return ret;
+
+ if (tui_version)
+ {
+ /* If doing command window the "XDB way" (command window
+ * is unmanaged by curses...
+ */
+ /* Set up terminal for TUI */
+ tuiTermSetup (1);
+
+ ret = va_catch_errors (func, args);
+
+ /* Set up terminal for command window */
+ tuiTermUnsetup (1, cmdWin->detail.commandInfo.curch);
+ }
+
+ return ret;
+} /* _tui_vDo */
+
+
+static void
+#ifdef __STDC__
+_toggle_command (
+ char *arg,
+ int fromTTY)
+#else
+_toggle_command (arg, fromTTY)
+ char *arg;
+ int fromTTY;
+#endif
+{
+ printf_filtered ("Specify feature to toggle.\n%s\n",
+ (tui_version) ? TUI_TOGGLE_USAGE : TOGGLE_USAGE);
+/*
+ tuiDo((TuiOpaqueFuncPtr)_Toggle_command, arg, fromTTY);
+*/
+}
+
+/*
+** _tui_vToggle_command().
+*/
+static void
+#ifdef __STDC__
+_tui_vToggle_command (
+ va_list args)
+#else
+_tui_vToggle_command (args)
+ va_list args;
+#endif
+{
+ char *arg;
+ int fromTTY;
+
+ arg = va_arg (args, char *);
+
+ if (arg == (char *) NULL)
+ printf_filtered (TOGGLE_USAGE);
+ else
+ {
+ char *ptr = (char *) tuiStrDup (arg);
+ int i;
+
+ for (i = 0; (ptr[i]); i++)
+ ptr[i] = toupper (arg[i]);
+
+ if (subsetCompare (ptr, TUI_FLOAT_REGS_NAME))
+ tuiToggleFloatRegs ();
+/* else if (subsetCompare(ptr, "ANOTHER TOGGLE OPTION"))
+ ...
+*/
+ else
+ printf_filtered (TOGGLE_USAGE);
+ tuiFree (ptr);
+ }
+
+ return;
+} /* _tuiToggle_command */
+
+
+static void
+#ifdef __STDC__
+_tuiReset (void)
+#else
+_tuiReset ()
+#endif
+{
+ struct termio mode;
+
+ /*
+ ** reset the teletype mode bits to a sensible state.
+ ** Copied tset.c
+ */
+#if ! defined (USG) && defined (TIOCGETC)
+ struct tchars tbuf;
+#endif /* !USG && TIOCGETC */
+#ifdef UCB_NTTY
+ struct ltchars ltc;
+
+ if (ldisc == NTTYDISC)
+ {
+ ioctl (FILEDES, TIOCGLTC, &ltc);
+ ltc.t_suspc = CHK (ltc.t_suspc, CTRL ('Z'));
+ ltc.t_dsuspc = CHK (ltc.t_dsuspc, CTRL ('Y'));
+ ltc.t_rprntc = CHK (ltc.t_rprntc, CTRL ('R'));
+ ltc.t_flushc = CHK (ltc.t_flushc, CTRL ('O'));
+ ltc.t_werasc = CHK (ltc.t_werasc, CTRL ('W'));
+ ltc.t_lnextc = CHK (ltc.t_lnextc, CTRL ('V'));
+ ioctl (FILEDES, TIOCSLTC, &ltc);
+ }
+#endif /* UCB_NTTY */
+#ifndef USG
+#ifdef TIOCGETC
+ ioctl (FILEDES, TIOCGETC, &tbuf);
+ tbuf.t_intrc = CHK (tbuf.t_intrc, CTRL ('?'));
+ tbuf.t_quitc = CHK (tbuf.t_quitc, CTRL ('\\'));
+ tbuf.t_startc = CHK (tbuf.t_startc, CTRL ('Q'));
+ tbuf.t_stopc = CHK (tbuf.t_stopc, CTRL ('S'));
+ tbuf.t_eofc = CHK (tbuf.t_eofc, CTRL ('D'));
+ /* brkc is left alone */
+ ioctl (FILEDES, TIOCSETC, &tbuf);
+#endif /* TIOCGETC */
+ mode.sg_flags &= ~(RAW
+#ifdef CBREAK
+ | CBREAK
+#endif /* CBREAK */
+ | VTDELAY | ALLDELAY);
+ mode.sg_flags |= XTABS | ECHO | CRMOD | ANYP;
+#else /*USG*/
+ ioctl (FILEDES, TCGETA, &mode);
+ mode.c_cc[VINTR] = CHK (mode.c_cc[VINTR], CTRL ('?'));
+ mode.c_cc[VQUIT] = CHK (mode.c_cc[VQUIT], CTRL ('\\'));
+ mode.c_cc[VEOF] = CHK (mode.c_cc[VEOF], CTRL ('D'));
+
+ mode.c_iflag &= ~(IGNBRK | PARMRK | INPCK | INLCR | IGNCR | IUCLC | IXOFF);
+ mode.c_iflag |= (BRKINT | ISTRIP | ICRNL | IXON);
+ mode.c_oflag &= ~(OLCUC | OCRNL | ONOCR | ONLRET | OFILL | OFDEL |
+ NLDLY | CRDLY | TABDLY | BSDLY | VTDLY | FFDLY);
+ mode.c_oflag |= (OPOST | ONLCR);
+ mode.c_cflag &= ~(CSIZE | PARODD | CLOCAL);
+#ifndef hp9000s800
+ mode.c_cflag |= (CS8 | CREAD);
+#else /*hp9000s800*/
+ mode.c_cflag |= (CS8 | CSTOPB | CREAD);
+#endif /* hp9000s800 */
+ mode.c_lflag &= ~(XCASE | ECHONL | NOFLSH);
+ mode.c_lflag |= (ISIG | ICANON | ECHO | ECHOK);
+ ioctl (FILEDES, TCSETAW, &mode);
+#endif /* USG */
+
+ return;
+} /* _tuiReset */
diff --git a/gdb/tui/tui.h b/gdb/tui/tui.h
new file mode 100644
index 00000000000..bc9fb31e649
--- /dev/null
+++ b/gdb/tui/tui.h
@@ -0,0 +1,120 @@
+/* External/Public TUI Header File */
+
+#ifndef TUI_H
+#define TUI_H
+#include <curses.h>
+
+#ifdef ANSI_PROTOTYPES
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+
+#include "ansidecl.h"
+
+#if defined(reg)
+#undef reg
+#endif
+#if defined(chtype)
+#undef chtype
+#endif
+
+/* Opaque data type */
+typedef char *Opaque;
+typedef Opaque (*OpaqueFuncPtr) PARAMS ((va_list));
+typedef char **OpaqueList;
+typedef OpaqueList OpaquePtr;
+
+/* Generic function pointer */
+typedef void (*TuiVoidFuncPtr) PARAMS ((va_list));
+typedef int (*TuiIntFuncPtr) PARAMS ((va_list));
+/*
+typedef Opaque (*TuiOpaqueFuncPtr) PARAMS ((va_list));
+*/
+typedef OpaqueFuncPtr TuiOpaqueFuncPtr;
+
+extern Opaque vcatch_errors PARAMS ((OpaqueFuncPtr, ...));
+extern Opaque va_catch_errors PARAMS ((OpaqueFuncPtr, va_list));
+
+extern void strcat_to_buf PARAMS ((char *, int, char *));
+extern void strcat_to_buf_with_fmt PARAMS ((char *, int, char *, ...));
+
+/* Types of error returns */
+typedef enum {
+ TUI_SUCCESS,
+ TUI_FAILURE
+} TuiStatus, *TuiStatusPtr;
+
+/* Types of windows */
+typedef enum {
+ SRC_WIN = 0,
+ DISASSEM_WIN,
+ DATA_WIN,
+ CMD_WIN,
+ /* This must ALWAYS be AFTER the major windows last */
+ MAX_MAJOR_WINDOWS,
+ /* auxillary windows */
+ LOCATOR_WIN,
+ EXEC_INFO_WIN,
+ DATA_ITEM_WIN,
+ /* This must ALWAYS be next to last */
+ MAX_WINDOWS,
+ UNDEFINED_WIN /* LAST */
+} TuiWinType, *TuiWinTypePtr;
+
+/* This is a point definition */
+typedef struct _TuiPoint {
+ int x, y;
+} TuiPoint, *TuiPointPtr;
+
+/* Generic window information */
+typedef struct _TuiGenWinInfo {
+ WINDOW *handle; /* window handle */
+ TuiWinType type; /* type of window */
+ int width; /* window width */
+ int height; /* window height */
+ TuiPoint origin; /* origin of window */
+ OpaquePtr content; /* content of window */
+ int contentSize; /* Size of content (# of elements) */
+ int contentInUse; /* Can it be used, or is it already used? */
+ int viewportHeight; /* viewport height */
+ int lastVisibleLine; /* index of last visible line */
+ int isVisible; /* whether the window is visible or not */
+} TuiGenWinInfo, *TuiGenWinInfoPtr;
+
+/* GENERAL TUI FUNCTIONS */
+/* tui.c */
+extern void tuiInit PARAMS ((char *argv0));
+extern void tuiInitWindows PARAMS ((void));
+extern void tuiResetScreen PARAMS ((void));
+extern void tuiCleanUp PARAMS ((void));
+extern void tuiError PARAMS ((char *, int));
+extern void tui_vError PARAMS ((va_list));
+extern void tuiFree PARAMS ((char *));
+extern Opaque tuiDo PARAMS ((TuiOpaqueFuncPtr, ...));
+extern Opaque tuiDoAndReturnToTop PARAMS ((TuiOpaqueFuncPtr, ...));
+extern Opaque tuiGetLowDisassemblyAddress PARAMS ((Opaque, Opaque));
+extern Opaque tui_vGetLowDisassemblyAddress PARAMS ((va_list));
+extern void tui_vSelectSourceSymtab PARAMS ((va_list));
+
+/* tuiDataWin.c */
+extern void tui_vCheckDataValues PARAMS ((va_list));
+
+/* tuiIO.c */
+extern void tui_vStartNewLines PARAMS ((va_list));
+
+/* tuiLayout.c */
+extern void tui_vAddWinToLayout PARAMS ((va_list));
+extern TuiStatus tui_vSetLayoutTo PARAMS ((va_list));
+
+/* tuiSourceWin.c */
+extern void tuiDisplayMainFunction PARAMS ((void));
+extern void tuiUpdateAllExecInfos PARAMS ((void));
+extern void tuiUpdateOnEnd PARAMS ((void));
+extern void tui_vAllSetHasBreakAt PARAMS ((va_list));
+extern void tui_vUpdateSourceWindowsWithAddr PARAMS ((va_list));
+
+/* tuiStack.c */
+extern void tui_vShowFrameInfo PARAMS ((va_list));
+extern void tui_vUpdateLocatorFilename PARAMS ((va_list));
+#endif /* TUI_H */
diff --git a/gdb/tui/tuiCommand.c b/gdb/tui/tuiCommand.c
new file mode 100644
index 00000000000..454dc62e857
--- /dev/null
+++ b/gdb/tui/tuiCommand.c
@@ -0,0 +1,215 @@
+/*
+** tuiCommand.c
+** This module contains functions specific to command window processing.
+*/
+
+
+#include "defs.h"
+#include "tui.h"
+#include "tuiData.h"
+#include "tuiWin.h"
+#include "tuiIO.h"
+
+
+/*****************************************
+** STATIC LOCAL FUNCTIONS FORWARD DECLS **
+******************************************/
+
+
+
+/*****************************************
+** PUBLIC FUNCTIONS **
+******************************************/
+
+/*
+** tuiDispatchCtrlChar().
+** Dispatch the correct tui function based upon the control character.
+*/
+unsigned int
+#ifdef __STDC__
+tuiDispatchCtrlChar (
+ unsigned int ch)
+#else
+tuiDispatchCtrlChar (ch)
+ unsigned int ch;
+#endif
+{
+ TuiWinInfoPtr winInfo = tuiWinWithFocus ();
+
+ /*
+ ** If the command window has the logical focus, or no-one does
+ ** assume it is the command window; in this case, pass the
+ ** character on through and do nothing here.
+ */
+ if (winInfo == (TuiWinInfoPtr) NULL || winInfo == cmdWin)
+ return ch;
+ else
+ {
+ unsigned int c = 0, chCopy = ch;
+ register int i;
+ char *term;
+
+ /* If this is an xterm, page next/prev keys aren't returned
+ ** by keypad as a single char, so we must handle them here.
+ ** Seems like a bug in the curses library?
+ */
+ term = (char *) getenv ("TERM");
+ for (i = 0; (term && term[i]); i++)
+ term[i] = toupper (term[i]);
+ if ((strcmp (term, "XTERM") == 0) && m_isStartSequence (ch))
+ {
+ unsigned int pageCh = 0, tmpChar;
+
+ tmpChar = 0;
+ while (!m_isEndSequence (tmpChar))
+ {
+ tmpChar = (int) wgetch (cmdWin->generic.handle);
+ if (!tmpChar)
+ break;
+ if (tmpChar == 53)
+ pageCh = KEY_PPAGE;
+ else if (tmpChar == 54)
+ pageCh = KEY_NPAGE;
+ }
+ chCopy = pageCh;
+ }
+
+ switch (chCopy)
+ {
+ case KEY_NPAGE:
+ tuiScrollForward (winInfo, 0);
+ break;
+ case KEY_PPAGE:
+ tuiScrollBackward (winInfo, 0);
+ break;
+ case KEY_DOWN:
+ case KEY_SF:
+ tuiScrollForward (winInfo, 1);
+ break;
+ case KEY_UP:
+ case KEY_SR:
+ tuiScrollBackward (winInfo, 1);
+ break;
+ case KEY_RIGHT:
+ tuiScrollLeft (winInfo, 1);
+ break;
+ case KEY_LEFT:
+ tuiScrollRight (winInfo, 1);
+ break;
+ case '\f':
+ tuiRefreshAll ();
+ break;
+ default:
+ c = chCopy;
+ break;
+ }
+ return c;
+ }
+} /* tuiDispatchCtrlChar */
+
+
+/*
+** tuiIncrCommandCharCountBy()
+** Increment the current character count in the command window,
+** checking for overflow. Returns the new value of the char count.
+*/
+int
+#ifdef __STDC__
+tuiIncrCommandCharCountBy (
+ int count)
+#else
+tuiIncrCommandCharCountBy (count)
+ int count;
+#endif
+{
+ if (tui_version)
+ {
+ if ((count + cmdWin->detail.commandInfo.curch) >= cmdWin->generic.width)
+ cmdWin->detail.commandInfo.curch =
+ (count + cmdWin->detail.commandInfo.curch) - cmdWin->generic.width;
+ else
+ cmdWin->detail.commandInfo.curch += count;
+ }
+
+ return cmdWin->detail.commandInfo.curch;
+} /* tuiIncrCommandCharCountBy */
+
+
+/*
+** tuiDecrCommandCharCountBy()
+** Decrement the current character count in the command window,
+** checking for overflow. Returns the new value of the char count.
+*/
+int
+#ifdef __STDC__
+tuiDecrCommandCharCountBy (
+ int count)
+#else
+tuiDecrCommandCharCountBy (count)
+ int count;
+#endif
+{
+ if (tui_version)
+ {
+ if ((cmdWin->detail.commandInfo.curch - count) < 0)
+ cmdWin->detail.commandInfo.curch =
+ cmdWin->generic.width + (cmdWin->detail.commandInfo.curch - count);
+ else
+ cmdWin->detail.commandInfo.curch -= count;
+ }
+
+ return cmdWin->detail.commandInfo.curch;
+} /* tuiDecrCommandCharCountBy */
+
+
+/*
+** tuiSetCommandCharCountTo()
+** Set the character count to count.
+*/
+int
+#ifdef __STDC__
+tuiSetCommandCharCountTo (
+ int count)
+#else
+tuiSetCommandCharCountTo (count)
+ int count;
+#endif
+{
+ if (tui_version)
+ {
+ if (count > cmdWin->generic.width - 1)
+ {
+ cmdWin->detail.commandInfo.curch = 0;
+ tuiIncrCommandCharCountBy (count);
+ }
+ else
+ cmdWin->detail.commandInfo.curch -= count;
+ }
+
+ return cmdWin->detail.commandInfo.curch;
+} /* tuiSetCommandCharCountTo */
+
+
+
+/*
+** tuiClearCommandCharCount()
+** Clear the character count to count.
+*/
+int
+#ifdef __STDC__
+tuiClearCommandCharCount (void)
+#else
+tuiClearCommandCharCount ()
+#endif
+{
+ if (tui_version)
+ cmdWin->detail.commandInfo.curch = 0;
+
+ return cmdWin->detail.commandInfo.curch;
+} /* tuiClearCommandCharCount */
+
+
+
+/*****************************************
+** STATIC LOCAL FUNCTIONS **
+******************************************/
diff --git a/gdb/tui/tuiCommand.h b/gdb/tui/tuiCommand.h
new file mode 100644
index 00000000000..206d918dd56
--- /dev/null
+++ b/gdb/tui/tuiCommand.h
@@ -0,0 +1,24 @@
+#ifndef _TUI_COMMAND_H
+#define _TUI_COMMAND_H
+/*
+** This header file supports
+*/
+
+
+/*****************************************
+** TYPE DEFINITIONS **
+******************************************/
+
+
+
+/*****************************************
+** PUBLIC FUNCTION EXTERNAL DECLS **
+******************************************/
+
+extern unsigned int tuiDispatchCtrlChar PARAMS ((unsigned int));
+extern int tuiIncrCommandCharCountBy PARAMS ((int));
+extern int tuiDecrCommandCharCountBy PARAMS ((int));
+extern int tuiSetCommandCharCountTo PARAMS ((int));
+extern int tuiClearCommandCharCount PARAMS ((void));
+
+#endif /*_TUI_COMMAND_H*/
diff --git a/gdb/tui/tuiData.c b/gdb/tui/tuiData.c
new file mode 100644
index 00000000000..758a6cde492
--- /dev/null
+++ b/gdb/tui/tuiData.c
@@ -0,0 +1,1624 @@
+/*
+** tuiData.c
+** This module contains functions for manipulating the data
+** structures used by the TUI
+*/
+
+#include "defs.h"
+#include "tui.h"
+#include "tuiData.h"
+
+/****************************
+** GLOBAL DECLARATIONS
+****************************/
+TuiWinInfoPtr winList[MAX_MAJOR_WINDOWS];
+
+/***************************
+** Private Definitions
+****************************/
+#define FILE_WIDTH 30
+#define PROC_WIDTH 40
+#define LINE_WIDTH 4
+#define PC_WIDTH 8
+
+/***************************
+** Private data
+****************************/
+static char *_tuiNullStr = TUI_NULL_STR;
+static char *_tuiBlankStr = " ";
+static char *_tuiLocationStr = " >";
+static char *_tuiBreakStr = " * ";
+static char *_tuiBreakLocationStr = " *>";
+static TuiLayoutType _currentLayout = UNDEFINED_LAYOUT;
+static int _termHeight, _termWidth;
+static int _historyLimit = DEFAULT_HISTORY_COUNT;
+static TuiGenWinInfo _locator;
+static TuiGenWinInfo _execInfo[2];
+static TuiWinInfoPtr _srcWinList[2];
+static TuiList _sourceWindows =
+{(OpaqueList) _srcWinList, 0};
+static int _defaultTabLen = DEFAULT_TAB_LEN;
+static TuiWinInfoPtr _winWithFocus = (TuiWinInfoPtr) NULL;
+static TuiLayoutDef _layoutDef =
+{SRC_WIN, /* displayMode */
+ FALSE, /* split */
+ TUI_UNDEFINED_REGS, /* regsDisplayType */
+ TUI_SFLOAT_REGS}; /* floatRegsDisplayType */
+static int _winResized = FALSE;
+
+
+/*********************************
+** Static function forward decls
+**********************************/
+static void freeContent PARAMS ((TuiWinContent, int, TuiWinType));
+static void freeContentElements PARAMS ((TuiWinContent, int, TuiWinType));
+
+
+
+/*********************************
+** PUBLIC FUNCTIONS
+**********************************/
+
+/******************************************
+** ACCESSORS & MUTATORS FOR PRIVATE DATA
+******************************************/
+
+/*
+** tuiWinResized().
+** Answer a whether the terminal window has been resized or not
+*/
+int
+#ifdef __STDC__
+tuiWinResized (void)
+#else
+tuiWinResized ()
+#endif
+{
+ return _winResized;
+} /* tuiWinResized */
+
+
+/*
+** tuiSetWinResized().
+** Set a whether the terminal window has been resized or not
+*/
+void
+#ifdef __STDC__
+tuiSetWinResizedTo (
+ int resized)
+#else
+tuiSetWinResizedTo (resized)
+ int resized;
+#endif
+{
+ _winResized = resized;
+
+ return;
+} /* tuiSetWinResizedTo */
+
+
+/*
+** tuiLayoutDef().
+** Answer a pointer to the current layout definition
+*/
+TuiLayoutDefPtr
+#ifdef __STDC__
+tuiLayoutDef (void)
+#else
+tuiLayoutDef ()
+#endif
+{
+ return &_layoutDef;
+} /* tuiLayoutDef */
+
+
+/*
+** tuiWinWithFocus().
+** Answer the window with the logical focus
+*/
+TuiWinInfoPtr
+#ifdef __STDC__
+tuiWinWithFocus (void)
+#else
+tuiWinWithFocus ()
+#endif
+{
+ return _winWithFocus;
+} /* tuiWinWithFocus */
+
+
+/*
+** tuiSetWinWithFocus().
+** Set the window that has the logical focus
+*/
+void
+#ifdef __STDC__
+tuiSetWinWithFocus (
+ TuiWinInfoPtr winInfo)
+#else
+tuiSetWinWithFocus (winInfo)
+ TuiWinInfoPtr winInfo;
+#endif
+{
+ _winWithFocus = winInfo;
+
+ return;
+} /* tuiSetWinWithFocus */
+
+
+/*
+** tuiDefaultTabLen().
+** Answer the length in chars, of tabs
+*/
+int
+#ifdef __STDC__
+tuiDefaultTabLen (void)
+#else
+tuiDefaultTabLen ()
+#endif
+{
+ return _defaultTabLen;
+} /* tuiDefaultTabLen */
+
+
+/*
+** tuiSetDefaultTabLen().
+** Set the length in chars, of tabs
+*/
+void
+#ifdef __STDC__
+tuiSetDefaultTabLen (
+ int len)
+#else
+tuiSetDefaultTabLen (len)
+ int len;
+#endif
+{
+ _defaultTabLen = len;
+
+ return;
+} /* tuiSetDefaultTabLen */
+
+
+/*
+** currentSourceWin()
+** Accessor for the current source window. Usually there is only
+** one source window (either source or disassembly), but both can
+** be displayed at the same time.
+*/
+TuiListPtr
+#ifdef __STDC__
+sourceWindows (void)
+#else
+sourceWindows ()
+#endif
+{
+ return &_sourceWindows;
+} /* currentSourceWindows */
+
+
+/*
+** clearSourceWindows()
+** Clear the list of source windows. Usually there is only one
+** source window (either source or disassembly), but both can be
+** displayed at the same time.
+*/
+void
+#ifdef __STDC__
+clearSourceWindows (void)
+#else
+clearSourceWindows ()
+#endif
+{
+ _sourceWindows.list[0] = (Opaque) NULL;
+ _sourceWindows.list[1] = (Opaque) NULL;
+ _sourceWindows.count = 0;
+
+ return;
+} /* currentSourceWindows */
+
+
+/*
+** clearSourceWindowsDetail()
+** Clear the pertinant detail in the source windows.
+*/
+void
+#ifdef __STDC__
+clearSourceWindowsDetail (void)
+#else
+clearSourceWindowsDetail ()
+#endif
+{
+ int i;
+
+ for (i = 0; i < (sourceWindows ())->count; i++)
+ clearWinDetail ((TuiWinInfoPtr) (sourceWindows ())->list[i]);
+
+ return;
+} /* currentSourceWindows */
+
+
+/*
+** addSourceWindowToList().
+** Add a window to the list of source windows. Usually there is
+** only one source window (either source or disassembly), but
+** both can be displayed at the same time.
+*/
+void
+#ifdef __STDC__
+addToSourceWindows (
+ TuiWinInfoPtr winInfo)
+#else
+addToSourceWindows (winInfo)
+ TuiWinInfoPtr winInfo;
+#endif
+{
+ if (_sourceWindows.count < 2)
+ _sourceWindows.list[_sourceWindows.count++] = (Opaque) winInfo;
+
+ return;
+} /* addToSourceWindows */
+
+
+/*
+** clearWinDetail()
+** Clear the pertinant detail in the windows.
+*/
+void
+#ifdef __STDC__
+clearWinDetail (
+ TuiWinInfoPtr winInfo)
+#else
+clearWinDetail (winInfo)
+ TuiWinInfoPtr winInfo;
+#endif
+{
+ if (m_winPtrNotNull (winInfo))
+ {
+ switch (winInfo->generic.type)
+ {
+ case SRC_WIN:
+ case DISASSEM_WIN:
+ winInfo->detail.sourceInfo.startLineOrAddr.addr = (Opaque) NULL;
+ winInfo->detail.sourceInfo.horizontalOffset = 0;
+ break;
+ case CMD_WIN:
+ winInfo->detail.commandInfo.curLine =
+ winInfo->detail.commandInfo.curch = 0;
+ break;
+ case DATA_WIN:
+ winInfo->detail.dataDisplayInfo.dataContent =
+ (TuiWinContent) NULL;
+ winInfo->detail.dataDisplayInfo.dataContentCount = 0;
+ winInfo->detail.dataDisplayInfo.regsContent =
+ (TuiWinContent) NULL;
+ winInfo->detail.dataDisplayInfo.regsContentCount = 0;
+ winInfo->detail.dataDisplayInfo.regsDisplayType =
+ TUI_UNDEFINED_REGS;
+ winInfo->detail.dataDisplayInfo.regsColumnCount = 1;
+ winInfo->detail.dataDisplayInfo.displayRegs = FALSE;
+ break;
+ default:
+ break;
+ }
+ }
+
+ return;
+} /* clearWinDetail */
+
+
+/*
+** blankStr()
+** Accessor for the blank string.
+*/
+char *
+#ifdef __STDC__
+blankStr (void)
+#else
+blankStr ()
+#endif
+{
+ return _tuiBlankStr;
+} /* blankStr */
+
+
+/*
+** locationStr()
+** Accessor for the location string.
+*/
+char *
+#ifdef __STDC__
+locationStr (void)
+#else
+locationStr ()
+#endif
+{
+ return _tuiLocationStr;
+} /* locationStr */
+
+
+/*
+** breakStr()
+** Accessor for the break string.
+*/
+char *
+#ifdef __STDC__
+breakStr (void)
+#else
+breakStr ()
+#endif
+{
+ return _tuiBreakStr;
+} /* breakStr */
+
+
+/*
+** breakLocationStr()
+** Accessor for the breakLocation string.
+*/
+char *
+#ifdef __STDC__
+breakLocationStr (void)
+#else
+breakLocationStr ()
+#endif
+{
+ return _tuiBreakLocationStr;
+} /* breakLocationStr */
+
+
+/*
+** nullStr()
+** Accessor for the null string.
+*/
+char *
+#ifdef __STDC__
+nullStr (void)
+#else
+nullStr ()
+#endif
+{
+ return _tuiNullStr;
+} /* nullStr */
+
+
+/*
+** sourceExecInfoPtr().
+** Accessor for the source execution info ptr.
+*/
+TuiGenWinInfoPtr
+#ifdef __STDC__
+sourceExecInfoWinPtr (void)
+#else
+sourceExecInfoWinPtr ()
+#endif
+{
+ return &_execInfo[0];
+} /* sourceExecInfoWinPtr */
+
+
+/*
+** disassemExecInfoPtr().
+** Accessor for the disassem execution info ptr.
+*/
+TuiGenWinInfoPtr
+#ifdef __STDC__
+disassemExecInfoWinPtr (void)
+#else
+disassemExecInfoWinPtr ()
+#endif
+{
+ return &_execInfo[1];
+} /* disassemExecInfoWinPtr */
+
+
+/*
+** locatorWinInfoPtr().
+** Accessor for the locator win info. Answers a pointer to the
+** static locator win info struct.
+*/
+TuiGenWinInfoPtr
+#ifdef __STDC__
+locatorWinInfoPtr (void)
+#else
+locatorWinInfoPtr ()
+#endif
+{
+ return &_locator;
+} /* locatorWinInfoPtr */
+
+
+/*
+** historyLimit().
+** Accessor for the history limit
+*/
+int
+#ifdef __STDC__
+historyLimit (void)
+#else
+historyLimit ()
+#endif
+{
+ return _historyLimit;
+} /* historyLimit */
+
+
+/*
+** setHistoryLimitTo().
+** Mutator for the history limit
+*/
+void
+#ifdef __STDC__
+setHistoryLimitTo (
+ int h)
+#else
+setHistoryLimitTo (h)
+ int h;
+#endif
+{
+ _historyLimit = h;
+
+ return;
+} /* setHistoryLimitTo */
+
+/*
+** termHeight().
+** Accessor for the termHeight
+*/
+int
+#ifdef __STDC__
+termHeight (void)
+#else
+termHeight ()
+#endif
+{
+ return _termHeight;
+} /* termHeight */
+
+
+/*
+** setTermHeightTo().
+** Mutator for the term height
+*/
+void
+#ifdef __STDC__
+setTermHeightTo (
+ int h)
+#else
+setTermHeightTo (h)
+ int h;
+#endif
+{
+ _termHeight = h;
+
+ return;
+} /* setTermHeightTo */
+
+
+/*
+** termWidth().
+** Accessor for the termWidth
+*/
+int
+#ifdef __STDC__
+termWidth (void)
+#else
+termWidth ()
+#endif
+{
+ return _termWidth;
+} /* termWidth */
+
+
+/*
+** setTermWidth().
+** Mutator for the termWidth
+*/
+void
+#ifdef __STDC__
+setTermWidthTo (
+ int w)
+#else
+setTermWidthTo (w)
+ int w;
+#endif
+{
+ _termWidth = w;
+
+ return;
+} /* setTermWidthTo */
+
+
+/*
+** currentLayout().
+** Accessor for the current layout
+*/
+TuiLayoutType
+#ifdef __STDC__
+currentLayout (void)
+#else
+currentLayout ()
+#endif
+{
+ return _currentLayout;
+} /* currentLayout */
+
+
+/*
+** setCurrentLayoutTo().
+** Mutator for the current layout
+*/
+void
+#ifdef __STDC__
+setCurrentLayoutTo (
+ TuiLayoutType newLayout)
+#else
+setCurrentLayoutTo (newLayout)
+ TuiLayoutType newLayout;
+#endif
+{
+ _currentLayout = newLayout;
+
+ return;
+} /* setCurrentLayoutTo */
+
+
+/*
+** setGenWinOrigin().
+** Set the origin of the window
+*/
+void
+#ifdef __STDC__
+setGenWinOrigin (
+ TuiGenWinInfoPtr winInfo,
+ int x,
+ int y)
+#else
+setGenWinOrigin (winInfo, x, y)
+ TuiGenWinInfoPtr winInfo;
+ int x;
+ int y;
+#endif
+{
+ winInfo->origin.x = x;
+ winInfo->origin.y = y;
+
+ return;
+} /* setGenWinOrigin */
+
+
+/*****************************
+** OTHER PUBLIC FUNCTIONS
+*****************************/
+
+
+/*
+** tuiNextWin().
+** Answer the next window in the list, cycling back to the top
+** if necessary
+*/
+TuiWinInfoPtr
+#ifdef __STDC__
+tuiNextWin (
+ TuiWinInfoPtr curWin)
+#else
+tuiNextWin (curWin)
+ TuiWinInfoPtr curWin;
+#endif
+{
+ TuiWinType type = curWin->generic.type;
+ TuiWinInfoPtr nextWin = (TuiWinInfoPtr) NULL;
+
+ if (curWin->generic.type == CMD_WIN)
+ type = SRC_WIN;
+ else
+ type = curWin->generic.type + 1;
+ while (type != curWin->generic.type && m_winPtrIsNull (nextWin))
+ {
+ if (winList[type]->generic.isVisible)
+ nextWin = winList[type];
+ else
+ {
+ if (type == CMD_WIN)
+ type = SRC_WIN;
+ else
+ type++;
+ }
+ }
+
+ return nextWin;
+} /* tuiNextWin */
+
+
+/*
+** tuiPrevWin().
+** Answer the prev window in the list, cycling back to the bottom
+** if necessary
+*/
+TuiWinInfoPtr
+#ifdef __STDC__
+tuiPrevWin (
+ TuiWinInfoPtr curWin)
+#else
+tuiPrevWin (curWin)
+ TuiWinInfoPtr curWin;
+#endif
+{
+ TuiWinType type = curWin->generic.type;
+ TuiWinInfoPtr prev = (TuiWinInfoPtr) NULL;
+
+ if (curWin->generic.type == SRC_WIN)
+ type = CMD_WIN;
+ else
+ type = curWin->generic.type - 1;
+ while (type != curWin->generic.type && m_winPtrIsNull (prev))
+ {
+ if (winList[type]->generic.isVisible)
+ prev = winList[type];
+ else
+ {
+ if (type == SRC_WIN)
+ type = CMD_WIN;
+ else
+ type--;
+ }
+ }
+
+ return prev;
+} /* tuiPrevWin */
+
+
+/*
+** displayableWinContentOf().
+** Answer a the content at the location indicated by index. Note
+** that if this is a locator window, the string returned should be
+** freed after use.
+*/
+char *
+#ifdef __STDC__
+displayableWinContentOf (
+ TuiGenWinInfoPtr winInfo,
+ TuiWinElementPtr elementPtr)
+#else
+displayableWinContentOf (winInfo, elementPtr)
+ TuiGenWinInfoPtr winInfo;
+ TuiWinElementPtr elementPtr;
+#endif
+{
+
+ char *string = nullStr ();
+
+ if (elementPtr != (TuiWinElementPtr) NULL || winInfo->type == LOCATOR_WIN)
+ {
+ /*
+ ** Now convert the line to a displayable string
+ */
+ switch (winInfo->type)
+ {
+ case SRC_WIN:
+ case DISASSEM_WIN:
+ string = elementPtr->whichElement.source.line;
+ break;
+ case CMD_WIN:
+ string = elementPtr->whichElement.command.line;
+ break;
+ case LOCATOR_WIN:
+ if ((string = (char *) xmalloc (
+ (termWidth () + 1) * sizeof (char))) == (char *) NULL)
+ string = nullStr ();
+ else
+ {
+ char lineNo[50], pc[50], buf[50], *fname, *pname;
+ register int strSize = termWidth (), i, procWidth, fileWidth;
+
+ /*
+ ** First determine the amount of file/proc name width
+ ** we have available
+ */
+ i = strSize - (PC_WIDTH + LINE_WIDTH
+ + 25 /* pc and line labels */
+ + strlen (FILE_PREFIX) + 1 /* file label */
+ + 15 /* procedure label */ );
+ if (i >= FILE_WIDTH + PROC_WIDTH)
+ {
+ fileWidth = FILE_WIDTH;
+ procWidth = PROC_WIDTH;
+ }
+ else
+ {
+ fileWidth = i / 2;
+ procWidth = i - fileWidth;
+ }
+
+ /* Now convert elements to string form */
+ if (elementPtr != (TuiWinElementPtr) NULL &&
+ *elementPtr->whichElement.locator.fileName != (char) 0 &&
+ srcWin->generic.isVisible)
+ fname = elementPtr->whichElement.locator.fileName;
+ else
+ fname = "??";
+ if (elementPtr != (TuiWinElementPtr) NULL &&
+ *elementPtr->whichElement.locator.procName != (char) 0)
+ pname = elementPtr->whichElement.locator.procName;
+ else
+ pname = "??";
+ if (elementPtr != (TuiWinElementPtr) NULL &&
+ elementPtr->whichElement.locator.lineNo > 0)
+ sprintf (lineNo, "%d",
+ elementPtr->whichElement.locator.lineNo);
+ else
+ strcpy (lineNo, "??");
+ if (elementPtr != (TuiWinElementPtr) NULL &&
+ elementPtr->whichElement.locator.addr > (Opaque) 0)
+ sprintf (pc, "0x%x",
+ elementPtr->whichElement.locator.addr);
+ else
+ strcpy (pc, "??");
+ /*
+ ** Now create the locator line from the string version
+ ** of the elements. We could use sprintf() here but
+ ** that wouldn't ensure that we don't overrun the size
+ ** of the allocated buffer. strcat_to_buf() will.
+ */
+ *string = (char) 0;
+ /* Filename */
+ strcat_to_buf (string, strSize, " ");
+ strcat_to_buf (string, strSize, FILE_PREFIX);
+ if (strlen (fname) > fileWidth)
+ {
+ strncpy (buf, fname, fileWidth - 1);
+ buf[fileWidth - 1] = '*';
+ buf[fileWidth] = (char) 0;
+ }
+ else
+ strcpy (buf, fname);
+ strcat_to_buf (string, strSize, buf);
+ /* procedure/class name */
+ sprintf (buf, "%15s", PROC_PREFIX);
+ strcat_to_buf (string, strSize, buf);
+ if (strlen (pname) > procWidth)
+ {
+ strncpy (buf, pname, procWidth - 1);
+ buf[procWidth - 1] = '*';
+ buf[procWidth] = (char) 0;
+ }
+ else
+ strcpy (buf, pname);
+ strcat_to_buf (string, strSize, buf);
+ sprintf (buf, "%10s", LINE_PREFIX);
+ strcat_to_buf (string, strSize, buf);
+ strcat_to_buf (string, strSize, lineNo);
+ sprintf (buf, "%10s", PC_PREFIX);
+ strcat_to_buf (string, strSize, buf);
+ strcat_to_buf (string, strSize, pc);
+ for (i = strlen (string); i < strSize; i++)
+ string[i] = ' ';
+ string[strSize] = (char) 0;
+ }
+ break;
+ case EXEC_INFO_WIN:
+ string = elementPtr->whichElement.simpleString;
+ break;
+ default:
+ break;
+ }
+ }
+ return string;
+} /* displayableWinContentOf */
+
+
+/*
+** winContentAt().
+** Answer a the content at the location indicated by index
+*/
+char *
+#ifdef __STDC__
+displayableWinContentAt (
+ TuiGenWinInfoPtr winInfo,
+ int index)
+#else
+displayableWinContentAt (winInfo, index)
+ TuiGenWinInfoPtr winInfo;
+ int index;
+#endif
+{
+ return (displayableWinContentOf (winInfo, (TuiWinElementPtr) winInfo->content[index]));
+} /* winContentAt */
+
+
+/*
+** winElementHeight().
+** Answer the height of the element in lines
+*/
+int
+#ifdef __STDC__
+winElementHeight (
+ TuiGenWinInfoPtr winInfo,
+ TuiWinElementPtr element)
+#else
+winElementHeight (winInfo, element)
+ TuiGenWinInfoPtr winInfo;
+ TuiWinElementPtr element;
+#endif
+{
+ int h;
+
+ if (winInfo->type == DATA_WIN)
+/* FOR NOW SAY IT IS ONLY ONE LINE HIGH */
+ h = 1;
+ else
+ h = 1;
+
+ return h;
+} /* winElementHeight */
+
+
+/*
+** winByName().
+** Answer the window represented by name
+*/
+TuiWinInfoPtr
+#ifdef __STDC__
+winByName (
+ char *name)
+#else
+winByName (name)
+ char *name;
+#endif
+{
+ TuiWinInfoPtr winInfo = (TuiWinInfoPtr) NULL;
+ int i = 0;
+
+ while (i < MAX_MAJOR_WINDOWS && m_winPtrIsNull (winInfo))
+ {
+ if (strcmp (name, winName (&(winList[i]->generic))) == 0)
+ winInfo = winList[i];
+ i++;
+ }
+
+ return winInfo;
+} /* winByName */
+
+
+/*
+** partialWinByName().
+** Answer the window represented by name
+*/
+TuiWinInfoPtr
+#ifdef __STDC__
+partialWinByName (
+ char *name)
+#else
+partialWinByName (name)
+ char *name;
+#endif
+{
+ TuiWinInfoPtr winInfo = (TuiWinInfoPtr) NULL;
+
+ if (name != (char *) NULL)
+ {
+ int i = 0;
+
+ while (i < MAX_MAJOR_WINDOWS && m_winPtrIsNull (winInfo))
+ {
+ char *curName = winName (&winList[i]->generic);
+ if (strlen (name) <= strlen (curName) &&
+ strncmp (name, curName, strlen (name)) == 0)
+ winInfo = winList[i];
+ i++;
+ }
+ }
+
+ return winInfo;
+} /* partialWinByName */
+
+
+/*
+** winName().
+** Answer the name of the window
+*/
+char *
+#ifdef __STDC__
+winName (
+ TuiGenWinInfoPtr winInfo)
+#else
+winName (winInfo)
+ TuiGenWinInfoPtr winInfo;
+#endif
+{
+ char *name = (char *) NULL;
+
+ switch (winInfo->type)
+ {
+ case SRC_WIN:
+ name = SRC_NAME;
+ break;
+ case CMD_WIN:
+ name = CMD_NAME;
+ break;
+ case DISASSEM_WIN:
+ name = DISASSEM_NAME;
+ break;
+ case DATA_WIN:
+ name = DATA_NAME;
+ break;
+ default:
+ name = "";
+ break;
+ }
+
+ return name;
+} /* winName */
+
+
+/*
+** initializeStaticData
+*/
+void
+#ifdef __STDC__
+initializeStaticData (void)
+#else
+initializeStaticData ()
+#endif
+{
+ initGenericPart (sourceExecInfoWinPtr ());
+ initGenericPart (disassemExecInfoWinPtr ());
+ initGenericPart (locatorWinInfoPtr ());
+
+ return;
+} /* initializeStaticData */
+
+
+/*
+** allocGenericWinInfo().
+*/
+TuiGenWinInfoPtr
+#ifdef __STDC__
+allocGenericWinInfo (void)
+#else
+allocGenericWinInfo ()
+#endif
+{
+ TuiGenWinInfoPtr win;
+
+ if ((win = (TuiGenWinInfoPtr) xmalloc (
+ sizeof (TuiGenWinInfoPtr))) != (TuiGenWinInfoPtr) NULL)
+ initGenericPart (win);
+
+ return win;
+} /* allocGenericWinInfo */
+
+
+/*
+** initGenericPart().
+*/
+void
+#ifdef __STDC__
+initGenericPart (
+ TuiGenWinInfoPtr win)
+#else
+initGenericPart (win)
+ TuiGenWinInfoPtr win;
+#endif
+{
+ win->width =
+ win->height =
+ win->origin.x =
+ win->origin.y =
+ win->viewportHeight =
+ win->contentSize =
+ win->lastVisibleLine = 0;
+ win->handle = (WINDOW *) NULL;
+ win->content = (OpaquePtr) NULL;
+ win->contentInUse =
+ win->isVisible = FALSE;
+
+ return;
+} /* initGenericPart */
+
+
+/*
+** initContentElement().
+*/
+void
+#ifdef __STDC__
+initContentElement (
+ TuiWinElementPtr element,
+ TuiWinType type)
+#else
+initContentElement (element, type)
+ TuiWinElementPtr element;
+ TuiWinType type;
+#endif
+{
+ element->highlight = FALSE;
+ switch (type)
+ {
+ case SRC_WIN:
+ case DISASSEM_WIN:
+ element->whichElement.source.line = (char *) NULL;
+ element->whichElement.source.lineOrAddr.lineNo = 0;
+ element->whichElement.source.isExecPoint = FALSE;
+ element->whichElement.source.hasBreak = FALSE;
+ break;
+ case DATA_WIN:
+ initGenericPart (&element->whichElement.dataWindow);
+ element->whichElement.dataWindow.type = DATA_ITEM_WIN;
+ ((TuiGenWinInfoPtr) & element->whichElement.dataWindow)->content =
+ (OpaquePtr) allocContent (1, DATA_ITEM_WIN);
+ ((TuiGenWinInfoPtr)
+ & element->whichElement.dataWindow)->contentSize = 1;
+ break;
+ case CMD_WIN:
+ element->whichElement.command.line = (char *) NULL;
+ break;
+ case DATA_ITEM_WIN:
+ element->whichElement.data.name = (char *) NULL;
+ element->whichElement.data.type = TUI_REGISTER;
+ element->whichElement.data.itemNo = UNDEFINED_ITEM;
+ element->whichElement.data.value = (Opaque) NULL;
+ element->whichElement.data.highlight = FALSE;
+ break;
+ case LOCATOR_WIN:
+ element->whichElement.locator.fileName[0] =
+ element->whichElement.locator.procName[0] = (char) 0;
+ element->whichElement.locator.lineNo = 0;
+ element->whichElement.locator.addr = 0;
+ break;
+ case EXEC_INFO_WIN:
+ element->whichElement.simpleString = blankStr ();
+ break;
+ default:
+ break;
+ }
+ return;
+} /* initContentElement */
+
+/*
+** initWinInfo().
+*/
+void
+#ifdef __STDC__
+initWinInfo (
+ TuiWinInfoPtr winInfo)
+#else
+initWinInfo (winInfo)
+ TuiWinInfoPtr winInfo;
+#endif
+{
+ initGenericPart (&winInfo->generic);
+ winInfo->canHighlight =
+ winInfo->isHighlighted = FALSE;
+ switch (winInfo->generic.type)
+ {
+ case SRC_WIN:
+ case DISASSEM_WIN:
+ winInfo->detail.sourceInfo.executionInfo = (TuiGenWinInfoPtr) NULL;
+ winInfo->detail.sourceInfo.hasLocator = FALSE;
+ winInfo->detail.sourceInfo.horizontalOffset = 0;
+ winInfo->detail.sourceInfo.startLineOrAddr.addr = (Opaque) NULL;
+ break;
+ case DATA_WIN:
+ winInfo->detail.dataDisplayInfo.dataContent = (TuiWinContent) NULL;
+ winInfo->detail.dataDisplayInfo.dataContentCount = 0;
+ winInfo->detail.dataDisplayInfo.regsContent = (TuiWinContent) NULL;
+ winInfo->detail.dataDisplayInfo.regsContentCount = 0;
+ winInfo->detail.dataDisplayInfo.regsDisplayType =
+ TUI_UNDEFINED_REGS;
+ winInfo->detail.dataDisplayInfo.regsColumnCount = 1;
+ winInfo->detail.dataDisplayInfo.displayRegs = FALSE;
+ break;
+ case CMD_WIN:
+ winInfo->detail.commandInfo.curLine = 0;
+ winInfo->detail.commandInfo.curch = 0;
+ break;
+ default:
+ winInfo->detail.opaque = (Opaque) NULL;
+ break;
+ }
+
+ return;
+} /* initWinInfo */
+
+
+/*
+** allocWinInfo().
+*/
+TuiWinInfoPtr
+#ifdef __STDC__
+allocWinInfo (
+ TuiWinType type)
+#else
+allocWinInfo (type)
+ TuiWinType type;
+#endif
+{
+ TuiWinInfoPtr winInfo = (TuiWinInfoPtr) NULL;
+
+ winInfo = (TuiWinInfoPtr) xmalloc (sizeof (TuiWinInfo));
+ if (m_winPtrNotNull (winInfo))
+ {
+ winInfo->generic.type = type;
+ initWinInfo (winInfo);
+ }
+
+ return winInfo;
+} /* allocWinInfo */
+
+
+/*
+** allocContent().
+** Allocates the content and elements in a block.
+*/
+TuiWinContent
+#ifdef __STDC__
+allocContent (
+ int numElements,
+ TuiWinType type)
+#else
+allocContent (numElements, type)
+ int numElements;
+ TuiWinType type;
+#endif
+{
+ TuiWinContent content = (TuiWinContent) NULL;
+ char *elementBlockPtr = (char *) NULL;
+ int i;
+
+ if ((content = (TuiWinContent)
+ xmalloc (sizeof (TuiWinElementPtr) * numElements)) != (TuiWinContent) NULL)
+ { /*
+ ** All windows, except the data window, can allocate the elements
+ ** in a chunk. The data window cannot because items can be
+ ** added/removed from the data display by the user at any time.
+ */
+ if (type != DATA_WIN)
+ {
+ if ((elementBlockPtr = (char *)
+ xmalloc (sizeof (TuiWinElement) * numElements)) != (char *) NULL)
+ {
+ for (i = 0; i < numElements; i++)
+ {
+ content[i] = (TuiWinElementPtr) elementBlockPtr;
+ initContentElement (content[i], type);
+ elementBlockPtr += sizeof (TuiWinElement);
+ }
+ }
+ else
+ {
+ tuiFree ((char *) content);
+ content = (TuiWinContent) NULL;
+ }
+ }
+ }
+
+ return content;
+} /* allocContent */
+
+
+/*
+** addContentElements().
+** Adds the input number of elements to the windows's content. If
+** no content has been allocated yet, allocContent() is called to
+** do this. The index of the first element added is returned,
+** unless there is a memory allocation error, in which case, (-1)
+** is returned.
+*/
+int
+#ifdef __STDC__
+addContentElements (
+ TuiGenWinInfoPtr winInfo,
+ int numElements)
+#else
+addContentElements (winInfo, numElements)
+ TuiGenWinInfoPtr winInfo;
+ int numElements;
+#endif
+{
+ TuiWinElementPtr elementPtr;
+ int i, indexStart;
+
+ if (winInfo->content == (OpaquePtr) NULL)
+ {
+ winInfo->content = (OpaquePtr) allocContent (numElements, winInfo->type);
+ indexStart = 0;
+ }
+ else
+ indexStart = winInfo->contentSize;
+ if (winInfo->content != (OpaquePtr) NULL)
+ {
+ for (i = indexStart; (i < numElements + indexStart); i++)
+ {
+ if ((elementPtr = (TuiWinElementPtr)
+ xmalloc (sizeof (TuiWinElement))) != (TuiWinElementPtr) NULL)
+ {
+ winInfo->content[i] = (Opaque) elementPtr;
+ initContentElement (elementPtr, winInfo->type);
+ winInfo->contentSize++;
+ }
+ else /* things must be really hosed now! We ran out of memory!?*/
+ return (-1);
+ }
+ }
+
+ return indexStart;
+} /* addContentElements */
+
+
+/*
+** tuiDelWindow().
+** Delete all curses windows associated with winInfo, leaving everything
+** else in tact.
+*/
+void
+#ifdef __STDC__
+tuiDelWindow (
+ TuiWinInfoPtr winInfo)
+#else
+tuiDelWindow (winInfo)
+ TuiWinInfoPtr winInfo;
+#endif
+{
+ Opaque detail;
+ int i;
+ TuiGenWinInfoPtr genericWin;
+
+
+ switch (winInfo->generic.type)
+ {
+ case SRC_WIN:
+ case DISASSEM_WIN:
+ genericWin = locatorWinInfoPtr ();
+ if (genericWin != (TuiGenWinInfoPtr) NULL)
+ {
+ tuiDelwin (genericWin->handle);
+ genericWin->handle = (WINDOW *) NULL;
+ genericWin->isVisible = FALSE;
+ }
+ genericWin = winInfo->detail.sourceInfo.executionInfo;
+ if (genericWin != (TuiGenWinInfoPtr) NULL)
+ {
+ tuiDelwin (genericWin->handle);
+ genericWin->handle = (WINDOW *) NULL;
+ genericWin->isVisible = FALSE;
+ }
+ break;
+ case DATA_WIN:
+ if (winInfo->generic.content != (OpaquePtr) NULL)
+ {
+ int i;
+
+ tuiDelDataWindows (
+ winInfo->detail.dataDisplayInfo.regsContent,
+ winInfo->detail.dataDisplayInfo.regsContentCount);
+ tuiDelDataWindows (
+ winInfo->detail.dataDisplayInfo.dataContent,
+ winInfo->detail.dataDisplayInfo.dataContentCount);
+ }
+ break;
+ default:
+ break;
+ }
+ if (winInfo->generic.handle != (WINDOW *) NULL)
+ {
+ tuiDelwin (winInfo->generic.handle);
+ winInfo->generic.handle = (WINDOW *) NULL;
+ winInfo->generic.isVisible = FALSE;
+ }
+
+ return;
+} /* tuiDelWindow */
+
+
+/*
+** freeWindow().
+*/
+void
+#ifdef __STDC__
+freeWindow (
+ TuiWinInfoPtr winInfo)
+#else
+freeWindow (winInfo)
+ TuiWinInfoPtr winInfo;
+#endif
+{
+ Opaque detail;
+ int i;
+ TuiGenWinInfoPtr genericWin;
+
+
+ switch (winInfo->generic.type)
+ {
+ case SRC_WIN:
+ case DISASSEM_WIN:
+ genericWin = locatorWinInfoPtr ();
+ if (genericWin != (TuiGenWinInfoPtr) NULL)
+ {
+ tuiDelwin (genericWin->handle);
+ genericWin->handle = (WINDOW *) NULL;
+ }
+ freeWinContent (genericWin);
+ genericWin = winInfo->detail.sourceInfo.executionInfo;
+ if (genericWin != (TuiGenWinInfoPtr) NULL)
+ {
+ tuiDelwin (genericWin->handle);
+ genericWin->handle = (WINDOW *) NULL;
+ freeWinContent (genericWin);
+ }
+ break;
+ case DATA_WIN:
+ if (winInfo->generic.content != (OpaquePtr) NULL)
+ {
+ freeDataContent (
+ winInfo->detail.dataDisplayInfo.regsContent,
+ winInfo->detail.dataDisplayInfo.regsContentCount);
+ winInfo->detail.dataDisplayInfo.regsContent =
+ (TuiWinContent) NULL;
+ winInfo->detail.dataDisplayInfo.regsContentCount = 0;
+ freeDataContent (
+ winInfo->detail.dataDisplayInfo.dataContent,
+ winInfo->detail.dataDisplayInfo.dataContentCount);
+ winInfo->detail.dataDisplayInfo.dataContent =
+ (TuiWinContent) NULL;
+ winInfo->detail.dataDisplayInfo.dataContentCount = 0;
+ winInfo->detail.dataDisplayInfo.regsDisplayType =
+ TUI_UNDEFINED_REGS;
+ winInfo->detail.dataDisplayInfo.regsColumnCount = 1;
+ winInfo->detail.dataDisplayInfo.displayRegs = FALSE;
+ winInfo->generic.content = (OpaquePtr) NULL;
+ winInfo->generic.contentSize = 0;
+ }
+ break;
+ default:
+ break;
+ }
+ if (winInfo->generic.handle != (WINDOW *) NULL)
+ {
+ tuiDelwin (winInfo->generic.handle);
+ winInfo->generic.handle = (WINDOW *) NULL;
+ freeWinContent (&winInfo->generic);
+ }
+ free (winInfo);
+
+ return;
+} /* freeWindow */
+
+
+/*
+** freeAllSourceWinsContent().
+*/
+void
+#ifdef __STDC__
+freeAllSourceWinsContent (void)
+#else
+freeAllSourceWinsContent ()
+#endif
+{
+ int i;
+
+ for (i = 0; i < (sourceWindows ())->count; i++)
+ {
+ TuiWinInfoPtr winInfo = (TuiWinInfoPtr) (sourceWindows ())->list[i];
+
+ if (m_winPtrNotNull (winInfo))
+ {
+ freeWinContent (&(winInfo->generic));
+ freeWinContent (winInfo->detail.sourceInfo.executionInfo);
+ }
+ }
+
+ return;
+} /* freeAllSourceWinsContent */
+
+
+/*
+** freeWinContent().
+*/
+void
+#ifdef __STDC__
+freeWinContent (
+ TuiGenWinInfoPtr winInfo)
+#else
+freeWinContent (winInfo)
+ TuiGenWinInfoPtr winInfo;
+#endif
+{
+ if (winInfo->content != (OpaquePtr) NULL)
+ {
+ freeContent ((TuiWinContent) winInfo->content,
+ winInfo->contentSize,
+ winInfo->type);
+ winInfo->content = (OpaquePtr) NULL;
+ }
+ winInfo->contentSize = 0;
+
+ return;
+} /* freeWinContent */
+
+
+/*
+** freeAllWindows().
+*/
+void
+#ifdef __STDC__
+freeAllWindows (void)
+#else
+freeAllWindows ()
+#endif
+{
+ TuiWinType type = SRC_WIN;
+
+ for (; type < MAX_MAJOR_WINDOWS; type++)
+ if (m_winPtrNotNull (winList[type]) &&
+ winList[type]->generic.type != UNDEFINED_WIN)
+ freeWindow (winList[type]);
+ return;
+} /* freeAllWindows */
+
+
+void
+#ifdef __STDC__
+tuiDelDataWindows (
+ TuiWinContent content,
+ int contentSize)
+#else
+tuiDelDataWindows (content, contentSize)
+ TuiWinContent content;
+ int contentSize;
+#endif
+{
+ int i;
+
+ /*
+ ** Remember that data window content elements are of type TuiGenWinInfoPtr,
+ ** each of which whose single element is a data element.
+ */
+ for (i = 0; i < contentSize; i++)
+ {
+ TuiGenWinInfoPtr genericWin = &content[i]->whichElement.dataWindow;
+
+ if (genericWin != (TuiGenWinInfoPtr) NULL)
+ {
+ tuiDelwin (genericWin->handle);
+ genericWin->handle = (WINDOW *) NULL;
+ genericWin->isVisible = FALSE;
+ }
+ }
+
+ return;
+} /* tuiDelDataWindows */
+
+
+void
+#ifdef __STDC__
+freeDataContent (
+ TuiWinContent content,
+ int contentSize)
+#else
+freeDataContent (content, contentSize)
+ TuiWinContent content;
+ int contentSize;
+#endif
+{
+ int i;
+
+ /*
+ ** Remember that data window content elements are of type TuiGenWinInfoPtr,
+ ** each of which whose single element is a data element.
+ */
+ for (i = 0; i < contentSize; i++)
+ {
+ TuiGenWinInfoPtr genericWin = &content[i]->whichElement.dataWindow;
+
+ if (genericWin != (TuiGenWinInfoPtr) NULL)
+ {
+ tuiDelwin (genericWin->handle);
+ genericWin->handle = (WINDOW *) NULL;
+ freeWinContent (genericWin);
+ }
+ }
+ freeContent (content,
+ contentSize,
+ DATA_WIN);
+
+ return;
+} /* freeDataContent */
+
+
+/**********************************
+** LOCAL STATIC FUNCTIONS **
+**********************************/
+
+
+/*
+** freeContent().
+*/
+static void
+#ifdef __STDC__
+freeContent (
+ TuiWinContent content,
+ int contentSize,
+ TuiWinType winType)
+#else
+freeContent (content, contentSize, winType)
+ TuiWinContent content;
+ int contentSize;
+ TuiWinType winType;
+#endif
+{
+ if (content != (TuiWinContent) NULL)
+ {
+ freeContentElements (content, contentSize, winType);
+ tuiFree ((char *) content);
+ }
+
+ return;
+} /* freeContent */
+
+
+/*
+** freeContentElements().
+*/
+static void
+#ifdef __STDC__
+freeContentElements (
+ TuiWinContent content,
+ int contentSize,
+ TuiWinType type)
+#else
+freeContentElements (content, contentSize, type)
+ TuiWinContent content;
+ int contentSize;
+ TuiWinType type;
+#endif
+{
+ if (content != (TuiWinContent) NULL)
+ {
+ int i;
+
+ if (type == SRC_WIN || type == DISASSEM_WIN)
+ {
+ /* free whole source block */
+ if (content[0]->whichElement.source.line != (char *) NULL)
+ tuiFree (content[0]->whichElement.source.line);
+ }
+ else
+ {
+ for (i = 0; i < contentSize; i++)
+ {
+ TuiWinElementPtr element;
+
+ element = content[i];
+ if (element != (TuiWinElementPtr) NULL)
+ {
+ switch (type)
+ {
+ case DATA_WIN:
+ tuiFree ((char *) element);
+ break;
+ case DATA_ITEM_WIN:
+ /*
+ ** Note that data elements are not allocated
+ ** in a single block, but individually, as needed.
+ */
+ if (element->whichElement.data.type != TUI_REGISTER)
+ tuiFree ((char *)
+ element->whichElement.data.name);
+ tuiFree ((char *) element->whichElement.data.value);
+ tuiFree ((char *) element);
+ break;
+ case CMD_WIN:
+ tuiFree ((char *) element->whichElement.command.line);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ }
+ if (type != DATA_WIN && type != DATA_ITEM_WIN)
+ tuiFree ((char *) content[0]); /* free the element block */
+ }
+
+ return;
+} /* freeContentElements */
diff --git a/gdb/tui/tuiData.h b/gdb/tui/tuiData.h
new file mode 100644
index 00000000000..bb4d19c90e2
--- /dev/null
+++ b/gdb/tui/tuiData.h
@@ -0,0 +1,302 @@
+#ifndef TUI_DATA_H
+#define TUI_DATA_H
+
+/* Constant definitions */
+#define DEFAULT_TAB_LEN 8
+#define NO_SRC_STRING "[ No Source Available ]"
+#define NO_DISASSEM_STRING "[ No Assembly Available ]"
+#define NO_REGS_STRING "[ Register Values Unavailable ]"
+#define NO_DATA_STRING "[ No Data Values Displayed ]"
+#define MAX_CONTENT_COUNT 100
+#define SRC_NAME "SRC"
+#define CMD_NAME "CMD"
+#define DATA_NAME "REGS"
+#define DISASSEM_NAME "ASM"
+#define TUI_NULL_STR ""
+#define DEFAULT_HISTORY_COUNT 25
+#define BOX_WINDOW TRUE
+#define DONT_BOX_WINDOW FALSE
+#define HILITE TRUE
+#define NO_HILITE FALSE
+#define WITH_LOCATOR TRUE
+#define NO_LOCATOR FALSE
+#define EMPTY_SOURCE_PROMPT TRUE
+#define NO_EMPTY_SOURCE_PROMPT FALSE
+#define UNDEFINED_ITEM -1
+#define MIN_WIN_HEIGHT 3
+#define MIN_CMD_WIN_HEIGHT 3
+
+#define FILE_PREFIX "File: "
+#define PROC_PREFIX "Procedure: "
+#define LINE_PREFIX "Line: "
+#define PC_PREFIX "pc: "
+
+#define TUI_FLOAT_REGS_NAME "$FREGS"
+#define TUI_FLOAT_REGS_NAME_LOWER "$fregs"
+#define TUI_GENERAL_REGS_NAME "$GREGS"
+#define TUI_GENERAL_REGS_NAME_LOWER "$gregs"
+#define TUI_SPECIAL_REGS_NAME "$SREGS"
+#define TUI_SPECIAL_REGS_NAME_LOWER "$sregs"
+#define TUI_GENERAL_SPECIAL_REGS_NAME "$REGS"
+#define TUI_GENERAL_SPECIAL_REGS_NAME_LOWER "$regs"
+
+/* Scroll direction enum */
+typedef enum {
+ FORWARD_SCROLL,
+ BACKWARD_SCROLL,
+ LEFT_SCROLL,
+ RIGHT_SCROLL
+} TuiScrollDirection, *TuiScrollDirectionPtr;
+
+
+/* General list struct */
+typedef struct _TuiList {
+ OpaqueList list;
+ int count;
+} TuiList, *TuiListPtr;
+
+
+/* The kinds of layouts available */
+typedef enum {
+ SRC_COMMAND,
+ DISASSEM_COMMAND,
+ SRC_DISASSEM_COMMAND,
+ SRC_DATA_COMMAND,
+ DISASSEM_DATA_COMMAND,
+ UNDEFINED_LAYOUT
+} TuiLayoutType, *TuiLayoutTypePtr;
+
+/* Basic data types that can be displayed in the data window. */
+typedef enum _TuiDataType {
+ TUI_REGISTER,
+ TUI_SCALAR,
+ TUI_COMPLEX,
+ TUI_STRUCT
+} TuiDataType, TuiDataTypePtr;
+
+/* Types of register displays */
+typedef enum _TuiRegisterDisplayType {
+ TUI_UNDEFINED_REGS,
+ TUI_GENERAL_REGS,
+ TUI_SFLOAT_REGS,
+ TUI_DFLOAT_REGS,
+ TUI_SPECIAL_REGS,
+ TUI_GENERAL_AND_SPECIAL_REGS
+} TuiRegisterDisplayType, *TuiRegisterDisplayTypePtr;
+
+/* Structure describing source line or line address */
+typedef union _TuiLineOrAddress {
+ int lineNo;
+ Opaque addr;
+} TuiLineOrAddress, *TuiLineOrAddressPtr;
+
+/* Current Layout definition */
+typedef struct _TuiLayoutDef {
+ TuiWinType displayMode;
+ int split;
+ TuiRegisterDisplayType regsDisplayType;
+ TuiRegisterDisplayType floatRegsDisplayType;
+} TuiLayoutDef, *TuiLayoutDefPtr;
+
+/* Elements in the Source/Disassembly Window */
+typedef struct _TuiSourceElement
+{
+ char *line;
+ TuiLineOrAddress lineOrAddr;
+ int isExecPoint;
+ int hasBreak;
+} TuiSourceElement, *TuiSourceElementPtr;
+
+
+/* Elements in the data display window content */
+typedef struct _TuiDataElement
+{
+ char *name;
+ int itemNo; /* the register number, or data display number */
+ TuiDataType type;
+ Opaque value;
+ int highlight;
+} TuiDataElement, *TuiDataElementPtr;
+
+
+/* Elements in the command window content */
+typedef struct _TuiCommandElement
+{
+ char *line;
+} TuiCommandElement, *TuiCommandElementPtr;
+
+
+#define MAX_LOCATOR_ELEMENT_LEN 100
+
+/* Elements in the locator window content */
+typedef struct _TuiLocatorElement
+{
+ char fileName[MAX_LOCATOR_ELEMENT_LEN];
+ char procName[MAX_LOCATOR_ELEMENT_LEN];
+ int lineNo;
+ Opaque addr;
+} TuiLocatorElement, *TuiLocatorElementPtr;
+
+
+/* An content element in a window */
+typedef union
+{
+ TuiSourceElement source; /* the source elements */
+ TuiGenWinInfo dataWindow; /* data display elements */
+ TuiDataElement data; /* elements of dataWindow */
+ TuiCommandElement command; /* command elements */
+ TuiLocatorElement locator; /* locator elements */
+ char *simpleString; /* simple char based elements */
+} TuiWhichElement, *TuiWhichElementPtr;
+
+typedef struct _TuiWinElement
+{
+ int highlight;
+ TuiWhichElement whichElement;
+} TuiWinElement, *TuiWinElementPtr;
+
+
+/* This describes the content of the window. */
+typedef TuiWinElementPtr *TuiWinContent;
+
+
+/* This struct defines the specific information about a data display window */
+typedef struct _TuiDataInfo {
+ TuiWinContent dataContent; /* start of data display content */
+ int dataContentCount;
+ TuiWinContent regsContent; /* start of regs display content */
+ int regsContentCount;
+ TuiRegisterDisplayType regsDisplayType;
+ int regsColumnCount;
+ int displayRegs; /* Should regs be displayed at all? */
+} TuiDataInfo, *TuiDataInfoPtr;
+
+
+typedef struct _TuiSourceInfo {
+ int hasLocator; /* Does locator belongs to this window? */
+ TuiGenWinInfoPtr executionInfo; /* execution information window */
+ int horizontalOffset; /* used for horizontal scroll */
+ TuiLineOrAddress startLineOrAddr;
+} TuiSourceInfo, *TuiSourceInfoPtr;
+
+
+typedef struct _TuiCommandInfo {
+ int curLine; /* The current line position */
+ int curch; /* The current cursor position */
+} TuiCommandInfo, *TuiCommandInfoPtr;
+
+
+/* This defines information about each logical window */
+typedef struct _TuiWinInfo {
+ TuiGenWinInfo generic; /* general window information */
+ union {
+ TuiSourceInfo sourceInfo;
+ TuiDataInfo dataDisplayInfo;
+ TuiCommandInfo commandInfo;
+ Opaque opaque;
+ } detail;
+ int canHighlight; /* Can this window ever be highlighted? */
+ int isHighlighted; /* Is this window highlighted? */
+} TuiWinInfo, *TuiWinInfoPtr;
+
+/* MACROS (prefixed with m_) */
+
+/* Testing macros */
+#define m_genWinPtrIsNull(winInfo) \
+ ((winInfo) == (TuiGenWinInfoPtr)NULL)
+#define m_genWinPtrNotNull(winInfo) \
+ ((winInfo) != (TuiGenWinInfoPtr)NULL)
+#define m_winPtrIsNull(winInfo) \
+ ((winInfo) == (TuiWinInfoPtr)NULL)
+#define m_winPtrNotNull(winInfo) \
+ ((winInfo) != (TuiWinInfoPtr)NULL)
+
+#define m_winIsSourceType(type) \
+ (type == SRC_WIN || type == DISASSEM_WIN)
+#define m_winIsAuxillary(winType) \
+ (winType > MAX_MAJOR_WINDOWS)
+#define m_hasLocator(winInfo) \
+ ( ((winInfo) != (TuiWinInfoPtr)NULL) ? \
+ (winInfo->detail.sourceInfo.hasLocator) : \
+ FALSE )
+
+#define m_setWinHighlightOn(winInfo) \
+ if ((winInfo) != (TuiWinInfoPtr)NULL) \
+ (winInfo)->isHighlighted = TRUE
+#define m_setWinHighlightOff(winInfo) \
+ if ((winInfo) != (TuiWinInfoPtr)NULL) \
+ (winInfo)->isHighlighted = FALSE
+
+
+/* Global Data */
+extern TuiWinInfoPtr winList[MAX_MAJOR_WINDOWS];
+extern int tui_version;
+
+/* Macros */
+#define srcWin winList[SRC_WIN]
+#define disassemWin winList[DISASSEM_WIN]
+#define dataWin winList[DATA_WIN]
+#define cmdWin winList[CMD_WIN]
+
+/* Data Manipulation Functions */
+extern void initializeStaticData PARAMS ((void));
+extern TuiGenWinInfoPtr allocGenericWinInfo PARAMS ((void));
+extern TuiWinInfoPtr allocWinInfo PARAMS ((TuiWinType));
+extern void initGenericPart PARAMS ((TuiGenWinInfoPtr));
+extern void initWinInfo PARAMS ((TuiWinInfoPtr));
+extern TuiWinContent allocContent PARAMS ((int, TuiWinType));
+extern int addContentElements
+ PARAMS ((TuiGenWinInfoPtr, int));
+extern void initContentElement
+ PARAMS ((TuiWinElementPtr, TuiWinType));
+extern void freeWindow PARAMS ((TuiWinInfoPtr));
+extern void freeAllWindows PARAMS ((void));
+extern void freeWinContent PARAMS ((TuiGenWinInfoPtr));
+extern void freeDataContent PARAMS ((TuiWinContent, int));
+extern void freeAllSourceWinsContent PARAMS ((void));
+extern void tuiDelWindow PARAMS ((TuiWinInfoPtr));
+extern void tuiDelDataWindows PARAMS ((TuiWinContent, int));
+extern TuiWinInfoPtr winByName PARAMS ((char *));
+extern TuiWinInfoPtr partialWinByName PARAMS ((char *));
+extern char *winName PARAMS ((TuiGenWinInfoPtr));
+extern char *displayableWinContentOf
+ PARAMS ((TuiGenWinInfoPtr, TuiWinElementPtr));
+extern char *displayableWinContentAt
+ PARAMS ((TuiGenWinInfoPtr, int));
+extern int winElementHeight
+ PARAMS ((TuiGenWinInfoPtr, TuiWinElementPtr));
+extern TuiLayoutType currentLayout PARAMS ((void));
+extern void setCurrentLayoutTo PARAMS ((TuiLayoutType));
+extern int termHeight PARAMS ((void));
+extern void setTermHeight PARAMS ((int));
+extern int termWidth PARAMS ((void));
+extern void setTermWidth PARAMS ((int));
+extern int historyLimit PARAMS ((void));
+extern void setHistoryLimit PARAMS ((int));
+extern void setGenWinOrigin PARAMS ((TuiGenWinInfoPtr, int, int));
+extern TuiGenWinInfoPtr locatorWinInfoPtr PARAMS ((void));
+extern TuiGenWinInfoPtr sourceExecInfoWinPtr PARAMS ((void));
+extern TuiGenWinInfoPtr disassemExecInfoWinPtr PARAMS ((void));
+extern char *nullStr PARAMS ((void));
+extern char *blankStr PARAMS ((void));
+extern char *locationStr PARAMS ((void));
+extern char *breakStr PARAMS ((void));
+extern char *breakLocationStr PARAMS ((void));
+extern TuiListPtr sourceWindows PARAMS ((void));
+extern void clearSourceWindows PARAMS ((void));
+extern void clearSourceWindowsDetail PARAMS ((void));
+extern void clearWinDetail PARAMS ((TuiWinInfoPtr winInfo));
+extern void tuiAddToSourceWindows PARAMS ((TuiWinInfoPtr));
+extern int tuiDefaultTabLen PARAMS ((void));
+extern void tuiSetDefaultTabLen PARAMS ((int));
+extern TuiWinInfoPtr tuiWinWithFocus PARAMS ((void));
+extern void tuiSetWinWithFocus PARAMS ((TuiWinInfoPtr));
+extern TuiLayoutDefPtr tuiLayoutDef PARAMS ((void));
+extern int tuiWinResized PARAMS ((void));
+extern void tuiSetWinResizedTo PARAMS ((int));
+
+extern TuiWinInfoPtr tuiNextWin PARAMS ((TuiWinInfoPtr));
+extern TuiWinInfoPtr tuiPrevWin PARAMS ((TuiWinInfoPtr));
+
+
+#endif /* TUI_DATA_H */
diff --git a/gdb/tui/tuiDataWin.c b/gdb/tui/tuiDataWin.c
new file mode 100644
index 00000000000..522730ae2fd
--- /dev/null
+++ b/gdb/tui/tuiDataWin.c
@@ -0,0 +1,400 @@
+/*
+** tuiDataWin.c
+** This module contains functions to support the data/register window display.
+*/
+
+
+#include "defs.h"
+#include "tui.h"
+#include "tuiData.h"
+#include "tuiRegs.h"
+
+
+/*****************************************
+** STATIC LOCAL FUNCTIONS FORWARD DECLS **
+******************************************/
+
+
+
+/*****************************************
+** PUBLIC FUNCTIONS **
+******************************************/
+
+
+/*
+** tuiFirstDataItemDisplayed()
+** Answer the index first element displayed.
+** If none are displayed, then return (-1).
+*/
+int
+#ifdef __STDC__
+tuiFirstDataItemDisplayed (void)
+#else
+tuiFirstDataItemDisplayed ()
+#endif
+{
+ int elementNo = (-1);
+ int i;
+
+ for (i = 0; (i < dataWin->generic.contentSize && elementNo < 0); i++)
+ {
+ TuiGenWinInfoPtr dataItemWin;
+
+ dataItemWin = &((TuiWinContent)
+ dataWin->generic.content)[i]->whichElement.dataWindow;
+ if (dataItemWin->handle != (WINDOW *) NULL && dataItemWin->isVisible)
+ elementNo = i;
+ }
+
+ return elementNo;
+} /* tuiFirstDataItemDisplayed */
+
+
+/*
+** tuiFirstDataElementNoInLine()
+** Answer the index of the first element in lineNo. If lineNo is
+** past the data area (-1) is returned.
+*/
+int
+#ifdef __STDC__
+tuiFirstDataElementNoInLine (
+ int lineNo)
+#else
+tuiFirstDataElementNoInLine (lineNo)
+ int lineNo;
+#endif
+{
+ int firstElementNo = (-1);
+
+ /*
+ ** First see if there is a register on lineNo, and if so, set the
+ ** first element number
+ */
+ if ((firstElementNo = tuiFirstRegElementNoInLine (lineNo)) == -1)
+ { /*
+ ** Looking at the general data, the 1st element on lineNo
+ */
+ }
+
+ return firstElementNo;
+} /* tuiFirstDataElementNoInLine */
+
+
+/*
+** tuiDeleteDataContentWindows()
+** Function to delete all the item windows in the data window.
+** This is usually done when the data window is scrolled.
+*/
+void
+#ifdef __STDC__
+tuiDeleteDataContentWindows (void)
+#else
+tuiDeleteDataContentWindows ()
+#endif
+{
+ int i;
+ TuiGenWinInfoPtr dataItemWinPtr;
+
+ for (i = 0; (i < dataWin->generic.contentSize); i++)
+ {
+ dataItemWinPtr = &((TuiWinContent)
+ dataWin->generic.content)[i]->whichElement.dataWindow;
+ tuiDelwin (dataItemWinPtr->handle);
+ dataItemWinPtr->handle = (WINDOW *) NULL;
+ dataItemWinPtr->isVisible = FALSE;
+ }
+
+ return;
+} /* tuiDeleteDataContentWindows */
+
+
+void
+#ifdef __STDC__
+tuiEraseDataContent (
+ char *prompt)
+#else
+tuiEraseDataContent (prompt)
+ char *prompt;
+#endif
+{
+ werase (dataWin->generic.handle);
+ checkAndDisplayHighlightIfNeeded (dataWin);
+ if (prompt != (char *) NULL)
+ {
+ int halfWidth = (dataWin->generic.width - 2) / 2;
+ int xPos;
+
+ if (strlen (prompt) >= halfWidth)
+ xPos = 1;
+ else
+ xPos = halfWidth - strlen (prompt);
+ mvwaddstr (dataWin->generic.handle,
+ (dataWin->generic.height / 2),
+ xPos,
+ prompt);
+ }
+ wrefresh (dataWin->generic.handle);
+
+ return;
+} /* tuiEraseDataContent */
+
+
+/*
+** tuiDisplayAllData().
+** This function displays the data that is in the data window's
+** content. It does not set the content.
+*/
+void
+#ifdef __STDC__
+tuiDisplayAllData (void)
+#else
+tuiDisplayAllData ()
+#endif
+{
+ if (dataWin->generic.contentSize <= 0)
+ tuiEraseDataContent (NO_DATA_STRING);
+ else
+ {
+ tuiEraseDataContent ((char *) NULL);
+ tuiDeleteDataContentWindows ();
+ checkAndDisplayHighlightIfNeeded (dataWin);
+ tuiDisplayRegistersFrom (0);
+ /*
+ ** Then display the other data
+ */
+ if (dataWin->detail.dataDisplayInfo.dataContent !=
+ (TuiWinContent) NULL &&
+ dataWin->detail.dataDisplayInfo.dataContentCount > 0)
+ {
+ }
+ }
+ return;
+} /* tuiDisplayAllData */
+
+
+/*
+** tuiDisplayDataFromLine()
+** Function to display the data starting at line, lineNo, in the
+** data window.
+*/
+void
+#ifdef __STDC__
+tuiDisplayDataFromLine (
+ int lineNo)
+#else
+tuiDisplayDataFromLine (lineNo)
+ int lineNo;
+#endif
+{
+ int _lineNo = lineNo;
+
+ if (lineNo < 0)
+ _lineNo = 0;
+
+ checkAndDisplayHighlightIfNeeded (dataWin);
+
+ /* there is no general data, force regs to display (if there are any) */
+ if (dataWin->detail.dataDisplayInfo.dataContentCount <= 0)
+ tuiDisplayRegistersFromLine (_lineNo, TRUE);
+ else
+ {
+ int elementNo, startLineNo;
+ int regsLastLine = tuiLastRegsLineNo ();
+
+
+ /* display regs if we can */
+ if (tuiDisplayRegistersFromLine (_lineNo, FALSE) < 0)
+ { /*
+ ** _lineNo is past the regs display, so calc where the
+ ** start data element is
+ */
+ if (regsLastLine < _lineNo)
+ { /* figure out how many lines each element is to obtain
+ the start elementNo */
+ }
+ }
+ else
+ { /*
+ ** calculate the starting element of the data display, given
+ ** regsLastLine and how many lines each element is, up to
+ ** _lineNo
+ */
+ }
+ /* Now display the data , starting at elementNo */
+ }
+
+ return;
+} /* tuiDisplayDataFromLine */
+
+
+/*
+** tuiDisplayDataFrom()
+** Display data starting at element elementNo
+*/
+void
+#ifdef __STDC__
+tuiDisplayDataFrom (
+ int elementNo,
+ int reuseWindows)
+#else
+tuiDisplayDataFrom (elementNo, reuseWindows)
+ int elementNo;
+ int reuseWindows;
+#endif
+{
+ int firstLine = (-1);
+
+ if (elementNo < dataWin->detail.dataDisplayInfo.regsContentCount)
+ firstLine = tuiLineFromRegElementNo (elementNo);
+ else
+ { /* calculate the firstLine from the element number */
+ }
+
+ if (firstLine >= 0)
+ {
+ tuiEraseDataContent ((char *) NULL);
+ if (!reuseWindows)
+ tuiDeleteDataContentWindows ();
+ tuiDisplayDataFromLine (firstLine);
+ }
+
+ return;
+} /* tuiDisplayDataFrom */
+
+
+/*
+** tuiRefreshDataWin()
+** Function to redisplay the contents of the data window.
+*/
+void
+#ifdef __STDC__
+tuiRefreshDataWin (void)
+#else
+tuiRefreshDataWin ()
+#endif
+{
+ tuiEraseDataContent ((char *) NULL);
+ if (dataWin->generic.contentSize > 0)
+ {
+ int firstElement = tuiFirstDataItemDisplayed ();
+
+ if (firstElement >= 0) /* re-use existing windows */
+ tuiDisplayDataFrom (firstElement, TRUE);
+ }
+
+ return;
+} /* tuiRefreshDataWin */
+
+
+/*
+** tuiCheckDataValues().
+** Function to check the data values and hilite any that have changed
+*/
+void
+#ifdef __STDC__
+tuiCheckDataValues (
+ struct frame_info *frame)
+#else
+tuiCheckDataValues (frame)
+ struct frame_info *frame;
+#endif
+{
+ tuiCheckRegisterValues (frame);
+
+ /* Now check any other data values that there are */
+ if (m_winPtrNotNull (dataWin) && dataWin->generic.isVisible)
+ {
+ int i;
+
+ for (i = 0; dataWin->detail.dataDisplayInfo.dataContentCount; i++)
+ {
+#ifdef LATER
+ TuiDataElementPtr dataElementPtr;
+ TuiGenWinInfoPtr dataItemWinPtr;
+ Opaque newValue;
+
+ dataItemPtr = &dataWin->detail.dataDisplayInfo.
+ dataContent[i]->whichElement.dataWindow;
+ dataElementPtr = &((TuiWinContent)
+ dataItemWinPtr->content)[0]->whichElement.data;
+ if value
+ has changed (dataElementPtr, frame, &newValue)
+ {
+ dataElementPtr->value = newValue;
+ update the display with the new value, hiliting it.
+ }
+#endif
+ }
+ }
+} /* tuiCheckDataValues */
+
+
+/*
+** tui_vCheckDataValues().
+** Function to check the data values and hilite any that have
+** changed with args in a va_list
+*/
+void
+#ifdef __STDC__
+tui_vCheckDataValues (
+ va_list args)
+#else
+tui_vCheckDataValues (args)
+ va_list args;
+#endif
+{
+ struct frame_info *frame = va_arg (args, struct frame_info *);
+
+ tuiCheckDataValues (frame);
+
+ return;
+} /* tui_vCheckDataValues */
+
+
+/*
+** tuiVerticalDataScroll()
+** Scroll the data window vertically forward or backward.
+*/
+void
+#ifdef __STDC__
+tuiVerticalDataScroll (
+ TuiScrollDirection scrollDirection,
+ int numToScroll)
+#else
+tuiVerticalDataScroll (scrollDirection, numToScroll)
+ TuiScrollDirection scrollDirection;
+ int numToScroll;
+#endif
+{
+ int firstElementNo;
+ int firstLine = (-1);
+
+ firstElementNo = tuiFirstDataItemDisplayed ();
+ if (firstElementNo < dataWin->detail.dataDisplayInfo.regsContentCount)
+ firstLine = tuiLineFromRegElementNo (firstElementNo);
+ else
+ { /* calculate the first line from the element number which is in
+ ** the general data content
+ */
+ }
+
+ if (firstLine >= 0)
+ {
+ int lastElementNo, lastLine;
+
+ if (scrollDirection == FORWARD_SCROLL)
+ firstLine += numToScroll;
+ else
+ firstLine -= numToScroll;
+ tuiEraseDataContent ((char *) NULL);
+ tuiDeleteDataContentWindows ();
+ tuiDisplayDataFromLine (firstLine);
+ }
+
+ return;
+} /* tuiVerticalDataScroll */
+
+
+/*****************************************
+** STATIC LOCAL FUNCTIONS **
+******************************************/
diff --git a/gdb/tui/tuiDataWin.h b/gdb/tui/tuiDataWin.h
new file mode 100644
index 00000000000..8f9e46d80e7
--- /dev/null
+++ b/gdb/tui/tuiDataWin.h
@@ -0,0 +1,29 @@
+#ifndef _TUI_DATAWIN_H
+#define _TUI_DATAWIN_H
+/*
+** This header file supports the display of registers/data in the data window.
+*/
+
+
+/*****************************************
+** TYPE DEFINITIONS **
+******************************************/
+
+
+
+/*****************************************
+** PUBLIC FUNCTION EXTERNAL DECLS **
+******************************************/
+extern void tuiEraseDataContent PARAMS ((char *));
+extern void tuiDisplayAllData PARAMS ((void));
+extern void tuiCheckDataValues PARAMS ((struct frame_info *));
+extern void tui_vCheckDataValues PARAMS ((va_list));
+extern void tuiDisplayDataFromLine PARAMS ((int));
+extern int tuiFirstDataItemDisplayed PARAMS ((void));
+extern int tuiFirstDataElementNoInLine PARAMS ((int));
+extern void tuiDeleteDataContentWindows PARAMS ((void));
+extern void tuiRefreshDataWin PARAMS ((void));
+extern void tuiDisplayDataFrom PARAMS ((int, int));
+extern void tuiVerticalDataScroll PARAMS ((TuiScrollDirection, int));
+
+#endif /*_TUI_DATAWIN_H*/
diff --git a/gdb/tui/tuiDisassem.c b/gdb/tui/tuiDisassem.c
new file mode 100644
index 00000000000..ad0b70f655d
--- /dev/null
+++ b/gdb/tui/tuiDisassem.c
@@ -0,0 +1,343 @@
+/*
+** tuiDisassem.c
+** This module contains functions for handling disassembly display.
+*/
+
+
+#include "defs.h"
+#include "symtab.h"
+#include "breakpoint.h"
+#include "frame.h"
+
+#include "tui.h"
+#include "tuiData.h"
+#include "tuiLayout.h"
+#include "tuiSourceWin.h"
+#include "tuiStack.h"
+
+
+/*****************************************
+** STATIC LOCAL FUNCTIONS FORWARD DECLS **
+******************************************/
+
+static struct breakpoint *_hasBreak PARAMS ((CORE_ADDR));
+
+
+/*****************************************
+** PUBLIC FUNCTIONS **
+******************************************/
+
+/*
+** tuiSetDisassemContent().
+** Function to set the disassembly window's content.
+*/
+TuiStatus
+#ifdef __STDC__
+tuiSetDisassemContent (
+ struct symtab *s,
+ Opaque startAddr)
+#else
+ tuiSetDisassemContent (s, startAddr)
+ struct symtab *s;
+ Opaque startAddr;
+#endif
+{
+ TuiStatus ret = TUI_FAILURE;
+ GDB_FILE *gdb_dis_out;
+
+ if (startAddr != (Opaque) NULL)
+ {
+ register int i, desc;
+
+ if ((ret = tuiAllocSourceBuffer (disassemWin)) == TUI_SUCCESS)
+ {
+ register int offset = disassemWin->detail.sourceInfo.horizontalOffset;
+ register int threshold, curLine = 0, lineWidth, maxLines;
+ CORE_ADDR newpc, pc;
+ disassemble_info asmInfo;
+ TuiGenWinInfoPtr locator = locatorWinInfoPtr ();
+ extern void strcat_address PARAMS ((CORE_ADDR, char *, int));
+ extern void strcat_address_numeric PARAMS ((CORE_ADDR, int, char *, int));
+ int curLen = 0;
+ int tab_len = tuiDefaultTabLen ();
+
+ maxLines = disassemWin->generic.height - 2; /* account for hilite */
+ lineWidth = disassemWin->generic.width - 1;
+ threshold = (lineWidth - 1) + offset;
+
+ /* now init the gdb_file structure */
+ gdb_dis_out = gdb_file_init_astring (threshold);
+
+ INIT_DISASSEMBLE_INFO_NO_ARCH (asmInfo, gdb_dis_out, (fprintf_ftype) fprintf_filtered);
+ asmInfo.read_memory_func = dis_asm_read_memory;
+ asmInfo.memory_error_func = dis_asm_memory_error;
+
+ disassemWin->detail.sourceInfo.startLineOrAddr.addr = startAddr;
+
+ /* Now construct each line */
+ for (curLine = 0, pc = (CORE_ADDR) startAddr; (curLine < maxLines);)
+ {
+ TuiWinElementPtr element = (TuiWinElementPtr)disassemWin->generic.content[curLine];
+ struct breakpoint *bp;
+
+ print_address (pc, gdb_dis_out);
+
+ curLen = strlen (gdb_file_get_strbuf (gdb_dis_out));
+ i = curLen - ((curLen / tab_len) * tab_len);
+
+ /* adjust buffer length if necessary */
+ gdb_file_adjust_strbuf ((tab_len - i > 0) ? (tab_len - i ) : 0, gdb_dis_out);
+
+ /* Add spaces to make the instructions start onthe same column */
+ while (i < tab_len)
+ {
+ gdb_file_get_strbuf (gdb_dis_out)[curLen] = ' ';
+ i++;
+ curLen++;
+ }
+ gdb_file_get_strbuf (gdb_dis_out)[curLen] = '\0';
+
+ newpc = pc + ((*tm_print_insn) (pc, &asmInfo));
+
+ /* Now copy the line taking the offset into account */
+ if (strlen (gdb_file_get_strbuf (gdb_dis_out)) > offset)
+ strcpy (element->whichElement.source.line,
+ &(gdb_file_get_strbuf (gdb_dis_out)[offset]));
+ else
+ element->whichElement.source.line[0] = '\0';
+ element->whichElement.source.lineOrAddr.addr = (Opaque) pc;
+ element->whichElement.source.isExecPoint =
+ (pc == (CORE_ADDR) ((TuiWinElementPtr)locator->content[0])->whichElement.locator.addr);
+ bp = _hasBreak (pc);
+ element->whichElement.source.hasBreak =
+ (bp != (struct breakpoint *) NULL &&
+ (!element->whichElement.source.isExecPoint ||
+ (bp->disposition != del || bp->hit_count <= 0)));
+ curLine++;
+ pc = newpc;
+ /* reset the buffer to empty */
+ gdb_file_get_strbuf (gdb_dis_out)[0] = '\0';
+ }
+ gdb_file_deallocate (&gdb_dis_out);
+ disassemWin->generic.contentSize = curLine;
+ ret = TUI_SUCCESS;
+ }
+ }
+
+ return ret;
+} /* tuiSetDisassemContent */
+
+
+/*
+** tuiShowDisassem().
+** Function to display the disassembly window with disassembled code.
+*/
+void
+#ifdef __STDC__
+tuiShowDisassem (
+ Opaque startAddr)
+#else
+tuiShowDisassem (startAddr)
+ Opaque startAddr;
+#endif
+{
+ struct symtab *s = find_pc_symtab ((CORE_ADDR) startAddr);
+ TuiWinInfoPtr winWithFocus = tuiWinWithFocus ();
+
+ tuiAddWinToLayout (DISASSEM_WIN);
+ tuiUpdateSourceWindow (disassemWin, s, startAddr, FALSE);
+ /*
+ ** if the focus was in the src win, put it in the asm win, if the
+ ** source view isn't split
+ */
+ if (currentLayout () != SRC_DISASSEM_COMMAND && winWithFocus == srcWin)
+ tuiSetWinFocusTo (disassemWin);
+
+ return;
+} /* tuiShowDisassem */
+
+
+/*
+** tuiShowDisassemAndUpdateSource().
+** Function to display the disassembly window.
+*/
+void
+#ifdef __STDC__
+tuiShowDisassemAndUpdateSource (
+ Opaque startAddr)
+#else
+tuiShowDisassemAndUpdateSource (startAddr)
+ Opaque startAddr;
+#endif
+{
+ struct symtab_and_line sal;
+
+ tuiShowDisassem (startAddr);
+ if (currentLayout () == SRC_DISASSEM_COMMAND)
+ {
+ TuiGenWinInfoPtr locator = locatorWinInfoPtr ();
+ /*
+ ** Update what is in the source window if it is displayed too,
+ ** note that it follows what is in the disassembly window and visa-versa
+ */
+ sal = find_pc_line ((CORE_ADDR) startAddr, 0);
+ current_source_symtab = sal.symtab;
+ tuiUpdateSourceWindow (srcWin, sal.symtab, (Opaque) sal.line, TRUE);
+ tuiUpdateLocatorFilename (sal.symtab->filename);
+ }
+
+ return;
+} /* tuiShowDisassemAndUpdateSource */
+
+
+/*
+** tuiShowDisassemAsIs().
+** Function to display the disassembly window. This function shows
+** the disassembly as specified by the horizontal offset.
+*/
+void
+#ifdef __STDC__
+tuiShowDisassemAsIs (
+ Opaque addr)
+#else
+tuiShowDisassemAsIs (addr)
+ Opaque addr;
+#endif
+{
+ tuiAddWinToLayout (DISASSEM_WIN);
+ tuiUpdateSourceWindowAsIs (disassemWin, (struct symtab *) NULL, addr, FALSE);
+ /*
+ ** Update what is in the source window if it is displayed too, not that it
+ ** follows what is in the disassembly window and visa-versa
+ */
+ if (currentLayout () == SRC_DISASSEM_COMMAND)
+ tuiShowSourceContent (srcWin); /*???? Need to do more? */
+
+ return;
+} /* tuiShowDisassem */
+
+
+/*
+** tuiGetBeginAsmAddress().
+*/
+Opaque
+#ifdef __STDC__
+tuiGetBeginAsmAddress (void)
+#else
+tuiGetBeginAsmAddress ()
+#endif
+{
+ TuiGenWinInfoPtr locator;
+ TuiLocatorElementPtr element;
+ Opaque addr;
+
+ locator = locatorWinInfoPtr ();
+ element = &((TuiWinElementPtr) locator->content[0])->whichElement.locator;
+
+ if (element->addr == (Opaque) 0)
+ {
+ /*the target is not executing, because the pc is 0*/
+
+ addr = (Opaque) parse_and_eval_address ("main");
+
+ if (addr == (Opaque) 0)
+ addr = (Opaque) parse_and_eval_address ("MAIN");
+
+ }
+ else /* the target is executing */
+ addr = element->addr;
+
+ return addr;
+} /* tuiGetBeginAsmAddress */
+
+
+/*
+** tuiVerticalDisassemScroll().
+** Scroll the disassembly forward or backward vertically
+*/
+void
+#ifdef __STDC__
+tuiVerticalDisassemScroll (
+ TuiScrollDirection scrollDirection,
+ int numToScroll)
+#else
+tuiVerticalDisassemScroll (scrollDirection, numToScroll)
+ TuiScrollDirection scrollDirection;
+ int numToScroll;
+#endif
+{
+ if (disassemWin->generic.content != (OpaquePtr) NULL)
+ {
+ Opaque pc, lowAddr;
+ TuiWinContent content;
+ struct symtab *s;
+
+ content = (TuiWinContent) disassemWin->generic.content;
+ if (current_source_symtab == (struct symtab *) NULL)
+ s = find_pc_symtab (selected_frame->pc);
+ else
+ s = current_source_symtab;
+
+ pc = content[0]->whichElement.source.lineOrAddr.addr;
+ if (find_pc_partial_function ((CORE_ADDR) pc,
+ (char **) NULL,
+ (CORE_ADDR *) & lowAddr,
+ (CORE_ADDR) NULL) == 0)
+ error ("No function contains prgram counter for selected frame.\n");
+ else
+ {
+ register int line = 0;
+ register Opaque newLow;
+ bfd_byte buffer[4];
+
+ newLow = pc;
+ if (scrollDirection == FORWARD_SCROLL)
+ {
+ for (; line < numToScroll; line++)
+ newLow += sizeof (bfd_getb32 (buffer));
+ }
+ else
+ {
+ for (; newLow >= (Opaque) 0 && line < numToScroll; line++)
+ newLow -= sizeof (bfd_getb32 (buffer));
+ }
+ tuiUpdateSourceWindowAsIs (disassemWin, s, newLow, FALSE);
+ }
+ }
+
+ return;
+} /* tuiVerticalDisassemScroll */
+
+
+
+/*****************************************
+** STATIC LOCAL FUNCTIONS **
+******************************************/
+/*
+** _hasBreak().
+** Answer whether there is a break point at the input line in the
+** source file indicated
+*/
+static struct breakpoint *
+#ifdef __STDC__
+_hasBreak (
+ CORE_ADDR addr)
+#else
+_hasBreak (addr)
+ CORE_ADDR addr;
+#endif
+{
+ struct breakpoint *bpWithBreak = (struct breakpoint *) NULL;
+ struct breakpoint *bp;
+ extern struct breakpoint *breakpoint_chain;
+
+
+ for (bp = breakpoint_chain;
+ (bp != (struct breakpoint *) NULL &&
+ bpWithBreak == (struct breakpoint *) NULL);
+ bp = bp->next)
+ if (addr == bp->address)
+ bpWithBreak = bp;
+
+ return bpWithBreak;
+} /* _hasBreak */
diff --git a/gdb/tui/tuiDisassem.h b/gdb/tui/tuiDisassem.h
new file mode 100644
index 00000000000..711ac48587d
--- /dev/null
+++ b/gdb/tui/tuiDisassem.h
@@ -0,0 +1,22 @@
+#ifndef _TUI_DISASSEM_H
+#define _TUI_DISASSEM_H
+/*
+** This header file supports
+*/
+
+/*****************************************
+** TYPE DEFINITIONS **
+******************************************/
+
+
+
+/*****************************************
+** PUBLIC FUNCTION EXTERNAL DECLS **
+******************************************/
+extern TuiStatus tuiSetDisassemContent PARAMS ((struct symtab *, Opaque));
+extern void tuiShowDisassem PARAMS ((Opaque));
+extern void tuiShowDisassemAndUpdateSource PARAMS ((Opaque));
+extern void tuiVerticalDisassemScroll PARAMS ((TuiScrollDirection, int));
+extern Opaque tuiGetBeginAsmAddress PARAMS ((void));
+
+#endif /*_TUI_DISASSEM_H*/
diff --git a/gdb/tui/tuiGeneralWin.c b/gdb/tui/tuiGeneralWin.c
new file mode 100644
index 00000000000..5af0cd7a92e
--- /dev/null
+++ b/gdb/tui/tuiGeneralWin.c
@@ -0,0 +1,469 @@
+/*
+** TuiGeneralWin.c
+** This module supports general window behavior
+*/
+
+#include <curses.h>
+#include "defs.h"
+#include "tui.h"
+#include "tuiData.h"
+#include "tuiGeneralWin.h"
+
+
+/*
+** local support functions
+*/
+static void _winResize PARAMS ((void));
+
+
+/***********************
+** PUBLIC FUNCTIONS
+***********************/
+/*
+** tuiRefreshWin()
+** Refresh the window
+*/
+void
+#ifdef __STDC__
+tuiRefreshWin (
+ TuiGenWinInfoPtr winInfo)
+#else
+tuiRefreshWin (winInfo)
+ TuiGenWinInfoPtr winInfo;
+#endif
+{
+ if (winInfo->type == DATA_WIN && winInfo->contentSize > 0)
+ {
+ int i;
+
+ for (i = 0; (i < winInfo->contentSize); i++)
+ {
+ TuiGenWinInfoPtr dataItemWinPtr;
+
+ dataItemWinPtr = &((TuiWinContent)
+ winInfo->content)[i]->whichElement.dataWindow;
+ if (m_genWinPtrNotNull (dataItemWinPtr) &&
+ dataItemWinPtr->handle != (WINDOW *) NULL)
+ wrefresh (dataItemWinPtr->handle);
+ }
+ }
+ else if (winInfo->type == CMD_WIN)
+ {
+ /* Do nothing */
+ }
+ else
+ {
+ if (winInfo->handle != (WINDOW *) NULL)
+ wrefresh (winInfo->handle);
+ }
+
+ return;
+} /* tuiRefreshWin */
+
+
+/*
+** tuiDelwin()
+** Function to delete the curses window, checking for null
+*/
+void
+#ifdef __STDC__
+tuiDelwin (
+ WINDOW * window)
+#else
+tuiDelwin (window)
+ WINDOW *window;
+#endif
+{
+ if (window != (WINDOW *) NULL)
+ delwin (window);
+
+ return;
+} /* tuiDelwin */
+
+
+/*
+** boxWin().
+*/
+void
+#ifdef __STDC__
+boxWin (
+ TuiGenWinInfoPtr winInfo,
+ int highlightFlag)
+#else
+boxWin (winInfo, highlightFlag)
+ TuiGenWinInfoPtr winInfo;
+ int highlightFlag;
+#endif
+{
+ if (m_genWinPtrNotNull (winInfo) && winInfo->handle != (WINDOW *) NULL)
+ {
+ if (highlightFlag == HILITE)
+ box (winInfo->handle, '|', '-');
+ else
+ {
+/* wattron(winInfo->handle, A_DIM);*/
+ box (winInfo->handle, ':', '.');
+/* wattroff(winInfo->handle, A_DIM);*/
+ }
+ }
+
+ return;
+} /* boxWin */
+
+
+/*
+** unhighlightWin().
+*/
+void
+#ifdef __STDC__
+unhighlightWin (
+ TuiWinInfoPtr winInfo)
+#else
+unhighlightWin (winInfo)
+ TuiWinInfoPtr winInfo;
+#endif
+{
+ if (m_winPtrNotNull (winInfo) && winInfo->generic.handle != (WINDOW *) NULL)
+ {
+ boxWin ((TuiGenWinInfoPtr) winInfo, NO_HILITE);
+ wrefresh (winInfo->generic.handle);
+ m_setWinHighlightOff (winInfo);
+ }
+} /* unhighlightWin */
+
+
+/*
+** highlightWin().
+*/
+void
+#ifdef __STDC__
+highlightWin (
+ TuiWinInfoPtr winInfo)
+#else
+highlightWin (winInfo)
+ TuiWinInfoPtr winInfo;
+#endif
+{
+ if (m_winPtrNotNull (winInfo) &&
+ winInfo->canHighlight && winInfo->generic.handle != (WINDOW *) NULL)
+ {
+ boxWin ((TuiGenWinInfoPtr) winInfo, HILITE);
+ wrefresh (winInfo->generic.handle);
+ m_setWinHighlightOn (winInfo);
+ }
+} /* highlightWin */
+
+
+/*
+** checkAndDisplayHighlightIfNecessay
+*/
+void
+#ifdef __STDC__
+checkAndDisplayHighlightIfNeeded (
+ TuiWinInfoPtr winInfo)
+#else
+checkAndDisplayHighlightIfNeeded (winInfo)
+ TuiWinInfoPtr winInfo;
+#endif
+{
+ if (m_winPtrNotNull (winInfo) && winInfo->generic.type != CMD_WIN)
+ {
+ if (winInfo->isHighlighted)
+ highlightWin (winInfo);
+ else
+ unhighlightWin (winInfo);
+
+ }
+ return;
+} /* checkAndDisplayHighlightIfNeeded */
+
+
+/*
+** makeWindow().
+*/
+void
+#ifdef __STDC__
+makeWindow (
+ TuiGenWinInfoPtr winInfo,
+ int boxIt)
+#else
+makeWindow (winInfo, boxIt)
+ TuiGenWinInfoPtr winInfo;
+ int boxIt;
+#endif
+{
+ WINDOW *handle;
+
+ handle = newwin (winInfo->height,
+ winInfo->width,
+ winInfo->origin.y,
+ winInfo->origin.x);
+ winInfo->handle = handle;
+ if (handle != (WINDOW *) NULL)
+ {
+ if (boxIt == BOX_WINDOW)
+ boxWin (winInfo, NO_HILITE);
+ winInfo->isVisible = TRUE;
+ scrollok (handle, TRUE);
+ tuiRefreshWin (winInfo);
+
+#ifndef FOR_TEST
+ if ( /*!m_WinIsAuxillary(winInfo->type) && */
+ (winInfo->type != CMD_WIN) &&
+ (winInfo->content == (OpaquePtr) NULL))
+ {
+ mvwaddstr (handle, 1, 1, winName (winInfo));
+ tuiRefreshWin (winInfo);
+ }
+#endif /*FOR_TEST*/
+ }
+
+ return;
+} /* makeWindow */
+
+
+/*
+** tuiClearWin().
+** Clear the window of all contents without calling wclear.
+*/
+void
+#ifdef __STDC__
+tuiClearWin (
+ TuiGenWinInfoPtr winInfo)
+#else
+tuiClearWin (winInfo)
+ TuiGenWinInfoPtr winInfo;
+#endif
+{
+ if (m_genWinPtrNotNull (winInfo) && winInfo->handle != (WINDOW *) NULL)
+ {
+ int curRow, curCol;
+
+ for (curRow = 0; (curRow < winInfo->height); curRow++)
+ for (curCol = 0; (curCol < winInfo->width); curCol++)
+ mvwaddch (winInfo->handle, curRow, curCol, ' ');
+
+ tuiRefreshWin (winInfo);
+ }
+
+ return;
+} /* tuiClearWin */
+
+
+/*
+** makeVisible().
+** We can't really make windows visible, or invisible. So we
+** have to delete the entire window when making it visible,
+** and create it again when making it visible.
+*/
+void
+#ifdef __STDC__
+makeVisible (
+ TuiGenWinInfoPtr winInfo,
+ int visible)
+#else
+makeVisible (winInfo, visible)
+ TuiGenWinInfoPtr winInfo;
+ int visible;
+#endif
+{
+ /* Don't tear down/recreate command window */
+ if (winInfo->type == CMD_WIN)
+ return;
+
+ if (visible)
+ {
+ if (!winInfo->isVisible)
+ {
+ makeWindow (
+ winInfo,
+ (winInfo->type != CMD_WIN && !m_winIsAuxillary (winInfo->type)));
+ winInfo->isVisible = TRUE;
+ }
+ tuiRefreshWin (winInfo);
+ }
+ else if (!visible &&
+ winInfo->isVisible && winInfo->handle != (WINDOW *) NULL)
+ {
+ winInfo->isVisible = FALSE;
+ tuiClearWin (winInfo);
+ tuiDelwin (winInfo->handle);
+ winInfo->handle = (WINDOW *) NULL;
+ }
+
+ return;
+} /* makeVisible */
+
+
+/*
+** makeAllVisible().
+** Makes all windows invisible (except the command and locator windows)
+*/
+void
+#ifdef __STDC__
+makeAllVisible (
+ int visible)
+#else
+makeAllVisible (visible)
+ int visible;
+#endif
+{
+ int i;
+
+ for (i = 0; i < MAX_MAJOR_WINDOWS; i++)
+ {
+ if (m_winPtrNotNull (winList[i]) &&
+ ((winList[i])->generic.type) != CMD_WIN)
+ {
+ if (m_winIsSourceType ((winList[i])->generic.type))
+ makeVisible ((winList[i])->detail.sourceInfo.executionInfo,
+ visible);
+ makeVisible ((TuiGenWinInfoPtr) winList[i], visible);
+ }
+ }
+
+ return;
+} /* makeAllVisible */
+
+
+/*
+** scrollWinForward
+*/
+void
+#ifdef __STDC__
+scrollWinForward (
+ TuiGenWinInfoPtr winInfo,
+ int numLines)
+#else
+scrollWinForward (winInfo, numLines)
+ TuiGenWinInfoPtr winInfo;
+ int numLines;
+#endif
+{
+ if (winInfo->content != (OpaquePtr) NULL &&
+ winInfo->lastVisibleLine < winInfo->contentSize - 1)
+ {
+ int i, firstLine, newLastLine;
+
+ firstLine = winInfo->lastVisibleLine - winInfo->viewportHeight + 1;
+ if (winInfo->lastVisibleLine + numLines > winInfo->contentSize)
+ newLastLine = winInfo->contentSize - 1;
+ else
+ newLastLine = winInfo->lastVisibleLine + numLines - 1;
+
+ for (i = (newLastLine - winInfo->viewportHeight);
+ (i <= newLastLine); i++)
+ {
+ TuiWinElementPtr line;
+ int lineHeight;
+
+ line = (TuiWinElementPtr) winInfo->content[i];
+ if (line->highlight)
+ wstandout (winInfo->handle);
+ mvwaddstr (winInfo->handle,
+ i - (newLastLine - winInfo->viewportHeight),
+ 1,
+ displayableWinContentOf (winInfo, line));
+ if (line->highlight)
+ wstandend (winInfo->handle);
+ lineHeight = winElementHeight (winInfo, line);
+ newLastLine += (lineHeight - 1);
+ }
+ winInfo->lastVisibleLine = newLastLine;
+ }
+
+ return;
+} /* scrollWinForward */
+
+
+/*
+** scrollWinBackward
+*/
+void
+#ifdef __STDC__
+scrollWinBackward (
+ TuiGenWinInfoPtr winInfo,
+ int numLines)
+#else
+scrollWinBackward (winInfo, numLines)
+ TuiGenWinInfoPtr winInfo;
+ int numLines;
+#endif
+{
+ if (winInfo->content != (OpaquePtr) NULL &&
+ (winInfo->lastVisibleLine - winInfo->viewportHeight) > 0)
+ {
+ int i, newLastLine, firstLine;
+
+ firstLine = winInfo->lastVisibleLine - winInfo->viewportHeight + 1;
+ if ((firstLine - numLines) < 0)
+ newLastLine = winInfo->viewportHeight - 1;
+ else
+ newLastLine = winInfo->lastVisibleLine - numLines + 1;
+
+ for (i = newLastLine - winInfo->viewportHeight; (i <= newLastLine); i++)
+ {
+ TuiWinElementPtr line;
+ int lineHeight;
+
+ line = (TuiWinElementPtr) winInfo->content[i];
+ if (line->highlight)
+ wstandout (winInfo->handle);
+ mvwaddstr (winInfo->handle,
+ i - (newLastLine - winInfo->viewportHeight),
+ 1,
+ displayableWinContentOf (winInfo, line));
+ if (line->highlight)
+ wstandend (winInfo->handle);
+ lineHeight = winElementHeight (winInfo, line);
+ newLastLine += (lineHeight - 1);
+ }
+ winInfo->lastVisibleLine = newLastLine;
+ }
+
+ return;
+} /* scrollWinBackward */
+
+
+/*
+** refreshAll().
+** Function to refresh all the windows currently displayed
+*/
+void
+#ifdef __STDC__
+refreshAll (
+ TuiWinInfoPtr * list)
+#else
+refreshAll (list)
+ TuiWinInfoPtr *list;
+#endif
+{
+ TuiWinType type;
+ TuiGenWinInfoPtr locator = locatorWinInfoPtr ();
+
+ for (type = SRC_WIN; (type < MAX_MAJOR_WINDOWS); type++)
+ {
+ if (list[type]->generic.isVisible)
+ {
+ if (type == SRC_WIN || type == DISASSEM_WIN)
+ {
+ touchwin (list[type]->detail.sourceInfo.executionInfo->handle);
+ tuiRefreshWin (list[type]->detail.sourceInfo.executionInfo);
+ }
+ touchwin (list[type]->generic.handle);
+ tuiRefreshWin (&list[type]->generic);
+ }
+ }
+ if (locator->isVisible)
+ {
+ touchwin (locator->handle);
+ tuiRefreshWin (locator);
+ }
+
+ return;
+} /* refreshAll */
+
+
+/*********************************
+** Local Static Functions
+*********************************/
diff --git a/gdb/tui/tuiGeneralWin.h b/gdb/tui/tuiGeneralWin.h
new file mode 100644
index 00000000000..559f8ab3339
--- /dev/null
+++ b/gdb/tui/tuiGeneralWin.h
@@ -0,0 +1,31 @@
+#ifndef TUI_GENERAL_WIN_H
+#define TUI_GENERAL_WIN_H
+
+/*
+** Functions
+*/
+extern void tuiClearWin PARAMS ((TuiGenWinInfoPtr));
+extern void unhighlightWin PARAMS ((TuiWinInfoPtr));
+extern void makeVisible PARAMS ((TuiGenWinInfoPtr, int));
+extern void makeAllVisible PARAMS ((int));
+extern void scrollWinForward PARAMS ((TuiGenWinInfoPtr, int));
+extern void scrollWinBackward PARAMS ((TuiGenWinInfoPtr, int));
+extern void makeWindow PARAMS ((TuiGenWinInfoPtr, int));
+extern TuiWinInfoPtr copyWin PARAMS ((TuiWinInfoPtr));
+extern void boxWin PARAMS ((TuiGenWinInfoPtr, int));
+extern void highlightWin PARAMS ((TuiWinInfoPtr));
+extern void checkAndDisplayHighlightIfNeeded PARAMS ((TuiWinInfoPtr));
+extern void refreshAll PARAMS ((TuiWinInfoPtr *));
+extern void tuiDelwin PARAMS ((WINDOW *window));
+extern void tuiRefreshWin PARAMS ((TuiGenWinInfoPtr));
+
+/*
+** Macros
+*/
+#define m_beVisible(winInfo) makeVisible((TuiGenWinInfoPtr)(winInfo), TRUE)
+#define m_beInvisible(winInfo) \
+ makeVisible((TuiGenWinInfoPtr)(winInfo), FALSE)
+#define m_allBeVisible() makeAllVisible(TRUE)
+#define m_allBeInvisible() makeAllVisible(FALSE)
+
+#endif /*TUI_GENERAL_WIN_H*/
diff --git a/gdb/tui/tuiIO.c b/gdb/tui/tuiIO.c
new file mode 100644
index 00000000000..29a3613f968
--- /dev/null
+++ b/gdb/tui/tuiIO.c
@@ -0,0 +1,734 @@
+
+/*
+** This module contains functions to support i/o in the TUI
+*/
+
+
+#include <stdio.h>
+#include "defs.h"
+#include "terminal.h"
+#include "tui.h"
+#include "tuiData.h"
+#include "tuiIO.h"
+#include "tuiCommand.h"
+#include "tuiWin.h"
+
+#ifdef ANSI_PROTOTYPES
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+
+/* The Solaris header files seem to provide no declaration for this at
+ all when __STDC__ is defined. This shouldn't conflict with
+ anything. */
+extern char *tgoto ();
+
+int insert_mode = 0;
+
+/********************************************
+** LOCAL STATIC FORWARD DECLS **
+********************************************/
+static void _updateCommandInfo PARAMS ((int));
+static unsigned int _tuiHandleResizeDuringIO PARAMS ((unsigned int));
+
+
+/*********************************************************************************
+** PUBLIC FUNCTIONS **
+*********************************************************************************/
+
+/*
+** tuiPuts_unfiltered().
+** Function to put a string to the command window
+** When running in TUI mode, this is the "hook"
+** for fputs_unfiltered(). That is, all debugger
+** output eventually makes it's way to the bottom-level
+** routine fputs_unfiltered (main.c), which (in TUI
+** mode), calls tuiPuts_unfiltered().
+*/
+void
+#ifdef __STDC__
+tuiPuts_unfiltered (
+ const char *string,
+ GDB_FILE * stream)
+#else
+tuiPuts_unfiltered (string, stream)
+ char *string;
+ GDB_FILE *stream;
+#endif
+{
+ int len = strlen (string);
+ int i, linech;
+
+ for (i = 0; i < len; i++)
+ {
+ if (string[i] == '\n' || string[i] == '\r')
+ m_tuiStartNewLine;
+ else
+ {
+ if ((cmdWin->detail.commandInfo.curch + 1) > cmdWin->generic.width)
+ m_tuiStartNewLine;
+
+ if (insert_mode)
+ {
+ mvwinsch (cmdWin->generic.handle,
+ cmdWin->detail.commandInfo.curLine,
+ cmdWin->detail.commandInfo.curch++,
+ string[i]);
+ wmove (cmdWin->generic.handle,
+ cmdWin->detail.commandInfo.curLine,
+ cmdWin->detail.commandInfo.curch);
+ }
+ else
+ mvwaddch (cmdWin->generic.handle,
+ cmdWin->detail.commandInfo.curLine,
+ cmdWin->detail.commandInfo.curch++,
+ string[i]);
+ }
+ }
+ tuiRefreshWin (&cmdWin->generic);
+
+ return;
+} /* tuiPuts_unfiltered */
+
+/* A cover routine for tputs().
+ * tputs() is called from the readline package to put
+ * out strings representing cursor positioning.
+ * In TUI mode (non-XDB-style), tui_tputs() is called instead.
+ *
+ * The reason we need to hook tputs() is:
+ * Since the output is going to curses and not to
+ * a raw terminal, we need to intercept these special
+ * sequences, and handle them them here.
+ *
+ * This function seems to be correctly handling all sequences
+ * aimed at hpterm's, but there is additional work to do
+ * for xterm's and dtterm's. I abandoned further work on this
+ * in favor of "XDB style". In "XDB style", the command region
+ * looks like terminal, not a curses window, and this routine
+ * is not called. - RT
+ */
+void
+tui_tputs (str, affcnt, putfunc)
+ char *str;
+ int affcnt;
+ int (*putfunc) PARAMS ((int));
+{
+ extern char *rl_prompt; /* the prompt string */
+
+ /* This set of globals are defined and initialized
+ * by the readline package.
+ *
+ * Note we're assuming tui_tputs() is being called
+ * by the readline package. That's because we're recognizing
+ * that a given string is being passed by
+ * matching the string address against readline's
+ * term_<whatever> global. To make this more general,
+ * we'd have to actually recognize the termcap sequence
+ * inside the string (more work than I want to do). - RT
+ *
+ * We don't see or need to handle every one of these here;
+ * this is just the full list defined in readline/readline.c
+ */
+ extern char *term_backspace;
+ extern char *term_clreol;
+ extern char *term_clrpag;
+ extern char *term_cr;
+ extern char *term_dc;
+ extern char *term_ei;
+ extern char *term_goto;
+ extern char *term_ic;
+ extern char *term_im;
+ extern char *term_mm;
+ extern char *term_mo;
+ extern char *term_up;
+ extern char *term_scroll_region;
+ extern char *term_memory_lock;
+ extern char *term_memory_unlock;
+ extern char *term_cursor_move;
+ extern char *visible_bell;
+
+ /* Sanity check - if not TUI, just call tputs() */
+ if (!tui_version)
+ tputs (str, affcnt, putfunc);
+
+ /* The strings we special-case are handled first */
+
+ if (str == term_backspace)
+ {
+ /* Backspace. */
+
+ /* We see this on an emacs control-B.
+ * I.e., it's like the left-arrow key (not like the backspace key).
+ * The effect that readline wants when it transmits this
+ * character to us is simply to back up one character
+ * (but not to write a space over the old character).
+ */
+
+ _updateCommandInfo (-1);
+ wmove (cmdWin->generic.handle,
+ cmdWin->detail.commandInfo.curLine,
+ cmdWin->detail.commandInfo.curch);
+ wrefresh (cmdWin->generic.handle);
+
+ }
+ else if (str == term_clreol)
+ {
+
+ /* Clear to end of line. */
+ wclrtoeol (cmdWin->generic.handle);
+ wrefresh (cmdWin->generic.handle);
+
+ }
+ else if (str == term_cr)
+ {
+
+ /* Carriage return */
+ _updateCommandInfo (-cmdWin->detail.commandInfo.curch);
+ wmove (cmdWin->generic.handle,
+ cmdWin->detail.commandInfo.curLine,
+ 0 /* readline will rewrite the prompt from 0 */ );
+ wrefresh (cmdWin->generic.handle);
+
+ }
+ else if (str == term_goto)
+ {
+
+ /* This is actually a tgoto() specifying a character position,
+ * followed by either a term_IC/term_DC which [I think] means
+ * insert/delete one character at that position.
+ * There are complications with this one - need to either
+ * extract the position from the string, or have a backdoor
+ * means of communicating it from ../readline/display.c.
+ * So this one is not yet implemented.
+ * Not doing it seems to have no ill effects on command-line-editing
+ * that I've noticed so far. - RT
+ */
+
+ }
+ else if (str == term_dc)
+ {
+
+ /* Delete character at current cursor position */
+ wdelch (cmdWin->generic.handle);
+ wrefresh (cmdWin->generic.handle);
+
+ }
+ else if (str == term_im)
+ {
+
+ /* Turn on insert mode. */
+ insert_mode = 1;
+
+ }
+ else if (str == term_ei)
+ {
+
+ /* Turn off insert mode. */
+ insert_mode = 0;
+
+ /* Strings we know about but don't handle
+ * specially here are just passed along to tputs().
+ *
+ * These are not handled because (as far as I can tell)
+ * they are not actually emitted by the readline package
+ * in the course of doing command-line editing. Some of them
+ * theoretically could be used in the future, in which case we'd
+ * need to handle them.
+ */
+ }
+ else if (str == term_ic || /* insert character */
+ str == term_cursor_move || /* cursor move */
+ str == term_clrpag ||/* clear page */
+ str == term_mm || /* turn on meta key */
+ str == term_mo || /* turn off meta key */
+ str == term_up || /* up one line (not expected) */
+ str == term_scroll_region || /* set scroll region */
+ str == term_memory_lock || /* lock screen above cursor */
+ str == term_memory_unlock || /* unlock screen above cursor */
+ str == visible_bell)
+ { /* flash screen */
+ tputs (str, affcnt, putfunc);
+ }
+ else
+ { /* something else */
+ tputs (str, affcnt, putfunc);
+ }
+} /* tui_tputs */
+
+
+/*
+** tui_vwgetch()
+** Wrapper around wgetch with the window in a va_list
+*/
+unsigned int
+#ifdef __STDC__
+tui_vwgetch (va_list args)
+#else
+tui_vwgetch (args)
+ va_list args;
+#endif
+{
+ unsigned int ch;
+ WINDOW *window;
+
+ window = va_arg (args, WINDOW *);
+
+ return ((unsigned int) wgetch (window));
+} /* tui_vwgetch */
+
+
+/*
+** tui_vread()
+** Wrapper around read() with paramets in a va_list
+*/
+unsigned int
+#ifdef __STDC__
+tui_vread (va_list args)
+#else
+tui_vread (args)
+ va_list args;
+#endif
+{
+ int result = 0;
+ int filedes = va_arg (args, int);
+ char *buf = va_arg (args, char *);
+ int nbytes = va_arg (args, int);
+
+ result = read (filedes, buf, nbytes);
+
+ return result;
+} /* tui_vread() */
+
+/*
+** tuiRead()
+** Function to perform a read() catching resize events
+*/
+int
+#ifdef __STDC__
+tuiRead (
+ int filedes,
+ char *buf,
+ int nbytes)
+#else
+tuiRead (filedes, buf, nbytes)
+ int filedes;
+ char *buf;
+ int nbytes;
+#endif
+{
+ int result = 0;
+
+ result = (int) vcatch_errors ((OpaqueFuncPtr) tui_vread, filedes, buf, nbytes);
+ *buf = _tuiHandleResizeDuringIO (*buf);
+
+ return result;
+} /* tuiRead */
+
+
+/*
+** tuiGetc().
+** Get a character from the command window.
+** This is called from the readline package,
+** that is, we have:
+** tuiGetc() [here], called from
+** readline code [in ../readline/], called from
+** command_line_input() in top.c
+*/
+unsigned int
+#ifdef __STDC__
+tuiGetc (void)
+#else
+tuiGetc ()
+#endif
+{
+ unsigned int ch;
+ extern char *rl_prompt;
+ extern char *rl_line_buffer;
+ extern int rl_point;
+
+ /* Call the curses routine that reads one character */
+#ifndef COMMENT
+ ch = (unsigned int) vcatch_errors ((OpaqueFuncPtr) tui_vwgetch,
+ cmdWin->generic.handle);
+#else
+ ch = wgetch (cmdWin->generic.handle);
+#endif
+ ch = _tuiHandleResizeDuringIO (ch);
+
+ if (m_isCommandChar (ch))
+ { /* Handle prev/next/up/down here */
+ tuiTermSetup (0);
+ ch = tuiDispatchCtrlChar (ch);
+ cmdWin->detail.commandInfo.curch = strlen (rl_prompt) + rl_point;
+ tuiTermUnsetup (0, cmdWin->detail.commandInfo.curch);
+ }
+ if (ch == '\n' || ch == '\r' || ch == '\f')
+ cmdWin->detail.commandInfo.curch = 0;
+ else
+ tuiIncrCommandCharCountBy (1);
+
+ return ch;
+} /* tuiGetc */
+
+
+/*
+** tuiBufferGetc().
+*/
+/*elz: this function reads a line of input from the user and
+puts it in a static buffer. Subsequent calls to this same function
+obtain one char at the time, providing the caller with a behavior
+similar to fgetc. When the input is buffered, the backspaces have
+the needed effect, i.e. ignore the last char active in the buffer*/
+/* so far this function is called only from the query function in
+utils.c*/
+
+unsigned int
+#ifdef __STDC__
+tuiBufferGetc (void)
+#else
+tuiBufferGetc ()
+#endif
+{
+ unsigned int ch;
+ static unsigned char _ibuffer[512];
+ static int index_read = -1;
+ static int length_of_answer = -1;
+ int pos = 0;
+
+ if (length_of_answer == -1)
+ {
+ /* this is the first time through, need to read the answer*/
+ do
+ {
+ /* Call the curses routine that reads one character */
+ ch = (unsigned int) wgetch (cmdWin->generic.handle);
+ if (ch != '\b')
+ {
+ _ibuffer[pos] = ch;
+ pos++;
+ }
+ else
+ pos--;
+ }
+ while (ch != '\r' && ch != '\n');
+
+ length_of_answer = pos;
+ index_read = 0;
+ }
+
+ ch = _ibuffer[index_read];
+ index_read++;
+
+ if (index_read == length_of_answer)
+ {
+ /*this is the last time through, reset for next query*/
+ index_read = -1;
+ length_of_answer = -1;
+ }
+
+ wrefresh (cmdWin->generic.handle);
+
+ return (ch);
+} /* tuiBufferGetc */
+
+
+/*
+** tuiStartNewLines().
+*/
+void
+#ifdef __STDC__
+tuiStartNewLines (
+ int numLines)
+#else
+tuiStartNewLines (numLines)
+ int numLines;
+#endif
+{
+ if (numLines > 0)
+ {
+ if (cmdWin->generic.viewportHeight > 1 &&
+ cmdWin->detail.commandInfo.curLine < cmdWin->generic.viewportHeight)
+ cmdWin->detail.commandInfo.curLine += numLines;
+ else
+ scroll (cmdWin->generic.handle);
+ cmdWin->detail.commandInfo.curch = 0;
+ wmove (cmdWin->generic.handle,
+ cmdWin->detail.commandInfo.curLine,
+ cmdWin->detail.commandInfo.curch);
+ tuiRefreshWin (&cmdWin->generic);
+ }
+
+ return;
+} /* tuiStartNewLines */
+
+
+/*
+** tui_vStartNewLines().
+** With numLines in a va_list
+*/
+void
+#ifdef __STDC__
+tui_vStartNewLines (
+ va_list args)
+#else
+tui_vStartNewLines (args)
+ va_list args;
+#endif
+{
+ int numLines = va_arg (args, int);
+
+ tuiStartNewLines (numLines);
+
+ return;
+} /* tui_vStartNewLines */
+
+
+/****************************************************************************
+** LOCAL STATIC FUNCTIONS **
+*****************************************************************************/
+
+
+/*
+** _tuiHandleResizeDuringIO
+** This function manages the cleanup when a resize has occured
+** From within a call to getch() or read. Returns the character
+** to return from getc or read.
+*/
+static unsigned int
+#ifdef __STDC__
+_tuiHandleResizeDuringIO (
+ unsigned int originalCh) /* the char just read */
+#else
+_tuiHandleResizeDuringIO (originalCh)
+ unsigned int originalCh;
+#endif
+{
+ if (tuiWinResized ())
+ {
+ tuiDo ((TuiOpaqueFuncPtr) tuiRefreshAll);
+ dont_repeat ();
+ tuiSetWinResizedTo (FALSE);
+ rl_reset ();
+ return '\n';
+ }
+ else
+ return originalCh;
+} /* _tuiHandleResizeDuringIO */
+
+
+/*
+** _updateCommandInfo().
+** Function to update the command window information.
+*/
+static void
+#ifdef __STDC__
+_updateCommandInfo (
+ int sizeOfString)
+#else
+_updateCommandInfo (sizeOfString)
+ int sizeOfString;
+#endif
+{
+
+ if ((sizeOfString +
+ cmdWin->detail.commandInfo.curch) > cmdWin->generic.width)
+ {
+ int newCurch = sizeOfString + cmdWin->detail.commandInfo.curch;
+
+ tuiStartNewLines (1);
+ cmdWin->detail.commandInfo.curch = newCurch - cmdWin->generic.width;
+ }
+ else
+ cmdWin->detail.commandInfo.curch += sizeOfString;
+
+ return;
+} /* _updateCommandInfo */
+
+
+/* Looked at in main.c, fputs_unfiltered(), to decide
+ * if it's safe to do standard output to the command window.
+ */
+int tui_owns_terminal = 0;
+
+/* Called to set up the terminal for TUI (curses) I/O.
+ * We do this either on our way "in" to GDB after target
+ * program execution, or else within tuiDo just before
+ * going off to TUI routines.
+ */
+
+void
+#ifdef __STDC__
+tuiTermSetup (
+ int turn_off_echo)
+#else
+tuiTermSetup (turn_off_echo)
+ int turn_off_echo;
+#endif
+{
+ char *buffer;
+ int start;
+ int end;
+ int endcol;
+ extern char *term_scroll_region;
+ extern char *term_cursor_move;
+ extern char *term_memory_lock;
+ extern char *term_memory_unlock;
+
+ /* Turn off echoing, since the TUI does not
+ * expect echoing. Below I only put in the TERMIOS
+ * case, since that is what applies on HP-UX. turn_off_echo
+ * is 1 except for the case where we're being called
+ * on a "quit", in which case we want to leave echo on.
+ */
+ if (turn_off_echo)
+ {
+#ifdef HAVE_TERMIOS
+ struct termios tio;
+ tcgetattr (0, &tio);
+ tio.c_lflag &= ~(ECHO);
+ tcsetattr (0, TCSANOW, &tio);
+#endif
+ }
+
+ /* Compute the start and end lines of the command
+ * region. (Actually we only use end here)
+ */
+ start = winList[CMD_WIN]->generic.origin.y;
+ end = start + winList[CMD_WIN]->generic.height - 1;
+ endcol = winList[CMD_WIN]->generic.width - 1;
+
+ if (term_memory_unlock)
+ {
+
+ /* Un-do the effect of the memory lock in terminal_inferior() */
+ tputs (term_memory_unlock, 1, (int (*)PARAMS ((int))) putchar);
+ fflush (stdout);
+
+ }
+ else if (term_scroll_region)
+ {
+
+ /* Un-do the effect of setting scroll region in terminal_inferior() */
+ /* I'm actually not sure how to do this (we don't know for
+ * sure what the scroll region was *before* we changed it),
+ * but I'll guess that setting it to the whole screen is
+ * the right thing. So, ...
+ */
+
+ /* Set scroll region to be 0..end */
+ buffer = (char *) tgoto (term_scroll_region, end, 0);
+ tputs (buffer, 1, (int (*)PARAMS ((int))) putchar);
+
+ } /* else we're out of luck */
+
+ /* This is an attempt to keep the logical & physical
+ * cursor in synch, going into curses. Without this,
+ * curses seems to be confused by the fact that
+ * GDB has physically moved the curser on it. One
+ * visible effect of removing this code is that the
+ * locator window fails to get updated and the line
+ * of text that *should* go into the locator window
+ * often goes to the wrong place.
+ */
+ /* What's done here is to tell curses to write a ' '
+ * at the bottom right corner of the screen.
+ * The idea is to wind up with the cursor in a known
+ * place.
+ * Note I'm relying on refresh()
+ * only writing what changed (the space),
+ * not the whole screen.
+ */
+ standend ();
+ move (end, endcol - 1);
+ addch (' ');
+ refresh ();
+
+ tui_owns_terminal = 1;
+} /* tuiTermSetup */
+
+
+/* Called to set up the terminal for target program I/O, meaning I/O
+ * is confined to the command-window area. We also call this on our
+ * way out of tuiDo, thus setting up the terminal this way for
+ * debugger command I/O. */
+void
+#ifdef __STDC__
+tuiTermUnsetup (
+ int turn_on_echo,
+ int to_column)
+#else
+tuiTermUnsetup (turn_on_echo, to_column)
+ int turn_on_echo;
+ int to_column;
+#endif
+{
+ int start;
+ int end;
+ int curline;
+ char *buffer;
+ /* The next bunch of things are from readline */
+ extern char *term_scroll_region;
+ extern char *term_cursor_move;
+ extern char *term_memory_lock;
+ extern char *term_memory_unlock;
+ extern char *term_se;
+
+ /* We need to turn on echoing, since the TUI turns it off */
+ /* Below I only put in the TERMIOS case, since that
+ * is what applies on HP-UX.
+ */
+ if (turn_on_echo)
+ {
+#ifdef HAVE_TERMIOS
+ struct termios tio;
+ tcgetattr (0, &tio);
+ tio.c_lflag |= (ECHO);
+ tcsetattr (0, TCSANOW, &tio);
+#endif
+ }
+
+ /* Compute the start and end lines of the command
+ * region, as well as the last "real" line of
+ * the region (normally same as end, except when
+ * we're first populating the region)
+ */
+ start = winList[CMD_WIN]->generic.origin.y;
+ end = start + winList[CMD_WIN]->generic.height - 1;
+ curline = start + winList[CMD_WIN]->detail.commandInfo.curLine;
+
+ /* We want to confine target I/O to the command region.
+ * In order to do so, we must either have "memory lock"
+ * (hpterm's) or "scroll regions" (xterm's).
+ */
+ if (term_cursor_move && term_memory_lock)
+ {
+
+ /* Memory lock means lock region above cursor.
+ * So first position the cursor, then call memory lock.
+ */
+ buffer = tgoto (term_cursor_move, 0, start);
+ tputs (buffer, 1, (int (*)PARAMS ((int))) putchar);
+ tputs (term_memory_lock, 1, (int (*)PARAMS ((int))) putchar);
+
+ }
+ else if (term_scroll_region)
+ {
+
+ /* Set the scroll region to the command window */
+ buffer = tgoto (term_scroll_region, end, start);
+ tputs (buffer, 1, (int (*)PARAMS ((int))) putchar);
+
+ } /* else we can't do anything about target I/O */
+
+ /* Also turn off standout mode, in case it is on */
+ if (term_se != NULL)
+ tputs (term_se, 1, (int (*)PARAMS ((int))) putchar);
+
+ /* Now go to the appropriate spot on the end line */
+ buffer = tgoto (term_cursor_move, to_column, end);
+ tputs (buffer, 1, (int (*)PARAMS ((int))) putchar);
+ fflush (stdout);
+
+ tui_owns_terminal = 0;
+} /* tuiTermUnsetup */
diff --git a/gdb/tui/tuiIO.h b/gdb/tui/tuiIO.h
new file mode 100644
index 00000000000..bcbeffe4edc
--- /dev/null
+++ b/gdb/tui/tuiIO.h
@@ -0,0 +1,43 @@
+#ifndef _TUI_IO_H
+#define _TUI_IO_H
+/*
+** This header contains defitions to support tuiIO.c
+*/
+
+
+#include <stdio.h>
+
+extern void tuiPuts_unfiltered PARAMS ((const char *, GDB_FILE *));
+extern unsigned int tuiGetc PARAMS ((void));
+extern unsigned int tuiBufferGetc PARAMS ((void));
+extern int tuiRead PARAMS ((int, char *, int));
+extern void tuiStartNewLines PARAMS ((int));
+extern void tui_vStartNewLines PARAMS ((va_list));
+extern unsigned int tui_vwgetch PARAMS ((va_list));
+extern void tuiTermSetup PARAMS ((int));
+extern void tuiTermUnsetup PARAMS ((int, int));
+
+
+
+#define m_tuiStartNewLine tuiStartNewLines(1)
+#define m_isStartSequence(ch) (ch == 27)
+#define m_isEndSequence(ch) (ch == 126)
+#define m_isBackspace(ch) (ch == 8)
+#define m_isDeleteChar(ch) (ch == KEY_DC)
+#define m_isDeleteLine(ch) (ch == KEY_DL)
+#define m_isDeleteToEol(ch) (ch == KEY_EOL)
+#define m_isNextPage(ch) (ch == KEY_NPAGE)
+#define m_isPrevPage(ch) (ch == KEY_PPAGE)
+#define m_isLeftArrow(ch) (ch == KEY_LEFT)
+#define m_isRightArrow(ch) (ch == KEY_RIGHT)
+
+#define m_isCommandChar(ch) (m_isNextPage(ch) || m_isPrevPage(ch) || \
+ m_isLeftArrow(ch) || m_isRightArrow(ch) || \
+ (ch == KEY_UP) || (ch == KEY_DOWN) || \
+ (ch == KEY_SF) || (ch == KEY_SR) || \
+ (ch == (int)'\f') || m_isStartSequence(ch))
+
+#define m_isXdbStyleCommandChar(ch) (m_isNextPage(ch) || m_isPrevPage(ch))
+
+
+#endif /*_TUI_IO_H*/
diff --git a/gdb/tui/tuiLayout.c b/gdb/tui/tuiLayout.c
new file mode 100644
index 00000000000..6aa380cfe41
--- /dev/null
+++ b/gdb/tui/tuiLayout.c
@@ -0,0 +1,1410 @@
+/*
+** tuiLayout.c
+** This module contains procedures for handling the layout of the windows.
+*/
+
+
+#include "defs.h"
+#include "command.h"
+#include "symtab.h"
+#include "frame.h"
+
+#include "tui.h"
+#include "tuiData.h"
+#include "tuiGeneralWin.h"
+#include "tuiStack.h"
+#include "tuiRegs.h"
+#include "tuiDisassem.h"
+
+/*******************************
+** Static Local Decls
+********************************/
+
+static void _initGenWinInfo PARAMS
+ ((TuiGenWinInfoPtr, TuiWinType, int, int, int, int));
+static void _initAndMakeWin PARAMS
+ ((Opaque *, TuiWinType, int, int, int, int, int));
+static void _showSourceOrDisassemAndCommand PARAMS
+ ((TuiLayoutType));
+static void _makeSourceOrDisassemWindow PARAMS
+ ((TuiWinInfoPtr *, TuiWinType, int, int));
+static void _makeCommandWindow PARAMS ((TuiWinInfoPtr *, int, int));
+static void _makeSourceWindow PARAMS ((TuiWinInfoPtr *, int, int));
+static void _makeDisassemWindow PARAMS
+ ((TuiWinInfoPtr *, int, int));
+static void _makeDataWindow PARAMS ((TuiWinInfoPtr *, int, int));
+static void _showSourceCommand PARAMS ((void));
+static void _showDisassemCommand PARAMS ((void));
+static void _showSourceDisassemCommand PARAMS ((void));
+static void _showData PARAMS ((TuiLayoutType));
+static TuiLayoutType _nextLayout PARAMS ((void));
+static TuiLayoutType _prevLayout PARAMS ((void));
+static void _tuiLayout_command PARAMS ((char *, int));
+static void _tuiToggleLayout_command PARAMS ((char *, int));
+static void _tui_vToggleLayout_command PARAMS ((va_list));
+static void _tuiToggleSplitLayout_command PARAMS ((char *, int));
+static void _tui_vToggleSplitLayout_command PARAMS ((va_list));
+static Opaque _extractDisplayStartAddr PARAMS ((void));
+static void _tuiHandleXDBLayout PARAMS ((TuiLayoutDefPtr));
+static TuiStatus _tuiSetLayoutTo PARAMS ((char *));
+
+
+/***************************************
+** DEFINITIONS
+***************************************/
+
+#define LAYOUT_USAGE "Usage: layout prev | next | <layout_name> \n"
+
+/***************************************
+** Static Local Data
+***************************************/
+static TuiLayoutType lastLayout = UNDEFINED_LAYOUT;
+
+/***************************************
+** PUBLIC FUNCTIONS
+***************************************/
+
+/*
+** showLayout().
+** Show the screen layout defined
+*/
+void
+#ifdef __STDC__
+showLayout (
+ TuiLayoutType layout)
+#else
+showLayout (layout)
+ TuiLayoutType layout;
+#endif
+{
+ TuiLayoutType curLayout = currentLayout ();
+
+ if (layout != curLayout)
+ {
+ /*
+ ** Since the new layout may cause changes in window size, we
+ ** should free the content and reallocate on next display of
+ ** source/asm
+ */
+ tuiClearAllSourceWinsContent (NO_EMPTY_SOURCE_PROMPT);
+ freeAllSourceWinsContent ();
+ clearSourceWindows ();
+ if (layout == SRC_DATA_COMMAND || layout == DISASSEM_DATA_COMMAND)
+ {
+ _showData (layout);
+ refreshAll (winList);
+ }
+ else
+ {
+ /* First make the current layout be invisible */
+ m_allBeInvisible ();
+ m_beInvisible (locatorWinInfoPtr ());
+
+ switch (layout)
+ {
+ /* Now show the new layout */
+ case SRC_COMMAND:
+ _showSourceCommand ();
+ addToSourceWindows (srcWin);
+ break;
+ case DISASSEM_COMMAND:
+ _showDisassemCommand ();
+ addToSourceWindows (disassemWin);
+ break;
+ case SRC_DISASSEM_COMMAND:
+ _showSourceDisassemCommand ();
+ addToSourceWindows (srcWin);
+ addToSourceWindows (disassemWin);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ return;
+} /* showLayout */
+
+
+/*
+** tuiSetLayout()
+** Function to set the layout to SRC_COMMAND, DISASSEM_COMMAND,
+** SRC_DISASSEM_COMMAND, SRC_DATA_COMMAND, or DISASSEM_DATA_COMMAND.
+** If the layout is SRC_DATA_COMMAND, DISASSEM_DATA_COMMAND, or
+** UNDEFINED_LAYOUT, then the data window is populated according
+** to regsDisplayType.
+*/
+TuiStatus
+#ifdef __STDC__
+tuiSetLayout (
+ TuiLayoutType layoutType,
+ TuiRegisterDisplayType regsDisplayType)
+#else
+tuiSetLayout (layoutType, regsDisplayType)
+ TuiLayoutType layoutType;
+ TuiRegisterDisplayType regsDisplayType;
+#endif
+{
+ TuiStatus status = TUI_SUCCESS;
+
+ if (layoutType != UNDEFINED_LAYOUT || regsDisplayType != TUI_UNDEFINED_REGS)
+ {
+ TuiLayoutType curLayout = currentLayout (), newLayout = UNDEFINED_LAYOUT;
+ int regsPopulate = FALSE;
+ Opaque addr = _extractDisplayStartAddr ();
+ TuiWinInfoPtr newWinWithFocus = (TuiWinInfoPtr) NULL, winWithFocus = tuiWinWithFocus ();
+ TuiLayoutDefPtr layoutDef = tuiLayoutDef ();
+
+
+ if (layoutType == UNDEFINED_LAYOUT &&
+ regsDisplayType != TUI_UNDEFINED_REGS)
+ {
+ if (curLayout == SRC_DISASSEM_COMMAND)
+ newLayout = DISASSEM_DATA_COMMAND;
+ else if (curLayout == SRC_COMMAND || curLayout == SRC_DATA_COMMAND)
+ newLayout = SRC_DATA_COMMAND;
+ else if (curLayout == DISASSEM_COMMAND ||
+ curLayout == DISASSEM_DATA_COMMAND)
+ newLayout = DISASSEM_DATA_COMMAND;
+ }
+ else
+ newLayout = layoutType;
+
+ regsPopulate = (newLayout == SRC_DATA_COMMAND ||
+ newLayout == DISASSEM_DATA_COMMAND ||
+ regsDisplayType != TUI_UNDEFINED_REGS);
+ if (newLayout != curLayout || regsDisplayType != TUI_UNDEFINED_REGS)
+ {
+ if (newLayout != curLayout)
+ {
+ if (winWithFocus != cmdWin)
+ tuiClearWinFocus ();
+ showLayout (newLayout);
+ /*
+ ** Now determine where focus should be
+ */
+ if (winWithFocus != cmdWin)
+ {
+ switch (newLayout)
+ {
+ case SRC_COMMAND:
+ tuiSetWinFocusTo (srcWin);
+ layoutDef->displayMode = SRC_WIN;
+ layoutDef->split = FALSE;
+ break;
+ case DISASSEM_COMMAND:
+ /* the previous layout was not showing
+ ** code. this can happen if there is no
+ ** source available:
+ ** 1. if the source file is in another dir OR
+ ** 2. if target was compiled without -g
+ ** We still want to show the assembly though!
+ */
+ addr = vcatch_errors ((OpaqueFuncPtr)
+ tuiGetBeginAsmAddress);
+ tuiSetWinFocusTo (disassemWin);
+ layoutDef->displayMode = DISASSEM_WIN;
+ layoutDef->split = FALSE;
+ break;
+ case SRC_DISASSEM_COMMAND:
+ /* the previous layout was not showing
+ ** code. this can happen if there is no
+ ** source available:
+ ** 1. if the source file is in another dir OR
+ ** 2. if target was compiled without -g
+ ** We still want to show the assembly though!
+ */
+ addr = vcatch_errors ((OpaqueFuncPtr)
+ tuiGetBeginAsmAddress);
+ if (winWithFocus == srcWin)
+ tuiSetWinFocusTo (srcWin);
+ else
+ tuiSetWinFocusTo (disassemWin);
+ layoutDef->split = TRUE;
+ break;
+ case SRC_DATA_COMMAND:
+ if (winWithFocus != dataWin)
+ tuiSetWinFocusTo (srcWin);
+ else
+ tuiSetWinFocusTo (dataWin);
+ layoutDef->displayMode = SRC_WIN;
+ layoutDef->split = FALSE;
+ break;
+ case DISASSEM_DATA_COMMAND:
+ /* the previous layout was not showing
+ ** code. this can happen if there is no
+ ** source available:
+ ** 1. if the source file is in another dir OR
+ ** 2. if target was compiled without -g
+ ** We still want to show the assembly though!
+ */
+ addr = vcatch_errors ((OpaqueFuncPtr)
+ tuiGetBeginAsmAddress);
+ if (winWithFocus != dataWin)
+ tuiSetWinFocusTo (disassemWin);
+ else
+ tuiSetWinFocusTo (dataWin);
+ layoutDef->displayMode = DISASSEM_WIN;
+ layoutDef->split = FALSE;
+ break;
+ default:
+ break;
+ }
+ }
+ if (newWinWithFocus != (TuiWinInfoPtr) NULL)
+ tuiSetWinFocusTo (newWinWithFocus);
+ /*
+ ** Now update the window content
+ */
+ if (!regsPopulate &&
+ (newLayout == SRC_DATA_COMMAND ||
+ newLayout == DISASSEM_DATA_COMMAND))
+ tuiDisplayAllData ();
+
+ tuiUpdateSourceWindowsWithAddr (addr);
+ }
+ if (regsPopulate)
+ {
+ layoutDef->regsDisplayType =
+ (regsDisplayType == TUI_UNDEFINED_REGS ?
+ TUI_GENERAL_REGS : regsDisplayType);
+ tuiShowRegisters (layoutDef->regsDisplayType);
+ }
+ }
+ }
+ else
+ status = TUI_FAILURE;
+
+ return status;
+} /* tuiSetLayout */
+
+
+/*
+** tui_vSetLayoutTo()
+** Function to set the layout to SRC, ASM, SPLIT, NEXT, PREV, DATA,
+** REGS, $REGS, $GREGS, $FREGS, $SREGS with arguments in a va_list
+*/
+TuiStatus
+#ifdef __STDC__
+tui_vSetLayoutTo (
+ va_list args)
+#else
+tui_vSetLayoutTo (args)
+ va_list args;
+#endif
+{
+ char *layoutName;
+
+ layoutName = va_arg (args, char *);
+
+ return (_tuiSetLayoutTo (layoutName));
+} /* tui_vSetLayoutTo */
+
+
+/*
+** tuiAddWinToLayout().
+** Add the specified window to the layout in a logical way.
+** This means setting up the most logical layout given the
+** window to be added.
+*/
+void
+#ifdef __STDC__
+tuiAddWinToLayout (
+ TuiWinType type)
+#else
+tuiAddWinToLayout (type)
+ TuiWinType type;
+#endif
+{
+ TuiLayoutType curLayout = currentLayout ();
+
+ switch (type)
+ {
+ case SRC_WIN:
+ if (curLayout != SRC_COMMAND &&
+ curLayout != SRC_DISASSEM_COMMAND &&
+ curLayout != SRC_DATA_COMMAND)
+ {
+ clearSourceWindowsDetail ();
+ if (curLayout == DISASSEM_DATA_COMMAND)
+ showLayout (SRC_DATA_COMMAND);
+ else
+ showLayout (SRC_COMMAND);
+ }
+ break;
+ case DISASSEM_WIN:
+ if (curLayout != DISASSEM_COMMAND &&
+ curLayout != SRC_DISASSEM_COMMAND &&
+ curLayout != DISASSEM_DATA_COMMAND)
+ {
+ clearSourceWindowsDetail ();
+ if (curLayout == SRC_DATA_COMMAND)
+ showLayout (DISASSEM_DATA_COMMAND);
+ else
+ showLayout (DISASSEM_COMMAND);
+ }
+ break;
+ case DATA_WIN:
+ if (curLayout != SRC_DATA_COMMAND &&
+ curLayout != DISASSEM_DATA_COMMAND)
+ {
+ if (curLayout == DISASSEM_COMMAND)
+ showLayout (DISASSEM_DATA_COMMAND);
+ else
+ showLayout (SRC_DATA_COMMAND);
+ }
+ break;
+ default:
+ break;
+ }
+
+ return;
+} /* tuiAddWinToLayout */
+
+
+/*
+** tui_vAddWinToLayout().
+** Add the specified window to the layout in a logical way,
+** with arguments in a va_list.
+*/
+void
+#ifdef __STDC__
+tui_vAddWinToLayout (
+ va_list args)
+#else
+tui_vAddWinToLayout (args)
+ va_list args;
+#endif
+{
+ TuiWinType type = va_arg (args, TuiWinType);
+
+ tuiAddWinToLayout (type);
+
+ return;
+} /* tui_vAddWinToLayout */
+
+
+/*
+** tuiDefaultWinHeight().
+** Answer the height of a window. If it hasn't been created yet,
+** answer what the height of a window would be based upon its
+** type and the layout.
+*/
+int
+#ifdef __STDC__
+tuiDefaultWinHeight (
+ TuiWinType type,
+ TuiLayoutType layout)
+#else
+tuiDefaultWinHeight (type, layout)
+ TuiWinType type;
+ TuiLayoutType layout;
+#endif
+{
+ int h;
+
+ if (winList[type] != (TuiWinInfoPtr) NULL)
+ h = winList[type]->generic.height;
+ else
+ {
+ switch (layout)
+ {
+ case SRC_COMMAND:
+ case DISASSEM_COMMAND:
+ if (m_winPtrIsNull (cmdWin))
+ h = termHeight () / 2;
+ else
+ h = termHeight () - cmdWin->generic.height;
+ break;
+ case SRC_DISASSEM_COMMAND:
+ case SRC_DATA_COMMAND:
+ case DISASSEM_DATA_COMMAND:
+ if (m_winPtrIsNull (cmdWin))
+ h = termHeight () / 3;
+ else
+ h = (termHeight () - cmdWin->generic.height) / 2;
+ break;
+ default:
+ h = 0;
+ break;
+ }
+ }
+
+ return h;
+} /* tuiDefaultWinHeight */
+
+
+/*
+** tuiDefaultWinViewportHeight().
+** Answer the height of a window. If it hasn't been created yet,
+** answer what the height of a window would be based upon its
+** type and the layout.
+*/
+int
+#ifdef __STDC__
+tuiDefaultWinViewportHeight (
+ TuiWinType type,
+ TuiLayoutType layout)
+#else
+tuiDefaultWinViewportHeight (type, layout)
+ TuiWinType type;
+ TuiLayoutType layout;
+#endif
+{
+ int h;
+
+ h = tuiDefaultWinHeight (type, layout);
+
+ if (winList[type] == cmdWin)
+ h -= 1;
+ else
+ h -= 2;
+
+ return h;
+} /* tuiDefaultWinViewportHeight */
+
+
+/*
+** _initialize_tuiLayout().
+** Function to initialize gdb commands, for tui window layout
+** manipulation.
+*/
+void
+_initialize_tuiLayout ()
+{
+ if (tui_version)
+ {
+ add_com ("layout", class_tui, _tuiLayout_command,
+ "Change the layout of windows.\n\
+Usage: layout prev | next | <layout_name> \n\
+Layout names are:\n\
+ src : Displays source and command windows.\n\
+ asm : Displays disassembly and command windows.\n\
+ split : Displays source, disassembly and command windows.\n\
+ regs : Displays register window. If existing layout\n\
+ is source/command or assembly/command, the \n\
+ register window is displayed. If the\n\
+ source/assembly/command (split) is displayed, \n\
+ the register window is displayed with \n\
+ the window that has current logical focus.\n");
+ if (xdb_commands)
+ {
+ add_com ("td", class_tui, _tuiToggleLayout_command,
+ "Toggle between Source/Command and Disassembly/Command layouts.\n");
+ add_com ("ts", class_tui, _tuiToggleSplitLayout_command,
+ "Toggle between Source/Command or Disassembly/Command and \n\
+Source/Disassembly/Command layouts.\n");
+ }
+ }
+
+ return;
+} /* _intialize_tuiLayout */
+
+
+/*************************
+** STATIC LOCAL FUNCTIONS
+**************************/
+
+
+/*
+** _tuiSetLayoutTo()
+** Function to set the layout to SRC, ASM, SPLIT, NEXT, PREV, DATA, REGS,
+** $REGS, $GREGS, $FREGS, $SREGS.
+*/
+static TuiStatus
+#ifdef __STDC__
+_tuiSetLayoutTo (
+ char *layoutName)
+#else
+_tuiSetLayoutTo (layoutName)
+ char *layoutName;
+#endif
+{
+ TuiStatus status = TUI_SUCCESS;
+
+ if (layoutName != (char *) NULL)
+ {
+ register int i;
+ register char *bufPtr;
+ TuiLayoutType newLayout = UNDEFINED_LAYOUT;
+ TuiRegisterDisplayType dpyType = TUI_UNDEFINED_REGS;
+ TuiLayoutType curLayout = currentLayout ();
+
+ bufPtr = (char *) tuiStrDup (layoutName);
+ for (i = 0; (i < strlen (layoutName)); i++)
+ bufPtr[i] = toupper (bufPtr[i]);
+
+ /* First check for ambiguous input */
+ if (strlen (bufPtr) <= 1 && (*bufPtr == 'S' || *bufPtr == '$'))
+ {
+ warning ("Ambiguous command input.\n");
+ status = TUI_FAILURE;
+ }
+ else
+ {
+ if (subsetCompare (bufPtr, "SRC"))
+ newLayout = SRC_COMMAND;
+ else if (subsetCompare (bufPtr, "ASM"))
+ newLayout = DISASSEM_COMMAND;
+ else if (subsetCompare (bufPtr, "SPLIT"))
+ newLayout = SRC_DISASSEM_COMMAND;
+ else if (subsetCompare (bufPtr, "REGS") ||
+ subsetCompare (bufPtr, TUI_GENERAL_SPECIAL_REGS_NAME) ||
+ subsetCompare (bufPtr, TUI_GENERAL_REGS_NAME) ||
+ subsetCompare (bufPtr, TUI_FLOAT_REGS_NAME) ||
+ subsetCompare (bufPtr, TUI_SPECIAL_REGS_NAME))
+ {
+ if (curLayout == SRC_COMMAND || curLayout == SRC_DATA_COMMAND)
+ newLayout = SRC_DATA_COMMAND;
+ else
+ newLayout = DISASSEM_DATA_COMMAND;
+
+/* could ifdef out the following code. when compile with -z, there are null
+ pointer references that cause a core dump if 'layout regs' is the first
+ layout command issued by the user. HP has asked us to hook up this code
+ - edie epstein
+ */
+ if (subsetCompare (bufPtr, TUI_FLOAT_REGS_NAME))
+ {
+ if (dataWin->detail.dataDisplayInfo.regsDisplayType !=
+ TUI_SFLOAT_REGS &&
+ dataWin->detail.dataDisplayInfo.regsDisplayType !=
+ TUI_DFLOAT_REGS)
+ dpyType = TUI_SFLOAT_REGS;
+ else
+ dpyType =
+ dataWin->detail.dataDisplayInfo.regsDisplayType;
+ }
+ else if (subsetCompare (bufPtr,
+ TUI_GENERAL_SPECIAL_REGS_NAME))
+ dpyType = TUI_GENERAL_AND_SPECIAL_REGS;
+ else if (subsetCompare (bufPtr, TUI_GENERAL_REGS_NAME))
+ dpyType = TUI_GENERAL_REGS;
+ else if (subsetCompare (bufPtr, TUI_SPECIAL_REGS_NAME))
+ dpyType = TUI_SPECIAL_REGS;
+ else
+ {
+ if (dataWin->detail.dataDisplayInfo.regsDisplayType !=
+ TUI_UNDEFINED_REGS)
+ dpyType =
+ dataWin->detail.dataDisplayInfo.regsDisplayType;
+ else
+ dpyType = TUI_GENERAL_REGS;
+ }
+
+/* end of potential ifdef
+ */
+
+/* if ifdefed out code above, then assume that the user wishes to display the
+ general purpose registers
+ */
+
+/* dpyType = TUI_GENERAL_REGS;
+ */
+ }
+ else if (subsetCompare (bufPtr, "NEXT"))
+ newLayout = _nextLayout ();
+ else if (subsetCompare (bufPtr, "PREV"))
+ newLayout = _prevLayout ();
+ else
+ status = TUI_FAILURE;
+ free (bufPtr);
+
+ tuiSetLayout (newLayout, dpyType);
+ }
+ }
+ else
+ status = TUI_FAILURE;
+
+ return status;
+} /* _tuiSetLayoutTo */
+
+
+static Opaque
+#ifdef __STDC__
+_extractDisplayStartAddr (void)
+#else
+_extractDisplayStartAddr ()
+#endif
+{
+ TuiLayoutType curLayout = currentLayout ();
+ Opaque addr;
+
+ switch (curLayout)
+ {
+ case SRC_COMMAND:
+ case SRC_DATA_COMMAND:
+ addr = (Opaque) find_line_pc (
+ current_source_symtab,
+ srcWin->detail.sourceInfo.startLineOrAddr.lineNo);
+ break;
+ case DISASSEM_COMMAND:
+ case SRC_DISASSEM_COMMAND:
+ case DISASSEM_DATA_COMMAND:
+ addr = disassemWin->detail.sourceInfo.startLineOrAddr.addr;
+ break;
+ default:
+ addr = (Opaque) NULL;
+ break;
+ }
+
+ return addr;
+} /* _extractDisplayStartAddr */
+
+
+static void
+#ifdef __STDC__
+_tuiHandleXDBLayout (
+ TuiLayoutDefPtr layoutDef)
+#else
+_tuiHandleXDBLayout (layoutDef)
+ TuiLayoutDefPtr layoutDef;
+#endif
+{
+ if (layoutDef->split)
+ {
+ tuiSetLayout (SRC_DISASSEM_COMMAND, TUI_UNDEFINED_REGS);
+ tuiSetWinFocusTo (winList[layoutDef->displayMode]);
+ }
+ else
+ {
+ if (layoutDef->displayMode == SRC_WIN)
+ tuiSetLayout (SRC_COMMAND, TUI_UNDEFINED_REGS);
+ else
+ tuiSetLayout (DISASSEM_DATA_COMMAND, layoutDef->regsDisplayType);
+ }
+
+
+ return;
+} /* _tuiHandleXDBLayout */
+
+
+static void
+#ifdef __STDC__
+_tuiToggleLayout_command (
+ char *arg,
+ int fromTTY)
+#else
+_tuiToggleLayout_command (arg, fromTTY)
+ char *arg;
+ int fromTTY;
+#endif
+{
+ tuiDo ((TuiOpaqueFuncPtr) _tui_vToggleLayout_command, arg, fromTTY);
+}
+
+static void
+#ifdef __STDC__
+_tui_vToggleLayout_command (
+ va_list args)
+#else
+_tui_vToggleLayout_command (args)
+ va_list args;
+#endif
+{
+ TuiLayoutDefPtr layoutDef = tuiLayoutDef ();
+
+ if (layoutDef->displayMode == SRC_WIN)
+ layoutDef->displayMode = DISASSEM_WIN;
+ else
+ layoutDef->displayMode = SRC_WIN;
+
+ if (!layoutDef->split)
+ _tuiHandleXDBLayout (layoutDef);
+
+ return;
+} /* _tuiToggleLayout_command */
+
+
+static void
+#ifdef __STDC__
+_tuiToggleSplitLayout_command (
+ char *arg,
+ int fromTTY)
+#else
+_tuiToggleSplitLayout_command (arg, fromTTY)
+ char *arg;
+ int fromTTY;
+#endif
+{
+ tuiDo ((TuiOpaqueFuncPtr) _tui_vToggleSplitLayout_command, arg, fromTTY);
+}
+
+static void
+#ifdef __STDC__
+_tui_vToggleSplitLayout_command (
+ va_list args)
+#else
+_tui_vToggleSplitLayout_command (args)
+ va_list args;
+#endif
+{
+ TuiLayoutDefPtr layoutDef = tuiLayoutDef ();
+
+ layoutDef->split = (!layoutDef->split);
+ _tuiHandleXDBLayout (layoutDef);
+
+ return;
+} /* _tui_vToggleSplitLayout_command */
+
+
+static void
+#ifdef __STDC__
+_tuiLayout_command (
+ char *arg,
+ int fromTTY)
+#else
+_tuiLayout_command (arg, fromTTY)
+ char *arg;
+ int fromTTY;
+#endif
+{
+ if ((TuiStatus) tuiDo (
+ (TuiOpaqueFuncPtr) tui_vSetLayoutTo, arg) != TUI_SUCCESS)
+ warning ("Invalid layout specified.\n%s" LAYOUT_USAGE);
+
+ return;
+} /* _tuiLayout_command */
+
+/*
+** _nextLayout().
+** Answer the previous layout to cycle to.
+*/
+static TuiLayoutType
+#ifdef __STDC__
+_nextLayout (void)
+#else
+_nextLayout ()
+#endif
+{
+ TuiLayoutType newLayout;
+
+ newLayout = currentLayout ();
+ if (newLayout == UNDEFINED_LAYOUT)
+ newLayout = SRC_COMMAND;
+ else
+ {
+ newLayout++;
+ if (newLayout == UNDEFINED_LAYOUT)
+ newLayout = SRC_COMMAND;
+ }
+
+ return newLayout;
+} /* _nextLayout */
+
+
+/*
+** _prevLayout().
+** Answer the next layout to cycle to.
+*/
+static TuiLayoutType
+#ifdef __STDC__
+_prevLayout (void)
+#else
+_prevLayout ()
+#endif
+{
+ TuiLayoutType newLayout;
+
+ newLayout = currentLayout ();
+ if (newLayout == SRC_COMMAND)
+ newLayout = DISASSEM_DATA_COMMAND;
+ else
+ {
+ newLayout--;
+ if (newLayout == UNDEFINED_LAYOUT)
+ newLayout = DISASSEM_DATA_COMMAND;
+ }
+
+ return newLayout;
+} /* _prevLayout */
+
+
+
+/*
+** _makeCommandWindow().
+*/
+static void
+#ifdef __STDC__
+_makeCommandWindow (
+ TuiWinInfoPtr * winInfoPtr,
+ int height,
+ int originY)
+#else
+_makeCommandWindow (winInfoPtr, height, originY)
+ TuiWinInfoPtr *winInfoPtr;
+ int height;
+ int originY;
+#endif
+{
+ _initAndMakeWin ((Opaque *) winInfoPtr,
+ CMD_WIN,
+ height,
+ termWidth (),
+ 0,
+ originY,
+ DONT_BOX_WINDOW);
+
+ (*winInfoPtr)->canHighlight = FALSE;
+
+ return;
+} /* _makeCommandWindow */
+
+
+/*
+** _makeSourceWindow().
+*/
+static void
+#ifdef __STDC__
+_makeSourceWindow (
+ TuiWinInfoPtr * winInfoPtr,
+ int height,
+ int originY)
+#else
+_makeSourceWindow (winInfoPtr, height, originY)
+ TuiWinInfoPtr *winInfoPtr;
+ int height;
+ int originY;
+#endif
+{
+ _makeSourceOrDisassemWindow (winInfoPtr, SRC_WIN, height, originY);
+
+ return;
+} /* _makeSourceWindow */
+
+
+/*
+** _makeDisassemWindow().
+*/
+static void
+#ifdef __STDC__
+_makeDisassemWindow (
+ TuiWinInfoPtr * winInfoPtr,
+ int height,
+ int originY)
+#else
+_makeDisassemWindow (winInfoPtr, height, originY)
+ TuiWinInfoPtr *winInfoPtr;
+ int height;
+ int originY;
+#endif
+{
+ _makeSourceOrDisassemWindow (winInfoPtr, DISASSEM_WIN, height, originY);
+
+ return;
+} /* _makeDisassemWindow */
+
+
+/*
+** _makeDataWindow().
+*/
+static void
+#ifdef __STDC__
+_makeDataWindow (
+ TuiWinInfoPtr * winInfoPtr,
+ int height,
+ int originY)
+#else
+_makeDataWindow (winInfoPtr, height, originY)
+ TuiWinInfoPtr *winInfoPtr;
+ int height;
+ int originY;
+#endif
+{
+ _initAndMakeWin ((Opaque *) winInfoPtr,
+ DATA_WIN,
+ height,
+ termWidth (),
+ 0,
+ originY,
+ BOX_WINDOW);
+
+ return;
+} /* _makeDataWindow */
+
+
+
+/*
+** _showSourceCommand().
+** Show the Source/Command layout
+*/
+static void
+#ifdef __STDC__
+_showSourceCommand (void)
+#else
+_showSourceCommand ()
+#endif
+{
+ _showSourceOrDisassemAndCommand (SRC_COMMAND);
+
+ return;
+} /* _showSourceCommand */
+
+
+/*
+** _showDisassemCommand().
+** Show the Dissassem/Command layout
+*/
+static void
+#ifdef __STDC__
+_showDisassemCommand (void)
+#else
+_showDisassemCommand ()
+#endif
+{
+ _showSourceOrDisassemAndCommand (DISASSEM_COMMAND);
+
+ return;
+} /* _showDisassemCommand */
+
+
+/*
+** _showSourceDisassemCommand().
+** Show the Source/Disassem/Command layout
+*/
+static void
+#ifdef __STDC__
+_showSourceDisassemCommand (void)
+#else
+_showSourceDisassemCommand ()
+#endif
+{
+ TuiGenWinInfoPtr locator = locatorWinInfoPtr ();
+
+ if (currentLayout () != SRC_DISASSEM_COMMAND)
+ {
+ int cmdHeight, srcHeight, asmHeight;
+
+ if (m_winPtrNotNull (cmdWin))
+ cmdHeight = cmdWin->generic.height;
+ else
+ cmdHeight = termHeight () / 3;
+
+ srcHeight = (termHeight () - cmdHeight) / 2;
+ asmHeight = termHeight () - (srcHeight + cmdHeight);
+
+ if (m_winPtrIsNull (srcWin))
+ _makeSourceWindow (&srcWin, srcHeight, 0);
+ else
+ {
+ _initGenWinInfo (&srcWin->generic,
+ srcWin->generic.type,
+ srcHeight,
+ srcWin->generic.width,
+ srcWin->detail.sourceInfo.executionInfo->width,
+ 0);
+ srcWin->canHighlight = TRUE;
+ _initGenWinInfo (srcWin->detail.sourceInfo.executionInfo,
+ EXEC_INFO_WIN,
+ srcHeight,
+ 3,
+ 0,
+ 0);
+ m_beVisible (srcWin);
+ m_beVisible (srcWin->detail.sourceInfo.executionInfo);
+ srcWin->detail.sourceInfo.hasLocator = FALSE;;
+ }
+ if (m_winPtrNotNull (srcWin))
+ {
+ TuiGenWinInfoPtr locator = locatorWinInfoPtr ();
+
+ tuiShowSourceContent (srcWin);
+ if (m_winPtrIsNull (disassemWin))
+ {
+ _makeDisassemWindow (&disassemWin, asmHeight, srcHeight - 1);
+ _initAndMakeWin ((Opaque *) & locator,
+ LOCATOR_WIN,
+ 2 /* 1 */ ,
+ termWidth (),
+ 0,
+ (srcHeight + asmHeight) - 1,
+ DONT_BOX_WINDOW);
+ }
+ else
+ {
+ _initGenWinInfo (locator,
+ LOCATOR_WIN,
+ 2 /* 1 */ ,
+ termWidth (),
+ 0,
+ (srcHeight + asmHeight) - 1);
+ disassemWin->detail.sourceInfo.hasLocator = TRUE;
+ _initGenWinInfo (
+ &disassemWin->generic,
+ disassemWin->generic.type,
+ asmHeight,
+ disassemWin->generic.width,
+ disassemWin->detail.sourceInfo.executionInfo->width,
+ srcHeight - 1);
+ _initGenWinInfo (disassemWin->detail.sourceInfo.executionInfo,
+ EXEC_INFO_WIN,
+ asmHeight,
+ 3,
+ 0,
+ srcHeight - 1);
+ disassemWin->canHighlight = TRUE;
+ m_beVisible (disassemWin);
+ m_beVisible (disassemWin->detail.sourceInfo.executionInfo);
+ }
+ if (m_winPtrNotNull (disassemWin))
+ {
+ srcWin->detail.sourceInfo.hasLocator = FALSE;
+ disassemWin->detail.sourceInfo.hasLocator = TRUE;
+ m_beVisible (locator);
+ tuiShowLocatorContent ();
+ tuiShowSourceContent (disassemWin);
+
+ if (m_winPtrIsNull (cmdWin))
+ _makeCommandWindow (&cmdWin,
+ cmdHeight,
+ termHeight () - cmdHeight);
+ else
+ {
+ _initGenWinInfo (&cmdWin->generic,
+ cmdWin->generic.type,
+ cmdWin->generic.height,
+ cmdWin->generic.width,
+ 0,
+ cmdWin->generic.origin.y);
+ cmdWin->canHighlight = FALSE;
+ m_beVisible (cmdWin);
+ }
+ if (m_winPtrNotNull (cmdWin))
+ tuiRefreshWin (&cmdWin->generic);
+ }
+ }
+ setCurrentLayoutTo (SRC_DISASSEM_COMMAND);
+ }
+
+ return;
+} /* _showSourceDisassemCommand */
+
+
+/*
+** _showData().
+** Show the Source/Data/Command or the Dissassembly/Data/Command layout
+*/
+static void
+#ifdef __STDC__
+_showData (
+ TuiLayoutType newLayout)
+#else
+_showData (newLayout)
+ TuiLayoutType newLayout;
+#endif
+{
+ int totalHeight = (termHeight () - cmdWin->generic.height);
+ int srcHeight, dataHeight;
+ TuiWinType winType;
+ TuiGenWinInfoPtr locator = locatorWinInfoPtr ();
+
+
+ dataHeight = totalHeight / 2;
+ srcHeight = totalHeight - dataHeight;
+ m_allBeInvisible ();
+ m_beInvisible (locator);
+ _makeDataWindow (&dataWin, dataHeight, 0);
+ dataWin->canHighlight = TRUE;
+ if (newLayout == SRC_DATA_COMMAND)
+ winType = SRC_WIN;
+ else
+ winType = DISASSEM_WIN;
+ if (m_winPtrIsNull (winList[winType]))
+ {
+ if (winType == SRC_WIN)
+ _makeSourceWindow (&winList[winType], srcHeight, dataHeight - 1);
+ else
+ _makeDisassemWindow (&winList[winType], srcHeight, dataHeight - 1);
+ _initAndMakeWin ((Opaque *) & locator,
+ LOCATOR_WIN,
+ 2 /* 1 */ ,
+ termWidth (),
+ 0,
+ totalHeight - 1,
+ DONT_BOX_WINDOW);
+ }
+ else
+ {
+ _initGenWinInfo (&winList[winType]->generic,
+ winList[winType]->generic.type,
+ srcHeight,
+ winList[winType]->generic.width,
+ winList[winType]->detail.sourceInfo.executionInfo->width,
+ dataHeight - 1);
+ _initGenWinInfo (winList[winType]->detail.sourceInfo.executionInfo,
+ EXEC_INFO_WIN,
+ srcHeight,
+ 3,
+ 0,
+ dataHeight - 1);
+ m_beVisible (winList[winType]);
+ m_beVisible (winList[winType]->detail.sourceInfo.executionInfo);
+ _initGenWinInfo (locator,
+ LOCATOR_WIN,
+ 2 /* 1 */ ,
+ termWidth (),
+ 0,
+ totalHeight - 1);
+ }
+ winList[winType]->detail.sourceInfo.hasLocator = TRUE;
+ m_beVisible (locator);
+ tuiShowLocatorContent ();
+ addToSourceWindows (winList[winType]);
+ setCurrentLayoutTo (newLayout);
+
+ return;
+} /* _showData */
+
+/*
+** _initGenWinInfo().
+*/
+static void
+#ifdef __STDC__
+_initGenWinInfo (
+ TuiGenWinInfoPtr winInfo,
+ TuiWinType type,
+ int height,
+ int width,
+ int originX,
+ int originY)
+#else
+_initGenWinInfo (winInfo, type, height, width, originX, originY)
+ TuiGenWinInfoPtr winInfo;
+ TuiWinType type;
+ int height;
+ int width;
+ int originX;
+ int originY;
+#endif
+{
+ int h = height;
+
+ winInfo->type = type;
+ winInfo->width = width;
+ winInfo->height = h;
+ if (h > 1)
+ {
+ winInfo->viewportHeight = h - 1;
+ if (winInfo->type != CMD_WIN)
+ winInfo->viewportHeight--;
+ }
+ else
+ winInfo->viewportHeight = 1;
+ winInfo->origin.x = originX;
+ winInfo->origin.y = originY;
+
+ return;
+} /* _initGenWinInfo */
+
+/*
+** _initAndMakeWin().
+*/
+static void
+#ifdef __STDC__
+_initAndMakeWin (
+ Opaque * winInfoPtr,
+ TuiWinType winType,
+ int height,
+ int width,
+ int originX,
+ int originY,
+ int boxIt)
+#else
+_initAndMakeWin (winInfoPtr, winType, height, width, originX, originY, boxIt)
+ Opaque *winInfoPtr;
+ TuiWinType winType;
+ int height;
+ int width;
+ int originX;
+ int originY;
+ int boxIt;
+#endif
+{
+ Opaque opaqueWinInfo = *winInfoPtr;
+ TuiGenWinInfoPtr generic;
+
+ if (opaqueWinInfo == (Opaque) NULL)
+ {
+ if (m_winIsAuxillary (winType))
+ opaqueWinInfo = (Opaque) allocGenericWinInfo ();
+ else
+ opaqueWinInfo = (Opaque) allocWinInfo (winType);
+ }
+ if (m_winIsAuxillary (winType))
+ generic = (TuiGenWinInfoPtr) opaqueWinInfo;
+ else
+ generic = &((TuiWinInfoPtr) opaqueWinInfo)->generic;
+
+ if (opaqueWinInfo != (Opaque) NULL)
+ {
+ _initGenWinInfo (generic, winType, height, width, originX, originY);
+ if (!m_winIsAuxillary (winType))
+ {
+ if (generic->type == CMD_WIN)
+ ((TuiWinInfoPtr) opaqueWinInfo)->canHighlight = FALSE;
+ else
+ ((TuiWinInfoPtr) opaqueWinInfo)->canHighlight = TRUE;
+ }
+ makeWindow (generic, boxIt);
+ if (winType == LOCATOR_WIN)
+ tuiClearLocatorDisplay ();
+ echo ();
+ }
+ *winInfoPtr = opaqueWinInfo;
+
+ return;
+} /* _initAndMakeWin */
+
+
+/*
+** _makeSourceOrDisassemWindow().
+*/
+static void
+#ifdef __STDC__
+_makeSourceOrDisassemWindow (
+ TuiWinInfoPtr * winInfoPtr,
+ TuiWinType type,
+ int height,
+ int originY)
+#else
+_makeSourceOrDisassemWindow (winInfoPtr, type, height, originY)
+ TuiWinInfoPtr *winInfoPtr;
+ TuiWinType type;
+ int height;
+ int originY;
+#endif
+{
+ TuiGenWinInfoPtr executionInfo = (TuiGenWinInfoPtr) NULL;
+
+ /*
+ ** Create the exeuction info window.
+ */
+ if (type == SRC_WIN)
+ executionInfo = sourceExecInfoWinPtr ();
+ else
+ executionInfo = disassemExecInfoWinPtr ();
+ _initAndMakeWin ((Opaque *) & executionInfo,
+ EXEC_INFO_WIN,
+ height,
+ 3,
+ 0,
+ originY,
+ DONT_BOX_WINDOW);
+ /*
+ ** Now create the source window.
+ */
+ _initAndMakeWin ((Opaque *) winInfoPtr,
+ type,
+ height,
+ termWidth () - executionInfo->width,
+ executionInfo->width,
+ originY,
+ BOX_WINDOW);
+
+ (*winInfoPtr)->detail.sourceInfo.executionInfo = executionInfo;
+
+ return;
+} /* _makeSourceOrDisassemWindow */
+
+
+/*
+** _showSourceOrDisassemAndCommand().
+** Show the Source/Command or the Disassem layout
+*/
+static void
+#ifdef __STDC__
+_showSourceOrDisassemAndCommand (
+ TuiLayoutType layoutType)
+#else
+_showSourceOrDisassemAndCommand (layoutType)
+ TuiLayoutType layoutType;
+#endif
+{
+ if (currentLayout () != layoutType)
+ {
+ TuiWinInfoPtr *winInfoPtr;
+ int areaLeft;
+ int srcHeight, cmdHeight;
+ TuiGenWinInfoPtr locator = locatorWinInfoPtr ();
+
+ if (m_winPtrNotNull (cmdWin))
+ cmdHeight = cmdWin->generic.height;
+ else
+ cmdHeight = termHeight () / 3;
+ srcHeight = termHeight () - cmdHeight;
+
+
+ if (layoutType == SRC_COMMAND)
+ winInfoPtr = &srcWin;
+ else
+ winInfoPtr = &disassemWin;
+
+ if (m_winPtrIsNull (*winInfoPtr))
+ {
+ if (layoutType == SRC_COMMAND)
+ _makeSourceWindow (winInfoPtr, srcHeight - 1, 0);
+ else
+ _makeDisassemWindow (winInfoPtr, srcHeight - 1, 0);
+ _initAndMakeWin ((Opaque *) & locator,
+ LOCATOR_WIN,
+ 2 /* 1 */ ,
+ termWidth (),
+ 0,
+ srcHeight - 1,
+ DONT_BOX_WINDOW);
+ }
+ else
+ {
+ _initGenWinInfo (locator,
+ LOCATOR_WIN,
+ 2 /* 1 */ ,
+ termWidth (),
+ 0,
+ srcHeight - 1);
+ (*winInfoPtr)->detail.sourceInfo.hasLocator = TRUE;
+ _initGenWinInfo (
+ &(*winInfoPtr)->generic,
+ (*winInfoPtr)->generic.type,
+ srcHeight - 1,
+ (*winInfoPtr)->generic.width,
+ (*winInfoPtr)->detail.sourceInfo.executionInfo->width,
+ 0);
+ _initGenWinInfo ((*winInfoPtr)->detail.sourceInfo.executionInfo,
+ EXEC_INFO_WIN,
+ srcHeight - 1,
+ 3,
+ 0,
+ 0);
+ (*winInfoPtr)->canHighlight = TRUE;
+ m_beVisible (*winInfoPtr);
+ m_beVisible ((*winInfoPtr)->detail.sourceInfo.executionInfo);
+ }
+ if (m_winPtrNotNull (*winInfoPtr))
+ {
+ (*winInfoPtr)->detail.sourceInfo.hasLocator = TRUE;
+ m_beVisible (locator);
+ tuiShowLocatorContent ();
+ tuiShowSourceContent (*winInfoPtr);
+
+ if (m_winPtrIsNull (cmdWin))
+ {
+ _makeCommandWindow (&cmdWin, cmdHeight, srcHeight);
+ tuiRefreshWin (&cmdWin->generic);
+ }
+ else
+ {
+ _initGenWinInfo (&cmdWin->generic,
+ cmdWin->generic.type,
+ cmdWin->generic.height,
+ cmdWin->generic.width,
+ cmdWin->generic.origin.x,
+ cmdWin->generic.origin.y);
+ cmdWin->canHighlight = FALSE;
+ m_beVisible (cmdWin);
+ }
+ }
+ setCurrentLayoutTo (layoutType);
+ }
+
+ return;
+} /* _showSourceOrDisassemAndCommand */
diff --git a/gdb/tui/tuiLayout.h b/gdb/tui/tuiLayout.h
new file mode 100644
index 00000000000..57d8bbc90b6
--- /dev/null
+++ b/gdb/tui/tuiLayout.h
@@ -0,0 +1,15 @@
+#ifndef TUI_LAYOUT_H
+#define TUI_LAYOUT_H
+
+extern void showLayout PARAMS ((TuiLayoutType));
+extern void tuiAddWinToLayout PARAMS ((TuiWinType));
+extern void tui_vAddWinToLayout PARAMS ((va_list));
+extern int tuiDefaultWinHeight
+ PARAMS ((TuiWinType, TuiLayoutType));
+extern int tuiDefaultWinViewportHeight
+ PARAMS ((TuiWinType, TuiLayoutType));
+extern TuiStatus tuiSetLayout
+ PARAMS ((TuiLayoutType, TuiRegisterDisplayType));
+extern TuiStatus tui_vSetLayoutTo PARAMS ((va_list));
+
+#endif /*TUI_LAYOUT_H*/
diff --git a/gdb/tui/tuiRegs.c b/gdb/tui/tuiRegs.c
new file mode 100644
index 00000000000..b78b9bc873c
--- /dev/null
+++ b/gdb/tui/tuiRegs.c
@@ -0,0 +1,1210 @@
+
+/*
+** tuiRegs.c
+** This module contains functions to support display of registers
+** in the data window.
+*/
+
+
+#include "defs.h"
+#include "tui.h"
+#include "tuiData.h"
+#include "symtab.h"
+#include "gdbtypes.h"
+#include "gdbcmd.h"
+#include "frame.h"
+#include "inferior.h"
+#include "target.h"
+#include "tuiLayout.h"
+#include "tuiWin.h"
+
+
+/*****************************************
+** LOCAL DEFINITIONS **
+******************************************/
+#define DOUBLE_FLOAT_LABEL_WIDTH 6
+#define DOUBLE_FLOAT_LABEL_FMT "%6.6s: "
+#define DOUBLE_FLOAT_VALUE_WIDTH 30 /*min of 16 but may be in sci notation */
+
+#define SINGLE_FLOAT_LABEL_WIDTH 6
+#define SINGLE_FLOAT_LABEL_FMT "%6.6s: "
+#define SINGLE_FLOAT_VALUE_WIDTH 25 /* min of 8 but may be in sci notation */
+
+#define SINGLE_LABEL_WIDTH 10
+#define SINGLE_LABEL_FMT "%10.10s: "
+#define SINGLE_VALUE_WIDTH 14/* minimum of 8 but may be in sci notation */
+
+/* In the code HP gave Cygnus, this was actually a function call to a
+ PA-specific function, which was supposed to determine whether the
+ target was a 64-bit or 32-bit processor. However, the 64-bit
+ support wasn't complete, so we didn't merge that in, so we leave
+ this here as a stub. */
+#define IS_64BIT 0
+
+/*****************************************
+** STATIC DATA **
+******************************************/
+
+
+/*****************************************
+** STATIC LOCAL FUNCTIONS FORWARD DECLS **
+******************************************/
+static TuiStatus _tuiSetRegsContent
+ PARAMS ((int, int, struct frame_info *,
+ TuiRegisterDisplayType, int));
+static char *_tuiRegisterName PARAMS ((int));
+static TuiStatus _tuiGetRegisterRawValue
+ PARAMS ((int, char *, struct frame_info *));
+static void _tuiSetRegisterElement
+ PARAMS ((int, struct frame_info *,
+ TuiDataElementPtr, int));
+static void _tuiDisplayRegister
+ PARAMS ((int, TuiGenWinInfoPtr, enum precision_type));
+static void _tuiRegisterFormat
+ PARAMS ((char *, int, int, TuiDataElementPtr,
+ enum precision_type));
+static TuiStatus _tuiSetGeneralRegsContent PARAMS ((int));
+static TuiStatus _tuiSetSpecialRegsContent PARAMS ((int));
+static TuiStatus _tuiSetGeneralAndSpecialRegsContent PARAMS ((int));
+static TuiStatus _tuiSetFloatRegsContent PARAMS ((TuiRegisterDisplayType, int));
+static int _tuiRegValueHasChanged
+ PARAMS ((TuiDataElementPtr, struct frame_info *,
+ char *));
+static void _tuiShowFloat_command PARAMS ((char *, int));
+static void _tuiShowGeneral_command PARAMS ((char *, int));
+static void _tuiShowSpecial_command PARAMS ((char *, int));
+static void _tui_vShowRegisters_commandSupport PARAMS ((va_list));
+static void _tuiToggleFloatRegs_command PARAMS ((char *, int));
+static void _tuiScrollRegsForward_command PARAMS ((char *, int));
+static void _tuiScrollRegsBackward_command PARAMS ((char *, int));
+static void _tui_vShowRegisters_commandSupport PARAMS ((va_list));
+
+
+
+/*****************************************
+** PUBLIC FUNCTIONS **
+******************************************/
+
+/*
+** tuiLastRegsLineNo()
+** Answer the number of the last line in the regs display.
+** If there are no registers (-1) is returned.
+*/
+int
+#ifdef __STDC__
+tuiLastRegsLineNo (void)
+#else
+tuiLastRegsLineNo ()
+#endif
+{
+ register int numLines = (-1);
+
+ if (dataWin->detail.dataDisplayInfo.regsContentCount > 0)
+ {
+ numLines = (dataWin->detail.dataDisplayInfo.regsContentCount /
+ dataWin->detail.dataDisplayInfo.regsColumnCount);
+ if (dataWin->detail.dataDisplayInfo.regsContentCount %
+ dataWin->detail.dataDisplayInfo.regsColumnCount)
+ numLines++;
+ }
+ return numLines;
+} /* tuiLastRegsLineNo */
+
+
+/*
+** tuiLineFromRegElementNo()
+** Answer the line number that the register element at elementNo is
+** on. If elementNo is greater than the number of register elements
+** there are, -1 is returned.
+*/
+int
+#ifdef __STDC__
+tuiLineFromRegElementNo (
+ int elementNo)
+#else
+tuiLineFromRegElementNo (elementNo)
+ int elementNo;
+#endif
+{
+ if (elementNo < dataWin->detail.dataDisplayInfo.regsContentCount)
+ {
+ int i, line = (-1);
+
+ i = 1;
+ while (line == (-1))
+ {
+ if (elementNo <
+ (dataWin->detail.dataDisplayInfo.regsColumnCount * i))
+ line = i - 1;
+ else
+ i++;
+ }
+
+ return line;
+ }
+ else
+ return (-1);
+} /* tuiLineFromRegElementNo */
+
+
+/*
+** tuiFirstRegElementNoInLine()
+** Answer the index of the first element in lineNo. If lineNo is
+** past the register area (-1) is returned.
+*/
+int
+#ifdef __STDC__
+tuiFirstRegElementNoInLine (
+ int lineNo)
+#else
+tuiFirstRegElementNoInLine (lineNo)
+ int lineNo;
+#endif
+{
+ if ((lineNo * dataWin->detail.dataDisplayInfo.regsColumnCount)
+ <= dataWin->detail.dataDisplayInfo.regsContentCount)
+ return ((lineNo + 1) *
+ dataWin->detail.dataDisplayInfo.regsColumnCount) -
+ dataWin->detail.dataDisplayInfo.regsColumnCount;
+ else
+ return (-1);
+} /* tuiFirstRegElementNoInLine */
+
+
+/*
+** tuiLastRegElementNoInLine()
+** Answer the index of the last element in lineNo. If lineNo is past
+** the register area (-1) is returned.
+*/
+int
+#ifdef __STDC__
+tuiLastRegElementNoInLine (
+ int lineNo)
+#else
+tuiLastRegElementNoInLine (lineNo)
+ int lineNo;
+#endif
+{
+ if ((lineNo * dataWin->detail.dataDisplayInfo.regsColumnCount) <=
+ dataWin->detail.dataDisplayInfo.regsContentCount)
+ return ((lineNo + 1) *
+ dataWin->detail.dataDisplayInfo.regsColumnCount) - 1;
+ else
+ return (-1);
+} /* tuiLastRegElementNoInLine */
+
+
+/*
+** tuiCalculateRegsColumnCount
+** Calculate the number of columns that should be used to display
+** the registers.
+*/
+int
+#ifdef __STDC__
+tuiCalculateRegsColumnCount (
+ TuiRegisterDisplayType dpyType)
+#else
+tuiCalculateRegsColumnCount (dpyType)
+ TuiRegisterDisplayType dpyType;
+#endif
+{
+ int colCount, colWidth;
+
+ if (IS_64BIT || dpyType == TUI_DFLOAT_REGS)
+ colWidth = DOUBLE_FLOAT_VALUE_WIDTH + DOUBLE_FLOAT_LABEL_WIDTH;
+ else
+ {
+ if (dpyType == TUI_SFLOAT_REGS)
+ colWidth = SINGLE_FLOAT_VALUE_WIDTH + SINGLE_FLOAT_LABEL_WIDTH;
+ else
+ colWidth = SINGLE_VALUE_WIDTH + SINGLE_LABEL_WIDTH;
+ }
+ colCount = (dataWin->generic.width - 2) / colWidth;
+
+ return colCount;
+} /* tuiCalulateRegsColumnCount */
+
+
+/*
+** tuiShowRegisters().
+** Show the registers int the data window as indicated by dpyType.
+** If there is any other registers being displayed, then they are
+** cleared. What registers are displayed is dependent upon dpyType.
+*/
+void
+#ifdef __STDC__
+tuiShowRegisters (
+ TuiRegisterDisplayType dpyType)
+#else
+tuiShowRegisters (dpyType)
+ TuiRegisterDisplayType dpyType;
+#endif
+{
+ TuiStatus ret = TUI_FAILURE;
+ int refreshValuesOnly = FALSE;
+
+ /* Say that registers should be displayed, even if there is a problem */
+ dataWin->detail.dataDisplayInfo.displayRegs = TRUE;
+
+ if (target_has_registers)
+ {
+ refreshValuesOnly =
+ (dpyType == dataWin->detail.dataDisplayInfo.regsDisplayType);
+ switch (dpyType)
+ {
+ case TUI_GENERAL_REGS:
+ ret = _tuiSetGeneralRegsContent (refreshValuesOnly);
+ break;
+ case TUI_SFLOAT_REGS:
+ case TUI_DFLOAT_REGS:
+ ret = _tuiSetFloatRegsContent (dpyType, refreshValuesOnly);
+ break;
+
+/* could ifdef out */
+
+ case TUI_SPECIAL_REGS:
+ ret = _tuiSetSpecialRegsContent (refreshValuesOnly);
+ break;
+ case TUI_GENERAL_AND_SPECIAL_REGS:
+ ret = _tuiSetGeneralAndSpecialRegsContent (refreshValuesOnly);
+ break;
+
+/* end of potential if def */
+
+ default:
+ break;
+ }
+ }
+ if (ret == TUI_FAILURE)
+ {
+ dataWin->detail.dataDisplayInfo.regsDisplayType = TUI_UNDEFINED_REGS;
+ tuiEraseDataContent (NO_REGS_STRING);
+ }
+ else
+ {
+ int i;
+
+ /* Clear all notation of changed values */
+ for (i = 0; (i < dataWin->detail.dataDisplayInfo.regsContentCount); i++)
+ {
+ TuiGenWinInfoPtr dataItemWin;
+
+ dataItemWin = &dataWin->detail.dataDisplayInfo.
+ regsContent[i]->whichElement.dataWindow;
+ (&((TuiWinElementPtr)
+ dataItemWin->content[0])->whichElement.data)->highlight = FALSE;
+ }
+ dataWin->detail.dataDisplayInfo.regsDisplayType = dpyType;
+ tuiDisplayAllData ();
+ }
+ (tuiLayoutDef ())->regsDisplayType = dpyType;
+
+ return;
+} /* tuiShowRegisters */
+
+
+/*
+** tuiDisplayRegistersFrom().
+** Function to display the registers in the content from
+** 'startElementNo' until the end of the register content or the
+** end of the display height. No checking for displaying past
+** the end of the registers is done here.
+*/
+void
+#ifdef __STDC__
+tuiDisplayRegistersFrom (
+ int startElementNo)
+#else
+tuiDisplayRegistersFrom (startElementNo)
+ int startElementNo;
+#endif
+{
+ if (dataWin->detail.dataDisplayInfo.regsContent != (TuiWinContent) NULL &&
+ dataWin->detail.dataDisplayInfo.regsContentCount > 0)
+ {
+ register int i = startElementNo;
+ int j, valueCharsWide, charsWide, itemWinWidth, curY, labelWidth;
+ enum precision_type precision;
+
+ precision = (dataWin->detail.dataDisplayInfo.regsDisplayType
+ == TUI_DFLOAT_REGS) ?
+ double_precision : unspecified_precision;
+ if (IS_64BIT ||
+ dataWin->detail.dataDisplayInfo.regsDisplayType == TUI_DFLOAT_REGS)
+ {
+ valueCharsWide = DOUBLE_FLOAT_VALUE_WIDTH;
+ labelWidth = DOUBLE_FLOAT_LABEL_WIDTH;
+ }
+ else
+ {
+ if (dataWin->detail.dataDisplayInfo.regsDisplayType ==
+ TUI_SFLOAT_REGS)
+ {
+ valueCharsWide = SINGLE_FLOAT_VALUE_WIDTH;
+ labelWidth = SINGLE_FLOAT_LABEL_WIDTH;
+ }
+ else
+ {
+ valueCharsWide = SINGLE_VALUE_WIDTH;
+ labelWidth = SINGLE_LABEL_WIDTH;
+ }
+ }
+ itemWinWidth = valueCharsWide + labelWidth;
+ /*
+ ** Now create each data "sub" window, and write the display into it.
+ */
+ curY = 1;
+ while (i < dataWin->detail.dataDisplayInfo.regsContentCount &&
+ curY <= dataWin->generic.viewportHeight)
+ {
+ for (j = 0;
+ (j < dataWin->detail.dataDisplayInfo.regsColumnCount &&
+ i < dataWin->detail.dataDisplayInfo.regsContentCount); j++)
+ {
+ TuiGenWinInfoPtr dataItemWin;
+ TuiDataElementPtr dataElementPtr;
+
+ /* create the window if necessary*/
+ dataItemWin = &dataWin->detail.dataDisplayInfo.
+ regsContent[i]->whichElement.dataWindow;
+ dataElementPtr = &((TuiWinElementPtr)
+ dataItemWin->content[0])->whichElement.data;
+ if (dataItemWin->handle == (WINDOW *) NULL)
+ {
+ dataItemWin->height = 1;
+ dataItemWin->width = (precision == double_precision) ?
+ itemWinWidth + 2 : itemWinWidth + 1;
+ dataItemWin->origin.x = (itemWinWidth * j) + 1;
+ dataItemWin->origin.y = curY;
+ makeWindow (dataItemWin, DONT_BOX_WINDOW);
+ }
+ /*
+ ** Get the printable representation of the register
+ ** and display it
+ */
+ _tuiDisplayRegister (
+ dataElementPtr->itemNo, dataItemWin, precision);
+ i++; /* next register */
+ }
+ curY++; /* next row; */
+ }
+ }
+
+ return;
+} /* tuiDisplayRegistersFrom */
+
+
+/*
+** tuiDisplayRegElementAtLine().
+** Function to display the registers in the content from
+** 'startElementNo' on 'startLineNo' until the end of the
+** register content or the end of the display height.
+** This function checks that we won't display off the end
+** of the register display.
+*/
+void
+#ifdef __STDC__
+tuiDisplayRegElementAtLine (
+ int startElementNo,
+ int startLineNo)
+#else
+tuiDisplayRegElementAtLine (startElementNo, startLineNo)
+ int startElementNo;
+ int startLineNo;
+#endif
+{
+ if (dataWin->detail.dataDisplayInfo.regsContent != (TuiWinContent) NULL &&
+ dataWin->detail.dataDisplayInfo.regsContentCount > 0)
+ {
+ register int elementNo = startElementNo;
+
+ if (startElementNo != 0 && startLineNo != 0)
+ {
+ register int lastLineNo, firstLineOnLastPage;
+
+ lastLineNo = tuiLastRegsLineNo ();
+ firstLineOnLastPage = lastLineNo - (dataWin->generic.height - 2);
+ if (firstLineOnLastPage < 0)
+ firstLineOnLastPage = 0;
+ /*
+ ** If there is no other data displayed except registers,
+ ** and the elementNo causes us to scroll past the end of the
+ ** registers, adjust what element to really start the display at.
+ */
+ if (dataWin->detail.dataDisplayInfo.dataContentCount <= 0 &&
+ startLineNo > firstLineOnLastPage)
+ elementNo = tuiFirstRegElementNoInLine (firstLineOnLastPage);
+ }
+ tuiDisplayRegistersFrom (elementNo);
+ }
+
+ return;
+} /* tuiDisplayRegElementAtLine */
+
+
+
+/*
+** tuiDisplayRegistersFromLine().
+** Function to display the registers starting at line lineNo in
+** the data window. Answers the line number that the display
+** actually started from. If nothing is displayed (-1) is returned.
+*/
+int
+#ifdef __STDC__
+tuiDisplayRegistersFromLine (
+ int lineNo,
+ int forceDisplay)
+#else
+tuiDisplayRegistersFromLine (lineNo, forceDisplay)
+ int lineNo;
+ int forceDisplay;
+#endif
+{
+ int elementNo;
+
+ if (dataWin->detail.dataDisplayInfo.regsContentCount > 0)
+ {
+ int line, elementNo;
+
+ if (lineNo < 0)
+ line = 0;
+ else if (forceDisplay)
+ { /*
+ ** If we must display regs (forceDisplay is true), then make
+ ** sure that we don't display off the end of the registers.
+ */
+ if (lineNo >= tuiLastRegsLineNo ())
+ {
+ if ((line = tuiLineFromRegElementNo (
+ dataWin->detail.dataDisplayInfo.regsContentCount - 1)) < 0)
+ line = 0;
+ }
+ else
+ line = lineNo;
+ }
+ else
+ line = lineNo;
+
+ elementNo = tuiFirstRegElementNoInLine (line);
+ if (elementNo < dataWin->detail.dataDisplayInfo.regsContentCount)
+ tuiDisplayRegElementAtLine (elementNo, line);
+ else
+ line = (-1);
+
+ return line;
+ }
+
+ return (-1); /* nothing was displayed */
+} /* tuiDisplayRegistersFromLine */
+
+
+/*
+** tuiCheckRegisterValues()
+** This function check all displayed registers for changes in
+** values, given a particular frame. If the values have changed,
+** they are updated with the new value and highlighted.
+*/
+void
+#ifdef __STDC__
+tuiCheckRegisterValues (
+ struct frame_info *frame)
+#else
+tuiCheckRegisterValues (frame)
+ struct frame_info *frame;
+#endif
+{
+ if (m_winPtrNotNull (dataWin) && dataWin->generic.isVisible)
+ {
+ if (dataWin->detail.dataDisplayInfo.regsContentCount <= 0 &&
+ dataWin->detail.dataDisplayInfo.displayRegs)
+ tuiShowRegisters ((tuiLayoutDef ())->regsDisplayType);
+ else
+ {
+ int i, j;
+ char rawBuf[MAX_REGISTER_RAW_SIZE];
+
+ for (i = 0;
+ (i < dataWin->detail.dataDisplayInfo.regsContentCount); i++)
+ {
+ TuiDataElementPtr dataElementPtr;
+ TuiGenWinInfoPtr dataItemWinPtr;
+ int wasHilighted;
+
+ dataItemWinPtr = &dataWin->detail.dataDisplayInfo.
+ regsContent[i]->whichElement.dataWindow;
+ dataElementPtr = &((TuiWinElementPtr)
+ dataItemWinPtr->content[0])->whichElement.data;
+ wasHilighted = dataElementPtr->highlight;
+ dataElementPtr->highlight =
+ _tuiRegValueHasChanged (dataElementPtr, frame, &rawBuf[0]);
+ if (dataElementPtr->highlight)
+ {
+ for (j = 0; j < MAX_REGISTER_RAW_SIZE; j++)
+ ((char *) dataElementPtr->value)[j] = rawBuf[j];
+ _tuiDisplayRegister (
+ dataElementPtr->itemNo,
+ dataItemWinPtr,
+ ((dataWin->detail.dataDisplayInfo.regsDisplayType ==
+ TUI_DFLOAT_REGS) ?
+ double_precision : unspecified_precision));
+ }
+ else if (wasHilighted)
+ {
+ dataElementPtr->highlight = FALSE;
+ _tuiDisplayRegister (
+ dataElementPtr->itemNo,
+ dataItemWinPtr,
+ ((dataWin->detail.dataDisplayInfo.regsDisplayType ==
+ TUI_DFLOAT_REGS) ?
+ double_precision : unspecified_precision));
+ }
+ }
+ }
+ }
+ return;
+} /* tuiCheckRegisterValues */
+
+
+/*
+** tuiToggleFloatRegs().
+*/
+void
+#ifdef __STDC__
+tuiToggleFloatRegs (void)
+#else
+tuiToggleFloatRegs ()
+#endif
+{
+ TuiLayoutDefPtr layoutDef = tuiLayoutDef ();
+
+ if (layoutDef->floatRegsDisplayType == TUI_SFLOAT_REGS)
+ layoutDef->floatRegsDisplayType = TUI_DFLOAT_REGS;
+ else
+ layoutDef->floatRegsDisplayType = TUI_SFLOAT_REGS;
+
+ if (m_winPtrNotNull (dataWin) && dataWin->generic.isVisible &&
+ (dataWin->detail.dataDisplayInfo.regsDisplayType == TUI_SFLOAT_REGS ||
+ dataWin->detail.dataDisplayInfo.regsDisplayType == TUI_DFLOAT_REGS))
+ tuiShowRegisters (layoutDef->floatRegsDisplayType);
+
+ return;
+} /* tuiToggleFloatRegs */
+
+
+void
+_initialize_tuiRegs ()
+{
+ if (tui_version && xdb_commands)
+ {
+ add_com ("fr", class_tui, _tuiShowFloat_command,
+ "Display only floating point registers\n");
+ add_com ("gr", class_tui, _tuiShowGeneral_command,
+ "Display only general registers\n");
+ add_com ("sr", class_tui, _tuiShowSpecial_command,
+ "Display only special registers\n");
+ add_com ("+r", class_tui, _tuiScrollRegsForward_command,
+ "Scroll the registers window forward\n");
+ add_com ("-r", class_tui, _tuiScrollRegsBackward_command,
+ "Scroll the register window backward\n");
+ add_com ("tf", class_tui, _tuiToggleFloatRegs_command,
+ "Toggle between single and double precision floating point registers.\n");
+ add_cmd (TUI_FLOAT_REGS_NAME_LOWER,
+ class_tui,
+ _tuiToggleFloatRegs_command,
+ "Toggle between single and double precision floating point \
+registers.\n",
+ &togglelist);
+ }
+
+ return;
+} /* _initialize_tuiRegs */
+
+
+/*****************************************
+** STATIC LOCAL FUNCTIONS **
+******************************************/
+
+
+/*
+** _tuiRegisterName().
+** Return the register name.
+*/
+static char *
+#ifdef __STDC__
+_tuiRegisterName (
+ int regNum)
+#else
+_tuiRegisterName (regNum)
+ int regNum;
+#endif
+{
+ if (reg_names[regNum] != (char *) NULL && *(reg_names[regNum]) != (char) 0)
+ return reg_names[regNum];
+ else
+ return ((char *) NULL);
+} /* tuiGetRegisterName */
+
+
+/*
+** _tuiRegisterFormat
+** Function to format the register name and value into a buffer,
+** suitable for printing or display
+*/
+static void
+#ifdef __STDC__
+_tuiRegisterFormat (
+ char *buf,
+ int bufLen,
+ int regNum,
+ TuiDataElementPtr dataElement,
+ enum precision_type precision)
+#else
+_tuiRegisterFormat (buf, bufLen, regNum, dataElement, precision)
+ char *buf;
+ int bufLen;
+ int regNum;
+ TuiDataElementPtr dataElement;
+ enum precision_type precision;
+#endif
+{
+ char tmpBuf[15];
+ char *fmt;
+ GDB_FILE *stream;
+
+ stream = gdb_file_init_astring(bufLen);
+ pa_do_strcat_registers_info (regNum, 0, stream, precision);
+ strcpy (buf, gdb_file_get_strbuf(stream));
+ gdb_file_deallocate(&stream);
+
+ return;
+} /* _tuiRegisterFormat */
+
+
+#define NUM_GENERAL_REGS 32
+/*
+** _tuiSetGeneralRegsContent().
+** Set the content of the data window to consist of the general registers.
+*/
+static TuiStatus
+#ifdef __STDC__
+_tuiSetGeneralRegsContent (
+ int refreshValuesOnly)
+#else
+_tuiSetGeneralRegsContent (refreshValuesOnly)
+ int refreshValuesOnly;
+#endif
+{
+ return (_tuiSetRegsContent (0,
+ NUM_GENERAL_REGS - 1,
+ selected_frame,
+ TUI_GENERAL_REGS,
+ refreshValuesOnly));
+
+} /* _tuiSetGeneralRegsContent */
+
+
+#define START_SPECIAL_REGS PCOQ_HEAD_REGNUM
+/*
+** _tuiSetSpecialRegsContent().
+** Set the content of the data window to consist of the special registers.
+*/
+static TuiStatus
+#ifdef __STDC__
+_tuiSetSpecialRegsContent (
+ int refreshValuesOnly)
+#else
+_tuiSetSpecialRegsContent (refreshValuesOnly)
+ int refreshValuesOnly;
+#endif
+{
+ TuiStatus ret = TUI_FAILURE;
+ int i, endRegNum;
+
+ endRegNum = FP0_REGNUM - 1;
+#if 0
+ endRegNum = (-1);
+ for (i = START_SPECIAL_REGS; (i < ARCH_NUM_REGS && endRegNum < 0); i++)
+ if (TYPE_CODE (REGISTER_VIRTUAL_TYPE (i)) == TYPE_CODE_FLT)
+ endRegNum = i - 1;
+#endif
+ ret = _tuiSetRegsContent (START_SPECIAL_REGS,
+ endRegNum,
+ selected_frame,
+ TUI_SPECIAL_REGS,
+ refreshValuesOnly);
+
+ return ret;
+} /* _tuiSetSpecialRegsContent */
+
+
+/*
+** _tuiSetGeneralAndSpecialRegsContent().
+** Set the content of the data window to consist of the special registers.
+*/
+static TuiStatus
+#ifdef __STDC__
+_tuiSetGeneralAndSpecialRegsContent (
+ int refreshValuesOnly)
+#else
+_tuiSetGeneralAndSpecialRegsContent (refreshValuesOnly)
+ int refreshValuesOnly;
+#endif
+{
+ TuiStatus ret = TUI_FAILURE;
+ int i, endRegNum = (-1);
+
+ endRegNum = FP0_REGNUM - 1;
+#if 0
+ endRegNum = (-1);
+ for (i = 0; (i < ARCH_NUM_REGS && endRegNum < 0); i++)
+ if (TYPE_CODE (REGISTER_VIRTUAL_TYPE (i)) == TYPE_CODE_FLT)
+ endRegNum = i - 1;
+#endif
+ ret = _tuiSetRegsContent (
+ 0, endRegNum, selected_frame, TUI_SPECIAL_REGS, refreshValuesOnly);
+
+ return ret;
+} /* _tuiSetGeneralAndSpecialRegsContent */
+
+/*
+** _tuiSetFloatRegsContent().
+** Set the content of the data window to consist of the float registers.
+*/
+static TuiStatus
+#ifdef __STDC__
+_tuiSetFloatRegsContent (
+ TuiRegisterDisplayType dpyType,
+ int refreshValuesOnly)
+#else
+_tuiSetFloatRegsContent (dpyType, refreshValuesOnly)
+ TuiRegisterDisplayType dpyType;
+ int refreshValuesOnly;
+#endif
+{
+ TuiStatus ret = TUI_FAILURE;
+ int i, startRegNum;
+
+ startRegNum = FP0_REGNUM;
+#if 0
+ startRegNum = (-1);
+ for (i = ARCH_NUM_REGS - 1; (i >= 0 && startRegNum < 0); i--)
+ if (TYPE_CODE (REGISTER_VIRTUAL_TYPE (i)) != TYPE_CODE_FLT)
+ startRegNum = i + 1;
+#endif
+ ret = _tuiSetRegsContent (startRegNum,
+ ARCH_NUM_REGS - 1,
+ selected_frame,
+ dpyType,
+ refreshValuesOnly);
+
+ return ret;
+} /* _tuiSetFloatRegsContent */
+
+
+/*
+** _tuiRegValueHasChanged().
+** Answer TRUE if the register's value has changed, FALSE otherwise.
+** If TRUE, newValue is filled in with the new value.
+*/
+static int
+#ifdef __STDC__
+_tuiRegValueHasChanged (
+ TuiDataElementPtr dataElement,
+ struct frame_info *frame,
+ char *newValue)
+#else
+_tuiRegValueHasChanged (dataElement, frame, newValue)
+ TuiDataElementPtr dataElement;
+ struct frame_info *frame;
+ char *newValue;
+#endif
+{
+ int hasChanged = FALSE;
+
+ if (dataElement->itemNo != UNDEFINED_ITEM &&
+ _tuiRegisterName (dataElement->itemNo) != (char *) NULL)
+ {
+ char rawBuf[MAX_REGISTER_RAW_SIZE];
+ int i;
+
+ if (_tuiGetRegisterRawValue (
+ dataElement->itemNo, rawBuf, frame) == TUI_SUCCESS)
+ {
+ for (i = 0; (i < MAX_REGISTER_RAW_SIZE && !hasChanged); i++)
+ hasChanged = (((char *) dataElement->value)[i] != rawBuf[i]);
+ if (hasChanged && newValue != (char *) NULL)
+ {
+ for (i = 0; (i < MAX_REGISTER_RAW_SIZE); i++)
+ newValue[i] = rawBuf[i];
+ }
+ }
+ }
+ return hasChanged;
+} /* _tuiRegValueHasChanged */
+
+
+
+/*
+** _tuiGetRegisterRawValue().
+** Get the register raw value. The raw value is returned in regValue.
+*/
+static TuiStatus
+#ifdef __STDC__
+_tuiGetRegisterRawValue (
+ int regNum,
+ char *regValue,
+ struct frame_info *frame)
+#else
+_tuiGetRegisterRawValue (regNum, regValue, frame)
+ int regNum;
+ char *regValue;
+ struct frame_info *frame;
+#endif
+{
+ TuiStatus ret = TUI_FAILURE;
+
+ if (target_has_registers)
+ {
+ read_relative_register_raw_bytes_for_frame (regNum, regValue, frame);
+ ret = TUI_SUCCESS;
+ }
+
+ return ret;
+} /* _tuiGetRegisterRawValue */
+
+
+
+/*
+** _tuiSetRegisterElement().
+** Function to initialize a data element with the input and
+** the register value.
+*/
+static void
+#ifdef __STDC__
+_tuiSetRegisterElement (
+ int regNum,
+ struct frame_info *frame,
+ TuiDataElementPtr dataElement,
+ int refreshValueOnly)
+#else
+_tuiSetRegisterElement (regNum, frame, dataElement, refreshValueOnly)
+ int regNum;
+ struct frame_info *frame;
+ TuiDataElementPtr dataElement;
+ int refreshValueOnly;
+#endif
+{
+ if (dataElement != (TuiDataElementPtr) NULL)
+ {
+ if (!refreshValueOnly)
+ {
+ dataElement->itemNo = regNum;
+ dataElement->name = _tuiRegisterName (regNum);
+ dataElement->highlight = FALSE;
+ }
+ if (dataElement->value == (Opaque) NULL)
+ dataElement->value = (Opaque) xmalloc (MAX_REGISTER_RAW_SIZE);
+ if (dataElement->value != (Opaque) NULL)
+ _tuiGetRegisterRawValue (regNum, dataElement->value, frame);
+ }
+
+ return;
+} /* _tuiSetRegisterElement */
+
+
+/*
+** _tuiSetRegsContent().
+** Set the content of the data window to consist of the registers
+** numbered from startRegNum to endRegNum. Note that if
+** refreshValuesOnly is TRUE, startRegNum and endRegNum are ignored.
+*/
+static TuiStatus
+#ifdef __STDC__
+_tuiSetRegsContent (
+ int startRegNum,
+ int endRegNum,
+ struct frame_info *frame,
+ TuiRegisterDisplayType dpyType,
+ int refreshValuesOnly)
+#else
+_tuiSetRegsContent (startRegNum, endRegNum, frame, dpyType, refreshValuesOnly)
+ int startRegNum;
+ int endRegNum;
+ struct frame_info *frame;
+ TuiRegisterDisplayType dpyType;
+ int refreshValuesOnly;
+#endif
+{
+ TuiStatus ret = TUI_FAILURE;
+ int numRegs = endRegNum - startRegNum + 1;
+ int allocatedHere = FALSE;
+
+ if (dataWin->detail.dataDisplayInfo.regsContentCount > 0 &&
+ !refreshValuesOnly)
+ {
+ freeDataContent (dataWin->detail.dataDisplayInfo.regsContent,
+ dataWin->detail.dataDisplayInfo.regsContentCount);
+ dataWin->detail.dataDisplayInfo.regsContentCount = 0;
+ }
+ if (dataWin->detail.dataDisplayInfo.regsContentCount <= 0)
+ {
+ dataWin->detail.dataDisplayInfo.regsContent =
+ allocContent (numRegs, DATA_WIN);
+ allocatedHere = TRUE;
+ }
+
+ if (dataWin->detail.dataDisplayInfo.regsContent != (TuiWinContent) NULL)
+ {
+ int i;
+
+ if (!refreshValuesOnly || allocatedHere)
+ {
+ dataWin->generic.content = (OpaquePtr) NULL;
+ dataWin->generic.contentSize = 0;
+ addContentElements (&dataWin->generic, numRegs);
+ dataWin->detail.dataDisplayInfo.regsContent =
+ (TuiWinContent) dataWin->generic.content;
+ dataWin->detail.dataDisplayInfo.regsContentCount = numRegs;
+ }
+ /*
+ ** Now set the register names and values
+ */
+ for (i = startRegNum; (i <= endRegNum); i++)
+ {
+ TuiGenWinInfoPtr dataItemWin;
+
+ dataItemWin = &dataWin->detail.dataDisplayInfo.
+ regsContent[i - startRegNum]->whichElement.dataWindow;
+ _tuiSetRegisterElement (
+ i,
+ frame,
+ &((TuiWinElementPtr) dataItemWin->content[0])->whichElement.data,
+ !allocatedHere && refreshValuesOnly);
+ }
+ dataWin->detail.dataDisplayInfo.regsColumnCount =
+ tuiCalculateRegsColumnCount (dpyType);
+#ifdef LATER
+ if (dataWin->detail.dataDisplayInfo.dataContentCount > 0)
+ {
+ /* delete all the windows? */
+ /* realloc content equal to dataContentCount + regsContentCount */
+ /* append dataWin->detail.dataDisplayInfo.dataContent to content */
+ }
+#endif
+ dataWin->generic.contentSize =
+ dataWin->detail.dataDisplayInfo.regsContentCount +
+ dataWin->detail.dataDisplayInfo.dataContentCount;
+ ret = TUI_SUCCESS;
+ }
+
+ return ret;
+} /* _tuiSetRegsContent */
+
+
+/*
+** _tuiDisplayRegister().
+** Function to display a register in a window. If hilite is TRUE,
+** than the value will be displayed in reverse video
+*/
+static void
+#ifdef __STDC__
+_tuiDisplayRegister (
+ int regNum,
+ TuiGenWinInfoPtr winInfo, /* the data item window */
+ enum precision_type precision)
+#else
+_tuiDisplayRegister (regNum, winInfo, precision)
+ int regNum;
+ TuiGenWinInfoPtr winInfo; /* the data item window */
+ enum precision_type precision;
+#endif
+{
+ if (winInfo->handle != (WINDOW *) NULL)
+ {
+ char buf[100];
+ int valueCharsWide, labelWidth;
+ TuiDataElementPtr dataElementPtr = &((TuiWinContent)
+ winInfo->content)[0]->whichElement.data;
+
+ if (IS_64BIT ||
+ dataWin->detail.dataDisplayInfo.regsDisplayType == TUI_DFLOAT_REGS)
+ {
+ valueCharsWide = DOUBLE_FLOAT_VALUE_WIDTH;
+ labelWidth = DOUBLE_FLOAT_LABEL_WIDTH;
+ }
+ else
+ {
+ if (dataWin->detail.dataDisplayInfo.regsDisplayType ==
+ TUI_SFLOAT_REGS)
+ {
+ valueCharsWide = SINGLE_FLOAT_VALUE_WIDTH;
+ labelWidth = SINGLE_FLOAT_LABEL_WIDTH;
+ }
+ else
+ {
+ valueCharsWide = SINGLE_VALUE_WIDTH;
+ labelWidth = SINGLE_LABEL_WIDTH;
+ }
+ }
+
+ buf[0] = (char) 0;
+ _tuiRegisterFormat (buf,
+ valueCharsWide + labelWidth,
+ regNum,
+ dataElementPtr,
+ precision);
+ if (dataElementPtr->highlight)
+ wstandout (winInfo->handle);
+
+ werase (winInfo->handle);
+ wmove (winInfo->handle, 0, 0);
+ waddstr (winInfo->handle, buf);
+
+ if (dataElementPtr->highlight)
+ wstandend (winInfo->handle);
+ tuiRefreshWin (winInfo);
+ }
+ return;
+} /* _tuiDisplayRegister */
+
+
+static void
+#ifdef __STDC__
+_tui_vShowRegisters_commandSupport (
+ va_list args)
+#else
+_tui_vShowRegisters_commandSupport (args)
+ va_list args;
+#endif
+{
+ TuiRegisterDisplayType dpyType = va_arg (args, TuiRegisterDisplayType);
+
+ if (m_winPtrNotNull (dataWin) && dataWin->generic.isVisible)
+ { /* Data window already displayed, show the registers */
+ if (dataWin->detail.dataDisplayInfo.regsDisplayType != dpyType)
+ tuiShowRegisters (dpyType);
+ }
+ else
+ (tuiLayoutDef ())->regsDisplayType = dpyType;
+
+ return;
+} /* _tui_vShowRegisters_commandSupport */
+
+
+static void
+#ifdef __STDC__
+_tuiShowFloat_command (
+ char *arg,
+ int fromTTY)
+#else
+_tuiShowFloat_command (arg, fromTTY)
+ char *arg;
+ int fromTTY;
+#endif
+{
+ if (m_winPtrIsNull (dataWin) || !dataWin->generic.isVisible ||
+ (dataWin->detail.dataDisplayInfo.regsDisplayType != TUI_SFLOAT_REGS &&
+ dataWin->detail.dataDisplayInfo.regsDisplayType != TUI_DFLOAT_REGS))
+ tuiDo ((TuiOpaqueFuncPtr) _tui_vShowRegisters_commandSupport,
+ (tuiLayoutDef ())->floatRegsDisplayType);
+
+ return;
+} /* _tuiShowFloat_command */
+
+
+static void
+#ifdef __STDC__
+_tuiShowGeneral_command (
+ char *arg,
+ int fromTTY)
+#else
+_tuiShowGeneral_command (arg, fromTTY)
+ char *arg;
+ int fromTTY;
+#endif
+{
+ tuiDo ((TuiOpaqueFuncPtr) _tui_vShowRegisters_commandSupport,
+ TUI_GENERAL_REGS);
+
+ return;
+} /* _tuiShowGeneral_command */
+
+
+static void
+#ifdef __STDC__
+_tuiShowSpecial_command (
+ char *arg,
+ int fromTTY)
+#else
+_tuiShowSpecial_command (arg, fromTTY)
+ char *arg;
+ int fromTTY;
+#endif
+{
+ tuiDo ((TuiOpaqueFuncPtr) _tui_vShowRegisters_commandSupport,
+ TUI_SPECIAL_REGS);
+
+ return;
+} /* _tuiShowSpecial_command */
+
+
+static void
+#ifdef __STDC__
+_tuiToggleFloatRegs_command (
+ char *arg,
+ int fromTTY)
+#else
+_tuiToggleFloatRegs_command (arg, fromTTY)
+ char *arg;
+ int fromTTY;
+#endif
+{
+ if (m_winPtrNotNull (dataWin) && dataWin->generic.isVisible)
+ tuiDo ((TuiOpaqueFuncPtr) tuiToggleFloatRegs);
+ else
+ {
+ TuiLayoutDefPtr layoutDef = tuiLayoutDef ();
+
+ if (layoutDef->floatRegsDisplayType == TUI_SFLOAT_REGS)
+ layoutDef->floatRegsDisplayType = TUI_DFLOAT_REGS;
+ else
+ layoutDef->floatRegsDisplayType = TUI_SFLOAT_REGS;
+ }
+
+
+ return;
+} /* _tuiToggleFloatRegs_command */
+
+
+static void
+#ifdef __STDC__
+_tuiScrollRegsForward_command (
+ char *arg,
+ int fromTTY)
+#else
+_tuiScrollRegsForward_command (arg, fromTTY)
+ char *arg;
+ int fromTTY;
+#endif
+{
+ tuiDo ((TuiOpaqueFuncPtr) tui_vScroll, FORWARD_SCROLL, dataWin, 1);
+
+ return;
+} /* _tuiScrollRegsForward_command */
+
+
+static void
+#ifdef __STDC__
+_tuiScrollRegsBackward_command (
+ char *arg,
+ int fromTTY)
+#else
+_tuiScrollRegsBackward_command (arg, fromTTY)
+ char *arg;
+ int fromTTY;
+#endif
+{
+ tuiDo ((TuiOpaqueFuncPtr) tui_vScroll, BACKWARD_SCROLL, dataWin, 1);
+
+ return;
+} /* _tuiScrollRegsBackward_command */
diff --git a/gdb/tui/tuiRegs.h b/gdb/tui/tuiRegs.h
new file mode 100644
index 00000000000..4a777ec9a9b
--- /dev/null
+++ b/gdb/tui/tuiRegs.h
@@ -0,0 +1,28 @@
+#ifndef _TUI_REGS_H
+#define _TUI_REGS_H
+/*
+** This header file supports the display of registers in the data window.
+*/
+
+/*****************************************
+** TYPE DEFINITIONS **
+******************************************/
+
+
+
+/*****************************************
+** PUBLIC FUNCTION EXTERNAL DECLS **
+******************************************/
+extern void tuiCheckRegisterValues PARAMS ((struct frame_info *));
+extern void tuiShowRegisters PARAMS ((TuiRegisterDisplayType));
+extern void tuiDisplayRegistersFrom PARAMS ((int));
+extern int tuiDisplayRegistersFromLine PARAMS ((int, int));
+extern int tuiLastRegsLineNo PARAMS ((void));
+extern int tuiFirstRegElementInLine PARAMS ((int));
+extern int tuiLastRegElementInLine PARAMS ((int));
+extern int tuiLineFromRegElementNo PARAMS ((int));
+extern void tuiToggleFloatRegs PARAMS ((void));
+extern int tuiCalculateRegsColumnCount PARAMS ((TuiRegisterDisplayType));
+
+
+#endif /*_TUI_REGS_H*/
diff --git a/gdb/tui/tuiSource.c b/gdb/tui/tuiSource.c
new file mode 100644
index 00000000000..e0259d014b4
--- /dev/null
+++ b/gdb/tui/tuiSource.c
@@ -0,0 +1,465 @@
+/*
+** tuiSource.c
+** This module contains functions for displaying source in the source window
+*/
+
+#include "defs.h"
+#include <ctype.h>
+#include "symtab.h"
+#include "frame.h"
+#include "breakpoint.h"
+
+#include "tui.h"
+#include "tuiData.h"
+#include "tuiStack.h"
+#include "tuiSourceWin.h"
+#include "tuiSource.h"
+
+
+/*****************************************
+** EXTERNAL FUNCTION DECLS **
+******************************************/
+
+extern int open_source_file PARAMS ((struct symtab *));
+extern void find_source_lines PARAMS ((struct symtab *, int));
+
+/*****************************************
+** EXTERNAL DATA DECLS **
+******************************************/
+extern int current_source_line;
+extern struct symtab *current_source_symtab;
+
+
+/*****************************************
+** STATIC LOCAL FUNCTIONS FORWARD DECLS **
+******************************************/
+
+static struct breakpoint *_hasBreak PARAMS ((char *, int));
+
+
+/*****************************************
+** STATIC LOCAL DATA **
+******************************************/
+
+
+/*****************************************
+** PUBLIC FUNCTIONS **
+******************************************/
+
+/*********************************
+** SOURCE/DISASSEM FUNCTIONS **
+*********************************/
+
+/*
+** tuiSetSourceContent().
+** Function to display source in the source window.
+*/
+TuiStatus
+#ifdef __STDC__
+tuiSetSourceContent (
+ struct symtab *s,
+ int lineNo,
+ int noerror)
+#else
+tuiSetSourceContent (s, lineNo, noerror)
+ struct symtab *s;
+ int lineNo;
+ int noerror;
+#endif
+{
+ TuiStatus ret = TUI_FAILURE;
+
+ if (s != (struct symtab *) NULL && s->filename != (char *) NULL)
+ {
+ register FILE *stream;
+ register int i, desc, c, lineWidth, nlines;
+ register char *srcLine;
+
+ if ((ret = tuiAllocSourceBuffer (srcWin)) == TUI_SUCCESS)
+ {
+ lineWidth = srcWin->generic.width - 1;
+ /*
+ ** Take hilite (window border) into account, when calculating
+ ** the number of lines
+ */
+ nlines = (lineNo + (srcWin->generic.height - 2)) - lineNo;
+ desc = open_source_file (s);
+ if (desc < 0)
+ {
+ if (!noerror)
+ {
+ char *name = alloca (strlen (s->filename) + 100);
+ sprintf (name, "%s:%d", s->filename, lineNo);
+ print_sys_errmsg (name, errno);
+ }
+ ret = TUI_FAILURE;
+ }
+ else
+ {
+ if (s->line_charpos == 0)
+ find_source_lines (s, desc);
+
+ if (lineNo < 1 || lineNo > s->nlines)
+ {
+ close (desc);
+ printf_unfiltered (
+ "Line number %d out of range; %s has %d lines.\n",
+ lineNo, s->filename, s->nlines);
+ }
+ else if (lseek (desc, s->line_charpos[lineNo - 1], 0) < 0)
+ {
+ close (desc);
+ perror_with_name (s->filename);
+ }
+ else
+ {
+ register int offset, curLineNo, curLine, curLen, threshold;
+ TuiGenWinInfoPtr locator = locatorWinInfoPtr ();
+ /*
+ ** Determine the threshold for the length of the line
+ ** and the offset to start the display
+ */
+ offset = srcWin->detail.sourceInfo.horizontalOffset;
+ threshold = (lineWidth - 1) + offset;
+ stream = fdopen (desc, FOPEN_RT);
+ clearerr (stream);
+ curLine = 0;
+ curLineNo =
+ srcWin->detail.sourceInfo.startLineOrAddr.lineNo = lineNo;
+ if (offset > 0)
+ srcLine = (char *) xmalloc (
+ (threshold + 1) * sizeof (char));
+ while (curLine < nlines)
+ {
+ TuiWinElementPtr element = (TuiWinElementPtr)
+ srcWin->generic.content[curLine];
+ struct breakpoint *bp;
+
+ /* get the first character in the line */
+ c = fgetc (stream);
+
+ if (offset == 0)
+ srcLine = ((TuiWinElementPtr)
+ srcWin->generic.content[
+ curLine])->whichElement.source.line;
+ /* Init the line with the line number */
+ sprintf (srcLine, "%-6d", curLineNo);
+ curLen = strlen (srcLine);
+ i = curLen -
+ ((curLen / tuiDefaultTabLen ()) * tuiDefaultTabLen ());
+ while (i < tuiDefaultTabLen ())
+ {
+ srcLine[curLen] = ' ';
+ i++;
+ curLen++;
+ }
+ srcLine[curLen] = (char) 0;
+
+ /*
+ ** Set whether element is the execution point and
+ ** whether there is a break point on it.
+ */
+ element->whichElement.source.lineOrAddr.lineNo =
+ curLineNo;
+ element->whichElement.source.isExecPoint =
+ (strcmp (((TuiWinElementPtr)
+ locator->content[0])->whichElement.locator.fileName,
+ s->filename) == 0
+ && curLineNo == ((TuiWinElementPtr)
+ locator->content[0])->whichElement.locator.lineNo);
+ bp = _hasBreak (s->filename, curLineNo);
+ element->whichElement.source.hasBreak =
+ (bp != (struct breakpoint *) NULL &&
+ (!element->whichElement.source.isExecPoint ||
+ (bp->disposition != del || bp->hit_count <= 0)));
+ if (c != EOF)
+ {
+ i = strlen (srcLine) - 1;
+ do
+ {
+ if ((c != '\n') &&
+ (c != '\r') && (++i < threshold))
+ {
+ if (c < 040 && c != '\t')
+ {
+ srcLine[i++] = '^';
+ srcLine[i] = c + 0100;
+ }
+ else if (c == 0177)
+ {
+ srcLine[i++] = '^';
+ srcLine[i] = '?';
+ }
+ else
+ { /*
+ ** Store the charcter in the line
+ ** buffer. If it is a tab, then
+ ** translate to the correct number of
+ ** chars so we don't overwrite our
+ ** buffer.
+ */
+ if (c == '\t')
+ {
+ int j, maxTabLen = tuiDefaultTabLen ();
+
+ for (j = i - (
+ (i / maxTabLen) * maxTabLen);
+ ((j < maxTabLen) &&
+ i < threshold);
+ i++, j++)
+ srcLine[i] = ' ';
+ i--;
+ }
+ else
+ srcLine[i] = c;
+ }
+ srcLine[i + 1] = 0;
+ }
+ else
+ { /*
+ ** if we have not reached EOL, then eat
+ ** chars until we do
+ */
+ while (c != EOF && c != '\n' && c != '\r')
+ c = fgetc (stream);
+ }
+ }
+ while (c != EOF && c != '\n' && c != '\r' &&
+ i < threshold && (c = fgetc (stream)));
+ }
+ /* Now copy the line taking the offset into account */
+ if (strlen (srcLine) > offset)
+ strcpy (((TuiWinElementPtr) srcWin->generic.content[
+ curLine])->whichElement.source.line,
+ &srcLine[offset]);
+ else
+ ((TuiWinElementPtr)
+ srcWin->generic.content[
+ curLine])->whichElement.source.line[0] = (char) 0;
+ curLine++;
+ curLineNo++;
+ }
+ if (offset > 0)
+ tuiFree (srcLine);
+ fclose (stream);
+ srcWin->generic.contentSize = nlines;
+ ret = TUI_SUCCESS;
+ }
+ }
+ }
+ }
+ return ret;
+} /* tuiSetSourceContent */
+
+
+/* elz: this function sets the contents of the source window to empty
+ except for a line in the middle with a warning message about the
+ source not being available. This function is called by
+ tuiEraseSourceContents, which in turn is invoked when the source files
+ cannot be accessed*/
+
+void
+#ifdef __STDC__
+tuiSetSourceContentNil (
+ TuiWinInfoPtr winInfo,
+ char *warning_string)
+#else
+tuiSetSourceContentNil (winInfo, warning_string)
+ TuiWinInfoPtr winInfo;
+ char *warning_string;
+#endif
+{
+ int lineWidth;
+ int nLines;
+ int curr_line = 0;
+
+ lineWidth = winInfo->generic.width - 1;
+ nLines = winInfo->generic.height - 2;
+
+ /* set to empty each line in the window, except for the one
+ which contains the message*/
+ while (curr_line < winInfo->generic.contentSize)
+ {
+ /* set the information related to each displayed line
+ to null: i.e. the line number is 0, there is no bp,
+ it is not where the program is stopped */
+
+ TuiWinElementPtr element =
+ (TuiWinElementPtr) winInfo->generic.content[curr_line];
+ element->whichElement.source.lineOrAddr.lineNo = 0;
+ element->whichElement.source.isExecPoint = FALSE;
+ element->whichElement.source.hasBreak = FALSE;
+
+ /* set the contents of the line to blank*/
+ element->whichElement.source.line[0] = (char) 0;
+
+ /* if the current line is in the middle of the screen, then we want to
+ display the 'no source available' message in it.
+ Note: the 'weird' arithmetic with the line width and height comes from
+ the function tuiEraseSourceContent. We need to keep the screen and the
+ window's actual contents in synch */
+
+ if (curr_line == (nLines / 2 + 1))
+ {
+ int i;
+ int xpos;
+ int warning_length = strlen (warning_string);
+ char *srcLine;
+
+ srcLine = element->whichElement.source.line;
+
+ if (warning_length >= ((lineWidth - 1) / 2))
+ xpos = 1;
+ else
+ xpos = (lineWidth - 1) / 2 - warning_length;
+
+ for (i = 0; i < xpos; i++)
+ srcLine[i] = ' ';
+
+ sprintf (srcLine + i, "%s", warning_string);
+
+ for (i = xpos + warning_length; i < lineWidth; i++)
+ srcLine[i] = ' ';
+
+ srcLine[i] = '\n';
+
+ } /* end if */
+
+ curr_line++;
+
+ } /* end while*/
+
+} /*tuiSetSourceContentNil*/
+
+
+
+
+/*
+** tuiShowSource().
+** Function to display source in the source window. This function
+** initializes the horizontal scroll to 0.
+*/
+void
+#ifdef __STDC__
+tuiShowSource (
+ struct symtab *s,
+ Opaque line,
+ int noerror)
+#else
+tuiShowSource (s, line, noerror)
+ struct symtab *s;
+ Opaque line;
+ int noerror;
+#endif
+{
+ srcWin->detail.sourceInfo.horizontalOffset = 0;
+ m_tuiShowSourceAsIs (s, line, noerror);
+
+ return;
+} /* tuiShowSource */
+
+
+/*
+** tuiSourceIsDisplayed().
+** Answer whether the source is currently displayed in the source window.
+*/
+int
+#ifdef __STDC__
+tuiSourceIsDisplayed (
+ char *fname)
+#else
+tuiSourceIsDisplayed (fname)
+ char *fname;
+#endif
+{
+ return (srcWin->generic.contentInUse &&
+ (strcmp (((TuiWinElementPtr) (locatorWinInfoPtr ())->
+ content[0])->whichElement.locator.fileName, fname) == 0));
+} /* tuiSourceIsDisplayed */
+
+
+/*
+** tuiVerticalSourceScroll().
+** Scroll the source forward or backward vertically
+*/
+void
+#ifdef __STDC__
+tuiVerticalSourceScroll (
+ TuiScrollDirection scrollDirection,
+ int numToScroll)
+#else
+tuiVerticalSourceScroll (scrollDirection, numToScroll)
+ TuiScrollDirection scrollDirection;
+ int numToScroll;
+#endif
+{
+ if (srcWin->generic.content != (OpaquePtr) NULL)
+ {
+ int line;
+ Opaque addr;
+ struct symtab *s;
+ TuiWinContent content = (TuiWinContent) srcWin->generic.content;
+
+ if (current_source_symtab == (struct symtab *) NULL)
+ s = find_pc_symtab (selected_frame->pc);
+ else
+ s = current_source_symtab;
+
+ if (scrollDirection == FORWARD_SCROLL)
+ {
+ line = content[0]->whichElement.source.lineOrAddr.lineNo +
+ numToScroll;
+ if (line > s->nlines)
+ /*line = s->nlines - winInfo->generic.contentSize + 1;*/
+ /*elz: fix for dts 23398*/
+ line = content[0]->whichElement.source.lineOrAddr.lineNo;
+ }
+ else
+ {
+ line = content[0]->whichElement.source.lineOrAddr.lineNo -
+ numToScroll;
+ if (line <= 0)
+ line = 1;
+ }
+ tuiUpdateSourceWindowAsIs (srcWin, s, (Opaque) line, FALSE);
+ }
+
+ return;
+} /* tuiVerticalSourceScroll */
+
+
+/*****************************************
+** STATIC LOCAL FUNCTIONS **
+******************************************/
+
+/*
+** _hasBreak().
+** Answer whether there is a break point at the input line in
+** the source file indicated
+*/
+static struct breakpoint *
+#ifdef __STDC__
+_hasBreak (
+ char *sourceFileName,
+ int lineNo)
+#else
+_hasBreak (sourceFileName, lineNo)
+ char *sourceFileName;
+ int lineNo;
+#endif
+{
+ struct breakpoint *bpWithBreak = (struct breakpoint *) NULL;
+ struct breakpoint *bp;
+ extern struct breakpoint *breakpoint_chain;
+
+
+ for (bp = breakpoint_chain;
+ (bp != (struct breakpoint *) NULL &&
+ bpWithBreak == (struct breakpoint *) NULL);
+ bp = bp->next)
+ if ((strcmp (sourceFileName, bp->source_file) == 0) &&
+ (lineNo == bp->line_number))
+ bpWithBreak = bp;
+
+ return bpWithBreak;
+} /* _hasBreak */
diff --git a/gdb/tui/tuiSource.h b/gdb/tui/tuiSource.h
new file mode 100644
index 00000000000..f898c611c71
--- /dev/null
+++ b/gdb/tui/tuiSource.h
@@ -0,0 +1,27 @@
+#ifndef _TUI_SOURCE_H
+#define _TUI_SOURCE_H
+/*
+** This header file supports
+*/
+
+
+#include "defs.h"
+#if 0
+#include "symtab.h"
+#include "breakpoint.h"
+#endif
+
+extern TuiStatus tuiSetSourceContent PARAMS ((struct symtab *, int, int));
+extern void tuiShowSource PARAMS ((struct symtab *, Opaque, int));
+extern void tuiShowSourceAsIs PARAMS ((struct symtab *, Opaque, int));
+extern int tuiSourceIsDisplayed PARAMS ((char *));
+extern void tuiVerticalSourceScroll PARAMS ((TuiScrollDirection, int));
+
+
+/*******************
+** MACROS **
+*******************/
+#define m_tuiShowSourceAsIs(s, line, noerror) tuiUpdateSourceWindowAsIs(srcWin, s, line, noerror)
+
+
+#endif /*_TUI_SOURCE_H*/
diff --git a/gdb/tui/tuiSourceWin.c b/gdb/tui/tuiSourceWin.c
new file mode 100644
index 00000000000..e20392598ad
--- /dev/null
+++ b/gdb/tui/tuiSourceWin.c
@@ -0,0 +1,1098 @@
+/*
+** tuiSourceWin.c
+** This module contains functions for displaying source or assembly in the "source" window.
+* The "source" window may be the assembly or the source windows.
+*/
+
+#include "defs.h"
+#include <ctype.h>
+#include "symtab.h"
+#include "frame.h"
+#include "breakpoint.h"
+
+#include "tui.h"
+#include "tuiData.h"
+#include "tuiStack.h"
+#include "tuiSourceWin.h"
+#include "tuiSource.h"
+#include "tuiDisassem.h"
+
+
+/*****************************************
+** EXTERNAL FUNCTION DECLS **
+******************************************/
+
+/*****************************************
+** EXTERNAL DATA DECLS **
+******************************************/
+extern int current_source_line;
+extern struct symtab *current_source_symtab;
+
+
+/*****************************************
+** STATIC LOCAL FUNCTIONS FORWARD DECLS **
+******************************************/
+
+/*****************************************
+** STATIC LOCAL DATA **
+******************************************/
+
+
+/*****************************************
+** PUBLIC FUNCTIONS **
+******************************************/
+
+/*********************************
+** SOURCE/DISASSEM FUNCTIONS **
+*********************************/
+
+/*
+** tuiSrcWinIsDisplayed().
+*/
+int
+#ifdef __STDC__
+tuiSrcWinIsDisplayed (void)
+#else
+tuiSrcWinIsDisplayed ()
+#endif
+{
+ return (m_winPtrNotNull (srcWin) && srcWin->generic.isVisible);
+} /* tuiSrcWinIsDisplayed */
+
+
+/*
+** tuiAsmWinIsDisplayed().
+*/
+int
+#ifdef __STDC__
+tuiAsmWinIsDisplayed (void)
+#else
+tuiAsmWinIsDisplayed ()
+#endif
+{
+ return (m_winPtrNotNull (disassemWin) && disassemWin->generic.isVisible);
+} /* tuiAsmWinIsDisplayed */
+
+
+/*
+** tuiDisplayMainFunction().
+** Function to display the "main" routine"
+*/
+void
+#ifdef __STDC__
+tuiDisplayMainFunction (void)
+#else
+tuiDisplayMainFunction ()
+#endif
+{
+ if ((sourceWindows ())->count > 0)
+ {
+ CORE_ADDR addr;
+
+ addr = parse_and_eval_address ("main");
+ if (addr <= (CORE_ADDR) 0)
+ addr = parse_and_eval_address ("MAIN");
+ if (addr > (CORE_ADDR) 0)
+ {
+ struct symtab_and_line sal;
+
+ tuiUpdateSourceWindowsWithAddr ((Opaque) addr);
+ sal = find_pc_line (addr, 0);
+ tuiSwitchFilename (sal.symtab->filename);
+ }
+ }
+
+ return;
+} /* tuiDisplayMainFunction */
+
+
+
+/*
+** tuiUpdateSourceWindow().
+** Function to display source in the source window. This function
+** initializes the horizontal scroll to 0.
+*/
+void
+#ifdef __STDC__
+tuiUpdateSourceWindow (
+ TuiWinInfoPtr winInfo,
+ struct symtab *s,
+ Opaque lineOrAddr,
+ int noerror)
+#else
+tuiUpdateSourceWindow (winInfo, s, lineOrAddr, noerror)
+ TuiWinInfoPtr winInfo;
+ struct symtab *s;
+ Opaque lineOrAddr;
+ int noerror;
+#endif
+{
+ winInfo->detail.sourceInfo.horizontalOffset = 0;
+ tuiUpdateSourceWindowAsIs (winInfo, s, lineOrAddr, noerror);
+
+ return;
+} /* tuiUpdateSourceWindow */
+
+
+/*
+** tuiUpdateSourceWindowAsIs().
+** Function to display source in the source/asm window. This
+** function shows the source as specified by the horizontal offset.
+*/
+void
+#ifdef __STDC__
+tuiUpdateSourceWindowAsIs (
+ TuiWinInfoPtr winInfo,
+ struct symtab *s,
+ Opaque lineOrAddr,
+ int noerror)
+#else
+tuiUpdateSourceWindowAsIs (winInfo, s, lineOrAddr, noerror)
+ TuiWinInfoPtr winInfo;
+ struct symtab *s;
+ Opaque lineOrAddr;
+ int noerror;
+#endif
+{
+ TuiStatus ret;
+
+ if (winInfo->generic.type == SRC_WIN)
+ ret = tuiSetSourceContent (s, (int) lineOrAddr, noerror);
+ else
+ ret = tuiSetDisassemContent (s, (Opaque) lineOrAddr);
+
+ if (ret == TUI_FAILURE)
+ {
+ tuiClearSourceContent (winInfo, EMPTY_SOURCE_PROMPT);
+ tuiClearExecInfoContent (winInfo);
+ }
+ else
+ {
+ tuiEraseSourceContent (winInfo, NO_EMPTY_SOURCE_PROMPT);
+ tuiShowSourceContent (winInfo);
+ tuiUpdateExecInfo (winInfo);
+ if (winInfo->generic.type == SRC_WIN)
+ {
+ current_source_line = (int) lineOrAddr +
+ (winInfo->generic.contentSize - 2);
+ current_source_symtab = s;
+ /*
+ ** If the focus was in the asm win, put it in the src
+ ** win if we don't have a split layout
+ */
+ if (tuiWinWithFocus () == disassemWin &&
+ currentLayout () != SRC_DISASSEM_COMMAND)
+ tuiSetWinFocusTo (srcWin);
+ }
+ }
+
+
+ return;
+} /* tuiUpdateSourceWindowAsIs */
+
+
+/*
+** tuiUpdateSourceWindowsWithAddr().
+** Function to ensure that the source and/or disassemly windows
+** reflect the input address.
+*/
+void
+#ifdef __STDC__
+tuiUpdateSourceWindowsWithAddr (
+ Opaque addr)
+#else
+tuiUpdateSourceWindowsWithAddr (addr)
+ Opaque addr;
+#endif
+{
+ if (addr > (Opaque) NULL)
+ {
+ struct symtab_and_line sal;
+
+ switch (currentLayout ())
+ {
+ case DISASSEM_COMMAND:
+ case DISASSEM_DATA_COMMAND:
+ tuiShowDisassem (addr);
+ break;
+ case SRC_DISASSEM_COMMAND:
+ tuiShowDisassemAndUpdateSource (addr);
+ break;
+ default:
+ sal = find_pc_line ((CORE_ADDR) addr, 0);
+ tuiShowSource (sal.symtab,
+ (Opaque) sal.line,
+ FALSE);
+ break;
+ }
+ }
+ else
+ {
+ int i;
+
+ for (i = 0; i < (sourceWindows ())->count; i++)
+ {
+ TuiWinInfoPtr winInfo = (TuiWinInfoPtr) (sourceWindows ())->list[i];
+
+ tuiClearSourceContent (winInfo, EMPTY_SOURCE_PROMPT);
+ tuiClearExecInfoContent (winInfo);
+ }
+ }
+
+ return;
+} /* tuiUpdateSourceWindowsWithAddr */
+
+
+/*
+** tui_vUpdateSourceWindowsWithAddr()
+** Update the source window with the address in a va_list
+*/
+void
+#ifdef __STDC__
+tui_vUpdateSourceWindowsWithAddr (
+ va_list args)
+#else
+tui_vUpdateSourceWindowsWithAddr (args)
+ va_list args;
+#endif
+{
+ Opaque addr = va_arg (args, Opaque);
+
+ tuiUpdateSourceWindowsWithAddr (addr);
+
+ return;
+} /* tui_vUpdateSourceWindowsWithAddr */
+
+
+/*
+** tuiUpdateSourceWindowsWithLine().
+** Function to ensure that the source and/or disassemly windows
+** reflect the input address.
+*/
+void
+#ifdef __STDC__
+tuiUpdateSourceWindowsWithLine (
+ struct symtab *s,
+ int line)
+#else
+tuiUpdateSourceWindowsWithLine (s, line)
+ struct symtab *s;
+ int line;
+#endif
+{
+ switch (currentLayout ())
+ {
+ case DISASSEM_COMMAND:
+ case DISASSEM_DATA_COMMAND:
+ tuiUpdateSourceWindowsWithAddr ((Opaque) find_line_pc (s, line));
+ break;
+ default:
+ tuiShowSource (s, (Opaque) line, FALSE);
+ if (currentLayout () == SRC_DISASSEM_COMMAND)
+ tuiShowDisassem ((Opaque) find_line_pc (s, line));
+ break;
+ }
+
+ return;
+} /* tuiUpdateSourceWindowsWithLine */
+
+
+/*
+** tui_vUpdateSourceWindowsWithLine()
+** Update the source window with the line number in a va_list
+*/
+void
+#ifdef __STDC__
+tui_vUpdateSourceWindowsWithLine (
+ va_list args)
+#else
+tui_vUpdateSourceWindowsWithLine (args)
+ va_list args;
+#endif
+{
+ struct symtab *s = va_arg (args, struct symtab *);
+ int line = va_arg (args, int);
+
+ tuiUpdateSourceWindowsWithLine (s, line);
+
+ return;
+} /* tui_vUpdateSourceWindowsWithLine */
+
+
+/*
+** tuiClearSourceContent().
+*/
+void
+#ifdef __STDC__
+tuiClearSourceContent (
+ TuiWinInfoPtr winInfo,
+ int displayPrompt)
+#else
+tuiClearSourceContent (winInfo, displayPrompt)
+ TuiWinInfoPtr winInfo;
+ int displayPrompt;
+#endif
+{
+ if (m_winPtrNotNull (winInfo))
+ {
+ register int i;
+
+ winInfo->generic.contentInUse = FALSE;
+ tuiEraseSourceContent (winInfo, displayPrompt);
+ for (i = 0; i < winInfo->generic.contentSize; i++)
+ {
+ TuiWinElementPtr element =
+ (TuiWinElementPtr) winInfo->generic.content[i];
+ element->whichElement.source.hasBreak = FALSE;
+ element->whichElement.source.isExecPoint = FALSE;
+ }
+ }
+
+ return;
+} /* tuiClearSourceContent */
+
+
+/*
+** tuiClearAllSourceWinsContent().
+*/
+void
+#ifdef __STDC__
+tuiClearAllSourceWinsContent (
+ int displayPrompt)
+#else
+tuiClearAllSourceWinsContent (displayPrompt)
+ int displayPrompt;
+#endif
+{
+ int i;
+
+ for (i = 0; i < (sourceWindows ())->count; i++)
+ tuiClearSourceContent ((TuiWinInfoPtr) (sourceWindows ())->list[i],
+ displayPrompt);
+
+ return;
+} /* tuiClearAllSourceWinsContent */
+
+
+/*
+** tuiEraseSourceContent().
+*/
+void
+#ifdef __STDC__
+tuiEraseSourceContent (
+ TuiWinInfoPtr winInfo,
+ int displayPrompt)
+#else
+tuiEraseSourceContent (winInfo, displayPrompt)
+ TuiWinInfoPtr winInfo;
+ int displayPrompt;
+#endif
+{
+ int xPos;
+ int halfWidth = (winInfo->generic.width - 2) / 2;
+
+ if (winInfo->generic.handle != (WINDOW *) NULL)
+ {
+ werase (winInfo->generic.handle);
+ checkAndDisplayHighlightIfNeeded (winInfo);
+ if (displayPrompt == EMPTY_SOURCE_PROMPT)
+ {
+ char *noSrcStr;
+
+ if (winInfo->generic.type == SRC_WIN)
+ noSrcStr = NO_SRC_STRING;
+ else
+ noSrcStr = NO_DISASSEM_STRING;
+ if (strlen (noSrcStr) >= halfWidth)
+ xPos = 1;
+ else
+ xPos = halfWidth - strlen (noSrcStr);
+ mvwaddstr (winInfo->generic.handle,
+ (winInfo->generic.height / 2),
+ xPos,
+ noSrcStr);
+
+ /* elz: added this function call to set the real contents of
+ the window to what is on the screen, so that later calls
+ to refresh, do display
+ the correct stuff, and not the old image */
+
+ tuiSetSourceContentNil (winInfo, noSrcStr);
+ }
+ tuiRefreshWin (&winInfo->generic);
+ }
+ return;
+} /* tuiEraseSourceContent */
+
+
+/*
+** tuiEraseAllSourceContent().
+*/
+void
+#ifdef __STDC__
+tuiEraseAllSourceWinsContent (
+ int displayPrompt)
+#else
+tuiEraseAllSourceWinsContent (displayPrompt)
+ int displayPrompt;
+#endif
+{
+ int i;
+
+ for (i = 0; i < (sourceWindows ())->count; i++)
+ tuiEraseSourceContent ((TuiWinInfoPtr) (sourceWindows ())->list[i],
+ displayPrompt);
+
+ return;
+} /* tuiEraseAllSourceWinsContent */
+
+
+/*
+** tuiShowSourceContent().
+*/
+void
+#ifdef __STDC__
+tuiShowSourceContent (
+ TuiWinInfoPtr winInfo)
+#else
+tuiShowSourceContent (winInfo)
+ TuiWinInfoPtr winInfo;
+#endif
+{
+ int curLine, i, curX;
+
+ tuiEraseSourceContent (winInfo, (winInfo->generic.contentSize <= 0));
+ if (winInfo->generic.contentSize > 0)
+ {
+ char *line;
+
+ for (curLine = 1; (curLine <= winInfo->generic.contentSize); curLine++)
+ mvwaddstr (
+ winInfo->generic.handle,
+ curLine,
+ 1,
+ ((TuiWinElementPtr)
+ winInfo->generic.content[curLine - 1])->whichElement.source.line);
+ }
+ checkAndDisplayHighlightIfNeeded (winInfo);
+ tuiRefreshWin (&winInfo->generic);
+ winInfo->generic.contentInUse = TRUE;
+
+ return;
+} /* tuiShowSourceContent */
+
+
+/*
+** tuiShowAllSourceWinsContent()
+*/
+void
+#ifdef __STDC__
+tuiShowAllSourceWinsContent (void)
+#else
+tuiShowAllSourceWinsContent ()
+#endif
+{
+ int i;
+
+ for (i = 0; i < (sourceWindows ())->count; i++)
+ tuiShowSourceContent ((TuiWinInfoPtr) (sourceWindows ())->list[i]);
+
+ return;
+} /* tuiShowAllSourceWinsContent */
+
+
+/*
+** tuiHorizontalSourceScroll().
+** Scroll the source forward or backward horizontally
+*/
+void
+#ifdef __STDC__
+tuiHorizontalSourceScroll (
+ TuiWinInfoPtr winInfo,
+ TuiScrollDirection direction,
+ int numToScroll)
+#else
+tuiHorizontalSourceScroll (winInfo, direction, numToScroll)
+ TuiWinInfoPtr winInfo;
+ TuiScrollDirection direction;
+ int numToScroll;
+#endif
+{
+ if (winInfo->generic.content != (OpaquePtr) NULL)
+ {
+ int offset;
+ struct symtab *s;
+
+ if (current_source_symtab == (struct symtab *) NULL)
+ s = find_pc_symtab (selected_frame->pc);
+ else
+ s = current_source_symtab;
+
+ if (direction == LEFT_SCROLL)
+ offset = winInfo->detail.sourceInfo.horizontalOffset + numToScroll;
+ else
+ {
+ if ((offset =
+ winInfo->detail.sourceInfo.horizontalOffset - numToScroll) < 0)
+ offset = 0;
+ }
+ winInfo->detail.sourceInfo.horizontalOffset = offset;
+ tuiUpdateSourceWindowAsIs (
+ winInfo,
+ s,
+ ((winInfo == srcWin) ?
+ (Opaque) ((TuiWinElementPtr)
+ winInfo->generic.content[0])->whichElement.source.lineOrAddr.lineNo :
+ (Opaque) ((TuiWinElementPtr)
+ winInfo->generic.content[0])->whichElement.source.lineOrAddr.addr),
+ (int) FALSE);
+ }
+
+ return;
+} /* tuiHorizontalSourceScroll */
+
+
+/*
+** tuiSetHasExecPointAt().
+** Set or clear the hasBreak flag in the line whose line is lineNo.
+*/
+void
+#ifdef __STDC__
+tuiSetIsExecPointAt (
+ Opaque lineOrAddr,
+ TuiWinInfoPtr winInfo)
+#else
+tuiSetIsExecPointAt (lineOrAddr, winInfo)
+ Opaque lineOrAddr;
+ TuiWinInfoPtr winInfo;
+#endif
+{
+ int i;
+ TuiWinContent content = (TuiWinContent) winInfo->generic.content;
+
+ i = 0;
+ while (i < winInfo->generic.contentSize)
+ {
+ if (content[i]->whichElement.source.lineOrAddr.addr == lineOrAddr)
+ content[i]->whichElement.source.isExecPoint = TRUE;
+ else
+ content[i]->whichElement.source.isExecPoint = FALSE;
+ i++;
+ }
+
+ return;
+} /* tuiSetIsExecPointAt */
+
+
+/*
+** tuiSetHasBreakAt().
+** Set or clear the hasBreak flag in the line whose line is lineNo.
+*/
+void
+#ifdef __STDC__
+tuiSetHasBreakAt (
+ struct breakpoint *bp,
+ TuiWinInfoPtr winInfo,
+ int hasBreak)
+#else
+tuiSetHasBreakAt (bp, winInfo, hasBreak)
+ struct breakpoint *bp;
+ TuiWinInfoPtr winInfo;
+ int hasBreak;
+#endif
+{
+ int i;
+ TuiWinContent content = (TuiWinContent) winInfo->generic.content;
+
+ i = 0;
+ while (i < winInfo->generic.contentSize)
+ {
+ int gotIt;
+ TuiGenWinInfoPtr locator = locatorWinInfoPtr ();
+
+ if (winInfo == srcWin)
+ {
+ char *fileNameDisplayed = (char *) NULL;
+
+ if (((TuiWinElementPtr)
+ locator->content[0])->whichElement.locator.fileName !=
+ (char *) NULL)
+ fileNameDisplayed = ((TuiWinElementPtr)
+ locator->content[0])->whichElement.locator.fileName;
+ else if (current_source_symtab != (struct symtab *) NULL)
+ fileNameDisplayed = current_source_symtab->filename;
+
+ gotIt = (fileNameDisplayed != (char *) NULL &&
+ (strcmp (bp->source_file, fileNameDisplayed) == 0) &&
+ content[i]->whichElement.source.lineOrAddr.lineNo ==
+ bp->line_number);
+ }
+ else
+ gotIt = (content[i]->whichElement.source.lineOrAddr.addr
+ == (Opaque) bp->address);
+ if (gotIt)
+ {
+ content[i]->whichElement.source.hasBreak = hasBreak;
+ break;
+ }
+ i++;
+ }
+
+ return;
+} /* tuiSetHasBreakAt */
+
+
+/*
+** tuiAllSetHasBreakAt().
+** Set or clear the hasBreak flag in all displayed source windows.
+*/
+void
+#ifdef __STDC__
+tuiAllSetHasBreakAt (
+ struct breakpoint *bp,
+ int hasBreak)
+#else
+tuiAllSetHasBreakAt (bp, hasBreak)
+ struct breakpoint *bp;
+ int hasBreak;
+#endif
+{
+ int i;
+
+ for (i = 0; i < (sourceWindows ())->count; i++)
+ tuiSetHasBreakAt (bp,
+ (TuiWinInfoPtr) (sourceWindows ())->list[i], hasBreak);
+
+ return;
+} /* tuiAllSetHasBreakAt */
+
+
+/*
+** tui_vAllSetHasBreakAt()
+** Set or clear the hasBreak flag in all displayed source windows,
+** with params in a va_list
+*/
+void
+#ifdef __STDC__
+tui_vAllSetHasBreakAt (
+ va_list args)
+#else
+tui_vAllSetHasBreakAt (args)
+ va_list args;
+#endif
+{
+ struct breakpoint *bp = va_arg (args, struct breakpoint *);
+ int hasBreak = va_arg (args, int);
+
+ tuiAllSetHasBreakAt (bp, hasBreak);
+
+ return;
+} /* tui_vAllSetHasBreakAt */
+
+
+
+/*********************************
+** EXECUTION INFO FUNCTIONS **
+*********************************/
+
+/*
+** tuiSetExecInfoContent().
+** Function to initialize the content of the execution info window,
+** based upon the input window which is either the source or
+** disassembly window.
+*/
+TuiStatus
+#ifdef __STDC__
+tuiSetExecInfoContent (
+ TuiWinInfoPtr winInfo)
+#else
+tuiSetExecInfoContent (winInfo)
+ TuiWinInfoPtr winInfo;
+#endif
+{
+ TuiStatus ret = TUI_SUCCESS;
+
+ if (winInfo->detail.sourceInfo.executionInfo != (TuiGenWinInfoPtr) NULL)
+ {
+ TuiGenWinInfoPtr execInfoPtr = winInfo->detail.sourceInfo.executionInfo;
+
+ if (execInfoPtr->content == (OpaquePtr) NULL)
+ execInfoPtr->content =
+ (OpaquePtr) allocContent (winInfo->generic.height,
+ execInfoPtr->type);
+ if (execInfoPtr->content != (OpaquePtr) NULL)
+ {
+ int i;
+
+ for (i = 0; i < winInfo->generic.contentSize; i++)
+ {
+ TuiWinElementPtr element;
+ TuiWinElementPtr srcElement;
+
+ element = (TuiWinElementPtr) execInfoPtr->content[i];
+ srcElement = (TuiWinElementPtr) winInfo->generic.content[i];
+ /*
+ ** First check to see if we have a breakpoint that is
+ ** temporary. If so, and this is our current execution point,
+ ** then clear the break indicator.
+ */
+ if (srcElement->whichElement.source.hasBreak &&
+ srcElement->whichElement.source.isExecPoint)
+ {
+ struct breakpoint *bp;
+ int found = FALSE;
+ extern struct breakpoint *breakpoint_chain;
+
+ for (bp = breakpoint_chain;
+ (bp != (struct breakpoint *) NULL && !found);
+ bp = bp->next)
+ {
+ found =
+ (winInfo == srcWin &&
+ bp->line_number ==
+ srcElement->whichElement.source.lineOrAddr.lineNo) ||
+ (winInfo == disassemWin &&
+ bp->address == (CORE_ADDR)
+ srcElement->whichElement.source.lineOrAddr.addr);
+ if (found)
+ srcElement->whichElement.source.hasBreak =
+ (bp->disposition != del || bp->hit_count <= 0);
+ }
+ if (!found)
+ srcElement->whichElement.source.hasBreak = FALSE;
+ }
+ /*
+ ** Now update the exec info content based upon the state
+ ** of each line as indicated by the source content.
+ */
+ if (srcElement->whichElement.source.hasBreak &&
+ srcElement->whichElement.source.isExecPoint)
+ element->whichElement.simpleString = breakLocationStr ();
+ else if (srcElement->whichElement.source.hasBreak)
+ element->whichElement.simpleString = breakStr ();
+ else if (srcElement->whichElement.source.isExecPoint)
+ element->whichElement.simpleString = locationStr ();
+ else
+ element->whichElement.simpleString = blankStr ();
+ }
+ execInfoPtr->contentSize = winInfo->generic.contentSize;
+ }
+ else
+ ret = TUI_FAILURE;
+ }
+
+ return ret;
+} /* tuiSetExecInfoContent */
+
+
+/*
+** tuiShowExecInfoContent().
+*/
+void
+#ifdef __STDC__
+tuiShowExecInfoContent (
+ TuiWinInfoPtr winInfo)
+#else
+tuiShowExecInfoContent (winInfo)
+ TuiWinInfoPtr winInfo;
+#endif
+{
+ TuiGenWinInfoPtr execInfo = winInfo->detail.sourceInfo.executionInfo;
+ int curLine;
+
+ werase (execInfo->handle);
+ tuiRefreshWin (execInfo);
+ for (curLine = 1; (curLine <= execInfo->contentSize); curLine++)
+ mvwaddstr (execInfo->handle,
+ curLine,
+ 0,
+ ((TuiWinElementPtr)
+ execInfo->content[curLine - 1])->whichElement.simpleString);
+ tuiRefreshWin (execInfo);
+ execInfo->contentInUse = TRUE;
+
+ return;
+} /* tuiShowExecInfoContent */
+
+
+/*
+** tuiShowAllExecInfosContent()
+*/
+void
+#ifdef __STDC__
+tuiShowAllExecInfosContent (void)
+#else
+tuiShowAllExecInfosContent ()
+#endif
+{
+ int i;
+
+ for (i = 0; i < (sourceWindows ())->count; i++)
+ tuiShowExecInfoContent ((TuiWinInfoPtr) (sourceWindows ())->list[i]);
+
+ return;
+} /* tuiShowAllExecInfosContent */
+
+
+/*
+** tuiEraseExecInfoContent().
+*/
+void
+#ifdef __STDC__
+tuiEraseExecInfoContent (
+ TuiWinInfoPtr winInfo)
+#else
+tuiEraseExecInfoContent (winInfo)
+ TuiWinInfoPtr winInfo;
+#endif
+{
+ TuiGenWinInfoPtr execInfo = winInfo->detail.sourceInfo.executionInfo;
+
+ werase (execInfo->handle);
+ tuiRefreshWin (execInfo);
+
+ return;
+} /* tuiEraseExecInfoContent */
+
+
+/*
+** tuiEraseAllExecInfosContent()
+*/
+void
+#ifdef __STDC__
+tuiEraseAllExecInfosContent (void)
+#else
+tuiEraseAllExecInfosContent ()
+#endif
+{
+ int i;
+
+ for (i = 0; i < (sourceWindows ())->count; i++)
+ tuiEraseExecInfoContent ((TuiWinInfoPtr) (sourceWindows ())->list[i]);
+
+ return;
+} /* tuiEraseAllExecInfosContent */
+
+
+/*
+** tuiClearExecInfoContent().
+*/
+void
+#ifdef __STDC__
+tuiClearExecInfoContent (
+ TuiWinInfoPtr winInfo)
+#else
+tuiClearExecInfoContent (winInfo)
+ TuiWinInfoPtr winInfo;
+#endif
+{
+ winInfo->detail.sourceInfo.executionInfo->contentInUse = FALSE;
+ tuiEraseExecInfoContent (winInfo);
+
+ return;
+} /* tuiClearExecInfoContent */
+
+
+/*
+** tuiClearAllExecInfosContent()
+*/
+void
+#ifdef __STDC__
+tuiClearAllExecInfosContent (void)
+#else
+tuiClearAllExecInfosContent ()
+#endif
+{
+ int i;
+
+ for (i = 0; i < (sourceWindows ())->count; i++)
+ tuiClearExecInfoContent ((TuiWinInfoPtr) (sourceWindows ())->list[i]);
+
+ return;
+} /* tuiClearAllExecInfosContent */
+
+
+/*
+** tuiUpdateExecInfo().
+** Function to update the execution info window
+*/
+void
+#ifdef __STDC__
+tuiUpdateExecInfo (
+ TuiWinInfoPtr winInfo)
+#else
+tuiUpdateExecInfo (winInfo)
+ TuiWinInfoPtr winInfo;
+#endif
+{
+ tuiSetExecInfoContent (winInfo);
+ tuiShowExecInfoContent (winInfo);
+} /* tuiUpdateExecInfo
+
+
+/*
+** tuiUpdateAllExecInfos()
+*/
+void
+#ifdef __STDC__
+tuiUpdateAllExecInfos (void)
+#else
+tuiUpdateAllExecInfos ()
+#endif
+{
+ int i;
+
+ for (i = 0; i < (sourceWindows ())->count; i++)
+ tuiUpdateExecInfo ((TuiWinInfoPtr) (sourceWindows ())->list[i]);
+
+ return;
+} /* tuiUpdateAllExecInfos*/
+
+
+
+/* tuiUpdateOnEnd()
+** elz: This function clears the execution info from the source windows
+** and resets the locator to display no line info, procedure info, pc
+** info. It is called by stack_publish_stopped_with_no_frame, which
+** is called then the target terminates execution
+*/
+void
+#ifdef __STDC__
+tuiUpdateOnEnd (void)
+#else
+tuiUpdateOnEnd ()
+#endif
+{
+ int i;
+ TuiGenWinInfoPtr locator;
+ char *filename;
+ TuiWinInfoPtr winInfo;
+
+ locator = locatorWinInfoPtr ();
+
+ /* for all the windows (src, asm) */
+ for (i = 0; i < (sourceWindows ())->count; i++)
+ {
+ winInfo = (TuiWinInfoPtr) (sourceWindows ())->list[i];
+
+ tuiSetIsExecPointAt ((Opaque) - 1, winInfo); /* the target is'n running */
+ /* -1 should not match any line number or pc */
+ tuiSetExecInfoContent (winInfo); /*set winInfo so that > is'n displayed*/
+ tuiShowExecInfoContent (winInfo); /* display the new contents */
+ }
+
+ /*now update the locator*/
+ tuiClearLocatorDisplay ();
+ tuiGetLocatorFilename (locator, &filename);
+ tuiSetLocatorInfo (
+ filename,
+ (char *) NULL,
+ 0,
+ (Opaque) NULL,
+ &((TuiWinElementPtr) locator->content[0])->whichElement.locator);
+ tuiShowLocatorContent ();
+
+ return;
+} /* tuiUpdateOnEnd */
+
+
+
+TuiStatus
+#ifdef __STDC__
+tuiAllocSourceBuffer (
+ TuiWinInfoPtr winInfo)
+#else
+tuiAllocSourceBuffer (winInfo)
+ TuiWinInfoPtr winInfo;
+#endif
+{
+ register char *srcLine, *srcLineBuf;
+ register int i, lineWidth, c, maxLines;
+ TuiStatus ret = TUI_FAILURE;
+
+ maxLines = winInfo->generic.height; /* less the highlight box */
+ lineWidth = winInfo->generic.width - 1;
+ /*
+ ** Allocate the buffer for the source lines. Do this only once since they
+ ** will be re-used for all source displays. The only other time this will
+ ** be done is when a window's size changes.
+ */
+ if (winInfo->generic.content == (OpaquePtr) NULL)
+ {
+ srcLineBuf = (char *) xmalloc ((maxLines * lineWidth) * sizeof (char));
+ if (srcLineBuf == (char *) NULL)
+ fputs_unfiltered (
+ "Unable to Allocate Memory for Source or Disassembly Display.\n",
+ gdb_stderr);
+ else
+ {
+ /* allocate the content list */
+ if ((winInfo->generic.content =
+ (OpaquePtr) allocContent (maxLines, SRC_WIN)) == (OpaquePtr) NULL)
+ {
+ tuiFree (srcLineBuf);
+ srcLineBuf = (char *) NULL;
+ fputs_unfiltered (
+ "Unable to Allocate Memory for Source or Disassembly Display.\n",
+ gdb_stderr);
+ }
+ }
+ for (i = 0; i < maxLines; i++)
+ ((TuiWinElementPtr)
+ winInfo->generic.content[i])->whichElement.source.line =
+ srcLineBuf + (lineWidth * i);
+ ret = TUI_SUCCESS;
+ }
+ else
+ ret = TUI_SUCCESS;
+
+ return ret;
+} /* tuiAllocSourceBuffer */
+
+
+/*
+** tuiLineIsDisplayed().
+** Answer whether the a particular line number or address is displayed
+** in the current source window.
+*/
+int
+#ifdef __STDC__
+tuiLineIsDisplayed (
+ Opaque lineNoOrAddr,
+ TuiWinInfoPtr winInfo,
+ int checkThreshold)
+#else
+tuiLineIsDisplayed (lineNoOrAddr, winInfo, checkThreshold)
+ Opaque lineNoOrAddr;
+ TuiWinInfoPtr winInfo;
+ int checkThreshold;
+#endif
+{
+ int isDisplayed = FALSE;
+ int i, threshold;
+
+ if (checkThreshold)
+ threshold = SCROLL_THRESHOLD;
+ else
+ threshold = 0;
+ i = 0;
+ while (i < winInfo->generic.contentSize - threshold && !isDisplayed)
+ {
+ if (winInfo == srcWin)
+ isDisplayed = (((TuiWinElementPtr)
+ winInfo->generic.content[i])->whichElement.source.lineOrAddr.lineNo
+ == (int) lineNoOrAddr);
+ else
+ isDisplayed = (((TuiWinElementPtr)
+ winInfo->generic.content[i])->whichElement.source.lineOrAddr.addr
+ == lineNoOrAddr);
+ i++;
+ }
+
+ return isDisplayed;
+} /* tuiLineIsDisplayed */
+
+
+/*****************************************
+** STATIC LOCAL FUNCTIONS **
+******************************************/
diff --git a/gdb/tui/tuiSourceWin.h b/gdb/tui/tuiSourceWin.h
new file mode 100644
index 00000000000..13f3a78ab18
--- /dev/null
+++ b/gdb/tui/tuiSourceWin.h
@@ -0,0 +1,74 @@
+#ifndef _TUI_SOURCEWIN_H
+#define _TUI_SOURCEWIN_H
+/*
+** This header file supports
+*/
+
+
+extern void tuiDisplayMainFunction PARAMS ((void));
+extern void tuiUpdateSourceWindow PARAMS
+ ((TuiWinInfoPtr, struct symtab *, Opaque, int));
+extern void tuiUpdateSourceWindowAsIs PARAMS
+ ((TuiWinInfoPtr, struct symtab *, Opaque, int));
+extern void tuiUpdateSourceWindowsWithAddr PARAMS ((Opaque));
+extern void tui_vUpdateSourceWindowsWithAddr PARAMS ((va_list));
+extern void tuiUpdateSourceWindowsWithLine PARAMS ((struct symtab *, int));
+extern void tui_vUpdateSourceWindowsWithLine PARAMS ((va_list));
+extern void tuiUpdateSourceWindowsFromLocator PARAMS ((void));
+extern void tuiClearSourceContent PARAMS ((TuiWinInfoPtr, int));
+extern void tuiClearAllSourceWinsContent PARAMS ((int));
+extern void tuiEraseSourceContent PARAMS ((TuiWinInfoPtr, int));
+extern void tuiEraseAllSourceWinsContent PARAMS ((int));
+extern void tuiSetSourceContentNil PARAMS ((TuiWinInfoPtr, char *));
+extern void tuiShowSourceContent PARAMS ((TuiWinInfoPtr));
+extern void tuiShowAllSourceWinsContent PARAMS ((void));
+extern void tuiHorizontalSourceScroll PARAMS ((TuiWinInfoPtr, TuiScrollDirection, int));
+extern void tuiUpdateOnEnd PARAMS ((void));
+
+extern TuiStatus tuiSetExecInfoContent PARAMS ((TuiWinInfoPtr));
+extern void tuiShowExecInfoContent PARAMS ((TuiWinInfoPtr));
+extern void tuiShowAllExecInfosContent PARAMS ((void));
+extern void tuiEraseExecInfoContent PARAMS ((TuiWinInfoPtr));
+extern void tuiEraseAllExecInfosContent PARAMS ((void));
+extern void tuiClearExecInfoContent PARAMS ((TuiWinInfoPtr));
+extern void tuiClearAllExecInfosContent PARAMS ((void));
+extern void tuiUpdateExecInfo PARAMS ((TuiWinInfoPtr));
+extern void tuiUpdateAllExecInfos PARAMS ((void));
+
+extern void tuiSetIsExecPointAt PARAMS ((Opaque, TuiWinInfoPtr));
+extern void tuiSetHasBreakAt PARAMS ((struct breakpoint *, TuiWinInfoPtr, int));
+extern void tuiAllSetHasBreakAt PARAMS ((struct breakpoint *, int));
+extern void tui_vAllSetHasBreakAt PARAMS ((va_list));
+extern TuiStatus tuiAllocSourceBuffer PARAMS ((TuiWinInfoPtr));
+extern int tuiLineIsDisplayed PARAMS ((Opaque, TuiWinInfoPtr, int));
+
+
+/*
+** Constant definitions
+*/
+#define SCROLL_THRESHOLD 2 /* threshold for lazy scroll */
+
+
+/*
+** Macros
+*/
+#define m_tuiSetBreakAt(bp, winInfo) tuiSetHasBreakAt((bp, winInfo, TRUE)
+#define m_tuiClearBreakAt(bp, winInfo) tuiSetHasBreakAt(bp, winInfo, FALSE)
+
+#define m_tuiAllSetBreakAt(bp) tuiAllSetHasBreakAt(bp, TRUE)
+#define m_tuiAllClearBreakAt(bp) tuiAllSetHasBreakAt(bp, FALSE)
+
+#define m_tuiSrcLineDisplayed(lineNo) tuiLineIsDisplayed((Opaque)(lineNo), srcWin, FALSE)
+#define m_tuiSrcAddrDisplayed(addr) tuiLineIsDisplayed((Opaque)(addr), disassemWin, FALSE)
+#define m_tuiSrcLineDisplayedWithinThreshold(lineNo) \
+ tuiLineIsDisplayed((Opaque)(lineNo), srcWin, TRUE)
+#define m_tuiSrcAddrDisplayedWithinThreshold(addr) \
+ tuiLineIsDisplayed((Opaque)(addr), disassemWin, TRUE)
+#define m_tuiLineDisplayedWithinThreshold(winInfo, lineOrAddr) \
+ ( (winInfo == srcWin) ? \
+ m_tuiSrcLineDisplayedWithinThreshold(lineOrAddr) : \
+ m_tuiSrcAddrDisplayedWithinThreshold(lineOrAddr) )
+
+
+
+#endif /*_TUI_SOURCEWIN_H */
diff --git a/gdb/tui/tuiStack.c b/gdb/tui/tuiStack.c
new file mode 100644
index 00000000000..401dfe23d82
--- /dev/null
+++ b/gdb/tui/tuiStack.c
@@ -0,0 +1,554 @@
+/*
+** This module contains functions for displaying the locator information in the locator window.
+*/
+
+#include "defs.h"
+#include "symtab.h"
+#include "breakpoint.h"
+#include "frame.h"
+
+#include "tui.h"
+#include "tuiData.h"
+#include "tuiStack.h"
+#include "tuiSourceWin.h"
+
+
+/*****************************************
+** STATIC LOCAL FUNCTIONS FORWARD DECLS **
+******************************************/
+
+static char *_getFuncNameFromFrame PARAMS ((struct frame_info *));
+static void _tuiUpdateLocation_command PARAMS ((char *, int));
+
+
+
+/*****************************************
+** PUBLIC FUNCTION **
+******************************************/
+
+/*
+** tuiClearLocatorDisplay()
+*/
+void
+#ifdef __STDC__
+tuiClearLocatorDisplay (void)
+#else
+tuiClearLocatorDisplay ()
+#endif
+{
+ TuiGenWinInfoPtr locator = locatorWinInfoPtr ();
+ int i;
+
+ if (locator->handle != (WINDOW *) NULL)
+ {
+ /* No need to werase, since writing a line of
+ * blanks which we do below, is equivalent.
+ */
+ /* werase(locator->handle); */
+ wmove (locator->handle, 0, 0);
+ wstandout (locator->handle);
+ for (i = 0; i < locator->width; i++)
+ waddch (locator->handle, ' ');
+ wstandend (locator->handle);
+ tuiRefreshWin (locator);
+ wmove (locator->handle, 0, 0);
+ locator->contentInUse = FALSE;
+ }
+
+ return;
+} /* tuiClearLocatorDisplay */
+
+
+/*
+** tuiShowLocatorContent()
+*/
+void
+#ifdef __STDC__
+tuiShowLocatorContent (void)
+#else
+tuiShowLocatorContent ()
+#endif
+{
+ char *string;
+ TuiGenWinInfoPtr locator;
+
+ locator = locatorWinInfoPtr ();
+
+ if (m_genWinPtrNotNull (locator) && locator->handle != (WINDOW *) NULL)
+ {
+ string = displayableWinContentAt (locator, 0);
+ if (string != (char *) NULL)
+ {
+ wmove (locator->handle, 0, 0);
+ wstandout (locator->handle);
+ waddstr (locator->handle, string);
+ wstandend (locator->handle);
+ tuiRefreshWin (locator);
+ wmove (locator->handle, 0, 0);
+ if (string != nullStr ())
+ tuiFree (string);
+ locator->contentInUse = TRUE;
+ }
+ }
+
+ return;
+} /* tuiShowLocatorContent */
+
+
+/*
+** tuiSetLocatorInfo().
+** Function to update the locator, with the provided arguments.
+*/
+void
+#ifdef __STDC__
+tuiSetLocatorInfo (
+ char *fname,
+ char *procname,
+ int lineNo,
+ Opaque addr,
+ TuiLocatorElementPtr element)
+#else
+tuiSetLocatorInfo (fname, procname, lineNo, addr, element)
+ char *fname;
+ char *procname;
+ int lineNo;
+ Opaque addr;
+ TuiLocatorElementPtr element;
+#endif
+{
+#ifdef COMMENT
+ /* first free the old info */
+ if (element->fileName)
+ tuiFree (element->fileName);
+ if (element->procName)
+ tuiFree (element->procName);
+
+ if (fname == (char *) NULL)
+ element->fileName = fname;
+ else
+ element->fileName = tuiStrDup (fname);
+ if (procname == (char *) NULL)
+ element->procName = procname;
+ else
+ element->procName = tuiStrDup (procname);
+#else
+ element->fileName[0] = (char) 0;
+ element->procName[0] = (char) 0;
+ strcat_to_buf (element->fileName, MAX_LOCATOR_ELEMENT_LEN, fname);
+ strcat_to_buf (element->procName, MAX_LOCATOR_ELEMENT_LEN, procname);
+#endif
+ element->lineNo = lineNo;
+ element->addr = (Opaque) addr;
+
+ return;
+} /* tuiSetLocatorInfo */
+
+
+/*
+** tuiUpdateLocatorFilename().
+** Update only the filename portion of the locator.
+*/
+void
+#ifdef __STDC__
+tuiUpdateLocatorFilename (
+ char *fileName)
+#else
+tuiUpdateLocatorFilename (fileName)
+ char *fileName;
+#endif
+{
+ TuiGenWinInfoPtr locator = locatorWinInfoPtr ();
+
+ if (locator->content[0] == (Opaque) NULL)
+ tuiSetLocatorContent ((struct frame_info *) NULL);
+ ((TuiWinElementPtr) locator->content[0])->whichElement.locator.fileName[0] = (char) 0;
+ strcat_to_buf (((TuiWinElementPtr) locator->content[0])->whichElement.locator.fileName,
+ MAX_LOCATOR_ELEMENT_LEN,
+ fileName);
+
+ tuiShowLocatorContent ();
+
+ return;
+} /* tuiUpdateLocatorFilename */
+
+
+/*
+** tui_vUpdateLocatorFilename().
+** Update only the filename portion of the locator with args in a va_list.
+*/
+void
+#ifdef __STDC__
+tui_vUpdateLocatorFilename (
+ va_list args)
+#else
+tui_vUpdateLocatorFilename (args)
+ va_list args;
+#endif
+{
+ char *fileName;
+
+ fileName = va_arg (args, char *);
+ tuiUpdateLocatorFilename (fileName);
+
+ return;
+} /* tui_vUpdateLocatorFilename */
+
+
+/*
+** tuiSwitchFilename().
+** Update the filename portion of the locator. Clear the other info in locator.
+** (elz)
+*/
+void
+#ifdef __STDC__
+tuiSwitchFilename (
+ char *fileName)
+#else
+tuiSwitchFilename (fileName)
+ char *fileName;
+#endif
+{
+ TuiGenWinInfoPtr locator = locatorWinInfoPtr ();
+
+ if (locator->content[0] == (Opaque) NULL)
+ tuiSetLocatorContent ((struct frame_info *) NULL);
+ ((TuiWinElementPtr) locator->content[0])->whichElement.locator.fileName[0] = (char) 0;
+
+ tuiSetLocatorInfo (fileName,
+ (char *) NULL,
+ 0,
+ (Opaque) NULL,
+ &((TuiWinElementPtr) locator->content[0])->whichElement.locator);
+
+ tuiShowLocatorContent ();
+
+ return;
+} /* tuiSwitchFilename */
+
+
+/*
+** tuiGetLocatorFilename().
+** Get the filename portion of the locator.
+** (elz)
+*/
+void
+#ifdef __STDC__
+tuiGetLocatorFilename (
+ TuiGenWinInfoPtr locator,
+ char **filename)
+#else
+tuiGetLocatorFilename (locator, filename)
+ TuiGenWinInfoPtr locator;
+ char **filename;
+#endif
+{
+
+ /* the current filename could be non known, in which case the xmalloc would
+ allocate no memory, because the length would be 0 */
+ if (((TuiWinElementPtr) locator->content[0])->whichElement.locator.fileName)
+ {
+ int name_length =
+ strlen (((TuiWinElementPtr) locator->content[0])->whichElement.locator.fileName);
+
+ (*filename) = (char *) xmalloc (name_length + 1);
+ strcpy ((*filename),
+ ((TuiWinElementPtr) locator->content[0])->whichElement.locator.fileName);
+ }
+
+ return;
+} /* tuiGetLocatorFilename */
+
+
+/*
+** tuiUpdateLocatorInfoFromFrame().
+** Function to update the locator, with the information extracted from frameInfo
+*/
+void
+#ifdef __STDC__
+tuiUpdateLocatorInfoFromFrame (
+ struct frame_info *frameInfo,
+ TuiLocatorElementPtr element)
+#else
+tuiUpdateLocatorInfoFromFrame (frameInfo, element)
+ struct frame_info *frameInfo;
+ TuiLocatorElementPtr element;
+#endif
+{
+ struct symtab_and_line symtabAndLine;
+
+ /* now get the new info */
+ symtabAndLine = find_pc_line (frameInfo->pc,
+ (frameInfo->next != (struct frame_info *) NULL &&
+ !frameInfo->next->signal_handler_caller &&
+ !frame_in_dummy (frameInfo->next)));
+ if (symtabAndLine.symtab && symtabAndLine.symtab->filename)
+ tuiSetLocatorInfo (symtabAndLine.symtab->filename,
+ _getFuncNameFromFrame (frameInfo),
+ symtabAndLine.line,
+ (Opaque) frameInfo->pc,
+ element);
+ else
+ tuiSetLocatorInfo ((char *) NULL,
+ _getFuncNameFromFrame (frameInfo),
+ 0,
+ (Opaque) frameInfo->pc,
+ element);
+
+ return;
+} /* tuiUpdateLocatorInfoFromFrame */
+
+
+/*
+** tuiSetLocatorContent().
+** Function to set the content of the locator
+*/
+void
+#ifdef __STDC__
+tuiSetLocatorContent (
+ struct frame_info *frameInfo)
+#else
+tuiSetLocatorContent (frameInfo)
+ struct frame_info *frameInfo;
+#endif
+{
+ TuiGenWinInfoPtr locator = locatorWinInfoPtr ();
+ TuiWinElementPtr element;
+ struct symtab_and_line symtabAndLine;
+
+ /* Allocate the element if necessary */
+ if (locator->contentSize <= 0)
+ {
+ TuiWinContent contentPtr;
+
+ if ((locator->content = (OpaquePtr) allocContent (1, locator->type)) == (OpaquePtr) NULL)
+ error ("Unable to Allocate Memory to Display Location.");
+ locator->contentSize = 1;
+ }
+
+ if (frameInfo != (struct frame_info *) NULL)
+ tuiUpdateLocatorInfoFromFrame (frameInfo,
+ &((TuiWinElementPtr) locator->content[0])->whichElement.locator);
+ else
+ tuiSetLocatorInfo ((char *) NULL,
+ (char *) NULL,
+ 0,
+ (Opaque) NULL,
+ &((TuiWinElementPtr) locator->content[0])->whichElement.locator);
+ return;
+} /* tuiSetLocatorContent */
+
+
+/*
+** tuiUpdateLocatorDisplay().
+** Function to update the locator display
+*/
+void
+#ifdef __STDC__
+tuiUpdateLocatorDisplay (
+ struct frame_info *frameInfo)
+#else
+tuiUpdateLocatorDisplay (frameInfo)
+ struct frame_info *frameInfo;
+#endif
+{
+ tuiClearLocatorDisplay ();
+ tuiSetLocatorContent (frameInfo);
+ tuiShowLocatorContent ();
+
+ return;
+} /* tuiUpdateLocatorDisplay */
+
+
+/*
+** tuiShowFrameInfo().
+** Function to print the frame inforrmation for the TUI.
+*/
+void
+#ifdef __STDC__
+tuiShowFrameInfo (
+ struct frame_info *fi)
+#else
+tuiShowFrameInfo (fi)
+ struct frame_info *fi;
+#endif
+{
+ TuiWinInfoPtr winInfo;
+ register int i;
+
+ if (fi)
+ {
+ register int startLine, i;
+ register struct symtab *s;
+ CORE_ADDR low;
+ TuiGenWinInfoPtr locator = locatorWinInfoPtr ();
+ int sourceAlreadyDisplayed;
+
+
+ s = find_pc_symtab (fi->pc);
+ sourceAlreadyDisplayed = tuiSourceIsDisplayed (s->filename);
+ tuiUpdateLocatorDisplay (fi);
+ for (i = 0; i < (sourceWindows ())->count; i++)
+ {
+ winInfo = (TuiWinInfoPtr) (sourceWindows ())->list[i];
+ if (winInfo == srcWin)
+ {
+ startLine =
+ (((TuiWinElementPtr) locator->content[0])->whichElement.locator.lineNo -
+ (winInfo->generic.viewportHeight / 2)) + 1;
+ if (startLine <= 0)
+ startLine = 1;
+ }
+ else
+ {
+ if (find_pc_partial_function (fi->pc, (char **) NULL, &low, (CORE_ADDR) NULL) == 0)
+ error ("No function contains program counter for selected frame.\n");
+ else
+ low = (CORE_ADDR) tuiGetLowDisassemblyAddress ((Opaque) low, (Opaque) fi->pc);
+ }
+
+ if (winInfo == srcWin)
+ {
+ if (!(sourceAlreadyDisplayed && m_tuiLineDisplayedWithinThreshold (
+ winInfo,
+ ((TuiWinElementPtr) locator->content[0])->whichElement.locator.lineNo)))
+ tuiUpdateSourceWindow (winInfo, s, (Opaque) startLine, TRUE);
+ else
+ tuiSetIsExecPointAt ((Opaque)
+ ((TuiWinElementPtr) locator->content[0])->whichElement.locator.lineNo,
+ winInfo);
+ }
+ else
+ {
+ if (winInfo == disassemWin)
+ {
+ if (!m_tuiLineDisplayedWithinThreshold (winInfo,
+ ((TuiWinElementPtr) locator->content[0])->whichElement.locator.addr))
+ tuiUpdateSourceWindow (winInfo, s, (Opaque) low, TRUE);
+ else
+ tuiSetIsExecPointAt ((Opaque)
+ ((TuiWinElementPtr) locator->content[0])->whichElement.locator.addr,
+ winInfo);
+ }
+ }
+ tuiUpdateExecInfo (winInfo);
+ }
+ }
+ else
+ {
+ tuiUpdateLocatorDisplay (fi);
+ for (i = 0; i < (sourceWindows ())->count; i++)
+ {
+ winInfo = (TuiWinInfoPtr) (sourceWindows ())->list[i];
+ tuiClearSourceContent (winInfo, EMPTY_SOURCE_PROMPT);
+ tuiUpdateExecInfo (winInfo);
+ }
+ }
+
+ return;
+} /* tuiShowFrameInfo */
+
+
+/*
+** tui_vShowFrameInfo().
+** Function to print the frame inforrmation for the TUI with args in a va_list.
+*/
+void
+#ifdef __STDC__
+tui_vShowFrameInfo (
+ va_list args)
+#else
+tui_vShowFrameInfo (args)
+ va_list args;
+#endif
+{
+ struct frame_info *fi;
+
+ fi = va_arg (args, struct frame_info *);
+ tuiShowFrameInfo (fi);
+
+ return;
+} /* tui_vShowFrameInfo */
+
+
+/*
+** _initialize_tuiStack().
+** Function to initialize gdb commands, for tui window stack manipulation.
+*/
+void
+_initialize_tuiStack ()
+{
+ if (tui_version)
+ {
+ add_com ("update", class_tui, _tuiUpdateLocation_command,
+ "Update the source window and locator to display the current execution point.\n");
+ }
+
+ return;
+} /* _initialize_tuiStack */
+
+
+/*****************************************
+** STATIC LOCAL FUNCTIONS **
+******************************************/
+
+/*
+** _getFuncNameFromFrame().
+*/
+static char *
+#ifdef __STDC__
+_getFuncNameFromFrame (
+ struct frame_info *frameInfo)
+#else
+_getFuncNameFromFrame (frameInfo)
+ struct frame_info *frameInfo;
+#endif
+{
+ char *funcName = (char *) NULL;
+
+ find_pc_partial_function (frameInfo->pc,
+ &funcName,
+ (CORE_ADDR *) NULL,
+ (CORE_ADDR *) NULL);
+ return funcName;
+} /* _getFuncNameFromFrame */
+
+
+/*
+** _tuiUpdateLocation_command().
+** Command to update the display with the current execution point
+*/
+static void
+#ifdef __STDC__
+_tuiUpdateLocation_command (
+ char *arg,
+ int fromTTY)
+#else
+_tuiUpdateLocation_command (arg, fromTTY)
+ char *arg;
+ int fromTTY;
+#endif
+{
+#ifndef TRY
+ extern void frame_command PARAMS ((char *, int));
+ frame_command ("0", FALSE);
+#else
+ struct frame_info *curFrame;
+
+ /* Obtain the current execution point */
+ if ((curFrame = get_current_frame ()) != (struct frame_info *) NULL)
+ {
+ struct frame_info *frame;
+ int curLevel = 0;
+
+ for (frame = get_prev_frame (curLevel);
+ (frame != (struct frame_info *) NULL && (frame != curFrame));
+ frame = get_prev_frame (frame))
+ curLevel++;
+
+ if (curFrame != (struct frame_info *) NULL)
+ print_frame_info (frame, curLevel, 0, 1);
+ }
+#endif
+
+ return;
+} /* _tuiUpdateLocation_command */
diff --git a/gdb/tui/tuiStack.h b/gdb/tui/tuiStack.h
new file mode 100644
index 00000000000..20e9a92c61c
--- /dev/null
+++ b/gdb/tui/tuiStack.h
@@ -0,0 +1,22 @@
+#ifndef _TUI_STACK_H
+#define _TUI_STACK_H
+/*
+** This header file supports
+*/
+
+extern void tuiSetLocatorInfo PARAMS ((char *, char *, int, Opaque, TuiLocatorElementPtr));
+extern void tuiUpdateLocatorFilename PARAMS ((char *));
+extern void tui_vUpdateLocatorFilename PARAMS ((va_list));
+extern void tuiUpdateLocatorInfoFromFrame
+ PARAMS ((struct frame_info *, TuiLocatorElementPtr));
+extern void tuiUpdateLocatorDisplay PARAMS ((struct frame_info *));
+extern void tuiSetLocatorContent PARAMS ((struct frame_info *));
+extern void tuiShowLocatorContent PARAMS ((void));
+extern void tuiClearLocatorContent PARAMS ((void));
+extern void tuiSwitchFilename PARAMS ((char *));
+extern void tuiShowFrameInfo PARAMS ((struct frame_info *));
+extern void tui_vShowFrameInfo PARAMS ((va_list));
+extern void tuiGetLocatorFilename PARAMS ((TuiGenWinInfoPtr, char **));
+
+
+#endif /*_TUI_STACK_H*/
diff --git a/gdb/tui/tuiWin.c b/gdb/tui/tuiWin.c
new file mode 100644
index 00000000000..45bb0f6a4e9
--- /dev/null
+++ b/gdb/tui/tuiWin.c
@@ -0,0 +1,1650 @@
+/*
+** tuiWin.c
+** This module contains procedures for handling tui window functions
+** like resize, scrolling, scrolling, changing focus, etc.
+**
+** Author: Susan B. Macchia
+*/
+
+
+#include <string.h>
+#include "defs.h"
+#include "command.h"
+#include "symtab.h"
+#include "breakpoint.h"
+#include "frame.h"
+
+#include "tui.h"
+#include "tuiData.h"
+#include "tuiGeneralWin.h"
+#include "tuiStack.h"
+#include "tuiSourceWin.h"
+#include "tuiDataWin.h"
+
+/*******************************
+** External Declarations
+********************************/
+extern void init_page_info ();
+
+/*******************************
+** Static Local Decls
+********************************/
+static void _makeVisibleWithNewHeight PARAMS ((TuiWinInfoPtr));
+static void _makeInvisibleAndSetNewHeight PARAMS ((TuiWinInfoPtr, int));
+static TuiStatus _tuiAdjustWinHeights PARAMS ((TuiWinInfoPtr, int));
+static int _newHeightOk PARAMS ((TuiWinInfoPtr, int));
+static void _tuiSetTabWidth_command PARAMS ((char *, int));
+static void _tuiRefreshAll_command PARAMS ((char *, int));
+static void _tuiSetWinHeight_command PARAMS ((char *, int));
+static void _tuiXDBsetWinHeight_command PARAMS ((char *, int));
+static void _tuiAllWindowsInfo PARAMS ((char *, int));
+static void _tuiSetFocus_command PARAMS ((char *, int));
+static void _tuiScrollForward_command PARAMS ((char *, int));
+static void _tuiScrollBackward_command PARAMS ((char *, int));
+static void _tuiScrollLeft_command PARAMS ((char *, int));
+static void _tuiScrollRight_command PARAMS ((char *, int));
+static void _parseScrollingArgs PARAMS ((char *, TuiWinInfoPtr *, int *));
+
+
+/***************************************
+** DEFINITIONS
+***************************************/
+#define WIN_HEIGHT_USAGE "Usage: winheight <win_name> [+ | -] <#lines>\n"
+#define XDBWIN_HEIGHT_USAGE "Usage: w <#lines>\n"
+#define FOCUS_USAGE "Usage: focus {<win> | next | prev}\n"
+
+/***************************************
+** PUBLIC FUNCTIONS
+***************************************/
+
+/*
+** _initialize_tuiWin().
+** Function to initialize gdb commands, for tui window manipulation.
+*/
+void
+_initialize_tuiWin ()
+{
+ if (tui_version)
+ {
+ add_com ("refresh", class_tui, _tuiRefreshAll_command,
+ "Refresh the terminal display.\n");
+ if (xdb_commands)
+ add_com_alias ("U", "refresh", class_tui, 0);
+ add_com ("tabset", class_tui, _tuiSetTabWidth_command,
+ "Set the width (in characters) of tab stops.\n\
+Usage: tabset <n>\n");
+ add_com ("winheight", class_tui, _tuiSetWinHeight_command,
+ "Set the height of a specified window.\n\
+Usage: winheight <win_name> [+ | -] <#lines>\n\
+Window names are:\n\
+src : the source window\n\
+cmd : the command window\n\
+asm : the disassembly window\n\
+regs : the register display\n");
+ add_com_alias ("wh", "winheight", class_tui, 0);
+ add_info ("win", _tuiAllWindowsInfo,
+ "List of all displayed windows.\n");
+ add_com ("focus", class_tui, _tuiSetFocus_command,
+ "Set focus to named window or next/prev window.\n\
+Usage: focus {<win> | next | prev}\n\
+Valid Window names are:\n\
+src : the source window\n\
+asm : the disassembly window\n\
+regs : the register display\n\
+cmd : the command window\n");
+ add_com_alias ("fs", "focus", class_tui, 0);
+ add_com ("+", class_tui, _tuiScrollForward_command,
+ "Scroll window forward.\nUsage: + [win] [n]\n");
+ add_com ("-", class_tui, _tuiScrollBackward_command,
+ "Scroll window backward.\nUsage: - [win] [n]\n");
+ add_com ("<", class_tui, _tuiScrollLeft_command,
+ "Scroll window forward.\nUsage: < [win] [n]\n");
+ add_com (">", class_tui, _tuiScrollRight_command,
+ "Scroll window backward.\nUsage: > [win] [n]\n");
+ if (xdb_commands)
+ add_com ("w", class_xdb, _tuiXDBsetWinHeight_command,
+ "XDB compatibility command for setting the height of a command window.\n\
+Usage: w <#lines>\n");
+ }
+
+ return;
+} /* _intialize_tuiWin */
+
+
+/*
+** tuiClearWinFocusFrom
+** Clear the logical focus from winInfo
+*/
+void
+#ifdef __STDC__
+tuiClearWinFocusFrom (
+ TuiWinInfoPtr winInfo)
+#else
+tuiClearWinFocusFrom (winInfo)
+ TuiWinInfoPtr winInfo;
+#endif
+{
+ if (m_winPtrNotNull (winInfo))
+ {
+ if (winInfo->generic.type != CMD_WIN)
+ unhighlightWin (winInfo);
+ tuiSetWinWithFocus ((TuiWinInfoPtr) NULL);
+ }
+
+ return;
+} /* tuiClearWinFocusFrom */
+
+
+/*
+** tuiClearWinFocus().
+** Clear the window that has focus.
+*/
+void
+#ifdef __STDC__
+tuiClearWinFocus (void)
+#else
+tuiClearWinFocus ()
+#endif
+{
+ tuiClearWinFocusFrom (tuiWinWithFocus ());
+
+ return;
+} /* tuiClearWinFocus */
+
+
+/*
+** tuiSetWinFocusTo
+** Set the logical focus to winInfo
+*/
+void
+#ifdef __STDC__
+tuiSetWinFocusTo (
+ TuiWinInfoPtr winInfo)
+#else
+tuiSetWinFocusTo (winInfo)
+ TuiWinInfoPtr winInfo;
+#endif
+{
+ if (m_winPtrNotNull (winInfo))
+ {
+ TuiWinInfoPtr winWithFocus = tuiWinWithFocus ();
+
+ if (m_winPtrNotNull (winWithFocus) &&
+ winWithFocus->generic.type != CMD_WIN)
+ unhighlightWin (winWithFocus);
+ tuiSetWinWithFocus (winInfo);
+ if (winInfo->generic.type != CMD_WIN)
+ highlightWin (winInfo);
+ }
+
+ return;
+} /* tuiSetWinFocusTo */
+
+
+char *
+#ifdef __STDC__
+tuiStrDup (
+ char *str)
+#else
+tuiStrDup (str)
+ char *str;
+#endif
+{
+ char *newStr = (char *) NULL;
+
+ if (str != (char *) NULL)
+ {
+ newStr = (char *) xmalloc (strlen (str) + 1);
+ strcpy (newStr, str);
+ }
+
+ return newStr;
+} /* tuiStrDup */
+
+
+/*
+** tuiScrollForward().
+*/
+void
+#ifdef __STDC__
+tuiScrollForward (
+ TuiWinInfoPtr winToScroll,
+ int numToScroll)
+#else
+tuiScrollForward (winToScroll, numToScroll)
+ TuiWinInfoPtr winToScroll;
+ int numToScroll;
+#endif
+{
+ if (winToScroll != cmdWin)
+ {
+ int _numToScroll = numToScroll;
+
+ if (numToScroll == 0)
+ _numToScroll = winToScroll->generic.height - 3;
+ /*
+ ** If we are scrolling the source or disassembly window, do a
+ ** "psuedo" scroll since not all of the source is in memory,
+ ** only what is in the viewport. If winToScroll is the
+ ** command window do nothing since the term should handle it.
+ */
+ if (winToScroll == srcWin)
+ tuiVerticalSourceScroll (FORWARD_SCROLL, _numToScroll);
+ else if (winToScroll == disassemWin)
+ tuiVerticalDisassemScroll (FORWARD_SCROLL, _numToScroll);
+ else if (winToScroll == dataWin)
+ tuiVerticalDataScroll (FORWARD_SCROLL, _numToScroll);
+ }
+
+ return;
+} /* tuiScrollForward */
+
+
+/*
+** tuiScrollBackward().
+*/
+void
+#ifdef __STDC__
+tuiScrollBackward (
+ TuiWinInfoPtr winToScroll,
+ int numToScroll)
+#else
+tuiScrollBackward (winToScroll, numToScroll)
+ TuiWinInfoPtr winToScroll;
+ int numToScroll;
+#endif
+{
+ if (winToScroll != cmdWin)
+ {
+ int _numToScroll = numToScroll;
+
+ if (numToScroll == 0)
+ _numToScroll = winToScroll->generic.height - 3;
+ /*
+ ** If we are scrolling the source or disassembly window, do a
+ ** "psuedo" scroll since not all of the source is in memory,
+ ** only what is in the viewport. If winToScroll is the
+ ** command window do nothing since the term should handle it.
+ */
+ if (winToScroll == srcWin)
+ tuiVerticalSourceScroll (BACKWARD_SCROLL, _numToScroll);
+ else if (winToScroll == disassemWin)
+ tuiVerticalDisassemScroll (BACKWARD_SCROLL, _numToScroll);
+ else if (winToScroll == dataWin)
+ tuiVerticalDataScroll (BACKWARD_SCROLL, _numToScroll);
+ }
+ return;
+} /* tuiScrollBackward */
+
+
+/*
+** tuiScrollLeft().
+*/
+void
+#ifdef __STDC__
+tuiScrollLeft (
+ TuiWinInfoPtr winToScroll,
+ int numToScroll)
+#else
+tuiScrollLeft (winToScroll, numToScroll)
+ TuiWinInfoPtr winToScroll;
+ int numToScroll;
+#endif
+{
+ if (winToScroll != cmdWin)
+ {
+ int _numToScroll = numToScroll;
+
+ if (_numToScroll == 0)
+ _numToScroll = 1;
+ /*
+ ** If we are scrolling the source or disassembly window, do a
+ ** "psuedo" scroll since not all of the source is in memory,
+ ** only what is in the viewport. If winToScroll is the
+ ** command window do nothing since the term should handle it.
+ */
+ if (winToScroll == srcWin || winToScroll == disassemWin)
+ tuiHorizontalSourceScroll (winToScroll, LEFT_SCROLL, _numToScroll);
+ }
+ return;
+} /* tuiScrollLeft */
+
+
+/*
+** tuiScrollRight().
+*/
+void
+#ifdef __STDC__
+tuiScrollRight (
+ TuiWinInfoPtr winToScroll,
+ int numToScroll)
+#else
+tuiScrollRight (winToScroll, numToScroll)
+ TuiWinInfoPtr winToScroll;
+ int numToScroll;
+#endif
+{
+ if (winToScroll != cmdWin)
+ {
+ int _numToScroll = numToScroll;
+
+ if (_numToScroll == 0)
+ _numToScroll = 1;
+ /*
+ ** If we are scrolling the source or disassembly window, do a
+ ** "psuedo" scroll since not all of the source is in memory,
+ ** only what is in the viewport. If winToScroll is the
+ ** command window do nothing since the term should handle it.
+ */
+ if (winToScroll == srcWin || winToScroll == disassemWin)
+ tuiHorizontalSourceScroll (winToScroll, RIGHT_SCROLL, _numToScroll);
+ }
+ return;
+} /* tuiScrollRight */
+
+
+/*
+** tui_vScroll().
+** Scroll a window. Arguments are passed through a va_list.
+*/
+void
+#ifdef __STDC__
+tui_vScroll (
+ va_list args)
+#else
+tui_vScroll (args)
+ va_list args;
+#endif
+{
+ TuiScrollDirection direction = va_arg (args, TuiScrollDirection);
+ TuiWinInfoPtr winToScroll = va_arg (args, TuiWinInfoPtr);
+ int numToScroll = va_arg (args, int);
+
+ switch (direction)
+ {
+ case FORWARD_SCROLL:
+ tuiScrollForward (winToScroll, numToScroll);
+ break;
+ case BACKWARD_SCROLL:
+ tuiScrollBackward (winToScroll, numToScroll);
+ break;
+ case LEFT_SCROLL:
+ tuiScrollLeft (winToScroll, numToScroll);
+ break;
+ case RIGHT_SCROLL:
+ tuiScrollRight (winToScroll, numToScroll);
+ break;
+ default:
+ break;
+ }
+
+ return;
+} /* tui_vScroll */
+
+
+/*
+** tuiRefreshAll().
+*/
+void
+#ifdef __STDC__
+tuiRefreshAll (void)
+#else
+tuiRefreshAll ()
+#endif
+{
+ TuiWinType type;
+
+ refreshAll (winList);
+ for (type = SRC_WIN; type < MAX_MAJOR_WINDOWS; type++)
+ {
+ if (winList[type]->generic.isVisible)
+ {
+ switch (type)
+ {
+ case SRC_WIN:
+ case DISASSEM_WIN:
+ tuiClearWin (&winList[type]->generic);
+ if (winList[type]->detail.sourceInfo.hasLocator)
+ tuiClearLocatorDisplay ();
+ tuiShowSourceContent (winList[type]);
+ checkAndDisplayHighlightIfNeeded (winList[type]);
+ tuiEraseExecInfoContent (winList[type]);
+ tuiUpdateExecInfo (winList[type]);
+ break;
+ case DATA_WIN:
+ tuiRefreshDataWin ();
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ tuiClearLocatorDisplay ();
+ tuiShowLocatorContent ();
+
+ return;
+} /* tuiRefreshAll */
+
+
+/*
+** tuiResizeAll().
+** Resize all the windows based on the the terminal size. This
+** function gets called from within the readline sinwinch handler.
+*/
+void
+#ifdef __STDC__
+tuiResizeAll (void)
+#else
+tuiResizeAll ()
+#endif
+{
+ int heightDiff, widthDiff;
+ extern int screenheight, screenwidth; /* in readline */
+
+ widthDiff = screenwidth - termWidth ();
+ heightDiff = screenheight - termHeight ();
+ if (heightDiff || widthDiff)
+ {
+ TuiLayoutType curLayout = currentLayout ();
+ TuiWinInfoPtr winWithFocus = tuiWinWithFocus ();
+ TuiWinInfoPtr firstWin, secondWin;
+ TuiGenWinInfoPtr locator = locatorWinInfoPtr ();
+ TuiWinType winType;
+ int i, newHeight, splitDiff, cmdSplitDiff, numWinsDisplayed = 2;
+
+ /* turn keypad off while we resize */
+ if (winWithFocus != cmdWin)
+ keypad (cmdWin->generic.handle, FALSE);
+ init_page_info ();
+ setTermHeightTo (screenheight);
+ setTermWidthTo (screenwidth);
+ if (curLayout == SRC_DISASSEM_COMMAND ||
+ curLayout == SRC_DATA_COMMAND || curLayout == DISASSEM_DATA_COMMAND)
+ numWinsDisplayed++;
+ splitDiff = heightDiff / numWinsDisplayed;
+ cmdSplitDiff = splitDiff;
+ if (heightDiff % numWinsDisplayed)
+ {
+ if (heightDiff < 0)
+ cmdSplitDiff--;
+ else
+ cmdSplitDiff++;
+ }
+ /* now adjust each window */
+ clear ();
+ refresh ();
+ switch (curLayout)
+ {
+ case SRC_COMMAND:
+ case DISASSEM_COMMAND:
+ firstWin = (TuiWinInfoPtr) (sourceWindows ())->list[0];
+ firstWin->generic.width += widthDiff;
+ locator->width += widthDiff;
+ /* check for invalid heights */
+ if (heightDiff == 0)
+ newHeight = firstWin->generic.height;
+ else if ((firstWin->generic.height + splitDiff) >=
+ (screenheight - MIN_CMD_WIN_HEIGHT - 1))
+ newHeight = screenheight - MIN_CMD_WIN_HEIGHT - 1;
+ else if ((firstWin->generic.height + splitDiff) <= 0)
+ newHeight = MIN_WIN_HEIGHT;
+ else
+ newHeight = firstWin->generic.height + splitDiff;
+
+ _makeInvisibleAndSetNewHeight (firstWin, newHeight);
+ cmdWin->generic.origin.y = locator->origin.y + 1;
+ cmdWin->generic.width += widthDiff;
+ newHeight = screenheight - cmdWin->generic.origin.y;
+ _makeInvisibleAndSetNewHeight (cmdWin, newHeight);
+ _makeVisibleWithNewHeight (firstWin);
+ _makeVisibleWithNewHeight (cmdWin);
+ if (firstWin->generic.contentSize <= 0)
+ tuiEraseSourceContent (firstWin, EMPTY_SOURCE_PROMPT);
+ break;
+ default:
+ if (curLayout == SRC_DISASSEM_COMMAND)
+ {
+ firstWin = srcWin;
+ firstWin->generic.width += widthDiff;
+ secondWin = disassemWin;
+ secondWin->generic.width += widthDiff;
+ }
+ else
+ {
+ firstWin = dataWin;
+ firstWin->generic.width += widthDiff;
+ secondWin = (TuiWinInfoPtr) (sourceWindows ())->list[0];
+ secondWin->generic.width += widthDiff;
+ }
+ /* Change the first window's height/width */
+ /* check for invalid heights */
+ if (heightDiff == 0)
+ newHeight = firstWin->generic.height;
+ else if ((firstWin->generic.height +
+ secondWin->generic.height + (splitDiff * 2)) >=
+ (screenheight - MIN_CMD_WIN_HEIGHT - 1))
+ newHeight = (screenheight - MIN_CMD_WIN_HEIGHT - 1) / 2;
+ else if ((firstWin->generic.height + splitDiff) <= 0)
+ newHeight = MIN_WIN_HEIGHT;
+ else
+ newHeight = firstWin->generic.height + splitDiff;
+ _makeInvisibleAndSetNewHeight (firstWin, newHeight);
+
+ if (firstWin == dataWin && widthDiff != 0)
+ firstWin->detail.dataDisplayInfo.regsColumnCount =
+ tuiCalculateRegsColumnCount (
+ firstWin->detail.dataDisplayInfo.regsDisplayType);
+ locator->width += widthDiff;
+
+ /* Change the second window's height/width */
+ /* check for invalid heights */
+ if (heightDiff == 0)
+ newHeight = secondWin->generic.height;
+ else if ((firstWin->generic.height +
+ secondWin->generic.height + (splitDiff * 2)) >=
+ (screenheight - MIN_CMD_WIN_HEIGHT - 1))
+ {
+ newHeight = screenheight - MIN_CMD_WIN_HEIGHT - 1;
+ if (newHeight % 2)
+ newHeight = (newHeight / 2) + 1;
+ else
+ newHeight /= 2;
+ }
+ else if ((secondWin->generic.height + splitDiff) <= 0)
+ newHeight = MIN_WIN_HEIGHT;
+ else
+ newHeight = secondWin->generic.height + splitDiff;
+ secondWin->generic.origin.y = firstWin->generic.height - 1;
+ _makeInvisibleAndSetNewHeight (secondWin, newHeight);
+
+ /* Change the command window's height/width */
+ cmdWin->generic.origin.y = locator->origin.y + 1;
+ _makeInvisibleAndSetNewHeight (
+ cmdWin, cmdWin->generic.height + cmdSplitDiff);
+ _makeVisibleWithNewHeight (firstWin);
+ _makeVisibleWithNewHeight (secondWin);
+ _makeVisibleWithNewHeight (cmdWin);
+ if (firstWin->generic.contentSize <= 0)
+ tuiEraseSourceContent (firstWin, EMPTY_SOURCE_PROMPT);
+ if (secondWin->generic.contentSize <= 0)
+ tuiEraseSourceContent (secondWin, EMPTY_SOURCE_PROMPT);
+ break;
+ }
+ /*
+ ** Now remove all invisible windows, and their content so that they get
+ ** created again when called for with the new size
+ */
+ for (winType = SRC_WIN; (winType < MAX_MAJOR_WINDOWS); winType++)
+ {
+ if (winType != CMD_WIN && m_winPtrNotNull (winList[winType]) &&
+ !winList[winType]->generic.isVisible)
+ {
+ freeWindow (winList[winType]);
+ winList[winType] = (TuiWinInfoPtr) NULL;
+ }
+ }
+ tuiSetWinResizedTo (TRUE);
+ /* turn keypad back on, unless focus is in the command window */
+ if (winWithFocus != cmdWin)
+ keypad (cmdWin->generic.handle, TRUE);
+ }
+ return;
+} /* tuiResizeAll */
+
+
+/*
+** tuiSigwinchHandler()
+** SIGWINCH signal handler for the tui. This signal handler is
+** always called, even when the readline package clears signals
+** because it is set as the old_sigwinch() (TUI only)
+*/
+void
+#ifdef __STDC__
+tuiSigwinchHandler (
+ int signal)
+#else
+tuiSigwinchHandler (signal)
+ int signal;
+#endif
+{
+ /*
+ ** Say that a resize was done so that the readline can do it
+ ** later when appropriate.
+ */
+ tuiSetWinResizedTo (TRUE);
+
+ return;
+} /* tuiSigwinchHandler */
+
+
+
+/*************************
+** STATIC LOCAL FUNCTIONS
+**************************/
+
+
+/*
+** _tuiScrollForward_command().
+*/
+static void
+#ifdef __STDC__
+_tuiScrollForward_command (
+ char *arg,
+ int fromTTY)
+#else
+_tuiScrollForward_command (arg, fromTTY)
+ char *arg;
+ int fromTTY;
+#endif
+{
+ int numToScroll = 1;
+ TuiWinInfoPtr winToScroll;
+
+ if (arg == (char *) NULL)
+ _parseScrollingArgs (arg, &winToScroll, (int *) NULL);
+ else
+ _parseScrollingArgs (arg, &winToScroll, &numToScroll);
+ tuiDo ((TuiOpaqueFuncPtr) tui_vScroll,
+ FORWARD_SCROLL,
+ winToScroll,
+ numToScroll);
+
+ return;
+} /* _tuiScrollForward_command */
+
+
+/*
+** _tuiScrollBackward_command().
+*/
+static void
+#ifdef __STDC__
+_tuiScrollBackward_command (
+ char *arg,
+ int fromTTY)
+#else
+_tuiScrollBackward_command (arg, fromTTY)
+ char *arg;
+ int fromTTY;
+#endif
+{
+ int numToScroll = 1;
+ TuiWinInfoPtr winToScroll;
+
+ if (arg == (char *) NULL)
+ _parseScrollingArgs (arg, &winToScroll, (int *) NULL);
+ else
+ _parseScrollingArgs (arg, &winToScroll, &numToScroll);
+ tuiDo ((TuiOpaqueFuncPtr) tui_vScroll,
+ BACKWARD_SCROLL,
+ winToScroll,
+ numToScroll);
+
+ return;
+} /* _tuiScrollBackward_command */
+
+
+/*
+** _tuiScrollLeft_command().
+*/
+static void
+#ifdef __STDC__
+_tuiScrollLeft_command (
+ char *arg,
+ int fromTTY)
+#else
+_tuiScrollLeft_command (arg, fromTTY)
+ char *arg;
+ int fromTTY;
+#endif
+{
+ int numToScroll;
+ TuiWinInfoPtr winToScroll;
+
+ _parseScrollingArgs (arg, &winToScroll, &numToScroll);
+ tuiDo ((TuiOpaqueFuncPtr) tui_vScroll,
+ LEFT_SCROLL,
+ winToScroll,
+ numToScroll);
+
+ return;
+} /* _tuiScrollLeft_command */
+
+
+/*
+** _tuiScrollRight_command().
+*/
+static void
+#ifdef __STDC__
+_tuiScrollRight_command (
+ char *arg,
+ int fromTTY)
+#else
+_tuiScrollRight_command (arg, fromTTY)
+ char *arg;
+ int fromTTY;
+#endif
+{
+ int numToScroll;
+ TuiWinInfoPtr winToScroll;
+
+ _parseScrollingArgs (arg, &winToScroll, &numToScroll);
+ tuiDo ((TuiOpaqueFuncPtr) tui_vScroll,
+ RIGHT_SCROLL,
+ winToScroll,
+ numToScroll);
+
+ return;
+} /* _tuiScrollRight_command */
+
+
+/*
+** _tuiSetFocus().
+** Set focus to the window named by 'arg'
+*/
+static void
+#ifdef __STDC__
+_tuiSetFocus (
+ char *arg,
+ int fromTTY)
+#else
+_tuiSetFocus (arg, fromTTY)
+ char *arg;
+ int fromTTY;
+#endif
+{
+ if (arg != (char *) NULL)
+ {
+ char *bufPtr = (char *) tuiStrDup (arg);
+ int i;
+ TuiWinInfoPtr winInfo = (TuiWinInfoPtr) NULL;
+
+ for (i = 0; (i < strlen (bufPtr)); i++)
+ bufPtr[i] = toupper (arg[i]);
+
+ if (subsetCompare (bufPtr, "NEXT"))
+ winInfo = tuiNextWin (tuiWinWithFocus ());
+ else if (subsetCompare (bufPtr, "PREV"))
+ winInfo = tuiPrevWin (tuiWinWithFocus ());
+ else
+ winInfo = partialWinByName (bufPtr);
+
+ if (winInfo == (TuiWinInfoPtr) NULL || !winInfo->generic.isVisible)
+ warning ("Invalid window specified. \n\
+The window name specified must be valid and visible.\n");
+ else
+ {
+ tuiSetWinFocusTo (winInfo);
+ keypad (cmdWin->generic.handle, (winInfo != cmdWin));
+ }
+
+ if (dataWin->generic.isVisible)
+ tuiRefreshDataWin ();
+ tuiFree (bufPtr);
+ printf_filtered ("Focus set to %s window.\n",
+ winName ((TuiGenWinInfoPtr) tuiWinWithFocus ()));
+ }
+ else
+ warning ("Incorrect Number of Arguments.\n%s", FOCUS_USAGE);
+
+ return;
+} /* _tuiSetFocus */
+
+
+/*
+** _tui_vSetFocus()
+*/
+static void
+#ifdef __STDC__
+_tui_vSetFocus (
+ va_list args)
+#else
+_tui_vSetFocus (args)
+ va_list args;
+#endif
+{
+ char *arg = va_arg (args, char *);
+ int fromTTY = va_arg (args, int);
+
+ _tuiSetFocus (arg, fromTTY);
+
+ return;
+} /* tui_vSetFocus */
+
+
+/*
+** _tuiSetFocus_command()
+*/
+static void
+#ifdef __STDC__
+_tuiSetFocus_command (
+ char *arg,
+ int fromTTY)
+#else
+_tuiSetFocus_command (arg, fromTTY)
+ char *arg;
+ int fromTTY;
+#endif
+{
+ tuiDo ((TuiOpaqueFuncPtr) _tui_vSetFocus, arg, fromTTY);
+
+ return;
+} /* tui_SetFocus */
+
+
+/*
+** _tuiAllWindowsInfo().
+*/
+static void
+#ifdef __STDC__
+_tuiAllWindowsInfo (
+ char *arg,
+ int fromTTY)
+#else
+_tuiAllWindowsInfo (arg, fromTTY)
+ char *arg;
+ int fromTTY;
+#endif
+{
+ TuiWinType type;
+ TuiWinInfoPtr winWithFocus = tuiWinWithFocus ();
+
+ for (type = SRC_WIN; (type < MAX_MAJOR_WINDOWS); type++)
+ if (winList[type]->generic.isVisible)
+ {
+ if (winWithFocus == winList[type])
+ printf_filtered (" %s\t(%d lines) <has focus>\n",
+ winName (&winList[type]->generic),
+ winList[type]->generic.height);
+ else
+ printf_filtered (" %s\t(%d lines)\n",
+ winName (&winList[type]->generic),
+ winList[type]->generic.height);
+ }
+
+ return;
+} /* _tuiAllWindowsInfo */
+
+
+/*
+** _tuiRefreshAll_command().
+*/
+static void
+#ifdef __STDC__
+_tuiRefreshAll_command (
+ char *arg,
+ int fromTTY)
+#else
+_tuiRefreshAll_command (arg, fromTTY)
+ char *arg;
+ int fromTTY;
+#endif
+{
+ tuiDo ((TuiOpaqueFuncPtr) tuiRefreshAll);
+}
+
+
+/*
+** _tuiSetWinTabWidth_command().
+** Set the height of the specified window.
+*/
+static void
+#ifdef __STDC__
+_tuiSetTabWidth_command (
+ char *arg,
+ int fromTTY)
+#else
+_tuiSetTabWidth_command (arg, fromTTY)
+ char *arg;
+ int fromTTY;
+#endif
+{
+ if (arg != (char *) NULL)
+ {
+ int ts;
+
+ ts = atoi (arg);
+ if (ts > 0)
+ tuiSetDefaultTabLen (ts);
+ else
+ warning ("Tab widths greater than 0 must be specified.\n");
+ }
+
+ return;
+} /* _tuiSetTabWidth_command */
+
+
+/*
+** _tuiSetWinHeight().
+** Set the height of the specified window.
+*/
+static void
+#ifdef __STDC__
+_tuiSetWinHeight (
+ char *arg,
+ int fromTTY)
+#else
+_tuiSetWinHeight (arg, fromTTY)
+ char *arg;
+ int fromTTY;
+#endif
+{
+ if (arg != (char *) NULL)
+ {
+ char *buf = tuiStrDup (arg);
+ char *bufPtr = buf;
+ char *wname = (char *) NULL;
+ int newHeight, i;
+ TuiWinInfoPtr winInfo;
+
+ wname = bufPtr;
+ bufPtr = strchr (bufPtr, ' ');
+ if (bufPtr != (char *) NULL)
+ {
+ *bufPtr = (char) 0;
+
+ /*
+ ** Validate the window name
+ */
+ for (i = 0; i < strlen (wname); i++)
+ wname[i] = toupper (wname[i]);
+ winInfo = partialWinByName (wname);
+
+ if (winInfo == (TuiWinInfoPtr) NULL || !winInfo->generic.isVisible)
+ warning ("Invalid window specified. \n\
+The window name specified must be valid and visible.\n");
+ else
+ {
+ /* Process the size */
+ while (*(++bufPtr) == ' ')
+ ;
+
+ if (*bufPtr != (char) 0)
+ {
+ int negate = FALSE;
+ int fixedSize = TRUE;
+ int inputNo;;
+
+ if (*bufPtr == '+' || *bufPtr == '-')
+ {
+ if (*bufPtr == '-')
+ negate = TRUE;
+ fixedSize = FALSE;
+ bufPtr++;
+ }
+ inputNo = atoi (bufPtr);
+ if (inputNo > 0)
+ {
+ if (negate)
+ inputNo *= (-1);
+ if (fixedSize)
+ newHeight = inputNo;
+ else
+ newHeight = winInfo->generic.height + inputNo;
+ /*
+ ** Now change the window's height, and adjust all
+ ** other windows around it
+ */
+ if (_tuiAdjustWinHeights (winInfo,
+ newHeight) == TUI_FAILURE)
+ warning ("Invalid window height specified.\n%s",
+ WIN_HEIGHT_USAGE);
+ else
+ init_page_info ();
+ }
+ else
+ warning ("Invalid window height specified.\n%s",
+ WIN_HEIGHT_USAGE);
+ }
+ }
+ }
+ else
+ printf_filtered (WIN_HEIGHT_USAGE);
+
+ if (buf != (char *) NULL)
+ tuiFree (buf);
+ }
+ else
+ printf_filtered (WIN_HEIGHT_USAGE);
+
+ return;
+} /* _tuiSetWinHeight */
+
+
+/*
+** _tui_vSetWinHeight().
+** Set the height of the specified window, with va_list.
+*/
+static void
+#ifdef __STDC__
+_tui_vSetWinHeight (
+ va_list args)
+#else
+_tui_vSetWinHeight (args)
+ va_list args;
+#endif
+{
+ char *arg = va_arg (args, char *);
+ int fromTTY = va_arg (args, int);
+
+ _tuiSetWinHeight (arg, fromTTY);
+
+ return;
+} /* _tui_vSetWinHeight */
+
+
+/*
+** _tuiSetWinHeight_command().
+** Set the height of the specified window, with va_list.
+*/
+static void
+#ifdef __STDC__
+_tuiSetWinHeight_command (
+ char *arg,
+ int fromTTY)
+#else
+_tuiSetWinHeight_command (arg, fromTTY)
+ char *arg;
+ int fromTTY;
+#endif
+{
+ tuiDo ((TuiOpaqueFuncPtr) _tui_vSetWinHeight, arg, fromTTY);
+
+ return;
+} /* _tuiSetWinHeight_command */
+
+
+/*
+** _tuiXDBsetWinHeight().
+** XDB Compatibility command for setting the window height. This will
+** increase or decrease the command window by the specified amount.
+*/
+static void
+#ifdef __STDC__
+_tuiXDBsetWinHeight (
+ char *arg,
+ int fromTTY)
+#else
+_tuiXDBsetWinHeight (arg, fromTTY)
+ char *arg;
+ int fromTTY;
+#endif
+{
+ if (arg != (char *) NULL)
+ {
+ int inputNo = atoi (arg);
+
+ if (inputNo > 0)
+ { /* Add 1 for the locator */
+ int newHeight = termHeight () - (inputNo + 1);
+
+ if (!_newHeightOk (winList[CMD_WIN], newHeight) ||
+ _tuiAdjustWinHeights (winList[CMD_WIN],
+ newHeight) == TUI_FAILURE)
+ warning ("Invalid window height specified.\n%s",
+ XDBWIN_HEIGHT_USAGE);
+ }
+ else
+ warning ("Invalid window height specified.\n%s",
+ XDBWIN_HEIGHT_USAGE);
+ }
+ else
+ warning ("Invalid window height specified.\n%s", XDBWIN_HEIGHT_USAGE);
+
+ return;
+} /* _tuiXDBsetWinHeight */
+
+
+/*
+** _tui_vXDBsetWinHeight().
+** Set the height of the specified window, with va_list.
+*/
+static void
+#ifdef __STDC__
+_tui_vXDBsetWinHeight (
+ va_list args)
+#else
+_tui_vXDBsetWinHeight (args)
+ va_list args;
+#endif
+{
+ char *arg = va_arg (args, char *);
+ int fromTTY = va_arg (args, int);
+
+ _tuiXDBsetWinHeight (arg, fromTTY);
+
+ return;
+} /* _tui_vXDBsetWinHeight */
+
+
+/*
+** _tuiSetWinHeight_command().
+** Set the height of the specified window, with va_list.
+*/
+static void
+#ifdef __STDC__
+_tuiXDBsetWinHeight_command (
+ char *arg,
+ int fromTTY)
+#else
+_tuiXDBsetWinHeight_command (arg, fromTTY)
+ char *arg;
+ int fromTTY;
+#endif
+{
+ tuiDo ((TuiOpaqueFuncPtr) _tui_vXDBsetWinHeight, arg, fromTTY);
+
+ return;
+} /* _tuiXDBsetWinHeight_command */
+
+
+/*
+** _tuiAdjustWinHeights().
+** Function to adjust all window heights around the primary
+*/
+static TuiStatus
+#ifdef __STDC__
+_tuiAdjustWinHeights (
+ TuiWinInfoPtr primaryWinInfo,
+ int newHeight)
+#else
+_tuiAdjustWinHeights (primaryWinInfo, newHeight)
+ TuiWinInfoPtr primaryWinInfo;
+ int newHeight;
+#endif
+{
+ TuiStatus status = TUI_FAILURE;
+
+ if (_newHeightOk (primaryWinInfo, newHeight))
+ {
+ status = TUI_SUCCESS;
+ if (newHeight != primaryWinInfo->generic.height)
+ {
+ int i, diff;
+ TuiWinInfoPtr winInfo;
+ TuiGenWinInfoPtr locator = locatorWinInfoPtr ();
+ TuiLayoutType curLayout = currentLayout ();
+
+ diff = (newHeight - primaryWinInfo->generic.height) * (-1);
+ if (curLayout == SRC_COMMAND || curLayout == DISASSEM_COMMAND)
+ {
+ TuiWinInfoPtr srcWinInfo;
+
+ _makeInvisibleAndSetNewHeight (primaryWinInfo, newHeight);
+ if (primaryWinInfo->generic.type == CMD_WIN)
+ {
+ winInfo = (TuiWinInfoPtr) (sourceWindows ())->list[0];
+ srcWinInfo = winInfo;
+ }
+ else
+ {
+ winInfo = winList[CMD_WIN];
+ srcWinInfo = primaryWinInfo;
+ }
+ _makeInvisibleAndSetNewHeight (winInfo,
+ winInfo->generic.height + diff);
+ cmdWin->generic.origin.y = locator->origin.y + 1;
+ _makeVisibleWithNewHeight (winInfo);
+ _makeVisibleWithNewHeight (primaryWinInfo);
+ if (srcWinInfo->generic.contentSize <= 0)
+ tuiEraseSourceContent (srcWinInfo, EMPTY_SOURCE_PROMPT);
+ }
+ else
+ {
+ TuiWinInfoPtr firstWin, secondWin;
+
+ if (curLayout == SRC_DISASSEM_COMMAND)
+ {
+ firstWin = srcWin;
+ secondWin = disassemWin;
+ }
+ else
+ {
+ firstWin = dataWin;
+ secondWin = (TuiWinInfoPtr) (sourceWindows ())->list[0];
+ }
+ if (primaryWinInfo == cmdWin)
+ { /*
+ ** Split the change in height accross the 1st & 2nd windows
+ ** adjusting them as well.
+ */
+ int firstSplitDiff = diff / 2; /* subtract the locator */
+ int secondSplitDiff = firstSplitDiff;
+
+ if (diff % 2)
+ {
+ if (firstWin->generic.height >
+ secondWin->generic.height)
+ if (diff < 0)
+ firstSplitDiff--;
+ else
+ firstSplitDiff++;
+ else
+ {
+ if (diff < 0)
+ secondSplitDiff--;
+ else
+ secondSplitDiff++;
+ }
+ }
+ /* make sure that the minimum hieghts are honored */
+ while ((firstWin->generic.height + firstSplitDiff) < 3)
+ {
+ firstSplitDiff++;
+ secondSplitDiff--;
+ }
+ while ((secondWin->generic.height + secondSplitDiff) < 3)
+ {
+ secondSplitDiff++;
+ firstSplitDiff--;
+ }
+ _makeInvisibleAndSetNewHeight (
+ firstWin,
+ firstWin->generic.height + firstSplitDiff);
+ secondWin->generic.origin.y = firstWin->generic.height - 1;
+ _makeInvisibleAndSetNewHeight (
+ secondWin, secondWin->generic.height + secondSplitDiff);
+ cmdWin->generic.origin.y = locator->origin.y + 1;
+ _makeInvisibleAndSetNewHeight (cmdWin, newHeight);
+ }
+ else
+ {
+ if ((cmdWin->generic.height + diff) < 1)
+ { /*
+ ** If there is no way to increase the command window
+ ** take real estate from the 1st or 2nd window.
+ */
+ if ((cmdWin->generic.height + diff) < 1)
+ {
+ int i;
+ for (i = cmdWin->generic.height + diff;
+ (i < 1); i++)
+ if (primaryWinInfo == firstWin)
+ secondWin->generic.height--;
+ else
+ firstWin->generic.height--;
+ }
+ }
+ if (primaryWinInfo == firstWin)
+ _makeInvisibleAndSetNewHeight (firstWin, newHeight);
+ else
+ _makeInvisibleAndSetNewHeight (
+ firstWin,
+ firstWin->generic.height);
+ secondWin->generic.origin.y = firstWin->generic.height - 1;
+ if (primaryWinInfo == secondWin)
+ _makeInvisibleAndSetNewHeight (secondWin, newHeight);
+ else
+ _makeInvisibleAndSetNewHeight (
+ secondWin, secondWin->generic.height);
+ cmdWin->generic.origin.y = locator->origin.y + 1;
+ if ((cmdWin->generic.height + diff) < 1)
+ _makeInvisibleAndSetNewHeight (cmdWin, 1);
+ else
+ _makeInvisibleAndSetNewHeight (
+ cmdWin, cmdWin->generic.height + diff);
+ }
+ _makeVisibleWithNewHeight (cmdWin);
+ _makeVisibleWithNewHeight (secondWin);
+ _makeVisibleWithNewHeight (firstWin);
+ if (firstWin->generic.contentSize <= 0)
+ tuiEraseSourceContent (firstWin, EMPTY_SOURCE_PROMPT);
+ if (secondWin->generic.contentSize <= 0)
+ tuiEraseSourceContent (secondWin, EMPTY_SOURCE_PROMPT);
+ }
+ }
+ }
+
+ return status;
+} /* _tuiAdjustWinHeights */
+
+
+/*
+** _makeInvisibleAndSetNewHeight().
+** Function make the target window (and auxillary windows associated
+** with the targer) invisible, and set the new height and location.
+*/
+static void
+#ifdef __STDC__
+_makeInvisibleAndSetNewHeight (
+ TuiWinInfoPtr winInfo,
+ int height)
+#else
+_makeInvisibleAndSetNewHeight (winInfo, height)
+ TuiWinInfoPtr winInfo;
+ int height;
+#endif
+{
+ int i;
+ struct symtab *s;
+ TuiGenWinInfoPtr genWinInfo;
+
+
+ m_beInvisible (&winInfo->generic);
+ winInfo->generic.height = height;
+ if (height > 1)
+ winInfo->generic.viewportHeight = height - 1;
+ else
+ winInfo->generic.viewportHeight = height;
+ if (winInfo != cmdWin)
+ winInfo->generic.viewportHeight--;
+
+ /* Now deal with the auxillary windows associated with winInfo */
+ switch (winInfo->generic.type)
+ {
+ case SRC_WIN:
+ case DISASSEM_WIN:
+ genWinInfo = winInfo->detail.sourceInfo.executionInfo;
+ m_beInvisible (genWinInfo);
+ genWinInfo->height = height;
+ genWinInfo->origin.y = winInfo->generic.origin.y;
+ if (height > 1)
+ genWinInfo->viewportHeight = height - 1;
+ else
+ genWinInfo->viewportHeight = height;
+ if (winInfo != cmdWin)
+ genWinInfo->viewportHeight--;
+
+ if (m_hasLocator (winInfo))
+ {
+ genWinInfo = locatorWinInfoPtr ();
+ m_beInvisible (genWinInfo);
+ genWinInfo->origin.y = winInfo->generic.origin.y + height;
+ }
+ break;
+ case DATA_WIN:
+ /* delete all data item windows */
+ for (i = 0; i < winInfo->generic.contentSize; i++)
+ {
+ genWinInfo = (TuiGenWinInfoPtr) & ((TuiWinElementPtr)
+ winInfo->generic.content[i])->whichElement.dataWindow;
+ tuiDelwin (genWinInfo->handle);
+ genWinInfo->handle = (WINDOW *) NULL;
+ }
+ break;
+ default:
+ break;
+ }
+
+ return;
+} /* _makeInvisibleAndSetNewHeight */
+
+
+/*
+** _makeVisibleWithNewHeight().
+** Function to make the windows with new heights visible.
+** This means re-creating the windows' content since the window
+** had to be destroyed to be made invisible.
+*/
+static void
+#ifdef __STDC__
+_makeVisibleWithNewHeight (
+ TuiWinInfoPtr winInfo)
+#else
+_makeVisibleWithNewHeight (winInfo)
+ TuiWinInfoPtr winInfo;
+#endif
+{
+ int i;
+ struct symtab *s;
+
+ m_beVisible (&winInfo->generic);
+ checkAndDisplayHighlightIfNeeded (winInfo);
+ switch (winInfo->generic.type)
+ {
+ case SRC_WIN:
+ case DISASSEM_WIN:
+ freeWinContent (winInfo->detail.sourceInfo.executionInfo);
+ m_beVisible (winInfo->detail.sourceInfo.executionInfo);
+ if (winInfo->generic.content != (OpaquePtr) NULL)
+ {
+ TuiLineOrAddress lineOrAddr;
+
+ if (winInfo->generic.type == SRC_WIN)
+ lineOrAddr.lineNo =
+ winInfo->detail.sourceInfo.startLineOrAddr.lineNo;
+ else
+ lineOrAddr.addr =
+ winInfo->detail.sourceInfo.startLineOrAddr.addr;
+ freeWinContent (&winInfo->generic);
+ tuiUpdateSourceWindow (winInfo,
+ current_source_symtab,
+ ((winInfo->generic.type == SRC_WIN) ?
+ (Opaque) lineOrAddr.lineNo :
+ lineOrAddr.addr),
+ TRUE);
+ }
+ else if (selected_frame != (struct frame_info *) NULL)
+ {
+ Opaque line = 0;
+ extern int current_source_line;
+
+ s = find_pc_symtab (selected_frame->pc);
+ if (winInfo->generic.type == SRC_WIN)
+ line = (Opaque) current_source_line;
+ else
+ line = (Opaque) find_line_pc (s, current_source_line);
+ tuiUpdateSourceWindow (winInfo, s, line, TRUE);
+ }
+ if (m_hasLocator (winInfo))
+ {
+ m_beVisible (locatorWinInfoPtr ());
+ tuiClearLocatorDisplay ();
+ tuiShowLocatorContent ();
+ }
+ break;
+ case DATA_WIN:
+ tuiDisplayAllData ();
+ break;
+ case CMD_WIN:
+ winInfo->detail.commandInfo.curLine = 0;
+ winInfo->detail.commandInfo.curch = 0;
+ wmove (winInfo->generic.handle,
+ winInfo->detail.commandInfo.curLine,
+ winInfo->detail.commandInfo.curch);
+ break;
+ default:
+ break;
+ }
+
+ return;
+} /* _makeVisibleWithNewHeight */
+
+
+static int
+#ifdef __STDC__
+_newHeightOk (
+ TuiWinInfoPtr primaryWinInfo,
+ int newHeight)
+#else
+_newHeightOk (primaryWinInfo, newHeight)
+ TuiWinInfoPtr primaryWinInfo;
+ int newHeight;
+#endif
+{
+ int ok = (newHeight < termHeight ());
+
+ if (ok)
+ {
+ int diff, curHeight;
+ TuiLayoutType curLayout = currentLayout ();
+
+ diff = (newHeight - primaryWinInfo->generic.height) * (-1);
+ if (curLayout == SRC_COMMAND || curLayout == DISASSEM_COMMAND)
+ {
+ ok = ((primaryWinInfo->generic.type == CMD_WIN &&
+ newHeight <= (termHeight () - 4) &&
+ newHeight >= MIN_CMD_WIN_HEIGHT) ||
+ (primaryWinInfo->generic.type != CMD_WIN &&
+ newHeight <= (termHeight () - 2) &&
+ newHeight >= MIN_WIN_HEIGHT));
+ if (ok)
+ { /* check the total height */
+ TuiWinInfoPtr winInfo;
+
+ if (primaryWinInfo == cmdWin)
+ winInfo = (TuiWinInfoPtr) (sourceWindows ())->list[0];
+ else
+ winInfo = cmdWin;
+ ok = ((newHeight +
+ (winInfo->generic.height + diff)) <= termHeight ());
+ }
+ }
+ else
+ {
+ int curTotalHeight, totalHeight, minHeight;
+ TuiWinInfoPtr firstWin, secondWin;
+
+ if (curLayout == SRC_DISASSEM_COMMAND)
+ {
+ firstWin = srcWin;
+ secondWin = disassemWin;
+ }
+ else
+ {
+ firstWin = dataWin;
+ secondWin = (TuiWinInfoPtr) (sourceWindows ())->list[0];
+ }
+ /*
+ ** We could simply add all the heights to obtain the same result
+ ** but below is more explicit since we subtract 1 for the
+ ** line that the first and second windows share, and add one
+ ** for the locator.
+ */
+ curTotalHeight =
+ (firstWin->generic.height + secondWin->generic.height - 1)
+ + cmdWin->generic.height + 1 /*locator*/ ;
+ if (primaryWinInfo == cmdWin)
+ {
+ /* locator included since first & second win share a line */
+ ok = ((firstWin->generic.height +
+ secondWin->generic.height + diff) >=
+ (MIN_WIN_HEIGHT * 2) &&
+ newHeight >= MIN_CMD_WIN_HEIGHT);
+ if (ok)
+ {
+ totalHeight = newHeight + (firstWin->generic.height +
+ secondWin->generic.height + diff);
+ minHeight = MIN_CMD_WIN_HEIGHT;
+ }
+ }
+ else
+ {
+ minHeight = MIN_WIN_HEIGHT;
+ /*
+ ** First see if we can increase/decrease the command
+ ** window. And make sure that the command window is
+ ** at least 1 line
+ */
+ ok = ((cmdWin->generic.height + diff) > 0);
+ if (!ok)
+ { /*
+ ** Looks like we have to increase/decrease one of
+ ** the other windows
+ */
+ if (primaryWinInfo == firstWin)
+ ok = (secondWin->generic.height + diff) >= minHeight;
+ else
+ ok = (firstWin->generic.height + diff) >= minHeight;
+ }
+ if (ok)
+ {
+ if (primaryWinInfo == firstWin)
+ totalHeight = newHeight +
+ secondWin->generic.height +
+ cmdWin->generic.height + diff;
+ else
+ totalHeight = newHeight +
+ firstWin->generic.height +
+ cmdWin->generic.height + diff;
+ }
+ }
+ /*
+ ** Now make sure that the proposed total height doesn't exceed
+ ** the old total height.
+ */
+ if (ok)
+ ok = (newHeight >= minHeight && totalHeight <= curTotalHeight);
+ }
+ }
+
+ return ok;
+} /* _newHeightOk */
+
+
+/*
+** _parseScrollingArgs().
+*/
+static void
+#ifdef __STDC__
+_parseScrollingArgs (
+ char *arg,
+ TuiWinInfoPtr * winToScroll,
+ int *numToScroll)
+#else
+_parseScrollingArgs (arg, winToScroll, numToScroll)
+ char *arg;
+ TuiWinInfoPtr *winToScroll;
+ int *numToScroll;
+#endif
+{
+ if (numToScroll)
+ *numToScroll = 0;
+ *winToScroll = tuiWinWithFocus ();
+
+ /*
+ ** First set up the default window to scroll, in case there is no
+ ** window name arg
+ */
+ if (arg != (char *) NULL)
+ {
+ char *buf, *bufPtr;
+
+ /* process the number of lines to scroll */
+ buf = bufPtr = tuiStrDup (arg);
+ if (isdigit (*bufPtr))
+ {
+ char *numStr;
+
+ numStr = bufPtr;
+ bufPtr = strchr (bufPtr, ' ');
+ if (bufPtr != (char *) NULL)
+ {
+ *bufPtr = (char) 0;
+ if (numToScroll)
+ *numToScroll = atoi (numStr);
+ bufPtr++;
+ }
+ else if (numToScroll)
+ *numToScroll = atoi (numStr);
+ }
+
+ /* process the window name if one is specified */
+ if (bufPtr != (char *) NULL)
+ {
+ char *wname;
+ int i;
+
+ if (*bufPtr == ' ')
+ while (*(++bufPtr) == ' ')
+ ;
+
+ if (*bufPtr != (char) 0)
+ wname = bufPtr;
+
+ /* Validate the window name */
+ for (i = 0; i < strlen (wname); i++)
+ wname[i] = toupper (wname[i]);
+ *winToScroll = partialWinByName (wname);
+
+ if (*winToScroll == (TuiWinInfoPtr) NULL ||
+ !(*winToScroll)->generic.isVisible)
+ warning ("Invalid window specified. \n\
+The window name specified must be valid and visible.\n");
+ else if (*winToScroll == cmdWin)
+ *winToScroll = (TuiWinInfoPtr) (sourceWindows ())->list[0];
+ }
+ tuiFree (buf);
+ }
+
+ return;
+} /* _parseScrollingArgs */
diff --git a/gdb/tui/tuiWin.h b/gdb/tui/tuiWin.h
new file mode 100644
index 00000000000..cb8455dd8e0
--- /dev/null
+++ b/gdb/tui/tuiWin.h
@@ -0,0 +1,28 @@
+#ifndef _TUI_WIN_H
+#define _TUI_WIN_H
+/*
+** This header file supports
+*/
+
+/*****************************************
+** TYPE DEFINITIONS **
+******************************************/
+
+
+
+/*****************************************
+** PUBLIC FUNCTION EXTERNAL DECLS **
+******************************************/
+extern void tuiScrollForward PARAMS ((TuiWinInfoPtr, int));
+extern void tuiScrollBackward PARAMS ((TuiWinInfoPtr, int));
+extern void tuiScrollLeft PARAMS ((TuiWinInfoPtr, int));
+extern void tuiScrollRight PARAMS ((TuiWinInfoPtr, int));
+extern void tui_vScroll PARAMS ((va_list));
+extern void tuiSetWinFocusTo PARAMS ((TuiWinInfoPtr));
+extern void tuiClearWinFocusFrom PARAMS ((TuiWinInfoPtr));
+extern void tuiClearWinFocus PARAMS ((void));
+extern void tuiResizeAll PARAMS ((void));
+extern void tuiRefreshAll PARAMS ((void));
+extern void tuiSigwinchHandler PARAMS ((int));
+
+#endif /*_TUI_WIN_H*/
diff --git a/gdb/typeprint.c b/gdb/typeprint.c
new file mode 100644
index 00000000000..1a4877befb3
--- /dev/null
+++ b/gdb/typeprint.c
@@ -0,0 +1,321 @@
+/* Language independent support for printing types for GDB, the GNU debugger.
+ Copyright 1986, 88, 89, 91, 92, 93, 1998 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 "gdb_string.h"
+#include <errno.h>
+
+/* For real-type printing in whatis_exp() */
+extern int objectprint; /* Controls looking up an object's derived type
+ using what we find in its vtables. */
+
+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;
+ GDB_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_ptr val;
+ register struct cleanup *old_chain = NULL;
+ struct type * real_type = NULL;
+ int full = 0;
+ int top = -1;
+ int using_enc = 0;
+
+ if (exp)
+ {
+ expr = parse_expression (exp);
+ old_chain = make_cleanup ((make_cleanup_func) free_current_contents,
+ &expr);
+ val = evaluate_type (expr);
+ }
+ else
+ val = access_value_history (0);
+
+ real_type = value_rtti_type (val, &full, &top, &using_enc);
+
+ printf_filtered ("type = ");
+
+ if (real_type && objectprint)
+ printf_filtered ("/* real type = %s%s */\n",
+ TYPE_NAME (real_type),
+ full ? "" : " (incomplete object)");
+ /* FIXME: maybe better to use type_print (real_type, "", gdb_stdout, -1); */
+
+ type_print (VALUE_TYPE (val), "", gdb_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 ((make_cleanup_func) free_current_contents,
+ &expr);
+ type = ptype_eval (expr);
+ if (type != NULL)
+ {
+ /* User did "ptype <typename>" */
+ printf_filtered ("type = ");
+ type_print (type, "", gdb_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;
+ GDB_FILE *stream;
+{
+ unsigned int i;
+ unsigned len;
+
+ CHECK_TYPEDEF (type);
+
+ 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_RANGE:
+ print_type_scalar (TYPE_TARGET_TYPE (type), val, stream);
+ return;
+
+ 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_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.");
+ }
+ gdb_flush (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_ptr val;
+ register struct type *type;
+ register struct cleanup *old_chain;
+ struct expression *expr;
+
+ if (typename != NULL)
+ {
+ expr = parse_expression (typename);
+ old_chain = make_cleanup ((make_cleanup_func) 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 STRUCT-TAG\"\n\
+or \"class CLASS-NAME\" or \"union UNION-TAG\" or \"enum ENUM-TAG\".\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/gdb/typeprint.h b/gdb/typeprint.h
new file mode 100644
index 00000000000..be4d81a3cb1
--- /dev/null
+++ b/gdb/typeprint.h
@@ -0,0 +1,25 @@
+/* Language independent support for printing types for GDB, the GNU debugger.
+ Copyright 1986, 1988, 1989, 1991, 1992, 1993, 1999
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+void
+print_type_scalar PARAMS ((struct type *type, LONGEST, GDB_FILE *));
+
+void
+c_type_print_varspec_suffix PARAMS ((struct type *, GDB_FILE *, int, int, int));
diff --git a/gdb/ultra3-nat.c b/gdb/ultra3-nat.c
new file mode 100644
index 00000000000..2b84cdd8942
--- /dev/null
+++ b/gdb/ultra3-nat.c
@@ -0,0 +1,329 @@
+/* Native-dependent code for GDB, for NYU Ultra3 running Sym1 OS.
+ Copyright (C) 1988, 1989, 1991, 1992 Free Software Foundation, Inc.
+ Contributed by David Wood (wood@nyu.edu) at New York University.
+
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define DEBUG
+#include "defs.h"
+#include "frame.h"
+#include "inferior.h"
+#include "symtab.h"
+#include "value.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <signal.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+
+#include "gdbcore.h"
+
+#include <sys/file.h>
+#include "gdb_stat.h"
+
+static void fetch_core_registers PARAMS ((char *, unsigned, int, CORE_ADDR));
+
+/* Assumes support for AMD's Binary Compatibility Standard
+ for ptrace(). If you define ULTRA3, the ultra3 extensions to
+ ptrace() are used allowing the reading of more than one register
+ at a time.
+
+ This file assumes KERNEL_DEBUGGING is turned off. This means
+ that if the user/gdb tries to read gr64-gr95 or any of the
+ protected special registers we silently return -1 (see the
+ CANNOT_STORE/FETCH_REGISTER macros). */
+#define ULTRA3
+
+#if !defined (offsetof)
+# define offsetof(TYPE, MEMBER) ((unsigned long) &((TYPE *)0)->MEMBER)
+#endif
+
+extern int errno;
+struct ptrace_user pt_struct;
+
+/* Get all available registers from the inferior. Registers that are
+ * defined in REGISTER_NAMES, but not available to the user/gdb are
+ * supplied as -1. This may include gr64-gr95 and the protected special
+ * purpose registers.
+ */
+
+void
+fetch_inferior_registers (regno)
+ int regno;
+{
+ register int i,j,ret_val=0;
+ char buf[128];
+
+ if (regno != -1) {
+ fetch_register (regno);
+ return;
+ }
+
+/* Global Registers */
+#ifdef ULTRA3
+ errno = 0;
+ ptrace (PT_READ_STRUCT, inferior_pid,
+ (PTRACE_ARG3_TYPE) register_addr(GR96_REGNUM,0),
+ (int)&pt_struct.pt_gr[0], 32*4);
+ if (errno != 0) {
+ perror_with_name ("reading global registers");
+ ret_val = -1;
+ } else for (regno=GR96_REGNUM, j=0 ; j<32 ; regno++, j++) {
+ supply_register (regno, &pt_struct.pt_gr[j]);
+ }
+#else
+ for (regno=GR96_REGNUM ; !ret_val && regno < GR96_REGNUM+32 ; regno++)
+ fetch_register(regno);
+#endif
+
+/* Local Registers */
+#ifdef ULTRA3
+ errno = 0;
+ ptrace (PT_READ_STRUCT, inferior_pid,
+ (PTRACE_ARG3_TYPE) register_addr(LR0_REGNUM,0),
+ (int)&pt_struct.pt_lr[0], 128*4);
+ if (errno != 0) {
+ perror_with_name ("reading local registers");
+ ret_val = -1;
+ } else for (regno=LR0_REGNUM, j=0 ; j<128 ; regno++, j++) {
+ supply_register (regno, &pt_struct.pt_lr[j]);
+ }
+#else
+ for (regno=LR0_REGNUM ; !ret_val && regno < LR0_REGNUM+128 ; regno++)
+ fetch_register(regno);
+#endif
+
+/* Special Registers */
+ fetch_register(GR1_REGNUM);
+ fetch_register(CPS_REGNUM);
+ fetch_register(PC_REGNUM);
+ fetch_register(NPC_REGNUM);
+ fetch_register(PC2_REGNUM);
+ fetch_register(IPC_REGNUM);
+ fetch_register(IPA_REGNUM);
+ fetch_register(IPB_REGNUM);
+ fetch_register(Q_REGNUM);
+ fetch_register(BP_REGNUM);
+ fetch_register(FC_REGNUM);
+
+/* Fake any registers that are in REGISTER_NAMES, but not available to gdb */
+ registers_fetched();
+}
+
+/* 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).
+ * NOTE: Assumes AMD's binary compatibility standard.
+ */
+
+void
+store_inferior_registers (regno)
+ int regno;
+{
+ register unsigned int regaddr;
+ char buf[80];
+
+ if (regno >= 0)
+ {
+ if (CANNOT_STORE_REGISTER(regno))
+ return;
+ regaddr = register_addr (regno, 0);
+ errno = 0;
+ ptrace (PT_WRITE_U, inferior_pid,
+ (PTRACE_ARG3_TYPE) regaddr, read_register(regno));
+ if (errno != 0)
+ {
+ sprintf (buf, "writing register %s (#%d)", REGISTER_NAME (regno), regno);
+ perror_with_name (buf);
+ }
+ }
+ else
+ {
+#ifdef ULTRA3
+ pt_struct.pt_gr1 = read_register(GR1_REGNUM);
+ for (regno = GR96_REGNUM; regno < GR96_REGNUM+32; regno++)
+ pt_struct.pt_gr[regno] = read_register(regno);
+ for (regno = LR0_REGNUM; regno < LR0_REGNUM+128; regno++)
+ pt_struct.pt_gr[regno] = read_register(regno);
+ errno = 0;
+ ptrace (PT_WRITE_STRUCT, inferior_pid,
+ (PTRACE_ARG3_TYPE) register_addr(GR1_REGNUM,0),
+ (int)&pt_struct.pt_gr1,(1*32*128)*4);
+ if (errno != 0)
+ {
+ sprintf (buf, "writing all local/global registers");
+ perror_with_name (buf);
+ }
+ pt_struct.pt_psr = read_register(CPS_REGNUM);
+ pt_struct.pt_pc0 = read_register(NPC_REGNUM);
+ pt_struct.pt_pc1 = read_register(PC_REGNUM);
+ pt_struct.pt_pc2 = read_register(PC2_REGNUM);
+ pt_struct.pt_ipc = read_register(IPC_REGNUM);
+ pt_struct.pt_ipa = read_register(IPA_REGNUM);
+ pt_struct.pt_ipb = read_register(IPB_REGNUM);
+ pt_struct.pt_q = read_register(Q_REGNUM);
+ pt_struct.pt_bp = read_register(BP_REGNUM);
+ pt_struct.pt_fc = read_register(FC_REGNUM);
+ errno = 0;
+ ptrace (PT_WRITE_STRUCT, inferior_pid,
+ (PTRACE_ARG3_TYPE) register_addr(CPS_REGNUM,0),
+ (int)&pt_struct.pt_psr,(10)*4);
+ if (errno != 0)
+ {
+ sprintf (buf, "writing all special registers");
+ perror_with_name (buf);
+ return;
+ }
+#else
+ store_inferior_registers(GR1_REGNUM);
+ for (regno=GR96_REGNUM ; regno<GR96_REGNUM+32 ; regno++)
+ store_inferior_registers(regno);
+ for (regno=LR0_REGNUM ; regno<LR0_REGNUM+128 ; regno++)
+ store_inferior_registers(regno);
+ store_inferior_registers(CPS_REGNUM);
+ store_inferior_registers(PC_REGNUM);
+ store_inferior_registers(NPC_REGNUM);
+ store_inferior_registers(PC2_REGNUM);
+ store_inferior_registers(IPC_REGNUM);
+ store_inferior_registers(IPA_REGNUM);
+ store_inferior_registers(IPB_REGNUM);
+ store_inferior_registers(Q_REGNUM);
+ store_inferior_registers(BP_REGNUM);
+ store_inferior_registers(FC_REGNUM);
+#endif /* ULTRA3 */
+ }
+}
+
+/*
+ * Fetch an individual register (and supply it).
+ * return 0 on success, -1 on failure.
+ * NOTE: Assumes AMD's Binary Compatibility Standard for ptrace().
+ */
+static void
+fetch_register (regno)
+ int regno;
+{
+ char buf[128];
+ int val;
+
+ if (CANNOT_FETCH_REGISTER(regno)) {
+ val = -1;
+ supply_register (regno, &val);
+ } else {
+ errno = 0;
+ val = ptrace (PT_READ_U, inferior_pid,
+ (PTRACE_ARG3_TYPE) register_addr(regno,0), 0);
+ if (errno != 0) {
+ sprintf(buf,"reading register %s (#%d)",REGISTER_NAME (regno), regno);
+ perror_with_name (buf);
+ } else {
+ supply_register (regno, &val);
+ }
+ }
+}
+
+
+/*
+ * Read AMD's Binary Compatibilty Standard conforming core file.
+ * struct ptrace_user is the first thing in the core file
+ */
+
+static void
+fetch_core_registers (core_reg_sect, core_reg_size, which, reg_addr)
+ char *core_reg_sect; /* Unused in this version */
+ unsigned core_reg_size; /* Unused in this version */
+ int which; /* Unused in this version */
+ CORE_ADDR reg_addr; /* Unused in this version */
+{
+ register int regno;
+ int val;
+ char buf[4];
+
+ for (regno = 0 ; regno < NUM_REGS; regno++) {
+ if (!CANNOT_FETCH_REGISTER(regno)) {
+ val = bfd_seek (core_bfd, (file_ptr) register_addr (regno, 0), SEEK_SET);
+ if (val < 0 || (val = bfd_read (buf, sizeof buf, 1, core_bfd)) < 0) {
+ char * buffer = (char *) alloca (strlen (REGISTER_NAME (regno)) + 35);
+ strcpy (buffer, "Reading core register ");
+ strcat (buffer, REGISTER_NAME (regno));
+ perror_with_name (buffer);
+ }
+ supply_register (regno, buf);
+ }
+ }
+
+ /* Fake any registers that are in REGISTER_NAMES, but not available to gdb */
+ registers_fetched();
+}
+
+
+/*
+ * Takes a register number as defined in tm.h via REGISTER_NAMES, and maps
+ * it to an offset in a struct ptrace_user defined by AMD's BCS.
+ * That is, it defines the mapping between gdb register numbers and items in
+ * a struct ptrace_user.
+ * A register protection scheme is set up here. If a register not
+ * available to the user is specified in 'regno', then an address that
+ * will cause ptrace() to fail is returned.
+ */
+CORE_ADDR
+register_addr (regno,blockend)
+ int regno;
+ CORE_ADDR blockend;
+{
+ if ((regno >= LR0_REGNUM) && (regno < LR0_REGNUM + 128)) {
+ return(offsetof(struct ptrace_user,pt_lr[regno-LR0_REGNUM]));
+ } else if ((regno >= GR96_REGNUM) && (regno < GR96_REGNUM + 32)) {
+ return(offsetof(struct ptrace_user,pt_gr[regno-GR96_REGNUM]));
+ } else {
+ switch (regno) {
+ case GR1_REGNUM: return(offsetof(struct ptrace_user,pt_gr1));
+ case CPS_REGNUM: return(offsetof(struct ptrace_user,pt_psr));
+ case NPC_REGNUM: return(offsetof(struct ptrace_user,pt_pc0));
+ case PC_REGNUM: return(offsetof(struct ptrace_user,pt_pc1));
+ case PC2_REGNUM: return(offsetof(struct ptrace_user,pt_pc2));
+ case IPC_REGNUM: return(offsetof(struct ptrace_user,pt_ipc));
+ case IPA_REGNUM: return(offsetof(struct ptrace_user,pt_ipa));
+ case IPB_REGNUM: return(offsetof(struct ptrace_user,pt_ipb));
+ case Q_REGNUM: return(offsetof(struct ptrace_user,pt_q));
+ case BP_REGNUM: return(offsetof(struct ptrace_user,pt_bp));
+ case FC_REGNUM: return(offsetof(struct ptrace_user,pt_fc));
+ default:
+ fprintf_filtered(gdb_stderr,"register_addr():Bad register %s (%d)\n",
+ REGISTER_NAME (regno), regno);
+ return(0xffffffff); /* Should make ptrace() fail */
+ }
+ }
+}
+
+
+/* Register that we are able to handle ultra3 core file formats.
+ FIXME: is this really bfd_target_unknown_flavour? */
+
+static struct core_fns ultra3_core_fns =
+{
+ bfd_target_unknown_flavour,
+ fetch_core_registers,
+ NULL
+};
+
+void
+_initialize_core_ultra3 ()
+{
+ add_core_fns (&ultra3_core_fns);
+}
diff --git a/gdb/ultra3-xdep.c b/gdb/ultra3-xdep.c
new file mode 100644
index 00000000000..57bab86e3bf
--- /dev/null
+++ b/gdb/ultra3-xdep.c
@@ -0,0 +1,128 @@
+/* Host-dependent code for GDB, for NYU Ultra3 running Sym1 OS.
+ Copyright (C) 1988, 1989, 1991, 1992 Free Software Foundation, Inc.
+ Contributed by David Wood (wood@nyu.edu) at New York University.
+
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define DEBUG
+#include "defs.h"
+#include "frame.h"
+#include "inferior.h"
+#include "symtab.h"
+#include "value.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <signal.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+
+#include "gdbcore.h"
+
+#include <sys/file.h>
+#include "gdb_stat.h"
+
+/* Assorted operating system circumventions */
+
+#ifdef SYM1
+
+/* FIXME: Kludge this for now. It really should be system call. */
+int
+getpagesize()
+{ return(8192); }
+
+/* FIXME: Fake out the fcntl() call, which we don't have. */
+fcntl(fd, cmd, arg)
+int fd, cmd, arg;
+{
+
+ switch (cmd) {
+ case F_GETFL: return(O_RDONLY); break;
+ default:
+ printf_unfiltered("Ultra3's fcntl() failing, cmd = %d.\n",cmd);
+ return(-1);
+ }
+}
+
+
+/*
+ * 4.2 Signal support, requires linking with libjobs.
+ */
+static int _SigMask;
+#define sigbit(s) (1L << ((s)-1))
+
+init_SigMask()
+{
+ /* Taken from the sym1 kernel in machdep.c:startup() */
+ _SigMask = sigbit (SIGTSTP) | sigbit (SIGTTOU) | sigbit (SIGTTIN) |
+ sigbit (SIGCHLD) | sigbit (SIGTINT);
+}
+
+sigmask(signo)
+ int signo;
+{
+ return (1 << (signo-1));
+}
+
+sigsetmask(sigmask)
+unsigned int sigmask;
+{
+ int i, mask = 1;
+ int lastmask = _SigMask;
+
+ for (i=0 ; i<NSIG ; i++) {
+ if (sigmask & mask) {
+ if (!(_SigMask & mask)) {
+ sighold(i+1);
+ _SigMask |= mask;
+ }
+ } else if (_SigMask & mask) {
+ sigrelse(i+1);
+ _SigMask &= ~mask;
+ }
+ mask <<= 1;
+ }
+ return (lastmask);
+}
+
+sigblock(sigmask)
+unsigned int sigmask;
+{
+ int i, mask = 1;
+ int lastmask = _SigMask;
+
+ for (i=0 ; i<NSIG ; i++) {
+ if ((sigmask & mask) && !(_SigMask & mask)) {
+ sighold(i+1);
+ _SigMask |= mask;
+ }
+ mask <<= 1;
+ }
+ return (lastmask);
+}
+#endif /* SYM1 */
+
+
+/* Initialization code for this module. */
+
+void
+_initialize_ultra3 ()
+{
+#ifdef SYM1
+ init_SigMask();
+#endif
+}
diff --git a/gdb/umax-xdep.c b/gdb/umax-xdep.c
new file mode 100644
index 00000000000..d54519e6384
--- /dev/null
+++ b/gdb/umax-xdep.c
@@ -0,0 +1,133 @@
+/* umax host stuff.
+ Copyright (C) 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "frame.h"
+#include "inferior.h"
+
+#include <sys/param.h>
+#include <sys/dir.h>
+#include <signal.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+
+#include "gdbcore.h"
+#include <sys/ptrace.h>
+#define PTRACE_ATTACH PT_ATTACH
+#define PTRACE_DETACH PT_FREEPROC
+
+#include <sys/file.h>
+#include "gdb_stat.h"
+
+/* Work with core dump and executable files, for GDB.
+ This code would be in corefile.c if it weren't machine-dependent. */
+
+void
+core_file_command (filename, from_tty)
+ char *filename;
+ int from_tty;
+{
+ int val;
+ extern char registers[];
+
+ /* Discard all vestiges of any previous core file
+ and mark data and stack spaces as empty. */
+
+ if (corefile)
+ free (corefile);
+ corefile = 0;
+
+ if (corechan >= 0)
+ close (corechan);
+ corechan = -1;
+
+ data_start = 0;
+ data_end = 0;
+ stack_start = STACK_END_ADDR;
+ stack_end = STACK_END_ADDR;
+
+ /* Now, if a new core file was specified, open it and digest it. */
+
+ if (filename)
+ {
+ filename = tilde_expand (filename);
+ make_cleanup (free, filename);
+
+ if (have_inferior_p ())
+ error ("To look at a core file, you must kill the program with \"kill\".");
+ corechan = open (filename, O_RDONLY, 0);
+ if (corechan < 0)
+ perror_with_name (filename);
+ /* 4.2-style (and perhaps also sysV-style) core dump file. */
+ {
+ struct ptrace_user u;
+ int reg_offset;
+
+ val = myread (corechan, &u, sizeof u);
+ if (val < 0)
+ perror_with_name (filename);
+ data_start = exec_data_start;
+
+ data_end = data_start + u.pt_dsize;
+ stack_start = stack_end - u.pt_ssize;
+ data_offset = sizeof u;
+ stack_offset = data_offset + u.pt_dsize;
+ reg_offset = 0;
+
+ memcpy (&core_aouthdr, &u.pt_aouthdr, sizeof (AOUTHDR));
+ printf_unfiltered ("Core file is from \"%s\".\n", u.pt_comm);
+ if (u.pt_signal > 0)
+ printf_unfiltered ("Program terminated with signal %d, %s.\n",
+ u.pt_signal, safe_strsignal (u.pt_signal));
+
+ /* 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, NULL);
+ }
+
+ flush_cached_frames ();
+ select_frame (get_current_frame (), 0);
+ validate_files ();
+ }
+ else if (from_tty)
+ printf_unfiltered ("No core file now.\n");
+}
diff --git a/gdb/utils.c b/gdb/utils.c
new file mode 100644
index 00000000000..08b801b9759
--- /dev/null
+++ b/gdb/utils.c
@@ -0,0 +1,2932 @@
+/* General utility routines for GDB, the GNU debugger.
+ Copyright 1986, 89, 90, 91, 92, 95, 96, 1998 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include <ctype.h>
+#include "gdb_string.h"
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#ifdef HAVE_CURSES_H
+#include <curses.h>
+#endif
+#ifdef HAVE_TERM_H
+#include <term.h>
+#endif
+
+/* SunOS's curses.h has a '#define reg register' in it. Thank you Sun. */
+#ifdef reg
+#undef reg
+#endif
+
+#include "signals.h"
+#include "gdbcmd.h"
+#include "serial.h"
+#include "bfd.h"
+#include "target.h"
+#include "demangle.h"
+#include "expression.h"
+#include "language.h"
+#include "annotate.h"
+
+#include <readline/readline.h>
+
+/* readline defines this. */
+#undef savestring
+
+void (*error_begin_hook) PARAMS ((void));
+
+/* Prototypes for local functions */
+
+static void vfprintf_maybe_filtered PARAMS ((GDB_FILE *, const char *,
+ va_list, int));
+
+static void fputs_maybe_filtered PARAMS ((const char *, GDB_FILE *, int));
+
+#if defined (USE_MMALLOC) && !defined (NO_MMCHECK)
+static void malloc_botch PARAMS ((void));
+#endif
+
+static void
+fatal_dump_core PARAMS((char *, ...));
+
+static void
+prompt_for_continue PARAMS ((void));
+
+static void
+set_width_command PARAMS ((char *, int, struct cmd_list_element *));
+
+static void
+set_width PARAMS ((void));
+
+/* 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
+
+#ifndef GDB_FILE_ISATTY
+#define GDB_FILE_ISATTY(GDB_FILE_PTR) (gdb_file_isatty(GDB_FILE_PTR))
+#endif
+
+/* Chain of cleanup actions established with make_cleanup,
+ to be executed if an error happens. */
+
+static struct cleanup *cleanup_chain; /* cleaned up after a failed command */
+static struct cleanup *final_cleanup_chain; /* cleaned up when gdb exits */
+static struct cleanup *run_cleanup_chain; /* cleaned up on each 'run' */
+
+/* Nonzero if we have job control. */
+
+int job_control;
+
+/* 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;
+
+/* String to be printed before quit messages, if any. */
+
+char *quit_pre_print;
+
+/* String to be printed before warning messages, if any. */
+
+char *warning_pre_print = "\nwarning: ";
+
+int pagination_enabled = 1;
+
+
+/* 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;
+{
+ return make_my_cleanup (&cleanup_chain, function, arg);
+}
+
+struct cleanup *
+make_final_cleanup (function, arg)
+ void (*function) PARAMS ((PTR));
+ PTR arg;
+{
+ return make_my_cleanup (&final_cleanup_chain, function, arg);
+}
+struct cleanup *
+make_run_cleanup (function, arg)
+ void (*function) PARAMS ((PTR));
+ PTR arg;
+{
+ return make_my_cleanup (&run_cleanup_chain, function, arg);
+}
+struct cleanup *
+make_my_cleanup (pmy_chain, function, arg)
+ struct cleanup **pmy_chain;
+ void (*function) PARAMS ((PTR));
+ PTR arg;
+{
+ register struct cleanup *new
+ = (struct cleanup *) xmalloc (sizeof (struct cleanup));
+ register struct cleanup *old_chain = *pmy_chain;
+
+ new->next = *pmy_chain;
+ new->function = function;
+ new->arg = arg;
+ *pmy_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;
+{
+ do_my_cleanups (&cleanup_chain, old_chain);
+}
+
+void
+do_final_cleanups (old_chain)
+ register struct cleanup *old_chain;
+{
+ do_my_cleanups (&final_cleanup_chain, old_chain);
+}
+
+void
+do_run_cleanups (old_chain)
+ register struct cleanup *old_chain;
+{
+ do_my_cleanups (&run_cleanup_chain, old_chain);
+}
+
+void
+do_my_cleanups (pmy_chain, old_chain)
+ register struct cleanup **pmy_chain;
+ register struct cleanup *old_chain;
+{
+ register struct cleanup *ptr;
+ while ((ptr = *pmy_chain) != old_chain)
+ {
+ *pmy_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;
+{
+ discard_my_cleanups (&cleanup_chain, old_chain);
+}
+
+void
+discard_final_cleanups (old_chain)
+ register struct cleanup *old_chain;
+{
+ discard_my_cleanups (&final_cleanup_chain, old_chain);
+}
+
+void
+discard_my_cleanups (pmy_chain, old_chain)
+ register struct cleanup **pmy_chain;
+ register struct cleanup *old_chain;
+{
+ register struct cleanup *ptr;
+ while ((ptr = *pmy_chain) != old_chain)
+ {
+ *pmy_chain = ptr->next;
+ free ((PTR)ptr);
+ }
+}
+
+/* Set the cleanup_chain to 0, and return the old cleanup chain. */
+struct cleanup *
+save_cleanups ()
+{
+ return save_my_cleanups (&cleanup_chain);
+}
+
+struct cleanup *
+save_final_cleanups ()
+{
+ return save_my_cleanups (&final_cleanup_chain);
+}
+
+struct cleanup *
+save_my_cleanups (pmy_chain)
+ struct cleanup **pmy_chain;
+{
+ struct cleanup *old_chain = *pmy_chain;
+
+ *pmy_chain = 0;
+ return old_chain;
+}
+
+/* Restore the cleanup chain from a previously saved chain. */
+void
+restore_cleanups (chain)
+ struct cleanup *chain;
+{
+ restore_my_cleanups (&cleanup_chain, chain);
+}
+
+void
+restore_final_cleanups (chain)
+ struct cleanup *chain;
+{
+ restore_my_cleanups (&final_cleanup_chain, chain);
+}
+
+void
+restore_my_cleanups (pmy_chain, chain)
+ struct cleanup **pmy_chain;
+ struct cleanup *chain;
+{
+ *pmy_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)
+ PTR arg;
+{
+}
+
+
+/* Print a warning message. Way to use this is to call warning_begin,
+ output the warning message (use unfiltered output to gdb_stderr),
+ ending in a newline. There is not currently a warning_end that you
+ call afterwards, but such a thing might be added if it is useful
+ for a GUI to separate warning messages from other output.
+
+ FIXME: Why do warnings use unfiltered output and errors filtered?
+ Is this anything other than a historical accident? */
+
+void
+warning_begin ()
+{
+ target_terminal_ours ();
+ wrap_here(""); /* Force out any buffered output */
+ gdb_flush (gdb_stdout);
+ if (warning_pre_print)
+ fprintf_unfiltered (gdb_stderr, warning_pre_print);
+}
+
+/* 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
+#ifdef ANSI_PROTOTYPES
+warning (const char *string, ...)
+#else
+warning (va_alist)
+ va_dcl
+#endif
+{
+ va_list args;
+#ifdef ANSI_PROTOTYPES
+ va_start (args, string);
+#else
+ char *string;
+
+ va_start (args);
+ string = va_arg (args, char *);
+#endif
+ if (warning_hook)
+ (*warning_hook) (string, args);
+ else
+ {
+ warning_begin ();
+ vfprintf_unfiltered (gdb_stderr, string, args);
+ fprintf_unfiltered (gdb_stderr, "\n");
+ va_end (args);
+ }
+}
+
+/* Start the printing of an error message. Way to use this is to call
+ this, output the error message (use filtered output to gdb_stderr
+ (FIXME: Some callers, like memory_error, use gdb_stdout)), ending
+ in a newline, and then call return_to_top_level (RETURN_ERROR).
+ error() provides a convenient way to do this for the special case
+ that the error message can be formatted with a single printf call,
+ but this is more general. */
+void
+error_begin ()
+{
+ if (error_begin_hook)
+ error_begin_hook ();
+
+ target_terminal_ours ();
+ wrap_here (""); /* Force out any buffered output */
+ gdb_flush (gdb_stdout);
+
+ annotate_error_begin ();
+
+ if (error_pre_print)
+ fprintf_filtered (gdb_stderr, error_pre_print);
+}
+
+/* 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
+#ifdef ANSI_PROTOTYPES
+error (const char *string, ...)
+#else
+error (va_alist)
+ va_dcl
+#endif
+{
+ va_list args;
+#ifdef ANSI_PROTOTYPES
+ va_start (args, string);
+#else
+ va_start (args);
+#endif
+ if (error_hook)
+ (*error_hook) ();
+ else
+ {
+ error_begin ();
+#ifdef ANSI_PROTOTYPES
+ vfprintf_filtered (gdb_stderr, string, args);
+#else
+ {
+ char *string1;
+
+ string1 = va_arg (args, char *);
+ vfprintf_filtered (gdb_stderr, string1, args);
+ }
+#endif
+ fprintf_filtered (gdb_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
+#ifdef ANSI_PROTOTYPES
+fatal (char *string, ...)
+#else
+fatal (va_alist)
+ va_dcl
+#endif
+{
+ va_list args;
+#ifdef ANSI_PROTOTYPES
+ va_start (args, string);
+#else
+ char *string;
+ va_start (args);
+ string = va_arg (args, char *);
+#endif
+ fprintf_unfiltered (gdb_stderr, "\ngdb: ");
+ vfprintf_unfiltered (gdb_stderr, string, args);
+ fprintf_unfiltered (gdb_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
+#ifdef ANSI_PROTOTYPES
+fatal_dump_core (char *string, ...)
+#else
+fatal_dump_core (va_alist)
+ va_dcl
+#endif
+{
+ va_list args;
+#ifdef ANSI_PROTOTYPES
+ va_start (args, string);
+#else
+ char *string;
+
+ va_start (args);
+ string = va_arg (args, char *);
+#endif
+ /* "internal error" is always correct, since GDB should never dump
+ core, no matter what the input. */
+ fprintf_unfiltered (gdb_stderr, "\ngdb internal error: ");
+ vfprintf_unfiltered (gdb_stderr, string, args);
+ fprintf_unfiltered (gdb_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. */
+
+NORETURN 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_set_error (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);
+
+ /* We want anything which was printed on stdout to come out first, before
+ this message. */
+ gdb_flush (gdb_stdout);
+ fprintf_unfiltered (gdb_stderr, "%s.\n", combined);
+}
+
+/* Control C eventually causes this to be called, at a convenient time. */
+
+void
+quit ()
+{
+ serial_t gdb_stdout_serial = serial_fdopen (1);
+
+ target_terminal_ours ();
+
+ /* We want all output to appear now, before we print "Quit". We
+ have 3 levels of buffering we have to flush (it's possible that
+ some of these should be changed to flush the lower-level ones
+ too): */
+
+ /* 1. The _filtered buffer. */
+ wrap_here ((char *)0);
+
+ /* 2. The stdio buffer. */
+ gdb_flush (gdb_stdout);
+ gdb_flush (gdb_stderr);
+
+ /* 3. The system-level buffer. */
+ SERIAL_DRAIN_OUTPUT (gdb_stdout_serial);
+ SERIAL_UN_FDOPEN (gdb_stdout_serial);
+
+ annotate_error_begin ();
+
+ /* Don't use *_filtered; we don't want to prompt the user to continue. */
+ if (quit_pre_print)
+ fprintf_unfiltered (gdb_stderr, quit_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_unfiltered (gdb_stderr, "Quit\n");
+ else
+ fprintf_unfiltered (gdb_stderr,
+ "Quit (expect signal SIGINT when the program is resumed)\n");
+ return_to_top_level (RETURN_QUIT);
+}
+
+
+#if defined(__GO32__)
+
+/* In the absence of signals, poll keyboard for a quit.
+ Called from #define QUIT pollquit() in xm-go32.h. */
+
+void
+notice_quit()
+{
+ if (kbhit ())
+ switch (getkey ())
+ {
+ case 1:
+ quit_flag = 1;
+ break;
+ case 2:
+ immediate_quit = 2;
+ break;
+ default:
+ /* We just ignore it */
+ /* FIXME!! Don't think this actually works! */
+ fprintf_unfiltered (gdb_stderr, "CTRL-A to quit, CTRL-B to quit harder\n");
+ break;
+ }
+}
+
+#elif defined(_MSC_VER) /* should test for wingdb instead? */
+
+/*
+ * Windows translates all keyboard and mouse events
+ * into a message which is appended to the message
+ * queue for the process.
+ */
+
+void notice_quit()
+{
+ int k = win32pollquit();
+ if (k == 1)
+ quit_flag = 1;
+ else if (k == 2)
+ immediate_quit = 1;
+}
+
+#else /* !defined(__GO32__) && !defined(_MSC_VER) */
+
+void notice_quit()
+{
+ /* Done by signals */
+}
+
+#endif /* !defined(__GO32__) && !defined(_MSC_VER) */
+
+void
+pollquit()
+{
+ notice_quit ();
+ if (quit_flag || immediate_quit)
+ quit ();
+}
+
+/* Control C comes here */
+
+void
+request_quit (signo)
+ int signo;
+{
+ quit_flag = 1;
+ /* Restore the signal handler. Harmless with BSD-style signals, needed
+ for System V-style signals. So just always do it, rather than worrying
+ about USG defines and stuff like that. */
+ signal (signo, request_quit);
+
+#ifdef REQUEST_QUIT
+ REQUEST_QUIT;
+#else
+ if (immediate_quit)
+ quit ();
+#endif
+}
+
+
+/* Memory management stuff (malloc friends). */
+
+/* Make a substitute size_t for non-ANSI compilers. */
+
+#ifndef HAVE_STDDEF_H
+#ifndef size_t
+#define size_t unsigned int
+#endif
+#endif
+
+#if !defined (USE_MMALLOC)
+
+PTR
+mmalloc (md, size)
+ PTR md;
+ size_t size;
+{
+ return malloc (size);
+}
+
+PTR
+mrealloc (md, ptr, size)
+ PTR md;
+ PTR ptr;
+ size_t 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 /* USE_MMALLOC */
+
+#if !defined (USE_MMALLOC) || defined (NO_MMCHECK)
+
+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 mmcheckf 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. */
+
+#ifndef MMCHECK_FORCE
+#define MMCHECK_FORCE 0
+#endif
+
+void
+init_malloc (md)
+ PTR md;
+{
+ if (!mmcheckf (md, malloc_botch, MMCHECK_FORCE))
+ {
+ /* Don't use warning(), which relies on current_target being set
+ to something other than dummy_target, until after
+ initialize_all_files(). */
+
+ fprintf_unfiltered
+ (gdb_stderr, "warning: failed to install memory consistency checks; ");
+ fprintf_unfiltered
+ (gdb_stderr, "configuration should define NO_MMCHECK or MMCHECK_FORCE\n");
+ }
+
+ 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)
+ size_t size;
+{
+ return (xmmalloc ((PTR) NULL, size));
+}
+
+/* Like mrealloc but get error if no storage available. */
+
+PTR
+xrealloc (ptr, size)
+ PTR ptr;
+ size_t 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 GDB_FILE *file;
+{
+ if (file->ts_streamtype == astring)
+ {
+ char *p;
+
+ gdb_file_adjust_strbuf (n, file);
+ p = file->ts_strbuf + strlen (file->ts_strbuf);
+
+ memset (p, ' ', n);
+ p[n] = '\000';
+ }
+ else
+ {
+ while (n-- > 0)
+ fputc (' ', file->ts_filestream);
+ }
+}
+
+/* Print a host address. */
+
+void
+gdb_print_address (addr, stream)
+ PTR addr;
+ GDB_FILE *stream;
+{
+
+ /* We could use the %p conversion specifier to fprintf if we had any
+ way of knowing whether this host supports it. But the following
+ should work on the Alpha and on 32 bit machines. */
+
+ fprintf_filtered (stream, "0x%lx", (unsigned long)addr);
+}
+
+/* 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
+#ifdef ANSI_PROTOTYPES
+query (char *ctlstr, ...)
+#else
+query (va_alist)
+ va_dcl
+#endif
+{
+ va_list args;
+ register int answer;
+ register int ans2;
+ int retval;
+
+#ifdef ANSI_PROTOTYPES
+ va_start (args, ctlstr);
+#else
+ char *ctlstr;
+ va_start (args);
+ ctlstr = va_arg (args, char *);
+#endif
+
+ if (query_hook)
+ {
+ return query_hook (ctlstr, args);
+ }
+
+ /* Automatically answer "yes" if input is not from a terminal. */
+ if (!input_from_terminal_p ())
+ return 1;
+#ifdef MPW
+ /* FIXME Automatically answer "yes" if called from MacGDB. */
+ if (mac_app)
+ return 1;
+#endif /* MPW */
+
+ while (1)
+ {
+ wrap_here (""); /* Flush any buffered output */
+ gdb_flush (gdb_stdout);
+
+ if (annotation_level > 1)
+ printf_filtered ("\n\032\032pre-query\n");
+
+ vfprintf_filtered (gdb_stdout, ctlstr, args);
+ printf_filtered ("(y or n) ");
+
+ if (annotation_level > 1)
+ printf_filtered ("\n\032\032query\n");
+
+#ifdef MPW
+ /* If not in MacGDB, move to a new line so the entered line doesn't
+ have a prompt on the front of it. */
+ if (!mac_app)
+ fputs_unfiltered ("\n", gdb_stdout);
+#endif /* MPW */
+
+ wrap_here("");
+ gdb_flush (gdb_stdout);
+
+#if defined(TUI)
+ if (!tui_version || cmdWin == tuiWinWithFocus())
+#endif
+ answer = fgetc (stdin);
+#if defined(TUI)
+ else
+
+ answer = (unsigned char)tuiBufferGetc();
+
+#endif
+ clearerr (stdin); /* in case of C-d */
+ if (answer == EOF) /* C-d */
+ {
+ retval = 1;
+ break;
+ }
+ /* Eat rest of input line, to EOF or newline */
+ if ((answer != '\n') || (tui_version && answer != '\r'))
+ do
+ {
+#if defined(TUI)
+ if (!tui_version || cmdWin == tuiWinWithFocus())
+#endif
+ ans2 = fgetc (stdin);
+#if defined(TUI)
+ else
+
+ ans2 = (unsigned char)tuiBufferGetc();
+#endif
+ clearerr (stdin);
+ }
+ while (ans2 != EOF && ans2 != '\n' && ans2 != '\r');
+ TUIDO(((TuiOpaqueFuncPtr)tui_vStartNewLines, 1));
+
+ if (answer >= 'a')
+ answer -= 040;
+ if (answer == 'Y')
+ {
+ retval = 1;
+ break;
+ }
+ if (answer == 'N')
+ {
+ retval = 0;
+ break;
+ }
+ printf_filtered ("Please answer y or n.\n");
+ }
+
+ if (annotation_level > 1)
+ printf_filtered ("\n\032\032post-query\n");
+ return retval;
+}
+
+
+/* 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;
+ GDB_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);
+ }
+}
+
+
+
+
+static char * hexlate = "0123456789abcdef" ;
+int fmthex(inbuf,outbuff,length,linelength)
+ unsigned char * inbuf ;
+ unsigned char * outbuff;
+ int length;
+ int linelength;
+{
+ unsigned char byte , nib ;
+ int outlength = 0 ;
+
+ while (length)
+ {
+ if (outlength >= linelength) break ;
+ byte = *inbuf ;
+ inbuf++ ;
+ nib = byte >> 4 ;
+ *outbuff++ = hexlate[nib] ;
+ nib = byte &0x0f ;
+ *outbuff++ = hexlate[nib] ;
+ *outbuff++ = ' ' ;
+ length-- ;
+ outlength += 3 ;
+ }
+ *outbuff = '\0' ; /* null terminate our output line */
+ return outlength ;
+}
+
+
+/* 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;
+
+
+/* Inialize the lines and chars per page */
+void
+init_page_info()
+{
+#if defined(TUI)
+ if (tui_version && m_winPtrNotNull(cmdWin))
+ {
+ lines_per_page = cmdWin->generic.height;
+ chars_per_line = cmdWin->generic.width;
+ }
+ else
+#endif
+ {
+ /* 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;
+
+#if !defined (MPW) && !defined (_WIN32)
+ /* No termcap under MPW, although might be cool to do something
+ by looking at worksheet or console window sizes. */
+ /* 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;
+ int running_in_emacs = getenv ("EMACS") != NULL;
+
+ val = tgetnum ("li");
+ if (val >= 0 && !running_in_emacs)
+ 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;
+ }
+ }
+ }
+#endif /* MPW */
+
+#if defined(SIGWINCH) && defined(SIGWINCH_HANDLER)
+
+ /* If there is a better way to determine the window size, use it. */
+ SIGWINCH_HANDLER (SIGWINCH);
+#endif
+#endif
+ /* If the output is not a terminal, don't paginate it. */
+ if (!GDB_FILE_ISATTY (gdb_stdout))
+ lines_per_page = UINT_MAX;
+ } /* the command_line_version */
+ set_width();
+}
+
+static void
+set_width()
+{
+ if (chars_per_line == 0)
+ init_page_info();
+
+ 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 */
+}
+
+/* ARGSUSED */
+static void
+set_width_command (args, from_tty, c)
+ char *args;
+ int from_tty;
+ struct cmd_list_element *c;
+{
+ set_width ();
+}
+
+/* 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;
+ char cont_prompt[120];
+
+ if (annotation_level > 1)
+ printf_unfiltered ("\n\032\032pre-prompt-for-continue\n");
+
+ strcpy (cont_prompt,
+ "---Type <return> to continue, or q <return> to quit---");
+ if (annotation_level > 1)
+ strcat (cont_prompt, "\n\032\032prompt-for-continue\n");
+
+ /* 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. */
+ /* Call readline, not gdb_readline, because GO32 readline handles control-C
+ whereas control-C to gdb_readline will cause the user to get dumped
+ out to DOS. */
+ ignore = readline (cont_prompt);
+
+ if (annotation_level > 1)
+ printf_unfiltered ("\n\032\032post-prompt-for-continue\n");
+
+ 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;
+{
+ /* This should have been allocated, but be paranoid anyway. */
+ if (!wrap_buffer)
+ abort ();
+
+ if (wrap_buffer[0])
+ {
+ *wrap_pointer = '\0';
+ fputs_unfiltered (wrap_buffer, gdb_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");
+ }
+}
+
+int
+gdb_file_isatty (stream)
+ GDB_FILE *stream;
+{
+
+ if (stream->ts_streamtype == afile)
+ return (isatty(fileno(stream->ts_filestream)));
+ else return 0;
+}
+
+GDB_FILE *
+gdb_file_init_astring (n)
+ int n;
+{
+ GDB_FILE *tmpstream;
+
+ tmpstream = xmalloc (sizeof(GDB_FILE));
+ tmpstream->ts_streamtype = astring;
+ tmpstream->ts_filestream = NULL;
+ if (n > 0)
+ {
+ tmpstream->ts_strbuf = xmalloc ((n + 1)*sizeof(char));
+ tmpstream->ts_strbuf[0] = '\0';
+ }
+ else
+ tmpstream->ts_strbuf = NULL;
+ tmpstream->ts_buflen = n;
+
+ return tmpstream;
+}
+
+void
+gdb_file_deallocate (streamptr)
+ GDB_FILE **streamptr;
+{
+ GDB_FILE *tmpstream;
+
+ tmpstream = *streamptr;
+ if ((tmpstream->ts_streamtype == astring) &&
+ (tmpstream->ts_strbuf != NULL))
+ {
+ free (tmpstream->ts_strbuf);
+ }
+
+ free (tmpstream);
+ *streamptr = NULL;
+}
+
+char *
+gdb_file_get_strbuf (stream)
+ GDB_FILE *stream;
+{
+ return (stream->ts_strbuf);
+}
+
+/* adjust the length of the buffer by the amount necessary
+ to accomodate appending a string of length N to the buffer contents */
+void
+gdb_file_adjust_strbuf (n, stream)
+ int n;
+ GDB_FILE *stream;
+{
+ int non_null_chars;
+
+ non_null_chars = strlen(stream->ts_strbuf);
+
+ if (n > (stream->ts_buflen - non_null_chars - 1))
+ {
+ stream->ts_buflen = n + non_null_chars + 1;
+ stream->ts_strbuf = xrealloc (stream->ts_strbuf, stream->ts_buflen);
+ }
+}
+
+GDB_FILE *
+gdb_fopen (name, mode)
+ char * name;
+ char * mode;
+{
+ int gdb_file_size;
+ GDB_FILE *tmp;
+
+ gdb_file_size = sizeof(GDB_FILE);
+ tmp = (GDB_FILE *) xmalloc (gdb_file_size);
+ tmp->ts_streamtype = afile;
+ tmp->ts_filestream = fopen (name, mode);
+ tmp->ts_strbuf = NULL;
+ tmp->ts_buflen = 0;
+
+ return tmp;
+}
+
+void
+gdb_flush (stream)
+ GDB_FILE *stream;
+{
+ if (flush_hook
+ && (stream == gdb_stdout
+ || stream == gdb_stderr))
+ {
+ flush_hook (stream);
+ return;
+ }
+
+ fflush (stream->ts_filestream);
+}
+
+void
+gdb_fclose(streamptr)
+ GDB_FILE **streamptr;
+{
+ GDB_FILE *tmpstream;
+
+ tmpstream = *streamptr;
+ fclose (tmpstream->ts_filestream);
+ gdb_file_deallocate (streamptr);
+}
+
+/* Like fputs but if FILTER is true, pause after every screenful.
+
+ Regardless of FILTER can wrap at points other than the final
+ character of a line.
+
+ Unlike fputs, fputs_maybe_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 (only if
+ FILTER is true) (since prompt_for_continue may do so) so this
+ routine should not be called when cleanups are not in place. */
+
+static void
+fputs_maybe_filtered (linebuffer, stream, filter)
+ const char *linebuffer;
+ GDB_FILE *stream;
+ int filter;
+{
+ const char *lineptr;
+
+ if (linebuffer == 0)
+ return;
+
+ /* Don't do any filtering if it is disabled. */
+ if (stream != gdb_stdout
+ || (lines_per_page == UINT_MAX && chars_per_line == UINT_MAX))
+ {
+ fputs_unfiltered (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 (filter &&
+ (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
+ fputc_unfiltered ('\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
+ fputc_unfiltered (*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)
+ fputc_unfiltered ('\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_unfiltered (wrap_indent, stream);
+ *wrap_pointer = '\0'; /* Null-terminate saved stuff */
+ fputs_unfiltered (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++;
+ fputc_unfiltered ('\n', stream);
+ lineptr++;
+ }
+ }
+}
+
+void
+fputs_filtered (linebuffer, stream)
+ const char *linebuffer;
+ GDB_FILE *stream;
+{
+ fputs_maybe_filtered (linebuffer, stream, 1);
+}
+
+int
+putchar_unfiltered (c)
+ int c;
+{
+ char buf[2];
+
+ buf[0] = c;
+ buf[1] = 0;
+ fputs_unfiltered (buf, gdb_stdout);
+ return c;
+}
+
+int
+fputc_unfiltered (c, stream)
+ int c;
+ GDB_FILE * stream;
+{
+ char buf[2];
+
+ buf[0] = c;
+ buf[1] = 0;
+ fputs_unfiltered (buf, stream);
+ return c;
+}
+
+int
+fputc_filtered (c, stream)
+ int c;
+ GDB_FILE * stream;
+{
+ char buf[2];
+
+ buf[0] = c;
+ buf[1] = 0;
+ fputs_filtered (buf, stream);
+ return c;
+}
+
+/* puts_debug is like fputs_unfiltered, except it prints special
+ characters in printable fashion. */
+
+void
+puts_debug (prefix, string, suffix)
+ char *prefix;
+ char *string;
+ char *suffix;
+{
+ int ch;
+
+ /* Print prefix and suffix after each line. */
+ static int new_line = 1;
+ static int return_p = 0;
+ static char *prev_prefix = "";
+ static char *prev_suffix = "";
+
+ if (*string == '\n')
+ return_p = 0;
+
+ /* If the prefix is changing, print the previous suffix, a new line,
+ and the new prefix. */
+ if ((return_p || (strcmp(prev_prefix, prefix) != 0)) && !new_line)
+ {
+ fputs_unfiltered (prev_suffix, gdb_stderr);
+ fputs_unfiltered ("\n", gdb_stderr);
+ fputs_unfiltered (prefix, gdb_stderr);
+ }
+
+ /* Print prefix if we printed a newline during the previous call. */
+ if (new_line)
+ {
+ new_line = 0;
+ fputs_unfiltered (prefix, gdb_stderr);
+ }
+
+ prev_prefix = prefix;
+ prev_suffix = suffix;
+
+ /* Output characters in a printable format. */
+ while ((ch = *string++) != '\0')
+ {
+ switch (ch)
+ {
+ default:
+ if (isprint (ch))
+ fputc_unfiltered (ch, gdb_stderr);
+
+ else
+ fprintf_unfiltered (gdb_stderr, "\\x%02x", ch & 0xff);
+ break;
+
+ case '\\': fputs_unfiltered ("\\\\", gdb_stderr); break;
+ case '\b': fputs_unfiltered ("\\b", gdb_stderr); break;
+ case '\f': fputs_unfiltered ("\\f", gdb_stderr); break;
+ case '\n': new_line = 1;
+ fputs_unfiltered ("\\n", gdb_stderr); break;
+ case '\r': fputs_unfiltered ("\\r", gdb_stderr); break;
+ case '\t': fputs_unfiltered ("\\t", gdb_stderr); break;
+ case '\v': fputs_unfiltered ("\\v", gdb_stderr); break;
+ }
+
+ return_p = ch == '\r';
+ }
+
+ /* Print suffix if we printed a newline. */
+ if (new_line)
+ {
+ fputs_unfiltered (suffix, gdb_stderr);
+ fputs_unfiltered ("\n", gdb_stderr);
+ }
+}
+
+
+/* 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,
+ call prompt_for_continue 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 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. */
+
+static void
+vfprintf_maybe_filtered (stream, format, args, filter)
+ GDB_FILE *stream;
+ const char *format;
+ va_list args;
+ int filter;
+{
+ char *linebuffer;
+ struct cleanup *old_cleanups;
+
+ vasprintf (&linebuffer, format, args);
+ if (linebuffer == NULL)
+ {
+ fputs_unfiltered ("\ngdb: virtual memory exhausted.\n", gdb_stderr);
+ exit (1);
+ }
+ old_cleanups = make_cleanup (free, linebuffer);
+ fputs_maybe_filtered (linebuffer, stream, filter);
+ do_cleanups (old_cleanups);
+}
+
+
+void
+vfprintf_filtered (stream, format, args)
+ GDB_FILE *stream;
+ const char *format;
+ va_list args;
+{
+ vfprintf_maybe_filtered (stream, format, args, 1);
+}
+
+void
+vfprintf_unfiltered (stream, format, args)
+ GDB_FILE *stream;
+ const char *format;
+ va_list args;
+{
+ char *linebuffer;
+ struct cleanup *old_cleanups;
+
+ vasprintf (&linebuffer, format, args);
+ if (linebuffer == NULL)
+ {
+ fputs_unfiltered ("\ngdb: virtual memory exhausted.\n", gdb_stderr);
+ exit (1);
+ }
+ old_cleanups = make_cleanup (free, linebuffer);
+ fputs_unfiltered (linebuffer, stream);
+ do_cleanups (old_cleanups);
+}
+
+void
+vprintf_filtered (format, args)
+ const char *format;
+ va_list args;
+{
+ vfprintf_maybe_filtered (gdb_stdout, format, args, 1);
+}
+
+void
+vprintf_unfiltered (format, args)
+ const char *format;
+ va_list args;
+{
+ vfprintf_unfiltered (gdb_stdout, format, args);
+}
+
+/* VARARGS */
+void
+#ifdef ANSI_PROTOTYPES
+fprintf_filtered (GDB_FILE *stream, const char *format, ...)
+#else
+fprintf_filtered (va_alist)
+ va_dcl
+#endif
+{
+ va_list args;
+#ifdef ANSI_PROTOTYPES
+ va_start (args, format);
+#else
+ GDB_FILE *stream;
+ char *format;
+
+ va_start (args);
+ stream = va_arg (args, GDB_FILE *);
+ format = va_arg (args, char *);
+#endif
+ vfprintf_filtered (stream, format, args);
+ va_end (args);
+}
+
+/* VARARGS */
+void
+#ifdef ANSI_PROTOTYPES
+fprintf_unfiltered (GDB_FILE *stream, const char *format, ...)
+#else
+fprintf_unfiltered (va_alist)
+ va_dcl
+#endif
+{
+ va_list args;
+#ifdef ANSI_PROTOTYPES
+ va_start (args, format);
+#else
+ GDB_FILE *stream;
+ char *format;
+
+ va_start (args);
+ stream = va_arg (args, GDB_FILE *);
+ format = va_arg (args, char *);
+#endif
+ vfprintf_unfiltered (stream, format, args);
+ va_end (args);
+}
+
+/* Like fprintf_filtered, but prints its result indented.
+ Called as fprintfi_filtered (spaces, stream, format, ...); */
+
+/* VARARGS */
+void
+#ifdef ANSI_PROTOTYPES
+fprintfi_filtered (int spaces, GDB_FILE *stream, const char *format, ...)
+#else
+fprintfi_filtered (va_alist)
+ va_dcl
+#endif
+{
+ va_list args;
+#ifdef ANSI_PROTOTYPES
+ va_start (args, format);
+#else
+ int spaces;
+ GDB_FILE *stream;
+ char *format;
+
+ va_start (args);
+ spaces = va_arg (args, int);
+ stream = va_arg (args, GDB_FILE *);
+ format = va_arg (args, char *);
+#endif
+ print_spaces_filtered (spaces, stream);
+
+ vfprintf_filtered (stream, format, args);
+ va_end (args);
+}
+
+
+/* VARARGS */
+void
+#ifdef ANSI_PROTOTYPES
+printf_filtered (const char *format, ...)
+#else
+printf_filtered (va_alist)
+ va_dcl
+#endif
+{
+ va_list args;
+#ifdef ANSI_PROTOTYPES
+ va_start (args, format);
+#else
+ char *format;
+
+ va_start (args);
+ format = va_arg (args, char *);
+#endif
+ vfprintf_filtered (gdb_stdout, format, args);
+ va_end (args);
+}
+
+
+/* VARARGS */
+void
+#ifdef ANSI_PROTOTYPES
+printf_unfiltered (const char *format, ...)
+#else
+printf_unfiltered (va_alist)
+ va_dcl
+#endif
+{
+ va_list args;
+#ifdef ANSI_PROTOTYPES
+ va_start (args, format);
+#else
+ char *format;
+
+ va_start (args);
+ format = va_arg (args, char *);
+#endif
+ vfprintf_unfiltered (gdb_stdout, format, args);
+ va_end (args);
+}
+
+/* Like printf_filtered, but prints it's result indented.
+ Called as printfi_filtered (spaces, format, ...); */
+
+/* VARARGS */
+void
+#ifdef ANSI_PROTOTYPES
+printfi_filtered (int spaces, const char *format, ...)
+#else
+printfi_filtered (va_alist)
+ va_dcl
+#endif
+{
+ va_list args;
+#ifdef ANSI_PROTOTYPES
+ va_start (args, format);
+#else
+ int spaces;
+ char *format;
+
+ va_start (args);
+ spaces = va_arg (args, int);
+ format = va_arg (args, char *);
+#endif
+ print_spaces_filtered (spaces, gdb_stdout);
+ vfprintf_filtered (gdb_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)
+ const char *string;
+{
+ fputs_filtered (string, gdb_stdout);
+}
+
+void
+puts_unfiltered (string)
+ const char *string;
+{
+ fputs_unfiltered (string, gdb_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;
+ GDB_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)
+ GDB_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_java:
+ demangled = cplus_demangle (name, arg_mode | DMGL_JAVA);
+ 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');
+}
+
+
+/*
+** subsetCompare()
+** Answer whether stringToCompare is a full or partial match to
+** templateString. The partial match must be in sequence starting
+** at index 0.
+*/
+int
+#ifdef _STDC__
+subsetCompare(
+ char *stringToCompare,
+ char *templateString)
+#else
+subsetCompare(stringToCompare, templateString)
+ char *stringToCompare;
+ char *templateString;
+#endif
+{
+ int match = 0;
+
+ if (templateString != (char *)NULL && stringToCompare != (char *)NULL &&
+ strlen(stringToCompare) <= strlen(templateString))
+ match = (strncmp(templateString,
+ stringToCompare,
+ strlen(stringToCompare)) == 0);
+
+ return match;
+} /* subsetCompare */
+
+
+void pagination_on_command(arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ pagination_enabled = 1;
+}
+
+void pagination_off_command(arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ pagination_enabled = 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);
+
+ init_page_info ();
+
+ /* If the output is not a terminal, don't paginate it. */
+ if (!GDB_FILE_ISATTY (gdb_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 ("pagination", class_support,
+ var_boolean, (char *)&pagination_enabled,
+ "Set state of pagination.", &setlist),
+ &showlist);
+ if (xdb_commands)
+ {
+ add_com("am", class_support, pagination_on_command,
+ "Enable pagination");
+ add_com("sm", class_support, pagination_off_command,
+ "Disable pagination");
+ }
+
+ 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
+
+/* Support for converting target fp numbers into host DOUBLEST format. */
+
+/* XXX - This code should really be in libiberty/floatformat.c, however
+ configuration issues with libiberty made this very difficult to do in the
+ available time. */
+
+#include "floatformat.h"
+#include <math.h> /* ldexp */
+
+/* The odds that CHAR_BIT will be anything but 8 are low enough that I'm not
+ going to bother with trying to muck around with whether it is defined in
+ a system header, what we do if not, etc. */
+#define FLOATFORMAT_CHAR_BIT 8
+
+static unsigned long get_field PARAMS ((unsigned char *,
+ enum floatformat_byteorders,
+ unsigned int,
+ unsigned int,
+ unsigned int));
+
+/* Extract a field which starts at START and is LEN bytes long. DATA and
+ TOTAL_LEN are the thing we are extracting it from, in byteorder ORDER. */
+static unsigned long
+get_field (data, order, total_len, start, len)
+ unsigned char *data;
+ enum floatformat_byteorders order;
+ unsigned int total_len;
+ unsigned int start;
+ unsigned int len;
+{
+ unsigned long result;
+ unsigned int cur_byte;
+ int cur_bitshift;
+
+ /* Start at the least significant part of the field. */
+ cur_byte = (start + len) / FLOATFORMAT_CHAR_BIT;
+ if (order == floatformat_little || order == floatformat_littlebyte_bigword)
+ cur_byte = (total_len / FLOATFORMAT_CHAR_BIT) - cur_byte - 1;
+ cur_bitshift =
+ ((start + len) % FLOATFORMAT_CHAR_BIT) - FLOATFORMAT_CHAR_BIT;
+ result = *(data + cur_byte) >> (-cur_bitshift);
+ cur_bitshift += FLOATFORMAT_CHAR_BIT;
+ if (order == floatformat_little || order == floatformat_littlebyte_bigword)
+ ++cur_byte;
+ else
+ --cur_byte;
+
+ /* Move towards the most significant part of the field. */
+ while (cur_bitshift < len)
+ {
+ if (len - cur_bitshift < FLOATFORMAT_CHAR_BIT)
+ /* This is the last byte; zero out the bits which are not part of
+ this field. */
+ result |=
+ (*(data + cur_byte) & ((1 << (len - cur_bitshift)) - 1))
+ << cur_bitshift;
+ else
+ result |= *(data + cur_byte) << cur_bitshift;
+ cur_bitshift += FLOATFORMAT_CHAR_BIT;
+ if (order == floatformat_little || order == floatformat_littlebyte_bigword)
+ ++cur_byte;
+ else
+ --cur_byte;
+ }
+ return result;
+}
+
+/* Convert from FMT to a DOUBLEST.
+ FROM is the address of the extended float.
+ Store the DOUBLEST in *TO. */
+
+void
+floatformat_to_doublest (fmt, from, to)
+ const struct floatformat *fmt;
+ char *from;
+ DOUBLEST *to;
+{
+ unsigned char *ufrom = (unsigned char *)from;
+ DOUBLEST dto;
+ long exponent;
+ unsigned long mant;
+ unsigned int mant_bits, mant_off;
+ int mant_bits_left;
+ int special_exponent; /* It's a NaN, denorm or zero */
+
+ /* If the mantissa bits are not contiguous from one end of the
+ mantissa to the other, we need to make a private copy of the
+ source bytes that is in the right order since the unpacking
+ algorithm assumes that the bits are contiguous.
+
+ Swap the bytes individually rather than accessing them through
+ "long *" since we have no guarantee that they start on a long
+ alignment, and also sizeof(long) for the host could be different
+ than sizeof(long) for the target. FIXME: Assumes sizeof(long)
+ for the target is 4. */
+
+ if (fmt -> byteorder == floatformat_littlebyte_bigword)
+ {
+ static unsigned char *newfrom;
+ unsigned char *swapin, *swapout;
+ int longswaps;
+
+ longswaps = fmt -> totalsize / FLOATFORMAT_CHAR_BIT;
+ longswaps >>= 3;
+
+ if (newfrom == NULL)
+ {
+ newfrom = (unsigned char *) xmalloc (fmt -> totalsize);
+ }
+ swapout = newfrom;
+ swapin = ufrom;
+ ufrom = newfrom;
+ while (longswaps-- > 0)
+ {
+ /* This is ugly, but efficient */
+ *swapout++ = swapin[4];
+ *swapout++ = swapin[5];
+ *swapout++ = swapin[6];
+ *swapout++ = swapin[7];
+ *swapout++ = swapin[0];
+ *swapout++ = swapin[1];
+ *swapout++ = swapin[2];
+ *swapout++ = swapin[3];
+ swapin += 8;
+ }
+ }
+
+ exponent = get_field (ufrom, fmt->byteorder, fmt->totalsize,
+ fmt->exp_start, fmt->exp_len);
+ /* Note that if exponent indicates a NaN, we can't really do anything useful
+ (not knowing if the host has NaN's, or how to build one). So it will
+ end up as an infinity or something close; that is OK. */
+
+ mant_bits_left = fmt->man_len;
+ mant_off = fmt->man_start;
+ dto = 0.0;
+
+ special_exponent = exponent == 0 || exponent == fmt->exp_nan;
+
+/* Don't bias zero's, denorms or NaNs. */
+ if (!special_exponent)
+ exponent -= fmt->exp_bias;
+
+ /* Build the result algebraically. Might go infinite, underflow, etc;
+ who cares. */
+
+/* If this format uses a hidden bit, explicitly add it in now. Otherwise,
+ increment the exponent by one to account for the integer bit. */
+
+ if (!special_exponent)
+ if (fmt->intbit == floatformat_intbit_no)
+ dto = ldexp (1.0, exponent);
+ else
+ exponent++;
+
+ while (mant_bits_left > 0)
+ {
+ mant_bits = min (mant_bits_left, 32);
+
+ mant = get_field (ufrom, fmt->byteorder, fmt->totalsize,
+ mant_off, mant_bits);
+
+ dto += ldexp ((double)mant, exponent - mant_bits);
+ exponent -= mant_bits;
+ mant_off += mant_bits;
+ mant_bits_left -= mant_bits;
+ }
+
+ /* Negate it if negative. */
+ if (get_field (ufrom, fmt->byteorder, fmt->totalsize, fmt->sign_start, 1))
+ dto = -dto;
+ *to = dto;
+}
+
+static void put_field PARAMS ((unsigned char *, enum floatformat_byteorders,
+ unsigned int,
+ unsigned int,
+ unsigned int,
+ unsigned long));
+
+/* Set a field which starts at START and is LEN bytes long. DATA and
+ TOTAL_LEN are the thing we are extracting it from, in byteorder ORDER. */
+static void
+put_field (data, order, total_len, start, len, stuff_to_put)
+ unsigned char *data;
+ enum floatformat_byteorders order;
+ unsigned int total_len;
+ unsigned int start;
+ unsigned int len;
+ unsigned long stuff_to_put;
+{
+ unsigned int cur_byte;
+ int cur_bitshift;
+
+ /* Start at the least significant part of the field. */
+ cur_byte = (start + len) / FLOATFORMAT_CHAR_BIT;
+ if (order == floatformat_little || order == floatformat_littlebyte_bigword)
+ cur_byte = (total_len / FLOATFORMAT_CHAR_BIT) - cur_byte - 1;
+ cur_bitshift =
+ ((start + len) % FLOATFORMAT_CHAR_BIT) - FLOATFORMAT_CHAR_BIT;
+ *(data + cur_byte) &=
+ ~(((1 << ((start + len) % FLOATFORMAT_CHAR_BIT)) - 1) << (-cur_bitshift));
+ *(data + cur_byte) |=
+ (stuff_to_put & ((1 << FLOATFORMAT_CHAR_BIT) - 1)) << (-cur_bitshift);
+ cur_bitshift += FLOATFORMAT_CHAR_BIT;
+ if (order == floatformat_little || order == floatformat_littlebyte_bigword)
+ ++cur_byte;
+ else
+ --cur_byte;
+
+ /* Move towards the most significant part of the field. */
+ while (cur_bitshift < len)
+ {
+ if (len - cur_bitshift < FLOATFORMAT_CHAR_BIT)
+ {
+ /* This is the last byte. */
+ *(data + cur_byte) &=
+ ~((1 << (len - cur_bitshift)) - 1);
+ *(data + cur_byte) |= (stuff_to_put >> cur_bitshift);
+ }
+ else
+ *(data + cur_byte) = ((stuff_to_put >> cur_bitshift)
+ & ((1 << FLOATFORMAT_CHAR_BIT) - 1));
+ cur_bitshift += FLOATFORMAT_CHAR_BIT;
+ if (order == floatformat_little || order == floatformat_littlebyte_bigword)
+ ++cur_byte;
+ else
+ --cur_byte;
+ }
+}
+
+#ifdef HAVE_LONG_DOUBLE
+/* Return the fractional part of VALUE, and put the exponent of VALUE in *EPTR.
+ The range of the returned value is >= 0.5 and < 1.0. This is equivalent to
+ frexp, but operates on the long double data type. */
+
+static long double ldfrexp PARAMS ((long double value, int *eptr));
+
+static long double
+ldfrexp (value, eptr)
+ long double value;
+ int *eptr;
+{
+ long double tmp;
+ int exp;
+
+ /* Unfortunately, there are no portable functions for extracting the exponent
+ of a long double, so we have to do it iteratively by multiplying or dividing
+ by two until the fraction is between 0.5 and 1.0. */
+
+ if (value < 0.0l)
+ value = -value;
+
+ tmp = 1.0l;
+ exp = 0;
+
+ if (value >= tmp) /* Value >= 1.0 */
+ while (value >= tmp)
+ {
+ tmp *= 2.0l;
+ exp++;
+ }
+ else if (value != 0.0l) /* Value < 1.0 and > 0.0 */
+ {
+ while (value < tmp)
+ {
+ tmp /= 2.0l;
+ exp--;
+ }
+ tmp *= 2.0l;
+ exp++;
+ }
+
+ *eptr = exp;
+ return value/tmp;
+}
+#endif /* HAVE_LONG_DOUBLE */
+
+
+/* The converse: convert the DOUBLEST *FROM to an extended float
+ and store where TO points. Neither FROM nor TO have any alignment
+ restrictions. */
+
+void
+floatformat_from_doublest (fmt, from, to)
+ CONST struct floatformat *fmt;
+ DOUBLEST *from;
+ char *to;
+{
+ DOUBLEST dfrom;
+ int exponent;
+ DOUBLEST mant;
+ unsigned int mant_bits, mant_off;
+ int mant_bits_left;
+ unsigned char *uto = (unsigned char *)to;
+
+ memcpy (&dfrom, from, sizeof (dfrom));
+ memset (uto, 0, fmt->totalsize / FLOATFORMAT_CHAR_BIT);
+ if (dfrom == 0)
+ return; /* Result is zero */
+ if (dfrom != dfrom) /* Result is NaN */
+ {
+ /* From is NaN */
+ put_field (uto, fmt->byteorder, fmt->totalsize, fmt->exp_start,
+ fmt->exp_len, fmt->exp_nan);
+ /* Be sure it's not infinity, but NaN value is irrel */
+ put_field (uto, fmt->byteorder, fmt->totalsize, fmt->man_start,
+ 32, 1);
+ return;
+ }
+
+ /* If negative, set the sign bit. */
+ if (dfrom < 0)
+ {
+ put_field (uto, fmt->byteorder, fmt->totalsize, fmt->sign_start, 1, 1);
+ dfrom = -dfrom;
+ }
+
+ if (dfrom + dfrom == dfrom && dfrom != 0.0) /* Result is Infinity */
+ {
+ /* Infinity exponent is same as NaN's. */
+ put_field (uto, fmt->byteorder, fmt->totalsize, fmt->exp_start,
+ fmt->exp_len, fmt->exp_nan);
+ /* Infinity mantissa is all zeroes. */
+ put_field (uto, fmt->byteorder, fmt->totalsize, fmt->man_start,
+ fmt->man_len, 0);
+ return;
+ }
+
+#ifdef HAVE_LONG_DOUBLE
+ mant = ldfrexp (dfrom, &exponent);
+#else
+ mant = frexp (dfrom, &exponent);
+#endif
+
+ put_field (uto, fmt->byteorder, fmt->totalsize, fmt->exp_start, fmt->exp_len,
+ exponent + fmt->exp_bias - 1);
+
+ mant_bits_left = fmt->man_len;
+ mant_off = fmt->man_start;
+ while (mant_bits_left > 0)
+ {
+ unsigned long mant_long;
+ mant_bits = mant_bits_left < 32 ? mant_bits_left : 32;
+
+ mant *= 4294967296.0;
+ mant_long = (unsigned long)mant;
+ mant -= mant_long;
+
+ /* If the integer bit is implicit, then we need to discard it.
+ If we are discarding a zero, we should be (but are not) creating
+ a denormalized number which means adjusting the exponent
+ (I think). */
+ if (mant_bits_left == fmt->man_len
+ && fmt->intbit == floatformat_intbit_no)
+ {
+ mant_long <<= 1;
+ mant_bits -= 1;
+ }
+
+ if (mant_bits < 32)
+ {
+ /* The bits we want are in the most significant MANT_BITS bits of
+ mant_long. Move them to the least significant. */
+ mant_long >>= 32 - mant_bits;
+ }
+
+ put_field (uto, fmt->byteorder, fmt->totalsize,
+ mant_off, mant_bits, mant_long);
+ mant_off += mant_bits;
+ mant_bits_left -= mant_bits;
+ }
+ if (fmt -> byteorder == floatformat_littlebyte_bigword)
+ {
+ int count;
+ unsigned char *swaplow = uto;
+ unsigned char *swaphigh = uto + 4;
+ unsigned char tmp;
+
+ for (count = 0; count < 4; count++)
+ {
+ tmp = *swaplow;
+ *swaplow++ = *swaphigh;
+ *swaphigh++ = tmp;
+ }
+ }
+}
+
+/* temporary storage using circular buffer */
+#define NUMCELLS 16
+#define CELLSIZE 32
+static char*
+get_cell()
+{
+ static char buf[NUMCELLS][CELLSIZE];
+ static int cell=0;
+ if (++cell>=NUMCELLS) cell=0;
+ return buf[cell];
+}
+
+/* print routines to handle variable size regs, etc.
+
+ FIXME: Note that t_addr is a bfd_vma, which is currently either an
+ unsigned long or unsigned long long, determined at configure time.
+ If t_addr is an unsigned long long and sizeof (unsigned long long)
+ is greater than sizeof (unsigned long), then I believe this code will
+ probably lose, at least for little endian machines. I believe that
+ it would also be better to eliminate the switch on the absolute size
+ of t_addr and replace it with a sequence of if statements that compare
+ sizeof t_addr with sizeof the various types and do the right thing,
+ which includes knowing whether or not the host supports long long.
+ -fnf
+
+ */
+
+static int thirty_two = 32; /* eliminate warning from compiler on 32-bit systems */
+
+char*
+paddr(addr)
+ t_addr addr;
+{
+ char *paddr_str=get_cell();
+ switch (sizeof(t_addr))
+ {
+ case 8:
+ sprintf (paddr_str, "%08lx%08lx",
+ (unsigned long) (addr >> thirty_two), (unsigned long) (addr & 0xffffffff));
+ break;
+ case 4:
+ sprintf (paddr_str, "%08lx", (unsigned long) addr);
+ break;
+ case 2:
+ sprintf (paddr_str, "%04x", (unsigned short) (addr & 0xffff));
+ break;
+ default:
+ sprintf (paddr_str, "%lx", (unsigned long) addr);
+ }
+ return paddr_str;
+}
+
+char*
+preg(reg)
+ t_reg reg;
+{
+ char *preg_str=get_cell();
+ switch (sizeof(t_reg))
+ {
+ case 8:
+ sprintf (preg_str, "%08lx%08lx",
+ (unsigned long) (reg >> thirty_two), (unsigned long) (reg & 0xffffffff));
+ break;
+ case 4:
+ sprintf (preg_str, "%08lx", (unsigned long) reg);
+ break;
+ case 2:
+ sprintf (preg_str, "%04x", (unsigned short) (reg & 0xffff));
+ break;
+ default:
+ sprintf (preg_str, "%lx", (unsigned long) reg);
+ }
+ return preg_str;
+}
+
+char*
+paddr_nz(addr)
+ t_addr addr;
+{
+ char *paddr_str=get_cell();
+ switch (sizeof(t_addr))
+ {
+ case 8:
+ {
+ unsigned long high = (unsigned long) (addr >> thirty_two);
+ if (high == 0)
+ sprintf (paddr_str, "%lx", (unsigned long) (addr & 0xffffffff));
+ else
+ sprintf (paddr_str, "%lx%08lx",
+ high, (unsigned long) (addr & 0xffffffff));
+ break;
+ }
+ case 4:
+ sprintf (paddr_str, "%lx", (unsigned long) addr);
+ break;
+ case 2:
+ sprintf (paddr_str, "%x", (unsigned short) (addr & 0xffff));
+ break;
+ default:
+ sprintf (paddr_str,"%lx", (unsigned long) addr);
+ }
+ return paddr_str;
+}
+
+char*
+preg_nz(reg)
+ t_reg reg;
+{
+ char *preg_str=get_cell();
+ switch (sizeof(t_reg))
+ {
+ case 8:
+ {
+ unsigned long high = (unsigned long) (reg >> thirty_two);
+ if (high == 0)
+ sprintf (preg_str, "%lx", (unsigned long) (reg & 0xffffffff));
+ else
+ sprintf (preg_str, "%lx%08lx",
+ high, (unsigned long) (reg & 0xffffffff));
+ break;
+ }
+ case 4:
+ sprintf (preg_str, "%lx", (unsigned long) reg);
+ break;
+ case 2:
+ sprintf (preg_str, "%x", (unsigned short) (reg & 0xffff));
+ break;
+ default:
+ sprintf (preg_str, "%lx", (unsigned long) reg);
+ }
+ return preg_str;
+}
diff --git a/gdb/v850-tdep.c b/gdb/v850-tdep.c
new file mode 100644
index 00000000000..b98a4bdb200
--- /dev/null
+++ b/gdb/v850-tdep.c
@@ -0,0 +1,884 @@
+/* Target-dependent code for the NEC V850 for GDB, the GNU debugger.
+ Copyright 1996, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "frame.h"
+#include "inferior.h"
+#include "obstack.h"
+#include "target.h"
+#include "value.h"
+#include "bfd.h"
+#include "gdb_string.h"
+#include "gdbcore.h"
+#include "symfile.h"
+
+
+static char *v850_generic_reg_names[] = REGISTER_NAMES;
+
+static char *v850e_reg_names[] =
+{
+ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
+ "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
+ "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
+ "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
+ "eipc", "eipsw", "fepc", "fepsw", "ecr", "psw", "sr6", "sr7",
+ "sr8", "sr9", "sr10", "sr11", "sr12", "sr13", "sr14", "sr15",
+ "ctpc", "ctpsw", "dbpc", "dbpsw", "ctbp", "sr21", "sr22", "sr23",
+ "sr24", "sr25", "sr26", "sr27", "sr28", "sr29", "sr30", "sr31",
+ "pc", "fp"
+};
+
+char **v850_register_names = v850_generic_reg_names;
+
+struct
+{
+ char **regnames;
+ int mach;
+} v850_processor_type_table[] =
+{
+ { v850_generic_reg_names, bfd_mach_v850 },
+ { v850e_reg_names, bfd_mach_v850e },
+ { v850e_reg_names, bfd_mach_v850ea },
+ { NULL, 0 }
+};
+
+/* Info gleaned from scanning a function's prologue. */
+
+struct pifsr /* Info about one saved reg */
+{
+ int framereg; /* Frame reg (SP or FP) */
+ int offset; /* Offset from framereg */
+ int cur_frameoffset; /* Current frameoffset */
+ int reg; /* Saved register number */
+};
+
+struct prologue_info
+{
+ int framereg;
+ int frameoffset;
+ int start_function;
+ struct pifsr *pifsrs;
+};
+
+static CORE_ADDR v850_scan_prologue PARAMS ((CORE_ADDR pc,
+ struct prologue_info *fs));
+
+
+/* Should call_function allocate stack space for a struct return? */
+int
+v850_use_struct_convention (gcc_p, type)
+ int gcc_p;
+ struct type *type;
+{
+ return (TYPE_NFIELDS (type) > 1 || TYPE_LENGTH (type) > 4);
+}
+
+
+
+/* Structure for mapping bits in register lists to register numbers. */
+struct reg_list
+{
+ long mask;
+ int regno;
+};
+
+/* Helper function for v850_scan_prologue to handle prepare instruction. */
+
+static void
+handle_prepare (int insn, int insn2, CORE_ADDR *current_pc_ptr,
+ struct prologue_info *pi, struct pifsr **pifsr_ptr)
+
+{
+ CORE_ADDR current_pc = *current_pc_ptr;
+ struct pifsr *pifsr = *pifsr_ptr;
+ long next = insn2 & 0xffff;
+ long list12 = ((insn & 1) << 16) + (next & 0xffe0);
+ long offset = (insn & 0x3e) << 1;
+ static struct reg_list reg_table [] =
+ {
+ { 0x00800, 20 }, /* r20 */
+ { 0x00400, 21 }, /* r21 */
+ { 0x00200, 22 }, /* r22 */
+ { 0x00100, 23 }, /* r23 */
+ { 0x08000, 24 }, /* r24 */
+ { 0x04000, 25 }, /* r25 */
+ { 0x02000, 26 }, /* r26 */
+ { 0x01000, 27 }, /* r27 */
+ { 0x00080, 28 }, /* r28 */
+ { 0x00040, 29 }, /* r29 */
+ { 0x10000, 30 }, /* ep */
+ { 0x00020, 31 }, /* lp */
+ { 0, 0 } /* end of table */
+ };
+ int i;
+
+ if ((next & 0x1f) == 0x0b) /* skip imm16 argument */
+ current_pc += 2;
+ else if ((next & 0x1f) == 0x13) /* skip imm16 argument */
+ current_pc += 2;
+ else if ((next & 0x1f) == 0x1b) /* skip imm32 argument */
+ current_pc += 4;
+
+ /* Calculate the total size of the saved registers, and add it
+ it to the immediate value used to adjust SP. */
+ for (i = 0; reg_table[i].mask != 0; i++)
+ if (list12 & reg_table[i].mask)
+ offset += REGISTER_RAW_SIZE (regtable[i].regno);
+ pi->frameoffset -= offset;
+
+ /* Calculate the offsets of the registers relative to the value
+ the SP will have after the registers have been pushed and the
+ imm5 value has been subtracted from it. */
+ if (pifsr)
+ {
+ for (i = 0; reg_table[i].mask != 0; i++)
+ {
+ if (list12 & reg_table[i].mask)
+ {
+ int reg = reg_table[i].regno;
+ offset -= REGISTER_RAW_SIZE (reg);
+ pifsr->reg = reg;
+ pifsr->offset = offset;
+ pifsr->cur_frameoffset = pi->frameoffset;
+ #ifdef DEBUG
+ printf_filtered ("\tSaved register r%d, offset %d", reg, pifsr->offset);
+ #endif
+ pifsr++;
+ }
+ }
+ }
+#ifdef DEBUG
+ printf_filtered ("\tfound ctret after regsave func");
+#endif
+
+ /* Set result parameters. */
+ *current_pc_ptr = current_pc;
+ *pifsr_ptr = pifsr;
+}
+
+
+/* Helper function for v850_scan_prologue to handle pushm/pushl instructions.
+ FIXME: the SR bit of the register list is not supported; must check
+ that the compiler does not ever generate this bit. */
+
+static void
+handle_pushm (int insn, int insn2, struct prologue_info *pi,
+ struct pifsr **pifsr_ptr)
+
+{
+ struct pifsr *pifsr = *pifsr_ptr;
+ long list12 = ((insn & 0x0f) << 16) + (insn2 & 0xfff0);
+ long offset = 0;
+ static struct reg_list pushml_reg_table [] =
+ {
+ { 0x80000, PS_REGNUM }, /* PSW */
+ { 0x40000, 1 }, /* r1 */
+ { 0x20000, 2 }, /* r2 */
+ { 0x10000, 3 }, /* r3 */
+ { 0x00800, 4 }, /* r4 */
+ { 0x00400, 5 }, /* r5 */
+ { 0x00200, 6 }, /* r6 */
+ { 0x00100, 7 }, /* r7 */
+ { 0x08000, 8 }, /* r8 */
+ { 0x04000, 9 }, /* r9 */
+ { 0x02000, 10 }, /* r10 */
+ { 0x01000, 11 }, /* r11 */
+ { 0x00080, 12 }, /* r12 */
+ { 0x00040, 13 }, /* r13 */
+ { 0x00020, 14 }, /* r14 */
+ { 0x00010, 15 }, /* r15 */
+ { 0, 0 } /* end of table */
+ };
+ static struct reg_list pushmh_reg_table [] =
+ {
+ { 0x80000, 16 }, /* r16 */
+ { 0x40000, 17 }, /* r17 */
+ { 0x20000, 18 }, /* r18 */
+ { 0x10000, 19 }, /* r19 */
+ { 0x00800, 20 }, /* r20 */
+ { 0x00400, 21 }, /* r21 */
+ { 0x00200, 22 }, /* r22 */
+ { 0x00100, 23 }, /* r23 */
+ { 0x08000, 24 }, /* r24 */
+ { 0x04000, 25 }, /* r25 */
+ { 0x02000, 26 }, /* r26 */
+ { 0x01000, 27 }, /* r27 */
+ { 0x00080, 28 }, /* r28 */
+ { 0x00040, 29 }, /* r29 */
+ { 0x00010, 30 }, /* r30 */
+ { 0x00020, 31 }, /* r31 */
+ { 0, 0 } /* end of table */
+ };
+ struct reg_list *reg_table;
+ int i;
+
+ /* Is this a pushml or a pushmh? */
+ if ((insn2 & 7) == 1)
+ reg_table = pushml_reg_table;
+ else
+ reg_table = pushmh_reg_table;
+
+ /* Calculate the total size of the saved registers, and add it
+ it to the immediate value used to adjust SP. */
+ for (i = 0; reg_table[i].mask != 0; i++)
+ if (list12 & reg_table[i].mask)
+ offset += REGISTER_RAW_SIZE (regtable[i].regno);
+ pi->frameoffset -= offset;
+
+ /* Calculate the offsets of the registers relative to the value
+ the SP will have after the registers have been pushed and the
+ imm5 value is subtracted from it. */
+ if (pifsr)
+ {
+ for (i = 0; reg_table[i].mask != 0; i++)
+ {
+ if (list12 & reg_table[i].mask)
+ {
+ int reg = reg_table[i].regno;
+ offset -= REGISTER_RAW_SIZE (reg);
+ pifsr->reg = reg;
+ pifsr->offset = offset;
+ pifsr->cur_frameoffset = pi->frameoffset;
+ #ifdef DEBUG
+ printf_filtered ("\tSaved register r%d, offset %d", reg, pifsr->offset);
+ #endif
+ pifsr++;
+ }
+ }
+ }
+#ifdef DEBUG
+ printf_filtered ("\tfound ctret after regsave func");
+#endif
+
+ /* Set result parameters. */
+ *pifsr_ptr = pifsr;
+}
+
+
+
+
+/* Function: scan_prologue
+ Scan the prologue of the function that contains PC, and record what
+ we find in PI. PI->fsr must be zeroed by the called. Returns the
+ pc after the prologue. Note that the addresses saved in pi->fsr
+ are actually just frame relative (negative offsets from the frame
+ pointer). This is because we don't know the actual value of the
+ frame pointer yet. In some circumstances, the frame pointer can't
+ be determined till after we have scanned the prologue. */
+
+static CORE_ADDR
+v850_scan_prologue (pc, pi)
+ CORE_ADDR pc;
+ struct prologue_info *pi;
+{
+ CORE_ADDR func_addr, prologue_end, current_pc;
+ struct pifsr *pifsr, *pifsr_tmp;
+ int fp_used;
+ int ep_used;
+ int reg;
+ CORE_ADDR save_pc, save_end;
+ int regsave_func_p;
+ int r12_tmp;
+
+ /* First, figure out the bounds of the prologue so that we can limit the
+ search to something reasonable. */
+
+ if (find_pc_partial_function (pc, NULL, &func_addr, NULL))
+ {
+ struct symtab_and_line sal;
+
+ sal = find_pc_line (func_addr, 0);
+
+ if (func_addr == entry_point_address ())
+ pi->start_function = 1;
+ else
+ pi->start_function = 0;
+
+#if 0
+ if (sal.line == 0)
+ prologue_end = pc;
+ else
+ prologue_end = sal.end;
+#else
+ prologue_end = pc;
+#endif
+ }
+ else
+ { /* We're in the boondocks */
+ func_addr = pc - 100;
+ prologue_end = pc;
+ }
+
+ prologue_end = min (prologue_end, pc);
+
+ /* Now, search the prologue looking for instructions that setup fp, save
+ rp, adjust sp and such. We also record the frame offset of any saved
+ registers. */
+
+ pi->frameoffset = 0;
+ pi->framereg = SP_REGNUM;
+ fp_used = 0;
+ ep_used = 0;
+ pifsr = pi->pifsrs;
+ regsave_func_p = 0;
+ save_pc = 0;
+ save_end = 0;
+ r12_tmp = 0;
+
+#ifdef DEBUG
+ printf_filtered ("Current_pc = 0x%.8lx, prologue_end = 0x%.8lx\n",
+ (long)func_addr, (long)prologue_end);
+#endif
+
+ for (current_pc = func_addr; current_pc < prologue_end; )
+ {
+ int insn, insn2;
+
+#ifdef DEBUG
+ printf_filtered ("0x%.8lx ", (long)current_pc);
+ (*tm_print_insn) (current_pc, &tm_print_insn_info);
+#endif
+
+ insn = read_memory_unsigned_integer (current_pc, 2);
+ current_pc += 2;
+ if ((insn & 0x0780) >= 0x0600) /* Four byte instruction? */
+ {
+ insn2 = read_memory_unsigned_integer (current_pc, 2);
+ current_pc += 2;
+ }
+
+ if ((insn & 0xffc0) == ((10 << 11) | 0x0780) && !regsave_func_p)
+ { /* jarl <func>,10 */
+ long low_disp = insn2 & ~ (long) 1;
+ long disp = (((((insn & 0x3f) << 16) + low_disp)
+ & ~ (long) 1) ^ 0x00200000) - 0x00200000;
+
+ save_pc = current_pc;
+ save_end = prologue_end;
+ regsave_func_p = 1;
+ current_pc += disp - 4;
+ prologue_end = (current_pc
+ + (2 * 3) /* moves to/from ep */
+ + 4 /* addi <const>,sp,sp */
+ + 2 /* jmp [r10] */
+ + (2 * 12) /* sst.w to save r2, r20-r29, r31 */
+ + 20); /* slop area */
+
+#ifdef DEBUG
+ printf_filtered ("\tfound jarl <func>,r10, disp = %ld, low_disp = %ld, new pc = 0x%.8lx\n",
+ disp, low_disp, (long)current_pc + 2);
+#endif
+ continue;
+ }
+ else if ((insn & 0xffc0) == 0x0200 && !regsave_func_p)
+ { /* callt <imm6> */
+ long ctbp = read_register (CTBP_REGNUM);
+ long adr = ctbp + ((insn & 0x3f) << 1);
+
+ save_pc = current_pc;
+ save_end = prologue_end;
+ regsave_func_p = 1;
+ current_pc = ctbp + (read_memory_unsigned_integer (adr, 2) & 0xffff);
+ prologue_end = (current_pc
+ + (2 * 3) /* prepare list2,imm5,sp/imm */
+ + 4 /* ctret */
+ + 20); /* slop area */
+
+#ifdef DEBUG
+ printf_filtered ("\tfound callt, ctbp = 0x%.8lx, adr = %.8lx, new pc = 0x%.8lx\n",
+ ctbp, adr, (long)current_pc);
+#endif
+ continue;
+ }
+ else if ((insn & 0xffc0) == 0x0780) /* prepare list2,imm5 */
+ {
+ handle_prepare (insn, insn2, &current_pc, pi, &pifsr);
+ continue;
+ }
+ else if (insn == 0x07e0 && regsave_func_p && insn2 == 0x0144)
+ { /* ctret after processing register save function */
+ current_pc = save_pc;
+ prologue_end = save_end;
+ regsave_func_p = 0;
+#ifdef DEBUG
+ printf_filtered ("\tfound ctret after regsave func");
+#endif
+ continue;
+ }
+ else if ((insn & 0xfff0) == 0x07e0 && (insn2 & 5) == 1)
+ { /* pushml, pushmh */
+ handle_pushm (insn, insn2, pi, &pifsr);
+ continue;
+ }
+ else if ((insn & 0xffe0) == 0x0060 && regsave_func_p)
+ { /* jmp after processing register save function */
+ current_pc = save_pc;
+ prologue_end = save_end;
+ regsave_func_p = 0;
+#ifdef DEBUG
+ printf_filtered ("\tfound jmp after regsave func");
+#endif
+ continue;
+ }
+ else if ((insn & 0x07c0) == 0x0780 /* jarl or jr */
+ || (insn & 0xffe0) == 0x0060 /* jmp */
+ || (insn & 0x0780) == 0x0580) /* branch */
+ {
+#ifdef DEBUG
+ printf_filtered ("\n");
+#endif
+ break; /* Ran into end of prologue */
+ }
+
+ else if ((insn & 0xffe0) == ((SP_REGNUM << 11) | 0x0240)) /* add <imm>,sp */
+ pi->frameoffset += ((insn & 0x1f) ^ 0x10) - 0x10;
+ else if (insn == ((SP_REGNUM << 11) | 0x0600 | SP_REGNUM)) /* addi <imm>,sp,sp */
+ pi->frameoffset += insn2;
+ else if (insn == ((FP_RAW_REGNUM << 11) | 0x0000 | SP_REGNUM)) /* mov sp,fp */
+ {
+ fp_used = 1;
+ pi->framereg = FP_RAW_REGNUM;
+ }
+
+ else if (insn == ((R12_REGNUM << 11) | 0x0640 | R0_REGNUM)) /* movhi hi(const),r0,r12 */
+ r12_tmp = insn2 << 16;
+ else if (insn == ((R12_REGNUM << 11) | 0x0620 | R12_REGNUM)) /* movea lo(const),r12,r12 */
+ r12_tmp += insn2;
+ else if (insn == ((SP_REGNUM << 11) | 0x01c0 | R12_REGNUM) && r12_tmp) /* add r12,sp */
+ pi->frameoffset = r12_tmp;
+ else if (insn == ((EP_REGNUM << 11) | 0x0000 | SP_REGNUM)) /* mov sp,ep */
+ ep_used = 1;
+ else if (insn == ((EP_REGNUM << 11) | 0x0000 | R1_REGNUM)) /* mov r1,ep */
+ ep_used = 0;
+ else if (((insn & 0x07ff) == (0x0760 | SP_REGNUM) /* st.w <reg>,<offset>[sp] */
+ || (fp_used
+ && (insn & 0x07ff) == (0x0760 | FP_RAW_REGNUM))) /* st.w <reg>,<offset>[fp] */
+ && pifsr
+ && (((reg = (insn >> 11) & 0x1f) >= SAVE1_START_REGNUM && reg <= SAVE1_END_REGNUM)
+ || (reg >= SAVE2_START_REGNUM && reg <= SAVE2_END_REGNUM)
+ || (reg >= SAVE3_START_REGNUM && reg <= SAVE3_END_REGNUM)))
+ {
+ pifsr->reg = reg;
+ pifsr->offset = insn2 & ~1;
+ pifsr->cur_frameoffset = pi->frameoffset;
+#ifdef DEBUG
+ printf_filtered ("\tSaved register r%d, offset %d", reg, pifsr->offset);
+#endif
+ pifsr++;
+ }
+
+ else if (ep_used /* sst.w <reg>,<offset>[ep] */
+ && ((insn & 0x0781) == 0x0501)
+ && pifsr
+ && (((reg = (insn >> 11) & 0x1f) >= SAVE1_START_REGNUM && reg <= SAVE1_END_REGNUM)
+ || (reg >= SAVE2_START_REGNUM && reg <= SAVE2_END_REGNUM)
+ || (reg >= SAVE3_START_REGNUM && reg <= SAVE3_END_REGNUM)))
+ {
+ pifsr->reg = reg;
+ pifsr->offset = (insn & 0x007e) << 1;
+ pifsr->cur_frameoffset = pi->frameoffset;
+#ifdef DEBUG
+ printf_filtered ("\tSaved register r%d, offset %d", reg, pifsr->offset);
+#endif
+ pifsr++;
+ }
+
+#ifdef DEBUG
+ printf_filtered ("\n");
+#endif
+ }
+
+ if (pifsr)
+ pifsr->framereg = 0; /* Tie off last entry */
+
+ /* Fix up any offsets to the final offset. If a frame pointer was created, use it
+ instead of the stack pointer. */
+ for (pifsr_tmp = pi->pifsrs; pifsr_tmp && pifsr_tmp != pifsr; pifsr_tmp++)
+ {
+ pifsr_tmp->offset -= pi->frameoffset - pifsr_tmp->cur_frameoffset;
+ pifsr_tmp->framereg = pi->framereg;
+
+#ifdef DEBUG
+ printf_filtered ("Saved register r%d, offset = %d, framereg = r%d\n",
+ pifsr_tmp->reg, pifsr_tmp->offset, pifsr_tmp->framereg);
+#endif
+ }
+
+#ifdef DEBUG
+ printf_filtered ("Framereg = r%d, frameoffset = %d\n", pi->framereg, pi->frameoffset);
+#endif
+
+ return current_pc;
+}
+
+/* Function: init_extra_frame_info
+ Setup the frame's frame pointer, pc, and frame addresses for saved
+ registers. Most of the work is done in scan_prologue().
+
+ Note that when we are called for the last frame (currently active frame),
+ that fi->pc and fi->frame will already be setup. However, fi->frame will
+ be valid only if this routine uses FP. For previous frames, fi-frame will
+ always be correct (since that is derived from v850_frame_chain ()).
+
+ We can be called with the PC in the call dummy under two circumstances.
+ First, during normal backtracing, second, while figuring out the frame
+ pointer just prior to calling the target function (see run_stack_dummy). */
+
+void
+v850_init_extra_frame_info (fi)
+ struct frame_info *fi;
+{
+ struct prologue_info pi;
+ struct pifsr pifsrs[NUM_REGS + 1], *pifsr;
+
+ if (fi->next)
+ fi->pc = FRAME_SAVED_PC (fi->next);
+
+ memset (fi->fsr.regs, '\000', sizeof fi->fsr.regs);
+
+ /* The call dummy doesn't save any registers on the stack, so we can return
+ now. */
+ if (PC_IN_CALL_DUMMY (fi->pc, fi->frame, fi->frame))
+ return;
+
+ pi.pifsrs = pifsrs;
+
+ v850_scan_prologue (fi->pc, &pi);
+
+ if (!fi->next && pi.framereg == SP_REGNUM)
+ fi->frame = read_register (pi.framereg) - pi.frameoffset;
+
+ for (pifsr = pifsrs; pifsr->framereg; pifsr++)
+ {
+ fi->fsr.regs[pifsr->reg] = pifsr->offset + fi->frame;
+
+ if (pifsr->framereg == SP_REGNUM)
+ fi->fsr.regs[pifsr->reg] += pi.frameoffset;
+ }
+}
+
+/* Function: frame_chain
+ Figure out the frame prior to FI. Unfortunately, this involves
+ scanning the prologue of the caller, which will also be done
+ shortly by v850_init_extra_frame_info. For the dummy frame, we
+ just return the stack pointer that was in use at the time the
+ function call was made. */
+
+CORE_ADDR
+v850_frame_chain (fi)
+ struct frame_info *fi;
+{
+ struct prologue_info pi;
+ CORE_ADDR callers_pc, fp;
+
+ /* First, find out who called us */
+ callers_pc = FRAME_SAVED_PC (fi);
+ /* If caller is a call-dummy, then our FP bears no relation to his FP! */
+ fp = v850_find_callers_reg (fi, FP_RAW_REGNUM);
+ if (PC_IN_CALL_DUMMY(callers_pc, fp, fp))
+ return fp; /* caller is call-dummy: return oldest value of FP */
+
+ /* Caller is NOT a call-dummy, so everything else should just work.
+ Even if THIS frame is a call-dummy! */
+ pi.pifsrs = NULL;
+
+ v850_scan_prologue (callers_pc, &pi);
+
+ if (pi.start_function)
+ return 0; /* Don't chain beyond the start function */
+
+ if (pi.framereg == FP_RAW_REGNUM)
+ return v850_find_callers_reg (fi, pi.framereg);
+
+ return fi->frame - pi.frameoffset;
+}
+
+/* Function: find_callers_reg
+ Find REGNUM on the stack. Otherwise, it's in an active register.
+ One thing we might want to do here is to check REGNUM against the
+ clobber mask, and somehow flag it as invalid if it isn't saved on
+ the stack somewhere. This would provide a graceful failure mode
+ when trying to get the value of caller-saves registers for an inner
+ frame. */
+
+CORE_ADDR
+v850_find_callers_reg (fi, regnum)
+ struct frame_info *fi;
+ int regnum;
+{
+ for (; fi; fi = fi->next)
+ if (PC_IN_CALL_DUMMY (fi->pc, fi->frame, fi->frame))
+ return generic_read_register_dummy (fi->pc, fi->frame, regnum);
+ else if (fi->fsr.regs[regnum] != 0)
+ return read_memory_unsigned_integer (fi->fsr.regs[regnum],
+ REGISTER_RAW_SIZE(regnum));
+
+ return read_register (regnum);
+}
+
+/* Function: skip_prologue
+ Return the address of the first code past the prologue of the function. */
+
+CORE_ADDR
+v850_skip_prologue (pc)
+ CORE_ADDR pc;
+{
+ CORE_ADDR func_addr, func_end;
+
+ /* See what the symbol table says */
+
+ if (find_pc_partial_function (pc, NULL, &func_addr, &func_end))
+ {
+ struct symtab_and_line sal;
+
+ sal = find_pc_line (func_addr, 0);
+
+ if (sal.line != 0 && sal.end < func_end)
+ return sal.end;
+ else
+ /* Either there's no line info, or the line after the prologue is after
+ the end of the function. In this case, there probably isn't a
+ prologue. */
+ return pc;
+ }
+
+/* We can't find the start of this function, so there's nothing we can do. */
+ return pc;
+}
+
+/* Function: pop_frame
+ This routine gets called when either the user uses the `return'
+ command, or the call dummy breakpoint gets hit. */
+
+void
+v850_pop_frame (frame)
+ struct frame_info *frame;
+{
+ int regnum;
+
+ if (PC_IN_CALL_DUMMY(frame->pc, frame->frame, frame->frame))
+ generic_pop_dummy_frame ();
+ else
+ {
+ write_register (PC_REGNUM, FRAME_SAVED_PC (frame));
+
+ for (regnum = 0; regnum < NUM_REGS; regnum++)
+ if (frame->fsr.regs[regnum] != 0)
+ write_register (regnum,
+ read_memory_unsigned_integer (frame->fsr.regs[regnum],
+ REGISTER_RAW_SIZE(regnum)));
+
+ write_register (SP_REGNUM, FRAME_FP (frame));
+ }
+
+ flush_cached_frames ();
+}
+
+/* Function: push_arguments
+ Setup arguments and RP for a call to the target. First four args
+ go in R6->R9, subsequent args go into sp + 16 -> sp + ... Structs
+ are passed by reference. 64 bit quantities (doubles and long
+ longs) may be split between the regs and the stack. When calling a
+ function that returns a struct, a pointer to the struct is passed
+ in as a secret first argument (always in R6).
+
+ Stack space for the args has NOT been allocated: that job is up to us.
+ */
+
+CORE_ADDR
+v850_push_arguments (nargs, args, sp, struct_return, struct_addr)
+ int nargs;
+ value_ptr *args;
+ CORE_ADDR sp;
+ unsigned char struct_return;
+ CORE_ADDR struct_addr;
+{
+ int argreg;
+ int argnum;
+ int len = 0;
+ int stack_offset;
+
+ /* First, just for safety, make sure stack is aligned */
+ sp &= ~3;
+
+ /* Now make space on the stack for the args. */
+ for (argnum = 0; argnum < nargs; argnum++)
+ len += ((TYPE_LENGTH(VALUE_TYPE(args[argnum])) + 3) & ~3);
+ sp -= len; /* possibly over-allocating, but it works... */
+ /* (you might think we could allocate 16 bytes */
+ /* less, but the ABI seems to use it all! ) */
+ argreg = ARG0_REGNUM;
+
+ /* the struct_return pointer occupies the first parameter-passing reg */
+ if (struct_return)
+ write_register (argreg++, struct_addr);
+
+ stack_offset = 16;
+ /* The offset onto the stack at which we will start copying parameters
+ (after the registers are used up) begins at 16 rather than at zero.
+ I don't really know why, that's just the way it seems to work. */
+
+ /* Now load as many as possible of the first arguments into
+ registers, and push the rest onto the stack. There are 16 bytes
+ in four registers available. Loop thru args from first to last. */
+ for (argnum = 0; argnum < nargs; argnum++)
+ {
+ int len;
+ char *val;
+ char valbuf[REGISTER_RAW_SIZE(ARG0_REGNUM)];
+
+ if (TYPE_CODE (VALUE_TYPE (*args)) == TYPE_CODE_STRUCT
+ && TYPE_LENGTH (VALUE_TYPE (*args)) > 8)
+ {
+ store_address (valbuf, 4, VALUE_ADDRESS (*args));
+ len = 4;
+ val = valbuf;
+ }
+ else
+ {
+ len = TYPE_LENGTH (VALUE_TYPE (*args));
+ val = (char *)VALUE_CONTENTS (*args);
+ }
+
+ while (len > 0)
+ if (argreg <= ARGLAST_REGNUM)
+ {
+ CORE_ADDR regval;
+
+ regval = extract_address (val, REGISTER_RAW_SIZE (argreg));
+ write_register (argreg, regval);
+
+ len -= REGISTER_RAW_SIZE (argreg);
+ val += REGISTER_RAW_SIZE (argreg);
+ argreg++;
+ }
+ else
+ {
+ write_memory (sp + stack_offset, val, 4);
+
+ len -= 4;
+ val += 4;
+ stack_offset += 4;
+ }
+ args++;
+ }
+ return sp;
+}
+
+/* Function: push_return_address (pc)
+ Set up the return address for the inferior function call.
+ Needed for targets where we don't actually execute a JSR/BSR instruction */
+
+CORE_ADDR
+v850_push_return_address (pc, sp)
+ CORE_ADDR pc;
+ CORE_ADDR sp;
+{
+ write_register (RP_REGNUM, CALL_DUMMY_ADDRESS ());
+ return sp;
+}
+
+/* Function: frame_saved_pc
+ Find the caller of this frame. We do this by seeing if RP_REGNUM
+ is saved in the stack anywhere, otherwise we get it from the
+ registers. If the inner frame is a dummy frame, return its PC
+ instead of RP, because that's where "caller" of the dummy-frame
+ will be found. */
+
+CORE_ADDR
+v850_frame_saved_pc (fi)
+ struct frame_info *fi;
+{
+ if (PC_IN_CALL_DUMMY(fi->pc, fi->frame, fi->frame))
+ return generic_read_register_dummy(fi->pc, fi->frame, PC_REGNUM);
+ else
+ return v850_find_callers_reg (fi, RP_REGNUM);
+}
+
+void
+get_saved_register (raw_buffer, optimized, addrp, frame, regnum, lval)
+ char *raw_buffer;
+ int *optimized;
+ CORE_ADDR *addrp;
+ struct frame_info *frame;
+ int regnum;
+ enum lval_type *lval;
+{
+ generic_get_saved_register (raw_buffer, optimized, addrp,
+ frame, regnum, lval);
+}
+
+
+/* Function: fix_call_dummy
+ Pokes the callee function's address into the CALL_DUMMY assembly stub.
+ Assumes that the CALL_DUMMY looks like this:
+ jarl <offset24>, r31
+ trap
+ */
+
+int
+v850_fix_call_dummy (dummy, sp, fun, nargs, args, type, gcc_p)
+ char *dummy;
+ CORE_ADDR sp;
+ CORE_ADDR fun;
+ int nargs;
+ value_ptr *args;
+ struct type *type;
+ int gcc_p;
+{
+ long offset24;
+
+ offset24 = (long) fun - (long) entry_point_address ();
+ offset24 &= 0x3fffff;
+ offset24 |= 0xff800000; /* jarl <offset24>, r31 */
+
+ store_unsigned_integer ((unsigned int *)&dummy[2], 2, offset24 & 0xffff);
+ store_unsigned_integer ((unsigned int *)&dummy[0], 2, offset24 >> 16);
+ return 0;
+}
+
+/* Change the register names based on the current machine type. */
+
+static int
+v850_target_architecture_hook (ap)
+ const bfd_arch_info_type *ap;
+{
+ int i, j;
+
+ if (ap->arch != bfd_arch_v850)
+ return 0;
+
+ for (i = 0; v850_processor_type_table[i].regnames != NULL; i++)
+ {
+ if (v850_processor_type_table[i].mach == ap->mach)
+ {
+ v850_register_names = v850_processor_type_table[i].regnames;
+ return 1;
+ }
+ }
+
+ fatal ("Architecture `%s' unreconized", ap->printable_name);
+}
+
+void
+_initialize_v850_tdep ()
+{
+ tm_print_insn = print_insn_v850;
+ target_architecture_hook = v850_target_architecture_hook;
+}
diff --git a/gdb/valarith.c b/gdb/valarith.c
new file mode 100644
index 00000000000..0a3aa4d8e36
--- /dev/null
+++ b/gdb/valarith.c
@@ -0,0 +1,1259 @@
+/* Perform arithmetic and other operations on values, for GDB.
+ Copyright 1986, 89, 91, 92, 93, 94, 95, 96, 97, 1998
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "value.h"
+#include "symtab.h"
+#include "gdbtypes.h"
+#include "expression.h"
+#include "target.h"
+#include "language.h"
+#include "demangle.h"
+#include "gdb_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_ptr value_subscripted_rvalue PARAMS ((value_ptr, value_ptr, int));
+
+void _initialize_valarith PARAMS ((void));
+
+
+value_ptr
+value_add (arg1, arg2)
+ value_ptr arg1, arg2;
+{
+ register value_ptr valint, valptr;
+ register int len;
+ struct type *type1, *type2, *valptrtype;
+
+ COERCE_NUMBER (arg1);
+ COERCE_NUMBER (arg2);
+ type1 = check_typedef (VALUE_TYPE (arg1));
+ type2 = check_typedef (VALUE_TYPE (arg2));
+
+ if ((TYPE_CODE (type1) == TYPE_CODE_PTR
+ || TYPE_CODE (type2) == TYPE_CODE_PTR)
+ &&
+ (TYPE_CODE (type1) == TYPE_CODE_INT
+ || TYPE_CODE (type2) == TYPE_CODE_INT))
+ /* Exactly one argument is a pointer, and one is an integer. */
+ {
+ value_ptr retval;
+
+ if (TYPE_CODE (type1) == TYPE_CODE_PTR)
+ {
+ valptr = arg1;
+ valint = arg2;
+ valptrtype = type1;
+ }
+ else
+ {
+ valptr = arg2;
+ valint = arg1;
+ valptrtype = type2;
+ }
+ len = TYPE_LENGTH (check_typedef (TYPE_TARGET_TYPE (valptrtype)));
+ if (len == 0)
+ len = 1; /* For (void *) */
+ retval = value_from_longest (valptrtype,
+ value_as_long (valptr)
+ + (len * value_as_long (valint)));
+ VALUE_BFD_SECTION (retval) = VALUE_BFD_SECTION (valptr);
+ return retval;
+ }
+
+ return value_binop (arg1, arg2, BINOP_ADD);
+}
+
+value_ptr
+value_sub (arg1, arg2)
+ value_ptr arg1, arg2;
+{
+ struct type *type1, *type2;
+ COERCE_NUMBER (arg1);
+ COERCE_NUMBER (arg2);
+ type1 = check_typedef (VALUE_TYPE (arg1));
+ type2 = check_typedef (VALUE_TYPE (arg2));
+
+ if (TYPE_CODE (type1) == TYPE_CODE_PTR)
+ {
+ if (TYPE_CODE (type2) == TYPE_CODE_INT)
+ {
+ /* pointer - integer. */
+ LONGEST sz = TYPE_LENGTH (check_typedef (TYPE_TARGET_TYPE (type1)));
+ return value_from_longest
+ (VALUE_TYPE (arg1),
+ value_as_long (arg1) - (sz * value_as_long (arg2)));
+ }
+ else if (TYPE_CODE (type2) == TYPE_CODE_PTR
+ && TYPE_LENGTH (TYPE_TARGET_TYPE (type1))
+ == TYPE_LENGTH (TYPE_TARGET_TYPE (type2)))
+ {
+ /* pointer to <type x> - pointer to <type x>. */
+ LONGEST sz = TYPE_LENGTH (check_typedef (TYPE_TARGET_TYPE (type1)));
+ return value_from_longest
+ (builtin_type_long, /* FIXME -- should be ptrdiff_t */
+ (value_as_long (arg1) - value_as_long (arg2)) / sz);
+ }
+ 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_ptr
+value_subscript (array, idx)
+ value_ptr array, idx;
+{
+ value_ptr bound;
+ int c_style = current_language->c_style_arrays;
+ struct type *tarray;
+
+ COERCE_REF (array);
+ tarray = check_typedef (VALUE_TYPE (array));
+ COERCE_VARYING_ARRAY (array, tarray);
+
+ if (TYPE_CODE (tarray) == TYPE_CODE_ARRAY
+ || TYPE_CODE (tarray) == TYPE_CODE_STRING)
+ {
+ struct type *range_type = TYPE_INDEX_TYPE (tarray);
+ LONGEST lowerbound, upperbound;
+ get_discrete_bounds (range_type, &lowerbound, &upperbound);
+
+ if (VALUE_LVAL (array) != lval_memory)
+ return value_subscripted_rvalue (array, idx, lowerbound);
+
+ if (c_style == 0)
+ {
+ LONGEST index = value_as_long (idx);
+ if (index >= lowerbound && index <= upperbound)
+ return value_subscripted_rvalue (array, idx, lowerbound);
+ warning ("array or string index out of range");
+ /* fall doing C stuff */
+ c_style = 1;
+ }
+
+ if (lowerbound != 0)
+ {
+ bound = value_from_longest (builtin_type_int, (LONGEST) lowerbound);
+ idx = value_sub (idx, bound);
+ }
+
+ array = value_coerce_array (array);
+ }
+
+ if (TYPE_CODE (tarray) == TYPE_CODE_BITSTRING)
+ {
+ struct type *range_type = TYPE_INDEX_TYPE (tarray);
+ LONGEST index = value_as_long (idx);
+ value_ptr v;
+ int offset, byte, bit_index;
+ LONGEST lowerbound, upperbound;
+ get_discrete_bounds (range_type, &lowerbound, &upperbound);
+ if (index < lowerbound || index > upperbound)
+ error ("bitstring index out of range");
+ index -= lowerbound;
+ offset = index / TARGET_CHAR_BIT;
+ byte = *((char*)VALUE_CONTENTS (array) + offset);
+ bit_index = index % TARGET_CHAR_BIT;
+ byte >>= (BITS_BIG_ENDIAN ? TARGET_CHAR_BIT - 1 - bit_index : bit_index);
+ v = value_from_longest (LA_BOOL_TYPE, byte & 1);
+ VALUE_BITPOS (v) = bit_index;
+ VALUE_BITSIZE (v) = 1;
+ VALUE_LVAL (v) = VALUE_LVAL (array);
+ if (VALUE_LVAL (array) == lval_internalvar)
+ VALUE_LVAL (v) = lval_internalvar_component;
+ VALUE_ADDRESS (v) = VALUE_ADDRESS (array);
+ VALUE_OFFSET (v) = offset + VALUE_OFFSET (array);
+ return v;
+ }
+
+ if (c_style)
+ return value_ind (value_add (array, idx));
+ else
+ error ("not an array or string");
+}
+
+/* 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_ptr
+value_subscripted_rvalue (array, idx, lowerbound)
+ value_ptr array, idx;
+ int lowerbound;
+{
+ struct type *array_type = check_typedef (VALUE_TYPE (array));
+ struct type *elt_type = check_typedef (TYPE_TARGET_TYPE (array_type));
+ unsigned int elt_size = TYPE_LENGTH (elt_type);
+ LONGEST index = value_as_long (idx);
+ unsigned int elt_offs = elt_size * longest_to_int (index - lowerbound);
+ value_ptr v;
+
+ if (index < lowerbound || elt_offs >= TYPE_LENGTH (array_type))
+ error ("no such vector element");
+
+ v = allocate_value (elt_type);
+ if (VALUE_LAZY (array))
+ VALUE_LAZY (v) = 1;
+ else
+ 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) = VALUE_LVAL (array);
+ VALUE_ADDRESS (v) = VALUE_ADDRESS (array);
+ VALUE_OFFSET (v) = VALUE_OFFSET (array) + elt_offs;
+ 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_ptr arg1, arg2;
+{
+ struct type *type1, *type2;
+ if (op == BINOP_ASSIGN || op == BINOP_CONCAT)
+ return 0;
+ type1 = check_typedef (VALUE_TYPE (arg1));
+ type2 = check_typedef (VALUE_TYPE (arg2));
+ return (TYPE_CODE (type1) == TYPE_CODE_STRUCT
+ || TYPE_CODE (type2) == TYPE_CODE_STRUCT
+ || (TYPE_CODE (type1) == TYPE_CODE_REF
+ && TYPE_CODE (TYPE_TARGET_TYPE (type1)) == TYPE_CODE_STRUCT)
+ || (TYPE_CODE (type2) == TYPE_CODE_REF
+ && TYPE_CODE (TYPE_TARGET_TYPE (type2)) == 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_ptr arg1;
+{
+ struct type *type1;
+ if (op == UNOP_ADDR)
+ return 0;
+ type1 = check_typedef (VALUE_TYPE (arg1));
+ for (;;)
+ {
+ if (TYPE_CODE (type1) == TYPE_CODE_STRUCT)
+ return 1;
+ else if (TYPE_CODE (type1) == TYPE_CODE_REF)
+ type1 = TYPE_TARGET_TYPE (type1);
+ else
+ return 0;
+ }
+}
+
+/* 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_ptr
+value_x_binop (arg1, arg2, op, otherop, noside)
+ value_ptr arg1, arg2;
+ enum exp_opcode op, otherop;
+ enum noside noside;
+{
+ value_ptr * 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 (check_typedef (VALUE_TYPE (arg1))) != TYPE_CODE_STRUCT)
+ error ("Can't do that binary op on that type"); /* FIXME be explicit */
+
+ argvec = (value_ptr *) alloca (sizeof (value_ptr) * 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++;
+ }
+ if (noside == EVAL_AVOID_SIDE_EFFECTS)
+ {
+ struct type *return_type;
+ return_type
+ = TYPE_TARGET_TYPE (check_typedef (VALUE_TYPE (argvec[0])));
+ return value_zero (return_type, VALUE_LVAL (arg1));
+ }
+ 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_ptr
+value_x_unop (arg1, op, noside)
+ value_ptr arg1;
+ enum exp_opcode op;
+ enum noside noside;
+{
+ value_ptr * argvec;
+ char *ptr, *mangle_ptr;
+ char tstr[13], mangle_tstr[13];
+ int static_memfuncp;
+
+ COERCE_REF (arg1);
+ 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 (check_typedef (VALUE_TYPE (arg1))) != TYPE_CODE_STRUCT)
+ error ("Can't do that unary op on that type"); /* FIXME be explicit */
+
+ argvec = (value_ptr *) alloca (sizeof (value_ptr) * 3);
+ argvec[1] = value_addr (arg1);
+ argvec[2] = 0;
+
+ /* make the right function name up */
+ strcpy(tstr,"operator__");
+ ptr = tstr+8;
+ strcpy(mangle_tstr, "__");
+ mangle_ptr = mangle_tstr+2;
+ 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;
+ case UNOP_IND: strcpy(ptr,"*"); break;
+ default:
+ error ("Invalid unary 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++;
+ }
+ if (noside == EVAL_AVOID_SIDE_EFFECTS)
+ {
+ struct type *return_type;
+ return_type
+ = TYPE_TARGET_TYPE (check_typedef (VALUE_TYPE (argvec[0])));
+ return value_zero (return_type, VALUE_LVAL (arg1));
+ }
+ 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_ptr
+value_concat (arg1, arg2)
+ value_ptr arg1, arg2;
+{
+ register value_ptr inval1, inval2, outval;
+ int inval1len, inval2len;
+ int count, idx;
+ char *ptr;
+ char inchar;
+ struct type *type1 = check_typedef (VALUE_TYPE (arg1));
+ struct type *type2 = check_typedef (VALUE_TYPE (arg2));
+
+ COERCE_VARYING_ARRAY (arg1, type1);
+ COERCE_VARYING_ARRAY (arg2, type2);
+
+ /* 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 (type2) == TYPE_CODE_INT)
+ {
+ struct type *tmp = type1;
+ type1 = tmp;
+ tmp = type2;
+ inval1 = arg2;
+ inval2 = arg1;
+ }
+ else
+ {
+ inval1 = arg1;
+ inval2 = arg2;
+ }
+
+ /* Now process the input values. */
+
+ if (TYPE_CODE (type1) == TYPE_CODE_INT)
+ {
+ /* We have a repeat count. Validate the second value and then
+ construct a value repeated that many times. */
+ if (TYPE_CODE (type2) == TYPE_CODE_STRING
+ || TYPE_CODE (type2) == TYPE_CODE_CHAR)
+ {
+ count = longest_to_int (value_as_long (inval1));
+ inval2len = TYPE_LENGTH (type2);
+ ptr = (char *) alloca (count * inval2len);
+ if (TYPE_CODE (type2) == TYPE_CODE_CHAR)
+ {
+ inchar = (char) unpack_long (type2,
+ 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 (type2) == TYPE_CODE_BITSTRING
+ || TYPE_CODE (type2) == TYPE_CODE_BOOL)
+ {
+ error ("unimplemented support for bitstring/boolean repeats");
+ }
+ else
+ {
+ error ("can't repeat values of that type");
+ }
+ }
+ else if (TYPE_CODE (type1) == TYPE_CODE_STRING
+ || TYPE_CODE (type1) == TYPE_CODE_CHAR)
+ {
+ /* We have two character strings to concatenate. */
+ if (TYPE_CODE (type2) != TYPE_CODE_STRING
+ && TYPE_CODE (type2) != TYPE_CODE_CHAR)
+ {
+ error ("Strings can only be concatenated with other strings.");
+ }
+ inval1len = TYPE_LENGTH (type1);
+ inval2len = TYPE_LENGTH (type2);
+ ptr = (char *) alloca (inval1len + inval2len);
+ if (TYPE_CODE (type1) == TYPE_CODE_CHAR)
+ {
+ *ptr = (char) unpack_long (type1, VALUE_CONTENTS (inval1));
+ }
+ else
+ {
+ memcpy (ptr, VALUE_CONTENTS (inval1), inval1len);
+ }
+ if (TYPE_CODE (type2) == TYPE_CODE_CHAR)
+ {
+ *(ptr + inval1len) =
+ (char) unpack_long (type2, VALUE_CONTENTS (inval2));
+ }
+ else
+ {
+ memcpy (ptr + inval1len, VALUE_CONTENTS (inval2), inval2len);
+ }
+ outval = value_string (ptr, inval1len + inval2len);
+ }
+ else if (TYPE_CODE (type1) == TYPE_CODE_BITSTRING
+ || TYPE_CODE (type1) == TYPE_CODE_BOOL)
+ {
+ /* We have two bitstrings to concatenate. */
+ if (TYPE_CODE (type2) != TYPE_CODE_BITSTRING
+ && TYPE_CODE (type2) != 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_ptr
+value_binop (arg1, arg2, op)
+ value_ptr arg1, arg2;
+ enum exp_opcode op;
+{
+ register value_ptr val;
+ struct type *type1, *type2;
+
+ COERCE_REF (arg1);
+ COERCE_REF (arg2);
+ COERCE_ENUM (arg1);
+ COERCE_ENUM (arg2);
+ type1 = check_typedef (VALUE_TYPE (arg1));
+ type2 = check_typedef (VALUE_TYPE (arg2));
+
+ if ((TYPE_CODE (type1) != TYPE_CODE_FLT
+ && TYPE_CODE (type1) != TYPE_CODE_CHAR
+ && TYPE_CODE (type1) != TYPE_CODE_INT
+ && TYPE_CODE (type1) != TYPE_CODE_BOOL
+ && TYPE_CODE (type1) != TYPE_CODE_RANGE)
+ ||
+ (TYPE_CODE (type2) != TYPE_CODE_FLT
+ && TYPE_CODE (type2) != TYPE_CODE_CHAR
+ && TYPE_CODE (type2) != TYPE_CODE_INT
+ && TYPE_CODE (type2) != TYPE_CODE_BOOL
+ && TYPE_CODE (type2) != TYPE_CODE_RANGE))
+ error ("Argument to arithmetic operation not a number or boolean.");
+
+ if (TYPE_CODE (type1) == TYPE_CODE_FLT
+ ||
+ TYPE_CODE (type2) == TYPE_CODE_FLT)
+ {
+ /* FIXME-if-picky-about-floating-accuracy: Should be doing this
+ in target format. real.c in GCC probably has the necessary
+ code. */
+ DOUBLEST 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.");
+ }
+
+ /* If either arg was long double, make sure that value is also long
+ double. */
+
+ if (TYPE_LENGTH(type1) * 8 > TARGET_DOUBLE_BIT
+ || TYPE_LENGTH(type2) * 8 > TARGET_DOUBLE_BIT)
+ val = allocate_value (builtin_type_long_double);
+ else
+ val = allocate_value (builtin_type_double);
+
+ store_floating (VALUE_CONTENTS_RAW (val), TYPE_LENGTH (VALUE_TYPE (val)),
+ v);
+ }
+ else if (TYPE_CODE (type1) == TYPE_CODE_BOOL
+ &&
+ TYPE_CODE (type2) == 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 (type1);
+ store_signed_integer (VALUE_CONTENTS_RAW (val),
+ TYPE_LENGTH (type1),
+ v);
+ }
+ else
+ /* Integral operations here. */
+ /* FIXME: Also mixed integral/booleans, with result an integer. */
+ /* FIXME: This implements ANSI C rules (also correct for C++).
+ What about FORTRAN and chill? */
+ {
+ unsigned int promoted_len1 = TYPE_LENGTH (type1);
+ unsigned int promoted_len2 = TYPE_LENGTH (type2);
+ int is_unsigned1 = TYPE_UNSIGNED (type1);
+ int is_unsigned2 = TYPE_UNSIGNED (type2);
+ unsigned int result_len;
+ int unsigned_operation;
+
+ /* Determine type length and signedness after promotion for
+ both operands. */
+ if (promoted_len1 < TYPE_LENGTH (builtin_type_int))
+ {
+ is_unsigned1 = 0;
+ promoted_len1 = TYPE_LENGTH (builtin_type_int);
+ }
+ if (promoted_len2 < TYPE_LENGTH (builtin_type_int))
+ {
+ is_unsigned2 = 0;
+ promoted_len2 = TYPE_LENGTH (builtin_type_int);
+ }
+
+ /* Determine type length of the result, and if the operation should
+ be done unsigned.
+ Use the signedness of the operand with the greater length.
+ If both operands are of equal length, use unsigned operation
+ if one of the operands is unsigned. */
+ if (promoted_len1 > promoted_len2)
+ {
+ unsigned_operation = is_unsigned1;
+ result_len = promoted_len1;
+ }
+ else if (promoted_len2 > promoted_len1)
+ {
+ unsigned_operation = is_unsigned2;
+ result_len = promoted_len2;
+ }
+ else
+ {
+ unsigned_operation = is_unsigned1 || is_unsigned2;
+ result_len = promoted_len1;
+ }
+
+ if (unsigned_operation)
+ {
+ ULONGEST v1, v2, v;
+ v1 = (ULONGEST) value_as_long (arg1);
+ v2 = (ULONGEST) value_as_long (arg2);
+
+ /* Truncate values to the type length of the result. */
+ if (result_len < sizeof (ULONGEST))
+ {
+ v1 &= ((LONGEST) 1 << HOST_CHAR_BIT * result_len) - 1;
+ v2 &= ((LONGEST) 1 << HOST_CHAR_BIT * result_len) - 1;
+ }
+
+ 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;
+
+ case BINOP_EQUAL:
+ v = v1 == v2;
+ break;
+
+ case BINOP_LESS:
+ v = v1 < v2;
+ break;
+
+ default:
+ error ("Invalid binary operation on numbers.");
+ }
+
+ /* This is a kludge to get around the fact that we don't
+ know how to determine the result type from the types of
+ the operands. (I'm not really sure how much we feel the
+ need to duplicate the exact rules of the current
+ language. They can get really hairy. But not to do so
+ makes it hard to document just what we *do* do). */
+
+ /* Can't just call init_type because we wouldn't know what
+ name to give the type. */
+ val = allocate_value
+ (result_len > TARGET_LONG_BIT / HOST_CHAR_BIT
+ ? builtin_type_unsigned_long_long
+ : builtin_type_unsigned_long);
+ 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;
+
+ case BINOP_EQUAL:
+ v = v1 == v2;
+ break;
+
+ case BINOP_LESS:
+ v = v1 < v2;
+ break;
+
+ default:
+ error ("Invalid binary operation on numbers.");
+ }
+
+ /* This is a kludge to get around the fact that we don't
+ know how to determine the result type from the types of
+ the operands. (I'm not really sure how much we feel the
+ need to duplicate the exact rules of the current
+ language. They can get really hairy. But not to do so
+ makes it hard to document just what we *do* do). */
+
+ /* Can't just call init_type because we wouldn't know what
+ name to give the type. */
+ val = allocate_value
+ (result_len > TARGET_LONG_BIT / HOST_CHAR_BIT
+ ? builtin_type_long_long
+ : builtin_type_long);
+ 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_ptr arg1;
+{
+ register int len;
+ register char *p;
+ struct type *type1;
+
+ COERCE_NUMBER (arg1);
+ type1 = check_typedef (VALUE_TYPE (arg1));
+
+ if (TYPE_CODE (type1) == TYPE_CODE_FLT)
+ return 0 == value_as_double (arg1);
+
+ len = TYPE_LENGTH (type1);
+ 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_ptr arg1, arg2;
+
+{
+ register int len;
+ register char *p1, *p2;
+ struct type *type1, *type2;
+ enum type_code code1;
+ enum type_code code2;
+
+ COERCE_NUMBER (arg1);
+ COERCE_NUMBER (arg2);
+
+ type1 = check_typedef (VALUE_TYPE (arg1));
+ type2 = check_typedef (VALUE_TYPE (arg2));
+ code1 = TYPE_CODE (type1);
+ code2 = TYPE_CODE (type2);
+
+ if ((code1 == TYPE_CODE_INT || code1 == TYPE_CODE_BOOL) &&
+ (code2 == TYPE_CODE_INT || code2 == TYPE_CODE_BOOL))
+ return longest_to_int (value_as_long (value_binop (arg1, arg2,
+ BINOP_EQUAL)));
+ else if ((code1 == TYPE_CODE_FLT || code1 == TYPE_CODE_INT || code1 == TYPE_CODE_BOOL)
+ && (code2 == TYPE_CODE_FLT || code2 == TYPE_CODE_INT || code2 == TYPE_CODE_BOOL))
+ 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 || code2 == TYPE_CODE_BOOL))
+ return value_as_pointer (arg1) == (CORE_ADDR) value_as_long (arg2);
+ else if (code2 == TYPE_CODE_PTR && (code1 == TYPE_CODE_INT || code1 == TYPE_CODE_BOOL))
+ return (CORE_ADDR) value_as_long (arg1) == value_as_pointer (arg2);
+
+ else if (code1 == code2
+ && ((len = (int) TYPE_LENGTH (type1))
+ == (int) TYPE_LENGTH (type2)))
+ {
+ 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_ptr arg1, arg2;
+{
+ register enum type_code code1;
+ register enum type_code code2;
+ struct type *type1, *type2;
+
+ COERCE_NUMBER (arg1);
+ COERCE_NUMBER (arg2);
+
+ type1 = check_typedef (VALUE_TYPE (arg1));
+ type2 = check_typedef (VALUE_TYPE (arg2));
+ code1 = TYPE_CODE (type1);
+ code2 = TYPE_CODE (type2);
+
+ if ((code1 == TYPE_CODE_INT || code1 == TYPE_CODE_BOOL) &&
+ (code2 == TYPE_CODE_INT || code2 == TYPE_CODE_BOOL))
+ return longest_to_int (value_as_long (value_binop (arg1, arg2,
+ BINOP_LESS)));
+ else if ((code1 == TYPE_CODE_FLT || code1 == TYPE_CODE_INT || code1 == TYPE_CODE_BOOL)
+ && (code2 == TYPE_CODE_FLT || code2 == TYPE_CODE_INT || code2 == TYPE_CODE_BOOL))
+ 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 || code2 == TYPE_CODE_BOOL))
+ return value_as_pointer (arg1) < (CORE_ADDR) value_as_long (arg2);
+ else if (code2 == TYPE_CODE_PTR && (code1 == TYPE_CODE_INT || code1 == TYPE_CODE_BOOL))
+ 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_ptr
+value_neg (arg1)
+ register value_ptr arg1;
+{
+ register struct type *type;
+ register struct type *result_type = VALUE_TYPE (arg1);
+
+ COERCE_REF (arg1);
+ COERCE_ENUM (arg1);
+
+ type = check_typedef (VALUE_TYPE (arg1));
+
+ if (TYPE_CODE (type) == TYPE_CODE_FLT)
+ return value_from_double (result_type, - value_as_double (arg1));
+ else if (TYPE_CODE (type) == TYPE_CODE_INT || TYPE_CODE (type) == TYPE_CODE_BOOL)
+ {
+ /* Perform integral promotion for ANSI C/C++.
+ FIXME: What about FORTRAN and chill ? */
+ if (TYPE_LENGTH (type) < TYPE_LENGTH (builtin_type_int))
+ result_type = builtin_type_int;
+
+ return value_from_longest (result_type, - value_as_long (arg1));
+ }
+ else {
+ error ("Argument to negate operation not a number.");
+ return 0; /* For lint -- never reached */
+ }
+}
+
+value_ptr
+value_complement (arg1)
+ register value_ptr arg1;
+{
+ register struct type *type;
+ register struct type *result_type = VALUE_TYPE (arg1);
+ int typecode;
+
+ COERCE_REF (arg1);
+ COERCE_ENUM (arg1);
+
+ type = check_typedef (VALUE_TYPE (arg1));
+
+ typecode = TYPE_CODE (type);
+ if ((typecode != TYPE_CODE_INT) && (typecode != TYPE_CODE_BOOL))
+ error ("Argument to complement operation not an integer or boolean.");
+
+ /* Perform integral promotion for ANSI C/C++.
+ FIXME: What about FORTRAN ? */
+ if (TYPE_LENGTH (type) < TYPE_LENGTH (builtin_type_int))
+ result_type = builtin_type_int;
+
+ return value_from_longest (result_type, ~ value_as_long (arg1));
+}
+
+/* The INDEX'th bit of SET value whose VALUE_TYPE is TYPE,
+ and whose VALUE_CONTENTS is valaddr.
+ Return -1 if out of range, -2 other error. */
+
+int
+value_bit_index (type, valaddr, index)
+ struct type *type;
+ char *valaddr;
+ int index;
+{
+ LONGEST low_bound, high_bound;
+ LONGEST word;
+ unsigned rel_index;
+ struct type *range = TYPE_FIELD_TYPE (type, 0);
+ if (get_discrete_bounds (range, &low_bound, &high_bound) < 0)
+ return -2;
+ if (index < low_bound || index > high_bound)
+ return -1;
+ rel_index = index - low_bound;
+ word = unpack_long (builtin_type_unsigned_char,
+ valaddr + (rel_index / TARGET_CHAR_BIT));
+ rel_index %= TARGET_CHAR_BIT;
+ if (BITS_BIG_ENDIAN)
+ rel_index = TARGET_CHAR_BIT - 1 - rel_index;
+ return (word >> rel_index) & 1;
+}
+
+value_ptr
+value_in (element, set)
+ value_ptr element, set;
+{
+ int member;
+ struct type *settype = check_typedef (VALUE_TYPE (set));
+ struct type *eltype = check_typedef (VALUE_TYPE (element));
+ if (TYPE_CODE (eltype) == TYPE_CODE_RANGE)
+ eltype = TYPE_TARGET_TYPE (eltype);
+ if (TYPE_CODE (settype) != TYPE_CODE_SET)
+ error ("Second argument of 'IN' has wrong type");
+ if (TYPE_CODE (eltype) != TYPE_CODE_INT
+ && TYPE_CODE (eltype) != TYPE_CODE_CHAR
+ && TYPE_CODE (eltype) != TYPE_CODE_ENUM
+ && TYPE_CODE (eltype) != TYPE_CODE_BOOL)
+ error ("First argument of 'IN' has wrong type");
+ member = value_bit_index (settype, VALUE_CONTENTS (set),
+ value_as_long (element));
+ if (member < 0)
+ error ("First argument of 'IN' not in range");
+ return value_from_longest (LA_BOOL_TYPE, member);
+}
+
+void
+_initialize_valarith ()
+{
+}
diff --git a/gdb/valops.c b/gdb/valops.c
new file mode 100644
index 00000000000..77d2396aa1a
--- /dev/null
+++ b/gdb/valops.c
@@ -0,0 +1,3461 @@
+/* Perform non-arithmetic operations on values, for GDB.
+ Copyright 1986, 87, 89, 91, 92, 93, 94, 95, 96, 97, 1998
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 "gdbcmd.h"
+
+#include <errno.h>
+#include "gdb_string.h"
+
+/* Default to coercing float to double in function calls only when there is
+ no prototype. Otherwise on targets where the debug information is incorrect
+ for either the prototype or non-prototype case, we can force it by defining
+ COERCE_FLOAT_TO_DOUBLE in the target configuration file. */
+
+#ifndef COERCE_FLOAT_TO_DOUBLE
+#define COERCE_FLOAT_TO_DOUBLE (param_type == NULL)
+#endif
+
+/* Flag indicating HP compilers were used; needed to correctly handle some
+ value operations with HP aCC code/runtime. */
+extern int hp_som_som_object_present;
+
+
+/* Local functions. */
+
+static int typecmp PARAMS ((int staticp, struct type *t1[], value_ptr t2[]));
+
+#ifdef CALL_DUMMY
+static CORE_ADDR find_function_addr PARAMS ((value_ptr, struct type **));
+static value_ptr value_arg_coerce PARAMS ((value_ptr, struct type *, int));
+#endif
+
+
+#ifndef PUSH_ARGUMENTS
+static CORE_ADDR value_push PARAMS ((CORE_ADDR, value_ptr));
+#endif
+
+static value_ptr search_struct_field PARAMS ((char *, value_ptr, int,
+ struct type *, int));
+
+static value_ptr search_struct_field_aux PARAMS ((char *, value_ptr, int,
+ struct type *, int, int *, char *,
+ struct type **));
+
+static value_ptr search_struct_method PARAMS ((char *, value_ptr *,
+ value_ptr *,
+ int, int *, struct type *));
+
+static int check_field_in PARAMS ((struct type *, const char *));
+
+static CORE_ADDR allocate_space_in_inferior PARAMS ((int));
+
+static value_ptr cast_into_complex PARAMS ((struct type *, value_ptr));
+
+void _initialize_valops PARAMS ((void));
+
+#define VALUE_SUBSTRING_START(VAL) VALUE_FRAME(VAL)
+
+/* Flag for whether we want to abandon failed expression evals by default. */
+
+#if 0
+static int auto_abandon = 0;
+#endif
+
+int overload_resolution = 0;
+
+
+
+/* Find the address of function name NAME in the inferior. */
+
+value_ptr
+find_function_in_inferior (name)
+ char *name;
+{
+ register struct symbol *sym;
+ sym = lookup_symbol (name, 0, VAR_NAMESPACE, 0, NULL);
+ if (sym != NULL)
+ {
+ if (SYMBOL_CLASS (sym) != LOC_BLOCK)
+ {
+ error ("\"%s\" exists in this program but is not a function.",
+ name);
+ }
+ return value_of_variable (sym, NULL);
+ }
+ else
+ {
+ struct minimal_symbol *msymbol = lookup_minimal_symbol(name, NULL, NULL);
+ if (msymbol != NULL)
+ {
+ struct type *type;
+ LONGEST maddr;
+ type = lookup_pointer_type (builtin_type_char);
+ type = lookup_function_type (type);
+ type = lookup_pointer_type (type);
+ maddr = (LONGEST) SYMBOL_VALUE_ADDRESS (msymbol);
+ return value_from_longest (type, maddr);
+ }
+ else
+ {
+ if (!target_has_execution)
+ error ("evaluation of this expression requires the target program to be active");
+ else
+ error ("evaluation of this expression requires the program to have a function \"%s\".", name);
+ }
+ }
+}
+
+/* Allocate NBYTES of space in the inferior using the inferior's malloc
+ and return a value that is a pointer to the allocated space. */
+
+value_ptr
+value_allocate_space_in_inferior (len)
+ int len;
+{
+ value_ptr blocklen;
+ register value_ptr val = find_function_in_inferior ("malloc");
+
+ blocklen = value_from_longest (builtin_type_int, (LONGEST) len);
+ val = call_function_by_hand (val, 1, &blocklen);
+ if (value_logical_not (val))
+ {
+ if (!target_has_execution)
+ error ("No memory available to program now: you need to start the target first");
+ else
+ error ("No memory available to program: call to malloc failed");
+ }
+ return val;
+}
+
+static CORE_ADDR
+allocate_space_in_inferior (len)
+ int len;
+{
+ return value_as_long (value_allocate_space_in_inferior (len));
+}
+
+/* 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_ptr
+value_cast (type, arg2)
+ struct type *type;
+ register value_ptr arg2;
+{
+ register enum type_code code1;
+ register enum type_code code2;
+ register int scalar;
+ struct type *type2;
+
+ int convert_to_boolean = 0;
+
+ if (VALUE_TYPE (arg2) == type)
+ return arg2;
+
+ CHECK_TYPEDEF (type);
+ code1 = TYPE_CODE (type);
+ COERCE_REF(arg2);
+ type2 = check_typedef (VALUE_TYPE (arg2));
+
+ /* A cast to an undetermined-length array_type, such as (TYPE [])OBJECT,
+ is treated like a cast to (TYPE [N])OBJECT,
+ where N is sizeof(OBJECT)/sizeof(TYPE). */
+ if (code1 == TYPE_CODE_ARRAY)
+ {
+ struct type *element_type = TYPE_TARGET_TYPE (type);
+ unsigned element_length = TYPE_LENGTH (check_typedef (element_type));
+ if (element_length > 0
+ && TYPE_ARRAY_UPPER_BOUND_TYPE (type) == BOUND_CANNOT_BE_DETERMINED)
+ {
+ struct type *range_type = TYPE_INDEX_TYPE (type);
+ int val_length = TYPE_LENGTH (type2);
+ LONGEST low_bound, high_bound, new_length;
+ if (get_discrete_bounds (range_type, &low_bound, &high_bound) < 0)
+ low_bound = 0, high_bound = 0;
+ new_length = val_length / element_length;
+ if (val_length % element_length != 0)
+ warning("array element type size does not divide object size in cast");
+ /* FIXME-type-allocation: need a way to free this type when we are
+ done with it. */
+ range_type = create_range_type ((struct type *) NULL,
+ TYPE_TARGET_TYPE (range_type),
+ low_bound,
+ new_length + low_bound - 1);
+ VALUE_TYPE (arg2) = create_array_type ((struct type *) NULL,
+ element_type, range_type);
+ return arg2;
+ }
+ }
+
+ if (current_language->c_style_arrays
+ && TYPE_CODE (type2) == TYPE_CODE_ARRAY)
+ arg2 = value_coerce_array (arg2);
+
+ if (TYPE_CODE (type2) == TYPE_CODE_FUNC)
+ arg2 = value_coerce_function (arg2);
+
+ type2 = check_typedef (VALUE_TYPE (arg2));
+ COERCE_VARYING_ARRAY (arg2, type2);
+ code2 = TYPE_CODE (type2);
+
+ if (code1 == TYPE_CODE_COMPLEX)
+ return cast_into_complex (type, arg2);
+ if (code1 == TYPE_CODE_BOOL)
+ {
+ code1 = TYPE_CODE_INT;
+ convert_to_boolean = 1;
+ }
+ if (code1 == TYPE_CODE_CHAR)
+ code1 = TYPE_CODE_INT;
+ if (code2 == TYPE_CODE_BOOL || code2 == TYPE_CODE_CHAR)
+ code2 = TYPE_CODE_INT;
+
+ scalar = (code2 == TYPE_CODE_INT || code2 == TYPE_CODE_FLT
+ || code2 == TYPE_CODE_ENUM || code2 == TYPE_CODE_RANGE);
+
+ 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_ptr v = search_struct_field (type_name_no_tag (type),
+ arg2, 0, type2, 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
+ || code1 == TYPE_CODE_RANGE)
+ && (scalar || code2 == TYPE_CODE_PTR))
+ {
+ LONGEST longest;
+
+ if (hp_som_som_object_present && /* if target compiled by HP aCC */
+ (code2 == TYPE_CODE_PTR))
+ {
+ unsigned int * ptr;
+ value_ptr retvalp;
+
+ switch (TYPE_CODE (TYPE_TARGET_TYPE (type2)))
+ {
+ /* With HP aCC, pointers to data members have a bias */
+ case TYPE_CODE_MEMBER:
+ retvalp = value_from_longest (type, value_as_long (arg2));
+ ptr = (unsigned int *) VALUE_CONTENTS (retvalp); /* force evaluation */
+ *ptr &= ~0x20000000; /* zap 29th bit to remove bias */
+ return retvalp;
+
+ /* While pointers to methods don't really point to a function */
+ case TYPE_CODE_METHOD:
+ error ("Pointers to methods not supported with HP aCC");
+
+ default:
+ break; /* fall out and go to normal handling */
+ }
+ }
+ longest = value_as_long (arg2);
+ return value_from_longest (type, convert_to_boolean ? (LONGEST) (longest ? 1 : 0) : longest);
+ }
+ else if (TYPE_LENGTH (type) == TYPE_LENGTH (type2))
+ {
+ if (code1 == TYPE_CODE_PTR && code2 == TYPE_CODE_PTR)
+ {
+ struct type *t1 = check_typedef (TYPE_TARGET_TYPE (type));
+ struct type *t2 = check_typedef (TYPE_TARGET_TYPE (type2));
+ if ( TYPE_CODE (t1) == TYPE_CODE_STRUCT
+ && TYPE_CODE (t2) == TYPE_CODE_STRUCT
+ && !value_logical_not (arg2))
+ {
+ value_ptr v;
+
+ /* 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. */
+ if (TYPE_NAME (t1) != NULL)
+ {
+ 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;
+ }
+ }
+
+ /* Look in the type of the target to see if it contains the
+ type of the source as a superclass. If so, we'll need to
+ offset the pointer rather than just change its type.
+ FIXME: This fails silently with virtual inheritance. */
+ if (TYPE_NAME (t2) != NULL)
+ {
+ v = search_struct_field (type_name_no_tag (t2),
+ value_zero (t1, not_lval), 0, t1, 1);
+ if (v)
+ {
+ value_ptr v2 = value_ind (arg2);
+ VALUE_ADDRESS (v2) -= VALUE_ADDRESS (v)
+ + VALUE_OFFSET (v);
+ v2 = value_addr (v2);
+ VALUE_TYPE (v2) = type;
+ return v2;
+ }
+ }
+ }
+ /* No superclass found, just fall through to change ptr type. */
+ }
+ VALUE_TYPE (arg2) = type;
+ VALUE_ENCLOSING_TYPE (arg2) = type; /* pai: chk_val */
+ VALUE_POINTED_TO_OFFSET (arg2) = 0; /* pai: chk_val */
+ return arg2;
+ }
+ else if (chill_varying_type (type))
+ {
+ struct type *range1, *range2, *eltype1, *eltype2;
+ value_ptr val;
+ int count1, count2;
+ LONGEST low_bound, high_bound;
+ char *valaddr, *valaddr_data;
+ /* For lint warning about eltype2 possibly uninitialized: */
+ eltype2 = NULL;
+ if (code2 == TYPE_CODE_BITSTRING)
+ error ("not implemented: converting bitstring to varying type");
+ if ((code2 != TYPE_CODE_ARRAY && code2 != TYPE_CODE_STRING)
+ || (eltype1 = check_typedef (TYPE_TARGET_TYPE (TYPE_FIELD_TYPE (type, 1))),
+ eltype2 = check_typedef (TYPE_TARGET_TYPE (type2)),
+ (TYPE_LENGTH (eltype1) != TYPE_LENGTH (eltype2)
+ /* || TYPE_CODE (eltype1) != TYPE_CODE (eltype2) */ )))
+ error ("Invalid conversion to varying type");
+ range1 = TYPE_FIELD_TYPE (TYPE_FIELD_TYPE (type, 1), 0);
+ range2 = TYPE_FIELD_TYPE (type2, 0);
+ if (get_discrete_bounds (range1, &low_bound, &high_bound) < 0)
+ count1 = -1;
+ else
+ count1 = high_bound - low_bound + 1;
+ if (get_discrete_bounds (range2, &low_bound, &high_bound) < 0)
+ count1 = -1, count2 = 0; /* To force error before */
+ else
+ count2 = high_bound - low_bound + 1;
+ if (count2 > count1)
+ error ("target varying type is too small");
+ val = allocate_value (type);
+ valaddr = VALUE_CONTENTS_RAW (val);
+ valaddr_data = valaddr + TYPE_FIELD_BITPOS (type, 1) / 8;
+ /* Set val's __var_length field to count2. */
+ store_signed_integer (valaddr, TYPE_LENGTH (TYPE_FIELD_TYPE (type, 0)),
+ count2);
+ /* Set the __var_data field to count2 elements copied from arg2. */
+ memcpy (valaddr_data, VALUE_CONTENTS (arg2),
+ count2 * TYPE_LENGTH (eltype2));
+ /* Zero the rest of the __var_data field of val. */
+ memset (valaddr_data + count2 * TYPE_LENGTH (eltype2), '\0',
+ (count1 - count2) * TYPE_LENGTH (eltype2));
+ return val;
+ }
+ else if (VALUE_LVAL (arg2) == lval_memory)
+ {
+ return value_at_lazy (type, VALUE_ADDRESS (arg2) + VALUE_OFFSET (arg2),
+ VALUE_BFD_SECTION (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_ptr
+value_zero (type, lv)
+ struct type *type;
+ enum lval_type lv;
+{
+ register value_ptr val = allocate_value (type);
+
+ memset (VALUE_CONTENTS (val), 0, TYPE_LENGTH (check_typedef (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.
+
+ Note: value_at does *NOT* handle embedded offsets; perform such
+ adjustments before or after calling it. */
+
+value_ptr
+value_at (type, addr, sect)
+ struct type *type;
+ CORE_ADDR addr;
+ asection *sect;
+{
+ register value_ptr val;
+
+ if (TYPE_CODE (check_typedef (type)) == TYPE_CODE_VOID)
+ error ("Attempt to dereference a generic pointer.");
+
+ val = allocate_value (type);
+
+#ifdef GDB_TARGET_IS_D10V
+ if (TYPE_CODE (type) == TYPE_CODE_PTR
+ && TYPE_TARGET_TYPE (type)
+ && (TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_FUNC))
+ {
+ /* pointer to function */
+ unsigned long num;
+ unsigned short snum;
+ snum = read_memory_unsigned_integer (addr, 2);
+ num = D10V_MAKE_IADDR(snum);
+ store_address ( VALUE_CONTENTS_RAW (val), 4, num);
+ }
+ else if (TYPE_CODE(type) == TYPE_CODE_PTR)
+ {
+ /* pointer to data */
+ unsigned long num;
+ unsigned short snum;
+ snum = read_memory_unsigned_integer (addr, 2);
+ num = D10V_MAKE_DADDR(snum);
+ store_address ( VALUE_CONTENTS_RAW (val), 4, num);
+ }
+ else
+#endif
+ read_memory_section (addr, VALUE_CONTENTS_ALL_RAW (val), TYPE_LENGTH (type), sect);
+
+ VALUE_LVAL (val) = lval_memory;
+ VALUE_ADDRESS (val) = addr;
+ VALUE_BFD_SECTION (val) = sect;
+
+ return val;
+}
+
+/* Return a lazy value with type TYPE located at ADDR (cf. value_at). */
+
+value_ptr
+value_at_lazy (type, addr, sect)
+ struct type *type;
+ CORE_ADDR addr;
+ asection *sect;
+{
+ register value_ptr val;
+
+ if (TYPE_CODE (check_typedef (type)) == TYPE_CODE_VOID)
+ error ("Attempt to dereference a generic pointer.");
+
+ val = allocate_value (type);
+
+ VALUE_LVAL (val) = lval_memory;
+ VALUE_ADDRESS (val) = addr;
+ VALUE_LAZY (val) = 1;
+ VALUE_BFD_SECTION (val) = sect;
+
+ return val;
+}
+
+/* Called only from the VALUE_CONTENTS and VALUE_CONTENTS_ALL macros,
+ 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_ptr val;
+{
+ CORE_ADDR addr = VALUE_ADDRESS (val) + VALUE_OFFSET (val);
+ int length = TYPE_LENGTH (VALUE_ENCLOSING_TYPE (val));
+
+#ifdef GDB_TARGET_IS_D10V
+ struct type *type = VALUE_TYPE(val);
+ if (TYPE_CODE (type) == TYPE_CODE_PTR
+ && TYPE_TARGET_TYPE (type)
+ && (TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_FUNC))
+ {
+ /* pointer to function */
+ unsigned long num;
+ unsigned short snum;
+ snum = read_memory_unsigned_integer (addr, 2);
+ num = D10V_MAKE_IADDR(snum);
+ store_address ( VALUE_CONTENTS_RAW (val), 4, num);
+ }
+ else if (TYPE_CODE(type) == TYPE_CODE_PTR)
+ {
+ /* pointer to data */
+ unsigned long num;
+ unsigned short snum;
+ snum = read_memory_unsigned_integer (addr, 2);
+ num = D10V_MAKE_DADDR(snum);
+ store_address ( VALUE_CONTENTS_RAW (val), 4, num);
+ }
+ else
+#endif
+
+ if (length)
+ read_memory_section (addr, VALUE_CONTENTS_ALL_RAW (val), length,
+ VALUE_BFD_SECTION (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_ptr
+value_assign (toval, fromval)
+ register value_ptr toval, fromval;
+{
+ register struct type *type;
+ register value_ptr val;
+ char raw_buffer[MAX_REGISTER_RAW_SIZE];
+ int use_buffer = 0;
+
+ if (!toval->modifiable)
+ error ("Left operand of assignment is not a modifiable lvalue.");
+
+ COERCE_REF (toval);
+
+ type = VALUE_TYPE (toval);
+ if (VALUE_LVAL (toval) != lval_internalvar)
+ fromval = value_cast (type, fromval);
+ else
+ COERCE_ARRAY (fromval);
+ CHECK_TYPEDEF (type);
+
+ /* 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. */
+
+#ifdef REGISTER_CONVERTIBLE
+ if (VALUE_REGNO (toval) >= 0
+ && REGISTER_CONVERTIBLE (VALUE_REGNO (toval)))
+ {
+ int regno = VALUE_REGNO (toval);
+ if (REGISTER_CONVERTIBLE (regno))
+ {
+ struct type *fromtype = check_typedef (VALUE_TYPE (fromval));
+ REGISTER_CONVERT_TO_RAW (fromtype, regno,
+ VALUE_CONTENTS (fromval), raw_buffer);
+ use_buffer = REGISTER_RAW_SIZE (regno);
+ }
+ }
+#endif
+
+ switch (VALUE_LVAL (toval))
+ {
+ case lval_internalvar:
+ set_internalvar (VALUE_INTERNALVAR (toval), fromval);
+ val = value_copy (VALUE_INTERNALVAR (toval)->value);
+ VALUE_ENCLOSING_TYPE (val) = VALUE_ENCLOSING_TYPE (fromval);
+ VALUE_EMBEDDED_OFFSET (val) = VALUE_EMBEDDED_OFFSET (fromval);
+ VALUE_POINTED_TO_OFFSET (val) = VALUE_POINTED_TO_OFFSET (fromval);
+ return val;
+
+ case lval_internalvar_component:
+ set_internalvar_component (VALUE_INTERNALVAR (toval),
+ VALUE_OFFSET (toval),
+ VALUE_BITPOS (toval),
+ VALUE_BITSIZE (toval),
+ fromval);
+ break;
+
+ case lval_memory:
+ {
+ char *dest_buffer;
+ CORE_ADDR changed_addr;
+ int changed_len;
+
+ if (VALUE_BITSIZE (toval))
+ {
+ char buffer[sizeof (LONGEST)];
+ /* We assume that the argument to read_memory is in units of
+ host chars. FIXME: Is that correct? */
+ changed_len = (VALUE_BITPOS (toval)
+ + VALUE_BITSIZE (toval)
+ + HOST_CHAR_BIT - 1)
+ / HOST_CHAR_BIT;
+
+ if (changed_len > (int) sizeof (LONGEST))
+ error ("Can't handle bitfields which don't fit in a %d bit word.",
+ sizeof (LONGEST) * HOST_CHAR_BIT);
+
+ read_memory (VALUE_ADDRESS (toval) + VALUE_OFFSET (toval),
+ buffer, changed_len);
+ modify_field (buffer, value_as_long (fromval),
+ VALUE_BITPOS (toval), VALUE_BITSIZE (toval));
+ changed_addr = VALUE_ADDRESS (toval) + VALUE_OFFSET (toval);
+ dest_buffer = buffer;
+ }
+ else if (use_buffer)
+ {
+ changed_addr = VALUE_ADDRESS (toval) + VALUE_OFFSET (toval);
+ changed_len = use_buffer;
+ dest_buffer = raw_buffer;
+ }
+ else
+ {
+ changed_addr = VALUE_ADDRESS (toval) + VALUE_OFFSET (toval);
+ changed_len = TYPE_LENGTH (type);
+ dest_buffer = VALUE_CONTENTS (fromval);
+ }
+
+ write_memory (changed_addr, dest_buffer, changed_len);
+ if (memory_changed_hook)
+ memory_changed_hook (changed_addr, changed_len);
+ }
+ break;
+
+ case lval_register:
+ if (VALUE_BITSIZE (toval))
+ {
+ char buffer[sizeof (LONGEST)];
+ int len = REGISTER_RAW_SIZE (VALUE_REGNO (toval));
+
+ if (len > (int) sizeof (LONGEST))
+ error ("Can't handle bitfields in registers larger than %d bits.",
+ sizeof (LONGEST) * HOST_CHAR_BIT);
+
+ if (VALUE_BITPOS (toval) + VALUE_BITSIZE (toval)
+ > len * HOST_CHAR_BIT)
+ /* Getting this right would involve being very careful about
+ byte order. */
+ error ("\
+Can't handle bitfield which doesn't fit in a single register.");
+
+ read_register_bytes (VALUE_ADDRESS (toval) + VALUE_OFFSET (toval),
+ buffer, len);
+ modify_field (buffer, value_as_long (fromval),
+ VALUE_BITPOS (toval), VALUE_BITSIZE (toval));
+ write_register_bytes (VALUE_ADDRESS (toval) + VALUE_OFFSET (toval),
+ buffer, len);
+ }
+ 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
+ }
+ /* Assigning to the stack pointer, frame pointer, and other
+ (architecture and calling convention specific) registers may
+ cause the frame cache to be out of date. We just do this
+ on all assignments to registers for simplicity; I doubt the slowdown
+ matters. */
+ reinit_frame_cache ();
+ 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;
+
+ /* Make the buffer large enough in all cases. */
+ char *buffer = (char *) alloca (amount_to_copy
+ + sizeof (LONGEST)
+ + MAX_REGISTER_RAW_SIZE);
+
+ int regno;
+ struct frame_info *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.");
+ }
+
+ if (register_changed_hook)
+ register_changed_hook (-1);
+ }
+ break;
+
+
+ default:
+ error ("Left operand of assignment is not an lvalue.");
+ }
+
+ /* 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 ((VALUE_BITSIZE (toval) > 0)
+ && (VALUE_BITSIZE (toval) < 8 * (int) sizeof (LONGEST)))
+ {
+ LONGEST fieldval = value_as_long (fromval);
+ LONGEST valmask = (((ULONGEST) 1) << VALUE_BITSIZE (toval)) - 1;
+
+ fieldval &= valmask;
+ if (!TYPE_UNSIGNED (type) && (fieldval & (valmask ^ (valmask >> 1))))
+ fieldval |= ~valmask;
+
+ fromval = value_from_longest (type, fieldval);
+ }
+
+ val = value_copy (toval);
+ memcpy (VALUE_CONTENTS_RAW (val), VALUE_CONTENTS (fromval),
+ TYPE_LENGTH (type));
+ VALUE_TYPE (val) = type;
+ VALUE_ENCLOSING_TYPE (val) = VALUE_ENCLOSING_TYPE (fromval);
+ VALUE_EMBEDDED_OFFSET (val) = VALUE_EMBEDDED_OFFSET (fromval);
+ VALUE_POINTED_TO_OFFSET (val) = VALUE_POINTED_TO_OFFSET (fromval);
+
+ return val;
+}
+
+/* Extend a value VAL to COUNT repetitions of its type. */
+
+value_ptr
+value_repeat (arg1, count)
+ value_ptr arg1;
+ int count;
+{
+ register value_ptr 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_ENCLOSING_TYPE (arg1), count);
+
+ read_memory (VALUE_ADDRESS (arg1) + VALUE_OFFSET (arg1),
+ VALUE_CONTENTS_ALL_RAW (val),
+ TYPE_LENGTH (VALUE_ENCLOSING_TYPE (val)));
+ VALUE_LVAL (val) = lval_memory;
+ VALUE_ADDRESS (val) = VALUE_ADDRESS (arg1) + VALUE_OFFSET (arg1);
+
+ return val;
+}
+
+value_ptr
+value_of_variable (var, b)
+ struct symbol *var;
+ struct block *b;
+{
+ value_ptr val;
+ struct frame_info *frame = NULL;
+
+ if (!b)
+ frame = NULL; /* Use selected frame. */
+ else if (symbol_read_needs_frame (var))
+ {
+ frame = block_innermost_frame (b);
+ if (!frame)
+ {
+ if (BLOCK_FUNCTION (b)
+ && SYMBOL_SOURCE_NAME (BLOCK_FUNCTION (b)))
+ error ("No frame is currently executing in block %s.",
+ SYMBOL_SOURCE_NAME (BLOCK_FUNCTION (b)));
+ else
+ error ("No frame is currently executing in specified block");
+ }
+ }
+
+ val = read_var_value (var, frame);
+ if (!val)
+ 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_ptr
+value_coerce_array (arg1)
+ value_ptr arg1;
+{
+ register struct type *type = check_typedef (VALUE_TYPE (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_TARGET_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_ptr
+value_coerce_function (arg1)
+ value_ptr arg1;
+{
+ value_ptr retval;
+
+ if (VALUE_LVAL (arg1) != lval_memory)
+ error ("Attempt to take address of value not located in memory.");
+
+ retval = value_from_longest (lookup_pointer_type (VALUE_TYPE (arg1)),
+ (LONGEST) (VALUE_ADDRESS (arg1) + VALUE_OFFSET (arg1)));
+ VALUE_BFD_SECTION (retval) = VALUE_BFD_SECTION (arg1);
+ return retval;
+}
+
+/* Return a pointer value for the object for which ARG1 is the contents. */
+
+value_ptr
+value_addr (arg1)
+ value_ptr arg1;
+{
+ value_ptr arg2;
+
+ struct type *type = check_typedef (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. */
+ arg2 = value_copy (arg1);
+ VALUE_TYPE (arg2) = lookup_pointer_type (TYPE_TARGET_TYPE (type));
+ return arg2;
+ }
+ 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.");
+
+ /* Get target memory address */
+ arg2 = value_from_longest (lookup_pointer_type (VALUE_TYPE (arg1)),
+ (LONGEST) (VALUE_ADDRESS (arg1)
+ + VALUE_OFFSET (arg1)
+ + VALUE_EMBEDDED_OFFSET (arg1)));
+
+ /* This may be a pointer to a base subobject; so remember the
+ full derived object's type ... */
+ VALUE_ENCLOSING_TYPE (arg2) = lookup_pointer_type (VALUE_ENCLOSING_TYPE (arg1));
+ /* ... and also the relative position of the subobject in the full object */
+ VALUE_POINTED_TO_OFFSET (arg2) = VALUE_EMBEDDED_OFFSET (arg1);
+ VALUE_BFD_SECTION (arg2) = VALUE_BFD_SECTION (arg1);
+ return arg2;
+}
+
+/* Given a value of a pointer type, apply the C unary * operator to it. */
+
+value_ptr
+value_ind (arg1)
+ value_ptr arg1;
+{
+ struct type *base_type;
+ value_ptr arg2;
+ value_ptr real_val;
+
+ COERCE_ARRAY (arg1);
+
+ base_type = check_typedef (VALUE_TYPE (arg1));
+
+ if (TYPE_CODE (base_type) == 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 (base_type) == TYPE_CODE_INT)
+ return value_at (builtin_type_int,
+ (CORE_ADDR) value_as_long (arg1),
+ VALUE_BFD_SECTION (arg1));
+ else if (TYPE_CODE (base_type) == TYPE_CODE_PTR)
+ {
+ struct type *enc_type;
+ /* We may be pointing to something embedded in a larger object */
+ /* Get the real type of the enclosing object */
+ enc_type = check_typedef (VALUE_ENCLOSING_TYPE (arg1));
+ enc_type = TYPE_TARGET_TYPE (enc_type);
+ /* Retrieve the enclosing object pointed to */
+ arg2 = value_at_lazy (enc_type,
+ value_as_pointer (arg1) - VALUE_POINTED_TO_OFFSET (arg1),
+ VALUE_BFD_SECTION (arg1));
+ /* Re-adjust type */
+ VALUE_TYPE (arg2) = TYPE_TARGET_TYPE (base_type);
+ /* Add embedding info */
+ VALUE_ENCLOSING_TYPE (arg2) = enc_type;
+ VALUE_EMBEDDED_OFFSET (arg2) = VALUE_POINTED_TO_OFFSET (arg1);
+
+ /* We may be pointing to an object of some derived type */
+ arg2 = value_full_object (arg2, NULL, 0, 0, 0);
+ return arg2;
+ }
+
+ 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;
+ ULONGEST word;
+{
+ register int len = REGISTER_SIZE;
+ char buffer[MAX_REGISTER_RAW_SIZE];
+
+ store_unsigned_integer (buffer, len, word);
+ if (INNER_THAN (1, 2))
+ {
+ /* stack grows downward */
+ sp -= len;
+ write_memory (sp, buffer, len);
+ }
+ else
+ {
+ /* stack grows upward */
+ write_memory (sp, buffer, len);
+ sp += len;
+ }
+
+ return sp;
+}
+
+/* Push LEN bytes with data at BUFFER. */
+
+CORE_ADDR
+push_bytes (sp, buffer, len)
+ CORE_ADDR sp;
+ char *buffer;
+ int len;
+{
+ if (INNER_THAN (1, 2))
+ {
+ /* stack grows downward */
+ sp -= len;
+ write_memory (sp, buffer, len);
+ }
+ else
+ {
+ /* stack grows upward */
+ write_memory (sp, buffer, len);
+ sp += len;
+ }
+
+ return sp;
+}
+
+/* Push onto the stack the specified value VALUE. */
+
+#ifndef PUSH_ARGUMENTS
+
+static CORE_ADDR
+value_push (sp, arg)
+ register CORE_ADDR sp;
+ value_ptr arg;
+{
+ register int len = TYPE_LENGTH (VALUE_ENCLOSING_TYPE (arg));
+
+ if (INNER_THAN (1, 2))
+ {
+ /* stack grows downward */
+ sp -= len;
+ write_memory (sp, VALUE_CONTENTS_ALL (arg), len);
+ }
+ else
+ {
+ /* stack grows upward */
+ write_memory (sp, VALUE_CONTENTS_ALL (arg), len);
+ sp += len;
+ }
+
+ return sp;
+}
+
+#endif /* !PUSH_ARGUMENTS */
+
+#ifdef CALL_DUMMY
+/* Perform the standard coercions that are specified
+ for arguments to be passed to C functions.
+
+ If PARAM_TYPE is non-NULL, it is the expected parameter type.
+ IS_PROTOTYPED is non-zero if the function declaration is prototyped. */
+
+static value_ptr
+value_arg_coerce (arg, param_type, is_prototyped)
+ value_ptr arg;
+ struct type *param_type;
+ int is_prototyped;
+{
+ register struct type *arg_type = check_typedef (VALUE_TYPE (arg));
+ register struct type *type
+ = param_type ? check_typedef (param_type) : arg_type;
+
+ switch (TYPE_CODE (type))
+ {
+ case TYPE_CODE_REF:
+ if (TYPE_CODE (arg_type) != TYPE_CODE_REF)
+ {
+ arg = value_addr (arg);
+ VALUE_TYPE (arg) = param_type;
+ return arg;
+ }
+ break;
+ case TYPE_CODE_INT:
+ case TYPE_CODE_CHAR:
+ case TYPE_CODE_BOOL:
+ case TYPE_CODE_ENUM:
+ /* If we don't have a prototype, coerce to integer type if necessary. */
+ if (!is_prototyped)
+ {
+ if (TYPE_LENGTH (type) < TYPE_LENGTH (builtin_type_int))
+ type = builtin_type_int;
+ }
+ /* Currently all target ABIs require at least the width of an integer
+ type for an argument. We may have to conditionalize the following
+ type coercion for future targets. */
+ if (TYPE_LENGTH (type) < TYPE_LENGTH (builtin_type_int))
+ type = builtin_type_int;
+ break;
+ case TYPE_CODE_FLT:
+ /* FIXME: We should always convert floats to doubles in the
+ non-prototyped case. As many debugging formats include
+ no information about prototyping, we have to live with
+ COERCE_FLOAT_TO_DOUBLE for now. */
+ if (!is_prototyped && COERCE_FLOAT_TO_DOUBLE)
+ {
+ if (TYPE_LENGTH (type) < TYPE_LENGTH (builtin_type_double))
+ type = builtin_type_double;
+ else if (TYPE_LENGTH (type) > TYPE_LENGTH (builtin_type_double))
+ type = builtin_type_long_double;
+ }
+ break;
+ case TYPE_CODE_FUNC:
+ type = lookup_pointer_type (type);
+ break;
+ case TYPE_CODE_ARRAY:
+ if (current_language->c_style_arrays)
+ type = lookup_pointer_type (TYPE_TARGET_TYPE (type));
+ break;
+ case TYPE_CODE_UNDEF:
+ case TYPE_CODE_PTR:
+ case TYPE_CODE_STRUCT:
+ case TYPE_CODE_UNION:
+ case TYPE_CODE_VOID:
+ case TYPE_CODE_SET:
+ case TYPE_CODE_RANGE:
+ case TYPE_CODE_STRING:
+ case TYPE_CODE_BITSTRING:
+ case TYPE_CODE_ERROR:
+ case TYPE_CODE_MEMBER:
+ case TYPE_CODE_METHOD:
+ case TYPE_CODE_COMPLEX:
+ default:
+ break;
+ }
+
+ return value_cast (type, 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_ptr function;
+ struct type **retval_type;
+{
+ register struct type *ftype = check_typedef (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);
+ ftype = check_typedef (TYPE_TARGET_TYPE (ftype));
+ if (TYPE_CODE (ftype) == TYPE_CODE_FUNC
+ || TYPE_CODE (ftype) == TYPE_CODE_METHOD)
+ {
+#ifdef CONVERT_FROM_FUNC_PTR_ADDR
+ /* FIXME: This is a workaround for the unusual function
+ pointer representation on the RS/6000, see comment
+ in config/rs6000/tm-rs6000.h */
+ funaddr = CONVERT_FROM_FUNC_PTR_ADDR (funaddr);
+#endif
+ value_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;
+}
+
+/* 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.
+
+ ARGS is modified to contain coerced values. */
+
+value_ptr
+call_function_by_hand (function, nargs, args)
+ value_ptr function;
+ int nargs;
+ value_ptr *args;
+{
+ register CORE_ADDR sp;
+ register int i;
+ CORE_ADDR start_sp;
+ /* CALL_DUMMY is an array of words (REGISTER_SIZE), but each word
+ is in host byte order. Before calling FIX_CALL_DUMMY, we byteswap it
+ and remove any extra bytes which might exist because ULONGEST is
+ bigger than REGISTER_SIZE.
+
+ NOTE: This is pretty wierd, as the call dummy is actually a
+ sequence of instructions. But CISC machines will have
+ to pack the instructions into REGISTER_SIZE units (and
+ so will RISC machines for which INSTRUCTION_SIZE is not
+ REGISTER_SIZE). */
+
+ static ULONGEST dummy[] = CALL_DUMMY;
+ char dummy1[REGISTER_SIZE * sizeof dummy / sizeof (ULONGEST)];
+ CORE_ADDR old_sp;
+ struct type *value_type;
+ unsigned char struct_return;
+ CORE_ADDR struct_addr = 0;
+ struct inferior_status inf_status;
+ struct cleanup *old_chain;
+ CORE_ADDR funaddr;
+ int using_gcc; /* Set to version of gcc in use, or zero if not gcc */
+ CORE_ADDR real_pc;
+ struct type *param_type = NULL;
+ struct type *ftype = check_typedef (SYMBOL_TYPE (function));
+
+ if (!target_has_execution)
+ noprocess();
+
+ save_inferior_status (&inf_status, 1);
+ old_chain = make_cleanup ((make_cleanup_func) 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 (INNER_THAN (1, 2))
+ {
+ /* Stack grows down */
+ sp -= sizeof dummy1;
+ start_sp = sp;
+ }
+ else
+ {
+ /* Stack grows up */
+ start_sp = sp;
+ sp += sizeof dummy1;
+ }
+
+ funaddr = find_function_addr (function, &value_type);
+ CHECK_TYPEDEF (value_type);
+
+ {
+ struct block *b = block_for_pc (funaddr);
+ /* If compiled without -g, assume GCC 2. */
+ using_gcc = (b == NULL ? 2 : 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 < (int) (sizeof (dummy) / sizeof (dummy[0])); i++)
+ store_unsigned_integer (&dummy1[i * REGISTER_SIZE],
+ REGISTER_SIZE,
+ (ULONGEST)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 dummy1);
+#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 dummy1; 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 dummy1;
+ write_memory (real_pc, (char *)dummy1, sizeof dummy1);
+ }
+#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 dummy1);
+ 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
+
+ if (nargs < TYPE_NFIELDS (ftype))
+ error ("too few arguments in function call");
+
+ for (i = nargs - 1; i >= 0; i--)
+ {
+ /* If we're off the end of the known arguments, do the standard
+ promotions. FIXME: if we had a prototype, this should only
+ be allowed if ... were present. */
+ if (i >= TYPE_NFIELDS (ftype))
+ args[i] = value_arg_coerce (args[i], NULL, 0);
+
+ else
+ {
+ int is_prototyped = TYPE_FLAGS (ftype) & TYPE_FLAG_PROTOTYPED;
+ param_type = TYPE_FIELD_TYPE (ftype, i);
+
+ args[i] = value_arg_coerce (args[i], param_type, is_prototyped);
+ }
+
+ /*elz: this code is to handle the case in which the function to be called
+ has a pointer to function as parameter and the corresponding actual argument
+ is the address of a function and not a pointer to function variable.
+ In aCC compiled code, the calls through pointers to functions (in the body
+ of the function called by hand) are made via $$dyncall_external which
+ requires some registers setting, this is taken care of if we call
+ via a function pointer variable, but not via a function address.
+ In cc this is not a problem. */
+
+ if (using_gcc == 0)
+ if (param_type)
+ /* if this parameter is a pointer to function*/
+ if (TYPE_CODE (param_type) == TYPE_CODE_PTR)
+ if (TYPE_CODE (param_type->target_type) == TYPE_CODE_FUNC)
+ /* elz: FIXME here should go the test about the compiler used
+ to compile the target. We want to issue the error
+ message only if the compiler used was HP's aCC.
+ If we used HP's cc, then there is no problem and no need
+ to return at this point */
+ if (using_gcc == 0) /* && compiler == aCC*/
+ /* go see if the actual parameter is a variable of type
+ pointer to function or just a function */
+ if (args[i]->lval == not_lval)
+ {
+ char *arg_name;
+ if (find_pc_partial_function((CORE_ADDR)args[i]->aligner.contents[0], &arg_name, NULL, NULL))
+ error("\
+You cannot use function <%s> as argument. \n\
+You must use a pointer to function type variable. Command ignored.", arg_name);
+ }
+ }
+
+#if defined (REG_STRUCT_HAS_ADDR)
+ {
+ /* This is a machine like the sparc, where we may need to pass a pointer
+ to the structure, not the structure itself. */
+ for (i = nargs - 1; i >= 0; i--)
+ {
+ struct type *arg_type = check_typedef (VALUE_TYPE (args[i]));
+ if ((TYPE_CODE (arg_type) == TYPE_CODE_STRUCT
+ || TYPE_CODE (arg_type) == TYPE_CODE_UNION
+ || TYPE_CODE (arg_type) == TYPE_CODE_ARRAY
+ || TYPE_CODE (arg_type) == TYPE_CODE_STRING
+ || TYPE_CODE (arg_type) == TYPE_CODE_BITSTRING
+ || TYPE_CODE (arg_type) == TYPE_CODE_SET
+ || (TYPE_CODE (arg_type) == TYPE_CODE_FLT
+ && TYPE_LENGTH (arg_type) > 8)
+ )
+ && REG_STRUCT_HAS_ADDR (using_gcc, arg_type))
+ {
+ CORE_ADDR addr;
+ int len; /* = TYPE_LENGTH (arg_type); */
+ int aligned_len;
+ arg_type = check_typedef (VALUE_ENCLOSING_TYPE (args[i]));
+ len = TYPE_LENGTH (arg_type);
+
+#ifdef STACK_ALIGN
+ /* MVS 11/22/96: I think at least some of this stack_align code is
+ really broken. Better to let PUSH_ARGUMENTS adjust the stack in
+ a target-defined manner. */
+ aligned_len = STACK_ALIGN (len);
+#else
+ aligned_len = len;
+#endif
+ if (INNER_THAN (1, 2))
+ {
+ /* stack grows downward */
+ sp -= aligned_len;
+ }
+ else
+ {
+ /* The stack grows up, so the address of the thing we push
+ is the stack pointer before we push it. */
+ addr = sp;
+ }
+ /* Push the structure. */
+ write_memory (sp, VALUE_CONTENTS_ALL (args[i]), len);
+ if (INNER_THAN (1, 2))
+ {
+ /* The stack grows down, so the address of the thing we push
+ is the stack pointer after we push it. */
+ addr = sp;
+ }
+ else
+ {
+ /* stack grows upward */
+ sp += aligned_len;
+ }
+ /* 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);*/
+ args[i] = value_from_longest (lookup_pointer_type (arg_type),
+ (LONGEST) addr);
+ }
+ }
+ }
+#endif /* REG_STRUCT_HAS_ADDR. */
+
+ /* Reserve space for the return structure to be written on the
+ stack, if necessary */
+
+ if (struct_return)
+ {
+ int len = TYPE_LENGTH (value_type);
+#ifdef STACK_ALIGN
+ /* MVS 11/22/96: I think at least some of this stack_align code is
+ really broken. Better to let PUSH_ARGUMENTS adjust the stack in
+ a target-defined manner. */
+ len = STACK_ALIGN (len);
+#endif
+ if (INNER_THAN (1, 2))
+ {
+ /* stack grows downward */
+ sp -= len;
+ struct_addr = sp;
+ }
+ else
+ {
+ /* stack grows upward */
+ struct_addr = sp;
+ sp += len;
+ }
+ }
+
+/* elz: on HPPA no need for this extra alignment, maybe it is needed
+ on other architectures. This is because all the alignment is taken care
+ of in the above code (ifdef REG_STRUCT_HAS_ADDR) and in
+ hppa_push_arguments*/
+#ifndef NO_EXTRA_ALIGNMENT_NEEDED
+
+#if defined(STACK_ALIGN)
+ /* MVS 11/22/96: I think at least some of this stack_align code is
+ really broken. Better to let PUSH_ARGUMENTS adjust the stack in
+ a target-defined manner. */
+ if (INNER_THAN (1, 2))
+ {
+ /* If stack grows down, we must leave a hole at the top. */
+ int len = 0;
+
+ for (i = nargs - 1; i >= 0; i--)
+ len += TYPE_LENGTH (VALUE_ENCLOSING_TYPE (args[i]));
+#ifdef CALL_DUMMY_STACK_ADJUST
+ len += CALL_DUMMY_STACK_ADJUST;
+#endif
+ sp -= STACK_ALIGN (len) - len;
+ }
+#endif /* STACK_ALIGN */
+#endif /* NO_EXTRA_ALIGNMENT_NEEDED */
+
+#ifdef PUSH_ARGUMENTS
+ PUSH_ARGUMENTS(nargs, args, sp, struct_return, struct_addr);
+#else /* !PUSH_ARGUMENTS */
+ for (i = nargs - 1; i >= 0; i--)
+ sp = value_push (sp, args[i]);
+#endif /* !PUSH_ARGUMENTS */
+
+#ifdef PUSH_RETURN_ADDRESS /* for targets that use no CALL_DUMMY */
+ /* There are a number of targets now which actually don't write any
+ CALL_DUMMY instructions into the target, but instead just save the
+ machine state, push the arguments, and jump directly to the callee
+ function. Since this doesn't actually involve executing a JSR/BSR
+ instruction, the return address must be set up by hand, either by
+ pushing onto the stack or copying into a return-address register
+ as appropriate. Formerly this has been done in PUSH_ARGUMENTS,
+ but that's overloading its functionality a bit, so I'm making it
+ explicit to do it here. */
+ sp = PUSH_RETURN_ADDRESS(real_pc, sp);
+#endif /* PUSH_RETURN_ADDRESS */
+
+#if defined(STACK_ALIGN)
+ if (! INNER_THAN (1, 2))
+ {
+ /* If stack grows up, we must leave a hole at the bottom, note
+ that sp already has been advanced for the arguments! */
+#ifdef CALL_DUMMY_STACK_ADJUST
+ sp += CALL_DUMMY_STACK_ADJUST;
+#endif
+ sp = STACK_ALIGN (sp);
+ }
+#endif /* STACK_ALIGN */
+
+/* XXX This seems wrong. For stacks that grow down we shouldn't do
+ anything here! */
+ /* MVS 11/22/96: I think at least some of this stack_align code is
+ really broken. Better to let PUSH_ARGUMENTS adjust the stack in
+ a target-defined manner. */
+#ifdef CALL_DUMMY_STACK_ADJUST
+ if (INNER_THAN (1, 2))
+ {
+ /* stack grows downward */
+ sp -= CALL_DUMMY_STACK_ADJUST;
+ }
+#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);
+ /* FIXME-32x64: assumes funaddr fits in a long. */
+ 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. */
+/* elz: I defined this new macro for the hppa architecture only.
+ this gives us a way to get the value returned by the function from the stack,
+ at the same address we told the function to put it.
+ We cannot assume on the pa that r28 still contains the address of the returned
+ structure. Usually this will be overwritten by the callee.
+ I don't know about other architectures, so I defined this macro
+*/
+
+#ifdef VALUE_RETURNED_FROM_STACK
+ if (struct_return)
+ return (value_ptr) VALUE_RETURNED_FROM_STACK (value_type, struct_addr);
+#endif
+
+ return value_being_returned (value_type, retbuf, struct_return);
+ }
+}
+#else /* no CALL_DUMMY. */
+value_ptr
+call_function_by_hand (function, nargs, args)
+ value_ptr function;
+ int nargs;
+ value_ptr *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_ptr
+value_array (lowbound, highbound, elemvec)
+ int lowbound;
+ int highbound;
+ value_ptr *elemvec;
+{
+ int nelem;
+ int idx;
+ unsigned int typelength;
+ value_ptr 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_ENCLOSING_TYPE (elemvec[0]));
+ for (idx = 1; idx < nelem; idx++)
+ {
+ if (TYPE_LENGTH (VALUE_ENCLOSING_TYPE (elemvec[idx])) != typelength)
+ {
+ error ("array elements must all be the same size");
+ }
+ }
+
+ rangetype = create_range_type ((struct type *) NULL, builtin_type_int,
+ lowbound, highbound);
+ arraytype = create_array_type ((struct type *) NULL,
+ VALUE_ENCLOSING_TYPE (elemvec[0]), rangetype);
+
+ if (!current_language->c_style_arrays)
+ {
+ val = allocate_value (arraytype);
+ for (idx = 0; idx < nelem; idx++)
+ {
+ memcpy (VALUE_CONTENTS_ALL_RAW (val) + (idx * typelength),
+ VALUE_CONTENTS_ALL (elemvec[idx]),
+ typelength);
+ }
+ VALUE_BFD_SECTION (val) = VALUE_BFD_SECTION (elemvec[0]);
+ return val;
+ }
+
+ /* 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_ALL (elemvec[idx]),
+ typelength);
+ }
+
+ /* Create the array type and set up an array value to be evaluated lazily. */
+
+ val = value_at_lazy (arraytype, addr, VALUE_BFD_SECTION (elemvec[0]));
+ 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_ptr
+value_string (ptr, len)
+ char *ptr;
+ int len;
+{
+ value_ptr val;
+ int lowbound = current_language->string_lower_bound;
+ struct type *rangetype = create_range_type ((struct type *) NULL,
+ builtin_type_int,
+ lowbound, len + lowbound - 1);
+ struct type *stringtype
+ = create_string_type ((struct type *) NULL, rangetype);
+ CORE_ADDR addr;
+
+ if (current_language->c_style_arrays == 0)
+ {
+ val = allocate_value (stringtype);
+ memcpy (VALUE_CONTENTS_RAW (val), ptr, len);
+ return val;
+ }
+
+
+ /* 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);
+
+ val = value_at_lazy (stringtype, addr, NULL);
+ return (val);
+}
+
+value_ptr
+value_bitstring (ptr, len)
+ char *ptr;
+ int len;
+{
+ value_ptr val;
+ struct type *domain_type = create_range_type (NULL, builtin_type_int,
+ 0, len - 1);
+ struct type *type = create_set_type ((struct type*) NULL, domain_type);
+ TYPE_CODE (type) = TYPE_CODE_BITSTRING;
+ val = allocate_value (type);
+ memcpy (VALUE_CONTENTS_RAW (val), ptr, TYPE_LENGTH (type));
+ 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_ptr 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++)
+ {
+ struct type *tt1, *tt2;
+ if (! t2[i])
+ return i+1;
+ tt1 = check_typedef (t1[i]);
+ tt2 = check_typedef (VALUE_TYPE(t2[i]));
+ if (TYPE_CODE (tt1) == TYPE_CODE_REF
+ /* We should be doing hairy argument matching, as below. */
+ && (TYPE_CODE (check_typedef (TYPE_TARGET_TYPE (tt1))) == TYPE_CODE (tt2)))
+ {
+ if (TYPE_CODE (tt2) == TYPE_CODE_ARRAY)
+ t2[i] = value_coerce_array (t2[i]);
+ else
+ t2[i] = value_addr (t2[i]);
+ continue;
+ }
+
+ while (TYPE_CODE (tt1) == TYPE_CODE_PTR
+ && ( TYPE_CODE (tt2) == TYPE_CODE_ARRAY
+ || TYPE_CODE (tt2) == TYPE_CODE_PTR))
+ {
+ tt1 = check_typedef (TYPE_TARGET_TYPE(tt1));
+ tt2 = check_typedef (TYPE_TARGET_TYPE(tt2));
+ }
+ if (TYPE_CODE(tt1) == TYPE_CODE(tt2)) continue;
+ /* Array to pointer is a `trivial conversion' according to the ARM. */
+
+ /* 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_ptr
+search_struct_field (name, arg1, offset, type, looking_for_baseclass)
+ char *name;
+ register value_ptr arg1;
+ int offset;
+ register struct type *type;
+ int looking_for_baseclass;
+{
+ int i;
+ int nbases = TYPE_N_BASECLASSES (type);
+
+ CHECK_TYPEDEF (type);
+
+ if (! looking_for_baseclass)
+ for (i = TYPE_NFIELDS (type) - 1; i >= nbases; i--)
+ {
+ char *t_field_name = TYPE_FIELD_NAME (type, i);
+
+ if (t_field_name && STREQ (t_field_name, name))
+ {
+ value_ptr v;
+ if (TYPE_FIELD_STATIC (type, i))
+ v = value_static_field (type, i);
+ else
+ v = value_primitive_field (arg1, offset, i, type);
+ if (v == 0)
+ error("there is no field named %s", name);
+ return v;
+ }
+
+ if (t_field_name
+ && (t_field_name[0] == '\0'
+ || (TYPE_CODE (type) == TYPE_CODE_UNION
+ && STREQ (t_field_name, "else"))))
+ {
+ struct type *field_type = TYPE_FIELD_TYPE (type, i);
+ if (TYPE_CODE (field_type) == TYPE_CODE_UNION
+ || TYPE_CODE (field_type) == TYPE_CODE_STRUCT)
+ {
+ /* Look for a match through the fields of an anonymous union,
+ or anonymous struct. C++ provides anonymous unions.
+
+ In the GNU Chill implementation of variant record types,
+ each <alternative field> has an (anonymous) union type,
+ each member of the union represents a <variant alternative>.
+ Each <variant alternative> is represented as a struct,
+ with a member for each <variant field>. */
+
+ value_ptr v;
+ int new_offset = offset;
+
+ /* This is pretty gross. In G++, the offset in an anonymous
+ union is relative to the beginning of the enclosing struct.
+ In the GNU Chill implementation of variant records,
+ the bitpos is zero in an anonymous union field, so we
+ have to add the offset of the union here. */
+ if (TYPE_CODE (field_type) == TYPE_CODE_STRUCT
+ || (TYPE_NFIELDS (field_type) > 0
+ && TYPE_FIELD_BITPOS (field_type, 0) == 0))
+ new_offset += TYPE_FIELD_BITPOS (type, i) / 8;
+
+ v = search_struct_field (name, arg1, new_offset, field_type,
+ looking_for_baseclass);
+ if (v)
+ return v;
+ }
+ }
+ }
+
+ for (i = 0; i < nbases; i++)
+ {
+ value_ptr v;
+ struct type *basetype = check_typedef (TYPE_BASECLASS (type, i));
+ /* 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))
+ {
+ int boffset;
+ value_ptr v2 = allocate_value (basetype);
+
+ boffset = baseclass_offset (type, i,
+ VALUE_CONTENTS (arg1) + offset,
+ VALUE_ADDRESS (arg1)
+ + VALUE_OFFSET (arg1) + offset);
+ if (boffset == -1)
+ error ("virtual baseclass botch");
+
+ /* The virtual base class pointer might have been clobbered by the
+ user program. Make sure that it still points to a valid memory
+ location. */
+
+ boffset += offset;
+ if (boffset < 0 || boffset >= TYPE_LENGTH (type))
+ {
+ CORE_ADDR base_addr;
+
+ base_addr = VALUE_ADDRESS (arg1) + VALUE_OFFSET (arg1) + boffset;
+ if (target_read_memory (base_addr, VALUE_CONTENTS_RAW (v2),
+ TYPE_LENGTH (basetype)) != 0)
+ error ("virtual baseclass botch");
+ VALUE_LVAL (v2) = lval_memory;
+ VALUE_ADDRESS (v2) = base_addr;
+ }
+ else
+ {
+ VALUE_LVAL (v2) = VALUE_LVAL (arg1);
+ VALUE_ADDRESS (v2) = VALUE_ADDRESS (arg1);
+ VALUE_OFFSET (v2) = VALUE_OFFSET (arg1) + boffset;
+ if (VALUE_LAZY (arg1))
+ VALUE_LAZY (v2) = 1;
+ else
+ memcpy (VALUE_CONTENTS_RAW (v2),
+ VALUE_CONTENTS_RAW (arg1) + boffset,
+ TYPE_LENGTH (basetype));
+ }
+
+ 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,
+ basetype, looking_for_baseclass);
+ if (v) return v;
+ }
+ return NULL;
+}
+
+
+/* Return the offset (in bytes) of the virtual base of type BASETYPE
+ * in an object pointed to by VALADDR (on the host), assumed to be of
+ * type TYPE. OFFSET is number of bytes beyond start of ARG to start
+ * looking (in case VALADDR is the contents of an enclosing object).
+ *
+ * This routine recurses on the primary base of the derived class because
+ * the virtual base entries of the primary base appear before the other
+ * virtual base entries.
+ *
+ * If the virtual base is not found, a negative integer is returned.
+ * The magnitude of the negative integer is the number of entries in
+ * the virtual table to skip over (entries corresponding to various
+ * ancestral classes in the chain of primary bases).
+ *
+ * Important: This assumes the HP / Taligent C++ runtime
+ * conventions. Use baseclass_offset() instead to deal with g++
+ * conventions. */
+
+void
+find_rt_vbase_offset(type, basetype, valaddr, offset, boffset_p, skip_p)
+ struct type * type;
+ struct type * basetype;
+ char * valaddr;
+ int offset;
+ int * boffset_p;
+ int * skip_p;
+{
+ int boffset; /* offset of virtual base */
+ int index; /* displacement to use in virtual table */
+ int skip;
+
+ value_ptr vp;
+ CORE_ADDR vtbl; /* the virtual table pointer */
+ struct type * pbc; /* the primary base class */
+
+ /* Look for the virtual base recursively in the primary base, first.
+ * This is because the derived class object and its primary base
+ * subobject share the primary virtual table. */
+
+ boffset = 0;
+ pbc = TYPE_PRIMARY_BASE(type);
+ if (pbc)
+ {
+ find_rt_vbase_offset (pbc, basetype, valaddr, offset, &boffset, &skip);
+ if (skip < 0)
+ {
+ *boffset_p = boffset;
+ *skip_p = -1;
+ return;
+ }
+ }
+ else
+ skip = 0;
+
+
+ /* Find the index of the virtual base according to HP/Taligent
+ runtime spec. (Depth-first, left-to-right.) */
+ index = virtual_base_index_skip_primaries (basetype, type);
+
+ if (index < 0) {
+ *skip_p = skip + virtual_base_list_length_skip_primaries (type);
+ *boffset_p = 0;
+ return;
+ }
+
+ /* pai: FIXME -- 32x64 possible problem */
+ /* First word (4 bytes) in object layout is the vtable pointer */
+ vtbl = * (CORE_ADDR *) (valaddr + offset);
+
+ /* Before the constructor is invoked, things are usually zero'd out. */
+ if (vtbl == 0)
+ error ("Couldn't find virtual table -- object may not be constructed yet.");
+
+
+ /* Find virtual base's offset -- jump over entries for primary base
+ * ancestors, then use the index computed above. But also adjust by
+ * HP_ACC_VBASE_START for the vtable slots before the start of the
+ * virtual base entries. Offset is negative -- virtual base entries
+ * appear _before_ the address point of the virtual table. */
+
+ /* pai: FIXME -- 32x64 problem, if word = 8 bytes, change multiplier
+ & use long type */
+
+ /* epstein : FIXME -- added param for overlay section. May not be correct */
+ vp = value_at (builtin_type_int, vtbl + 4 * (- skip - index - HP_ACC_VBASE_START), NULL);
+ boffset = value_as_long (vp);
+ *skip_p = -1;
+ *boffset_p = boffset;
+ return;
+}
+
+
+/* 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_ptr
+search_struct_method (name, arg1p, args, offset, static_memfuncp, type)
+ char *name;
+ register value_ptr *arg1p, *args;
+ int offset, *static_memfuncp;
+ register struct type *type;
+{
+ int i;
+ value_ptr v;
+ int name_matched = 0;
+ char dem_opname[64];
+
+ CHECK_TYPEDEF (type);
+ for (i = TYPE_NFN_FIELDS (type) - 1; i >= 0; i--)
+ {
+ char *t_field_name = TYPE_FN_FIELDLIST_NAME (type, i);
+ /* FIXME! May need to check for ARM demangling here */
+ if (strncmp(t_field_name, "__", 2)==0 ||
+ strncmp(t_field_name, "op", 2)==0 ||
+ strncmp(t_field_name, "type", 4)==0 )
+ {
+ if (cplus_demangle_opname(t_field_name, dem_opname, DMGL_ANSI))
+ t_field_name = dem_opname;
+ else if (cplus_demangle_opname(t_field_name, dem_opname, 0))
+ t_field_name = dem_opname;
+ }
+ 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': no arguments supplied", 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_virtual_fn_field (arg1p, f, j, type, offset);
+ if (TYPE_FN_FIELD_STATIC_P (f, j) && static_memfuncp)
+ *static_memfuncp = 1;
+ v = value_fn_field (arg1p, f, j, type, offset);
+ if (v != NULL) return v;
+ }
+ j--;
+ }
+ }
+ }
+
+ for (i = TYPE_N_BASECLASSES (type) - 1; i >= 0; i--)
+ {
+ int base_offset;
+
+ if (BASETYPE_VIA_VIRTUAL (type, i))
+ {
+ if (TYPE_HAS_VTABLE (type))
+ {
+ /* HP aCC compiled type, search for virtual base offset
+ according to HP/Taligent runtime spec. */
+ int skip;
+ find_rt_vbase_offset (type, TYPE_BASECLASS (type, i),
+ VALUE_CONTENTS_ALL (*arg1p),
+ offset + VALUE_EMBEDDED_OFFSET (*arg1p),
+ &base_offset, &skip);
+ if (skip >= 0)
+ error ("Virtual base class offset not found in vtable");
+ }
+ else
+ {
+ struct type *baseclass = check_typedef (TYPE_BASECLASS (type, i));
+ char *base_valaddr;
+
+ /* The virtual base class pointer might have been clobbered by the
+ user program. Make sure that it still points to a valid memory
+ location. */
+
+ if (offset < 0 || offset >= TYPE_LENGTH (type))
+ {
+ base_valaddr = (char *) alloca (TYPE_LENGTH (baseclass));
+ if (target_read_memory (VALUE_ADDRESS (*arg1p)
+ + VALUE_OFFSET (*arg1p) + offset,
+ base_valaddr,
+ TYPE_LENGTH (baseclass)) != 0)
+ error ("virtual baseclass botch");
+ }
+ else
+ base_valaddr = VALUE_CONTENTS (*arg1p) + offset;
+
+ base_offset =
+ baseclass_offset (type, i, base_valaddr,
+ VALUE_ADDRESS (*arg1p)
+ + VALUE_OFFSET (*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_ptr) -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_ptr) -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_ptr
+value_struct_elt (argp, args, name, static_memfuncp, err)
+ register value_ptr *argp, *args;
+ char *name;
+ int *static_memfuncp;
+ char *err;
+{
+ register struct type *t;
+ value_ptr v;
+
+ COERCE_ARRAY (*argp);
+
+ t = check_typedef (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 = check_typedef (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 == (value_ptr) -1)
+ error ("Cannot take address of a method");
+ else 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. */
+ int m_index, f_index;
+
+ v = NULL;
+ if (get_destructor_fn_field (t, &m_index, &f_index))
+ {
+ v = value_fn_field (NULL, TYPE_FN_FIELDLIST1 (t, m_index),
+ f_index, NULL, 0);
+ }
+ if (v == NULL)
+ error ("could not find destructor function named %s.", name);
+ else
+ return v;
+ }
+ else
+ {
+ error ("destructor should not have any argument");
+ }
+ }
+ else
+ v = search_struct_method (name, argp, args, 0, static_memfuncp, t);
+
+ if (v == (value_ptr) -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;
+}
+
+/* Search through the methods of an object (and its bases)
+ * to find a specified method. Return the pointer to the
+ * fn_field list of overloaded instances.
+ * Helper function for value_find_oload_list.
+ * ARGP is a pointer to a pointer to a value (the object)
+ * METHOD is a string containing the method name
+ * OFFSET is the offset within the value
+ * STATIC_MEMFUNCP is set if the method is static
+ * TYPE is the assumed type of the object
+ * NUM_FNS is the number of overloaded instances
+ * BASETYPE is set to the actual type of the subobject where the method is found
+ * BOFFSET is the offset of the base subobject where the method is found */
+
+struct fn_field *
+find_method_list (argp, method, offset, static_memfuncp, type, num_fns, basetype, boffset)
+ value_ptr *argp;
+ char * method;
+ int offset;
+ int * static_memfuncp;
+ struct type * type;
+ int * num_fns;
+ struct type ** basetype;
+ int * boffset;
+{
+ int i;
+ struct fn_field * f;
+ CHECK_TYPEDEF (type);
+
+ *num_fns = 0;
+
+ /* First check in object itself */
+ for (i = TYPE_NFN_FIELDS (type) -1; i >= 0; i--)
+ {
+ /* pai: FIXME What about operators and type conversions? */
+ char * fn_field_name = TYPE_FN_FIELDLIST_NAME (type, i);
+ if (fn_field_name && STREQ (fn_field_name, method))
+ {
+ *num_fns = TYPE_FN_FIELDLIST_LENGTH (type, i);
+ *basetype = type;
+ *boffset = offset;
+ return TYPE_FN_FIELDLIST1 (type, i);
+ }
+ }
+
+ /* Not found in object, check in base subobjects */
+ for (i = TYPE_N_BASECLASSES (type) - 1; i >= 0; i--)
+ {
+ int base_offset;
+ if (BASETYPE_VIA_VIRTUAL (type, i))
+ {
+ if (TYPE_HAS_VTABLE (type))
+ {
+ /* HP aCC compiled type, search for virtual base offset
+ * according to HP/Taligent runtime spec. */
+ int skip;
+ find_rt_vbase_offset (type, TYPE_BASECLASS (type, i),
+ VALUE_CONTENTS_ALL (*argp),
+ offset + VALUE_EMBEDDED_OFFSET (*argp),
+ &base_offset, &skip);
+ if (skip >= 0)
+ error ("Virtual base class offset not found in vtable");
+ }
+ else
+ {
+ /* probably g++ runtime model */
+ base_offset = VALUE_OFFSET (*argp) + offset;
+ base_offset =
+ baseclass_offset (type, i,
+ VALUE_CONTENTS (*argp) + base_offset,
+ VALUE_ADDRESS (*argp) + base_offset);
+ if (base_offset == -1)
+ error ("virtual baseclass botch");
+ }
+ }
+ else /* non-virtual base, simply use bit position from debug info */
+ {
+ base_offset = TYPE_BASECLASS_BITPOS (type, i) / 8;
+ }
+ f = find_method_list (argp, method, base_offset + offset,
+ static_memfuncp, TYPE_BASECLASS (type, i), num_fns, basetype, boffset);
+ if (f)
+ return f;
+ }
+ return NULL;
+}
+
+/* Return the list of overloaded methods of a specified name.
+ * ARGP is a pointer to a pointer to a value (the object)
+ * METHOD is the method name
+ * OFFSET is the offset within the value contents
+ * STATIC_MEMFUNCP is set if the method is static
+ * NUM_FNS is the number of overloaded instances
+ * BASETYPE is set to the type of the base subobject that defines the method
+ * BOFFSET is the offset of the base subobject which defines the method */
+
+struct fn_field *
+value_find_oload_method_list (argp, method, offset, static_memfuncp, num_fns, basetype, boffset)
+ value_ptr *argp;
+ char * method;
+ int offset;
+ int * static_memfuncp;
+ int * num_fns;
+ struct type ** basetype;
+ int * boffset;
+{
+ struct type * t;
+ value_ptr v;
+
+ t = check_typedef (VALUE_TYPE (*argp));
+
+ /* code snarfed from value_struct_elt */
+ 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 = check_typedef (VALUE_TYPE (*argp));
+ }
+
+ if (TYPE_CODE (t) == TYPE_CODE_MEMBER)
+ error ("Not implemented: member type in value_find_oload_lis");
+
+ 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 struct or union");
+
+ /* Assume it's not static, unless we see that it is. */
+ if (static_memfuncp)
+ *static_memfuncp =0;
+
+ return find_method_list (argp, method, 0, static_memfuncp, t, num_fns, basetype, boffset);
+
+}
+
+/* Given an array of argument types (ARGTYPES) (which includes an
+ entry for "this" in the case of C++ methods), the number of
+ arguments NARGS, the NAME of a function whether it's a method or
+ not (METHOD), and the degree of laxness (LAX) in conforming to
+ overload resolution rules in ANSI C++, find the best function that
+ matches on the argument types according to the overload resolution
+ rules.
+
+ In the case of class methods, the parameter OBJ is an object value
+ in which to search for overloaded methods.
+
+ In the case of non-method functions, the parameter FSYM is a symbol
+ corresponding to one of the overloaded functions.
+
+ Return value is an integer: 0 -> good match, 10 -> debugger applied
+ non-standard coercions, 100 -> incompatible.
+
+ If a method is being searched for, VALP will hold the value.
+ If a non-method is being searched for, SYMP will hold the symbol for it.
+
+ If a method is being searched for, and it is a static method,
+ then STATICP will point to a non-zero value.
+
+ Note: This function does *not* check the value of
+ overload_resolution. Caller must check it to see whether overload
+ resolution is permitted.
+ */
+
+int
+find_overload_match (arg_types, nargs, name, method, lax, obj, fsym, valp, symp, staticp)
+ struct type ** arg_types;
+ int nargs;
+ char * name;
+ int method;
+ int lax;
+ value_ptr obj;
+ struct symbol * fsym;
+ value_ptr * valp;
+ struct symbol ** symp;
+ int * staticp;
+{
+ int nparms;
+ struct type ** parm_types;
+ int champ_nparms = 0;
+
+ short oload_champ = -1; /* Index of best overloaded function */
+ short oload_ambiguous = 0; /* Current ambiguity state for overload resolution */
+ /* 0 => no ambiguity, 1 => two good funcs, 2 => incomparable funcs */
+ short oload_ambig_champ = -1; /* 2nd contender for best match */
+ short oload_non_standard = 0; /* did we have to use non-standard conversions? */
+ short oload_incompatible = 0; /* are args supplied incompatible with any function? */
+
+ struct badness_vector * bv; /* A measure of how good an overloaded instance is */
+ struct badness_vector * oload_champ_bv = NULL; /* The measure for the current best match */
+
+ value_ptr temp = obj;
+ struct fn_field * fns_ptr = NULL; /* For methods, the list of overloaded methods */
+ struct symbol ** oload_syms = NULL; /* For non-methods, the list of overloaded function symbols */
+ int num_fns = 0; /* Number of overloaded instances being considered */
+ struct type * basetype = NULL;
+ int boffset;
+ register int jj;
+ register int ix;
+
+ char * obj_type_name = NULL;
+ char * func_name = NULL;
+
+ /* Get the list of overloaded methods or functions */
+ if (method)
+ {
+ obj_type_name = TYPE_NAME (VALUE_TYPE (obj));
+ /* Hack: evaluate_subexp_standard often passes in a pointer
+ value rather than the object itself, so try again */
+ if ((!obj_type_name || !*obj_type_name) &&
+ (TYPE_CODE (VALUE_TYPE (obj)) == TYPE_CODE_PTR))
+ obj_type_name = TYPE_NAME (TYPE_TARGET_TYPE (VALUE_TYPE (obj)));
+
+ fns_ptr = value_find_oload_method_list (&temp, name, 0,
+ staticp,
+ &num_fns,
+ &basetype, &boffset);
+ if (!fns_ptr || !num_fns)
+ error ("Couldn't find method %s%s%s",
+ obj_type_name,
+ (obj_type_name && *obj_type_name) ? "::" : "",
+ name);
+ }
+ else
+ {
+ int i = -1;
+ func_name = cplus_demangle (SYMBOL_NAME (fsym), DMGL_NO_OPTS);
+
+ oload_syms = make_symbol_overload_list (fsym);
+ while (oload_syms[++i])
+ num_fns++;
+ if (!num_fns)
+ error ("Couldn't find function %s", func_name);
+ }
+
+ oload_champ_bv = NULL;
+
+ /* Consider each candidate in turn */
+ for (ix = 0; ix < num_fns; ix++)
+ {
+ int jj;
+
+ /* Number of parameters for current candidate */
+ nparms = method ? TYPE_NFIELDS (fns_ptr[ix].type)
+ : TYPE_NFIELDS (SYMBOL_TYPE (oload_syms[ix]));
+
+ /* Prepare array of parameter types */
+ parm_types = (struct type **) xmalloc (nparms * (sizeof (struct type *)));
+ for (jj = 0; jj < nparms; jj++)
+ parm_types[jj] = method ? TYPE_FIELD_TYPE (fns_ptr[ix].type, jj)
+ : TYPE_FIELD_TYPE (SYMBOL_TYPE (oload_syms[ix]), jj);
+
+ /* Compare parameter types to supplied argument types */
+ bv = rank_function (parm_types, nparms, arg_types, nargs);
+
+ if (!oload_champ_bv)
+ {
+ oload_champ_bv = bv;
+ oload_champ = 0;
+ champ_nparms = nparms;
+ }
+ else
+ /* See whether current candidate is better or worse than previous best */
+ switch (compare_badness (bv, oload_champ_bv))
+ {
+ case 0:
+ oload_ambiguous = 1; /* top two contenders are equally good */
+ oload_ambig_champ = ix;
+ break;
+ case 1:
+ oload_ambiguous = 2; /* incomparable top contenders */
+ oload_ambig_champ = ix;
+ break;
+ case 2:
+ oload_champ_bv = bv; /* new champion, record details */
+ oload_ambiguous = 0;
+ oload_champ = ix;
+ oload_ambig_champ = -1;
+ champ_nparms = nparms;
+ break;
+ case 3:
+ default:
+ break;
+ }
+ free (parm_types);
+#ifdef DEBUG_OLOAD
+ if (method)
+ printf("Overloaded method instance %s, # of parms %d\n", fns_ptr[ix].physname, nparms);
+ else
+ printf("Overloaded function instance %s # of parms %d\n", SYMBOL_DEMANGLED_NAME(oload_syms[ix]),nparms);
+ for (jj = 0; jj <= nargs; jj++)
+ printf("...Badness @ %d : %d\n", jj, bv->rank[jj]);
+ printf("Overload resolution champion is %d, ambiguous? %d\n", oload_champ, oload_ambiguous);
+#endif
+ } /* end loop over all candidates */
+
+ if (oload_ambiguous)
+ {
+ if (method)
+ error ("Cannot resolve overloaded method %s%s%s to unique instance; disambiguate by specifying function signature",
+ obj_type_name,
+ (obj_type_name && *obj_type_name) ? "::" : "",
+ name);
+ else
+ error ("Cannot resolve overloaded function %s to unique instance; disambiguate by specifying function signature",
+ func_name);
+ }
+
+ /* Check how bad the best match is */
+ for (ix = 1; ix <= nargs; ix++)
+ {
+ switch (oload_champ_bv->rank[ix])
+ {
+ case 10:
+ oload_non_standard = 1; /* non-standard type conversions needed */
+ break;
+ case 100:
+ oload_incompatible = 1; /* truly mismatched types */
+ break;
+ }
+ }
+ if (oload_incompatible)
+ {
+ if (method)
+ error ("Cannot resolve method %s%s%s to any overloaded instance",
+ obj_type_name,
+ (obj_type_name && *obj_type_name) ? "::" : "",
+ name);
+ else
+ error ("Cannot resolve function %s to any overloaded instance",
+ func_name);
+ }
+ else if (oload_non_standard)
+ {
+ if (method)
+ warning ("Using non-standard conversion to match method %s%s%s to supplied arguments",
+ obj_type_name,
+ (obj_type_name && *obj_type_name) ? "::" : "",
+ name);
+ else
+ warning ("Using non-standard conversion to match function %s to supplied arguments",
+ func_name);
+ }
+
+ if (method)
+ {
+ if (TYPE_FN_FIELD_VIRTUAL_P (fns_ptr, oload_champ))
+ *valp = value_virtual_fn_field (&temp, fns_ptr, oload_champ, basetype, boffset);
+ else
+ *valp = value_fn_field (&temp, fns_ptr, oload_champ, basetype, boffset);
+ }
+ else
+ {
+ *symp = oload_syms[oload_champ];
+ free (func_name);
+ }
+
+ return oload_incompatible ? 100 : (oload_non_standard ? 10 : 0);
+}
+
+/* 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);
+ char *cp = strchr (dname, '<');
+ unsigned int len;
+
+ /* Do not compare the template part for template classes. */
+ if (cp == NULL)
+ len = strlen (dname);
+ else
+ len = cp - dname;
+ if (strlen (name + 1) != len || !STREQN (dname, name + 1, len))
+ 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))
+ {
+ int m_index, f_index;
+
+ return get_destructor_fn_field (type, &m_index, &f_index);
+ }
+
+ 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_ptr arg1;
+ const char *name;
+{
+ register struct type *t;
+
+ COERCE_ARRAY (arg1);
+
+ t = VALUE_TYPE (arg1);
+
+ /* Follow pointers until we get to a non-pointer. */
+
+ for (;;)
+ {
+ CHECK_TYPEDEF (t);
+ if (TYPE_CODE (t) != TYPE_CODE_PTR && TYPE_CODE (t) != TYPE_CODE_REF)
+ break;
+ 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_ptr
+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_ptr 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))
+ {
+ v = value_static_field (t, i);
+ if (v == NULL)
+ error ("Internal error: could not find static variable %s",
+ name);
+ return v;
+ }
+ 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)
+ {
+ char *t_field_name = TYPE_FN_FIELDLIST_NAME (t, i);
+ char dem_opname[64];
+
+ if (strncmp(t_field_name, "__", 2)==0 ||
+ strncmp(t_field_name, "op", 2)==0 ||
+ strncmp(t_field_name, "type", 4)==0 )
+ {
+ if (cplus_demangle_opname(t_field_name, dem_opname, DMGL_ANSI))
+ t_field_name = dem_opname;
+ else if (cplus_demangle_opname(t_field_name, dem_opname, 0))
+ t_field_name = dem_opname;
+ }
+ if (t_field_name && STREQ (t_field_name, 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_ptr 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;
+}
+
+
+/* Find the real run-time type of a value using RTTI.
+ * V is a pointer to the value.
+ * A pointer to the struct type entry of the run-time type
+ * is returneed.
+ * FULL is a flag that is set only if the value V includes
+ * the entire contents of an object of the RTTI type.
+ * TOP is the offset to the top of the enclosing object of
+ * the real run-time type. This offset may be for the embedded
+ * object, or for the enclosing object of V.
+ * USING_ENC is the flag that distinguishes the two cases.
+ * If it is 1, then the offset is for the enclosing object,
+ * otherwise for the embedded object.
+ *
+ * This currently works only for RTTI information generated
+ * by the HP ANSI C++ compiler (aCC). g++ today (1997-06-10)
+ * does not appear to support RTTI. This function returns a
+ * NULL value for objects in the g++ runtime model. */
+
+struct type *
+value_rtti_type (v, full, top, using_enc)
+ value_ptr v;
+ int * full;
+ int * top;
+ int * using_enc;
+{
+ struct type * known_type;
+ struct type * rtti_type;
+ CORE_ADDR coreptr;
+ value_ptr vp;
+ int using_enclosing = 0;
+ long top_offset = 0;
+ char rtti_type_name[256];
+
+ if (full)
+ *full = 0;
+ if (top)
+ *top = -1;
+ if (using_enc)
+ *using_enc = 0;
+
+ /* Get declared type */
+ known_type = VALUE_TYPE (v);
+ CHECK_TYPEDEF (known_type);
+ /* RTTI works only or class objects */
+ if (TYPE_CODE (known_type) != TYPE_CODE_CLASS)
+ return NULL;
+
+ /* If neither the declared type nor the enclosing type of the
+ * value structure has a HP ANSI C++ style virtual table,
+ * we can't do anything. */
+ if (!TYPE_HAS_VTABLE (known_type))
+ {
+ known_type = VALUE_ENCLOSING_TYPE (v);
+ CHECK_TYPEDEF (known_type);
+ if ((TYPE_CODE (known_type) != TYPE_CODE_CLASS) ||
+ !TYPE_HAS_VTABLE (known_type))
+ return NULL; /* No RTTI, or not HP-compiled types */
+ CHECK_TYPEDEF (known_type);
+ using_enclosing = 1;
+ }
+
+ if (using_enclosing && using_enc)
+ *using_enc = 1;
+
+ /* First get the virtual table address */
+ coreptr = * (CORE_ADDR *) ((VALUE_CONTENTS_ALL (v))
+ + VALUE_OFFSET (v)
+ + (using_enclosing ? 0 : VALUE_EMBEDDED_OFFSET (v)));
+ if (coreptr == 0)
+ return NULL; /* return silently -- maybe called on gdb-generated value */
+
+ /* Fetch the top offset of the object */
+ /* FIXME possible 32x64 problem with pointer size & arithmetic */
+ vp = value_at (builtin_type_int,
+ coreptr + 4 * HP_ACC_TOP_OFFSET_OFFSET,
+ VALUE_BFD_SECTION (v));
+ top_offset = value_as_long (vp);
+ if (top)
+ *top = top_offset;
+
+ /* Fetch the typeinfo pointer */
+ /* FIXME possible 32x64 problem with pointer size & arithmetic */
+ vp = value_at (builtin_type_int, coreptr + 4 * HP_ACC_TYPEINFO_OFFSET, VALUE_BFD_SECTION (v));
+ /* Indirect through the typeinfo pointer and retrieve the pointer
+ * to the string name */
+ coreptr = * (CORE_ADDR *) (VALUE_CONTENTS (vp));
+ if (!coreptr)
+ error ("Retrieved null typeinfo pointer in trying to determine run-time type");
+ vp = value_at (builtin_type_int, coreptr + 4, VALUE_BFD_SECTION (v)); /* 4 -> offset of name field */
+ /* FIXME possible 32x64 problem */
+
+ coreptr = * (CORE_ADDR *) (VALUE_CONTENTS (vp));
+
+ read_memory_string (coreptr, rtti_type_name, 256);
+
+ if (strlen (rtti_type_name) == 0)
+ error ("Retrieved null type name from typeinfo");
+
+ /* search for type */
+ rtti_type = lookup_typename (rtti_type_name, (struct block *) 0, 1);
+
+ if (!rtti_type)
+ error ("Could not find run-time type: invalid type name %s in typeinfo??", rtti_type_name);
+ CHECK_TYPEDEF (rtti_type);
+
+#if 0 /* debugging*/
+ printf("RTTI type name %s, tag %s, full? %d\n", TYPE_NAME (rtti_type), TYPE_TAG_NAME (rtti_type), full ? *full : -1);
+#endif
+
+ /* Check whether we have the entire object */
+ if (full /* Non-null pointer passed */
+
+ &&
+ /* Either we checked on the whole object in hand and found the
+ top offset to be zero */
+ (((top_offset == 0) &&
+ using_enclosing &&
+ TYPE_LENGTH (known_type) == TYPE_LENGTH (rtti_type))
+ ||
+ /* Or we checked on the embedded object and top offset was the
+ same as the embedded offset */
+ ((top_offset == VALUE_EMBEDDED_OFFSET (v)) &&
+ !using_enclosing &&
+ TYPE_LENGTH (VALUE_ENCLOSING_TYPE (v)) == TYPE_LENGTH (rtti_type))))
+
+ *full = 1;
+
+ return rtti_type;
+}
+
+/* Given a pointer value V, find the real (RTTI) type
+ of the object it points to.
+ Other parameters FULL, TOP, USING_ENC as with value_rtti_type()
+ and refer to the values computed for the object pointed to. */
+
+struct type *
+value_rtti_target_type (v, full, top, using_enc)
+ value_ptr v;
+ int * full;
+ int * top;
+ int * using_enc;
+{
+ value_ptr target;
+
+ target = value_ind (v);
+
+ return value_rtti_type (target, full, top, using_enc);
+}
+
+/* Given a value pointed to by ARGP, check its real run-time type, and
+ if that is different from the enclosing type, create a new value
+ using the real run-time type as the enclosing type (and of the same
+ type as ARGP) and return it, with the embedded offset adjusted to
+ be the correct offset to the enclosed object
+ RTYPE is the type, and XFULL, XTOP, and XUSING_ENC are the other
+ parameters, computed by value_rtti_type(). If these are available,
+ they can be supplied and a second call to value_rtti_type() is avoided.
+ (Pass RTYPE == NULL if they're not available */
+
+value_ptr
+value_full_object (argp, rtype, xfull, xtop, xusing_enc)
+ value_ptr argp;
+ struct type * rtype;
+ int xfull;
+ int xtop;
+ int xusing_enc;
+
+{
+ struct type * real_type;
+ int full = 0;
+ int top = -1;
+ int using_enc = 0;
+ value_ptr new_val;
+
+ if (rtype)
+ {
+ real_type = rtype;
+ full = xfull;
+ top = xtop;
+ using_enc = xusing_enc;
+ }
+ else
+ real_type = value_rtti_type (argp, &full, &top, &using_enc);
+
+ /* If no RTTI data, or if object is already complete, do nothing */
+ if (!real_type || real_type == VALUE_ENCLOSING_TYPE (argp))
+ return argp;
+
+ /* If we have the full object, but for some reason the enclosing
+ type is wrong, set it */ /* pai: FIXME -- sounds iffy */
+ if (full)
+ {
+ VALUE_ENCLOSING_TYPE (argp) = real_type;
+ return argp;
+ }
+
+ /* Check if object is in memory */
+ if (VALUE_LVAL (argp) != lval_memory)
+ {
+ warning ("Couldn't retrieve complete object of RTTI type %s; object may be in register(s).", TYPE_NAME (real_type));
+
+ return argp;
+ }
+
+ /* All other cases -- retrieve the complete object */
+ /* Go back by the computed top_offset from the beginning of the object,
+ adjusting for the embedded offset of argp if that's what value_rtti_type
+ used for its computation. */
+ new_val = value_at_lazy (real_type, VALUE_ADDRESS (argp) - top +
+ (using_enc ? 0 : VALUE_EMBEDDED_OFFSET (argp)),
+ VALUE_BFD_SECTION (argp));
+ VALUE_TYPE (new_val) = VALUE_TYPE (argp);
+ VALUE_EMBEDDED_OFFSET (new_val) = using_enc ? top + VALUE_EMBEDDED_OFFSET (argp) : top;
+ return new_val;
+}
+
+
+
+
+/* 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_ptr
+value_of_this (complain)
+ int complain;
+{
+ struct symbol *func, *sym;
+ struct block *b;
+ int i;
+ static const char funny_this[] = "this";
+ value_ptr 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;
+}
+
+/* Create a slice (sub-string, sub-array) of ARRAY, that is LENGTH elements
+ long, starting at LOWBOUND. The result has the same lower bound as
+ the original ARRAY. */
+
+value_ptr
+value_slice (array, lowbound, length)
+ value_ptr array;
+ int lowbound, length;
+{
+ struct type *slice_range_type, *slice_type, *range_type;
+ LONGEST lowerbound, upperbound, offset;
+ value_ptr slice;
+ struct type *array_type;
+ array_type = check_typedef (VALUE_TYPE (array));
+ COERCE_VARYING_ARRAY (array, array_type);
+ if (TYPE_CODE (array_type) != TYPE_CODE_ARRAY
+ && TYPE_CODE (array_type) != TYPE_CODE_STRING
+ && TYPE_CODE (array_type) != TYPE_CODE_BITSTRING)
+ error ("cannot take slice of non-array");
+ range_type = TYPE_INDEX_TYPE (array_type);
+ if (get_discrete_bounds (range_type, &lowerbound, &upperbound) < 0)
+ error ("slice from bad array or bitstring");
+ if (lowbound < lowerbound || length < 0
+ || lowbound + length - 1 > upperbound
+ /* Chill allows zero-length strings but not arrays. */
+ || (current_language->la_language == language_chill
+ && length == 0 && TYPE_CODE (array_type) == TYPE_CODE_ARRAY))
+ error ("slice out of range");
+ /* FIXME-type-allocation: need a way to free this type when we are
+ done with it. */
+ slice_range_type = create_range_type ((struct type*) NULL,
+ TYPE_TARGET_TYPE (range_type),
+ lowbound, lowbound + length - 1);
+ if (TYPE_CODE (array_type) == TYPE_CODE_BITSTRING)
+ {
+ int i;
+ slice_type = create_set_type ((struct type*) NULL, slice_range_type);
+ TYPE_CODE (slice_type) = TYPE_CODE_BITSTRING;
+ slice = value_zero (slice_type, not_lval);
+ for (i = 0; i < length; i++)
+ {
+ int element = value_bit_index (array_type,
+ VALUE_CONTENTS (array),
+ lowbound + i);
+ if (element < 0)
+ error ("internal error accessing bitstring");
+ else if (element > 0)
+ {
+ int j = i % TARGET_CHAR_BIT;
+ if (BITS_BIG_ENDIAN)
+ j = TARGET_CHAR_BIT - 1 - j;
+ VALUE_CONTENTS_RAW (slice)[i / TARGET_CHAR_BIT] |= (1 << j);
+ }
+ }
+ /* We should set the address, bitssize, and bitspos, so the clice
+ can be used on the LHS, but that may require extensions to
+ value_assign. For now, just leave as a non_lval. FIXME. */
+ }
+ else
+ {
+ struct type *element_type = TYPE_TARGET_TYPE (array_type);
+ offset
+ = (lowbound - lowerbound) * TYPE_LENGTH (check_typedef (element_type));
+ slice_type = create_array_type ((struct type*) NULL, element_type,
+ slice_range_type);
+ TYPE_CODE (slice_type) = TYPE_CODE (array_type);
+ slice = allocate_value (slice_type);
+ if (VALUE_LAZY (array))
+ VALUE_LAZY (slice) = 1;
+ else
+ memcpy (VALUE_CONTENTS (slice), VALUE_CONTENTS (array) + offset,
+ TYPE_LENGTH (slice_type));
+ if (VALUE_LVAL (array) == lval_internalvar)
+ VALUE_LVAL (slice) = lval_internalvar_component;
+ else
+ VALUE_LVAL (slice) = VALUE_LVAL (array);
+ VALUE_ADDRESS (slice) = VALUE_ADDRESS (array);
+ VALUE_OFFSET (slice) = VALUE_OFFSET (array) + offset;
+ }
+ return slice;
+}
+
+/* Assuming chill_varying_type (VARRAY) is true, return an equivalent
+ value as a fixed-length array. */
+
+value_ptr
+varying_to_slice (varray)
+ value_ptr varray;
+{
+ struct type *vtype = check_typedef (VALUE_TYPE (varray));
+ LONGEST length = unpack_long (TYPE_FIELD_TYPE (vtype, 0),
+ VALUE_CONTENTS (varray)
+ + TYPE_FIELD_BITPOS (vtype, 0) / 8);
+ return value_slice (value_primitive_field (varray, 0, 1, vtype), 0, length);
+}
+
+/* Create a value for a FORTRAN complex number. Currently most of
+ the time values are coerced to COMPLEX*16 (i.e. a complex number
+ composed of 2 doubles. This really should be a smarter routine
+ that figures out precision inteligently as opposed to assuming
+ doubles. FIXME: fmb */
+
+value_ptr
+value_literal_complex (arg1, arg2, type)
+ value_ptr arg1;
+ value_ptr arg2;
+ struct type *type;
+{
+ register value_ptr val;
+ struct type *real_type = TYPE_TARGET_TYPE (type);
+
+ val = allocate_value (type);
+ arg1 = value_cast (real_type, arg1);
+ arg2 = value_cast (real_type, arg2);
+
+ memcpy (VALUE_CONTENTS_RAW (val),
+ VALUE_CONTENTS (arg1), TYPE_LENGTH (real_type));
+ memcpy (VALUE_CONTENTS_RAW (val) + TYPE_LENGTH (real_type),
+ VALUE_CONTENTS (arg2), TYPE_LENGTH (real_type));
+ return val;
+}
+
+/* Cast a value into the appropriate complex data type. */
+
+static value_ptr
+cast_into_complex (type, val)
+ struct type *type;
+ register value_ptr val;
+{
+ struct type *real_type = TYPE_TARGET_TYPE (type);
+ if (TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_COMPLEX)
+ {
+ struct type *val_real_type = TYPE_TARGET_TYPE (VALUE_TYPE (val));
+ value_ptr re_val = allocate_value (val_real_type);
+ value_ptr im_val = allocate_value (val_real_type);
+
+ memcpy (VALUE_CONTENTS_RAW (re_val),
+ VALUE_CONTENTS (val), TYPE_LENGTH (val_real_type));
+ memcpy (VALUE_CONTENTS_RAW (im_val),
+ VALUE_CONTENTS (val) + TYPE_LENGTH (val_real_type),
+ TYPE_LENGTH (val_real_type));
+
+ return value_literal_complex (re_val, im_val, type);
+ }
+ else if (TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_FLT
+ || TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_INT)
+ return value_literal_complex (val, value_zero (real_type, not_lval), type);
+ else
+ error ("cannot cast non-number to complex");
+}
+
+void
+_initialize_valops ()
+{
+#if 0
+ add_show_from_set
+ (add_set_cmd ("abandon", class_support, var_boolean, (char *)&auto_abandon,
+ "Set automatic abandonment of expressions upon failure.",
+ &setlist),
+ &showlist);
+#endif
+
+ add_show_from_set
+ (add_set_cmd ("overload-resolution", class_support, var_boolean, (char *)&overload_resolution,
+ "Set overload resolution in evaluating C++ functions.",
+ &setlist),
+ &showlist);
+ overload_resolution = 1;
+
+}
diff --git a/gdb/valprint.c b/gdb/valprint.c
new file mode 100644
index 00000000000..b09da9b3145
--- /dev/null
+++ b/gdb/valprint.c
@@ -0,0 +1,1567 @@
+/* Print values for GDB, the GNU debugger.
+ Copyright 1986, 1988, 1989, 1991, 1992, 1993, 1994, 1998
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "gdb_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 "annotate.h"
+#include "valprint.h"
+
+#include <errno.h>
+
+/* Prototypes for local functions */
+
+static void print_hex_chars PARAMS ((GDB_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));
+
+void _initialize_valprint PARAMS ((void));
+
+/* 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;
+
+/* If nonzero, stops printing of char arrays at first null. */
+
+int stop_print_at_null;
+
+/* Controls pretty printing of structures. */
+
+int prettyprint_structs;
+
+/* Controls pretty printing of arrays. */
+
+int prettyprint_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, embedded_offset, address,
+ stream, format, deref_ref, recurse, pretty)
+ struct type *type;
+ char *valaddr;
+ int embedded_offset;
+ CORE_ADDR address;
+ GDB_FILE *stream;
+ int format;
+ int deref_ref;
+ int recurse;
+ enum val_prettyprint pretty;
+{
+ struct type *real_type = check_typedef (type);
+ 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. */
+
+ if (TYPE_FLAGS (real_type) & TYPE_FLAG_STUB)
+ {
+ fprintf_filtered (stream, "<incomplete type>");
+ gdb_flush (stream);
+ return (0);
+ }
+
+ return (LA_VAL_PRINT (type, valaddr, embedded_offset, 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_ptr val;
+ GDB_FILE *stream;
+ int format;
+ enum val_prettyprint pretty;
+{
+ if (val == 0)
+ {
+ printf_filtered ("<address of value unknown>");
+ return 0;
+ }
+ if (VALUE_OPTIMIZED_OUT (val))
+ {
+ printf_filtered ("<value optimized out>");
+ return 0;
+ }
+ return LA_VALUE_PRINT (val, stream, format, pretty);
+}
+
+/* Called by various <lang>_val_print routines to print
+ TYPE_CODE_INT's. TYPE is the type. VALADDR is the address of the
+ value. STREAM is where to print the value. */
+
+void
+val_print_type_code_int (type, valaddr, stream)
+ struct type *type;
+ char *valaddr;
+ GDB_FILE *stream;
+{
+ if (TYPE_LENGTH (type) > sizeof (LONGEST))
+ {
+ LONGEST val;
+
+ if (TYPE_UNSIGNED (type)
+ && extract_long_unsigned_integer (valaddr, TYPE_LENGTH (type),
+ &val))
+ {
+ print_longest (stream, 'u', 0, val);
+ }
+ else
+ {
+ /* Signed, or we couldn't turn an unsigned value into a
+ LONGEST. For signed values, 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 representable as either a signed or
+ unsigned long, depending upon what format is desired, 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(). If USE_LOCAL,
+ format it according to the current language (this should be used for most
+ integers which GDB prints, the exception is things like protocols where
+ the format of the integer is a protocol thing, not a user-visible thing).
+ */
+
+#if defined (CC_HAS_LONG_LONG) && !defined (PRINTF_HAS_LONG_LONG)
+static void
+print_decimal (stream, sign, use_local, val_ulong)
+ GDB_FILE *stream;
+ char *sign;
+ int use_local;
+ ULONGEST val_ulong;
+{
+ unsigned long temp[3];
+ int i = 0;
+ do
+ {
+ temp[i] = val_ulong % (1000 * 1000 * 1000);
+ val_ulong /= (1000 * 1000 * 1000);
+ i++;
+ }
+ while (val_ulong != 0 && i < (sizeof (temp) / sizeof (temp[0])));
+ switch (i)
+ {
+ case 1:
+ fprintf_filtered (stream, "%s%lu",
+ sign, temp[0]);
+ break;
+ case 2:
+ fprintf_filtered (stream, "%s%lu%09lu",
+ sign, temp[1], temp[0]);
+ break;
+ case 3:
+ fprintf_filtered (stream, "%s%lu%09lu%09lu",
+ sign, temp[2], temp[1], temp[0]);
+ break;
+ default:
+ abort ();
+ }
+ return;
+}
+#endif
+
+void
+print_longest (stream, format, use_local, val_long)
+ GDB_FILE *stream;
+ int format;
+ int use_local;
+ LONGEST val_long;
+{
+#if defined (CC_HAS_LONG_LONG) && !defined (PRINTF_HAS_LONG_LONG)
+ if (sizeof (long) < sizeof (LONGEST))
+ {
+ switch (format)
+ {
+ case 'd':
+ {
+ /* Print a signed value, that doesn't fit in a long */
+ if ((long) val_long != val_long)
+ {
+ if (val_long < 0)
+ print_decimal (stream, "-", use_local, -val_long);
+ else
+ print_decimal (stream, "", use_local, val_long);
+ return;
+ }
+ break;
+ }
+ case 'u':
+ {
+ /* Print an unsigned value, that doesn't fit in a long */
+ if ((unsigned long) val_long != (ULONGEST) val_long)
+ {
+ print_decimal (stream, "", use_local, val_long);
+ return;
+ }
+ break;
+ }
+ case 'x':
+ case 'o':
+ case 'b':
+ case 'h':
+ case 'w':
+ case 'g':
+ /* Print as unsigned value, must fit completely in unsigned long */
+ {
+ unsigned long temp = val_long;
+ if (temp != val_long)
+ {
+ /* Urk, can't represent value in long so print in hex.
+ Do shift in two operations so that if sizeof (long)
+ == sizeof (LONGEST) we can avoid warnings from
+ picky compilers about shifts >= the size of the
+ shiftee in bits */
+ unsigned long vbot = (unsigned long) val_long;
+ LONGEST temp = (val_long >> (sizeof (long) * HOST_CHAR_BIT - 1));
+ unsigned long vtop = temp >> 1;
+ fprintf_filtered (stream, "0x%lx%08lx", vtop, vbot);
+ return;
+ }
+ break;
+ }
+ }
+ }
+#endif
+
+#if defined (CC_HAS_LONG_LONG) && defined (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",
+ val_long);
+ 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 /* !CC_HAS_LONG_LONG || !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",
+ (unsigned long) val_long);
+ break;
+ case 'o':
+ fprintf_filtered (stream,
+ use_local ? local_octal_format_custom ("l")
+ : "%lo",
+ (unsigned long) val_long);
+ break;
+ case 'b':
+ fprintf_filtered (stream, local_hex_format_custom ("02l"),
+ (unsigned long) val_long);
+ break;
+ case 'h':
+ fprintf_filtered (stream, local_hex_format_custom ("04l"),
+ (unsigned long) val_long);
+ break;
+ case 'w':
+ fprintf_filtered (stream, local_hex_format_custom ("08l"),
+ (unsigned long) val_long);
+ break;
+ case 'g':
+ fprintf_filtered (stream, local_hex_format_custom ("016l"),
+ (unsigned long) val_long);
+ break;
+ default:
+ abort ();
+ }
+#endif /* CC_HAS_LONG_LONG || PRINTF_HAS_LONG_LONG */
+}
+
+void
+strcat_longest (format, use_local, val_long, buf, buflen)
+ int format;
+ int use_local;
+ LONGEST val_long;
+ char *buf;
+ int buflen; /* ignored, for now */
+{
+#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') && (unsigned long long)val_long > UINT_MAX))
+ {
+ sprintf (buf, "0x%lx%08lx", vtop, vbot);
+ return;
+ }
+#endif
+
+#ifdef PRINTF_HAS_LONG_LONG
+ switch (format)
+ {
+ case 'd':
+ sprintf (buf,
+ (use_local ? local_decimal_format_custom ("ll") : "%lld"),
+ val_long);
+ break;
+ case 'u':
+ sprintf (buf, "%llu", val_long);
+ break;
+ case 'x':
+ sprintf (buf,
+ (use_local ? local_hex_format_custom ("ll") : "%llx"),
+
+ val_long);
+ break;
+ case 'o':
+ sprintf (buf,
+ (use_local ? local_octal_format_custom ("ll") : "%llo"),
+ val_long);
+ break;
+ case 'b':
+ sprintf (buf, local_hex_format_custom ("02ll"), val_long);
+ break;
+ case 'h':
+ sprintf (buf, local_hex_format_custom ("04ll"), val_long);
+ break;
+ case 'w':
+ sprintf (buf, local_hex_format_custom ("08ll"), val_long);
+ break;
+ case 'g':
+ sprintf (buf, 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':
+ sprintf (buf, (use_local ? local_decimal_format_custom ("l") : "%ld"),
+ ((long) val_long));
+ break;
+ case 'u':
+ sprintf (buf, "%lu", ((unsigned long) val_long));
+ break;
+ case 'x':
+ sprintf (buf, (use_local ? local_hex_format_custom ("l") : "%lx"),
+ ((long) val_long));
+ break;
+ case 'o':
+ sprintf (buf, (use_local ? local_octal_format_custom ("l") : "%lo"),
+ ((long) val_long));
+ break;
+ case 'b':
+ sprintf (buf, local_hex_format_custom ("02l"),
+ ((long) val_long));
+ break;
+ case 'h':
+ sprintf (buf, local_hex_format_custom ("04l"),
+ ((long) val_long));
+ break;
+ case 'w':
+ sprintf (buf, local_hex_format_custom ("08l"),
+ ((long) val_long));
+ break;
+ case 'g':
+ sprintf (buf, local_hex_format_custom ("016l"),
+ ((long) val_long));
+ break;
+ default:
+ abort ();
+ }
+
+#endif /* !PRINTF_HAS_LONG_LONG */
+}
+
+/* This used to be a macro, but I don't think it is called often enough
+ to merit such treatment. */
+/* 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. */
+
+int
+longest_to_int (arg)
+ LONGEST arg;
+{
+ /* Let the compiler do the work */
+ int rtnval = (int) arg;
+
+ /* Check for overflows or underflows */
+ if (sizeof (LONGEST) > sizeof (int))
+ {
+ if (rtnval != arg)
+ {
+ error ("Value out of range.");
+ }
+ }
+ return (rtnval);
+}
+
+/* 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;
+ GDB_FILE *stream;
+{
+ DOUBLEST 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. */
+
+ {
+ unsigned 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;
+
+ /* For lint, initialize these two variables to suppress warning: */
+ low = high = nonnegative = 0;
+ if (len == 4)
+ {
+ /* It's single precision. */
+ /* Assume that floating point byte order is the same as
+ integer byte order. */
+ low = extract_unsigned_integer (valaddr, 4);
+ nonnegative = ((low & 0x80000000) == 0);
+ is_nan = ((((low >> 23) & 0xFF) == 0xFF)
+ && 0 != (low & 0x7FFFFF));
+ low &= 0x7fffff;
+ high = 0;
+ }
+ else if (len == 8)
+ {
+ /* It's double precision. Get the high and low words. */
+
+ /* Assume that floating point byte order is the same as
+ integer byte order. */
+ if (TARGET_BYTE_ORDER == BIG_ENDIAN)
+ {
+ low = extract_unsigned_integer (valaddr + 4, 4);
+ high = extract_unsigned_integer (valaddr, 4);
+ }
+ else
+ {
+ low = extract_unsigned_integer (valaddr, 4);
+ high = extract_unsigned_integer (valaddr + 4, 4);
+ }
+ nonnegative = ((high & 0x80000000) == 0);
+ is_nan = (((high >> 20) & 0x7ff) == 0x7ff
+ && ! ((((high & 0xfffff) == 0)) && (low == 0)));
+ high &= 0xfffff;
+ }
+ else
+ /* Extended. We can't detect NaNs for extendeds yet. Also note
+ that currently extendeds get nuked to double in
+ REGISTER_CONVERTIBLE. */
+ is_nan = 0;
+
+ 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>");
+ return;
+ }
+
+ if (len < sizeof (double))
+ fprintf_filtered (stream, "%.9g", (double) doub);
+ else if (len == sizeof (double))
+ fprintf_filtered (stream, "%.17g", (double) doub);
+ else
+#ifdef PRINTF_HAS_LONG_DOUBLE
+ fprintf_filtered (stream, "%.35Lg", doub);
+#else
+ /* This at least wins with values that are representable as doubles */
+ fprintf_filtered (stream, "%.17g", (double) doub);
+#endif
+}
+
+void
+print_binary_chars (stream, valaddr, len)
+ GDB_FILE *stream;
+ unsigned char *valaddr;
+ unsigned len;
+{
+
+#define BITS_IN_BYTES 8
+
+ unsigned char *p;
+ int i;
+ int b;
+
+ /* Declared "int" so it will be signed.
+ * This ensures that right shift will shift in zeros.
+ */
+ const int mask = 0x080;
+
+ /* FIXME: We should be not printing leading zeroes in most cases. */
+
+ fprintf_filtered (stream, local_binary_format_prefix ());
+ if (TARGET_BYTE_ORDER == BIG_ENDIAN)
+ {
+ for (p = valaddr;
+ p < valaddr + len;
+ p++)
+ {
+ /* Every byte has 8 binary characters; peel off
+ * and print from the MSB end.
+ */
+ for( i = 0; i < (BITS_IN_BYTES * sizeof( *p )); i++ ) {
+ if( *p & ( mask >> i ))
+ b = 1;
+ else
+ b = 0;
+
+ fprintf_filtered (stream, "%1d", b);
+ }
+ }
+ }
+ else
+ {
+ for (p = valaddr + len - 1;
+ p >= valaddr;
+ p--)
+ {
+ for( i = 0; i < (BITS_IN_BYTES * sizeof( *p )); i++ ) {
+ if( *p & ( mask >> i ))
+ b = 1;
+ else
+ b = 0;
+
+ fprintf_filtered (stream, "%1d", b);
+ }
+ }
+ }
+ fprintf_filtered (stream, local_binary_format_suffix ());
+}
+
+/* VALADDR points to an integer of LEN bytes.
+ * Print it in octal on stream or format it in buf.
+ */
+void
+print_octal_chars (stream, valaddr, len)
+ GDB_FILE *stream;
+ unsigned char *valaddr;
+ unsigned len;
+{
+ unsigned char *p;
+ unsigned char octa1, octa2, octa3, carry;
+ int cycle;
+
+ /* FIXME: We should be not printing leading zeroes in most cases. */
+
+
+ /* Octal is 3 bits, which doesn't fit. Yuk. So we have to track
+ * the extra bits, which cycle every three bytes:
+ *
+ * Byte side: 0 1 2 3
+ * | | | |
+ * bit number 123 456 78 | 9 012 345 6 | 78 901 234 | 567 890 12 |
+ *
+ * Octal side: 0 1 carry 3 4 carry ...
+ *
+ * Cycle number: 0 1 2
+ *
+ * But of course we are printing from the high side, so we have to
+ * figure out where in the cycle we are so that we end up with no
+ * left over bits at the end.
+ */
+#define BITS_IN_OCTAL 3
+#define HIGH_ZERO 0340
+#define LOW_ZERO 0016
+#define CARRY_ZERO 0003
+#define HIGH_ONE 0200
+#define MID_ONE 0160
+#define LOW_ONE 0016
+#define CARRY_ONE 0001
+#define HIGH_TWO 0300
+#define MID_TWO 0070
+#define LOW_TWO 0007
+
+ /* For 32 we start in cycle 2, with two bits and one bit carry;
+ * for 64 in cycle in cycle 1, with one bit and a two bit carry.
+ */
+ cycle = (len * BITS_IN_BYTES) % BITS_IN_OCTAL;
+ carry = 0;
+
+ fprintf_filtered (stream, local_octal_format_prefix ());
+ if (TARGET_BYTE_ORDER == BIG_ENDIAN)
+ {
+ for (p = valaddr;
+ p < valaddr + len;
+ p++)
+ {
+ switch (cycle) {
+ case 0:
+ /* No carry in, carry out two bits.
+ */
+ octa1 = (HIGH_ZERO & *p) >> 5;
+ octa2 = (LOW_ZERO & *p) >> 2;
+ carry = (CARRY_ZERO & *p);
+ fprintf_filtered (stream, "%o", octa1);
+ fprintf_filtered (stream, "%o", octa2);
+ break;
+
+ case 1:
+ /* Carry in two bits, carry out one bit.
+ */
+ octa1 = (carry << 1) | ((HIGH_ONE & *p) >> 7);
+ octa2 = (MID_ONE & *p) >> 4;
+ octa3 = (LOW_ONE & *p) >> 1;
+ carry = (CARRY_ONE & *p);
+ fprintf_filtered (stream, "%o", octa1);
+ fprintf_filtered (stream, "%o", octa2);
+ fprintf_filtered (stream, "%o", octa3);
+ break;
+
+ case 2:
+ /* Carry in one bit, no carry out.
+ */
+ octa1 = (carry << 2) | ((HIGH_TWO & *p) >> 6);
+ octa2 = (MID_TWO & *p) >> 3;
+ octa3 = (LOW_TWO & *p);
+ carry = 0;
+ fprintf_filtered (stream, "%o", octa1);
+ fprintf_filtered (stream, "%o", octa2);
+ fprintf_filtered (stream, "%o", octa3);
+ break;
+
+ default:
+ error( "Internal error in octal conversion;" );
+ }
+
+ cycle++;
+ cycle = cycle % BITS_IN_OCTAL;
+ }
+ }
+ else
+ {
+ for (p = valaddr + len - 1;
+ p >= valaddr;
+ p--)
+ {
+ switch (cycle) {
+ case 0:
+ /* Carry out, no carry in */
+ octa1 = (HIGH_ZERO & *p) >> 5;
+ octa2 = (LOW_ZERO & *p) >> 2;
+ carry = (CARRY_ZERO & *p);
+ fprintf_filtered (stream, "%o", octa1);
+ fprintf_filtered (stream, "%o", octa2);
+ break;
+
+ case 1:
+ /* Carry in, carry out */
+ octa1 = (carry << 1) | ((HIGH_ONE & *p) >> 7);
+ octa2 = (MID_ONE & *p) >> 4;
+ octa3 = (LOW_ONE & *p) >> 1;
+ carry = (CARRY_ONE & *p);
+ fprintf_filtered (stream, "%o", octa1);
+ fprintf_filtered (stream, "%o", octa2);
+ fprintf_filtered (stream, "%o", octa3);
+ break;
+
+ case 2:
+ /* Carry in, no carry out */
+ octa1 = (carry << 2) | ((HIGH_TWO & *p) >> 6);
+ octa2 = (MID_TWO & *p) >> 3;
+ octa3 = (LOW_TWO & *p);
+ carry = 0;
+ fprintf_filtered (stream, "%o", octa1);
+ fprintf_filtered (stream, "%o", octa2);
+ fprintf_filtered (stream, "%o", octa3);
+ break;
+
+ default:
+ error( "Internal error in octal conversion;" );
+ }
+
+ cycle++;
+ cycle = cycle % BITS_IN_OCTAL;
+ }
+ }
+
+ fprintf_filtered (stream, local_octal_format_suffix ());
+}
+
+/* VALADDR points to an integer of LEN bytes.
+ * Print it in decimal on stream or format it in buf.
+ */
+void
+print_decimal_chars (stream, valaddr, len)
+ GDB_FILE *stream;
+ unsigned char *valaddr;
+ unsigned len;
+{
+#define TEN 10
+#define TWO_TO_FOURTH 16
+#define CARRY_OUT( x ) ((x) / TEN) /* extend char to int */
+#define CARRY_LEFT( x ) ((x) % TEN)
+#define SHIFT( x ) ((x) << 4)
+#define START_P \
+ ((TARGET_BYTE_ORDER == BIG_ENDIAN) ? valaddr : valaddr + len - 1)
+#define NOT_END_P \
+ ((TARGET_BYTE_ORDER == BIG_ENDIAN) ? (p < valaddr + len) : (p >= valaddr))
+#define NEXT_P \
+ ((TARGET_BYTE_ORDER == BIG_ENDIAN) ? p++ : p-- )
+#define LOW_NIBBLE( x ) ( (x) & 0x00F)
+#define HIGH_NIBBLE( x ) (((x) & 0x0F0) >> 4)
+
+ unsigned char *p;
+ unsigned char *digits;
+ int carry;
+ int decimal_len;
+ int i, j, decimal_digits;
+ int dummy;
+ int flip;
+
+ /* Base-ten number is less than twice as many digits
+ * as the base 16 number, which is 2 digits per byte.
+ */
+ decimal_len = len * 2 * 2;
+ digits = (unsigned char *) malloc( decimal_len );
+ if( digits == NULL )
+ error( "Can't allocate memory for conversion to decimal." );
+
+ for( i = 0; i < decimal_len; i++ ) {
+ digits[i] = 0;
+ }
+
+ fprintf_filtered (stream, local_decimal_format_prefix ());
+
+ /* Ok, we have an unknown number of bytes of data to be printed in
+ * decimal.
+ *
+ * Given a hex number (in nibbles) as XYZ, we start by taking X and
+ * decemalizing it as "x1 x2" in two decimal nibbles. Then we multiply
+ * the nibbles by 16, add Y and re-decimalize. Repeat with Z.
+ *
+ * The trick is that "digits" holds a base-10 number, but sometimes
+ * the individual digits are > 10.
+ *
+ * Outer loop is per nibble (hex digit) of input, from MSD end to
+ * LSD end.
+ */
+ decimal_digits = 0; /* Number of decimal digits so far */
+ p = START_P;
+ flip = 0;
+ while( NOT_END_P ) {
+ /*
+ * Multiply current base-ten number by 16 in place.
+ * Each digit was between 0 and 9, now is between
+ * 0 and 144.
+ */
+ for( j = 0; j < decimal_digits; j++ ) {
+ digits[j] = SHIFT( digits[j] );
+ }
+
+ /* Take the next nibble off the input and add it to what
+ * we've got in the LSB position. Bottom 'digit' is now
+ * between 0 and 159.
+ *
+ * "flip" is used to run this loop twice for each byte.
+ */
+ if( flip == 0 ) {
+ /* Take top nibble.
+ */
+ digits[0] += HIGH_NIBBLE( *p );
+ flip = 1;
+ }
+ else {
+ /* Take low nibble and bump our pointer "p".
+ */
+ digits[0] += LOW_NIBBLE( *p );
+ NEXT_P;
+ flip = 0;
+ }
+
+ /* Re-decimalize. We have to do this often enough
+ * that we don't overflow, but once per nibble is
+ * overkill. Easier this way, though. Note that the
+ * carry is often larger than 10 (e.g. max initial
+ * carry out of lowest nibble is 15, could bubble all
+ * the way up greater than 10). So we have to do
+ * the carrying beyond the last current digit.
+ */
+ carry = 0;
+ for( j = 0; j < decimal_len - 1; j++ ) {
+ digits[j] += carry;
+
+ /* "/" won't handle an unsigned char with
+ * a value that if signed would be negative.
+ * So extend to longword int via "dummy".
+ */
+ dummy = digits[j];
+ carry = CARRY_OUT( dummy );
+ digits[j] = CARRY_LEFT( dummy );
+
+ if( j >= decimal_digits && carry == 0 ) {
+ /*
+ * All higher digits are 0 and we
+ * no longer have a carry.
+ *
+ * Note: "j" is 0-based, "decimal_digits" is
+ * 1-based.
+ */
+ decimal_digits = j + 1;
+ break;
+ }
+ }
+ }
+
+ /* Ok, now "digits" is the decimal representation, with
+ * the "decimal_digits" actual digits. Print!
+ */
+ for( i = decimal_digits - 1; i >= 0; i-- ) {
+ fprintf_filtered( stream, "%1d", digits[i] );
+ }
+ free( digits );
+
+ fprintf_filtered (stream, local_decimal_format_suffix ());
+}
+
+/* VALADDR points to an integer of LEN bytes. Print it in hex on stream. */
+
+static void
+print_hex_chars (stream, valaddr, len)
+ GDB_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++)
+ {
+ fprintf_filtered (stream, "%02x", *p);
+ }
+ }
+ else
+ {
+ for (p = valaddr + len - 1;
+ p >= valaddr;
+ p--)
+ {
+ 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;
+ GDB_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 (check_typedef (elttype));
+ len = TYPE_LENGTH (type) / eltlen;
+
+ annotate_array_section_begin (i, elttype);
+
+ 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, 0, stream, format,
+ deref_ref, recurse + 1, pretty);
+ annotate_elt_rep (reps);
+ fprintf_filtered (stream, " <repeats %u times>", reps);
+ annotate_elt_rep_end ();
+
+ i = rep1 - 1;
+ things_printed += repeat_count_threshold;
+ }
+ else
+ {
+ val_print (elttype, valaddr + i * eltlen, 0, 0, stream, format,
+ deref_ref, recurse + 1, pretty);
+ annotate_elt ();
+ things_printed++;
+ }
+ }
+ annotate_array_section_end ();
+ if (i < len)
+ {
+ fprintf_filtered (stream, "...");
+ }
+}
+
+/* Print a string from the inferior, starting at ADDR and printing up to LEN
+ characters, of WIDTH bytes a piece, to STREAM. If LEN is -1, 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. */
+
+/* FIXME: Use target_read_string. */
+
+int
+val_print_string (addr, len, width, stream)
+ CORE_ADDR addr;
+ int len;
+ int width;
+ GDB_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 chars to print. */
+ unsigned int nfetch; /* Chars to fetch / chars fetched. */
+ unsigned int chunksize; /* Size of each fetch, in chars. */
+ 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. */
+ int found_nul; /* Non-zero if we found the nul 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 >= zero, then the limit is the minimum of LEN and print_max. If
+ LEN is -1, 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 == -1 ? 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 >= zero, then we want fetchlimit chars,
+ so we might as well read them all in one operation. If LEN is -1, 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 8 and fetchlimit. We used to use 200 instead of 8 but
+ 200 is way too big for remote debugging over a serial line. */
+
+ chunksize = (len == -1 ? min (8, 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. */
+
+ found_nul = 0;
+ old_chain = make_cleanup (null_cleanup, 0);
+
+ if (len > 0)
+ {
+ buffer = (char *) xmalloc (len * width);
+ bufptr = buffer;
+ old_chain = make_cleanup (free, buffer);
+
+ nfetch = target_read_memory_partial (addr, bufptr, len * width, &errcode)
+ / width;
+ addr += nfetch * width;
+ bufptr += nfetch * width;
+ }
+ else if (len == -1)
+ {
+ unsigned long bufsize = 0;
+ do
+ {
+ QUIT;
+ nfetch = min (chunksize, fetchlimit - bufsize);
+
+ if (buffer == NULL)
+ buffer = (char *) xmalloc (nfetch * width);
+ else
+ {
+ discard_cleanups (old_chain);
+ buffer = (char *) xrealloc (buffer, (nfetch + bufsize) * width);
+ }
+
+ old_chain = make_cleanup (free, buffer);
+ bufptr = buffer + bufsize * width;
+ bufsize += nfetch;
+
+ /* Read as much as we can. */
+ nfetch = target_read_memory_partial (addr, bufptr, nfetch * width, &errcode)
+ / width;
+
+ /* 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 * width;
+ while (bufptr < limit)
+ {
+ unsigned long c;
+
+ c = extract_unsigned_integer (bufptr, width);
+ addr += width;
+ bufptr += width;
+ if (c == 0)
+ {
+ /* We don't care about any error which happened after
+ the NULL terminator. */
+ errcode = 0;
+ found_nul = 1;
+ break;
+ }
+ }
+ }
+ while (errcode == 0 /* no error */
+ && bufptr - buffer < fetchlimit * width /* no overrun */
+ && !found_nul); /* haven't found nul yet */
+ }
+ else
+ { /* length of string is really 0! */
+ buffer = bufptr = NULL;
+ errcode = 0;
+ }
+
+ /* bufptr and addr now point immediately beyond the last byte which we
+ consider part of the string (including a '\0' which ends the string). */
+
+ /* We now have either successfully filled the buffer to fetchlimit, or
+ terminated early due to an error or finding a null char when LEN is -1. */
+
+ if (len == -1 && !found_nul)
+ {
+ char *peekbuf;
+
+ /* 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. */
+
+ peekbuf = (char *) alloca (width);
+
+ if (target_read_memory (addr, peekbuf, width) == 0
+ && extract_unsigned_integer (peekbuf, width) != 0)
+ force_ellipsis = 1;
+ }
+ else if ((len >= 0 && errcode != 0) || (len > (bufptr - buffer)/width))
+ {
+ /* 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 we get an error before fetching anything, don't print a string.
+ But if we fetch something and then get an error, print the string
+ and then the error message. */
+ if (errcode == 0 || bufptr > buffer)
+ {
+ if (addressprint)
+ {
+ fputs_filtered (" ", stream);
+ }
+ LA_PRINT_STRING (stream, buffer, (bufptr - buffer)/width, width, force_ellipsis);
+ }
+
+ if (errcode != 0)
+ {
+ if (errcode == EIO)
+ {
+ fprintf_filtered (stream, " <Address ");
+ print_address_numeric (addr, 1, stream);
+ fprintf_filtered (stream, " out of bounds>");
+ }
+ else
+ {
+ fprintf_filtered (stream, " <Error reading address ");
+ print_address_numeric (addr, 1, stream);
+ fprintf_filtered (stream, ": %s>", safe_strerror (errcode));
+ }
+ }
+ gdb_flush (stream);
+ do_cleanups (old_chain);
+ return ((bufptr - buffer)/width);
+}
+
+
+/* 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_unfiltered (
+"\"set print\" must be followed by the name of a print subcommand.\n");
+ help_list (setprintlist, "set print ", -1, gdb_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 ("null-stop", no_class, var_boolean,
+ (char *)&stop_print_at_null,
+ "Set printing of char arrays to stop at first null char.",
+ &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/gdb/valprint.h b/gdb/valprint.h
new file mode 100644
index 00000000000..e6edb15c650
--- /dev/null
+++ b/gdb/valprint.h
@@ -0,0 +1,54 @@
+/* Declarations for value printing routines for GDB, the GNU debugger.
+ Copyright 1986, 1988, 1989, 1991, 1992, 1993, 1994
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 int stop_print_at_null; /* Stop printing at null char? */
+
+extern void
+val_print_array_elements PARAMS ((struct type *, char *, CORE_ADDR, GDB_FILE *,
+ int, int, int, enum val_prettyprint,
+ unsigned int));
+
+extern void
+val_print_type_code_int PARAMS ((struct type *, char *, GDB_FILE *));
+
+extern void
+print_binary_chars PARAMS ((GDB_FILE *, unsigned char *, unsigned int));
+
+extern void
+print_octal_chars PARAMS ((GDB_FILE *, unsigned char *, unsigned int));
+
+extern void
+print_decimal_chars PARAMS ((GDB_FILE *, unsigned char *, unsigned int));
+
diff --git a/gdb/value.h b/gdb/value.h
new file mode 100644
index 00000000000..44c70dec22b
--- /dev/null
+++ b/gdb/value.h
@@ -0,0 +1,568 @@
+/* Definitions for values of C expressions, for GDB.
+ Copyright 1986, 1987, 1989, 1992, 1993, 1994, 1995, 1996
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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;
+ /* Is it modifiable? Only relevant if lval != not_lval. */
+ int modifiable;
+ /* 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 of a structure in bytes.
+ This is used in retrieving contents from target memory. [Note also
+ the member embedded_offset below.] */
+ 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;
+ /* Type of the enclosing object if this is an embedded subobject.
+ The member embedded_offset gives the real position of the subobject
+ if type is not the same as enclosing_type.
+
+ If the type field is a pointer type, then enclosing_type is
+ a pointer type pointing to the real (enclosing) type of the target
+ object. */
+ struct type *enclosing_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;
+
+ /* ??? When is this used? */
+ union {
+ CORE_ADDR memaddr;
+ char *myaddr;
+ } substring_addr;
+
+ /* 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;
+ /* If this value represents an object that is embedded inside a
+ larger object (e.g., a base subobject in C++), this gives the
+ offset (in bytes) from the start of the contents buffer where
+ the embedded object begins. This is required because some C++
+ runtime implementations lay out objects (especially virtual bases
+ with possibly negative offsets to ancestors).
+ Note: This may be positive or negative! Also note that this offset
+ is not used when retrieving contents from target memory; the entire
+ enclosing object has to be retrieved always, and the offset for
+ that is given by the member offset above. */
+ int embedded_offset;
+ /* If this value represents a pointer to an object that is embedded
+ in another object, this gives the embedded_offset of the object
+ that is pointed to. */
+ int pointed_to_offset;
+ /* The BFD section associated with this value. */
+ asection *bfd_section;
+ /* 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. Note that a value therefore extends beyond
+ what is declared here. */
+ union {
+ long contents[1];
+ double force_double_align;
+ LONGEST force_longlong_align;
+ char *literal_data;
+ } aligner;
+ /* Do not add any new members here -- contents above will trash them */
+ };
+
+typedef struct value *value_ptr;
+
+#define VALUE_TYPE(val) (val)->type
+#define VALUE_ENCLOSING_TYPE(val) (val)->enclosing_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.
+ Note: The contents pointer is adjusted by the offset required to
+ get to the real subobject, if the value happens to represent
+ something embedded in a larger run-time object. */
+
+#define VALUE_CONTENTS_RAW(val) ((char *) (val)->aligner.contents + (val)->embedded_offset)
+#define VALUE_CONTENTS(val) ((void)(VALUE_LAZY(val) && value_fetch_lazy(val)),\
+ VALUE_CONTENTS_RAW(val))
+
+/* The ALL variants of the above two macros do not adjust the returned
+ pointer by the embedded_offset value. */
+
+#define VALUE_CONTENTS_ALL_RAW(val) ((char *) (val)->aligner.contents)
+#define VALUE_CONTENTS_ALL(val) ((void) (VALUE_LAZY(val) && value_fetch_lazy(val)),\
+ VALUE_CONTENTS_ALL_RAW(val))
+
+
+extern int value_fetch_lazy PARAMS ((value_ptr 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_REGNO(val) (val)->regno
+#define VALUE_OPTIMIZED_OUT(val) ((val)->optimized_out)
+#define VALUE_EMBEDDED_OFFSET(val) ((val)->embedded_offset)
+#define VALUE_POINTED_TO_OFFSET(val) ((val)->pointed_to_offset)
+#define VALUE_BFD_SECTION(val) ((val)->bfd_section)
+
+/* Convert a REF to the object referenced. */
+
+#define COERCE_REF(arg) \
+do { struct type *value_type_arg_tmp = check_typedef (VALUE_TYPE (arg));\
+ if (TYPE_CODE (value_type_arg_tmp) == TYPE_CODE_REF) \
+ arg = value_at_lazy (TYPE_TARGET_TYPE (value_type_arg_tmp), \
+ unpack_long (VALUE_TYPE (arg), \
+ VALUE_CONTENTS (arg)), \
+ VALUE_BFD_SECTION (arg)); \
+ } while (0)
+
+/* 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) \
+do { COERCE_REF(arg); \
+ if (current_language->c_style_arrays \
+ && 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); \
+} while (0)
+
+#define COERCE_NUMBER(arg) \
+ do { COERCE_ARRAY(arg); COERCE_ENUM(arg); } while (0)
+
+#define COERCE_VARYING_ARRAY(arg, real_arg_type) \
+{ if (chill_varying_type (real_arg_type)) \
+ arg = varying_to_slice (arg), real_arg_type = VALUE_TYPE (arg); }
+
+/* If ARG is an enum, convert it to an integer. */
+
+#define COERCE_ENUM(arg) { \
+ if (TYPE_CODE (check_typedef (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_ptr 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, GDB_FILE *, int));
+
+extern LONGEST value_as_long PARAMS ((value_ptr val));
+
+extern DOUBLEST value_as_double PARAMS ((value_ptr val));
+
+extern CORE_ADDR value_as_pointer PARAMS ((value_ptr val));
+
+extern LONGEST unpack_long PARAMS ((struct type *type, char *valaddr));
+
+extern DOUBLEST 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_ptr value_from_longest PARAMS ((struct type *type, LONGEST num));
+
+extern value_ptr value_from_double PARAMS ((struct type *type, DOUBLEST num));
+
+extern value_ptr value_at PARAMS ((struct type *type, CORE_ADDR addr, asection *sect));
+
+extern value_ptr value_at_lazy PARAMS ((struct type *type, CORE_ADDR addr, asection *sect));
+
+extern value_ptr value_from_register PARAMS ((struct type *type, int regnum,
+ struct frame_info * frame));
+
+extern value_ptr value_of_variable PARAMS ((struct symbol *var,
+ struct block *b));
+
+extern value_ptr value_of_register PARAMS ((int regnum));
+
+extern int symbol_read_needs_frame PARAMS ((struct symbol *));
+
+extern value_ptr read_var_value PARAMS ((struct symbol *var,
+ struct frame_info *frame));
+
+extern value_ptr locate_var_value PARAMS ((struct symbol *var,
+ struct frame_info *frame));
+
+extern value_ptr allocate_value PARAMS ((struct type *type));
+
+extern value_ptr allocate_repeat_value PARAMS ((struct type *type, int count));
+
+extern value_ptr value_mark PARAMS ((void));
+
+extern void value_free_to_mark PARAMS ((value_ptr mark));
+
+extern value_ptr value_string PARAMS ((char *ptr, int len));
+extern value_ptr value_bitstring PARAMS ((char *ptr, int len));
+
+extern value_ptr value_array PARAMS ((int lowbound, int highbound,
+ value_ptr *elemvec));
+
+extern value_ptr value_concat PARAMS ((value_ptr arg1, value_ptr arg2));
+
+extern value_ptr value_binop PARAMS ((value_ptr arg1, value_ptr arg2,
+ enum exp_opcode op));
+
+extern value_ptr value_add PARAMS ((value_ptr arg1, value_ptr arg2));
+
+extern value_ptr value_sub PARAMS ((value_ptr arg1, value_ptr arg2));
+
+extern value_ptr value_coerce_array PARAMS ((value_ptr arg1));
+
+extern value_ptr value_coerce_function PARAMS ((value_ptr arg1));
+
+extern value_ptr value_ind PARAMS ((value_ptr arg1));
+
+extern value_ptr value_addr PARAMS ((value_ptr arg1));
+
+extern value_ptr value_assign PARAMS ((value_ptr toval, value_ptr fromval));
+
+extern value_ptr value_neg PARAMS ((value_ptr arg1));
+
+extern value_ptr value_complement PARAMS ((value_ptr arg1));
+
+extern value_ptr value_struct_elt PARAMS ((value_ptr *argp, value_ptr *args,
+ char *name,
+ int *static_memfuncp, char *err));
+
+extern value_ptr value_struct_elt_for_reference PARAMS ((struct type *domain,
+ int offset,
+ struct type *curtype,
+ char *name,
+ struct type *intype));
+
+extern value_ptr value_static_field PARAMS ((struct type *type, int fieldno));
+
+extern struct fn_field *
+value_find_oload_method_list PARAMS ((value_ptr *, char *, int, int *, int *, struct type **, int *));
+
+extern value_ptr value_field PARAMS ((value_ptr arg1, int fieldno));
+
+extern value_ptr value_primitive_field PARAMS ((value_ptr arg1, int offset,
+ int fieldno,
+ struct type *arg_type));
+
+extern struct type *
+value_rtti_type PARAMS ((value_ptr, int *, int *, int *));
+
+extern struct type *
+value_rtti_target_type PARAMS ((value_ptr, int *, int *, int *));
+
+extern value_ptr
+value_full_object PARAMS ((value_ptr, struct type *, int, int, int));
+
+extern value_ptr value_cast PARAMS ((struct type *type, value_ptr arg2));
+
+extern value_ptr value_zero PARAMS ((struct type *type, enum lval_type lv));
+
+extern value_ptr value_repeat PARAMS ((value_ptr arg1, int count));
+
+extern value_ptr value_subscript PARAMS ((value_ptr array, value_ptr idx));
+
+extern value_ptr value_from_vtable_info PARAMS ((value_ptr arg,
+ struct type *type));
+
+extern value_ptr value_being_returned PARAMS ((struct type *valtype,
+ char retbuf[REGISTER_BYTES],
+ int struct_return));
+
+extern value_ptr value_in PARAMS ((value_ptr element, value_ptr set));
+
+extern int value_bit_index PARAMS ((struct type *type, char *addr, int index));
+
+extern int using_struct_return PARAMS ((value_ptr function, CORE_ADDR funcaddr,
+ struct type *value_type, int gcc_p));
+
+extern void set_return_value PARAMS ((value_ptr val));
+
+extern value_ptr evaluate_expression PARAMS ((struct expression *exp));
+
+extern value_ptr evaluate_type PARAMS ((struct expression *exp));
+
+extern value_ptr evaluate_subexp_with_coercion PARAMS ((struct expression *,
+ int *, enum noside));
+
+extern value_ptr parse_and_eval PARAMS ((char *exp));
+
+extern value_ptr 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_ptr access_value_history PARAMS ((int num));
+
+extern value_ptr value_of_internalvar PARAMS ((struct internalvar *var));
+
+extern void set_internalvar PARAMS ((struct internalvar *var, value_ptr val));
+
+extern void set_internalvar_component PARAMS ((struct internalvar *var,
+ int offset,
+ int bitpos, int bitsize,
+ value_ptr newvalue));
+
+extern struct internalvar *lookup_internalvar PARAMS ((char *name));
+
+extern int value_equal PARAMS ((value_ptr arg1, value_ptr arg2));
+
+extern int value_less PARAMS ((value_ptr arg1, value_ptr arg2));
+
+extern int value_logical_not PARAMS ((value_ptr arg1));
+
+/* C++ */
+
+extern value_ptr value_of_this PARAMS ((int complain));
+
+extern value_ptr value_x_binop PARAMS ((value_ptr arg1, value_ptr arg2,
+ enum exp_opcode op,
+ enum exp_opcode otherop,
+ enum noside noside));
+
+extern value_ptr value_x_unop PARAMS ((value_ptr arg1, enum exp_opcode op,
+ enum noside noside));
+
+extern value_ptr value_fn_field PARAMS ((value_ptr *arg1p, struct fn_field *f,
+ int j,
+ struct type* type, int offset));
+
+extern value_ptr value_virtual_fn_field PARAMS ((value_ptr *arg1p,
+ struct fn_field *f, int j,
+ struct type *type,
+ int offset));
+
+extern int binop_user_defined_p PARAMS ((enum exp_opcode op,
+ value_ptr arg1, value_ptr arg2));
+
+extern int unop_user_defined_p PARAMS ((enum exp_opcode op, value_ptr 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_ptr val));
+
+extern int record_latest_value PARAMS ((value_ptr 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 CORE_ADDR
+read_register_pid PARAMS ((int regno, int pid));
+
+extern void
+write_register PARAMS ((int regno, LONGEST val));
+
+extern void
+write_register_pid PARAMS ((int regno, CORE_ADDR val, int pid));
+
+extern void
+supply_register PARAMS ((int regno, char *val));
+
+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, GDB_FILE *stream,
+ int show));
+
+extern char *baseclass_addr PARAMS ((struct type *type, int index,
+ char *valaddr,
+ value_ptr *valuep, int *errp));
+
+extern void
+print_longest PARAMS ((GDB_FILE *stream, int format, int use_local,
+ LONGEST val));
+
+extern void
+print_floating PARAMS ((char *valaddr, struct type *type, GDB_FILE *stream));
+
+extern int value_print PARAMS ((value_ptr val, GDB_FILE *stream, int format,
+ enum val_prettyprint pretty));
+
+extern void
+value_print_array_elements PARAMS ((value_ptr val, GDB_FILE* stream,
+ int format, enum val_prettyprint pretty));
+
+extern value_ptr
+value_release_to_mark PARAMS ((value_ptr mark));
+
+extern int
+val_print PARAMS ((struct type *type, char *valaddr, int embedded_offset, CORE_ADDR address,
+ GDB_FILE *stream, int format, int deref_ref,
+ int recurse, enum val_prettyprint pretty));
+
+extern int
+val_print_string PARAMS ((CORE_ADDR addr, int len, int width, GDB_FILE *stream));
+
+extern void
+print_variable_value PARAMS ((struct symbol *var, struct frame_info *frame,
+ GDB_FILE *stream));
+
+extern int check_field PARAMS ((value_ptr, const char *));
+
+extern void
+c_typedef_print PARAMS ((struct type *type, struct symbol *news, GDB_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_ptr value_copy PARAMS ((value_ptr));
+
+extern int baseclass_offset PARAMS ((struct type *, int, char *, CORE_ADDR));
+
+/* From valops.c */
+
+extern value_ptr varying_to_slice PARAMS ((value_ptr));
+
+extern value_ptr value_slice PARAMS ((value_ptr, int, int));
+
+extern value_ptr call_function_by_hand PARAMS ((value_ptr, int, value_ptr *));
+
+extern value_ptr value_literal_complex PARAMS ((value_ptr, value_ptr, struct type*));
+
+extern void find_rt_vbase_offset PARAMS ((struct type *, struct type *, char *, int, int *, int *));
+
+extern value_ptr find_function_in_inferior PARAMS ((char *));
+
+extern value_ptr value_allocate_space_in_inferior PARAMS ((int));
+
+#endif /* !defined (VALUE_H) */
diff --git a/gdb/values.c b/gdb/values.c
new file mode 100644
index 00000000000..c7053b8df78
--- /dev/null
+++ b/gdb/values.c
@@ -0,0 +1,1623 @@
+/* Low level packing and unpacking of values for GDB, the GNU Debugger.
+ Copyright 1986, 87, 89, 91, 93, 94, 95, 96, 97, 1998
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "gdb_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 "language.h"
+#include "scm-lang.h"
+#include "demangle.h"
+
+/* Prototypes for exported functions. */
+
+void _initialize_values PARAMS ((void));
+
+/* Prototypes for local functions. */
+
+static value_ptr value_headof PARAMS ((value_ptr, struct type *,
+ struct type *));
+
+static void show_values PARAMS ((char *, int));
+
+static void show_convenience PARAMS ((char *, int));
+
+static int vb_match PARAMS ((struct type *, int, struct type *));
+
+/* 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_ptr 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_ptr all_values;
+
+/* Allocate a value that has the correct length for type TYPE. */
+
+value_ptr
+allocate_value (type)
+ struct type *type;
+{
+ register value_ptr val;
+ struct type *atype = check_typedef (type);
+
+ val = (struct value *) xmalloc (sizeof (struct value) + TYPE_LENGTH (atype));
+ VALUE_NEXT (val) = all_values;
+ all_values = val;
+ VALUE_TYPE (val) = type;
+ VALUE_ENCLOSING_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_REGNO (val) = -1;
+ VALUE_LAZY (val) = 0;
+ VALUE_OPTIMIZED_OUT (val) = 0;
+ VALUE_BFD_SECTION (val) = NULL;
+ VALUE_EMBEDDED_OFFSET (val) = 0;
+ VALUE_POINTED_TO_OFFSET (val) = 0;
+ val->modifiable = 1;
+ return val;
+}
+
+/* Allocate a value that has the correct length
+ for COUNT repetitions type TYPE. */
+
+value_ptr
+allocate_repeat_value (type, count)
+ struct type *type;
+ int count;
+{
+ int low_bound = current_language->string_lower_bound; /* ??? */
+ /* FIXME-type-allocation: need a way to free this type when we are
+ done with it. */
+ struct type *range_type
+ = create_range_type ((struct type *) NULL, builtin_type_int,
+ low_bound, count + low_bound - 1);
+ /* FIXME-type-allocation: need a way to free this type when we are
+ done with it. */
+ return allocate_value (create_array_type ((struct type *) NULL,
+ type, range_type));
+}
+
+/* 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_ptr
+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_ptr mark;
+{
+ value_ptr 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_ptr 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_ptr val;
+{
+ register value_ptr 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;
+ }
+ }
+}
+
+/* Release all values up to mark */
+value_ptr
+value_release_to_mark (mark)
+ value_ptr mark;
+{
+ value_ptr val, next;
+
+ for (val = next = all_values; next; next = VALUE_NEXT (next))
+ if (VALUE_NEXT (next) == mark)
+ {
+ all_values = VALUE_NEXT (next);
+ VALUE_NEXT (next) = 0;
+ return val;
+ }
+ all_values = 0;
+ return val;
+}
+
+/* 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_ptr
+value_copy (arg)
+ value_ptr arg;
+{
+ register struct type *encl_type = VALUE_ENCLOSING_TYPE (arg);
+ register value_ptr val = allocate_value (encl_type);
+ VALUE_TYPE (val) = VALUE_TYPE (arg);
+ 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_FRAME (val) = VALUE_FRAME (arg);
+ VALUE_REGNO (val) = VALUE_REGNO (arg);
+ VALUE_LAZY (val) = VALUE_LAZY (arg);
+ VALUE_OPTIMIZED_OUT (val) = VALUE_OPTIMIZED_OUT (arg);
+ VALUE_EMBEDDED_OFFSET (val) = VALUE_EMBEDDED_OFFSET (arg);
+ VALUE_POINTED_TO_OFFSET (val) = VALUE_POINTED_TO_OFFSET (arg);
+ VALUE_BFD_SECTION (val) = VALUE_BFD_SECTION (arg);
+ val->modifiable = arg->modifiable;
+ if (!VALUE_LAZY (val))
+ {
+ memcpy (VALUE_CONTENTS_ALL_RAW (val), VALUE_CONTENTS_ALL_RAW (arg),
+ TYPE_LENGTH (VALUE_ENCLOSING_TYPE (arg)));
+
+ }
+ 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_ptr val;
+{
+ int i;
+
+ /* 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);
+ /* We preserve VALUE_LVAL so that the user can find out where it was fetched
+ from. This is a bit dubious, because then *&$1 does not just return $1
+ but the current contents of that location. c'est la vie... */
+ val->modifiable = 0;
+ release_value (val);
+
+ /* 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;
+
+ /* 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_ptr
+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_ptr 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_ptr 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, gdb_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_ptr
+value_of_internalvar (var)
+ struct internalvar *var;
+{
+ register value_ptr 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_ptr 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_ptr val;
+{
+ value_ptr newval;
+
+#ifdef IS_TRAPPED_INTERNALVAR
+ if (IS_TRAPPED_INTERNALVAR (var->name))
+ SET_TRAPPED_INTERNALVAR (var, val, 0, 0, 0);
+#endif
+
+ newval = value_copy (val);
+ newval->modifiable = 1;
+
+ /* 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 (newval))
+ value_fetch_lazy (newval);
+
+ /* Begin code which must not call error(). If var->value points to
+ something free'd, an error() obviously leaves a dangling pointer.
+ But we also get a danling pointer if var->value points to
+ something in the value chain (i.e., before release_value is
+ called), because after the error free_all_values will get called before
+ long. */
+ free ((PTR)var->value);
+ var->value = newval;
+ release_value (newval);
+ /* End code which must not call error(). */
+}
+
+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, gdb_stdout, 0, Val_pretty_default);
+ printf_filtered ("\n");
+ }
+ if (!varseen)
+ printf_unfiltered ("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_ptr 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. */
+ COERCE_ARRAY (val);
+ return unpack_long (VALUE_TYPE (val), VALUE_CONTENTS (val));
+}
+
+DOUBLEST
+value_as_double (val)
+ register value_ptr val;
+{
+ DOUBLEST 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_ptr 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. */
+
+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 (current_language->la_language == language_scm
+ && is_scmvalue_type (type))
+ return scm_unpack (type, valaddr, TYPE_CODE_INT);
+
+ switch (code)
+ {
+ case TYPE_CODE_TYPEDEF:
+ return unpack_long (check_typedef (type), valaddr);
+ case TYPE_CODE_ENUM:
+ case TYPE_CODE_BOOL:
+ case TYPE_CODE_INT:
+ case TYPE_CODE_CHAR:
+ case TYPE_CODE_RANGE:
+ if (nosign)
+ return extract_unsigned_integer (valaddr, len);
+ else
+ return extract_signed_integer (valaddr, len);
+
+ case TYPE_CODE_FLT:
+ return extract_floating (valaddr, len);
+
+ case TYPE_CODE_PTR:
+ case TYPE_CODE_REF:
+ /* Assume a CORE_ADDR can fit in a LONGEST (for now). Not sure
+ whether we want this to be true eventually. */
+#ifdef GDB_TARGET_IS_D10V
+ if (len == 2)
+ return D10V_MAKE_DADDR(extract_address (valaddr, len));
+#endif
+ return extract_address (valaddr, len);
+
+ case TYPE_CODE_MEMBER:
+ error ("not implemented: member types in unpack_long");
+
+ default:
+ error ("Value can't be converted to integer.");
+ }
+ return 0; /* Placate lint. */
+}
+
+/* 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. */
+
+DOUBLEST
+unpack_double (type, valaddr, invp)
+ struct type *type;
+ char *valaddr;
+ int *invp;
+{
+ enum type_code code;
+ int len;
+ int nosign;
+
+ *invp = 0; /* Assume valid. */
+ CHECK_TYPEDEF (type);
+ code = TYPE_CODE (type);
+ len = TYPE_LENGTH (type);
+ nosign = TYPE_UNSIGNED (type);
+ if (code == TYPE_CODE_FLT)
+ {
+#ifdef INVALID_FLOAT
+ if (INVALID_FLOAT (valaddr, len))
+ {
+ *invp = 1;
+ return 1.234567891011121314;
+ }
+#endif
+ return extract_floating (valaddr, len);
+ }
+ else if (nosign)
+ {
+ /* Unsigned -- be sure we compensate for signed LONGEST. */
+#if !defined (_MSC_VER) || (_MSC_VER > 900)
+ return (ULONGEST) unpack_long (type, valaddr);
+#else
+ /* FIXME!!! msvc22 doesn't support unsigned __int64 -> double */
+ return (LONGEST) unpack_long (type, valaddr);
+#endif /* _MSC_VER */
+ }
+ 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);
+}
+
+/* Get the value of the FIELDN'th field (which must be static) of TYPE. */
+
+value_ptr
+value_static_field (type, fieldno)
+ struct type *type;
+ int fieldno;
+{
+ CORE_ADDR addr;
+ asection *sect;
+ if (TYPE_FIELD_STATIC_HAS_ADDR (type, fieldno))
+ {
+ addr = TYPE_FIELD_STATIC_PHYSADDR (type, fieldno);
+ sect = NULL;
+ }
+ else
+ {
+ char *phys_name = TYPE_FIELD_STATIC_PHYSNAME (type, fieldno);
+ struct symbol *sym = lookup_symbol (phys_name, 0, VAR_NAMESPACE, 0, NULL);
+ if (sym == NULL)
+ {
+ /* With some compilers, e.g. HP aCC, static data members are reported
+ as non-debuggable symbols */
+ struct minimal_symbol * msym = lookup_minimal_symbol (phys_name, NULL, NULL);
+ if (!msym)
+ return NULL;
+ else
+ {
+ addr = SYMBOL_VALUE_ADDRESS (msym);
+ sect = SYMBOL_BFD_SECTION (msym);
+ }
+ }
+ else
+ {
+ addr = SYMBOL_VALUE_ADDRESS (sym);
+ sect = SYMBOL_BFD_SECTION (sym);
+ }
+ SET_FIELD_PHYSADDR (TYPE_FIELD (type, fieldno), addr);
+ }
+ return value_at (TYPE_FIELD_TYPE (type, fieldno), addr, sect);
+}
+
+/* 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 (non-static) fields.
+ FIELDNO says which field. */
+
+value_ptr
+value_primitive_field (arg1, offset, fieldno, arg_type)
+ register value_ptr arg1;
+ int offset;
+ register int fieldno;
+ register struct type *arg_type;
+{
+ register value_ptr v;
+ register struct type *type;
+
+ CHECK_TYPEDEF (arg_type);
+ type = TYPE_FIELD_TYPE (arg_type, fieldno);
+
+ /* Handle packed fields */
+
+ if (TYPE_FIELD_BITSIZE (arg_type, fieldno))
+ {
+ v = value_from_longest (type,
+ unpack_field_as_long (arg_type,
+ VALUE_CONTENTS (arg1)
+ + offset,
+ fieldno));
+ VALUE_BITPOS (v) = TYPE_FIELD_BITPOS (arg_type, fieldno) % 8;
+ VALUE_BITSIZE (v) = TYPE_FIELD_BITSIZE (arg_type, fieldno);
+ }
+ else if (fieldno < TYPE_N_BASECLASSES (arg_type))
+ {
+ /* This field is actually a base subobject, so preserve the
+ entire object's contents for later references to virtual
+ bases, etc. */
+ v = allocate_value (VALUE_ENCLOSING_TYPE (arg1));
+ VALUE_TYPE (v) = arg_type;
+ if (VALUE_LAZY (arg1))
+ VALUE_LAZY (v) = 1;
+ else
+ memcpy (VALUE_CONTENTS_ALL_RAW (v), VALUE_CONTENTS_ALL_RAW (arg1),
+ TYPE_LENGTH (VALUE_ENCLOSING_TYPE (arg1)));
+ VALUE_OFFSET (v) = VALUE_OFFSET (arg1);
+ VALUE_EMBEDDED_OFFSET (v)
+ = offset +
+ VALUE_EMBEDDED_OFFSET (arg1) +
+ TYPE_FIELD_BITPOS (arg_type, fieldno) / 8;
+ }
+ else
+ {
+ /* Plain old data member */
+ offset += TYPE_FIELD_BITPOS (arg_type, fieldno) / 8;
+ 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_OFFSET (v) = VALUE_OFFSET (arg1) + offset;
+ }
+ 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) = VALUE_OFFSET (arg1) + offset
+ + TYPE_FIELD_BITPOS (arg_type, fieldno) / 8; */
+ return v;
+}
+
+/* Given a value ARG1 of a struct or union type,
+ extract and return the value of one of its (non-static) fields.
+ FIELDNO says which field. */
+
+value_ptr
+value_field (arg1, fieldno)
+ register value_ptr 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_ptr
+value_fn_field (arg1p, f, j, type, offset)
+ value_ptr *arg1p;
+ struct fn_field *f;
+ int j;
+ struct type *type;
+ int offset;
+{
+ register value_ptr 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)
+ return NULL;
+/*
+ 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_ptr
+value_virtual_fn_field (arg1p, f, j, type, offset)
+ value_ptr *arg1p;
+ struct fn_field *f;
+ int j;
+ struct type *type;
+ int offset;
+{
+ value_ptr arg1 = *arg1p;
+ struct type *type1 = check_typedef (VALUE_TYPE (arg1));
+
+ if (TYPE_HAS_VTABLE (type))
+ {
+ /* Deal with HP/Taligent runtime model for virtual functions */
+ value_ptr vp;
+ value_ptr argp; /* arg1 cast to base */
+ CORE_ADDR vfunc_addr; /* address of virtual method */
+ CORE_ADDR coreptr; /* pointer to target address */
+ int class_index; /* which class segment pointer to use */
+ struct type * ftype = TYPE_FN_FIELD_TYPE (f, j); /* method type */
+
+ argp = value_cast (type, *arg1p);
+
+ if (VALUE_ADDRESS (argp) == 0)
+ error ("Address of object is null; object may not have been created.");
+
+ /* pai: FIXME -- 32x64 possible problem? */
+ /* First word (4 bytes) in object layout is the vtable pointer */
+ coreptr = * (CORE_ADDR *) (VALUE_CONTENTS (argp)); /* pai: (temp) */
+ /* + offset + VALUE_EMBEDDED_OFFSET (argp)); */
+
+ if (!coreptr)
+ error ("Virtual table pointer is null for object; object may not have been created.");
+
+ /* pai/1997-05-09
+ * FIXME: The code here currently handles only
+ * the non-RRBC case of the Taligent/HP runtime spec; when RRBC
+ * is introduced, the condition for the "if" below will have to
+ * be changed to be a test for the RRBC case. */
+
+ if (1)
+ {
+ /* Non-RRBC case; the virtual function pointers are stored at fixed
+ * offsets in the virtual table. */
+
+ /* Retrieve the offset in the virtual table from the debug
+ * info. The offset of the vfunc's entry is in words from
+ * the beginning of the vtable; but first we have to adjust
+ * by HP_ACC_VFUNC_START to account for other entries */
+
+ /* pai: FIXME: 32x64 problem here, a word may be 8 bytes in
+ * which case the multiplier should be 8 and values should be long */
+ vp = value_at (builtin_type_int,
+ coreptr + 4 * (TYPE_FN_FIELD_VOFFSET (f, j) + HP_ACC_VFUNC_START), NULL);
+
+ coreptr = * (CORE_ADDR *) (VALUE_CONTENTS (vp));
+ /* coreptr now contains the address of the virtual function */
+ /* (Actually, it contains the pointer to the plabel for the function. */
+ }
+ else
+ {
+ /* RRBC case; the virtual function pointers are found by double
+ * indirection through the class segment tables. */
+
+ /* Choose class segment depending on type we were passed */
+ class_index = class_index_in_primary_list (type);
+
+ /* Find class segment pointer. These are in the vtable slots after
+ * some other entries, so adjust by HP_ACC_VFUNC_START for that. */
+ /* pai: FIXME 32x64 problem here, if words are 8 bytes long
+ * the multiplier below has to be 8 and value should be long. */
+ vp = value_at (builtin_type_int,
+ coreptr + 4 * (HP_ACC_VFUNC_START + class_index), NULL);
+ /* Indirect once more, offset by function index */
+ /* pai: FIXME 32x64 problem here, again multiplier could be 8 and value long */
+ coreptr = * (CORE_ADDR *) (VALUE_CONTENTS (vp) + 4 * TYPE_FN_FIELD_VOFFSET (f, j));
+ vp = value_at (builtin_type_int, coreptr, NULL);
+ coreptr = * (CORE_ADDR *) (VALUE_CONTENTS (vp));
+
+ /* coreptr now contains the address of the virtual function */
+ /* (Actually, it contains the pointer to the plabel for the function.) */
+
+ }
+
+ if (!coreptr)
+ error ("Address of virtual function is null; error in virtual table?");
+
+ /* Wrap this addr in a value and return pointer */
+ vp = allocate_value (ftype);
+ VALUE_TYPE (vp) = ftype;
+ VALUE_ADDRESS (vp) = coreptr;
+
+ /* pai: (temp) do we need the value_ind stuff in value_fn_field? */
+ return vp;
+ }
+ else
+ { /* Not using HP/Taligent runtime conventions; so try to
+ * use g++ conventions for virtual table */
+
+ struct type *entry_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_ptr entry, vfn, vtbl;
+ value_ptr 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) != type1)
+ {
+ value_ptr tmp = value_cast (context, value_addr (arg1));
+ VALUE_POINTED_TO_OFFSET (tmp) = 0;
+ arg1 = value_ind (tmp);
+ type1 = check_typedef (VALUE_TYPE (arg1));
+ }
+
+ context = type1;
+ /* 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_primitive_field (arg1, 0, TYPE_VPTR_FIELDNO (context),
+ TYPE_VPTR_BASETYPE (context));
+
+ /* With older versions of g++, the vtbl field pointed to an array
+ of structures. Nowadays it points directly to the structure. */
+ if (TYPE_CODE (VALUE_TYPE (vtbl)) == TYPE_CODE_PTR
+ && TYPE_CODE (TYPE_TARGET_TYPE (VALUE_TYPE (vtbl))) == TYPE_CODE_ARRAY)
+ {
+ /* Handle the case where the vtbl field points to an
+ array of structures. */
+ vtbl = value_ind (vtbl);
+
+ /* 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);
+ }
+ else
+ {
+ /* Handle the case where the vtbl field points directly to a structure. */
+ vtbl = value_add (vtbl, vi);
+ entry = value_ind (vtbl);
+ }
+
+ entry_type = check_typedef (VALUE_TYPE (entry));
+
+ if (TYPE_CODE (entry_type) == TYPE_CODE_STRUCT)
+ {
+ /* Move the `this' pointer according to the virtual function table. */
+ VALUE_OFFSET (arg1) += value_as_long (value_field (entry, 0));
+
+ if (! VALUE_LAZY (arg1))
+ {
+ VALUE_LAZY (arg1) = 1;
+ value_fetch_lazy (arg1);
+ }
+
+ vfn = value_field (entry, 2);
+ }
+ else if (TYPE_CODE (entry_type) == TYPE_CODE_PTR)
+ vfn = entry;
+ else
+ error ("I'm confused: virtual function table has bad type");
+ /* 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_ptr
+value_headof (in_arg, btype, dtype)
+ value_ptr 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_ptr 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_TYPEDEF (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
+ || (demangled_name = SYMBOL_NAME (msymbol)) == NULL
+ || !VTBL_PREFIX_P (demangled_name))
+ {
+ /* 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));
+ /* This won't work if we're using thunks. */
+ if (TYPE_CODE (check_typedef (VALUE_TYPE (entry))) != TYPE_CODE_STRUCT)
+ break;
+ 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_ptr
+value_from_vtable_info (arg, type)
+ value_ptr 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)
+ 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' && is_cplus_marker (name[3]))
+ 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 value at VALADDR (in host) at ADDRESS (in target).
+ The result is the offset of the baseclass value relative
+ to (the address of)(ARG) + OFFSET.
+
+ -1 is returned on error. */
+
+int
+baseclass_offset (type, index, valaddr, address)
+ struct type *type;
+ int index;
+ char *valaddr;
+ CORE_ADDR address;
+{
+ 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),
+ valaddr + (TYPE_FIELD_BITPOS (type, i) / 8));
+
+ return addr - (LONGEST) address;
+ }
+ }
+ /* Not in the fields, so try looking through the baseclasses. */
+ for (i = index+1; i < n_baseclasses; i++)
+ {
+ int boffset =
+ baseclass_offset (type, i, valaddr, address);
+ if (boffset)
+ return boffset;
+ }
+ /* Not found. */
+ return -1;
+ }
+
+ /* Baseclass is easily computed. */
+ return 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;
+{
+ ULONGEST val;
+ ULONGEST valmask;
+ int bitpos = TYPE_FIELD_BITPOS (type, fieldno);
+ int bitsize = TYPE_FIELD_BITSIZE (type, fieldno);
+ int lsbcount;
+ struct type *field_type;
+
+ val = extract_unsigned_integer (valaddr + bitpos / 8, sizeof (val));
+ field_type = TYPE_FIELD_TYPE (type, fieldno);
+ CHECK_TYPEDEF (field_type);
+
+ /* Extract bits. See comment above. */
+
+ if (BITS_BIG_ENDIAN)
+ lsbcount = (sizeof val * 8 - bitpos % 8 - bitsize);
+ else
+ lsbcount = (bitpos % 8);
+ 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 * (int) sizeof (val)))
+ {
+ valmask = (((ULONGEST) 1) << bitsize) - 1;
+ val &= valmask;
+ if (!TYPE_UNSIGNED (field_type))
+ {
+ 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;
+
+ /* If a negative fieldval fits in the field in question, chop
+ off the sign extension bits. */
+ if (bitsize < (8 * (int) sizeof (fieldval))
+ && (~fieldval & ~((1 << (bitsize - 1)) - 1)) == 0)
+ fieldval = fieldval & ((1 << bitsize) - 1);
+
+ /* Warn if value is too big to fit in the field in question. */
+ if (bitsize < (8 * (int) sizeof (fieldval))
+ && 0 != (fieldval & ~((1<<bitsize)-1)))
+ {
+ /* FIXME: would like to include fieldval in the message, but
+ we don't have a sprintf_longest. */
+ warning ("Value does not fit in %d bits.", bitsize);
+
+ /* Truncate it, otherwise adjoining fields may be corrupted. */
+ fieldval = fieldval & ((1 << bitsize) - 1);
+ }
+
+ 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;
+
+ /* Mask out old value, while avoiding shifts >= size of oword */
+ if (bitsize < 8 * (int) sizeof (oword))
+ oword &= ~(((((ULONGEST)1) << bitsize) - 1) << bitpos);
+ else
+ oword &= ~((~(ULONGEST)0) << bitpos);
+ oword |= fieldval << bitpos;
+
+ store_signed_integer (addr, sizeof oword, oword);
+}
+
+/* Convert C numbers into newly allocated values */
+
+value_ptr
+value_from_longest (type, num)
+ struct type *type;
+ register LONGEST num;
+{
+ register value_ptr val = allocate_value (type);
+ register enum type_code code;
+ register int len;
+ retry:
+ code = TYPE_CODE (type);
+ len = TYPE_LENGTH (type);
+
+ switch (code)
+ {
+ case TYPE_CODE_TYPEDEF:
+ type = check_typedef (type);
+ goto retry;
+ case TYPE_CODE_INT:
+ case TYPE_CODE_CHAR:
+ case TYPE_CODE_ENUM:
+ case TYPE_CODE_BOOL:
+ case TYPE_CODE_RANGE:
+ 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 (%d) encountered for integer constant.", code);
+ }
+ return val;
+}
+
+value_ptr
+value_from_double (type, num)
+ struct type *type;
+ DOUBLEST num;
+{
+ register value_ptr val = allocate_value (type);
+ struct type *base_type = check_typedef (type);
+ register enum type_code code = TYPE_CODE (base_type);
+ register int len = TYPE_LENGTH (base_type);
+
+ if (code == TYPE_CODE_FLT)
+ {
+ store_floating (VALUE_CONTENTS_RAW (val), len, num);
+ }
+ 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_ptr
+value_being_returned (valtype, retbuf, struct_return)
+ register struct type *valtype;
+ char retbuf[REGISTER_BYTES];
+ int struct_return;
+ /*ARGSUSED*/
+{
+ register value_ptr 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, NULL);
+ }
+#endif
+
+ val = allocate_value (valtype);
+ CHECK_TYPEDEF (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. */
+
+int
+generic_use_struct_convention (gcc_p, value_type)
+ int gcc_p;
+ struct type *value_type;
+{
+ return !((gcc_p == 1)
+ && (TYPE_LENGTH (value_type) == 1
+ || TYPE_LENGTH (value_type) == 2
+ || TYPE_LENGTH (value_type) == 4
+ || TYPE_LENGTH (value_type) == 8));
+}
+
+#ifndef USE_STRUCT_CONVENTION
+#define USE_STRUCT_CONVENTION(gcc_p,type) generic_use_struct_convention (gcc_p, type)
+#endif
+
+/* Some fundamental types (such as long double) are returned on the stack for
+ certain architectures. This macro should return true for any type besides
+ struct, union or array that gets returned on the stack. */
+
+#ifndef RETURN_VALUE_ON_STACK
+#define RETURN_VALUE_ON_STACK(TYPE) 0
+#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_ptr 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_VALUE_ON_STACK (value_type))
+ 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_ptr val;
+{
+ struct type *type = check_typedef (VALUE_TYPE (val));
+ register enum type_code code = TYPE_CODE (type);
+
+ 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.");
+
+ STORE_RETURN_VALUE (type, VALUE_CONTENTS (val));
+}
+
+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/gdb/vax-tdep.c b/gdb/vax-tdep.c
new file mode 100644
index 00000000000..b378571ec56
--- /dev/null
+++ b/gdb/vax-tdep.c
@@ -0,0 +1,263 @@
+/* Print VAX instructions for GDB, the GNU debugger.
+ Copyright 1986, 1989, 1991, 1992, 1996 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "symtab.h"
+#include "opcode/vax.h"
+
+/* Vax instructions are never longer than this. */
+#define MAXLEN 62
+
+/* Number of elements in the opcode table. */
+#define NOPCODES (sizeof votstrs / sizeof votstrs[0])
+
+static unsigned char *print_insn_arg ();
+
+/* Print the vax instruction at address MEMADDR in debugged memory,
+ from disassembler info INFO.
+ Returns length of the instruction, in bytes. */
+
+static int
+vax_print_insn (memaddr, info)
+ CORE_ADDR memaddr;
+ disassemble_info *info;
+{
+ unsigned char buffer[MAXLEN];
+ register int i;
+ register unsigned char *p;
+ register char *d;
+
+ int status = (*info->read_memory_func) (memaddr, buffer, MAXLEN, info);
+ if (status != 0)
+ {
+ (*info->memory_error_func) (status, memaddr, info);
+ return -1;
+ }
+
+ for (i = 0; i < NOPCODES; i++)
+ if (votstrs[i].detail.code == buffer[0]
+ || votstrs[i].detail.code == *(unsigned short *)buffer)
+ break;
+
+ /* Handle undefined instructions. */
+ if (i == NOPCODES)
+ {
+ (*info->fprintf_func) (info->stream, "0%o", buffer[0]);
+ return 1;
+ }
+
+ (*info->fprintf_func) (info->stream, "%s", votstrs[i].name);
+
+ /* Point at first byte of argument data,
+ and at descriptor for first argument. */
+ p = buffer + 1 + (votstrs[i].detail.code >= 0x100);
+ d = votstrs[i].detail.args;
+
+ if (*d)
+ (*info->fprintf_func) (info->stream, " ");
+
+ while (*d)
+ {
+ p = print_insn_arg (d, p, memaddr + (p - buffer), info);
+ d += 2;
+ if (*d)
+ (*info->fprintf_func) (info->stream, ",");
+ }
+ return p - buffer;
+}
+
+static unsigned char *
+print_insn_arg (d, p, addr, info)
+ char *d;
+ register char *p;
+ CORE_ADDR addr;
+ disassemble_info *info;
+{
+ register int regnum = *p & 0xf;
+ float floatlitbuf;
+
+ if (*d == 'b')
+ {
+ if (d[1] == 'b')
+ (*info->fprintf_func) (info->stream, "0x%x", addr + *p++ + 1);
+ else
+ {
+ (*info->fprintf_func) (info->stream, "0x%x", addr + *(short *)p + 2);
+ p += 2;
+ }
+ }
+ else
+ switch ((*p++ >> 4) & 0xf)
+ {
+ case 0:
+ case 1:
+ case 2:
+ case 3: /* Literal mode */
+ if (d[1] == 'd' || d[1] == 'f' || d[1] == 'g' || d[1] == 'h')
+ {
+ *(int *)&floatlitbuf = 0x4000 + ((p[-1] & 0x3f) << 4);
+ (*info->fprintf_func) (info->stream, "$%f", floatlitbuf);
+ }
+ else
+ (*info->fprintf_func) (info->stream, "$%d", p[-1] & 0x3f);
+ break;
+
+ case 4: /* Indexed */
+ p = (char *) print_insn_arg (d, p, addr + 1, info);
+ (*info->fprintf_func) (info->stream, "[%s]", REGISTER_NAME (regnum));
+ break;
+
+ case 5: /* Register */
+ (*info->fprintf_func) (info->stream, REGISTER_NAME (regnum));
+ break;
+
+ case 7: /* Autodecrement */
+ (*info->fprintf_func) (info->stream, "-");
+ case 6: /* Register deferred */
+ (*info->fprintf_func) (info->stream, "(%s)", REGISTER_NAME (regnum));
+ break;
+
+ case 9: /* Autoincrement deferred */
+ (*info->fprintf_func) (info->stream, "@");
+ if (regnum == PC_REGNUM)
+ {
+ (*info->fprintf_func) (info->stream, "#");
+ info->target = *(long *)p;
+ (*info->print_address_func) (info->target, info);
+ p += 4;
+ break;
+ }
+ case 8: /* Autoincrement */
+ if (regnum == PC_REGNUM)
+ {
+ (*info->fprintf_func) (info->stream, "#");
+ switch (d[1])
+ {
+ case 'b':
+ (*info->fprintf_func) (info->stream, "%d", *p++);
+ break;
+
+ case 'w':
+ (*info->fprintf_func) (info->stream, "%d", *(short *)p);
+ p += 2;
+ break;
+
+ case 'l':
+ (*info->fprintf_func) (info->stream, "%d", *(long *)p);
+ p += 4;
+ break;
+
+ case 'q':
+ (*info->fprintf_func) (info->stream, "0x%x%08x",
+ ((long *)p)[1], ((long *)p)[0]);
+ p += 8;
+ break;
+
+ case 'o':
+ (*info->fprintf_func) (info->stream, "0x%x%08x%08x%08x",
+ ((long *)p)[3], ((long *)p)[2],
+ ((long *)p)[1], ((long *)p)[0]);
+ p += 16;
+ break;
+
+ case 'f':
+ if (INVALID_FLOAT (p, 4))
+ (*info->fprintf_func) (info->stream,
+ "<<invalid float 0x%x>>",
+ *(int *) p);
+ else
+ (*info->fprintf_func) (info->stream, "%f", *(float *) p);
+ p += 4;
+ break;
+
+ case 'd':
+ if (INVALID_FLOAT (p, 8))
+ (*info->fprintf_func) (info->stream,
+ "<<invalid float 0x%x%08x>>",
+ ((long *)p)[1], ((long *)p)[0]);
+ else
+ (*info->fprintf_func) (info->stream, "%f", *(double *) p);
+ p += 8;
+ break;
+
+ case 'g':
+ (*info->fprintf_func) (info->stream, "g-float");
+ p += 8;
+ break;
+
+ case 'h':
+ (*info->fprintf_func) (info->stream, "h-float");
+ p += 16;
+ break;
+
+ }
+ }
+ else
+ (*info->fprintf_func) (info->stream, "(%s)+", REGISTER_NAME (regnum));
+ break;
+
+ case 11: /* Byte displacement deferred */
+ (*info->fprintf_func) (info->stream, "@");
+ case 10: /* Byte displacement */
+ if (regnum == PC_REGNUM)
+ {
+ info->target = addr + *p + 2;
+ (*info->print_address_func) (info->target, info);
+ }
+ else
+ (*info->fprintf_func) (info->stream, "%d(%s)", *p, REGISTER_NAME (regnum));
+ p += 1;
+ break;
+
+ case 13: /* Word displacement deferred */
+ (*info->fprintf_func) (info->stream, "@");
+ case 12: /* Word displacement */
+ if (regnum == PC_REGNUM)
+ {
+ info->target = addr + *(short *)p + 3;
+ (*info->print_address_func) (info->target, info);
+ }
+ else
+ (*info->fprintf_func) (info->stream, "%d(%s)",
+ *(short *)p, REGISTER_NAME (regnum));
+ p += 2;
+ break;
+
+ case 15: /* Long displacement deferred */
+ (*info->fprintf_func) (info->stream, "@");
+ case 14: /* Long displacement */
+ if (regnum == PC_REGNUM)
+ {
+ info->target = addr + *(short *)p + 5;
+ (*info->print_address_func) (info->target, info);
+ }
+ else
+ (*info->fprintf_func) (info->stream, "%d(%s)",
+ *(long *)p, REGISTER_NAME (regnum));
+ p += 4;
+ }
+
+ return (unsigned char *) p;
+}
+
+void
+_initialize_vax_tdep ()
+{
+ tm_print_insn = vax_print_insn;
+}
diff --git a/gdb/vx-share/README b/gdb/vx-share/README
new file mode 100644
index 00000000000..924b668585e
--- /dev/null
+++ b/gdb/vx-share/README
@@ -0,0 +1,7 @@
+The files in this directory are shared with Wind River Systems' VxWorks
+debug stub. This stub runs in the realtime system, as a process, and
+waits for net connections from GDB's and DBX's and such.
+
+Do not change these files without coordinating with Wind River Systems
+in Alameda, California. Talk to postmaster@wrs.com to find out who
+currently maintains GDB for them.
diff --git a/gdb/vx-share/dbgRpcLib.h b/gdb/vx-share/dbgRpcLib.h
new file mode 100644
index 00000000000..e858e558e43
--- /dev/null
+++ b/gdb/vx-share/dbgRpcLib.h
@@ -0,0 +1,32 @@
+/* Copyright 1992 Free Software Foundation, Inc.
+
+ This code was donated by Wind River Systems, Inc.
+
+ dbgRpcLib.h - header file for remote debugging via rpc */
+
+/*
+modification history
+--------------------
+01b,04oct90,maf added VX_BOOT_FILE_INQ.
+01a,05jun90,llk extracted from xdr_dbx.h.
+*/
+
+#ifndef INCdbxRpcLibh
+#define INCdbxRpcLibh 1
+
+#define PROCESS_START 50
+#define PROCESS_WAIT 51
+#define VX_STATE_INQ 60
+#define VX_LOAD 61
+#define VX_SYMBOL_INQ 62
+#define VX_BREAK_ADD 63
+#define VX_BREAK_DELETE 64
+#define VX_FP_INQUIRE 65
+#define VX_TASK_SUSPEND 66
+#define VX_CALL_FUNC 67
+#define VX_CONV_FROM_68881 68
+#define VX_CONV_TO_68881 69
+#define VX_BOOT_FILE_INQ 70
+#define VX_SOURCE_STEP 71
+
+#endif INCdbxRpcLibh
diff --git a/gdb/vx-share/ptrace.h b/gdb/vx-share/ptrace.h
new file mode 100644
index 00000000000..8e3554f13a0
--- /dev/null
+++ b/gdb/vx-share/ptrace.h
@@ -0,0 +1,44 @@
+/* @(#)ptrace.h 1.1 86/07/07 SMI */
+
+/*
+ * Copyright (c) 1985 by Sun Microsystems, Inc.
+ */
+
+/*
+modification history
+--------------------
+01a,05jun90,llk borrowed.
+*/
+
+#ifndef _PTRACE_
+#define _PTRACE_
+
+/*
+ * Request values for the ptrace system call
+ */
+enum ptracereq {
+ PTRACE_TRACEME = 0, /* 0, by tracee to begin tracing */
+ PTRACE_CHILDDONE = 0, /* 0, tracee is done with his half */
+ PTRACE_PEEKTEXT, /* 1, read word from text segment */
+ PTRACE_PEEKDATA, /* 2, read word from data segment */
+ PTRACE_PEEKUSER, /* 3, read word from user struct */
+ PTRACE_POKETEXT, /* 4, write word into text segment */
+ PTRACE_POKEDATA, /* 5, write word into data segment */
+ PTRACE_POKEUSER, /* 6, write word into user struct */
+ PTRACE_CONT, /* 7, continue process */
+ PTRACE_KILL, /* 8, terminate process */
+ PTRACE_SINGLESTEP, /* 9, single step process */
+ PTRACE_ATTACH, /* 10, attach to an existing process */
+ PTRACE_DETACH, /* 11, detach from a process */
+ PTRACE_GETREGS, /* 12, get all registers */
+ PTRACE_SETREGS, /* 13, set all registers */
+ PTRACE_GETFPREGS, /* 14, get all floating point regs */
+ PTRACE_SETFPREGS, /* 15, set all floating point regs */
+ PTRACE_READDATA, /* 16, read data segment */
+ PTRACE_WRITEDATA, /* 17, write data segment */
+ PTRACE_READTEXT, /* 18, read text segment */
+ PTRACE_WRITETEXT, /* 19, write text segment */
+ PTRACE_GETFPAREGS, /* 20, get all fpa regs */
+ PTRACE_SETFPAREGS /* 21, set all fpa regs */
+};
+#endif !_PTRACE
diff --git a/gdb/vx-share/regPacket.h b/gdb/vx-share/regPacket.h
new file mode 100644
index 00000000000..6160c846862
--- /dev/null
+++ b/gdb/vx-share/regPacket.h
@@ -0,0 +1,160 @@
+/* regPacket.h - register packet definitions for rdb */
+
+/* Copyright 1992-1993 Wind River Systems, Inc. */
+
+/*
+modification history
+--------------------
+01d,30nov93,pad Added Am29K target definitions.
+01c,14jun93,maf additional definitions for documentation purposes.
+ fixed reversal of MIPS_R_LO and MIPS_R_HI.
+01b,08feb93,scy added SPARC target definitions. changed to WRS code convetion.
+01a,20feb92,j_w created.
+*/
+
+#ifndef __INCregPacketh
+#define __INCregPacketh
+
+
+/* MC68K */
+
+#define MC68K_GREG_SIZE 0x04 /* size of general-purpose reg */
+#define MC68K_GREG_PLEN 0x48 /* size of general-purpose reg block */
+
+/* offsets into general-purpose register block */
+
+#define MC68K_R_D0 0x00 /* d0; d1 - d7 follow in sequence */
+#define MC68K_R_A0 0x20 /* a0; a1 - a7 follow in sequence */
+#define MC68K_R_SR 0x40 /* sr (represented as a 4-byte val) */
+#define MC68K_R_PC 0x44 /* pc */
+
+#define MC68K_FPREG_SIZE 0x0c /* size of floating-point data reg */
+#define MC68K_FPREG_PLEN 0x6c /* size of floating-point reg block */
+
+/* offsets into floating-point register block */
+
+#define MC68K_R_FP0 0x00 /* fp0; fp1 - fp7 follow in sequence */
+#define MC68K_R_FPCR 0x60 /* fpcr */
+#define MC68K_R_FPSR 0x64 /* fpsr */
+#define MC68K_R_FPIAR 0x68 /* fpiar */
+
+
+/* I960 */
+
+#define I960_GREG_SIZE 0x04 /* size of general-purpose reg */
+#define I960_GREG_PLEN 0x8c /* size of general-purpose reg block */
+
+/* offsets into general-purpose register block */
+
+#define I960_R_R0 0x00 /* r0; r1 - r15 follow in sequence */
+#define I960_R_G0 0x40 /* g0; g1 - g15 follow in sequence */
+#define I960_R_PCW 0x80 /* pcw */
+#define I960_R_ACW 0x84 /* acw */
+#define I960_R_TCW 0x88 /* tcw */
+
+#define I960_FPREG_SIZE 0x10 /* size of floating-point reg */
+#define I960_FPREG_PLEN 0x28 /* size of floating-point reg block */
+
+/* offsets into floating-point register block */
+
+#define I960_R_FP0 0x00 /* fp0; fp1 - fp3 follow in sequence */
+
+
+/* SPARC */
+
+#define SPARC_GREG_SIZE 0x04 /* size of general-purpose reg */
+#define SPARC_GREG_PLEN 0x98 /* size of general-purpose reg block */
+
+/* offsets into general-purpose register block */
+
+#define SPARC_R_G0 0x00 /* g0; g1 - g7 follow in sequence */
+#define SPARC_R_O0 0x20 /* o0; o1 - o7 follow in sequence */
+#define SPARC_R_L0 0x40 /* l0; l1 - l7 follow in sequence */
+#define SPARC_R_I0 0x60 /* i0; i1 - i7 follow in sequence */
+#define SPARC_R_Y 0x80 /* y */
+#define SPARC_R_PSR 0x84 /* psr */
+#define SPARC_R_WIM 0x88 /* wim */
+#define SPARC_R_TBR 0x8c /* tbr */
+#define SPARC_R_PC 0x90 /* pc */
+#define SPARC_R_NPC 0x94 /* npc */
+
+#define SPARC_FPREG_SIZE 0x04 /* size of floating-point reg */
+#define SPARC_FPREG_PLEN 0x84 /* size of floating-point reg block */
+
+/* offsets into floating-point register block */
+
+#define SPARC_R_FP0 0x00 /* f0; f1 - f31 follow in sequence */
+#define SPARC_R_FSR 0x80 /* fsr */
+
+
+/* MIPS */
+
+#define MIPS_GREG_SIZE 0x04 /* size of general-purpose reg */
+#define MIPS_GREG_PLEN 0x90 /* size of general-purpose reg block */
+
+/* offsets into general-purpose register block */
+
+#define MIPS_R_GP0 0x00 /* gp0 (zero) */
+#define MIPS_R_AT 0x04 /* at */
+#define MIPS_R_V0 0x08 /* v0 */
+#define MIPS_R_V1 0x0c /* v1 */
+#define MIPS_R_A0 0x10 /* a0 */
+#define MIPS_R_A1 0x14 /* a1 */
+#define MIPS_R_A2 0x18 /* a2 */
+#define MIPS_R_A3 0x1c /* a3 */
+#define MIPS_R_T0 0x20 /* t0 */
+#define MIPS_R_T1 0x24 /* t1 */
+#define MIPS_R_T2 0x28 /* t2 */
+#define MIPS_R_T3 0x2c /* t3 */
+#define MIPS_R_T4 0x30 /* t4 */
+#define MIPS_R_T5 0x34 /* t5 */
+#define MIPS_R_T6 0x38 /* t6 */
+#define MIPS_R_T7 0x3c /* t7 */
+#define MIPS_R_S0 0x40 /* s0 */
+#define MIPS_R_S1 0x44 /* s1 */
+#define MIPS_R_S2 0x48 /* s2 */
+#define MIPS_R_S3 0x4c /* s3 */
+#define MIPS_R_S4 0x50 /* s4 */
+#define MIPS_R_S5 0x54 /* s5 */
+#define MIPS_R_S6 0x58 /* s6 */
+#define MIPS_R_S7 0x5c /* s7 */
+#define MIPS_R_T8 0x60 /* t8 */
+#define MIPS_R_T9 0x64 /* t9 */
+#define MIPS_R_K0 0x68 /* k0 */
+#define MIPS_R_K1 0x6c /* k1 */
+#define MIPS_R_GP 0x70 /* gp */
+#define MIPS_R_SP 0x74 /* sp */
+#define MIPS_R_S8 0x78 /* s8 */
+#define MIPS_R_LO 0x80 /* lo */
+#define MIPS_R_HI 0x84 /* hi */
+#define MIPS_R_SR 0x88 /* sr */
+#define MIPS_R_PC 0x8c /* pc */
+
+#define MIPS_FPREG_SIZE 0x04 /* size of floating-point data reg */
+#define MIPS_FPREG_PLEN 0x84 /* size of floating-point reg block */
+
+/* offsets into floating-point register block */
+
+#define MIPS_R_FP0 0x00 /* f0; f1 - f31 follow in sequence */
+#define MIPS_R_FPCSR 0x80 /* offset of fpcsr in reg block */
+
+
+/* General registers for the Am29k */
+
+#define AM29K_GREG_SIZE 0x04
+#define AM29K_GREG_PLEN 0x2d4
+
+#define AM29K_R_GR96 0x0
+#define AM29K_R_VAB 0x280
+#define AM29K_R_INTE 0x2bc
+#define AM29K_R_RSP 0x2c0
+
+/* Floating Point registers for the Am29k */
+
+#define AM29K_FPREG_SIZE 0x04
+#define AM29K_FPREG_PLEN 0x8
+
+#define AM29K_R_FPE 0x0
+#define AM29K_R_FPS 0x4
+
+#endif /* __INCregPacketh */
diff --git a/gdb/vx-share/vxTypes.h b/gdb/vx-share/vxTypes.h
new file mode 100644
index 00000000000..c6b84192233
--- /dev/null
+++ b/gdb/vx-share/vxTypes.h
@@ -0,0 +1,72 @@
+/* vxTypes.h - VxWorks type definition header */
+
+/* Copyright 1984, 1985, 1986, 1987, 1988, 1989, 1990, 1992 Free Software Foundation, Inc.
+
+ This code was donated by Wind River Systems, Inc. */
+
+/*
+modification history
+--------------------
+01c,05oct90,shl added copyright notice.
+ made #endif ANSI style.
+01b,10aug90,dnw added VOIDFUNCPTR
+01a,29may90,del written.
+*/
+
+#ifndef INCvxTypesh
+#define INCvxTypesh
+
+/* The following stuff must NOT be included if this include file is used
+ * from assembly language. Just #define ASMLANGUAGE before the include,
+ * to get rid of it.
+ */
+
+#ifndef ASMLANGUAGE
+
+/* vxWorks types */
+
+typedef char INT8;
+typedef short INT16;
+typedef int INT32;
+
+typedef unsigned char UINT8;
+typedef unsigned short UINT16;
+typedef unsigned int UINT32;
+
+typedef unsigned char UCHAR;
+typedef unsigned short USHORT;
+typedef unsigned int UINT;
+typedef unsigned long ULONG;
+
+typedef int BOOL;
+typedef int VOID;
+typedef int STATUS;
+typedef int ARGINT;
+
+typedef int (*FUNCPTR) (); /* ptr to function returning int */
+typedef VOID (*VOIDFUNCPTR) (); /* ptr to function returning VOID */
+
+
+/* historical definitions - now obsolete */
+
+typedef char TINY; /* obsolete */
+typedef char TBOOL; /* obsolete */
+typedef unsigned char UTINY; /* obsolete */
+
+
+/* architecture dependent typedefs */
+
+#ifdef CPU_FAMILY
+
+#if CPU_FAMILY==MC680X0
+typedef unsigned short INSTR; /* word-aligned instructions */
+#endif /* CPU_FAMILY==MC680X0 */
+
+#if CPU_FAMILY==SPARC
+typedef unsigned long INSTR; /* 32 bit word-aligned instructions */
+#endif /* CPU_FAMILY==SPARC */
+
+#endif
+
+#endif /* ASMLANGUAGE */
+#endif /* INCvxTypesh */
diff --git a/gdb/vx-share/vxWorks.h b/gdb/vx-share/vxWorks.h
new file mode 100644
index 00000000000..159883750f1
--- /dev/null
+++ b/gdb/vx-share/vxWorks.h
@@ -0,0 +1,171 @@
+/* vxWorks.h - VxWorks standard definitions header */
+
+/* Copyright 1984, 1985, 1986, 1987, 1988, 1989, 1990, 1992 Free Software Foundation, Inc.
+
+ This code was donated by Wind River Systems, Inc. */
+
+/*
+modification history
+--------------------
+01z,05oct90,shl added copyright notice.
+ made #endif ANSI style.
+01y,28sep90,del added I960 defines.
+01x,29may90,del moved types to vxTypes.h
+01w,09apr90,jcf added timeout definitions.
+01v,24jan90,gae moved network configuration flags here from makefile's.
+01u,01sep88,mcl definition of INSTR dependent on processor family; added SPARC.
+ +gae added MC680X0 and defined CPU_FAMILY.
+01t,08apr89,dnw added ifdef to prevent inclusion of vxWorks.h more than once.
+01s,22jun88,dnw moved READ, WRITE, and UPDATE back here from ioLib.h.
+01r,22apr88,gae oops! forgot some #endif's in 01q.
+01q,12apr88,gae removed QUICK & WAIT; added STD_{IN,OUT,ERR}.
+ fixed #define's of FALSE, TRUE, etc.
+ moved READ, WRITE, and UPDATE to ioLib.h.
+01p,04dec87,dnw added undefine of MC68000 to get around Green Hills bug that
+ pre-defines MC68000.
+01o,12nov87,ecs added type ULONG.
+01n,08feb86,dnw added types INSTR, UINT, USHORT.
+01m,14oct85,rdc added BUS types.
+01l,16jul85,jlf added conditional for NULL and EOF.
+01k,24jun85,rdc installed condtional compile so we can include in
+ assembly language files. See instructions below.
+ Added System type macro and CPU type macro.
+01j,13jun85,dnw cleaned-up, removed more obsolete stuff to wrs.h
+01i,11sep84,jlf changed name from wrs.h to vxWorks.h. removed GLOBAL.
+01h,03jun84,dnw removed IGNORE declaration.
+01g,09apr84,jlf added MEMBER_SIZE macro.
+01f,14dec83,dnw added MSB, LSB macros
+01e,17nov83,jlf added STATUS type, for routines which return a status.
+01d,13jul83,dnw added NELEMENTS macro
+01c,14May83,dnw added OFFSET macro
+01b,17Feb83,dnw added stuff from Whitesmiths std.h
+01a,15Feb83,dnw written
+*/
+
+#ifndef INCvxWorksh
+#define INCvxWorksh
+
+#if !defined(EOF) || (EOF!=(-1))
+#define EOF (-1)
+#endif
+
+#if !defined(FALSE) || (FALSE!=0)
+#define FALSE 0
+#endif
+
+#if !defined(TRUE) || (TRUE!=1)
+#define TRUE 1
+#endif
+
+
+#define NONE (-1) /* for times when NULL won't do */
+#define EOS '\0' /* C string terminator */
+
+
+/* return status values */
+
+#define OK 0
+#define ERROR (-1)
+
+/* timeout defines */
+
+#define NO_WAIT 0
+#define WAIT_FOREVER (-1)
+
+/* low-level I/O input, output, error fd's */
+
+#define STD_IN 0
+#define STD_OUT 1
+#define STD_ERR 2
+
+/* modes - must match O_RDONLY/O_WRONLY/O_RDWR in ioLib.h! */
+
+#define READ 0
+#define WRITE 1
+#define UPDATE 2
+
+/* SYSTEM types */
+
+#define V7 1 /* ATT version 7 */
+#define SYS_V 2 /* ATT System 5 */
+#define BSD_4_2 3 /* Berkeley BSD 4.2 */
+
+/* CPU types */
+
+/* The Green Hills compiler pre-defines "MC68000"!! */
+#ifdef MC68000
+#undef MC68000
+#endif
+
+#define MC68000 1
+#define MC68010 2
+#define MC68020 3
+#define MC68030 4
+#define MC68040 5
+#define MC680X0 9
+
+#define SPARC 10
+
+#ifndef I960
+#define I960 20
+#endif
+
+#define I960KB 21
+#define I960CA 22
+
+#if CPU==MC68000 || CPU==MC68010 || CPU==MC68020 || CPU==MC68030
+#define CPU_FAMILY MC680X0
+#endif /* CPU==MC68000 || CPU==MC68010 || CPU==MC68020 || CPU==MC68030 */
+
+#if CPU==SPARC
+#define CPU_FAMILY SPARC
+#endif /* CPU==SPARC */
+
+#if CPU==I960KB
+#define CPU_FAMILY I960
+#endif /* CPU==I960KB */
+
+#if CPU==I960CA
+#define CPU_FAMILY I960
+#endif /* CPU==I960CA */
+
+/* BUS types */
+
+#define VME_BUS 1
+#define MULTI_BUS 2
+
+/* network configuration parameters */
+
+#define INET /* include internet protocols */
+#define BSD 43 /* BSD 4.3 -like OS */
+#define BSDDEBUG /* turn on debug */
+#define GATEWAY /* tables to be initialized for gateway routing */
+
+/* common macros */
+
+#define MSB(x) (((x) >> 8) & 0xff) /* most signif byte of 2-byte integer */
+#define LSB(x) ((x) & 0xff) /* least signif byte of 2-byte integer*/
+
+#define OFFSET(structure, member) /* byte offset of member in structure*/\
+ ((int) &(((structure *) 0) -> member))
+
+#define MEMBER_SIZE(structure, member) /* size of a member of a structure */\
+ (sizeof (((structure *) 0) -> member))
+
+#define NELEMENTS(array) /* number of elements in an array */ \
+ (sizeof (array) / sizeof ((array) [0]))
+
+#define FOREVER for (;;)
+
+/* storage class specifier definitions */
+
+#define FAST register
+#define IMPORT extern
+#define LOCAL static
+
+
+/* include typedefs - must come after CPU_FAMILY definitions above */
+
+#include "vxTypes.h"
+
+#endif /* INCvxWorksh */
diff --git a/gdb/vx-share/wait.h b/gdb/vx-share/wait.h
new file mode 100644
index 00000000000..cb8d1b5bbaa
--- /dev/null
+++ b/gdb/vx-share/wait.h
@@ -0,0 +1,46 @@
+/* wait.h - header file for remote wait call */
+
+/* Copyright 1992 Free Software Foundation, Inc.
+
+ This code was donated by Wind River Systems, Inc. */
+
+/*
+modification history
+--------------------
+01a,05jun90,llk borrowed.
+*/
+
+/* Define how to access the structure that the wait system call stores.
+ On many systems, there is a structure defined for this.
+ But on vanilla-ish USG systems there is not. */
+
+#ifndef HAVE_WAIT_STRUCT
+#define WAITTYPE int
+#define WIFSTOPPED(w) (((w)&0377) == 0177)
+#define WIFSIGNALED(w) (((w)&0377) != 0177 && ((w)&~0377) == 0)
+#define WIFEXITED(w) (((w)&0377) == 0)
+#define WRETCODE(w) ((w) >> 8)
+#define WSTOPSIG(w) ((w) >> 8)
+#define WCOREDUMP(w) (((w)&0200) != 0)
+#define WTERMSIG(w) ((w) & 0177)
+#define WSETEXIT(w, status) ((w) = (status))
+#define WSETSTOP(w,sig) ((w) = (0177 | ((sig) << 8)))
+#else
+#if FALSE
+#ifndef ORIG
+
+/* don't include sys/wait.h */
+
+#else ORIG
+#include <sys/wait.h>
+#endif ORIG
+#endif FALSE
+#define WAITTYPE union wait
+#define WRETCODE(w) (w).w_retcode
+#define WSTOPSIG(w) (w).w_stopsig
+#define WCOREDUMP(w) (w).w_coredump
+#define WTERMSIG(w) (w).w_termsig
+#define WSETEXIT(w, status) ((w).w_status = (status))
+#define WSETSTOP(w,sig) \
+ ((w).w_stopsig = (sig), (w).w_coredump = 0, (w).w_termsig = 0177)
+#endif
diff --git a/gdb/vx-share/xdr_ld.c b/gdb/vx-share/xdr_ld.c
new file mode 100644
index 00000000000..3678c3501b8
--- /dev/null
+++ b/gdb/vx-share/xdr_ld.c
@@ -0,0 +1,84 @@
+/* xdr_ld.c - xdr routines for remote dbx interface to VxWorks */
+
+/* Copyright 1984, 1985, 1986, 1987, 1988, 1989, 1992 Free Software Foundation, Inc.
+
+ This code was donated by Wind River Systems, Inc. */
+
+/*
+modification history
+--------------------
+01a,05jun90,llk extracted from xdr_dbx.c.
+*/
+
+/*
+DESCRIPTION
+This module contains the eXternal Data Representation (XDR) routines
+for object files that are downloaded to VxWorks. They are used by
+remote debuggers that use RPC (such as dbxWorks and vxGdb).
+*/
+
+#include "defs.h"
+#include "vxWorks.h"
+#include "rpc/rpc.h"
+#include "xdr_ld.h"
+
+/* forward declarations */
+
+bool_t xdr_String(); /* xdr routine for argument list */
+
+
+/*******************************************************************************
+*
+* xdr_String - xdr routine for strings.
+*
+* Used by xdr_arg_info to handle the actual argument
+* strings. normally calls xdr_string - but does something
+* reasonable encode of null pointer.
+*/
+
+bool_t xdr_String (xdrs, strp)
+ XDR *xdrs;
+ char **strp;
+
+ {
+ if ((*strp == NULL) & (xdrs->x_op == XDR_ENCODE))
+ return(FALSE);
+ else
+ return(xdr_string(xdrs, strp, MAXSTRLEN));
+ }
+/*******************************************************************************
+*
+* xdr_ldfile - xdr routine for a single element in the load table
+*/
+
+bool_t xdr_ldfile (xdrs, objp)
+ XDR *xdrs;
+ ldfile *objp;
+
+ {
+ if (! xdr_String(xdrs, &objp->name))
+ return(FALSE);
+ if (! xdr_int(xdrs, &objp->txt_addr))
+ return(FALSE);
+ if (! xdr_int(xdrs, &objp->data_addr))
+ return(FALSE);
+ if (! xdr_int(xdrs, &objp->bss_addr))
+ return(FALSE);
+
+ return(TRUE);
+ }
+/*******************************************************************************
+*
+* xdr_ldtabl -
+*
+* xdr routine for a list of files and load addresses loaded into VxWorks.
+*/
+
+bool_t xdr_ldtabl (xdrs,objp)
+ XDR *xdrs;
+ ldtabl *objp;
+
+ {
+ return (xdr_array (xdrs, (char **) &objp->tbl_ent, (UINT *) &objp->tbl_size,
+ MAXTBLSZ, sizeof(ldfile), xdr_ldfile));
+ }
diff --git a/gdb/vx-share/xdr_ld.h b/gdb/vx-share/xdr_ld.h
new file mode 100644
index 00000000000..2899c0ef78f
--- /dev/null
+++ b/gdb/vx-share/xdr_ld.h
@@ -0,0 +1,45 @@
+/* xdr_ld.h - xdr for additional dbxWorks structures */
+
+/* Copyright 1992 Free Software Foundation, Inc.
+
+ This code was donated by Wind River Systems, Inc. */
+
+/*
+modification history
+--------------------
+01a,05jun90,llk extracted from xdr_dbx.h.
+*/
+
+#ifndef INCxdrldh
+#define INCxdrldh
+
+#define MAXSTRLEN 256
+#define MAXTBLSZ 100
+
+/*
+ * structure used to pass back the information for a single file
+ * loaded in VxWorks
+ */
+struct ldfile {
+ char *name;
+ int txt_addr;
+ int data_addr;
+ int bss_addr;
+};
+typedef struct ldfile ldfile;
+
+/*
+ * structure used to return a list of all files loaded over to
+ * VxWorks. (VX_STATE_INQ return)
+ */
+struct ldtabl {
+ u_int tbl_size;
+ ldfile *tbl_ent;
+};
+typedef struct ldtabl ldtabl;
+
+
+bool_t xdr_ldfile();
+bool_t xdr_ldtabl();
+
+#endif INCxdrldh
diff --git a/gdb/vx-share/xdr_ptrace.c b/gdb/vx-share/xdr_ptrace.c
new file mode 100644
index 00000000000..fff43246218
--- /dev/null
+++ b/gdb/vx-share/xdr_ptrace.c
@@ -0,0 +1,118 @@
+/* xdr_ptrace.c - xdr routines for remote ptrace calls */
+
+/* Copyright 1984, 1985, 1986, 1987, 1988, 1989, 1992 Free Software Foundation, Inc.
+
+ This code was donated by Wind River Systems, Inc. */
+
+/*
+modification history
+--------------------
+01b,25may91,maf now uses counted bytes struct to transfer registers.
+ removed xdr_regs_ptr (), xdr_fp_status_ptr (), and
+ xdr_fpa_regs_ptr ().
+01a,05jun90,llk extracted from xdr_ptrace.h, version 01c.
+*/
+
+#include "defs.h"
+#include "vxWorks.h"
+#include <rpc/rpc.h>
+#include "xdr_ptrace.h"
+
+#define MAX_LEN 32000
+
+/********************************************************************
+*
+* xdr_c_bytes -
+*
+* xdr routine for counted bytes
+*
+*/
+bool_t xdr_c_bytes(xdrs,objp)
+ XDR *xdrs;
+ C_bytes *objp;
+ {
+ return(xdr_bytes(xdrs, &objp->bytes, (u_int *) &objp->len, MAX_LEN));
+ } /* xdr_c_bytes */
+
+/********************************************************************
+*
+* xdr_c_bytes_ptr -
+*
+* xdr routine for counted bytes branch of ptrace_info
+*
+*/
+
+LOCAL bool_t xdr_c_bytes_ptr(xdrs,objp)
+ XDR *xdrs;
+ C_bytes **objp;
+ {
+ return(xdr_pointer(xdrs, (char **) objp, sizeof(C_bytes), xdr_c_bytes));
+ } /* xdr_c_bytes_ptr */
+
+/********************************************************************
+*
+* xdr_ptrace_info -
+*
+* xdr routine for discriminated union ptrace_info
+*
+*/
+
+bool_t xdr_ptrace_info(xdrs,objp)
+ XDR *xdrs;
+ Ptrace_info *objp;
+ {
+ static struct xdr_discrim choices[] =
+ {
+ { (int) DATA, xdr_c_bytes_ptr },
+ { __dontcare__, NULL }
+ };
+
+ return(xdr_union(xdrs, (enum_t *) &objp->ttype,
+ (char *) &objp->more_data, choices, xdr_void));
+ } /* xdr_ptrace_info */
+
+/********************************************************************
+*
+* xdr_rptrace -
+*
+* xdr routine for remote ptrace data into server
+*
+*/
+
+bool_t xdr_rptrace(xdrs,objp)
+ XDR *xdrs;
+ Rptrace *objp;
+ {
+ if (! xdr_int(xdrs, &objp->pid))
+ return(FALSE);
+ if (! xdr_int(xdrs, &objp->data))
+ return(FALSE);
+ if (! xdr_int(xdrs, &objp->addr))
+ return(FALSE);
+ if (! xdr_ptrace_info(xdrs, &objp->info))
+ return(FALSE);
+
+ return(TRUE);
+ } /* xdr_rptrace */
+
+/********************************************************************
+*
+* xdr_ptrace_return -
+*
+* xdr routine for remote ptrace data returned by server
+*
+*/
+
+bool_t xdr_ptrace_return(xdrs, objp)
+ XDR *xdrs;
+ Ptrace_return *objp;
+ {
+ if (! xdr_int(xdrs, &objp->status))
+ return(FALSE);
+ if (! xdr_int(xdrs, &objp->errno_num))
+ return(FALSE);
+ if (! xdr_ptrace_info(xdrs, &objp->info))
+ return(FALSE);
+
+ return(TRUE);
+ } /* xdr_ptrace_return */
diff --git a/gdb/vx-share/xdr_ptrace.h b/gdb/vx-share/xdr_ptrace.h
new file mode 100644
index 00000000000..9b4eb2b0872
--- /dev/null
+++ b/gdb/vx-share/xdr_ptrace.h
@@ -0,0 +1,72 @@
+/* xdr_ptrace.h - xdr header for remote ptrace structures */
+
+/* Copyright 1992 Free Software Foundation, Inc.
+
+ This code was donated by Wind River Systems, Inc. */
+
+/*
+modification history
+--------------------
+01b,25may91,maf now uses counted bytes struct to transfer registers;
+ removed references to old xdr_regs functions.
+ removed includes of "xdr_regs.h" and "reg.h".
+01a,05jun90,llk extracted from xdr_ptrace.h.
+*/
+
+
+/*
+ * Counted byte structure used by READ/WRITE TEXT/DATA
+ * and GET/SET REGS/FPREGS
+ */
+struct c_bytes {
+ u_int len;
+ caddr_t bytes;
+};
+typedef struct c_bytes C_bytes;
+
+/*
+ * enum for discriminated union ptrace_info
+ */
+enum ptype {
+ NOINFO = 0, /* no additional infomation */
+ DATA = 1 /* c_bytes */
+};
+typedef enum ptype ptype;
+
+/*
+ * discrimnated union for passing additional data to be
+ * written to the debugged process.
+ */
+struct ptrace_info {
+ ptype ttype;
+ caddr_t more_data;
+};
+typedef struct ptrace_info Ptrace_info;
+
+/*
+ * structure passed to server on all remote ptrace calls
+ */
+struct rptrace {
+ int pid;
+ int data;
+ int addr; /* FIX! this really should be caddr_t or something */
+ Ptrace_info info;
+};
+typedef struct rptrace Rptrace;
+
+/*
+ * structure returned by server on all remote ptrace calls
+ */
+/* This used to have a field called errno, but that fails on hosts which
+ define errno to be a macro, so it was changed to errno_num. */
+struct ptrace_return {
+ int status;
+ int errno_num;
+ Ptrace_info info;
+};
+typedef struct ptrace_return Ptrace_return;
+
+bool_t xdr_c_bytes();
+bool_t xdr_ptrace_info();
+bool_t xdr_rptrace();
+bool_t xdr_ptrace_return();
diff --git a/gdb/vx-share/xdr_rdb.c b/gdb/vx-share/xdr_rdb.c
new file mode 100644
index 00000000000..0520f7f6e7a
--- /dev/null
+++ b/gdb/vx-share/xdr_rdb.c
@@ -0,0 +1,212 @@
+/* xdr_rdb.c - xdr routines for Remote Debug interface to VxWorks */
+
+/* Copyright 1992 Free Software Foundation, Inc.
+
+ This code was donated by Wind River Systems, Inc. */
+
+/*
+modification history
+--------------------
+01a,21mar90,llk created using modification 01d of xdr_dbx.c.
+*/
+
+/*
+DESCRIPTION
+This module contains the eXternal Data Representation (XDR) routines
+for the RDB interface for VxWorks.
+*/
+
+#include "defs.h"
+#include "vxWorks.h"
+#include <rpc/rpc.h>
+#include "xdr_rdb.h"
+
+/* forward declarations */
+
+bool_t
+xdr_arg_type(xdrs, objp)
+ XDR *xdrs;
+ arg_type *objp;
+{
+ if (!xdr_enum(xdrs, (enum_t *)objp)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_arg_value(xdrs, objp)
+ XDR *xdrs;
+ arg_value *objp;
+{
+ if (!xdr_arg_type(xdrs, &objp->type)) {
+ return (FALSE);
+ }
+ switch (objp->type) {
+ case T_BYTE:
+ if (!xdr_char(xdrs, &objp->arg_value_u.v_byte)) {
+ return (FALSE);
+ }
+ break;
+ case T_WORD:
+ if (!xdr_short(xdrs, &objp->arg_value_u.v_word)) {
+ return (FALSE);
+ }
+ break;
+ case T_INT:
+ if (!xdr_int(xdrs, &objp->arg_value_u.v_int)) {
+ return (FALSE);
+ }
+ break;
+ case T_FLOAT:
+ if (!xdr_float(xdrs, &objp->arg_value_u.v_fp)) {
+ return (FALSE);
+ }
+ break;
+ case T_DOUBLE:
+ if (!xdr_double(xdrs, &objp->arg_value_u.v_dp)) {
+ return (FALSE);
+ }
+ break;
+ case T_UNKNOWN:
+ break;
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_func_call(xdrs, objp)
+ XDR *xdrs;
+ func_call *objp;
+{
+ if (!xdr_int(xdrs, &objp->func_addr)) {
+ return (FALSE);
+ }
+ if (!xdr_array(xdrs, (char **)&objp->args.args_val, (u_int *)&objp->args.args_len, MAX_FUNC_ARGS, sizeof(arg_value), xdr_arg_value)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_arg_one(xdrs, objp)
+ XDR *xdrs;
+ arg_one *objp;
+{
+ if (!xdr_string(xdrs, objp, MAX_ARG_LEN)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+
+
+
+bool_t
+xdr_arg_array(xdrs, objp)
+ XDR *xdrs;
+ arg_array *objp;
+{
+ if (!xdr_array(xdrs, (char **)&objp->arg_array_val, (u_int *)&objp->arg_array_len, MAX_ARG_CNT, sizeof(arg_one), xdr_arg_one)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+/*********************************************************************
+*
+* xdr_EVENT_TYPE -
+*
+*/
+
+bool_t xdr_EVENT_TYPE(xdrs, objp)
+ XDR *xdrs;
+ EVENT_TYPE *objp;
+
+ {
+ if (!xdr_enum (xdrs, (enum_t *) objp))
+ return (FALSE);
+ return (TRUE);
+ }
+
+/*********************************************************************
+*
+* xdr_RDB_EVENT -
+*
+*/
+
+bool_t xdr_RDB_EVENT (xdrs, objp)
+ XDR *xdrs;
+ RDB_EVENT *objp;
+
+ {
+ if (!xdr_int (xdrs, &objp->status))
+ return (FALSE);
+ if (!xdr_int (xdrs, &objp->taskId))
+ return (FALSE);
+ if (!xdr_EVENT_TYPE (xdrs, &objp->eventType))
+ return (FALSE);
+ if (!xdr_int (xdrs, &objp->sigType))
+ return (FALSE);
+ return (TRUE);
+ }
+
+/*********************************************************************
+*
+* xdr_TASK_START -
+*
+*/
+
+bool_t
+xdr_TASK_START (xdrs, objp)
+ XDR *xdrs;
+ TASK_START *objp;
+
+ {
+ if (!xdr_int (xdrs, &objp->status))
+ return (FALSE);
+ if (!xdr_int (xdrs, &objp->pid))
+ return (FALSE);
+ return (TRUE);
+ }
+
+
+/*********************************************************************
+*
+* xdr_SYMBOL_ADDR -
+*
+*/
+
+bool_t
+xdr_SYMBOL_ADDR (xdrs, objp)
+ XDR *xdrs;
+ SYMBOL_ADDR *objp;
+
+ {
+ if (!xdr_int (xdrs, &objp->status))
+ return (FALSE);
+ if (!xdr_u_int (xdrs, &objp->addr))
+ return (FALSE);
+ return (TRUE);
+ }
+
+/*********************************************************************
+*
+* xdr_SOURCE_STEP -
+*
+*/
+
+bool_t
+xdr_SOURCE_STEP (xdrs, objp)
+ XDR *xdrs;
+ SOURCE_STEP *objp;
+
+ {
+ if (!xdr_int (xdrs, &objp->taskId))
+ return (FALSE);
+ if (!xdr_u_int (xdrs, &objp->startAddr))
+ return (FALSE);
+ if (!xdr_u_int (xdrs, &objp->endAddr))
+ return (FALSE);
+ return (TRUE);
+ }
diff --git a/gdb/vx-share/xdr_rdb.h b/gdb/vx-share/xdr_rdb.h
new file mode 100644
index 00000000000..01894536297
--- /dev/null
+++ b/gdb/vx-share/xdr_rdb.h
@@ -0,0 +1,137 @@
+/* xdr_rdb.h - xdr for additional rdb structures */
+
+/* Copyright 1992 Free Software Foundation, Inc.
+
+ This code was donated by Wind River Systems, Inc. */
+
+/*
+modification history
+--------------------
+01c,25may91,maf rolled RDBVERS for VxGDB 1.0 version.
+01b,12apr91,maf rolled RDBVERS.
+01a,09jan91,maf created using v1a of xdr_rdb.h for 4.0.2 VxWorks 68k.
+ added struct SOURCE_STEP.
+*/
+
+#ifndef INCxdrrdbh
+#define INCxdrrdbh
+
+enum arg_type {
+ T_UNKNOWN = 0,
+ T_BYTE = 1,
+ T_WORD = 2,
+ T_INT = 3,
+ T_FLOAT = 4,
+ T_DOUBLE = 5
+};
+typedef enum arg_type arg_type;
+bool_t xdr_arg_type();
+
+
+struct arg_value {
+ arg_type type;
+ union {
+ char v_byte;
+ short v_word;
+ int v_int;
+ float v_fp;
+ double v_dp;
+ } arg_value_u;
+};
+typedef struct arg_value arg_value;
+bool_t xdr_arg_value();
+
+struct func_call {
+ int func_addr;
+ struct {
+ u_int args_len;
+ arg_value *args_val;
+ } args;
+};
+typedef struct func_call func_call;
+bool_t xdr_func_call();
+
+
+typedef char *arg_one;
+bool_t xdr_arg_one();
+
+
+typedef struct {
+ u_int arg_array_len;
+ arg_one *arg_array_val;
+} arg_array;
+bool_t xdr_arg_array();
+
+
+/*
+ * Structures used to pass structures required for
+ * process control but not part of the standard ptrace interface
+ */
+
+/*
+ * arg_info is used to pass arguments into process start
+ */
+struct arg_info {
+ int rargc;
+ char **rargv;
+};
+typedef struct arg_info Arg_info;
+
+
+enum EVENT_TYPE {
+ EVENT_BREAK = 0,
+ EVENT_STOP = 1,
+ EVENT_EXIT = 2,
+ EVENT_BUS_ERR = 3,
+ EVENT_SUSPEND = 4,
+ EVENT_ZERO_DIV = 5,
+ EVENT_SIGNAL = 6,
+ EVENT_START = 7
+};
+typedef enum EVENT_TYPE EVENT_TYPE;
+
+
+struct RDB_EVENT {
+ int status;
+ int taskId;
+ EVENT_TYPE eventType;
+ int sigType;
+};
+typedef struct RDB_EVENT RDB_EVENT;
+
+
+struct TASK_START {
+ int status;
+ int pid;
+};
+typedef struct TASK_START TASK_START;
+
+
+struct SYMBOL_ADDR {
+ int status;
+ u_int addr;
+};
+typedef struct SYMBOL_ADDR SYMBOL_ADDR;
+
+struct SOURCE_STEP {
+ int taskId;
+ u_int startAddr;
+ u_int endAddr;
+};
+typedef struct SOURCE_STEP SOURCE_STEP;
+
+#define MAX_ARG_CNT 10
+#define MAX_FUNC_ARGS 100
+#define MAX_ARG_LEN 100
+
+
+bool_t xdr_arg_info();
+bool_t xdr_EVENT_TYPE();
+bool_t xdr_RDB_EVENT();
+bool_t xdr_TASK_START();
+bool_t xdr_SYMBOL_ADDR();
+bool_t xdr_SOURCE_STEP();
+
+#define RDBPROG (u_long) 0x44444444
+#define RDBVERS (u_long) 3
+#endif INCxdrrdbh
diff --git a/gdb/w65-tdep.c b/gdb/w65-tdep.c
new file mode 100644
index 00000000000..9546616af4e
--- /dev/null
+++ b/gdb/w65-tdep.c
@@ -0,0 +1,295 @@
+/* Target-machine dependent code for WDC-65816, for GDB.
+ Copyright (C) 1995 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/*
+ Contributed by Steve Chamberlain
+ sac@cygnus.com
+ */
+
+#include "defs.h"
+#include "frame.h"
+#include "obstack.h"
+#include "symtab.h"
+#include "gdbcmd.h"
+#include "gdbtypes.h"
+#include "dis-asm.h"
+#include "gdbcore.h"
+
+/* Return the saved PC from this frame. */
+
+
+CORE_ADDR
+w65_frame_saved_pc (frame)
+ struct frame_info *frame;
+{
+ return (read_memory_integer (frame->frame + 2, 4) & 0xffffff);
+}
+
+CORE_ADDR
+w65_addr_bits_remove (addr)
+ CORE_ADDR addr;
+{
+ return ((addr) & 0xffffff);
+}
+
+read_memory_pointer (x)
+ CORE_ADDR x;
+{
+ return read_memory_integer (ADDR_BITS_REMOVE (x), 4);
+}
+
+init_frame_pc ()
+{
+ abort ();
+}
+
+void
+w65_push_dummy_frame ()
+{
+ abort ();
+}
+
+/* Put here the code to store, into a struct frame_saved_regs,
+ the addresses of the saved registers of frame described by FRAME_INFO.
+ This includes special registers such as pc and fp saved in special
+ ways in the stack frame. sp is even more special:
+ the address we return for it IS the sp for the next frame.
+
+ We cache the result of doing this in the frame_cache_obstack, since
+ it is fairly expensive. */
+
+void
+frame_find_saved_regs (fip, fsrp)
+ struct frame_info *fip;
+ struct frame_saved_regs *fsrp;
+{
+ int locals;
+ CORE_ADDR pc;
+ CORE_ADDR adr;
+ int i;
+
+ memset (fsrp, 0, sizeof *fsrp);
+}
+
+int
+saved_pc_after_call ()
+{
+ int sp = read_register (SP_REGNUM);
+ int val = read_memory_integer (sp + 1, 4);
+ return ADDR_BITS_REMOVE (val);
+}
+
+
+extract_return_value (type, regbuf, valbuf)
+ struct type *type;
+ char *regbuf;
+ char *valbuf;
+{
+ int b;
+ int len = TYPE_LENGTH (type);
+
+ for (b = 0; b < len; b += 2)
+ {
+ int todo = len - b;
+ if (todo > 2)
+ todo = 2;
+ memcpy (valbuf + b, regbuf + b, todo);
+ }
+}
+
+void
+write_return_value (type, valbuf)
+ struct type *type;
+ char *valbuf;
+{
+ int reg;
+ int len;
+ for (len = 0; len < TYPE_LENGTH (type); len += 2)
+ {
+ write_register_bytes (REGISTER_BYTE (len / 2 + 2), valbuf + len, 2);
+ }
+}
+
+void
+store_struct_return (addr, sp)
+ CORE_ADDR addr;
+ CORE_ADDR sp;
+{
+ write_register (2, addr);
+}
+
+void
+w65_pop_frame ()
+{
+}
+
+init_extra_frame_info ()
+{
+}
+
+pop_frame ()
+{
+}
+
+w65_frame_chain (thisframe)
+ struct frame_info *thisframe;
+{
+ return 0xffff & read_memory_integer ((thisframe)->frame, 2);
+}
+
+static int
+gb (x)
+{
+ return read_memory_integer (x, 1) & 0xff;
+}
+
+extern CORE_ADDR
+w65_skip_prologue (pc)
+ CORE_ADDR pc;
+{
+ CORE_ADDR too_far = pc + 20;
+
+ /* looking for bits of the prologue, we can expect to
+ see this in a frameful function:
+
+ stack adjust:
+
+ 3B tsc
+ 1A inc a
+ 18 clc
+ 69E2FF adc #0xffe2
+ 3A dec a
+ 1B tcs
+ 1A inc a
+
+ link:
+
+ A500 lda <r15
+ 48 pha
+ 3B tsc
+ 1a inc a
+ 8500 sta <r15
+
+ */
+
+#define TSC 0x3b
+#define TCS 0x1b
+#define INCA 0x1a
+#define PHA 0x48
+#define LDADIR 0xa5
+#define STADIR 0x85
+
+ /* Skip a stack adjust - any area between a tsc and tcs */
+ if (gb (pc) == TSC)
+ {
+ while (pc < too_far && gb (pc) != TCS)
+ {
+ pc++;
+ }
+ pc++;
+ /* Skip a stupid inc a */
+ if (gb (pc) == INCA)
+ pc++;
+
+ }
+ /* Stack adjust can also be done with n pha's */
+ while (gb (pc) == PHA)
+ pc++;
+
+ /* Skip a link - that's a ld/ph/tsc/inc/sta */
+
+ if (gb (pc) == LDADIR
+ && gb (pc + 5) == STADIR
+ && gb (pc + 1) == gb (pc + 6)
+ && gb (pc + 2) == PHA
+ && gb (pc + 3) == TSC
+ && gb (pc + 4) == INCA)
+ {
+ pc += 7;
+ }
+
+ return pc;
+}
+
+
+register_raw_size (n)
+{
+ return sim_reg_size (n);
+}
+
+
+void
+print_register_hook (regno)
+{
+ if (regno == P_REGNUM)
+ {
+ /* CCR register */
+
+ int C, Z, N, V, I, D, X, M;
+ unsigned char b[1];
+ unsigned char l;
+
+ read_relative_register_raw_bytes (regno, b);
+ l = b[0];
+ printf_unfiltered ("\t");
+ C = (l & 0x1) != 0;
+ Z = (l & 0x2) != 0;
+ I = (l & 0x4) != 0;
+ D = (l & 0x8) != 0;
+ X = (l & 0x10) != 0;
+ M = (l & 0x20) != 0;
+ V = (l & 0x40) != 0;
+ N = (l & 0x80) != 0;
+
+ printf_unfiltered ("N-%d ", N);
+ printf_unfiltered ("V-%d ", V);
+ printf_unfiltered ("M-%d ", M);
+ printf_unfiltered ("X-%d ", X);
+ printf_unfiltered ("D-%d ", D);
+ printf_unfiltered ("I-%d ", I);
+ printf_unfiltered ("Z-%d ", Z);
+ printf_unfiltered ("C-%d ", C);
+ if ((C | Z) == 0)
+ printf_unfiltered ("u> ");
+ if ((C | Z) == 1)
+ printf_unfiltered ("u<= ");
+ if ((C == 0))
+ printf_unfiltered ("u>= ");
+ if (C == 1)
+ printf_unfiltered ("u< ");
+ if (Z == 0)
+ printf_unfiltered ("!= ");
+ if (Z == 1)
+ printf_unfiltered ("== ");
+ if ((N ^ V) == 0)
+ printf_unfiltered (">= ");
+ if ((N ^ V) == 1)
+ printf_unfiltered ("< ");
+ if ((Z | (N ^ V)) == 0)
+ printf_unfiltered ("> ");
+ if ((Z | (N ^ V)) == 1)
+ printf_unfiltered ("<= ");
+ }
+}
+
+void
+_initialize_w65_tdep ()
+{
+ tm_print_insn = print_insn_w65;
+}
diff --git a/gdb/w89k-rom.c b/gdb/w89k-rom.c
new file mode 100644
index 00000000000..d01a26582a7
--- /dev/null
+++ b/gdb/w89k-rom.c
@@ -0,0 +1,317 @@
+/* Remote target glue for the WinBond ROM monitor running on the "Cougar"
+ W89k eval board.
+
+ Copyright 1995 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "gdbcore.h"
+#include "target.h"
+#include "monitor.h"
+#include "serial.h"
+#include "xmodem.h"
+
+
+static void w89k_open PARAMS ((char *args, int from_tty));
+
+/*
+ * this array of registers need to match the indexes used by GDB. The
+ * whole reason this exists is cause the various ROM monitors use
+ * different strings than GDB does, and doesn't support all the
+ * registers either. So, typing "info reg sp" becomes a "r30".
+ */
+
+static char *w89k_regnames[NUM_REGS] =
+{
+ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
+ "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
+ "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
+ "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
+ "SAR", "PC", NULL, NULL, NULL, "EIEM", "IIR", "IVA",
+ "IOR", "IPSW", NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ "CCR", NULL, NULL, "TR0", "TR1",
+};
+
+static void
+w89k_supply_register (regname, regnamelen, val, vallen)
+ char *regname;
+ int regnamelen;
+ char *val;
+ int vallen;
+{
+ int numregs;
+ int regno;
+
+ numregs = 1;
+ regno = -1;
+
+ if (regnamelen == 2)
+ switch (regname[0])
+ {
+ case 'r':
+ numregs = 4;
+ switch (regname[1])
+ {
+ case '0':
+ regno = R0_REGNUM;
+ break;
+ case '4':
+ regno = R0_REGNUM + 4;
+ break;
+ case '8':
+ regno = R0_REGNUM + 8;
+ break;
+ }
+ break;
+ case 'P':
+ if (regname[1] == 'C')
+ regno = PC_REGNUM;
+ break;
+ }
+ else if (regnamelen == 3)
+ switch (regname[0])
+ {
+ case 'r':
+ numregs = 4;
+ if (regname[1] == '1' && regname[2] == '2')
+ regno = R0_REGNUM + 12;
+ else if (regname[1] == '1' && regname[2] == '6')
+ regno = R0_REGNUM + 16;
+ else if (regname[1] == '2' && regname[2] == '0')
+ regno = R0_REGNUM + 20;
+ else if (regname[1] == '2' && regname[2] == '4')
+ regno = R0_REGNUM + 24;
+ else if (regname[1] == '2' && regname[2] == '8')
+ regno = R0_REGNUM + 28;
+ break;
+ case 'R':
+ if (regname[1] == 'C' && regname[2] == 'R')
+ regno = RCR_REGNUM;
+ break;
+ case 'C':
+ if (regname[1] == 'C' && regname[2] == 'R')
+ regno = CCR_REGNUM;
+ break;
+ case 'S':
+ if (regname[1] == 'A' && regname[2] == 'R')
+ regno = SAR_REGNUM;
+ break;
+ case 'I':
+ if (regname[1] == 'I' && regname[2] == 'R')
+ regno = IIR_REGNUM;
+ else if (regname[1] == 'O' && regname[2] == 'R')
+ regno = IOR_REGNUM;
+ break;
+ case 'T':
+ numregs = 4;
+ if (regname[1] == 'R')
+ if (regname[2] == '0')
+ regno = TR0_REGNUM;
+ else if (regname[2] == '4')
+ regno = TR0_REGNUM + 4;
+ break;
+ }
+ else if (regnamelen == 4)
+ switch (regname[0])
+ {
+ case 'E':
+ if (regname[1] == 'I')
+ if (regname[2] == 'E' && regname[3] == 'M')
+ regno = EIEM_REGNUM;
+ break;
+ case 'I':
+ if (regname[1] == 'P' && regname[2] == 'S' && regname[3] == 'W')
+ regno = IPSW_REGNUM;
+ break;
+ }
+ else if (regnamelen == 5)
+ switch (regname[0])
+ {
+ case 'I':
+ if (regname[1] == 'A'
+ && regname[2] == 'O'
+ && regname[3] == 'Q'
+ && regname[4] == 'B')
+ regno = PCOQ_TAIL_REGNUM;
+ break;
+ }
+
+ if (regno >= 0)
+ while (numregs-- > 0)
+ val = monitor_supply_register (regno++, val);
+}
+
+static int hashmark = 1; /* flag set by "set hash" */
+
+extern struct monitor_ops w89k_cmds; /* fwd decl */
+
+static void
+w89k_load (desc, file, hashmark)
+ serial_t desc;
+ char *file;
+ int hashmark;
+{
+ bfd *abfd;
+ asection *s;
+ char *buffer;
+ int i;
+
+ buffer = alloca (XMODEM_PACKETSIZE);
+
+ abfd = bfd_openr (file, 0);
+ if (!abfd)
+ {
+ printf_filtered ("Unable to open file %s\n", file);
+ return;
+ }
+
+ if (bfd_check_format (abfd, bfd_object) == 0)
+ {
+ printf_filtered ("File is not an object file\n");
+ return;
+ }
+
+ for (s = abfd->sections; s; s = s->next)
+ if (s->flags & SEC_LOAD)
+ {
+ bfd_size_type section_size;
+
+ printf_filtered ("%s\t: 0x%4x .. 0x%4x ", s->name, s->vma,
+ s->vma + s->_raw_size);
+ gdb_flush (gdb_stdout);
+
+ monitor_printf (w89k_cmds.load, s->vma);
+ if (w89k_cmds.loadresp)
+ monitor_expect (w89k_cmds.loadresp, NULL, 0);
+
+ xmodem_init_xfer (desc);
+
+ section_size = bfd_section_size (abfd, s);
+
+ for (i = 0; i < section_size; i += XMODEM_DATASIZE)
+ {
+ int numbytes;
+
+ numbytes = min (XMODEM_DATASIZE, section_size - i);
+
+ bfd_get_section_contents (abfd, s, buffer + XMODEM_DATAOFFSET, i,
+ numbytes);
+
+ xmodem_send_packet (desc, buffer, numbytes, hashmark);
+
+ if (hashmark)
+ {
+ putchar_unfiltered ('#');
+ gdb_flush (gdb_stdout);
+ }
+ } /* Per-packet (or S-record) loop */
+
+ xmodem_finish_xfer (desc);
+
+ monitor_expect_prompt (NULL, 0);
+
+ putchar_unfiltered ('\n');
+ } /* Loadable sections */
+
+ if (hashmark)
+ putchar_unfiltered ('\n');
+}
+
+/*
+ * Define the monitor command strings. Since these are passed directly
+ * through to a printf style function, we need can include formatting
+ * strings. We also need a CR or LF on the end.
+ */
+
+static struct target_ops w89k_ops;
+
+static char *w89k_inits[] = {"\n", NULL};
+
+static struct monitor_ops w89k_cmds ;
+static void
+init_w89k_cmds(void)
+{
+ w89k_cmds.flags = MO_GETMEM_NEEDS_RANGE|MO_FILL_USES_ADDR; /* flags */
+ w89k_cmds.init = w89k_inits; /* Init strings */
+ w89k_cmds.cont = "g\n"; /* continue command */
+ w89k_cmds.step = "t\n"; /* single step */
+ w89k_cmds.stop = "\003"; /* Interrupt char (^C) */
+ w89k_cmds.set_break = "bp %x\n"; /* set a breakpoint */
+ w89k_cmds.clr_break = "bc %x\n"; /* clear a breakpoint */
+ w89k_cmds.clr_all_break = "bc *\n"; /* clear all breakpoints */
+ w89k_cmds.fill = "f %x %x %x\n"; /* memory fill cmd */
+ w89k_cmds.setmem.cmdb = "eb %x %x\n"; /* setmem.cmdb (addr, value) */
+ w89k_cmds.setmem.cmdw = "eh %x %x\n"; /* setmem.cmdw (addr, value) */
+ w89k_cmds.setmem.cmdl = "ew %x %x\n"; /* setmem.cmdl (addr, value) */
+ w89k_cmds.setmem.cmdll = NULL; /* setmem.cmdll (addr, value) */
+ w89k_cmds.setmem.resp_delim = NULL; /* setreg.resp_delim */
+ w89k_cmds.setmem.term = NULL; /* setreg.term */
+ w89k_cmds.setmem.term_cmd = NULL; /* setreg.term_cmd */
+ w89k_cmds.getmem.cmdb = "db %x %x\n";/* getmem.cmdb (startaddr, endaddr) */
+ w89k_cmds.getmem.cmdw = "dh %x %x\n";/* getmem.cmdw (startaddr, endaddr) */
+ w89k_cmds.getmem.cmdl = "dw %x %x\n";/* getmem.cmdl (startaddr, endaddr) */
+ w89k_cmds.getmem.cmdll = NULL; /* getmem.cmdll (startaddr, endaddr) */
+ w89k_cmds.getmem.resp_delim = " "; /* getmem.resp_delim */
+ w89k_cmds.getmem.term = NULL; /* getmem.term */
+ w89k_cmds.getmem.term_cmd = NULL; /* getmem.term_cmd */
+ w89k_cmds.setreg.cmd = "r %s %x\n"; /* setreg.cmd (name, value) */
+ w89k_cmds.setreg.resp_delim = NULL; /* setreg.resp_delim */
+ w89k_cmds.setreg.term = NULL; /* setreg.term */
+ w89k_cmds.setreg.term_cmd = NULL; /* setreg.term_cmd */
+ w89k_cmds.getreg.cmd = "r %s\n"; /* getreg.cmd (name) */
+ w89k_cmds.getreg.resp_delim = "\r"; /* getreg.resp_delim */
+ w89k_cmds.getreg.term = NULL; /* getreg.term */
+ w89k_cmds.getreg.term_cmd = NULL; /* getreg.term_cmd */
+ w89k_cmds.dump_registers = "r\n"; /* dump_registers */
+ w89k_cmds.register_pattern = "\\(\\w+\\)\\( +[0-9a-fA-F]+\\b\\)+";
+ w89k_cmds.supply_register = w89k_supply_register; /* supply_register */
+ w89k_cmds.load_routine = w89k_load; /* load routine */
+ w89k_cmds.load = "u %x\n"; /* download command */
+ w89k_cmds.loadresp = "\021"; /* load response (^Q) */
+ w89k_cmds.prompt = "ROM>"; /* monitor command prompt */
+ w89k_cmds.line_term = "\n"; /* end-of-line terminator */
+ w89k_cmds.cmd_end = NULL; /* optional command terminator */
+ w89k_cmds.target = &w89k_ops; /* target operations */
+ w89k_cmds.stopbits = SERIAL_1_STOPBITS; /* number of stop bits */
+ w89k_cmds.regnames = w89k_regnames; /* register names */
+ w89k_cmds.magic = MONITOR_OPS_MAGIC ; /* magic */
+} /* init_w89k_cmds */
+
+static void
+w89k_open(args, from_tty)
+ char *args;
+ int from_tty;
+{
+ monitor_open (args, &w89k_cmds, from_tty);
+}
+
+void
+_initialize_w89k ()
+{
+ init_w89k_cmds() ;
+ init_monitor_ops (&w89k_ops);
+
+ w89k_ops.to_shortname = "w89k";
+ w89k_ops.to_longname = "WinBond's debug monitor for the W89k Eval board";
+ w89k_ops.to_doc = "Debug on a WinBond W89K eval board.\n\
+Specify the serial device it is connected to (e.g. /dev/ttya).";
+ w89k_ops.to_open = w89k_open;
+
+ add_target (&w89k_ops);
+}
diff --git a/gdb/win32-nat.c b/gdb/win32-nat.c
new file mode 100644
index 00000000000..87e96bd23ac
--- /dev/null
+++ b/gdb/win32-nat.c
@@ -0,0 +1,1122 @@
+/* Target-vector operations for controlling win32 child processes, for GDB.
+ Copyright 1995, 1996, 1997, 1998 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 eve nthe implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+/* by Steve Chamberlain, sac@cygnus.com */
+
+/* We assume we're being built with and will be used for cygwin. */
+
+#include "defs.h"
+#include "frame.h" /* required by inferior.h */
+#include "inferior.h"
+#include "target.h"
+#include "wait.h"
+#include "gdbcore.h"
+#include "command.h"
+#include <signal.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <stdlib.h>
+
+#ifdef _MSC_VER
+#include "windefs.h"
+#else /* other WIN32 compiler */
+#include <windows.h>
+#endif
+
+#include "buildsym.h"
+#include "symfile.h"
+#include "objfiles.h"
+#include "gdb_string.h"
+#include "gdbthread.h"
+#include "gdbcmd.h"
+#include <sys/param.h>
+#include <unistd.h>
+
+/* The string sent by cygwin when it processes a signal.
+ FIXME: This should be in a cygwin include file. */
+#define CYGWIN_SIGNAL_STRING "cygwin: signal"
+
+#define CHECK(x) check (x, __FILE__,__LINE__)
+#define DEBUG_EXEC(x) if (debug_exec) printf x
+#define DEBUG_EVENTS(x) if (debug_events) printf x
+#define DEBUG_MEM(x) if (debug_memory) printf x
+#define DEBUG_EXCEPT(x) if (debug_exceptions) printf x
+
+/* Forward declaration */
+extern struct target_ops child_ops;
+
+static void child_stop PARAMS ((void));
+static int win32_child_thread_alive PARAMS ((int));
+
+static int last_sig = 0; /* Set if a signal was received from the
+ debugged process */
+
+/* Thread information structure used to track information that is
+ not available in gdb's thread structure. */
+typedef struct thread_info_struct
+{
+ struct thread_info_struct *next;
+ DWORD id;
+ HANDLE h;
+ char *name;
+ int suspend_count;
+ CONTEXT context;
+} thread_info;
+
+static thread_info thread_head = {NULL};
+
+/* The process and thread handles for the above context. */
+
+static DEBUG_EVENT current_event; /* The current debug event from
+ WaitForDebugEvent */
+static HANDLE current_process_handle; /* Currently executing process */
+static thread_info *current_thread; /* Info on currently selected thread */
+static DWORD main_thread_id; /* Thread ID of the main thread */
+
+/* Counts of things. */
+static int exception_count = 0;
+static int event_count = 0;
+
+/* User options. */
+static int new_console = 0;
+static int new_group = 0;
+static int debug_exec = 0; /* show execution */
+static int debug_events = 0; /* show events from kernel */
+static int debug_memory = 0; /* show target memory accesses */
+static int debug_exceptions = 0; /* show target exceptions */
+
+/* This vector maps GDB's idea of a register's number into an address
+ in the win32 exception context vector.
+
+ It also contains the bit mask needed to load the register in question.
+
+ One day we could read a reg, we could inspect the context we
+ already have loaded, if it doesn't have the bit set that we need,
+ we read that set of registers in using GetThreadContext. If the
+ context already contains what we need, we just unpack it. Then to
+ write a register, first we have to ensure that the context contains
+ the other regs of the group, and then we copy the info in and set
+ out bit. */
+
+#define context_offset(x) ((int)&(((CONTEXT *)NULL)->x))
+static const int mappings[] =
+{
+ context_offset(Eax),
+ context_offset(Ecx),
+ context_offset(Edx),
+ context_offset(Ebx),
+ context_offset(Esp),
+ context_offset(Ebp),
+ context_offset(Esi),
+ context_offset(Edi),
+ context_offset(Eip),
+ context_offset(EFlags),
+ context_offset(SegCs),
+ context_offset(SegSs),
+ context_offset(SegDs),
+ context_offset(SegEs),
+ context_offset(SegFs),
+ context_offset(SegGs),
+ context_offset(FloatSave.RegisterArea[0 * 10]),
+ context_offset(FloatSave.RegisterArea[1 * 10]),
+ context_offset(FloatSave.RegisterArea[2 * 10]),
+ context_offset(FloatSave.RegisterArea[3 * 10]),
+ context_offset(FloatSave.RegisterArea[4 * 10]),
+ context_offset(FloatSave.RegisterArea[5 * 10]),
+ context_offset(FloatSave.RegisterArea[6 * 10]),
+ context_offset(FloatSave.RegisterArea[7 * 10]),
+};
+
+/* This vector maps the target's idea of an exception (extracted
+ from the DEBUG_EVENT structure) to GDB's idea. */
+
+struct xlate_exception
+ {
+ int them;
+ enum target_signal us;
+ };
+
+static const struct xlate_exception
+ xlate[] =
+{
+ {EXCEPTION_ACCESS_VIOLATION, TARGET_SIGNAL_SEGV},
+ {STATUS_STACK_OVERFLOW, TARGET_SIGNAL_SEGV},
+ {EXCEPTION_BREAKPOINT, TARGET_SIGNAL_TRAP},
+ {DBG_CONTROL_C, TARGET_SIGNAL_INT},
+ {EXCEPTION_SINGLE_STEP, TARGET_SIGNAL_TRAP},
+ {-1, -1}};
+
+/* Find a thread record given a thread id.
+ If get_context then also retrieve the context for this
+ thread. */
+static thread_info *
+thread_rec (DWORD id, int get_context)
+{
+ thread_info *th;
+
+ for (th = &thread_head; (th = th->next) != NULL; )
+ if (th->id == id)
+ {
+ if (!th->suspend_count && get_context)
+ {
+ if (get_context > 0)
+ th->suspend_count = SuspendThread (th->h) + 1;
+ else if (get_context < 0)
+ th->suspend_count = -1;
+
+ th->context.ContextFlags = CONTEXT_DEBUGGER;
+ GetThreadContext (th->h, &th->context);
+ }
+ return th;
+ }
+
+ return NULL;
+}
+
+/* Add a thread to the thread list */
+static thread_info *
+child_add_thread(DWORD id, HANDLE h)
+{
+ thread_info *th;
+
+ if ((th = thread_rec (id, FALSE)))
+ return th;
+
+ th = (thread_info *) xmalloc (sizeof (*th));
+ memset(th, 0, sizeof (*th));
+ th->id = id;
+ th->h = h;
+ th->next = thread_head.next;
+ thread_head.next = th;
+ add_thread (id);
+ return th;
+}
+
+/* Clear out any old thread list and reintialize it to a
+ pristine state. */
+static void
+child_init_thread_list ()
+{
+ thread_info *th = &thread_head;
+
+ DEBUG_EVENTS (("gdb: child_init_thread_list\n"));
+ init_thread_list ();
+ while (th->next != NULL)
+ {
+ thread_info *here = th->next;
+ th->next = here->next;
+ (void) CloseHandle (here->h);
+ free (here);
+ }
+}
+
+/* Delete a thread from the list of threads */
+static void
+child_delete_thread (DWORD id)
+{
+ thread_info *th;
+
+ if (info_verbose)
+ printf_unfiltered ("[Deleting %s]\n", target_pid_to_str (id));
+ delete_thread (id);
+
+ for (th = &thread_head;
+ th->next != NULL && th->next->id != id;
+ th = th->next)
+ continue;
+
+ if (th->next != NULL)
+ {
+ thread_info *here = th->next;
+ th->next = here->next;
+ CloseHandle (here->h);
+ free (here);
+ }
+}
+
+static void
+check (BOOL ok, const char *file, int line)
+{
+ if (!ok)
+ printf_filtered ("error return %s:%d was %d\n", file, line, GetLastError ());
+}
+
+static void
+do_child_fetch_inferior_registers (int r)
+{
+ if (r >= 0)
+ supply_register (r, ((char *) &current_thread->context) + mappings[r]);
+ else
+ {
+ for (r = 0; r < NUM_REGS; r++)
+ do_child_fetch_inferior_registers (r);
+ }
+}
+
+static void
+child_fetch_inferior_registers (int r)
+{
+ current_thread = thread_rec (inferior_pid, TRUE);
+ do_child_fetch_inferior_registers (r);
+}
+
+static void
+do_child_store_inferior_registers (int r)
+{
+ if (r >= 0)
+ read_register_gen (r, ((char *) &current_thread->context) + mappings[r]);
+ else
+ {
+ for (r = 0; r < NUM_REGS; r++)
+ do_child_store_inferior_registers (r);
+ }
+}
+
+/* Store a new register value into the current thread context */
+static void
+child_store_inferior_registers (int r)
+{
+ current_thread = thread_rec (inferior_pid, TRUE);
+ do_child_store_inferior_registers (r);
+}
+
+/* Wait for child to do something. Return pid of child, or -1 in case
+ of error; store status through argument pointer OURSTATUS. */
+
+static int
+handle_load_dll (PTR dummy)
+{
+ LOAD_DLL_DEBUG_INFO * event = &current_event.u.LoadDll;
+ DWORD dll_name_ptr;
+ DWORD done;
+ char dll_buf[MAX_PATH + 1];
+ char *p, *dll_name = NULL, *dll_basename;
+ struct objfile *objfile;
+ MEMORY_BASIC_INFORMATION minfo;
+
+ dll_buf[0] = dll_buf[sizeof(dll_buf) - 1] = '\0';
+
+ /* The following code attempts to find the name of the dll by reading the
+ name from the processes memory. Unfortunately it doesn't work right.
+ Doing this the "right way" for Windows is very difficult. FIXME */
+#ifdef DOESNT_WORK
+ memset (&minfo, 0, sizeof minfo);
+ if (VirtualQueryEx (current_process_handle, (LPCVOID) event->lpBaseOfDll,
+ &minfo, sizeof(minfo)) && minfo.BaseAddress) {
+ DWORD len;
+ IMAGE_DOS_HEADER *hmm0 = (IMAGE_DOS_HEADER *) minfo.BaseAddress;
+ HMODULE hmm = (HMODULE) (((DWORD) hmm0) + hmm0->e_lfanew);
+
+ if ((len = GetModuleFileName (hmm, dll_buf, MAX_PATH)))
+ {
+ dll_name = dll_buf;
+ dll_name[len] = '\0';
+ }
+ }
+#endif
+
+ /* Attempt to read the name of the dll that was detected.
+ This is documented to work only when actively debugging
+ a program. It will not work for attached processes. */
+ if (dll_name == NULL || *dll_name == '\0')
+ {
+ int size = event->fUnicode ? sizeof (WCHAR) : sizeof (char);
+ int len = 0;
+ char b[2];
+
+ ReadProcessMemory (current_process_handle,
+ (LPCVOID) event->lpImageName,
+ (char *) &dll_name_ptr,
+ sizeof (dll_name_ptr), &done);
+
+ /* See if we could read the address of a string, and that the
+ address isn't null. */
+
+ if (done != sizeof (dll_name_ptr) || !dll_name_ptr)
+ return 1;
+
+ do
+ {
+ ReadProcessMemory (current_process_handle,
+ (LPCVOID) (dll_name_ptr + len * size),
+ &b,
+ size,
+ &done);
+ len++;
+ }
+ while ((b[0] != 0 || b[size - 1] != 0) && done == size);
+
+ dll_name = alloca (len);
+
+ if (event->fUnicode)
+ {
+ WCHAR *unicode_dll_name = (WCHAR *) alloca (len * sizeof (WCHAR));
+ ReadProcessMemory (current_process_handle,
+ (LPCVOID) dll_name_ptr,
+ unicode_dll_name,
+ len * sizeof (WCHAR),
+ &done);
+
+ WideCharToMultiByte (CP_ACP, 0,
+ unicode_dll_name, len,
+ dll_name, len, 0, 0);
+ }
+ else
+ {
+ ReadProcessMemory (current_process_handle,
+ (LPCVOID) dll_name_ptr,
+ dll_name,
+ len,
+ &done);
+ }
+ }
+
+ if (!dll_name)
+ return 1;
+
+ while ((p = strchr (dll_name, '\\')))
+ *p = '/';
+
+ /* FIXME!! It would be nice to define one symbol which pointed to the
+ front of the dll if we can't find any symbols. */
+
+ if (!(dll_basename = strrchr(dll_name, '/')))
+ dll_basename = dll_name;
+ else
+ dll_basename++;
+
+ ALL_OBJFILES(objfile)
+ {
+ char *objfile_basename;
+ objfile_basename = strrchr(objfile->name, '/');
+
+ if (objfile_basename &&
+ strcmp(dll_basename, objfile_basename + 1) == 0)
+ {
+ printf_unfiltered ("%x:%s (symbols previously loaded)\n",
+ event->lpBaseOfDll, dll_name);
+ goto out;
+ }
+ }
+
+ /* The symbols in a dll are offset by 0x1000, which is the
+ the offset from 0 of the first byte in an image - because
+ of the file header and the section alignment.
+
+ FIXME: Is this the real reason that we need the 0x1000 ? */
+
+ printf_unfiltered ("%x:%s", event->lpBaseOfDll, dll_name);
+ symbol_file_add (dll_name, 0, (int) event->lpBaseOfDll + 0x1000, 0, 0, 0, 0, 1);
+ printf_unfiltered ("\n");
+
+out:
+ return 1;
+}
+
+/* Handle DEBUG_STRING output from child process.
+ Cygwin prepends its messages with a "cygwin:". Interpret this as
+ a Cygwin signal. Otherwise just print the string as a warning. */
+static int
+handle_output_debug_string (struct target_waitstatus *ourstatus)
+{
+ char *s;
+ int gotasig = FALSE;
+
+ if (!target_read_string
+ ((CORE_ADDR) current_event.u.DebugString.lpDebugStringData, &s, 1024, 0)
+ || !s || !*s)
+ return gotasig;
+
+ if (strncmp(s, CYGWIN_SIGNAL_STRING, sizeof(CYGWIN_SIGNAL_STRING) - 1))
+ {
+ warning (s);
+ }
+ else
+ {
+ char *p;
+ /*last_sig = */strtol(s + sizeof(CYGWIN_SIGNAL_STRING) - 1, &p, 0);
+ if (gotasig = (ourstatus->value.sig = target_signal_from_host (last_sig)))
+ ourstatus->kind = TARGET_WAITKIND_STOPPED;
+ }
+
+ free (s);
+ return gotasig;
+}
+
+static int
+handle_exception (struct target_waitstatus *ourstatus)
+{
+ int i;
+ int done = 0;
+ thread_info *th;
+
+ ourstatus->kind = TARGET_WAITKIND_STOPPED;
+
+ /* Record the context of the current thread */
+ th = thread_rec (current_event.dwThreadId, -1);
+
+ switch (current_event.u.Exception.ExceptionRecord.ExceptionCode)
+ {
+ case EXCEPTION_ACCESS_VIOLATION:
+ DEBUG_EXCEPT (("gdb: Target exception ACCESS_VIOLATION at 0x%08x\n",
+ current_event.u.Exception.ExceptionRecord.ExceptionAddress));
+ ourstatus->value.sig = TARGET_SIGNAL_SEGV;
+ break;
+ case STATUS_STACK_OVERFLOW:
+ DEBUG_EXCEPT (("gdb: Target exception STACK_OVERFLOW at 0x%08x\n",
+ current_event.u.Exception.ExceptionRecord.ExceptionAddress));
+ ourstatus->value.sig = TARGET_SIGNAL_SEGV;
+ break;
+ case EXCEPTION_BREAKPOINT:
+ DEBUG_EXCEPT (("gdb: Target exception BREAKPOINT at 0x%08x\n",
+ current_event.u.Exception.ExceptionRecord.ExceptionAddress));
+ ourstatus->value.sig = TARGET_SIGNAL_TRAP;
+ break;
+ case DBG_CONTROL_C:
+ DEBUG_EXCEPT (("gdb: Target exception CONTROL_C at 0x%08x\n",
+ current_event.u.Exception.ExceptionRecord.ExceptionAddress));
+ ourstatus->value.sig = TARGET_SIGNAL_INT;
+ /* User typed CTRL-C. Continue with this status */
+ last_sig = SIGINT; /* FIXME - should check pass state */
+ break;
+ case EXCEPTION_SINGLE_STEP:
+ DEBUG_EXCEPT (("gdb: Target exception SINGLE_STEP at 0x%08x\n",
+ current_event.u.Exception.ExceptionRecord.ExceptionAddress));
+ ourstatus->value.sig = TARGET_SIGNAL_TRAP;
+ break;
+ default:
+ /* This may be a structured exception handling exception. In
+ that case, we want to let the program try to handle it, and
+ only break if we see the exception a second time. */
+ if (current_event.u.Exception.dwFirstChance)
+ return 0;
+
+ printf_unfiltered ("gdb: unknown target exception 0x%08x at 0x%08x\n",
+ current_event.u.Exception.ExceptionRecord.ExceptionCode,
+ current_event.u.Exception.ExceptionRecord.ExceptionAddress);
+ ourstatus->value.sig = TARGET_SIGNAL_UNKNOWN;
+ break;
+ }
+ exception_count++;
+ return 1;
+}
+
+/* Resume all artificially suspended threads if we are continuing
+ execution */
+static BOOL
+child_continue (DWORD continue_status, int id)
+{
+ int i;
+ thread_info *th;
+ BOOL res;
+
+ DEBUG_EVENTS (("ContinueDebugEvent (cpid=%d, ctid=%d, DBG_CONTINUE);\n",
+ current_event.dwProcessId, current_event.dwThreadId));
+ if (res = ContinueDebugEvent (current_event.dwProcessId,
+ current_event.dwThreadId,
+ continue_status))
+ for (th = &thread_head; (th = th->next) != NULL; )
+ if (((id == -1) || (id == th->id)) && th->suspend_count)
+ {
+ for (i = 0; i < th->suspend_count; i++)
+ (void) ResumeThread (th->h);
+ th->suspend_count = 0;
+ }
+
+ return res;
+}
+
+static int
+child_wait (int pid, struct target_waitstatus *ourstatus)
+{
+ /* We loop when we get a non-standard exception rather than return
+ with a SPURIOUS because resume can try and step or modify things,
+ which needs a current_thread->h. But some of these exceptions mark
+ the birth or death of threads, which mean that the current thread
+ isn't necessarily what you think it is. */
+
+ while (1)
+ {
+ DWORD continue_status;
+ BOOL t = WaitForDebugEvent (&current_event, INFINITE);
+ char *p;
+ thread_info *th;
+ int sig;
+
+ event_count++;
+
+ continue_status = DBG_CONTINUE;
+
+ switch (current_event.dwDebugEventCode)
+ {
+ case CREATE_THREAD_DEBUG_EVENT:
+ DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%x code=%s)\n",
+ current_event.dwProcessId, current_event.dwThreadId,
+ "CREATE_THREAD_DEBUG_EVENT"));
+ /* Record the existence of this thread */
+ child_add_thread (current_event.dwThreadId,
+ current_event.u.CreateThread.hThread);
+ if (info_verbose)
+ printf_unfiltered ("[New %s]\n",
+ target_pid_to_str (current_event.dwThreadId));
+ break;
+
+ case EXIT_THREAD_DEBUG_EVENT:
+ DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
+ current_event.dwProcessId, current_event.dwThreadId,
+ "EXIT_THREAD_DEBUG_EVENT"));
+ child_delete_thread (current_event.dwThreadId);
+ break;
+
+ case CREATE_PROCESS_DEBUG_EVENT:
+ DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
+ current_event.dwProcessId, current_event.dwThreadId,
+ "CREATE_PROCESS_DEBUG_EVENT"));
+ current_process_handle = current_event.u.CreateProcessInfo.hProcess;
+
+ main_thread_id = inferior_pid = current_event.dwThreadId;
+ /* Add the main thread */
+ current_thread = child_add_thread (inferior_pid,
+ current_event.u.CreateProcessInfo.hThread);
+ break;
+
+ case EXIT_PROCESS_DEBUG_EVENT:
+ DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
+ current_event.dwProcessId, current_event.dwThreadId,
+ "EXIT_PROCESS_DEBUG_EVENT"));
+ ourstatus->kind = TARGET_WAITKIND_EXITED;
+ ourstatus->value.integer = current_event.u.ExitProcess.dwExitCode;
+ CloseHandle (current_process_handle);
+ return current_event.dwProcessId;
+ break;
+
+ case LOAD_DLL_DEBUG_EVENT:
+ DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
+ current_event.dwProcessId, current_event.dwThreadId,
+ "LOAD_DLL_DEBUG_EVENT"));
+ catch_errors (handle_load_dll, NULL, "", RETURN_MASK_ALL);
+ registers_changed(); /* mark all regs invalid */
+ break;
+
+ case UNLOAD_DLL_DEBUG_EVENT:
+ DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
+ current_event.dwProcessId, current_event.dwThreadId,
+ "UNLOAD_DLL_DEBUG_EVENT"));
+ break; /* FIXME: don't know what to do here */
+
+ case EXCEPTION_DEBUG_EVENT:
+ DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
+ current_event.dwProcessId, current_event.dwThreadId,
+ "EXCEPTION_DEBUG_EVENT"));
+ if (handle_exception (ourstatus))
+ return current_event.dwThreadId;
+ continue_status = DBG_EXCEPTION_NOT_HANDLED;
+ break;
+
+ case OUTPUT_DEBUG_STRING_EVENT: /* message from the kernel */
+ DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
+ current_event.dwProcessId, current_event.dwThreadId,
+ "OUTPUT_DEBUG_STRING_EVENT"));
+ if (handle_output_debug_string (ourstatus))
+ return main_thread_id;
+ break;
+ default:
+ printf_unfiltered ("gdb: kernel event for pid=%d tid=%d\n",
+ current_event.dwProcessId,
+ current_event.dwThreadId);
+ printf_unfiltered (" unknown event code %d\n",
+ current_event.dwDebugEventCode);
+ break;
+ }
+
+ CHECK (child_continue (continue_status, -1));
+ }
+}
+
+/* Attach to process PID, then initialize for debugging it. */
+
+static void
+child_attach (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ BOOL ok;
+
+ if (!args)
+ error_no_arg ("process-id to attach");
+
+ current_event.dwProcessId = strtoul (args, 0, 0);
+
+ ok = DebugActiveProcess (current_event.dwProcessId);
+
+ if (!ok)
+ error ("Can't attach to process.");
+
+ exception_count = 0;
+ event_count = 0;
+
+ if (from_tty)
+ {
+ char *exec_file = (char *) get_exec_file (0);
+
+ if (exec_file)
+ printf_unfiltered ("Attaching to program `%s', %s\n", exec_file,
+ target_pid_to_str (current_event.dwProcessId));
+ else
+ printf_unfiltered ("Attaching to %s\n",
+ target_pid_to_str (current_event.dwProcessId));
+
+ gdb_flush (gdb_stdout);
+ }
+
+ push_target (&child_ops);
+}
+
+static void
+child_detach (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ if (from_tty)
+ {
+ char *exec_file = get_exec_file (0);
+ if (exec_file == 0)
+ exec_file = "";
+ printf_unfiltered ("Detaching from program: %s %s\n", exec_file,
+ target_pid_to_str (inferior_pid));
+ gdb_flush (gdb_stdout);
+ }
+ inferior_pid = 0;
+ unpush_target (&child_ops);
+}
+
+/* Print status information about what we're accessing. */
+
+static void
+child_files_info (ignore)
+ struct target_ops *ignore;
+{
+ printf_unfiltered ("\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.");
+}
+
+/* Start an inferior win32 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;
+{
+ char real_path[MAXPATHLEN];
+ char *winenv;
+ char *temp;
+ int envlen;
+ int i;
+
+ STARTUPINFO si;
+ PROCESS_INFORMATION pi;
+ struct target_waitstatus dummy;
+ BOOL ret;
+ DWORD flags;
+ char *args;
+
+ if (!exec_file)
+ {
+ error ("No executable specified, use `target exec'.\n");
+ }
+
+ memset (&si, 0, sizeof (si));
+ si.cb = sizeof (si);
+
+ cygwin32_conv_to_win32_path (exec_file, real_path);
+
+ flags = DEBUG_ONLY_THIS_PROCESS;
+
+ if (new_group)
+ flags |= CREATE_NEW_PROCESS_GROUP;
+
+ if (new_console)
+ flags |= CREATE_NEW_CONSOLE;
+
+ args = alloca (strlen (real_path) + strlen (allargs) + 2);
+
+ strcpy (args, real_path);
+
+ strcat (args, " ");
+ strcat (args, allargs);
+
+ /* Prepare the environment vars for CreateProcess. */
+ {
+ /* This code use to assume all env vars were file names and would
+ translate them all to win32 style. That obviously doesn't work in the
+ general case. The current rule is that we only translate PATH.
+ We need to handle PATH because we're about to call CreateProcess and
+ it uses PATH to find DLL's. Fortunately PATH has a well-defined value
+ in both posix and win32 environments. cygwin.dll will change it back
+ to posix style if necessary. */
+
+ static const char *conv_path_names[] =
+ {
+ "PATH=",
+ 0
+ };
+
+ /* CreateProcess takes the environment list as a null terminated set of
+ strings (i.e. two nulls terminate the list). */
+
+ /* Get total size for env strings. */
+ for (envlen = 0, i = 0; env[i] && *env[i]; i++)
+ {
+ int j, len;
+
+ for (j = 0; conv_path_names[j]; j++)
+ {
+ len = strlen (conv_path_names[j]);
+ if (strncmp (conv_path_names[j], env[i], len) == 0)
+ {
+ if (cygwin32_posix_path_list_p (env[i] + len))
+ envlen += len
+ + cygwin32_posix_to_win32_path_list_buf_size (env[i] + len);
+ else
+ envlen += strlen (env[i]) + 1;
+ break;
+ }
+ }
+ if (conv_path_names[j] == NULL)
+ envlen += strlen (env[i]) + 1;
+ }
+
+ winenv = alloca (envlen + 1);
+
+ /* Copy env strings into new buffer. */
+ for (temp = winenv, i = 0; env[i] && *env[i]; i++)
+ {
+ int j, len;
+
+ for (j = 0; conv_path_names[j]; j++)
+ {
+ len = strlen (conv_path_names[j]);
+ if (strncmp (conv_path_names[j], env[i], len) == 0)
+ {
+ if (cygwin32_posix_path_list_p (env[i] + len))
+ {
+ memcpy (temp, env[i], len);
+ cygwin32_posix_to_win32_path_list (env[i] + len, temp + len);
+ }
+ else
+ strcpy (temp, env[i]);
+ break;
+ }
+ }
+ if (conv_path_names[j] == NULL)
+ strcpy (temp, env[i]);
+
+ temp += strlen (temp) + 1;
+ }
+
+ /* Final nil string to terminate new env. */
+ *temp = 0;
+ }
+
+ ret = CreateProcess (0,
+ args, /* command line */
+ NULL, /* Security */
+ NULL, /* thread */
+ TRUE, /* inherit handles */
+ flags, /* start flags */
+ winenv,
+ NULL, /* current directory */
+ &si,
+ &pi);
+ if (!ret)
+ error ("Error creating process %s, (error %d)\n", exec_file, GetLastError());
+
+ exception_count = 0;
+ event_count = 0;
+
+ current_process_handle = pi.hProcess;
+ current_event.dwProcessId = pi.dwProcessId;
+ memset (&current_event, 0, sizeof (current_event));
+ inferior_pid = current_event.dwThreadId = pi.dwThreadId;
+ push_target (&child_ops);
+ child_init_thread_list ();
+ init_wait_for_inferior ();
+ clear_proceed_status ();
+ target_terminal_init ();
+ target_terminal_inferior ();
+
+ /* Ignore the first trap */
+ child_wait (inferior_pid, &dummy);
+
+ proceed ((CORE_ADDR) - 1, TARGET_SIGNAL_0, 0);
+}
+
+static void
+child_mourn_inferior ()
+{
+ (void) child_continue (DBG_CONTINUE, -1);
+ unpush_target (&child_ops);
+ generic_mourn_inferior ();
+}
+
+/* Send a SIGINT to the process group. This acts just like the user typed a
+ ^C on the controlling terminal. */
+
+static void
+child_stop ()
+{
+ DEBUG_EVENTS (("gdb: GenerateConsoleCtrlEvent (CTRLC_EVENT, 0)\n"));
+ CHECK (GenerateConsoleCtrlEvent (CTRL_C_EVENT, 0));
+ registers_changed(); /* refresh register state */
+}
+
+int
+child_xfer_memory (CORE_ADDR memaddr, char *our, int len,
+ int write, struct target_ops *target)
+{
+ DWORD done;
+ if (write)
+ {
+ DEBUG_MEM (("gdb: write target memory, %d bytes at 0x%08x\n",
+ len, memaddr));
+ WriteProcessMemory (current_process_handle, (LPVOID) memaddr, our,
+ len, &done);
+ FlushInstructionCache (current_process_handle, (LPCVOID) memaddr, len);
+ }
+ else
+ {
+ DEBUG_MEM (("gdb: read target memory, %d bytes at 0x%08x\n",
+ len, memaddr));
+ ReadProcessMemory (current_process_handle, (LPCVOID) memaddr, our, len,
+ &done);
+ }
+ return done;
+}
+
+void
+child_kill_inferior (void)
+{
+ CHECK (TerminateProcess (current_process_handle, 0));
+
+ for (;;)
+ {
+ if (!child_continue (DBG_CONTINUE, -1))
+ break;
+ if (!WaitForDebugEvent (&current_event, INFINITE))
+ break;
+ if (current_event.dwDebugEventCode == EXIT_PROCESS_DEBUG_EVENT)
+ break;
+ }
+
+ CHECK (CloseHandle (current_process_handle));
+
+ /* this may fail in an attached process so don't check. */
+ (void) CloseHandle (current_thread->h);
+ target_mourn_inferior(); /* or just child_mourn_inferior? */
+}
+
+void
+child_resume (int pid, int step, enum target_signal sig)
+{
+ int i;
+ thread_info *th;
+ DWORD continue_status = last_sig > 0 && last_sig < NSIG ?
+ DBG_EXCEPTION_NOT_HANDLED : DBG_CONTINUE;
+
+ DEBUG_EXEC (("gdb: child_resume (pid=%d, step=%d, sig=%d);\n",
+ pid, step, sig));
+
+ /* Get context for currently selected thread */
+ th = thread_rec (current_event.dwThreadId, FALSE);
+ if (step)
+ {
+#ifdef i386
+ /* Single step by setting t bit */
+ child_fetch_inferior_registers (PS_REGNUM);
+ th->context.EFlags |= FLAG_TRACE_BIT;
+#endif
+ }
+
+ if (th->context.ContextFlags)
+ {
+ CHECK (SetThreadContext (th->h, &th->context));
+ th->context.ContextFlags = 0;
+ }
+
+ /* Allow continuing with the same signal that interrupted us.
+ Otherwise complain. */
+ if (sig && sig != last_sig)
+ fprintf_unfiltered (gdb_stderr, "Can't send signals to the child. signal %d\n", sig);
+
+ last_sig = 0;
+ child_continue (continue_status, pid);
+}
+
+static void
+child_prepare_to_store ()
+{
+ /* Do nothing, since we can store individual regs */
+}
+
+static int
+child_can_run ()
+{
+ return 1;
+}
+
+static void
+child_close ()
+{
+ DEBUG_EVENTS (("gdb: child_close, inferior_pid=%d\n", inferior_pid));
+}
+
+struct target_ops child_ops ;
+
+static void
+init_child_ops(void)
+{
+ child_ops.to_shortname = "child";
+ child_ops.to_longname = "Win32 child process";
+ child_ops.to_doc = "Win32 child process (started by the \"run\" command).";
+ child_ops.to_open = child_open;
+ child_ops.to_close = child_close;
+ child_ops.to_attach = child_attach;
+ child_ops.to_detach = child_detach;
+ child_ops.to_resume = child_resume;
+ child_ops.to_wait = child_wait;
+ child_ops.to_fetch_registers = child_fetch_inferior_registers;
+ child_ops.to_store_registers = child_store_inferior_registers;
+ child_ops.to_prepare_to_store = child_prepare_to_store;
+ child_ops.to_xfer_memory = child_xfer_memory;
+ child_ops.to_files_info = child_files_info;
+ child_ops.to_insert_breakpoint = memory_insert_breakpoint;
+ child_ops.to_remove_breakpoint = memory_remove_breakpoint;
+ child_ops.to_terminal_init = terminal_init_inferior;
+ child_ops.to_terminal_inferior = terminal_inferior;
+ child_ops.to_terminal_ours_for_output = terminal_ours_for_output;
+ child_ops.to_terminal_ours = terminal_ours;
+ child_ops.to_terminal_info = child_terminal_info;
+ child_ops.to_kill = child_kill_inferior;
+ child_ops.to_load = 0;
+ child_ops.to_lookup_symbol = 0;
+ child_ops.to_create_inferior = child_create_inferior;
+ child_ops.to_mourn_inferior = child_mourn_inferior;
+ child_ops.to_can_run = child_can_run;
+ child_ops.to_notice_signals = 0;
+ child_ops.to_thread_alive = win32_child_thread_alive;
+ child_ops.to_stop = child_stop;
+ child_ops.to_stratum = process_stratum;
+ child_ops.DONT_USE = 0;
+ child_ops.to_has_all_memory = 1;
+ child_ops.to_has_memory = 1;
+ child_ops.to_has_stack = 1;
+ child_ops.to_has_registers = 1;
+ child_ops.to_has_execution = 1;
+ child_ops.to_sections = 0;
+ child_ops.to_sections_end = 0;
+ child_ops.to_magic = OPS_MAGIC;
+}
+
+void
+_initialize_inftarg ()
+{
+ struct cmd_list_element *c;
+ init_child_ops() ;
+
+ add_show_from_set
+ (add_set_cmd ("new-console", class_support, var_boolean,
+ (char *) &new_console,
+ "Set creation of new console when creating child process.",
+ &setlist),
+ &showlist);
+
+ add_show_from_set
+ (add_set_cmd ("new-group", class_support, var_boolean,
+ (char *) &new_group,
+ "Set creation of new group when creating child process.",
+ &setlist),
+ &showlist);
+
+ add_show_from_set
+ (add_set_cmd ("debugexec", class_support, var_boolean,
+ (char *) &debug_exec,
+ "Set whether to display execution in child process.",
+ &setlist),
+ &showlist);
+
+ add_show_from_set
+ (add_set_cmd ("debugevents", class_support, var_boolean,
+ (char *) &debug_events,
+ "Set whether to display kernel events in child process.",
+ &setlist),
+ &showlist);
+
+ add_show_from_set
+ (add_set_cmd ("debugmemory", class_support, var_boolean,
+ (char *) &debug_memory,
+ "Set whether to display memory accesses in child process.",
+ &setlist),
+ &showlist);
+
+ add_show_from_set
+ (add_set_cmd ("debugexceptions", class_support, var_boolean,
+ (char *) &debug_exceptions,
+ "Set whether to display kernel exceptions in child process.",
+ &setlist),
+ &showlist);
+
+ add_target (&child_ops);
+}
+
+/* Determine if the thread referenced by "pid" is alive
+ by "polling" it. If WaitForSingleObject returns WAIT_OBJECT_0
+ it means that the pid has died. Otherwise it is assumed to be alive. */
+static int
+win32_child_thread_alive (int pid)
+{
+ return WaitForSingleObject(thread_rec (pid, FALSE)->h, 0) == WAIT_OBJECT_0 ?
+ FALSE : TRUE;
+}
+
+/* Convert pid to printable format. */
+char *
+cygwin_pid_to_str (int pid)
+{
+ static char buf[80];
+ if (pid == current_event.dwProcessId)
+ sprintf (buf, "process %d", pid);
+ else
+ sprintf (buf, "thread %d.0x%x", current_event.dwProcessId, pid);
+ return buf;
+}
diff --git a/gdb/xcoffread.c b/gdb/xcoffread.c
new file mode 100644
index 00000000000..0cf93714821
--- /dev/null
+++ b/gdb/xcoffread.c
@@ -0,0 +1,2811 @@
+/* Read AIX xcoff symbol tables and convert to internal format, for GDB.
+ Copyright 1986, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 1997
+ Free Software Foundation, Inc.
+ Derived from coffread.c, dbxread.c, and a lot of hacking.
+ Contributed by IBM Corporation.
+
+This file is part of GDB.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "bfd.h"
+
+#include <sys/types.h>
+#include <fcntl.h>
+#include <ctype.h>
+#include "gdb_string.h"
+
+#include <sys/param.h>
+#ifndef NO_SYS_FILE
+#include <sys/file.h>
+#endif
+#include "gdb_stat.h"
+
+#include "coff/internal.h"
+#include "libcoff.h" /* FIXME, internal data from BFD */
+#include "coff/rs6000.h"
+
+#include "symtab.h"
+#include "gdbtypes.h"
+#include "symfile.h"
+#include "objfiles.h"
+#include "buildsym.h"
+#include "stabsread.h"
+#include "expression.h"
+#include "language.h" /* Needed inside partial-stab.h */
+#include "complaints.h"
+
+#include "gdb-stabs.h"
+
+/* For interface with stabsread.c. */
+#include "aout/stab_gnu.h"
+
+/* For interface with partial-stab.h. */
+#define N_UNDF 0 /* Undefined symbol */
+#undef N_ABS
+#define N_ABS 2
+#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_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. */
+
+/* We put a pointer to this structure in the read_symtab_private field
+ of the psymtab. */
+
+struct symloc {
+
+ /* First symbol number for this file. */
+
+ int first_symnum;
+
+ /* Number of symbols in 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). If numsyms is 0, the only
+ reason for this thing's existence is the dependency list. Nothing
+ else will happen when it is read in. */
+
+ int numsyms;
+
+ /* Position of the start of the line number information for this psymtab. */
+ unsigned int lineno_off;
+};
+
+/* Remember what we deduced to be the source language of this psymtab. */
+
+static enum language psymtab_language = language_unknown;
+
+
+/* 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 */
+ long c_value;
+ unsigned char c_sclass;
+ int c_secnum;
+ unsigned int c_type;
+};
+
+/* last function's saved coff symbol `cs' */
+
+static struct coff_symbol fcn_cs_saved;
+
+static bfd *symfile_bfd;
+
+/* Core address of start and end of text of current source file.
+ This is calculated from the first function seen after a C_FILE
+ symbol. */
+
+
+static CORE_ADDR cur_src_end_addr;
+
+/* Core address of the end of the first object file. */
+
+static CORE_ADDR first_object_file_end;
+
+/* initial symbol-table-debug-string vector length */
+
+#define INITIAL_STABVECTOR_LENGTH 40
+
+/* Nonzero if within a function (so symbols should be local,
+ if nothing says specifically). */
+
+int within_function;
+
+/* Size of a COFF symbol. I think it is always 18, so I'm not sure
+ there is any reason not to just use a #define, but might as well
+ ask BFD for the size and store it here, I guess. */
+
+static unsigned local_symesz;
+
+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 */
+
+ /* Pointer to the string table. */
+ char *strtbl;
+
+ /* Pointer to debug section. */
+ char *debugsec;
+
+ /* Pointer to the a.out symbol table. */
+ char *symtbl;
+
+ /* Number of symbols in symtbl. */
+ int symtbl_num_syms;
+
+ /* Offset in data section to TOC anchor. */
+ CORE_ADDR toc_offset;
+};
+
+static struct complaint storclass_complaint =
+ {"Unexpected storage class: %d", 0, 0};
+
+static struct complaint bf_notfound_complaint =
+ {"line numbers off, `.bf' symbol not found", 0, 0};
+
+static struct complaint ef_complaint =
+ {"Mismatched .ef symbol ignored starting at symnum %d", 0, 0};
+
+static struct complaint eb_complaint =
+ {"Mismatched .eb symbol ignored starting at symnum %d", 0, 0};
+
+static void
+xcoff_initial_scan PARAMS ((struct objfile *, struct section_offsets *, int));
+
+static void
+scan_xcoff_symtab PARAMS ((struct section_offsets *, struct objfile *));
+
+static char *
+xcoff_next_symbol_text PARAMS ((struct objfile *));
+
+static void
+record_include_begin PARAMS ((struct coff_symbol *));
+
+static void
+enter_line_range PARAMS ((struct subfile *, unsigned, unsigned,
+ CORE_ADDR, CORE_ADDR, unsigned *));
+
+static void
+init_stringtab PARAMS ((bfd *, file_ptr, struct objfile *));
+
+static void
+xcoff_symfile_init PARAMS ((struct objfile *));
+
+static void
+xcoff_new_init PARAMS ((struct objfile *));
+
+static void
+xcoff_symfile_finish PARAMS ((struct objfile *));
+
+static struct section_offsets *
+xcoff_symfile_offsets PARAMS ((struct objfile *, CORE_ADDR));
+
+static void
+find_linenos PARAMS ((bfd *, sec_ptr, PTR));
+
+static char *
+coff_getfilename PARAMS ((union internal_auxent *, struct objfile *));
+
+static void
+read_symbol PARAMS ((struct internal_syment *, int));
+
+static int
+read_symbol_lineno PARAMS ((int));
+
+static int
+read_symbol_nvalue PARAMS ((int));
+
+static struct symbol *
+process_xcoff_symbol PARAMS ((struct coff_symbol *, struct objfile *));
+
+static void
+read_xcoff_symtab PARAMS ((struct partial_symtab *));
+
+#if 0
+static void
+add_stab_to_list PARAMS ((char *, struct pending_stabs **));
+#endif
+
+static int
+compare_lte PARAMS ((const void *, const void *));
+
+static struct linetable *
+arrange_linetable PARAMS ((struct linetable *));
+
+static void
+record_include_end PARAMS ((struct coff_symbol *));
+
+static void
+process_linenos PARAMS ((CORE_ADDR, CORE_ADDR));
+
+
+/* Translate from a COFF section number (target_index) to a SECT_OFF_*
+ code. */
+static int secnum_to_section PARAMS ((int, struct objfile *));
+static asection * secnum_to_bfd_section PARAMS ((int, struct objfile *));
+
+struct find_targ_sec_arg {
+ int targ_index;
+ int *resultp;
+ asection **bfd_sect;
+};
+
+static void find_targ_sec PARAMS ((bfd *, asection *, void *));
+
+static void find_targ_sec (abfd, sect, obj)
+ bfd *abfd;
+ asection *sect;
+ PTR obj;
+{
+ struct find_targ_sec_arg *args = (struct find_targ_sec_arg *)obj;
+ if (sect->target_index == args->targ_index)
+ {
+ /* This is the section. Figure out what SECT_OFF_* code it is. */
+ if (bfd_get_section_flags (abfd, sect) & SEC_CODE)
+ *args->resultp = SECT_OFF_TEXT;
+ else if (bfd_get_section_flags (abfd, sect) & SEC_LOAD)
+ *args->resultp = SECT_OFF_DATA;
+ else
+ *args->resultp = SECT_OFF_BSS;
+ *args->bfd_sect = sect;
+ }
+}
+
+/* Return the section number (SECT_OFF_*) that CS points to. */
+static int
+secnum_to_section (secnum, objfile)
+ int secnum;
+ struct objfile *objfile;
+{
+ int off = SECT_OFF_TEXT;
+ asection *sect = NULL;
+ struct find_targ_sec_arg args;
+ args.targ_index = secnum;
+ args.resultp = &off;
+ args.bfd_sect = &sect;
+ bfd_map_over_sections (objfile->obfd, find_targ_sec, &args);
+ return off;
+}
+
+/* Return the BFD section that CS points to. */
+static asection *
+secnum_to_bfd_section (secnum, objfile)
+ int secnum;
+ struct objfile *objfile;
+{
+ int off = SECT_OFF_TEXT;
+ asection *sect = NULL;
+ struct find_targ_sec_arg args;
+ args.targ_index = secnum;
+ args.resultp = &off;
+ args.bfd_sect = &sect;
+ bfd_map_over_sections (objfile->obfd, find_targ_sec, &args);
+ return sect;
+}
+
+/* add a given stab string into given stab vector. */
+
+#if 0
+
+static void
+add_stab_to_list (stabname, stabvector)
+char *stabname;
+struct pending_stabs **stabvector;
+{
+ if ( *stabvector == NULL) {
+ *stabvector = (struct pending_stabs *)
+ xmalloc (sizeof (struct pending_stabs) +
+ INITIAL_STABVECTOR_LENGTH * sizeof (char*));
+ (*stabvector)->count = 0;
+ (*stabvector)->length = INITIAL_STABVECTOR_LENGTH;
+ }
+ else if ((*stabvector)->count >= (*stabvector)->length) {
+ (*stabvector)->length += INITIAL_STABVECTOR_LENGTH;
+ *stabvector = (struct pending_stabs *)
+ xrealloc ((char *) *stabvector, sizeof (struct pending_stabs) +
+ (*stabvector)->length * sizeof (char*));
+ }
+ (*stabvector)->stab [(*stabvector)->count++] = stabname;
+}
+
+#endif
+
+
+/* Linenos are processed on a file-by-file basis.
+
+ Two reasons:
+
+ 1) xlc (IBM's native c compiler) postpones static function code
+ emission to the end of a compilation unit. This way it can
+ determine if those functions (statics) are needed or not, and
+ can do some garbage collection (I think). This makes line
+ numbers and corresponding addresses unordered, and we end up
+ with a line table like:
+
+
+ lineno addr
+ foo() 10 0x100
+ 20 0x200
+ 30 0x300
+
+ foo3() 70 0x400
+ 80 0x500
+ 90 0x600
+
+ static foo2()
+ 40 0x700
+ 50 0x800
+ 60 0x900
+
+ and that breaks gdb's binary search on line numbers, if the
+ above table is not sorted on line numbers. And that sort
+ should be on function based, since gcc can emit line numbers
+ like:
+
+ 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.
+
+ arrange_linetable() will do this sorting.
+
+ 2) aix symbol table might look like:
+
+ c_file // beginning of a new file
+ .bi // beginning of include file
+ .ei // end of include file
+ .bi
+ .ei
+
+ basically, .bi/.ei pairs do not necessarily encapsulate
+ their scope. They need to be recorded, and processed later
+ on when we come the end of the compilation unit.
+ Include table (inclTable) and process_linenos() handle
+ that. */
+
+/* compare line table entry addresses. */
+
+static int
+compare_lte (lte1p, lte2p)
+ const void *lte1p;
+ const void *lte2p;
+{
+ struct linetable_entry *lte1 = (struct linetable_entry *) lte1p;
+ struct linetable_entry *lte2 = (struct linetable_entry *) lte2p;
+ return lte1->pc - lte2->pc;
+}
+
+/* Given a line table with function entries are marked, arrange its functions
+ in ascending order and strip off function entry markers and return it in
+ a newly created table. If the old one is good enough, return the old one. */
+/* FIXME: I think all this stuff can be replaced by just passing
+ sort_linevec = 1 to end_symtab. */
+
+static struct linetable *
+arrange_linetable (oldLineTb)
+ struct linetable *oldLineTb; /* old linetable */
+{
+ int ii, jj,
+ newline, /* new line count */
+ function_count; /* # of functions */
+
+ struct linetable_entry *fentry; /* function entry vector */
+ int fentry_size; /* # of function entries */
+ struct linetable *newLineTb; /* new line table */
+
+#define NUM_OF_FUNCTIONS 20
+
+ fentry_size = NUM_OF_FUNCTIONS;
+ fentry = (struct linetable_entry*)
+ xmalloc (fentry_size * sizeof (struct linetable_entry));
+
+ for (function_count=0, ii=0; ii <oldLineTb->nitems; ++ii) {
+
+ if (oldLineTb->item[ii].line == 0) { /* function entry found. */
+
+ if (function_count >= fentry_size) { /* make sure you have room. */
+ fentry_size *= 2;
+ fentry = (struct linetable_entry*)
+ xrealloc (fentry, fentry_size * sizeof (struct linetable_entry));
+ }
+ fentry[function_count].line = ii;
+ fentry[function_count].pc = oldLineTb->item[ii].pc;
+ ++function_count;
+ }
+ }
+
+ if (function_count == 0) {
+ free (fentry);
+ return oldLineTb;
+ }
+ else if (function_count > 1)
+ qsort (fentry, function_count, sizeof(struct linetable_entry), compare_lte);
+
+ /* allocate a new line table. */
+ newLineTb = (struct linetable *)
+ xmalloc
+ (sizeof (struct linetable) +
+ (oldLineTb->nitems - function_count) * sizeof (struct linetable_entry));
+
+ /* if line table does not start with a function beginning, copy up until
+ a function begin. */
+
+ newline = 0;
+ if (oldLineTb->item[0].line != 0)
+ for (newline=0;
+ newline < oldLineTb->nitems && oldLineTb->item[newline].line; ++newline)
+ newLineTb->item[newline] = oldLineTb->item[newline];
+
+ /* Now copy function lines one by one. */
+
+ for (ii=0; ii < function_count; ++ii) {
+ for (jj = fentry[ii].line + 1;
+ jj < oldLineTb->nitems && oldLineTb->item[jj].line != 0;
+ ++jj, ++newline)
+ newLineTb->item[newline] = oldLineTb->item[jj];
+ }
+ free (fentry);
+ newLineTb->nitems = oldLineTb->nitems - function_count;
+ return newLineTb;
+}
+
+/* include file support: C_BINCL/C_EINCL pairs will be kept in the
+ following `IncludeChain'. At the end of each symtab (end_symtab),
+ we will determine if we should create additional symtab's to
+ represent if (the include files. */
+
+
+typedef struct _inclTable {
+ char *name; /* include filename */
+
+ /* Offsets to the line table. end points to the last entry which is
+ part of this include file. */
+ int begin, end;
+
+ struct subfile *subfile;
+ unsigned funStartLine; /* start line # of its function */
+} InclTable;
+
+#define INITIAL_INCLUDE_TABLE_LENGTH 20
+static InclTable *inclTable; /* global include table */
+static int inclIndx; /* last entry to table */
+static int inclLength; /* table length */
+static int inclDepth; /* nested include depth */
+
+static void allocate_include_entry PARAMS ((void));
+
+static void
+record_include_begin (cs)
+struct coff_symbol *cs;
+{
+ if (inclDepth)
+ {
+ /* In xcoff, we assume include files cannot be nested (not in .c files
+ of course, but in corresponding .s files.). */
+
+ /* This can happen with old versions of GCC.
+ GCC 2.3.3-930426 does not exhibit this on a test case which
+ a user said produced the message for him. */
+ static struct complaint msg = {"Nested C_BINCL symbols", 0, 0};
+ complain (&msg);
+ }
+ ++inclDepth;
+
+ allocate_include_entry ();
+
+ inclTable [inclIndx].name = cs->c_name;
+ inclTable [inclIndx].begin = cs->c_value;
+}
+
+static void
+record_include_end (cs)
+struct coff_symbol *cs;
+{
+ InclTable *pTbl;
+
+ if (inclDepth == 0)
+ {
+ static struct complaint msg = {"Mismatched C_BINCL/C_EINCL pair", 0, 0};
+ complain (&msg);
+ }
+
+ allocate_include_entry ();
+
+ pTbl = &inclTable [inclIndx];
+ pTbl->end = cs->c_value;
+
+ --inclDepth;
+ ++inclIndx;
+}
+
+static void
+allocate_include_entry ()
+{
+ if (inclTable == NULL)
+ {
+ inclTable = (InclTable *)
+ xmalloc (sizeof (InclTable) * INITIAL_INCLUDE_TABLE_LENGTH);
+ memset (inclTable,
+ '\0', sizeof (InclTable) * INITIAL_INCLUDE_TABLE_LENGTH);
+ inclLength = INITIAL_INCLUDE_TABLE_LENGTH;
+ inclIndx = 0;
+ }
+ else if (inclIndx >= inclLength)
+ {
+ inclLength += INITIAL_INCLUDE_TABLE_LENGTH;
+ inclTable = (InclTable *)
+ xrealloc (inclTable, sizeof (InclTable) * inclLength);
+ memset (inclTable + inclLength - INITIAL_INCLUDE_TABLE_LENGTH,
+ '\0', sizeof (InclTable)*INITIAL_INCLUDE_TABLE_LENGTH);
+ }
+}
+
+/* Global variable to pass the psymtab down to all the routines involved
+ in psymtab to symtab processing. */
+static struct partial_symtab *this_symtab_psymtab;
+
+/* given the start and end addresses of a compilation unit (or a csect,
+ at times) process its lines and create appropriate line vectors. */
+
+static void
+process_linenos (start, end)
+ CORE_ADDR start, end;
+{
+ int offset, ii;
+ file_ptr max_offset =
+ ((struct coff_symfile_info *)this_symtab_psymtab->objfile->sym_private)
+ ->max_lineno_offset;
+
+ /* subfile structure for the main compilation unit. */
+ struct subfile main_subfile;
+
+ /* In the main source file, any time we see a function entry, we
+ reset this variable to function's absolute starting line number.
+ All the following line numbers in the function are relative to
+ this, and we record absolute line numbers in record_line(). */
+
+ unsigned int main_source_baseline = 0;
+
+ unsigned *firstLine;
+
+ offset =
+ ((struct symloc *)this_symtab_psymtab->read_symtab_private)->lineno_off;
+ if (offset == 0)
+ goto return_after_cleanup;
+
+ memset (&main_subfile, '\0', sizeof (main_subfile));
+
+ if (inclIndx == 0)
+ /* All source lines were in the main source file. None in include files. */
+
+ enter_line_range (&main_subfile, offset, 0, start, end,
+ &main_source_baseline);
+
+ else
+ {
+ /* There was source with line numbers in include files. */
+ main_source_baseline = 0;
+ for (ii=0; ii < inclIndx; ++ii)
+ {
+ struct subfile *tmpSubfile;
+
+ /* If there is main file source before include file, enter it. */
+ if (offset < inclTable[ii].begin)
+ {
+ enter_line_range
+ (&main_subfile, offset, inclTable[ii].begin - LINESZ,
+ start, 0, &main_source_baseline);
+ }
+
+ /* Have a new subfile for the include file. */
+
+ tmpSubfile = inclTable[ii].subfile =
+ (struct subfile *) xmalloc (sizeof (struct subfile));
+
+ memset (tmpSubfile, '\0', sizeof (struct subfile));
+ firstLine = &(inclTable[ii].funStartLine);
+
+ /* Enter include file's lines now. */
+ enter_line_range (tmpSubfile, inclTable[ii].begin,
+ inclTable[ii].end, start, 0, firstLine);
+
+ if (offset <= inclTable[ii].end)
+ offset = inclTable[ii].end + LINESZ;
+ }
+
+ /* All the include files' line have been processed at this point. Now,
+ enter remaining lines of the main file, if any left. */
+ if (offset < max_offset + 1 - LINESZ)
+ {
+ enter_line_range (&main_subfile, offset, 0, start, end,
+ &main_source_baseline);
+ }
+ }
+
+ /* Process main file's line numbers. */
+ if (main_subfile.line_vector)
+ {
+ struct linetable *lineTb, *lv;
+
+ lv = main_subfile.line_vector;
+
+ /* Line numbers are not necessarily ordered. xlc compilation will
+ put static function to the end. */
+
+ lineTb = arrange_linetable (lv);
+ if (lv == lineTb)
+ {
+ current_subfile->line_vector = (struct linetable *)
+ xrealloc (lv, (sizeof (struct linetable)
+ + lv->nitems * sizeof (struct linetable_entry)));
+ }
+ else
+ {
+ free (lv);
+ current_subfile->line_vector = lineTb;
+ }
+
+ current_subfile->line_vector_length =
+ current_subfile->line_vector->nitems;
+ }
+
+ /* Now, process included files' line numbers. */
+
+ for (ii=0; ii < inclIndx; ++ii)
+ {
+ if ((inclTable[ii].subfile)->line_vector) /* Useless if!!! FIXMEmgo */
+ {
+ struct linetable *lineTb, *lv;
+
+ lv = (inclTable[ii].subfile)->line_vector;
+
+ /* Line numbers are not necessarily ordered. xlc compilation will
+ put static function to the end. */
+
+ lineTb = arrange_linetable (lv);
+
+ push_subfile ();
+
+ /* For the same include file, we might want to have more than one
+ subfile. This happens if we have something like:
+
+ ......
+ #include "foo.h"
+ ......
+ #include "foo.h"
+ ......
+
+ while foo.h including code in it. (stupid but possible)
+ Since start_subfile() looks at the name and uses an
+ existing one if finds, we need to provide a fake name and
+ fool it. */
+
+#if 0
+ start_subfile (inclTable[ii].name, (char*)0);
+#else
+ {
+ /* Pick a fake name that will produce the same results as this
+ one when passed to deduce_language_from_filename. Kludge on
+ top of kludge. */
+ char *fakename = strrchr (inclTable[ii].name, '.');
+ if (fakename == NULL)
+ fakename = " ?";
+ start_subfile (fakename, (char*)0);
+ free (current_subfile->name);
+ }
+ current_subfile->name = strdup (inclTable[ii].name);
+#endif
+
+ if (lv == lineTb)
+ {
+ current_subfile->line_vector =
+ (struct linetable *) xrealloc
+ (lv, (sizeof (struct linetable)
+ + lv->nitems * sizeof (struct linetable_entry)));
+
+ }
+ else
+ {
+ free (lv);
+ current_subfile->line_vector = lineTb;
+ }
+
+ current_subfile->line_vector_length =
+ current_subfile->line_vector->nitems;
+ start_subfile (pop_subfile (), (char*)0);
+ }
+ }
+
+ return_after_cleanup:
+
+ /* We don't want to keep alloc/free'ing the global include file table. */
+ inclIndx = 0;
+
+ /* Start with a fresh subfile structure for the next file. */
+ memset (&main_subfile, '\0', sizeof (struct subfile));
+}
+
+void
+aix_process_linenos ()
+{
+ /* process line numbers and enter them into line vector */
+ process_linenos (last_source_start_addr, cur_src_end_addr);
+}
+
+
+/* Enter a given range of lines into the line vector.
+ can be called in the following two ways:
+ enter_line_range (subfile, beginoffset, endoffset, startaddr, 0, firstLine) or
+ enter_line_range (subfile, beginoffset, 0, startaddr, endaddr, firstLine)
+
+ endoffset points to the last line table entry that we should pay
+ attention to. */
+
+static void
+enter_line_range (subfile, beginoffset, endoffset, startaddr, endaddr,
+ firstLine)
+ struct subfile *subfile;
+ unsigned beginoffset, endoffset; /* offsets to line table */
+ CORE_ADDR startaddr, endaddr;
+ unsigned *firstLine;
+{
+ unsigned int curoffset;
+ CORE_ADDR addr;
+ struct external_lineno ext_lnno;
+ struct internal_lineno int_lnno;
+ unsigned int limit_offset;
+ bfd *abfd;
+
+ if (endoffset == 0 && startaddr == 0 && endaddr == 0)
+ return;
+ curoffset = beginoffset;
+ limit_offset =
+ ((struct coff_symfile_info *)this_symtab_psymtab->objfile->sym_private)
+ ->max_lineno_offset;
+
+ if (endoffset != 0)
+ {
+ if (endoffset >= limit_offset)
+ {
+ static struct complaint msg =
+ {"Bad line table offset in C_EINCL directive", 0, 0};
+ complain (&msg);
+ return;
+ }
+ limit_offset = endoffset;
+ }
+ else
+ limit_offset -= 1;
+ abfd = this_symtab_psymtab->objfile->obfd;
+
+ while (curoffset <= limit_offset)
+ {
+ bfd_seek (abfd, curoffset, SEEK_SET);
+ bfd_read (&ext_lnno, sizeof (struct external_lineno), 1, abfd);
+ bfd_coff_swap_lineno_in (abfd, &ext_lnno, &int_lnno);
+
+ /* Find the address this line represents. */
+ addr = (int_lnno.l_lnno
+ ? int_lnno.l_addr.l_paddr
+ : read_symbol_nvalue (int_lnno.l_addr.l_symndx));
+ addr += ANOFFSET (this_symtab_psymtab->objfile->section_offsets,
+ SECT_OFF_TEXT);
+
+ if (addr < startaddr || (endaddr && addr >= endaddr))
+ return;
+
+ if (int_lnno.l_lnno == 0)
+ {
+ *firstLine = read_symbol_lineno (int_lnno.l_addr.l_symndx);
+ record_line (subfile, 0, addr);
+ --(*firstLine);
+ }
+ else
+ record_line (subfile, *firstLine + int_lnno.l_lnno, addr);
+ curoffset += LINESZ;
+ }
+}
+
+
+/* Save the vital information 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. */
+
+#define complete_symtab(name, start_addr) { \
+ last_source_file = savestring (name, strlen (name)); \
+ last_source_start_addr = start_addr; \
+}
+
+
+/* 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. */
+
+/* Reading symbol table has to be fast! Keep the followings as macros, rather
+ than functions. */
+
+#define RECORD_MINIMAL_SYMBOL(NAME, ADDR, TYPE, SECTION, OBJFILE) \
+{ \
+ char *namestr; \
+ namestr = (NAME); \
+ if (namestr[0] == '.') ++namestr; \
+ prim_record_minimal_symbol_and_info (namestr, (ADDR), (TYPE), \
+ (char *)NULL, (SECTION), (asection *)NULL, (OBJFILE)); \
+ misc_func_recorded = 1; \
+}
+
+
+/* xcoff has static blocks marked in `.bs', `.es' pairs. They cannot be
+ nested. At any given time, a symbol can only be in one static block.
+ This is the base address of current static block, zero if non exists. */
+
+static int static_block_base = 0;
+
+/* Section number for the current static block. */
+
+static int static_block_section = -1;
+
+/* true if space for symbol name has been allocated. */
+
+static int symname_alloced = 0;
+
+/* Next symbol to read. Pointer into raw seething symbol table. */
+
+static char *raw_symbol;
+
+/* This is the function which stabsread.c calls to get symbol
+ continuations. */
+
+static char *
+xcoff_next_symbol_text (objfile)
+ struct objfile *objfile;
+{
+ struct internal_syment symbol;
+ static struct complaint msg =
+ {"Unexpected symbol continuation", 0, 0};
+ char *retval;
+ /* FIXME: is this the same as the passed arg? */
+ objfile = this_symtab_psymtab->objfile;
+
+ bfd_coff_swap_sym_in (objfile->obfd, raw_symbol, &symbol);
+ if (symbol.n_zeroes)
+ {
+ complain (&msg);
+
+ /* Return something which points to '\0' and hope the symbol reading
+ code does something reasonable. */
+ retval = "";
+ }
+ else if (symbol.n_sclass & 0x80)
+ {
+ retval =
+ ((struct coff_symfile_info *)objfile->sym_private)->debugsec
+ + symbol.n_offset;
+ raw_symbol +=
+ coff_data (objfile->obfd)->local_symesz;
+ ++symnum;
+ }
+ else
+ {
+ complain (&msg);
+
+ /* Return something which points to '\0' and hope the symbol reading
+ code does something reasonable. */
+ retval = "";
+ }
+ return retval;
+}
+
+/* Read symbols for a given partial symbol table. */
+
+static void
+read_xcoff_symtab (pst)
+ struct partial_symtab *pst;
+{
+ struct objfile *objfile = pst->objfile;
+ bfd *abfd = objfile->obfd;
+ char *raw_auxptr; /* Pointer to first raw aux entry for sym */
+ char *strtbl = ((struct coff_symfile_info *)objfile->sym_private)->strtbl;
+ char *debugsec =
+ ((struct coff_symfile_info *)objfile->sym_private)->debugsec;
+
+ struct internal_syment symbol[1];
+ union internal_auxent main_aux;
+ struct coff_symbol cs[1];
+ CORE_ADDR file_start_addr = 0;
+ CORE_ADDR file_end_addr = 0;
+
+ int next_file_symnum = -1;
+ unsigned int max_symnum;
+ int just_started = 1;
+ int depth = 0;
+ int fcn_start_addr = 0;
+
+ struct coff_symbol fcn_stab_saved;
+
+ /* fcn_cs_saved is global because process_xcoff_symbol needs it. */
+ union internal_auxent fcn_aux_saved;
+ struct context_stack *new;
+
+ char *filestring = " _start_ "; /* Name of the current file. */
+
+ char *last_csect_name; /* last seen csect's name and value */
+ CORE_ADDR last_csect_val;
+ int last_csect_sec;
+
+ this_symtab_psymtab = pst;
+
+ /* Get the appropriate COFF "constants" related to the file we're
+ handling. */
+ local_symesz = coff_data (abfd)->local_symesz;
+
+ last_source_file = NULL;
+ last_csect_name = 0;
+ last_csect_val = 0;
+
+ start_stabs ();
+ start_symtab (filestring, (char *)NULL, file_start_addr);
+ record_debugformat ("XCOFF");
+ symnum = ((struct symloc *)pst->read_symtab_private)->first_symnum;
+ max_symnum =
+ symnum + ((struct symloc *)pst->read_symtab_private)->numsyms;
+ first_object_file_end = 0;
+
+ raw_symbol =
+ ((struct coff_symfile_info *) objfile->sym_private)->symtbl
+ + symnum * local_symesz;
+
+ while (symnum < max_symnum)
+ {
+
+ QUIT; /* make this command interruptable. */
+
+ /* READ_ONE_SYMBOL (symbol, cs, symname_alloced); */
+ /* read one symbol into `cs' structure. After processing the
+ whole symbol table, only string table will be kept in memory,
+ symbol table and debug section of xcoff will be freed. Thus
+ we can mark symbols with names in string table as
+ `alloced'. */
+ {
+ int ii;
+
+ /* Swap and align the symbol into a reasonable C structure. */
+ bfd_coff_swap_sym_in (abfd, raw_symbol, symbol);
+
+ cs->c_symnum = symnum;
+ cs->c_naux = symbol->n_numaux;
+ if (symbol->n_zeroes)
+ {
+ symname_alloced = 0;
+ /* We must use the original, unswapped, name here so the name field
+ pointed to by cs->c_name will persist throughout xcoffread. If
+ we use the new field, it gets overwritten for each symbol. */
+ cs->c_name = ((struct external_syment *)raw_symbol)->e.e_name;
+ /* If it's exactly E_SYMNMLEN characters long it isn't
+ '\0'-terminated. */
+ if (cs->c_name[E_SYMNMLEN - 1] != '\0')
+ {
+ char *p;
+ p = obstack_alloc (&objfile->symbol_obstack, E_SYMNMLEN + 1);
+ strncpy (p, cs->c_name, E_SYMNMLEN);
+ p[E_SYMNMLEN] = '\0';
+ cs->c_name = p;
+ symname_alloced = 1;
+ }
+ }
+ else if (symbol->n_sclass & 0x80)
+ {
+ cs->c_name = debugsec + symbol->n_offset;
+ symname_alloced = 0;
+ }
+ else
+ {
+ /* in string table */
+ cs->c_name = strtbl + (int)symbol->n_offset;
+ symname_alloced = 1;
+ }
+ cs->c_value = symbol->n_value;
+ cs->c_sclass = symbol->n_sclass;
+ cs->c_secnum = symbol->n_scnum;
+ cs->c_type = (unsigned)symbol->n_type;
+
+ raw_symbol += coff_data (abfd)->local_symesz;
+ ++symnum;
+
+ /* Save addr of first aux entry. */
+ raw_auxptr = raw_symbol;
+
+ /* Skip all the auxents associated with this symbol. */
+ for (ii = symbol->n_numaux; ii; --ii)
+ {
+ raw_symbol += coff_data (abfd)->local_auxesz;
+ ++symnum;
+ }
+ }
+
+ /* if symbol name starts with ".$" or "$", ignore it. */
+ if (cs->c_name[0] == '$'
+ || (cs->c_name[1] == '$' && cs->c_name[0] == '.'))
+ continue;
+
+ if (cs->c_symnum == next_file_symnum && cs->c_sclass != C_FILE)
+ {
+ if (last_source_file)
+ {
+ pst->symtab =
+ end_symtab (cur_src_end_addr, objfile, SECT_OFF_TEXT);
+ end_stabs ();
+ }
+
+ start_stabs ();
+ start_symtab ("_globals_", (char *)NULL, (CORE_ADDR)0);
+ record_debugformat ("XCOFF");
+ cur_src_end_addr = first_object_file_end;
+ /* done with all files, everything from here on is globals */
+ }
+
+ /* if explicitly specified as a function, treat is as one. */
+ if (ISFCN(cs->c_type) && cs->c_sclass != C_TPDEF)
+ {
+ bfd_coff_swap_aux_in (abfd, raw_auxptr, cs->c_type, cs->c_sclass,
+ 0, cs->c_naux, &main_aux);
+ goto function_entry_point;
+ }
+
+ if ((cs->c_sclass == C_EXT || cs->c_sclass == C_HIDEXT)
+ && cs->c_naux == 1)
+ {
+ /* Dealing with a symbol with a csect entry. */
+
+#define CSECT(PP) ((PP)->x_csect)
+#define CSECT_LEN(PP) (CSECT(PP).x_scnlen.l)
+#define CSECT_ALIGN(PP) (SMTYP_ALIGN(CSECT(PP).x_smtyp))
+#define CSECT_SMTYP(PP) (SMTYP_SMTYP(CSECT(PP).x_smtyp))
+#define CSECT_SCLAS(PP) (CSECT(PP).x_smclas)
+
+ /* Convert the auxent to something we can access. */
+ bfd_coff_swap_aux_in (abfd, raw_auxptr, cs->c_type, cs->c_sclass,
+ 0, cs->c_naux, &main_aux);
+
+ switch (CSECT_SMTYP (&main_aux))
+ {
+
+ case XTY_ER:
+ /* Ignore all external references. */
+ continue;
+
+ case XTY_SD:
+ /* A section description. */
+ {
+ switch (CSECT_SCLAS (&main_aux))
+ {
+
+ case XMC_PR:
+ {
+
+ /* A program csect is seen. We have to allocate one
+ symbol table for each program csect. Normally gdb
+ prefers one symtab for each source file. In case
+ of AIX, one source file might include more than one
+ [PR] csect, and they don't have to be adjacent in
+ terms of the space they occupy in memory. Thus, one
+ single source file might get fragmented in the
+ memory and gdb's file start and end address
+ approach does not work! GCC (and I think xlc) seem
+ to put all the code in the unnamed program csect. */
+
+ if (last_csect_name)
+ {
+ complete_symtab (filestring, file_start_addr);
+ cur_src_end_addr = file_end_addr;
+ end_symtab (file_end_addr, objfile, SECT_OFF_TEXT);
+ end_stabs ();
+ start_stabs ();
+ /* Give all csects for this source file the same
+ name. */
+ start_symtab (filestring, NULL, (CORE_ADDR)0);
+ record_debugformat ("XCOFF");
+ }
+
+ /* If this is the very first csect seen,
+ basically `__start'. */
+ if (just_started)
+ {
+ first_object_file_end
+ = cs->c_value + CSECT_LEN (&main_aux);
+ just_started = 0;
+ }
+
+ file_start_addr =
+ cs->c_value + ANOFFSET (objfile->section_offsets,
+ SECT_OFF_TEXT);
+ file_end_addr = file_start_addr + CSECT_LEN (&main_aux);
+
+ if (cs->c_name && cs->c_name[0] == '.')
+ {
+ last_csect_name = cs->c_name;
+ last_csect_val = cs->c_value;
+ last_csect_sec = secnum_to_section (cs->c_secnum, objfile);
+ }
+ }
+ continue;
+
+ /* All other symbols are put into the minimal symbol
+ table only. */
+
+ case XMC_RW:
+ continue;
+
+ case XMC_TC0:
+ continue;
+
+ case XMC_TC:
+ continue;
+
+ default:
+ /* Ignore the symbol. */
+ continue;
+ }
+ }
+ break;
+
+ case XTY_LD:
+
+ switch (CSECT_SCLAS (&main_aux))
+ {
+ case XMC_PR:
+ /* a function entry point. */
+ function_entry_point:
+
+ fcn_start_addr = cs->c_value;
+
+ /* save the function header info, which will be used
+ when `.bf' is seen. */
+ fcn_cs_saved = *cs;
+ fcn_aux_saved = main_aux;
+ continue;
+
+ case XMC_GL:
+ /* shared library function trampoline code entry point. */
+ continue;
+
+ case XMC_DS:
+ /* The symbols often have the same names as debug symbols for
+ functions, and confuse lookup_symbol. */
+ continue;
+
+ default:
+ /* xlc puts each variable in a separate csect, so we get
+ an XTY_SD for each variable. But gcc puts several
+ variables in a csect, so that each variable only gets
+ an XTY_LD. This will typically be XMC_RW; I suspect
+ XMC_RO and XMC_BS might be possible too.
+ These variables are put in the minimal symbol table
+ only. */
+ continue;
+ }
+ break;
+
+ case XTY_CM:
+ /* Common symbols are put into the minimal symbol table only. */
+ continue;
+
+ default:
+ break;
+ }
+ }
+
+ switch (cs->c_sclass)
+ {
+
+ 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;
+
+ /* Complete symbol table for last object file containing
+ debugging information. */
+
+ /* Whether or not there was a csect in the previous file, we
+ have to call `end_stabs' and `start_stabs' to reset
+ type_vector, line_vector, etc. structures. */
+
+ complete_symtab (filestring, file_start_addr);
+ cur_src_end_addr = file_end_addr;
+ end_symtab (file_end_addr, objfile, SECT_OFF_TEXT);
+ end_stabs ();
+
+ /* XCOFF, according to the AIX 3.2 documentation, puts the filename
+ in cs->c_name. But xlc 1.3.0.2 has decided to do things the
+ standard COFF way and put it in the auxent. We use the auxent if
+ the symbol is ".file" and an auxent exists, otherwise use the symbol
+ itself. Simple enough. */
+ if (!strcmp (cs->c_name, ".file") && cs->c_naux > 0)
+ {
+ bfd_coff_swap_aux_in (abfd, raw_auxptr, cs->c_type, cs->c_sclass,
+ 0, cs->c_naux, &main_aux);
+ filestring = coff_getfilename (&main_aux, objfile);
+ }
+ else
+ filestring = cs->c_name;
+
+ start_stabs ();
+ start_symtab (filestring, (char *)NULL, (CORE_ADDR)0);
+ record_debugformat ("XCOFF");
+ last_csect_name = 0;
+
+ /* reset file start and end addresses. A compilation unit with no text
+ (only data) should have zero file boundaries. */
+ file_start_addr = file_end_addr = 0;
+ break;
+
+ case C_FUN:
+ fcn_stab_saved = *cs;
+ break;
+
+ case C_FCN:
+ if (STREQ (cs->c_name, ".bf"))
+ {
+ CORE_ADDR off = ANOFFSET (objfile->section_offsets,
+ SECT_OFF_TEXT);
+ bfd_coff_swap_aux_in (abfd, raw_auxptr, cs->c_type, cs->c_sclass,
+ 0, cs->c_naux, &main_aux);
+
+ within_function = 1;
+
+ new = push_context (0, fcn_start_addr + off);
+
+ new->name = define_symbol
+ (fcn_cs_saved.c_value + off,
+ fcn_stab_saved.c_name, 0, 0, objfile);
+ if (new->name != NULL)
+ SYMBOL_SECTION (new->name) = SECT_OFF_TEXT;
+ }
+ else if (STREQ (cs->c_name, ".ef"))
+ {
+
+ bfd_coff_swap_aux_in (abfd, raw_auxptr, cs->c_type, cs->c_sclass,
+ 0, cs->c_naux, &main_aux);
+
+ /* 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 '}' */
+
+ if (context_stack_depth <= 0)
+ { /* We attempted to pop an empty context stack */
+ complain (&ef_complaint, cs->c_symnum);
+ within_function = 0;
+ break;
+ }
+ 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;
+ }
+
+ finish_block (new->name, &local_symbols, new->old_blocks,
+ new->start_addr,
+ (fcn_cs_saved.c_value
+ + fcn_aux_saved.x_sym.x_misc.x_fsize
+ + ANOFFSET (objfile->section_offsets,
+ SECT_OFF_TEXT)),
+ objfile);
+ within_function = 0;
+ }
+ break;
+
+ case C_BSTAT:
+ /* Begin static block. */
+ {
+ struct internal_syment symbol;
+
+ read_symbol (&symbol, cs->c_value);
+ static_block_base = symbol.n_value;
+ static_block_section =
+ secnum_to_section (symbol.n_scnum, objfile);
+ }
+ break;
+
+ case C_ESTAT:
+ /* End of static block. */
+ static_block_base = 0;
+ static_block_section = -1;
+ break;
+
+ case C_ARG:
+ case C_REGPARM:
+ case C_REG:
+ case C_TPDEF:
+ case C_STRTAG:
+ case C_UNTAG:
+ case C_ENTAG:
+ {
+ static struct complaint msg =
+ {"Unrecognized storage class %d.", 0, 0};
+ complain (&msg, cs->c_sclass);
+ }
+ break;
+
+ case C_LABEL:
+ case C_NULL:
+ /* Ignore these. */
+ break;
+
+ case C_HIDEXT:
+ case C_STAT:
+ break;
+
+ case C_BINCL:
+ /* beginning of include file */
+ /* In xlc output, C_BINCL/C_EINCL pair doesn't show up in sorted
+ order. Thus, when wee see them, we might not know enough info
+ to process them. Thus, we'll be saving them into a table
+ (inclTable) and postpone their processing. */
+
+ record_include_begin (cs);
+ break;
+
+ case C_EINCL:
+ /* End of include file. */
+ /* See the comment after case C_BINCL. */
+ record_include_end (cs);
+ break;
+
+ case C_BLOCK:
+ if (STREQ (cs->c_name, ".bb"))
+ {
+ depth++;
+ new = push_context (depth,
+ (cs->c_value
+ + ANOFFSET (objfile->section_offsets,
+ SECT_OFF_TEXT)));
+ }
+ else if (STREQ (cs->c_name, ".eb"))
+ {
+ if (context_stack_depth <= 0)
+ { /* We attempted to pop an empty context stack */
+ complain (&eb_complaint, cs->c_symnum);
+ break;
+ }
+ new = pop_context ();
+ if (depth-- != new->depth)
+ {
+ complain (&eb_complaint, cs->c_symnum);
+ break;
+ }
+ if (local_symbols && context_stack_depth > 0)
+ {
+ /* Make a block for the local symbols within. */
+ finish_block (new->name, &local_symbols, new->old_blocks,
+ new->start_addr,
+ (cs->c_value
+ + ANOFFSET (objfile->section_offsets,
+ SECT_OFF_TEXT)),
+ objfile);
+ }
+ local_symbols = new->locals;
+ }
+ break;
+
+ default:
+ process_xcoff_symbol (cs, objfile);
+ break;
+ }
+ }
+
+ if (last_source_file)
+ {
+ struct symtab *s;
+
+ complete_symtab (filestring, file_start_addr);
+ cur_src_end_addr = file_end_addr;
+ s = end_symtab (file_end_addr, objfile, SECT_OFF_TEXT);
+ /* When reading symbols for the last C_FILE of the objfile, try
+ to make sure that we set pst->symtab to the symtab for the
+ file, not to the _globals_ symtab. I'm not sure whether this
+ actually works right or when/if it comes up. */
+ if (pst->symtab == NULL)
+ pst->symtab = s;
+ end_stabs ();
+ }
+}
+
+#define SYMBOL_DUP(SYMBOL1, SYMBOL2) \
+ (SYMBOL2) = (struct symbol *) \
+ obstack_alloc (&objfile->symbol_obstack, sizeof (struct symbol)); \
+ *(SYMBOL2) = *(SYMBOL1);
+
+
+#define SYMNAME_ALLOC(NAME, ALLOCED) \
+ (ALLOCED) ? (NAME) : obsavestring ((NAME), strlen (NAME), &objfile->symbol_obstack);
+
+
+static struct type *func_symbol_type;
+static struct type *var_symbol_type;
+
+/* process one xcoff symbol. */
+
+static struct symbol *
+process_xcoff_symbol (cs, objfile)
+ register struct coff_symbol *cs;
+ struct objfile *objfile;
+{
+ struct symbol onesymbol;
+ register struct symbol *sym = &onesymbol;
+ struct symbol *sym2 = NULL;
+ char *name, *pp;
+
+ int sec;
+ CORE_ADDR off;
+
+ if (cs->c_secnum < 0)
+ {
+ /* The value is a register number, offset within a frame, etc.,
+ and does not get relocated. */
+ off = 0;
+ sec = -1;
+ }
+ else
+ {
+ sec = secnum_to_section (cs->c_secnum, objfile);
+ off = ANOFFSET (objfile->section_offsets, sec);
+ }
+
+ name = cs->c_name;
+ if (name[0] == '.')
+ ++name;
+
+ memset (sym, '\0', sizeof (struct symbol));
+
+ /* default assumptions */
+ SYMBOL_VALUE (sym) = cs->c_value + off;
+ SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
+ SYMBOL_SECTION (sym) = secnum_to_section (cs->c_secnum, objfile);
+
+ if (ISFCN (cs->c_type))
+ {
+ /* At this point, we don't know the type of the function. This
+ will be patched with the type from its stab entry later on in
+ patch_block_stabs (), unless the file was compiled without -g. */
+
+ SYMBOL_NAME (sym) = SYMNAME_ALLOC (name, symname_alloced);
+ SYMBOL_TYPE (sym) = func_symbol_type;
+
+ SYMBOL_CLASS (sym) = LOC_BLOCK;
+ SYMBOL_DUP (sym, sym2);
+
+ if (cs->c_sclass == C_EXT)
+ add_symbol_to_list (sym2, &global_symbols);
+ else if (cs->c_sclass == C_HIDEXT || cs->c_sclass == C_STAT)
+ add_symbol_to_list (sym2, &file_symbols);
+ }
+ else
+ {
+ /* In case we can't figure out the type, provide default. */
+ SYMBOL_TYPE (sym) = var_symbol_type;
+
+ switch (cs->c_sclass)
+ {
+#if 0
+ /* The values of functions and global symbols are now resolved
+ via the global_sym_chain in stabsread.c. */
+ case C_FUN:
+ if (fcn_cs_saved.c_sclass == C_EXT)
+ add_stab_to_list (name, &global_stabs);
+ else
+ add_stab_to_list (name, &file_stabs);
+ break;
+
+ case C_GSYM:
+ add_stab_to_list (name, &global_stabs);
+ break;
+#endif
+
+ case C_BCOMM:
+ common_block_start (cs->c_name, objfile);
+ break;
+
+ case C_ECOMM:
+ common_block_end (objfile);
+ break;
+
+ default:
+ complain (&storclass_complaint, cs->c_sclass);
+ /* FALLTHROUGH */
+
+ case C_DECL:
+ case C_PSYM:
+ case C_RPSYM:
+ case C_ECOML:
+ case C_LSYM:
+ case C_RSYM:
+ case C_GSYM:
+
+ {
+ sym = define_symbol (cs->c_value + off, cs->c_name, 0, 0, objfile);
+ if (sym != NULL)
+ {
+ SYMBOL_SECTION (sym) = sec;
+ }
+ return sym;
+ }
+
+ case C_STSYM:
+
+ /* For xlc (not GCC), the 'V' symbol descriptor is used for
+ all statics and we need to distinguish file-scope versus
+ function-scope using within_function. We do this by
+ changing the string we pass to define_symbol to use 'S'
+ where we need to, which is not necessarily super-clean,
+ but seems workable enough. */
+
+ if (*name == ':' || (pp = (char *) strchr(name, ':')) == NULL)
+ return NULL;
+
+ ++pp;
+ if (*pp == 'V' && !within_function)
+ *pp = 'S';
+ sym = define_symbol ((cs->c_value
+ + ANOFFSET (objfile->section_offsets,
+ static_block_section)),
+ cs->c_name, 0, 0, objfile);
+ if (sym != NULL)
+ {
+ SYMBOL_VALUE (sym) += static_block_base;
+ SYMBOL_SECTION (sym) = static_block_section;
+ }
+ return sym;
+
+ }
+ }
+ return sym2;
+}
+
+/* Extract the file name from the aux entry of a C_FILE symbol.
+ Result is in static storage and is only good for temporary use. */
+
+static char *
+coff_getfilename (aux_entry, objfile)
+ union internal_auxent *aux_entry;
+ struct objfile *objfile;
+{
+ static char buffer[BUFSIZ];
+
+ if (aux_entry->x_file.x_n.x_zeroes == 0)
+ strcpy (buffer,
+ ((struct coff_symfile_info *)objfile->sym_private)->strtbl
+ + aux_entry->x_file.x_n.x_offset);
+ else
+ {
+ strncpy (buffer, aux_entry->x_file.x_fname, FILNMLEN);
+ buffer[FILNMLEN] = '\0';
+ }
+ return (buffer);
+}
+
+/* Set *SYMBOL to symbol number symno in symtbl. */
+static void
+read_symbol (symbol, symno)
+ struct internal_syment *symbol;
+ int symno;
+{
+ int nsyms =
+ ((struct coff_symfile_info *)this_symtab_psymtab->objfile->sym_private)
+ ->symtbl_num_syms;
+ char *stbl =
+ ((struct coff_symfile_info *)this_symtab_psymtab->objfile->sym_private)
+ ->symtbl;
+ if (symno < 0 || symno >= nsyms)
+ {
+ static struct complaint msg =
+ {"Invalid symbol offset", 0, 0};
+ complain (&msg);
+ symbol->n_value = 0;
+ symbol->n_scnum = -1;
+ return;
+ }
+ bfd_coff_swap_sym_in (this_symtab_psymtab->objfile->obfd,
+ stbl + (symno*local_symesz),
+ symbol);
+}
+
+/* Get value corresponding to symbol number symno in symtbl. */
+
+static int
+read_symbol_nvalue (symno)
+ int symno;
+{
+ struct internal_syment symbol[1];
+
+ read_symbol (symbol, symno);
+ return symbol->n_value;
+}
+
+
+/* Find the address of the function corresponding to symno, where
+ symno is the symbol pointed to by the linetable. */
+
+static int
+read_symbol_lineno (symno)
+ int symno;
+{
+ int nsyms =
+ ((struct coff_symfile_info *)this_symtab_psymtab->objfile->sym_private)
+ ->symtbl_num_syms;
+ char *stbl =
+ ((struct coff_symfile_info *)this_symtab_psymtab->objfile->sym_private)
+ ->symtbl;
+ struct internal_syment symbol[1];
+ union internal_auxent main_aux[1];
+
+ if (symno < 0)
+ {
+ complain (&bf_notfound_complaint);
+ return 0;
+ }
+
+ /* Note that just searching for a short distance (e.g. 50 symbols)
+ is not enough, at least in the following case.
+
+ .extern foo
+ [many .stabx entries]
+ [a few functions, referring to foo]
+ .globl foo
+ .bf
+
+ What happens here is that the assembler moves the .stabx entries
+ to right before the ".bf" for foo, but the symbol for "foo" is before
+ all the stabx entries. See PR gdb/2222. */
+
+ /* Maintaining a table of .bf entries might be preferable to this search.
+ If I understand things correctly it would need to be done only for
+ the duration of a single psymtab to symtab conversion. */
+ while (symno < nsyms)
+ {
+ bfd_coff_swap_sym_in (symfile_bfd,
+ stbl + (symno * local_symesz), symbol);
+ if (symbol->n_sclass == C_FCN && STREQ (symbol->n_name, ".bf"))
+ goto gotit;
+ symno += symbol->n_numaux + 1;
+ }
+
+ complain (&bf_notfound_complaint);
+ return 0;
+
+gotit:
+ /* take aux entry and return its lineno */
+ symno++;
+ bfd_coff_swap_aux_in (this_symtab_psymtab->objfile->obfd,
+ stbl + symno * local_symesz,
+ symbol->n_type, symbol->n_sclass,
+ 0, symbol->n_numaux, main_aux);
+
+ return main_aux->x_sym.x_misc.x_lnsz.x_lnno;
+}
+
+/* Support for line number handling */
+
+/* This function is called for every section; it finds the outer limits
+ * of the line table (minimum and maximum file offset) so that the
+ * mainline code can read the whole thing for efficiency.
+ */
+static void
+find_linenos (abfd, asect, vpinfo)
+ bfd *abfd;
+ sec_ptr asect;
+ PTR vpinfo;
+{
+ struct coff_symfile_info *info;
+ int size, count;
+ file_ptr offset, maxoff;
+
+ count = asect->lineno_count;
+
+ if (!STREQ (asect->name, ".text") || count == 0)
+ return;
+
+ size = count * coff_data (abfd)->local_linesz;
+ info = (struct coff_symfile_info *)vpinfo;
+ offset = asect->line_filepos;
+ maxoff = offset + size;
+
+ if (offset < info->min_lineno_offset || info->min_lineno_offset == 0)
+ info->min_lineno_offset = offset;
+
+ if (maxoff > info->max_lineno_offset)
+ info->max_lineno_offset = maxoff;
+}
+
+static void xcoff_psymtab_to_symtab_1 PARAMS ((struct partial_symtab *));
+
+static void
+xcoff_psymtab_to_symtab_1 (pst)
+ struct partial_symtab *pst;
+{
+ struct cleanup *old_chain;
+ int i;
+
+ if (!pst)
+ return;
+
+ if (pst->readin)
+ {
+ fprintf_unfiltered
+ (gdb_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 (" ", gdb_stdout);
+ wrap_here ("");
+ fputs_filtered ("and ", gdb_stdout);
+ wrap_here ("");
+ printf_filtered ("%s...", pst->dependencies[i]->filename);
+ wrap_here (""); /* Flush output */
+ gdb_flush (gdb_stdout);
+ }
+ xcoff_psymtab_to_symtab_1 (pst->dependencies[i]);
+ }
+
+ if (((struct symloc *)pst->read_symtab_private)->numsyms != 0)
+ {
+ /* Init stuff necessary for reading in symbols. */
+ stabsread_init ();
+ buildsym_init ();
+ old_chain = make_cleanup ((make_cleanup_func) really_free_pendings, 0);
+
+ read_xcoff_symtab (pst);
+ sort_symtab_syms (pst->symtab);
+
+ do_cleanups (old_chain);
+ }
+
+ pst->readin = 1;
+}
+
+static void xcoff_psymtab_to_symtab PARAMS ((struct partial_symtab *));
+
+/* Read in all of the symbols for a given psymtab for real.
+ Be verbose about it if the user wants that. */
+
+static void
+xcoff_psymtab_to_symtab (pst)
+ struct partial_symtab *pst;
+{
+ bfd *sym_bfd;
+
+ if (!pst)
+ return;
+
+ if (pst->readin)
+ {
+ fprintf_unfiltered
+ (gdb_stderr, "Psymtab for %s already read in. Shouldn't happen.\n",
+ pst->filename);
+ return;
+ }
+
+ if (((struct symloc *)pst->read_symtab_private)->numsyms != 0
+ || 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);
+ gdb_flush (gdb_stdout);
+ }
+
+ sym_bfd = pst->objfile->obfd;
+
+ next_symbol_text_func = xcoff_next_symbol_text;
+
+ xcoff_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");
+ }
+}
+
+static void
+xcoff_new_init (objfile)
+ struct objfile *objfile;
+{
+ stabsread_new_init ();
+ buildsym_new_init ();
+}
+
+/* Do initialization in preparation for reading symbols from OBJFILE.
+
+ We will only be called if this is an XCOFF or XCOFF-like file.
+ BFD handles figuring out the format of the file, and code in symfile.c
+ uses BFD's determination to vector to us. */
+
+static void
+xcoff_symfile_init (objfile)
+ struct objfile *objfile;
+{
+ /* Allocate struct to keep track of the symfile */
+ objfile -> sym_private = xmmalloc (objfile -> md,
+ sizeof (struct coff_symfile_info));
+
+ /* XCOFF objects may be reordered, so set OBJF_REORDERED. If we
+ find this causes a significant slowdown in gdb then we could
+ set it in the debug symbol readers only when necessary. */
+ objfile->flags |= OBJF_REORDERED;
+
+ init_entry_point_info (objfile);
+}
+
+/* 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
+xcoff_symfile_finish (objfile)
+ struct objfile *objfile;
+{
+ if (objfile -> sym_private != NULL)
+ {
+ mfree (objfile -> md, objfile -> sym_private);
+ }
+
+ /* Start with a fresh include table for the next objfile. */
+ if (inclTable)
+ {
+ free (inclTable);
+ inclTable = NULL;
+ }
+ inclIndx = inclLength = inclDepth = 0;
+}
+
+
+static void
+init_stringtab (abfd, offset, objfile)
+ bfd *abfd;
+ file_ptr offset;
+ struct objfile *objfile;
+{
+ long length;
+ int val;
+ unsigned char lengthbuf[4];
+ char *strtbl;
+
+ ((struct coff_symfile_info *)objfile->sym_private)->strtbl = NULL;
+
+ if (bfd_seek (abfd, offset, SEEK_SET) < 0)
+ error ("cannot seek to string table in %s: %s",
+ bfd_get_filename (abfd), bfd_errmsg (bfd_get_error ()));
+
+ val = bfd_read ((char *)lengthbuf, 1, sizeof lengthbuf, abfd);
+ length = bfd_h_get_32 (abfd, lengthbuf);
+
+ /* If no string table is needed, then the file may end immediately
+ after the symbols. Just return with `strtbl' set to NULL. */
+
+ if (val != sizeof lengthbuf || length < sizeof lengthbuf)
+ return;
+
+ /* Allocate string table from symbol_obstack. We will need this table
+ as long as we have its symbol table around. */
+
+ strtbl = (char *) obstack_alloc (&objfile->symbol_obstack, length);
+ ((struct coff_symfile_info *)objfile->sym_private)->strtbl = strtbl;
+
+ /* Copy length buffer, the first byte is usually zero and is
+ used for stabs with a name length of zero. */
+ memcpy (strtbl, lengthbuf, sizeof lengthbuf);
+ if (length == sizeof lengthbuf)
+ return;
+
+ val = bfd_read (strtbl + sizeof lengthbuf, 1, length - sizeof lengthbuf,
+ abfd);
+
+ if (val != length - sizeof lengthbuf)
+ error ("cannot read string table from %s: %s",
+ bfd_get_filename (abfd), bfd_errmsg (bfd_get_error ()));
+ if (strtbl[length - 1] != '\0')
+ error ("bad symbol file: string table does not end with null character");
+
+ return;
+}
+
+/* If we have not yet seen a function for this psymtab, this is 0. If we
+ have seen one, it is the offset in the line numbers of the line numbers
+ for the psymtab. */
+static unsigned int first_fun_line_offset;
+
+static struct partial_symtab *xcoff_start_psymtab
+ PARAMS ((struct objfile *, struct section_offsets *, char *, int,
+ struct partial_symbol **, struct partial_symbol **));
+
+/* Allocate and partially fill a partial symtab. It will be
+ completely filled at the end of the symbol list.
+
+ SYMFILE_NAME is the name of the symbol-file we are reading from, and ADDR
+ is the address relative to which its symbols are (incremental) or 0
+ (normal). */
+
+static struct partial_symtab *
+xcoff_start_psymtab (objfile, section_offsets,
+ filename, first_symnum, global_syms, static_syms)
+ struct objfile *objfile;
+ struct section_offsets *section_offsets;
+ char *filename;
+ int first_symnum;
+ struct partial_symbol **global_syms;
+ struct partial_symbol **static_syms;
+{
+ struct partial_symtab *result =
+ start_psymtab_common (objfile, section_offsets,
+ filename,
+ /* We fill in textlow later. */
+ 0,
+ global_syms, static_syms);
+
+ result->read_symtab_private = (char *)
+ obstack_alloc (&objfile -> psymbol_obstack, sizeof (struct symloc));
+ ((struct symloc *)result->read_symtab_private)->first_symnum = first_symnum;
+ result->read_symtab = xcoff_psymtab_to_symtab;
+
+ /* Deduce the source language from the filename for this psymtab. */
+ psymtab_language = deduce_language_from_filename (filename);
+
+ return result;
+}
+
+static struct partial_symtab *xcoff_end_psymtab
+ PARAMS ((struct partial_symtab *, char **, int, int,
+ struct partial_symtab **, int, int));
+
+/* Close off the current usage of PST.
+ Returns PST, or NULL if the partial symtab was empty and thrown away.
+
+ CAPPING_SYMBOL_NUMBER is the end of pst (exclusive).
+
+ INCLUDE_LIST, NUM_INCLUDES, DEPENDENCY_LIST, and NUMBER_DEPENDENCIES
+ are the information for includes and dependencies. */
+
+static struct partial_symtab *
+xcoff_end_psymtab (pst, include_list, num_includes, capping_symbol_number,
+ dependency_list, number_dependencies, textlow_not_set)
+ struct partial_symtab *pst;
+ char **include_list;
+ int num_includes;
+ int capping_symbol_number;
+ struct partial_symtab **dependency_list;
+ int number_dependencies;
+ int textlow_not_set;
+{
+ int i;
+ struct objfile *objfile = pst -> objfile;
+
+ if (capping_symbol_number != -1)
+ ((struct symloc *)pst->read_symtab_private)->numsyms =
+ capping_symbol_number
+ - ((struct symloc *)pst->read_symtab_private)->first_symnum;
+ ((struct symloc *)pst->read_symtab_private)->lineno_off =
+ first_fun_line_offset;
+ first_fun_line_offset = 0;
+ 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));
+ ((struct symloc *)subpst->read_symtab_private)->first_symnum = 0;
+ ((struct symloc *)subpst->read_symtab_private)->numsyms = 0;
+ subpst->textlow = 0;
+ 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. */
+ /* Empty psymtabs happen as a result of header files which don't have
+ any symbols in them. There can be a lot of them. */
+
+ discard_psymtab (pst);
+
+ /* Indicate that psymtab was thrown away. */
+ pst = (struct partial_symtab *)NULL;
+ }
+ return pst;
+}
+
+static void swap_sym PARAMS ((struct internal_syment *,
+ union internal_auxent *, char **, char **,
+ unsigned int *,
+ struct objfile *));
+
+/* Swap raw symbol at *RAW and put the name in *NAME, the symbol in
+ *SYMBOL, the first auxent in *AUX. Advance *RAW and *SYMNUMP over
+ the symbol and its auxents. */
+
+static void
+swap_sym (symbol, aux, name, raw, symnump, objfile)
+ struct internal_syment *symbol;
+ union internal_auxent *aux;
+ char **name;
+ char **raw;
+ unsigned int *symnump;
+ struct objfile *objfile;
+{
+ bfd_coff_swap_sym_in (objfile->obfd, *raw, symbol);
+ if (symbol->n_zeroes)
+ {
+ /* If it's exactly E_SYMNMLEN characters long it isn't
+ '\0'-terminated. */
+ if (symbol->n_name[E_SYMNMLEN - 1] != '\0')
+ {
+ /* FIXME: wastes memory for symbols which we don't end up putting
+ into the minimal symbols. */
+ char *p;
+ p = obstack_alloc (&objfile->psymbol_obstack, E_SYMNMLEN + 1);
+ strncpy (p, symbol->n_name, E_SYMNMLEN);
+ p[E_SYMNMLEN] = '\0';
+ *name = p;
+ }
+ else
+ /* Point to the unswapped name as that persists as long as the
+ objfile does. */
+ *name = ((struct external_syment *)*raw)->e.e_name;
+ }
+ else if (symbol->n_sclass & 0x80)
+ {
+ *name = ((struct coff_symfile_info *)objfile->sym_private)->debugsec
+ + symbol->n_offset;
+ }
+ else
+ {
+ *name = ((struct coff_symfile_info *)objfile->sym_private)->strtbl
+ + symbol->n_offset;
+ }
+ ++*symnump;
+ *raw += coff_data (objfile->obfd)->local_symesz;
+ if (symbol->n_numaux > 0)
+ {
+ bfd_coff_swap_aux_in (objfile->obfd, *raw, symbol->n_type,
+ symbol->n_sclass, 0, symbol->n_numaux, aux);
+
+ *symnump += symbol->n_numaux;
+ *raw += coff_data (objfile->obfd)->local_symesz * symbol->n_numaux;
+ }
+}
+
+static void
+scan_xcoff_symtab (section_offsets, objfile)
+ struct section_offsets *section_offsets;
+ struct objfile *objfile;
+{
+ CORE_ADDR toc_offset = 0; /* toc offset value in data section. */
+ char *filestring = NULL;
+
+ char *namestring;
+ int past_first_source_file = 0;
+ bfd *abfd;
+ asection *bfd_sect;
+ unsigned int nsyms;
+
+ /* 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;
+
+ char *sraw_symbol;
+ struct internal_syment symbol;
+ union internal_auxent main_aux;
+ unsigned int ssymnum;
+
+ char *last_csect_name = NULL; /* last seen csect's name and value */
+ CORE_ADDR last_csect_val = 0;
+ int last_csect_sec = 0;
+ int misc_func_recorded = 0; /* true if any misc. function */
+ int textlow_not_set = 1;
+
+ 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 *));
+
+ last_source_file = NULL;
+
+ abfd = objfile->obfd;
+
+ sraw_symbol = ((struct coff_symfile_info *)objfile->sym_private)->symtbl;
+ nsyms = ((struct coff_symfile_info *)objfile->sym_private)->symtbl_num_syms;
+ ssymnum = 0;
+ while (ssymnum < nsyms)
+ {
+ int sclass = ((struct external_syment *)sraw_symbol)->e_sclass[0] & 0xff;
+ /* This is the type we pass to partial-stab.h. A less kludgy solution
+ would be to break out partial-stab.h into its various parts--shuffle
+ off the DBXREAD_ONLY stuff to dbxread.c, and make separate
+ pstab-norm.h (for most types), pstab-sol.h (for N_SOL), etc. */
+ int stype;
+
+ QUIT;
+
+ switch (sclass)
+ {
+ case C_EXT:
+ case C_HIDEXT:
+ {
+ /* The CSECT auxent--always the last auxent. */
+ union internal_auxent csect_aux;
+ unsigned int symnum_before = ssymnum;
+
+ swap_sym (&symbol, &main_aux, &namestring, &sraw_symbol,
+ &ssymnum, objfile);
+ if (symbol.n_numaux > 1)
+ {
+ bfd_coff_swap_aux_in
+ (objfile->obfd,
+ sraw_symbol - coff_data(abfd)->local_symesz,
+ symbol.n_type,
+ symbol.n_sclass,
+ symbol.n_numaux - 1,
+ symbol.n_numaux,
+ &csect_aux);
+ }
+ else
+ csect_aux = main_aux;
+
+ /* If symbol name starts with ".$" or "$", ignore it. */
+ if (namestring[0] == '$'
+ || (namestring[0] == '.' && namestring[1] == '$'))
+ break;
+
+ switch (csect_aux.x_csect.x_smtyp & 0x7)
+ {
+ case XTY_SD:
+ switch (csect_aux.x_csect.x_smclas)
+ {
+ case XMC_PR:
+ if (last_csect_name)
+ {
+ /* If no misc. function recorded in the last
+ seen csect, enter it as a function. This
+ will take care of functions like strcmp()
+ compiled by xlc. */
+
+ if (!misc_func_recorded)
+ {
+ RECORD_MINIMAL_SYMBOL
+ (last_csect_name, last_csect_val,
+ mst_text, last_csect_sec,
+ objfile);
+ }
+
+ if (pst != NULL)
+ {
+ /* We have to allocate one psymtab for
+ each program csect, because their text
+ sections need not be adjacent. */
+ xcoff_end_psymtab
+ (pst, psymtab_include_list, includes_used,
+ symnum_before, dependency_list,
+ dependencies_used, textlow_not_set);
+ includes_used = 0;
+ dependencies_used = 0;
+ /* Give all psymtabs for this source file the same
+ name. */
+ pst = xcoff_start_psymtab
+ (objfile, section_offsets,
+ filestring,
+ symnum_before,
+ objfile->global_psymbols.next,
+ objfile->static_psymbols.next);
+ }
+ }
+ if (namestring && namestring[0] == '.')
+ {
+ last_csect_name = namestring;
+ last_csect_val = symbol.n_value;
+ last_csect_sec =
+ secnum_to_section (symbol.n_scnum, objfile);
+ }
+ if (pst != NULL)
+ {
+ CORE_ADDR highval =
+ symbol.n_value + csect_aux.x_csect.x_scnlen.l;
+ if (highval > pst->texthigh)
+ pst->texthigh = highval;
+ if (pst->textlow == 0 || symbol.n_value < pst->textlow)
+ pst->textlow = symbol.n_value;
+ }
+ misc_func_recorded = 0;
+ break;
+
+ case XMC_RW:
+ /* Data variables are recorded in the minimal symbol
+ table, except for section symbols. */
+ if (*namestring != '.')
+ prim_record_minimal_symbol_and_info
+ (namestring, symbol.n_value,
+ sclass == C_HIDEXT ? mst_file_data : mst_data,
+ NULL, secnum_to_section (symbol.n_scnum, objfile),
+ NULL, objfile);
+ break;
+
+ case XMC_TC0:
+ if (toc_offset)
+ warning ("More than one XMC_TC0 symbol found.");
+ toc_offset = symbol.n_value;
+
+ /* Make TOC offset relative to start address of section. */
+ bfd_sect = secnum_to_bfd_section (symbol.n_scnum, objfile);
+ if (bfd_sect)
+ toc_offset -= bfd_section_vma (objfile->obfd, bfd_sect);
+ break;
+
+ case XMC_TC:
+ /* These symbols tell us where the TOC entry for a
+ variable is, not the variable itself. */
+ break;
+
+ default:
+ break;
+ }
+ break;
+
+ case XTY_LD:
+ switch (csect_aux.x_csect.x_smclas)
+ {
+ case XMC_PR:
+ /* A function entry point. */
+
+ if (first_fun_line_offset == 0 && symbol.n_numaux > 1)
+ first_fun_line_offset =
+ main_aux.x_sym.x_fcnary.x_fcn.x_lnnoptr;
+ RECORD_MINIMAL_SYMBOL
+ (namestring, symbol.n_value,
+ sclass == C_HIDEXT ? mst_file_text : mst_text,
+ secnum_to_section (symbol.n_scnum, objfile),
+ objfile);
+ break;
+
+ case XMC_GL:
+ /* shared library function trampoline code entry
+ point. */
+
+ /* record trampoline code entries as
+ mst_solib_trampoline symbol. When we lookup mst
+ symbols, we will choose mst_text over
+ mst_solib_trampoline. */
+ RECORD_MINIMAL_SYMBOL
+ (namestring, symbol.n_value,
+ mst_solib_trampoline,
+ secnum_to_section (symbol.n_scnum, objfile),
+ objfile);
+ break;
+
+ case XMC_DS:
+ /* The symbols often have the same names as
+ debug symbols for functions, and confuse
+ lookup_symbol. */
+ break;
+
+ default:
+
+ /* xlc puts each variable in a separate csect,
+ so we get an XTY_SD for each variable. But
+ gcc puts several variables in a csect, so
+ that each variable only gets an XTY_LD. We
+ still need to record them. This will
+ typically be XMC_RW; I suspect XMC_RO and
+ XMC_BS might be possible too. */
+ if (*namestring != '.')
+ prim_record_minimal_symbol_and_info
+ (namestring, symbol.n_value,
+ sclass == C_HIDEXT ? mst_file_data : mst_data,
+ NULL, secnum_to_section (symbol.n_scnum, objfile),
+ NULL, objfile);
+ break;
+ }
+ break;
+
+ case XTY_CM:
+ switch (csect_aux.x_csect.x_smclas)
+ {
+ case XMC_RW:
+ case XMC_BS:
+ /* Common variables are recorded in the minimal symbol
+ table, except for section symbols. */
+ if (*namestring != '.')
+ prim_record_minimal_symbol_and_info
+ (namestring, symbol.n_value,
+ sclass == C_HIDEXT ? mst_file_bss : mst_bss,
+ NULL, secnum_to_section (symbol.n_scnum, objfile),
+ NULL, objfile);
+ break;
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+ break;
+ case C_FILE:
+ {
+ unsigned int symnum_before;
+
+ symnum_before = ssymnum;
+ swap_sym (&symbol, &main_aux, &namestring, &sraw_symbol,
+ &ssymnum, objfile);
+
+ /* See if the last csect needs to be recorded. */
+
+ if (last_csect_name && !misc_func_recorded)
+ {
+
+ /* If no misc. function recorded in the last seen csect, enter
+ it as a function. This will take care of functions like
+ strcmp() compiled by xlc. */
+
+ RECORD_MINIMAL_SYMBOL
+ (last_csect_name, last_csect_val,
+ mst_text, last_csect_sec, objfile);
+ }
+
+ if (pst)
+ {
+ xcoff_end_psymtab (pst, psymtab_include_list, includes_used,
+ symnum_before, dependency_list,
+ dependencies_used, textlow_not_set);
+ includes_used = 0;
+ dependencies_used = 0;
+ }
+ first_fun_line_offset = 0;
+
+ /* XCOFF, according to the AIX 3.2 documentation, puts the
+ filename in cs->c_name. But xlc 1.3.0.2 has decided to
+ do things the standard COFF way and put it in the auxent.
+ We use the auxent if the symbol is ".file" and an auxent
+ exists, otherwise use the symbol itself. */
+ if (!strcmp (namestring, ".file") && symbol.n_numaux > 0)
+ {
+ filestring = coff_getfilename (&main_aux, objfile);
+ }
+ else
+ filestring = namestring;
+
+ pst = xcoff_start_psymtab (objfile, section_offsets,
+ filestring,
+ symnum_before,
+ objfile->global_psymbols.next,
+ objfile->static_psymbols.next);
+ last_csect_name = NULL;
+ }
+ break;
+
+ default:
+ {
+ static struct complaint msg =
+ {"Storage class %d not recognized during scan", 0, 0};
+ complain (&msg, sclass);
+ }
+ /* FALLTHROUGH */
+
+ /* C_FCN is .bf and .ef symbols. I think it is sufficient
+ to handle only the C_FUN and C_EXT. */
+ case C_FCN:
+
+ case C_BSTAT:
+ case C_ESTAT:
+ case C_ARG:
+ case C_REGPARM:
+ case C_REG:
+ case C_TPDEF:
+ case C_STRTAG:
+ case C_UNTAG:
+ case C_ENTAG:
+ case C_LABEL:
+ case C_NULL:
+
+ /* C_EINCL means we are switching back to the main file. But there
+ is no reason to care; the only thing we want to know about
+ includes is the names of all the included (.h) files. */
+ case C_EINCL:
+
+ case C_BLOCK:
+
+ /* I don't think C_STAT is used in xcoff; C_HIDEXT appears to be
+ used instead. */
+ case C_STAT:
+
+ /* I don't think the name of the common block (as opposed to the
+ variables within it) is something which is user visible
+ currently. */
+ case C_BCOMM:
+ case C_ECOMM:
+
+ case C_PSYM:
+ case C_RPSYM:
+
+ /* I think we can ignore C_LSYM; types on xcoff seem to use C_DECL
+ so C_LSYM would appear to be only for locals. */
+ case C_LSYM:
+
+ case C_AUTO:
+ case C_RSYM:
+ {
+ /* We probably could save a few instructions by assuming that
+ C_LSYM, C_PSYM, etc., never have auxents. */
+ int naux1 =
+ ((struct external_syment *)sraw_symbol)->e_numaux[0] + 1;
+ ssymnum += naux1;
+ sraw_symbol += sizeof (struct external_syment) * naux1;
+ }
+ break;
+
+ case C_BINCL:
+ stype = N_SOL;
+ goto pstab;
+
+ case C_FUN:
+ /* The value of the C_FUN is not the address of the function (it
+ appears to be the address before linking), but as long as it
+ is smaller than the actual address, then find_pc_partial_function
+ will use the minimal symbols instead. I hope. */
+
+ case C_GSYM:
+ case C_ECOML:
+ case C_DECL:
+ case C_STSYM:
+ stype = N_LSYM;
+ pstab:;
+ swap_sym (&symbol, &main_aux, &namestring, &sraw_symbol,
+ &ssymnum, objfile);
+#define CUR_SYMBOL_TYPE stype
+#define CUR_SYMBOL_VALUE symbol.n_value
+
+/* START_PSYMTAB and END_PSYMTAB are never used, because they are only
+ called from DBXREAD_ONLY or N_SO code. Likewise for the symnum
+ variable. */
+#define START_PSYMTAB(ofile,secoff,fname,low,symoff,global_syms,static_syms) 0
+#define END_PSYMTAB(pst,ilist,ninc,c_off,c_text,dep_list,n_deps,textlow_not_set)\
+ do {} while (0)
+/* We have already set the namestring. */
+#define SET_NAMESTRING() /* */
+
+#include "partial-stab.h"
+ }
+ }
+
+ if (pst)
+ {
+ xcoff_end_psymtab (pst, psymtab_include_list, includes_used,
+ ssymnum, dependency_list,
+ dependencies_used, textlow_not_set);
+ }
+
+ /* Record the toc offset value of this symbol table into objfile structure.
+ If no XMC_TC0 is found, toc_offset should be zero. Another place to obtain
+ this information would be file auxiliary header. */
+
+ ((struct coff_symfile_info *) objfile->sym_private)->toc_offset = toc_offset;
+}
+
+/* Return the toc offset value for a given objfile. */
+
+CORE_ADDR
+get_toc_offset (objfile)
+ struct objfile *objfile;
+{
+ if (objfile)
+ return ((struct coff_symfile_info *) objfile->sym_private)->toc_offset;
+ return 0;
+}
+
+/* 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
+xcoff_initial_scan (objfile, section_offsets, mainline)
+ struct objfile *objfile;
+ struct section_offsets *section_offsets;
+ int mainline; /* FIXME comments above */
+{
+ bfd *abfd;
+ int val;
+ struct cleanup *back_to;
+ int num_symbols; /* # of symbols */
+ file_ptr symtab_offset; /* symbol table and */
+ file_ptr stringtab_offset; /* string table file offsets */
+ struct coff_symfile_info *info;
+ char *name;
+ unsigned int size;
+
+ info = (struct coff_symfile_info *) objfile -> sym_private;
+ symfile_bfd = abfd = objfile->obfd;
+ name = objfile->name;
+
+ num_symbols = bfd_get_symcount (abfd); /* # of symbols */
+ symtab_offset = obj_sym_filepos (abfd); /* symbol table file offset */
+ stringtab_offset = symtab_offset +
+ num_symbols * coff_data(abfd)->local_symesz;
+
+ info->min_lineno_offset = 0;
+ info->max_lineno_offset = 0;
+ bfd_map_over_sections (abfd, find_linenos, info);
+
+ if (num_symbols > 0)
+ {
+ /* Read the string table. */
+ init_stringtab (abfd, stringtab_offset, objfile);
+
+ /* Read the .debug section, if present. */
+ {
+ sec_ptr secp;
+ bfd_size_type length;
+ char *debugsec = NULL;
+
+ secp = bfd_get_section_by_name (abfd, ".debug");
+ if (secp)
+ {
+ length = bfd_section_size (abfd, secp);
+ if (length)
+ {
+ debugsec =
+ (char *) obstack_alloc (&objfile->symbol_obstack, length);
+
+ if (!bfd_get_section_contents (abfd, secp, debugsec,
+ (file_ptr) 0, length))
+ {
+ error ("Error reading .debug section of `%s': %s",
+ name, bfd_errmsg (bfd_get_error ()));
+ }
+ }
+ }
+ ((struct coff_symfile_info *)objfile->sym_private)->debugsec =
+ debugsec;
+ }
+ }
+
+ /* Read the symbols. We keep them in core because we will want to
+ access them randomly in read_symbol*. */
+ val = bfd_seek (abfd, symtab_offset, SEEK_SET);
+ if (val < 0)
+ error ("Error reading symbols from %s: %s",
+ name, bfd_errmsg (bfd_get_error ()));
+ size = coff_data (abfd)->local_symesz * num_symbols;
+ ((struct coff_symfile_info *)objfile->sym_private)->symtbl =
+ obstack_alloc (&objfile->symbol_obstack, size);
+ ((struct coff_symfile_info *)objfile->sym_private)->symtbl_num_syms =
+ num_symbols;
+
+ val = bfd_read (((struct coff_symfile_info *)objfile->sym_private)->symtbl,
+ size, 1, abfd);
+ if (val != size)
+ perror_with_name ("reading symbol table");
+
+ /* 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)
+ /* I'm not sure how how good num_symbols is; the rule of thumb in
+ init_psymbol_list was developed for a.out. On the one hand,
+ num_symbols includes auxents. On the other hand, it doesn't
+ include N_SLINE. */
+ init_psymbol_list (objfile, num_symbols);
+
+ free_pending_blocks ();
+ back_to = make_cleanup ((make_cleanup_func) really_free_pendings, 0);
+
+ init_minimal_symbol_collection ();
+ make_cleanup ((make_cleanup_func) discard_minimal_symbols, 0);
+
+ /* Now that the symbol table data of the executable file are all in core,
+ process them and define symbols accordingly. */
+
+ scan_xcoff_symtab (section_offsets, objfile);
+
+ /* Install any minimal symbols that have been collected as the current
+ minimal symbols for this objfile. */
+
+ install_minimal_symbols (objfile);
+
+ do_cleanups (back_to);
+}
+
+static struct section_offsets *
+xcoff_symfile_offsets (objfile, addr)
+ struct objfile *objfile;
+ CORE_ADDR addr;
+{
+ struct section_offsets *section_offsets;
+ int i;
+
+ objfile->num_sections = SECT_OFF_MAX;
+ section_offsets = (struct section_offsets *)
+ obstack_alloc
+ (&objfile -> psymbol_obstack,
+ sizeof (struct section_offsets)
+ + sizeof (section_offsets->offsets) * objfile->num_sections);
+
+ /* syms_from_objfile kindly subtracts from addr the bfd_section_vma
+ of the .text section. This strikes me as wrong--whether the
+ offset to be applied to symbol reading is relative to the start
+ address of the section depends on the symbol format. In any
+ event, this whole "addr" concept is pretty broken (it doesn't
+ handle any section but .text sensibly), so just ignore the addr
+ parameter and use 0. rs6000-nat.c will set the correct section
+ offsets via objfile_relocate. */
+ for (i = 0; i < objfile->num_sections; ++i)
+ ANOFFSET (section_offsets, i) = 0;
+
+ return section_offsets;
+}
+
+/* Register our ability to parse symbols for xcoff BFD files. */
+
+static struct sym_fns xcoff_sym_fns =
+{
+
+ /* Because the bfd uses coff_flavour, we need to specially kludge
+ the flavour. It is possible that coff and xcoff should be merged as
+ they do have fundamental similarities (for example, the extra storage
+ classes used for stabs could presumably be recognized in any COFF file).
+ However, in addition to obvious things like all the csect hair, there are
+ some subtler differences between xcoffread.c and coffread.c, notably
+ the fact that coffread.c has no need to read in all the symbols, but
+ xcoffread.c reads all the symbols and does in fact randomly access them
+ (in C_BSTAT and line number processing). */
+
+ (enum bfd_flavour)-1,
+
+ xcoff_new_init, /* sym_new_init: init anything gbl to entire symtab */
+ xcoff_symfile_init, /* sym_init: read initial info, setup for sym_read() */
+ xcoff_initial_scan, /* sym_read: read a symbol file into symtab */
+ xcoff_symfile_finish, /* sym_finish: finished with file, cleanup */
+ xcoff_symfile_offsets, /* sym_offsets: xlate offsets ext->int form */
+ NULL /* next: pointer to next struct sym_fns */
+};
+
+void
+_initialize_xcoffread ()
+{
+ add_symtab_fns(&xcoff_sym_fns);
+
+ func_symbol_type = init_type (TYPE_CODE_FUNC, 1, 0,
+ "<function, no debug info>", NULL);
+ TYPE_TARGET_TYPE (func_symbol_type) = builtin_type_int;
+ var_symbol_type =
+ init_type (TYPE_CODE_INT, TARGET_INT_BIT / HOST_CHAR_BIT, 0,
+ "<variable, no debug info>", NULL);
+}
diff --git a/gdb/xcoffsolib.c b/gdb/xcoffsolib.c
new file mode 100644
index 00000000000..13d8065ea1d
--- /dev/null
+++ b/gdb/xcoffsolib.c
@@ -0,0 +1,220 @@
+/* Shared library support for RS/6000 (xcoff) object files, for GDB.
+ Copyright 1991, 1992 Free Software Foundation.
+ Contributed by IBM Corporation.
+
+This file is part of GDB.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#if 0
+#include <sys/types.h>
+#include <sys/ldr.h>
+#endif
+
+#include "defs.h"
+#include "bfd.h"
+#include "xcoffsolib.h"
+#include "inferior.h"
+#include "command.h"
+
+/* Hook to relocate symbols at runtime. If gdb is build natively, this
+ hook is initialized in by rs6000-nat.c. If not, it is currently left
+ NULL and never called. */
+
+void (*xcoff_relocate_symtab_hook) PARAMS ((unsigned int)) = NULL;
+
+#ifdef SOLIB_SYMBOLS_MANUAL
+
+extern struct symtab *current_source_symtab;
+extern int current_source_line;
+
+/* The real work of adding a shared library file to the symtab and
+ the section list. */
+
+void
+solib_add (arg_string, from_tty, target)
+ char *arg_string;
+ int from_tty;
+ struct target_ops *target;
+{
+ char *val;
+ struct vmap *vp = vmap;
+ struct objfile *obj;
+ struct symtab *saved_symtab;
+ int saved_line;
+
+ int loaded = 0; /* true if any shared obj loaded */
+ int matched = 0; /* true if any shared obj matched */
+
+ if (arg_string == 0)
+ re_comp (".");
+ else if (val = (char *) re_comp (arg_string)) {
+ error ("Invalid regexp: %s", val);
+ }
+ if (!vp || !vp->nxt)
+ return;
+
+ /* save current symbol table and line number, in case they get changed
+ in symbol loading process. */
+
+ saved_symtab = current_source_symtab;
+ saved_line = current_source_line;
+
+ /* skip over the first vmap, it is the main program, always loaded. */
+ vp = vp->nxt;
+
+ for (; vp; vp = vp->nxt) {
+
+ if (re_exec (vp->name) || (*vp->member && re_exec (vp->member))) {
+
+ matched = 1;
+
+ /* if already loaded, continue with the next one. */
+ if (vp->loaded) {
+
+ printf_unfiltered ("%s%s%s%s: already loaded.\n",
+ *vp->member ? "(" : "",
+ vp->member,
+ *vp->member ? ") " : "",
+ vp->name);
+ continue;
+ }
+
+ printf_unfiltered ("Loading %s%s%s%s...",
+ *vp->member ? "(" : "",
+ vp->member,
+ *vp->member ? ") " : "",
+ vp->name);
+ gdb_flush (gdb_stdout);
+
+ /* This is gross and doesn't work. If this code is re-enabled,
+ just stick a objfile member into the struct vmap; that's the
+ way solib.c (for SunOS/SVR4) does it. */
+ obj = lookup_objfile_bfd (vp->bfd);
+ if (!obj) {
+ warning ("\nObj structure for the shared object not found. Loading failed.");
+ continue;
+ }
+
+ syms_from_objfile (obj, 0, 0, 0);
+ new_symfile_objfile (obj, 0, 0);
+ vmap_symtab (vp, 0, 0);
+ printf_unfiltered ("Done.\n");
+ loaded = vp->loaded = 1;
+ }
+ }
+ /* if any shared object is loaded, then misc_func_vector needs sorting. */
+ if (loaded) {
+#if 0
+ sort_misc_function_vector ();
+#endif
+ current_source_symtab = saved_symtab;
+ current_source_line = saved_line;
+
+ /* Getting new symbols might change our opinion about what is frameless.
+ Is this correct?? FIXME. */
+/* reinit_frame_cache(); */
+ }
+ else if (!matched)
+ printf_unfiltered ("No matching shared object found.\n");
+}
+#endif /* SOLIB_SYMBOLS_MANUAL */
+
+/* Return the module name of a given text address. Note that returned buffer
+ is not persistent. */
+
+char *
+pc_load_segment_name (addr)
+CORE_ADDR addr;
+{
+ static char buffer [BUFSIZ];
+ struct vmap *vp = vmap;
+
+ buffer [0] = buffer [1] = '\0';
+ for (; vp; vp = vp->nxt)
+ if (vp->tstart <= addr && addr < vp->tend) {
+ if (*vp->member) {
+ buffer [0] = '(';
+ strcat (&buffer[1], vp->member);
+ strcat (buffer, ")");
+ }
+ strcat (buffer, vp->name);
+ return buffer;
+ }
+ return "(unknown load module)";
+}
+
+static void solib_info PARAMS ((char *, int));
+
+static void
+solib_info (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ struct vmap *vp = vmap;
+
+ /* Check for new shared libraries loaded with load (). */
+ if (xcoff_relocate_symtab_hook != NULL)
+ (*xcoff_relocate_symtab_hook) (inferior_pid);
+
+ if (vp == NULL || vp->nxt == NULL)
+ {
+ printf_unfiltered ("No shared libraries loaded at this time.\n");
+ return;
+ }
+
+ /* Skip over the first vmap, it is the main program, always loaded. */
+ vp = vp->nxt;
+
+ printf_unfiltered ("\
+Text Range Data Range Syms Shared Object Library\n");
+
+ for (; vp != NULL; vp = vp->nxt)
+ {
+ printf_unfiltered ("0x%08x-0x%08x 0x%08x-0x%08x %s %s%s%s%s\n",
+ vp->tstart, vp->tend,
+ vp->dstart, vp->dend,
+ vp->loaded ? "Yes" : "No ",
+ *vp->member ? "(" : "",
+ vp->member,
+ *vp->member ? ") " : "",
+ vp->name);
+ }
+}
+
+void
+sharedlibrary_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ dont_repeat ();
+
+ /* Check for new shared libraries loaded with load (). */
+ if (xcoff_relocate_symtab_hook != NULL)
+ (*xcoff_relocate_symtab_hook) (inferior_pid);
+
+#ifdef SOLIB_SYMBOLS_MANUAL
+ solib_add (args, from_tty, (struct target_ops *)0);
+#endif /* SOLIB_SYMBOLS_MANUAL */
+}
+
+void
+_initialize_solib()
+{
+ add_com ("sharedlibrary", class_files, sharedlibrary_command,
+ "Load shared object library symbols for files matching REGEXP.");
+ add_info ("sharedlibrary", solib_info,
+ "Status of loaded shared object libraries");
+}
diff --git a/gdb/xcoffsolib.h b/gdb/xcoffsolib.h
new file mode 100644
index 00000000000..77d691bda83
--- /dev/null
+++ b/gdb/xcoffsolib.h
@@ -0,0 +1,58 @@
+/* Data structures for RS/6000 shared libraries, for GDB.
+ Copyright 1991, 1992, 1994, 1997 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* The vmap struct is used to describe the virtual address space of
+ the target we are manipulating. The first entry is always the "exec"
+ file. Subsequent entries correspond to other objects that are
+ mapped into the address space of a process created from the "exec" file.
+ These are either in response to exec()ing the file, in which case all
+ shared libraries are loaded, or a "load" system call, followed by the
+ user's issuance of a "load" command. */
+
+struct vmap {
+ struct vmap *nxt; /* ptr to next in chain */
+ bfd *bfd; /* BFD for mappable object library */
+ char *name; /* ptr to object file name */
+ char *member; /* ptr to member name */
+ CORE_ADDR tstart; /* virtual addr where member is mapped */
+ CORE_ADDR tend; /* virtual upper bound of member */
+ CORE_ADDR tvma; /* virtual addr of text section in object file */
+ CORE_ADDR toffs; /* offset of text section in object file */
+ CORE_ADDR dstart; /* virtual address of data start */
+ CORE_ADDR dend; /* virtual address of data end */
+ CORE_ADDR dvma; /* virtual addr of data section in object file */
+
+ /* This is NULL for the exec-file. */
+ struct objfile *objfile;
+
+ unsigned loaded:1; /* True if symbols are loaded */
+ unsigned padding:15;
+};
+
+
+struct vmap_and_bfd {
+ bfd *pbfd;
+ struct vmap *pvmap;
+};
+
+extern struct vmap *vmap;
+
+/* Hook for symbol table relocation at runtime. */
+
+extern void (*xcoff_relocate_symtab_hook) PARAMS ((unsigned int));
diff --git a/gdb/xmodem.c b/gdb/xmodem.c
new file mode 100644
index 00000000000..dd13b873c14
--- /dev/null
+++ b/gdb/xmodem.c
@@ -0,0 +1,284 @@
+/* XMODEM support for GDB, the GNU debugger.
+ Copyright 1995 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "serial.h"
+#include "target.h"
+#include "xmodem.h"
+
+/* These definitions are for xmodem protocol. */
+
+#define SOH 0x01
+#define STX 0x02
+#define ACK 0x06
+#define NAK 0x15
+#define EOT 0x04
+#define CANCEL 0x18
+
+static int blknum; /* XMODEM block number */
+static int crcflag; /* Sez we are using CRC's instead of cksums */
+
+static int
+readchar (desc, timeout)
+ serial_t desc;
+ int timeout;
+{
+ int c;
+
+ c = SERIAL_READCHAR (desc, timeout);
+
+ if (remote_debug > 0)
+ fputc_unfiltered (c, gdb_stderr);
+
+ if (c >= 0)
+ return c;
+
+ if (c == SERIAL_TIMEOUT)
+ error ("Timeout reading from remote system.");
+
+ perror_with_name ("xmodem.c:readchar()");
+}
+
+#define CRC16 0x1021 /* Generator polynomial (X^16 + X^12 + X^5 + 1) */
+
+static unsigned short *crctab;
+
+/* Call this to init the fast CRC-16 calculation table. */
+
+static void
+crcinit ()
+{
+ static int crctab_inited = 0;
+ int val;
+
+ if (crctab_inited == 1)
+ return;
+
+ crctab = xmalloc (256 * sizeof (short));
+
+ for (val = 0; val <= 255; val++)
+ {
+ int i;
+ unsigned int crc;
+
+ crc = val << 8;
+
+ for (i = 0; i < 8; ++i)
+ {
+ crc <<= 1;
+
+ if (crc & 0x10000)
+ crc ^= CRC16;
+ }
+
+ crctab [val] = crc;
+ }
+
+ crctab_inited = 1;
+}
+
+/* Calculate a CRC-16 for the LEN byte message pointed at by P. */
+
+static unsigned short
+docrc (p, len)
+ unsigned char *p;
+ int len;
+{
+ unsigned short crc = 0;
+
+ while (len-- > 0)
+ crc = (crc << 8) ^ crctab [(crc >> 8) ^ *p++];
+
+ return crc;
+}
+
+/* Start up the transmit process. Reset state variables. Wait for receiver to
+ send NAK or CRC request. */
+
+int
+xmodem_init_xfer (desc)
+ serial_t desc;
+{
+ int c;
+ int i;
+
+ blknum = 1;
+ crcflag = 0;
+ crcinit ();
+
+ for (i = 1; i <= 10; i++)
+ {
+ c = readchar (desc, 6);
+
+ switch (c)
+ {
+ case 'C':
+ crcflag = 1;
+ case NAK:
+ return 0;
+ default:
+ fprintf_unfiltered (gdb_stderr, "xmodem_init_xfer: Got unexpected character %c (0%o)\n", c, c);
+ continue;
+ case CANCEL: /* target aborted load */
+ fprintf_unfiltered (gdb_stderr, "Got a CANCEL from the target.\n");
+ continue;
+ }
+ }
+ error ("xmodem_init_xfer: Too many unexpected characters.");
+}
+
+/* Take 128 bytes of data and make a packet out of it.
+ *
+ * Each packet looks like this:
+ * +-----+-------+-------+------+-----+
+ * | SOH | Seq1. | Seq2. | data | SUM |
+ * +-----+-------+-------+------+-----+
+ * SOH = 0x01
+ * Seq1 = The sequence number.
+ * Seq2 = The complement of the sequence number.
+ * Data = A 128 bytes of data.
+ * SUM = Add the contents of the 128 bytes and use the low-order
+ * 8 bits of the result.
+ *
+ * send_xmodem_packet fills in the XMODEM fields of PACKET and sends it to the
+ * remote system. PACKET must be XMODEM_PACKETSIZE bytes long. The data must
+ * start 3 bytes after the beginning of the packet to leave room for the
+ * XMODEM header. LEN is the length of the data portion of the packet (and
+ * must be <= 128 bytes). If it is < 128 bytes, ^Z padding will be added.
+ */
+
+void
+xmodem_send_packet (desc, packet, len, hashmark)
+ serial_t desc;
+ unsigned char *packet;
+ int len;
+ int hashmark;
+{
+ int i;
+ int retries;
+ int pktlen;
+ int datasize;
+
+ /* build the packet header */
+
+ packet[1] = blknum;
+ packet[2] = ~blknum;
+
+ blknum++;
+
+ if (len <= XMODEM_DATASIZE)
+ {
+ packet[0] = SOH;
+ datasize = XMODEM_DATASIZE;
+ }
+ else if (len <= XMODEM_1KDATASIZE)
+ {
+ packet[0] = STX;
+ datasize = XMODEM_1KDATASIZE;
+ }
+ else
+ abort (); /* Packet way too large */
+
+ /* Add ^Z padding if packet < 128 (or 1024) bytes */
+
+ memset (packet + 3 + len, '\026', datasize - len);
+
+ if (crcflag)
+ {
+ int crc;
+
+ crc = docrc (packet + 3, datasize);
+
+ packet[3 + datasize] = crc >> 8;
+ packet[3 + datasize + 1] = crc;
+ pktlen = datasize + 5;
+ }
+ else
+ {
+ int sum;
+
+ sum = 0;
+ for (i = 3; i < datasize + 3; i++)
+ sum += packet[i];
+
+ packet[3 + datasize] = sum; /* add the checksum */
+ pktlen = datasize + 4;
+ }
+
+ for (retries = 3; retries >= 0; retries--)
+ {
+ int c;
+
+ SERIAL_WRITE (desc, packet, pktlen);
+
+ c = readchar (desc, 3);
+ switch (c)
+ {
+ case ACK:
+ return;
+ case NAK:
+ if (!hashmark)
+ continue;
+ putchar_unfiltered ('-');
+ gdb_flush (gdb_stdout);
+ continue;
+ case CANCEL:
+ error ("xmodem_send_packet: Transfer aborted by receiver.");
+ default:
+ fprintf_unfiltered (gdb_stderr, "xmodem_send_packet: Got unexpected character %c (0%o)\n", c, c);
+ continue;
+ }
+ }
+
+ SERIAL_WRITE (desc, "\004", 1); /* Send an EOT */
+
+ error ("xmodem_send_packet: Excessive retries.");
+}
+
+/* Finish off the transfer. Send out the EOT, and wait for an ACK. */
+
+void
+xmodem_finish_xfer (desc)
+ serial_t desc;
+{
+ int retries;
+
+ for (retries = 10; retries >= 0; retries--)
+ {
+ int c;
+
+ SERIAL_WRITE (desc, "\004", 1); /* Send an EOT */
+
+ c = readchar (desc, 3);
+ switch (c)
+ {
+ case ACK:
+ return;
+ case NAK:
+ continue;
+ case CANCEL:
+ error ("xmodem_finish_xfer: Transfer aborted by receiver.");
+ default:
+ fprintf_unfiltered (gdb_stderr, "xmodem_send_packet: Got unexpected character %c (0%o)\n", c, c);
+ continue;
+ }
+ }
+
+ error ("xmodem_finish_xfer: Excessive retries.");
+}
diff --git a/gdb/xmodem.h b/gdb/xmodem.h
new file mode 100644
index 00000000000..03036120fc6
--- /dev/null
+++ b/gdb/xmodem.h
@@ -0,0 +1,29 @@
+/* XMODEM support for GDB, the GNU debugger.
+ Copyright 1995 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+int xmodem_init_xfer PARAMS ((serial_t desc));
+void send_xmodem_packet PARAMS ((serial_t desc, unsigned char *packet, int len,
+ int hashmark));
+void xmodem_finish_xfer PARAMS ((serial_t desc));
+
+#define XMODEM_DATASIZE 128 /* The data size is ALWAYS 128 */
+#define XMODEM_1KDATASIZE 1024 /* Unless it's 1024!!! */
+#define XMODEM_PACKETSIZE 133 /* data + packet headers and crc */
+#define XMODEM_1KPACKETSIZE 1024 + 5 /* data + packet headers and crc */
+#define XMODEM_DATAOFFSET 3 /* Offset to start of actual data */
diff --git a/gdb/z8k-tdep.c b/gdb/z8k-tdep.c
new file mode 100644
index 00000000000..0b5c1c29aff
--- /dev/null
+++ b/gdb/z8k-tdep.c
@@ -0,0 +1,453 @@
+/* Target-machine dependent code for Zilog Z8000, for GDB.
+ Copyright (C) 1992, 1993, 1994 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/*
+ Contributed by Steve Chamberlain
+ sac@cygnus.com
+ */
+
+#include "defs.h"
+#include "frame.h"
+#include "obstack.h"
+#include "symtab.h"
+#include "gdbcmd.h"
+#include "gdbtypes.h"
+#include "dis-asm.h"
+#include "gdbcore.h"
+
+
+/* Return the saved PC from this frame.
+
+ If the frame has a memory copy of SRP_REGNUM, use that. If not,
+ just use the register SRP_REGNUM itself. */
+
+CORE_ADDR
+frame_saved_pc (frame)
+ struct frame_info *frame;
+{
+ return read_memory_pointer (frame->frame + (BIG ? 4 : 2));
+}
+
+#define IS_PUSHL(x) (BIG ? ((x & 0xfff0) == 0x91e0):((x & 0xfff0) == 0x91F0))
+#define IS_PUSHW(x) (BIG ? ((x & 0xfff0) == 0x93e0):((x & 0xfff0)==0x93f0))
+#define IS_MOVE_FP(x) (BIG ? x == 0xa1ea : x == 0xa1fa)
+#define IS_MOV_SP_FP(x) (BIG ? x == 0x94ea : x == 0x0d76)
+#define IS_SUB2_SP(x) (x==0x1b87)
+#define IS_MOVK_R5(x) (x==0x7905)
+#define IS_SUB_SP(x) ((x & 0xffff) == 0x020f)
+#define IS_PUSH_FP(x) (BIG ? (x == 0x93ea) : (x == 0x93fa))
+
+/* work out how much local space is on the stack and
+ return the pc pointing to the first push */
+
+static CORE_ADDR
+skip_adjust (pc, size)
+ CORE_ADDR pc;
+ int *size;
+{
+ *size = 0;
+
+ if (IS_PUSH_FP (read_memory_short (pc))
+ && IS_MOV_SP_FP (read_memory_short (pc + 2)))
+ {
+ /* This is a function with an explict frame pointer */
+ pc += 4;
+ *size += 2; /* remember the frame pointer */
+ }
+
+ /* remember any stack adjustment */
+ if (IS_SUB_SP (read_memory_short (pc)))
+ {
+ *size += read_memory_short (pc + 2);
+ pc += 4;
+ }
+ return pc;
+}
+
+static CORE_ADDR examine_frame PARAMS ((CORE_ADDR, CORE_ADDR *regs, CORE_ADDR));
+static CORE_ADDR
+examine_frame (pc, regs, sp)
+ CORE_ADDR pc;
+ CORE_ADDR *regs;
+ CORE_ADDR sp;
+{
+ int w = read_memory_short (pc);
+ int offset = 0;
+ int regno;
+
+ for (regno = 0; regno < NUM_REGS; regno++)
+ regs[regno] = 0;
+
+ while (IS_PUSHW (w) || IS_PUSHL (w))
+ {
+ /* work out which register is being pushed to where */
+ if (IS_PUSHL (w))
+ {
+ regs[w & 0xf] = offset;
+ regs[(w & 0xf) + 1] = offset + 2;
+ offset += 4;
+ }
+ else
+ {
+ regs[w & 0xf] = offset;
+ offset += 2;
+ }
+ pc += 2;
+ w = read_memory_short (pc);
+ }
+
+ if (IS_MOVE_FP (w))
+ {
+ /* We know the fp */
+
+ }
+ else if (IS_SUB_SP (w))
+ {
+ /* Subtracting a value from the sp, so were in a function
+ which needs stack space for locals, but has no fp. We fake up
+ the values as if we had an fp */
+ regs[FP_REGNUM] = sp;
+ }
+ else
+ {
+ /* This one didn't have an fp, we'll fake it up */
+ regs[SP_REGNUM] = sp;
+ }
+ /* stack pointer contains address of next frame */
+ /* regs[fp_regnum()] = fp;*/
+ regs[SP_REGNUM] = sp;
+ return pc;
+}
+
+CORE_ADDR
+z8k_skip_prologue (start_pc)
+ CORE_ADDR start_pc;
+{
+ CORE_ADDR dummy[NUM_REGS];
+
+ return examine_frame (start_pc, dummy, 0);
+}
+
+CORE_ADDR
+z8k_addr_bits_remove (addr)
+ CORE_ADDR addr;
+{
+ return (addr & PTR_MASK);
+}
+
+int
+read_memory_pointer (x)
+ CORE_ADDR x;
+{
+ return read_memory_integer (ADDR_BITS_REMOVE (x), BIG ? 4 : 2);
+}
+
+CORE_ADDR
+frame_chain (thisframe)
+ struct frame_info *thisframe;
+{
+ if (thisframe->prev == 0)
+ {
+ /* This is the top of the stack, let's get the sp for real */
+ }
+ if (!inside_entry_file (thisframe->pc))
+ {
+ return read_memory_pointer (thisframe->frame);
+ }
+ return 0;
+}
+
+void
+init_frame_pc ()
+{
+ abort ();
+}
+
+/* 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. */
+
+void
+z8k_frame_init_saved_regs (frame_info)
+ struct frame_info *frame_info;
+{
+ CORE_ADDR pc;
+ int w;
+
+ frame_saved_regs_zalloc (frame_info);
+ pc = get_pc_function_start (frame_info->pc);
+
+ /* wander down the instruction stream */
+ examine_frame (pc, frame_info->saved_regs, frame_info->frame);
+
+}
+
+void
+z8k_push_dummy_frame ()
+{
+ abort ();
+}
+
+int
+gdb_print_insn_z8k (memaddr, info)
+ bfd_vma memaddr;
+ disassemble_info *info;
+{
+ if (BIG)
+ return print_insn_z8001 (memaddr, info);
+ else
+ return print_insn_z8002 (memaddr, info);
+}
+
+/* Fetch the instruction at ADDR, returning 0 if ADDR is beyond LIM or
+ is not the address of a valid instruction, the address of the next
+ instruction beyond ADDR otherwise. *PWORD1 receives the first word
+ of the instruction.*/
+
+CORE_ADDR
+NEXT_PROLOGUE_INSN (addr, lim, pword1)
+ CORE_ADDR addr;
+ CORE_ADDR lim;
+ short *pword1;
+{
+ char buf[2];
+ if (addr < lim + 8)
+ {
+ read_memory (addr, buf, 2);
+ *pword1 = extract_signed_integer (buf, 2);
+
+ return addr + 2;
+ }
+ return 0;
+}
+
+#if 0
+/* Put here the code to store, into a struct frame_saved_regs,
+ the addresses of the saved registers of frame described by FRAME_INFO.
+ This includes special registers such as pc and fp saved in special
+ ways in the stack frame. sp is even more special:
+ the address we return for it IS the sp for the next frame.
+
+ We cache the result of doing this in the frame_cache_obstack, since
+ it is fairly expensive. */
+
+void
+frame_find_saved_regs (fip, fsrp)
+ struct frame_info *fip;
+ struct frame_saved_regs *fsrp;
+{
+ int locals;
+ CORE_ADDR pc;
+ CORE_ADDR adr;
+ int i;
+
+ memset (fsrp, 0, sizeof *fsrp);
+
+ pc = skip_adjust (get_pc_function_start (fip->pc), &locals);
+
+ {
+ adr = FRAME_FP (fip) - locals;
+ for (i = 0; i < 8; i++)
+ {
+ int word = read_memory_short (pc);
+
+ pc += 2;
+ if (IS_PUSHL (word))
+ {
+ fsrp->regs[word & 0xf] = adr;
+ fsrp->regs[(word & 0xf) + 1] = adr - 2;
+ adr -= 4;
+ }
+ else if (IS_PUSHW (word))
+ {
+ fsrp->regs[word & 0xf] = adr;
+ adr -= 2;
+ }
+ else
+ break;
+ }
+
+ }
+
+ fsrp->regs[PC_REGNUM] = fip->frame + 4;
+ fsrp->regs[FP_REGNUM] = fip->frame;
+
+}
+#endif
+
+int
+saved_pc_after_call ()
+{
+ return ADDR_BITS_REMOVE
+ (read_memory_integer (read_register (SP_REGNUM), PTR_SIZE));
+}
+
+
+void
+extract_return_value (type, regbuf, valbuf)
+ struct type *type;
+ char *regbuf;
+ char *valbuf;
+{
+ int b;
+ int len = TYPE_LENGTH (type);
+
+ for (b = 0; b < len; b += 2)
+ {
+ int todo = len - b;
+
+ if (todo > 2)
+ todo = 2;
+ memcpy (valbuf + b, regbuf + b, todo);
+ }
+}
+
+void
+write_return_value (type, valbuf)
+ struct type *type;
+ char *valbuf;
+{
+ int reg;
+ int len;
+
+ for (len = 0; len < TYPE_LENGTH (type); len += 2)
+ write_register_bytes (REGISTER_BYTE (len / 2 + 2), valbuf + len, 2);
+}
+
+void
+store_struct_return (addr, sp)
+ CORE_ADDR addr;
+ CORE_ADDR sp;
+{
+ write_register (2, addr);
+}
+
+
+void
+print_register_hook (regno)
+ int regno;
+{
+ if ((regno & 1) == 0 && regno < 16)
+ {
+ unsigned short l[2];
+
+ read_relative_register_raw_bytes (regno, (char *) (l + 0));
+ read_relative_register_raw_bytes (regno + 1, (char *) (l + 1));
+ printf_unfiltered ("\t");
+ printf_unfiltered ("%04x%04x", l[0], l[1]);
+ }
+
+ if ((regno & 3) == 0 && regno < 16)
+ {
+ unsigned short l[4];
+
+ read_relative_register_raw_bytes (regno, (char *) (l + 0));
+ read_relative_register_raw_bytes (regno + 1, (char *) (l + 1));
+ read_relative_register_raw_bytes (regno + 2, (char *) (l + 2));
+ read_relative_register_raw_bytes (regno + 3, (char *) (l + 3));
+
+ printf_unfiltered ("\t");
+ printf_unfiltered ("%04x%04x%04x%04x", l[0], l[1], l[2], l[3]);
+ }
+ if (regno == 15)
+ {
+ unsigned short rval;
+ int i;
+
+ read_relative_register_raw_bytes (regno, (char *) (&rval));
+
+ printf_unfiltered ("\n");
+ for (i = 0; i < 10; i += 2)
+ {
+ printf_unfiltered ("(sp+%d=%04x)", i, read_memory_short (rval + i));
+ }
+ }
+
+}
+
+void
+z8k_pop_frame ()
+{
+}
+
+struct cmd_list_element *setmemorylist;
+
+void
+z8k_set_pointer_size (newsize)
+ int newsize;
+{
+ static int oldsize = 0;
+
+ if (oldsize != newsize)
+ {
+ printf_unfiltered ("pointer size set to %d bits\n", newsize);
+ oldsize = newsize;
+ if (newsize == 32)
+ {
+ BIG = 1;
+ }
+ else
+ {
+ BIG = 0;
+ }
+ _initialize_gdbtypes ();
+ }
+}
+
+static void
+segmented_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ z8k_set_pointer_size (32);
+}
+
+static void
+unsegmented_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ z8k_set_pointer_size (16);
+}
+
+static void
+set_memory (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ printf_unfiltered ("\"set memory\" must be followed by the name of a memory subcommand.\n");
+ help_list (setmemorylist, "set memory ", -1, gdb_stdout);
+}
+
+void
+_initialize_z8ktdep ()
+{
+ tm_print_insn = gdb_print_insn_z8k;
+
+ add_prefix_cmd ("memory", no_class, set_memory,
+ "set the memory model", &setmemorylist, "set memory ", 0,
+ &setlist);
+ add_cmd ("segmented", class_support, segmented_command,
+ "Set segmented memory model.", &setmemorylist);
+ add_cmd ("unsegmented", class_support, unsegmented_command,
+ "Set unsegmented memory model.", &setmemorylist);
+
+}